diff --git a/.gitignore b/.gitignore new file mode 100755 index 0000000..c1061dd --- /dev/null +++ b/.gitignore @@ -0,0 +1,16 @@ +*.o +*.d +*.map +*.nmap +beken_os/Debug +beken_os/.ver +beken_os/.config +beken_os/tools/generate/config.json +beken_os/tools/generate/*.cpr +beken_os/tools/generate/*.out +beken_os/tools/generate/*.bin +!beken_os/tools/generate/t2_bootloader.bin +!beken_os/tools/generate/t2_bootloader_enc.bin +!beken_os/tools/generate/package.bin +qt_proj/ +toolchain/gcc-arm-none-eabi-4_9-2015q1 diff --git a/Kconfig b/Kconfig new file mode 100755 index 0000000..2895e88 --- /dev/null +++ b/Kconfig @@ -0,0 +1,29 @@ +menu "configure bk7231n" + config OPERATING_SYSTEM + int "OPERATING_SYSTEM --- mandatory for board" + default 98 + ---help--- + 100 /* LINUX */ + 98 /* RTOS */ + 3 /* Non-OS */ + + config ENABLE_WIFI + bool "ENABLE_WIFI --- use wifi to connect" + default y + + config ENABLE_WATCHDOG + bool "ENABLE_WATCHDOG --- use watchdog" + default y + + config ENABLE_BLUETOOTH + bool "ENABLE_BLUETOOTH --- use bluetooth to connect" + default y + + config LITTLE_END + int "LITTLE_END --- mandatory for board" + default 1 + ---help--- + 0 /* big endian */ + 1 /* little endian */ + + endmenu diff --git a/README.md b/README.md new file mode 100755 index 0000000..106c2d6 --- /dev/null +++ b/README.md @@ -0,0 +1,41 @@ +# T2 +English | [中文](README_zh.md) + +**T2-U development board** is designed for prototyping smart devices easily and quickly. You can use it with other purpose-built modules or development boards to evaluate your project. + +image.png + +## T2-U module Overview +T2-U development board consists of Tuya’s highly-integrated Wi-Fi and Bluetooth module [T2-U](https://developer.tuya.com/en/docs/iot/T2-U-module-datasheet?id=Kce1tncb80ldq) and peripherals including buttons, LED indicator, GPIOs, power, and USB-to-serial chip. + +T2-U is built-in with a 32-bit MCU with a running speed of up to 120 MHz, 2 Mbyte flash, and 256-KB RAM。 + +### Features + +- Embedded low-power 32-bit CPU, which can also function as an application processor +- The clock rate: 120 MHz +- Operating voltage: 3.0V to 3.6V +- Peripherals: + - 6×PWM + - 4xTimer + - 2×UART + - 1×SPI + - 2xI2C + - 1xADC + - 19xGPIO +- Wi-Fi connectivity + - 802.11 b/g/n + - Channels 1 to 14@2.4 GHz + - Support WEP, WPA/WPA2, WPA/WPA2 PSK (AES), WPA3 security modes + - Up to +16 dBm output power in 802.11b mode + - Support STA/AP/STA+AP working mode + - Support SmartConfig and AP pairing manners for Android and iOS devices + - Onboard PCB antenna with a gain of 2.2 dBi + - Operating temperature: -40°C to 105°C +- Bluetooth LE connectivity + - Support the Bluetooth LE V5.2 + - 6 dBm transmit power in Bluetooth mode + - Complete Bluetooth coexistence interface + - Onboard PCB antenna with a gain of 2.2 dBi + +[ More T2-U module information](https://developer.tuya.com/en/docs/iot/T2-U-module-datasheet?id=Kce1tncb80ldq) \ No newline at end of file diff --git a/README_zh.md b/README_zh.md new file mode 100755 index 0000000..5d29aa4 --- /dev/null +++ b/README_zh.md @@ -0,0 +1,42 @@ +# T2 + +[English](https://github.com/tuya/T2/blob/main/README.md) | 中文 + +**涂鸦 T2-U 开发板** 是一款专为开发者打造的智能硬件产品原型开发板。它可与其他功能电路模组或电路板配合使用,实现各种智能硬件产品的开发。涂鸦 T2-U 开发板非常易于使用,您可以利用此开发板快速实现各种智能硬件 Demo。 + +image.png + +## T2-U模组概述 +涂鸦 T2-U 开发板主控采用涂鸦智能开发的一款嵌入式 Wi-Fi+蓝牙模组 [T2-U](https://developer.tuya.com/en/docs/iot/T2-U-module-datasheet?id=Kce1tncb80ldq)。它由一个高集成度的无线射频模组 T2-U 和外围的按键、LED 指示灯、I/O 接口、电源和 USB 转串口芯片构成。 + +T2-U模组 内置运行速度最高可到 120 MHz 的 32-bit MCU,内置 2Mbyte 闪存和 256 KB RAM。 + +### 特性 + +- 内置低功耗 32 位 CPU,可以兼作应用处理器 +- 主频支持 120MHz +- 工作电压:3.0V-3.6V +- 外设: + - 6×PWM + - 4xTimer + - 2×UART + - 1×SPI + - 2xI2C + - 1xADC + - 19xGPIO +- Wi-Fi 连通性 + - 802.11 b/g/n + - 通道1-14@2.4GHz + - 支持 WEP、WPA/WPA2、WPA/WPA2 PSK (AES) 和 WPA3 安全模式 + - 802.11b 模式下最大 +16dBm 的输出功率 + - 支持 STA/AP/STA+AP 工作模式 + - 支持 SmartConfig 和 AP 两种配网方式(包括 Android 和 iOS 设备) + - 板载 PCB 天线,天线峰值增益 2.2dBi + - 工作温度:-40℃ 到 105℃ +- 蓝牙连通性 + - 低功耗蓝牙 V5.2 完整标准 + - 蓝牙模式支持 6 dBm 发射功率 + - 完整的蓝牙共存接口 + - 板载 PCB 天线,天线峰值增益 2.2dBi + +[更多T2-U模组资料](https://developer.tuya.com/cn/docs/iot/T2-U-module-datasheet?id=Kce1tncb80ldq) \ No newline at end of file diff --git a/beken_os/Makefile b/beken_os/Makefile new file mode 100755 index 0000000..25b943a --- /dev/null +++ b/beken_os/Makefile @@ -0,0 +1,52 @@ +OS := $(shell uname) + +GREEN := \033[0;32m +RED := \033[0;31m +NC := \033[0m # No Color +ifeq ($(findstring bash, $(shell readlink $(SHELL))), bash) +ECHO = echo -e +else +ECHO = echo +endif + +GIT_VERSION := $(shell git describe --tags --dirty=-Dev) +ARM_GCC_TOOLCHAIN = ../toolchain/gcc-arm-none-eabi-4_9-2015q1/bin + +CROSS_COMPILE = $(ARM_GCC_TOOLCHAIN)/arm-none-eabi- +.config: beken378/app/config/sys_config.h + @echo 'GEN .config' + @-rm -f $@ + @echo '#include "beken378/app/config/sys_config.h"' > config.c + @sed -n '/^#define/p' beken378/app/config/sys_config.h | awk '{print $$2}' | sort -d | uniq | awk '{print "valueOf_"$$1"="$$1}' >> config.c + @echo "# Autogenerated by Makefile, DON'T EDIT" > .config + @$(ARM_GCC_TOOLCHAIN)/arm-none-eabi-gcc -E -I ../../../sdk/include/ config.c | grep '^valueOf_' | sed 's/valueOf_//' >> .config + @sed -i '/_SYS_CONFIG_H_/d' .config + @-rm -f config.c + +.PHONY: mp +mp: .config + @$(MAKE) -f application.mk CFG_GIT_VERSION=\"$(GIT_VERSION)\" + +all: .config + @$(MAKE) -f application.mk CFG_GIT_VERSION=\"$(GIT_VERSION)\" + +.PHONY: beken +beken: .config + @$(MAKE) -f application.mk application + +.PHONY: clean +clean: + @$(MAKE) -f application.mk clean + +.PHONY: flash debug ramdebug setup +setup: + @$(MAKE) -f application.mk $(MAKECMDGOALS) + +flash: toolchain + @$(MAKE) -f application.mk flashburn + +debug: toolchain + @$(MAKE) -f application.mk debug + +ramdebug: toolchain + @$(MAKE) -f application.mk ramdebug diff --git a/beken_os/application.mk b/beken_os/application.mk new file mode 100755 index 0000000..2d7b717 --- /dev/null +++ b/beken_os/application.mk @@ -0,0 +1,936 @@ +TOP_DIR = ../../.. +TOP_INCLUDE_DIR = $(TOP_DIR)/include + +# Initialize tool chain /usr/bin/gcc-arm-none-eabi-4_9-2015q1/bin +# ------------------------------------------------------------------- + +CROSS_COMPILE = $(ARM_GCC_TOOLCHAIN)/arm-none-eabi- + +CFG_BLE_5X_VERSION ?= 1 +CFG_BLE_5X_RW ?= 1 +CFG_BLE_5X_USE_RWIP_LIB ?= 1 +CFG_GIT_VERSION ?= "" +CFG_WRAP_LIBC ?= 1 + +ota_idx = 1 + +# Compilation tools +AR = $(CROSS_COMPILE)ar +CC = $(CROSS_COMPILE)gcc +AS = $(CROSS_COMPILE)as +NM = $(CROSS_COMPILE)nm +LD = $(CROSS_COMPILE)gcc +GDB = $(CROSS_COMPILE)gdb +OBJCOPY = $(CROSS_COMPILE)objcopy +OBJDUMP = $(CROSS_COMPILE)objdump + +Q := @ +ifeq ($(V),1) +Q := +endif +OS := $(shell uname) + +ifeq ($(findstring CYGWIN, $(OS)), CYGWIN) +PICK = $(AMEBA_TOOLDIR)pick.exe +PAD = $(AMEBA_TOOLDIR)padding.exe +CHKSUM = $(AMEBA_TOOLDIR)checksum.exe +OTA = $(AMEBA_TOOLDIR)ota.exe +else +PICK = $(AMEBA_TOOLDIR)pick +PAD = $(AMEBA_TOOLDIR)padding +CHKSUM = $(AMEBA_TOOLDIR)checksum +OTA = $(AMEBA_TOOLDIR)ota +endif + +ifeq ($(ECHO),) +ECHO=echo +endif + +-include .config + +# ------------------------------------------------------------------- +# Initialize target name and target object files +# ------------------------------------------------------------------- + +WPA_VERSION := hostapd-2.5 +ifeq ($(CFG_USE_WPA_29),1) +WPA_VERSION := wpa_supplicant-2.9 +endif + +all: application + +TARGET=Debug + +OBJ_DIR=$(TARGET) +BIN_DIR=$(TARGET) + + + +# ------------------------------------------------------------------- +# Include folder list +# ------------------------------------------------------------------- +INCLUDES = + +INCLUDES += -I./beken378/common +INCLUDES += -I./beken378/demo +INCLUDES += -I./beken378/app +INCLUDES += -I./beken378/app/config +INCLUDES += -I./beken378/app/standalone-station +INCLUDES += -I./beken378/app/standalone-ap +INCLUDES += -I./beken378/ip/common +INCLUDES += -I./beken378/ip/ke/ +INCLUDES += -I./beken378/ip/mac/ +INCLUDES += -I./beken378/ip/lmac/src/hal +INCLUDES += -I./beken378/ip/lmac/src/mm +INCLUDES += -I./beken378/ip/lmac/src/ps +INCLUDES += -I./beken378/ip/lmac/src/rd +INCLUDES += -I./beken378/ip/lmac/src/rwnx +INCLUDES += -I./beken378/ip/lmac/src/rx +INCLUDES += -I./beken378/ip/lmac/src/scan +INCLUDES += -I./beken378/ip/lmac/src/sta +INCLUDES += -I./beken378/ip/lmac/src/tx +INCLUDES += -I./beken378/ip/lmac/src/vif +INCLUDES += -I./beken378/ip/lmac/src/rx/rxl +INCLUDES += -I./beken378/ip/lmac/src/tx/txl +INCLUDES += -I./beken378/ip/lmac/src/p2p +INCLUDES += -I./beken378/ip/lmac/src/chan +INCLUDES += -I./beken378/ip/lmac/src/td +INCLUDES += -I./beken378/ip/lmac/src/tpc +INCLUDES += -I./beken378/ip/lmac/src/tdls +INCLUDES += -I./beken378/ip/umac/src/mesh +INCLUDES += -I./beken378/ip/umac/src/mfp +INCLUDES += -I./beken378/ip/umac/src/rc +INCLUDES += -I./beken378/ip/umac/src/apm +INCLUDES += -I./beken378/ip/umac/src/bam +INCLUDES += -I./beken378/ip/umac/src/llc +INCLUDES += -I./beken378/ip/umac/src/me +INCLUDES += -I./beken378/ip/umac/src/rxu +INCLUDES += -I./beken378/ip/umac/src/scanu +INCLUDES += -I./beken378/ip/umac/src/sm +INCLUDES += -I./beken378/ip/umac/src/txu +INCLUDES += -I./beken378/driver/include +INCLUDES += -I./beken378/driver/common/reg +INCLUDES += -I./beken378/driver/entry +INCLUDES += -I./beken378/driver/dma +INCLUDES += -I./beken378/driver/intc +INCLUDES += -I./beken378/driver/phy +INCLUDES += -I./beken378/driver/pwm +INCLUDES += -I./beken378/driver/rc_beken +INCLUDES += -I./beken378/driver/flash +INCLUDES += -I./beken378/driver/rw_pub +INCLUDES += -I./beken378/driver/common/reg +INCLUDES += -I./beken378/driver/common +INCLUDES += -I./beken378/driver/uart +INCLUDES += -I./beken378/driver/sys_ctrl +INCLUDES += -I./beken378/driver/gpio +INCLUDES += -I./beken378/driver/general_dma +INCLUDES += -I./beken378/driver/spidma +INCLUDES += -I./beken378/driver/icu +INCLUDES += -I./beken378/driver/spi +INCLUDES += -I./beken378/func/include +INCLUDES += -I./beken378/func/misc +INCLUDES += -I./beken378/func/rf_test +INCLUDES += -I./beken378/func/bk7011_cal +INCLUDES += -I./beken378/func/user_driver +INCLUDES += -I./beken378/func/power_save +INCLUDES += -I./beken378/func/uart_debug +INCLUDES += -I./beken378/func/ethernet_intf +INCLUDES += -I./beken378/func/$(WPA_VERSION)/hostapd +INCLUDES += -I./beken378/func/$(WPA_VERSION)/bk_patch +INCLUDES += -I./beken378/func/$(WPA_VERSION)/src/utils +INCLUDES += -I./beken378/func/$(WPA_VERSION)/src/ap +INCLUDES += -I./beken378/func/$(WPA_VERSION)/src/common +INCLUDES += -I./beken378/func/$(WPA_VERSION)/src/drivers +INCLUDES += -I./beken378/func/$(WPA_VERSION)/src +INCLUDES += -I./beken378/func/$(WPA_VERSION)/wpa_supplicant +INCLUDES += -I./beken378/func/$(WPA_VERSION)/bk_patch +#INCLUDES += -I./beken378/func/lwip_intf/lwip-2.0.2 +#INCLUDES += -I./beken378/func/lwip_intf/lwip-2.0.2/src +#INCLUDES += -I./beken378/func/lwip_intf/lwip-2.0.2/port +#INCLUDES += -I./beken378/func/lwip_intf/lwip-2.0.2/src/include +#INCLUDES += -I./beken378/func/lwip_intf/lwip-2.0.2/src/include/netif +#INCLUDES += -I./beken378/func/lwip_intf/lwip-2.0.2/src/include/lwip +INCLUDES += -I../tuyaos/tuyaos_adapter/include +INCLUDES += -I../tuyaos/tuyaos_adapter/include/lwip +INCLUDES += -I./beken378/func/temp_detect +INCLUDES += -I./beken378/func/spidma_intf +INCLUDES += -I./beken378/func/rwnx_intf +INCLUDES += -I./beken378/func/joint_up +#INCLUDES += -I./beken378/func/bk_tuya_pwm +INCLUDES += -I./beken378/os/include +INCLUDES += -I./beken378/os/FreeRTOSv9.0.0/FreeRTOS/Source/portable/Keil/ARM968es +INCLUDES += -I./beken378/os/FreeRTOSv9.0.0/FreeRTOS/Source/include +INCLUDES += -I./beken378/os/FreeRTOSv9.0.0 + +ifeq ($(CFG_WRAP_LIBC),1) +INCLUDES += -I./beken378/func/libc +endif + +# For WPA3 +ifeq ($(CFG_WPA3),1) +INCLUDES += -I./beken378/func/wolfssl +endif + +# ------------------------------------------------------------------- +# Source file list +# ------------------------------------------------------------------- +SRC_C = +DRAM_C = +SRC_OS = + +#application layer +SRC_C += ./beken378/app/app_bk.c +SRC_C += ./beken378/app/ate_app.c +SRC_C += ./beken378/app/config/param_config.c +SRC_C += ./beken378/app/standalone-ap/sa_ap.c +SRC_C += ./beken378/app/standalone-station/sa_station.c + +#demo module +SRC_C += ./beken378/demo/ieee802_11_demo.c + +#driver layer +SRC_C += ./beken378/driver/common/dd.c +SRC_C += ./beken378/driver/common/drv_model.c +SRC_C += ./beken378/driver/dma/dma.c +SRC_C += ./beken378/driver/driver.c +SRC_C += ./beken378/driver/entry/arch_main.c +#SRC_C += ./beken378/driver/fft/fft.c +SRC_C += ./beken378/driver/flash/flash.c +SRC_C += ./beken378/driver/general_dma/general_dma.c +SRC_C += ./beken378/driver/gpio/gpio.c +#SRC_C += ./beken378/driver/i2s/i2s.c +SRC_C += ./beken378/driver/icu/icu.c +SRC_C += ./beken378/driver/intc/intc.c +SRC_C += ./beken378/driver/irda/irda.c +SRC_C += ./beken378/driver/macphy_bypass/mac_phy_bypass.c +SRC_C += ./beken378/driver/phy/phy_trident.c +SRC_C += ./beken378/driver/pwm/pwm.c +SRC_C += ./beken378/driver/pwm/pwm_new.c +SRC_C += ./beken378/driver/pwm/mcu_ps_timer.c +SRC_C += ./beken378/driver/pwm/bk_timer.c +SRC_C += ./beken378/driver/rw_pub/rw_platf_pub.c +SRC_C += ./beken378/driver/saradc/saradc.c +SRC_C += ./beken378/driver/spi/spi_bk7231n.c +SRC_C += ./beken378/driver/spi/spi_master_bk7231n_new.c +SRC_C += ./beken378/driver/spi/spi_slave_bk7231n.c +SRC_C += ./beken378/driver/spidma/spidma.c +SRC_C += ./beken378/driver/sys_ctrl/sys_ctrl.c +SRC_C += ./beken378/driver/uart/Retarget.c +SRC_C += ./beken378/driver/uart/uart_bk.c +SRC_C += ./beken378/driver/uart/printf.c +SRC_C += ./beken378/driver/wdt/wdt.c + +#################################################### +#rw head start +#ifeq (${CFG_BLE_5X_VERSION}${CFG_BLE_5X_RW},11) +ifeq ("${CFG_BLE_5X_VERSION}", "1") +ifeq ("${CFG_BLE_5X_RW}", "1") +INCLUDES += -I./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/api +INCLUDES += -I./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/inc +INCLUDES += -I./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gap/gapc +INCLUDES += -I./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gap/gapm +INCLUDES += -I./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gatt +INCLUDES += -I./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gatt/attc +INCLUDES += -I./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gatt/attm +INCLUDES += -I./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gatt/atts +INCLUDES += -I./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gatt/gattc +INCLUDES += -I./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gatt/gattm +INCLUDES += -I./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/l2c/l2cc +INCLUDES += -I./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/l2c/l2cm +INCLUDES += -I./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/api +INCLUDES += -I./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg +INCLUDES += -I./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src +INCLUDES += -I./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/llc +INCLUDES += -I./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/lld +INCLUDES += -I./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/llm +INCLUDES += -I./beken378/driver/ble_5_x_rw/ble_lib/ip/em/api +INCLUDES += -I./beken378/driver/ble_5_x_rw/ble_lib/ip/hci/api +INCLUDES += -I./beken378/driver/ble_5_x_rw/ble_lib/ip/hci/src +INCLUDES += -I./beken378/driver/ble_5_x_rw/ble_lib/ip/sch/api +INCLUDES += -I./beken378/driver/ble_5_x_rw/ble_lib/ip/sch/import +INCLUDES += -I./beken378/driver/ble_5_x_rw/ble_lib/modules/aes/api +INCLUDES += -I./beken378/driver/ble_5_x_rw/ble_lib/modules/aes/src +INCLUDES += -I./beken378/driver/ble_5_x_rw/ble_lib/modules/common/api +INCLUDES += -I./beken378/driver/ble_5_x_rw/ble_lib/modules/dbg/api +INCLUDES += -I./beken378/driver/ble_5_x_rw/ble_lib/modules/dbg/src +INCLUDES += -I./beken378/driver/ble_5_x_rw/ble_lib/modules/ecc_p256/api +INCLUDES += -I./beken378/driver/ble_5_x_rw/ble_lib/modules/h4tl/api +INCLUDES += -I./beken378/driver/ble_5_x_rw/ble_lib/modules/ke/api +INCLUDES += -I./beken378/driver/ble_5_x_rw/ble_lib/modules/ke/src +INCLUDES += -I./beken378/driver/ble_5_x_rw/ble_pub/prf +INCLUDES += -I./beken378/driver/ble_5_x_rw/platform/7231n/rwip/api +INCLUDES += -I./beken378/driver/ble_5_x_rw/platform/7231n/rwip/import/reg +INCLUDES += -I./beken378/driver/ble_5_x_rw/platform/7231n/nvds/api +INCLUDES += -I./beken378/driver/ble_5_x_rw/platform/7231n/config +INCLUDES += -I./beken378/driver/ble_5_x_rw/platform/7231n/driver/reg +INCLUDES += -I./beken378/driver/ble_5_x_rw/platform/7231n/driver/rf +INCLUDES += -I./beken378/driver/ble_5_x_rw/platform/7231n/driver/uart +INCLUDES += -I./beken378/driver/ble_5_x_rw/platform/7231n/entry +INCLUDES += -I./beken378/driver/ble_5_x_rw/arch/armv5 +INCLUDES += -I./beken378/driver/ble_5_x_rw/arch/armv5/ll +INCLUDES += -I./beken378/driver/ble_5_x_rw/arch/armv5/compiler +INCLUDES += -I./beken378/driver/ble_5_x_rw/ble_pub/profiles/comm/api +INCLUDES += -I./beken378/driver/ble_5_x_rw/ble_pub/app/api +INCLUDES += -I./beken378/driver/ble_5_x_rw/ble_pub/ui +#rw head end + +#################################################### +ifeq ("${CFG_BLE_5X_USE_RWIP_LIB}", "0") +#rw source start +#ble lib +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gap/gapc/gapc.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gap/gapc/gapc_cte.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gap/gapc/gapc_hci.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gap/gapc/gapc_past.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gap/gapc/gapc_sig.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gap/gapc/gapc_smp.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gap/gapc/gapc_task.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gap/gapm/gapm.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gap/gapm/gapm_actv.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gap/gapm/gapm_addr.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gap/gapm/gapm_adv.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gap/gapm/gapm_cfg.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gap/gapm/gapm_init.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gap/gapm/gapm_list.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gap/gapm/gapm_per_sync.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gap/gapm/gapm_scan.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gap/gapm/gapm_smp.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gap/gapm/gapm_task.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gatt/attc/attc.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gatt/attm/attm.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gatt/attm/attm_db.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gatt/atts/atts.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gatt/gattc/gattc.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gatt/gattc/gattc_rc.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gatt/gattc/gattc_sdp.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gatt/gattc/gattc_svc.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gatt/gattc/gattc_task.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gatt/gattm/gattm.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gatt/gattm/gattm_task.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/l2c/l2cc/l2cc.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/l2c/l2cc/l2cc_lecb.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/l2c/l2cc/l2cc_pdu.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/l2c/l2cc/l2cc_sig.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/l2c/l2cc/l2cc_task.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/l2c/l2cm/l2cm.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/rwble_hl/rwble_hl.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/co/ble_util_buf.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/llc/llc.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/llc/llc_chmap_upd.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/llc/llc_clk_acc.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/llc/llc_con_upd.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/llc/llc_cte.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/llc/llc_dbg.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/llc/llc_disconnect.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/llc/llc_dl_upd.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/llc/llc_encrypt.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/llc/llc_feat_exch.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/llc/llc_hci.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/llc/llc_le_ping.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/llc/llc_llcp.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/llc/llc_past.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/llc/llc_phy_upd.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/llc/llc_task.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/llc/llc_ver_exch.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/lld/lld.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/lld/lld_adv.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/lld/lld_con.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/lld/lld_init.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/lld/lld_per_adv.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/lld/lld_scan.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/lld/lld_sync.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/lld/lld_test.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/llm/llm.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/llm/llm_adv.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/llm/llm_hci.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/llm/llm_init.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/llm/llm_scan.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/llm/llm_task.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/llm/llm_test.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/hci/src/hci.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/hci/src/hci_fc.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/hci/src/hci_msg.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/hci/src/hci_tl.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/sch/src/sch_alarm.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/sch/src/sch_arb.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/sch/src/sch_plan.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/sch/src/sch_prog.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/sch/src/sch_slice.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/modules/aes/src/ble_aes.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/modules/aes/src/ble_aes_c1.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/modules/aes/src/ble_aes_ccm.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/modules/aes/src/ble_aes_cmac.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/modules/aes/src/ble_aes_f4.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/modules/aes/src/ble_aes_f5.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/modules/aes/src/ble_aes_f6.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/modules/aes/src/ble_aes_g2.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/modules/aes/src/ble_aes_k1.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/modules/aes/src/ble_aes_k2.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/modules/aes/src/ble_aes_k3.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/modules/aes/src/ble_aes_k4.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/modules/aes/src/ble_aes_rpa.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/modules/aes/src/ble_aes_s1.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/modules/common/src/common_list.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/modules/common/src/common_utils.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/modules/dbg/src/dbg.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/modules/dbg/src/dbg_iqgen.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/modules/dbg/src/dbg_mwsgen.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/modules/dbg/src/dbg_swdiag.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/modules/dbg/src/dbg_task.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/modules/dbg/src/dbg_trc.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/modules/dbg/src/dbg_trc_mem.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/modules/dbg/src/dbg_trc_tl.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/modules/ecc_p256/src/ecc_p256.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/modules/h4tl/src/h4tl.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/modules/ke/src/kernel.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/modules/ke/src/kernel_event.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/modules/ke/src/kernel_mem.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/modules/ke/src/kernel_msg.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/modules/ke/src/kernel_queue.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/modules/ke/src/kernel_task.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/modules/ke/src/kernel_timer.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/modules/rwip/rwip_driver.c +#################################################### +endif ###ifeq ("${CFG_BLE_5X_USE_RWIP_LIB}", "0") + +#ble pub +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/hci/src/hci.c +SRC_C += ./beken378/driver/ble_5_x_rw/platform/7231n/rwip/src/rwip.c +SRC_C += ./beken378/driver/ble_5_x_rw/platform/7231n/rwip/src/rwble.c +SRC_C += ./beken378/driver/ble_5_x_rw/platform/7231n/entry/ble_main.c +SRC_C += ./beken378/driver/ble_5_x_rw/platform/7231n/driver/rf/rf_xvr.c +SRC_C += ./beken378/driver/ble_5_x_rw/platform/7231n/driver/uart/uart_ble.c +SRC_C += ./beken378/driver/ble_5_x_rw/platform/7231n/driver/rf/ble_rf_port.c +ifeq ("${CFG_USE_BK_HOST}", "1") +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/hci/src/hci_fc.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/hci/src/hci_msg.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_lib/ip/hci/src/hci_tl.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_pub/prf/prf.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_pub/prf/prf_utils.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_pub/profiles/comm/src/comm.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_pub/profiles/comm/src/comm_task.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_pub/app/src/app_comm.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_pub/app/src/app_ble.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_pub/app/src/app_task.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_pub/ui/ble_ui.c +SRC_C += ./beken378/driver/ble_5_x_rw/ble_pub/app/src/app_ble_task.c +endif +#rw source end +else ###ifeq ("${CFG_BLE_5X_VERSION}", "1") && ("${CFG_BLE_5X_RW}", "1") + +endif ##ifeq ("${CFG_BLE_5X_VERSION}", "1") +endif ##ifeq ("${CFG_BLE_5X_RW}", "1") +#################################################### + +#function layer +SRC_C += ./beken378/func/func.c +SRC_C += ./beken378/func/bk7011_cal/bk7231U_cal.c +SRC_C += ./beken378/func/bk7011_cal/bk7231N_cal.c +SRC_C += ./beken378/func/bk7011_cal/manual_cal_bk7231U.c +SRC_C += ./beken378/func/joint_up/role_launch.c +SRC_C += ./beken378/func/hostapd_intf/hostapd_intf.c +SRC_C += ./beken378/func/$(WPA_VERSION)/bk_patch/ddrv.c +SRC_C += ./beken378/func/$(WPA_VERSION)/bk_patch/signal.c +SRC_C += ./beken378/func/$(WPA_VERSION)/bk_patch/sk_intf.c +SRC_C += ./beken378/func/$(WPA_VERSION)/bk_patch/fake_socket.c +SRC_C += ./beken378/func/$(WPA_VERSION)/hostapd/main_none.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/crypto/aes-unwrap.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/crypto/aes-wrap.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/crypto/rc4.c +ifeq ($(CFG_WPA_CRYPTO_MBEDTLS),1) +SRC_C += ./beken378/func/$(WPA_VERSION)/src/crypto/crypto_mbedtls.c +else +SRC_C += ./beken378/func/$(WPA_VERSION)/src/crypto/aes-internal.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/crypto/aes-internal-dec.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/crypto/aes-internal-enc.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/crypto/md5.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/crypto/md5-internal.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/crypto/sha1.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/crypto/sha1-internal.c +endif +SRC_C += ./beken378/func/$(WPA_VERSION)/src/crypto/sha1-pbkdf2.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/crypto/sha1-prf.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/crypto/tls_none.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/ap/ap_config.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/ap/ap_drv_ops.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/ap/ap_list.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/ap/ap_mlme.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/ap/beacon.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/ap/drv_callbacks.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/ap/hostapd.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/ap/hw_features.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/ap/ieee802_11_auth.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/ap/ieee802_11.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/ap/ieee802_11_ht.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/ap/ieee802_11_shared.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/ap/ieee802_1x.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/ap/sta_info.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/ap/tkip_countermeasures.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/ap/utils.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/ap/wmm.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/ap/wpa_auth.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/ap/wpa_auth_glue.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/ap/wpa_auth_ie.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/common/hw_features_common.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/common/ieee802_11_common.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/common/wpa_common.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/drivers/driver_beken.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/drivers/driver_common.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/drivers/drivers.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/l2_packet/l2_packet_none.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/rsn_supp/wpa.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/rsn_supp/wpa_ie.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/utils/common.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/utils/eloop.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/utils/os_none.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/utils/wpabuf.c +SRC_C += ./beken378/func/$(WPA_VERSION)/wpa_supplicant/blacklist.c +SRC_C += ./beken378/func/$(WPA_VERSION)/wpa_supplicant/bss.c +SRC_C += ./beken378/func/$(WPA_VERSION)/wpa_supplicant/config.c +SRC_C += ./beken378/func/$(WPA_VERSION)/wpa_supplicant/config_none.c +SRC_C += ./beken378/func/$(WPA_VERSION)/wpa_supplicant/events.c +SRC_C += ./beken378/func/$(WPA_VERSION)/wpa_supplicant/main_supplicant.c +SRC_C += ./beken378/func/$(WPA_VERSION)/wpa_supplicant/notify.c +SRC_C += ./beken378/func/$(WPA_VERSION)/wpa_supplicant/wmm_ac.c +SRC_C += ./beken378/func/$(WPA_VERSION)/wpa_supplicant/wpa_scan.c +SRC_C += ./beken378/func/$(WPA_VERSION)/wpa_supplicant/wpas_glue.c +SRC_C += ./beken378/func/$(WPA_VERSION)/wpa_supplicant/wpa_supplicant.c + +ifeq ($(CFG_USE_WPA_29),1) +SRC_C += ./beken378/func/$(WPA_VERSION)/wpa_supplicant/op_classes.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/rsn_supp/pmksa_cache.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/ap/pmksa_cache_auth.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/common/notifier.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/common/wpa_psk_cache.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/utils/wpa_debug.c +SRC_C += ./beken378/func/$(WPA_VERSION)/wpa_supplicant/ctrl_iface.c +SRC_C += ./beken378/func/$(WPA_VERSION)/wpa_supplicant/wlan.c +SRC_C += ./beken378/func/$(WPA_VERSION)/wpa_supplicant/sme.c +SRC_C += ./beken378/func/$(WPA_VERSION)/wpa_supplicant/cmd_wlan.c +endif + +# for WPA3 +ifeq ($(CFG_WPA3),1) +SRC_C += ./beken378/func/$(WPA_VERSION)/src/common/sae.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/common/dragonfly.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/crypto/aes-ctr.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/crypto/aes-omac1.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/crypto/aes-siv.c +#SRC_C += ./beken378/func/$(WPA_VERSION)/src/crypto/crypto_wolfssl.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/crypto/crypto_mbedtls-bignum.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/crypto/crypto_mbedtls-ec.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/crypto/dh_group5.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/crypto/dh_groups.c +SRC_C += ./beken378/func/$(WPA_VERSION)/src/crypto/sha256.c +ifneq ($(CFG_WPA_CRYPTO_MBEDTLS),1) +SRC_C += ./beken378/func/$(WPA_VERSION)/src/crypto/sha256-internal.c +endif +SRC_C += ./beken378/func/$(WPA_VERSION)/src/crypto/sha256-prf.c +endif # CFG_WPA3 + +ifeq ($(CFG_WRAP_LIBC),1) +SRC_C += ./beken378/func/libc/stdio/lib_libvscanf.c +SRC_C += ./beken378/func/libc/stdio/lib_memsistream.c +SRC_C += ./beken378/func/libc/stdio/lib_meminstream.c +SRC_C += ./beken378/func/libc/stdio/lib_sscanf.c +SRC_C += ./beken378/func/libc/stdio/lib_vsscanf.c +SRC_C += ./beken378/func/libc/stdlib/lib_strtod.c +SRC_C += ./beken378/func/libc/stdlib/lib_qsort.c +endif + +# SRC_C += ./beken378/func/lwip_intf/lwip-2.0.2/port/ethernetif.c +# SRC_C += ./beken378/func/lwip_intf/lwip-2.0.2/port/net.c +# SRC_C += ./beken378/func/lwip_intf/lwip-2.0.2/port/sys_arch.c +# SRC_C += ./beken378/func/lwip_intf/lwip-2.0.2/src/api/api_lib.c +# SRC_C += ./beken378/func/lwip_intf/lwip-2.0.2/src/api/api_msg.c +# SRC_C += ./beken378/func/lwip_intf/lwip-2.0.2/src/api/err.c +# SRC_C += ./beken378/func/lwip_intf/lwip-2.0.2/src/api/netbuf.c +# SRC_C += ./beken378/func/lwip_intf/lwip-2.0.2/src/api/netdb.c +# SRC_C += ./beken378/func/lwip_intf/lwip-2.0.2/src/api/netifapi.c +# SRC_C += ./beken378/func/lwip_intf/lwip-2.0.2/src/api/sockets.c +# SRC_C += ./beken378/func/lwip_intf/lwip-2.0.2/src/api/tcpip.c +# SRC_C += ./beken378/func/lwip_intf/lwip-2.0.2/src/core/def.c +# SRC_C += ./beken378/func/lwip_intf/lwip-2.0.2/src/core/dns.c +# SRC_C += ./beken378/func/lwip_intf/lwip-2.0.2/src/core/inet_chksum.c +# SRC_C += ./beken378/func/lwip_intf/lwip-2.0.2/src/core/init.c +# SRC_C += ./beken378/func/lwip_intf/lwip-2.0.2/src/core/ip.c +# SRC_C += ./beken378/func/lwip_intf/lwip-2.0.2/src/core/ipv4/autoip.c +# SRC_C += ./beken378/func/lwip_intf/lwip-2.0.2/src/core/ipv4/dhcp.c +# SRC_C += ./beken378/func/lwip_intf/lwip-2.0.2/src/core/ipv4/etharp.c +# SRC_C += ./beken378/func/lwip_intf/lwip-2.0.2/src/core/ipv4/icmp.c +# SRC_C += ./beken378/func/lwip_intf/lwip-2.0.2/src/core/ipv4/igmp.c +# SRC_C += ./beken378/func/lwip_intf/lwip-2.0.2/src/core/ipv4/ip4_addr.c +# SRC_C += ./beken378/func/lwip_intf/lwip-2.0.2/src/core/ipv4/ip4.c +# SRC_C += ./beken378/func/lwip_intf/lwip-2.0.2/src/core/ipv4/ip4_frag.c +# SRC_C += ./beken378/func/lwip_intf/lwip-2.0.2/src/core/ipv6/dhcp6.c +# SRC_C += ./beken378/func/lwip_intf/lwip-2.0.2/src/core/ipv6/ethip6.c +# SRC_C += ./beken378/func/lwip_intf/lwip-2.0.2/src/core/ipv6/icmp6.c +# SRC_C += ./beken378/func/lwip_intf/lwip-2.0.2/src/core/ipv6/inet6.c +# SRC_C += ./beken378/func/lwip_intf/lwip-2.0.2/src/core/ipv6/ip6_addr.c +# SRC_C += ./beken378/func/lwip_intf/lwip-2.0.2/src/core/ipv6/ip6.c +# SRC_C += ./beken378/func/lwip_intf/lwip-2.0.2/src/core/ipv6/ip6_frag.c +# SRC_C += ./beken378/func/lwip_intf/lwip-2.0.2/src/core/ipv6/mld6.c +# SRC_C += ./beken378/func/lwip_intf/lwip-2.0.2/src/core/ipv6/nd6.c +# SRC_C += ./beken378/func/lwip_intf/lwip-2.0.2/src/core/mem.c +# SRC_C += ./beken378/func/lwip_intf/lwip-2.0.2/src/core/memp.c +# SRC_C += ./beken378/func/lwip_intf/lwip-2.0.2/src/core/netif.c +# SRC_C += ./beken378/func/lwip_intf/lwip-2.0.2/src/core/pbuf.c +# SRC_C += ./beken378/func/lwip_intf/lwip-2.0.2/src/core/raw.c +# SRC_C += ./beken378/func/lwip_intf/lwip-2.0.2/src/core/stats.c +# SRC_C += ./beken378/func/lwip_intf/lwip-2.0.2/src/core/sys.c +# SRC_C += ./beken378/func/lwip_intf/lwip-2.0.2/src/core/tcp.c +# SRC_C += ./beken378/func/lwip_intf/lwip-2.0.2/src/core/tcp_in.c +# SRC_C += ./beken378/func/lwip_intf/lwip-2.0.2/src/core/tcp_out.c +# SRC_C += ./beken378/func/lwip_intf/lwip-2.0.2/src/core/timeouts.c +# SRC_C += ./beken378/func/lwip_intf/lwip-2.0.2/src/core/udp.c +# SRC_C += ./beken378/func/lwip_intf/lwip-2.0.2/src/netif/ethernet.c +SRC_C += ./beken378/func/lwip_intf/dhcpd/dhcp-server.c +SRC_C += ./beken378/func/lwip_intf/dhcpd/dhcp-server-main.c +SRC_C += ./beken378/func/misc/fake_clock.c +SRC_C += ./beken378/func/misc/target_util.c +SRC_C += ./beken378/func/misc/start_type.c +SRC_C += ./beken378/func/misc/soft_encrypt.c +SRC_C += ./beken378/func/power_save/power_save.c +SRC_C += ./beken378/func/power_save/manual_ps.c +SRC_C += ./beken378/func/power_save/mcu_ps.c +SRC_C += ./beken378/func/rf_test/rx_sensitivity.c +SRC_C += ./beken378/func/rf_test/tx_evm.c +SRC_C += ./beken378/func/rwnx_intf/rw_ieee80211.c +SRC_C += ./beken378/func/rwnx_intf/rw_msdu.c +SRC_C += ./beken378/func/rwnx_intf/rw_msg_rx.c +SRC_C += ./beken378/func/rwnx_intf/rw_msg_tx.c +SRC_C += ./beken378/func/sim_uart/gpio_uart.c +SRC_C += ./beken378/func/sim_uart/pwm_uart.c +SRC_C += ./beken378/func/spidma_intf/spidma_intf.c +SRC_C += ./beken378/func/temp_detect/temp_detect.c +SRC_C += ./beken378/func/uart_debug/cmd_evm.c +SRC_C += ./beken378/func/uart_debug/cmd_help.c +SRC_C += ./beken378/func/uart_debug/cmd_reg.c +SRC_C += ./beken378/func/uart_debug/cmd_rx_sensitivity.c +SRC_C += ./beken378/func/uart_debug/command_line.c +SRC_C += ./beken378/func/uart_debug/command_table.c +SRC_C += ./beken378/func/uart_debug/udebug.c +SRC_C += ./beken378/func/user_driver/BkDriverFlash.c +SRC_C += ./beken378/func/user_driver/BkDriverRng.c +SRC_C += ./beken378/func/user_driver/BkDriverGpio.c +SRC_C += ./beken378/func/user_driver/BkDriverPwm.c +SRC_C += ./beken378/func/user_driver/BkDriverUart.c +SRC_C += ./beken378/func/user_driver/BkDriverWdg.c +SRC_C += ./beken378/func/user_driver/BkDriverTimer.c +SRC_C += ./beken378/func/wlan_ui/wlan_cli.c + +# For WPA3: wolfssl +ifeq ($(CFG_WPA3),1) +#SRC_C += ./beken378/func/wolfssl/wolfcrypt/src/wolfmath.c +#SRC_C += ./beken378/func/wolfssl/wolfcrypt/src/memory.c +#SRC_C += ./beken378/func/wolfssl/wolfcrypt/src/tfm.c +#SRC_C += ./beken378/func/wolfssl/wolfcrypt/src/ecc.c + +# wpa_supplicant 2.9 needs random generator +#SRC_C += ./beken378/func/wolfssl/wolfcrypt/src/random.c +#SRC_C += ./beken378/func/wolfssl/wolfcrypt/src/sha256.c +endif + +SRC_C += ./beken378/func/wlan_ui/wlan_ui.c +#SRC_C += ./beken378/func/bk_tuya_pwm/bk_tuya_pwm.c +SRC_C += ./beken378/func/net_param_intf/net_param.c + +#rwnx ip module +# SRC_C += ./beken378/ip/common/co_dlist.c +# SRC_C += ./beken378/ip/common/co_list.c +# SRC_C += ./beken378/ip/common/co_math.c +# SRC_C += ./beken378/ip/common/co_pool.c +# SRC_C += ./beken378/ip/common/co_ring.c +# SRC_C += ./beken378/ip/ke/ke_env.c +# SRC_C += ./beken378/ip/ke/ke_event.c +# SRC_C += ./beken378/ip/ke/ke_msg.c +# SRC_C += ./beken378/ip/ke/ke_queue.c +# SRC_C += ./beken378/ip/ke/ke_task.c +# SRC_C += ./beken378/ip/ke/ke_timer.c +# SRC_C += ./beken378/ip/lmac/src/chan/chan.c +# SRC_C += ./beken378/ip/lmac/src/hal/hal_desc.c +# SRC_C += ./beken378/ip/lmac/src/hal/hal_dma.c +# SRC_C += ./beken378/ip/lmac/src/hal/hal_machw.c +# SRC_C += ./beken378/ip/lmac/src/hal/hal_mib.c +# SRC_C += ./beken378/ip/lmac/src/mm/mm.c +# SRC_C += ./beken378/ip/lmac/src/mm/mm_bcn.c +# SRC_C += ./beken378/ip/lmac/src/mm/mm_task.c +# SRC_C += ./beken378/ip/lmac/src/mm/mm_timer.c +# SRC_C += ./beken378/ip/lmac/src/p2p/p2p.c +# SRC_C += ./beken378/ip/lmac/src/ps/ps.c +# SRC_C += ./beken378/ip/lmac/src/rd/rd.c +# SRC_C += ./beken378/ip/lmac/src/rwnx/rwnx.c +# SRC_C += ./beken378/ip/lmac/src/rx/rx_swdesc.c +# SRC_C += ./beken378/ip/lmac/src/rx/rxl/rxl_cntrl.c +# SRC_C += ./beken378/ip/lmac/src/rx/rxl/rxl_hwdesc.c +# SRC_C += ./beken378/ip/lmac/src/scan/scan.c +# SRC_C += ./beken378/ip/lmac/src/scan/scan_shared.c +# SRC_C += ./beken378/ip/lmac/src/scan/scan_task.c +# SRC_C += ./beken378/ip/lmac/src/sta/sta_mgmt.c +# SRC_C += ./beken378/ip/lmac/src/td/td.c +# SRC_C += ./beken378/ip/lmac/src/tdls/tdls.c +# SRC_C += ./beken378/ip/lmac/src/tdls/tdls_task.c +# SRC_C += ./beken378/ip/lmac/src/tpc/tpc.c +# SRC_C += ./beken378/ip/lmac/src/tx/tx_swdesc.c +# SRC_C += ./beken378/ip/lmac/src/tx/txl/txl_buffer.c +# SRC_C += ./beken378/ip/lmac/src/tx/txl/txl_buffer_shared.c +# SRC_C += ./beken378/ip/lmac/src/tx/txl/txl_cfm.c +# SRC_C += ./beken378/ip/lmac/src/tx/txl/txl_cntrl.c +# SRC_C += ./beken378/ip/lmac/src/tx/txl/txl_frame.c +# SRC_C += ./beken378/ip/lmac/src/tx/txl/txl_frame_shared.c +# SRC_C += ./beken378/ip/lmac/src/tx/txl/txl_hwdesc.c +# SRC_C += ./beken378/ip/lmac/src/vif/vif_mgmt.c +# SRC_C += ./beken378/ip/mac/mac.c +# SRC_C += ./beken378/ip/mac/mac_ie.c +# SRC_C += ./beken378/ip/umac/src/apm/apm.c +# SRC_C += ./beken378/ip/umac/src/apm/apm_task.c +# SRC_C += ./beken378/ip/umac/src/bam/bam.c +# SRC_C += ./beken378/ip/umac/src/bam/bam_task.c +# SRC_C += ./beken378/ip/umac/src/me/me.c +# SRC_C += ./beken378/ip/umac/src/me/me_mgmtframe.c +# SRC_C += ./beken378/ip/umac/src/me/me_mic.c +# SRC_C += ./beken378/ip/umac/src/me/me_task.c +# SRC_C += ./beken378/ip/umac/src/me/me_utils.c +# SRC_C += ./beken378/ip/umac/src/rc/rc.c +# SRC_C += ./beken378/ip/umac/src/rc/rc_basic.c +# SRC_C += ./beken378/ip/umac/src/rxu/rxu_cntrl.c +# SRC_C += ./beken378/ip/umac/src/scanu/scanu.c +# SRC_C += ./beken378/ip/umac/src/scanu/scanu_shared.c +# SRC_C += ./beken378/ip/umac/src/scanu/scanu_task.c +# SRC_C += ./beken378/ip/umac/src/sm/sm.c +# SRC_C += ./beken378/ip/umac/src/sm/sm_task.c +# SRC_C += ./beken378/ip/umac/src/txu/txu_cntrl.c + +ifeq ($(CFG_WPA3),1) +# SRC_C += ./beken378/ip/umac/src/mfp/mfp.c +# SRC_C += ./beken378/ip/umac/src/mfp/mfp_bip.c +endif + +#operation system module +SRC_OS += ./beken378/os/FreeRTOSv9.0.0/FreeRTOS/Source/croutine.c +SRC_OS += ./beken378/os/FreeRTOSv9.0.0/FreeRTOS/Source/event_groups.c +SRC_OS += ./beken378/os/FreeRTOSv9.0.0/FreeRTOS/Source/list.c +SRC_OS += ./beken378/os/FreeRTOSv9.0.0/FreeRTOS/Source/portable/Keil/ARM968es/port.c +SRC_OS += ./beken378/os/FreeRTOSv9.0.0/FreeRTOS/Source/portable/MemMang/heap_6.c +SRC_OS += ./beken378/os/FreeRTOSv9.0.0/FreeRTOS/Source/queue.c +SRC_OS += ./beken378/os/FreeRTOSv9.0.0/FreeRTOS/Source/tasks.c +SRC_OS += ./beken378/os/FreeRTOSv9.0.0/FreeRTOS/Source/timers.c +SRC_OS += ./beken378/os/FreeRTOSv9.0.0/rtos_pub.c +SRC_C += ./beken378/os/mem_arch.c +SRC_C += ./beken378/os/platform_stub.c +SRC_C += ./beken378/os/str_arch.c + +#examples for customer +TY_SRC_DIRS += $(shell find ../tuyaos/tuyaos_adapter/src -type d) +TY_SRC_DIRS += $(shell find ../tuyaos/tuyaos_adapter/include -type d) + +SRC_C += $(foreach dir, $(TY_SRC_DIRS), $(wildcard $(dir)/*.c)) # need export +SRC_C += $(foreach dir, $(TY_SRC_DIRS), $(wildcard $(dir)/*.cpp)) +SRC_C += $(foreach dir, $(TY_SRC_DIRS), $(wildcard $(dir)/*.s)) +SRC_C += $(foreach dir, $(TY_SRC_DIRS), $(wildcard $(dir)/*.S)) + +#assembling files +SRC_S = +SRC_S += ./beken378/driver/entry/boot_handlers.S +SRC_S += ./beken378/driver/entry/boot_vectors.S + +# Generate obj list +# ------------------------------------------------------------------- +# remove leading ../, ../.., ../../.. +OBJ_LIST = $(patsubst $(OBJ_DIR)/../%,$(OBJ_DIR)/%,$(patsubst $(OBJ_DIR)/../%,$(OBJ_DIR)/%,$(patsubst $(OBJ_DIR)/../%,$(OBJ_DIR)/%,$(SRC_C:%.c=$(OBJ_DIR)/%.o)))) +# The same as previoius, but cost too must time +# OBJ_LIST = $(foreach n,$(SRC_C:%.c=$(OBJ_DIR)/%.o),$(shell echo $(n) | sed -e 's|\.\./||g')) +DEPENDENCY_LIST = $(patsubst %.o,%.d,$(OBJ_LIST)) + +OBJ_S_LIST = $(SRC_S:%.S=$(OBJ_DIR)/%.O) +DEPENDENCY_S_LIST = $(SRC_S:%.S=$(OBJ_DIR)/%.d) + +OBJ_OS_LIST = $(SRC_OS:%.c=$(OBJ_DIR)/%.marm.o) +DEPENDENCY_OS_LIST = $(SRC_OS:%.c=$(OBJ_DIR)/%.d) + +# Compile options +# ------------------------------------------------------------------- +CFLAGS = +CFLAGS += -g -mthumb -mcpu=arm968e-s -march=armv5te -mthumb-interwork -mlittle-endian -Os -std=c99 -ffunction-sections -Wall -fsigned-char -fdata-sections -Wunknown-pragmas -nostdlib -Wno-unused-function -Wno-unused-but-set-variable + +OSFLAGS = +OSFLAGS += -g -marm -mcpu=arm968e-s -march=armv5te -mthumb-interwork -mlittle-endian -Os -std=c99 -ffunction-sections -Wall -fsigned-char -fdata-sections -Wunknown-pragmas + +ASMFLAGS = +ASMFLAGS += -g -marm -mthumb-interwork -mcpu=arm968e-s -march=armv5te -x assembler-with-cpp + +LFLAGS = +LFLAGS += -g -Wl,--gc-sections -marm -mcpu=arm968e-s -mthumb-interwork -nostdlib -Xlinker -Map=tuya.map +LFLAGS += -Wl,-wrap,malloc -Wl,-wrap,_malloc_r -Wl,-wrap,free -Wl,-wrap,_free_r -Wl,-wrap,zalloc -Wl,-wrap,calloc -Wl,-wrap,realloc -Wl,-wrap,_realloc_r +LFLAGS += -Wl,-wrap,printf -Wl,-wrap,vsnprintf -Wl,-wrap,snprintf -Wl,-wrap,sprintf -Wl,-wrap,puts + +# stdlib wrapper +ifeq ($(CFG_WRAP_LIBC),1) +LFLAGS += -Wl,-wrap,strtod -Wl,-wrap,qsort +LFLAGS += -Wl,-wrap,sscanf +endif + +# For WPA3 +ifeq ($(CFG_WPA3),1) +WOLFSSL_CFLAGS += -DWOLFSSL_BEKEN +CFLAGS += $(WOLFSSL_CFLAGS) +endif + +LIBFLAGS = +LIBFLAGS += -L./beken378/lib/ -lrwnx +ifeq ("${CFG_BLE_5X_USE_RWIP_LIB}", "1") +ifeq ("${CFG_USE_BK_HOST}", "1") +LIBFLAGS += -L./beken378/lib/ -lble +else +LIBFLAGS += -L./beken378/lib/ -lblenohost +endif +endif + +ifeq ("${CFG_GIT_VERSION}", "") + +else +CFLAGS += -DVCS_RELEASE_VERSION=\"$(CFG_GIT_VERSION)\" +endif + +# Compile +# ------------------------------------------------------------------- +# add tuya iot lib compile support +# ------------------------------------------------------------------- +LIBFLAGS += -L $(LIBS_DIR) $(addprefix -l, $(LIBS)) +ifeq ("${CFG_USE_BK_HOST}", "0") +ifneq ($(wildcard $(TOP_DIR)/libs/libtal_ble_host_stack.a), ) +LIBFLAGS += -L $(TOP_DIR)/libs/ -ltal_ble_host_stack +endif +endif +CFLAGS += -DUSER_SW_VER=\"$(APP_VERSION)\" -DAPP_BIN_NAME=\"$(APP_BIN_NAME)\" + +# ------------------------------------------------------------------- +# add tuya iot application compile support +# ------------------------------------------------------------------- +TY_OUTPUT = ${OUTPUT_DIR}/$(APP_BIN_NAME)_$(APP_VERSION) +TY_INC_DIRS += ${HEADER_DIR} +#TY_INC_DIRS += $(shell find $(TOP_DIR)/sdk/include -type d) +#SDK_INCLUDE_DIRS := $(shell find $(TOP_DIR)/sdk -name include -type d) +#TY_INC_DIRS += $(foreach dir,$(SDK_INCLUDE_DIRS),$(shell find $(dir) -type d)) + +#TY_INC_DIRS := $(shell find $(TOP_INCLUDE_DIR)/adapter -name include -type d) +# TY_INC_DIRS += $(shell find $(TOP_DIR)/include -type d) +# TY_INC_DIRS += $(shell find $(TOP_DIR)/${APP_DIR}/$(APP_BIN_NAME)/include -type d) +# TY_INC_DIRS += $(shell find ../tuyaos/tuyaos_adapter/include -type d) +#TY_INC_DIRS += $(shell find $(TOP_DIR)/include -type d) +TY_INC_DIRS += $(shell find ../tuyaos/tuyaos_adapter/include -type d) +# TY_INC_DIRS += $(shell find $(TOP_DIR)/samples/$(APP_BIN_NAME)/include -type d) +#TY_INC_DIRS += $(shell find $(TOP_DIR)/samples/$(APP_BIN_NAME) -type d) + +INCLUDES += $(foreach base_dir, $(TY_INC_DIRS), $(addprefix -I , $(base_dir))) + +$(TY_OBJS): %.o : %.c + echo "build $@ ..." + @$(CC) $(CFLAGS) $(TY_IOT_CFLAGS) $(INCLUDES) -c $< -o $@ + @$(CC) $(CFLAGS) $(TY_IOT_CFLAGS) $(INCLUDES) -c $< -MM -MT $@ -MF $(OBJ_DIR)/$(notdir $(patsubst %.o,%.d,$@)) + @cp $@ $(OBJ_DIR)/$(notdir $@) + @chmod 777 $(OBJ_DIR)/$(notdir $@) + +sinclude $(TY_DEPENDENCY_LIST) + +CUR_PATH = $(shell pwd) +.PHONY: application + +test_target: prerequirement $(OBJ_LIST) $(OBJ_S_LIST) $(OBJ_OS_LIST) $(TY_IOT_LIB) +ifneq ($(COMPONENTS_LIB),) +ifneq ($(COMP_SRCS),) + @$(MAKE) -f application.mk comp_libs +endif # COMP_SRCS +endif # COMPONENTS_LIB + + +application: test_target +ifeq ("${ota_idx}", "1") + $(Q)$(ECHO) " $(GREEN)LD $(APP_BIN_NAME)_$(APP_VERSION).axf$(NC)" + $(Q)$(LD) $(LFLAGS) -o $(TY_OUTPUT)/$(APP_BIN_NAME)_$(APP_VERSION).axf $(OBJ_LIST) $(OBJ_S_LIST) $(OBJ_OS_LIST) $(LIBFLAGS) -T./beken378/build/bk7231n_ota.ld +else ifeq ("${ota_idx}", "2") +else + @echo =========================================================== + @echo ota_idx must be "1" or "2" + @echo =========================================================== +endif + + $(NM) $(TY_OUTPUT)/$(APP_BIN_NAME)_$(APP_VERSION).axf | sort > $(TY_OUTPUT)/$(APP_BIN_NAME)_$(APP_VERSION).map + $(OBJDUMP) -d $(TY_OUTPUT)/$(APP_BIN_NAME)_$(APP_VERSION).axf > $(TY_OUTPUT)/$(APP_BIN_NAME)_$(APP_VERSION).asm + $(OBJCOPY) -O binary $(TY_OUTPUT)/$(APP_BIN_NAME)_$(APP_VERSION).axf $(TY_OUTPUT)/$(APP_BIN_NAME)_$(APP_VERSION).bin +# Generate build info +# ------------------------------------------------------------------- + +vpath % ..:../..:../../.. +.PHONY: prerequirement +prerequirement: + + echo prerequirement0 + @echo =========================================================== + @echo Build $(APP_BIN_NAME) + @echo =========================================================== + echo prerequirement1 + mkdir -p $(OBJ_DIR) +#mkdir -p $(BIN_DIR) +#@echo $(OBJ_LIST) +#@echo $(OBJ_S_LIST) +#@echo $(OBJ_OS_LIST) +#@echo $(DEPENDENCY_LIST) + echo prerequirement2 + + @# add tuya bin output + @mkdir -p $(TY_OUTPUT) + +$(OBJ_DIR)/%.o: %.c + $(Q)if [ ! -d $(dir $@) ]; then mkdir -p $(dir $@); fi + $(Q)$(ECHO) " $(GREEN)CC $<$(NC)" + $(Q)$(CC) $(CFLAGS) $(INCLUDES) -c $< -o $@ + $(Q)$(CC) $(CFLAGS) $(INCLUDES) -c $< -MM -MT $@ -MF $(patsubst %.o,%.d,$@) + +$(OBJ_DIR)/%.O: %.S + $(Q)if [ ! -d $(dir $@) ]; then mkdir -p $(dir $@); fi + $(Q)$(ECHO) " $(GREEN)AS $<$(NC)" + $(Q)$(CC) $(ASMFLAGS) $(INCLUDES) -c $< -o $@ + $(Q)$(CC) $(ASMFLAGS) $(INCLUDES) -c $< -MM -MT $@ -MF $(patsubst %.O,%.d,$@) + +$(OBJ_DIR)/%.marm.o: %.c + $(Q)if [ ! -d $(dir $@) ]; then mkdir -p $(dir $@); fi + $(Q)$(ECHO) " $(GREEN)CC $<$(NC)" + $(Q)$(CC) $(OSFLAGS) $(INCLUDES) -c $< -o $@ + $(Q)$(CC) $(OSFLAGS) $(INCLUDES) -c $< -MM -MT $@ -MF $(patsubst %.marm.o,%.d,$@) + +-include $(DEPENDENCY_LIST) +-include $(DEPENDENCY_S_LIST) +-include $(DEPENDENCY_OS_LIST) + +# ------------------------------------------------------------------- +# Generate build info +# ------------------------------------------------------------------- +.PHONY: setup +setup: + @echo "----------------" + @echo Setup $(GDB_SERVER) + @echo "----------------" + +.PHONY: debug +debug: + @if [ ! -f $(FLASH_TOOLDIR)/rtl_gdb_debug.txt ] ; then echo Please do \"make setup GDB_SERVER=[jlink or openocd]\" first; echo && false ; fi +ifeq ($(findstring CYGWIN, $(OS)), CYGWIN) + $(FLASH_TOOLDIR)/Check_Jtag.sh + cmd /c start $(GDB) -x $(FLASH_TOOLDIR)/rtl_gdb_debug.txt +else + $(GDB) -x $(FLASH_TOOLDIR)/rtl_gdb_debug.txt +endif + +.PHONY: clean +clean: +ifneq ($(COMPONENTS_LIB),) +ifneq ($(COMP_SRCS),) + @$(MAKE) -f application.mk comp_libs_clean +endif # COMP_SRCS +endif # COMPONENTS_LIB + @echo "clean $(TY_OUTPUT)" + -rm -f .config + rm -rf $(TARGET) + rm -rf $(TY_OUTPUT) + diff --git a/beken_os/beken378/app/airkiss/airkiss.c b/beken_os/beken378/app/airkiss/airkiss.c new file mode 100755 index 0000000..e235301 --- /dev/null +++ b/beken_os/beken378/app/airkiss/airkiss.c @@ -0,0 +1,561 @@ +#include "airkiss.h" +#include +#include +#include + +#include "mac_frame.h" +#include "mac_ie.h" + +#define PASSWORD_MAX_LEN 32 +#define ESSID_MAX_LEN 32 +#define USR_DATA_BUFF_MAX_SIZE (PASSWORD_MAX_LEN + 1 + ESSID_MAX_LEN) + +typedef enum +{ + AIRKISS_STATE_STOPED = 0, + AIRKISS_STATE_IDLE, + AIRKISS_STATE_SRC_LOCKED, + AIRKISS_STATE_MAGIC_CODE_COMPLETE, + AIRKISS_STATE_PREFIX_CODE_COMPLETE, + AIRKISS_STATE_COMPLETE +} AIR_KISS_STATE; + +#define MAX_SRC_NUM 10 +typedef struct { + u8 crc; + u8 rev_cnt; + u8 ap_sta; + u8 seq_cnt; + u16 len; + u16 seq; +} src_info_st; + +typedef struct +{ + src_info_st src_info[MAX_SRC_NUM]; + u8 src_num; +}guide_code_record; + +#define MAX_MAGIC_CODE_RECORD 4 +typedef struct +{ + unsigned short record[MAX_MAGIC_CODE_RECORD + 1]; +}magic_code_record; + +#define MAX_PREFIX_CODE_RECORD 4 +typedef struct +{ + unsigned short record[MAX_PREFIX_CODE_RECORD + 1]; +}prfix_code_record; + +#define MAX_SEQ_CODE_RECORD 6 +typedef struct +{ + unsigned short record[MAX_SEQ_CODE_RECORD + 1]; +}seq_code_record; + +union airkiss_data{ + guide_code_record guide_code; + magic_code_record magic_code; + prfix_code_record prefix_code; + seq_code_record seq_code; +}; + +typedef struct +{ + char* pwd; + char* ssid; + unsigned char pswd_len; + unsigned char ssid_len; + unsigned char random_num; + unsigned char ssid_crc; //reserved used as ssid_crc + //above is airkiss_context_t + unsigned char usr_data[USR_DATA_BUFF_MAX_SIZE]; + unsigned char airkiss_state; + unsigned char src_mac_crc; + unsigned char src_ap_sta; + unsigned char base_len; + unsigned char need_seq; + unsigned char total_len; + unsigned char pswd_lencrc; + unsigned short seq_success_map; + unsigned short seq_success_map_cmp; + union airkiss_data data; +}_airkiss_local_context; + +const char airkiss_vers[] = "V1.0, Design by beken corporation\0"; +static airkiss_config_t *akconf = 0; +static _airkiss_local_context *_akcontext; + +//crc8 +static unsigned char calcrc_1byte(unsigned char abyte) +{ + unsigned char i,crc_1byte; + crc_1byte=0; + for(i = 0; i < 8; i++) + { + if(((crc_1byte^abyte)&0x01)) + { + crc_1byte^=0x18; + crc_1byte>>=1; + crc_1byte|=0x80; + } + else + { + crc_1byte>>=1; + } + abyte>>=1; + } + return crc_1byte; +} + +static unsigned char calcrc_bytes(unsigned char *p,unsigned int num_of_bytes) +{ + unsigned char crc=0; + while(num_of_bytes--) + { + crc=calcrc_1byte(crc^*p++); + } + return crc; +} + +static void airkiss_resest_data(void) +{ + akconf->memset(&_akcontext->data, 0, sizeof(union airkiss_data)); +} + +const char* airkiss_version(void) +{ + return airkiss_vers; +} + +/* return 1 is valid + * return 0 is invalid + * */ +static int airkiss_filter(const unsigned char *frame, int size) +{ + int isvalid = 0; + u8 *mac_ptr = NULL; + struct mac_hdr *fmac_hdr = (struct mac_hdr *)frame; + + if(MAC_FCTRL_DATA_T != (fmac_hdr->fctl & MAC_FCTRL_TYPE_MASK)) + { + goto invalid; + } + + // after discover + // at least base len, not more than 2^9; + if(size < _akcontext->base_len || size > _akcontext->base_len + 512) + { + goto invalid; + } + + if((fmac_hdr->fctl & MAC_FCTRL_TODS_FROMDS) == MAC_FCTRL_FROMDS) + { + if(_akcontext->src_ap_sta != 1) + { + goto invalid; + } + mac_ptr = (u8*)&fmac_hdr->addr3; + } + else if((fmac_hdr->fctl & MAC_FCTRL_TODS_FROMDS) == MAC_FCTRL_TODS) + { + if(_akcontext->src_ap_sta != 2) + { + goto invalid; + } + mac_ptr = (u8*)&fmac_hdr->addr2; + } + + if(_akcontext->src_mac_crc != calcrc_bytes(mac_ptr, 6)) + { + goto invalid; + } + + isvalid = 1; + +invalid: + return isvalid; +} + +/* return 1 is valid + * return 0 is invalid + * */ +static int airkiss_discover_filter(const unsigned char *frame, int size) +{ + int isvalid = 0; + + struct mac_hdr *fmac_hdr = (struct mac_hdr *)frame; + + if(MAC_FCTRL_DATA_T != (fmac_hdr->fctl & MAC_FCTRL_TYPE_MASK)) + { + goto invalid; + } + + // at least mac head, not more than 2^9; + if(size < 24 || size > 1024) + { + goto invalid; + } + + isvalid = 1; + +invalid: + + return isvalid; +} + +static void airkiss_record_move_ones(void *base_addr, int record_num) +{ + int i; + unsigned short *record_base = base_addr; + + for(i = 0; i < record_num; i++) + { + record_base[i] = record_base[i+1]; + } +} + +static void airkiss_add_seq_data(const unsigned char *data, int seq) +{ + if(seq < _akcontext->need_seq) + { + if((seq*4 + 4) <= USR_DATA_BUFF_MAX_SIZE) + { + if((_akcontext->seq_success_map & (1 << seq)) == 0) + { + akconf->memcpy(_akcontext->usr_data + seq*4, data, 4); + _akcontext->seq_success_map |= (1 << seq); + } + } + } +} + +int airkiss_init(airkiss_context_t* context, + const airkiss_config_t* config) +{ + if(!context || !config) + return -1; + + akconf = (airkiss_config_t*)config; + if(sizeof(_airkiss_local_context) > sizeof(airkiss_context_t)) + { + akconf->printf("airkiss_local_context to large, size:%ld\r\n", + sizeof(_airkiss_local_context)); + return -1; + } + + _akcontext = (_airkiss_local_context*)context; + akconf->memset(_akcontext, 0, sizeof(_airkiss_local_context)); + + _akcontext->airkiss_state = AIRKISS_STATE_IDLE; + + akconf->printf("airkiss_local_context size:%ld\r\n", sizeof(_airkiss_local_context)); + return 0; +} + +static int airkiss_add_src_macinfo(u8 mac_crc, u8 ap_sta, u16 f_len, u16 f_seq) +{ + int success = 0; + int i; + u8 src_num = _akcontext->data.guide_code.src_num; + src_info_st *src_info_ptr = &_akcontext->data.guide_code.src_info[0]; + + for(i=0; idata.guide_code.src_info[i]; + if((src_info_ptr->crc == mac_crc) + && (src_info_ptr->ap_sta == ap_sta)) + { + if(src_info_ptr->seq == f_seq) + break; + + if(f_len == (src_info_ptr->len + 1)) + src_info_ptr->seq_cnt++; + else + src_info_ptr->seq_cnt = 0; + + src_info_ptr->len = f_len; + src_info_ptr->seq = f_seq; + src_info_ptr->rev_cnt++; + + if(src_info_ptr->seq_cnt == 3) + { + _akcontext->base_len = src_info_ptr->len - 4; + _akcontext->src_ap_sta = src_info_ptr->ap_sta; + _akcontext->src_mac_crc = src_info_ptr->crc; + success = 1; + } + break; + } + } + + if(i == src_num) + { + if(src_num == MAX_SRC_NUM) + { + // replace and least one + u8 min_rev_cnt = 255; + int min_idx = 0; + for(i = 0; i < MAX_SRC_NUM; i++) + { + src_info_ptr = &_akcontext->data.guide_code.src_info[i]; + if(min_rev_cnt > src_info_ptr->rev_cnt) + { + min_rev_cnt = src_info_ptr->rev_cnt; + min_idx = i; + } + } + i = src_num = min_idx; + } + + src_info_ptr = &_akcontext->data.guide_code.src_info[i]; + _akcontext->data.guide_code.src_num++; + + src_info_ptr->crc = mac_crc; + src_info_ptr->len = f_len; + src_info_ptr->seq = f_seq; + src_info_ptr->rev_cnt = 1; + src_info_ptr->seq_cnt = 0; + src_info_ptr->ap_sta = ap_sta; + } + + akconf->printf("%s/guide field:%2d ", (ap_sta == 2)?"STA":" AP", i); + akconf->printf("mac_crc:0x%02x, len:%4d, seq_cnt:%3d, rev_cnt:%3d, seq:%4d\r\n", + src_info_ptr->crc, src_info_ptr->len, src_info_ptr->seq_cnt, + src_info_ptr->rev_cnt, src_info_ptr->seq); + + return success; +} + +// 1: locked +// 0: nothing happened, contine +static int airkiss_recv_discover(const void* frame, unsigned short length) +{ + int success = 0; + u16 frame_seq = 0; + u8 mac_crc = 0, ap_sta = 0; + u8 *mac_ptr = 0; + struct mac_hdr *fmac_hdr = (struct mac_hdr *)frame; + + if((fmac_hdr->fctl & MAC_FCTRL_TODS_FROMDS) == MAC_FCTRL_FROMDS) + { + mac_ptr = (u8*)&fmac_hdr->addr3; + ap_sta = 1; //from ap + } + else if((fmac_hdr->fctl & MAC_FCTRL_TODS_FROMDS) == MAC_FCTRL_TODS) + { + mac_ptr = (u8*)&fmac_hdr->addr2; + ap_sta = 2; // from sta + } + + mac_crc = calcrc_bytes(mac_ptr, 6); + frame_seq = (fmac_hdr->seq)>>4; + + success = airkiss_add_src_macinfo(mac_crc, ap_sta, length, frame_seq); + + if(success) + { + _akcontext->airkiss_state = AIRKISS_STATE_SRC_LOCKED; + airkiss_resest_data(); + akconf->printf("airkiss_recv_discover success\r\n"); + akconf->printf("base len:%d\r\n", _akcontext->base_len); + } + + return success; +} + +static void airkiss_process_magic_code(unsigned short length) +{ + _akcontext->data.magic_code.record[MAX_MAGIC_CODE_RECORD] = length - _akcontext->base_len; + + + airkiss_record_move_ones(_akcontext->data.magic_code.record, MAX_MAGIC_CODE_RECORD); + + + if(((_akcontext->data.magic_code.record[0]&0x01f0)==0x0000)&& + ((_akcontext->data.magic_code.record[1]&0x01f0)==0x0010)&& + ((_akcontext->data.magic_code.record[2]&0x01f0)==0x0020)&& + ((_akcontext->data.magic_code.record[3]&0x01f0)==0x0030)) + { + // attention: not airkiss encode stand for 0, but use 8 for instand + // we can't get 0x0 but get 0x8, here we and 0x0007 to get 0 + // this problem only happen in bssid + keylen+ 1 < 16 + _akcontext->total_len = ((_akcontext->data.magic_code.record[0] & 0x0007) << 4) + (_akcontext->data.magic_code.record[1] & 0x000F); + _akcontext->ssid_crc = ((_akcontext->data.magic_code.record[2] & 0x000F) << 4) + (_akcontext->data.magic_code.record[3] & 0x000F); + //TODO:double check magic code + _akcontext->airkiss_state = AIRKISS_STATE_MAGIC_CODE_COMPLETE; + airkiss_resest_data(); + akconf->printf("airkiss_process_magic_code success\r\n"); + akconf->printf("total_len:%d, ssid crc:%x\r\n", _akcontext->total_len, _akcontext->ssid_crc); + } +} + +static void airkiss_process_prefix_code(unsigned short length) +{ + _akcontext->data.prefix_code.record[MAX_PREFIX_CODE_RECORD] = length - _akcontext->base_len; + + + airkiss_record_move_ones(_akcontext->data.prefix_code.record, MAX_PREFIX_CODE_RECORD ); + + + if((_akcontext->data.prefix_code.record[0]&0x01f0)==0x0040&& + (_akcontext->data.prefix_code.record[1]&0x01f0)==0x0050&& + (_akcontext->data.prefix_code.record[2]&0x01f0)==0x0060&& + (_akcontext->data.prefix_code.record[3]&0x01f0)==0x0070) + { + _akcontext->pswd_len = ((_akcontext->data.prefix_code.record[0] & 0x000F) << 4) + (_akcontext->data.prefix_code.record[1] & 0x000F); + if(_akcontext->pswd_len > PASSWORD_MAX_LEN) + _akcontext->pswd_len = 0; + + _akcontext->pswd_lencrc = ((_akcontext->data.prefix_code.record[2] & 0x000F) << 4) + (_akcontext->data.prefix_code.record[3] & 0x000F); + if(calcrc_1byte(_akcontext->pswd_len)==_akcontext->pswd_lencrc) + { + _akcontext->airkiss_state = AIRKISS_STATE_PREFIX_CODE_COMPLETE; + } + else + { + akconf->printf("password length crc error.\r\n"); + airkiss_resest_data(); + return; + } + + // receive password, random and ssid + _akcontext->need_seq = ((_akcontext->total_len) + 3)/4; + _akcontext->seq_success_map_cmp = (1 << _akcontext->need_seq) - 1; // EXAMPLE: need_seq = 5; seq_success_map_cmp = 0x1f; ??? + + airkiss_resest_data(); + akconf->printf("airkiss_process_prefix_code success\r\n"); + akconf->printf(" pswd_len:%d, pswd_lencrc:%x, need seq:%d, seq map:%x\r\n", + _akcontext->pswd_len, _akcontext->pswd_lencrc, _akcontext->need_seq, _akcontext->seq_success_map_cmp); + } +} + +static void airkiss_process_sequence(unsigned short length) +{ + + _akcontext->data.seq_code.record[MAX_SEQ_CODE_RECORD] = length - _akcontext->base_len; + + airkiss_record_move_ones(_akcontext->data.seq_code.record, MAX_SEQ_CODE_RECORD); + + if(((_akcontext->data.seq_code.record[0]&0x180)==0x80) && + ((_akcontext->data.seq_code.record[1]&0x180)==0x80)) + { + unsigned char seq_crc, cur_seq, seq_byte, data[5]={0}; + unsigned short *pdata = &_akcontext->data.seq_code.record[0]; + int seq_idx; + + seq_crc = pdata[0]&0x7F; //seq crc + seq_idx = cur_seq = data[0] = pdata[1]&0x7F; //seq index + + // aready received + if((_akcontext->seq_success_map & (1 << seq_idx))) + return; + + if(cur_seq <= ((_akcontext->total_len>>2)+1)) + { + int i; + seq_byte = _akcontext->total_len - (cur_seq << 2); + seq_byte = (seq_byte>4)? 4 : seq_byte; + + for(i=0; iprintf("[crc:%02x][index:%d]:%02x,%02x,%02x,%02x; ", + seq_crc, cur_seq, data[1], data[2], data[3], data[4]); + + if(seq_crc == (calcrc_bytes(data, seq_byte+1)&0x7F)) + { + airkiss_add_seq_data(&data[1], cur_seq); + + akconf->printf("seq mapped:%x\r\n", _akcontext->seq_success_map); + + airkiss_resest_data(); + + if(_akcontext->seq_success_map_cmp == _akcontext->seq_success_map) + { + int i; + akconf->printf("User data is :"); + for(i=0; i<_akcontext->total_len; i++) + { + akconf->printf("%02x ",_akcontext->usr_data[i]); + } + akconf->printf("\r\n"); + _akcontext->random_num = _akcontext->usr_data[_akcontext->pswd_len]; + _akcontext->usr_data[_akcontext->pswd_len] = 0; + _akcontext->pwd = (char*)_akcontext->usr_data; + _akcontext->ssid_len = _akcontext->total_len - _akcontext->pswd_len; + + _akcontext->ssid = (char*)_akcontext->usr_data + _akcontext->pswd_len + 1; + _akcontext->usr_data[_akcontext->pswd_len + 1 + _akcontext->ssid_len] = 0; + + _akcontext->airkiss_state = AIRKISS_STATE_COMPLETE; + } + } + else + { + akconf->printf("crc check error. calc crc:[%02x-%02x]\r\n", + seq_crc, + calcrc_bytes(data,seq_byte+1)&0x7F); + } + } + } +} + +int airkiss_recv(airkiss_context_t* context, + const void* frame, unsigned short length) +{ + if(_akcontext->airkiss_state != AIRKISS_STATE_IDLE) { + if(!airkiss_filter(frame, length)) + return AIRKISS_STATUS_CONTINUE; + } + + switch(_akcontext->airkiss_state) + { + case AIRKISS_STATE_IDLE: + if(airkiss_discover_filter(frame, length)) + { + int is_locked = airkiss_recv_discover(frame, length); + if(is_locked) + return AIRKISS_STATUS_CHANNEL_LOCKED; + } + break; + case AIRKISS_STATE_SRC_LOCKED: + airkiss_process_magic_code(length); + break; + case AIRKISS_STATE_MAGIC_CODE_COMPLETE: + airkiss_process_prefix_code(length); + break; + case AIRKISS_STATE_PREFIX_CODE_COMPLETE: + airkiss_process_sequence(length); + if(_akcontext->airkiss_state == AIRKISS_STATE_COMPLETE) + return AIRKISS_STATUS_COMPLETE; + break; + + default: + _akcontext->airkiss_state = AIRKISS_STATE_IDLE; + break; + } + return AIRKISS_STATUS_CONTINUE; +} + +int airkiss_get_result(airkiss_context_t* context, + airkiss_result_t* result) +{ + memcpy(result, _akcontext, sizeof(airkiss_result_t)); + return 0; +} + +int airkiss_change_channel(airkiss_context_t* context) +{ + memset(_akcontext , 0, sizeof(_airkiss_local_context)); + _akcontext->airkiss_state = AIRKISS_STATE_IDLE; + return 0; +} + +// EOF diff --git a/beken_os/beken378/app/airkiss/airkiss.h b/beken_os/beken378/app/airkiss/airkiss.h new file mode 100755 index 0000000..5b23375 --- /dev/null +++ b/beken_os/beken378/app/airkiss/airkiss.h @@ -0,0 +1,218 @@ +/* + * airkiss.h + * + * Created on: 2015-1-26 + * Author: peterfan + */ + +#ifndef AIRKISS_H_ +#define AIRKISS_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * 定义AIRKISS_ENABLE_CRYPT为1以启用AirKiss加密功能 + */ +#ifndef AIRKISS_ENABLE_CRYPT +#define AIRKISS_ENABLE_CRYPT 0 +#endif + +typedef void* (*airkiss_memset_fn) (void* ptr, int value, unsigned int num); +typedef void* (*airkiss_memcpy_fn) (void* dst, const void* src, unsigned int num); +typedef int (*airkiss_memcmp_fn) (const void* ptr1, const void* ptr2, unsigned int num); +typedef int (*airkiss_printf_fn) (const char* format, ...); + + +/* + * 对AirKiss库进行配置,目前仅定义了一些回调函数 + */ +typedef struct +{ + /* + * 为尽量减少库文件体积,如下c标准库函数需要上层使用者提供 + * 其中printf可以为NULL + */ + airkiss_memset_fn memset; + airkiss_memcpy_fn memcpy; + airkiss_memcmp_fn memcmp; + airkiss_printf_fn printf; + +} airkiss_config_t; + +/* + * AirKiss API工作需要的结构体,必须为全局变量或者通过malloc动态分配 + */ +typedef struct +{ + int dummyap[26]; + int dummy[32]; +} airkiss_context_t; + +/* + * AirKiss解码成功后的结果 + */ +typedef struct +{ + char* pwd; /* wifi密码,以'\0'结尾 */ + char* ssid; /* wifi ssid,以'\0'结尾 */ + unsigned char pwd_length; /* wifi密码长度 */ + unsigned char ssid_length; /* wifi ssid长度 */ + unsigned char random; /* 随机值,根据AirKiss协议,当wifi连接成功后,需要通过udp向10000端口广播这个随机值,这样AirKiss发送端(微信客户端或者AirKissDebugger)就能知道AirKiss已配置成功 */ + unsigned char reserved; /* 保留值 */ +} airkiss_result_t; + +/* + * airkiss_recv()正常情况下的返回值 + */ +typedef enum +{ + /* 解码正常,无需特殊处理,继续调用airkiss_recv()直到解码成功 */ + AIRKISS_STATUS_CONTINUE = 0, + + /* wifi信道已经锁定,上层应该立即停止切换信道 */ + AIRKISS_STATUS_CHANNEL_LOCKED = 1, + + /* 解码成功,可以调用airkiss_get_result()取得结果 */ + AIRKISS_STATUS_COMPLETE = 2 + +} airkiss_status_t; + +#if AIRKISS_ENABLE_CRYPT + +/* + * 设置解密key,最长可以为128bit,若传入的key不足128bit,则默认用0填充 + * + * 返回值 + * < 0:出错,通常是参数错误 + * 0:成功 + */ +int airkiss_set_key(airkiss_context_t* context, const unsigned char* key, unsigned int length); + +#endif + +/* + * 获取AirKiss库版本信息 + */ +const char* airkiss_version(void); + +/* + * 初始化AirKiss库,如要复用context,可以多次调用 + * + * 返回值 + * < 0:出错,通常是参数错误 + * 0:成功 + */ +int airkiss_init(airkiss_context_t* context, const airkiss_config_t* config); + +/* + * 开启WiFi Promiscuous Mode后,将收到的包传给airkiss_recv以进行解码 + * + * 参数说明 + * frame:802.11 frame mac header(must contain at least first 24 bytes) + * length:total frame length + * + * 返回值 + * < 0:出错,通常是参数错误 + * >= 0:成功,请参考airkiss_status_t + */ +int airkiss_recv(airkiss_context_t* context, const void* frame, unsigned short length); + +/* + * 当airkiss_recv()返回AIRKISS_STATUS_COMPLETE后,调用此函数来获取AirKiss解码结果 + * + * 返回值 + * < 0:出错,解码状态还不是AIRKISS_STATUS_COMPLETE + * 0:成功 + */ +int airkiss_get_result(airkiss_context_t* context, airkiss_result_t* result); + +/* + * 上层切换信道以后,可以调用一下本接口清缓存,降低锁定错信道的概率,注意调用的逻辑是在airkiss_init之后 + * + * 返回值 + * < 0:出错,通常是参数错误 + * 0:成功 + */ +int airkiss_change_channel(airkiss_context_t* context); + +/* + * + * 以上是实现智能配置网络的相关API,以下是微信内网发现相关API + * + */ + +/* + * airkiss_lan_recv()的返回值 + */ +typedef enum +{ + /* 提供的数据缓冲区长度不足 */ + AIRKISS_LAN_ERR_OVERFLOW = -5, + + /* 当前版本不支持的指令类型 */ + AIRKISS_LAN_ERR_CMD = -4, + + /* 打包数据出错 */ + AIRKISS_LAN_ERR_PAKE = -3, + + /* 函数传递参数出错 */ + AIRKISS_LAN_ERR_PARA = -2, + + /* 报文数据错误 */ + AIRKISS_LAN_ERR_PKG = -1, + + /* 报文格式正确,但是不需要设备处理的数据包 */ + AIRKISS_LAN_CONTINUE = 0, + + /* 接收到发现设备请求数据包 */ + AIRKISS_LAN_SSDP_REQ = 1, + + /* 数据包打包完成 */ + AIRKISS_LAN_PAKE_READY = 2 + + +} airkiss_lan_ret_t; + + +typedef enum +{ + AIRKISS_LAN_SSDP_REQ_CMD = 0x1, + AIRKISS_LAN_SSDP_RESP_CMD = 0x1001, + AIRKISS_LAN_SSDP_NOTIFY_CMD = 0x1002 +} airkiss_lan_cmdid_t; + +/* + * 设备进入内网发现模式后,将收到的包传给airkiss_lan_recv以进行解析 + * + * 参数说明 + * body:802.11 frame mac header(must contain at least first 24 bytes) + * length:total frame length + * config:AirKiss回调函数 + * + * 返回值 + * < 0:出错,请参考airkiss_lan_ret_t,通常是报文数据出错 + * >= 0:成功,请参考airkiss_lan_ret_t + */ +int airkiss_lan_recv(const void* body, unsigned short length, const airkiss_config_t* config); + +/* + * 设备要发送内网协议包时,调用本接口完成数据包打包 + * + * 参数说明 + * body:802.11 frame mac header(must contain at least first 24 bytes) + * length:total frame length + * config:AirKiss回调函数 + * + * 返回值 + * < 0:出错,请参考airkiss_lan_ret_t,通常是报文数据出错 + * >= 0:成功,请参考airkiss_lan_ret_t + */ +int airkiss_lan_pack(airkiss_lan_cmdid_t ak_lan_cmdid, void* appid, void* deviceid, void* _datain, unsigned short inlength, void* _dataout, unsigned short* outlength, const airkiss_config_t* config); + +#ifdef __cplusplus +} +#endif + +#endif /* AIRKISS_H_ */ diff --git a/beken_os/beken378/app/airkiss/airkiss_main.c b/beken_os/beken378/app/airkiss/airkiss_main.c new file mode 100755 index 0000000..a53ed4d --- /dev/null +++ b/beken_os/beken378/app/airkiss/airkiss_main.c @@ -0,0 +1,626 @@ +#include "include.h" +#include "arm_arch.h" +#include "target_util_pub.h" +#include "mem_pub.h" +#include "uart_pub.h" +#include "sys_rtos.h" +#include "rtos_pub.h" +#include "error.h" +#include "fake_clock_pub.h" +#include "wlan_ui_pub.h" +#include "lwip/sockets.h" +#include "airkiss.h" +#include "mac_ie.h" + +#define MAX_CHANNELS 14 +#define MAX_MAC 50 +#define AIRKISS_DEBUG 0 +#define AIRKISS_SWITCH_TIMER 50 // ms +#define AIRKISS_DOING_TIMER 20000 // 20s +#define MIN_SEL_CHAN_TIMER 1000 // ms +#define MAX_SEL_CHAN_TIMER 5000 // ms +#define AIRKISS_CONNECT_TIMER 60000 // Ms + +#define AIRKISS_RECV_BUFSIZE 24 // fctrl + duration + mac1+ mac2 + mac3 + seq +#define MIN_UDP_RANDOM_SEND 20 +#define MIN_VALID_DATACNT_INCHAN 4 +#define MIN_VALID_BCNCNT_INCHAN 1 + + +#if AIRKISS_DEBUG +#define AIRKISS_PRT os_printf +#define AIRKISS_WARN warning_prf +#define AIRKISS_FATAL fatal_prf +#else +#define AIRKISS_PRT null_prf +#define AIRKISS_WARN warning_prf +#define AIRKISS_FATAL fatal_prf +#endif + +typedef enum +{ + AIRKISS_SCAN_ALL_CHAN = 0, + AIRKISS_SCAN_SELECTED_CHAN +} airkiss_mode; + +typedef struct { + u8 bcn_cnt; + u8 data_cnt; + u16 channel; +} chan_param_t; + +typedef struct { + u8 frame_cnt; + u8 mac_crc; + u8 ap_sta; + u16 channel; +} mac_param_t; +typedef struct { + chan_param_t chan[MAX_CHANNELS]; + u8 cur_chan_idx; + u8 all_chan_nums; + u8 selected_chan_nums; + u8 mode; +} airkiss_channel_t; +typedef struct { + mac_param_t mac[MAX_MAC]; + u8 mac_cnt; +} airkiss_mac_t; + +static airkiss_context_t *ak_contex = NULL; +const airkiss_config_t ak_conf = { + (airkiss_memset_fn)&os_memset, + (airkiss_memcpy_fn)&os_memcpy, + (airkiss_memcmp_fn)&os_memcmp, + (airkiss_printf_fn)&AIRKISS_PRT +}; + +beken_timer_t ak_chan_timer; +beken_timer_t ak_doing_timer; +xTaskHandle ak_thread_handle = NULL; +beken_semaphore_t ak_semaphore = NULL; +beken_semaphore_t ak_connect_semaphore = NULL; +airkiss_channel_t g_chans; +airkiss_mac_t g_macs; + +volatile u8 airkiss_exit = 0; +int read_size = 0; +u8 *read_buf = NULL; + +extern void demo_sta_app_init(char *oob_ssid,char *connect_key); +extern void net_set_sta_ipup_callback(void *fn); + +static unsigned char calcrc_1byte(unsigned char abyte) +{ + unsigned char i,crc_1byte; + crc_1byte=0; + for(i = 0; i < 8; i++) + { + if(((crc_1byte^abyte)&0x01)) + { + crc_1byte^=0x18; + crc_1byte>>=1; + crc_1byte|=0x80; + } + else + { + crc_1byte>>=1; + } + abyte>>=1; + } + return crc_1byte; +} +static unsigned char calcrc_bytes(unsigned char *p,unsigned int num_of_bytes) +{ + unsigned char crc=0; + while(num_of_bytes--) + { + crc=calcrc_1byte(crc^*p++); + } + return crc; +} +void airkiss_count_usefull_packet(const unsigned char *frame, int size) +{ + u8 mac_crc = 0; + u8 *mac_ptr = 0; + u16 channel = 0; + uint32_t elmt_addr, var_part_addr, var_part_len; + int i; + struct mac_hdr *fmac_hdr = (struct mac_hdr *)frame; + struct bcn_frame const *frm = (struct bcn_frame const *)frame; + chan_param_t *cur_chan = &g_chans.chan[g_chans.cur_chan_idx]; + + mac_ptr = (u8*)&fmac_hdr->addr2; + mac_crc = calcrc_bytes(mac_ptr, 6); + if(!frame || !size) + return; + + if((MAC_FCTRL_BEACON == (fmac_hdr->fctl & MAC_FCTRL_TYPESUBTYPE_MASK)) || + (MAC_FCTRL_PROBERSP == (fmac_hdr->fctl & MAC_FCTRL_TYPESUBTYPE_MASK))) { + cur_chan->bcn_cnt++; + var_part_addr = CPU2HW(frm->variable); + var_part_len = size - MAC_BEACON_VARIABLE_PART_OFT; + elmt_addr = mac_ie_find(var_part_addr, var_part_len, MAC_ELTID_DS); + if (elmt_addr != 0) + { + channel = co_read8p(elmt_addr + MAC_DS_CHANNEL_OFT); + } + for(i = 0; i < g_macs.mac_cnt; i++) + { + if((mac_crc == g_macs.mac[i].mac_crc)) + { + if(channel != 0) + { + g_macs.mac[i].channel = channel; + } + break; + } + } + if(i == g_macs.mac_cnt) + { + g_macs.mac[i].mac_crc = mac_crc; + if(channel != 0) + { + g_macs.mac[i].channel = channel; + } + g_macs.mac_cnt++; + } + } else if(MAC_FCTRL_DATA_T == (fmac_hdr->fctl & MAC_FCTRL_TYPE_MASK)){ + cur_chan->data_cnt++; + } +} + +void airkiss_set_scan_all_channel(void) +{ + int i; + os_memset(&g_chans, 0, sizeof(airkiss_channel_t)); + os_memset(&g_macs, 0, sizeof(airkiss_mac_t)); + + g_chans.all_chan_nums = MAX_CHANNELS - 1; + for(i=0; i MAX_SEL_CHAN_TIMER) + return MAX_SEL_CHAN_TIMER; + + return timer_cnt; +} + +void airkiss_add_channel(u8 channel, u8 bcn_cnt, u8 data_cnt) +{ + int i; + + if(data_cnt < MIN_VALID_DATACNT_INCHAN) + return; + if(bcn_cnt < MIN_VALID_BCNCNT_INCHAN) + return; + + for(i=0; ibcn_cnt; + data_cnt = cur_chan->data_cnt; + channel = cur_chan->channel; + AIRKISS_PRT("finish scan ch:%02d, bcn:%03d, data:%03d\r\n", + channel, bcn_cnt, data_cnt); + AIRKISS_PRT("\r\n"); + + + switch(g_chans.mode) + { + case AIRKISS_SCAN_ALL_CHAN: + airkiss_add_channel(channel, bcn_cnt, data_cnt); + //airkiss_clear_channel_valid_data_count(); + + g_chans.cur_chan_idx++; + timer_cnt = AIRKISS_SWITCH_TIMER; + + if(g_chans.cur_chan_idx >= g_chans.all_chan_nums) { + g_chans.cur_chan_idx = 0; + if(g_chans.selected_chan_nums) { + g_chans.mode = AIRKISS_SCAN_SELECTED_CHAN; + data_cnt = g_chans.chan[g_chans.cur_chan_idx].data_cnt; + timer_cnt = airkiss_calc_time_for_selected_channel(data_cnt); + AIRKISS_WARN("change to selected scan mode\r\n"); + }else{ + airkiss_set_scan_all_channel(); + } + } + break; + + case AIRKISS_SCAN_SELECTED_CHAN: + g_chans.cur_chan_idx++; + data_cnt = g_chans.chan[g_chans.cur_chan_idx].data_cnt; + timer_cnt = airkiss_calc_time_for_selected_channel(data_cnt); + + if(g_chans.cur_chan_idx >= g_chans.selected_chan_nums) { + g_chans.cur_chan_idx = 0; + airkiss_set_scan_all_channel(); + g_chans.mode = AIRKISS_SCAN_ALL_CHAN; + timer_cnt = AIRKISS_SWITCH_TIMER; + } + break; + + default: + AIRKISS_WARN("unknow state:%d\r\n", g_chans.mode); + g_chans.mode = AIRKISS_SCAN_ALL_CHAN; + return; + break; + } + + channel = g_chans.chan[g_chans.cur_chan_idx].channel; + + AIRKISS_PRT("start scan ch:%02d/%02d, time_intval:%d\r\n", g_chans.cur_chan_idx, channel, timer_cnt); + bk_wlan_set_channel_sync(channel); + airkiss_change_channel(ak_contex); + + ret = rtos_change_period(&ak_chan_timer, timer_cnt); + ASSERT(kNoErr == ret); + +} + +void airkiss_doing_timeout_callback(void *data) +{ + int ret; + AIRKISS_WARN("airkiss_doing_timeout, restart channel switch timer\r\n"); + + // stop doing timer + ret = rtos_stop_timer(&ak_doing_timer); + ASSERT(kNoErr == ret); + + airkiss_change_channel(ak_contex); + + // restart scan process + airkiss_set_scan_all_channel(); + g_chans.cur_chan_idx = 0; // set channel 1 + bk_wlan_set_channel_sync(g_chans.chan[g_chans.cur_chan_idx].channel); + ret = rtos_change_period(&ak_chan_timer, AIRKISS_SWITCH_TIMER); + ASSERT(kNoErr == ret); +} + +void airkiss_monitor_callback(uint8_t*data, int len, hal_wifi_link_info_t *info) +{ + u16 fctl; + GLOBAL_INT_DECLARATION(); + + if(len < AIRKISS_RECV_BUFSIZE) + return; + + GLOBAL_INT_DISABLE(); + read_size = len; + read_buf = data; + GLOBAL_INT_RESTORE(); + + if(ak_semaphore) + rtos_set_semaphore(&ak_semaphore); +} + +int process_airkiss(const unsigned char *packet, int size) +{ + int ret, result, i; + u8 mac_crc = 0; + u8 *mac_ptr = 0; + struct mac_hdr *fmac_hdr = (struct mac_hdr *)packet; + mac_ptr = (u8*)&fmac_hdr->addr2; + mac_crc = calcrc_bytes(mac_ptr, 6); + ret = airkiss_recv(ak_contex, (void *)packet, size); + if(ret == AIRKISS_STATUS_CONTINUE) + { + } + else if(ret == AIRKISS_STATUS_CHANNEL_LOCKED) + { + result = rtos_stop_timer(&ak_chan_timer); + ASSERT(kNoErr == result); + for(i = 0; i < g_macs.mac_cnt; i++) + { + if((mac_crc == g_macs.mac[i].mac_crc)) + { + if(g_chans.chan[g_chans.cur_chan_idx].channel != g_macs.mac[i].channel) + { + g_chans.chan[g_chans.cur_chan_idx].channel = g_macs.mac[i].channel; + bk_wlan_set_channel_sync(g_chans.chan[g_chans.cur_chan_idx].channel); + } + } + } + AIRKISS_WARN("Lock channel in %d\r\n", g_chans.chan[g_chans.cur_chan_idx].channel); + + AIRKISS_WARN("start airkiss doing timer\r\n"); + result = rtos_start_timer(&ak_doing_timer); + ASSERT(kNoErr == result); + } + else if(ret == AIRKISS_STATUS_COMPLETE) + { + result = rtos_stop_timer(&ak_doing_timer); + ASSERT(kNoErr == result); + } + + return ret; +} + +void airkiss_connected_to_bssid(void) +{ + if(ak_connect_semaphore) + rtos_set_semaphore(&ak_connect_semaphore); +} + +void airkiss_start_udp_boardcast(u8 random_data) +{ + int err, i; + + int udp_broadcast_fd = -1; + struct sockaddr_in remote_skt; + + udp_broadcast_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if(udp_broadcast_fd == -1) + { + AIRKISS_WARN("Socket failed\r\n"); + return; + } + os_memset(&remote_skt, 0, sizeof(struct sockaddr_in)); + remote_skt.sin_family = AF_INET; + remote_skt.sin_addr.s_addr = INADDR_BROADCAST;//INADDR_ANY; + remote_skt.sin_port = htons(10000); + + i = MIN_UDP_RANDOM_SEND; + while(i--) + { + err = sendto(udp_broadcast_fd, &random_data, 1, 0, (struct sockaddr *)&remote_skt, sizeof(remote_skt)); + vTaskDelay(2); + if(err == -1) + { + AIRKISS_WARN("send udp boardcast failed\r\n"); + } + } + + close(udp_broadcast_fd); +} + +void airkiss_main( void* arg ) +{ + int result; + u32 con_time; + airkiss_result_t ak_result; + int airkiss_read_size = 0; + u8 *airkiss_read_buf = NULL; + + result = rtos_init_timer(&ak_chan_timer, + AIRKISS_SWITCH_TIMER, + airkiss_switch_channel_callback, + (void *)0); + ASSERT(kNoErr == result); + + result = rtos_init_timer(&ak_doing_timer, + AIRKISS_DOING_TIMER, + airkiss_doing_timeout_callback, + (void *)0); + ASSERT(kNoErr == result); + + ak_contex = (airkiss_context_t *)os_malloc(sizeof(airkiss_context_t)); + airkiss_read_buf = (u8*)os_malloc(sizeof(u8)*AIRKISS_RECV_BUFSIZE); + if((!ak_contex) || (!airkiss_read_buf)) + { + AIRKISS_FATAL("Airkiss no buffer\r\n"); + goto kiss_exit; + } + + result = airkiss_init(ak_contex, &ak_conf); + if(result != 0) + { + AIRKISS_FATAL("Airkiss init failed!!\r\n"); + goto kiss_exit; + } + + AIRKISS_WARN("Airkiss version: %s\r\n", airkiss_version()); + + // stop monitor mode + bk_wlan_stop_monitor(); + bk_wlan_register_monitor_cb(NULL); + + // start monitor + bk_wlan_register_monitor_cb(airkiss_monitor_callback); + bk_wlan_start_monitor(); + + // start from first channel + airkiss_set_scan_all_channel(); + g_chans.cur_chan_idx = 0; // set channel 1 + bk_wlan_set_channel_sync(g_chans.chan[g_chans.cur_chan_idx].channel); + + result = rtos_start_timer(&ak_chan_timer); + ASSERT(kNoErr == result); + + airkiss_exit = 0; + ak_result.ssid = NULL; + + for(;;) + { + GLOBAL_INT_DECLARATION(); + + // check exteral single to exit + if(airkiss_exit) + break; + + result = rtos_get_semaphore(&ak_semaphore, BEKEN_WAIT_FOREVER); + //ASSERT(kNoErr == result); + + GLOBAL_INT_DISABLE(); + os_memcpy(airkiss_read_buf, read_buf, AIRKISS_RECV_BUFSIZE); + airkiss_read_size = read_size; + GLOBAL_INT_RESTORE(); + + // count received packet + airkiss_count_usefull_packet(read_buf, airkiss_read_size); + + if(g_chans.mode == AIRKISS_SCAN_SELECTED_CHAN) + { + if(AIRKISS_STATUS_COMPLETE == process_airkiss(airkiss_read_buf, airkiss_read_size)) + { + AIRKISS_WARN("Airkiss completed.\r\n"); + airkiss_get_result(ak_contex, &ak_result); + + AIRKISS_WARN("Result:\r\n"); + AIRKISS_WARN("ssid:[%s]\r\n", ak_result.ssid); + AIRKISS_WARN("ssid_len:[%d]\r\n", ak_result.ssid_length); + AIRKISS_WARN("ssid_crc:[%x]\r\n", ak_result.reserved); + AIRKISS_WARN("key:[%s]\r\n", ak_result.pwd); + AIRKISS_WARN("key_len:[%d]\r\n", ak_result.pwd_length); + AIRKISS_WARN("random:[0x%02x]\r\n", ak_result.random); + break; + } + } + } + + // stop monitor mode + bk_wlan_stop_monitor(); + bk_wlan_register_monitor_cb(NULL); + + if(ak_result.ssid) + { + if(ak_connect_semaphore == NULL) { + result = rtos_init_semaphore(&ak_connect_semaphore, 1); + ASSERT(kNoErr == result); + } + + net_set_sta_ipup_callback((void*)airkiss_connected_to_bssid); + + // connect to this bssid + demo_sta_app_init(ak_result.ssid, ak_result.pwd); + + // wait for connect to bssid + con_time = AIRKISS_CONNECT_TIMER; + result = rtos_get_semaphore(&ak_connect_semaphore, con_time); + if(result == kNoErr) { + // start udp boardcast + if(airkiss_exit) + { + bk_wlan_stop(STATION); + } + else + { + airkiss_start_udp_boardcast(ak_result.random); + } + }else { + bk_wlan_stop(STATION); + AIRKISS_FATAL("airkiss connect to bssid timeout\r\n"); + } + + net_set_sta_ipup_callback(NULL); + + rtos_deinit_semaphore(&ak_connect_semaphore); + ak_connect_semaphore = NULL; + } + +kiss_exit: + AIRKISS_WARN("Airkiss exit.\r\n"); + + os_free(ak_contex); + ak_contex = NULL; + os_free(airkiss_read_buf); + + result = rtos_deinit_timer(&ak_chan_timer); + ASSERT(kNoErr == result); + result = rtos_deinit_timer(&ak_doing_timer); + ASSERT(kNoErr == result); + + rtos_deinit_semaphore(&ak_semaphore); + ak_semaphore = NULL; + + ak_thread_handle = NULL; + rtos_delete_thread(NULL); +} + +u32 airkiss_process(u8 start) +{ + int ret; + GLOBAL_INT_DECLARATION(); + + AIRKISS_FATAL("airkiss_process:%d\r\n", start); + + if(start) + { + // start airkiss + if(ak_semaphore == NULL) { + ret = rtos_init_semaphore(&ak_semaphore, 1); + ASSERT(kNoErr == ret); + } + + if(ak_thread_handle == NULL) { + ret = rtos_create_thread(&ak_thread_handle, + BEKEN_DEFAULT_WORKER_PRIORITY, + "airkiss", + (beken_thread_function_t)airkiss_main, + 2048, + (beken_thread_arg_t)0); + if (ret != kNoErr) + { + AIRKISS_FATAL("Error: airkiss_start_process: %d\r\n", ret); + goto init_err; + } + } + } + else + { + // stop airkiss + if(ak_thread_handle && ak_semaphore) + { + GLOBAL_INT_DISABLE(); + airkiss_exit = 1; + GLOBAL_INT_RESTORE(); + if(ak_connect_semaphore) + { + rtos_set_semaphore(&ak_connect_semaphore); + } + } + + } + + return kNoErr; + +init_err: + return kGeneralErr; + +} diff --git a/beken_os/beken378/app/airkiss/libairkiss.a b/beken_os/beken378/app/airkiss/libairkiss.a new file mode 100755 index 0000000..b8eb3ff Binary files /dev/null and b/beken_os/beken378/app/airkiss/libairkiss.a differ diff --git a/beken_os/beken378/app/app.h b/beken_os/beken378/app/app.h new file mode 100755 index 0000000..5adf86e --- /dev/null +++ b/beken_os/beken378/app/app.h @@ -0,0 +1,90 @@ +#ifndef _APP_H_ +#define _APP_H_ + +#pragma once + +#if (!CFG_SUPPORT_ALIOS) +#include "sys_rtos.h" +#endif +#include "rtos_pub.h" + +//#define APP_DEBUG + +#ifdef APP_DEBUG +#define APP_PRT os_printf +#define APP_WPRT warning_prf +#else +#define APP_PRT os_null_printf +#define APP_WPRT warning_prf +#endif + +enum +{ + BMSG_NULL_TYPE = 0, + BMSG_RX_TYPE = 1, + BMSG_TX_TYPE = 2, + BMSG_IOCTL_TYPE = 3, + BMSG_SKT_TX_TYPE = 4, + BMSG_MEDIA_TYPE = 5, + +#if CFG_USE_AP_PS + BMSG_TXING_TYPE = 6, +#endif + BMSG_STA_PS_TYPE = 7, + + BMSG_TX_RAW_TYPE = 8, + BMSG_TX_RAW_CB_TYPE = 9, + BMSG_TX_BCN_TYPE = 10, + +#if CFG_SUPPORT_ALIOS + BMSG_RX_LSIG = 11, /* phy receive 802.11 LSIG*/ +#endif +}; + +typedef struct bus_message +{ + uint32_t type; + uint32_t arg; + uint32_t len; + beken_semaphore_t sema; + + void *cb; + void *param; +} BUS_MSG_T; + +#define CORE_QITEM_COUNT (64) +#if CFG_SUPPORT_ALIOS +#define CORE_STACK_SIZE (4 * 1024) +#else +#define CORE_STACK_SIZE (2 * 1024) +#endif + +typedef struct _wifi_core_ +{ + uint32_t queue_item_count; + beken_queue_t io_queue; + +#if (CFG_SUPPORT_ALIOS || CFG_SUPPORT_RTT) + beken_thread_t handle; +#else + xTaskHandle handle; +#endif + uint32_t stack_size; +} WIFI_CORE_T; + +typedef struct _bus_msg_param_ +{ + uint8_t channel; + uint8_t ssid[33]; +} BUS_MSG_PARAM_T; + +int bmsg_tx_beacon_sender(BUS_MSG_PARAM_T *bcn_param); + +void app_start(void); +void app_pre_start(void); +int bmsg_is_empty(void); +void core_thread_uninit(void); + +#endif // _APP_H_ +// eof + diff --git a/beken_os/beken378/app/app_bk.c b/beken_os/beken378/app/app_bk.c new file mode 100755 index 0000000..127d5c8 --- /dev/null +++ b/beken_os/beken378/app/app_bk.c @@ -0,0 +1,916 @@ +/** + **************************************************************************************** + * + * @file app_bk.c + * + * + * Copyright (C) Beken Corp 2011-2016 + * + **************************************************************************************** + */ +#include "include.h" +#include "mem_pub.h" +#include "rwnx_config.h" +#include "app.h" + +#if (NX_POWERSAVE) +#include "ps.h" +#endif //(NX_POWERSAVE) + +#include "sa_ap.h" +#include "sa_station.h" +#include "main_none.h" +#include "sm.h" +#include "uart_pub.h" + +#include "rtos_pub.h" +#include "rtos_error.h" +#include "param_config.h" +#include "rxl_cntrl.h" +#include "lwip/pbuf.h" +#include "rw_pub.h" +#include "rw_msg_rx.h" +#include "hostapd_intf_pub.h" +#include "wlan_ui_pub.h" +#include "ps_debug_pub.h" +#include "power_save_pub.h" +#include "mcu_ps_pub.h" +#include "rw_msdu.h" +#include "txu_cntrl.h" + +#if CFG_SUPPORT_ALIOS +#include "ll.h" +#elif (!CFG_SUPPORT_RTT) +#include "wlan_cli_pub.h" +#endif + +#include "app_music_pub.h" +#include "bk7011_cal_pub.h" + +#if (CFG_SUPPORT_ALIOS || CFG_SUPPORT_RTT) +beken_thread_t init_thread_handle; +beken_thread_t app_thread_handle; +#else +xTaskHandle init_thread_handle; +xTaskHandle app_thread_handle; +#endif +#define INIT_STACK_SIZE 2000 +#define APP_STACK_SIZE 3072 + +beken_semaphore_t app_sema = NULL; +WIFI_CORE_T g_wifi_core = {0}; +volatile int32_t bmsg_rx_count = 0; + +extern void net_wlan_initial(void); +extern void wpas_thread_start(void); + +void bk_app_init(void) +{ +#if (!CFG_SUPPORT_RTT) + //net_wlan_initial(); +#endif + wpas_thread_start(); +} + +void app_set_sema(void) +{ + OSStatus ret; + ret = rtos_set_semaphore(&app_sema); + + (void)ret; +} + +static void kmsg_bk_thread_main( void *arg ) +{ + OSStatus ret; + + mr_kmsg_init(); + while(1) + { + ret = rtos_get_semaphore(&app_sema, BEKEN_WAIT_FOREVER); + ASSERT(kNoErr == ret); + + rwnx_recv_msg(); + ke_evt_none_core_scheduler(); + } +} + +static void init_thread_main( void *arg ) +{ + GLOBAL_INTERRUPT_START(); + + bk_app_init(); + os_printf("app_init finished\r\n"); + + rtos_delete_thread( NULL ); +} + +/** @brief When in dtim rf off mode,user can manual wakeup before dtim wakeup time. + * this function must be called in "core_thread" context + */ +int bmsg_ps_handler_rf_ps_mode_real_wakeup(void) +{ +#if CFG_USE_STA_PS + power_save_rf_dtim_manual_do_wakeup(); +#endif + return 0; +} + +void bmsg_rx_handler(BUS_MSG_T *msg) +{ + GLOBAL_INT_DECLARATION(); + + GLOBAL_INT_DISABLE(); + if(bmsg_rx_count > 0) + { + bmsg_rx_count -= 1; + } + GLOBAL_INT_RESTORE(); + + rxl_cntrl_evt((int)msg->arg); +} + +void bmsg_skt_tx_handler(BUS_MSG_T *msg) +{ + hapd_intf_ke_rx_handle(msg->arg); +} + +void bmsg_tx_handler(BUS_MSG_T *msg) +{ + struct pbuf *p = (struct pbuf *)msg->arg; + struct pbuf *q = p; + uint8_t vif_idx = (uint8_t)msg->len; + + if(p->next) + { + q = pbuf_coalesce(p, PBUF_RAW); + if(q == p) + { + // must be out of memory + goto tx_handler_exit; + } + } + + ps_set_data_prevent(); +#if CFG_USE_STA_PS + bmsg_ps_handler_rf_ps_mode_real_wakeup(); + bk_wlan_dtim_rf_ps_mode_do_wakeup(); +#endif + rwm_transfer(vif_idx, q->payload, q->len, 0, 0); +tx_handler_exit: + + pbuf_free(q); +} + +void bmsg_tx_raw_cb_handler(BUS_MSG_T *msg) +{ + rwm_raw_frame_with_cb((uint8_t *)msg->arg, msg->len, msg->cb, msg->param); +} + +int bmsg_tx_raw_cb_sender(uint8_t *buffer, int length, void *cb, void *param) +{ + OSStatus ret; + BUS_MSG_T msg; + + msg.type = BMSG_TX_RAW_CB_TYPE; + msg.arg = (uint32_t)buffer; + msg.len = length; + msg.sema = NULL; + msg.cb = cb; + msg.param = param; + + ret = rtos_push_to_queue(&g_wifi_core.io_queue, &msg, 1*SECONDS); + if(ret != kNoErr) + { + APP_PRT("bmsg_tx_sender failed\r\n"); + } + + return ret; +} + +static void tx_raw_data(uint8_t *pkt, int16_t len) +{ + MSDU_NODE_T *node; + UINT8 *content_ptr; + UINT32 queue_idx = AC_VI; + struct txdesc *txdesc_new; + struct umacdesc *umac; + + node = rwm_tx_node_alloc(len); + if (node == NULL) { + goto exit; + } + + rwm_tx_msdu_renew(pkt, len, node->msdu_ptr); + content_ptr = rwm_get_msdu_content_ptr(node); + + txdesc_new = tx_txdesc_prepare(queue_idx); + if(txdesc_new == NULL || TXDESC_STA_USED == txdesc_new->status) { + rwm_node_free(node); + goto exit; + } + + txdesc_new->status = TXDESC_STA_USED; + txdesc_new->host.flags = TXU_CNTRL_MGMT; + txdesc_new->host.msdu_node = (void *)node; + txdesc_new->host.orig_addr = (UINT32)node->msdu_ptr; + txdesc_new->host.packet_addr = (UINT32)content_ptr; + txdesc_new->host.packet_len = len; + txdesc_new->host.status_desc_addr = (UINT32)content_ptr; + txdesc_new->host.tid = 0xff; + + umac = &txdesc_new->umac; + umac->payl_len = len; + umac->head_len = 0; + umac->tail_len = 0; + umac->hdr_len_802_2 = 0; + + umac->buf_control = &txl_buffer_control_24G; + + txdesc_new->lmac.agg_desc = NULL; + txdesc_new->lmac.hw_desc->cfm.status = 0; + + ps_set_data_prevent(); +#if CFG_USE_STA_PS + bmsg_ps_handler_rf_ps_mode_real_wakeup(); + bk_wlan_dtim_rf_ps_mode_do_wakeup(); +#endif + + txl_cntrl_push(txdesc_new, queue_idx); + +exit: + os_free(pkt); +} + +static void tx_raw_beacon(int8_t chan, uint8_t *ssid, int8_t ssid_len) +{ + const int8_t *hdr = (const int8_t *)"\x80\x00\x00\x00""\xff\xff\xff\xff\xff\xff""\x00\x00\x00\x00\x00\x00""\x00\x00\x00\x00\x00\x00""\x00\x00"; + const int8_t *ie = (const int8_t *)"\x01\x08\x82\x84\x8b\x96\x0c\x12\x18\x24"/*supported rates*/\ + "\x03\x01\x06"/*DS*/\ + "\x05\x04\x00\x02\x00\x06"/*TIM*/\ + "\x2a\x01\x00"/*ERP*/\ + "\x32\x04\x30\x48\x60\x6c"/*Ext supported rates*/\ + "\x3b\x02\x51\x00"/*SOC*/\ + "\xdd\x18\x00\x50\xf2\x02\x01\x01\x00\x00\x03\xa4\x00\x00\x27\xa4\x00\x00\x42\x43\x5e\x00\x62\x32\x2f\x00";/*WMM*/ + uint8_t *ptr; + int32_t bcn_len, ie_len = 58; + struct bcn_frame *bcn = NULL; + + if ((NULL == ssid) || (0 == ssid_len)) + return; + + bcn_len = sizeof(struct bcn_frame) + (2 + ssid_len) + ie_len; + bcn_len -= 4; /*bcn_frame variable[]*/ + + bcn = (struct bcn_frame *)os_zalloc(bcn_len); + if (NULL != bcn) { + memcpy(&bcn->h, hdr, sizeof(bcn->h)); + wifi_get_mac_address((char *)&bcn->h.addr2, CONFIG_ROLE_AP); + memcpy(&bcn->h.addr3, &bcn->h.addr2, 6); + bcn->bcnint = 0x0064; + bcn->capa = 0x0421; + + ptr = bcn->variable; + *ptr++ = 0x00; + *ptr++ = ssid_len; + memcpy(ptr, ssid, ssid_len); + ptr += ssid_len; + memcpy(ptr, ie, ie_len); + bcn->variable[12+ssid_len+2] = chan; + tx_raw_data((uint8_t*)bcn, bcn_len); + } +} + +static void bmsg_tx_beacon_handler(BUS_MSG_T *msg) +{ + BUS_MSG_PARAM_T *bcn_param; + + bcn_param = (BUS_MSG_PARAM_T*)msg->arg; + if (bcn_param) { + tx_raw_beacon(bcn_param->channel, bcn_param->ssid, strlen((char*)bcn_param->ssid)); + os_free(bcn_param); + } +} + +static void bmsg_tx_raw_handler(BUS_MSG_T *msg) +{ + uint8_t *pkt = (uint8_t *)msg->arg; + uint16_t len = msg->len; + + tx_raw_data(pkt, len); +} + +#if CFG_SUPPORT_ALIOS +void bmsg_rx_lsig_handler(BUS_MSG_T *msg) +{ + lsig_input((msg->arg&0xFFFF0000)>>16, msg->arg&0xFF, msg->len); +} +#endif + +void bmsg_ioctl_handler(BUS_MSG_T *msg) +{ + ke_msg_send((void *)msg->arg); +} + +void bmsg_music_handler(BUS_MSG_T *msg) +{ +#if (CONFIG_APP_MP3PLAYER == 1) + media_msg_sender((void *)msg->arg); +#endif +} + +void bmsg_skt_tx_sender(void *arg) +{ + OSStatus ret; + BUS_MSG_T msg; + + msg.type = BMSG_SKT_TX_TYPE; + msg.arg = (uint32_t)arg; + msg.len = 0; + msg.sema = NULL; + + ret = rtos_push_to_queue(&g_wifi_core.io_queue, &msg, BEKEN_NO_WAIT); + if(kNoErr != ret) + { + os_printf("bmsg_rx_sender_failed\r\n"); + } +} + +extern void power_save_wait_timer_real_handler(void *data); +extern void power_save_wait_timer_start(void); + +void ps_msg_process(UINT8 ps_msg) +{ + switch(ps_msg) + { +#if CFG_USE_STA_PS + case PS_BMSG_IOCTL_RF_ENABLE: + power_save_dtim_enable(); + break; + + case PS_BMSG_IOCTL_RF_USER_WKUP: + bmsg_ps_handler_rf_ps_mode_real_wakeup(); + break; + + case PS_BMSG_IOCTL_RF_DISANABLE: + bmsg_ps_handler_rf_ps_mode_real_wakeup(); + power_save_dtim_disable(); + break; +#endif +#if CFG_USE_MCU_PS + case PS_BMSG_IOCTL_MCU_ENABLE: + mcu_ps_init(); + break; + + case PS_BMSG_IOCTL_MCU_DISANABLE: + mcu_ps_exit(); + break; +#endif +#if CFG_USE_STA_PS + case PS_BMSG_IOCTL_RF_TD_SET: + power_save_td_ck_timer_set(); + break; + + case PS_BMSG_IOCTL_RF_TD_HANDLER: + power_save_td_ck_timer_real_handler(); + break; + + case PS_BMSG_IOCTL_RF_KP_HANDLER: + power_save_keep_timer_real_handler(); + break; + + case PS_BMSG_IOCTL_RF_KP_SET: + power_save_keep_timer_set(); + break; + + case PS_BMSG_IOCTL_RF_KP_STOP: + power_save_keep_timer_stop(); + break; + + case PS_BMSG_IOCTL_WAIT_TM_HANDLER: + power_save_wait_timer_real_handler(NULL); + break; + + case PS_BMSG_IOCTL_WAIT_TM_SET: + power_save_wait_timer_start(); + break; + + case PS_BMSG_IOCTL_RF_PS_TIMER_INIT: + power_save_set_keep_timer_time(20); + break; + + case PS_BMSG_IOCTL_RF_PS_TIMER_DEINIT: + power_save_set_keep_timer_time(0); + break; +#endif + + default: + break; + } +} + +void bmsg_null_sender(void) +{ + OSStatus ret; + BUS_MSG_T msg; + + msg.type = BMSG_NULL_TYPE; + msg.arg = 0; + msg.len = 0; + msg.sema = NULL; + + if(!rtos_is_queue_empty(&g_wifi_core.io_queue)) + { + return; + } + + ret = rtos_push_to_queue(&g_wifi_core.io_queue, &msg, BEKEN_NO_WAIT); + if(kNoErr != ret) + { + os_printf("bmsg_null_sender_failed\r\n"); + } +} + +void bmsg_rx_sender(void *arg) +{ + OSStatus ret; + BUS_MSG_T msg; + GLOBAL_INT_DECLARATION(); + + msg.type = BMSG_RX_TYPE; + msg.arg = (uint32_t)arg; + msg.len = 0; + msg.sema = NULL; + + GLOBAL_INT_DISABLE(); + if(bmsg_rx_count >= 2) + { + GLOBAL_INT_RESTORE(); + return; + } + + bmsg_rx_count += 1; + GLOBAL_INT_RESTORE(); + + ret = rtos_push_to_queue(&g_wifi_core.io_queue, &msg, BEKEN_NO_WAIT); + if(kNoErr != ret) + { + APP_PRT("bmsg_rx_sender_failed\r\n"); + } +} + +int bmsg_tx_sender(struct pbuf *p, uint32_t vif_idx) +{ + OSStatus ret; + BUS_MSG_T msg; + + msg.type = BMSG_TX_TYPE; + msg.arg = (uint32_t)p; + msg.len = vif_idx; + msg.sema = NULL; + + pbuf_ref(p); + ret = rtos_push_to_queue(&g_wifi_core.io_queue, &msg, 1 * SECONDS); + if(kNoErr != ret) + { + APP_PRT("bmsg_tx_sender failed\r\n"); + pbuf_free(p); + } + + return ret; +} + +int bmsg_tx_raw_sender(uint8_t *payload, uint16_t length) +{ + OSStatus ret; + BUS_MSG_T msg; + + msg.type = BMSG_TX_RAW_TYPE; + msg.arg = (uint32_t)payload; + msg.len = length; + msg.sema = NULL; + + ret = rtos_push_to_queue(&g_wifi_core.io_queue, &msg, 1*SECONDS); + + if(ret != kNoErr) + { + APP_PRT("bmsg_tx_sender failed\r\n"); + os_free(payload); + } + + return ret; +} + +int bmsg_tx_beacon_sender(BUS_MSG_PARAM_T *bcn_param) +{ + OSStatus ret; + BUS_MSG_T msg; + + msg.type = BMSG_TX_BCN_TYPE; + msg.arg = (uint32_t)bcn_param; + msg.len = sizeof(BUS_MSG_PARAM_T); + msg.sema = NULL; + + ret = rtos_push_to_queue(&g_wifi_core.io_queue, &msg, 1*SECONDS); + + if(ret != kNoErr) + { + APP_PRT("bmsg_tx_bcn_sender failed\r\n"); + os_free(bcn_param); + } + + return ret; +} + +#if CFG_SUPPORT_ALIOS +void bmsg_rx_lsig(uint16_t len, uint8_t rssi) +{ + BUS_MSG_T msg; + + msg.type = BMSG_RX_LSIG; + msg.arg = (uint32_t)((len << 16) | rssi); + msg.len = rtos_get_time(); + msg.sema = NULL; + rtos_push_to_queue(&g_wifi_core.io_queue, &msg, BEKEN_NO_WAIT); +} +#endif + +int bmsg_ioctl_sender(void *arg) +{ + OSStatus ret; + BUS_MSG_T msg; + + msg.type = BMSG_IOCTL_TYPE; + msg.arg = (uint32_t)arg; + msg.len = 0; + msg.sema = NULL; + + ret = rtos_push_to_queue(&g_wifi_core.io_queue, &msg, BEKEN_NO_WAIT); + if(kNoErr != ret) + { + APP_PRT("bmsg_ioctl_sender_failed\r\n"); + } + else + { + APP_PRT("bmsg_ioctl_sender\r\n"); + } + + return ret; +} + +void bmsg_music_sender(void *arg) +{ + OSStatus ret; + BUS_MSG_T msg; + + msg.type = BMSG_MEDIA_TYPE; + msg.arg = (uint32_t)arg; + msg.len = 0; + msg.sema = NULL; + + ret = rtos_push_to_queue(&g_wifi_core.io_queue, &msg, BEKEN_NO_WAIT); + if(kNoErr != ret) + { + APP_PRT("bmsg_media_sender_failed\r\n"); + } +} + +#if CFG_USE_AP_PS +void bmsg_txing_sender(uint8_t sta_idx) +{ + OSStatus ret; + BUS_MSG_T msg; + + msg.type = BMSG_TXING_TYPE; + msg.arg = (uint32_t)sta_idx; + msg.len = 0; + msg.sema = NULL; + + ret = rtos_push_to_queue(&g_wifi_core.io_queue, &msg, BEKEN_NO_WAIT); + if(kNoErr != ret) + { + APP_PRT("bmsg_txing_sender failed\r\n"); + } +} + +void bmsg_txing_handler(BUS_MSG_T *msg) +{ + OSStatus ret; + UINT8 sta_idx = (UINT8)msg->arg; + + rwm_msdu_send_txing_node(sta_idx); +} +#endif + +void bmsg_ps_sender(uint8_t arg) +{ + OSStatus ret; + BUS_MSG_T msg; + if(g_wifi_core.io_queue) + { + msg.type = BMSG_STA_PS_TYPE; + msg.arg = (uint32_t)arg; + msg.len = 0; + msg.sema = NULL; + + ret = rtos_push_to_queue(&g_wifi_core.io_queue, &msg, BEKEN_NO_WAIT); + if(kNoErr != ret) + { + os_printf("bmsg_ps_sender failed\r\n"); + } + } + else + { + os_printf("g_wifi_core.io_queue null\r\n"); + } +} +#if CFG_USE_STA_PS + +void bmsg_ps_handler(BUS_MSG_T *msg) +{ + UINT8 arg; + + arg = (UINT8)msg->arg; + ps_msg_process(arg); +} +#endif +static void core_thread_main( void *arg ) +{ + OSStatus ret; + BUS_MSG_T msg; + uint8_t ke_skip = 0; + uint8_t ps_flag = 0; + + while(1) + { + ret = rtos_pop_from_queue(&g_wifi_core.io_queue, &msg, BEKEN_WAIT_FOREVER); + if(kNoErr == ret) + { + switch(msg.type) + { +#if CFG_USE_STA_PS + case BMSG_STA_PS_TYPE: + if(msg.arg == PS_BMSG_IOCTL_RF_DISANABLE) + { + bmsg_ps_handler(&msg); + } + else + { + ps_flag = 1; + } + break; +#endif + + case BMSG_RX_TYPE: + APP_PRT("bmsg_rx_handler\r\n"); + bmsg_rx_handler(&msg); + break; + + case BMSG_TX_TYPE: + APP_PRT("bmsg_tx_handler\r\n"); + bmsg_tx_handler(&msg); + break; + + case BMSG_SKT_TX_TYPE: + APP_PRT("bmsg_skt_tx_handler\r\n"); + bmsg_skt_tx_handler(&msg); + break; + + case BMSG_IOCTL_TYPE: + APP_PRT("bmsg_ioctl_handler\r\n"); + bmsg_ioctl_handler(&msg); + break; + case BMSG_MEDIA_TYPE: + ke_skip = 1; + bmsg_music_handler(&msg); + break; + +#if CFG_USE_AP_PS + case BMSG_TXING_TYPE: + bmsg_txing_handler(&msg); + break; +#endif + + case BMSG_TX_RAW_TYPE: + bmsg_tx_raw_handler(&msg); + break; + + case BMSG_TX_RAW_CB_TYPE: + bmsg_tx_raw_cb_handler(&msg); + break; + + case BMSG_TX_BCN_TYPE: + bmsg_tx_beacon_handler(&msg); + break; + +#if CFG_SUPPORT_ALIOS + case BMSG_RX_LSIG: + bmsg_rx_lsig_handler(&msg); + break; + +#endif + default: + APP_PRT("unknown_msg\r\n"); + break; + } + + if (msg.sema != NULL) + { + rtos_set_semaphore(&msg.sema); + } + if(!ke_skip) + ke_evt_core_scheduler(); + else + ke_skip = 0; + } + +#if CFG_USE_STA_PS + if(ps_flag == 1) + { + bmsg_ps_handler(&msg); + ps_flag = 0; + } + power_save_rf_sleep_check(); +#endif + + } +} + +beken_thread_t core_thread_handle; + +void core_thread_init(void) +{ + OSStatus ret; + + g_wifi_core.queue_item_count = CORE_QITEM_COUNT; + g_wifi_core.stack_size = CORE_STACK_SIZE; + + ret = rtos_init_queue(&g_wifi_core.io_queue, + "core_queue", + sizeof(BUS_MSG_T), + g_wifi_core.queue_item_count); + if (kNoErr != ret) + { + os_printf("Create io queue failed\r\n"); + goto fail; + } + + ret = rtos_create_thread(&g_wifi_core.handle, + THD_CORE_PRIORITY, + "core_thread", + (beken_thread_function_t)core_thread_main, + (unsigned short)g_wifi_core.stack_size, + (beken_thread_arg_t)0); + if (kNoErr != ret) + { + os_printf("Create core thread failed\r\n"); + goto fail; + } + + core_thread_handle = g_wifi_core.handle; + return; + +fail: + core_thread_uninit(); + + return; +} + +void core_thread_uninit(void) +{ + if(g_wifi_core.handle) + { + rtos_delete_thread(&g_wifi_core.handle); + g_wifi_core.handle = 0; + } + + if(g_wifi_core.io_queue) + { + rtos_deinit_queue(&g_wifi_core.io_queue); + g_wifi_core.io_queue = 0; + } + + g_wifi_core.queue_item_count = 0; + g_wifi_core.stack_size = 0; +} + +#if (!CFG_SUPPORT_ALIOS && !CFG_SUPPORT_RTT) +extern void user_main(void); +void __attribute__((weak)) user_main(void) +{ + +} + +static void init_app_thread( void *arg ) +{ + user_main(); + + rtos_delete_thread( NULL ); +} +#endif + +void app_pre_start(void) +{ + OSStatus ret; + +#if CFG_SUPPORT_ALIOS + ret = rtos_init_semaphore(&app_sema, 0); +#else + ret = rtos_init_semaphore(&app_sema, 1); +#endif + ASSERT(kNoErr == ret); + + ret = rtos_create_thread(&app_thread_handle, + THD_APPLICATION_PRIORITY, + "kmsgbk", + (beken_thread_function_t)kmsg_bk_thread_main, + (unsigned short)APP_STACK_SIZE, + (beken_thread_arg_t)0); + ASSERT(kNoErr == ret); + + ret = rtos_create_thread(&init_thread_handle, + THD_INIT_PRIORITY, + "init_thread", + (beken_thread_function_t)init_thread_main, + (unsigned short)INIT_STACK_SIZE, + (beken_thread_arg_t)0); + ASSERT(kNoErr == ret); + + core_thread_init(); + +#if (CONFIG_APP_MP3PLAYER == 1) + key_init(); + media_thread_init(); +#endif +} + +#if CFG_USE_TUYA_CCA_TEST +beken_timer_t test_timer; +static void test_timer_handler(void *data) +{ + LinkStatusTypeDef linkStatus; + + bk_wlan_get_link_status(&linkStatus); + + os_printf("rssi:%d\r\n", linkStatus.wifi_strength); +} +#endif + +void app_start(void) +{ + app_pre_start(); + +#if CFG_UART2_CLI + cli_init(); +#endif + +#if defined(SUPPORT_MIDEA_BLE) + if(!get_ate_mode_state()) + { + bk_wlan_start_ble(); + } +#endif + +#if CFG_USE_TUYA_CCA_TEST + rtos_init_timer(&test_timer, + 1000, + test_timer_handler, + (void *)0); + + rtos_start_timer(&test_timer); +#endif + +#if (0)//(CFG_SUPPORT_BLE) + extern void ble_entry(void); + ble_entry(); +#endif +} + +void user_main_entry(void) +{ + extern void tuya_app_main(void); + tuya_app_main(); + /* + rtos_create_thread(NULL, + THD_INIT_PRIORITY, + "app", + (beken_thread_function_t)init_app_thread, + APP_STACK_SIZE, + (beken_thread_arg_t)0); + */ +} + +int bmsg_is_empty(void) +{ + if(!rtos_is_queue_empty(&g_wifi_core.io_queue)) + { + return 0; + } + else + { + return 1; + } +} + +// eof + diff --git a/beken_os/beken378/app/ate_app.c b/beken_os/beken378/app/ate_app.c new file mode 100755 index 0000000..2ee9bb1 --- /dev/null +++ b/beken_os/beken378/app/ate_app.c @@ -0,0 +1,78 @@ +#include "ate_app.h" +#include "include.h" + +#if ATE_APP_FUN + +#if (!CFG_SUPPORT_ALIOS) +#include "app.h" +#include "wlan_cli_pub.h" +#endif + +char ate_mode_state = 0; + +void ate_gpio_init(void) +{ + uint32_t param; + + param = GPIO_CFG_PARAM(ATE_GPIO_ID, GMODE_INPUT_PULLUP); + gpio_ctrl( CMD_GPIO_CFG, ¶m); +} + +uint32_t ate_mode_check(void) +{ + uint32_t ret; + uint32_t param; + + param = ATE_GPIO_ID; + ret = gpio_ctrl( CMD_GPIO_INPUT, ¶m); + + return (0 == ret); +} + +void ate_app_init(void) +{ + uint32_t mode = 0; + ate_gpio_init(); + + mode = ate_mode_check(); + if(mode) + { + ate_mode_state = (char)1; + } + else + { + ate_mode_state = (char)0; + } +} + +uint32_t get_ate_mode_state(void) +{ + if(ate_mode_state != (char)0) + return 1; + return 0; +} + +#if (!CFG_SUPPORT_ALIOS) +void ate_start(void) +{ + app_pre_start(); + + cli_init(); + +#if CFG_SUPPORT_BLE + extern void ble_entry(void); + ble_entry(); +#endif + + ATE_PRT("ate_start\r\n"); +} +#endif + +#else +uint32_t get_ate_mode_state(void) +{ + return 0; +} + +#endif /*ATE_APP_FUN */ +// eof diff --git a/beken_os/beken378/app/ate_app.h b/beken_os/beken378/app/ate_app.h new file mode 100755 index 0000000..dc4ac48 --- /dev/null +++ b/beken_os/beken378/app/ate_app.h @@ -0,0 +1,33 @@ +#ifndef _ATE_APP_H_ +#define _ATE_APP_H_ + +#include "sys_config.h" + +#define ATE_APP_FUN CFG_ENABLE_ATE_FEATURE + +#if ATE_APP_FUN +#include "gpio_pub.h" + +#include "uart_pub.h" +#define ATE_DEBUG +#ifdef ATE_DEBUG +#define ATE_PRT os_printf +#define ATE_WARN warning_prf +#define ATE_FATAL fatal_prf +#else +#define ATE_PRT null_prf +#define ATE_WARN null_prf +#define ATE_FATAL null_prf +#endif + +#define ATE_GPIO_ID GPIO21 /* jtag tms pin*/ + +extern void ate_gpio_init(void); +extern uint32_t ate_mode_check(void); +extern void ate_app_init(void); +extern uint32_t get_ate_mode_state(void); +extern void ate_start(void); +#endif /*ATE_APP_FUN */ +#endif // _ATE_APP_H_ +// eof + diff --git a/beken_os/beken378/app/config/param_config.c b/beken_os/beken378/app/config/param_config.c new file mode 100755 index 0000000..fb7c5d1 --- /dev/null +++ b/beken_os/beken378/app/config/param_config.c @@ -0,0 +1,286 @@ +/** + **************************************************************************************** + * + * @file arch_config.c + * + * + * Copyright (C) Beken Corp 2011-2016 + * + **************************************************************************************** + */ +#include "include.h" +#include "mem_pub.h" +#include "drv_model_pub.h" +#include "flash_pub.h" +#include "mac.h" +#include "param_config.h" +#include "uart_pub.h" +#include "bk7011_cal_pub.h" +#include "rw_pub.h" +#include "net_param_pub.h" + +general_param_t *g_wlan_general_param = NULL; +ap_param_t *g_ap_param_ptr = NULL; +sta_param_t *g_sta_param_ptr = NULL; + +uint32_t cfg_param_init(void) +{ + if(NULL == g_wlan_general_param) + { + g_wlan_general_param = (general_param_t *)os_zalloc(sizeof(general_param_t)); + ASSERT(g_wlan_general_param); + } + + if(NULL == g_ap_param_ptr) + { + g_ap_param_ptr = (ap_param_t *)os_zalloc(sizeof(ap_param_t)); + ASSERT(g_ap_param_ptr); + } + + if(NULL == g_sta_param_ptr) + { + g_sta_param_ptr = (sta_param_t *)os_zalloc(sizeof(sta_param_t)); + ASSERT(g_sta_param_ptr); + } + + return 0; +} + +#define MAC_EFUSE 0 +#define MAC_ITEM 1 +#define MAC_RF_OTP_FLASH 2 + +#define WIFI_MAC_POS MAC_RF_OTP_FLASH +#if ((CFG_SOC_NAME == SOC_BK7231) && (WIFI_MAC_POS == MAC_EFUSE)) +#error "BK7231 not support efuse!" +#endif + +#define DEFAULT_MAC_ADDR "\xC8\x47\x8C\x00\x00\x00" +uint8_t system_mac[6] = DEFAULT_MAC_ADDR; + +#if CFG_SUPPORT_RTT +uint32_t prandom_get(void); +static void random_mac_address(u8 *mac) +{ + int i = 0; + int val = 0; + + os_memcpy(mac, DEFAULT_MAC_ADDR, 6); + val = prandom_get(); + + for (i = 0; i < 3; i++) + { + mac[i + 3] = (val >> i * 2) & 0xff; + } + + os_printf("mac:"); + for (i = 0; i < 6; i++) + os_printf("%02X ", mac[i]); + os_printf("\n"); +} +#endif + +void cfg_load_mac(u8 *mac) +{ +#if (WIFI_MAC_POS == MAC_EFUSE) + if(!wifi_get_mac_address_from_efuse((UINT8 *)mac)) +#elif (WIFI_MAC_POS == MAC_RF_OTP_FLASH) + if(!manual_cal_get_macaddr_from_flash((UINT8 *)mac)) +#elif (WIFI_MAC_POS == MAC_ITEM) + if(!get_info_item(WIFI_MAC_ITEM, (UINT8 *)mac, NULL, NULL)) +#endif + { +#if CFG_SUPPORT_RTT + random_mac_address(mac); +#else + os_memcpy(mac, DEFAULT_MAC_ADDR, 6); +#endif + if(mac[0] & 0x01) + { + fatal_prf("cfg_load_mac failed, MAC[0]&0x1 == 1\r\n"); + ASSERT(0); + } + +#if (WIFI_MAC_POS == MAC_EFUSE) + //wifi_set_mac_address_to_efuse((UINT8 *)mac); +#elif (WIFI_MAC_POS == MAC_RF_OTP_FLASH) + manual_cal_write_macaddr_to_flash((UINT8 *)mac); +#elif (WIFI_MAC_POS == MAC_ITEM) + save_info_item(WIFI_MAC_ITEM, (UINT8 *)mac, NULL, NULL); +#endif + } +} + +uint32_t wifi_get_rescan_cnt(void) +{ + uint32_t cnt = 0; + + if(g_sta_param_ptr) + { + cnt = g_sta_param_ptr->retry_cnt; + } + + return cnt; +} + +void wifi_get_mac_address(char *mac, u8 type) +{ + cfg_load_mac(system_mac); + + if(type == CONFIG_ROLE_AP) + { + u8 mac_mask = (0xff & (NX_VIRT_DEV_MAX - 1)); + u8 mac_low; + + os_memcpy(mac, system_mac, 6); + mac_low = mac[5]; + + // if NX_VIRT_DEV_MAX == 4. + // if support AP+STA, mac addr should be equal with each other in byte0-4 & byte5[7:2], + // byte5[1:0] can be different + // ie: mac[5]= 0xf7, so mac[5] can be 0xf4, f5, f6. here wre chose 0xf4 + mac[5] &= ~mac_mask; + mac_low = ((mac_low & mac_mask) ^ mac_mask ); + mac[5] |= mac_low; + } + else if(type == CONFIG_ROLE_STA) + { + os_memcpy(mac, system_mac, 6); + } +} + +uint8_t wifi_get_vif_index_by_mac(char *mac) +{ + return rwm_mgmt_vif_mac2idx(mac); +} + +int wifi_set_mac_address(char *mac) +{ + int ret = 0; + +#if (WIFI_MAC_POS == MAC_EFUSE) + //wifi_set_mac_address_to_efuse((UINT8 *)mac); +#elif (WIFI_MAC_POS == MAC_RF_OTP_FLASH) + ret = manual_cal_write_macaddr_to_flash((UINT8 *)mac); +#elif (WIFI_MAC_POS == MAC_ITEM) + ret = save_info_item(WIFI_MAC_ITEM, (UINT8 *)mac, NULL, NULL); +#endif + + if(1 == ret) + { + os_memcpy(system_mac, mac, 6); + } + + return ret; +} + +#if (CFG_SOC_NAME != SOC_BK7231) +#include "sys_ctrl_pub.h" +int wifi_set_mac_address_to_efuse(UINT8 *mac) +{ + EFUSE_OPER_ST efuse; + int i = 0, ret; + + if(!mac) + return 0; + + for(i=0; i EFUSE_CTRL_ADDR) { + os_printf("efuse addr:0x%x out of range(0-0x1F)\r\n", addr); + return 0; + } + + efuse.addr = addr; + efuse.data = data; + + ret = sddev_control(SCTRL_DEV_NAME, CMD_EFUSE_WRITE_BYTE, &efuse); + if(ret != 0) { + os_printf("efuse write failed, aready write this addr 0x%x\r\n", addr); + return 0; + } + + return 1; +} + +UINT8 wifi_read_efuse(UINT8 addr) +{ + EFUSE_OPER_ST efuse; + int ret; + + if(addr > EFUSE_CTRL_ADDR) { + os_printf("efuse addr:0x%x out of range(0-0x1F)\r\n", addr); + return 0; + } + + efuse.addr = addr; + efuse.data = 0; + + ret = sddev_control(SCTRL_DEV_NAME, CMD_EFUSE_READ_BYTE, &efuse); + if(ret == 0) { + return efuse.data; + } else { + os_printf("efuse get MAC -1\r\n"); + return 0xff; + } +} +#endif // #if (CFG_SOC_NAME != SOC_BK7231) + + diff --git a/beken_os/beken378/app/config/param_config.h b/beken_os/beken378/app/config/param_config.h new file mode 100755 index 0000000..31029d0 --- /dev/null +++ b/beken_os/beken378/app/config/param_config.h @@ -0,0 +1,79 @@ +#ifndef _ARCH_CONFIG_H_ +#define _ARCH_CONFIG_H_ + +#include "mac.h" + +#define PARAM_CFG_DEBUG + +#ifdef PARAM_CFG_DEBUG +#define PARAM_CFG_PRT os_printf +#define PARAM_CFG_WARN warning_prf +#define PARAM_CFG_FATAL fatal_prf +#else +#define PARAM_CFG_PRT null_prf +#define PARAM_CFG_WARN null_prf +#define PARAM_CFG_FATAL null_prf +#endif + +#define CONFIG_ROLE_NULL 0 +#define CONFIG_ROLE_AP 1 +#define CONFIG_ROLE_STA 2 +#define CONFIG_ROLE_COEXIST 3 + +#define DEFAULT_CHANNEL_AP 11 + +typedef struct fast_connect_param +{ + uint8_t bssid[6]; + uint8_t chann; +} fast_connect_param_t; + +typedef struct general_param +{ + uint8_t role; + uint8_t dhcp_enable; + uint32_t ip_addr; + uint32_t ip_mask; + uint32_t ip_gw; +} general_param_t; + +typedef struct ap_param +{ + struct mac_addr bssid; + struct mac_ssid ssid; + uint8_t chann; + uint8_t cipher_suite; + uint8_t key[65]; + uint8_t key_len; +} ap_param_t; + +#define MAX_STA_RETRY_COUNT 1 + +typedef struct sta_param +{ + struct mac_addr own_mac; + struct mac_ssid ssid; + uint8_t cipher_suite; + uint8_t key[65]; + uint8_t key_len; + uint8_t orig_key[65]; + uint8_t orig_key_len; + uint8_t fast_connect_set; + uint8_t retry_cnt; + fast_connect_param_t fast_connect; +} sta_param_t; + +extern general_param_t *g_wlan_general_param; +extern ap_param_t *g_ap_param_ptr; +extern sta_param_t *g_sta_param_ptr; +extern uint8_t system_mac[6]; + +void cfg_load_mac(u8 *mac); +uint32_t cfg_param_init(void); +void wifi_get_mac_address(char *mac, u8 type); +int wifi_set_mac_address(char *mac); +int wifi_set_mac_address_to_efuse(UINT8 *mac); +int wifi_get_mac_address_from_efuse(UINT8 *mac); +int wifi_write_efuse(UINT8 addr, UINT8 data); +UINT8 wifi_read_efuse(UINT8 addr); +#endif diff --git a/beken_os/beken378/app/config/sys_config.h b/beken_os/beken378/app/config/sys_config.h new file mode 100755 index 0000000..8edbd45 --- /dev/null +++ b/beken_os/beken378/app/config/sys_config.h @@ -0,0 +1,225 @@ +#ifndef _SYS_CONFIG_H_ +#define _SYS_CONFIG_H_ + + +#define CFG_SUPPORT_BOOTLOADER 1 + +/*SUMMARY: macro--1: OPEN; --0:CLOSE*/ + +/* uart2 for debug, and generally, uart1 is used for communication. + what is more, uart1 maybe is not bound out*/ +#define CFG_USE_UART1 1 +#define CFG_UART2_CLI 0 +#define CFG_JTAG_ENABLE 0 //edit tuya_cheyisong 2020-2-28 +#define OSMALLOC_STATISTICAL 0 + +/*section 0-----app macro config-----*/ +#define CFG_IEEE80211N 1 + +/*section 1-----OS macro config-----*/ +#define CFG_OS_FREERTOS 1 + +#if CFG_OS_FREERTOS +#define THD_APPLICATION_PRIORITY 3 +#define THD_CORE_PRIORITY 2 +#define THD_UMP3_PRIORITY 4 +#define THD_UBG_PRIORITY 5 +#define THD_LWIP_PRIORITY 4 +#define THD_INIT_PRIORITY 4 +#define THD_RECONNECT_PRIORITY 4 +#define THD_MEDIA_PRIORITY 4 +#define THD_WPAS_PRIORITY 5 +#define THD_EXTENDED_APP_PRIORITY (5 + 1) //change extended priority lower for light-firmware +#define THD_HOSTAPD_PRIORITY 5 +#define THDD_KEY_SCAN_PRIORITY 7 +#endif // CFG_OS_FREERTOS + +/*section 2-----function macro config-----*/ +#define CFG_TX_EVM_TEST 1 +#define CFG_RX_SENSITIVITY_TEST 1 +#define CFG_ROLE_LAUNCH 1 +#define CFG_USE_WPA_29 0 +#define CFG_WPA_CTRL_IFACE 0 +#define CFG_WLAN_FAST_CONNECT 1 +/* PMF */ +#define CFG_IEEE80211W 0 +#if CFG_WPA_CTRL_IFACE +#undef CFG_ROLE_LAUNCH +#define CFG_ROLE_LAUNCH 0 +#endif +#define CFG_WPA3 1 +#if CFG_WPA3 +/* disable rl, enable ctrl iface, enable wpa29, pmf, sme */ +#undef CFG_ROLE_LAUNCH +#define CFG_ROLE_LAUNCH 0 +#undef CFG_WPA_CTRL_IFACE +#define CFG_WPA_CTRL_IFACE 1 +#undef CFG_USE_WPA_29 +#define CFG_USE_WPA_29 1 +#undef CFG_IEEE80211W +#define CFG_IEEE80211W 1 +//#define CFG_SME 1 +#define CFG_WPA_CRYPTO_MBEDTLS 1 +#define CFG_WRAP_LIBC 1 +#endif /* CFG_WPA3 */ +//#define CFG_MESH 0 +#define CFG_WFA_CERT 0 +#define CFG_ENABLE_BUTTON 0 +#define CFG_UDISK_MP3 0 + +#define ENC_METHOD_NULL 1 +#define ENC_METHOD_XOR 2 +#define ENC_METHOD_AES 3 + +#define FAST_CONNECT_INFO_ENC_METHOD ENC_METHOD_XOR + +/*section 3-----driver macro config-----*/ +#define CFG_MAC_PHY_BAPASS 1 + +#define CFG_SDIO 0 +#define CFG_SDIO_TRANS 0 +#define CFG_REAL_SDIO 0 +#if CFG_REAL_SDIO +#define FOR_SDIO_BLK_512 0 +#endif + +#define CFG_MSDU_RESV_HEAD_LEN 96 +#define CFG_MSDU_RESV_TAIL_LEN 16 + +#define CFG_USE_USB_HOST 0 + +#define CFG_USB 0 +#if CFG_USB +#define CFG_SUPPORT_MSD 1 +#define CFG_SUPPORT_HID 0 +#define CFG_SUPPORT_CCD 0 +#define CFG_SUPPORT_UVC 0 +#endif + +/*section 4-----DEBUG macro config-----*/ +#define CFG_UART_DEBUG 0 +#define CFG_UART_DEBUG_COMMAND_LINE 1 +#define CFG_SUPPORT_BKREG 0 +#define CFG_ENABLE_WPA_LOG 0 +#define CFG_IPERF_TEST 0 +#define CFG_ENABLE_DEMO_TEST 0 + +/*section 5-----PRODUCT macro config-----*/ +#define CFG_RELEASE_FIRMWARE 0 + +/*section 6-----for platform*/ +#define SOC_PLATFORM 1 +#define FPGA_PLATFORM 0 +#define CFG_RUNNING_PLATFORM SOC_PLATFORM + +#define SOC_BK7231 1 +#define SOC_BK7231U 2 +#define SOC_BK7221U 3 +#define SOC_BK7231N 5 +#define CFG_SOC_NAME SOC_BK7231N + +/*section 7-----calibration*/ +#if (CFG_RUNNING_PLATFORM == FPGA_PLATFORM) +#define CFG_SUPPORT_CALIBRATION 0 +#define CFG_SUPPORT_MANUAL_CALI 0 +#else +#define CFG_SUPPORT_CALIBRATION 1 +#define CFG_SUPPORT_MANUAL_CALI 1 +//tpc rf pa map power for bk7231u +#define CFG_SUPPORT_TPC_PA_MAP 1 +#endif + +/*section 8-----for netstack*/ +#define CFG_USE_LWIP_NETSTACK 1 + +/*section 9-----for DHCP servicers and client*/ +#define CFG_USE_DHCP 1 + +/*section 10-----patch*/ +#define CFG_BK7221_MDM_WATCHDOG_PATCH 0 + +/*section 11-----temperature detect*/ +#define CFG_USE_TEMPERATURE_DETECT 1 + +/*section 12-----for SPIDMA interface*/ +#define CFG_USE_SPIDMA 0 +#define CFG_USE_CAMERA_INTF 0 + +/*section 13-----for GENERRAL DMA */ +#define CFG_GENERAL_DMA 1 + +/*section 14-----for FTPD UPGRADE*/ +#define CFG_USE_FTPD_UPGRADE 0 + +/*section 15-----support customer macro*/ +#define CFG_SUPPORT_TIANZHIHENG_DRONE 0 + +/*section 16-----support mcu & deep sleep*/ +#define CFG_USE_MCU_PS 1 +#define CFG_USE_DEEP_PS 1 + +/*section 17-----support sta power sleep*/ +#define CFG_USE_STA_PS 1 +#define CFG_LOW_LATENCY_PS 0 +/*section 18-----AP support stas in power save*/ +#define CFG_USE_AP_PS 0 + +/*section 19-----for SDCARD HOST*/ +#define CFG_USE_SDCARD_HOST 0 + +/*section 20 ----- support mp3 decoder*/ +#define CONFIG_APP_MP3PLAYER 0 + +/*section 21 ----- support ota*/ +#define CFG_SUPPORT_OTA_HTTP 0 +#define CFG_SUPPORT_OTA_TFTP 0 + +/*section 22 ----- support adc calibrate*/ +#define CFG_SARADC_CALIBRATE 1 + +/*section 23 ----- support reduce nomal power*/ +#define CFG_SYS_REDUCE_NORMAL_POWER 0 + +/*section 24 ----- less memery in rwnx*/ +#define CFG_LESS_MEMERY_IN_RWNX 1 +#define CFG_LESS_CODE_SIZE 1 + +/*section 25 ----- use audio*/ +#define CFG_USE_AUDIO 0 +#define CFG_USE_AUD_DAC 0 +#define CFG_USE_AUD_ADC 0 + +#define CFG_PTA_SWITCH_RF_EN 0 + +#define CFG_RF_USER_BLE 1 +#define CFG_RF_USER_WIFI 2 +#define CFG_DEFAULT_RF_USER CFG_RF_USER_WIFI + +#define CFG_USE_TUYA_CCA_TEST 0 + +#define CFG_AP_MONITOR_COEXIST 1 + +#define CFG_SUPPORT_BLE 1 +#define BLE_VERSION_4_2 1 +#define BLE_VERSION_5_X 2 +#define CFG_BLE_VERSION BLE_VERSION_5_X + +#define CFG_USE_BK_HOST 0 +#define CFG_USE_BLE_PS 1 + +#define CFG_ENABLE_ATE_FEATURE 0 + +#define CFG_XTAL_FREQUENCE_40M 40000000 //40MHz +#define CFG_XTAL_FREQUENCE_26M 26000000 //26MHz +#if (CFG_SOC_NAME == SOC_BK7231N) +#define CFG_XTAL_FREQUENCE CFG_XTAL_FREQUENCE_26M//CFG_XTAL_FREQUENCE_40M +#else +#define CFG_XTAL_FREQUENCE CFG_XTAL_FREQUENCE_26M +#endif + +#define CFG_RWNX_QOS_MSDU 1 + +#define CFG_USE_SPI_DMA 1 +#define CFG_USE_SPI_MASTER 1 +#define CFG_USE_SPI_SLAVE 1 +#endif // _SYS_CONFIG_H_ diff --git a/beken_os/beken378/app/config/sys_version.h b/beken_os/beken378/app/config/sys_version.h new file mode 100755 index 0000000..9a27871 --- /dev/null +++ b/beken_os/beken378/app/config/sys_version.h @@ -0,0 +1,9 @@ +#ifndef _SYS_VERSION_H_ +#define _SYS_VERSION_H_ + +#define RELEASE_VERSION "1.0.9" +#define RELEASE_TIME "2020.09.10 13:44" +#define FMALL_VERSION "5.0.4" +#define FMAC_LIB_VERSON "2.0.2" + +#endif // _SYS_VERSION_H_ diff --git a/beken_os/beken378/app/ftp/ftpd.c b/beken_os/beken378/app/ftp/ftpd.c new file mode 100755 index 0000000..416397a --- /dev/null +++ b/beken_os/beken378/app/ftp/ftpd.c @@ -0,0 +1,1493 @@ +/* + * Copyright (c) 2002 Florian Schulze. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the authors nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * ftpd.c - This file is part of the FTP daemon for lwIP + * + */ +#include "include.h" +#if CFG_USE_FTPD_UPGRADE +#include "mem_pub.h" +#include "lwip/debug.h" + +#include "lwip/stats.h" + +#include "ftpd.h" + +#include "lwip/tcp.h" + +#include +#include +#include +#include + +#include "vfs.h" + +//#define FTPD_DEBUG +#include "uart_pub.h" +#ifdef FTPD_DEBUG +#define dbg_printf os_printf +#else +#ifdef _MSC_VER +#define dbg_printf(x) /* x */ +#else +#define dbg_printf(f, ...) /* */ +#endif +#endif + +#define EINVAL 1 +#define ENOMEM 2 +#define ENODEV 3 + +#define msg110 "110 MARK %s = %s." +/* + 110 Restart marker reply. + In this case, the text is exact and not left to the + particular implementation; it must read: + MARK yyyy = mmmm + Where yyyy is User-process data stream marker, and mmmm + server's equivalent marker (note the spaces between markers + and "="). +*/ +#define msg120 "120 Service ready in nnn minutes." +#define msg125 "125 Data connection already open; transfer starting." +#define msg150 "150 File status okay; about to open data connection." +#define msg150recv "150 Opening BINARY mode data connection for %s (%i bytes)." +#define msg150stor "150 Opening BINARY mode data connection for %s." +#define msg200 "200 Command okay." +#define msg202 "202 Command not implemented, superfluous at this site." +#define msg211 "211 System status, or system help reply." +#define msg212 "212 Directory status." +#define msg213 "213 File status." +#define msg214 "214 %s." +/* + 214 Help message. + On how to use the server or the meaning of a particular + non-standard command. This reply is useful only to the + human user. +*/ +#define msg214SYST "214 %s system type." +/* + 215 NAME system type. + Where NAME is an official system name from the list in the + Assigned Numbers document. +*/ +#define msg220 "220 lwIP FTP Server ready." +/* + 220 Service ready for new user. +*/ +#define msg221 "221 Goodbye." +/* + 221 Service closing control connection. + Logged out if appropriate. +*/ +#define msg225 "225 Data connection open; no transfer in progress." +#define msg226 "226 Closing data connection." +/* + Requested file action successful (for example, file + transfer or file abort). +*/ +#define msg227 "227 Entering Passive Mode (%i,%i,%i,%i,%i,%i)." +/* + 227 Entering Passive Mode (h1,h2,h3,h4,p1,p2). +*/ +#define msg230 "230 User logged in, proceed." +#define msg250 "250 Requested file action okay, completed." +#define msg257PWD "257 \"%s\" is current directory." +#define msg257 "257 \"%s\" created." +/* + 257 "PATHNAME" created. +*/ +#define msg331 "331 User name okay, need password." +#define msg332 "332 Need account for login." +#define msg350 "350 Requested file action pending further information." +#define msg421 "421 Service not available, closing control connection." +/* + This may be a reply to any command if the service knows it + must shut down. +*/ +#define msg425 "425 Can't open data connection." +#define msg426 "426 Connection closed; transfer aborted." +#define msg450 "450 Requested file action not taken." +/* + File unavailable (e.g., file busy). +*/ +#define msg451 "451 Requested action aborted: local error in processing." +#define msg452 "452 Requested action not taken." +/* + Insufficient storage space in system. +*/ +#define msg500 "500 Syntax error, command unrecognized." +/* + This may include errors such as command line too long. +*/ +#define msg501 "501 Syntax error in parameters or arguments." +#define msg502 "502 Command not implemented." +#define msg503 "503 Bad sequence of commands." +#define msg504 "504 Command not implemented for that parameter." +#define msg530 "530 Not logged in." +#define msg532 "532 Need account for storing files." +#define msg550 "550 Requested action not taken." +/* + File unavailable (e.g., file not found, no access). +*/ +#define msg551 "551 Requested action aborted: page type unknown." +#define msg552 "552 Requested file action aborted." +/* + Exceeded storage allocation (for current directory or + dataset). +*/ +#define msg553 "553 Requested action not taken." +/* + File name not allowed. +*/ + +enum ftpd_state_e +{ + FTPD_USER, + FTPD_PASS, + FTPD_IDLE, + FTPD_NLST, + FTPD_LIST, + FTPD_RETR, + FTPD_RNFR, + FTPD_STOR, + FTPD_QUIT +}; + +static const char *month_table[12] = +{ + "Jan", + "Feb", + "Mar", + "Apr", + "May", + "Jun", + "Jul", + "Aug", + "Sep", + "Oct", + "Nov", + "Dez" +}; + +/* +------------------------------------------------------------ + SFIFO 1.3 +------------------------------------------------------------ + * Simple portable lock-free FIFO + * (c) 2000-2002, David Olofson + * + * Platform support: + * gcc / Linux / x86: Works + * gcc / Linux / x86 kernel: Works + * gcc / FreeBSD / x86: Works + * gcc / NetBSD / x86: Works + * gcc / Mac OS X / PPC: Works + * gcc / Win32 / x86: Works + * Borland C++ / DOS / x86RM: Works + * Borland C++ / Win32 / x86PM16: Untested + * ? / Various Un*ces / ?: Untested + * ? / Mac OS / PPC: Untested + * gcc / BeOS / x86: Untested + * gcc / BeOS / PPC: Untested + * ? / ? / Alpha: Untested + * + * 1.2: Max buffer size halved, to avoid problems with + * the sign bit... + * + * 1.3: Critical buffer allocation bug fixed! For certain + * requested buffer sizes, older version would + * allocate a buffer of insufficient size, which + * would result in memory thrashing. (Amazing that + * I've manage to use this to the extent I have + * without running into this... *heh*) + */ + +/* + * Porting note: + * Reads and writes of a variable of this type in memory + * must be *atomic*! 'int' is *not* atomic on all platforms. + * A safe type should be used, and sfifo should limit the + * maximum buffer size accordingly. + */ +typedef int sfifo_atomic_t; +#ifdef __TURBOC__ +# define SFIFO_MAX_BUFFER_SIZE 0x7fff +#else /* Kludge: Assume 32 bit platform */ +# define SFIFO_MAX_BUFFER_SIZE 0x7fffffff +#endif + +typedef struct sfifo_t +{ + char *buffer; + int size; /* Number of bytes */ + sfifo_atomic_t readpos; /* Read position */ + sfifo_atomic_t writepos; /* Write position */ +} sfifo_t; + +#define SFIFO_SIZEMASK(x) ((x)->size - 1) + +#define sfifo_used(x) (((x)->writepos - (x)->readpos) & SFIFO_SIZEMASK(x)) +#define sfifo_space(x) ((x)->size - 1 - sfifo_used(x)) + +#define DBG(x) + +/* + * Alloc buffer, init FIFO etc... + */ +static int sfifo_init(sfifo_t *f, int size) +{ + memset(f, 0, sizeof(sfifo_t)); + + if(size > SFIFO_MAX_BUFFER_SIZE) + return -EINVAL; + + /* + * Set sufficient power-of-2 size. + * + * No, there's no bug. If you need + * room for N bytes, the buffer must + * be at least N+1 bytes. (The fifo + * can't tell 'empty' from 'full' + * without unsafe index manipulations + * otherwise.) + */ + f->size = 1; + for(; f->size <= size; f->size <<= 1) + ; + + /* Get buffer */ + if( 0 == (f->buffer = (void *)os_malloc(f->size)) ) + return -ENOMEM; + + return 0; +} + +/* + * Dealloc buffer etc... + */ +static void sfifo_close(sfifo_t *f) +{ + if(f->buffer) + os_free(f->buffer); +} + +/* + * Write bytes to a FIFO + * Return number of bytes written, or an error code + */ +static int sfifo_write(sfifo_t *f, const void *_buf, int len) +{ + int total; + int i; + const char *buf = (const char *)_buf; + + if(!f->buffer) + return -ENODEV; /* No buffer! */ + + /* total = len = min(space, len) */ + total = sfifo_space(f); + DBG(dbg_printf("sfifo_space() = %d\r\n", total)); + if(len > total) + len = total; + else + total = len; + + i = f->writepos; + if(i + len > f->size) + { + memcpy(f->buffer + i, buf, f->size - i); + buf += f->size - i; + len -= f->size - i; + i = 0; + } + memcpy(f->buffer + i, buf, len); + f->writepos = i + len; + + return total; +} + +struct ftpd_datastate +{ + int connected; + vfs_dir_t *vfs_dir; + vfs_dirent_t *vfs_dirent; + vfs_file_t *vfs_file; + sfifo_t fifo; + struct tcp_pcb *msgpcb; + struct ftpd_msgstate *msgfs; +}; + +struct ftpd_msgstate +{ + enum ftpd_state_e state; + sfifo_t fifo; + vfs_t *vfs; + struct ip_addr dataip; + u16_t dataport; + struct tcp_pcb *datapcb; + struct ftpd_datastate *datafs; + int passive; + char *renamefrom; +}; + +static void send_msg(struct tcp_pcb *pcb, struct ftpd_msgstate *fsm, char *msg, ...); + +static void ftpd_dataerr(void *arg, err_t err) +{ + struct ftpd_datastate *fsd = arg; + + dbg_printf("ftpd_dataerr: %s (%i)\r\n", lwip_strerr(err), err); + if (fsd == NULL) + return; + fsd->msgfs->datafs = NULL; + fsd->msgfs->state = FTPD_IDLE; + os_free(fsd); +} + +static void ftpd_dataclose(struct tcp_pcb *pcb, struct ftpd_datastate *fsd) +{ + tcp_arg(pcb, NULL); + tcp_sent(pcb, NULL); + tcp_recv(pcb, NULL); + fsd->msgfs->datafs = NULL; + sfifo_close(&fsd->fifo); + os_free(fsd); + tcp_arg(pcb, NULL); + tcp_close(pcb); +} + +static void send_data(struct tcp_pcb *pcb, struct ftpd_datastate *fsd) +{ + err_t err; + u16_t len; + + if (sfifo_used(&fsd->fifo) > 0) + { + int i; + + /* We cannot send more data than space available in the send + buffer. */ + if (tcp_sndbuf(pcb) < sfifo_used(&fsd->fifo)) + { + len = tcp_sndbuf(pcb); + } + else + { + len = (u16_t) sfifo_used(&fsd->fifo); + } + + i = fsd->fifo.readpos; + if ((i + len) > fsd->fifo.size) + { + err = tcp_write(pcb, fsd->fifo.buffer + i, (u16_t)(fsd->fifo.size - i), 1); + if (err != ERR_OK) + { + dbg_printf("send_data: error writing!\r\n"); + return; + } + len -= fsd->fifo.size - i; + fsd->fifo.readpos = 0; + i = 0; + } + + err = tcp_write(pcb, fsd->fifo.buffer + i, len, 1); + if (err != ERR_OK) + { + dbg_printf("send_data: error writing!\r\n"); + return; + } + fsd->fifo.readpos += len; + } +} + +static void send_file(struct ftpd_datastate *fsd, struct tcp_pcb *pcb) +{ + if (!fsd->connected) + return; + + if (fsd->vfs_file) + { + char buffer[2048]; + int len; + + len = sfifo_space(&fsd->fifo); + if (len == 0) + { + send_data(pcb, fsd); + return; + } + if (len > 2048) + len = 2048; + len = vfs_read(buffer, 1, len, fsd->vfs_file); + if (len == 0) + { + if (vfs_eof(fsd->vfs_file) == 0) + return; + vfs_close(fsd->vfs_file); + fsd->vfs_file = NULL; + return; + } + sfifo_write(&fsd->fifo, buffer, len); + send_data(pcb, fsd); + } + else + { + struct ftpd_msgstate *fsm; + struct tcp_pcb *msgpcb; + + if (sfifo_used(&fsd->fifo) > 0) + { + send_data(pcb, fsd); + return; + } + fsm = fsd->msgfs; + msgpcb = fsd->msgpcb; + + vfs_close(fsd->vfs_file); + fsd->vfs_file = NULL; + ftpd_dataclose(pcb, fsd); + fsm->datapcb = NULL; + fsm->datafs = NULL; + fsm->state = FTPD_IDLE; + send_msg(msgpcb, fsm, msg226); + return; + } +} + +static void send_next_directory(struct ftpd_datastate *fsd, struct tcp_pcb *pcb, int shortlist) +{ + char buffer[1024]; + int len; + + while (1) + { + if (fsd->vfs_dirent == NULL) + fsd->vfs_dirent = vfs_readdir(fsd->vfs_dir); + + if (fsd->vfs_dirent) + { + if (shortlist) + { + len = sprintf(buffer, "%s\r\n", fsd->vfs_dirent->name); + if (sfifo_space(&fsd->fifo) < len) + { + send_data(pcb, fsd); + return; + } + sfifo_write(&fsd->fifo, buffer, len); + fsd->vfs_dirent = NULL; + } + else + { + vfs_stat_t st; + time_t current_time; + int current_year; + struct tm *s_time; + + time(¤t_time); + s_time = gmtime(¤t_time); + current_year = s_time->tm_year; + + vfs_stat(fsd->msgfs->vfs, fsd->vfs_dirent->name, &st); + s_time = gmtime(&st.st_mtime); + if (s_time->tm_year == current_year) + len = sprintf(buffer, "-rw-rw-rw- 1 user ftp %11ld %s %02i %02i:%02i %s\r\n", st.st_size, month_table[s_time->tm_mon], s_time->tm_mday, s_time->tm_hour, s_time->tm_min, fsd->vfs_dirent->name); + else + len = sprintf(buffer, "-rw-rw-rw- 1 user ftp %11ld %s %02i %5i %s\r\n", st.st_size, month_table[s_time->tm_mon], s_time->tm_mday, s_time->tm_year + 1900, fsd->vfs_dirent->name); + if (VFS_ISDIR(st.st_mode)) + buffer[0] = 'd'; + if (sfifo_space(&fsd->fifo) < len) + { + send_data(pcb, fsd); + return; + } + sfifo_write(&fsd->fifo, buffer, len); + fsd->vfs_dirent = NULL; + } + } + else + { + struct ftpd_msgstate *fsm; + struct tcp_pcb *msgpcb; + + if (sfifo_used(&fsd->fifo) > 0) + { + send_data(pcb, fsd); + return; + } + fsm = fsd->msgfs; + msgpcb = fsd->msgpcb; + + vfs_closedir(fsd->vfs_dir); + fsd->vfs_dir = NULL; + ftpd_dataclose(pcb, fsd); + fsm->datapcb = NULL; + fsm->datafs = NULL; + fsm->state = FTPD_IDLE; + send_msg(msgpcb, fsm, msg226); + return; + } + } +} + +static err_t ftpd_datasent(void *arg, struct tcp_pcb *pcb, u16_t len) +{ + struct ftpd_datastate *fsd = arg; + + switch (fsd->msgfs->state) + { + case FTPD_LIST: + send_next_directory(fsd, pcb, 0); + break; + case FTPD_NLST: + send_next_directory(fsd, pcb, 1); + break; + case FTPD_RETR: + send_file(fsd, pcb); + break; + default: + break; + } + + return ERR_OK; +} + +static err_t ftpd_datarecv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) +{ + struct ftpd_datastate *fsd = arg; + + if (err == ERR_OK && p != NULL) + { + struct pbuf *q; + u16_t tot_len = 0; + + for (q = p; q != NULL; q = q->next) + { + int len; + + len = vfs_write(q->payload, 1, q->len, fsd->vfs_file); + tot_len += len; + if (len != q->len) + break; + } + + /* Inform TCP that we have taken the data. */ + tcp_recved(pcb, tot_len); + + pbuf_free(p); + } + if (err == ERR_OK && p == NULL) + { + struct ftpd_msgstate *fsm; + struct tcp_pcb *msgpcb; + + fsm = fsd->msgfs; + msgpcb = fsd->msgpcb; + + vfs_close(fsd->vfs_file); + fsd->vfs_file = NULL; + ftpd_dataclose(pcb, fsd); + fsm->datapcb = NULL; + fsm->datafs = NULL; + fsm->state = FTPD_IDLE; + send_msg(msgpcb, fsm, msg226); + } + + return ERR_OK; +} + +static err_t ftpd_dataconnected(void *arg, struct tcp_pcb *pcb, err_t err) +{ + struct ftpd_datastate *fsd = arg; + + fsd->msgfs->datapcb = pcb; + fsd->connected = 1; + + /* Tell TCP that we wish to be informed of incoming data by a call + to the http_recv() function. */ + tcp_recv(pcb, ftpd_datarecv); + + /* Tell TCP that we wish be to informed of data that has been + successfully sent by a call to the ftpd_sent() function. */ + tcp_sent(pcb, ftpd_datasent); + + tcp_err(pcb, ftpd_dataerr); + + switch (fsd->msgfs->state) + { + case FTPD_LIST: + send_next_directory(fsd, pcb, 0); + break; + case FTPD_NLST: + send_next_directory(fsd, pcb, 1); + break; + case FTPD_RETR: + send_file(fsd, pcb); + break; + default: + break; + } + + return ERR_OK; +} + +static err_t ftpd_dataaccept(void *arg, struct tcp_pcb *pcb, err_t err) +{ + struct ftpd_datastate *fsd = arg; + + fsd->msgfs->datapcb = pcb; + fsd->connected = 1; + + /* Tell TCP that we wish to be informed of incoming data by a call + to the http_recv() function. */ + tcp_recv(pcb, ftpd_datarecv); + + /* Tell TCP that we wish be to informed of data that has been + successfully sent by a call to the ftpd_sent() function. */ + tcp_sent(pcb, ftpd_datasent); + + tcp_err(pcb, ftpd_dataerr); + + switch (fsd->msgfs->state) + { + case FTPD_LIST: + send_next_directory(fsd, pcb, 0); + break; + case FTPD_NLST: + send_next_directory(fsd, pcb, 1); + break; + case FTPD_RETR: + send_file(fsd, pcb); + break; + default: + break; + } + + return ERR_OK; +} + +static int open_dataconnection(struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) +{ + if (fsm->passive) + return 0; + + /* Allocate memory for the structure that holds the state of the + connection. */ + fsm->datafs = (struct ftpd_datastate *)os_malloc(sizeof(struct ftpd_datastate)); + + if (fsm->datafs == NULL) + { + send_msg(pcb, fsm, msg451); + return 1; + } + memset(fsm->datafs, 0, sizeof(struct ftpd_datastate)); + fsm->datafs->msgfs = fsm; + fsm->datafs->msgpcb = pcb; + sfifo_init(&fsm->datafs->fifo, 2000); + + fsm->datapcb = tcp_new(); + tcp_bind(fsm->datapcb, (ip_addr_t *)&pcb->local_ip, 20); + /* Tell TCP that this is the structure we wish to be passed for our + callbacks. */ + tcp_arg(fsm->datapcb, fsm->datafs); + ip_addr_t dataip; + ip_addr_copy(dataip, fsm->dataip); + tcp_connect(fsm->datapcb, &dataip, fsm->dataport, ftpd_dataconnected); + + return 0; +} + +static void cmd_user(const char *arg, struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) +{ + send_msg(pcb, fsm, msg331); + fsm->state = FTPD_PASS; + /* + send_msg(pcb, fs, msgLoginFailed); + fs->state = FTPD_QUIT; + */ +} + +static void cmd_pass(const char *arg, struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) +{ + send_msg(pcb, fsm, msg230); + fsm->state = FTPD_IDLE; + /* + send_msg(pcb, fs, msgLoginFailed); + fs->state = FTPD_QUIT; + */ +} + +static void cmd_port(const char *arg, struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) +{ + int nr; + unsigned pHi, pLo; + unsigned ip[4]; + + nr = sscanf(arg, "%u,%u,%u,%u,%u,%u", &(ip[0]), &(ip[1]), &(ip[2]), &(ip[3]), &pHi, &pLo); + if (nr != 6) + { + send_msg(pcb, fsm, msg501); + } + else + { + IP4_ADDR(&fsm->dataip, (u8_t) ip[0], (u8_t) ip[1], (u8_t) ip[2], (u8_t) ip[3]); + fsm->dataport = ((u16_t) pHi << 8) | (u16_t) pLo; + send_msg(pcb, fsm, msg200); + } +} + +static void cmd_quit(const char *arg, struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) +{ + send_msg(pcb, fsm, msg221); + fsm->state = FTPD_QUIT; +} + +static void cmd_cwd(const char *arg, struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) +{ + if (!vfs_chdir(fsm->vfs, arg)) + { + send_msg(pcb, fsm, msg250); + } + else + { + send_msg(pcb, fsm, msg550); + } +} + +static void cmd_cdup(const char *arg, struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) +{ + if (!vfs_chdir(fsm->vfs, "..")) + { + send_msg(pcb, fsm, msg250); + } + else + { + send_msg(pcb, fsm, msg550); + } +} + +static void cmd_pwd(const char *arg, struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) +{ + char *path; + + path = vfs_getcwd(fsm->vfs, NULL, 0); + if (path) + { + send_msg(pcb, fsm, msg257PWD, path); + os_free(path); + } +} + +static void cmd_list_common(const char *arg, struct tcp_pcb *pcb, struct ftpd_msgstate *fsm, int shortlist) +{ + vfs_dir_t *vfs_dir; + char *cwd; + + cwd = vfs_getcwd(fsm->vfs, NULL, 0); + if ((!cwd)) + { + send_msg(pcb, fsm, msg451); + return; + } + vfs_dir = vfs_opendir(fsm->vfs, cwd); + os_free(cwd); + if (!vfs_dir) + { + send_msg(pcb, fsm, msg451); + return; + } + + if (open_dataconnection(pcb, fsm) != 0) + { + vfs_closedir(vfs_dir); + return; + } + + fsm->datafs->vfs_dir = vfs_dir; + fsm->datafs->vfs_dirent = NULL; + if (shortlist != 0) + fsm->state = FTPD_NLST; + else + fsm->state = FTPD_LIST; + + send_msg(pcb, fsm, msg150); +} + +static void cmd_nlst(const char *arg, struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) +{ + cmd_list_common(arg, pcb, fsm, 1); +} + +static void cmd_list(const char *arg, struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) +{ + cmd_list_common(arg, pcb, fsm, 0); +} + +static void cmd_retr(const char *arg, struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) +{ + vfs_file_t *vfs_file; + vfs_stat_t st; + + vfs_stat(fsm->vfs, arg, &st); + if (!VFS_ISREG(st.st_mode)) + { + send_msg(pcb, fsm, msg550); + return; + } + vfs_file = vfs_open(fsm->vfs, arg, "rb"); + if (!vfs_file) + { + send_msg(pcb, fsm, msg550); + return; + } + + send_msg(pcb, fsm, msg150recv, arg, st.st_size); + + if (open_dataconnection(pcb, fsm) != 0) + { + vfs_close(vfs_file); + return; + } + + fsm->datafs->vfs_file = vfs_file; + fsm->state = FTPD_RETR; +} + +static void cmd_stor(const char *arg, struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) +{ + vfs_file_t *vfs_file; + + vfs_file = vfs_open(fsm->vfs, arg, "wb"); + if (!vfs_file) + { + send_msg(pcb, fsm, msg550); + return; + } + + send_msg(pcb, fsm, msg150stor, arg); + + if (open_dataconnection(pcb, fsm) != 0) + { + vfs_close(vfs_file); + return; + } + + fsm->datafs->vfs_file = vfs_file; + fsm->state = FTPD_STOR; +} + +static void cmd_noop(const char *arg, struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) +{ + send_msg(pcb, fsm, msg200); +} + +static void cmd_syst(const char *arg, struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) +{ + send_msg(pcb, fsm, msg214SYST, "UNIX"); +} + +static void cmd_pasv(const char *arg, struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) +{ + static u16_t port = 4096; + static u16_t start_port = 4096; + struct tcp_pcb *temppcb; + + /* Allocate memory for the structure that holds the state of the + connection. */ + fsm->datafs = (struct ftpd_datastate *)os_malloc(sizeof(struct ftpd_datastate)); + + if (fsm->datafs == NULL) + { + send_msg(pcb, fsm, msg451); + return; + } + memset(fsm->datafs, 0, sizeof(struct ftpd_datastate)); + + fsm->datapcb = tcp_new(); + if (!fsm->datapcb) + { + os_free(fsm->datafs); + send_msg(pcb, fsm, msg451); + return; + } + + sfifo_init(&fsm->datafs->fifo, 2000); + + start_port = port; + + while (1) + { + err_t err; + + if(++port > 0x7fff) + port = 4096; + + fsm->dataport = port; + err = tcp_bind(fsm->datapcb, (ip_addr_t *)&pcb->local_ip, fsm->dataport); + if (err == ERR_OK) + break; + if (start_port == port) + err = ERR_CLSD; + if (err == ERR_USE) + continue; + if (err != ERR_OK) + { + ftpd_dataclose(fsm->datapcb, fsm->datafs); + fsm->datapcb = NULL; + fsm->datafs = NULL; + return; + } + } + + fsm->datafs->msgfs = fsm; + + temppcb = tcp_listen(fsm->datapcb); + if (!temppcb) + { + ftpd_dataclose(fsm->datapcb, fsm->datafs); + fsm->datapcb = NULL; + fsm->datafs = NULL; + return; + } + fsm->datapcb = temppcb; + + fsm->passive = 1; + fsm->datafs->connected = 0; + fsm->datafs->msgpcb = pcb; + + /* Tell TCP that this is the structure we wish to be passed for our + callbacks. */ + tcp_arg(fsm->datapcb, fsm->datafs); + + tcp_accept(fsm->datapcb, ftpd_dataaccept); + send_msg(pcb, fsm, msg227, ip4_addr1(&pcb->local_ip), ip4_addr2(&pcb->local_ip), ip4_addr3(&pcb->local_ip), ip4_addr4(&pcb->local_ip), (fsm->dataport >> 8) & 0xff, (fsm->dataport) & 0xff); +} + +static void cmd_abrt(const char *arg, struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) +{ + if (fsm->datafs != NULL) + { + tcp_arg(fsm->datapcb, NULL); + tcp_sent(fsm->datapcb, NULL); + tcp_recv(fsm->datapcb, NULL); + tcp_arg(fsm->datapcb, NULL); + tcp_abort(pcb); + sfifo_close(&fsm->datafs->fifo); + os_free(fsm->datafs); + fsm->datafs = NULL; + } + fsm->state = FTPD_IDLE; +} + +static void cmd_type(const char *arg, struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) +{ + dbg_printf("Got TYPE -%s-\r\n", arg); + send_msg(pcb, fsm, msg502); +} + +static void cmd_mode(const char *arg, struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) +{ + dbg_printf("Got MODE -%s-\r\n", arg); + send_msg(pcb, fsm, msg502); +} + +static void cmd_rnfr(const char *arg, struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) +{ + if (arg == NULL) + { + send_msg(pcb, fsm, msg501); + return; + } + if (*arg == '\0') + { + send_msg(pcb, fsm, msg501); + return; + } + if (fsm->renamefrom) + os_free(fsm->renamefrom); + fsm->renamefrom = (char *)os_malloc(strlen(arg) + 1); + if (fsm->renamefrom == NULL) + { + send_msg(pcb, fsm, msg451); + return; + } + strcpy(fsm->renamefrom, arg); + fsm->state = FTPD_RNFR; + send_msg(pcb, fsm, msg350); +} + +static void cmd_rnto(const char *arg, struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) +{ + if (fsm->state != FTPD_RNFR) + { + send_msg(pcb, fsm, msg503); + return; + } + fsm->state = FTPD_IDLE; + if (arg == NULL) + { + send_msg(pcb, fsm, msg501); + return; + } + if (*arg == '\0') + { + send_msg(pcb, fsm, msg501); + return; + } + if (vfs_rename(fsm->vfs, fsm->renamefrom, arg)) + { + send_msg(pcb, fsm, msg450); + } + else + { + send_msg(pcb, fsm, msg250); + } +} + +static void cmd_mkd(const char *arg, struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) +{ + if (arg == NULL) + { + send_msg(pcb, fsm, msg501); + return; + } + if (*arg == '\0') + { + send_msg(pcb, fsm, msg501); + return; + } + if (vfs_mkdir(fsm->vfs, arg, VFS_IRWXU | VFS_IRWXG | VFS_IRWXO) != 0) + { + send_msg(pcb, fsm, msg550); + } + else + { + send_msg(pcb, fsm, msg257, arg); + } +} + +static void cmd_rmd(const char *arg, struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) +{ + vfs_stat_t st; + + if (arg == NULL) + { + send_msg(pcb, fsm, msg501); + return; + } + if (*arg == '\0') + { + send_msg(pcb, fsm, msg501); + return; + } + if (vfs_stat(fsm->vfs, arg, &st) != 0) + { + send_msg(pcb, fsm, msg550); + return; + } + if (!VFS_ISDIR(st.st_mode)) + { + send_msg(pcb, fsm, msg550); + return; + } + if (vfs_rmdir(fsm->vfs, arg) != 0) + { + send_msg(pcb, fsm, msg550); + } + else + { + send_msg(pcb, fsm, msg250); + } +} + +static void cmd_dele(const char *arg, struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) +{ + vfs_stat_t st; + + if (arg == NULL) + { + send_msg(pcb, fsm, msg501); + return; + } + if (*arg == '\0') + { + send_msg(pcb, fsm, msg501); + return; + } + if (vfs_stat(fsm->vfs, arg, &st) != 0) + { + send_msg(pcb, fsm, msg550); + return; + } + if (!VFS_ISREG(st.st_mode)) + { + send_msg(pcb, fsm, msg550); + return; + } + if (vfs_remove(fsm->vfs, arg) != 0) + { + send_msg(pcb, fsm, msg550); + } + else + { + send_msg(pcb, fsm, msg250); + } +} + +struct ftpd_command +{ + char *cmd; + void (*func) (const char *arg, struct tcp_pcb *pcb, struct ftpd_msgstate *fsm); +}; + +static struct ftpd_command ftpd_commands[] = +{ + {"USER", cmd_user}, + {"PASS", cmd_pass}, + {"PORT", cmd_port}, + {"QUIT", cmd_quit}, + {"CWD", cmd_cwd}, + {"CDUP", cmd_cdup}, + {"PWD", cmd_pwd}, + {"XPWD", cmd_pwd}, + {"NLST", cmd_nlst}, + {"LIST", cmd_list}, + {"RETR", cmd_retr}, + {"STOR", cmd_stor}, + {"NOOP", cmd_noop}, + {"SYST", cmd_syst}, + {"ABOR", cmd_abrt}, + {"TYPE", cmd_type}, + {"MODE", cmd_mode}, + {"RNFR", cmd_rnfr}, + {"RNTO", cmd_rnto}, + {"MKD", cmd_mkd}, + {"XMKD", cmd_mkd}, + {"RMD", cmd_rmd}, + {"XRMD", cmd_rmd}, + {"DELE", cmd_dele}, + //{"PASV", cmd_pasv}, + {NULL, NULL} +}; + +static void send_msgdata(struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) +{ + err_t err; + u16_t len; + + if (sfifo_used(&fsm->fifo) > 0) + { + int i; + + /* We cannot send more data than space available in the send + buffer. */ + if (tcp_sndbuf(pcb) < sfifo_used(&fsm->fifo)) + { + len = tcp_sndbuf(pcb); + } + else + { + len = (u16_t) sfifo_used(&fsm->fifo); + } + + i = fsm->fifo.readpos; + if ((i + len) > fsm->fifo.size) + { + err = tcp_write(pcb, fsm->fifo.buffer + i, (u16_t)(fsm->fifo.size - i), 1); + if (err != ERR_OK) + { + dbg_printf("send_msgdata: error writing!\r\n"); + return; + } + len -= fsm->fifo.size - i; + fsm->fifo.readpos = 0; + i = 0; + } + + err = tcp_write(pcb, fsm->fifo.buffer + i, len, 1); + if (err != ERR_OK) + { + dbg_printf("send_msgdata: error writing!\r\n"); + return; + } + fsm->fifo.readpos += len; + } +} + +static void send_msg(struct tcp_pcb *pcb, struct ftpd_msgstate *fsm, char *msg, ...) +{ + va_list arg; + char buffer[1024]; + int len; + + va_start(arg, msg); + vsprintf(buffer, msg, arg); + va_end(arg); + strcat(buffer, "\r\n"); + len = strlen(buffer); + if (sfifo_space(&fsm->fifo) < len) + return; + sfifo_write(&fsm->fifo, buffer, len); + dbg_printf("response: %s", buffer); + send_msgdata(pcb, fsm); +} + +static void ftpd_msgerr(void *arg, err_t err) +{ + struct ftpd_msgstate *fsm = arg; + + dbg_printf("ftpd_msgerr: %s (%i)\r\n", lwip_strerr(err), err); + if (fsm == NULL) + return; + if (fsm->datafs) + ftpd_dataclose(fsm->datapcb, fsm->datafs); + sfifo_close(&fsm->fifo); + vfs_close(fsm->vfs); + fsm->vfs = NULL; + if (fsm->renamefrom) + os_free(fsm->renamefrom); + fsm->renamefrom = NULL; + os_free(fsm); +} + +static void ftpd_msgclose(struct tcp_pcb *pcb, struct ftpd_msgstate *fsm) +{ + tcp_arg(pcb, NULL); + tcp_sent(pcb, NULL); + tcp_recv(pcb, NULL); + if (fsm->datafs) + ftpd_dataclose(fsm->datapcb, fsm->datafs); + sfifo_close(&fsm->fifo); + vfs_close(fsm->vfs); + fsm->vfs = NULL; + if (fsm->renamefrom) + os_free(fsm->renamefrom); + fsm->renamefrom = NULL; + os_free(fsm); + tcp_arg(pcb, NULL); + tcp_close(pcb); +} + +static err_t ftpd_msgsent(void *arg, struct tcp_pcb *pcb, u16_t len) +{ + struct ftpd_msgstate *fsm = arg; + + if (pcb->state > ESTABLISHED) + return ERR_OK; + + if ((sfifo_used(&fsm->fifo) == 0) && (fsm->state == FTPD_QUIT)) + { + ftpd_msgclose(pcb, fsm); + return ERR_OK; + } + + send_msgdata(pcb, fsm); + + return ERR_OK; +} + +static err_t ftpd_msgrecv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err) +{ + char *text; + struct ftpd_msgstate *fsm = arg; + + if (err == ERR_OK && p != NULL) + { + + /* Inform TCP that we have taken the data. */ + tcp_recved(pcb, p->tot_len); + + text = (char *)os_malloc(p->tot_len + 1); + if (text) + { + char cmd[5]; + struct pbuf *q; + char *pt = text; + struct ftpd_command *ftpd_cmd; + + for (q = p; q != NULL; q = q->next) + { + bcopy(q->payload, pt, q->len); + pt += q->len; + } + *pt = '\0'; + + pt = &text[strlen(text) - 1]; + while (((*pt == '\r') || (*pt == '\n')) && pt >= text) + *pt-- = '\0'; + + dbg_printf("query: %s\r\n", text); + + strncpy(cmd, text, 4); + for (pt = cmd; isalpha(*pt) && pt < &cmd[4]; pt++) + *pt = toupper(*pt); + *pt = '\0'; + + for (ftpd_cmd = ftpd_commands; ftpd_cmd->cmd != NULL; ftpd_cmd++) + { + if (!strcmp(ftpd_cmd->cmd, cmd)) + break; + } + + if (strlen(text) < (strlen(cmd) + 1)) + pt = ""; + else + pt = &text[strlen(cmd) + 1]; + + if (ftpd_cmd->func) + ftpd_cmd->func(pt, pcb, fsm); + else + send_msg(pcb, fsm, msg502); + + os_free(text); + } + pbuf_free(p); + } + + return ERR_OK; +} + +static err_t ftpd_msgpoll(void *arg, struct tcp_pcb *pcb) +{ + struct ftpd_msgstate *fsm = arg; + + if (fsm == NULL) + return ERR_OK; + + if (fsm->datafs) + { + if (fsm->datafs->connected) + { + switch (fsm->state) + { + case FTPD_LIST: + send_next_directory(fsm->datafs, fsm->datapcb, 0); + break; + case FTPD_NLST: + send_next_directory(fsm->datafs, fsm->datapcb, 1); + break; + case FTPD_RETR: + send_file(fsm->datafs, fsm->datapcb); + break; + default: + break; + } + } + } + + return ERR_OK; +} + +static err_t ftpd_msgaccept(void *arg, struct tcp_pcb *pcb, err_t err) +{ + struct ftpd_msgstate *fsm; + + /* Allocate memory for the structure that holds the state of the + connection. */ + fsm = (struct ftpd_msgstate *)os_malloc(sizeof(struct ftpd_msgstate)); + + if (fsm == NULL) + { + dbg_printf("ftpd_msgaccept: Out of memory\r\n"); + return ERR_MEM; + } + memset(fsm, 0, sizeof(struct ftpd_msgstate)); + + /* Initialize the structure. */ + sfifo_init(&fsm->fifo, 2000); + fsm->state = FTPD_IDLE; + fsm->vfs = vfs_openfs(); + if (!fsm->vfs) + { + os_free(fsm); + return ERR_CLSD; + } + + /* Tell TCP that this is the structure we wish to be passed for our + callbacks. */ + tcp_arg(pcb, fsm); + + /* Tell TCP that we wish to be informed of incoming data by a call + to the http_recv() function. */ + tcp_recv(pcb, ftpd_msgrecv); + + /* Tell TCP that we wish be to informed of data that has been + successfully sent by a call to the ftpd_sent() function. */ + tcp_sent(pcb, ftpd_msgsent); + + tcp_err(pcb, ftpd_msgerr); + + tcp_poll(pcb, ftpd_msgpoll, 1); + + send_msg(pcb, fsm, msg220); + + return ERR_OK; +} + +/*---------------------------------------------------------------------------*/ +PROCESS(lwip_ftp_server_process, "LWIP FTP server"); +/*---------------------------------------------------------------------------*/ + +PROCESS_THREAD(lwip_ftp_server_process, ev , data) +{ + struct tcp_pcb *pcb; + + PROCESS_BEGIN(); + + pcb = tcp_new(); + tcp_bind(pcb, IP_ADDR_ANY, 21); + pcb = tcp_listen(pcb); + tcp_accept(pcb, ftpd_msgaccept); + + while(1) + { + PROCESS_WAIT_EVENT(); + if(ev == PROCESS_EVENT_EXIT) + { + pcb = NULL; + } + } + + PROCESS_END(); +} + +void ftpd_stop(void) +{ +} + +void ftpd_start(void) +{ + dbg_printf("ftp server started\r\n"); + process_start(&lwip_ftp_server_process, NULL); +} +#endif + +//eof + diff --git a/beken_os/beken378/app/ftp/ftpd.h b/beken_os/beken378/app/ftp/ftpd.h new file mode 100755 index 0000000..bb9bf4a --- /dev/null +++ b/beken_os/beken378/app/ftp/ftpd.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2002 Florian Schulze. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the authors nor the names of the contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * ftpd.h - This file is part of the FTP daemon for lwIP + * + */ + +#ifndef __FTPD_H__ +#define __FTPD_H__ + +void ftpd_start(void); +void ftpd_stop(void); +#endif /* __FTPD_H__ */ diff --git a/beken_os/beken378/app/ftp/vfs.c b/beken_os/beken378/app/ftp/vfs.c new file mode 100755 index 0000000..d4fb20e --- /dev/null +++ b/beken_os/beken378/app/ftp/vfs.c @@ -0,0 +1,152 @@ +/* Copyright (c) 2013, Philipp T?lke + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "include.h" +#if CFG_USE_FTPD_UPGRADE +#include "mem_pub.h" +#include "vfs.h" +#include "ff.h" +#include +#include + +/* dirent that will be given to callers; + * note: both APIs assume that only one dirent ever exists + */ +vfs_dirent_t dir_ent; + +FIL guard_for_the_whole_fs; + +int vfs_read (void *buffer, int dummy, int len, vfs_file_t *file) +{ + unsigned int bytesread; + FRESULT r = f_read(file, buffer, len, &bytesread); + if (r != FR_OK) return 0; + return bytesread; +} + +vfs_dirent_t *vfs_readdir(vfs_dir_t *dir) +{ + FILINFO fi; + FRESULT r = f_readdir(dir, &fi); + if (r != FR_OK) return NULL; + if (fi.fname[0] == 0) return NULL; + memcpy(dir_ent.name, fi.fname, sizeof(fi.fname)); + return &dir_ent; +} + +int vfs_stat(vfs_t *vfs, const char *filename, vfs_stat_t *st) +{ + FILINFO f; + if (FR_OK != f_stat(filename, &f)) + { + return 1; + } + st->st_size = f.fsize; + st->st_mode = f.fattrib; + st->st_mtime.date = f.fdate; + st->st_mtime.time = f.ftime; + return 0; +} + +void vfs_close(vfs_t *vfs) +{ + if (vfs != &guard_for_the_whole_fs) + { + /* Close a file */ + f_close(vfs); + } + os_free(vfs); +} + +int vfs_write (void *buffer, int dummy, int len, vfs_file_t *file) +{ + unsigned int byteswritten; + FRESULT r = f_write(file, buffer, len, &byteswritten); + if (r != FR_OK) return 0; + return byteswritten; +} + +vfs_t *vfs_openfs(void) +{ + return &guard_for_the_whole_fs; +} + +vfs_file_t *vfs_open(vfs_t *vfs, const char *filename, const char *mode) +{ + vfs_file_t *f = (vfs_file_t *)os_malloc(sizeof(vfs_file_t)); + uint8 flags = 0; + while (*mode != '\0') + { + if (*mode == 'r') flags |= FA_READ; + if (*mode == 'w') flags |= FA_WRITE | FA_CREATE_ALWAYS; + mode++; + } + FRESULT r = f_open(f, filename, flags); + if (FR_OK != r) + { + os_free(f); + return NULL; + } + return f; +} + +char *vfs_getcwd(vfs_t *vfs, void *dummy1, int dummy2) +{ + char *cwd = (char *)os_malloc(255); + FRESULT r = f_getcwd(cwd, 255); + if (r != FR_OK) + { + os_free(cwd); + return NULL; + } + return cwd; +} + +vfs_dir_t *vfs_opendir(vfs_t *vfs, const char *path) +{ + vfs_dir_t *dir = (vfs_dir_t *)os_malloc(sizeof * dir); + FRESULT r = f_opendir(dir, path); + if (FR_OK != r) + { + os_free(dir); + return NULL; + } + return dir; +} + +void vfs_closedir(vfs_dir_t *dir) +{ + os_free(dir); +} + +struct tm dummy; +struct tm *gmtime(time_t *c_t) +{ + return &dummy; +} +#endif + +//eof + diff --git a/beken_os/beken378/app/ftp/vfs.h b/beken_os/beken378/app/ftp/vfs.h new file mode 100755 index 0000000..2986983 --- /dev/null +++ b/beken_os/beken378/app/ftp/vfs.h @@ -0,0 +1,89 @@ +/* Copyright (c) 2013, Philipp Tlke + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef INCLUDE_VFS_H +#define INCLUDE_VFS_H + +#include "ff.h" +#include + +#define vfs_load_plugin(x) +#define bcopy(src, dest, len) memmove(dest, src, len) + + +typedef struct +{ + short date; + short time; +} time_t; +typedef DIR vfs_dir_t; +typedef FIL vfs_file_t; +typedef struct +{ + long st_size; + char st_mode; + time_t st_mtime; +} vfs_stat_t; +typedef struct +{ + char name[13]; +} vfs_dirent_t; +typedef FIL vfs_t; + +struct tm +{ + int tm_year; + int tm_mon; + int tm_mday; + int tm_hour; + int tm_min; +}; + +#define time(x) +#define vfs_eof f_eof +#define VFS_ISDIR(st_mode) ((st_mode) & AM_DIR) +#define VFS_ISREG(st_mode) !((st_mode) & AM_DIR) +#define vfs_rename(vfs, from, to) f_rename(from, to) +#define VFS_IRWXU 0 +#define VFS_IRWXG 0 +#define VFS_IRWXO 0 +#define vfs_mkdir(vfs, name, mode) f_mkdir(name) +#define vfs_rmdir(vfs, name) f_unlink(name) +#define vfs_remove(vfs, name) f_unlink(name) +#define vfs_chdir(vfs, dir) f_chdir(dir) +char *vfs_getcwd(vfs_t *vfs, void *, int dummy); +int vfs_read (void *buffer, int dummy, int len, vfs_file_t *file); +int vfs_write (void *buffer, int dummy, int len, vfs_file_t *file); +vfs_dirent_t *vfs_readdir(vfs_dir_t *dir); +vfs_file_t *vfs_open(vfs_t *vfs, const char *filename, const char *mode); +vfs_t *vfs_openfs(void); +void vfs_close(vfs_t *vfs); +int vfs_stat(vfs_t *vfs, const char *filename, vfs_stat_t *st); +void vfs_closedir(vfs_dir_t *dir); +vfs_dir_t *vfs_opendir(vfs_t *vfs, const char *path); +struct tm *gmtime(time_t *c_t); + +#endif /* INCLUDE_VFS_H */ diff --git a/beken_os/beken378/app/http/http_flash.h b/beken_os/beken378/app/http/http_flash.h new file mode 100755 index 0000000..6fae0f8 --- /dev/null +++ b/beken_os/beken378/app/http/http_flash.h @@ -0,0 +1,23 @@ +#include "drv_model_pub.h" + +#define HTTP_WR_TO_FLASH 1 + +typedef struct http_data_st{ + UINT32 http_total; + UINT8 do_data; + #if HTTP_WR_TO_FLASH + UINT8 *wr_buf ; + UINT16 wr_last_len ; + UINT32 flash_address; + UINT8 *wr_tmp_buf; + #endif + DD_HANDLE flash_hdl; +}HTTP_DATA_ST; + +#define TCP_LEN_MAX 1460 +#define HTTP_FLASH_ADDR 0xff000 + +extern void store_block (unsigned block, uint8_t * src, unsigned len); +#define WR_BUF_MAX 1048 + +extern HTTP_DATA_ST *bk_http_ptr; diff --git a/beken_os/beken378/app/http/iot_export_errno.h b/beken_os/beken378/app/http/iot_export_errno.h new file mode 100755 index 0000000..c827c71 --- /dev/null +++ b/beken_os/beken378/app/http/iot_export_errno.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2015-2017 Alibaba Group Holding Limited + */ + +/* From utils_error.h */ +typedef enum IOT_RETURN_CODES { + ERROR_DEVICE_NOT_EXSIT = -311, + ERROR_NET_TIMEOUT = -310, + ERROR_CERT_VERIFY_FAIL = -309, + ERROR_NET_SETOPT_TIMEOUT = -308, + ERROR_NET_SOCKET = -307, + ERROR_NET_CONNECT = -306, + ERROR_NET_BIND = -305, + ERROR_NET_LISTEN = -304, + ERROR_NET_RECV = -303, + ERROR_NET_SEND = -302, + ERROR_NET_CONN = -301, + ERROR_NET_UNKNOWN_HOST = -300, + + MQTT_SUB_INFO_NOT_FOUND_ERROR = -43, + MQTT_PUSH_TO_LIST_ERROR = -42, + MQTT_TOPIC_FORMAT_ERROR = -41, + NETWORK_RECONNECT_TIMED_OUT_ERROR = -40,/** Returned when the Network is disconnected and the reconnect attempt has timed out */ + MQTT_CONNACK_UNKNOWN_ERROR = -39,/** Connect request failed with the server returning an unknown error */ + MQTT_CONANCK_UNACCEPTABLE_PROTOCOL_VERSION_ERROR = -38,/** Connect request failed with the server returning an unacceptable protocol version error */ + MQTT_CONNACK_IDENTIFIER_REJECTED_ERROR = -37,/** Connect request failed with the server returning an identifier rejected error */ + MQTT_CONNACK_SERVER_UNAVAILABLE_ERROR = -36,/** Connect request failed with the server returning an unavailable error */ + MQTT_CONNACK_BAD_USERDATA_ERROR = -35,/** Connect request failed with the server returning a bad userdata error */ + MQTT_CONNACK_NOT_AUTHORIZED_ERROR = -34,/** Connect request failed with the server failing to authenticate the request */ + MQTT_CONNECT_ERROR = -33, + MQTT_CREATE_THREAD_ERROR = -32, + MQTT_PING_PACKET_ERROR = -31, + MQTT_CONNECT_PACKET_ERROR = -30, + MQTT_CONNECT_ACK_PACKET_ERROR = -29, + MQTT_NETWORK_CONNECT_ERROR = -28, + MQTT_STATE_ERROR = -27, + MQTT_SUBSCRIBE_PACKET_ERROR = -26, + MQTT_SUBSCRIBE_ACK_PACKET_ERROR = -25, + MQTT_SUBSCRIBE_ACK_FAILURE = -24, + MQTT_SUBSCRIBE_QOS_ERROR = -23, + MQTT_UNSUBSCRIBE_PACKET_ERROR = -22, + MQTT_PUBLISH_PACKET_ERROR = -21, + MQTT_PUBLISH_QOS_ERROR = -20, + MQTT_PUBLISH_ACK_PACKET_ERROR = -19, + MQTT_PUBLISH_COMP_PACKET_ERROR = -18, + MQTT_PUBLISH_REC_PACKET_ERROR = -17, + MQTT_PUBLISH_REL_PACKET_ERROR = -16, + MQTT_UNSUBSCRIBE_ACK_PACKET_ERROR = -15, + MQTT_NETWORK_ERROR = -14, + MQTT_PUBLISH_ACK_TYPE_ERROR = -13, + + ERROR_SHADOW_NO_METHOD = -2008, + ERROR_SHADOW_UNDEF_TYPE = -2007, + ERROR_SHADOW_UPDATE_TIMEOUT = -2006, + ERROR_SHADOW_UPDATE_NACK = -2005, /**< Negative ACK */ + ERROR_SHADOW_NO_ATTRIBUTE = -2004, + ERROR_SHADOW_ATTR_NO_EXIST = -2003, /**< NO such attribute */ + ERROR_SHADOW_ATTR_EXIST = -2002, /**< attribute already exists */ + ERROR_SHADOW_WAIT_LIST_OVERFLOW = -2001, + ERROR_SHADOW_INVALID_STATE = -2000, + + ERROR_NO_MEM = -1016, + ERROR_CERTIFICATE_EXPIRED = -1015, + ERROR_MALLOC = -1014, + ERROR_NO_ENOUGH_MEM = -1013, /**< Writes more than size value. */ + + ERROR_NO_SUPPORT = -12, + ERROR_NO_PERSISTENCE = -11, + ERROR_HTTP_BREAK = -10, + ERROR_NULL_VALUE = -9, + ERROR_HTTP_CONN = -8, /**< Connection failed. */ + ERROR_HTTP_PARSE = -7, /**< A URL parse error occurred. */ + ERROR_HTTP_UNRESOLVED_DNS = -6, /**< Could not resolve the hostname. */ + ERROR_HTTP_PRTCL = -5, /**< A protocol error occurred. */ + ERROR_HTTP = -4, /**< An unknown error occurred. */ + ERROR_HTTP_CLOSED = -3, /**< Connection was closed by a remote host. */ + NULL_VALUE_ERROR = -2, + + FAIL_RETURN = -1, /**< generic error. */ + SUCCESS_RETURN = 0, + + + /* @value > 0, reserved for other usage */ + +} iotx_err_t; +/* From utils_error.h */ diff --git a/beken_os/beken378/app/http/lite-log.c b/beken_os/beken378/app/http/lite-log.c new file mode 100755 index 0000000..086eaa3 --- /dev/null +++ b/beken_os/beken378/app/http/lite-log.c @@ -0,0 +1,257 @@ +/* + * Copyright (C) 2015-2017 Alibaba Group Holding Limited + */ +#include "include.h" +#include "lite-log.h" +#include "lite-log_internal.h" +#include "uart_pub.h" +#include "str_pub.h" +#include "mem_pub.h" + + +#define LITE_HEXDUMP_DRAWLINE(start_mark, len, end_mark) \ + do { \ + int i; \ + \ + LITE_printf("%s", start_mark); \ + for(i = 0; i < len; ++i) { LITE_printf("-"); } \ + LITE_printf("%s", end_mark); \ + LITE_printf("\r\n"); \ + \ + } while(0) + +int LITE_hexdump(const char *title, const void *buff, const int len) +{ + int i, j, written; + unsigned char ascii[16 + 1] = {0}; + char header[64] = {0}; + unsigned char *buf = (unsigned char *)buff; + + LITE_snprintf(header, sizeof(header), "| %s: (len=%d) |\r\n", title, (int)len); + + LITE_HEXDUMP_DRAWLINE("+", os_strlen(header) - 4, "+"); + LITE_printf("%s", header); + LITE_printf("%s\r\n", HEXDUMP_SEP_LINE); + + written = 0; + for (i = 0; i < len; ++ i) { + if (i % 16 == 0) { + LITE_printf("| %08X: ", (unsigned int)(i + (long)buff)); + written += 8; + } + + LITE_printf("%02X", buf[i]); + written += 2; + + if (i % 2 == 1) { + LITE_printf(" "); + written += 1; + } + LITE_sprintf((char *__restrict__)ascii + i % 16, "%c", ((buf[i] >= ' ' && buf[i] <= '~') ? buf[i] : '.')); + + if (((i + 1) % 16 == 0) || (i == len - 1)) { + for (j = 0; j < 48 - written; ++j) { + LITE_printf(" "); + } + + LITE_printf(" %s", ascii); + LITE_printf("\r\n"); + + written = 0; + os_memset(ascii, 0, sizeof(ascii)); + } + } + LITE_printf("%s\r\n", HEXDUMP_SEP_LINE); + + return 0; +} + +#if defined(LITE_LOG_ENABLED) +static log_client logcb; + +static char *lvl_names[] = { + "emg", "crt", "err", "wrn", "inf", "dbg", +}; + +void LITE_syslog(const char *f, const int l, const int level, const char *fmt, ...) +{ + char *tmpbuf = logcb.text_buf; + char *o = tmpbuf; + int truncated = 0; + va_list ap; + + if (!os_strlen(LITE_get_logname()) || LITE_get_loglevel() < level || level < LOG_EMERG_LEVEL) { + return; + } + + LITE_printf(LOG_PREFIX_FMT, lvl_names[level], f, l); + + os_memset(tmpbuf, 0, sizeof(logcb.text_buf)); + va_start(ap, fmt); + o += vsnprintf(o, LOG_MSG_MAXLEN + 1, fmt, ap); + va_end(ap); + + if (o - tmpbuf > LOG_MSG_MAXLEN) { + o = tmpbuf + os_strlen(tmpbuf); + truncated = 1; + } + if (os_strlen(tmpbuf) == LOG_MSG_MAXLEN) { + truncated = 1; + } + + LITE_printf("%s", tmpbuf); + if (truncated) { + LITE_printf(" ..."); + } + + LITE_printf("\r\n"); + return; +} + +int LITE_log_enabled(void) +{ + return 1; +} + +void LITE_openlog(const char *ident) +{ + os_strncpy(logcb.name, ident, LOG_MOD_NAME_LEN); + logcb.name[LOG_MOD_NAME_LEN] = 0; + logcb.priority = 0; +} + +void LITE_closelog(void) +{ + os_strncpy(logcb.name, "", LOG_MOD_NAME_LEN); + logcb.name[LOG_MOD_NAME_LEN] = 0; + logcb.priority = 0; +} + +char *LITE_get_logname(void) +{ + return logcb.name; +} + +int LITE_get_loglevel(void) +{ + return logcb.priority; +} + +void LITE_set_loglevel(int pri) +{ + logcb.priority = pri; +} + +void LITE_rich_hexdump(const char *f, const int l, + const int level, + const char *buf_str, + const void *buf_ptr, + const int buf_len) +{ + if (LITE_get_loglevel() < level) { + return; + } + + LITE_printf(LOG_PREFIX_FMT, lvl_names[LITE_get_loglevel()], f, l); + LITE_printf("HEXDUMP %s @ %p[%d]\r\n", buf_str, buf_ptr, buf_len); + LITE_hexdump(buf_str, buf_ptr, buf_len); + + return; +} + +int log_multi_line_internal(const char *f, const int l, + const char *title, int level, char *payload, const char *mark) +{ + const char *pos; + const char *endl; + int i; + + if (LITE_get_loglevel() < level) { + return 1; + } + + LITE_printf("[%s] %s(%d): %s (Length: %d Bytes)\r\n", + lvl_names[LITE_get_loglevel()], f, l, title, (int)strlen(payload)); + + pos = payload; + while (pos && *pos) { + LITE_printf("%s ", mark); + + if (*pos == '\r') { + LITE_printf("\r\n"); + pos += 2; + continue; + } + + endl = os_strchr(pos + 1, '\r'); + if (endl == NULL) { + endl = pos; + do { + ++endl; + } while (*endl); + } + + for (i = 0; i < endl - pos; ++i) { + LITE_printf("%c", pos[i]); + } + LITE_printf("\r\n"); + + pos = *endl ? endl + 2 : 0; + } + + return 0; +} + +#else /* defined(LITE_LOG_ENABLED) */ +void LITE_syslog(const char *f, const int l, const int level, const char *fmt, ...) +{ + + return; +} + +int log_multi_line_internal(const char *f, const int l, + const char *title, + int level, + char *payload, + const char *mark) +{ + + return 0; +} + + +int LITE_log_enabled(void) +{ + return 0; +} +void LITE_openlog(const char *ident) +{ + return; +} +void LITE_closelog(void) +{ + return; +} +char *LITE_get_logname(void) +{ + return NULL; +} +int LITE_get_loglevel(void) +{ + return -1; +} +void LITE_set_loglevel(int lvl) +{ + return; +} +void LITE_rich_hexdump(const char *f, const int l, + const int level, + const char *buf_str, + const void *buf_ptr, + const int buf_len) +{ + return; +} + +#endif /* defined(LITE_LOG_ENABLED) */ + diff --git a/beken_os/beken378/app/http/lite-log.h b/beken_os/beken378/app/http/lite-log.h new file mode 100755 index 0000000..fbbfd96 --- /dev/null +++ b/beken_os/beken378/app/http/lite-log.h @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2015-2017 Alibaba Group Holding Limited + */ + +#ifndef __LITE_LOG_H__ +#define __LITE_LOG_H__ +#if defined(__cplusplus) +extern "C" { +#endif + +#include "include.h" +#include "arm_arch.h" +#include "uart_pub.h" +#include + + +#define LITE_printf bk_printf +#define LITE_sprintf sprintf +#define LITE_snprintf snprintf + +typedef enum _LOGLEVEL { + LOG_EMERG_LEVEL = 0, // OS system is unavailable + LOG_CRIT_LEVEL, // current application aborting + LOG_ERR_LEVEL, // current app-module error + LOG_WARNING_LEVEL, // using default parameters + LOG_INFO_LEVEL, // running messages + LOG_DEBUG_LEVEL, // debugging messages +} LOGLEVEL; + +void LITE_openlog(const char *ident); +void LITE_closelog(void); +int LITE_log_enabled(void); +char *LITE_get_logname(void); +int LITE_get_loglevel(void); +void LITE_set_loglevel(int level); +int LITE_hexdump(const char *title, const void *buf, const int len); + +void LITE_syslog(const char *f, const int l, const int level, const char *fmt, ...); +#define log_emerg(args...) LITE_syslog(__FUNCTION__, __LINE__, LOG_EMERG_LEVEL, args) +#define log_crit(args...) LITE_syslog(__FUNCTION__, __LINE__, LOG_CRIT_LEVEL, args) +#define log_err(args...) LITE_syslog(__FUNCTION__, __LINE__, LOG_ERR_LEVEL, args) +#define log_warning(args...) LITE_syslog(__FUNCTION__, __LINE__, LOG_WARNING_LEVEL, args) +#define log_info(args...) LITE_syslog(__FUNCTION__, __LINE__, LOG_INFO_LEVEL, args) +#define log_debug(args...) LITE_syslog(__FUNCTION__, __LINE__, LOG_DEBUG_LEVEL, args) + +int log_multi_line_internal(const char *f, const int l, + const char *title, int level, char *payload, const char *mark); +#define log_multi_line(level, title, fmt, payload, mark) \ + log_multi_line_internal(__func__, __LINE__, title, level, payload, mark) + +void LITE_rich_hexdump(const char *f, const int l, + const int level, + const char *buf_str, + const void *buf_ptr, + const int buf_len +); +#define HEXDUMP_DEBUG(buf, len) \ + LITE_rich_hexdump(__func__, __LINE__, LOG_DEBUG_LEVEL, #buf, (const void *)buf, (const int)len) + +#define HEXDUMP_INFO(buf, len) \ + LITE_rich_hexdump(__func__, __LINE__, LOG_INFO_LEVEL, #buf, (const void *)buf, (const int)len) + + +#if defined(__cplusplus) +} +#endif +#endif /* __LITE_LOG_H__ */ diff --git a/beken_os/beken378/app/http/lite-log_internal.h b/beken_os/beken378/app/http/lite-log_internal.h new file mode 100755 index 0000000..6c19a64 --- /dev/null +++ b/beken_os/beken378/app/http/lite-log_internal.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2015-2017 Alibaba Group Holding Limited + */ + +#ifndef __LITE_LOG_INTERNAL_H__ +#define __LITE_LOG_INTERNAL_H__ + +#include +#include "lite-log.h" + + +//#define LITE_LOG_ENABLED + +#define LOG_MSG_MAXLEN (255) +#define LOG_MOD_NAME_LEN (7) +#define LOG_PREFIX_FMT "[%s] %s(%d): " +#define HEXDUMP_SEP_LINE "+" \ + "-----------------------" \ + "-----------------------" \ + "-----------------------" + +#if defined(_PLATFORM_IS_LINUX_) +#undef LOG_MSG_MAXLEN +#define LOG_MSG_MAXLEN (1023) +#endif + +typedef struct { + char name[LOG_MOD_NAME_LEN + 1]; + int priority; + char text_buf[LOG_MSG_MAXLEN + 1]; +} log_client; + +#endif /* __LITE_LOG_INTERNAL_H__ */ diff --git a/beken_os/beken378/app/http/utils_httpc.c b/beken_os/beken378/app/http/utils_httpc.c new file mode 100755 index 0000000..abcea71 --- /dev/null +++ b/beken_os/beken378/app/http/utils_httpc.c @@ -0,0 +1,1018 @@ +/* + * Copyright (C) 2015-2017 Alibaba Group Holding Limited + */ + +#include +#include +#include "include.h" +#include "utils_timer.h" +#include "lite-log.h" +#include "utils_httpc.h" +#include "uart_pub.h" +#include "flash_pub.h" +#include "mem_pub.h" +#include "str_pub.h" + + +#define HTTPCLIENT_MIN(x,y) (((x)<(y))?(x):(y)) +#define HTTPCLIENT_MAX(x,y) (((x)>(y))?(x):(y)) + +#define HTTPCLIENT_AUTHB_SIZE 128 + +#define HTTPCLIENT_CHUNK_SIZE 256 +#define HTTPCLIENT_SEND_BUF_SIZE 2048 + +#define HTTPCLIENT_MAX_HOST_LEN 64 +#define HTTPCLIENT_MAX_URL_LEN 2048 + +#define HTTP_RETRIEVE_MORE_DATA (1) /**< More data needs to be retrieved. */ + +extern void flash_protection_op(UINT8 mode,PROTECT_TYPE type); + +#if CFG_SUPPORT_OTA_HTTP +#define HTTP_FLASH_WR_BUF_MAX WR_BUF_MAX +#else +#define HTTP_FLASH_WR_BUF_MAX 1024 +#endif + + +HTTP_DATA_ST bk_http = { + .http_total = 0, + .do_data = 0, +#if HTTP_WR_TO_FLASH + .wr_buf = NULL, + .wr_last_len = 0, + .flash_address = HTTP_FLASH_ADDR, + .wr_tmp_buf = NULL, +#endif +}; +HTTP_DATA_ST *bk_http_ptr = &bk_http; +static UINT32 ota_wr_block = 0; + +static int httpclient_parse_host(const char *url, char *host, uint32_t maxhost_len); +static int httpclient_parse_url(const char *url, char *scheme, uint32_t max_scheme_len, char *host, + uint32_t maxhost_len, int *port, char *path, uint32_t max_path_len); +static int httpclient_conn(httpclient_t *client); +static int httpclient_recv(httpclient_t *client, char *buf, int min_len, int max_len, int *p_read_len, + uint32_t timeout); +static int httpclient_retrieve_content(httpclient_t *client, char *data, int len, uint32_t timeout, + httpclient_data_t *client_data); +static int httpclient_response_parse(httpclient_t *client, char *data, int len, uint32_t timeout, + httpclient_data_t *client_data); + +static void httpclient_base64enc(char *out, const char *in) +{ + const char code[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; + int i = 0, x = 0, l = 0; + + for (; *in; in++) { + x = x << 8 | *in; + for (l += 8; l >= 6; l -= 6) { + out[i++] = code[(x >> (l - 6)) & 0x3f]; + } + } + if (l > 0) { + x <<= 6 - l; + out[i++] = code[x & 0x3f]; + } + for (; i % 4;) { + out[i++] = '='; + } + out[i] = '\0'; +} + +int httpclient_conn(httpclient_t *client) +{ + if (0 != client->net.connect(&client->net)) { + log_err("establish connection failed"); + return ERROR_HTTP_CONN; + } + + return SUCCESS_RETURN; +} + +int httpclient_parse_url(const char *url, char *scheme, uint32_t max_scheme_len, char *host, uint32_t maxhost_len, + int *port, char *path, uint32_t max_path_len) +{ + char *scheme_ptr = (char *) url; + char *host_ptr = (char *) os_strstr(url, "://"); + uint32_t host_len = 0; + uint32_t path_len; + //char *port_ptr; + char *path_ptr; + char *fragment_ptr; + + if (host_ptr == NULL) { + log_err("Could not find host"); + return ERROR_HTTP_PARSE; /* URL is invalid */ + } + + if (max_scheme_len < host_ptr - scheme_ptr + 1) { + /* including NULL-terminating char */ + log_err("Scheme str is too small (%u >= %u)", max_scheme_len, (uint32_t)(host_ptr - scheme_ptr + 1)); + return ERROR_HTTP_PARSE; + } + os_memcpy(scheme, scheme_ptr, host_ptr - scheme_ptr); + scheme[host_ptr - scheme_ptr] = '\0'; + + host_ptr += 3; + + *port = 0; + + path_ptr = os_strchr(host_ptr, '/'); + if (NULL == path_ptr) { + log_err("invalid path"); + return -1; + } + + if (host_len == 0) { + host_len = path_ptr - host_ptr; + } + + if (maxhost_len < host_len + 1) { + /* including NULL-terminating char */ + log_err("Host str is too long (host_len(%d) >= max_len(%d))", host_len + 1, maxhost_len); + return ERROR_HTTP_PARSE; + } + os_memcpy(host, host_ptr, host_len); + host[host_len] = '\0'; + + fragment_ptr = os_strchr(host_ptr, '#'); + if (fragment_ptr != NULL) { + path_len = fragment_ptr - path_ptr; + } else { + path_len = os_strlen(path_ptr); + } + + if (max_path_len < path_len + 1) { + /* including NULL-terminating char */ + log_err("Path str is too small (%d >= %d)", max_path_len, path_len + 1); + return ERROR_HTTP_PARSE; + } + os_memcpy(path, path_ptr, path_len); + path[path_len] = '\0'; + + return SUCCESS_RETURN; +} + +int httpclient_parse_host(const char *url, char *host, uint32_t maxhost_len) +{ + const char *host_ptr = (const char *) os_strstr(url, "://"); + uint32_t host_len = 0; + char *path_ptr; + + if (host_ptr == NULL) { + log_err("Could not find host"); + return ERROR_HTTP_PARSE; /* URL is invalid */ + } + host_ptr += 3; + + path_ptr = os_strchr(host_ptr, '/'); + if (host_len == 0) { + host_len = path_ptr - host_ptr; + } + + if (maxhost_len < host_len + 1) { + /* including NULL-terminating char */ + log_err("Host str is too small (%d >= %d)", maxhost_len, host_len + 1); + return ERROR_HTTP_PARSE; + } + os_memcpy(host, host_ptr, host_len); + host[host_len] = '\0'; + + return SUCCESS_RETURN; +} + +int httpclient_get_info(httpclient_t *client, char *send_buf, int *send_idx, char *buf, + uint32_t len) /* 0 on success, err code on failure */ +{ + int ret; + int cp_len; + int idx = *send_idx; + + if (len == 0) { + len = os_strlen(buf); + } + + do { + if ((HTTPCLIENT_SEND_BUF_SIZE - idx) >= len) { + cp_len = len; + } else { + cp_len = HTTPCLIENT_SEND_BUF_SIZE - idx; + } + + os_memcpy(send_buf + idx, buf, cp_len); + idx += cp_len; + len -= cp_len; + + if (idx == HTTPCLIENT_SEND_BUF_SIZE) { + // if (client->remote_port == HTTPS_PORT) + // { + // WRITE_IOT_ERROR_LOG("send buffer overflow"); + // return ERROR_HTTP; + // } + //ret = httpclient_tcp_send_all(client->handle, send_buf, HTTPCLIENT_SEND_BUF_SIZE); + ret = client->net.write(&client->net, send_buf, HTTPCLIENT_SEND_BUF_SIZE, 5000); + if (ret) { + return (ret); + } + } + } while (len); + + *send_idx = idx; + return SUCCESS_RETURN; +} + +void httpclient_set_custom_header(httpclient_t *client, char *header) +{ + client->header = header; +} + +int httpclient_basic_auth(httpclient_t *client, char *user, char *password) +{ + if ((os_strlen(user) + os_strlen(password)) >= HTTPCLIENT_AUTHB_SIZE) { + return ERROR_HTTP; + } + client->auth_user = user; + client->auth_password = password; + return SUCCESS_RETURN; +} + +int httpclient_send_auth(httpclient_t *client, char *send_buf, int *send_idx) +{ + char b_auth[(int)((HTTPCLIENT_AUTHB_SIZE + 3) * 4 / 3 + 1)]; + char base64buff[HTTPCLIENT_AUTHB_SIZE + 3]; + + httpclient_get_info(client, send_buf, send_idx, "Authorization: Basic ", 0); + sprintf(base64buff, "%s:%s", client->auth_user, client->auth_password); + log_debug("bAuth: %s", base64buff) ; + httpclient_base64enc(b_auth, base64buff); + b_auth[os_strlen(b_auth) + 1] = '\0'; + b_auth[os_strlen(b_auth)] = '\n'; + log_debug("b_auth:%s", b_auth) ; + httpclient_get_info(client, send_buf, send_idx, b_auth, 0); + return SUCCESS_RETURN; +} + +int httpclient_send_header(httpclient_t *client, const char *url, int method, httpclient_data_t *client_data) +{ + char scheme[8] = { 0 }; + //char host[HTTPCLIENT_MAX_HOST_LEN] = { 0 }; + //char path[HTTPCLIENT_MAX_URL_LEN] = { 0 }; + char *host;//[HTTPCLIENT_MAX_HOST_LEN] = { 0 }; + char *path;//[HTTPCLIENT_MAX_URL_LEN] = { 0 }; + int len; + //char send_buf[HTTPCLIENT_SEND_BUF_SIZE] = { 0 }; + //char buf[HTTPCLIENT_SEND_BUF_SIZE] = { 0 }; + char *send_buf; + char *buf; + char *meth = (method == HTTPCLIENT_GET) ? "GET" : (method == HTTPCLIENT_POST) ? "POST" : + (method == HTTPCLIENT_PUT) ? "PUT" : (method == HTTPCLIENT_DELETE) ? "DELETE" : + (method == HTTPCLIENT_HEAD) ? "HEAD" : ""; + int ret; + int port; + int rc = SUCCESS_RETURN; + + if (NULL == (host = (char *)os_malloc(HTTPCLIENT_MAX_HOST_LEN))) { + log_err("not enough memory"); + return FAIL_RETURN; + } + if (NULL == (path = (char *)os_malloc(HTTPCLIENT_MAX_HOST_LEN))) { + log_err("not enough memory"); + rc = FAIL_RETURN; + goto GO_ERR_3; + } + if (NULL == (send_buf = (char *)os_malloc(HTTPCLIENT_SEND_BUF_SIZE))) { + log_err("not enough memory"); + rc = FAIL_RETURN; + goto GO_ERR_2; + } + if (NULL == (buf = (char *)os_malloc(HTTPCLIENT_SEND_BUF_SIZE))) { + log_err("not enough memory"); + rc = FAIL_RETURN; + goto GO_ERR_1; + } + /* First we need to parse the url (http[s]://host[:port][/[path]]) */ + int res = httpclient_parse_url(url, scheme, sizeof(scheme), host, HTTPCLIENT_MAX_HOST_LEN, &port, path, HTTPCLIENT_MAX_HOST_LEN); + if (res != SUCCESS_RETURN) { + log_err("httpclient_parse_url returned %d", res); + //return res; + rc = res; + goto GO_ERR; + } + + //if (client->remote_port == 0) + //{ + if (os_strcmp(scheme, "http") == 0) { + //client->remote_port = HTTP_PORT; + } else if (os_strcmp(scheme, "https") == 0) { + //client->remote_port = HTTPS_PORT; + } + //} + + /* Send request */ + os_memset(send_buf, 0, HTTPCLIENT_SEND_BUF_SIZE); + os_memset(buf, 0, HTTPCLIENT_SEND_BUF_SIZE); + len = 0; /* Reset send buffer */ + + snprintf(buf, HTTPCLIENT_SEND_BUF_SIZE, "%s %s HTTP/1.1\r\nHost: %s\r\n", meth, path, host); /* Write request */ + ret = httpclient_get_info(client, send_buf, &len, buf, os_strlen(buf)); + if (ret) { + log_err("Could not write request"); + //return ERROR_HTTP_CONN; + rc = ERROR_HTTP_CONN; + goto GO_ERR; + } + + /* Send all headers */ + if (client->auth_user) { + httpclient_send_auth(client, send_buf, &len); /* send out Basic Auth header */ + } + + /* Add user header information */ + if (client->header) { + httpclient_get_info(client, send_buf, &len, (char *) client->header, os_strlen(client->header)); + } + + if (client_data->post_buf != NULL) { + snprintf(buf, HTTPCLIENT_SEND_BUF_SIZE, "Content-Length: %d\r\n", client_data->post_buf_len); + httpclient_get_info(client, send_buf, &len, buf, os_strlen(buf)); + + if (client_data->post_content_type != NULL) { + snprintf(buf, HTTPCLIENT_SEND_BUF_SIZE, "Content-Type: %s\r\n", client_data->post_content_type); + httpclient_get_info(client, send_buf, &len, buf, os_strlen(buf)); + } + } + + /* Close headers */ + httpclient_get_info(client, send_buf, &len, "\r\n", 0); + + log_multi_line(LOG_DEBUG_LEVEL, "REQUEST", "%s", send_buf, ">"); + + //ret = httpclient_tcp_send_all(client->net.handle, send_buf, len); + ret = client->net.write(&client->net, send_buf, len, 5000); + if (ret > 0) { + log_debug("Written %d bytes", ret); + } else if (ret == 0) { + log_err("ret == 0,Connection was closed by server"); + //return ERROR_HTTP_CLOSED; /* Connection was closed by server */ + rc = ERROR_HTTP_CLOSED; + } else { + log_err("Connection error (send returned %d)", ret); + //return ERROR_HTTP_CONN; + rc = ERROR_HTTP_CONN; + } +GO_ERR: + os_free(buf); +GO_ERR_1: + os_free(send_buf); +GO_ERR_2: + os_free(path); +GO_ERR_3: + os_free(host); + return rc;//SUCCESS_RETURN; +} + +int httpclient_send_userdata(httpclient_t *client, httpclient_data_t *client_data) +{ + int ret = 0; + + if (client_data->post_buf && client_data->post_buf_len) { + log_debug("client_data->post_buf: %s", client_data->post_buf); + { + //ret = httpclient_tcp_send_all(client->handle, (char *)client_data->post_buf, client_data->post_buf_len); + ret = client->net.write(&client->net, (char *)client_data->post_buf, client_data->post_buf_len, 5000); + if (ret > 0) { + log_debug("Written %d bytes", ret); + } else if (ret == 0) { + log_err("ret == 0,Connection was closed by server"); + return ERROR_HTTP_CLOSED; /* Connection was closed by server */ + } else { + log_err("Connection error (send returned %d)", ret); + return ERROR_HTTP_CONN; + } + } + } + + return SUCCESS_RETURN; +} + +/* 0 on success, err code on failure */ +int httpclient_recv(httpclient_t *client, char *buf, int min_len, int max_len, int *p_read_len, uint32_t timeout_ms) +{ + int ret = 0; + iotx_time_t timer; + + iotx_time_init(&timer); + utils_time_countdown_ms(&timer, timeout_ms); + + *p_read_len = 0; + + ret = client->net.read(&client->net, buf, max_len, iotx_time_left(&timer)); + //log_debug("Recv: | %s", buf); + + if (ret > 0) { + *p_read_len = ret; + } else if (ret == 0) { + //timeout + return 0; + } else if (-1 == ret) { + log_info("Connection closed."); + return ERROR_HTTP_CONN; + } else { + log_err("Connection error (recv returned %d)", ret); + return ERROR_HTTP_CONN; + } + log_info("%u bytes has been read", *p_read_len); + return 0; + + +} + + +#if HTTP_WR_TO_FLASH + +void http_flash_wr ( UINT8 *src, unsigned len) +{ + UINT32 param , or_crc; + UINT32 param1; + GLOBAL_INT_DECLARATION(); + + if(bk_http_ptr->flash_address % 0x1000 == 0) + { + param = bk_http_ptr->flash_address; + GLOBAL_INT_DISABLE(); + ddev_control(bk_http_ptr->flash_hdl, CMD_FLASH_ERASE_SECTOR, (void *)¶m); + GLOBAL_INT_RESTORE(); + } + + if((u32)bk_http_ptr->flash_address >= 0x200000 || (u32)bk_http_ptr->flash_address < 0x27000) + { + os_printf ("err_addr:%x \r\n", bk_http_ptr->flash_address); + return; + } + + if((u32)bk_http_ptr->flash_address < 0x400000) + { + + + GLOBAL_INT_DISABLE(); + ddev_write(bk_http_ptr->flash_hdl, src, len, (u32)bk_http_ptr->flash_address); + GLOBAL_INT_RESTORE(); + if(bk_http_ptr->wr_tmp_buf) + { + GLOBAL_INT_DISABLE(); + ddev_read(bk_http_ptr->flash_hdl, bk_http_ptr->wr_tmp_buf, len , (u32)bk_http_ptr->flash_address); + GLOBAL_INT_RESTORE(); + if(!os_memcmp(src , bk_http_ptr->wr_tmp_buf, len )) + { + } + else + { + os_printf ("wr flash write err\n"); + } + } + + bk_http_ptr->flash_address += len; + //os_printf("ad %x.\r\n",bk_http_ptr->flash_address); + } + +} + + +void http_flash_init(void) +{ + UINT32 status; + bk_http_ptr->wr_buf = NULL; + bk_http_ptr->wr_tmp_buf = NULL; + + if(!bk_http_ptr->wr_buf) + { + bk_http_ptr->wr_buf = os_malloc(HTTP_FLASH_WR_BUF_MAX * sizeof(char)); + if(! bk_http_ptr->wr_buf) + { + os_printf("wr_buf malloc err\r\n"); + } + } + + if(!bk_http_ptr->wr_tmp_buf) + { + bk_http_ptr->wr_tmp_buf = os_malloc(HTTP_FLASH_WR_BUF_MAX * sizeof(char)); + if(! bk_http_ptr->wr_tmp_buf) + { + os_printf("wr_tmp_buf malloc err\r\n"); + } + } + + bk_http_ptr->flash_hdl = ddev_open(FLASH_DEV_NAME, &status, 0); + ASSERT(DD_HANDLE_UNVALID != bk_http_ptr->flash_hdl); + + bk_http_ptr->wr_last_len = 0; + ota_wr_block = 0; + bk_http_ptr->flash_address = 0xff000; + flash_protection_op(FLASH_XTX_16M_SR_WRITE_ENABLE, FLASH_PROTECT_NONE); + +} + +void http_flash_deinit(void) +{ + os_free(bk_http_ptr->wr_buf); + os_free(bk_http_ptr->wr_tmp_buf); + bk_http_ptr->wr_buf = NULL; + bk_http_ptr->wr_tmp_buf = NULL; + bk_http_ptr->wr_last_len = 0; + ota_wr_block = 0; + ddev_close(bk_http_ptr->flash_hdl); + flash_protection_op(FLASH_XTX_16M_SR_WRITE_ENABLE, FLASH_UNPROTECT_LAST_BLOCK); +} + +void http_wr_to_flash(char *page, UINT32 len) +{ + UINT8 *tmp; + UINT32 w_l = 0,i=0; + + i =0; + tmp = (UINT8 *)page; + while(i < len ) + { + w_l = min(len - i, HTTP_FLASH_WR_BUF_MAX-bk_http_ptr->wr_last_len); + os_memcpy(bk_http_ptr->wr_buf+bk_http_ptr->wr_last_len,tmp+i,w_l); + i+=w_l; + bk_http_ptr->wr_last_len+=w_l; + if(bk_http_ptr->wr_last_len>=HTTP_FLASH_WR_BUF_MAX) + { + os_printf ("."); + #if CFG_SUPPORT_OTA_HTTP //support bk ota format + store_block(ota_wr_block, bk_http_ptr->wr_buf, HTTP_FLASH_WR_BUF_MAX); + ota_wr_block++; + #else //direct wrtie to flash + http_flash_wr(bk_http_ptr->wr_buf, HTTP_FLASH_WR_BUF_MAX); + #endif + bk_http_ptr->wr_last_len = 0; + } + } +} +#endif + + +void http_data_process(char *buf, UINT32 len) +{ + #if HTTP_WR_TO_FLASH + http_wr_to_flash(buf,len); + #else + os_printf("d"); + //os_printf("len:%d\r\n",len); + #endif +} + +int httpclient_retrieve_content(httpclient_t *client, char *data, int len, uint32_t timeout_ms, + httpclient_data_t *client_data) +{ + int count = 0; + int templen = 0; + int crlf_pos; + iotx_time_t timer; + char * b_data = NULL; + + iotx_time_init(&timer); + utils_time_countdown_ms(&timer, timeout_ms); + + /* Receive data */ + log_debug("Current data: %s", data); + + client_data->is_more = true; + + if (client_data->response_content_len == -1 && client_data->is_chunked == false) { + while (true) { + int ret, max_len; + if (count + len < client_data->response_buf_len - 1) { + os_memcpy(client_data->response_buf + count, data, len); + count += len; + client_data->response_buf[count] = '\0'; + } else { + os_memcpy(client_data->response_buf + count, data, client_data->response_buf_len - 1 - count); + client_data->response_buf[client_data->response_buf_len - 1] = '\0'; + return HTTP_RETRIEVE_MORE_DATA; + } + + max_len = HTTPCLIENT_MIN(HTTPCLIENT_CHUNK_SIZE - 1, client_data->response_buf_len - 1 - count); + ret = httpclient_recv(client, data, 1, max_len, &len, iotx_time_left(&timer)); + + /* Receive data */ + log_debug("data len: %d %d", len, count); + + if (ret == ERROR_HTTP_CONN) { + log_debug("ret == ERROR_HTTP_CONN"); + return ret; + } + + if (len == 0) { + /* read no more data */ + log_debug("no more len == 0"); + client_data->is_more = false; + return SUCCESS_RETURN; + } + } + } + + while (true) { + uint32_t readLen = 0; + + if (client_data->is_chunked && client_data->retrieve_len <= 0) { + /* Read chunk header */ + bool foundCrlf; + int n; + do { + foundCrlf = false; + crlf_pos = 0; + data[len] = 0; + if (len >= 2) { + for (; crlf_pos < len - 2; crlf_pos++) { + if (data[crlf_pos] == '\r' && data[crlf_pos + 1] == '\n') { + foundCrlf = true; + break; + } + } + } + if (!foundCrlf) { + /* Try to read more */ + if (len < HTTPCLIENT_CHUNK_SIZE) { + int new_trf_len, ret; + ret = httpclient_recv(client, + data + len, + 0, + HTTPCLIENT_CHUNK_SIZE - len - 1, + &new_trf_len, + iotx_time_left(&timer)); + len += new_trf_len; + if (ret == ERROR_HTTP_CONN) { + return ret; + } else { + continue; + } + } else { + return ERROR_HTTP; + } + } + } while (!foundCrlf); + data[crlf_pos] = '\0'; + n = sscanf(data, "%x", &readLen);/* chunk length */ + client_data->retrieve_len = readLen; + client_data->response_content_len += client_data->retrieve_len; + if (n != 1) { + log_err("Could not read chunk length"); + return ERROR_HTTP_UNRESOLVED_DNS; + } + + os_memmove(data, &data[crlf_pos + 2], len - (crlf_pos + 2)); /* Not need to move NULL-terminating char any more */ + len -= (crlf_pos + 2); + + if (readLen == 0) { + /* Last chunk */ + client_data->is_more = false; + log_debug("no more (last chunk)"); + break; + } + } else { + readLen = client_data->retrieve_len; + } + + log_debug("Total-Payload: %d Bytes; Read: %d Bytes", readLen, len); + #if HTTP_WR_TO_FLASH + http_flash_init(); + http_wr_to_flash(data,len); + #endif + + b_data = os_malloc((TCP_LEN_MAX+1) * sizeof(char)); + bk_http_ptr->do_data = 1; + bk_http_ptr->http_total = readLen - len; + do { + templen = HTTPCLIENT_MIN(len, readLen); + if (count + templen < client_data->response_buf_len - 1) { + count += templen; + client_data->response_buf[count] = '\0'; + client_data->retrieve_len -= templen; + } else { + client_data->response_buf[client_data->response_buf_len - 1] = '\0'; + client_data->retrieve_len -= (client_data->response_buf_len - 1 - count); + return HTTP_RETRIEVE_MORE_DATA; + } + + if (len > readLen) { + log_debug("memmove %d %d %d\n", readLen, len, client_data->retrieve_len); + os_memmove(b_data, &b_data[readLen], len - readLen); /* chunk case, read between two chunks */ + len -= readLen; + readLen = 0; + client_data->retrieve_len = 0; + } else { + readLen -= len; + } + + if (readLen) { + int ret; + int max_len = HTTPCLIENT_MIN(TCP_LEN_MAX, client_data->response_buf_len - 1 - count); + max_len = HTTPCLIENT_MIN(max_len, readLen); + + ret = httpclient_recv(client, b_data, 1, max_len, &len, iotx_time_left(&timer)); + if (ret == ERROR_HTTP_CONN) { + return ret; + } + } + } while (readLen); + + bk_http_ptr->do_data = 0; + os_free(b_data); + b_data = NULL; + + if (client_data->is_chunked) { + if (len < 2) { + int new_trf_len, ret; + /* Read missing chars to find end of chunk */ + ret = httpclient_recv(client, data + len, 2 - len, HTTPCLIENT_CHUNK_SIZE - len - 1, &new_trf_len, + iotx_time_left(&timer)); + if (ret == ERROR_HTTP_CONN) { + return ret; + } + len += new_trf_len; + } + if ((data[0] != '\r') || (data[1] != '\n')) { + log_err("Format error, %s", data); /* after memmove, the beginning of next chunk */ + return ERROR_HTTP_UNRESOLVED_DNS; + } + os_memmove(data, &data[2], len - 2); /* remove the \r\n */ + len -= 2; + } else { + log_debug("no more (content-length)"); +#if HTTP_WR_TO_FLASH + #if CFG_SUPPORT_OTA_HTTP //support bk ota format + store_block(ota_wr_block, bk_http_ptr->wr_buf, bk_http_ptr->wr_last_len); + #else //direct wrtie to flash + http_flash_wr(bk_http_ptr->wr_buf, bk_http_ptr->wr_last_len); + #endif + http_flash_deinit(); +#endif + client_data->is_more = false; + break; + } + + } + + return SUCCESS_RETURN; +} + +int httpclient_response_parse(httpclient_t *client, char *data, int len, uint32_t timeout_ms, + httpclient_data_t *client_data) +{ + int crlf_pos; + iotx_time_t timer; + + iotx_time_init(&timer); + utils_time_countdown_ms(&timer, timeout_ms); + + client_data->response_content_len = -1; + + char *crlf_ptr = os_strstr(data, "\r\n"); + if (crlf_ptr == NULL) { + log_err("\r\n not found"); + return ERROR_HTTP_UNRESOLVED_DNS; + } + + crlf_pos = crlf_ptr - data; + data[crlf_pos] = '\0'; + + /* Parse HTTP response */ + if (sscanf(data, "HTTP/%*d.%*d %d %*[^\r\n]", &(client->response_code)) != 1) { + /* Cannot match string, error */ + log_err("Not a correct HTTP answer : %s\n", data); + return ERROR_HTTP_UNRESOLVED_DNS; + } + + if ((client->response_code < 200) || (client->response_code >= 400)) { + /* Did not return a 2xx code; TODO fetch headers/(&data?) anyway and implement a mean of writing/reading headers */ + log_warning("Response code %d", client->response_code); + } + + log_debug("Reading headers%s", data); + + os_memmove(data, &data[crlf_pos + 2], len - (crlf_pos + 2) + 1); /* Be sure to move NULL-terminating char as well */ + len -= (crlf_pos + 2); + + client_data->is_chunked = false; + + /* Now get headers */ + while (true) { + char key[32]; + char value[32]; + int n; + + key[31] = '\0'; + value[31] = '\0'; + + crlf_ptr = os_strstr(data, "\r\n"); + if (crlf_ptr == NULL) { + if (len < HTTPCLIENT_CHUNK_SIZE - 1) { + int new_trf_len, ret; + ret = httpclient_recv(client, data + len, 1, HTTPCLIENT_CHUNK_SIZE - len - 1, &new_trf_len, iotx_time_left(&timer)); + len += new_trf_len; + data[len] = '\0'; + log_debug("Read %d chars; In buf: [%s]", new_trf_len, data); + if (ret == ERROR_HTTP_CONN) { + return ret; + } else { + continue; + } + } else { + log_debug("header len > chunksize"); + return ERROR_HTTP; + } + } + + crlf_pos = crlf_ptr - data; + if (crlf_pos == 0) { + /* End of headers */ + os_memmove(data, &data[2], len - 2 + 1); /* Be sure to move NULL-terminating char as well */ + len -= 2; + break; + } + + data[crlf_pos] = '\0'; + + n = sscanf(data, "%31[^:]: %31[^\r\n]", key, value); + if (n == 2) { + log_debug("Read header : %s: %s", key, value); + if (!os_strcmp(key, "Content-Length")) { + sscanf(value, "%d", &(client_data->response_content_len)); + client_data->retrieve_len = client_data->response_content_len; + } else if (!os_strcmp(key, "Transfer-Encoding")) { + if (!os_strcmp(value, "Chunked") || !os_strcmp(value, "chunked")) { + client_data->is_chunked = true; + client_data->response_content_len = 0; + client_data->retrieve_len = 0; + } + } + os_memmove(data, &data[crlf_pos + 2], len - (crlf_pos + 2) + 1); /* Be sure to move NULL-terminating char as well */ + len -= (crlf_pos + 2); + + } else { + log_err("Could not parse header"); + return ERROR_HTTP; + } + } + + if(client->response_code != 200) + { + os_printf("Could not found\r\n"); + return MQTT_SUB_INFO_NOT_FOUND_ERROR; + } + + return httpclient_retrieve_content(client, data, len, iotx_time_left(&timer), client_data); +} + +iotx_err_t httpclient_connect(httpclient_t *client) +{ + int ret = ERROR_HTTP_CONN; + + client->net.handle = 0; + + ret = httpclient_conn(client); + // if (0 == ret) + // { + // client->remote_port = HTTP_PORT; + // } + + return ret; +} + +iotx_err_t httpclient_send_request(httpclient_t *client, const char *url, int method, httpclient_data_t *client_data) +{ + int ret = ERROR_HTTP_CONN; + + if (0 == client->net.handle) { + log_debug("not connection have been established"); + return ret; + } + + ret = httpclient_send_header(client, url, method, client_data); + if (ret != 0) { + log_err("httpclient_send_header is error,ret = %d", ret); + return ret; + } + + if (method == HTTPCLIENT_POST || method == HTTPCLIENT_PUT) { + ret = httpclient_send_userdata(client, client_data); + } + + return ret; +} + +iotx_err_t httpclient_recv_response(httpclient_t *client, uint32_t timeout_ms, httpclient_data_t *client_data) +{ + int reclen = 0, ret = ERROR_HTTP_CONN; + char buf[HTTPCLIENT_CHUNK_SIZE] = { 0 }; + iotx_time_t timer; + + iotx_time_init(&timer); + utils_time_countdown_ms(&timer, timeout_ms); + + if (0 == client->net.handle) { + log_debug("not connection have been established"); + return ret; + } + + + if (client_data->is_more) { + client_data->response_buf[0] = '\0'; + ret = httpclient_retrieve_content(client, buf, reclen, iotx_time_left(&timer), client_data); + } else { + client_data->is_more = 1; + ret = httpclient_recv(client, buf, 1, HTTPCLIENT_CHUNK_SIZE - 1, &reclen, iotx_time_left(&timer)); + if (ret != 0) { + return ret; + } + + buf[reclen] = '\0'; + + if (reclen) { + log_multi_line(LOG_DEBUG_LEVEL, "RESPONSE", "%s", buf, "<"); + ret = httpclient_response_parse(client, buf, reclen, iotx_time_left(&timer), client_data); + } + } + + return ret; +} + +void httpclient_close(httpclient_t *client) +{ + if (client->net.handle > 0) { + client->net.disconnect(&client->net); + } + client->net.handle = 0; +} + +int httpclient_common(httpclient_t *client, const char *url, int port, const char *ca_crt, int method, + uint32_t timeout_ms, + httpclient_data_t *client_data) +{ + iotx_time_t timer; + int ret = 0; + char host[HTTPCLIENT_MAX_HOST_LEN] = { 0 }; + + if (0 == client->net.handle) { + //Establish connection if no. + httpclient_parse_host(url, host, sizeof(host)); + log_debug("host: '%s', port: %d", host, port); + + iotx_net_init(&client->net, host, port, ca_crt); + + ret = httpclient_connect(client); + if (0 != ret) { + log_err("httpclient_connect is error,ret = %d", ret); + httpclient_close(client); + return ret; + } + + ret = httpclient_send_request(client, url, method, client_data); + if (0 != ret) { + log_err("httpclient_send_request is error,ret = %d", ret); + httpclient_close(client); + return ret; + } + } + + iotx_time_init(&timer); + utils_time_countdown_ms(&timer, timeout_ms); + + if ((NULL != client_data->response_buf) + || (0 != client_data->response_buf_len)) { + ret = httpclient_recv_response(client, iotx_time_left(&timer), client_data); + if (ret < 0) { + log_err("httpclient_recv_response is error,ret = %d", ret); + httpclient_close(client); + return ret; + } + } + + if (! client_data->is_more) { + //Close the HTTP if no more data. + log_info("close http channel"); + httpclient_close(client); + } + return (ret >= 0) ? 0 : -1; +} + +int utils_get_response_code(httpclient_t *client) +{ + return client->response_code; +} + +iotx_err_t iotx_post( + httpclient_t *client, + const char *url, + int port, + const char *ca_crt, + uint32_t timeout_ms, + httpclient_data_t *client_data) +{ + return httpclient_common(client, url, port, ca_crt, HTTPCLIENT_POST, timeout_ms, client_data); +} + diff --git a/beken_os/beken378/app/http/utils_httpc.h b/beken_os/beken378/app/http/utils_httpc.h new file mode 100755 index 0000000..49e9fb8 --- /dev/null +++ b/beken_os/beken378/app/http/utils_httpc.h @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2015-2017 Alibaba Group Holding Limited + */ + +#ifndef _UTILS_HTTPC_H_ +#define _UTILS_HTTPC_H_ + +#include "iot_export_errno.h" +#include "utils_net.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @addtogroup HttpClient + * @{ + * HttpClient API implements the client-side of HTTP/1.1. It provides base interfaces to execute an HTTP request on a given URL. It also supports HTTPS (HTTP over TLS) to provide secure communication.\n + * @section HttpClient_Usage_Chapter How to use this module + * In this release, MediaTek provides two types of APIs: high level APIs and low level APIs.\n + * - \b The \b high \b level \b APIs + * - Enables to execute a single HTTP request on a given URL. + * - Call #httpclient_get(), #httpclient_post(), #httpclient_put() or #httpclient_delete() to get, post, put or delete and HTTP request.\n + * - \b The \b low \b level \b APIs + * - Enables to execute more than one HTTP requests during a Keep-Alive connection. Keep-alive is the idea of using a single TCP connection to send and receive multiple HTTP requests/responses, as opposed to opening a new connection for every single request/response pair. + * - Step1: Call #httpclient_connect() to connect to a remote server. + * - Step2: Call #httpclient_send_request() to send an HTTP request to the server. + * - Step3: Call #httpclient_recv_response() to receive an HTTP response from the server. + * - Step4: Repeat Steps 2 and 3 to execute more requests. + * - Step5: Call #httpclient_close() to close the connection. + * - Sample code: Please refer to the example under /project/mt7687_hdk/apps/http_client/http_client_keepalive folder. + */ + +/** @defgroup httpclient_define Define + * @{ + */ +/** @brief This macro defines the HTTP port. */ +#define HTTP_PORT 80 + +/** @brief This macro defines the HTTPS port. */ +#define HTTPS_PORT 443 +/** + * @} + */ + +/** @defgroup httpclient_enum Enum + * @{ + */ +/** @brief This enumeration defines the HTTP request type. */ +typedef enum { + HTTPCLIENT_GET, + HTTPCLIENT_POST, + HTTPCLIENT_PUT, + HTTPCLIENT_DELETE, + HTTPCLIENT_HEAD +} HTTPCLIENT_REQUEST_TYPE; + +/** @defgroup httpclient_struct Struct + * @{ + */ +/** @brief This structure defines the httpclient_t structure. */ +typedef struct { + //intptr_t handle; /**< handle of TCP connection or SSL connection. */ + int remote_port; /**< HTTP or HTTPS port. */ + utils_network_t net; + int response_code; /**< Response code. */ + char *header; /**< Custom header. */ + char *auth_user; /**< Username for basic authentication. */ + char *auth_password; /**< Password for basic authentication. */ +} httpclient_t; + +/** @brief This structure defines the HTTP data structure. */ +typedef struct { + bool is_more; /**< Indicates if more data needs to be retrieved. */ + bool is_chunked; /**< Response data is encoded in portions/chunks.*/ + int retrieve_len; /**< Content length to be retrieved. */ + uint32_t response_content_len; /**< Response content length. */ + uint32_t post_buf_len; /**< Post data length. */ + uint32_t response_buf_len; /**< Response buffer length. */ + char *post_content_type; /**< Content type of the post data. */ + char *post_buf; /**< User data to be posted. */ + char *response_buf; /**< Buffer to store the response data. */ +} httpclient_data_t; + + + +/** + * @brief This function executes a POST request on a given URL. It blocks until completion. + * @param[in] client is a pointer to the #httpclient_t. + * @param[in] url is the URL to run the request. + * @param[in] port is #HTTP_PORT or #HTTPS_PORT. + * @param[in, out] client_data is a pointer to the #httpclient_data_t instance to collect the data returned by the request. It also contains the data to be posted. + * @return Please refer to #HTTPCLIENT_RESULT. + * @par HttpClient Post Example + * @code + * char *url = "https://api.mediatek.com/mcs/v2/devices/D0n2yhrl/datapoints.csv"; + * char *header = "deviceKey:FZoo0S07CpwUHcrt\r\n"; + * char *content_type = "text/csv"; + * char *post_data = "1,,I am string!"; + * httpclient_t client = {0}; + * httpclient_data_t client_data = {0}; + * char *buf = NULL; + * buf = pvPortMalloc(BUF_SIZE); + * if (buf == NULL) { + * printf("Malloc failed.\r\n"); + * return; + * } + * memset(buf, 0, sizeof(buf)); + * client_data.response_buf = buf; //Sets a buffer to store the result. + * client_data.response_buf_len = BUF_SIZE; //Sets the buffer size. + * httpclient_set_custom_header(&client, header); //Sets the custom header if needed. + * client_data.post_buf = post_data; //Sets the user data to be posted. + * client_data.post_buf_len = strlen(post_data); //Sets the post data length. + * client_data.post_content_type = content_type; //Sets the content type. + * httpclient_post(&client, url, HTTPS_PORT, &client_data); + * printf("Data received: %s\r\n", client_data.response_buf); + * @endcode + */ +iotx_err_t iotx_post( + httpclient_t *client, + const char *url, + int port, + const char *ca_crt, + uint32_t timeout, + httpclient_data_t *client_data); + + +#ifdef __cplusplus +} +#endif + +#endif /* __HTTPCLIENT_H__ */ + diff --git a/beken_os/beken378/app/http/utils_net.c b/beken_os/beken378/app/http/utils_net.c new file mode 100755 index 0000000..23d74bb --- /dev/null +++ b/beken_os/beken378/app/http/utils_net.c @@ -0,0 +1,341 @@ +/* + * Copyright (C) 2015-2017 Alibaba Group Holding Limited + */ + +#include + +#include "include.h" +#include "utils_net.h" +#include "lite-log.h" +#include "errno.h" +#include "lwip/sockets.h" +#include "lwip/netdb.h" +#include "utils_timer.h" +#include "str_pub.h" +#include "mem_pub.h" + + +uintptr_t HAL_TCP_Establish(const char *host, uint16_t port) +{ + struct addrinfo hints; + struct addrinfo *addrInfoList = NULL; + struct addrinfo *cur = NULL; + int fd = 0; + int rc = 0; + char service[6]; + + os_memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; //only IPv4 + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + sprintf(service, "%u", port); + + if ((rc = getaddrinfo(host, service, &hints, &addrInfoList)) != 0) { + log_err("getaddrinfo error"); + return 0; + } + + for (cur = addrInfoList; cur != NULL; cur = cur->ai_next) { + if (cur->ai_family != AF_INET) { + log_err("socket type error"); + rc = 0; + continue; + } + + fd = socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol); + if (fd < 0) { + log_err("create socket error"); + rc = 0; + continue; + } + + if (connect(fd, cur->ai_addr, cur->ai_addrlen) == 0) { + rc = fd; + break; + } + + close(fd); + log_err("connect error"); + rc = 0; + } + + if (0 == rc){ + log_err("fail to establish tcp"); + } else { + log_err("success to establish tcp, fd=%d", rc); + } + freeaddrinfo(addrInfoList); + + return (uintptr_t)rc; +} + + +int32_t HAL_TCP_Destroy(uintptr_t fd) +{ + int rc; + + //Shutdown both send and receive operations. + rc = shutdown((int) fd, 2); + if (0 != rc) { + log_err("shutdown error"); + return -1; + } + + rc = close((int) fd); + if (0 != rc) { + log_err("closesocket error"); + return -1; + } + + return 0; +} + + +int32_t HAL_TCP_Write(uintptr_t fd, const char *buf, uint32_t len, uint32_t timeout_ms) +{ + int ret, err_code; + uint32_t len_sent; + uint64_t t_end, t_left; + fd_set sets; + + t_end = utils_time_get_ms() + timeout_ms; + len_sent = 0; + err_code = 0; + ret = 1; //send one time if timeout_ms is value 0 + + do { + t_left = utils_time_left(t_end, utils_time_get_ms()); + + if (0 != t_left) { + struct timeval timeout; + + FD_ZERO( &sets ); + FD_SET(fd, &sets); + + timeout.tv_sec = t_left / 1000; + timeout.tv_usec = (t_left % 1000) * 1000; + + ret = select(fd + 1, NULL, &sets, NULL, &timeout); + if (ret > 0) { + if (0 == FD_ISSET(fd, &sets)) { + log_err("Should NOT arrive"); + //If timeout in next loop, it will not sent any data + ret = 0; + continue; + } + } else if (0 == ret) { + log_err("select-write timeout %lu", fd); + break; + } else { + if (EINTR == errno) { + log_err("EINTR be caught"); + continue; + } + + err_code = -1; + log_err("select-write fail"); + break; + } + } + + if (ret > 0) { + ret = send(fd, buf + len_sent, len - len_sent, 0); + if (ret > 0) { + len_sent += ret; + } else if (0 == ret) { + log_err("No data be sent"); + } else { + if (EINTR == errno) { + log_err("EINTR be caught"); + continue; + } + + err_code = -1; + log_err("send fail"); + break; + } + } + } while((len_sent < len) && (utils_time_left(t_end, utils_time_get_ms()) > 0)); + + return len_sent; +} + + +int32_t HAL_TCP_Read(uintptr_t fd, char *buf, uint32_t len, uint32_t timeout_ms) +{ + int ret, err_code,data_over; + uint32_t len_recv; + uint64_t t_end, t_left; + fd_set sets; + struct timeval timeout; + + t_end = utils_time_get_ms( ) + timeout_ms ; + len_recv = 0; + err_code = 0; + + data_over = 0; + + do { + t_left = utils_time_left(t_end, utils_time_get_ms()); + if (0 == t_left && bk_http_ptr->do_data == 0) { + break; + } + FD_ZERO( &sets ); + FD_SET(fd, &sets); + + timeout.tv_sec = t_left / 1000; + timeout.tv_usec = (t_left % 1000) * 1000; + + ret = select(fd + 1, &sets, NULL, NULL, NULL); + if ( FD_ISSET( fd, &sets ) ) + { + if (ret > 0) { + ret = recv(fd, buf, len, 0); + if (ret > 0) { + if(ret < len) + { + data_over = 1; + } + if(bk_http_ptr->do_data == 1) + { + http_data_process(buf,ret); + } + + len_recv += ret; + } else if (0 == ret) { + log_err("connection is closed"); + err_code = -1; + break; + } else { + if (EINTR == errno) { + log_err("EINTR be caught"); + continue; + } + log_err("send fail"); + err_code = -2; + break; + } + } else if (0 == ret) { + break; + } else { + if (EINTR == errno) { + log_err("EINTR be caught-------\r\n"); + //continue; + } + log_err("select-recv fail"); + err_code = -2; + break; + } + } + else + { + } + }while((bk_http_ptr->do_data == 1 && len_recv < bk_http_ptr->http_total) || ((len_recv < len) && (0 == data_over))); + + //priority to return data bytes if any data be received from TCP connection. + //It will get error code on next calling + return (0 != len_recv) ? len_recv : err_code; +} + +/*** TCP connection ***/ +int read_tcp(utils_network_pt pNetwork, char *buffer, uint32_t len, uint32_t timeout_ms) +{ + return HAL_TCP_Read(pNetwork->handle, buffer, len, timeout_ms); +} + + +static int write_tcp(utils_network_pt pNetwork, const char *buffer, uint32_t len, uint32_t timeout_ms) +{ + return HAL_TCP_Write(pNetwork->handle, buffer, len, timeout_ms); +} + +static int disconnect_tcp(utils_network_pt pNetwork) +{ + if (0 == pNetwork->handle) { + return -1; + } + + HAL_TCP_Destroy(pNetwork->handle); + pNetwork->handle = 0; + return 0; +} + + +static int connect_tcp(utils_network_pt pNetwork) +{ + if (NULL == pNetwork) { + log_err("network is null"); + return 1; + } + + pNetwork->handle = HAL_TCP_Establish(pNetwork->pHostAddress, pNetwork->port); + if (0 == pNetwork->handle) { + return -1; + } + + return 0; +} + +/****** network interface ******/ + +int utils_net_read(utils_network_pt pNetwork, char *buffer, uint32_t len, uint32_t timeout_ms) +{ + if (NULL == pNetwork->ca_crt) { //TCP connection + return read_tcp(pNetwork, buffer, len, timeout_ms); + } + + return 0; +} + + +int utils_net_write(utils_network_pt pNetwork, const char *buffer, uint32_t len, uint32_t timeout_ms) +{ + if (NULL == pNetwork->ca_crt) { //TCP connection + return write_tcp(pNetwork, buffer, len, timeout_ms); + } + return 0; +} + + +int iotx_net_disconnect(utils_network_pt pNetwork) +{ + if (NULL == pNetwork->ca_crt) { //TCP connection + return disconnect_tcp(pNetwork); + } + return 0; +} + + +int iotx_net_connect(utils_network_pt pNetwork) +{ + if (NULL == pNetwork->ca_crt) { //TCP connection + return connect_tcp(pNetwork); + } + return 0; +} + + +int iotx_net_init(utils_network_pt pNetwork, const char *host, uint16_t port, const char *ca_crt) +{ + if (!pNetwork || !host) { + log_err("parameter error! pNetwork=%p, host = %p", pNetwork, host); + return -1; + } + pNetwork->pHostAddress = host; + pNetwork->port = port; + pNetwork->ca_crt = ca_crt; + + if (NULL == ca_crt) { + pNetwork->ca_crt_len = 0; + } else { + pNetwork->ca_crt_len = os_strlen(ca_crt); + } + + pNetwork->handle = 0; + pNetwork->read = utils_net_read; + pNetwork->write = utils_net_write; + pNetwork->disconnect = iotx_net_disconnect; + pNetwork->connect = iotx_net_connect; + + return 0; +} diff --git a/beken_os/beken378/app/http/utils_net.h b/beken_os/beken378/app/http/utils_net.h new file mode 100755 index 0000000..6da95a9 --- /dev/null +++ b/beken_os/beken378/app/http/utils_net.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2015-2017 Alibaba Group Holding Limited + */ +#ifndef _UTILS_NET_H_ +#define _UTILS_NET_H_ +#include "http_flash.h" +#include "flash_pub.h" + +/** + * @brief The structure of network connection(TCP or SSL). + * The user has to allocate memory for this structure. + */ + +struct utils_network; +typedef struct utils_network utils_network_t, *utils_network_pt; + +struct utils_network { + const char *pHostAddress; + uint16_t port; + uint16_t ca_crt_len; + + /**< NULL, TCP connection; NOT NULL, SSL connection */ + const char *ca_crt; + + /**< connection handle: 0, NOT connection; NOT 0, handle of the connection */ + uintptr_t handle; + + /**< Read data from server function pointer. */ + int (*read)(utils_network_pt, char *, uint32_t, uint32_t); + + /**< Send data to server function pointer. */ + int (*write)(utils_network_pt, const char *, uint32_t, uint32_t); + + /**< Disconnect the network */ + int (*disconnect)(utils_network_pt); + + /**< Establish the network */ + int (*connect)(utils_network_pt); +}; + + +int utils_net_read(utils_network_pt pNetwork, char *buffer, uint32_t len, uint32_t timeout_ms); +int utils_net_write(utils_network_pt pNetwork, const char *buffer, uint32_t len, uint32_t timeout_ms); +int iotx_net_disconnect(utils_network_pt pNetwork); +int iotx_net_connect(utils_network_pt pNetwork); +int iotx_net_init(utils_network_pt pNetwork, const char *host, uint16_t port, const char *ca_crt); +extern void http_data_process(char *buf, UINT32 len); + +#endif /* IOTX_COMMON_NET_H */ diff --git a/beken_os/beken378/app/http/utils_timer.c b/beken_os/beken378/app/http/utils_timer.c new file mode 100755 index 0000000..8f5cf66 --- /dev/null +++ b/beken_os/beken378/app/http/utils_timer.c @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2015-2017 Alibaba Group Holding Limited + */ +#include "include.h" +#include "lite-log.h" +#include "utils_timer.h" +#include "hal_machw.h" +#include "uart_pub.h" + + +void iotx_time_start(iotx_time_t *timer) +{ + if (!timer) { + return; + } + + timer->time = utils_time_get_ms(); +} + +uint32_t utils_time_spend(iotx_time_t *start) +{ + uint32_t now, res; + + if (!start) { + return 0; + } + + now = utils_time_get_ms(); + res = now - start->time; + return res; +} + +uint32_t iotx_time_left(iotx_time_t *end) +{ + uint32_t now, res; + + if (!end) { + return 0; + } + + if (utils_time_is_expired(end)) { + return 0; + } + + now = utils_time_get_ms(); + res = end->time - now; + return res; +} + +uint32_t utils_time_is_expired(iotx_time_t *timer) +{ + uint32_t cur_time; + + if (!timer) { + return 1; + } + + cur_time = utils_time_get_ms(); + /* + * WARNING: Do NOT change the following code until you know exactly what it do! + * + * check whether it reach destination time or not. + */ + if ((cur_time - timer->time) < (UINT32_MAX / 2)) { + return 1; + } else { + return 0; + } +} + +void iotx_time_init(iotx_time_t *timer) +{ + if (!timer) { + return; + } + + timer->time = 0; +} + +void utils_time_countdown_ms(iotx_time_t *timer, uint32_t millisecond) +{ + if (!timer) { + return; + } + + timer->time = utils_time_get_ms() + millisecond; +} + +uint32_t utils_time_get_ms(void) +{ + + return hal_machw_time()/1000; +} + +uint64_t utils_time_left(uint64_t t_end, uint64_t t_now) +{ + uint64_t t_left; + + return (1!=(hal_machw_time_past(t_end*1000))); +} + diff --git a/beken_os/beken378/app/http/utils_timer.h b/beken_os/beken378/app/http/utils_timer.h new file mode 100755 index 0000000..1184263 --- /dev/null +++ b/beken_os/beken378/app/http/utils_timer.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2015-2017 Alibaba Group Holding Limited + */ + +#ifndef _UTILS_TIMER_H_ +#define _UTILS_TIMER_H_ + +//#include "iot_import.h" + +typedef struct { + uint32_t time; +} iotx_time_t; + + +void iotx_time_start(iotx_time_t *timer); + +uint32_t utils_time_spend(iotx_time_t *start); + +uint32_t iotx_time_left(iotx_time_t *end); + +uint32_t utils_time_is_expired(iotx_time_t *timer); + +void iotx_time_init(iotx_time_t *timer); + +void utils_time_countdown_ms(iotx_time_t *timer, uint32_t millisecond); + +uint32_t utils_time_get_ms(void); + +uint64_t utils_time_left(uint64_t t_end, uint64_t t_now); + +#endif /* _IOTX_COMMON_TIMER_H_ */ diff --git a/beken_os/beken378/app/led/app_led.c b/beken_os/beken378/app/led/app_led.c new file mode 100755 index 0000000..339db9c --- /dev/null +++ b/beken_os/beken378/app/led/app_led.c @@ -0,0 +1,227 @@ +#include "include.h" + +// led show spi data state for tianzhiheng +#if CFG_SUPPORT_TIANZHIHENG_DRONE +#include "FreeRTOS.h" +#include "task.h" +#include "rtos_pub.h" +#include "error.h" +#include "fake_clock_pub.h" +#include "mem_pub.h" +#include "gpio_pub.h" +#include "app_led.h" + + +#include "uart_pub.h" +#define LED_DEBUG +#ifdef LED_DEBUG +#define LED_PRT os_printf +#define LED_WARN warning_prf +#define LED_FATAL fatal_prf +#else +#define LED_PRT null_prf +#define LED_WARN null_prf +#define LED_FATAL null_prf +#endif + +#define LED_QITEM_COUNT (2) +#define LED_GPIO_INDEX GPIO29 // GPIO19 +#define LED_INITIAL_VAL 1 +#define LED_ON_VAL 0 // LOW LED ON +#define LED_DISCONNECT_VAL 125 // ms +#define LED_MONITOR_VAL 50 // ms +#define LED_SOFTAP_VAL 250 // ms + +typedef struct led_st +{ + beken_timer_t led_timer; + DEV_STATE state; + GPIO_INDEX gpio_idx; +} LED_ST, LED_PTR; + +typedef struct led_message +{ + DEV_STATE led_msg; +} LED_MSG_T; + +static LED_ST ledctr; +beken_queue_t led_msg_que = NULL; +xTaskHandle led_thread_handle = NULL; + +void app_led_send_msg(DEV_STATE new_msg) +{ + OSStatus ret; + LED_MSG_T msg; + + if(led_msg_que) + { + msg.led_msg = new_msg; + + ret = rtos_push_to_queue(&led_msg_que, &msg, BEKEN_NO_WAIT); + if(kNoErr != ret) + { + os_printf("app_led_send_msg failed\r\n"); + } + } +} + +static void app_led_timer_poll_handler(void) +{ + OSStatus err; + + bk_gpio_output_reverse(ledctr.gpio_idx); + + err = rtos_reload_timer(&ledctr.led_timer); + ASSERT(kNoErr == err); +} + +static void app_led_timer_handler(void *data) +{ + app_led_send_msg(TIMER_POLL); +} + +static void app_led_poll_handler(DEV_STATE next_sta) +{ + uint32_t intval = 0; + OSStatus err; + + //LED_PRT("state:%d, next_sta:%d\r\n", ledctr.state, next_sta); + + if(ledctr.state == next_sta) + return; + + err = rtos_stop_timer(&ledctr.led_timer); + ASSERT(kNoErr == err); + + switch(next_sta) + { + case STA_NONE: + break; + + case POWER_ON: + case LED_DISCONNECT: + { + intval = LED_DISCONNECT_VAL; + ledctr.state = LED_DISCONNECT; + break; + } + + case MONITOR_MODE: + { + intval = LED_MONITOR_VAL; + ledctr.state = MONITOR_MODE; + break; + } + + case SOFTAP_MODE: + { + intval = LED_SOFTAP_VAL; + ledctr.state = SOFTAP_MODE; + break; + } + + case LED_CONNECT: + { + intval = 0; + ledctr.state = LED_CONNECT; + bk_gpio_output(ledctr.gpio_idx, LED_ON_VAL); + break; + } + + default: + break; + } + + if(intval) + { + err = rtos_change_period(&ledctr.led_timer, intval); + ASSERT(kNoErr == err); + } +} + +static void app_led_main( beken_thread_arg_t data ) +{ + OSStatus err; + + os_memset(&ledctr, 0, sizeof(LED_ST)); + ledctr.state = STA_NONE; + + ledctr.gpio_idx = LED_GPIO_INDEX; + + bk_gpio_config_output(ledctr.gpio_idx); + bk_gpio_output(ledctr.gpio_idx, LED_INITIAL_VAL); + + err = rtos_init_timer(&ledctr.led_timer, + 1 * 1000, + app_led_timer_handler, + (void *)0); + ASSERT(kNoErr == err); + + err = rtos_start_timer(&ledctr.led_timer); + ASSERT(kNoErr == err); + + while(1) + { + LED_MSG_T msg; + err = rtos_pop_from_queue(&led_msg_que, &msg, BEKEN_WAIT_FOREVER); + if(kNoErr == err) + { + switch(msg.led_msg) + { + case TIMER_POLL: + app_led_timer_poll_handler(); + break; + default: + app_led_poll_handler(msg.led_msg); + break; + } + } + } + +app_led_exit: + LED_PRT("app_led_main exit\r\n"); + + rtos_deinit_queue(led_msg_que); + led_msg_que = NULL; + + led_thread_handle = NULL; + rtos_delete_thread(NULL); + +} + +UINT32 app_led_init(void) +{ + int ret; + + LED_PRT("app_led_init %d\r\n"); + if((!led_thread_handle) && (!led_msg_que)) + { + ret = rtos_init_queue(&led_msg_que, + "led_queue", + sizeof(LED_MSG_T), + LED_QITEM_COUNT); + if (kNoErr != ret) + { + LED_PRT("temp detect ceate queue failed\r\n"); + return kGeneralErr; + } + + ret = rtos_create_thread(&led_thread_handle, + BEKEN_DEFAULT_WORKER_PRIORITY, + "app led", + (beken_thread_function_t)app_led_main, + 1024, + NULL); + if (ret != kNoErr) + { + rtos_deinit_queue(led_msg_que); + led_msg_que = NULL; + LED_PRT("Error: Failed to create app_led_init: %d\r\n", ret); + return kGeneralErr; + } + } + + return kNoErr; +} +#endif + diff --git a/beken_os/beken378/app/led/app_led.h b/beken_os/beken378/app/led/app_led.h new file mode 100755 index 0000000..37b1c68 --- /dev/null +++ b/beken_os/beken378/app/led/app_led.h @@ -0,0 +1,19 @@ +#ifndef __APP_LED_H__ +#define __APP_LED_H__ + +typedef enum +{ + STA_NONE = 0, + POWER_ON, + LED_CONNECT, + LED_DISCONNECT, + MONITOR_MODE, + SOFTAP_MODE, + TIMER_POLL, +} DEV_STATE; + + +UINT32 app_led_init(void); +void app_led_send_msg(DEV_STATE new_msg); + +#endif diff --git a/beken_os/beken378/app/net_work/app_drone.c b/beken_os/beken378/app/net_work/app_drone.c new file mode 100755 index 0000000..5afbcdc --- /dev/null +++ b/beken_os/beken378/app/net_work/app_drone.c @@ -0,0 +1,544 @@ +#include "include.h" +#include "common.h" +#include "uart_pub.h" +#include "mem_pub.h" + +#include "task.h" +#include "rtos_pub.h" +#include "error.h" + +#include "app_lwip_udp.h" +#include "app_lwip_tcp.h" +#include "app_led.h" + +#include "wlan_ui_pub.h" +#include "ieee802_11_demo.h" +#include "rw_pub.h" +#include "app_drone.h" + +#include "param_config.h" +#include "drv_model_pub.h" +#include "flash_pub.h" + +#include "inet.h" +#include "ieee802_11_defs.h" + +#if CFG_SUPPORT_TIANZHIHENG_DRONE +#define APP_DRONE_DEBUG 1 +#if APP_DRONE_DEBUG +#define APP_DRONE_PRT warning_prf +#define APP_DRONE_WARN warning_prf +#define APP_DRONE_FATAL fatal_prf +#else +#define APP_DRONE_PRT null_prf +#define APP_DRONE_WARN null_prf +#define APP_DRONE_FATAL null_prf +#endif + +#define APP_DRONE_QITEM_COUNT 4 +#define APP_DRONE_TIMER_INTVAL 500 // ms +#define CONFIG_ADDR_START 0xbd000 + +typedef enum +{ + DS_WIFI_DISCONECTED = 0, + DS_WIFI_CONECTED, + DS_APP_DISCONECTED, + DS_APP_CONECTED, +} DRONE_STATUS; + +typedef struct temp_message +{ + u32 dmsg; +}DRONE_MSG_T; + +typedef struct app_drone_st +{ + xTaskHandle thread_hdl; + beken_queue_t msg_que; + beken_timer_t timer; + DRONE_STATUS status; +}APP_DRONE_ST, *APP_DRONE_PTR; + +enum{ + ARCH_CONFIG_GENERAL, + ARCH_CONFIG_AP, + ARCH_CONFIG_STA, + ARCH_CONFIG_MISC, +}; + +enum{ + GENERAL_TYPE_ROLE, + GENERAL_TYPE_DHCP, + GENERAL_TYPE_IP, + GENERAL_TYPE_MASK, + GENERAL_TYPE_GW, +}; + +enum{ + AP_TYPE_BSSID, + AP_TYPE_SSID, + AP_TYPE_CHANNEL, + AP_TYPE_MODE, + AP_TYPE_PASSWD, +}; + +typedef struct head_param{ + u32 type; + u32 len; +}head_param_t; + +APP_DRONE_PTR g_drone = NULL; + +static int app_drone_get_general_paramters(general_param_t *general); +static int app_drone_get_ap_paramters(ap_param_t *ap); + +static u32 app_drone_timer_poll(void) +{ + u8 sta_num = 0; + + //APP_DRONE_PRT("timer_handler %d\r\n", sta_num); + + if(sta_num) { + if(g_drone->status == DS_WIFI_DISCONECTED) + app_drone_send_msg(DMSG_WIFI_CONECTED); + } else { + if(g_drone->status != DS_WIFI_DISCONECTED) + app_drone_send_msg(DMSG_WIFI_DISCONECTED); + } + + return 0; +} + +void app_drone_send_msg(u32 new_msg) +{ + OSStatus ret; + DRONE_MSG_T msg; + + if(g_drone && g_drone->msg_que) + { + msg.dmsg = new_msg; + + ret = rtos_push_to_queue(&g_drone->msg_que, &msg, BEKEN_NO_WAIT); + if(kNoErr != ret) + { + os_printf("app_drone_send_msg failed\r\n"); + } + } +} + +static void app_drone_timer_handler(void *data) +{ + app_drone_send_msg(DMSG_TIMER_POLL); +} + +static int app_drone_rw_event_func(enum rw_evt_type evt_type, void *data) +{ + struct rw_evt_payload *evt_payload = (struct rw_evt_payload *)data; + + if(evt_type == RW_EVT_AP_CONNECTED) { + APP_DRONE_PRT("RW_EVT_AP_CONNECTED-(mac="MACSTR")\r\n", MAC2STR(evt_payload->mac)); + if(g_drone->status == DS_WIFI_DISCONECTED) + app_drone_send_msg(DMSG_WIFI_CONECTED); + } else if(evt_type == RW_EVT_AP_DISCONNECTED) { + APP_DRONE_PRT("RW_EVT_AP_DISCONNECTED-(mac="MACSTR")\r\n", MAC2STR(evt_payload->mac)); + if(g_drone->status != DS_WIFI_DISCONECTED) + app_drone_send_msg(DMSG_WIFI_DISCONECTED); + } + + return 0; +} + +static int app_drone_setup(void) +{ + #define APP_DRONE_DEF_SSID "WIFI_UPV_000000" + #define APP_DRONE_DEF_NET_IP "192.168.4.151" + #define APP_DRONE_DEF_NET_MASK "255.255.255.0" + #define APP_DRONE_DEF_NET_GW "192.168.4.151" + #define APP_DRONE_DEF_CHANNEL 1 + + general_param_t general; + ap_param_t ap_info; + network_InitTypeDef_st wNetConfig; + int len; + u8 *mac; + + os_memset(&general, 0, sizeof(general_param_t)); + os_memset(&ap_info, 0, sizeof(ap_param_t)); + os_memset(&wNetConfig, 0x0, sizeof(network_InitTypeDef_st)); + + if(app_drone_get_general_paramters(&general) == -1) { + APP_DRONE_PRT("no flash configuration, use default\r\n"); + general.role = 1, + general.dhcp_enable = 1, + + os_strcpy((char *)wNetConfig.local_ip_addr, APP_DRONE_DEF_NET_IP); + os_strcpy((char *)wNetConfig.net_mask, APP_DRONE_DEF_NET_MASK); + os_strcpy((char *)wNetConfig.dns_server_ip_addr, APP_DRONE_DEF_NET_GW); + } else { + APP_DRONE_PRT("read flash configuration:\r\n"); + APP_DRONE_PRT("general: %d,%d,%08x,%08x,%08x\r\n", + general.role, + general.dhcp_enable, + general.ip_addr, + general.ip_mask, + general.ip_gw); + + general.ip_addr = htonl(general.ip_addr); + general.ip_mask = htonl(general.ip_mask); + general.ip_gw = htonl(general.ip_gw); + + os_strcpy((char *)wNetConfig.local_ip_addr, inet_ntoa(general.ip_addr)); + os_strcpy((char *)wNetConfig.net_mask, inet_ntoa(general.ip_mask)); + os_strcpy((char *)wNetConfig.dns_server_ip_addr, inet_ntoa(general.ip_gw)); + } + + if(app_drone_get_ap_paramters(&ap_info) == -1) { + APP_DRONE_PRT("no flash configuration, use default\r\n"); + mac = (u8*)&ap_info.bssid.array; + wifi_get_mac_address(mac, CONFIG_ROLE_AP); + ap_info.chann = APP_DRONE_DEF_CHANNEL; + ap_info.cipher_suite = 0; + os_memcpy(ap_info.ssid.array, APP_DRONE_DEF_SSID, os_strlen(APP_DRONE_DEF_SSID)); + ap_info.key_len = 0; + os_memset(&ap_info.key, 0, 65); + } else { + // first load mac addr from flash + wifi_get_mac_address(NULL, 0); + mac = (u8*)&ap_info.bssid.array; + APP_DRONE_PRT("ap: %02x:%02x:%02x:%02x:%02x:%02x,%d,%d,%s,%d,%s\r\n", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], + ap_info.chann, + ap_info.cipher_suite, + ap_info.ssid.array, + ap_info.key_len, + ap_info.key); + + wifi_set_mac_address(mac); + } + bk_wlan_ap_set_default_channel(ap_info.chann); + + len = os_strlen(ap_info.ssid.array); + if(SSID_MAX_LEN < len) + { + APP_DRONE_FATAL("ssid name more than 32 Bytes\r\n"); + return -1; + } + + os_strcpy((char *)wNetConfig.wifi_ssid, ap_info.ssid.array); + os_strcpy((char *)wNetConfig.wifi_key, ap_info.key); + + wNetConfig.wifi_mode = SOFT_AP; + wNetConfig.dhcp_mode = DHCP_SERVER; + wNetConfig.wifi_retry_interval = 100; + + APP_DRONE_PRT("set ip info: %s,%s,%s\r\n", + wNetConfig.local_ip_addr, + wNetConfig.net_mask, + wNetConfig.dns_server_ip_addr); + + APP_DRONE_PRT("ssid:%s key:%s\r\n", wNetConfig.wifi_ssid, wNetConfig.wifi_key); + bk_wlan_start(&wNetConfig); + + return 0; +} + +static void app_drone_main( beken_thread_arg_t data ) +{ + OSStatus err; + int ret = 0; + u32 status; + + err = rtos_init_timer(&g_drone->timer, + APP_DRONE_TIMER_INTVAL, + app_drone_timer_handler, + (void *)0); + ASSERT(kNoErr == err); + + //err = rtos_start_timer(&g_drone->timer); + //ASSERT(kNoErr == err); + + app_led_init(); + app_led_send_msg(POWER_ON); + + rw_evt_set_callback(RW_EVT_AP_CONNECTED, app_drone_rw_event_func); + rw_evt_set_callback(RW_EVT_AP_DISCONNECTED, app_drone_rw_event_func); + + app_drone_setup(); + + //app_lwip_udp_init(); + //app_lwip_tcp_init(); + + g_drone->status = DS_WIFI_DISCONECTED; + + while(1) + { + DRONE_MSG_T msg; + status = g_drone->status; + + err = rtos_pop_from_queue(&g_drone->msg_que, &msg, BEKEN_WAIT_FOREVER); + if(kNoErr == err) + { + switch(msg.dmsg) + { + case DMSG_TIMER_POLL: + app_drone_timer_poll(); + break; + + case DMSG_WIFI_DISCONECTED: + g_drone->status = DS_WIFI_DISCONECTED; + app_led_send_msg(LED_DISCONNECT); + app_lwip_udp_deinit(); + //app_lwip_tcp_deinit(); + APP_DRONE_PRT("wifi disconnected!\r\n"); + break; + + case DMSG_WIFI_CONECTED: + g_drone->status = DS_WIFI_CONECTED; + app_led_send_msg(LED_CONNECT); + app_lwip_udp_init(); + //app_lwip_tcp_init(); + APP_DRONE_PRT("wifi connected!\r\n"); + break; + + case DMSG_APP_CONECTED: + APP_DRONE_PRT("app connected!\r\n"); + g_drone->status = DS_APP_CONECTED; + break; + + case DMSG_APP_DISCONECTED: + APP_DRONE_PRT("app disconnected!\r\n"); + g_drone->status = DS_APP_DISCONECTED; + break; + + case DMSG_EXIT: + goto app_drone_exit; + break; + + default: + break; + } + } + } + +app_drone_exit: + err = rtos_deinit_timer(&g_drone->timer); + ASSERT(kNoErr == err); + + rtos_deinit_queue(&g_drone->msg_que); + + os_free(g_drone); + g_drone = NULL; + + rtos_delete_thread(NULL); +} + + +void user_main( beken_thread_arg_t args ) +{ + int ret; + + APP_DRONE_PRT("app_drone_init\r\n"); +#if 1 + if(!g_drone) + { + g_drone = os_malloc(sizeof(APP_DRONE_ST)); + if(!g_drone) { + APP_DRONE_FATAL("app_drone_init malloc failed\r\n"); + return; + } + + ret = rtos_init_queue(&g_drone->msg_que, + "app_drone_queue", + sizeof(DRONE_MSG_T), + APP_DRONE_QITEM_COUNT); + if (kNoErr != ret) + { + APP_DRONE_FATAL("app_drone_init ceate queue failed\r\n"); + os_free(g_drone); + g_drone = NULL; + return; + } + + ret = rtos_create_thread(&g_drone->thread_hdl, + BEKEN_DEFAULT_WORKER_PRIORITY, + "app_drone", + (beken_thread_function_t)app_drone_main, + 2048, + (beken_thread_arg_t)NULL); + if (ret != kNoErr) + { + APP_DRONE_FATAL("Error: Failed to create spidma_intfer: %d\r\n", ret); + + rtos_deinit_queue(g_drone->msg_que); + os_free(g_drone); + g_drone = NULL; + return; + } + + } +#endif + rtos_delete_thread(NULL); + +} + +static UINT32 search_by_type(UINT32 type, UINT32 start_addr) +{ + UINT32 status, addr, end_addr; + DD_HANDLE flash_handle; + head_param_t head; + + flash_handle = ddev_open(FLASH_DEV_NAME, &status, 0); + ddev_read(flash_handle, (char *)&head, sizeof(head_param_t), start_addr); + addr = start_addr + sizeof(head_param_t); + end_addr = addr + head.len; + while(addr < end_addr){ + ddev_read(flash_handle, (char *)&head, sizeof(head_param_t), addr); + if(type == head.type){ + break; + }else{ + addr += sizeof(head_param_t); + addr += head.len; + } + } + + if(addr >= end_addr){ + addr = 0; + } + ddev_close(flash_handle); + + return addr; +} + +static int app_drone_get_general_paramters(general_param_t *general) +{ + UINT32 status, addr, addr_start; + DD_HANDLE flash_handle; + head_param_t head; + + if(!general){ + APP_DRONE_FATAL("get_general_paramters is null\r\n"); + return -1; + } + + addr_start = search_by_type(ARCH_CONFIG_GENERAL, CONFIG_ADDR_START); + if(!addr_start){ + APP_DRONE_FATAL("SEARCH GENERAL CLASS FAIL\r\n"); + return -1; + } + + flash_handle = ddev_open(FLASH_DEV_NAME, &status, 0); + + addr = search_by_type(GENERAL_TYPE_ROLE, addr_start); + if(!addr){ + APP_DRONE_FATAL("SEARCH ROLE FAIL\r\n"); + return -1; + } + ddev_read(flash_handle, (char *)&head, sizeof(head_param_t), addr); + ddev_read(flash_handle, (char *)&general->role, head.len, addr+sizeof(head_param_t)); + + addr = search_by_type(GENERAL_TYPE_DHCP, addr_start); + if(!addr){ + APP_DRONE_FATAL("SEARCH DHCP FAIL\r\n"); + return -1; + } + ddev_read(flash_handle, (char *)&head, sizeof(head_param_t), addr); + ddev_read(flash_handle, (char *)&general->dhcp_enable, head.len, addr+sizeof(head_param_t)); + + addr = search_by_type(GENERAL_TYPE_IP, addr_start); + if(!addr){ + APP_DRONE_FATAL("SEARCH IP FAIL\r\n"); + return -1; + } + ddev_read(flash_handle, (char *)&head, sizeof(head_param_t), addr); + ddev_read(flash_handle, (char *)&general->ip_addr, head.len, addr+sizeof(head_param_t)); + + addr = search_by_type(GENERAL_TYPE_MASK, addr_start); + if(!addr){ + APP_DRONE_FATAL("SEARCH MASK FAIL\r\n"); + return -1; + } + ddev_read(flash_handle, (char *)&head, sizeof(head_param_t), addr); + ddev_read(flash_handle, (char *)&general->ip_mask, head.len, addr+sizeof(head_param_t)); + + addr = search_by_type(GENERAL_TYPE_GW, addr_start); + if(!addr){ + APP_DRONE_FATAL("SEARCH GW FAIL\r\n"); + return -1; + } + ddev_read(flash_handle, (char *)&head, sizeof(head_param_t), addr); + ddev_read(flash_handle, (char *)&general->ip_gw, head.len, addr+sizeof(head_param_t)); + + ddev_close(flash_handle); + return 0; +} + +static int app_drone_get_ap_paramters(ap_param_t *ap) +{ + UINT32 status, addr, addr_start; + DD_HANDLE flash_handle; + head_param_t head; + + if(!ap) { + APP_DRONE_FATAL("get_ap_paramters is null\r\n"); + return -1; + } + + addr_start = search_by_type(ARCH_CONFIG_AP, CONFIG_ADDR_START); + if(!addr_start){ + APP_DRONE_FATAL("SEARCH AP CLASS FAIL\r\n"); + return -1; + } + + flash_handle = ddev_open(FLASH_DEV_NAME, &status, 0); + + addr = search_by_type(AP_TYPE_BSSID, addr_start); + if(!addr){ + APP_DRONE_FATAL("SEARCH BSSID FAIL\r\n"); + return -1; + } + ddev_read(flash_handle, (char *)&head, sizeof(head_param_t), addr); + ddev_read(flash_handle, (char *)&ap->bssid, head.len, addr+sizeof(head_param_t)); + + addr = search_by_type(AP_TYPE_SSID, addr_start); + if(!addr){ + APP_DRONE_FATAL("SEARCH SSID FAIL\r\n"); + return -1; + } + ddev_read(flash_handle, (char *)&head, sizeof(head_param_t), addr); + ap->ssid.length = head.len; + ddev_read(flash_handle, (char *)ap->ssid.array, head.len, addr+sizeof(head_param_t)); + + addr = search_by_type(AP_TYPE_CHANNEL, addr_start); + if(!addr){ + APP_DRONE_FATAL("SEARCH CHANNEL FAIL\r\n"); + return -1; + } + ddev_read(flash_handle, (char *)&head, sizeof(head_param_t), addr); + ddev_read(flash_handle, (char *)&ap->chann, head.len, addr+sizeof(head_param_t)); + + addr = search_by_type(AP_TYPE_MODE, addr_start); + if(!addr){ + APP_DRONE_FATAL("SEARCH MODE FAIL\r\n"); + return -1; + } + ddev_read(flash_handle, (char *)&head, sizeof(head_param_t), addr); + ddev_read(flash_handle, (char *)&ap->cipher_suite, head.len, addr+sizeof(head_param_t)); + +#if 1 + addr = search_by_type(AP_TYPE_PASSWD, addr_start); + if(!addr){ + APP_DRONE_FATAL("SEARCH PASSWORD FAIL\r\n"); + return 0; + } + ddev_read(flash_handle, (char *)&head, sizeof(head_param_t), addr); + ap->key_len = head.len; + ddev_read(flash_handle, (char *)ap->key, head.len, addr+sizeof(head_param_t)); +#endif + return 0; +} + + + +#endif // CFG_SUPPORT_TIANZHIHENG_DRONE + diff --git a/beken_os/beken378/app/net_work/app_drone.h b/beken_os/beken378/app/net_work/app_drone.h new file mode 100755 index 0000000..bbdb73f --- /dev/null +++ b/beken_os/beken378/app/net_work/app_drone.h @@ -0,0 +1,17 @@ +#ifndef __APP_DRONE_H__ +#define __APP_DRONE_H__ + +enum +{ + DMSG_TIMER_POLL = 0, + DMSG_WIFI_DISCONECTED, + DMSG_WIFI_CONECTED, + DMSG_APP_CONECTED, + DMSG_APP_DISCONECTED, + DMSG_EXIT, +}; + +void app_drone_send_msg(u32 new_msg); +UINT32 app_drone_init(void); + +#endif diff --git a/beken_os/beken378/app/net_work/app_lwip_tcp.c b/beken_os/beken378/app/net_work/app_lwip_tcp.c new file mode 100755 index 0000000..cff6fda --- /dev/null +++ b/beken_os/beken378/app/net_work/app_lwip_tcp.c @@ -0,0 +1,320 @@ +#include "include.h" + +#if CFG_USE_LWIP_NETSTACK +#include "lwip/tcp.h" +#include "app_lwip_tcp.h" +#include "app_led.h" +#include "uart_pub.h" +#include "mem_pub.h" + +#include "FreeRTOS.h" +#include "task.h" +#include "rtos_pub.h" +#include "error.h" +#include "lwip/sockets.h" + +#include "app_drone.h" + +#include "video_transfer.h" + + +#if CFG_SUPPORT_TIANZHIHENG_DRONE + +#define LWIP_TCP_DEBUG 1 +#if LWIP_TCP_DEBUG +#define LWIP_TCP_PRT warning_prf +#define LWIP_TCP_WARN warning_prf +#define LWIP_TCP_FATAL fatal_prf +#else +#define LWIP_TCP_PRT null_prf +#define LWIP_TCP_WARN null_prf +#define LWIP_TCP_FATAL null_prf +#endif + +#define APP_TCP_LISTEN_MAX 1 +#define APP_TCP_RCV_BUF_LEN 1460 + +xTaskHandle app_tcp_hdl = NULL; +int watch_fd_list[APP_TCP_LISTEN_MAX]; +int tcp_server_fd; +volatile int app_tcp_run = 0; + +static void app_lwip_tcp_set_keepalive(int fd) +{ + int opt = 1, ret; + // open tcp keepalive + ret = setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &opt, sizeof(int)); + + opt = 30; // 5 second + ret = setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &opt, sizeof(int)); + + opt = 1; // 1s second for intval + ret = setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &opt, sizeof(int)); + + opt = 3; // 3 times + ret = setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &opt, sizeof(int)); + ret = ret; +} + +static void app_lwip_tcp_main( beken_thread_arg_t data ) +{ + GLOBAL_INT_DECLARATION(); + OSStatus err = kNoErr; + int maxfd = -1; + int ret = 0, i = 0; + int snd_len = 0, rcv_len = 0; + struct sockaddr_in server_addr; + socklen_t srvaddr_len = 0; + fd_set watchfd, watchwd; + u8 *rcv_buf = NULL; + + (void)(data); + + LWIP_TCP_FATAL("app_lwip_tcp_main entry\r\n"); + + rcv_buf = (u8*) os_malloc((APP_TCP_RCV_BUF_LEN + 1) * sizeof(u8)); + if(!rcv_buf) { + LWIP_TCP_PRT("tcp os_malloc failed\r\n"); + goto app_tcp_exit; + } + + tcp_server_fd = socket(AF_INET, SOCK_STREAM, 0); + if (tcp_server_fd == -1) { + LWIP_TCP_PRT("socket failed\r\n"); + goto app_tcp_exit; + } + + server_addr.sin_family = AF_INET; + server_addr.sin_port = htons(APP_LWIP_TCP_SERVER_PORT); + server_addr.sin_addr.s_addr = htonl(INADDR_ANY); + + srvaddr_len = (socklen_t)sizeof(server_addr); + if (bind(tcp_server_fd, (struct sockaddr *)&server_addr, srvaddr_len) == -1) { + LWIP_TCP_PRT("bind failed\r\n"); + goto app_tcp_exit; + } + + if (listen(tcp_server_fd, APP_TCP_LISTEN_MAX) == -1) { + LWIP_TCP_PRT("listen failed\r\n"); + goto app_tcp_exit; + } + + maxfd = tcp_server_fd; + for (i=0; i APP_TCP_RCV_BUF_LEN)? APP_TCP_RCV_BUF_LEN: rcv_len; + rcv_buf[rcv_len] = 0; + + snd_len = send(watch_fd_list[i], rcv_buf, rcv_len, 0); + if (snd_len < 0) { + /* err */ + LWIP_TCP_PRT("send return fd:%d\r\n", snd_len); + } + } + FD_CLR(watch_fd_list[i], &watchfd); + } + }// ret = select + } + +app_tcp_exit: + + LWIP_TCP_FATAL("app_lwip_tcp_main exit\r\n"); + +#if (CFG_USE_SPIDMA || CFG_USE_CAMERA_INTF) + video_transfer_deinit(); +#endif + //app_drone_send_msg(DRONE_TCP_DISCONECTED); + + if(rcv_buf) { + os_free(rcv_buf); + rcv_buf = NULL; + } + + for (i=0; isin_addr.s_addr; + LWIP_UDP_PRT("src_ipaddr: %d.%d.%d.%d\r\n", src_ipaddr[0], src_ipaddr[1], + src_ipaddr[2], src_ipaddr[3]); + LWIP_UDP_PRT("udp connect to new port:%d\r\n", udp_remote->sin_port); + + GLOBAL_INT_DISABLE(); + udp_romote_connected = 1; + GLOBAL_INT_RESTORE(); + + #if (CFG_USE_SPIDMA || CFG_USE_CAMERA_INTF) + video_transfer_init(TVIDEO_SND_UDP); + #endif + + app_drone_send_msg(DMSG_APP_CONECTED); + } + else if(data[1] == CMD_STOP_IMG) { + LWIP_UDP_PRT("udp close\r\n"); + + #if (CFG_USE_SPIDMA || CFG_USE_CAMERA_INTF) + video_transfer_deinit(); + #endif + + app_drone_send_msg(DMSG_APP_DISCONECTED); + + GLOBAL_INT_DISABLE(); + udp_romote_connected = 0; + GLOBAL_INT_RESTORE(); + + } + } +} + +static void app_lwip_udp_main( beken_thread_arg_t data ) +{ + OSStatus err = kNoErr; + GLOBAL_INT_DECLARATION(); + int maxfd, udp_cmd_fd, ret = 0; + int snd_len = 0, rcv_len = 0; + struct sockaddr_in cmd_remote; + socklen_t srvaddr_len = 0; + fd_set watchfd; + struct timeval timeout; + u8 *rcv_buf = NULL; + + (void)(data); + + rcv_buf = (u8*) os_malloc((APP_UDP_RCV_BUF_LEN + 1) * sizeof(u8)); + if(!rcv_buf) { + LWIP_UDP_PRT("udp os_malloc failed\r\n"); + goto app_udp_exit; + } + + udp_remote = (struct sockaddr_in *)os_malloc(sizeof(struct sockaddr_in)); + if(!udp_remote) { + LWIP_UDP_PRT("udp os_malloc failed\r\n"); + goto app_udp_exit; + } + + // for data transfer + udp_img_fd = socket(AF_INET, SOCK_DGRAM, 0); + if (udp_img_fd == -1) { + LWIP_UDP_PRT("socket failed\r\n"); + goto app_udp_exit; + } + + udp_remote->sin_family = AF_INET; + udp_remote->sin_port = htons(APP_LWIP_UDP_IMG_PORT); + udp_remote->sin_addr.s_addr = htonl(INADDR_ANY); + + srvaddr_len = (socklen_t)sizeof(struct sockaddr_in); + if (bind(udp_img_fd, (struct sockaddr *)udp_remote, srvaddr_len) == -1) { + LWIP_UDP_PRT("bind failed\r\n"); + goto app_udp_exit; + } + + // for recv uart cmd + udp_cmd_fd = socket(AF_INET, SOCK_DGRAM, 0); + if (udp_cmd_fd == -1) { + LWIP_UDP_PRT("socket failed\r\n"); + goto app_udp_exit; + } + + cmd_remote.sin_family = AF_INET; + cmd_remote.sin_port = htons(APP_LWIP_UDP_CMD_PORT); + cmd_remote.sin_addr.s_addr = htonl(INADDR_ANY); + + if (bind(udp_cmd_fd, (struct sockaddr *)&cmd_remote, srvaddr_len) == -1) { + LWIP_UDP_PRT("bind failed\r\n"); + goto app_udp_exit; + } + + maxfd = (udp_cmd_fd > udp_img_fd)? udp_cmd_fd : udp_img_fd; + + timeout.tv_sec = APP_UDP_SOCKET_TIMEOUT / 1000; + timeout.tv_usec = (APP_UDP_SOCKET_TIMEOUT % 1000) * 1000; + + GLOBAL_INT_DISABLE(); + udp_romote_connected = 0; + app_udp_run = 1; + GLOBAL_INT_RESTORE(); + + while (app_udp_run) + { + FD_ZERO(&watchfd); + FD_SET(udp_img_fd, &watchfd); + FD_SET(udp_cmd_fd, &watchfd); + + ret = select(maxfd+1, &watchfd, NULL, NULL, &timeout); + if (ret < 0) { + LWIP_UDP_PRT("select ret:%d\r\n", ret); + break; + } + else + { + // is img fd, data transfer + if(FD_ISSET(udp_img_fd, &watchfd)) + { + rcv_len = recvfrom(udp_img_fd, rcv_buf, APP_UDP_RCV_BUF_LEN, 0, + (struct sockaddr *)udp_remote, &srvaddr_len); + + if(rcv_len <= 0) + { + // close this socket + LWIP_UDP_PRT("recv close fd:%d\r\n", udp_img_fd); + break; + } + else + { + rcv_len = (rcv_len > APP_UDP_RCV_BUF_LEN)? APP_UDP_RCV_BUF_LEN: rcv_len; + rcv_buf[rcv_len] = 0; + + app_lwip_udp_receiver(rcv_buf, rcv_len, udp_remote); + } + } + else if(FD_ISSET(udp_cmd_fd, &watchfd)) + { + rcv_len = recvfrom(udp_cmd_fd, rcv_buf, APP_UDP_RCV_BUF_LEN, 0, + (struct sockaddr *)&cmd_remote, &srvaddr_len); + + if(rcv_len <= 0) + { + // close this socket + LWIP_UDP_PRT("recv close fd:%d\r\n", udp_cmd_fd); + break; + } + else + { + rcv_len = (rcv_len > APP_UDP_RCV_BUF_LEN)? APP_UDP_RCV_BUF_LEN: rcv_len; + rcv_buf[rcv_len] = 0; + + app_lwip_udp_handle_cmd_data(rcv_buf, rcv_len); + } + + } + + } + } + +app_udp_exit: + + LWIP_UDP_FATAL("app_lwip_udp_main exit %d\r\n", app_udp_run); + +#if (CFG_USE_SPIDMA || CFG_USE_CAMERA_INTF) + video_transfer_deinit(); +#endif + + if(rcv_buf) { + os_free(rcv_buf); + rcv_buf = NULL; + } + + if(udp_remote) { + os_free(udp_remote); + udp_remote = NULL; + } + + if(udp_img_fd != -1) { + close(udp_img_fd); + udp_img_fd = -1; + } + + if(udp_cmd_fd != -1) { + close(udp_cmd_fd); + udp_cmd_fd = -1; + } + + GLOBAL_INT_DISABLE(); + udp_romote_connected = 0; + app_udp_run = 0; + GLOBAL_INT_RESTORE(); + + app_upd_hdl = NULL; + rtos_delete_thread(NULL); +} + +UINT32 app_lwip_udp_init(void) +{ + int ret; + + LWIP_UDP_PRT("app_lwip_udp_init\r\n"); + if(!app_upd_hdl) + { + ret = rtos_create_thread(&app_upd_hdl, + 4, + "app_udp", + (beken_thread_function_t)app_lwip_udp_main, + 1024, + (beken_thread_arg_t)NULL); + if (ret != kNoErr) + { + LWIP_UDP_PRT("Error: Failed to create spidma_intfer: %d\r\n", ret); + return kGeneralErr; + } + } + + return kNoErr; +} + +int app_lwip_udp_send_packet (UINT8 *data, UINT32 len) +{ + int send_byte = 0; + + if(!udp_romote_connected) + return 0; + + send_byte = sendto(udp_img_fd, data, len, MSG_DONTWAIT|MSG_MORE, + (struct sockaddr *)udp_remote, sizeof(struct sockaddr_in)); + + if (send_byte < 0) { + /* err */ + //LWIP_UDP_PRT("send return fd:%d\r\n", send_byte); + send_byte = 0; + } + + return send_byte; +} + +void app_lwip_udp_deinit(void) +{ + GLOBAL_INT_DECLARATION(); + + LWIP_UDP_PRT("app_lwip_udp_deinit\r\n"); + if(app_udp_run == 0) + return; + + GLOBAL_INT_DISABLE(); + app_udp_run = 0; + GLOBAL_INT_RESTORE(); +} + +#endif // CFG_SUPPORT_TIANZHIHENG_DRONE +#endif // CFG_USE_LWIP_NETSTACK + +// EOF + diff --git a/beken_os/beken378/app/net_work/app_lwip_udp.h b/beken_os/beken378/app/net_work/app_lwip_udp.h new file mode 100755 index 0000000..43adcca --- /dev/null +++ b/beken_os/beken378/app/net_work/app_lwip_udp.h @@ -0,0 +1,11 @@ +#ifndef __APP_LWIP_UDP_H__ +#define __APP_LWIP_UDP_H__ + +UINT32 app_lwip_udp_init(void); +void app_lwip_udp_deinit(void); +int app_lwip_udp_send_packet (UINT8 *data, UINT32 len); +void app_lwip_disconnect_cmd_udp(void); + +#endif +// eof + diff --git a/beken_os/beken378/app/standalone-ap/sa_ap.c b/beken_os/beken378/app/standalone-ap/sa_ap.c new file mode 100755 index 0000000..c1b51c2 --- /dev/null +++ b/beken_os/beken378/app/standalone-ap/sa_ap.c @@ -0,0 +1,51 @@ +#include "include.h" +#include "sa_ap.h" +#include "schedule_pub.h" +#include "drv_model_pub.h" +#include "uart_pub.h" +#include "rw_pub.h" +#include "rxu_task.h" +#include "mm_task.h" +#include "me_task.h" +#include "apm_task.h" +#include "vif_mgmt.h" + +#include "hostapd_cfg.h" +#include "rw_ieee80211.h" + +#if CFG_USE_TEMPERATURE_DETECT +#include "temp_detect_pub.h" +#endif + +extern void mm_bcn_init(void); +void sa_ap_init(void) +{ + if (rwm_mgmt_is_vif_first_used() == NULL) + { + SAAP_PRT("[saap]MM_RESET_REQ\r\n"); + rw_msg_send_reset(); + + SAAP_PRT("[saap]ME_CONFIG_REQ\r\n"); + rw_msg_send_me_config_req(); + + SAAP_PRT("[saap]ME_CHAN_CONFIG_REQ\r\n"); + rw_msg_send_me_chan_config_req(); + + SAAP_PRT("[saap]MM_START_REQ\r\n"); + rw_msg_send_start(); + } +#if !CFG_WPA_CTRL_IFACE + else + { + SAAP_PRT("[saap]mm_bcn_init\r\n"); + mm_bcn_init(); + } +#endif +} + +void sa_ap_uninit(void) +{ + +} +// eof + diff --git a/beken_os/beken378/app/standalone-ap/sa_ap.h b/beken_os/beken378/app/standalone-ap/sa_ap.h new file mode 100755 index 0000000..95be199 --- /dev/null +++ b/beken_os/beken378/app/standalone-ap/sa_ap.h @@ -0,0 +1,17 @@ +#ifndef _SA_AP_H_ +#define _SA_AP_H_ + +#define SAAP_DEBUG + +#ifdef SAAP_DEBUG +#define SAAP_PRT os_printf +#define SAAP_WPRT warning_prf +#else +#define SAAP_PRT os_null_printf +#define SAAP_WPRT os_null_printf +#endif + +extern void sa_ap_init(void); +#endif // _SA_AP_H_ +// eof + diff --git a/beken_os/beken378/app/standalone-station/sa_station.c b/beken_os/beken378/app/standalone-station/sa_station.c new file mode 100755 index 0000000..52d4621 --- /dev/null +++ b/beken_os/beken378/app/standalone-station/sa_station.c @@ -0,0 +1,145 @@ +#include "include.h" + +#include "schedule_pub.h" + +#include "sa_station.h" +#include "drv_model_pub.h" +#include "uart_pub.h" +#include "scanu_task.h" +#include "scan_task.h" +#include "rxu_task.h" +#include "mm_task.h" +#include "me_task.h" +#include "sm_task.h" +#include "rw_msg_tx.h" +#include "mac_ie.h" +#include "vif_mgmt.h" + +#include "arm_arch.h" +#include "mem_pub.h" +#include "rw_pub.h" +#include "common.h" + +#if CFG_USE_TEMPERATURE_DETECT +#include "temp_detect_pub.h" +#endif + +#include "param_config.h" + +#if (!CFG_SUPPORT_ALIOS) +#include "sys_rtos.h" +#endif +#include "rtos_pub.h" +#include "errno.h" +#include "rtos_error.h" +#include "errno-base.h" +#include "rw_ieee80211.h" + +extern struct mac_scan_result *scanu_search_by_ssid(struct mac_ssid const *ssid); + +/*---------------------------------------------------------------------------*/ +int sa_station_send_associate_cmd(CONNECT_PARAM_T *connect_param) +{ + int ret; + struct mac_scan_result *desired_ap_ptr; + struct sm_connect_cfm sm_connect_cfm; + +#if !CFG_WPA_CTRL_IFACE + if(g_sta_param_ptr->fast_connect_set) + { + g_sta_param_ptr->fast_connect_set = 0; + if ((g_sta_param_ptr->key_len != g_sta_param_ptr->orig_key_len) + || !os_strncmp((char *)g_sta_param_ptr->key, (char *)g_sta_param_ptr->orig_key, g_sta_param_ptr->key_len)) + { + os_null_printf("%s:%d %d vs %d\n", __FUNCTION__, __LINE__, g_sta_param_ptr->key_len, g_sta_param_ptr->orig_key_len); + g_sta_param_ptr->key_len = g_sta_param_ptr->orig_key_len; + os_memcpy(g_sta_param_ptr->key, g_sta_param_ptr->orig_key, g_sta_param_ptr->orig_key_len); + } + connect_param->chan.freq = rw_ieee80211_get_centre_frequency(g_sta_param_ptr->fast_connect.chann); + connect_param->chan.band = 0; + connect_param->chan.flags = 0; + connect_param->chan.tx_power = 10; + } + else +#else + if (connect_param->chan.freq) { + /* for fast connect */ + connect_param->chan.band = 0; + connect_param->chan.flags = 0; + connect_param->chan.tx_power = 10; + } else +#endif + { + desired_ap_ptr = scanu_search_by_ssid((void *)&connect_param->ssid); + if(NULL == desired_ap_ptr) + { + return -1; + } + connect_param->chan = *(desired_ap_ptr->chan); + if(0 == connect_param->chan.tx_power) + { + connect_param->chan.tx_power = 10; + } + } + + if(rw_ieee80211_is_scan_rst_in_countrycode(rw_ieee80211_get_chan_id(connect_param->chan.freq)) == 0) + { + os_printf("ch:%d not in countrycode\r\n", connect_param->chan.freq); + return -1; + } + + ret = rw_msg_send_sm_connect_req(connect_param, &sm_connect_cfm); + if(ret) + return ret; + + switch (sm_connect_cfm.status) + { + case CO_OK: + ret = 0; + break; + + case CO_BUSY: + ret = -ERRINPROGRESS; + break; + + case CO_OP_IN_PROGRESS: + ret = -ERRALREADY; + break; + + default: + ret = -EERIO; + break; + } + + return ret; +} + +/*---------------------------------------------------------------------------*/ +static void sa_station_cfg80211_init(void) +{ + if (rwm_mgmt_is_vif_first_used() == NULL) + { + SASTA_PRT("[sa_sta]MM_RESET_REQ\r\n"); + rw_msg_send_reset(); + + SASTA_PRT("[sa_sta]ME_CONFIG_REQ\r\n"); + rw_msg_send_me_config_req(); + + SASTA_PRT("[sa_sta]ME_CHAN_CONFIG_REQ\r\n"); + rw_msg_send_me_chan_config_req(); + + SASTA_PRT("[sa_sta]MM_START_REQ\r\n"); + rw_msg_send_start(); + } +} + +void sa_station_init(void) +{ + sa_station_cfg80211_init(); +} + +void sa_station_uninit(void) +{ +} + +// eof diff --git a/beken_os/beken378/app/standalone-station/sa_station.h b/beken_os/beken378/app/standalone-station/sa_station.h new file mode 100755 index 0000000..bcac820 --- /dev/null +++ b/beken_os/beken378/app/standalone-station/sa_station.h @@ -0,0 +1,69 @@ +#ifndef _SA_STATION_H_ +#define _SA_STATION_H_ + +#include "schedule_pub.h" +#include "rw_msg_tx.h" + +#define SASTA_DEBUG + +#ifdef SASTA_DEBUG +#define SASTA_PRT os_printf +#define SASTA_WPRT warning_prf +#else +#define SASTA_PRT os_null_printf +#define SASTA_WPRT os_null_printf +#endif + +#define SCANU_IND_PAYLOAD_LEN 512 + +typedef struct _scan_result_ +{ + /// Length of the frame + UINT16 length; + /// Frame control field of the frame. + UINT16 framectrl; + /// Center frequency on which we received the packet + UINT16 center_freq; + /// PHY band + UINT8 band; + /// Index of the station that sent the frame. 0xFF if unknown. + UINT8 sta_idx; + /// Index of the VIF that received the frame. 0xFF if unknown. + UINT8 inst_nbr; + /// RSSI of the received frame. + INT8 rssi; + /// Frame payload. + UINT32 payload[1]; +} SCAN_IND_T, *SCAN_IND_PTR; + +typedef struct probe_rsp +{ + UINT8 timestamp[8]; + UINT16 beacon_int; + UINT16 capab_info; + + /* followed by some of SSID, Supported rates, + * FH Params, DS Params, CF Params, IBSS Params */ + UINT8 variable[1]; +} __attribute__ ((packed)) PROBE_RSP_T; + +typedef struct ieee802_11_probe_rsp +{ + UINT16 frame_control; + UINT16 duration; + UINT8 da[6]; + UINT8 sa[6]; + UINT8 bssid[6]; + UINT16 seq_ctrl; + struct probe_rsp rsp; +} __attribute__ ((packed)) IEEE802_11_PROBE_RSP_T, *IEEE802_11_PROBE_RSP_PTR; + +void sa_station_init(void); +void sa_station_uninit(void); +void sa_station_set_reconnect_timer(void); +void sa_reconnect_init(void); +int sa_station_send_associate_cmd(CONNECT_PARAM_T *connect_param); + +#endif // _SA_STATION_H_ +// eof + diff --git a/beken_os/beken378/app/tftp/tftpclient.c b/beken_os/beken378/app/tftp/tftpclient.c new file mode 100755 index 0000000..87016c7 --- /dev/null +++ b/beken_os/beken378/app/tftp/tftpclient.c @@ -0,0 +1,575 @@ +#include "include.h" +#include "arm_arch.h" +#include "rwnx_config.h" +#include "app.h" +#include "target_util_pub.h" +#include "mem_pub.h" +#include "str_pub.h" +#include "drv_model_pub.h" +#include "sys_ctrl_pub.h" +#include "saradc_pub.h" +#include "uart_pub.h" +#include "sys_rtos.h" +#include "rtos_pub.h" +#include "error.h" +#include "fake_clock_pub.h" +#include "rw_pub.h" +#include "tftpclient.h" +#include "udp.h" +#include "flash_pub.h" +#include "fake_clock_pub.h" + +#include "lwip/sockets.h" +#include "lwip/ip_addr.h" +#include "lwip/inet.h" + +#if CFG_SUPPORT_BOOTLOADER +extern void flash_protection_op(UINT8 mode,PROTECT_TYPE type); +#if (CFG_SUPPORT_OTA_TFTP || CFG_SUPPORT_OTA_HTTP) +SEND_PTK_HD send_hd, send_hd_bk; +static u32 os_data_addr = OS1_FLASH_ADDR; +uint32_t tftp_crc = 0; +IMG_HEAD img_hd = {0,}; +#endif + +#if CFG_SUPPORT_OTA_TFTP + +beken_semaphore_t sm_tftp_server; +beken_timer_t tm_tftp_server; +xTaskHandle tftp_thread_handle = NULL; + +int udp_tftp_listen_fd = -1; +struct sockaddr_in server_addr; +int tftp_s_addr; +socklen_t s_addr_len = sizeof(server_addr); +char *tftp_buf = NULL; +char BootFile[128] = "rwnx_fmac_crc.bin"; /* Boot File name */ +static int TftpServerPort; /* The UDP port at their end */ +static int TftpOurPort; /* The UDP port at our end */ +static int TftpTimeoutCount; +static uint64_t TftpBlock; /* packet sequence number */ +static uint64_t TftpLastBlock; /* last packet sequence number received */ +static uint64_t TftpBlockWrap; /* count of sequence number wraparounds */ +static uint64_t TftpBlockWrapOffset; /* memory offset due to wrapping */ +static int TftpState; + +static unsigned short TftpBlkSize = TFTP_BLOCK_SIZE; +static unsigned short TftpBlkSizeOption = TFTP_MTU_BLOCKSIZE; + +void string_to_ip(char *s) +{ + tftp_s_addr = inet_addr(s); + return ; +} + +static void +TftpSend (void) +{ + uint8_t pkt_buf[700]; + volatile uint8_t *pkt; + volatile uint8_t *xp; + int len = 0; + volatile uint16_t *s; + + memset(pkt_buf, 0, 700); + pkt = pkt_buf; + + TFTP_WARN("TftpState-- %d\r\n", TftpState); + + switch (TftpState) + { + + case STATE_RRQ: + xp = pkt; + s = (uint16_t *)pkt; + *s++ = htons(TFTP_RRQ); + pkt = (uint8_t *)s; + os_strcpy ((char *)pkt, BootFile); + pkt += os_strlen(BootFile) + 1; + os_strcpy ((char *)pkt, "octet"); + pkt += 5 /*strlen("octet")*/ + 1; + os_strcpy ((char *)pkt, "timeout"); + pkt += 7 /*strlen("timeout")*/ + 1; + sprintf((char *)pkt, "%lu", TIMEOUT); +#ifdef ET_DEBUG + TFTP_PRT("send option \"timeout %s\"\n", (char *)pkt); +#endif + pkt += os_strlen((char *)pkt) + 1; + /* try for more effic. blk size */ + pkt += sprintf((char *)pkt, "blksize%c%d%c", + 0, TftpBlkSizeOption, 0); + + len = pkt - xp; + break; + + case STATE_OACK: + case STATE_DATA: + xp = pkt; + s = (uint16_t *)pkt; + *s++ = htons(TFTP_ACK); + *s++ = htons(TftpBlock); + pkt = (uint8_t *)s; + len = pkt - xp; + break; + + case STATE_TOO_LARGE: + xp = pkt; + s = (uint16_t *)pkt; + *s++ = htons(TFTP_ERROR); + *s++ = htons(3); + pkt = (uint8_t *)s; + os_strcpy ((char *)pkt, "File too large"); + pkt += 14 /*strlen("File too large")*/ + 1; + len = pkt - xp; + break; + + case STATE_BAD_MAGIC: + xp = pkt; + s = (uint16_t *)pkt; + *s++ = htons(TFTP_ERROR); + *s++ = htons(2); + pkt = (uint8_t *)s; + os_strcpy ((char *)pkt, "File has bad magic"); + pkt += 18 /*strlen("File has bad magic")*/ + 1; + len = pkt - xp; + break; + } + + len = sendto( udp_tftp_listen_fd, pkt_buf, len, 0 , (struct sockaddr *) &server_addr, s_addr_len); + TFTP_PRT( "Server p: %x\r\n", server_addr.sin_port ); +} + +void Tftp_Uninit(void) +{ + rtos_deinit_timer(&tm_tftp_server); + close( udp_tftp_listen_fd ); + + if(tftp_buf) + { + os_free(tftp_buf); + tftp_buf = NULL; + } + + if(tftp_thread_handle) + { + rtos_delete_thread(&tftp_thread_handle); + tftp_thread_handle = 0; + } +} + +static void +TftpHandler ( + char *p, unsigned len, u16_t port) +{ + uint16_t proto; + uint16_t *s; + int i; + volatile uint8_t *pkt; + + if (TftpState != STATE_RRQ && port != TftpServerPort) + { + os_printf("err %d %x %x\r\n", TftpState, port, TftpServerPort); + return; + } + + if (len < 2) + { + return; + } + len -= 2; + /* warning: don't use increment (++) in ntohs() macros!! */ + s = (uint16_t *)p; + proto = *s++; + pkt = (uint8_t *)s; + + TFTP_WARN ("get proto:%d \r\n", proto); + + switch (ntohs(proto)) + { + + case TFTP_RRQ: + case TFTP_WRQ: + case TFTP_ACK: + break; + default: + break; + + case TFTP_OACK: +#ifdef ET_DEBUG + TFTP_PRT("Got OACK: %s %s\n", pkt, pkt + os_strlen((UINT8 *)pkt) + 1); +#endif + TftpState = STATE_OACK; + TftpServerPort = port; + /* + * Check for 'blksize' option. + * Careful: "i" is signed, "len" is unsigned, thus + * something like "len-8" may give a *huge* number + */ + for (i = 0; i + 8 < len; i++) + { + if (os_strcmp ((char *)pkt + i, "blksize") == 0) + { + TftpBlkSize = (unsigned short) + os_strtoul((char *)pkt + i + 8, NULL, 10); +#ifdef ET_DEBUG + TFTP_PRT ("Blocksize ack: %s, %d\n", + (char *)pkt + i + 8, TftpBlkSize); +#endif + break; + } + } + TftpSend (); /* Send ACK */ + break; + case TFTP_DATA: + if (len < 2) + return; + len -= 2; + TftpBlock = ntohs(*(uint16_t *)pkt); + + /* + * RFC1350 specifies that the first data packet will + * have sequence number 1. If we receive a sequence + * number of 0 this means that there was a wrap + * around of the (16 bit) counter. + */ + if (TftpBlock == 0) + { + TftpBlockWrap++; + TftpBlockWrapOffset += TftpBlkSize * TFTP_SEQUENCE_SIZE; + TFTP_PRT ("\n\t %lu MB received\n\t ", TftpBlockWrapOffset >> 20); + } + else + { + if (((TftpBlock - 1) % 10) == 0) + { + TFTP_PRT ("#"); + } + else if ((TftpBlock % (10 * HASHES_PER_LINE)) == 0) + { + TFTP_PRT ("\n\t "); + } + } + +#ifdef ET_DEBUG + if (TftpState == STATE_RRQ) + { + TFTP_PRT ("Server did not acknowledge timeout option!\n"); + } +#endif + + if (TftpState == STATE_RRQ || TftpState == STATE_OACK) + { + /* first block received */ + TftpState = STATE_DATA; + TftpServerPort = port; + TftpLastBlock = 0; + TftpBlockWrap = 0; + TftpBlockWrapOffset = 0; + + if (TftpBlock != 1) /* Assertion */ + { + TFTP_PRT ("\nTFTP error: " + "First block is not block 1 (%ld)\n" + "Starting again\n\n", + TftpBlock); + break; + } + } + + if (TftpBlock == TftpLastBlock) + { + /* + * Same block again; ignore it. + */ + TftpSend (); + break; + } + TFTP_WARN("TftpState %d\r\n", TftpState); + + TftpLastBlock = TftpBlock; + store_block (TftpBlock - 1, (UINT8 *)(pkt + 2), len); + + /* + * Acknoledge the block just received, which will prompt + * the server for the next one. + */ + TftpSend (); + + if (len < TftpBlkSize) + { + /* + * We received the whole thing. Try to + * run it. + */ + os_printf ("\ntftp succeed\n"); + Tftp_Uninit(); + } + break; + + case TFTP_ERROR: + TFTP_PRT ("\nTFTP error: '%s' (%d)\n", + pkt + 2, ntohs(*(uint16_t *)pkt)); + TFTP_PRT ("Starting again\n\n"); + break; + } +} + +static void +TftpTimeout (void) +{ + err_t err; + + TFTP_PRT("------\r\n"); + if (++TftpTimeoutCount > TIMEOUT_COUNT) + { + TFTP_PRT ("\nRetry count exceeded; starting again\n"); + + } + else + { + os_printf ("T "); + TftpSend (); + } + +} + +void +TftpStart (void) +{ +#ifdef CONFIG_TFTP_PORT + char *ep; /* Environment pointer */ +#endif + + if (BootFile[0] == '\0') + { + TFTP_PRT ("*** Warning: no boot file name;\r\n"); + } + + TFTP_PRT ("Filename '%s'.\n", BootFile); + TFTP_PRT ("Load addr: 0x%lx\n", OS1_FLASH_ADDR); + TFTP_PRT ("Loading: *\b"); + + tftp_crc = 0; + TftpServerPort = WELL_KNOWN_PORT; + TftpTimeoutCount = 0; + TftpState = STATE_RRQ; + /* Use a pseudo-random port unless a specific port is set */ + TftpOurPort = 1024 + (fclk_get_tick() % 3072); + +#ifdef CONFIG_TFTP_PORT + if ((ep = getenv("tftpdstp")) != NULL) + { + TftpServerPort = simple_strtol(ep, NULL, 10); + } + if ((ep = getenv("tftpsrcp")) != NULL) + { + TftpOurPort = simple_strtol(ep, NULL, 10); + } +#endif + TftpBlock = 0; + /* Revert TftpBlkSize to dflt */ + TftpBlkSize = TFTP_BLOCK_SIZE; +} + +void tftp_timer_callback(void *data) +{ + TftpTimeout(); +} + +void tftp_server_process( beken_thread_arg_t arg ) +{ + int result; + (void)( arg ); + + OSStatus err = kNoErr; + int len = 0; + int i; + + tftp_buf = (char *) os_malloc( TFTP_LEN ); + if(tftp_buf == NULL) + { + os_printf("buf == NULL\r\n"); + goto exit; + } + + udp_tftp_listen_fd = socket( AF_INET, SOCK_DGRAM, 0 );//Make UDP socket + if(udp_tftp_listen_fd == -1) + { + os_printf("udp_listen_fd == -1\r\n"); + goto exit; + } + os_memset(&server_addr, 0, sizeof(server_addr)); + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = tftp_s_addr; + server_addr.sin_port = htons(WELL_KNOWN_PORT); + + TftpStart(); + + result = rtos_init_timer(&tm_tftp_server, + TFTP_TIMER / FCLK_DURATION_MS, + tftp_timer_callback, + (void *)0); + ASSERT(kNoErr == result); + result = rtos_start_timer(&tm_tftp_server); + ASSERT(kNoErr == result); + flash_protection_op(FLASH_XTX_16M_SR_WRITE_ENABLE, FLASH_PROTECT_NONE); + + while ( 1 ) + { + len = recvfrom( udp_tftp_listen_fd, tftp_buf, TFTP_LEN, 0 , (struct sockaddr *) &server_addr, &s_addr_len); + TFTP_PRT( "Server port: %x len:%d\r\n", server_addr.sin_port, len ); + TftpHandler(tftp_buf, len, server_addr.sin_port); + } + +exit: + if ( err != kNoErr ) + os_printf( "Server listener thread exit with err: %d", err ); + + close( udp_tftp_listen_fd ); + + if(tftp_buf) + os_free(tftp_buf); + + flash_protection_op(FLASH_XTX_16M_SR_WRITE_ENABLE, FLASH_UNPROTECT_LAST_BLOCK); + rtos_delete_thread(&tftp_thread_handle); +} + +void tftp_start(void) +{ + UINT32 ret; + + Tftp_Uninit(); + + TFTP_PRT("tftp c started\r\n"); + { + rtos_init_semaphore(&sm_tftp_server, 10); + + /* Start ps server listener thread*/ + ret = rtos_create_thread( &tftp_thread_handle, BEKEN_APPLICATION_PRIORITY, + "tftp_ota", + (beken_thread_function_t)tftp_server_process, + 0x1000, + 0 ); + + if (kNoErr != ret) + { + os_printf("Create power_sleep failed\r\n"); + } + } + +} +#endif + +#if (CFG_SUPPORT_OTA_TFTP || CFG_SUPPORT_OTA_HTTP) +void store_block (unsigned block, uint8_t *src, unsigned len) +{ + uint8_t *f_data; + UINT32 param , or_crc; + UINT32 param1; + + + TFTP_WARN ("p_len%d \r\n", len); + + os_memcpy(&send_hd, src, sizeof(send_hd)); + TFTP_WARN ("seq%d t_seq:%d\r\n", send_hd.seq, send_hd.total_seq); + if((block + 1 != send_hd.seq)) + { + os_printf ("bk:%d seq%d t_seq:%d fail!\r\n", block, send_hd.seq, send_hd.total_seq); + } + + if(block) + { + if(!((send_hd_bk.seq + 1 == send_hd.seq) + && (send_hd_bk.total_len == send_hd.total_len) + && (send_hd_bk.os0_ex_addr == send_hd.os0_ex_addr) + && (send_hd_bk.os0_flash_addr == send_hd.os0_flash_addr) + && (send_hd_bk.os1_flash_addr == send_hd.os1_flash_addr) + && (send_hd_bk.total_seq == send_hd.total_seq))) + TFTP_PRT ("tftp seq head err\r\n"); + } + else + { + os_data_addr = send_hd.os1_flash_addr; + tftp_crc = 0; + } + os_memcpy(&send_hd_bk, &send_hd, sizeof(send_hd)); + + if(os_data_addr % 0x1000 == 0) + { + param = os_data_addr; + flash_ctrl(CMD_FLASH_ERASE_SECTOR, ¶m); + TFTP_WARN ("erase_addr:%x \r\n", os_data_addr); + TFTP_WARN ("e"); + } + + TFTP_WARN ("w_addr:%x \r\n", os_data_addr); + if((u32)os_data_addr >= 0x200000 || (u32)os_data_addr < 0x27000) + { + TFTP_PRT ("eerr_addr:%x \r\n", os_data_addr); + return; + } + + if((u32)os_data_addr < 0x400000) + { + flash_write(src + TFTP_PKT_HD_LEN , len - TFTP_PKT_HD_LEN, (u32)os_data_addr); + f_data = os_malloc(1024); + if(f_data) + { + flash_read(f_data, len - TFTP_PKT_HD_LEN, (u32)os_data_addr); + if(!os_memcmp(src + TFTP_PKT_HD_LEN, f_data, len - TFTP_PKT_HD_LEN)) + { + TFTP_WARN ("block%d WRITE ok !\n", block); + TFTP_WARN ("."); + } + else + { + TFTP_PRT ("block%d flash write err\n", block); + } + os_free(f_data); + } + else + { + TFTP_PRT("malloc fail.\r\n"); + } + + if(send_hd.seq != send_hd.total_seq) + tftp_crc = co_crc32((UINT32)src, len, tftp_crc); + else + { + TFTP_WARN ("seq%d send over\n", send_hd.seq); + os_memcpy(&or_crc, src + len - TFTP_ALL_CRC_LEN, TFTP_ALL_CRC_LEN); + tftp_crc = co_crc32((UINT32)src, len - TFTP_ALL_CRC_LEN, tftp_crc); + if(tftp_crc == or_crc) + { + TFTP_PRT ("crc OK:%x %x\n", tftp_crc, or_crc); + img_hd.bkup_addr = send_hd.os1_flash_addr; + img_hd.bkup_len = send_hd_bk.total_len; + img_hd.crc = or_crc; + img_hd.ex_addr = send_hd.os0_ex_addr; + img_hd.os_addr = send_hd.os0_flash_addr; + img_hd.hd_addr = send_hd.os_hd_addr; + img_hd.status = 1; + param = (u32)send_hd.os_hd_addr; + flash_ctrl(CMD_FLASH_ERASE_SECTOR, ¶m); + flash_write((char *)&img_hd, sizeof(img_hd), (u32)send_hd.os_hd_addr); + + TFTP_WARN ("%X %X %X %X %X \r\n", img_hd.bkup_addr, + img_hd.bkup_len, img_hd.crc, img_hd.ex_addr, img_hd.status); + } + else + { + TFTP_PRT ("crc ERR--:%d %d\n", tftp_crc, or_crc); + + } + } + + os_data_addr += len - TFTP_PKT_HD_LEN; + } +} + +#endif + +#endif + +//eof + diff --git a/beken_os/beken378/app/tftp/tftpclient.h b/beken_os/beken378/app/tftp/tftpclient.h new file mode 100755 index 0000000..9ae5ef2 --- /dev/null +++ b/beken_os/beken378/app/tftp/tftpclient.h @@ -0,0 +1,114 @@ + +#include "include.h" +#include "arm_arch.h" +#include "rwnx_config.h" +#include "app.h" +#include "target_util_pub.h" +#include "mem_pub.h" +#include "str_pub.h" +#include "drv_model_pub.h" +#include "sys_ctrl_pub.h" +#include "saradc_pub.h" +#include "uart_pub.h" +#include "sys_rtos.h" +#include "rtos_pub.h" +#include "error.h" +#include "fake_clock_pub.h" +#include "rw_pub.h" +#include "udp.h" +#include "flash_pub.h" +#include "fake_clock_pub.h" + +#include "lwip/sockets.h" +#include "lwip/ip_addr.h" +#include "lwip/inet.h" + +//#define TFTP_DEBUG +#ifdef TFTP_DEBUG +#define TFTP_PRT os_printf +#define TFTP_WARN os_printf +#define TFTP_FATAL os_printf +#else +#define TFTP_PRT os_null_printf +#define TFTP_WARN os_null_printf +#define TFTP_FATAL os_null_printf +#endif + +#define OS1_FLASH_ADDR 0x8C000 +#define TFTP_ALL_CRC_LEN 4 + +typedef struct send_data_hd +{ + u32 total_len; + u16 seq; + u16 total_seq; + u32 os0_ex_addr; + u32 os_hd_addr; + u32 os0_flash_addr; + u32 os1_flash_addr; +} SEND_PTK_HD; + +typedef struct img_head +{ + uint32_t bkup_addr; + uint32_t bkup_len; + uint32_t ex_addr; + uint32_t os_addr; + uint32_t hd_addr; + uint32_t crc; + uint32_t status; + uint32_t bk; +} IMG_HEAD, *IMG_HEAD_P; + +#define TFTP_PKT_HD_LEN (sizeof(SEND_PTK_HD)) + +extern UINT32 flash_read(char *user_buf, UINT32 count, UINT32 address); +extern UINT32 flash_write(char *user_buf, UINT32 count, UINT32 address); +extern UINT32 flash_ctrl(UINT32 cmd, void *parm); +void store_block (unsigned block, uint8_t *src, unsigned len); + + +#if CFG_SUPPORT_OTA_TFTP +void ftpd_start(void); + +#define ET_DEBUG 0 + +#define WELL_KNOWN_PORT 69 /* Well known TFTP port # */ +#define TIMEOUT 5UL /* Seconds to timeout for a lost pkt */ +#ifndef CONFIG_NET_RETRY_COUNT +# define TIMEOUT_COUNT 10 /* # of timeouts before giving up */ +#else +# define TIMEOUT_COUNT (CONFIG_NET_RETRY_COUNT * 2) +#endif +/* (for checking the image size) */ +#define HASHES_PER_LINE 65 /* Number of "loading" hashes per line */ + +/* + * TFTP operations. + */ +#define TFTP_RRQ 1 +#define TFTP_WRQ 2 +#define TFTP_DATA 3 +#define TFTP_ACK 4 +#define TFTP_ERROR 5 +#define TFTP_OACK 6 + +#define STATE_RRQ 1 +#define STATE_DATA 2 +#define STATE_TOO_LARGE 3 +#define STATE_BAD_MAGIC 4 +#define STATE_OACK 5 +#define TFTP_BLOCK_SIZE 512 /* default TFTP block size */ +#define TFTP_SEQUENCE_SIZE ((uint64_t)(1<<16)) /* sequence number is 16 bit */ +#define TFTP_TIMER 1000 // ms + + +/* 512 is poor choice for ethernet, MTU is typically 1500. + * Minus eth.hdrs thats 1468. Can get 2x better throughput with + * almost-MTU block sizes. At least try... fall back to 512 if need be. + */ +#define TFTP_MTU_BLOCKSIZE (1024+sizeof(SEND_PTK_HD)) +#define TFTP_LEN 1600 + +#endif + diff --git a/beken_os/beken378/build/bk7221_jlink.ini b/beken_os/beken378/build/bk7221_jlink.ini new file mode 100755 index 0000000..fee90a5 --- /dev/null +++ b/beken_os/beken378/build/bk7221_jlink.ini @@ -0,0 +1,34 @@ + +FUNC void flash_init (void) { + unsigned int reg_val; + + // flash data to CPU CRC disable + _WDWORD(0x0080301c, (_RDWORD(0x0080301c))&(~(1<<26))); + + // flash status register data to be written + _WDWORD(0x0080301c, (_RDWORD(0x0080301c))&(~(0xffff<<10))); + + // cpu data writting enable + _WDWORD(0x0080301c, (_RDWORD(0x0080301c))|(1<<9)); + + // flash operation command : WRSR2 + reg_val = _RDWORD(0x00803000); + reg_val &= (~(0x1f<<24)); // clr op_type_sw + reg_val |= (0x07<<24) | (1<<29) | (1<<30); // op_sw, wp_value + _WDWORD(0x00803000, reg_val); + _sleep_(1000); + while(_RDWORD(0x00803000) & (0x01<<31)){;} + + // flash operation command : CE + reg_val = _RDWORD(0x00803000); + reg_val &= (~(0x1f<<24)); // clr op_type_sw + reg_val |= (0x10<<24) | (1<<29) | (1<<30); // op_sw, wp_value + _WDWORD(0x00803000, reg_val); + _sleep_(10000); + while(_RDWORD(0x00803000) & (0x01<<31)){;} +} + +flash_init(); + +LOAD .\build\macsw_fmac_arm\bk-mx-wifi001.hex INCREMENTAL +//LOAD .\build\macsw_fmac_arm\rwnx_fmac.axf INCREMENTAL // Download diff --git a/beken_os/beken378/build/bk7231.ld b/beken_os/beken378/build/bk7231.ld new file mode 100755 index 0000000..a270ef1 --- /dev/null +++ b/beken_os/beken378/build/bk7231.ld @@ -0,0 +1,124 @@ +/* + * Script for GNU linker. + * Describes layout of sections, location of stack. + * + * In this case vectors are at location 0 (reset @ 0x08) + * + * +------------+ 0x00400000 + * data | + * end + * |(heap) | + * . . + * . . + * |(heap limit)| + * + * |- - - - - - | + * stack bottom 256k + * +------------+ + * + * +------------+ 0x0000000 + * |vectors | + * | | + * |------------+ + * |text | + * |data | + * | | 1024k + * +------------+ + */ + + +/* Split memory into area for vectors and ram */ +MEMORY +{ + flash (rx) : ORIGIN = 0x00000000, LENGTH = 2M + ram (rw!x): ORIGIN = 0x00400000, LENGTH = 256k - 0x100 +} + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_vector_start); +_vector_start = ORIGIN(flash); + +SECTIONS +{ +/* vectors go to vectors region */ + . = ORIGIN(flash); + .vectors : + { + KEEP(*(*.vectors)) + KEEP( *(*.boot)) + } > flash + +/* instructions go to the text region*/ + + . = ALIGN(0x8); +/* code, instructions.for example: i=i+1; */ + .text : + { + *(.text) + *(.text.*) + *(.stub) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.gnu.linkonce.t*) + *(.glue_7t) *(.glue_7) + } > flash + +/* read only data.for example: const int rom_data[3]={1,2,3}; */ + .rodata ALIGN(8) : + { + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r*) + } > flash + + .ARM.exidx : + { + *(.ARM.exidx*) + *(.gnu.linkonce.armexidx.*) + } > flash + +/* globals.for example: int ram_data[3]={4,5,6}; */ /* VMA in RAM, but keep LMA in flash */ + _begin_data = .; + .data : AT ( _begin_data ) + { + *(.data .data.*) + *(.sdata) + *(.gnu.linkonce.d*) + SORT(CONSTRUCTORS) + } >ram + + /* Loader will copy data from _flash_begin to _ram_begin..ram_end */ + _data_flash_begin = LOADADDR(.data); + _data_ram_begin = ADDR(.data); + _data_ram_end = .; + +/* uninitialized data section - global int i; */ + .bss ALIGN(8): + { + _bss_start = .; + *(.bss .bss.*) + *(.scommon) + *(.sbss) + *(.dynbss) + *(COMMON) + /* Align here to ensure that the .bss section occupies space up to + _end. Align after .bss to ensure correct alignment even if the + .bss section disappears because there are no input sections. */ + . = ALIGN(32 / 8); + _bss_end = .; + } > ram /* in RAM */ + + . = ALIGN (8); + _empty_ram = .; + +/* This symbol defines end of code/data sections. Heap starts here. */ + PROVIDE(end = .); +} + GROUP( + libgcc.a + libg.a + libc.a + libm.a + libnosys.a + ) \ No newline at end of file diff --git a/beken_os/beken378/build/bk7231_ota.ld b/beken_os/beken378/build/bk7231_ota.ld new file mode 100755 index 0000000..5213525 --- /dev/null +++ b/beken_os/beken378/build/bk7231_ota.ld @@ -0,0 +1,124 @@ +/* + * Script for GNU linker. + * Describes layout of sections, location of stack. + * + * In this case vectors are at location 0 (reset @ 0x08) + * + * +------------+ 0x00400020 + * data | + * end + * |(heap) | + * . . + * . . + * |(heap limit)| + * + * |- - - - - - | + * stack bottom 256k + * +------------+ + * + * +------------+ 0x0000000 + * |vectors | + * | | + * |------------+ + * |text | + * |data | + * | | 1024k + * +------------+ + */ + + +/* Split memory into area for vectors and ram */ +MEMORY +{ + flash (rx) : ORIGIN = 0x00010000, LENGTH = 2M - 64k + ram (rw!x): ORIGIN = 0x00400100, LENGTH = 256k - 0x100 +} + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_vector_start); +_vector_start = ORIGIN(flash); + +SECTIONS +{ +/* vectors go to vectors region */ + . = ORIGIN(flash); + .vectors : + { + KEEP(*(*.vectors)) + KEEP( *(*.boot)) + } > flash + +/* instructions go to the text region*/ + + . = ALIGN(0x8); +/* code, instructions.for example: i=i+1; */ + .text : + { + *(.text) + *(.text.*) + *(.stub) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.gnu.linkonce.t*) + *(.glue_7t) *(.glue_7) + } > flash + +/* read only data.for example: const int rom_data[3]={1,2,3}; */ + .rodata ALIGN(8) : + { + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r*) + } > flash + + .ARM.exidx : + { + *(.ARM.exidx*) + *(.gnu.linkonce.armexidx.*) + } > flash + +/* globals.for example: int ram_data[3]={4,5,6}; */ /* VMA in RAM, but keep LMA in flash */ + _begin_data = .; + .data : AT ( _begin_data ) + { + *(.data .data.*) + *(.sdata) + *(.gnu.linkonce.d*) + SORT(CONSTRUCTORS) + } >ram + + /* Loader will copy data from _flash_begin to _ram_begin..ram_end */ + _data_flash_begin = LOADADDR(.data); + _data_ram_begin = ADDR(.data); + _data_ram_end = .; + +/* uninitialized data section - global int i; */ + .bss ALIGN(8): + { + _bss_start = .; + *(.bss .bss.*) + *(.scommon) + *(.sbss) + *(.dynbss) + *(COMMON) + /* Align here to ensure that the .bss section occupies space up to + _end. Align after .bss to ensure correct alignment even if the + .bss section disappears because there are no input sections. */ + . = ALIGN(32 / 8); + _bss_end = .; + } > ram /* in RAM */ + + . = ALIGN (8); + _empty_ram = .; + +/* This symbol defines end of code/data sections. Heap starts here. */ + PROVIDE(end = .); +} + GROUP( + libgcc.a + libg.a + libc.a + libm.a + libnosys.a + ) \ No newline at end of file diff --git a/beken_os/beken378/build/bk7231n_ota.ld b/beken_os/beken378/build/bk7231n_ota.ld new file mode 100755 index 0000000..46f34f5 --- /dev/null +++ b/beken_os/beken378/build/bk7231n_ota.ld @@ -0,0 +1,514 @@ +/* + * Script for GNU linker. + * Describes layout of sections, location of stack. + * + * In this case vectors are at location 0 (reset @ 0x08) + * + * +------------+ 0x00400020 + * data | + * end + * |(heap) | + * . . + * . . + * |(heap limit)| + * + * |- - - - - - | + * stack bottom 256k + * +------------+ + * + * +------------+ 0x0000000 + * |vectors | + * | | + * |------------+ + * |text | + * |data | + * | | 1024k + * +------------+ + */ + + +/* Split memory into area for vectors and ram */ +MEMORY +{ + flash (rx) : ORIGIN = 0x00010000, LENGTH = 2M - 64k + tcm (rw!x): ORIGIN = 0x003F0000, LENGTH = 55k + dtcm (rw!x): ORIGIN = 0x003FDC00, LENGTH = 5k - 512 + itcm (rwx): ORIGIN = 0X003FEE00, LENGTH = 4608 + ram (rw!x): ORIGIN = 0x00400100, LENGTH = 192k - 0x100 +} + +OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") +OUTPUT_ARCH(arm) +ENTRY(_vector_start); +_vector_start = ORIGIN(flash); + +SECTIONS +{ +/* vectors go to vectors region */ + . = ORIGIN(flash); + .vectors : + { + KEEP(*(*.vectors)) + KEEP( *(*.boot)) + } > flash + +/* instructions go to the text region*/ + + . = ORIGIN(itcm); + .itcm.code ALIGN(8) : + { + /* itcm 8KB code */ + *(.text.intc_hdl_entry) + *(.text.intc_irq) + *(.text.intc_fiq) + *(.text.bk_timer_isr) + *(.text.power_save_wakeup_isr) + *(.text.bmsg_rx_sender) + *(.text.bmsg_null_sender) + *(.text.fclk_get_tick) + *(.text.flash_read_sr) + *(.text.flash_write_sr) + *(.text.flash_clr_qwfr) + *(.text.set_flash_protect) + *(.text.flash_read) + *(.text.flash_read_data) + *(.text.flash_set_qe) + *(.text.flash_set_qwfr) + *(.text.flash_set_line_mode*) + *(.text.flash_get_line_mode) + *(.text.flash_write) + *(.text.flash_ctrl) + *(.text.power_save_dtim_wake) + *(.text.sctrl_fix_dpll_div) + + *(.text.vTaskSuspendAll) + *(.text.xTaskGetTickCount) + *(.text.xTaskGetTickCountFromISR) + *(.text.vTaskStepTick) + *(.text.xTaskIncrementTick) + *(.text.xTaskResumeAll) + *(.text.vTaskSwitchContext) + *(.text.vApplicationIdleHook) + *(.text.platform_is_in_irq_context) + *(.text.platform_is_in_fiq_context) + *(.text.platform_is_in_interrupt_context) + *(.text.portENABLE_IRQ) + *(.text.portENABLE_FIQ) + *(.text.portDISABLE_FIQ) + *(.text.portDISABLE_IRQ) + *(.text.vPortEnterCritical) + *(.text.vPortExitCritical) + } > itcm AT>flash + _itcmcode_flash_begin = LOADADDR(.itcm.code); + _itcmcode_ram_begin = ADDR(.itcm.code); + _itcmcode_ram_end = _itcmcode_ram_begin + SIZEOF(.itcm.code); + + . = ALIGN(0x8); +/* code, instructions.for example: i=i+1; */ + .text : + { + *(.text) + *(.text.*) + *(.stub) + /* .gnu.warning sections are handled specially by elf32.em. */ + *(.gnu.warning) + *(.gnu.linkonce.t*) + *(.glue_7t) *(.glue_7) + } > flash + +/* read only data.for example: const int rom_data[3]={1,2,3}; */ + .rodata ALIGN(8) : + { + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r*) + } > flash + + .ARM.exidx : + { + *(.ARM.exidx*) + *(.gnu.linkonce.armexidx.*) + } > flash + + . = ORIGIN(tcm); + .tcm ALIGN(8) : + { + /*beken378*os*.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *beken378*driver*.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *beken378*func*.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *beken378*app*.o(.bss .bss.* .scommon .sbss .dynbss COMMON)*/ + + /* beken_wifi.a */ + /*hal_desc.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *scanu.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *tx_swdesc.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *vif_mgmt.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *rxu_cntrl.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *rxl_hwdesc.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *scan_task.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *scan.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *scan_shared.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *scanu_shared.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *scanu_task.o(.bss .bss.* .scommon .sbss .dynbss COMMON)*/ + + /*mem.c.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *ip.c.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *memp.c.o(.bss .bss.* .scommon .sbss .dynbss COMMON)*/ + + *ps.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *rc.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *rwnx.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *rx_swdesc.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *rxu_cntrl.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *rxl_cntrl.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *rxl_hwdesc.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *sta_mgmt.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *scan_task.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *scan.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *scanu.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *scanu_shared.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *scanu_task.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *sm.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *sm_task.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *me.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *mm.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *mm_bcn.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *mm_task.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *mm_timer.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *td.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *tx_swdesc.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *txl_buffer.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *txl_cfm.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *txl_cntrl.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *vif_mgmt.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + + *app_bk.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *ate_app.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *param_config.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *sa_ap.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *sa_station.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *ieee802_11_demo.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *ble.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *prf.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *comm.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *comm_task.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *sdp_service.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *sdp_service_task.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *app_ble.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *app_comm.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *app_sdp.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *app_sec.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *app_task.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *common_list.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *common_utils.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *RomCallFlash.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *dbg.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *dbg_mwsgen.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *dbg_swdiag.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *dbg_task.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *ecc_p256.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *ble_rf_xvr.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *rwip.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *uart.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *app_ble.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *app_ble_task.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *app_comm.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *app_task.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *prf.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *prf_utils.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *comm.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *comm_task.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *ble_ui.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *ble_rf_port.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *rf_xvr.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *uart_ble.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *ble_main.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *rwble.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *rwip.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *dd.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *drv_model.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *dma.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *driver.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *arch_main.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *boot_handlers.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *boot_vectors.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *fft.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *flash.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *general_dma.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *gpio.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *i2s.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *icu.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *intc.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *irda.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *mac_phy_bypass.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *phy_trident.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *bk_timer.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *mcu_ps_timer.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *pwm.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *pwm_new.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *rw_platf_pub.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *saradc.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *spi.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *spidma.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *sys_ctrl.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *Retarget.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *uart_bk.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *wdt.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *bk7231N_cal.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *bk7231U_cal.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *manual_cal_bk7231U.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *func.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *ddrv.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *fake_socket.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *signal.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *sk_intf.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *main_none.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *ap_config.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *ap_drv_ops.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *ap_list.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *ap_mlme.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *authsrv.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *beacon.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *bss_load.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *dfs.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *drv_callbacks.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *eap_user_db.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *hostapd.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *hw_features.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *ieee802_11.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *ieee802_11_auth.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *ieee802_11_ht.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *ieee802_11_shared.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *ieee802_1x.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *pmksa_cache_auth.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *sta_info.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *tkip_countermeasures.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *utils.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *wmm.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *wpa_auth.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *wpa_auth_glue.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *wpa_auth_ie.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *hw_features_common.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *ieee802_11_common.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *wpa_common.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *aes-internal-dec.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *aes-internal-enc.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *aes-internal.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *aes-unwrap.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *aes-wrap.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *bk_md5.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *bk_sha1.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *md5-internal.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *rc4.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *sha1-internal.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *sha1-pbkdf2.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *sha1-prf.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *tls_none.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *drivers.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *driver_beken.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *driver_common.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *eapol_auth_sm.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *eap_common.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *eap_server.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *eap_server_methods.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *l2_packet_none.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *preauth.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *wpa.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *wpa_ie.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *common.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *eloop.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *os_none.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *wpabuf.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *ap.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *blacklist.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *bss.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *config.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *config_none.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *eap_register.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *events.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *main_supplicant.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *notify.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *wmm_ac.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *wpas_glue.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *wpa_scan.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *wpa_supplicant.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *hostapd_intf.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *reconnect_startup.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *role_launch.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *dhcp-server-main.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *dhcp-server.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *ethernetif.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *net.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *sys_arch.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *api_lib.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *api_msg.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *err.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *netbuf.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *netdb.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *netifapi.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + + *fake_clock.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *start_type.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *target_util.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *net_param.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *low_voltage_ps.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *manual_ps.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *mcu_ps.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *power_save.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *rx_sensitivity.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *tx_evm.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *rw_ieee80211.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *rw_msdu.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *rw_msg_rx.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *rw_msg_tx.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *gpio_uart.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *pwm_uart.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *spidma_intf.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *temp_detect.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *tuya_pwm.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *cmd_evm.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *cmd_help.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *cmd_reg.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *cmd_rx_sensitivity.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *command_line.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *command_table.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *udebug.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *BkDriverFlash.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *BkDriverGpio.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *BkDriverPwm.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *BkDriverRng.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *BkDriverTimer.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *BkDriverUart.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *BkDriverWdg.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *wlan_cli.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *wlan_ui.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *croutine.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *event_groups.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *list.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *port.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *heap_6.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *queue.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *tasks.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *timers.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *rtos_pub.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *mem_arch.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *str_arch.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + + *sockets.c.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *tcpip.c.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *def.c.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *dns.c.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *inet_chksum.c.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *init.c.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *autoip.c.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + /*dhcp.c.o(.bss .bss.* .scommon .sbss .dynbss COMMON)*/ + + *etharp.c.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *icmp.c.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *igmp.c.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *ip4.c.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *ip4_addr.c.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *ip4_frag.c.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *dhcp6.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *ethip6.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *icmp6.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *inet6.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *ip6.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *ip6_addr.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *ip6_frag.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *mld6.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *nd6.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *netif.c.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *pbuf.c.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *raw.c.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *stats.c.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *sys.c.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *tcp.c.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *tcp_in.c.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *tcp_out.c.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *timeouts.c.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *udp.c.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *ethernet.c.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + + *ip.c.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *memp.c.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *mem.c.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *bluetooth*.c.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + + *tuya_iot_com_api.c.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + /* *aes.c.o(.bss .bss.* .scommon .sbss .dynbss COMMON) */ + *tuya_tls.c.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *tuya_iot_api_pre_handle.c.o(.bss .bss.* .scommon .bss .dynbss COMMON) + *ble_att_svr.c.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *tal_wifi.c.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *tkl_wifi.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *tkl*.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *tal*.c.o(.bss .bss.* .scommon .sbss .dynbss COMMON) + *boot_handlers.O(.bss .bss.* .scommon .sbss .dynbss COMMON) + } >tcm AT>flash + _tcmbss_start = ADDR(.tcm); + _tcmbss_end = _tcmbss_start + SIZEOF(.tcm); + + . = ALIGN(0x8); + .gfw_cmd : + { + KEEP(*(*.gfw_cmd)) + KEEP(*(*.gfw_cmd.*)) + } > flash + _gfw_cmd_begin = ADDR(.gfw_cmd); + _gfw_cmd_end = _gfw_cmd_begin + SIZEOF(.gfw_cmd); + + . = ORIGIN(dtcm); + .user.ram.data ALIGN(8) : + { + __user_ram_data_start__ = .; + *(.user.ram.data*) + __user_ram_data_end__ = .; + } >dtcm AT>flash + + . = ORIGIN(ram); +/* globals.for example: int ram_data[3]={4,5,6}; */ /* VMA in RAM, but keep LMA in flash */ + _begin_data = .; + .data : + { + *(.data .data.*) + *(.sdata) + *(.gnu.linkonce.d*) + SORT(CONSTRUCTORS) + } >ram AT>flash + _end_data = .; + + /* Loader will copy data from _flash_begin to _ram_begin..ram_end */ + _data_flash_begin = LOADADDR(.data); + _data_ram_begin = ADDR(.data); + _data_ram_end = .; + +/* uninitialized data section - global int i; */ + .bss ALIGN(8): + { + _bss_start = .; + *(.bss .bss.*) + *(.scommon) + *(.sbss) + *(.dynbss) + *(COMMON) + /* Align here to ensure that the .bss section occupies space up to + _end. Align after .bss to ensure correct alignment even if the + .bss section disappears because there are no input sections. */ + . = ALIGN(32 / 8); + _bss_end = .; + } > ram /* in RAM */ + + . = ALIGN (8); + _empty_ram = .; + +/* This symbol defines end of code/data sections. Heap starts here. */ + PROVIDE(end = .); +} + GROUP( + libgcc.a + libg.a + libc.a + libm.a + libnosys.a + ) diff --git a/beken_os/beken378/build/encrypt.bat b/beken_os/beken378/build/encrypt.bat new file mode 100755 index 0000000..5b3e347 --- /dev/null +++ b/beken_os/beken378/build/encrypt.bat @@ -0,0 +1 @@ +encrypt.exe rwnx_fmac.bin 00000000 \ No newline at end of file diff --git a/beken_os/beken378/build/encrypt.exe b/beken_os/beken378/build/encrypt.exe new file mode 100755 index 0000000..37aa6df Binary files /dev/null and b/beken_os/beken378/build/encrypt.exe differ diff --git a/beken_os/beken378/build/itcm_load_script.ini b/beken_os/beken378/build/itcm_load_script.ini new file mode 100755 index 0000000..0e869d0 --- /dev/null +++ b/beken_os/beken378/build/itcm_load_script.ini @@ -0,0 +1,25 @@ +/******************************************************************************/ +/* RAM.INI: RAM Initialization File */ +/******************************************************************************/ +// <<< Use Configuration Wizard in Context Menu >>> // +/******************************************************************************/ +/* This file is part of the uVision/ARM development tools. */ +/* Copyright (c) 2005-2008 Keil Software. All rights reserved. */ +/* This software may only be used under the terms of a valid, current, */ +/* end user licence from KEIL for a compatible version of KEIL software */ +/* development tools. Nothing else gives you the right to use this software. */ +/******************************************************************************/ + +FUNC void Setup(void) { + PC = _RDWORD(0x00000000); // Setup Program Counter +} + +FUNC void Init(void) { + _WDWORD(0x00920000, 0x00000001); +} + +Init(); + +LOAD .\build\macsw_fmac_arm\rwnx_fmac.axf INCREMENTAL // Download + +Setup(); // Setup for Running \ No newline at end of file diff --git a/beken_os/beken378/build/map-gnuarm.txt b/beken_os/beken378/build/map-gnuarm.txt new file mode 100755 index 0000000..c407fbd --- /dev/null +++ b/beken_os/beken378/build/map-gnuarm.txt @@ -0,0 +1,133 @@ +/* configure the CPU type */ +OUTPUT_ARCH(arm) +/* link with the standard c library */ +INPUT(-lc) +/* link with the standard GCC library */ +INPUT(-lgcc) +/* configure the entry point */ +ENTRY(vectors) + +MEMORY +{ + /* the internal SRAM */ + rom (wx) : ORIGIN = 0x0, LENGTH = 128K + ram (wx) : ORIGIN = 0x400000, LENGTH = 128K + + /* the shared RAM */ + sharedram (rw!x) : ORIGIN = 0x10000000, LENGTH = 256K + + /* Fake LA memory */ + lamac_memory (!rx) : ORIGIN = 0x11000000, LENGTH = 1024K + laphy_memory (!rx) : ORIGIN = 0x11800000, LENGTH = 1024K + + /* the MACHW MIB location */ + machw_mib_loc (rw!x) : ORIGIN = 0x10B00800, LENGTH = 1K +} + +/* configure the stack sizes */ +stack_len_fiq = 0x3F0; +stack_len_irq = 0x10; +stack_len_svc = 0x3F0; +stack_len_unused = 0x10; + +SECTIONS +{ + + + /* shared RAM */ + SHAREDRAM ORIGIN(sharedram) : + { + _sshram = . ; + *ipc_shared.o(COMMON) + *hal_desc.o(COMMON) + *txl_buffer_shared.o(COMMON) + *txl_frame_shared.o(COMMON) + *la_shared.o(COMMON) + _eshram = . ; + } + + /* MAC logic analyzer RAM */ + LARAMMAC : + { + _slarammac = . ; + *la_mem_mac.o(COMMON) + _elarammac = . ; + } > lamac_memory + + /* PHY logic analyzer RAM */ + LARAMPHY : + { + _slaramphy = . ; + *la_mem_phy.o(COMMON) + _elaramphy = . ; + } > laphy_memory + + /* MAC HW MIBs */ + MACHW_MIB ORIGIN(machw_mib_loc) : + { + _smachw_mib = . ; + *hal_mib.o(COMMON) + _emachw_mib = . ; + } > machw_mib_loc + + EXEC_RAM_TEXT 0x0 : + { + /* the address 0 must contain the boot vectors */ + *boot_vectors.o(.text) + /* immediately followed by the boot handlers */ + *boot_handlers.o(.text) + *(.text) + *(.rodata) + } > rom + + /* ram data immediately follows the TEXT */ + RAM_DATA : + { + *(.data) + } > ram AT > rom + + /* BSS section */ + RAM_BSS : + { + bss_base = .; + *(.bss) + *(COMMON) + bss_end = .; + } > ram AT > rom + bss_length = bss_end - bss_base; + + /* UNUSED STACK */ + RAM_STACK_UNUSED ORIGIN(ram) + LENGTH(ram) - stack_len_fiq - stack_len_irq - stack_len_svc - stack_len_unused : + { + stack_base_unused = .; + *ipc_shared.o(.bss) + . = stack_len_unused; + } > ram AT > rom + + /* SVC STACK */ + RAM_STACK_SVC ORIGIN(ram) + LENGTH(ram) - stack_len_fiq - stack_len_irq - stack_len_svc : + { + stack_base_svc = .; + . = stack_len_svc; + } > ram AT > rom + + /* IRQ STACK */ + RAM_STACK_IRQ ORIGIN(ram) + LENGTH(ram) - stack_len_fiq - stack_len_irq : + { + stack_base_irq = .; + . = stack_len_irq; + } > ram AT > rom + + /* FIQ STACK */ + RAM_STACK_FIQ ORIGIN(ram) + LENGTH(ram) - stack_len_fiq : + { + stack_base_fiq = .; + . = stack_len_fiq; + } > ram AT > rom + + + + + +} + diff --git a/beken_os/beken378/build/post-build-steps.bat b/beken_os/beken378/build/post-build-steps.bat new file mode 100755 index 0000000..e65e0fd --- /dev/null +++ b/beken_os/beken378/build/post-build-steps.bat @@ -0,0 +1,2 @@ +arm-none-eabi-objcopy.exe -O binary .\beken7231.elf .\beken7231.bin +..\beken378\build\encrypt.exe .\beken7231.bin 0000000 diff --git a/beken_os/beken378/build/scatter_rwnx.scat b/beken_os/beken378/build/scatter_rwnx.scat new file mode 100755 index 0000000..50b75df --- /dev/null +++ b/beken_os/beken378/build/scatter_rwnx.scat @@ -0,0 +1,56 @@ + +;/* the internal SRAM */ +;rom (wx) : ORIGIN = 0x0, LENGTH = 128K +;ram (wx) : ORIGIN = 0x400000, LENGTH = 128K +; +;/* the shared RAM */ +;sharedram (rw!x) : ORIGIN = 0x10000000, LENGTH = 256K +; +;/* Fake LA memory */ +;lamac_memory (!rx) : org = 0x11000000, len = 1024K +;laphy_memory (!rx) : org = 0x11800000, len = 1024K +; +;/* the MACHW MIB location */ +;machw_mib_loc (rw!x) : ORIGIN = 0x10B00800, LENGTH = 1K + +SECTIONS 0x0000 +{ + ROM 0x000000 + { + *boot_vectors.o(SYS_BOOT, +First) + *boot_handlers.o(SYS_BOOT) + + *(+RO) + } + + RAM_DATA 0x400000 + { + *(+RW) + } + + RAM_BSS +0 + { + *(+ZI) + } + + RAM_STACK_UNUSED 0x440000 - 0x3F0 - 0x7F0 - 0xFF0 - 0x7F0 - 0x10 EMPTY 0x10 + { + } + + RAM_STACK_SVC 0x440000 - 0x3F0 - 0x7F0 - 0xFF0 - 0x7F0 EMPTY 0xFF0 + { + } + + RAM_STACK_IRQ 0x440000 - 0x3F0 - 0x7F0 - 0x7F0 EMPTY 0x7F0 + { + } + + RAM_STACK_FIQ 0x440000 - 0x3F0 - 0x7F0 EMPTY 0x7F0 + { + } + + RAM_STACK_SYS 0x440000 - 0x3F0 EMPTY 0x3F0 + { + } +} + diff --git a/beken_os/beken378/common/doubly_list.h b/beken_os/beken378/common/doubly_list.h new file mode 100755 index 0000000..d34ddcb --- /dev/null +++ b/beken_os/beken378/common/doubly_list.h @@ -0,0 +1,224 @@ +#ifndef _DOUBLY_LIST_H +#define _DOUBLY_LIST_H + +#ifndef offsetof +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +#endif +#define list_entry(ptr, type, member) ((type *)((char *)ptr - offsetof(type,member))) + +/* + * Simple doubly linked list implementation. + * + * Some of the internal functions ("__xxx") are useful when + * manipulating whole lists rather than single entries, as + * sometimes we already know the next/prev entries and we can + * generate better code by using them directly rather than + * using the generic single-entry routines. + */ +typedef struct list_head +{ + struct list_head *next, *prev; +}LIST_HEADER_T; + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define LIST_HEAD_DEFINE(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +#define INIT_LIST_HEAD(ptr) do { \ + (ptr)->next = (ptr); (ptr)->prev = (ptr); \ +} while (0) + +/* + * Insert a new_node entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +__INLINE void __list_add(struct list_head *new_node, struct list_head *prev, struct list_head *next) +{ + next->prev = new_node; + new_node->next = next; + new_node->prev = prev; + prev->next = new_node; +} + +/** + * list_add - add a new_node entry + * @new_node: new_node entry to be added + * @head: list head to add it after + * + * Insert a new_node entry after the specified head. + * This is good for implementing stacks. + */ +__INLINE void list_add_head(struct list_head *new_node, struct list_head *head) +{ + __list_add(new_node, head, head->next); +} + +/** + * list_add_tail - add a new_node entry + * @new_node: new_node entry to be added + * @head: list head to add it before + * + * Insert a new_node entry before the specified head. + * This is useful for implementing queues. + */ +__INLINE void list_add_tail(struct list_head *new_node, struct list_head *head) +{ + __list_add(new_node, head->prev, head); +} + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +__INLINE void __list_del(struct list_head * prev, struct list_head * next) +{ + next->prev = prev; + prev->next = next; +} + +/** + * list_del - deletes entry from list. + * @entry: the element to delete from the list. + * Note: list_empty on entry does not return true after this, the entry is + * in an undefined state. + */ +__INLINE void list_del(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); +} + +/** + * list_del_init - deletes entry from list and reinitialize it. + * @entry: the element to delete from the list. + */ +__INLINE void list_del_init(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + INIT_LIST_HEAD(entry); +} + +/** + * list_move - delete from one list and add as another's head + * @list: the entry to move + * @head: the head that will precede our entry + */ +__INLINE void list_move(struct list_head *list, struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add_head(list, head); +} + +/** + * list_move_tail - delete from one list and add as another's tail + * @list: the entry to move + * @head: the head that will follow our entry + */ +__INLINE void list_move_tail(struct list_head *list, + struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add_tail(list, head); +} + +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +__INLINE unsigned int list_empty(const struct list_head *head) +{ + return head->next == head; +} + +__INLINE void __list_splice(struct list_head *list, + struct list_head *head) +{ + struct list_head *first = list->next; + struct list_head *last = list->prev; + struct list_head *at = head->next; + + first->prev = head; + head->next = first; + + last->next = at; + at->prev = last; +} + +/** + * list_splice - join two lists + * @list: the new_node list to add. + * @head: the place to add it in the first list. + */ +__INLINE void list_splice(struct list_head *list, struct list_head *head) +{ + if (!list_empty(list)) + __list_splice(list, head); +} + +/** + * list_splice_init - join two lists and reinitialise the emptied list. + * @list: the new_node list to add. + * @head: the place to add it in the first list. + * + * The list at @list is reinitialised + */ +__INLINE void list_splice_init(struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) { + __list_splice(list, head); + INIT_LIST_HEAD(list); + } +} + +__INLINE void list_switch(struct list_head **list1, + struct list_head ** list2) +{ + struct list_head * temp; + + temp = *list1; + *list1 = *list2; + *list2 = temp; +} + + + +/** + * list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop counter. + * @head: the head for your list. + */ +#define list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + + +/** + * list_for_each_safe - iterate over a list safe against removal of list entry + * @pos: the &struct list_head to use as a loop counter. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each_safe(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ + pos = n, n = pos->next) + +/** + * list_size + * @head: the head for your list. + */ +__INLINE unsigned int list_size(struct list_head *list) { + unsigned int num_of_list=0; + struct list_head *n, *pos; + + list_for_each_safe(pos, n, list) + num_of_list++; + + return num_of_list; +} + +#endif /* _DOUBLY_LIST_H */ diff --git a/beken_os/beken378/common/fifo.h b/beken_os/beken378/common/fifo.h new file mode 100755 index 0000000..b26770e --- /dev/null +++ b/beken_os/beken378/common/fifo.h @@ -0,0 +1,202 @@ +#ifndef _FIFO_H_ +#define _FIFO_H_ + +#include "include.h" +#include "generic.h" +#include "mem_pub.h" +#include "mem_pub.h" +#if CFG_SUPPORT_ALIOS +#include "ll.h" +#endif + +typedef struct kfifo +{ + unsigned int in; + unsigned int out; + + unsigned int mask; + + unsigned int size; + unsigned char *buffer; +}KFIFO_T, *KFIFO_PTR; + +/** + * kfifo_init - allocates a new FIFO using a preallocated buffer + * @buffer: the preallocated buffer to be used. + * @size: the size of the internal buffer, this have to be a power of 2. + * @gfp_mask: get_free_pages mask, passed to ke_malloc() + * @lock: the lock to be used to protect the fifo buffer + * + * Do NOT pass the kfifo to kfifo_free() after use ! Simply free the + * struct kfifo with ke_free(). + */ +__INLINE struct kfifo *kfifo_init(unsigned char *buffer, unsigned int size) +{ + struct kfifo *fifo; + + /* size must be a power of 2 */ + BUG_ON(size & (size - 1)); + + fifo = os_malloc(sizeof(struct kfifo)); + if (!fifo) + return NULLPTR; + + fifo->buffer = buffer; + fifo->size = size; + fifo->in = 0; + fifo->out = 0; + fifo->mask = fifo->size - 1; + + return fifo; +} + +/** + * kfifo_alloc - allocates a new FIFO and its internal buffer + * @size: the size of the internal buffer to be allocated. + * @gfp_mask: get_free_pages mask, passed to ke_malloc() + * @lock: the lock to be used to protect the fifo buffer + * + * The size will be rounded-up to a power of 2. + */ +__INLINE struct kfifo *kfifo_alloc(unsigned int size) +{ + unsigned char *buffer; + struct kfifo *ret; + + buffer = os_malloc(size); + if (!buffer) + return 0; + + ret = kfifo_init(buffer, size); + + if (!(ret)) + os_free(buffer); + + return ret; +} + +/** + * kfifo_free - frees the FIFO + * @fifo: the fifo to be freed. + */ +__INLINE void kfifo_free(struct kfifo *fifo) +{ + os_free(fifo->buffer); + fifo->buffer = 0; + + os_free(fifo); +} + +/** + * __kfifo_put - puts some data into the FIFO, no locking version + * @fifo: the fifo to be used. + * @buffer: the data to be added. + * @len: the length of the data to be added. + * + * This function copies at most 'len' bytes from the 'buffer' into + * the FIFO depending on the free space, and returns the number of + * bytes copied. + * + * Note that with only one concurrent reader and one concurrent + * writer, you don't need extra locking to use these functions. + */ +__INLINE unsigned int kfifo_put(struct kfifo *fifo, + unsigned char *buffer, unsigned int len) +{ + unsigned int l; + GLOBAL_INT_DECLARATION(); + + GLOBAL_INT_DISABLE(); + len = min(len, fifo->size - fifo->in + fifo->out); + + /* first put the data starting from fifo->in to buffer end */ + l = min(len, fifo->size - (fifo->in & (fifo->size - 1))); + os_memcpy(fifo->buffer + (fifo->in & (fifo->size - 1)), buffer, l); + + /* then put the rest (if any) at the beginning of the buffer */ + os_memcpy(fifo->buffer, buffer + l, len - l); + + fifo->in += len; + GLOBAL_INT_RESTORE(); + + return len; +} + +/** + * __kfifo_get - gets some data from the FIFO, no locking version + * @fifo: the fifo to be used. + * @buffer: where the data must be copied. + * @len: the size of the destination buffer. + * + * This function copies at most 'len' bytes from the FIFO into the + * 'buffer' and returns the number of copied bytes. + * + * Note that with only one concurrent reader and one concurrent + * writer, you don't need extra locking to use these functions. + */ +__INLINE unsigned int kfifo_get(struct kfifo *fifo, + unsigned char *buffer, unsigned int len) +{ + unsigned int l; + GLOBAL_INT_DECLARATION(); + + GLOBAL_INT_DISABLE(); + len = min(len, fifo->in - fifo->out); + + /* first get the data from fifo->out until the end of the buffer */ + l = min(len, fifo->size - (fifo->out & (fifo->size - 1))); + os_memcpy(buffer, fifo->buffer + (fifo->out & (fifo->size - 1)), l); + + /* then get the rest (if any) from the beginning of the buffer */ + os_memcpy(buffer + l, fifo->buffer, len - l); + + fifo->out += len; + GLOBAL_INT_RESTORE(); + + return len; +} + +__INLINE unsigned int kfifo_data_size(struct kfifo *fifo) +{ + return (fifo->in - fifo->out); +} + +__INLINE unsigned int kfifo_unused(struct kfifo *fifo) +{ + return (fifo->mask + 1) - (fifo->in - fifo->out); +} + +__INLINE void kfifo_copy_out(struct kfifo *fifo, void *dst, + unsigned int len, unsigned int off) +{ + unsigned int size = fifo->mask + 1; + unsigned int l; + + off &= fifo->mask; + + l = min(len, size - off); + + os_memcpy(dst, (void *)(fifo->buffer + off), l); + os_memcpy((void *)((unsigned int)dst + l), (void *)fifo->buffer, len - l); + /* + * make sure that the data is copied before + * incrementing the fifo->out index counter + */ +} + +__INLINE unsigned int kfifo_out_peek(struct kfifo *fifo, + unsigned char *buffer, unsigned int len) +{ + unsigned int l; + + l = fifo->in - fifo->out; + if (len > l) + len = l; + + kfifo_copy_out(fifo, buffer, len, fifo->out); + + return len; +} +#endif // _FIFO_H_ +// eof + diff --git a/beken_os/beken378/common/generic.h b/beken_os/beken378/common/generic.h new file mode 100755 index 0000000..6e16e77 --- /dev/null +++ b/beken_os/beken378/common/generic.h @@ -0,0 +1,161 @@ +#ifndef _GENERIC_H_ +#define _GENERIC_H_ +#include +#include "include.h" + +typedef void (*FUNCPTR)(void); +typedef void (*FUNC_1PARAM_PTR)(void *ctxt); +typedef void (*FUNC_2PARAM_PTR)(void *arg, uint8_t vif_idx); + +#ifndef MAX +#define MAX(x, y) (((x) > (y)) ? (x) : (y)) +#endif +#ifndef MIN +#define MIN(x, y) (((x) < (y)) ? (x) : (y)) +#endif +#ifndef max +#define max(x, y) (((x) > (y)) ? (x) : (y)) +#endif +#ifndef min +#define min(x, y) (((x) < (y)) ? (x) : (y)) +#endif + +extern void bk_printf(const char *fmt, ...); +#define as_printf (bk_printf("%s:%d\r\n",__FUNCTION__,__LINE__)) + + +#if (0 == CFG_RELEASE_FIRMWARE) +#define ASSERT_EQ(a, b) \ +{ \ + if ((a) != (b)) \ + { \ + bk_printf("%s:%d %d!=%d\r\n",__FUNCTION__,__LINE__, (a), (b)); \ + while(1); \ + } \ +} +#define ASSERT_NE(a, b) \ +{ \ + if ((a) == (b)) \ + { \ + bk_printf("%s:%d %d==%d\r\n",__FUNCTION__,__LINE__, (a), (b)); \ + while(1); \ + } \ +} +#define ASSERT_GT(a, b) \ +{ \ + if ((a) <= (b)) \ + { \ + bk_printf("%s:%d %d<=%d\r\n",__FUNCTION__,__LINE__, (a), (b)); \ + while(1); \ + } \ +} +#define ASSERT_GE(a, b) \ +{ \ + if ((a) < (b)) \ + { \ + bk_printf("%s:%d %d<%d\r\n",__FUNCTION__,__LINE__, (a), (b)); \ + while(1); \ + } \ +} +#define ASSERT_LT(a, b) \ +{ \ + if ((a) >= (b)) \ + { \ + bk_printf("%s:%d %d>=%d\r\n",__FUNCTION__,__LINE__, (a), (b)); \ + while(1); \ + } \ +} +#define ASSERT_LE(a, b) \ +{ \ + if ((a) > (b)) \ + { \ + bk_printf("%s:%d %d>%d\r\n",__FUNCTION__,__LINE__, (a), (b)); \ + while(1); \ + } \ +} +#define ASSERT(exp) \ +{ \ + if ( !(exp) ) \ + { \ + as_printf; \ + while(1); \ + } \ +} +#else +#define ASSERT_EQ(exp) +#define ASSERT_NE(exp) +#define ASSERT_GT(exp) +#define ASSERT_GE(exp) +#define ASSERT_LT(exp) +#define ASSERT_LE(exp) +#define ASSERT(exp) +#endif + +#define BUG_ON(exp) ASSERT(!(exp)) + +#ifndef NULL +#define NULL (0L) +#endif + +#ifndef NULLPTR +#define NULLPTR ((void *)0) +#endif + +#ifndef BIT +#define BIT(i) (1UL << (i)) +#endif + +static inline __uint16_t __bswap16(__uint16_t _x) +{ + + return ((__uint16_t)((_x >> 8) | ((_x << 8) & 0xff00))); +} + +static inline __uint32_t __bswap32(__uint32_t _x) +{ + + return ((__uint32_t)((_x >> 24) | ((_x >> 8) & 0xff00) | + ((_x << 8) & 0xff0000) | ((_x << 24) & 0xff000000))); +} + +static inline __uint64_t __bswap64(__uint64_t _x) +{ + + return ((__uint64_t)((_x >> 56) | ((_x >> 40) & 0xff00) | + ((_x >> 24) & 0xff0000) | ((_x >> 8) & 0xff000000) | + ((_x << 8) & ((__uint64_t)0xff << 32)) | + ((_x << 24) & ((__uint64_t)0xff << 40)) | + ((_x << 40) & ((__uint64_t)0xff << 48)) | ((_x << 56)))); +} + +#define __swab16(x) __bswap16((__u8 *)&(x)) +#define __swab32(x) __bswap32((__u8 *)&(x)) + +#define cpu_to_le16(x) (x) +#define cpu_to_le32(x) (x) + +#define __cpu_to_be32(x) __swab32((x)) +#define __be32_to_cpu(x) __swab32((x)) +#define __cpu_to_be16(x) __swab16((x)) +#define __be16_to_cpu(x) __swab16((x)) + + +#define __htonl(_x) __bswap32(_x) +#define __htons(_x) __bswap16(_x) +#define __ntohl(_x) __bswap32(_x) +#define __ntohs(_x) __bswap16(_x) + +#define ___htonl(x) __cpu_to_be32(x) +#define ___htons(x) __cpu_to_be16(x) +#define ___ntohl(x) __be32_to_cpu(x) +#define ___ntohs(x) __be16_to_cpu(x) + +#ifdef LWIP_DONT_PROVIDE_BYTEORDER_FUNCTIONS +#define htons(x) __htons(x) +#define ntohs(x) __ntohs(x) +#define htonl(x) __htonl(x) +#define ntohl(x) __ntohl(x) +#endif + +#endif // _GENERIC_H_ + diff --git a/beken_os/beken378/common/include.h b/beken_os/beken378/common/include.h new file mode 100755 index 0000000..8ab9dd1 --- /dev/null +++ b/beken_os/beken378/common/include.h @@ -0,0 +1,13 @@ +#ifndef _INCLUDES_H_ +#define _INCLUDES_H_ + +#include "sys_config.h" +#include "typedef.h" +#include "generic.h" +#include "compiler.h" +#if (!CFG_SUPPORT_ALIOS) +#include "arch.h" +#endif + + +#endif // _INCLUDES_H_ diff --git a/beken_os/beken378/common/typedef.h b/beken_os/beken378/common/typedef.h new file mode 100755 index 0000000..a120f43 --- /dev/null +++ b/beken_os/beken378/common/typedef.h @@ -0,0 +1,69 @@ +#ifndef _TYPEDEF_H_ +#define _TYPEDEF_H_ + +#include + +typedef unsigned char uint8; /* unsigned 8 bit quantity */ +typedef signed char int8; /* signed 8 bit quantity */ +typedef unsigned short uint16; /* unsigned 16 bit quantity */ +typedef signed short int16; /* signed 16 bit quantity */ +typedef unsigned int uint32; /* unsigned 32 bit quantity */ +typedef signed int int32; /* signed 32 bit quantity */ +typedef unsigned long long uint64; /* unsigned 32 bit quantity */ +typedef signed long long int64; /* signed 32 bit quantity */ + +typedef unsigned char UINT8; /* Unsigned 8 bit quantity */ +typedef signed char INT8; /* Signed 8 bit quantity */ +typedef unsigned short UINT16; /* Unsigned 16 bit quantity */ +typedef signed short INT16; /* Signed 16 bit quantity */ +typedef unsigned int UINT32; /* Unsigned 32 bit quantity */ +typedef signed int INT32; /* Signed 32 bit quantity */ +typedef unsigned long long UINT64; /* Unsigned 32 bit quantity */ +typedef signed long long INT64; /* Signed 32 bit quantity */ +typedef float FP32; /* Single precision floating point */ +typedef double FP64; /* Double precision floating point */ +typedef unsigned int size_t; +typedef unsigned char BOOLEAN; +typedef unsigned char BOOL; +//typedef unsigned char bool; + +#define LPVOID void * +#define VOID void + +typedef volatile signed long VS32; +typedef volatile signed short VS16; +typedef volatile signed char VS8; + +typedef volatile signed long const VSC32; +typedef volatile signed short const VSC16; +typedef volatile signed char const VSC8; + +typedef volatile unsigned long VU32; +typedef volatile unsigned short VU16; +typedef volatile unsigned char VU8; + +typedef volatile unsigned long const VUC32; +typedef volatile unsigned short const VUC16; +typedef volatile unsigned char const VUC8; + +#ifndef HAVE_UTYPES +typedef unsigned char u8; +typedef signed char s8; +typedef unsigned short u16; +typedef signed short s16; +typedef unsigned int u32; +typedef signed int s32; +#endif /* HAVE_UTYPES */ + +typedef unsigned long long u64; +typedef long long s64; + +typedef unsigned int __u32; +typedef int __s32; +typedef unsigned short __u16; +typedef signed short __s16; +typedef unsigned char __u8; + +#endif // _TYPEDEF_H_ +// eof + diff --git a/beken_os/beken378/demo/ieee802_11_demo.c b/beken_os/beken378/demo/ieee802_11_demo.c new file mode 100755 index 0000000..f84e7a4 --- /dev/null +++ b/beken_os/beken378/demo/ieee802_11_demo.c @@ -0,0 +1,351 @@ +#include "include.h" +#include "common.h" +#include "rwnx_config.h" +#include "app.h" + +#if (NX_POWERSAVE) +#include "ps.h" +#endif //(NX_POWERSAVE) + +#include "sa_ap.h" +#include "sa_station.h" +#include "main_none.h" +#include "sm.h" + +#include "sys_rtos.h" +#include "rtos_pub.h" +#include "rtos_error.h" + +#include "wlan_ui_pub.h" +#include "uart_pub.h" +#include "mem_pub.h" +#include "str_pub.h" +#include "ieee802_11_demo.h" +#include "rw_pub.h" +#include "ethernet_intf.h" +#include "ieee802_11_defs.h" +#include "power_save_pub.h" + +#include "lwip/net.h" + +#if CFG_ROLE_LAUNCH +#include "role_launch.h" +#endif + +static void scan_cb(void *ctxt, uint8_t param) +{ +#if !CFG_WPA_CTRL_IFACE + struct scanu_rst_upload *scan_rst; + ScanResult apList; + int i; + + apList.ApList = NULL; + scan_rst = sr_get_scan_results(); + if (scan_rst == NULL) { + apList.ApNum = 0; + return; + } else { + apList.ApNum = scan_rst->scanu_num; + } + if (apList.ApNum > 0) { + apList.ApList = (void *)os_malloc(sizeof(*apList.ApList) * apList.ApNum); + for (i = 0; i < scan_rst->scanu_num; i++) { + os_memcpy(apList.ApList[i].ssid, scan_rst->res[i]->ssid, 32); + apList.ApList[i].ApPower = scan_rst->res[i]->level; + } + } + if (apList.ApList == NULL) + apList.ApNum = 0; + + bk_printf("Got ap count: %d\r\n", apList.ApNum); + for (i = 0; i < apList.ApNum; i++) { + if (os_strlen(apList.ApList[i].ssid) >= SSID_MAX_LEN) { + char temp_ssid[33]; + os_memset(temp_ssid, 0, 33); + os_memcpy(temp_ssid, apList.ApList[i].ssid, 32); + bk_printf(" %s, RSSI=%d\r\n", temp_ssid, apList.ApList[i].ApPower); + } else { + bk_printf(" %s, RSSI=%d\r\n", apList.ApList[i].ssid, apList.ApList[i].ApPower); + } + } + bk_printf("Get ap end.......\r\n\r\n"); + + if (apList.ApList != NULL) { + os_free(apList.ApList); + apList.ApList = NULL; + } + +#if CFG_ROLE_LAUNCH + rl_pre_sta_set_status(RL_STATUS_STA_LAUNCHED); +#endif + + sr_release_scan_results(scan_rst); +#else /* CFG_WPA_CTRL_IFACE */ + static const char *crypto_str[] = { + "None", + "WEP", + "WPA_TKIP", + "WPA_AES", + "WPA2_TKIP", + "WPA2_AES", + "WPA2_MIXED", ////BK_SECURITY_TYPE_WPA3_SAE + "WPA3_SAE", /**< WPA3 SAE */ + "WPA3_WPA2_MIXED", /** WPA3 SAE or WPA2 AES */ + "AUTO", + }; + + ScanResult_adv apList; + if (wlan_sta_scan_result(&apList) == 0) { + int ap_num = apList.ApNum; + int i; + + bk_printf("Got ap count: %d\r\n", apList.ApNum); + for (i = 0; i < ap_num; i++) + bk_printf(" \"%s\", " MACSTR "\b, %d, %s, %d\n", + apList.ApList[i].ssid, MAC2STR(apList.ApList[i].bssid), + apList.ApList[i].ApPower, crypto_str[apList.ApList[i].security], + apList.ApList[i].channel); + os_free(apList.ApList); + } +#endif /* CFG_WPA_CTRL_IFACE */ +} + +void demo_scan_app_init(void) +{ + mhdr_scanu_reg_cb(scan_cb, 0); + bk_wlan_start_scan(); +} + +void demo_scan_adv_app_init(uint8_t *oob_ssid) +{ + uint8_t **ssid_array; + + ssid_array = &oob_ssid; + mhdr_scanu_reg_cb(scan_cb, 0); + + bk_printf("scan for ssid:%s\r\n", oob_ssid); + bk_wlan_start_assign_scan(ssid_array, 1); +} + +void demo_softap_app_init(char *ap_ssid, char *ap_key) +{ + network_InitTypeDef_st wNetConfig; + int len; + + os_memset(&wNetConfig, 0x0, sizeof(network_InitTypeDef_st)); + + len = os_strlen(ap_ssid); + if(SSID_MAX_LEN < len) + { + bk_printf("ssid name more than 32 Bytes\r\n"); + return; + } + + os_strcpy((char *)wNetConfig.wifi_ssid, ap_ssid); + os_strcpy((char *)wNetConfig.wifi_key, ap_key); + + wNetConfig.wifi_mode = SOFT_AP; + wNetConfig.dhcp_mode = DHCP_SERVER; + wNetConfig.wifi_retry_interval = 100; + os_strcpy((char *)wNetConfig.local_ip_addr, WLAN_DEFAULT_IP); + os_strcpy((char *)wNetConfig.net_mask, WLAN_DEFAULT_MASK); + os_strcpy((char *)wNetConfig.gateway_ip_addr, WLAN_DEFAULT_GW); + os_strcpy((char *)wNetConfig.dns_server_ip_addr, WLAN_DEFAULT_IP); + + bk_printf("ssid:%s key:%s\r\n", wNetConfig.wifi_ssid, wNetConfig.wifi_key); + bk_wlan_start(&wNetConfig); +} + +void demo_sta_app_init(char *oob_ssid,char *connect_key) +{ + network_InitTypeDef_st wNetConfig; + int len; + os_memset(&wNetConfig, 0x0, sizeof(network_InitTypeDef_st)); + + len = os_strlen(oob_ssid); + if(SSID_MAX_LEN < len) + { + bk_printf("ssid name more than 32 Bytes\r\n"); + return; + } + + os_strcpy((char *)wNetConfig.wifi_ssid, oob_ssid); + os_strcpy((char *)wNetConfig.wifi_key, connect_key); + + wNetConfig.wifi_mode = STATION; + wNetConfig.dhcp_mode = DHCP_CLIENT; + wNetConfig.wifi_retry_interval = 100; + + bk_printf("ssid:%s key:%s\r\n", wNetConfig.wifi_ssid, wNetConfig.wifi_key); + bk_wlan_start(&wNetConfig); +} + +void demo_sta_adv_app_init(char *oob_ssid,char *connect_key) +{ + network_InitTypeDef_adv_st wNetConfigAdv; + + os_memset( &wNetConfigAdv, 0x0, sizeof(network_InitTypeDef_adv_st) ); + + os_strcpy((char*)wNetConfigAdv.ap_info.ssid, oob_ssid); + hwaddr_aton("48:ee:0c:48:93:12", (unsigned char*)wNetConfigAdv.ap_info.bssid); + wNetConfigAdv.ap_info.security = SECURITY_TYPE_WPA2_MIXED; + wNetConfigAdv.ap_info.channel = 11; + + os_strcpy((char*)wNetConfigAdv.key, connect_key); + wNetConfigAdv.key_len = os_strlen(connect_key); + wNetConfigAdv.dhcp_mode = DHCP_CLIENT; + wNetConfigAdv.wifi_retry_interval = 100; + + bk_wlan_start_sta_adv(&wNetConfigAdv); +} + +void demo_wlan_app_init(VIF_ADDCFG_PTR cfg) +{ + network_InitTypeDef_st network_cfg; + + if(cfg->wlan_role == STATION) { + if(cfg->adv == 1) { + network_InitTypeDef_adv_st networkadv_cfg; + + os_memset( &networkadv_cfg, 0x0, sizeof(network_InitTypeDef_adv_st) ); + + os_strcpy((char*)networkadv_cfg.ap_info.ssid, cfg->ssid); + hwaddr_aton("48:ee:0c:48:93:12", (unsigned char*)networkadv_cfg.ap_info.bssid); + networkadv_cfg.ap_info.security = SECURITY_TYPE_WPA2_MIXED; + networkadv_cfg.ap_info.channel = 11; + + os_strcpy((char*)networkadv_cfg.key, cfg->key); + networkadv_cfg.key_len = os_strlen(cfg->key); + networkadv_cfg.dhcp_mode = DHCP_CLIENT; + networkadv_cfg.wifi_retry_interval = 100; + + bk_wlan_start_sta_adv(&networkadv_cfg); + return; + } else { + os_memset(&network_cfg, 0x0, sizeof(network_InitTypeDef_st)); + + os_strcpy((char *)network_cfg.wifi_ssid, cfg->ssid); + os_strcpy((char *)network_cfg.wifi_key, cfg->key); + + network_cfg.wifi_mode = STATION; + network_cfg.dhcp_mode = DHCP_CLIENT; + network_cfg.wifi_retry_interval = 100; + + bk_printf("ssid:%s key:%s\r\n", network_cfg.wifi_ssid, network_cfg.wifi_key); + } + } else if(cfg->wlan_role == SOFT_AP) { + + os_memset(&network_cfg, 0x0, sizeof(network_InitTypeDef_st)); + os_strcpy((char *)network_cfg.wifi_ssid, cfg->ssid); + os_strcpy((char *)network_cfg.wifi_key, cfg->key); + + network_cfg.wifi_mode = SOFT_AP; + network_cfg.dhcp_mode = DHCP_SERVER; + network_cfg.wifi_retry_interval = 100; + os_strcpy((char *)network_cfg.local_ip_addr, WLAN_DEFAULT_IP); + os_strcpy((char *)network_cfg.net_mask, WLAN_DEFAULT_MASK); + os_strcpy((char *)network_cfg.gateway_ip_addr, WLAN_DEFAULT_GW); + os_strcpy((char *)network_cfg.dns_server_ip_addr, WLAN_DEFAULT_IP); + + bk_printf("ssid:%s key:%s\r\n", network_cfg.wifi_ssid, network_cfg.wifi_key); + } + + bk_wlan_start(&network_cfg); + +} + +void demo_state_app_init(void) +{ + LinkStatusTypeDef linkStatus; + network_InitTypeDef_ap_st ap_info; + char ssid[33] = {0}; + #if CFG_IEEE80211N + bk_printf("sta: %d, softap: %d, b/g/n\r\n",sta_ip_is_start(),uap_ip_is_start()); + #else + bk_printf("sta: %d, softap: %d, b/g\r\n",sta_ip_is_start(),uap_ip_is_start()); + #endif + + if( sta_ip_is_start() ) + { + os_memset(&linkStatus, 0x0, sizeof(LinkStatusTypeDef)); + bk_wlan_get_link_status(&linkStatus); + os_memcpy(ssid, linkStatus.ssid, 32); + + bk_printf("sta:rssi=%d,ssid=%s,bssid=" MACSTR ",channel=%d,cipher_type:", + linkStatus.wifi_strength, ssid, MAC2STR(linkStatus.bssid), linkStatus.channel); + switch(bk_sta_cipher_type()) + { + case SECURITY_TYPE_NONE: + bk_printf("OPEN\r\n"); + break; + case SECURITY_TYPE_WEP : + bk_printf("WEP\r\n"); + break; + case SECURITY_TYPE_WPA_TKIP: + bk_printf("TKIP\r\n"); + break; + case SECURITY_TYPE_WPA2_AES: + bk_printf("CCMP\r\n"); + break; + case SECURITY_TYPE_WPA2_MIXED: + bk_printf("MIXED\r\n"); + break; + case SECURITY_TYPE_AUTO: + bk_printf("AUTO\r\n"); + break; + default: + bk_printf("Error\r\n"); + break; + } + } + + if( uap_ip_is_start() ) + { + os_memset(&ap_info, 0x0, sizeof(network_InitTypeDef_ap_st)); + bk_wlan_ap_para_info_get(&ap_info); + os_memcpy(ssid, ap_info.wifi_ssid, 32); + bk_printf("softap:ssid=%s,channel=%d,dhcp=%d,cipher_type:", + ssid, ap_info.channel,ap_info.dhcp_mode); + switch(ap_info.security) + { + case SECURITY_TYPE_NONE: + bk_printf("OPEN\r\n"); + break; + case SECURITY_TYPE_WEP : + bk_printf("WEP\r\n"); + break; + case SECURITY_TYPE_WPA_TKIP: + bk_printf("TKIP\r\n"); + break; + case SECURITY_TYPE_WPA2_AES: + bk_printf("CCMP\r\n"); + break; + case SECURITY_TYPE_WPA2_MIXED: + bk_printf("MIXED\r\n"); + break; + case SECURITY_TYPE_AUTO: + bk_printf("AUTO\r\n"); + break; + default: + bk_printf("Error\r\n"); + break; + } + bk_printf("ip=%s,gate=%s,mask=%s,dns=%s\r\n", + ap_info.local_ip_addr, ap_info.gateway_ip_addr, ap_info.net_mask, ap_info.dns_server_ip_addr); + } +} + +void demo_ip_app_init(void) +{ + IPStatusTypedef ipStatus; + + os_memset(&ipStatus, 0x0, sizeof(IPStatusTypedef)); + bk_wlan_get_ip_status(&ipStatus, STATION); + + bk_printf("dhcp=%d ip=%s gate=%s mask=%s mac=" MACSTR "\r\n", + ipStatus.dhcp, ipStatus.ip, ipStatus.gate, + ipStatus.mask, MAC2STR((unsigned char*)ipStatus.mac)); +} + +// eof + diff --git a/beken_os/beken378/demo/ieee802_11_demo.h b/beken_os/beken378/demo/ieee802_11_demo.h new file mode 100755 index 0000000..d78292c --- /dev/null +++ b/beken_os/beken378/demo/ieee802_11_demo.h @@ -0,0 +1,19 @@ +#ifndef _IEEE802_11_DEMO_H_ +#define _IEEE802_11_DEMO_H_ + + +#define WLAN_DEFAULT_IP "192.168.0.1" +#define WLAN_DEFAULT_GW "192.168.0.1" +#define WLAN_DEFAULT_MASK "255.255.255.0" + +void demo_scan_app_init(void); +void demo_scan_adv_app_init(uint8_t *oob_ssid); +void demo_softap_app_init(char *ap_ssid, char *ap_key); +void demo_sta_app_init(char *oob_ssid,char *connect_key); +void demo_sta_adv_app_init(char *oob_ssid,char *connect_key); +void demo_wlan_app_init(VIF_ADDCFG_PTR cfg); +void demo_state_app_init(void); +void demo_ip_app_init(void); + +#endif + diff --git a/beken_os/beken378/driver/audio/audio.c b/beken_os/beken378/driver/audio/audio.c new file mode 100755 index 0000000..f1da202 --- /dev/null +++ b/beken_os/beken378/driver/audio/audio.c @@ -0,0 +1,155 @@ +#include "include.h" +#include "arm_arch.h" + +#include "audio.h" +#include "audio_pub.h" + +#include "intc_pub.h" +#include "icu_pub.h" +#include "sys_ctrl_pub.h" + +#include "drv_model_pub.h" +#include "mem_pub.h" +#include "ring_buffer.h" + +#if CFG_USE_AUDIO +void audio_power_up(void) +{ + UINT32 param; + param = PWD_AUDIO_CLK_BIT; + sddev_control(ICU_DEV_NAME, CMD_CLK_PWR_UP, ¶m); +} + +void audio_power_down(void) +{ + UINT32 param; + param = PWD_AUDIO_CLK_BIT; + sddev_control(ICU_DEV_NAME, CMD_CLK_PWR_DOWN, ¶m); +} + +void audio_enable_interrupt(void) +{ + UINT32 param; + param = (IRQ_AUDIO_BIT); + sddev_control(ICU_DEV_NAME, CMD_ICU_INT_ENABLE, ¶m); +} + +void audio_disable_interrupt(void) +{ + UINT32 param; + param = (IRQ_AUDIO_BIT); + sddev_control(ICU_DEV_NAME, CMD_ICU_INT_DISABLE, ¶m); +} + +static void audio_isr(void) +{ + UINT32 status = REG_READ(AUD_AD_FIFO_STATUS); + //AUD_PRT("%x\r\n", status); + if (status & (DAC_R_INT_FLAG | DAC_L_INT_FLAG)) + { + #if CFG_USE_AUD_DAC + audio_dac_isr(); + #endif + + REG_WRITE(AUD_AD_FIFO_STATUS, + DAC_R_NEAR_FULL | DAC_L_NEAR_FULL + | DAC_R_NEAR_EMPTY | DAC_L_NEAR_EMPTY + | DAC_R_FIFO_FULL | DAC_L_FIFO_FULL + | DAC_R_FIFO_EMPTY | DAC_L_FIFO_EMPTY + | DAC_R_INT_FLAG | DAC_L_INT_FLAG); + + } + if (status & ADC_INT_FLAG) + { + #if CFG_USE_AUD_ADC + audio_adc_isr(); + #endif + + REG_WRITE(AUD_AD_FIFO_STATUS, + ADC_NEAR_FULL | ADC_NEAR_EMPTY | ADC_FIFO_FULL + | ADC_FIFO_EMPTY | ADC_INT_FLAG); + } + if (status & DTMF_INT_FLAG) + { + //audio_dtmf_isr(status); + REG_WRITE(AUD_AD_FIFO_STATUS, + DTMF_NEAR_FULL | DTMF_NEAR_EMPTY | DTMF_FIFO_FULL + | DTMF_FIFO_EMPTY | DTMF_INT_FLAG); + } +} + +void audio_hardware_init(void) +{ + UINT32 val; + + /* register interrupt */ + intc_service_register(IRQ_AUDIO, PRI_IRQ_AUDIO, audio_isr); + + REG_WRITE(AUDIO_CONFIG, 0); + + REG_WRITE(AUD_DTMF_CONFIG_0, 0); + REG_WRITE(AUD_DTMF_CONFIG_1, 0); + REG_WRITE(AUD_DTMF_CONFIG_2, 0); + + REG_WRITE(AUD_ADC_CONFIG_0, 0x00e93A22); + REG_WRITE(AUD_ADC_CONFIG_1, 0x8BBF3A22); + REG_WRITE(AUD_ADC_CONFIG_2, 0xC9E6751C); + REG_WRITE(AUD_AGC_CONFIG_0, 0x4A019465); + REG_WRITE(AUD_AGC_CONFIG_1, 0x02016C01); + REG_WRITE(AUD_AGC_CONFIG_2, 0x0F020940); + + REG_WRITE(AUD_DAC_CONFIG_0, 0); + REG_WRITE(AUD_DAC_CONFIG_1, 0); + REG_WRITE(AUD_DAC_CONFIG_2, 0); + + // it's very import to config dac interrupt thred(not all zero) + REG_WRITE(AUD_FIFO_CONFIG, 0x210); + + /* reset int status */ + val = REG_READ(AUD_AD_FIFO_STATUS); + REG_WRITE(AUD_AD_FIFO_STATUS, val); +} + + +void audio_init(void) +{ + #if CFG_USE_AUD_DAC + audio_dac_software_init(); + #endif + + #if CFG_USE_AUD_ADC + audio_adc_software_init(); + #endif + + audio_hardware_init(); +} + +void audio_exit(void) +{ + UINT32 val; + + REG_WRITE(AUDIO_CONFIG, 0); + + REG_WRITE(AUD_DTMF_CONFIG_0, 0); + REG_WRITE(AUD_DTMF_CONFIG_1, 0); + REG_WRITE(AUD_DTMF_CONFIG_2, 0); + + REG_WRITE(AUD_ADC_CONFIG_0, 0); + REG_WRITE(AUD_ADC_CONFIG_1, 0); + REG_WRITE(AUD_ADC_CONFIG_2, 0); + + REG_WRITE(AUD_DAC_CONFIG_0, 0); + REG_WRITE(AUD_DAC_CONFIG_1, 0); + REG_WRITE(AUD_DAC_CONFIG_2, 0); + + REG_WRITE(AUD_FIFO_CONFIG, 0); + + /* reset int status */ + val = REG_READ(AUD_AD_FIFO_STATUS); + REG_WRITE(AUD_AD_FIFO_STATUS, val); + + #if CFG_USE_AUD_DAC + ddev_unregister_dev(AUD_DAC_DEV_NAME); + #endif +} +#endif // CFG_USE_AUDIO diff --git a/beken_os/beken378/driver/audio/audio.h b/beken_os/beken378/driver/audio/audio.h new file mode 100755 index 0000000..b6a983c --- /dev/null +++ b/beken_os/beken378/driver/audio/audio.h @@ -0,0 +1,307 @@ +#ifndef _BK_AUDIO_H_ +#define _BK_AUDIO_H_ + +#define AUDIO_BASE (0x00802B00) + +#define AUDIO_CONFIG (AUDIO_BASE + 0x0 * 4) +#define SAMPLE_RATE_ADC_POSI (0) +#define SAMPLE_RATE_ADC_MASK (0x3U) +#define SAMPLE_RATE_8K (0) +#define SAMPLE_RATE_16K (1) +#define SAMPLE_RATE_44_1_K (2) +#define SAMPLE_RATE_48K (3) +#define DAC_ENABLE (1 << 2) +#define ADC_ENABLE (1 << 3) +#define DTMF_ENABLE (1 << 4) +#define LINEIN_ENABLE (1 << 5) +#define SAMPLE_RATE_DAC_POSI (6) +#define SAMPLE_RATE_DAC_MASK (0x3U) + +#define AUD_DTMF_CONFIG_0 (AUDIO_BASE + 0x1 * 4) +#define TONE_PATTERN (1 << 0) +#define TONE_MODE (1 << 0) +#define TONE_PAUSE_TIME_POSI (2) +#define TONE_PAUSE_TIME_MASK (0xFU) +#define TONE_ACTIVE_TIME_POSI (6) +#define TONE_ACTIVE_TIME_MASK (0xFU) + +#define AUD_DTMF_CONFIG_1 (AUDIO_BASE + 0x2 * 4) +#define TONE_1_STEP_POSI (0) +#define TONE_1_STEP_MASK (0xFFFFU) +#define TONE_1_ATTU_POSI (16) +#define TONE_1_ATTU_MASK (0xFU) +#define TONE_1_ENABLE (1 << 20) + +#define AUD_DTMF_CONFIG_2 (AUDIO_BASE + 0x3 * 4) +#define TONE_2_STEP_POSI (0) +#define TONE_2_STEP_MASK (0xFFFFU) +#define TONE_2_ATTU_POSI (16) +#define TONE_2_ATTU_MASK (0xFU) +#define TONE_2_ENABLE (1 << 20) + +#define AUD_ADC_CONFIG_0 (AUDIO_BASE + 0x4 * 4) +#define ADC_HPF2_COEF_B2_POSI (0) +#define ADC_HPF2_COEF_B2_MASK (0xFFFFU) +#define ADC_HPF2_BYPASS (1 << 16) +#define ADC_HPF1_BYPASS (1 << 17) +#define ADC_SET_GAIN_POSI (18) +#define ADC_SET_GAIN_MASK (0x3FU) +#define ADC_SAMPLE_EDGE (1 << 24) + +#define AUD_ADC_CONFIG_1 (AUDIO_BASE + 0x5 * 4) +#define ADC_HPF2_COEF_B0_POSI (0) +#define ADC_HPF2_COEF_B0_MASK (0xFFFFU) +#define ADC_HPF2_COEF_B1_POSI (16) +#define ADC_HPF2_COEF_B1_MASK (0xFFFFU) + +#define AUD_ADC_CONFIG_2 (AUDIO_BASE + 0x6 * 4) +#define ADC_HPF2_COEF_A0_POSI (0) +#define ADC_HPF2_COEF_A0_MASK (0xFFFFU) +#define ADC_HPF2_COEF_A1_POSI (16) +#define ADC_HPF2_COEF_A1_MASK (0xFFFFU) + +#define AUD_DAC_CONFIG_0 (AUDIO_BASE + 0x7 * 4) +#define DAC_HPF2_COEF_B2_POSI (0) +#define DAC_HPF2_COEF_B2_MASK (0xFFFFU) +#define DAC_HPF2_BYPASS (1 << 16) +#define DAC_HPF1_BYPASS (1 << 17) +#define DAC_SET_GAIN_POSI (18) +#define DAC_SET_GAIN_MASK (0x3FU) +#define DAC_CLK_INVERT (1 << 24) + +#define AUD_DAC_CONFIG_1 (AUDIO_BASE + 0x8 * 4) +#define DAC_HPF2_COEF_B0_POSI (0) +#define DAC_HPF2_COEF_B0_MASK (0xFFFFU) +#define DAC_HPF2_COEF_B1_POSI (16) +#define DAC_HPF2_COEF_B1_MASK (0xFFFFU) + +#define AUD_DAC_CONFIG_2 (AUDIO_BASE + 0x9 * 4) +#define DAC_HPF2_COEF_A1_POSI (0) +#define DAC_HPF2_COEF_A1_MASK (0xFFFFU) +#define DAC_HPF2_COEF_A2_POSI (16) +#define DAC_HPF2_COEF_A2_MASK (0xFFFFU) + +#define AUD_FIFO_CONFIG (AUDIO_BASE + 0xA * 4) +#define DAC_R_RD_THRED_POSI (0) +#define DAC_R_RD_THRED_MASK (0x1FU) +#define DAC_L_RD_THRED_POSI (5) +#define DAC_L_RD_THRED_MASK (0x1FU) +#define DTMF_WR_THRED_POSI (10) +#define DTMF_WR_THRED_MASK (0x1FU) +#define ADC_WR_THRED_POSI (15) +#define ADC_WR_THRED_MASK (0x1FU) +#define DAC_R_INT_EN (1 << 20) +#define DAC_L_INT_EN (1 << 21) +#define DTMF_INT_EN (1 << 22) +#define ADC_INT_EN (1 << 23) +#define LOOP_TON2DAC (1 << 24) +#define LOOP_ADC2DAC (1 << 25) + +#define AUD_AGC_CONFIG_0 (AUDIO_BASE + 0xB * 4) +#define AGC_NOISE_THRED_POSI (0) +#define AGC_NOISE_THRED_MASK (0x3FFU) +#define AGC_NOISE_HIGH_POSI (10) +#define AGC_NOISE_HIGH_MASK (0x3FFU) +#define AGC_NOISE_LOW_POSI (20) +#define AGC_NOISE_LOW_MASK (0x3FFU) +#define AGC_STEP_POSI (30) +#define AGC_STEP_MASK (0x3U) + +#define AUD_AGC_CONFIG_1 (AUDIO_BASE + 0xC * 4) +#define AGC_NOISE_MIN_POSI (0) +#define AGC_NOISE_MIN_MASK (0x7FU) +#define AGC_NOISE_TOUT_POSI (7) +#define AGC_NOISE_TOUT_MASK (0x7U) +#define AGC_HIGH_DUR_POSI (10) +#define AGC_HIGH_DUR_MASK (0x7U) +#define AGC_LOW_DUR_POSI (13) +#define AGC_LOW_DUR_MASK (0x7U) +#define AGC_MIN_POSI (16) +#define AGC_MIN_MASK (0x7FU) +#define AGC_MAX_POSI (23) +#define AGC_MAX_MASK (0x7FU) +#define AGC_NG_METHOD (1 << 30) +#define AGC_NG_ENABLE (1 << 31) + +#define AUD_AGC_CONFIG_2 (AUDIO_BASE + 0xD * 4) +#define AGC_DECAY_TIME_POSI (0) +#define AGC_DECAY_TIME_MASK (0x7U) +#define AGC_ATTACK_TIME_POSI (3) +#define AGC_ATTACK_TIME_MASK (0x7U) +#define AGC_HIGH_THRD_POSI (6) +#define AGC_HIGH_THRD_MASK (0x1FU) +#define AGC_LOW_THRED_POSI (11) +#define AGC_LOW_THRED_MASK (0x1FU) +#define AGC_IIR_COEF_POSI (16) +#define AGC_IIR_COEF_MAS (0x7U) +#define AGC_ENABLE (1 << 19) +#define MANUAL_PGA_VAL_POSI (20) +#define MANUAL_PGA_VAL_MASK (0x7FU) +#define MANUAL_PGA_MODE (1 << 27) + +#define AUD_AD_FIFO_STATUS (AUDIO_BASE + 0xE * 4) +#define DAC_R_NEAR_FULL (1 << 0) +#define DAC_L_NEAR_FULL (1 << 1) +#define ADC_NEAR_FULL (1 << 2) +#define DTMF_NEAR_FULL (1 << 3) +#define DAC_R_NEAR_EMPTY (1 << 4) +#define DAC_L_NEAR_EMPTY (1 << 5) +#define ADC_NEAR_EMPTY (1 << 6) +#define DTMF_NEAR_EMPTY (1 << 7) +#define DAC_R_FIFO_FULL (1 << 8) +#define DAC_L_FIFO_FULL (1 << 9) +#define ADC_FIFO_FULL (1 << 10) +#define DTMF_FIFO_FULL (1 << 11) +#define DAC_R_FIFO_EMPTY (1 << 12) +#define DAC_L_FIFO_EMPTY (1 << 13) +#define ADC_FIFO_EMPTY (1 << 14) +#define DTMF_FIFO_EMPTY (1 << 15) +#define DAC_R_INT_FLAG (1 << 16) +#define DAC_L_INT_FLAG (1 << 17) +#define ADC_INT_FLAG (1 << 18) +#define DTMF_INT_FLAG (1 << 19) + +#define AUD_AGC_STATUS (AUDIO_BASE + 0xF * 4) +#define AGC_RSSI_POSI (0) +#define AGC_RSSI_MASK (0xFFU) +#define AGC_MIC_PGA_POSI (8) +#define AGC_MIC_PGA_MASK (0xFFU) +#define AGC_MIC_RSSI_POSI (16) +#define AGC_MIC_RSSI_MASK (0xFFFFU) + +#define AUD_DTMF_FIFO_PORT (AUDIO_BASE + 0x10 * 4) +#define AD_DTMF_FIFO_MASK (0xFFFFU) + +#define AUD_ADC_FIFO_PORT (AUDIO_BASE + 0x11 * 4) +#define AD_ADC_L_FIFO_MASK (0xFFFFU) +#define AD_ADC_L_FIFO_POSI (0) +#define AD_ADC_R_FIFO_MASK (0xFFFFU) +#define AD_ADC_R_FIFO_POSI (16) +#define AD_ADC_LR_FIFO_MASK (0xFFFFFFFFU) + +#define AUD_DAC_FIFO_PORT (AUDIO_BASE + 0x12 * 4) +#define AD_DAC_L_FIFO_POSI (0) +#define AD_DAC_L_FIFO_MASK (0xFFFFU) +#define AD_DAC_R_FIFO_POSI (16) +#define AD_DAC_R_FIFO_MASK (0xFFFFU) + +#define AUD_EXTEND_CFG (AUDIO_BASE + 0x18 * 4) +#define DAC_FRACMOD_MANUAL (1 << 0) +#define ADC_FRACMOD_MANUAL (1 << 1) +#define FILT_ENABLE (1 << 2) + +#define AUD_DAC_FRACMOD (AUDIO_BASE + 0x19 * 4) + +#define AUD_ADC_FRACMOD (AUDIO_BASE + 0x1A * 4) + +#define AUD_HPF2_EXT_COEF (AUDIO_BASE + 0x1F * 4) +#define HPF2_A1_L_6BIT_POSI (0) +#define HPF2_A1_L_6BIT_MASK (0x3FU) +#define HPF2_A2_L_6BIT_POSI (6) +#define HPF2_A2_L_6BIT_MASK (0x3FU) +#define HPF2_B0_L_6BIT_POSI (12) +#define HPF2_B0_L_6BIT_MASK (0x3FU) +#define HPF2_B1_L_6BIT_POSI (18) +#define HPF2_B1_L_6BIT_MASK (0x3FU) +#define HPF2_B2_L_6BIT_POSI (24) +#define HPF2_B2_L_6BIT_MASK (0x3FU) + +#define AUD_FLT_0_COEF_1 (AUDIO_BASE + 0x20 * 4) +#define FLT_0_A1_POSI (0) +#define FLT_0_A1_MASK (0xFFFFU) +#define FLT_0_A2_POSI (16) +#define FLT_0_A2_MASK (0xFFFFU) +#define AD_FLT_0_COEF_2 (AUDIO_BASE + 0x21 * 4) +#define FLT_0_B0_POSI (0) +#define FLT_0_B0_MASK (0xFFFFU) +#define FLT_0_B1_POSI (16) +#define FLT_0_B1_MASK (0xFFFFU) +#define AD_FLT_0_COEF_3 (AUDIO_BASE + 0x22 * 4) +#define FLT_0_B2_POSI (0) +#define FLT_0_B2_MASK (0xFFFFU) + +#define AUD_FLT_1_COEF_1 (AUDIO_BASE + 0x23 * 4) +#define FLT_1_A1_POSI (0) +#define FLT_1_A1_MASK (0xFFFFU) +#define FLT_1_A2_POSI (16) +#define FLT_1_A2_MASK (0xFFFFU) +#define AD_FLT_1_COEF_2 (AUDIO_BASE + 0x24 * 4) +#define FLT_1_B0_POSI (0) +#define FLT_1_B0_MASK (0xFFFFU) +#define FLT_1_B1_POSI (16) +#define FLT_1_B1_MASK (0xFFFFU) +#define AD_FLT_1_COEF_3 (AUDIO_BASE + 0x25 * 4) +#define FLT_1_B2_POSI (0) +#define FLT_1_B2_MASK (0xFFFFU) + +#define AUD_FLT_2_COEF_1 (AUDIO_BASE + 0x26 * 4) +#define FLT_2_A1_POSI (0) +#define FLT_2_A1_MASK (0xFFFFU) +#define FLT_2_A2_POSI (16) +#define FLT_2_A2_MASK (0xFFFFU) +#define AD_FLT_2_COEF_2 (AUDIO_BASE + 0x27 * 4) +#define FLT_2_B0_POSI (0) +#define FLT_2_B0_MASK (0xFFFFU) +#define FLT_2_B1_POSI (16) +#define FLT_2_B1_MASK (0xFFFFU) +#define AD_FLT_2_COEF_3 (AUDIO_BASE + 0x28 * 4) +#define FLT_2_B2_POSI (0) +#define FLT_2_B2_MASK (0xFFFFU) + +#define AUD_FLT_3_COEF_1 (AUDIO_BASE + 0x29 * 4) +#define FLT_3_A1_POSI (0) +#define FLT_3_A1_MASK (0xFFFFU) +#define FLT_3_A2_POSI (16) +#define FLT_3_A2_MASK (0xFFFFU) +#define AD_FLT_3_COEF_2 (AUDIO_BASE + 0x2A * 4) +#define FLT_3_B0_POSI (0) +#define FLT_3_B0_MASK (0xFFFFU) +#define FLT_3_B1_POSI (16) +#define FLT_3_B1_MASK (0xFFFFU) +#define AD_FLT_3_COEF_3 (AUDIO_BASE + 0x2B * 4) +#define FLT_3_B2_POSI (0) +#define FLT_3_B2_MASK (0xFFFFU) + +#define AUD_FLT_0_EXT_COEF (AUDIO_BASE + 0x2C * 4) +#define FLT_A1_L_6BIT_POSI (0) +#define FLT_A1_L_6BIT_MASK (0x3FU) +#define FLT_A2_L_6BIT_POSI (6) +#define FLT_A2_L_6BIT_MASK (0x3FU) +#define FLT_B0_L_6BIT_POSI (12) +#define FLT_B0_L_6BIT_MASK (0x3FU) +#define FLT_B1_L_6BIT_POSI (18) +#define FLT_B1_L_6BIT_MASK (0x3FU) +#define FLT_B2_L_6BIT_POSI (24) +#define FLT_B2_L_6BIT_MASK (0x3FU) + +#define AUD_FLT_1_EXT_COEF (AUDIO_BASE + 0x2D * 4) + +#define AUD_FLT_2_EXT_COEF (AUDIO_BASE + 0x2E * 4) + +#define AUD_FLT_3_EXT_COEF (AUDIO_BASE + 0x2F * 4) + +#define CONST_DIV_441K (0x049B2368) +#define CONST_DIV_48K (0x043B5554) +#define CONST_DIV_16K (0x06590000) +#define CONST_DIV_32K (0x01964000) + +extern void audio_power_up(void); +extern void audio_power_down(void); +extern void audio_enable_interrupt(void); +extern void audio_disable_interrupt(void); +extern void audio_dac_software_init(void); +extern void audio_dac_isr(void); + +extern void audio_adc_software_init(void); +extern void audio_adc_isr(void); + +#include "uart_pub.h" +#define AUD_DEBUG (1) +#if AUD_DEBUG +#define AUD_PRT os_printf +#else +#define AUD_PRT null_prf +#define AUD_WPRT null_prf +#endif + +#endif // _BK_AUDIO_H_ diff --git a/beken_os/beken378/driver/audio/audio_adc.c b/beken_os/beken378/driver/audio/audio_adc.c new file mode 100755 index 0000000..fbf6195 --- /dev/null +++ b/beken_os/beken378/driver/audio/audio_adc.c @@ -0,0 +1,691 @@ +#include "include.h" +#include "arm_arch.h" + +#include "audio.h" +#include "audio_pub.h" + +#include "intc_pub.h" +#include "icu_pub.h" +#include "sys_ctrl_pub.h" + +#include "mem_pub.h" +#include "ring_buffer.h" +#include "ring_buffer_dma_write.h" +#include "gpio_pub.h" + +#if CFG_GENERAL_DMA +#include "general_dma_pub.h" +#define AUD_ADC_DEF_DMA_CHANNEL GDMA_CHANNEL_2 +#endif + +#if CFG_USE_AUD_ADC +enum +{ + AUD_ADC_STA_CLOSED = 0, + AUD_ADC_STA_OPENED, + AUD_ADC_STA_PAUSE, + AUD_ADC_STA_PLAYING +}; + +typedef struct aud_adc_desc +{ + UINT8 *buf; + UINT16 buf_len; + UINT16 freq; + UINT16 channels; + UINT16 mode; + UINT32 linein_detect_pin; + + UINT32 status; + union { + RB_ST rb; + RB_DMA_WR_ST rb_dma_wr; + }u; +} AUD_ADC_DESC_ST, *AUD_ADC_DESC_PTR; + +static UINT32 audio_adc_open(UINT32 op_flag); +static UINT32 audio_adc_close(void); +static UINT32 audio_adc_read(char *user_buf, UINT32 count, UINT32 op_flag); +static UINT32 audio_adc_ctrl(UINT32 cmd, void *param); + +DD_OPERATIONS adu_adc_op = +{ + audio_adc_open, + audio_adc_close, + audio_adc_read, + NULL, + audio_adc_ctrl +}; +static AUD_ADC_DESC_ST aud_adc = {0}; + +static void audio_adc_set_enable_bit(UINT32 enable) +{ + UINT32 reg_addr = AUDIO_CONFIG; + UINT32 reg_val = REG_READ(reg_addr); + + // linein and adc enable bits are the two channels for adc + // open both of them, no mater channel is. + if (enable) + reg_val |= (ADC_ENABLE | LINEIN_ENABLE); + else + reg_val &= ~(ADC_ENABLE | LINEIN_ENABLE); + REG_WRITE(reg_addr, reg_val); +} + +static void audio_adc_set_int_enable_bit(UINT32 enable) +{ + UINT32 reg_addr = AUD_FIFO_CONFIG; + UINT32 reg_val = REG_READ(reg_addr); + + if (enable) + reg_val |= ADC_INT_EN; + else + reg_val &= ~ADC_INT_EN; + REG_WRITE(reg_addr, reg_val); +} + +static void audio_adc_get_l_sample(INT16 *left) +{ + UINT32 reg_addr = AUD_ADC_FIFO_PORT; + UINT32 reg_val = REG_READ(reg_addr); + + *left = (INT16)(reg_val & AD_ADC_L_FIFO_MASK); +} + +static void audio_adc_get_l_and_r_samples(INT16 *left, INT16 *right) +{ + UINT32 reg_addr = AUD_ADC_FIFO_PORT; + UINT32 reg_val = REG_READ(reg_addr); + + reg_val &= AD_ADC_LR_FIFO_MASK; + + *left = (INT16)(reg_val & AD_ADC_L_FIFO_MASK); + *right = (INT16)((reg_val >> AD_ADC_R_FIFO_POSI) & AD_ADC_R_FIFO_MASK); +} + +static void audio_adc_set_hpf2_bypass_bit(UINT32 enable) +{ + UINT32 reg_addr = AUD_ADC_CONFIG_0; + UINT32 reg_val = REG_READ(reg_addr); + + if (enable) + reg_val |= ADC_HPF2_BYPASS; + else + reg_val &= ~ADC_HPF2_BYPASS; + REG_WRITE(reg_addr, reg_val); +} + +static void audio_adc_set_gain(UINT32 gain) +{ + UINT32 reg_addr = AUD_ADC_CONFIG_0; + UINT32 reg_val = REG_READ(reg_addr); + + if (gain > ADC_SET_GAIN_MASK) + gain = ADC_SET_GAIN_MASK; + + reg_val &= ~(ADC_SET_GAIN_MASK << ADC_SET_GAIN_POSI); + reg_val |= ((gain & ADC_SET_GAIN_MASK) << ADC_SET_GAIN_POSI); + + REG_WRITE(reg_addr, reg_val); +} + +static void audio_adc_set_write_thred_bit(UINT32 thred) +{ + UINT32 reg_addr = AUD_FIFO_CONFIG; + UINT32 reg_val = REG_READ(reg_addr); + + if (thred > ADC_WR_THRED_MASK) + thred = ADC_WR_THRED_MASK; + + reg_val &= ~(ADC_WR_THRED_MASK << ADC_WR_THRED_POSI); + reg_val &= ~(DTMF_WR_THRED_MASK << DTMF_WR_THRED_POSI); + reg_val |= ((thred & ADC_WR_THRED_MASK) << ADC_WR_THRED_POSI); + reg_val |= ((thred & DTMF_WR_THRED_MASK) << DTMF_WR_THRED_POSI); + + REG_WRITE(reg_addr, reg_val); +} + +static void audio_adc_set_sample_rate(UINT32 sample_rate) +{ + UINT32 reg; + + /* disable adc handset bit again, to make sure this bit unset */ + reg = REG_READ(AUD_EXTEND_CFG); + reg &= ~(ADC_FRACMOD_MANUAL); + REG_WRITE(AUD_EXTEND_CFG, reg); + + switch (sample_rate) + { + case 11025: + reg = REG_READ(AUD_EXTEND_CFG); + reg |= ADC_FRACMOD_MANUAL; + REG_WRITE(AUD_EXTEND_CFG, reg); + reg = (CONST_DIV_441K); + REG_WRITE(AUD_ADC_FRACMOD, reg); + reg = REG_READ(AUDIO_CONFIG); + reg &= ~(SAMPLE_RATE_ADC_MASK << SAMPLE_RATE_ADC_POSI); + reg |= ((SAMPLE_RATE_44_1_K & SAMPLE_RATE_ADC_MASK) << SAMPLE_RATE_ADC_POSI); + REG_WRITE(AUDIO_CONFIG, reg); + break; + + case 22050: // + reg = REG_READ(AUD_EXTEND_CFG); + reg |= ADC_FRACMOD_MANUAL; + REG_WRITE(AUD_EXTEND_CFG, reg); + reg = (CONST_DIV_441K >> 1); + REG_WRITE(AUD_ADC_FRACMOD, reg); + reg = REG_READ(AUDIO_CONFIG); + reg &= ~(SAMPLE_RATE_ADC_MASK << SAMPLE_RATE_ADC_POSI); + reg |= ((SAMPLE_RATE_44_1_K & SAMPLE_RATE_ADC_MASK) << SAMPLE_RATE_ADC_POSI); + REG_WRITE(AUDIO_CONFIG, reg); + break; + + case 44100: + reg = REG_READ(AUDIO_CONFIG); + reg &= ~(SAMPLE_RATE_ADC_MASK << SAMPLE_RATE_ADC_POSI); + reg |= ((SAMPLE_RATE_44_1_K & SAMPLE_RATE_ADC_MASK) << SAMPLE_RATE_ADC_POSI); + REG_WRITE(AUDIO_CONFIG, reg); + break; + + case 12000: + reg = REG_READ(AUD_EXTEND_CFG); + reg |= ADC_FRACMOD_MANUAL; + REG_WRITE(AUD_EXTEND_CFG, reg); + reg = (CONST_DIV_48K); + REG_WRITE(AUD_ADC_FRACMOD, reg); + reg = REG_READ(AUDIO_CONFIG); + reg &= ~(SAMPLE_RATE_ADC_MASK << SAMPLE_RATE_ADC_POSI); + reg |= ((SAMPLE_RATE_48K & SAMPLE_RATE_ADC_MASK) << SAMPLE_RATE_ADC_POSI); + REG_WRITE(AUDIO_CONFIG, reg); + break; + + case 24000: + reg = REG_READ(AUD_EXTEND_CFG); + reg |= ADC_FRACMOD_MANUAL; + REG_WRITE(AUD_EXTEND_CFG, reg); + reg = (CONST_DIV_48K >> 1); + REG_WRITE(AUD_ADC_FRACMOD, reg); + reg = REG_READ(AUDIO_CONFIG); + reg &= ~(SAMPLE_RATE_ADC_MASK << SAMPLE_RATE_ADC_POSI); + reg |= ((SAMPLE_RATE_48K & SAMPLE_RATE_ADC_MASK) << SAMPLE_RATE_ADC_POSI); + REG_WRITE(AUDIO_CONFIG, reg); + break; + + case 48000: + reg = REG_READ(AUDIO_CONFIG); + reg &= ~(SAMPLE_RATE_ADC_MASK << SAMPLE_RATE_ADC_POSI); + reg |= ((SAMPLE_RATE_48K & SAMPLE_RATE_ADC_MASK) << SAMPLE_RATE_ADC_POSI); + REG_WRITE(AUDIO_CONFIG, reg); + break; + + case 8000: + reg = REG_READ(AUDIO_CONFIG); + reg &= ~(SAMPLE_RATE_ADC_MASK << SAMPLE_RATE_ADC_POSI); + reg |= ((SAMPLE_RATE_8K & SAMPLE_RATE_ADC_MASK) << SAMPLE_RATE_ADC_POSI); + REG_WRITE(AUDIO_CONFIG, reg); + break; + + case 16000: + reg = REG_READ(AUDIO_CONFIG); + reg &= ~(SAMPLE_RATE_ADC_MASK << SAMPLE_RATE_ADC_POSI); + reg |= ((SAMPLE_RATE_16K & SAMPLE_RATE_ADC_MASK) << SAMPLE_RATE_ADC_POSI); + REG_WRITE(AUDIO_CONFIG, reg); + break; + + case 32000: + reg = REG_READ(AUD_EXTEND_CFG); + reg |= ADC_FRACMOD_MANUAL; + REG_WRITE(AUD_EXTEND_CFG, reg); + reg = (CONST_DIV_32K); + REG_WRITE(AUD_ADC_FRACMOD, reg); + reg = REG_READ(AUDIO_CONFIG); + reg &= ~(SAMPLE_RATE_ADC_MASK << SAMPLE_RATE_ADC_POSI); + reg |= ((SAMPLE_RATE_48K & SAMPLE_RATE_ADC_MASK) << SAMPLE_RATE_ADC_POSI); + REG_WRITE(AUDIO_CONFIG, reg); + break; + + default: + AUD_PRT("unsupported sample rate:%d\r\n", sample_rate); + break; + } +} + +#if CFG_GENERAL_DMA +void audio_adc_dma_handler(UINT32 param) +{ + //AUD_PRT("audio_dac_dma_handler:%d\r\n", param); +} + +static void audio_adc_config_dma(void) +{ + GDMACFG_TPYES_ST cfg; + GDMA_CFG_ST en_cfg; + + if(!aud_adc.buf) + return; + + os_memset(&cfg, 0, sizeof(GDMACFG_TPYES_ST)); + + cfg.dstdat_width = 32; + cfg.srcdat_width = 32; + cfg.dstptr_incr = 1; + cfg.srcptr_incr = 0; + + cfg.src_start_addr = (void*)AUD_ADC_FIFO_PORT; + cfg.dst_start_addr = aud_adc.buf; + + cfg.channel = AUD_ADC_DEF_DMA_CHANNEL; + cfg.prio = 0; + cfg.u.type5.dst_loop_start_addr = aud_adc.buf; + cfg.u.type5.dst_loop_end_addr = aud_adc.buf + aud_adc.buf_len; + + //cfg.fin_handler = audio_dac_dma_handler; + cfg.fin_handler = NULL; + + cfg.src_module = GDMA_X_SRC_AUDIO_TX_REQ; + cfg.dst_module = GDMA_X_DST_DTCM_WR_REQ; + + sddev_control(GDMA_DEV_NAME, CMD_GDMA_CFG_TYPE5, &cfg); + + en_cfg.channel = AUD_ADC_DEF_DMA_CHANNEL; + en_cfg.param = aud_adc.buf_len; // dma translen + sddev_control(GDMA_DEV_NAME, CMD_GDMA_SET_TRANS_LENGTH, &en_cfg); + + en_cfg.channel = AUD_ADC_DEF_DMA_CHANNEL; + en_cfg.param = (UINT32)(aud_adc.buf); + sddev_control(GDMA_DEV_NAME, CMD_GDMA_SET_DST_PAUSE_ADDR, &en_cfg); + + //en_cfg.channel = AUD_ADC_DEF_DMA_CHANNEL; + //en_cfg.param = 1; + //sddev_control(GDMA_DEV_NAME, CMD_GDMA_SET_DMA_ENABLE, &en_cfg); +} + +static void audio_adc_set_dma(UINT32 enable) +{ + GDMA_CFG_ST en_cfg; + + en_cfg.channel = AUD_ADC_DEF_DMA_CHANNEL; + if (enable) + en_cfg.param = 1; + else + en_cfg.param = 0; + sddev_control(GDMA_DEV_NAME, CMD_GDMA_SET_DMA_ENABLE, &en_cfg); +} + +static void audio_adc_eixt_dma(void) +{ + GDMA_CFG_ST en_cfg; + + en_cfg.channel = AUD_ADC_DEF_DMA_CHANNEL; + en_cfg.param = 0; + sddev_control(GDMA_DEV_NAME, CMD_GDMA_SET_DMA_ENABLE, &en_cfg); +} +#endif // CFG_GENERAL_DMA + +static void audio_adc_open_analog_regs(void) +{ + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_OPEN_ADC_MIC_ANALOG, NULL); +} + +static void audio_adc_close_analog_regs(void) +{ + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_CLOSE_ADC_MIC_ANALOG, NULL); +} + +static void audio_adc_enable_linein(void) +{ + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_ENALBLE_ADC_LINE_IN, NULL); +} + +static void audio_adc_disable_linein(void) +{ + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_DISALBLE_ADC_LINE_IN, NULL); +} + +static void audio_adc_init_linein_detect_pin(UINT32 pin) +{ + UINT32 param; + + ASSERT(pin < GPIONUM); + + param = GPIO_CFG_PARAM(pin, GMODE_INPUT_PULLUP); + sddev_control(GPIO_DEV_NAME, CMD_GPIO_CFG, ¶m); +} + +static void audio_adc_linein_detect(void) +{ + UINT32 param; + + if(aud_adc.status != AUD_ADC_STA_CLOSED) + { + UINT32 gpio_val; + + param = aud_adc.linein_detect_pin; + gpio_val = sddev_control(GPIO_DEV_NAME, CMD_GPIO_INPUT, ¶m); + //AUD_PRT("%d\r\n", gpio_val); + if((gpio_val == AUD_ADC_LINEIN_ENABLE_LEVEL) + &&(!(aud_adc.mode & AUD_ADC_MODE_LINEIN))) + { + audio_adc_enable_linein(); + aud_adc.mode |= AUD_ADC_MODE_LINEIN; + AUD_PRT("enable line in: %d\r\n", aud_adc.mode); + } + else if((gpio_val != AUD_ADC_LINEIN_ENABLE_LEVEL) + &&(aud_adc.mode & AUD_ADC_MODE_LINEIN)) + { + audio_adc_disable_linein(); + aud_adc.mode &= ~AUD_ADC_MODE_LINEIN; + AUD_PRT("disable line in: %d\r\n", aud_adc.mode); + } + } +} + +static UINT32 audio_adc_open(UINT32 op_flag) +{ + AUD_ADC_DESC_PTR cfg; + + if(!op_flag) { + AUD_PRT("audio_adc_open is NULL\r\n"); + return AUD_FAILURE; + } + + cfg = (AUD_ADC_DESC_PTR)op_flag; + + #if(!CFG_GENERAL_DMA) + if(cfg->mode & AUD_ADC_MODE_DMA_BIT) + { + AUD_PRT("audio_dac_open no support dma\r\n"); + return AUD_FAILURE; + } + #endif // !CFG_GENERAL_DMA + + aud_adc.status = AUD_ADC_STA_CLOSED; + aud_adc.buf = cfg->buf; + aud_adc.buf_len = cfg->buf_len; + aud_adc.channels = cfg->channels; + aud_adc.freq= cfg->freq; + aud_adc.mode = cfg->mode; + aud_adc.linein_detect_pin = cfg->linein_detect_pin; + + audio_adc_set_enable_bit(0); + audio_adc_set_sample_rate(aud_adc.freq); + audio_adc_set_hpf2_bypass_bit(1); + audio_adc_set_gain(AUD_ADC_DEF_GAIN); + audio_adc_init_linein_detect_pin(aud_adc.linein_detect_pin); + + #if !AUD_ADC_DAC_HARDWARD_LOOPBACK + if(!(aud_adc.mode & AUD_ADC_MODE_DMA_BIT)) { + audio_adc_set_write_thred_bit(AUD_ADC_DEF_WR_THRED); + audio_adc_set_int_enable_bit(1); + audio_enable_interrupt(); + + rb_init(&aud_adc.u.rb, aud_adc.buf, aud_adc.buf_len); + } else { + audio_adc_set_int_enable_bit(0); + //audio_disable_interrupt(); + + #if (CFG_GENERAL_DMA) + audio_adc_config_dma(); + + rb_init_dma_write(&aud_adc.u.rb_dma_wr, aud_adc.buf, aud_adc.buf_len, AUD_ADC_DEF_DMA_CHANNEL); + #endif + } + #else + REG_WRITE(AUD_FIFO_CONFIG, (REG_READ(AUD_FIFO_CONFIG) | LOOP_ADC2DAC)); + #endif + + audio_adc_open_analog_regs(); + audio_power_up(); + #if AUD_ADC_DAC_HARDWARD_LOOPBACK + audio_adc_set_enable_bit(1); + aud_adc.status = AUD_ADC_STA_PLAYING; + #else + aud_adc.status = AUD_ADC_STA_OPENED; + #endif + + return AUD_SUCCESS; +} + +static UINT32 audio_adc_close(void) +{ + audio_adc_set_enable_bit(0); + audio_adc_set_int_enable_bit(0); + + if(aud_adc.status == AUD_ADC_STA_CLOSED) + return AUD_SUCCESS; + + #if (CFG_GENERAL_DMA) + if(aud_adc.mode & AUD_ADC_MODE_DMA_BIT) { + audio_adc_eixt_dma(); + //rb_clear_dma_read(&aud_dac.u.rb_dma_rd); + } + #endif + + //audio_disable_interrupt(); + //audio_power_down(); + audio_adc_close_analog_regs(); + + os_memset(&aud_adc, 0, sizeof(AUD_ADC_DESC_ST)); + aud_adc.status = AUD_ADC_STA_CLOSED; + + return AUD_SUCCESS; +} + + +static UINT32 audio_adc_read(char *user_buf, UINT32 count, UINT32 op_flag) +{ + int fill_size; + UINT8 *read, *write; + + if(aud_adc.status != AUD_ADC_STA_PLAYING) + return 0; + if(aud_adc.mode & AUD_ADC_MODE_DMA_BIT) + { + #if CFG_GENERAL_DMA + RB_DMA_WR_PTR rb; + rb = &aud_adc.u.rb_dma_wr; + fill_size = rb_get_fill_size_dma_write(rb); + if(fill_size > count) + fill_size = count; + rb_read_dma_write(rb, user_buf, fill_size, 1); + #endif + } + else + { + RB_PTR rb; + + rb = &aud_adc.u.rb; + fill_size = rb_get_fill_size(rb); + if(fill_size > count) + fill_size = count; + + rb_read(rb, user_buf, fill_size, 1); + } + + return fill_size; +} + +static UINT32 audio_adc_get_fill_buf_size(void) +{ + int free_size; + UINT8 *read, *write; + + if(aud_adc.status != AUD_ADC_STA_PLAYING) + return 0; + + if(aud_adc.mode & AUD_ADC_MODE_DMA_BIT) { + #if CFG_GENERAL_DMA + RB_DMA_WR_PTR rb; + rb = &aud_adc.u.rb_dma_wr; + free_size = rb_get_fill_size_dma_write(rb); + #endif + } else { + RB_PTR rb; + rb = &aud_adc.u.rb; + free_size = rb_get_fill_size(rb); + } + + return free_size; +} + +static void audio_adc_pause(void) +{ + if(aud_adc.status == AUD_ADC_STA_PAUSE) + return; + + if(aud_adc.mode & AUD_ADC_MODE_DMA_BIT) + { + #if CFG_GENERAL_DMA + audio_adc_set_dma(0); + #endif + } + + audio_adc_set_enable_bit(0); + + aud_adc.status = AUD_ADC_STA_PAUSE; +} + +static void audio_adc_play(void) +{ + if(aud_adc.status == AUD_ADC_STA_PLAYING) + return; + + if(aud_adc.mode & AUD_ADC_MODE_DMA_BIT) + { + #if CFG_GENERAL_DMA + audio_adc_set_dma(1); + #endif + } + + audio_adc_set_enable_bit(1); + + aud_adc.status = AUD_ADC_STA_PLAYING; +} + +static void audio_adc_set_volume(UINT32 volume) +{ + UINT32 act_vol; + UINT8 high, low; + UINT32 reg_addr = AUD_AGC_CONFIG_2; + UINT32 reg_val = REG_READ(reg_addr); + + if (volume > AUD_ADC_MAX_VOLUME) + volume = AUD_ADC_MAX_VOLUME; + + high = volume & 0x70; + low = volume & 0x0f; + + if (low > 0xc) + low = 0xc; + + act_vol = high | low; + + reg_val &= ~(MANUAL_PGA_VAL_MASK << MANUAL_PGA_VAL_POSI); + reg_val |= ((act_vol & MANUAL_PGA_VAL_MASK) << MANUAL_PGA_VAL_POSI); + + REG_WRITE(reg_addr, reg_val); + + AUD_PRT("set adc vol: %d - %d\r\n", volume, act_vol); +} + +static UINT32 audio_adc_ctrl(UINT32 cmd, void *param) +{ + UINT32 ret = AUD_SUCCESS; + + switch(cmd) + { + case AUD_ADC_CMD_GET_FILL_BUF_SIZE: + ret = audio_adc_get_fill_buf_size(); + break; + + case AUD_ADC_CMD_PLAY: + audio_adc_play(); + break; + + case AUD_ADC_CMD_PAUSE: + audio_adc_pause(); + break; + + case AUD_ADC_CMD_DO_LINEIN_DETECT: + audio_adc_linein_detect(); + break; + + case AUD_ADC_CMD_SET_SAMPLE_RATE: + ASSERT(param); + audio_adc_set_enable_bit(0); + audio_adc_set_sample_rate(*((UINT32 *)param)); + audio_adc_set_enable_bit(1); + break; + + case AUD_ADC_CMD_SET_VOLUME: + ASSERT(param); + audio_adc_set_volume(*((UINT32 *)param)); + break; + + default: + break; + } + return ret; +} + +void audio_adc_software_init(void) +{ + ddev_register_dev(AUD_ADC_DEV_NAME, &adu_adc_op); + + os_memset(&aud_adc, 0, sizeof(AUD_ADC_DESC_ST)); + aud_adc.status = AUD_ADC_STA_CLOSED; +} + +void audio_adc_isr(void) +{ + UINT32 status = REG_READ(AUD_AD_FIFO_STATUS); + RB_PTR rb = NULL; + UINT32 ret = 0, channel; + INT16 sample[2] = {0}; + + if(aud_adc.status == AUD_ADC_STA_PLAYING && (!(aud_adc.mode & AUD_ADC_MODE_DMA_BIT))) + { + rb = &aud_adc.u.rb; + channel = aud_adc.channels; + if(status & ADC_INT_FLAG) + { + if(channel == 2) + { + while(!(status & (ADC_FIFO_EMPTY))) + { + audio_adc_get_l_and_r_samples(&sample[0], &sample[1]); + ret = rb_write(rb, (UINT8*)&sample[0], sizeof(int16), 2); + //AUD_PRT("%d\r\n", ret); + if(!ret) + break; + status = REG_READ(AUD_AD_FIFO_STATUS); + } + } else { + while(!(status & (ADC_FIFO_EMPTY))) + { + audio_adc_get_l_sample(&sample[0]); + ret = rb_write(rb, (UINT8*)&sample[0], sizeof(int16), 1); + //AUD_PRT("%d\r\n", ret); + if(!ret) + break; + status = REG_READ(AUD_AD_FIFO_STATUS); + } + } + } + } + + if(ret == 0) + { + while(!(status & (ADC_FIFO_EMPTY))) + { + audio_adc_get_l_and_r_samples(&sample[0], &sample[1]); + status = REG_READ(AUD_AD_FIFO_STATUS); + } + //AUD_PRT("set\r\n"); + } + + //audio_adc_linein_detect(); +} + +#endif // CFG_USE_AUD_ADC + diff --git a/beken_os/beken378/driver/audio/audio_dac.c b/beken_os/beken378/driver/audio/audio_dac.c new file mode 100755 index 0000000..abc1bea --- /dev/null +++ b/beken_os/beken378/driver/audio/audio_dac.c @@ -0,0 +1,728 @@ +#include "include.h" +#include "arm_arch.h" + +#include "audio.h" +#include "audio_pub.h" + +#include "intc_pub.h" +#include "icu_pub.h" +#include "sys_ctrl_pub.h" +#include "gpio_pub.h" + +#include "mem_pub.h" +#include "ring_buffer.h" +#include "ring_buffer_dma_read.h" + +#if CFG_GENERAL_DMA +#include "general_dma_pub.h" +#define AUD_DAC_DEF_DMA_CHANNEL GDMA_CHANNEL_1 +#endif + +#if CFG_USE_AUD_DAC +enum +{ + AUD_DAC_STA_CLOSED = 0, + AUD_DAC_STA_OPENED, + AUD_DAC_STA_PAUSE, + AUD_DAC_STA_PLAYING +}; + +typedef struct aud_dac_desc +{ + UINT8 *buf; + UINT16 buf_len; + UINT16 freq; + UINT16 channels; + UINT16 dma_mode; + UINT32 status; + UINT16 mute_pin; + UINT16 volume; + union { + RB_ST rb; + RB_DMA_RD_ST rb_dma_rd; + }u; +} AUD_DAC_DESC_ST, *AUD_DAC_DESC_PTR; + +typedef struct aud_volome_s +{ + UINT8 ana_gain; + UINT8 dig_gain; +} AUD_VOL_ST, *AUD_VOL_PTR; + +#define AUD_DAC_VOL_TABLE_LEN (17) +#define AUD_DAC_DEF_VOL (AUD_DAC_VOL_TABLE_LEN/2) +#define AUD_DAC_DEF_RD_THRED (0x10) +#define AUD_DAC_DEF_DIGTAL_GAIN (0x2D) // 0dm + +static UINT32 audio_dac_open(UINT32 op_flag); +static UINT32 audio_dac_close(void); +static UINT32 audio_dac_write(char *user_buf, UINT32 count, UINT32 op_flag); +static UINT32 audio_dac_ctrl(UINT32 cmd, void *param); + +DD_OPERATIONS aud_dac_op = +{ + audio_dac_open, + audio_dac_close, + NULL, + audio_dac_write, + audio_dac_ctrl +}; +static AUD_DAC_DESC_ST aud_dac = {0}; + +#if (AUD_USE_EXT_PA == 1) +static const AUD_VOL_ST aud_vol_table[AUD_DAC_VOL_TABLE_LEN] = +{ + {0x00, 44}, // 0 + {0x01, 45}, // 1 + {0x03, 45}, // 1+ + {0x05, 45}, // 2 + {0x07, 45}, // 3 + {0x09, 45}, // 4 + {0x0b, 45}, // 5 + {0x0d, 45}, // 6 + {0x0f, 45}, // 7 + {0x11, 45}, // 8 + {0x13, 45}, // 9 + {0x15, 45}, // A + {0x17, 45}, // B + {0x19, 45}, // C + {0x1B, 45}, // D + {0x1D, 45}, // E + {0x1F, 45}, // F +}; +#else +static const AUD_VOL_ST aud_vol_table[AUD_DAC_VOL_TABLE_LEN] = +{ + {0x1A, 0}, // 0 + {0x1A, 2}, // 1 + {0x1A, 4}, // 1+ + {0x1A, 6}, // 2 + {0x1A, 9}, // 3 + {0x1A, 12}, // 4 + {0x1A, 15}, // 5 + {0x1A, 18}, // 6 + {0x1A, 21}, // 7 + {0x1A, 24}, // 8 + {0x1A, 27}, // 9 + {0x1A, 30}, // A + {0x1A, 33}, // B + {0x1A, 36}, // C + {0x1A, 39}, // D + {0x1A, 42}, // E + {0x1A, 45}, // F +}; +#endif + +static void audio_dac_set_enable_bit(UINT32 enable) +{ + UINT32 reg_addr = AUDIO_CONFIG; + UINT32 reg_val = REG_READ(reg_addr); + + if (enable) + reg_val |= DAC_ENABLE; + else + reg_val &= ~DAC_ENABLE; + REG_WRITE(reg_addr, reg_val); +} + +static void audio_dac_set_int_enable_bit(UINT32 enable) +{ + UINT32 reg_addr = AUD_FIFO_CONFIG; + UINT32 reg_val = REG_READ(reg_addr); + + if (enable) + reg_val |= (DAC_R_INT_EN | DAC_L_INT_EN); + else + reg_val &= ~(DAC_R_INT_EN | DAC_L_INT_EN); + REG_WRITE(reg_addr, reg_val); +} + +static void audio_dac_set_read_thred_bit(UINT32 thred) +{ + UINT32 reg_addr = AUD_FIFO_CONFIG; + UINT32 reg_val = REG_READ(reg_addr); + + reg_val &= ~(DAC_R_RD_THRED_MASK << DAC_R_RD_THRED_POSI); + reg_val &= ~(DAC_L_RD_THRED_MASK << DAC_L_RD_THRED_POSI); + + reg_val |= ((thred & DAC_R_RD_THRED_MASK) << DAC_R_RD_THRED_POSI); + reg_val |= ((thred & DAC_L_RD_THRED_MASK) << DAC_L_RD_THRED_POSI); + + REG_WRITE(reg_addr, reg_val); +} + +static void audio_dac_set_hpf1_bit(UINT32 enable) +{ + UINT32 reg_addr = AUD_DAC_CONFIG_0; + UINT32 reg_val = REG_READ(reg_addr); + + if (enable) + reg_val |= DAC_HPF1_BYPASS; + else + reg_val &= ~DAC_HPF1_BYPASS; + REG_WRITE(reg_addr, reg_val); +} + +static void audio_dac_set_hpf2_bit(UINT32 enable) +{ + UINT32 reg_addr = AUD_DAC_CONFIG_0; + UINT32 reg_val = REG_READ(reg_addr); + + if (enable) + reg_val |= DAC_HPF2_BYPASS; + else + reg_val &= ~DAC_HPF2_BYPASS; + REG_WRITE(reg_addr, reg_val); +} + +static void audio_dac_set_gain(UINT32 gain) +{ + UINT32 reg_addr = AUD_DAC_CONFIG_0; + UINT32 reg_val = REG_READ(reg_addr); + + if (gain > DAC_SET_GAIN_MASK) + gain = DAC_SET_GAIN_MASK; + + reg_val &= ~(DAC_SET_GAIN_MASK << DAC_SET_GAIN_POSI); + reg_val |= ((gain & DAC_SET_GAIN_MASK) << DAC_SET_GAIN_POSI); + + REG_WRITE(reg_addr, reg_val); +} + +static void audio_dac_set_sample(INT16 left, INT16 right) +{ + UINT32 reg_addr = AUD_DAC_FIFO_PORT; + UINT32 reg_val; + + reg_val = ((left & AD_DAC_L_FIFO_MASK) << AD_DAC_L_FIFO_POSI) + | ((right & AD_DAC_R_FIFO_MASK) << AD_DAC_R_FIFO_POSI); + + REG_WRITE(reg_addr, reg_val); +} + +static void audio_dac_set_sample_rate(UINT32 sample_rate) +{ + UINT32 reg; + + /* disable dac handset bit again, to make sure this bit unset */ + reg = REG_READ(AUD_EXTEND_CFG); + reg &= ~(DAC_FRACMOD_MANUAL); + REG_WRITE(AUD_EXTEND_CFG, reg); + + switch (sample_rate) + { + case 11025: + reg = REG_READ(AUD_EXTEND_CFG); + reg |= DAC_FRACMOD_MANUAL; + REG_WRITE(AUD_EXTEND_CFG, reg); + reg = (CONST_DIV_441K << 2); + REG_WRITE(AUD_DAC_FRACMOD, reg); + reg = REG_READ(AUDIO_CONFIG); + reg &= ~(SAMPLE_RATE_DAC_MASK << SAMPLE_RATE_DAC_POSI); + reg |= ((SAMPLE_RATE_44_1_K & SAMPLE_RATE_DAC_MASK) << SAMPLE_RATE_DAC_POSI); + REG_WRITE(AUDIO_CONFIG, reg); + break; + + case 22050: + reg = REG_READ(AUD_EXTEND_CFG); + reg |= DAC_FRACMOD_MANUAL; + REG_WRITE(AUD_EXTEND_CFG, reg); + reg = (CONST_DIV_441K << 1); + REG_WRITE(AUD_DAC_FRACMOD, reg); + reg = REG_READ(AUDIO_CONFIG); + reg &= ~(SAMPLE_RATE_DAC_MASK << SAMPLE_RATE_DAC_POSI); + reg |= ((SAMPLE_RATE_44_1_K & SAMPLE_RATE_DAC_MASK) << SAMPLE_RATE_DAC_POSI); + REG_WRITE(AUDIO_CONFIG, reg); + break; + + case 44100: + reg = REG_READ(AUDIO_CONFIG); + reg &= ~(SAMPLE_RATE_DAC_MASK << SAMPLE_RATE_DAC_POSI); + reg |= ((SAMPLE_RATE_44_1_K & SAMPLE_RATE_DAC_MASK) << SAMPLE_RATE_DAC_POSI); + REG_WRITE(AUDIO_CONFIG, reg); + break; + + case 12000: + reg = REG_READ(AUD_EXTEND_CFG); + reg |= DAC_FRACMOD_MANUAL; + REG_WRITE(AUD_EXTEND_CFG, reg); + reg = (CONST_DIV_48K << 2); + REG_WRITE(AUD_DAC_FRACMOD, reg); + reg = REG_READ(AUDIO_CONFIG); + reg &= ~(SAMPLE_RATE_DAC_MASK << SAMPLE_RATE_DAC_POSI); + reg |= ((SAMPLE_RATE_48K & SAMPLE_RATE_DAC_MASK) << SAMPLE_RATE_DAC_POSI); + REG_WRITE(AUDIO_CONFIG, reg); + break; + + case 24000: + reg = REG_READ(AUD_EXTEND_CFG); + reg |= DAC_FRACMOD_MANUAL; + REG_WRITE(AUD_EXTEND_CFG, reg); + reg = (CONST_DIV_48K << 1); + REG_WRITE(AUD_DAC_FRACMOD, reg); + reg = REG_READ(AUDIO_CONFIG); + reg &= ~(SAMPLE_RATE_DAC_MASK << SAMPLE_RATE_DAC_POSI); + reg |= ((SAMPLE_RATE_48K & SAMPLE_RATE_DAC_MASK) << SAMPLE_RATE_DAC_POSI); + REG_WRITE(AUDIO_CONFIG, reg); + break; + + case 48000: + reg = REG_READ(AUDIO_CONFIG); + reg &= ~(SAMPLE_RATE_DAC_MASK << SAMPLE_RATE_DAC_POSI); + reg |= ((SAMPLE_RATE_48K & SAMPLE_RATE_DAC_MASK) << SAMPLE_RATE_DAC_POSI); + REG_WRITE(AUDIO_CONFIG, reg); + break; + + case 8000: + reg = REG_READ(AUDIO_CONFIG); + reg &= ~(SAMPLE_RATE_DAC_MASK << SAMPLE_RATE_DAC_POSI); + reg |= ((SAMPLE_RATE_8K & SAMPLE_RATE_DAC_MASK) << SAMPLE_RATE_DAC_POSI); + REG_WRITE(AUDIO_CONFIG, reg); + break; + + case 16000: + reg = REG_READ(AUDIO_CONFIG); + reg &= ~(SAMPLE_RATE_DAC_MASK << SAMPLE_RATE_DAC_POSI); + reg |= ((SAMPLE_RATE_16K & SAMPLE_RATE_DAC_MASK) << SAMPLE_RATE_DAC_POSI); + REG_WRITE(AUDIO_CONFIG, reg); + break; + + case 32000: + reg = REG_READ(AUD_EXTEND_CFG); + reg |= DAC_FRACMOD_MANUAL; + REG_WRITE(AUD_EXTEND_CFG, reg); + reg = (CONST_DIV_16K >> 1); + REG_WRITE(AUD_DAC_FRACMOD, reg); + reg = REG_READ(AUDIO_CONFIG); + reg &= ~(SAMPLE_RATE_DAC_MASK << SAMPLE_RATE_DAC_POSI); + reg |= ((SAMPLE_RATE_16K & SAMPLE_RATE_DAC_MASK) << SAMPLE_RATE_DAC_POSI); + REG_WRITE(AUDIO_CONFIG, reg); + break; + + default: + AUD_PRT("unsupported sample rate:%d\r\n", sample_rate); + break; + } +} + +#if CFG_GENERAL_DMA +void audio_dac_dma_handler(UINT32 param) +{ + //AUD_PRT("audio_dac_dma_handler:%d\r\n", param); +} + +static void audio_dac_config_dma(void) +{ + GDMACFG_TPYES_ST cfg; + GDMA_CFG_ST en_cfg; + + if(!aud_dac.buf) + return; + + os_memset(&cfg, 0, sizeof(GDMACFG_TPYES_ST)); + + cfg.dstdat_width = 32; + cfg.srcdat_width = 32; + cfg.dstptr_incr = 0; + cfg.srcptr_incr = 1; + + cfg.src_start_addr = aud_dac.buf; + cfg.dst_start_addr = (void*)AUD_DAC_FIFO_PORT; + + cfg.channel = AUD_DAC_DEF_DMA_CHANNEL; + cfg.prio = 0; + cfg.u.type4.src_loop_start_addr = aud_dac.buf; + cfg.u.type4.src_loop_end_addr = aud_dac.buf + aud_dac.buf_len; + + //cfg.fin_handler = audio_dac_dma_handler; + cfg.fin_handler = NULL; + + cfg.src_module = GDMA_X_SRC_DTCM_RD_REQ; + cfg.dst_module = GDMA_X_DST_AUDIO_RX_REQ; + + sddev_control(GDMA_DEV_NAME, CMD_GDMA_CFG_TYPE4, &cfg); + + en_cfg.channel = AUD_DAC_DEF_DMA_CHANNEL; + en_cfg.param = aud_dac.buf_len; // dma translen + sddev_control(GDMA_DEV_NAME, CMD_GDMA_SET_TRANS_LENGTH, &en_cfg); + + en_cfg.channel = AUD_DAC_DEF_DMA_CHANNEL; + en_cfg.param = (UINT32)(aud_dac.buf); + sddev_control(GDMA_DEV_NAME, CMD_GDMA_SET_SRC_PAUSE_ADDR, &en_cfg); + + //en_cfg.channel = AUD_DAC_DEF_DMA_CHANNEL; + //en_cfg.param = 1; + //sddev_control(GDMA_DEV_NAME, CMD_GDMA_SET_DMA_ENABLE, &en_cfg); +} + +static void audio_dac_set_dma(UINT32 enable) +{ + GDMA_CFG_ST en_cfg; + + en_cfg.channel = AUD_DAC_DEF_DMA_CHANNEL; + if (enable) + en_cfg.param = 1; + else + en_cfg.param = 0; + sddev_control(GDMA_DEV_NAME, CMD_GDMA_SET_DMA_ENABLE, &en_cfg); +} + +static void audio_dac_eixt_dma(void) +{ + GDMA_CFG_ST en_cfg; + + en_cfg.channel = AUD_DAC_DEF_DMA_CHANNEL; + en_cfg.param = 0; + sddev_control(GDMA_DEV_NAME, CMD_GDMA_SET_DMA_ENABLE, &en_cfg); +} +#endif // CFG_GENERAL_DMA + +static void audio_dac_open_analog_regs(void) +{ + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_OPEN_DAC_ANALOG, NULL); +} + +static void audio_dac_close_analog_regs(void) +{ + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_CLOSE_DAC_ANALOG, NULL); +} + +#if AUD_USE_EXT_PA +static void audio_dac_init_mute_pin(UINT32 pin) +{ + UINT32 param; + + ASSERT(pin < GPIONUM); + + param = GPIO_CFG_PARAM(pin, GMODE_OUTPUT); + sddev_control(GPIO_DEV_NAME, CMD_GPIO_CFG, ¶m); +} + +static void audio_dac_eable_mute(UINT32 enable) +{ + UINT32 param; + ASSERT(aud_dac.mute_pin < GPIONUM); + + if (enable) + { + param = GPIO_CFG_PARAM(aud_dac.mute_pin, AUD_DAC_MUTE_ENA_LEVEL); + } + else + { + param = GPIO_CFG_PARAM(aud_dac.mute_pin, ~AUD_DAC_MUTE_ENA_LEVEL); + } + sddev_control(GPIO_DEV_NAME, CMD_GPIO_OUTPUT, ¶m); +} +#endif + +static void audio_dac_set_volume(UINT32 percent) +{ + UINT32 param = percent, idx; + AUD_VOL_PTR vol; + + if (percent > 99) + percent = 99; + + idx = percent * AUD_DAC_VOL_TABLE_LEN / 100; + + vol = (AUD_VOL_PTR)&aud_vol_table[idx]; + + audio_dac_set_gain(vol->dig_gain); + + param = vol->ana_gain; + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_SET_DAC_VOLUME_ANALOG, ¶m); + + if (percent == 0) + { + // no volume, so do mute(disable extral PA) + #if AUD_USE_EXT_PA + //audio_dac_eable_mute(1); + #endif + //audio_dac_set_gain(0); + } else { + #if AUD_USE_EXT_PA + //audio_dac_eable_mute(0); + #endif + } + AUD_PRT("set dac vol - indx:%d,dig:%d,ana:%02x\r\n", percent, vol->dig_gain, vol->ana_gain); +} + +static UINT32 audio_dac_open(UINT32 op_flag) +{ + AUD_DAC_CFG_PTR cfg; + + if(!op_flag) { + AUD_PRT("audio_dac_open is NULL\r\n"); + return AUD_FAILURE; + } + + cfg = (AUD_DAC_CFG_PTR)op_flag; + + #if (!CFG_GENERAL_DMA) + if(cfg->dma_mode) + { + AUD_PRT("audio_dac_open no support dma\r\n"); + return AUD_FAILURE; + } + #endif // !CFG_GENERAL_DMA + + aud_dac.status = AUD_DAC_STA_CLOSED; + aud_dac.buf = cfg->buf; + aud_dac.buf_len = cfg->buf_len; + aud_dac.channels = cfg->channels; + aud_dac.freq= cfg->freq; + aud_dac.dma_mode = cfg->dma_mode; + + audio_dac_set_enable_bit(0); + audio_dac_set_sample_rate(aud_dac.freq); + audio_dac_set_hpf1_bit(1); + audio_dac_set_hpf2_bit(1); + + #if AUD_USE_EXT_PA + aud_dac.mute_pin = cfg->mute_pin; + audio_dac_init_mute_pin(aud_dac.mute_pin); + audio_dac_eable_mute(1); + #endif + aud_dac.volume = AUD_DAC_DEF_VOL; + audio_dac_set_volume(aud_dac.volume); + + #if !AUD_ADC_DAC_HARDWARD_LOOPBACK + // audio should cfg DAC fifo, both use DMA or not use DMA + audio_dac_set_read_thred_bit(AUD_DAC_DEF_RD_THRED); + if(!aud_dac.dma_mode) { + audio_dac_set_int_enable_bit(1); + audio_enable_interrupt(); + rb_init(&aud_dac.u.rb, aud_dac.buf, aud_dac.buf_len); + } else { + audio_dac_set_int_enable_bit(0); + //audio_disable_interrupt(); + #if (CFG_GENERAL_DMA) + audio_dac_config_dma(); + + rb_init_dma_read(&aud_dac.u.rb_dma_rd, aud_dac.buf, aud_dac.buf_len, AUD_DAC_DEF_DMA_CHANNEL); + #endif + } + #endif + + audio_dac_open_analog_regs(); + audio_power_up(); + #if AUD_ADC_DAC_HARDWARD_LOOPBACK + audio_dac_set_enable_bit(1); + aud_dac.status = AUD_DAC_STA_PLAYING; + #else + aud_dac.status = AUD_DAC_STA_OPENED; + #endif + + return AUD_SUCCESS; +} + +static UINT32 audio_dac_close(void) +{ + audio_dac_set_enable_bit(0); + audio_dac_set_int_enable_bit(0); + + if(aud_dac.status == AUD_DAC_STA_CLOSED) + return AUD_SUCCESS; + + #if (CFG_GENERAL_DMA) + if(aud_dac.dma_mode) { + audio_dac_eixt_dma(); + rb_clear_dma_read(&aud_dac.u.rb_dma_rd); + } + #endif + + //audio_disable_interrupt(); + //audio_power_down(); + audio_dac_close_analog_regs(); + + os_memset(&aud_dac, 0, sizeof(AUD_DAC_DESC_ST)); + aud_dac.status = AUD_DAC_STA_CLOSED; + + return AUD_SUCCESS; +} + +static UINT32 audio_dac_write(char *user_buf, UINT32 count, UINT32 op_flag) +{ + int free_size; + UINT8 *read, *write; + + if(aud_dac.status != AUD_DAC_STA_PLAYING) + return 0; + if(aud_dac.dma_mode) + { + #if CFG_GENERAL_DMA + RB_DMA_RD_PTR rb; + rb = &aud_dac.u.rb_dma_rd; + free_size = rb_get_free_size_dma_read(rb); + if(free_size > count) + free_size = count; + rb_write_dma_read(rb, user_buf, free_size, 1); + #endif + } + else + { + RB_PTR rb; + + rb = &aud_dac.u.rb; + free_size = rb_get_free_size(rb); + if(free_size > count) + free_size = count; + rb_write(rb, user_buf, free_size, 1); + } + + return free_size; +} + +static UINT32 audio_dac_get_free_buf_size(void) +{ + int free_size; + UINT8 *read, *write; + + if(aud_dac.status != AUD_DAC_STA_PLAYING) + return 0; + + if(aud_dac.dma_mode) { + #if CFG_GENERAL_DMA + RB_DMA_RD_PTR rb; + rb = &aud_dac.u.rb_dma_rd; + free_size = rb_get_free_size_dma_read(rb); + #endif + } else { + RB_PTR rb; + rb = &aud_dac.u.rb; + free_size = rb_get_free_size(rb); + } + + return free_size; +} + +static void audio_dac_pause(void) +{ + if(aud_dac.status == AUD_DAC_STA_PAUSE) + return; + + if(aud_dac.dma_mode) + { + #if CFG_GENERAL_DMA + audio_dac_set_dma(0); + #endif + } + + audio_dac_set_enable_bit(0); + + aud_dac.status = AUD_DAC_STA_PAUSE; +} + +static void audio_dac_play(void) +{ + if(aud_dac.status == AUD_DAC_STA_PLAYING) + return; + + if(aud_dac.dma_mode) + { + #if CFG_GENERAL_DMA + audio_dac_set_dma(1); + #endif + } + + audio_dac_set_enable_bit(1); + + aud_dac.status = AUD_DAC_STA_PLAYING; +} + +static UINT32 audio_dac_ctrl(UINT32 cmd, void *param) +{ + UINT32 ret = AUD_SUCCESS; + + switch(cmd) + { + case AUD_DAC_CMD_GET_FREE_BUF_SIZE: + ret = audio_dac_get_free_buf_size(); + break; + + case AUD_DAC_CMD_PLAY: + audio_dac_play(); + break; + + case AUD_DAC_CMD_PAUSE: + audio_dac_pause(); + break; + + case AUD_DAC_CMD_SET_SAMPLE_RATE: + ASSERT(param); + audio_dac_set_enable_bit(0); + audio_dac_set_sample_rate(*((UINT32 *)param)); + audio_dac_set_enable_bit(1); + break; + + case AUD_DAC_CMD_SET_VOLUME: + ASSERT(param); + audio_dac_set_volume(*((UINT32 *)param)); + break; + + default: + break; + } + return ret; +} + +void audio_dac_software_init(void) +{ + ddev_register_dev(AUD_DAC_DEV_NAME, &aud_dac_op); + + os_memset(&aud_dac, 0, sizeof(AUD_DAC_DESC_ST)); + aud_dac.status = AUD_DAC_STA_CLOSED; +} + +void audio_dac_isr(void) +{ + UINT32 status = REG_READ(AUD_AD_FIFO_STATUS); + RB_PTR rb = NULL; + UINT32 ret = 0, channel; + INT16 sample[2] = {0}; + + if(aud_dac.status == AUD_DAC_STA_PLAYING && !aud_dac.dma_mode) + { + rb = &aud_dac.u.rb; + channel = aud_dac.channels; + if(status & (DAC_R_INT_FLAG | DAC_L_INT_FLAG)) + { + if(channel == 2) + { + while(!(status & (DAC_R_FIFO_FULL|DAC_L_FIFO_FULL))) + { + ret = rb_read(rb, (UINT8*)&sample[0], sizeof(int16), 2); + //AUD_PRT("%d\r\n", ret); + if(!ret) + break; + + audio_dac_set_sample(sample[0], sample[1]); + status = REG_READ(AUD_AD_FIFO_STATUS); + } + } else { + while(!(status & (DAC_R_FIFO_FULL|DAC_L_FIFO_FULL))) + { + ret = rb_read(rb, (UINT8*)&sample[0], sizeof(int16), 1); + if(!ret) + break; + + audio_dac_set_sample(sample[0], sample[0]); + status = REG_READ(AUD_AD_FIFO_STATUS); + } + } + } + } + + if(ret == 0) + { + while(!(status & (DAC_R_FIFO_FULL|DAC_L_FIFO_FULL))) + { + audio_dac_set_sample(0, 0); + status = REG_READ(AUD_AD_FIFO_STATUS); + } + //AUD_PRT("set\r\n"); + } +} + +#endif // CFG_USE_AUD_DAC + diff --git a/beken_os/beken378/driver/audio/audio_pub.h b/beken_os/beken378/driver/audio/audio_pub.h new file mode 100755 index 0000000..9a20959 --- /dev/null +++ b/beken_os/beken378/driver/audio/audio_pub.h @@ -0,0 +1,81 @@ +#ifndef __AUDIO_PUB_H__ +#define __AUDIO_PUB_H__ + +#define AUD_FAILURE (1) +#define AUD_SUCCESS (0) + +#define AUD_DAC_DEV_NAME "aud_dac" +#define AUD_DAC_CMD_MAGIC (0x1EBC0000) + +typedef struct aud_dac_cfg_st +{ + UINT8 *buf; + UINT16 buf_len; + UINT16 freq; + UINT16 channels; + UINT16 dma_mode; + UINT16 mute_pin; + UINT16 def_volume; +} AUD_DAC_CFG_ST, *AUD_DAC_CFG_PTR; + +enum +{ + AUD_DAC_CMD_GET_FREE_BUF_SIZE = AUD_DAC_CMD_MAGIC + 1, + AUD_DAC_CMD_PLAY, + AUD_DAC_CMD_PAUSE, + AUD_DAC_CMD_SET_SAMPLE_RATE, + AUD_DAC_CMD_SET_VOLUME, +}; + +#include "gpio_pub.h" +#include "sys_ctrl_pub.h" +#define AUD_USE_EXT_PA 0 +#if AUD_USE_EXT_PA +#define AUD_DAC_MUTE_PIN GPIO9 +#define AUD_DAC_MUTE_ENA_LEVEL 0 +#endif + + +/////////////////////////////////////////////////////////////////////////////// + + +#define AUD_ADC_DEV_NAME "aud_adc" +#define AUD_ADC_CMD_MAGIC (0x2EBC0000) +typedef struct aud_adc_cfg_st +{ + UINT8 *buf; + UINT16 buf_len; + UINT16 freq; + UINT16 channels; + UINT16 mode; + UINT32 linein_detect_pin; +} AUD_ADC_CFG_ST, *AUD_ADC_CFG_PTR; + +enum +{ + AUD_ADC_CMD_GET_FILL_BUF_SIZE = AUD_ADC_CMD_MAGIC + 1, + AUD_ADC_CMD_PLAY, + AUD_ADC_CMD_PAUSE, + AUD_ADC_CMD_DO_LINEIN_DETECT, + AUD_ADC_CMD_SET_SAMPLE_RATE, + AUD_ADC_CMD_SET_VOLUME +}; + + +#define AUD_ADC_LINEIN_DETECT_PIN GPIO8 +#define AUD_ADC_LINEIN_ENABLE_LEVEL 0 +#define AUD_ADC_DAC_HARDWARD_LOOPBACK 0 + +#define AUD_ADC_MODE_DMA_BIT (1 << 0) // 1: DMA MODE, 0: ISR MODE +#define AUD_ADC_MODE_LINEIN (1 << 1) // 1: LINEIN, 0: MIC +#define AUD_ADC_DEF_WR_THRED (8) +#define AUD_ADC_DEF_GAIN (0x2D) // 0dm +#define AUD_ADC_MAX_THRED (0x10) +#define AUD_ADC_MAX_VOLUME (124) + +void audio_init(void); +void audio_exit(void); + + + +#endif // __AUDIO_PUB_H__ \ No newline at end of file diff --git a/beken_os/beken378/driver/audio/ring_buffer.c b/beken_os/beken378/driver/audio/ring_buffer.c new file mode 100755 index 0000000..c390b7d --- /dev/null +++ b/beken_os/beken378/driver/audio/ring_buffer.c @@ -0,0 +1,194 @@ +#include "include.h" +#include "ring_buffer.h" +#include "arch.h" +#include "mem_pub.h" + +#define RWP_SAFE_INTERVAL (4) + +#define RB_MEMCPY os_memcpy +#define RB_INT_DECLARATION() GLOBAL_INT_DECLARATION() +#define RB_INT_DISABLE() GLOBAL_INT_DISABLE() +#define RB_INT_RESTORE() GLOBAL_INT_RESTORE() + +void rb_init(RB_PTR rb, UINT8 *addr, UINT32 capacity) +{ + RB_INT_DECLARATION(); + + RB_INT_DISABLE(); + rb->address = addr; + rb->capacity = capacity; + rb->wp = 0; + rb->rp = 0; + RB_INT_RESTORE(); +} + +void rb_clear(RB_PTR rb) +{ + RB_INT_DECLARATION(); + + RB_INT_DISABLE(); + rb->wp = 0; + rb->rp = 0; + RB_INT_RESTORE(); +} + +UINT32 rb_read(RB_PTR rb, UINT8 *buffer, UINT32 size, UINT32 count) +{ + UINT32 required_bytes = size * count; + UINT32 read_bytes; + UINT32 remain_bytes; + UINT32 wp; + RB_INT_DECLARATION(); + + wp = rb->wp; + + if(required_bytes == 0) + return 0; + + if(wp >= rb->rp) + { + remain_bytes = wp - rb->rp; + + if(required_bytes > remain_bytes) + { + read_bytes = remain_bytes; + RB_MEMCPY(buffer, &rb->address[rb->rp], read_bytes); + + RB_INT_DISABLE(); + rb->rp += read_bytes; + RB_INT_RESTORE(); + } + else + { + read_bytes = required_bytes; + RB_MEMCPY(buffer, &rb->address[rb->rp], read_bytes); + RB_INT_DISABLE(); + rb->rp += read_bytes; + RB_INT_RESTORE(); + } + } + else + { + remain_bytes = rb->capacity - rb->rp; + + if(required_bytes > remain_bytes) + { + read_bytes = remain_bytes; + RB_MEMCPY(buffer, &rb->address[rb->rp], read_bytes); + + if(required_bytes - read_bytes > wp) + { + RB_MEMCPY(buffer + read_bytes, &rb->address[0], wp); + RB_INT_DISABLE(); + rb->rp = wp; + RB_INT_RESTORE(); + read_bytes += wp; + } + else + { + RB_MEMCPY(buffer + read_bytes, &rb->address[0], required_bytes - read_bytes); + RB_INT_DISABLE(); + rb->rp = required_bytes - read_bytes; + RB_INT_RESTORE(); + read_bytes = required_bytes; + } + } + else + { + read_bytes = required_bytes; + RB_MEMCPY(buffer, &rb->address[rb->rp], read_bytes); + RB_INT_DISABLE(); + rb->rp += read_bytes; + RB_INT_RESTORE(); + } + } + + return read_bytes; +} + +UINT32 rb_write(RB_PTR rb, UINT8 *buffer, UINT32 size, UINT32 count) +{ + UINT32 remain_bytes; + UINT32 write_bytes = size * count; + UINT32 rp; + RB_INT_DECLARATION(); + + if(write_bytes == 0) + return 0; + + rp = rb->rp; + + if(rb->wp >= rp) + { + remain_bytes = rb->capacity - rb->wp + rp; + + if(remain_bytes >= write_bytes + RWP_SAFE_INTERVAL) + { + remain_bytes = rb->capacity - rb->wp; + + if(remain_bytes >= write_bytes) + { + RB_MEMCPY(&rb->address[rb->wp], buffer, write_bytes); + RB_INT_DISABLE(); + rb->wp += write_bytes; + RB_INT_RESTORE(); + } + else + { + RB_MEMCPY(&rb->address[rb->wp], buffer, remain_bytes); + RB_INT_DISABLE(); + rb->wp = write_bytes - remain_bytes; + RB_INT_RESTORE(); + RB_MEMCPY(&rb->address[0], &buffer[remain_bytes], rb->wp); + } + } + else + { + return 0; + } + } + else + { + remain_bytes = rp - rb->wp; + + if(remain_bytes >= write_bytes + RWP_SAFE_INTERVAL) + { + RB_MEMCPY(&rb->address[rb->wp], buffer, write_bytes); + RB_INT_DISABLE(); + rb->wp += write_bytes; + RB_INT_RESTORE(); + } + else + { + return 0; + } + } + + if(rb->wp >= rb->capacity && rb->rp) + { + RB_INT_DISABLE(); + rb->wp = 0; + RB_INT_RESTORE(); + } + + return write_bytes; +} + +UINT32 rb_get_fill_size(RB_PTR rb) +{ + UINT32 fill_size; + + fill_size = rb->wp >= rb->rp ? rb->wp - rb->rp : rb->capacity - rb->rp + rb->wp; + + return fill_size; +} + +UINT32 rb_get_free_size(RB_PTR rb) +{ + UINT32 free_size; + + free_size = rb->wp >= rb->rp ? rb->capacity - rb->wp + rb->rp : rb->rp - rb->wp; + + return free_size > RWP_SAFE_INTERVAL ? free_size - RWP_SAFE_INTERVAL : 0; +} + diff --git a/beken_os/beken378/driver/audio/ring_buffer.h b/beken_os/beken378/driver/audio/ring_buffer.h new file mode 100755 index 0000000..778f31b --- /dev/null +++ b/beken_os/beken378/driver/audio/ring_buffer.h @@ -0,0 +1,20 @@ +#ifndef __RING_BUFFER_H__ +#define __RING_BUFFER_H__ + + +typedef struct rb_st +{ + UINT8 *address; + UINT32 capacity; /**< memory capacity in bytes */ + UINT32 wp; /**< write point in bytes */ + UINT32 rp; /**< read point in bytes */ +}RB_ST, *RB_PTR; + +void rb_init(RB_PTR rb, UINT8 *addr, UINT32 capacity); +void rb_clear(RB_PTR rb); +UINT32 rb_read(RB_PTR rb, UINT8 *buffer, UINT32 size, UINT32 count); +UINT32 rb_write(RB_PTR rb, UINT8 *buffer, UINT32 size, UINT32 count); +UINT32 rb_get_fill_size(RB_PTR rb); +UINT32 rb_get_free_size(RB_PTR rb); + +#endif//__RING_BUFFER_H__ diff --git a/beken_os/beken378/driver/audio/ring_buffer_dma_read.c b/beken_os/beken378/driver/audio/ring_buffer_dma_read.c new file mode 100755 index 0000000..9432469 --- /dev/null +++ b/beken_os/beken378/driver/audio/ring_buffer_dma_read.c @@ -0,0 +1,167 @@ +#include "include.h" +#include "ring_buffer_dma_read.h" +#include "arch.h" +#include "mem_pub.h" +#include "drv_model_pub.h" +#include "uart_pub.h" + +#if CFG_GENERAL_DMA +#include "general_dma_pub.h" + +#define RWP_SAFE_INTERVAL (4) + +#define RB_DMA_RD_MEMCPY os_memcpy +#define RB_DMA_RD_INT_DECLARATION() +#define RB_DMA_RD_INT_DISABLE() +#define RB_DMA_RD_INT_RESTORE() +#define RB_DMA_RD_PRT //os_printf + +void rb_init_dma_read(RB_DMA_RD_PTR rb, UINT8 *addr, UINT32 capacity, UINT32 ch) +{ + GDMA_CFG_ST en_cfg; + RB_DMA_RD_INT_DECLARATION(); + + RB_DMA_RD_INT_DISABLE(); + rb->address = addr; + rb->capacity = capacity; + rb->wp = 0; + rb->rp = 0; + rb->dma_ch = ch; + RB_DMA_RD_INT_RESTORE(); + + en_cfg.channel = rb->dma_ch; + en_cfg.param = (UINT32)(rb->address + rb->wp); + RB_DMA_RD_PRT("init set src:%x\r\n", en_cfg.param); + sddev_control(GDMA_DEV_NAME, CMD_GDMA_SET_SRC_PAUSE_ADDR, &en_cfg); +} + +void rb_clear_dma_read(RB_DMA_RD_PTR rb) +{ + GDMA_CFG_ST en_cfg; + RB_DMA_RD_INT_DECLARATION(); + + RB_DMA_RD_INT_DISABLE(); + rb->wp = 0; + rb->rp = 0; + RB_DMA_RD_INT_RESTORE(); + + en_cfg.channel = rb->dma_ch; + en_cfg.param = (UINT32)(rb->address + rb->wp); + RB_DMA_RD_PRT("clear set src:%x\r\n", en_cfg.param); + sddev_control(GDMA_DEV_NAME, CMD_GDMA_SET_SRC_PAUSE_ADDR, &en_cfg); +} + + +UINT32 rb_write_dma_read(RB_DMA_RD_PTR rb, UINT8 *buffer, UINT32 size, UINT32 count) +{ + UINT32 remain_bytes; + UINT32 write_bytes = size * count; + UINT32 rp; + GDMA_CFG_ST en_cfg; + + RB_DMA_RD_INT_DECLARATION(); + + if(write_bytes == 0) + return 0; + + en_cfg.channel = rb->dma_ch; + en_cfg.param = 0; + rp = sddev_control(GDMA_DEV_NAME, CMD_GDMA_GET_SRC_READ_ADDR, &en_cfg); + RB_DMA_RD_PRT("write get src_rd:%x\r\n", rp); + rp -= (UINT32)rb->address; + rb->rp = rp; + + if(rb->wp >= rp) + { + remain_bytes = rb->capacity - rb->wp + rp; + + if(remain_bytes >= write_bytes + RWP_SAFE_INTERVAL) + { + remain_bytes = rb->capacity - rb->wp; + + if(remain_bytes >= write_bytes) + { + RB_DMA_RD_MEMCPY(&rb->address[rb->wp], buffer, write_bytes); + RB_DMA_RD_INT_DISABLE(); + rb->wp += write_bytes; + RB_DMA_RD_INT_RESTORE(); + } + else + { + RB_DMA_RD_MEMCPY(&rb->address[rb->wp], buffer, remain_bytes); + RB_DMA_RD_INT_DISABLE(); + rb->wp = write_bytes - remain_bytes; + RB_DMA_RD_INT_RESTORE(); + RB_DMA_RD_MEMCPY(&rb->address[0], &buffer[remain_bytes], rb->wp); + } + } + else + { + return 0; + } + } + else + { + remain_bytes = rp - rb->wp; + + if(remain_bytes >= write_bytes + RWP_SAFE_INTERVAL) + { + RB_DMA_RD_MEMCPY(&rb->address[rb->wp], buffer, write_bytes); + RB_DMA_RD_INT_DISABLE(); + rb->wp += write_bytes; + RB_DMA_RD_INT_RESTORE(); + } + else + { + return 0; + } + } + + if(rb->wp >= rb->capacity && rb->rp) + { + RB_DMA_RD_INT_DISABLE(); + rb->wp = 0; + RB_DMA_RD_INT_RESTORE(); + } + + en_cfg.channel = rb->dma_ch; + en_cfg.param = (UINT32)(rb->address + rb->wp); + RB_DMA_RD_PRT("write set src:%x\r\n", en_cfg.param); + sddev_control(GDMA_DEV_NAME, CMD_GDMA_SET_SRC_PAUSE_ADDR, &en_cfg); + + return write_bytes; +} + +UINT32 rb_get_fill_size_dma_read(RB_DMA_RD_PTR rb) +{ + UINT32 fill_size, rp; + GDMA_CFG_ST en_cfg; + + en_cfg.channel = rb->dma_ch; + rp = sddev_control(GDMA_DEV_NAME, CMD_GDMA_GET_SRC_READ_ADDR, &en_cfg); + RB_DMA_RD_PRT("fillsize get src_rd:%x\r\n", rp); + rp -= (UINT32)rb->address; + rb->rp = rp; + + fill_size = rb->wp >= rb->rp ? rb->wp - rb->rp : rb->capacity - rb->rp + rb->wp; + + return fill_size; +} + +UINT32 rb_get_free_size_dma_read(RB_DMA_RD_PTR rb) +{ + UINT32 free_size, rp; + GDMA_CFG_ST en_cfg; + + en_cfg.channel = rb->dma_ch; + rp = sddev_control(GDMA_DEV_NAME, CMD_GDMA_GET_SRC_READ_ADDR, &en_cfg); + RB_DMA_RD_PRT("freesize get src_rd:%x\r\n", rp); + rp -= (UINT32)rb->address; + rb->rp = rp; + + free_size = rb->wp >= rb->rp ? rb->capacity - rb->wp + rb->rp : rb->rp - rb->wp; + + return free_size > RWP_SAFE_INTERVAL ? free_size - RWP_SAFE_INTERVAL : 0; +} + +#endif // CFG_GENERAL_DMA \ No newline at end of file diff --git a/beken_os/beken378/driver/audio/ring_buffer_dma_read.h b/beken_os/beken378/driver/audio/ring_buffer_dma_read.h new file mode 100755 index 0000000..60a57b8 --- /dev/null +++ b/beken_os/beken378/driver/audio/ring_buffer_dma_read.h @@ -0,0 +1,20 @@ +#ifndef __RING_BUFFER_DMA_RD_H__ +#define __RING_BUFFER_DMA_RD_H__ + + +typedef struct rb_dma_rd_st +{ + UINT8 *address; + UINT32 capacity; /**< memory capacity in bytes */ + UINT32 wp; /**< write point in bytes */ + UINT32 rp; /**< read point in bytes */ + UINT32 dma_ch; +}RB_DMA_RD_ST, *RB_DMA_RD_PTR; + +void rb_init_dma_read(RB_DMA_RD_PTR rb, UINT8 *addr, UINT32 capacity, UINT32 ch); +void rb_clear_dma_read(RB_DMA_RD_PTR rb); +UINT32 rb_write_dma_read(RB_DMA_RD_PTR rb, UINT8 *buffer, UINT32 size, UINT32 count); +UINT32 rb_get_fill_size_dma_read(RB_DMA_RD_PTR rb); +UINT32 rb_get_free_size_dma_read(RB_DMA_RD_PTR rb); + +#endif//__RING_BUFFER_DMA_RD_H__ \ No newline at end of file diff --git a/beken_os/beken378/driver/audio/ring_buffer_dma_write.c b/beken_os/beken378/driver/audio/ring_buffer_dma_write.c new file mode 100755 index 0000000..47f30e4 --- /dev/null +++ b/beken_os/beken378/driver/audio/ring_buffer_dma_write.c @@ -0,0 +1,172 @@ +#include "include.h" +#include "ring_buffer_dma_write.h" +#include "arch.h" +#include "mem_pub.h" +#include "drv_model_pub.h" +#include "uart_pub.h" + +#if CFG_GENERAL_DMA +#include "general_dma_pub.h" + +#define RWP_SAFE_INTERVAL (4) +#define RB_DMA_WR_MEMCPY os_memcpy +#define RB_DMA_WR_INT_DECLARATION() +#define RB_DMA_WR_INT_DISABLE() +#define RB_DMA_WR_INT_RESTORE() +#define RB_DMA_WR_PRT //os_printf + +void rb_init_dma_write(RB_DMA_WR_PTR rb, UINT8 *addr, UINT32 capacity, UINT32 ch) +{ + GDMA_CFG_ST en_cfg; + RB_DMA_WR_INT_DECLARATION(); + + RB_DMA_WR_INT_DISABLE(); + rb->address = addr; + rb->capacity = capacity; + rb->wp = 0; + rb->rp = 0; + rb->dma_ch = ch; + RB_DMA_WR_INT_RESTORE(); + + en_cfg.channel = rb->dma_ch; + en_cfg.param = (UINT32)(rb->address + rb->capacity - RWP_SAFE_INTERVAL); + RB_DMA_WR_PRT("init set dst:%x\r\n", en_cfg.param); + sddev_control(GDMA_DEV_NAME, CMD_GDMA_SET_DST_PAUSE_ADDR, &en_cfg); +} + +void rb_clear_dma_write(RB_DMA_WR_PTR rb) +{ + GDMA_CFG_ST en_cfg; + RB_DMA_WR_INT_DECLARATION(); + + RB_DMA_WR_INT_DISABLE(); + rb->wp = 0; + rb->rp = 0; + RB_DMA_WR_INT_RESTORE(); + + en_cfg.channel = rb->dma_ch; + en_cfg.param = (UINT32)(rb->address + rb->capacity - RWP_SAFE_INTERVAL); + RB_DMA_WR_PRT("clear set dst:%x\r\n", en_cfg.param); + sddev_control(GDMA_DEV_NAME, CMD_GDMA_SET_DST_PAUSE_ADDR, &en_cfg); +} + +UINT32 rb_read_dma_write(RB_DMA_WR_PTR rb, UINT8 *buffer, UINT32 size, UINT32 count) +{ + UINT32 required_bytes = size * count; + UINT32 read_bytes; + UINT32 remain_bytes; + UINT32 wp; + GDMA_CFG_ST en_cfg; + + RB_DMA_WR_INT_DECLARATION(); + + if(required_bytes == 0) + return 0; + + en_cfg.channel = rb->dma_ch; + wp = sddev_control(GDMA_DEV_NAME, CMD_GDMA_GET_DST_WRITE_ADDR, &en_cfg); + RB_DMA_WR_PRT("rb read get dst_wr:%x\r\n", wp); + wp -= (UINT32)rb->address; + rb->wp = wp; + + if(wp >= rb->rp) + { + remain_bytes = wp - rb->rp; + + if(required_bytes > remain_bytes) + { + read_bytes = remain_bytes; + } + else + { + read_bytes = required_bytes; + } + + RB_DMA_WR_MEMCPY(buffer, &rb->address[rb->rp], read_bytes); + RB_DMA_WR_INT_DISABLE(); + rb->rp += read_bytes; + RB_DMA_WR_INT_RESTORE(); + } + else + { + remain_bytes = rb->capacity - rb->rp; + + if(required_bytes > remain_bytes) + { + read_bytes = remain_bytes; + RB_DMA_WR_MEMCPY(buffer, &rb->address[rb->rp], read_bytes); + + if(required_bytes - read_bytes > wp) + { + RB_DMA_WR_MEMCPY(buffer + read_bytes, &rb->address[0], wp); + RB_DMA_WR_INT_DISABLE(); + rb->rp = wp; + RB_DMA_WR_INT_RESTORE(); + read_bytes += wp; + } + else + { + RB_DMA_WR_MEMCPY(buffer + read_bytes, &rb->address[0], required_bytes - read_bytes); + RB_DMA_WR_INT_DISABLE(); + rb->rp = required_bytes - read_bytes; + RB_DMA_WR_INT_RESTORE(); + read_bytes = required_bytes; + } + } + else + { + read_bytes = required_bytes; + RB_DMA_WR_MEMCPY(buffer, &rb->address[rb->rp], read_bytes); + RB_DMA_WR_INT_DISABLE(); + rb->rp += read_bytes; + RB_DMA_WR_INT_RESTORE(); + } + } + + + + en_cfg.channel = rb->dma_ch; + if(rb->rp >= RWP_SAFE_INTERVAL) + en_cfg.param = (UINT32)(rb->address + rb->rp - RWP_SAFE_INTERVAL); + else + en_cfg.param = (UINT32)(rb->address + rb->capacity + rb->rp - RWP_SAFE_INTERVAL); + + RB_DMA_WR_PRT("read set dst:%x\r\n", en_cfg.param); + sddev_control(GDMA_DEV_NAME, CMD_GDMA_SET_DST_PAUSE_ADDR, &en_cfg); + + return read_bytes; +} + +UINT32 rb_get_fill_size_dma_write(RB_DMA_WR_PTR rb) +{ + UINT32 fill_size, wp; + GDMA_CFG_ST en_cfg; + + en_cfg.channel = rb->dma_ch; + wp = sddev_control(GDMA_DEV_NAME, CMD_GDMA_GET_DST_WRITE_ADDR, &en_cfg); + RB_DMA_WR_PRT("fillsize get dst_wr:%x\r\n", wp); + wp -= (UINT32)rb->address; + rb->wp = wp; + + fill_size = rb->wp >= rb->rp ? rb->wp - rb->rp : rb->capacity - rb->rp + rb->wp; + + return fill_size; +} + +UINT32 rb_get_free_size_dma_write(RB_DMA_WR_PTR rb) +{ + UINT32 free_size, wp; + GDMA_CFG_ST en_cfg; + + en_cfg.channel = rb->dma_ch; + wp = sddev_control(GDMA_DEV_NAME, CMD_GDMA_GET_DST_WRITE_ADDR, &en_cfg); + RB_DMA_WR_PRT("free size get dst_wr:%x\r\n", wp); + wp -= (UINT32)rb->address; + rb->wp = wp; + + free_size = rb->wp >= rb->rp ? rb->capacity - rb->wp + rb->rp : rb->rp - rb->wp; + + return free_size > RWP_SAFE_INTERVAL ? free_size - RWP_SAFE_INTERVAL : 0; +} + +#endif // CFG_GENERAL_DMA diff --git a/beken_os/beken378/driver/audio/ring_buffer_dma_write.h b/beken_os/beken378/driver/audio/ring_buffer_dma_write.h new file mode 100755 index 0000000..b002486 --- /dev/null +++ b/beken_os/beken378/driver/audio/ring_buffer_dma_write.h @@ -0,0 +1,20 @@ +#ifndef __RING_BUFFER_DMA_WR_H__ +#define __RING_BUFFER_DMA_WR_H__ + + +typedef struct rb_dma_rd_st +{ + UINT8 *address; + UINT32 capacity; /**< memory capacity in bytes */ + UINT32 wp; /**< write point in bytes */ + UINT32 rp; /**< read point in bytes */ + UINT32 dma_ch; +}RB_DMA_WR_ST, *RB_DMA_WR_PTR; + +void rb_init_dma_write(RB_DMA_WR_PTR rb, UINT8 *addr, UINT32 capacity, UINT32 ch); +void rb_clear_dma_write(RB_DMA_WR_PTR rb); +UINT32 rb_read_dma_write(RB_DMA_WR_PTR rb, UINT8 *buffer, UINT32 size, UINT32 count); +UINT32 rb_get_fill_size_dma_write(RB_DMA_WR_PTR rb); +UINT32 rb_get_free_size_dma_write(RB_DMA_WR_PTR rb); + +#endif//__RING_BUFFER_DMA_RD_H__ \ No newline at end of file diff --git a/beken_os/beken378/driver/ble/ble.c b/beken_os/beken378/driver/ble/ble.c new file mode 100755 index 0000000..a1c2e56 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble.c @@ -0,0 +1,832 @@ +#include "include.h" + +#include "drv_model_pub.h" +#include "intc_pub.h" +#include "uart_pub.h" + +#include "ble.h" +#include "ble_pub.h" +#include "ble_api.h" +#include "rwble.h" +#include "app_task.h" +#include "udebug.h" +#include "typedef.h" +#include "sys_ctrl_pub.h" +#include "icu_pub.h" +#include "intc_pub.h" +#include "common_bt.h" +#include "arm_arch.h" +#include "rw_pub.h" +#include "power_save_pub.h" +#include "gapc_task.h" +#include "bk7011_cal_pub.h" + +#define BLE_MSG_QUEUE_COUNT (20) + +beken_queue_t ble_msg_que = NULL; +beken_thread_t ble_thread_handle = NULL; +#if (CFG_DEFAULT_RF_USER == CFG_RF_USER_BLE) +beken_thread_t rf_switch_thread = NULL; +int rf_loop = 0; +#endif +uint32_t ble_stack_size = 4096; +uint32_t ble_dut_flag = 0; +ble_event_cb_t ble_event_cb = NULL; +ble_recv_adv_cb_t ble_recv_adv_cb = NULL; +bk_ble_read_cb_t bk_ble_read_cb = NULL; +bk_ble_write_cb_t bk_ble_write_cb = NULL; +ble_role_t ble_role_mode = BLE_ROLE_NONE; +uint8_t ble_switch_old_state = HW_IDLE; +uint8_t ble_switch_mac_sleeped = 0; +uint8_t ble_active = 0; + +typedef struct ble_cfg_st { + struct bd_addr mac; + char name[APP_DEVICE_NAME_LENGTH_MAX]; +}BLE_CFG_ST, *BLE_CFG_PTR; +BLE_CFG_ST ble_cfg; + +static SDD_OPERATIONS ble_op = +{ + ble_ctrl +}; + + +extern /*const */struct bd_addr common_default_bdaddr; +extern void uart_isr(void); +extern void intc_service_change_handler(UINT8 int_num, FUNCPTR isr); +extern void wifi_get_mac_address(char *mac, u8 type); +extern void rwnxl_reset_handle(int dummy); +extern uint32_t ps_get_sleep_prevent(void); +extern UINT32 txl_cntrl_pck_get(void ); +extern void sctrl_modem_core_reset(void); +extern void delay(INT32 num); +extern void rw_main(void); +extern void appm_update_param(struct gapc_conn_param *conn_param); + +void ble_intc_set(uint32_t enable) +{ + if(enable) + intc_enable(FIQ_BLE); + else + intc_disable(FIQ_BLE); +} + +void ble_clk_power_up(void) +{ + UINT32 param; + param = PWD_BLE_CLK_BIT; + sddev_control(ICU_DEV_NAME, CMD_TL410_CLK_PWR_UP, ¶m); +} + +void ble_clk_power_down(void) +{ + UINT32 param; + param = PWD_BLE_CLK_BIT; + sddev_control(ICU_DEV_NAME, CMD_TL410_CLK_PWR_DOWN, ¶m); +} + +UINT32 rf_wifi_used = 0; + +void rf_wifi_used_set(void) +{ + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + if(0 == rf_wifi_used) + { + rf_wifi_used = 1; + } + GLOBAL_INT_RESTORE(); +} + +void rf_wifi_used_clr(void) +{ + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + if(1 == rf_wifi_used) + { + rf_wifi_used = 0; + } + GLOBAL_INT_RESTORE(); +} + +UINT32 if_rf_wifi_used(void ) +{ + uint32_t value = 0; + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + value = rf_wifi_used; + GLOBAL_INT_RESTORE(); + return value; +} + +uint8 is_rf_switch_to_ble(void) +{ + UINT32 param; + + sddev_control(SCTRL_DEV_NAME, CMD_BLE_RF_BIT_GET, ¶m); + + return (param > 0 ) ? 1 : 0; +} + +void ble_switch_rf_to_wifi(void) +{ + // if in ble dut mode, no need change back to wifi any more. + // ble dut mode can not exit until power off + // if (!is_rf_switch_to_ble() || power_save_if_rf_sleep()) + if (!is_rf_switch_to_ble()) + return; + + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); +#if ATE_APP_FUN + if(!get_ate_mode_state()) +#endif + { + rwnx_cal_recover_txpwr_for_wifi(); + } + + rwnx_cal_ble_recover_rfconfig(); + + sddev_control(SCTRL_DEV_NAME, CMD_BLE_RF_BIT_CLR, NULL); + extern void sctrl_set_rf_sleep(void); + sctrl_set_rf_sleep();//after swtich wifi check if can stop rf + ble_switch_mac_sleeped = 0; + if(power_save_if_rf_sleep()) + { + GLOBAL_INT_RESTORE(); + return; + } + if (ble_switch_old_state != HW_IDLE && nxmac_current_state_getf() == HW_IDLE) + { + if(ke_state_get(TASK_MM) == MM_ACTIVE) + { + nxmac_next_state_setf(ble_switch_old_state); + while (nxmac_current_state_getf() != ble_switch_old_state); + } + } + + + if (!power_save_if_rf_sleep()) + { + power_save_rf_ps_wkup_semlist_set(); + } + GLOBAL_INT_RESTORE(); + + //Re-enable MAC interrupts + nxmac_enable_master_gen_int_en_setf(1); + nxmac_enable_master_tx_rx_int_en_setf(1); + + //PS_DEBUG_RF_UP_TRIGER; +} + +#define MAX_SKIP_CNT 5 +uint32_t ble_switch_skip_cnt = 0; +void ble_switch_data_pend(void) +{ + return; + while(ble_switch_skip_cnt == MAX_SKIP_CNT) + { + bk_printf("p"); + rtos_delay_milliseconds(2) ; + } +} + +void ble_switch_clear_mac_interrupts(void) +{ + uint32_t fiq_status; + + hal_machw_disable_int(); + nxmac_tx_rx_int_ack_clear(0xffffffff); + nxmac_gen_int_ack_clear(0xffffffff); + fiq_status = sddev_control(ICU_DEV_NAME, CMD_GET_INTR_STATUS, 0); + fiq_status = fiq_status & 0xFFFF0000; + sddev_control(ICU_DEV_NAME, CMD_CLR_INTR_STATUS, &fiq_status); +} + +void ble_switch_rf_to_ble(void) +{ + if(if_rf_wifi_used()) + return; + + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + + if (txl_cntrl_pck_get() && ble_switch_skip_cnt < MAX_SKIP_CNT) + { + ble_switch_skip_cnt++; + GLOBAL_INT_RESTORE(); + return; + } + + if (ps_get_sleep_prevent() & 0x37) + { + GLOBAL_INT_RESTORE(); + return; + } + + if(REG_READ((ICU_BASE + 19 * 4)) + & (CO_BIT(FIQ_MAC_TX_RX_MISC) + | CO_BIT(FIQ_MAC_TX_RX_TIMER) + | CO_BIT(FIQ_MAC_RX_TRIGGER) + | CO_BIT(FIQ_MAC_TX_TRIGGER) + | CO_BIT(FIQ_MAC_GENERAL) + | CO_BIT(FIQ_MAC_PROT_TRIGGER) + | CO_BIT(FIQ_DPLL_UNLOCK) + )) + { + GLOBAL_INT_RESTORE(); + return; + } + + ble_switch_skip_cnt = 0; + + ble_switch_old_state = nxmac_current_state_getf(); + + // Ask HW to go to IDLE + if (ble_switch_old_state == HW_ACTIVE) + { + uint32_t i_tmp = 0, y_tmp = 0; + uint32_t v_tmp; + + // Ask HW to go to IDLE + if (nxmac_current_state_getf() != HW_IDLE) + { + nxmac_next_state_setf(HW_IDLE); + + while(1) + { + if(nxmac_status_idle_interrupt_getf() == 1) + break; + else + { + i_tmp++; + if(i_tmp > 1000) + { + i_tmp = 0; + v_tmp =nxmac_state_cntrl_get(); + PS_WPRT("s s:0x%x c:0x%x\r\n",v_tmp,power_save_get_sleep_count()); + y_tmp ++; + if(y_tmp > 500) + { + y_tmp = 0; + PS_WPRT("idle rec\r\n"); + bk_printf("idle rec\r\n"); + //long time wait idle interrupt,recover! + hal_machw_disable_int(); + rwnxl_reset_handle(0); + PS_WPRT("idle rec over\r\n"); + nxmac_next_state_setf(HW_IDLE); + } + } + } + } + //while (nxmac_status_idle_interrupt_getf() != 1); + nxmac_gen_int_ack_clear(NXMAC_IDLE_INTERRUPT_BIT); + + // reset modem. + sctrl_modem_core_reset(); + + // Disable MAC interrupts and clear all existing ones + ble_switch_clear_mac_interrupts(); + } + } + else + ble_switch_old_state = HW_IDLE; + + sctrl_rf_wakeup();//after swtich ble check if need start rf + + sddev_control(SCTRL_DEV_NAME, CMD_BLE_RF_BIT_SET, NULL); + + rwnx_cal_ble_set_rfconfig(); + +#if ATE_APP_FUN + if(!get_ate_mode_state()) +#endif + { + rwnx_cal_set_txpwr_for_ble_boardcast(); + } + + ble_switch_mac_sleeped = 1; + + GLOBAL_INT_RESTORE(); + + //PS_DEBUG_RF_UP_TRIGER; +} + +void ble_request_rf_by_isr(void) +{ +#if (CFG_DEFAULT_RF_USER == CFG_RF_USER_WIFI) + if(!ble_dut_flag) + { + ble_switch_rf_to_ble(); + } +#else + if (kernel_state_get(TASK_APP) == APPM_CONNECTED) + { + ble_switch_rf_to_ble(); + } +#endif +} + +void ble_release_rf_by_isr(void) +{ +#if (CFG_DEFAULT_RF_USER == CFG_RF_USER_WIFI) + if(!ble_dut_flag) + { + ble_switch_rf_to_wifi(); + } +#else + if (kernel_state_get(TASK_APP) == APPM_CONNECTED) + { + ble_switch_rf_to_wifi(); + } +#endif +} + +void ble_set_power_up(uint32 up) +{ + if(up) + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_BLE_POWERUP, NULL); + else + { +#if ATE_APP_FUN + if(!get_ate_mode_state()) +#endif + { + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_BLE_POWERDOWN, NULL); + } + } +} + +void ble_set_pn9_trx(uint32 param) +{ + UINT32 reg; + + if(PN9_RX == param) + { + reg = 0x0; + REG_WRITE(REG_BLE_XVR_TRX_CONFIG_ADDR, reg); + delay(10); + reg = 0x2400; + REG_WRITE(REG_BLE_XVR_TRX_CONFIG_ADDR, reg); + } + else + { + reg = 0x0; + REG_WRITE(REG_BLE_XVR_TRX_CONFIG_ADDR, reg); + delay(10); + reg = 0x3800; + REG_WRITE(REG_BLE_XVR_TRX_CONFIG_ADDR, reg); + } +} + +void ble_init(void) +{ + intc_service_register( FIQ_BLE, PRI_FIQ_BLE, ble_isr ); + + sddev_register_dev( BLE_DEV_NAME, &ble_op ); + + return; +} + +void ble_exit(void) +{ + sddev_unregister_dev( BLE_DEV_NAME ); + + return; +} + +UINT32 ble_ctrl( UINT32 cmd, void *param ) +{ + UINT32 reg; + UINT32 ret = ERR_SUCCESS; + + switch(cmd) + { + case CMD_BLE_REG_INIT: + break; + + case CMD_BLE_REG_DEINIT: + break; + + case CMD_BLE_SET_CHANNEL: + reg = REG_READ(REG_BLE_XVR_CHANNEL_CONFIG_ADDR); + reg &= ~(REG_BLE_XVR_CHANNEL_VALUE_MASK << REG_BLE_XVR_CHANNEL_VALUE_POST); + reg |= (*(UINT32 *)param) << REG_BLE_XVR_CHANNEL_VALUE_POST; + REG_WRITE(REG_BLE_XVR_CHANNEL_CONFIG_ADDR, reg); + reg = REG_READ(REG_BLE_XVR_TRX_CONFIG_ADDR); + reg &= ~(1 << REG_BLE_XVR_TEST_RADIO_POST); + REG_WRITE(REG_BLE_XVR_TRX_CONFIG_ADDR, reg); + delay(10); + reg |= (1 << REG_BLE_XVR_TEST_RADIO_POST); + REG_WRITE(REG_BLE_XVR_TRX_CONFIG_ADDR, reg); + break; + + case CMD_BLE_AUTO_CHANNEL_ENABLE: + reg = REG_READ(REG_BLE_XVR_CHANNEL_CONFIG_ADDR); + reg |= 1 << REG_BLE_XVR_AUTO_CHANNEL_POST; + REG_WRITE(REG_BLE_XVR_CHANNEL_CONFIG_ADDR, reg); + break; + + case CMD_BLE_AUTO_CHANNEL_DISABLE: + reg = REG_READ(REG_BLE_XVR_CHANNEL_CONFIG_ADDR); + reg &= ~(1 << REG_BLE_XVR_AUTO_CHANNEL_POST); + REG_WRITE(REG_BLE_XVR_CHANNEL_CONFIG_ADDR, reg); + break; + + case CMD_BLE_AUTO_SYNCWD_ENABLE: + reg = REG_READ(REG_BLE_XVR_CHANNEL_CONFIG_ADDR); + reg |= 1 << REG_BLE_XVR_AUTO_SYNCWD_POST; + REG_WRITE(REG_BLE_XVR_CHANNEL_CONFIG_ADDR, reg); + break; + + case CMD_BLE_AUTO_SYNCWD_DISABLE: + reg = REG_READ(REG_BLE_XVR_CHANNEL_CONFIG_ADDR); + reg &= ~(1 << REG_BLE_XVR_AUTO_SYNCWD_POST); + REG_WRITE(REG_BLE_XVR_CHANNEL_CONFIG_ADDR, reg); + break; + + case CMD_BLE_SET_PN9_TRX: + ble_set_pn9_trx(*(UINT32 *)param); + break; + + case CMD_BLE_SET_GFSK_SYNCWD: + reg = (*(UINT32 *)param); + REG_WRITE(REG_BLE_XVR_GFSK_SYNCWD_ADDR, reg); + break; + + case CMD_BLE_HOLD_PN9_ESTIMATE: + reg = REG_READ(REG_BLE_XVR_TRX_CONFIG_ADDR); + reg |= 1 << REG_BLE_XVR_HOLD_ESTIMATE_POST; + REG_WRITE(REG_BLE_XVR_TRX_CONFIG_ADDR, reg); + break; + + case CMD_BLE_STOP_COUNTING: + reg = REG_READ(REG_BLE_XVR_TRX_CONFIG_ADDR); + reg &= ~(1 << REG_BLE_XVR_PN9_RECV_POST); + REG_WRITE(REG_BLE_XVR_TRX_CONFIG_ADDR, reg); + break; + + case CMD_BLE_START_COUNTING: + reg = REG_READ(REG_BLE_XVR_TRX_CONFIG_ADDR); + reg |= 1 << REG_BLE_XVR_PN9_RECV_POST; + reg &= ~(1 << REG_BLE_XVR_HOLD_ESTIMATE_POST); + REG_WRITE(REG_BLE_XVR_TRX_CONFIG_ADDR, reg); + break; + + default: + ret = ERR_CMD_NOT_SUPPORT; + break; + } + + return ret; +} + +void ble_isr(void) +{ + rwble_isr(); + return; +} + +static void ble_main( void *arg ) +{ + memcpy(&common_default_bdaddr, &ble_cfg.mac, sizeof(struct bd_addr)); + memcpy(&app_dflt_dev_name, &ble_cfg.name, APP_DEVICE_NAME_LENGTH_MAX); + + if(!ble_dut_flag) + { + UINT8 *mac = (UINT8 *)&ble_cfg.mac; + + os_printf("ble name:%s, %02x:%02x:%02x:%02x:%02x:%02x\r\n", + app_dflt_dev_name, mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + } + rw_main(); + + rtos_deinit_queue(&ble_msg_que); + ble_msg_que = NULL; +#if (CFG_DEFAULT_RF_USER == CFG_RF_USER_BLE) + rf_loop = 0; +#endif + ble_thread_handle = NULL; + rtos_delete_thread(NULL); +} + +#if (CFG_DEFAULT_RF_USER == CFG_RF_USER_BLE) +ble_err_t ble_request_rf(rf_time_t *rt) +{ + ble_err_t rc = ERR_SUCCESS; + rw_evt_type sta_stat; + + if(rt == NULL) + { + return ERR_REQ_RF; + } + + sta_stat = mhdr_get_station_status(); + + //bk_printf("sta_stat:%d\r\n", sta_stat); + + if(sta_stat == RW_EVT_STA_GOT_IP) + { + if(power_save_if_rf_sleep()) + { + sctrl_rf_wakeup(); + + /* wake up after a beacon package, next beacon will coming in 100 ms */ + UINT32 power_save_time_to_sleep(void); + rt->ble_rf_time = power_save_time_to_sleep(); + if(rt->ble_rf_time < 10) + { + rt->ble_rf_time = 10; + } + else + { + rt->ble_rf_time -= 3; + } + rt->wifi_rf_time = 15; + } + else + { + /* + rt->ble_rf_time = 15; + rt->wifi_rf_time = 60; + */ + rt->ble_rf_time = 10; + } + } + else if(sta_stat == MSG_IDLE) + { + rt->ble_rf_time = 200; + rt->wifi_rf_time = 10; + } + else + { + rt->ble_rf_time = 20; + rt->wifi_rf_time = 100; + } + + return rc; +} + +void ble_release_rf(void *param) +{ + ble_switch_rf_to_wifi(); + return; +} + +void rf_switch_loop(void *param) +{ + rt_timer_t ble_timer; + rf_time_t rf_tm; + int timeout_tick; + int *loop = (int *)param; + + ble_timer = rt_timer_create("ble_timer", ble_release_rf, NULL, 10, RT_TIMER_FLAG_ONE_SHOT|RT_TIMER_FLAG_SOFT_TIMER); + if (NULL == ble_timer) + { + bk_printf("create one shot ble timer failed\n"); + return; + } + + bk_printf("rf_switch_loop start\r\n"); + + while (*loop) + { + if(ble_request_rf(&rf_tm) == ERR_REQ_RF) + { + break; + } + /* switch rf to ble if ble can run more than 10 ms */ + if (rf_tm.ble_rf_time > 10) + { + timeout_tick = rt_tick_from_millisecond(rf_tm.ble_rf_time); + rt_timer_control(ble_timer, RT_TIMER_CTRL_SET_TIME, (void *)&timeout_tick); + rt_timer_start(ble_timer); + + ble_switch_rf_to_ble(); + /* dealing with scan result in this interval... no matter in this task or others */ + timeout_tick = rt_tick_from_millisecond(rf_tm.ble_rf_time + rf_tm.wifi_rf_time); + rt_thread_delay(timeout_tick); + } + else + { + timeout_tick = rt_tick_from_millisecond(10);//check power save 10ms later + rt_thread_delay(timeout_tick); + } + } + + rf_switch_thread = NULL; + + rt_timer_delete(ble_timer); + + bk_printf("rf_switch_loop end\r\n"); +} +#endif + +static void ble_thread_start(void) +{ + OSStatus ret; + + if(!ble_thread_handle && !ble_msg_que) + { + ret = rtos_init_queue(&ble_msg_que, + "ble_msg_queue", + sizeof(BLE_MSG_T), + BLE_MSG_QUEUE_COUNT); + ASSERT(0 == ret); + + ret = rtos_create_thread(&ble_thread_handle, + 6, + "ble", + (beken_thread_function_t)ble_main, + (unsigned short)ble_stack_size, + (beken_thread_arg_t)0); + + ASSERT(0 == ret); + } +#if (CFG_DEFAULT_RF_USER == CFG_RF_USER_BLE) + if(!rf_switch_thread) + { + rf_loop = 1; + rtos_create_thread(&rf_switch_thread, 15, "rf_switch_loop", rf_switch_loop, 2048, &rf_loop); + } +#endif +} + +void ble_stop(void) +{ + if(ble_thread_handle) { + ble_send_msg(BLE_MSG_EXIT); + + while(ble_thread_handle) + rtos_delay_milliseconds(100); + } +} + +void ble_activate(char *ble_name) +{ + UINT32 len; + +// bk_wlan_stop(1); + + if((!ble_name) && (!ble_dut_flag)) { + os_printf("ble start no ble name\r\n"); + ble_name = APP_DFLT_DEVICE_NAME; + } + + ble_stop(); + + memset(&ble_cfg, 0, sizeof(BLE_CFG_ST)); + + wifi_get_mac_address((char *)&ble_cfg.mac, 2); // get sta's mac addr + ble_cfg.mac.addr[0] += 1; // add 1, diff from wifi's mac + + len = strlen(ble_name); + len = (len > APP_DEVICE_NAME_LENGTH_MAX)? APP_DEVICE_NAME_LENGTH_MAX:len; + memcpy(&ble_cfg.name, ble_name, len); + + ble_thread_start(); +} + +void ble_dut_start(void) +{ + if(!ble_thread_handle) + { + ble_dut_flag = 1; + extern uint8_t system_mode; + system_mode = RW_DUT_MODE; + os_printf("enter ble dut\r\n"); + rwnx_no_use_tpc_set_pwr(); + sddev_control(SCTRL_DEV_NAME, CMD_BLE_RF_BIT_SET, NULL); + + #if (BLE_DUT_UART_PORT == PORT_UART2) + intc_service_change_handler(IRQ_UART2, uart_isr); + #else + intc_service_change_handler(IRQ_UART1, uart_isr); + #endif // (BLE_DUT_UART_PORT == PORT_UART2) + + ble_activate(NULL); + } +} + +UINT8 ble_is_start(void) +{ + return (ble_thread_handle == NULL)? 0:1; +} + +UINT8* ble_get_mac_addr(void) +{ + return (UINT8*)&common_default_bdaddr; +} + +UINT8* ble_get_name(void) +{ + return (UINT8*)&app_dflt_dev_name; +} + +void ble_send_msg(UINT32 data) +{ + OSStatus ret; + BLE_MSG_T msg; + + if(ble_msg_que) { + msg.data = data; + + ret = rtos_push_to_queue(&ble_msg_que, &msg, BEKEN_NO_WAIT); + if(0 != ret) + { + //os_printf("ble_send_msg failed\r\n"); + } + } +} + +int blemsg_is_empty(void) +{ + if(!rtos_is_queue_empty(&ble_msg_que)) + { + return 0; + } + else + { + return 1; + } +} + +void ble_update_connection(void) +{ + struct gapc_conn_param up_param; + + up_param.intv_min = 39;///78; + up_param.intv_max = 40;//80; + up_param.latency = 0; + up_param.time_out = BLE_UAPDATA_TIMEOUT; + + appm_update_param(&up_param); +} + +void ble_update_connection2(void) +{ + struct gapc_conn_param up_param; + + up_param.intv_min = 78; + up_param.intv_max = 80; + up_param.latency = 10; + up_param.time_out = BLE_UAPDATA_TIMEOUT; + + appm_update_param(&up_param); +} + +unsigned char mhdr_wifi_status = RW_EVT_STA_IDLE; +void ble_is_wifi_status(void) +{ + if((kernel_state_get(TASK_APP) == APPM_CONNECTED) + && (mhdr_get_station_status() == RW_EVT_STA_GOT_IP) + && (mhdr_wifi_status != RW_EVT_STA_GOT_IP)) + { + mhdr_wifi_status = mhdr_get_station_status(); + ble_update_connection2(); + } + else if((kernel_state_get(TASK_APP) == APPM_CONNECTED) + && (mhdr_get_station_status() != RW_EVT_STA_GOT_IP) + && (mhdr_wifi_status == RW_EVT_STA_GOT_IP)) + { + mhdr_wifi_status = mhdr_get_station_status(); + ble_update_connection(); + } +} + +void ble_set_write_cb(bk_ble_write_cb_t func) +{ + bk_ble_write_cb = func; +} + +void ble_set_event_cb(ble_event_cb_t func) +{ + ble_event_cb = func; +} + +void ble_set_recv_adv_cb(ble_recv_adv_cb_t func) +{ + ble_recv_adv_cb = func; +} + +void ble_set_read_cb(bk_ble_read_cb_t func) +{ + bk_ble_read_cb = func; +} + +void ble_set_role_mode(ble_role_t role) +{ + ble_role_mode = role; +} + +ble_role_t ble_get_role_mode() +{ + return ble_role_mode; +} + +UINT32 ble_in_dut_mode(void) +{ + return (ble_dut_flag == 1) ? 1 : 0; +} diff --git a/beken_os/beken378/driver/ble/ble.h b/beken_os/beken378/driver/ble/ble.h new file mode 100755 index 0000000..bef3340 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble.h @@ -0,0 +1,116 @@ +#ifndef _BLE_H_ +#define _BLE_H_ + +#include "include.h" +#include "rtos_pub.h" +#include "rwble_config.h" + +#define BLE_PS_DEBUG +#ifdef BLE_PS_DEBUG +#define BLE_PS_PRT os_printf +#else +#define BLE_PS_PRT os_null_printf +#endif + +#define BLE_CONN_IDX_MAX (0x01) +#define BLE_CHAR_DATA_LEN (128) + +#define REG_BLE_XVR_BASE_ADDR (0x0080B400) + +#define BLE_XVR_SLOT_TIME (REG_BLE_XVR_BASE_ADDR + 0x2a * 4) +#define BLE_XVR_RF_TX_DELAY_POSI (24) +#define BLE_XVR_RF_TX_DELAY_MASK (0xFF) +#define BLE_XVR_RF_RX_DELAY_POSI (16) +#define BLE_XVR_RF_RX_DELAY_MASK (0xFF) +#define BLE_XVR_TX_SLOT_TIME_POSI (8) +#define BLE_XVR_TX_SLOT_TIME_MASK (0xFF) +#define BLE_XVR_RX_SLOT_TIME_POSI (0) +#define BLE_XVR_RX_SLOT_TIME_MASK (0xFF) + +#define REG_BLE_XVR_CHANNEL_CONFIG_ADDR (REG_BLE_XVR_BASE_ADDR + 0x24 * 4) +#define REG_BLE_XVR_CHANNEL_VALUE_POST (0) +#define REG_BLE_XVR_CHANNEL_VALUE_MASK (0x7F) +#define REG_BLE_XVR_AUTO_CHANNEL_POST (17) +#define REG_BLE_XVR_AUTO_SYNCWD_POST (19) + +#define REG_BLE_XVR_TRX_CONFIG_ADDR (REG_BLE_XVR_BASE_ADDR + 0x25 * 4) +#define REG_BLE_XVR_TEST_RADIO_POST (13) +#define REG_BLE_XVR_HOLD_ESTIMATE_POST (9) +#define REG_BLE_XVR_PN9_RECV_POST (10) + +#define REG_BLE_XVR_GFSK_SYNCWD_ADDR (REG_BLE_XVR_BASE_ADDR + 0x20 * 4) + + +#define REG_BLE_XVR_RADIOON_CONFIG_ADDR (REG_BLE_XVR_BASE_ADDR + 0x29 * 4) + +#define BLE_USER_CMD_OPCODE (0xFCE0) +#define BLE_USER_CMD_EXIT_DUT_LEN (2) +#define BLE_USER_CMD_EXIT_DUT_CMD (0x0E) +#define BLE_USER_CMD_EXIT_DUT_ACT (0xA0) +#define BLE_USER_CMD_TX_PWR_SET_CMD (0x10) +#define BLE_USER_CMD_TX_PWR_SAVE_CMD (0x11) +#define BLE_USER_CMD_XTAL_SET_CMD (0x12) + +// ble dut uart port +#define PORT_UART1 (1) +#define PORT_UART2 (2) +#define BLE_DUT_UART_PORT PORT_UART1 // PORT_UART2 + + +typedef enum { + BLE_PS_FORBID_KRL = 1, + BLE_PS_FORBID_ENABLED = 2, + BLE_PS_FORBID_PREVENT = 3, + BLE_PS_FORBID_TM = 4, + BLE_PS_FORBID_RWBT = 5, + BLE_PS_FORBID_RWBLE = 6, + BLE_PS_FORBID_EA = 7, + BLE_PS_FORBID_H4TL = 8, +} BLE_PS_FORBID_STATUS; + +typedef struct ble_message +{ + uint32_t data; +}BLE_MSG_T; + +typedef struct rf_time_s +{ + UINT32 ble_rf_time; + UINT32 wifi_rf_time; +} rf_time_t; + +typedef enum +{ + BLE_ROLE_NONE = 0, + BLE_ROLE_MASTER, + BLE_ROLE_SLAVE, + BLE_ROLE_HYBRID, /* reserved */ +} ble_role_t; + +#define APP_DEVICE_NAME_LENGTH_MAX (18) +/// Default Device Name if no value can be found in NVDS +#define APP_DFLT_DEVICE_NAME ("BK7231BT-01") +#define APP_DFLT_DEVICE_NAME_LEN (sizeof(APP_DFLT_DEVICE_NAME)) + +extern char app_dflt_dev_name[APP_DEVICE_NAME_LENGTH_MAX]; +extern uint32_t ble_dut_flag; +extern ble_role_t ble_role_mode; +extern beken_queue_t ble_msg_que; +extern uint8_t ble_init_over; +extern uint8_t ble_deep_sleep; + +extern UINT32 ble_ctrl( UINT32 cmd, void *param ); +extern void ble_isr(void); +extern void ble_set_role_mode(ble_role_t role); +extern ble_role_t ble_get_role_mode(); +extern void ble_send_msg(UINT32 msg); +extern void ble_intc_set(uint32_t enable); +extern void ble_clk_power_up(void); +extern void ble_clk_power_down(void); +extern void ble_switch_rf_to_wifi(void); +extern void ble_switch_rf_to_ble(void); +extern void ble_set_power_up(uint32 up); +extern UINT32 ble_ps_enabled(void ); +extern UINT16 ble_ps_forbid_trace(BLE_PS_FORBID_STATUS forbid); + +#endif /* _BLE_H_ */ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ahi/api/ahi.h b/beken_os/beken378/driver/ble/ble_lib/ip/ahi/api/ahi.h new file mode 100755 index 0000000..5c6e88b --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ahi/api/ahi.h @@ -0,0 +1,122 @@ +/** + **************************************************************************************** + * + * @file ahi.h + * + * @brief This file contains definitions related to the Application Host Interface + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef AHI_H_ +#define AHI_H_ + +/** + **************************************************************************************** + * @addtogroup AHI Application Host Interface + * @ingroup AHI + * @brief Application Host Interface, based on AHI functionality. + * + *@{ + * + **************************************************************************************** + */ + + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" // SW configuration + +#if (AHI_TL_SUPPORT) +#include "rwip.h" // SW interface + +#include "stdbool.h" // boolean definition +#include "kernel_msg.h" // kernel message definition +#include "common_list.h" // list API + + + +/* + * Defines + **************************************************************************************** + */ +/// Kernel message type +#define AHI_KERNEL_MSG_TYPE 0x05 +///Kernel message header length for transport through interface between App and SW stack. +#define AHI_KERNEL_MSG_HDR_LEN 8 + +/// GAPM Reset size (LC + KERNEL_HEADER + Reset_operation code) +#define AHI_RESET_MSG_LEN (1+AHI_KERNEL_MSG_HDR_LEN+1) +/// GAPM Reset Message use to resync. +#define AHI_RESET_MSG_BUF {AHI_KERNEL_MSG_TYPE, \ + (GAPM_RESET_CMD & 0xFF), ((GAPM_RESET_CMD >> 8) & 0xFF), \ + (TASK_ID_GAPM & 0xFF), ((TASK_ID_GAPM >> 8) & 0xFF), \ + (TASK_ID_AHI & 0xFF), ((TASK_ID_AHI >> 8) & 0xFF), \ + 0x01, 0x00, GAPM_RESET}; + + +/// Size of the sync pattern (RW!) +#define AHI_SYNC_PATTERN_SIZE 3 +/// Transport layer synchronization pattern +#define AHI_SYNC_PATTERN_BUF "RW!" + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + +///Structure for application system interface packet header +struct ahi_kemsghdr +{ + ///Message id + kernel_msg_id_t id; + ///Destination task identifier for KE + kernel_task_id_t dest_id; + ///Source task identifier for KE + kernel_task_id_t src_id; + ///Message parameter length + uint16_t param_len; +}; + + +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ + + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief AHI initialization function: initializes states and transport. + ***************************************************************************************** + */ +void ahi_init(void); + + +/** + **************************************************************************************** + * @brief Send a data message over the Application to Host Interface + * + * @param[in] msg_type Message type (logical channel) + * @param[in] len Message data length + * @param[in] data Data buffer to send + * @param[in] msg_type Callback called when message is send. It provides message pointer + ***************************************************************************************** + */ +void ahi_send_msg(uint8_t msg_type, uint16_t len, uint8_t *data, void (*tx_callback)(uint8_t *)); + +#endif //AHI_TL_SUPPORT + +/// @} AHI +#endif // AHI_H_ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ahi/api/ahi_task.h b/beken_os/beken378/driver/ble/ble_lib/ip/ahi/api/ahi_task.h new file mode 100755 index 0000000..f5a5775 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ahi/api/ahi_task.h @@ -0,0 +1,83 @@ +/** + **************************************************************************************** + * + * @file ahi_task.h + * + * @brief This file contains definitions related to the Application Host Interface + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef AHI_TASK_H_ +#define AHI_TASK_H_ + +/** + **************************************************************************************** + * @addtogroup AHI Application Host Interface + *@{ + **************************************************************************************** + */ + + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" // SW configuration + +#if (AHI_TL_SUPPORT) + +#include "rwip_task.h" // Task definition +#include "rwble_hl.h" // BLE HL default include + +/* + * INSTANCES + **************************************************************************************** + */ +/// Maximum number of instances of the AHI task +#define AHI_IDX_MAX 1 + +/* + * STATES + **************************************************************************************** + */ +/// Possible states of the AHI task +enum AHI_STATE +{ + /// TX IDLE state + AHI_TX_IDLE, + /// TX ONGOING state + AHI_TX_ONGOING, + /// Number of states. + AHI_STATE_MAX +}; + +/* + * MESSAGES + **************************************************************************************** + */ +/// Message API of the AHI task +enum AHI_MSG +{ + AHI_MSG_ID_FIRST = TASK_FIRST_MSG(TASK_ID_AHI), + + AHI_MSG_ID_LAST +}; + +/* + * TASK DESCRIPTOR DECLARATIONS + **************************************************************************************** + */ +extern const struct kernel_state_handler ahi_default_handler; +extern kernel_state_t ahi_state[AHI_IDX_MAX]; + +#endif //AHI_TL_SUPPORT + +/// @} AHI + +#endif // AHI_TASK_H_ + diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/api/att.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/api/att.h new file mode 100755 index 0000000..b2d153d --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/api/att.h @@ -0,0 +1,1169 @@ +/** + **************************************************************************************** + * + * @file att.h + * + * @brief Header file - ATT. + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + +#ifndef ATT_H_ +#define ATT_H_ + +/** + **************************************************************************************** + * @addtogroup ATT Attribute Protocol + * @ingroup HOST + * @brief Attribute Protocol. + * + * The ATT block contains the procedures for discovering, reading, writing + * and indicating attributes to peer device . It also defines a number of items + * that caters to the security aspect of the block as access to some information + * may require both authorization and an authenticated and encrypted physical + * link before an attribute can be read or written + * + * @{ + * + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include + +/* + * DEFINES + **************************************************************************************** + */ + +/// Macro used to convert CPU integer define to LSB first 16-bits UUID +#define ATT_UUID_16(uuid) (uuid) + +/// Invalid attribute handle +#define ATT_INVALID_HDL (0x0000) +/// Invalid attribute idx (used for profiles) +#define ATT_INVALID_IDX (0xff) + +#define ATT_1ST_REQ_START_HDL 0x0001 +#define ATT_1ST_REQ_END_HDL 0xFFFF + +/// Maximum possible attribute handle +#define ATT_MAX_ATTR_HDL ATT_1ST_REQ_END_HDL + +/// Offset of value in signed PDU +#define ATT_SIGNED_PDU_VAL_OFFSET 0x03 + +/// Attribute Features +#define ATT_SERVER_CONFIG 0x0001 +#define ATT_SERVICE_DISC 0x0002 +#define ATT_RELATIONSHIP_DISC 0x0004 +#define ATT_CHAR_DISC 0x0008 +#define ATT_CHAR_DESC_DISC 0x0010 +#define ATT_RD_CHAR_VALUE 0x0020 +#define ATT_WR_CHAR_VALUE 0x0040 +#define ATT_NOTIF_CHAR_VALUE 0x0080 +#define ATT_IND_CHAR_VALUE 0x0100 +#define ATT_RD_CHAR_DESC 0x0200 +#define ATT_WR_CHAR_DESC 0x0400 + +/// Length, number, offset defines +#define ATT_SVC_VALUE_MAX_LEN 0x0030 +#define ATT_CHAR_NAME_MAX_LEN 0x0030 +#define ATT_UUID_16_LEN 0x0002 +#define ATT_UUID_32_LEN 0x0004 +#define ATT_UUID_128_LEN 0x0010 + +/// offset - l2cap header and ATT code +#define ATT_PDU_DATA_OFFSET 0x05 + +/// Characteristic Properties Bit +#define ATT_CHAR_PROP_BCAST 0x01 +#define ATT_CHAR_PROP_RD 0x02 +#define ATT_CHAR_PROP_WR_NO_RESP 0x04 +#define ATT_CHAR_PROP_WR 0x08 +#define ATT_CHAR_PROP_NTF 0x10 +#define ATT_CHAR_PROP_IND 0x20 +#define ATT_CHAR_PROP_AUTH 0x40 +#define ATT_CHAR_PROP_EXT_PROP 0x80 +/// Invalid Attribute Handle +#define ATT_INVALID_SEARCH_HANDLE 0x0000 +#define ATT_INVALID_HANDLE 0x0000 +/// Read Information Request +#define ATT_UUID_FILTER_0 0x00 +#define ATT_UUID_FILTER_2 0x02 +#define ATT_UUID_FILTER_16 0x10 +/// Read Information Response +#define ATT_FORMAT_LEN 0x0001 +#define ATT_FORMAT_16BIT_UUID 0x01 +#define ATT_FORMAT_128BIT_UUID 0x02 +/// For No fix length PDU +#define ATT_HANDLE_LEN 0x0002 +#define ATT_EACHLEN_LEN 0x0001 +#define ATT_PROP_LEN 0x0001 +#define ATT_CODE_LEN 0x0001 +#define ATT_CODE_AND_DATA_LEN 0x0002 +#define ATT_CODE_AND_HANDLE_LEN 0x0003 +#define ATT_CODE_AND_HANDLE_LEN_AND_OFFSET 0x0005 +#define ATT_SIGNATURE_LEN 0x0C + +/// extended characteristics +#define ATT_EXT_RELIABLE_WRITE 0x0001 +#define ATT_EXT_WRITABLE_AUX 0x0002 +#define ATT_EXT_RFU 0xFFFC + +/// PDU size for error response +#define ATT_ERROR_RESP_LEN 0x05 + +/// Offset of value in signed PDU +#define ATT_SIGNED_PDU_VAL_OFFSET 0x03 + +#define HI_UINT16(a) (((a) >> 8) & 0xFF) +#define LO_UINT16(a) ((a) & 0xFF) + + +// TI Base 128-bit UUID: F000XXXX-0451-4000-B000-000000000000 +#define TI_BASE_UUID_128( uuid ) {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB0, \ + 0x00, 0x40, 0x51, 0x04, LO_UINT16( uuid ), HI_UINT16( uuid ), 0x00, 0xF0} + + +// TI Base 128-bit UUID: F000XXXX-0451-4000-B000-000000000000 +#define TI_BASE_UUID_1281 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB0, \ + 0x00, 0x40, 0x51, 0x04, 0x00, 0x00, 0x00, 0xF0} + + +#define ATT_BT_UUID_128 {0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80, \ + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} + + + +/* Attribute Specification Defines */ + +/// Common 16-bit Universal Unique Identifier +enum +{ + ATT_INVALID_UUID = ATT_UUID_16(0x0000), + /*----------------- SERVICES ---------------------*/ + /// Generic Access Profile + ATT_SVC_GENERIC_ACCESS = ATT_UUID_16(0x1800), + /// Attribute Profile + ATT_SVC_GENERIC_ATTRIBUTE = ATT_UUID_16(0x1801), + /// Immediate alert Service + ATT_SVC_IMMEDIATE_ALERT = ATT_UUID_16(0x1802), + /// Link Loss Service + ATT_SVC_LINK_LOSS = ATT_UUID_16(0x1803), + /// Tx Power Service + ATT_SVC_TX_POWER = ATT_UUID_16(0x1804), + /// Current Time Service Service + ATT_SVC_CURRENT_TIME = ATT_UUID_16(0x1805), + /// Reference Time Update Service + ATT_SVC_REF_TIME_UPDATE = ATT_UUID_16(0x1806), + /// Next DST Change Service + ATT_SVC_NEXT_DST_CHANGE = ATT_UUID_16(0x1807), + /// Glucose Service + ATT_SVC_GLUCOSE = ATT_UUID_16(0x1808), + /// Health Thermometer Service + ATT_SVC_HEALTH_THERMOM = ATT_UUID_16(0x1809), + /// Device Information Service + ATT_SVC_DEVICE_INFO = ATT_UUID_16(0x180A), + /// Heart Rate Service + ATT_SVC_HEART_RATE = ATT_UUID_16(0x180D), + /// Phone Alert Status Service + ATT_SVC_PHONE_ALERT_STATUS = ATT_UUID_16(0x180E), + /// Battery Service + ATT_SVC_BATTERY_SERVICE = ATT_UUID_16(0x180F), + /// Blood Pressure Service + ATT_SVC_BLOOD_PRESSURE = ATT_UUID_16(0x1810), + /// Alert Notification Service + ATT_SVC_ALERT_NTF = ATT_UUID_16(0x1811), + /// HID Service + ATT_SVC_HID = ATT_UUID_16(0x1812), + /// Scan Parameters Service + ATT_SVC_SCAN_PARAMETERS = ATT_UUID_16(0x1813), + /// Running Speed and Cadence Service + ATT_SVC_RUNNING_SPEED_CADENCE = ATT_UUID_16(0x1814), + /// Cycling Speed and Cadence Service + ATT_SVC_CYCLING_SPEED_CADENCE = ATT_UUID_16(0x1816), + /// Cycling Power Service + ATT_SVC_CYCLING_POWER = ATT_UUID_16(0x1818), + /// Location and Navigation Service + ATT_SVC_LOCATION_AND_NAVIGATION = ATT_UUID_16(0x1819), + /// Environmental Sensing Service + ATT_SVC_ENVIRONMENTAL_SENSING = ATT_UUID_16(0x181A), + /// Body Composition Service + ATT_SVC_BODY_COMPOSITION = ATT_UUID_16(0x181B), + /// User Data Service + ATT_SVC_USER_DATA = ATT_UUID_16(0x181C), + /// Weight Scale Service + ATT_SVC_WEIGHT_SCALE = ATT_UUID_16(0x181D), + /// Bond Management Service + ATT_SVC_BOND_MANAGEMENT = ATT_UUID_16(0x181E), + /// Continuous Glucose Monitoring Service + ATT_SVC_CONTINUOUS_GLUCOSE_MONITORING = ATT_UUID_16(0x181F), + /// Internet Protocol Support Service + ATT_SVC_IP_SUPPORT = ATT_UUID_16(0x1820), + /// Indoor Positioning Service + ATT_SVC_INDOOR_POSITIONING = ATT_UUID_16(0x1821), + /// Pulse Oximeter Service + ATT_SVC_PULSE_OXIMETER = ATT_UUID_16(0x1822), + /// HTTP Proxy Service + ATT_SVC_HTTP_PROXY = ATT_UUID_16(0x1823), + /// Transport Discovery Service + ATT_SVC_TRANSPORT_DISCOVERY = ATT_UUID_16(0x1824), + /// Object Transfer Service + ATT_SVC_OBJECT_TRANSFER = ATT_UUID_16(0x1825), + /// Mesh Provisioning Service + ATT_SVC_MESH_PROVISIONING = ATT_UUID_16(0x1827), + /// Mesh Proxy Service + ATT_SVC_MESH_PROXY = ATT_UUID_16(0x1828), + + /*------------------- UNITS ---------------------*/ + /// No defined unit + ATT_UNIT_UNITLESS = ATT_UUID_16(0x2700), + /// Length Unit - Metre + ATT_UNIT_METRE = ATT_UUID_16(0x2701), + ///Mass unit - Kilogram + ATT_UNIT_KG = ATT_UUID_16(0x2702), + ///Time unit - second + ATT_UNIT_SECOND = ATT_UUID_16(0x2703), + ///Electric current unit - Ampere + ATT_UNIT_AMPERE = ATT_UUID_16(0x2704), + ///Thermodynamic Temperature unit - Kelvin + ATT_UNIT_KELVIN = ATT_UUID_16(0x2705), + /// Amount of substance unit - mole + ATT_UNIT_MOLE = ATT_UUID_16(0x2706), + ///Luminous intensity unit - candela + ATT_UNIT_CANDELA = ATT_UUID_16(0x2707), + ///Area unit - square metres + ATT_UNIT_SQ_METRE = ATT_UUID_16(0x2710), + ///Colume unit - cubic metres + ATT_UNIT_CUBIC_METRE = ATT_UUID_16(0x2710), + ///Velocity unit - metres per second + ATT_UNIT_METRE_PER_SECOND = ATT_UUID_16(0x2711), + ///Acceleration unit - metres per second squared + ATT_UNIT_METRES_PER_SEC_SQ = ATT_UUID_16(0x2712), + ///Wavenumber unit - reciprocal metre + ATT_UNIT_RECIPROCAL_METRE = ATT_UUID_16(0x2713), + ///Density unit - kilogram per cubic metre + ATT_UNIT_DENS_KG_PER_CUBIC_METRE = ATT_UUID_16(0x2714), + ///Surface density unit - kilogram per square metre + ATT_UNIT_KG_PER_SQ_METRE = ATT_UUID_16(0x2715), + ///Specific volume unit - cubic metre per kilogram + ATT_UNIT_CUBIC_METRE_PER_KG = ATT_UUID_16(0x2716), + ///Current density unit - ampere per square metre + ATT_UNIT_AMPERE_PER_SQ_METRE = ATT_UUID_16(0x2717), + ///Magnetic field strength unit - Ampere per metre + ATT_UNIT_AMPERE_PER_METRE = ATT_UUID_16(0x2718), + ///Amount concentration unit - mole per cubic metre + ATT_UNIT_MOLE_PER_CUBIC_METRE = ATT_UUID_16(0x2719), + ///Mass Concentration unit - kilogram per cubic metre + ATT_UNIT_MASS_KG_PER_CUBIC_METRE = ATT_UUID_16(0x271A), + ///Luminance unit - candela per square metre + ATT_UNIT_CANDELA_PER_SQ_METRE = ATT_UUID_16(0x271B), + ///Refractive index unit + ATT_UNIT_REFRACTIVE_INDEX = ATT_UUID_16(0x271C), + ///Relative permeability unit + ATT_UNIT_RELATIVE_PERMEABILITY = ATT_UUID_16(0x271D), + ///Plane angle unit - radian + ATT_UNIT_RADIAN = ATT_UUID_16(0x2720), + ///Solid angle unit - steradian + ATT_UNIT_STERADIAN = ATT_UUID_16(0x2721), + ///Frequency unit - Hertz + ATT_UNIT_HERTZ = ATT_UUID_16(0x2722), + ///Force unit - Newton + ATT_UNIT_NEWTON = ATT_UUID_16(0x2723), + ///Pressure unit - Pascal + ATT_UNIT_PASCAL = ATT_UUID_16(0x2724), + ///Energy unit - Joule + ATT_UNIT_JOULE = ATT_UUID_16(0x2725), + ///Power unit - Watt + ATT_UNIT_WATT = ATT_UUID_16(0x2726), + ///electric Charge unit - Coulomb + ATT_UNIT_COULOMB = ATT_UUID_16(0x2727), + ///Electric potential difference - Volt + ATT_UNIT_VOLT = ATT_UUID_16(0x2728), + ///Capacitance unit - Farad + ATT_UNIT_FARAD = ATT_UUID_16(0x2729), + ///electric resistance unit - Ohm + ATT_UNIT_OHM = ATT_UUID_16(0x272A), + ///Electric conductance - Siemens + ATT_UNIT_SIEMENS = ATT_UUID_16(0x272B), + ///Magnetic flux unit - Weber + ATT_UNIT_WEBER = ATT_UUID_16(0x272C), + ///Magnetic flux density unit - Tesla + ATT_UNIT_TESLA = ATT_UUID_16(0x272D), + ///Inductance unit - Henry + ATT_UNIT_HENRY = ATT_UUID_16(0x272E), + ///Temperature unit - degree Celsius + ATT_UNIT_CELSIUS = ATT_UUID_16(0x272F), + ///Luminous flux unit - lumen + ATT_UNIT_LUMEN = ATT_UUID_16(0x2730), + ///Illuminance unit - lux + ATT_UNIT_LUX = ATT_UUID_16(0x2731), + ///Activity referred to a radionuclide unit - becquerel + ATT_UNIT_BECQUEREL = ATT_UUID_16(0x2732), + ///Absorbed dose unit - Gray + ATT_UNIT_GRAY = ATT_UUID_16(0x2733), + ///Dose equivalent unit - Sievert + ATT_UNIT_SIEVERT = ATT_UUID_16(0x2734), + ///Catalytic activity unit - Katal + ATT_UNIT_KATAL = ATT_UUID_16(0x2735), + ///Synamic viscosity unit - Pascal second + ATT_UNIT_PASCAL_SECOND = ATT_UUID_16(0x2740), + ///Moment of force unit - Newton metre + ATT_UNIT_NEWTON_METRE = ATT_UUID_16(0x2741), + ///surface tension unit - Newton per metre + ATT_UNIT_NEWTON_PER_METRE = ATT_UUID_16(0x2742), + ///Angular velocity unit - radian per second + ATT_UNIT_RADIAN_PER_SECOND = ATT_UUID_16(0x2743), + ///Angular acceleration unit - radian per second squared + ATT_UNIT_RADIAN_PER_SECOND_SQ = ATT_UUID_16(0x2744), + ///Heat flux density unit - Watt per square metre + ATT_UNIT_WATT_PER_SQ_METRE = ATT_UUID_16(0x2745), + ///HEat capacity unit - Joule per Kelvin + ATT_UNIT_JOULE_PER_KELVIN = ATT_UUID_16(0x2746), + ///Specific heat capacity unit - Joule per kilogram kelvin + ATT_UNIT_JOULE_PER_KG_KELVIN = ATT_UUID_16(0x2747), + ///Specific Energy unit - Joule per kilogram + ATT_UNIT_JOULE_PER_KG = ATT_UUID_16(0x2748), + ///Thermal conductivity - Watt per metre Kelvin + ATT_UNIT_WATT_PER_METRE_KELVIN = ATT_UUID_16(0x2749), + ///Energy Density unit - joule per cubic metre + ATT_UNIT_JOULE_PER_CUBIC_METRE = ATT_UUID_16(0x274A), + ///Electric field strength unit - volt per metre + ATT_UNIT_VOLT_PER_METRE = ATT_UUID_16(0x274B), + ///Electric charge density unit - coulomb per cubic metre + ATT_UNIT_COULOMB_PER_CUBIC_METRE = ATT_UUID_16(0x274C), + ///Surface charge density unit - coulomb per square metre + ATT_UNIT_SURF_COULOMB_PER_SQ_METRE = ATT_UUID_16(0x274D), + ///Electric flux density unit - coulomb per square metre + ATT_UNIT_FLUX_COULOMB_PER_SQ_METRE = ATT_UUID_16(0x274E), + ///Permittivity unit - farad per metre + ATT_UNIT_FARAD_PER_METRE = ATT_UUID_16(0x274F), + ///Permeability unit - henry per metre + ATT_UNIT_HENRY_PER_METRE = ATT_UUID_16(0x2750), + ///Molar energy unit - joule per mole + ATT_UNIT_JOULE_PER_MOLE = ATT_UUID_16(0x2751), + ///Molar entropy unit - joule per mole kelvin + ATT_UNIT_JOULE_PER_MOLE_KELVIN = ATT_UUID_16(0x2752), + ///Exposure unit - coulomb per kilogram + ATT_UNIT_COULOMB_PER_KG = ATT_UUID_16(0x2753), + ///Absorbed dose rate unit - gray per second + ATT_UNIT_GRAY_PER_SECOND = ATT_UUID_16(0x2754), + ///Radiant intensity unit - watt per steradian + ATT_UNIT_WATT_PER_STERADIAN = ATT_UUID_16(0x2755), + ///Radiance unit - watt per square meter steradian + ATT_UNIT_WATT_PER_SQ_METRE_STERADIAN = ATT_UUID_16(0x2756), + ///Catalytic activity concentration unit - katal per cubic metre + ATT_UNIT_KATAL_PER_CUBIC_METRE = ATT_UUID_16(0x2757), + ///Time unit - minute + ATT_UNIT_MINUTE = ATT_UUID_16(0x2760), + ///Time unit - hour + ATT_UNIT_HOUR = ATT_UUID_16(0x2761), + ///Time unit - day + ATT_UNIT_DAY = ATT_UUID_16(0x2762), + ///Plane angle unit - degree + ATT_UNIT_ANGLE_DEGREE = ATT_UUID_16(0x2763), + ///Plane angle unit - minute + ATT_UNIT_ANGLE_MINUTE = ATT_UUID_16(0x2764), + ///Plane angle unit - second + ATT_UNIT_ANGLE_SECOND = ATT_UUID_16(0x2765), + ///Area unit - hectare + ATT_UNIT_HECTARE = ATT_UUID_16(0x2766), + ///Volume unit - litre + ATT_UNIT_LITRE = ATT_UUID_16(0x2767), + ///Mass unit - tonne + ATT_UNIT_TONNE = ATT_UUID_16(0x2768), + ///Pressure unit - bar + ATT_UNIT_BAR = ATT_UUID_16(0x2780), + ///Pressure unit - millimetre of mercury + ATT_UNIT_MM_MERCURY = ATT_UUID_16(0x2781), + ///Length unit - angstrom + ATT_UNIT_ANGSTROM = ATT_UUID_16(0x2782), + ///Length unit - nautical mile + ATT_UNIT_NAUTICAL_MILE = ATT_UUID_16(0x2783), + ///Area unit - barn + ATT_UNIT_BARN = ATT_UUID_16(0x2784), + ///Velocity unit - knot + ATT_UNIT_KNOT = ATT_UUID_16(0x2785), + ///Logarithmic radio quantity unit - neper + ATT_UNIT_NEPER = ATT_UUID_16(0x2786), + ///Logarithmic radio quantity unit - bel + ATT_UNIT_BEL = ATT_UUID_16(0x2787), + ///Length unit - yard + ATT_UNIT_YARD = ATT_UUID_16(0x27A0), + ///Length unit - parsec + ATT_UNIT_PARSEC = ATT_UUID_16(0x27A1), + ///length unit - inch + ATT_UNIT_INCH = ATT_UUID_16(0x27A2), + ///length unit - foot + ATT_UNIT_FOOT = ATT_UUID_16(0x27A3), + ///length unit - mile + ATT_UNIT_MILE = ATT_UUID_16(0x27A4), + ///pressure unit - pound-force per square inch + ATT_UNIT_POUND_FORCE_PER_SQ_INCH = ATT_UUID_16(0x27A5), + ///velocity unit - kilometre per hour + ATT_UNIT_KM_PER_HOUR = ATT_UUID_16(0x27A6), + ///velocity unit - mile per hour + ATT_UNIT_MILE_PER_HOUR = ATT_UUID_16(0x27A7), + ///angular velocity unit - revolution per minute + ATT_UNIT_REVOLUTION_PER_MINUTE = ATT_UUID_16(0x27A8), + ///energy unit - gram calorie + ATT_UNIT_GRAM_CALORIE = ATT_UUID_16(0x27A9), + ///energy unit - kilogram calorie + ATT_UNIT_KG_CALORIE = ATT_UUID_16(0x27AA), + /// energy unit - kilowatt hour + ATT_UNIT_KILOWATT_HOUR = ATT_UUID_16(0x27AB), + ///thermodynamic temperature unit - degree Fahrenheit + ATT_UNIT_FAHRENHEIT = ATT_UUID_16(0x27AC), + ///percentage + ATT_UNIT_PERCENTAGE = ATT_UUID_16(0x27AD), + ///per mille + ATT_UNIT_PER_MILLE = ATT_UUID_16(0x27AE), + ///period unit - beats per minute) + ATT_UNIT_BEATS_PER_MINUTE = ATT_UUID_16(0x27AF), + ///electric charge unit - ampere hours + ATT_UNIT_AMPERE_HOURS = ATT_UUID_16(0x27B0), + ///mass density unit - milligram per decilitre + ATT_UNIT_MILLIGRAM_PER_DECILITRE = ATT_UUID_16(0x27B1), + ///mass density unit - millimole per litre + ATT_UNIT_MILLIMOLE_PER_LITRE = ATT_UUID_16(0x27B2), + ///time unit - year + ATT_UNIT_YEAR = ATT_UUID_16(0x27B3), + ////time unit - month + ATT_UNIT_MONTH = ATT_UUID_16(0x27B4), + + + /*---------------- DECLARATIONS -----------------*/ + /// Primary service Declaration + ATT_DECL_PRIMARY_SERVICE = ATT_UUID_16(0x2800), + /// Secondary service Declaration + ATT_DECL_SECONDARY_SERVICE = ATT_UUID_16(0x2801), + /// Include Declaration + ATT_DECL_INCLUDE = ATT_UUID_16(0x2802), + /// Characteristic Declaration + ATT_DECL_CHARACTERISTIC = ATT_UUID_16(0x2803), + + + /*----------------- DESCRIPTORS -----------------*/ + /// Characteristic extended properties + ATT_DESC_CHAR_EXT_PROPERTIES = ATT_UUID_16(0x2900), + /// Characteristic user description + ATT_DESC_CHAR_USER_DESCRIPTION = ATT_UUID_16(0x2901), + /// Client characteristic configuration + ATT_DESC_CLIENT_CHAR_CFG = ATT_UUID_16(0x2902), + /// Server characteristic configuration + ATT_DESC_SERVER_CHAR_CFG = ATT_UUID_16(0x2903), + /// Characteristic Presentation Format + ATT_DESC_CHAR_PRES_FORMAT = ATT_UUID_16(0x2904), + /// Characteristic Aggregate Format + ATT_DESC_CHAR_AGGREGATE_FORMAT = ATT_UUID_16(0x2905), + /// Valid Range + ATT_DESC_VALID_RANGE = ATT_UUID_16(0x2906), + /// External Report Reference + ATT_DESC_EXT_REPORT_REF = ATT_UUID_16(0x2907), + /// Report Reference + ATT_DESC_REPORT_REF = ATT_UUID_16(0x2908), + /// Environmental Sensing Configuration + ATT_DESC_ES_CONFIGURATION = ATT_UUID_16(0x290B), + /// Environmental Sensing Measurement + ATT_DESC_ES_MEASUREMENT = ATT_UUID_16(0x290C), + /// Environmental Sensing Trigger Setting + ATT_DESC_ES_TRIGGER_SETTING = ATT_UUID_16(0x290D), + + + /*--------------- CHARACTERISTICS ---------------*/ + /// Device name + ATT_CHAR_DEVICE_NAME = ATT_UUID_16(0x2A00), + /// Appearance + ATT_CHAR_APPEARANCE = ATT_UUID_16(0x2A01), + /// Privacy flag + ATT_CHAR_PRIVACY_FLAG = ATT_UUID_16(0x2A02), + /// Reconnection address + ATT_CHAR_RECONNECTION_ADDR = ATT_UUID_16(0x2A03), + /// Peripheral preferred connection parameters + ATT_CHAR_PERIPH_PREF_CON_PARAM = ATT_UUID_16(0x2A04), + /// Service handles changed + ATT_CHAR_SERVICE_CHANGED = ATT_UUID_16(0x2A05), + /// Alert Level characteristic + ATT_CHAR_ALERT_LEVEL = ATT_UUID_16(0x2A06), + /// Tx Power Level + ATT_CHAR_TX_POWER_LEVEL = ATT_UUID_16(0x2A07), + /// Date Time + ATT_CHAR_DATE_TIME = ATT_UUID_16(0x2A08), + /// Day of Week + ATT_CHAR_DAY_WEEK = ATT_UUID_16(0x2A09), + /// Day Date Time + ATT_CHAR_DAY_DATE_TIME = ATT_UUID_16(0x2A0A), + /// Exact time 256 + ATT_CHAR_EXACT_TIME_256 = ATT_UUID_16(0x2A0C), + /// DST Offset + ATT_CHAR_DST_OFFSET = ATT_UUID_16(0x2A0D), + /// Time zone + ATT_CHAR_TIME_ZONE = ATT_UUID_16(0x2A0E), + /// Local time Information + ATT_CHAR_LOCAL_TIME_INFO = ATT_UUID_16(0x2A0F), + /// Time with DST + ATT_CHAR_TIME_WITH_DST = ATT_UUID_16(0x2A11), + /// Time Accuracy + ATT_CHAR_TIME_ACCURACY = ATT_UUID_16(0x2A12), + ///Time Source + ATT_CHAR_TIME_SOURCE = ATT_UUID_16(0x2A13), + /// Reference Time Information + ATT_CHAR_REFERENCE_TIME_INFO = ATT_UUID_16(0x2A14), + /// Time Update Control Point + ATT_CHAR_TIME_UPDATE_CNTL_POINT = ATT_UUID_16(0x2A16), + /// Time Update State + ATT_CHAR_TIME_UPDATE_STATE = ATT_UUID_16(0x2A17), + /// Glucose Measurement + ATT_CHAR_GLUCOSE_MEAS = ATT_UUID_16(0x2A18), + /// Battery Level + ATT_CHAR_BATTERY_LEVEL = ATT_UUID_16(0x2A19), + /// Temperature Measurement + ATT_CHAR_TEMPERATURE_MEAS = ATT_UUID_16(0x2A1C), + /// Temperature Type + ATT_CHAR_TEMPERATURE_TYPE = ATT_UUID_16(0x2A1D), + /// Intermediate Temperature + ATT_CHAR_INTERMED_TEMPERATURE = ATT_UUID_16(0x2A1E), + /// Measurement Interval + ATT_CHAR_MEAS_INTERVAL = ATT_UUID_16(0x2A21), + /// Boot Keyboard Input Report + ATT_CHAR_BOOT_KB_IN_REPORT = ATT_UUID_16(0x2A22), + /// System ID + ATT_CHAR_SYS_ID = ATT_UUID_16(0x2A23), + /// Model Number String + ATT_CHAR_MODEL_NB = ATT_UUID_16(0x2A24), + /// Serial Number String + ATT_CHAR_SERIAL_NB = ATT_UUID_16(0x2A25), + /// Firmware Revision String + ATT_CHAR_FW_REV = ATT_UUID_16(0x2A26), + /// Hardware revision String + ATT_CHAR_HW_REV = ATT_UUID_16(0x2A27), + /// Software Revision String + ATT_CHAR_SW_REV = ATT_UUID_16(0x2A28), + /// Manufacturer Name String + ATT_CHAR_MANUF_NAME = ATT_UUID_16(0x2A29), + /// IEEE Regulatory Certification Data List + ATT_CHAR_IEEE_CERTIF = ATT_UUID_16(0x2A2A), + /// CT Time + ATT_CHAR_CT_TIME = ATT_UUID_16(0x2A2B), + /// Magnetic Declination + ATT_CHAR_MAGN_DECLINE = ATT_UUID_16(0x2A2C), + /// Scan Refresh + ATT_CHAR_SCAN_REFRESH = ATT_UUID_16(0x2A31), + /// Boot Keyboard Output Report + ATT_CHAR_BOOT_KB_OUT_REPORT = ATT_UUID_16(0x2A32), + /// Boot Mouse Input Report + ATT_CHAR_BOOT_MOUSE_IN_REPORT = ATT_UUID_16(0x2A33), + /// Glucose Measurement Context + ATT_CHAR_GLUCOSE_MEAS_CTX = ATT_UUID_16(0x2A34), + /// Blood Pressure Measurement + ATT_CHAR_BLOOD_PRESSURE_MEAS = ATT_UUID_16(0x2A35), + /// Intermediate Cuff Pressure + ATT_CHAR_INTERMEDIATE_CUFF_PRESSURE = ATT_UUID_16(0x2A36), + /// Heart Rate Measurement + ATT_CHAR_HEART_RATE_MEAS = ATT_UUID_16(0x2A37), + /// Body Sensor Location + ATT_CHAR_BODY_SENSOR_LOCATION = ATT_UUID_16(0x2A38), + /// Heart Rate Control Point + ATT_CHAR_HEART_RATE_CNTL_POINT = ATT_UUID_16(0x2A39), + /// Alert Status + ATT_CHAR_ALERT_STATUS = ATT_UUID_16(0x2A3F), + /// Ringer Control Point + ATT_CHAR_RINGER_CNTL_POINT = ATT_UUID_16(0x2A40), + /// Ringer Setting + ATT_CHAR_RINGER_SETTING = ATT_UUID_16(0x2A41), + /// Alert Category ID Bit Mask + ATT_CHAR_ALERT_CAT_ID_BIT_MASK = ATT_UUID_16(0x2A42), + /// Alert Category ID + ATT_CHAR_ALERT_CAT_ID = ATT_UUID_16(0x2A43), + /// Alert Notification Control Point + ATT_CHAR_ALERT_NTF_CTNL_PT = ATT_UUID_16(0x2A44), + /// Unread Alert Status + ATT_CHAR_UNREAD_ALERT_STATUS = ATT_UUID_16(0x2A45), + /// New Alert + ATT_CHAR_NEW_ALERT = ATT_UUID_16(0x2A46), + /// Supported New Alert Category + ATT_CHAR_SUP_NEW_ALERT_CAT = ATT_UUID_16(0x2A47), + /// Supported Unread Alert Category + ATT_CHAR_SUP_UNREAD_ALERT_CAT = ATT_UUID_16(0x2A48), + /// Blood Pressure Feature + ATT_CHAR_BLOOD_PRESSURE_FEATURE = ATT_UUID_16(0x2A49), + /// HID Information + ATT_CHAR_HID_INFO = ATT_UUID_16(0x2A4A), + /// Report Map + ATT_CHAR_REPORT_MAP = ATT_UUID_16(0x2A4B), + /// HID Control Point + ATT_CHAR_HID_CTNL_PT = ATT_UUID_16(0x2A4C), + /// Report + ATT_CHAR_REPORT = ATT_UUID_16(0x2A4D), + /// Protocol Mode + ATT_CHAR_PROTOCOL_MODE = ATT_UUID_16(0x2A4E), + /// Scan Interval Window + ATT_CHAR_SCAN_INTV_WD = ATT_UUID_16(0x2A4F), + /// PnP ID + ATT_CHAR_PNP_ID = ATT_UUID_16(0x2A50), + /// Glucose Feature + ATT_CHAR_GLUCOSE_FEATURE = ATT_UUID_16(0x2A51), + /// Record access control point + ATT_CHAR_REC_ACCESS_CTRL_PT = ATT_UUID_16(0x2A52), + /// RSC Measurement + ATT_CHAR_RSC_MEAS = ATT_UUID_16(0x2A53), + /// RSC Feature + ATT_CHAR_RSC_FEAT = ATT_UUID_16(0x2A54), + /// SC Control Point + ATT_CHAR_SC_CNTL_PT = ATT_UUID_16(0x2A55), + /// CSC Measurement + ATT_CHAR_CSC_MEAS = ATT_UUID_16(0x2A5B), + /// CSC Feature + ATT_CHAR_CSC_FEAT = ATT_UUID_16(0x2A5C), + /// Sensor Location + ATT_CHAR_SENSOR_LOC = ATT_UUID_16(0x2A5D), + /// PLX Spot-Check Measurement + ATT_CHAR_PLX_SPOT_CHECK_MEASUREMENT_LOC = ATT_UUID_16(0x2A5E), + /// PLX Continuous Measurement + ATT_CHAR_PLX_CONTINUOUS_MEASUREMENT_LOC = ATT_UUID_16(0x2A5F), + /// PLX Features + ATT_CHAR_PLX_FEATURES_LOC = ATT_UUID_16(0x2A60), + /// CP Measurement + ATT_CHAR_CP_MEAS = ATT_UUID_16(0x2A63), + /// CP Vector + ATT_CHAR_CP_VECTOR = ATT_UUID_16(0x2A64), + /// CP Feature + ATT_CHAR_CP_FEAT = ATT_UUID_16(0x2A65), + /// CP Control Point + ATT_CHAR_CP_CNTL_PT = ATT_UUID_16(0x2A66), + /// Location and Speed + ATT_CHAR_LOC_SPEED = ATT_UUID_16(0x2A67), + /// Navigation + ATT_CHAR_NAVIGATION = ATT_UUID_16(0x2A68), + /// Position Quality + ATT_CHAR_POS_QUALITY = ATT_UUID_16(0x2A69), + /// LN Feature + ATT_CHAR_LN_FEAT = ATT_UUID_16(0x2A6A), + /// LN Control Point + ATT_CHAR_LN_CNTL_PT = ATT_UUID_16(0x2A6B), + /// Elevation + ATT_CHAR_ELEVATION = ATT_UUID_16(0x2A6C), + /// Pressure + ATT_CHAR_PRESSURE = ATT_UUID_16(0x2A6D), + /// Temperature + ATT_CHAR_TEMPERATURE = ATT_UUID_16(0x2A6E), + /// Humidity + ATT_CHAR_HUMIDITY = ATT_UUID_16(0x2A6F), + /// True Wind Speed + ATT_CHAR_TRUE_WIND_SPEED = ATT_UUID_16(0x2A70), + /// True Wind Direction + ATT_CHAR_TRUE_WIND_DIR = ATT_UUID_16(0x2A71), + /// Apparent Wind Speed + ATT_CHAR_APRNT_WIND_SPEED = ATT_UUID_16(0x2A72), + /// Apparent Wind Direction + ATT_CHAR_APRNT_WIND_DIRECTION = ATT_UUID_16(0x2A73), + /// Gust Factor + ATT_CHAR_GUST_FACTOR = ATT_UUID_16(0x2A74), + /// Pollen Concentration + ATT_CHAR_POLLEN_CONC = ATT_UUID_16(0x2A75), + /// UV Index + ATT_CHAR_UV_INDEX = ATT_UUID_16(0x2A76), + /// Irradiance + ATT_CHAR_IRRADIANCE = ATT_UUID_16(0x2A77), + /// Rainfall + ATT_CHAR_RAINFALL = ATT_UUID_16(0x2A78), + /// Wind Chill + ATT_CHAR_WIND_CHILL = ATT_UUID_16(0x2A79), + /// Heat Index + ATT_CHAR_HEAT_INDEX = ATT_UUID_16(0x2A7A), + /// Dew Point + ATT_CHAR_DEW_POINT = ATT_UUID_16(0x2A7B), + /// Descriptor Value Changed + ATT_CHAR_DESCRIPTOR_VALUE_CHANGED = ATT_UUID_16(0x2A7D), + /// Aerobic Heart Rate Lower Limit + ATT_CHAR_AEROBIC_HEART_RATE_LOWER_LIMIT = ATT_UUID_16(0x2A7E), + /// Aerobic Threshhold + ATT_CHAR_AEROBIC_THRESHHOLD = ATT_UUID_16(0x2A7F), + /// Age + ATT_CHAR_AGE = ATT_UUID_16(0x2A80), + /// Anaerobic Heart Rate Lower Limit + ATT_CHAR_ANAEROBIC_HEART_RATE_LOWER_LIMIT = ATT_UUID_16(0x2A81), + /// Anaerobic Heart Rate Upper Limit + ATT_CHAR_ANAEROBIC_HEART_RATE_UPPER_LIMIT = ATT_UUID_16(0x2A82), + /// Anaerobic Threshhold + ATT_CHAR_ANAEROBIC_THRESHHOLD = ATT_UUID_16(0x2A83), + /// Aerobic Heart Rate Upper Limit + ATT_CHAR_AEROBIC_HEART_RATE_UPPER_LIMIT = ATT_UUID_16(0x2A84), + /// Date Of Birth + ATT_CHAR_DATE_OF_BIRTH = ATT_UUID_16(0x2A85), + /// Date Of Threshold Assessment + ATT_CHAR_DATE_OF_THRESHOLD_ASSESSMENT = ATT_UUID_16(0x2A86), + /// Email Address + ATT_CHAR_EMAIL_ADDRESS = ATT_UUID_16(0x2A87), + /// Fat Burn Heart Rate Lower Limit + ATT_CHAR_FAT_BURN_HEART_RATE_LOWER_LIMIT = ATT_UUID_16(0x2A88), + /// Fat Burn Heart Rate Upper Limit + ATT_CHAR_FAT_BURN_HEART_RATE_UPPER_LIMIT = ATT_UUID_16(0x2A89), + /// First Name + ATT_CHAR_FIRST_NAME = ATT_UUID_16(0x2A8A), + /// Five Zone Heart Rate Limits + ATT_CHAR_FIVE_ZONE_HEART_RATE_LIMITS = ATT_UUID_16(0x2A8B), + /// Gender + ATT_CHAR_GENDER = ATT_UUID_16(0x2A8C), + /// Max Heart Rate + ATT_CHAR_MAX_HEART_RATE = ATT_UUID_16(0x2A8D), + /// Height + ATT_CHAR_HEIGHT = ATT_UUID_16(0x2A8E), + /// Hip Circumference + ATT_CHAR_HIP_CIRCUMFERENCE = ATT_UUID_16(0x2A8F), + /// Last Name + ATT_CHAR_LAST_NAME = ATT_UUID_16(0x2A90), + /// Maximum Recommended Heart Rate + ATT_CHAR_MAXIMUM_RECOMMENDED_HEART_RATE = ATT_UUID_16(0x2A91), + /// Resting Heart Rate + ATT_CHAR_RESTING_HEART_RATE = ATT_UUID_16(0x2A92), + /// Sport Type For Aerobic And Anaerobic Thresholds + ATT_CHAR_SPORT_TYPE_FOR_AEROBIC_AND_ANAEROBIC_THRESHOLDS = ATT_UUID_16(0x2A93), + /// Three Zone Heart Rate Limits + ATT_CHAR_THREE_ZONE_HEART_RATE_LIMITS = ATT_UUID_16(0x2A94), + /// Two Zone Heart Rate Limit + ATT_CHAR_TWO_ZONE_HEART_RATE_LIMIT = ATT_UUID_16(0x2A95), + /// Vo2 Max + ATT_CHAR_VO2_MAX = ATT_UUID_16(0x2A96), + /// Waist Circumference + ATT_CHAR_WAIST_CIRCUMFERENCE = ATT_UUID_16(0x2A97), + /// Weight + ATT_CHAR_WEIGHT = ATT_UUID_16(0x2A98), + /// Database Change Increment + ATT_CHAR_DATABASE_CHANGE_INCREMENT = ATT_UUID_16(0x2A99), + /// User Index + ATT_CHAR_USER_INDEX = ATT_UUID_16(0x2A9A), + /// Body Composition Feature + ATT_CHAR_BODY_COMPOSITION_FEATURE = ATT_UUID_16(0x2A9B), + /// Body Composition Measurement + ATT_CHAR_BODY_COMPOSITION_MEASUREMENT = ATT_UUID_16(0x2A9C), + /// Weight Measurement + ATT_CHAR_WEIGHT_MEASUREMENT = ATT_UUID_16(0x2A9D), + /// Weight Scale Feature + ATT_CHAR_WEIGHT_SCALE_FEATURE = ATT_UUID_16(0x2A9E), + /// User Control Point + ATT_CHAR_USER_CONTROL_POINT = ATT_UUID_16(0x2A9F), + /// Flux Density - 2D + ATT_CHAR_MAGN_FLUX_2D = ATT_UUID_16(0x2AA0), + /// Magnetic Flux Density - 3D + ATT_CHAR_MAGN_FLUX_3D = ATT_UUID_16(0x2AA1), + /// Language string + ATT_CHAR_LANGUAGE = ATT_UUID_16(0x2AA2), + /// Barometric Pressure Trend + ATT_CHAR_BAR_PRES_TREND = ATT_UUID_16(0x2AA3), + /// Central Address Resolution Support + ATT_CHAR_CTL_ADDR_RESOL_SUPP = ATT_UUID_16(0x2AA6), + /// CGM Measurement + ATT_CHAR_CGM_MEASUREMENT = ATT_UUID_16(0x2AA7), + /// CGM Features + ATT_CHAR_CGM_FEATURES = ATT_UUID_16(0x2AA8), + /// CGM Status + ATT_CHAR_CGM_STATUS = ATT_UUID_16(0x2AA9), + /// CGM Session Start + ATT_CHAR_CGM_SESSION_START = ATT_UUID_16(0x2AAA), + /// CGM Session Run + ATT_CHAR_CGM_SESSION_RUN = ATT_UUID_16(0x2AAB), + /// CGM Specific Ops Control Point + ATT_CHAR_CGM_SPECIFIC_OPS_CTRL_PT = ATT_UUID_16(0x2AAC), + /// Resolvable Private Address only + ATT_CHAR_RSLV_PRIV_ADDR_ONLY = ATT_UUID_16(0x2AC9), + /// Mesh Provisioning Data In + ATT_CHAR_MESH_PROV_DATA_IN = ATT_UUID_16(0x2ADB), + /// Mesh Provisioning Data Out + ATT_CHAR_MESH_PROV_DATA_OUT = ATT_UUID_16(0x2ADC), + /// Mesh Proxy Data In + ATT_CHAR_MESH_PROXY_DATA_IN = ATT_UUID_16(0x2ADD), + /// Mesh Proxy Data Out + ATT_CHAR_MESH_PROXY_DATA_OUT = ATT_UUID_16(0x2ADE), +}; + +/// Format for Characteristic Presentation +enum +{ + /// unsigned 1-bit: true or false + ATT_FORMAT_BOOL = 0x01, + /// unsigned 2-bit integer + ATT_FORMAT_2BIT, + /// unsigned 4-bit integer + ATT_FORMAT_NIBBLE, + /// unsigned 8-bit integer + ATT_FORMAT_UINT8, + /// unsigned 12-bit integer + ATT_FORMAT_UINT12, + /// unsigned 16-bit integer + ATT_FORMAT_UINT16, + /// unsigned 24-bit integer + ATT_FORMAT_UINT24, + /// unsigned 32-bit integer + ATT_FORMAT_UINT32, + /// unsigned 48-bit integer + ATT_FORMAT_UINT48, + /// unsigned 64-bit integer + ATT_FORMAT_UINT64, + /// unsigned 128-bit integer + ATT_FORMAT_UINT128, + /// signed 8-bit integer + ATT_FORMAT_SINT8, + /// signed 12-bit integer + ATT_FORMAT_SINT12, + /// signed 16-bit integer + ATT_FORMAT_SINT16, + /// signed 24-bit integer + ATT_FORMAT_SINT24, + /// signed 32-bit integer + ATT_FORMAT_SINT32, + /// signed 48-bit integer + ATT_FORMAT_SINT48, + /// signed 64-bit integer + ATT_FORMAT_SINT64, + /// signed 128-bit integer + ATT_FORMAT_SINT128, + /// IEEE-754 32-bit floating point + ATT_FORMAT_FLOAT32, + /// IEEE-754 64-bit floating point + ATT_FORMAT_FLOAT64, + /// IEEE-11073 16-bit SFLOAT + ATT_FORMAT_SFLOAT, + /// IEEE-11073 32-bit FLOAT + ATT_FORMAT_FLOAT, + /// IEEE-20601 format + ATT_FORMAT_DUINT16, + /// UTF-8 string + ATT_FORMAT_UTF8S, + /// UTF-16 string + ATT_FORMAT_UTF16S, + /// Opaque structure + ATT_FORMAT_STRUCT, + /// Last format + ATT_FORMAT_LAST +}; + + +/// Client Characteristic Configuration Codes +enum att_ccc_val +{ + /// Stop notification/indication + ATT_CCC_STOP_NTFIND = 0x0000, + /// Start notification + ATT_CCC_START_NTF, + /// Start indication + ATT_CCC_START_IND +}; + +/* + * Type Definition + **************************************************************************************** + */ + +/// Attribute length type +typedef uint16_t att_size_t; + + +/// UUID - 128-bit type +struct att_uuid_128 +{ + /// 128-bit UUID + uint8_t uuid[ATT_UUID_128_LEN]; +}; + +/// UUID - 32-bit type +struct att_uuid_32 +{ + /// 32-bit UUID + uint8_t uuid[ATT_UUID_32_LEN]; +}; + + + +/// Characteristic Value Descriptor +struct att_char_desc +{ + /// properties + uint8_t prop; + /// attribute handle + uint8_t attr_hdl[ATT_HANDLE_LEN]; + /// attribute type + uint8_t attr_type[ATT_UUID_16_LEN]; +}; + +/// Characteristic Value Descriptor +struct att_char128_desc +{ + /// properties + uint8_t prop; + /// attribute handle + uint8_t attr_hdl[ATT_HANDLE_LEN]; + /// attribute type + uint8_t attr_type[ATT_UUID_128_LEN]; +}; + +/// Service Value Descriptor - 16-bit +typedef uint16_t att_svc_desc_t; + +/// include service entry element +struct att_incl_desc +{ + /// start handle value of included service + uint16_t start_hdl; + /// end handle value of included service + uint16_t end_hdl; + /// attribute value UUID + uint16_t uuid; +}; + +/// include service entry element +struct att_incl128_desc +{ + /// start handle value of included service + uint16_t start_hdl; + /// end handle value of included service + uint16_t end_hdl; +}; + + +// -------------------------- PDU HANDLER Definition -------------------------- + +/// used to know if PDU handler has been found +#define ATT_PDU_HANDLER_NOT_FOUND (0xff) + +/// Format of a pdu handler function +typedef int (*att_func_t)(uint8_t conidx, void *pdu); + +/// Element of a pdu handler table. +struct att_pdu_handler +{ + /// PDU identifier of the message + uint8_t pdu_id; + /// Pointer to the handler function for the pdu above. + att_func_t handler; +}; + + +// --------------------------- Database permissions ----------------------------- + +/// Macro used to retrieve access permission rights +#define PERM_GET(perm, access)\ + (((perm) & (PERM_MASK_ ## access)) >> (PERM_POS_ ## access)) + +/// Macro used to set a permission value +#define PERM_SET(perm, access, value)\ + perm = ((perm & ~(PERM_MASK_ ## access)) | ((value << (PERM_POS_ ## access)) & (PERM_MASK_ ## access))) + +/// Macro used to retrieve permission value from access and rights on attribute. +#define PERM(access, right) \ + (((PERM_RIGHT_ ## right) << (PERM_POS_ ## access)) & (PERM_MASK_ ## access)) + +/// Macro used know if permission is set or not. +#define PERM_IS_SET(perm, access, right) \ + (((perm) & (((PERM_RIGHT_ ## right) << (PERM_POS_ ## access))) \ + & (PERM_MASK_ ## access)) == PERM(access, right)) + +/// Macro used to create permission value +#define PERM_VAL(access, perm) \ + ((((perm) << (PERM_POS_ ## access))) & (PERM_MASK_ ## access)) + + +/// Retrieve attribute security level from attribute right and service right +#define ATT_GET_SEC_LVL(att_right, svc_right) \ + common_max(((att_right) & PERM_RIGHT_AUTH), ((svc_right) & PERM_RIGHT_AUTH)); + +/// Retrieve UUID LEN from UUID Length Permission +#define ATT_UUID_LEN(uuid_len_perm) ((uuid_len_perm == 0) ? ATT_UUID_16_LEN : \ + ((uuid_len_perm == 1) ? ATT_UUID_32_LEN : \ + ((uuid_len_perm == 2) ? ATT_UUID_128_LEN : 0))) + +/// Initialization of attribute element +#define ATT_ELEMT_INIT {{NULL}, false} + +/** + * 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + * +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + * |EXT | WS | I | N | WR | WC | RD | B | NP | IP | WP | RP | + * +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + * + * Bit [0-1] : Read Permission (0 = NO_AUTH, 1 = UNAUTH, 2 = AUTH, 3 = SEC_CON) + * Bit [2-3] : Write Permission (0 = NO_AUTH, 1 = UNAUTH, 2 = AUTH, 3 = SEC_CON) + * Bit [4-5] : Indication Permission (0 = NO_AUTH, 1 = UNAUTH, 2 = AUTH, 3 = SEC_CON) + * Bit [6-7] : Notification Permission (0 = NO_AUTH, 1 = UNAUTH, 2 = AUTH, 3 = SEC_CON) + * + * Bit [8] : Extended properties present (only relevant for a characteristic value) + * Bit [9] : Broadcast permission (only relevant for a characteristic value) + * Bit [10] : Write Command accepted + * Bit [11] : Write Signed accepted + * Bit [12] : Write Request accepted + * Bit [13] : Encryption key Size must be 16 bytes + */ +enum attm_perm_mask +{ + /// retrieve all permission info + PERM_MASK_ALL = 0x0000, + /// Read Permission Mask + PERM_MASK_RP = 0x0003, + PERM_POS_RP = 0, + /// Write Permission Mask + PERM_MASK_WP = 0x000C, + PERM_POS_WP = 2, + /// Indication Access Mask + PERM_MASK_IP = 0x0030, + PERM_POS_IP = 4, + /// Notification Access Mask + PERM_MASK_NP = 0x00C0, + PERM_POS_NP = 6, + /// Broadcast descriptor present + PERM_MASK_BROADCAST = 0x0100, + PERM_POS_BROADCAST = 8, + /// Read Access Mask + PERM_MASK_RD = 0x0200, + PERM_POS_RD = 9, + /// Write Command Enabled attribute Mask + PERM_MASK_WRITE_COMMAND = 0x0400, + PERM_POS_WRITE_COMMAND = 10, + /// Write Request Enabled attribute Mask + PERM_MASK_WRITE_REQ = 0x0800, + PERM_POS_WRITE_REQ = 11, + /// Notification Access Mask + PERM_MASK_NTF = 0x1000, + PERM_POS_NTF = 12, + /// Indication Access Mask + PERM_MASK_IND = 0x2000, + PERM_POS_IND = 13, + /// Write Signed Enabled attribute Mask + PERM_MASK_WRITE_SIGNED = 0x4000, + PERM_POS_WRITE_SIGNED = 14, + /// Extended properties descriptor present + PERM_MASK_EXT = 0x8000, + PERM_POS_EXT = 15, + + /// Properties + PERM_MASK_PROP = 0xFF00, + PERM_POS_PROP = 8, +}; + +/** + * Value permission bit field + * + * 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + * +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + * | RI |UUID_LEN |EKS | MAX_LEN (RI = 1) / Value Offset (RI = 0) | + * +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + * + * Bit [0-11] : Maximum Attribute Length or Value Offset pointer + * Bit [12] : Encryption key Size must be 16 bytes + * Bit [14-13]: UUID Length (0 = 16 bits, 1 = 32 bits, 2 = 128 bits, 3 = RFU) + * Bit [15] : Trigger Read Indication (0 = Value present in Database, 1 = Value not present in Database) + */ +enum attm_value_perm_mask +{ + /// Maximum Attribute Length + PERM_MASK_MAX_LEN = 0x0FFF, + PERM_POS_MAX_LEN = 0, + /// Attribute value Offset + PERM_MASK_VAL_OFFSET = 0x0FFF, + PERM_POS_VAL_OFFSET = 0, + /// Check Encryption key size Mask + PERM_MASK_EKS = 0x1000, + PERM_POS_EKS = 12, + /// UUID Length + PERM_MASK_UUID_LEN = 0x6000, + PERM_POS_UUID_LEN = 13, + /// Read trigger Indication + PERM_MASK_RI = 0x8000, + PERM_POS_RI = 15, +}; + + +/** + * Service permissions + * + * 7 6 5 4 3 2 1 0 + * +----+----+----+----+----+----+----+----+ + * |SEC |UUID_LEN |DIS | AUTH |EKS | MI | + * +----+----+----+----+----+----+----+----+ + * + * Bit [0] : Task that manage service is multi-instantiated (Connection index is conveyed) + * Bit [1] : Encryption key Size must be 16 bytes + * Bit [2-3]: Service Permission (0 = NO_AUTH, 1 = UNAUTH, 2 = AUTH, 3 = Secure Connect) + * Bit [4] : Disable the service + * Bit [5-6]: UUID Length (0 = 16 bits, 1 = 32 bits, 2 = 128 bits, 3 = RFU) + * Bit [7] : Secondary Service (0 = Primary Service, 1 = Secondary Service) + */ +enum attm_svc_perm_mask +{ + /// Task that manage service is multi-instantiated + PERM_MASK_SVC_MI = 0x01, + PERM_POS_SVC_MI = 0, + /// Check Encryption key size for service Access + PERM_MASK_SVC_EKS = 0x02, + PERM_POS_SVC_EKS = 1, + /// Service Permission authentication + PERM_MASK_SVC_AUTH = 0x0C, + PERM_POS_SVC_AUTH = 2, + /// Disable the service + PERM_MASK_SVC_DIS = 0x10, + PERM_POS_SVC_DIS = 4, + /// Service UUID Length + PERM_MASK_SVC_UUID_LEN = 0x60, + PERM_POS_SVC_UUID_LEN = 5, + /// Service type Secondary + PERM_MASK_SVC_SECONDARY = 0x80, + PERM_POS_SVC_SECONDARY = 7, +}; + +/// Attribute & Service access mode +enum +{ + /// Disable access + PERM_RIGHT_DISABLE = 0, + /// Enable access + PERM_RIGHT_ENABLE = 1, +}; + +/// Attribute & Service access rights +enum +{ + /// No Authentication + PERM_RIGHT_NO_AUTH = 0, + /// Access Requires Unauthenticated link + PERM_RIGHT_UNAUTH = 1, + /// Access Requires Authenticated link + PERM_RIGHT_AUTH = 2, + /// Access Requires Secure Connection link + PERM_RIGHT_SEC_CON = 3, +}; + +/// Attribute & Service UUID Length +enum +{ + /// 16 bits UUID + PERM_UUID_16 = 0, + PERM_RIGHT_UUID_16 = 0, + /// 32 bits UUID + PERM_UUID_32 = 1, + PERM_RIGHT_UUID_32 = 1, + /// 128 bits UUID + PERM_UUID_128 = 2, + PERM_RIGHT_UUID_128 = 2, + /// Invalid + PERM_UUID_RFU = 3, +}; + +/// execute flags +enum +{ + /// Cancel All the Reliable Writes + ATT_CANCEL_ALL_PREPARED_WRITES = 0x00, + /// Write All the Reliable Writes + ATT_EXECUTE_ALL_PREPARED_WRITES +}; + + + +/// @} ATT +#endif // ATT_H_ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/api/gap.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/api/gap.h new file mode 100755 index 0000000..370a988 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/api/gap.h @@ -0,0 +1,667 @@ +/** + **************************************************************************************** + * + * @file gap.h + * + * @brief Header file - GAP. + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ +#ifndef GAP_H_ +#define GAP_H_ +/** + **************************************************************************************** + * @addtogroup HOST + * @ingroup ROOT + * @brief Bluetooth Low Energy Host + * + * The HOST layer of the stack contains the higher layer protocols (@ref ATT "ATT", + * @ref SMP "SMP") and transport module (@ref L2C "L2C"). It also includes the Generic + * Access Profile (@ref GAP "GAP"), used for scanning/connection operations. + **************************************************************************************** + */ +/** + **************************************************************************************** + * @addtogroup GAP Generic Access Profile + * @ingroup HOST + * @brief Generic Access Profile. + * + * The GAP module is responsible for providing an API to the application in order to + * configure the device in the desired mode (discoverable, connectable, etc.) and perform + * required actions (scanning, connection, pairing, etc.). To achieve this, the GAP + * interfaces with both the @ref SMP "SMP", @ref L2C "L2C" and the @ref CONTROLLER "CONTROLLER" + * + * @{ + **************************************************************************************** + */ + +#include +#include "ble_compiler.h" + +/* + * DEFINES + **************************************************************************************** + */ + +/// BD address length +#define GAP_BD_ADDR_LEN (6) +/// LE Channel map length +#define GAP_LE_CHNL_MAP_LEN (0x05) +/// LE Feature Flags Length +#define GAP_LE_FEATS_LEN (0x08) +/// ADV Data and Scan Response length +#define GAP_ADV_DATA_LEN (0x1F) +#define GAP_SCAN_RSP_DATA_LEN (0x1F) +/// Random number length +#define GAP_RAND_NB_LEN (0x08) +/// Key length +#define GAP_KEY_LEN (16) +/// P256 Key Len +#define GAP_P256_KEY_LEN (0x20) + + +///***** AD Type Flag - Bit set *******/ +/// Limited discovery flag - AD Flag +#define GAP_LE_LIM_DISCOVERABLE_FLG 0x01 +/// General discovery flag - AD Flag +#define GAP_LE_GEN_DISCOVERABLE_FLG 0x02 +/// Legacy BT not supported - AD Flag +#define GAP_BR_EDR_NOT_SUPPORTED 0x04 +/// Dual mode for controller supported (BR/EDR/LE) - AD Flag +#define GAP_SIMUL_BR_EDR_LE_CONTROLLER 0x08 +/// Dual mode for host supported (BR/EDR/LE) - AD Flag +#define GAP_SIMUL_BR_EDR_LE_HOST 0x10 + +/*********** GAP Miscellaneous Defines *************/ +/// Invalid connection index +#define GAP_INVALID_CONIDX 0xFF + +/// Invalid connection handle +#define GAP_INVALID_CONHDL 0xFFFF + +/// Connection interval min (N*1.250ms) +#define GAP_CNX_INTERVAL_MIN 6 //(0x06) +/// Connection interval Max (N*1.250ms) +#define GAP_CNX_INTERVAL_MAX 3200 //(0xC80) +/// Connection latency min (N*cnx evt) +#define GAP_CNX_LATENCY_MIN 0 //(0x00) +/// Connection latency Max (N*cnx evt +#define GAP_CNX_LATENCY_MAX 499 //(0x1F3) +/// Supervision TO min (N*10ms) +#define GAP_CNX_SUP_TO_MIN 10 //(0x0A) +/// Supervision TO Max (N*10ms) +#define GAP_CNX_SUP_TO_MAX 3200 //(0xC80) + + + +/// Length of resolvable random address prand part +#define GAP_ADDR_PRAND_LEN (3) +/// Length of resolvable random address hash part +#define GAP_ADDR_HASH_LEN (3) + + +/* + * DEFINES - Optional for BLE application usage + **************************************************************************************** + */ + +/// Central idle timer +/// TGAP(conn_pause_central) +/// recommended value: 1 s: (100 for ke timer) +#define GAP_TMR_CONN_PAUSE_CT 0x0064 + +/// Minimum time upon connection establishment before the peripheral +/// starts a connection update procedure: TGAP(conn_pause_peripheral) +/// recommended value: 5 s: (500 for ke timer) +#define GAP_TMR_CONN_PAUSE_PH 0x01F4 + +/// Minimum time to perform scanning when user initiated +/// TGAP(scan_fast_period) +/// recommended value: 30.72 s: (3072 for ke timer) +#define GAP_TMR_SCAN_FAST_PERIOD 0x0C00 + +/// Minimum time to perform advertising when user initiated +/// TGAP(adv_fast_period) +/// recommended value: 30 s: (3000 for ke timer) +#define GAP_TMR_ADV_FAST_PERIOD 0x0BB8 + +/// Scan interval used during Link Layer Scanning State when +/// performing the Limited Discovery procedure +/// TGAP(lim_disc_scan_int) +/// recommended value: 11.25ms; (18 decimal) +#define GAP_LIM_DISC_SCAN_INT 0x0012 + +/// Scan interval in any discovery or connection establishment +/// procedure when user initiated: TGAP(scan_fast_interval) +/// recommended value: 30 to 60 ms; N * 0.625 +#define GAP_SCAN_FAST_INTV 0x0030 + +/// Scan window in any discovery or connection establishment +/// procedure when user initiated: TGAP(scan_fast_window) +/// recommended value: 30 ms; N * 0.625 +#define GAP_SCAN_FAST_WIND 0x0030 + +/// Scan interval in any discovery or connection establishment +/// procedure when background scanning: TGAP(scan_slow_interval1) +/// recommended value: 1.28 s : 0x00CD (205); N * 0.625 +#define GAP_SCAN_SLOW_INTV1 0x00CD + +/// Scan interval in any discovery or connection establishment +/// procedure when background scanning: TGAP(scan_slow_interval2) +/// recommended value: 2.56 s : 0x019A (410); N * 0.625 +#define GAP_SCAN_SLOW_INTV2 0x019A + +/// Scan window in any discovery or connection establishment +/// procedure when background scanning: TGAP(scan_slow_window1) +/// recommended value: 11.25 ms : 0x0012 (18); N * 0.625 +#define GAP_SCAN_SLOW_WIND1 0x0012 + +/// Scan window in any discovery or connection establishment +/// procedure when background scanning: TGAP(scan_slow_window2) +/// recommended value: 22.5 ms : 0x0024 (36); N * 0.625 +#define GAP_SCAN_SLOW_WIND2 0x0024 + +/// Minimum to maximum advertisement interval in any discoverable +/// or connectable mode when user initiated: TGAP(adv_fast_interval1) +/// recommended value: 30 to 60 ms; N * 0.625 +#define GAP_ADV_FAST_INTV1 0x0030 + +/// Minimum to maximum advertisement interval in any discoverable +/// or connectable mode when user initiated: TGAP(adv_fast_interval2) +/// recommended value: 100 to 150 ms; N * 0.625 +#define GAP_ADV_FAST_INTV2 0x0064 + +/// Minimum to maximum advertisement interval in any discoverable or +/// connectable mode when background advertising: TGAP(adv_slow_interval) +/// recommended value: 1 to 1.2 s : 0x00B0 (176); N * 0.625 +#define GAP_ADV_SLOW_INTV 0x00B0 + +/// Minimum to maximum connection interval upon any connection +/// establishment: TGAP(initial_conn_interval) +/// recommended value: 30 to 50 ms ; N * 1.25 ms +#define GAP_INIT_CONN_MIN_INTV 0x0018 +#define GAP_INIT_CONN_MAX_INTV 0x0028 + +/// RW Defines +#define GAP_INQ_SCAN_INTV 0x0012 +#define GAP_INQ_SCAN_WIND 0x0012 + +/// Connection supervision timeout +/// recommended value: 20s +#define GAP_CONN_SUPERV_TIMEOUT 0x07D0 + +/// Minimum connection event +/// default value: 0x0000 +#define GAP_CONN_MIN_CE 0x0000 + +/// Maximum connection event +/// default value: 0xFFFF +#define GAP_CONN_MAX_CE 0xFFFF + +/// Connection latency +/// default value: 0x0000 +#define GAP_CONN_LATENCY 0x0000 + +/// GAP Device name Characteristic +/// Default device name +#define GAP_DEV_NAME "RIVIERAWAVES-BLE" + +/// GAP Appearance or Icon Characteristic - 2 octets +/// Current appearance value is 0x0000 (unknown appearance) +/// Description: +/// http://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.gap.appearance.xml +#define GAP_APPEARANCE 0x0000 + +///GAP Peripheral Preferred Connection Parameter - 8 octets +#define GAP_PPCP_CONN_INTV_MAX 0x0064 +#define GAP_PPCP_CONN_INTV_MIN 0x00C8 +#define GAP_PPCP_SLAVE_LATENCY 0x0000 +#define GAP_PPCP_STO_MULT 0x07D0 + + +/* + * Enumerations + **************************************************************************************** + */ +/// GAP Advertising Flags +enum gap_ad_type +{ + /// Flag + GAP_AD_TYPE_FLAGS = 0x01, + /// Use of more than 16 bits UUID + GAP_AD_TYPE_MORE_16_BIT_UUID = 0x02, + /// Complete list of 16 bit UUID + GAP_AD_TYPE_COMPLETE_LIST_16_BIT_UUID = 0x03, + /// Use of more than 32 bit UUD + GAP_AD_TYPE_MORE_32_BIT_UUID = 0x04, + /// Complete list of 32 bit UUID + GAP_AD_TYPE_COMPLETE_LIST_32_BIT_UUID = 0x05, + /// Use of more than 128 bit UUID + GAP_AD_TYPE_MORE_128_BIT_UUID = 0x06, + /// Complete list of 128 bit UUID + GAP_AD_TYPE_COMPLETE_LIST_128_BIT_UUID = 0x07, + /// Shortened device name + GAP_AD_TYPE_SHORTENED_NAME = 0x08, + /// Complete device name + GAP_AD_TYPE_COMPLETE_NAME = 0x09, + /// Transmit power + GAP_AD_TYPE_TRANSMIT_POWER = 0x0A, + /// Class of device + GAP_AD_TYPE_CLASS_OF_DEVICE = 0x0D, + /// Simple Pairing Hash C + GAP_AD_TYPE_SP_HASH_C = 0x0E, + /// Simple Pairing Randomizer + GAP_AD_TYPE_SP_RANDOMIZER_R = 0x0F, + /// Temporary key value + GAP_AD_TYPE_TK_VALUE = 0x10, + /// Out of Band Flag + GAP_AD_TYPE_OOB_FLAGS = 0x11, + /// Slave connection interval range + GAP_AD_TYPE_SLAVE_CONN_INT_RANGE = 0x12, + /// Require 16 bit service UUID + GAP_AD_TYPE_RQRD_16_BIT_SVC_UUID = 0x14, + /// Require 32 bit service UUID + GAP_AD_TYPE_RQRD_32_BIT_SVC_UUID = 0x1F, + /// Require 128 bit service UUID + GAP_AD_TYPE_RQRD_128_BIT_SVC_UUID = 0x15, + /// Service data 16-bit UUID + GAP_AD_TYPE_SERVICE_16_BIT_DATA = 0x16, + /// Service data 32-bit UUID + GAP_AD_TYPE_SERVICE_32_BIT_DATA = 0x20, + /// Service data 128-bit UUID + GAP_AD_TYPE_SERVICE_128_BIT_DATA = 0x21, + /// Public Target Address + GAP_AD_TYPE_PUB_TGT_ADDR = 0x17, + /// Random Target Address + GAP_AD_TYPE_RAND_TGT_ADDR = 0x18, + /// Appearance + GAP_AD_TYPE_APPEARANCE = 0x19, + /// Advertising Interval + GAP_AD_TYPE_ADV_INTV = 0x1A, + /// LE Bluetooth Device Address + GAP_AD_TYPE_LE_BT_ADDR = 0x1B, + /// LE Role + GAP_AD_TYPE_LE_ROLE = 0x1C, + /// Simple Pairing Hash C-256 + GAP_AD_TYPE_SPAIR_HASH = 0x1D, + /// Simple Pairing Randomizer R-256 + GAP_AD_TYPE_SPAIR_RAND = 0x1E, + /// 3D Information Data + GAP_AD_TYPE_3D_INFO = 0x3D, + + /// Manufacturer specific data + GAP_AD_TYPE_MANU_SPECIFIC_DATA = 0xFF, +}; + + +/// Random Address type +enum gap_rnd_addr_type +{ + /// Static random address - 11 (MSB->LSB) + GAP_STATIC_ADDR = 0xC0, + /// Private non resolvable address - 01 (MSB->LSB) + GAP_NON_RSLV_ADDR = 0x00, + /// Private resolvable address - 01 (MSB->LSB) + GAP_RSLV_ADDR = 0x40, +}; + +/// Boolean value set +enum +{ + /// Disable + GAP_DISABLE = 0x00, + /// Enable + GAP_ENABLE +}; + + +/// GAP Attribute database handles +/// Generic Access Profile Service +enum +{ + GAP_IDX_PRIM_SVC, + GAP_IDX_CHAR_DEVNAME, + GAP_IDX_DEVNAME, + GAP_IDX_CHAR_ICON, + GAP_IDX_ICON, + GAP_IDX_CHAR_SLAVE_PREF_PARAM, + GAP_IDX_SLAVE_PREF_PARAM, + GAP_IDX_CHAR_CNT_ADDR_RESOL, + GAP_IDX_CNT_ADDR_RESOL, + GAP_IDX_NUMBER +}; + + + +/****************** GAP Role **********************/ +enum gap_role +{ + /// No role set yet + GAP_ROLE_NONE = 0x00, + + /// Observer role + GAP_ROLE_OBSERVER = 0x01, + + /// Broadcaster role + GAP_ROLE_BROADCASTER = 0x02, + + /// Master/Central role + GAP_ROLE_CENTRAL = (0x04 | GAP_ROLE_OBSERVER), + + /// Peripheral/Slave role + GAP_ROLE_PERIPHERAL = (0x08 | GAP_ROLE_BROADCASTER), + + /// Device has all role, both peripheral and central + GAP_ROLE_ALL = (GAP_ROLE_CENTRAL | GAP_ROLE_PERIPHERAL), + + /// Debug mode used to force LL configuration on BLE 4.0 + GAP_ROLE_DBG_LE_4_0 = 0x80, +}; + +/// Advertising mode +enum gap_adv_mode +{ + /// Mode in non-discoverable + GAP_NON_DISCOVERABLE, + /// Mode in general discoverable + GAP_GEN_DISCOVERABLE, + /// Mode in limited discoverable + GAP_LIM_DISCOVERABLE, + /// Broadcaster mode which is a non discoverable and non connectable mode. + GAP_BROADCASTER_MODE +}; + +/// Scan mode +enum gap_scan_mode +{ + /// Mode in general discovery + GAP_GEN_DISCOVERY, + /// Mode in limited discovery + GAP_LIM_DISCOVERY, + /// Observer mode + GAP_OBSERVER_MODE, + /// Invalid mode + GAP_INVALID_MODE +}; + + + +/// IO Capability Values +enum gap_io_cap +{ + /// Display Only + GAP_IO_CAP_DISPLAY_ONLY = 0x00, + /// Display Yes No + GAP_IO_CAP_DISPLAY_YES_NO, + /// Keyboard Only + GAP_IO_CAP_KB_ONLY, + /// No Input No Output + GAP_IO_CAP_NO_INPUT_NO_OUTPUT, + /// Keyboard Display + GAP_IO_CAP_KB_DISPLAY, + GAP_IO_CAP_LAST +}; + +/// TK Type +enum gap_tk_type +{ + /// TK get from out of band method + GAP_TK_OOB = 0x00, + /// TK generated and shall be displayed by local device + GAP_TK_DISPLAY, + /// TK shall be entered by user using device keyboard + GAP_TK_KEY_ENTRY +}; + +/// OOB Data Present Flag Values +enum gap_oob +{ + /// OOB Data not present + GAP_OOB_AUTH_DATA_NOT_PRESENT = 0x00, + /// OOB data present + GAP_OOB_AUTH_DATA_PRESENT, + GAP_OOB_AUTH_DATA_LAST +}; + +/// Authentication mask +enum gap_auth_mask +{ + /// No Flag set + GAP_AUTH_NONE = 0, + /// Bond authentication + GAP_AUTH_BOND = (1 << 0), + /// Man In the middle protection + GAP_AUTH_MITM = (1 << 2), + /// Secure Connection + GAP_AUTH_SEC_CON = (1 << 3), + /// Key Notification + GAP_AUTH_KEY_NOTIF = (1 << 4) +}; + +/// Security Link Level +enum gap_lk_sec_lvl +{ + /// No authentication + GAP_LK_NO_AUTH = 0, + /// Unauthenticated link + GAP_LK_UNAUTH, + /// Authenticated link + GAP_LK_AUTH, + /// Secure Connection link + GAP_LK_SEC_CON, +}; + +/// Authentication Requirements +enum gap_auth +{ + /// No MITM No Bonding + GAP_AUTH_REQ_NO_MITM_NO_BOND = (GAP_AUTH_NONE), + /// No MITM Bonding + GAP_AUTH_REQ_NO_MITM_BOND = (GAP_AUTH_BOND), + /// MITM No Bonding + GAP_AUTH_REQ_MITM_NO_BOND = (GAP_AUTH_MITM), + /// MITM and Bonding + GAP_AUTH_REQ_MITM_BOND = (GAP_AUTH_MITM | GAP_AUTH_BOND), + /// SEC_CON and No Bonding + GAP_AUTH_REQ_SEC_CON_NO_BOND = (GAP_AUTH_SEC_CON), + /// SEC_CON and Bonding + GAP_AUTH_REQ_SEC_CON_BOND = (GAP_AUTH_SEC_CON | GAP_AUTH_BOND), + + GAP_AUTH_REQ_LAST, + + /// Mask of authentication features without reserved flag + GAP_AUTH_REQ_MASK = 0x1F, +}; + +/// Key Distribution Flags +enum gap_kdist +{ + /// No Keys to distribute + GAP_KDIST_NONE = 0x00, + /// Encryption key in distribution + GAP_KDIST_ENCKEY = (1 << 0), + /// IRK (ID key)in distribution + GAP_KDIST_IDKEY = (1 << 1), + /// CSRK(Signature key) in distribution + GAP_KDIST_SIGNKEY= (1 << 2), + /// LTK in distribution + GAP_KDIST_LINKKEY= (1 << 3), + + GAP_KDIST_LAST = (1 << 4) +}; + +/// Security Defines +enum gap_sec_req +{ + /// No security (no authentication and encryption) + GAP_NO_SEC = 0x00, + /// Unauthenticated pairing with encryption + GAP_SEC1_NOAUTH_PAIR_ENC, + /// Authenticated pairing with encryption + GAP_SEC1_AUTH_PAIR_ENC, + /// Unauthenticated pairing with data signing + GAP_SEC2_NOAUTH_DATA_SGN, + /// Authentication pairing with data signing + GAP_SEC2_AUTH_DATA_SGN, + /// Secure Connection pairing with encryption + GAP_SEC1_SEC_CON_PAIR_ENC, +}; + +/// Bit field use to select the preferred TX or RX LE PHY Rate. 0 means no preferences +enum gap_rate +{ + /// No preferred rate + GAP_RATE_ANY = 0x00, + /// LE PHY 1mb/s preferred rate for an active link + GAP_RATE_LE_1MBPS = (1 << 0), + /// LE PHY 2mb/s preferred rate for an active link + GAP_RATE_LE_2MBPS = (1 << 1), +}; + +/// Modulation index +enum gap_modulation_idx +{ + /// Assume transmitter will have a standard modulation index + GAP_MODULATION_STANDARD, + /// Assume transmitter will have a stable modulation index + GAP_MODULATION_STABLE, +}; + +/// Packet Payload type for test mode +enum gap_pkt_pld_type +{ + /// PRBS9 sequence "11111111100000111101..." (in transmission order) + GAP_PKT_PLD_PRBS9, + /// Repeated "11110000" (in transmission order) + GAP_PKT_PLD_REPEATED_11110000, + /// Repeated "10101010" (in transmission order) + GAP_PKT_PLD_REPEATED_10101010, + /// PRBS15 sequence + GAP_PKT_PLD_PRBS15, + /// Repeated "11111111" (in transmission order) sequence + GAP_PKT_PLD_REPEATED_11111111, + /// Repeated "00000000" (in transmission order) sequence + GAP_PKT_PLD_REPEATED_00000000, + /// Repeated "00001111" (in transmission order) sequence + GAP_PKT_PLD_REPEATED_00001111, + /// Repeated "01010101" (in transmission order) sequence + GAP_PKT_PLD_REPEATED_01010101, +}; + +/// device name +struct gap_dev_name +{ + /// name length + uint16_t length; + /// name value + uint8_t value[__ARRAY_EMPTY]; +}; + +/// Slave preferred connection parameters +struct gap_slv_pref +{ + /// Connection interval minimum + uint16_t con_intv_min; + /// Connection interval maximum + uint16_t con_intv_max; + /// Slave latency + uint16_t slave_latency; + /// Connection supervision timeout multiplier + uint16_t conn_timeout; +}; + + + + + +/*************** GAP Structures ********************/ + +///BD Address structure +typedef struct +{ + ///6-byte array address value + uint8_t addr[GAP_BD_ADDR_LEN]; +} bd_addr_t; + +///Channel map structure +typedef struct +{ + ///5-byte channel map array + uint8_t map[GAP_LE_CHNL_MAP_LEN]; +} le_chnl_map_t; + + +///Random number structure +typedef struct +{ + ///8-byte array for random number + uint8_t nb[GAP_RAND_NB_LEN]; +} rand_nb_t; + +///Advertising report structure +typedef struct +{ + ///Event type: + /// - ADV_CONN_UNDIR: Connectable Undirected advertising + /// - ADV_CONN_DIR: Connectable directed advertising + /// - ADV_DISC_UNDIR: Discoverable undirected advertising + /// - ADV_NONCONN_UNDIR: Non-connectable undirected advertising + uint8_t evt_type; + ///Advertising address type: public/random + uint8_t adv_addr_type; + ///Advertising address value + bd_addr_t adv_addr; + ///Data length in advertising packet + uint8_t data_len; + ///Data of advertising packet + uint8_t data[GAP_ADV_DATA_LEN]; + ///RSSI value for advertising packet + int8_t rssi; +} adv_report_t; + + +/// P256 Public key data format +typedef struct +{ + /// X Coordinate of the key + uint8_t x[GAP_P256_KEY_LEN]; + /// X Coordinate of the key + uint8_t y[GAP_P256_KEY_LEN]; +} public_key_t; + +/// Address information about a device address +struct gap_bdaddr +{ + /// BD Address of device + bd_addr_t addr; + /// Address type of the device 0=public/1=private random + uint8_t addr_type; +}; + +/// Resolving list device information +struct gap_ral_dev_info +{ + /// Address type of the device 0=public/1=private random + uint8_t addr_type; + /// BD Address of device + bd_addr_t addr; + /// Peer IRK + uint8_t peer_irk[GAP_KEY_LEN]; + /// Local IRK + uint8_t local_irk[GAP_KEY_LEN]; +}; + +/// Generic Security key structure +struct gap_sec_key +{ + /// Key value MSB -> LSB + uint8_t key[GAP_KEY_LEN]; +}; + + + +/// @} GAP +#endif // GAP_H_ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/api/gapc_task.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/api/gapc_task.h new file mode 100755 index 0000000..ac24e93 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/api/gapc_task.h @@ -0,0 +1,979 @@ +/** + **************************************************************************************** + * + * @file gapc_task.h + * + * @brief Generic Access Profile Controller Task Header. + * + * Copyright (C) RivieraWaves 2009-2016 + * + **************************************************************************************** + */ +#ifndef _GAPC_TASK_H_ +#define _GAPC_TASK_H_ + +/** + **************************************************************************************** + * @addtogroup GAPC_TASK Generic Access Profile Controller Task + * @ingroup GAPC + * @brief Handles ALL messages to/from GAP Controller block. + * + * It handles messages from lower and higher layers related to an ongoing connection. + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_task.h" // Task definitions +#include "gap.h" +#include + + +/* + * MACROS + **************************************************************************************** + */ + +/* + * DEFINES + **************************************************************************************** + */ + + +/// GAP Controller Task messages +enum gapc_msg_id +{ + /* Default event */ + /// Command Complete event + GAPC_CMP_EVT = TASK_FIRST_MSG(TASK_ID_GAPC), + + /* Connection state information */ + /// Indicate that a connection has been established + GAPC_CONNECTION_REQ_IND, + /// Set specific link data configuration. + GAPC_CONNECTION_CFM, + + /// Indicate that a link has been disconnected + GAPC_DISCONNECT_IND, + + /* Link management command */ + /// Request disconnection of current link command. + GAPC_DISCONNECT_CMD, + + /* Peer device info */ + /// Retrieve information command + GAPC_GET_INFO_CMD, + /// Peer device attribute DB info such as Device Name, Appearance or Slave Preferred Parameters + GAPC_PEER_ATT_INFO_IND, + /// Indication of peer version info + GAPC_PEER_VERSION_IND, + /// Indication of peer features info + GAPC_PEER_FEATURES_IND, + /// Indication of ongoing connection RSSI + GAPC_CON_RSSI_IND, + + /* Device Name Management */ + /// Peer device request local device info such as name, appearance or slave preferred parameters + GAPC_GET_DEV_INFO_REQ_IND, + /// Send requested info to peer device + GAPC_GET_DEV_INFO_CFM, + /// Peer device request to modify local device info such as name or appearance + GAPC_SET_DEV_INFO_REQ_IND, + /// Local device accept or reject device info modification + GAPC_SET_DEV_INFO_CFM, + + /* Connection parameters update */ + /// Perform update of connection parameters command + GAPC_PARAM_UPDATE_CMD, + /// Request of updating connection parameters indication + GAPC_PARAM_UPDATE_REQ_IND, + /// Master confirm or not that parameters proposed by slave are accepted or not + GAPC_PARAM_UPDATE_CFM, + /// Connection parameters updated indication + GAPC_PARAM_UPDATED_IND, + + /* Bonding procedure */ + /// Start Bonding command procedure + GAPC_BOND_CMD, + /// Bonding requested by peer device indication message. + GAPC_BOND_REQ_IND, + /// Confirm requested bond information. + GAPC_BOND_CFM, + /// Bonding information indication message + GAPC_BOND_IND, + + /* Encryption procedure */ + /// Start Encryption command procedure + GAPC_ENCRYPT_CMD, + /// Encryption requested by peer device indication message. + GAPC_ENCRYPT_REQ_IND, + /// Confirm requested Encryption information. + GAPC_ENCRYPT_CFM, + /// Encryption information indication message + GAPC_ENCRYPT_IND, + + /* Security request procedure */ + /// Start Security Request command procedure + GAPC_SECURITY_CMD, + /// Security requested by peer device indication message + GAPC_SECURITY_IND, + + /* Signature procedure */ + /// Indicate the current sign counters to the application + GAPC_SIGN_COUNTER_IND, + + /* Device information */ + /// Indication of ongoing connection Channel Map + GAPC_CON_CHANNEL_MAP_IND, + + + /* Deprecated */ + /// Deprecated messages + GAPC_DEPRECATED_0, + GAPC_DEPRECATED_1, + GAPC_DEPRECATED_2, + GAPC_DEPRECATED_3, + GAPC_DEPRECATED_4, + GAPC_DEPRECATED_5, + GAPC_DEPRECATED_6, + GAPC_DEPRECATED_7, + GAPC_DEPRECATED_8, + GAPC_DEPRECATED_9, + + /* LE Ping */ + /// Update LE Ping timeout value + GAPC_SET_LE_PING_TO_CMD, + /// LE Ping timeout indication + GAPC_LE_PING_TO_VAL_IND, + /// LE Ping timeout expires indication + GAPC_LE_PING_TO_IND, + + /* LE Data Length extension*/ + /// LE Set Data Length Command + GAPC_SET_LE_PKT_SIZE_CMD, + /// LE Set Data Length Indication + GAPC_LE_PKT_SIZE_IND, + + /* Secure Connections */ + /// Request to inform the remote device when keys have been entered or erased + GAPC_KEY_PRESS_NOTIFICATION_CMD, + /// Indication that a KeyPress has been performed on the peer device. + GAPC_KEY_PRESS_NOTIFICATION_IND, + + /* LE PHY update */ + /// Set the PHY configuration for current active link + GAPC_SET_PHY_CMD, + /// Active link PHY configuration. Triggered when configuration is read or during an update. + GAPC_LE_PHY_IND, + + /* Connection parameters update - cont */ + /// Set the preferred slave latency (for slave only, with RW controller) + GAPC_SET_PREF_SLAVE_LATENCY_CMD, + + // ---------------------- INTERNAL API ------------------------ + /* Internal messages for timer events, not part of API*/ + /// Signature procedure + GAPC_SIGN_CMD, + /// Signature result + GAPC_SIGN_IND, + + /// Parameter update procedure timeout indication + GAPC_PARAM_UPDATE_TO_IND, + /// Pairing procedure timeout indication + GAPC_SMP_TIMEOUT_TIMER_IND, + /// Pairing repeated attempts procedure timeout indication + GAPC_SMP_REP_ATTEMPTS_TIMER_IND, +}; + + + + +/// request operation type - application interface +enum gapc_operation +{ + /* Operation Flags */ + /* No Operation (if nothing has been requested) */ + /* ************************************************ */ + /// No operation + GAPC_NO_OP = 0x00, + + /* Connection management */ + /// Disconnect link + GAPC_DISCONNECT, + + /* Connection information */ + /// Retrieve name of peer device. + GAPC_GET_PEER_NAME, + /// Retrieve peer device version info. + GAPC_GET_PEER_VERSION, + /// Retrieve peer device features. + GAPC_GET_PEER_FEATURES, + /// Get Peer device appearance + GAPC_GET_PEER_APPEARANCE, + /// Get Peer device Slaved Preferred Parameters + GAPC_GET_PEER_SLV_PREF_PARAMS, + /// Retrieve connection RSSI. + GAPC_GET_CON_RSSI, + /// Retrieve Connection Channel MAP. + GAPC_GET_CON_CHANNEL_MAP, + + /* Connection parameters update */ + /// Perform update of connection parameters. + GAPC_UPDATE_PARAMS, + + /* Security procedures */ + /// Start bonding procedure. + GAPC_BOND, + /// Start encryption procedure. + GAPC_ENCRYPT, + /// Start security request procedure + GAPC_SECURITY_REQ, + + /* Deprecated */ + /// Deprecated operation + GAPC_OP_DEPRECATED_0, + GAPC_OP_DEPRECATED_1, + GAPC_OP_DEPRECATED_2, + GAPC_OP_DEPRECATED_3, + GAPC_OP_DEPRECATED_4, + + /* LE Ping*/ + /// get timer timeout value + GAPC_GET_LE_PING_TO, + /// set timer timeout value + GAPC_SET_LE_PING_TO, + + /* LE Data Length extension*/ + /// LE Set Data Length + GAPC_SET_LE_PKT_SIZE, + + /* Central Address resolution supported*/ + GAPC_GET_ADDR_RESOL_SUPP, + + /* Secure Connections */ + /// Request to inform the remote device when keys have been entered or erased + GAPC_KEY_PRESS_NOTIFICATION, + + /* LE PHY update */ + /// Set the PHY configuration for current active link + GAPC_SET_PHY, + /// Retrieve PHY configuration of active link + GAPC_GET_PHY, + + /* Connection parameters update - Cont -*/ + /// Set the preferred slave latency (for slave only, with RW controller) + GAPC_SET_PREF_SLAVE_LATENCY, + + // ---------------------- INTERNAL API ------------------------ + /* Packet signature */ + /// sign an attribute packet + GAPC_SIGN_PACKET, + /// Verify signature or an attribute packet + GAPC_SIGN_CHECK, +}; + +/// Bond event type. +enum gapc_bond +{ + /// Bond Pairing request + GAPC_PAIRING_REQ, + /// Respond to Pairing request + GAPC_PAIRING_RSP, + + /// Pairing Finished information + GAPC_PAIRING_SUCCEED, + /// Pairing Failed information + GAPC_PAIRING_FAILED, + + /// Used to retrieve pairing Temporary Key + GAPC_TK_EXCH, + /// Used for Identity Resolving Key exchange + GAPC_IRK_EXCH, + /// Used for Connection Signature Resolving Key exchange + GAPC_CSRK_EXCH, + /// Used for Long Term Key exchange + GAPC_LTK_EXCH, + + /// Bond Pairing request issue, Repeated attempt + GAPC_REPEATED_ATTEMPT, + + /// Out of Band - exchange of confirm and rand. + GAPC_OOB_EXCH, + + /// Numeric Comparison - Exchange of Numeric Value - + GAPC_NC_EXCH +}; + +/// List of device info that should be provided by application +enum gapc_dev_info +{ + /// Device Name + GAPC_DEV_NAME, + /// Device Appearance Icon + GAPC_DEV_APPEARANCE, + /// Device Slave preferred parameters + GAPC_DEV_SLV_PREF_PARAMS, + /// Device Central address resolution + GAPC_DEV_CTL_ADDR_RESOL, + /// maximum device info parameter + GAPC_DEV_INFO_MAX, +}; + +/// List of features available on a device +enum gapc_features_list +{ + /// LE encryption + GAPC_ENCRYPT_FEAT_MASK = (1 << 0), + /// Connection Parameters Request Procedure + GAPC_CONN_PARAM_REQ_FEAT_MASK = (1 << 1), + /// Extended Reject Indication + GAPC_EXT_REJECT_IND_FEAT_MASK = (1 << 2), + /// Slave-initiated Features Exchange + GAPC_SLAVE_FEAT_EXCH_FEAT_MASK = (1 << 3), + /// LE ping + GAPC_LE_PING_FEAT_MASK = (1 << 4) +}; + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + +/// Operation command structure in order to keep requested operation. +struct gapc_operation_cmd +{ + /// GAP request type + uint8_t operation; +}; + + +/// Command complete event data structure +struct gapc_cmp_evt +{ + /// GAP request type + uint8_t operation; + /// Status of the request + uint8_t status; +}; + +/// Indicate that a connection has been established +struct gapc_connection_req_ind +{ + /// Connection handle + uint16_t conhdl; + /// Connection interval + uint16_t con_interval; + /// Connection latency + uint16_t con_latency; + /// Link supervision timeout + uint16_t sup_to; + /// Clock accuracy + uint8_t clk_accuracy; + /// Peer address type + uint8_t peer_addr_type; + /// Peer BT address + bd_addr_t peer_addr; +}; + + +/// Set specific link data configuration. +struct gapc_connection_cfm +{ + /// Local CSRK value + struct gap_sec_key lcsrk; + /// Local signature counter value + uint32_t lsign_counter; + + /// Remote CSRK value + struct gap_sec_key rcsrk; + /// Remote signature counter value + uint32_t rsign_counter; + + /// Authentication (@see gap_auth) + uint8_t auth; + /// Service Changed Indication enabled + uint8_t svc_changed_ind_enable; + /// LTK exchanged during pairing. + bool ltk_present; +}; + + +/// Request disconnection of current link command. +struct gapc_disconnect_cmd +{ + /// GAP request type: + /// - GAPC_DISCONNECT: Disconnect link. + uint8_t operation; + + /// Reason of disconnection + uint8_t reason; +}; + + +/// Indicate that a link has been disconnected +struct gapc_disconnect_ind +{ + /// Connection handle + uint16_t conhdl; + /// Reason of disconnection + uint8_t reason; +}; + + +/// Retrieve information command +struct gapc_get_info_cmd +{ + /// GAP request type: + /// - GAPC_GET_PEER_NAME: Retrieve name of peer device. + /// - GAPC_GET_PEER_VERSION: Retrieve peer device version info. + /// - GAPC_GET_PEER_FEATURES: Retrieve peer device features. + /// - GAPC_GET_CON_RSSI: Retrieve connection RSSI. + /// - GAPC_GET_CON_CHANNEL_MAP: Retrieve Connection Channel MAP. + /// - GAPC_GET_PEER_APPEARANCE: Get Peer device appearance + /// - GAPC_GET_PEER_SLV_PREF_PARAMS: Get Peer device Slaved Preferred Parameters + /// - GAPC_GET_ADDR_RESOL_SUPP: Address Resolution Supported + /// - GAPC_GET_LE_PING_TIMEOUT: Retrieve LE Ping Timeout Value + uint8_t operation; +}; + +/// device information data +union gapc_dev_info_val +{ + /// Device name + struct gap_dev_name name; + /// Appearance Icon + uint16_t appearance; + /// Slave preferred parameters + struct gap_slv_pref slv_params; + /// Central address resolution + uint8_t cnt_addr_resol; +}; + +/// Peer device attribute DB info such as Device Name, Appearance or Slave Preferred Parameters +struct gapc_peer_att_info_ind +{ + /// Requested information + /// - GAPC_DEV_NAME: Device Name + /// - GAPC_DEV_APPEARANCE: Device Appearance Icon + /// - GAPC_DEV_SLV_PREF_PARAMS: Device Slave preferred parameters + /// - GAPC_GET_ADDR_RESOL_SUPP: Address resolution supported + uint8_t req; + /// Attribute handle + uint16_t handle; + + /// device information data + union gapc_dev_info_val info; +}; + +/// Indication of peer version info +struct gapc_peer_version_ind +{ + /// Manufacturer name + uint16_t compid; + /// LMP subversion + uint16_t lmp_subvers; + /// LMP version + uint8_t lmp_vers; +}; + +/// Indication of peer features info +struct gapc_peer_features_ind +{ + /// 8-byte array for LE features + uint8_t features[GAP_LE_FEATS_LEN]; +}; + +/// Indication of ongoing connection RSSI +struct gapc_con_rssi_ind +{ + /// RSSI value + int8_t rssi; +}; +/// Indication of ongoing connection Channel Map +struct gapc_con_channel_map_ind +{ + /// channel map value + le_chnl_map_t ch_map; +}; + +/// Sign counter value changed due to packet signing or signature verification. +struct gapc_sign_counter_updated_ind +{ + /// New Local signature counter value + uint32_t lsign_counter; + /// New Remote signature counter value + uint32_t rsign_counter; +}; + +/// Indication of LE Ping +struct gapc_le_ping_to_val_ind +{ + ///Authenticated payload timeout + uint16_t timeout; +}; + + +/// Peer device request local device info such as name, appearance or slave preferred parameters +struct gapc_get_dev_info_req_ind +{ + /// Requested information + /// - GAPC_DEV_NAME: Device Name + /// - GAPC_DEV_APPEARANCE: Device Appearance Icon + /// - GAPC_DEV_SLV_PREF_PARAMS: Device Slave preferred parameters + uint8_t req; +}; + + + +/// Send requested info to peer device +struct gapc_get_dev_info_cfm +{ + /// Requested information + /// - GAPC_DEV_NAME: Device Name + /// - GAPC_DEV_APPEARANCE: Device Appearance Icon + /// - GAPC_DEV_SLV_PREF_PARAMS: Device Slave preferred parameters + uint8_t req; + + /// Peer device information data + union gapc_dev_info_val info; +}; + +/// Peer device request to modify local device info such as name or appearance +struct gapc_set_dev_info_req_ind +{ + /// Requested information + /// - GAPC_DEV_NAME: Device Name + /// - GAPC_DEV_APPEARANCE: Device Appearance Icon + uint8_t req; + + /// device information data + union gapc_set_dev_info + { + /// Device name + struct gap_dev_name name; + /// Appearance Icon + uint16_t appearance; + } info; +}; + +/// Local device accept or reject device info modification +struct gapc_set_dev_info_cfm +{ + /// Requested information + /// - GAPC_DEV_NAME: Device Name + /// - GAPC_DEV_APPEARANCE: Device Appearance Icon + uint8_t req; + + /// Status code used to know if requested has been accepted or not + uint8_t status; +}; + +/// Connection Parameter used to update connection parameters +struct gapc_conn_param +{ + /// Connection interval minimum + uint16_t intv_min; + /// Connection interval maximum + uint16_t intv_max; + /// Latency + uint16_t latency; + /// Supervision timeout + uint16_t time_out; +}; + +/// Perform update of connection parameters command +struct gapc_param_update_cmd +{ + /// GAP request type: + /// - GAPC_UPDATE_PARAMS: Perform update of connection parameters. + uint8_t operation; + /// Internal parameter used to manage internally l2cap packet identifier for signaling + uint8_t pkt_id; + /// Connection interval minimum + uint16_t intv_min; + /// Connection interval maximum + uint16_t intv_max; + /// Latency + uint16_t latency; + /// Supervision timeout + uint16_t time_out; + /// Minimum Connection Event Duration + uint16_t ce_len_min; + /// Maximum Connection Event Duration + uint16_t ce_len_max; +}; + +/// Request of updating connection parameters indication +struct gapc_param_update_req_ind +{ + /// Connection interval minimum + uint16_t intv_min; + /// Connection interval maximum + uint16_t intv_max; + /// Latency + uint16_t latency; + /// Supervision timeout + uint16_t time_out; +}; + +/// Connection parameters updated indication +struct gapc_param_updated_ind +{ + ///Connection interval value + uint16_t con_interval; + ///Connection latency value + uint16_t con_latency; + ///Supervision timeout + uint16_t sup_to; +}; + +/// Master confirm or not that parameters proposed by slave are accepted or not +struct gapc_param_update_cfm +{ + /// True to accept slave connection parameters, False else. + bool accept; + /// Minimum Connection Event Duration + uint16_t ce_len_min; + /// Maximum Connection Event Duration + uint16_t ce_len_max; +}; + +/// Parameters of the @ref GAPC_SET_PREF_SLAVE_LATENCY_CMD message +struct gapc_set_pref_slave_latency_cmd +{ + /// GAP request type: + /// - GAPC_SET_PREF_SLAVE_LATENCY_CMD : Set preferred slave latency + uint8_t operation; + /// Preferred latency that the controller should use on a connection (in number of connection events) + uint16_t latency; +}; + +/// Pairing parameters +struct gapc_pairing +{ + /// IO capabilities (@see gap_io_cap) + uint8_t iocap; + /// OOB information (@see gap_oob) + uint8_t oob; + /// Authentication (@see gap_auth) + /// Note in BT 4.1 the Auth Field is extended to include 'Key Notification' and + /// and 'Secure Connections'. + uint8_t auth; + /// Encryption key size (7 to 16) + uint8_t key_size; + ///Initiator key distribution (@see gap_kdist) + uint8_t ikey_dist; + ///Responder key distribution (@see gap_kdist) + uint8_t rkey_dist; + + /// Device security requirements (minimum security level). (@see gap_sec_req) + uint8_t sec_req; +}; + +/// Long Term Key information +struct gapc_ltk +{ + /// Long Term Key + struct gap_sec_key ltk; + /// Encryption Diversifier + uint16_t ediv; + /// Random Number + rand_nb_t randnb; + /// Encryption key size (7 to 16) + uint8_t key_size; +}; +/// Out of Band Information +struct gapc_oob +{ + /// Confirm Value + uint8_t conf[GAP_KEY_LEN]; + /// Random Number + uint8_t rand[GAP_KEY_LEN]; +}; + +struct gapc_nc +{ + uint8_t value[4]; +}; + +/// Identity Resolving Key information +struct gapc_irk +{ + /// Identity Resolving Key + struct gap_sec_key irk; + /// Device BD Identity Address + struct gap_bdaddr addr; +}; + + +/// Start Bonding command procedure +struct gapc_bond_cmd +{ + /// GAP request type: + /// - GAPC_BOND: Start bonding procedure. + uint8_t operation; + /// Pairing information + struct gapc_pairing pairing; +}; + +/// Bonding requested by peer device indication message. +struct gapc_bond_req_ind +{ + /// Bond request type (@see gapc_bond) + uint8_t request; + + /// Bond procedure requested information data + union gapc_bond_req_data + { + /// Authentication level (@see gap_auth) (if request = GAPC_PAIRING_REQ) + uint8_t auth_req; + /// LTK Key Size (if request = GAPC_LTK_EXCH) + uint8_t key_size; + /// Device IO used to get TK: (if request = GAPC_TK_EXCH) + /// - GAP_TK_OOB: TK get from out of band method + /// - GAP_TK_DISPLAY: TK generated and shall be displayed by local device + /// - GAP_TK_KEY_ENTRY: TK shall be entered by user using device keyboard + uint8_t tk_type; + + /// Addition OOB Data for the OOB Conf and Rand values + struct gapc_oob oob_data; + /// Numeric Comparison Data + struct gapc_nc nc_data; + } data; +}; + +/// Confirm requested bond information. +struct gapc_bond_cfm +{ + /// Bond request type (@see gapc_bond) + uint8_t request; + /// Request accepted + uint8_t accept; + + /// Bond procedure information data + union gapc_bond_cfm_data + { + /// Pairing Features (request = GAPC_PAIRING_RSP) + struct gapc_pairing pairing_feat; + /// LTK (request = GAPC_LTK_EXCH) + struct gapc_ltk ltk; + /// CSRK (request = GAPC_CSRK_EXCH) + struct gap_sec_key csrk; + /// TK (request = GAPC_TK_EXCH) + struct gap_sec_key tk; + /// IRK (request = GAPC_IRK_EXCH) + struct gapc_irk irk; + /// OOB Confirm and Random from the peer (request = GAPC_OOB_EXCH) + struct gapc_oob oob; + } data; +}; + +/** + * Authentication information + */ +struct gapc_bond_auth +{ + /// Authentication information (@see gap_auth) + uint8_t info; + + /// LTK exchanged during pairing. + bool ltk_present; +}; + + + +/// Bonding information indication message +struct gapc_bond_ind +{ + /// Bond information type (@see gapc_bond) + uint8_t info; + + /// Bond procedure information data + union gapc_bond_data + { + /// Authentication information (@see gap_auth) + /// (if info = GAPC_PAIRING_SUCCEED) + struct gapc_bond_auth auth; + /// Pairing failed reason (if info = GAPC_PAIRING_FAILED) + uint8_t reason; + /// Long Term Key information (if info = GAPC_LTK_EXCH) + struct gapc_ltk ltk; + /// Identity Resolving Key information (if info = GAPC_IRK_EXCH) + struct gapc_irk irk; + /// Connection Signature Resolving Key information (if info = GAPC_CSRK_EXCH) + struct gap_sec_key csrk; + } data; +}; + +/// Start Encryption command procedure +struct gapc_encrypt_cmd +{ + /// GAP request type: + /// - GAPC_ENCRYPT: Start encryption procedure. + uint8_t operation; + /// Long Term Key information + struct gapc_ltk ltk; +}; + +/// Encryption requested by peer device indication message. +struct gapc_encrypt_req_ind +{ + /// Encryption Diversifier + uint16_t ediv; + /// Random Number + rand_nb_t rand_nb; +}; + +/// Confirm requested Encryption information. +struct gapc_encrypt_cfm +{ + /// Indicate if a LTK has been found for the peer device + uint8_t found; + /// Long Term Key + struct gap_sec_key ltk; + /// LTK Key Size + uint8_t key_size; +}; + +/// Encryption information indication message +struct gapc_encrypt_ind +{ + /// Authentication level (@see gap_auth) + uint8_t auth; +}; + +/// Start Security Request command procedure +struct gapc_security_cmd +{ + /// GAP request type: + /// - GAPC_SECURITY_REQ: Start security request procedure + uint8_t operation; + /// Authentication level (@see gap_auth) + uint8_t auth; +}; +/// Security requested by peer device indication message +struct gapc_security_ind +{ + /// Authentication level (@see gap_auth) + uint8_t auth; +}; + +/// Parameters of the @ref GAPC_SIGN_COUNTER_IND message +struct gapc_sign_counter_ind +{ + /// Local SignCounter value + uint32_t local_sign_counter; + /// Peer SignCounter value + uint32_t peer_sign_counter; +}; + + +/// Parameters of the @ref GAPC_SET_LE_PING_TO_CMD message +struct gapc_set_le_ping_to_cmd +{ + /// GAP request type: + /// - GAPC_SET_LE_PING_TO : Set the LE Ping timeout value + uint8_t operation; + /// Authenticated payload timeout + uint16_t timeout; +}; + +/// Parameters of the @ref GAPC_SET_LE_PKT_SIZE_CMD message +struct gapc_set_le_pkt_size_cmd +{ + /// GAP request type: + /// - GAPC_SET_LE_PKT_SIZE : Set the LE Data length value + uint8_t operation; + ///Preferred maximum number of payload octets that the local Controller should include + ///in a single Link Layer Data Channel PDU. + uint16_t tx_octets; + ///Preferred maximum number of microseconds that the local Controller should use to transmit + ///a single Link Layer Data Channel PDU + uint16_t tx_time; +}; + +/// Parameters of the @ref GAPC_LE_PKT_SIZE_IND message +struct gapc_le_pkt_size_ind +{ + ///The maximum number of payload octets in TX + uint16_t max_tx_octets; + ///The maximum time that the local Controller will take to TX + uint16_t max_tx_time; + ///The maximum number of payload octets in RX + uint16_t max_rx_octets; + ///The maximum time that the local Controller will take to RX + uint16_t max_rx_time; +}; + +/// Parameters of the @ref GAPC_KEY_PRESS_NOTIFICATION_CMD message +struct gapc_key_press_notif_cmd +{ + /// GAP request type: + /// - GAPC_KEY_PRESS_NOTIFICATION_CMD : Inform the remote device when keys have been entered or erased + uint8_t operation; + /// notification type + uint8_t notification_type; +}; + +/// Parameters of the @ref GAPC_KEY_PRESS_NOTIFICATION_IND message +struct gapc_key_press_notif_ind +{ + /// notification type + uint8_t notification_type; +}; + +/// Set the PHY configuration for current active link +struct gapc_set_phy_cmd +{ + /// GAP request type: + /// - GAPC_SET_PHY : Set the PHY configuration for current active link + uint8_t operation; + /// Supported LE PHY rates for data transmission (@see enum gap_rate) + uint8_t tx_rates; + /// Supported LE PHY rates for data reception (@see enum gap_rate) + uint8_t rx_rates; +}; + +/// Active link PHY configuration. Triggered when configuration is read or during an update. +struct gapc_le_phy_ind +{ + /// LE PHY rate for data transmission (@see enum gap_rate) + uint8_t tx_rate; + /// LE PHY rate for data reception (@see enum gap_rate) + uint8_t rx_rate; +}; + +/// Parameters of the @ref GAPC_SIGN_CMD message +struct gapc_sign_cmd +{ + /// GAP request type: + /// - GAPC_SIGN_PACKET: Sign an attribute packet + /// - GAPC_SIGN_CHECK: Verify signature or an attribute packet + uint8_t operation; + /// Data PDU length (Bytes) + uint16_t byte_len; + /// Data PDU + SignCounter if generation, Data PDU + SignCounter + MAC if verification + uint8_t msg[__ARRAY_EMPTY]; +}; + +/// Parameters of the @ref GAPC_SIGN_IND message +struct gapc_sign_ind +{ + /// GAP request type: + /// - GAPC_SIGN_PACKET: Sign an attribute packet + /// - GAPC_SIGN_CHECK: Verify signature or an attribute packet + uint8_t operation; + /// Data PDU length (Bytes) + uint16_t byte_len; + /// Data PDU + SignCounter + MAC + uint8_t signed_msg[__ARRAY_EMPTY]; +}; + + +/// @} GAPC_TASK + +#endif /* _GAPC_TASK_H_ */ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/api/gapm_task.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/api/gapm_task.h new file mode 100755 index 0000000..67a9c21 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/api/gapm_task.h @@ -0,0 +1,1166 @@ +/** + **************************************************************************************** + * + * @file gapm_task.h + * + * @brief Generic Access Profile Manager Task Header. + * + * Copyright (C) RivieraWaves 2009-2016 + * + **************************************************************************************** + */ + + +#ifndef _GAPM_TASK_H_ +#define _GAPM_TASK_H_ + +/** + **************************************************************************************** + * @addtogroup GAPM_TASK Generic Access Profile Manager Task + * @ingroup GAPM + * @brief Handles ALL messages to/from GAP Manager block. + * + * It handles messages from lower and higher layers not related to an ongoing connection. + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_task.h" // Task definitions +#include "gap.h" + + +/* + * DEFINES + **************************************************************************************** + */ + +/// GAP Manager Message Interface +enum gapm_msg_id +{ + /* Default event */ + /// Command Complete event + GAPM_CMP_EVT = TASK_FIRST_MSG(TASK_ID_GAPM), + /// Event triggered to inform that lower layers are ready + GAPM_DEVICE_READY_IND, + + /* Default commands */ + /// Reset link layer and the host command + GAPM_RESET_CMD, + /// Cancel ongoing operation + GAPM_CANCEL_CMD, + + /* Device Configuration */ + /// Set device configuration command + GAPM_SET_DEV_CONFIG_CMD, + /// Set device channel map + GAPM_SET_CHANNEL_MAP_CMD, + + /* Local device information */ + /// Get local device info command + GAPM_GET_DEV_INFO_CMD, + /// Local device version indication event + GAPM_DEV_VERSION_IND, + /// Local device BD Address indication event + GAPM_DEV_BDADDR_IND, + /// Advertising channel Tx power level + GAPM_DEV_ADV_TX_POWER_IND, + /// Indication containing information about memory usage. + GAPM_DBG_MEM_INFO_IND, + + /* White List */ + /// White List Management Command + GAPM_WHITE_LIST_MGT_CMD, + /// White List Size indication event + GAPM_WHITE_LIST_SIZE_IND, + + /* Air Operations */ + /// Set advertising mode Command + GAPM_START_ADVERTISE_CMD, + /// Update Advertising Data Command - On fly update when device is advertising + GAPM_UPDATE_ADVERTISE_DATA_CMD, + + /// Set Scan mode Command + GAPM_START_SCAN_CMD, + /// Advertising or scanning report information event + GAPM_ADV_REPORT_IND, + + /// Set connection initialization Command + GAPM_START_CONNECTION_CMD, + /// Name of peer device indication + GAPM_PEER_NAME_IND, + /// Confirm connection to a specific device (Connection Operation in Selective mode) + GAPM_CONNECTION_CFM, + + /* Security / Encryption Toolbox */ + /// Resolve address command + GAPM_RESOLV_ADDR_CMD, + /// Indicate that resolvable random address has been solved + GAPM_ADDR_SOLVED_IND, + /// Generate a random address. + GAPM_GEN_RAND_ADDR_CMD, + /// Use the AES-128 block in the controller + GAPM_USE_ENC_BLOCK_CMD, + /// AES-128 block result indication + GAPM_USE_ENC_BLOCK_IND, + /// Generate a 8-byte random number + GAPM_GEN_RAND_NB_CMD, + /// Random Number Indication + GAPM_GEN_RAND_NB_IND, + + /* Profile Management */ + /// Create new task for specific profile + GAPM_PROFILE_TASK_ADD_CMD, + /// Inform that profile task has been added. + GAPM_PROFILE_ADDED_IND, + + /// Indicate that a message has been received on an unknown task + GAPM_UNKNOWN_TASK_IND, + + /* Data Length Extension */ + /// Suggested Default Data Length indication + GAPM_SUGG_DFLT_DATA_LEN_IND, + /// Maximum Data Length indication + GAPM_MAX_DATA_LEN_IND, + + /* Resolving list for controller-based privacy*/ + /// Resolving address list management + GAPM_RAL_MGT_CMD, + /// Resolving address list size indication + GAPM_RAL_SIZE_IND, + /// Resolving address list address indication + GAPM_RAL_ADDR_IND, + + /* Set new IRK */ + /// Modify current IRK + GAPM_SET_IRK_CMD, + + /* LE Protocol/Service Multiplexer Management */ + /// Register a LE Protocol/Service Multiplexer command + GAPM_LEPSM_REGISTER_CMD, + /// Unregister a LE Protocol/Service Multiplexer command + GAPM_LEPSM_UNREGISTER_CMD, + + /* LE Test Mode */ + /// Control of the test mode command + GAPM_LE_TEST_MODE_CTRL_CMD, + /// Indicate end of test mode + GAPM_LE_TEST_END_IND, + + /* ************************************************ */ + /* -------------- Internal usage only ------------- */ + /* ************************************************ */ + /// Message received to unknown task received + GAPM_UNKNOWN_TASK_MSG, + + /* Secure Connections */ + /// Request to provide DH Key + GAPM_GEN_DH_KEY_CMD, + /// Indicates the DH Key computation is complete and available + GAPM_GEN_DH_KEY_IND, + /// Retrieve Public Key + GAPM_GET_KEY_CMD, + /// Indicates the Public Key Pair value + GAPM_GET_KEY_IND, + + /* Internal messages for timer events, not part of API*/ + /// Limited discoverable timeout indication + GAPM_LIM_DISC_TO_IND, + /// Scan timeout indication + GAPM_SCAN_TO_IND, + /// Address renewal timeout indication + GAPM_ADDR_RENEW_TO_IND, +}; + + +/// GAP Manager operation type - application interface +enum gapm_operation +{ + /* No Operation (if nothing has been requested) */ + /* ************************************************ */ + /// No operation. + GAPM_NO_OP = 0x00, + + /* Default operations */ + /* ************************************************ */ + /// Reset BLE subsystem: LL and HL. + GAPM_RESET, // 0x01 + /// Cancel currently executed operation. + GAPM_CANCEL, // 0x02 + + /* Configuration operations */ + /* ************************************************ */ + /// Set device configuration + GAPM_SET_DEV_CONFIG, // 0x03 + /// Set device channel map + GAPM_SET_CHANNEL_MAP, // 0x04 + + /* Retrieve device information */ + /* ************************************************ */ + /// Get Local device version + GAPM_GET_DEV_VERSION, // 0x05 + /// Get Local device BD Address + GAPM_GET_DEV_BDADDR, // 0x06 + /// Get device advertising power level + GAPM_GET_DEV_ADV_TX_POWER, // 0x07 + /* Operation on White list */ + /* ************************************************ */ + /// Get White List Size. + GAPM_GET_WLIST_SIZE,// 0x08 + /// Add devices in white list. + GAPM_ADD_DEV_IN_WLIST,// 0x09 + /// Remove devices form white list. + GAPM_RMV_DEV_FRM_WLIST, // 0x0A + /// Clear all devices from white list. + GAPM_CLEAR_WLIST, // 0x0B + + /* Advertise mode operations */ + /* ************************************************ */ + /// Start non connectable advertising + GAPM_ADV_NON_CONN,// 0x0C + /// Start undirected connectable advertising + GAPM_ADV_UNDIRECT, // 0x0D + /// Start directed connectable advertising + GAPM_ADV_DIRECT, // 0x0E + /// Start directed connectable advertising using Low Duty Cycle + GAPM_ADV_DIRECT_LDC, // 0x0F + /// Update on the fly advertising data + GAPM_UPDATE_ADVERTISE_DATA,// 0x10 + + /* Scan mode operations */ + /* ************************************************ */ + /// Start active scan operation + GAPM_SCAN_ACTIVE,// 0x11 + /// Start passive scan operation + GAPM_SCAN_PASSIVE,// 0x12 + + /* Connection mode operations */ + /* ************************************************ */ + /// Direct connection operation + GAPM_CONNECTION_DIRECT,// 0x13 + /// Automatic connection operation + GAPM_CONNECTION_AUTO,// 0x14 + /// Selective connection operation + GAPM_CONNECTION_SELECTIVE,// 0x15 + /// Name Request operation (requires to start a direct connection) + GAPM_CONNECTION_NAME_REQUEST,// 0x16 + + /* Security / Encryption Toolbox */ + /* ************************************************ */ + /// Resolve device address + GAPM_RESOLV_ADDR,// 0x17 + /// Generate a random address + GAPM_GEN_RAND_ADDR,// 0x18 + /// Use the controller's AES-128 block + GAPM_USE_ENC_BLOCK,// 0x19 + /// Generate a 8-byte random number + GAPM_GEN_RAND_NB,// 0x1A + + /* Profile Management */ + /* ************************************************ */ + /// Create new task for specific profile + GAPM_PROFILE_TASK_ADD,// 0x1B + + + /* DEBUG */ + /* ************************************************ */ + /// Get memory usage + GAPM_DBG_GET_MEM_INFO,// 0x1C + /// Perform a platform reset + GAPM_PLF_RESET,// 0x1D + + /* Data Length Extension */ + /* ************************************************ */ + /// Set Suggested Default LE Data Length + GAPM_SET_SUGGESTED_DFLT_LE_DATA_LEN,// 0x1E + /// Get Suggested Default LE Data Length + GAPM_GET_SUGGESTED_DFLT_LE_DATA_LEN,// 0x1F + /// Get Maximum LE Data Length + GAPM_GET_MAX_LE_DATA_LEN,// 0x20 + + /* Operation on Resolving List */ + /* ************************************************ */ + /// Get resolving address list size + GAPM_GET_RAL_SIZE,// 0x21 + /// Get resolving local address + GAPM_GET_RAL_LOC_ADDR,// 0x22 + /// Get resolving peer address + GAPM_GET_RAL_PEER_ADDR,// 0x23 + /// Add device in resolving address list + GAPM_ADD_DEV_IN_RAL,// 0x24 + /// Remove device from resolving address list + GAPM_RMV_DEV_FRM_RAL,// 0x25 + /// Clear resolving address list + GAPM_CLEAR_RAL,// 0x26 + + /* Connection mode operations - cont */ + /* ************************************************ */ + /// General connection operation + GAPM_CONNECTION_GENERAL,// 0x27 + + /* Change current IRK */ + /* ************************************************ */ + /// Set IRK + GAPM_SET_IRK,// 0x28 + + /* LE Protocol/Service Multiplexer management */ + /* ************************************************ */ + /// Register a LE Protocol/Service Multiplexer + GAPM_LEPSM_REG,// 0x29 + /// Unregister a LE Protocol/Service Multiplexer + GAPM_LEPSM_UNREG,// 0x2A + + /* LE Direct Test Mode */ + /* ************************************************ */ + /// Stop the test mode + GAPM_LE_TEST_STOP,// 0x2B + /// Start RX Test Mode + GAPM_LE_TEST_RX_START,// 0x2C + /// Start TX Test Mode + GAPM_LE_TEST_TX_START,// 0x2D + + /* Secure Connection - Internal API */ + /* ************************************************ */ + /// Generate DH_Key + GAPM_GEN_DH_KEY,// 0x2E + /// Retrieve Public Key + GAPM_GET_PUB_KEY,// 0x2F +}; + + +/// Device Address type Configuration +enum gapm_addr_type +{ + /// Device Address is a Public Static address + GAPM_CFG_ADDR_PUBLIC = 0, + /// Device Address is a Private Static address + GAPM_CFG_ADDR_PRIVATE = 1, + /// Device Address generated using host-based Privacy feature + GAPM_CFG_ADDR_HOST_PRIVACY = 2, + /// Device Address generated using controller-based Privacy feature + GAPM_CFG_ADDR_CTNL_PRIVACY = 4, +}; + + +/// Own BD address source of the device +enum gapm_own_addr +{ + /// Public or Private Static Address according to device address configuration + GAPM_STATIC_ADDR, + /// Generated resolvable private random address + GAPM_GEN_RSLV_ADDR, + /// Generated non-resolvable private random address + GAPM_GEN_NON_RSLV_ADDR, +}; + +/// Device Attribute write permission requirement +enum gapm_write_att_perm +{ + /// Disable write access + GAPM_WRITE_DISABLE = 0, + /// Enable write access - no authentication required + GAPM_WRITE_NO_AUTH = 1, + /// Write access requires unauthenticated link + GAPM_WRITE_UNAUTH = 2, + /// Write access requires authenticated link + GAPM_WRITE_AUTH = 3, + /// Write access requires secure connected link + GAPM_WRITE_SEC_CON = 4 +}; + + +/// Attribute database configuration +/// 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +/// +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ +/// | DBG | RFU | SC |PCP | APP_PERM | NAME_PERM | +/// +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ +/// - Bit [0-2] : Device Name write permission requirements for peer device (@see gapm_write_att_perm) +/// - Bit [3-5] : Device Appearance write permission requirements for peer device (@see gapm_write_att_perm) +/// - Bit [6] : Slave Preferred Connection Parameters present +/// - Bit [7] : Service change feature present in GATT attribute database. +/// - Bit [8-14]: Reserved +/// - Bit [15] : Enable Debug Mode +enum gapm_att_cfg_flag +{ + /// Device Name write permission requirements for peer device (@see gapm_write_att_perm) + GAPM_MASK_ATT_NAME_PERM = 0x0007, + GAPM_POS_ATT_NAME_PERM = 0x00, + /// Device Appearance write permission requirements for peer device (@see gapm_write_att_perm) + GAPM_MASK_ATT_APPEARENCE_PERM = 0x0038, + GAPM_POS_ATT_APPEARENCE_PERM = 0x03, + /// Slave Preferred Connection Parameters present in GAP attribute database. + GAPM_MASK_ATT_SLV_PREF_CON_PAR_EN = 0x0040, + GAPM_POS_ATT_SLV_PREF_CON_PAR_EN = 0x06, + /// Service change feature present in GATT attribute database. + GAPM_MASK_ATT_SVC_CHG_EN = 0x0080, + GAPM_POS_ATT_SVC_CHG_EN = 0x07, + /// Service change feature present in GATT attribute database. + GAPM_MASK_ATT_DBG_MODE_EN = 0x8000, + GAPM_POS_ATT_DBG_MODE_EN = 0x0F, +}; + +/// Pairing mode authorized on the device +/// 7 6 5 4 3 2 1 0 +/// +----+----+----+----+----+----+----+----+ +/// |KGEN| RFU | SCP| LP | +/// +----+----+----+----+----+----+----+----+ +enum gapm_pairing_mode +{ + /// No pairing authorized + GAPM_PAIRING_DISABLE = 0, + /// Legacy pairing Authorized + GAPM_PAIRING_LEGACY = (1 << 0), + /// Secure Connection pairing Authorized + GAPM_PAIRING_SEC_CON = (1 << 1), + + + /// Force re-generation of P256 private and public keys + GAPM_PAIRING_FORCE_P256_KEY_GEN = (1 << 7), +}; + +/// LE Audio Mode Configuration +/// 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +/// +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ +/// | RFU | AM0| +/// +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ +enum gapm_audio_cfg_flag +{ + /// LE Audio Mode 0 Supported + GAPM_MASK_AUDIO_AM0_SUP = 0x0001, + GAPM_POS_AUDIO_AM0_SUP = 0x00, +}; + +/// Security level +/// 7 6 5 4 3 2 1 0 +/// +---+---+---+---+---+---+---+---+ +/// |MI | RFU |EKS|SEC_LVL| +/// +---+---+---+---+---+---+---+---+ +/// bit[0-1]: Security level requirement (0=NO_AUTH, 1=UNAUTH, 2=AUTH, 3=SEC_CON) +/// bit[2] : Encryption Key Size length must have 16 bytes +/// bit[7] : Multi-instantiated task +enum gapm_le_psm_sec_mask +{ + /// bit[0-1]: Security level requirement (0=NO_AUTH, 1=UNAUTH, 2=AUTH, 3=SEC_CON) + /// bit[2] : Encryption Key Size length must have 16 bytes + GAPM_LE_PSM_SEC_LVL_MASK = 0x07, + /// bit[7] : Multi-instantiated task + GAPM_LE_PSM_MI_TASK_MASK = 0x80, +}; + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + +/// Operation command structure in order to keep requested operation. +struct gapm_operation_cmd +{ + /// GAP request type + uint8_t operation; +}; + +/// Command complete event data structure +struct gapm_cmp_evt +{ + /// GAP requested operation + uint8_t operation; + /// Status of the request + uint8_t status; +}; + +/// Reset link layer and the host command +struct gapm_reset_cmd +{ + /// GAPM requested operation: + /// - GAPM_RESET: Reset BLE subsystem: LL and HL. + uint8_t operation; +}; + +/// Set device configuration command +struct gapm_set_dev_config_cmd +{ + /// GAPM requested operation: + /// - GAPM_SET_DEV_CONFIG: Set device configuration + uint8_t operation; + /// Device Role: Central, Peripheral, Observer, Broadcaster or All roles. + uint8_t role; + + /// -------------- Privacy Config ----------------------- + /// Duration before regenerate device address when privacy is enabled. - in seconds + uint16_t renew_dur; + /// Provided own static private random address (addr_type = GAPM_CFG_ADDR_PRIVATE) + bd_addr_t addr; + /// Device IRK used for resolvable random BD address generation (LSB first) + struct gap_sec_key irk; + /// Device Address Type + /// - GAPM_CFG_ADDR_PUBLIC: Device Address is a Public Static address + /// - GAPM_CFG_ADDR_PRIVATE: Device Address is a Private Static address + /// - GAPM_CFG_ADDR_HOST_PRIVACY: Device Address generated using Host Privacy feature + /// - GAPM_CFG_ADDR_CTNL_PRIVACY: Device Address generated using Controller Privacy feature + uint8_t addr_type; + + /// -------------- Security Config ----------------------- + + /// Pairing mode authorized (see enum gapm_pairing_mode) + uint8_t pairing_mode; + + /// -------------- ATT Database Config ----------------------- + + /// GAP service start handle + uint16_t gap_start_hdl; + /// GATT service start handle + uint16_t gatt_start_hdl; + + /// Attribute database configuration + /// 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + /// +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + /// | DBG | RFU | SC |PCP | APP_PERM | NAME_PERM | + /// +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + /// - Bit [0-2] : Device Name write permission requirements for peer device (@see gapm_write_att_perm) + /// - Bit [3-5] : Device Appearance write permission requirements for peer device (@see gapm_write_att_perm) + /// - Bit [6] : Slave Preferred Connection Parameters present + /// - Bit [7] : Service change feature present in GATT attribute database. + /// - Bit [8-14]: Reserved + /// - Bit [15] : Enable Debug Mode + uint16_t att_cfg; + + /// -------------- LE Data Length Extension ----------------------- + ///Suggested value for the Controller's maximum transmitted number of payload octets to be used + uint16_t sugg_max_tx_octets; + ///Suggested value for the Controller's maximum packet transmission time to be used + uint16_t sugg_max_tx_time; + + /// --------------- L2CAP Configuration --------------------------- + /// Maximal MTU acceptable for device + uint16_t max_mtu; + /// Maximal MPS Packet size acceptable for device + uint16_t max_mps; + /// Maximum number of LE Credit based connection that can be established + uint8_t max_nb_lecb; + + /// --------------- LE Audio Mode Supported ----------------------- + /// + /// LE Audio Mode Configuration (@see gapm_audio_cfg_flag) + uint16_t audio_cfg; + + /// ------------------ LE PHY Management ------------------------- + /// Preferred LE PHY rate for data transmission (@see enum gap_rate) + uint8_t tx_pref_rates; + /// Preferred LE PHY rate for data reception (@see enum gap_rate) + uint8_t rx_pref_rates; +}; + +/// Set new IRK +struct gapm_set_irk_cmd +{ + /// GAPM requested operation: + /// - GAPM_SET_IRK: Set device configuration + uint8_t operation; + /// Device IRK used for resolvable random BD address generation (LSB first) + struct gap_sec_key irk; +}; + +/// Set device channel map +struct gapm_set_channel_map_cmd +{ + /// GAPM requested operation: + /// - GAPM_SET_CHANNEL_MAP: Set device channel map. + uint8_t operation; + /// Channel map + le_chnl_map_t chmap; +}; + + +/// Get local device info command +struct gapm_get_dev_info_cmd +{ + /// GAPM requested operation: + /// - GAPM_GET_DEV_VERSION: Get Local device version + /// - GAPM_GET_DEV_BDADDR: Get Local device BD Address + /// - GAPM_GET_DEV_ADV_TX_POWER: Get device advertising power level + /// - GAPM_DBG_GET_MEM_INFO: Get memory usage (debug only) + uint8_t operation; +}; + +/// Local device version indication event +struct gapm_dev_version_ind +{ + /// HCI version + uint8_t hci_ver; + /// LMP version + uint8_t lmp_ver; + /// Host version + uint8_t host_ver; + /// HCI revision + uint16_t hci_subver; + /// LMP subversion + uint16_t lmp_subver; + /// Host revision + uint16_t host_subver; + /// Manufacturer name + uint16_t manuf_name; +}; + +/// Local device BD Address indication event +struct gapm_dev_bdaddr_ind +{ + /// Local device address information + struct gap_bdaddr addr; +}; + +/// Advertising channel Tx power level indication event +struct gapm_dev_adv_tx_power_ind +{ + /// Advertising channel Tx power level + int8_t power_lvl; +}; + +/// Cancel ongoing operation +struct gapm_cancel_cmd +{ + /// GAPM requested operation + /// - GAPM_CANCEL: Cancel running operation + uint8_t operation; +}; + + +/// White List Management Command +struct gapm_white_list_mgt_cmd +{ + /// GAPM requested operation: + /// - GAPM_GET_WLIST_SIZE: Get White List Size. + /// - GAPM_ADD_DEV_IN_WLIST: Add devices in white list. + /// - GAPM_RMV_DEV_FRM_WLIST: Remove devices form white list. + /// - GAPM_CLEAR_WLIST: Clear all devices from white list. + uint8_t operation; + /// Number of device information present in command + uint8_t nb; + /// Device address information that can be used to add or remove element in device list. + struct gap_bdaddr devices[__ARRAY_EMPTY]; +}; + +/// White List Size indication event +struct gapm_white_list_size_ind +{ + /// White List size + uint8_t size; +}; + +/// Resolving List Management Command +struct gapm_ral_mgt_cmd +{ + /// GAPM requested operation: + /// - GAPM_GET_RAL_SIZE: Get Resolving List Size. + /// - GAPM_GET_RAL_LOC_ADDR: Get Resolving Local Address. + /// - GAPM_GET_RAL_PEER_ADDR: Get Resolving Peer Address. + /// - GAPM_ADD_DEV_IN_RAL: Add devices in resolving list. + /// - GAPM_RMV_DEV_FRM_RAL: Remove devices form resolving list. + /// - GAPM_CLEAR_RAL: Clear all devices from resolving list. + uint8_t operation; + /// Number of device information present in command + uint8_t nb; + /// Device address information that can be used to add or remove element in device list. + struct gap_ral_dev_info devices[__ARRAY_EMPTY]; +}; + +/// Resolving List Size indication event +struct gapm_ral_size_ind +{ + /// Resolving List size + uint8_t size; +}; + +/// Resolving Address indication event +struct gapm_ral_addr_ind +{ + /// Peer or local read operation + uint8_t operation; + /// Resolving List address + struct gap_bdaddr addr; +}; + +/// Resolve Address command +struct gapm_resolv_addr_cmd +{ + /// GAPM requested operation: + /// - GAPM_RESOLV_ADDR: Resolve device address + uint8_t operation; + /// Number of provided IRK (sahlle be > 0) + uint8_t nb_key; + /// Resolvable random address to solve + bd_addr_t addr; + /// Array of IRK used for address resolution (MSB -> LSB) + struct gap_sec_key irk[__ARRAY_EMPTY]; +}; + + +/// Indicate that resolvable random address has been solved +struct gapm_addr_solved_ind +{ + /// Resolvable random address solved + bd_addr_t addr; + /// IRK that correctly solved the random address + struct gap_sec_key irk; +}; + + +/// Advertising data that contains information set by host. +struct gapm_adv_host +{ + /// Advertising mode : + /// - GAP_NON_DISCOVERABLE: Non discoverable mode + /// - GAP_GEN_DISCOVERABLE: General discoverable mode + /// - GAP_LIM_DISCOVERABLE: Limited discoverable mode + /// - GAP_BROADCASTER_MODE: Broadcaster mode + uint8_t mode; + + /// Advertising filter policy: + /// - ADV_ALLOW_SCAN_ANY_CON_ANY: Allow both scan and connection requests from anyone + /// - ADV_ALLOW_SCAN_WLST_CON_ANY: Allow both scan req from White List devices only and + /// connection req from anyone + /// - ADV_ALLOW_SCAN_ANY_CON_WLST: Allow both scan req from anyone and connection req + /// from White List devices only + /// - ADV_ALLOW_SCAN_WLST_CON_WLST: Allow scan and connection requests from White List + /// devices only + uint8_t adv_filt_policy; + + /// Advertising data length - maximum 28 bytes, 3 bytes are reserved to set + /// Advertising AD type flags, shall not be set in advertising data + uint8_t adv_data_len; + /// Advertising data + uint8_t adv_data[GAP_ADV_DATA_LEN]; + /// Scan response data length- maximum 31 bytes + uint8_t scan_rsp_data_len; + /// Scan response data + uint8_t scan_rsp_data[GAP_SCAN_RSP_DATA_LEN]; + /// Peer address + struct gap_bdaddr peer_addr; +}; + +/// Air operation default parameters +struct gapm_air_operation +{ + /// Operation code. + uint8_t code; + + /** + * Own BD address source of the device: + * - GAPM_STATIC_ADDR: Public or Private Static Address according to device address configuration + * - GAPM_GEN_RSLV_ADDR: Generated resolvable private random address + * - GAPM_GEN_NON_RSLV_ADDR: Generated non-resolvable private random address + */ + uint8_t addr_src; + + /// Dummy data use to retrieve internal operation state (should be set to 0). + uint16_t state; +}; + + +/// Set advertising mode Command +struct gapm_start_advertise_cmd +{ + /// GAPM requested operation: + /// - GAPM_ADV_NON_CONN: Start non connectable advertising + /// - GAPM_ADV_UNDIRECT: Start undirected connectable advertising + /// - GAPM_ADV_DIRECT: Start directed connectable advertising + /// - GAPM_ADV_DIRECT_LDC: Start directed connectable advertising using Low Duty Cycle + struct gapm_air_operation op; + + /// Minimum interval for advertising + uint16_t intv_min; + /// Maximum interval for advertising + uint16_t intv_max; + + ///Advertising channel map + uint8_t channel_map; + + /// Advertising information + union gapm_adv_info + { + /// Host information advertising data (GAPM_ADV_NON_CONN and GAPM_ADV_UNDIRECT) + struct gapm_adv_host host; + /// Direct address information (GAPM_ADV_DIRECT) + /// (used only if reconnection address isn't set or privacy disabled) + struct gap_bdaddr direct; + } info; +}; + + +/// Update Advertising Data Command - On fly update when device is advertising +struct gapm_update_advertise_data_cmd +{ + /// GAPM requested operation: + /// - GAPM_UPDATE_ADVERTISE_DATA: Update on the fly advertising data + uint8_t operation; + /// Advertising data length - maximum 28 bytes, 3 bytes are reserved to set + /// Advertising AD type flags, shall not be set in advertising data + uint8_t adv_data_len; + /// Advertising data + uint8_t adv_data[GAP_ADV_DATA_LEN]; + /// Scan response data length- maximum 31 bytes + uint8_t scan_rsp_data_len; + /// Scan response data + uint8_t scan_rsp_data[GAP_SCAN_RSP_DATA_LEN]; +}; + +/// Set scan mode Command +struct gapm_start_scan_cmd +{ + /// GAPM requested operation: + /// - GAPM_SCAN_ACTIVE: Start active scan operation + /// - GAPM_SCAN_PASSIVE: Start passive scan operation + struct gapm_air_operation op; + + /// Scan interval + uint16_t interval; + /// Scan window size + uint16_t window; + + /// Scanning mode : + /// - GAP_GEN_DISCOVERY: General discovery mode + /// - GAP_LIM_DISCOVERY: Limited discovery mode + /// - GAP_OBSERVER_MODE: Observer mode + uint8_t mode; + + /// Scan filter policy: + /// - SCAN_ALLOW_ADV_ALL: Allow advertising packets from anyone + /// - SCAN_ALLOW_ADV_WLST: Allow advertising packets from White List devices only + uint8_t filt_policy; + /// Scan duplicate filtering policy: + /// - SCAN_FILT_DUPLIC_DIS: Disable filtering of duplicate packets + /// - SCAN_FILT_DUPLIC_EN: Enable filtering of duplicate packets + uint8_t filter_duplic; + + ///Scanning channel map, add by hengzhang for fixed channel scan + uint8_t channel_map; +}; + + +/// Advertising or scanning report information event +struct gapm_adv_report_ind +{ + /// Advertising report structure + adv_report_t report; +}; + + +/// Set connection initialization Command +struct gapm_start_connection_cmd +{ + /// GAPM requested operation: + /// - GAPM_CONNECTION_DIRECT: Direct connection operation + /// - GAPM_CONNECTION_AUTO: Automatic connection operation + /// - GAPM_CONNECTION_SELECTIVE: Selective connection operation + /// - GAPM_CONNECTION_NAME_REQUEST: Name Request operation (requires to start a direct + /// connection) + /// - GAPM_CONNECTION_GENERAL: General connection operation + struct gapm_air_operation op; + + /// Scan interval + uint16_t scan_interval; + /// Scan window size + uint16_t scan_window; + + /// Minimum of connection interval + uint16_t con_intv_min; + /// Maximum of connection interval + uint16_t con_intv_max; + /// Connection latency + uint16_t con_latency; + /// Link supervision timeout + uint16_t superv_to; + /// Minimum CE length + uint16_t ce_len_min; + /// Maximum CE length + uint16_t ce_len_max; + + /// Number of peer device information present in message. + /// Shall be 1 for GAPM_CONNECTION_DIRECT or GAPM_CONNECTION_NAME_REQUEST operations + /// Shall be greater than 0 for other operations + uint8_t nb_peers; + + /// Peer device information + struct gap_bdaddr peers[__ARRAY_EMPTY]; +}; + + +/// Name of peer device indication +struct gapm_peer_name_ind +{ + /// peer device bd address + bd_addr_t addr; + /// peer device address type + uint8_t addr_type; + /// peer device name length + uint8_t name_len; + /// peer device name + uint8_t name[__ARRAY_EMPTY]; +}; + +/// Confirm connection to a specific device (Connection Operation in Selective mode) +struct gapm_connection_cfm +{ + /// peer device bd address + bd_addr_t addr; + /// peer device address type + uint8_t addr_type; + + /// Minimum of connection interval + uint16_t con_intv_min; + /// Maximum of connection interval + uint16_t con_intv_max; + /// Connection latency + uint16_t con_latency; + /// Link supervision timeout + uint16_t superv_to; + /// Minimum CE length + uint16_t ce_len_min; + /// Maximum CE length + uint16_t ce_len_max; +}; + +/// Generate a random address. +struct gapm_gen_rand_addr_cmd +{ + /// GAPM requested operation: + /// - GAPM_GEN_RAND_ADDR: Generate a random address + uint8_t operation; + /// Dummy parameter used to store the prand part of the address + uint8_t prand[GAP_ADDR_PRAND_LEN]; + /// Random address type @see gap_rnd_addr_type + /// - GAP_STATIC_ADDR: Static random address + /// - GAP_NON_RSLV_ADDR: Private non resolvable address + /// - GAP_RSLV_ADDR: Private resolvable address + uint8_t rnd_type; +}; + +/// Parameters of the @ref GAPM_USE_ENC_BLOCK_CMD message +struct gapm_use_enc_block_cmd +{ + /// Command Operation Code (shall be GAPM_USE_ENC_BLOCK) + uint8_t operation; + /// Operand 1 + uint8_t operand_1[GAP_KEY_LEN]; + /// Operand 2 + uint8_t operand_2[GAP_KEY_LEN]; +}; + +/// Parameters of the @ref GAPM_USE_ENC_BLOCK_IND message +struct gapm_use_enc_block_ind +{ + /// Result (16 bytes) + uint8_t result[GAP_KEY_LEN]; +}; + +/// Parameters of the @ref GAPM_GEN_DH_KEY_CMD message +struct gapm_gen_dh_key_cmd +{ + /// Command Operation Code (shall be GAPM_GEN_DH_KEY) + uint8_t operation; + /// X coordinate + uint8_t operand_1[GAP_P256_KEY_LEN]; + /// Y coordinate + uint8_t operand_2[GAP_P256_KEY_LEN]; +}; + +/// Parameters of the @ref GAPM_GEN_DH_KEY_IND message +struct gapm_gen_dh_key_ind +{ + /// Result (32 bytes) + uint8_t result[GAP_P256_KEY_LEN]; + uint8_t status; +}; + +/// Parameters of the @ref GAPM_GET_PUB_KEY_CMD message +struct gapm_get_key_cmd +{ + /// Command Operation Code (shall be GAPM_GET_PUB_KEY) + uint8_t operation; + /// 1 to renew, 0 to read current value + uint8_t renew; +}; + +/// Parameters of the @ref GAPM_GET_KEY_IND message +struct gapm_get_key_ind +{ + uint8_t pri_key[GAP_P256_KEY_LEN]; + /// X coordinate + uint8_t pub_key_x[GAP_P256_KEY_LEN]; + /// Y coordinate + uint8_t pub_key_y[GAP_P256_KEY_LEN]; +}; + +/// Parameters of the @ref GAPM_GEN_RAND_NB_CMD message +struct gapm_gen_rand_nb_cmd +{ + /// Command Operation Code (shall be GAPM_GEN_RAND_NB) + uint8_t operation; +}; + +/// Parameters of the @ref GAPM_GEN_RAND_NB_IND message +struct gapm_gen_rand_nb_ind +{ + /// Generation Random Number (8 bytes) + rand_nb_t randnb; +}; + + + +/// Create new task for specific profile +struct gapm_profile_task_add_cmd +{ + /// GAPM requested operation: + /// - GAPM_PROFILE_TASK_ADD: Add new profile task + uint8_t operation; + /// Security Level : + /// 7 6 5 4 3 2 1 0 + /// +----+----+----+----+----+----+----+----+ + /// | Reserved |DIS | AUTH |EKS | MI | + /// +----+----+----+----+----+----+----+----+ + /// + /// - MI: 1 - Application task is a Multi-Instantiated task, 0 - Mono-Instantiated + /// Only applies for service - Ignored by collectors: + /// - EKS: Service needs a 16 bytes encryption key + /// - AUTH: 0 - Disable, 1 - Enable, 2 - Unauth, 3 - Auth + /// - DIS: Disable the service + uint8_t sec_lvl; + /// Profile task identifier + uint16_t prf_task_id; + /// Application task number + uint16_t app_task; + /// Service start handle + /// Only applies for services - Ignored by collectors + /// 0: dynamically allocated in Attribute database + uint16_t start_hdl; + /// 32 bits value that contains value to initialize profile (database parameters, etc...) + uint32_t param[__ARRAY_EMPTY]; +}; + + +/// Inform that profile task has been added. +struct gapm_profile_added_ind +{ + /// Profile task identifier + uint16_t prf_task_id; + /// Profile task number allocated + uint16_t prf_task_nb; + /// Service start handle + /// Only applies for services - Ignored by collectors + uint16_t start_hdl; +}; + +/// Indicate that a message has been received on an unknown task +struct gapm_unknown_task_ind +{ + /// Message identifier + uint16_t msg_id; + /// Task identifier + uint16_t task_id; +}; + +/// Indicates suggested default data length +struct gapm_sugg_dflt_data_len_ind +{ + ///Host's suggested value for the Controller's maximum transmitted number of payload octets + uint16_t suggted_max_tx_octets; + ///Host's suggested value for the Controller's maximum packet transmission time + uint16_t suggted_max_tx_time; +}; + +/// Indicates maximum data length +struct gapm_max_data_len_ind +{ + ///Maximum number of payload octets that the local Controller supports for transmission + uint16_t suppted_max_tx_octets; + ///Maximum time, in microseconds, that the local Controller supports for transmission + uint16_t suppted_max_tx_time; + ///Maximum number of payload octets that the local Controller supports for reception + uint16_t suppted_max_rx_octets; + ///Maximum time, in microseconds, that the local Controller supports for reception + uint16_t suppted_max_rx_time; +}; + + +/// Register a LE Protocol/Service Multiplexer command +struct gapm_lepsm_register_cmd +{ + /// GAPM requested operation: + /// - GAPM_LEPSM_REG: Register a LE Protocol/Service Multiplexer + uint8_t operation; + /// LE Protocol/Service Multiplexer + uint16_t le_psm; + /// Application task number + uint16_t app_task; + /// Security level + /// 7 6 5 4 3 2 1 0 + /// +---+---+---+---+---+---+---+---+ + /// |MI | RFU |EKS|SEC_LVL| + /// +---+---+---+---+---+---+---+---+ + /// bit[0-1]: Security level requirement (0=NO_AUTH, 1=UNAUTH, 2=AUTH, 3=SEC_CON) + /// bit[2] : Encryption Key Size length must have 16 bytes + /// bit[7] : Does the application task is multi-instantiated or not + uint8_t sec_lvl; +}; + + +/// Unregister a LE Protocol/Service Multiplexer command +struct gapm_lepsm_unregister_cmd +{ + /// GAPM requested operation: + /// - GAPM_LEPSM_UNREG: Unregister a LE Protocol/Service Multiplexer + uint8_t operation; + /// LE Protocol/Service Multiplexer + uint16_t le_psm; +}; + +/// Control LE Test Mode command +struct gapm_le_test_mode_ctrl_cmd +{ + /// GAPM requested operation: + /// - GAPM_LE_TEST_STOP: Unregister a LE Protocol/Service Multiplexer + /// - GAPM_LE_TEST_RX_START: Start RX Test Mode + /// - GAPM_LE_TEST_TX_START: Start TX Test Mode + uint8_t operation; + /// Tx or Rx Channel (Range 0x00 to 0x27) + uint8_t channel; + /// Length in bytes of payload data in each packet (only valid for TX mode, range 0x00-0xFF) + uint8_t tx_data_length; + /// Packet Payload type (only valid for TX mode @see enum gap_pkt_pld_type) + uint8_t tx_pkt_payload; + /// PHY rate (@see enum gap_rate) + uint8_t phy; + /// Modulation Index (only valid for RX mode @see enum gap_modulation_idx) + uint8_t modulation_idx; +}; + +/// Indicate end of test mode event +struct gapm_le_test_end_ind +{ + /// Number of received packets + uint16_t nb_packet_received; +}; + +/* + * MACROS + **************************************************************************************** + */ + + +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + + +/// @} GAPM_TASK + +#endif /* _GAPM_TASK_H_ */ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/api/gattc_task.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/api/gattc_task.h new file mode 100755 index 0000000..0c809f2 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/api/gattc_task.h @@ -0,0 +1,721 @@ +/** + **************************************************************************************** + * + * @file gattc_task.h + * + * @brief Header file - GATTCTASK. + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + +#ifndef GATTC_TASK_H_ +#define GATTC_TASK_H_ + +/** + **************************************************************************************** + * @addtogroup GATTCTASK Task + * @ingroup GATTC + * @brief Handles ALL messages to/from GATT Controller block. + * + * The GATTCTASK is responsible for managing the messages coming from + * the attribute layer and host-level layers for dedicated connection. + * The task includes services and characteristic discovery, configuration exchanges + * and attribute value access operations (reading, writing, notification and indication). + * + * Messages may originate from @ref ATTC "ATTC", @ref ATTS "ATTS", @ref GAP "GAP" + * and Application. + * + * @{ + **************************************************************************************** + */ +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "att.h" +#include "rwip_task.h" // Task definitions +#include "ble_compiler.h" +#include +/* + * DEFINES + **************************************************************************************** + */ + +/// GATT Task messages +enum gattc_msg_id +{ + /* Default event */ + /// Command Complete event + GATTC_CMP_EVT = TASK_FIRST_MSG(TASK_ID_GATTC), + + /* ATTRIBUTE CLIENT */ + /// Server configuration request + GATTC_EXC_MTU_CMD, + /// Indicate that the ATT MTU has been updated (negotiated) + GATTC_MTU_CHANGED_IND, + + /*Discover All Services */ + /*Discover Services by Service UUID*/ + /*Find Included Services*/ + /*Discover Characteristics by UUID*/ + /*Discover All Characteristics of a Service*/ + /*Discover All Characteristic Descriptors*/ + /// Discovery command + GATTC_DISC_CMD, + /* GATT -> HL: Events to Upper layer */ + /*Discover All Services*/ + /// Discovery services indication + GATTC_DISC_SVC_IND, + /*Find Included Services*/ + /// Discover included services indication + GATTC_DISC_SVC_INCL_IND, + /*Discover All Characteristics of a Service*/ + /// Discover characteristic indication + GATTC_DISC_CHAR_IND, + /*Discover All Characteristic Descriptors*/ + /// Discovery characteristic descriptor indication + GATTC_DISC_CHAR_DESC_IND, + + /*Read Value*/ + /*Read Using UUID*/ + /*Read Long Value*/ + /*Read Multiple Values*/ + /// Read command + GATTC_READ_CMD, + /// Read response + GATTC_READ_IND, + + /*Write without response*/ + /*Write without response with Authentication*/ + /*Write Characteristic Value*/ + /*Signed Write Characteristic Value*/ + /*Write Long Characteristic Value*/ + /*Characteristic Value Reliable Write*/ + /*Write Characteristic Descriptors*/ + /*Write Long Characteristic Descriptors*/ + /*Characteristic Value Reliable Write*/ + /// Write command request + GATTC_WRITE_CMD, + + /* Cancel / Execute pending write operations */ + /// Execute write characteristic request + GATTC_EXECUTE_WRITE_CMD, + + /* Reception of an indication or notification from peer device. */ + /// peer device triggers an event (notification) + GATTC_EVENT_IND, + /// peer device triggers an event that requires a confirmation (indication) + GATTC_EVENT_REQ_IND, + /// Confirm reception of event (trigger a confirmation message) + GATTC_EVENT_CFM, + + /// Registration to peer device events (Indication/Notification). + GATTC_REG_TO_PEER_EVT_CMD, + + /* -------------------------- ATTRIBUTE SERVER ------------------------------- */ + /*Notify Characteristic*/ + /*Indicate Characteristic*/ + /// send an event to peer device + GATTC_SEND_EVT_CMD, + + /* Service Changed Characteristic Indication */ + /** + * Send a Service Changed indication to a device + * (message structure is struct gattm_svc_changed_ind_req) + */ + GATTC_SEND_SVC_CHANGED_CMD, + /** + * Inform the application when sending of Service Changed indications has been + * enabled or disabled + */ + GATTC_SVC_CHANGED_CFG_IND, + + /* Indicate that read operation is requested. */ + /// Read command indicated to upper layers. + GATTC_READ_REQ_IND, + /// REad command confirmation from upper layers. + GATTC_READ_CFM, + + /* Indicate that write operation is requested. */ + /// Write command indicated to upper layers. + GATTC_WRITE_REQ_IND, + /// Write command confirmation from upper layers. + GATTC_WRITE_CFM, + + /* Indicate that write operation is requested. */ + /// Request Attribute info to upper layer - could be trigger during prepare write + GATTC_ATT_INFO_REQ_IND, + /// Attribute info from upper layer confirmation + GATTC_ATT_INFO_CFM, + + /* ----------------------- SERVICE DISCOVERY PROCEDURE --------------------------- */ + /// Service Discovery command + GATTC_SDP_SVC_DISC_CMD, + /// Service Discovery indicate that a service has been found. + GATTC_SDP_SVC_IND, + + /* -------------------------- TRANSACTION ERROR EVENT ----------------------------- */ + /// Transaction Timeout Error Event no more transaction will be accepted + GATTC_TRANSACTION_TO_ERROR_IND, + + /* ------------------------------- Internal API ----------------------------------- */ + /// Client Response timeout indication + GATTC_CLIENT_RTX_IND, + /// Server indication confirmation timeout indication + GATTC_SERVER_RTX_IND, +}; + + +/// request operation type - application interface +enum gattc_operation +{ + /* Attribute Client Flags */ + /* No Operation (if nothing has been requested) */ + /* ************************************************ */ + /// No operation + GATTC_NO_OP = 0x00, + + /* Operation flags for MTU Exchange */ + /* ************************************************ */ + /// Perform MTU exchange + GATTC_MTU_EXCH, + + /* Operation flags for discovery operation */ + /* ************************************************ */ + /// Discover all services + GATTC_DISC_ALL_SVC, + /// Discover services by UUID + GATTC_DISC_BY_UUID_SVC, + /// Discover included services + GATTC_DISC_INCLUDED_SVC, + /// Discover all characteristics + GATTC_DISC_ALL_CHAR, + /// Discover characteristic by UUID + GATTC_DISC_BY_UUID_CHAR, + /// Discover characteristic descriptor + GATTC_DISC_DESC_CHAR, + + /* Operation flags for reading attributes */ + /* ************************************************ */ + /// Read attribute + GATTC_READ, + /// Read long attribute + GATTC_READ_LONG, + /// Read attribute by UUID + GATTC_READ_BY_UUID, + /// Read multiple attribute + GATTC_READ_MULTIPLE, + + /* Operation flags for writing/modifying attributes */ + /* ************************************************ */ + /// Write attribute + GATTC_WRITE, + /// Write no response + GATTC_WRITE_NO_RESPONSE, + /// Write signed + GATTC_WRITE_SIGNED, + /// Execute write + GATTC_EXEC_WRITE, + + /* Operation flags for registering to peer device */ + /* events */ + /* ************************************************ */ + /// Register to peer device events + GATTC_REGISTER, + /// Unregister from peer device events + GATTC_UNREGISTER, + + /* Operation flags for sending events to peer device*/ + /* ************************************************ */ + /// Send an attribute notification + GATTC_NOTIFY, + /// Send an attribute indication + GATTC_INDICATE, + /// Send a service changed indication + GATTC_SVC_CHANGED, + + /* Service Discovery Procedure */ + /* ************************************************ */ + /// Search specific service + GATTC_SDP_DISC_SVC, + /// Search for all services + GATTC_SDP_DISC_SVC_ALL, + /// Cancel Service Discovery Procedure + GATTC_SDP_DISC_CANCEL, +}; + +/// Service Discovery Attribute type +enum gattc_sdp_att_type +{ + /// No Attribute Information + GATTC_SDP_NONE, + /// Included Service Information + GATTC_SDP_INC_SVC, + /// Characteristic Declaration + GATTC_SDP_ATT_CHAR, + /// Attribute Value + GATTC_SDP_ATT_VAL, + /// Attribute Descriptor + GATTC_SDP_ATT_DESC, +}; + +/// Command complete event data structure +struct gattc_op_cmd +{ + /// GATT request type + uint8_t operation; + /// operation sequence number + uint16_t seq_num; +}; + +/// Command complete event data structure +struct gattc_cmp_evt +{ + /// GATT request type + uint8_t operation; + /// Status of the request + uint8_t status; + /// operation sequence number - provided when operation is started + uint16_t seq_num; +}; + + +/// Service Discovery Command Structure +struct gattc_exc_mtu_cmd +{ + /// GATT request type + uint8_t operation; + /// operation sequence number + uint16_t seq_num; +}; + +/// Indicate that the ATT MTU has been updated (negotiated) +struct gattc_mtu_changed_ind +{ + /// Exchanged MTU value + uint16_t mtu; + /// operation sequence number + uint16_t seq_num; +}; + +/// Service Discovery Command Structure +struct gattc_disc_cmd +{ + /// GATT request type + uint8_t operation; + /// UUID length + uint8_t uuid_len; + /// operation sequence number + uint16_t seq_num; + /// start handle range + uint16_t start_hdl; + /// start handle range + uint16_t end_hdl; + /// UUID + uint8_t uuid[__ARRAY_EMPTY]; +}; + + +/// Discover Service indication Structure +struct gattc_disc_svc_ind +{ + /// start handle + uint16_t start_hdl; + /// end handle + uint16_t end_hdl; + /// UUID length + uint8_t uuid_len; + /// service UUID + uint8_t uuid[__ARRAY_EMPTY]; +}; + +/// Discover Service indication Structure +struct gattc_disc_svc_incl_ind +{ + /// element handle + uint16_t attr_hdl; + /// start handle + uint16_t start_hdl; + /// end handle + uint16_t end_hdl; + /// UUID length + uint8_t uuid_len; + /// included service UUID + uint8_t uuid[__ARRAY_EMPTY]; +}; + +/// Discovery All Characteristic indication Structure +struct gattc_disc_char_ind +{ + /// database element handle + uint16_t attr_hdl; + /// pointer attribute handle to UUID + uint16_t pointer_hdl; + /// properties + uint8_t prop; + /// UUID length + uint8_t uuid_len; + /// characteristic UUID + uint8_t uuid[__ARRAY_EMPTY]; +}; + +/// Discovery Characteristic Descriptor indication Structure +struct gattc_disc_char_desc_ind +{ + /// database element handle + uint16_t attr_hdl; + /// UUID length + uint8_t uuid_len; + /// Descriptor UUID + uint8_t uuid[__ARRAY_EMPTY]; +}; + + +/// Simple Read (GATTC_READ or GATTC_READ_LONG) +struct gattc_read_simple +{ + /// attribute handle + uint16_t handle; + /// start offset in data payload + uint16_t offset; + /// Length of data to read (0 = read all) + uint16_t length; +}; + +/// Read by UUID: search UUID and read it's characteristic value (GATTC_READ_BY_UUID) +/// Note: it doesn't perform an automatic read long. +struct gattc_read_by_uuid +{ + /// Start handle + uint16_t start_hdl; + /// End handle + uint16_t end_hdl; + /// Size of UUID + uint8_t uuid_len; + /// UUID value + uint8_t uuid[__ARRAY_EMPTY]; +}; + +/// Read Multiple short characteristic (GATTC_READ_MULTIPLE) +struct gattc_read_multiple +{ + /// attribute handle + uint16_t handle; + /// Known Handle length (shall be != 0) + uint16_t len; +}; + +/// Read command (Simple, Long, Multiple, or by UUID) +struct gattc_read_cmd +{ + /// request type + uint8_t operation; + /// number of read (only used for multiple read) + uint8_t nb; + /// operation sequence number + uint16_t seq_num; + + /// request union according to read type + union gattc_read_req + { + /// Simple Read (GATTC_READ or GATTC_READ_LONG) + struct gattc_read_simple simple; + /// Read by UUID (GATTC_READ_BY_UUID) + struct gattc_read_by_uuid by_uuid; + /// Read Multiple short characteristic (GATTC_READ_MULTIPLE) + struct gattc_read_multiple multiple[1]; + } req; +}; + +/// Attribute value read indication +struct gattc_read_ind +{ + /// Attribute handle + uint16_t handle; + /// Read offset + uint16_t offset; + /// Read length + uint16_t length; + /// Handle value + uint8_t value[__ARRAY_EMPTY]; +}; + +/// Write peer attribute value command +struct gattc_write_cmd +{ + /// Request type + uint8_t operation; + /// Perform automatic execution + /// (if false, an ATT Prepare Write will be used this shall be use for reliable write) + bool auto_execute; + /// operation sequence number + uint16_t seq_num; + /// Attribute handle + uint16_t handle; + /// Write offset + uint16_t offset; + /// Write length + uint16_t length; + /// Internal write cursor shall be initialized to 0 + uint16_t cursor; + /// Value to write + uint8_t value[__ARRAY_EMPTY]; +}; + +/// Write peer attribute value command +struct gattc_execute_write_cmd +{ + /// Request type + uint8_t operation; + + /// [True = perform/False cancel] pending write operations + bool execute; + /// operation sequence number + uint16_t seq_num; +}; +/// peer device triggers an event (notification) +struct gattc_event_ind +{ + /// Event Type + uint8_t type; + /// Data length + uint16_t length; + /// Attribute handle + uint16_t handle; + /// Event Value + uint8_t value[__ARRAY_EMPTY]; +}; + +/// peer device triggers an event that requires a confirmation (indication) +struct gattc_event_req_ind +{ + /// Event Type + uint8_t type; + /// Data length + uint16_t length; + /// Attribute handle + uint16_t handle; + /// Event Value + uint8_t value[__ARRAY_EMPTY]; +}; + +/// Confirm reception of event (trigger a confirmation message) +struct gattc_event_cfm +{ + /// Attribute handle + uint16_t handle; +}; + +/// Register to peer device events command +struct gattc_reg_to_peer_evt_cmd +{ + /// Request type + uint8_t operation; + /// operation sequence number + uint16_t seq_num; + /// attribute start handle + uint16_t start_hdl; + /// attribute end handle + uint16_t end_hdl; +}; + +/// Send an event to peer device +struct gattc_send_evt_cmd +{ + /// Request type (notification / indication) + uint8_t operation; + /// operation sequence number + uint16_t seq_num; + /// characteristic handle + uint16_t handle; + /// length of packet to send + uint16_t length; + /// data value + uint8_t value[__ARRAY_EMPTY]; +}; + +/// Inform that attribute value is requested by lower layers. +struct gattc_read_req_ind +{ + /// Handle of the attribute that has to be read + uint16_t handle; +}; + +/// Confirm Read Request requested by GATT to profile +struct gattc_read_cfm +{ + /// Handle of the attribute read + uint16_t handle; + /// Data length read + uint16_t length; + /// Status of read command execution by upper layers + uint8_t status; + /// attribute data value + uint8_t value[__ARRAY_EMPTY]; +}; + +/// Inform that a modification of database has been requested by peer device. +struct gattc_write_req_ind +{ + /// Handle of the attribute that has to be written + uint16_t handle; + /// offset at which the data has to be written + uint16_t offset; + /// Data length to be written + uint16_t length; + /// Data to be written in attribute database + uint8_t value[__ARRAY_EMPTY]; +}; + +/// Confirm modification of database from upper layer when requested by peer device. +struct gattc_write_cfm +{ + /// Handle of the attribute written + uint16_t handle; + /// Status of write command execution by upper layers + uint8_t status; +}; + +/// Parameters for @ref GATTC_SEND_SVC_CHANGED_CMD message +struct gattc_send_svc_changed_cmd +{ + /// Request Type + uint8_t operation; + /// operation sequence number + uint16_t seq_num; + /// Start of Affected Attribute Handle Range + uint16_t svc_shdl; + /// End of Affected Attribute Handle Range + uint16_t svc_ehdl; +}; + +/// Parameters for @ref GATTC_SVC_CHANGED_CFG_IND and @ref GATTC_SVC_CHANGED_SET_CFG_REQ message +struct gattc_svc_changed_cfg +{ + /** + * Current value of the Client Characteristic Configuration descriptor for the Service + * Changed characteristic + */ + uint16_t ind_cfg; +}; + + +/// Request Attribute info to upper layer - could be trigger during prepare write +struct gattc_att_info_req_ind +{ + /// Handle of the attribute for which info are requested + uint16_t handle; +}; + +/// Attribute info from upper layer confirmation +struct gattc_att_info_cfm +{ + /// Handle of the attribute + uint16_t handle; + /// Current length of the attribute + uint16_t length; + /// use to know if it's possible to modify the attribute + /// can contains authorization or application error code. + uint8_t status; +}; + + +/// Service Discovery command +struct gattc_sdp_svc_disc_cmd +{ + /// GATT Request Type + /// - GATTC_SDP_DISC_SVC Search specific service + /// - GATTC_SDP_DISC_SVC_ALL Search for all services + /// - GATTC_SDP_DISC_CANCEL Cancel Service Discovery Procedure + uint8_t operation; + /// Service UUID Length + uint8_t uuid_len; + /// operation sequence number + uint16_t seq_num; + /// Search start handle + uint16_t start_hdl; + /// Search end handle + uint16_t end_hdl; + /// Service UUID + uint8_t uuid[ATT_UUID_128_LEN]; +}; + + +/// Information about included service +struct gattc_sdp_include_svc +{ + /// Attribute Type + /// - GATTC_SDP_INC_SVC: Included Service Information + uint8_t att_type; + /// Included service UUID Length + uint8_t uuid_len; + /// Included Service UUID + uint8_t uuid[ATT_UUID_128_LEN]; + /// Included service Start Handle + uint16_t start_hdl; + /// Included service End Handle + uint16_t end_hdl; +}; + +/// Information about attribute characteristic +struct gattc_sdp_att_char +{ + /// Attribute Type + /// - GATTC_SDP_ATT_CHAR: Characteristic Declaration + uint8_t att_type; + /// Value property + uint8_t prop; + /// Value Handle + uint16_t handle; +}; + +/// Information about attribute +struct gattc_sdp_att +{ + /// Attribute Type + /// - GATTC_SDP_ATT_VAL: Attribute Value + /// - GATTC_SDP_ATT_DESC: Attribute Descriptor + uint8_t att_type; + /// Attribute UUID Length + uint8_t uuid_len; + /// Attribute UUID + uint8_t uuid[ATT_UUID_128_LEN]; +}; + +/// Attribute information +union gattc_sdp_att_info +{ + /// Attribute Type + uint8_t att_type; + /// Information about attribute characteristic + struct gattc_sdp_att_char att_char; + /// Information about included service + struct gattc_sdp_include_svc inc_svc; + /// Information about attribute + struct gattc_sdp_att att; +}; + + +/// Service Discovery indicate that a service has been found. +struct gattc_sdp_svc_ind +{ + /// Service UUID Length + uint8_t uuid_len; + /// Service UUID + uint8_t uuid[ATT_UUID_128_LEN]; + /// Service start handle + uint16_t start_hdl; + /// Service end handle + uint16_t end_hdl; + /// attribute information present in the service + /// (length = end_hdl - start_hdl) + union gattc_sdp_att_info info[__ARRAY_EMPTY]; +}; + + + +/// @} GATTCTASK +#endif // GATTC_TASK_H_ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/api/gattm_task.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/api/gattm_task.h new file mode 100755 index 0000000..eb00bac --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/api/gattm_task.h @@ -0,0 +1,388 @@ +/** + **************************************************************************************** + * + * @file gattm_task.h + * + * @brief Header file - GATTMTASK. + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + +#ifndef GATTM_TASK_H_ +#define GATTM_TASK_H_ + +/** + **************************************************************************************** + * @addtogroup GATTMTASK Task + * @ingroup GATTM + * @brief Handles ALL GATT block operations not related to a connection. + * + * The GATTMTASK is responsible for managing internal attribute database and state of + * GATT controller which manage GATT block operations related to a connection. + * + * Messages may originate from @ref ATTM "ATTM", @ref GAP "GAP" and Application. + * + * @{ + **************************************************************************************** + */ +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_task.h" // Task definitions +#include "att.h" + +/* + * DEFINES + **************************************************************************************** + */ + + +/// GATT Task messages +enum gattm_msg_id +{ + /* Database Management */ + /// Add service in database request + GATTM_ADD_SVC_REQ = TASK_FIRST_MSG(TASK_ID_GATTM), + /// Add service in database response + GATTM_ADD_SVC_RSP, + + /* Service management */ + /// Get permission settings of service request + GATTM_SVC_GET_PERMISSION_REQ, + /// Get permission settings of service response + GATTM_SVC_GET_PERMISSION_RSP, + /// Set permission settings of service request + GATTM_SVC_SET_PERMISSION_REQ, + /// Set permission settings of service response + GATTM_SVC_SET_PERMISSION_RSP, + + /* Attribute Manipulation */ + /// Get permission settings of attribute request + GATTM_ATT_GET_PERMISSION_REQ, + /// Get permission settings of attribute response + GATTM_ATT_GET_PERMISSION_RSP, + /// Set permission settings of attribute request + GATTM_ATT_SET_PERMISSION_REQ, + /// Set permission settings of attribute response + GATTM_ATT_SET_PERMISSION_RSP, + + /// Get attribute value request + GATTM_ATT_GET_VALUE_REQ, + /// Get attribute value response + GATTM_ATT_GET_VALUE_RSP, + /// Set attribute value request + GATTM_ATT_SET_VALUE_REQ, + /// Set attribute value response + GATTM_ATT_SET_VALUE_RSP, + + /* Debug messages */ + /// DEBUG ONLY: Destroy Attribute database request + GATTM_DESTROY_DB_REQ, + /// DEBUG ONLY: Destroy Attribute database response + GATTM_DESTROY_DB_RSP, + /// DEBUG ONLY: Retrieve list of services request + GATTM_SVC_GET_LIST_REQ, + /// DEBUG ONLY: Retrieve list of services response + GATTM_SVC_GET_LIST_RSP, + /// DEBUG ONLY: Retrieve information of attribute request + GATTM_ATT_GET_INFO_REQ, + /// DEBUG ONLY: Retrieve information of attribute response + GATTM_ATT_GET_INFO_RSP, +}; + + +/** + * Attribute Description + */ +struct gattm_att_desc +{ + /** Attribute UUID (LSB First) */ + uint8_t uuid[ATT_UUID_128_LEN]; + + /** + * Attribute Permission (@see attm_perm_mask) + */ + uint16_t perm; + + + /** + * Maximum length of the attribute + * + * Note: + * For Included Services and Characteristic Declarations, this field contains targeted + * handle. + * + * For Characteristic Extended Properties, this field contains 2 byte value + * + * Not used Client Characteristic Configuration and Server Characteristic Configuration, + * this field is not used. + */ + uint16_t max_len; + + /** + * Attribute Extended permissions + * + * Extended Value permission bit field + * + * 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + * +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + * | RI |UUID_LEN |EKS | Reserved | + * +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + * + * Bit [0-11] : Reserved + * Bit [12] : Encryption key Size must be 16 bytes + * Bit [13-14]: UUID Length (0 = 16 bits, 1 = 32 bits, 2 = 128 bits, 3 = RFU) + * Bit [15] : Trigger Read Indication (0 = Value present in Database, 1 = Value not present in Database) + */ + uint16_t ext_perm; +}; + +/** + * Service description + */ +struct gattm_svc_desc +{ + /// Attribute Start Handle (0 = dynamically allocated) + uint16_t start_hdl; + /// Task identifier that manages service + uint16_t task_id; + + /** + * 7 6 5 4 3 2 1 0 + * +----+----+----+----+----+----+----+----+ + * |SEC |UUID_LEN |DIS | AUTH |EKS | MI | + * +----+----+----+----+----+----+----+----+ + * + * Bit [0] : Task that manage service is multi-instantiated (Connection index is conveyed) + * Bit [1] : Encryption key Size must be 16 bytes + * Bit [2-3]: Service Permission (0 = NO_AUTH, 1 = UNAUTH, 2 = AUTH, 3 = Secure Connect) + * Bit [4] : Disable the service + * Bit [5-6]: UUID Length (0 = 16 bits, 1 = 32 bits, 2 = 128 bits, 3 = RFU) + * Bit [7] : Secondary Service (0 = Primary Service, 1 = Secondary Service) + */ + uint8_t perm; + + /// Number of attributes + uint8_t nb_att; + + /** Service UUID */ + uint8_t uuid[ATT_UUID_128_LEN]; + /** + * List of attribute description present in service. + */ + struct gattm_att_desc atts[__ARRAY_EMPTY]; +}; + + +/// Add service in database request +struct gattm_add_svc_req +{ + /// service description + struct gattm_svc_desc svc_desc; +}; + +/// Add service in database response +struct gattm_add_svc_rsp +{ + /// Start handle of allocated service in attribute database + uint16_t start_hdl; + /// Return status of service allocation in attribute database. + uint8_t status; +}; + +/* Service management */ +/// Get permission settings of service request +struct gattm_svc_get_permission_req +{ + /// Service start attribute handle + uint16_t start_hdl; +}; + +/// Get permission settings of service response +struct gattm_svc_get_permission_rsp +{ + /// Service start attribute handle + uint16_t start_hdl; + /// service permission + uint8_t perm; + /// Return status + uint8_t status; +}; + +/// Set permission settings of service request +struct gattm_svc_set_permission_req +{ + /// Service start attribute handle + uint16_t start_hdl; + /// service permission + uint8_t perm; +}; + +/// Set permission settings of service response +struct gattm_svc_set_permission_rsp +{ + /// Service start attribute handle + uint16_t start_hdl; + /// Return status + uint8_t status; +}; + + +/* Attribute management */ +/// Get permission settings of attribute request +struct gattm_att_get_permission_req +{ + /// Handle of the attribute + uint16_t handle; +}; + +/// Get permission settings of attribute response +struct gattm_att_get_permission_rsp +{ + /// Handle of the attribute + uint16_t handle; + /// Attribute permission + uint16_t perm; + /// Extended Attribute permission + uint16_t ext_perm; + /// Return status + uint8_t status; +}; + +/// Set permission settings of attribute request +struct gattm_att_set_permission_req +{ + /// Handle of the attribute + uint16_t handle; + /// Attribute permission + uint16_t perm; + /// Extended Attribute permission + uint16_t ext_perm; +}; + +/// Set permission settings of attribute response +struct gattm_att_set_permission_rsp +{ + /// Handle of the attribute + uint16_t handle; + /// Return status + uint8_t status; +}; + + +/// Get attribute value request +struct gattm_att_get_value_req +{ + /// Handle of the attribute + uint16_t handle; +}; + +/// Get attribute value response +struct gattm_att_get_value_rsp +{ + /// Handle of the attribute + uint16_t handle; + /// Attribute value length + uint16_t length; + /// Return status + uint8_t status; + /// Attribute value + uint8_t value[__ARRAY_EMPTY]; +}; + +/// Set attribute value request +struct gattm_att_set_value_req +{ + /// Handle of the attribute + uint16_t handle; + /// Attribute value length + uint16_t length; + /// Attribute value + uint8_t value[__ARRAY_EMPTY]; +}; + +/// Set attribute value response +struct gattm_att_set_value_rsp +{ + /// Handle of the attribute + uint16_t handle; + /// Return status + uint8_t status; +}; + +/// DEBUG ONLY: Destroy Attribute database request +struct gattm_destroy_db_req +{ + /// New Gap Start Handle + uint16_t gap_hdl; + /// New Gatt Start Handle + uint16_t gatt_hdl; +}; + +/// DEBUG ONLY: Destroy Attribute database Response +struct gattm_destroy_db_rsp +{ + /// Return status + uint8_t status; +}; + + +/// Service information +struct gattm_svc_info +{ + /// Service start handle + uint16_t start_hdl; + /// Service end handle + uint16_t end_hdl; + /// Service task_id + uint16_t task_id; + /// Service permission + uint8_t perm; +}; + +/// DEBUG ONLY: Retrieve list of services response +struct gattm_svc_get_list_rsp +{ + /// Return status + uint8_t status; + /// Number of services + uint8_t nb_svc; + /// Array of information about services + struct gattm_svc_info svc[__ARRAY_EMPTY]; +}; + +/// DEBUG ONLY: Retrieve information of attribute request +struct gattm_att_get_info_req +{ + /// Attribute Handle + uint16_t handle; +}; + +/// DEBUG ONLY: Retrieve information of attribute response +struct gattm_att_get_info_rsp +{ + /// Return status + uint8_t status; + /// UUID Length + uint8_t uuid_len; + /// Attribute Handle + uint16_t handle; + /// Attribute Permissions + uint16_t perm; + /// Extended Attribute permission + uint16_t ext_perm; + /// UUID value + uint8_t uuid[ATT_UUID_128_LEN]; +}; + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/// @} GATTMTASK +#endif // GATTM_TASK_H_ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/api/l2cc_task.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/api/l2cc_task.h new file mode 100755 index 0000000..70c8eaf --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/api/l2cc_task.h @@ -0,0 +1,311 @@ +/** + **************************************************************************************** + * + * @file l2cc_task.h + * + * @brief Header file - L2CCTASK. + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + +#ifndef L2CC_TASK_H_ +#define L2CC_TASK_H_ + +/** + **************************************************************************************** + * @addtogroup L2CCTASK Task + * @ingroup L2CC + * @brief Handles ALL messages to/from L2CC block. + * + * The L2CC task is responsible for L2CAP attribute and security block handling. + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_task.h" // Task definitions +#include "ble_compiler.h" +#include + +/* + * MACRO DEFINITIONS + **************************************************************************************** + */ + +/// Number of L2CC Deprecated messages +#define L2CC_NB_DEPRECATED_MSG (4) + +/* + * STATES + **************************************************************************************** + */ + +/* + * MESSAGES + **************************************************************************************** + */ + +/// Message API of the L2CC task +enum l2cc_msg_id +{ + /// L2CAP Operation completed event + L2CC_CMP_EVT = TASK_FIRST_MSG(TASK_ID_L2CC) + L2CC_NB_DEPRECATED_MSG, + + /* ************* LE Credit Based API ************* */ + /// LE credit based connection request + L2CC_LECB_CONNECT_CMD, + /// LE credit based connection request indication + L2CC_LECB_CONNECT_REQ_IND, + /// LE credit based connection request confirmation + L2CC_LECB_CONNECT_CFM, + /// LE credit based connection indication + L2CC_LECB_CONNECT_IND, + /// LE credit based disconnect request + L2CC_LECB_DISCONNECT_CMD, + /// LE credit based disconnect indication + L2CC_LECB_DISCONNECT_IND, + /// LE credit based credit addition + L2CC_LECB_ADD_CMD, + /// LE credit based credit addition indication + L2CC_LECB_ADD_IND, + + /// Send data over an LE Credit Based Connection + L2CC_LECB_SDU_SEND_CMD, + /// Inform that a data packet has been received from a LE Credit Based connection. + L2CC_LECB_SDU_RECV_IND, + + + /* ******************* Debug API ******************* */ + /// Send Debug PDU data + L2CC_DBG_PDU_SEND_CMD, + /// Debug PDU data received + L2CC_DBG_PDU_RECV_IND, + + + /* **************** PDU Internal API ****************** */ + /// Send Legacy PDU data + L2CC_PDU_SEND_CMD, + /// Legacy PDU data received + L2CC_PDU_RECV_IND, + + /// Timeout indication for a transaction on signaling channel + L2CC_SIGNALING_TRANS_TO_IND, +}; + + +/// request operation type - application interface +enum l2cc_operation +{ + /* Operation Flags */ + /* No Operation (if nothing has been requested) */ + /* ************************************************ */ + /// No operation + L2CC_NO_OP = 0x00, + + /* LE Credit Based */ + /* ************************************************ */ + /// LE credit based connection request + L2CC_LECB_CONNECT, + /// LE credit based disconnection request + L2CC_LECB_DISCONNECT, + /// LE credit addition request + L2CC_LECB_CREDIT_ADD, + /// Send SDU + L2CC_LECB_SDU_SEND, + + /* Debug PDU Transmission (internal) */ + /* ************************************************ */ + /// Send a Debug PDU + L2CC_DBG_PDU_SEND, + + /* PDU Transmission (internal) */ + /* ************************************************ */ + /// Send internal LE Legacy PDU + L2CC_PDU_SEND, +}; + + +/// Default L2Cap SDU definition +struct l2cc_sdu +{ + /// Channel Identifier + uint16_t cid; + /// Number of credit used + uint16_t credit; + /// SDU Data length + uint16_t length; + /// data + uint8_t data[__ARRAY_EMPTY]; +}; + + +/// Operation completed event +struct l2cc_cmp_evt +{ + /// L2CC request type (@see enum l2cc_operation) + uint8_t operation; + /// Status of request. + uint8_t status; + /// Channel ID + uint16_t cid; + /// Number of peer credit used - only relevant for LECB + uint16_t credit; +}; + +/// LE credit based connection request +struct l2cc_lecb_connect_cmd +{ + /// L2CC request type: + /// - L2CC_LECB_CONNECT: LE credit connection + uint8_t operation; + /// parameter used for internal usage + uint8_t pkt_id; + /// LE Protocol/Service Multiplexer + uint16_t le_psm; + /// Local Channel identifier (0: automatically allocate a free channel) + uint16_t local_cid; + /// Credit allocated for the LE Credit Based Connection + /// Shall be at least: floor(((SDU + 2) + (MPS - 1)) / MPS) + 1 + /// To be sure that 1 SDU can be fully received without requesting credits to application + uint16_t local_credit; + /// Maximum SDU size - Shall not exceed device MTU + uint16_t local_mtu; + /// Maximum Packet size - Shall not exceed device MPS + uint16_t local_mps; +}; + +/// LE credit based connection request indication +struct l2cc_lecb_connect_req_ind +{ + /// LE Protocol/Service Multiplexer + uint16_t le_psm; + /// Peer Channel identifier + uint16_t peer_cid; + /// Maximum SDU size + uint16_t peer_mtu; + /// Maximum Packet size + uint16_t peer_mps; +}; + +/// LE credit based connection request confirmation +struct l2cc_lecb_connect_cfm +{ + /// LE Protocol/Service Multiplexer + uint16_t le_psm; + /// Peer Channel identifier + uint16_t peer_cid; + /// True to accept the incoming connection, False else + bool accept; + /// Local Channel identifier (0: automatically allocate a free channel) + uint16_t local_cid; + /// Credit allocated for the LE Credit Based Connection + /// Shall be at least: floor(((SDU + 2) + (MPS - 1)) / MPS) + 1 + /// To be sure that 1 SDU can be fully received without requesting credits to application + uint16_t local_credit; + /// Maximum SDU size - Shall not exceed device MTU + uint16_t local_mtu; + /// Maximum Packet size - Shall not exceed device MPS + uint16_t local_mps; +}; + +/// LE credit based connection indication +struct l2cc_lecb_connect_ind +{ + /// Status + uint8_t status; + /// LE Protocol/Service Multiplexer + uint16_t le_psm; + /// Local Channel identifier + uint16_t local_cid; + /// Peer Channel identifier + uint16_t peer_cid; + /// Destination Credit for the LE Credit Based Connection + uint16_t peer_credit; + /// Maximum SDU size + uint16_t peer_mtu; + /// Maximum Packet size + uint16_t peer_mps; +}; + +/// LE credit based disconnect request +struct l2cc_lecb_disconnect_cmd +{ + /// L2CC request type: + /// - L2CC_LECB_DISCONNECT: LE credit disconnection + uint8_t operation; + /// parameter used for internal usage + uint8_t pkt_id; + /// Peer Channel identifier + uint16_t peer_cid; +}; + +/// LE credit based disconnect indication +struct l2cc_lecb_disconnect_ind +{ + /// LE Protocol/Service Multiplexer + uint16_t le_psm; + /// Local Channel identifier + uint16_t local_cid; + /// Peer Channel identifier + uint16_t peer_cid; + /// Reason + uint8_t reason; +}; + +/// LE credit based credit addition +struct l2cc_lecb_add_cmd +{ + /// L2CC request type: + /// - L2CC_LECB_CREDIT_ADD: LE credit addition + uint8_t operation; + /// parameter used for internal usage + uint8_t pkt_id; + /// Local Channel identifier + uint16_t local_cid; + /// Credit added locally for channel identifier + uint16_t credit; +}; + +///LE credit based credit addition indication +struct l2cc_lecb_add_ind +{ + /// Peer Channel identifier + uint16_t peer_cid; + /// Destination added credit (relative value) + uint16_t peer_added_credit; +}; + +/// Send data over an LE Credit Based Connection +struct l2cc_lecb_sdu_send_cmd +{ + /// L2CC request type (@see enum l2cc_operation): + /// - L2CC_LECB_SDU_SEND: Send a SDU + uint8_t operation; + /// offset value information - for internal use only + uint16_t offset; + /// SDU information + struct l2cc_sdu sdu; +}; + +/// Inform that a data packet has been received from a LE Credit Based connection. +struct l2cc_lecb_sdu_recv_ind +{ + /// Status information + uint8_t status; + /// offset value information + uint16_t offset; + /// SDU information + struct l2cc_sdu sdu; +}; + + +/// @} L2CCTASK + +#endif // L2CC_TASK_H_ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/api/prf_types.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/api/prf_types.h new file mode 100755 index 0000000..4b4963c --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/api/prf_types.h @@ -0,0 +1,276 @@ +/** + **************************************************************************************** + * + * @file prf_types.h + * + * @brief Header file - Profile Types + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + + +#ifndef _PRF_TYPES_H_ +#define _PRF_TYPES_H_ + +/** + **************************************************************************************** + * @addtogroup PRF_TYPES + * @ingroup PROFILE + * @brief Definitions of shared profiles types + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "att.h" +#include "ble_compiler.h" + +/* + * DEFINES + **************************************************************************************** + */ + +/// Attribute is mandatory +#define ATT_MANDATORY (0xFF) +/// Attribute is optional +#define ATT_OPTIONAL (0x00) + +/// Characteristic Presentation Format Descriptor Size +#define PRF_CHAR_PRES_FMT_SIZE (7) + + +/// Possible values for setting client configuration characteristics +enum prf_cli_conf +{ + /// Stop notification/indication + PRF_CLI_STOP_NTFIND = 0x0000, + /// Start notification + PRF_CLI_START_NTF, + /// Start indication + PRF_CLI_START_IND, +}; + +/// Possible values for setting server configuration characteristics +enum prf_srv_conf +{ + /// Stop Broadcast + PRF_SRV_STOP_BCST = 0x0000, + /// Start Broadcast + PRF_SRV_START_BCST, +}; + +/// Connection type +enum prf_con_type +{ + ///Discovery type connection + PRF_CON_DISCOVERY = 0x00, + /// Normal type connection + PRF_CON_NORMAL = 0x01, +}; + +enum prf_svc_type +{ + PRF_PRIMARY_SERVICE = 0x00, + PRF_SECONDARY_SERVICE = 0x01 +}; + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + +/** + * Characteristic Presentation Format Descriptor structure + * Packed size is PRF_CHAR_PRES_FMT_SIZE + */ +/// characteristic presentation information +struct prf_char_pres_fmt +{ + /// Unit (The Unit is a UUID) + uint16_t unit; + /// Description + uint16_t description; + /// Format + uint8_t format; + /// Exponent + uint8_t exponent; + /// Name space + uint8_t name_space; +}; + +/** + * date and time structure + * size = 7 bytes + */ +/// Time profile information +struct prf_date_time +{ + /// year time element + uint16_t year; + /// month time element + uint8_t month; + /// day time element + uint8_t day; + /// hour time element + uint8_t hour; + /// minute time element + uint8_t min; + /// second time element + uint8_t sec; +}; + +/** + * SFLOAT: Short Floating Point Type + * + * +----------+----------+---------+ + * | Exponent | Mantissa | Total | + * +------+----------+----------+---------+ + * | size | 4 bits | 12 bits | 16 bits | + * +------+----------+----------+---------+ + */ +typedef uint16_t prf_sfloat; + + + +/// Attribute information +struct prf_att_info +{ + /// Attribute Handle + uint16_t handle; + /// Attribute length + uint16_t length; + /// Status of request + uint8_t status; + /// Attribute value + uint8_t value[__ARRAY_EMPTY]; +}; + + + + +/// service handles +struct prf_svc +{ + /// start handle + uint16_t shdl; + /// end handle + uint16_t ehdl; +}; + +/// service handles +struct prf_incl_svc +{ + /// attribute handle + uint16_t handle; + /// included service start handle + uint16_t start_hdl; + /// included service end handle + uint16_t end_hdl; + /// UUID length + uint8_t uuid_len; + /// UUID + uint8_t uuid[ATT_UUID_128_LEN]; +}; + +/// characteristic info +struct prf_char_inf +{ + /// uuid + uint16_t uuid; + /// Characteristic handle + uint16_t char_hdl; + /// Value handle + uint16_t val_hdl; + /// Characteristic properties + uint8_t prop; + /// End of characteristic offset + uint8_t char_ehdl_off; +}; + +/// characteristic description +struct prf_char_desc_inf +{ + /// Descriptor handle + uint16_t desc_hdl; + uint8_t char_code; + uint16_t uuid; +}; + + +/// Characteristic definition +struct prf_char_def +{ + /// Characteristic UUID + uint16_t uuid; + /// Requirement Attribute Flag + uint8_t req_flag; + /// Mandatory Properties + uint8_t prop_mand; +}; + +/// Characteristic definition uuid128 +struct prf_char_uuid128_def +{ + /// Service UUID Length + uint8_t uuid_len; + /// 128 bits UUID LSB First + uint8_t uuid[ATT_UUID_128_LEN]; + /// Requirement Attribute Flag + uint8_t req_flag; + /// Mandatory Properties + uint8_t prop_mand; +}; + +/// Characteristic Descriptor definition +struct prf_char_desc_def +{ + /// Characteristic Descriptor uuid + uint16_t uuid; + /// requirement attribute flag + uint8_t req_flag; + /// Corresponding characteristic code + uint8_t char_code; +}; + +/// Characteristic Descriptor definition uuid128 +struct prf_char_desc_uuid128_def +{ + /// Service UUID Length + uint8_t uuid_len; + /// 128 bits UUID LSB First + uint8_t uuid[ATT_UUID_128_LEN]; + /// requirement attribute flag + uint8_t req_flag; + /// Corresponding characteristic code + uint8_t char_code; +}; + +/// Message structure used to inform APP that a profile client role has been disabled +struct prf_client_disable_ind +{ + /// Status + uint8_t status; +}; + + + +/// Message structure used to inform APP that an error has occured in the profile server role task +struct prf_server_error_ind +{ + /// Message ID + uint16_t msg_id; + /// Status + uint8_t status; +}; + + +/// @} PRF_TYPES + +#endif /* _PRF_TYPES_H_ */ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/api/rwble_hl_error.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/api/rwble_hl_error.h new file mode 100755 index 0000000..37cfe20 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/api/rwble_hl_error.h @@ -0,0 +1,427 @@ +/** + **************************************************************************************** + * + * @file rwble_hl_error.h + * + * @brief File that contains all error codes. + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + +#ifndef RWBLE_HL_ERROR_H_ +#define RWBLE_HL_ERROR_H_ + + +/** + **************************************************************************************** + * @addtogroup ROOT + * @brief High layer error codes + * + * This module contains the primitives that allow an application accessing and running the + * BLE protocol stack + * + * @{ + **************************************************************************************** + */ + + + +/// Error code from HCI TO HL Range - from 0x90 to 0xD0 +#define RW_ERR_HCI_TO_HL(err) (((err) != 0) ? ((err) + 0x90) : (0)) + + +/// Error code from HL TO HCI Range - from 0x90 to 0xD0 +#define RW_ERR_HL_TO_HCI(err) (((err) > 0x90) ? ((err) - 0x90) : (0)) + +/** + * List all HL error codes + */ +enum hl_err +{ + /// No error + GAP_ERR_NO_ERROR = 0x00, + + // ---------------------------------------------------------------------------------- + // ------------------------- ATT Specific Error ------------------------------------ + // ---------------------------------------------------------------------------------- + /// No error + ATT_ERR_NO_ERROR = 0x00, + /// 0x01: Handle is invalid + ATT_ERR_INVALID_HANDLE = 0x01, + /// 0x02: Read permission disabled + ATT_ERR_READ_NOT_PERMITTED = 0x02, + /// 0x03: Write permission disabled + ATT_ERR_WRITE_NOT_PERMITTED = 0x03, + /// 0x04: Incorrect PDU + ATT_ERR_INVALID_PDU = 0x04, + /// 0x05: Authentication privilege not enough + ATT_ERR_INSUFF_AUTHEN = 0x05, + /// 0x06: Request not supported or not understood + ATT_ERR_REQUEST_NOT_SUPPORTED = 0x06, + /// 0x07: Incorrect offset value + ATT_ERR_INVALID_OFFSET = 0x07, + /// 0x08: Authorization privilege not enough + ATT_ERR_INSUFF_AUTHOR = 0x08, + /// 0x09: Capacity queue for reliable write reached + ATT_ERR_PREPARE_QUEUE_FULL = 0x09, + /// 0x0A: Attribute requested not existing + ATT_ERR_ATTRIBUTE_NOT_FOUND = 0x0A, + /// 0x0B: Attribute requested not long + ATT_ERR_ATTRIBUTE_NOT_LONG = 0x0B, + /// 0x0C: Encryption size not sufficient + ATT_ERR_INSUFF_ENC_KEY_SIZE = 0x0C, + /// 0x0D: Invalid length of the attribute value + ATT_ERR_INVALID_ATTRIBUTE_VAL_LEN = 0x0D, + /// 0x0E: Operation not fit to condition + ATT_ERR_UNLIKELY_ERR = 0x0E, + /// 0x0F: Attribute requires encryption before operation + ATT_ERR_INSUFF_ENC = 0x0F, + /// 0x10: Attribute grouping not supported + ATT_ERR_UNSUPP_GRP_TYPE = 0x10, + /// 0x11: Resources not sufficient to complete the request + ATT_ERR_INSUFF_RESOURCE = 0x11, + /// 0x80: Application error (also used in PRF Errors) + ATT_ERR_APP_ERROR = 0x80, + + // ---------------------------------------------------------------------------------- + // -------------------------- L2C Specific Error ------------------------------------ + // ---------------------------------------------------------------------------------- + /// Message cannot be sent because connection lost. (disconnected) + L2C_ERR_CONNECTION_LOST = 0x30, + /// Invalid PDU length exceed MTU + L2C_ERR_INVALID_MTU_EXCEED = 0x31, + /// Invalid PDU length exceed MPS + L2C_ERR_INVALID_MPS_EXCEED = 0x32, + /// Invalid Channel ID + L2C_ERR_INVALID_CID = 0x33, + /// Invalid PDU + L2C_ERR_INVALID_PDU = 0x34, + /// Connection refused - no resources available + L2C_ERR_NO_RES_AVAIL = 0x35, + /// Connection refused - insufficient authentication + L2C_ERR_INSUFF_AUTHEN = 0x36, + /// Connection refused - insufficient authorization + L2C_ERR_INSUFF_AUTHOR = 0x37, + /// Connection refused - insufficient encryption key size + L2C_ERR_INSUFF_ENC_KEY_SIZE = 0x38, + /// Connection Refused - insufficient encryption + L2C_ERR_INSUFF_ENC = 0x39, + /// Connection refused - LE_PSM not supported + L2C_ERR_LEPSM_NOT_SUPP = 0x3A, + /// No more credit + L2C_ERR_INSUFF_CREDIT = 0x3B, + /// Command not understood by peer device + L2C_ERR_NOT_UNDERSTOOD = 0x3C, + /// Credit error, invalid number of credit received + L2C_ERR_CREDIT_ERROR = 0x3D, + /// Channel identifier already allocated + L2C_ERR_CID_ALREADY_ALLOC = 0x3E, + + + // ---------------------------------------------------------------------------------- + // -------------------------- GAP Specific Error ------------------------------------ + // ---------------------------------------------------------------------------------- + /// Invalid parameters set + GAP_ERR_INVALID_PARAM = 0x40, + /// Problem with protocol exchange, get unexpected response + GAP_ERR_PROTOCOL_PROBLEM = 0x41, + /// Request not supported by software configuration + GAP_ERR_NOT_SUPPORTED = 0x42, + /// Request not allowed in current state. + GAP_ERR_COMMAND_DISALLOWED = 0x43, + /// Requested operation canceled. + GAP_ERR_CANCELED = 0x44, + /// Requested operation timeout. + GAP_ERR_TIMEOUT = 0x45, + /// Link connection lost during operation. + GAP_ERR_DISCONNECTED = 0x46, + /// Search algorithm finished, but no result found + GAP_ERR_NOT_FOUND = 0x47, + /// Request rejected by peer device + GAP_ERR_REJECTED = 0x48, + /// Problem with privacy configuration + GAP_ERR_PRIVACY_CFG_PB = 0x49, + /// Duplicate or invalid advertising data + GAP_ERR_ADV_DATA_INVALID = 0x4A, + /// Insufficient resources + GAP_ERR_INSUFF_RESOURCES = 0x4B, + /// Unexpected Error + GAP_ERR_UNEXPECTED = 0x4C, + /// Feature mismatch + GAP_ERR_MISMATCH = 0x4D, + + + // ---------------------------------------------------------------------------------- + // ------------------------- GATT Specific Error ------------------------------------ + // ---------------------------------------------------------------------------------- + /// Problem with ATTC protocol response + GATT_ERR_INVALID_ATT_LEN = 0x50, + /// Error in service search + GATT_ERR_INVALID_TYPE_IN_SVC_SEARCH = 0x51, + /// Invalid write data + GATT_ERR_WRITE = 0x52, + /// Signed write error + GATT_ERR_SIGNED_WRITE = 0x53, + /// No attribute client defined + GATT_ERR_ATTRIBUTE_CLIENT_MISSING = 0x54, + /// No attribute server defined + GATT_ERR_ATTRIBUTE_SERVER_MISSING = 0x55, + /// Permission set in service/attribute are invalid + GATT_ERR_INVALID_PERM = 0x56, + + // ---------------------------------------------------------------------------------- + // ------------------------- SMP Specific Error ------------------------------------- + // ---------------------------------------------------------------------------------- + // SMP Protocol Errors detected on local device + /// The user input of pass key failed, for example, the user canceled the operation. + SMP_ERROR_LOC_PASSKEY_ENTRY_FAILED = 0x61, + /// The OOB Data is not available. + SMP_ERROR_LOC_OOB_NOT_AVAILABLE = 0x62, + /// The pairing procedure cannot be performed as authentication requirements cannot be met + /// due to IO capabilities of one or both devices. + SMP_ERROR_LOC_AUTH_REQ = 0x63, + /// The confirm value does not match the calculated confirm value. + SMP_ERROR_LOC_CONF_VAL_FAILED = 0x64, + /// Pairing is not supported by the device. + SMP_ERROR_LOC_PAIRING_NOT_SUPP = 0x65, + /// The resultant encryption key size is insufficient for the security requirements of + /// this device. + SMP_ERROR_LOC_ENC_KEY_SIZE = 0x66, + /// The SMP command received is not supported on this device. + SMP_ERROR_LOC_CMD_NOT_SUPPORTED = 0x67, + /// Pairing failed due to an unspecified reason. + SMP_ERROR_LOC_UNSPECIFIED_REASON = 0x68, + /// Pairing or Authentication procedure is disallowed because too little time has elapsed + /// since last pairing request or security request. + SMP_ERROR_LOC_REPEATED_ATTEMPTS = 0x69, + /// The command length is invalid or a parameter is outside of the specified range. + SMP_ERROR_LOC_INVALID_PARAM = 0x6A, + /// Indicates to the remote device that the DHKey Check value received doesn't + /// match the one calculated by the local device. + SMP_ERROR_LOC_DHKEY_CHECK_FAILED = 0x6B, + /// Indicates that the confirm values in the numeric comparison protocol do not match. + SMP_ERROR_LOC_NUMERIC_COMPARISON_FAILED = 0x6C, + /// Indicates that the pairing over the LE transport failed due to a Pairing Request sent + /// over the BR/EDR transport in process. + SMP_ERROR_LOC_BREDR_PAIRING_IN_PROGRESS = 0x6D, + /// Indicates that the BR/EDR Link Key generated on the BR/EDR transport cannot be + /// used to derive and distribute keys for the LE transport. + SMP_ERROR_LOC_CROSS_TRANSPORT_KEY_GENERATION_NOT_ALLOWED = 0x6E, + // SMP Protocol Errors detected by remote device + /// The user input of passkey failed, for example, the user canceled the operation. + SMP_ERROR_REM_PASSKEY_ENTRY_FAILED = 0x71, + /// The OOB Data is not available. + SMP_ERROR_REM_OOB_NOT_AVAILABLE = 0x72, + /// The pairing procedure cannot be performed as authentication requirements cannot be + /// met due to IO capabilities of one or both devices. + SMP_ERROR_REM_AUTH_REQ = 0x73, + /// The confirm value does not match the calculated confirm value. + SMP_ERROR_REM_CONF_VAL_FAILED = 0x74, + /// Pairing is not supported by the device. + SMP_ERROR_REM_PAIRING_NOT_SUPP = 0x75, + /// The resultant encryption key size is insufficient for the security requirements of + /// this device. + SMP_ERROR_REM_ENC_KEY_SIZE = 0x76, + /// The SMP command received is not supported on this device. + SMP_ERROR_REM_CMD_NOT_SUPPORTED = 0x77, + /// Pairing failed due to an unspecified reason. + SMP_ERROR_REM_UNSPECIFIED_REASON = 0x78, + /// Pairing or Authentication procedure is disallowed because too little time has elapsed + /// since last pairing request or security request. + SMP_ERROR_REM_REPEATED_ATTEMPTS = 0x79, + /// The command length is invalid or a parameter is outside of the specified range. + SMP_ERROR_REM_INVALID_PARAM = 0x7A, + /// Indicates to the remote device that the DHKey Check value received doesn't + /// match the one calculated by the local device. + SMP_ERROR_REM_DHKEY_CHECK_FAILED = 0x7B, + /// Indicates that the confirm values in the numeric comparison protocol do not match. + SMP_ERROR_REM_NUMERIC_COMPARISON_FAILED = 0x7C, + /// Indicates that the pairing over the LE transport failed due to a Pairing Request sent + /// over the BR/EDR transport in process. + SMP_ERROR_REM_BREDR_PAIRING_IN_PROGRESS = 0x7D, + /// Indicates that the BR/EDR Link Key generated on the BR/EDR transport cannot be + /// used to derive and distribute keys for the LE transport. + SMP_ERROR_REM_CROSS_TRANSPORT_KEY_GENERATION_NOT_ALLOWED = 0x7E, + // SMP Errors triggered by local device + /// The provided resolvable address has not been resolved. + SMP_ERROR_ADDR_RESOLV_FAIL = 0xD0, + /// The Signature Verification Failed + SMP_ERROR_SIGN_VERIF_FAIL = 0xD1, + /// The encryption procedure failed because the slave device didn't find the LTK + /// needed to start an encryption session. + SMP_ERROR_ENC_KEY_MISSING = 0xD2, + /// The encryption procedure failed because the slave device doesn't support the + /// encryption feature. + SMP_ERROR_ENC_NOT_SUPPORTED = 0xD3, + /// A timeout has occurred during the start encryption session. + SMP_ERROR_ENC_TIMEOUT = 0xD4, + + // ---------------------------------------------------------------------------------- + //------------------------ Profiles specific error codes ---------------------------- + // ---------------------------------------------------------------------------------- + /// Application Error + PRF_APP_ERROR = 0x80, + /// Invalid parameter in request + PRF_ERR_INVALID_PARAM = 0x81, + /// Inexistent handle for sending a read/write characteristic request + PRF_ERR_INEXISTENT_HDL = 0x82, + /// Discovery stopped due to missing attribute according to specification + PRF_ERR_STOP_DISC_CHAR_MISSING = 0x83, + /// Too many SVC instances found -> protocol violation + PRF_ERR_MULTIPLE_SVC = 0x84, + /// Discovery stopped due to found attribute with incorrect properties + PRF_ERR_STOP_DISC_WRONG_CHAR_PROP = 0x85, + /// Too many Char. instances found-> protocol violation + PRF_ERR_MULTIPLE_CHAR = 0x86, + /// Attribute write not allowed + PRF_ERR_NOT_WRITABLE = 0x87, + /// Attribute read not allowed + PRF_ERR_NOT_READABLE = 0x88, + /// Request not allowed + PRF_ERR_REQ_DISALLOWED = 0x89, + /// Notification Not Enabled + PRF_ERR_NTF_DISABLED = 0x8A, + /// Indication Not Enabled + PRF_ERR_IND_DISABLED = 0x8B, + /// Feature not supported by profile + PRF_ERR_FEATURE_NOT_SUPPORTED = 0x8C, + /// Read value has an unexpected length + PRF_ERR_UNEXPECTED_LEN = 0x8D, + /// Disconnection occurs + PRF_ERR_DISCONNECTED = 0x8E, + /// Procedure Timeout + PRF_ERR_PROC_TIMEOUT = 0x8F, + /// Client characteristic configuration improperly configured + PRF_CCCD_IMPR_CONFIGURED = 0xFD, + /// Procedure already in progress + PRF_PROC_IN_PROGRESS = 0xFE, + /// Out of Range + PRF_OUT_OF_RANGE = 0xFF, + + // ---------------------------------------------------------------------------------- + //-------------------- LL Error codes conveyed to upper layer ----------------------- + // ---------------------------------------------------------------------------------- + /// Unknown HCI Command + LL_ERR_UNKNOWN_HCI_COMMAND = 0x91, + /// Unknown Connection Identifier + LL_ERR_UNKNOWN_CONNECTION_ID = 0x92, + /// Hardware Failure + LL_ERR_HARDWARE_FAILURE = 0x93, + /// BT Page Timeout + LL_ERR_PAGE_TIMEOUT = 0x94, + /// Authentication failure + LL_ERR_AUTH_FAILURE = 0x95, + /// Pin code missing + LL_ERR_PIN_MISSING = 0x96, + /// Memory capacity exceed + LL_ERR_MEMORY_CAPA_EXCEED = 0x97, + /// Connection Timeout + LL_ERR_CON_TIMEOUT = 0x98, + /// Connection limit Exceed + LL_ERR_CON_LIMIT_EXCEED = 0x99, + /// Synchronous Connection limit exceed + LL_ERR_SYNC_CON_LIMIT_DEV_EXCEED = 0x9A, + /// ACL Connection exits + LL_ERR_ACL_CON_EXISTS = 0x9B, + /// Command Disallowed + LL_ERR_COMMAND_DISALLOWED = 0x9C, + /// Connection rejected due to limited resources + LL_ERR_CONN_REJ_LIMITED_RESOURCES = 0x9D, + /// Connection rejected due to security reason + LL_ERR_CONN_REJ_SECURITY_REASONS = 0x9E, + /// Connection rejected due to unacceptable BD Addr + LL_ERR_CONN_REJ_UNACCEPTABLE_BDADDR = 0x9F, + /// Connection rejected due to Accept connection timeout + LL_ERR_CONN_ACCEPT_TIMEOUT_EXCEED = 0xA0, + /// Not Supported + LL_ERR_UNSUPPORTED = 0xA1, + /// invalid parameters + LL_ERR_INVALID_HCI_PARAM = 0xA2, + /// Remote user terminate connection + LL_ERR_REMOTE_USER_TERM_CON = 0xA3, + /// Remote device terminate connection due to low resources + LL_ERR_REMOTE_DEV_TERM_LOW_RESOURCES = 0xA4, + /// Remote device terminate connection due to power off + LL_ERR_REMOTE_DEV_POWER_OFF = 0xA5, + /// Connection terminated by local host + LL_ERR_CON_TERM_BY_LOCAL_HOST = 0xA6, + /// Repeated attempts + LL_ERR_REPEATED_ATTEMPTS = 0xA7, + /// Pairing not Allowed + LL_ERR_PAIRING_NOT_ALLOWED = 0xA8, + /// Unknown PDU Error + LL_ERR_UNKNOWN_LMP_PDU = 0xA9, + /// Unsupported remote feature + LL_ERR_UNSUPPORTED_REMOTE_FEATURE = 0xAA, + /// Sco Offset rejected + LL_ERR_SCOMMON_OFFSET_REJECTED = 0xAB, + /// SCO Interval Rejected + LL_ERR_SCOMMON_INTERVAL_REJECTED = 0xAC, + /// SCO air mode Rejected + LL_ERR_SCOMMON_AIR_MODE_REJECTED = 0xAD, + /// Invalid LMP parameters + LL_ERR_INVALID_LMP_PARAM = 0xAE, + /// Unspecified error + LL_ERR_UNSPECIFIED_ERROR = 0xAF, + /// Unsupported LMP Parameter value + LL_ERR_UNSUPPORTED_LMP_PARAM_VALUE = 0xB0, + /// Role Change Not allowed + LL_ERR_ROLE_CHANGE_NOT_ALLOWED = 0xB1, + /// LMP Response timeout + LL_ERR_LMP_RSP_TIMEOUT = 0xB2, + /// LMP Collision + LL_ERR_LMP_COLLISION = 0xB3, + /// LMP Pdu not allowed + LL_ERR_LMP_PDU_NOT_ALLOWED = 0xB4, + /// Encryption mode not accepted + LL_ERR_ENC_MODE_NOT_ACCEPT = 0xB5, + /// Link Key Cannot be changed + LL_ERR_LINK_KEY_CANT_CHANGE = 0xB6, + /// Quality of Service not supported + LL_ERR_QOS_NOT_SUPPORTED = 0xB7, + /// Error, instant passed + LL_ERR_INSTANT_PASSED = 0xB8, + /// Pairing with unit key not supported + LL_ERR_PAIRING_WITH_UNIT_KEY_NOT_SUP = 0xB9, + /// Transaction collision + LL_ERR_DIFF_TRANSACTION_COLLISION = 0xBA, + /// Unacceptable parameters + LL_ERR_QOS_UNACCEPTABLE_PARAM = 0xBC, + /// Quality of Service rejected + LL_ERR_QOS_REJECTED = 0xBD, + /// Channel class not supported + LL_ERR_CHANNEL_CLASS_NOT_SUP = 0xBE, + /// Insufficient security + LL_ERR_INSUFFICIENT_SECURITY = 0xBF, + /// Parameters out of mandatory range + LL_ERR_PARAM_OUT_OF_MAND_RANGE = 0xC0, + /// Role switch pending + LL_ERR_ROLE_SWITCH_PEND = 0xC2, + /// Reserved slot violation + LL_ERR_RESERVED_SLOT_VIOLATION = 0xC4, + /// Role Switch fail + LL_ERR_ROLE_SWITCH_FAIL = 0xC5, + /// Error, EIR too large + LL_ERR_EIR_TOO_LARGE = 0xC6, + /// Simple pairing not supported by host + LL_ERR_SP_NOT_SUPPORTED_HOST = 0xC7, + /// Host pairing is busy + LL_ERR_HOST_BUSY_PAIRING = 0xC8, + /// Controller is busy + LL_ERR_CONTROLLER_BUSY = 0xCA, + /// Unacceptable connection initialization + LL_ERR_UNACCEPTABLE_CONN_INT = 0xCB, + /// Direct Advertising Timeout + LL_ERR_DIRECT_ADV_TO = 0xCC, + /// Connection Terminated due to a MIC failure + LL_ERR_TERMINATED_MIC_FAILURE = 0xCD, + /// Connection failed to be established + LL_ERR_CONN_FAILED_TO_BE_EST = 0xCE, +}; + +/// @} RWBLE_HL_ERROR_H + +#endif // RWBLE_HL_ERROR_H_ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/inc/attm.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/inc/attm.h new file mode 100755 index 0000000..ccfb5e8 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/inc/attm.h @@ -0,0 +1,482 @@ +/** + **************************************************************************************** + * + * @file attm.h + * + * @brief Header file - ATTM. + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + +#ifndef ATTM_H_ +#define ATTM_H_ + +/** + **************************************************************************************** + * @addtogroup ATTM Attribute Manager + * @ingroup ATT + * @brief Attribute Manager + * + * The ATTM is the attribute manager of the Attribute Profile block and + * is responsible for managing messages and providing generic attribute + * functionalities to @ref ATTC "ATTC" and @ref ATTS "ATTS". + * + * + * @{ + * + **************************************************************************************** + */ + + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_config.h" +#include +#include + +#include "common_error.h" +#include "att.h" +#include "kernel_task.h" + +/* + * DEFINES + **************************************************************************************** + */ + +/// update attribute permission on specific handle +#define ATTMDB_UPDATE_PERM(handle, access, right)\ + attm_att_update_perm(handle, (PERM_MASK_ ## access), PERM(access, right)) + +#define ATTMDB_UPDATE_PERM_VAL(handle, access, val)\ + attm_att_update_perm(handle, (PERM_MASK_ ## access), ((val) << (PERM_POS_ ## access))) + + + +/* + * DATA STRUCTURES + **************************************************************************************** + */ + +/// Internal 16bits UUID service description +struct attm_desc +{ + /// 16 bits UUID LSB First + uint16_t uuid; + /// Attribute Permissions (@see enum attm_perm_mask) + uint16_t perm; + /// Attribute Extended Permissions (@see enum attm_value_perm_mask) + uint16_t ext_perm; + /// Attribute Max Size + /// note: for characteristic declaration contains handle offset + /// note: for included service, contains target service handle + uint16_t max_size; +}; + + +/// Internal 128bits UUID service description +struct attm_desc_128 +{ + /// 128 bits UUID LSB First + uint8_t uuid[ATT_UUID_128_LEN]; + /// Attribute Permissions (@see enum attm_perm_mask) + uint16_t perm; + /// Attribute Extended Permissions (@see enum attm_value_perm_mask) + uint16_t ext_perm; + /// Attribute Max Size + /// note: for characteristic declaration contains handle offset + /// note: for included service, contains target service handle + uint16_t max_size; +}; + + + +#if (BLE_CENTRAL || BLE_PERIPHERAL) +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + + +/** + **************************************************************************************** + * @brief Compare if two UUIDs matches + * + * @param[in] uuid_a UUID A value + * @param[in] uuid_a_len UUID A length + * @param[in] uuid_b UUID B value + * @param[in] uuid_b_len UUID B length + * + * @return true if UUIDs matches, false otherwise + **************************************************************************************** + */ +bool attm_uuid_comp(uint8_t *uuid_a, uint8_t uuid_a_len, + uint8_t *uuid_b, uint8_t uuid_b_len); + + +/** + **************************************************************************************** + * @brief Check if two UUIDs matches (2nd UUID is a 16 bits UUID with LSB First) + * + * @param[in] uuid_a UUID A value + * @param[in] uuid_a_len UUID A length + * @param[in] uuid_b UUID B 16 bit value + * + * @return true if UUIDs matches, false otherwise + **************************************************************************************** + */ +bool attm_uuid16_comp(uint8_t *uuid_a, uint8_t uuid_a_len, uint16_t uuid_b); + + +/** + **************************************************************************************** + * @brief Convert UUID value to 128 bit UUID + * + * @param[out] uuid128 converted 32-bit Bluetooth UUID to 128-bit UUID + * @param[in] uuid UUID to convert to 128-bit UUID + * @param[in] uuid_len UUID length + * + **************************************************************************************** + */ +void attm_convert_to128(uint8_t *uuid128, uint8_t *uuid, uint8_t uuid_len); + +/** + **************************************************************************************** + * @brief Check if it's a Bluetooth 16-bits UUID for 128-bit input + * + * @param[in] uuid 128-bit UUID + * + * @return true if uuid is a Bluetooth 16-bit UUID, false else. + **************************************************************************************** + */ +bool attm_is_bt16_uuid(uint8_t *uuid); + +/** + **************************************************************************************** + * @brief Check if it's a Bluetooth 32 bits UUID for 128-bit input + * + * @param[in] uuid 128-bit UUID + * + * @return true if uuid is a Bluetooth 32-bits UUID, false else. + **************************************************************************************** + */ +bool attm_is_bt32_uuid(uint8_t *uuid); + + +#if (BLE_ATTS) +/** + **************************************************************************************** + * @brief Function use to ease service database creation. + * Use @see attmdb_add_service function of attmdb module to create service database, + * then use @see attmdb_add_attribute function of attmdb module to create attributes + * according to database description array given in parameter. + * + * @note: database description array shall be const to reduce memory consumption (only ROM) + * @note: It supports only 16 bits UUIDs + * + * @note: If shdl = 0, it return handle using first available handle (shdl is + * modified); else it verifies if start handle given can be used to allocates handle range. + * + * @param[in|out] shdl Service start handle. + * @param[in] uuid Service UUID + * @param[in|out] cfg_flag Configuration Flag, each bit matches with an attribute of + * att_db (Max: 32 attributes); if the bit is set to 1, the + * attribute will be added in the service. + * @param[in] max_nb_att Number of attributes in the service + * @param[in|out] att_tbl Array which will be fulfilled with the difference between + * each characteristic handle and the service start handle. + * This array is useful if several characteristics are optional + * within the service, can be set to NULL if not needed. + * @param[in] dest_id Task ID linked to the service. This task will be notified + * each time the service content is modified by a peer device. + * @param[in|out] att_db Table containing all attributes information + * @param[in] svc_perm Service permission (@see enum attm_svc_perm_mask) + * + * @return Command status code: + * - @ref ATT_ERR_NO_ERROR: If database creation succeeds. + * - @ref ATT_ERR_INVALID_HANDLE: If start_hdl given in parameter + nb of attribute override + * some existing services handles. + * - @ref ATT_ERR_INSUFF_RESOURCE: There is not enough memory to allocate service buffer. + * or of new attribute cannot be added because all expected + * attributes already added or buffer overflow detected during + * allocation + **************************************************************************************** + */ +uint8_t attm_svc_create_db(uint16_t *shdl, uint16_t uuid, uint8_t *cfg_flag, uint8_t max_nb_att, + uint8_t *att_tbl, kernel_task_id_t const dest_id, + const struct attm_desc *att_db, uint8_t svc_perm); + + + +/** + **************************************************************************************** + * @brief Function use to ease service database creation. + * Use @see attmdb_add_service function of attmdb module to create service database, + * then use @see attmdb_add_attribute function of attmdb module to create attributes + * according to database description array given in parameter. + * + * @note: database description array shall be const to reduce memory consumption (only ROM) + * @note: It supports 128, 32 and 16 bits UUIDs + * + * @note: If shdl = 0, it return handle using first available handle (shdl is + * modified); else it verifies if start handle given can be used to allocates handle range. + * + * @param[in|out] shdl Service start handle. + * @param[in] uuid Service UUID + * @param[in|out] cfg_flag Configuration Flag, each bit matches with an attribute of + * att_db (Max: 32 attributes); if the bit is set to 1, the + * attribute will be added in the service. + * @param[in] max_nb_att Number of attributes in the service + * @param[in|out] att_tbl Array which will be fulfilled with the difference between + * each characteristic handle and the service start handle. + * This array is useful if several characteristics are optional + * within the service, can be set to NULL if not needed. + * @param[in] dest_id Task ID linked to the service. This task will be notified + * each time the service content is modified by a peer device. + * @param[in|out] att_db Table containing all attributes information + * @param[in] svc_perm Service permission (@see enum attm_svc_perm_mask) + * + * @return Command status code: + * - @ref ATT_ERR_NO_ERROR: If database creation succeeds. + * - @ref ATT_ERR_INVALID_HANDLE: If start_hdl given in parameter + nb of attribute override + * some existing services handles. + * - @ref ATT_ERR_INSUFF_RESOURCE: There is not enough memory to allocate service buffer. + * or of new attribute cannot be added because all expected + * attributes already added or buffer overflow detected during + * allocation + **************************************************************************************** + */ +uint8_t attm_svc_create_db_128(uint16_t *shdl, const uint8_t *uuid, uint8_t *cfg_flag, uint8_t max_nb_att, + uint8_t *att_tbl, kernel_task_id_t const dest_id, + const struct attm_desc_128 *att_db, uint8_t svc_perm); + +uint8_t attm_svc_create_db128(uint16_t *shdl, uint16_t uuid, uint8_t *cfg_flag, uint8_t max_nb_att, + uint8_t *att_tbl, kernel_task_id_t const dest_id, + const struct attm_desc *att_db, uint8_t svc_perm); //add for TI OTA use 128uuid + + +/** + **************************************************************************************** + * @brief Function use to ease service database creation. + * Use @see attmdb_add_service function of attmdb module to create service database, + * then use @see attmdb_add_attribute function of attmdb module to create attributes + * according to database description array given in parameter. + * + * @note: database description array shall be const to reduce memory consumption (only ROM) + * @note: It supports 128, 32 and 16 bits UUIDs + * + * @note: If shdl = 0, it return handle using first available handle (shdl is + * modified); else it verifies if start handle given can be used to allocates handle range. + * + * @param[in|out] shdl Service start handle. + * @param[in] uuid Service UUID + * @param[in|out] cfg_flag Configuration Flag, each bit matches with an attribute of + * att_db (Max: 32 attributes); if the bit is set to 1, the + * attribute will be added in the service. + * @param[in] max_nb_att Number of attributes in the service + * @param[in|out] att_tbl Array which will be fulfilled with the difference between + * each characteristic handle and the service start handle. + * This array is useful if several characteristics are optional + * within the service, can be set to NULL if not needed. + * @param[in] dest_id Task ID linked to the service. This task will be notified + * each time the service content is modified by a peer device. + * @param[in|out] att_db Table containing all attributes information + * @param[in] svc_perm Service permission (@see enum attm_svc_perm_mask) + * + * @return Command status code: + * - @ref ATT_ERR_NO_ERROR: If database creation succeeds. + * - @ref ATT_ERR_INVALID_HANDLE: If start_hdl given in parameter + nb of attribute override + * some existing services handles. + * - @ref ATT_ERR_INSUFF_RESOURCE: There is not enough memory to allocate service buffer. + * or of new attribute cannot be added because all expected + * attributes already added or buffer overflow detected during + * allocation + **************************************************************************************** + */ +uint8_t attm_svc_create_db_128(uint16_t *shdl, const uint8_t *uuid, uint8_t *cfg_flag, uint8_t max_nb_att, + uint8_t *att_tbl, kernel_task_id_t const dest_id, + const struct attm_desc_128 *att_db, uint8_t svc_perm); + + +/** + **************************************************************************************** + * @brief Control visibility of a service from peer device. service present in database + * but cannot be access by a peer device. + * + * @param[in] handle Service handle. + * @param[in] hide True to hide the service, False to restore visibility + * + * @return Command status code: + * - @ref ATT_ERR_NO_ERROR: If service allocation succeeds. + * - @ref ATT_ERR_INVALID_HANDLE: If start_hdl given in parameter or UUIDs value invalid + **************************************************************************************** + */ +uint8_t attmdb_svc_visibility_set(uint16_t handle, bool hide); + +/** + **************************************************************************************** + * @brief Function use to verify if several services can be allocated on a contiguous + * handle range. If this command succeed, it means that service allocation will succeed. + * + * If start_hdl = 0, it return handle using first available handle (start_hdl is + * modified); else it verifies if start handle given can be used to allocates handle range. + * + * @param[in|out] start_hdl Service start handle. + * @param[in] nb_att Number of handle to allocate (containing service handles) + * + * @return Command status code: + * - @ref ATT_ERR_NO_ERROR: If service allocation succeeds. + * - @ref ATT_ERR_INVALID_HANDLE: If start_hdl given in parameter or UUIDs value invalid + **************************************************************************************** + */ +uint8_t attm_reserve_handle_range(uint16_t *start_hdl, uint8_t nb_att); + + + +/** + **************************************************************************************** + * @brief Update attribute value + * + * Updating attribute value do not trigger any notification or indication, this shall be + * handled by GATT task. + * + * @param[in] handle Attribute handle. + * @param[in] length Size of new attribute value + * @param[in] offset Data offset of in the payload to set + * @param[in] value Attribute value payload + * + * @return Command status code: + * - @ref ATT_ERR_NO_ERROR: If attribute value update succeeds + * - @ref ATT_ERR_INVALID_HANDLE: If handle doesn't exist in database + * - @ref ATT_ERR_REQUEST_NOT_SUPPORTED: If attribute data not present in database or + * cannot be modified + * - @ref ATT_ERR_INVALID_ATTRIBUTE_VAL_LEN: If new value length exceeds maximum attribute + * value length. + * + **************************************************************************************** + */ +uint8_t attm_att_set_value(uint16_t handle, att_size_t length, att_size_t offset, uint8_t *value); + +/** + **************************************************************************************** + * @brief Retrieve attribute value + + * + * @param[in] handle Attribute handle. + * @param[out] length Size of attribute value + * @param[out] value Pointer to attribute value payload + * + * @return Command status code: + * - @ref ATT_ERR_NO_ERROR: If request succeeds + * - @ref ATT_ERR_INVALID_HANDLE: If handle doesn't exist in database + * - @ref ATT_ERR_REQUEST_NOT_SUPPORTED: If attribute data not present in database + **************************************************************************************** + */ +uint8_t attm_get_value(uint16_t handle, att_size_t *length, uint8_t **value); + + +/** + **************************************************************************************** + * @brief Update attribute permission + * + * @param[in] handle Attribute handle. + * - @ref ATT_ERR_REQUEST_NOT_SUPPORTED: If attribute data not present in database + * @param[in] perm New attribute permission + * @param[in] ext_perm New attribute extended permission + * + * @return Command status code: + * - @ref ATT_ERR_NO_ERROR: If request succeeds + * - @ref ATT_ERR_INVALID_HANDLE: If handle doesn't exist in database + * - @ref ATT_ERR_REQUEST_NOT_SUPPORTED: If attribute permission is fixed + **************************************************************************************** + */ +uint8_t attm_att_set_permission(uint16_t handle, uint16_t perm, uint16_t ext_perm); + + +/** + **************************************************************************************** + * @brief Reset some permissions bit in the Handle passed as parameter. + * + * @param[in] handle Attribute handle. + * @param[in] access_mask Access mask of permission to update + * @param[in] perm New value of the permission to update + * + * + * @return Command status code: + * - @ref ATT_ERR_NO_ERROR: If request succeeds + * - @ref ATT_ERR_INVALID_HANDLE: If handle doesn't exist in database + * - @ref ATT_ERR_REQUEST_NOT_SUPPORTED: If attribute permission is fixed + **************************************************************************************** + */ +uint8_t attm_att_update_perm(uint16_t handle, uint16_t access_mask, uint16_t perm); + +/** + **************************************************************************************** + * @brief Update attribute service permission + * + * @param[in] handle Attribute handle. + * @param[in] perm New attribute permission + * + * @return Command status code: + * - @ref ATT_ERR_NO_ERROR: If request succeeds + * - @ref ATT_ERR_INVALID_HANDLE: If handle doesn't exist in database + **************************************************************************************** + */ +uint8_t attm_svc_set_permission(uint16_t handle, uint8_t perm); + + +/** + **************************************************************************************** + * @brief Retrieve attribute service permission + * + * @param[in] handle Attribute handle. + * @param[out] perm Permission value to return + * + * @return Command status code: + * - @ref ATT_ERR_NO_ERROR: If request succeeds + * - @ref ATT_ERR_INVALID_HANDLE: If handle doesn't exist in database + **************************************************************************************** + */ +uint8_t attm_svc_get_permission(uint16_t handle, uint8_t *perm); + + +/** + **************************************************************************************** + * @brief Clear database + * + * For debug purpose only, this function clear the database and unalloc all services + * within database. + * + * This function shall be used only for qualification and tests in order to manually + * change database without modifying software. + **************************************************************************************** + */ +void attmdb_destroy(void); + +/** + **************************************************************************************** + * @brief Initialize Attribute Database (clear it) + * + * @param[in] reset true if it's requested by a reset; false if it's boot initialization + **************************************************************************************** + */ +void attm_init(bool reset); + + +uint16_t attm_convert_to16(uint8_t *uuid, uint8_t uuid_len); + + +#endif // (BLE_ATTS) + +#endif // #if (BLE_CENTRAL || BLE_PERIPHERAL) +/// @} ATTM +#endif // ATTM_H_ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/inc/gapc.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/inc/gapc.h new file mode 100755 index 0000000..67c1def --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/inc/gapc.h @@ -0,0 +1,231 @@ +/** + **************************************************************************************** + * + * @file gapc.h + * + * @brief Generic Access Profile Controller Header. + * + * Copyright (C) RivieraWaves 2009-2016 + * + **************************************************************************************** + */ + + +#ifndef _GAPC_H_ +#define _GAPC_H_ + +/** + **************************************************************************************** + * @addtogroup GAPC Generic Access Profile Controller + * @ingroup GAP + * @brief Generic Access Profile Controller. + * + * The GAP Controller module is responsible for providing an API to the application in + * to perform GAP action related to a BLE connection (pairing, update parameters, + * disconnect ...). GAP controller is multi-instantiated, one task instance per BLE + * connection. + * + * @{ + **************************************************************************************** + */ + + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_config.h" + +#if (BLE_GAPC) + +#include "kernel_task.h" +#include "gap.h" +#include "smpc.h" + + + +/* + * DEFINES + **************************************************************************************** + */ + + +/// Operation type +enum gapc_op_type +{ + /// Operation used to manage Link (update params, get peer info) + GAPC_OP_LINK_INFO = 0x00, + + /// Operation used to manage SMP + GAPC_OP_SMP = 0x01, + + /// Operation used to manage connection update + GAPC_OP_LINK_UPD = 0x02, + + /// Max number of operations + GAPC_OP_MAX +}; + +/// Link security status. This status represents the authentication/authorization/bonding levels of the connection +enum gapc_lk_sec_req +{ + /// Link is bonded + GAPC_LK_BONDED, + /// Link is Encrypted + GAPC_LK_ENCRYPTED, + /// Link LTK Exchanged during pairing + GAPC_LK_LTK_PRESENT, +}; + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + +/// GAP controller environment variable structure. +struct gapc_env_tag +{ + /// Request operation Kernel message + void *operation[GAPC_OP_MAX]; + /// Task id requested disconnection + kernel_task_id_t disc_requester; + + + /* Connection parameters to keep */ + + /// Security Management Protocol environment variables + struct smpc_env smpc; + + /// connection handle + uint16_t conhdl; + + /// Configuration fields (@see enum gapc_fields) + uint8_t fields; + + // BD Address used for the link that should be kept + struct gap_bdaddr src[SMPC_INFO_MAX]; + + /// Relevant information of peer LE features 8-byte array + uint8_t features; +}; + + + +/* + * MACROS + **************************************************************************************** + */ + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Retrieve connection index from connection handle. + * + * @param[in] conhdl Connection handle + * + * @return Return found connection index, GAP_INVALID_CONIDX if not found. + **************************************************************************************** + */ +uint8_t gapc_get_conidx(uint16_t conhdl); + +/** + **************************************************************************************** + * @brief Retrieve connection handle from connection index. + * + * @param[in] conidx Connection index + * + * @return Return found connection handle, GAP_INVALID_CONHDL if not found. + **************************************************************************************** + */ +uint16_t gapc_get_conhdl(uint8_t conidx); + +/** + **************************************************************************************** + * @brief Retrieve connection role from connection index. + * + * @param[in] conidx Connection index + * + * @return Return found connection role + **************************************************************************************** + */ +uint8_t gapc_get_role(uint8_t conidx); + +/** + **************************************************************************************** + * @brief Retrieve connection address information on current link. + * + * @param[in] conidx Connection index + * @param[in] src Connection information source + * + * @return Return found connection address + **************************************************************************************** + */ +struct gap_bdaddr *gapc_get_bdaddr(uint8_t conidx, uint8_t src); + + +/** + **************************************************************************************** + * @brief Check if current link support security requirements. + * + * @param[in] conidx Connection index + * @param[in] sec_req Link security requirement to test + * + * @return True if link requirement is supported, False else. + **************************************************************************************** + */ +bool gapc_is_sec_set(uint8_t conidx, uint8_t sec_req); + +/** + **************************************************************************************** + * @brief Retrieve Link Security level + * + * @param[in] conidx Connection index + * + * @return Link Security level. + **************************************************************************************** + */ +uint8_t gapc_lk_sec_lvl_get(uint8_t conidx); + +/** + **************************************************************************************** + * @brief Retrieve the encryption key size of the connection + * + * @param[in] conidx Connection index + * + * @return encryption key size (size is 7 - 16 byte range) + * + **************************************************************************************** + */ +uint8_t gapc_enc_keysize_get(uint8_t conidx); + +/** + **************************************************************************************** + * @brief Get Service Change Client Configuration + * + * @param[in] conidx Connection index + * + * @return Service Change Client Configuration + **************************************************************************************** + */ +bool gapc_svc_chg_ccc_get(uint8_t conidx); + +/** + **************************************************************************************** + * @brief Set Service Change Client Configuration + * + * @param[in] conidx Connection index + * @param[in] enable True if CCC is enabled, False else + * + **************************************************************************************** + */ +void gapc_svc_chg_ccc_set(uint8_t conidx, bool enable); + + +#endif // (BLE_GAPC) +/// @} GAPC + +#endif /* _GAPC_H_ */ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/inc/gapm.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/inc/gapm.h new file mode 100755 index 0000000..baced60 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/inc/gapm.h @@ -0,0 +1,350 @@ +/** + **************************************************************************************** + * + * @file gapm.h + * + * @brief Generic Access Profile Manager Header. + * + * Copyright (C) RivieraWaves 2009-2016 + * + **************************************************************************************** + */ + + +#ifndef _GAPM_H_ +#define _GAPM_H_ + +/** + **************************************************************************************** + * @addtogroup GAPM Generic Access Profile Manager + * @ingroup GAP + * @brief Generic Access Profile Manager. + * + * The GAP Manager module is responsible for providing an API to the application in order + * to manage all non connected stuff such as configuring device to go in desired mode + * (discoverable, connectable, etc.) and perform required actions (scanning, connection, + * etc.). GAP Manager is also responsible of managing GAP Controller state according to + * corresponding BLE connection states. + * + * @{ + **************************************************************************************** + */ + + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_config.h" +#include "kernel_task.h" +#include "gap.h" + +/* + * DEFINES + **************************************************************************************** + */ +/// Bit checking +#define GAPM_ISBITSET(flag, mask) (((flag)&(mask)) == mask) + + + + + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Initialize Generic Access Profile Manager Module. + * + * @param[in] reset true if it's requested by a reset; false if it's boot initialization + * + **************************************************************************************** + */ +void gapm_init(bool reset); + + +/** + **************************************************************************************** + * @brief Retrieve Task Identifier from Task number + * (automatically update index of task in returned task id) + * + * @param task Task number + * @return Task Identifier + **************************************************************************************** + */ +kernel_task_id_t gapm_get_id_from_task(kernel_msg_id_t task); + +/** + **************************************************************************************** + * @brief Retrieve Task Number from Task Identifier + * (automatically update index of task in returned task id) + * + * @param id Task Identifier + * @return Task Number + **************************************************************************************** + */ +kernel_task_id_t gapm_get_task_from_id(kernel_msg_id_t id); + + + +#if (BLE_GAPC) +/** + **************************************************************************************** + * @brief Created link connection parameters (from bond data) has been set, connection + * ready to be used. + * + * @param[in] conidx Connection Index + * + **************************************************************************************** + */ +void gapm_con_enable(uint8_t conidx); + + +/** + **************************************************************************************** + * @brief A link has been disconnected, clean-up host stack for this connection. + * + * @param[in] conidx Connection Index + * @param[in] conhdl Connection Handle + * @param[in] reason Reason of the disconnection + * + **************************************************************************************** + */ +void gapm_con_cleanup(uint8_t conidx, uint16_t conhdl, uint8_t reason); + +#endif // (BLE_GAPC) + + +/** + **************************************************************************************** + * @brief Retrieve device identity key. + * + * @return Device Identity Key + **************************************************************************************** + */ +struct gap_sec_key *gapm_get_irk(void); + + +/** + **************************************************************************************** + * @brief Retrieve local identity address. + * + * @return Return local identity address + **************************************************************************************** + */ +bd_addr_t *gapm_get_bdaddr(void); + + + +#ifdef BLE_AUDIO_AM0_TASK +/** + **************************************************************************************** + * @brief Return if LE Audio Mode 0 is supported or not + * + * @return True if supported, False else + **************************************************************************************** + */ +bool gapm_is_audio_am0_sup(void); +#endif // BLE_AUDIO_AM0_TASK + + +#if(BLE_EMB_PRESENT && HCI_TL_SUPPORT) +/** + **************************************************************************************** + * @brief Retrieve if host is embedded or not + * + * @return True if embedded host is enabled, false else. + **************************************************************************************** + */ +bool gapm_is_embedded_host(void); + +/** + **************************************************************************************** + * @brief Set if host is embedded or not + * + * @param[in] enable True to enable embedded host, false else. + **************************************************************************************** + */ +void gapm_set_embedded_host(bool enable); +#endif // (BLE_EMB_PRESENT && HCI_TL_SUPPORT) + + + +/** + **************************************************************************************** + * @brief Retrieve the device address type (@see enum gapm_addr_type) + * + * @return address type + **************************************************************************************** + */ +uint8_t gapm_get_address_type(void); + + +#if (BLE_ATTS) + +/** + **************************************************************************************** + * @brief Get if preferred connection parameters present in GAP ATT database + * + * @return True if referred connection parameters present in GAP ATT database, False else + **************************************************************************************** + */ +bool gapm_is_pref_con_param_pres(void); + +/** + **************************************************************************************** + * @brief retrieve gap attribute handle from attribute index. + * + * @param[in] att_idx Attribute index + * + * @return Attribute handle + **************************************************************************************** + */ +uint16_t gapm_get_att_handle(uint8_t att_idx); + +#endif // (BLE_ATTS) + +#if (SECURE_CONNECTIONS) +/** + **************************************************************************************** + * @brief Returns the local Public Key + * + * @return pointer to the local Public Key + **************************************************************************************** + */ +public_key_t *gapm_get_local_public_key(void); +#endif // (SECURE_CONNECTIONS) + +/** + **************************************************************************************** + * @brief Retrieve if Legacy pairing is supported on local device + * + * @return True if legacy pairing is supported + **************************************************************************************** + */ +bool gapm_is_legacy_pairing_supp(void); + + +/** + **************************************************************************************** + * @brief Retrieve if Secure Connection pairing is supported on local device + * + * @return True if Secure Connection pairing is supported + **************************************************************************************** + */ +bool gapm_is_sec_con_pairing_supp(void); + + +#if (BLE_LECB) +/** + **************************************************************************************** + * @brief Check if LECB connection can be registered (established) + * + * @param[in] le_psm LE Protocol/Service Multiplexer + * @param[in] conidx Connection index for app_task computation + * @param[out] app_task Destination application/profile task + * @param[out] sec_lvl Security level requirements + * + * + * @return GAP_ERR_NOT_FOUND if LE_PSM not register, GAP_ERR_NO_ERROR else + **************************************************************************************** + */ +uint8_t gapm_le_psm_get_info(uint16_t le_psm, uint8_t conidx, kernel_task_id_t *app_task, uint8_t *sec_lvl); + + +/** + **************************************************************************************** + * @brief Check if LECB connection can be registered (established) + * + * @param[in] le_psm LE Protocol/Service Multiplexer + * @param[in] peer_con_init Info to know if connection is initiated by peer device + * + * @return L2C_ERR_NO_RES_AVAIL if all LECB link are established, GAP_ERR_NO_ERROR else + **************************************************************************************** + */ +uint8_t gapm_lecb_register(uint16_t le_psm, bool peer_con_init); + + +/** + **************************************************************************************** + * @brief Unregister an existing LECB connection + * + * @param[in] le_psm LE Protocol/Service Multiplexer + * @param[in] peer_con_init Info to know if connection is initiated by peer device + * + * @return GAP_ERR_NO_ERROR + **************************************************************************************** + */ +uint8_t gapm_lecb_unregister(uint16_t le_psm, bool peer_con_init); + +#endif // (BLE_LECB) + +/** + **************************************************************************************** + * @brief Return the maximal MTU value + * + * @param[out] Maximal MTU value + **************************************************************************************** + */ +uint16_t gapm_get_max_mtu(void); + +/** + **************************************************************************************** + * @brief Return the maximal MPS value + * + * @param[out] Maximal MPS value + **************************************************************************************** + */ +uint16_t gapm_get_max_mps(void); + + + +/** + **************************************************************************************** + * @brief Check If Service changed feature is enabled or not + * + * @return true if enabled, false else. + * + **************************************************************************************** + */ +bool gapm_svc_chg_en(void); + +#if (BLE_DEBUG) +/** + **************************************************************************************** + * @brief Check If Debug mode feature is enabled or not + * + * @return true if enabled, false else. + * + **************************************************************************************** + */ +bool gapm_dbg_mode_en(void); + +#if (BLE_ATTS) +/** + **************************************************************************************** + * @brief Force the GAP service start handle + **************************************************************************************** + */ +void gapm_set_svc_start_hdl(uint16_t start_hdl); +#endif //(BLE_ATTS) +#endif // (BLE_DEBUG) + +/** + **************************************************************************************** + * Retrieve if current connection index is used for a discovery purpose such as + * Name discovery + * + * @param conidx Index of the specific connection + * + * @return true if connection has a discovery purpose, False else + **************************************************************************************** + */ +bool gapm_is_disc_connection(uint8_t conidx); + +/// @} GAPM + +#endif /* _GAPM_H_ */ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/inc/gattc.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/inc/gattc.h new file mode 100755 index 0000000..a8a3172 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/inc/gattc.h @@ -0,0 +1,178 @@ +/** + **************************************************************************************** + * + * @file gattc.h + * + * @brief Header file - GATT Controller. + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + +#ifndef GATTC_H_ +#define GATTC_H_ + +/** + **************************************************************************************** + * @addtogroup GATTC Generic Attribute Profile Controller + * @ingroup GATT + * @brief Generic Attribute Profile Controller. + * + * This GATT module is responsible for providing an API for all attribute related operations + * related to a BLE connection. + * It is responsible for all the service framework activities using the Attribute protocol + * for discovering services and for reading and writing characteristic values on a peer device. + * To achieve this, the GATT interfaces with @ref ATTC "ATTC" and the @ref ATTS "ATTS". + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +/* kernel task */ +#include "rwip_config.h" +#if (BLE_GATTC) + +#include "common_list.h" + + +/* + * DEFINES + **************************************************************************************** + */ + +/// Operation type +enum gattc_op_type +{ +#if (BLE_ATTS) + /// Operation used to Server Request operations + GATTC_OP_SERVER, +#endif // (BLE_ATTS) + +#if (BLE_ATTC) + /// Operation used to Client Request operations + GATTC_OP_CLIENT, + /// Service Discovery Procedure operation + GATTC_OP_SDP, +#endif // (BLE_ATTC) + + /// Max number of operations + GATTC_OP_MAX +}; + +/* + * TYPES DEFINITIONS + **************************************************************************************** + */ + +#if (BLE_ATTC) +/// Attribute Client environment variable requirements +struct attc_env +{ + /// List of ATT message used to aggregate long value in a single buffer. + struct common_list rsp_list; + /// List that contains peer device event registration + struct common_list reg_evt; + /// List that contains data for service discovery + struct common_list sdp_data; +}; +#endif // (BLE_ATTC) + +#if (BLE_ATTS) +/// Attribute server environment variables +struct atts_env +{ + /// This is used to merge save all the prepare write request received , + /// before receiving the execute or cancel or disconnection. + struct common_list prep_wr_req_list; + /// This list is used to put any data in order to send a response to peer device + struct common_list rsp; + /// List of PDU to process + struct common_list pdu_queue; + /// This structure is used to store in cache latest attribute read value + struct gattc_read_cfm *read_cache; + /// pointer to the PDU which is currently handled by ATTS + struct l2cc_pdu_recv_ind *pdu; +}; +#endif // (BLE_ATTS) + +/// GATT controller environment variable structure. +struct gattc_env_tag +{ + /// Request operation Kernel message + void *operation[GATTC_OP_MAX]; + +#if (BLE_ATTC) + struct attc_env client; +#endif // (BLE_ATTC) + +#if (BLE_ATTS) + struct atts_env server; +#endif // (BLE_ATTS) + + /// Current MTU Size + uint16_t mtu_size; + + /// A transaction timeout occurs, reject next attribute commands + bool trans_timeout; +}; +/* + * MACRO DEFINITIONS + **************************************************************************************** + */ + + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + + +/** + **************************************************************************************** + * @brief Created link connection parameters (from bond data) has been set, connection + * ready to be used. + * + * @param[in] conidx Connection Index + * + **************************************************************************************** + */ +void gattc_con_enable(uint8_t conidx); + + +/** + **************************************************************************************** + * @brief Gets the negotiated MTU. This function gets the negotiated MTU. + * + * @param[in] idx connection record index + * + * @return MTU negotiated + * + **************************************************************************************** + */ +uint16_t gattc_get_mtu(uint8_t idx); + +/** + **************************************************************************************** + * @brief Sets the negotiated MTU This function stores the negotiated MTU. + * + * @param[in] idx connection record index + * @param[in] mtu negotiated MTU + * + * @return status indicates if the MTU setting operation is successful + * + **************************************************************************************** + */ +void gattc_set_mtu(uint8_t idx, uint16_t mtu); + + + +#endif /* (BLE_GATTC) */ + +/// @} GATTC +#endif // GATTC_H_ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/inc/gattm.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/inc/gattm.h new file mode 100755 index 0000000..2046762 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/inc/gattm.h @@ -0,0 +1,117 @@ +/** + **************************************************************************************** + * + * @file gattm.h + * + * @brief Header file - GATT Manager. + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + +#ifndef GATTM_H_ +#define GATTM_H_ + + + +/** + **************************************************************************************** + * @addtogroup GATTM Generic Attribute Profile Manager + * @ingroup GATT + * @brief Generic Attribute Profile. + * + * The GATT manager module is responsible for providing an API for all action operations + * not related to a connection. It's responsible to managing internal database. + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +/* kernel task */ +#include "rwip_config.h" + +#if (BLE_CENTRAL || BLE_PERIPHERAL) +#include +#include + +/* + * DEFINES + **************************************************************************************** + */ + + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Initialization of the GATT manager module. + * This function performs all the initialization steps of the GATT module. + * + * @param[in] reset true if it's requested by a reset; false if it's boot initialization + * + **************************************************************************************** + */ +void gattm_init(bool reset); + + +/** + **************************************************************************************** + * @brief Initialize GATT attribute database + * + * @param[in] start_hdl Service Start Handle + * @param[in] svc_chg_en Service Change feature enabled + * + * @return status code of attribute database initialization + * Command status code: + * - @ref ATT_ERR_NO_ERROR: If database creation succeeds. + * - @ref ATT_ERR_INVALID_HANDLE: If start_hdl given in parameter + nb of attribute override + * some existing services handles. + * - @ref ATT_ERR_INSUFF_RESOURCE: There is not enough memory to allocate service buffer. + * or of new attribute cannot be added because all expected + * attributes already add + **************************************************************************************** + */ +uint8_t gattm_init_attr(uint16_t start_hdl, bool svc_chg_en); + +/** + **************************************************************************************** + * @brief Initialize GATT resources for connection. + * + * @param[in] conidx connection record index + * @param[in] role device role after connection establishment + * + **************************************************************************************** + */ +void gattm_create(uint8_t conidx); +/** + **************************************************************************************** + * @brief Cleanup GATT resources for connection + * + * @param[in] conidx connection record index + * + **************************************************************************************** + */ +void gattm_cleanup(uint8_t conidx); + + +#if (BLE_ATTS) +/** + **************************************************************************************** + * @brief Return the start handle of the GATT service in the database * + **************************************************************************************** + */ +uint16_t gattm_svc_get_start_hdl(void); +#endif //(BLE_ATTS) +#endif /* (BLE_CENTRAL || BLE_PERIPHERAL) */ + +/// @} GATTM +#endif // GATTM_H_ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/inc/l2cc.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/inc/l2cc.h new file mode 100755 index 0000000..35748c7 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/inc/l2cc.h @@ -0,0 +1,258 @@ +/** + **************************************************************************************** + * + * @file l2cc.h + * + * @brief Header file - L2CC. + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + +#ifndef L2CC_H_ +#define L2CC_H_ + +/** + **************************************************************************************** + * @addtogroup L2CC L2CAP Controller + * @ingroup L2C + * @brief L2CAP block for data processing and per device connection + * + * The L2CC is responsible for all the data processing related + * functions of the L2CAP block per device connection. + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" + +#if (BLE_L2CC) + +#include "l2cc_task.h" +#include "l2cc_pdu.h" + +#include +#include +#include "common_list.h" +#include "kernel_task.h" + +/* + * DEFINES + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Generic way to creates and allocate a Signaling PDU message that can be then + * sent to peer device + * + * @param[in] conidx Connection Index + * @param[in] code PDU code + * @param[in] src_id Source task ID + * + * @return Pointer to the PDU payload + **************************************************************************************** + */ +#define L2CC_SIG_PDU_ALLOC(conidx, code, src_id, type) \ + ((struct type*) l2cc_pdu_alloc(conidx, L2C_CID_LE_SIGNALING, code, src_id, 0)) + +/// from PDU, retrieve the send command +#define L2CC_PDU_TO_CMD(_pdu) \ + ((struct l2cc_pdu_send_cmd*) (((uint8_t*)_pdu) - offsetof(struct l2cc_pdu_send_cmd, pdu.data.code))) + +/// from PDU, retrieve the receive indication +#define L2CC_PDU_TO_IND(_pdu) \ + ((struct l2cc_pdu_recv_ind*) (((uint8_t*)_pdu) - offsetof(struct l2cc_pdu_recv_ind, pdu.data.code))) + + +/** + **************************************************************************************** + * @brief Generic way to creates and allocate a SMP PDU message that can be then sent to + * peer device + * + * @param[in] conidx Connection Index + * @param[in] code PDU code + * @param[in] src_id Source task ID + * + * @return Pointer to the PDU payload + **************************************************************************************** + */ +#define L2CC_SMP_PDU_ALLOC(conidx, code, src_id, type) \ + ((struct type*) l2cc_pdu_alloc(conidx, L2C_CID_SECURITY, code, src_id, 0)) + + +/** + **************************************************************************************** + * @brief Generic way to creates and allocate an ATT PDU message that can be then sent to + * peer device + * + * @param[in] conidx Connection Index + * @param[in] code PDU code + * @param[in] src_id Source task ID + * + * @return Pointer to the PDU payload + **************************************************************************************** + */ +#define L2CC_ATT_PDU_ALLOC(conidx, code, src_id, type)\ + ((struct type*) l2cc_pdu_alloc(conidx, L2C_CID_ATTRIBUTE, code, src_id, 0)) + + +/** + **************************************************************************************** + * @brief Generic way to creates and allocate an ATT PDU message that can be then sent to + * peer device + * + * @param[in] conidx Connection Index + * @param[in] code PDU code + * @param[in] src_id Source task ID + * @param[in] length Dynamic payload length to allocate + * + * @return Pointer to the PDU payload + **************************************************************************************** + */ +#define L2CC_ATT_PDU_ALLOC_DYN(conidx, code, src_id, type, length)\ + ((struct type*) l2cc_pdu_alloc(conidx, L2C_CID_ATTRIBUTE, code, src_id, length)) + +/* + * INTERNAL MESSAGES API TYPES + **************************************************************************************** + */ + + + +/// Send Debug PDU data +struct l2cc_dbg_pdu_send_cmd +{ + /// L2CC request type (@see enum l2cc_operation): + /// - L2CC_DBG_PDU_SEND: Send a PDU + uint8_t operation; + /// offset value information + uint16_t offset; + /// PDU Data + struct l2cc_dbg_pdu pdu; +}; + +/// Debug PDU data received +struct l2cc_dbg_pdu_recv_ind +{ + /// Status information + uint8_t status; + /// offset value information + uint16_t offset; + /// PDU Data + struct l2cc_dbg_pdu pdu; +}; + +/// Send Legacy PDU data +struct l2cc_pdu_send_cmd +{ + /// L2CC request type (@see enum l2cc_operation): + /// - L2CC_PDU_SEND: Send internal LE Legacy PDU + uint8_t operation; + /// offset value information + uint16_t offset; + /// PDU Data + struct l2cc_pdu pdu; +}; + + +/// Legacy PDU data received +struct l2cc_pdu_recv_ind +{ + /// Status information + uint8_t status; + /// offset value information + uint16_t offset; + /// PDU Data + struct l2cc_pdu pdu; +}; + +/// Operation type +enum l2cc_op_type +{ + /// Operation used for signaling protocol message exchange + L2CC_OP_SIG = 0x00, + /// Max number of operations + L2CC_OP_MAX, +}; + +/* + * STRUCTURES + **************************************************************************************** + */ + + + +/// L2CAP environment structure +struct l2cc_env_tag +{ + /// Ongoing operation + void *operation[L2CC_OP_MAX]; + + /// Buffer in TX queue + struct common_list tx_queue; + /// Buffer currently receiving data + struct kernel_msg *rx_buffer; +#if (BLE_LECB) + /// List of LE credit based connections + struct common_list lecb_list; +#endif // (BLE_LECB) + + /// Length of PDU still expected + uint16_t rx_pdu_rem_len; + /// Cursor into the the received header + uint8_t rx_cursor; + /// Expected cursor header length + uint8_t rx_exp_len; + /// Temporary buffer for reception of an l2cap packet + uint8_t rx_buf[L2C_HEADER_LEN + L2C_MIN_LE_MTUSIG]; +}; + + + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Generic way to creates and allocate a PDU message that can be then sent to peer + * device + * + * @note use L2CC_SIG_PDU_ALLOC, L2CC_SMP_PDU_ALLOC, L2CC_ATT_PDU_ALLOC + * or L2CC_ATT_PDU_ALLOC_DYN instead of direct function call + * + * @param[in] conidx Connection Index + * @param[in] cid Channel Identifier + * @param[in] code PDU code + * @param[in] src_id Source task ID + * @param[in] length Dynamic payload length to allocate + * + * @return Generic pointer to the PDU payload + **************************************************************************************** + */ +void *l2cc_pdu_alloc(uint8_t conidx, uint16_t cid, uint8_t code, kernel_task_id_t src_id, uint16_t length); + +/** + **************************************************************************************** + * @brief Generic way to send the PDU message + * + * @param[in] pdu PDU message to send to peer device + **************************************************************************************** + */ +void l2cc_pdu_send(void *pdu); + +#endif //(BLE_L2CC) + +/// @} L2CC + +#endif // L2CC_H_ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/inc/l2cc_pdu.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/inc/l2cc_pdu.h new file mode 100755 index 0000000..40a3d25 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/inc/l2cc_pdu.h @@ -0,0 +1,1111 @@ +/** + **************************************************************************************** + * + * @file l2cc_pdu.h + * + * @brief Header file - L2CAP Controller PDU packer / unpacker + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + + +#ifndef _L2CC_PDU_H_ +#define _L2CC_PDU_H_ + +/** + **************************************************************************************** + * @addtogroup L2CC_PDU L2Cap Controller PDU generator/extractor + * @ingroup L2CC + * @brief This module is in charge to pack or unpack L2CAP packets + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "common_bt.h" +#include "gap.h" +#include "att.h" +#include "ble_compiler.h" + +/* + * MACROS + **************************************************************************************** + */ + + +/* + * DEFINES + **************************************************************************************** + */ + +/// Minimal authorized MTU value (defined by Bluetooth SIG) +#define L2C_MIN_LE_MTUSIG (23) + +/// L2CAP mode supported for BLE - only mode accepted +#define L2C_MODE_BASIC_L2CAP (0x00) + +/// Packet partition +#define L2C_CID_LEN (2) +#define L2C_LENGTH_LEN (2) +#define L2C_CODE_LEN (1) +#define L2C_HEADER_LEN (L2C_CID_LEN + L2C_LENGTH_LEN) +#define L2C_SDU_LEN (2) +#define L2C_LECB_HEADER_LEN (L2C_HEADER_LEN + L2C_SDU_LEN) + +/// Maximum credit +#define L2C_LECB_MAX_CREDIT 0xFFFF + + +/* result for connection parameter update response */ +#define L2C_CONN_PARAM_ACCEPT 0x0000 +#define L2C_CONN_PARAM_REJECT 0x0001 + +/* command reject reasons */ +enum l2cc_pdu_err +{ + L2C_CMD_NOT_UNDERSTOOD = 0x0000, + L2C_MTU_SIG_EXCEEDED = 0x0001, + L2C_INVALID_CID = 0x0002, +}; + +/* Flag to describe the packet boundary */ +#define L2C_PB_START_NON_FLUSH 0x00 +#define L2C_PB_CONTINUE 0x01 +#define L2C_PB_START_FLUSH 0x02 + +/// Check if channel ID is within the correct range +#define L2C_IS_DYNAMIC_CID(cid) ((cid >= L2C_CID_DYN_MIN) && (cid <= L2C_CID_DYN_MAX)) + +/// Check if LE PSM is within the correct range +#define L2C_IS_VALID_LEPSM(lepsm) (lepsm != L2C_LEPSM_RESERVED) + +/* + * ENUMERATIONS + **************************************************************************************** + */ + +/** L2CAP LE PSM limits */ +enum l2cc_lepsm_limits +{ + /// Reserved + L2C_LEPSM_RESERVED = 0x0000, + /// Fixed minimum range SIG assigned + L2C_LEPSM_FIXED_MIN = 0x0001, + /// Fixed maximum range SIG assigned + L2C_LEPSM_FIXED_MAX = 0x007F, + /// Dynamic minimum range SIG assigned + L2C_LEPSM_DYN_MIN = 0x0080, + /// Dynamic maximum range SIG assigned + L2C_LEPSM_DYN_MAX = 0x00FF, + /// Reserved minimum range SIG assigned + L2C_LEPSM_RSV_MIN = 0x0100, + /// Reserved maximum range SIG assigned + L2C_LEPSM_RSV_MAX = 0xFFFF, +}; + +/** L2CAP channels id */ +enum l2cc_cid +{ + /// Reserved channel id + L2C_CID_RESERVED = 0x0000, + /// Attribute channel id + L2C_CID_ATTRIBUTE = 0x0004, + /// Signaling channel id + L2C_CID_LE_SIGNALING = 0x0005, + /// Security channel id + L2C_CID_SECURITY = 0x0006, + /// Dynamically allocated minimum range + L2C_CID_DYN_MIN = 0x0040, + /// Dynamically allocated maximum range + L2C_CID_DYN_MAX = 0x007F, +}; + + +/// signaling codes +enum l2cc_signal_code +{ + /// Reserved code + L2C_CODE_RESERVED = 0x00, + /// Reject request + L2C_CODE_REJECT = 0x01, + /// Connection request + L2C_CODE_CONNECTION_REQ = 0x02, + /// Connection response + L2C_CODE_CONNECTION_RESP = 0x03, + /// Configuration request + L2C_CODE_CONFIGURATION_REQ = 0x04, + /// Configuration response + L2C_CODE_CONFIGURATION_RESP = 0x05, + /// Disconnection request + L2C_CODE_DISCONNECTION_REQ = 0x06, + /// Disconnection response + L2C_CODE_DISCONNECTION_RESP = 0x07, + /// Echo request + L2C_CODE_ECHO_REQ = 0x08, + /// Echo response + L2C_CODE_ECHO_RESP = 0x09, + /// Information request + L2C_CODE_INFORMATION_REQ = 0x0A, + /// Information response + L2C_CODE_INFORMATION_RESP = 0x0B, + /// Create channel request + L2C_CODE_CREATE_CHANNEL_REQ = 0x0C, + /// Create channel response + L2C_CODE_CREATE_CHANNEL_RESP = 0x0D, + /// Move channel request + L2C_CODE_MOVE_CHANNEL_REQ = 0x0E, + /// Move channel response + L2C_CODE_MOVE_CHANNEL_RESP = 0x0F, + /// Move channel confirmation + L2C_CODE_MOVE_CHANNEL_CFM = 0x10, + /// Move channel confirmation response + L2C_CODE_MOVE_CHANNEL_CFM_RESP = 0x11, + /// Connection Parameter Update Request + L2C_CODE_CONN_PARAM_UPD_REQ = 0x12, + /// Connection Parameter Update Response + L2C_CODE_CONN_PARAM_UPD_RESP = 0x13, + /// LE Credit Based Connection request + L2C_CODE_LE_CB_CONN_REQ = 0x14, + /// LE Credit Based Connection response + L2C_CODE_LE_CB_CONN_RESP = 0x15, + /// LE Flow Control Credit + L2C_CODE_LE_FLOW_CONTROL_CREDIT = 0x16, + + /// max number of signaling codes + L2C_CODE_SIGNALING_MAX +}; + + +/// security codes +enum l2cc_security_code +{ + /// Pairing Request + L2C_CODE_PAIRING_REQUEST = 0x01, + /// Pairing Response + L2C_CODE_PAIRING_RESPONSE = 0x02, + /// Pairing Confirm + L2C_CODE_PAIRING_CONFIRM = 0x03, + /// Pairing Random + L2C_CODE_PAIRING_RANDOM = 0x04, + /// Pairing Failed + L2C_CODE_PAIRING_FAILED = 0x05, + /// Encryption Information + L2C_CODE_ENCRYPTION_INFORMATION = 0x06, + /// Master Identification + L2C_CODE_MASTER_IDENTIFICATION = 0x07, + /// Identity Information + L2C_CODE_IDENTITY_INFORMATION = 0x08, + /// Identity Address Information + L2C_CODE_IDENTITY_ADDRESS_INFORMATION = 0x09, + /// Signing Information + L2C_CODE_SIGNING_INFORMATION = 0x0A, + /// Security Request + L2C_CODE_SECURITY_REQUEST = 0x0B, + // Pairing Public Keys + L2C_CODE_PUBLIC_KEY = 0x0C, + // Pairing DHKey Check + L2C_CODE_DHKEY_CHECK = 0x0D, + // Pairing Keypress Notification + L2C_CODE_KEYPRESS_NOTIFICATION = 0x0E, + /// max number of security codes + L2C_CODE_SECURITY_MAX +}; + + +/// attribute protocol PDU codes +enum l2cc_attribute_code +{ + /// Error response + L2C_CODE_ATT_ERR_RSP = 0x01, + /// Exchange MTU Request + L2C_CODE_ATT_MTU_REQ = 0x02, + /// Exchange MTU Response + L2C_CODE_ATT_MTU_RSP = 0x03, + /// Find Information Request + L2C_CODE_ATT_FIND_INFO_REQ = 0x04, + /// Find Information Response + L2C_CODE_ATT_FIND_INFO_RSP = 0x05, + /// Find By Type Value Request + L2C_CODE_ATT_FIND_BY_TYPE_REQ = 0x06, + /// Find By Type Value Response + L2C_CODE_ATT_FIND_BY_TYPE_RSP = 0x07, + /// Read By Type Request + L2C_CODE_ATT_RD_BY_TYPE_REQ = 0x08, + /// Read By Type Response + L2C_CODE_ATT_RD_BY_TYPE_RSP = 0x09, + /// Read Request + L2C_CODE_ATT_RD_REQ = 0x0A, + /// Read Response + L2C_CODE_ATT_RD_RSP = 0x0B, + /// Read Blob Request + L2C_CODE_ATT_RD_BLOB_REQ = 0x0C, + /// Read Blob Response + L2C_CODE_ATT_RD_BLOB_RSP = 0x0D, + /// Read Multiple Request + L2C_CODE_ATT_RD_MULT_REQ = 0x0E, + /// Read Multiple Response + L2C_CODE_ATT_RD_MULT_RSP = 0x0F, + /// Read by Group Type Request + L2C_CODE_ATT_RD_BY_GRP_TYPE_REQ = 0x10, + /// Read By Group Type Response + L2C_CODE_ATT_RD_BY_GRP_TYPE_RSP = 0x11, + /// Write Request + L2C_CODE_ATT_WR_REQ = 0x12, + /// Write Response + L2C_CODE_ATT_WR_RSP = 0x13, + /// Write Command + L2C_CODE_ATT_WR_CMD_INFO = 0x14, + L2C_CODE_ATT_WR_CMD = 0x52, + /// Signed Write Command + L2C_CODE_ATT_SIGN_WR_CMD_INFO = 0x15, + L2C_CODE_ATT_SIGN_WR_CMD = 0xD2, + /// Prepare Write Request + L2C_CODE_ATT_PREP_WR_REQ = 0x16, + /// Prepare Write Response + L2C_CODE_ATT_PREP_WR_RSP = 0x17, + /// Execute Write Request + L2C_CODE_ATT_EXE_WR_REQ = 0x18, + /// Execute Write Response + L2C_CODE_ATT_EXE_WR_RSP = 0x19, + /// Handle Value Notification + L2C_CODE_ATT_HDL_VAL_NTF = 0x1B, + /// Handle Value Indication + L2C_CODE_ATT_HDL_VAL_IND = 0x1D, + /// Handle Value Confirmation + L2C_CODE_ATT_HDL_VAL_CFM = 0x1E, + + /// max number of security codes + L2C_CODE_ATT_MAX +}; + +/// LE Connection oriented PDU codes +enum l2cc_le_connor_code +{ + /// Data frame + L2C_CODE_CON_DATA = 0x01, + + /// max number of connection oriented codes + L2C_CODE_CON_MAX +}; + +/// Result values for LE Credit Based Connection Response +enum l2cc_cb_resp_value +{ + /// connection successful + L2C_CB_CON_SUCCESS = 0x0000, + /// Reserved + L2C_CB_CON_RSV1, + /// Connection refused - LE_PSM not supported + L2C_CB_CON_LEPSM_NOT_SUPP, + /// Reserved + L2C_CB_CON_RSV2, + /// Connection refused - no resources available + L2C_CB_CON_NO_RES_AVAIL, + /// Connection refused - insufficient authentication + L2C_CB_CON_INS_AUTH, + /// Connection refused - insufficient authorization + L2C_CB_CON_INS_AUTHOR, + /// Connection refused - insufficient encryption key size + L2C_CB_CON_INS_EKS, + /// Connection Refused - insufficient encryption + L2C_CB_CON_INS_ENCRYPTION, + + /* ESR 09 error codes */ + /// Connection Refused - invalid Source CID + L2C_CB_CON_INVALID_SRC_CID, + /// Connection Refused - Source CID already allocated + L2C_CB_CON_SRC_CID_ALREADY_ALLOC, + /// Connection Refused - Unacceptable parameters + L2C_CB_CON_UNACCEPTABLE_PARAM +}; + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + +/// Disconnection Request +struct l2cc_disconnection_req +{ + /// Signaling code - 0x06 + uint8_t code; + /// Packet Identifier + uint8_t pkt_id; + /// data length + uint16_t length; + /// Destination CID + uint16_t dcid; + /// Source CID + uint16_t scid; +}; + +/// Disconnection Response +struct l2cc_disconnection_rsp +{ + /// Signaling code - 0x07 + uint8_t code; + /// Packet Identifier + uint8_t pkt_id; + /// data length + uint16_t length; + /// Destination CID + uint16_t dcid; + /// Source CID + uint16_t scid; +}; + +/// Connection Parameter Update Request +struct l2cc_update_param_req +{ + /// Signaling code - 0x12 + uint8_t code; + /// Packet Identifier + uint8_t pkt_id; + /// data length + uint16_t length; + /// minimum value for the connection event interval + uint16_t intv_min; + /// maximum value for the connection event interval + uint16_t intv_max; + /// slave latency parameter + uint16_t latency; + /// connection timeout parameter + uint16_t timeout; +}; + +/// Connection Parameter Update Response +struct l2cc_update_param_rsp +{ + /// Signaling code - 0x13 + uint8_t code; + /// Packet Identifier + uint8_t pkt_id; + /// data length + uint16_t length; + /// Result field indicates the response to the Connection Parameter Update Request + /// - 0x0000 Connection Parameters accepted + /// - 0x0001 Connection Parameters rejected + uint16_t response; +}; + +/// LE Credit based connection request +struct l2cc_lecb_req +{ + /// Signaling code - 0x14 + uint8_t code; + /// Packet Identifier + uint8_t pkt_id; + /// data length + uint16_t length; + /// LE Protocol/Service Multiplexer + uint16_t le_psm; + /// Source CID + uint16_t scid; + /// Maximum Transmission Unit + uint16_t mtu; + /// Maximum PDU Size + uint16_t mps; + /// Initial credits + uint16_t initial_credits; +}; + +/// LE Credit based connection response +struct l2cc_lecb_rsp +{ + /// Signaling code - 0x15 + uint8_t code; + /// Packet Identifier + uint8_t pkt_id; + /// data length + uint16_t length; + /// Destination CID + uint16_t dcid; + /// Maximum Transmission Unit + uint16_t mtu; + /// Maximum PDU Size + uint16_t mps; + /// Initial credits + uint16_t initial_credits; + /// Result + uint16_t result; +}; + +/// LE Flow Control Credit +struct l2cc_le_flow_ctl_credit +{ + /// Signaling code - 0x16 + uint8_t code; + /// Packet Identifier + uint8_t pkt_id; + /// data length + uint16_t length; + /// CID + uint16_t cid; + /// Credits + uint16_t credits; +}; + +/// Command Reject +struct l2cc_reject +{ + /// Signaling code - 0x01 + uint8_t code; + /// Packet Identifier + uint8_t pkt_id; + /// data length + uint16_t length; + /// The Reason field describes why the Request packet was rejected + /// - 0x0000 Command not understood + /// - 0x0001 Signaling MTU exceeded + /// - 0x0002 Invalid CID in request + uint16_t reason; + /// Optional parameters total length + uint16_t opt_len; + ///16-byte array for optional parameters + uint8_t opt[__ARRAY_EMPTY]; +}; + + +/// Pairing Request +struct l2cc_pairing_req +{ + /// security code - 0x01 + uint8_t code; + /// IO Capability + uint8_t iocap; + /// OOB data flag + uint8_t oob; + /// AuthReq + uint8_t auth; + /// Maximum Encryption Key Size + uint8_t key_size; + /// Initiator Key Distribution + uint8_t ikey_dist; + /// Responder Key Distribution + uint8_t rkey_dist; +}; +/// Pairing Response +struct l2cc_pairing_rsp +{ + /// security code - 0x02 + uint8_t code; + /// IO Capability + uint8_t iocap; + /// OOB data flag + uint8_t oob; + /// AuthReq + uint8_t auth; + /// Maximum Encryption Key Size + uint8_t key_size; + /// Initiator Key Distribution + uint8_t ikey_dist; + /// Responder Key Distribution + uint8_t rkey_dist; +}; +/// Pairing Confirm +struct l2cc_pairing_cfm +{ + /// security code - 0x03 + uint8_t code; + ///Confirm value + uint8_t cfm_val[CFM_LEN]; +}; +/// Pairing Random +struct l2cc_pairing_random +{ + /// security code - 0x04 + uint8_t code; + ///Random value + uint8_t random[RAND_VAL_LEN]; +}; +/// Pairing Failed +struct l2cc_pairing_failed +{ + /// security code - 0x05 + uint8_t code; + /// The Reason field indicates why the pairing failed + uint8_t reason; +}; +/// Encryption Information +struct l2cc_encryption_inf +{ + /// security code - 0x06 + uint8_t code; + ///16-byte array for LTK value + uint8_t ltk[GAP_KEY_LEN]; +}; +/// Master Identification +struct l2cc_master_id +{ + /// security code - 0x07 + uint8_t code; + /// key diversifier + uint16_t ediv; + ///8-byte array for random number + uint8_t nb[GAP_RAND_NB_LEN]; +}; +/// Identity Information +struct l2cc_identity_inf +{ + /// security code - 0x08 + uint8_t code; + ///16-byte array for IRK value + uint8_t irk[GAP_KEY_LEN]; +}; +/// Identity Address Information +struct l2cc_id_addr_inf +{ + /// security code - 0x09 + uint8_t code; + /// BD Address Type + uint8_t addr_type; + /// BD Address + bd_addr_t addr; +}; +/// Signing Information +struct l2cc_signing_inf +{ + /// security code - 0x0A + uint8_t code; + ///16-byte array for CSRK value + uint8_t csrk[GAP_KEY_LEN]; +}; +/// Security Request +struct l2cc_security_req +{ + /// security code - 0x0B + uint8_t code; + /// AuthReq + uint8_t auth; +}; + +/// Public Key (x,y) +struct l2cc_public_key +{ + /// security code - 0x0C + uint8_t code; + /// X and Y co-ordinates of the Public Key + uint8_t x[GAP_P256_KEY_LEN]; + uint8_t y[GAP_P256_KEY_LEN]; +}; + +/// DH Key Check +struct l2cc_dhkey_check +{ + /// security code - 0x0D + uint8_t code; + uint8_t check[DHKEY_CHECK_LEN]; +}; +/// Keypress Notification - PassKey method only +struct l2cc_keypress_notification +{ + /// security code - 0x0E + uint8_t code; + + uint8_t notification_type; +}; + + +/* Attribute protocol PDUs */ + +/// Error response +struct l2cc_att_err_rsp +{ + /// Error Response - 0x01 + uint8_t code; + /// The request that generated this error response + uint8_t op_code; + /// The attribute handle that generated this error response + uint16_t handle; + ///The reason why the request has generated an error response + uint8_t reason; +}; + +/// Exchange MTU Request +struct l2cc_att_mtu_req +{ + /// Exchange MTU Request - 0x02 + uint8_t code; + /// Client Rx MTU size + uint16_t mtu_size; +}; + +/// Exchange MTU Response +struct l2cc_att_mtu_rsp +{ + /// Exchange MTU Response - 0x03 + uint8_t code; + /// Server Rx MTU size + uint16_t mtu_size; +}; + +/// Find Information Request +struct l2cc_att_find_info_req +{ + /// Find Information Request - 0x04 + uint8_t code; + /// First requested handle number + uint16_t shdl; + /// Last requested handle number + uint16_t ehdl; +}; + +/// Find Information Response +struct l2cc_att_find_info_rsp +{ + /// Find Information Response - 0x05 + uint8_t code; + /// The format of the information data. + uint8_t format; + /// Data length + uint16_t data_len; + ///The information data whose format is determined by the Format field + uint8_t data[__ARRAY_EMPTY]; +}; + +/// Find By Type Value Request +struct l2cc_att_find_by_type_req +{ + /// Find By Type Value Request - 0x06 + uint8_t code; + /// First requested handle number + uint16_t shdl; + /// Last requested handle number + uint16_t ehdl; + /// 2 octet UUID to find + uint16_t type; + /// Attribute value length + uint16_t val_len; + /// Attribute value to find + uint8_t val[__ARRAY_EMPTY]; +}; + +/// Find By Type Value Response +struct l2cc_att_find_by_type_rsp +{ + /// Find By Type Value Response - 0x07 + uint8_t code; + /// data length + uint16_t data_len; + /// A list of 1 or more Handle Informations. + uint8_t data[__ARRAY_EMPTY]; +}; + +/// Read By Type Request +struct l2cc_att_rd_by_type_req +{ + /// Read By Type Request - 0x08 + uint8_t code; + /// Starting Handle + uint16_t shdl; + /// Ending Handle + uint16_t ehdl; + /// Attribute uuid length + uint16_t uuid_len; + /// Attribute type uuid + uint8_t uuid[__ARRAY_EMPTY]; +}; + +/// Read By Type Response +struct l2cc_att_rd_by_type_rsp +{ + /// Read By Type Response - 0x09 + uint8_t code; + /// size of each attribute handle listed + uint8_t each_len; + /// Attribute Data length + uint16_t data_len; + /// A list of Attribute Data. + uint8_t data[__ARRAY_EMPTY]; +}; + +/// Read Request +struct l2cc_att_rd_req +{ + /// Read Request - 0x0A + uint8_t code; + /// Attribute Handle + uint16_t handle; +}; + +/// Read Response +struct l2cc_att_rd_rsp +{ + /// Read Response - 0x0B + uint8_t code; + /// value length + uint16_t value_len; + /// The value of the attribute with the handle given + uint8_t value[__ARRAY_EMPTY]; +}; + +/// Read Blob Request +struct l2cc_att_rd_blob_req +{ + /// Read Blob Request - 0x0C + uint8_t code; + /// Attribute Handle + uint16_t handle; + /// The offset of the first octet to be read + uint16_t offset; +}; + +/// Read Blob Response +struct l2cc_att_rd_blob_rsp +{ + /// Read Blob Response - 0x0D + uint8_t code; + /// value length + uint16_t value_len; + /// Part of the value of the attribute with the handle given + uint8_t value[__ARRAY_EMPTY]; +}; + +/// Read Multiple Request +struct l2cc_att_rd_mult_req +{ + /// Read Multiple Request - 0x0E + uint8_t code; + /// Number of handles + uint16_t nb_handles; + /// A set of two or more attribute handles. + uint16_t handles[__ARRAY_EMPTY]; +}; + +/// Read Multiple Response +struct l2cc_att_rd_mult_rsp +{ + /// Read Multiple Response - 0x0F + uint8_t code; + /// value length + uint16_t value_len; + /// A set of two or more values. + uint8_t value[__ARRAY_EMPTY]; +}; + +/// Read by Group Type Request +struct l2cc_att_rd_by_grp_type_req +{ + /// Read by Group Type Request - 0x10 + uint8_t code; + /// First requested handle number + uint16_t shdl; + /// Last requested handle number + uint16_t ehdl; + /// Attribute uuid length + uint16_t uuid_len; + /// Attribute type uuid (2 or 16 octet UUID) + uint8_t uuid[__ARRAY_EMPTY]; +}; + +/// Read By Group Type Response +struct l2cc_att_rd_by_grp_type_rsp +{ + /// Read By Group Type Response - 0x11 + uint8_t code; + /// size of each attribute handle listed + uint8_t each_len; + /// Attribute Data length + uint16_t data_len; + /// A list of Attribute Data. + uint8_t data[__ARRAY_EMPTY]; +}; + +/// Write Request +struct l2cc_att_wr_req +{ + /// Write Request - 0x12 + uint8_t code; + /// The handle of the attribute to be written + uint16_t handle; + /// Value length + uint16_t value_len; + /// The value to be written to the attribute + uint8_t value[__ARRAY_EMPTY]; +}; + +/// Write Response +struct l2cc_att_wr_rsp +{ + /// Write Response - 0x13 + uint8_t code; +}; + +/// Write Command +struct l2cc_att_wr_cmd +{ + /// Write Command - 0x52 + uint8_t code; + /// The handle of the attribute to be written + uint16_t handle; + /// Value length + uint16_t value_len; + /// The value to be written to the attribute + uint8_t value[__ARRAY_EMPTY]; +}; + +/// Signed Write Command +struct l2cc_att_sign_wr_cmd +{ + /// Write Command - 0xD2 + uint8_t code; + /// The handle of the attribute to be written + uint16_t handle; + /// Attribute Data length + uint16_t value_len; + /// The value to be written to the attribute + /// + 12 bytes of signatures: + /// Authentication signature for the Attribute Upload, Attribute Handle and Attribute + /// Value Parameters + uint8_t value[__ARRAY_EMPTY]; +}; + +/// Prepare Write Request +struct l2cc_att_prep_wr_req +{ + /// Prepare Write Request - 0x16 + uint8_t code; + /// The handle of the attribute to be written + uint16_t handle; + /// The offset of the first octet to be written + uint16_t offset; + /// Value length + uint16_t value_len; + /// The value to be written to the attribute + uint8_t value[__ARRAY_EMPTY]; +}; + +/// Prepare Write Response +struct l2cc_att_prep_wr_rsp +{ + /// Prepare Write Response - 0x17 + uint8_t code; + /// The handle of the attribute to be written + uint16_t handle; + /// The offset of the first octet to be written + uint16_t offset; + /// Value length + uint16_t value_len; + /// The value to be written to the attribute + uint8_t value[__ARRAY_EMPTY]; +}; + +/// Execute Write Request +struct l2cc_att_exe_wr_req +{ + /// Execute Write Request - 0x18 + uint8_t code; + /// 0x00 - Cancel all prepared writes + /// 0x01 - Immediately write all pending prepared values + uint8_t flags; +}; + +/// Execute Write Response +struct l2cc_att_exe_wr_rsp +{ + /// Prepare Write Response - 0x19 + uint8_t code; +}; + +/// Handle Value Notification +struct l2cc_att_hdl_val_ntf +{ + /// Handle Value Notification - 0x1B + uint8_t code; + /// The handle of the attribute to be written + uint16_t handle; + /// Value length + uint16_t value_len; + /// The current value of the attribute + uint8_t value[__ARRAY_EMPTY]; +}; + +/// Handle Value Indication +struct l2cc_att_hdl_val_ind +{ + /// Handle Value Indication - 0x1D + uint8_t code; + /// The handle of the attribute to be written + uint16_t handle; + /// Value length + uint16_t value_len; + /// The current value of the attribute + uint8_t value[__ARRAY_EMPTY]; +}; + +/// Handle Value Confirmation +struct l2cc_att_hdl_val_cfm +{ + /// Handle Value Confirmation - 0x1E + uint8_t code; +}; + +/* LE Credit Based PDUs */ + +/// LE Generic send data request (includes total SDU Length) +struct l2cc_lecb_send_data_req +{ + /// Code variable (RFU) + uint8_t code; + /// SDU data length + uint16_t sdu_data_len; + /// Data + uint8_t sdu_data[__ARRAY_EMPTY]; +}; + + +struct l2cc_pdu_data_t +{ + /// L2Cap packet code. + uint8_t code; +}; + +/// Default L2Cap PDU definition +struct l2cc_pdu +{ + /// L2Cap Payload Length + uint16_t payld_len; + /// L2Cap Channel ID + uint16_t chan_id; + + /// Data PDU definition + union l2cc_pdu_data + { + /// L2Cap packet code. + uint8_t code; + + /* LE Credit Based packets */ + /// LE send first frame + struct l2cc_lecb_send_data_req send_lecb_data_req; + + /* Connection Signaling Packets */ + /// Command Reject + struct l2cc_reject reject; + /// Connection Parameter Update Request + struct l2cc_update_param_req update_req; + /// Connection Parameter Update Response + struct l2cc_update_param_rsp update_rsp; + /// LE Credit based connection request + struct l2cc_lecb_req credit_con_req; + /// LE Credit based connection response + struct l2cc_lecb_rsp credit_con_rsp; + /// LE Flow Control Credit + struct l2cc_le_flow_ctl_credit flow_ctl_credit; + /// LE disconnection request + struct l2cc_disconnection_req disc_req; + /// LE disconnection response + struct l2cc_disconnection_rsp disc_rsp; + + /* Security manager PDUs */ + /// Pairing Request + struct l2cc_pairing_req pairing_req; + /// Pairing Response + struct l2cc_pairing_rsp pairing_rsp; + /// Pairing Confirm + struct l2cc_pairing_cfm pairing_cfm; + /// Pairing Random + struct l2cc_pairing_random pairing_random; + /// Pairing Failed + struct l2cc_pairing_failed pairing_failed; + /// Encryption Information + struct l2cc_encryption_inf encryption_inf; + /// Master Identification + struct l2cc_master_id master_id; + /// Identity Information + struct l2cc_identity_inf identity_inf; + /// Identity Address Information + struct l2cc_id_addr_inf id_addr_inf; + /// Signing Information + struct l2cc_signing_inf signing_inf; + /// Security Request + struct l2cc_security_req security_req; + /// Public Keys + struct l2cc_public_key public_key; + /// Key Press Notification + struct l2cc_keypress_notification keypress_notification; + /// DH Key Check + struct l2cc_dhkey_check dhkey_check; + /* Attribute protocol PDUs */ + /// Error response + struct l2cc_att_err_rsp err_rsp; + /// Exchange MTU Request + struct l2cc_att_mtu_req mtu_req; + /// Exchange MTU Response + struct l2cc_att_mtu_rsp mtu_rsp; + /// Find Information Request + struct l2cc_att_find_info_req find_info_req; + /// Find Information Response + struct l2cc_att_find_info_rsp find_info_rsp; + /// Find By Type Value Request + struct l2cc_att_find_by_type_req find_by_type_req; + /// Find By Type Value Response + struct l2cc_att_find_by_type_rsp find_by_type_rsp; + /// Read By Type Request + struct l2cc_att_rd_by_type_req rd_by_type_req; + /// Read By Type Response + struct l2cc_att_rd_by_type_rsp rd_by_type_rsp; + /// Read Request + struct l2cc_att_rd_req rd_req; + /// Read Response + struct l2cc_att_rd_rsp rd_rsp; + /// Read Blob Request + struct l2cc_att_rd_blob_req rd_blob_req; + /// Read Blob Response + struct l2cc_att_rd_blob_rsp rd_blob_rsp; + /// Read Multiple Request + struct l2cc_att_rd_mult_req rd_mult_req; + /// Read Multiple Response + struct l2cc_att_rd_mult_rsp rd_mult_rsp; + /// Read by Group Type Request + struct l2cc_att_rd_by_grp_type_req rd_by_grp_type_req; + /// Read By Group Type Response + struct l2cc_att_rd_by_grp_type_rsp rd_by_grp_type_rsp; + /// Write Request + struct l2cc_att_wr_req wr_req; + /// Write Response + struct l2cc_att_wr_rsp wr_rsp; + /// Write Command + struct l2cc_att_wr_cmd wr_cmd; + /// Signed Write Command + struct l2cc_att_sign_wr_cmd sign_wr_cmd; + /// Prepare Write Request + struct l2cc_att_prep_wr_req prep_wr_req; + /// Prepare Write Response + struct l2cc_att_prep_wr_rsp prep_wr_rsp; + /// Execute Write Request + struct l2cc_att_exe_wr_req exe_wr_req; + /// Execute Write Response + struct l2cc_att_exe_wr_rsp exe_wr_rsp; + /// Handle Value Notification + struct l2cc_att_hdl_val_ntf hdl_val_ntf; + /// Handle Value Indication + struct l2cc_att_hdl_val_ind hdl_val_ind; + /// Handle Value Confirmation + struct l2cc_att_hdl_val_cfm hdl_val_cfm; + } data; +}; + +/// Default L2Cap DBG pdu definition +struct l2cc_dbg_pdu +{ + /// Data length + uint16_t length; + /// data + uint8_t data[__ARRAY_EMPTY]; +}; + +/// Default L2Cap SDU definition +struct l2cc_sdu; + + +/// @} L2CC_PDU + + +#endif /* _L2CC_PDU_H_ */ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/inc/l2cm.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/inc/l2cm.h new file mode 100755 index 0000000..4739552 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/inc/l2cm.h @@ -0,0 +1,127 @@ +/** + **************************************************************************************** + * + * @file l2cm.h + * + * @brief Header file - L2CM. + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + +#ifndef L2CM_H_ +#define L2CM_H_ + +/** + **************************************************************************************** + * @addtogroup L2C Logical Link Control and Adaptation Protocol + * @ingroup HOST + * @brief Logical Link Control and Adaptation Protocol - BLE Host. + * + * The L2C module is responsible for L2CAP provides connection-oriented + * and connection-less data services to upper layer protocols with protocol + * multiplexing capability and segmentation and re-assembly operation. + * + * @{ + **************************************************************************************** + */ +/** + **************************************************************************************** + * @addtogroup L2CM L2CAP Manager + * @ingroup L2C + * @brief L2CAP block for signaling and resource management functions + * + * The L2CM is an internal L2CAP block responsible for managing + * the signaling messages and propagation of connection and disconnection + * related L2CAP messages within the Host. + * + * @{ + **************************************************************************************** + */ +#include "rwip_config.h" + +#if (BLE_L2CM) +#include +#include + +/* + * INCLUDE FILES + **************************************************************************************** + */ + + +/* + * DEFINES + **************************************************************************************** + */ + +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Create and Initialize the L2CAP manager task. + * + * @param[in] reset true if it's requested by a reset; false if it's boot initialization + * + **************************************************************************************** + */ +void l2cm_init(bool reset); + + + +/** + **************************************************************************************** + * @brief Allocates an L2CAP resource. + * + * @param[in] conidx connection index + * + **************************************************************************************** + */ +void l2cm_create(uint8_t conidx); + +/** + **************************************************************************************** + * @brief De-initializes the L2CAP resources for specified link. + * + * @param[in] conidx connection index + * + **************************************************************************************** + */ +void l2cm_cleanup(uint8_t conidx); + + +/** + **************************************************************************************** + * @brief Sets link layer buffer size capacity + * + * @param[in] pkt_len length of the packet + * @param[in] nb_acl number of acl + * + **************************************************************************************** + */ +void l2cm_set_link_layer_buff_size(uint16_t pkt_len, uint16_t nb_acl); + +/** + **************************************************************************************** + * @brief Retrieve number of low layer buffer available + * + * @return Number of low layer buffer available + **************************************************************************************** + */ +uint16_t l2cm_get_nb_buffer_available(void); + +/// @} L2CM + +#endif //(BLE_L2CM) + +#endif // L2CM_H_ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/inc/prf.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/inc/prf.h new file mode 100755 index 0000000..f774f35 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/inc/prf.h @@ -0,0 +1,322 @@ +/** + **************************************************************************************** + * + * @file prf.h + * + * @brief Entry point of profile header file. + * + * Used to manage life cycle of profiles + * + * Copyright (C) RivieraWaves 2009-2016 + * + **************************************************************************************** + */ + + +#ifndef _PRF_H_ +#define _PRF_H_ + +/** + **************************************************************************************** + * @addtogroup PROFILE PROFILES + * @ingroup ROOT + * @brief Bluetooth Low Energy Host Profiles + * + * The PROFILE of the stack contains the profile layers (@ref PROX "PROXIMITY", + * @ref HTP "HTP",@ref FIND "FIND ME" @ref BPS "Blood Pressure"). + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @addtogroup PRF + * @ingroup PROFILE + * @brief Definitions of Profile management API + * + * @{ + **************************************************************************************** + */ + + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_config.h" + +#if (BLE_PROFILES) + +#include "kernel_task.h" +#include "gapm_task.h" + +/* + * DEFINES + **************************************************************************************** + */ + +/** + * Profile task fields + * + * 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + * +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + * | MI | TASK Number | + * +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + * + * Bit [0-14] : Task number value + * Bit [15] : Task is multi-instantiated (Connection index is conveyed) + */ +enum prf_perm_mask +{ + /// Task number value + PERM_MASK_PRF_TASK = 0x7FFF, + PERM_POS_PRF_TASK = 0, + /// Task is multi-instantiated + PERM_MASK_PRF_MI = 0x8000, + PERM_POS_PRF_MI = 15, +}; + +enum +{ + PRF_SERVICE = 0, + PRF_CLIENT = 1, +}; + + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + + +/// Profile Environment Data +typedef struct prf_env +{ + /// Application Task Number - if MSB bit set, Multi-Instantiated task + kernel_task_id_t app_task; + /// Profile Task Number - if MSB bit set, Multi-Instantiated task + kernel_task_id_t prf_task; +} prf_env_t; + + + +/// Profile task environment variable definition to dynamically allocate a Task. +struct prf_task_env +{ + /// Profile Task description + struct kernel_task_desc desc; + /// pointer to the allocated memory used by profile during runtime. + prf_env_t *env; + /// Profile Task Number + kernel_task_id_t task; + /// Profile Task Identifier + kernel_task_id_t id; + // Profile Task role (service / client) + uint8_t role; +}; + +/** + **************************************************************************************** + * @brief Initialization of the Profile module. + * This function performs all the initializations of the Profile module. + * - Creation of database (if it's a service) + * - Allocation of profile required memory + * - Initialization of task descriptor to register application + * - Task State array + * - Number of tasks + * - Default task handler + * + * @param[out] env Collector or Service allocated environment data. + * @param[in|out] start_hdl Service start handle (0 - dynamically allocated), only applies for services. + * @param[in] app_task Application task number. + * @param[in] sec_lvl Security level (AUTH, EKS and MI field of @see enum attm_value_perm_mask) + * @param[in] param Configuration parameters of profile collector or service (32 bits aligned) + * + * @return status code to know if profile initialization succeed or not. + **************************************************************************************** + */ +typedef uint8_t (*prf_init_fnct) (struct prf_task_env *env, uint16_t *start_hdl, uint16_t app_task, uint8_t sec_lvl, void *params); + +/** + **************************************************************************************** + * @brief Destruction of the Profile module - due to a reset for instance. + * This function clean-up allocated memory (attribute database is destroyed by another + * procedure) + * + * @param[in|out] env Collector or Service allocated environment data. + **************************************************************************************** + */ +typedef void (*prf_destroy_fnct) (struct prf_task_env *env); + +/** + **************************************************************************************** + * @brief Handles Connection creation + * + * @param[in|out] env Collector or Service allocated environment data. + * @param[in] conidx Connection index + **************************************************************************************** + */ +typedef void (*prf_create_fnct) (struct prf_task_env *env, uint8_t conidx); + +/** + **************************************************************************************** + * @brief Handles Disconnection + * + * @param[in|out] env Collector or Service allocated environment data. + * @param[in] conidx Connection index + * @param[in] reason Detach reason + **************************************************************************************** + */ +typedef void (*prf_cleanup_fnct) (struct prf_task_env *env, uint8_t conidx, uint8_t reason); + +/// Profile task callbacks. +struct prf_task_cbs +{ + /// Initialization callback + prf_init_fnct init; + /// Destroy profile callback + prf_destroy_fnct destroy; + /// Connection callback + prf_create_fnct create; + /// Disconnection callback + prf_cleanup_fnct cleanup; +}; + + +/// Profile Manager environment structure +struct prf_env_tag +{ + /// Array of profile tasks that can be managed by Profile manager. + struct prf_task_env prf[BLE_NB_PROFILES]; + uint8_t prf_used; +}; + +/* + * MACROS + **************************************************************************************** + */ + + +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ +extern struct prf_env_tag prf_env; + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Perform Profile initialization + * + * @param[in] reset Reset requested or basic initialization + **************************************************************************************** + */ +void prf_init(bool reset); + + +/** + **************************************************************************************** + * @brief Create Profile (collector or service) task creation and initialize it. + * + * @param[in|out] params Collector or Service parameter used for profile task creation + * @param[out] prf_task Allocated Task number + * + * @return status of adding profile task + **************************************************************************************** + */ +uint8_t prf_add_profile(struct gapm_profile_task_add_cmd *params, kernel_task_id_t *prf_task); + + +/** + **************************************************************************************** + * @brief Link creation event, update profiles states. + * + * @param[in] conidx connection index + * + **************************************************************************************** + */ +void prf_create(uint8_t conidx); + +/** + **************************************************************************************** + * @brief Link disconnection event, clean-up profiles. + * + * @param[in] conidx connection index + * @param[in] reason detach reason + * + **************************************************************************************** + */ +void prf_cleanup(uint8_t conidx, uint8_t reason); + + + +/** + **************************************************************************************** + * @brief Retrieve environment variable allocated for a profile + * + * @param[in] prf_id Profile Task Identifier + * + * @return Environment variable allocated for a profile + **************************************************************************************** + */ +prf_env_t *prf_env_get(uint16_t prf_id); + + +/** + **************************************************************************************** + * @brief Retrieve source profile task number value + * + * @param[in] env Profile Environment + * @param[in] conidx Connection index + * + * @return Source profile task number value + **************************************************************************************** + */ +kernel_task_id_t prf_src_task_get(prf_env_t *env, uint8_t conidx); + +/** + **************************************************************************************** + * @brief Retrieve destination application task number value + * + * @param[in] env Profile Environment + * @param[in] conidx Connection index + * + * @return Destination application task number value + **************************************************************************************** + */ +kernel_task_id_t prf_dst_task_get(prf_env_t *env, uint8_t conidx); + + +/** + **************************************************************************************** + * @brief Retrieve Task Identifier from Task number + * (automatically update index of task in returned task id) + * + * @param task Task number + * @return Task Identifier + **************************************************************************************** + */ +kernel_task_id_t prf_get_id_from_task(kernel_msg_id_t task); + +/** + **************************************************************************************** + * @brief Retrieve Task Number from Task Identifier + * (automatically update index of task in returned task id) + * + * @param id Task Identifier + * @return Task Number + **************************************************************************************** + */ +kernel_task_id_t prf_get_task_from_id(kernel_msg_id_t id); + +struct prf_env_t * prf_env_get_from_uuid(uint16_t uuid,uint16_t char_num); + +uint16_t prf_get_uuid_from_handle(uint16_t handle); +#endif // (BLE_PROFILES) + +/// @} PRF + +#endif /* _PRF_H_ */ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/inc/prf_utils.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/inc/prf_utils.h new file mode 100755 index 0000000..ae199ed --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/inc/prf_utils.h @@ -0,0 +1,377 @@ +/** + **************************************************************************************** + * + * @file prf_utils.h + * + * @brief Header file - Profile Utilities + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + + +#ifndef _PRF_UTILS_H_ +#define _PRF_UTILS_H_ + +/** + **************************************************************************************** + * @addtogroup PRF_UTILS + * @ingroup PROFILE + * + * @brief Definitions of shared profiles functions that can be used by several profiles + * + * @{ + **************************************************************************************** + */ + + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" +#if (BLE_SERVER_PRF || BLE_CLIENT_PRF) +#include "kernel_msg.h" +#include "prf_types.h" +#include "gattc_task.h" +#include "gapc.h" +#include "gapc_task.h" +#include "attm.h" +#include "prf.h" +#endif /* (BLE_SERVER_PRF || BLE_CLIENT_PRF) */ + +/* + * MACROS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Macro used to called the prf_client_get_env function. + * + * @param prf_id Profile Task ID (In Upper case, ex: HTPC, DISC, ...) + * @param type Profile task type (In lower case, ex: htpc, disc, ...) + **************************************************************************************** + */ +#define PRF_ENV_GET(prf_id, type) \ + ((struct type ## _env_tag *)prf_env_get((TASK_ID_##prf_id))) + + + + + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +#if (BLE_BATT_SERVER) +/** + **************************************************************************************** + * @brief Pack Characteristic Presentation Format descriptor value + **************************************************************************************** + */ +void prf_pack_char_pres_fmt(uint8_t *packed_val, const struct prf_char_pres_fmt *char_pres_fmt); +#endif // (BLE_BATT_SERVER) + +#if (BLE_BATT_CLIENT) +/** + **************************************************************************************** + * @brief Unpack Characteristic Presentation Format descriptor value + **************************************************************************************** + */ +void prf_unpack_char_pres_fmt(const uint8_t *packed_val, struct prf_char_pres_fmt *char_pres_fmt); +#endif // (BLE_BATT_CLIENT) + +#if (BLE_CLIENT_PRF) +/** + **************************************************************************************** + * @brief Request peer device to read an attribute + * + * @param[in] prf_env Pointer to profile information + * + * @param conidx Connection index + * @param shdl Search Start Handle + * @param ehdl Search End Handle + * + * @param valhdl Value Handle + * + * @note: if attribute is invalid, nothing is registered + **************************************************************************************** + */ +void prf_read_char_send(prf_env_t *prf_env, uint8_t conidx, + uint16_t shdl, uint16_t ehdl, uint16_t valhdl); + + +/** + **************************************************************************************** + * @brief register attribute handle in GATT + * + * @param[in] prf_env Pointer to profile information + * + * @param conidx Connection index + * @param svc Service to register + * + * @note: if attribute is invalid, nothing is registered + **************************************************************************************** + */ +void prf_register_atthdl2gatt(prf_env_t *prf_env, uint8_t conidx, struct prf_svc *svc); + +/** + **************************************************************************************** + * @brief Unregister attribute handle in GATT + * + * @param[in] prf_env Pointer to profile information + * + * @param conidx Connection index + * @param svc Service to register + * + * @note: if attribute is invalid, nothing is registered + **************************************************************************************** + */ +void prf_unregister_atthdl2gatt(prf_env_t *prf_env, uint8_t conidx, struct prf_svc *svc); + +/** + **************************************************************************************** + * @brief Request service discovery on peer device. + * + * This request will be used to retrieve start and end handles of the service. + * + * @param[in] prf_env Pointer to profile information + * + * @param conidx Connection index + * @param uuid Service UUID + **************************************************************************************** + */ +void prf_disc_svc_send(prf_env_t *prf_env, uint8_t conidx, uint16_t uuid); + + +/** + **************************************************************************************** + * @brief Request service discovery on peer device. + * + * This request will be used to retrieve start and end handles of the service. + * + * @param[in] prf_env Pointer to profile information + * + * @param conidx Connection index + * @param uuid Service UUID + **************************************************************************************** + */ +void prf_disc_svc_send_uuid128(prf_env_t *prf_env, uint8_t conidx, uint8_t *uuid ); + +/** + **************************************************************************************** + * @brief Write peer characteristic using GATT. + * + * It will request write modification of peer handle + * + * @param[in] prf_env Pointer to profile information + * @param[in] conidx Connection index + * @param[in] handle Peer handle to modify + * @param[in] value New Peer handle value + * @param[in] length Value length + **************************************************************************************** + */ +void prf_gatt_write(prf_env_t *prf_env, uint8_t conidx, + uint16_t handle, uint8_t* value, uint16_t length, uint8_t operation,uint8_t seq_num); + +/** + **************************************************************************************** + * @brief Modify peer client configuration descriptor using GATT + * + * It will request write modification of peer client configuration descriptor handle + * + * @param[in] prf_env Pointer to profile information + * + * @param[in] conidx Connection index + * @param[in] handle Peer client configuration descriptor handle to modify + * + * @param[in] ntf_ind_cfg Indication/Notification configuration + **************************************************************************************** + */ +void prf_gatt_write_ntf_ind(prf_env_t *prf_env, uint8_t conidx, uint16_t handle, + uint16_t ntf_ind_cfg,uint8_t seq_num); + +/** + **************************************************************************************** + * @brief Check service characteristic validity + * + * For each characteristic in service it verifies handles. + * + * If some handles are not present, it checks if they shall be present or they are optional. + * + * @param nb_chars Number of Characteristics in the service + * @param chars Characteristics values (char handles, val handles, properties) + * @param chars_req Characteristics requirements. + * + * @return 0x1 if service is valid, 0x00 else. + **************************************************************************************** + */ +uint8_t prf_check_svc_char_validity(uint8_t nb_chars, + const struct prf_char_inf *chars, + const struct prf_char_def *chars_req); + +/** + **************************************************************************************** + * @brief Check service characteristic validity + * + * For each characteristic in service it verifies handles. + * + * If some handles are not present, it checks if they shall be present or they are optional. + * + * @param nb_chars Number of Characteristics in the service + * @param chars Characteristics values (char handles, val handles, properties) + * @param chars_req Characteristics requirements. + * + * @return 0x1 if service is valid, 0x00 else. + **************************************************************************************** + */ +uint8_t prf_check_svc_char_uuid128_validity(uint8_t nb_chars, + const struct prf_char_inf *chars, + const struct prf_char_uuid128_def *chars_req); + +/** + **************************************************************************************** + * @brief Check service characteristic descriptors validity + * + * For each characteristic descriptors in service it verifies handles. + * + * If some handles are not present, according to characteristic properties it verify if + * descriptor is optional or not. + * + * @param descs_size Number of Characteristic descriptors in the service + * @param descs Characteristic descriptors values (handles) + * @param descs_req Characteristics descriptors requirements. + * + * @return 0x1 if service is valid, 0x00 else. + **************************************************************************************** + */ +uint8_t prf_check_svc_char_desc_validity(uint8_t descs_size, + const struct prf_char_desc_inf *descs, + const struct prf_char_desc_def *descs_req, + const struct prf_char_inf *chars); + +/** + **************************************************************************************** + * @brief Check service characteristic descriptors validity + * + * For each characteristic descriptors in service it verifies handles. + * + * If some handles are not present, according to characteristic properties it verify if + * descriptor is optional or not. + * + * @param descs_size Number of Characteristic descriptors in the service + * @param descs Characteristic descriptors values (handles) + * @param descs_req Characteristics descriptors requirements. + * + * @return 0x1 if service is valid, 0x00 else. + **************************************************************************************** + */ +uint8_t prf_check_svc_char_desc_uuid128_validity(uint8_t descs_size, + const struct prf_char_desc_inf *descs, + const struct prf_char_desc_uuid128_def *descs_req, + const struct prf_char_inf *chars); + +/** + **************************************************************************************** + * @brief Extract information of the service according to the service description + * + * @param param Service information + * @param nb_chars Length of provided arrays (chars and chars_req) + * @param chars_req Characteristics requirements + * @param chars Characteristics + * @param nb_descs Length of provided arrays (descs and descs_req) + * @param descs_req Descriptors requirements + * @param descs Descriptors + **************************************************************************************** + */ +void prf_extract_svc_info(const struct gattc_sdp_svc_ind *param, + uint8_t nb_chars, const struct prf_char_def *chars_req, struct prf_char_inf *chars, + uint8_t nb_descs, const struct prf_char_desc_def *descs_req, struct prf_char_desc_inf *descs); + +/** + **************************************************************************************** + * @brief Extract information of the service according to the service description + * + * @param param Service information + * @param nb_chars Length of provided arrays (chars and chars_req) + * @param chars_req Characteristics requirements in UUID128 format + * @param chars Characteristics + * @param nb_descs Length of provided arrays (descs and descs_req) + * @param descs_req Descriptors requirements in UUID128 format + * @param descs Descriptors + **************************************************************************************** + */ +void prf_extract_svc_uuid128_info(const struct gattc_sdp_svc_ind *param, + uint8_t nb_chars, const struct prf_char_uuid128_def *chars_uuid128_req, struct prf_char_inf *chars, + uint8_t nb_descs, const struct prf_char_desc_uuid128_def *descs_uuid128_req, struct prf_char_desc_inf *descs); + +#endif //(BLE_CLIENT_PRF) + + +#if (BLE_CLIENT_PRF || BLE_TIP_SERVER || BLE_AN_SERVER || BLE_PAS_SERVER) + +/** + **************************************************************************************** + * @brief The function is used to send information about peer attribute value + * + * @param[in] prf_env Pointer to the profile environment variable + * @param[in] conidx Connection index + * @param[in] msg_id Profile message ID to trigger + * @param[in] status Response status code + * @param[in] read_ind GATT read message indication + **************************************************************************************** + */ +void prf_client_att_info_rsp(prf_env_t *prf_env, uint8_t conidx, uint16_t msg_id, + uint8_t status, struct gattc_read_ind const *read_ind); + +#endif //(BLE_CLIENT_PRF || BLE_TIP_SERVER || BLE_AN_SERVER || BLE_PAS_SERVER) + +#if (BLE_SERVER_PRF || BLE_CLIENT_PRF) +/** + **************************************************************************************** + * @brief Pack date time value + * + * @param[out] packed_date packed date time + * @param[in] date_time structure date time + * + * @return size of packed value + **************************************************************************************** + */ +uint8_t prf_pack_date_time(uint8_t *packed_date, const struct prf_date_time *date_time); + +/** + **************************************************************************************** + * @brief Unpack date time value + * + * @param[in] packed_date packed date time + * @param[out] date_time structure date time + * + * @return size of packed value + **************************************************************************************** + */ +uint8_t prf_unpack_date_time(uint8_t *packed_date, struct prf_date_time *date_time); + +#endif /* (BLE_SERVER_PRF || BLE_CLIENT_PRF) */ + +#if ((BLE_CGM_SERVER || BLE_CGM_CLIENT)) +/** + **************************************************************************************** + * @brief calculate E2E-CRC according to the profile specification + * @param[in] buf Pointer to the byte buffer for the crc calculation. + * @param[in] length Length of the buffer for calculation. + * @return E2E-CRC according to the specification. + **************************************************************************************** + */ +uint16_t prf_e2e_crc(const uint8_t *buf, uint16_t length); + +#endif /* ((BLE_CGM_SERVER || BLE_CGM_CLIENT)) */ + + +/// @} prf_utils + +#endif /* _PRF_UTILS_H_ */ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/inc/rwble_hl.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/inc/rwble_hl.h new file mode 100755 index 0000000..1725862 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/inc/rwble_hl.h @@ -0,0 +1,60 @@ +/** + **************************************************************************************** + * + * @file rwble_hl.h + * + * @brief Entry points of the BLE HL software + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + +#ifndef RWBLE_HL_H_ +#define RWBLE_HL_H_ + +#include + +/** + **************************************************************************************** + * @addtogroup ROOT + * @brief Entry points of the BLE Host stack + * + * This module contains the primitives that allow an application accessing and running the + * BLE protocol stack + * + * @{ + **************************************************************************************** + */ + + +/* + * DEFINES + **************************************************************************************** + */ + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + + +/** + **************************************************************************************** + * @brief Initialize the BLE Host stack. + **************************************************************************************** + */ +void rwble_hl_init(void); + +/** + **************************************************************************************** + * @brief Initialize the host (reset requested) + * + **************************************************************************************** + */ +void rwble_hl_reset(void); + +/// @} RWBLE_HL + +#endif // RWBLE_HL_H_ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/inc/rwble_hl_config.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/inc/rwble_hl_config.h new file mode 100755 index 0000000..49909a5 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/inc/rwble_hl_config.h @@ -0,0 +1,271 @@ +/** + **************************************************************************************** + * + * @file rwble_hl_config.h + * + * @brief Configuration of the BLE protocol stack (max number of supported connections, + * type of partitioning, etc.) + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + +#ifndef RWBLE_HL_CONFIG_H_ +#define RWBLE_HL_CONFIG_H_ + +/** + **************************************************************************************** + * @addtogroup ROOT + * @{ + * @name BLE stack configuration + * @{ + **************************************************************************************** + */ + +#include "rwble_hl_error.h" + +/******************************************************************************************/ +/* ------------------------- BLE PARTITIONING -------------------------------------*/ +/******************************************************************************************/ + + +/******************************************************************************************/ +/* -------------------------- INTERFACES ----------------------------------------*/ +/******************************************************************************************/ + + +#if BLE_APP_PRESENT +#define APP_MAIN_TASK TASK_APP +#else // BLE_APP_PRESENT +#define APP_MAIN_TASK TASK_AHI +#endif // BLE_APP_PRESENT + +// Host Controller Interface (Host side) +#define BLEHL_HCIH_ITF HCIH_ITF + +/******************************************************************************************/ +/* -------------------------- COEX SETUP ----------------------------------------*/ +/******************************************************************************************/ + +///WLAN coex +#define BLEHL_WLAN_COEX RW_WLAN_COEX +///WLAN test mode +#define BLEHL_WLAN_COEX_TEST RW_WLAN_COEX_TEST + +/******************************************************************************************/ +/* -------------------------- HOST MODULES ----------------------------------------*/ +/******************************************************************************************/ + +#define BLE_GAPM 1 +#if (BLE_CENTRAL || BLE_PERIPHERAL) +#define BLE_GAPC 1 +#define BLE_GAPC_HEAP_ENV_SIZE (sizeof(struct gapc_env_tag) + KERNEL_HEAP_MEM_RESERVED) +#else //(BLE_CENTRAL || BLE_PERIPHERAL) +#define BLE_GAPC 0 +#define BLE_GAPC_HEAP_ENV_SIZE 0 +#endif //(BLE_CENTRAL || BLE_PERIPHERAL) + +#if (BLE_CENTRAL || BLE_PERIPHERAL) +#define BLE_L2CM 1 +#define BLE_L2CC 1 +#define BLE_ATTM 1 +#define BLE_GATTM 1 +#define BLE_GATTC 1 +#define BLE_GATTC_HEAP_ENV_SIZE (sizeof(struct gattc_env_tag) + KERNEL_HEAP_MEM_RESERVED) +#define BLE_L2CC_HEAP_ENV_SIZE (sizeof(struct l2cc_env_tag) + KERNEL_HEAP_MEM_RESERVED) +#else //(BLE_CENTRAL || BLE_PERIPHERAL) +#define BLE_L2CM 0 +#define BLE_L2CC 0 +#define BLE_ATTC 0 +#define BLE_ATTS 0 +#define BLE_ATTM 0 +#define BLE_GATTM 0 +#define BLE_GATTC 0 +#define BLE_GATTC_HEAP_ENV_SIZE 0 +#define BLE_L2CC_HEAP_ENV_SIZE 0 +#endif //(BLE_CENTRAL || BLE_PERIPHERAL) + +#define BLE_SMPM 1 +#if (BLE_CENTRAL || BLE_PERIPHERAL) +#define BLE_SMPC 1 +#else //(BLE_CENTRAL || BLE_PERIPHERAL) +#define BLE_SMPC 0 +#endif //(BLE_CENTRAL || BLE_PERIPHERAL) + + +/******************************************************************************************/ +/* -------------------------- ATT DB ----------------------------------------*/ +/******************************************************************************************/ + +//ATT DB,Testing and Qualification related flags +#if (BLE_CENTRAL || BLE_PERIPHERAL) +/// Support of External DB Management +#if defined(CFG_EXT_DB) +#define BLE_EXT_ATT_DB 1 +#else +#define BLE_EXT_ATT_DB 0 +#endif // defined(CFG_EXT_DB) +#else +#define BLE_EXT_ATT_DB 0 +#endif // (BLE_CENTRAL || BLE_PERIPHERAL) +/******************************************************************************************/ +/* -------------------------- PROFILES ----------------------------------------*/ +/******************************************************************************************/ +#ifdef CFG_PRF +#define BLE_PROFILES (1) +/// Number of Profile tasks managed by GAP manager. +#define BLE_NB_PROFILES (CFG_NB_PRF) +#include "rwprf_config.h" +#else +#define BLE_PROFILES (0) +#define BLE_NB_PROFILES (0) +#endif // CFG_PRF + + +#ifndef BLE_ATTS +#if (BLE_CENTRAL || BLE_PERIPHERAL || defined(CFG_ATTS)) +#define BLE_ATTS 1 +#else +#define BLE_ATTS 0 +#endif // (BLE_CENTRAL || BLE_PERIPHERAL || defined(CFG_ATTS)) +#endif // BLE_ATTS + + +#ifndef BLE_ATTC +#if (BLE_CENTRAL || BLE_PERIPHERAL || defined(CFG_ATTC)) +#define BLE_ATTC 1 +#else +#define BLE_ATTC 0 +#endif // (BLE_CENTRAL || defined(CFG_ATTC)) +#endif // BLE_ATTC + +#ifndef BLE_LECB +#if (BLE_CENTRAL || BLE_PERIPHERAL) +#define BLE_LECB 1 +#else +#define BLE_LECB 0 +#endif // (BLE_CENTRAL || defined(CFG_ATTC)) +#endif // BLE_ATTC + + +/// Attribute Server +#if (BLE_ATTS) +#define BLE_ATTS 1 +#else +#define BLE_ATTS 0 +#endif //(BLE_ATTS) + + +/// Size of the heap +#if (BLE_CENTRAL || BLE_PERIPHERAL) +/// some heap must be reserved for attribute database +#if (BLE_ATTS || BLE_ATTC) + #define BLEHL_HEAP_DB_SIZE (3072)//(1024)//(3072) +#else +#define BLEHL_HEAP_DB_SIZE (0) +#endif /* (BLE_ATTS || BLE_ATTC) */ + +#define BLEHL_HEAP_MSG_SIZE (256 + 256 * BLE_CONNECTION_MAX) +#elif (defined(CFG_BLE_MESH)) +#define BLEHL_HEAP_MSG_SIZE (1024) +#define BLEHL_HEAP_DB_SIZE (3072) + +#else +#define BLEHL_HEAP_MSG_SIZE (256) +#define BLEHL_HEAP_DB_SIZE (0) +#endif /* #if (BLE_CENTRAL || BLE_PERIPHERAL) */ + + + + +/// Number of BLE HL tasks +#define BLEHL_TASK_SIZE BLE_HOST_TASK_SIZE + BLE_PRF_TASK_SIZE + +/// Size of environment variable needed on BLE Host Stack for one link +#define BLEHL_HEAP_ENV_SIZE ( BLE_GAPC_HEAP_ENV_SIZE + \ + BLE_GATTC_HEAP_ENV_SIZE + \ + BLE_L2CC_HEAP_ENV_SIZE) + + + + + + + +/* + * DEFINES - Mandatory for BLE Host Layers + **************************************************************************************** + */ +/// Maximum time to remain advertising when in the Limited +/// Discover able mode: TGAP(lim_adv_timeout) +/// required value: 180s: (18000 for ke timer) +#define GAP_TMR_LIM_ADV_TIMEOUT 0x4650 + +/// Minimum time to perform scanning when performing +/// the General Discovery procedure: TGAP(gen_disc_scan_min) +/// recommended value: 10.24s: (1024 for ke timer) +#define GAP_TMR_GEN_DISC_SCAN 0x0300 + +/// Minimum time to perform scanning when performing the +/// Limited Discovery procedure: TGAP(lim_disc_scan_min) +/// recommended value: 10.24s: (1024 for ke timer) +#define GAP_TMR_LIM_DISC_SCAN 0x0300 + +/// Minimum time interval between private address change +/// TGAP(private_addr_int) +/// recommended value: 15 minutes; 0x01F4 for PTS +/// 0x3A98 is 150 seconds; 0xEA60 is 10 minutes +#define GAP_TMR_PRIV_ADDR_INT 0x3A98 + + +/// Minimum time interval between private address change +/// TGAP(private_addr_int) +/// recommended value: 15 minutes +/// Minimum value 150s +#define GAP_TMR_PRIV_ADDR_MIN (150) +/// Maximum time interval between private address change +/// 0xA1B8 (approximately 11.5 hours) +#define GAP_TMR_PRIV_ADDR_MAX (0xA1B8) + +/// Timer used in connection parameter update procedure +/// TGAP(conn_param_timeout) +/// recommended value: 30 s: (3000 for ke timer) +#define GAP_TMR_CONN_PARAM_TIMEOUT 0x0BB8 + +/// Timer used in LE credit based connection procedure +/// TGAP(lecb_conn_timeout) +/// recommended value: 30 s: (3000 for ke timer) +#define GAP_TMR_LECB_CONN_TIMEOUT 0x0BB8 + +/// Timer used in LE credit based disconnection procedure +/// TGAP(lecb_disconn_timeout) +/// recommended value: 30 s: (3000 for ke timer) +#define GAP_TMR_LECB_DISCONN_TIMEOUT 0x0BB8 + +/// Maximal authorized MTU value +#define GAP_MAX_LE_MTU (2048) + +/// Maximum GAP device name size +#define GAP_MAX_NAME_SIZE (0x20) + + + + +/// Maximum Transmission Unit +#define ATT_DEFAULT_MTU (23) +/// 30 seconds transaction timer +#define ATT_TRANS_RTX (0x0BB8) +/// Acceptable encryption key size - strict access +#define ATT_SEC_ENC_KEY_SIZE (0x10) + + +/// Maximum attribute value length +#define ATT_MAX_VALUE (GAP_MAX_LE_MTU) + + +/// @} BLE stack configuration +/// @} ROOT + +#endif // RWBLE_HL_CONFIG_H_ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/inc/smpc.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/inc/smpc.h new file mode 100755 index 0000000..69ee823 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/inc/smpc.h @@ -0,0 +1,327 @@ +/** + **************************************************************************************** + * + * @file smpc.h + * + * @brief Header file - SMPC. + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + +#ifndef SMPC_H_ +#define SMPC_H_ + +/** + **************************************************************************************** + * @addtogroup SMP Security Manager Protocol + * @ingroup HOST + * @brief Security Manager Protocol. + * + * The SMP is responsible for the over-all security policies of BLE. + * It defines methods for pairing and key distribution, handles encryption, + * data signing and privacy features such as random addressing generation and resolution. + * + * Pairing is performed to exchange pairing features and generate a short term + * key for link encryption. + * A transport specific key distribution is performed to + * share the keys that can be used to encrypt the link in the future + * reconnection process, signed data verification and random address + * resolution. + * + * There exist 3 phases in the complete security procedure: + * 1. Feature exchange (IO capabilities, OOB flags, Authentication Requirements, Key distributions) + * 2. Short Term Key generation + * Generation method depends on exchanged features: + * - Just Works - use Temporary key = 0 + * - PassKey Entry - use Temporary Key = 6-digit provided by user + * - Out of Band (OOB) - use Temporary Key = 16-octet key, available form OOB source + * 3. Transport Specific Key Distribution (TKDP)(LTK+EDIV+RAND_NB, IRK+ADDR, CSRK) + *--------------------------------------------------------------------- + * @addtogroup SMPC Security Manager Protocol Controller + * @ingroup SMP + * @brief Security Manager Protocol Controller. + * + * This block handles control of SM procedures for several possible existing connections, + * for which the security procedure may be conducted simultaneously. + * + * It allows flow control for HCI access to encryption and random number generation, used + * at different moments in the procedure. + * + * It handles PDU creation and sending through L2CAP, also their reception from L2CAP + * and interpretation. + * + * Other small utilities such as maximum key size determination and TKDP organization are + * implemented in SMPC. + * @{ + * + **************************************************************************************** + */ + + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_config.h" + +#if (BLE_SMPC) +#include "common_bt.h" +#include "gap.h" +#include "gapc_task.h" +#include "kernel_task.h" + +/* + * DEFINES + **************************************************************************************** + */ + +/// MAC length +#define SMPC_SIGN_MAC_LEN (8) +/// SignCounter length +#define SMPC_SIGN_COUNTER_LEN (4) +/// Signature length +#define SMPC_SIGN_LEN (SMPC_SIGN_MAC_LEN + SMPC_SIGN_COUNTER_LEN) + +/** + * Repeated Attempts Timer Configuration + */ +/// Repeated Attempts Timer default value (x10ms) +#define SMPC_REP_ATTEMPTS_TIMER_DEF_VAL (200) //2s +/// Repeated Attempts Timer max value (x10ms) +#define SMPC_REP_ATTEMPTS_TIMER_MAX_VAL (3000) //30s +/// Repeated Attempts Timer multiplier +#define SMPC_REP_ATTEMPTS_TIMER_MULT (2) + +/** + * Timeout Timer Configuration + */ +#define SMPC_TIMEOUT_TIMER_DURATION (3000) //30s + +#define SMPC_PUBLIC_KEY_256_COORD_LEN 0x20 +/* + * ENUMERATIONS + **************************************************************************************** + */ + + +/// Information source. +enum smpc_addr_src +{ + /// Local info. + SMPC_INFO_LOCAL, + /// Peer info. + SMPC_INFO_PEER, + /// Maximum info source. + SMPC_INFO_MAX +}; + +/* + * STRUCTURES DEFINITION + **************************************************************************************** + */ + +/// Master ID Information Structure +struct smpc_mst_id_info +{ + // Encryption Diversifier + uint16_t ediv; + + // Random Number + uint8_t randnb[GAP_RAND_NB_LEN]; +}; + +#if (SECURE_CONNECTIONS) +struct smp_aes_cmac +{ + uint8_t *M; // pointer to memory allocated by calling function + uint8_t M_len; + uint8_t M_last[16]; + uint8_t X[16]; + uint8_t Y[16]; + uint8_t *K; //[16]; + uint8_t K1[16]; + uint8_t K2[16]; + uint8_t next_block; + uint8_t num_blocks; + uint8_t state; // Only 3 States - Idle, SubKey Generation, Block AES +}; + +struct smp_f4 +{ + uint8_t M[65]; + uint8_t X[16]; // The Key +}; + +struct smp_f5 +{ + uint8_t M[53]; + uint8_t *W; + uint8_t T[16]; + uint8_t SALT[16]; +}; + + +struct smp_f6 +{ + uint8_t W[16]; + uint8_t M[65]; +}; + +struct smp_g2 +{ + uint8_t X[16]; + uint8_t M[80]; +}; + +struct gapc_public_key +{ + uint8_t x[GAP_P256_KEY_LEN]; + uint8_t y[GAP_P256_KEY_LEN]; +}; + +#endif // (SECURE_CONNECTIONS) +/// Pairing Information +struct smpc_pair_info +{ + /// TK during Phase 2, LTK or IRK during Phase 3 + struct gap_sec_key key; + /// Pairing request command + struct gapc_pairing pair_req_feat; + /// Pairing response feature + struct gapc_pairing pair_rsp_feat; + /// Random number value + uint8_t rand[RAND_VAL_LEN]; + /// Remote random number value + uint8_t rem_rand[RAND_VAL_LEN]; + /// Confirm value to check + uint8_t conf_value[GAP_KEY_LEN]; + /// Pairing Method + uint8_t pair_method; + /// Authentication level + uint8_t auth; + /// check that LTK exchanged during pairing + bool ltk_exchanged; + /// Key to be exchanged (transmitted or to be received) + uint8_t keys_dist; + + +#if (SECURE_CONNECTIONS) + // AES_CMAC Info + struct smp_aes_cmac *aes_cmac; + // Structure for Secure Connections Crypto functions + struct smp_f4 *f4_info; + struct smp_f5 *f5_info; + struct smp_f6 *f6_info; + struct smp_g2 *g2_info; + + bool dh_key_calculation_complete; + + uint8_t MacKey[GAP_KEY_LEN]; + uint8_t dh_key_check_peer[DHKEY_CHECK_LEN]; + uint8_t dh_key_local[DH_KEY_LEN]; + + uint8_t dh_key_check_local[DHKEY_CHECK_LEN]; + bool dh_key_check_received_from_peer; + + public_key_t peer_public_key; + + uint8_t passkey_bit_count; + uint32_t passkey; + + // Required for OOB + uint8_t peer_r[GAP_KEY_LEN]; + uint8_t local_r[GAP_KEY_LEN]; + bool peer_rand_received; + bool peer_confirm_received; +#endif // (SECURE_CONNECTIONS) +}; + +/// Signing Information +struct smpc_sign_info +{ + /// Operation requester task id + kernel_task_id_t requester; + + /// Message offset + uint16_t msg_offset; + /// Number of block + uint8_t block_nb; + /// Cn-1 value -> Need to kept this value to retrieve it after L generation + uint8_t cn1[GAP_KEY_LEN]; +}; + +/// SMPC environment structure +struct smpc_env +{ + /// SMPC temporary information + union smpc_info + { + /** + * Pairing Information - This structure is allocated at the beginning of a pairing + * or procedure. It is freed when a disconnection occurs or at the end of + * the pairing procedure. If not enough memory can be found, the procedure will fail + * with an "Unspecified Reason" error + */ + struct smpc_pair_info *pair; + + /** + * Signature Procedure Information - This structure is allocated at the beginning of a + * signing procedure. It is freed when a disconnection occurs or at the end of + * the signing procedure. If not enough memory can be found, the procedure will fail + * with an "Unspecified Reason" error. + */ + struct smpc_sign_info *sign; + } info; + + /// CSRK values (Local and remote) + struct gap_sec_key csrk[SMPC_INFO_MAX]; + + /// signature counter values (Local and remote) + uint32_t sign_counter[SMPC_INFO_MAX]; + + /// Repeated Attempt Timer value + uint16_t rep_att_timer_val; + + /// Encryption key size + uint8_t key_size; + + /** + * Contains the current state of the two timers needed in the SMPC task + * Bit 0 - Is Timeout Timer running + * Bit 1 - Is Repeated Attempt Timer running + * Bit 2 - Has task reached a SMP Timeout + */ + uint8_t timer_state; + + /// State of the current procedure + uint8_t state; + +#if (SECURE_CONNECTIONS) + bool secure_connections_enabled; +#endif // (SECURE_CONNECTIONS) +}; + +/* + * GLOBAL VARIABLES DEFINITION + **************************************************************************************** + */ + + +/* + * MACROS + **************************************************************************************** + */ + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + + +#endif //(BLE_SMPC) +#endif //SMPC_H_ + +/// @} SMPC diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/gap/gapc/gapc_int.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/gap/gapc/gapc_int.h new file mode 100755 index 0000000..69dae92 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/gap/gapc/gapc_int.h @@ -0,0 +1,391 @@ +/** + **************************************************************************************** + * + * @file gapc_int.h + * + * @brief Generic Access Profile Controller Internal Header. + * + * Copyright (C) RivieraWaves 2009-2016 + * + **************************************************************************************** + */ +#ifndef _GAPC_INT_H_ +#define _GAPC_INT_H_ + +/** + **************************************************************************************** + * @addtogroup GAPC_INT Generic Access Profile Controller Internals + * @ingroup GAPC + * @brief Handles ALL Internal GAPC API + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "gapc.h" +#include "gapc_task.h" + +#if (BLE_GAPC) + +/* + * MACROS + **************************************************************************************** + */ + +/// Set link configuration field +#define GAPC_SET_FIELD(conidx, field, value)\ + (gapc_env[conidx]->fields) = ((gapc_env[conidx]->fields) & (~GAPC_##field##_MASK)) \ + | (((value) << GAPC_##field) & (GAPC_##field##_MASK)) + + +/// Get link configuration field +#define GAPC_GET_FIELD(conidx, field)\ + (((gapc_env[conidx]->fields) & (GAPC_##field##_MASK)) >> GAPC_##field) + + +/* + * DEFINES + **************************************************************************************** + */ + +/// number of GAP Controller Process +#define GAPC_IDX_MAX BLE_CONNECTION_MAX + + + + +/// states of GAP Controller task +enum gapc_state_id +{ + /// Connection ready state + GAPC_READY, + + /// Link Operation on-going + GAPC_LINK_INFO_BUSY = (1 << GAPC_OP_LINK_INFO), + /// SMP Operation on-going + GAPC_SMP_BUSY = (1 << GAPC_OP_SMP), + /// Update Operation on-going + GAPC_LINK_UPD_BUSY = (1 << GAPC_OP_LINK_UPD), + /// SMP start encryption on-going + GAPC_ENCRYPT_BUSY = (1 << GAPC_OP_MAX), + + /// Disconnection on-going + GAPC_DISC_BUSY = 0x1F, + /// Free state + GAPC_FREE = 0X3F, + + /// Number of defined states. + GAPC_STATE_MAX +}; + + + +/// fields definitions. +/// Configuration fields: +/// 7 6 5 4 3 2 1 0 +/// +----+----+----+----+----+----+----+----+ +/// |RFU |SVCH|ROLE|LTK |ENC |BOND| SEC_LVL | +/// +----+----+----+----+----+----+----+----+ +enum gapc_fields +{ + /// Link Security Level + GAPC_SEC_LVL = 0, + GAPC_SEC_LVL_MASK = 0x03, + /// Link Bonded or not + GAPC_BONDED = 2, + GAPC_BONDED_MASK = 0x04, + /// Encrypted connection or not + GAPC_ENCRYPTED = 3, + GAPC_ENCRYPTED_MASK = 0x08, + /// Ltk present and exchanged during pairing + GAPC_LTK_PRESENT = 4, + GAPC_LTK_PRESENT_MASK = 0x10, + /// Local connection role + GAPC_ROLE = 5, + GAPC_ROLE_MASK = 0x20, + /// Service Changed CCC configuration + GAPC_SVC_CHG_CCC = 6, + GAPC_SVC_CHG_CCC_MASK = 0x40, +}; + + +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ +extern struct gapc_env_tag *gapc_env[GAPC_IDX_MAX]; + + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Initialize Generic Access Profile Controller Module. + * + * @param[in] reset true if it's requested by a reset; false if it's boot initialization + * + **************************************************************************************** + */ +void gapc_init(bool reset); + + +/** + **************************************************************************************** + * @brief A connection has been created, initialize Controller task. + * + * This function find first available task index available for new connection. + * It triggers also connection event to task that has requested the connection. + * + * @param[in] msgid Message id for normal or enhanced privacy + * @param[in] con_params Connection parameters from lower layers + * @param[in] requester Task that request the connection to send indication(s) + * @param[in] laddr Local BD Address + * @param[in] laddr_type Local BD Address Type (PUBLIC or RAND) + * + * @return Connection index allocated to the new connection. + **************************************************************************************** + */ +uint8_t gapc_con_create(kernel_msg_id_t const msgid, struct hci_le_enh_con_cmp_evt const *con_params, + kernel_task_id_t requester, bd_addr_t *laddr, uint8_t laddr_type); + +/** + **************************************************************************************** + * @brief A connection has been disconnected, uninitialized Controller task. + * + * unregister connection, and destroy environment variable allocated for current connection. + * + * @param[in] conidx Connection index + * + * @return Connection index of the connection. + **************************************************************************************** + */ +uint8_t gapc_con_cleanup(uint8_t conidx); + + +/** + **************************************************************************************** + * @brief Send Disconnection indication to specific task + * + * @param[in] conidx Connection index + * @param[in] reason Disconnection reason + * @param[in] conhdl Connection handle + * @param[in] dest_id Message destination ID + * + **************************************************************************************** + */ +void gapc_send_disconect_ind(uint8_t conidx, uint8_t reason, uint8_t conhdl, + kernel_task_id_t dest_id); + + + +/** + **************************************************************************************** + * @brief Retrieve connection CSRK information on current link. + * + * @param[in] conidx Connection index + * @param[in] src Connection information source + * + * @return Return found connection CSRK + **************************************************************************************** + */ +struct gap_sec_key *gapc_get_csrk(uint8_t conidx, uint8_t src); + +/** + **************************************************************************************** + * @brief Return the sign counter value for the specified connection index. + * + * @param[in] conidx Connection index + * @param[in] src Connection information source + * + * @return the requested signCounter value + **************************************************************************************** + */ +uint32_t gapc_get_sign_counter(uint8_t conidx, uint8_t src); + +/** + * @brief Send a complete event of ongoing executed operation to requester. + * It also clean-up variable used for ongoing operation. + * + * @param[in] conidx Connection index + * @param[in] op_type Operation type. + * @param[in] status Status of completed operation + */ +void gapc_send_complete_evt(uint8_t conidx, uint8_t op_type, uint8_t status); + +/** + **************************************************************************************** + * @brief Send operation completed message with status error code not related to a + * running operation. + * + * @param[in] conidx Connection index + * @param[in] operation Operation code + * @param[in] requester requester of operation + * @param[in] status Error status code + **************************************************************************************** + */ +void gapc_send_error_evt(uint8_t conidx, uint8_t operation, const kernel_task_id_t requester, uint8_t status); + + +/** + **************************************************************************************** + * @brief Get operation on going + * + * @param[in] conidx Connection Index + * @param[in] op_type Operation type. + * + * @return operation code on going + **************************************************************************************** + */ +uint8_t gapc_get_operation(uint8_t conidx, uint8_t op_type); + +/** + **************************************************************************************** + * @brief Get operation pointer + * + * @param[in] conidx Connection Index + * @param[in] op_type Operation type. + * + * @return operation pointer on going + **************************************************************************************** + */ +void *gapc_get_operation_ptr(uint8_t conidx, uint8_t op_type); + + +/** + **************************************************************************************** + * @brief Set operation pointer + * + * @param[in] conidx Connection Index + * @param[in] op_type Operation type. + * @param[in] op Operation pointer. + * + **************************************************************************************** + */ +void gapc_set_operation_ptr(uint8_t conidx, uint8_t op_type, void *op); + +/** + **************************************************************************************** + * @brief Operation execution not finish, request kernel to reschedule it in order to + * continue its execution + * + * @param[in] conidx Connection Index + * @param[in] op_type Operation type. + * + * @return if operation has been rescheduled (not done if operation pointer is null) + **************************************************************************************** + */ +bool gapc_reschedule_operation(uint8_t conidx, uint8_t op_type); + +/** + **************************************************************************************** + * @brief Get requester of on going operation + * + * @param[in] conidx Connection Index + * @param[in] op_type Operation type. + * + * @return task that requests to execute the operation + **************************************************************************************** + */ +kernel_task_id_t gapc_get_requester(uint8_t conidx, uint8_t op_type); + + + + +/** + **************************************************************************************** + * @brief Set the encryption key size of the connection + * + * @param[in] conidx Connection index + * @param[in] key_size encryption key size (size is 7 - 16 byte range) + * + **************************************************************************************** + */ +void gapc_enc_keysize_set(uint8_t conidx, uint8_t key_size); + + +/** + **************************************************************************************** + * @brief Update link status, current link is now encrypted + * + * @param[in] conidx Connection index + * + **************************************************************************************** + */ +void gapc_link_encrypted(uint8_t conidx); + +/** + **************************************************************************************** + * @brief Update link authentication level + * + * @param[in] conidx Connection index + * @param[in] auth Link authentication level + * @param[in] ltk_present Link paired and an LTK has been exchanged + * + **************************************************************************************** + */ +void gapc_auth_set(uint8_t conidx, uint8_t auth, bool ltk_present); + +/** + **************************************************************************************** + * @brief Retrieve link authentication level + * + * @param[in] conidx Connection index + * @return Link authentication level + **************************************************************************************** + */ +uint8_t gapc_auth_get(uint8_t conidx); + +/** + **************************************************************************************** + * @brief Update task state + * + * @param[in] conidx Connection index + * @param[in] state to update + * @param[in] set state to busy (true) or idle (false) + * + **************************************************************************************** + */ +void gapc_update_state(uint8_t conidx, kernel_state_t state, bool busy); + + +/** + **************************************************************************************** + * @brief Checks connection parameters values + * + * @param[in] intv_max maximum interval + * @param[in] intv_min minimum interval + * @param[in] latency latency + * @param[in] timeout timeout value + * + * @return true if OK, false if not OK + **************************************************************************************** + */ +bool gapc_param_update_sanity(uint16_t intv_max, uint16_t intv_min, uint16_t latency, uint16_t timeout); + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ +int gapc_process_op(uint8_t conidx, uint8_t op_type, void *op_msg, enum gapc_operation *supp_ops); + + + + +/* + * TASK DESCRIPTOR DECLARATIONS + **************************************************************************************** + */ +extern const struct kernel_state_handler gapc_default_handler; +extern kernel_state_t gapc_state[GAPC_IDX_MAX]; + +#endif // (BLE_GAPC) +/// @} GAPC_INT + +#endif /* _GAPC_INT_H_ */ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/gap/gapc/gapc_sig.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/gap/gapc/gapc_sig.h new file mode 100755 index 0000000..352724f --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/gap/gapc/gapc_sig.h @@ -0,0 +1,64 @@ +/** + **************************************************************************************** + * + * @file gapc_sig.h + * + * @brief Generic Access Profile Controller Signaling PDU Handler. + * + * Copyright (C) RivieraWaves 2009-2016 + * + **************************************************************************************** + */ + +#ifndef _GAPC_SIG_H_ +#define _GAPC_SIG_H_ + + +/** + **************************************************************************************** + * @addtogroup GAPC_SIG Generic Access Profile Controller Signaling PDU Handler. + * @ingroup GAPC + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_config.h" + +#if (BLE_GAPC) +#include "l2cc_pdu.h" + + +#if (BLE_CENTRAL) +/** + **************************************************************************************** + * @brief Sends parameter response + * + * @param[in] conidx connection index + * @param[in] result response result + * @param[in] pkt_id Packet identifier + **************************************************************************************** + */ +void gapc_sig_send_param_resp(uint8_t conidx, uint16_t result, uint8_t pkt_id); +#endif // (BLE_CENTRAL) + +/** + **************************************************************************************** + * @brief Handles reception of L2CAP signaling messages from peer device. + * + * @param[in] conidx Connection Index + * @param[in] pdu PDU Received + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +int gapc_sig_pdu_recv_handler(uint8_t conidx, struct l2cc_pdu *pdu); + +#endif // (BLE_GAPC) + +#endif // _GAPC_SIG_H_ + +/// @} GAPC_SIG diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/gap/gapm/gapm_int.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/gap/gapm/gapm_int.h new file mode 100755 index 0000000..fa2077a --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/gap/gapm/gapm_int.h @@ -0,0 +1,506 @@ +/** + **************************************************************************************** + * + * @file gapm_int.h + * + * @brief Generic Access Profile Manager Internal Header. + * + * Copyright (C) RivieraWaves 2009-2016 + * + **************************************************************************************** + */ + + +#ifndef _GAPM_INT_H_ +#define _GAPM_INT_H_ + +/** + **************************************************************************************** + * @addtogroup GAPM_INT Generic Access Profile Manager Internal + * @ingroup GAPM + * @brief defines for internal GAPM usage + * + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "gapm.h" +#include "gapm_task.h" +#include "common_bt.h" + + +/* + * DEFINES + **************************************************************************************** + */ + +/// Maximum number of GAP Manager process +#define GAPM_IDX_MAX 0x01 + + +/// Scan filter size +#define GAPM_SCAN_FILTER_SIZE 10 + + + +/* + * INTERNAL API TYPES + **************************************************************************************** + */ + + +/// Retrieve information about memory usage +struct gapm_dbg_get_mem_info_cmd +{ + /// GAPM requested operation: + /// - GAPM_DBG_GET_MEM_INFO: Get memory usage + uint8_t operation; +}; + +/// Indication containing information about memory usage. +struct gapm_dbg_mem_info_ind +{ + /// peak of memory usage measured + uint32_t max_mem_used; + /// memory size currently used into each heaps. + uint16_t mem_used[KERNEL_MEM_BLOCK_MAX]; +}; + + +/// Operation type +enum gapm_op_type +{ + /// Configuration operation + GAPM_OP_CFG = 0x00, + + /// Air mode operation (scanning, advertising, connection establishment) + /// Note: Restriction, only one air operation supported. + GAPM_OP_AIR = 0x01, +#if (SECURE_CONNECTIONS) + /// GAP State for DH Key Generation + GAPM_OP_DHKEY = 0x02, +#endif // (SECURE_CONNECTIONS) + /// Max number of operations + GAPM_OP_MAX +}; + + +/// GAPM states +enum gapm_state_id +{ + /// Idle state - no on going operation + GAPM_IDLE, + + /// Busy state - Configuration operation on going + GAPM_CFG_BUSY = 1 << GAPM_OP_CFG, + /// Busy state - Air operation on going + GAPM_AIR_BUSY = 1 << GAPM_OP_AIR, +#if (SECURE_CONNECTIONS) + /// Busy state - DH Key Calculation operation on going + GAPM_DHKEY_BUSY = 1 << GAPM_OP_DHKEY, +#endif // (SECURE_CONNECTIONS) + + /// Reset state - Reset operation on going + GAPM_DEVICE_SETUP = 1 << GAPM_OP_MAX, + + GAPM_STATE_MAX +}; +/// Device configuration flags +/// 7 6 5 4 3 2 1 0 +/// +-----+----+----+----+----+----+----+----+ +/// | DBG | SC | CP | GA | RE |CTLP|HSTP|ADDR| +/// +-----+----+----+----+----+----+----+----+ +/// - Bit [0-2]: Address Type @see enum gapm_cfg_flag +/// Bit 0: 0 = Public address, 1 = Private address +/// Bit 1: 0 = Host-based Privacy disabled, 1 = enabled +/// Bit 2: 0 = Controller-based Privacy disabled, 1 = enabled +/// +/// - Bit [3] : Address to renew (only if privacy is enabled, 1 address to renew else 0) +/// - Bit [4] : Generated Address type (1 = Resolvable, 0 = Non Resolvable) +/// - Bit [5] : Preferred Connection parameters present in GAP DB +/// - Bit [6] : Service Change feature present +/// - Bit [7] : Enable Debug mode + +/// Configuration flag bit description +enum gapm_cfg_flag_def +{ + /// Address Type + GAPM_MASK_ADDR_TYPE = 0x07, + GAPM_POS_ADDR_TYPE = 0x00, + /// Address to renew + GAPM_MASK_ADDR_RENEW = 0x08, + GAPM_POS_ADDR_RENEW = 0x03, + /// Generated Address type + GAPM_MASK_RESOLV_ADDR = 0x10, + GAPM_POS_RESOLV_ADDR = 0x04, + /// Preferred Connection parameters present in GAP DB + GAPM_MASK_PREF_CON_PAR_PRES = 0x20, + GAPM_POS_PREF_CON_PAR_PRES = 0x05, + /// Service Change feature present + GAPM_MASK_SVC_CHG_EN = 0x40, + GAPM_POS_SVC_CHG_EN = 0x06, + +#if (BLE_DEBUG) + /// L2CAP Debug Mode used to force LE-frames + GAPM_MASK_DBG_MODE_EN = 0x80, + GAPM_POS_DBG_MODE_EN = 0x07, +#endif // (BLE_DEBUG) + +}; + + +/* + * MACROS + **************************************************************************************** + */ +/// Macro used to retrieve field +#define GAPM_F_GET(data, field)\ + (((data) & (GAPM_MASK_ ## field)) >> (GAPM_POS_ ## field)) + +/// Macro used to set field +#define GAPM_F_SET(data, field, val)\ + (data) = (((data) & ~(GAPM_MASK_ ## field)) \ + | ((val << (GAPM_POS_ ## field)) & (GAPM_MASK_ ## field))) + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + +/// Information about registered LE_PSM +struct gapm_le_psm_info +{ + /// List header structure to put information within a list + struct common_list_hdr hdr; + + /// LE Protocol/Service Multiplexer + uint16_t le_psm; + + /// Registered task identifier + kernel_task_id_t task_id; + + /// Security level + /// 7 6 5 4 3 2 1 0 + /// +---+---+---+---+---+---+---+---+ + /// |MI | RFU |EKS|SEC_LVL| + /// +---+---+---+---+---+---+---+---+ + /// bit[0-1]: Security level requirement (0=NO_AUTH, 1=UNAUTH, 2=AUTH, 3=SEC_CON) + /// bit[2] : Encryption Key Size length must have 16 bytes + /// bit[7] : Multi-instantiated task + uint8_t sec_lvl; + + /// Number of established link + uint8_t nb_est_lk; +}; + + +/// GAP Manager environment structure +struct gapm_env_tag +{ + /// Request operation Kernel message + void *operation[GAPM_OP_MAX]; + +#if (BLE_CENTRAL || BLE_OBSERVER) + /// Scan filtering Array + struct gap_bdaddr *scan_filter; +#endif // (BLE_CENTRAL || BLE_OBSERVER) + +#if (BLE_LECB) + /// Registered list of LE Protocol/Service Multiplexer for LE Credit Based Connection + struct common_list reg_le_psm; +#endif // (BLE_LECB) + +#if (BLE_ATTS) + /// GAP service start handle + uint16_t svc_start_hdl; +#endif // (BLE_ATTS) + + /// Duration before regenerate device address when privacy is enabled. - in seconds + uint16_t renew_dur; + /// Device IRK used for resolvable random BD address generation (MSB -> LSB) + struct gap_sec_key irk; + /// Device Identity Address + bd_addr_t addr_identity; + /// Current device Address + bd_addr_t addr; + /// Device Role + uint8_t role; + /// Number of BLE connection + uint8_t connections; + /// Device configuration flags - (@see enum gapm_cfg_flag_def) + uint8_t cfg_flags; + /// Pairing mode authorized (see enum gapm_pairing_mode) + uint8_t pairing_mode; + /// Maximum device MTU size + uint16_t max_mtu; + /// Maximum device MPS size + uint16_t max_mps; +#if (SECURE_CONNECTIONS) + /// Local device Public Key + public_key_t public_key; +#endif // (SECURE_CONNECTIONS) + +#if(BLE_AUDIO) + /// Audio configuration flag (see gapm_audio_cfg_flag) + uint16_t audio_cfg; +#endif // (BLE_AUDIO) + +#if(BLE_EMB_PRESENT && HCI_TL_SUPPORT) + /// In Full mode, by default the AHI API is used, but if an HCI Reset is received, + /// TL is switched to HCI and embedded host is disabled + bool embedded_host; +#endif // (BLE_EMB_PRESENT && HCI_TL_SUPPORT) + +#if (BLE_LECB) + /// Maximum number of allowed LE Credit Based channels + uint8_t max_nb_lecb; + /// Current number of LE Credit Based channel connections established + uint8_t nb_lecb; +#endif // (BLE_LECB) +}; + +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ +/// GAP Manager environment variable. +extern struct gapm_env_tag gapm_env; + + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Initialize GAP attribute database + * + * @param[in] start_hdl Service Start Handle + * @param[in] feat Attribute database features + * + * @return status code of attribute database initialization + * - @ref ATT_ERR_NO_ERROR: If database creation succeeds. + * - @ref ATT_ERR_INVALID_HANDLE: If start_hdl given in parameter + nb of attribute override + * some existing services handles. + * - @ref ATT_ERR_INSUFF_RESOURCE: There is not enough memory to allocate service buffer. + * or of new attribute cannot be added because all expected + * attributes already add + **************************************************************************************** + */ +uint8_t gapm_init_attr(uint16_t start_hdl, uint32_t feat); + +/** + **************************************************************************************** + * @brief Send operation completed message according to operation type. + * Perform also am operation clean-up + * + * @param[in] op_type Operation type + * @param[in] status Command status + ***************************************************************************************** + */ +void gapm_send_complete_evt(uint8_t op_type, uint8_t status); + +/** + **************************************************************************************** + * @brief Send operation completed message with status error code not related to a + * running operation. + * + * @param[in] operation Operation code + * @param[in] requester requester of operation + * @param[in] status Error status code + **************************************************************************************** + */ +void gapm_send_error_evt(uint8_t operation, const kernel_task_id_t requester, uint8_t status); + + +/** + **************************************************************************************** + * @brief Get operation pointer + * + * @param[in] op_type Operation type. + * + * @return operation pointer on going + **************************************************************************************** + */ +__INLINE void *gapm_get_operation_ptr(uint8_t op_type) +{ + ASSERT_ERR(op_type < GAPM_OP_MAX); + // return operation pointer + return gapm_env.operation[op_type]; +} + + +/** + **************************************************************************************** + * @brief Set operation pointer + * + * @param[in] op_type Operation type. + * @param[in] op Operation pointer. + * + **************************************************************************************** + */ +__INLINE void gapm_set_operation_ptr(uint8_t op_type, void *op) +{ + ASSERT_ERR(op_type < GAPM_OP_MAX); + // update operation pointer + gapm_env.operation[op_type] = op; +} + + +/** + **************************************************************************************** + * @brief Get operation on going + * + * @param[in] op_type Operation type. + * + * @return operation code on going + **************************************************************************************** + */ +uint8_t gapm_get_operation(uint8_t op_type); + + +/** + **************************************************************************************** + * @brief Operation execution not finish, request kernel to reschedule it in order to + * continue its execution + * + * @param[in] op_type Operation type. + * + * @return if operation has been rescheduled (not done if operation pointer is null) + **************************************************************************************** + */ +bool gapm_reschedule_operation(uint8_t op_type); + +/** + **************************************************************************************** + * @brief Get requester of on going operation + * + * @param[in] op_type Operation type. + * + * @return task that requests to execute the operation + **************************************************************************************** + */ +kernel_task_id_t gapm_get_requester(uint8_t op_type); + + + + +#if (BLE_GAPC) +/** + **************************************************************************************** + * @brief A connection has been created, initialize host stack to be ready for connection. + * + * @param[in] msgid Message id + * @param[in] operation Air operation type + * @param[in] con_params Connection parameters from lower layers + * + * @return Connection index allocated to the new connection. + **************************************************************************************** + */ +uint8_t gapm_con_create(kernel_msg_id_t const msgid, uint8_t operation, struct hci_le_enh_con_cmp_evt const *con_params); + +#endif // (BLE_GAPC) + +/** + **************************************************************************************** + * Retrieve if current connection index is used for a discovery purpose such as + * Name discovery + * + * @param conidx Index of the specific connection + * + * @return true if connection has a discovery purpose, False else + **************************************************************************************** + */ +bool gapm_is_disc_connection(uint8_t conidx); + +/** + **************************************************************************************** + * @brief Set the maximal MTU value + * + * @param[in] mtu Max MTU value (Minimum is 23) + **************************************************************************************** + */ +void gapm_set_max_mtu(uint16_t mtu); + +/** + **************************************************************************************** + * @brief Set the maximal MPS value + * + * @param[in] mps Max MPS value (Minimum is 23) + **************************************************************************************** + */ +void gapm_set_max_mps(uint16_t mps); + +/** + **************************************************************************************** + * @brief Checks validity of the address type + * + * @param[in] addr_type Address type + **************************************************************************************** + */ +uint8_t gapm_addr_check( uint8_t addr_type); + +/** + **************************************************************************************** + * @brief Checks validity of the Data Length Suggested values + * + * @param[in] sugg_oct Suggested octets + * @param[in] sugg_time Suggested time + **************************************************************************************** + */ +uint8_t gapm_dle_val_check(uint16_t sugg_oct, uint16_t sugg_time); + + + +/** + **************************************************************************************** + * @brief Update task state + * + * @param[in] operation that modify the state + * @param[in] set state to busy (true) or idle (false) + * + **************************************************************************************** + */ +void gapm_update_state(uint8_t operation, bool busy); + + + +#if (BLE_LECB) + + +/** + **************************************************************************************** + * @brief Find Information about LE_PSM registered in GAPM + * + * @param[in] le_psm LE Protocol/Service Multiplexer + * + * @return Null if not found or LE_PSM info structure + **************************************************************************************** + */ +struct gapm_le_psm_info *gapm_le_psm_find(uint16_t le_psm); + + +/** + **************************************************************************************** + * @brief Remove all registered LE_PSM + **************************************************************************************** + */ +void gapm_le_psm_cleanup(void); +#endif // (BLE_LECB) + +/* + * TASK DESCRIPTOR DECLARATIONS + **************************************************************************************** + */ +extern const struct kernel_state_handler gapm_default_handler; +extern kernel_state_t gapm_state[GAPM_IDX_MAX]; + +/// @} GAPM_INT + +#endif /* _GAPM_INT_H_ */ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/gap/gapm/gapm_util.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/gap/gapm/gapm_util.h new file mode 100755 index 0000000..970c446 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/gap/gapm/gapm_util.h @@ -0,0 +1,439 @@ +/** + **************************************************************************************** + * + * @file gapm_util.h + * + * @brief Generic Access Profile Manager Tool Box Header. + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + + +#ifndef _GAPM_UTIL_H_ +#define _GAPM_UTIL_H_ + +/** + **************************************************************************************** + * @addtogroup GAPM_UTIL Generic Access Profile Manager Tool Box + * @ingroup GAPM + * @brief Generic Access Profile Manager Tool Box + * + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_config.h" +#include "kernel_task.h" +#include "gapm.h" + + +/* + * DEFINES + **************************************************************************************** + */ +/// GAP Manager operation state - air commands +enum gapm_op_state +{ + /* state in non connected mode */ + /// Initial state of the operation + GAPM_OP_INIT, // 0 + /// Set operation parameters + GAPM_OP_SET_PARAMS, // 1 + /// Clear White List operation + GAPM_OP_CLEAR_WL,// 2 + /// Set White List operation + GAPM_OP_SET_WL,// 3 + /// Set operation advertise data + GAPM_OP_SET_ADV_DATA,// 4 + /// Set operation scan response data + GAPM_OP_SET_SCAN_RSP_DATA,// 5 + /// Generation of address + GAPM_OP_ADDR_GEN,// 6 + /// Set private address + GAPM_OP_ADDR_SET,// 7 + /// Start operation (advertising, scanning or connecting) + GAPM_OP_START,// 8 + /// Operation is in wait (advertising, scanning or connecting) state + GAPM_OP_WAIT, + /// Stop operation (advertising, scanning or connecting) + GAPM_OP_STOP, + /// Operation is finished + GAPM_OP_FINISH, + + /// Error state + GAPM_OP_ERROR, + + + /* state in connected mode */ + /// Connection established + GAPM_OP_CONNECT, + /// Perform peer device name request + GAPM_OP_NAME_REQ, + /// Perform peer device disconnection + GAPM_OP_DISCONNECT, + + /// Operation is in canceled state and shall be terminated. + GAPM_OP_CANCEL, + /// Operation is in timeout state and shall be terminated. + GAPM_OP_TIMEOUT, + /// Operation is terminated due to a timeout. + GAPM_OP_TERM_TIMEOUT, + /// Renew address generation + GAPM_OP_ADDR_RENEW, + /// initiate a connection request + GAPM_OP_CONNECT_REQ, + + + /// Mask used to retrieve operation state in state parameter + GAPM_OP_MASK = 0x00FF, + + /* Specific bit fields into operation state machine */ + /// Mask used to know in state parameter if message is in kernel queue + GAPM_OP_QUEUED_MASK = 0x0100, + + /// Operation is in canceled state and shall be terminated. + GAPM_OP_CANCELED_MASK = 0x0200, + + /// Operation is in timeout state and shall be terminated. + GAPM_OP_TIMEOUT_MASK = 0x0400, + + /// Renew address generation + GAPM_OP_ADDR_RENEW_MASK = 0x0800, + + /// Mask used to know in state parameter if a connection has been initiated + GAPM_OP_CONNECTING_MASK = 0x1000, + + /// Mask used to know if device is currently in scanning state + GAPM_OP_SCANNING_MASK = 0x2000 +}; + +/// state machine of reset operation +enum gapm_op_reset_state +{ + /// initialization of reset operation state machine + GAPM_OP_RESET_INIT, + /// HCI_RESET_CMD command execution completed + GAPM_OP_RESET_HCI, + /// HCI_SET_EVT_MASK_CMD command execution completed + GAPM_OP_RESET_SET_EVT_MASK, + /// HCI_LE_SET_EVT_MASK_CMD command execution completed + GAPM_OP_RESET_LE_SET_EVT_MASK, + /// HCI_RD_BD_ADDR_CMD command execution completed + GAPM_OP_RESET_RD_BD_ADDR, + #if (BLE_CENTRAL || BLE_PERIPHERAL) + /// HCI_LE_RD_BUFF_SIZE_CMD command execution completed + GAPM_OP_RESET_LE_RD_BUFF_SIZE, + /// HCI_RD_BUFF_SIZE_CMD command execution completed + GAPM_OP_RESET_RD_BUFF_SIZE, + #endif // (BLE_CENTRAL || BLE_PERIPHERAL) +}; + +/// state machine of setup operation +enum gapm_op_setup_state +{ + /// initialization of device setup operation state machine + GAPM_OP_SETUP_INIT, + #if BLE_DEBUG + GAPM_OP_SETUP_SET_4_0_LE_EVT_MASK, + #endif // BLE_DEBUG + /// HCI_LE_WR_SUGGTED_DFT_DATA_LEN_CMD command execution completed + GAPM_OP_SETUP_WR_LE_DFT_DATA_LEN_CMD, + #if (BLE_2MBPS) + /// HCI_LE_SET_DFT_PHY_CMD command execution completed + GAPM_OP_SETUP_SET_LE_DFT_PHY_CMD, + #endif // (BLE_2MBPS) + /// HCI_LE_SET_RSLV_PRIV_ADDR_TO_CMD command execution completed + GAPM_OP_SETUP_SET_RENEW_TO, + /// HCI_LE_SET_ADDR_RESOL_EN_CMD command execution completed + GAPM_OP_SETUP_EN_CTRL_PRIV, + /// Device address management is over: + /// HCI_RD_BD_ADDR_CMD command execution completed + /// or HCI_LE_SET_RAND_ADDR_CMD command execution completed + GAPM_OP_SETUP_ADDR_MGT, + #if (SECURE_CONNECTIONS) + /// HCI_LE_RD_LOC_P256_PUB_KEY_CMD command execution completed + GAPM_OP_SETUP_RD_PRIV_KEY, + #endif // (SECURE_CONNECTIONS) +}; + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + + +/* + * MACROS + **************************************************************************************** + */ +/// check if current role is supported by configuration +#define GAPM_IS_ROLE_SUPPORTED(role_type)\ + ((gapm_env.role & (role_type)) == (role_type)) + +/// Get current operation state +#define GAPM_GET_OP_STATE(operation) \ + ((operation).state & (GAPM_OP_MASK)) + +/// Set current operation state +#define GAPM_SET_OP_STATE(operation, new_state) \ + (operation).state = (((operation).state & ~(GAPM_OP_MASK)) | (new_state)) + + +/// Get if operation is in kernel queue +#define GAPM_IS_OP_FIELD_SET(operation, field) \ + ((((operation).state) & (GAPM_OP_##field##_MASK)) != 0) + +/// Set operation in kernel queue +#define GAPM_SET_OP_FIELD(operation, field) \ + ((operation).state) |= (GAPM_OP_##field##_MASK) + +/// Clear operation in kernel queue +#define GAPM_CLEAR_OP_FIELD(operation, field) \ + ((operation).state) &= ~(GAPM_OP_##field##_MASK) + + + + +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Interface to get the device role. + * + * @return uint8_t device role + * + **************************************************************************************** + */ +uint8_t gapm_get_role(void); + + +#if (BLE_BROADCASTER || BLE_PERIPHERAL) +/** + **************************************************************************************** + * @brief Enable or disable advertising mode. + * + * @param[in] en_flag enabling flag for advertising mode + * + **************************************************************************************** + */ +void gapm_set_adv_mode(uint8_t en_flag); +/** + **************************************************************************************** + * Execute Advertising operation according to current operation state. + **************************************************************************************** + */ +void gapm_execute_adv_op(void); + + +/** + **************************************************************************************** + * Perform a sanity check on advertising operation + * + * @return sanity check status: GAP_ERR_NO_ERROR if succeed, error code else. + **************************************************************************************** + */ +uint8_t gapm_adv_op_sanity(void); + +/** + **************************************************************************************** + * Set the advertising data + * + * @return length Size of the + **************************************************************************************** + */ +void gapm_set_adv_data(uint8_t length, uint8_t* data); + +#endif // (BLE_BROADCASTER || BLE_PERIPHERAL) + + +#if (BLE_OBSERVER || BLE_CENTRAL) +/** + **************************************************************************************** + * @brief Enable or disable scanning mode. + * + * @param[in] en_flag enabling flag for scanning mode + * @param[in] filter_duplic_en enabling duplicate filtering mode + * + **************************************************************************************** + */ +void gapm_set_scan_mode(uint8_t en_flag, uint8_t filter_duplic_en); + + +/** + **************************************************************************************** + * @brief retrieve AD Type Flag information in advertising data. + * + * @param[in] data Advertising data + * @param[in] length Advertising data length + * + * @return Advertising AD Type flag value if found, 0x00 else. + **************************************************************************************** + */ +uint8_t gapm_get_ad_type_flag(uint8_t *data, uint8_t length); + + +/** + **************************************************************************************** + * @brief Add device to unfiltered device + * + * @param[in] addr Device address + * @param[in] addr_type Device address type + **************************************************************************************** + */ +void gapm_add_to_filter(bd_addr_t * addr, uint8_t addr_type); + +/** + **************************************************************************************** + * @brief Check if device is filtered or not when a scan response data is received + * + * If device is not filtered (present in filter list), in that case function returns false + * and device is removed from filtered devices. + * + * @param[in] addr Device address + * @param[in] addr_type Device address type + * + * @return true if device filtered, false else. + **************************************************************************************** + */ +bool gapm_is_filtered(bd_addr_t * addr, uint8_t addr_type); + +/** + **************************************************************************************** + * @brief Execute Scan operation according to current operation state. + * + **************************************************************************************** + */ +void gapm_execute_scan_op(void); + +/** + **************************************************************************************** + * Perform a sanity check on Scanning operation + * + * @return sanity check status: GAP_ERR_NO_ERROR if succeed, error code else. + **************************************************************************************** + */ +uint8_t gapm_scan_op_sanity(void); + +#endif // (BLE_OBSERVER || BLE_CENTRAL) + + +#if (BLE_CENTRAL) +/** + **************************************************************************************** + * @brief Execute Connection operation according to current operation state. + * + **************************************************************************************** + */ +void gapm_execute_connect_op(void); + + +/** + **************************************************************************************** + * Perform a sanity check on connection operation + * + * @return sanity check status: GAP_ERR_NO_ERROR if succeed, error code else. + **************************************************************************************** + */ +uint8_t gapm_connect_op_sanity(void); + +#endif // (BLE_CENTRAL) + +/** + **************************************************************************************** + * @brief Requests current operation state to change. + * + * 1. Check if new state can be applied to ongoing operation. + * 2. Verify that message is not in kernel message queue. + * 3. If not push it into @ref TASK_GAPM message queue + * + * @param[in] op_type Ongoing Air operation type (GAPM_OP_AIR) + * @param[in] state New state to set + * @param[in] status Status code of the transition + * + **************************************************************************************** + */ +void gapm_update_air_op_state(uint8_t op_type, uint8_t state, uint8_t status); + + +/** + **************************************************************************************** + * @brief Sends a basic HCI command (with no parameter) + * + * @param[in] opcode Command opcode + **************************************************************************************** + */ +void gapm_basic_hci_cmd_send(uint16_t opcode); + +/** + **************************************************************************************** + * @brief General configuration for new connections (including privacy 1.2) + * + * @param[in] msgid message id + * @param[in] event Parameters + **************************************************************************************** + */ +void gapm_setup_conn(kernel_msg_id_t const msgid, struct hci_le_enh_con_cmp_evt const *event); + +/** + **************************************************************************************** + * @brief Get proper advertising mode + * + * @param[in] operation Operation + * @param[in] air_op Air operation + * + * @return mode + **************************************************************************************** + */ +uint8_t gapm_get_adv_mode (uint8_t operation, struct gapm_air_operation* air_op); + +/** + **************************************************************************************** + * @brief Get local address type + * + * @return addres type + **************************************************************************************** + */ +uint8_t gapm_get_local_addrtype (void); + + +/** + **************************************************************************************** + * Handles the Reset state machine + * + * + * @param[in] current_state Current operation state (@see enum gapm_reset_state) + * @param[in] status Current operation status + **************************************************************************************** + */ +void gapm_op_reset_continue(uint8_t current_state, uint8_t status); + +/** + **************************************************************************************** + * Handles the Device Setup state machine + * + * + * @param[in] current_state Current operation state (@see enum gapm_reset_state) + * @param[in] status Current operation status + **************************************************************************************** + */ +void gapm_op_setup_continue(uint8_t current_state, uint8_t status); + +/// @} GAPM_UTIL + +#endif /* _GAPM_UTIL_H_ */ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/gap/smp_common.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/gap/smp_common.h new file mode 100755 index 0000000..5940f62 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/gap/smp_common.h @@ -0,0 +1,159 @@ +/** +**************************************************************************************** +* +* @file smp_common.h +* +* @brief Header file - Security Manager Protocol Common Definitions and Functions. +* +* Copyright (C) RivieraWaves 2009-2016 +* +* +**************************************************************************************** +*/ + +/** + **************************************************************************************** + * @addtogroup SMP_COMMON + * @ingroup SMP + * @{ + **************************************************************************************** + */ + +#ifndef SMP_COMMON_H_ +#define SMP_COMMON_H_ + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" + +#include // Standard Boolean Definitions +#include // Standard Integer Definitions + +#include "common_utils.h" +#include "common_bt.h" // Common Bluetooth Definitions + +/* + * DEFINES + **************************************************************************************** + */ + +/// Mask applied to a Pairing Failed error triggered by us. +#define SMP_PAIR_FAIL_REASON_MASK (0x60) +/// Mask applied to a Pairing Failed error triggered by the peer device. +#define SMP_PAIR_FAIL_REASON_REM_MASK (0x70) + +/* + * MACROS + **************************************************************************************** + */ + +/// Mask a Pairing Failed reason value with the provided mask. +#define SMP_GEN_PAIR_FAIL_REASON(mask, reason) (mask | reason) +/// Extract the mask from a masked Pairing Failed reason value. +#define SMP_GET_PAIR_FAIL_MASK(reason) (0xF0 & reason) +/// Extract the Pairing Failed reason value from a masked Pairing Failed reason value. +#define SMP_GET_PAIR_FAIL_REASON(reason) (0x0F & reason) + +/* + * ENUMERATIONS + **************************************************************************************** + */ + +/** + * SMP Pairing Failed Reasons + */ +enum smp_pair_fail_reason +{ + + /** + * Passkey Entry Failed (0x01) + * The user input of passkey failed, for example, the user cancelled the operation. + */ + SMP_ERROR_PASSKEY_ENTRY_FAILED = 0x01, + /** + * OOB Not Available (0x02) + * The OOB Data is not available. + */ + SMP_ERROR_OOB_NOT_AVAILABLE, + /** + * Authentication Requirements (0x03) + * The pairing procedure cannot be performed as authentication requirements cannot be + * met due to IO capabilities of one or both devices. + */ + SMP_ERROR_AUTH_REQ, + /** + * Confirm Value Failed (0x04) + * The confirm value does not match the calculated confirm value. + */ + SMP_ERROR_CONF_VAL_FAILED, + /** + * Pairing Not Supported (0x05) + * Pairing is not supported by the device. + */ + SMP_ERROR_PAIRING_NOT_SUPP, + /** + * Encryption Key Size (0x06) + * The resultant encryption key size is insufficient for the security requirements of + * this device. + */ + SMP_ERROR_ENC_KEY_SIZE, + /** + * Command Not Supported (0x07) + * The SMP command received is not supported on this device. + */ + SMP_ERROR_CMD_NOT_SUPPORTED, + /** + * Unspecified Reason (0x08) + * Pairing failed due to an unspecified reason. + */ + SMP_ERROR_UNSPECIFIED_REASON, + /** + * Repeated Attempts (0x09) + * Pairing or Authentication procedure is disallowed because too little time has elapsed + * since last pairing request or security request. + */ + SMP_ERROR_REPEATED_ATTEMPTS, + /** + * Invalid Parameters (0x0A) + * The command length is invalid or a parameter is outside of the specified range. + */ + SMP_ERROR_INVALID_PARAM, + /** + * DHKey Check Failed (0x0B) + * Indicates to the remote device that the DHKey Check value received doesn't + * match the one calculated by the local device. + */ + SMP_ERROR_DHKEY_CHECK_FAILED, + /** + * Numeric Comparison Failed (0x0C) + * Indicates that the confirm values in the numeric comparison protocol do not match. + */ + SMP_ERROR_NUMERIC_COMPARISON_FAILED, + /** + * BR/EDR pairing in progress (0x0D) + * Indicates that the pairing over the LE transport failed due to a Pairing Request sent + * over the BR/EDR transport in process. + */ + SMP_ERROR_BREDR_PAIRING_IN_PROGRESS, + /** + * Cross-transport Key Derivation/Generation not allowed (0x0E) + * + * Indicates that the BR/EDR Link Key generated on the BR/EDR transport cannot be + * used to derive and distribute keys for the LE transport. + */ + SMP_ERROR_CROSS_TRANSPORT_KEY_GENERATION_NOT_ALLOWED, +}; + + +/* + * STRUCTURES + **************************************************************************************** + */ + + +#endif // (SMP_COMMON_H_) + +/// @} SMP_COMMON diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/gap/smpc/smpc_api.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/gap/smpc/smpc_api.h new file mode 100755 index 0000000..e97373f --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/gap/smpc/smpc_api.h @@ -0,0 +1,561 @@ +/** + **************************************************************************************** + * + * @file smpc_api.h + * + * @brief Header file SMPC API. + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + +#ifndef SMPC_API_H_ +#define SMPC_API_H_ + +/** + **************************************************************************************** + * @addtogroup SMPC_API Task + * @ingroup SMPC + * @brief Provides a SMP API for controller tasks. + * + * The SMPC api is responsible for all security protocol and secure connections handling. + * + * @{ + **************************************************************************************** + */ +/* + * INCLUDE FILES + **************************************************************************************** + */ + + +#include "rwip_config.h" +#if (BLE_SMPC) +#include "../smp_common.h" +#include "gap.h" +#include "gapc_task.h" +#include "l2cc_pdu.h" + +/* + * DEFINES + **************************************************************************************** + */ + + +/// check if flag is set +#define SMPC_IS_FLAG_SET(conidx, flag) ((gapc_env[conidx]->smpc.timer_state & flag) == flag) + +#define SMPC_TIMER_SET_FLAG(conidx, flag) (gapc_env[conidx]->smpc.timer_state |= flag) + +#define SMPC_TIMER_UNSET_FLAG(conidx, flag) (gapc_env[conidx]->smpc.timer_state &= ~flag) + + +/** + * Timer State Masks + */ +/// Timeout Timer +#define SMPC_TIMER_TIMEOUT_FLAG (0x01) +/// Repeated Attempts Timer +#define SMPC_TIMER_REP_ATT_FLAG (SMPC_TIMER_TIMEOUT_FLAG << 1) +/// Blocked because of SMP Timeout +#define SMPC_TIMER_TIMEOUT_BLOCKED_FLAG (SMPC_TIMER_REP_ATT_FLAG << 1) + + +/// SMPC Internal State Code +enum smpc_state +{ + SMPC_STATE_RESERVED = 0x00, + + /******************************************************** + * Pairing Procedure + ********************************************************/ + + /**------------------------------------** + * Pairing Features Exchange Phase * + **------------------------------------**/ + /// Is waiting for the pairing response + SMPC_PAIRING_RSP_WAIT, + /// Is waiting for the pairing features + SMPC_PAIRING_FEAT_WAIT, + + /**------------------------------------** + * Legacy (Pre BT 4.2 ) Authentication and Encryption Phase * + **------------------------------------**/ + + /// Is waiting for the TK + SMPC_PAIRING_TK_WAIT, + /// Is waiting for the TK, peer confirm value has been received + SMPC_PAIRING_TK_WAIT_CONF_RCV, + /// Calculate the Random Number, part 1 + SMPC_PAIRING_GEN_RAND_P1, + /// Calculate the Random Number, part 2 + SMPC_PAIRING_GEN_RAND_P2, + /// The first part of the device's confirm value is being generated + SMPC_PAIRING_CFM_P1, + /// The device's confirm value is being generated + SMPC_PAIRING_CFM_P2, + /// The first part of the peer device's confirm value is being generated + SMPC_PAIRING_REM_CFM_P1, + /// The peer device's confirm value is being generated + SMPC_PAIRING_REM_CFM_P2, + /// The device is waiting for the confirm value generated by the peer device + SMPC_PAIRING_WAIT_CONFIRM, + /// The device is waiting for the random value generated by the peer device + SMPC_PAIRING_WAIT_RAND, + /// The STK is being generated + SMPC_PAIRING_GEN_STK, + +#if (SECURE_CONNECTIONS) + /**------------------------------------** + * Secure Connections (BT 4.2 ) Authentication and Encryption Phase * + **------------------------------------**/ + SMPC_PAIRING_SC_W4_PEER_PUBLIC_KEY, + + // Just Works and Numeric Comparison + //--------------------------------- + + // In Just Works/Numeric Comparison - this state is used while + // we are waiting for the LL to generate a Rand. + SMPC_PAIRING_SC_W4_LOCAL_RAND_N_P1, + SMPC_PAIRING_SC_W4_LOCAL_RAND_N_P2, + // Used in Slave during F4 while waiting for AES_CMAC + SMPC_PAIRING_SC_W4_F4_COMMITMENT_DETERMINATION, + + // Used in Master to Wait for Peer Commitment Cb + SMPC_PAIRING_SC_W4_PEER_COMMITMENT, + + // Used in Master/Slave to Wait for Random Number From peer. + SMPC_PAIRING_SC_W4_PEER_RAND, + + // Used in Slave to wait for Random Number Na from Master + // SMPC_PAIRING_SC_W4_PAIRING_Na, + + // Used in Master during F4 calculation for Commitment Check + SMPC_PAIRING_SC_W4_F4_COMMITMENT_CHECK, + + // Numeric Comparison + // States specific to Secure Commenctions - numeric comparison + + // Used in both Master/Slave to wait for the AES-CMAC calculation does to calculated the + // PassCode for the user. + + SMPC_PAIRING_SC_W4_G2_AES_CMAC, + + // Wait for the user to enter Accept/Reject for the Numeric Value + SMPC_PAIRING_SC_W4_NC_ACCEPT, + // Used in both Master/Slave while waiting for the user Pass Code Confirmation. + + SMPC_PAIRING_SC_W4_USER_PASSCODE_CONFIRMATION, + + //----------------------------- + // Secure Connections - Passkey + //----------------------------- + + // Used in both Master/Slave while the user is entering the PassKey + SMPC_PAIRING_SC_PASSKEY_W4_PASSKEY_RAND, + + // Used in both Master/Slave while Random numbers Nai,Nbi are being generated. + SMPC_PAIRING_SC_PASSKEY_W4_LOCAL_RAND_N_P1, + + // Used in both Master/Slave while Random numbers Nai,Nbi are being generated. + SMPC_PAIRING_SC_PASSKEY_W4_LOCAL_RAND_N_P2, + + // Used in both Master/Slave while waiting for the commitment value Cai,Cbi from the peer + SMPC_PAIRING_SC_PASSKEY_W4_PEER_COMMITMENT, + + // Used in both Master/Slave while using AES_CMAC during F4 calculation of the commitment + SMPC_PAIRING_SC_PASSKEY_W4_F4_COMMITMENT_DETERMINATION, + + // Used in both Master/Slave while waiting for the random number Nai,Nbi from the peer + SMPC_PAIRING_SC_PASSKEY_W4_PEER_RAND, + + // Used in both Master/Slave while using AES_CMAC during F4 calculation for the commitment check + SMPC_PAIRING_SC_PASSKEY_W4_F4_COMMITMENT_CHECK, + + + // OOB + SMPC_PAIRING_SC_OOB_W4_LOCAL_RAND_N_P1, + + SMPC_PAIRING_SC_OOB_W4_LOCAL_RAND_N_P2, + + SMPC_PAIRING_SC_OOB_W4_LOCAL_RAND_R_P1, + + SMPC_PAIRING_SC_OOB_W4_LOCAL_RAND_R_P2, + + SMPC_PAIRING_SC_OOB_W4_F4_COMMITMENT_DETERMINATION, + + SMPC_PAIRING_SC_OOB_W4_F4_COMMITMENT_CHECK, + + SMPC_PAIRING_SC_OOB_W4_PEER_RAND, + + // Wait for OOB data (A,Ca,Ra OR B,Cb,Rb) to be recieved from Peer. + SMPC_PAIRING_SC_OOB_W4_OOB_DATA, + + // Secure Connections Authentication Phase 2 + SMPC_PAIRING_SC_AUTH_START_PHASE_2, + + // Wait for the AES_CMACsalt to generate T + SMPC_PAIRING_SC_W4_F5_P1, + + // Wait for the AES_CMAC to generate MACKEY + SMPC_PAIRING_SC_W4_F5_P2, + + // Wait for the AES_CMAC to generate LTK + SMPC_PAIRING_SC_W4_F5_P3, + + // Wait for the AES_CMAC to complete the DHKEY check + SMPC_PAIRING_SC_W4_F6_DHKEY_CHECK, + + // Wait for DHkey_Check from the peer + SMPC_PAIRING_SC_W4_PEER_DHKEY_CHECK, + + SMPC_PAIRING_SC_W4_F6_DHKEY_VERIFICATION, + + SMPC_PAIRING_SC_W4_DHKEY_KEY_COMPLETE, + + SMPC_PAIRING_SC_W4_ENCRYPTION_START, + + SMPC_PAIRING_SC_W4_ENCRYPTION_CHANGE, + +#endif // (SECURE_CONNECTIONS) + /**------------------------------------** + * Transport Keys Distribution Phase * + **------------------------------------**/ + + /// Default pairing remote waiting state + SMPC_PAIRING_APP_WAIT, + /// Is waiting for the LTK from application + SMPC_PAIRING_APP_LTK_WAIT, + /// Is waiting for the Identity Resolving Key from application + SMPC_PAIRING_APP_IRK_WAIT, + /// Is waiting for the CSRK from application + SMPC_PAIRING_APP_CSRK_WAIT, + + + /// Default pairing remote waiting state + SMPC_PAIRING_REM_WAIT, + /// Is waiting for the remote LTK + SMPC_PAIRING_REM_LTK_WAIT, + /// Is waiting for the remote EDIV and Rand Value + SMPC_PAIRING_REM_MST_ID_WAIT, + /// Is waiting for the remote IRK + SMPC_PAIRING_REM_IRK_WAIT, + /// Is waiting for the remote BD Address + SMPC_PAIRING_REM_BD_ADDR_WAIT, + /// Is waiting for the remote CSRK + SMPC_PAIRING_REM_CSRK_WAIT, + + /******************************************************** + * Signing Procedure + ********************************************************/ + /// Generation of L + SMPC_SIGN_L_GEN, + /// Generation of Ci + SMPC_SIGN_Ci_GEN, + + /******************************************************** + * Encryption Procedure (STK or LTK) + ********************************************************/ + /// Is waiting the change encryption event with LTK + SMPC_START_ENC_LTK, + /// Is waiting the change encryption event with STK + SMPC_START_ENC_STK +}; + +/* + * FUNCTION DEFINITION + **************************************************************************************** + */ + +#if (BLE_CENTRAL) +/** + **************************************************************************************** + * @brief Handles pairing request from GAP, start the pairing procedure + * + * @param[in] idx Connection Index + * @param[in] pairing Pairing Information + * + * @return Status of Pairing start + **************************************************************************************** + */ +uint8_t smpc_pairing_start(uint8_t idx, struct gapc_pairing *pairing); +#endif // (BLE_CENTRAL) + + +/** + **************************************************************************************** + * @brief Handles TK exchange part of pairing + * + * @param[in] idx Connection Index + * @param[in] accept True if pairing is accepted, False else + * @param[in] tk The TK transmitted by application + * + * @return status of pairing + **************************************************************************************** + */ +uint8_t smpc_pairing_tk_exch(uint8_t idx, bool accept, struct gap_sec_key *tk); + +/** + **************************************************************************************** + * @brief Handles LTK exchange part of pairing + * + * @param[in] idx Connection Index + * @param[in] ltk The LTK transmitted by application + * + * @return status of pairing + **************************************************************************************** + */ +uint8_t smpc_pairing_ltk_exch(uint8_t idx, struct gapc_ltk *ltk); + + +/** + **************************************************************************************** + * @brief Handles IRK exchange part of pairing + * + * @param[in] idx Connection Index + * @param[in] irk The IRK transmitted by application + * @param[in] identity Device identity address + * + * @return status of pairing + **************************************************************************************** + */ +uint8_t smpc_pairing_irk_exch(uint8_t idx, struct gap_sec_key *irk, struct gap_bdaddr *identity); + +/** + **************************************************************************************** + * @brief Handles CSRK exchange part of pairing + * + * @param[in] idx Connection Index + * @param[in] csrk The CSRK transmitted by application + * + * @return status of pairing + **************************************************************************************** + */ +uint8_t smpc_pairing_csrk_exch(uint8_t idx, struct gap_sec_key *csrk); + +#if (SECURE_CONNECTIONS) +/** + **************************************************************************************** + * @brief Handles OOB exchange part of pairing + * + * @param[in] idx Connection Index + * @param[in] accept Accept or Reject the OOB (reject if OOB reception not available on the device) + * @param[in] csrk The OOB Confirm and OOB Rand from the peer + * + * @return status of pairing + **************************************************************************************** + */ + +uint8_t smpc_pairing_oob_exch(uint8_t idx, bool accept, struct gapc_oob *oob); + +/** + **************************************************************************************** + * @brief Handles Numeric Value Acceptance as part of pairing + * + * @param[in] idx Connection Index + * @param[in] accept Accept or Reject the numeric comparison + * + * @return status of pairing + **************************************************************************************** + */ + +uint8_t smpc_pairing_nc_exch(uint8_t idx, uint8_t accept ); + +#endif // (SECURE_CONNECTIONS) +/** + **************************************************************************************** + * @brief Handles reception of pairing response information + * + * @param[in] idx Connection Index + * @param[in] accept True if pairing is accepted, False else + * @param[in] feat Pairing response feature information + * + * @return status of pairing + **************************************************************************************** + */ +uint8_t smpc_pairing_rsp(uint8_t idx, bool accept, struct gapc_pairing *feat); + + +#if (BLE_PERIPHERAL) + +/** + **************************************************************************************** + * @brief Handles reception of pairing request information + * + * @param[in] idx Connection Index + * @param[in] feat Pairing request feature information + **************************************************************************************** + */ +void smpc_pairing_req_handler(uint8_t idx, struct gapc_pairing *feat); + +/** + **************************************************************************************** + * @brief Handles request to send a security request to peer device + * + * @param[in] idx Connection Index + * @param[in] auth Requested Authentication Level + * + * @return status of the request + **************************************************************************************** + */ +uint8_t smpc_security_req_send(uint8_t idx, uint8_t auth); +#endif // (BLE_PERIPHERAL) + + +#if (BLE_CENTRAL) +/** + **************************************************************************************** + * @brief Master requests to start encryption + * + * @param[in] idx Connection Index + * @param[in] ltk LTK information + * + * @return status of the request + **************************************************************************************** + */ +uint8_t smpc_encrypt_start(uint8_t idx, struct gapc_ltk *ltk); +#endif //(BLE_CENTRAL) + + +#if (BLE_PERIPHERAL) + +/** + **************************************************************************************** + * @brief Handles reception of encryption request + * + * @param[in] idx Connection Index + * @param[in] ltk LTK to search information + **************************************************************************************** + */ +void smpc_encrypt_start_handler(uint8_t idx, struct gapc_ltk *ltk); + +/** + **************************************************************************************** + * @brief Slave respond to peer device encryption request + * + * @param[in] idx Connection Index + * @param[in] accept Accept or not to start encryption + * @param[in] ltk LTK information + * @param[in] key_size Encryption key size + **************************************************************************************** + */ +void smpc_encrypt_cfm(uint8_t idx, bool accept, struct gap_sec_key *ltk, uint8_t key_size); +#endif //(BLE_PERIPHERAL) + + +/** + **************************************************************************************** + * @brief Request to sign an attribute packet or check signature + * + * @param[in] idx Connection Index + * @param[in] param ATT packet information + * + * @return status of signature request + **************************************************************************************** + */ +uint8_t smpc_sign_command(uint8_t idx, struct gapc_sign_cmd *param); + + +/** + **************************************************************************************** + * @brief Continue signature generation or check of an attribute packet after an AES. + * + * @param[in] idx Connection Index + * @param[in] aes_res Result of AES calculation + **************************************************************************************** + */ +void smpc_sign_cont(uint8_t idx, uint8_t *aes_res); + +/** + **************************************************************************************** + * @brief Continue generation of rand number for confirm value. + * + * @param[in] idx Connection Index + * @param[in] randnb Generated Random Number + **************************************************************************************** + */ +void smpc_confirm_gen_rand(uint8_t idx, rand_nb_t *randnb); + +/** + **************************************************************************************** + * @brief Continue Calculation of Confirm Value or STK after AES. + * + * @param[in] idx Connection Index + * @param[in] aes_res Result of AES calculation + **************************************************************************************** + */ +void smpc_calc_confirm_cont(uint8_t idx, uint8_t *aes_res); + +/** + **************************************************************************************** + * @brief Send an KeyPress Notification Event to the Host + * + * @param[in] idx Connection Index + * @param[in] keypress KeyPress Type + **************************************************************************************** + */ +void smpc_key_press_notification_ind(uint8_t idx, uint8_t keypress); + +/** + **************************************************************************************** + * @brief Stop the timer used to detect a SMP Timeout + * + * @param[in] conidx Connection Index + **************************************************************************************** + */ +void smpc_clear_timeout_timer(uint8_t conidx); + + +/** + **************************************************************************************** + * @brief Handle reception of a SMP PDU sent by the peer device. + * + * @param[in] conidx Connection Index + * @param[in] pdu Unpacked PDU + **************************************************************************************** + */ +void smpc_pdu_recv(uint8_t conidx, struct l2cc_pdu *pdu); + +/** + **************************************************************************************** + * @brief Send a SMP PDU to the peer device + * + * @param[in] conidx Connection Index + * @param[in] cmd_code Code of the PDU to send + * @param[in] value Unpacked value + **************************************************************************************** + */ +void smpc_pdu_send(uint8_t conidx, uint8_t cmd_code, void *value); + + +/** + **************************************************************************************** + * @brief Inform the HL that the pairing procedure currently in progress is over. + * + * @param[in] conidx Connection Index + * @param[in] role Current role of the device + * @param[in] status Status + * @param[in] start_ra_timer Indicate if the repeated attempts timer shall be started in + * the case of a pairing failed. + **************************************************************************************** + */ +void smpc_pairing_end(uint8_t conidx, uint8_t role, uint8_t status, bool start_ra_timer); + + +/** + **************************************************************************************** + * @brief Handle reception of a DH Key from HCI + * + * @param[in] conidx Connection Index + * @param[in] status Indicates if HCI request Succeeded or Failed + * @param[in] dh_key Diffie Helman Key - 32 Bytes + **************************************************************************************** + */ +void smpc_handle_dh_key_check_complete(uint8_t conidx, const uint8_t *dh_key); + +#endif // (BLE_SMPC) +#endif //(SMPC_API_H_) + +/// @} SMPC_API diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/gap/smpc/smpc_crypto.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/gap/smpc/smpc_crypto.h new file mode 100755 index 0000000..407d566 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/gap/smpc/smpc_crypto.h @@ -0,0 +1,177 @@ +/** + **************************************************************************************** + * + * @file smpc_crypto.h + * + * @brief Header file for SMP Secure Connection Cryptographic Functions + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + +#ifndef SMPC_CRYPTO_H_ +#define SMPC_CRYPTO_H_ + +#include "rwip_config.h" +#if (SECURE_CONNECTIONS) +#include "../smp_common.h" + +/** + **************************************************************************************** + * @brief Initiates the F4 crypto function + * + * @param[in] conidx connection identifier + * @param[in] U pointer to array of bytes (see spec) + * @param[in] V pointer to array of bytes (see spec) + * @param[in] X pointer to array of bytes (see spec) + * @param[in] Z single byte value (see spec) + * @return none. + **************************************************************************************** + */ +void smpc_f4_Init(uint8_t conidx, uint8_t *U, uint8_t *V, uint8_t *X, uint8_t Z); + + +/** + **************************************************************************************** + * @brief Cleans up after the F4 crypto function, freeing any memory which had been allocated + * + * @param[in] conidx connection identifier + * @return none. + **************************************************************************************** + */ +void smpc_f4_complete(uint8_t conidx); + + +/** + **************************************************************************************** + * @brief Initiates the G2 crypto function + * + * @param[in] conidx connection identifier + * @param[in] U pointer to array of bytes (see spec) + * @param[in] V pointer to array of bytes (see spec) + * @param[in] X pointer to array of bytes (see spec) + * @param[in] Y pointer to array of bytes (see spec) + * @return none. + **************************************************************************************** + */ +void smpc_g2_init(uint8_t conidx, uint8_t *U, uint8_t *V, uint8_t *X, uint8_t *Y); + +/** + **************************************************************************************** + * @brief Cleans up after the G2 crypto function, freeing any memory which had been allocated + * + * @param[in] conidx connection identifier + * @return none. + **************************************************************************************** + */ +void smpc_g2_complete(uint8_t conidx); + +/** + **************************************************************************************** + * @brief Initiates the F5 crypto function + * + * @param[in] conidx connection identifier + * @param[in] W pointer to the DH Key + * @param[in] N1 pointer to 16 byte random number + * @param[in] N2 pointer to 16 byte random number + * @param[in] A1 pointer to array representing address of device + * @param[in] A2 pointer to array representing address of device + * @return none. + **************************************************************************************** + */ +void smpc_f5_init(uint8_t conidx, uint8_t *W, uint8_t *N1, uint8_t *N2, uint8_t *A1, uint8_t *A2); + +/** + **************************************************************************************** + * @brief Cleans up after the F5 crypto function, freeing any memory which had been allocated + * + * @param[in] conidx connection identifier + * @return none. + **************************************************************************************** + */ +void smpc_f5_complete(uint8_t conidx); + +/** + **************************************************************************************** + * @brief Initiates the F6 crypto function + * + * @param[in] conidx connection identifier + * @param[in] W pointer to Mac Key + * @param[in] N1 pointer to 16 byte random number + * @param[in] N2 pointer to 16 byte random number + * @param[in] R pointer to array of bytes (see spec) + * @param[in] IoCap pointer to array representing IO capabilities of device + * @param[in] A1 pointer to array representing address of device + * @param[in] A2 pointer to array representing address of device + * @return none. + **************************************************************************************** + */ +void smpc_f6_init(uint8_t conidx, uint8_t *W, uint8_t *N1, uint8_t *N2, uint8_t *R, uint8_t *IOcap, uint8_t *A1, uint8_t *A2); + +/** + **************************************************************************************** + * @brief Cleans up after the F6 crypto function, freeing any memory which had been allocated + * + * @param[in] conidx connection identifier + * @return none. + **************************************************************************************** + */ +void smpc_f6_complete(uint8_t conidx); + +/** + **************************************************************************************** + * @brief Initiates the AES CMAC crypto function. Allocate memory for the CMAC and + * begins the subkey generation + * + * @param[in] conidx connection identifier + * @param[in] K pointer to the Key to be used + * @param[in] M pointer to the block of data the data on which the CMAC is performed + * @param[in] M_len length (in bytes) of the block of data M + * @return none. + **************************************************************************************** + */ +void smpc_aes_cmac_init(uint8_t conidx, uint8_t *K, uint8_t *M, uint8_t M_len); + +/** + **************************************************************************************** + * @brief Continues subsequent stages of the AES CMAC crypto function + * + * @param[in] conidx connection identifier + * @param[in] aes_res point to the result of the previous stage of the AES CMAC + * + * @return none. + **************************************************************************************** + */ +void smpc_aes_cmac_continue(uint8_t conIdx, uint8_t *aes_res); + +/** + **************************************************************************************** + * @brief The final stage of the AES CMAC crypto function + * + * @param[in] conidx connection identifier + * @param[in] aes_res point to the result of the previous stage of the AES CMAC + * + * @return none. + **************************************************************************************** + */ +void smpc_aes_cmac_complete(uint8_t conIdx, uint8_t *aes_res); + +/** + **************************************************************************************** + * @brief Process the next stage of the AES CMAC (wrapping smpc_aes_cmac_continue(..) and + * smpc_aes_cmac_complete(..) + * + * @param[in] conidx connection identifier + * @param[in] aes_res point to the result of the previous stage of the AES CMAC + * + * @returns boolean Indicate if the AES CMAC is complete + **************************************************************************************** + */ + +bool smpc_process_aes_cmac(uint8_t idx, uint8_t *aes_res); +#endif // (SECURE_CONNECTIONS) + + +#endif /* SMPC_CRYPTO_H_ */ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/gap/smpc/smpc_int.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/gap/smpc/smpc_int.h new file mode 100755 index 0000000..d702a14 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/gap/smpc/smpc_int.h @@ -0,0 +1,511 @@ +/** + **************************************************************************************** + * + * @file smpc_int.h + * + * @brief Header file - SMPC. + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + +#ifndef SMPC_INT_H_ +#define SMPC_INT_H_ + +/** + **************************************************************************************** + * @addtogroup SMP_INT Security Manager Protocol Internal + * @ingroup HOST + * @brief Security Manager Protocol Internals. + * @{ + * + **************************************************************************************** + */ + + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_config.h" + +#if (BLE_SMPC) +#include "smpc.h" + +#include "../smp_common.h" + +#include +#include + +#include "common_bt.h" +#include "gap.h" + +#include "smpc_api.h" + +/* + * DEFINES + **************************************************************************************** + */ + +/// Minimum Encryption key size +#define SMPC_MIN_ENC_SIZE_LEN (7) +/// Maximum Encryption Key size +#define SMPC_MAX_ENC_SIZE_LEN (16) + + +/// Pairing Request and Pairing Response PDU Length +#define SMPC_CODE_PAIRING_REQ_RESP_LEN (7) + + +/* + * ENUMERATIONS + **************************************************************************************** + */ + + +///Security Properties for distributed keys(all have the issued STK's properties) +enum +{ + ///No security properties + SMP_KSEC_NONE = 0x00, + ///Unauthenticated no MITM + SMP_KSEC_UNAUTH_NO_MITM, + ///Authenticated with MITM + SMP_KSEC_AUTH_MITM, +}; + +/// Repeated Attempts Attack Detection status +enum smpc_attempts_status +{ + /// No attack has been detected + SMPC_REP_ATTEMPTS_NO_ERROR = GAP_ERR_NO_ERROR, // 0x00 + /// An attack has already been detected, drop the message + SMPC_REP_ATTEMPTS_ATTACK, + /// An attack has been detected, an indication has been sent to the HL + SMPC_REP_ATTEMPS_ATTACK_DETECTED, + /// Repeated Attempt detected, need to send a Pairing Failed PDU to the peer device + SMPC_REP_ATTEMPT = SMP_ERROR_REPEATED_ATTEMPTS // 0x09 +}; + + +/// STK generation methods +enum smpc_method +{ + ///Just Works Method + SMPC_METH_JW = 0x00, + ///PassKey Entry Method + SMPC_METH_PK, + ////OOB Method + SMPC_METH_OOB, + ////Numeric Comparison + SMPC_METH_NC +}; + +/// Signature Command Types +enum +{ + /// Generate Signature + SMPC_SIGN_GEN = 0x00, + /// Verify Signature + SMPC_SIGN_VERIF +}; + +enum +{ + /// Use of STK in start encryption command + SMPC_USE_STK = 0x00, + /// Use of LTK in start encryption command + SMPC_USE_LTK +}; + +#if (SECURE_CONNECTIONS) +enum +{ + SMP_AES_CMAC_KEY_GENERATION = 0x00, + + SMP_AES_CMAC_BLOCK +}; + +/// Keypress Notification types +enum smpc_notification_type +{ + /// Passkey entry started + SMP_PASSKEY_ENTRY_STARTED = 0x00, + /// Passkey digit entered + SMP_PASSKEY_DIGIT_ENTERED, + /// Passkey digit erased + SMP_PASSKEY_DIGIT_ERASED, + /// Passkey cleared + SMP_PASSKEY_CLEARED, + /// Passkey entry completed + SMP_PASSKEY_ENTRY_COMPLETED +}; +#endif // (SECURE_CONNECTIONS) +/* + * STRUCTURES DEFINITION + **************************************************************************************** + */ + +/* + * GLOBAL VARIABLES DEFINITION + **************************************************************************************** + */ + + +/* + * MACROS + **************************************************************************************** + */ +/// Authentication Request mask +#define SMPC_MASK_AUTH_REQ(req) (req & 0x07) + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Send a SMPM_USE_ENC_BLOCK_CMD message to the SMPM. Shall be use when the AES_128 + * encryption block need to be used. + * + * @param[in] conidx Connection Index + * @param[in] operand_1 First operand + * @param[in] operand_2 Second operand + **************************************************************************************** + */ +void smpc_send_use_enc_block_cmd(uint8_t conidx, + uint8_t *operand_1, uint8_t *operand_2); + + +/** + **************************************************************************************** + * @brief Send a SMPM_GEN_DH_KEY_CMD message to the SMPM. Shall be use when we need to + * generate a DH KEy + * + * @param[in] conidx Connection Index + * @param[in] operand_1 X co-ordinate + * @param[in] operand_2 Y co-ordinate + **************************************************************************************** + */ + +void smpc_send_gen_dh_key_cmd(uint8_t conidx, + uint8_t *operand_1, uint8_t *operand_2); + +/** + **************************************************************************************** + * @brief Send a request to the controller to start the encryption procedure. + * + * @param[in] conidx Connection Index + * @param[in] operand_1 First operand + * @param[in] operand_2 Second operand + **************************************************************************************** + */ +void smpc_send_start_enc_cmd(uint8_t idx, uint8_t key_type, uint8_t *key, + uint8_t *randnb, uint16_t ediv); + +/** + **************************************************************************************** + * @brief Send the LTK provided by the HL to the controller. + * + * @param[in] idx Connection Index + * @param[in] found Indicate if the requested LTK has been found by the application + * @param[in] key Found LTK, used only if found is set to true + **************************************************************************************** + */ +void smpc_send_ltk_req_rsp(uint8_t idx, bool found, uint8_t *key); + +/** + **************************************************************************************** + * @brief Send a SMPC_PAIRING_REQ_IND message to the HL + * + * @param[in] conidx Connection Index + * @param[in] req_type Kind of request + **************************************************************************************** + */ +void smpc_send_pairing_req_ind(uint8_t conidx, uint8_t req_type); + +/** + **************************************************************************************** + * @brief Send a SMPC_PAIRING_IND message to the HL + * + * @param[in] conidx Connection Index + * @param[in] ind_type Kind of indication + * @param[in] value Value to indicate (keys, ...) + **************************************************************************************** + */ +void smpc_send_pairing_ind(uint8_t conidx, uint8_t ind_type, void *value); + +/** + **************************************************************************************** + * @brief Check if the provided pairing features are within the specified range. + * + * @param[in] pair_feat Pairing Features values to check + * + * @param[out] true if features are valid, else false + **************************************************************************************** + */ +bool smpc_check_pairing_feat(struct gapc_pairing *pair_feat); + +/** + **************************************************************************************** + * @brief Check if an attack by repeated attempts has been triggered by the peer device + * + * @param[in] conidx Connection Index + **************************************************************************************** + */ +uint8_t smpc_check_repeated_attempts(uint8_t conidx); + +/** + **************************************************************************************** + * @brief Compute and check the encryption key size to use during the connection. + * + * @param[in] conidx Connection Index + * + * @param[out] true if the resultant EKS is within the specified range [7-16 bytes], else false + **************************************************************************************** + */ +bool smpc_check_max_key_size(uint8_t conidx); + +/** + **************************************************************************************** + * @brief Check if the keys distribution scheme is compliant with the required security + * level + * + * @param[in] conidx Connection Index + * @param[in] sec_level Security level required by the device. + **************************************************************************************** + */ +bool smpc_check_key_distrib(uint8_t conidx, uint8_t sec_level); + +/** + **************************************************************************************** + * @brief Apply the XOR operator to the two provided operands + * + * @param[in|out] result Buffer which will contain the result of the XOR operation + * @param[in] operand_1 First operand + * @param[in] operand_2 Second operand + **************************************************************************************** + */ +void smpc_xor(uint8_t *result, uint8_t *operand_1, uint8_t *operand_2); + +/** + **************************************************************************************** + * @brief Generate the L value during a signature verification/generation procedure. + * + * @param[in] conidx Connection Index + * @param[in] src Indicate the source of the CSRK which will be used (LOCAL or PEER) + **************************************************************************************** + */ +void smpc_generate_l(uint8_t conidx, uint8_t src); + +/** + **************************************************************************************** + * @brief Generate one of the Ci value during a signature verification/generation procedure. + * + * @param[in] conidx Connection Index + * @param[in] src Indicate the source of the CSRK which will be used (LOCAL or PEER) + * @param[in] ci1 Previous computed Ci value + * @param[in] mi 16-byte block used to generate the ci value + **************************************************************************************** + */ +void smpc_generate_ci(uint8_t conidx, uint8_t src, uint8_t *ci1, uint8_t *mi); + +/** + **************************************************************************************** + * @brief Generate the random value exchanged during the pairing procedure (phase 2) + * + * @param[in] conidx Connection Index + * @param[in] state New state of the SMPC task. + **************************************************************************************** + */ +void smpc_generate_rand(uint8_t conidx, uint8_t state); + +/** + **************************************************************************************** + * @brief Generate the first value needed in the confirm value generation + * + * @param[in] conidx Connection Index + * @param[in] role Current role of the device + * @param[in] local true if the confirm value to generate is the confirm value of the + * device, false if it is the remote device's one. + **************************************************************************************** + */ +void smpc_generate_e1(uint8_t conidx, uint8_t role, bool local); + +/** + **************************************************************************************** + * @brief Generate the confirm value + * + * @param[in] conidx Connection Index + * @param[in] role Current role of the device + * @param[in] e1 e1 value + **************************************************************************************** + */ +void smpc_generate_cfm(uint8_t conidx, uint8_t role, uint8_t *e1); + +/** + **************************************************************************************** + * @brief Generate the STK used to encrypt a link after the pairing procedure + * + * @param[in] conidx Connection Index + * @param[in] role Current role of the device + **************************************************************************************** + */ +void smpc_generate_stk(uint8_t conidx, uint8_t role); + +/** + **************************************************************************************** + * @brief Calculate one of the subkey used during the signature generation/verification + * procedure. + * + * @param[in] gen_k2 true if the returned subkeys is k2, false if k1 + * @param[in] l_value L value obtained from the CSRK. + * @param[in|out] subkey Buffer which will contain the generated subkey. + **************************************************************************************** + */ +void smpc_calc_subkeys(bool gen_k2, uint8_t *l_value, uint8_t *subkey); + +/** + **************************************************************************************** + * @brief Start to send the keys defined during the pairing features exchange procedure. + * + * @param[in] conidx Connection Index + * @param[in] role Current role of the device + **************************************************************************************** + */ +void smpc_tkdp_send_start(uint8_t conidx, uint8_t role); + +/** + **************************************************************************************** + * @brief Define the next step of TKDP procedure (sending side). + * + * @param[in] conidx Connection Index + * @param[in] role Current role of the device + **************************************************************************************** + */ +void smpc_tkdp_send_continue(uint8_t conidx, uint8_t role); + +/** + **************************************************************************************** + * @brief Put the task in a state allowing to receive the keys defined during the pairing + * features exchange procedure. + * + * @param[in] conidx Connection Index + * @param[in] role Current role of the device + **************************************************************************************** + */ +void smpc_tkdp_rcp_start(uint8_t conidx, uint8_t role); + +/** + **************************************************************************************** + * @brief Define the next step of TKDP procedure (reception side). + * + * @param[in] conidx Connection Index + * @param[in] role Current role of the device + **************************************************************************************** + */ +void smpc_tkdp_rcp_continue(uint8_t conidx, uint8_t role); + + +/** + **************************************************************************************** + * @brief Start the timer used to detect a Repeated Attempts attack + * + * @param[in] conidx Connection Index + **************************************************************************************** + */ +void smpc_launch_rep_att_timer(uint8_t conidx); + +/** + **************************************************************************************** + * @brief Determine the method which will be used to generate the STK during a pairing + * procedure + * + * @param[in] conidx Connection Index + **************************************************************************************** + */ +void smpc_get_key_sec_prop(uint8_t conidx); + +/** + **************************************************************************************** + * @brief Check if the security mode requested by the application or the peer device can + * be reached with the exchanged pairing features. + * + * @param[in] conidx Connection Index + * @param[in] role Current role of the device + **************************************************************************************** + */ +bool smpc_is_sec_mode_reached(uint8_t conidx, uint8_t role); + +/** + **************************************************************************************** + * @brief Define what to do once a start encryption procedure has been successfully finished. + * + * @param[in] conidx Connection Index + * @param[in] role Current role of the device + * @param[in] status Status + **************************************************************************************** + */ +void smpc_handle_enc_change_evt(uint8_t conidx, uint8_t role, uint8_t status); + + +#if (SECURE_CONNECTIONS) +/** + **************************************************************************************** + * @brief Initiate DHKey Check algorithm + * + * @param[in] conidx Connection Index + **************************************************************************************** + */ +void smpc_initiate_dhkey_check(uint8_t conidx); + +/** + **************************************************************************************** + * @brief Initiates the f5 algorithm to calculate the MacKey and LTK for a link + * + * @param[in] conidx Connection Index + * + **************************************************************************************** + */ + +void smpc_init_mac_key_calculation(uint8_t conidx); + +/** + **************************************************************************************** + * @brief Initiates the f6 algorithm to verify a DH Key Check. + * + * @param[in] conidx Connection Index + * + **************************************************************************************** + */ + +void smpc_initiate_dhkey_verification(uint8_t conidx); + +/** + **************************************************************************************** + * @brief Determines the next bit of the passkey to be used + * + * @param[in] conidx Connection Index + * + **************************************************************************************** + */ +uint8_t smpc_get_next_passkey_bit(uint8_t conidx); + +/** + **************************************************************************************** + * @brief Checks if secure connections are enabled on a link + * + * @param[in] conidx Connection Index + * + **************************************************************************************** + */ +bool smpc_secure_connections_enabled(uint8_t idx); + +#endif // (SECURE_CONNECTIONS) +#endif //(BLE_SMPC) +#endif //SMPC_INT_H_ + +/// @} SMPC diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/gap/smpc/smpc_util.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/gap/smpc/smpc_util.h new file mode 100755 index 0000000..2b19a29 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/gap/smpc/smpc_util.h @@ -0,0 +1,82 @@ +/** + **************************************************************************************** + * + * @file smpc_util.h + * + * @brief Header file for SMPC utilities. + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + +#ifndef SMPC_UTIL_H_ +#define SMPC_UTIL_H_ + +/** + **************************************************************************************** + * @addtogroup SMPC_UTIL Utility + * @ingroup SMPC + * @brief Contains utility functions and macros for SMPC. + * + * The SMPC Utilities block contains key generating and security related functions + * that are useful in accomplishing the task of the security manager protocol + * layer of the Bluetooth Low Energy. + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_config.h" +#if (BLE_SMPC) + +#include "../smp_common.h" +#include + +#include "l2cc_pdu.h" +#include "smpc_int.h" + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + +/// SMPC command PDU construct function pointer type definition +typedef void (*smpc_construct_pdu_t)(struct l2cc_pdu *pdu, void *value); + +/// SMPC command PDU reception functions +typedef void (*smpc_recv_pdu_t)(uint8_t idx, struct l2cc_pdu *pdu); + +/* + * GLOBAL VARIABLES DECLARATION + **************************************************************************************** + */ + +extern const smpc_construct_pdu_t smpc_construct_pdu[L2C_CODE_SECURITY_MAX]; +extern const smpc_recv_pdu_t smpc_recv_pdu[L2C_CODE_SECURITY_MAX]; + +/* + * FUNCTIONS DECLARATION + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Parameter checking function of SMP PDU packets. + * + * @param[in] pdu Pointer to the data part of the SMP command PDU. + * + * @return Value of check parameter status, to be reported to host or back to peer. + **************************************************************************************** + */ +uint8_t smpc_check_param(struct l2cc_pdu *pdu); + +#endif //(BLE_SMPC) +#endif //(SMPC_UTIL_H_) + +/// @} SMPC_UTIL diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/gap/smpm/smpm_api.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/gap/smpm/smpm_api.h new file mode 100755 index 0000000..1ce8b08 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/gap/smpm/smpm_api.h @@ -0,0 +1,125 @@ +/** + **************************************************************************************** + * + * @file smpm_api.h + * + * @brief Header file - SMPM API + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + +#ifndef SMPM_API_H_ +#define SMPM_API_H_ + +/** + **************************************************************************************** + * @addtogroup SMPM_API Security Manager Protocol Manager API + * @ingroup SMPM + * @brief Provide an API to GAPM task + * + * The SMPM is responsible for all security related functions not related to a + * specific connection with a peer. + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ + + +#include "rwip_config.h" +#if (BLE_SMPM) +#include "gap.h" // GAP Definitions + +/* + * DEFINES + **************************************************************************************** + */ + + +/* + * ENUMERATIONS + **************************************************************************************** + */ + + +/* + * STRUCTURES + **************************************************************************************** +*/ + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + + +/** + **************************************************************************************** + * @brief Generate a random address + * + * @param[in] addr_type Provided address type + * + * @return If request has been processed or not + **************************************************************************************** + */ +uint8_t smpm_gen_rand_addr(uint8_t addr_type); + +/** + **************************************************************************************** + * @brief Resolve a random address + * Note: address should be resolvable + * + * @param[in] addr Device address + * @param[in] irk IRK used for address resolution + * + **************************************************************************************** + */ +void smpm_resolv_addr(bd_addr_t *addr, struct gap_sec_key *irk); + + +/** + **************************************************************************************** + * @brief Use the encryption block + * + * @param[in] operand_1 First operand as encryption block input (16 bytes) + * @param[in] operand_2 Second operand as encryption block input (16 bytes) + * + **************************************************************************************** + */ +void smpm_use_enc_block(uint8_t *operand_1, uint8_t *operand_2); + +/** + **************************************************************************************** + * @brief Generate a random number + **************************************************************************************** + */ +void smpm_gen_rand_nb(void); + + + +/** + **************************************************************************************** + * @brief Send an encryption request to the HCI. + **************************************************************************************** + */ +void smpm_send_encrypt_req(uint8_t *operand_1, uint8_t *operand_2); + +#if (SECURE_CONNECTIONS) +/** + **************************************************************************************** + * @brief Send a generate DH Key request to the HCI. + **************************************************************************************** + */ +void smpm_send_generate_dh_key(uint8_t *operand_1, uint8_t *operand_2); +#endif // (SECURE_CONNECTIONS) + +#endif // (BLE_SMPM) +#endif // (SMPM_API_H_) + +/// @} SMPM_API diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/gatt/attc/attc.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/gatt/attc/attc.h new file mode 100755 index 0000000..413fd07 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/gatt/attc/attc.h @@ -0,0 +1,127 @@ +/** + **************************************************************************************** + * + * @file attc.h + * + * @brief Header file - ATTC. + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + +#ifndef ATTC_H_ +#define ATTC_H_ + +/** + **************************************************************************************** + * @addtogroup ATTC Attribute Client + * @ingroup ATT + * @brief Attribute Protocol Client + * + * The ATTC module is responsible for handling messages intended for the attribute + * profile client. It has defined interfaces with @ref ATTM "ATTM". + * + * @{ + * + **************************************************************************************** + */ +#include "rwip_config.h" + +#include +#include "l2cc.h" +#include "kernel_task.h" + +#if (BLE_ATTC) +/* + * INCLUDE FILES + **************************************************************************************** + */ +/* + * DEFINES + **************************************************************************************** + */ + +/// Allocate a Attribute PDU packet for a specific attribute request. +#define ATTC_ALLOCATE_ATT_REQ(conidx, opcode, pdu_type, value_len)\ + L2CC_ATT_PDU_ALLOC_DYN(conidx, opcode, KERNEL_BUILD_ID(TASK_GATTC, conidx), pdu_type, value_len) + +/* + * DATA STRUCTURES + **************************************************************************************** + */ + +/// Peer device event registration +struct attc_register_evt +{ + /// list header + struct common_list_hdr hdr; + /// Attribute start handle + uint16_t start_hdl; + /// Attribute end handle + uint16_t end_hdl; + /// Task to be notified + kernel_task_id_t task; +}; + + +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ +/** + **************************************************************************************** + * @brief Sends Indication reception confirmation message + * + * @param[in] conidx connection index + * + **************************************************************************************** + */ +void attc_send_hdl_cfm(uint8_t conidx); + +/** + **************************************************************************************** + * @brief Sends write execute. + * + * @param[in] conidx connection index + * @param[in] flag write execute flag (write or discard) + * + **************************************************************************************** + */ +void attc_send_execute(uint8_t conidx, uint8_t flag); + + +/** + **************************************************************************************** + * @brief Send a PDU Attribute request packet + * + * @param[in] conidx Index of the connection with the peer device + * @param[in] pdu PDU Packet + **************************************************************************************** + */ +void attc_send_att_req(uint8_t conidx, void *pdu); + +#endif /* (BLE_ATTC) */ + +#if (BLE_CENTRAL || BLE_PERIPHERAL) +/** + **************************************************************************************** + * @brief Handles reception of PDU Packet + * + * @param[in] conidx Index of the connection with the peer device + * @param[in] param Received PDU Packet + * + * @return If message has been proceed or consumed + **************************************************************************************** + */ +int attc_l2cc_pdu_recv_handler(uint8_t conidx, struct l2cc_pdu_recv_ind *param); +#endif /* #if (BLE_CENTRAL || BLE_PERIPHERAL) */ + +/// @} ATTC +#endif // ATT_H_ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/gatt/attm/attm_db.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/gatt/attm/attm_db.h new file mode 100755 index 0000000..ad888df --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/gatt/attm/attm_db.h @@ -0,0 +1,387 @@ +/** + **************************************************************************************** + * + * @file attm_db.h + * + * @brief Header file - ATTM. + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + +#ifndef ATTM_DB_H_ +#define ATTM_DB_H_ + +/** + **************************************************************************************** + * @addtogroup ATTDB Database + * @ingroup ATTM + * @brief Attribute Protocol Database + * + * The ATTDB module is responsible for providing different sets of attribute databases + * for Attribute Profile server. + * + * This module can be tailored by client, to match the requirement of the desired database. + * + * @{ + * + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_config.h" +#if (BLE_ATTS) +#include +#include "rwip_config.h" +#include "kernel_task.h" +#include "attm.h" +#include "gattm_task.h" + +/* + * DEFINES + **************************************************************************************** + */ + +/** +* Extended Service permissions +* +* 7 6 5 4 3 2 1 0 +* +----+----+----+----+----+----+----+----+ +* | RFU |HIDE| +* +----+----+----+----+----+----+----+----+ +* +* Bit [0] : Hide service visibility +* Bit [1-7]: Reserved for future use +*/ +enum attm_ext_svc_perm_mask +{ + /// Service visibility - Hide = 1 + PERM_MASK_EXT_SVC_HIDE = 0x01, + PERM_POS_EXT_SVC_HIDE = 0, +}; + + + +/* + * TYPE DEFINITION + **************************************************************************************** + */ +#if(BLE_ATTS) + +/** + * Attribute Description + */ +struct attm_att_desc +{ + /** + * 16 bits UUID or data offset used to retrieve 32 or 128 bits UUID in service memory block + */ + uint16_t uuid; + + /** + * Attribute Permission (@see attm_perm_mask) + */ + uint16_t perm; + + /** + * value information (@see attm_value_perm_mask) + */ + union att_info + { + /// attribute max length (RI = 1) + uint16_t max_length; + + /// attribute value offset pointer (RI = 0) + uint16_t offset; + } info; +}; + +/// attribute value if present in database +struct attm_att_value +{ + /// Maximum attribute length + uint16_t max_length; + /// currrent attribute length that can be read. + uint16_t length; + ///value data pointer + uint8_t value[__ARRAY_EMPTY]; +}; + +/// service description +struct attm_svc_desc +{ + /// Service Start Handle + uint16_t start_hdl; + /// Service End Handle + uint16_t end_hdl; + /// Task identifier that manages service + uint16_t task_id; + + /** + * Service Permission (@see attm_svc_perm_mask) + */ + uint8_t perm; + + /// Extended Service Permission (@see attm_ext_svc_perm_mask) + uint8_t ext_perm; + + /// Service 16 bits UUID (LSB First) or data offset used to retrieve 32 or 128 bits + /// UUID in service memory block + uint16_t uuid; +}; + +/** + * Service description present in attribute database + */ +struct attm_svc +{ + /// Next Service + struct attm_svc *next; + + /// service description + struct attm_svc_desc svc; + + /** + * List of attribute description present in service. + */ + struct attm_att_desc atts[__ARRAY_EMPTY]; +}; + +/// Attribute element information +struct attm_elmt +{ + /// element info + union elem_info + { + /// attribute info pointer + struct attm_att_desc *att; + + /// service info pointer + struct attm_svc_desc *svc; + } info; + + /// use to know if current element is a service or an attribute + bool service; +}; + +/// ATTM General Information Manager +struct attm_db +{ + /** + * ************************************************************************************** + * @brief Attribute database + * + * The Attribute database is a list of attribute services sorted by handle number. + * This database shall be initiate by GAP, GATT, profiles and application process at + * startup and must not change during runtime. + * + * Database initialization shall be deterministic in order to always have service handle + * at same position in database during all product life-cycle. This is required since + * database client can save position of services in database to not perform service + * discovery at each connection. + *************************************************************************************** + */ + struct attm_svc *svcs; + + /** + *************************************************************************************** + * Last attribute service searched. + * + * Used as a cached variable, it's used to reduce handle search duration. + *************************************************************************************** + */ + struct attm_svc *cache; + + /** + * Temporary value used for read operation on service and characteristics attributes + */ + uint8_t temp_val[ATT_UUID_128_LEN + ATT_HANDLE_LEN + ATT_HANDLE_LEN]; +}; + + + + + +#endif //(BLE_ATTS) + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + * Check if Service handle Range can be allocated in Database, and if handle should be + * dynamically allocated, calculate first available handle range. + * + * @param[in|out] svc_desc Service information to add in DB + * + * @return status of operation + */ +uint8_t attmdb_svc_check_hdl(struct gattm_svc_desc *svc_desc); + +/** + **************************************************************************************** + * @brief Add a service in database. + * + * According to service start handle and number of attribute, ATTM DB allocate a set of + * attribute handles, then using other parameters it allocate a buffer used to describe + * service, and allocate attributes + their values. + * + * If start_hdl = 0, it allocated service using first available handle (start_hdl is + * modified); else it will allocate service according to given start handle. + * + * + * @param[in|out] svc_desc Service description. + * + * @return Command status code: + * - @ref ATT_ERR_NO_ERROR: If service allocation succeeds. + * - @ref ATT_ERR_INVALID_HANDLE: If start_hdl given in parameter or UUIDs value invalid + * - @ref ATT_ERR_INSUFF_RESOURCE: There is not enough memory to allocate service buffer. + **************************************************************************************** + */ +uint8_t attmdb_add_service(struct gattm_svc_desc *svc_desc); + + + + +/** + **************************************************************************************** + * @brief Search in database from which service attribute handle comes from. + * + * @param[in] handle Attribute handle. + * + * @return Services that contains attribute handle; NULL if handle not available in + * database. + **************************************************************************************** + */ +struct attm_svc *attmdb_get_service(uint16_t handle); + +/** + **************************************************************************************** + * @brief Search in database Attribute pointer using attribute handle. + * + * @param[in] handle Attribute handle. + * @param[out] elmt Attribute element to fill + * + * @return Command status code: + * - @ref ATT_ERR_NO_ERROR: If attribute found. + * - @ref ATT_ERR_INVALID_HANDLE: If No Attribute found + **************************************************************************************** + */ +uint8_t attmdb_get_attribute(uint16_t handle, struct attm_elmt *elmt); + +/** + **************************************************************************************** + * @brief Retrieve attribute at or after specified handle + * + * Retrieve first attribute with handle >= parameter handle. + * Parameter handle is updated according found attribute. + * + * @param[in|out] handle Attribute handle. + * @param[out] elmt Attribute element to fill + * + * @return Command status code: + * - @ref ATT_ERR_NO_ERROR: If attribute found. + * - @ref ATT_ERR_INVALID_HANDLE: If No Attribute found + **************************************************************************************** + */ +uint8_t attmdb_get_next_att(uint16_t *handle, struct attm_elmt *elmt); + +/** + **************************************************************************************** + * Check if attribute element UUID is equals to uuid given in parameter. + * + * @param elmt Attribute element that can be a UUID 16 or 128 bits + * @param uuid16 UUID 16 bits to compare + * + * @return True if UUIDs matches, False else. + **************************************************************************************** + */ +bool attmdb_uuid16_comp(struct attm_elmt *elmt, uint16_t uuid16); + +/** + **************************************************************************************** + * @brief Retrieve attribute value Max Length + * + * @param[in] elmt Attribute element information + * @param[out] length Max length Size of attribute value + * + * @return Command status code: + * - @ref ATT_ERR_NO_ERROR: If request succeeds + * - @ref ATT_ERR_REQUEST_NOT_SUPPORTED: If attribute is read only + **************************************************************************************** + */ +uint8_t attmdb_get_max_len(struct attm_elmt *elmt, att_size_t *length); + + +/** + **************************************************************************************** + * @brief Retrieve attribute UUID + * + * @param[in] elmt Attribute information. + * @param[out] uuid_len Size of attribute UUID + * @param[out] uuid UUID value to update + * @param[in] srv_uuid For a service, if set, return service UUID + * @param[in] air Prepare UUID for the air (For a 32 bit UUID, returns a 128 bit UUID) + * + * @return Command status code: + * - @ref ATT_ERR_NO_ERROR: If request succeeds + * - @ref ATT_ERR_INVALID_HANDLE: If handle doesn't exist in database + **************************************************************************************** + */ +uint8_t attmdb_get_uuid(struct attm_elmt *elmt, uint8_t *uuid_len, uint8_t *uuid, bool srv_uuid, bool air); + +/** + **************************************************************************************** + * @brief Retrieve attribute permission + * If access mask is set, service authentication or encryption key size value can be loaded. + * + * @param[in] handle Attribute handle. + * @param[out] perm Permission value to return + * @param[in] mode_mask Mode Access mask to check type of access + * parameter (0 return full attribute permission) + * @param[in] perm_mask Permission Access mask to check only specific permission + * @param[in|out] elmt Attribute information + * + * @return Command status code: + * - @ref ATT_ERR_NO_ERROR: If request succeeds + * - @ref ATT_ERR_INVALID_HANDLE: If handle doesn't exist in database. + * - @ref ATT_ERR_REQUEST_NOT_SUPPORTED: If mode is disabled. + * - @ref ATT_ERR_INSUFF_AUTHOR: when service is disabled. + * - @ref ATT_ERR_INSUFF_ENC_KEY_SIZE: + **************************************************************************************** + */ +uint8_t attmdb_att_get_permission(uint16_t handle, uint16_t *perm, uint16_t mode_mask, + uint16_t perm_mask, struct attm_elmt *elmt); + + +#if (BLE_DEBUG) + +/** + **************************************************************************************** + * @brief Retrieve number of services. + * + * @return number of services + **************************************************************************************** + */ +uint8_t attmdb_get_nb_svc(void); + +/** + **************************************************************************************** + * @brief Retrieve services informations + * + * @param[in] svc_info Services information array to update + **************************************************************************************** + */ +void attmdb_get_svc_info(struct gattm_svc_info *svc_info); +#endif /* (BLE_DEBUG) */ + +#endif // #if (BLE_ATTS) + +/// @} ATTDB +#endif // ATTM_DB_H_ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/gatt/atts/atts.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/gatt/atts/atts.h new file mode 100755 index 0000000..58560e1 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/gatt/atts/atts.h @@ -0,0 +1,157 @@ +/** + **************************************************************************************** + * + * @file atts.h + * + * @brief Header file - ATTS. + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + +#ifndef ATTS_H_ +#define ATTS_H_ + +/** + **************************************************************************************** + * @addtogroup ATTS Attribute Server + * @ingroup ATT + * @brief Attribute Protocol Server + * + * The ATTS module is responsible for handling messages intended for the attribute + * profile server. It has defined interfaces with @ref ATTM "ATTM". + * + * + * @{ + * + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_config.h" +#if (BLE_ATTS) +#include "att.h" +#include "ble_compiler.h" +#include +#include "common_list.h" +#include "gattc_task.h" +#include "l2cc.h" + +/* + * DEFINES + **************************************************************************************** + */ + + + +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ + + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + + +/** + * Confirmation of write signed (signature verified) + * + * @param[in] conidx Connection Index + * @param[in] length Signed Data Length + * @param[in] sign_data Signed Data + */ +void atts_write_signed_cfm(uint8_t conidx, uint16_t length, uint8_t* sign_data); + + +/** + **************************************************************************************** + * @brief Send an attribute error response to peer. + * + * @param[in] conidx Index of the connection with the peer device + * @param[in] opcode failing operation code + * @param[in] uuid attribute UUID + * @param[in] error error code + **************************************************************************************** + */ +void atts_send_error(uint8_t conidx, uint8_t opcode, uint16_t uuid, uint8_t error); + + +/** + **************************************************************************************** + * @brief Format the Write Response PDU and send it after receiving a Write Request PDU + * @param[in] conidx Index of the connection with the peer device + * @param[in] atthdl Attribute handle for which to send the response + * @param[in] status ATT error code + **************************************************************************************** + */ +void atts_write_rsp_send(uint8_t conidx, uint16_t atthdl, uint8_t status); + + +/** + **************************************************************************************** + * @brief Sends a value notification/indication command + * + * @param[in] conidx Connection Index + * @param[in] event Event parameters to send + * + * @return If notification can be sent or not + **************************************************************************************** + */ +uint8_t atts_send_event(uint8_t conidx, struct gattc_send_evt_cmd *event); + + +/** + * @brief Clear allocated prepare write temporary data. + * + * @param[in] conidx connection index + */ +void atts_clear_prep_data(uint8_t conidx); + + +/** + * @brief Clear allocated temporary data used for ATTS response. + * + * @param[in] conidx connection index + */ +void atts_clear_rsp_data(uint8_t conidx); + +/** + * @brief Clear temporary attribute read data present in cache. + * + * @param[in] conidx connection index + */ +void atts_clear_read_cache(uint8_t conidx); + +/** + * @brief Process execution of a received ATTS PDU. + * + * @param conidx connection index + */ +void atts_process_pdu(uint8_t conidx); + +/// @} ATTS +#endif /* (BLE_ATTS) */ + +#if (BLE_CENTRAL || BLE_PERIPHERAL) +/** + **************************************************************************************** + * @brief Handles reception of PDU Packet + * + * @param[in] conidx Index of the connection with the peer device + * @param[in] param Received PDU Packet + * + * @return If message has been proceed or consumed + **************************************************************************************** + */ +int atts_l2cc_pdu_recv_handler(uint8_t conidx, struct l2cc_pdu_recv_ind *param); +#endif /* #if (BLE_CENTRAL || BLE_PERIPHERAL) */ + +#endif // ATTS_H_ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/gatt/gatt.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/gatt/gatt.h new file mode 100755 index 0000000..e09c9ae --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/gatt/gatt.h @@ -0,0 +1,83 @@ +/** + **************************************************************************************** + * + * @file gatt.h + * + * @brief Header file - GATT. + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + +#ifndef GATT_H_ +#define GATT_H_ + +/** + **************************************************************************************** + * @addtogroup GATT Generic Attribute Profile + * @ingroup HOST + * @brief Generic Attribute Profile. + * + * The GATT module is responsible for providing an API for all attribute related operations. + * It is responsible for all the service framework activities using the Attribute protocol + * for discovering services and for reading and writing characteristic values on a peer device. + * To achieve this, the GATT interfaces with @ref ATTM "ATTM", @ref ATTC "ATTC" and the + * @ref ATTS "ATTS". + * + * @{ + **************************************************************************************** + */ +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_config.h" +#include "att.h" + + +/* + * DEFINE DECLARATIONS + **************************************************************************************** + */ + +/// retrieve gatt attribute handle from attribute index. +#define GATT_GET_ATT_HANDLE(idx)\ + ((gattm_svc_get_start_hdl() == 0)? (0) :(gattm_svc_get_start_hdl() + (idx))) + + + + +#if (BLE_ATTS) +/// GATT Attribute database handles +/// Generic Attribute Profile Service +enum gatt_db_att +{ + GATT_IDX_PRIM_SVC, + GATT_IDX_CHAR_SVC_CHANGED, + GATT_IDX_SVC_CHANGED, + GATT_IDX_SVC_CHANGED_CFG, + + GATT_IDX_NUMBER +}; +#endif /* (BLE_ATTS)*/ + +/* + * Type Definition + **************************************************************************************** + */ + + +/// Service Changed type definition +struct gatt_svc_changed +{ + /// Service start handle which changed + uint16_t start_hdl; + /// Service end handle which changed + uint16_t end_hdl; +}; + + +/// @} GATT +#endif // GATT_H_ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/gatt/gattc/gattc_int.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/gatt/gattc/gattc_int.h new file mode 100755 index 0000000..29e485f --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/gatt/gattc/gattc_int.h @@ -0,0 +1,261 @@ +/** + **************************************************************************************** + * + * @file gattc_int.h + * + * @brief Header file - GATTC_INT. + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + +#ifndef GATTC_TASK_INT_H_ +#define GATTC_TASK_INT_H_ + +/** + **************************************************************************************** + * @addtogroup GATTC_INT Internals + * @ingroup GATTC + * @brief Internal features of the GATTC module + * + * @{ + **************************************************************************************** + */ +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_config.h" + +#if (BLE_GATTC) +#include "gattc.h" +#include "gattc_task.h" +#include "kernel_task.h" + +/* + * DEFINES + **************************************************************************************** + */ +/// retrieve on-going operation command +#define GATT_OPERATION_CMD(conidx, op_type, cmd) \ + ((struct cmd*) gattc_get_operation_ptr(conidx, op_type)) + +#define GATT_WRITE_ERROR_CODE (0xFFFF) + + +/// number of GATT Controller Process +#define GATTC_IDX_MAX BLE_CONNECTION_MAX + + + +/// states of GATT Controller task +enum gattc_state_id +{ + /// Connection ready state + GATTC_READY = 0, +#if (BLE_ATTC) + /// Client operation on-going + GATTC_CLIENT_BUSY = (1 << GATTC_OP_CLIENT), + /// Service Discovery Procedure operation on-going + GATTC_SDP_BUSY = (1 << GATTC_OP_SDP), +#endif // (BLE_ATTC) +#if (BLE_ATTS) + /// Server operation on-going + GATTC_SERVER_BUSY = (1 << GATTC_OP_SERVER), + GATTC_ATTS_BUSY = (1 << GATTC_OP_MAX), +#endif // (BLE_ATTS) + /// Connection started but ATTS not ready + GATTC_CONNECTED = (1 << (GATTC_OP_MAX + 1)), + + /// Free state + GATTC_FREE = (1 << (GATTC_OP_MAX + 2)), + /// Number of defined states. + GATTC_STATE_MAX +}; + + + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + + + +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ +extern struct gattc_env_tag *gattc_env[GATTC_IDX_MAX]; + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + + +/** + **************************************************************************************** + * @brief Initialization of the GATT controller module. + * This function performs all the initialization steps of the GATT module. + * + * @param[in] reset true if it's requested by a reset; false if it's boot initialization + * + **************************************************************************************** + */ +void gattc_init(bool reset); + + +/** + **************************************************************************************** + * @brief Initialize GATT controller for connection. + * + * @param[in] conidx connection record index + * @param[in] role device role after connection establishment + * + **************************************************************************************** + */ +void gattc_create(uint8_t conidx); + + + +/** + **************************************************************************************** + * @brief Cleanup GATT controller resources for connection + * + * @param[in] conidx connection record index + * @param[in] disconnect True if disconnection occurs else request due to init or reset + * + **************************************************************************************** + */ +void gattc_cleanup(uint8_t conidx, bool disconnect); + +/** + * @brief Send a complete event of ongoing executed operation to requester. + * It also clean-up variable used for ongoing operation. + * + * @param[in] conidx Connection index + * @param[in] op_type Operation type. + * @param[in] status Status of completed operation + */ +void gattc_send_complete_evt(uint8_t conidx, uint8_t op_type, uint8_t status); + +/** + **************************************************************************************** + * @brief Send operation completed message with status error code not related to a + * running operation. + * + * @param[in] conidx Connection index + * @param[in] operation Operation code + * @param[in] seq_num Operation sequence number + * @param[in] requester requester of operation + * @param[in] status Error status code + **************************************************************************************** + */ +void gattc_send_error_evt(uint8_t conidx, uint8_t operation, uint16_t seq_num, const kernel_task_id_t requester, uint8_t status); + + +/** + **************************************************************************************** + * @brief Get operation on going + * + * @param[in] conidx Connection Index + * @param[in] op_type Operation type. + * + * @return operation code on going + **************************************************************************************** + */ +uint8_t gattc_get_operation(uint8_t conidx, uint8_t op_type); + +/** + **************************************************************************************** + * @brief Get operation pointer + * + * @param[in] conidx Connection Index + * @param[in] op_type Operation type. + * + * @return operation pointer on going + **************************************************************************************** + */ +void *gattc_get_operation_ptr(uint8_t conidx, uint8_t op_type); + + +/** + **************************************************************************************** + * @brief Set operation pointer + * + * @param[in] conidx Connection Index + * @param[in] op_type Operation type. + * @param[in] op Operation pointer. + * + **************************************************************************************** + */ +void gattc_set_operation_ptr(uint8_t conidx, uint8_t op_type, void *op); + +/** + **************************************************************************************** + * @brief Operation execution not finish, request kernel to reschedule it in order to + * continue its execution + * + * @param[in] conidx Connection Index + * @param[in] op_type Operation type. + * + * @return if operation has been rescheduled (not done if operation pointer is null) + **************************************************************************************** + */ +bool gattc_reschedule_operation(uint8_t conidx, uint8_t op_type); + +/** + **************************************************************************************** + * @brief Get requester of on going operation + * + * @param[in] conidx Connection Index + * @param[in] op_type Operation type. + * + * @return task that requests to execute the operation + **************************************************************************************** + */ +kernel_task_id_t gattc_get_requester(uint8_t conidx, uint8_t op_type); + + + +/** + **************************************************************************************** + * @brief Get Operation Sequence Number + * + * @param[in] conidx Connection Index + * @param[in] op_type Operation type. + * + * @return Sequence number provided for operation execution + **************************************************************************************** + */ +uint16_t gattc_get_op_seq_num(uint8_t conidx, uint8_t op_type); + + +/** + **************************************************************************************** + * @brief Update task state + * + * @param[in] conidx Connection index + * @param[in] state to update + * @param[in] set state to busy (true) or idle (false) + * + **************************************************************************************** + */ +void gattc_update_state(uint8_t conidx, kernel_state_t state, bool busy); + + +/* + * TASK DESCRIPTOR DECLARATIONS + **************************************************************************************** + */ +extern const struct kernel_state_handler gattc_default_handler; +extern kernel_state_t gattc_state[GATTC_IDX_MAX]; + + +#endif // (BLE_GATTC) + +/// @} GATTCTASK +#endif // GATTC_INT diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/gatt/gattm/gattm_int.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/gatt/gattm/gattm_int.h new file mode 100755 index 0000000..2a58ed4 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/gatt/gattm/gattm_int.h @@ -0,0 +1,98 @@ +/** + **************************************************************************************** + * + * @file gattm_int.h + * + * @brief Internal Header file - GATTM. + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + +#ifndef GATTM_INT_H_ +#define GATTM_INT_H_ + +/** + **************************************************************************************** + * @addtogroup GATTM_INT Task + * @ingroup GATTM + * @brief Internal function required for GATTM usage + * @{ + **************************************************************************************** + */ +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "kernel_task.h" +#include "gattm_task.h" + +#include "../attm/attm_db.h" + +/* + * DEFINES + **************************************************************************************** + */ + +/// number of GATT Process +#define GATTM_IDX_MAX 0x01 + + +/// GATT database default features +#define GATT_DB_DEFAULT_FEAT 0x0001 +/// GATT database Service changed feature +#define GATT_DB_SVC_CHG_FEAT 0x000E + + + +/// states of GATT task +enum gattm_state_id +{ + /// idle state + GATTM_IDLE, + /// busy state + GATTM_BUSY, + /// Number of defined states. + GATTM_STATE_MAX +}; + + + +/// GATT General Information Manager +struct gattm_env_tag +{ +#if (BLE_ATTS) + /// Environment data needed by attribute database + struct attm_db db; + + /// GATT service start handle + uint16_t svc_start_hdl; +#endif // (BLE_ATTS) +}; + +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ +extern struct gattm_env_tag gattm_env; + + +/* + * FUNCTIONS DECLARATIONS + **************************************************************************************** + */ + + + +/* + * TASK DESCRIPTOR DECLARATIONS + **************************************************************************************** + */ +extern const struct kernel_state_handler gattm_default_handler; +extern kernel_state_t gattm_state[GATTM_IDX_MAX]; + + +/// @} GATTM_INT +#endif // GATTM_INT_H_ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/l2c/l2cc/l2cc_int.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/l2c/l2cc/l2cc_int.h new file mode 100755 index 0000000..9dd7d1c --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/l2c/l2cc/l2cc_int.h @@ -0,0 +1,209 @@ +/** + **************************************************************************************** + * + * @file l2cc_int.h + * + * @brief Header file - L2CCTASK that contains internal API. + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + +#ifndef L2CC_INT_H_ +#define L2CC_INT_H_ + +/** + **************************************************************************************** + * @addtogroup L2CCINT Internals + * @ingroup L2CC + * @brief Internal API for L2CC module + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_config.h" +#if (BLE_L2CC) + +#include "l2cc_task.h" +#include "l2cc.h" + +/* + * MACRO DEFINITIONS + **************************************************************************************** + */ + + +/// Maximum number of instances of the L2CC task +#define L2CC_IDX_MAX (BLE_CONNECTION_MAX) + +/* + * STATES + **************************************************************************************** + */ + + + +/// states of L2CAP Controller task +enum l2cc_state_id +{ + /// Connection ready state + L2CC_READY, + /// LE signaling protocol busy + L2CC_SIG_BUSY = (1 << L2CC_OP_SIG), + /// Free state + L2CC_FREE = 0X3F, + + /// Number of defined states. + L2CC_STATE_MAX +}; + +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ + +/// L2CAP environment pool +extern struct l2cc_env_tag *l2cc_env[L2CC_IDX_MAX]; + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Create and Initialize the L2CAP controller task. + * + * @param[in] reset true if it's requested by a reset; false if it's boot initialization + * + **************************************************************************************** + */ +void l2cc_init(bool reset); + +/** +struct l2cc_pdu_recv_ind; + * + **************************************************************************************** + * @brief Initialize the link layer controller task. + * + * @param[in] conidx Connection index + * + **************************************************************************************** + */ +void l2cc_create(uint8_t conidx); + +/** + **************************************************************************************** + * @brief De-initialize the task. + * + * @param[in] conidx Connection index + * @param[in] reset true if it's requested by a reset; false if it's boot initialization + **************************************************************************************** + */ +void l2cc_cleanup(uint8_t conidx, bool reset); + +/** + **************************************************************************************** + * @brief Update task state + * + * @param[in] conidx Connection index + * @param[in] state to update + * @param[in] set state to busy (true) or idle (false) + * + **************************************************************************************** + */ +void l2cc_update_state(uint8_t conidx, kernel_state_t state, bool busy); + + +/** + * @brief Send a complete event of ongoing executed operation to requester. + * It also clean-up variable used for ongoing operation. + * + * @param[in] conidx Connection index + * @param[in] op_type Operation type. + * @param[in] status Status of completed operation + */ +void l2cc_send_complete_evt(uint8_t conidx, uint8_t op_type, uint8_t status); + +/** + **************************************************************************************** + * @brief Send operation completed message with status error code not related to a + * running operation. + * + * @param[in] conidx Connection index + * @param[in] operation Operation code + * @param[in] requester requester of operation + * @param[in] status Error status code + * @param[in] cid Channel Identifier + **************************************************************************************** + */ +void l2cc_send_error_evt(uint8_t conidx, uint8_t operation, const kernel_task_id_t requester, uint8_t status, uint16_t cid); + + +/** + **************************************************************************************** + * @brief Get operation on going + * + * @param[in] conidx Connection Index + * @param[in] op_type Operation type. + * + * @return operation code on going + **************************************************************************************** + */ +uint8_t l2cc_get_operation(uint8_t conidx, uint8_t op_type); + +/** + **************************************************************************************** + * @brief Get operation pointer + * + * @param[in] conidx Connection Index + * @param[in] op_type Operation type. + * + * @return operation pointer on going + **************************************************************************************** + */ +void *l2cc_get_operation_ptr(uint8_t conidx, uint8_t op_type); + + +/** + **************************************************************************************** + * @brief Set operation pointer + * + * @param[in] conidx Connection Index + * @param[in] op_type Operation type. + * @param[in] op Operation pointer. + * + **************************************************************************************** + */ +void l2cc_set_operation_ptr(uint8_t conidx, uint8_t op_type, void *op); + + + + +/** + **************************************************************************************** + * @brief Perform data packet TX over HCI (call of this function is handled by L2CM + * + * @param[in] conidx Connection Index + * @param[in] nb_buffer Number of available TX buffers + **************************************************************************************** + */ +void l2cc_data_send(uint8_t conidx, uint8_t nb_buffer); + + + + + + +#endif //(BLE_L2CC) + +/// @} L2CCINT + +#endif // L2CC_INT_H_ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/l2c/l2cc/l2cc_lecb.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/l2c/l2cc/l2cc_lecb.h new file mode 100755 index 0000000..7350e46 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/l2c/l2cc/l2cc_lecb.h @@ -0,0 +1,262 @@ +/** + **************************************************************************************** + * + * @file l2cc_pdu.h + * + * @brief Header file - L2CAP LE Credit Based connection management + * + * Copyright (C) RivieraWaves 2009-2016 + * + **************************************************************************************** + */ + + +#ifndef _L2CC_LECB_H_ +#define _L2CC_LECB_H_ + +/** + **************************************************************************************** + * @addtogroup L2CC_LECB L2Cap Controller LE Credit Based connection management + * @ingroup L2CC + * @brief This module is in charge of LECB connection management + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" + +#if (BLE_LECB) + +/* + * DEFINES + **************************************************************************************** + */ +/// LE Credit Based fields. +enum l2cc_lecb_fields +{ + /// LE Protocol Service Multiplexer + L2CC_LECB_LEPSM, + /// Local channel ID + L2CC_LECB_LOCAL_CID, + /// Peer channel ID + L2CC_LECB_PEER_CID, +}; + + +/// Status of the LE Credit Based connection +/// +/// 7 6 5 4 3 2 1 0 +/// +----+----+----+----+----+----+----+----+ +/// | RFU |P_I |TX_W|CON | +/// +----+----+----+----+----+----+----+----+ +/// +/// bit [2] : Local(0)/Peer (1) initiated connection +/// bit [1] : TX in Wait state (segment transmission not finished) +/// bit [0] : LECB Connected +enum l2cc_lecb_state +{ + /// Peer initiated connection + L2CC_LECB_PEER_INIT_BIT = (1 << 2), + L2CC_LECB_PEER_INIT_POS = (2), + + /// TX in Wait state (segment transmission not finished) + L2CC_LECB_TX_WAIT_BIT = (1 << 1), + L2CC_LECB_TX_WAIT_POS = (1), + + /// Channel Connected + L2CC_LECB_CONNECTED_BIT = (1 << 0), + L2CC_LECB_CONNECTED_POS = (0), +}; + + + + + +/* + * MACRO DEFINITIONS + **************************************************************************************** + */ + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + + + +/// LE credit based information for a link started or on-going. +struct l2cc_lecb_info +{ + /// Pointer to the following list + struct common_list_hdr hdr; + /// SDU waiting to be transfered (required for segmentation algorithm) + struct l2cc_lecb_sdu_send_cmd *tx_sdu; + /// SDU waiting to be received (required for reassembly algorithm) + struct l2cc_lecb_sdu_recv_ind *rx_sdu; + + /// LE Protocol/Service Multiplexer + uint16_t le_psm; + + /// Local channel ID + uint16_t local_cid; + /// Local Maximum Transmission Unit + uint16_t local_mtu; + /// Local Maximum Packet Size + uint16_t local_mps; + /// Local credit + uint16_t local_credit; + + /// Peer channel ID + uint16_t peer_cid; + /// Peer Maximum Transmission Unit + uint16_t peer_mtu; + /// Peer Maximum Packet Size + uint16_t peer_mps; + /// Peer credit + uint16_t peer_credit; + + /// Task id requested connection + kernel_task_id_t task_id; + + /// Status of the LE Credit Based connection (@see enum l2cc_lecb_state) + uint8_t state; + + /// disconnection reason + uint8_t disc_reason; + + /// Packet identifier - used for LECB negotiation + uint8_t pkt_id; +}; + + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Search LE Credit Based channel depending on the parameter + * + * @param[in] conidx Connection Index + * @param[in] field Search field (@see enum l2cc_lecb_fields) + * @param[in] value Field value to search + * + * @return Returns NULL or pointer to the LE Credit Based channel info + **************************************************************************************** + */ +struct l2cc_lecb_info *l2cc_lecb_find(uint8_t conidx, uint8_t field, uint16_t value); + +/** + **************************************************************************************** + * @brief End of LECB Connection, free information, and send disconnect indication + * + * @param[in] conidx Connection Index + * @param[in] lecb LE Credit Based Connection information + * @param[in] disconnect_ind True, sends disconnect indication + **************************************************************************************** + */ +void l2cc_lecb_free(uint8_t conidx, struct l2cc_lecb_info *lecb, bool disconnect_ind); + + +/** + **************************************************************************************** + * @brief Sends LE credit based connection request + * + * @param[in] conidx connection index + * @param[in] pkt_id Packet identifier + * @param[in] scid Source channel ID + * @param[in] credits Credits + * @param[in] mps Maximum Packet Size + * @param[in] mtu Maximum Transfer Unit + **************************************************************************************** + */ +void l2cc_lecb_send_con_req(uint8_t conidx, uint8_t pkt_id, uint16_t le_psm, uint16_t scid, uint16_t credits, + uint16_t mps, uint16_t mtu); + +/** + **************************************************************************************** + * @brief Sends LE credit based connection response + * + * @param[in] conidx connection index + * @param[in] status status of the connection + * @param[in] pkt_id Packet identifier + * @param[in] dcid Destination channel ID + * @param[in] credits Credits + * @param[in] mps Maximum Packet Size + * @param[in] mtu Maximum Transfer Unit + **************************************************************************************** + */ +void l2cc_lecb_send_con_rsp(uint8_t conidx, uint16_t status, uint8_t pkt_id, + uint16_t dcid, uint16_t credits, uint16_t mps, uint16_t mtu); + +/** + **************************************************************************************** + * @brief Sends LE credit based disconnection request + * + * @param[in] conidx connection index + * @param[in] pkt_id Packet identifier + * @param[in] dcid Destination channel ID + * @param[in] scid Source channel ID + **************************************************************************************** + */ +void l2cc_lecb_send_disc_req(uint8_t conidx, uint8_t pkt_id, uint16_t scid, uint16_t dcid); + +/** + **************************************************************************************** + * @brief Sends LE credit based disconnection response + * + * @param[in] conidx connection index + * @param[in] pkt_id Packet identifier + * @param[in] dcid Destination channel ID + * @param[in] scid Source channel ID + **************************************************************************************** + */ +void l2cc_lecb_send_disc_rsp(uint8_t conidx, uint8_t pkt_id, uint16_t dcid, uint16_t scid); +/** + **************************************************************************************** + * @brief Sends LE credit based Flow Control credit add message + * + * @param[in] conidx connection index + * @param[in] pkt_id Packet identifier + * @param[in] cid Source Channel ID + * @param[in] credits Credits + **************************************************************************************** + */ +void l2cc_lecb_send_credit_add(uint8_t conidx, uint8_t pkt_id, uint16_t cid, uint16_t credits); + + +/** + **************************************************************************************** + * @brief Due to an error on LECB link, initiate a disconnection of the channel + * + * @param[in] conidx connection index + * @param[in] lecb Information of the channel + * @param[in] disc_reason Disconnection reason + * + **************************************************************************************** + */ +void l2cc_lecb_init_disconnect(uint8_t conidx, struct l2cc_lecb_info *lecb, uint8_t disc_reason); + +/** + **************************************************************************************** + * @brief Retrieve LECB error Code from Host error code + * + * @param[in] h_err Host Error code + * + * @return LECB Error code + **************************************************************************************** + */ +uint16_t l2cc_lecb_h2l_err(uint8_t h_err); + +#endif //(BLE_LECB) + +/// @} L2CC_LECB + +#endif /* _L2CC_LECB_H_ */ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/l2c/l2cc/l2cc_pdu_int.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/l2c/l2cc/l2cc_pdu_int.h new file mode 100755 index 0000000..716918d --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/l2c/l2cc/l2cc_pdu_int.h @@ -0,0 +1,195 @@ +/** + **************************************************************************************** + * + * @file l2cc_pdu_int.h + * + * @brief Header file - L2CAP Controller PDU packer / unpacker (internal) + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + + +#ifndef _L2CC_PDU_INT_H_ +#define _L2CC_PDU_INT_H_ + +/** + **************************************************************************************** + * @addtogroup L2CC_PDU_INT L2Cap Controller (internal) + * @ingroup L2CC + * @brief This module is in charge to pack or unpack L2CAP packets + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" + +#if (BLE_L2CC) + +#include "l2cc_pdu.h" + +/* + * MACROS + **************************************************************************************** + */ + + +/* + * DEFINES + **************************************************************************************** + */ + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * Pack PDU from firmware readable data to a L2CAP packet using generic method. + * (no segmentation) + * + * @param[in] p_pdu Pointer to the unpacked PDU structure + * @param[in|out] p_offset Pointer to address where the next part of PDU will be read + * @param[in|out] p_length Pointer to the length of payload that has been packed + * @param[in|out] p_buffer Pointer to address where the next part of PDU will be written + * @param[in|out] llid LLID of the next packet to send + * + * @return GAP_ERR_NO_ERROR if packing succeed, else another error code. + **************************************************************************************** + */ +uint8_t l2cc_pdu_pack(struct l2cc_pdu *p_pdu, uint16_t *p_offset, uint16_t *p_length, uint8_t *p_buffer, uint8_t *llid); + +/** + **************************************************************************************** + * Unpack L2Cap PDU in a generic format that can be used by firmware using generic method. + * (no reassembly) + * + * @param[in] conidx Connection Index + * @param[in] p_pdu Pointer to the unpacked PDU structure + * @param[in|out] p_offset Pointer to address where the next part of PDU will be written + * @param[in|out] p_rem_len Pointer to the remaining length value of PDU to receive + * @param[in|out] p_buffer Pointer to address where the next part of PDU will be read + * @param[in] pkt_length Length of the received packet + * @param[in] pb_flag Packet Boundary flags + * + * @return GAP_ERR_NO_ERROR if packing succeed, else another error code. + **************************************************************************************** + */ +uint8_t l2cc_pdu_unpack(uint8_t conidx, struct l2cc_pdu *p_pdu, uint16_t *p_offset, uint16_t *p_rem_len, + const uint8_t *p_buffer, uint16_t pkt_length, uint8_t pb_flag); + + + +#if (BLE_DEBUG) +/** + **************************************************************************************** + * Pack DBG PDU (any kind of PDU generated by Host) from firmware readable data to a L2CAP + * packet (no segmentation) + * + * @param[in] conidx Connection Index + * @param[in] pdu Pointer to the Debug PDU to send + * @param[in|out] p_length Pointer to the length of payload that has been packed + * @param[in|out] buffer Pointer to address where the next part of PDU will be written + * @param[in|out] offset Pointer to address where the next part of PDU will be read + * @param[in|out] llid LLID of the next packet to send + * + * @return GAP_ERR_NO_ERROR if packing succeed, else another error code. + **************************************************************************************** + */ +uint8_t l2cc_dbg_pdu_pack(struct l2cc_dbg_pdu *pdu, uint16_t *length, uint8_t *buffer, uint16_t *offset, uint8_t *llid); + + +/** + **************************************************************************************** + * Unpack L2Cap PDU in a generic format that can be used by firmware for debugging + * (no reassembly) + * + * @param[in|out] sdu Pointer to the unpacked SDU structure + * @param[in] buffer Pointer to address where the next part of PDU will be read + * @param[in] length Length of the received packet + * @param[in|out] offset Pointer to address where the next part of PDU will be written + * @param[in] pb_flag Packet Boundary flags + * + * @return GAP_ERR_NO_ERROR if packing succeed, else another error code. + **************************************************************************************** + */ +uint8_t l2cc_dbg_pdu_unpack(struct l2cc_dbg_pdu *pdu, uint8_t *buffer, uint16_t length, uint16_t *offset, uint8_t pb_flag); +#endif // (BLE_DEBUG) + +#if (BLE_LECB) +/** + **************************************************************************************** + * Pack LE Credit Based channel PDU from firmware readable data to a L2CAP packet + * + * @param[in] conidx Connection Index + * @param[in] pdu Pointer to the SDU to send + * @param[out] length Pointer to the length of payload that has been packed + * @param[in|out] buffer Pointer to address where the next part of PDU will be written + * @param[in|out] offset Pointer to address where the next part of PDU will be read + * @param[in|out] pdu_len PDU length to transmitt + * @param[in] llid LLID of the next packet to send + * + * @return GAP_ERR_NO_ERROR if packing succeed, else another error code. + **************************************************************************************** + */ +uint8_t l2cc_lecb_pdu_pack(uint8_t conidx, struct l2cc_sdu *sdu, uint16_t *length, uint8_t *buffer, uint16_t *offset, + uint16_t pdu_len, uint8_t llid); + + +/** + **************************************************************************************** + * Unpack L2Cap LECB SDU in a generic format that can be used by firmware + * + * @param[in|out] sdu Pointer to the unpacked SDU structure + * @param[in] buffer Pointer to address where the next part of PDU will be read + * @param[in] length Length of the received packet + * @param[in|out] offset Pointer to address where the next part of PDU will be written + * @param[in|out] pdu_remain_len Pointer to the data length still expected on segment + * @param[in] pb_flag Packet Boundary flags + * + * @return GAP_ERR_NO_ERROR if packing succeed, else another error code. + **************************************************************************************** + */ +uint8_t l2cc_lecb_pdu_unpack(uint8_t conidx, struct l2cc_sdu *sdu, uint8_t *buffer, uint16_t length, uint16_t *offset, + uint16_t *pdu_remain_len, uint8_t pb_flag); + +#endif //(BLE_LECB) + +/** + **************************************************************************************** + * @brief New message received, initialize reception of the buffer + * - if a PDU not fully received, drop it. + * + * @param[in] conidx Connection Index + **************************************************************************************** + */ +void l2cc_pdu_rx_init(uint8_t conidx); + +/** + **************************************************************************************** + * @brief Check the PDU packet header channel ID, Length, in order to: + * - verify if no error detected + * - allocate or retrieve the RX message for expected destination task + * + * @param[in] conidx Connection Index + * @param[in|out] pp_buffer Buffer received, pointer updated according to header length + * @param[in|out] p_rx_length Received length, updated according to extracted header length + **************************************************************************************** + */ +void l2cc_pdu_header_check(uint8_t conidx, uint8_t **pp_buffer, uint16_t *p_rx_length); + + +/// @} L2CC_PDU_INT + +#endif //(BLE_L2CC) + +#endif /* _L2CC_PDU_INT_H_ */ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/l2c/l2cc/l2cc_sig.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/l2c/l2cc/l2cc_sig.h new file mode 100755 index 0000000..e16bfeb --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/l2c/l2cc/l2cc_sig.h @@ -0,0 +1,96 @@ +/** + **************************************************************************************** + * + * @file l2cc_sig.h + * + * @brief L2CAP Controller Controller Signaling PDU Handler. + * + * Copyright (C) RivieraWaves 2009-2016 + * + **************************************************************************************** + */ + +#ifndef _L2CC_SIG_H_ +#define _L2CC_SIG_H_ + + +/** + **************************************************************************************** + * @addtogroup L2CC_SIG L2CAP Controller Signaling PDU Handler. + * @ingroup L2CC + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_config.h" + +#if (BLE_L2CC) + +#include "l2cc.h" +#include "l2cc_task.h" + +/* + * DEFINES + **************************************************************************************** + */ + +/* + * MACRO DEFINITIONS + **************************************************************************************** + */ + + + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + + + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + + +/** + **************************************************************************************** + * @brief Send an L2Cap command rejected signaling packet with command not understood + * error code. + * + * @param[in] conidx Connection Index + * @param[in] pkt_id Packet identifier + * + * @param[in] reason The Reason field describes why the Request packet was rejected + * @param[in] opt1 Optional param 1 + * @param[in] opt2 Optional param 2 + **************************************************************************************** + */ +void l2cc_sig_send_cmd_reject(uint8_t conidx, uint8_t pkt_id, uint16_t reason, uint16_t opt1, uint16_t opt2); + + +/** + **************************************************************************************** + * @brief Handles reception of L2CAP signaling messages from peer device. + * + * @param[in] conidx Connection Index + * @param[in] pdu PDU Received + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +int l2cc_sig_pdu_recv_handler(uint8_t conidx, struct l2cc_pdu *pdu); + + + + +#endif // (BLE_L2CC) + +#endif // _L2CC_SIG_H_ + +/// @} L2CC_SIG diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/l2c/l2cm/l2cm_int.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/l2c/l2cm/l2cm_int.h new file mode 100755 index 0000000..4fcbae1 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/hl/src/l2c/l2cm/l2cm_int.h @@ -0,0 +1,136 @@ +/** + **************************************************************************************** + * + * @file l2cm_int.h + * + * @brief Header file - L2CM internal. + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + +#ifndef L2CM_INT_H_ +#define L2CM_INT_H_ + +/** + **************************************************************************************** + * @addtogroup L2C_INT Logical Link Control and Adaptation Protocol internals + * @ingroup HOST + * @brief Logical Link Control and Adaptation Protocol - Internal API. + * + * @{ + **************************************************************************************** + */ +#include "rwip_config.h" +#include "architect.h" + +#if (BLE_L2CM) +#include +#include +#include "ble_compiler.h" +#include "l2cm.h" + +/* + * INCLUDE FILES + **************************************************************************************** + */ + + +/* + * DEFINES + **************************************************************************************** + */ + +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ + +/// L2CAP Manager environment structure to be saved +struct l2cm_env_tag +{ +#if (BLE_L2CC) + /// bit field used to know per connection if TX activity is on-going + uint32_t con_tx_state; +#endif // (BLE_L2CC) + /// Lower Layer buffers length + uint16_t le_acl_data_pkt_len; + /// Total number of available Lower Layer buffers + uint16_t le_acl_total_nb_acl_pkt; + /// Number of available Lower Layer buffers + uint16_t nb_buffer_avail; +}; + +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ +extern struct l2cm_env_tag l2cm_env; +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Acquire low layer LE ACL packet + **************************************************************************************** + */ +__INLINE void l2cm_buffer_acquire(void) +{ + l2cm_env.nb_buffer_avail--; +} + +/** + **************************************************************************************** + * @brief Release low layer LE ACL packet + * + * @parm[in] nb Number of buffer to release. + **************************************************************************************** + */ +__INLINE void l2cm_buffer_release(uint16_t nb) +{ + // nb of buffer should not exceed le_acl_total_nb_acl_pkt + ASSERT_INFO(((l2cm_env.nb_buffer_avail + nb) <= l2cm_env.le_acl_total_nb_acl_pkt), l2cm_env.nb_buffer_avail, nb); + + l2cm_env.nb_buffer_avail += nb; + if (l2cm_env.nb_buffer_avail > BLE_TX_BUFF_DATA) + { + l2cm_env.nb_buffer_avail = BLE_TX_BUFF_DATA; + } +} + + +/** + **************************************************************************************** + * @brief Retrieve low layer LE ACL Buffers size + * + * @return size of LE ACL Buffers + **************************************************************************************** + */ +__INLINE uint16_t l2cm_get_buffer_size(void) +{ + return l2cm_env.le_acl_data_pkt_len; +} + + +/** + **************************************************************************************** + * @brief Set if TX queue for specific connection is empty or not. + * + * If not empty, it will request L2CM to start transmission of buffers + * + * @param[in] conidx Connection index + * @param[in] busy False if TX buffer queue is empty, True else + * + **************************************************************************************** + */ +void l2cm_tx_status(uint8_t conidx, bool busy); + +/// @} L2CM_INT + +#endif //(BLE_L2CM) + +#endif // L2CM_INT_H_ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/em/em_buf.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/em/em_buf.h new file mode 100755 index 0000000..a034236 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/em/em_buf.h @@ -0,0 +1,393 @@ +/** + **************************************************************************************** + * + * @file bt_em_buf.h + * + * @brief Main API file for the BT EM buffer management system + * + * Copyright (C) RivieraWaves 2009-2015 + * + **************************************************************************************** + */ + +#ifndef BT_EM_BUF_H_ +#define BT_EM_BUF_H_ + +/** + **************************************************************************************** + * @defgroup BT_EM_BUF BT EM buffer management system + * @ingroup ROOT + * @brief BT EM buffer management system + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include // standard integer +#if (BLE_EMB_PRESENT) + +#include "common_list.h" // common list definition +#include "common_bt.h" // common bt definitions +#include "common_endian.h" // endianess +#include "reg_ble_em_tx_desc.h" // EM TX_DESC BLE register +#include "ble_reg_access.h" // register access +/* + * DEFINES + **************************************************************************************** + */ + +/// ACL data: handle and data length decoding +#define BT_EM_ACL_DATA_LEN_POS (0) +#define BT_EM_ACL_DATA_LEN_MASK (0x03FF) +#define BT_EM_ACL_FLAGS_POS (12) +#define BT_EM_ACL_FLAGS_MASK (0xF000) + + +/* + * STRUCTURE DEFINITION + **************************************************************************************** + */ +struct em_buf_node +{ + struct common_list_hdr hdr; + /// Index of the buffer + uint16_t idx; + /// EM buffer pointer + uint16_t buf_ptr; +}; + +struct em_desc_node +{ + struct common_list_hdr hdr; + /// Index of the buffer + uint16_t idx; + /// EM Pointer of the buffer + uint16_t buffer_idx; + /// Buffer index + uint16_t buffer_ptr; + /// Logical Link Identifier + uint8_t llid; + /// Data length + uint8_t length; +}; + +/// Tx desc tag +struct em_buf_tx_desc +{ + /// tx pointer + uint16_t txptr; + /// tx header + uint16_t txheader; + /// tx data pointer + uint16_t txdataptr; + /// tx data length extension info + uint16_t txdle; +}; + +/// BLE EM buffer management environment structure +struct em_buf_env_tag +{ + /// List of free TX descriptors + struct common_list tx_desc_free; + /// List of free TX buffers + struct common_list tx_buff_free; + /// Array of TX descriptors (SW tag) + struct em_desc_node tx_desc_node[BLE_TX_DESC_CNT]; +#if (BLE_TX_BUFFER_CNT > 0) + /// Array of TX buffer (SW tag) + struct em_buf_node tx_buff_node[BLE_TX_BUFFER_CNT]; +#endif // (BLE_TX_BUFFER_CNT > 0) + /// Pointer to TX descriptors + struct em_buf_tx_desc *tx_desc; + /// Index of the current RX buffer + uint8_t rx_current;//for connect + + uint8_t scan_rx_current; + +}; +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ + +/// BLE EM buffer management environment +extern struct em_buf_env_tag em_buf_env; +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Initialize BT EM buffers management system + **************************************************************************************** + */ +void em_buf_init(void); + +/** + **************************************************************************************** + * @brief Freeing of a RX buffer + * + * @param hdl Handle of the RX buffer to be freed + * + **************************************************************************************** + */ +void em_buf_rx_free(uint8_t hdl); + +/** + **************************************************************************************** + * @brief Returns the pointer to the TX descriptor from the index + * + * @return The pointer to the TX descriptor corresponding to the index. + * + **************************************************************************************** + */ +__INLINE struct em_buf_tx_desc *em_buf_tx_desc_addr_get(uint16_t idx) +{ + // Pop a descriptor from the TX free list + return (&em_buf_env.tx_desc[idx]); +} + +/** + **************************************************************************************** + * @brief Returns the pointer to the TX node from the index + * + * @return The pointer to the TX node corresponding to the index. + * + **************************************************************************************** + */ +__INLINE struct em_desc_node *em_buf_tx_desc_node_get(uint16_t idx) +{ + // Pop a descriptor from the TX free list + return (&em_buf_env.tx_desc_node[idx]); +} + +/** + **************************************************************************************** + * @brief Get the handle of the next RX buffer in the list + * + **************************************************************************************** + */ +__INLINE uint8_t em_buf_rx_current_get(void) +{ + return (em_buf_env.rx_current); +} + +/** + **************************************************************************************** + * @brief Set the current RX buffer + * + * @param hdl Handle of the current RX buffer + * + **************************************************************************************** + */ +__INLINE void em_buf_rx_current_set(uint8_t hdl) +{ + em_buf_env.rx_current = hdl; +} + +/** + **************************************************************************************** + * @brief Get the handle of the next RX buffer in the list + * + * @param hdl Handle of the current RX buffer + * + **************************************************************************************** + */ +__INLINE uint8_t em_buf_rx_next(uint8_t hdl) +{ + return ((hdl + 1) % BLE_RX_BUFFER_CNT); +} + +/** + **************************************************************************************** + * @brief Allocation of a TX data descriptor + * + * @return The pointer to the TX descriptor corresponding to the allocated buffer, NULL if + * no buffers are available anymore. + * + **************************************************************************************** + */ +__INLINE struct em_desc_node *em_buf_tx_desc_alloc(void) +{ + return ((struct em_desc_node *)common_list_pop_front(&em_buf_env.tx_desc_free)); +} +/** + **************************************************************************************** + * @brief Allocation of a TX data descriptor and a TX data buffer + * + * @return The pointer to the TX descriptor corresponding to handle + * + **************************************************************************************** + */ +__INLINE struct em_buf_node *em_buf_tx_alloc(void) +{ + struct em_buf_node *node = NULL; + GLOBAL_INT_DIS(); + // Get free element from free list + node = (struct em_buf_node *) common_list_pop_front(&em_buf_env.tx_buff_free); + GLOBAL_INT_RES(); + return node; +} + +/** + **************************************************************************************** + * @brief Returns the pointer to the TX descriptor from the index + * + * @return The pointer to the TX descriptor corresponding to the index. + * + **************************************************************************************** + */ +__INLINE struct em_buf_tx_desc *em_buf_tx_desc_get(uint16_t idx) +{ + // Pop a descriptor from the TX free list + return (&em_buf_env.tx_desc[idx]); +} +/** + **************************************************************************************** + * @brief Freeing of a TX descriptor + * + * @param desc The pointer to the TX descriptor to be freed + * + **************************************************************************************** + */ +__INLINE void em_buf_tx_desc_free(struct em_desc_node *desc) +{ + //Clear Descriptor fields + ble_txphce_set(desc->idx, 0); + ble_txdle_set(desc->idx, 0); + ble_txdataptr_set(desc->idx, 0); + // Push back the descriptor in the TX free list + common_list_push_back(&em_buf_env.tx_desc_free, &desc->hdr); +} + +#if (BLE_TX_BUFFER_CNT > 0) +/** + **************************************************************************************** + * @brief Freeing of a TX buffer + * + * @param desc The pointer to the TX descriptor to be freed + * + **************************************************************************************** + */ +__INLINE void em_buf_tx_buff_free(int idx) +{ + struct em_buf_node *buff_node = &em_buf_env.tx_buff_node[idx]; + // Push back the buffer in the TX free list + common_list_push_back(&em_buf_env.tx_buff_free, &buff_node->hdr); +} +#endif // (BLE_TX_BUFFER_CNT > 0) + +/** + **************************************************************************************** + * @brief Returns the pointer to the TX node from the index + * + * @return The pointer to the TX node corresponding to the index. + * + **************************************************************************************** + */ +__INLINE struct em_desc_node *em_buf_node_get(uint16_t idx) +{ + // Pop a descriptor from the TX free list + return (&em_buf_env.tx_desc_node[idx]); +} +/** + **************************************************************************************** + * @brief Return a pointer to a RX Buffer + * + * @return The pointer to the RX buffer corresponding to handle. + * + **************************************************************************************** + */ +uint8_t *em_buf_rx_buff_addr_get(uint16_t rx_hdl); + +/** + **************************************************************************************** + * @brief Return a pointer to a TX Buffer + * + * @return The pointer to the TX buffer corresponding to handle. + * + **************************************************************************************** + */ +uint8_t *em_buf_tx_buff_addr_get(struct em_buf_tx_desc *tx_desc); + + + +/** + **************************************************************************************** + * @brief Freeing of TX data descriptor and buffer if needed + * + * @param desc The pointer to the TX descriptor to be freed + * +* @return if the buffer linked to the descriptor has been flushed + * + **************************************************************************************** + */ +bool em_buf_tx_free(struct em_desc_node *desc_to_be_freed); + +/** + **************************************************************************************** + * @brief Read a 8bits value in EM + * + * @param[in] em_addr Exchange memory address + * + * @return 8bits value + * + **************************************************************************************** + */ +__INLINE uint16_t em_read_8(uint16_t em_addr) +{ + uint8_t res; + /// opcode + em_rd(&res, em_addr, 1); + + return res; +} + + +/** + **************************************************************************************** + * @brief Read a 16bits value in EM + * + * @param[in] em_addr Exchange memory address + * + * @return 16bits value + * + **************************************************************************************** + */ +__INLINE uint16_t em_read_16(uint16_t em_addr) +{ + uint16_t res; + /// opcode + em_rd(&res, em_addr, 2); + + return common_btohs(res); +} + +/** + **************************************************************************************** + * @brief Read a 32bits value in EM + * + * @param[in] em_addr Exchange memory address + * + * @return 32bits value + * + **************************************************************************************** + */ +__INLINE uint32_t em_read_32(uint16_t em_addr) +{ + uint32_t res; + /// opcode + em_rd(&res, em_addr, 4); + + return common_btohl(res); +} + +#endif //BLE_EMB_PRESENT +/// @} EM_BUF + +#endif // EM_BUF_H_ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/em/em_map_ble.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/em/em_map_ble.h new file mode 100755 index 0000000..f362366 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/em/em_map_ble.h @@ -0,0 +1,137 @@ +/** + **************************************************************************************** + * + * @file em_map_ble.h + * + * @brief Mapping of the different descriptors in the exchange memory + * + * Copyright (C) RivieraWaves 2009-2015 + * + **************************************************************************************** + */ + +#ifndef EM_MAP_BLE_H_ +#define EM_MAP_BLE_H_ + +/** + **************************************************************************************** + * @addtogroup EM EM + * @ingroup CONTROLLER + * @brief Mapping of the different descriptors in the exchange memory + * + * @{ + **************************************************************************************** + */ +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_config.h" // stack configuration + +#include +#include +#include +#include "common_bt.h" +#include "_reg_ble_em_tx_desc.h" +#include "_reg_ble_em_tx_buffer_data.h" +#include "_reg_ble_em_tx_buffer_cntl.h" +#include "_reg_ble_em_rx_desc.h" +#include "_reg_ble_em_rx_buffer.h" +#include "_reg_ble_em_wpb.h" +#include "_reg_ble_em_wpv.h" +#include "_reg_ble_em_ral.h" +#include "_reg_ble_em_cs.h" + +#if (BLE_AUDIO) +#include "_reg_ble_em_tx_audio_buffer.h" +#include "_reg_ble_em_rx_audio_buffer.h" +#endif // (BLE_AUDIO) + + +/* + * DEFINES + **************************************************************************************** + */ + + + +/// Size of the encryption area +#define EM_BLE_ENC_LEN 16 + +/// number of control structure entries for the exchange memory +#define EM_BLE_CS_COUNT (BLE_CONNECTION_MAX + 1) + +/// number of tx buffer entries for the exchange memory +#define EM_BLE_TX_BUFF_CNTL_COUNT (BLE_TX_BUFF_CNTL) + +/// number of tx buffer entries for the exchange memory +#define EM_BLE_TX_BUFF_ADV_COUNT (BLE_TX_BUFF_ADV) + +/// number of tx buffer entries for the exchange memory +#define EM_BLE_TX_BUFF_DATA_COUNT (BLE_TX_BUFF_DATA) + + +/// number of tx descriptor entries for the exchange table +#define EM_BLE_TX_DESC_COUNT (BLE_TX_DESC_CNT) + +/// number of tx buffer entries for the exchange memory +#define EM_BLE_TX_BUFFER_COUNT (BLE_TX_BUFFER_CNT) + +/// number of rx descriptor entries for the exchange memory +#define EM_BLE_RX_DESC_COUNT (BLE_RX_DESC_CNT) + +/// number of rx buffer entries for the exchange memory +#define EM_BLE_RX_BUFFER_COUNT (BLE_RX_BUFFER_CNT) + +#if (BLE_AUDIO) +/// number of tx audio buffer entries for the exchange memory +#define EM_BLE_TX_AUDIO_BUFF_DATA_COUNT (BLE_TX_AUDIO_BUFFER_CNT) + +/// number of rx audio buffer entries for the exchange memory +#define EM_BLE_RX_AUDIO_BUFF_DATA_COUNT (BLE_RX_AUDIO_BUFFER_CNT) +#endif // (BLE_AUDIO) + +/* + * Mapping of the different elements in EM + **************************************************************************************** + */ + +#define EM_BLE_ET_OFFSET (EM_ET_OFFSET) + +/// Offset of the plain data area (used for SW initiated encryption) +#define EM_BLE_ENC_PLAIN_OFFSET (EM_BLE_OFFSET) +/// Offset of the ciphered data area (used for SW initiated encryption) +#define EM_BLE_ENC_CIPHER_OFFSET (EM_BLE_ENC_PLAIN_OFFSET + EM_BLE_ENC_LEN * sizeof(uint8_t)) +/// Offset of the control structure area +#define EM_BLE_CS_OFFSET (EM_BLE_ENC_CIPHER_OFFSET + EM_BLE_ENC_LEN * sizeof(uint8_t)) +/// Offset of the public white list area +#define EM_BLE_WPB_OFFSET (EM_BLE_CS_OFFSET + EM_BLE_CS_COUNT * REG_BLE_EM_CS_SIZE) +/// Offset of the private white list area +#define EM_BLE_WPV_OFFSET (EM_BLE_WPB_OFFSET + BLE_WHITELIST_MAX * REG_BLE_EM_WPB_SIZE) +/// Offset of the private white list area +#define EM_BLE_RAL_OFFSET (EM_BLE_WPV_OFFSET + BLE_WHITELIST_MAX * REG_BLE_EM_WPV_SIZE) +/// Offset of the TX descriptor area +#define EM_BLE_TX_DESC_OFFSET (EM_BLE_RAL_OFFSET + BLE_RESOL_ADDR_LIST_MAX * REG_BLE_EM_RAL_SIZE) +/// Offset of the RX descriptor area +#define EM_BLE_RX_DESC_OFFSET (EM_BLE_TX_DESC_OFFSET + EM_BLE_TX_DESC_COUNT * REG_BLE_EM_TX_DESC_SIZE) +/// Offset of the TX buffer area +#define EM_BLE_TX_BUFFER_CNTL_OFFSET (EM_BLE_RX_DESC_OFFSET + EM_BLE_RX_DESC_COUNT * REG_BLE_EM_RX_DESC_SIZE) +/// Offset of the TX buffer area +#define EM_BLE_TX_BUFFER_DATA_OFFSET (EM_BLE_TX_BUFFER_CNTL_OFFSET + (EM_BLE_TX_BUFF_CNTL_COUNT + EM_BLE_TX_BUFF_ADV_COUNT) * REG_BLE_EM_TX_BUFFER_CNTL_SIZE) +/// Offset of the RX buffer area +#define EM_BLE_RX_BUFFER_OFFSET (EM_BLE_TX_BUFFER_DATA_OFFSET + EM_BLE_TX_BUFF_DATA_COUNT * REG_BLE_EM_TX_BUFFER_DATA_SIZE) +#if (BLE_AUDIO) +/// Offset of the TX Audio buffer area +#define EM_BLE_TX_AUDIO_BUFFER_OFFSET (EM_BLE_RX_BUFFER_OFFSET + EM_BLE_RX_BUFFER_COUNT * REG_BLE_EM_RX_BUFFER_SIZE) +/// Offset of the RX Audio buffer area +#define EM_BLE_RX_AUDIO_BUFFER_OFFSET (EM_BLE_TX_AUDIO_BUFFER_OFFSET + EM_BLE_TX_AUDIO_BUFF_DATA_COUNT * REG_BLE_EM_TX_AUDIO_BUFFER_SIZE) +/// End of BLE EM +#define EM_BLE_END (EM_BLE_RX_AUDIO_BUFFER_OFFSET + EM_BLE_RX_AUDIO_BUFF_DATA_COUNT * REG_BLE_EM_RX_AUDIO_BUFFER_SIZE) +#else // !(BLE_AUDIO) +/// End of BLE EM +#define EM_BLE_END (EM_BLE_RX_BUFFER_OFFSET + EM_BLE_RX_BUFFER_COUNT * REG_BLE_EM_RX_BUFFER_SIZE) +#endif // (BLE_AUDIO) + +/// @} LLDEXMEM + +#endif // EM_MAP_BLE_H_ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/llc/llc_ch_asses.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/llc/llc_ch_asses.h new file mode 100755 index 0000000..0e9ae30 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/llc/llc_ch_asses.h @@ -0,0 +1,158 @@ +/** + **************************************************************************************** + * + * @file llc_ch_asses.h + * + * @brief Declaration of functions used for channel assessment + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef LLC_CH_ASSES_H_ +#define LLC_CH_ASSES_H_ + +/** + **************************************************************************************** + * @addtogroup LLCCHASSES + * @ingroup LLC + * @brief Channel assessment functions + * + * This module implements the primitives used for channel assessment + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#if (BLE_CHNL_ASSESS) + +#include +#include +#include "rwip_config.h" +#include "common_bt.h" + + + +/* + * MACROS + **************************************************************************************** + */ + +/* + * DEFINES + **************************************************************************************** + */ + + + +/* + * ENUMERATIONS + **************************************************************************************** + */ + +enum lld_ch_asses_ponderation +{ + // Noiser + LLD_CH_ASSES_SYNC_ERR_HIGH_RSSI = -3, + // Packet error + LLD_CH_ASSES_CRC_ERR = -3, + // Sync missed + LLD_CH_ASSES_SYNC_ERR_LOW_RSSI_NO_LATENCY = -1, + // Latency + LLD_CH_ASSES_SYNC_ERR_LOW_RSSI_LATENCY = 0, + // Packet ok + LLD_CH_ASSES_SYNC_FOUND_NO_CRC_ERR = 3 +}; + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + + +/// Structure describing the channel assessment environment +struct llc_ch_asses_tag +{ + /// Standard deviation + int8_t rcvd_quality[LE_DATA_FREQ_LEN]; + /// Latency enable + bool latency_en; + /// Re-assessment counter (nb of assessment timer expiration) + uint8_t reassess_count; + /// cursor to last channel re-assess + uint8_t reassess_cursor; +}; + +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ + + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Get the informations on the received packet (error, RSSI) to take the decision + * to remove or not the channel + * + * @param[in] handle Connection handle of the current link to be analyzed + * @param[in] status rx status information from rx descriptor + * @param[in] rssi rssi value of received pdu + * @param[in] channel channel number of RX packet + * + **************************************************************************************** + */ +void llc_ch_assess_local(uint16_t conhdl, uint16_t status, int8_t rssi, uint8_t channel); + +/** + **************************************************************************************** + * @brief Get the local channel map + * + * @param[in] conhdl Connection handle of the current link + * @param[in] map pointer to local channel map + * @param[in] hostmap pointer to channel map configured by host + * + * @return number of good channels + **************************************************************************************** + */ +uint8_t llc_ch_assess_get_local_ch_map(uint16_t conhdl, struct le_chnl_map *map, struct le_chnl_map *hostmap); + +/** + **************************************************************************************** + * @brief Get the current channel map + * + * @param[in] conhdl Connection handle of the current link + * + * @param[out] le_chnl_map Current channel map + * + **************************************************************************************** + */ +struct le_chnl_map *llc_ch_assess_get_current_ch_map(uint16_t conhdl); + +/** + **************************************************************************************** + * @brief Re-enable 25% of new channel (if possible) and at least ensure that 2 channels are available + * + * @param[in] conhdl Connection handle of the current link + * @param[in] map pointer to local channel map + * @param[in] hostmap pointer to channel map configured by host + * @param[in] nb_chgood Current number of good channels + * + **************************************************************************************** + */ +void llc_ch_assess_reass_ch(uint16_t conhdl, struct le_chnl_map *map, struct le_chnl_map *hostmap, uint8_t nb_chgood); +#endif//#if (BLE_CHNL_ASSESS) + +/// @} LLCCHASSES + +#endif // LLC_CH_ASSES_H_ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/llc/llc_llcp.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/llc/llc_llcp.h new file mode 100755 index 0000000..949ab6b --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/llc/llc_llcp.h @@ -0,0 +1,426 @@ +/** + **************************************************************************************** + * + * @file llc_llcp.h + * + * @brief Functions for control pdu transmission/reception handling + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef LLC_CNTL_H_ +#define LLC_CNTL_H_ + +/** + **************************************************************************************** + * @addtogroup LLCLLCP LLCLLCP + * @ingroup LLC + * @brief Functions for control pdu transmission/reception handling + * + * This module implements the functions allowing the handling of the transmission and + * reception of the control pdu. + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "common_llcp.h" +#include "kernel_msg.h" +#include "llc_task.h" + +#if (BLE_PERIPHERAL || BLE_CENTRAL) +/// Maximum size of LMP unpacked parameters +#define LLCP_MAX_UNPACKED_SIZE (LLCP_PDU_LENGTH_MAX + BLE_MIC_LEN) + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + +/// LLCP pdu element structure +struct llcp_pdu_tag +{ + /// List element for chaining + struct common_list_hdr hdr; + /// Node index + uint16_t idx; + /// Pointer on the pdu to send + void *ptr; +#if (BLE_TESTER) + uint16_t pdu_length; +#endif // BLE_TESTER + + /// opcode + uint8_t opcode; +}; + + +/// Status to check if a llcp can be sent or not during start en pause encryption +enum llc_llcp_authorize +{ + LLC_LLCP_NO_AUTHZED = 0x00, + LLC_LLCP_START_ENC_AUTHZED = 0x01, + LLC_LLCP_PAUSE_ENC_AUTHZED = 0x02, +}; + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Sends the (extended) reject indication pdu. + * + * This function allocates an sets header and parameters of the pdu before pushing it in + * the tx queue. + * + * @param[in] conhdl Connection handle on which the PDU will be sent. + * @param[in] reason The reason to be put in the Reject Indication PDU + **************************************************************************************** + */ +void llc_llcp_reject_ind_pdu_send(uint16_t conhdl, uint8_t rej_opcode, uint8_t reason); + +/** + **************************************************************************************** + * @brief Sends the read remote information version pdu. + * + * This function allocates an sets header and parameters of the pdu before pushing it in + * the tx queue. + * + * @param[in] conhdl Connection handle on which the PDU will be sent. + **************************************************************************************** + */ +void llc_llcp_version_ind_pdu_send(uint16_t conhdl); + +/** + **************************************************************************************** + * @brief Sends the set host channel classification pdu. + * + * This function allocates an sets header and parameters of the pdu before pushing it in + * the tx queue. + * + * @param[in] conhdl Connection handle on which the pdu will be sent. + **************************************************************************************** + */ +void llc_llcp_ch_map_update_pdu_send(uint16_t conhdl); + +/** + **************************************************************************************** + * @brief Sends the pause encryption request pdu. + * + * This function allocates an sets header and parameters of the pdu before pushing it in + * the tx queue. + * + * @param[in] conhdl Connection handle on which the pdu will be sent. + **************************************************************************************** + */ +void llc_llcp_pause_enc_req_pdu_send(uint16_t conhdl); + +/** + **************************************************************************************** + * @brief Sends the pause encryption response pdu. + * + * This function allocates an sets header and parameters of the pdu before pushing it in + * the tx queue. + * + * @param[in] conhdl Connection handle on which the pdu will be sent. + **************************************************************************************** + */ +void llc_llcp_pause_enc_rsp_pdu_send(uint16_t conhdl); + +/** + **************************************************************************************** + * @brief Sends the encryption request pdu. + * + * This function allocates an sets header and parameters of the pdu before pushing it in + * the tx queue. + * + * @param[in] conhdl Connection handle on which the pdu will be sent. + * @param[in] param The parameters to be put in the encryption request + **************************************************************************************** + */ +void llc_llcp_enc_req_pdu_send(uint16_t conhdl, struct hci_le_start_enc_cmd *param); + +/** + **************************************************************************************** + * @brief Sends the encryption response pdu. + * + * This function allocates an sets header and parameters of the pdu before pushing it in + * the tx queue. + * + * @param[in] conhdl Connection handle on which the pdu will be sent. + **************************************************************************************** + */ +void llc_llcp_enc_rsp_pdu_send(uint16_t conhdl, struct llcp_enc_req *param); + +/** + **************************************************************************************** + * @brief Sends the start encryption response pdu. + * + * This function allocates an sets header and parameters of the pdu before pushing it in + * the tx queue. + * + * @param[in] conhdl Connection handle on which the pdu will be sent. + **************************************************************************************** + */ +void llc_llcp_start_enc_rsp_pdu_send(uint16_t conhdl); + +/** + **************************************************************************************** + * @brief Sends the connection update request pdu. + * + * This function allocates an sets header and parameters of the pdu before pushing it in + * the tx queue. + * + * @param[in] conhdl Connection handle on which the pdu will be sent. + * @param[in] param Pointer on the structure which contains all the updated + * parameters useful for the link. + **************************************************************************************** + */ +void llc_llcp_con_update_pdu_send(uint16_t conhdl, struct llcp_con_upd_ind *param); + +/** + **************************************************************************************** + * @brief Sends the connection parameters request pdu. + * + * This function allocates an sets header and parameters of the pdu before pushing it in + * the tx queue. + * + * @param[in] conhdl Connection handle on which the pdu will be sent. + * @param[in] param Pointer on the structure which contains all the updated + * parameters useful for the link. + **************************************************************************************** + */ +void llc_llcp_con_param_req_pdu_send(uint16_t conhdl, struct llc_con_upd_req_ind *param); + +/** + **************************************************************************************** + * @brief Sends the connection parameters response pdu. + * + * This function allocates an sets header and parameters of the pdu before pushing it in + * the tx queue. + * + * @param[in] conhdl Connection handle on which the pdu will be sent. + * @param[in] param Pointer on the structure which contains all the updated + * parameters useful for the link. + **************************************************************************************** + */ +void llc_llcp_con_param_rsp_pdu_send(uint16_t conhdl, struct llc_con_upd_req_ind *param); + +/** + **************************************************************************************** + * @brief Sends the features request pdu. + * + * This function allocates an sets header and parameters of the pdu before pushing it in + * the tx queue. + * + * @param[in] conhdl Connection handle on which the pdu will be sent. + **************************************************************************************** + */ +void llc_llcp_feats_req_pdu_send(uint16_t conhdl); + +/** + **************************************************************************************** + * @brief Sends the features response pdu. + * + * This function allocates an sets header and parameters of the pdu before pushing it in + * the tx queue. + * + * @param[in] conhdl Connection handle on which the pdu will be sent. + **************************************************************************************** + */ +void llc_llcp_feats_rsp_pdu_send(uint16_t conhdl); + +/** + **************************************************************************************** + * @brief Sends the start encryption request pdu. + * + * This function allocates an sets header and parameters of the pdu before pushing it in + * the tx queue. + * + * @param[in] conhdl Connection handle on which the pdu will be sent. + **************************************************************************************** + */ +void llc_llcp_start_enc_req_pdu_send(uint16_t conhdl); + +/** + **************************************************************************************** + * @brief Sends the terminate indication pdu. + * + * This function allocates an sets header and parameters of the pdu before pushing it in + * the tx queue. + * + * @param[in] conhdl Connection handle on which the pdu will be sent. + * @param[in] err_code Reason of the termination. + **************************************************************************************** + */ +void llc_llcp_terminate_ind_pdu_send(uint16_t conhdl, uint8_t err_code); +/** + **************************************************************************************** + * @brief Sends the unknown response pdu. + * + * This function allocates an sets header and parameters of the pdu before pushing it in + * the tx queue. + * + * @param[in] conhdl Connection handle on which the pdu will be sent. + * @param[in] unk_type Opcode of the unknown pdu type . + **************************************************************************************** + */ +void llc_llcp_unknown_rsp_send_pdu(uint16_t conhdl, uint8_t unk_type); + +#if !(BLE_QUALIF) +/** + **************************************************************************************** + * @brief Sends the ping request pdu. + * + * This function allocates an sets header and parameters of the pdu before pushing it in + * the tx queue. + * + * @param[in] conhdl Connection handle on which the pdu will be sent. + **************************************************************************************** + */ +void llc_llcp_ping_req_pdu_send(uint16_t conhdl); +/** + **************************************************************************************** + * @brief Sends the ping response pdu. + * + * This function allocates an sets header and parameters of the pdu before pushing it in + * the tx queue. + * + * @param[in] conhdl Connection handle on which the pdu will be sent. + **************************************************************************************** + */ +void llc_llcp_ping_rsp_pdu_send(uint16_t conhdl); +/** + **************************************************************************************** + * @brief Sends the length request pdu. + * + * This function allocates an sets header and parameters of the pdu before pushing it in + * the tx queue. + * + * @param[in] conhdl Connection handle on which the pdu will be sent. + **************************************************************************************** + */ +void llc_llcp_length_req_pdu_send(uint16_t conhdl); + +/** + **************************************************************************************** + * @brief Sends the length response pdu. + * + * This function allocates an sets header and parameters of the pdu before pushing it in + * the tx queue. + * + * @param[in] conhdl Connection handle on which the pdu will be sent. + **************************************************************************************** + */ +void llc_llcp_length_rsp_pdu_send(uint16_t conhdl); + + +/** + ****************************************************************************************** + * @brief GENERAL COMMENT FOR llcp_..._pdu_unpk : LMP PDU param extraction function + * + * @param[in] pdu Pointer to PDU buffer, without the 1 or two opcode bytes. + * @param[in] parlen Length of left over pdu params. + * @param[in] param Pointer to kernel message param position for direct copy of pdu params + * + ****************************************************************************************** + */ +#endif + +#if (BLE_TESTER) +/** + **************************************************************************************** + * @brief Sends through tester the LLCP PDU on the given connection handle. + * + * @param[in] conhdl The connection handle on which the LLCP has to be transmitted + * @param[in] length The length of the LLCP packet (required to build the header) + * @param[in] dara The LLCP PDU Data + * + **************************************************************************************** + */ +void llc_llcp_tester_send(uint8_t conhdl, uint8_t length, uint8_t *data); +#endif // (BLE_TESTER) + +#if (BLE_2MBPS) +/** + **************************************************************************************** + * @brief Sends the PHY request pdu. + * + * This function allocates an sets header and parameters of the pdu before pushing it in + * the tx queue. + * + * @param[in] conhdl Connection handle on which the pdu will be sent. + * @param[in] param RX and TX phys requested + **************************************************************************************** + */ +void llc_llcp_phy_req_pdu_send(uint16_t conhdl, struct llcp_phy_req *param); + +/** + **************************************************************************************** + * @brief Sends the PHY response pdu. + * + * This function allocates an sets header and parameters of the pdu before pushing it in + * the tx queue. + * + * @param[in] conhdl Connection handle on which the pdu will be sent. + * @param[in] param RX and TX phys response + **************************************************************************************** + */ +void llc_llcp_phy_rsp_pdu_send(uint16_t conhdl, struct llcp_phy_rsp *param); + +/** + **************************************************************************************** + * @brief Sends the PHY update request pdu. + * + * This function allocates an sets header and parameters of the pdu before pushing it in + * the tx queue. + * + * @param[in] conhdl Connection handle on which the pdu will be sent. + * @param[in] param RX and TX phys chosen and the instant + **************************************************************************************** + */ +void llc_llcp_phy_upd_ind_pdu_send(uint16_t conhdl, struct llcp_phy_upd_req *param); + +#endif // (BLE_2MBPS) + +/** + **************************************************************************************** + * @brief Default handler for LLCP packet received. + * + * @param[in] dest_id ID of the receiving task instance. + * @param[in] status status of the PDU rx unpack. + * @param[in] pdu Pointer to the received PDU. + * @param[in] int_ctx True if executing within interrupt context, False else + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +int llc_llcp_recv_handler(kernel_task_id_t dest_id, uint8_t status, union llcp_pdu *pdu, bool int_ctx); + +/** + **************************************************************************************** + * @brief Get the authorization value for a dedicated LLCP + * + * @param[in] opcode Opcode of the LLCP to be checked + * + * @return Authorization value see enum llc_llcp_authorize + **************************************************************************************** + */ +uint8_t llc_llcp_get_autorize(uint8_t opcode); + +#endif // #if (BLE_PERIPHERAL || BLE_CENTRAL) + + + +/// @} LLCLLCP + +#endif // LLC_CNTL_H_ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/llc/llc_task.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/llc/llc_task.h new file mode 100755 index 0000000..3fb89a3 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/llc/llc_task.h @@ -0,0 +1,503 @@ +/** + **************************************************************************************** + * + * @file llc_task.h + * + * @brief LLM task header file + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef LLC_TASK_H_ +#define LLC_TASK_H_ + +/** + **************************************************************************************** + * @addtogroup LLCTASK LLCTASK + * @ingroup LLC + * @brief Link Layer Controller Task + * + * The LLC task is responsible for managing link layer actions related to a + * specific connection with a peer (e.g. Encryption setup, Supervision timeout, etc.). It + * implements the state machine related to these actions. + * + * @{ + **************************************************************************************** + */ + + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include +#include "common_bt.h" +#include "common_llcp.h" +#include "rwip_task.h" // Task definitions + +#if (BLE_PERIPHERAL || BLE_CENTRAL) +/* + * INSTANCES + **************************************************************************************** + */ +/// Maximum number of instances of the LLC task +#define LLC_IDX_MAX BLE_CONNECTION_MAX + +/* + * STATES + **************************************************************************************** + */ + + +/// Operation type +enum llc_op_type +{ + /// Parameters update operation (initiated by local device) + LLC_OP_LOC_PARAM_UPD = 0x00, + /// Parameters update operation (initiated by peer device) + LLC_OP_REM_PARAM_UPD = 0x01, + /// Encryption operation + LLC_OP_ENCRYPT = 0x02, + /// Data length update operation + LLC_OP_DLE_UPD = 0x03, +#if (BLE_2MBPS) + /// Phys update operation (initiated by local device) + LLC_OP_LOC_PHY_UPD = 0x04, +#endif + /// Max number of operations + LLC_OP_MAX +}; + +/// procedure bit fields +enum llc_proc_field +{ + /// Local procedure on-going bit field + LLC_LOC_PROC = 0, + + /// Remote procedure on-going bit field + LLC_REM_PROC, + /// Traffic is currently paused bit field + LLC_TRAFFIC_PAUSED, + /// Disconnection on-going bit field + LLC_DISC, +}; + + +/// Possible states of the LLC task +enum llc_state_id +{ + /// Connection ready state + LLC_CONNECTED = 0x00, + /// Local procedure on-going + LLC_LOC_PROC_BUSY = (1 << LLC_LOC_PROC), + /// Remote procedure on-going + LLC_REM_PROC_BUSY = (1 << LLC_REM_PROC), + /// Traffic is currently paused + LLC_TRAFFIC_PAUSED_BUSY = (1 << LLC_TRAFFIC_PAUSED), + /// Disconnection procedure on-going + LLC_DISC_BUSY = ((1 << (LLC_DISC + 1)) - 1), + /// Disconnected state, connection handle ready to be used + LLC_FREE = 0X7F, + /// Number of defined states. + LLC_STATE_MAX, +}; + +/// Local procedure state +enum llc_loc_proc_state +{ + /// No on-going local procedure + LLC_LOC_IDLE, + /// wait for remote feature response + LLC_LOC_WAIT_FEAT_RSP, + /// Wait for peer version indication (when we initiated the procedure) + LLC_LOC_WAIT_VERS_IND, + /// Wait for acknowledgment of terminate indication + LLC_LOC_WAIT_TERM_ACK, + /// Wait for the peer response to length request + LLC_LOC_WAIT_LENGTH_RSP, + /// wait for LE Ping response + LLC_LOC_WAIT_PING_RSP, + + /* **** Channel Map Update procedure **** */ + /// Wait for Channel map update instant (Master only) + LLC_LOC_WAIT_MAP_UPD_INSTANT, + + /* **** Connection Update procedure **** */ + /// Wait for connection response packet + LLC_LOC_WAIT_CON_PARAM_RSP, + /// Wait for connection update PDU + LLC_LOC_WAIT_CON_UPD_REQ, + /// Wait for connection update instant (Master only) + LLC_LOC_WAIT_CON_UPD_INSTANT, + + /* **** Encryption procedure **** */ + /// Wait for traffic to be paused before starting any encryption procedure + LLC_LOC_WAIT_TRAFFIC_PAUSED, + /// Encryption pause procedure is ongoing + LLC_LOC_WAIT_PAUSE_ENC_RSP, + /// Wait for pause response to be sent + LLC_LOC_WAIT_PAUSE_ENC_RSP_SENT, + + /// Wait for encryption response + LLC_LOC_WAIT_ENC_RSP, + /// Wait for Session Key generated by HW AES engine or start encryption request + LLC_LOC_WAIT_SK_AND_START_ENC_REQ, + /// Wait for Session Key generated by HW AES engine + LLC_LOC_WAIT_SK, + /// Wait for start encryption request + LLC_LOC_WAIT_START_ENC_REQ, + /// ready to send start encryption response + LLC_LOC_SEND_START_ENC_RSP, + /// wait for start encryption response from slave + LLC_LOC_WAIT_START_ENC_RSP, + /// Wait random number generation used by SKD and IV in LL_ENC_REQ + LLC_LOC_WAIT_RANDN_GEN_IND, + +#if(BLE_2MBPS) + /* **** phys Update procedure **** */ + /// Wait for phys response packet + LLC_LOC_WAIT_PHY_RSP, + /// Wait for phys update PDU + LLC_LOC_WAIT_PHY_UPD_REQ, + /// Wait for phys update instant + LLC_LOC_WAIT_PHY_UPD_INSTANT, + /// No wait nothing change + LLC_LOC_PHY_NO_INSTANT, +#endif +}; + +/// remote procedure state +enum llc_rem_proc_state +{ + /// No on-going remote procedure + LLC_REM_IDLE, + + /* **** Channel Map Update procedure **** */ + /// Wait for Channel map update instant (Slave only) + LLC_REM_WAIT_MAP_UPD_INSTANT, + + /* **** Connection Update procedure **** */ + /// Wait for the host response to parameter request + LLC_REM_WAIT_CON_PARAM_HOST_RSP, + /// Wait for connection updae LLCP from master (Slave only) + LLC_REM_WAIT_CON_UPD_REQ, + /// Wait for connection update instant (Slave only) + LLC_REM_WAIT_CON_UPD_INSTANT, + + /* **** Encryption procedure **** */ + /// Wait for traffic to be paused to handle Pause encryption request + LLC_REM_WAIT_TP_FOR_PAUSE_ENC_REQ, + /// Wait for pause encryption response to be received + LLC_REM_WAIT_PAUSE_ENC_RSP, + /// Wait for encryption request to be received + LLC_REM_WAIT_ENC_REQ, + + /// Wait for traffic to be paused to handle encryption request + LLC_REM_WAIT_TP_FOR_ENC_REQ, + /// Wait for LTK from host + LLC_REM_WAIT_LTK, + /// Wait for Session Key generated by HW AES engine + LLC_REM_WAIT_SK, + /// Wait for start encryption response + LLC_REM_WAIT_START_ENC_RSP, + /// Wait for TX Ack Response + LLC_REM_WAIT_START_ENC_RSP_ACK, + /// Wait for Encryption reject Ack Response + LLC_REM_WAIT_ENC_REJECT_ACK, + /// Wait random number generation used by SKD and IV in LL_ENC_REQ + LLC_REM_WAIT_RANDN_GEN_IND, + +#if(BLE_2MBPS) + /* **** phys Update procedure **** */ + /// Wait for phys update PDU + LLC_REM_WAIT_PHY_UPD_REQ, + /// Wait for phys update instant + LLC_REM_WAIT_PHY_UPD_INSTANT, + /// No wait nothing change + LLC_REM_PHY_NO_INSTANT, +#endif +}; + + +/* + * MESSAGES + **************************************************************************************** + */ +/// Message API of the LLC task +enum LLC_MSG +{ + /* + * ************** Msg HCI->LLC**************** + */ + ///Data packet from driver + LLC_DATA_IND = TASK_FIRST_MSG(TASK_ID_LLC), + + /* + * ************** Msg LLC->LLC**************** + */ + /* ************** Timeout ******************** */ + /// Link supervision timeout detected + LLC_LE_LINK_SUP_TO, + /// LLCP response timeout detected + LLC_LLCP_RSP_TO, + /// Authenticated payload 'nearly' time out + LLC_AUTH_PAYL_NEARLY_TO, + /// Authenticated payload 'real' time out. + LLC_AUTH_PAYL_REAL_TO, + /// Channel assessment decision timer expiration + LLC_CHNL_ASSESS_TO, + + /* ************** procedure execution ******** */ + /// + LLC_ENC_MGT_IND, + /// Update link packet size procedure + LLC_LENGTH_REQ_IND, + /// Update channel map procedure + LLC_CHMAP_UPDATE_REQ_IND, + + /// Start a connection update procedure + LLC_CON_UPD_REQ_IND, +#if (BLE_2MBPS) + /// Start a connection update procedure + LLC_PHY_UPD_REQ_IND, +#endif //(BLE_2MBPS) + /* + * ************** LLCP messages ************** + */ + /// Handles Reception of an LLCP message + LLC_LLCP_RECV_IND, +}; + +/* + * ************** Local Defines**************** + */ +/// type of tx power level +enum +{ + TX_LVL_CURRENT, + TX_LVL_MAX, + TX_LVL_LEN +}; + +/// different control state for the LLC +enum +{ + LLC_CNTL_STATE_IDLE, + LLC_ENC_PAUSE_RESUME, + LLC_ENC_START, + LLC_UPDATE_CNX, + LLC_CNTL_STATE_LEN + +}; +/* + * ************** API low energy **************** + */ + + +/// llc le create connection request parameters structure description. +struct llc_create_con_req +{ + ///Connection handle + uint16_t conhdl; + ///Scan interval + uint16_t scan_intv; + ///Scan window size + uint16_t scan_window; + ///Initiator filter policy + uint8_t init_filt_policy; + ///Peer address type - 0=public/1=random + uint8_t peer_addr_type; + ///Peer BD address + struct bd_addr peer_addr; + ///Own address type - 0=public/1=random + uint8_t own_addr_type; + ///Minimum of connection interval + uint16_t con_intv_min; + ///Maximum of connection interval + uint16_t con_intv_max; + ///Connection latency + uint16_t con_latency; + ///Link supervision timeout + uint16_t superv_to; + ///Minimum CE length + uint16_t ce_len_min; + ///Maximum CE length + uint16_t ce_len_max; +}; + +/// llc le create connection confirmation parameters structure description. +struct llc_create_con_cfm +{ + /// status + uint8_t status; + /// connection handle + uint16_t conhdl; +}; + +/// llc le create connection indication and cfm structure description. +struct llc_create_con_req_ind +{ + /// connection interval + uint16_t con_int; + /// connection latency + uint16_t con_lat; + /// supervision time out + uint16_t sup_to; + /// Pointer to element into the resolving list + uint16_t ral_ptr; + /// peer bd address + struct bd_addr peer_addr; + /// peer bd address type + uint8_t peer_addr_type; + /// Local bd address + struct bd_addr loc_addr; + /// Local bd address type + uint8_t loc_addr_type; + /// hopping + uint8_t hop_inc; + /// sleep accuracy + uint8_t sleep_clk_acc; + /// filter_policy + uint8_t filter_policy; +}; + +/// llc data rx packet structure +struct llc_data_ind +{ + /// connection handle + uint16_t conhdl; + /// broadcast and packet boundary flag + uint8_t pb_bc_flag; + /// length of the data + uint16_t length; + /// Handle of the descriptor containing RX Data + uint8_t rx_hdl; +}; + + +///llc read rssi command parameters structure +struct llc_unknown_rsp_send +{ + /// Unknown opcode + uint8_t opcode; +}; + +/// Handles Reception of an LLCP message +struct llc_llcp_recv_ind +{ + /// status of LLCP unpacking + uint8_t status; + /// dummy byte for internal use + uint8_t dummy; + + /// PDU data packet + union llcp_pdu pdu; +}; + +/// connection update operation +enum llc_con_up_op +{ + /// Connection update requested by HCI + LLC_CON_UP_HCI_REQ, + /// Move the device anchor point + LLC_CON_UP_MOVE_ANCHOR, + /// force sending connection update request + LLC_CON_UP_FORCE, + + /// Update connection parameter according to peer request + LLC_CON_UP_PEER_REQ, + /// Update connection parameter according to local request + LLC_CON_UP_LOC_REQ, +}; + + +/// Start a connection update procedure +struct llc_con_upd_req_ind +{ + /// requested operation + uint8_t operation; + + /// minimum value of connInterval + uint16_t con_intv_min; + /// maximum value of connInterval + uint16_t con_intv_max; + + ///Connection latency + uint16_t con_latency; + ///Link supervision timeout + uint16_t superv_to; + + ///Minimum of CE length + uint16_t ce_len_min; + ///Maximum of CE length + uint16_t ce_len_max; + + + /// minimum value of connInterval -> update request + uint16_t interval_min; + /// maximum value of connInterval -> update request + uint16_t interval_max; + + /// preferred periodicity + uint8_t pref_period; + /// ReferenceConnEventCount + uint16_t ref_con_event_count; + /// Offset0 + uint16_t offset0; + /// Offset1 + uint16_t offset1; + /// Offset2 + uint16_t offset2; + /// Offset3 + uint16_t offset3; + /// Offset4 + uint16_t offset4; + /// Offset5 + uint16_t offset5; +}; + +#if (BLE_2MBPS) +/// Phys update request indication structure definition +struct llc_phy_upd_req_ind +{ + /// requested operation + uint8_t operation; + ///Phys selection + uint8_t all_phys; + ///Tx phy rate + uint8_t tx_phys; + ///Rx phy rate + uint8_t rx_phys; + ///Status of the end of the procedure + uint8_t status; +}; + +/// Phys update operation +enum llc_phy_up_op +{ + /// Phys update requested by HCI + LLC_PHY_UPD_HCI_REQ, + /// Update Phys parameter according to peer request + LLC_PHY_UPD_PEER_REQ, + /// Update Phys parameter according to peer response + LLC_PHY_UPD_PEER_RSP, + /// The procedure is finished due to a reason + LLC_PHY_UPD_TERMINATE, +}; +#endif // (BLE_2MBPS) + + +/* + * TASK DESCRIPTOR DECLARATIONS + **************************************************************************************** + */ +extern const struct kernel_state_handler llc_default_handler; +extern kernel_state_t llc_state[LLC_IDX_MAX]; + +#endif // #if (BLE_PERIPHERAL || BLE_CENTRAL) +/// @} LLCTASK + +#endif // LLC_TASK_H_ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/llc/llc_util.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/llc/llc_util.h new file mode 100755 index 0000000..dabec99 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/llc/llc_util.h @@ -0,0 +1,509 @@ +/** + **************************************************************************************** + * + * @file llc_util.h + * + * @brief Link layer controller utilities definitions + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ +#ifndef LLC_UTIL_H_ +#define LLC_UTIL_H_ +/** + **************************************************************************************** + * @addtogroup LLCUTIL + * @ingroup LLC + * @brief Link layer controller utilities definitions + * + * full description + * + * @{ + **************************************************************************************** + */ + + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include + +#include "ble_compiler.h" +#include "em_buf.h" +#include "llc_task.h" +#include "reg_ble_em_rx_desc.h" +#include "reg_ble_em_cs.h" +#include "llcontrl.h" +#if (BLE_PERIPHERAL || BLE_CENTRAL) + +/* + * MARCROS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Get PDU Encryption state value + * + * @param[in] conhdl handle of the link where the flow should be get + * + * @return Encryption state + * + **************************************************************************************** + */ +#define LLC_UTIL_ENC_STATE_GET(conhdl)\ + (llc_env[(conhdl)]->encryption_state) + +/** + **************************************************************************************** + * @brief Check if the Encryption state value is set + * + * @param[in] conhdl handle of the link where the flow should be on/off + * @param[in] field State field + * + * @return True if state is enabled ; False else + **************************************************************************************** + */ +#define LLC_UTIL_ENC_STATE_IS_SET(conhdl, field) \ + (((llc_env[(conhdl)]->encryption_state) & (field)) == (field)) + +/** + **************************************************************************************** + * @brief Set the Encryption state value + * + * @param[in] conhdl handle of the link where the flow should be on/off + * @param[in] value value of the encryption state + * + **************************************************************************************** + */ +#define LLC_UTIL_ENC_STATE_SET(conhdl, value)\ + (llc_env[(conhdl)]->encryption_state = (value)) + +/** + **************************************************************************************** + * @brief Update the Encryption state value + * + * @param[in] conhdl handle of the link where the flow should be on/off + * @param[in] field Field value to update + * @param[in] enable Enable or not the state field + * + **************************************************************************************** + */ +#define LLC_UTIL_ENC_STATE_UP(conhdl, field, enable) \ + llc_env[(conhdl)]->encryption_state = (enable)\ + ? ((llc_env[(conhdl)]->encryption_state) | (field)) \ + : ((llc_env[(conhdl)]->encryption_state) & ~(field)) + + + +/* + * DEFINES + **************************************************************************************** + */ + +// Encryption state +enum llc_util_enc_state +{ + /// Encryption is disabled + LLC_ENC_DISABLED = 0x00, + + /// Encryption enabled in TX + LLC_ENC_TX = 0x01, + /// Encryption enabled in RX + LLC_ENC_RX = 0x02, + /// Encryption enabled for TX and RX + LLC_ENC_ENABLE = 0x03, + + ///TX flow is now allowed + LLC_ENC_TX_FLOW_OFF = 0x04, + ///RX flow is now allowed + LLC_ENC_RX_FLOW_OFF = 0x08, + /// Both TX and RX Flow are off + LLC_ENC_FLOW_OFF = 0x0C, + + /// Encryption key refresh procedure is pending + LLC_ENC_REFRESH_PENDING = 0x10, + /// Encryption pause procedure is pending + LLC_ENC_PAUSE_PENDING = 0x20, +}; + + +/* + * FUNCTION DEFINITIONS + **************************************************************************************** + */ +/** + **************************************************************************************** + * @brief Gets a free connection handle. + * + * This function allocates a new connection handle if possible. + * + * @param[in/out] conhdl Pointer on the connection handle allocated. + * + * @return If the connection handle has been correctly allocated. + * + **************************************************************************************** + */ +uint8_t llc_util_get_free_conhdl(uint16_t *conhdl); + + +/** + **************************************************************************************** + * @brief Process the disconnection + * + * This function request to the Link Layer to stop sending any further packets, frees the + * LLC conhdl and LLC task associated, notifies the host of the loss of connection. + * + * @param[in] conhdl Connection handle disconnected. + * @param[in] reason reason of the disconnection. + * + **************************************************************************************** + */ +void llc_util_dicon_procedure(uint16_t conhdl, uint8_t reason); + +/** + **************************************************************************************** + * @brief Checks the number of active(s) link(s). + * + * This function returns the number of active(s) link(s). + * + * @return The number of active(s) link(s). + * + **************************************************************************************** + */ +__INLINE uint8_t llc_util_get_active_conhdl(void) +{ + uint8_t idx; + uint8_t cpt_active = 0; + kernel_task_id_t llc_free; + for (idx = 0; idx < BLE_CONNECTION_MAX; idx++) + { + // build a task ID dedicated to the conhdl + llc_free = KERNEL_BUILD_ID(TASK_LLC, idx); + // gets the state + if (kernel_state_get(llc_free) != LLC_FREE) + { + cpt_active++; + } + } + return cpt_active; +} + +/** + **************************************************************************************** + * @brief Checks if the meta event is enabled. + * + * This function checks if the meta event is authorized to be sent to the host. + * + * @param[in] meta_event Event to be checked. + * + * @return The is the event is authorized. + * + **************************************************************************************** + */ +__INLINE bool llc_util_event_enabled(uint8_t meta_event) +{ + uint8_t idx; + uint8_t cpt_active = 0; + kernel_task_id_t llc_free; + for (idx = 0; idx < BLE_CONNECTION_MAX; idx++) + { + // build a task ID dedicated to the conhdl + llc_free = KERNEL_BUILD_ID(TASK_LLC, idx); + // gets the state + if (kernel_state_get(llc_free) != LLC_FREE) + { + cpt_active++; + } + } + return cpt_active; +} + +/** + **************************************************************************************** + * @brief Gets the L2CAP length. + * + * This function gets in the data buffer the L2CAP length. + * + * @param[in] data Pointer on the data buffer . + * + * @return The L2CAP data length. + * + **************************************************************************************** + */ +__INLINE uint16_t llc_util_rxl2clen_getf(uint8_t *data) +{ + uint16_t localVal = *data++ & 0x00FF; //gets the lsb first + localVal |= (uint16_t) (*data << 8) & 0xFF00; + return (localVal); +} + +/** + **************************************************************************************** + * @brief Set the IVm in the control structure + * + * @param[in] conhdl Handle of the connection for which the IVm is set + * @param[in] ivm Pointer to the IVm to set for this connection + * + **************************************************************************************** + */ +__INLINE void llc_util_ivm_set(uint16_t conhdl, uint8_t const *ivm) +{ + for (int i = 0; i < 2; i++) + { + // Sets the lower part of the IV with the IVm + ble_iv_setf(conhdl, i, common_read16p(&ivm[2 * i])); + } +} + +/** + **************************************************************************************** + * @brief Set the IVs in the control structure + * + * @param[in] conhdl Handle of the connection for which the IVs is set + * @param[in] ivs Pointer to the IVs to set for this connection + * + **************************************************************************************** + */ +__INLINE void llc_util_ivs_set(uint16_t conhdl, uint8_t const *ivs) +{ + for (int i = 0; i < 2; i++) + { + // Sets the upper part of the IV with the IVs + ble_iv_setf(conhdl, i + 2, common_read16p(&ivs[2 * i])); + } +} + +/** + **************************************************************************************** + * @brief Update the channel map of a specific link + * + * @param[in] conhdl Handle of the connection for which the IVs is set + * @param[in] map Pointer to the channel map + **************************************************************************************** + */ +void llc_util_update_channel_map(uint16_t conhdl, struct le_chnl_map *map); + +/** + **************************************************************************************** + * @brief Enable/disable LLCP discard + * + * @param[in] conhdl Connection handle + **************************************************************************************** + */ +void llc_util_set_llcp_discard_enable(uint16_t conhdl, bool enable); + +/** + **************************************************************************************** + * @brief Calculates and sets an appropriate margin for the authenticated payload timeout + * + * @param[in] conhdl Handle of the connection for which the IVs is set + * @param[in] enable True/false + **************************************************************************************** + */ +void llc_util_set_auth_payl_to_margin(struct lld_evt_tag *evt); + +/** + **************************************************************************************** + * @brief Check disc command param + * + * @param[in] reason Reason for disconnection + * + * @return reason accepted or rejected + **************************************************************************************** + */ +__INLINE bool llc_util_disc_reason_ok(uint8_t reason) +{ + // disconnection reason range + uint8_t valid_r[7] = + { + COMMON_ERROR_AUTH_FAILURE, + COMMON_ERROR_REMOTE_USER_TERM_CON, + COMMON_ERROR_REMOTE_DEV_TERM_LOW_RESOURCES, + COMMON_ERROR_REMOTE_DEV_POWER_OFF, + COMMON_ERROR_UNSUPPORTED_REMOTE_FEATURE, + COMMON_ERROR_PAIRING_WITH_UNIT_KEY_NOT_SUP, + COMMON_ERROR_UNACCEPTABLE_CONN_INT + }; + + for (uint8_t i = 0; i < 7; i++) + if (reason == valid_r[i]) + { + return (true); + } + + return (false); +} + +/** + **************************************************************************************** + * @brief Set operation pointer + * + * @param[in] conhdl Connection handle. + * @param[in] op_type Operation type. + * @param[in] op Operation pointer. + * + **************************************************************************************** + */ +__INLINE void llc_util_set_operation_ptr(uint16_t conhdl, uint8_t op_type, void *op) +{ + ASSERT_ERR(op_type < LLC_OP_MAX); + struct llc_env_tag *llc_env_ptr = llc_env[conhdl]; + // update operation pointer + llc_env_ptr->operation[op_type] = op; +} + +/** + **************************************************************************************** + * @brief Get operation pointer + * + * @param[in] conhdl Connection handle. + * @param[in] op_type Operation type. + * + * @return operation pointer on going + **************************************************************************************** + */ +__INLINE void *llc_util_get_operation_ptr(uint16_t conhdl, uint8_t op_type) +{ + ASSERT_ERR(op_type < LLC_OP_MAX); + struct llc_env_tag *llc_env_ptr = llc_env[conhdl]; + // return operation pointer + return llc_env_ptr->operation[op_type]; +} +/** + **************************************************************************************** + * @brief Get element pointer + * + * @param[in] conhdl Connection handle. + * + * @return element pointer on going + **************************************************************************************** + */ +__INLINE struct ea_elt_tag *llc_util_get_element_ptr(uint16_t conhdl) +{ + ASSERT_ERR(conhdl <= BLE_CONNECTION_MAX); + // return element pointer + return ((void *)(llc_env[conhdl]->elt)); +} +/** + **************************************************************************************** + * @brief Clear operation and allocated area + * + * @param[in] conhdl Connection handle. + * @param[in] op_type Operation type. + * + **************************************************************************************** + */ +void llc_util_clear_operation_ptr(uint16_t conhdl, uint8_t op_type); + +/** + **************************************************************************************** + * @brief Check if the bandwidth after data length extension procedure has changed + * + * @param[in] conhdl Connection handle. + * + **************************************************************************************** + */ +void llc_util_bw_mgt(uint16_t conhdl); + + +/** + **************************************************************************************** + * @brief Check if procedure state is on-going + * + * @param state Current task state + * @param procedure Procedure to check + * + * @return true if procedure is on-going, false else + **************************************************************************************** + */ +__INLINE bool llc_state_chk(kernel_state_t state, uint8_t procedure) +{ + return (((state) & (procedure)) == (procedure)); +} + +/** + **************************************************************************************** + * @brief Update task state according to on-going procedure + * + * @param[in] task Task where state has to be updated + * @param[in|out] state task state + * @param[in] procedure Procedure bit to update + * @param[in] enable Enable or disable procedure + **************************************************************************************** + */ +__INLINE void llc_state_update(kernel_task_id_t task, kernel_state_t *state, uint8_t procedure, bool enable) +{ + *state = enable ? ((*state) | (procedure)) : ((*state) & ~(procedure)); + + kernel_state_set(task, *state); +} + + +/** + **************************************************************************************** + * @brief Handling defer of End of event + * + * @param[in] conhdl Connection handle + **************************************************************************************** + */ +void llc_end_evt_defer(uint16_t conhdl); + +/** + **************************************************************************************** + * @brief Handling defer of TX ACL acknowledgment + * + * @param[in] conhdl Connection handle + * @param[in] tx_cnt Number of packet acknowledged + * + **************************************************************************************** + */ +void llc_pdu_acl_tx_ack_defer(uint16_t conhdl, uint8_t tx_cnt); + +/** + **************************************************************************************** + * @brief Handling defer of TX LLCP acknowledgment + * + * @param[in] conhdl Connection handle + * @param[in] opcode LLCP Operation code + * + **************************************************************************************** + */ +void llc_pdu_llcp_tx_ack_defer(uint16_t conhdl, uint8_t opcode); + + +/** + **************************************************************************************** + * @brief Handling of pdu information in a deferred event + * + * @param[in] conhdl Connection handle + * @param[in] status RX status + * @param[in] rssi RX detected RSSI raw value + * @param[in] channel Channel of packet received + * @param[in] length Length of packet received + **************************************************************************************** + */ +void llc_pdu_defer(uint16_t conhdl, uint16_t status, uint8_t rssi, uint8_t channel, uint8_t length); + +/** + **************************************************************************************** + * @brief Handling of starting the TX encryption and resetting the CCM counter + * + * @param[in] conhdl Connection handle + **************************************************************************************** + */ +void llc_start_enc_tx(uint16_t conhdl); +/** + **************************************************************************************** + * @brief Handling of starting the RX encryption and resetting the CCM counter + * + * @param[in] conhdl Connection handle + **************************************************************************************** + */ +void llc_start_enc_rx(uint16_t conhdl); +#endif // #if (BLE_PERIPHERAL || BLE_CENTRAL) +/// @} LLCUTIL +#endif // LLC_UTIL_H_ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/llc/llcontrl.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/llc/llcontrl.h new file mode 100755 index 0000000..0548da3 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/llc/llcontrl.h @@ -0,0 +1,600 @@ +/** + **************************************************************************************** + * + * @file llcontrl.h + * + * @brief Main API file for the Link Layer controller + * + * Copyright (C) RivieraWaves 2009-2015 + * + **************************************************************************************** + */ + +#ifndef LLCONTRL_H_ +#define LLCONTRL_H_ + +/** + **************************************************************************************** + * @addtogroup LLC LLC + * @ingroup CONTROLLER + * @brief Link Layer Controller + * + * Declaration of the functions used by the logical link controller + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "common_bt.h" +#include "common_llcp.h" +#include "common_error.h" +#include "llc_llcp.h" +#include "llc_task.h" +#include "llm.h" +#include "lld_evt.h" +#include "kernel_task.h" +#if (BLE_CHNL_ASSESS) +#include "llc_ch_asses.h" +#endif //(BLE_CHNL_ASSESS) +#if (BLE_PERIPHERAL || BLE_CENTRAL) + +/* + * DEFINES + **************************************************************************************** + */ + +/* + * MACROS + **************************************************************************************** + */ + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ +/// LLC Flags (Status) +/// [15-14] 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +/// +.....+-------+------+------+------+------+------+------+------+------+------+------+------+------+------+ +/// | RFU |PAR_REQ|PHY EN|IN_PRO|LLCP_E|DISC_R|S_FND | U_EVT| U_HST| U_PE | TO_PE|LLCP_D|W_T_PA| P_VER| F_EXC| +/// +.....+-------+------+------+------+------+------+------+------+------+------+------+------+------+------+ +enum llc_status_flag +{ + /// - [15]: Flag to indicate to start RX encryption + LLC_STAT_ENC_RX_REQUEST_MASK = 0x8000, + LLC_STAT_ENC_RX_REQUEST_LSB = 15, + + /// - [14]: Flag to indicate to start TX encryption + LLC_STAT_ENC_TX_REQUEST_MASK = 0x4000, + LLC_STAT_ENC_TX_REQUEST_LSB = 14, + + /// - [13]: Parameter request not supported + LLC_STAT_PARAM_UPD_NOT_SUP_MASK = 0x2000, + LLC_STAT_PARAM_UPD_NOT_SUP_LSB = 13, + +#if (BLE_2MBPS) + /// - [12]: Flag to indicate if the phy upd procedure is enabled + LLC_STAT_PHY_ENABLED_MASK = 0x1000, + LLC_STAT_PHY_ENABLED_LSB = 12, +#endif // (BLE_2MBPS) + /// - [11]: Instant finished and proceed + LLC_STAT_INSTANT_PROCEED_MASK = 0x800, + LLC_STAT_INSTANT_PROCEED_LSB = 11, + + /// - [10]: LLCP PDU Instant process in defer context + LLC_STAT_LLCP_INSTANT_EXTRACTED_MASK = 0x400, + LLC_STAT_LLCP_INSTANT_EXTRACTED_LSB = 10, + + /// - [9]: Flag indicating if disconnection is requested by remote device + LLC_STAT_DISC_REM_REQ_MASK = 0x200, + LLC_STAT_DISC_REM_REQ_LSB = 9, + + /// - [8]: Flag indicating if synchronization found + LLC_STAT_SYNC_FOUND_MASK = 0x100, + LLC_STAT_SYNC_FOUND_LSB = 8, + + /// - [7]: Flag indicating if connection update event should be sent + LLC_STAT_UPDATE_EVT_SENT_MASK = 0x80, + LLC_STAT_UPDATE_EVT_SENT_LSB = 7, + + /// - [6]: Flag indicating if connection update requested by host + LLC_STAT_UPDATE_HOST_REQ_MASK = 0x40, + LLC_STAT_UPDATE_HOST_REQ_LSB = 6, + + /// - [5]: Flag indicating if connection update ongoing flag + LLC_STAT_UPDATE_PENDING_MASK = 0x20, + LLC_STAT_UPDATE_PENDING_LSB = 5, + + /// - [4]: Flag indicating if connection TO is pending + LLC_STAT_TO_PENDING_MASK = 0x10, + LLC_STAT_TO_PENDING_LSB = 4, + + /// - [3]: Flag indicating if LLC messages received have to be discarded + LLC_STAT_LLCP_DISCARD_MASK = 0x08, + LLC_STAT_LLCP_DISCARD_LSB = 3, + + /// - [2]: Flag indicating if traffic has to be paused + LLC_STAT_WAIT_TRAFFIC_PAUSED_MASK = 0x04, + LLC_STAT_WAIT_TRAFFIC_PAUSED_LSB = 2, + + /// - [1]: Flag indicating if the peer version is already known + LLC_STAT_PEER_VERS_KNOWN_MASK = 0x02, + LLC_STAT_PEER_VERS_KNOWN_LSB = 1, + + /// - [0]: Flag indicating whether features have been exchanged or not + LLC_STAT_FEAT_EXCH_MASK = 0x01, + LLC_STAT_FEAT_EXCH_LSB = 0 +}; + + +/// Data Length Extension info +/// 7 6 5 4 3 2 1 0 +/// +--+--+--+--+--+--+---+---+ +/// | RFU |EVT|REQ| +/// +--+--+--+--+--+--+---+---+ +enum llc_dle_flag +{ + /// - [7:2]: RFU + + /// - [1]: SE Private Address Renewal timer started + LLC_DLE_EVT_SENT_MASK = 0x02, + LLC_DLE_EVT_SENT_LSB = 1, + + /// - [0]: RCVD/non RCVD LL_LENGTH_REQ + LLC_DLE_REQ_RCVD_MASK = 0x01, + LLC_DLE_REQ_RCVD_LSB = 0 +}; + + +#if (BLE_TESTER) +/// Tester flags +enum llc_tester_flag +{ + /// Ignore LLCP Feature request + LLC_TESTER_IGNORE_FEAT_REQ = 0x01, + /// Force connection update parameters + LLC_TESTER_FORCE_UP_PARAM = 0x02, + /// Surcharge LLCP connection parameter request + LLC_TESTER_SURCHARGE_PARAM_REQ = 0x04, +}; +#endif // (BLE_TESTER) + + + + + +/// Remote version information structure +struct rem_version +{ + /// LMP version + uint8_t vers; + /// Manufacturer ID + uint16_t compid; + /// LMP subversion + uint16_t subvers; +}; + +/// Encryption structure +struct encrypt +{ + /// Session key diversifier + struct sess_k_div skd; + /// Long term key + struct ltk ltk; + /// Random value + uint8_t randn[KEY_LEN]; +}; + +/// Data Length Extension structure +struct data_len_ext_tag +{ + ///the maximum number of octets that the local device will send to the remote device + uint16_t conn_max_tx_octets; + ///the maximum number of octets that the local device is able to receive from the remote device + uint16_t conn_max_rx_octets; + + ///the lesser of conn_max_tx_octets and conn_rem_max_rx_octets + uint16_t conn_eff_max_tx_octets; + ///the lesser of conn_max_rx_octets and conn_rem_max_tx_octets + uint16_t conn_eff_max_rx_octets; + + ///the maximum number of microsecond that the local device will take to transmit to the remote + uint16_t conn_max_tx_time; + ///the maximum number of microsecond that the local device can take to receive from the remote device + uint16_t conn_max_rx_time; + + ///the lesser of conn_max_tx_time and conn_rem_max_rx_time + uint16_t conn_eff_max_tx_time; + ///the lesser of conn_max_rx_time and conn_rem_max_tx_time + uint16_t conn_eff_max_rx_time; + + ///Flag to check if the request is allowed or not TRUE = not allowed + bool send_req_not_allowed; + + ///Flag to check if the request has been already done and the event sent + uint8_t data_len_ext_flag; +}; + + +/// LLC environment structure +struct llc_env_tag +{ + /// Request operation Kernel message + void *operation[LLC_OP_MAX]; + /// Pointer to the associated @ref LLD event + struct ea_elt_tag *elt; +#if (BLE_CHNL_ASSESS) + /// Channel Assessment structure environment + struct llc_ch_asses_tag chnl_assess; +#endif //(BLE_CHNL_ASSESS) + /// Peer version obtained using the LL_VERSION_IND LLCP message + struct rem_version peer_version; + /// Length extension + struct data_len_ext_tag data_len_ext_info; + /// Link supervision time out + uint16_t sup_to; + /// New link supervision time out to be applied + uint16_t n_sup_to; + /// Authenticated payload time out (expressed in units of 10 ms) + uint16_t auth_payl_to; + /// Authenticated payload time out margin (expressed in units of 10 ms) + uint16_t auth_payl_to_margin; + /// LLC status + uint16_t llc_status; + ///Current channel map + struct le_chnl_map ch_map; + ///New channel map - Will be applied at instant when a channel map update is pending + struct le_chnl_map n_ch_map; + /// Received signal strength indication + int8_t rssi; + /// Features used by the stack + struct le_features feats_used; + /// Structure dedicated for the encryption + struct encrypt encrypt; + /// Disconnection reason + uint8_t disc_reason; + /// Disconnection event sent + bool disc_event_sent; + /// Local procedure state + uint8_t loc_proc_state; + /// Remote procedure state + uint8_t rem_proc_state; + /// encryption state + uint8_t encryption_state; + +#if (BLE_TESTER) + struct hci_tester_set_le_params_cmd tester_params; + /// Use to know if LLCP pass through mechanism is enabled or not + bool llcp_pass_through_enable; +#endif +}; + +/* + * DEFINES + **************************************************************************************** + */ +/// Default values +#define LLC_DFT_INTERV 3200 +#define LLC_DFT_LATENCY 500 +#define LLC_DFT_SUP_TO 3200 +#define LLC_DFT_RSP_TO 4000 +#define LLC_DFT_AUTH_PAYL_TO 3000 // expressed in units of 10 ms, so 30 seconds +#define LLC_DFT_CE_LEN 65535 +#define LLC_DFT_WIN_OFF 0 +#define LLC_DFT_WIN_SIZE 8 +#define LLC_DFT_HOP_INC 1 +#define LLC_DFT_INST_MAP_UPD 6 + +/// Connection interval min (N*1.250ms) +#define LLC_CNX_INTERVAL_MIN 6 //(0x06) +/// Connection interval Max (N*1.250ms) +#define LLC_CNX_INTERVAL_MAX 3200 //(0xC80) +/// Connection latency min (N*cnx evt) +#define LLC_CNX_LATENCY_MIN 0 //(0x00) +/// Connection latency Max (N*cnx evt) +// "The connSlaveLatency parameter shall be less than 500" LL:4.5.1 +#define LLC_CNX_LATENCY_MAX 499 //(0x1F3) +/// Supervision TO min (N*10ms) +#define LLC_CNX_SUP_TO_MIN 10 //(0x0A) +/// Supervision TO Max (N*10ms) +#define LLC_CNX_SUP_TO_MAX 3200 //(0xC80) +/// Connection event length min (N*0.625ms) +#define LLC_CNX_CE_LGTH_MIN 0 //(0x00) +/// Connection event length Max (N*0.625ms) +#define LLC_CNX_CE_LGTH_MAX 65535 //(0xFFFF) + +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ +extern struct llc_env_tag *llc_env[BLE_CONNECTION_MAX]; + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ +/** + **************************************************************************************** + * @brief Initialization of the BLE LLC task + * + * This function initializes the LLC task, as well as assessment statistics + * + **************************************************************************************** + */ +void llc_init(void); + +/** + **************************************************************************************** + * @brief Reset of the BLE LLC task + * + * This function reset the LLC task + * + **************************************************************************************** + */ +void llc_reset(void); + +/** + **************************************************************************************** + * @brief Start the BLE LLC task + * + * This function set the state of the task, the initiating link supervision time out, the + * feature used as well as the environment of the LLC and send the connection completed + * event + * + * @param[in] param Pointer on the structure which contains all the parameters + * needed to create and maintain the link. + * @param[in] conhdl Connection handle on which the connection is created + * @param[in] evt Pointer to the event associated with this connection + * + **************************************************************************************** + */ +void llc_start(struct llc_create_con_req_ind *param, struct ea_elt_tag *elt); +/** + **************************************************************************************** + * @brief Stop the BLE LLC task + * + * This function clears the state of the task, the environment of the LLC and send the connection completed + * event + * + * @param[in] conhdl Connection handle on which the connection is created + **************************************************************************************** + */ +void llc_stop(uint16_t conhdl); + +/** + **************************************************************************************** + * @brief Sends the disconnection complete event + * + * This function notify the host that the disconnection happened + * + * @param[in] src_id Source of the disconnection + * @param[in] status Status on the completion of the disconnection + * @param[in] conhdl Connection handle on which the disconnection happened + * @param[in] reason Why the disconnection happened + **************************************************************************************** + */ +void llc_discon_event_complete_send(kernel_task_id_t src_id, uint8_t status, uint8_t conhdl, uint8_t reason); + +/** + **************************************************************************************** + * @brief Sends the LE connection complete event + * + * This function notify the host that the connection happened + * + * @param[in] status Status on the completion of the connection + * @param[in] conhdl Connection handle on which the connection happened + * @param[in] param Pointer on the structure which contains all the parameters + * needed to create and maintain the link. + **************************************************************************************** + */ +void llc_le_con_cmp_evt_send(uint8_t status, uint16_t conhdl, struct llc_create_con_req_ind *param); + +/** + **************************************************************************************** + * @brief Sends the update connection complete event. + * + * This function notify the host that the update of the connection's parameters happened. + * + * @param[in] status Status on the completion of the update connection. + * @param[in] conhdl Connection handle on which the update connection happened. + * @param[in] evt Pointer to the event structure linked to the connection. + **************************************************************************************** + */ +void llc_con_update_complete_send(uint8_t status, uint16_t conhdl, struct lld_evt_tag *evt); + +/** + **************************************************************************************** + * @brief Sends the command complete event. + * + * This function notify the host that the command is completed. + * + * @param[in] opcode Command opcode + * @param[in] status Status on the completion of the command. + * @param[in] conhdl Connection handle on which the command has been processed. + **************************************************************************************** + */ +void llc_common_cmd_complete_send(uint16_t opcode, uint8_t status, uint16_t conhdl); + +/** + **************************************************************************************** + * @brief Sends the command status event. + * + * This function notify the host that the command is understood. + * + * @param[in] opcode Command opcode + * @param[in] status Status on the understanding of the command. + * @param[in] conhdl Connection handle on which the command has been processed. + **************************************************************************************** + */ +void llc_common_cmd_status_send(uint16_t opcode, uint8_t status, uint16_t conhdl); + +/** + **************************************************************************************** + * @brief Sends the number of completed packet event. + * + * This function notify the host of the number of packets acknowledged + * + * @param[in] conhdl Connection handle on which the packet has been acknowledged + * @param[in] nb_of_pkt Number of acknowledged packets + **************************************************************************************** + */ +void llc_common_nb_of_pkt_comp_evt_send(uint16_t conhdl, uint8_t nb_of_pkt); + +/** + **************************************************************************************** + * @brief Sends the read remote used features meta-event. + * + * @param[in] status Status of the event + * @param[in] conhdl Connection handle on which the remote features have been read + * @param[in] feats Read remote features + * + **************************************************************************************** + */ +void llc_feats_rd_event_send(uint8_t status, + uint16_t conhdl, + struct le_features const *feats); + +/** + **************************************************************************************** + * @brief Sends the remote version indication event. + * + * @param[in] status Status of the event + * @param[in] conhdl Connection handle on which the remote version have been read + * + **************************************************************************************** + */ +void llc_version_rd_event_send(uint8_t status, uint16_t conhdl); + +/** + **************************************************************************************** + * @brief Sends the encryption change event. + * + * This function notify the host of the new encryption status. + * + * @param[in] conhdl Connection handle on which the status of the encryption has + * been changed + * @param[in] enc_status Status of the encryption (ON or OFF) + * @param[in] status Inform if the change is successfully done or not. + **************************************************************************************** + */ +void llc_common_enc_change_evt_send(uint16_t conhdl, uint8_t enc_status, uint8_t status); + +/** + **************************************************************************************** + * @brief Sends the flush occurred event. + * + * This function notify the host that a flush of packet occurred. + * + * @param[in] conhdl Connection handle on which the flush occurred. + **************************************************************************************** + */ +void llc_common_flush_occurred_send(uint16_t conhdl); + +/** + **************************************************************************************** + * @brief Sends the encryption key refresh completed event. + * + * This function notify the host that the resume is done for the encryption. + * + * @param[in] conhdl Connection handle on which the key has been refreshed. + **************************************************************************************** + */ +void llc_common_enc_key_ref_comp_evt_send(uint16_t conhdl, uint8_t status); + +/** + **************************************************************************************** + * @brief Sends the long term key request. + * + * This function request to the host for a LTK. + * + * @param[in] conhdl Connection handle on which the LTK is requested. + * @param[in] param Pointer to the parameters of the LL_ENC_REQ + **************************************************************************************** + */ +void llc_ltk_req_send(uint16_t conhdl, struct llcp_enc_req const *param); + +/** + **************************************************************************************** + * @brief Indicates that the parameter update has occurred + * + * @param[in] conhdl Connection handle on which the update occurred. + * @param[in] evt_new Pointer to the new LLD event that is used for this connection. + **************************************************************************************** + */ +void llc_con_update_ind(uint16_t conhdl, struct ea_elt_tag *elt_new); + +/** + **************************************************************************************** + * @brief Indicates that the channel map update should be done. + * + * @param[in] conhdl Connection handle on which the update occurred. + **************************************************************************************** + */ +void llc_map_update_ind(uint16_t conhdl); + + +/** + **************************************************************************************** + * @brief Finish the connection update procedure + * + * @param[in] conhdl Connection handle + **************************************************************************************** + */ +void llc_con_update_finished(uint16_t conhdl); + +/** + **************************************************************************************** + * @brief Finish the channel map update procedure + * + * @param[in] conhdl Connection handle + **************************************************************************************** + */ +void llc_map_update_finished(uint16_t conhdl); + + +#if(BLE_2MBPS) +/** + **************************************************************************************** + * @brief Finish the phys update procedure and check if the host event should be sent + * + * @param[in] conhdl Connection handle + * @param[in] tx_phy Transmitter phy selected + * @param[in] rx_phy Received phy selected + * @param[in] status reason of the end + * @param[in] operation current operation: Local, hci or peer request + * + **************************************************************************************** + */ +void llc_phy_update_finished(uint16_t conhdl, uint8_t tx_phy, uint8_t rx_phy, uint8_t status, uint8_t operation); + + +/** + **************************************************************************************** + * @brief send the HCI message to inform that PHY update is completed + * + * @param[in] status reason of the end + * @param[in] conhdl Connection handle + * @param[in] tx_phy Transmitter phy selected + * @param[in] rx_phy Received phy selected + * + **************************************************************************************** + */ +void llc_phy_update_complete_send(uint8_t status, uint16_t conhdl, uint8_t tx_phy, uint8_t rx_phy); +#endif // (BLE_2MBPS) +/** + **************************************************************************************** + * @brief Before the connection update instant used the greater LSTO + * + * @param[in] conhdl Connection handle + **************************************************************************************** + */ +void llc_lsto_con_update(uint16_t conhdl); + +#endif // #if (BLE_PERIPHERAL || BLE_CENTRAL) +/// @} LLC + +#endif // LLCONTRL_H_ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/lld/lld.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/lld/lld.h new file mode 100755 index 0000000..19edef4 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/lld/lld.h @@ -0,0 +1,449 @@ +/** + **************************************************************************************** + * + * @file lld.h + * + * @brief Main API file for the Link Layer Driver + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef LLD_H_ +#define LLD_H_ + +/** + **************************************************************************************** + * @addtogroup LLD LLD + * @ingroup CONTROLLER + * @brief Link Layer Driver + * + * The LLD is responsible for programming the HW for event scheduling. It provides an API + * to the @ref LLD and the @ref LLC for event programming (@ref LLDEVT)and data + * transmission/reception (@ref LLDDATA). This API takes two forms depending on the + * direction: + * - LLM/LLC->LLD: Functions + * - LLD->LLM/LLC: Messages + * + * A typical use case of the LLD API: + + * @msc + * a [label=LLC], + * b [label=LLD]; + * + * --- [label="Data transmission example"]; + * a=>b [label="lld_data_tx_push(evt, txdesc)", URL="\ref lld_data_tx_push()"]; + * b->b [label="Data transmission to peer device"]; + * b->a [label="lld_pdu_ind", URL="\ref lld_pdu_ind"]; + * @endmsc + * + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include +#include +#include "rwip_config.h" +#include "rwip_task.h" +#include "kernel_task.h" +#include "common_list.h" +#include "llm.h" +#include "common_llcp.h" +#include "llc_llcp.h" +#include "reg_blecore.h" +#include "lld_evt.h" + +// Forward declarations +struct llm_le_create_con_cmd; + +/* + * DEFINES + **************************************************************************************** + */ +/// Reserved Handle for advertising traffic +#define LLD_ADV_HDL BLE_CONNECTION_MAX + +/// RX interrupt threshold +#define LLD_RX_IRQ_THRES (BLE_RX_BUFFER_CNT) //(BLE_RX_BUFFER_CNT/4) //modify 2017/08/31 alen + +/// Basic rate and Enhanced Data Rate +#define MOD_GFSK 0x01 + +/* + * ENUMERATIONS + **************************************************************************************** + */ + +/// Message identifiers +enum +{ + /// Message confirming the event deletion requested by the upper layers + LLD_STOP_IND = TASK_FIRST_MSG(TASK_ID_LLD), +}; + +/* + * MESSAGE PARAMETER STRUCTURES + **************************************************************************************** + */ + + + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Initialization of the BLE HW and event scheduler + * + * This function initializes the BLE HW core, as well as the environment of the LLD + * + * @param[in] reset true if it's requested by a reset; false if it's boot initialization + **************************************************************************************** + */ +void lld_init(bool reset); + +/** + **************************************************************************************** + * @brief Reset the BLE HW + * + * This function stops any pending activity of the BLE core, resets it and disables it. It + * is called upon reception of a HCI reset command. + * + **************************************************************************************** + */ +void lld_core_reset(void); + +/** + **************************************************************************************** + * @brief Start advertising + * + * This function creates an event for advertising, set the control structure according + * to the parameters, and program the required data for transmission. + * + * @param[in] adv_par Pointer to the structure containing the advertising + * parameters + * @param[in] adv_pdu Pointer to the buffer containing the advertising data + * @param[in] scan_rsp_pdu Pointer to the buffer containing the scan response data + * (should be set to NULL is no scan response has to be + * transmitted) + * @param[in] adv_pwr Transmission power for the advertising data + * + * @return The event pointer associated to the advertising + * + **************************************************************************************** + */ +struct ea_elt_tag *lld_adv_start(struct advertising_pdu_params *adv_par, + struct em_desc_node *adv_pdu, + struct em_desc_node *scan_rsp_pdu, + uint8_t adv_pwr); +/** + **************************************************************************************** + * @brief Start scanning + * + * This function creates an event for scanning, set the control structure according + * to the parameters, and program the required data for transmission. + * + * @param[in] param Pointer to the structure containing the scanning parameters + * @param[in] scan_req_pdu Pointer to the buffer containing the scan request data + * (should be set to NULL if passive scanning is required) + * + * @return The event pointer associated to the scanning + * + **************************************************************************************** + */ +struct ea_elt_tag *lld_scan_start(struct scanning_pdu_params const *scan_par, + struct em_desc_node *scan_req_pdu); + +#if (BLE_CENTRAL) +/** + **************************************************************************************** + * @brief Initiates a connection + * + * @param[in] con_par Connection parameters as requested by the host + * @param[in] con_req_pdu Pointer to the data buffer containing the connection request + * @param[in] conhdl Connection handle on which connection is initiated + * + * @return The event pointer associated to the started connection + * + **************************************************************************************** + */ +struct ea_elt_tag *lld_con_start(struct hci_le_create_con_cmd const *con_par, + struct em_desc_node *con_req_pdu, + uint16_t conhdl); + +/** + **************************************************************************************** + * @brief Indicates to LLD that it can program the first connection event for this handle + * + * This function is called by the @ref LLM once it receives the confirmation that the + * connection request has been transmitted to the future slave. The LLD then programs the + * first connection event for this slave. + * @note The @ref lld_con_start function has to be called previously to start the + * initiating process, otherwise lld_move_to_master has unpredictable behavior. + * + * @param[in] evt The pointer to the event on which the connection will occur + * @param[in] conhdl Connection handle on which connection is initiated + * @param[in] rx_hdl Handle of the rx descriptor where the ADV has been detected + * + **************************************************************************************** + */ +struct ea_elt_tag *lld_move_to_master(struct ea_elt_tag *elt, uint16_t conhdl, struct llc_create_con_req_ind const *param, uint8_t rx_hdl); +#endif //(BLE_CENTRAL) + +#if (BLE_PERIPHERAL) +/** + **************************************************************************************** + * @brief Indicates to LLD that it can program the first slave connection event + * + * This function is called by the @ref LLM once it receives a CONNECT_REQ. The LLD then + * programs the first connection event according to the parameters received in the + * CONNECT_REQ frame. + * + * @param[in] con_par Parameters of the connection + * @param[in] con_req_pdu Buffer containing the CONNECT_REQ frame + * @param[in] evt_adv Event that was used for the advertising + * @param[in] conhdl Connection handle on which connection is started + * + **************************************************************************************** + */ +struct ea_elt_tag *lld_move_to_slave(struct llc_create_con_req_ind *con_par, + struct llm_pdu_con_req_rx *con_req_pdu, + struct ea_elt_tag *elt_adv, + uint16_t conhdl); +#endif //(BLE_PERIPHERAL) + +/** + **************************************************************************************** + * @brief Stop the activity of a scanning event + * + * This function flushes all the TX/RX data for this event, and unprogram the + * event + * + * @param[in] evt The pointer to the event to be stopped + * + **************************************************************************************** + */ +void lld_scan_stop(struct ea_elt_tag *elt); + +/** + **************************************************************************************** + * @brief Stop the activity of an advertising event + * + * This function flushes all the TX/RX data for this event, and unprogram the + * event + * + * @param[in] evt The pointer to the event to be stopped + * + **************************************************************************************** + */ +void lld_adv_stop(struct ea_elt_tag *evt); + +/** + **************************************************************************************** + * @brief Stop the activity of a connection event + * + * This function flushes all the TX/RX data for this event, and unprogram the + * event + * + * @param[in] evt The pointer to the event to be stopped + * + **************************************************************************************** + */ +void lld_con_stop(struct ea_elt_tag *elt); + +/** + **************************************************************************************** + * @brief Stop the activity of a RF test mode event + * + * This function flushes all the TX/RX data for this event, and unprogram the + * event + * + * @param[in] evt The pointer to the event to be stopped + * + **************************************************************************************** + */ +void lld_test_stop(struct ea_elt_tag *elt); + +/** + **************************************************************************************** + * @brief Return the type of a provided connection (Master, Slave, Broadcaster, Advertiser) + * + * @param[in] conhdl Connection Handle + * + * @return A mode contained in enum lld_evt_mode; if an error occurs mode is LLD_EVT_MODE_MAX + * + **************************************************************************************** + */ +uint8_t lld_get_mode(uint16_t conhdl); + +/** + **************************************************************************************** + * @brief Interrupt service routine for the end of encryption IRQ + * + **************************************************************************************** + */ +void lld_crypt_isr(void); + +#if (BLE_CENTRAL || BLE_PERIPHERAL) + +/** + **************************************************************************************** + * @brief Change map indication + * + * This function indicates to the slave that to channel map update request has been + * received from the master, and at which time it will occur. + * + * @param[in] evt The pointer to the event on which the channel map has to be changed + * @param[in] instant The connection event count on which the update has to be applied + * + **************************************************************************************** + */ +void lld_ch_map_ind(struct ea_elt_tag *elt, uint16_t instant); + +/** + **************************************************************************************** + * @brief Update connection parameters (in Master mode) + * + * This function request to change the current connection parameters. + * + * @param[in] evt_old The event used prior to connection update + * @param[in] param Pointer on the structure which contains the latency, + * interval, window offset and size, timeout and the instant + * @param[out] param_pdu Pointer on the structure which contains the latency, + * interval, window offset and size, timeout and the instant + * dedicated to create the pdu + * + **************************************************************************************** + */ +void lld_con_update_req(struct ea_elt_tag *elt_old, + struct llc_con_upd_req_ind *param, + struct llcp_con_upd_ind *param_pdu); + +/** + **************************************************************************************** + * @brief Update connection parameters after a param_req from peer(in Master mode) + * + * This function request to change the current connection parameters. + * + * @param[in] evt_old The event used prior to connection update + * @param[in] param Pointer on the structure which contains the latency, + * interval, window offset and size, timeout and the instant + * @param[out] param_pdu Pointer on the structure which contains the latency, + * interval, window offset and size, timeout and the instant + * dedicated to create the pdu + * @param[in] bypass_offchk Bypass the check of the offset in case + * + **************************************************************************************** + */ +uint8_t lld_con_update_after_param_req(uint16_t conhdl, + struct ea_elt_tag *elt_old, + struct llc_con_upd_req_ind *param, + struct llcp_con_upd_ind *param_pdu, + bool bypass_offchk); + +/** + **************************************************************************************** + * @brief Respond to a param_req from peer(in Slave mode) + * + * This function checks if the parameters proposed by the peer (master) can be accepted. + * + * @param[in] conhdl Connection handle + * @param[in] evt The event used + * @param[in|out] param Pointer to the param_rsp to be sent to the peer + * + **************************************************************************************** + */ +uint8_t lld_con_param_rsp(uint16_t conhdl, + struct ea_elt_tag *elt, + struct llc_con_upd_req_ind *param); + +/** + **************************************************************************************** + * @brief Send a param_req to peer(in Slave mode) + * + * This function checks if the parameters proposed by the host can be accepted. + * + * @param[in] evt The event used + * @param[in|out] param Pointer to the parameters to update for the connection + * + **************************************************************************************** + */ +void lld_con_param_req(uint16_t conhdl, struct ea_elt_tag *elt, struct llc_con_upd_req_ind *param); + +/** + **************************************************************************************** + * @brief Update connection parameters (in Slave mode) + * + * This function request to change the current connection parameters. + * + * @param[in] evt_old The event used prior to connection update + * @param[in] param_pdu Pointer on the structure which contains the latency, + * interval, window offset and size, timeout and the instant + * received from the connection update pdu + **************************************************************************************** + */ +void lld_con_update_ind(struct ea_elt_tag *elt_old, + struct llcp_con_upd_ind const *param_pdu); + +#endif //(BLE_CENTRAL || BLE_PERIPHERAL) + +/** + **************************************************************************************** + * @brief Start the transmit test mode + * + * This function request to the HW to start the transmit test mode, by setting the format + * synchronization word (0x94826E8E), CRC(0x555555) and the transmit frequency in the CS + * and the address of the tx descriptor. + * + * @param[in] enh_cmd True if it is the enhanced command + * @param[in] txdesc Pointer on the TX descriptor containing the length, type and payload. + * @param[in] tx_freq Value of the Tx frequency + * @param[in] phy Value of the phy + * + * @return The event pointer associated to the tx test mode + * + **************************************************************************************** + */ +struct ea_elt_tag *lld_test_mode_tx(bool enh_cmd, struct em_desc_node *txdesc, uint8_t tx_freq, uint8_t phy); + +/** + **************************************************************************************** + * @brief Start the receive test mode + * + * This function request to the HW to start the transmit test mode, by setting the format + * and the receive frequency in the CS. + * + * @param[in] enh_cmd True if it is the enhanced command + * @param[in] rx_freq Value of the rx frequency + * @param[in] phy Value of the phy + * @param[in] modul_idx Value of the modulation index + * + * @return The event pointer associated to the rx test mode + * + **************************************************************************************** + */ +struct ea_elt_tag *lld_test_mode_rx(bool enh_cmd, uint8_t rx_freq, uint8_t phy, uint8_t modul_idx); + +/** + **************************************************************************************** + * @brief Request renewal of RPA addresses + * + * @return The event pointer associated to the ADV/SCAN/INIT mode + * + **************************************************************************************** + */ +void lld_ral_renew_req(struct ea_elt_tag *elt); + +/// @} LLD + +#endif // LLD_H_ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/lld/lld_evt.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/lld/lld_evt.h new file mode 100755 index 0000000..f64d6a3 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/lld/lld_evt.h @@ -0,0 +1,871 @@ +/** + **************************************************************************************** + * + * @file lld_evt.h + * + * @brief Declaration of functions used for event scheduling + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef LLD_EVT_H_ +#define LLD_EVT_H_ + +/** + **************************************************************************************** + * @addtogroup LLDEVT + * @ingroup LLD + * @brief Event scheduling functions + * + * This module implements the primitives used for event scheduling + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include +#include +#include "rwip_config.h" +#include "common_bt.h" +#include "common_list.h" +#include "common_llcp.h" +#include "reg_blecore.h" +#include "llm.h" +#include "llc_task.h" + +/* + * MACROS + **************************************************************************************** + */ + +/// Get BLE Event environment address from an element +#define LLD_EVT_ENV_ADDR_GET(elt) \ + ((struct lld_evt_tag *)(&(elt->env))) + + +/* + * DEFINES + **************************************************************************************** + */ + +/// Size of the LLD event table. It shall be equal to the max number of supported +/// connections * 2 + 1 for the scanning/advertising +#define LLD_EVT_TAB_SIZE (BLE_CONNECTION_MAX * 2 + 1) + +/// Invalid value for an interval +#define LLD_EVT_INTERVAL_INVALID 0xFFFF + +/// Maximum value an interval can take. This value is for time comparison +#define MAX_INTERVAL_TIME 3193600 // Max number of 625us periods for a connection interval + +/// Default RX window size +#define LLD_EVT_DEFAULT_RX_WIN_SIZE (14) +/// Frame Duration +#define LLD_EVT_FRAME_DURATION (1250) +/// Max Finecounter value +#define LLD_EVT_FINECNT_MAX (SLOT_SIZE - 1) +/// MAX LP Clock Jitter allowed by the specification (Core 4.0 - vol 6, -B - 4.2.2) +#define LLD_EVT_MAX_JITTER (16) +/// Duration of IFS (150 us) +#define LLD_EVT_IFS_DURATION (150) +/// Synchronization Word Duration + preamble 1MB 8us(preamble)+32us(AA) +#define LLD_EVT_SYNCWORD_DURATION_1MBPS (40) +/// Synchronization Word Duration + preamble 2MB 8us(preamble)+16us(AA) +#define LLD_EVT_SYNCWORD_DURATION_2MBPS (24) + +/// CONNECT_REQ PDU duration +#define LLD_EVT_CONNECT_REQ_DURATION (312) + +/// Default RX window offset 1MBPS +#define LLD_EVT_RX_WIN_DFT_OFF_1MBPS (LLD_EVT_SYNCWORD_DURATION_1MBPS - (LLD_EVT_DEFAULT_RX_WIN_SIZE / 2)) + +/// Default RX window offset 2MBPS +#define LLD_EVT_RX_WIN_DFT_OFF_2MBPS (LLD_EVT_SYNCWORD_DURATION_2MBPS - (LLD_EVT_DEFAULT_RX_WIN_SIZE / 2)) + +/// Path delay (in us) compensation for RX window @1MBPS +#define LLD_EVT_RX_WIN_PATHDLY_COMP_1MBPS (0) + +/// Path delay (in us) compensation for RX window @2MBPS +#define LLD_EVT_RX_WIN_PATHDLY_COMP_2MBPS (6) + +/// Maximum duration of a sleep, in low power clock cycles (around 300s) +#define LLD_EVT_MAX_SLEEP_DURATION 12000000 + +/// Default sleep duration when no event is programmed (in slot count) +#define LLD_EVT_DEFAULT_SLEEP_DURATION 8000 + +/// Maximum slave latency supported when total SCA is 1000ppm +#define LLD_EVT_MAX_LATENCY 450 + +/* + * Setting is calculated arbitrary on the bellow assumtions (for worst case) + * CS Size is 50 (16 bits access and DM field included) + * HW CS Read is 44 access + * HW CS Update is 18 access + * Tx Desc Size is 5 (16 bits access) + * HW TX Desc Read is 5 access + * HW Tx Desc Update is 1 access + * Rx Desc Size is 7 + * HW Rx Desc Read is 3 access + * HW Rx Desc Update is 5 access + * Worst case for aborting current frame is 76 access + * + * Assuming IP is running at 8MHz = 0.125 us + * Assuming EM waitstate is 4 for each access + * Assuming Hopping is 10 us + * Assuming Radio busy is 26 us (Ripple only) + * Assuming Highest Radio pwrup is 110 us + * + * Total time needed for abort with no bitoffset (worst case) is = 76*0.125*4 + 10 + 26 + 110 = 184 us + * + * PREFETCH ABORT TIME is = 624 - 184 = 440 + * PREFETCH TIME is = 184 + 26 us of Margin for abort and skip decision = 210 + */ + +/// Prefetch Abort time (in us) +#define LLD_EVT_ABORT_CNT_DURATION_US (440) + +/// Prefetch time (in us) +#define LLD_EVT_PREFETCH_TIME_US (210) + +/// Define the margin needed to reschedule correctly a scan/adv in case where the interval == window +/// or if the interval is < LLD_EVT_START_MARGIN +#define LLD_EVT_START_MARGIN (2) + +/***************************************************************************************** + * Event Flags (Status) + ****************************************************************************************/ + +enum lld_evt_flag +{ + /// Flag forcing the slave to wait for the next acknowledgment + LLD_EVT_FLAG_WAITING_ACK = (1 << 0), + /// Flag that indicate we are waiting for first sync + LLD_EVT_FLAG_WAITING_SYNC = (1 << 1), + /// Inform that a LLCP will be sent, used to update priority + LLD_EVT_FLAG_WAITING_TXPROG = (1 << 2), + /// Flag forcing the slave to wake up at instant + LLD_EVT_FLAG_WAITING_INSTANT = (1 << 3), + /// Delete the event after next End of Event ISR + LLD_EVT_FLAG_WAITING_EOEVT_TO_DELETE = (1 << 4), + /// Do not restart the element + LLD_EVT_FLAG_NO_RESTART = (1 << 5), + /// Indicate that end of event is due to an APFM interrupt + LLD_EVT_FLAG_APFM = (1 << 6), + /// Mark that latency is active for the link + LLD_EVT_FLAG_LATENCY_ACTIVE = (1 << 7), +}; + + +/* + * MACROS + **************************************************************************************** + */ + +/// Set Event status flag +#define LLD_EVT_FLAG_SET(evt, flag) \ + (evt->evt_flag |= (LLD_EVT_FLAG_ ## flag)) +/// Reset Event status flag +#define LLD_EVT_FLAG_RESET(evt, flag) \ + (evt->evt_flag &= (~(LLD_EVT_FLAG_ ## flag))) +/// Get Event status flag +#define LLD_EVT_FLAG_GET(evt, flag) \ + (evt->evt_flag & (LLD_EVT_FLAG_ ## flag)) + +/* + * ENUMERATIONS + **************************************************************************************** + */ + +enum lld_evt_mode +{ + LLD_EVT_ADV_MODE = 0, + LLD_EVT_SCAN_MODE, + LLD_EVT_TEST_MODE, + LLD_EVT_MST_MODE, + LLD_EVT_SLV_MODE, + + LLD_EVT_MODE_MAX +}; + + + +/// Type of events - Format value set in the Control Structure +enum lld_evt_cs_format +{ + // Master Connect + LLD_MASTER_CONNECTED = 0x02, + // Slave Connect + LLD_SLAVE_CONNECTED = 0x03, + // Low Duty Cycle Advertiser + LLD_LD_ADVERTISER = 0x04, + // High Duty Cycle Advertiser + LLD_HD_ADVERTISER = 0x05, + // Passive Scanner + LLD_PASSIVE_SCANNING = 0x08, + // Active Scanner + LLD_ACTIVE_SCANNING = 0x09, + // Initiator + LLD_INITIATING = 0x0F, + // Tx Test Mode + LLD_TXTEST_MODE = 0x1C, + // Rx Test Mode + LLD_RXTEST_MODE = 0x1D, + // Tx / Rx Test Mode + LLD_TXRXTEST_MODE = 0x1E, +}; + + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + +/// Synchronization counters +struct lld_evt_anchor +{ + /// Base time counter value of the latest found sync + uint32_t basetime_cnt; + /// Fine time counter value of the latest found sync + uint16_t finetime_cnt; + /// Event counter of the of the latest found sync + uint16_t evt_cnt; +}; + +/// Non connected event information +struct lld_non_conn +{ + /// Scan Window Size + uint32_t window; + /// Anchor timestamp + uint32_t anchor; + /// Event end time stamp + uint32_t end_ts; + /// use to know if it's an initiate procedure + bool initiate; + /// use to know if connect request has been sent + bool connect_req_sent; +}; + +/// Connected event information +struct lld_conn +{ + /// Synchronization Window Size (in us) + uint32_t sync_win_size; + /// SCA Drift (in us) + uint32_t sca_drift; + /// Instant of the next action (in events) + uint16_t instant; + /// Latency + uint16_t latency; + /// Event counter + uint16_t counter; + /// Number of connection events missed since last anchor point + uint16_t missed_cnt; + /// Minimum duration of the event or frame (in slots) + uint16_t duration_dft; + /// Update offset + uint16_t update_offset; + /// Effective maximum tx time + uint16_t eff_max_tx_time; + /// Effective maximum tx size + uint16_t eff_max_tx_size; + /// Update window size + uint8_t update_size; + /// Describe the action to be done when instant occurs + uint8_t instant_action; + /// Master sleep clock accuracy + uint8_t mst_sca; + /// value of the latest More Data bit received + uint8_t last_md_rx; + /// TX programmed packet counter + uint8_t tx_prog_pkt_cnt; + /// Default RX windows offset + uint8_t rx_win_off_dft; + /// Default RX windows path delay compensation + uint8_t rx_win_pathdly_comp; +#if (BLE_2MBPS) + /// TX phy to be programmed + uint8_t tx_phy; + /// RX phy to be programmed + uint8_t rx_phy; +#endif // (BLE_2MBPS) + /// Wait for a sync due to a connection update + bool wait_con_up_sync; + + uint32_t win_size_backup; //us +}; + +/// Structure describing an event +struct lld_evt_tag +{ + /// Information about the latest found synchronization + struct lld_evt_anchor anchor_point; + + /// List of TX Data descriptors ready for transmission (i.e. not yet chained with the CS) + struct common_list tx_acl_rdy; + /// List of TX Data descriptors ready to be freed (i.e. already chained in the CS) + struct common_list tx_acl_tofree; +#if (BLE_CENTRAL || BLE_PERIPHERAL) + /// List of TX LLCP descriptors ready for transmission (i.e. not yet chained with the CS) + struct common_list tx_llcp_pdu_rdy; +#endif // (BLE_CENTRAL || BLE_PERIPHERAL) + /// List of TX LLCP descriptors programmed for transmission (i.e. chained with the CS) + struct common_list tx_prog; + + + /// Interval element pointer linked to this event + struct ea_interval_tag *interval_elt; + + /// event information for connected and non-connected activity + union lld_evt_info + { + /// Non connected event information + struct lld_non_conn non_conn; + + /// Connected event information + struct lld_conn conn; + } evt; + + /// Connection Handle + uint16_t conhdl; + /// Control structure pointer address + uint16_t cs_ptr; + /// Connection Interval + uint16_t interval; + /// Number of RX Descriptors already handled in the event + uint8_t rx_cnt; + /// Mode of the link (Master connect, slave connect, ...) + uint8_t mode; + /// TX Power + uint8_t tx_pwr; + /// Default priority + uint8_t default_prio; + + /// Internal status + uint8_t evt_flag; + + /// Flag delete on going + bool delete_ongoing; +}; + +/// Structure describing the parameters for a connection update +struct lld_evt_update_tag +{ + /// Offset to be put in the connection update request + uint16_t win_offset; + /// Instant for the connection update + uint16_t instant; + /// Size of the window to be put in the connection update request + uint8_t win_size; +}; + +/// Structure describing an event +struct lld_evt_int_tag +{ + /// List element for chaining + struct common_list_hdr hdr; + /// List of events attached to this interval + struct lld_evt_tag *evt; + /// Number of free slots + uint32_t freeslot; + /// Base interval time + uint16_t int_base; +}; + +/// Environment structure for the LLD module +struct lld_evt_env_tag +{ + /// List of programmed element + struct common_list elt_prog; + /// List of programmed element + struct common_list elt_wait; + /// List of element pending to be freed + struct common_list elt_deferred; + /// List of rx packet to handle + struct common_list rx_pkt_deferred; + /// List of element pending to be deleted + struct common_list elt_to_be_deleted; + /// Accuracy of the low power clock connected to the BLE core + uint8_t sca; + /// Used to know if resolvable private address shall be renewed + bool renew; + /// Compensation in us of the HW behavior when fine_cnt compensation equals zero, HW does not execute 1 us. + uint8_t hw_wa_sleep_compensation; +}; + +/// Environment structure for the LLD module +struct lld_evt_wait_tag +{ + /// List element for chaining in the Even Arbiter lists + struct common_list_hdr hdr; + /// Pointer on the waiting element + struct ea_elt_tag *elt_ptr; +}; + +/// Deferred element structure +struct lld_evt_deferred_tag +{ + /// List element for chaining in the Even Arbiter lists + struct common_list_hdr hdr; + + /// Pointer on the deferred element + struct ea_elt_tag *elt_ptr; + + /// Type of deferring + uint8_t type; + + /// Number of used RX Descriptors + uint8_t rx_desc_cnt; +}; + +/// Delete element structure +struct lld_evt_delete_tag +{ + /// List element for chaining in the delete lists + struct common_list_hdr hdr; + + /// Pointer on the deferred element + struct ea_elt_tag *elt_ptr; + + /// Tparameters of teh deletion + bool flush; + bool send_ind; +}; + + +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ + +/// Environment of the LLDEVT module +extern struct lld_evt_env_tag lld_evt_env; + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Get sleep clock accuracy + * + * @return The sleep clock accuracy as defined in the standard + * + **************************************************************************************** + */ +__INLINE uint8_t lld_evt_sca_get(void) +{ + // Read sleep clock accuracy from the environment + return (lld_evt_env.sca); +} + +/** + **************************************************************************************** + * @brief Get current time value from HW + * + * @return The current time in units of 625us + * + **************************************************************************************** + */ +__INLINE uint32_t lld_evt_time_get(void) +{ + // Sample the base time count + ble_samp_setf(1); + while (ble_samp_getf()); + // Read current time in HW + return (ble_basetimecnt_get()); +} + + +__INLINE void lld_evt_time_get_us(uint32_t *slot, uint32_t *slot1) +{ + // Sample the base time count + ble_samp_setf(1); + while (ble_samp_getf()); + + *slot = ble_basetimecnt_get(); + *slot1 = ble_finetimecnt_get(); + + // Read current time in HW + //return (ble_finetimecnt_get()); +} + + +/** + **************************************************************************************** + * @brief Compare absolute times + * + * The absolute time difference between time1 and time2 is supposed to be less than the + * maximum interval time + * + * @param[in] time1 First time to compare + * @param[in] time2 Second time to compare + * + * @return true if time1 is smaller than time2. + **************************************************************************************** + */ +__INLINE bool lld_evt_time_cmp(uint32_t time1, + uint32_t time2) +{ + return (((time1 - time2) & BLE_BASETIMECNT_MASK) > MAX_INTERVAL_TIME); +} + +/** + **************************************************************************************** + * @brief Check if time passed as parameter is in the past + * + * @param[in] time Time to be compare with current time to see if it in the past + * + * @return true if time is in the past, false otherwise + * + **************************************************************************************** + */ +__INLINE bool lld_evt_time_past(uint32_t time) +{ + // Compare time and current time + return (lld_evt_time_cmp(time & BLE_BASETIMECNT_MASK, lld_evt_time_get())); +} + +/** + **************************************************************************************** + * @brief Computes the maximum drift according to the master clock accuracy and the delay + * passed as parameters + * + * @param[in] delay Duration for which the drift is computed + * @param[in] master_sca Sleep clock accuracy of the master + * + * @return The value of the RX window size formatted for the RXWINCNTL field of the + * control structure + * + **************************************************************************************** + */ +uint16_t lld_evt_drift_compute(uint16_t delay, uint8_t master_sca); + +/** + **************************************************************************************** + * @brief Create a connection or scanning event and chain it in the scheduling and + * interval lists + * + * @param[in] handle Connection handle for which the event is created (LLD_ADV_HDL if + * non-connected event) + * @param[in] duration Expected duration of the event, in units of 625us. This duration + * can be reduced if scheduling of other events is requiring that. + * @param[in] mininterval Minimum interval for the connection event + * @param[in] maxinterval Maximum interval for the connection event + * @param[in] latency Requested latency for the event + * + * @return The pointer to the event just created + * + **************************************************************************************** + */ +struct ea_elt_tag *lld_evt_scan_create(uint16_t handle, uint16_t latency); + +/** + **************************************************************************************** + * @brief Create an advertising event and chain it in the scheduling list + * + * @param[in] handle Connection handle for which the event is created (LLD_ADV_HDL if + * non-connected event) + * @param[in] mininterval Minimum interval for the advertising event + * @param[in] maxinterval Maximum interval for the advertising event + * @param[in] restart_pol Requested restart policy, i.e. LLD_ADV_RESTART or LLD_NO_RESTART + * + * @return The pointer to the event just created + * + **************************************************************************************** + */ +struct ea_elt_tag *lld_evt_adv_create(uint16_t handle, + uint16_t mininterval, + uint16_t maxinterval, + bool restart_pol); + +#if (BLE_CENTRAL || BLE_PERIPHERAL) +/** + **************************************************************************************** + * @brief Create a connection event for parameter update + * + * @param[in] evt_old Pointer to the current connection event + * @param[in] ce_len Requested size of the connection event (in 625us slots) + * @param[in] mininterval Minimum interval for the connection event + * @param[in] maxinterval Maximum interval for the connection event + * @param[in] latency Requested slave latency + * @param[in] pref_period preferred periodicity + * @param[out] upd_par Computed updated parameters, to be put in the LLCP frame + * + * @return The pointer to the new event created (used after instant) + * + **************************************************************************************** + */ +struct ea_elt_tag *lld_evt_update_create(struct ea_elt_tag *evt_old, + uint16_t ce_len, + uint16_t mininterval, + uint16_t maxinterval, + uint16_t latency, + uint8_t pref_period, + struct lld_evt_update_tag *upd_par); + +/** + **************************************************************************************** + * @brief Create a slave connection event + * + * @param[in] con_par Pointer to the decoded connection parameters + * @param[in] con_req_pdu Pointer to the connection request frame as received + * @param[in] evt_adv Pointer to the advertising event that triggered the connection + * @param[in] conhdl Connection handle to the established connection + * + * @return The pointer to the slave event created + * + **************************************************************************************** + */ +struct ea_elt_tag *lld_evt_move_to_slave(struct llc_create_con_req_ind *con_par, + struct llm_pdu_con_req_rx *con_req_pdu, + struct ea_elt_tag *elt_adv, + uint16_t conhdl); +/** + **************************************************************************************** + * @brief Indicates to the LLD the occurrence of a connection parameter update. + * + * @param[in] param_pdu Pointer to the connection parameter update PDU + * @param[in] evt_old Pointer to the current event used for this connection + * + **************************************************************************************** + */ +void lld_evt_slave_update(struct llcp_con_upd_ind const *param_pdu, + struct ea_elt_tag *elt_old); + +/** + **************************************************************************************** + * @brief Indicates to the LLD to move from initiating to master connected state. + * + * @param[in] evt Pointer to the event used for initiation + * @param[in] conhdl Handle of the new master connection + * @param[in] rx_hdl Handle of the rx descriptor where the ADV has been detected + * + **************************************************************************************** + */ +struct ea_elt_tag *lld_evt_move_to_master(struct ea_elt_tag *elt_scan, uint16_t conhdl, struct llc_create_con_req_ind const *pdu_tx, uint8_t rx_hdl); +#endif //(BLE_CENTRAL || BLE_PERIPHERAL) + +/** + **************************************************************************************** + * @brief Program the next occurrence of the slave event passed as parameter + * In case the slave event passed as parameter is far enough in the future (e.g. due to + * slave latency), the event is canceled and replaced with the earliest possible one. This + * function is called when a data has been pushed for transmission in order to send it as + * soon as possible even if slave latency is used. + * + * @param[in] elt Element to be deleted + **************************************************************************************** + */ +void lld_evt_schedule_next(struct ea_elt_tag *elt); + + +/** + **************************************************************************************** + * @brief Initialization of the BLE event scheduler + * + * This function initializes the lists used for event scheduling. + * + * @param[in] reset true if it's requested by a reset; false if it's boot initialization + **************************************************************************************** + */ +void lld_evt_init(bool reset); + +/** + **************************************************************************************** + * @brief Initialization of BLE event environement + **************************************************************************************** + */ +void lld_evt_init_evt(struct lld_evt_tag *evt); + +/** + **************************************************************************************** + * @brief Handle insertion of an element in Event Arbitrer list of elements + **************************************************************************************** + */ +void lld_evt_elt_insert(struct ea_elt_tag *elt, bool inc_prio); + +/** + **************************************************************************************** + * @brief Handle removing of an element in Event Arbitrer list of elements + **************************************************************************************** + */ +bool lld_evt_elt_delete(struct ea_elt_tag *elt, bool flush_data, bool send_indication); + +/** + **************************************************************************************** + * @brief Kernel event scheduled when BLE events has to be programmed in the HW + * + * This function is a deferred action of the BLE wake up interrupt. It programs the data + * Tx/Rx exchange in the control structure corresponding to the event, and programs the + * target time of the next event to be scheduled. + * + **************************************************************************************** + */ +void lld_evt_schedule(struct ea_elt_tag *elt); + +/** + **************************************************************************************** + * @brief Kernel event scheduled when a BLE event has to be handled by the HW + * + * This function is a deferred action of the BLE end of event interrupt. It flushes the + * data Tx/Rx exchange corresponding to the event, and programs the + * target time of the next event to be scheduled. + * + **************************************************************************************** + */ +void lld_evt_end(struct ea_elt_tag *elt); + +/** + **************************************************************************************** + * @brief Kernel event scheduled when a BLE RX has to be handled by the HW + * + * This function is a deferred action of the BLE RX interrupt. It flushes the + * data Tx/Rx exchange corresponding to the event. + * + **************************************************************************************** + */ +void lld_evt_rx(struct ea_elt_tag *elt); + +/** + **************************************************************************************** + * @brief End of sleep interrupt handler + * + * This function is called under interrupt when an end of sleep interrupt is generated by + * the BLE core. It sets the associated kernel event in order to perform the handling as a + * deferred action in background context. + * + **************************************************************************************** + */ +void lld_evt_start_isr(void); + + +/** + **************************************************************************************** + * @brief End of event/frame interrupt handler + * + * This function is called under interrupt when an end of event/frame interrupt is + * generated by the BLE/BT core. + * + * param[in] apfm - Indicate if end of event is due to an apfm interrupt + * + **************************************************************************************** + */ +void lld_evt_end_isr(bool apfm); + +/** + **************************************************************************************** + * @brief RX interrupt handler + * + * This function is called under interrupt when an RX interrupt is generated by + * the BLE core. It sets the associated kernel event in order to perform the handling as a + * deferred action in background context. + * + **************************************************************************************** + */ +void lld_evt_rx_isr(void); + +/** + **************************************************************************************** + * @brief General purpose timer interrupt handler + * + * This function is called under interrupt when a general purpose timer interrupt is + * generated by the BLE core. It sets the associated kernel event in order to perform the + * handling as a deferred action in background context. + * + **************************************************************************************** + */ +void lld_evt_timer_isr(void); + + +/** + **************************************************************************************** + * @brief Check if event has an alternative event, if yes, delete it. + * + * @param[in] evt Pointer to the event which can have alternative event + **************************************************************************************** + */ +void lld_delete_alt_evt(struct lld_evt_tag *evt); + +/** + **************************************************************************************** + * @brief Computes the next unmapped channel index according to the hopping mechanism. + * The previous channel index is taken from the control structure, and once the next + * unmapped channel is computed, it is put back in the control structure. + * + * @param[in] evt The event for which the next channel has to be computed + * + **************************************************************************************** + */ +void lld_evt_channel_next(uint16_t conhdl, int16_t nb_inc); + +/** + **************************************************************************************** + * @brief Try to cancel an event fur to host or EA request + * + * @param[in] elt Pointer to the element to be canceled + * + **************************************************************************************** + */ +void lld_evt_canceled(struct ea_elt_tag *elt); + +/** + **************************************************************************************** + * @brief Function which handles the non IRQ functionalities: RX data, ... + * + **************************************************************************************** + */ +void lld_evt_deffered_elt_handler(void); + +/** + **************************************************************************************** + * @brief Dummy call back function to match with EA API + * + * @param[in] elt Pointer to the element to be stopped + * + **************************************************************************************** + */ +void lld_evt_prevent_stop(struct ea_elt_tag *elt); + +/** + **************************************************************************************** + * @brief Try to restart the event by updating scheduling parameters + * + * @param[in] elt Pointer to the element to be restarted + * @param[in] rejected Flag to indicate if the restart comes from a reject + * + * @return True if element can be restarted, False else + **************************************************************************************** + */ +bool lld_evt_restart(struct ea_elt_tag *elt, bool rejected); + +/** + **************************************************************************************** + * @brief Try push a delete element in the list + * + * @param[in] elt Pointer to the element to be deleted + * @param[in] flush Flag to indicate if the tx data should be flushed + * @param[in] flush Flag to indicate if an event should be sent to the host + * + **************************************************************************************** + */ +void lld_evt_delete_elt_push(struct ea_elt_tag *elt, bool flush, bool send_indication); + + +uint32_t lld_evt_get_next_free_slot(void); + +//uint8_t lld_evt_get_scan_act_id(void); + +/// @} LLDEVT + +#endif // LLD_EVT_H_ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/lld/lld_pdu.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/lld/lld_pdu.h new file mode 100755 index 0000000..2332e7e --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/lld/lld_pdu.h @@ -0,0 +1,177 @@ +/** + **************************************************************************************** + * + * @file lld_pdu.h + * + * @brief Functions for adv\acl\llcp transmission/reception handling + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef LLD_PDU_H_ +#define LLD_PDU_H_ + +/** + **************************************************************************************** + * @addtogroup LLDPDU LLDPDU + * @ingroup LLD + * @brief Functions for adv/acl/llcp transmission/reception handling + * + * This module implements the primitives allowing the LLC asking for adv/acl/llcp transmission. + * It configures the Tx lists and handles the reception. + * + * @{ + **************************************************************************************** + */ + + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include +#include "em_buf.h" +#include "lld.h" +#include "lld_evt.h" + +/* + * MESSAGE PARAMETER STRUCTURES + **************************************************************************************** + */ +/// ACL data TX element structure +struct lld_pdu_data_tx_tag +{ + /// List element for chaining + struct common_list_hdr hdr; + /// index + uint16_t idx; + /// connection handle + uint16_t conhdl; + /// length of the data + uint16_t length; + /// broadcast and packet boundary flag + uint8_t pb_bc_flag; +#if (BLE_EMB_PRESENT) + /// Pointer to the first descriptor containing RX Data + struct em_buf_node *buf; +#else // (BLE_HOST_PRESENT) + /// Pointer to the data buffer + uint8_t *buffer; +#endif // (BLE_EMB_PRESENT) / (BLE_HOST_PRESENT) +}; + + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ +/** + **************************************************************************************** + * @brief Ask for a adv/connection/scan transmission + * + * This function is called by the LLM to request for a transmission. It chains the + * descriptor passed as parameter in the list of descriptors ready for transmission. + * + * @param[in] elt Pointer to the element for which a transmission is requested + * @param[in] txnode Pointer to the TX node + * + **************************************************************************************** + */ +void lld_pdu_tx_push(struct ea_elt_tag *elt, struct em_desc_node *txnode); + +/** + **************************************************************************************** + * @brief Ask for a data transmission + * + * This function is called by the LLC to request for a transmission. It chains the + * descriptor passed as parameter in the list of descriptors ready for transmission. + * + * @param[in] elt Pointer to the element for which a transmission is requested + * @param[in] txnode Pointer to the TX node + * @param[in] can_be_freed Flag to indicate if the buffer can be freed + * + **************************************************************************************** + */ +void lld_pdu_data_tx_push(struct lld_evt_tag *evt, struct em_desc_node *txnode, bool can_be_freed, bool encrypted); + +/** + **************************************************************************************** + * @brief Loop back the TX data in the exchange memory + * + * This function chains the next descriptor pointer of the last TX descriptor with the + * first TX descriptor. It therefore creates a loop. + * + * @param[in] evt Event associated with the data to loop + * + **************************************************************************************** + */ +void lld_pdu_tx_loop(struct lld_evt_tag *evt); + +/** + **************************************************************************************** + * @brief Prepare buffer pointers in the control structure for TX + * + * This function is called by the event scheduler when an event for a connection is ready + * to be programmed. It chains the descriptors ready for transmissions with the ones + * already programmed, and update the control structure with the pointer to the first + * descriptor. + * + * @param[in] evt Event for which the buffers have to be programmed + * + **************************************************************************************** + */ +void lld_pdu_tx_prog(struct lld_evt_tag *evt); + + +/** + **************************************************************************************** + * @brief Flush the data currently programmed for transmission + * + * @param[in] evt Pointer to the event for which TX data has to be flushed + **************************************************************************************** + */ +void lld_pdu_tx_flush(struct lld_evt_tag *evt); + +uint8_t lld_pdu_adv_pack(uint8_t code, uint8_t *buf, uint8_t *p_len); + + +/** + **************************************************************************************** + * @brief Called in interrupt context, it retrieves information about received data packet + * and decide if it should process it within interrupt context or to defer it. + * + * @param[in] evt Pointer on the on-going event + * @param[in] nb_rx_desc Number of RX descriptor updated by HW + **************************************************************************************** + */ +void lld_pdu_rx_handler(struct lld_evt_tag *evt, uint8_t nb_rx_desc); + +/** + **************************************************************************************** + * @brief Called in event context, it retrieves information about received and acknowledged + * data packet + * + * @param[in] evt Pointer on the event defered + * @param[out] elt_deleted Return if the element has been deleted (scan evt during init) + **************************************************************************************** + */ +bool lld_pdu_check(struct lld_evt_tag *evt); + +/** + **************************************************************************************** + * @brief Called in background context, it pushes the data to transmit in the ready to be + * sent queue + * + * @param[in] param Pointer on element to be sent + * + * Return true if pushed in teh ready queue + **************************************************************************************** + */ +bool lld_pdu_data_send(void *param); + +/// @} LLDPDU + +#endif // LLD_PDU_H_ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/lld/lld_sleep.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/lld/lld_sleep.h new file mode 100755 index 0000000..4566d3f --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/lld/lld_sleep.h @@ -0,0 +1,103 @@ +/** + **************************************************************************************** + * + * @file lld_sleep.h + * + * @brief Functions for RWBLE core sleep mode management + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef LLD_SLEEP_H_ +#define LLD_SLEEP_H_ + +/** + **************************************************************************************** + * @addtogroup LLDSLEEP LLDSLEEP + * @ingroup LLD + * @brief Functions for RWBLE core sleep mode management + * + * This module implements the function that manages deep sleep of BLE core. + * + * @{ + **************************************************************************************** + */ + + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" + +#if (DEEP_SLEEP) +#include +#include + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +#if (!BT_DUAL_MODE) + +/** + **************************************************************************************** + * @brief Initialize sleep module + **************************************************************************************** + */ +void lld_sleep_init(void); + +/** + **************************************************************************************** + * @brief The Sleep function. Enter BLE Core in deep sleep + * + * @param[in] sleep_duration Duration of deep sleep (slot time duration) + * @param[in] ext_wakeup False: external wake-up disabled / True: enabled + **************************************************************************************** + */ +void lld_sleep_enter(uint32_t sleep_duration, bool ext_wakeup); + +/** + **************************************************************************************** + * @brief Function to wake up BLE core + **************************************************************************************** + */ +void lld_sleep_wakeup(void); + +/** + **************************************************************************************** + * @brief Function to handle the end of BLE core wake up + **************************************************************************************** + */ +void lld_sleep_wakeup_end(void); + +#endif // !BT_DUAL_MODE + +/** + **************************************************************************************** + * @brief Check if sleep mode is possible + * + * The function takes as argument the allowed sleep duration that must not be increased. + * If BLE needs an earlier wake-up than initial duration, the allowed sleep duration + * is updated. + * If BLE needs a shorter duration than the wake-up delay, sleep is not possible and + * the function returns a bad status. + * + * @param[in/out] sleep_duration Initial allowed sleep duration (in slot of 625us) + * @param[in] wakeup_delay Delay for system wake-up (in slot of 625us) + * + * @return true if sleep is allowed, false otherwise + **************************************************************************************** + */ +//bool lld_sleep_check(uint32_t *sleep_duration, uint32_t wakeup_delay); + +#endif // DEEP_SLEEP + +/// @} LLDSLEEP + +#endif // LLD_SLEEP_H_ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/lld/lld_util.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/lld/lld_util.h new file mode 100755 index 0000000..ab05f1e --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/lld/lld_util.h @@ -0,0 +1,362 @@ +/** + **************************************************************************************** + * + * @file lld_util.h + * + * @brief Link layer driver utilities definitions + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ +#ifndef LLD_UTIL_H_ +#define LLD_UTIL_H_ +/** + **************************************************************************************** + * @addtogroup LLDUTIL + * @ingroup LLD + * @brief Link layer driver utilities definitions + * + * full description + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include +#include "common_bt.h" +#include "ea.h" +#include "lld_evt.h" + +/* + * DEFINES + **************************************************************************************** + */ + +/// Minimum number of connection event for instant calculation (6 according to the SIG) +#define LLD_UTIL_MIN_INSTANT_CON_EVT (6) + +/* + * ENUMERATIONS + **************************************************************************************** + */ +enum lld_util_instant_action +{ + LLD_UTIL_NO_ACTION = 0, + LLD_UTIL_PARAM_UPDATE, + LLD_UTIL_CHMAP_UPDATE, +#if (BLE_2MBPS) + LLD_UTIL_PHY_UPDATE, +#endif // (BLE_2MBPS) +}; + + +enum lld_cs_rate +{ + LLD_CS_RATE_1MBPS, + LLD_CS_RATE_2MBPS, +}; + +/* + * FUNCTION DEFINITIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Get the BD address + * + * @param[out] Pointer to BD address buffer + **************************************************************************************** + */ +void lld_util_get_bd_address(struct bd_addr *bd_addr); + +/** + **************************************************************************************** + * @brief Set the BD address + * + * @param[in] bd_addr Pointer to BD address buffer + * @param[in] type Address type (0:public, 1:random) + **************************************************************************************** + */ +void lld_util_set_bd_address(struct bd_addr *bd_addr, uint8_t type); + + +/** + **************************************************************************************** + * @brief Force renewal of resolvable private addresses + **************************************************************************************** + */ +void lld_util_ral_force_rpa_renew(void); +/** + **************************************************************************************** + * @brief Convert frequecny in channel + * + * @param[in] freq Frequency to convert + * + * @return return the channel used + * + **************************************************************************************** + */ +uint8_t lld_util_freq2chnl(uint8_t freq); + +/** + **************************************************************************************** + * @brief Check if the element is in the programmed queue + * + * @param[in] elt element to be checked + * + * @return return true if the element has been found + * + **************************************************************************************** + */ +bool lld_util_elt_is_prog(struct ea_elt_tag *elt); + + +/** + **************************************************************************************** + * @brief This function returns the local offset (with respect to CLKN). + * + * @param[in] PeerOffset Peer offset + * @param[in] Interval Interval + * @param[in] AnchorPoint Anchor point (with respect to CLKN) + * + * @return Offset value + * + **************************************************************************************** + */ +uint16_t lld_util_get_local_offset(uint16_t PeerOffset, uint16_t Interval, uint32_t AnchorPoint); + +/** + **************************************************************************************** + * @brief This function returns the peer offset (with respect to CLKE). + * + * @param[in] LocalOffset Local offset + * @param[in] Interval Interval + * @param[in] AnchorPoint Anchor point (with respect to CLKN) + * + * @return Offset value + * + **************************************************************************************** + */ +uint16_t lld_util_get_peer_offset(uint16_t LocalOffset, uint16_t Interval, uint32_t AnchorPoint); + +/** + **************************************************************************************** + * @brief Function to set the duration and the start of the event + * + * @param[in] elt element to update + * + * @param[in] param parameter to compute the start of the event + * + **************************************************************************************** + */ +void lld_util_connection_param_set(struct ea_elt_tag *elt, struct ea_param_output *param); + + +/** + **************************************************************************************** + * @brief Free all the elements of the list + * + * This function is called to flush and free the elements contain in a list + * + * @param[in] list pointer on the list to be flushed + * + **************************************************************************************** + */ +void lld_util_flush_list(struct common_list *list); + +/** + **************************************************************************************** + * @brief Set the Rxmax size and time in the CS for a dedicated link + * + * This function is called by the event scheduler when an event for a connection is ready + * to be programmed. It updates the CS-RXMAXBUFF and CS_RXMAXTIME + * + * @param[in] conhdl handle for which the fields should be updated + * + **************************************************************************************** + */ +void lld_util_dle_set_cs_fields(uint16_t conhdl); + +/** + **************************************************************************************** + * @brief Function to launch automatically an anchor point move + * + * @param[in] elt element to move + * + **************************************************************************************** + */ +void lld_util_anchor_point_move(struct ea_elt_tag *elt_connect); +#if (BLE_PERIPHERAL || BLE_CENTRAL) +/** + **************************************************************************************** + * @brief Check if an instant is already pending + * + * @param[in] elt element to check + * + * @return if an instant is on going + **************************************************************************************** + */ +bool lld_util_instant_ongoing(struct ea_elt_tag *elt); +/** + **************************************************************************************** + * @brief Compute the new connection event max accordingly to the rx and tx time (DLE) + * + * @param[in] elt element to update + * @param[in] tx_time rx time negotiated during DLE + * @param[in] rx_time tc time negotiated during DLE + * + **************************************************************************************** + */ + +void lld_util_compute_ce_max(struct ea_elt_tag *elt, uint16_t tx_time, uint16_t rx_time); + +#endif //(BLE_PERIPHERAL || BLE_CENTRAL) + +/** + **************************************************************************************** + * @brief Check if an the element is already programmed or will be programmed + * + * @param[in] elt element to check + * + * @return true if the element is programmed + **************************************************************************************** + */ +bool lld_util_elt_programmed(struct ea_elt_tag *elt); + +/** + **************************************************************************************** + * @brief Set the priority used by the element + * + * @param[in] elt element to set the priority + * @param[in] priority_index index of the priority + * + **************************************************************************************** + */ +void lld_util_priority_set(struct ea_elt_tag *elt, uint8_t priority_index); +/** + **************************************************************************************** + * @brief Update the default priority used by the element + * + * @param[in] elt element to set the default priority + * @param[in] value value of the priority + * + **************************************************************************************** + */ +void lld_util_priority_update(struct ea_elt_tag *elt, uint8_t value); + + +#if (BLE_CENTRAL || BLE_PERIPHERAL) +/** + **************************************************************************************** + * Retrieve number of Packet to transmit in programmed queue + * + * @param elt Connection element + * + * @return Number of Packet to transmit in programmed queue + **************************************************************************************** + */ +uint8_t lld_util_get_tx_pkt_cnt(struct ea_elt_tag *elt); + + +/** + **************************************************************************************** + * @brief Request to program a channel map update + * + * @param[in] evt Pointer to the event for which the update has to be programmed + * @param[in] action Type of action which request the instant (channel map,...) + * + * @return The instant computed for the update + * + **************************************************************************************** + */ +uint16_t lld_util_instant_get(void *evt, uint8_t action); + +#if (BLE_2MBPS) +/** + **************************************************************************************** + * @brief Gets the values of the RX and TX PHYS used by the element + * + * @param[in] elt element to set + * + * @return value of the rx and tx phys used by the link + * + **************************************************************************************** + */ +void lld_util_get_phys(struct ea_elt_tag *elt, uint8_t *tx_phy, uint8_t *rx_phy); + + +/** + **************************************************************************************** + * @brief Update phys parameters (in Slave mode) + * + * This function give to the driver the instant and the parameters of the future phys + * + * @param[in] elt The element used + * @param[in] instant Instant (event counter) of the switch + * @param[in] tx_phy transmitter phy for the slave + * @param[in] rx_phy receiver phy for the slave + * + **************************************************************************************** + */ +void lld_util_phy_update_req(struct ea_elt_tag *elt, uint16_t instant, uint8_t tx_phy, uint8_t rx_phy); + +/** + **************************************************************************************** + * @brief Update phys parameters (in Slave mode) + * + * This function request to change the current phys parameters. + * + * @param[in] elt The element used + **************************************************************************************** + */ +void lld_util_phy_update_ind(struct ea_elt_tag *elt); +#endif // (BLE2MBPS) +#endif // (BLE_CENTRAL || BLE_PERIPHERAL) +#if (BLE_PERIPHERAL) +/** + **************************************************************************************** + * @brief Set the latency for a slave link + * + * This function set an immediate latency without starting procedure. + * + * @param[in] conhdl Connection handle + * @param[in] latency Latency + **************************************************************************************** + */ +uint8_t lld_util_pref_slave_latency_set(uint16_t conhdl, uint16_t latency); +#endif // (BLE_PERIPHERAL) +/** + **************************************************************************************** + * @brief Set maximum transmission time + * + * This function set the maximum time for a pdu transmission + * + * @param[in] elt The element used + * @param[in] max_tx_time Maximum transmission time + * @param[in] max_tx_time Maximum transmission size + **************************************************************************************** + */ +void lld_util_eff_tx_time_set(struct ea_elt_tag *elt, uint16_t max_tx_time, uint16_t max_tx_size); + +#if (BLE_PERIPHERAL || BLE_CENTRAL) +/** + **************************************************************************************** + * @brief Calculate and set the maximum latency that can be used on this link + * + * @param[in] link_id Link identifier + * @param[in] lsto Link supervision TO in multiple of 10ms + **************************************************************************************** + */ +void lld_util_max_lat_compute(struct ea_elt_tag *elt, uint16_t lsto); +#endif //(BLE_PERIPHERAL || BLE_CENTRAL) + +/// @} LLDUTIL + +#endif // LLD_UTIL_H_ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/lld/lld_wlcoex.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/lld/lld_wlcoex.h new file mode 100755 index 0000000..6b3822b --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/lld/lld_wlcoex.h @@ -0,0 +1,77 @@ +/** +**************************************************************************************** +* +* @file lld_wlcoex.h +* +* @brief Wireless LAN Coexistence mailbox functions +* +* Copyright (C) RivieraWaves 2009-2015 +* +* +**************************************************************************************** +*/ +#ifndef LLD_WLCOEX_H_ +#define LLD_WLCOEX_H_ +/** +**************************************************************************************** +* @defgroup LDWLCOEX WIFI Coexistence +* @ingroup LD +* @brief Responsible for WIFI coexistence. +* @{ +**************************************************************************************** +*/ + +/* + * CONSTANT DEFINTIONS + **************************************************************************************** + */ +#if (RW_BLE_WLAN_COEX) || (RW_BLE_MWS_COEX) +/// Coexistence disabled +#define BLECOEX_DISABLED 0 +/// Coexistence enabled +#define BLECOEX_ENABLED 1 + +/// Coexistence Definitions +#define BLEMPRIO_CONREQ 0 +#define BLEMPRIO_LLCP 1 +#define BLEMPRIO_DATA 2 +#define BLEMPRIO_INITSC 3 +#define BLEMPRIO_ACTSC 4 +#define BLEMPRIO_CONADV 5 +#define BLEMPRIO_NCONADV 6 +#define BLEMPRIO_PASSC 7 +#define BLEMPRIO_DFT 15 +#endif // (RW_BLE_WLAN_COEX) || (RW_BLE_MWS_COEX) + + +/* + * FUNCTION PROTOTYPES + **************************************************************************************** + */ +#if (RW_BLE_WLAN_COEX) +/** + **************************************************************************************** + * @brief Enable/Disable the Wireless LAN coexistence interface. + * + * @param[in] CoexSetting Coexistence value + * + **************************************************************************************** + */ +void lld_wlcoex_set(bool en); +#endif // RW_BLE_WLAN_COEX + +#if (RW_BLE_MWS_COEX) +/** + **************************************************************************************** + * @brief Enable/Disable the MWS coexistence interface. + * + * @param[in] en Enable=true/Disable=false + * + **************************************************************************************** + */ +void lld_mwscoex_set(bool en); +#endif // RW_BLE_MWS_COEX + +///@} LLDWLCOEX + +#endif // LLD_WLCOEX_H_ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/llm/llm.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/llm/llm.h new file mode 100755 index 0000000..345a315 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/llm/llm.h @@ -0,0 +1,1013 @@ +/** + **************************************************************************************** + * + * @file llm.h + * + * @brief Main API file for the Link Layer manager + * + * Copyright (C) RivieraWaves 2009-2015 + * + **************************************************************************************** + */ + +#ifndef LLM_H_ +#define LLM_H_ + +/** + **************************************************************************************** + * @addtogroup CONTROLLER + * @ingroup ROOT + * @brief BLE Lower Layers + * + * The CONTROLLER contains the modules allowing the physical link establishment, + * maintenance and management. + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @addtogroup LLM LLM + * @ingroup CONTROLLER + * @brief Link Layer Manager + * + * The link layer manager contains the modules allowing the physical link establishment, + * and all the non-connected states. + * @{ + **************************************************************************************** + */ + + + + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "common_bt.h" +#include "common_math.h" +#include "common_utils.h" +#include "em_buf.h" +#include "llm_task.h" +#include "rwip.h" +#include "ea.h" + +/* + * DEFINES + **************************************************************************************** + */ + + +/// Maximum authorized RPA Timeout +#define LLM_RPA_TIMEOUT_MAX (0xA1B8) +/// Default RPA Timeout +#define LLM_RPA_TIMEOUT_DEFAULT (0x0384) + +/// LLM_P256_BYTE_TIMOUT +#define LLM_P256_BYTE_TIMOUT (0x0010) + + +/// Enhanced Privacy 1.2 info +/// 7 6 5 4 3 2 1 0 +/// +--+--+--+--+--+--+--+--+ +/// | RFU |TO|EN| +/// +--+--+--+--+--+--+--+--+ +enum llm_enh_priv +{ + /// - [7:1]: RFU + LLM_PRIV_RFU_MASK = 0x8C, + LLM_PRIV_RFU_LSB = 2, + + /// - [1]: Resolving Private Address Renewal timer started + LLM_RPA_RENEW_TIMER_EN_MASK = 0x02, + LLM_RPA_RENEW_TIMER_EN_LSB = 1, + + /// - [0]: Enable/Disable Privacy Flag + LLM_PRIV_ENABLE_MASK = 0x01, + LLM_PRIV_ENABLE_LSB = 0, +}; + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ +/// Advertising parameters +struct advertising_pdu_params +{ + /// Pointer on the data adv request + struct kernel_msg *adv_data_req; + /// Pointer on the scan response request + struct kernel_msg *scan_rsp_req; + /// Pointer of the ADV_X_IND descriptor + struct em_buf_node *adv_desc_node; + /// Pointer of the SCAN_RSP descriptor + struct em_buf_node *scan_rsp_desc_node; + /// Peer address + struct bd_addr peer_addr; + /// Connection interval min + uint16_t intervalmin; + /// Connection interval max + uint16_t intervalmax; + /// Channel mapping + uint8_t channelmap; + /// Filtering policy + uint8_t filterpolicy; + /// Advertising type + uint8_t type; + /// Data length + uint8_t datalen; + /// Scan RSP length + uint8_t scanrsplen; + /// Local address type + uint8_t own_addr_type; + /// Peer address type + uint8_t peer_addr_type; + /// Advertising frequency: true for low duty cycle, false for high duty cycle + bool adv_ldc_flag; +}; + +///Scanning parameters +struct scanning_pdu_params +{ + /// Pointer of the CONNECT_REQ and SCAN_REQ descriptor + struct em_buf_node *conn_req_desc_node; + /// Scan interval + uint16_t interval; + /// Scan window + uint16_t window; + /// Filtering policy + uint8_t filterpolicy; + /// Scanning type + uint8_t type; + /// Duplicate the advertising report + uint8_t filter_duplicate; + /// Local address type + uint8_t own_addr_type; + + ///Scanning channel map, add by hengzhang for fixed channel scan + uint8_t channel_map; +}; + +///Access address generation structure +struct access_addr_gen +{ + /// random + uint8_t intrand; + /// index 1 + uint8_t ct1_idx; + /// index 2 + uint8_t ct2_idx; +}; + +/// Advertising report list +struct adv_device_list +{ + /// Header + struct common_list_hdr hdr; + /// Advertising type + uint8_t adv_type; + /// Advertising device address + struct bd_addr adv_addr; +}; + +//advertising pdu +///structure adv undirected +struct llm_pdu_adv +{ + /// advertising address + struct bd_addr adva; + /// advertising data + uint8_t *adva_data; +}; +///structure adv directed +struct llm_pdu_adv_directed +{ + /// advertising address + struct bd_addr adva; + /// initiator address + struct bd_addr inita; +}; + +//scanning pdu +///structure scan request +struct llm_pdu_scan_req +{ + /// scanning address + struct bd_addr scana; + /// advertising address + struct bd_addr adva; +}; +///structure scan response +struct llm_pdu_scan_rsp +{ + /// advertising address + struct bd_addr adva; + /// scan response data + uint8_t *scan_data; + +}; +///initiating pdu +///structure connection request reception +struct llm_pdu_con_req_rx +{ + /// initiator address + struct bd_addr inita; + /// advertiser address + struct bd_addr adva; + /// access address + struct access_addr aa; + /// CRC init + struct crc_init crcinit; + /// window size + uint8_t winsize; + /// window offset + uint16_t winoffset; + /// interval + uint16_t interval; + /// latency + uint16_t latency; + /// timeout + uint16_t timeout; + /// channel mapping + struct le_chnl_map chm; + /// hopping + uint8_t hop_sca; +}; +///structure connection request transmission +struct llm_pdu_con_req_tx +{ + /// access address + struct access_addr aa; + /// CRC init + struct crc_init crcinit; + /// window size + uint8_t winsize; + /// window offset + uint16_t winoffset; + /// interval + uint16_t interval; + /// latency + uint16_t latency; + /// timeout + uint16_t timeout; + /// channel mapping + struct le_chnl_map chm; + /// hopping + uint8_t hop_sca; +}; + +///structure for the test mode +struct llm_test_mode +{ + /// flag indicating the end of test + bool end_of_tst; + /// Direct test type + uint8_t directtesttype; +}; + +#if (BLE_CENTRAL || BLE_PERIPHERAL || BLE_MESH) +#if (SECURE_CONNECTIONS) +typedef enum t_key_multiplication_type +{ + LLM_ECC_IDLE = 0, + LLM_PUBLIC_KEY_GENERATION = 1, + LLM_DHKEY_GENERATION = 2 +} t_key_multi_type; + +typedef struct t_public_key256 +{ + uint8_t x[PUBLIC_KEY_P256_LEN]; + uint8_t y[PUBLIC_KEY_P256_LEN]; +} t_public_key256; +#endif // (SECURE_CONNECTIONS) +#endif //(BLE_CENTRAL || BLE_PERIPHERAL || BLE_MESH) + +#if (BLE_CENTRAL || BLE_PERIPHERAL) +///structure for the data length extension +struct data_len_ext +{ + ///the value of connMaxTxOctets that the Controller will use for a new connection. + uint16_t conn_initial_max_tx_octets; + ///the value of connMaxTxTime that the Controller will use for a new connection. + uint16_t conn_initial_max_tx_time; + ///the maximum value of connMaxTxOctets that the Controller supports. + uint16_t suppted_max_tx_octets; + ///the maximum value of connMaxTxTime that the Controller supports. + uint16_t suppted_max_tx_time; + ///the maximum value of connMaxRxOctets that the Controller supports. + uint16_t suppted_max_rx_octets; + ///the maximum value of connMaxRxTime that the Controller supports. + uint16_t suppted_max_rx_time; +}; +#if (BLE_2MBPS) +struct phys_tag +{ + ///the preference among the PHYs that the Controller supports in a given direction. + uint8_t rate_preference; + ///the value of the transmitter PHYs that the Host prefers the Controller to use. + uint8_t conn_initial_rate_tx; + ///the value of the receiver PHYs that the Host prefers the Controller to use. + uint8_t conn_initial_rate_rx; +}; +#endif // (BLE_2MPBS) + +///Structure for the channel map assessment +struct channel_map_assess +{ + /// Assessment timer (second) + uint16_t assess_timer; + /// Lower limit of the receiver quality casted + int8_t lower_limit; + /// Upper limit of the receiver quality casted + int8_t upper_limit; + /// Noise RSSI + int8_t rssi_noise_limit; + /// Re-assessment counter (nb of assessment timer expiration) + uint8_t reassess_count; + ///current channel map + struct le_chnl_map ch_map; + ///protection for the command + bool llm_le_set_host_ch_class_cmd_sto; +}; +#endif + +/// LLM environment structure to be saved +struct llm_le_env_tag +{ + /// List of encryption requests + struct common_list enc_req; + +#if (BLE_CENTRAL || BLE_OBSERVER) + /// Advertising reports filter policy + struct common_list adv_list; + + /// Scanning parameters + struct scanning_pdu_params *scanning_params; +#endif //(BLE_CENTRAL || BLE_OBSERVER) + +#if (BLE_BROADCASTER || BLE_PERIPHERAL) + /// Advertising parameters + struct advertising_pdu_params *advertising_params; +#endif //(BLE_BROADCASTER || BLE_PERIPHERAL) + +#if (BLE_CENTRAL || BLE_PERIPHERAL) + /// Connected bd address list + struct common_list cnx_list; + + /// Data length extension values + struct data_len_ext data_len_val; + + /// Channel Assessment structure environment + struct channel_map_assess ch_map_assess; + +#if (BLE_2MBPS) + /// 2MPBS PHY values + struct phys_tag phys_val; +#endif // (BLE_2MBPS) +#endif //(BLE_CENTRAL || BLE_PERIPHERAL) + + /// Event mask + struct evt_mask eventmask; + + /// Access address + struct access_addr_gen aa; + + /// conhdl_allocated + uint16_t conhdl_alloc; + + /// Element + struct ea_elt_tag *elt; + + ///encryption pending + bool enc_pend; + + ///test mode + struct llm_test_mode test_mode; + + /// random bd_address + struct bd_addr rand_add; + + /// public bd_address + struct bd_addr public_add; + + /// Resolvable private address renew timeout + uint16_t enh_priv_rpa_timeout; + +#if (BLE_CENTRAL || BLE_PERIPHERAL || BLE_MESH) +#if (SECURE_CONNECTIONS) + /// The time between the processing of each byte in a P-256 calculation + uint16_t p256_byte_process_timeout; +#endif // (SECURE_CONNECTIONS) +#endif // (BLE_CENTRAL || BLE_PERIPHERAL || BLE_MESH) + + /// Stop command deferred opcode and state + uint16_t opcode; + uint8_t state; + + /// Enhanced Privacy 1.2 info (@see enum llm_enh_priv) + /// - [7:1]: RFU + /// - [0]: Enable/Disable Privacy Flag + uint8_t enh_priv_info; + + /// current @type in the register + uint8_t curr_addr_type; + + /// number of devices in WL + uint8_t nb_dev_in_wl; + /// number of devices in WL written in HW (not in Black List) + uint8_t nb_dev_in_hw_wl; + +#if (BLE_CENTRAL || BLE_PERIPHERAL || BLE_MESH) +#if (SECURE_CONNECTIONS) + t_public_key256 public_key256; + uint8_t secret_key256[32]; + t_key_multi_type cur_ecc_multiplication; +#endif // (SECURE_CONNECTIONS) +#endif // (BLE_CENTRAL || BLE_PERIPHERAL || BLE_MESH) + + ///Boolean to avoid having buffer full (non encrypted link) and SW encrypt at the same time which lead an error + bool enc_postponed; + +}; + +extern const struct supp_cmds llm_local_cmds; +extern const struct le_features llm_local_le_feats; +extern const struct le_states llm_local_le_states; +#if (BLE_CENTRAL || BLE_PERIPHERAL) +extern const struct data_len_ext llm_local_data_len_values; +#endif + +/* + * DEFINES + **************************************************************************************** + */ +/// Advertising channel TX power +#define LLM_ADV_CHANNEL_TXPWR rwip_rf.txpwr_max + +/// Advertising set parameters range min +#define LLM_ADV_INTERVAL_MIN 32//(0x20) +/// Advertising set parameters range max +#define LLM_ADV_INTERVAL_MAX 16384//(0x4000) + +/// Scanning set parameters range min +#define LLM_SCAN_INTERVAL_MIN 4//(0x4) +/// Scanning set parameters range max +#define LLM_SCAN_INTERVAL_MAX 16384//(0x4000) + +/// Scanning set parameters range min +#define LLM_SCAN_WINDOW_MIN 4//(0x4) +/// Scanning set parameters range max +#define LLM_SCAN_WINDOW_MAX 16384//(0x4000) + + +/// In case where the adv_type is set to non connectable or discoverable +#define LLM_ADV_INTERVAL_MIN_NONCON_DISC 160 //(0xA0) + +/// Time out value for the advertising direct event +#define LLM_LE_ADV_TO_DIRECTED 1024 //10,24 s -> 1024 ticks(10ms) + +/// Default value for the number of advertising report +#define LLM_LE_ADV_REPORT_DFT 0x1 + +/// Frequency max for the receiver test mode +#define RX_TEST_FREQ_MAX 39 + +/// Size maximum for the receiver test mode +#define RX_TEST_SIZE_MAX 255 + +/// Number max of good channel +#define LE_NB_CH_MAP_MAX 37 + +/// default irq interrupt threshold +#define RX_THR_DFT 1 + +/// Index dedicated for the advertising pdu +enum +{ + LLM_LE_ADV_DUMMY_IDX = (BLE_TX_DESC_CNTL - 1), +#if (BLE_OBSERVER || BLE_PERIPHERAL || BLE_CENTRAL) + LLM_LE_SCAN_CON_REQ_ADV_DIR_IDX, +#endif // BLE_OBSERVER || BLE_PERIPHERAL || BLE_CENTRAL +#if (BLE_BROADCASTER || BLE_PERIPHERAL) + LLM_LE_SCAN_RSP_IDX, +#endif // BLE_BROADCASTER || BLE_PERIPHERAL + LLM_LE_ADV_IDX +}; + + +/// Advertising Access Address +#define LLM_LE_ADV_AA 0x8E89BED6 + +/// Scanning default interval (10ms) +#define LLM_LE_SCAN_INTERV_DFLT 16 //(0X10) + +/// Advertising default interval (1,28s) +#define LLM_LE_ADV_INTERV_DFLT 2048 //(0X800) + +/// Advertising default channel map (ch37, ch38, ch39) +#define LLM_LE_ADV_CH_MAP_DFLT 0X7 + +#if !(BLE_QUALIF) +/// Features byte 0 +/* +#define BLE_FEATURES_BYTE0 ( BLE_ENC_FEATURE | BLE_CON_PARAM_REQ_PROC_FEATURE | BLE_REJ_IND_EXT_FEATURE | BLE_SLAVE_INIT_EXCHG_FEATURE | BLE_PING_FEATURE\ + | BLE_LENGTH_EXT_FEATURE | BLE_LL_PRIVACY_FEATURE | BLE_EXT_SCAN_POLICY_FEATURE) +*/ +#define BLE_FEATURES_BYTE0 ( BLE_ENC_FEATURE | BLE_CON_PARAM_REQ_PROC_FEATURE | BLE_REJ_IND_EXT_FEATURE | BLE_SLAVE_INIT_EXCHG_FEATURE | BLE_PING_FEATURE\ + | BLE_LENGTH_EXT_FEATURE | BLE_LL_PRIVACY_FEATURE | BLE_EXT_SCAN_POLICY_FEATURE) +/// Features byte 1 +#if (BLE_2MBPS) +#define BLE_FEATURES_BYTE1 ( BLE_2MBPS_FEATURE | BLE_STABLE_MOD_FEATURE) +#else // !(BLE_2MBPS) +/// Features byte 1 +#define BLE_FEATURES_BYTE1 0x00 +#endif //(BLE_2MBPS) +#else +/// Features byte 0 +#define BLE_FEATURES_BYTE0 ( BLE_ENC_FEATURE) +/// Features byte 1 +#define BLE_FEATURES_BYTE1 0x00 +#endif + +/// Features byte 2 +#define BLE_FEATURES_BYTE2 0x00 +/// Features byte 3 +#define BLE_FEATURES_BYTE3 0x00 +/// Features byte 4 +#define BLE_FEATURES_BYTE4 0x00 +/// Features byte 5 +#define BLE_FEATURES_BYTE5 0x00 +/// Features byte 6 +#define BLE_FEATURES_BYTE6 0x00 +/// Features byte 7 +#define BLE_FEATURES_BYTE7 0x00 + +/// States byte 0 +#define BLE_STATES_BYTE0 ( BLE_NON_CON_ADV_STATE | BLE_DISC_ADV_STATE\ + | BLE_CON_ADV_STATE | BLE_HDC_DIRECT_ADV_STATE\ + | BLE_PASS_SCAN_STATE | BLE_ACTIV_SCAN_STATE\ + | BLE_INIT_MASTER_STATE | BLE_CON_SLAVE_STATE) +#if !(BLE_QUALIF) +/// States byte 1 +#define BLE_STATES_BYTE1 ( BLE_NON_CON_ADV_PASS_SCAN_STATE | BLE_DISC_ADV_PASS_SCAN_STATE\ + | BLE_CON_ADV_PASS_SCAN_STATE | BLE_HDC_DIRECT_ADV_PASS_SCAN_STATE\ + | BLE_NON_CON_ADV_ACTIV_SCAN_STATE | BLE_DISC_ADV_ACTIV_SCAN_STATE\ + | BLE_CON_ADV_ACTIV_SCAN_STATE | BLE_HDC_DIRECT_ADV_ACTIV_SCAN_STATE) + +/// States byte 2 +#define BLE_STATES_BYTE2 ( BLE_NON_CON_ADV_INIT_STATE | BLE_DISC_ADV_INIT_STATE\ + | BLE_NON_CON_ADV_MASTER_STATE | BLE_DISC_ADV_MASTER_STATE\ + | BLE_NON_CON_ADV_SLAVE_STATE | BLE_DISC_ADV_SLAVE_STATE\ + | BLE_PASS_SCAN_INIT_STATE | BLE_ACTIV_SCAN_INIT_STATE) + +/// States byte 3 +#define BLE_STATES_BYTE3 ( BLE_PASS_SCAN_MASTER_STATE | BLE_ACTIV_SCAN_MASTER_STATE\ + | BLE_PASS_SCAN_SLAVE_STATE | BLE_ACTIV_SCAN_SLAVE_STATE\ + | BLE_INIT_MASTER_MASTER_STATE | BLE_LDC_DIRECT_ADV_STATE\ + | BLE_LDC_DIRECT_ADV_PASS_SCAN_STATE | BLE_LDC_DIRECT_ADV_ACTIV_SCAN_STATE) + +/// States byte 4 +#define BLE_STATES_BYTE4 ( BLE_CON_ADV_INIT_MASTER_SLAVE_STATE | BLE_HDC_DIRECT_ADV_INIT_MASTER_SLAVE_STATE\ + | BLE_LDC_DIRECT_ADV_INIT_MASTER_SLAVE_STATE | BLE_CON_ADV_MASTER_SLAVE_STATE\ + | BLE_HDC_DIRECT_ADV_MASTER_SLAVE_STATE | BLE_LDC_DIRECT_ADV_MASTER_SLAVE_STATE\ + | BLE_CON_ADV_SLAVE_SLAVE_STATE | BLE_HDC_DIRECT_ADV_SLAVE_SLAVE_STATE) + +/// States byte 5 +#define BLE_STATES_BYTE5 ( BLE_LDC_DIRECT_ADV_SLAVE_SLAVE_STATE | BLE_INIT_MASTER_SLAVE_STATE) +#else +/// States byte 1 +#define BLE_STATES_BYTE1 0x0 + +/// States byte 2 +#define BLE_STATES_BYTE2 ( BLE_NON_CON_ADV_MASTER_STATE | BLE_DISC_ADV_MASTER_STATE\ + | BLE_NON_CON_ADV_SLAVE_STATE | BLE_DISC_ADV_SLAVE_STATE) + +/// States byte 3 +#define BLE_STATES_BYTE3 ( BLE_PASS_SCAN_MASTER_STATE | BLE_ACTIV_SCAN_MASTER_STATE\ + | BLE_PASS_SCAN_SLAVE_STATE | BLE_ACTIV_SCAN_SLAVE_STATE\ + | BLE_INIT_MASTER_MASTER_STATE) + +/// States byte 4 +#define BLE_STATES_BYTE4 0x0 + +/// States byte 5 +#define BLE_STATES_BYTE5 0x0 +#endif +/// States byte 6 +#define BLE_STATES_BYTE6 0x0 +/// States byte 7 +#define BLE_STATES_BYTE7 0x0 + +///Le Initiating enables +enum +{ + INIT_DIS = 0x00, + INIT_EN, + INIT_EN_END +}; +///Le Direct test types +enum +{ + TEST_TX = 0x00, + TEST_RX, + TEST_RXTX, + TEST_END +}; + + +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ +extern struct llm_le_env_tag llm_le_env; + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ +/** + **************************************************************************************** + * @brief Initialization of the BLE LLM task + * + * This function initializes the the LLC task, as well as the environment of the LLM + * + **************************************************************************************** + */ +void llm_init(bool reset); + +/** + **************************************************************************************** + * @brief Sends the NOP event. + * + * This function sends the No Operation command completed event to the host when all the + * Initializations are done. + * + **************************************************************************************** + */ +void llm_ble_ready(void); + +/** + **************************************************************************************** + * @brief Handle the command clear the white list. + * + * This function clear the public and private white lists. + * + **************************************************************************************** + */ +void llm_wl_clr(void); + +/** + **************************************************************************************** + * @brief Handle the command set advertising parameters. + * + * This function checks the parameters , fulfill the advertising packet with the useful + * parameters + * + * @param[in] param Pointer on the structure which contains all the parameters + * needed to setup the advertising mode. + * + * @return The status of the parameters validity + * + **************************************************************************************** + */ +uint8_t llm_set_adv_param(struct hci_le_set_adv_param_cmd const *param); + +/** + **************************************************************************************** + * @brief Handle the command set advertising data. + * + * This function checks the parameters , fulfill the advertising packet with the data + * + * @param[in] param Pointer on the structure which contains all the parameters + * needed to setup the advertising data. + * + * @return The status of the parameters validity + * + **************************************************************************************** + */ +#if (BLE_BROADCASTER || BLE_PERIPHERAL) +uint8_t llm_set_adv_data(struct hci_le_set_adv_data_cmd const *param); +#endif + +/** + **************************************************************************************** + * @brief Handle the command set advertising enable. + * + * This function checks the parameters , starts or stops the requested advertising mode. + * + * @param[in] param Pointer on the structure which contains all the parameters + * needed to start or stop the advertising mode. + * + * @return The status of the parameters validity + * + **************************************************************************************** + */ +uint8_t llm_set_adv_en(struct hci_le_set_adv_en_cmd const *param); + +/** + **************************************************************************************** + * @brief Handle the command set scanning parameters. + * + * This function checks the parameters , fulfill the scanning packet with the useful + * parameters + * + * @param[in] param Pointer on the structure which contains all the parameters + * needed to setup the scanning mode. + * + * @return The status of the parameters validity + * + **************************************************************************************** + */ +uint8_t llm_set_scan_param(struct hci_le_set_scan_param_cmd const *param); + +/** + **************************************************************************************** + * @brief Handle the command set scanning enable. + * + * This function checks the parameters , starts or stops the requested scanning mode. + * + * @param[in] param Pointer on the structure which contains all the parameters + * needed to start or stop the scanning mode. + * + * @return The status of the parameters validity + * + **************************************************************************************** + */ +uint8_t llm_set_scan_en(struct hci_le_set_scan_en_cmd const *param); + +/** + **************************************************************************************** + * @brief Handle the command set scanning response data. + * + * This function checks the parameters , fulfill the scanning packet with the data + * + * @param[in] param Pointer on the structure which contains all the parameters + * needed to setup the scanning response data. + * + * @return The status of the parameters validity + * + **************************************************************************************** + */ +uint8_t llm_set_scan_rsp_data(struct hci_le_set_scan_rsp_data_cmd const *param); + +/** + **************************************************************************************** + * @brief Handle the command start transmit test mode. + * + * This function checks the parameters , set the transmit mode parameters, turn on the + * mode and set the LLM state. + * + * @param[in] param Pointer on the structure which contains all the parameters + * needed to setup the transmit test mode. + * @param[in] msgid Type of the command Legacy or Enhanced test mode + * + * @return The status of the parameters validity + * + **************************************************************************************** + */ +uint8_t llm_test_mode_start_tx(void const *param, kernel_msg_id_t const msgid); + +/** + **************************************************************************************** + * @brief Handle the command start receive test mode. + * + * This function checks the parameters , set the receive mode parameters, turn on the + * mode and set the LLM state. + * + * @param[in] param Pointer on the structure which contains all the parameters + * needed to setup the receive test mode. + * @param[in] msgid Type of the command Legacy or Enhanced test mode + * + * @return The status of the parameters validity + * + **************************************************************************************** + */ +uint8_t llm_test_mode_start_rx(void const *param, kernel_msg_id_t const msgid); + +/** + **************************************************************************************** + * @brief Handle the command add device in the white list. + * + * This function adds the device in the white list, according to the type (public or + * private) + * + * @param[in] bd_addr BLE Address value + * @param[in] bd_addr_type BLE Address type + * + * @return The status of the parameters validity + * + **************************************************************************************** + */ +uint8_t llm_wl_dev_add_hdl(struct bd_addr *bd_addr, uint8_t bd_addr_type); + +/** + **************************************************************************************** + * @brief Handle the command remove device in the white list. + * + * This function removes the device in the white list, according to the type (public or + * private) + * + * @param[in] bd_addr BLE Address value + * @param[in] bd_addr_type BLE Address type + * + * @return The status of the parameters validity + * + **************************************************************************************** + */ +uint8_t llm_wl_dev_rem_hdl(struct bd_addr *bd_addr, uint8_t bd_addr_type); + +/** + **************************************************************************************** + * @brief Add a device in HW white list + * + * @param[in] bd_addr BLE Address value + * @param[in] bd_addr_type BLE Address type + * + **************************************************************************************** + */ +void llm_wl_dev_add(struct bd_addr *bd_addr, uint8_t bd_addr_type); + +/** + **************************************************************************************** + * @brief Remove a device from HW white list + * + * @param[in] bd_addr BLE Address value + * @param[in] bd_addr_type BLE Address type + * + **************************************************************************************** + */ +void llm_wl_dev_rem(struct bd_addr *bd_addr, uint8_t bd_addr_type); + +/** + **************************************************************************************** + * @brief Handle the command create connection. + * + * This function checks the parameters, fulfill the connect_req pdu with the useful + * parameters, changes the state of the LLM task and requests the LLD to schedule the + * connection initiation. + * + * @param[in] param Pointer on the structure which contains all the parameters + * needed to create the link. + * + * @return The status of the parameters validity + * + **************************************************************************************** + */ +uint8_t llm_create_con(struct hci_le_create_con_cmd const *param); + +/** + **************************************************************************************** + * @brief Handle the command start encryption. + * + * This function sets the key and the data to be encrypted in the encryption engine and + * start it. + * + * @param[in] param Pointer on the structure which contains all the parameters + * needed to star tthe encryption engine. + * + **************************************************************************************** + */ +void llm_encryption_start(struct llm_enc_req const *param); + +/** + **************************************************************************************** + * @brief Handle the end of the encryption process. + * + * This function provide to the host or the LLC the data encrypted by the engine. + * + **************************************************************************************** + */ +void llm_encryption_done(void); + +/** + **************************************************************************************** + * @brief Sends the command complete event. + * + * This function notify the host that the command is completed. + * + * @param[in] opcode Command opcode + * @param[in] status Status on the completion of the command. + **************************************************************************************** + */ +void llm_common_cmd_complete_send(uint16_t opcode, uint8_t status); + +/** + **************************************************************************************** + * @brief Sends the command status event. + * + * This function notify the host that the command is understood. + * + * @param[in] opcode Command opcode + * @param[in] status Status on the completion of the command. + **************************************************************************************** + */ +void llm_common_cmd_status_send(uint16_t opcode, uint8_t status); + +/** + **************************************************************************************** + * @brief Handles the connection request pdu. + * + * This function extracts the parameters from the packet received and takes the + * associated actions (new pdu generation, new state , parameters update, etc...). + * + * @param[in] rxdesc Pointer on the received pdu packet. + * @param[in] status Packet status bit field + * + **************************************************************************************** + */ +void llm_con_req_ind(uint8_t rx_hdl, uint16_t status); + +#if (BLE_CENTRAL || BLE_OBSERVER) +/** + **************************************************************************************** + * @brief Handles the advertising packet. + * + * This function extracts the parameters from the advertising packet received and + * generates the event if needed + * + * @param[in] rxdesc Pointer on the received advertising packet. + * + **************************************************************************************** + */ +void llm_le_adv_report_ind(uint8_t rx_hdl); +#endif // BLE_CENTRAL || BLE_OBSERVER + +/** + **************************************************************************************** + * @brief Handles the transmission confirmation of the packet. + * + * This function sends the connection complete event to the host and start the LLC task + * for the dedicated conhdl. + * + * @param[in] rx_hdl Handle on the received advertising packet who has generated + * the sending of the connect_req pdu. + * + **************************************************************************************** + */ +void llm_con_req_tx_cfm(uint8_t rx_hdl); + +/** + **************************************************************************************** + * @brief Clear the resolution address list + **************************************************************************************** + */ +void llm_ral_clear(void); + + +/** + **************************************************************************************** + * @brief Add A device into resolving address list + * + * @param[in] param command parameters + * + * @return status of the request + **************************************************************************************** + */ +uint8_t llm_ral_dev_add(struct hci_le_add_dev_to_rslv_list_cmd *param); + +/** + **************************************************************************************** + * @brief Remove a device from resolving address list + * + * @param[in] param command parameters + * + * @return status of the request + **************************************************************************************** + */ +uint8_t llm_ral_dev_rm(struct hci_le_rmv_dev_from_rslv_list_cmd *param); + + +/** + **************************************************************************************** + * @brief Retrieve value of peer or local Resolvable Private Address (RPA) + * + * @param[in] param command parameters + * @param[out] addr RPA found + * @param[in] local True to retrieve local RPA, else peer RPA + * + * @return status of the request + **************************************************************************************** + */ +uint8_t llm_ral_get_rpa(struct hci_le_rd_loc_rslv_addr_cmd *param, struct bd_addr *addr, bool local); + +/** + **************************************************************************************** + * @brief Modify Resolvable Private Address Renew Timeout duration + * + * @param[in] param command parameters + * + * @return status of the request + **************************************************************************************** + */ +uint8_t llm_ral_set_timeout(struct hci_le_set_rslv_priv_addr_to_cmd *param); + + +/** + **************************************************************************************** + * @brief Update state of the enhanced privacy + **************************************************************************************** + */ +void llm_ral_update(void); + +/// @} LLM + +#endif // LLM_H_ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/llm/llm_task.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/llm/llm_task.h new file mode 100755 index 0000000..37c8609 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/llm/llm_task.h @@ -0,0 +1,154 @@ +/** + **************************************************************************************** + * + * @file llm_task.h + * + * @brief LLM task header file + * + * Copyright (C) RivieraWaves 2009-2015 + * + **************************************************************************************** + */ + +#ifndef LLM_TASK_H_ +#define LLM_TASK_H_ + +/** + **************************************************************************************** + * @addtogroup LLMTASK LLMTASK + * @ingroup LLM + * @brief Link Layer Manager Task + * + * The LLM task is responsible for managing link layer actions not related to a + * specific connection with a peer (e.g. scanning, advertising, etc.). It implements the + * state machine related to these actions. + * + * @{ + **************************************************************************************** + */ + + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_config.h" // stack configuration +#include +#include "common_bt.h" +#include "rwip_task.h" // Task definitions +#include "kernel_task.h" // Task informations + +/* + * INSTANCES + **************************************************************************************** + */ +/// Maximum number of instances of the LLM task +#define LLM_IDX_MAX 1 + +/// LE events subcodes +#define LLM_LE_EVT_ADV_REPORT 0x02 +/* + * STATES + **************************************************************************************** + */ +/// Possible states of the LLM task +enum llm_state_id +{ + /// IDLE state + LLM_IDLE, + /// ADVERTISING state + LLM_ADVERTISING, + /// SCANNING state + LLM_SCANNING, + /// INITIATING state + LLM_INITIATING, + /// STOPPING state + LLM_STOPPING, + /// TEST states. + LLM_TEST, + /// Number of states. + LLM_STATE_MAX +}; + +/* + * MESSAGES + **************************************************************************************** + */ +/// Message API of the LLM task +enum llm_msg_id +{ + /* + * ************** Msg LLM->LLM**************** + */ + /// Time out message + /// to authorize the reception of the cmd + LLM_LE_SET_HOST_CH_CLASS_CMD_STO = TASK_FIRST_MSG(TASK_ID_LLM), + /// Request to initialize LLM + LLM_STOP_IND, + + /* + * ************** Msg LLM->LLC**************** + */ + /// request changing map + LLM_LE_SET_HOST_CH_CLASS_REQ, + /// channel map req indication + LLM_LE_SET_HOST_CH_CLASS_REQ_IND, + /* + * ************** Msg LLC->LLM**************** + */ + /// link layer disconnection indication + LLM_ENC_REQ, + LLM_ENC_IND, + +#if SECURE_CONNECTIONS +#if (BLE_CENTRAL || BLE_PERIPHERAL || BLE_MESH) + /* + * ************** Msg ECC->LLM**************** + */ + LLM_ECC_RESULT_IND, +#endif //(BLE_CENTRAL || BLE_PERIPHERAL || BLE_MESH) +#endif //SECURE_CONNECTIONS + + /* + * ************** Channel Assessment ******** + */ + /// Channel Assessment Timer + LLM_LE_CHNL_ASSESS_TIMER, + /// Channel Assessment - Generate Channel classification + LLM_GEN_CHNL_CLS_CMD, + + /* + * **** Privacy 1.2 - Controller Privacy **** + */ + /// Enhanced privacy timer used to renew Local Resolving Private Addresses + LLM_LE_ENH_PRIV_ADDR_RENEW_TIMER, +}; + +///LLC Encrypt Request parameters structure +struct llm_enc_req +{ + ///Long term key structure + struct ltk key; + ///Pointer to buffer with plain data to encrypt - 16 bytes + uint8_t plain_data[16]; +}; + +///LLM LE Encrypt indication structure +struct llm_enc_ind +{ + /// Status of the command reception + uint8_t status; + ///Encrypted data to return to command source. + uint8_t encrypted_data[ENC_DATA_LEN]; +}; + +/* + * TASK DESCRIPTOR DECLARATIONS + **************************************************************************************** + */ +extern const struct kernel_state_handler llm_default_handler; +extern kernel_state_t llm_state[LLM_IDX_MAX]; + +/// @} LLMTASK + +#endif // LLM_TASK_H_ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/llm/llm_util.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/llm/llm_util.h new file mode 100755 index 0000000..bd43e9b --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/llm/llm_util.h @@ -0,0 +1,686 @@ +/** + **************************************************************************************** + * + * @file llm_util.h + * + * @brief Link layer manager utilities definitions + * + * Copyright (C) RivieraWaves 2009-2015 + * + **************************************************************************************** + */ + +#ifndef LLM_UTIL_H_ +#define LLM_UTIL_H_ + +/** + **************************************************************************************** + * @addtogroup LLMUTIL + * @ingroup LLM + * @brief Link layer manager utilities definitions + * + * full description + * + * @{ + **************************************************************************************** + */ + + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include +#include "ble_compiler.h" +#include "em_buf.h" +#include "common_endian.h" +#include "common_error.h" +#include "kernel_mem.h" +#include "reg_ble_em_rx_desc.h" +#include "reg_ble_em_tx_desc.h" +#include "reg_ble_em_cs.h" +#include "reg_blecore.h" +#include "llm.h" +#include "lld.h" +#if (HCI_PRESENT) +#include "hci.h" +#endif //(HCI_PRESENT) + + +/* + * DEFINES + **************************************************************************************** + */ +#if (BLE_CENTRAL && BLE_CHNL_ASSESS) +/// Default Channel Assessment Timer duration (1s - Multiple of 10ms) +#define LLM_UTIL_CH_ASSES_DFLT_TIMER_DUR (100) +/// When a command to change the channel map is sent we should process it within 10 sec (9sec) +#define LLM_UTIL_CH_ASSES_MAX_TIMER_DUR (900) +/// Default Channel Reassessment Timer duration (Multiple of Channel Assessment Timer duration) +#define LLM_UTIL_CH_ASSES_DFLT_REASS_CNT (8) +/// Default Minimal Threshold +#define LLM_UTIL_CH_ASSES_DFLT_MIN_THR (-10) +/// Default Maximum Threshold +#define LLM_UTIL_CH_ASSES_DFLT_MAX_THR (+10) +/// Default noise RSSI Threshold +#define LLM_UTIL_CH_ASSES_DFLT_NOISE_THR (-60) +#endif // (BLE_CENTRAL && BLE_CHNL_ASSESS) + +///Constant nibble to use as top 4 MSBs, to have at least 2 transitions +extern const uint8_t LLM_AA_CT1[3]; + +///Constant nibble to use in AA to get more than 1 bit different from Advertising AA +extern const uint8_t LLM_AA_CT2[2]; + +enum bl_flag_wl +{ + LLM_UTIL_BL_NO_ACTION_WL, + LLM_UTIL_BL_CLEAR_WL, + LLM_UTIL_BL_SET_WL +}; +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ +#if (BLE_CENTRAL && BLE_CHNL_ASSESS) +/** + **************************************************************************************** + * @brief Return the upper limit for the received quality(value set by the NVDS) + * + **************************************************************************************** + */ +__INLINE int8_t llm_util_ch_assess_get_upper_limit(void) +{ + return (llm_le_env.ch_map_assess.upper_limit); +}; +/** + **************************************************************************************** + * @brief Return the lower limit for the received quality (value set by the NVDS) + * + **************************************************************************************** + */ +__INLINE int8_t llm_util_ch_assess_get_lower_limit(void) +{ + return (llm_le_env.ch_map_assess.lower_limit); +}; +/** + **************************************************************************************** + * @brief Return the reassessment counter (value set by the NVDS) + * + **************************************************************************************** + */ +__INLINE uint8_t llm_util_ch_assess_get_reass_cnt(void) +{ + return (llm_le_env.ch_map_assess.reassess_count); +}; +/** + **************************************************************************************** + * @brief Return the RSSI threshold for a noiser (value set by the NVDS) + * + **************************************************************************************** + */ +__INLINE int8_t llm_util_ch_assess_get_rssi_noise(void) +{ + return (llm_le_env.ch_map_assess.rssi_noise_limit); +}; +/** + **************************************************************************************** + * @brief Return the assessment time (in multiple of 10ms) (value set by the NVDS) + * + **************************************************************************************** + */ +__INLINE uint16_t llm_util_ch_assess_get_assess_timer(void) +{ + return (llm_le_env.ch_map_assess.assess_timer); +}; +#endif //(BLE_CENTRAL && BLE_CHNL_ASSESS) + +/** + **************************************************************************************** + * @brief Checks if the channel map contains at least 1 channel + * + * This function checks if advertising or data channel map contains at least 1 channel. + * + * @param[in] channel_map Pointer on the channel map to be checked. + * @param[in] nb_octet number of octet(s) to be parsed. + * + * @return If the channel map is correct or not. + * + **************************************************************************************** + */ +uint8_t llm_util_check_map_validity(uint8_t *channel_map, uint8_t nb_octet); + + +/** + **************************************************************************************** + * Retrieve position of address in white list + * + * @param[in] bd_address BLE Address + * @param[in] bd_addr_type BLE Address type + * + * @return position of device or BLE_WHITELIST_MAX if not found + **************************************************************************************** + */ +uint16_t llm_util_bd_addr_wl_position(struct bd_addr const *bd_address, uint8_t bd_addr_type); + +/** + **************************************************************************************** + * @brief Checks if the device address is available in the white list. + * + * This function checks if the bd address if present in the WL and return the status + * + * @param[in] bd_address Pointer on the device address to be checked. + * @param[in] bd_address_type Type of the address .. + * @param[in/out] position Position in the White List. + * @param[out] in_black_list check if device is in black list or not + * + * @return If the device address has been found or not. + * + **************************************************************************************** + */ +bool llm_util_bd_addr_in_wl(struct bd_addr const *bd_address, uint8_t bd_addr_type, bool *in_black_list); + +/** + **************************************************************************************** + * @brief Checks the validity of the device address + * + * This function checks if the address type and value are available, no NULL, available + * in the WL, not the local one. + * + * @param[in] bd_address Pointer on the device address to be checked. + * @param[in] addr_type Type of the device address to be checked. + * + * @return If the device address is correct or not. + * + **************************************************************************************** + */ +uint8_t llm_util_check_address_validity( struct bd_addr *bd_address, uint8_t addr_type); + +/** + **************************************************************************************** + * @brief Apply the BD address + * + * This function applies the BD address corresponding to the current address type on the + * device. + * + * @param[in] addr_type Type of the requested address + * + **************************************************************************************** + */ +void llm_util_apply_bd_addr(uint8_t addr_type); + +/** + **************************************************************************************** + * @brief Set the public address + * + * @param[in] bd_addr Public address + **************************************************************************************** + */ +void llm_util_set_public_addr(struct bd_addr *bd_addr); + +extern uint8_t max_scan_numbers; + +#if (BLE_CENTRAL || BLE_OBSERVER) +/** + **************************************************************************************** + * @brief Check if the advertiser address has been already received. + * + * This function checks in case where the filtering is enabled if the address is already + * listed. + * + * @param[in] adv_bd_addr Pointer on the device address to be checked. + * @param[in] adv_type Type of the advertising report (ADV_IND, ADV., SCANRSP) + * + * @return If the device address has been found or not. + * + **************************************************************************************** + */ +__INLINE bool llm_util_check_adv_report_list(struct bd_addr *adv_bd_addr, uint8_t adv_type) +{ + // Get first ADV device in the list + struct adv_device_list *adv_device = (struct adv_device_list *)common_list_pick(&llm_le_env.adv_list); + // Returned status - Address not found by default + bool found = false; + + while (adv_device) + { + // Check BD Address + if (common_bdaddr_compare(adv_bd_addr, &adv_device->adv_addr)) + { + // Check Address Type + if (adv_device->adv_type == adv_type) + { + found = true; + break; + } + } + + // Get next ADV device + adv_device = (struct adv_device_list *)(adv_device->hdr.next); + } + + // If the device has not been found, add it + if (!found) + { + // Check number of element in the list + //if (common_list_size(&llm_le_env.adv_list) == BLE_DUPLICATE_FILTER_MAX) + if (common_list_size(&llm_le_env.adv_list) == max_scan_numbers) + { + // Consider the device as found + found = true; + } + else + { + // Allocate an adv device element + adv_device = (struct adv_device_list *)kernel_malloc(sizeof(struct adv_device_list), + KERNEL_MEM_ENV); + + // Saves the bd address in the adv filter list + memcpy(&adv_device->adv_addr.addr[0], &adv_bd_addr->addr[0], BD_ADDR_LEN); + // Save the type of the device address + adv_device->adv_type = adv_type; + + // Add the element at the end of the list + common_list_push_back(&llm_le_env.adv_list, &adv_device->hdr); + } + } + + return (found); +} + +/** + **************************************************************************************** + * @brief Set the default scan parameters values + * + * This function set the default values for the scan parameters + * + **************************************************************************************** + */ +__INLINE void llm_util_set_param_scan_dft(void) +{ + // Allocate a structure containing scan parameters + llm_le_env.scanning_params = (struct scanning_pdu_params *)kernel_malloc(sizeof(struct scanning_pdu_params), + KERNEL_MEM_ENV); + + // Disable filtering + llm_le_env.scanning_params->filterpolicy = SCAN_ALLOW_ADV_ALL; + // Set the scan interval to 10ms + llm_le_env.scanning_params->interval = LLM_LE_SCAN_INTERV_DFLT; + // Set the scan interval to scan_interv/2 + llm_le_env.scanning_params->window = LLM_LE_SCAN_INTERV_DFLT / 2; + // Set the scan mode to passive (no transmission) + llm_le_env.scanning_params->type = SCAN_BLE_PASSIVE; + // Disable the duplicate filtering + llm_le_env.scanning_params->filter_duplicate = SCAN_FILT_DUPLIC_DIS; +} +#endif //(BLE_CENTRAL || BLE_OBSERVER) + +/** +**************************************************************************************** +* @brief LLM function generating the Access Address for a new Link. +* +* The function will generate the following 4 bytes: +* |Byte 3 | Byte 2 | Byte 1 | Byte 0 | +* |CT1 | PRAND_4MSB | CT2 | PRAND_4LSB | CT2 | INCRAND_4MSB | CT2 | INCRAND_4LSB| +* +* For each new generated AA, +* - PRAND is a pseudo random 1 byte number. +* - INCRAND is an initially generated random number, increased by 1 for each AA +* - CT2 is toggled between the two values +* - CT1 is again toggled between the 3 possible values +* +* Considering the formats of CT1 and CT2, the rules for AA generation are respected: +* - since CT2 is put between bytes, and has two equal bits on each half, +* it ensures no more than 6 consecutive bits inside the address. CT1 also. +* +* - CT2 and CT1 ensure that the newly generated address is different and at least 1 bit +* different from the advertising access address +* +* - since CT1 != CT2 , the four bytes of the AA can never be equal +* +* - Since in a 32 bit number there are 31 transitions, and the neighboring equal bits +* in CT1 and CT2 represent 7 transitions, there can never be more than 31-7=24 +* transitions in the AA +* +* - The format of CT1 ensures at least two transitions in the most significant 6 bits. +* +* @param acc_addr Pointer to the 4 byte array space for the AA. +* +* +***************************************************************************************** +*/ +__INLINE void llm_util_aa_gen(uint8_t *acc_addr) +{ + //the pseudo random byte is generated every time - use a seed? + uint8_t prand = common_rand_byte(); + + //Create the AA - MSB to LSB + + acc_addr[0] = (LLM_AA_CT2[llm_le_env.aa.ct2_idx] << 4 ) | (llm_le_env.aa.intrand & 0x0F) | (1 << (prand & 3)); // ensures a 3rd bit set to 1 + acc_addr[1] = (LLM_AA_CT2[llm_le_env.aa.ct2_idx] << 4 ) | (llm_le_env.aa.intrand >> 4); + acc_addr[2] = (LLM_AA_CT2[llm_le_env.aa.ct2_idx] << 4 ) | (llm_le_env.conhdl_alloc & 0x0F); // ensures at least 1 bit different from & between Advertising AAs + acc_addr[3] = (LLM_AA_CT1[llm_le_env.aa.ct1_idx] << 4 ) | (prand >> 4) | (1 << (prand & 3)); // ensures no more than six consecutive 0s + + llm_le_env.aa.ct1_idx = (llm_le_env.aa.ct1_idx + 1) % 3; + llm_le_env.aa.ct2_idx = (llm_le_env.aa.ct2_idx + 1) % 2; + + //Increase random + llm_le_env.aa.intrand ++; + +} + +/** + **************************************************************************************** + * @brief Fulfills the payload for the transmit test mode. + * + * This function fulfills the payload for the transmit test mode. + * + * @param[in] pattern_type type of the pattern. + * @param[in] payload_len length of the payload. + * + **************************************************************************************** + */ +__INLINE void llm_util_gen_pattern(uint8_t pattern_type, uint8_t payload_len, + uint8_t *payload) +{ + uint8_t pattern = 0; + // get the pattern + switch (pattern_type) + { + case PAYL_11110000: + pattern = 0xF0; + break; + case PAYL_10101010: + pattern = 0xAA; + break; + case PAYL_ALL_1: + pattern = 0xFF; + break; + case PAYL_ALL_0: + pattern = 0x00; + break; + case PAYL_00001111: + pattern = 0x0F; + break; + case PAYL_01010101: + pattern = 0x55; + break; + default: + ASSERT_ERR(pattern_type < PAYL_END); + break; + } + // fulfill the payload + memset(payload, pattern, payload_len); + +} + +/** + **************************************************************************************** + * @brief Set the default advertising parameters values + * + * This function set the default values for the advertising parameters + * + **************************************************************************************** + */ +#if (BLE_PERIPHERAL || BLE_BROADCASTER) +__INLINE void llm_util_set_param_adv_dft(void) +{ + // Allocate a structure containing scan parameters + llm_le_env.advertising_params = (struct advertising_pdu_params *)kernel_malloc(sizeof(struct advertising_pdu_params), + KERNEL_MEM_ENV); + memset(llm_le_env.advertising_params, 0, sizeof(struct advertising_pdu_params)); + + // Disable filtering + llm_le_env.advertising_params->filterpolicy = ADV_ALLOW_SCAN_ANY_CON_ANY; + // Set the advertising type to connectable undirected + llm_le_env.advertising_params->type = ADV_CONN_UNDIR; + // Set the interval max to 1.28s + llm_le_env.advertising_params->intervalmax = LLM_LE_ADV_INTERV_DFLT; + // Set the interval min to 1.28s + llm_le_env.advertising_params->intervalmin = LLM_LE_ADV_INTERV_DFLT; + // Set all adv channels available + llm_le_env.advertising_params->channelmap = LLM_LE_ADV_CH_MAP_DFLT; + // use low duty cycle ADV + llm_le_env.advertising_params->adv_ldc_flag = true; + + + // Sets the type of advertising, the length(only AdvA len = 6 bytes) + ble_txphadv_pack(LLM_LE_ADV_IDX, // index for the ADVERTISING PDU descriptor + 6, // Length of the connect req + 0, // peer address type + 0, // updated by HW + llm_le_env.advertising_params->type ); // type of PDU + + // Sets the scan response + ble_txphadv_pack(LLM_LE_SCAN_RSP_IDX, // index for the SCAN RESPONSE PDU descriptor + 6, // Length of the connect req + 0, // peer address type + 0, // updated by HW + LL_SCAN_RSP ); // type of PDU +} +#endif //(BLE_PERIPHERAL || BLE_BROADCASTER) + +/** + **************************************************************************************** + * @brief Chek the status of the test mode + * + * This function sends an event to the host when the TX or RX test mode is finished + * + **************************************************************************************** + */ +__INLINE void llm_util_chk_tst_mode(void) +{ + //if the current state is not IDLE + if ((llm_le_env.test_mode.directtesttype != TEST_END) && (llm_le_env.test_mode.end_of_tst == true)) + { + // structure type for the complete command event + struct hci_test_end_cmd_cmp_evt *event; + + // allocate the complete event message + event = KERNEL_MSG_ALLOC(HCI_CMD_CMP_EVENT, 0, HCI_LE_TEST_END_CMD_OPCODE, hci_test_end_cmd_cmp_evt); + + llm_le_env.test_mode.end_of_tst = false; + // enable the whitening + ble_whit_dsb_setf(0); + + // Number_Of_Packets for a transmitter test is reported as NULL. + if (llm_le_env.test_mode.directtesttype == TEST_TX) + { + event->nb_packet_received = 0; + } + else + { + event->nb_packet_received = ble_rxccmpktcnt0_get(LLD_ADV_HDL); + } + // set the env variable, + llm_le_env.test_mode.directtesttype = TEST_END; + // update the status + event->status = COMMON_ERROR_NO_ERROR; + // send the message + hci_send_2_host(event); + kernel_msg_send_basic(LLM_STOP_IND, TASK_LLM, TASK_LLM); + } +} + +#if (BLE_BROADCASTER || BLE_PERIPHERAL) +/** + **************************************************************************************** + * @brief Get Advertising type + * + * @return The type of the advertising: Low or High Duty Cycle + * + **************************************************************************************** + */ +__INLINE uint8_t llm_util_get_adv_type(void) +{ + if (llm_le_env.advertising_params->adv_ldc_flag) + { + return (LLD_LD_ADVERTISER); + } + else + { + return (LLD_HD_ADVERTISER); + } +} +#endif +#if ((BLE_CENTRAL || BLE_PERIPHERAL) && (RW_DEBUG)) +/** + **************************************************************************************** + * @brief Gets the size of the packet received. + * + * This function gets the maximum length of the packet to be transmitted. + * + * + * @return The length of the data. + * + **************************************************************************************** + */ +__INLINE uint16_t llm_util_dle_get_tx_max_size(void) +{ + return (llm_le_env.data_len_val.suppted_max_tx_octets); +} +#endif + +/** + **************************************************************************************** + * @brief Check the event mask + * + * @param[in] event_id event to check + * + * @return True: event can be sent / False: event is masked + **************************************************************************************** + */ +bool llm_util_check_evt_mask(uint8_t event_id); + +/** + **************************************************************************************** + * @brief Get the channel map + * + * @param[out] map Pointer to channel map buffer + **************************************************************************************** + */ +void llm_util_get_channel_map(struct le_chnl_map *map); + +/** + **************************************************************************************** + * @brief Get supported features + * + * @param[out] feats Pointer to supported features buffer + **************************************************************************************** + */ +void llm_util_get_supp_features(struct le_features *feats); + +#if (BLE_BROADCASTER || BLE_PERIPHERAL) +/** + **************************************************************************************** + * @brief Check if advertising data need to be updated and update it if yes + * + **************************************************************************************** + */ +void llm_util_adv_data_update(void); +#endif//(BLE_BROADCASTER || BLE_PERIPHERAL) + +#if (BLE_CENTRAL || BLE_PERIPHERAL) +/** + **************************************************************************************** + * @brief Checks if the device address is already in the black list. + * + * This function checks if the bd address if present in the connected list and return + * the status. + * + * @param[in] bd_address_to_add Pointer on the device address to be checked. + * @param[in] bd_addr_type Type of BD Address + * @param[out] conhdl Pointer on the Connection handle. + * @param[in] wl_flag_action set/clear the flag. + * @param[out] in_wl Retrieve if device present in WL + * + * @return If the device address has been found or not. + * + **************************************************************************************** + */ +uint8_t llm_util_bl_check(const struct bd_addr *bd_addr_to_add, uint8_t bd_addr_type, uint16_t *conhdl, uint8_t wl_flag_action, bool *in_wl); +/** + **************************************************************************************** + * @brief Add the device address in the BLACK list. + * + * This function checks if the bd address if present in the connected list and return + * the status. + * + * @param[in] bd_address_to_add Pointer on the device address to be added. + * @param[in] bd_addr_type address type (public or random) on the device address to be added. + * @param[in] conhdl Connection handle linked to the bd address. + + * + * @return If the device address has been added or not. + * + **************************************************************************************** + */ +uint8_t llm_util_bl_add(struct bd_addr *bd_addr_to_add, uint8_t bd_addr_type, uint16_t conhdl); + +/** + **************************************************************************************** + * @brief Remove the bd address if already connected. + * + * This function checks if the bd address if present in the connected list, extract the + * bd address from the list and free the memory. + * + * @param[in] conhdl connection handle linked to the bd address to be removed. + * + * @return If the bd address has been removed or not. + * + **************************************************************************************** + */ +uint8_t llm_util_bl_rem(uint16_t conhdl); + +#if (BLE_2MBPS) +/** + **************************************************************************************** + * @brief Get the default Phys values. + * + * This function gets the values of the default Phys set over the command hci_set_dft_phy + * + * @param[out] tx_phy Retrieve phy used for TX + * @param[out] rx_phy Retrieve phy used for RX + * + **************************************************************************************** + */ +void llm_util_get_default_phy(uint8_t *tx_phy, uint8_t *rx_phy); +#endif + +#endif // (BLE_CENTRAL || BLE_PERIPHERAL) + +/** + **************************************************************************************** + * @brief check if the bd address if present in the RAL and return the status and position + * + * If not present, this function provide first available element in the list + **************************************************************************************** + */ +bool llm_util_bd_addr_in_ral(struct bd_addr const *bd_address, uint8_t bd_addr_type, uint8_t *position); + + + +/** + **************************************************************************************** + * @brief Handling defer of End of event + * + **************************************************************************************** + */ +void llm_end_evt_defer(void); + +/** + **************************************************************************************** + * @brief Handling of pdu information in a deferred event + * + * @param[in] conhdl Connection handle + * @param[in] rx_hdl RX Descriptor handle + * @param[in] tx_cnt Number of buffer acknowledged + * + * @param[out] elt_deleted Return true if the element has been delested (scan evt for init) + **************************************************************************************** + */ +bool llm_pdu_defer(uint16_t status, uint8_t rx_hdl, uint8_t tx_cnt); +/// @} LLM + +#endif // LLM_UTIL_H_ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/rwble/rwble.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/rwble/rwble.h new file mode 100755 index 0000000..c8df522 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/rwble/rwble.h @@ -0,0 +1,97 @@ +/** + **************************************************************************************** + * + * @file rwble.h + * + * @brief Entry points of the BLE software + * + * Copyright (C) RivieraWaves 2009-2015 + * + **************************************************************************************** + */ + +#ifndef RWBLE_H_ +#define RWBLE_H_ + +/** + **************************************************************************************** + * @addtogroup ROOT + * @brief Entry points of the BLE stack + * + * This module contains the primitives that allow an application accessing and running the + * BLE protocol stack + * + * @{ + **************************************************************************************** + */ + + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include +#include +#include "rwip_config.h" +#include "ble_compiler.h" +#include "common_error.h" + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Initialize the BLE stack. + **************************************************************************************** + */ +void rwble_init(void); + + +/** + **************************************************************************************** + * @brief Reset the BLE stack. + **************************************************************************************** + */ +void rwble_reset(void); + +#if (DEEP_SLEEP) +/** + **************************************************************************************** + * @brief Return true if no BLE activity on going + * + **************************************************************************************** + */ +bool rwble_sleep_check(void); +#endif + +/** + **************************************************************************************** + * @brief Return true if no BLE activity on going + * + **************************************************************************************** + */ +bool rwble_activity_ongoing_check(void); + +/** + **************************************************************************************** + * @brief Gives FW/HW versions of RW-BLE stack. + * + **************************************************************************************** + */ +void rwble_version(uint8_t *fw_version, uint8_t *hw_version); + +/** + **************************************************************************************** + * @brief RWBLE interrupt service routine + * + * This function is the interrupt service handler of RWBLE. + * + **************************************************************************************** + */ +__BLEIRQ void rwble_isr(void); + +/// @} RWBLE + +#endif // RWBLE_H_ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/rwble/rwble_config.h b/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/rwble/rwble_config.h new file mode 100755 index 0000000..f471b2f --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ble/ll/src/rwble/rwble_config.h @@ -0,0 +1,316 @@ +/** + **************************************************************************************** + * + * @file rwble_config.h + * + * @brief Configuration of the BLE protocol stack (max number of supported connections, + * type of partitioning, etc.) + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef RWBLE_CONFIG_H_ +#define RWBLE_CONFIG_H_ + +/** + **************************************************************************************** + * @addtogroup ROOT + * @{ + * @name BLE stack configuration + * @{ + **************************************************************************************** + */ + +#include "rwip_config.h" + + +/******************************************************************************************/ +/* ------------------------- COEXISTENCE SETUP ------------------------------------*/ +/******************************************************************************************/ + +///WLAN coex +#define RW_BLE_WLAN_COEX RW_WLAN_COEX +///WLAN test mode +#define RW_BLE_WLAN_COEX_TEST RW_WLAN_COEX_TEST + +/// MWS Coexistence +#define RW_BLE_MWS_COEX RW_MWS_COEX +///WLAN test mode +#define RW_BLE_MWS_COEX_TEST RW_MWS_COEX_TEST + +///To let the HW using the default values set in the registers +#define RW_BLE_PTI_PRIO_AUTO 15 + + + +/// PTI configuration index +enum rwble_pti_config_idx +{ + BLE_PTI_CON_IDX, + BLE_PTI_ADV_IDX, + BLE_PTI_SCAN_IDX, + BLE_PTI_INIT_IDX, + BLE_PTI_IDX_MAX +}; + + +/******************************************************************************************/ +/* -------------------------- DEBUG SETUP ----------------------------------------*/ +/******************************************************************************************/ + +/// Flag indicating if tester emulator is available or not +#if defined(CFG_BLE_TESTER) +/// Flag indicating if tester emulator is available or not +#define BLE_TESTER 1 +#else // defined (CFG_BLE_TESTER) +#define BLE_TESTER 0 +#endif // defined (CFG_BLE_TESTER) + +/// Flag indicating that Advertising Test mode is enabled or not +#if defined(CFG_BLE_ADV_TEST_MODE) +#define BLE_ADV_TEST_MODE 1 +#else // !defined(CFG_BLE_ADV_TESTER) +#define BLE_ADV_TEST_MODE 0 +#endif // defined(CFG_BLE_ADV_TESTER) + + + + +/// Flag indicating if debug mode is activated or not +#define BLE_DEBUG RW_DEBUG +#define BLE_SWDIAG RW_SWDIAG + +/// Flag indicating if Read/Write memory commands are supported or not +#define BLE_DEBUG_MEM RW_DEBUG_MEM + +/// Flag indicating if Flash debug commands are supported or not +#define BLE_DEBUG_FLASH RW_DEBUG_FLASH + +/// Flag indicating if NVDS feature is supported or not +#define BLE_DEBUG_NVDS RW_DEBUG_NVDS + +/// Flag indicating if CPU stack profiling commands are supported or not +#define BLE_DEBUG_STACK_PROF RW_DEBUG_STACK_PROF + +/******************************************************************************************/ +/* ------------------------- BLE SETUP --------------------------------------------*/ +/******************************************************************************************/ + +/// Exchange memory presence +#define BLE_EM_PRESENT (BLE_EMB_PRESENT) + +#if BLE_TESTER +#define BLE_TEST_MODE_SUPPORT (1) +#else +#define BLE_TEST_MODE_SUPPORT (0) +#endif + +/// Number of devices in the white list +#define BLE_WHITELIST_MAX (BLE_CONNECTION_MAX + 2) + +/// Number of devices in the Resolution Address List +/// This have to be tuned according to the core frequency. Worst case is having in scan mode +/// all IRK and valid in resolving list and device receive a Direct Adv Report that contains +/// RPAs for InitA and AdvA +#define BLE_RESOL_ADDR_LIST_MAX (3) + +/// Connection handle max +#define BLE_MAX_CONHDL (BLE_CONNECTION_MAX) + +/// Number of devices capacity for the scan filtering +#if (BLE_CENTRAL || BLE_OBSERVER) +#define BLE_DUPLICATE_FILTER_MAX (10) +#endif //(BLE_CENTRAL || BLE_OBSERVER) + +/** Size of the heap + * - For KE messages: (N+1) x 256 + * - For LLC environment: N x 80 Bytes + * - For LLD events/intervals: (2N+1) x (80 + 16) + */ +#if (BLE_CENTRAL || BLE_PERIPHERAL) +#define BLE_HEAP_MSG_SIZE (256 * (BLE_CONNECTION_MAX+1) + 80 * (BLE_CONNECTION_MAX) + 96 * (2*BLE_CONNECTION_MAX+1)) +/// Size required to allocate environment variable for one link +#define BLE_HEAP_ENV_SIZE (sizeof(struct llc_env_tag) + 4) +#else +#define BLE_HEAP_MSG_SIZE (256) +/// Size required to allocate environment variable for one link +#define BLE_HEAP_ENV_SIZE (4) +#endif /* #if (BLE_CENTRAL || BLE_PERIPHERAL) */ + + +/******************************************************************************************/ +/* -------------------------- RADIO SETUP ----------------------------------------*/ +/******************************************************************************************/ +/// Class of device +#define RF_CLASS1 0 + +/******************************************************************************************/ +/* -------------------------- REGISTER SETUP --------------------------------------*/ +/******************************************************************************************/ + +#define RW_BLE_CUST1_INST 0 + +/******************************************************************************************/ +/* -------------------------- SCHEDULING SETUP --------------------------------------*/ +/******************************************************************************************/ + +/// EA programming latency for only 1 activity +#define RWBLE_PROG_LATENCY_DFT (2) +/// EA asap latency +#define RWBLE_ASAP_LATENCY (2) +/// Instant value mask +#define RWBLE_INSTANT_MASK (0x0000FFFF) + +/******************************************************************************************/ +/* ----------------------- SUPPORTED HCI COMMANDS --------------------------------*/ +/******************************************************************************************/ + +//byte0 +#define BLE_CMDS_BYTE0 BLE_DISC_CMD +//byte2 +#define BLE_CMDS_BYTE2 BLE_RD_REM_VERS_CMD +//byte5 +#define BLE_CMDS_BYTE5 (BLE_SET_EVT_MSK_CMD | BLE_RESET_CMD) +//byte10 +#define BLE_CMDS_BYTE10 (BLE_HL_NB_CMP_PKT_CMD | BLE_RD_TX_PWR_CMD\ + |BLE_HL_BUF_SIZE_CMD | BLE_SET_CTRL_TO_HL_FCTRL_CMD) +//byte14 +#define BLE_CMDS_BYTE14 (BLE_RD_LOC_VERS_CMD | BLE_RD_LOC_SUP_FEAT_CMD\ + |BLE_RD_BUF_SIZE_CMD) +//byte15 +#define BLE_CMDS_BYTE15 (BLE_RD_BD_ADDR_CMD | BLE_RD_RSSI_CMD) +#if !(BLE_QUALIF) +//byte22 +#define BLE_CMDS_BYTE22 (BLE_SET_EVT_MSK_PG2_CMD) +#else +//byte22 +#define BLE_CMDS_BYTE22 0 +#endif +//byte25 +#define BLE_CMDS_BYTE25 (BLE_LE_SET_EVT_MSK_CMD | BLE_LE_RD_BUF_SIZE_CMD\ + |BLE_LE_RD_LOC_SUP_FEAT_CMD | BLE_LE_SET_RAND_ADDR_CMD\ + |BLE_LE_SET_ADV_PARAM_CMD | BLE_LE_RD_ADV_TX_PWR_CMD\ + |BLE_LE_SET_ADV_DATA_CMD) +//byte26 +#define BLE_CMDS_BYTE26 (BLE_LE_SET_SC_RSP_DATA_CMD | BLE_LE_SET_ADV_EN_CMD\ + |BLE_LE_SET_SC_PARAM_CMD | BLE_LE_SET_SC_EN_CMD\ + |BLE_LE_CREAT_CNX_CMD | BLE_LE_CREAT_CNX_CNL_CMD\ + |BLE_LE_RD_WL_SIZE_CMD | BLE_LE_CLEAR_WL_CMD) +//byte27 +#define BLE_CMDS_BYTE27 (BLE_LE_ADD_DEV_WL_CMD | BLE_LE_REM_DEV_WL_CMD\ + |BLE_LE_CNX_UPDATE_CMD | BLE_LE_SET_HL_CH_CLASS_CMD\ + |BLE_LE_RD_CH_MAP_CMD | BLE_LE_RD_REM_USED_FEAT_CMD\ + |BLE_LE_ENCRYPT_CMD | BLE_LE_RAND_CMD) +//byte28 +#define BLE_CMDS_BYTE28 (BLE_LE_START_ENC_CMD | BLE_LE_LTK_REQ_RPLY_CMD\ + |BLE_LE_LTK_REQ_NEG_RPLY_CMD | BLE_LE_RD_SUPP_STATES_CMD\ + |BLE_LE_RX_TEST_CMD | BLE_LE_TX_TEST_CMD\ + |BLE_LE_STOP_TEST_CMD) +#if !(BLE_QUALIF) +//byte32 +#define BLE_CMDS_BYTE32 (BLE_RD_AUTH_PAYL_TO_CMD | BLE_WR_AUTH_PAYL_TO_CMD) +//byte33 +#define BLE_CMDS_BYTE33 (BLE_LE_REM_CON_PARA_REQ_RPLY_CMD | BLE_LE_REM_CON_PARA_REQ_NEG_RPLY_CMD\ + | BLE_LE_SET_DATA_LEN_CMD | BLE_LE_RD_SUGGTED_DFT_DATA_LEN_CMD) +//byte34 +#define BLE_CMDS_BYTE34 ( BLE_LE_WR_SUGGTED_DFT_DATA_LEN_CMD \ + | BLE_LE_RD_LOC_P256_PUB_KEY_CMD \ + | BLE_LE_GEN_DH_KEY_CMD \ + | BLE_LE_ADD_DEV_TO_RESOLV_LIST_CMD \ + | BLE_LE_REM_DEV_FROM_RESOLV_LIST_CMD \ + | BLE_LE_CLEAR_RESOLV_LIST_CMD \ + | BLE_LE_RD_RESOLV_LIST_SIZE_CMD \ + | BLE_LE_RD_PEER_RESOLV_ADDR_CMD) +#if (BLE_2MBPS) +//byte35 +#define BLE_CMDS_BYTE35 ( BLE_LE_RD_LOCAL_RESOLV_ADDR_CMD \ + | BLE_LE_SET_ADDR_RESOL_CMD \ + | BLE_LE_SET_RESOLV_PRIV_ADDR_TO_CMD \ + | BLE_LE_RD_MAX_DATA_LEN_CMD \ + | BLE_LE_RD_PHY_CMD | BLE_LE_SET_DFT_PHY_CMD\ + | BLE_LE_SET_PHY_CMD | BLE_LE_ENH_RX_TEST_CMD) + +//byte36 +#define BLE_CMDS_BYTE36 ( BLE_LE_ENH_RX_TEST_CMD) + +#else +//byte35 +#define BLE_CMDS_BYTE35 ( BLE_LE_RD_LOCAL_RESOLV_ADDR_CMD \ + | BLE_LE_SET_ADDR_RESOL_CMD \ + | BLE_LE_SET_RESOLV_PRIV_ADDR_TO_CMD \ + | BLE_LE_RD_MAX_DATA_LEN_CMD) +//byte36 +#define BLE_CMDS_BYTE36 0 +#endif +#else +//byte32 +#define BLE_CMDS_BYTE32 0 +//byte33 +#define BLE_CMDS_BYTE33 0 +//byte34 +#define BLE_CMDS_BYTE34 0 +//byte35 +#define BLE_CMDS_BYTE35 0 +//byte36 +#define BLE_CMDS_BYTE36 0 +#endif // BLE_QUALIF + + +/******************************************************************************************/ +/* ------- SUPPORTED VALUES FOR DATA LENGTH EXTENSION COMMANDS -----------------------*/ +/******************************************************************************************/ +#define BLE_TESTMODE_MAX_OCTETS (255) +//8 bits preamble +#define BLE_PREAMBLE_TIME (8) +//32 bits Access Code +#define BLE_ACCESS_CODE_BIT_SIZE (32) +//16 bits header +#define BLE_HEADER_BIT_SIZE (16) +//32bits MIC +#define BLE_MIC_BIT_SIZE (32) +//24 bits CRC +#define BLE_CRC_BIT_SIZE (24) +//8 bits preamble +#define BLE_PREAMBLE_SIZE (1) +//4 bytes Access Code +#define BLE_ACCESS_CODE_SIZE (4) +//2 bytes header +#define BLE_HEADER_SIZE (2) +//4 bytes MIC +#define BLE_MIC_SIZE (4) +//3 bytes CRC +#define BLE_CRC_SIZE (3) + +#define BLE_COMMON_BIT_SIZE (BLE_ACCESS_CODE_BIT_SIZE + BLE_HEADER_BIT_SIZE + BLE_CRC_BIT_SIZE) +/******************************************************************************************/ +/* -------------------------- DLE SETUP ----------------------------------------*/ +/******************************************************************************************/ + + + +#define BLE_MIN_OCTETS (27) +#define BLE_MIN_TIME (328) +#if !(BLE_QUALIF) +#define BLE_MAX_OCTETS (251) +#define BLE_MAX_TIME (2120) +#else +#define BLE_MAX_OCTETS (27) +#define BLE_MAX_TIME (328) +#endif +// Max number of descriptor to be linked under IRQ context to avoid CPU overload +#define BLE_NB_MAX_PACKET_PROG (10) +/******************************************************************************************/ +/* -------------------------- PROCEDURE STARTUP ----------------------------------------*/ +/******************************************************************************************/ + +#define BLE_NO_PROCEDURE (0) +#define BLE_DLE_PROCEDURE (1 << 0) +#define BLE_PHY_PROCEDURE (1 << 1) + +/// @} BLE stack configuration +/// @} ROOT + +#endif // RWBLE_CONFIG_H_ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/ea/api/ea.h b/beken_os/beken378/driver/ble/ble_lib/ip/ea/api/ea.h new file mode 100755 index 0000000..0b308f8 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/ea/api/ea.h @@ -0,0 +1,476 @@ +/** +**************************************************************************************** +* +* @file EA.h +* +* @brief EA main module +* +* Copyright (C) RivieraWaves 2009-2015 +* +* +**************************************************************************************** +*/ + +#ifndef _EA_H_ +#define _EA_H_ + +/** + **************************************************************************************** + * @addtogroup EA + * @brief Entry points of the Event Arbiter module + * + * This module contains the primitives that allow stacks to schedule an event or frame. + * + * @{ + **************************************************************************************** + */ + +#include "rwip_config.h" + +#if (EA_PRESENT) + +#include // Standard integer definitions +#include // Standard boolean definitions +#include "common_list.h" // List management functions definitions + + +#if (BT_EMB_PRESENT) +#define EA_ALARM_SUPPORT 1 +#else +#define EA_ALARM_SUPPORT 0 +#endif //(BT_EMB_PRESENT) + +/* + * MACROS + **************************************************************************************** + */ + + + +/* + * DEFINES + **************************************************************************************** + */ + +/// Default BW 2 slots +#define EA_BW_USED_DFT_SLOT (2) +#define EA_BW_USED_DFT_US (EA_BW_USED_DFT_SLOT*SLOT_SIZE) +/// Clock correction delay +#define EA_CLOCK_CORR_LAT (1) + +/// Set ASAP settings +#define EA_ASAP_STG_SET(evt, type, parity, to_protect, resched_att, prio_inc) evt->asap_settings = ( (((type) << 14) & 0xC000) | (((parity) << 12) & 0x3000) | (((to_protect) << 11) & 0x0800) | (((resched_att) << 4) & 0x03F0) | (((prio_inc) << 0) & 0x000F) ); +/// Get/Set type from ASAP settings +#define EA_ASAP_STG_TYPE_GET(evt) ((uint8_t)((evt->asap_settings & 0xC000) >> 14)) +#define EA_ASAP_STG_TYPE_SET(evt, type) ( evt->asap_settings = ((evt->asap_settings & ~(0xC000)) | (((type) << 14) & 0xC000)) ) +/// Get parity from ASAP settings +#define EA_ASAP_STG_PARITY_GET(evt) ((uint8_t)((evt->asap_settings & 0x3000) >> 12)) +/// Get to protect from ASAP settings +#define EA_ASAP_STG_TO_PROTECT_GET(evt) ((uint8_t)((evt->asap_settings & 0x0800) >> 11)) +/// Get/Set rescheduling attempts from ASAP settings +#define EA_ASAP_STG_RESCHED_ATT_GET(evt) ((uint8_t)((evt->asap_settings & 0x03F0) >> 4)) +#define EA_ASAP_STG_RESCHED_ATT_SET(evt, resched_att) ( evt->asap_settings = ((evt->asap_settings & ~(0x03F0)) | (((resched_att) << 4) & 0x03F0)) ) +/// Get priority increment from ASAP settings +#define EA_ASAP_STG_PRIO_INC_GET(evt) ((uint8_t)((evt->asap_settings & 0x000F) >> 0)) + + +/* + * DEFINITIONS + **************************************************************************************** + */ + +/// EA error codes +enum ea_error +{ + /// EA request succeed + EA_ERROR_OK = 0, + /// EA request rejected error + EA_ERROR_REJECTED, + /// EA element not found error + EA_ERROR_NOT_FOUND, + /// EA request rejected due to bandwidth full error + EA_ERROR_BW_FULL +}; + +/// Action for the parameters request API +enum ea_param_req_action +{ + EA_PARAM_REQ_GET, + EA_PARAM_REQ_CHECK, +}; + +/// ASAP type definition +enum ea_elt_asap_type +{ + /// 00: No ASAP + EA_FLAG_NO_ASAP = 0, + /// 01: ASAP no limit + EA_FLAG_ASAP_NO_LIMIT, + /// 10: ASAP with limit + EA_FLAG_ASAP_LIMIT, + EA_FLAG_MAX +}; + +/// ASAP slot parity definition +enum ea_elt_asap_parity +{ + EA_EVEN_SLOT, + EA_ODD_SLOT, + EA_NO_PARITY, +}; + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + + + +/// Event Arbiter Element +struct ea_elt_tag +{ + /// List element for chaining in the Even Arbiter lists + struct common_list_hdr hdr; + + /// Pointer on the next element linked to the current action + struct ea_elt_tag *linked_element; + + /// Programming time in basetime (CLOCKN) absolute value + uint32_t timestamp; + + /// Scheduling time limit in base time (CLOCKN) (in slots) (only for ASAP LIMIT requests) + uint32_t asap_limit; + + /** + * ASAP settings field + * bit |15 14| 13 12 | 11 | 10| 9..4 | 3..0 | + * def | TYPE | Parity | To protect |RFU| Resched att | Prio inc | + * + * Type: + * - 00: No ASAP + * - 01: ASAP no limit + * - 10: ASAP with limit + * - 11: ASAP with limit, no parity check + * + * Parity: (only for ASAP requests) + * - 0: even slots + * - 1: odd slots + * - 2: don't care + * + * To protect: + * - 0: Event does NOT need to be protected by the bigger stop notification delay + * - 1: Event needs to be protected by the bigger stop notification delay (when priority is higher) + * + * Number of rescheduling attempts: + * - The remaining number of rescheduling attempts. + * - Rescheduling happens when the event is overlapped by a higher priority event + * - Only used for ASAP requests + * + * Priority increment: + * - The current priority value is incremented each time the event is overlapped by a new insertion and postponed + * - Only used for ASAP requests + */ + uint16_t asap_settings; + + /// Minimum duration of the event or frame (in us) + uint16_t duration_min; + + /// Delay of the start of the activity from the local slot boundary (in us) + uint16_t delay; + + /// Current priority + uint8_t current_prio; + /// Latency to stop the activity (when next activity is lower priority) + uint8_t stop_latency1; + /** + * Latency to stop the activity (when next activity is higher priority, and next activity needs protection) + * Note: threshold 2 is always higher than threshold 1, so that any following higher priority activity is protected + * from being overlapped by this activity + */ + uint8_t stop_latency2; + /// Latency to start the activity + uint8_t start_latency; + + /************************************************************************************ + * ISR CALLBACKS + ************************************************************************************/ + + /// Start notification call back function + void (*ea_cb_start)(struct ea_elt_tag*); + /// Stop notification call back function + void (*ea_cb_stop)(struct ea_elt_tag*); + /// Cancel notification call back function + void (*ea_cb_cancel)(struct ea_elt_tag*); + + /// BT/BLE Specific environment variable + void *env; +}; + +/// Interval element strcuture +struct ea_interval_tag +{ + /// List element for chaining in the Interval list + struct common_list_hdr hdr; + /// Interval used + uint16_t interval_used; + /// Offset used + uint16_t offset_used; + /// Bandwidth used + uint16_t bandwidth_used; + /// Connection handle used + uint16_t conhdl_used; + /// Role used + uint16_t role_used; + /// Odd offset or even offset + bool odd_offset; + /// Link id + uint16_t linkid; +}; + +/// API get/check parameters input +struct ea_param_input +{ + /// Interval minimum requested + uint16_t interval_min; + /// Interval maximum requested + uint16_t interval_max; + /// Duration minimum requested + uint32_t duration_min; + /// Duration maximum requested + uint16_t duration_max; + /// Preferred periodicity + uint8_t pref_period; + /// Offset requested + uint16_t offset; + /// action + uint8_t action; + /// Connection handle + uint16_t conhdl; + /// Role + uint16_t role; + /// Odd offset or even offset + bool odd_offset; + /// Link id + uint16_t linkid; +}; + +/// API get/check parameters output +struct ea_param_output +{ + /// Interval returned + uint16_t interval; + /// Duration returned + uint32_t duration; + /// Offset returned + uint16_t offset; +}; + +#if (EA_ALARM_SUPPORT) +/// Alarm element structure +struct ea_alarm_tag +{ + /// List element for chaining in the Even Arbiter lists + struct common_list_hdr hdr; + + /// Timestamp of alarm expiry + uint32_t timestamp; + + /// Call back function invoked upon alarm expiry + void (*ea_cb_alarm)(struct ea_alarm_tag*); +}; +#endif //(EA_ALARM_SUPPORT) + +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ + + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Initialize the Event Arbiter. + **************************************************************************************** + */ +void ea_init(bool reset); + +/** + **************************************************************************************** + * @brief Return the current time half slot boundary rounded + * + * @return Current time (in BT slots) + **************************************************************************************** + */ +uint32_t ea_time_get_halfslot_rounded(void); + +/** + **************************************************************************************** + * @brief Return the current time slot boundary rounded + * + * @return Current time (in BT slots) + **************************************************************************************** + */ +uint32_t ea_time_get_slot_rounded(void); + +/** + **************************************************************************************** + * @brief Create a new event element + * + * @param[in] size_of_env Size of the dedicated environment structure + * + * @return Pointer on the allocated element + **************************************************************************************** + */ +struct ea_elt_tag *ea_elt_create(uint16_t size_of_env); + +/** + **************************************************************************************** + * @brief API to try to insert a new element in the scheduler queue + * + * @param[in] elt Pointer to the element to be inserted + * + * @return No error if element is inserted. + **************************************************************************************** + */ +uint8_t ea_elt_insert(struct ea_elt_tag *elt); + +/** + **************************************************************************************** + * @brief API to try to remove the current element programmed + * + * @param[in] elt Pointer to the element to be removed from current ptr + * + **************************************************************************************** + */ +uint8_t ea_elt_remove(struct ea_elt_tag *elt); + +/** + **************************************************************************************** + * @brief Start of event/frame interrupt handler + * + * This function is called under interrupt when a start of event/frame interrupt is + * generated by the BLE/BT core. + * + **************************************************************************************** + */ +void ea_finetimer_isr(void); + +/** + **************************************************************************************** + * @brief Software interrupt handler + * + * This function is called under interrupt when a SW interrupt is generated by the BLE/BT + * core. + * + **************************************************************************************** + */ +void ea_sw_isr(void); + +/** + **************************************************************************************** + * @brief Create a new interval element + * + * @return Pointer on the allocated element + **************************************************************************************** + */ +struct ea_interval_tag *ea_interval_create(void); + +/** + **************************************************************************************** + * @brief API to try to remove an interval from the queue + * + * @param[in] interval_to_remove Interval to be removed + * + **************************************************************************************** + */ +void ea_interval_delete(struct ea_interval_tag *interval_to_remove); + +/** + **************************************************************************************** + * @brief Insert the interval in the common interval queue + **************************************************************************************** + */ +void ea_interval_insert(struct ea_interval_tag *interval_to_add); + +/** + **************************************************************************************** + * @brief Remove the interval from the common interval queue + **************************************************************************************** + */ +void ea_interval_remove(struct ea_interval_tag *interval_to_remove); + + +/** + **************************************************************************************** + * @brief Get the first timer target (in Slot) used for deep sleep decision + * + * @param[in] current_time Current time value used in case of HW activity programmed + * + * @return Invalid time if nothing programmed; target time else. + **************************************************************************************** + */ + + uint32_t ea_timer_target_get(uint32_t current_time); + +uint32_t ea_timer_next_target_get(void); + +bool ea_sleep_check(uint32_t *sleep_duration, uint32_t wakeup_delay); + +/** + **************************************************************************************** + * @brief Choose an appropriate offset according to the interval + * + * @param[in] input_param parameters used to compute the offset + * + * @param[in] output_param offset used for the interval + * + * @return true if an offset has been found or not + **************************************************************************************** + */ +uint8_t ea_offset_req(struct ea_param_input* input_param, struct ea_param_output* output_param); +/** + **************************************************************************************** + * @brief Choose an appropriate interval and duration for the event + * + * @param[in] input_param parameter used to compute the interval and duration of the event + * + * @param[in] output_param interval and duration chosen for the event + * + **************************************************************************************** + */ +void ea_interval_duration_req(struct ea_param_input* input_param, struct ea_param_output* output_param); + +#if (EA_ALARM_SUPPORT) +/** + **************************************************************************************** + * @brief Set an alarm + * + * @param[in] elt Pointer to the alarm element to be programmed + * + * @return 0 - no error / 1:255 - error + **************************************************************************************** + */ +uint8_t ea_alarm_set(struct ea_alarm_tag* elt); + +/** + **************************************************************************************** + * @brief Clear an alarm + * + * @param[in] elt Pointer to the alarm element to be cleared + * + * @return 0 - no error / 1:255 - error + **************************************************************************************** + */ +uint8_t ea_alarm_clear(struct ea_alarm_tag* elt); +#endif //(EA_ALARM_SUPPORT) + +//struct ea_elt_tag *ea_elt_get(void); +#endif //(EA_PRESENT) + +///@} EA + +#endif // _EA_H_ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/em/api/em_map.h b/beken_os/beken378/driver/ble/ble_lib/ip/em/api/em_map.h new file mode 100755 index 0000000..38b15a4 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/em/api/em_map.h @@ -0,0 +1,256 @@ +/** + **************************************************************************************** + * + * @file em_map.h + * + * @brief Mapping of the exchange memory + * + * Copyright (C) RivieraWaves 2009-2015 + * + **************************************************************************************** + */ + +#ifndef EM_MAP_H_ +#define EM_MAP_H_ + +/** + **************************************************************************************** + * @addtogroup EM EM + * @ingroup IP + * @brief Mapping of the different common area in the exchange memory + * + * @{ + **************************************************************************************** + */ +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include +#include +#include + +#if BT_EMB_PRESENT +#include "_reg_em_et.h" +/// Exchange memory base address +#define EM_BASE_ADDR REG_EM_ET_BASE_ADDR +#elif BLE_EMB_PRESENT +#include "_reg_common_em_et.h" +//#include "_reg_common_em_et.h" +/// Exchange memory base address +#define EM_BASE_ADDR REG_COMMON_EM_ET_BASE_ADDR +#endif // BT_EMB_PRESENT/BLE_EMB_PRESENT + + +/* + **************************************************************************************** + ********************** Common EM part ********************** + **************************************************************************************** + */ +/// Start of the common EM part +#define EM_COMMON_OFFSET (0) + +/* + * EXCHANGE TABLE + **************************************************************************************** + */ + +/// Exchange table area definition +#define EM_EXCH_TABLE_LEN 16 +#define EM_ET_OFFSET (EM_COMMON_OFFSET) +#if BT_EMB_PRESENT +#define EM_ET_END (EM_ET_OFFSET + EM_EXCH_TABLE_LEN * REG_EM_ET_SIZE) +#elif BLE_EMB_PRESENT +#define EM_ET_END (EM_ET_OFFSET + EM_EXCH_TABLE_LEN * REG_COMMON_EM_ET_SIZE) +#endif // BT_EMB_PRESENT/BLE_EMB_PRESENT + +/** + * MODEn[3:0] + * + * 0x0: No mode selected, nothing to be performed + * 0x1: BR/EDR Mode + * 0x2: BLE Mode + * 0x3-0xF: Reserved for future use - + */ +#define EM_ET_MODE_NONE 0x00 +#define EM_ET_MODE_BREDR 0x01 +#define EM_ET_MODE_BLE 0x02 + +/** + * STATUSn[1:0] + * + * 00: Control Structure Pointer is ready for processing. + * 01: Control Structure Pointer is currently under process + * 10: Reserved + * 11: Reserved + */ +#define EM_ET_STATUS_READY 0x00 +#define EM_ET_STATUS_UNDER_PROCESS 0x01 + +/** + * ISOBUFSELn + * Used to select Isochronous channel Buffer Pointer + * 0x0: Uses ISO<0/1/2>PTR0 + * 0x1: Uses ISO<0/1/2>PTR1 + */ +#define EM_ET_ISO_PTR0 0x00 +#define EM_ET_ISO_PTR1 0x01 + +/** + * ISOn + * Indicates a Isochronous connection event is programmed + * 0x0: Not an Isochronous Channel event + * 0x1: Isochronous Channel event + */ +#define EM_ET_ISO_NOTPROGRAMMED 0x00 +#define EM_ET_ISO_PROGRAMMED 0x01 + +/** + * ISOCHANn[1:0] + * Meaningful if ISOn = 1 + * 00: Select Isochronous channel 0. + * 01: Select Isochronous channel 1. + * 10: Select Isochronous channel 2. + * 11: Trash received isochronous packet / Sent null length packet if ET-ISO = 1 / No Tx if ET-ISO = 0 + */ +#define EM_ET_ISO_CHANNEL_0 0x00 +#define EM_ET_ISO_CHANNEL_1 0x01 +#define EM_ET_ISO_CHANNEL_2 0x02 +#define EM_ET_ISO_NOCHANNEL 0x03 + + +/** + * RSVDn + * Indicates a reserved event + * 0x0: Not a reserved event (ISO connection re-Tx) + * 0x1: Reserved event (ISO connection primary event) + */ +#define EM_ET_ISO_NOT_RSVD 0x00 +#define EM_ET_ISO_RSVD 0x01 +/* + * FREQUENCY TABLE + **************************************************************************************** + */ + +/// Frequency table area definition +#define EM_FT_OFFSET (EM_ET_END) + +/// number of frequencies / Depends on RF target +#if defined(CFG_RF_ATLAS) + /// IcyTRx requires 40 x 32-bit words for Frequency table + 40 byte for VCO sub-band table + #define EM_RF_FREQ_TABLE_LEN 160 + #define EM_RF_VCOMMON_TABLE_LEN 40 + +#elif defined(CFG_RF_BLIM) + /// IcyTRx requires 40 x 32-bit words for Frequency table + 40 byte for VCO sub-band table + #define EM_RF_FREQ_TABLE_LEN 160 + #define EM_RF_VCOMMON_TABLE_LEN 40 +#else + #if BT_EMB_PRESENT + /// Ripple/ExtRC requires 80 x 8-bit words for Frequency table / No VCO sub-band table + #define EM_RF_FREQ_TABLE_LEN 80 + #define EM_RF_VCOMMON_TABLE_LEN 0 + #elif BLE_EMB_PRESENT + /// Ripple/ExtRC requires 40 x 8-bit words for Frequency table / No VCO sub-band table + #define EM_RF_FREQ_TABLE_LEN 40 + #define EM_RF_VCOMMON_TABLE_LEN 0 + #endif // BT_EMB_PRESENT/BLE_EMB_PRESENT +#endif + +#define EM_FT_END (EM_FT_OFFSET + (EM_RF_VCOMMON_TABLE_LEN + EM_RF_FREQ_TABLE_LEN) * sizeof(uint8_t)) + +/* + * RF SW SPI + **************************************************************************************** + */ +/// RF SW-Driven SPI transfers area definition +#if defined(CFG_RF_ATLAS) + /// IcyTYRx (Former Atlas) SW Driven SPI space + #define EM_RF_SW_SPI_OFFSET (EM_FT_END) + #define EM_RF_SW_SPI_SIZE_MAX 100 + #define EM_RF_SW_SPI_END (EM_RF_SW_SPI_OFFSET + EM_RF_SW_SPI_SIZE_MAX) + +#elif defined(CFG_RF_BLIM) + /// IcyTYRx (Former Atlas) SW Driven SPI space + #define EM_RF_SW_SPI_OFFSET (EM_FT_END) + #define EM_RF_SW_SPI_SIZE_MAX 100 + #define EM_RF_SW_SPI_END (EM_RF_SW_SPI_OFFSET + EM_RF_SW_SPI_SIZE_MAX) + +#else + /// Ripple SW Driven SPI space + /// RF-SW-SPI transfers area definition + #define EM_RF_SW_SPI_OFFSET (EM_FT_END) + #define EM_RF_SW_SPI_SIZE_MAX 6 + #define EM_RF_SW_SPI_END (EM_RF_SW_SPI_OFFSET + EM_RF_SW_SPI_SIZE_MAX) +#endif + + + +/* + * RF HW SPI + **************************************************************************************** + */ +/// RF HW-Driven SPI transfers area definition +#if defined(CFG_RF_ATLAS) + /// IcyTYRx (Former Atlas) SW Driven SPI space + #define EM_RF_HW_SPI_OFFSET (EM_RF_SW_SPI_END) + #define EM_RF_HW_SPI_SIZE_MAX 100 + #define EM_RF_HW_SPI_END (EM_RF_HW_SPI_OFFSET + EM_RF_HW_SPI_SIZE_MAX) + +#elif defined(CFG_RF_BLIM) + /// IcyTYRx (Former Atlas) SW Driven SPI space + #define EM_RF_HW_SPI_OFFSET (EM_RF_SW_SPI_END) + #define EM_RF_HW_SPI_SIZE_MAX 100 + #define EM_RF_HW_SPI_END (EM_RF_HW_SPI_OFFSET + EM_RF_HW_SPI_SIZE_MAX) + +#else + /// Ripple SW Driven SPI space + /// RF-SW-SPI transfers area definition + #define EM_RF_HW_SPI_OFFSET (EM_RF_SW_SPI_END) + #define EM_RF_HW_SPI_SIZE_MAX 0 + #define EM_RF_HW_SPI_END (EM_RF_HW_SPI_OFFSET + EM_RF_HW_SPI_SIZE_MAX) +#endif + + +/// End of the common EM part +#define EM_COMMON_END (EM_RF_HW_SPI_END) + + +/* + **************************************************************************************** + ********************** BLE EM part ********************** + **************************************************************************************** + */ + +#if BLE_EMB_PRESENT +#define EM_BLE_OFFSET (EM_COMMON_END) +#include "em_map_ble.h" +#endif //BLE_EMB_PRESENT + + + +/* + **************************************************************************************** + ********************** BT EM part ********************** + **************************************************************************************** + */ + +#if BT_EMB_PRESENT +#if BLE_EMB_PRESENT +#define EM_BT_OFFSET (EM_BLE_END) +#else //BLE_EMB_PRESENT +#define EM_BT_OFFSET (EM_COMMON_END) +#endif //BLE_EMB_PRESENT +#include "em_map_bt.h" +#endif //BT_EMB_PRESENT + + +/* + * RF SPI part + **************************************************************************************** + */ + + +/// @} IPDEXMEM + +#endif // EM_MAP_H_ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/hci/api/hci.h b/beken_os/beken378/driver/ble/ble_lib/ip/hci/api/hci.h new file mode 100755 index 0000000..fcdd17c --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/hci/api/hci.h @@ -0,0 +1,496 @@ +/** + **************************************************************************************** + * + * @file hci.h + * + * @brief This file contains definitions related to the HCI module. + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef HCI_H_ +#define HCI_H_ + +/** + **************************************************************************************** + * @addtogroup HCI Host Controller Interface + * @ingroup ROOT + * @brief HCI module handling communication between lower and higher layers in split + * architecture. + * @{ + **************************************************************************************** + */ + + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" // SW configuration + +#if (HCI_PRESENT) + +#include // standard definition +#include // standard integer +#include "common_bt.h" // BT standard definitions + +#include "kernel_task.h" // SW main module +#include "rwip_task.h" // Task definitions + +/* + * DEFINES + **************************************************************************************** + */ + +#if (BLE_EMB_PRESENT || BLE_HOST_PRESENT) +#if (BLE_CENTRAL || BLE_PERIPHERAL) +#define HCI_BLE_CON_SUPPORT 1 +#else // (BLE_CENTRAL || BLE_PERIPHERAL) +#define HCI_BLE_CON_SUPPORT 0 +#endif // (BLE_CENTRAL || BLE_PERIPHERAL) +#else //(BLE_EMB_PRESENT || BLE_HOST_PRESENT) +#define HCI_BLE_CON_SUPPORT 0 +#endif //(BLE_EMB_PRESENT || BLE_HOST_PRESENT) + +/// Length of HCI Reset Message +#define HCI_RESET_MSG_LEN 4 + +/// HCI Reset Message use to resync. +#define HCI_RESET_MSG_BUF {HCI_CMD_MSG_TYPE, (HCI_RESET_CMD_OPCODE & 0xFF), ((HCI_RESET_CMD_OPCODE >> 8) & 0xFF), 0} + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + +/// Message API of the HCI task +enum HCI_MSG +{ + HCI_MSG_ID_FIRST = TASK_FIRST_MSG(TASK_ID_HCI), + + HCI_CMD_CMP_EVENT, + HCI_CMD_STAT_EVENT, + HCI_EVENT, + HCI_LE_EVENT, + + HCI_COMMAND, + +#if (HCI_BLE_CON_SUPPORT) + HCI_ACL_DATA_RX, + HCI_ACL_DATA_TX, +#endif // (HCI_BLE_CON_SUPPORT) + +#if BT_EMB_PRESENT + HCI_BT_ACL_DATA_TX, + HCI_BT_ACL_DATA_RX, +#if VOICE_OVER_HCI + HCI_BT_SYNC_DATA_TX, + HCI_BT_SYNC_DATA_RX, +#endif //VOICE_OVER_HCI +#endif //BT_EMB_PRESENT + + HCI_TCI_LMP, + + HCI_DBG_EVT, + + HCI_MSG_ID_LAST +}; + +/// Status of HCI command header processing +enum HCI_CMD_HDR +{ + /// Header is correct + HCI_CMD_HDR_STATUS_OK, + /// Opcode is unknown + HCI_CMD_HDR_STATUS_UNKNOWN, + /// Header is not correct + HCI_CMD_HDR_STATUS_FAIL +}; + + + +///HCI Command header components structure +struct hci_cmd_hdr +{ + /// Opcode field + uint16_t opcode; + ///Parameter length - the number of bytes of the command parameters + uint8_t parlen; +}; + +///HCI ACL data packets header structure +struct hci_acl_hdr +{ + ///Connection handle & Data Flags + uint16_t hdl_flags; + ///Data length in number of bytes + uint16_t datalen; +}; + +#if (BT_EMB_PRESENT) +#if (VOICE_OVER_HCI) +///HCI synchronous data packets header structure +struct hci_sync_hdr +{ + /// Connection handle & Data Flags + uint16_t conhdl_flags; + /// Data total length in number of bytes + uint8_t data_total_len; +}; +#endif // (VOICE_OVER_HCI) +#endif // (BT_EMB_PRESENT) + +///HCI Event header components structure - contains all details possible in an event +struct hci_evt_hdr +{ + ///Event code + uint8_t code; + ///Event parameters length + uint8_t parlen; +}; + +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ + + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** +**************************************************************************************** +* @brief Initialize HCI (including transport) +***************************************************************************************** +*/ +void hci_init(void); + +/** +**************************************************************************************** +* @brief Reset HCI +***************************************************************************************** +*/ +void hci_reset(void); + +#if (BLE_EMB_PRESENT || BT_EMB_PRESENT) +/** + **************************************************************************************** + * @brief Function called when an internal task needs to send a HCI message to Host + * + * This function decides whether the message is sent externally onto HCI Transport Layer + * or redirected into an internal task of the other side of the HCI. + * + * The input message ID, length and parameters must be filled. + * In case the message is an HCI command or event, the source ID must be filled with the + * command opcode or event code. + * In case the message concerns a particular BT or BLE link, the destination ID must be + * filled with the associated link ID. + * + * @param[in] param Pointer to the parameters of the Kernel message carrying the HCI message + ***************************************************************************************** + */ +void hci_send_2_host(void *param); +#endif // (BLE_EMB_PRESENT || BT_EMB_PRESENT) + +#if BLE_HOST_PRESENT +/** + **************************************************************************************** + * @brief Function called when an internal task needs to send a HCI message to Controller + * + * This function decides whether the message is sent externally onto HCI Transport Layer + * or redirected into an internal task of the other side of the HCI. + * + * The input message ID, length and parameters must be filled. + * In case the message is an HCI command or event, the source ID must be filled with the + * command opcode or event code. + * In case the message concerns a particular BT or BLE link, the destination ID must be + * filled with the associated link ID. + * + * @param[in] param Pointer to the parameters of the Kernel message carrying the HCI message + ***************************************************************************************** + */ +void hci_send_2_controller(void *param); +#endif //BLE_HOST_PRESENT + +#if (BT_EMB_PRESENT) +/** + **************************************************************************************** + * @brief Register BD address for a BT ACL connection + * + * @param[in] link_id BT ACL connection link ID + * @param[in] bd_addr Pointer to the device BD address associated to the connection + ***************************************************************************************** + */ +void hci_bt_acl_bdaddr_register(uint8_t link_id, struct bd_addr *bd_addr); +/** + **************************************************************************************** + * @brief Register connection handle for a BT ACL connection + * + * @param[in] link_id BT ACL connection link ID + ***************************************************************************************** + */ +void hci_bt_acl_conhdl_register(uint8_t link_id); + +/** + **************************************************************************************** + * @brief Unregister a BT ACL connection + * + * @param[in] link_id BT ACL connection link ID + ***************************************************************************************** + */ +void hci_bt_acl_bdaddr_unregister(uint8_t link_id); + +#endif //(BT_EMB_PRESENT) + +/** + **************************************************************************************** + * @brief Set the event mask + * + * @param[in] evt_msk Pointer to the new event mask + * @param[in] page indicate which event page should be changed + * + * @return The status of the event mask saving + ***************************************************************************************** + */ +uint8_t hci_evt_mask_set(struct evt_mask const *evt_msk, uint8_t page); + +#if (BT_EMB_PRESENT) +/** + **************************************************************************************** + * @brief Add an event filter according to the parameters of the HCI command + * + * Note: the consistency of the parameters according to the input has already been checked by HCI during the special + * unpacking. + * + * @param[in] param Pointer to the HCI parameter + * + * @return The status of the filter addition + ***************************************************************************************** + */ +uint8_t hci_evt_filter_add(struct hci_set_evt_filter_cmd const *param); + +#if (MAX_NB_SYNC > 0) +/** + **************************************************************************************** + * @brief Get voice setting (for SCO auto-accept via event filter) + * + * @return Voice settings + ***************************************************************************************** + */ +uint16_t hci_voice_settings_get(void); + +/** + **************************************************************************************** + * @brief Set voice setting (for SCO auto-accept via event filter) + * + * @param[in] voice_settings Voice settings + * + * @return Status (0: Success | Others: failure) + ***************************************************************************************** + */ +uint8_t hci_voice_settings_set(uint16_t voice_settings); +#endif // (MAX_NB_SYNC > 0) +#endif //(BT_EMB_PRESENT) + +#if (HCI_TL_SUPPORT) +#if (BLE_EMB_PRESENT || BT_EMB_PRESENT) +/** + **************************************************************************************** + * @brief Get the maximum parameter size for a specific command + * + * This function is used by TL to know the theoretical maximum parameters size for a + * specific HCI command. + * Note: if the command is not supported by HCI (unknown), the maximum possible value of + * 255 bytes is returned. + * + * @param[in] opcode Opcode received + * + * @return The command maximum parameters size / 255 if command is unknown + ***************************************************************************************** + */ +uint8_t hci_cmd_get_max_param_size(uint16_t opcode); + +/** + **************************************************************************************** + * @brief Indicates that a HCI command has been received + * + * This function is used by TL to indicate the reception of a HCI command. + * + * @param[in] opcode Command Opcode + * @param[in] length Parameters length + * @param[in] payload Pointer to payload + ***************************************************************************************** + */ +void hci_cmd_received(uint16_t opcode, uint8_t length, uint8_t *payload); + +/** + **************************************************************************************** + * @brief Allocates the reception buffer for ACL TX data + * + * @param[in] hdl_flags Connection handle and data flags from HCI ACL packet header + * @param[in] len Length to receive (from HCI ACL packet header) + * + * @return Buffer for data reception (NULL if not possible to allocate one) + ***************************************************************************************** + */ +uint8_t *hci_acl_tx_data_alloc(uint16_t hdl_flags, uint16_t len); + +/** + **************************************************************************************** + * @brief Indicates that a HCI ACL TX data packet has been received + * + * This function is used by TL to indicate the reception of a HCI ACL TX data. + * + * @param[in] hdl_flags Connection handle and data flags from HCI ACL packet header + * @param[out] datalen Data length + * @param[in] payload Pointer to payload + ***************************************************************************************** + */ +void hci_acl_tx_data_received(uint16_t hdl_flags, uint16_t datalen, uint8_t *payload); + +#if (BT_EMB_PRESENT) +#if (VOICE_OVER_HCI) +/** + **************************************************************************************** + * @brief Allocates the reception buffer for Sync TX data + * + * @param[in] conhdl_flags Connection handle and data flags from HCI Sync packet header + * @param[in] len Length to receive (from HCI Sync packet header) + * + * @return Buffer for data reception (NULL if not possible to allocate one) + ***************************************************************************************** + */ +uint8_t *hci_sync_tx_data_alloc(uint16_t conhdl_flags, uint8_t len); + +/** + **************************************************************************************** + * @brief Indicates that a HCI Sync TX data packet has been received + * + * This function is used by TL to indicate the reception of a HCI Sync TX data. + * + * @param[in] conhdl_flags Connection handle and data flags from HCI Sync packet header + * @param[in] len Length to receive (from HCI Sync packet header) + * @param[in] payload Pointer to payload + ***************************************************************************************** + */ +void hci_sync_tx_data_received(uint16_t conhdl_flags, uint8_t len, uint8_t *payload); +#endif // (VOICE_OVER_HCI) +#endif // (BT_EMB_PRESENT) +#endif // (BLE_EMB_PRESENT || BT_EMB_PRESENT) + +#if ((BLE_HOST_PRESENT) && (!BLE_EMB_PRESENT)) +/** + **************************************************************************************** + * @brief Allocates the reception buffer for ACL RX data + * + * @param[in] hdl_flags Connection handle and data flags from HCI ACL RX packet header + * @param[in] len Length to receive (from HCI ACL packet header) + * + * @return Buffer for data reception (NULL if not possible to allocate one) + ***************************************************************************************** + */ +uint8_t *hci_acl_rx_data_alloc(uint16_t hdl_flags, uint16_t len); + +/** + **************************************************************************************** + * @brief Indicates that a HCI ACL RX data packet has been received + * + * This function is used by TL to indicate the reception of a HCI ACL RX data. + * + * @param[in] hdl_flags Connection handle and data flags from HCI ACL packet header + * @param[out] datalen Data length + * @param[in] payload Pointer to payload + ***************************************************************************************** + */ +void hci_acl_rx_data_received(uint16_t hdl_flags, uint16_t datalen, uint8_t *payload); + +/** + **************************************************************************************** + * @brief Indicates that a HCI event has been received + * + * This function is used by TL to indicate the reception of a HCI event. + * + * @param[in] code Event code + * @param[in] length Parameters length + * @param[in] payload Pointer to payload + * + * @return status of receive operation + ***************************************************************************************** + */ +uint8_t hci_evt_received(uint8_t code, uint8_t length, uint8_t *payload); +#endif // ((BLE_HOST_PRESENT) && (!BLE_EMB_PRESENT)) +#endif // HCI_TL_SUPPORT + +//common for both BLE & BT +/** + **************************************************************************************** + * @brief process HostBufferSize + * + * @param[in] acl_pkt_len ACL packet length + * @param[in] nb_acl_pkts Number of ACL packets + * + * @return status + ***************************************************************************************** + */ +uint8_t hci_fc_acl_buf_size_set(uint16_t acl_pkt_len, uint16_t nb_acl_pkts); +/** + **************************************************************************************** + * @brief process HostBufferSize + * + * @param[in] sync_pkt_len SYNC packet length + * @param[in] nb_sync_pkts Number of SYNC packets + * + * @return status + ***************************************************************************************** + */ +uint8_t hci_fc_sync_buf_size_set(uint8_t sync_pkt_len, uint16_t nb_sync_pkts); + +/** + **************************************************************************************** + * @brief set the state of the ACL flow control + * + * @param[in] flow_enable boolean state of control + * + * @return status + ***************************************************************************************** + */ +uint8_t hci_fc_acl_en(bool flow_enable); + +/** + **************************************************************************************** + * @brief set the state of the SYNC flow control + * + * @param[in] flow_enable boolean state of control + ***************************************************************************************** + */ +void hci_fc_sync_en(bool flow_enable); + +/** + **************************************************************************************** + * @brief update data packet counters according to HostNumberOfCompletePackets + * + * @param[in] acl_pkt_nb accumulated number for ACL handles + ***************************************************************************************a** + */ +void hci_fc_host_nb_acl_pkts_complete(uint16_t acl_pkt_nb); + +/** + **************************************************************************************** + * @brief update data packet counters according to HostNumberOfCompletePackets + * + * @param[in] sync_pkt_nb accumulated number for SCO handles + ***************************************************************************************a** + */ +void hci_fc_host_nb_sync_pkts_complete(uint16_t sync_pkt_nb); + +#endif //HCI_PRESENT + +/// @} HCI + +#endif // HCI_H_ diff --git a/beken_os/beken378/driver/ble/ble_lib/ip/hci/src/hci_int.h b/beken_os/beken378/driver/ble/ble_lib/ip/hci/src/hci_int.h new file mode 100755 index 0000000..7030da4 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/ip/hci/src/hci_int.h @@ -0,0 +1,494 @@ +/** + **************************************************************************************** + * + * @file hci.h + * + * @brief This file contains definitions related to the HCI module. + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef HCI_INT_H_ +#define HCI_INT_H_ + +/** + **************************************************************************************** + * @addtogroup HCI Host Controller Interface + *@{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" // SW configuration + +#if (HCI_PRESENT) + +#include // standard definition +#include // standard integer +#include "common_bt.h" // BT standard definitions + +#include "kernel_msg.h" // Kernel message definitions + +/* + * DEFINES + **************************************************************************************** + */ + +/// Macro to get OCF of a known command +#define OCF(cmd) (HCI_OP2OCF(HCI_##cmd##_CMD_OPCODE)) + +/// Unknown opcode identifier +#define HCI_OPCODE_UNKNOWN 0xFFFF + +/** + * Destination field decoding + * + * bit | 7 6 | 5 4 | 3..0 | + * def | Rsvd (pkupk) | HL | LL | + */ +#define HCI_CMD_DEST_LL_POS 0 +#define HCI_CMD_DEST_LL_MASK 0x0F +#define HCI_CMD_DEST_HL_POS 4 +#define HCI_CMD_DEST_HL_MASK 0x30 + +/** + * Destination field decoding + * + * bit | 7..2 | 1 0 | + * def | Rsvd | HL | + */ +#define HCI_EVT_DEST_HL_POS 0 +#define HCI_EVT_DEST_HL_MASK 0x03 + +#if (HCI_TL_SUPPORT) + +/// Special Pack-Unpack settings for HCI commands (parameters and return parameters) +/** + * Special Pack-Unpack settings for HCI commands (parameters and return parameters) + * + * bit | 7 | 6 | 5..0 | + * def | RET PAR | PAR | Rsvd | + */ +#define HCI_CMD_DEST_SPEC_PAR_PK_POS 6 +#define HCI_CMD_DEST_SPEC_PAR_PK_MSK 0x40 +#define HCI_CMD_DEST_SPEC_RET_PAR_PK_POS 7 +#define HCI_CMD_DEST_SPEC_RET_PAR_PK_MSK 0x80 +#define PK_GEN_GEN (0x00) +#define PK_GEN_SPE (HCI_CMD_DEST_SPEC_RET_PAR_PK_MSK) +#define PK_SPE_GEN (HCI_CMD_DEST_SPEC_PAR_PK_MSK) +#define PK_SPE_SPE (HCI_CMD_DEST_SPEC_RET_PAR_PK_MSK | HCI_CMD_DEST_SPEC_PAR_PK_MSK) + +/// Special Pack settings for HCI events +#define PK_GEN 0x00 +#define PK_SPE 0x01 + +/// Macro for building a command descriptor in split mode (with parameters packing/unpacking) +#define CMD(opcode, dest_ll, dest_hl, pkupk, par_size_max, par_fmt, ret_fmt) {HCI_##opcode##_CMD_OPCODE, (dest_ll< 0) + /** + * Voice settings used when SCO connection is auto-accepted + */ + uint16_t voice_settings; +#endif //(MAX_NB_SYNC > 0) + + /** + * Auto-reject flag, used to filter the complete event when a request has been auto-rejected + */ + bool auto_reject; + +#elif (BLE_HOST_PRESENT && !BLE_EMB_PRESENT && (BLE_CENTRAL || BLE_PERIPHERAL)) + /// Link association table for BLE link-oriented messages routing + struct hci_ble_acl_con_tag ble_acl_con_tab[BLE_CONNECTION_MAX]; + +#endif //(BT_EMB_PRESENT || (BLE_HOST_PRESENT && !BLE_EMB_PRESENT)) +}; + +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ + +#if BLE_HOST_PRESENT +extern const uint8_t hl_task_type[]; +#endif //BLE_HOST_PRESENT + +///HCI environment context +extern struct hci_env_tag hci_env; + + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** +**************************************************************************************** +* @brief Look for a command descriptor that could match with the specified opcode +* +* @param[in] opcode Command opcode +* +* @return Pointer the command descriptor (NULL if not found) +***************************************************************************************** +*/ +const struct hci_cmd_desc_tag *hci_look_for_cmd_desc(uint16_t opcode); + +/** +**************************************************************************************** +* @brief Look for an event descriptor that could match with the specified event code +* +* @param[in] code event code +* +* @return Pointer the event descriptor (NULL if not found) +***************************************************************************************** +*/ +const struct hci_evt_desc_tag *hci_look_for_evt_desc(uint8_t code); + + +/** +**************************************************************************************** +* @brief Look for an event descriptor that could match with the specified DBG subcode +* +* @param[in] subcode DBG event subcode +* +* @return Pointer the event descriptor (NULL if not found) +***************************************************************************************** +*/ +const struct hci_evt_desc_tag *hci_look_for_dbg_evt_desc(uint8_t subcode); + +#if (BLE_EMB_PRESENT || BLE_HOST_PRESENT) +/** +**************************************************************************************** +* @brief Look for an event descriptor that could match with the specified LE subcode +* +* @param[in] subcode LE event subcode +* +* @return Pointer the event descriptor (NULL if not found) +***************************************************************************************** +*/ +const struct hci_evt_desc_tag *hci_look_for_le_evt_desc(uint8_t subcode); + +#endif //(BLE_EMB_PRESENT || BLE_HOST_PRESENT) + +#if (HCI_TL_SUPPORT) +/** + **************************************************************************************** + * @brief Initialize HIC TL part + ***************************************************************************************** + */ +void hci_tl_init(bool reset); + +/** + **************************************************************************************** + * @brief Send an HCI message over TL + * + * @param[in] msg Kernel message carrying the HCI message + ***************************************************************************************** + */ +void hci_tl_send(struct kernel_msg *msg); + +/** + **************************************************************************************** + * @brief Pack parameters + * + * This function packs parameters according to a specific format. It takes care of the + * endianess, padding, required by the compiler. + * + * @param[inout] inout Data Buffer + * @param[inout] inout_len Input: buffer size / Output: size of packed data + * @param[in] format Parameters format + * + * @return Status of the packing operation + ***************************************************************************************** + */ +enum HCI_PACK_STATUS hci_util_pack(uint8_t *inout, uint16_t *inout_len, const char *format); + +/** + **************************************************************************************** + * @brief Unpack parameters + * + * This function unpacks parameters according to a specific format. It takes care of the + * endianess, padding, required by the compiler. + * + * Note: the buffer provided must be large enough to contain the unpacked data. + * + * @param[out] out Unpacked parameters buffer + * @param[in] in Packed parameters buffer + * @param[inout] out_len Input: buffer size / Output: size of unpacked data + * @param[in] in_len Size of the packed data + * @param[in] format Parameters format + * + * @return Status of the unpacking operation + ***************************************************************************************** + */ +enum HCI_PACK_STATUS hci_util_unpack(uint8_t *out, uint8_t *in, uint16_t *out_len, uint16_t in_len, const char *format); +#endif //(HCI_TL_SUPPORT) + +/** + **************************************************************************************** + * @brief Initialize Flow Control Structure + * + ***************************************************************************************** + */ +void hci_fc_init(void); + +/** + **************************************************************************************** + * @brief count ACL packets sent to Host + * + ***************************************************************************************** + */ +void hci_fc_acl_packet_sent(void); + +/** + **************************************************************************************** + * @brief count SCO packets sent to Host + * + ***************************************************************************************** + */ +void hci_fc_sync_packet_sent(void); + +/** + **************************************************************************************** + * @brief Calculate number of ACL packets slots available on Host side + * + * @return number of packets available + ***************************************************************************************** + */ +uint16_t hci_fc_check_host_available_nb_acl_packets(void); + +/** + **************************************************************************************** + * @brief Calculate number of SCO packets slots available on Host side + * + * @return number of packets available + ***************************************************************************************** + */ +uint16_t hci_fc_check_host_available_nb_sync_packets(void); + + +#endif //HCI_PRESENT + +/// @} HCI + +#endif // HCI_INT_H_ diff --git a/beken_os/beken378/driver/ble/ble_lib/modules/h4tl/api/h4tl.h b/beken_os/beken378/driver/ble/ble_lib/modules/h4tl/api/h4tl.h new file mode 100755 index 0000000..2f2ae3d --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/modules/h4tl/api/h4tl.h @@ -0,0 +1,148 @@ +/** + **************************************************************************************** + * + * @file h4tl.h + * + * @brief H4 UART Transport Layer header file. + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef H4TL_H_ +#define H4TL_H_ + +/** + **************************************************************************************** + * @addtogroup H4TL H4 UART Transport Layer + * @ingroup H4TL + * @brief H4 UART Transport Layer + * + * This module creates the abstraction between External UART driver and HCI generic functions + * (designed for H4 UART transport layer). + * + * @{ + **************************************************************************************** + */ + + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" // stack configuration + +#if (H4TL_SUPPORT) +#include "rwip.h" // SW interface + +#include // standard integer definition +#include // standard boolean definition + +/* + * DEFINES + **************************************************************************************** + */ +#define H4TL_LOGICAL_CHANNEL_LEN (1) + + +/// Type of transport layer +enum h4tl_type +{ +#if (BLE_HOST_PRESENT) +#if (BLE_EMB_PRESENT) // FULL HOST + /// Application Controller Interface Transport Layer + H4TL_TYPE_AHI = 0, +#if(HCI_TL_SUPPORT) + /// Host Controller Interface Transport Layer + H4TL_TYPE_HCI = 0, +#endif // (HCI_TL_SUPPORT) +#else // !(BLE_EMB_PRESENT) // SPLIT HOST +#if(AHI_TL_SUPPORT) + /// Application Controller Interface Transport Layer + H4TL_TYPE_AHI, +#endif // AHI_TL_SUPPORT + /// Host Controller Interface Transport Layer + H4TL_TYPE_HCI, +#endif // (BLE_EMB_PRESENT) +#else // !(BLE_HOST_PRESENT) // SPLIT EMB + /// Host Controller Interface Transport Layer + H4TL_TYPE_HCI = 0, +#endif // (BLE_HOST_PRESENT) + + H4TL_TYPE_MAX, +}; + + +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ + + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ +/** + **************************************************************************************** + * @brief H4TL transport initialization. + * + * Puts the External Interface driver in reception, waiting for simple 1 byte message type. Space for + * reception is allocated with kernel_msg_alloc and the pointer is handed to env.rx. RX + * interrupt is enabled. + * + * @param[in] tl_type Transport Layer Type (@see enum h4tl_type) + * @param[in] len Length of the buffer to be transmitted. + * + ***************************************************************************************** + */ +//void h4tl_init(uint8_t tl_type, const struct rwip_eif_api* eif); + +void h4tl_init(uint8_t tl_type, const struct rwip_eif_api *eif, uint8_t *cur_read_idx); +/** + **************************************************************************************** + * @brief H4TL write function. + * + * @param[in] type Type of the buffer to be transmitted. It can take one of the following + * values: + * - @ref HCI_EVT_MSG_TYPE for event message + * - @ref HCI_ACL_MSG_TYPE for ACL data + * - @ref HCI_SYNC_MSG_TYPE for synchronous data + * + * @param[in] buf Pointer to the buffer to be transmitted. @note The buffer passed as + * parameter must have one free byte before the first payload byte, so that the H4TL + * module can put the type byte as first transmitted data. + * + * @param[in] len Length of the buffer to be transmitted. + * @param[in] tx_callback Callback for indicating the end of transfer + ***************************************************************************************** + */ +void h4tl_write(uint8_t type, uint8_t *buf, uint16_t len, void (*tx_callback)(void)); + +#if DEEP_SLEEP +/** + **************************************************************************************** + * @brief Start External Interface input flow + * + ***************************************************************************************** + */ +void h4tl_start(void); + +/** + **************************************************************************************** + * @brief Stop External Interface input flow if possible + * + * @return true if External Interface flow was stopped, false otherwise + ***************************************************************************************** + */ +bool h4tl_stop(void); +#endif //DEEP_SLEEP + +#endif //H4TL_SUPPORT + +/// @} H4TL + +#endif // H4TL_H_ diff --git a/beken_os/beken378/driver/ble/ble_lib/modules/ke/api/kernel.h b/beken_os/beken378/driver/ble/ble_lib/modules/ke/api/kernel.h new file mode 100755 index 0000000..4524c33 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/modules/ke/api/kernel.h @@ -0,0 +1,103 @@ +/** + **************************************************************************************** + * + * @file kernel.h + * + * @brief This file contains the definition of the kernel environment. + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef _KERNEL_H_ +#define _KERNEL_H_ + +/** + **************************************************************************************** + * @addtogroup ENV Environment + * @ingroup KERNEL + * @brief Kernel Environment + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" // stack configuration + +#include // standard boolean definitions +#include // standard integer definitions + +/* + * ENUMERATION + **************************************************************************************** + */ + +/// Kernel Error Status +enum KERNEL_STATUS +{ + KERNEL_SUCCESS = 0, + KERNEL_FAIL +}; + + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief This function performs all the initializations of the kernel. + * + * It initializes first the heap, then the message queues and the events. Then if required + * it initializes the trace. + * + **************************************************************************************** + */ +void kernel_init(void); + +/** + **************************************************************************************** + * @brief This function flushes all messages, timers and events currently pending in the + * kernel. + * + **************************************************************************************** + */ +void kernel_flush(void); + +/** + **************************************************************************************** + * @brief This function checks if sleep is possible or kernel is processing + * + * @return True if sleep is allowed, false otherwise + **************************************************************************************** + */ +bool kernel_sleep_check(void); + +#if (KERNEL_PROFILING) +/** + **************************************************************************************** + * @brief This function gets the statistics of the kernel usage. + * + * @param[out] max_msg_sent Max message sent + * @param[out] max_msg_saved Max message saved + * @param[out] max_timer_used Max timer used + * @param[out] max_heap_used Max heap used + **************************************************************************************** + */ +enum KERNEL_STATUS kernel_stats_get(uint8_t* max_msg_sent, + uint8_t* max_msg_saved, + uint8_t* max_timer_used, + uint16_t* max_heap_used); +#endif //KERNEL_PROFILING + +/// @} KE + +#endif // _KERNEL_H_ diff --git a/beken_os/beken378/driver/ble/ble_lib/modules/ke/api/kernel_config.h b/beken_os/beken378/driver/ble/ble_lib/modules/ke/api/kernel_config.h new file mode 100755 index 0000000..34e7f22 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/modules/ke/api/kernel_config.h @@ -0,0 +1,60 @@ +/** + **************************************************************************************** + * + * @file kernel_config.h + * + * @brief This file contains all the constant that can be changed in order to + * tailor the kernel. + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef _KERNEL_CONFIG_H_ +#define _KERNEL_CONFIG_H_ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_config.h" // stack configuration + +/** + **************************************************************************************** + * @addtogroup KERNEL KERNEL + * @ingroup ROOT + * @brief The Kernel module. + * + * The Kernel is responsible for providing essential OS features like time management, + * inter-task communication, task management and message handling and administration. + * + * @{ + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @addtogroup CFG Settings and Configuration + * @ingroup KERNEL + * @brief Kernel Configuration + * + * @{ + **************************************************************************************** + */ + +/* + * CONSTANT DEFINITIONS + **************************************************************************************** + */ +#define KERNEL_MEM_RW 1 +#define KERNEL_MEM_LINUX 0 +#define KERNEL_MEM_LIBC 0 + +#define KERNEL_FULL 1 +#define KERNEL_SEND_ONLY 0 + +/// @} CFG + +#endif // _KERNEL_CONFIG_H_ diff --git a/beken_os/beken378/driver/ble/ble_lib/modules/ke/api/kernel_event.h b/beken_os/beken378/driver/ble/ble_lib/modules/ke/api/kernel_event.h new file mode 100755 index 0000000..4890e84 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/modules/ke/api/kernel_event.h @@ -0,0 +1,152 @@ +/** + **************************************************************************************** + * + * @file kernel_event.h + * + * @brief This file contains the definition related to kernel events. + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef _KERNEL_EVENT_H_ +#define _KERNEL_EVENT_H_ + +/** + **************************************************************************************** + * @addtogroup EVT Events and Schedule + * @ingroup KERNEL + * @brief Event scheduling module. + * + * The KERNEL_EVT module implements event scheduling functions. It can be used to + * implement deferred actions. + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" // stack configuration + +#include // standard integer definition + + +/* + * CONSTANTS + **************************************************************************************** + */ + + +/// Status of kernel_task API functions +enum KERNEL_EVENT_STATUS +{ + KERNEL_EVENT_OK = 0, + KERNEL_EVENT_FAIL, + KERNEL_EVENT_UNKNOWN, + KERNEL_EVENT_CAPA_EXCEEDED, + KERNEL_EVENT_ALREADY_EXISTS, +}; + + +/* + * TYPE DEFINITION + **************************************************************************************** + */ + + + + +/* + * FUNCTION PROTOTYPES + **************************************************************************************** + */ + + + +/** + **************************************************************************************** + * @brief Initialize Kernel event module. + **************************************************************************************** + */ +void kernel_event_init(void); + +/** + **************************************************************************************** + * @brief Register an event callback. + * + * @param[in] event_type Event type. + * @param[in] p_callback Pointer to callback function. + * + * @return Status + **************************************************************************************** + */ +uint8_t kernel_event_callback_set(uint8_t event_type, void (*p_callback)(void)); + +/** + **************************************************************************************** + * @brief Set an event + * + * This primitive sets one event. It will trigger the call to the corresponding event + * handler in the next scheduling call. + * + * @param[in] event_type Event to be set. + **************************************************************************************** + */ +void kernel_event_set(uint8_t event_type); + +/** + **************************************************************************************** + * @brief Clear an event + * + * @param[in] event_type Event to be cleared. + **************************************************************************************** + */ +void kernel_event_clear(uint8_t event_type); + +/** + **************************************************************************************** + * @brief Get the status of an event + * + * @param[in] event_type Event to get. + * + * @return Event status (0: not set / 1: set) + **************************************************************************************** + */ +uint8_t kernel_event_get(uint8_t event_type); + +/** + **************************************************************************************** + * @brief Get all event status + * + * @return Events bit field + **************************************************************************************** + */ +uint32_t kernel_event_get_all(void); + +/** + **************************************************************************************** + * @brief Flush all pending events. + **************************************************************************************** + */ +void kernel_event_flush(void); + +/** + **************************************************************************************** + * @brief Event scheduler entry point. + * + * This primitive is the entry point of Kernel event scheduling. + **************************************************************************************** + */ +void kernel_event_schedule(void); + + + +/// @} EVT + +#endif //_KERNEL_EVENT_H_ diff --git a/beken_os/beken378/driver/ble/ble_lib/modules/ke/api/kernel_mem.h b/beken_os/beken378/driver/ble/ble_lib/modules/ke/api/kernel_mem.h new file mode 100755 index 0000000..ae65b11 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/modules/ke/api/kernel_mem.h @@ -0,0 +1,192 @@ +/** + **************************************************************************************** + * + * @file kernel_mem.h + * + * @brief API for the heap management module. + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef _KERNEL_MEM_H_ +#define _KERNEL_MEM_H_ + +#include "rwip_config.h" // IP configuration +#include // standard integer +#include // standard includes + +#include "kernel_config.h" // kernel configuration + +/** + **************************************************************************************** + * @defgroup MEM Memory + * @ingroup KERNEL + * @brief Heap management module. + * + * This module implements heap management functions that allow initializing heap, + * allocating and freeing memory. + * + * @{ + **************************************************************************************** + */ + +#if (KERNEL_MEM_RW) + + +// forward declarations +struct mblock_free; + +/** + **************************************************************************************** + * @brief Heap initialization. + * + * This function performs the following operations: + * - sanity checks + * - check memory allocated is at least large enough to hold two block descriptors to hold + * start and end + * - initialize the first and last descriptors + * - save heap into kernel environment variable. + * + * @param[in] type Memory type. + * @param[in|out] heap Heap pointer + * @param[in] heap_size Size of the heap + * + * + **************************************************************************************** + */ +void kernel_mem_init(uint8_t type, uint8_t* heap, uint16_t heap_size); + +/** + **************************************************************************************** + * @brief Allocation of a block of memory. + * + * Allocates a memory block whose size is size; if no memory is available return NULL + * + * @param[in] size Size of the memory area that need to be allocated. + * @param[in] type Type of memory block + * + * @return A pointer to the allocated memory area. + * + **************************************************************************************** + */ +void *kernel_malloc(uint32_t size, uint8_t type); + + +/** + **************************************************************************************** + * @brief Check if it's possible to allocate a block of memory with a specific size. + * + * @param[in] size Size of the memory area that need to be allocated. + * @param[in] type Type of memory block + * + * @return True if memory block can be allocated, False else. + * + **************************************************************************************** + */ +bool kernel_check_malloc(uint32_t size, uint8_t type); + +/** + **************************************************************************************** + * @brief Freeing of a block of memory. + * + * Free the memory area pointed by mem_ptr : mark the block as free and insert it in + * the pool of free block. + * + * @param[in] mem_ptr Pointer to the memory area that need to be freed. + * + **************************************************************************************** + */ +void kernel_free(void *mem_ptr); + + +/** + **************************************************************************************** + * @brief Check if current heap is empty or not (not used) + * + * @param[in] type Type of memory heap block + * + * @return true if heap not used, false else. + **************************************************************************************** + */ +bool kernel_mem_is_empty(uint8_t type); + + + +/** + **************************************************************************************** + * @brief Check if current pointer is free or not + * + * @param[in] mem_ptr pointer to a memory block + * + * @return true if already free, false else. + **************************************************************************************** + */ +bool kernel_is_free(void* mem_ptr); + +#if (KERNEL_PROFILING) + +/** + **************************************************************************************** + * @brief Retrieve memory usage of selected heap. + * + * @param[in] type Type of memory heap block + * + * @return current memory usage of current heap. + **************************************************************************************** + */ +uint16_t kernel_get_mem_usage(uint8_t type); + + +/** + **************************************************************************************** + * @brief Retrieve max memory usage of all heap. + * This command also resets max measured value. + * + * @return max memory usage of all heap. + **************************************************************************************** + */ +uint32_t kernel_get_max_mem_usage(void); + +#endif // (KERNEL_PROFILING) + + + + +#elif (KERNEL_MEM_LINUX) +// Wrappers to Linux mem functions here + +#include + +__INLINE void *kernel_malloc(uint32_t size) +{ + return kmalloc(size, GFP_KERNEL); +} + +__INLINE void kernel_free (void * mem_ptr) +{ + kfree(mem_ptr); +} + +#elif (KERNEL_MEM_LIBC) +// Wrapper to lib C mem functions here +#include + +__INLINE void *kernel_malloc(uint32_t size) +{ + return malloc(size); +} + +__INLINE void kernel_free(void *mem_ptr) +{ + free(mem_ptr); +} + +#endif // KERNEL_MEM_RW + +///@} MEM + +#endif // _KERNEL_MEM_H_ + diff --git a/beken_os/beken378/driver/ble/ble_lib/modules/ke/api/kernel_msg.h b/beken_os/beken378/driver/ble/ble_lib/modules/ke/api/kernel_msg.h new file mode 100755 index 0000000..9399f8f --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/modules/ke/api/kernel_msg.h @@ -0,0 +1,319 @@ +/** + **************************************************************************************** + * + * @file kernel_msg.h + * + * @brief This file contains the definition related to message scheduling. + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef _KERNEL_MSG_H_ +#define _KERNEL_MSG_H_ + +/** + **************************************************************************************** + * @defgroup MSG Message Exchange + * @ingroup KERNEL + * @brief Message scheduling module. + * + * The MSG module implements message scheduling functions. + + * A kernel message has an ID, a receiver task ID and a source task ID. + * In most cases, it also has parameters which are defined in + * a structure dynamically embedded in the message structure, + * so the whole message will be managed internally as one block. + * + * A message can also have one extra parameter which is referenced + * in the normal parameter structure. This extra block is assumed + * to be large by the kernel and will be moved by DMA if needed. + * This feature allows moving MMPDU from LMAC to UMAC. + * + * In order to send a message, a function first have to allocate + * the memory for this message. It can be done with the wrapper + * macro KERNEL_MSG_ALLOC() (which will call kernel_msg_alloc()). + + * The message can then be sent with kernel_msg_send(). The kernel + * will take care of freeing the allocated memory. + + * If the message has no parameters, the kernel_msg_send_basic() function + * can be used. + * + * @{ + **************************************************************************************** + */ + +#include // standard definition +#include // standard integer +#include // standard boolean +#include "architect.h" // architectural definition +#include "ble_compiler.h" // compiler definition +#include "kernel_config.h" // kernel configuration +#include "common_list.h" // list definition + +/// Task Identifier. Composed by the task type and the task index. +typedef uint16_t kernel_task_id_t; + +/// Builds the task identifier from the type and the index of that task. +#define KERNEL_BUILD_ID(type, index) ( (kernel_task_id_t)(((index) << 8)|(type)) ) + +/// Retrieves task type from task id. +#define KERNEL_TYPE_GET(kernel_task_id) ((kernel_task_id) & 0xFF) + +/// Retrieves task index number from task id. +#define KERNEL_IDX_GET(kernel_task_id) (((kernel_task_id) >> 8) & 0xFF) + +/// Task State +typedef uint8_t kernel_state_t; + +/// Message Identifier. The number of messages is limited to 0xFFFF. +/// The message ID is divided in two parts: +/// - bits[15..10] : task index (no more than 64 tasks supported). +/// - bits[9..0] : message index (no more that 1024 messages per task). +typedef uint16_t kernel_msg_id_t; + +/// Message structure. +struct kernel_msg +{ + struct common_list_hdr hdr; ///< List header for chaining + + kernel_msg_id_t id; ///< Message id. + kernel_task_id_t dest_id; ///< Destination kernel identifier. + kernel_task_id_t src_id; ///< Source kernel identifier. + uint16_t param_len; ///< Parameter embedded struct length. + uint32_t param[1]; ///< Parameter embedded struct. Must be word-aligned. +}; + + +/// Status returned by a task when handling a message +enum kernel_msg_status_tag +{ + KERNEL_MSG_CONSUMED = 0, ///< consumed, msg and ext are freed by the kernel + KERNEL_MSG_NO_FREE, ///< consumed, nothing is freed by the kernel + KERNEL_MSG_SAVED, ///< not consumed, will be pushed in the saved queue +}; + +/** + **************************************************************************************** + * @brief Convert a parameter pointer to a message pointer + * + * @param[in] param_ptr Pointer to the parameter member of a kernel_msg + * Usually retrieved by a kernel_msg_alloc() + * + * @return The pointer to the kernel_msg + **************************************************************************************** + */ +__INLINE struct kernel_msg *kernel_param2msg(void const *param_ptr) +{ + return (struct kernel_msg *) (((uint8_t *)param_ptr) - offsetof(struct kernel_msg, param)); +} + +/** + **************************************************************************************** + * @brief Convert a message pointer to a parameter pointer + * + * @param[in] msg Pointer to the kernel_msg. + * + * @return The pointer to the param member + **************************************************************************************** + */ +__INLINE void *kernel_msg2param(struct kernel_msg const *msg) +{ + return (void *) (((uint8_t *) msg) + offsetof(struct kernel_msg, param)); +} + +/** + **************************************************************************************** + * @brief Convenient wrapper to kernel_msg_alloc() + * + * This macro calls kernel_msg_alloc() and cast the returned pointer to the + * appropriate structure. Can only be used if a parameter structure exists + * for this message (otherwise, use kernel_msg_send_basic()). + * + * @param[in] id Message identifier + * @param[in] dest Destination Identifier + * @param[in] src Source Identifier + * @param[in] param_str parameter structure tag + * + * @return Pointer to the parameter member of the kernel_msg. + **************************************************************************************** + */ +#define KERNEL_MSG_ALLOC(id, dest, src, param_str) \ + (struct param_str*) kernel_msg_alloc(id, dest, src, sizeof(struct param_str)) + +/** + **************************************************************************************** + * @brief Convenient wrapper to kernel_msg_free() + * + * This macro calls kernel_msg_free() with the appropriate msg pointer as parameter, according + * to the message parameter pointer passed. + * + * @param[in] param_ptr parameter structure pointer + **************************************************************************************** + */ +#define KERNEL_MSG_FREE(param_ptr) kernel_msg_free(kernel_param2msg((param_ptr))) + +/** + **************************************************************************************** + * @brief Convenient wrapper to kernel_msg_alloc() + * + * This macro calls kernel_msg_alloc() and cast the returned pointer to the + * appropriate structure with a variable length. Can only be used if a parameter structure exists + * for this message (otherwise, use kernel_msg_send_basic()).Can only be used if the data array is + * located at the end of the structure. + * + * @param[in] id Message identifier + * @param[in] dest Destination Identifier + * @param[in] src Source Identifier + * @param[in] param_str parameter structure tag + * @param[in] length length for the data + * + * @return Pointer to the parameter member of the kernel_msg. + **************************************************************************************** + */ +#define KERNEL_MSG_ALLOC_DYN(id, dest, src, param_str,length) (struct param_str*)kernel_msg_alloc(id, dest, src, \ + (sizeof(struct param_str) + (length))); + +/** + **************************************************************************************** + * @brief Allocate memory for a message + * + * This primitive allocates memory for a message that has to be sent. The memory + * is allocated dynamically on the heap and the length of the variable parameter + * structure has to be provided in order to allocate the correct size. + * + * Several additional parameters are provided which will be preset in the message + * and which may be used internally to choose the kind of memory to allocate. + * + * The memory allocated will be automatically freed by the kernel, after the + * pointer has been sent to kernel_msg_send(). If the message is not sent, it must + * be freed explicitly with kernel_msg_free(). + * + * Allocation failure is considered critical and should not happen. + * + * @param[in] id Message identifier + * @param[in] dest_id Destination Task Identifier + * @param[in] src_id Source Task Identifier + * @param[in] param_len Size of the message parameters to be allocated + * + * @return Pointer to the parameter member of the kernel_msg. If the parameter + * structure is empty, the pointer will point to the end of the message + * and should not be used (except to retrieve the message pointer or to + * send the message) + **************************************************************************************** + */ +void *kernel_msg_alloc(kernel_msg_id_t const id, kernel_task_id_t const dest_id, + kernel_task_id_t const src_id, uint16_t const param_len); + +/** + **************************************************************************************** + * @brief Message sending. + * + * Send a message previously allocated with any kernel_msg_alloc()-like functions. + * + * The kernel will take care of freeing the message memory. + * + * Once the function have been called, it is not possible to access its data + * anymore as the kernel may have copied the message and freed the original + * memory. + * + * @param[in] param_ptr Pointer to the parameter member of the message that + * should be sent. + **************************************************************************************** + */ + +void kernel_msg_send(void const *param_ptr); + +/** + **************************************************************************************** + * @brief Basic message sending. + * + * Send a message that has a zero length parameter member. No allocation is + * required as it will be done internally. + * + * @param[in] id Message identifier + * @param[in] dest_id Destination Identifier + * @param[in] src_id Source Identifier + **************************************************************************************** + */ +void kernel_msg_send_basic(kernel_msg_id_t const id, kernel_task_id_t const dest_id, kernel_task_id_t const src_id); + +/** + **************************************************************************************** + * @brief Message forwarding. + * + * Forward a message to another task by changing its destination and source tasks IDs. + * + * @param[in] param_ptr Pointer to the parameter member of the message that + * should be sent. + * @param[in] dest_id New destination task of the message. + * @param[in] src_id New source task of the message. + **************************************************************************************** + */ +void kernel_msg_forward(void const *param_ptr, kernel_task_id_t const dest_id, kernel_task_id_t const src_id); + +/** + **************************************************************************************** + * @brief Message forwarding. + * + * Forward a message to another task by changing its message ID and its destination and source tasks IDs. + * + * @param[in] param_ptr Pointer to the parameter member of the message that + * should be sent. + * @param[in] msg_id New ID of the message. + * @param[in] dest_id New destination task of the message. + * @param[in] src_id New source task of the message. + **************************************************************************************** + */ +void kernel_msg_forward_new_id(void const *param_ptr, + kernel_msg_id_t const msg_id, kernel_task_id_t const dest_id, kernel_task_id_t const src_id); + +/** + **************************************************************************************** + * @brief Free allocated message + * + * @param[in] msg Pointer to the message to be freed (not the parameter member!) + **************************************************************************************** + */ +void kernel_msg_free(struct kernel_msg const *param); + + + +/** + **************************************************************************************** + * @brief Retrieve destination task identifier of a kernel message + * + * @param[in] param_ptr Pointer to the parameter member of the message. + * + * @return message destination task + **************************************************************************************** + */ +kernel_msg_id_t kernel_msg_dest_id_get(void const *param_ptr); + + + +/** + **************************************************************************************** + * @brief Retrieve source task identifier of a kernel message + * + * @param[in] param_ptr Pointer to the parameter member of the message. + * + * @return message source task + **************************************************************************************** + */ +kernel_msg_id_t kernel_msg_src_id_get(void const *param_ptr); + +/** + * Used to know if message is present in kernel queue or not. + * + * @param[in] param_ptr Pointer to the parameter member of the message. + * + * @return True if message is present in Kernel Queue, False else. + */ +bool kernel_msg_in_queue(void const *param_ptr); +/// @} MSG + +#endif // _KERNEL_MSG_H_ diff --git a/beken_os/beken378/driver/ble/ble_lib/modules/ke/api/kernel_task.h b/beken_os/beken378/driver/ble/ble_lib/modules/ke/api/kernel_task.h new file mode 100755 index 0000000..887ddea --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/modules/ke/api/kernel_task.h @@ -0,0 +1,236 @@ +/** + **************************************************************************************** + * + * @file kernel_task.h + * + * @brief This file contains the definition related to kernel task management. + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef _KERNEL_TASK_H_ +#define _KERNEL_TASK_H_ + +/** + **************************************************************************************** + * @defgroup TASK Task and Process + * @ingroup KERNEL + * @brief Task management module. + * + * This module implements the functions used for managing tasks. + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include // standard integer +#include // standard boolean + +#include "rwip_config.h" // stack configuration +#include "ble_compiler.h" // compiler defines, INLINE +#include "kernel_msg.h" // kernel message defines + +/* Default Message handler code to handle several message type in same handler. */ +#define KERNEL_MSG_DEFAULT_HANDLER (0xFFFF) +/* Invalid task */ +#define KERNEL_TASK_INVALID (0xFFFF) +/* Used to know if a message is not present in kernel queue */ +#define KERNEL_MSG_NOT_IN_QUEUE ((struct common_list_hdr *) 0xFFFFFFFF) + +/// Status of kernel_task API functions +enum KERNEL_TASK_STATUS +{ + KERNEL_TASK_OK = 0, + KERNEL_TASK_FAIL, + KERNEL_TASK_UNKNOWN, + KERNEL_TASK_CAPA_EXCEEDED, + KERNEL_TASK_ALREADY_EXISTS, +}; + + +#define BLE_MSG_T(msg) ((kernel_task_id_t)((msg) >> 8)) +#define BLE_MSG_I(msg) ((msg) & ((1<<8)-1)) + +/// Format of a task message handler function +typedef int (*kernel_msg_func_t)(kernel_msg_id_t const msgid, void const *param, + kernel_task_id_t const dest_id, kernel_task_id_t const src_id); + +/// Macro for message handler function declaration or definition +#define KERNEL_MSG_HANDLER(msg_name, param_struct) __STATIC int msg_name##_handler(kernel_msg_id_t const msgid, \ + param_struct const *param, \ + kernel_task_id_t const dest_id, \ + kernel_task_id_t const src_id) + +/// Macro for message handlers table declaration or definition +#define KERNEL_MSG_HANDLER_TAB(task) __STATIC const struct kernel_msg_handler task##_default_state[] = + +/// Macro for state handler declaration or definition +#define KERNEL_MSG_STATE(task) const struct kernel_state_handler task##_default_handler = KERNEL_STATE_HANDLER(task##_default_state); + +/// Element of a message handler table. +struct kernel_msg_handler +{ + /// Id of the handled message. + kernel_msg_id_t id; + /// Pointer to the handler function for the msgid above. + kernel_msg_func_t func; +}; + +/// Element of a state handler table. +struct kernel_state_handler +{ + /// Pointer to the message handler table of this state. + const struct kernel_msg_handler *msg_table; + /// Number of messages handled in this state. + uint16_t msg_cnt; +}; + +/// Helps writing the initialization of the state handlers without errors. +#define KERNEL_STATE_HANDLER(hdl) {hdl, sizeof(hdl)/sizeof(struct kernel_msg_handler)} + +/// Helps writing empty states. +#define KERNEL_STATE_HANDLER_NONE {NULL, 0} + +/// Task descriptor grouping all information required by the kernel for the scheduling. +struct kernel_task_desc +{ + /// Pointer to the state handler table (one element for each state). + const struct kernel_state_handler *state_handler; + /// Pointer to the default state handler (element parsed after the current state). + const struct kernel_state_handler *default_handler; + /// Pointer to the state table (one element for each instance). + kernel_state_t *state; + /// Maximum number of states in the task. + uint16_t state_max; + /// Maximum index of supported instances of the task. + uint16_t idx_max; +}; + +/* + * FUNCTION PROTOTYPES + **************************************************************************************** + */ + + +/** + **************************************************************************************** + * @brief Initialize Kernel task module. + **************************************************************************************** + */ +void kernel_task_init(void); + +/** + **************************************************************************************** + * @brief Create a task. + * + * @param[in] task_type Task type. + * @param[in] p_task_desc Pointer to task descriptor. + * + * @return Status + **************************************************************************************** + */ +uint8_t kernel_task_create(uint8_t task_type, struct kernel_task_desc const *p_task_desc); + +/** + **************************************************************************************** + * @brief Delete a task. + * + * @param[in] task_type Task type. + * + * @return Status + **************************************************************************************** + */ +uint8_t kernel_task_delete(uint8_t task_type); + +/** + **************************************************************************************** + * @brief Retrieve the state of a task. + * + * @param[in] id Task id. + * + * @return Current state of the task + **************************************************************************************** + */ +kernel_state_t kernel_state_get(kernel_task_id_t const id); + +/** + **************************************************************************************** + * @brief Set the state of the task identified by its Task Id. + * + * In this function we also handle the SAVE service: when a task state changes we + * try to activate all the messages currently saved in the save queue for the given + * task identifier. + * + * @param[in] id Identifier of the task instance whose state is going to be modified + * @param[in] state_id New State + * + **************************************************************************************** + */ +void kernel_state_set(kernel_task_id_t const id, kernel_state_t const state_id); + +/** + **************************************************************************************** + * @brief Generic message handler to consume message without handling it in the task. + * + * @param[in] msgid Id of the message received (probably unused) + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id TaskId of the receiving task. + * @param[in] src_id TaskId of the sending task. + * + * @return KERNEL_MSG_CONSUMED + **************************************************************************************** + */ +int kernel_msg_discard(kernel_msg_id_t const msgid, void const *param, + kernel_task_id_t const dest_id, kernel_task_id_t const src_id); + +/** + **************************************************************************************** + * @brief Generic message handler to consume message without handling it in the task. + * + * @param[in] msgid Id of the message received (probably unused) + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id TaskId of the receiving task. + * @param[in] src_id TaskId of the sending task. + * + * @return KERNEL_MSG_CONSUMED + **************************************************************************************** + */ +int kernel_msg_save(kernel_msg_id_t const msgid, void const *param, + kernel_task_id_t const dest_id, kernel_task_id_t const src_id); + + + +/** + **************************************************************************************** + * @brief This function flushes all messages, currently pending in the kernel for a + * specific task. + * + * @param[in] task The Task Identifier that shall be flushed. + **************************************************************************************** + */ +void kernel_task_msg_flush(kernel_task_id_t task); + + +/** + **************************************************************************************** + * @brief Check validity of a task. If task type or task instance does not exist, + * return invalid task + * + * @param[in] task Task Identifier to check. + * + * @return Task identifier if valid, invalid identifier else. + **************************************************************************************** + */ +kernel_task_id_t kernel_task_check(kernel_task_id_t task); + +/// @} TASK + +#endif // _KERNEL_TASK_H_ + diff --git a/beken_os/beken378/driver/ble/ble_lib/modules/ke/api/kernel_timer.h b/beken_os/beken378/driver/ble/ble_lib/modules/ke/api/kernel_timer.h new file mode 100755 index 0000000..f337d38 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/modules/ke/api/kernel_timer.h @@ -0,0 +1,143 @@ +/** + **************************************************************************************** + * + * @file kernel_timer.h + * + * @brief This file contains the definitions used for timer management + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef _KERNEL_TIMER_H_ +#define _KERNEL_TIMER_H_ + +/** + **************************************************************************************** + * @defgroup TIMER BT Time + * @ingroup KERNEL + * @brief Timer management module. + * + * This module implements the functions used for managing kernel timers. + * + **************************************************************************************** + */ + +#include "rwip_config.h" // stack configuration +#include "kernel_msg.h" // messaging definition + + +/* + * DEFINITIONS + **************************************************************************************** + */ + +/// Convert timer from second to timer accuracy (10ms) +#define KERNEL_TIME_IN_SEC(_time) (_time * 100) + + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + +/// Timer Object +struct kernel_timer +{ + /// next ke timer + struct kernel_timer *next; + /// message identifier + kernel_msg_id_t id; + /// task identifier + kernel_task_id_t task; + /// time value + uint32_t time; +}; + + +/* + * FUNCTION PROTOTYPES + **************************************************************************************** + */ + + +/** + **************************************************************************************** + * @brief Initialize Kernel timer module. + **************************************************************************************** + */ +void kernel_timer_init(void); + +/** + **************************************************************************************** + * @brief Set a timer. + * + * The function first cancel the timer if it is already existing, then + * it creates a new one. The timer can be one-shot or periodic, i.e. it + * will be automatically set again after each trigger. + * + * When the timer expires, a message is sent to the task provided as + * argument, with the timer id as message id. + * + * The timer is programmed in time units (TU is 10ms). + * + * @param[in] timer_id Timer identifier (message identifier type). + * @param[in] task_id Task identifier which will be notified + * @param[in] delay Delay in time units. + **************************************************************************************** + */ +void kernel_timer_set(kernel_msg_id_t const timer_id, kernel_task_id_t const task, uint32_t delay); + +/** + **************************************************************************************** + * @brief Remove an registered timer. + * + * This function search for the timer identified by its id and its task id. + * If found it is stopped and freed, otherwise an error message is returned. + * + * @param[in] timer_id Timer identifier. + * @param[in] task Task identifier. + **************************************************************************************** + */ +void kernel_timer_clear(kernel_msg_id_t const timerid, kernel_task_id_t const task); + +/** + **************************************************************************************** + * @brief Checks if a requested timer is active. + * + * This function pops the first timer from the timer queue and notifies the appropriate + * task by sending a kernel message. If the timer is periodic, it is set again; + * if it is one-shot, the timer is freed. The function checks also the next timers + * and process them if they have expired or are about to expire. + **************************************************************************************** + */ +bool kernel_timer_active(kernel_msg_id_t const timer_id, kernel_task_id_t const task_id); + +/** + **************************************************************************************** + * @brief Adjust all kernel timers by specified adjustment delay. + * + * This function updates all timers to align to a new SCLK after a system clock adjust. + **************************************************************************************** + */ +void kernel_timer_adjust_all(uint32_t delay); + + +#if (DEEP_SLEEP) +/** + **************************************************************************************** + * @brief Get the first timer target (in Slot) used for deep sleep decision + * + * @return Invalid time if nothing programmed; target time else. + **************************************************************************************** + */ +bool kernel_timer_sleep_check(uint32_t *sleep_duration, uint32_t wakeup_delay); +uint32_t kernel_timer_target_get(void); + +#endif //DEEP_SLEEP + +/// @} TIMER + +#endif // _KERNEL_TIMER_H_ diff --git a/beken_os/beken378/driver/ble/ble_lib/modules/ke/src/kernel_env.h b/beken_os/beken378/driver/ble/ble_lib/modules/ke/src/kernel_env.h new file mode 100755 index 0000000..b7d4d97 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/modules/ke/src/kernel_env.h @@ -0,0 +1,69 @@ +/** + **************************************************************************************** + * + * @file kernel_env.h + * + * @brief This file contains the definition of the kernel. + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef _KERNEL_ENV_H_ +#define _KERNEL_ENV_H_ + +/** + **************************************************************************************** + * @addtogroup ENV Environment + * @ingroup KERNEL + * @brief Kernel Environment + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_config.h" // stack configuration +#include "kernel_config.h" // kernel configuration +#include "kernel_event.h" // kernel event +#include "common_list.h" // kernel queue definition + +// forward declaration +struct mblock_free; + +/// Kernel environment definition +struct kernel_env_tag +{ + /// Queue of sent messages but not yet delivered to receiver + struct common_list queue_sent; + /// Queue of messages delivered but not consumed by receiver + struct common_list queue_saved; + /// Queue of timers + struct common_list queue_timer; + +#if (KERNEL_MEM_RW) + /// Root pointer = pointer to first element of heap linked lists + struct mblock_free *heap[KERNEL_MEM_BLOCK_MAX]; + /// Size of heaps + uint16_t heap_size[KERNEL_MEM_BLOCK_MAX]; + +#if (KERNEL_PROFILING) + /// Size of heap used + uint16_t heap_used[KERNEL_MEM_BLOCK_MAX]; + /// Maximum heap memory used + uint32_t max_heap_used; +#endif //KERNEL_PROFILING +#endif //KERNEL_MEM_RW +}; + +/// Kernel environment +extern struct kernel_env_tag kernel_env; + +/// @} ENV + +#endif // _KERNEL_ENV_H_ diff --git a/beken_os/beken378/driver/ble/ble_lib/modules/ke/src/kernel_queue.h b/beken_os/beken378/driver/ble/ble_lib/modules/ke/src/kernel_queue.h new file mode 100755 index 0000000..c8041d8 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_lib/modules/ke/src/kernel_queue.h @@ -0,0 +1,108 @@ +/** + **************************************************************************************** + * + * @file kernel_queue.h + * + * @brief This file contains the definition of the message object, queue element + * object and queue object + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef _KERNEL_QUEUE_H_ +#define _KERNEL_QUEUE_H_ + +/** + **************************************************************************************** + * @addtogroup QUEUE Queues and Lists + * @ingroup KERNEL + * @brief Queue management module + * + * This module implements the functions used for managing message queues. + * These functions must not be called under IRQ! + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include // standard integer +#include // standard boolean +#include "ble_compiler.h" // compiler definitions +#include "kernel_config.h" // kernel configuration +#include "common_list.h" // list definition + +/* + * FUNCTION PROTOTYPES + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Pop entry to the queue + * + * @param[in] queue Pointer to the queue. + * @param[in] element Pointer to the element. + **************************************************************************************** + */ +__INLINE void kernel_queue_push(struct common_list *const queue, struct common_list_hdr *const element) +{ + common_list_push_back(queue, element); +} + +/** + **************************************************************************************** + * @brief Pop entry from the queue + * + * @param[in] queue Pointer to the queue. + * + * @return Pointer to the element. + **************************************************************************************** + */ +__INLINE struct common_list_hdr *kernel_queue_pop(struct common_list *const queue) +{ + return common_list_pop_front(queue); +} + +/** + **************************************************************************************** + * @brief Extracts an element matching a given algorithm. + * + * @param[in] queue Pointer to the queue. + * @param[in] func Matching function. + * @param[in] arg Match argument. + * + * @return Pointer to the element found and removed (NULL otherwise). + **************************************************************************************** + */ +struct common_list_hdr *kernel_queue_extract(struct common_list *const queue, + bool (*func)(struct common_list_hdr const *elmt, uint32_t arg), + uint32_t arg); + +/** + **************************************************************************************** + * @brief Insert an element in a sorted queue. + * + * This primitive use a comparison function from the parameter list to select where the + * element must be inserted. + * + * @param[in] queue Pointer to the queue. + * @param[in] element Pointer to the element to insert. + * @param[in] cmp Comparison function (return true if first element has to be inserted + * before the second one). + * + * @return Pointer to the element found and removed (NULL otherwise). + **************************************************************************************** + */ +void kernel_queue_insert(struct common_list *const queue, struct common_list_hdr *const element, + bool (*cmp)(struct common_list_hdr const *elementA, + struct common_list_hdr const *elementB)); + +/// @} QUEUE + +#endif // _KERNEL_QUEUE_H_ diff --git a/beken_os/beken378/driver/ble/ble_pub/ip/ble/hl/inc/rwprf_config.h b/beken_os/beken378/driver/ble/ble_pub/ip/ble/hl/inc/rwprf_config.h new file mode 100755 index 0000000..1aae87a --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/ip/ble/hl/inc/rwprf_config.h @@ -0,0 +1,621 @@ +/** + **************************************************************************************** + * + * @file rwprf_config.h + * + * @brief Header file - Profile Configuration + * + * Copyright (C) RivieraWaves 2009-2016 + * + **************************************************************************************** + */ + + +#ifndef _RWPRF_CONFIG_H_ +#define _RWPRF_CONFIG_H_ + + +#include "rwapp_config.h" +/** + **************************************************************************************** + * @addtogroup PRF_CONFIG + * @ingroup PROFILE + * @brief Profile configuration + * + * @{ + **************************************************************************************** + */ + +//ATT DB,Testing and Qualification related flags +#if (BLE_CENTRAL || BLE_PERIPHERAL) + +// <<< Use Configuration Wizard in Context Menu >>> + // Config BLE profile + +// CFG_PRF_FFF0 +// FFF0 profile Locator Role +// +#if ( 0 ) +#define CFG_PRF_FFF0 +#endif + + +// CFG_PRF_FFE0 +// FFF0 profile Locator Role +// +#if ( 0 ) +#define CFG_PRF_FFE0 +#endif + +// CFG_PRF_SDP +// SDP profile Locator Role +// +#if ( 1 ) +#define CFG_PRF_SDP +#endif + +// CFG_PRF_COMM +// COMM profile Locator Role +// +#if ( 1 ) +#define CFG_PRF_COMM +#endif + +///HID Device Role + +// CFG_PRF_HOGPD +// HID Device Role +// +#if ( 0 ) +#define CFG_PRF_HOGPD +#endif + + + + +// CFG_PRF_DISS +// Battery Service Server Role +// +#if ( 0 ) +#define CFG_PRF_DISS +#endif + +// CFG_PRF_BASS +// Device Information Service Server Role +// +#if ( 0 ) +#define CFG_PRF_BASS +#endif + + + +// CFG_PRF_FMPT +// Find Me Profile Target role +// +#if ( 0 ) +#define CFG_PRF_FMPT +#endif + +// CFG_PRF_FMPL +// Find Me Profile Locator role +// +#if ( 0 ) +#define CFG_PRF_FMPL +#endif +// CFG_PRF_PXPR +// Proximity Reporter +// +#if ( 0 ) +#define CFG_PRF_PXPR +#endif + +// CFG_PRF_HRPS +// Heart Rate Profile Sensor Role +// Heart Rate Profile Sensor Role +// +#if ( 0 ) +#define CFG_PRF_HRPS +#endif + +// CFG_PRF_ANCSC +// ANCS profile Client Role +// +#if ( 0 ) +#define CFG_PRF_ANCSC +#endif + +// CFG_PRF_OADS +// OAD Profile Server Role +// OAD Profile Server Role +// +#if ( 0 ) +#define CFG_PRF_OADS +#endif + +// + +///OTAS Profile Server role +#if defined(CFG_PRF_OADS) +#define BLE_OADS_SERVER 1 +#else +#define BLE_OADS_SERVER 0 +#endif // defined(CFG_PRF_OADS) + + +///FFF0 Profile Locator role +#if defined(CFG_PRF_FFF0) +#define BLE_FFF0_SERVER 1 +#else +#define BLE_FFF0_SERVER 0 +#endif // defined(CFG_PRF_FFF0) + +///SDP Profile Locator role +#if defined(CFG_PRF_SDP) +#define BLE_SDP_CLIENT 1 +#else +#define BLE_SDP_CLIENT 0 +#endif // defined(CFG_PRF_SDP)) + + +///FFE0 Profile Locator role +#if defined(CFG_PRF_FFE0) +#define BLE_FFE0_SERVER 1 +#else +#define BLE_FFE0_SERVER 0 +#endif // defined(CFG_PRF_FFE0) + +///COMM Profile Locator role +#if defined(CFG_PRF_COMM) +#define BLE_COMM_SERVER 1 +#else +#define BLE_COMM_SERVER 0 +#endif // defined(CFG_PRF_AYLA_CONN) + +/// Proximity Profile Monitor Role +#if defined(CFG_PRF_PXPM) +#define BLE_PROX_MONITOR 1 +#else +#define BLE_PROX_MONITOR 0 +#endif // defined(CFG_PRF_PXPM) + +/// Proximity Profile Reporter Role +#if defined(CFG_PRF_PXPR) +#define BLE_PROX_REPORTER 1 +#else +#define BLE_PROX_REPORTER 0 +#endif // defined(CFG_PRF_PXPR) + +///Find Me Profile Locator role +#if defined(CFG_PRF_FMPL) +#define BLE_FINDME_LOCATOR 1 +#else +#define BLE_FINDME_LOCATOR 0 +#endif // defined(CFG_PRF_FMPL) + +///Find Me Profile Target role +#if defined(CFG_PRF_FMPT) +#define BLE_FINDME_TARGET 1 +#else +#define BLE_FINDME_TARGET 0 +#endif // defined(CFG_PRF_FMPT) + +///Health Thermometer Profile Collector Role +#if defined(CFG_PRF_HTPC) +#define BLE_HT_COLLECTOR 1 +#else +#define BLE_HT_COLLECTOR 0 +#endif // defined(CFG_PRF_HTPC) + +///Health Thermometer Profile Thermometer Role +#if defined(CFG_PRF_HTPT) +#define BLE_HT_THERMOM 1 +#else +#define BLE_HT_THERMOM 0 +#endif // defined(CFG_PRF_HTPT) + +///Device Information Service Client Role +#if defined(CFG_PRF_DISC) +#define BLE_DIS_CLIENT 1 +#else +#define BLE_DIS_CLIENT 0 +#endif // defined(CFG_PRF_DISC) + +///Device Information Service Server Role +#if (defined(CFG_PRF_DISS) || BLE_APP_HRPS) +#define BLE_DIS_SERVER 1 +#else +#define BLE_DIS_SERVER 0 +#endif // defined(CFG_PRF_DISS) + +///Blood Pressure Profile Collector Role +#if defined(CFG_PRF_BLPC) +#define BLE_BP_COLLECTOR 1 +#else +#define BLE_BP_COLLECTOR 0 +#endif // defined(CFG_PRF_BLPC) + +///ANCS Profile Client role +#if defined(CFG_PRF_ANCSC) +#define BLE_ANCS_CLIENT 1 +#else +#define BLE_ANCS_CLIENT 0 +#endif // defined(CFG_PRF_ANCSC) + +///Blood Pressure Profile Sensor Role +#if defined(CFG_PRF_BLPS) +#define BLE_BP_SENSOR 1 +#else +#define BLE_BP_SENSOR 0 +#endif // defined(CFG_PRF_BLPS) + +///Time Profile Client Role +#if defined(CFG_PRF_TIPC) +#define BLE_TIP_CLIENT 1 +#else +#define BLE_TIP_CLIENT 0 +#endif // defined(CFG_PRF_TIPC) + +///Time Profile Server Role +#if defined(CFG_PRF_TIPS) +#define BLE_TIP_SERVER 1 +#else +#define BLE_TIP_SERVER 0 +#endif // defined(CFG_PRF_TIPS) + +///Heart Rate Profile Collector Role +#if defined(CFG_PRF_HRPC) +#define BLE_HR_COLLECTOR 1 +#else +#define BLE_HR_COLLECTOR 0 +#endif // defined(CFG_PRF_HRPC) + +///Heart Rate Profile Sensor Role +#if defined(CFG_PRF_HRPS) +#define BLE_HR_SENSOR 1 +#else +#define BLE_HR_SENSOR 0 +#endif // defined(CFG_PRF_HRPS) + +///Scan Parameter Profile Client Role +#if defined(CFG_PRF_SCPPC) +#define BLE_SP_CLIENT 1 +#else +#define BLE_SP_CLIENT 0 +#endif // defined(CFG_PRF_SCPPC) + +///Scan Parameter Profile Server Role +#if defined(CFG_PRF_SCPPS) +#define BLE_SP_SERVER 1 +#else +#define BLE_SP_SERVER 0 +#endif // defined(CFG_PRF_SCPPS) + +///Battery Service Client Role +#if defined(CFG_PRF_BASC) +#define BLE_BATT_CLIENT 1 +#else +#define BLE_BATT_CLIENT 0 +#endif // defined(CFG_PRF_BASC) + +///Battery Service Server Role +#if defined(CFG_PRF_BASS) +#define BLE_BATT_SERVER 1 +#else +#define BLE_BATT_SERVER 0 +#endif // defined(CFG_PRF_BASS) + +///HID Device Role +#if defined(CFG_PRF_HOGPD) +#define BLE_HID_DEVICE 1 +#else +#define BLE_HID_DEVICE 0 +#endif // defined(CFG_PRF_HOGPD) + +///HID Boot Host Role +#if defined(CFG_PRF_HOGPBH) +#define BLE_HID_BOOT_HOST 1 +#else +#define BLE_HID_BOOT_HOST 0 +#endif // defined(CFG_PRF_HOGPBH) + +///HID Report Host Role +#if defined(CFG_PRF_HOGPRH) +#define BLE_HID_REPORT_HOST 1 +#else +#define BLE_HID_REPORT_HOST 0 +#endif // defined(CFG_PRF_HOGPRH) + +/// Glucose Profile Collector Role +#if defined(CFG_PRF_GLPC) +#define BLE_GL_COLLECTOR 1 +#else +#define BLE_GL_COLLECTOR 0 +#endif // defined(CFG_PRF_GLPC) + +/// Glucose Profile Sensor Role +#if defined(CFG_PRF_GLPS) +#define BLE_GL_SENSOR 1 +#else +#define BLE_GL_SENSOR 0 +#endif // defined(CFG_PRF_GLPS) + +/// Running Speed and Cadence Profile Collector Role +#if defined(CFG_PRF_RSCPC) +#define BLE_RSC_COLLECTOR 1 +#else +#define BLE_RSC_COLLECTOR 0 +#endif // defined(CFG_PRF_RSCPC) + +/// Running Speed and Cadence Profile Server Role +#if defined(CFG_PRF_RSCPS) +#define BLE_RSC_SENSOR 1 +#else +#define BLE_RSC_SENSOR 0 +#endif // defined(CFG_PRF_RSCPS) + +/// Cycling Speed and Cadence Profile Collector Role +#if defined(CFG_PRF_CSCPC) +#define BLE_CSC_COLLECTOR 1 +#else +#define BLE_CSC_COLLECTOR 0 +#endif // defined(CFG_PRF_CSCPC) + +/// Cycling Speed and Cadence Profile Server Role +#if defined(CFG_PRF_CSCPS) +#define BLE_CSC_SENSOR 1 +#else +#define BLE_CSC_SENSOR 0 +#endif // defined(CFG_PRF_CSCPS) + +/// Cycling Power Profile Collector Role +#if defined(CFG_PRF_CPPC) +#define BLE_CP_COLLECTOR 1 +#else +#define BLE_CP_COLLECTOR 0 +#endif // defined (CFG_PRF_CPPC) + +/// Cycling Power Profile Server Role +#if defined(CFG_PRF_CPPS) +#define BLE_CP_SENSOR 1 +#else +#define BLE_CP_SENSOR 0 +#endif // defined (CFG_PRF_CPPS) + +/// Location and Navigation Profile Collector Role +#if defined(CFG_PRF_LANC) +#define BLE_LN_COLLECTOR 1 +#else +#define BLE_LN_COLLECTOR 0 +#endif // defined (CFG_PRF_LANC) + +/// Location and Navigation Profile Server Role +#if defined(CFG_PRF_LANS) +#define BLE_LN_SENSOR 1 +#else +#define BLE_LN_SENSOR 0 +#endif // defined (CFG_PRF_LANS) + +/// Alert Notification Profile Client Role +#if defined(CFG_PRF_ANPC) +#define BLE_AN_CLIENT 1 +#else +#define BLE_AN_CLIENT 0 +#endif // defined(CFG_PRF_ANPC) + +/// Alert Notification Profile Server Role +#if defined(CFG_PRF_ANPS) +#define BLE_AN_SERVER 1 +#else +#define BLE_AN_SERVER 0 +#endif // defined(CFG_PRF_ANPS) + +/// Phone Alert Status Profile Client Role +#if defined(CFG_PRF_PASPC) +#define BLE_PAS_CLIENT 1 +#else +#define BLE_PAS_CLIENT 0 +#endif // defined(CFG_PRF_PASPC) + +/// Phone Alert Status Profile Server Role +#if defined(CFG_PRF_PASPS) +#define BLE_PAS_SERVER 1 +#else +#define BLE_PAS_SERVER 0 +#endif // defined(CFG_PRF_PASPS) + +/// Internet Protocol Support Profile Server Role +#if defined(CFG_PRF_IPSS) +#define BLE_IPS_SERVER 1 +#else +#define BLE_IPS_SERVER 0 +#endif // defined(CFG_PRF_IPSS) + +/// Internet Protocol Support Profile Client Role +#if defined(CFG_PRF_IPSC) +#define BLE_IPS_CLIENT 1 +#else +#define BLE_IPS_CLIENT 0 +#endif // defined(CFG_PRF_IPSC) + +/// Environmental Sensing Profile Server Role +#if defined(CFG_PRF_ENVS) +#define BLE_ENV_SERVER 1 +#else +#define BLE_ENV_SERVER 0 +#endif // defined(CFG_PRF_ENVS) + +/// Environmental Sensing Profile Client Role +#if defined(CFG_PRF_ENVC) +#define BLE_ENV_CLIENT 0 +#else +#define BLE_ENV_CLIENT 0 +#endif // defined(CFG_PRF_ENVC) + +/// Weight Scale Profile Server Role +#if defined(CFG_PRF_WSCS) +#define BLE_WSC_SERVER 1 +#else +#define BLE_WSC_SERVER 0 +#endif // defined(CFG_PRF_WSCS) + +/// Weight Scale Profile Client Role +#if defined(CFG_PRF_WSCC) +#define BLE_WSC_CLIENT 0 +#else +#define BLE_WSC_CLIENT 0 +#endif // defined(CFG_PRF_WSCC) + + + + +/// BLE_CLIENT_PRF indicates if at least one client profile is present +#if (BLE_PROX_MONITOR || BLE_FINDME_LOCATOR || BLE_HT_COLLECTOR || BLE_BP_COLLECTOR \ + || BLE_HR_COLLECTOR || BLE_DIS_CLIENT || BLE_TIP_CLIENT || BLE_SP_CLIENT \ + || BLE_BATT_CLIENT || BLE_GL_COLLECTOR || BLE_HID_BOOT_HOST || BLE_HID_REPORT_HOST \ + || BLE_RSC_COLLECTOR || BLE_CSC_COLLECTOR || BLE_CP_COLLECTOR || BLE_LN_COLLECTOR || BLE_AN_CLIENT \ + || BLE_PAS_CLIENT || BLE_IPS_CLIENT || BLE_ENV_CLIENT || BLE_WSC_CLIENT || BLE_SDP_CLIENT) +#define BLE_CLIENT_PRF 1 +#else +#define BLE_CLIENT_PRF 0 +#endif //(BLE_PROX_MONITOR || BLE_FINDME_LOCATOR ...) + +/// BLE_SERVER_PRF indicates if at least one server profile is present +#if (BLE_PROX_REPORTER || BLE_FINDME_TARGET || BLE_HT_THERMOM || BLE_BP_SENSOR \ + || BLE_TIP_SERVER || BLE_HR_SENSOR || BLE_DIS_SERVER || BLE_SP_SERVER \ + || BLE_BATT_SERVER || BLE_HID_DEVICE || BLE_GL_SENSOR || BLE_RSC_SENSOR \ + || BLE_CSC_SENSOR || BLE_CP_SENSOR || BLE_LN_SENSOR || BLE_AN_SERVER \ + || BLE_PAS_SERVER || BLE_IPS_SERVER || BLE_ENV_SERVER || BLE_WSC_SERVER \ + || BLE_UDS_SERVER || BLE_BCS_SERVER || BLE_WPT_SERVER || BLE_PLX_SERVER \ + || BLE_FFF0_SERVER || BLE_FFE0_SERVER || BLE_COMM_SERVER) +#define BLE_SERVER_PRF 1 +#else +#define BLE_SERVER_PRF 0 +#endif //(BLE_PROX_REPORTER || BLE_FINDME_TARGET ...) + +//Force ATT parts depending on profile roles or compile options +/// Attribute Client +#if (BLE_CLIENT_PRF) +#define BLE_ATTC 1 +#endif //(BLE_CLIENT_PRF) + +/// Attribute Server +#if (BLE_SERVER_PRF) +#define BLE_ATTS 1 +#endif //(BLE_SERVER_PRF) + + +#elif (BLE_OBSERVER || BLE_BROADCASTER) +/// Proximity Profile Monitor Role +#define BLE_PROX_MONITOR 0 +/// Proximity Profile Reporter Role +#define BLE_PROX_REPORTER 0 +///ANCS Profile Client role +#define BLE_ANCS_CLIENT 0 +///Find Me Profile Locator role +#define BLE_FINDME_LOCATOR 0 +///Find Me Profile Target role +#define BLE_FINDME_TARGET 0 +///Health Thermometer Profile Collector Role +#define BLE_HT_COLLECTOR 0 +///Health Thermometer Profile Thermometer Role +#define BLE_HT_THERMOM 0 +///Blood Pressure Profile Collector Role +#define BLE_BP_COLLECTOR 0 +///Blood Pressure Profile Sensor Role +#define BLE_BP_SENSOR 0 +///Heart Rate Profile Collector Role +#define BLE_HR_COLLECTOR 0 +///Heart Rate Profile Sensor Role +#define BLE_HR_SENSOR 0 +///Time Profile Client Role +#define BLE_TIP_CLIENT 0 +///Time Profile Server Role +#define BLE_TIP_SERVER 0 +/// Device Information Service Client Role +#define BLE_DIS_CLIENT 0 +/// Device Information Service Server Role +#define BLE_DIS_SERVER 0 +/// Scan Parameter Profile Client Role +#define BLE_SP_CLIENT 0 +/// Scan Parameter Profile Server Role +#define BLE_SP_SERVER 0 +/// Battery Service Client Role +#define BLE_BATT_CLIENT 0 +/// Battery Service Server Role +#define BLE_BATT_SERVER 0 +/// HID Device Role +#define BLE_HID_DEVICE 0 +/// HID Boot Host Role +#define BLE_HID_BOOT_HOST 0 +/// HID Report Host Role +#define BLE_HID_REPORT_HOST 0 +/// Glucose Profile Collector Role +#define BLE_GL_COLLECTOR 0 +/// Glucose Profile Sensor Role +#define BLE_GL_SENSOR 0 +/// Running Speed and Cadence Collector Role +#define BLE_RSC_COLLECTOR 0 +/// Running Speed and Cadence Server Role +#define BLE_RSC_SENSOR 0 +/// Cycling Speed and Cadence Collector Role +#define BLE_CSC_COLLECTOR 0 +/// Cycling Speed and Cadence Server Role +#define BLE_CSC_SENSOR 0 +/// Cycling Power Collector Role +#define BLE_CP_COLLECTOR 0 +/// Cycling Power Server Role +#define BLE_CP_SENSOR 0 +/// Location and Navigation Collector Role +#define BLE_LN_COLLECTOR 0 +/// Location and Navigation Server Role +#define BLE_LN_SENSOR 0 +/// Alert Notification Client Role +#define BLE_AN_CLIENT 0 +/// Alert Notification Server Role +#define BLE_AN_SERVER 0 +/// Phone Alert Status Client Role +#define BLE_PAS_CLIENT 0 +/// Phone Alert Status Server Role +#define BLE_PAS_SERVER 0 +/// Internet Protocol Support Profile Server Role +#define BLE_IPS_SERVER 0 +/// Internet Protocol Support Profile Client Role +#define BLE_IPS_CLIENT 0 +/// Environmental Sensing Profile Server Role +#define BLE_ENV_SERVER 0 +/// Environmental Sensing Profile Client Role +#define BLE_ENV_CLIENT 0 +/// Weight Scale Profile Server Role +#define BLE_WSC_SERVER 0 +/// Weight Scale Profile Client Role +#define BLE_WSC_CLIENT 0 +/// Body Composition Profile Client Role +#define BLE_BCS_CLIENT 0 +/// Body Composition Profile Server Role +#define BLE_BCS_SERVER 0 +/// User Data Service Server Role +#define BLE_UDS_SERVER 0 +/// User Data Service Client Role +#define BLE_UDS_CLIENT 0 +/// Wireless Power Transfer Profile Server Role +#define BLE_WPT_SERVER 0 +/// Wireless Power Transfer Profile Client Role +#define BLE_WPT_CLIENT 0 +/// Pulse Oximete Profile Server Role +#define BLE_PLX_SERVER 0 +/// Pulse Oximete Profile Client Role +#define BLE_PLX_CLIENT 0 + +//Force ATT parts to 0 +/// External database management +#define BLE_EXT_ATTS_DB 0 +/// Profile Server +#define BLE_SERVER_PRF 0 +/// Profile Client +#define BLE_CLIENT_PRF 0 +#endif //(BLE_OBSERVER || BLE_BROADCASTER) + + +/// @} PRF_CONFIG + +#endif /* _RWPRF_CONFIG_H_ */ diff --git a/beken_os/beken378/driver/ble/ble_pub/ip/ble/hl/src/prf/prf.c b/beken_os/beken378/driver/ble/ble_pub/ip/ble/hl/src/prf/prf.c new file mode 100755 index 0000000..3d40ea8 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/ip/ble/hl/src/prf/prf.c @@ -0,0 +1,1001 @@ +/** + **************************************************************************************** + * + * @file prf.c + * + * @brief Entry point of profile source file. + * + * Used to manage life cycle of profiles + * + * Copyright (C) RivieraWaves 2009-2016 + * + **************************************************************************************** + */ + + +/** + **************************************************************************************** + * @addtogroup PRF + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" + +#if (BLE_PROFILES) +#include "prf.h" +#include "att.h" + +#if (BLE_OADS_SERVER) +#include "oads.h" +#endif //(BLE_OADS_SERVER) + +#if (BLE_OADS_SERVER) +extern const struct prf_task_cbs* oads_prf_itf_get(void); +#endif // (BLE_OADS_SERVER) + +#if (BLE_SDP_CLIENT) +#include "sdp_service.h" +#endif //(BLE_SDP_CLIENT) + +#if (BLE_FFF0_SERVER) +extern const struct prf_task_cbs* fff0s_prf_itf_get(void); +#endif // (BLE_FFF0_SERVER) + +#if (BLE_SDP_CLIENT) +extern const struct prf_task_cbs* sdp_prf_itf_get(void); +#endif // (BLE_SDP_CLIENT) + +#if (BLE_FFE0_SERVER) +extern const struct prf_task_cbs* ffe0s_prf_itf_get(void); +#endif // (BLE_FFF0_SERVER) + +#if (BLE_COMM_SERVER) +extern const struct prf_task_cbs* bk_ble_prf_itf_get(void); +#endif // (BLE_FFF0_SERVER) + +#if (BLE_HT_THERMOM) +extern const struct prf_task_cbs* htpt_prf_itf_get(void); +#endif // (BLE_HT_THERMOM) + +#if (BLE_HT_COLLECTOR) +extern const struct prf_task_cbs* htpc_prf_itf_get(void); +#endif // (BLE_HT_COLLECTOR) + +#if (BLE_DIS_SERVER) +extern const struct prf_task_cbs* diss_prf_itf_get(void); +#endif // (BLE_HT_THERMOM) + +#if (BLE_DIS_CLIENT) +extern const struct prf_task_cbs* disc_prf_itf_get(void); +#endif // (BLE_DIS_CLIENT) + +#if (BLE_BP_SENSOR) +extern const struct prf_task_cbs* blps_prf_itf_get(void); +#endif // (BLE_BP_SENSOR) + +#if (BLE_BP_COLLECTOR) +extern const struct prf_task_cbs* blpc_prf_itf_get(void); +#endif // (BLE_BP_COLLECTOR) + +#if (BLE_ANCS_CLIENT) +extern const struct prf_task_cbs* ancsc_prf_itf_get(void); +#endif // (BLE_ANCS_CLIENT) + +#if (BLE_TIP_SERVER) +extern const struct prf_task_cbs* tips_prf_itf_get(void); +#endif // (BLE_TIP_SERVER) + +#if (BLE_TIP_CLIENT) +extern const struct prf_task_cbs* tipc_prf_itf_get(void); +#endif // (BLE_TIP_CLIENT) + +#if (BLE_HR_SENSOR) +extern const struct prf_task_cbs* hrps_prf_itf_get(void); +#endif // (BLE_HR_SENSOR) + +#if (BLE_HR_COLLECTOR) +extern const struct prf_task_cbs* hrpc_prf_itf_get(void); +#endif // (BLE_HR_COLLECTOR) + +#if (BLE_FINDME_LOCATOR) +extern const struct prf_task_cbs* findl_prf_itf_get(void); +#endif // (BLE_FINDME_LOCATOR) + +#if (BLE_FINDME_TARGET) +extern const struct prf_task_cbs* findt_prf_itf_get(void); +#endif // (BLE_FINDME_TARGET) + +#if (BLE_PROX_MONITOR) +extern const struct prf_task_cbs* proxm_prf_itf_get(void); +#endif // (BLE_PROX_MONITOR) + +#if (BLE_PROX_REPORTER) +extern const struct prf_task_cbs* proxr_prf_itf_get(void); +#endif // (BLE_PROX_REPORTER) + +#if (BLE_SP_CLIENT) +extern const struct prf_task_cbs* scppc_prf_itf_get(void); +#endif // (BLE_SP_CLENT) + +#if (BLE_SP_SERVER) +extern const struct prf_task_cbs* scpps_prf_itf_get(void); +#endif // (BLE_SP_SERVER) + +#if (BLE_BATT_CLIENT) +extern const struct prf_task_cbs* basc_prf_itf_get(void); +#endif // (BLE_BATT_CLIENT) + +#if (BLE_BATT_SERVER) +extern const struct prf_task_cbs* bass_prf_itf_get(void); +#endif // (BLE_BATT_SERVER) + +#if (BLE_HID_DEVICE) +extern const struct prf_task_cbs* hogpd_prf_itf_get(void); +#endif // (BLE_HID_DEVICE) + +#if (BLE_HID_BOOT_HOST) +extern const struct prf_task_cbs* hogpbh_prf_itf_get(void); +#endif // (BLE_HID_BOOT_HOST) + +#if (BLE_HID_REPORT_HOST) +extern const struct prf_task_cbs* hogprh_prf_itf_get(void); +#endif // (BLE_HID_REPORT_HOST) + +#if (BLE_GL_COLLECTOR) +extern const struct prf_task_cbs* glpc_prf_itf_get(void); +#endif // (BLE_GL_COLLECTOR) + +#if (BLE_GL_SENSOR) +extern const struct prf_task_cbs* glps_prf_itf_get(void); +#endif // (BLE_GL_SENSOR) + +#if (BLE_RSC_COLLECTOR) +extern const struct prf_task_cbs* rscpc_prf_itf_get(void); +#endif // (BLE_RSC_COLLECTOR) + +#if (BLE_RSC_SENSOR) +extern const struct prf_task_cbs* rscps_prf_itf_get(void); +#endif // (BLE_RSC_COLLECTOR) + +#if (BLE_CSC_COLLECTOR) +extern const struct prf_task_cbs* cscpc_prf_itf_get(void); +#endif // (BLE_CSC_COLLECTOR) + +#if (BLE_CSC_SENSOR) +extern const struct prf_task_cbs* cscps_prf_itf_get(void); +#endif // (BLE_CSC_COLLECTOR) + +#if (BLE_AN_CLIENT) +extern const struct prf_task_cbs* anpc_prf_itf_get(void); +#endif // (BLE_AN_CLIENT) + +#if (BLE_AN_SERVER) +extern const struct prf_task_cbs* anps_prf_itf_get(void); +#endif // (BLE_AN_SERVER) + +#if (BLE_PAS_CLIENT) +extern const struct prf_task_cbs* paspc_prf_itf_get(void); +#endif // (BLE_PAS_CLIENT) + +#if (BLE_PAS_SERVER) +extern const struct prf_task_cbs* pasps_prf_itf_get(void); +#endif // (BLE_PAS_SERVER) + +#if (BLE_CP_COLLECTOR) +extern const struct prf_task_cbs* cppc_prf_itf_get(void); +#endif //(BLE_CP_COLLECTOR) + +#if (BLE_CP_SENSOR) +extern const struct prf_task_cbs* cpps_prf_itf_get(void); +#endif //(BLE_CP_SENSOR) + +#if (BLE_LN_COLLECTOR) +extern const struct prf_task_cbs* lanc_prf_itf_get(void); +#endif //(BLE_CP_COLLECTOR) + +#if (BLE_LN_SENSOR) +extern const struct prf_task_cbs* lans_prf_itf_get(void); +#endif //(BLE_CP_SENSOR) + +#if (BLE_IPS_SERVER) +extern const struct prf_task_cbs* ipss_prf_itf_get(void); +#endif //(BLE_IPS_SERVER) + +#if (BLE_IPS_CLIENT) +extern const struct prf_task_cbs* ipsc_prf_itf_get(void); +#endif //(BLE_IPS_CLIENT) + +#if (BLE_ENV_SERVER) +extern const struct prf_task_cbs* envs_prf_itf_get(void); +#endif //(BLE_ENV_SERVER) + +#if (BLE_ENV_CLIENT) +extern const struct prf_task_cbs* envc_prf_itf_get(void); +#endif //(BLE_ENV_CLIENT + +#if (BLE_WSC_SERVER) +extern const struct prf_task_cbs* wscs_prf_itf_get(void); +#endif //(BLE_WSC_SERVER) + +#if (BLE_WSC_CLIENT) +extern const struct prf_task_cbs* wscc_prf_itf_get(void); +#endif //(BLE_WSC_CLIENT + +#if (BLE_BCS_SERVER) +extern const struct prf_task_cbs* bcss_prf_itf_get(void); +#endif //(BLE_BCS_SERVER) + +#if (BLE_BCS_CLIENT) +extern const struct prf_task_cbs* bcsc_prf_itf_get(void); +#endif //(BLE_BCS_CLIENT) + +#if (BLE_WPT_SERVER) +extern const struct prf_task_cbs* wpts_prf_itf_get(void); +#endif //(BLE_WPT_SERVER) + +#if (BLE_WPT_CLIENT) +extern const struct prf_task_cbs* wptc_prf_itf_get(void); +#endif //(BLE_WPT_CLIENT + +#if (BLE_PLX_SERVER) +extern const struct prf_task_cbs* plxs_prf_itf_get(void); +#endif //(BLE_PLX_SERVER) + +#if (BLE_PLX_CLIENT) +extern const struct prf_task_cbs* plxc_prf_itf_get(void); +#endif //(BLE_PLX_CLIENT + +#ifdef BLE_AM0_HEARING_AID_SERV +extern const struct prf_task_cbs* am0_has_prf_itf_get(void); +#endif // BLE_AM0_HEARING_AID_SERV + +#if (BLE_UDS_SERVER) +extern const struct prf_task_cbs* udss_prf_itf_get(void); +#endif //(BLE_UDS_SERVER) + +#if (BLE_UDS_CLIENT) +extern const struct prf_task_cbs* udsc_prf_itf_get(void); +#endif //(BLE_UDS_SERVER) + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + + +/* + * DEFINES + **************************************************************************************** + */ + +/* + * MACROS + **************************************************************************************** + */ + + +/* + * GLOBAL VARIABLE DEFINITIONS + **************************************************************************************** + */ +struct prf_env_tag prf_env; + +/* + * LOCAL FUNCTIONS DEFINITIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Retrieve profile interface + **************************************************************************************** + */ +static const struct prf_task_cbs * prf_itf_get(uint16_t task_id) +{ + const struct prf_task_cbs* prf_cbs = NULL; + + uint16_t id = KERNEL_TYPE_GET(task_id); +#if (BLE_SDP_CLIENT) + if((id >= TASK_ID_SDP) && (id <= TASK_ID_SDP + BLE_NB_PROFILES) ) + { + id = TASK_ID_SDP; + } +#endif + + if((id >= TASK_ID_COMMON) && (id <= TASK_ID_COMMON + BLE_NB_PROFILES)) + { + id = TASK_ID_COMMON; + } + + switch(id) + { + #if (BLE_OADS_SERVER) + case TASK_ID_OADS: + prf_cbs = oads_prf_itf_get(); + break; + #endif // (BLE_OADS_SERVER) + +#if (BLE_SDP_CLIENT) + case TASK_ID_SDP: + prf_cbs = sdp_prf_itf_get(); + break; +#endif // (BLE_SDP_CLIENT) + #if (BLE_FFF0_SERVER) + case TASK_ID_FFF0S: + prf_cbs = fff0s_prf_itf_get(); + break; + #endif // (BLE_FFF0_SERVER) + + #if (BLE_FFE0_SERVER) + case TASK_ID_FFE0S: + prf_cbs = ffe0s_prf_itf_get(); + break; + #endif // (BLE_FFE0_SERVER) + + #if (BLE_COMM_SERVER) + case TASK_ID_COMMON: + prf_cbs = bk_ble_prf_itf_get(); + break; + #endif // (BLE_COMM_SERVER) + + #if (BLE_HT_THERMOM) + case TASK_ID_HTPT: + prf_cbs = htpt_prf_itf_get(); + break; + #endif // (BLE_HT_THERMOM) + + #if (BLE_HT_COLLECTOR) + case TASK_ID_HTPC: + prf_cbs = htpc_prf_itf_get(); + break; + #endif // (BLE_HT_COLLECTOR) + + #if (BLE_DIS_SERVER) + case TASK_ID_DISS: + prf_cbs = diss_prf_itf_get(); + break; + #endif // (BLE_DIS_SERVER) + + #if (BLE_DIS_CLIENT) + case TASK_ID_DISC: + prf_cbs = disc_prf_itf_get(); + break; + #endif // (BLE_DIS_CLIENT) + + #if (BLE_BP_SENSOR) + case TASK_ID_BLPS: + prf_cbs = blps_prf_itf_get(); + break; + #endif // (BLE_BP_SENSOR) + + #if (BLE_BP_COLLECTOR) + case TASK_ID_BLPC: + prf_cbs = blpc_prf_itf_get(); + break; + #endif // (BLE_BP_COLLECTOR) + + #if (BLE_ANCS_CLIENT) + case TASK_ID_ANCSC: + prf_cbs = ancsc_prf_itf_get(); + break; + #endif // (BLE_ANCS_CLIENT) + + #if (BLE_TIP_SERVER) + case TASK_ID_TIPS: + prf_cbs = tips_prf_itf_get(); + break; + #endif // (BLE_TIP_SERVER) + + #if (BLE_TIP_CLIENT) + case TASK_ID_TIPC: + prf_cbs = tipc_prf_itf_get(); + break; + #endif // (BLE_TIP_CLIENT) + + #if (BLE_HR_SENSOR) + case TASK_ID_HRPS: + prf_cbs = hrps_prf_itf_get(); + break; + #endif // (BLE_HR_SENSOR) + + #if (BLE_HR_COLLECTOR) + case TASK_ID_HRPC: + prf_cbs = hrpc_prf_itf_get(); + break; + #endif // (BLE_HR_COLLECTOR) + + #if (BLE_FINDME_LOCATOR) + case TASK_ID_FINDL: + prf_cbs = findl_prf_itf_get(); + break; + #endif // (BLE_FINDME_LOCATOR) + + #if (BLE_FINDME_TARGET) + case TASK_ID_FINDT: + prf_cbs = findt_prf_itf_get(); + break; + #endif // (BLE_FINDME_TARGET) + + #if (BLE_PROX_MONITOR) + case TASK_ID_PROXM: + prf_cbs = proxm_prf_itf_get(); + break; + #endif // (BLE_PROX_MONITOR) + + #if (BLE_PROX_REPORTER) + case TASK_ID_PROXR: + prf_cbs = proxr_prf_itf_get(); + break; + #endif // (BLE_PROX_REPORTER) + + #if (BLE_SP_SERVER) + case TASK_ID_SCPPS: + prf_cbs = scpps_prf_itf_get(); + break; + #endif // (BLE_SP_SERVER) + + #if (BLE_SP_CLIENT) + case TASK_ID_SCPPC: + prf_cbs = scppc_prf_itf_get(); + break; + #endif // (BLE_SP_CLIENT) + + #if (BLE_BATT_SERVER) + case TASK_ID_BASS: + prf_cbs = bass_prf_itf_get(); + break; + #endif // (BLE_BATT_SERVER) + + #if (BLE_BATT_CLIENT) + case TASK_ID_BASC: + prf_cbs = basc_prf_itf_get(); + break; + #endif // (BLE_BATT_CLIENT) + + #if (BLE_HID_DEVICE) + case TASK_ID_HOGPD: + prf_cbs = hogpd_prf_itf_get(); + break; + #endif // (BLE_HID_DEVICE) + + #if (BLE_HID_BOOT_HOST) + case TASK_ID_HOGPBH: + prf_cbs = hogpbh_prf_itf_get(); + break; + #endif // (BLE_HID_BOOT_HOST) + + #if (BLE_HID_REPORT_HOST) + case TASK_ID_HOGPRH: + prf_cbs = hogprh_prf_itf_get(); + break; + #endif // (BLE_HID_REPORT_HOST) + + #if (BLE_GL_COLLECTOR) + case TASK_ID_GLPC: + prf_cbs = glpc_prf_itf_get(); + break; + #endif // (BLE_GL_COLLECTOR) + + #if (BLE_GL_SENSOR) + case TASK_ID_GLPS: + prf_cbs = glps_prf_itf_get(); + break; + #endif // (BLE_GL_SENSOR) + + #if (BLE_RSC_COLLECTOR) + case TASK_ID_RSCPC: + prf_cbs = rscpc_prf_itf_get(); + break; + #endif // (BLE_RSC_COLLECTOR) + + #if (BLE_RSC_SENSOR) + case TASK_ID_RSCPS: + prf_cbs = rscps_prf_itf_get(); + break; + #endif // (BLE_RSC_SENSOR) + + #if (BLE_CSC_COLLECTOR) + case TASK_ID_CSCPC: + prf_cbs = cscpc_prf_itf_get(); + break; + #endif // (BLE_CSC_COLLECTOR) + + #if (BLE_CSC_SENSOR) + case TASK_ID_CSCPS: + prf_cbs = cscps_prf_itf_get(); + break; + #endif // (BLE_CSC_SENSOR) + + #if (BLE_CP_COLLECTOR) + case TASK_ID_CPPC: + prf_cbs = cppc_prf_itf_get(); + break; + #endif // (BLE_CP_COLLECTOR) + + #if (BLE_CP_SENSOR) + case TASK_ID_CPPS: + prf_cbs = cpps_prf_itf_get(); + break; + #endif // (BLE_CP_SENSOR) + + #if (BLE_LN_COLLECTOR) + case TASK_ID_LANC: + prf_cbs = lanc_prf_itf_get(); + break; + #endif // (BLE_LN_COLLECTOR) + + #if (BLE_LN_SENSOR) + case TASK_ID_LANS: + prf_cbs = lans_prf_itf_get(); + break; + #endif // (BLE_LN_SENSOR) + + #if (BLE_AN_CLIENT) + case TASK_ID_ANPC: + prf_cbs = anpc_prf_itf_get(); + break; + #endif // (BLE_AN_CLIENT) + + #if (BLE_AN_SERVER) + case TASK_ID_ANPS: + prf_cbs = anps_prf_itf_get(); + break; + #endif // (BLE_AN_SERVER) + + #if (BLE_PAS_CLIENT) + case TASK_ID_PASPC: + prf_cbs = paspc_prf_itf_get(); + break; + #endif // (BLE_PAS_CLIENT) + + #if (BLE_PAS_SERVER) + case TASK_ID_PASPS: + prf_cbs = pasps_prf_itf_get(); + break; + #endif // (BLE_PAS_SERVER) + + #ifdef BLE_AM0_HEARING_AID_SERV + case TASK_ID_AM0_HAS: + prf_cbs = am0_has_prf_itf_get(); + break; + #endif // defined(BLE_AM0_HEARING_AID_SERV) + + #if (BLE_IPS_SERVER) + case TASK_ID_IPSS: + prf_cbs = ipss_prf_itf_get(); + break; + #endif //(BLE_IPS_SERVER) + + #if (BLE_IPS_CLIENT) + case TASK_ID_IPSC: + prf_cbs = ipsc_prf_itf_get(); + break; + #endif //(BLE_IPS_CLIENT) + + #if (BLE_ENV_SERVER) + case TASK_ID_ENVS: + prf_cbs = envs_prf_itf_get(); + break; + #endif //(BLE_ENV_SERVER) + + #if (BLE_ENV_CLIENT) + case TASK_ID_ENVC: + prf_cbs = envc_prf_itf_get(); + break; + #endif //(BLE_ENV_CLIENT + + #if (BLE_WSC_SERVER) + case TASK_ID_WSCS: + prf_cbs = wscs_prf_itf_get(); + break; + #endif //(BLE_WSC_SERVER) + + #if (BLE_WSC_CLIENT) + case TASK_ID_WSCC: + prf_cbs = wscc_prf_itf_get(); + break; + #endif //(BLE_WSC_CLIENT) + + #if (BLE_BCS_SERVER) + case TASK_ID_BCSS: + prf_cbs = bcss_prf_itf_get(); + break; + #endif //(BLE_BCS_SERVER) + + #if (BLE_BCS_CLIENT) + case TASK_ID_BCSC: + prf_cbs = bcsc_prf_itf_get(); + break; + #endif //(BLE_BCS_CLIENT) + + #if (BLE_UDS_SERVER) + case TASK_ID_UDSS: + prf_cbs = udss_prf_itf_get(); + break; + #endif //(BLE_UDS_SERVER) + + #if (BLE_UDS_CLIENT) + case TASK_ID_UDSC: + prf_cbs = udsc_prf_itf_get(); + break; + #endif //(BLE_UDS_CLIENT) + + #if (BLE_WPT_SERVER) + case TASK_ID_WPTS: + prf_cbs = wpts_prf_itf_get(); + break; + #endif //(BLE_WPT_SERVER) + + #if (BLE_WPT_CLIENT) + case TASK_ID_WPTC: + prf_cbs = wptc_prf_itf_get(); + break; + #endif //(BLE_WPT_CLIENT) + + #if (BLE_PLX_SERVER) + case TASK_ID_PLXS: + prf_cbs = plxs_prf_itf_get(); + break; + #endif //(BLE_PLX_SERVER) + + #if (BLE_PLX_CLIENT) + case TASK_ID_PLXC: + prf_cbs = plxc_prf_itf_get(); + break; + #endif //(BLE_PLX_CLIENT) + + default: /* Nothing to do */ break; + } + + return prf_cbs; +} + +/* + * EXPORTED FUNCTIONS DEFINITIONS + **************************************************************************************** + */ +void prf_init(bool reset) +{ + uint8_t i; + if(!reset) + { + // FW boot profile initialization + for(i = 0; i < BLE_NB_PROFILES ; i++) + { + prf_env.prf[i].env = NULL; + prf_env.prf[i].task = TASK_GAPC + i +1; + prf_env.prf[i].id = TASK_ID_INVALID; + + // Initialize Task Descriptor + prf_env.prf[i].desc.default_handler = NULL; + prf_env.prf[i].desc.state = NULL; + prf_env.prf[i].desc.idx_max = 0; + + prf_env.prf[i].desc.state_max = 0; + prf_env.prf[i].desc.state_handler = NULL; + prf_env.prf_used = 0; + + kernel_task_create(prf_env.prf[i].task, &(prf_env.prf[i].desc)); + } + } + else + { + // FW boot profile destruction + for(i = 0; i < BLE_NB_PROFILES ; i++) + { + // Get Profile API + const struct prf_task_cbs * cbs = prf_itf_get(prf_env.prf[i].id); + if(cbs != NULL) + { + // request to destroy profile + cbs->destroy(&(prf_env.prf[i])); + if(prf_env.prf_used > 0) + { + prf_env.prf_used--; + //UART_PRINTF("*******destroy prf_used = 0x%x\r\n",prf_env.prf_used); + } + } + // unregister profile + prf_env.prf[i].id = TASK_ID_INVALID; + prf_env.prf[i].desc.default_handler = NULL; + prf_env.prf[i].desc.state = NULL; + prf_env.prf[i].desc.idx_max = 0; + + // Request kernel to flush task messages + kernel_task_msg_flush(KERNEL_TYPE_GET(prf_env.prf[i].task)); + } + } +} + +void prf_remove(kernel_task_id_t task_id) +{ + uint8_t i; + uint16_t id = KERNEL_TYPE_GET(task_id); + + for(i = 0; i < BLE_NB_PROFILES ; i++) + { + // Get Profile API + if(prf_env.prf[i].id == id) + { + const struct prf_task_cbs * cbs = prf_itf_get(prf_env.prf[i].id); + if(cbs != NULL) + { + // request to destroy profile + cbs->destroy(&(prf_env.prf[i])); + if(prf_env.prf_used > 0) + { + prf_env.prf_used--; + //UART_PRINTF("*******destroy prf_used = 0x%x\r\n",prf_env.prf_used); + } + } + // unregister profile + prf_env.prf[i].id = TASK_ID_INVALID; + prf_env.prf[i].desc.default_handler = NULL; + prf_env.prf[i].desc.state = NULL; + prf_env.prf[i].desc.idx_max = 0; + + // Request kernel to flush task messages + kernel_task_msg_flush(KERNEL_TYPE_GET(prf_env.prf[i].task)); + } + } +} + +uint8_t prf_add_profile(struct gapm_profile_task_add_cmd * params, kernel_task_id_t* prf_task) +{ + uint8_t i; + uint8_t status = GAP_ERR_NO_ERROR; + + // retrieve profile callback + const struct prf_task_cbs * cbs = prf_itf_get(params->prf_task_id); + if(cbs == NULL) + { + // profile API not available + status = GAP_ERR_INVALID_PARAM; + } + + // check if profile not already present in task list + if(status == GAP_ERR_NO_ERROR) + { + for(i = 0; i < BLE_NB_PROFILES ; i++) + { + if(prf_env.prf[i].id == params->prf_task_id) + { + status = GAP_ERR_NOT_SUPPORTED; + break; + } + } + } + + if(status == GAP_ERR_NO_ERROR) + { + // find fist available task + for(i = 0; i < BLE_NB_PROFILES ; i++) + { + // available task found + if(prf_env.prf[i].id == TASK_ID_INVALID) + { + // initialize profile + status = cbs->init(&(prf_env.prf[i]), &(params->start_hdl), params->app_task, params->sec_lvl, params->param); + prf_env.prf_used++; + //UART_PRINTF("add prf_used = 0x%x\r\n",prf_env.prf_used); + // initialization succeed + if(status == GAP_ERR_NO_ERROR) + { + // register profile + prf_env.prf[i].id = params->prf_task_id; + *prf_task = prf_env.prf[i].task; + } + break; + } + } + + if(i == BLE_NB_PROFILES) + { + status = GAP_ERR_INSUFF_RESOURCES; + //UART_PRINTF("GAP_ERR_INSUFF_RESOURCES 1\r\n"); + } + } + //UART_PRINTF("prf_add_profile status = 0x%x\r\n",status); + return (status); +} + + + +void prf_create(uint8_t conidx) +{ + uint8_t i; + /* simple connection creation handler, nothing to do. */ + + // execute create function of each profiles + for(i = 0; i < BLE_NB_PROFILES ; i++) + { + // Get Profile API + const struct prf_task_cbs * cbs = prf_itf_get(prf_env.prf[i].id); + if(cbs != NULL) + { + // call create callback + cbs->create(&(prf_env.prf[i]), conidx); + } + } +} + + +void prf_cleanup(uint8_t conidx, uint8_t reason) +{ + uint8_t i; + /* simple connection creation handler, nothing to do. */ + + // execute create function of each profiles + for(i = 0; i < BLE_NB_PROFILES ; i++) + { + // Get Profile API + const struct prf_task_cbs * cbs = prf_itf_get(prf_env.prf[i].id); + if(cbs != NULL) + { + // call cleanup callback + cbs->cleanup(&(prf_env.prf[i]), conidx, reason); + } + } +} + + +prf_env_t* prf_env_get(uint16_t prf_id) +{ + prf_env_t* env = NULL; + uint8_t i; + // find if profile present in profile tasks + for(i = 0; i < BLE_NB_PROFILES ; i++) + { + // check if profile identifier is known + if(prf_env.prf[i].id == prf_id) + { + env = prf_env.prf[i].env; + break; + } + } + + return env; +} + +#if (BLE_SDP_CLIENT) +//added by allen 2018/04/19 +uint16_t prf_get_uuid_from_handle(uint16_t handle) +{ + struct sdp_env_tag* sdp_env; + uint16_t uuid = 0xffff; + uint8_t i; + uint8_t j; + + // find if profile present in profile tasks + for(i = 0; i < BLE_NB_PROFILES ; i++) + { + if(prf_env.prf[i].role == PRF_CLIENT) + { + sdp_env = (struct sdp_env_tag *) prf_env.prf[i].env; + // check if profile identifier is known + for(j = 0; j < sdp_env->db_env[0].cnx_env->sdp.chars_nb; j++) + { + if(sdp_env->db_env[0].cnx_env->sdp.chars[j].val_hdl == handle) + { + uuid = sdp_env->db_env[0].cnx_env->sdp.chars[j].uuid; + return uuid; + } + } + } + } + + return uuid; +} + +struct prf_env_t * prf_env_get_from_uuid(uint16_t uuid,uint16_t char_num) +{ + struct sdp_env_tag* sdp_env; + struct prf_env_t* env = NULL; + uint8_t i; + uint8_t j; + + // find if profile present in profile tasks + for(i = 0; i < BLE_NB_PROFILES ; i++) + { + //uart_printf("prf_env.prf[%d].id = 0x%x \r\n",i,prf_env.prf[i].id); + if(prf_env.prf[i].role == PRF_CLIENT) + { + sdp_env = (struct sdp_env_tag *) prf_env.prf[i].env; + // check if profile identifier is known + for(j = 0; j < sdp_env->db_env[0].cnx_env->sdp.chars_nb; j++) + { + if(sdp_env->db_env[0].cnx_env->sdp.chars[j].uuid == uuid) + { + if(char_num==j||char_num==0) + { + env = (struct prf_env_t*) prf_env.prf[i].env; + sdp_env->db_env[0].cnx_env->sdp.char_idx = j; + return env; + } + } + } + } + } + + return env; + +} +#endif + +kernel_task_id_t prf_src_task_get(prf_env_t* env, uint8_t conidx) +{ + kernel_task_id_t task = PERM_GET(env->prf_task, PRF_TASK); + + if(PERM_GET(env->prf_task, PRF_MI)) + { + task = KERNEL_BUILD_ID(task, conidx); + } + + return task; +} + +kernel_task_id_t prf_dst_task_get(prf_env_t* env, uint8_t conidx) +{ + kernel_task_id_t task = PERM_GET(env->app_task, PRF_TASK); + + if(PERM_GET(env->app_task, PRF_MI)) + { + task = KERNEL_BUILD_ID(task, conidx); + } + + return task; +} + + +kernel_task_id_t prf_get_id_from_task(kernel_msg_id_t task) +{ + kernel_task_id_t id = TASK_ID_INVALID; + uint8_t idx = KERNEL_IDX_GET(task); + uint8_t i; + task = KERNEL_TYPE_GET(task); + + // find if profile present in profile tasks + for(i = 0; i < BLE_NB_PROFILES ; i++) + { + // check if profile identifier is known + if(prf_env.prf[i].task == task) + { + id = prf_env.prf[i].id; + break; + } + } + + return KERNEL_BUILD_ID(id, idx); +} + +kernel_task_id_t prf_get_task_from_id(kernel_msg_id_t id) +{ + kernel_task_id_t task = TASK_BLE_NONE; + uint8_t idx = KERNEL_IDX_GET(id); + uint8_t i; + id = KERNEL_TYPE_GET(id); + + // find if profile present in profile tasks + for(i = 0; i < BLE_NB_PROFILES ; i++) + { + // check if profile identifier is known + if(prf_env.prf[i].id == id) + { + task = prf_env.prf[i].task; + break; + } + } + + return KERNEL_BUILD_ID(task, idx); +} + + +#endif // (BLE_PROFILES) + +/// @} PRF diff --git a/beken_os/beken378/driver/ble/ble_pub/ip/ble/profiles/comm/api/comm.h b/beken_os/beken378/driver/ble/ble_pub/ip/ble/profiles/comm/api/comm.h new file mode 100755 index 0000000..f2a78c5 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/ip/ble/profiles/comm/api/comm.h @@ -0,0 +1,55 @@ +#ifndef _COMM_H_ +#define _COMM_H_ + +#include "rwip_config.h" +#include "rwprf_config.h" + +#if (BLE_COMM_SERVER) +#include "ble.h" +#include "ble_pub.h" +#include "ble_api.h" +#include "comm_task.h" +#include "atts.h" +#include "prf_types.h" +#include "prf.h" +#include "ble_compiler.h" + +enum bk_ble_state +{ + /// Idle state + BLE_IDLE, + /// busy state + BLE_BUSY, + /// Number of defined states. + BLE_STATE_MAX +}; + +/// 'Profile' Server environment variable +struct bk_ble_env_tag +{ + /// profile environment + prf_env_t prf_env; + + /// On-going operation + struct kernel_msg * operation; + /// Services Start Handle + uint16_t start_hdl; + + /// Number of attribute + uint8_t att_db_nb; + + /// Profile id + uint16_t id; + + /// BASS task state + kernel_state_t state[BLE_CONN_IDX_MAX]; + + uint16_t ntf_cfg[BLE_CONNECTION_MAX]; + + uint16_t ind_cfg[BLE_CONNECTION_MAX]; +}; + +const struct prf_task_cbs* bk_ble_prf_itf_get(void); + +#endif +#endif diff --git a/beken_os/beken378/driver/ble/ble_pub/ip/ble/profiles/comm/api/comm_pub.h b/beken_os/beken378/driver/ble/ble_pub/ip/ble/profiles/comm/api/comm_pub.h new file mode 100755 index 0000000..e69de29 diff --git a/beken_os/beken378/driver/ble/ble_pub/ip/ble/profiles/comm/api/comm_task.h b/beken_os/beken378/driver/ble/ble_pub/ip/ble/profiles/comm/api/comm_task.h new file mode 100755 index 0000000..f9d07c8 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/ip/ble/profiles/comm/api/comm_task.h @@ -0,0 +1,92 @@ +#ifndef _COMM_TASK_H_ +#define _COMM_TASK_H_ + +#include "rwprf_config.h" +#if (BLE_COMM_SERVER) +#include +#include "rwip_task.h" // Task definitions +#include "ble_compiler.h" + + +struct bk_ble_enable_req +{ + /// connection index + uint8_t conidx; + /// Configuration + uint16_t ind_cfg; + + uint16_t ntf_cfg; + +}; + +struct bk_ble_enable_rsp +{ + /// connection index + uint8_t conidx; + uint16_t prf_id; + ///status + uint8_t status; +}; + +struct bk_ble_ntf_upd_req +{ + /// instance + uint8_t conidx; + + uint16_t length; + + uint16_t att_id; + /// ffe1 Level + uint8_t value[__ARRAY_EMPTY]; +}; + +struct bk_ble_ind_upd_req +{ + /// instance + uint8_t conidx; + + uint16_t length; + + uint16_t att_id; + /// ffe1 Level + uint8_t value[__ARRAY_EMPTY]; +}; + + +struct bk_ble_write_ind +{ + uint8_t conidx; + uint16_t prf_id; + uint16_t att_id; + uint8_t length; + uint8_t value[__ARRAY_EMPTY]; +}; + +/// Command complete event data structure +struct bk_ble_gattc_cmp_evt +{ + /// GATT request type + uint8_t operation; + /// Status of the request + uint8_t status; + + uint16_t prf_id; + /// operation sequence number - provided when operation is started + uint16_t att_id; +}; + +enum bk_ble_msg_id +{ + BK_BLE_ENABLE_REQ = TASK_FIRST_MSG(TASK_ID_COMMON), + BK_BLE_ENABLE_RSP, + BK_BLE_NTF_UPD_REQ, + BK_BLE_IND_UPD_REQ, + BK_BLE_WRITE_REQ_IND, + BK_BLE_GATTC_CMP_EVT, +}; + +extern const struct kernel_state_handler bk_ble_default_handler; + +#endif + +#endif diff --git a/beken_os/beken378/driver/ble/ble_pub/ip/ble/profiles/comm/src/comm.c b/beken_os/beken378/driver/ble/ble_pub/ip/ble/profiles/comm/src/comm.c new file mode 100755 index 0000000..f290211 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/ip/ble/profiles/comm/src/comm.c @@ -0,0 +1,117 @@ +#include "rwip_config.h" + +#if (BLE_COMM_SERVER) +#include "attm.h" +#include "comm.h" +#include "comm_task.h" +#include "prf_utils.h" +#include "prf.h" +#include "kernel_mem.h" + +static uint8_t bk_ble_service_init (struct prf_task_env* env, uint16_t* start_hdl, uint16_t app_task, uint8_t sec_lvl, struct bk_ble_db_cfg* params) +{ + uint16_t shdl; + struct bk_ble_env_tag* ble_env = NULL; + // Status + uint8_t status = GAP_ERR_NO_ERROR; + + //-------------------- allocate memory required for the profile --------------------- + ble_env = (struct bk_ble_env_tag* ) kernel_malloc(sizeof(struct bk_ble_env_tag), KERNEL_MEM_ATT_DB); + memset(ble_env, 0 , sizeof(struct bk_ble_env_tag)); + + // Service content flag + uint16_t cfg_flag = 0xFFFF; + + shdl = *start_hdl; + + //Create FFF0 in the DB + //------------------ create the attribute database for the profile ------------------- + status = attm_svc_create_db_128(&(shdl), params->uuid, (uint8_t *)&cfg_flag, + params->att_db_nb, NULL, env->task, (struct attm_desc_128 *)params->att_db, + (sec_lvl & (PERM_MASK_SVC_DIS | PERM_MASK_SVC_AUTH | PERM_MASK_SVC_EKS | PERM_MASK_SVC_UUID_LEN))); + + //-------------------- Update profile task information --------------------- + if (status == ATT_ERR_NO_ERROR) + { + + // allocate BASS required environment variable + env->env = (prf_env_t*) ble_env; + *start_hdl = shdl; + ble_env->start_hdl = *start_hdl; + ble_env->prf_env.app_task = app_task + | (PERM_GET(sec_lvl, SVC_MI) ? PERM(PRF_MI, ENABLE) : PERM(PRF_MI, DISABLE)); + ble_env->prf_env.prf_task = env->task | PERM(PRF_MI, DISABLE); + + ble_env->att_db_nb = params->att_db_nb; + + // initialize environment variable + env->id = params->prf_task_id; + env->desc.idx_max = BLE_CONN_IDX_MAX; + env->desc.state = ble_env->state; + env->desc.default_handler = &bk_ble_default_handler; + + bk_printf("ble_env->start_hdl = 0x%x",ble_env->start_hdl); + + // service is ready, go into an Idle state + kernel_state_set(env->task, BLE_IDLE); + } + else if(ble_env != NULL) + { + kernel_free(ble_env); + } + + return (status); +} + +static void bk_ble_service_destroy(struct prf_task_env* env) +{ + struct bk_ble_env_tag* ble_env = (struct bk_ble_env_tag*) env->env; + + // clear on-going operation + if(ble_env->operation != NULL) + { + kernel_free(ble_env->operation); + } + + // free profile environment variables + env->env = NULL; + kernel_free(ble_env); +} + +static void bk_ble_service_create(struct prf_task_env* env, uint8_t conidx) +{ + struct bk_ble_env_tag* ble_env = (struct bk_ble_env_tag*) env->env; + ASSERT_ERR(conidx < BLE_CONNECTION_MAX); + + // force notification config to zero when peer device is connected + ble_env->ntf_cfg[conidx] = 0; + ble_env->ind_cfg[conidx] = 0; +} + + +static void bk_ble_service_cleanup(struct prf_task_env* env, uint8_t conidx, uint8_t reason) +{ + struct bk_ble_env_tag* ble_env = (struct bk_ble_env_tag*) env->env; + + ASSERT_ERR(conidx < BLE_CONNECTION_MAX); + // force notification config to zero when peer device is disconnected + ble_env->ntf_cfg[conidx] = 0; + ble_env->ind_cfg[conidx] = 0; +} + +/// Task interface required by profile manager +const struct prf_task_cbs bk_ble_itf = +{ + (prf_init_fnct) bk_ble_service_init, + bk_ble_service_destroy, + bk_ble_service_create, + bk_ble_service_cleanup, +}; + +const struct prf_task_cbs* bk_ble_prf_itf_get(void) +{ + return &bk_ble_itf; +} + +#endif + diff --git a/beken_os/beken378/driver/ble/ble_pub/ip/ble/profiles/comm/src/comm_task.c b/beken_os/beken378/driver/ble/ble_pub/ip/ble/profiles/comm/src/comm_task.c new file mode 100755 index 0000000..378bb4e --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/ip/ble/profiles/comm/src/comm_task.c @@ -0,0 +1,387 @@ +#include "rwip_config.h" + +#if (BLE_COMM_SERVER) + +#include "gap.h" +#include "gattc_task.h" +#include "attm.h" +#include "atts.h" +#include "common_utils.h" +#include "kernel_mem.h" +#include "comm.h" +#include "comm_task.h" + +#include "prf_utils.h" +#include "ble.h" +#include "ble_pub.h" +#include "ble_api.h" + +extern struct prf_env_tag prf_env;; + +static uint8_t bk_ble_get_prf_by_handler(uint16_t handler, struct prf_task_env **env) +{ + uint8_t status = PRF_APP_ERROR; + struct bk_ble_env_tag* ble_env = NULL; + uint32_t i; + for(i = 0; i < BLE_NB_PROFILES ; i++) + { + ble_env = (struct bk_ble_env_tag*)(prf_env.prf[i].env); + if(((ble_env->start_hdl) <= handler) && ((ble_env->start_hdl + ble_env->att_db_nb) >= handler)) + { + *env = &(prf_env.prf[i]); + status = GAP_ERR_NO_ERROR; + break; + } + } + + return status; +} + +static uint8_t bk_ble_get_prf_by_task(kernel_task_id_t task, struct prf_task_env **env) +{ + uint8_t status = PRF_APP_ERROR; + uint32_t i; + for(i = 0; i < BLE_NB_PROFILES ; i++) + { + if(prf_env.prf[i].task == task) + { + *env = &(prf_env.prf[i]); + status = GAP_ERR_NO_ERROR; + break; + } + } + + return status; +} + +static int bk_ble_enable_req_handler(kernel_msg_id_t const msgid, + struct bk_ble_enable_req const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + int msg_status = KERNEL_MSG_SAVED; + uint8_t state = kernel_state_get(dest_id); + + struct prf_task_env *prf_env = NULL; + + // retrieve handle information + uint8_t status = bk_ble_get_prf_by_task(dest_id, &prf_env); + if(status != GAP_ERR_NO_ERROR) + { + bk_printf("dest_id is invalid:%d\r\n", dest_id); + return KERNEL_MSG_CONSUMED; + } + + // check state of the task + if(state == BLE_IDLE) + { + // struct ffe0s_env_tag* ffe0s_env = PRF_ENV_GET(FFE0S, ffe0s); + + // Check provided values + if((param->conidx > BLE_CONNECTION_MAX) + || (gapc_get_conhdl(param->conidx) == GAP_INVALID_CONHDL)) + { + // an error occurs, trigg it. + struct bk_ble_enable_rsp* rsp = KERNEL_MSG_ALLOC(BK_BLE_ENABLE_RSP, src_id, + dest_id, bk_ble_enable_rsp); + rsp->prf_id = prf_env->id - TASK_ID_COMMON; + rsp->conidx = param->conidx; + rsp->status = (param->conidx > BLE_CONNECTION_MAX) ? GAP_ERR_INVALID_PARAM : PRF_ERR_REQ_DISALLOWED; + kernel_msg_send(rsp); + + msg_status = KERNEL_MSG_CONSUMED; + } + + } + + return msg_status; +} + +static void bk_ble_ntf_val(struct bk_ble_env_tag* ble_env,struct bk_ble_ntf_upd_req const *param) +{ + + // UART_PRINTF("%s\r\n",__func__); + //Allocate the GATT notification message + struct gattc_send_evt_cmd *ntf_value = KERNEL_MSG_ALLOC_DYN(GATTC_SEND_EVT_CMD, + KERNEL_BUILD_ID(TASK_GATTC, 0), prf_src_task_get(&(ble_env->prf_env),0), + gattc_send_evt_cmd, param->length); + + //Fill in the parameter structure + ntf_value->operation = GATTC_NOTIFY; + ntf_value->handle = ble_env->start_hdl + param->att_id; + // pack measured value in databaseS + ntf_value->length = param->length; + ntf_value->seq_num = param->att_id; + + //UART_PRINTF("fed6_value->handle = 0x%x\r\n",fed6_value->handle); + memcpy(&ntf_value->value[0],param->value,ntf_value->length); + + //send notification to peer device + kernel_msg_send(ntf_value); +} + +static int bk_ble_ntf_upd_req_handler(kernel_msg_id_t const msgid, + struct bk_ble_ntf_upd_req const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + int msg_status = KERNEL_MSG_CONSUMED; + uint8_t state = kernel_state_get(dest_id); + + struct prf_task_env *prf_env = NULL; + struct bk_ble_env_tag* ble_env = NULL; + + // retrieve handle information + uint8_t status = bk_ble_get_prf_by_task(dest_id, &prf_env); + // retrieve handle information + ble_env = (struct bk_ble_env_tag*)(prf_env->env); + if(GAP_ERR_NO_ERROR == status) + { + // check state of the task + if(state == BLE_IDLE) + { + // update the battery level value + kernel_state_set(dest_id, BLE_BUSY); + + bk_ble_ntf_val(ble_env, param); + // ke_state_set(dest_id, FEB3S_IDLE); + msg_status = KERNEL_MSG_CONSUMED; + } + else + { + //UART_PRINTF("KE_MSG_SAVED6\r\n"); + msg_status = KERNEL_MSG_SAVED; + } + } + + return (msg_status); + +} + +static void bk_ble_ind_val(struct bk_ble_env_tag* ble_env,struct bk_ble_ind_upd_req const *param) +{ + + // UART_PRINTF("%s\r\n",__func__); + //Allocate the GATT notification message + struct gattc_send_evt_cmd *ntf_value = KERNEL_MSG_ALLOC_DYN(GATTC_SEND_EVT_CMD, + KERNEL_BUILD_ID(TASK_GATTC, 0), prf_src_task_get(&(ble_env->prf_env),0), + gattc_send_evt_cmd, param->length); + + //Fill in the parameter structure + ntf_value->operation = GATTC_INDICATE; + ntf_value->handle = ble_env->start_hdl + param->att_id; + // pack measured value in databaseS + ntf_value->length = param->length; + ntf_value->seq_num = param->att_id; + + //UART_PRINTF("fed6_value->handle = 0x%x\r\n",fed6_value->handle); + memcpy(&ntf_value->value[0],param->value,ntf_value->length); + + //send notification to peer device + kernel_msg_send(ntf_value); +} + +static int bk_ble_ind_upd_req_handler(kernel_msg_id_t const msgid, + struct bk_ble_ind_upd_req const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + int msg_status = KERNEL_MSG_CONSUMED; + uint8_t state = kernel_state_get(dest_id); + + struct prf_task_env *prf_env = NULL; + struct bk_ble_env_tag* ble_env = NULL; + + // retrieve handle information + uint8_t status = bk_ble_get_prf_by_task(dest_id, &prf_env); + // retrieve handle information + ble_env = (struct bk_ble_env_tag*)(prf_env->env); + if(GAP_ERR_NO_ERROR == status) + { + // check state of the task + if(state == BLE_IDLE) + { + // update the battery level value + kernel_state_set(dest_id, BLE_BUSY); + + bk_ble_ind_val(ble_env, param); + // ke_state_set(dest_id, FEB3S_IDLE); + msg_status = KERNEL_MSG_CONSUMED; + } + else + { + //UART_PRINTF("KE_MSG_SAVED6\r\n"); + msg_status = KERNEL_MSG_SAVED; + } + } + + return (msg_status); + +} + +static int gattc_att_info_req_ind_handler(kernel_msg_id_t const msgid, + struct gattc_att_info_req_ind *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + struct gattc_att_info_cfm * cfm; + att_info_req_t att_info; + // retrieve handle information + struct prf_task_env *prf_env = NULL; + struct bk_ble_env_tag* ble_env = NULL; + + // retrieve handle information + uint8_t status = bk_ble_get_prf_by_handler(param->handle, &prf_env); + ble_env = (struct bk_ble_env_tag*)(prf_env->env); + att_info.att_idx = param->handle - ble_env->start_hdl; + att_info.prf_id = prf_env->id - TASK_ID_COMMON; + //Send write response + cfm = KERNEL_MSG_ALLOC(GATTC_ATT_INFO_CFM, src_id, dest_id, gattc_att_info_cfm); + cfm->handle = param->handle; + + if(status == GAP_ERR_NO_ERROR) + { + if(ble_event_cb) + { + ble_event_cb(BLE_ATT_INFO_REQ, (void *)&att_info); + } + } + + cfm->length = att_info.length; + cfm->status = att_info.status; + kernel_msg_send(cfm); + + return (KERNEL_MSG_CONSUMED); +} + +static int gattc_read_req_ind_handler(kernel_msg_id_t const msgid, struct gattc_read_req_ind const *param, + kernel_task_id_t const dest_id, kernel_task_id_t const src_id) +{ + struct gattc_read_cfm * cfm; + read_req_t read_req; + uint16_t length = 0; + + struct prf_task_env *prf_env = NULL; + struct bk_ble_env_tag* ble_env = NULL; + + // retrieve handle information + uint8_t status = bk_ble_get_prf_by_handler(param->handle, &prf_env); + + read_req.value = kernel_malloc(BLE_CHAR_DATA_LEN, KERNEL_MEM_KERNEL_MSG); + read_req.size = BLE_CHAR_DATA_LEN; + ble_env = (struct bk_ble_env_tag*)(prf_env->env); + read_req.att_idx = param->handle - ble_env->start_hdl; + read_req.prf_id = prf_env->id - TASK_ID_COMMON; + // If the attribute has been found, status is GAP_ERR_NO_ERROR + if (status == GAP_ERR_NO_ERROR) + { + if(bk_ble_read_cb) + { + length = bk_ble_read_cb(&read_req); + } + } + + cfm = KERNEL_MSG_ALLOC_DYN(GATTC_READ_CFM, src_id, dest_id, gattc_read_cfm, length); + + cfm->length = length; + cfm->handle = param->handle; + cfm->status = status; + memcpy(cfm->value,read_req.value,cfm->length); + + kernel_msg_send(cfm); + + kernel_free(read_req.value); + + return (KERNEL_MSG_CONSUMED); +} + +static int gattc_write_req_ind_handler(kernel_msg_id_t const msgid, struct gattc_write_req_ind const *param, + kernel_task_id_t const dest_id, kernel_task_id_t const src_id) +{ + struct gattc_write_cfm * cfm; + struct prf_task_env *prf_env = NULL; + struct bk_ble_env_tag* ble_env = NULL; + + // retrieve handle information + uint8_t status = bk_ble_get_prf_by_handler(param->handle, &prf_env); + uint8_t conidx = KERNEL_IDX_GET(src_id); + // retrieve handle information + ble_env = (struct bk_ble_env_tag*)(prf_env->env); + + + + // If the attribute has been found, status is GAP_ERR_NO_ERROR + if (status == GAP_ERR_NO_ERROR) + { + // Allocate the alert value change indication + struct bk_ble_write_ind *ind = KERNEL_MSG_ALLOC_DYN(BK_BLE_WRITE_REQ_IND, + prf_dst_task_get(&(ble_env->prf_env), conidx), + dest_id, bk_ble_write_ind, param->length); + + // Fill in the parameter structure + memcpy(ind->value,¶m->value[0],param->length); + ind->att_id = param->handle - ble_env->start_hdl;; + ind->prf_id = prf_env->id - TASK_ID_COMMON; + ind->conidx = conidx; + ind->length = param->length; + // Send the message + kernel_msg_send(ind); + } + + //Send write response + cfm = KERNEL_MSG_ALLOC(GATTC_WRITE_CFM, src_id, dest_id, gattc_write_cfm); + cfm->handle = param->handle; + cfm->status = status; + kernel_msg_send(cfm); + + return (KERNEL_MSG_CONSUMED); +} + +static int gattc_cmp_evt_handler(kernel_msg_id_t const msgid, struct gattc_cmp_evt const *param, + kernel_task_id_t const dest_id, kernel_task_id_t const src_id) +{ + //UART_PRINTF("%s\r\n",__func__); + struct prf_task_env *prf_env = NULL; + struct bk_ble_env_tag* ble_env = NULL; + + // retrieve handle information + uint8_t status = bk_ble_get_prf_by_task(dest_id, &prf_env); + // retrieve handle information + ble_env = (struct bk_ble_env_tag*)(prf_env->env); + + if (status == GAP_ERR_NO_ERROR) + { + // continue operation execution + struct bk_ble_gattc_cmp_evt *evt = KERNEL_MSG_ALLOC(BK_BLE_GATTC_CMP_EVT, + prf_dst_task_get(&(ble_env->prf_env), 0), + dest_id, bk_ble_gattc_cmp_evt); + + evt->operation = param->operation; + evt->status = param->status; + evt->prf_id = prf_env->id - TASK_ID_COMMON; + evt->att_id = param->seq_num; + + kernel_state_set(dest_id, BLE_IDLE); + kernel_msg_send(evt); + } + + return (KERNEL_MSG_CONSUMED); +} + +/// Default State handlers definition +const struct kernel_msg_handler bk_ble_default_state[] = +{ + {BK_BLE_ENABLE_REQ, (kernel_msg_func_t) bk_ble_enable_req_handler}, + {BK_BLE_NTF_UPD_REQ, (kernel_msg_func_t) bk_ble_ntf_upd_req_handler}, + {BK_BLE_IND_UPD_REQ, (kernel_msg_func_t) bk_ble_ind_upd_req_handler}, + {GATTC_ATT_INFO_REQ_IND, (kernel_msg_func_t) gattc_att_info_req_ind_handler}, + {GATTC_READ_REQ_IND, (kernel_msg_func_t) gattc_read_req_ind_handler}, + {GATTC_WRITE_REQ_IND, (kernel_msg_func_t) gattc_write_req_ind_handler}, + {GATTC_CMP_EVT, (kernel_msg_func_t) gattc_cmp_evt_handler}, +}; + + +/// Specifies the message handlers that are common to all states. +const struct kernel_state_handler bk_ble_default_handler = KERNEL_STATE_HANDLER(bk_ble_default_state); + +#endif diff --git a/beken_os/beken378/driver/ble/ble_pub/ip/ble/profiles/sdp/api/sdp_service.h b/beken_os/beken378/driver/ble/ble_pub/ip/ble/profiles/sdp/api/sdp_service.h new file mode 100755 index 0000000..812c92f --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/ip/ble/profiles/sdp/api/sdp_service.h @@ -0,0 +1,132 @@ +/** + **************************************************************************************** + * + * @file sdp_service.h + * + * @brief Header file - sdp Role. + * + * Copyright (C) Beken 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef _SDP_SERVICE_H_ +#define _SDP_SERVICE_H_ + +/** + **************************************************************************************** + * @addtogroup SDP_SERVICE + * @ingroup SDP + * @brief SDP Service + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_config.h" +#if 1 //(BLE_SDP_CLIENT) + +#include +#include +#include "kernel_task.h" +#include "common_utils.h" +#include "prf_types.h" +#include "prf_utils.h" +#include "sdp_service_task.h" + +/* + * DEFINES + **************************************************************************************** + */ + +#define INVALID_STATUS (0xFFFF) +#define VALID_STATUS (0xA5A5) +/* + * ENUMERATIONS + **************************************************************************************** + */ + + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + +struct sdp_db_env +{ + ///Number of instances added + uint8_t prf_nb; + /// on-going operation + struct sdp_cnx_env *cnx_env; + +}; + +/// Environment variable for each Connections +struct sdp_cnx_env +{ + + + ///SDP characteristics + struct sdp_content sdp; + + ///Number of BAS instances found +}; + +/// SDP 'Profile' Client environment variable +struct sdp_env_tag +{ + /// profile environment + prf_env_t prf_env; + + uint16_t use_status; + /// on-going operation + struct kernel_msg * operation; + + /// Environment variable pointer for each connections + struct sdp_db_env db_env[SDP_IDX_MAX]; + /// State of different task instances + kernel_state_t state[SDP_IDX_MAX]; +}; + +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ + +extern uint8_t sdp_need_dis_flag; +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + + +/** + **************************************************************************************** + * @brief Retrieve BAS client profile interface + * + * @return BAS client profile interface + **************************************************************************************** + */ +const struct prf_task_cbs* sdp_prf_itf_get(void); + +/** + **************************************************************************************** + * @brief Send ATT DB discovery results to BASC host. + **************************************************************************************** + */ + +void sdp_discover_all_service(void); +void sdp_service_init_env(void); +void sdp_add_profiles(struct sdp_db_env *env); +void sdp_extract_svc_info(struct gattc_sdp_svc_ind const *param); +void sdp_enable_rsp_send(struct sdp_env_tag *basc_env, uint8_t conidx, uint8_t status); + +#endif /* (BLE_BATT_CLIENT) */ + +/// @} BASC + +#endif /* _BASC_H_ */ diff --git a/beken_os/beken378/driver/ble/ble_pub/ip/ble/profiles/sdp/api/sdp_service_task.h b/beken_os/beken378/driver/ble/ble_pub/ip/ble/profiles/sdp/api/sdp_service_task.h new file mode 100755 index 0000000..fe8edf5 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/ip/ble/profiles/sdp/api/sdp_service_task.h @@ -0,0 +1,224 @@ +/** + **************************************************************************************** + * + * @file sdp_service_task.h + * + * @brief Header file - SDP Service Client Role Task. + * + * Copyright (C) Beken 2009-2015 + * + * + **************************************************************************************** + */ + + +#ifndef _SDP_SERVICE_TASK_H_ +#define _SDP_SERVICE_TASK_H_ + +/** + **************************************************************************************** + * @addtogroup SDP Service Client Task + * @ingroup SDP + * @brief SDP Service Client Task + * + * The SDPTASK is responsible for handling the messages coming in and out of the + * @ref SDP block of the BLE Host. + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" + +#if (BLE_SDP_CLIENT) +#include "kernel_task.h" +#include "prf_types.h" +#include "rwip_task.h" + +/* + * DEFINES + **************************************************************************************** + */ + +///Maximum number of Battery Client task instances +#define SDP_IDX_MAX (BLE_CONNECTION_MAX) + +///Maximum number of SDP Service instances we can handle +#define SDP_NB_BAS_INSTANCES_MAX (2) + + +#define SDP_NB_SERVICE_INSTANCES_MAX (BLE_NB_PROFILES - 2) +#define SDP_NB_CHAR_INSTANCES_MAX (20) +#define SDP_NB_DESC_INSTANCES_MAX (SDP_NB_CHAR_INSTANCES_MAX * 1) +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + + +/// Parameters for the database creation +struct sdp_db_cfg +{ + /// Number of sdp to add + uint8_t sdp_idx; + +}; + +/// Possible states of the SDP task +enum sdp_state +{ + /// Disconnected state + SDP_FREE, + SDP_IDLE, + SDP_DISCOVING, + SDP_BUSY, + SDP_STATE_MAX +}; + +enum sdp_msg_id +{ + /// Start the Battery Service Client Role - at connection + SDP_ENABLE_REQ = TASK_FIRST_MSG(TASK_ID_SDP), + /// Confirm that cfg connection has finished with discovery results, or that normal cnx started + SDP_ENABLE_RSP, + + /// Read Characteristic xxxx Request + SDP_READ_INFO_REQ, + /// Read Characteristic xxxx Response + SDP_READ_INFO_RSP, + + /// Write Characteristic Value Request + SDP_WRITE_VALUE_INFO_REQ, + /// Write Characteristic Value response + SDP_WRITE_VALUE_INFO_RSP, + + /// Write Notification Configuration Value request + SDP_WRITE_NTF_CFG_REQ, + /// Write Notification Configuration Value response + SDP_WRITE_NTF_CFG_RSP, + + /// Indicate to APP that the ntf value has been received + SDP_NTF_IND, +}; + + +/// Peer service info that can be read +enum sdpc_info +{ + /// SERVICE Char value + SDPC_CHAR_VAL, + /// Client Characteristic Configuration + SDPC_CHAR_NTF_CFG, + /// Client Characteristic User Description + SDPC_CHAR_USER_DESC_VAL, + /// Characteristic Presentation Format + SDPC_CHAR_PRES_FORMAT, + + SDPC_INFO_MAX, +}; +/* + * APIs Structure + **************************************************************************************** + */ + +///Structure containing the characteristics handles, value handles and descriptors +struct sdp_content +{ + /// service info + struct prf_svc svc; + + /// Characteristic Info: + uint8_t chars_nb; + uint8_t char_idx; + struct prf_char_inf chars[SDP_NB_CHAR_INSTANCES_MAX]; + + /// Descriptor handles: + /// - Level Client Characteristic Configuration + uint8_t descs_nb; + //struct prf_char_desc_inf *descs; + struct prf_char_desc_inf descs[SDP_NB_DESC_INSTANCES_MAX]; +}; + + +/// Parameters of the @ref SDP_ENABLE_REQ message +struct sdp_enable_req +{ + ///Connection type + uint8_t con_type; +}; + +/// Parameters of the @ref SDP_ENABLE_RSP message +struct sdp_enable_rsp +{ + /// Status + uint8_t status; + +}; + + +///Parameters of the @ref SDP_READ_INFO_REQ message +struct sdp_read_info_req +{ + ///Characteristic info @see enum sdpc_info + uint8_t info; + uint16_t uuid; + +}; + +///Parameters of the @ref SDP_READ_INFO_RSP message +struct sdp_read_info_rsp +{ + /// status of the request + uint8_t status; + ///Characteristic info @see enum sdpc_info + uint8_t info; + /// Information data + uint8_t data[__ARRAY_EMPTY]; +}; + +///Parameters of the @ref SDP_WRITE_INFO_REQ message +struct sdp_write_info_req +{ + uint8_t info; + uint8_t length; + uint16_t uuid; + uint8_t data[__ARRAY_EMPTY]; +}; + +///Parameters of the @ref SDP_W_NTF_CFG_REQ message +struct sdp_w_ntf_cfg_req +{ + uint16_t uuid; + uint16_t char_num; + ///Notification Configuration + uint16_t ntf_cfg; + +}; + +///Parameters of the @ref SDP_W_NTF_CFG_RSP message +struct sdp_w_ntf_cfg_rsp +{ + ///Status + uint8_t status; + ///Battery Service Instance - From 0 to BASC_NB_BAS_INSTANCES_MAX-1 +}; + + + +/* + * TASK DESCRIPTOR DECLARATIONS + **************************************************************************************** + */ + +extern const struct kernel_state_handler sdp_default_handler; + +#endif // (BLE_BATT_CLIENT) + +/// @} SDPTASK + +#endif /* _SDP_SERVICE_TASK_H_ */ diff --git a/beken_os/beken378/driver/ble/ble_pub/ip/ble/profiles/sdp/src/sdp_service.c b/beken_os/beken378/driver/ble/ble_pub/ip/ble/profiles/sdp/src/sdp_service.c new file mode 100755 index 0000000..3578159 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/ip/ble/profiles/sdp/src/sdp_service.c @@ -0,0 +1,481 @@ +/** + **************************************************************************************** + * + * @file sdp_service.c + * + * @brief Sdp Service Client implementation. + * + * Copyright (C) Beken 2009-2015 + * + * + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_config.h" +#if (BLE_SDP_CLIENT) +#include "kernel_mem.h" +#include "gap.h" +#include "kernel_env.h" +#include "sdp_service.h" +#include "sdp_service_task.h" +#include "common_math.h" +#include "uart.h" +#include // standard definition +#include // standard boolean +#include "arch.h" // architecture +#include "common_math.h" // computation utilities +#include "kernel_config.h" // kernel configuration +#include "kernel_env.h" // kernel environment +#include "kernel_mem.h" // kernel memory +#include "RomCallFlash.h" + + +uint8_t sdp_need_dis_flag = 0; +uint8_t prf_nb = 0; +struct sdp_env_tag adp_serv_env[SDP_NB_SERVICE_INSTANCES_MAX]; +struct sdp_cnx_env cnx_env[SDP_NB_SERVICE_INSTANCES_MAX]; + +/* + * LOCAL FUNCTION DEFINITIONS + **************************************************************************************** + */ + +void sdp_service_init_env(void) +{ + for(int i = 0; i < SDP_NB_SERVICE_INSTANCES_MAX ; i++) + { + adp_serv_env[i].use_status = INVALID_STATUS; + adp_serv_env[i].db_env[0].cnx_env = &cnx_env[i]; + } + sdp_need_dis_flag = 0; +} + +static uint8_t sdp_init (struct prf_task_env* env, uint16_t* start_hdl, uint16_t app_task, uint8_t sec_lvl, void* params) +{ + printf("%s \r\n",__func__); + uint8_t idx; + int i; + struct sdp_db_env *db_env = (struct sdp_db_env *)params; + + printf("db_env->prf_nb = %x\r\n",db_env->prf_nb); + printf("db_env->sdp.chars_nb = %x\r\n",db_env->cnx_env->sdp.chars_nb); + + for(i =0; i < db_env->cnx_env->sdp.chars_nb; i++) + { + printf("uuid = 0x%02x,char_hdl = 0x%02x,val_hdl = 0x%02x,prop = 0x%02x\r\n",db_env->cnx_env->sdp.chars[i].uuid,db_env->cnx_env->sdp.chars[i].char_hdl,db_env->cnx_env->sdp.chars[i].val_hdl,db_env->cnx_env->sdp.chars[i].prop); + } + for(i =0; i < db_env->cnx_env->sdp.descs_nb; i++) + { + printf("uuid = 0x%02x,desc_hdl = 0x%02x\r\n",db_env->cnx_env->sdp.descs[i].uuid,db_env->cnx_env->sdp.descs[i].desc_hdl); + } + + //-------------------- allocate memory required for the profile --------------------- + struct sdp_env_tag* sdp_env = &adp_serv_env[db_env->prf_nb]; + + // allocate required environment variable + env->env = (prf_env_t*) sdp_env; + sdp_env->prf_env.app_task = app_task + | (PERM_GET(sec_lvl, SVC_MI) ? PERM(PRF_MI, ENABLE) : PERM(PRF_MI, DISABLE)); + sdp_env->prf_env.prf_task = env->task | PERM(PRF_MI, ENABLE); + // initialize environment variable + env->role = PRF_CLIENT; + env->id = TASK_ID_SDP; + env->desc.idx_max = SDP_IDX_MAX; + env->desc.state = sdp_env->state; + env->desc.default_handler = &sdp_default_handler; + for(idx = 0; idx < SDP_IDX_MAX ; idx++) + { + sdp_env->db_env[0].cnx_env = db_env->cnx_env; //init env + + // service is ready, go into an Idle state + kernel_state_set(KERNEL_BUILD_ID(env->task, idx), SDP_IDLE); + } + if(0 != db_env->cnx_env->sdp.descs_nb) + { + for(idx = 0; idx < SDP_IDX_MAX ; idx++) + { + printf("prf_register_atthdl2gatt start_hdl = 0x%x,end_hdl = 0x%x\r\n",sdp_env->db_env[0].cnx_env->sdp.svc.shdl,sdp_env->db_env[0].cnx_env->sdp.svc.ehdl); + prf_register_atthdl2gatt(&(sdp_env->prf_env), 0, &sdp_env->db_env[0].cnx_env->sdp.svc); + } + } + printf("%s end!!\r\n",__func__); + + return GAP_ERR_NO_ERROR; +} + +/** + **************************************************************************************** + * @brief Destruction of the BASC module - due to a reset for instance. + * This function clean-up allocated memory (attribute database is destroyed by another + * procedure) + * + * @param[in|out] env Collector or Service allocated environment data. + **************************************************************************************** + */ +static void sdp_destroy(struct prf_task_env* env) +{ + printf("sdp_destroy START env->id = 0x%x,role = %x\r\n",env->id,env->role); + + if(sdp_need_dis_flag == 1) + { + printf("no need sdp_destroy \r\n"); + return; + } + uint8_t idx; + struct sdp_env_tag* sdp_env = (struct sdp_env_tag*) env->env; + printf("use_status = 0x%x\r\n",sdp_env->use_status); + sdp_env->use_status = INVALID_STATUS; + // cleanup environment variable for each task instances + for(idx = 0; idx < SDP_IDX_MAX ; idx++) + { + if(sdp_env->db_env[idx].cnx_env != NULL) + { + if(sdp_env->operation != NULL) + { + sdp_env->operation = NULL; + printf("sdp_destroy sdp_env->operation = NULL\r\n"); + } + } + } + // free profile environment variables + printf("sdp_destroy end\r\n"); +} +/** + **************************************************************************************** + * @brief Handles Connection creation + * + * @param[in|out] env Collector or Service allocated environment data. + * @param[in] conidx Connection index + **************************************************************************************** + */ +static void sdp_create(struct prf_task_env* env, uint8_t conidx) +{ + /* Put BAS Client in Idle state */ + kernel_state_set(KERNEL_BUILD_ID(env->task, conidx), SDP_IDLE); +} +/** + **************************************************************************************** + * @brief Handles Disconnection + * + * @param[in|out] env Collector or Service allocated environment data. + * @param[in] conidx Connection index + * @param[in] reason Detach reason + **************************************************************************************** + */ +static void sdp_cleanup(struct prf_task_env* env, uint8_t conidx, uint8_t reason) +{ + + printf("sdp_cleanup env->id = 0x%x,role = %x,conidx = %x reason = 0x%x\r\n",env->id,env->role,conidx,reason); + if(sdp_need_dis_flag == 1) + { + printf("no need sdp_cleanup \r\n"); + return; + } + struct sdp_env_tag* sdp_env = (struct sdp_env_tag*) env->env; + printf("use_status = 0x%x\r\n",sdp_env->use_status); + sdp_env->use_status = INVALID_STATUS; + uint8_t idx; + for(idx = 0; idx < SDP_IDX_MAX ; idx++) + { + if(0 != sdp_env->db_env[idx].cnx_env->sdp.descs_nb) + { + prf_unregister_atthdl2gatt(&(sdp_env->prf_env), idx, &sdp_env->db_env[idx].cnx_env->sdp.svc); + sdp_env->db_env[idx].cnx_env->sdp.descs_nb = 0; + } + } + // clean-up environment variable allocated for task instance + if(sdp_env->db_env[conidx].cnx_env != NULL) + { + if(sdp_env->operation != NULL) + { + struct kernel_msg *msg = kernel_msg2param(sdp_env->operation); + printf("operation = 0x%x\r\n",(unsigned int)sdp_env->operation); + printf("msgid = 0x%02x,dest_id = 0x%02x,src_id = 0x%02x\r\n",msg->id,msg->dest_id,msg->src_id); + + kernel_free(sdp_env->operation); + + } + if(sdp_env->db_env[conidx].cnx_env->sdp.chars_nb != 0) + { + sdp_env->db_env[conidx].cnx_env->sdp.chars_nb = 0; + printf("000042\r\n"); + } + if(sdp_env->db_env[conidx].cnx_env->sdp.descs_nb != 0) + { + sdp_env->db_env[conidx].cnx_env->sdp.descs_nb = 0; + printf("000044\r\n"); + } + printf("00006\r\n"); + } + prf_nb = 0; + printf("sdp_cleanup end\r\n"); + /* Put BAS Client in Free state */ + kernel_state_set(KERNEL_BUILD_ID(env->task, conidx), SDP_FREE); +} + +/* + * GLOBAL VARIABLE DEFINITIONS + **************************************************************************************** + */ +/// BASC Task interface required by profile manager +const struct prf_task_cbs sdp_itf = +{ + sdp_init, + sdp_destroy, + sdp_create, + sdp_cleanup, +}; +/* + * GLOBAL FUNCTIONS DEFINITIONS + **************************************************************************************** + */ +const struct prf_task_cbs* sdp_prf_itf_get(void) +{ + return &sdp_itf; +} +void sdp_discover_all_service(void) +{ + printf("sdp_discover_all_service\r\n"); + sdp_service_init_env(); + struct gattc_sdp_svc_disc_cmd * svc_req = KERNEL_MSG_ALLOC_DYN(GATTC_SDP_SVC_DISC_CMD, + TASK_GATTC, TASK_APP, + gattc_sdp_svc_disc_cmd, ATT_UUID_16_LEN); + //gatt request type: by UUID + svc_req->operation = GATTC_SDP_DISC_SVC_ALL; + //start handle; + svc_req->start_hdl = ATT_1ST_REQ_START_HDL; + //end handle + svc_req->end_hdl = ATT_1ST_REQ_END_HDL; + // UUID search + svc_req->uuid_len = ATT_UUID_16_LEN; + + //set the first two bytes to the value array, LSB to MSB:Health Thermometer Service UUID first + common_write16p(&(svc_req->uuid[0]), 0x0000); + //send the message to GATT, which will send back the response when it gets it + kernel_msg_send(svc_req); +} + +extern struct prf_env_tag prf_env; +void sdp_extract_svc_info(struct gattc_sdp_svc_ind const *ind) +{ + printf("*************************************************************************************************\r\n"); + uint8_t sdp_env_idx = 0; + int i; + uint8_t add_svc_flag = false; + printf("prf_env.prf_used = %d\r\n",prf_env.prf_used); + if(prf_env.prf_used == SDP_NB_SERVICE_INSTANCES_MAX ) + { + printf("not have prf_used = %d\r\n",BLE_NB_PROFILES); + return; + } + for(i = 0; i < SDP_NB_SERVICE_INSTANCES_MAX; i ++) + { + if(adp_serv_env[i].use_status == INVALID_STATUS) + { + sdp_env_idx = i; + add_svc_flag = true; + adp_serv_env[sdp_env_idx].use_status = VALID_STATUS; + printf("found sdp_env_idx = %d,use_status = 0x%04x\r\n",sdp_env_idx,adp_serv_env[sdp_env_idx].use_status); + printf("p_use_status = 0x%x\r\n",(unsigned int)&adp_serv_env[sdp_env_idx].use_status); + break; + } + } + printf("%s\r\n",__func__); + printf("service uuid len = 0x%x,uuid = 0x",ind->uuid_len); + uint16_t uuid ; + uint16_t length; + if(ind->uuid_len == 0x10) + { + uuid = (ind->uuid[12] | (ind->uuid[13] << 8)); + } + else + { + uuid = (ind->uuid[0] | (ind->uuid[1] << 8)); + } + for(i = 0; i < ind->uuid_len; i++) + { + printf("%02x",ind->uuid[i]); + } + printf("\r\n"); + printf("uuid16 = %02x\r\n",uuid); + length = ind->end_hdl - ind->start_hdl; + printf("start_hdl = 0x%02x\r\n",ind->start_hdl); + printf("end_hdl = 0x%02x\r\n",ind->end_hdl); + printf("length = %d\r\n",length); + //Counters + uint8_t svc_char,svc_char_cnt; + uint8_t svc_desc,svc_desc_cnt; + uint8_t fnd_att; + /** search svc_char_cnt and desc_cnt for alloc memory **/ + svc_char_cnt = 0; + svc_desc_cnt = 0; + for (fnd_att=0; fnd_att< (ind->end_hdl - ind->start_hdl); fnd_att++) + { + if(ind->info[fnd_att].att_type == GATTC_SDP_ATT_CHAR) + { + uint16_t val_hdl = ind->info[fnd_att].att_char.handle; + // check that value handle is in a valid range + if((val_hdl <= ind->end_hdl) && (val_hdl > (ind->start_hdl + fnd_att))) + { + //Look over requested characteristics + for (svc_char=0; svc_char < ind->end_hdl -ind->start_hdl ; svc_char++) + { + svc_char_cnt = (svc_char_cnt + 1) % SDP_NB_CHAR_INSTANCES_MAX; + // find end of characteristic handle and discover descriptors + do + { + fnd_att++; + // found a descriptor + if(ind->info[fnd_att].att_type == GATTC_SDP_ATT_DESC) + { + //Retrieve characteristic descriptor handle using UUID + for(svc_desc = 0; svc_descend_hdl - ind->start_hdl; svc_desc++) + { + // check if it's expected descriptor + if ( svc_desc == svc_char) + { + svc_desc_cnt = (svc_desc_cnt + 1 ) % SDP_NB_DESC_INSTANCES_MAX; + } + } + } + } + while(((ind->start_hdl+ 1 + fnd_att) <= ind->end_hdl) + && (ind->info[fnd_att].att_type != GATTC_SDP_ATT_CHAR) + && (ind->info[fnd_att].att_type != GATTC_SDP_INC_SVC)); + // return to previous valid value + fnd_att--; + // search next characteristic + break; + } + } + } + } + /**************************end search ************************************/ + struct sdp_db_env *env = NULL ; + struct prf_char_inf *chars = NULL; + struct prf_char_desc_inf *descs = NULL; + if(true == add_svc_flag) + { + env = adp_serv_env[sdp_env_idx].db_env; + env->prf_nb = sdp_env_idx; + chars = env[0].cnx_env->sdp.chars; + descs = env[0].cnx_env->sdp.descs; + env[0].cnx_env->sdp.svc.shdl = ind->start_hdl; + env[0].cnx_env->sdp.svc.ehdl = ind->end_hdl; + svc_char_cnt = 0; + svc_desc_cnt = 0; + env[0].cnx_env->sdp.chars_nb = 0; + env[0].cnx_env->sdp.descs_nb = 0; + for (fnd_att=0; fnd_att< (ind->end_hdl - ind->start_hdl); fnd_att++) + { + if(ind->info[fnd_att].att_type == GATTC_SDP_ATT_CHAR) + { + uint16_t char_hdl = ind->start_hdl+ 1 + fnd_att; + uint16_t val_hdl = ind->info[fnd_att].att_char.handle; + uint8_t val_prop = ind->info[fnd_att].att_char.prop; + uint8_t char_idx = fnd_att; + // check that value handle is in a valid range + if((val_hdl <= ind->end_hdl) && (val_hdl > (ind->start_hdl + fnd_att))) + { + // retrieve value index + uint8_t val_idx = (val_hdl - ind->start_hdl - 1); + //Look over requested characteristics + for (svc_char=0; svc_char < ind->end_hdl -ind->start_hdl ; svc_char++) + { + printf("char uuid len = 0x%x ,",ind->info[val_idx].att.uuid_len); + printf("char uuid = 0x%04x \r\n",attm_convert_to16((uint8_t *)ind->info[val_idx].att.uuid,ind->info[val_idx].att.uuid_len)); + for(int i = 0; i < ind->info[val_idx].att.uuid_len; i++) + { + printf("%02x",ind->info[val_idx].att.uuid[i]); + } + printf("\r\n"); + printf("char_hdl = 0x%x,val_hdl = 0x%x,val_prop = 0x%x,svc_char = 0x%x ,val_idx = 0x%x\r\n",char_hdl,val_hdl,val_prop,svc_char,val_idx); + //Save properties and handles + chars[svc_char_cnt].uuid = attm_convert_to16((uint8_t *)ind->info[val_idx].att.uuid,ind->info[val_idx].att.uuid_len); + chars[svc_char_cnt].char_hdl = char_hdl; + chars[svc_char_cnt].val_hdl = val_hdl; + chars[svc_char_cnt].prop = val_prop; + svc_char_cnt++; + env[0].cnx_env->sdp.chars_nb = svc_char_cnt; + // find end of characteristic handle and discover descriptors + do + { + fnd_att++; + // found a descriptor + if(ind->info[fnd_att].att_type == GATTC_SDP_ATT_DESC) + { + //Retrieve characteristic descriptor handle using UUID + for(svc_desc = 0; svc_descend_hdl - ind->start_hdl; svc_desc++) + { + // check if it's expected descriptor + if ( svc_desc == svc_char) + { + printf("svc_desc = 0x%x,desc uuid = 0x%02x ",svc_desc,attm_convert_to16((uint8_t*)ind->info[fnd_att].att.uuid,ind->info[fnd_att].att.uuid_len)); + descs[svc_desc_cnt].uuid = attm_convert_to16((uint8_t*)&(ind->info[fnd_att].att.uuid[0]),ind->info[fnd_att].att.uuid_len); + descs[svc_desc_cnt].desc_hdl = ind->start_hdl + 1 + fnd_att; + descs[svc_desc_cnt].char_code = svc_char_cnt - 1; + printf("desc_hdl = 0x%x desc_char_code = 0x%x,val_idx = 0x%x\r\n",ind->start_hdl + 1 + fnd_att,svc_char_cnt - 1,val_idx); + // search for next descriptor + svc_desc_cnt++; + env[0].cnx_env->sdp.descs_nb++; + //break; + } + } + } + } while(((ind->start_hdl+ 1 + fnd_att) <= ind->end_hdl) + && (ind->info[fnd_att].att_type != GATTC_SDP_ATT_CHAR) + && (ind->info[fnd_att].att_type != GATTC_SDP_INC_SVC)); + // return to previous valid value + fnd_att--; + // previous handle was end of the characteristic + chars[svc_char_cnt].char_ehdl_off = fnd_att - char_idx; + // search next characteristic + break; + } + } + } + } + + printf("%s end\r\n",__func__); + sdp_add_profiles(adp_serv_env[sdp_env_idx].db_env); + } +} + +void sdp_add_profiles(struct sdp_db_env *db_env) +{ + printf("%s \r\n",__func__); + // return; + struct sdp_db_env *env; + struct gapm_profile_task_add_cmd *req = KERNEL_MSG_ALLOC_DYN(GAPM_PROFILE_TASK_ADD_CMD, + TASK_GAPM, TASK_APP, + gapm_profile_task_add_cmd, sizeof(struct sdp_db_env)); + // Fill message + req->operation = GAPM_PROFILE_TASK_ADD; + req->sec_lvl = 0;//PERM(SVC_AUTH, ENABLE); + req->prf_task_id = TASK_ID_SDP + prf_nb++; + req->app_task = TASK_APP; + req->start_hdl = 0; + env = (struct sdp_db_env *)req->param ; + env->cnx_env = db_env->cnx_env; + env->prf_nb = db_env->prf_nb; + printf("env->cnx_env->sdp.chars_nb = %d\r\n",env->cnx_env->sdp.chars_nb); + kernel_msg_send(req); +} + +void sdp_enable_rsp_send(struct sdp_env_tag *sdp_env, uint8_t conidx, uint8_t status) +{ + // Send APP the details of the discovered attributes on + struct sdp_enable_rsp * rsp = KERNEL_MSG_ALLOC(SDP_ENABLE_RSP, + prf_dst_task_get(&(sdp_env->prf_env) ,conidx), + prf_src_task_get(&(sdp_env->prf_env) ,conidx), + sdp_enable_rsp); + rsp->status = status; + kernel_msg_send(rsp); +} + +#endif /* (BLE_CLIENT) */ +/// @} SDP diff --git a/beken_os/beken378/driver/ble/ble_pub/ip/ble/profiles/sdp/src/sdp_service_task.c b/beken_os/beken378/driver/ble/ble_pub/ip/ble/profiles/sdp/src/sdp_service_task.c new file mode 100755 index 0000000..b5a334f --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/ip/ble/profiles/sdp/src/sdp_service_task.c @@ -0,0 +1,352 @@ +/** + **************************************************************************************** + * + * @file sdp_service_task.c + * + * @brief SDP Service Client Task implementation. + * + * Copyright (C) Beken 2016-2017 + * + * + **************************************************************************************** + */ +/** + **************************************************************************************** + * @addtogroup SDPTASK + * @{ + **************************************************************************************** + */ +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_config.h" +#if (BLE_SDP_CLIENT) +#include "gap.h" +#include "attm.h" +#include "sdp_service.h" +#include "sdp_service_task.h" +#include "gattc_task.h" +#include "common_math.h" +#include "uart.h" +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ +/* + * GLOBAL FUNCTIONS DEFINITIONS + **************************************************************************************** + */ +/** + **************************************************************************************** + * @brief Handles reception of the @ref BASC_ENABLE_REQ message. + * The handler enables the NTF Service Client Role. + * @param[in] msgid Id of the message received (probably unused). + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (probably unused). + * @param[in] src_id ID of the sending task instance. + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int sdp_enable_req_handler(kernel_msg_id_t const msgid, + struct sdp_enable_req const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + // Status + int msg_status = KERNEL_MSG_CONSUMED; + return (msg_status); +} +/** + **************************************************************************************** + * @brief Handles reception of the @ref SDP_READ_INFO_REQ message. + * @param[in] msgid Id of the message received (probably unused). + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (probably unused). + * @param[in] src_id ID of the sending task instance. + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int sdp_read_info_req_handler(kernel_msg_id_t const msgid, + struct sdp_read_info_req const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + printf("%s\r\n",__func__); + + int msg_status = KERNEL_MSG_CONSUMED; + uint8_t conidx = KERNEL_IDX_GET(dest_id); + uint8_t char_idx; + uint16_t handle; + int i; + uint8_t desc_nb; + struct sdp_env_tag *sdp_env =(struct sdp_env_tag *) prf_env_get_from_uuid(param->uuid,0); + if(sdp_env != NULL) + { + char_idx = sdp_env->db_env[conidx].cnx_env->sdp.char_idx; + desc_nb = sdp_env->db_env[conidx].cnx_env->sdp.descs_nb; + handle = sdp_env->db_env[conidx].cnx_env->sdp.chars[char_idx].val_hdl; + uint16_t val_prop = sdp_env->db_env[conidx].cnx_env->sdp.chars[char_idx].prop; + printf("desc_nb = 0x%x,char_idx = 0x%x,value_handle = 0x%x\r\n",desc_nb,char_idx,handle); + if(SDPC_CHAR_NTF_CFG == param->info) + { + for(i = 0; i < desc_nb; i++) + { + if((ATT_DESC_CLIENT_CHAR_CFG == sdp_env->db_env[conidx].cnx_env->sdp.descs[i].uuid) + && (sdp_env->db_env[conidx].cnx_env->sdp.descs[i].char_code == char_idx)) + { + handle = sdp_env->db_env[conidx].cnx_env->sdp.descs[i].desc_hdl; + val_prop |= ATT_CHAR_PROP_RD; + break; + } + } + } + else if(SDPC_CHAR_USER_DESC_VAL == param->info) + { + for(i = 0; i < desc_nb; i++) + { + if((ATT_DESC_CHAR_USER_DESCRIPTION == sdp_env->db_env[conidx].cnx_env->sdp.descs[i].uuid) + && (sdp_env->db_env[conidx].cnx_env->sdp.descs[i].char_code == char_idx)) + { + handle = sdp_env->db_env[conidx].cnx_env->sdp.descs[i].desc_hdl; + val_prop |= ATT_CHAR_PROP_RD; + break; + } + } + } + printf("prop = 0x%x,char_idx = 0x%x\r\n",val_prop,char_idx); + printf("handle = 0x%x\r\n",handle); + if((val_prop & ATT_CHAR_PROP_RD) == ATT_CHAR_PROP_RD ) + { + printf("prf_read_char_send \r\n"); + prf_read_char_send(&(sdp_env->prf_env), conidx,handle, handle, handle); + } + else + { + printf("val_prop not read prop!!!! \r\n"); + } + } + else + { + printf("param unvalid uuid = 0x%02x\r\n",param->uuid); + } + + return (msg_status); +} + +/** + **************************************************************************************** + * @brief Handles reception of the @ref BASC_BATT_LEVEL_NTF_CFG_REQ message. + * It allows configuration of the peer ntf/stop characteristic for Battery Level Characteristic. + * Will return an error code if that cfg char does not exist. + * @param[in] msgid Id of the message received (probably unused). + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (probably unused). + * @param[in] src_id ID of the sending task instance. + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int sdp_write_value_info_req_handler(kernel_msg_id_t const msgid, + struct sdp_write_info_req const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) + +{ + int msg_status = KERNEL_MSG_CONSUMED; + + uint8_t conidx = KERNEL_IDX_GET(dest_id); + uint8_t char_idx; + struct sdp_env_tag *sdp_env =(struct sdp_env_tag *) prf_env_get_from_uuid(param->uuid,0); + if(sdp_env != NULL) + { + char_idx = sdp_env->db_env[conidx].cnx_env->sdp.char_idx; + uint16_t handle = sdp_env->db_env[conidx].cnx_env->sdp.chars[char_idx].val_hdl; + uint16_t length = param->length; + uint16_t val_prop = sdp_env->db_env[conidx].cnx_env->sdp.chars[char_idx].prop; + uint8_t *buf = (uint8_t *)(¶m->data[0]); + uint8_t operation = GATTC_WRITE_NO_RESPONSE; + if((val_prop & ATT_CHAR_PROP_WR) == ATT_CHAR_PROP_WR) + { + operation = GATTC_WRITE; + printf("operation = %x\r\n",operation); + } + prf_gatt_write(&(sdp_env->prf_env), conidx,handle, buf,length,operation,0); + } + else + { + printf("param unvalid uuid = 0x%02x\r\n",param->uuid); + } + return (msg_status); +} + +/** + **************************************************************************************** + * @brief Handles reception of the @ref BASC_BATT_LEVEL_NTF_CFG_REQ message. + * It allows configuration of the peer ntf/stop characteristic for Battery Level Characteristic. + * Will return an error code if that cfg char does not exist. + * @param[in] msgid Id of the message received (probably unused). + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (probably unused). + * @param[in] src_id ID of the sending task instance. + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int sdp_write_ntf_cfg_req_handler(kernel_msg_id_t const msgid, + struct sdp_w_ntf_cfg_req const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + printf("%s\r\n",__func__); + + int msg_status = KERNEL_MSG_CONSUMED; + uint8_t conidx = KERNEL_IDX_GET(dest_id); + uint8_t char_idx; + // put value in air format + printf("param->uuid = %x\r\n",param->uuid); + struct sdp_env_tag *sdp_env =(struct sdp_env_tag *) prf_env_get_from_uuid(param->uuid,param->char_num); + if(sdp_env != NULL) + { + char_idx = sdp_env->db_env[conidx].cnx_env->sdp.char_idx; + uint16_t handle = sdp_env->db_env[conidx].cnx_env->sdp.chars[char_idx].val_hdl; + printf("handle = 0x%x\r\n",handle + 1); + prf_gatt_write_ntf_ind(&(sdp_env->prf_env), conidx, handle + 1, param->ntf_cfg, 0xa5); + } + else + { + printf("param unvalid uuid = 0x%02x\r\n",param->uuid); + } + return (msg_status); +} + +/** + **************************************************************************************** + * @brief Handles reception of the @ref GATTC_CMP_EVT message. + * This generic event is received for different requests, so need to keep track. + * @param[in] msgid Id of the message received (probably unused). + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (probably unused). + * @param[in] src_id ID of the sending task instance. + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int gattc_cmp_evt_handler(kernel_msg_id_t const msgid, + struct gattc_cmp_evt const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + printf("sdp %s dest_id = %x\r\n",__func__,dest_id); + printf("operation = 0x%x,status = 0x%x,seq_num = 0x%x\r\n",param->operation,param->status,param->seq_num); + struct gattc_cmp_evt *cmp_evt = KERNEL_MSG_ALLOC(GATTC_CMP_EVT, TASK_APP, dest_id, gattc_cmp_evt); + cmp_evt->operation = param->operation; + cmp_evt->status = param->status; + cmp_evt->seq_num = param->seq_num ; + + kernel_msg_send(cmp_evt); + + return (KERNEL_MSG_CONSUMED); +} + +/** + **************************************************************************************** + * @brief Handles reception of the @ref GATTC_READ_IND message. + * Generic event received after every simple read command sent to peer server. + * @param[in] msgid Id of the message received (probably unused). + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (probably unused). + * @param[in] src_id ID of the sending task instance. + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int gattc_read_ind_handler(kernel_msg_id_t const msgid, + struct gattc_read_ind const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + int i; + + printf("%s \r\n",__func__); + printf("handle = 0x%x\r\n",param->handle); + printf("length = 0x%x\r\n",param->length); + printf("offset = 0x%x\r\n",param->offset); + printf("value = 0x"); + + for(i =0 ; i < param->length; i++) + { + printf("%x ",param->value[i]); + } + printf("\r\n"); + + return (KERNEL_MSG_CONSUMED); +} + + + +//˽յ豸NotifyĻص +/** + **************************************************************************************** + * @brief Handles reception of the @ref GATTC_EVENT_IND message. + * @param[in] msgid Id of the message received (probably unused). + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (probably unused). + * @param[in] src_id ID of the sending task instance. + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int gattc_event_ind_handler(kernel_msg_id_t const msgid, + struct gattc_event_ind const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + int i; + +#if 1 + printf("RECEIVE Value = \r\n"); + for(i = 0; i< param->length; i++) + { + printf("%02x ",param->value[i]); + } + printf("\r\n"); +#endif + return (KERNEL_MSG_CONSUMED); +} + +//˽յ豸IndicationĻص +static int gattc_event_req_ind_handler(kernel_msg_id_t const msgid, + struct gattc_event_ind const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ +#if 1 + printf("RECIVE value = \r\n"); + for(int i = 0; i< param->length; i++) + { + printf("%02x ",param->value[i]); + } + printf("\r\n"); +#endif + struct gattc_event_cfm *cfm = KERNEL_MSG_ALLOC(GATTC_EVENT_CFM, src_id, dest_id, gattc_event_cfm); + cfm->handle = param->handle; + kernel_msg_send(cfm); + + return (KERNEL_MSG_CONSUMED); +} +/* + * GLOBAL VARIABLE DEFINITIONS + **************************************************************************************** + */ +/// Default State handlers definition +const struct kernel_msg_handler sdp_default_state[] = +{ + {SDP_ENABLE_REQ, (kernel_msg_func_t)sdp_enable_req_handler}, + {SDP_READ_INFO_REQ, (kernel_msg_func_t)sdp_read_info_req_handler}, + {SDP_WRITE_VALUE_INFO_REQ, (kernel_msg_func_t)sdp_write_value_info_req_handler}, + {SDP_WRITE_NTF_CFG_REQ, (kernel_msg_func_t)sdp_write_ntf_cfg_req_handler}, + {GATTC_READ_IND, (kernel_msg_func_t)gattc_read_ind_handler}, + {GATTC_EVENT_IND, (kernel_msg_func_t)gattc_event_ind_handler}, + {GATTC_EVENT_REQ_IND, (kernel_msg_func_t)gattc_event_req_ind_handler}, + {GATTC_CMP_EVT, (kernel_msg_func_t)gattc_cmp_evt_handler}, +}; +// Specifies the message handlers that are common to all states. +const struct kernel_state_handler sdp_default_handler = KERNEL_STATE_HANDLER(sdp_default_state); +#endif /* (BLE_BATT_CLIENT) */ +/// @} BASCTASK diff --git a/beken_os/beken378/driver/ble/ble_pub/modules/app/api/app_comm.h b/beken_os/beken378/driver/ble/ble_pub/modules/app/api/app_comm.h new file mode 100755 index 0000000..e0ddf9f --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/modules/app/api/app_comm.h @@ -0,0 +1,17 @@ +#ifndef APP_COMM_H_ +#define APP_COMM_H_ + +#include "rwip_config.h" // SW configuration + +#if (BLE_APP_COMM) +#include // Standard Integer Definition +#include "ble.h" +#include "ble_pub.h" +#include "ble_api.h" +#include "kernel_task.h" // Kernel Task Definition + +extern const struct kernel_state_handler app_comm_table_handler; + +#endif + +#endif diff --git a/beken_os/beken378/driver/ble/ble_pub/modules/app/api/app_sdp.h b/beken_os/beken378/driver/ble/ble_pub/modules/app/api/app_sdp.h new file mode 100755 index 0000000..e007c69 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/modules/app/api/app_sdp.h @@ -0,0 +1,57 @@ +/** + **************************************************************************************** + * + * @file app_sdp.h + * + * @brief Application entry point + * + * Copyright (C) Beken 2009-2016 + * + * + **************************************************************************************** + */ +#ifndef APP_SDP_H_ +#define APP_SDP_H_ + + +#include "rwip_config.h" // SW configuration +#if (BLE_APP_SDP) +#include // Standard Integer Definition +#include // Common BT Definitions +#include "arch.h" // Platform Definitions +#include "gap.h" +#include "gapc.h" // GAPC Definitions +#include "gattc_task.h" +#include +#include "kernel_task.h" +#include "common_error.h" +#include "attm.h" +#include "gattc_task.h" +#include "prf_utils.h" +#include "kernel_mem.h" +#include "sdp_service.h" +#include "ble.h" +#include "ble_pub.h" +#include "ble_api.h" + + + +void appm_set_max_scan_nums(uint8_t max); +uint8_t appm_get_max_scan_nums(void); +uint8_t appm_start_scanning(void); +uint8_t appm_stop_scanning(void); +uint8_t appm_start_connenct_by_addr(uint8_t* bdaddr); +uint8_t appm_start_connenct_by_id(uint8_t id); +uint8_t appm_stop_connencting(void); +uint8_t appm_disconnect_link(void); +uint8_t appm_adv_data_decode(uint8_t len,const uint8_t *data,uint8_t *find_str,uint8_t str_len); +uint8_t appm_write_data_by_uuid(uint16_t uuid,uint8_t len,uint8_t *data); +uint8_t appm_write_ntf_cfg(uint16_t uuid,uint16_t number,uint16_t cfg); +uint8_t appm_read_data_by_uuid(uint16_t uuid); +uint8_t appm_read_cfg_by_uuid(uint16_t uuid); +uint8_t appm_read_user_desc_by_uuid(uint16_t uuid); +uint8_t sdp_enable_all_server_ntf_ind(uint8_t reset); +void sdp_prf_register_all_atthdl2gatt(void); + +#endif +#endif diff --git a/beken_os/beken378/driver/ble/ble_pub/modules/app/api/app_sec.h b/beken_os/beken378/driver/ble/ble_pub/modules/app/api/app_sec.h new file mode 100755 index 0000000..0ce1035 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/modules/app/api/app_sec.h @@ -0,0 +1,101 @@ +/** + **************************************************************************************** + * + * @file app_sec.h + * + * @brief Application Security Entry Point + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @addtogroup APP_SEC + * @{ + **************************************************************************************** + */ + +#ifndef APP_SEC_H_ +#define APP_SEC_H_ + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" + +#if (BLE_APP_SEC) + +#include // Standard Integer Definition + +/* + * DEFINES + **************************************************************************************** + */ + +/* + * STRUCTURES DEFINITIONS + **************************************************************************************** + */ + +struct app_sec_env_tag +{ + // Bond status + bool bonded; + bool peer_pairing_recv; + bool peer_encrypt_recv; +}; + +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ + +/// Application Security Environment +extern struct app_sec_env_tag app_sec_env; + +/// Table of message handlers +extern const struct kernel_state_handler app_sec_table_handler; + +/* + * GLOBAL FUNCTIONS DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Initialize the Application Security Module + **************************************************************************************** + */ +void app_sec_init(void); + + +#if (NVDS_SUPPORT) +/** + **************************************************************************************** + * @brief Remove all bond data stored in NVDS + **************************************************************************************** + */ +void app_sec_remove_bond(void); +#endif //(NVDS_SUPPORT) + +/** + **************************************************************************************** + * @brief Send a security request to the peer device. This function is used to require the + * central to start the encryption with a LTK that would have shared during a previous + * bond procedure. + * + * @param[in] - conidx: Connection Index + **************************************************************************************** + */ +void app_sec_send_security_req(uint8_t conidx); + +#endif //(BLE_APP_SEC) + +#endif // APP_SEC_H_ + +/// @} APP_SEC diff --git a/beken_os/beken378/driver/ble/ble_pub/modules/app/api/app_task.h b/beken_os/beken378/driver/ble/ble_pub/modules/app/api/app_task.h new file mode 100755 index 0000000..f3c8af2 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/modules/app/api/app_task.h @@ -0,0 +1,165 @@ +/** + **************************************************************************************** + * + * @file app_task.h + * + * @brief Header file - APPTASK. + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef APP_TASK_H_ +#define APP_TASK_H_ + +/** + **************************************************************************************** + * @addtogroup APPTASK Task + * @ingroup APP + * @brief Routes ALL messages to/from APP block. + * + * The APPTASK is the block responsible for bridging the final application with the + * RWBLE software host stack. It communicates with the different modules of the BLE host, + * i.e. @ref SMP, @ref GAP and @ref GATT. + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" // SW configuration + +#if (BLE_APP_PRESENT) + +#include // Standard Integer +#include "rwip.h" +#include "rwip_task.h" // Task definitions +#include "kernel_task.h" // Kernel Task +#include "common_bt.h" + + +/* + * DEFINES + **************************************************************************************** + */ + +/// Number of APP Task Instances +#define APP_IDX_MAX (1) +#define MAX_SCAN_NUM (15) + +/* + * ENUMERATIONS + **************************************************************************************** + */ + +/// States of APP task +enum appm_state +{ + /// Initialization state + APPM_INIT, + /// Database create state + APPM_CREATE_DB, + /// Ready State + APPM_READY, + /// Advertising state + APPM_ADVERTISING, + /// Scan state + APPM_SCANNING, + + APPM_WAIT_SCANNEND, + /// Connecting state + APPM_CONNECTING, + /// Link Connected state + APPM_LINK_CONNECTED, + + APPM_SDP_DISCOVERING, + + APPM_CONNECTED,//Prf Connected + + APPM_DISCONNECT, + + /// Number of defined states. + APPM_STATE_MAX +}; + + +/// APP Task messages +enum appm_msg +{ + APPM_DUMMY_MSG = TASK_FIRST_MSG(TASK_ID_APP), + + /// Timer used to automatically stop advertising + APP_ADV_TIMEOUT_TIMER, + + #if (BLE_APP_HT) + /// Timer used to refresh the temperature measurement value + APP_HT_MEAS_INTV_TIMER, + #endif //(BLE_APP_HT) + + #if (BLE_APP_HID) + /// Timer used to disconnect the moue if no activity is detecter + APP_HID_MOUSE_TIMEOUT_TIMER, + #endif //(BLE_APP_HID) + + APP_SEND_SECURITY_REQ, + + APP_GATTC_EXC_MTU_CMD, + + APP_PARAM_UPDATE_REQ_IND, + + APP_PERIOD_TIMER, + + APP_ENCODE_IND, + + APP_ADV_ENABLE_TIMER, + + APP_DISCONNECT_TIMER, + + APP_PERIOD_TEST_TIMER, //data test +}; + + +struct sbc_encode +{ + uint32_t len; + int16_t buf[__ARRAY_EMPTY]; +}; + + +typedef struct +{ + uint8_t number; + uint8_t addr_type; + uint8_t rssi; + uint8_t adv_type; + struct bd_addr adv_addr; +}device_info_t; + +typedef struct +{ + device_info_t info[MAX_SCAN_NUM]; +}ble_scan_list_t; + +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ + +extern const struct kernel_state_handler appm_default_handler; +extern kernel_state_t appm_state[APP_IDX_MAX]; + +extern uint8_t send_buf[20]; +extern uint8_t adv_count; +extern ble_scan_list_t ble_scan_list; + +/// @} APPTASK + +#endif //(BLE_APP_PRESENT) + +#endif // APP_TASK_H_ diff --git a/beken_os/beken378/driver/ble/ble_pub/modules/app/api/application.h b/beken_os/beken378/driver/ble/ble_pub/modules/app/api/application.h new file mode 100755 index 0000000..7d1d628 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/modules/app/api/application.h @@ -0,0 +1,333 @@ +/** + **************************************************************************************** + * + * @file application.h + * + * @brief Application entry point + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef APPLICATION_H_ +#define APPLICATION_H_ + +/** + **************************************************************************************** + * @addtogroup APP + * @ingroup RICOW + * + * @brief Application entry point. + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" // SW configuration + +#if (BLE_APP_PRESENT) + +#include // Standard Integer Definition +#include "common_bt.h" // Common BT Definitions +#include "architect.h" // Platform Definitions +#include "gapc.h" // GAPC Definitions + +#if (NVDS_SUPPORT) +#include "nvds.h" +#endif // (NVDS_SUPPORT) + +#include "ble.h" +#include "ble_pub.h" +#include "ble_api.h" + +/* + * DEFINES + **************************************************************************************** + */ +/// Maximal length of the Device Name value +#define APP_DEVICE_NAME_MAX_LEN (18) + +#define TOTAL_BLOCK_NUM (80) + +/// Default Advertising duration - 30s (in multiple of 10ms) +#define APP_DFLT_ADV_DURATION (3000) + + + +#define BASE3 0x00003C60 +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + +#if (NVDS_SUPPORT) +/// List of Application NVDS TAG identifiers +enum app_nvds_tag +{ + /// BLE Application Advertising data + NVDS_TAG_APP_BLE_ADV_DATA = 0x0B, + NVDS_LEN_APP_BLE_ADV_DATA = 32, + + /// BLE Application Scan response data + NVDS_TAG_APP_BLE_SCAN_RESP_DATA = 0x0C, + NVDS_LEN_APP_BLE_SCAN_RESP_DATA = 32, + + /// Mouse Sample Rate + NVDS_TAG_MOUSE_SAMPLE_RATE = 0x38, + NVDS_LEN_MOUSE_SAMPLE_RATE = 1, + /// Peripheral Bonded + NVDS_TAG_PERIPH_BONDED = 0x39, + NVDS_LEN_PERIPH_BONDED = 1, + /// Mouse NTF Cfg + NVDS_TAG_MOUSE_NTF_CFG = 0x3A, + NVDS_LEN_MOUSE_NTF_CFG = 2, + /// Mouse Timeout value + NVDS_TAG_MOUSE_TIMEOUT = 0x3B, + NVDS_LEN_MOUSE_TIMEOUT = 2, + /// Peer Device BD Address + NVDS_TAG_PEER_BD_ADDRESS = 0x3C, + NVDS_LEN_PEER_BD_ADDRESS = 7, + /// Mouse Energy Safe + NVDS_TAG_MOUSE_ENERGY_SAFE = 0x3D, + NVDS_LEN_MOUSE_SAFE_ENERGY = 2, + /// EDIV (2bytes), RAND NB (8bytes), LTK (16 bytes), Key Size (1 byte) + NVDS_TAG_LTK = 0x3E, + NVDS_LEN_LTK = 28, + /// PAIRING + NVDS_TAG_PAIRING = 0x3F, + NVDS_LEN_PAIRING = 54, +}; + +enum app_loc_nvds_tag +{ + /// Audio mode 0 task + NVDS_TAG_AM0_FIRST = NVDS_TAG_APP_SPECIFIC_FIRST, // 0x90 + NVDS_TAG_AM0_LAST = NVDS_TAG_APP_SPECIFIC_FIRST+16, // 0xa0 + + /// Local device Identity resolving key + NVDS_TAG_LOC_IRK, + /// Peer device Resolving identity key (+identity address) + NVDS_TAG_PEER_IRK, + + /// size of local identity resolving key + NVDS_LEN_LOC_IRK = KEY_LEN, + /// size of Peer device identity resolving key (+identity address) + NVDS_LEN_PEER_IRK = sizeof(struct gapc_irk), +}; +#endif // (NVDS_SUPPORT) + +/// Application environment structure +struct app_env_tag +{ + /// Connection handle + uint16_t conhdl; + /// Connection Index + uint8_t conidx; + + /// Last initialized profile + uint8_t next_svc; + + /// Bonding status + bool bonded; + + /// Device Name length + uint8_t dev_name_len; + /// Device Name + uint8_t dev_name[APP_DEVICE_NAME_MAX_LEN]; + + /// Local device IRK + uint8_t loc_irk[KEY_LEN]; + + /// Peer device IRK + struct gapc_irk peer_irk; + +}; + +//This struct use to remote ctrl device. +typedef enum +{ + CONN_MODE_LONG, + CONN_MODE_SHORT, + CONN_MODE_ERROR, +}remote_conn_mode; + + +typedef struct +{ + remote_conn_mode target_mode; + uint32_t target_timeout; +}remote_ctrl_struct; + + +/* + * GLOBAL VARIABLE DECLARATION + **************************************************************************************** + */ + +/// Application environment +extern struct app_env_tag app_env; + +//Voice buffer +extern uint8_t encode_voice_data[TOTAL_BLOCK_NUM][20]; + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Initialize the BLE demo application. + **************************************************************************************** + */ +void appm_init(void); + +/** + **************************************************************************************** + * @brief Add a required service in the database + **************************************************************************************** + */ +bool appm_add_svc(void); + +/** + **************************************************************************************** + * @brief Put the device in general discoverable and connectable mode + **************************************************************************************** + */ +ble_err_t appm_start_advertising(void); +/** + **************************************************************************************** + * @brief Put the device in general discoverable and connectable mode + **************************************************************************************** + */ +void appm_start_direct_dvertising(void); + +/** + **************************************************************************************** + * @brief Put the device in non discoverable and non connectable mode + **************************************************************************************** + */ +ble_err_t appm_stop_advertising(void); + +/** + **************************************************************************************** + * @brief Send to request to update the connection parameters + **************************************************************************************** + */ +void appm_update_param(struct gapc_conn_param *conn_param); + +/** + **************************************************************************************** + * @brief Send a disconnection request + **************************************************************************************** + */ +void appm_disconnect(uint8_t reason); + + +/** + **************************************************************************************** + * @brief appm_switch_general_adv + **************************************************************************************** + */ +void appm_switch_general_adv(void); + +/** + **************************************************************************************** + * @brief Retrieve device name + * + * @param[out] device name + * + * @return name length + **************************************************************************************** + */ +uint8_t appm_get_dev_name(uint8_t* name); + + +/** + **************************************************************************************** + * @brief Return if the device is currently bonded + **************************************************************************************** + */ +bool app_sec_get_bond_status(void); + + +/** + **************************************************************************************** + * @brief Send to request to security + **************************************************************************************** + */ +void appm_send_seurity_req(void); + + +/** + **************************************************************************************** + * @brief app_send_encode_evt + **************************************************************************************** + */ +void app_send_encode_evt(void); + +/** + **************************************************************************************** + * @brief read_encode_data + **************************************************************************************** + */ +uint8_t read_encode_data(uint8_t *buf); + +/** + **************************************************************************************** + * @brief store_encode_data + **************************************************************************************** + */ +uint8_t store_encode_data(uint8_t *buf); + +/** + **************************************************************************************** + * @brief encode_voice_init + **************************************************************************************** + */ +void encode_voice_init(void); + +/** + **************************************************************************************** + * @brief print_debug_info + **************************************************************************************** + */ +void print_debug_info(void); + + +/** + **************************************************************************************** + * @brief print_debug_status + **************************************************************************************** + */ +void print_debug_status(void); + + +/** + **************************************************************************************** + * @brief app_set_mode + **************************************************************************************** + */ +void app_set_mode(remote_conn_mode mode, uint32_t timeout); + + +/** + **************************************************************************************** + * @brief app_get_mode + **************************************************************************************** + */ +remote_ctrl_struct app_get_mode(void); + + +/// @} APP + +#endif //(BLE_APP_PRESENT) + +#endif // APP_H_ diff --git a/beken_os/beken378/driver/ble/ble_pub/modules/app/api/rwapp_config.h b/beken_os/beken378/driver/ble/ble_pub/modules/app/api/rwapp_config.h new file mode 100755 index 0000000..d015ef8 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/modules/app/api/rwapp_config.h @@ -0,0 +1,269 @@ +/** + **************************************************************************************** + * + * @file rwapp_config.h + * + * @brief Application configuration definition + * + * Copyright (C) RivieraWaves 2009-2016 + * + **************************************************************************************** + */ + + +#ifndef _RWAPP_CONFIG_H_ +#define _RWAPP_CONFIG_H_ + +/** + **************************************************************************************** + * @addtogroup app + * @brief Application configuration definition + * + * @{ + **************************************************************************************** + */ + +#include "rwip_config.h" +/* + * INCLUDE FILES + **************************************************************************************** + */ + +/* + * DEFINES + **************************************************************************************** + */ + +/******************************************************************************************/ +/* ------------------------- BLE APPLICATION SETTINGS -----------------------------*/ +/* ------------------------- don't change format -------------------------------*/ +/******************************************************************************************/ + +// <<< Use Configuration Wizard in Context Menu >>> + +// BLE APPLICATION SETTINGS + + +// BLE_APP_OADS +// BLE_APP_OADS enable /disable +// +#if ( 0 ) +#define CFG_APP_OADS +#endif + +// BLE_APP_FFF0 +// BLE_APP_FFF0 enable /disable +// +#if ( 0 ) +#define CFG_APP_FFF0 +#endif + + +// BLE_APP_FFE0 +// BLE_APP_FFE0 enable /disable +// +#if ( 0 ) +#define CFG_APP_FFE0 +#endif + +// BLE_APP_COMM +// BLE_APP_COMM enable /disable +// +#if ( 1 ) +#define CFG_APP_COMM +#endif + +// BLE_APP_SDP +// BLE_APP_SDP enable /disable +// +#if ( 1 ) +#define CFG_APP_SDP +#endif + +/// HID Application +// BLE_APP_HID +// BLE_APP_HID enable /disable +// +#if ( 0 ) +#define CFG_APP_HID +#endif + + + +// BLE_APP_PXPR +// BLE_APP_PXPR enable /disable +// +#if ( 0 ) +#define CFG_APP_PXPR +#endif + +// BLE_APP_ANCSC +// BLE_APP_ANCS enable /disable +// +#if ( 0 ) +#define CFG_APP_ANCSC +#endif + + +// BLE_APP_SEC +// BLE_APP_SEC enable /disable +// +#if ( 0 ) +#define CFG_APP_SEC +#endif + +// BLE_APP_FINDT +// BLE_APP_FINDT enable /disable +// +#if ( 0 ) +#define CFG_APP_FINDT +#endif + + +// BLE_APP_DIS +// BLE_APP_DIS enable /disable +// +#if ( 0 ) +#define CFG_APP_DIS +#endif + +// CFG_APP_BATT +// CFG_APP_BATT enable /disable +// +#if ( 0 ) +#define CFG_APP_BATT +#endif + +/// OAD Service Application +#if defined(CFG_APP_OADS) +#define BLE_APP_OADS 1 +#else +#define BLE_APP_OADS 0 +#endif // (BLE_APP_FFF0) + + +/// FFF0 Service Application +#if defined(CFG_APP_FFF0) +#define BLE_APP_FFF0 1 +#else +#define BLE_APP_FFF0 0 +#endif // (BLE_APP_FFF0) + + +/// FFE0 Service Application +#if defined(CFG_APP_FFE0) +#define BLE_APP_FFE0 1 +#else +#define BLE_APP_FFE0 0 +#endif // (BLE_APP_FFF0) + +/// COMM Service Application +#if defined(CFG_APP_COMM) +#define BLE_APP_COMM 1 +#else +#define BLE_APP_COMM 0 +#endif // defined(BLE_APP_COMM) + +// SDP Client Application +#if defined(CFG_APP_SDP) +#define BLE_APP_SDP 1 +#else +#define BLE_APP_SDP 0 +#endif // (CFG_APP_SDP) + +/// Proximity Service Application +#if defined(CFG_APP_PXPR) +#define BLE_APP_PXPR 1 +#else +#define BLE_APP_PXPR 0 +#endif // (CFG_APP_PXPR) + +/// Find me Locator role Application +#if defined(CFG_APP_ANCSC) +#define BLE_APP_ANCSC 1 +#else // defined(CFG_APP_ANCSC) +#define BLE_APP_ANCSC 0 +#endif // defined(CFG_APP_ANCSC) + +/// Find me Target role Application +#if defined(CFG_APP_FINDT) +#define BLE_APP_FINDT 1 +#else // defined(CFG_APP_HT) +#define BLE_APP_FINDT 0 +#endif // defined(CFG_APP_HT) + + +/// Find me Locator role Application +#if defined(CFG_APP_FINDL) +#define BLE_APP_FINDL 1 +#else // defined(CFG_APP_HT) +#define BLE_APP_FINDL 0 +#endif // defined(CFG_APP_HT) + + +/// Heart Rate Profile Sensor Application +#if defined(CFG_APP_HRPS) +#define BLE_APP_HRPS 1 +#else // defined(CFG_APP_HRPS) +#define BLE_APP_HRPS 0 +#endif // defined(CFG_APP_HRPS) + +/// Health Thermometer Application +#if defined(CFG_APP_HT) +#define BLE_APP_HT 1 +#else // defined(CFG_APP_HT) +#define BLE_APP_HT 0 +#endif // defined(CFG_APP_HT) + +/// HID Application +#if defined(CFG_APP_HID) +#define BLE_APP_HID 1 +#else // defined(CFG_APP_HID) +#define BLE_APP_HID 0 +#endif // defined(CFG_APP_HID) + +/// DIS Application +#if (defined(CFG_APP_DIS) || BLE_APP_HRPS) +#define BLE_APP_DIS 1 + +#else // defined(CFG_APP_DIS) +#define BLE_APP_DIS 0 +#endif // defined(CFG_APP_DIS) + +/// Time Application +#if defined(CFG_APP_TIME) +#define BLE_APP_TIME 1 +#else // defined(CFG_APP_TIME) +#define BLE_APP_TIME 0 +#endif // defined(CFG_APP_TIME) + +/// Battery Service Application +//#if (defined(CFG_APP_HID) || defined(CFG_APP_BATT)) +#if defined(CFG_APP_BATT) +#define BLE_APP_BATT 1 +#else +#define BLE_APP_BATT 0 +#endif // (BLE_APP_HID) + +/// Security Application +#if (defined(CFG_APP_SEC) || BLE_APP_HID || defined(BLE_APP_AM0)) +#define BLE_APP_SEC 1 +#else // defined(CFG_APP_SEC) +#define BLE_APP_SEC 0 +#endif // defined(CFG_APP_SEC) + +#if (BLE_APP_FFE0 || BLE_APP_FFF0 || BLE_APP_COMM) +#define BLE_APP_SERVICE 1 +#else +#define BLE_APP_SERVICE 0 +#endif + +#if (BLE_APP_SDP) +#define BLE_APP_CLIENT 1 +#else +#define BLE_APP_CLIENT 0 +#endif + +/// @} rwapp_config + +#endif /* _RWAPP_CONFIG_H_ */ diff --git a/beken_os/beken378/driver/ble/ble_pub/modules/app/src/app_ble.c b/beken_os/beken378/driver/ble/ble_pub/modules/app/src/app_ble.c new file mode 100755 index 0000000..9d89039 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/modules/app/src/app_ble.c @@ -0,0 +1,774 @@ +/** + **************************************************************************************** + * + * @file app.c + * + * @brief Application entry point + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @addtogroup APP + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "include.h" + +#include "rwip_config.h" // SW configuration + +#if (BLE_APP_PRESENT) +#include +#include "rwapp_config.h" +#include "app_task.h" // Application task Definition +#include "application.h" // Application Definition +#include "gap.h" // GAP Definition +#include "gapm_task.h" // GAP Manager Task API +#include "gapc_task.h" // GAP Controller Task API + +#include "common_bt.h" // Common BT Definition +#include "common_math.h" // Common Maths Definition +#include "kernel_timer.h" + +#include "mem_pub.h" + +#if (BLE_APP_FFF0) +#include "app_fff0.h" // Application security Definition +#endif // (BLE_APP_FFF0) + +#if (BLE_APP_FFE0) +#include "app_ffe0.h" // Application security Definition +#endif // (BLE_APP_FFE0) + +#if (BLE_APP_ANCSC) +#include "app_ancsc.h" // Application fff0s Definition +#endif // (BLE_APP_ANCSC) + +#if (BLE_APP_SEC) +#include "app_sec.h" // Application security Definition +#endif // (BLE_APP_SEC) + +#if (BLE_APP_HT) +#include "app_ht.h" // Health Thermometer Application Definitions +#endif //(BLE_APP_HT) + + +#if (BLE_APP_DIS) +#include "app_dis.h" // Device Information Service Application Definitions +#endif //(BLE_APP_DIS) + +#if (BLE_APP_BATT) +#include "app_batt.h" // Battery Application Definitions +#endif //(BLE_APP_DIS) + +#if (BLE_APP_HID) +#include "app_hid.h" // HID Application Definitions +#endif //(BLE_APP_HID) + +#if (DISPLAY_SUPPORT) +#include "app_display.h" // Application Display Definition +#endif //(DISPLAY_SUPPORT) + +#if (BLE_APP_OADS) +#include "app_oads.h" // Application oads Definition +#endif // (BLE_APP_OADS) + +#ifdef BLE_APP_AM0 +#include "am0_application.h" // Audio Mode 0 Application +#endif //defined(BLE_APP_AM0) + +#if (NVDS_SUPPORT) +#include "nvds.h" // NVDS Definitions +#endif //(NVDS_SUPPORT) + +#include "ble.h" +#include "ble_pub.h" +#include "mcu_ps_pub.h" +#include "ble_api.h" +#include "gapm_task.h" +char app_dflt_dev_name[APP_DEVICE_NAME_LENGTH_MAX] = {0}; + + +#if (BLE_APP_HID) +// HID Mouse +#define DEVICE_NAME "Hid Mouse" +#else +#define DEVICE_NAME "RW DEVICE" +#endif + + + +#define DEVICE_NAME_SIZE sizeof(DEVICE_NAME) + + +/** + * UUID List part of ADV Data + * -------------------------------------------------------------------------------------- + * x03 - Length + * x03 - Complete list of 16-bit UUIDs available + * x09\x18 - Health Thermometer Service UUID + * or + * x12\x18 - HID Service UUID + * -------------------------------------------------------------------------------------- + */ + +#if (BLE_APP_FFF0) +#define APP_FFF0_ADV_DATA_UUID "\x03\x03\xF0\xFF" +#define APP_FFF0_ADV_DATA_UUID_LEN (4) +#endif //(BLE_APP_HT) + +#if (BLE_APP_FFE0) +#define APP_FFE0_ADV_DATA_UUID "\x03\x03\xE0\xFF" +#define APP_FFE0_ADV_DATA_UUID_LEN (4) +#endif //(BLE_APP_HT) + + +#if (BLE_APP_HT) +#define APP_HT_ADV_DATA_UUID "\x03\x03\x09\x18" +#define APP_HT_ADV_DATA_UUID_LEN (4) +#endif //(BLE_APP_HT) + +#if (BLE_APP_HID) +#define APP_HID_ADV_DATA_UUID "\x03\x03\x12\x18" +#define APP_HID_ADV_DATA_UUID_LEN (4) +#endif //(BLE_APP_HID) + +/** + * Appearance part of ADV Data + * -------------------------------------------------------------------------------------- + * x03 - Length + * x19 - Appearance + * x03\x00 - Generic Thermometer + * or + * xC2\x03 - HID Mouse + * xC1\x03 - HID Keyboard + * xC3\x03 - HID Joystick + * -------------------------------------------------------------------------------------- + */ + +#if (BLE_APP_HT) +#define APP_HT_ADV_DATA_APPEARANCE "\x03\x19\x00\x03" +#endif //(BLE_APP_HT) + +#if (BLE_APP_HID) +#define APP_HID_ADV_DATA_APPEARANCE "\x03\x19\xC1\x03" +#endif //(BLE_APP_HID) + + +#define APP_ADV_DATA_APPEARANCE_LEN (4) + +/** + * Default Scan response data + * -------------------------------------------------------------------------------------- + * x09 - Length + * xFF - Vendor specific advertising type + * x00\x60\x52\x57\x2D\x42\x4C\x45 - "RW-BLE" + * -------------------------------------------------------------------------------------- + */ +#define APP_SCNRSP_DATA "\x08\x08\x42\x4B\x2D\x33\x34\x33\x35" //BK-3435" +//#define APP_SCNRSP_DATA "\x03\x19\x00\x03" +#define APP_SCNRSP_DATA_LEN (9) + +#if (BLE_APP_HID) +#define APP_HID_SCNRSP_DATA "\x03\x03\x12\x18" +#define APP_HID_SCNRSP_DATA_LEN (4) +#endif //(BLE_APP_HID) + +/** + * Advertising Parameters + */ + +/// Advertising channel map - 37, 38, 39 +#define APP_ADV_CHMAP (0x07) +/// Advertising minimum interval - 100ms (160*0.625ms) +#define APP_ADV_INT_MIN (160) +/// Advertising maximum interval - 100ms (160*0.625ms) +#define APP_ADV_INT_MAX (160) +/// Fast advertising interval +#define APP_ADV_FAST_INT (32) + +#define MAX_ADV_DATA_LEN (0x1F) + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + +typedef void (*appm_add_svc_func_t)(void); + +/* + * ENUMERATIONS + **************************************************************************************** + */ + +/// List of service to add in the database +enum appm_svc_list +{ + #if (BLE_APP_FFF0) + APPM_SVC_FFF0, + #endif // (BLE_APP_FFF0) + #if (BLE_APP_FFE0) + APPM_SVC_FFE0, + #endif // (BLE_APP_FFE0) + #if (BLE_APP_ANCSC) + APPM_SVC_ANCSC, + #endif //(BLE_APP_ANCSC) + #if (BLE_APP_HT) + APPM_SVC_HTS, + #endif //(BLE_APP_HT) + #if (BLE_APP_DIS) + APPM_SVC_DIS, + #endif //(BLE_APP_DIS) + #if (BLE_APP_BATT) + APPM_SVC_BATT, + #endif //(BLE_APP_BATT) + #if (BLE_APP_HID) + APPM_SVC_HIDS, + #endif //(BLE_APP_HID) + #ifdef BLE_APP_AM0 + APPM_SVC_AM0_HAS, + #endif //defined(BLE_APP_AM0) + #if (BLE_APP_OADS) + APPM_SVC_OADS, + #endif //(BLE_APP_OADS) + + APPM_SVC_LIST_STOP , +}; + +/* + * LOCAL VARIABLES DEFINITIONS + **************************************************************************************** + */ + +/// Application Task Descriptor +static const struct kernel_task_desc TASK_DESC_APP = {NULL, &appm_default_handler, + appm_state, APPM_STATE_MAX, APP_IDX_MAX}; + +adv_info_t adv_info = { + .channel_map = 7, + .interval_min = APP_ADV_INT_MIN, + .interval_max = APP_ADV_INT_MAX +}; + +/// List of functions used to create the database +static const appm_add_svc_func_t appm_add_svc_func_list[APPM_SVC_LIST_STOP] = +{ + #if (BLE_APP_FFF0) + (appm_add_svc_func_t)app_fff0_add_fff0s, + #endif // (BLE_APP_FFF0) + #if (BLE_APP_FFE0) + (appm_add_svc_func_t)app_ffe0_add_ffe0s, + #endif // (BLE_APP_FFE0) + + #if (BLE_APP_ANCSC) + (appm_add_svc_func_t)app_ancs_add_ancsc, + #endif //(BLE_APP_ANCSC) + #if (BLE_APP_HT) + (appm_add_svc_func_t)app_ht_add_hts, + #endif //(BLE_APP_HT) + #if (BLE_APP_DIS) + (appm_add_svc_func_t)app_dis_add_dis, + #endif //(BLE_APP_DIS) + #if (BLE_APP_BATT) + (appm_add_svc_func_t)app_batt_add_bas, + #endif //(BLE_APP_BATT) + #if (BLE_APP_HID) + (appm_add_svc_func_t)app_hid_add_hids, + #endif //(BLE_APP_HID) + #ifdef BLE_APP_AM0 + (appm_add_svc_func_t)am0_app_add_has, + #endif //defined(BLE_APP_AM0) + #if (BLE_APP_OADS) + (appm_add_svc_func_t)app_oad_add_oads, + #endif //(BLE_APP_OADS) +}; + +/* + * GLOBAL VARIABLE DEFINITIONS + **************************************************************************************** + */ + +/// Application Environment Structure +struct app_env_tag app_env; +char *dev_str_name = NULL; +int *scan_check_result = NULL; + +/* + * FUNCTION DEFINITIONS + **************************************************************************************** + */ + +void appm_init() +{ + #if (NVDS_SUPPORT) + + uint8_t peer_irk_len = NVDS_LEN_PEER_IRK; + uint8_t key_len = KEY_LEN; + #endif //(NVDS_SUPPORT) + + // Reset the application manager environment + memset(&app_env, 0, sizeof(app_env)); + + // Create APP task + kernel_task_create(TASK_APP, &TASK_DESC_APP); + + // Initialize Task state + kernel_state_set(TASK_APP, APPM_INIT); +#if 0 + // Get the Device Name to add in the Advertising Data (Default one or NVDS one) + #if (NVDS_SUPPORT) + app_env.dev_name_len = APP_DEVICE_NAME_MAX_LEN; + + if (nvds_get(NVDS_TAG_DEVICE_NAME, &(app_env.dev_name_len), app_env.dev_name) != NVDS_OK) + #endif //(NVDS_SUPPORT) + { + // Get default Device Name (No name if not enough space) + memcpy(app_env.dev_name, APP_DFLT_DEVICE_NAME, APP_DFLT_DEVICE_NAME_LEN); + app_env.dev_name_len = APP_DFLT_DEVICE_NAME_LEN; + + // TODO update this value per profiles + } + + #if (NVDS_SUPPORT) + if (nvds_get(NVDS_TAG_LOC_IRK, &key_len, app_env.loc_irk) != NVDS_OK) + #endif //(NVDS_SUPPORT) + { + uint8_t counter; + + // generate a new IRK + for (counter = 0; counter < KEY_LEN; counter++) + { + app_env.loc_irk[counter] = (uint8_t)common_rand_word(); + } + + // Store it in NVDS + #if (NVDS_SUPPORT) + // Store the generated value in NVDS + if (nvds_put(NVDS_TAG_LOC_IRK, KEY_LEN, (uint8_t *)&app_env.loc_irk) != NVDS_OK) + { + ASSERT_INFO(0, NVDS_TAG_LOC_IRK, 0); + } + #endif // #if (NVDS_SUPPORT) + } + #if (NVDS_SUPPORT) + // Store peer identity in NVDS + if (nvds_get(NVDS_TAG_PEER_IRK, &peer_irk_len, (uint8_t *)&app_env.peer_irk.irk.key) != NVDS_OK) + { + UART_PRINTF("not NVDS_TAG_PEER_IRK\r\n"); + + }else + { + for(int i = 0;ioperation = GAPC_DISCONNECT; + cmd->reason = reason; + + // Send the message + kernel_msg_send(cmd); + } +} + +/** + **************************************************************************************** + * Advertising Functions + **************************************************************************************** + */ + + +/* 豸㲥*/ +void appm_start_direct_dvertising(void) +{ + appm_start_advertising(); + + return; + // Check if the advertising procedure is already is progress + if (kernel_state_get(TASK_APP) == APPM_READY) + { + struct gapm_start_advertise_cmd *cmd = KERNEL_MSG_ALLOC(GAPM_START_ADVERTISE_CMD, + TASK_GAPM, TASK_APP, + gapm_start_advertise_cmd); + + cmd->op.addr_src = GAPM_STATIC_ADDR; + cmd->channel_map = APP_ADV_CHMAP; + + cmd->intv_min = APP_ADV_FAST_INT; + cmd->intv_max = APP_ADV_FAST_INT; + + cmd->op.code = GAPM_ADV_UNDIRECT; + + cmd->info.host.mode = GAP_GEN_DISCOVERABLE; + + /* + * If the peripheral is already bonded with a central device, use the direct advertising + * procedure (BD Address of the peer device is stored in NVDS. + */ + if(app_sec_get_bond_status()) + { + #if (NVDS_SUPPORT) + uint8_t bd_len = NVDS_LEN_PEER_BD_ADDRESS; + #endif + cmd->op.code = GAPM_ADV_DIRECT_LDC; + //cmd->info.direct.addr_type = 1; + + + #if (NVDS_SUPPORT) + if (nvds_get(NVDS_TAG_PEER_BD_ADDRESS, &bd_len, + (uint8_t *)cmd->info.direct.addr.addr) != NVDS_OK) + { + // An error has occurred during access to the NVDS + ASSERT_INFO(0,NVDS_TAG_PEER_BD_ADDRESS,bd_len); + } + #endif + + kernel_msg_send(cmd); + + #if !(DEEP_SLEEP) + kernel_msg_send_basic(APP_PERIOD_TIMER,TASK_APP,TASK_APP); + #endif + + // UART_PRINTF("appm start direct advertising\r\n"); + } + else + { + kernel_msg_free(kernel_param2msg(cmd)); + appm_start_advertising(); + // UART_PRINTF("appm start general advertising\r\n"); + } + + kernel_state_set(TASK_APP, APPM_ADVERTISING); + } +} + + +extern /*const */struct bd_addr common_default_bdaddr; + +/* 豸㲥*/ +ble_err_t appm_start_advertising(void) +{ + ble_err_t status = ERR_SUCCESS; +#if !(DEEP_SLEEP) + kernel_msg_send_basic(APP_PERIOD_TIMER,TASK_APP,TASK_APP); +#endif + + if(BLE_ROLE_MASTER == ble_get_role_mode()) + { + bk_printf("current role should not be master\r\n"); + return ERR_ADV_FAIL; + } + + // Check if the advertising procedure is already is progress + if (kernel_state_get(TASK_APP) == APPM_READY) + { + // Prepare the GAPM_START_ADVERTISE_CMD message + struct gapm_start_advertise_cmd *cmd = KERNEL_MSG_ALLOC(GAPM_START_ADVERTISE_CMD, + TASK_GAPM, TASK_APP, + gapm_start_advertise_cmd); + + cmd->op.addr_src = GAPM_STATIC_ADDR; + cmd->channel_map = adv_info.channel_map; + cmd->intv_min = adv_info.interval_min; + cmd->intv_max = adv_info.interval_max; + cmd->op.code = GAPM_ADV_UNDIRECT; + + cmd->info.host.mode = GAP_GEN_DISCOVERABLE; + + cmd->info.host.adv_filt_policy = ADV_ALLOW_SCAN_ANY_CON_ANY; + + /*----------------------------------------------------------------------------------- + * Set the Advertising Data and the Scan Response Data + *---------------------------------------------------------------------------------*/ + // Flag value is set by the GAP + cmd->info.host.adv_data_len = adv_info.advDataLen; + os_memcpy(cmd->info.host.adv_data, adv_info.advData, cmd->info.host.adv_data_len); + cmd->info.host.scan_rsp_data_len = adv_info.respDataLen; + os_memcpy(cmd->info.host.scan_rsp_data, adv_info.respData, cmd->info.host.scan_rsp_data_len); + + + // Send the message + kernel_msg_send(cmd); + bk_printf("appm start advertising\r\n"); + + ble_init_over = 1; + /// mcu_prevent_set(MCU_PS_BLE_FROBID); + ble_set_role_mode(BLE_ROLE_SLAVE); + + // Set the state of the task to APPM_ADVERTISING + kernel_state_set(TASK_APP, APPM_ADVERTISING); + } + else + { + status = ERR_ADV_FAIL; + } + return status; + // else ignore the request +} + +/* 豸ֹͣ㲥*/ +ble_err_t appm_stop_advertising(void) +{ + + ble_err_t status = ERR_SUCCESS; + + if (kernel_state_get(TASK_APP) == APPM_ADVERTISING) + { + // Go in ready state + kernel_state_set(TASK_APP, APPM_READY); + + // Prepare the GAPM_CANCEL_CMD message + struct gapm_cancel_cmd *cmd = KERNEL_MSG_ALLOC(GAPM_CANCEL_CMD, + TASK_GAPM, TASK_APP, + gapm_cancel_cmd); + cmd->operation = GAPM_CANCEL; + + ble_set_role_mode(BLE_ROLE_NONE); + + // Send the message + kernel_msg_send(cmd); + mcu_prevent_clear(MCU_PS_BLE_FROBID); + } + else + { + status = ERR_STOP_ADV_FAIL; + } + + return status; + // else ignore the request +} + +ble_err_t appm_stop_scan(void) +{ + ble_err_t status = ERR_SUCCESS; + if (kernel_state_get(TASK_APP) == APPM_SCANNING) + { + // Go in ready state + kernel_state_set(TASK_APP, APPM_READY); + + // Prepare the GAPM_CANCEL_CMD message + struct gapm_cancel_cmd *cmd = KERNEL_MSG_ALLOC(GAPM_CANCEL_CMD, + TASK_GAPM, TASK_APP, + gapm_cancel_cmd); + cmd->operation = GAPM_CANCEL; + + // Send the message + kernel_msg_send(cmd); + + kernel_state_set(TASK_APP, APPM_READY); + + } + else + { + status = -1; + } + + return status; +} + +void appm_update_adv_data( uint8_t* adv_buff, uint8_t adv_len, uint8_t* scan_buff, uint8_t scan_len) +{ + if (kernel_state_get(TASK_APP) == APPM_ADVERTISING + && (adv_len <= ADV_DATA_LEN) && (scan_len <= ADV_DATA_LEN)) + { + struct gapm_update_advertise_data_cmd *cmd = KERNEL_MSG_ALLOC( + GAPM_UPDATE_ADVERTISE_DATA_CMD, + TASK_GAPM, + TASK_APP, + gapm_update_advertise_data_cmd); + + cmd->operation = GAPM_UPDATE_ADVERTISE_DATA; + cmd->adv_data_len = adv_len; + cmd->scan_rsp_data_len = scan_len; + + //memcpy + memcpy(&cmd->adv_data[0], adv_buff, adv_len); + memcpy(&cmd->scan_rsp_data[0], scan_buff, scan_len); + + // Send the message + kernel_msg_send(cmd); + } +} + +void appm_update_param(struct gapc_conn_param *conn_param) +{ + // Prepare the GAPC_PARAM_UPDATE_CMD message + struct gapc_param_update_cmd *cmd = KERNEL_MSG_ALLOC(GAPC_PARAM_UPDATE_CMD, + KERNEL_BUILD_ID(TASK_GAPC, app_env.conidx), TASK_APP, + gapc_param_update_cmd); + + cmd->operation = GAPC_UPDATE_PARAMS; + cmd->intv_min = conn_param->intv_min; + cmd->intv_max = conn_param->intv_max; + cmd->latency = conn_param->latency; + cmd->time_out = conn_param->time_out; + + // not used by a slave device + cmd->ce_len_min = 0xFFFF; + cmd->ce_len_max = 0xFFFF; + + // printf("intv_min = %d,intv_max = %d,latency = %d,time_out = %d\r\n", +// cmd->intv_min,cmd->intv_max,cmd->latency,cmd->time_out); + + // Send the message + kernel_msg_send(cmd); +} + + +uint8_t appm_get_dev_name(uint8_t* name) +{ + // copy name to provided pointer + memcpy(name, app_env.dev_name, app_env.dev_name_len); + // return name length + return app_env.dev_name_len; +} + +void appm_calc_psk(uint8_t *p_pub_key) +{ + struct gapm_gen_dh_key_cmd *dh_key_cmd = KERNEL_MSG_ALLOC(GAPM_GEN_DH_KEY_CMD, + TASK_GAPM, TASK_APP, + gapm_gen_dh_key_cmd); + dh_key_cmd->operation = GAPM_GEN_DH_KEY; + memcpy(dh_key_cmd->operand_1, p_pub_key, GAP_P256_KEY_LEN); + memcpy(dh_key_cmd->operand_2, p_pub_key + GAP_P256_KEY_LEN, GAP_P256_KEY_LEN); + + kernel_msg_send(dh_key_cmd); +} + +void appm_get_key(void) +{ + struct gapm_get_key_cmd *get_key_cmd = KERNEL_MSG_ALLOC(GAPM_GET_KEY_CMD, + TASK_GAPM, TASK_APP, + gapm_get_key_cmd); + + get_key_cmd->operation = GAPM_GET_PUB_KEY; + kernel_msg_send(get_key_cmd); +} + +uint8_t appm_get_app_status(void) +{ + return kernel_state_get(TASK_APP); +} + +#if (BLE_APP_SEC) +void appm_send_seurity_req(void) +{ + //printf("%s \r\n",__func__); + return; + app_sec_send_security_req(app_env.conidx); +} +#endif + + +#endif //(BLE_APP_PRESENT) + + + +/// @} APP + + diff --git a/beken_os/beken378/driver/ble/ble_pub/modules/app/src/app_comm.c b/beken_os/beken378/driver/ble/ble_pub/modules/app/src/app_comm.c new file mode 100755 index 0000000..fa04da1 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/modules/app/src/app_comm.c @@ -0,0 +1,243 @@ +#include "rwip_config.h" // SW configuration + +#if (BLE_APP_COMM) +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include +#include "app_comm.h" // Application Module Definitions +#include "application.h" // Application Definitions +#include "app_task.h" // application task definitions +#include "comm_task.h" // health thermometer functions +#include "common_bt.h" +#include "prf_types.h" // Profile common types definition +#include "architect.h" // Platform Definitions +#include "prf.h" +#include "comm.h" +#include "attm.h" +#include "kernel_timer.h" + +static uint8_t bk_ble_get_prf_by_id(uint16_t id, struct prf_task_env **env) +{ + uint8_t status = PRF_APP_ERROR; + uint32_t i; + for(i = 0; i < BLE_NB_PROFILES ; i++) + { + if(prf_env.prf[i].id == id) + { + *env = &(prf_env.prf[i]); + status = GAP_ERR_NO_ERROR; + break; + } + } + + return status; +} + +ble_err_t bk_ble_create_db (struct bk_ble_db_cfg* ble_db_cfg) +{ + ble_err_t ret = ERR_SUCCESS; + bk_printf("ble create new db\r\n"); + + if (kernel_state_get(TASK_APP) == APPM_READY) + { + struct bk_ble_db_cfg *db_cfg; + + struct gapm_profile_task_add_cmd *req = KERNEL_MSG_ALLOC_DYN(GAPM_PROFILE_TASK_ADD_CMD, + TASK_GAPM, TASK_APP, + gapm_profile_task_add_cmd, sizeof(struct bk_ble_db_cfg)); + // Fill message + req->operation = GAPM_PROFILE_TASK_ADD; + req->sec_lvl = ble_db_cfg->svc_perm; + req->prf_task_id = TASK_ID_COMMON + ble_db_cfg->prf_task_id; + req->app_task = TASK_APP; + req->start_hdl = ble_db_cfg->start_hdl; //req->start_hdl = 0; dynamically allocated + + //Set parameters + db_cfg = (struct bk_ble_db_cfg* ) req->param; + memcpy(db_cfg, ble_db_cfg, sizeof(struct bk_ble_db_cfg)); + + kernel_state_set(TASK_APP, APPM_CREATE_DB); + //Send the message + kernel_msg_send(req); + } + else + { + ret = ERR_CREATE_DB; + } + + return ret; +} + +static int app_comm_msg_dflt_handler(kernel_msg_id_t const msgid, + void const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + // Drop the message + return (KERNEL_MSG_CONSUMED); +} + +ble_err_t bk_ble_conn_enable_prf(uint8_t conidx, uint16_t prf_id) +{ + ble_err_t ret = ERR_SUCCESS; + uint16_t prf_task_id = prf_id + TASK_ID_COMMON; + struct prf_task_env *prf_env = NULL; + uint8_t status; + + status = bk_ble_get_prf_by_id(prf_task_id, &prf_env); + if(status == GAP_ERR_NO_ERROR) + { + // Allocate the message + struct bk_ble_enable_req * req = KERNEL_MSG_ALLOC(BK_BLE_ENABLE_REQ, + prf_env->task, + TASK_APP, + bk_ble_enable_req); + // Fill in the parameter structure + req->conidx = conidx; + req->ind_cfg = 0; + req->ntf_cfg = 0; + + // Send the message + kernel_msg_send(req); + } + else + { + ret = ERR_PROFILE; + } + + return ret; +} + +ble_err_t bk_ble_send_ntf_value(uint32_t len, uint8_t *buf, uint16_t prf_id, uint16_t att_idx) +{ + ble_err_t ret = ERR_SUCCESS; + uint16_t prf_task_id = prf_id + TASK_ID_COMMON; + struct prf_task_env *prf_env = NULL; + struct bk_ble_env_tag* ble_env = NULL; + + uint8_t status = bk_ble_get_prf_by_id(prf_task_id, &prf_env); + ble_env = (struct bk_ble_env_tag*)(prf_env->env); + + if(status == GAP_ERR_NO_ERROR) + { + // Allocate the message + struct bk_ble_ntf_upd_req * req = KERNEL_MSG_ALLOC_DYN(BK_BLE_NTF_UPD_REQ, + prf_env->task, + TASK_APP, + bk_ble_ntf_upd_req,len); + + req->length = len; + memcpy(req->value, buf, len); + req->att_id = att_idx; + req->conidx = 0; + + kernel_msg_send(req); + } + else + { + ret = ERR_PROFILE; + } + + return ret; +} + +ble_err_t bk_ble_send_ind_value(uint32_t len, uint8_t *buf, uint16_t prf_id, uint16_t att_idx) +{ + ble_err_t ret = ERR_SUCCESS; + uint16_t prf_task_id = prf_id + TASK_ID_COMMON; + struct prf_task_env *prf_env = NULL; + + uint8_t status = bk_ble_get_prf_by_id(prf_task_id, &prf_env); + + if(status == GAP_ERR_NO_ERROR) + { + // Allocate the message + struct bk_ble_ind_upd_req * req = KERNEL_MSG_ALLOC_DYN(BK_BLE_IND_UPD_REQ, + prf_env->task, + TASK_APP, + bk_ble_ind_upd_req,len); + + req->length = len; + memcpy(req->value, buf, len); + req->att_id = att_idx; + req->conidx = 0; + + kernel_msg_send(req); + } + else + { + ret = ERR_PROFILE; + } + + return ret; +} + +static int bk_ble_write_req_ind_handler(kernel_msg_id_t const msgid, + struct bk_ble_write_ind *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + + write_req_t write_req; + + #if 0 //printf for test write req + uint32_t i; + bk_printf("prf_id:%d, att_idx:%d\r\n", param->prf_id, param->att_id); + + for(i = 0; i < param->length; i++) + { + bk_printf("%x ", (param->value)[i]); + } + bk_printf("\r\n"); + #endif + + write_req.att_idx = param->att_id; + write_req.len = param->length; + write_req.prf_id = param->prf_id; + write_req.value = &(param->value[0]); + + if(bk_ble_write_cb != NULL) + { + (*bk_ble_write_cb)(&write_req); + } + + return (KERNEL_MSG_CONSUMED); +} + +static int bk_ble_enable_rsp_handler(kernel_msg_id_t const msgid, + struct bk_ble_enable_rsp const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + return (KERNEL_MSG_CONSUMED); +} + +static int bk_ble_gattc_cmp_evt_handler(kernel_msg_id_t const msgid, struct bk_ble_gattc_cmp_evt const *param, + kernel_task_id_t const dest_id, kernel_task_id_t const src_id) +{ + if(param->operation == GATTC_INDICATE || param->operation == GATTC_NOTIFY) + { + if(ble_event_cb) + { + (*ble_event_cb)(BLE_TX_DONE, NULL); + } + } + return KERNEL_MSG_CONSUMED; +} + +const struct kernel_msg_handler app_comm_msg_handler_list[] = +{ + // Note: first message is latest message checked by kernel so default is put on top. + {KERNEL_MSG_DEFAULT_HANDLER, (kernel_msg_func_t)app_comm_msg_dflt_handler}, + {BK_BLE_WRITE_REQ_IND, (kernel_msg_func_t)bk_ble_write_req_ind_handler}, + {BK_BLE_ENABLE_RSP, (kernel_msg_func_t)bk_ble_enable_rsp_handler}, + {BK_BLE_GATTC_CMP_EVT, (kernel_msg_func_t)bk_ble_gattc_cmp_evt_handler}, +}; + +const struct kernel_state_handler app_comm_table_handler = + {&app_comm_msg_handler_list[0], (sizeof(app_comm_msg_handler_list)/sizeof(struct kernel_msg_handler))}; + +#endif + diff --git a/beken_os/beken378/driver/ble/ble_pub/modules/app/src/app_sdp.c b/beken_os/beken378/driver/ble/ble_pub/modules/app/src/app_sdp.c new file mode 100755 index 0000000..59f13f8 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/modules/app/src/app_sdp.c @@ -0,0 +1,546 @@ +#include "rwip_config.h" // SW configuration +#if (BLE_APP_SDP) +#include "app_task.h" // Application task Definition +#include "app_sdp.h" // Application Definition +#include "gap.h" // GAP Definition +#include "gapm_task.h" // GAP Manager Task API +#include "gapc_task.h" // GAP Controller Task API +#include "gattc_task.h" +#include "common_bt.h" // Common BT Definition +#include "common_math.h" // Common Maths Definition +#include "sdp_service_task.h" +#include "sdp_service.h" +#include "uart.h" +#include "gpio.h" +#include "llm_util.h" + + +uint32_t con_peer_idx; +struct gap_bdaddr con_bdaddr; +extern uint8_t max_scan_numbers; + +scan_info_t scan_info = { + .filter_en = SCAN_FILT_DUPLIC_DIS, + .channel_map = 7, + .interval = 100, + .window = 20 +}; + +void appm_set_max_scan_nums(uint8_t max) +{ + if(max > MAX_SCAN_NUM) + { + max_scan_numbers = MAX_SCAN_NUM; + } + else + { + max_scan_numbers = max; + } +} + +uint8_t appm_get_max_scan_nums(void) +{ + return max_scan_numbers; +} + + +ble_err_t appm_start_scanning(void) +{ + ble_err_t status = ERR_SUCCESS; + + if(BLE_ROLE_SLAVE == ble_get_role_mode()) + { + bk_printf("current role should not be slave\r\n"); + return ERR_SCAN_FAIL; + } + if (kernel_state_get(TASK_APP) == APPM_READY) + { + // Prepare the GAPM_START_SCAN_CMD message + struct gapm_start_scan_cmd *cmd = KERNEL_MSG_ALLOC(GAPM_START_SCAN_CMD, + TASK_GAPM, TASK_APP, + gapm_start_scan_cmd); + cmd->op.addr_src = GAPM_STATIC_ADDR; + cmd->op.code = GAPM_SCAN_PASSIVE; + cmd->interval = scan_info.interval;//50; + cmd->window = scan_info.window;//40; + cmd->mode = GAP_OBSERVER_MODE; + cmd->filt_policy = SCAN_ALLOW_ADV_ALL; + cmd->filter_duplic = scan_info.filter_en; + cmd->channel_map = scan_info.channel_map; /*APP_ADV_CHMAP*/ + adv_count = 0; + ble_set_role_mode(BLE_ROLE_MASTER); + // Send the message + kernel_msg_send(cmd); + // Set the state of the task to APPM_SCANNING + kernel_state_set(TASK_APP, APPM_SCANNING); + + } + else + { + bk_printf("CURRENT STATE= %x\r\n",kernel_state_get(TASK_APP)); + status = ERR_SCAN_FAIL; + } + + return status; +} + +ble_err_t appm_stop_scanning(void) +{ + ble_err_t status = ERR_SUCCESS; + + if (kernel_state_get(TASK_APP) == APPM_SCANNING) + { + // Prepare the GAPM_CANCEL_CMD message + struct gapm_cancel_cmd *cmd = KERNEL_MSG_ALLOC(GAPM_CANCEL_CMD, + TASK_GAPM, TASK_APP, + gapm_cancel_cmd); + cmd->operation = GAPM_CANCEL; + + ble_set_role_mode(BLE_ROLE_NONE); + // Send the message + kernel_msg_send(cmd); + // Go in ready state + kernel_state_set(TASK_APP, APPM_READY); + } + else + { + bk_printf("CURRENT STATE= %x\r\n",kernel_state_get(TASK_APP)); + status = ERR_STOP_SCAN_FAIL; + } + return status; +} + + +ble_err_t appm_start_connenct_by_id(uint8_t id) +{ + ble_err_t status = ERR_SUCCESS; + + if(BLE_ROLE_SLAVE == ble_get_role_mode()) + { + bk_printf("current role should not be slave\r\n"); + return ERR_CONN_FAIL; + } + if (kernel_state_get(TASK_APP) == APPM_READY) + { + // Prepare the GAPM_START_SCAN_CMD message + struct gapm_start_connection_cmd *cmd = KERNEL_MSG_ALLOC_DYN( + GAPM_START_CONNECTION_CMD, + TASK_GAPM, TASK_APP, + gapm_start_connection_cmd, + sizeof(struct gap_bdaddr)); + cmd->op.addr_src = GAPM_STATIC_ADDR; + cmd->op.code = GAPM_CONNECTION_DIRECT; + cmd->scan_interval = 50; + cmd->scan_window = 40; + cmd->con_intv_min = 16; + cmd->con_intv_max = 20; + cmd->con_latency = 0; + cmd->superv_to = 200; + cmd->ce_len_min = 100; + cmd->ce_len_max = 200; + cmd->nb_peers = 1; + + cmd->peers[0].addr_type = 0; + memcpy(&cmd->peers[0].addr.addr[0],&ble_scan_list.info[id].adv_addr.addr[0],6); + + bk_printf("conn addr = %02x:%02x:%02x:%02x:%02x:%02x\r\n",cmd->peers[0].addr.addr[0], + cmd->peers[0].addr.addr[1],cmd->peers[0].addr.addr[2], + cmd->peers[0].addr.addr[3],cmd->peers[0].addr.addr[4], + cmd->peers[0].addr.addr[5]); + + // Send the message + kernel_msg_send(cmd); + + ble_set_role_mode(BLE_ROLE_MASTER); + // Set the state of the task to APPM_SCANNING + kernel_state_set(TASK_APP, APPM_CONNECTING); + } + else + { + bk_printf("CURRENT STATE= %x\r\n",kernel_state_get(TASK_APP)); + status = ERR_CONN_FAIL; + } + return status; +} + + +ble_err_t appm_start_connenct_by_addr(uint8_t* bdaddr) +{ + ble_err_t status = ERR_SUCCESS; + + if(BLE_ROLE_SLAVE == ble_get_role_mode()) + { + bk_printf("current role should not be slave\r\n"); + return ERR_CONN_FAIL; + } + if (kernel_state_get(TASK_APP) == APPM_READY) + { + // Prepare the GAPM_START_SCAN_CMD message + struct gapm_start_connection_cmd *cmd = KERNEL_MSG_ALLOC_DYN( + GAPM_START_CONNECTION_CMD, + TASK_GAPM, TASK_APP, + gapm_start_connection_cmd, + sizeof(struct gap_bdaddr)); + cmd->op.addr_src = GAPM_STATIC_ADDR; + cmd->op.code = GAPM_CONNECTION_DIRECT; + cmd->scan_interval = 50; + cmd->scan_window = 40; + cmd->con_intv_min = 16; + cmd->con_intv_max = 20; + cmd->con_latency = 0; + cmd->superv_to = 200; + cmd->ce_len_min = 100; + cmd->ce_len_max = 200; + cmd->nb_peers = 1; + + cmd->peers[0].addr_type = 0; + memcpy(&cmd->peers[0].addr.addr[0],bdaddr,6); + + bk_printf("conn addr = %02x:%02x:%02x:%02x:%02x:%02x\r\n",cmd->peers[0].addr.addr[0], + cmd->peers[0].addr.addr[1],cmd->peers[0].addr.addr[2], + cmd->peers[0].addr.addr[3],cmd->peers[0].addr.addr[4], + cmd->peers[0].addr.addr[5]); + + // Send the message + kernel_msg_send(cmd); + + ble_set_role_mode(BLE_ROLE_MASTER); + // Set the state of the task to APPM_SCANNING + kernel_state_set(TASK_APP, APPM_CONNECTING); + + } + else + { + bk_printf("CURRENT STATE= %x\r\n",kernel_state_get(TASK_APP)); + status = ERR_CONN_FAIL; + } + return status; +} + + +ble_err_t appm_stop_connencting(void) +{ + ble_err_t status = ERR_SUCCESS; + + if (kernel_state_get(TASK_APP) == APPM_CONNECTING) + { + // Go in ready state + // Prepare the GAPM_CANCEL_CMD message + struct gapm_cancel_cmd *cmd = KERNEL_MSG_ALLOC( + GAPM_CANCEL_CMD, + TASK_GAPM, TASK_APP, + gapm_cancel_cmd); + cmd->operation = GAPM_CANCEL; + // Send the message + + ble_set_role_mode(BLE_ROLE_NONE); + + kernel_msg_send(cmd); + } + else + { + bk_printf("CURRENT STATE= %x\r\n",kernel_state_get(TASK_APP)); + status = ERR_STOP_CONN_FAIL; + } + return status; +} + + +ble_err_t appm_disconnect_link(void) +{ + ble_err_t status = ERR_SUCCESS; + + if((kernel_state_get(TASK_APP) == APPM_CONNECTED) + ||(kernel_state_get(TASK_APP) == APPM_LINK_CONNECTED) + ||(kernel_state_get(TASK_APP) == APPM_SDP_DISCOVERING)) + { + struct gapc_disconnect_cmd *cmd = KERNEL_MSG_ALLOC(GAPC_DISCONNECT_CMD, + KERNEL_BUILD_ID(TASK_GAPC, 0), + TASK_APP, + gapc_disconnect_cmd); + cmd->operation = GAPC_DISCONNECT; + cmd->reason = COMMON_ERROR_REMOTE_USER_TERM_CON; + + // Send the message + kernel_msg_send(cmd); + } + else + { + bk_printf("CURRENT STATE= %x\r\n",kernel_state_get(TASK_APP)); + status = ERR_DISCONN_FAIL; + } + return status; +} + + +uint8_t appm_adv_data_decode(uint8_t len,const uint8_t *data,uint8_t *find_str,uint8_t str_len) +{ + uint8_t find = 0; + uint8_t index; + uint8_t i; + for(index = 0; index < len;) + { + switch(data[index + 1]) + { + case GAP_AD_TYPE_FLAGS: + { + bk_printf("AD_TYPE : "); + for(i = 0; i < data[index] - 1; i++) + { + bk_printf("%02x ",data[index + 2 + i]); + } + bk_printf("\r\n"); + index +=(data[index] + 1); + } + break; + case GAP_AD_TYPE_SHORTENED_NAME: + case GAP_AD_TYPE_COMPLETE_NAME: + { + if(strncmp((char*)&data[index + 2],(char*)find_str,str_len) == 0) + { + find = 1; + } + bk_printf("ADV_NAME : "); + for(i = 0; i < data[index] - 1; i++) + { + bk_printf("%c",data[index + 2 + i]); + } + bk_printf("\r\n"); + index +=(data[index] + 1); + } + break; + case GAP_AD_TYPE_MORE_16_BIT_UUID: + { + bk_printf("UUID : "); + for(i = 0; i < data[index] - 1;) + { + bk_printf("%02x%02x ",data[index + 2 + i],data[index + 3 + i]); + i+=2; + } + bk_printf("\r\n"); + index +=(data[index] + 1); + } + break; + default: + { + index +=(data[index] + 1); + } + break; + } + } + return find; +} + + +ble_err_t appm_write_data_by_uuid(uint16_t uuid,uint8_t len,uint8_t *data) +{ + ble_err_t status = ERR_SUCCESS; + + if(BLE_ROLE_MASTER != ble_get_role_mode()) + { + bk_printf("current role should be master\r\n"); + return ERR_WRITE_FAIL; + } + if(kernel_state_get(TASK_APP) == APPM_CONNECTED) + { + struct sdp_write_info_req *req = KERNEL_MSG_ALLOC_DYN(SDP_WRITE_VALUE_INFO_REQ, + prf_get_task_from_id(TASK_ID_SDP), + TASK_APP, + sdp_write_info_req, len); + // Fill in the parameter structure + req->uuid = uuid; + req->length = len; + memcpy(req->data,data,len); + // Send the message + kernel_msg_send(req); + } + else + { + status = ERR_WRITE_FAIL; + } + + return status; +} + +ble_err_t appm_write_ntf_cfg(uint16_t uuid,uint16_t number,uint16_t cfg) +{ + ble_err_t status = ERR_SUCCESS; + bk_printf("uuid = 0x%04x,cfg = 0x%x\r\n",uuid, cfg); + if(kernel_state_get(TASK_APP) == APPM_CONNECTED ) + { + struct sdp_w_ntf_cfg_req *req = KERNEL_MSG_ALLOC(SDP_WRITE_NTF_CFG_REQ, + prf_get_task_from_id(TASK_ID_SDP), + TASK_APP, + sdp_w_ntf_cfg_req); + // Fill in the parameter structure + req->uuid = uuid; + req->char_num = number; + req->ntf_cfg = cfg; + + // Send the message + kernel_msg_send(req); + } + else + { + status = ERR_WRITE_FAIL; + } + + return status; +} + + +ble_err_t appm_read_data_by_uuid(uint16_t uuid) +{ + ble_err_t status = ERR_SUCCESS; + + if(BLE_ROLE_MASTER != ble_get_role_mode()) + { + bk_printf("current role should be master\r\n"); + return ERR_READ_FAIL; + } + if(kernel_state_get(TASK_APP) == APPM_CONNECTED) + { + struct sdp_read_info_req *req = KERNEL_MSG_ALLOC(SDP_READ_INFO_REQ, + prf_get_task_from_id(TASK_ID_SDP), + TASK_APP, + sdp_read_info_req); + // Fill in the parameter structure + req->uuid = uuid; + req->info = SDPC_CHAR_VAL; + + // Send the message + kernel_msg_send(req); + } + else + { + status = ERR_READ_FAIL; + } + + return status; +} + +ble_err_t appm_read_cfg_by_uuid(uint16_t uuid) +{ + ble_err_t status = ERR_SUCCESS; + + if(kernel_state_get(TASK_APP) == APPM_CONNECTED ) + { + struct sdp_read_info_req *req = KERNEL_MSG_ALLOC(SDP_READ_INFO_REQ, + prf_get_task_from_id(TASK_ID_SDP), + TASK_APP, + sdp_read_info_req); + // Fill in the parameter structure + req->uuid = uuid; + req->info = SDPC_CHAR_NTF_CFG; + + // Send the message + kernel_msg_send(req); + } + else + { + status = ERR_READ_FAIL; + } + + return status; +} + +ble_err_t appm_read_user_desc_by_uuid(uint16_t uuid) +{ + ble_err_t status = ERR_SUCCESS; + + if(kernel_state_get(TASK_APP) == APPM_CONNECTED ) + { + struct sdp_read_info_req *req = KERNEL_MSG_ALLOC(SDP_READ_INFO_REQ, + prf_get_task_from_id(TASK_ID_SDP), + TASK_APP, + sdp_read_info_req); + // Fill in the parameter structure + req->uuid = uuid; + req->info = SDPC_CHAR_USER_DESC_VAL; + + // Send the message + kernel_msg_send(req); + } + else + { + status = ERR_READ_FAIL; + } + + return status; +} + +extern struct sdp_env_tag adp_serv_env[SDP_NB_SERVICE_INSTANCES_MAX]; +uint8_t sdp_enable_all_server_ntf_ind(uint8_t reset) +{ + bool more_enable = false; + static uint8_t server_num = 0; + static uint8_t chars_num = 0; + + bk_printf("%s\r\n",__func__); + + if(reset == 1) + { + server_num = 0; + chars_num = 0; + } + for(; server_num < SDP_NB_SERVICE_INSTANCES_MAX;) + { + if( adp_serv_env[server_num].use_status == VALID_STATUS) + { + for(; chars_num < adp_serv_env[server_num].db_env[0].cnx_env->sdp.chars_nb;) + { + bk_printf("server_num = %d,chars_num = %d,prop = 0x%x\r\n",server_num,chars_num,adp_serv_env[server_num].db_env[0].cnx_env->sdp.chars[chars_num].prop); + if(adp_serv_env[server_num].db_env[0].cnx_env->sdp.chars[chars_num].prop & 0x20) + { + if(adp_serv_env[server_num].db_env[0].cnx_env->sdp.chars[chars_num].prop ) + { + appm_write_ntf_cfg(adp_serv_env[server_num].db_env[0].cnx_env->sdp.chars[chars_num].uuid,chars_num,0x02); + } + more_enable = true; + chars_num++; + return more_enable; + } + else if(adp_serv_env[server_num].db_env[0].cnx_env->sdp.chars[chars_num].prop & 0x10) + { + if(adp_serv_env[server_num].db_env[0].cnx_env->sdp.chars[chars_num].prop ) + { + appm_write_ntf_cfg(adp_serv_env[server_num].db_env[0].cnx_env->sdp.chars[chars_num].uuid,chars_num,0x01); + } + more_enable = true; + chars_num++; + return more_enable; + } + else + { + chars_num++; + } + } + server_num++; + chars_num = 0; + } + else + { + more_enable = false; + return more_enable; + } + } + return more_enable; +} + +void sdp_prf_register_all_atthdl2gatt(void) +{ + uint8_t idx = 0; + for(idx = 0;idx < SDP_NB_SERVICE_INSTANCES_MAX;idx++) + { + struct sdp_env_tag* sdp_env = &adp_serv_env[idx]; + + if(0 != sdp_env->db_env[0].cnx_env->sdp.descs_nb) + { + bk_printf("prf_register_atthdl2gatt start_hdl = 0x%x,end_hdl = 0x%x\r\n",sdp_env->db_env[0].cnx_env->sdp.svc.shdl,sdp_env->db_env[0].cnx_env->sdp.svc.ehdl); + prf_register_atthdl2gatt(&(sdp_env->prf_env), 0, &sdp_env->db_env[0].cnx_env->sdp.svc); + } + } +} + +#endif + diff --git a/beken_os/beken378/driver/ble/ble_pub/modules/app/src/app_sec.c b/beken_os/beken378/driver/ble/ble_pub/modules/app/src/app_sec.c new file mode 100755 index 0000000..cd040f1 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/modules/app/src/app_sec.c @@ -0,0 +1,553 @@ +/** + **************************************************************************************** + * + * @file app_sec.c + * + * @brief Application Security Entry Point + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @addtogroup APP + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" + +#if (BLE_APP_SEC) + +#include +#include "common_math.h" +#include "gapc_task.h" // GAP Controller Task API Definition +#include "gap.h" // GAP Definition +#include "gapc.h" // GAPC Definition +#include "prf_types.h" +#include "llc_llcp.h" + +#include "application.h" // Application API Definition +#include "app_sec.h" // Application Security API Definition +#include "app_task.h" // Application Manager API Definitionde +#include "kernel_timer.h" + +#if (BLE_APP_ANCSC) +#include "app_ancsc.h" +#endif //(BLE_APP_ANCSC) + +#if (DISPLAY_SUPPORT) +#include "app_display.h" // Display Application Definitions +#endif //(DISPLAY_SUPPORT) + +#if (NVDS_SUPPORT) +#include "nvds.h" // NVDS API Definitions +#endif //(NVDS_SUPPORT) + +#ifdef BLE_APP_AM0 +#include "am0_application.h" +#endif // BLE_APP_AM0 +#include "common_utils.h" +#include "uart.h" +/* + * GLOBAL VARIABLE DEFINITIONS + **************************************************************************************** + */ + +#define DIRECT_ADV_EN 0 //test + +/// Application Security Environment Structure +struct app_sec_env_tag app_sec_env; + + + + +bool app_sec_peer_pairing_recv(void); + +bool app_sec_peer_encrypt_recv(void); + + +/* + * GLOBAL FUNCTION DEFINITIONS + **************************************************************************************** + */ + +void app_sec_init(void) +{ + //UART_PRINTF("%s \r\n",__func__); + #if (NVDS_SUPPORT && DIRECT_ADV_EN) + uint8_t length = NVDS_LEN_PERIPH_BONDED; + if (nvds_get(NVDS_TAG_PERIPH_BONDED, &length, (uint8_t *)&app_sec_env.bonded) != NVDS_OK) + { + //UART_PRINTF("read app_sec_env.bonded = %x\r\n",app_sec_env.bonded); + // If read value is invalid, set status to not bonded + if ((app_sec_env.bonded != true) && (app_sec_env.bonded != false)) + { + app_sec_env.bonded = false; + } + } + app_sec_env.peer_pairing_recv = false; + app_sec_env.peer_encrypt_recv = false; + #else + app_sec_env.bonded = false; + app_sec_env.peer_pairing_recv = false; + app_sec_env.peer_encrypt_recv = false; + #endif + +} + +bool app_sec_get_bond_status(void) +{ + //UART_PRINTF("bonded = %d\r\n",app_sec_env.bonded); + return app_sec_env.bonded; +} + + +bool app_sec_peer_pairing_recv(void) +{ + //UART_PRINTF("peer pairing = %d\r\n",app_sec_env.peer_pairing_recv); + return app_sec_env.peer_pairing_recv; +} + + +bool app_sec_peer_encrypt_recv(void) +{ + //UART_PRINTF("peer encrypt = %d\r\n",app_sec_env.peer_encrypt_recv); + return app_sec_env.peer_encrypt_recv; +} + + +#if (NVDS_SUPPORT ) +void app_sec_remove_bond(void) +{ + #if (BLE_APP_HID) + uint16_t ntf_cfg = PRF_CLI_STOP_NTFIND; + #endif //(BLE_APP_HID) + + // Check if we are well bonded + if (app_sec_env.bonded == true) + { + // Update the environment variable + app_sec_env.bonded = false; + + if (nvds_put(NVDS_TAG_PERIPH_BONDED, NVDS_LEN_PERIPH_BONDED, + (uint8_t *)&app_sec_env.bonded) != NVDS_OK) + { + ASSERT_ERR(0); + } + + #if (BLE_APP_HID) + if (nvds_put(NVDS_TAG_MOUSE_NTF_CFG, NVDS_LEN_MOUSE_NTF_CFG, + (uint8_t *)&ntf_cfg) != NVDS_OK) + { + ASSERT_ERR(0); + } + #endif //(BLE_APP_HID) + } + app_sec_env.bonded = false; + app_sec_env.peer_pairing_recv = false; + app_sec_env.peer_encrypt_recv = false; +} +#endif + +void app_sec_send_security_req(uint8_t conidx) +{ + if(!app_sec_peer_encrypt_recv() && !app_sec_peer_pairing_recv()) + { + //UART_PRINTF("app_sec_send_security_req\r\n"); + + // Send security request + struct gapc_security_cmd *cmd = KERNEL_MSG_ALLOC(GAPC_SECURITY_CMD, + KERNEL_BUILD_ID(TASK_GAPC, conidx), TASK_APP, + gapc_security_cmd); + + cmd->operation = GAPC_SECURITY_REQ; + + #if (BLE_APP_HID || BLE_APP_HT) + //cmd->auth = GAP_AUTH_REQ_MITM_BOND; + cmd->auth = GAP_AUTH_REQ_NO_MITM_BOND; + #elif defined(BLE_APP_AM0) + cmd->auth = GAP_AUTH_REQ_NO_MITM_BOND; + #else + cmd->auth = GAP_AUTH_REQ_NO_MITM_NO_BOND; + #endif //(BLE_APP_HID || BLE_APP_HT) + + // Send the message + kernel_msg_send(cmd); + } + else + { + kernel_timer_clear(APP_SEND_SECURITY_REQ,TASK_APP); + } +} + +/* + * MESSAGE HANDLERS + **************************************************************************************** + */ + +static int gapc_bond_req_ind_handler(kernel_msg_id_t const msgid, + struct gapc_bond_req_ind const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + //UART_PRINTF("%s \r\n",__func__); + // Prepare the GAPC_BOND_CFM message + struct gapc_bond_cfm *cfm = KERNEL_MSG_ALLOC(GAPC_BOND_CFM, + src_id, TASK_APP, + gapc_bond_cfm); + + switch (param->request) + { + case (GAPC_PAIRING_REQ): + { + //UART_PRINTF("gapc_pairing req\r\n"); + app_sec_env.peer_pairing_recv = true; + cfm->request = GAPC_PAIRING_RSP; + + #ifndef BLE_APP_AM0 + cfm->accept = false; + + // Check if we are already bonded (Only one bonded connection is supported) + if (!app_sec_env.bonded) + #endif // !BLE_APP_AM0 + { + cfm->accept = true; + + #if (BLE_APP_HID || BLE_APP_HT) + // Pairing Features + cfm->data.pairing_feat.auth = GAP_AUTH_REQ_NO_MITM_BOND; + #elif defined(BLE_APP_AM0) + cfm->data.pairing_feat.auth = GAP_AUTH_REQ_NO_MITM_BOND; + #else + cfm->data.pairing_feat.auth = GAP_AUTH_REQ_NO_MITM_NO_BOND; + #endif //(BLE_APP_HID || BLE_APP_HT) + + #if (BLE_APP_HT) + cfm->data.pairing_feat.iocap = GAP_IO_CAP_DISPLAY_ONLY; + #else + cfm->data.pairing_feat.iocap = GAP_IO_CAP_NO_INPUT_NO_OUTPUT; + #endif //(BLE_APP_HT) + + cfm->data.pairing_feat.key_size = 16; + cfm->data.pairing_feat.oob = GAP_OOB_AUTH_DATA_NOT_PRESENT; + cfm->data.pairing_feat.sec_req = GAP_NO_SEC; + //cfm->data.pairing_feat.ikey_dist = GAP_KDIST_ENCKEY | GAP_KDIST_IDKEY | GAP_KDIST_SIGNKEY; + //cfm->data.pairing_feat.rkey_dist = GAP_KDIST_ENCKEY | GAP_KDIST_IDKEY | GAP_KDIST_SIGNKEY; + + //cfm->data.pairing_feat.ikey_dist = GAP_KDIST_IDKEY | GAP_KDIST_SIGNKEY; + //cfm->data.pairing_feat.rkey_dist = GAP_KDIST_ENCKEY; + cfm->data.pairing_feat.ikey_dist = GAP_KDIST_ENCKEY| GAP_KDIST_IDKEY; + cfm->data.pairing_feat.rkey_dist = GAP_KDIST_ENCKEY| GAP_KDIST_IDKEY; + /* + #if (defined(BLE_APP_AM0)) + cfm->data.pairing_feat.ikey_dist = GAP_KDIST_IDKEY; + cfm->data.pairing_feat.rkey_dist = GAP_KDIST_ENCKEY | GAP_KDIST_IDKEY; + #else + cfm->data.pairing_feat.ikey_dist = GAP_KDIST_NONE; + cfm->data.pairing_feat.rkey_dist = GAP_KDIST_ENCKEY; + #endif // (defined(BLE_APP_AM0)) + */ + } + } break; + + case (GAPC_LTK_EXCH): + { + // UART_PRINTF("gapc_ltk req\r\n"); + // Counter + uint8_t counter; + cfm->accept = true; + cfm->request = GAPC_LTK_EXCH; + + // Generate all the values + cfm->data.ltk.ediv = (uint16_t)common_rand_word(); + + for (counter = 0; counter < RAND_NB_LEN; counter++) + { + cfm->data.ltk.ltk.key[counter] = (uint8_t)common_rand_word(); + cfm->data.ltk.randnb.nb[counter] = (uint8_t)common_rand_word(); + } + + for (counter = RAND_NB_LEN; counter < KEY_LEN; counter++) + { + cfm->data.ltk.ltk.key[counter] = (uint8_t)common_rand_word(); + } + + #if (NVDS_SUPPORT) + // Store the generated value in NVDS + if (nvds_put(NVDS_TAG_LTK, NVDS_LEN_LTK, + (uint8_t *)&cfm->data.ltk) != NVDS_OK) + { + ASSERT_ERR(0); + } + #endif// #if (NVDS_SUPPORT) + } break; + + + case (GAPC_IRK_EXCH): + { + //UART_PRINTF("gapc_lrk exch\r\n"); + + cfm->accept = true; + cfm->request = GAPC_IRK_EXCH; + + // Load IRK + memcpy(cfm->data.irk.irk.key, app_env.loc_irk, KEY_LEN); + // load device address + cfm->data.irk.addr.addr_type = ADDR_PUBLIC; + memcpy(cfm->data.irk.addr.addr.addr,(uint8_t *)&common_default_bdaddr,BD_ADDR_LEN); + } break; + + + #if (BLE_APP_HT) + case (GAPC_TK_EXCH): + { + // Generate a PIN Code- (Between 100000 and 999999) + uint32_t pin_code = (100000 + (common_rand_word()%900000)); + + #if DISPLAY_SUPPORT + // Display the PIN Code + app_display_pin_code(pin_code); + #endif //DISPLAY_SUPPORT + + cfm->accept = true; + cfm->request = GAPC_TK_EXCH; + + // Set the TK value + memset(cfm->data.tk.key, 0, KEY_LEN); + + cfm->data.tk.key[0] = (uint8_t)((pin_code & 0x000000FF) >> 0); + cfm->data.tk.key[1] = (uint8_t)((pin_code & 0x0000FF00) >> 8); + cfm->data.tk.key[2] = (uint8_t)((pin_code & 0x00FF0000) >> 16); + cfm->data.tk.key[3] = (uint8_t)((pin_code & 0xFF000000) >> 24); + } break; + #endif //(BLE_APP_HT) + + default: + { + ASSERT_ERR(0); + } break; + } + + // Send the message + kernel_msg_send(cfm); + + return (KERNEL_MSG_CONSUMED); +} + + +static int gapc_bond_ind_handler(kernel_msg_id_t const msgid, + struct gapc_bond_ind const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + //UART_PRINTF("%s param->info = 0x%x\r\n",__func__,param->info); + switch (param->info) + { + case (GAPC_PAIRING_SUCCEED): + { + // Update the bonding status in the environment + app_sec_env.bonded = true; + //UART_PRINTF("gapc pairing success\r\n"); + + // Update the bonding status in the environment + #if (PLF_NVDS) + if (nvds_put(NVDS_TAG_PERIPH_BONDED, NVDS_LEN_PERIPH_BONDED, + (uint8_t *)&app_sec_env.bonded) != NVDS_OK) + { + // An error has occurred during access to the NVDS + ASSERT_ERR(0); + } + + // Set the BD Address of the peer device in NVDS + if (nvds_put(NVDS_TAG_PEER_BD_ADDRESS, NVDS_LEN_PEER_BD_ADDRESS, + (uint8_t *)gapc_get_bdaddr(0, SMPC_INFO_PEER)) != NVDS_OK) + { + // An error has occurred during access to the NVDS + ASSERT_ERR(0); + } + #endif //(PLF_NVDS) + + #if (DISPLAY_SUPPORT) + // Update the bond status screen value + app_display_set_bond(app_sec_env.bonded); + #endif //(DISPLAY_SUPPORT) + #ifdef BLE_APP_AM0 + am0_app_send_audio_init(KERNEL_IDX_GET(src_id)); + #endif // BLE_APP_AM0 + } break; + + case (GAPC_REPEATED_ATTEMPT): + { + appm_disconnect(0x13); + } break; + + case (GAPC_IRK_EXCH): + { + //UART_PRINTF("gapc pairing GAPC_IRK_EXCH\r\n"); + #if (NVDS_SUPPORT) + // Store peer identity in NVDS + if (nvds_put(NVDS_TAG_PEER_IRK, NVDS_LEN_PEER_IRK, (uint8_t *)¶m->data.irk) != NVDS_OK) + { + ASSERT_ERR(0); + } + #endif // (NVDS_SUPPORT) + + memcpy(&app_env.peer_irk,¶m->data.irk.irk.key[0],sizeof(struct gapc_irk)); + for(int i = 0;idata.irk.irk.key[i]); + } + + //UART_PRINTF("addr tyep = %x\r\n",param->data.irk.addr.addr_type); + for(int i = 0;idata.irk.addr.addr.addr[i]); + } + + + + + } break; + + case (GAPC_PAIRING_FAILED): + { + //UART_PRINTF("gapc pairing failed\r\n"); + app_sec_env.peer_pairing_recv = false; + app_sec_env.peer_encrypt_recv = false; + appm_disconnect(0x13); + //app_sec_send_security_req(0); + } break; + + default: + { + ASSERT_ERR(0); + } break; + } + + return (KERNEL_MSG_CONSUMED); +} + +static int gapc_encrypt_req_ind_handler(kernel_msg_id_t const msgid, + struct gapc_encrypt_req_ind const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + if(kernel_timer_active(APP_SEND_SECURITY_REQ, TASK_APP)) + { + kernel_timer_clear(APP_SEND_SECURITY_REQ, TASK_APP); + } + + //UART_PRINTF("%s \r\n",__func__); + app_sec_env.peer_encrypt_recv = true; + #if (NVDS_SUPPORT) + // LTK value + struct gapc_ltk ltk; + // Length + uint8_t length = NVDS_LEN_LTK; + #endif // #if (NVDS_SUPPORT) + + // Prepare the GAPC_ENCRYPT_CFM message + struct gapc_encrypt_cfm *cfm = KERNEL_MSG_ALLOC(GAPC_ENCRYPT_CFM, + src_id, TASK_APP, + gapc_encrypt_cfm); + + cfm->found = false; + +#if (NVDS_SUPPORT && DIRECT_ADV_EN) + if (app_sec_env.bonded) +#else + if(1) +#endif + { + #if (NVDS_SUPPORT) + // Retrieve the required informations from NVDS + if (nvds_get(NVDS_TAG_LTK, &length, (uint8_t *)<k) == NVDS_OK) + { + // Check if the provided EDIV and Rand Nb values match with the stored values + if ((param->ediv == ltk.ediv) && + !memcmp(¶m->rand_nb.nb[0], <k.randnb.nb[0], sizeof(struct rand_nb))) + { + cfm->found = true; + cfm->key_size = 16; + memcpy(&cfm->ltk, <k.ltk, sizeof(struct gap_sec_key)); + } + /* + * else we are bonded with another device, disconnect the link + */ + } + else + { + //UART_PRINTF("read ltk fail\r\n"); + ASSERT_ERR(0); + } + #endif // #if (NVDS_SUPPORT) + + } + /* + * else the peer device is not known, an error should trigger a new pairing procedure. + */ + + // Send the message + kernel_msg_send(cfm); + + return (KERNEL_MSG_CONSUMED); +} + + +static int gapc_encrypt_ind_handler(kernel_msg_id_t const msgid, + struct gapc_encrypt_ind const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + // encryption/ re-encryption succeeded + //UART_PRINTF("%s \r\n",__func__); + #ifdef BLE_APP_AM0 + am0_app_send_audio_init(KERNEL_IDX_GET(src_id)); + #endif // BLE_APP_AM0 + + return (KERNEL_MSG_CONSUMED); +} + +static int app_sec_msg_dflt_handler(kernel_msg_id_t const msgid, + void *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + // Drop the message + + return (KERNEL_MSG_CONSUMED); +} + +/* + * LOCAL VARIABLE DEFINITIONS + **************************************************************************************** + */ + +/// Default State handlers definition +const struct kernel_msg_handler app_sec_msg_handler_list[] = +{ + // Note: first message is latest message checked by kernel so default is put on top. + {KERNEL_MSG_DEFAULT_HANDLER, (kernel_msg_func_t)app_sec_msg_dflt_handler}, + + {GAPC_BOND_REQ_IND, (kernel_msg_func_t)gapc_bond_req_ind_handler}, + {GAPC_BOND_IND, (kernel_msg_func_t)gapc_bond_ind_handler}, + + {GAPC_ENCRYPT_REQ_IND, (kernel_msg_func_t)gapc_encrypt_req_ind_handler}, + {GAPC_ENCRYPT_IND, (kernel_msg_func_t)gapc_encrypt_ind_handler}, +}; + +const struct kernel_state_handler app_sec_table_handler = + {&app_sec_msg_handler_list[0], (sizeof(app_sec_msg_handler_list)/sizeof(struct kernel_msg_handler))}; + +#endif //(BLE_APP_SEC) + +/// @} APP diff --git a/beken_os/beken378/driver/ble/ble_pub/modules/app/src/app_task.c b/beken_os/beken378/driver/ble/ble_pub/modules/app/src/app_task.c new file mode 100755 index 0000000..8ecd00e --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/modules/app/src/app_task.c @@ -0,0 +1,1619 @@ +/** + **************************************************************************************** + * + * @file appm_task.c + * + * @brief RW APP Task implementation + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @addtogroup APPTASK + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" // SW configuration + +#if (BLE_APP_PRESENT) +#include +#include "app_task.h" // Application Manager Task API +#include "application.h" // Application Manager Definition +#include "gapc_task.h" // GAP Controller Task API +#include "gapm_task.h" // GAP Manager Task API +#include "gattc_task.h" +#include "architect.h" // Platform Definitions + +#include "kernel_timer.h" // Kernel timer +//#include "kernel_task.h" + +#if (BLE_APP_FFF0) +#include "app_fff0.h" // fff0 Module Definition +#include "fff0s_task.h" +#endif //(BLE_APP_FFF0) + + +#if (BLE_APP_FFE0) +#include "app_ffe0.h" // ffe0 Module Definition +#endif //(BLE_APP_FFE0) + +#if (BLE_APP_COMM) +#include "app_comm.h" +#include "comm_task.h" +#endif + +#if BLE_APP_SDP +#include "sdp_service.h" +#include "sdp_service_task.h" +#include "app_sdp.h" +#endif + +#if (BLE_APP_ANCSC) +#include "app_ancsc.h" +#include "ancsc_task.h" +#endif //(BLE_APP_ANCSC) + +#if (BLE_APP_SEC) +#include "app_sec.h" // Security Module Definition +#endif //(BLE_APP_SEC) + +#if (BLE_APP_HT) +#include "app_ht.h" // Health Thermometer Module Definition +#include "htpt_task.h" +#endif //(BLE_APP_HT) + +#if (BLE_APP_DIS) +#include "app_dis.h" // Device Information Module Definition +#include "diss_task.h" +#endif //(BLE_APP_DIS) + +#if (BLE_APP_BATT) +#include "app_batt.h" // Battery Module Definition +#include "bass_task.h" +#endif //(BLE_APP_BATT) + +#if (BLE_APP_HID) +#include "app_hid.h" // HID Module Definition +#include "hogpd_task.h" +#endif //(BLE_APP_HID) + +#ifdef BLE_APP_AM0 +#include "am0_application.h" // Audio Mode 0 Application +#endif //defined(BLE_APP_AM0) + +#if (BLE_APP_OADS) +#include "app_oads.h" +#include "oads_task.h" +#endif //(BLE_APP_OADS) + +#if (DISPLAY_SUPPORT) +#include "app_display.h" // Application Display Definition +#endif //(DISPLAY_SUPPORT) + +#include "BK3435_reg.h" + +#include "reg_ble_em_cs.h" +#include "lld.h" +#include "ble.h" +#include "ble_pub.h" +#include "ble_api.h" + +//this flag use indicate adv timeout +static bool adv_timeout_flag = false; +/* + * LOCAL FUNCTION DEFINITIONS + **************************************************************************************** + */ +extern char *dev_str_name; +extern struct gap_bdaddr con_bdaddr; + +static uint8_t appm_get_handler(const struct kernel_state_handler *handler_list, + kernel_msg_id_t msgid, + void *param, + kernel_task_id_t src_id) +{ + // Counter + uint8_t counter; + + // Get the message handler function by parsing the message table + for (counter = handler_list->msg_cnt; 0 < counter; counter--) + { + + struct kernel_msg_handler handler = (struct kernel_msg_handler)(*(handler_list->msg_table + counter - 1)); + + if ((handler.id == msgid) || + (handler.id == KERNEL_MSG_DEFAULT_HANDLER)) + { + // If handler is NULL, message should not have been received in this state + ASSERT_ERR(handler.func); + + return (uint8_t)(handler.func(msgid, param, TASK_APP, src_id)); + } + } + + // If we are here no handler has been found, drop the message + return (KERNEL_MSG_CONSUMED); +} + +/* + * MESSAGE HANDLERS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief + * + * @param[in] msgid Id of the message received. + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (TASK_GAP). + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int app_adv_timeout_handler(kernel_msg_id_t const msgid, + void const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ +// UART_PRINTF("%s\r\n", __func__); + + adv_timeout_flag = true; + + // Stop advertising + appm_stop_advertising(); + + + return (KERNEL_MSG_CONSUMED); +} + +/** + **************************************************************************************** + * @brief Handles ready indication from the GAP. - Reset the stack + * + * @param[in] msgid Id of the message received. + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (TASK_GAP). + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int gapm_device_ready_ind_handler(kernel_msg_id_t const msgid, + void const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + // Application has not been initialized + ASSERT_ERR(kernel_state_get(dest_id) == APPM_INIT); + + // Reset the stack + struct gapm_reset_cmd* cmd = KERNEL_MSG_ALLOC(GAPM_RESET_CMD, + TASK_GAPM, TASK_APP, + gapm_reset_cmd); + + cmd->operation = GAPM_RESET; + + kernel_msg_send(cmd); + + return (KERNEL_MSG_CONSUMED); +} + +/** + **************************************************************************************** + * @brief Handles GAP manager command complete events. + * + * @param[in] msgid Id of the message received. + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (TASK_GAP). + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int gapm_cmp_evt_handler(kernel_msg_id_t const msgid, + struct gapm_cmp_evt const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + bk_printf("gapm_cmp_evt_handler operation = 0x%x, status = 0x%x \r\n", param->operation, param->status); + switch(param->operation) + { + // Reset completed + case (GAPM_RESET): + { + if(param->status == GAP_ERR_NO_ERROR) + { + // Set Device configuration + struct gapm_set_dev_config_cmd* cmd = KERNEL_MSG_ALLOC(GAPM_SET_DEV_CONFIG_CMD, + TASK_GAPM, TASK_APP, + gapm_set_dev_config_cmd); + // Set the operation + cmd->operation = GAPM_SET_DEV_CONFIG; + // Set the device role - Central + cmd->role = GAP_ROLE_ALL; + // Set Data length parameters + cmd->sugg_max_tx_octets = BLE_MIN_OCTETS; + cmd->sugg_max_tx_time = BLE_MIN_TIME; + + //cmd->max_mtu = 256; + //Do not support secure connections + cmd->pairing_mode = GAPM_PAIRING_LEGACY; + #if (BLE_APP_HID) + // Enable Slave Preferred Connection Parameters present + cmd->att_cfg = GAPM_MASK_ATT_SLV_PREF_CON_PAR_EN; + #endif //(BLE_APP_HID) + + #ifdef BLE_APP_AM0 + cmd->addr_type = GAPM_CFG_ADDR_HOST_PRIVACY; + cmd->audio_cfg = GAPM_MASK_AUDIO_AM0_SUP; + #endif // BLE_APP_AM0 + + // load IRK + memcpy(cmd->irk.key, app_env.loc_irk, KEY_LEN); + + // Send message + kernel_msg_send(cmd); + } + else + { + ASSERT_ERR(0); + } + } + break; + case (GAPM_PROFILE_TASK_ADD): + { +#if (BLE_APP_CLIENT) + if((BLE_ROLE_MASTER == ble_get_role_mode()) && (kernel_state_get(dest_id) == APPM_CONNECTED)) + { + uint8_t find; + find = sdp_enable_all_server_ntf_ind(1); + bk_printf("find = %d\r\n",find); + } +#endif + + // Add the next requested service + if (BLE_ROLE_MASTER != ble_get_role_mode()) + { + // Go to the ready state + kernel_state_set(TASK_APP, APPM_READY); + + if(param->status == GAP_ERR_NO_ERROR) + { + if(ble_event_cb) + { + ble_event_cb(BLE_CREATE_DB_OK, NULL); + } + } + else + { + if(ble_event_cb) + { + ble_event_cb(BLE_CREATE_DB_FAIL, NULL); + } + } + } + } + + break; + // Device Configuration updated + case (GAPM_SET_DEV_CONFIG): + { + ASSERT_INFO(param->status == GAP_ERR_NO_ERROR, param->operation, param->status); + + // Go to the create db state + // Add the first required service in the database + // and wait for the PROFILE_ADDED_IND + + kernel_state_set(TASK_APP, APPM_READY); + + if(ble_event_cb) + { + ble_event_cb(BLE_STACK_OK, NULL); + } + + } + break; + + case (GAPM_SCAN_ACTIVE): + case (GAPM_SCAN_PASSIVE): + { + if (param->status == GAP_ERR_CANCELED) + { + if (kernel_state_get(TASK_APP) == APPM_READY) + { + bk_printf("SCAN STOP CANCELED GAPM_SCAN_PASSIVE OK\r\n"); + } + + } + /* + if (kernel_state_get(TASK_APP) == APPM_WAIT_SCANNEND) + { + UART_PRINTF("CON CANCELED GAPM_SCAN_PASSIVE OK\r\n"); + kernel_state_set(TASK_APP, APPM_READY); + appm_start_connencting(con_bdaddr); + } + */ + } + break; + + case (GAPM_CONNECTION_DIRECT): + { + if (param->status == GAP_ERR_CANCELED) + { + if (kernel_state_get(TASK_APP) == APPM_CONNECTING) + { + kernel_state_set(TASK_APP, APPM_READY); + bk_printf("CANCELED GAPM_START_CONNECTION_CMD \r\n"); + } + } + } + break; + + case (GAPM_ADV_NON_CONN): + case (GAPM_ADV_UNDIRECT): + case (GAPM_ADV_DIRECT): + case (GAPM_UPDATE_ADVERTISE_DATA): + case (GAPM_ADV_DIRECT_LDC): + { + if (((param->status == GAP_ERR_CANCELED) || (param->status == GAP_ERR_TIMEOUT)) && (!adv_timeout_flag)) + { + kernel_state_set(TASK_APP, APPM_READY); + + } + //if device cancel advtising is adv timeout,then reset this flag + if((param->status == GAP_ERR_CANCELED) && (adv_timeout_flag == true)) + { + adv_timeout_flag = false; + } + } + break; + + + case (GAPM_RESOLV_ADDR): + { + // UART_PRINTF("GAPM_RESOLV_ADDR CMP status = %x\r\n",param->status); + if(param->status == GAP_ERR_NO_ERROR) + { + struct gapc_connection_cfm *cfm = KERNEL_MSG_ALLOC(GAPC_CONNECTION_CFM, + KERNEL_BUILD_ID(TASK_GAPC, app_env.conidx), TASK_APP, + gapc_connection_cfm); + +#if(BLE_APP_SEC) + cfm->auth = app_sec_get_bond_status() ? GAP_AUTH_REQ_NO_MITM_BOND : GAP_AUTH_REQ_NO_MITM_NO_BOND; +#else // !(BLE_APP_SEC) + cfm->auth = GAP_AUTH_REQ_NO_MITM_NO_BOND; +#endif // (BLE_APP_SEC) + } + } + break; + + default: + { + // Drop the message + } + break; + } + + return (KERNEL_MSG_CONSUMED); +} + + +static int gapc_get_dev_info_req_ind_handler(kernel_msg_id_t const msgid, + struct gapc_get_dev_info_req_ind const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + switch(param->req) + { + case GAPC_DEV_NAME: + { + struct gapc_get_dev_info_cfm * cfm = KERNEL_MSG_ALLOC_DYN(GAPC_GET_DEV_INFO_CFM, + src_id, dest_id, + gapc_get_dev_info_cfm, APP_DEVICE_NAME_MAX_LEN); + cfm->req = param->req; + cfm->info.name.length = appm_get_dev_name(cfm->info.name.value); + + // Send message + kernel_msg_send(cfm); + } break; + + case GAPC_DEV_APPEARANCE: + { + // Allocate message + struct gapc_get_dev_info_cfm *cfm = KERNEL_MSG_ALLOC(GAPC_GET_DEV_INFO_CFM, + src_id, dest_id, + gapc_get_dev_info_cfm); + cfm->req = param->req; + // Set the device appearance + #if (BLE_APP_HT) + // Generic Thermometer - TODO: Use a flag + cfm->info.appearance = 728; + #elif (BLE_APP_HID) + // HID keyboard + cfm->info.appearance = 961; + #else + // No appearance + cfm->info.appearance = 0; + #endif + + // Send message + kernel_msg_send(cfm); + } break; + + case GAPC_DEV_SLV_PREF_PARAMS: + { + // Allocate message + struct gapc_get_dev_info_cfm *cfm = KERNEL_MSG_ALLOC(GAPC_GET_DEV_INFO_CFM, + src_id, dest_id, + gapc_get_dev_info_cfm); + cfm->req = param->req; + // Slave preferred Connection interval Min + cfm->info.slv_params.con_intv_min = 8; + // Slave preferred Connection interval Max + cfm->info.slv_params.con_intv_max = 10; + // Slave preferred Connection latency + if (BLE_ROLE_MASTER == ble_get_role_mode()) + { + cfm->info.slv_params.slave_latency = 0; + } + else + { + cfm->info.slv_params.slave_latency = 180; + } + // Slave preferred Link supervision timeout + cfm->info.slv_params.conn_timeout = 600; // 6s (600*10ms) + + // Send message + kernel_msg_send(cfm); + } break; + + default: /* Do Nothing */ + break; + } + + + return (KERNEL_MSG_CONSUMED); +} +/** + **************************************************************************************** + * @brief Handles GAPC_SET_DEV_INFO_REQ_IND message. + * + * @param[in] msgid Id of the message received. + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (TASK_GAP). + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int gapc_set_dev_info_req_ind_handler(kernel_msg_id_t const msgid, + struct gapc_set_dev_info_req_ind const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + // Set Device configuration + struct gapc_set_dev_info_cfm* cfm = KERNEL_MSG_ALLOC(GAPC_SET_DEV_INFO_CFM, src_id, dest_id, + gapc_set_dev_info_cfm); + // Reject to change parameters + cfm->status = GAP_ERR_REJECTED; + cfm->req = param->req; + // Send message + kernel_msg_send(cfm); + + return (KERNEL_MSG_CONSUMED); +} + +/** + **************************************************************************************** + * @brief Handles connection complete event from the GAP. Enable all required profiles + * + * @param[in] msgid Id of the message received. + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (TASK_GAP). + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int gapc_connection_req_ind_handler(kernel_msg_id_t const msgid, + struct gapc_connection_req_ind const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + bk_printf("%s\r\n", __func__); + adv_timeout_flag = false; + + app_env.conidx = KERNEL_IDX_GET(src_id); + // Check if the received Connection Handle was valid + if (app_env.conidx != GAP_INVALID_CONIDX) + { + // Retrieve the connection info from the parameters + app_env.conhdl = param->conhdl; + +#if (BLE_APP_CLIENT) + if (BLE_ROLE_MASTER == ble_get_role_mode()) + { + if (!sdp_need_dis_flag) + { + kernel_state_set(dest_id, APPM_SDP_DISCOVERING); + sdp_discover_all_service(); + } + else + { + kernel_state_set(dest_id, APPM_CONNECTED); + + sdp_prf_register_all_atthdl2gatt(); + + sdp_enable_all_server_ntf_ind(1); + } + } + else +#endif + { + if (kernel_timer_active(APP_ADV_TIMEOUT_TIMER, TASK_APP)) + { + kernel_timer_clear(APP_ADV_TIMEOUT_TIMER, TASK_APP); + } + +#if 1 + // Send connection confirmation + struct gapc_connection_cfm *cfm = KERNEL_MSG_ALLOC(GAPC_CONNECTION_CFM, + KERNEL_BUILD_ID(TASK_GAPC, app_env.conidx), TASK_APP, + gapc_connection_cfm); + + #if(BLE_APP_SEC) + cfm->auth = app_sec_get_bond_status() ? GAP_AUTH_REQ_NO_MITM_BOND : GAP_AUTH_REQ_NO_MITM_NO_BOND; + #else // !(BLE_APP_SEC) + cfm->auth = GAP_AUTH_REQ_NO_MITM_NO_BOND; + #endif // (BLE_APP_SEC) + // Send the message + kernel_msg_send(cfm); +#endif + #if DISPLAY_SUPPORT + // Update displayed information + app_display_set_adv(false); + app_display_set_con(true); + #endif //(DISPLAY_SUPPORT) + + /*-------------------------------------------------------------- + * ENABLE REQUIRED PROFILES + *--------------------------------------------------------------*/ + #if (BLE_APP_BATT) + // Enable Battery Service + app_batt_enable_prf(app_env.conhdl); + #endif //(BLE_APP_BATT) + #if (BLE_APP_HID) + // Enable HID Service + app_hid_enable_prf(app_env.conhdl); + #endif //(BLE_APP_HID) + + // UART_PRINTF("peer_addr_type = 0x%x\r\n",param->peer_addr_type); + // UART_PRINTF("peer_addr = "); + // for(uint8_t i = 0; i < sizeof(bd_addr_t);i ++) + // { + // UART_PRINTF("%02x",param->peer_addr.addr[i]); + // } + // UART_PRINTF("\r\n"); + + // We are now in connected State + kernel_state_set(dest_id, APPM_CONNECTED); + + + #if (BLE_APP_SEC) + //if device not bond with local, send bond request + if(!app_sec_get_bond_status()) + { + //UART_PRINTF("app_sec_get_bond_status = 0x0\r\n"); + //kernel_timer_set(APP_SEND_SECURITY_REQ,TASK_APP,80); // 80 + } + else + { + ;// UART_PRINTF("app_sec_get_bond_status = 0x1\r\n"); + } + + #endif + + #if UPDATE_CONNENCT_PARAM + //kernel_timer_set(APP_PARAM_UPDATE_REQ_IND,TASK_APP,100); + #endif + + //test timer + //kernel_timer_set(APP_PERIOD_TEST_TIMER, TASK_APP, 2000); + + //set short connect + // if(app_get_mode().target_mode == CONN_MODE_SHORT) + // { + // kernel_timer_set(APP_DISCONNECT_TIMER, TASK_APP,app_get_mode().target_timeout); + // } + } + + if(ble_event_cb) + { + ble_event_cb(BLE_CONNECT, (void *)param); + } + + // ble_update_connection(); + + } + // jiangji master continue scan + else if (BLE_ROLE_SLAVE == ble_get_role_mode()) + { +#if (BLE_APP_SEC) + // No connection has been establish, restart advertising + if(app_sec_get_bond_status()) + { + //if device has bonded, then start direct adv + appm_start_direct_dvertising(); + } + else +#endif + { + //device not bonded, start general adv + appm_start_advertising(); + } + } + else + { + bk_printf("connect fail\r\n"); + } + + + + return (KERNEL_MSG_CONSUMED); +} + +/** + **************************************************************************************** + * @brief Handles GAP controller command complete events. + * + * @param[in] msgid Id of the message received. + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (TASK_GAP). + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int gapc_cmp_evt_handler(kernel_msg_id_t const msgid, + struct gapc_cmp_evt const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + bk_printf("gapc_cmp_evt_handler operation = 0x%x, status = 0x%x\r\n",param->operation, param->status); + switch(param->operation) + { + case (GAPC_UPDATE_PARAMS): + { + if (param->status != GAP_ERR_NO_ERROR) + { + //appm_disconnect(); + } + } break; + case (GAPC_BOND): // 0xa + { + if (param->status != GAP_ERR_NO_ERROR) + { + ;//UART_PRINTF("GAPC_BOND fail !\r\n"); + } + else if (BLE_ROLE_SLAVE == ble_get_role_mode()) + { + //UART_PRINTF("GAPC_BOND ok !\r\n"); + #if (BLE_APP_ANCSC) + // Enable ANCS Service + app_ancsc_enable_prf(app_env.conhdl); + #endif //(BLE_APP_ANCSC) + } + }break; + case (GAPC_ENCRYPT): // 0xb + { + if (param->status != GAP_ERR_NO_ERROR) + { + ;//UART_PRINTF("GAPC_ENCRYPT Start fail !\r\n"); + } + else if (BLE_ROLE_SLAVE == ble_get_role_mode()) + { + #if (BLE_APP_ANCSC) + // Enable ANCS Service + app_ancsc_enable_prf(app_env.conhdl); + #endif //(BLE_APP_ANCSC) + } + }break; + default: + break; + } + + return (KERNEL_MSG_CONSUMED); +} + +/** + **************************************************************************************** + * @brief Handles disconnection complete event from the GAP. + * + * @param[in] msgid Id of the message received. + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (TASK_GAP). + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int gapc_disconnect_ind_handler(kernel_msg_id_t const msgid, + struct gapc_disconnect_ind const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + + bk_printf("disconnect link reason = 0x%x, conhdl:0x%x\r\n",param->reason, param->conhdl); + if (BLE_ROLE_SLAVE == ble_get_role_mode()) + { +#if UPDATE_CONNENCT_PARAM + if(kernel_timer_active(APP_PARAM_UPDATE_REQ_IND, TASK_APP)) + { + kernel_timer_clear(APP_PARAM_UPDATE_REQ_IND, TASK_APP); + } +#endif + //test + if(kernel_timer_active(APP_PERIOD_TEST_TIMER, TASK_APP)) + { + kernel_timer_clear(APP_PERIOD_TEST_TIMER,TASK_APP); + } + } + + // Go to the ready state + kernel_state_set(TASK_APP, APPM_READY); + +#if (BLE_APP_HT) + // Stop interval timer + app_stop_timer(); +#endif + +#if (DISPLAY_SUPPORT) + // Update Connection State screen + app_display_set_con(false); +#endif + +#if (BLE_APP_SEC) + app_sec_init(); +#endif + +#if (BLE_APP_HID) + app_hid_init(); +#endif + + if (BLE_ROLE_SLAVE == ble_get_role_mode()) + { + ble_set_role_mode(BLE_ROLE_NONE); + adv_timeout_flag = false; + //device not bonded, start general adv + //appm_start_advertising(); + } + else if(BLE_ROLE_MASTER == ble_get_role_mode()) + { + ble_set_role_mode(BLE_ROLE_NONE); + } + + if(ble_event_cb) + { + ble_event_cb(BLE_DISCONNECT, (void*)(&(param->reason))); + } + + return (KERNEL_MSG_CONSUMED); +} + + +/******************************************************************************* + * Function: app_period_timer_handler + * Description: app period timer process + * Input: msgid -Id of the message received. + * param -Pointer to the parameters of the message. + * dest_id -ID of the receiving task instance (TASK_GAP). + * ID of the sending task instance. + * Return: If the message was consumed or not. + * Others: void +*******************************************************************************/ +static int app_period_timer_handler(kernel_msg_id_t const msgid, + void const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + kernel_timer_set(APP_PERIOD_TIMER,TASK_APP,20); + + //gpio_triger(0x15); + + + return KERNEL_MSG_CONSUMED; + +} + + + +static int app_period_test_handler(kernel_msg_id_t const msgid, + void const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ +#if 0 + uint8_t buf[8]; + memset(buf, 0x0, 8); + + switch(send_count) + { + case 0: + buf[2] = 0x4f; + send_count++; + app_hid_send_report(buf, 8); + printf_val(buf); + kernel_timer_set(APP_PERIOD_TEST_TIMER,TASK_APP,10); + break; + case 1: + buf[2] = 0x50; + send_count++; + app_hid_send_report(buf, 8); + printf_val(buf); + kernel_timer_set(APP_PERIOD_TEST_TIMER,TASK_APP,16); + break; + + case 2: + send_count++; + buf[2] = 0x4f; + buf[3] = 0x50; + app_hid_send_report(buf, 8); + printf_val(buf); + buf[3] = 0x0; + app_hid_send_report(buf, 8); + printf_val(buf); + kernel_timer_set(APP_PERIOD_TEST_TIMER,TASK_APP,46); + break; + + case 3: + memset(buf, 0x0, 8); + app_hid_send_report(buf, 8); + printf_val(buf); + buf[2] = 0x50; + app_hid_send_report(buf, 8); + printf_val(buf); + send_count++; + kernel_timer_set(APP_PERIOD_TEST_TIMER,TASK_APP,45); + break; + + case 4: + memset(buf, 0x0, 8); + app_hid_send_report(buf, 8); + printf_val(buf); + buf[2] = 0x4f; + app_hid_send_report(buf, 8); + printf_val(buf); + send_count++; + kernel_timer_set(APP_PERIOD_TEST_TIMER,TASK_APP,130); + break; + + case 5: + memset(buf, 0x0, 8); + app_hid_send_report(buf, 8); + printf_val(buf); + buf[2] = 0x50; + app_hid_send_report(buf, 8); + printf_val(buf); + send_count++; + kernel_timer_set(APP_PERIOD_TEST_TIMER,TASK_APP,3); + break; + + case 6: + send_count= 0; + memset(buf, 0x0, 8); + app_hid_send_report(buf, 8); + printf_val(buf); + kernel_timer_clear(APP_PERIOD_TEST_TIMER, TASK_APP); + break; + + default: + break; + } + + +/* + if(send_count) + { + buf[2] = 0x4f; + app_hid_send_report(buf, 8); + } + else + { + buf[2] = 0x0; + send_count = true; + app_hid_send_report(buf, 8); + } + kernel_timer_set(APP_PERIOD_TEST_TIMER,TASK_APP,20); +*/ +#endif // + return KERNEL_MSG_CONSUMED; +} + + +/** + **************************************************************************************** + * @brief Handles profile add indication from the GAP. + * + * @param[in] msgid Id of the message received. + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (TASK_GAP). + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int gapm_profile_added_ind_handler(kernel_msg_id_t const msgid, + struct gapm_profile_added_ind *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + uint8_t state = kernel_state_get(dest_id); + + if (state == APPM_CREATE_DB) + { + switch (param->prf_task_id) + { + #if defined (BLE_APP_AM0) + case (TASK_ID_AM0_HAS): + { + am0_app_set_prf_task(param->prf_task_nb); + } break; + #endif + default: + break; + } + } + else + { + ASSERT_INFO(0, state, src_id); + } + + return KERNEL_MSG_CONSUMED; +} + + + +/** + **************************************************************************************** + * @brief Handles reception of all messages sent from the lower layers to the application + * @param[in] msgid Id of the message received. + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int appm_msg_handler(kernel_msg_id_t const msgid, + void *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + // Retrieve identifier of the task from received message + kernel_task_id_t src_task_id = BLE_MSG_T(msgid); + // Message policy + uint8_t msg_pol = KERNEL_MSG_CONSUMED; + + switch (src_task_id) + { + case (TASK_ID_GAPC): + { + #if (BLE_APP_SEC) + if ((msgid >= GAPC_BOND_CMD) && + (msgid <= GAPC_SECURITY_IND)) + { + // Call the Security Module + msg_pol = appm_get_handler(&app_sec_table_handler, msgid, param, src_id); + } + #endif //(BLE_APP_SEC) + // else drop the message + } break; + + case (TASK_ID_GATTC): + { + // Service Changed - Drop + } break; + + #if (BLE_APP_FFF0) + case (TASK_ID_FFF0S): + { + // Call the Health Thermometer Module + msg_pol = appm_get_handler(&app_fff0_table_handler, msgid, param, src_id); + } break; + #endif //(BLE_APP_FFF0) + + #if (BLE_APP_FFE0) + case (TASK_ID_FFE0S): + { + // Call the Health Thermometer Module + msg_pol = appm_get_handler(&app_ffe0_table_handler, msgid, param, src_id); + } break; + #endif //(BLE_APP_FFE0) + + #if (BLE_APP_COMM) + case (TASK_ID_COMMON): + { + // Call the Health Thermometer Module + msg_pol = appm_get_handler(&app_comm_table_handler, msgid, param, src_id); + } break; + #endif //(BLE_APP_COMM) + + #if (BLE_APP_ANCSC) + case (TASK_ID_ANCSC): + { + // Call the Health Thermometer Module + msg_pol = appm_get_handler(&app_ancsc_table_handler, msgid, param, src_id); + } break; + #endif //(BLE_APP_ANCSC) + + #if (BLE_APP_HT) + case (TASK_ID_HTPT): + { + // Call the Health Thermometer Module + msg_pol = appm_get_handler(&app_ht_table_handler, msgid, param, src_id); + } break; + #endif //(BLE_APP_HT) + + #if (BLE_APP_DIS) + case (TASK_ID_DISS): + { + // Call the Device Information Module + msg_pol = appm_get_handler(&app_dis_table_handler, msgid, param, src_id); + } break; + #endif //(BLE_APP_DIS) + + + #if (BLE_APP_HID) + case (TASK_ID_HOGPD): + { + // Call the HID Module + msg_pol = appm_get_handler(&app_hid_table_handler, msgid, param, src_id); + } break; + #endif //(BLE_APP_HID) + + #if (BLE_APP_BATT) + case (TASK_ID_BASS): + { + // Call the Battery Module + msg_pol = appm_get_handler(&app_batt_table_handler, msgid, param, src_id); + } break; + #endif //(BLE_APP_BATT) + + #if defined(BLE_APP_AM0) + case (TASK_ID_AM0): + { + // Call the Audio Mode 0 Module + msg_pol = appm_get_handler(&am0_app_table_handler, msgid, param, src_id); + } break; + case (TASK_ID_AM0_HAS): + { + // Call the Audio Mode 0 Module + msg_pol = appm_get_handler(&am0_app_has_table_handler, msgid, param, src_id); + } break; + #endif // defined(BLE_APP_AM0) + + #if (BLE_APP_OADS) + case (TASK_ID_OADS): + { + // Call the Health Thermometer Module + msg_pol = appm_get_handler(&app_oads_table_handler, msgid, param, src_id); + } break; + #endif //(BLE_APP_OADS) + #if (BLE_APP_SDP) + case (TASK_ID_SDP): + { + // Call the SDP Module + msg_pol = appm_get_handler(&sdp_default_handler, msgid, param, src_id); + } + break; + #endif //(TASK_ID_SDP) + + default: + if (BLE_ROLE_SLAVE == ble_get_role_mode()) + { + #if (BLE_APP_HT) + if (msgid == APP_HT_MEAS_INTV_TIMER) + { + msg_pol = appm_get_handler(&app_ht_table_handler, msgid, param, src_id); + } + #endif //(BLE_APP_HT) + + #if (BLE_APP_HID) + if (msgid == APP_HID_MOUSE_TIMEOUT_TIMER) + { + msg_pol = appm_get_handler(&app_hid_table_handler, msgid, param, src_id); + } + #endif //(BLE_APP_HID) + } break; + } + + return (msg_pol); +} + + +/******************************************************************************* + * Function: gapc_update_conn_param_req_ind_handler + * Description: Update request command processing from slaver connection parameters + * Input: msgid -Id of the message received. + * param -Pointer to the parameters of the message. + * dest_id -ID of the receiving task instance + * src_id -ID of the sending task instance. + * Return: If the message was consumed or not. + * Others: void +*******************************************************************************/ +static int gapc_update_conn_param_req_ind_handler (kernel_msg_id_t const msgid, + const struct gapc_param_update_req_ind *param, + kernel_task_id_t const dest_id, kernel_task_id_t const src_id) +{ + //UART_PRINTF("slave send param_update_req\r\n"); + struct gapc_conn_param up_param; + + up_param.intv_min = BLE_UAPDATA_MIN_INTVALUE; + up_param.intv_max = BLE_UAPDATA_MAX_INTVALUE; + up_param.latency = BLE_UAPDATA_LATENCY; + up_param.time_out = BLE_UAPDATA_TIMEOUT; + + appm_update_param(&up_param); + + return KERNEL_MSG_CONSUMED; +} + + +/******************************************************************************* + * Function: gapc_le_pkt_size_ind_handler + * Description: GAPC_LE_PKT_SIZE_IND + * Input: msgid -Id of the message received. + * param -Pointer to the parameters of the message. + * dest_id -ID of the receiving task instance + * src_id -ID of the sending task instance. + * Return: If the message was consumed or not. + * Others: void +*******************************************************************************/ +static int gapc_le_pkt_size_ind_handler (kernel_msg_id_t const msgid, + const struct gapc_le_pkt_size_ind *param, + kernel_task_id_t const dest_id, kernel_task_id_t const src_id) +{ + // UART_PRINTF("%s \r\n", __func__); + + //UART_PRINTF("1max_rx_octets = %d\r\n",param->max_rx_octets); + //UART_PRINTF("1max_rx_time = %d\r\n",param->max_rx_time); + //UART_PRINTF("1max_tx_octets = %d\r\n",param->max_tx_octets); + //UART_PRINTF("1max_tx_time = %d\r\n",param->max_tx_time); + + return KERNEL_MSG_CONSUMED; +} + +/** + **************************************************************************************** + * @brief GAPC_PARAM_UPDATED_IND + * @param[in] msgid Id of the message received. + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int gapc_param_updated_ind_handler (kernel_msg_id_t const msgid, + const struct gapc_param_updated_ind *param, + kernel_task_id_t const dest_id, kernel_task_id_t const src_id) +{ + return KERNEL_MSG_CONSUMED; +} + + + + +/** + **************************************************************************************** + * @brief GATTC_MTU_CHANGED_IND + * @param[in] msgid Id of the message received. + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int gattc_mtu_changed_ind_handler(kernel_msg_id_t const msgid, + struct gattc_mtu_changed_ind const *ind, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + //UART_PRINTF("%s \r\n",__func__); + //UART_PRINTF("ind->mtu = %d,seq = %d\r\n",ind->mtu,ind->seq_num); + + if(ble_event_cb) + { + ble_event_cb(BLE_MTU_CHANGE, (void*)(&(ind->mtu))); + } + + return (KERNEL_MSG_CONSUMED); +} +/** + **************************************************************************************** + * @brief GATTC_EXC_MTU_CMD + * @param[in] msgid Id of the message received. + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int gattc_mtu_exchange_req_handler(kernel_msg_id_t const msgid, + struct gattc_exc_mtu_cmd const *req, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + bk_printf("gattc_mtu_exchange_req_handler\r\n"); + struct gattc_exc_mtu_cmd *cmd = KERNEL_MSG_ALLOC(GATTC_EXC_MTU_CMD, + KERNEL_BUILD_ID(TASK_GATTC, app_env.conidx), + TASK_APP,gattc_exc_mtu_cmd); + cmd->operation = GATTC_MTU_EXCH; + cmd->seq_num = 0; + kernel_msg_send(cmd); + + return (KERNEL_MSG_CONSUMED); +} + + +ble_scan_list_t ble_scan_list; +uint8_t adv_count = 0; + +static int gapm_adv_report_ind_handler(kernel_msg_id_t const msgid, + struct adv_report const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + //jiangji update + int i = 0; +#if (BLE_APP_CLIENT) + if(adv_count < appm_get_max_scan_nums()) + { + for (i = 0; i < adv_count; i++) + { + if(0 == memcmp(&ble_scan_list.info[i].adv_addr.addr[0], param->adv_addr.addr, 6)) + { + break; + } + } + + if(i == adv_count) + { + bk_printf("\r\n\r\n##################################\r\n"); + ble_scan_list.info[adv_count].addr_type = param->adv_addr_type; + ble_scan_list.info[adv_count].adv_type = param->evt_type; + ble_scan_list.info[adv_count].number = adv_count; + ble_scan_list.info[adv_count].rssi = param->rssi; + memcpy(&ble_scan_list.info[adv_count].adv_addr.addr[0],param->adv_addr.addr, 6); + bk_printf("adv number = %d\r\n", ble_scan_list.info[adv_count].number); + bk_printf("adv type = %x :%s\r\n",ble_scan_list.info[adv_count].adv_type, + (param->evt_type == ADV_CONN_UNDIR) ? "ADV_CONN_UNDIR" :(param->evt_type == ADV_CONN_DIR)? "ADV_CONN_DIR" : + (param->evt_type == ADV_DISC_UNDIR)? "ADV_DISC_UNDIR" : (param->evt_type == ADV_NONCONN_UNDIR)? "ADV_NONCONN_UNDIR": "Unknow"); + bk_printf("adv rssi = %d\r\n", (int8_t)ble_scan_list.info[adv_count].rssi); + bk_printf("adv addr = %02x:%02x:%02x:%02x:%02x:%02x\r\n", + ble_scan_list.info[adv_count].adv_addr.addr[0],ble_scan_list.info[adv_count].adv_addr.addr[1],ble_scan_list.info[adv_count].adv_addr.addr[2], + ble_scan_list.info[adv_count].adv_addr.addr[3],ble_scan_list.info[adv_count].adv_addr.addr[4],ble_scan_list.info[adv_count].adv_addr.addr[5]); + bk_printf("adv addr type = %02x\r\n",ble_scan_list.info[adv_count].addr_type); + + adv_count++; + bk_printf("\r\n##################################\r\n"); + } + } + if (ble_recv_adv_cb) + { + + (*ble_recv_adv_cb)((unsigned char*)param->data, param->data_len); + } + +#endif + + return (KERNEL_MSG_CONSUMED); +} + +#if (SECURE_CONNECTIONS) +static int gapm_gen_dh_key_ind_handler(kernel_msg_id_t const msgid, + struct gapm_gen_dh_key_ind const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + int msg_status = KERNEL_MSG_CONSUMED; + struct ble_gen_dh_key_ind ind; + + ind.result = (uint8_t *)(&(param->result[0])); + ind.len = GAP_P256_KEY_LEN; + + if(ble_event_cb) + { + ble_event_cb(BLE_GEN_DH_KEY, (void *)&ind); + } + + return (msg_status); +} + +static int gapm_get_key_ind_handler(kernel_msg_id_t const msgid, + struct gapm_get_key_ind const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + int msg_status = KERNEL_MSG_CONSUMED; + struct ble_get_key_ind ind; + + ind.pri_key = (uint8_t *)&(param->pri_key[0]); + ind.pri_len = GAP_P256_KEY_LEN; + ind.pub_key_x = (uint8_t *)&(param->pub_key_x[0]); + ind.pub_x_len = GAP_P256_KEY_LEN; + ind.pub_key_y = (uint8_t *)&(param->pub_key_y[0]); + ind.pub_y_len = GAP_P256_KEY_LEN; + + if(ble_event_cb) + { + ble_event_cb(BLE_GET_KEY, (void *)&ind); + } + + return (msg_status); +} +#endif + +/** + **************************************************************************************** + * @brief GAPC_PARAM_UPDATE_REQ_IND + * @param[in] msgid Id of the message received. + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int gapc_param_update_req_ind_handler(kernel_msg_id_t const msgid, + struct gapc_param_update_req_ind const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + //UART_PRINTF("%s \r\n", __func__); + // Prepare the GAPC_PARAM_UPDATE_CFM message + struct gapc_param_update_cfm *cfm = KERNEL_MSG_ALLOC(GAPC_PARAM_UPDATE_CFM, + src_id, dest_id, + gapc_param_update_cfm); + + //cfm->accept = false; + cfm->ce_len_max = 0xffff; + cfm->ce_len_min = 0xffff; + cfm->accept = true; + + // Send message + kernel_msg_send(cfm); + + return (KERNEL_MSG_CONSUMED); +} + +/** + **************************************************************************************** + * @brief app_adv_enable_handler + * + * @param[in] msgid Id of the message received. + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (TASK_GAP). + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int app_adv_enable_handler(kernel_msg_id_t const msgid, + void const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + if(kernel_state_get(TASK_APP) == APPM_CONNECTED) + { + return KERNEL_MSG_CONSUMED; + } + //UART_PRINTF("%s\r\n", __func__); + + // Restart Advertising + + { + //device not bonded, start general adv + appm_start_advertising(); + } + + return (KERNEL_MSG_CONSUMED); +} + + +/** + **************************************************************************************** + * @brief app_disconnect_timer_handler + * + * @param[in] msgid Id of the message received. + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (TASK_GAP). + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int app_disconnect_timer_handler(kernel_msg_id_t const msgid, + void const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + //UART_PRINTF("%s\r\n", __func__); + + if(kernel_state_get(TASK_APP) == APPM_CONNECTED) + { + appm_disconnect(0x13); + } + + return (KERNEL_MSG_CONSUMED); +} + + + + + + +/** + **************************************************************************************** + * @brief APP_ENCODE_IND + * + * @param[in] msgid Id of the message received. + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (TASK_GAP). + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int app_sbc_encode_handler(kernel_msg_id_t const msgid, + struct sbc_encode const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + + /* + sbc_env.stream[3] = app_hid_env.encode_cnt++; //for test + + //Store the data to be encoded into the loop buffer + store_encode_data(&sbc_env.stream[3]); + */ + + + + return (KERNEL_MSG_CONSUMED); +} + +#if (BLE_APP_SEC) +/** + **************************************************************************************** + * @brief APP_SEND_SECURITY_REQ + * @param[in] msgid Id of the message received. + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int gapc_send_security_req_handler( const kernel_msg_id_t msgid, const void *param, + const kernel_task_id_t dest_id, const kernel_task_id_t src_id) +{ + appm_send_seurity_req(); + + return KERNEL_MSG_CONSUMED; +} +#endif + +#if (BLE_APP_CLIENT) +static int gattc_cmp_evt_handler(kernel_msg_id_t const msgid, + struct gattc_cmp_evt const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + bk_printf("found %s operation = 0x%x,status = 0x%x,param->seq_num = 0x%x\r\n",__func__,param->operation,param->status,param->seq_num); + if(param->operation == GATTC_SDP_DISC_SVC_ALL) + { + if(param->status == ATT_ERR_NO_ERROR) + { + kernel_state_set(dest_id, APPM_CONNECTED); + sdp_need_dis_flag = 1; + } + } + if((param->operation == GATTC_WRITE) && (param->seq_num == 0xa5) ) + { + uint8_t find; + find = sdp_enable_all_server_ntf_ind(0); + if(sdp_need_dis_flag == 1) + { + kernel_state_set(dest_id, APPM_CONNECTED); + } + bk_printf("find = %d\r\n",find); + if(find == 0) + { + //set_flash_clk(0x8); + } + } + return (KERNEL_MSG_CONSUMED); +} + + + +static int gattc_sdp_svc_ind_handler(kernel_msg_id_t const msgid, + struct gattc_sdp_svc_ind const *ind, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + sdp_extract_svc_info(ind); + + return (KERNEL_MSG_CONSUMED); +} +#endif + +/* + * GLOBAL VARIABLES DEFINITION + **************************************************************************************** + */ + +/* Default State handlers definition. */ +const struct kernel_msg_handler appm_default_state[] = +{ + // Note: first message is latest message checked by kernel so default is put on top. + {KERNEL_MSG_DEFAULT_HANDLER, (kernel_msg_func_t)appm_msg_handler}, + {APP_ADV_TIMEOUT_TIMER, (kernel_msg_func_t)app_adv_timeout_handler}, + {GAPM_DEVICE_READY_IND, (kernel_msg_func_t)gapm_device_ready_ind_handler}, + {GAPM_CMP_EVT, (kernel_msg_func_t)gapm_cmp_evt_handler}, + {GAPC_GET_DEV_INFO_REQ_IND, (kernel_msg_func_t)gapc_get_dev_info_req_ind_handler}, + {GAPC_SET_DEV_INFO_REQ_IND, (kernel_msg_func_t)gapc_set_dev_info_req_ind_handler}, + {GAPC_CONNECTION_REQ_IND, (kernel_msg_func_t)gapc_connection_req_ind_handler}, + {GAPC_CMP_EVT, (kernel_msg_func_t)gapc_cmp_evt_handler}, + {GAPC_DISCONNECT_IND, (kernel_msg_func_t)gapc_disconnect_ind_handler}, + {GAPM_PROFILE_ADDED_IND, (kernel_msg_func_t)gapm_profile_added_ind_handler}, + {GAPC_LE_PKT_SIZE_IND, (kernel_msg_func_t)gapc_le_pkt_size_ind_handler}, + {GAPC_PARAM_UPDATED_IND, (kernel_msg_func_t)gapc_param_updated_ind_handler}, + {GATTC_MTU_CHANGED_IND, (kernel_msg_func_t)gattc_mtu_changed_ind_handler}, + {GAPM_ADV_REPORT_IND, (kernel_msg_func_t)gapm_adv_report_ind_handler}, +#if (SECURE_CONNECTIONS) + {GAPM_GEN_DH_KEY_IND, (kernel_msg_func_t) gapm_gen_dh_key_ind_handler}, + {GAPM_GET_KEY_IND, (kernel_msg_func_t) gapm_get_key_ind_handler}, +#endif + {GAPC_PARAM_UPDATE_REQ_IND, (kernel_msg_func_t)gapc_param_update_req_ind_handler}, +#if (BLE_APP_CLIENT) + {GATTC_CMP_EVT, (kernel_msg_func_t)gattc_cmp_evt_handler}, + {GATTC_SDP_SVC_IND, (kernel_msg_func_t)gattc_sdp_svc_ind_handler}, +#endif + {APP_PARAM_UPDATE_REQ_IND, (kernel_msg_func_t)gapc_update_conn_param_req_ind_handler}, + {APP_ADV_ENABLE_TIMER, (kernel_msg_func_t)app_adv_enable_handler}, + {APP_PERIOD_TIMER, (kernel_msg_func_t)app_period_timer_handler}, + {APP_GATTC_EXC_MTU_CMD, (kernel_msg_func_t)gattc_mtu_exchange_req_handler}, +#if (BLE_APP_SEC) + {APP_SEND_SECURITY_REQ, (kernel_msg_func_t)gapc_send_security_req_handler}, +#endif + {APP_ENCODE_IND, (kernel_msg_func_t)app_sbc_encode_handler}, + {APP_DISCONNECT_TIMER, (kernel_msg_func_t)app_disconnect_timer_handler}, + + {APP_PERIOD_TEST_TIMER, (kernel_msg_func_t)app_period_test_handler}, +}; + +/* Specifies the message handlers that are common to all states. */ +const struct kernel_state_handler appm_default_handler = KERNEL_STATE_HANDLER(appm_default_state); + +/* Defines the place holder for the states of all the task instances. */ +kernel_state_t appm_state[APP_IDX_MAX]; + +#endif //(BLE_APP_PRESENT) + +/// @} APPTASK diff --git a/beken_os/beken378/driver/ble/ble_pub/modules/common/api/RomCallFlash.h b/beken_os/beken378/driver/ble/ble_pub/modules/common/api/RomCallFlash.h new file mode 100755 index 0000000..e9e93fa --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/modules/common/api/RomCallFlash.h @@ -0,0 +1,80 @@ +#ifndef __ROM_CALL_FLASH_H_ +#define __ROM_CALL_FLASH_H_ + +#include "gapm_task.h" + +#include "rwble_hl.h" +#include "prf.h" +#include "lld_sleep.h" +#include "rwip.h" + +#include +#include "kernel_msg.h" +#include "kernel_task.h" +#include "kernel_env.h" // kernel environment +#include "common_bt.h" // common bt definitions + +extern uint8_t system_mode; +/* +struct flash_for_rom_func_tag +{ + kernel_task_id_t (*prf_get_id_from_task)(kernel_msg_id_t task); + kernel_task_id_t (*prf_get_task_from_id)(kernel_msg_id_t id); + + void (*prf_init)(bool reset); + void (*prf_create)(uint8_t conidx); + void (*prf_cleanup)(uint8_t conidx, uint8_t reason); + + uint8_t (*prf_add_profile)(struct gapm_profile_task_add_cmd * params, kernel_task_id_t* prf_task); + void (*rwble_hl_reset)(void); + + void (*rwip_reset)(void); + void (*lld_sleep_init)(void); + + void (*rwip_prevent_sleep_set)(uint16_t prv_slp_bit); + void (*rwip_prevent_sleep_clear)(uint16_t prv_slp_bit); + + void (*platform_reset)(uint32_t error); + +}; +*/ +struct rom_env_tag +{ + kernel_task_id_t (*prf_get_id_from_task)(kernel_msg_id_t task); + kernel_task_id_t (*prf_get_task_from_id)(kernel_msg_id_t id); + + void (*prf_init)(bool reset); + void (*prf_create)(uint8_t conidx); + void (*prf_cleanup)(uint8_t conidx, uint8_t reason); + + uint8_t (*prf_add_profile)(struct gapm_profile_task_add_cmd * params, kernel_task_id_t* prf_task); + void (*rwble_hl_reset)(void); + + void (*rwip_reset)(void); + void (*lld_sleep_init)(void); + + void (*rwip_prevent_sleep_set)(uint16_t prv_slp_bit); + void (*rwip_prevent_sleep_clear)(uint16_t prv_slp_bit); + + void (*platform_reset)(uint32_t error); + + + uint8_t (*Read_Uart_Buf)(void); + +}; + + + + + + +void rom_env_init(struct rom_env_tag *api); + +//extern struct flash_for_rom_func_tag RcallF_func_list; +extern struct rom_env_tag rom_env; + + +void lld_bdaddr_init(const struct bd_addr *addr); + +#endif // __ROM_CALL_FLASH_H_ + diff --git a/beken_os/beken378/driver/ble/ble_pub/modules/common/api/common_bt.h b/beken_os/beken378/driver/ble/ble_pub/modules/common/api/common_bt.h new file mode 100755 index 0000000..188a607 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/modules/common/api/common_bt.h @@ -0,0 +1,2177 @@ +/** + **************************************************************************************** + * + * @file common_bt.h + * + * @brief This file contains the common Bluetooth defines, enumerations and structures + * definitions for use by all modules in RW stack. + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef COMMON_BT_H_ +#define COMMON_BT_H_ + +/** + **************************************************************************************** + * @addtogroup COMMON Common SW Block + * @ingroup ROOT + * @brief The Common RW SW Block. + * + * The COMMON is the block with Bluetooth definitions and structures shared + * to all the protocol stack blocks. This also contain software wide error code + * definitions, mathematical functions, help functions, list and buffer definitions. + * + * @{ + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @addtogroup COMMON_BT Common Bluetooth defines + * @ingroup COMMON + * @brief Common Bluetooth definitions and structures. + * + * @{ + **************************************************************************************** + */ + + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include // standard boolean definitions +#include // standard definitions +#include // standard integer definitions + +/* + * DEFINES + **************************************************************************************** + */ + +/** + * BD Address format (values in bytes) + * | 3B | 1B | 2B | + * | LAP | UAP | NAP | + */ +#define BD_ADDR_LEN 6 +#define BD_ADDR_LAP_POS 0 +#define BD_ADDR_LAP_LEN 3 +#define BD_ADDR_UAP_POS BD_ADDR_LAP_LEN +#define BD_ADDR_UAP_LEN 1 +#define BD_ADDR_NAP_POS BD_ADDR_UAP_LEN +#define BD_ADDR_NAP_LEN 2 + +///Length of fields in Bluetooth messages, in number of bytes +#define EVT_MASK_LEN 8 +#define DEV_CLASS_LEN 3 +#define ACOMMON_LEN 12 +#define SRES_LEN 0x04 +#define ACCESS_ADDR_LEN 0x04 +#define LE_PASSKEY_LEN 0x04 +#define BD_NAME_SIZE 0xF8 // Was 0x20 for BLE HL +#define ADV_DATA_LEN 0x1F +#define BLE_DATA_LEN 0x1B +#define SCAN_RSP_DATA_LEN 0x1F +#define LE_CHNL_MAP_LEN 0x05 +#define CHNL_MAP_LEN 0x0A +#define KEY_LEN 0x10 +#define PIN_CODE_MIN_LEN 0x01 +#define PIN_CODE_MAX_LEN 0x10 +#define PRIV_KEY_192_LEN 24 +#define PUB_KEY_192_LEN 48 +#define PRIV_KEY_256_LEN 32 +#define PUB_KEY_256_LEN 64 +#define CFM_LEN 0x10 +#define ENC_DATA_LEN 0x10 +#define RAND_VAL_LEN 0x10 +#define RAND_NB_LEN 0x08 +#define LE_FEATS_LEN 0x08 +#define SUPP_CMDS_LEN 0x40 +#define FEATS_LEN 0x08 +#define NAME_VECT_SIZE 14 +#define LMP_FEATS_LEN 0x08 +#define LE_STATES_LEN 0x08 +#define WHITE_LIST_LEN 0x0A +#define LE_FREQ_LEN 0x28 +#define LE_DATA_FREQ_LEN 0x25 +#define CRC_INIT_LEN 0x03 +#define SESS_KEY_DIV_LEN 0x08 +#define INIT_VECT_LEN 0x04 +#define BLE_MIC_LEN 0x04 +#define BLE_IV_LEN 0x08 + +// BT 4.2 - Secure Connections +#define PUBLIC_KEY_P256_LEN 0x20 +#define DHKEY_CHECK_LEN 0x10 + +#define DH_KEY_LEN 0x20 + +/// Maximum maskable event code +#define EVT_MASK_CODE_MAX EVT_MASK_LEN * 8 + +/// Format of the Advertising packets +#define ADV_ADDR_OFFSET 0 +#define ADV_ADDR_LEN BD_ADDR_LEN +#define ADV_DATA_OFFSET (ADV_ADDR_OFFSET + ADV_ADDR_LEN) + +/// BLE supported features +//byte 0 +#define BLE_ENC_FEATURE 0x01 +#define BLE_CON_PARAM_REQ_PROC_FEATURE 0x02 +#define BLE_REJ_IND_EXT_FEATURE 0x04 +#define BLE_SLAVE_INIT_EXCHG_FEATURE 0x08 +#define BLE_PING_FEATURE 0x10 +#define BLE_LENGTH_EXT_FEATURE 0x20 +#define BLE_LL_PRIVACY_FEATURE 0x40 +#define BLE_EXT_SCAN_POLICY_FEATURE 0x80 + +//byte 1 +#define BLE_2MBPS_FEATURE 0x01 +#define BLE_STABLE_MOD_FEATURE 0x02 + +/// BLE supported states +//byte 0 +#define BLE_NON_CON_ADV_STATE 0x01 +#define BLE_DISC_ADV_STATE 0x02 +#define BLE_CON_ADV_STATE 0x04 +#define BLE_HDC_DIRECT_ADV_STATE 0x08 +#define BLE_PASS_SCAN_STATE 0x10 +#define BLE_ACTIV_SCAN_STATE 0x20 +#define BLE_INIT_MASTER_STATE 0x40 +#define BLE_CON_SLAVE_STATE 0x80 + +//byte 1 +#define BLE_NON_CON_ADV_PASS_SCAN_STATE 0x01 +#define BLE_DISC_ADV_PASS_SCAN_STATE 0x02 +#define BLE_CON_ADV_PASS_SCAN_STATE 0x04 +#define BLE_HDC_DIRECT_ADV_PASS_SCAN_STATE 0x08 +#define BLE_NON_CON_ADV_ACTIV_SCAN_STATE 0x10 +#define BLE_DISC_ADV_ACTIV_SCAN_STATE 0x20 +#define BLE_CON_ADV_ACTIV_SCAN_STATE 0x40 +#define BLE_HDC_DIRECT_ADV_ACTIV_SCAN_STATE 0x80 + +//byte 2 +#define BLE_NON_CON_ADV_INIT_STATE 0x01 +#define BLE_DISC_ADV_INIT_STATE 0x02 +#define BLE_NON_CON_ADV_MASTER_STATE 0x04 +#define BLE_DISC_ADV_MASTER_STATE 0x08 +#define BLE_NON_CON_ADV_SLAVE_STATE 0x10 +#define BLE_DISC_ADV_SLAVE_STATE 0x20 +#define BLE_PASS_SCAN_INIT_STATE 0x40 +#define BLE_ACTIV_SCAN_INIT_STATE 0x80 + +//byte 3 +#define BLE_PASS_SCAN_MASTER_STATE 0x01 +#define BLE_ACTIV_SCAN_MASTER_STATE 0x02 +#define BLE_PASS_SCAN_SLAVE_STATE 0x04 +#define BLE_ACTIV_SCAN_SLAVE_STATE 0x08 +#define BLE_INIT_MASTER_MASTER_STATE 0x10 +#define BLE_LDC_DIRECT_ADV_STATE 0x20 +#define BLE_LDC_DIRECT_ADV_PASS_SCAN_STATE 0x40 +#define BLE_LDC_DIRECT_ADV_ACTIV_SCAN_STATE 0x80 + +//byte 4 +#define BLE_CON_ADV_INIT_MASTER_SLAVE_STATE 0x01 +#define BLE_HDC_DIRECT_ADV_INIT_MASTER_SLAVE_STATE 0x02 +#define BLE_LDC_DIRECT_ADV_INIT_MASTER_SLAVE_STATE 0x04 +#define BLE_CON_ADV_MASTER_SLAVE_STATE 0x08 +#define BLE_HDC_DIRECT_ADV_MASTER_SLAVE_STATE 0x10 +#define BLE_LDC_DIRECT_ADV_MASTER_SLAVE_STATE 0x20 +#define BLE_CON_ADV_SLAVE_SLAVE_STATE 0x40 +#define BLE_HDC_DIRECT_ADV_SLAVE_SLAVE_STATE 0x80 + +//byte 5 +#define BLE_LDC_DIRECT_ADV_SLAVE_SLAVE_STATE 0x01 +#define BLE_INIT_MASTER_SLAVE_STATE 0x02 + +/// BLE supported commands +//byte0 +#define BLE_DISC_CMD 0x20 +//byte2 +#define BLE_RD_REM_VERS_CMD 0x80 +//byte5 +#define BLE_SET_EVT_MSK_CMD 0x40 +#define BLE_RESET_CMD 0x80 +//byte10 +#define BLE_RD_TX_PWR_CMD 0x04 +#define BLE_SET_CTRL_TO_HL_FCTRL_CMD 0x20 +#define BLE_HL_BUF_SIZE_CMD 0x40 +#define BLE_HL_NB_CMP_PKT_CMD 0x80 +//byte14 +#define BLE_RD_LOC_VERS_CMD 0x08 +#define BLE_RD_LOC_SUP_FEAT_CMD 0x20 +#define BLE_RD_BUF_SIZE_CMD 0x80 +//byte15 +#define BLE_RD_BD_ADDR_CMD 0x02 +#define BLE_RD_RSSI_CMD 0x20 +//byte22 +#define BLE_SET_EVT_MSK_PG2_CMD 0x04 +//byte25 +#define BLE_LE_SET_EVT_MSK_CMD 0x01 +#define BLE_LE_RD_BUF_SIZE_CMD 0x02 +#define BLE_LE_RD_LOC_SUP_FEAT_CMD 0x04 +#define BLE_LE_SET_RAND_ADDR_CMD 0x10 +#define BLE_LE_SET_ADV_PARAM_CMD 0x20 +#define BLE_LE_RD_ADV_TX_PWR_CMD 0x40 +#define BLE_LE_SET_ADV_DATA_CMD 0x80 +//byte26 +#define BLE_LE_SET_SC_RSP_DATA_CMD 0x01 +#define BLE_LE_SET_ADV_EN_CMD 0x02 +#define BLE_LE_SET_SC_PARAM_CMD 0x04 +#define BLE_LE_SET_SC_EN_CMD 0x08 +#define BLE_LE_CREAT_CNX_CMD 0x10 +#define BLE_LE_CREAT_CNX_CNL_CMD 0x20 +#define BLE_LE_RD_WL_SIZE_CMD 0x40 +#define BLE_LE_CLEAR_WL_CMD 0x80 +//byte27 +#define BLE_LE_ADD_DEV_WL_CMD 0x01 +#define BLE_LE_REM_DEV_WL_CMD 0x02 +#define BLE_LE_CNX_UPDATE_CMD 0x04 +#define BLE_LE_SET_HL_CH_CLASS_CMD 0x08 +#define BLE_LE_RD_CH_MAP_CMD 0x10 +#define BLE_LE_RD_REM_USED_FEAT_CMD 0x20 +#define BLE_LE_ENCRYPT_CMD 0x40 +#define BLE_LE_RAND_CMD 0x80 +//byte28 +#define BLE_LE_START_ENC_CMD 0x01 +#define BLE_LE_LTK_REQ_RPLY_CMD 0x02 +#define BLE_LE_LTK_REQ_NEG_RPLY_CMD 0x04 +#define BLE_LE_RD_SUPP_STATES_CMD 0x08 +#define BLE_LE_RX_TEST_CMD 0x10 +#define BLE_LE_TX_TEST_CMD 0x20 +#define BLE_LE_STOP_TEST_CMD 0x40 + +//byte32 +#define BLE_RD_AUTH_PAYL_TO_CMD 0x10 +#define BLE_WR_AUTH_PAYL_TO_CMD 0x20 + + +//byte33 +#define BLE_LE_REM_CON_PARA_REQ_RPLY_CMD 0x10 +#define BLE_LE_REM_CON_PARA_REQ_NEG_RPLY_CMD 0x20 +#define BLE_LE_SET_DATA_LEN_CMD 0x40 +#define BLE_LE_RD_SUGGTED_DFT_DATA_LEN_CMD 0x80 + +//byte34 +#define BLE_LE_WR_SUGGTED_DFT_DATA_LEN_CMD 0x01 +#define BLE_LE_RD_LOC_P256_PUB_KEY_CMD 0x02 +#define BLE_LE_GEN_DH_KEY_CMD 0x04 +#define BLE_LE_ADD_DEV_TO_RESOLV_LIST_CMD 0x08 +#define BLE_LE_REM_DEV_FROM_RESOLV_LIST_CMD 0x10 +#define BLE_LE_CLEAR_RESOLV_LIST_CMD 0x20 +#define BLE_LE_RD_RESOLV_LIST_SIZE_CMD 0x40 +#define BLE_LE_RD_PEER_RESOLV_ADDR_CMD 0x80 + +//byte35 +#define BLE_LE_RD_LOCAL_RESOLV_ADDR_CMD 0x01 +#define BLE_LE_SET_ADDR_RESOL_CMD 0x02 +#define BLE_LE_SET_RESOLV_PRIV_ADDR_TO_CMD 0x04 +#define BLE_LE_RD_MAX_DATA_LEN_CMD 0x08 +#define BLE_LE_RD_PHY_CMD 0x10 +#define BLE_LE_SET_DFT_PHY_CMD 0x20 +#define BLE_LE_SET_PHY_CMD 0x40 +#define BLE_LE_ENH_RX_TEST_CMD 0x80 + +//byte36 +#define BLE_LE_ENH_TX_TEST_CMD 0x01 + +// Inquiry Length HCI:7.1.1 +#define INQ_LEN_MIN 0x01 +#define INQ_LEN_MAX 0x30 + +// Inquiry Length HCI:7.1.3 +#define INQ_MIN_PER_LEN_MIN 0x0002 +#define INQ_MIN_PER_LEN_MAX 0xFFFE +#define INQ_MAX_PER_LEN_MIN 0x0003 +#define INQ_MAX_PER_LEN_MAX 0xFFFF + +// IAC support +#define NB_IAC_MIN 0x01 +#define NB_IAC_MAX 0x40 + +/// Maximum value of a Bluetooth clock (in 625us slots) +#define MAX_SLOT_CLOCK ((1L<<27) - 1) + + +/// Logical Transport Adresses BB:4.2 +#define LT_ADDR_BCST 0x00 +#define LT_ADDR_MIN 0x01 +#define LT_ADDR_MAX 0x07 + +/// Link type HCI:7.7.3 +#define SCOMMON_TYPE 0 +#define ACL_TYPE 1 +#define ESCOMMON_TYPE 2 +#define UNKNOWN_TYPE 3 // Used in LM +#define LE_TYPE 4 + + +/// Allow Role Switch HCI:4.6.8 +#define MASTER_ROLE 0 +#define SLAVE_ROLE 1 +#define UNKNOWN_ROLE 0xFF //Used in LC to init the links role + +/// Link policy HCI:4.6.9 and HCI:4.6.10 +#define POLICY_SWITCH 0x0001 +#define POLICY_HOLD 0x0002 +#define POLICY_SNIFF 0x0004 +#define POLICY_PARK 0x0008 + +/// Allow Role Switch HCI:4.5.5 +#define ROLE_SWITCH_NOT_ALLOWED 0 +#define ROLE_SWITCH_ALLOWED 1 + +/// AcceptConnection Role HCI:4.5.8 +#define ACCEPT_SWITCH_TO_MASTER 0 +#define ACCEPT_REMAIN_SLAVE 1 + +/// Packet Type Flags HCI:7.1.14 +#define PACKET_TYPE_EDR_MSK 0x330E +#define PACKET_TYPE_GFSK_MSK 0xCCF8 +#define PACKET_TYPE_NO_2_DH1_FLAG 0x0002 +#define PACKET_TYPE_NO_3_DH1_FLAG 0x0004 +#define PACKET_TYPE_DM1_FLAG 0x0008 +#define PACKET_TYPE_DH1_FLAG 0x0010 +#define PACKET_TYPE_HV1_FLAG 0x0020 +#define PACKET_TYPE_HV2_FLAG 0x0040 +#define PACKET_TYPE_HV3_FLAG 0x0080 +#define PACKET_TYPE_NO_2_DH3_FLAG 0x0100 +#define PACKET_TYPE_NO_3_DH3_FLAG 0x0200 +#define PACKET_TYPE_DM3_FLAG 0x0400 +#define PACKET_TYPE_DH3_FLAG 0x0800 +#define PACKET_TYPE_NO_2_DH5_FLAG 0x1000 +#define PACKET_TYPE_NO_3_DH5_FLAG 0x2000 +#define PACKET_TYPE_DM5_FLAG 0x4000 +#define PACKET_TYPE_DH5_FLAG 0x8000 + +/// Synchronous Packet Types HCI:7.1.14 +#define SYNC_PACKET_TYPE_HV1_FLAG 0x0001 +#define SYNC_PACKET_TYPE_HV2_FLAG 0x0002 +#define SYNC_PACKET_TYPE_HV3_FLAG 0x0004 +#define SYNC_PACKET_TYPE_EV3_FLAG 0x0008 +#define SYNC_PACKET_TYPE_EV4_FLAG 0x0010 +#define SYNC_PACKET_TYPE_EV5_FLAG 0x0020 + +#define SYNC_PACKET_TYPE_NO_EV3_2_FLAG 0x0040 +#define SYNC_PACKET_TYPE_NO_EV3_3_FLAG 0x0080 +#define SYNC_PACKET_TYPE_NO_EV5_2_FLAG 0x0100 +#define SYNC_PACKET_TYPE_NO_EV5_3_FLAG 0x0200 + +#define SYNC_PACKET_TYPE_EV3_2_FLAG 0x0040 +#define SYNC_PACKET_TYPE_EV3_3_FLAG 0x0080 +#define SYNC_PACKET_TYPE_EV5_2_FLAG 0x0100 +#define SYNC_PACKET_TYPE_EV5_3_FLAG 0x0200 + +/// RWBT 1.2 +#define SYNC_EV3_PACKET_SIZE 30 +#define SYNC_EV4_PACKET_SIZE 120 +#define SYNC_EV5_PACKET_SIZE 180 + +/// Packet Boundary Flag HCI:5.4.2 +#define PBF_1ST_NF_HL_FRAG 0x00 // Non-flushable packets +#define PBF_CONT_HL_FRAG 0x01 +#define PBF_1ST_HL_FRAG 0x02 +#define PBF_CMP_PDU 0x03 +#define PBF_MASK 0x03 + +/// Broadcast Flag HCI:5.4.2 +#define BCF_P2P 0x00 +#define BCF_ACTIVE_SLV_BCST 0x04 +#define BCF_PARK_SLV_BCST 0x08 +#define BCF_MASK 0x0C + +/// Synchronous Packet Status Flag HCI:5.4.3 +#define CORRECTLY_RX_FLAG 0x00 +#define POSSIBLY_INVALID_FLAG 0x01 +#define NO_RX_DATA_FLAG 0x02 +#define PARTIALLY_LOST_FLAG 0x03 + +/// Park mode defines LMP:3.17 +#define MACCESS_MSK 0x0F +#define ACCSCHEM_MSK 0xF0 + +/// Support 3 feature pages +#define FEATURE_PAGE_MAX 3 + +#define FEATURE_PAGE_0 0 +#define FEATURE_PAGE_1 1 +#define FEATURE_PAGE_2 2 + +/// Feature mask definition LMP:3.3 +#define B0_3_SLOT_POS 0 +#define B0_3_SLOT_MSK 0x01 +#define B0_5_SLOT_POS 1 +#define B0_5_SLOT_MSK 0x02 +#define B0_ENC_POS 2 +#define B0_ENC_MSK 0x04 +#define B0_SLOT_OFF_POS 3 +#define B0_SLOT_OFF_MSK 0x08 +#define B0_TIMING_ACCU_POS 4 +#define B0_TIMING_ACCU_MSK 0x10 +#define B0_ROLE_SWITCH_POS 5 +#define B0_ROLE_SWITCH_MSK 0x20 +#define B0_HOLD_MODE_POS 6 +#define B0_HOLD_MODE_MSK 0x40 +#define B0_SNIFF_MODE_POS 7 +#define B0_SNIFF_MODE_MSK 0x80 + +#define B1_PARK_POS 0 +#define B1_PARK_MSK 0x01 +#define B1_RSSI_POS 1 +#define B1_RSSI_MSK 0x02 +#define B1_CQDDR_POS 2 +#define B1_CQDDR_MSK 0x04 +#define B1_SCOMMON_POS 3 +#define B1_SCOMMON_MSK 0x08 +#define B1_HV2_POS 4 +#define B1_HV2_MSK 0x10 +#define B1_HV3_POS 5 +#define B1_HV3_MSK 0x20 +#define B1_MULAW_POS 6 +#define B1_MULAW_MSK 0x40 +#define B1_ALAW_POS 7 +#define B1_ALAW_MSK 0x80 + +#define B2_CVSD_POS 0 +#define B2_CVSD_MSK 0x01 +#define B2_PAGING_PAR_NEGO_POS 1 +#define B2_PAGING_PAR_NEGO_MSK 0x02 +#define B2_PWR_CTRL_POS 2 +#define B2_PWR_CTRL_MSK 0x04 +#define B2_TRANSPARENT_SCOMMON_POS 3 +#define B2_TRANSPARENT_SCOMMON_MSK 0x08 +#define B2_FLOW_CTRL_LAG_POS 4 +#define B2_FLOW_CTRL_LAG_MSK 0x70 +#define B2_BCAST_ENC_POS 7 +#define B2_BCAST_ENC_MSK 0x80 + +#define B3_EDR_2MBPS_ACL_POS 1 +#define B3_EDR_2MBPS_ACL_MSK 0x02 +#define B3_EDR_3MBPS_ACL_POS 2 +#define B3_EDR_3MBPS_ACL_MSK 0x04 +#define B3_ENH_INQSCAN_POS 3 +#define B3_ENH_INQSCAN_MSK 0x08 +#define B3_INT_INQSCAN_POS 4 +#define B3_INT_INQSCAN_MSK 0x10 +#define B3_INT_PAGESCAN_POS 5 +#define B3_INT_PAGESCAN_MSK 0x20 +#define B3_RSSI_INQ_RES_POS 6 +#define B3_RSSI_INQ_RES_MSK 0x40 +#define B3_ESCOMMON_EV3_POS 7 +#define B3_ESCOMMON_EV3_MSK 0x80 + +#define B4_EV4_PKT_POS 0 +#define B4_EV4_PKT_MSK 0x01 +#define B4_EV5_PKT_POS 1 +#define B4_EV5_PKT_MSK 0x02 +#define B4_AFH_CAP_SLV_POS 3 +#define B4_AFH_CAP_SLV_MSK 0x08 +#define B4_AFH_CLASS_SLV_POS 4 +#define B4_AFH_CLASS_SLV_MSK 0x10 +#define B4_BR_EDR_NOT_SUPP_POS 5 +#define B4_BR_EDR_NOT_SUPP_MSK 0x20 +#define B4_LE_SUPP_POS 6 +#define B4_LE_SUPP_MSK 0x40 +#define B4_3_SLOT_EDR_ACL_POS 7 +#define B4_3_SLOT_EDR_ACL_MSK 0x80 + +#define B5_5_SLOT_EDR_ACL_POS 0 +#define B5_5_SLOT_EDR_ACL_MSK 0x01 +#define B5_SSR_POS 1 +#define B5_SSR_MSK 0x02 +#define B5_PAUSE_ENC_POS 2 +#define B5_PAUSE_ENC_MSK 0x04 +#define B5_AFH_CAP_MST_POS 3 +#define B5_AFH_CAP_MST_MSK 0x08 +#define B5_AFH_CLASS_MST_POS 4 +#define B5_AFH_CLASS_MST_MSK 0x10 +#define B5_EDR_ESCOMMON_2MBPS_POS 5 +#define B5_EDR_ESCOMMON_2MBPS_MSK 0x20 +#define B5_EDR_ESCOMMON_3MBPS_POS 6 +#define B5_EDR_ESCOMMON_3MBPS_MSK 0x40 +#define B5_3_SLOT_EDR_ESCOMMON_POS 7 +#define B5_3_SLOT_EDR_ESCOMMON_MSK 0x80 + +#define B6_EIR_POS 0 +#define B6_EIR_MSK 0x01 +#define B6_SIM_LE_BREDR_DEV_CAP_POS 1 +#define B6_SIM_LE_BREDR_DEV_CAP_MSK 0x02 +#define B6_SSP_POS 3 +#define B6_SSP_MSK 0x08 +#define B6_ENCAPS_PDU_POS 4 +#define B6_ENCAPS_PDU_MSK 0x10 +#define B6_ERR_DATA_REP_POS 5 +#define B6_ERR_DATA_REP_MSK 0x20 +#define B6_NONFLUSH_PBF_POS 6 +#define B6_NONFLUSH_PBF_MSK 0x40 + +#define B7_LST_CHANGE_EVT_POS 0 +#define B7_LST_CHANGE_EVT_MSK 0x01 +#define B7_INQRES_TXPOW_POS 1 +#define B7_INQRES_TXPOW_MSK 0x02 +#define B7_ENH_PWR_CTRL_POS 2 +#define B7_ENH_PWR_CTRL_MSK 0x04 +#define B7_EXT_FEATS_POS 7 +#define B7_EXT_FEATS_MSK 0x80 + +/// Extended feature mask definition page 1 LMP:3.3 +#define B0_HOST_SSP_POS 0 +#define B0_HOST_SSP_MSK 0x01 +#define B0_HOST_LE_POS 1 +#define B0_HOST_LE_MSK 0x02 +#define B0_HOST_LE_BR_EDR_POS 2 +#define B0_HOST_LE_BR_EDR_MSK 0x04 +#define B0_HOST_SECURE_CON_POS 3 +#define B0_HOST_SECURE_CON_MSK 0x08 + +/// Extended feature mask definition page 2 LMP:3.3 +#define B0_CSB_MASTER_POS 0 +#define B0_CSB_MASTER_MSK 0x01 +#define B0_CSB_SLAVE_POS 1 +#define B0_CSB_SLAVE_MSK 0x02 +#define B0_SYNC_TRAIN_POS 2 +#define B0_SYNC_TRAIN_MSK 0x04 +#define B0_SYNC_SCAN_POS 3 +#define B0_SYNC_SCAN_MSK 0x08 +#define B0_INQ_RES_NOTIF_EVT_POS 4 +#define B0_INQ_RES_NOTIF_EVT_MSK 0x10 +#define B0_GEN_INTERL_SCAN_POS 5 +#define B0_GEN_INTERL_SCAN_MSK 0x20 +#define B0_COARSE_CLK_ADJ_POS 6 +#define B0_COARSE_CLK_ADJ_MSK 0x40 + +#define B1_SEC_CON_CTRL_POS 0 +#define B1_SEC_CON_CTRL_MSK 0x01 +#define B1_PING_POS 1 +#define B1_PING_MSK 0x02 +#define B1_TRAIN_NUDGING_POS 3 +#define B1_TRAIN_NUDGING_MSK 0x08 + +/// Features definitions +#define FEAT_3_SLOT_BIT_POS 0 +#define FEAT_5_SLOT_BIT_POS 1 +#define FEAT_ENC_BIT_POS 2 +#define FEAT_SLOT_OFFSET_BIT_POS 3 +#define FEAT_TIMING_ACC_BIT_POS 4 +#define FEAT_SWITCH_BIT_POS 5 +#define FEAT_HOLD_BIT_POS 6 +#define FEAT_SNIFF_BIT_POS 7 + +#define FEAT_PARK_BIT_POS 8 +#define FEAT_RSSI_BIT_POS 9 +#define FEAT_QUALITY_BIT_POS 10 +#define FEAT_SCOMMON_BIT_POS 11 +#define FEAT_HV2_BIT_POS 12 +#define FEAT_HV3_BIT_POS 13 +#define FEAT_ULAW_BIT_POS 14 +#define FEAT_ALAW_BIT_POS 15 + +#define FEAT_CVSD_BIT_POS 16 +#define FEAT_PAGING_BIT_POS 17 +#define FEAT_POWER_BIT_POS 18 +#define FEAT_TRANSP_SCOMMON_BIT_POS 19 +#define FEAT_BCAST_ENCRYPT_BIT_POS 23 + +#define FEAT_EDR_2MB_BIT_POS 25 +#define FEAT_EDR_3MB_BIT_POS 26 +#define FEAT_ENH_INQSCAN_BIT_POS 27 +#define FEAT_INT_INQSCAN_BIT_POS 28 +#define FEAT_INT_PAGESCAN_BIT_POS 29 +#define FEAT_RSSI_INQRES_BIT_POS 30 +#define FEAT_EV3_BIT_POS 31 + +#define FEAT_EV4_BIT_POS 32 +#define FEAT_EV5_BIT_POS 33 +#define FEAT_AFH_CAPABLE_S_BIT_POS 35 +#define FEAT_AFH_CLASS_S_BIT_POS 36 +#define FEAT_BR_EDR_NO_SUPP_BIT_POS 37 +#define FEAT_LE_BIT_POS 38 +#define FEAT_3_SLOT_EDR_BIT_POS 39 +#define FEAT_5_SLOT_EDR_BIT_POS 40 +#define FEAT_SNIFF_SUBRAT_BIT_POS 41 +#define FEAT_PAUSE_ENCRYPT_BIT_POS 42 +#define FEAT_AFH_CAPABLE_M_BIT_POS 43 +#define FEAT_AFH_CLASS_M_BIT_POS 44 +#define FEAT_EDR_ESCOMMON_2MB_BIT_POS 45 +#define FEAT_EDR_ESCOMMON_3MB_BIT_POS 46 +#define FEAT_3_SLOT_EDR_ESCOMMON_BIT_POS 47 +#define FEAT_EIR_BIT_POS 48 +#define FEAT_LE_BR_EDR_BIT_POS 49 +#define FEAT_SSP_BIT_POS 51 +#define FEAT_ENCAP_PDU_BIT_POS 52 +#define FEAT_ERRO_DATA_REP_BIT_POS 53 +#define FEAT_NFLUSH_PBF_BIT_POS 54 +#define FEAT_LSTO_CHG_EVT_BIT_POS 56 +#define FEAT_INQ_TXPWR_BIT_POS 57 +#define FEAT_EPC_BIT_POS 58 +#define FEAT_EXT_FEATS_BIT_POS 63 +#define FEAT_SSP_HOST_BIT_POS 64 +#define FEAT_LE_HOST_BIT_POS 65 +#define FEAT_LE_BR_EDR_HOST_BIT_POS 66 +#define FEAT_SEC_CON_HOST_BIT_POS 67 + +#define FEAT_CSB_MASTER_BIT_POS 128 +#define FEAT_CSB_SLAVE_BIT_POS 129 +#define FEAT_SYNC_TRAIN_BIT_POS 130 +#define FEAT_SYNC_SCAN_BIT_POS 131 +#define FEAT_INQ_RES_NOTIF_EVT_BIT_POS 132 +#define FEAT_GEN_INTERL_SCAN_BIT_POS 133 +#define FEAT_COARSE_CLK_ADJ_BIT_POS 134 +#define FEAT_SEC_CON_CTRL_BIT_POS 136 +#define FEAT_PING_BIT_POS 137 +#define FEAT_TRAIN_NUDGING_BIT_POS 139 + +/// Maximum number of feature bits per page (8 bytes x 8 bits) +#define MAX_FEAT_BITS_PER_PAGE 64 + +/// Poll interval defines LMP:5.2 +#define POLL_INTERVAL_MIN 0x0006 +#define POLL_INTERVAL_DFT 0x0028 +#define POLL_INTERVAL_MAX 0x1000 + +/// Power Adjustment Request LMP:5.2 +#define PWR_ADJ_REQ_DEC_1_STEP 0x00 +#define PWR_ADJ_REQ_INC_1_STEP 0x01 +#define PWR_ADJ_REQ_INC_MAX 0x02 + +/// Power Adjustment Response LMP:5.2 +#define PWR_ADJ_RES_GFSK_POS 0 +#define PWR_ADJ_RES_GFSK_MASK 0x03 +#define PWR_ADJ_RES_DQPSK_POS 2 +#define PWR_ADJ_RES_DQPSK_MASK 0x0C +#define PWR_ADJ_RES_8DPSK_POS 4 +#define PWR_ADJ_RES_8DPSK_MASK 0x30 + +#define PWR_ADJ_RES_NOT_SUPP 0x00 +#define PWR_ADJ_RES_CHG_1_STEP 0x01 +#define PWR_ADJ_RES_MAX 0x02 +#define PWR_ADJ_RES_MIN 0x03 + +/// Nb of Broadcast retransmissions defines +#define NB_BROADCAST_DFT 0x01 + +/// Nb of Broadcast CLK_ADJ PDU Baseband:4.1.14.1 +#define NB_BROADCAST_CLK_ADJ 0x06 + +/// Min PCA clk_adj_instant (in slots) LMP:4.1.14.1 +#define PCA_INSTANT_MIN 12 + +/// Piconet Clock Adjustment clk_adj_mode LMP:4.1.14.1 +#define CLK_ADJ_BEFORE_INSTANT 0 +#define CLK_ADJ_AFTER_INSTANT 1 + + +/// Different packet types BaseBand:6.7 +/* Packet and buffer sizes. These sizes do not include payload header (except for FHS + * packet where there is no payload header) since payload header is written or read by + * the RWBT in a different control structure part (TX/RXPHDR) */ +#define FHS_PACKET_SIZE 18 +#define DM1_PACKET_SIZE 17 +#define DH1_PACKET_SIZE 27 +#define DH1_2_PACKET_SIZE 54 +#define DH1_3_PACKET_SIZE 83 +#define DV_ACL_PACKET_SIZE 9 +#define DM3_PACKET_SIZE 121 +#define DH3_PACKET_SIZE 183 +#define DH3_2_PACKET_SIZE 367 +#define DH3_3_PACKET_SIZE 552 +#define DM5_PACKET_SIZE 224 +#define DH5_PACKET_SIZE 339 +#define DH5_2_PACKET_SIZE 679 +#define DH5_3_PACKET_SIZE 1021 +#define AUX1_PACKET_SIZE 29 + +#define HV1_PACKET_SIZE 10 +#define HV2_PACKET_SIZE 20 +#define HV3_PACKET_SIZE 30 +#define EV3_PACKET_SIZE 30 +#define EV3_2_PACKET_SIZE 60 +#define EV3_3_PACKET_SIZE 90 +#define EV4_PACKET_SIZE 120 +#define EV5_PACKET_SIZE 180 +#define EV5_2_PACKET_SIZE 360 +#define EV5_3_PACKET_SIZE 540 + +/// SCO Packet coding LMP:5.2 +#define SCOMMON_PACKET_HV1 0x00 +#define SCOMMON_PACKET_HV2 0x01 +#define SCOMMON_PACKET_HV3 0x02 + +/// eSCO Packet coding LMP:5.2 +#define ESCOMMON_PACKET_NULL 0x00 +#define ESCOMMON_PACKET_EV3 0x07 +#define ESCOMMON_PACKET_EV4 0x0C +#define ESCOMMON_PACKET_EV5 0x0D +#define ESCOMMON_PACKET_EV3_2 0x26 +#define ESCOMMON_PACKET_EV3_3 0x37 +#define ESCOMMON_PACKET_EV5_2 0x2C +#define ESCOMMON_PACKET_EV5_3 0x3D + +/// Max number of HV packet BaseBand:4.4.2.1 +#define MAX_NB_HV1 1 +#define MAX_NB_HV2 2 +#define MAX_NB_HV3 3 + +/// Tsco (ScoInterval) BaseBand:4.4.2.1 +#define TSCOMMON_HV1 2 +#define TSCOMMON_HV2 4 +#define TSCOMMON_HV3 6 + +/* Inquiry train repetition length , Baseband :Table 10.4 + * - 256 repetitions if no SCO + * - 512 repetitions if 1 SCO + * - 768 repetitions if 2 SCO */ +#define INQ_TRAIN_LENGTH_NO_SCO 256 +#define INQ_TRAIN_LENGTH_1_SCO 512 +#define INQ_TRAIN_LENGTH_2_SCO 768 + +/* Counter for train length, Npage (N*16 slots) depends on the slave page scan mode and + * the number of active SCO: + * | SR mode | no SCO | one SCO | two SCO | + * | R0 | >=1 | >=2 | >=3 | + * | R1 | >=128 | >=256 | >=384 | + * | R2 | >=256 | >=512 | >=768 | */ +#define PAGE_TRAIN_LENGTH_R0 1 +#define PAGE_TRAIN_LENGTH_R1 128 +#define PAGE_TRAIN_LENGTH_R2 256 + +/// Synchronisation defines +#define NORMAL_SYNC_POS (64 + 4) // End of Synchro word at bit 68 (64 + 4) +#define SLOT_SIZE 625 // A slot is 625 us + +/// Baseband timeout default value, Baseband timers: 1.1 +#define PAGE_RESP_TO_DEF 8 +#define INQ_RESP_TO_DEF 128 +#define NEW_CONNECTION_TO 32 + +/// LMP Response Timeout (in sec) +#define LMP_RSP_TO 30 + +/// Athenticated Payload Timeout (in units of 10 ms) +#define AUTH_PAYL_TO_DFT 0x0BB8 // 30 secs +#define AUTH_PAYL_TO_MIN 0x0001 + +/// Voice mute pattern defines +#define MU_LAW_MUTE 0xFF +#define ALAW_CVSD_MUTE 0x55 +#define TRANSP_MUTE 0x00 + +/// Air Mode LMP:5.2 +#define MU_LAW_MODE 0 +#define A_LAW_MODE 1 +#define CVSD_MODE 2 +#define TRANS_MODE 3 + +/// eSCO negotiation State LMP:5.2 +#define ESCOMMON_NEGO_INIT 0 +#define ESCOMMON_NEGO_LATEST_POSSIBLE 1 +#define ESCOMMON_NEGO_SLOT_VIOLATION 2 +#define ESCOMMON_NEGO_LAT_VIOLATION 3 +#define ESCOMMON_NEGO_UNSUPPORTED 4 + +#define SCOMMON_BANDWIDTH 8000 +#define SYNC_BANDWIDTH_DONT_CARE 0xFFFFFFFF + +#define SYNC_MIN_LATENCY 0x0004 +#define SYNC_MAX_LATENCY_ESCOMMON_S1 0x0007 +#define SYNC_MAX_LATENCY_ESCOMMON_S2 0x0007 +#define SYNC_MAX_LATENCY_ESCOMMON_S3 0x000A +#define SYNC_DONT_CARE_LATENCY 0xFFFF + +#define SYNC_NO_RE_TX 0x00 +#define SYNC_RE_TX_POWER 0x01 +#define SYNC_RE_TX_QUALITY 0x02 +#define SYNC_RE_TX_DONT_CARE 0xFF + +/// Timing Control Flags LMP:5.2 +#define TIM_CHANGE_FLAG 0x01 +#define INIT2_FLAG 0x02 +#define ACCESS_WIN_FLAG 0x04 + +/// Packet Type Table defines LMP:4.1.11 +#define PACKET_TABLE_1MBPS 0x00 +#define PACKET_TABLE_2_3MBPS 0x01 + +/// Data Rate defines LMP:5.2 +#define FEC_RATE_MSK 0x01 +#define USE_FEC_RATE 0x00 +#define NO_FEC_RATE 0x01 +#define PREF_PACK_MSK 0x06 +#define NO_PREF_PACK_SIZE 0x00 +#define USE_1_SLOT_PACKET 0x02 +#define USE_3_SLOT_PACKET 0x04 +#define USE_5_SLOT_PACKET 0x06 +#define PREF_EDR_MSK 0x18 +#define USE_DM1_ONLY 0x00 +#define USE_2_MBPS_RATE 0x08 +#define USE_3_MBPS_RATE 0x10 +#define PREF_PACK_EDR_MSK 0x60 +#define USE_1_SLOT_EDR_PKT 0x20 +#define USE_3_SLOT_EDR_PKT 0x40 +#define USE_5_SLOT_EDR_PKT 0x60 + +/// EIR Data Size HCI:6.24 +#define EIR_DATA_SIZE 240 + +/// Voice setting HCI:4.7.29 & 4.7.30 +#define INPUT_COD_LIN 0x0000 +#define INPUT_COD_MULAW 0x0100 +#define INPUT_COD_ALAW 0x0200 +#define INPUT_COD_MSK 0x0300 +#define INPUT_COD_OFF 8 +#define INPUT_DATA_1COMP 0x0000 +#define INPUT_DATA_2COMP 0x0040 +#define INPUT_DATA_SMAG 0x0080 +#define INPUT_DATA_UNSIGNED 0x00C0 +#define INPUT_DATAFORM_MSK 0x00C0 +#define INPUT_DATAFORM_OFF 6 +#define INPUT_SAMP_8BIT 0x0000 +#define INPUT_SAMP_16BIT 0x0020 +#define INPUT_SAMPSIZE_MSK 0x0020 +#define INPUT_SAMPSIZE_OFF 5 +#define LIN_PCM_BIT_POS_MSK 0x001C +#define LIN_PCM_BIT_POS_OFF 2 +#define AIR_COD_CVSD 0x0000 +#define AIR_COD_MULAW 0x0001 +#define AIR_COD_ALAW 0x0002 +#define AIR_COD_TRANS 0x0003 +#define AIR_COD_MSK 0x0003 +#define AIR_COD_OFF 0 + +/// ScanEnable HCI:6.1 +#define BOTH_SCAN_DISABLE 0 +#define INQUIRY_SCAN_ENABLE 1 +#define PAGE_SCAN_ENABLE 2 +#define BOTH_SCAN_ENABLE 3 + +/// PageScanInterval HCI:6.8 +#define PAGE_SCAN_INTV_MIN 0x0012 +#define PAGE_SCAN_INTV_MAX 0x1000 +#define PAGE_SCAN_INTV_DFT 0x0800 + +/// PageScanWindow HCI:6.9 +#define PAGE_SCAN_WIN_MIN 0x0011 +#define PAGE_SCAN_WIN_MAX 0x1000 +#define PAGE_SCAN_WIN_DFT 0x0012 + +/// InquiryScanInterval HCI:6.2 +#define INQ_SCAN_INTV_MIN 0x0012 +#define INQ_SCAN_INTV_MAX 0x1000 +#define INQ_SCAN_INTV_DFT 0x1000 + +/// InquiryScanWindow HCI:6.3 +#define INQ_SCAN_WIN_MIN 0x0011 +#define INQ_SCAN_WIN_MAX 0x1000 +#define INQ_SCAN_WIN_DFT 0x0012 + +/// General/Unlimited Inquiry Access Code (GIAC) +#define GIAC_LAP_0 0x33 +#define GIAC_LAP_1 0x8B +#define GIAC_LAP_2 0x9E + +/// Limited Dedicated Inquiry Access Code (LIAC) +#define LIAC_LAP_0 0x00 +#define LIAC_LAP_1 0x8B +#define LIAC_LAP_2 0x9E + +/// Maximum Dedicated Inquiry Access Code (DIAC MAX) +#define DIAC_MAX_LAP_0 0x3F +#define DIAC_MAX_LAP_1 0x8B +#define DIAC_MAX_LAP_2 0x9E + +/// PIN Type HCI:6.13 +#define VARIABLE_PIN 0 +#define FIXED_PIN 1 + +/// ConnectionAcceptTimeout HCI:6.7 +#define CON_ACCEPT_TO_MIN 0x00A0 +#define CON_ACCEPT_TO_MAX 0xB540 +#define CON_ACCEPT_TO_DFT 0x1FA0 + +/// PageTimeout HCI:6.6 +#define PAGE_TO_MIN 0x0016 +#define PAGE_TO_MAX 0xFFFF +#define PAGE_TO_DFT 0x2000 + +/// Clock offset valid flag in clock offset field HCI:7.1.5/7.1.19 +#define CLK_OFFSET_VALID_FLAG_POS 15 +#define CLK_OFFSET_VALID_FLAG_MSK 0x8000 + +/// AuthenticationEnable HCI:4.7.24 +#define AUTH_DISABLED 0x00 // Default +#define AUTH_ENABLED 0x01 + +/// EncryptionMode HCI:4.7.26 +#define ENC_DISABLED 0x00 // Default +#define ENC_PP_ENABLED 0x01 +#define ENC_PP_BC_ENABLED 0x02 + +/// AutomaticFlushTimeout HCI:4.7.32 +#define AUTO_FLUSH_TIMEOUT_MAX 0x07FF +#define AUTO_FLUSH_TIMEOUT_OFF 0x0000 +#define AUTO_FLUSH_TIMEOUT_DFT AUTO_FLUSH_TIMEOUT_OFF // Default (no automatic flush timeout) + +/// Link Supervision Time Out (in slots) HCI:6.21 +#define LSTO_OFF 0x0000 +#define LSTO_MIN 0x0001 +#define LSTO_DFT 0x7D00 // Default is 20 s +#define LSTO_MAX 0xFFFF + +/// PageScanRepetitionMode HCI:4.5.5 +#define R0 0x00 +#define R1 0x01 +#define R2 0x02 +#define PAGESCAN_REP_DEF R1 // Default + +/// PageScanPeriodMode HCI:4.7.49 +#define P0 0x00 // Default +#define P1 0x01 +#define P2 0x02 + +/// PageScanMode HCI:4.7.51 +#define MANDATORY_PAGE_SCAN_MODE 0x00 // Default + +#define OPT_PAGE_SCAN_MODE_1 0x01 +#define OPT_PAGE_SCAN_MODE_2 0x02 +#define OPT_PAGE_SCAN_MODE_3 0x03 + +/// Encryption Enable HCI:4.5.17 +#define ENCRYPTION_OFF 0x00 +#define ENCRYPTION_ON 0x01 + +/// Country Code HCI:4.8.4 +#define NORTH_AMERICA_EUROPE 0x00 +#define FRANCE 0x01 +#define SPAIN 0x02 +#define JAPAN 0x03 + +/// Loopback mode HCI:7.6.2 +#define NO_LOOPBACK 0x00 // Default +#define LOCAL_LOOPBACK 0x01 +#define REMOTE_LOOPBACK 0x02 + +/// Erroneous Data Reporting HCI:7.3.65 +#define ERR_DATA_REP_DIS 0x00 // Default +#define ERR_DATA_REP_EN 0x01 + +/// LM modes HCI:5.2.20 +#define LM_ACTIVE_MODE 0x00 +#define LM_HOLD_MODE 0x01 +#define LM_SNIFF_MODE 0x02 +#define LM_PARK_MODE 0x03 + +/// Key Type HCI:5.2.24 +#define COMB_KEY 0 +#define LOCAL_UNIT_KEY 1 +#define REMOTE_UNIT_KEY 2 +#define DEBUG_COMB_KEY 3 +#define UNAUTH_COMB_KEY_192 4 +#define AUTH_COMB_KEY_192 5 +#define CHANGED_COMB_KEY 6 +#define UNAUTH_COMB_KEY_256 7 +#define AUTH_COMB_KEY_256 8 + +/// Key Flag HCI:5.4.18 +#define SEMI_PERMANENT_KEY 0x00 +#define TEMPORARY_KEY 0x01 + +/// QOS Service Type HCI:4.6.6 +#define QOS_NO_TRAFFIC 0x00 +#define QOS_BEST_EFFORT 0x01 +#define QOS_GUARANTEED 0x02 +#define QOS_NOTSPECIFIED 0xFF + +#define QOS_WILD_CARD 0xFFFFFFFF + +/// RSSI golden range +#define RSSI_GOLDEN_RG 0x00 + +/// Inquiry TX power level (in dBm) HCI:7.3.62 +#define INQ_TX_PWR_DBM_MIN -70 +#define INQ_TX_PWR_DBM_DFT 0 +#define INQ_TX_PWR_DBM_MAX +20 + +/// Bluetooth Test Mode defines Bluetooth Test Mode: Table 3.2 + +#define PAUSE_MODE 0x00 +#define TXTEST0_MODE 0x01 +#define TXTEST1_MODE 0x02 +#define TXTEST10_MODE 0x03 +#define PRAND_MODE 0x04 +#define ACLLOOP_MODE 0x05 +#define SCOLOOP_MODE 0x06 +#define ACLNOWHIT_MODE 0x07 +#define SCONOWHIT_MODE 0x08 +#define TXTEST1100_MODE 0x09 +#define EXITTEST_MODE 0xFF + +#define HOPSINGLE 0x00 +#define HOPUSA 0x01 + +#define FIXTXPOW 0x00 +#define ADAPTTXPOW 0x01 + +/// Packet type parameter bit field of LMP_test_control +#define LMP_TEST_CTRL_PKT_TYPE_CODE_POS 0 +#define LMP_TEST_CTRL_PKT_TYPE_CODE_MSK 0x0F +#define LMP_TEST_CTRL_PKT_TYPE_LINK_POS 4 +#define LMP_TEST_CTRL_PKT_TYPE_LINK_MSK 0xF0 +#define TEST_ACLSCO 0 +#define TEST_ESCO 1 +#define TEST_EDRACL 2 +#define TEST_EDRESCO 3 + +/// LMP_encapsulated_header parameters LMP:5.3 +#define LMP_ENCAPS_P192_MAJ_TYPE 1 +#define LMP_ENCAPS_P192_MIN_TYPE 1 +#define LMP_ENCAPS_P192_PAYL_LEN 48 +#define LMP_ENCAPS_P192_PAYL_NB 3 +#define LMP_ENCAPS_P256_MAJ_TYPE 1 +#define LMP_ENCAPS_P256_MIN_TYPE 2 +#define LMP_ENCAPS_P256_PAYL_LEN 64 +#define LMP_ENCAPS_P256_PAYL_NB 4 + +/// Number of bits in the passkey code used during Secure Simple Pairing +#define SSP_PASSKEY_NB_BITS 20 + +// Event Filter HCI 4.7.3 + +/// Filter type +#define CLEAR_ALL_FILTER_TYPE 0x00 +#define INQUIRY_FILTER_TYPE 0x01 +#define CONNECTION_FILTER_TYPE 0x02 + +/// Filter size +#define CLEAR_ALL_FILTER_SIZE 0 + +/// Inquiry & Connection Setup Filter Condition Type +#define ALL_FILTER_CONDITION_TYPE 0x00 +#define CLASS_FILTER_CONDITION_TYPE 0x01 +#define BD_ADDR_FILTER_CONDITION_TYPE 0x02 + +/// Auto Accept Flag +#define DO_NOT_AUTO_ACCEPT_CONNECTION 0x01 +#define ACCEPT_CONNECTION_SLAVE 0x02 +#define ACCEPT_CONNECTION_MASTER 0x03 + +/// Event Mask HCI 4.7.1 +#define NO_EVENTS_SPECIFIED_FILTER 0x00000000 +#define INQUIRY_COMPLETE_EVENT_FILTER 0x00000001 +#define INQUIRY_RESULT_EVENT_FILTER 0x00000002 +#define CONNECTION_COMPLETE_EVENT_FILTER 0x00000004 +#define CONNECTION_REQUEST_EVENT_FILTER 0x00000008 +#define DISCONNECTION_COMPLETE_EVENT_FILTER 0x00000010 +#define AUTHENTICATION_COMPLETE_EVENT_FILTER 0x00000020 +#define REMOTE_NAME_REQUEST_COMPLETE_EVENT_FILTER 0x00000040 +#define ENCRYPTION_CHANGE_EVENT_FILTER 0x00000080 +#define CHANGE_CONNECTION_LINK_KEY_COMPLETE_EVENT_FILTER 0x00000100 +#define MASTER_LINK_KEY_COMPLETE_EVENT_FILTER 0x00000200 +#define READ_REMOTE_SUPPORTED_FEATURES_COMPLETE_EVENT_FILTER 0x00000400 +#define READ_REMOTE_VERSION_INFORMATION_COMPLETE_EVENT_FILTER 0x00000800 +#define QOS_SETUP_COMPLETE_EVENT_FILTER 0x00001000 +#define COMMAND_COMPLETE_EVENT_FILTER 0x00002000 // Unchecked */ +#define COMMAND_STATUS_EVENT_FILTER 0x00004000 // Unchecked */ +#define HARDWARE_ERROR_EVENT_FILTER 0x00008000 +#define FLUSH_OCCURRED_EVENT_FILTER 0x00010000 +#define ROLE_CHANGE_EVENT_FILTER 0x00020000 +#define NUMBER_OF_COMPLETED_PACKETS_EVENT_FILTER 0x00040000 // Unchecked */ +#define MODE_CHANGE_EVENT_FILTER 0x00080000 +#define RETURN_LINK_KEYS_EVENT_FILTER 0x00100000 +#define PIN_CODE_REQUEST_EVENT_FILTER 0x00200000 +#define LINK_KEY_REQUEST_EVENT_FILTER 0x00400000 +#define LINK_KEY_NOTIFICATION_EVENT_FILTER 0x00800000 +#define LOOPBACK_COMMAND_EVENT_FILTER 0x01000000 // Not implemented */ +#define DATA_BUFFER_OVERFLOW_EVENT_FILTER 0x02000000 +#define MAX_SLOTS_CHANGE_EVENT_FILTER 0x04000000 +#define READ_CLOCK_OFFSET_COMPLETE_EVENT_FILTER 0x08000000 +#define CONNECTION_PACKET_TYPE_CHANGED_EVENT_FILTER 0x10000000 +#define QOS_VIOLATION_EVENT_FILTER 0x20000000 +#define PAGE_SCAN_MODE_CHANGE_EVENT_FILTER 0x40000000 // Deprecated */ +#define PAGE_SCAN_REPETITION_MODE_CHANGE_EVENT_FILTER 0x80000000 + +#define FLOW_SPECIFICATION_COMPLETE_EVENT_FILTER 0x00000001 +#define INQUIRY_RESULT_WITH_RSSI_EVENT_FILTER 0x00000002 +#define READ_REMOTE_EXTENDED_FEATURES_COMPLETE_EVENT_FILTER 0x00000004 +#define SYNCHRONOUS_CONNECTION_COMPLETE_EVENT_FILTER 0x00000800 +#define SYNCHRONOUS_CONNECTION_CHANGE_EVENT_FILTER 0x00001000 +#define SNIFF_SUBRATING_EVENT_FILTER 0x00002000 +#define EXTENDED_INQUIRY_RESULT_EVENT_FILTER 0x00004000 +#define ENCRYPTION_KEY_REFRESH_COMPLETE_EVENT_FILTER 0x00008000 +#define IO_CAPABILITY_REQUEST_EVENT_FILTER 0x00010000 +#define IO_CAPABILITY_REQUEST_REPLY_EVENT_FILTER 0x00020000 +#define USER_CONFIRMATION_REQUEST_EVENT_FILTER 0x00040000 +#define USER_PASSKEY_REQUEST_EVENT_FILTER 0x00080000 +#define REMOTE_OOB_DATA_REQUEST_EVENT_FILTER 0x00100000 +#define SIMPLE_PAIRING_COMPLETE_EVENT_FILTER 0x00200000 +#define LINK_SUPERVISION_TIMEOUT_CHANGE_EVENT_FILTER 0x00800000 +#define ENHANCED_FLUSH_COMPLETE_EVENT_FILTER 0x01000000 +#define USER_PASSKEY_NOTIFICATION_EVENT_FILTER 0x04000000 +#define KEYPRESS_NOTIFICATION_EVENT_FILTER 0x08000000 +#define REM_HOST_SUPPORTED_FEATURES_NOTIFICATION_EVENT_FILTER 0x10000000 + +/// HostControllerToHostFlowControl (ACL) HCI 7.3.40 +#define FLOW_CONTROL_OFF 0x00 +#define FLOW_CONTROL_ACL 0x01 +#define FLOW_CONTROL_SCO 0x02 +#define FLOW_CONTROL_ACL_SCO 0x03 + +/// SynchroinousFlowControlEnable (SCO) HCI 7.3.39 +#define SYNC_FLOW_CONTROL_OFF 0x00 +#define SYNC_FLOW_CONTROL_ON 0x01 + +/// Tx Power HCI:4.7.37 +#define CURRENT_TX_POWER 0x00 +#define MAX_TX_POWER 0x01 + +/// Flow_direction HCI:7.2.13 +#define FLOW_DIR_OUT 0x00 +#define FLOW_DIR_IN 0x01 + +/// Drift and Jitter default value LMP 5.2 +#define DRIFT_BLE_DFT SCA_500PPM //500 +#define DRIFT_BT_DFT 250 +#define JITTER_DFT 10 +#define DRIFT_BT_ACTIVE_MAX 20 // BB:2.2.5 + +/// Read Stored Link Key HCI:4.7.8 +#define LINK_KEY_BD_ADDR 0x00 +#define LINK_KEY_ALL 0x01 + +/// Read/Write Hold Mode Activity HCI:4.7.35 and 4.7.36 +#define HOLD_MODE_ACTIV_DEFAULT 0x00 +#define HOLD_MODE_ACTIV_SUSP_PAGE_SCAN 0x01 +#define HOLD_MODE_ACTIV_SUSP_INQUIRY_SCAN 0x02 +#define HOLD_MODE_ACTIV_SUSP_PERIODIC_INQ 0x04 +#define HOLD_MODE_ACTIV_NOT_MASK 0xF8 + +/// AFH Mode +#define AFH_DISABLED 0x00 +#define AFH_ENABLED 0x01 + +/// AFH Reporting Mode +#define AFH_REPORTING_DISABLED 0x00 +#define AFH_REPORTING_ENABLED 0x01 + +/// AFH channel assessment Mode +#define AFH_CH_ASS_DISABLED 0x00 +#define AFH_CH_ASS_ENABLED 0x01 + +/// AFH MIn/Max interval, in BT slots (1s - 30s) +#define AFH_REPORT_INTERVAL_MIN 0x0640 +#define AFH_REPORT_INTERVAL_MAX 0xBB80 + +/// Channel classification values for frequency pairs +#define AFH_CH_CLASS_UNKNOWN 0x0 +#define AFH_CH_CLASS_GOOD 0x1 +#define AFH_CH_CLASS_RESERVED 0x2 +#define AFH_CH_CLASS_BAD 0x3 + +/// Maximum number of frequencies used in adapted channel hopping sequence +#define AFH_NB_CHANNEL_MIN 20 +#define AFH_NB_CHANNEL_MAX 79 + +/// Maximum number of frequencies used in synchronization train BB:2.6.4.8 +#define SYNC_TRAIN_CHANNEL_NB 3 +/// Indices of frequencies used in synchronization train +#define SYNC_TRAIN_CHANNEL_0 0 +#define SYNC_TRAIN_CHANNEL_1 24 +#define SYNC_TRAIN_CHANNEL_2 78 + +/// Maximum delay in synchronization train (in slots) BB:2.7.2 +#define SYNC_TRAIN_DELAY_MAX_DFT 16 +/// Maximum delay in synchronization train for Coarse clock adjustment (in slots) BB:2.7.2 +#define SYNC_TRAIN_DELAY_MAX_CLK_ADJ 4 +/// Synchronization train interval for Coarse clock adjustment (in slots) BB:2.7.2 +#define SYNC_TRAIN_INTV_CLK_ADJ 32 + +/// Future CSB instant value offset for Coarse clock adjustment (in slots) BB: 8.11.2 +#define SYNC_TRAIN_CSB_INSTANT_OFFSET_CLK_ADJ 1600 + +/// Minimum value for synchronization train interval (in slots) HCI:7.3.90 +#define SYNC_TRAIN_INTV_MIN 0x20 +/// Minimum value for synchronization train timeout (in slots) HCI:7.3.90 +#define SYNC_TRAIN_TO_MIN 0x00000002 +/// Maximum value for synchronization train timeout (in slots) HCI:7.3.90 +#define SYNC_TRAIN_TO_MAX 0x07FFFFFE + +/// Default value for synchronization train interval (in slots) HCI:6.36 +#define SYNC_TRAIN_INTV_DEFAULT 0x80 +/// Default value for synchronization train timeout (in slots) HCI:6.37 +#define SYNC_TRAIN_TO_DEFAULT 0x0002EE00 +/// Default value for synchronization train service data HCI:6.39 +#define SYNC_TRAIN_SVC_DATA_DEFAULT 0x00 + +/// Minimum value for synchronization scan timeout (in slots) HCI:7.1.52 +#define SYNC_SCAN_TO_MIN 0x22 +/// Minimum value for synchronization scan window (in slots) HCI:7.1.52 +#define SYNC_SCAN_WIN_MIN 0x22 +/// Minimum value for synchronization scan interval (in slots) HCI:7.1.52 +#define SYNC_SCAN_INTV_MIN 0x02 + +/// Default value for synchronization scan timeout (in slots) BB: Apppendix B +#define SYNC_SCAN_TO_DEFAULT 0x2000 +/// Recommended value for synchronization scan window (91.25ms) GAP: Appendix A +#define SYNC_SCAN_WIN_DEFAULT 0x0092 +/// Recommended value for synchronization scan interval (320 ms) GAP: Appendix A +#define SYNC_SCAN_INTV_DEFAULT 0x0200 + +/// CSB receive enable HCI:7.1.50 +#define CSB_RX_MODE_DIS 0x00 +#define CSB_RX_MODE_EN 0x01 + +/// CSB fragment HCI:7.2.88 +#define CSB_CONTINUATION_FRAGMENT 0 +#define CSB_STARTING_FRAGMENT 1 +#define CSB_ENDING_FRAGMENT 2 +#define CSB_NO_FRAGMENTATION 3 + +/// CSB max fragment size HCI:7.2.88 +#define CSB_FRAGMENT_SIZE_MAX 0xFF + +/// MWS Channel_Enable +#define MWS_CHANNEL_DISABLED 0x00 +#define MWS_CHANNEL_ENABLED 0x01 + +/// MWS Channel_Type +#define MWS_TDD_CHANNEL_TYPE 0x00 +#define MWS_FDD_CHANNEL_TYPE 0x01 + +/// MWS Transport_Layer +#define MWS_SIGNALING_ONLY 0x00 +#define MWS_WCI_1 0x01 +#define MWS_WCI_2 0x02 +#define MWS_TRANSPORT_TYPE_MAX 0x02 + +/// MWS PATTERN Index +#define MWS_PATTERN_INDEX_MAX 2 + +/// MWS PATTERN IntervalType +#define MWS_PATTERN_NO_TXRX 0 +#define MWS_PATTERN_TX_ALLOWED 1 +#define MWS_PATTERN_RX_ALLOWED 2 +#define MWS_PATTERN_TXRX_ALLOWED 3 +#define MWS_PATTERN_EXT_FRAME 4 +#define MWS_PATTERN_TYPE_MAX 4 + + +/// MWS Ext_Num_Periods +#define MWS_EXT_NUM_PERIODS_MIN 0x01 +#define MWS_EXT_NUM_PERIODS_MAX 0x32 + +/// MWS Period_Type +#define MWS_PERIOD_TYPE_DOWNLINK 0x00 +#define MWS_PERIOD_TYPE_UPLINK 0x01 +#define MWS_PERIOD_TYPE_BIDIRECTIONAL 0x02 +#define MWS_PERIOD_TYPE_GUARD_PERIOD 0x03 +#define MWS_PERIOD_TYPE_RESERVED 0x04 + +/// Simple pairing mode HCI:7.3.58/HCI:7.3.59 +#define SP_MODE_DIS 0x00 +#define SP_MODE_EN 0x01 + +/// Inquiry Scan Type and Page Scan Type HCI:6.4/HCI:6.11 +#define STANDARD_SCAN 0x00 +#define INTERLACED_SCAN 0x01 + +/// Default interlace offset used for frequency selection during interlaced inquiry/page scan BB:8.3.1/8.4.1 +#define INTERLACE_OFFSET_DFT 16 + +/// Inquiry Mode +#define STANDARD_INQUIRY 0x00 +#define RSSI_INQUIRY 0x01 +#define EXTENDED_INQUIRY 0x02 + +/// Maximum number of link keys Host can write via HCI Write Stored Link Key Command +#define NB_LINK_KEY 0x0B + +/// LMP Version +#define BT_LMP_V1_0 0 +#define BT_LMP_V1_1 1 +#define BT_LMP_V1_2 2 +#define BT_LMP_V2_0 3 +#define BT_LMP_V2_1 4 +#define BT_LMP_V3_0 5 +#define BT_LMP_V4_0 6 +#define BT_LMP_V4_1 7 + +/// WhichClock parameter +#define LOCAL_CLOCK 0 +#define PICONET_CLOCK 1 + +/// Clock Accuracy parameter +#define CLOCK_ACCURACY_UNKNOWN 0xFFFF + +#define SP_PASSKEY_STARTED 0x00 +#define SP_PASSKEY_DIGIT_ENTERED 0x01 +#define SP_PASSKEY_DIGIT_ERASED 0x02 +#define SP_PASSKEY_CLEARED 0x03 +#define SP_PASSKEY_COMPLETED 0x04 + +/// Low Power Mode +#define PARK_BEACON_MIN 0x000E + +/// RWBT Device can be slave of 2 master at max +#define MAX_SLAVES_FOR_DIFFERENT_MASTERS 2 +// Flags for ld_util_get_nb_acl function +/// Flag for master link +#define MASTER_FLAG 0x01 +/// Flag for slave link +#define SLAVE_FLAG 0x02 + +/// BLE event mask +enum le_evt_mask +{ + LE_CON_CMP_EVT_BIT = 0, + LE_CON_CMP_EVT_MSK = 0x0001, + LE_ADV_REP_EVT_BIT = 1, + LE_ADV_REP_EVT_MSK = 0x0002, + LE_CON_UPD_EVT_BIT = 2, + LE_CON_UPD_EVT_MSK = 0x0004, + LE_CON_RD_REM_FEAT_EVT_BIT = 3, + LE_CON_RD_REM_FEAT_EVT_MSK = 0x0008, + LE_LG_TR_KEY_REQ_EVT_BIT = 4, + LE_LG_TR_KEY_REQ_EVT_MSK = 0x0010, + LE_REM_CON_PARA_REQ_EVT_BIT = 5, + LE_REM_CON_PARA_REQ_EVT_MSK = 0x0020, + LE_DATA_LEN_CHG_EVT_BIT = 6, + LE_DATA_LEN_CHG_EVT_MSK = 0x0040, + LE_RD_LOC_P256_PUB_KEY_CMP_EVT_BIT = 7, + LE_RD_LOC_P256_PUB_KEY_CMP_EVT_MSK = 0x0080, + LE_GEN_DHKEY_CMP_EVT_BIT = 8, + LE_GEN_DHKEY_CMP_EVT_MSK = 0x0100, + LE_ENH_CON_CMP_EVT_BIT = 9, + LE_ENH_CON_CMP_EVT_MSK = 0x0200, + LE_DIR_ADV_REP_EVT_BIT = 10, + LE_DIR_ADV_REP_EVT_MSK = 0x0400, + LE_PHY_UPD_CMP_EVT_BIT = 11, + LE_PHY_UPD_CMP_EVT_MSK = 0x0800, + LE_DFT_EVT_MSK = 0x1F, +}; + +/// Enhanced Synchronous Connection HCI:7.1.41 & 7.1.42 +#define CODING_FORMAT_ULAW 0x00 +#define CODING_FORMAT_ALAW 0x01 +#define CODING_FORMAT_CVSD 0x02 +#define CODING_FORMAT_TRANSP 0x03 +#define CODING_FORMAT_LINPCM 0x04 +#define CODING_FORMAT_MSBC 0x05 +#define CODING_FORMAT_VENDSPEC 0xFF + +#define PCM_FORMAT_NA 0x00 +#define PCM_FORMAT_1SCOMP 0x01 +#define PCM_FORMAT_2SCOMP 0x02 +#define PCM_FORMAT_SIGNMAG 0x03 +#define PCM_FORMAT_UNSIGNED 0x04 + +#define PCM_SAMPLE_SIZE_8BITS 8 +#define PCM_SAMPLE_SIZE_16BITS 16 + +#define AUDIO_DATA_PATH_HCI 0 +#define AUDIO_DATA_PATH_PCM 1 + +/// Default maximum number of slots per packet +#define MAX_SLOT_DFT 1 + +/// Packet type code interpretation possibilities BB:6.5 +#define ID_NUL_TYPE 0x0 +#define POLL_TYPE 0x1 +#define FHS_TYPE 0x2 +#define DM1_TYPE 0x3 +#define DH1_TYPE 0x4 +#define DH1_2_TYPE 0x4 +#define DH1_3_TYPE 0x8 +#define HV1_TYPE 0x5 +#define HV2_TYPE 0x6 +#define EV3_2_TYPE 0x6 +#define HV3_TYPE 0x7 +#define EV3_TYPE 0x7 +#define EV3_3_TYPE 0x7 +#define DV_TYPE 0x8 +#define AUX1_TYPE 0x9 +#define DM3_TYPE 0xA +#define DH3_TYPE 0xB +#define DH3_2_TYPE 0xA +#define DH3_3_TYPE 0xB +#define EV4_TYPE 0xC +#define EV5_2_TYPE 0xC +#define EV5_TYPE 0xD +#define EV5_3_TYPE 0xD +#define DM5_TYPE 0xE +#define DH5_TYPE 0xF +#define DH5_2_TYPE 0xE +#define DH5_3_TYPE 0xF + +/// Format of the FHS payload BB:6.5.1.4 +#define FHS_PAR_BITS_POS 0 +#define FHS_PAR_BITS_LEN 34 +#define FHS_PAR_BITS_END (FHS_PAR_BITS_POS + FHS_PAR_BITS_LEN) +#define FHS_LAP_POS FHS_PAR_BITS_END +#define FHS_LAP_LEN 24 +#define FHS_LAP_END (FHS_LAP_POS + FHS_LAP_LEN) +#define FHS_EIR_POS FHS_LAP_END +#define FHS_EIR_LEN 1 +#define FHS_EIR_END (FHS_EIR_POS + FHS_EIR_LEN) +#define FHS_UNDEF_POS FHS_EIR_END +#define FHS_UNDEF_LEN 1 +#define FHS_UNDEF_END (FHS_UNDEF_POS + FHS_UNDEF_LEN) +#define FHS_SR_POS FHS_UNDEF_END +#define FHS_SR_LEN 2 +#define FHS_SR_END (FHS_SR_POS + FHS_SR_LEN) +#define FHS_RSVD_POS FHS_SR_END +#define FHS_RSVD_LEN 2 +#define FHS_RSVD_END (FHS_RSVD_POS + FHS_RSVD_LEN) +#define FHS_UAP_POS FHS_RSVD_END +#define FHS_UAP_LEN 8 +#define FHS_UAP_END (FHS_UAP_POS + FHS_UAP_LEN) +#define FHS_NAP_POS FHS_UAP_END +#define FHS_NAP_LEN 16 +#define FHS_NAP_END (FHS_NAP_POS + FHS_NAP_LEN) +#define FHS_CLASS_OF_DEV_POS FHS_NAP_END +#define FHS_CLASS_OF_DEV_LEN 24 +#define FHS_CLASS_OF_DEV_END (FHS_CLASS_OF_DEV_POS + FHS_CLASS_OF_DEV_LEN) +#define FHS_LT_ADDR_POS FHS_CLASS_OF_DEV_END +#define FHS_LT_ADDR_LEN 3 +#define FHS_LT_ADDR_END (FHS_LT_ADDR_POS + FHS_LT_ADDR_LEN) +#define FHS_CLK_POS FHS_LT_ADDR_END +#define FHS_CLK_LEN 26 +#define FHS_CLK_END (FHS_CLK_POS + FHS_CLK_LEN) +#define FHS_PAGE_SCAN_MODE_POS FHS_CLK_END +#define FHS_PAGE_SCAN_MODE_LEN 3 +#define FHS_PAGE_SCAN_MODE_END (FHS_PAGE_SCAN_MODE_POS + FHS_PAGE_SCAN_MODE_LEN) + +/// Format of the STP payload BB:8.11.2 +#define STP_CLK_POS 0 +#define STP_CLK_LEN 4 +#define STP_FUT_CSB_INST_POS 4 +#define STP_FUT_CSB_INST_LEN 4 +#define STP_AFH_CH_MAP_POS 8 +#define STP_AFH_CH_MAP_LEN 10 +#define STP_MST_BD_ADDR_POS 18 +#define STP_MST_BD_ADDR_LEN 6 +#define STP_CSB_INTV_POS 24 +#define STP_CSB_INTV_LEN 2 +#define STP_CSB_LT_ADDR_POS 26 +#define STP_CSB_LT_ADDR_LEN 1 +#define STP_SVC_DATA_POS 27 +#define STP_SVC_DATA_LEN 1 +#define STP_PACKET_SIZE 28 + +/// CSB Receive status HCI:7.7.69 +#define CSB_RX_OK 0x00 +#define CSB_RX_KO 0x01 + +/* + * ENUMERATIONS + **************************************************************************************** + */ + +///Transmit Power level types +enum +{ + ///Current Power Level + TX_PW_LVL_CURRENT = 0x00, + ///Maximum power level + TX_PW_LVL_MAX, + ///Enumeration end value for power level type value check + TX_PW_LVL_END, +}; + +///Controller to Host flow control +enum +{ + /// C-> H flow control off + FLOW_CTRL_OFF = 0x00, + ///C->H ACL flow control on only + FLOW_CTRL_ON_ACL_OFF_SYNC, + ///C->H Sync flow control on only + FLOW_CTRL_OFF_ACL_ON_SYNC, + ///C->H ACL and Sync flow control on + FLOW_CTRL_ON_ACL_ON_SYNC, + ///Enumeration end value for flow control value check + FLOW_CTRL_END +}; + +///LE Supported Host enable +enum +{ + ///Disable LE supported Host + LE_SUPP_HOST_DIS = 0x00, + ///Enable LE Supported Host + LE_SUPP_HOST_EN, + ///Enumeration end value for LE supported Host enable check + LE_SUPP_HOST_END +}; + +///Simultaneous LE Host enable +enum +{ + ///Disable LE simultaneous Host disable + SIMULT_LE_HOST_DIS = 0x00, + ///Enable LE simultaneous Host disable + SIMULT_LE_HOST_EN, + ///Enumeration end value for LE simultaneous Host enable check + SIMULT_LE_HOST_END +}; + +///Advertising HCI Type +enum +{ + ///Connectable Undirected advertising + ADV_CONN_UNDIR = 0x00, + ///Connectable high duty cycle directed advertising + ADV_CONN_DIR, + ///Discoverable undirected advertising + ADV_DISC_UNDIR, + ///Non-connectable undirected advertising + ADV_NONCONN_UNDIR, + ///Connectable low duty cycle directed advertising + ADV_CONN_DIR_LDC, + ///Enumeration end value for advertising type value check + ADV_END +}; + +///Scanning HCI Type +enum +{ + ///Scan request + SCAN_REQ, + ///Scan response + SCAN_RSP, + ///Enumeration end value for scanning type value check + SCAN_LEN +}; + +///BD address type +enum +{ + ///Public BD address + ADDR_PUBLIC = 0x00, + ///Random BD Address + ADDR_RAND, + /// Controller generates Resolvable Private Address based on the + /// local IRK from resolving list. If resolving list contains no matching + /// entry, use public address. + ADDR_RPA_OR_PUBLIC, + /// Controller generates Resolvable Private Address based on the + /// local IRK from resolving list. If resolving list contains no matching + /// entry, use random address. + ADDR_RPA_OR_RAND, + ///Enumeration end value for BD address type value check + ADDR_END, + + /// mask used to determine Address type in the air + ADDR_MASK = 0x01, + /// mask used to determine if an address is an RPA + ADDR_RPA_MASK = 0x02, +}; + +/// Random Address type (2 MSB of the LE BD Address) +enum rnd_addr_type +{ + /// Static random address - 11 (MSB->LSB) + RND_STATIC_ADDR = 0xC0, + /// Private non resolvable address - 01 (MSB->LSB) + RND_NON_RSLV_ADDR = 0x00, + /// Private resolvable address - 01 (MSB->LSB) + RND_RSLV_ADDR = 0x40, +}; + +///Advertising channels enables +enum adv_channel_map +{ + ///Byte value for advertising channel map for channel 37 enable + ADV_CHNL_37_EN = 0x01, + ///Byte value for advertising channel map for channel 38 enable + ADV_CHNL_38_EN, + ///Byte value for advertising channel map for channel 39 enable + ADV_CHNL_39_EN = 0x04, + ///Byte value for advertising channel map for channel 37, 38 and 39 enable + ADV_ALL_CHNLS_EN = 0x07, + ///Enumeration end value for advertising channels enable value check + ADV_CHNL_END +}; + +///Advertising filter policy +enum adv_filter_policy +{ + ///Allow both scan and connection requests from anyone + ADV_ALLOW_SCAN_ANY_CON_ANY = 0x00, + ///Allow both scan req from White List devices only and connection req from anyone + ADV_ALLOW_SCAN_WLST_CON_ANY, + ///Allow both scan req from anyone and connection req from White List devices only + ADV_ALLOW_SCAN_ANY_CON_WLST, + ///Allow scan and connection requests from White List devices only + ADV_ALLOW_SCAN_WLST_CON_WLST, + ///Enumeration end value for advertising filter policy value check + ADV_ALLOW_SCAN_END +}; + +///Advertising enables +enum +{ + ///Disable advertising + ADV_DIS = 0x00, + ///Enable advertising + ADV_EN, + ///Enumeration end value for advertising enable value check + ADV_EN_END +}; + +///LE Scan type +enum +{ + ///Passive scan + SCAN_BLE_PASSIVE = 0x00, + ///Active scan + SCAN_BLE_ACTIVE, + ///Enumeration end value for scan type value check + SCAN_END +}; + +///Scan filter policy +enum scan_filter_policy +{ + ///Allow advertising packets from anyone + SCAN_ALLOW_ADV_ALL = 0x00, + ///Allow advertising packets from White List devices only + SCAN_ALLOW_ADV_WLST, + ///Allow advertising packets from anyone and Direct adv using RPA in InitA + SCAN_ALLOW_ADV_ALL_AND_INIT_RPA, + ///Allow advertising packets from White List devices only and Direct adv using RPA in InitA + SCAN_ALLOW_ADV_WLST_AND_INIT_RPA, + ///Enumeration end value for scan filter policy value check + SCAN_ALLOW_ADV_END +}; + +///Le Scan enables +enum +{ + ///Disable scan + SCAN_DIS = 0x00, + ///Enable scan + SCAN_EN, + ///Enumeration end value for scan enable value check + SCAN_EN_END +}; + +///Filter duplicates +enum scan_dup_filter_policy +{ + ///Disable filtering of duplicate packets + SCAN_FILT_DUPLIC_DIS = 0x00, + ///Enable filtering of duplicate packets + SCAN_FILT_DUPLIC_EN, + ///Enumeration end value for scan duplicate filtering value check + SCAN_FILT_DUPLIC_END +}; + +///Initiator Filter policy +enum +{ + ///Initiator will ignore White List + INIT_FILT_IGNORE_WLST = 0x00, + ///Initiator will use White List + INIT_FILT_USE_WLST, + ///Enumeration end value for initiator filter policy value check + INIT_FILT_END +}; + +///Transmitter test Packet Payload Type +enum +{ + ///Pseudo-random 9 TX test payload type + PAYL_PSEUDO_RAND_9 = 0x00, + ///11110000 TX test payload type + PAYL_11110000, + ///10101010 TX test payload type + PAYL_10101010, + ///Pseudo-random 15 TX test payload type + PAYL_PSEUDO_RAND_15, + ///All 1s TX test payload type + PAYL_ALL_1, + ///All 0s TX test payload type + PAYL_ALL_0, + ///00001111 TX test payload type + PAYL_00001111, + ///01010101 TX test payload type + PAYL_01010101, + ///Enumeration end value for TX test payload type value check + PAYL_END +}; + +/// Constant defining the role +enum +{ + ///Master role + ROLE_MASTER, + ///Slave role + ROLE_SLAVE, + ///Enumeration end value for role value check + ROLE_END +}; + +/// Constant clock accuracy +enum +{ + ///Clock accuracy at 500PPM + SCA_500PPM, + ///Clock accuracy at 250PPM + SCA_250PPM, + ///Clock accuracy at 150PPM + SCA_150PPM, + ///Clock accuracy at 100PPM + SCA_100PPM, + ///Clock accuracy at 75PPM + SCA_75PPM, + ///Clock accuracy at 50PPM + SCA_50PPM, + ///Clock accuracy at 30PPM + SCA_30PPM, + ///Clock accuracy at 20PPM + SCA_20PPM +}; + +///Advertising pdu Type +enum +{ + /// Undirected advertising + LL_ADV_CONN_UNDIR = 0x00, + /// Directed advertising + LL_ADV_CONN_DIR, + /// Non Connectable advertising + LL_ADV_NONCONN_UNDIR, + /// Scan Request + LL_SCAN_REQ, + /// Scan Response + LL_SCAN_RSP, + /// Connect Request + LL_CONNECT_REQ, + /// Discoverable advertising + LL_ADV_DISC_UNDIR, + LL_ADV_END +}; + +/// LLID packet +enum +{ + /// Reserved for future use + LLID_RFU, + /// Continue + LLID_CONTINUE, + /// Start + LLID_START, + /// Control + LLID_CNTL, + /// End + LLID_END, +}; + +/// Remote OOB Data present parameter value HCI:7.1.29 +enum +{ + REM_OOB_DATA_NO = 0x00, + REM_OOB_DATA_P192 = 0x01, + REM_OOB_DATA_P256 = 0x02, + REM_OOB_DATA_P192_P256 = 0x03, +}; + +/// Encryption enabled parameter in HCI_Enc_Chg_Evt HCI:7.7.8 +enum +{ + ENC_OFF = 0x00, + ENC_BRDER_E0_LE_AESCCM = 0x01, + ENC_BREDR_AESCC = 0x02, +}; + +/// BLE 2MBPS HCI:7.8.x +enum ble_phys_preference +{ + // TX PHY preferences + ALL_PHYS_TX_NO_PREF = (1 << 0), + ALL_PHYS_TX_PREF = (0 << 0), + // RX PHY preferences + ALL_PHYS_RX_NO_PREF = (1 << 1), + ALL_PHYS_RX_PREF = (0 << 1), + ALL_PHYS_MASK = 0x3, + +}; + +enum ble_phys_param_size +{ + PARAM_SZ_MIN_RX_TST = 3, + PARAM_SZ_MIN_TX_TST = 4, + PARAM_SZ_MAX_RX_TST = 61, + PARAM_SZ_MAX_TX_TST = 62, +}; +enum ble_phys_value +{ + PHYS_NO_PREF , + PHYS_1MBPS_PREF , + PHYS_2MBPS_PREF , + PHYS_MBPS_MAX, +}; + +enum ble_phy_mode +{ + PHYS_MOD_STANDARD , + PHYS_MOD_STABLE , + PHYS_MOD_MAX, +}; + +/* + * STRUCTURE DEFINITONS + **************************************************************************************** + */ + +///BD name structure +struct bd_name +{ + ///length for name + uint8_t namelen; + ///array of bytes for name + uint8_t name[BD_NAME_SIZE]; +}; + +///Structure device name +struct device_name +{ + ///array of bytes for name + uint8_t name[BD_NAME_SIZE]; +}; + +///Structure name vector +struct name_vect +{ + uint8_t vect[NAME_VECT_SIZE]; +}; + +/// lap structure +struct lap +{ + /// LAP + uint8_t A[BD_ADDR_LAP_LEN]; +}; + +/// class structure +struct devclass +{ + /// class + uint8_t A[DEV_CLASS_LEN]; +}; + +///Extended inquiry response structure +struct eir +{ + /// eir data + uint8_t data[EIR_DATA_SIZE]; +}; + +///Event mask structure +struct evt_mask +{ + ///8-byte array for mask value + uint8_t mask[EVT_MASK_LEN]; +}; + +///Host number of completed packets structure, for 1 connection handle +struct host_cmpl_pkts +{ + ///Connection handle + uint16_t con_hdl; + ///Number of completed packets + uint16_t nb_cmpl_pkts; +}; + +///BD Address structure +struct bd_addr +{ + ///6-byte array address value + uint8_t addr[BD_ADDR_LEN]; +}; + +///Access Address structure +struct access_addr +{ + ///4-byte array access address + uint8_t addr[ACCESS_ADDR_LEN]; +}; + +///Advertising data structure +struct adv_data +{ + ///Maximum length data bytes array + uint8_t data[ADV_DATA_LEN]; +}; + +///Scan response data structure +struct scan_rsp_data +{ + ///Maximum length data bytes array + uint8_t data[SCAN_RSP_DATA_LEN]; +}; + +///Channel map structure +struct chnl_map +{ + ///10-bytes channel map array + uint8_t map[CHNL_MAP_LEN]; +}; + +///Channel map structure +struct le_chnl_map +{ + ///5-byte channel map array + uint8_t map[LE_CHNL_MAP_LEN]; +}; + +///Long Term Key structure +struct ltk +{ + ///16-byte array for LTK value + uint8_t ltk[KEY_LEN]; +}; + +///Identity Resolving Key structure +struct irk +{ + ///16-byte array for IRK value + uint8_t key[KEY_LEN]; +}; + +/// Initialization vector (for AES-CCM encryption) +struct initialization_vector +{ + ///8-byte array + uint8_t vect[BLE_IV_LEN]; +}; + +/// Bluetooth address with link key +struct bd_addr_plus_key +{ + /// BD Address + struct bd_addr bd_addr; + /// Link Key + struct ltk link_key; +}; + +///Random number structure +struct rand_nb +{ + ///8-byte array for random number + uint8_t nb[RAND_NB_LEN]; +}; + +///Advertising report structure +struct adv_report +{ + ///Event type: + /// - ADV_CONN_UNDIR: Connectable Undirected advertising + /// - ADV_CONN_DIR: Connectable directed advertising + /// - ADV_DISC_UNDIR: Discoverable undirected advertising + /// - ADV_NONCONN_UNDIR: Non-connectable undirected advertising + uint8_t evt_type; + ///Advertising address type: public/random + uint8_t adv_addr_type; + ///Advertising address value + struct bd_addr adv_addr; + ///Data length in advertising packet + uint8_t data_len; + ///Data of advertising packet + uint8_t data[ADV_DATA_LEN]; + ///RSSI value for advertising packet + uint8_t rssi; +}; + + +///Direct Advertising report structure +struct dir_adv_report +{ + ///Event type: + /// - ADV_CONN_DIR: Connectable directed advertising + uint8_t evt_type; + ///Address type: public/random + uint8_t addr_type; + ///Address value + struct bd_addr addr; + ///Direct address type: public/random + uint8_t dir_addr_type; + ///Direct address value + struct bd_addr dir_addr; + ///RSSI value for advertising packet + uint8_t rssi; +}; + +///Supported LE Features structure +struct le_features +{ + ///8-byte array for LE features + uint8_t feats[LE_FEATS_LEN]; +}; + +///Simple pairing hash structure +struct hash +{ + ///16-byte array for LTK value + uint8_t C[KEY_LEN]; +}; + +///Simple pairing randomizer structure +struct randomizer +{ + ///16-byte array for LTK value + uint8_t R[KEY_LEN]; +}; + +///Pin code structure +struct pin_code +{ + ///16-byte array for PIN value + uint8_t pin[PIN_CODE_MAX_LEN]; +}; + +///Sres structure +struct sres_nb +{ + ///8-byte array for random number + uint8_t nb[SRES_LEN]; +}; + +///aco structure +struct aco +{ + ///8-byte array for random number + uint8_t a[ACOMMON_LEN]; +}; + +///struct byte 16 to stay align with the sdl version +struct byte16 +{ + uint8_t A[16]; +}; + +///Controller number of completed packets structure +struct nb_cmpl_pk +{ + ///Connection handle + uint16_t con_hdl; + ///Controller number of data packets that have been completed since last time + uint16_t nb_hc_cmpl_pkts; +}; + +///Supported Features structure +struct features +{ + ///8-byte array for features + uint8_t feats[FEATS_LEN]; +}; + +///Supported commands structure +struct supp_cmds +{ + ///64-byte array for supported commands + uint8_t cmds[SUPP_CMDS_LEN]; +}; + +///Supported LMP features structure +struct lmp_features +{ + ///8-byte array for LMp features + uint8_t feats[FEATS_LEN]; +}; + +///Simple pairing IO capabilities +struct io_capability +{ + ///IO capability + uint8_t io_cap; + /// Out Of Band Data present + bool oob_data_present; + ///Authentication Requirement + uint8_t aut_req; +}; + +///Public key +struct pub_key_192 +{ + uint8_t p_key[PUB_KEY_192_LEN/2]; +}; + +///Public key +struct pub_key_256 +{ + uint8_t p_key[PUB_KEY_256_LEN/2]; +}; + +///Simple pairing public keys 192 +struct sp_pub_key_192 +{ + ///Public key X + struct pub_key_192 X; + ///Public key Y + struct pub_key_192 Y; +}; + +///Simple pairing public keys 256 +struct sp_pub_key_256 +{ + ///Public key X + struct pub_key_256 X; + ///Public key Y + struct pub_key_256 Y; +}; + +///Supported LE states structure +struct le_states +{ + ///8-byte array for LE states + uint8_t supp_states[LE_STATES_LEN]; +}; + +///White List element structure +struct white_list +{ + ///BD address of device entry + struct bd_addr wl_bdaddr; + ///BD address type of device entry + uint8_t wl_bdaddr_type; +}; + +///CRC initial value structure +struct crc_init +{ + ///3-byte array CRC initial value + uint8_t crc[CRC_INIT_LEN]; +}; + +///Session key diversifier master or slave structure +struct sess_k_div_x +{ + ///8-byte array for diversifier value + uint8_t skdiv[SESS_KEY_DIV_LEN]; +}; + +///Session key diversifier structure +struct sess_k_div +{ + ///16-byte array for session key diversifier. + uint8_t skd[2*SESS_KEY_DIV_LEN]; +}; + +///Initiator vector +struct init_vect +{ + ///4-byte array for vector + uint8_t iv[INIT_VECT_LEN]; +}; + +#include "common_lmp.h" // Bluetooth LMP definitions +#include "common_hci.h" // Bluetooth HCI definitions +#include "common_error.h" // Bluetooth error codes definitions + +/// @} COMMON_BT +#endif // COMMON_BT_H_ diff --git a/beken_os/beken378/driver/ble/ble_pub/modules/common/api/common_endian.h b/beken_os/beken378/driver/ble/ble_pub/modules/common/api/common_endian.h new file mode 100755 index 0000000..8fd72ef --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/modules/common/api/common_endian.h @@ -0,0 +1,248 @@ +/** + **************************************************************************************** + * + * @file common_endian.h + * + * @brief Common endianness conversion functions + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef _COMMON_ENDIAN_H_ +#define _COMMON_ENDIAN_H_ + +#include // standard integer definitions +#include "rwip_config.h" // stack configuration +#include "architect.h" // architectural platform definition + +/** + **************************************************************************************** + * @defgroup COMMON_ENDIAN Endianness + * @ingroup COMMON + * @brief Endianness conversion functions. + * + * This set of functions converts values between the local system + * and a external one. It is inspired from the htonl-like functions + * from the standard C library. + * + * Example: + * @code + * struct eth_header *header = get_header(); // get pointer on Eth II packet header + * uint16_t eth_id; // will contain the type of the packet + * eth_id = common_ntohs(header->eth_id); // retrieve the type with correct endianness + * @endcode + * + * @{ + * **************************************************************************************** + * */ + + +/** + **************************************************************************************** + * @brief Swap bytes of a 32 bits value. + * The swap is done in every case. Should not be called directly. + * @param[in] val32 The 32 bits value to swap. + * @return The 32 bit swapped value. + **************************************************************************************** + */ +__INLINE uint32_t common_bswap32(uint32_t val32) +{ + return (val32<<24) | ((val32<<8)&0xFF0000) | ((val32>>8)&0xFF00) | ((val32>>24)&0xFF); +} + +/** + **************************************************************************************** + * @brief Swap bytes of a 16 bits value. + * The swap is done in every case. Should not be called directly. + * @param[in] val16 The 16 bit value to swap. + * @return The 16 bit swapped value. + **************************************************************************************** + */ +__INLINE uint16_t common_bswap16(uint16_t val16) +{ + return ((val16<<8)&0xFF00) | ((val16>>8)&0xFF); +} +/// @} COMMON_ENDIAN + + + + +/** + * **************************************************************************************** + * @defgroup COMMON_ENDIAN_NET Endianness (Network) + * @ingroup COMMON_ENDIAN + * @brief Endianness conversion functions for Network data + * + * Converts values between the local system and big-endian network data + * (e.g. IP, Ethernet, but NOT WLAN). + * + * The \b host term in the descriptions of these functions refers + * to the local system, i.e. \b application or \b embedded system. + * Therefore, these functions will behave differently depending on which + * side they are used. The reason of this terminology is to keep the + * same name than the standard C function. + * + * Behavior will depends on the endianness of the host: + * - little endian: swap bytes; + * - big endian: identity function. + * + * @{ + * **************************************************************************************** + * */ + +/** + **************************************************************************************** + * @brief Convert host to network long word. + * + * @param[in] hostlong Long word value to convert. + * + * @return The converted long word. + **************************************************************************************** + */ +__INLINE uint32_t common_htonl(uint32_t hostlong) +{ + #if (!CPU_LE) + return hostlong; + #else + return common_bswap32(hostlong); + #endif // CPU_LE +} + +/** + **************************************************************************************** + * @brief Convert host to network short word. + * + * @param[in] hostshort Short word value to convert. + * + * @return The converted short word. + **************************************************************************************** + */ +__INLINE uint16_t common_htons(uint16_t hostshort) +{ + #if (!CPU_LE) + return hostshort; + #else + return common_bswap16(hostshort); + #endif // CPU_LE +} + +/** + **************************************************************************************** + * @brief Convert network to host long word. + * + * @param[in] netlong Long word value to convert. + * + * @return The converted long word. + **************************************************************************************** + */ +__INLINE uint32_t common_ntohl(uint32_t netlong) +{ + return common_htonl(netlong); +} + +/** + **************************************************************************************** + * @brief Convert network to host short word. + * + * @param[in] netshort Short word value to convert. + * + * @return The converted short word. + **************************************************************************************** + */ +__INLINE uint16_t common_ntohs(uint16_t netshort) +{ + return common_htons(netshort); +} +/// @} COMMON_ENDIAN_NET + +/** + * **************************************************************************************** + * @defgroup COMMON_ENDIAN_BT Endianness (BT) + * @ingroup COMMON_ENDIAN + * @brief Endianness conversion functions for Bluetooth data (HCI and protocol) + * + * Converts values between the local system and little-endian Bluetooth data. + * + * The \b host term in the descriptions of these functions refers + * to the local system (check \ref COMMON_ENDIAN_NET "this comment"). + * + * Behavior will depends on the endianness of the host: + * - little endian: identity function; + * - big endian: swap bytes. + * + * @addtogroup COMMON_ENDIAN_BT + * @{ + * **************************************************************************************** + * */ + +/** + **************************************************************************************** + * @brief Convert host to Bluetooth long word. + * + * @param[in] hostlong Long word value to convert. + * + * @return The converted long word. + **************************************************************************************** + */ +__INLINE uint32_t common_htobl(uint32_t hostlong) +{ + #if (CPU_LE) + return hostlong; + #else + return common_bswap32(hostlong); + #endif // CPU_LE +} + +/** + **************************************************************************************** + * @brief Convert host to Bluetooth short word. + * + * @param[in] hostshort Short word value to convert. + * + * @return The converted short word. + **************************************************************************************** + */ +__INLINE uint16_t common_htobs(uint16_t hostshort) +{ + #if (CPU_LE) + return hostshort; + #else + return common_bswap16(hostshort); + #endif // CPU_LE +} + + +/** + **************************************************************************************** + * @brief Convert Bluetooth to host long word. + * + * @param[in] btlong Long word value to convert. + * + * @return The converted long word. + **************************************************************************************** + */ +__INLINE uint32_t common_btohl(uint32_t btlong) +{ + return common_htobl(btlong); +} + + +/** + **************************************************************************************** + * @brief Convert Bluetooth to host short word. + * + * @param[in] btshort Short word value to convert. + * + * @return The converted short word. + **************************************************************************************** + */ +__INLINE uint16_t common_btohs(uint16_t btshort) +{ + return common_htobs(btshort); +} +/// @} COMMON_ENDIAN + +#endif // _COMMON_ENDIAN_H_ diff --git a/beken_os/beken378/driver/ble/ble_pub/modules/common/api/common_error.h b/beken_os/beken378/driver/ble/ble_pub/modules/common/api/common_error.h new file mode 100755 index 0000000..f1be225 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/modules/common/api/common_error.h @@ -0,0 +1,110 @@ +/** + **************************************************************************************** + * + * @file common_error.h + * + * @brief List of codes for error in RW Software. + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef COMMON_ERROR_H_ +#define COMMON_ERROR_H_ + +/** + **************************************************************************************** + * @addtogroup COMMON_ERROR Error Codes + * @ingroup COMMON + * @brief Defines error codes in messages. + * + * @{ + **************************************************************************************** + */ + +/* + * DEFINES + **************************************************************************************** + */ +enum common_error +{ +/***************************************************** + *** ERROR CODES *** + *****************************************************/ + + COMMON_ERROR_NO_ERROR = 0x00, + COMMON_ERROR_UNKNOWN_HCI_COMMAND = 0x01, + COMMON_ERROR_UNKNOWN_CONNECTION_ID = 0x02, + COMMON_ERROR_HARDWARE_FAILURE = 0x03, + COMMON_ERROR_PAGE_TIMEOUT = 0x04, + COMMON_ERROR_AUTH_FAILURE = 0x05, + COMMON_ERROR_PIN_MISSING = 0x06, + COMMON_ERROR_MEMORY_CAPA_EXCEED = 0x07, + COMMON_ERROR_CON_TIMEOUT = 0x08, + COMMON_ERROR_CON_LIMIT_EXCEED = 0x09, + COMMON_ERROR_SYNC_CON_LIMIT_DEV_EXCEED = 0x0A, + COMMON_ERROR_ACL_CON_EXISTS = 0x0B, + COMMON_ERROR_COMMAND_DISALLOWED = 0x0C, + COMMON_ERROR_CONN_REJ_LIMITED_RESOURCES = 0x0D, + COMMON_ERROR_CONN_REJ_SECURITY_REASONS = 0x0E, + COMMON_ERROR_CONN_REJ_UNACCEPTABLE_BDADDR = 0x0F, + COMMON_ERROR_CONN_ACCEPT_TIMEOUT_EXCEED = 0x10, + COMMON_ERROR_UNSUPPORTED = 0x11, + COMMON_ERROR_INVALID_HCI_PARAM = 0x12, + COMMON_ERROR_REMOTE_USER_TERM_CON = 0x13, + COMMON_ERROR_REMOTE_DEV_TERM_LOW_RESOURCES = 0x14, + COMMON_ERROR_REMOTE_DEV_POWER_OFF = 0x15, + COMMON_ERROR_CON_TERM_BY_LOCAL_HOST = 0x16, + COMMON_ERROR_REPEATED_ATTEMPTS = 0x17, + COMMON_ERROR_PAIRING_NOT_ALLOWED = 0x18, + COMMON_ERROR_UNKNOWN_LMP_PDU = 0x19, + COMMON_ERROR_UNSUPPORTED_REMOTE_FEATURE = 0x1A, + COMMON_ERROR_SCOMMON_OFFSET_REJECTED = 0x1B, + COMMON_ERROR_SCOMMON_INTERVAL_REJECTED = 0x1C, + COMMON_ERROR_SCOMMON_AIR_MODE_REJECTED = 0x1D, + COMMON_ERROR_INVALID_LMP_PARAM = 0x1E, + COMMON_ERROR_UNSPECIFIED_ERROR = 0x1F, + COMMON_ERROR_UNSUPPORTED_LMP_PARAM_VALUE = 0x20, + COMMON_ERROR_ROLE_CHANGE_NOT_ALLOWED = 0x21, + COMMON_ERROR_LMP_RSP_TIMEOUT = 0x22, + COMMON_ERROR_LMP_COLLISION = 0x23, + COMMON_ERROR_LMP_PDU_NOT_ALLOWED = 0x24, + COMMON_ERROR_ENC_MODE_NOT_ACCEPT = 0x25, + COMMON_ERROR_LINK_KEY_CANT_CHANGE = 0x26, + COMMON_ERROR_QOS_NOT_SUPPORTED = 0x27, + COMMON_ERROR_INSTANT_PASSED = 0x28, + COMMON_ERROR_PAIRING_WITH_UNIT_KEY_NOT_SUP = 0x29, + COMMON_ERROR_DIFF_TRANSACTION_COLLISION = 0x2A, + COMMON_ERROR_QOS_UNACCEPTABLE_PARAM = 0x2C, + COMMON_ERROR_QOS_REJECTED = 0x2D, + COMMON_ERROR_CHANNEL_CLASS_NOT_SUP = 0x2E, + COMMON_ERROR_INSUFFICIENT_SECURITY = 0x2F, + COMMON_ERROR_PARAM_OUT_OF_MAND_RANGE = 0x30, + COMMON_ERROR_ROLE_SWITCH_PEND = 0x32, /* LM_ROLE_SWITCH_PENDING */ + COMMON_ERROR_RESERVED_SLOT_VIOLATION = 0x34, /* LM_RESERVED_SLOT_VIOLATION */ + COMMON_ERROR_ROLE_SWITCH_FAIL = 0x35, /* LM_ROLE_SWITCH_FAILED */ + COMMON_ERROR_EIR_TOO_LARGE = 0x36, /* LM_EXTENDED_INQUIRY_RESPONSE_TOO_LARGE */ + COMMON_ERROR_SP_NOT_SUPPORTED_HOST = 0x37, + COMMON_ERROR_HOST_BUSY_PAIRING = 0x38, + COMMON_ERROR_CONTROLLER_BUSY = 0x3A, + COMMON_ERROR_UNACCEPTABLE_CONN_INT = 0x3B, + COMMON_ERROR_DIRECT_ADV_TO = 0x3C, + COMMON_ERROR_TERMINATED_MIC_FAILURE = 0x3D, + COMMON_ERROR_CONN_FAILED_TO_BE_EST = 0x3E, + COMMON_ERROR_CCA_REJ_USE_CLOCK_DRAG = 0x40, + COMMON_ERROR_UNDEFINED = 0xFF, + + +/***************************************************** + *** HW ERROR CODES *** + *****************************************************/ + + COMMON_ERROR_HW_UART_OUT_OF_SYNC = 0x00, + COMMON_ERROR_HW_MEM_ALLOC_FAIL = 0x01, +}; + +/// @} COMMON_ERROR + +#endif // COMMON_ERROR_H_ diff --git a/beken_os/beken378/driver/ble/ble_pub/modules/common/api/common_hci.h b/beken_os/beken378/driver/ble/ble_pub/modules/common/api/common_hci.h new file mode 100755 index 0000000..c8e2eb3 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/modules/common/api/common_hci.h @@ -0,0 +1,4616 @@ +/** + **************************************************************************************** + * + * @file common_hci.h + * + * @brief This file contains the HCI Bluetooth defines, enumerations and structures + * definitions for use by all modules in RW stack. + * + * Copyright (C) RivieraWaves 2009-2015 + * + **************************************************************************************** + */ + +#ifndef COMMON_HCI_H_ +#define COMMON_HCI_H_ + +/** + **************************************************************************************** + * @addtogroup COMMON Common SW Block + * @{ + **************************************************************************************** + */ + + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include // standard boolean definitions +#include // standard definitions +#include // standard integer definitions + +#include "rwip_config.h" // IP configuration + +#include "ble_compiler.h" // compiler definitions + +/* + * DEFINES + **************************************************************************************** + */ + + +/******************************************************************************************/ +/* ------------------------- H4TL DEFINITIONS Part IV.A -----------------------------*/ +/******************************************************************************************/ + +///HCI Transport Header length - change if different transport +#define HCI_TRANSPORT_HDR_LEN 0x01 + +///UART header: command message type +#define HCI_CMD_MSG_TYPE 0x01 + +///UART header: ACL data message type +#define HCI_ACL_MSG_TYPE 0x02 + +///UART header: Synchronous data message type +#define HCI_SYNC_MSG_TYPE 0x03 + +///UART header: event message type +#define HCI_EVT_MSG_TYPE 0x04 + +///UART header: event message type +#define HCI_TCI_MSG_TYPE 0xFF + +/******************************************************************************************/ +/* ------------------------- HCI DEFINITIONS Part II.E -----------------------------*/ +/******************************************************************************************/ + +///HCI Command Opcode byte length +#define HCI_CMD_OPCODE_LEN (0x02) + +///HCI Event code byte length +#define HCI_EVT_CODE_LEN (0x01) + +///HCI Command/Event parameter length field byte length +#define HCI_CMDEVT_PARLEN_LEN (0x01) + +///HCI Command header length +#define HCI_CMD_HDR_LEN (HCI_CMD_OPCODE_LEN + HCI_CMDEVT_PARLEN_LEN) + +///HCI Event header length +#define HCI_EVT_HDR_LEN (HCI_EVT_CODE_LEN + HCI_CMDEVT_PARLEN_LEN) + +/// HCI ACL header: handle and flags decoding +#define HCI_ACL_HDR_HDL_FLAGS_POS (0) +#define HCI_ACL_HDR_HDL_FLAGS_LEN (2) +#define HCI_ACL_HDR_HDL_POS (0) +#define HCI_ACL_HDR_HDL_MASK (0x0FFF) +#define HCI_ACL_HDR_PB_FLAG_POS (12) +#define HCI_ACL_HDR_PB_FLAG_MASK (0x3000) +#define HCI_ACL_HDR_BC_FLAG_POS (14) +#define HCI_ACL_HDR_BC_FLAG_MASK (0xC000) +#define HCI_ACL_HDR_DATA_FLAG_POS (12) +#define HCI_ACL_HDR_DATA_FLAG_MASK (0xF000) + +/// HCI ACL header: data length field length +#define HCI_ACL_HDR_DATA_LEN_POS (HCI_ACL_HDR_HDL_FLAGS_LEN) +#define HCI_ACL_HDR_DATA_LEN_LEN (2) + +///HCI ACL data packet header length +#define HCI_ACL_HDR_LEN (HCI_ACL_HDR_HDL_FLAGS_LEN + HCI_ACL_HDR_DATA_LEN_LEN) + +/// HCI Synchronous header: handle and flags decoding +#define HCI_SYNC_HDR_HDL_FLAGS_POS (0) +#define HCI_SYNC_HDR_HDL_FLAGS_LEN (2) +#define HCI_SYNC_HDR_HDL_POS (0) +#define HCI_SYNC_HDR_HDL_MASK (0x0FFF) +#define HCI_SYNC_HDR_PSF_FLAG_POS (12) +#define HCI_SYNC_HDR_PSF_FLAG_MASK (0x3000) +#define HCI_SYNC_HDR_RES_FLAG_POS (14) +#define HCI_SYNC_HDR_RES_FLAG_MASK (0xC000) +#define HCI_SYNC_HDR_DATA_FLAG_POS (12) +#define HCI_SYNC_HDR_DATA_FLAG_MASK (0xF000) + +/// HCI Synchronous header: data length field length +#define HCI_SYNC_HDR_DATA_LEN_POS (HCI_SYNC_HDR_HDL_FLAGS_LEN) +#define HCI_SYNC_HDR_DATA_LEN_LEN (1) +#define HCI_SYNC_MAX_DATA_SIZE (255) + +///HCI sync data packet header length +#define HCI_SYNC_HDR_LEN (HCI_SYNC_HDR_HDL_FLAGS_LEN + HCI_SYNC_HDR_DATA_LEN_LEN) + +///HCI Command Complete Event minimum parameter length: 1(nb_pk)+2(opcode) +#define HCI_CCEVT_HDR_PARLEN (0x03) + +///HCI Command Complete Event header length:1(code)+1(len)+1(pk)+2(opcode) +#define HCI_CCEVT_HDR_LEN (HCI_EVT_HDR_LEN + HCI_CCEVT_HDR_PARLEN) + +///HCI Basic Command Complete Event packet length +#define HCI_CCEVT_BASIC_LEN (HCI_CCEVT_HDR_LEN + 1) + +///HCI Command Status Event parameter length - constant +#define HCI_CSEVT_PARLEN (0x04) + +///HCI Command Status Event length:1(code)+1(len)+1(st)+1(pk)+2(opcode) +#define HCI_CSEVT_LEN (HCI_EVT_HDR_LEN + HCI_CSEVT_PARLEN) + +///HCI Reset Command parameter length +#define HCI_RESET_CMD_PARLEN 0 + +/// Default return parameter length for HCI Command Complete Event +#define HCI_CCEVT_BASIC_RETPAR_LEN 1 + +/// Max HCI commands param size +#define HCI_MAX_CMD_PARAM_SIZE 255 + +/// Macro to extract OCF from OPCODE +#define HCI_OP2OCF(opcode) ((opcode) & 0x03FF) + +/// Macro to extract OGF from OPCODE +#define HCI_OP2OGF(opcode) ((opcode) >> 10 & 0x003F) + +/// Macro to create OPCODE from OGF and OCF +#define HCI_OPCODE(ocf, ogf) (((ogf) << 10) | ocf) + +/************************************************************************************** + ************** HCI COMMANDS **************** + **************************************************************************************/ + +///HCI enumeration of possible Command OGF values. +enum +{ + ///HCI Link Control Commands Group OGF code + LK_CNTL_OGF = 0x01, + ///HCI Link Policy Commands Group OGF code + LK_POL_OGF, + ///HCI Controller and Baseband Commands Group OGF code + CNTLR_BB_OGF, + ///HCI Information Parameters Commands Group OGF code + INFO_PAR_OGF, + ///HCI Status Commands Group OGF code + STAT_PAR_OGF, + ///HCI Test Commands Group OGF code + TEST_OGF, + ///HCI Low Energy Commands Group OGF code + LE_CNTLR_OGF=0x08, + ///HCI Vendor Specific Group OGF code + VS_OGF = 0x3F, + MAX_OGF +}; + +typedef struct t_public_key +{ + uint8_t x[PUBLIC_KEY_P256_LEN]; + uint8_t y[PUBLIC_KEY_P256_LEN]; + +} t_public_key; + +///Commands Opcodes: OGF(6b) | OCF(10b) +/* Some Abbreviation used in names: + * - LK = Link Key + * - RD = Read + * - WR = Write + * - REM = Remote + * - STG = Settings + * - CON = Connection + * - CHG = Change + * - DFT = Default + * - PER = Periodic + */ + +///HCI enumeration of possible Command OP Codes. +enum hci_opcode +{ + HCI_NO_OPERATION_CMD_OPCODE = 0x0000, + + //Link Control Commands + HCI_INQ_CMD_OPCODE = 0x0401, + HCI_INQ_CANCEL_CMD_OPCODE = 0x0402, + HCI_PER_INQ_MODE_CMD_OPCODE = 0x0403, + HCI_EXIT_PER_INQ_MODE_CMD_OPCODE = 0x0404, + HCI_CREATE_CON_CMD_OPCODE = 0x0405, + HCI_DISCONNECT_CMD_OPCODE = 0x0406, + HCI_CREATE_CON_CANCEL_CMD_OPCODE = 0x0408, + HCI_ACCEPT_CON_REQ_CMD_OPCODE = 0x0409, + HCI_REJECT_CON_REQ_CMD_OPCODE = 0x040A, + HCI_LK_REQ_REPLY_CMD_OPCODE = 0x040B, + HCI_LK_REQ_NEG_REPLY_CMD_OPCODE = 0x040C, + HCI_PIN_CODE_REQ_REPLY_CMD_OPCODE = 0x040D, + HCI_PIN_CODE_REQ_NEG_REPLY_CMD_OPCODE = 0x040E, + HCI_CHG_CON_PKT_TYPE_CMD_OPCODE = 0x040F, + HCI_AUTH_REQ_CMD_OPCODE = 0x0411, + HCI_SET_CON_ENC_CMD_OPCODE = 0x0413, + HCI_CHG_CON_LK_CMD_OPCODE = 0x0415, + HCI_MASTER_LK_CMD_OPCODE = 0x0417, + HCI_REM_NAME_REQ_CMD_OPCODE = 0x0419, + HCI_REM_NAME_REQ_CANCEL_CMD_OPCODE = 0x041A, + HCI_RD_REM_SUPP_FEATS_CMD_OPCODE = 0x041B, + HCI_RD_REM_EXT_FEATS_CMD_OPCODE = 0x041C, + HCI_RD_REM_VER_INFO_CMD_OPCODE = 0x041D, + HCI_RD_CLK_OFF_CMD_OPCODE = 0x041F, + HCI_RD_LMP_HDL_CMD_OPCODE = 0x0420, + HCI_SETUP_SYNC_CON_CMD_OPCODE = 0x0428, + HCI_ACCEPT_SYNC_CON_REQ_CMD_OPCODE = 0x0429, + HCI_REJECT_SYNC_CON_REQ_CMD_OPCODE = 0x042A, + HCI_IO_CAP_REQ_REPLY_CMD_OPCODE = 0x042B, + HCI_USER_CFM_REQ_REPLY_CMD_OPCODE = 0x042C, + HCI_USER_CFM_REQ_NEG_REPLY_CMD_OPCODE = 0x042D, + HCI_USER_PASSKEY_REQ_REPLY_CMD_OPCODE = 0x042E, + HCI_USER_PASSKEY_REQ_NEG_REPLY_CMD_OPCODE = 0x042F, + HCI_REM_OOB_DATA_REQ_REPLY_CMD_OPCODE = 0x0430, + HCI_REM_OOB_DATA_REQ_NEG_REPLY_CMD_OPCODE = 0x0433, + HCI_IO_CAP_REQ_NEG_REPLY_CMD_OPCODE = 0x0434, + HCI_ENH_SETUP_SYNC_CON_CMD_OPCODE = 0x043D, + HCI_ENH_ACCEPT_SYNC_CON_CMD_OPCODE = 0x043E, + HCI_TRUNC_PAGE_CMD_OPCODE = 0x043F, + HCI_TRUNC_PAGE_CAN_CMD_OPCODE = 0x0440, + HCI_SET_CON_SLV_BCST_CMD_OPCODE = 0x0441, + HCI_SET_CON_SLV_BCST_REC_CMD_OPCODE = 0x0442, + HCI_START_SYNC_TRAIN_CMD_OPCODE = 0x0443, + HCI_REC_SYNC_TRAIN_CMD_OPCODE = 0x0444, + HCI_REM_OOB_EXT_DATA_REQ_REPLY_CMD_OPCODE = 0x0445, + + //Link Policy Commands + HCI_HOLD_MODE_CMD_OPCODE = 0x0801, + HCI_SNIFF_MODE_CMD_OPCODE = 0x0803, + HCI_EXIT_SNIFF_MODE_CMD_OPCODE = 0x0804, + HCI_PARK_STATE_CMD_OPCODE = 0x0805, + HCI_EXIT_PARK_STATE_CMD_OPCODE = 0x0806, + HCI_QOS_SETUP_CMD_OPCODE = 0x0807, + HCI_ROLE_DISCOVERY_CMD_OPCODE = 0x0809, + HCI_SWITCH_ROLE_CMD_OPCODE = 0x080B, + HCI_RD_LINK_POL_STG_CMD_OPCODE = 0x080C, + HCI_WR_LINK_POL_STG_CMD_OPCODE = 0x080D, + HCI_RD_DFT_LINK_POL_STG_CMD_OPCODE = 0x080E, + HCI_WR_DFT_LINK_POL_STG_CMD_OPCODE = 0x080F, + HCI_FLOW_SPEC_CMD_OPCODE = 0x0810, + HCI_SNIFF_SUB_CMD_OPCODE = 0x0811, + + //Controller and Baseband Commands + HCI_SET_EVT_MASK_CMD_OPCODE = 0x0C01, + HCI_RESET_CMD_OPCODE = 0x0C03, + HCI_SET_EVT_FILTER_CMD_OPCODE = 0x0C05, + HCI_FLUSH_CMD_OPCODE = 0x0C08, + HCI_RD_PIN_TYPE_CMD_OPCODE = 0x0C09, + HCI_WR_PIN_TYPE_CMD_OPCODE = 0x0C0A, + HCI_CREATE_NEW_UNIT_KEY_CMD_OPCODE = 0x0C0B, + HCI_RD_STORED_LK_CMD_OPCODE = 0x0C0D, + HCI_WR_STORED_LK_CMD_OPCODE = 0x0C11, + HCI_DEL_STORED_LK_CMD_OPCODE = 0x0C12, + HCI_WR_LOCAL_NAME_CMD_OPCODE = 0x0C13, + HCI_RD_LOCAL_NAME_CMD_OPCODE = 0x0C14, + HCI_RD_CON_ACCEPT_TO_CMD_OPCODE = 0x0C15, + HCI_WR_CON_ACCEPT_TO_CMD_OPCODE = 0x0C16, + HCI_RD_PAGE_TO_CMD_OPCODE = 0x0C17, + HCI_WR_PAGE_TO_CMD_OPCODE = 0x0C18, + HCI_RD_SCAN_EN_CMD_OPCODE = 0x0C19, + HCI_WR_SCAN_EN_CMD_OPCODE = 0x0C1A, + HCI_RD_PAGE_SCAN_ACT_CMD_OPCODE = 0x0C1B, + HCI_WR_PAGE_SCAN_ACT_CMD_OPCODE = 0x0C1C, + HCI_RD_INQ_SCAN_ACT_CMD_OPCODE = 0x0C1D, + HCI_WR_INQ_SCAN_ACT_CMD_OPCODE = 0x0C1E, + HCI_RD_AUTH_EN_CMD_OPCODE = 0x0C1F, + HCI_WR_AUTH_EN_CMD_OPCODE = 0x0C20, + HCI_RD_CLASS_OF_DEV_CMD_OPCODE = 0x0C23, + HCI_WR_CLASS_OF_DEV_CMD_OPCODE = 0x0C24, + HCI_RD_VOICE_STG_CMD_OPCODE = 0x0C25, + HCI_WR_VOICE_STG_CMD_OPCODE = 0x0C26, + HCI_RD_AUTO_FLUSH_TO_CMD_OPCODE = 0x0C27, + HCI_WR_AUTO_FLUSH_TO_CMD_OPCODE = 0x0C28, + HCI_RD_NB_BDCST_RETX_CMD_OPCODE = 0x0C29, + HCI_WR_NB_BDCST_RETX_CMD_OPCODE = 0x0C2A, + HCI_RD_HOLD_MODE_ACTIVITY_CMD_OPCODE = 0x0C2B, + HCI_WR_HOLD_MODE_ACTIVITY_CMD_OPCODE = 0x0C2C, + HCI_RD_TX_PWR_LVL_CMD_OPCODE = 0x0C2D, + HCI_RD_SYNC_FLOW_CTRL_EN_CMD_OPCODE = 0x0C2E, + HCI_WR_SYNC_FLOW_CTRL_EN_CMD_OPCODE = 0x0C2F, + HCI_SET_CTRL_TO_HOST_FLOW_CTRL_CMD_OPCODE = 0x0C31, + HCI_HOST_BUF_SIZE_CMD_OPCODE = 0x0C33, + HCI_HOST_NB_CMP_PKTS_CMD_OPCODE = 0x0C35, + HCI_RD_LINK_SUPV_TO_CMD_OPCODE = 0x0C36, + HCI_WR_LINK_SUPV_TO_CMD_OPCODE = 0x0C37, + HCI_RD_NB_SUPP_IAC_CMD_OPCODE = 0x0C38, + HCI_RD_CURR_IAC_LAP_CMD_OPCODE = 0x0C39, + HCI_WR_CURR_IAC_LAP_CMD_OPCODE = 0x0C3A, + HCI_SET_AFH_HOST_CH_CLASS_CMD_OPCODE = 0x0C3F, + HCI_RD_INQ_SCAN_TYPE_CMD_OPCODE = 0x0C42, + HCI_WR_INQ_SCAN_TYPE_CMD_OPCODE = 0x0C43, + HCI_RD_INQ_MODE_CMD_OPCODE = 0x0C44, + HCI_WR_INQ_MODE_CMD_OPCODE = 0x0C45, + HCI_RD_PAGE_SCAN_TYPE_CMD_OPCODE = 0x0C46, + HCI_WR_PAGE_SCAN_TYPE_CMD_OPCODE = 0x0C47, + HCI_RD_AFH_CH_ASSESS_MODE_CMD_OPCODE = 0x0C48, + HCI_WR_AFH_CH_ASSESS_MODE_CMD_OPCODE = 0x0C49, + HCI_RD_EXT_INQ_RSP_CMD_OPCODE = 0x0C51, + HCI_WR_EXT_INQ_RSP_CMD_OPCODE = 0x0C52, + HCI_REFRESH_ENC_KEY_CMD_OPCODE = 0x0C53, + HCI_RD_SP_MODE_CMD_OPCODE = 0x0C55, + HCI_WR_SP_MODE_CMD_OPCODE = 0x0C56, + HCI_RD_LOC_OOB_DATA_CMD_OPCODE = 0x0C57, + HCI_RD_INQ_RSP_TX_PWR_LVL_CMD_OPCODE = 0x0C58, + HCI_WR_INQ_TX_PWR_LVL_CMD_OPCODE = 0x0C59, + HCI_RD_DFT_ERR_DATA_REP_CMD_OPCODE = 0x0C5A, + HCI_WR_DFT_ERR_DATA_REP_CMD_OPCODE = 0x0C5B, + HCI_ENH_FLUSH_CMD_OPCODE = 0x0C5F, + HCI_SEND_KEYPRESS_NOTIF_CMD_OPCODE = 0x0C60, + HCI_SET_EVT_MASK_PAGE_2_CMD_OPCODE = 0x0C63, + HCI_RD_FLOW_CNTL_MODE_CMD_OPCODE = 0x0C66, + HCI_WR_FLOW_CNTL_MODE_CMD_OPCODE = 0x0C67, + HCI_RD_ENH_TX_PWR_LVL_CMD_OPCODE = 0x0C68, + HCI_RD_LE_HOST_SUPP_CMD_OPCODE = 0x0C6C, + HCI_WR_LE_HOST_SUPP_CMD_OPCODE = 0x0C6D, + HCI_SET_MWS_CHANNEL_PARAMS_CMD_OPCODE = 0x0C6E, + HCI_SET_EXTERNAL_FRAME_CONFIG_CMD_OPCODE = 0x0C6F, + HCI_SET_MWS_SIGNALING_CMD_OPCODE = 0x0C70, + HCI_SET_MWS_TRANSPORT_LAYER_CMD_OPCODE = 0x0C71, + HCI_SET_MWS_SCAN_FREQ_TABLE_CMD_OPCODE = 0x0C72, + HCI_SET_MWS_PATTERN_CONFIG_CMD_OPCODE = 0x0C73, + HCI_SET_RES_LT_ADDR_CMD_OPCODE = 0x0C74, + HCI_DEL_RES_LT_ADDR_CMD_OPCODE = 0x0C75, + HCI_SET_CON_SLV_BCST_DATA_CMD_OPCODE = 0x0C76, + HCI_RD_SYNC_TRAIN_PARAM_CMD_OPCODE = 0x0C77, + HCI_WR_SYNC_TRAIN_PARAM_CMD_OPCODE = 0x0C78, + HCI_RD_SEC_CON_HOST_SUPP_CMD_OPCODE = 0x0C79, + HCI_WR_SEC_CON_HOST_SUPP_CMD_OPCODE = 0x0C7A, + HCI_RD_AUTH_PAYL_TO_CMD_OPCODE = 0x0C7B, + HCI_WR_AUTH_PAYL_TO_CMD_OPCODE = 0x0C7C, + HCI_RD_LOC_OOB_EXT_DATA_CMD_OPCODE = 0x0C7D, + HCI_RD_EXT_PAGE_TO_CMD_OPCODE = 0x0C7E, + HCI_WR_EXT_PAGE_TO_CMD_OPCODE = 0x0C7F, + HCI_RD_EXT_INQ_LEN_CMD_OPCODE = 0x0C80, + HCI_WR_EXT_INQ_LEN_CMD_OPCODE = 0x0C81, + + //Info Params + HCI_RD_LOCAL_VER_INFO_CMD_OPCODE = 0x1001, + HCI_RD_LOCAL_SUPP_CMDS_CMD_OPCODE = 0x1002, + HCI_RD_LOCAL_SUPP_FEATS_CMD_OPCODE = 0x1003, + HCI_RD_LOCAL_EXT_FEATS_CMD_OPCODE = 0x1004, + HCI_RD_BUFF_SIZE_CMD_OPCODE = 0x1005, + HCI_RD_BD_ADDR_CMD_OPCODE = 0x1009, + HCI_RD_LOCAL_SUPP_CODECS_CMD_OPCODE = 0x100B, + + //Status Params + HCI_RD_FAIL_CONTACT_CNT_CMD_OPCODE = 0x1401, + HCI_RST_FAIL_CONTACT_CNT_CMD_OPCODE = 0x1402, + HCI_RD_LINK_QUAL_CMD_OPCODE = 0x1403, + HCI_RD_RSSI_CMD_OPCODE = 0x1405, + HCI_RD_AFH_CH_MAP_CMD_OPCODE = 0x1406, + HCI_RD_CLK_CMD_OPCODE = 0x1407, + HCI_RD_ENC_KEY_SIZE_CMD_OPCODE = 0x1408, + HCI_GET_MWS_TRANSPORT_LAYER_CONFIG_CMD_OPCODE = 0x140C, + + //Testing Commands + HCI_RD_LOOPBACK_MODE_CMD_OPCODE = 0x1801, + HCI_WR_LOOPBACK_MODE_CMD_OPCODE = 0x1802, + HCI_EN_DUT_MODE_CMD_OPCODE = 0x1803, + HCI_WR_SP_DBG_MODE_CMD_OPCODE = 0x1804, + HCI_WR_SEC_CON_TEST_MODE_CMD_OPCODE = 0x180A, + + /// LE Commands Opcodes + HCI_LE_SET_EVT_MASK_CMD_OPCODE = 0x2001, + HCI_LE_RD_BUFF_SIZE_CMD_OPCODE = 0x2002, + HCI_LE_RD_LOCAL_SUPP_FEATS_CMD_OPCODE = 0x2003, + HCI_LE_SET_RAND_ADDR_CMD_OPCODE = 0x2005, + HCI_LE_SET_ADV_PARAM_CMD_OPCODE = 0x2006, + HCI_LE_RD_ADV_CHNL_TX_PW_CMD_OPCODE = 0x2007, + HCI_LE_SET_ADV_DATA_CMD_OPCODE = 0x2008, + HCI_LE_SET_SCAN_RSP_DATA_CMD_OPCODE = 0x2009, + HCI_LE_SET_ADV_EN_CMD_OPCODE = 0x200A, + HCI_LE_SET_SCAN_PARAM_CMD_OPCODE = 0x200B, + HCI_LE_SET_SCAN_EN_CMD_OPCODE = 0x200C, + HCI_LE_CREATE_CON_CMD_OPCODE = 0x200D, + HCI_LE_CREATE_CON_CANCEL_CMD_OPCODE = 0x200E, + HCI_LE_RD_WLST_SIZE_CMD_OPCODE = 0x200F, + HCI_LE_CLEAR_WLST_CMD_OPCODE = 0x2010, + HCI_LE_ADD_DEV_TO_WLST_CMD_OPCODE = 0x2011, + HCI_LE_RMV_DEV_FROM_WLST_CMD_OPCODE = 0x2012, + HCI_LE_CON_UPDATE_CMD_OPCODE = 0x2013, + HCI_LE_SET_HOST_CH_CLASS_CMD_OPCODE = 0x2014, + HCI_LE_RD_CHNL_MAP_CMD_OPCODE = 0x2015, + HCI_LE_RD_REM_USED_FEATS_CMD_OPCODE = 0x2016, + HCI_LE_ENC_CMD_OPCODE = 0x2017, + HCI_LE_RAND_CMD_OPCODE = 0x2018, + HCI_LE_START_ENC_CMD_OPCODE = 0x2019, + HCI_LE_LTK_REQ_REPLY_CMD_OPCODE = 0x201A, + HCI_LE_LTK_REQ_NEG_REPLY_CMD_OPCODE = 0x201B, + HCI_LE_RD_SUPP_STATES_CMD_OPCODE = 0x201C, + HCI_LE_RX_TEST_CMD_OPCODE = 0x201D, + HCI_LE_TX_TEST_CMD_OPCODE = 0x201E, + HCI_LE_TEST_END_CMD_OPCODE = 0x201F, +#if !(BLE_QUALIF) + HCI_LE_REM_CON_PARAM_REQ_REPLY_CMD_OPCODE = 0x2020, + HCI_LE_REM_CON_PARAM_REQ_NEG_REPLY_CMD_OPCODE = 0x2021, + HCI_LE_SET_DATA_LEN_CMD_OPCODE = 0x2022, + HCI_LE_RD_SUGGTED_DFT_DATA_LEN_CMD_OPCODE = 0x2023, + HCI_LE_WR_SUGGTED_DFT_DATA_LEN_CMD_OPCODE = 0x2024, + HCI_LE_RD_LOC_P256_PUB_KEY_CMD_OPCODE = 0x2025, + HCI_LE_GEN_DHKEY_CMD_OPCODE = 0x2026, + HCI_LE_ADD_DEV_TO_RSLV_LIST_CMD_OPCODE = 0x2027, + HCI_LE_RMV_DEV_FROM_RSLV_LIST_CMD_OPCODE = 0x2028, + HCI_LE_CLEAR_RSLV_LIST_CMD_OPCODE = 0x2029, + HCI_LE_RD_RSLV_LIST_SIZE_CMD_OPCODE = 0x202A, + HCI_LE_RD_PEER_RSLV_ADDR_CMD_OPCODE = 0x202B, + HCI_LE_RD_LOC_RSLV_ADDR_CMD_OPCODE = 0x202C, + HCI_LE_SET_ADDR_RESOL_EN_CMD_OPCODE = 0x202D, + HCI_LE_SET_RSLV_PRIV_ADDR_TO_CMD_OPCODE = 0x202E, + HCI_LE_RD_MAX_DATA_LEN_CMD_OPCODE = 0x202F, +#if (1) + HCI_LE_RD_PHY_CMD_OPCODE = 0x2030, + HCI_LE_SET_DFT_PHY_CMD_OPCODE = 0x2031, + HCI_LE_SET_PHY_CMD_OPCODE = 0x2032, + HCI_LE_ENH_RX_TEST_CMD_OPCODE = 0x2033, + HCI_LE_ENH_TX_TEST_CMD_OPCODE = 0x2034, +#endif // (BLE_2MBPS) +#endif // !(BLE_QUALIF) + + ///Debug commands - OGF = 0x3F (spec) + HCI_DBG_RD_MEM_CMD_OPCODE = 0xFC01, + HCI_DBG_WR_MEM_CMD_OPCODE = 0xFC02, + HCI_DBG_DEL_PAR_CMD_OPCODE = 0xFC03, + HCI_DBG_ID_FLASH_CMD_OPCODE = 0xFC05, + HCI_DBG_ER_FLASH_CMD_OPCODE = 0xFC06, + HCI_DBG_WR_FLASH_CMD_OPCODE = 0xFC07, + HCI_DBG_RD_FLASH_CMD_OPCODE = 0xFC08, + HCI_DBG_RD_PAR_CMD_OPCODE = 0xFC09, + HCI_DBG_WR_PAR_CMD_OPCODE = 0xFC0A, + HCI_DBG_WLAN_COEX_CMD_OPCODE = 0xFC0B, + HCI_DBG_WLAN_COEXTST_SCEN_CMD_OPCODE = 0xFC0D, + HCI_DBG_BT_SEND_LMP_CMD_OPCODE = 0xFC0E, + HCI_DBG_SET_LOCAL_CLOCK_CMD_OPCODE = 0xFC0F, + HCI_DBG_RD_KERNEL_STATS_CMD_OPCODE = 0xFC10, + HCI_DBG_PLF_RESET_CMD_OPCODE = 0xFC11, + HCI_DBG_RD_MEM_INFO_CMD_OPCODE = 0xFC12, + HCI_VS_SET_PREF_SLAVE_LATENCY_CMD_OPCODE = 0xFC13, + HCI_DBG_HW_REG_RD_CMD_OPCODE = 0xFC30, + HCI_DBG_HW_REG_WR_CMD_OPCODE = 0xFC31, + HCI_DBG_SET_BD_ADDR_CMD_OPCODE = 0xFC32, + HCI_DBG_SET_TYPE_PUB_CMD_OPCODE = 0xFC33, + HCI_DBG_SET_TYPE_RAND_CMD_OPCODE = 0xFC34, + HCI_DBG_SET_CRC_CMD_OPCODE = 0xFC35, + HCI_DBG_LLCP_DISCARD_CMD_OPCODE = 0xFC36, + HCI_DBG_RESET_RX_CNT_CMD_OPCODE = 0xFC37, + HCI_DBG_RESET_TX_CNT_CMD_OPCODE = 0xFC38, + HCI_DBG_RF_REG_RD_CMD_OPCODE = 0xFC39, + HCI_DBG_RF_REG_WR_CMD_OPCODE = 0xFC3A, + HCI_DBG_SET_TX_PW_CMD_OPCODE = 0xFC3B, + HCI_DBG_RF_SWITCH_CLK_CMD_OPCODE = 0xFC3C, + HCI_DBG_RF_WR_DATA_TX_CMD_OPCODE = 0xFC3D, + HCI_DBG_RF_RD_DATA_RX_CMD_OPCODE = 0xFC3E, + HCI_DBG_RF_CNTL_TX_CMD_OPCODE = 0xFC3F, + HCI_DBG_RF_SYNC_P_CNTL_CMD_OPCODE = 0xFC40, + HCI_TESTER_SET_LE_PARAMS_CMD_OPCODE = 0xFC40, + HCI_DBG_WR_DLE_DFT_VALUE_CMD_OPCODE = 0xFC41, + HCI_DBG_BLE_TST_LLCP_PT_EN_CMD_OPCODE = 0xFC42, + HCI_DBG_BLE_TST_SEND_LLCP_CMD_OPCODE = 0xFC43, + HCI_VS_AUDIO_ALLOCATE_CMD_OPCODE = 0xFC50, + HCI_VS_AUDIO_CONFIGURE_CMD_OPCODE = 0xFC51, + HCI_VS_AUDIO_SET_MODE_CMD_OPCODE = 0xFC52, + HCI_VS_AUDIO_RESET_CMD_OPCODE = 0xFC53, + HCI_VS_AUDIO_SET_POINTER_CMD_OPCODE = 0xFC54, + HCI_VS_AUDIO_GET_BUFFER_RANGE_CMD_OPCODE = 0xFC55, + + HCI_VS_ADV_TEST_MODE_START_CMD_OPCODE = 0xFC56, + + #if (RW_DEBUG && BT_EMB_PRESENT) + HCI_DBG_BT_DISCARD_LMP_EN_CMD_OPCODE = 0xFC44, + #endif //RW_DEBUG && BT_EMB_PRESENT + + HCI_DBG_MWS_COEX_CMD_OPCODE = 0xFC45, + HCI_DBG_MWS_COEXTST_SCEN_CMD_OPCODE = 0xFC46, + + #if CRYPTO_UT + HCI_DBG_TEST_CRYPTO_FUNC_CMD_OPCODE = 0xFC60, + #endif //CRYPTO_UT +}; + +/************************************************************************************** + ************** HCI EVENTS **************** + **************************************************************************************/ + +///Event Codes +enum hci_evt_code +{ + HCI_INQ_CMP_EVT_CODE = 0x01, + HCI_INQ_RES_EVT_CODE = 0x02, + HCI_CON_CMP_EVT_CODE = 0x03, + HCI_CON_REQ_EVT_CODE = 0x04, + HCI_DISC_CMP_EVT_CODE = 0x05, + HCI_AUTH_CMP_EVT_CODE = 0x06, + HCI_REM_NAME_REQ_CMP_EVT_CODE = 0x07, + HCI_ENC_CHG_EVT_CODE = 0x08, + HCI_CHG_CON_LK_CMP_EVT_CODE = 0x09, + HCI_MASTER_LK_CMP_EVT_CODE = 0x0A, + HCI_RD_REM_SUPP_FEATS_CMP_EVT_CODE = 0x0B, + HCI_RD_REM_VER_INFO_CMP_EVT_CODE = 0x0C, + HCI_QOS_SETUP_CMP_EVT_CODE = 0x0D, + HCI_CMD_CMP_EVT_CODE = 0x0E, + HCI_CMD_STATUS_EVT_CODE = 0x0F, + HCI_HW_ERR_EVT_CODE = 0x10, + HCI_FLUSH_OCCURRED_EVT_CODE = 0x11, + HCI_ROLE_CHG_EVT_CODE = 0x12, + HCI_NB_CMP_PKTS_EVT_CODE = 0x13, + HCI_MODE_CHG_EVT_CODE = 0x14, + HCI_RETURN_LINK_KEYS_EVT_CODE = 0x15, + HCI_PIN_CODE_REQ_EVT_CODE = 0x16, + HCI_LK_REQ_EVT_CODE = 0x17, + HCI_LK_NOTIF_EVT_CODE = 0x18, + HCI_DATA_BUF_OVFLW_EVT_CODE = 0x1A, + HCI_MAX_SLOT_CHG_EVT_CODE = 0x1B, + HCI_RD_CLK_OFF_CMP_EVT_CODE = 0x1C, + HCI_CON_PKT_TYPE_CHG_EVT_CODE = 0x1D, + HCI_QOS_VIOL_EVT_CODE = 0x1E, + HCI_PAGE_SCAN_REPET_MODE_CHG_EVT_CODE = 0x20, + HCI_FLOW_SPEC_CMP_EVT_CODE = 0x21, + HCI_INQ_RES_WITH_RSSI_EVT_CODE = 0x22, + HCI_RD_REM_EXT_FEATS_CMP_EVT_CODE = 0x23, + HCI_SYNC_CON_CMP_EVT_CODE = 0x2C, + HCI_SYNC_CON_CHG_EVT_CODE = 0x2D, + HCI_SNIFF_SUB_EVT_CODE = 0x2E, + HCI_EXT_INQ_RES_EVT_CODE = 0x2F, + HCI_ENC_KEY_REFRESH_CMP_EVT_CODE = 0x30, + HCI_IO_CAP_REQ_EVT_CODE = 0x31, + HCI_IO_CAP_RSP_EVT_CODE = 0x32, + HCI_USER_CFM_REQ_EVT_CODE = 0x33, + HCI_USER_PASSKEY_REQ_EVT_CODE = 0x34, + HCI_REM_OOB_DATA_REQ_EVT_CODE = 0x35, + HCI_SP_CMP_EVT_CODE = 0x36, + HCI_LINK_SUPV_TO_CHG_EVT_CODE = 0x38, + HCI_ENH_FLUSH_CMP_EVT_CODE = 0x39, + HCI_USER_PASSKEY_NOTIF_EVT_CODE = 0x3B, + HCI_KEYPRESS_NOTIF_EVT_CODE = 0x3C, + HCI_REM_HOST_SUPP_FEATS_NOTIF_EVT_CODE = 0x3D, + HCI_LE_META_EVT_CODE = 0x3E, + HCI_MAX_EVT_MSK_PAGE_1_CODE = 0x40, + HCI_SYNC_TRAIN_CMP_EVT_CODE = 0x4F, + HCI_SYNC_TRAIN_REC_EVT_CODE = 0x50, + HCI_CON_SLV_BCST_REC_EVT_CODE = 0x51, + HCI_CON_SLV_BCST_TO_EVT_CODE = 0x52, + HCI_TRUNC_PAGE_CMP_EVT_CODE = 0x53, + HCI_SLV_PAGE_RSP_TO_EVT_CODE = 0x54, + HCI_CON_SLV_BCST_CH_MAP_CHG_EVT_CODE = 0x55, + HCI_AUTH_PAYL_TO_EXP_EVT_CODE = 0x57, + HCI_MAX_EVT_MSK_PAGE_2_CODE = 0x58, + HCI_DBG_META_EVT_CODE = 0xFF, + + /// LE Events Subcodes + HCI_LE_CON_CMP_EVT_SUBCODE = 0x01, + HCI_LE_ADV_REPORT_EVT_SUBCODE = 0x02, + HCI_LE_CON_UPDATE_CMP_EVT_SUBCODE = 0x03, + HCI_LE_RD_REM_USED_FEATS_CMP_EVT_SUBCODE = 0x04, + HCI_LE_LTK_REQUEST_EVT_SUBCODE = 0x05, + HCI_LE_REM_CON_PARAM_REQ_EVT_SUBCODE = 0x06, + HCI_LE_DATA_LEN_CHG_EVT_SUBCODE = 0x07, + HCI_LE_RD_LOC_P256_PUB_KEY_CMP_EVT_SUBCODE = 0x08, + HCI_LE_GEN_DHKEY_CMP_EVT_SUBCODE = 0x09, + HCI_LE_ENH_CON_CMP_EVT_SUBCODE = 0x0A, + HCI_LE_DIR_ADV_REP_EVT_SUBCODE = 0x0B, + #if (BLE_2MBPS) + HCI_LE_PHY_UPD_CMP_EVT_SUBCODE = 0x0C, + #endif // (BLE_2MBPS) + HCI_VS_SET_PREF_SLAVE_LATENCY_CMP_EVT_SUBCODE = 0x0D, + /// DBG Events Subcodes + #if (BLE_EMB_PRESENT && BLE_TESTER) + HCI_DBG_BLE_TST_LLCP_RECV_EVT_SUBCODE = 0x01, + #endif // (BLE_EMB_PRESENT && BLE_TESTER) + #if (RW_DEBUG) + HCI_DBG_ASSERT_ERR_EVT_SUBCODE = 0x02, + #endif //(RW_DEBUG) +}; + +/// Event mask page enum +enum hci_evt_mask_page +{ + /// page 0 + HCI_PAGE_0, + /// page 1 + HCI_PAGE_1, + /// page 2 + HCI_PAGE_2, + /// Default + HCI_PAGE_DFT +}; +/// HCI ACL data RX packet structure +struct hci_acl_data_rx +{ + /// connection handle + uint16_t conhdl; + /// broadcast and packet boundary flag + uint8_t pb_bc_flag; + /// length of the data + uint16_t length; + + #if (BLE_EMB_PRESENT) + /// Handle of the descriptor containing RX Data + uint8_t rx_hdl; + #else// (BLE_HOST_PRESENT) + /// Pointer to the data buffer + uint8_t* buffer; + #endif // (BLE_EMB_PRESENT) / (BLE_HOST_PRESENT) +}; + +/// HCI ACL data TX packet structure +struct hci_acl_data_tx +{ + /// connection handle + uint16_t conhdl; + /// broadcast and packet boundary flag + uint8_t pb_bc_flag; + /// length of the data + uint16_t length; + #if (BLE_EMB_PRESENT) + /// Pointer to the first descriptor containing RX Data + struct em_buf_node *buf; + #else // (BLE_HOST_PRESENT) + /// Pointer to the data buffer + uint8_t* buffer; + #endif // (BLE_EMB_PRESENT) / (BLE_HOST_PRESENT) +}; + +#if (BT_EMB_PRESENT) +/// HCI ACL data packet structure +struct hci_bt_acl_data_tx +{ + /// Buffer element + struct bt_em_acl_buf_elt* buf_elt; +}; + +/// HCI ACL data Rx packet structure +struct hci_bt_acl_data_rx +{ + /// EM buffer pointer + uint16_t buf_ptr; + /// Data length + Data Flags (PBF + BF) + uint16_t data_len_flags; +}; + +/// HCI Synchronous data packet structure +struct hci_bt_sync_data_tx +{ + /// Buffer element + struct bt_em_sync_buf_elt* buf_elt; +}; + +/// HCI Synchronous data Rx packet structure +struct hci_bt_sync_data_rx +{ + /// EM buffer pointer + uint16_t buf_ptr; + /// Data length + uint8_t data_len; + /// Packet status flag + uint8_t packet_status_flag; + /// Synchronous link identifier + uint8_t sync_link_id; +}; +#endif // (BT_EMB_PRESENT) + + +/* + * HCI COMMANDS PARAMETERS (to classify) + **************************************************************************************** + */ + +/// HCI basic command structure with connection handle +struct hci_basic_conhdl_cmd +{ + /// connection handle + uint16_t conhdl; +}; + +/// HCI basic command structure with BD address +struct hci_basic_bd_addr_cmd +{ + ///BdAddr + struct bd_addr bd_addr; +}; + +/// HCI Accept connection request command structure +struct hci_accept_con_req_cmd +{ + ///BdAddr + struct bd_addr bd_addr; + ///Page Scan Repetition Mode + uint8_t role; +}; + +/// HCI Accept synchronous connection request command structure +struct hci_accept_sync_con_req_cmd +{ + ///BdAddr + struct bd_addr bd_addr; + ///Transmit bandwidth + uint32_t tx_bw; + ///Receive bandwidth + uint32_t rx_bw; + ///Max latency + uint16_t max_lat; + ///Voice settings + uint16_t vx_set; + ///Retransmission effort + uint8_t retx_eff; + ///Packet type + uint16_t pkt_type ; +}; + +/// HCI Enhanced Accept synchronous connection request command structure +struct hci_enh_accept_sync_con_cmd +{ + + struct bd_addr bd_addr; // BD address + uint32_t tx_bw; // Transmit Bandwidth (in B/sec) + uint32_t rx_bw; // Receive Bandwidth (in B/sec) + uint8_t tx_cod_fmt[5]; // Transmit Coding Format + uint8_t rx_cod_fmt[5]; // Receive Coding Format + uint16_t tx_cod_fr_sz; // Transmit Codec Frame Size (in B) + uint16_t rx_cod_fr_sz; // Receive Codec Frame Size (in B) + uint32_t in_bw; // Input Bandwidth (in B/sec) + uint32_t out_bw; // Output Bandwidth (in B/sec) + uint8_t in_cod_fmt[5]; // Input Coding Format + uint8_t out_cod_fmt[5]; // Output Coding Format + uint16_t in_cod_data_sz; // Input Coded Data Size (in bits) + uint16_t out_cod_data_sz; // Output Coded Data Size (in bits) + uint8_t in_data_fmt; // Input PCM Data Format + uint8_t out_data_fmt; // Output PCM Data Format + uint8_t in_msb_pos; // Input PCM Sample Payload MSB Position (in bits) + uint8_t out_msb_pos; // Output PCM Sample Payload MSB Position (in bits) + uint8_t in_data_path; // Input Data Path + uint8_t out_data_path; // Output Data Path + uint8_t in_tr_unit_sz; // Input Transport Unit Size (in bits) + uint8_t out_tr_unit_sz; // Output Transport Unit Size (in bits) + uint16_t max_lat; // Max Latency (in ms) + uint16_t packet_type; // Packet Type + uint8_t retx_eff; // Retransmission Effort + + +}; + +/// HCI reject connection request command structure +struct hci_reject_con_req_cmd +{ + ///BdAddr + struct bd_addr bd_addr; + ///Reason + uint8_t reason; +}; + +/// HCI reject synchronous connection request command structure +struct hci_reject_sync_con_req_cmd +{ + ///BdAddr + struct bd_addr bd_addr; + ///Reason + uint8_t reason; +}; + +/// HCI link key request reply command structure +struct hci_lk_req_reply_cmd +{ + ///BdAddr + struct bd_addr bd_addr; + ///Key + struct ltk key; +}; + +/// HCI link key request reply command structure +struct hci_pin_code_req_reply_cmd +{ + ///BdAddr + struct bd_addr bd_addr; + ///Pin code length + uint8_t pin_len; + ///Key + struct pin_code pin; +}; + +/// HCI switch role command structure +struct hci_switch_role_cmd +{ + ///BdAddr + struct bd_addr bd_addr; + ///Read all flag + uint8_t role; +}; + +/// HCI flow specification command parameters structure +struct hci_flow_spec_cmd +{ + ///Connection handle + uint16_t conhdl; + ///Flags + uint8_t flags; + ///Flow direction + uint8_t flow_dir; + ///Service type + uint8_t serv_type; + ///Token rate + uint32_t tk_rate; + ///Token buffer size + uint32_t tk_buf_sz; + ///Peak bandwidth + uint32_t pk_bw; + ///Access latency + uint32_t acc_lat; +}; + +/// HCI enhanced flush command parameters structure +struct hci_enh_flush_cmd +{ + ///Connection handle + uint16_t conhdl; + ///Packet Type + uint8_t pkt_type; +}; + +/// HCI command complete event structure for the read auto flush TO command +struct hci_rd_auto_flush_to_cmd_cmp_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///Flush timeout + uint16_t flush_to; +}; + +/// HCI write flush timeout command parameters structure +struct hci_wr_auto_flush_to_cmd +{ + ///Connection handle + uint16_t conhdl; + ///Flush timeout + uint16_t flush_to; +}; + +/// HCI change connection packet type command parameters structure +struct hci_chg_con_pkt_type_cmd +{ + ///Connection handle + uint16_t conhdl; + ///Packet type + uint16_t pkt_type; +}; + +/// HCI read link policy settings command parameters structure +struct hci_rd_link_pol_stg_cmd_cmp_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///Link policy + uint16_t lnk_policy; +}; + +/// HCI read link policy settings command parameters structure +struct hci_wr_link_pol_stg_cmd +{ + ///Connection handle + uint16_t conhdl; + ///Link policy + uint16_t lnk_policy; +}; + +/// HCI sniff mode request command parameters structure +struct hci_sniff_mode_cmd +{ + ///Connection handle + uint16_t conhdl; + ///Sniff max interval + uint16_t max_int; + ///Sniff min interval + uint16_t min_int; + ///Sniff attempt + uint16_t attempt; + ///Sniff timeout + uint16_t timeout; +}; + +/// HCI sniff subrating mode request command parameters structure +struct hci_sniff_sub_cmd +{ + ///Connection handle + uint16_t conhdl; + ///Sniff max latency + uint16_t max_lat; + ///Minimun remote TO + uint16_t min_rem_to; + ///Minimun local TO + uint16_t min_loc_to; +}; + +/// HCI role discovery complete event parameters structure +struct hci_role_discovery_cmd_cmp_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///Role + uint8_t role; + +}; + +/// HCI read failed contact counter command parameters structure +struct hci_rd_fail_contact_cnt_cmd_cmp_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///Fail contact counter + uint16_t fail_cnt; +}; + +/// HCI read link quality complete event parameters structure +struct hci_rd_link_qual_cmd_cmp_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///Quality type + uint8_t quality; +}; + +/// HCI read afh channel map complete event parameters structure +struct hci_rd_afh_ch_map_cmd_cmp_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + /// AFH mode + uint8_t afh_mode; + /// AFH channel map + struct chnl_map afh_map; +}; + +/// HCI read lmp handle complete event parameters structure +struct hci_rd_lmp_hdl_cmd_cmp_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///lmp handle + uint8_t lmp_hdl; + ///rsvd + uint32_t rsvd; +}; + +/// HCI read remote extended features command parameters structure +struct hci_rd_rem_ext_feats_cmd +{ + ///Connection handle + uint16_t conhdl; + ///page number + uint8_t pg_nb; +}; + +/// HCI read encryption key size complete event parameters structure +struct hci_rd_enc_key_size_cmd_cmp_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///Key size + uint8_t key_sz; +}; + +/// HCI read enhanced transmit power command parameters structure +struct hci_rd_enh_tx_pwr_lvl_cmd +{ + ///Connection handle + uint16_t conhdl; + ///Type + uint8_t type; +}; + +/// HCI read enhanced transmit power complete event parameters structure +struct hci_rd_enh_tx_pwr_lvl_cmd_cmp_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///Transmit power GFSK + uint8_t pw_gfsk; + ///Transmit power DQPSK + uint8_t pw_dqpsk; + ///Transmit power 8DPSK + uint8_t pw_8dpsk; +}; + + +/* + * HCI LINK CONTROL COMMANDS PARAMETERS + **************************************************************************************** + */ + +/// Format of the message of the Group: LINK_CONTROL_COMMANDS +/// HCI Inquiry command parameters structure +struct hci_inq_cmd +{ + ///Lap + struct lap lap; + ///Inquiry Length + uint8_t inq_len; + ///Number of response + uint8_t nb_rsp; +}; +struct hci_per_inq_mode_cmd +{ + ///Maximum period length + uint16_t max_per_len; + ///Minimum period length + uint16_t min_per_len; + ///lap + struct lap lap; + ///Inquiry length + uint8_t inq_len; + ///Number of response + uint8_t nb_rsp; +}; +struct hci_create_con_cmd +{ + /// BdAddr + struct bd_addr bd_addr; + /// Packet Type + uint16_t pkt_type; + /// Page Scan Repetition Mode + uint8_t page_scan_rep_mode; + /// Reserved + uint8_t rsvd; + /** + * Clock Offset + * + * Bits 14-0 : Bits 16-2 of CLKNslave-CLK + * Bit 15 : Clock_Offset_Valid_Flag + * Invalid Clock Offset = 0 + * Valid Clock Offset = 1 + */ + uint16_t clk_off; + /// Allow Switch + uint8_t switch_en; +}; + +/// HCI disconnect command structure +struct hci_disconnect_cmd +{ + /// connection handle + uint16_t conhdl; + /// reason + uint8_t reason; +}; + +/// HCI master link key command structure +struct hci_master_lk_cmd +{ + ///Key flag + uint8_t key_flag; +}; + +/// HCI authentication request command parameters structure +struct hci_set_con_enc_cmd +{ + ///Connection handle + uint16_t conhdl; + ///Encryption mode + uint8_t enc_en; +}; + +struct hci_rem_name_req_cmd +{ + ///BdAddr + struct bd_addr bd_addr; + ///Page Scan Repetition Mode + uint8_t page_scan_rep_mode; + ///Reserved + uint8_t rsvd; + /** + * Clock Offset + * + * Bits 14-0 : Bits 16-2 of CLKNslave-CLK + * Bit 15 : Clock_Offset_Valid_Flag + * Invalid Clock Offset = 0 + * Valid Clock Offset = 1 + */ + uint16_t clk_off; +}; + +/// HCI remote name request complete event structure +struct hci_rem_name_req_cmp_evt +{ + /// Status + uint8_t status; + /// BD Addr + struct bd_addr bd_addr; + /// Name + struct device_name name; +}; + +/// HCI setup synchronous connection command structure +struct hci_setup_sync_con_cmd +{ + ///Connection handle + uint16_t conhdl; + ///Transmit bandwidth + uint32_t tx_bw; + ///Receive bandwidth + uint32_t rx_bw; + ///Max latency + uint16_t max_lat; + ///Voice setting + uint16_t vx_set; + ///Retransmission effort + uint8_t retx_eff; + ///Packet type + uint16_t pkt_type; +}; + +/// HCI setup synchronous connection command structure +struct hci_enh_setup_sync_con_cmd +{ + uint16_t conhdl; // Connection Handle + uint32_t tx_bw; // Transmit Bandwidth (in B/sec) + uint32_t rx_bw; // Receive Bandwidth (in B/sec) + uint8_t tx_cod_fmt[5]; // Transmit Coding Format + uint8_t rx_cod_fmt[5]; // Receive Coding Format + uint16_t tx_cod_fr_sz; // Transmit Codec Frame Size (in B) + uint16_t rx_cod_fr_sz; // Receive Codec Frame Size (in B) + uint32_t in_bw; // Input Bandwidth (in B/sec) + uint32_t out_bw; // Output Bandwidth (in B/sec) + uint8_t in_cod_fmt[5]; // Input Coding Format + uint8_t out_cod_fmt[5]; // Output Coding Format + uint16_t in_cod_data_sz; // Input Coded Data Size (in bits) + uint16_t out_cod_data_sz; // Output Coded Data Size (in bits) + uint8_t in_data_fmt; // Input PCM Data Format + uint8_t out_data_fmt; // Output PCM Data Format + uint8_t in_msb_pos; // Input PCM Sample Payload MSB Position (in bits) + uint8_t out_msb_pos; // Output PCM Sample Payload MSB Position (in bits) + uint8_t in_data_path; // Input Data Path + uint8_t out_data_path; // Output Data Path + uint8_t in_tr_unit_sz; // Input Transport Unit Size (in bits) + uint8_t out_tr_unit_sz; // Output Transport Unit Size (in bits) + uint16_t max_lat; // Max Latency (in ms) + uint16_t packet_type; // Packet Type + uint8_t retx_eff; // Retransmission Effort +}; + +/// HCI io capability request reply command structure +struct hci_io_cap_req_reply_cmd +{ + ///BdAddr + struct bd_addr bd_addr; + ///IO capability + uint8_t io_capa; + ///OOB data present + uint8_t oob_data_pres; + ///Authentication requirements + uint8_t auth_req; + +}; + +/// HCI io capability request negative reply command structure +struct hci_io_cap_req_neg_reply_cmd +{ + ///BdAddr + struct bd_addr bd_addr; + ///Reason + uint8_t reason; +}; + +/// HCI user pass key request reply command structure +struct hci_user_passkey_req_reply_cmd +{ + ///BdAddr + struct bd_addr bd_addr; + ///Numeric value + uint32_t num_val; +}; + +/// HCI remote oob data request reply command structure +struct hci_rem_oob_data_req_reply_cmd +{ + ///BdAddr + struct bd_addr bd_addr; + ///hash part + struct hash oob_c; + ///random part + struct randomizer oob_r; +}; + +/// HCI send key press notification command structure +struct hci_send_keypress_notif_cmd +{ + ///BdAddr + struct bd_addr bd_addr; + ///Notification type + uint8_t notif_type; +}; + +/// HCI truncated page command structure +struct hci_trunc_page_cmd +{ + ///BdAddr + struct bd_addr bd_addr; + /// Page Scan Repetition Mode + uint8_t page_scan_rep_mode; + /** + * Clock Offset + * + * Bits 14-0 : Bits 16-2 of CLKNslave-CLK + * Bit 15 : Clock_Offset_Valid_Flag + * Invalid Clock Offset = 0 + * Valid Clock Offset = 1 + */ + uint16_t clk_off; +}; + +/// HCI truncated page cancel command structure +struct hci_trunc_page_can_cmd +{ + ///BdAddr + struct bd_addr bd_addr; +}; + +/// HCI set connectionless slave broadcast command structure +struct hci_set_con_slv_bcst_cmd +{ + /// Enable + uint8_t enable; + /// LT_ADDR + uint8_t lt_addr; + /// LPO_Allowed + uint8_t lpo_allowed; + /// Packet_Type + uint16_t packet_type; + /// Interval_Min (in slots) + uint16_t interval_min; + /// Interval_Max (in slots) + uint16_t interval_max; + /// CSB_supervisionTO (in slots) + uint16_t csb_supv_to; +}; + +/// HCI set connectionless slave broadcast command complete event structure +struct hci_set_con_slv_bcst_cmd_cmp_evt +{ + /// Status + uint8_t status; + /// LT_ADDR + uint8_t lt_addr; + /// Interval (in slots) + uint16_t interval; +}; + +/// HCI set connectionless slave broadcast receive command structure +struct hci_set_con_slv_bcst_rec_cmd +{ + /// Enable + uint8_t enable; + /// BD_ADDR + struct bd_addr bd_addr; + /// LT_ADDR + uint8_t lt_addr; + /// Interval (in slots) + uint16_t interval; + /// Clock_Offset (28 bits) - (CLKNslave � CLK) modulo 2^28 + uint32_t clock_offset; + /// Next_Connectionless_Slave_Broadcast_Clock (28 bits) + uint32_t next_csb_clock; + /// CSB_supervisionTO (in slots) + uint16_t csb_supv_to; + /// Remote_Timing_Accuracy (in ppm) + uint8_t remote_timing_accuracy; + /// Skip + uint8_t skip; + /// Packet_Type + uint16_t packet_type; + /// AFH_Channel_Map + struct chnl_map afh_ch_map; +}; + +/// HCI set connectionless slave broadcast receive command complete event structure +struct hci_set_con_slv_bcst_rec_cmd_cmp_evt +{ + /// Status + uint8_t status; + /// BD_ADDR + struct bd_addr bd_addr; + /// LT_ADDR + uint8_t lt_addr; +}; + +/// HCI Receive Synchronization Train command structure +struct hci_rec_sync_train_cmd +{ + /// BD_ADDR + struct bd_addr bd_addr; + /// Synchronization_scanTO (in slots) + uint16_t sync_scan_to; + /// Sync_Scan_Window (in slots) + uint16_t sync_scan_win; + /// Sync_Scan_Interval (in slots) + uint16_t sync_scan_int; +}; + +/// HCI remote oob extended data request reply command structure +struct hci_rem_oob_ext_data_req_reply_cmd +{ + ///BdAddr + struct bd_addr bd_addr; + ///hash part + struct hash oob_c_192; + ///random part + struct randomizer oob_r_192; + ///hash part + struct hash oob_c_256; + ///random part + struct randomizer oob_r_256; +}; + + +struct hci_le_generate_dh_key_cmd +{ + uint8_t public_key[64]; +}; +/* + * HCI LINK POLICY COMMANDS PARAMETERS + **************************************************************************************** + */ + +/// HCI setup quality of service command structure +struct hci_qos_setup_cmd +{ + ///Connection handle + uint16_t conhdl; + ///Flags + uint8_t flags; + ///Service type + uint8_t serv_type; + ///Token rate + uint32_t tok_rate; + ///Peak bandwidth + uint32_t pk_bw; + ///Latency + uint32_t lat; + ///Delay variation + uint32_t del_var; +}; + +/// HCI command complete event structure for read default link policy command structure +struct hci_rd_dft_link_pol_stg_cmd_cmp_evt +{ + ///Status of the command reception + uint8_t status; + ///Link policy + uint16_t link_pol_stg; +}; + +struct hci_wr_dft_link_pol_stg_cmd +{ + ///Link policy + uint16_t link_pol_stg; +}; + +/* + * HCI CONTROL & BASEBAND COMMANDS PARAMETERS + **************************************************************************************** + */ + +/// HCI set event mask command structure +struct hci_set_evt_mask_cmd +{ + ///Event Mask + struct evt_mask event_mask; +}; + +/// HCI set event filter command structure +struct hci_set_evt_filter_cmd +{ + /// Filter type + uint8_t filter_type; + + /// Filters + union hci_filter + { + uint8_t clear_all_filter_reserved; + + /// Inquiry Result Filter + struct inq_res_filter + { + /// Filter Condition type + uint8_t cond_type; + + /// Filter conditions + union hci_inq_filter_cond + { + /// Reserved value (Inquiry Result Filter - condition type 0x00 has no condition) + uint8_t cond_0_reserved; + + /// Inquiry Result Filter Condition - condition type 0x01 + struct inq_res_filter_cond_1 + { + /// Class_of_Device + struct devclass class_of_dev; + /// Class_of_Device_Mask + struct devclass class_of_dev_msk; + } cond_1; + + /// Inquiry Result Filter Condition - condition type 0x02 + struct inq_res_filter_cond_2 + { + /// BD Address + struct bd_addr bd_addr; + } cond_2; + } cond; + } inq_res; + + /// Connection Setup Filter + struct con_set_filter + { + /// Filter Condition type + uint8_t cond_type; + + /// Filter conditions + union hci_con_filter_cond + { + /// Connection Setup Filter Condition - condition type 0x00 + struct con_set_filter_cond_0 + { + /// Auto_Accept_Flag + uint8_t auto_accept; + } cond_0; + + /// Connection Setup Filter Condition - condition type 0x01 + struct con_set_filter_cond_1 + { + /// Class_of_Device + struct devclass class_of_dev; + /// Class_of_Device_Mask + struct devclass class_of_dev_msk; + /// Auto_Accept_Flag + uint8_t auto_accept; + } cond_1; + + /// Connection Setup Filter Condition - condition type 0x02 + struct con_set_filter_cond_2 + { + /// BD Address + struct bd_addr bd_addr; + /// Auto_Accept_Flag + uint8_t auto_accept; + } cond_2; + } cond; + + } con_set; + + } filter; +}; + +/// HCI command completed event structure for the flush command +struct hci_flush_cmd_cmp_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; +}; + +/// HCI command complete event structure for the Read pin type command +struct hci_rd_pin_type_cmd_cmp_evt +{ + ///Status of the command + uint8_t status; + ///PIN type + uint8_t pin_type; +}; + +struct hci_wr_pin_type_cmd +{ + ///PIN type + uint8_t pin_type; +}; + +struct hci_rd_stored_lk_cmd +{ + ///BdAddr + struct bd_addr bd_addr; + ///Read all flag + uint8_t rd_all_flag; +}; + +/// HCI command complete event structure for read stored link key command +struct hci_rd_stored_lk_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + ///Maximum number of key + uint16_t num_key_max; + ///Read number of key + uint16_t num_key_rd; +}; + +#if BT_EMB_PRESENT +struct hci_wr_stored_lk_cmd +{ + /// Number of key to write + uint8_t num_key_wr; + + /// BD Address + Key table + struct bd_addr_plus_key link_keys[HCI_MAX_CMD_PARAM_SIZE / sizeof(struct bd_addr_plus_key)]; +}; +#endif //BT_EMB_PRESENT + +/// HCI command complete event structure for write stored link key command +struct hci_wr_stored_lk_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + ///number of key written + uint8_t num_key_wr; +}; + +struct hci_del_stored_lk_cmd +{ + ///BdAddr + struct bd_addr bd_addr; + ///Delete all flag + uint8_t del_all_flag; +}; + +/// HCI command complete event structure for delete stored link key command +struct hci_del_stored_lk_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + ///Read number of key + uint16_t num_key_del; +}; + +struct hci_wr_local_name_cmd +{ + ///Name + struct device_name name; +}; + +/// HCI command complete event structure for the read local name command +struct hci_rd_local_name_cmd_cmp_evt +{ + ///Status of the command + uint8_t status; + ///Name + uint8_t name[BD_NAME_SIZE]; +}; + +/// HCI command complete event structure for the Read connection accept to command +struct hci_rd_con_accept_to_cmd_cmp_evt +{ + ///Status of the command + uint8_t status; + /// Connection accept timeout (in slots) + uint16_t con_acc_to; +}; + +struct hci_wr_con_accept_to_cmd +{ + /// Connection accept timeout (in slots) + uint16_t con_acc_to; +}; + +/// HCI command complete event structure for the Read page to command +struct hci_rd_page_to_cmd_cmp_evt +{ + ///Status of the command + uint8_t status; + /// Page timeout (in slots) + uint16_t page_to; +}; + +struct hci_wr_page_to_cmd +{ + /// Page timeout (in slots) + uint16_t page_to; +}; + +/// HCI command complete event structure for the Read scan enable command +struct hci_rd_scan_en_cmd_cmp_evt +{ + ///Status of the command + uint8_t status; + ///Status of the scan enable + uint8_t scan_en; +}; + +struct hci_wr_scan_en_cmd +{ + ///Status of the scan enable + uint8_t scan_en; +}; + +/// HCI command complete event structure for the Read scan activity command +struct hci_rd_page_scan_act_cmd_cmp_evt +{ + ///Status of the command + uint8_t status; + /// Page scan interval (in slots) + uint16_t page_scan_intv; + /// Page scan window (in slots) + uint16_t page_scan_win; +}; + +struct hci_wr_page_scan_act_cmd +{ + /// Page scan interval (in slots) + uint16_t page_scan_intv; + /// Page scan window (in slots) + uint16_t page_scan_win; +}; + +/// HCI command complete event structure for the Read inquiry scan activity command +struct hci_rd_inq_scan_act_cmd_cmp_evt +{ + /// Status of the command + uint8_t status; + /// Inquiry scan interval (in slots) + uint16_t inq_scan_intv; + /// Inquiry scan window (in slots) + uint16_t inq_scan_win; +}; + +struct hci_wr_inq_scan_act_cmd +{ + /// Inquiry scan interval (in slots) + uint16_t inq_scan_intv; + /// Inquiry scan window (in slots) + uint16_t inq_scan_win; +}; + +/// HCI command complete event structure for the Read authentication command +struct hci_rd_auth_en_cmd_cmp_evt +{ + ///Status of the command + uint8_t status; + ///Value of the authentication + uint8_t auth_en; +}; + +struct hci_wr_auth_en_cmd +{ + ///Value of the authentication + uint8_t auth_en; +}; + +/// HCI command complete event structure for the read class of device command +struct hci_rd_class_of_dev_cmd_cmp_evt +{ + ///Status of the command + uint8_t status; + ///Class of device + struct devclass class_of_dev; +}; + +struct hci_wr_class_of_dev_cmd +{ + ///Class of device + struct devclass class_of_dev; +}; + +/// HCI read voice settings complete event +struct hci_rd_voice_stg_cmd_cmp_evt +{ + ///Status of the command reception + uint8_t status; + /// Voice setting + uint16_t voice_stg; +}; + +struct hci_wr_voice_stg_cmd +{ + /// voice setting + uint16_t voice_stg; +}; + +/// HCI command complete event structure for read number of broadcast retrans command +struct hci_rd_nb_bdcst_retx_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + ///Read number of broadcast retransmission + uint8_t num_bcst_ret; +}; + +struct hci_wr_nb_bdcst_retx_cmd +{ + ///Read number of broadcast retransmission + uint8_t num_bcst_ret; +}; + +/// HCI command complete event structure for the Read Synchronous Flow Control command +struct hci_rd_sync_flow_ctrl_en_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + ///Synchronous flow control enable + uint8_t sync_flow_ctrl_en; +}; + +struct hci_wr_sync_flow_ctrl_en_cmd +{ + /// Synchronous Flow Control enable + uint8_t sync_flow_ctrl_en; +}; + +///HCI set controller to host flow control command +struct hci_set_ctrl_to_host_flow_ctrl_cmd +{ + ///Flow control enable for controller + uint8_t flow_cntl; +}; + +///HCI host buffer size command +struct hci_host_buf_size_cmd +{ + ///Host ACL packet length + uint16_t acl_pkt_len; + ///Host synchronous packet length + uint8_t sync_pkt_len; + ///Host Total number of ACL packets allowed + uint16_t nb_acl_pkts; + ///Host total number of synchronous packets allowed + uint16_t nb_sync_pkts; +}; + +#if BT_EMB_PRESENT +///HCI host number of completed packets command +struct hci_host_nb_cmp_pkts_cmd +{ + ///Number of handles for which the completed packets number is given + uint8_t nb_of_hdl; + ///Array of connection handles + uint16_t con_hdl[MAX_NB_ACTIVE_ACL]; + ///Array of number of completed packets values for connection handles. + uint16_t nb_comp_pkt[MAX_NB_ACTIVE_ACL]; +}; +#elif BLE_EMB_PRESENT || BLE_HOST_PRESENT +///HCI host number of completed packets command +struct hci_host_nb_cmp_pkts_cmd +{ + ///Number of handles for which the completed packets number is given + uint8_t nb_of_hdl; + ///Array of connection handles + uint16_t con_hdl[BLE_CONNECTION_MAX+1]; // ensure that at least 1 element is present + ///Array of number of completed packets values for connection handles. + uint16_t nb_comp_pkt[BLE_CONNECTION_MAX+1]; // ensure that at least 1 element is present +}; +#endif //BLE_EMB_PRESENT || BLE_HOST_PRESENT + +/// HCI read link supervision timeout command parameters structure +struct hci_rd_link_supv_to_cmd_cmp_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///Link supervision timeout + uint16_t lsto_val; +}; + +/// HCI write link supervision timeout command parameters structure +struct hci_wr_link_supv_to_cmd +{ + ///Connection handle + uint16_t conhdl; + ///Link supervision timeout + uint16_t lsto_val; +}; + +/// HCI command complete event structure for the nb of supported IAC command +struct hci_rd_nb_supp_iac_cmd_cmp_evt +{ + ///Status of the command + uint8_t status; + ///nb_of iac + uint8_t nb_iac; +}; + +/// HCI command complete event structure for read current IAC LAP command +struct hci_rd_curr_iac_lap_cmd_cmp_evt +{ + ///Status of the command + uint8_t status; + ///nb of current iac + uint8_t nb_curr_iac; + ///lap + struct lap iac_lap; +}; + +/// HCI write current IAC LAP command structure +struct hci_wr_curr_iac_lap_cmd +{ + /// Number of current iac laps + uint8_t nb_curr_iac; + ///lap + struct lap iac_lap[(HCI_MAX_CMD_PARAM_SIZE / BD_ADDR_LAP_LEN) - 1]; +}; + +struct hci_set_afh_host_ch_class_cmd +{ + ///AFH channel map + struct chnl_map afh_ch; +}; + +/// HCI command complete event structure for write inquiry scan type command structure +struct hci_rd_inq_scan_type_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + /// Inquiry scan type + uint8_t inq_scan_type; +}; + +struct hci_wr_inq_scan_type_cmd +{ + /// Inquiry scan type + uint8_t inq_scan_type; +}; + +/// HCI command complete event structure for read inquiry mode command structure +struct hci_rd_inq_mode_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + /// Inquiry mode + uint8_t inq_mode; +}; + +struct hci_wr_inq_mode_cmd +{ + /// Inquiry mode + uint8_t inq_mode; +}; + +/// HCI command complete event structure for write page scan type command structure +struct hci_rd_page_scan_type_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + /// Page scan type + uint8_t page_scan_type; +}; + +struct hci_wr_page_scan_type_cmd +{ + /// Page scan type + uint8_t page_scan_type; +}; + +/// HCI command complete event structure for read assessment mode command structure +struct hci_rd_afh_ch_assess_mode_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + ///AFH channel assessment mode + uint8_t afh_ch_ass_mode; +}; + +struct hci_wr_afh_ch_assess_mode_cmd +{ + ///AFH channel assessment mode + uint8_t afh_ch_ass_mode; +}; + +/// HCI command complete event structure for remote name request cancel command +struct hci_rd_ext_inq_rsp_cmd_cmp_evt +{ + ///status + uint8_t status; + ///FEC required + uint8_t fec_req; + ///Extended inquiry response + struct eir eir; +}; + +struct hci_wr_ext_inq_rsp_cmd +{ + ///FEC required + uint8_t fec_req; + ///Extended inquiry response + struct eir eir; +}; + +/// HCI command complete event structure for remote name request cancel command +struct hci_rd_sp_mode_cmd_cmp_evt +{ + ///status + uint8_t status; + ///Simple pairing mode + uint8_t sp_mode; +}; + +struct hci_wr_sp_mode_cmd +{ + ///Simple pairing mode + uint8_t sp_mode; +}; + +/// HCI command complete event structure for read oob data command +struct hci_rd_loc_oob_data_cmd_cmp_evt +{ + ///status + uint8_t status; + ///hash part + struct hash oob_c; + ///random part + struct randomizer oob_r; +}; + +/// HCI command complete event structure for read inquiry response transmit power command +struct hci_rd_inq_rsp_tx_pwr_lvl_cmd_cmp_evt +{ + ///status + uint8_t status; + ///TX power + uint8_t tx_pwr; +}; + +struct hci_wr_inq_tx_pwr_lvl_cmd +{ + ///TX power + int8_t tx_pwr; +}; + +/// HCI command complete event structure for read erroneous data reporting command +struct hci_rd_dft_err_data_rep_cmd_cmp_evt +{ + ///status + uint8_t status; + ///Erroneous data reporting + uint8_t err_data_rep; +}; + +struct hci_wr_dft_err_data_rep_cmd +{ + ///Erroneous data reporting + uint8_t err_data_rep; +}; + +/// HCI read LE Host Supported complete event +struct hci_rd_le_host_supp_cmd_cmp_evt +{ + ///Status + uint8_t status; + ///LE_Supported_Host + uint8_t le_supported_host; + ///Simultaneous_LE_Host + uint8_t simultaneous_le_host; +}; + +/// HCI write LE Host Supported command +struct hci_wr_le_host_supp_cmd +{ + ///LE_Supported_Host + uint8_t le_supported_host; + ///Simultaneous_LE_Host + uint8_t simultaneous_le_host; +}; + +/// HCI Set MWS Channel Parameters command +struct hci_set_mws_channel_params_cmd +{ + ///MWS_Channel_Enable + uint8_t mws_channel_enable; + ///MWS_RX_Center_Frequency + uint16_t mws_rx_center_frequency; + ///MWS_TX_Center_Frequency + uint16_t mws_tx_center_frequency; + ///MWS_RX_Channel_Bandwidth + uint16_t mws_rx_channel_bandwidth; + ///MWS_TX_Channel_Bandwidth + uint16_t mws_tx_channel_bandwidth; + ///MWS_Channel_Type + uint8_t mws_channel_type; +}; + +/// HCI Set External Frame Configuration command +struct hci_set_external_frame_config_cmd +{ + /// Ext_Frame_Duration + uint16_t ext_fr_duration; + /// Ext_Frame_Sync_Assert_Offset + int16_t ext_fr_sync_assert_offset; + /// Ext_Frame_Sync_Assert_Jitter + uint16_t ext_fr_sync_assert_jitter; + /// Ext_Frame_Num_Periods + uint8_t ext_fr_num_periods; + /// Period_Duration[i] + uint16_t period_duration[__ARRAY_EMPTY]; + /// Period_Type[i] + //uint8_t period_type[__ARRAY_EMPTY]; +}; + +/// HCI Set MWS Signaling command +struct hci_set_mws_signaling_cmd +{ + ///MWS_RX_Assert_Offset + int16_t mws_rx_assert_offset; + ///MWS_RX_Assert_Jitter + uint16_t mws_rx_assert_jitter; + ///MWS_RX_Deassert_Offset + int16_t mws_rx_deassert_offset; + ///MWS_RX_Deassert_Jitter + uint16_t mws_rx_deassert_jitter; + ///MWS_TX_Assert_Offset + int16_t mws_tx_assert_offset; + ///MWS_TX_Assert_Jitter + uint16_t mws_tx_assert_jitter; + ///MWS_TX_Deassert_Offset + int16_t mws_tx_deassert_offset; + ///MWS_TX_Deassert_Jitter + uint16_t mws_tx_deassert_jitter; + ///MWS_Pattern_Assert_Offset + int16_t mws_pattern_assert_offset; + ///MWS_Pattern_Assert_Jitter + uint16_t mws_pattern_assert_jitter; + ///MWS_Inactivity_Duration_Assert_Offset + int16_t mws_inactivity_duration_assert_offset; + ///MWS_Inactivity_Duration_Assert_Jitter + uint16_t mws_inactivity_duration_assert_jitter; + ///MWS_Scan_Frequency_Assert_Offset + int16_t mws_scan_frequency_assert_offset; + ///MWS_Scan_Frequency_Assert_Jitter + uint16_t mws_scan_frequency_assert_jitter; + ///MWS_Priority_Assert_Offset_Request + uint16_t mws_priority_assert_offset_request; +}; + +/// HCI Set MWS Signaling command complete event +struct hci_set_mws_signaling_cmd_cmp_evt +{ + ///Status + uint8_t status; + ///Bluetooth_Rx_Priority_Assert_Offset + int16_t bt_rx_prio_assert_offset; + ///Bluetooth_Rx_Priority_Assert_Jitter + uint16_t bt_rx_prio_assert_jitter; + ///Bluetooth_Rx_Priority_Deassert_Offset + int16_t bt_rx_prio_deassert_offset; + ///Bluetooth_Rx_Priority_Deassert_Jitter + uint16_t bt_rx_prio_deassert_jitter; + ///802_Rx_Priority_Assert_Offset + int16_t _802_rx_prio_assert_offset; + ///802_Rx_Priority_Assert_Jitter + uint16_t _802_rx_prio_assert_jitter; + ///802_Rx_Priority_Deassert_Offset + int16_t _802_rx_prio_deasssert_offset; + ///802_Rx_Priority_Deassert_Jitter + uint16_t _802_rx_prio_deassert_jitter; + ///Bluetooth_Tx_On_Assert_Offset + int16_t bt_tx_on_assert_offset; + ///Bluetooth_Tx_On_Assert_Jitter + uint16_t bt_tx_on_assert_jitter; + ///Bluetooth_Tx_On_Deassert_Offset + int16_t bt_tx_on_deassert_offset; + ///Bluetooth_Tx_On_Deassert_Jitter + uint16_t bt_tx_on_deassert_jitter; + ///802_Tx_On_Assert_Offset + int16_t _802_tx_on_assert_offset; + ///802_Tx_On_Assert_Jitter + uint16_t _802_tx_on_assert_jitter; + ///802_Tx_On_Deassert_Offset + int16_t _802_tx_on_deassert_offset; + ///802_Tx_On_Deassert_Jitter + uint16_t _802_tx_on_deassert_jitter; +}; + +/// HCI Set MWS Transport Layer command +struct hci_set_mws_transport_layer_cmd +{ + ///Transport_Layer + uint8_t transport_layer; + ///To_MWS_Baud_Rate + uint32_t to_mws_baud_rate; + ///From_MWS_Baud_Rate + uint32_t from_mws_baud_rate; +}; + +/// HCI Set MWS Scan Frequency Table command +struct hci_set_mws_scan_freq_table_cmd +{ + ///Num_Scan_Frequencies + uint8_t num_scan_frequencies; + ///Scan_Frequency_Low[i] + uint16_t scan_frequency_low[1/*__ARRAY_EMPTY*/]; + ///Scan_Frequency_High[i] + uint16_t scan_frequency_high[1/*__ARRAY_EMPTY*/]; +}; + +/// HCI Set MWS Pattern Configuration command +struct hci_set_mws_pattern_config_cmd +{ + ///MWS_PATTERN_Index + uint8_t mws_pattern_index; + ///MWS_PATTERN_NumIntervals + uint8_t mws_pattern_num_intervals; + ///MWS_PATTERN_IntervalDuration[i] + uint16_t mws_pattern_interval_duration[1/*__ARRAY_EMPTY*/]; + ///MWS_PATTERN_IntervalType[i] + uint8_t mws_pattern_interval_type[1/*__ARRAY_EMPTY*/]; +}; + +/// Hci Get MWS Transport Layer Configuration command complete event +struct hci_get_mws_transport_layer_config_cmd_cmp_evt +{ + ///Status + uint8_t status; + ///Num_Transports + uint8_t num_transports; + ///Transport_Layer[i] + uint8_t transport_layer[1/*__ARRAY_EMPTY*/]; + ///Num_Baud_Rates[i] + uint8_t num_baud_rates[1/*__ARRAY_EMPTY*/]; + ///To_MWS_Baud_Rate[k] + uint32_t to_mws_baud_rate[1/*__ARRAY_EMPTY*/]; + ///From_MWS_Baud_Rate[k] + uint32_t from_mws_baud_rate[1/*__ARRAY_EMPTY*/]; +}; + +/// HCI read Secure Connections Host Support complete event +struct hci_rd_sec_con_host_supp_cmd_cmp_evt +{ + ///Status + uint8_t status; + /// Secure Connections Host Support + uint8_t sec_con_host_supp; +}; + +/// HCI write Secure Connections Host Support command +struct hci_wr_sec_con_host_supp_cmd +{ + /// Secure Connections Host Support + uint8_t sec_con_host_supp; +}; + +/// HCI Set Reserved LT_ADDR command +struct hci_set_res_lt_addr_cmd +{ + /// LT_ADDR + uint8_t lt_addr; +}; + +/// HCI Set Reserved LT_ADDR command complete event +struct hci_set_res_lt_addr_cmd_cmp_evt +{ + /// Status + uint8_t status; + /// LT_ADDR + uint8_t lt_addr; +}; + +/// HCI Delete Reserved LT_ADDR command +struct hci_del_res_lt_addr_cmd +{ + /// LT_ADDR + uint8_t lt_addr; +}; + +/// HCI Delete Reserved LT_ADDR command complete event +struct hci_del_res_lt_addr_cmd_cmp_evt +{ + /// Status + uint8_t status; + /// LT_ADDR + uint8_t lt_addr; +}; + +/// HCI Set Connectionless Slave Broadcast Data command +struct hci_set_con_slv_bcst_data_cmd +{ + /// LT_ADDR + uint8_t lt_addr; + /// Fragment + uint8_t fragment; + /// Data_Length (in bytes) + uint8_t data_length; + /// Data + uint8_t data[__ARRAY_EMPTY]; +}; + +/// HCI Set Connectionless Slave Broadcast Data command complete event +struct hci_set_con_slv_bcst_data_cmd_cmp_evt +{ + /// Status + uint8_t status; + /// LT_ADDR + uint8_t lt_addr; +}; + +/// HCI Read Synchronization Train Parameters command complete event +struct hci_rd_sync_train_param_cmd_cmp_evt +{ + /// Status + uint8_t status; + /// Sync_Train_Interval (in slots) + uint16_t sync_train_int; + /// synchronization_trainTO (in slots) + uint32_t sync_train_to; + /// Service_Data + uint8_t service_data; +}; + +/// HCI Write Synchronization Train Parameters command +struct hci_wr_sync_train_param_cmd +{ + /// Interval_Min (in slots) + uint16_t int_min; + /// Interval_Max (in slots) + uint16_t int_max; + /// synchronization_trainTO (in slots) + uint32_t sync_train_to; + /// Service_Data + uint8_t service_data; +}; + +/// HCI Write Synchronization Train Parameters command complete event +struct hci_wr_sync_train_param_cmd_cmp_evt +{ + /// Status + uint8_t status; + /// Sync_Train_Interval (in slots) + uint16_t sync_train_int; +}; + +// HCI Synchronization Train Complete event +struct hci_sync_train_cmp_evt +{ + /// Status + uint8_t status; +}; + +/// HCI read authenticated payload timeout command +struct hci_rd_auth_payl_to_cmd +{ + ///Connection handle + uint16_t conhdl; +}; + +/// HCI command complete event structure for the Read Authenticated Payload Timeout Command +struct hci_rd_auth_payl_to_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///Authenticated payload timeout + uint16_t auth_payl_to; +}; + +/// HCI command complete event structure for read oob extended data command +struct hci_rd_loc_oob_ext_data_cmd_cmp_evt +{ + ///status + uint8_t status; + ///hash part + struct hash oob_c_192; + ///random part + struct randomizer oob_r_192; + ///hash part + struct hash oob_c_256; + ///random part + struct randomizer oob_r_256; +}; + +/// HCI read Extended Page Timeout CC event +struct hci_rd_ext_page_to_cmd_cmp_evt +{ + /// Status + uint8_t status; + /** + * Extended Page Timeout measured in Number of Baseband slots. Interval Length = N * 0.625 msec (1 Baseband slot) + * Range for N: 0x0000 (default) - 0xFFFF + * Time Range: 0 - 40.9 Seconds + */ + uint16_t ext_page_to; +}; + +/// HCI write Extended Page Timeout +struct hci_wr_ext_page_to_cmd +{ + /** + * Extended Page Timeout measured in Number of Baseband slots. Interval Length = N * 0.625 msec (1 Baseband slot) + * Range for N: 0x0000 (default) - 0xFFFF + * Time Range: 0 - 40.9 Seconds + */ + uint16_t ext_page_to; +}; + +/// HCI read Extended Inquiry Length CC event +struct hci_rd_ext_inq_len_cmd_cmp_evt +{ + /// Status + uint8_t status; + /// Extended Inquiry Length + uint16_t ext_inq_len; +}; + +/// HCI write Extended Inquiry Length +struct hci_wr_ext_inq_len_cmd +{ + /// Extended Inquiry Length + uint16_t ext_inq_len; +}; + +/* + * HCI INFORMATIONAL PARAMETERS COMMANDS PARAMETERS + **************************************************************************************** + */ + +///HCI command complete event structure for read local version information +struct hci_rd_local_ver_info_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + ///HCI version number + uint8_t hci_ver; + ///HCI revision number + uint16_t hci_rev; + ///LMP version + uint8_t lmp_ver; + ///manufacturer name + uint16_t manuf_name; + ///LMP Subversion + uint16_t lmp_subver; +}; + +///HCI command complete event structure for read local supported commands +struct hci_rd_local_supp_cmds_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + ///Supported Commands structure + struct supp_cmds local_cmds; +}; + +/// HCI command complete event structure for read local supported features command +struct hci_rd_local_supp_feats_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + ///Local supported features + struct features feats; +}; + +struct hci_rd_local_ext_feats_cmd +{ + ///Page number + uint8_t page_nb; +}; + +/// HCI command complete event structure for read local extended features command +struct hci_rd_local_ext_feats_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + ///Page number + uint8_t page_nb; + ///Maximum page number + uint8_t page_nb_max; + ///Extended LMP features + struct features ext_feats; +}; + +///HCI command complete event structure for the Read Buffer Size Command +struct hci_rd_buff_size_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + ///ACL data packet length controller can receive from host + uint16_t hc_data_pk_len; + ///Synchronous data packet length controller can receive from host + uint8_t hc_sync_pk_len; + ///Total number of ACL data packets controller can receive from host + uint16_t hc_tot_nb_data_pkts; + ///Total number of synchronous data packets controller can receive from host + uint16_t hc_tot_nb_sync_pkts; +}; + +///HCI command complete event structure for read bd address +struct hci_rd_bd_addr_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + ///BD address + struct bd_addr local_addr; +}; + +/// HCI command complete event structure for read local supported codecs +struct hci_rd_local_supp_codecs_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + uint8_t nb_supp_codecs; + uint8_t nb_supp_vendor_specific_codecs; + +// ///Supported Codecs structure +// struct supp_codecs local_codecs; +}; + +/* + * HCI STATUS PARAMETERS COMMANDS PARAMETERS + **************************************************************************************** + */ + +/// HCI command complete event structure for read rssi +struct hci_rd_rssi_cmd_cmp_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///RSSI value + int8_t rssi; +}; + +struct hci_rd_clk_cmd +{ + ///Connection handle + uint16_t conhdl; + ///Which clock + uint8_t clk_type; +}; + +/// HCI read clock command structure +struct hci_rd_clk_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///clock + uint32_t clk; + ///Accuracy + uint16_t clk_acc; +}; + + +/* + * HCI TESTING COMMANDS PARAMETERS + **************************************************************************************** + */ + +/// HCI command complete event structure for read loop back mode command +struct hci_rd_loopback_mode_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + ///Local supported features + uint8_t lb_mode; +}; + +struct hci_wr_loopback_mode_cmd +{ + ///Local supported features + uint8_t lb_mode; +}; +struct hci_wr_sp_dbg_mode_cmd +{ + ///Simple pairing mode + uint8_t sp_mode; +}; + + +/// * TCI Event subcodes +enum tci_evt_subcode +{ + TCI_LMP_TX_EVENT = 0x22, + TCI_LMP_RX_EVENT = 0x23, + TCI_LC_TX_EVENT = 0x24, + TCI_LC_RX_EVENT = 0x25, + TCI_BB_TX_EVENT = 0x26, + TCI_BB_RX_EVENT = 0x27, + TCI_HW_ERROR_EVENT = 0x28, + TCI_RADIO_EVENT = 0x30, + TCI_INTERRUPT_EVENT = 0x40, +}; + +/// LMP direction +#define TCI_LMP_DIR_TX 0 +#define TCI_LMP_DIR_RX 1 + +/// HCI tci lmp exchange event structure +struct hci_tci_lmp_evt +{ + ///code + uint8_t tci_code; + ///length + uint8_t evt_len; + ///subcode + uint8_t subcode; + ///evt direction + uint8_t direction; + ///lmp evt body + uint8_t body[17]; +}; + +/* + * HCI LE CONTROLLER COMMANDS PARAMETERS + **************************************************************************************** + */ + +///HCI LE Set Event Mask Command parameters structure +struct hci_le_set_evt_mask_cmd +{ + ///LE Event Mask + struct evt_mask le_mask; +}; + +///HCI LE Set Random Address Command parameters structure +struct hci_le_set_rand_addr_cmd +{ + ///Random address to set + struct bd_addr rand_addr; +}; + +///HCI LE Set Advertising Parameters Command parameters structure +struct hci_le_set_adv_param_cmd +{ + ///Minimum interval for advertising + uint16_t adv_intv_min; + ///Maximum interval for advertising + uint16_t adv_intv_max; + ///Advertising type + uint8_t adv_type; + ///Own address type: public=0 / random=1 / rpa_or_pub=2 / rpa_or_rnd=3 + uint8_t own_addr_type; + ///Peer address type: public=0 / random=1 + uint8_t peer_addr_type; + ///Peer Bluetooth device address + struct bd_addr peer_addr; + ///Advertising channel map + uint8_t adv_chnl_map; + ///Advertising filter policy + uint8_t adv_filt_policy; +}; + +///HCI LE Set Advertising Data Command parameters structure +struct hci_le_set_adv_data_cmd +{ + ///Advertising data length + uint8_t adv_data_len; + ///Advertising data - maximum 31 bytes + struct adv_data data; +}; + +///HCI LE Set Scan Response Data Command parameters structure +struct hci_le_set_scan_rsp_data_cmd +{ + ///Scan response data length + uint8_t scan_rsp_data_len; + ///Scan response data - maximum 31 bytes + struct scan_rsp_data data; +}; + +///HCI LE Set Advertise Enable Command parameters structure +struct hci_le_set_adv_en_cmd +{ + ///Advertising enable - 0=disabled, 1=enabled + uint8_t adv_en; +}; + +///HCI LE Set Scan Parameters Command parameters structure +struct hci_le_set_scan_param_cmd +{ + ///Scan type - 0=passive / 1=active + uint8_t scan_type; + ///Scan interval + uint16_t scan_intv; + ///Scan window size + uint16_t scan_window; + ///Own address type - public=0 / random=1 / rpa_or_pub=2 / rpa_or_rnd=3 + uint8_t own_addr_type; + ///Scan filter policy + uint8_t scan_filt_policy; + + ///Scanning channel map, add by hengzhang for fixed channel scan + uint8_t channel_map; +}; + +///HCI LE Set Scan Enable Command parameters structure +struct hci_le_set_scan_en_cmd +{ + ///Scan enable - 0=disabled, 1=enabled + uint8_t scan_en; + ///Enable for duplicates filtering - 0 =disabled/ 1=enabled + uint8_t filter_duplic_en; +}; + +///HCI LE Create Connection Command parameters structure +struct hci_le_create_con_cmd +{ + ///Scan interval + uint16_t scan_intv; + ///Scan window size + uint16_t scan_window; + ///Initiator filter policy + uint8_t init_filt_policy; + ///Peer address type - public=0 / random=1 / rpa_or_pub=2 / rpa_or_rnd=3 + uint8_t peer_addr_type; + ///Peer BD address + struct bd_addr peer_addr; + ///Own address type - public=0 / random=1 / rpa_or_pub=2 / rpa_or_rnd=3 + uint8_t own_addr_type; + ///Minimum of connection interval + uint16_t con_intv_min; + ///Maximum of connection interval + uint16_t con_intv_max; + ///Connection latency + uint16_t con_latency; + ///Link supervision timeout + uint16_t superv_to; + ///Minimum CE length + uint16_t ce_len_min; + ///Maximum CE length + uint16_t ce_len_max; +}; + +///HCI LE Add Device to White List Command parameters structure +struct hci_le_add_dev_to_wlst_cmd +{ + ///Type of address of the device to be added to the White List - 0=public/1=random + uint8_t dev_addr_type; + ///Address of device to be added to White List + struct bd_addr dev_addr; +}; + +///HCI LE Remove Device from White List Command parameters structure +struct hci_le_rmv_dev_from_wlst_cmd +{ + ///Type of address of the device to be removed from the White List - 0=public/1=random + uint8_t dev_addr_type; + ///Address of device to be removed from White List + struct bd_addr dev_addr; +}; + + +///HCI LE Set Host Channel Classification Command parameters structure +struct hci_le_set_host_ch_class_cmd +{ + ///Channel map + struct le_chnl_map chmap; +}; + + +///HCI LE Receiver Test Command parameters structure +struct hci_le_rx_test_cmd +{ + ///RX frequency for Rx test + uint8_t rx_freq; +}; + +///HCI LE Transmitter Test Command parameters structure +struct hci_le_tx_test_cmd +{ + ///TX frequency for Tx test + uint8_t tx_freq; + ///TX test data length + uint8_t test_data_len; + ///TX test payload type - see enum + uint8_t pk_payload_type; +}; + +///HCI LE Encrypt Command parameters structure +struct hci_le_enc_cmd +{ + ///Long term key structure + struct ltk key; + ///Pointer to buffer with plain data to encrypt - 16 bytes + uint8_t plain_data[16]; +}; + +/// HCI LE Connection Update Command parameters structure +struct hci_le_con_update_cmd +{ + ///Connection Handle + uint16_t conhdl; + ///Minimum of connection interval + uint16_t con_intv_min; + ///Maximum of connection interval + uint16_t con_intv_max; + ///Connection latency + uint16_t con_latency; + ///Link supervision timeout + uint16_t superv_to; + ///Minimum of CE length + uint16_t ce_len_min; + ///Maximum of CE length + uint16_t ce_len_max; +}; + +/// HCI LE Start Encryption Command parameters structure +struct hci_le_start_enc_cmd +{ + ///Connection handle + uint16_t conhdl; + ///Random number - 8B + struct rand_nb nb; + ///Encryption Diversifier + uint16_t enc_div; + ///Long term key + struct ltk ltk; +}; + +/// HCI long term key request reply command parameters structure +struct hci_le_ltk_req_reply_cmd +{ + ///Connection handle + uint16_t conhdl; + ///Long term key + struct ltk ltk; +}; + +/// HCI LE remote connection parameter request reply command parameters structure +struct hci_le_rem_con_param_req_reply_cmd +{ + ///Connection handle + uint16_t conhdl; + ///Interval_Min + uint16_t interval_min; + ///Interval_Max + uint16_t interval_max; + ///Latency + uint16_t latency; + ///Timeout + uint16_t timeout; + ///Minimum_CE_Length + uint16_t min_ce_len; + ///Maximum_CE_Length + uint16_t max_ce_len; +}; + +/// HCI LE remote connection parameter request negative reply command parameters structure +struct hci_le_rem_con_param_req_neg_reply_cmd +{ + ///Connection handle + uint16_t conhdl; + ///Reason + uint8_t reason; +}; + + +/// HCI LE Set Data Length Command parameters structure +struct hci_le_set_data_len_cmd +{ + ///Connection Handle + uint16_t conhdl; + ///Preferred maximum number of payload octets that the local Controller should include + ///in a single Link Layer Data Channel PDU. + uint16_t tx_octets; + ///Preferred maximum number of microseconds that the local Controller should use to transmit + ///a single Link Layer Data Channel PDU + uint16_t tx_time; +}; + +/// HCI LE Read Suggested Default Data Length Command +struct hci_le_wr_suggted_dft_data_len_cmd +{ + ///Suggested value for the Controller's maximum transmitted number of payload octets to be used + uint16_t suggted_max_tx_octets; + ///Suggested value for the Controller's maximum packet transmission time to be used + uint16_t suggted_max_tx_time; +}; + +/// HCI LE Add Device to Resolving List Command +struct hci_le_add_dev_to_rslv_list_cmd +{ + /// Peer Identity Address Type + uint8_t peer_id_addr_type; + /// Peer Identity Address + struct bd_addr peer_id_addr; + /// Peer IRK + struct irk peer_irk; + /// Local IRK + struct irk local_irk; +}; + +/// HCI LE Remove Device From Resolving List Command +struct hci_le_rmv_dev_from_rslv_list_cmd +{ + /// Peer Identity Address Type + uint8_t peer_id_addr_type; + /// Peer Identity Address + struct bd_addr peer_id_addr; +}; + +/// HCI LE Read Peer Resolvable Address Command +struct hci_le_rd_peer_rslv_addr_cmd +{ + /// Peer Identity Address Type + uint8_t peer_id_addr_type; + /// Peer Identity Address + struct bd_addr peer_id_addr; +}; + +/// HCI LE Read Local Resolvable Address Command +struct hci_le_rd_loc_rslv_addr_cmd +{ + /// Peer Identity Address Type + uint8_t peer_id_addr_type; + /// Peer Identity Address + struct bd_addr peer_id_addr; +}; + +/// HCI LE Set Address Resolution Enable Command +struct hci_le_set_addr_resol_en_cmd +{ + /// Address Resolution Enable + uint8_t enable; +}; + +/// HCI LE Set Resolvable Private Address Timeout Command +struct hci_le_set_rslv_priv_addr_to_cmd +{ + /// RPA Timeout + uint16_t rpa_timeout; +}; + +#if 1//(BLE_2MBPS) +/// HCI LE Read PHY command +struct hci_le_rd_phy_cmd +{ + /// Connection Handle + uint16_t conhdl; +}; + +/// HCI LE Set Default PHY Command +struct hci_le_set_dft_phy_cmd +{ + /// Preferred PHYS selection + uint8_t all_phys; + /// Preferred PHYS for TX + uint8_t tx_phys; + /// Preferred PHYS for RX + uint8_t rx_phys; +}; + +/// HCI LE Set PHY Command +struct hci_le_set_phy_cmd +{ + /// Connection Handle + uint16_t conhdl; + /// Preferred PHYS selection + uint8_t all_phys; + /// Preferred PHYS for TX + uint8_t tx_phys; + /// Preferred PHYS for RX + uint8_t rx_phys; + /// PHYS option for LE coded PHY + uint16_t phys_option; +}; +/// HCI LE Enhanced Receiver Test Command +struct hci_le_enh_rx_test_cmd +{ + /// Reception channel value + uint8_t rx_channel; + /// Reception PHY rate + uint8_t phy; + /// Modulation index + uint8_t modulation_idx; +}; + +/// HCI LE Enhanced Transmitter Test Command +struct hci_le_enh_tx_test_cmd +{ + /// Transmit channel value + uint8_t tx_channel; + /// Length in bytes of payload data in each packet + uint8_t test_data_length; + /// Type of the data contained in a packet + uint8_t payload_type; + /// Transmit PHY rate + uint8_t phy; +}; + +/// HCI LE read PHY Command complete event +struct hci_le_rd_phy_cmd_cmp_evt +{ + ///Status of received command + uint8_t status; + /// Connection Handle + uint16_t conhdl; + /// Current configured PHY for TX + uint8_t tx_phy; + /// Current configured PHY for RX + uint8_t rx_phy; +}; + +/// HCI command complete event structure for HCI LE PHY Update Command +struct hci_le_phy_update_cmp_evt +{ + ///LE Subevent code + uint8_t subcode; + ///Status of received command + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///TX phy chosen + uint8_t tx_phy; + ///RX phy chosen + uint8_t rx_phy; +}; +#endif // (BLE_2MBPS) + +/* + * HCI EVENTS PARAMETERS + **************************************************************************************** + */ + +/// HCI inquiry complete event structure +struct hci_inq_cmp_evt +{ + ///Status of the procedure + uint8_t status; +}; + + +/// HCI Inquiry result event structure (with only 1 result) +struct hci_inq_res_evt +{ + + ///Number of response + uint8_t nb_rsp; + ///BdAddr + struct bd_addr bd_addr; + ///Page Scan Repetition Mode + uint8_t page_scan_rep_mode; + ///Reserved + uint8_t reserved1; + ///Reserved + uint8_t reserved2; + ///class of device + struct devclass class_of_dev; + ///Clock Offset + uint16_t clk_off; + +}; + +/// HCI Inquiry result with rssi event structure (with only 1 result) +struct hci_inq_res_with_rssi_evt +{ + ///Number of response + uint8_t nb_rsp; + ///BdAddr + struct bd_addr bd_addr; + ///Page Scan Repetition Mode + uint8_t page_scan_rep_mode; + ///Reserved + uint8_t reserved1; + ///class of device + struct devclass class_of_dev; + ///Clock Offset + uint16_t clk_off; + ///Rssi + uint8_t rssi; + +}; + +/// HCI Extended inquiry result indication structure (with only 1 result) +struct hci_ext_inq_res_evt +{ + ///Number of response + uint8_t nb_rsp; + ///BdAddr + struct bd_addr bd_addr; + ///Page Scan Repetition Mode + uint8_t page_scan_rep_mode; + ///Reserved + uint8_t reserved1; + ///class of device + struct devclass class_of_dev; + ///Clock Offset + uint16_t clk_off; + ///RSSi + uint8_t rssi; + ///Extended inquiry response data + struct eir eir; +}; + +/// HCI disconnect complete event structure +struct hci_disc_cmp_evt +{ + ///Status of received command + uint8_t status; + ///Connection Handle + uint16_t conhdl; + ///Reason for disconnection + uint8_t reason; +}; + +/// HCI basic command complete event structure +struct hci_basic_cmd_cmp_evt +{ + ///Status of the command reception + uint8_t status; +}; + +/// HCI basic command complete event structure with connection handle +struct hci_basic_conhdl_cmd_cmp_evt +{ + /// status + uint8_t status; + /// connection handle + uint16_t conhdl; +}; + +/// HCI basic command complete event structure with BD address +struct hci_basic_bd_addr_cmd_cmp_evt +{ + ///status + uint8_t status; + ///BdAddr + struct bd_addr bd_addr; +}; + +/// HCI basic event structure with status and BD address +struct hci_basic_stat_bd_addr_evt +{ + ///status + uint8_t status; + ///BdAddr + struct bd_addr bd_addr; +}; + +/// HCI basic event including a connection handle as parameter +struct hci_basic_conhdl_evt +{ + ///Connection handle + uint16_t conhdl; +}; + +/// HCI complete event with status only. +struct hci_cmd_stat_event +{ + /// Status of the command reception + uint8_t status; +}; + +/// HCI number of packet complete event structure +struct hci_nb_cmp_pkts_evt +{ + /// number of handles + uint8_t nb_of_hdl; + /// connection handle + uint16_t conhdl[1]; + /// number of completed packets + uint16_t nb_comp_pkt[1]; +}; + +/// HCI data buffer overflow event structure +struct hci_data_buf_ovflw_evt +{ + ///Link type + uint8_t link_type; +}; + +/// HCI Hardware Error Event parameters structure +struct hci_hw_err_evt +{ + /// HW error code + uint8_t hw_code; +}; + +/// HCI encryption change event structure +struct hci_enc_change_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///Encryption enabled information + uint8_t enc_stat; +}; + +/// HCI encryption key refresh complete event structure +struct hci_enc_key_ref_cmp_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; +}; + +/// HCI Authenticated Payload Timeout Expired Event structure +struct hci_auth_payl_to_exp_evt +{ + ///Connection handle + uint16_t conhdl; +}; + +/// HCI command complete event structure for create connection +struct hci_con_cmp_evt +{ + /// Status + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///Bluetooth Device address + struct bd_addr bd_addr; + ///Link type + uint8_t link_type; + ///Encryption state + uint8_t enc_en; +}; + +/// HCI command complete event structure for qos setup +struct hci_qos_setup_cmp_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///Flags + uint8_t flags; + ///Service type + uint8_t serv_type; + ///Token rate + uint32_t tok_rate; + ///Peak bandwidth + uint32_t pk_bw; + ///Latency + uint32_t lat; + ///Delay variation + uint32_t del_var; +}; + +/// HCI flow specification complete event parameters structure +struct hci_flow_spec_cmp_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///Flags + uint8_t flags; + ///Flow direction + uint8_t flow_dir; + ///Service type + uint8_t serv_type; + ///Token rate + uint32_t tk_rate; + ///Token buffer size + uint32_t tk_buf_sz; + ///Peak bandwidth + uint32_t pk_bw; + ///Access latency + uint32_t acc_lat; +}; + +/// HCI role change event parameters structure +struct hci_role_chg_evt +{ + ///Status + uint8_t status; + ///BD address + struct bd_addr bd_addr; + ///New role + uint8_t new_role; +}; + +/// HCI complete event structure for the read clock offset command +struct hci_rd_clk_off_cmp_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///Clock offset + uint16_t clk_off_val; +}; + +/// HCI event structure for the flush occurred event +struct hci_flush_occurred_evt +{ + ///Connection handle + uint16_t conhdl; +}; + +/// HCI max slot change event structure +struct hci_max_slot_chg_evt +{ + ///Connection handle + uint16_t conhdl; + ///Max slot + uint8_t max_slot; +}; + +/// HCI sniff subrating event parameters structure +struct hci_sniff_sub_evt +{ + ///Status. + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///Maximum transmit latency + uint16_t max_lat_tx; + ///Maximum receive latency + uint16_t max_lat_rx; + ///Minimum remote TO + uint16_t min_rem_to; + ///Minimum local TO + uint16_t min_loc_to; +}; + +/// HCI read remote extended features complete event parameters structure +struct hci_rd_rem_ext_feats_cmp_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///page number + uint8_t pg_nb; + ///page number max + uint8_t pg_nb_max; + ///ext LMP features + struct features ext_feats; +}; + +/// HCI read remote extended features complete event parameters structure +struct hci_rem_host_supp_feats_notif_evt +{ + ///BD address + struct bd_addr bd_addr; + ///ext lmp features + struct features ext_feats; +}; + +/// HCI command complete event structure for the read remote supported features command +struct hci_rd_rem_supp_feats_cmp_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///Remote features + struct features rem_feats; +}; + +/// HCI command complete event structure for the read remote information version command +struct hci_rd_rem_ver_info_cmp_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///LMP version + uint8_t vers; + ///Manufacturer name + uint16_t compid; + ///LMP subversion + uint16_t subvers; +}; + +/// HCI encryption change event structure +struct hci_enc_chg_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///Encryption enabled information + uint8_t enc_stat; +}; + +/// HCI mode change event structure +struct hci_mode_chg_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///Current mode + uint8_t cur_mode; + /// Interval + uint16_t interv; +}; + +/// HCI simple pairing complete event structure +struct hci_sp_cmp_evt +{ + ///Status for command reception + uint8_t status; + ///Bluetooth Device address + struct bd_addr bd_addr; +}; + +/// HCI Authentication complete event structure +struct hci_auth_cmp_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; +}; + +/// HCI change connection link key complete event structure +struct hci_chg_con_lk_cmp_evt +{ + ///Status + uint8_t status; + ///Connection handle + uint16_t conhdl; +}; + +/// HCI encryption key refresh complete event structure +struct hci_enc_key_refresh_cmp_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; +}; + +/// HCI master link key complete event structure +struct hci_master_lk_cmp_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///Key flag + uint8_t key_flag; +}; +/// HCI synchronous link connection complete event structure +struct hci_sync_con_cmp_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///BD address + struct bd_addr bd_addr; + ///Link type + uint8_t lk_type; + ///Transmit interval + uint8_t tx_int; + ///Retransmission window + uint8_t ret_win; + ///rx packet length + uint16_t rx_pkt_len; + ///tx packet length + uint16_t tx_pkt_len; + ///Air mode + uint8_t air_mode; + +}; + +/// HCI synchronous connection change event structure +struct hci_sync_con_chg_evt +{ + ///Status for command reception + uint8_t status; + ///Synchronous Connection handle + uint16_t sync_conhdl; + ///Transmit interval + uint8_t tx_int; + ///Retransmission window + uint8_t ret_win; + ///rx packet length + uint16_t rx_pkt_len; + ///tx packet length + uint16_t tx_pkt_len; +}; + +/// HCI connection packet type change event structure +struct hci_con_pkt_type_chg_evt +{ + ///Status for command reception + uint8_t status; + ///Synchronous Connection handle + uint16_t sync_conhdl; + ///Synchronous packet type + uint16_t pkt_type; +}; + +/// HCI link supervision timeout change event structure +struct hci_link_supv_to_chg_evt +{ + ///Connection handle + uint16_t conhdl; + ///Link supervision timeout + uint16_t lsto_val; +}; + +/// HCI link key request event structure +struct hci_lk_req_evt +{ + ///BD address + struct bd_addr bd_addr; +}; + +/// HCI encryption key refresh event structure +struct hci_enc_key_refresh_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; +}; + +/// HCI connection request event structure +struct hci_con_req_evt +{ + ///BD address + struct bd_addr bd_addr; + ///Class of device + struct devclass classofdev; + ///link type + uint8_t lk_type; +}; + +/// HCI quality of service violation event structure +struct hci_qos_viol_evt +{ + ///Connection handle + uint16_t conhdl; +}; + +/// HCI io capability response event structure +struct hci_io_cap_rsp_evt +{ + ///BdAddr + struct bd_addr bd_addr; + ///IO capability + uint8_t io_capa; + ///OOB data present + uint8_t oob_data_pres; + ///Authentication requirements + uint8_t auth_req; + +}; + +/// HCI IO capability response event structure +struct hci_io_cap_req_evt +{ + ///BdAddr + struct bd_addr bd_addr; +}; + +/// HCI Return link keys event structure +struct hci_return_link_keys_evt +{ + ///Number of Keys + uint8_t num_keys; + ///BdAddr + struct bd_addr bd_addr; + ///Key + struct ltk key; +}; + +/// HCI pin code request event structure +struct hci_pin_code_req_evt +{ + ///BdAddr + struct bd_addr bd_addr; +}; + +/// HCI user passkey request event structure +struct hci_user_passkey_req_evt +{ + ///BdAddr + struct bd_addr bd_addr; +}; + +/// HCI user passkey notification event structure +struct hci_user_passkey_notif_evt +{ + ///BdAddr + struct bd_addr bd_addr; + ///Passkey + uint32_t passkey; +}; + +/// HCI remote OOB data request event structure +struct hci_rem_oob_data_req_evt +{ + ///BdAddr + struct bd_addr bd_addr; +}; + +/// HCI user confirmation request event structure +struct hci_user_cfm_req_evt +{ + ///BdAddr + struct bd_addr bd_addr; + ///Passkey + uint32_t passkey; +}; + +/// HCI keypress notification event structure +struct hci_keypress_notif_evt +{ + ///BdAddr + struct bd_addr bd_addr; + ///type + uint8_t type; +}; + +/// HCI link key notification event structure +struct hci_lk_notif_evt +{ + ///BdAddr + struct bd_addr bd_addr; + ///Key + struct ltk key; + ///type + uint8_t key_type; +}; + + +/* + * HCI LE META EVENTS PARAMETERS + **************************************************************************************** + */ + + +// LE event structures + +/// HCI command complete event structure for the Read Local Supported Features +struct hci_le_rd_local_supp_feats_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + ///Local LE supported features + struct le_features feats; +}; + +/// HCI command complete event structure for the Read Advertising Channel Tx Power Command +struct hci_rd_adv_chnl_tx_pw_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + ///Advertising channel Tx power level + int8_t adv_tx_pw_lvl; +}; + +///HCI command complete event structure for the Read White List Size Command +struct hci_rd_wlst_size_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + ///White List size + uint8_t wlst_size; +}; + +///HCI command complete event structure for the Read Buffer Size Command +struct hci_le_rd_buff_size_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + ///ACL data packet length that can be sent from host to controller + uint16_t hc_data_pk_len; + ///Total number of ACL data packets that can be sent from host to controller. + uint8_t hc_tot_nb_data_pkts; +}; + +///HCI command complete event structure for LE Rand Command +struct hci_le_rand_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + ///Random number + struct rand_nb nb; +}; + +///HCI command complete event structure for Read Supported States Command +struct hci_rd_supp_states_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + ///LE supported states response + struct le_states states; +}; + +///HCI command complete event structure for Test End +struct hci_test_end_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + ///Number of RX packets - null if TX test was the ended one + uint16_t nb_packet_received; +}; + +///HCI LE Encrypt complete event structure +struct hci_le_enc_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + ///Encrypted data to return to command source. + uint8_t encrypted_data[ENC_DATA_LEN]; +}; + +#if BLE_EMB_PRESENT || BLE_HOST_PRESENT +///HCI LE advertising report event structure +struct hci_le_adv_report_evt +{ + ///LE Subevent code + uint8_t subcode; + ///Number of advertising reports in this event + uint8_t nb_reports; + ///Advertising reports structures array + struct adv_report adv_rep[BLE_ADV_REPORTS_MAX]; +}; +#endif //BLE_EMB_PRESENT || BLE_HOST_PRESENT + +/// HCI command complete event structure for Read Channel Map Command +struct hci_le_rd_chnl_map_cmd_cmp_evt +{ + ///Status of command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///Channel map + struct le_chnl_map ch_map; +}; + +/// HCI command complete event structure for Long Term Key Request Reply Command +struct hci_le_ltk_req_reply_cmd_cmp_evt +{ + ///Status of command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; +}; + +/// HCI command complete event structure for Long Term Key Request Negative Reply Command +struct hci_le_ltk_req_neg_reply_cmd_cmp_evt +{ + ///Status of command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; +}; + +/// HCI command complete event structure for LE Read Suggested Default Data Length Command +struct hci_le_rd_suggted_dft_data_len_cmd_cmp_evt +{ + ///Status of command reception + uint8_t status; + ///Host's suggested value for the Controller's maximum transmitted number of payload octets + uint16_t suggted_max_tx_octets; + ///Host's suggested value for the Controller's maximum packet transmission time + uint16_t suggted_max_tx_time; +}; +/// HCI command complete event structure for LE Read Maximum Data Length Command +struct hci_le_rd_max_data_len_cmd_cmp_evt +{ + ///Status of command reception + uint8_t status; + ///Maximum number of payload octets that the local Controller supports for transmission + uint16_t suppted_max_tx_octets; + ///Maximum time, in microseconds, that the local Controller supports for transmission + uint16_t suppted_max_tx_time; + ///Maximum number of payload octets that the local Controller supports for reception + uint16_t suppted_max_rx_octets; + ///Maximum time, in microseconds, that the local Controller supports for reception + uint16_t suppted_max_rx_time; +}; + +/// HCI LE Read Peer Resolvable Address Command Complete Event +struct hci_le_rd_peer_rslv_addr_cmd_cmp_evt +{ + ///Status + uint8_t status; + /// Peer Resolvable Address + struct bd_addr peer_rslv_addr; +}; + +/// HCI LE Read Local Resolvable Address Command Complete Event +struct hci_le_rd_loc_rslv_addr_cmd_cmp_evt +{ + ///Status + uint8_t status; + /// Local Resolvable Address + struct bd_addr loc_rslv_addr; +}; + +/// HCI LE Read Resolving List Size Command Complete Event +struct hci_le_rd_rslv_list_size_cmd_cmp_evt +{ + ///Status + uint8_t status; + /// Resolving List Size + uint8_t size; +}; + + +/// HCI write authenticated payload timeout command +struct hci_wr_auth_payl_to_cmd +{ + ///Connection handle + uint16_t conhdl; + ///Authenticated payload timeout + uint16_t auth_payl_to; +}; + +/// HCI command complete event structure for the Write Authenticated Payload Timeout Command +struct hci_wr_auth_payl_to_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; +}; + +/// HCI command complete event structure for HCI LE Connection Update Command +struct hci_le_con_update_cmp_evt +{ + ///LE Subevent code + uint8_t subcode; + ///Status of received command + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///Connection interval value + uint16_t con_interval; + ///Connection latency value + uint16_t con_latency; + ///Supervision timeout + uint16_t sup_to; +}; + +/// HCI command complete event structure for create connection +struct hci_le_con_cmp_evt +{ + ///LE Subevent code + uint8_t subcode; + ///Status of received command + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///Device role - 0=Master/ 1=Slave + uint8_t role; + ///Peer address type - 0=public/1=random + uint8_t peer_addr_type; + ///Peer address + struct bd_addr peer_addr; + ///Connection interval + uint16_t con_interval; + ///Connection latency + uint16_t con_latency; + ///Link supervision timeout + uint16_t sup_to; + ///Master clock accuracy + uint8_t clk_accuracy; +}; + +/// HCI LE read remote used feature command parameters structure +struct hci_le_rd_rem_used_feats_cmd +{ + ///Connection handle + uint16_t conhdl; +}; + +/// HCI command complete event structure for HCI LE read remote used feature Command +struct hci_le_rd_rem_used_feats_cmd_cmp_evt +{ + ///LE Subevent code + uint8_t subcode; + ///Status of received command + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///Le Features used + struct le_features feats_used; +}; + +/// HCI command structure for the read transmit power level command +struct hci_rd_tx_pwr_lvl_cmd +{ + ///Connection handle + uint16_t conhdl; + ///Power Level type: current or maximum + uint8_t type; +}; + +/// HCI command complete event structure for the read transmit power level command +struct hci_rd_tx_pwr_lvl_cmd_cmp_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///Value of TX power level + uint8_t tx_pow_lvl; +}; + +/// HCI read remote information version command parameters structure +struct hci_rd_rem_ver_info_cmd +{ + ///Connection handle + uint16_t conhdl; +}; + +/// HCI LE remote connection parameter request event +struct hci_le_rem_con_param_req_evt +{ + ///LE Subevent code + uint8_t subcode; + ///Connection handle + uint16_t conhdl; + ///Interval_Min + uint16_t interval_min; + ///Interval_Max + uint16_t interval_max; + ///Latency + uint16_t latency; + ///Timeout + uint16_t timeout; +}; + + +/// HCI command complete event structure for enhance create connection +struct hci_le_enh_con_cmp_evt +{ + ///LE Subevent code + uint8_t subcode; + ///Status of received command + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///Device role - 0=Master/ 1=Slave + uint8_t role; + ///Peer address type - 0=public/1=random + uint8_t peer_addr_type; + ///Peer address + struct bd_addr peer_addr; + ///Local Resolvable Private Address + struct bd_addr loc_rslv_priv_addr; + ///Peer Resolvable Private Address + struct bd_addr peer_rslv_priv_addr; + ///Connection interval + uint16_t con_interval; + ///Connection latency + uint16_t con_latency; + ///Link supervision timeout + uint16_t sup_to; + ///Master clock accuracy + uint8_t clk_accuracy; +}; + + +struct hci_generate_dhkey_cmp_evt +{ + ///LE Subevent code + uint8_t subcode; + ///Status of received command + uint8_t status; + /// The 32 byte Diffie Helman Key + uint8_t dh_key[32]; +}; + + +struct hci_rd_local_p256_public_key_cmp_evt +{ + ///LE Subevent code + uint8_t subcode; + ///Status of received command + uint8_t status; + /// The 32 byte Diffie Helman Key + uint8_t public_key[64]; + +}; + +#if BLE_EMB_PRESENT || BLE_HOST_PRESENT +/// HCI LE Direct Advertising Report Event +struct hci_le_dir_adv_rep_evt +{ + ///LE Subevent code + uint8_t subcode; + ///Number of reports + uint8_t nb_reports; + ///Direct Advertising reports structures array + struct dir_adv_report adv_rep[BLE_ADV_REPORTS_MAX]; +}; +#endif //BLE_EMB_PRESENT || BLE_HOST_PRESENT + +/// HCI command complete event structure for HCI LE read remote used feature Command +struct hci_le_ltk_request_evt +{ + ///LE Subevent code + uint8_t subcode; + ///Connection handle + uint16_t conhdl; + ///Random number + struct rand_nb rand; + ///Encryption diversifier + uint16_t ediv; +}; + +/// HCI LE META event LE Data Length Change Event +struct hci_le_data_len_chg_evt +{ + ///LE Subevent code + uint8_t subcode; + ///Connection handle + uint16_t conhdl; + ///The maximum number of payload octets in TX + uint16_t max_tx_octets; + ///The maximum time that the local Controller will take to TX + uint16_t max_tx_time; + ///The maximum number of payload octets in RX + uint16_t max_rx_octets; + ///The maximum time that the local Controller will take to RX + uint16_t max_rx_time; +}; + + +/// HCI Synchronization Train Received Event +struct hci_sync_train_rec_evt +{ + /// Status + uint8_t status; + /// BD_ADDR + struct bd_addr bd_addr; + /// Clock_Offset (28 bits) - (CLKNslave - CLK) modulo 2^28 + uint32_t clock_offset; + /// AFH_Channel_Map + struct chnl_map afh_ch_map; + /// LT_ADDR + uint8_t lt_addr; + /// Next_Broadcast_Instant (28 bits) + uint32_t next_bcst_instant; + /// Connectionless_Slave_Broadcast_Interval (in slots) + uint16_t csb_int; + /// Service_Data + uint8_t service_data; +}; + +/// HCI Connectionless Slave Broadcast Receive Event +struct hci_con_slv_bcst_rec_evt +{ + /// BD_ADDR + struct bd_addr bd_addr; + /// LT_ADDR + uint8_t lt_addr; + /// CLK (28 bits) + uint32_t clk; + /// Offset (28 bits) - (CLKNslave - CLK) modulo 2^28 + uint32_t offset; + /// Receive Status + uint8_t receive_status; + /// Fragment + uint8_t fragment; + /// Data_Length (in bytes) + uint8_t data_length; + /// Data + uint8_t data[__ARRAY_EMPTY]; +}; + +/// HCI Connectionless Slave Broadcast Timeout Event +struct hci_con_slv_bcst_to_evt +{ + /// BD_ADDR + struct bd_addr bd_addr; + /// LT_ADDR + uint8_t lt_addr; +}; + +/// HCI Connectionless Slave Broadcast Channel Map Change Event +struct hci_con_slv_bcst_ch_map_chg_evt +{ + /// Channel_Map + struct chnl_map ch_map; +}; + + +struct hci_le_generate_dhkey_cmp_evt +{ + ///LE Subevent code + uint8_t subcode; + uint8_t status; + uint8_t dh_key[32]; +}; + +struct hci_le_generate_p256_public_key_cmp_evt +{ + ///LE Subevent code + uint8_t subcode; + uint8_t status; + t_public_key public_key; +}; + +/* + * HCI VENDOR SPECIFIC COMMANDS PARAMETERS + **************************************************************************************** + */ + +/// Buffer structure +struct buffer_tag +{ + /// length of buffer + uint8_t length; + /// data of 128 bytes length + uint8_t data[128]; +}; + +/// Common structure for Command Complete Event of HCI Debug Read Memory/Flash/Param complete event parameters - vendor specific +struct hci_dbg_basic_rd_data_cmd_cmp_evt +{ + ///Status + uint8_t status; + ///buffer structure to return + struct buffer_tag buf; +}; + +///HCI Debug read memory variable command parameters - vendor specific +struct hci_dbg_rd_mem_cmd +{ + ///Start address to read + uint32_t start_addr; + ///Access size + uint8_t type; + ///Length to read + uint8_t length; +}; + +///HCI Debug write memory variable command parameters - vendor specific +struct hci_dbg_wr_mem_cmd +{ + ///Start address to read + uint32_t start_addr; + ///Access size + uint8_t type; + ///buffer structure to return + struct buffer_tag buf; +}; + +///HCI Debug delete parameter command parameters - vendor specific +struct hci_dbg_del_param_cmd +{ + ///Parameter tag + uint16_t param_tag; +}; + +///HCI Debug erase flash command parameters - vendor specific +struct hci_dbg_er_flash_cmd +{ + ///Flash type + uint8_t flashtype; + ///Start offset address + uint32_t startoffset; + ///Size to erase + uint32_t size; +}; + +///HCI Debug write flash command parameters - vendor specific +struct hci_dbg_wr_flash_cmd +{ + ///Flash type + uint8_t flashtype; + ///Start offset address + uint32_t startoffset; + ///buffer structure + struct buffer_tag buf; +}; + +///HCI Debug read flash command parameters - vendor specific +struct hci_dbg_rd_flash_cmd +{ + ///Flash type + uint8_t flashtype; + ///Start offset address + uint32_t startoffset; + ///Size to read + uint8_t size; +}; + +///HCI Debug read parameter command parameters - vendor specific +struct hci_dbg_rd_par_cmd +{ + ///Parameter tag + uint16_t param_tag; +}; + +///HCI Debug read parameters command parameters - vendor specific +struct hci_dbg_wr_par_cmd +{ + ///Parameter tag + uint16_t param_tag; + ///Structure buffer + struct buffer_tag buf; +}; + +#if CRYPTO_UT +struct hci_dbg_test_crypto_func_cmd +{ + /// Id of Function to be tested + uint8_t function; + /// Structure buffer + struct buffer_tag buf; +}; +#endif //CRYPTO_UT + +///HCI Debug Read Kernel Statistics complete event parameters - vendor specific +struct hci_dbg_rd_kernel_stats_cmd_cmp_evt +{ + ///Status + uint8_t status; + ///Max message sent + uint8_t max_msg_sent; + ///Max message saved + uint8_t max_msg_saved; + ///Max timer used + uint8_t max_timer_used; + ///Max heap used + uint16_t max_heap_used; + ///Max stack used + uint16_t max_stack_used; +}; + + +/// HCI Debug Read information about memory usage. - vendor specific +struct hci_dbg_rd_mem_info_cmd_cmp_evt +{ + ///Status + uint8_t status; + /// memory size currently used into each heaps. + uint16_t mem_used[KERNEL_MEM_BLOCK_MAX]; + /// peak of memory usage measured + uint32_t max_mem_used; +}; + +///HCI Debug identify Flash command complete event parameters - vendor specific +struct hci_dbg_id_flash_cmd_cmp_evt +{ + ///Status + uint8_t status; + ///Flash identity + uint8_t flash_id; +}; + +///HCI Debug RF Register read command +struct hci_dbg_rf_reg_rd_cmd +{ + /// register address + uint16_t addr; +}; + +///HCI Debug RF Register read command complete event +struct hci_dbg_rf_reg_rd_cmd_cmp_evt +{ + /// status + uint8_t status; + /// register address + uint16_t addr; + /// register value + uint32_t value; +}; + +///HCI Debug RF Register write command +struct hci_dbg_rf_reg_wr_cmd +{ + /// register address + uint16_t addr; + /// register value + uint32_t value; +}; + +///HCI Debug RF Register write command complete event +struct hci_dbg_rf_reg_wr_cmd_cmp_evt +{ + /// status + uint8_t status; + /// address + uint16_t addr; +}; + +///HCI Debug platform reset command parameters - vendor specific +struct hci_dbg_plf_reset_cmd +{ + /// reason + uint8_t reason; +}; + +#if (RW_DEBUG && BT_EMB_PRESENT) +/// Discard LMP Packets +struct hci_dbg_bt_send_lmp_cmd +{ + /// Connection handle + uint16_t conhdl; + ///buffer structure to return + struct buffer_tag buf; +}; + +/// Discard LMP Packets +struct hci_dbg_bt_discard_lmp_en_cmd +{ + /// Connection handle + uint16_t conhdl; + /// Enable/Disable LMP discard (0: disable / 1: enable) + uint8_t enable; +}; + +/// Set local clock +struct hci_dbg_set_local_clock_cmd +{ + /// Clock (in half-slots) + uint32_t clock; +}; +#endif //(RW_DEBUG && BT_EMB_PRESENT) + +#if (RW_WLAN_COEX) +///HCI Debug wlan coexistence command parameters - vendor specific +struct hci_dbg_wlan_coex_cmd +{ + /// State + uint8_t state; +}; +#if (RW_WLAN_COEX_TEST) +///HCI Debug wlan coexistence test scenario command parameters - vendor specific +struct hci_dbg_wlan_coextst_scen_cmd +{ + /// Scenario + uint32_t scenario; +}; +#endif //RW_WLAN_COEX_TEST +#endif //RW_WLAN_COEX + +#if (RW_MWS_COEX) +///HCI Debug mws coexistence command parameters - vendor specific +struct hci_dbg_mws_coex_cmd +{ + /// State + uint8_t state; +}; +#if (RW_MWS_COEX_TEST) +///HCI Debug mws coexistence test scenario command parameters - vendor specific +struct hci_dbg_mws_coextst_scen_cmd +{ + /// Scenario + uint32_t scenario; +}; +#endif //RW_MWS_COEX_TEST +#endif //RW_MWS_COEX + +///HCI Debug HW Register Read command parameters - vendor specific +struct hci_dbg_hw_reg_rd_cmd +{ + /// register address + uint16_t reg_addr; +}; + +///HCI Debug HW Register write command parameters - vendor specific +struct hci_dbg_hw_reg_wr_cmd +{ + /// register address + uint16_t reg_addr; + /// extra parameter + uint16_t reserved; + /// register value + uint32_t reg_value; +}; + +///HCI Debug HW Register Read Complete event parameters - vendor specific +struct hci_dbg_hw_reg_rd_cmd_cmp_evt +{ + /// status + uint8_t status; + /// register address + uint16_t reg_addr; + /// register value + uint32_t reg_value; +}; + +///HCI Debug HW Register Write Complete event parameters - vendor specific +struct hci_dbg_hw_reg_wr_cmd_cmp_evt +{ + /// status + uint8_t status; + /// register address + uint16_t reg_addr; +}; + +///HCI Debug write DLE default value command parameters - vendor specific +struct hci_dbg_wr_dle_dft_value_cmd +{ + /// Max transmit packet size supported + uint16_t suppted_max_tx_octets; + /// Max transmit packet time supported + uint16_t suppted_max_tx_time; + /// Max receive packet size supported + uint16_t suppted_max_rx_octets; + /// Max receive packet time supported + uint16_t suppted_max_rx_time; + +}; + +#if (BLE_EMB_PRESENT || BLE_HOST_PRESENT) +///HCI Debug bd address write command parameters - vendor specific +struct hci_dbg_set_bd_addr_cmd +{ + ///bd address to set + struct bd_addr addr; +}; + +///HCI Debug crc write command parameters - vendor specific +struct hci_dbg_set_crc_cmd +{ + /// Handle pointing to the connection for which CRC has to be modified + uint16_t conhdl; + /// CRC to set + struct crc_init crc; +}; + +///HCI Debug LLC discard command parameters - vendor specific +struct hci_dbg_llcp_discard_cmd +{ + /// Handle pointing to the connection for which LLCP commands have to be discarded + uint16_t conhdl; + /// Flag indicating if the discarding has to be enabled or disabled + uint8_t enable; +}; + +///HCI Debug reset RX counter command parameters - vendor specific +struct hci_dbg_reset_rx_cnt_cmd +{ + /// Handle pointing to the connection for which the counter have to be reseted + uint16_t conhdl; +}; + +///HCI Debug reset TX counter command parameters - vendor specific +struct hci_dbg_reset_tx_cnt_cmd +{ + /// Handle pointing to the connection for which the counter have to be reseted + uint16_t conhdl; +}; + +///HCI Debug Set TX Power Level Command parameters +struct hci_dbg_set_tx_pw_cmd +{ + /// Connection handle + uint16_t conhdl; + /// Power level + uint8_t pw_lvl; +}; + +///HCI Debug configure audio command parameters - vendor specific + +struct hci_vs_audio_configure_cmd +{ + /// Connection handle + uint16_t conhdl; + /// Voice channel to be updated + uint8_t voice_channel; + /// Configure transmitter size in bytes + uint8_t tx_size; + /// Configure receiver size in bytes + uint8_t rx_size; + /// Configure transmitter rate + uint8_t tx_rate; + /// Configure receiver rate + uint8_t rx_rate; + /// Configure number of retransmission + uint8_t nb_retx; + /// Audio link priority + uint8_t priority; + /// Encryption mode + uint8_t enc_mode; + /// Channel and mute configuration (@see enum audio_cfg) + uint8_t chan_mute_cfg; + /// Mute Pattern + uint8_t mute_pattern; + /// Audio interval in frame + uint16_t interval; +}; + +struct hci_vs_audio_set_pointer_cmd +{ + /// Connection handle + uint16_t conhdl; + /// Voice channel to be updated + uint8_t voice_channel; + /// Rx or Tx selection + uint8_t rx_tx_select; + /// Tog to be updated + uint8_t tog; + /// Exchange memory pointer + uint16_t em_ptr; +}; +///HCI Debug set audio mode command parameters - vendor specific. +struct hci_vs_audio_set_mode_cmd +{ + /// Connection handle + uint16_t conhdl; + /// Voice channel to be updated + uint8_t voice_channel; + /// Mode + uint8_t mode; +}; + +///HCI Debug set audio mode command parameters - vendor specific +struct hci_vs_audio_reset_cmd +{ + /// Connection handle + uint16_t conhdl; + /// Voice channel to be updated + uint8_t voice_channel; +}; + +///HCI Debug set audio mode command parameters - vendor specific +struct hci_vs_audio_allocate_cmd +{ + /// Connection handle + uint16_t conhdl; +}; + +///HCI Debug get audio buffer range - vendor specific +struct hci_vs_audio_get_buffer_range_cmd +{ + /// Rx or Tx selection + uint8_t rx_tx_select; +}; + + +///HCI VS basic command complete event - vendor specific +struct hci_vs_audio_cmd_cmp_evt +{ + /// status + uint8_t status; + /// Connection handle + uint16_t conhdl; +}; + + +///HCI Debug allocate audio voice channel complete event - vendor specific +struct hci_vs_audio_allocate_cmd_cmp_evt +{ + /// status + uint8_t status; + /// Connection handle + uint16_t conhdl; + /// voice channel allocated + uint8_t voice_channel; +}; + +///HCI Vendor Specific Set Preferred Slave Latency command parameters +struct hci_vs_set_pref_slave_latency_cmd +{ + /// Connection handle + uint16_t conhdl; + /// Preferred latency (in number of connection events) + uint16_t latency; +}; + +///HCI Debug set preferred slave latency complete event - vendor specific +struct hci_vs_set_pref_slave_latency_cmd_cmp_evt +{ + /// status + uint8_t status; + /// Connection handle + uint16_t conhdl; + /// latency preferred + uint16_t latency; +}; + + +///HCI Debug get audio buffer range complete event - vendor specific +struct hci_vs_audio_get_buffer_range_cmd_cmp_evt +{ + /// status + uint8_t status; + /// start address + uint32_t base_address; + /// end address + uint32_t end_address; +}; + +/// HCI Vendor specific to start Advertising test mode - vendor specific +/// The transmitted advertising packet is non connectable and non scannable +struct hci_vs_adv_test_mode_start_cmd +{ + /// Advertising interval (1 step = 625us) + uint16_t interval; + + /// Advertising channel map (bit 0 - 37, bit 1 - 38, bit 2 - 39) + uint8_t chmap; + + /// Number of transmission of advertising packet to perform per enabled advertising channel. + uint8_t nb_tx; + + /// Random address to transmit, if zero, Public address is used. + uint8_t rnd_addr[6]; + + /// Length of advertising data to transmit (range [0:31]) + uint8_t data_len; + + /// Advertising data to transmit + uint8_t data[31]; +}; + + +#if (BLE_TESTER) +///HCI Tester set LE parameters +struct hci_tester_set_le_params_cmd +{ + /// Connection handle + uint16_t conhdl; + /// Tester features + uint8_t tester_feats; + /// Preferred periodicity + uint8_t pref_period; + /// Offset0 + uint16_t offset0; + /// Offset1 + uint16_t offset1; + /// Offset2 + uint16_t offset2; + /// Offset3 + uint16_t offset3; + /// Offset4 + uint16_t offset4; + /// Offset5 + uint16_t offset5; +}; + +/// HCI BLE Tester: enable LLCP pass through mechanism +struct hci_dbg_ble_tst_llcp_pt_en_cmd +{ + /// Connection handle + uint16_t conhdl; + /// Enable or not LLCP pass through mechanism + uint8_t enable; +}; + +/// HCI BLE Tester: send an LLCP PDU +struct hci_dbg_ble_tst_send_llcp_cmd +{ + /// Connection handle + uint16_t conhdl; + /// length of LLCP PDU + uint8_t length; + /// LLCP PDU data + uint8_t data[26]; +}; + + +/// HCI DBG Meta Event trigg when LLCP message received with LLCP pass through mechanism +struct hci_dbg_ble_tst_llcp_recv_evt +{ + ///DBG Subevent code + uint8_t subcode; + ///Connection handle + uint16_t conhdl; + /// length of LLCP message + uint8_t length; + /// LLCP data + uint8_t data[26]; +}; + +#endif //(BLE_TESTER) +#endif //BLE_EMB_PRESENT || BLE_HOST_PRESENT + +#if (RW_DEBUG) +/// HCI DBG Meta Event indicating a SW assertion error +struct hci_dbg_assert_err_evt +{ + ///DBG Subevent code + uint8_t subcode; + /// Assert type (warning/error) + uint8_t type; + /// Line number + uint32_t line; + /// Param0 + uint32_t param0; + /// Param1 + uint32_t param1; + /// File name + uint8_t file[__ARRAY_EMPTY]; +}; +#endif //(RW_DEBUG) + + +/// @} COMMON_BT +#endif // COMMON_HCI_H_ diff --git a/beken_os/beken378/driver/ble/ble_pub/modules/common/api/common_list.h b/beken_os/beken378/driver/ble/ble_pub/modules/common/api/common_list.h new file mode 100755 index 0000000..32e15f8 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/modules/common/api/common_list.h @@ -0,0 +1,288 @@ +/** + **************************************************************************************** + * + * @file common_list.h + * + * @brief Common list structures definitions + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef _COMMON_LIST_H_ +#define _COMMON_LIST_H_ + +/** + ***************************************************************************************** + * @defgroup COMMON_LIST List management + * @ingroup COMMON + * + * @brief List management. + * + * This module contains the list structures and handling functions. + * @{ + ***************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include // standard definition +#include // boolean definition +#include // for NULL and size_t +#include "rwip_config.h" // stack configuration +#include "ble_compiler.h" // for __INLINE + + +/* + * DEFINES + **************************************************************************************** + */ +///list type +enum +{ + POOL_LINKED_LIST = 0x00, + RING_LINKED_LIST, + LINK_TYPE_END +}; + +/// structure of a list element header +struct common_list_hdr +{ + /// Pointer to next common_list_hdr + struct common_list_hdr *next; +}; + +/// structure of a list +struct common_list +{ + /// pointer to first element of the list + struct common_list_hdr *first; + /// pointer to the last element + struct common_list_hdr *last; + + #if (KERNEL_PROFILING) + /// number of element in the list + uint32_t cnt; + /// max number of element in the list + uint32_t maxcnt; + /// min number of element in the list + uint32_t mincnt; + #endif //KERNEL_PROFILING +}; + + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ +/** + **************************************************************************************** + * @brief Initialize a list to defaults values. + * + * @param list Pointer to the list structure. + **************************************************************************************** + */ +void common_list_init(struct common_list *list); + +/** + **************************************************************************************** + * @brief Initialize a pool to default values, and initialize the relative free list. + * + * @param list Pointer to the list structure + * @param pool Pointer to the pool to be initialized + * @param elmt_size Size of one element of the pool + * @param elmt_cnt Nb of elements available in the pool + * @param default_value Pointer to the default value of each element (may be NULL) + * @param list_type Determine if the it is a ring list or not + * + **************************************************************************************** + */ +void common_list_pool_init(struct common_list *list, + void *pool, + size_t elmt_size, + uint32_t elmt_cnt, + void *default_value, + uint8_t list_type); + +/** + **************************************************************************************** + * @brief Add an element as last on the list. + * + * @param list Pointer to the list structure + * @param list_hdr Pointer to the header to add at the end of the list + * + **************************************************************************************** + */ +void common_list_push_back(struct common_list *list, struct common_list_hdr *list_hdr); + +/** + **************************************************************************************** + * @brief Add an element as first on the list. + * + * @param list Pointer to the list structure + * @param list_hdr Pointer to the header to add at the beginning of the list + **************************************************************************************** + */ +void common_list_push_front(struct common_list *list, struct common_list_hdr *list_hdr); + +/** + **************************************************************************************** + * @brief Extract the first element of the list. + * @param list Pointer to the list structure + * @return The pointer to the element extracted, and NULL if the list is empty. + **************************************************************************************** + */ +struct common_list_hdr *common_list_pop_front(struct common_list *list); + +/** + **************************************************************************************** + * @brief Search for a given element in the list, and extract it if found. + * + * @param list Pointer to the list structure + * @param list_hdr Element to extract + * @param nb_following Number of following elements to extract + * + * @return true if the element is found in the list, false otherwise + **************************************************************************************** + */ +bool common_list_extract(struct common_list *list, struct common_list_hdr *list_hdr, uint8_t nb_following); + +/** + **************************************************************************************** + * @brief Extract an element when the previous element is known + * + * Note: the element to remove shall follow immediately the reference within the list + * + * @param list Pointer to the list structure + * @param elt_ref_hdr Pointer to the referenced element (NULL if element to extract is the first in the list) + * @param elt_to_rem_hdr Pointer to the element to be extracted + **************************************************************************************** + */ +void common_list_extract_after(struct common_list *list, struct common_list_hdr *elt_ref_hdr, struct common_list_hdr *elt_to_rem_hdr); + +/** + **************************************************************************************** + * @brief Searched a given element in the list. + * + * @param list Pointer to the list structure + * @param list_hdr Pointer to the searched element + * + * @return true if the element is found in the list, false otherwise + **************************************************************************************** + */ +bool common_list_find(struct common_list *list, struct common_list_hdr *list_hdr); + +/** + **************************************************************************************** + * @brief Merge two lists in a single one. + * + * This function appends the list pointed by list2 to the list pointed by list1. Once the + * merge is done, it empties list2. + * + * @param list1 Pointer to the destination list + * @param list2 Pointer to the list to append to list1 + **************************************************************************************** + */ +void common_list_merge(struct common_list *list1, struct common_list *list2); + +/** + **************************************************************************************** + * @brief Insert a given element in the list before the referenced element. + * + * @param list Pointer to the list structure + * @param elt_ref_hdr Pointer to the referenced element + * @param elt_to_add_hdr Pointer to the element to be inserted + * + * @return true if the element is found in the list, false otherwise + **************************************************************************************** + */ +void common_list_insert_before(struct common_list *list, + struct common_list_hdr *elt_ref_hdr, struct common_list_hdr *elt_to_add_hdr); + +/** + **************************************************************************************** + * @brief Insert a given element in the list after the referenced element. + * + * @param list Pointer to the list structure + * @param elt_ref_hdr Pointer to the referenced element + * @param elt_to_add_hdr Pointer to the element to be inserted + * + * @return true if the element is found in the list, false otherwise + **************************************************************************************** + */ +void common_list_insert_after(struct common_list *list, + struct common_list_hdr *elt_ref_hdr, struct common_list_hdr *elt_to_add_hdr); + + +/** + **************************************************************************************** + * @brief Count number of elements present in the list + * + * @param list Pointer to the list structure + * + * @return Number of elements present in the list + **************************************************************************************** + */ +uint16_t common_list_size(struct common_list *list); + +/** + **************************************************************************************** + * @brief Check if there is enough element available in the list + * + * @param list Pointer to the list structure + * @param nb_elt_needed Number of element needed + * + * @return True if enough element are available in the list + **************************************************************************************** + */ +bool common_list_check_size_available(struct common_list *list, uint8_t nb_elt_needed); + +/** + **************************************************************************************** + * @brief Test if the list is empty. + * @param list Pointer to the list structure. + * @return true if the list is empty, false else otherwise. + **************************************************************************************** + */ +bool __INLINE common_list_is_empty(const struct common_list *const list) +{ + bool listempty; + listempty = (list->first == NULL); + return (listempty); +} + +/** + **************************************************************************************** + * @brief Pick the first element from the list without removing it. + * + * @param list Pointer to the list structure. + * + * @return First element address. Returns NULL pointer if the list is empty. + **************************************************************************************** + */ +__INLINE struct common_list_hdr *common_list_pick(const struct common_list *const list) +{ + return(list->first); +} + + +/** + **************************************************************************************** + * @brief Return following element of a list element. + * + * @param list_hdr Pointer to the list element. + * + * @return The pointer to the next element. + **************************************************************************************** + */ +__INLINE struct common_list_hdr *common_list_next(const struct common_list_hdr *const list_hdr) +{ + return(list_hdr->next); +} + +/// @} COMMON_LIST +#endif // _COMMON_LIST_H_ diff --git a/beken_os/beken378/driver/ble/ble_pub/modules/common/api/common_llcp.h b/beken_os/beken378/driver/ble/ble_pub/modules/common/api/common_llcp.h new file mode 100755 index 0000000..3e3a468 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/modules/common/api/common_llcp.h @@ -0,0 +1,485 @@ +/** + **************************************************************************************** + * + * @file common_llcp.h + * + * @brief This file contains the LLCP Bluetooth defines, enumerations and structures + * definitions for use by all modules in RW stack. + * + * Copyright (C) RivieraWaves 2009-2015 + * + **************************************************************************************** + */ + +#ifndef COMMON_LLCP_H_ +#define COMMON_LLCP_H_ + +/** + **************************************************************************************** + * @addtogroup COMMON_BT + * @{ + **************************************************************************************** + */ + + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "common_bt.h" +/* + * DEFINES + **************************************************************************************** + */ +#define LLCP_OPCODE_MASK (0xFF) +#define LLCP_OPCODE_POS (0) +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ +/// Control packet opcode +enum common_llcp_opcode +{ + /// Connection update request + LLCP_CONNECTION_UPDATE_IND_OPCODE, + /// Channel map request + LLCP_CHANNEL_MAP_IND_OPCODE, + /// Termination indication + LLCP_TERMINATE_IND_OPCODE, + /// Encryption request + LLCP_ENC_REQ_OPCODE, + /// Encryption response + LLCP_ENC_RSP_OPCODE, + /// Start encryption request + LLCP_START_ENC_REQ_OPCODE, + /// Start encryption response + LLCP_START_ENC_RSP_OPCODE, + /// Unknown response + LLCP_UNKNOWN_RSP_OPCODE, + /// Feature request + LLCP_FEATURE_REQ_OPCODE, + /// Feature response + LLCP_FEATURE_RSP_OPCODE, + /// Pause encryption request + LLCP_PAUSE_ENC_REQ_OPCODE, + /// Pause encryption response + LLCP_PAUSE_ENC_RSP_OPCODE, + /// Version indication + LLCP_VERSION_IND_OPCODE, + /// Reject indication + LLCP_REJECT_IND_OPCODE, +#if !(BLE_QUALIF) + /// Slave feature request + LLCP_SLAVE_FEATURE_REQ_OPCODE, + /// Connection parameters request + LLCP_CONNECTION_PARAM_REQ_OPCODE, + /// Connection parameters response + LLCP_CONNECTION_PARAM_RSP_OPCODE, + /// Reject indication extended + LLCP_REJECT_IND_EXT_OPCODE, + /// Ping request + LLCP_PING_REQ_OPCODE, + /// Ping response + LLCP_PING_RSP_OPCODE, + /// Length request + LLCP_LENGTH_REQ_OPCODE, + /// Length response + LLCP_LENGTH_RSP_OPCODE, +#if (BLE_2MBPS) + /// Phy request + LLCP_PHY_REQ_OPCODE, + /// Phy response + LLCP_PHY_RSP_OPCODE, + /// Phy update indication + LLCP_PHY_UPD_IND_OPCODE, +#endif // (BLE_2MBPS) +#endif // !(BLE_QUALIF) + /// Opcode length + LLCP_OPCODE_MAX_OPCODE, + + #if (BLE_TESTER) + LLCP_OPCODE_DEBUG = 0xFF, + #endif // (BLE_TESTER) +}; + +/// PDU lengths (including opcode) +enum common_llcp_length +{ + LLCP_CON_REQ_LEN = 34, + LLCP_CON_UPD_IND_LEN = 12, + LLCP_CH_MAP_REQ_LEN = 8, + LLCP_TERM_IND_LEN = 2, + LLCP_ENC_REQ_LEN = 23, + LLCP_ENC_RSP_LEN = 13, + LLCP_ST_ENC_REQ_LEN = 1, + LLCP_ST_ENC_RSP_LEN = 1, + LLCP_UNKN_RSP_LEN = 2, + LLCP_FEAT_REQ_LEN = 9, + LLCP_FEAT_RSP_LEN = 9, + LLCP_PA_ENC_REQ_LEN = 1, + LLCP_PA_ENC_RSP_LEN = 1, + LLCP_VERS_IND_LEN = 6, + LLCP_REJ_IND_LEN = 2, + LLCP_SLAVE_FEATURE_REQ_LEN = 9, + LLCP_REJECT_IND_EXT_LEN = 3, + LLCP_CON_PARAM_REQ_LEN = 24, + LLCP_CON_PARAM_RSP_LEN = 24, + LLCP_PING_REQ_LEN = 1, + LLCP_PING_RSP_LEN = 1, + LLCP_LENGTH_REQ_LEN = 9, + LLCP_LENGTH_RSP_LEN = 9, + #if(BLE_2MBPS) + LLCP_PHY_REQ_LEN = 3, + LLCP_PHY_RSP_LEN = 3, + LLCP_PHY_UPD_REQ_LEN = 5, + #endif // (BLE_2MBPS) + LLCP_PDU_LENGTH_MAX = 34 +}; + +/* + * MESSAGES + **************************************************************************************** + */ + + +/// LLCP_CONNECTION_UPDATE_REQ structure. +struct llcp_con_upd_ind +{ + /// opcode + uint8_t opcode; + /// window size + uint8_t win_size; + /// window offset + uint16_t win_off; + /// interval + uint16_t interv; + /// latency + uint16_t latency; + /// timeout + uint16_t timeout; + /// instant + uint16_t instant; +}; + +/// LLCP_CHANNEL_MAP_REQ structure. +struct llcp_channel_map_ind +{ + /// opcode + uint8_t opcode; + /// channel mapping + struct le_chnl_map ch_map; + /// instant + uint16_t instant; +}; + +/// LLCP_TERMINATE_IND structure. +struct llcp_terminate_ind +{ + /// opcode + uint8_t opcode; + /// termination code + uint8_t err_code; +}; + +/// LLCP_ENC_REQ structure. +struct llcp_enc_req +{ + /// opcode + uint8_t opcode; + /// random value + struct rand_nb rand; + /// ediv + uint8_t ediv[2]; + /// skdm + struct sess_k_div_x skdm; + /// ivm + struct init_vect ivm; +}; + +/// LLCP_ENC_RSP structure. +struct llcp_enc_rsp +{ + /// opcode + uint8_t opcode; + /// skds + struct sess_k_div_x skds; + /// ivs + struct init_vect ivs; +}; + +/// LLCP_START_ENC_REQ structure. +struct llcp_start_enc_req +{ + /// opcode + uint8_t opcode; +}; + +/// LLCP_START_ENC_RSP structure. +struct llcp_start_enc_rsp +{ + /// opcode + uint8_t opcode; +}; + +/// LLCP_UNKNOWN_RSP structure. +struct llcp_unknown_rsp +{ + /// opcode + uint8_t opcode; + /// unknown type + uint8_t unk_type; +}; + +/// LLCP_FEATURE_REQ structure. +struct llcp_feats_req +{ + /// opcode + uint8_t opcode; + /// le features + struct le_features feats; +}; + +/// LLCP_FEATURE_RSP structure. +struct llcp_feats_rsp +{ + /// opcode + uint8_t opcode; + /// le features + struct le_features feats; +}; + +/// LLCP_PAUSE_ENC_REQ structure. +struct llcp_pause_enc_req +{ + /// opcode + uint8_t opcode; +}; + +/// LLCP_PAUSE_ENC_RSP structure. +struct llcp_pause_enc_rsp +{ + /// opcode + uint8_t opcode; +}; + +/// LLCP_VERS_IND structure +struct llcp_vers_ind +{ + /// opcode + uint8_t opcode; + /// version + uint8_t vers; + /// company id + uint16_t compid; + /// sub version + uint16_t subvers; +}; + +/// LLCP_REJECT_IND structure. +struct llcp_reject_ind +{ + /// opcode + uint8_t opcode; + /// reject reason + uint8_t err_code; +}; + +/// LLCP_SLAVE_FEATURE_REQ structure. +struct llcp_slave_feature_req +{ + /// opcode + uint8_t opcode; + /// le features + struct le_features feats; +}; + +/// LLCP_CONNECTION_PARAM_REQ structure. +struct llcp_con_param_req +{ + /// opcode + uint8_t opcode; + /// minimum value of connInterval + uint16_t interval_min; + /// maximum value of connInterval + uint16_t interval_max; + /// connSlaveLatency value + uint16_t latency; + /// connSupervisionTimeout value + uint16_t timeout; + /// preferred periodicity + uint8_t pref_period; + /// ReferenceConnEventCount + uint16_t ref_con_event_count; + /// Offset0 + uint16_t offset0; + /// Offset1 + uint16_t offset1; + /// Offset2 + uint16_t offset2; + /// Offset3 + uint16_t offset3; + /// Offset4 + uint16_t offset4; + /// Offset5 + uint16_t offset5; +}; + +/// LLCP_CONNECTION_PARAM_RSP structure. +struct llcp_con_param_rsp +{ + /// opcode + uint8_t opcode; + /// minimum value of connInterval + uint16_t interval_min; + /// maximum value of connInterval + uint16_t interval_max; + /// connSlaveLatency value + uint16_t latency; + /// connSupervisionTimeout value + uint16_t timeout; + /// preferred periodicity + uint8_t pref_period; + /// ReferenceConnEventCount + uint16_t ref_con_event_count; + /// Offset0 + uint16_t offset0; + /// Offset1 + uint16_t offset1; + /// Offset2 + uint16_t offset2; + /// Offset3 + uint16_t offset3; + /// Offset4 + uint16_t offset4; + /// Offset5 + uint16_t offset5; +}; + +/// LLCP_REJECT_IND structure. +struct llcp_reject_ind_ext +{ + /// opcode + uint8_t opcode; + /// rejected opcode + uint8_t rej_opcode; + /// reject reason + uint8_t err_code; +}; + +/// LLCP_PING_REQ structure. +struct llcp_ping_req +{ + /// opcode + uint8_t opcode; +}; + +/// LLCP_PING_RSP structure. +struct llcp_ping_rsp +{ + /// opcode + uint8_t opcode; +}; + +/// LLCP_LENGTH_REQ structure. +struct llcp_length_req +{ + /// opcode + uint8_t opcode; + /// The max size in reception + uint16_t max_rx_octets; + /// The max time in reception + uint16_t max_rx_time; + /// The max size in transmission + uint16_t max_tx_octets; + /// The max time in transmission + uint16_t max_tx_time; +}; + +/// LLCP_LENGTH_RSP structure. +struct llcp_length_rsp +{ + /// opcode + uint8_t opcode; + /// The max size in reception + uint16_t max_rx_octets; + /// The max time in reception + uint16_t max_rx_time; + /// The max size in transmission + uint16_t max_tx_octets; + /// The max time in transmission + uint16_t max_tx_time; +}; + +#if (BLE_2MBPS) +/// LLCP_PHY_REQ structure. +struct llcp_phy_req +{ + /// opcode + uint8_t opcode; + /// Tx phy selection + uint8_t tx_phys; + /// Rx phy selection + uint8_t rx_phys; +}; + +/// LLCP_PHY_RSP structure. +struct llcp_phy_rsp +{ + /// opcode + uint8_t opcode; + /// Tx phy selection + uint8_t tx_phys; + /// Rx phy selection + uint8_t rx_phys; +}; + +/// LLCP_PHY_UPD_REQ structure. +struct llcp_phy_upd_req +{ + /// opcode + uint8_t opcode; + /// master to slave phy selected + uint8_t m_to_s_phy; + /// slave to master phy selected + uint8_t s_to_m_phy; + /// Instant + uint16_t instant; +}; +#endif // (BLE_2MBPS) +/// LLCP pdu format +union llcp_pdu +{ + /// opcode + uint8_t opcode; + + struct llcp_con_upd_ind con_up_req; + struct llcp_channel_map_ind channel_map_req; + struct llcp_terminate_ind terminate_ind; + struct llcp_enc_req enc_req; + struct llcp_enc_rsp enc_rsp; + struct llcp_start_enc_req start_enc_req; + struct llcp_start_enc_rsp start_enc_rsp; + struct llcp_unknown_rsp unknown_rsp; + struct llcp_feats_req feats_req; + struct llcp_feats_rsp feats_rsp; + struct llcp_pause_enc_req pause_enc_req; + struct llcp_pause_enc_rsp pause_enc_rsp; + struct llcp_vers_ind vers_ind; + struct llcp_reject_ind reject_ind; + struct llcp_slave_feature_req slave_feature_req; + struct llcp_con_param_req con_param_req; + struct llcp_con_param_rsp con_param_rsp; + struct llcp_reject_ind_ext reject_ind_ext; + struct llcp_ping_req ping_req; + struct llcp_ping_rsp ping_rsp; + struct llcp_length_req length_req; + struct llcp_length_rsp length_rsp; + #if (BLE_2MBPS) + struct llcp_phy_req phy_req; + struct llcp_phy_rsp phy_rsp; + struct llcp_phy_upd_req phy_upd_req; + #endif +}; + +/// @} COMMON_BT +#endif // COMMON_LLCP_H_ diff --git a/beken_os/beken378/driver/ble/ble_pub/modules/common/api/common_lmp.h b/beken_os/beken378/driver/ble/ble_pub/modules/common/api/common_lmp.h new file mode 100755 index 0000000..efd8bf9 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/modules/common/api/common_lmp.h @@ -0,0 +1,1238 @@ +/** + **************************************************************************************** + * + * @file common_lmp.h + * + * @brief This file contains the HCI Bluetooth defines, enumerations and structures + * definitions for use by all modules in RW stack. + * + * Copyright (C) RivieraWaves 2009-2015 + * + **************************************************************************************** + */ + +#ifndef COMMON_LMP_H_ +#define COMMON_LMP_H_ + +/** + **************************************************************************************** + * @addtogroup COMMON_BT + * @{ + **************************************************************************************** + */ + + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "common_bt.h" +/* + * DEFINES + **************************************************************************************** + */ + +//LMP Opcodes +#define LMP_NAME_REQ_OPCODE 1 +#define LMP_NAME_RES_OPCODE 2 +#define LMP_ACCEPTED_OPCODE 3 +#define LMP_NOT_ACCEPTED_OPCODE 4 +#define LMP_CLK_OFF_REQ_OPCODE 5 +#define LMP_CLK_OFF_RES_OPCODE 6 +#define LMP_DETACH_OPCODE 7 +#define LMP_INRAND_OPCODE 8 +#define LMP_COMBKEY_OPCODE 9 +#define LMP_UNITKEY_OPCODE 10 +#define LMP_AURAND_OPCODE 11 +#define LMP_SRES_OPCODE 12 +#define LMP_TEMPRAND_OPCODE 13 +#define LMP_TEMPKEY_OPCODE 14 +#define LMP_ENC_MODE_REQ_OPCODE 15 +#define LMP_ENC_KEY_SIZE_REQ_OPCODE 16 +#define LMP_START_ENC_REQ_OPCODE 17 +#define LMP_STOP_ENC_REQ_OPCODE 18 +#define LMP_SWITCH_REQ_OPCODE 19 +#define LMP_HOLD_OPCODE 20 +#define LMP_HOLD_REQ_OPCODE 21 +#define LMP_SNIFF_REQ_OPCODE 23 +#define LMP_UNSNIFF_REQ_OPCODE 24 +#define LMP_PARK_REQ_OPCODE 25 +#define LMP_SET_BSWIN_OPCODE 27 +#define LMP_MODIF_BEACON_OPCODE 28 +#define LMP_UNPARK_BD_REQ_OPCODE 29 +#define LMP_UNPARK_PM_REQ_OPCODE 30 +#define LMP_INCR_PWR_REQ_OPCODE 31 +#define LMP_DECR_PWR_REQ_OPCODE 32 +#define LMP_MAX_PWR_OPCODE 33 +#define LMP_MIN_PWR_OPCODE 34 +#define LMP_AUTO_RATE_OPCODE 35 +#define LMP_PREF_RATE_OPCODE 36 +#define LMP_VER_REQ_OPCODE 37 +#define LMP_VER_RES_OPCODE 38 +#define LMP_FEATS_REQ_OPCODE 39 +#define LMP_FEATS_RES_OPCODE 40 +#define LMP_QOS_OPCODE 41 +#define LMP_QOS_REQ_OPCODE 42 +#define LMP_SCOMMON_LINK_REQ_OPCODE 43 +#define LMP_RMV_SCOMMON_LINK_REQ_OPCODE 44 +#define LMP_MAX_SLOT_OPCODE 45 +#define LMP_MAX_SLOT_REQ_OPCODE 46 +#define LMP_TIMING_ACCU_REQ_OPCODE 47 +#define LMP_TIMING_ACCU_RES_OPCODE 48 +#define LMP_SETUP_CMP_OPCODE 49 +#define LMP_USE_SEMI_PERM_KEY_OPCODE 50 +#define LMP_HOST_CON_REQ_OPCODE 51 +#define LMP_SLOT_OFF_OPCODE 52 +#define LMP_PAGE_MODE_REQ_OPCODE 53 +#define LMP_PAGE_SCAN_MODE_REQ_OPCODE 54 +#define LMP_SUPV_TO_OPCODE 55 +#define LMP_TEST_ACTIVATE_OPCODE 56 +#define LMP_TEST_CTRL_OPCODE 57 +#define LMP_ENC_KEY_SIZE_MASK_REQ_OPCODE 58 +#define LMP_ENC_KEY_SIZE_MASK_RES_OPCODE 59 +#define LMP_SET_AFH_OPCODE 60 +#define LMP_ENCAPS_HDR_OPCODE 61 +#define LMP_ENCAPS_PAYL_OPCODE 62 +#define LMP_SP_CFM_OPCODE 63 +#define LMP_SP_NB_OPCODE 64 +#define LMP_DHKEY_CHK_OPCODE 65 +#define LMP_PAUSE_ENC_AES_REQ_OPCODE 66 + +#define LMP_ESC1_OPCODE 124 +#define LMP_ESC2_OPCODE 125 +#define LMP_ESC3_OPCODE 126 +#define LMP_ESC4_OPCODE 127 + +///LMP Escape 4 Extended Opcodes +#define LMP_ACCEPTED_EXT_EXTOPCODE 1 +#define LMP_NOT_ACCEPTED_EXT_EXTOPCODE 2 +#define LMP_FEATS_REQ_EXT_EXTOPCODE 3 +#define LMP_FEATS_RES_EXT_EXTOPCODE 4 +#define LMP_CLK_ADJ_EXTOPCODE 5 +#define LMP_CLK_ADJ_ACK_EXTOPCODE 6 +#define LMP_CLK_ADJ_REQ_EXTOPCODE 7 +#define LMP_PKT_TYPE_TBL_REQ_EXTOPCODE 11 +#define LMP_ESCOMMON_LINK_REQ_EXTOPCODE 12 +#define LMP_RMV_ESCOMMON_LINK_REQ_EXTOPCODE 13 +#define LMP_CH_CLASS_REQ_EXTOPCODE 16 +#define LMP_CH_CLASS_EXTOPCODE 17 +#define LMP_SSR_REQ_EXTOPCODE 21 +#define LMP_SSR_RES_EXTOPCODE 22 +#define LMP_PAUSE_ENC_REQ_EXTOPCODE 23 +#define LMP_RESUME_ENC_REQ_EXTOPCODE 24 +#define LMP_IO_CAP_REQ_EXTOPCODE 25 +#define LMP_IO_CAP_RES_EXTOPCODE 26 +#define LMP_NUM_COMPARISON_FAIL_EXTOPCODE 27 +#define LMP_PASSKEY_FAIL_EXTOPCODE 28 +#define LMP_OOB_FAIL_EXTOPCODE 29 +#define LMP_KEYPRESS_NOTIF_EXTOPCODE 30 +#define LMP_PWR_CTRL_REQ_EXTOPCODE 31 +#define LMP_PWR_CTRL_RES_EXTOPCODE 32 +#define LMP_PING_REQ_EXTOPCODE 33 +#define LMP_PING_RES_EXTOPCODE 34 + +/// PDU lengths (including opcode) +#define LMP_NAME_REQ_LEN 2 +#define LMP_NAME_RES_LEN 17 +#define LMP_ACCEPTED_LEN 2 +#define LMP_NOT_ACCEPTED_LEN 3 +#define LMP_CLK_OFF_REQ_LEN 1 +#define LMP_CLK_OFF_RES_LEN 3 +#define LMP_DETACH_LEN 2 +#define LMP_INRAND_LEN 17 +#define LMP_COMBKEY_LEN 17 +#define LMP_UNITKEY_LEN 17 +#define LMP_AURAND_LEN 17 +#define LMP_SRES_LEN 5 +#define LMP_TEMPRAND_LEN 17 +#define LMP_TEMPKEY_LEN 17 +#define LMP_ENC_MODE_REQ_LEN 2 +#define LMP_ENC_KEY_SIZE_REQ_LEN 2 +#define LMP_START_ENC_REQ_LEN 17 +#define LMP_STOP_ENC_REQ_LEN 1 +#define LMP_SWITCH_REQ_LEN 5 +#define LMP_HOLD_LEN 7 +#define LMP_HOLD_REQ_LEN 7 +#define LMP_SNIFF_REQ_LEN 10 +#define LMP_UNSNIFF_REQ_LEN 1 +#define LMP_PARK_REQ_LEN 17 +#define LMP_INCR_PWR_REQ_LEN 2 +#define LMP_DECR_PWR_REQ_LEN 2 +#define LMP_MAX_PWR_LEN 1 +#define LMP_MIN_PWR_LEN 1 +#define LMP_AUTO_RATE_LEN 1 +#define LMP_PREF_RATE_LEN 2 +#define LMP_VER_REQ_LEN 6 +#define LMP_VER_RES_LEN 6 +#define LMP_FEATS_REQ_LEN 9 +#define LMP_FEATS_RES_LEN 9 +#define LMP_QOS_LEN 4 +#define LMP_QOS_REQ_LEN 4 +#define LMP_SCOMMON_LINK_REQ_LEN 7 +#define LMP_RMV_SCOMMON_LINK_REQ_LEN 3 +#define LMP_MAX_SLOT_LEN 2 +#define LMP_MAX_SLOT_REQ_LEN 2 +#define LMP_TIMING_ACCU_REQ_LEN 1 +#define LMP_TIMING_ACCU_RES_LEN 3 +#define LMP_SETUP_CMP_LEN 1 +#define LMP_USE_SEMI_PERM_KEY_LEN 1 +#define LMP_HOST_CON_REQ_LEN 1 +#define LMP_SLOT_OFF_LEN 9 +#define LMP_PAGE_MODE_REQ_LEN 3 +#define LMP_PAGE_SCAN_MODE_REQ_LEN 3 +#define LMP_SUPV_TO_LEN 3 +#define LMP_TEST_ACTIVATE_LEN 1 +#define LMP_TEST_CTRL_LEN 10 +#define LMP_ENC_KEY_SIZE_MASK_REQ_LEN 1 +#define LMP_ENC_KEY_SIZE_MASK_RES_LEN 3 +#define LMP_SET_AFH_LEN 16 +#define LMP_ENCAPS_HDR_LEN 4 +#define LMP_ENCAPS_PAYL_LEN 17 +#define LMP_SP_CFM_LEN 17 +#define LMP_SP_NB_LEN 17 +#define LMP_DHKEY_CHK_LEN 17 +#define LMP_PAUSE_ENC_AES_REQ_LEN 17 + +/// LMP Escape 4 Extended PDU length (including opcode and ext opcode) +#define LMP_ACCEPTED_EXT_LEN 4 +#define LMP_NOT_ACCEPTED_EXT_LEN 5 +#define LMP_FEATS_REQ_EXT_LEN 12 +#define LMP_FEATS_RES_EXT_LEN 12 +#define LMP_CLK_ADJ_LEN 15 +#define LMP_CLK_ADJ_ACK_LEN 3 +#define LMP_CLK_ADJ_REQ_LEN 6 +#define LMP_PKT_TYPE_TBL_REQ_LEN 3 +#define LMP_ESCOMMON_LINK_REQ_LEN 16 +#define LMP_RMV_ESCOMMON_LINK_REQ_LEN 4 +#define LMP_CH_CLASS_REQ_LEN 7 +#define LMP_CH_CLASS_LEN 12 +#define LMP_SSR_REQ_LEN 9 +#define LMP_SSR_RES_LEN 9 +#define LMP_PAUSE_ENC_REQ_LEN 2 +#define LMP_RESUME_ENC_REQ_LEN 2 +#define LMP_IO_CAP_REQ_LEN 5 +#define LMP_IO_CAP_RES_LEN 5 +#define LMP_NUM_COMPARISON_FAIL_LEN 2 +#define LMP_PASSKEY_FAIL_LEN 2 +#define LMP_OOB_FAIL_LEN 2 +#define LMP_KEYPRESS_NOTIF_LEN 3 +#define LMP_PWR_CTRL_REQ_LEN 3 +#define LMP_PWR_CTRL_RES_LEN 3 +#define LMP_PING_REQ_LEN 2 +#define LMP_PING_RES_LEN 2 + +/// Maximum LMP PDU size (including opcode and ext opcode) +#define LMP_MAX_PDU_SIZE DM1_PACKET_SIZE + +/// Position of transaction ID in 1st byte +#define LMP_TR_ID_POS 0 +#define LMP_TR_ID_MASK 0x01 +/// Position of opcode in 1st byte +#define LMP_OPCODE_POS 1 +#define LMP_OPCODE_MASK 0xFE + +#define LMP_OPCODE(opcode, tr_id) (((opcode << LMP_OPCODE_POS) & LMP_OPCODE_MASK) | ((tr_id << LMP_TR_ID_POS) & LMP_TR_ID_MASK)) +/* + * MESSAGES + **************************************************************************************** + */ + +///LMP_name_req PDU structure +struct lmp_name_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Offset + uint8_t offset; +}; + +///LMP_name_res PDU structure +struct lmp_name_res +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Offset + uint8_t offset; + ///Name Length + uint8_t length; + ///Name Fragment + struct name_vect name_frag; +}; + +///LMP_accepted PDU structure +struct lmp_accepted +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Opcode of the original LMP + uint8_t orig_opcode; +}; + +///LMP_not_accepted PDU structure +struct lmp_not_accepted +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Opcode of the original LMP + uint8_t orig_opcode; + ///Reason for not accepting the PDU (error code) + uint8_t reason; +}; + +///LMP_clkoffset_req PDU structure +struct lmp_clk_off_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; +}; + +///LMP_clkoffset_res PDU structure +struct lmp_clk_off_res +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Clock Offset value + uint16_t clk_offset ; +}; + +///LMP_detach PDU structure +struct lmp_detach +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Reason to detach + uint8_t reason; +}; + +///LMP_in_rand PDU structure +struct lmp_inrand +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Random number + struct ltk random; +}; + +///LMP_comb_key PDU structure +struct lmp_combkey +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Random number + struct ltk random; +}; + +///LMP_unit_key PDU structure +struct lmp_unitkey +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Key + struct ltk key; +}; + +///LMP_au_rand PDU structure +struct lmp_aurand +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Random number + struct ltk random; +}; + +///LMP_sres PDU structure +struct lmp_sres +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Authentication Response + struct sres_nb Sres; +}; + +///LMP_temp_rand PDU structure +struct lmp_temprand +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Random number + struct ltk random; +}; + +///LMP_temp_key PDU structure +struct lmp_tempkey +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Key + struct ltk key; +}; + +///LMP_encryption_mode_req PDU structure +struct lmp_enc_mode_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Encryption Mode + uint8_t enc_mode; +}; + +///LMP_encryption_key_size_req PDU structure +struct lmp_enc_key_size_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Key Size + uint8_t key_size; +}; + +///LMP_start_encryption_req PDU structure +struct lmp_start_enc_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Random number + struct ltk random; +}; + +///LMP_stop_encryption_req PDU structure +struct lmp_stop_enc_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; +}; + +///LMP_switch_req PDU structure +struct lmp_switch_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Switch Instant + uint32_t switch_inst; +}; + +///LMP_sniff_req PDU structure +struct lmp_sniff_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Timing Control Flags + uint8_t flags; + ///Dsniff + uint16_t d_sniff; + ///Tsniff + uint16_t t_sniff; + ///Sniff attempt + uint16_t sniff_attempt; + ///Sniff Timeout + uint16_t sniff_to; +}; + +///LMP_unsniff_req PDU structure +struct lmp_unsniff_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; +}; + +///LMP_incr_power_req PDU structure +struct lmp_incr_pwr_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///For future use + uint8_t reserved; +}; + +///LMP_decr_power_req PDU structure +struct lmp_decr_pwr_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///For future use + uint8_t reserved; +}; + +///LMP_max_power PDU structure +struct lmp_max_pwr +{ + ///Opcode (including transaction ID) + uint8_t opcode; +}; + +///LMP_min_power PDU structure +struct lmp_min_pwr +{ + ///Opcode (including transaction ID) + uint8_t opcode; +}; + +///LMP_auto_rate PDU structure +struct lmp_auto_rate +{ + ///Opcode (including transaction ID) + uint8_t opcode; +}; + +///LMP_preferred_rate PDU structure +struct lmp_pref_rate +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Data Rate + uint8_t rate; +}; + +///LMP_version_req PDU structure +struct lmp_ver_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Version number + uint8_t ver; + ///Company ID + uint16_t common_id; + ///Subversion number + uint16_t subver; +}; + +///LMP_version_res PDU structure +struct lmp_ver_res +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Version number + uint8_t ver; + ///Company ID + uint16_t common_id; + ///Subversion number + uint16_t subver; +}; + +///LMP_features_req PDU structure +struct lmp_feats_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Features + struct features feats; +}; + +///LMP_features_res PDU structure +struct lmp_feats_res +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Features + struct features feats; +}; + +///LMP_quality_of_service PDU structure +struct lmp_qos +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Poll interval + uint16_t poll_intv; + ///Nbc + uint8_t nbc; +}; + + +///LMP_quality_of_service_req PDU structure +struct lmp_qos_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Poll interval + uint16_t poll_intv; + ///Nbc + uint8_t nbc; +}; + +///LMP_SCOMMON_link_req PDU structure +struct lmp_scommon_link_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///SCO handle + uint8_t scommon_hdl; + ///timing control flags + uint8_t flags; + ///Dsco + uint8_t d_sco; + ///Tsco + uint8_t t_sco; + ///SCO packet + uint8_t scommon_pkt; + ///Air mode + uint8_t air_mode; +}; + +///LMP_remove_SCOMMON_link_req PDU structure +struct lmp_rmv_scommon_link_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///SCO handle + uint8_t scommon_hdl; + ///Reason for its removal(error code) + uint8_t reason; +}; + +///LMP_max_slot PDU structure +struct lmp_max_slot +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Max slots + uint8_t max_slots; +}; + + +///LMP_max_slot_req PDU structure +struct lmp_max_slot_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Max slots + uint8_t max_slots; +}; + +///LMP_timing_accuracy_req PDU structure +struct lmp_timing_accu_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; +}; + +///LMP_timing_accuracy_res PDU structure +struct lmp_timing_accu_res +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Drift + uint8_t drift; + ///Jitter + uint8_t jitter; +}; + +///LMP_setup_complete PDU structure +struct lmp_setup_cmp +{ + ///Opcode (including transaction ID) + uint8_t opcode; +}; + +///LMP_use_semi_permanent_key PDU structure +struct lmp_use_semi_perm_key +{ + ///Opcode (including transaction ID) + uint8_t opcode; +}; + +///LMP_host_connection_req PDU structure +struct lmp_host_con_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; +}; + +///LMP_slot_offset PDU structure +struct lmp_slot_off +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Slot Offset + uint16_t slot_off; + ///BD Address + struct bd_addr addr; +}; + +///LMP_page_mode_req PDU structure +struct lmp_page_mode_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Paging scheme + uint8_t page_scheme; + ///Paging scheme settings + uint8_t page_stg; +}; + +///LMP_page_scan_mode_req PDU structure +struct lmp_page_scan_mode_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Paging scheme + uint8_t page_scheme; + ///Paging scheme settings + uint8_t page_stg; +}; + +///LMP_supervision_timeout PDU structure +struct lmp_supv_to +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Supervision Timeout + uint16_t supv_to; +}; + +///LMP_test_activate PDU structure +struct lmp_test_activate +{ + ///Opcode (including transaction ID) + uint8_t opcode; +}; + +///LMP_test_control PDU structure +struct lmp_test_ctrl +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Test Scenario + uint8_t scenario; + ///Hopping Mode + uint8_t hop; + ///Tx frequency + uint8_t tx_freq; + ///Rx Frequency + uint8_t rx_freq; + ///Power Control Mode + uint8_t pwr_ctrl; + ///Poll period + uint8_t poll_period; + ///Packet type + uint8_t pkt_type; + ///length of test data + uint16_t data_len; +}; + +///LMP_encryption_key_size_mask_req PDU structure +struct lmp_enc_key_size_mask_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; +}; + +///LMP_encryption_key_size_mask_res PDU structure +struct lmp_enc_key_size_mask_res +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Encryption Key Size Mask + uint16_t mask; +}; + +///LMP_set_AFH PDU structure +struct lmp_set_afh +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///AFH Instant + uint32_t instant; + ///AFH Mode + uint8_t mode; + ///AFH channel map + struct chnl_map map; +}; + +///LMP_encapsulated_header PDU structure +struct lmp_encaps_hdr +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Encapsulated major type + uint8_t maj_type; + ///Encapsulated minor type + uint8_t min_type; + ///Encapsulated Payload Length + uint8_t payl_len; +}; + +///LMP_encapsulated_payload PDU structure +struct lmp_encaps_payl +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Encapsulated data + struct byte16 data; +}; + +///LMP_Simple_Pairing_Confirm PDU structure +struct lmp_sp_cfm +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Commitment Value + struct byte16 commitment_val ; +}; + +///LMP_Simple_Pairing_Number PDU structure +struct lmp_sp_nb +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///nonce Value + struct byte16 nonce; +}; + +///LMP_DHkey_check PDU structure +struct lmp_dhkey_chk +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Confirmation Value + struct ltk cfm_val; +}; + +///LMP_pause_encryption_aes_req PDU structure +struct lmp_pause_enc_aes_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + /// Random Number + struct ltk rand; +}; + +/* + * Extended PDUs parameter structures - Escape 4 + ****************************************************************************************/ + +///LMP_accepted_ext PDU structure +struct lmp_accepted_ext +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; + ///Escape opcode of the original LMP + uint8_t orig_esc_opcode; + ///Extended opcode of the original LMP + uint8_t orig_ext_opcode; +}; + +///LMP_not_accepted_ext PDU structure +struct lmp_not_accepted_ext +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; + ///Escape opcode of the original LMP + uint8_t orig_esc_opcode; + ///Extended opcode of the original LMP + uint8_t orig_ext_opcode; + ///Reason + uint8_t reason; +}; + +///LMP_features_req_ext PDU structure +struct lmp_feats_req_ext +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; + ///Features page + uint8_t page; + ///Max supported page + uint8_t max_page; + ///Extended features + struct features ext_feats; +}; + +///LMP_features_res_ext PDU structure +struct lmp_feats_res_ext +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; + ///Features page + uint8_t page; + ///Max supported page + uint8_t max_page; + ///Extended features + struct features ext_feats; +}; + +///LMP_clk_adj PDU structure +struct lmp_clk_adj +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; + ///Coarse clock adjustment Event ID + uint8_t clk_adj_id; + ///Coarse clock adjustment instant + uint32_t clk_adj_instant; + ///Coarse clock adjustment intraslot alignment offset + int16_t clk_adj_us; + ///Coarse clock adjustment slot offset + uint8_t clk_adj_slots; + ///Coarse clock adjustment mode (before/after instant) + uint8_t clk_adj_mode; + ///Coarse clock adjustment PDU CLK instant + uint32_t clk_adj_clk; +}; + +///LMP_clk_adj_ack PDU structure +struct lmp_clk_adj_ack +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; + ///Coarse clock adjustment Event ID + uint8_t clk_adj_id; +}; + +///LMP_clk_adj_req PDU structure +struct lmp_clk_adj_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; + ///Coarse clock adjustment intraslot alignment offset + int16_t clk_adj_us; + ///Coarse clock adjustment slot offset + uint8_t clk_adj_slots; + ///Corase clock adjustment period + uint8_t clk_adj_period; +}; + +///LMP_packet_type_table_req PDU structure +struct lmp_pkt_type_tbl_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; + ///Packet Type table + uint8_t pkt_type_tbl; +}; + +///LMP_eSCOMMON_link_req PDU structure +struct lmp_escommon_link_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; + ///eSCO handle + uint8_t escommon_hdl; + ///eSCo LT Address + uint8_t escommon_lt_addr; + ///timing control flags + uint8_t flags; + ///Desco + uint8_t d_esco; + ///t_esco + uint8_t t_esco; + ///Wesco + uint8_t w_esco; + ///eSCO packet type M2S + uint8_t m2s_pkt_type; + ///eSCO packet type S2M + uint8_t s2m_pkt_type; + ///Packet Length M2S + uint16_t m2s_pkt_len; + ///Packet Length S2m + uint16_t s2m_pkt_len; + ///Air Mode + uint8_t air_mode; + ///Negotiation state + uint8_t negt_st; +}; + +///LMP_remove_eSCOMMON_link_req PDU structure +struct lmp_rmv_escommon_link_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; + ///eSCO handle + uint8_t escommon_hdl; + ///Reason + uint8_t reason; +}; + +///LMP_channel_classification_req PDU structure +struct lmp_ch_class_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; + ///AFH reporting mode + uint8_t rep_mode; + ///AFH min interval + uint16_t min_intv; + ///AFH max interval + uint16_t max_intv; +}; + +///LMP_channel_classification PDU structure +struct lmp_ch_class +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; + ///AFh channel classification + struct chnl_map ch_class; +}; + +///LMP_sniff_subrating_req PDU structure +struct lmp_ssr_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; + ///Maximum sniff sub-rate + uint8_t max_subrate; + ///Minimum sniff mode timeout + uint16_t min_to; + ///Sniff sub-rating instant + uint32_t inst; +}; + +///LMP_sniff_subrating_res PDU structure +struct lmp_ssr_res +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; + ///Maximum sniff sub-rate + uint8_t max_subrate; + ///Minimum sniff mode timeout + uint16_t min_to; + ///Sniff sub-rating instant + uint32_t inst; +}; + +///LMP_pause_encryption_req PDU structure +struct lmp_pause_enc_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; +}; + +///LMP_resume_encryption_req PDU structure +struct lmp_resume_enc_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; +}; + +///LMP_IO_capability_req PDU structure +struct lmp_io_cap_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; + ///IO Capabilities + uint8_t io_cap; + /// OOB Authentication data + uint8_t oob_auth_data; + ///Authentication requirements + uint8_t auth_req; +}; + + +///LMP_IO_capability_res PDU structure +struct lmp_io_cap_res +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; + ///IO Capabilities + uint8_t io_cap; + /// OOB Authentication data + uint8_t oob_auth_data; + ///Authentication requirements + uint8_t auth_req; +}; + +///LMP_numeric_comparison_failed PDU structure +struct lmp_num_comparison_fail +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; +}; + +///LMP_passkey_failed PDU structure +struct lmp_passkey_fail +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; +}; + +///LMP_oob_failed PDU structure +struct lmp_oob_fail +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; +}; + +///LMP_keypress_notification PDU structure +struct lmp_keypress_notif +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; + ///Notification Type + uint8_t type; +}; + +///LMP_power_control_req PDU structure +struct lmp_pwr_ctrl_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; + ///Power adjustment request + uint8_t pwr_adj; + +}; + +///LMP_power_control_res PDU structure +struct lmp_pwr_ctrl_res +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; + ///Power adjustment response + uint8_t pwr_adj; +}; + +/// LMP_ping_req PDU structure +struct lmp_ping_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; +}; + +/// LMP_ping_res PDU structure +struct lmp_ping_res +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; +}; + +/// Union of all the LMP message structures +union lmp_pdu_data +{ + struct lmp_name_req name_req ; + struct lmp_name_res name_res ; + struct lmp_accepted accepted ; + struct lmp_not_accepted not_accepted ; + struct lmp_clk_off_req clk_off_req ; + struct lmp_clk_off_res clk_off_res ; + struct lmp_detach detach ; + struct lmp_inrand inrand ; + struct lmp_combkey combkey ; + struct lmp_unitkey unitkey ; + struct lmp_aurand aurand ; + struct lmp_sres sres ; + struct lmp_temprand temprand ; + struct lmp_tempkey tempkey ; + struct lmp_enc_mode_req enc_mode_req ; + struct lmp_enc_key_size_req enc_key_size_req ; + struct lmp_start_enc_req start_enc_req ; + struct lmp_stop_enc_req stop_enc_req ; + struct lmp_switch_req switch_req ; + struct lmp_sniff_req sniff_req ; + struct lmp_unsniff_req unsniff_req ; + struct lmp_incr_pwr_req incr_pwr_req ; + struct lmp_decr_pwr_req decr_pwr_req ; + struct lmp_max_pwr max_pwr ; + struct lmp_min_pwr min_pwr ; + struct lmp_auto_rate auto_rate ; + struct lmp_pref_rate pref_rate ; + struct lmp_ver_req ver_req ; + struct lmp_ver_res ver_res ; + struct lmp_feats_req feats_req ; + struct lmp_feats_res feats_res ; + struct lmp_clk_adj clk_adj ; + struct lmp_clk_adj_ack clk_adj_ack ; + struct lmp_clk_adj_req clk_adj_req ; + struct lmp_qos qos ; + struct lmp_qos_req qos_req ; + struct lmp_scommon_link_req scommon_link_req ; + struct lmp_rmv_scommon_link_req rmv_scommon_link_req ; + struct lmp_max_slot max_slot ; + struct lmp_max_slot_req max_slot_req ; + struct lmp_timing_accu_req timing_accu_req ; + struct lmp_timing_accu_res timing_accu_res ; + struct lmp_setup_cmp setup_cmp ; + struct lmp_use_semi_perm_key use_semi_perm_key ; + struct lmp_host_con_req host_con_req ; + struct lmp_slot_off slot_off ; + struct lmp_page_mode_req page_mode_req ; + struct lmp_page_scan_mode_req page_scan_mode_req ; + struct lmp_supv_to supv_to ; + struct lmp_test_activate test_activate ; + struct lmp_test_ctrl test_ctrl ; + struct lmp_enc_key_size_mask_req enc_key_size_mask_req ; + struct lmp_enc_key_size_mask_res enc_key_size_mask_res ; + struct lmp_set_afh set_afh ; + struct lmp_encaps_hdr encaps_hdr ; + struct lmp_encaps_payl encaps_payl ; + struct lmp_sp_cfm sp_cfm ; + struct lmp_sp_nb sp_nb ; + struct lmp_dhkey_chk dhkey_chk ; + struct lmp_accepted_ext accepted_ext ; + struct lmp_not_accepted_ext not_accepted_ext ; + struct lmp_feats_req_ext feats_req_ext ; + struct lmp_feats_res_ext feats_res_ext ; + struct lmp_pkt_type_tbl_req pkt_type_tbl_req ; + struct lmp_escommon_link_req escommon_link_req ; + struct lmp_rmv_escommon_link_req rmv_escommon_link_req ; + struct lmp_ch_class_req ch_class_req ; + struct lmp_ch_class ch_class ; + struct lmp_ssr_req ssr_req ; + struct lmp_ssr_res ssr_res ; + struct lmp_pause_enc_req pause_enc_req ; + struct lmp_resume_enc_req resume_enc_req ; + struct lmp_io_cap_req io_cap_req ; + struct lmp_io_cap_res io_cap_res ; + struct lmp_num_comparison_fail num_comparison_fail ; + struct lmp_passkey_fail passkey_fail ; + struct lmp_oob_fail oob_fail ; + struct lmp_keypress_notif keypress_notif ; + struct lmp_pwr_ctrl_req pwr_ctrl_req ; + struct lmp_pwr_ctrl_res pwr_ctrl_res ; + struct lmp_ping_req ping_req ; + struct lmp_ping_res ping_res ; +}; + + +/// @} COMMON_BT +#endif // COMMON_LMP_H_ diff --git a/beken_os/beken378/driver/ble/ble_pub/modules/common/api/common_math.h b/beken_os/beken378/driver/ble/ble_pub/modules/common/api/common_math.h new file mode 100755 index 0000000..8e2753a --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/modules/common/api/common_math.h @@ -0,0 +1,206 @@ +/** + **************************************************************************************** + * + * @file common_math.h + * + * @brief Common optimized math functions + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef _COMMON_MATH_H_ +#define _COMMON_MATH_H_ + +/** + ***************************************************************************************** + * @defgroup COMMON_MATH Math functions + * @ingroup COMMON + * @brief Optimized math functions and other computations. + * + * @{ + ***************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include // standard integer definitions +#include // boolean definitions +#include // standard library +#include "ble_compiler.h" // for __INLINE + +extern void srand (unsigned int seed); +extern int rand (void); + +/* + * MACROS + **************************************************************************************** + */ +/** + **************************************************************************************** + * @brief Return value with one bit set. + * + * @param[in] pos Position of the bit to set. + * + * @return Value with one bit set. There is no return type since this is a macro and this + * will be resolved by the compiler upon assignment to an l-value. + **************************************************************************************** + */ +#define COMMON_BIT(pos) (1UL<<(pos)) + +/** + **************************************************************************************** + * @brief Align val on the multiple of 4 equal or nearest higher. + * @param[in] val Value to align. + * @return Value aligned. + **************************************************************************************** + */ +#define COMMON_ALIGN4_HI(val) (((val)+3)&~3) + + +/** + **************************************************************************************** + * @brief Align val on the multiple of 4 equal or nearest lower. + * @param[in] val Value to align. + * @return Value aligned. + **************************************************************************************** + */ +#define COMMON_ALIGN4_LO(val) ((val)&~3) + +/** + **************************************************************************************** + * @brief Align val on the multiple of 2 equal or nearest higher. + * @param[in] val Value to align. + * @return Value aligned. + **************************************************************************************** + */ +#define COMMON_ALIGN2_HI(val) (((val)+1)&~1) + + +/** + **************************************************************************************** + * @brief Align val on the multiple of 2 equal or nearest lower. + * @param[in] val Value to align. + * @return Value aligned. + **************************************************************************************** + */ +#define COMMON_ALIGN2_LO(val) ((val)&~1) + + +/* + * FUNCTION DEFINTIONS + **************************************************************************************** + */ +/** + **************************************************************************************** + * @brief Count leading zeros. + * @param[in] val Value to count the number of leading zeros on. + * @return Number of leading zeros when value is written as 32 bits. + **************************************************************************************** + */ +__INLINE uint32_t common_clz(uint32_t val) +{ + #if defined(__arm__) + return __builtin_clz(val); + #elif defined(__GNUC__) + if (val == 0) + { + return 32; + } + return __builtin_clz(val); + #else + uint32_t i; + for (i = 0; i < 32; i++) + { + if (val & COMMON_BIT(31 - i)) + break; + } + return i; + #endif // defined(__arm__) +} + +/** + **************************************************************************************** + * @brief Function to initialize the random seed. + * @param[in] seed The seed number to use to generate the random sequence. + **************************************************************************************** + */ +__INLINE void common_random_init(uint32_t seed) +{ + srand(seed); +} + +/** + **************************************************************************************** + * @brief Function to get an 8 bit random number. + * @return Random byte value. + **************************************************************************************** + */ +__INLINE uint8_t common_rand_byte(void) +{ + return (uint8_t)(rand() & 0xFF); +} + +/** + **************************************************************************************** + * @brief Function to get an 16 bit random number. + * @return Random half word value. + **************************************************************************************** + */ +__INLINE uint16_t common_rand_hword(void) +{ + return (uint16_t)(rand() & 0xFFFF); +} + +/** + **************************************************************************************** + * @brief Function to get an 32 bit random number. + * @return Random word value. + **************************************************************************************** + */ +__INLINE uint32_t common_rand_word(void) +{ + return (uint32_t)rand(); +} + +/** + **************************************************************************************** + * @brief Function to return the smallest of 2 unsigned 32 bits words. + * @return The smallest value. + **************************************************************************************** + */ +__INLINE uint32_t common_min(uint32_t a, uint32_t b) +{ + return a < b ? a : b; +} + +/** + **************************************************************************************** + * @brief Function to return the greatest of 2 unsigned 32 bits words. + * @return The greatest value. + **************************************************************************************** + */ +__INLINE uint32_t common_max(uint32_t a, uint32_t b) +{ + return a > b ? a : b; +} + +/** + **************************************************************************************** + * @brief Function to return the absolute value of a signed integer. + * @return The absolute value. + **************************************************************************************** + */ +__INLINE int common_abs(int val) +{ + return val < 0 ? val*(-1) : val; +} + +/// @} COMMON_MATH + + +#endif // _COMMON_MATH_H_ diff --git a/beken_os/beken378/driver/ble/ble_pub/modules/common/api/common_utils.h b/beken_os/beken378/driver/ble/ble_pub/modules/common/api/common_utils.h new file mode 100755 index 0000000..a398588 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/modules/common/api/common_utils.h @@ -0,0 +1,436 @@ +/** + **************************************************************************************** + * + * @file common_utils.h + * + * @brief Common utilities definitions + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ +#ifndef _COMMON_UTILS_H_ +#define _COMMON_UTILS_H_ + +/** + **************************************************************************************** + * @defgroup COMMON_UTILS Utilities + * @ingroup COMMON + * @brief Common utilities + * + * This module contains the common utilities functions and macros. + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include // standard definitions +#include // standard definitions + +#include "common_bt.h" // common bt definitions +#include "rwip_config.h" // SW configuration +#include "ble_compiler.h" // for inline functions + + +/* + * MACRO DEFINITIONS + **************************************************************************************** + */ + +/// Number of '1' bits in a byte +#define NB_ONE_BITS(byte) (one_bits[byte & 0x0F] + one_bits[byte >> 4]) + +/// Get the number of elements within an array, give also number of rows in a 2-D array +#define ARRAY_LEN(array) (sizeof((array))/sizeof((array)[0])) + +/// Get the number of columns within a 2-D array +#define ARRAY_NB_COLUMNS(array) (sizeof((array[0]))/sizeof((array)[0][0])) + + +/// Macro for LMP message handler function declaration or definition +#define LMP_MSG_HANDLER(msg_name) __STATIC int lmp_##msg_name##_handler(struct lmp_##msg_name const *param, \ + kernel_task_id_t const dest_id) + +/// Macro for HCI message handler function declaration or definition (for multi-instanciated tasks) +#define HCI_CMD_HANDLER_C(cmd_name, param_struct) __STATIC int hci_##cmd_name##_cmd_handler(param_struct const *param, \ + kernel_task_id_t const dest_id, \ + uint16_t opcode) + +/// Macro for HCI message handler function declaration or definition (with parameters) +#define HCI_CMD_HANDLER(cmd_name, param_struct) __STATIC int hci_##cmd_name##_cmd_handler(param_struct const *param, \ + uint16_t opcode) + +/// Macro for HCI message handler function declaration or definition (with parameters) +#define HCI_CMD_HANDLER_TAB(task) __STATIC const struct task##_hci_cmd_handler task##_hci_command_handler_tab[] = + + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + + +/* + * CONSTANT DECLARATIONS + **************************************************************************************** + */ + +/// Number of '1' bits in values from 0 to 15, used to fasten bit counting +extern const unsigned char one_bits[16]; + +/// Conversion table Sleep Clock Accuracy to PPM +extern const uint16_t common_sca2ppm[]; + +/// NULL BD address +extern const struct bd_addr common_null_bdaddr; + +/// NULL BD address +extern /*const */struct bd_addr common_default_bdaddr; + +/* + * MACROS + **************************************************************************************** + */ + +/// MACRO to build a subversion field from the Minor and Release fields +#define COMMON_SUBVERSION_BUILD(minor, release) (((minor) << 8) | (release)) + + +/// Macro to get a structure from one of its structure field +#define CONTAINER_OF(ptr, type, member) ((type *)( (char *)ptr - offsetof(type,member) )) + +/* + * OPERATIONS ON BT CLOCK + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Clocks addition with 2 operands + * + * @param[in] clock_a 1st operand value (in BT slots) + * @param[in] clock_b 2nd operand value (in BT slots) + * @return result operation result (in BT slots) + **************************************************************************************** + */ +#define CLK_ADD_2(clock_a, clock_b) ((uint32_t)(((clock_a) + (clock_b)) & MAX_SLOT_CLOCK)) + +/** + **************************************************************************************** + * @brief Clocks addition with 3 operands + * + * @param[in] clock_a 1st operand value (in BT slots) + * @param[in] clock_b 2nd operand value (in BT slots) + * @param[in] clock_c 3rd operand value (in BT slots) + * @return result operation result (in BT slots) + **************************************************************************************** + */ +#define CLK_ADD_3(clock_a, clock_b, clock_c) ((uint32_t)(((clock_a) + (clock_b) + (clock_c)) & MAX_SLOT_CLOCK)) + +/** + **************************************************************************************** + * @brief Clocks subtraction + * + * @param[in] clock_a 1st operand value (in BT slots) + * @param[in] clock_b 2nd operand value (in BT slots) + * @return result operation result (in BT slots) + **************************************************************************************** + */ +#define CLK_SUB(clock_a, clock_b) ((uint32_t)(((clock_a) - (clock_b)) & MAX_SLOT_CLOCK)) + +/** + **************************************************************************************** + * @brief Clocks time difference + * + * @param[in] clock_a 1st operand value (in BT slots) + * @param[in] clock_b 2nd operand value (in BT slots) + * @return result return the time difference from clock A to clock B + * - result < 0 => clock_b is in the past + * - result == 0 => clock_a is equal to clock_b + * - result > 0 => clock_b is in the future + **************************************************************************************** + */ +#define CLK_DIFF(clock_a, clock_b) ( (CLK_SUB((clock_b), (clock_a)) > ((MAX_SLOT_CLOCK+1) >> 1)) ? \ + ((int32_t)((-CLK_SUB((clock_a), (clock_b))))) : ((int32_t)((CLK_SUB((clock_b), (clock_a))))) ) + +/** + **************************************************************************************** + * @brief Check if an instant is passed + * + * @param[in] instant Instant reference (in BT slots) + * @param[in] clock Current timestamp (in BT slots) + * @return result True: clock is after or equal to the instant | False: clock is before the instant + **************************************************************************************** + */ +#define CLK_INSTANT_PASSED(instant, clock) ((uint32_t)(clock - instant) < (MAX_SLOT_CLOCK >> 1)) + +/// macro to extract a field from a value containing several fields +/// @param[in] __r bit field value +/// @param[in] __f field name +/// @return the value of the register masked and shifted +#define GETF(__r, __f) \ + (( (__r) & (__f##_MASK) ) >> (__f##_LSB)) + +/// macro to set a field value into a value containing several fields. +/// @param[in] __r bit field value +/// @param[in] __f field name +/// @param[in] __v value to put in field +#define SETF(__r, __f, __v) \ + do { \ + ASSERT_ERR( ( ( ( (__v) << (__f##_LSB) ) & ( ~(__f##_MASK) ) ) ) == 0 ); \ + __r = (((__r) & ~(__f##_MASK)) | (__v) << (__f##_LSB)); \ + } while (0) + + + +/// macro to extract a bit field from a value containing several fields +/// @param[in] __r bit field value +/// @param[in] __b bit field name +/// @return the value of the register masked and shifted +#define GETB(__r, __b) \ + (( (__r) & (__b##_BIT) ) >> (__b##_POS)) + +/// macro to set a bit field value into a value containing several fields. +/// @param[in] __r bit field value +/// @param[in] __b bit field name +/// @param[in] __v value to put in field +#define SETB(__r, __b, __v) \ + do { \ + ASSERT_ERR( ( ( ( (__v) << (__b##_POS) ) & ( ~(__b##_BIT) ) ) ) == 0 ); \ + __r = (((__r) & ~(__b##_BIT)) | (__v) << (__b##_POS)); \ + } while (0) + + + +/* + * FUNCTION DEFINITIONS + **************************************************************************************** + */ +/** + **************************************************************************************** + * @brief Read an aligned 32 bit word. + * @param[in] ptr32 The address of the first byte of the 32 bit word. + * @return The 32 bit value. + **************************************************************************************** + */ +__INLINE uint32_t common_read32(void const *ptr32) +{ + return *((uint32_t*)ptr32); +} + +/** + **************************************************************************************** + * @brief read a 8 bits word. + * @param[in] ptr8 The address of the first byte of the 8 bits word. + * @param[in] value The value to read. + **************************************************************************************** + */ +__INLINE uint8_t common_read8(void const *ptr8) +{ + return *((uint16_t*)ptr8); +} + +/** + **************************************************************************************** + * @brief Read an aligned 16 bits word. + * @param[in] ptr16 The address of the first byte of the 16 bits word. + * @return The 16 bits value. + **************************************************************************************** + */ +__INLINE uint16_t common_read16(void const *ptr16) +{ + return *((uint16_t*)ptr16); +} + +/** + **************************************************************************************** + * @brief Write an aligned 32 bits word. + * @param[in] ptr32 The address of the first byte of the 32 bits word. + * @param[in] value The value to write. + **************************************************************************************** + */ +__INLINE void common_write32(void const *ptr32, uint32_t value) +{ + *(uint32_t*)ptr32 = value; +} + +/** + **************************************************************************************** + * @brief Write an aligned 16 bits word. + * @param[in] ptr16 The address of the first byte of the 16 bits word. + * @param[in] value The value to write. + **************************************************************************************** + */ +__INLINE void common_write16(void const *ptr16, uint32_t value) +{ + *(uint16_t*)ptr16 = value; +} + +/** + **************************************************************************************** + * @brief Write a 8 bits word. + * @param[in] ptr8 The address of the first byte of the 8 bits word. + * @param[in] value The value to write. + **************************************************************************************** + */ +__INLINE void common_write8(void const *ptr8, uint32_t value) +{ + *(uint8_t*)ptr8 = value; +} + +/** + **************************************************************************************** + * @brief Read a packed 16 bits word. + * @param[in] ptr16 The address of the first byte of the 16 bits word. + * @return The 16 bits value. + **************************************************************************************** + */ +__INLINE uint16_t common_read16p(void const *ptr16) +{ + uint16_t value = ((uint8_t *)ptr16)[0] | ((uint8_t *)ptr16)[1] << 8; + return value; +} + +/** + **************************************************************************************** + * @brief Read a packed 24 bits word. + * @param[in] ptr24 The address of the first byte of the 24 bits word. + * @return The 24 bits value. + **************************************************************************************** + */ +__INLINE uint32_t common_read24p(void const *ptr24) +{ + uint16_t addr_l, addr_h; + addr_l = common_read16p((uint16_t *)ptr24); + addr_h = *((uint16_t *)ptr24 + 1) & 0x00FF; + return ((uint32_t)addr_l | (uint32_t)addr_h << 16); +} + +/** + **************************************************************************************** + * @brief Write a packed 24 bits word. + * @param[in] ptr24 The address of the first byte of the 24 bits word. + * @param[in] value The value to write. + **************************************************************************************** + */ +__INLINE void common_write24p(void const *ptr24, uint32_t value) +{ + uint8_t *ptr=(uint8_t*)ptr24; + + *ptr++ = (uint8_t)(value&0xff); + *ptr++ = (uint8_t)((value&0xff00)>>8); + *ptr++ = (uint8_t)((value&0xff0000)>>16); +} + +/** + **************************************************************************************** + * @brief Read a packed 32 bits word. + * @param[in] ptr32 The address of the first byte of the 32 bits word. + * @return The 32 bits value. + **************************************************************************************** + */ +__INLINE uint32_t common_read32p(void const *ptr32) +{ + uint16_t addr_l, addr_h; + addr_l = common_read16p((uint16_t *)ptr32); + addr_h = common_read16p((uint16_t *)ptr32 + 1); + return ((uint32_t)addr_l | (uint32_t)addr_h << 16); +} +/** + **************************************************************************************** + * @brief Write a packed 32 bits word. + * @param[in] ptr32 The address of the first byte of the 32 bits word. + * @param[in] value The value to write. + **************************************************************************************** + */ +__INLINE void common_write32p(void const *ptr32, uint32_t value) +{ + uint8_t *ptr=(uint8_t*)ptr32; + + *ptr++ = (uint8_t)(value&0xff); + *ptr++ = (uint8_t)((value&0xff00)>>8); + *ptr++ = (uint8_t)((value&0xff0000)>>16); + *ptr = (uint8_t)((value&0xff000000)>>24); +} + +/** + **************************************************************************************** + * @brief Write a packed 16 bits word. + * @param[in] ptr16 The address of the first byte of the 16 bits word. + * @param[in] value The value to write. + **************************************************************************************** + */ +__INLINE void common_write16p(void const *ptr16, uint16_t value) +{ + uint8_t *ptr=(uint8_t*)ptr16; + + *ptr++ = value&0xff; + *ptr = (value&0xff00)>>8; +} + + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +#if RW_DEBUG +/** + **************************************************************************************** + * @brief Convert bytes to hexadecimal string + * + * @param[out] dest Pointer to the destination string (must be 2x longer than input table) + * @param[in] src Pointer to the bytes table + * @param[in] nb_bytes Number of bytes to display in the string + **************************************************************************************** + */ +void common_bytes_to_string(char* dest, uint8_t* src, uint8_t nb_bytes); +#endif //RW_DEBUG + +/** + **************************************************************************************** + * @brief Compares two Bluetooth device addresses + * + * This function checks if the two bd address are equal. + * + * @param[in] bd_address1 Pointer on the first bd address to be compared. + * @param[in] bd_address2 Pointer on the second bd address to be compared. + * + * @return result of the comparison (true or false). + * + **************************************************************************************** + */ +bool common_bdaddr_compare(struct bd_addr const *bd_address1, + struct bd_addr const *bd_address2); + +#if (BT_EMB_PRESENT) + +/** + ****************************************************************************** + * @brief Convert an duration in baseband slot to a duration in number of ticks. + * @param[in] slot_cnt Duration in number of baseband slot + * @return Duration (in number of ticks). + ****************************************************************************** + */ +uint32_t common_slot_to_duration(uint16_t slot_cnt); + +/** + ****************************************************************************** + * @brief Count the number of good channels in a map + * @param[in] map Channel Map (bit fields for the 79 BT RF channels) + * @return Number of good channels + ****************************************************************************** + */ +uint8_t common_nb_good_channels(const struct chnl_map* map); + +#endif //BT_EMB_PRESENT + +/// @} COMMON_UTILS + +#endif // _COMMON_UTILS_H_ diff --git a/beken_os/beken378/driver/ble/ble_pub/modules/common/api/common_version.h b/beken_os/beken378/driver/ble/ble_pub/modules/common/api/common_version.h new file mode 100755 index 0000000..f59a84e --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/modules/common/api/common_version.h @@ -0,0 +1,51 @@ +/** + **************************************************************************************** + * + * @file common_version.h + * + * @brief Version definitions for BT4.2 + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef _COMMON_VERSION_H_ +#define _COMMON_VERSION_H_ +/** + **************************************************************************************** + * @defgroup COMMON_VERSION Version Defines + * @ingroup COMMON + * + * @brief Bluetooth Controller Version definitions. + * + * @{ + **************************************************************************************** + */ +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_config.h" // SW configuration options + +#if (BLE_QUALIF) +/// RWBT SW Major Version +#define RWBT_SW_VERSION_MAJOR (RW_BT40_VERSION) +#else +/// RWBT SW Major Version +#define RWBT_SW_VERSION_MAJOR (RW_BT42_VERSION) +#endif +/// RWBT SW Minor Version +#define RWBT_SW_VERSION_MINOR (4) +/// RWBT SW Build Version +#define RWBT_SW_VERSION_BUILD (11) + +/// RWBT SW Major Version +#define RWBT_SW_VERSION_SUB_BUILD (0) + + +/// @} COMMON_VERSION + + +#endif // _COMMON_VERSION_H_ diff --git a/beken_os/beken378/driver/ble/ble_pub/modules/common/src/RomCallFlash.c b/beken_os/beken378/driver/ble/ble_pub/modules/common/src/RomCallFlash.c new file mode 100755 index 0000000..8f4a523 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/modules/common/src/RomCallFlash.c @@ -0,0 +1,55 @@ +#include "common_bt.h" +#include "common_utils.h" +#include "RomCallFlash.h" + + + + +struct rom_env_tag rom_env; + + +void rom_env_init(struct rom_env_tag *api) +{ + memset(api,0,sizeof(struct rom_env_tag)); + api->prf_get_id_from_task = prf_get_id_from_task; + api->prf_get_task_from_id = prf_get_task_from_id; + api->prf_init = prf_init; + api->prf_create = prf_create; + api->prf_cleanup = prf_cleanup; + api->prf_add_profile = prf_add_profile; + api->rwble_hl_reset = rwble_hl_reset; + + api->rwip_reset = rwip_reset; + +// api->lld_sleep_init = lld_sleep_init; + +// api->rwip_prevent_sleep_set = rwip_prevent_sleep_set; +// api->rwip_prevent_sleep_clear = rwip_prevent_sleep_clear; + + api->platform_reset = platform_reset; +} +/* +extern int _sysboot_copy_data_to_ram(void); +extern int _sysboot_zi_init(void); +void RomRunC_init(void) +{ +#pragma arm + __asm + { + bl _sysboot_copy_data_to_ram + bl _sysboot_zi_init + }; + + +} +*/ +void lld_bdaddr_init(const struct bd_addr *addr) +{ + if(addr != NULL) + { + memcpy(&common_default_bdaddr, addr, sizeof(struct bd_addr)); + } + +} + + diff --git a/beken_os/beken378/driver/ble/ble_pub/modules/common/src/common_list.c b/beken_os/beken378/driver/ble/ble_pub/modules/common/src/common_list.c new file mode 100755 index 0000000..91d1447 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/modules/common/src/common_list.c @@ -0,0 +1,479 @@ +/** + **************************************************************************************** + * + * @file common_list.c + * + * @brief List management functions + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @addtogroup COMMON_LIST + * @{ + ***************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include // for mem* functions +#include "common_list.h" // common list definitions + +#include "kernel_mem.h" +#include "architect.h" // for assertions + +/* + * FUNCTION DEFINTIONS + **************************************************************************************** + */ +void common_list_init(struct common_list *list) +{ + list->first = NULL; + list->last = NULL; + + #if (KERNEL_PROFILING) + list->cnt = 0; + list->maxcnt = 0; + list->mincnt = 0xFFFFFFFF; + #endif //KERNEL_PROFILING +} + +void common_list_pool_init(struct common_list *list, + void *pool, + size_t elmt_size, + uint32_t elmt_cnt, + void *default_value, + uint8_t list_type) +{ + uint32_t i; + + // initialize the free list relative to the pool + common_list_init(list); + + // Add each element of the pool to this list, and init them one by one + for (i = 0; i < elmt_cnt; i++) + { + if (default_value) + { + memcpy(pool, default_value, elmt_size); + } + if((i == (elmt_cnt - 1)) && (list_type != POOL_LINKED_LIST)) + { + struct common_list_hdr *list_hdr =(struct common_list_hdr *) pool; + // Sanity check + ASSERT_ERR(list_hdr != NULL); + + // check if list is empty + if (common_list_is_empty(list)) + { + // list empty => pushed element is also head + list->first = list_hdr; + } + else + { + // list not empty => update next of last + list->last->next = list_hdr; + } + + // add element at the end of the list + list->last = list_hdr; + list_hdr->next = NULL; + + #if (KERNEL_PROFILING) + list->cnt++; + if(list->maxcnt < list->cnt) + { + list->maxcnt = list->cnt; + } + #endif //KERNEL_PROFILING + } + else + { + common_list_push_back(list, (struct common_list_hdr *) pool); + } + + // move to the next pool element + pool = (void *)((uint8_t *)pool + (uint32_t)elmt_size); + } +} + +void common_list_push_back(struct common_list *list, + struct common_list_hdr *list_hdr) +{ + // Sanity check + ASSERT_ERR(list_hdr != NULL); + + // check if list is empty + if (common_list_is_empty(list)) + { + // list empty => pushed element is also head + list->first = list_hdr; + } + else + { + // list not empty => update next of last + list->last->next = list_hdr; + } + + // add element at the end of the list + list->last = list_hdr; + list_hdr->next = NULL; + + #if (KERNEL_PROFILING) + list->cnt++; + if(list->maxcnt < list->cnt) + { + list->maxcnt = list->cnt; + } + #endif //KERNEL_PROFILING +} + +void common_list_push_front(struct common_list *list, + struct common_list_hdr *list_hdr) +{ + // Sanity check + ASSERT_ERR(list_hdr != NULL); + + // check if list is empty + if (common_list_is_empty(list)) + { + // list empty => pushed element is also head + list->last = list_hdr; + } + + // add element at the beginning of the list + list_hdr->next = list->first; + list->first = list_hdr; + + #if (KERNEL_PROFILING) + list->cnt++; + if(list->maxcnt < list->cnt) + { + list->maxcnt = list->cnt; + } + #endif //KERNEL_PROFILING +} + +struct common_list_hdr *common_list_pop_front(struct common_list *list) +{ + struct common_list_hdr *element; + + // check if list is empty + element = list->first; + if (element != NULL) + { + + // The list isn't empty : extract the first element + list->first = list->first->next; + + if(list->first == NULL) + { + list->last = list->first; + } + + #if (KERNEL_PROFILING) + list->cnt--; + if(list->mincnt > list->cnt) + { + list->mincnt = list->cnt; + } + #endif //KERNEL_PROFILING + } + return element; +} + +bool common_list_extract(struct common_list *list, struct common_list_hdr *list_hdr, uint8_t nb_following) +{ + bool found = false; + + // sanity check + ASSERT_ERR(list != NULL); + + struct common_list_hdr *prev = NULL; + struct common_list_hdr *curr = list->first; + + // Search for the element + while(curr != NULL) + { + // Check element + if(curr == list_hdr) + { + found = true; + break; + } + + // Move pointers + prev = curr; + ASSERT_INFO(list->first != curr->next, ((uint32_t)curr)>>16, ((uint32_t)curr)&0xFFFF); + ASSERT_INFO(curr != curr->next, ((uint32_t)curr)>>16, ((uint32_t)curr)&0xFFFF); + curr = curr->next; + } + + if(found) + { + struct common_list_hdr *last = curr; + int i = 0; + // Get the last element to extract + for(i = nb_following; i > 0; i--) + { + // Jump to next + last = last->next; + ASSERT_INFO(last != NULL, i, nb_following); + #if (KERNEL_PROFILING) + // Following element extracted + list->cnt--; + #endif //KERNEL_PROFILING + } + + // Check if the element is first + if(prev == NULL) + { + // Extract element + list->first = last->next; + } + else + { + // Extract element + prev->next = last->next; + } + + // Check if the element is last + if(last == list->last) + { + // Update last pointer + list->last = prev; + } + + #if (KERNEL_PROFILING) + // Reference element extracted + list->cnt--; + if(list->mincnt > list->cnt) + { + list->mincnt = list->cnt; + } + #endif //KERNEL_PROFILING + } + + return found; +} + +void common_list_extract_after(struct common_list *list, struct common_list_hdr *elt_ref_hdr, struct common_list_hdr *elt_to_rem_hdr) +{ + // sanity check + ASSERT_ERR(list != NULL); + ASSERT_ERR(elt_to_rem_hdr != NULL); + + // Check if the element is first + if(elt_ref_hdr == NULL) + { + ASSERT_ERR(elt_to_rem_hdr == list->first); + + // The list isn't empty : extract the first element + list->first = list->first->next; + } + else + { + ASSERT_ERR(elt_to_rem_hdr == elt_ref_hdr->next); + + // Extract element + elt_ref_hdr->next = elt_to_rem_hdr->next; + } + + // Check if the element is last + if(elt_to_rem_hdr == list->last) + { + // Update last pointer + list->last = elt_ref_hdr; + } + + #if (KERNEL_PROFILING) + // Reference element extracted + list->cnt--; + if(list->mincnt > list->cnt) + { + list->mincnt = list->cnt; + } + #endif //KERNEL_PROFILING +} + +bool common_list_find(struct common_list *list, + struct common_list_hdr *list_hdr) +{ + struct common_list_hdr *tmp_list_hdr; + + // Go through the list to find the element + tmp_list_hdr = list->first; + + while ((tmp_list_hdr != list_hdr) && (tmp_list_hdr != NULL)) + { + tmp_list_hdr = tmp_list_hdr->next; + } + + return (tmp_list_hdr == list_hdr); +} + +void common_list_merge(struct common_list *list1, + struct common_list *list2) +{ + // Sanity check: list2 is not supposed to be empty + ASSERT_ERR(!common_list_is_empty(list2)); + + // just copy list elements + if(common_list_is_empty(list1)) + { + list1->first = list2->first; + list1->last = list2->last; + } + // merge lists + else + { + // Append list2 to list1 + list1->last->next = list2->first; + list1->last = list2->last; + + } + + // Empty list2 + list2->first = NULL; + + #if (KERNEL_PROFILING) + list1->cnt += list2->cnt; + list2->cnt = 0; + #endif //KERNEL_PROFILING +} + +void common_list_insert_before(struct common_list *list, + struct common_list_hdr *elt_ref_hdr, struct common_list_hdr *elt_to_add_hdr) +{ + // Sanity check + ASSERT_ERR(elt_to_add_hdr != NULL); + // If no element referenced + if(elt_ref_hdr == NULL) + { + common_list_push_front(list,elt_to_add_hdr); + } + else + { + struct common_list_hdr *tmp_list_prev_hdr = NULL; + struct common_list_hdr *tmp_list_curr_hdr; + + // Go through the list to find the element + tmp_list_curr_hdr = list->first; + + while ((tmp_list_curr_hdr != elt_ref_hdr) && (tmp_list_curr_hdr != NULL)) + { + // Save previous element + tmp_list_prev_hdr = tmp_list_curr_hdr; + // Get the next element of the list + tmp_list_curr_hdr = tmp_list_curr_hdr->next; + } + // If only one element is available + if(tmp_list_prev_hdr == NULL) + { + common_list_push_front(list,elt_to_add_hdr); + } + else + { + tmp_list_prev_hdr->next = elt_to_add_hdr; + elt_to_add_hdr->next = tmp_list_curr_hdr; + #if (KERNEL_PROFILING) + list->cnt++; + if(list->maxcnt < list->cnt) + { + list->maxcnt = list->cnt; + } + #endif //KERNEL_PROFILING + } + } +} + +void common_list_insert_after(struct common_list *list, + struct common_list_hdr *elt_ref_hdr, struct common_list_hdr *elt_to_add_hdr) +{ + // Sanity check + ASSERT_ERR(elt_to_add_hdr != NULL); + // If no element referenced + if(elt_ref_hdr == NULL) + { + common_list_push_back(list,elt_to_add_hdr); + } + else + { + struct common_list_hdr *tmp_list_curr_hdr; + + // Go through the list to find the element + tmp_list_curr_hdr = list->first; + + while ((tmp_list_curr_hdr != elt_ref_hdr) && (tmp_list_curr_hdr != NULL)) + { + // Get the next element of the list + tmp_list_curr_hdr = tmp_list_curr_hdr->next; + } + // If only one element is available + if(tmp_list_curr_hdr == NULL) + { + common_list_push_back(list,elt_to_add_hdr); + } + else + { + // Check if the found element was the last of the list + if (!tmp_list_curr_hdr->next) + { + // Update last pointer + list->last = elt_to_add_hdr; + } + + elt_to_add_hdr->next = tmp_list_curr_hdr->next; + tmp_list_curr_hdr->next = elt_to_add_hdr; + + #if (KERNEL_PROFILING) + list->cnt++; + if(list->maxcnt < list->cnt) + { + list->maxcnt = list->cnt; + } + #endif //KERNEL_PROFILING + } + } +} + +uint16_t common_list_size(struct common_list *list) +{ + uint16_t count = 0; + struct common_list_hdr *tmp_list_hdr = list->first; + + // browse list to count number of elements + while (tmp_list_hdr != NULL) + { + tmp_list_hdr = tmp_list_hdr->next; + count++; + } + + return count; +} + +bool common_list_check_size_available(struct common_list *list, uint8_t free_size_needed) +{ + uint16_t count = 0; + struct common_list_hdr *tmp_list_hdr = list->first; + + // browse list to count number of elements + while (tmp_list_hdr != NULL) + { + tmp_list_hdr = tmp_list_hdr->next; + count++; + if(count == free_size_needed) + return true; + } + + return false; +} + +/// @} COMMON_LIST diff --git a/beken_os/beken378/driver/ble/ble_pub/modules/common/src/common_utils.c b/beken_os/beken378/driver/ble/ble_pub/modules/common/src/common_utils.c new file mode 100755 index 0000000..8511acb --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/modules/common/src/common_utils.c @@ -0,0 +1,149 @@ +/** +**************************************************************************************** +* +* @file common_utils.c +* +* @brief Common Utility functions +* +* Copyright (C) RivieraWaves 2009-2015 +* +* +**************************************************************************************** +*/ + +/** +**************************************************************************************** +* @addtogroup COMMON_UTILS +* @{ +**************************************************************************************** +*/ + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" // SW configuration + +#include // for mem* functions +#include "common_bt.h" // common bt definitions +#include "common_utils.h" // common utility definitions + + + +/* + * DEFINES + **************************************************************************************** + */ + +/// Minimum time to do a kernel timer action +#define COMMON_MIN_NB_SLOT_DUR 32 + +/* + * GLOBAL VARIABLES + **************************************************************************************** + */ + + +/* + * CONSTANT DEFINITIONS + **************************************************************************************** + */ + +/// Number of '1' bits in values from 0 to 15, used to fasten bit counting +const unsigned char one_bits[] = {0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4}; + +/// SCA to PPM +const uint16_t common_sca2ppm[] = +{ + [SCA_500PPM] = 500, + [SCA_250PPM] = 250, + [SCA_150PPM] = 150, + [SCA_100PPM] = 100, + [SCA_75PPM] = 75, + [SCA_50PPM] = 50, + [SCA_30PPM] = 30, + [SCA_20PPM] = 20 +}; + +/// NULL BD address +const struct bd_addr common_null_bdaddr = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; + + +/* + * LOCAL FUNCTION DEFINITIONS + **************************************************************************************** + */ + + +/* + * EXPORTED FUNCTION DEFINITIONS + **************************************************************************************** + */ + +#if RW_DEBUG +void common_bytes_to_string(char* dest, uint8_t* src, uint8_t nb_bytes) +{ + for(int i = 0 ; i < nb_bytes ; i++) + { + char digit; + uint8_t byte = *(src + nb_bytes - 1 - i); + + // MSbs + digit = (byte & 0xF0) >> 4; + digit += (digit < 10) ? 48:55; + *(dest+2*i) = (char)digit; + + // LSbs + digit = (byte & 0x0F) >> 0; + digit += (digit < 10) ? 48:55; + *(dest+2*i+1) = (char)digit; + } +} +#endif //RW_DEBUG + +bool common_bdaddr_compare(struct bd_addr const *bd_address1, + struct bd_addr const *bd_address2) +{ + uint8_t idx = 0; + for(idx=0; idx < BD_ADDR_LEN; idx++) + { + /// checks if the addresses are similar + if (bd_address1->addr[idx] != bd_address2->addr[idx]) + { + return (false); + } + } + return(true); +} + +#if (BT_EMB_PRESENT) +uint32_t common_slot_to_duration(uint16_t slot_cnt) +{ + uint32_t duration = 0; + /* Avoid Slot number < 32 */ + if (slot_cnt < COMMON_MIN_NB_SLOT_DUR) + { + slot_cnt = COMMON_MIN_NB_SLOT_DUR; + } + /* Duration contains a number of Slot and a tick is 10 ms */ + duration = slot_cnt >> 4; + return (duration); +} + +uint8_t common_nb_good_channels(const struct chnl_map* map) +{ + uint8_t nb_good_channels = 0; + + // Count number of good channels + for(int i = (CHNL_MAP_LEN-1) ; i >= 0 ; i--) + { + uint8_t byte = map->map[i]; + nb_good_channels += NB_ONE_BITS(byte); + } + + return nb_good_channels; +} +#endif //BT_EMB_PRESENT + +/// @} COMMON_UTILS diff --git a/beken_os/beken378/driver/ble/ble_pub/modules/dbg/api/dbg.h b/beken_os/beken378/driver/ble/ble_pub/modules/dbg/api/dbg.h new file mode 100755 index 0000000..60ce532 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/modules/dbg/api/dbg.h @@ -0,0 +1,64 @@ +/** +**************************************************************************************** +* +* @file dbg.h +* +* @brief Debug function +* +* Copyright (C) RivieraWaves 2009-2015 +* +* +**************************************************************************************** +*/ +#ifndef DBG_H_ +#define DBG_H_ + +/** +**************************************************************************************** +* @addtogroup DBG +* @ingroup CONTROLLER +* @brief Debug +* +* @{ +**************************************************************************************** +*/ + + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" // stack configuration + +#include "dbg_swdiag.h" // sw profiling definitions + + +/* + * FUNCTION DECLARATION + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Initialization of the BT Debug task + * + * This function initializes the the DBG task + * + **************************************************************************************** + */ +void dbg_init(void); + +/** + **************************************************************************************** + * @brief Send back to host status of platform reset request. + * + * @param status Reset error code + * + **************************************************************************************** + */ +void dbg_platform_reset_complete(uint32_t error); + +///@} DBG + +#endif // DBG_H_ diff --git a/beken_os/beken378/driver/ble/ble_pub/modules/dbg/api/dbg_mwsgen.h b/beken_os/beken378/driver/ble/ble_pub/modules/dbg/api/dbg_mwsgen.h new file mode 100755 index 0000000..f550451 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/modules/dbg/api/dbg_mwsgen.h @@ -0,0 +1,212 @@ +/** +**************************************************************************************** +* +* @file dbg_mwsgen.h +* +* @brief MWS/WLAN Generator API. +* +* Copyright (C) RivieraWaves 2015 +* +* +**************************************************************************************** +*/ + +#ifndef DBG_MWSGEN_H_ +#define DBG_MWSGEN_H_ + +/** + **************************************************************************************** + * @addtogroup DBGMWSGEN + * @ingroup DBG + * @brief Debug SW - MWS/WLAN Generator. + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_config.h" + +#if (RW_WLAN_COEX_TEST) || (RW_MWS_COEX_TEST) + +#include "reg_mwsgen.h" // MWS Event Generator register functions + +/* + * CONSTANT DEFINITIONS + **************************************************************************************** + */ + +#if (RW_WLAN_COEX) +/// WLAN coexistence disabled +#define DBG_COEX_WLAN_DISABLED 0 +/// WLAN coexistence enabled +#define DBG_COEX_WLAN_ENABLED 1 +#endif + +#if (RW_MWS_COEX) +/// MWS coexistence disabled +#define DBG_COEX_MWS_DISABLED 0 +/// MWS coexistence enabled +#define DBG_COEX_MWS_ENABLED 1 +#endif + +/* + * VARIABLE DECLARATION + **************************************************************************************** + */ +#if (RW_WLAN_COEX_TEST) +extern uint32_t dbg_coex_scenario; +#endif // RW_WLAN_COEX_TEST + +#if (RW_MWS_COEX_TEST) +extern uint32_t dbg_coex_scenario; +#endif // RW_MWS_COEX_TEST + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +#if (RW_MWS_COEX_TEST) +/** + **************************************************************************************** + * @brief Set the scenario for the unitary testing. + * + * @param[in] scenario Scenario type + * + * @return none + * + **************************************************************************************** + */ +uint8_t dbg_mwscoex_scen_set(uint32_t scenario); + +/** + **************************************************************************************** + * @brief Initialize and configure MWS event generator registers to be in MWS mode. + **************************************************************************************** + */ +void dbg_mwsgen_init(void); + +/** + **************************************************************************************** + * @brief Configure MWS generator + * + * @param[in] period Period of the mws signal (us) + * @param[in] duty_cycle Duration of the high level (us) + * @param[in] tx_act Duration of the tx activity (us) + * @param[in] rx_act Duration of the rx activity (us) + * + **************************************************************************************** + */ +void dbg_mwsgen_config(uint32_t period, uint32_t duty_cycle, uint32_t tx_act, uint32_t rx_act); + +/** + **************************************************************************************** + * @brief Configure the WLAN COEX mode for BT. + * + * @param[in] txmode + * @param[in] rxmode + * @param[in] txmsk + * @param[in] rxmsk + * @param[in] txfmsk + * @param[in] rxfmsk + * @param[in] scanfmsk + * @param[in] knudge + * + **************************************************************************************** + */ +void dbg_mws_config(uint8_t txmode, uint8_t rxmode, uint8_t txmsk, uint8_t rxmsk, uint8_t txfms, uint8_t rxfmsk, uint8_t scanfmsk, uint8_t knudge); + +/** + **************************************************************************************** + * @brief Start the MWS signal generator. + * + **************************************************************************************** + */ +void dbg_mwsgen_start(void); + +/** + **************************************************************************************** + * @brief Stop the MWS signal generator. + * + **************************************************************************************** + */ +void dbg_mwsgen_stop(void); +#endif // RW_MWS_COEX_TEST + +#if (RW_WLAN_COEX_TEST) +/** + **************************************************************************************** + * @brief Set the scenario for the unitary testing. + * + * @param[in] scenario Scenario type + * + * @return none + * + **************************************************************************************** + */ + +uint8_t dbg_wlcoex_scen_set(uint32_t scenario); + +/** + **************************************************************************************** + * @brief Initialize and configure MWS event generator registers to be in WLAN mode. + **************************************************************************************** + */ +void dbg_wlangen_init(void); + +/** + **************************************************************************************** + * @brief Set the period and duty cycle for the wlrxbsy signal. + * + * @param[in] period Period of the wlrxbsy signal (us) + * @param[in] duty_cycle Duration of the high level (us) + * @param[in] tx_act Duration of the tx activity (us) + * @param[in] rx_act Duration of the rx activity (us) + * + **************************************************************************************** + */ +void dbg_wlangen_config(uint32_t period, uint32_t duty_cycle, uint32_t tx_act, uint32_t rx_act); + +/** + **************************************************************************************** + * @brief Configure the WLAN COEX mode for BT. + * + * @param[in] txmode + * @param[in] rxmode + * @param[in] txmsk + * @param[in] rxmsk + * @param[in] txthr + * @param[in] rxthr + * @param[in] pduration + * @param[in] pdelay + * + **************************************************************************************** + */ +void dbg_wlan_config(uint8_t txmode, uint8_t rxmode, uint8_t txmsk, uint8_t rxmsk, uint8_t txthr, uint8_t rxthr, uint8_t pduration, uint8_t pdelay); + +/** + **************************************************************************************** + * @brief Start the wlrxbs signal generator. + * + **************************************************************************************** + */ +void dbg_wlangen_start(void); + +/** + **************************************************************************************** + * @brief Stop the wlrxbs signal generator. + * + **************************************************************************************** + */ +void dbg_wlangen_stop(void); +#endif // RW_WLAN_COEX_TEST + +#endif // (RW_WLAN_COEX_TEST) || (RW_MWS_COEX_TEST) + +/// @} DBGMWSGEN + +#endif // DBG_MWSGEN_H_ diff --git a/beken_os/beken378/driver/ble/ble_pub/modules/dbg/api/dbg_swdiag.h b/beken_os/beken378/driver/ble/ble_pub/modules/dbg/api/dbg_swdiag.h new file mode 100755 index 0000000..f13d438 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/modules/dbg/api/dbg_swdiag.h @@ -0,0 +1,809 @@ +/** +**************************************************************************************** +* +* @file dbg_swdiag.h +* +* @brief SW profiling module +* +* Copyright (C) RivieraWaves 2009-2015 +* +* +**************************************************************************************** +*/ + +#ifndef DBG_SWDIAG_H_ +#define DBG_SWDIAG_H_ + +/** + **************************************************************************************** + * @addtogroup DBGSWDIAG Diag + * @ingroup DBG + * @brief Debug SW profiling module + * + * SW profiling is a debug feature that provides user a configurable way to analyze SW execution performance or + * behavior, such as timings, state machines, bit field values and so on. + * It manages the SW state representation over HW digital diagnostic signals (diagports), from the signals selection to + * the toggling of real HW signals. + * HW signals representing the SW execution could then be watched on a logic analyzer in parallel with HW internal + * signals, that could be very useful for low level debugging. + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_config.h" // stack configuration + +#if (!RW_SWDIAG) + +/// Macro used to set a SW diag to specific value +#define DBG_SWDIAG(bank , field , value) + +#else //RW_SWDIAG + +#if (BT_EMB_PRESENT) +#include "reg_btcore.h" // bt core registers +#elif (BLE_EMB_PRESENT) +#include "reg_blecore.h" // ble core registers +#endif //BT_EMB_PRESENT / BLE_EMB_PRESENT + + +/* + * DEFINES + **************************************************************************************** + */ + +/// Number of HW diagport banks +#define DBG_SWDIAG_NB_HW_BANKS 4 + +/// Undefined configuration +#define DBG_SWDIAG_UNDEFINED 0xFF + + +/* + * MACROS + **************************************************************************************** + */ +#if (BT_EMB_PRESENT) +#define SW_DIAG_SET bt_swprofiling_set +#define SW_DIAG_GET bt_swprofiling_get +#elif (BLE_EMB_PRESENT) +#define SW_DIAG_SET ble_swprofiling_set +#define SW_DIAG_GET ble_swprofiling_get +#endif //BT_EMB_PRESENT / BLE_EMB_PRESENT + +/// Macro used to set a SW diag to specific value +#define DBG_SWDIAG(bank , field , value) \ + if(sw_to_hw[DBG_SWDIAG_##bank] != DBG_SWDIAG_UNDEFINED) \ + { \ + SW_DIAG_SET( ((SW_DIAG_GET()) & (~(DBG_SWDIAG_##bank##_##field##_MASK << (8 * sw_to_hw[DBG_SWDIAG_##bank])))) | ((((value << DBG_SWDIAG_##bank##_##field##_OFFSET) & DBG_SWDIAG_##bank##_##field##_MASK) << (8*sw_to_hw[DBG_SWDIAG_##bank]))) ); \ + } + + +/* + * SW DIAGS MAP + **************************************************************************************** + */ + +enum dbg_swdiag +{ +/** +****************************************************************************************** +* @brief BANK 0 : BT_ISR +****************************************************************************************** +*/ + DBG_SWDIAG_BT_ISR = 0, + + DBG_SWDIAG_BT_ISR_CLK_OFFSET = 0, + DBG_SWDIAG_BT_ISR_CLK_MASK = 0x01, + + DBG_SWDIAG_BT_ISR_RX_OFFSET = 1, + DBG_SWDIAG_BT_ISR_RX_MASK = 0x02, + + DBG_SWDIAG_BT_ISR_SLP_OFFSET = 2, + DBG_SWDIAG_BT_ISR_SLP_MASK = 0x04, + + DBG_SWDIAG_BT_ISR_GROSSTGT_OFFSET = 3, + DBG_SWDIAG_BT_ISR_GROSSTGT_MASK = 0x08, + + DBG_SWDIAG_BT_ISR_FRAME_OFFSET = 4, + DBG_SWDIAG_BT_ISR_FRAME_MASK = 0x10, + + DBG_SWDIAG_BT_ISR_FINETGT_OFFSET = 5, + DBG_SWDIAG_BT_ISR_FINETGT_MASK = 0x20, + + DBG_SWDIAG_BT_ISR_SKET_OFFSET = 6, + DBG_SWDIAG_BT_ISR_SKET_MASK = 0x40, + + DBG_SWDIAG_BT_ISR_SW_OFFSET = 7, + DBG_SWDIAG_BT_ISR_SW_MASK = 0x80, + + +/** +****************************************************************************************** +* @brief BANK 1 : SLEEP +****************************************************************************************** +*/ + DBG_SWDIAG_SLEEP = 1, + + DBG_SWDIAG_SLEEP_SLEEP_OFFSET = 0, + DBG_SWDIAG_SLEEP_SLEEP_MASK = 0x01, + + DBG_SWDIAG_SLEEP_ALGO_OFFSET = 1, + DBG_SWDIAG_SLEEP_ALGO_MASK = 0x0E, + + DBG_SWDIAG_SLEEP_PREVENT_OFFSET = 4, + DBG_SWDIAG_SLEEP_PREVENT_MASK = 0xF0, + + +/** +****************************************************************************************** +* @brief BANK 2 : ISR +****************************************************************************************** +*/ + DBG_SWDIAG_ISR = 2, + + DBG_SWDIAG_ISR_UART_OFFSET = 0, + DBG_SWDIAG_ISR_UART_MASK = 0x01, + + DBG_SWDIAG_ISR_BT_OFFSET = 1, + DBG_SWDIAG_ISR_BT_MASK = 0x02, + + DBG_SWDIAG_ISR_PS2_OFFSET = 1, + DBG_SWDIAG_ISR_PS2_MASK = 0x02, + + DBG_SWDIAG_ISR_BLE_OFFSET = 2, + DBG_SWDIAG_ISR_BLE_MASK = 0x04, + + DBG_SWDIAG_ISR_RESERVED_OFFSET = 3, + DBG_SWDIAG_ISR_RESERVED_MASK = 0x08, + + DBG_SWDIAG_ISR_GPIO_OFFSET = 4, + DBG_SWDIAG_ISR_GPIO_MASK = 0x10, + + DBG_SWDIAG_ISR_RTC0_OFFSET = 5, + DBG_SWDIAG_ISR_RTC0_MASK = 0x20, + + DBG_SWDIAG_ISR_SPI_OFFSET = 6, + DBG_SWDIAG_ISR_SPI_MASK = 0x40, + + DBG_SWDIAG_ISR_WFI_OFFSET = 7, + DBG_SWDIAG_ISR_WFI_MASK = 0x80, + + +/** +****************************************************************************************** +* @brief BANK 3 : BLEISR +****************************************************************************************** +*/ + DBG_SWDIAG_BLE_ISR = 3, + + DBG_SWDIAG_BLE_ISR_CSCNTINT_OFFSET = 0, + DBG_SWDIAG_BLE_ISR_CSCNTINT_MASK = 0x01, + + DBG_SWDIAG_BLE_ISR_RXINT_OFFSET = 1, + DBG_SWDIAG_BLE_ISR_RXINT_MASK = 0x02, + + DBG_SWDIAG_BLE_ISR_SLPINT_OFFSET = 2, + DBG_SWDIAG_BLE_ISR_SLPINT_MASK = 0x04, + + DBG_SWDIAG_BLE_ISR_EVENTINT_OFFSET = 3, + DBG_SWDIAG_BLE_ISR_EVENTINT_MASK = 0x08, + + DBG_SWDIAG_BLE_ISR_CRYPTINT_OFFSET = 4, + DBG_SWDIAG_BLE_ISR_CRYPTINT_MASK = 0x10, + + DBG_SWDIAG_BLE_ISR_ERRORINT_OFFSET = 5, + DBG_SWDIAG_BLE_ISR_ERRORINT_MASK = 0x20, + + DBG_SWDIAG_BLE_ISR_GROSSTGTIMINT_OFFSET = 6, + DBG_SWDIAG_BLE_ISR_GROSSTGTIMINT_MASK = 0x40, + + DBG_SWDIAG_BLE_ISR_FINETGTIMINT_OFFSET = 7, + DBG_SWDIAG_BLE_ISR_FINETGTIMINT_MASK = 0x80, + + +/** +****************************************************************************************** +* @brief BANK 4 : FLASH +****************************************************************************************** +*/ + DBG_SWDIAG_FLASH = 4, + + DBG_SWDIAG_FLASH_STATE_OFFSET = 0, + DBG_SWDIAG_FLASH_STATE_MASK = 0x07, + + DBG_SWDIAG_FLASH_SUBSTATE_OFFSET = 3, + DBG_SWDIAG_FLASH_SUBSTATE_MASK = 0x38, + + DBG_SWDIAG_FLASH_MANAGE_OFFSET = 6, + DBG_SWDIAG_FLASH_MANAGE_MASK = 0x40, + + DBG_SWDIAG_FLASH_CALLBACK_OFFSET = 7, + DBG_SWDIAG_FLASH_CALLBACK_MASK = 0x80, + +/** +****************************************************************************************** +* @brief BANK 5 : Reserved +****************************************************************************************** +*/ + + + +/** +****************************************************************************************** +* @brief BANK 6 : Event execution overview. +****************************************************************************************** +*/ + DBG_SWDIAG_EVT = 6, + + DBG_SWDIAG_EVT_BLE_SCHEDULE_OFFSET = 0, + DBG_SWDIAG_EVT_BLE_SCHEDULE_MASK = 0x01, + + DBG_SWDIAG_EVT_BLE_RX_OFFSET = 1, + DBG_SWDIAG_EVT_BLE_RX_MASK = 0x02, + + DBG_SWDIAG_EVT_BLE_END_OFFSET = 2, + DBG_SWDIAG_EVT_BLE_END_MASK = 0x04, + + DBG_SWDIAG_EVT_BLE_RESTART_OFFSET = 3, + DBG_SWDIAG_EVT_BLE_RESTART_MASK = 0x08, + + DBG_SWDIAG_EVT_BLE_PROG_OFFSET = 4, + DBG_SWDIAG_EVT_BLE_PROG_MASK = 0x10, + + DBG_SWDIAG_EVT_BLE_CRYPT_OFFSET = 5, + DBG_SWDIAG_EVT_BLE_CRYPT_MASK = 0x20, + + DBG_SWDIAG_EVT_TIMER_OFFSET = 6, + DBG_SWDIAG_EVT_TIMER_MASK = 0x40, + + DBG_SWDIAG_EVT_MESSAGE_OFFSET = 7, + DBG_SWDIAG_EVT_MESSAGE_MASK = 0x80, + + +/** +****************************************************************************************** +* @brief BANK 8 : AFH +****************************************************************************************** +*/ + DBG_SWDIAG_AFH = 8, + + DBG_SWDIAG_AFH_TO_OFFSET = 0, + DBG_SWDIAG_AFH_TO_MASK = 0x01, + + DBG_SWDIAG_AFH_LMP_TX_OFFSET = 1, + DBG_SWDIAG_AFH_LMP_TX_MASK = 0x02, + + DBG_SWDIAG_AFH_CLASS_RX_OFFSET = 2, + DBG_SWDIAG_AFH_CLASS_RX_MASK = 0x04, + + DBG_SWDIAG_AFH_HOST_OFFSET = 3, + DBG_SWDIAG_AFH_HOST_MASK = 0x08, + + DBG_SWDIAG_AFH_REPORT_TO_OFFSET = 4, + DBG_SWDIAG_AFH_REPORT_TO_MASK = 0x10, + + DBG_SWDIAG_AFH_HSSI_OFFSET = 5, + DBG_SWDIAG_AFH_HSSI_MASK = 0x20, + + DBG_SWDIAG_AFH_CFM_OFFSET = 6, + DBG_SWDIAG_AFH_CFM_MASK = 0x40, + + DBG_SWDIAG_AFH_LMP_RX_OFFSET = 7, + DBG_SWDIAG_AFH_LMP_RX_MASK = 0x80, + + +/** +****************************************************************************************** +* @brief BANK 9 : SWITCH +****************************************************************************************** +*/ + DBG_SWDIAG_SWITCH = 9, + + DBG_SWDIAG_SWITCH_LOOP_OFFSET = 0, + DBG_SWDIAG_SWITCH_LOOP_MASK = 0x01, + + DBG_SWDIAG_SWITCH_SM_OFFSET = 1, + DBG_SWDIAG_SWITCH_SM_MASK = 0x06, + + DBG_SWDIAG_SWITCH_RSW_FAIL_OFFSET = 3, + DBG_SWDIAG_SWITCH_RSW_FAIL_MASK = 0x08, + + +/** +****************************************************************************************** +* @brief BANK 11 : VALUE8 +****************************************************************************************** +*/ + DBG_SWDIAG_VALUE8 = 11, + + DBG_SWDIAG_VALUE8_VALUE_OFFSET = 0, + DBG_SWDIAG_VALUE8_VALUE_MASK = 0xFF, + +/** +****************************************************************************************** +* @brief BANK 12 : VALUE16 +****************************************************************************************** +*/ + DBG_SWDIAG_VALUE16 = 12, + + DBG_SWDIAG_VALUE16_VALUE_OFFSET = 0, + DBG_SWDIAG_VALUE16_VALUE_MASK = 0xFF, + + +/** +****************************************************************************************** +* @brief BANK 13 : SNIFF +****************************************************************************************** +*/ + DBG_SWDIAG_SNIFF = 13, + + DBG_SWDIAG_SNIFF_EVT_START_OFFSET = 0, + DBG_SWDIAG_SNIFF_EVT_START_MASK = 0x01, + + DBG_SWDIAG_SNIFF_EVT_CANCELED_OFFSET = 1, + DBG_SWDIAG_SNIFF_EVT_CANCELED_MASK = 0x02, + + DBG_SWDIAG_SNIFF_FRM_ISR_OFFSET = 2, + DBG_SWDIAG_SNIFF_FRM_ISR_MASK = 0x04, + + DBG_SWDIAG_SNIFF_RX_ISR_OFFSET = 3, + DBG_SWDIAG_SNIFF_RX_ISR_MASK = 0x08, + + DBG_SWDIAG_SNIFF_SCHED_OFFSET = 4, + DBG_SWDIAG_SNIFF_SCHED_MASK = 0x10, + + +/** +****************************************************************************************** +* @brief BANK 14 : SCO +****************************************************************************************** +*/ + DBG_SWDIAG_SCO = 14, + + DBG_SWDIAG_SCOMMON_EVT_START_OFFSET = 0, + DBG_SWDIAG_SCOMMON_EVT_START_MASK = 0x01, + + DBG_SWDIAG_SCOMMON_EVT_STOP_OFFSET = 1, + DBG_SWDIAG_SCOMMON_EVT_STOP_MASK = 0x02, + + DBG_SWDIAG_SCOMMON_EVT_CANCELED_OFFSET = 2, + DBG_SWDIAG_SCOMMON_EVT_CANCELED_MASK = 0x04, + + DBG_SWDIAG_SCOMMON_FRM_ISR_OFFSET = 3, + DBG_SWDIAG_SCOMMON_FRM_ISR_MASK = 0x08, + + DBG_SWDIAG_SCOMMON_RESCHED_OFFSET = 4, + DBG_SWDIAG_SCOMMON_RESCHED_MASK = 0x10, + + DBG_SWDIAG_SCOMMON_UPDATE_OFFSET = 5, + DBG_SWDIAG_SCOMMON_UPDATE_MASK = 0x60, + + DBG_SWDIAG_SCOMMON_AUDIO_ISR_OFFSET = 7, + DBG_SWDIAG_SCOMMON_AUDIO_ISR_MASK = 0x80, + + +/** +****************************************************************************************** +* @brief BANK 15 : CHNL_ASSESS (NB_CHNL) +****************************************************************************************** +*/ + DBG_SWDIAG_CHNL_ASSESS = 15, + + DBG_SWDIAG_CHNL_ASSESS_NB_CHNL_OFFSET = 0, + DBG_SWDIAG_CHNL_ASSESS_NB_CHNL_MASK = 0x3F, + + DBG_SWDIAG_CHNL_ASSESS_REM_CHNL_OFFSET = 6, + DBG_SWDIAG_CHNL_ASSESS_REM_CHNL_MASK = 0x40, + + DBG_SWDIAG_CHNL_ASSESS_ADD_CHNL_OFFSET = 7, + DBG_SWDIAG_CHNL_ASSESS_ADD_CHNL_MASK = 0x80, + +/** +****************************************************************************************** +* @brief BANK 16 : ASSESS_MECH +****************************************************************************************** +*/ + DBG_SWDIAG_ASSESS_MECH = 16, + + DBG_SWDIAG_ASSESS_MECH_ATIMER_OFFSET = 0, + DBG_SWDIAG_ASSESS_MECH_ATIMER_MASK = 0x01, + + DBG_SWDIAG_ASSESS_MECH_RTIMER_OFFSET = 1, + DBG_SWDIAG_ASSESS_MECH_RTIMER_MASK = 0x02, + + DBG_SWDIAG_ASSESS_MECH_BAD_PKT_OFFSET = 2, + DBG_SWDIAG_ASSESS_MECH_BAD_PKT_MASK = 0x04, + + DBG_SWDIAG_ASSESS_MECH_SYNC_ERR_OFFSET = 3, + DBG_SWDIAG_ASSESS_MECH_SYNC_ERR_MASK = 0x08, + +/** +****************************************************************************************** +* @brief BANK 17 : PAGE +****************************************************************************************** +*/ + DBG_SWDIAG_PAGE = 17, + + DBG_SWDIAG_PAGE_PSCAN_EVT_START_OFFSET = 0, + DBG_SWDIAG_PAGE_PSCAN_EVT_START_MASK = 0x01, + + DBG_SWDIAG_PAGE_PSCAN_EVT_CANCELED_OFFSET = 1, + DBG_SWDIAG_PAGE_PSCAN_EVT_CANCELED_MASK = 0x02, + + DBG_SWDIAG_PAGE_PSCAN_FRM_ISR_OFFSET = 2, + DBG_SWDIAG_PAGE_PSCAN_FRM_ISR_MASK = 0x04, + + DBG_SWDIAG_PAGE_PSCAN_KERNEL_EVT_OFFSET = 3, + DBG_SWDIAG_PAGE_PSCAN_KERNEL_EVT_MASK = 0x08, + + DBG_SWDIAG_PAGE_PAGE_EVT_START_OFFSET = 4, + DBG_SWDIAG_PAGE_PAGE_EVT_START_MASK = 0x10, + + DBG_SWDIAG_PAGE_PAGE_EVT_CANCELED_OFFSET = 5, + DBG_SWDIAG_PAGE_PAGE_EVT_CANCELED_MASK = 0x20, + + DBG_SWDIAG_PAGE_PAGE_FRM_ISR_OFFSET = 6, + DBG_SWDIAG_PAGE_PAGE_FRM_ISR_MASK = 0x40, + + DBG_SWDIAG_PAGE_PAGE_STEP_OFFSET = 7, + DBG_SWDIAG_PAGE_PAGE_STEP_MASK = 0x80, + +/** +****************************************************************************************** +* @brief BANK 18 : INQ +****************************************************************************************** +*/ + DBG_SWDIAG_INQ = 18, + + DBG_SWDIAG_INQ_ISCAN_EVT_START_OFFSET = 0, + DBG_SWDIAG_INQ_ISCAN_EVT_START_MASK = 0x01, + + DBG_SWDIAG_INQ_ISCAN_EVT_CANCELED_OFFSET = 1, + DBG_SWDIAG_INQ_ISCAN_EVT_CANCELED_MASK = 0x02, + + DBG_SWDIAG_INQ_ISCAN_FRM_ISR_OFFSET = 2, + DBG_SWDIAG_INQ_ISCAN_FRM_ISR_MASK = 0x04, + + DBG_SWDIAG_INQ_INQ_EVT_START_OFFSET = 3, + DBG_SWDIAG_INQ_INQ_EVT_START_MASK = 0x08, + + DBG_SWDIAG_INQ_INQ_EVT_CANCELED_OFFSET = 4, + DBG_SWDIAG_INQ_INQ_EVT_CANCELED_MASK = 0x10, + + DBG_SWDIAG_INQ_INQ_FRM_ISR_OFFSET = 5, + DBG_SWDIAG_INQ_INQ_FRM_ISR_MASK = 0x20, + +/** +****************************************************************************************** +* @brief BANK 19 : ACL +****************************************************************************************** +*/ + DBG_SWDIAG_ACL = 19, + + DBG_SWDIAG_ACL_EVT_START_OFFSET = 0, + DBG_SWDIAG_ACL_EVT_START_MASK = 0x01, + + DBG_SWDIAG_ACL_EVT_STOP_OFFSET = 1, + DBG_SWDIAG_ACL_EVT_STOP_MASK = 0x02, + + DBG_SWDIAG_ACL_EVT_CANCELED_OFFSET = 2, + DBG_SWDIAG_ACL_EVT_CANCELED_MASK = 0x04, + + DBG_SWDIAG_ACL_FRM_ISR_OFFSET = 3, + DBG_SWDIAG_ACL_FRM_ISR_MASK = 0x08, + + DBG_SWDIAG_ACL_CLK_ISR_OFFSET = 4, + DBG_SWDIAG_ACL_CLK_ISR_MASK = 0x10, + + DBG_SWDIAG_ACL_PROG_EN_OFFSET = 5, + DBG_SWDIAG_ACL_PROG_EN_MASK = 0x20, + + DBG_SWDIAG_ACL_SKET_ISR_OFFSET = 6, + DBG_SWDIAG_ACL_SKET_ISR_MASK = 0x40, + + DBG_SWDIAG_ACL_PARITY_OFFSET = 7, + DBG_SWDIAG_ACL_PARITY_MASK = 0x80, + +/** +****************************************************************************************** +* @brief BANK 20 : RSW +****************************************************************************************** +*/ + DBG_SWDIAG_RSW = 20, + + DBG_SWDIAG_RSW_EVT_START_OFFSET = 0, + DBG_SWDIAG_RSW_EVT_START_MASK = 0x01, + + DBG_SWDIAG_RSW_EVT_CANCELED_OFFSET = 1, + DBG_SWDIAG_RSW_EVT_CANCELED_MASK = 0x02, + + DBG_SWDIAG_RSW_FRM_ISR_OFFSET = 2, + DBG_SWDIAG_RSW_FRM_ISR_MASK = 0x04, + + DBG_SWDIAG_RSW_STEP_OFFSET = 3, + DBG_SWDIAG_RSW_STEP_MASK = 0x08, + + DBG_SWDIAG_RSW_TX_SLOTOFF_OFFSET = 4, + DBG_SWDIAG_RSW_TX_SLOTOFF_MASK = 0x10, + + DBG_SWDIAG_RSW_TX_PARITY_OFFSET = 5, + DBG_SWDIAG_RSW_TX_PARITY_MASK = 0x20, + + DBG_SWDIAG_RSW_TDD_PARITY_OFFSET = 6, + DBG_SWDIAG_RSW_TDD_PARITY_MASK = 0x40, + +/** +****************************************************************************************** +* @brief BANK 21 : TX +****************************************************************************************** +*/ + DBG_SWDIAG_TX = 21, + + DBG_SWDIAG_TX_LMP_TX_OFFSET = 0, + DBG_SWDIAG_TX_LMP_TX_MASK = 0x01, + + DBG_SWDIAG_TX_ACL_TX_OFFSET = 1, + DBG_SWDIAG_TX_ACL_TX_MASK = 0x02, + + DBG_SWDIAG_TX_SW_IDX_OFFSET = 2, + DBG_SWDIAG_TX_SW_IDX_MASK = 0x04, + + DBG_SWDIAG_TX_HW_IDX_OFFSET = 3, + DBG_SWDIAG_TX_HW_IDX_MASK = 0x08, + + DBG_SWDIAG_TX_TX_CNT_OFFSET = 4, + DBG_SWDIAG_TX_TX_CNT_MASK = 0x30, + +/** +****************************************************************************************** +* @brief BANK 22 : DATA +****************************************************************************************** +*/ + DBG_SWDIAG_DATA = 22, + + DBG_SWDIAG_DATA_LMP_TX_OFFSET = 0, + DBG_SWDIAG_DATA_LMP_TX_MASK = 0x01, + + DBG_SWDIAG_DATA_ACL_TX_OFFSET = 1, + DBG_SWDIAG_DATA_ACL_TX_MASK = 0x02, + + DBG_SWDIAG_DATA_LMP_RX_OFFSET = 2, + DBG_SWDIAG_DATA_LMP_RX_MASK = 0x04, + + DBG_SWDIAG_DATA_ACL_RX_OFFSET = 3, + DBG_SWDIAG_DATA_ACL_RX_MASK = 0x08, + + DBG_SWDIAG_DATA_LMP_ACK_OFFSET = 4, + DBG_SWDIAG_DATA_LMP_ACK_MASK = 0x10, + + DBG_SWDIAG_DATA_ACL_ACK_OFFSET = 5, + DBG_SWDIAG_DATA_ACL_ACK_MASK = 0x20, + + /** + ****************************************************************************************** + * @brief BANK 23 : ECDH + ****************************************************************************************** + */ + DBG_SWDIAG_ECDH = 23, + + DBG_SWDIAG_ECDH_BUSY_OFFSET = 0, + DBG_SWDIAG_ECDH_BUSY_MASK = 0x01, + + DBG_SWDIAG_ECDH_COMPUTE_OFFSET = 1, + DBG_SWDIAG_ECDH_COMPUTE_MASK = 0x02, + + DBG_SWDIAG_ECDH_MULT_OFFSET = 2, + DBG_SWDIAG_ECDH_MULT_MASK = 0x04, + + DBG_SWDIAG_ECDH_END_OFFSET = 3, + DBG_SWDIAG_ECDH_END_MASK = 0x08, + + DBG_SWDIAG_ECDH_INV_OFFSET = 4, + DBG_SWDIAG_ECDH_INV_MASK = 0x10, + + /** + ****************************************************************************************** + * @brief BANK 24 : PCA + ****************************************************************************************** + */ + DBG_SWDIAG_PCA = 24, + + DBG_SWDIAG_PCA_FRAME_SYNC_INT_OFFSET = 0, + DBG_SWDIAG_PCA_FRAME_SYNC_INT_MASK = 0x01, + + DBG_SWDIAG_PCA_MTOFF_LT_INT_OFFSET = 1, + DBG_SWDIAG_PCA_MTOFF_LT_INT_MASK = 0x02, + + DBG_SWDIAG_PCA_SLOT_INT_OFFSET = 2, + DBG_SWDIAG_PCA_SLOT_INT_MASK = 0x04, + + DBG_SWDIAG_PCA_COARSE_CLK_ADJ_OFFSET = 3, + DBG_SWDIAG_PCA_COARSE_CLK_ADJ_MASK = 0x08, + + DBG_SWDIAG_PCA_EVT_START_OFFSET = 4, + DBG_SWDIAG_PCA_EVT_START_MASK = 0x10, + + DBG_SWDIAG_PCA_EVT_CANCELED_OFFSET = 5, + DBG_SWDIAG_PCA_EVT_CANCELED_MASK = 0x20, + + DBG_SWDIAG_PCA_ALARM_INSTANT_OFFSET = 6, + DBG_SWDIAG_PCA_ALARM_INSTANT_MASK = 0x40, + + DBG_SWDIAG_PCA_CLK_DRAG_OFFSET = 7, + DBG_SWDIAG_PCA_CLK_DRAG_MASK = 0x80, + + /** + ****************************************************************************************** + * @brief BANK 25 : BCST + ****************************************************************************************** + */ + DBG_SWDIAG_BCST = 25, + + DBG_SWDIAG_BCST_FRM_ISR_OFFSET = 0, + DBG_SWDIAG_BCST_FRM_ISR_MASK = 0x01, + + DBG_SWDIAG_BCST_EVT_START_OFFSET = 1, + DBG_SWDIAG_BCST_EVT_START_MASK = 0x02, + + DBG_SWDIAG_BCST_SKET_ISR_OFFSET = 2, + DBG_SWDIAG_BCST_SKET_ISR_MASK = 0x04, + + DBG_SWDIAG_BCST_EVT_CANCELED_OFFSET = 3, + DBG_SWDIAG_BCST_EVT_CANCELED_MASK = 0x08, + + DBG_SWDIAG_BCST_ACL_TX_OFFSET = 4, + DBG_SWDIAG_BCST_ACL_TX_MASK = 0x10, + + DBG_SWDIAG_BCST_ACL_ACK_OFFSET = 5, + DBG_SWDIAG_BCST_ACL_ACK_MASK = 0x20, + + DBG_SWDIAG_BCST_LMP_TX_OFFSET = 6, + DBG_SWDIAG_BCST_LMP_TX_MASK = 0x40, + + DBG_SWDIAG_BCST_LMP_ACK_OFFSET = 7, + DBG_SWDIAG_BCST_LMP_ACK_MASK = 0x80, + + + + /** + ****************************************************************************************** + * @brief BANK 3 : BLEISR - 2 + ****************************************************************************************** + */ + DBG_SWDIAG_BLE_ISR2 = 26, + + DBG_SWDIAG_BLE_ISR2_SWINT_OFFSET = 0, + DBG_SWDIAG_BLE_ISR2_SWINT_MASK = 0x01, + + DBG_SWDIAG_BLE_ISR2_EVENTAPFMINT_OFFSET = 1, + DBG_SWDIAG_BLE_ISR2_EVENTAPFMINT_MASK = 0x02, + + DBG_SWDIAG_BLE_ISR2_AUDIO0INT_OFFSET = 2, + DBG_SWDIAG_BLE_ISR2_AUDIO0INT_MASK = 0x04, + + DBG_SWDIAG_BLE_ISR2_AUDIO1INT_OFFSET = 3, + DBG_SWDIAG_BLE_ISR2_AUDIO1INT_MASK = 0x08, + + DBG_SWDIAG_BLE_ISR2_AUDIO2INT_OFFSET = 4, + DBG_SWDIAG_BLE_ISR2_AUDIO2INT_MASK = 0x10, + + + + /** + ****************************************************************************************** + * @brief RSA Algorithm + ****************************************************************************************** + */ + + DBG_SWDIAG_RSA = 27, + + DBG_SWDIAG_RSA_BUSY_OFFSET = 0, + DBG_SWDIAG_RSA_BUSY_MASK = 0x01, + + DBG_SWDIAG_RSA_COMPUTE_OFFSET = 1, + DBG_SWDIAG_RSA_COMPUTE_MASK = 0x02, + + /** + ****************************************************************************************** + * @brief BANK 28 : SYNC SCAN + ****************************************************************************************** + */ + DBG_SWDIAG_SSCAN = 28, + + DBG_SWDIAG_SSCAN_FRM_ISR_OFFSET = 0, + DBG_SWDIAG_SSCAN_FRM_ISR_MASK = 0x01, + + DBG_SWDIAG_SSCAN_EVT_START_OFFSET = 1, + DBG_SWDIAG_SSCAN_EVT_START_MASK = 0x02, + + DBG_SWDIAG_SSCAN_START_OFFSET = 2, + DBG_SWDIAG_SSCAN_START_MASK = 0x04, + + DBG_SWDIAG_SSCAN_EVT_CANCELED_OFFSET = 3, + DBG_SWDIAG_SSCAN_EVT_CANCELED_MASK = 0x08, + + DBG_SWDIAG_SSCAN_FRM_CBK_OFFSET = 4, + DBG_SWDIAG_SSCAN_FRM_CBK_MASK = 0x10, + + DBG_SWDIAG_SSCAN_STP_RX_OFFSET = 5, + DBG_SWDIAG_SSCAN_STP_RX_MASK = 0x20, + + DBG_SWDIAG_SSCAN_STP_RX_OK_OFFSET = 6, + DBG_SWDIAG_SSCAN_STP_RX_OK_MASK = 0x40, + + DBG_SWDIAG_SSCAN_TIMEOUT_OFFSET = 7, + DBG_SWDIAG_SSCAN_TIMEOUT_MASK = 0x80, + + /** + ****************************************************************************************** + * @brief BANK 29 : ACL_TX + ****************************************************************************************** + */ + DBG_SWDIAG_ACL_TX = 29, + + DBG_SWDIAG_ACL_TX_TRAFFIC_OFFSET = 0, + DBG_SWDIAG_ACL_TX_TRAFFIC_MASK = 0xFF, + + /** + ****************************************************************************************** + * @brief BANK 30 : ACL_RX + ****************************************************************************************** + */ + DBG_SWDIAG_ACL_RX = 30, + + DBG_SWDIAG_ACL_RX_TRAFFIC_OFFSET = 0, + DBG_SWDIAG_ACL_RX_TRAFFIC_MASK = 0xFF, + + /// Number of SW profiles - to increase when new bank are added + DBG_SWDIAG_NB_PROFILES = 31, +}; + +/* + * GLOBAL VARIABLE DECLARATION + **************************************************************************************** + */ + +/// Allocate HW banks to SW profiles +extern uint8_t sw_to_hw[DBG_SWDIAG_NB_PROFILES]; + + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** +****************************************************************************************** +* @brief Initialize SW profiling module +****************************************************************************************** +*/ +void dbg_swdiag_init(void); + +/** +****************************************************************************************** +* @brief Read the SW profiling configuration. +* +* @return SW profile configuration +****************************************************************************************** +*/ +uint32_t dbg_swdiag_read(void); + +/** +****************************************************************************************** +* @brief Write the SW profiling configuration. +* +* @param[in] profile SW profiling configuration to apply +****************************************************************************************** +*/ +void dbg_swdiag_write(uint32_t profile); + +#endif //RW_SWDIAG + +/// @} DBGSWDIAG + +#endif // DBG_SWDIAG_H_ diff --git a/beken_os/beken378/driver/ble/ble_pub/modules/dbg/api/dbg_task.h b/beken_os/beken378/driver/ble/ble_pub/modules/dbg/api/dbg_task.h new file mode 100755 index 0000000..f968f1f --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/modules/dbg/api/dbg_task.h @@ -0,0 +1,82 @@ +/** + **************************************************************************************** + * + * @file dbg_task.h + * + * @brief DBG task header file + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef DBG_TASK_H_ +#define DBG_TASK_H_ + +/** + **************************************************************************************** + * @addtogroup DBGTASK Task + * @ingroup DBG + * @brief Debug task + * + * The DBG task is responsible for receiving and sending debug informations between the + * HCI and the embedded. + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include // standard definition + +#include "common_bt.h" // common BT definitions +#include "kernel_task.h" // kernel task +#include "rwip_task.h" // Task definitions + +/* + * INSTANCES + **************************************************************************************** + */ +/// Maximum number of instances of the DBG task +#define DBG_IDX_MAX 1 + +/* + * STATES + **************************************************************************************** + */ +/// Possible states of the DBG task +enum +{ + /// IDLE state + DBG_IDLE, + /// Number of states. + DBG_STATE_MAX +}; + +/* + * MESSAGES + **************************************************************************************** + */ +/// Message API of the DBG task +enum +{ + /// Debug commands description. + DBG_MSG_ID_CMD_FIRST = TASK_FIRST_MSG(TASK_ID_DBG), +}; + + + +/* + * TASK DESCRIPTOR DECLARATIONS + **************************************************************************************** + */ +extern const struct kernel_state_handler dbg_default_handler; +extern kernel_state_t dbg_state[DBG_IDX_MAX]; + +/// @} DBGTASK + +#endif // DBG_TASK_H_ diff --git a/beken_os/beken378/driver/ble/ble_pub/modules/dbg/src/dbg.c b/beken_os/beken378/driver/ble/ble_pub/modules/dbg/src/dbg.c new file mode 100755 index 0000000..eadf0f4 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/modules/dbg/src/dbg.c @@ -0,0 +1,99 @@ +/** +**************************************************************************************** +* +* @file dbg.c +* +* @brief Debug function +* +* Copyright (C) RivieraWaves 2009-2015 +* +* +**************************************************************************************** +*/ + +/** +**************************************************************************************** +* @addtogroup DBG +* @{ +**************************************************************************************** +*/ + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" // stack configuration +#if ((BLE_EMB_PRESENT) || (BT_EMB_PRESENT)) + +#include "common_error.h" // common error definition +#include "kernel_task.h" // kernel task definition +#include "dbg_task.h" // debug task definition +#include "dbg.h" // debug definition + +#if (HCI_PRESENT) +#include "hci.h" +#endif //(HCI_PRESENT) + +/* + * DEFINES + **************************************************************************************** + */ + + +/* + * GLOBAL VARIABLE DEFINITIONS + **************************************************************************************** + */ +#if (RW_DEBUG) +/// DEBUG task descriptor +static const struct kernel_task_desc TASK_DESC_DBG = {NULL, &dbg_default_handler, dbg_state, DBG_STATE_MAX, DBG_IDX_MAX}; +#endif //RW_DEBUG + +/* + * LOCAL FUNCTION DEFINITION + **************************************************************************************** + */ + + + +/* + * EXPORTED FUNCTION DEFINITION + **************************************************************************************** + */ +#if (RW_DEBUG) +void dbg_init(void) +{ + // Create DEBUG Task + kernel_task_create(TASK_DBG, &TASK_DESC_DBG); + + // Initialize DBG task to idle state + kernel_state_set(TASK_DBG,DBG_IDLE); + + #if (RW_SWDIAG) + // Initialize SW profiling module + dbg_swdiag_init(); + #endif //RW_SWDIAG + +} +#endif //RW_DEBUG + +void dbg_platform_reset_complete(uint32_t error) +{ + // structure type for the complete command event + struct hci_basic_cmd_cmp_evt *evt = KERNEL_MSG_ALLOC(HCI_CMD_CMP_EVENT, 0, HCI_DBG_PLF_RESET_CMD_OPCODE, hci_basic_cmd_cmp_evt); + + if(error == RESET_TO_ROM) + { + evt->status = COMMON_ERROR_HARDWARE_FAILURE; + } + else if(error == RESET_AND_LOAD_FW) + { + evt->status = COMMON_ERROR_NO_ERROR; + } + + hci_send_2_host(evt); +} + +#endif // ((BLE_EMB_PRESENT) || (BT_EMB_PRESENT)) +///@} DBG diff --git a/beken_os/beken378/driver/ble/ble_pub/modules/dbg/src/dbg_mwsgen.c b/beken_os/beken378/driver/ble/ble_pub/modules/dbg/src/dbg_mwsgen.c new file mode 100755 index 0000000..6d5b97a --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/modules/dbg/src/dbg_mwsgen.c @@ -0,0 +1,372 @@ +/** + **************************************************************************************** + * + * @file dbg_mwsgen.c + * + * @brief MWS/WLAN Generator API. + * + * Copyright (C) RivieraWaves 2015 + * + * + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @addtogroup DBGMWSGEN + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" + +#if (RW_WLAN_COEX_TEST) || (RW_MWS_COEX_TEST) + +#include "dbg_mwsgen.h" +#include "reg_mwsgen.h" // MWS Event Generator register functions + +#include "reg_btcore.h" // BT MWS/WLAN COEX configurations + +#include "rwip.h" // SW interface + + +/* + * DEFINES & ENUMERATIONS + **************************************************************************************** + */ + +///WLAN/MWS source +enum { + EXTERNAL = 0, + INTERNAL = 1 +}; + +///WLAN/MWS enable +enum { + DISABLE = 0, + ENABLE = 1 +}; + +///WLAN/MWS priority level (BT with higher PTI will prioritize over WLAN/MWS) +#define MWSGEN_PTA_ARBITRATION_THRESHOLD 15 + + +/* + * GLOBAL VARIABLES + **************************************************************************************** + */ + +#if (RW_WLAN_COEX_TEST) +uint32_t dbg_wlcoex_scenario; +#endif // (RW_WLAN_COEX_TEST) + +#if (RW_MWS_COEX_TEST) +uint32_t dbg_mwscoex_scenario; +#endif // (RW_MWS_COEX_TEST) + +/* + * FUNCTION DEFINITIONS + **************************************************************************************** + */ +#if (RW_MWS_COEX_TEST) +uint8_t dbg_mwscoex_scen_set(uint32_t scenario) +{ + uint8_t status = COMMON_ERROR_NO_ERROR; + + dbg_mwscoex_scenario = scenario; + + // lower word configures MWS COEX mode for BT + switch (scenario & 0xFFFF) + { + case 0x0000: + /* default mode: mws_rx blocks bt_tx / leave as configured */ + //dbg_mws_config( 0/*txmode*/, 0/*rxmode*/, 0/*txmsk*/, 1/*rxmsk*/, 0/*txfmsk*/, 0/*rxfmsk*/, 0/*scanfmsk*/, 0/*knudge*/); + break; + case 0x0001: + /* customization: mws_rx frequencies block bt_tx */ + dbg_mws_config( 0/*txmode*/, 0/*rxmode*/, 0/*txmsk*/, 0/*rxmsk*/, 0/*txfmsk*/, 1/*rxfmsk*/, 0/*scanfmsk*/, 0/*knudge*/); + break; + case 0x0002: + /* customization: extended mode, mws_rx & mws_tx frequencies block bt_tx & bt_rx */ + dbg_mws_config( 1/*txmode*/, 1/*rxmode*/, 0/*txmsk*/, 0/*rxmsk*/, 3/*txfmsk*/, 3/*rxfmsk*/, 0/*scanfmsk*/, 0/*knudge*/); + break; + case 0x0003: + /* customization: mws_rx, mws_tx & scan frequencies block bt_tx */ + dbg_mws_config( 0/*txmode*/, 0/*rxmode*/, 0/*txmsk*/, 0/*rxmsk*/, 1/*txfmsk*/, 1/*rxfmsk*/, 1/*scanfmsk*/, 0/*knudge*/); + break; + case 0x0004: + /* priority mode: with mws_rx blocks bt_tx */ + dbg_mws_config( 2/*txmode*/, 2/*rxmode*/, 0/*txmsk*/, 1/*rxmsk*/, 0/*txfmsk*/, 0/*rxfmsk*/, 0/*scanfmsk*/, 0/*knudge*/); + break; + case 0x0005: + /* priority mode: with mws_rx, mws_tx & scan frequencies block bt_tx */ + dbg_mws_config( 2/*txmode*/, 2/*rxmode*/, 0/*txmsk*/, 0/*rxmsk*/, 1/*txfmsk*/, 1/*rxfmsk*/, 1/*scanfmsk*/, 0/*knudge*/); + break; + default: + status = COMMON_ERROR_INVALID_HCI_PARAM; + break; + } + + if (COMMON_ERROR_NO_ERROR == status) + { + // upper word configures WLAN GEN characteristics + switch (scenario & 0xFF000000) + { + case 0x00000000: + dbg_mwsgen_init(); + break; + case 0x01000000: + dbg_mwsgen_config(10000 /*mws_period*/, 6250 /*mws_duty_cycle*/, 4000 /*tx_act*/, 3000 /*rx_act*/); + mwsgen_mws_scan_frequency_setf((scenario >> 16) & 0xF); + break; + case 0x02000000: + dbg_mwsgen_config(20000 /*mws_period*/, 8000 /*mws_duty_cycle*/, 2000 /*tx_act*/, 1000 /*rx_act*/); + mwsgen_mws_scan_frequency_setf((scenario >> 16) & 0xF); + break; + case 0x03000000: + mwsgen_mws_inactivity_duration_setf((scenario >> 16) & 0x1F); + break; + default: + status = COMMON_ERROR_INVALID_HCI_PARAM; + } + } + + return status; +} + +void dbg_mwsgen_init(void) +{ + dbg_mwsgen_stop(); + + mwsgen_mwsgen_period_set(0); + mwsgen_mwsgen_duty_cycle_set(0); + + mwsgen_mws_rx_delay_setf(0); + mwsgen_mws_tx_delay_setf(0); + + mwsgen_mwsgen_tx_activity_set(0); + mwsgen_mwsgen_rx_activity_set(0); + + mwsgen_mws_en_setf(0); + mwsgen_wci_en_setf(0); + mwsgen_mws_txrnd_en_setf(0); + mwsgen_mws_rxrnd_en_setf(0); + mwsgen_mws_tx_en_setf(0); + mwsgen_mws_rx_en_setf(0); + mwsgen_wlanpti_setf(0); +} + +void dbg_mwsgen_config(uint32_t period, uint32_t duty_cycle, uint32_t tx_act, uint32_t rx_act) +{ + // Set MWS frame_sync period & duty cycle + mwsgen_mwsgen_period_set(period); /* duration between frame_sync */ + mwsgen_mwsgen_duty_cycle_set(duty_cycle); /* falling edge */ + + // Set uplink/downlink offsets + mwsgen_mws_rx_delay_setf(10); /* frame_sync rising edge to downlink mws_rx */ + mwsgen_mws_tx_delay_setf(10); /* frame_sync falling edge to uplink mws_tx */ + + // Set duration of mws_tx and mws_rx activities + mwsgen_mwsgen_tx_activity_set(tx_act); + mwsgen_mwsgen_rx_activity_set(rx_act); + + // Configure MWS_SCAN_FREQUENCY index output + mwsgen_mws_scan_frequency_setf(0); + + // Set general control flags + // mwsgen_mws_en_setf(ENABLE); + mwsgen_wci_en_setf(0); + mwsgen_mws_txrnd_en_setf(0); + mwsgen_mws_rxrnd_en_setf(0); + mwsgen_mws_tx_en_setf(1); + mwsgen_mws_rx_en_setf(1); + + // Configure the arbitration threshold + mwsgen_wlanpti_setf(MWSGEN_PTA_ARBITRATION_THRESHOLD); + + dbg_mwsgen_start(); +} + +void dbg_mwsgen_config_scan_frequency(uint8_t scan_freq) +{ + mwsgen_mws_scan_frequency_setf(scan_freq); +} + +void dbg_mws_config(uint8_t txmode, uint8_t rxmode, uint8_t txmsk, uint8_t rxmsk, uint8_t txfmsk, uint8_t rxfmsk, uint8_t scanfmsk, uint8_t knudge) +{ + bt_coexifcntl0_knudgeinc_setf(knudge); /* knudge value for train nudging */ + bt_coexifcntl0_mwsscanfreqmsk_setf(scanfmsk); /* mws scan frequency impact on bt_tx/bt_rx (default mode = no impact) */ + bt_coexifcntl0_mwstxfrqmsk_setf(txfmsk); /* mws tx frequency impact on bt_tx/bt_rx (default mode = no impact) */ + bt_coexifcntl0_mwsrxfrqmsk_setf(rxfmsk); /* mws rx frequency impact on bt_tx/bt_rx (default mode = no impact) */ + bt_coexifcntl0_mwstxmsk_setf(txmsk); /* mws_tx impact on bt_tx/bt_rx (default mode = no impact) */ + bt_coexifcntl0_mwsrxmsk_setf(rxmsk); /* mws_rx impact on bt_tx/bt_rx (default mode = no impact) */ + + // the following is shared with the wlan coexistance interface - + bt_coexifcntl0_wlcrxpriomode_setf(rxmode); /* set default/extended/priority mode for bt_rx */ + bt_coexifcntl0_wlctxpriomode_setf(txmode); /* set default/extended/priority mode for bt_tx */ + bt_coexifcntl1_pack(8 /*wlcpRXthr*/, 8 /*wlcpTXthr*/, 20 /*wlcpduration*/, 0 /*wlcpdelay*/); /* priority mode configuration */ +} + +void dbg_mwsgen_start(void) +{ +#if DEEP_SLEEP + rwip_prevent_sleep_set(RW_MWS_WLAN_EVENT_GENERATOR_ACTIVE); +#endif//DEEP_SLEEP + mwsgen_mws_en_setf(ENABLE); +} + +void dbg_mwsgen_stop(void) +{ +#if DEEP_SLEEP + rwip_prevent_sleep_clear(RW_MWS_WLAN_EVENT_GENERATOR_ACTIVE); +#endif//DEEP_SLEEP + mwsgen_mws_en_setf(DISABLE); +} + +#endif //(RW_MWS_COEX_TEST) + +#if (RW_WLAN_COEX_TEST) +uint8_t dbg_wlcoex_scen_set(uint32_t scenario) +{ + uint8_t status = COMMON_ERROR_NO_ERROR; + + dbg_wlcoex_scenario = scenario; + + // lower word configures WLAN COEX mode for BT + switch (scenario & 0xFFFF) + { + case 0x0000: + /* default mode: wlan_rx blocks bt_tx / leave as configured */ + //dbg_wlan_config( 0/*txmode*/, 0/*rxmode*/, 0/*txmsk*/, 1/*rxmsk*/, 0/*txthr*/, 0/*rxthr*/, 0/*pduration*/, 0/*pdelay*/); + break; + case 0x0001: + /* customization: wlan_tx and wlan_rx block bt_tx */ + dbg_wlan_config( 0/*txmode*/, 0/*rxmode*/, 1/*txmsk*/, 1/*rxmsk*/, 0/*txthr*/, 0/*rxthr*/, 0/*pduration*/, 0/*pdelay*/); + break; + case 0x0002: + /* customization: extended mode,and wlan_rx blocks bt_tx and bt_rx */ + dbg_wlan_config( 1/*txmode*/, 1/*rxmode*/, 0/*txmsk*/, 3/*rxmsk*/, 0/*txthr*/, 0/*rxthr*/, 0/*pduration*/, 0/*pdelay*/); + break; + case 0x0003: + /* priority mode: wlan_rx blocks bt_tx, threshold at 8, maintained until bt_tx/rx EN are deasserted */ + dbg_wlan_config( 2/*txmode*/, 2/*rxmode*/, 0/*txmsk*/, 1/*rxmsk*/, 8/*txthr*/, 8/*rxthr*/, 0/*pduration*/, 0/*pdelay*/); + break; + case 0x0004: + /* priority mode: wlan_rx blocks bt_tx, threshold at 4, pulse duration at 20us */ + dbg_wlan_config( 2/*txmode*/, 2/*rxmode*/, 0/*txmsk*/, 1/*rxmsk*/, 4/*txthr*/, 4/*rxthr*/, 20/*pduration*/, 0/*pdelay*/); + break; + case 0x0005: + /* priority mode: wlan_rx blocks bt_tx, threshold at 10, pulse duration at 10us */ + dbg_wlan_config( 2/*txmode*/, 2/*rxmode*/, 0/*txmsk*/, 1/*rxmsk*/, 10/*txthr*/, 10/*rxthr*/, 10/*pduration*/, 0/*pdelay*/); + break; + default: + status = COMMON_ERROR_INVALID_HCI_PARAM; + break; + } + + if (COMMON_ERROR_NO_ERROR == status) + { + // upper word configures WLAN GEN characteristics + switch (scenario & 0xFFFF0000) + { + case 0x00000000: + dbg_wlangen_init(); + break; + case 0x01000000: + dbg_wlangen_config(5000 /*wlan_period*/, 3125 /*wlan_duty_cycle*/, 1000 /*tx_act*/, 3000 /*rx_act*/); + break; + case 0x02000000: + dbg_wlangen_config(8000 /*wlan_period*/, 6000 /*wlan_duty_cycle*/, 1000 /*tx_act*/, 3000 /*rx_act*/); + break; + default: + status = COMMON_ERROR_INVALID_HCI_PARAM; + } + } + + return status; +} + +void dbg_wlangen_init(void) +{ + dbg_wlangen_stop(); + + mwsgen_wlan_duty_cycle_setf(0); + mwsgen_wlan_period_setf(0); + + mwsgen_wlan_rx_delay_setf(0); + mwsgen_wlan_tx_delay_setf(0); + + mwsgen_wlangen_tx_activity_set(0); + mwsgen_wlangen_rx_activity_set(0); + + mwsgen_wlan_en_setf(0); + mwsgen_wlan_source_setf(0); + mwsgen_wlan_txrnd_en_setf(0); + mwsgen_wlan_rxrnd_en_setf(0); + mwsgen_wlan_tx_en_setf(0); + mwsgen_wlan_rx_en_setf(0); + mwsgen_wlanpti_setf(0); +} + +void dbg_wlangen_config(uint32_t period, uint32_t duty_cycle, uint32_t tx_act, uint32_t rx_act) +{ + // Set WLAN period & duty cycle + mwsgen_wlan_duty_cycle_setf(duty_cycle); + mwsgen_wlan_period_setf(period); + + // Set wlan_tx and wlan_rx offsets + mwsgen_wlan_rx_delay_setf(10); /* pseudo WLAN frame Rx part to wlan_rx rising edge */ + mwsgen_wlan_tx_delay_setf(10); /* pseudo WLAN frame Tx part to wlan_tx rising edge */ + + // Set duration of wlan_tx and wlan_rx activities + mwsgen_wlangen_tx_activity_set(tx_act); + mwsgen_wlangen_rx_activity_set(rx_act); + + // Set general control flags + //mwsgen_wlan_en_setf(ENABLE); + mwsgen_wlan_source_setf(INTERNAL); + mwsgen_wlan_txrnd_en_setf(0); + mwsgen_wlan_rxrnd_en_setf(0); + mwsgen_wlan_tx_en_setf(1); + mwsgen_wlan_rx_en_setf(1); + + // Configure the arbitration threshold + mwsgen_wlanpti_setf(MWSGEN_PTA_ARBITRATION_THRESHOLD); + + dbg_wlangen_start(); +} + +void dbg_wlan_config(uint8_t txmode, uint8_t rxmode, uint8_t txmsk, uint8_t rxmsk, uint8_t txthr, uint8_t rxthr, uint8_t pduration, uint8_t pdelay) +{ + bt_coexifcntl0_wlcrxpriomode_setf(rxmode); /* set default/extended/priority mode for bt_rx */ + bt_coexifcntl0_wlctxpriomode_setf(txmode); /* set default/extended/priority mode for bt_tx */ + bt_coexifcntl0_wlantxmsk_setf(txmsk); /* wlan_tx impact on bt_tx/bt_rx (default mode = no impact) */ + bt_coexifcntl0_wlanrxmsk_setf(rxmsk); /* wlan_rx impact on bt_tx/bt_rx (default mode = can stop bt_tx) */ + bt_coexifcntl1_pack(rxthr /*wlcpRXthr*/, txthr /*wlcpTXthr*/, pduration /*wlcpduration*/, pdelay /*wlcpdelay*/); /* priority mode configuration */ +} + +void dbg_wlangen_start(void) +{ +#if DEEP_SLEEP + rwip_prevent_sleep_set(RW_MWS_WLAN_EVENT_GENERATOR_ACTIVE); +#endif//DEEP_SLEEP + mwsgen_wlan_en_setf(ENABLE); +} + +void dbg_wlangen_stop(void) +{ +#if DEEP_SLEEP + rwip_prevent_sleep_clear(RW_MWS_WLAN_EVENT_GENERATOR_ACTIVE); +#endif//DEEP_SLEEP + mwsgen_wlan_en_setf(DISABLE); +} +#endif // RW_WLAN_COEX_TEST + +#endif // (RW_WLAN_COEX_TEST) || (RW_WLAN_COEX_TEST) + +/// @} DBGMWSGEN diff --git a/beken_os/beken378/driver/ble/ble_pub/modules/dbg/src/dbg_swdiag.c b/beken_os/beken378/driver/ble/ble_pub/modules/dbg/src/dbg_swdiag.c new file mode 100755 index 0000000..dbedd84 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/modules/dbg/src/dbg_swdiag.c @@ -0,0 +1,132 @@ +/** +**************************************************************************************** +* +* @file dbg_swdiag.c +* +* @brief SW profiling module +* +* Copyright (C) RivieraWaves 2009-2015 +* +**************************************************************************************** +*/ + +/** + **************************************************************************************** + * @addtogroup DBGSWDIAG + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include // standard integer definitions +#include "dbg_swdiag.h" // SW profiling definition +#include "common_utils.h" // common utility declaration + +#if (RW_SWDIAG) + +#if (NVDS_SUPPORT) +#include "nvds.h" // NVDS definitions +#endif // NVDS_SUPPORT + +/* + * GLOBAL VARIABLE DEFINITIONS + **************************************************************************************** + */ + +/// Allocate SW profiles to HW banks +static uint8_t hw_to_sw[DBG_SWDIAG_NB_HW_BANKS]; + +/// Allocate HW banks to SW profiles +uint8_t sw_to_hw[DBG_SWDIAG_NB_PROFILES]; + + +/* + * LOCAL FUNCTION DEFINITIONS + **************************************************************************************** + */ + +/** + ****************************************************************************************** + * @brief Update SW profile. + * + * This function reserves the allocation of SW profiles to HW bank. It allocates to each + * SW profile a HW bank, depending on the HwToSW allocation table. + ****************************************************************************************** + */ +static void dbg_swdiag_update(void) +{ + uint8_t i; + + GLOBAL_INT_DIS(); + + // Clear sw_to_hw table + for(i = 0 ; i < DBG_SWDIAG_NB_PROFILES ; i++) + { + sw_to_hw[i] = DBG_SWDIAG_UNDEFINED; + } + + // Parse all HW banks + for(i = 0 ; i < DBG_SWDIAG_NB_HW_BANKS ; i++) + { + // Check if a valid profile is allocated to this HW bank + if(hw_to_sw[i] != DBG_SWDIAG_UNDEFINED) + { + // Allocate the SW profile + sw_to_hw[hw_to_sw[i]] = i; + } + } + + // Clear signals + SW_DIAG_SET(0); + + GLOBAL_INT_RES(); +} + + +/* + * EXPORTED FUNCTION DEFINITIONS + **************************************************************************************** + */ + +void dbg_swdiag_init(void) +{ + #if (NVDS_SUPPORT) + uint8_t length = NVDS_LEN_DIAG_SW; + + // Check SW diags configuration in NVDS + if(nvds_get(NVDS_TAG_DIAG_SW, &length, hw_to_sw) != NVDS_OK) + #endif // NVDS_SUPPORT + { + // Allocation is NULL + hw_to_sw[0] = DBG_SWDIAG_UNDEFINED; + hw_to_sw[1] = DBG_SWDIAG_UNDEFINED; + hw_to_sw[2] = DBG_SWDIAG_UNDEFINED; + hw_to_sw[3] = DBG_SWDIAG_UNDEFINED; + } + + // Update profiles allocation + dbg_swdiag_update(); +} + +uint32_t dbg_swdiag_read(void) +{ + return common_read32p(hw_to_sw); //*((uint32_t*) &hw_to_sw[0]); +} + +void dbg_swdiag_write(uint32_t profile) +{ + // Write new configuration into global variable + common_write32p(hw_to_sw, profile); +// *((uint32_t*) &hw_to_sw[0]) = profile; + + // Update profiles allocation + dbg_swdiag_update(); +} + +#endif //RW_SWDIAG + +/// @} DBGSWDIAG diff --git a/beken_os/beken378/driver/ble/ble_pub/modules/dbg/src/dbg_task.c b/beken_os/beken378/driver/ble/ble_pub/modules/dbg/src/dbg_task.c new file mode 100755 index 0000000..9c3f948 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/modules/dbg/src/dbg_task.c @@ -0,0 +1,1542 @@ +/** + **************************************************************************************** + * + * @file dbg_task.c + * + * @brief DBG task source file + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @addtogroup DBGTASK + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" // stack configuration +#if (RW_DEBUG && (BT_EMB_PRESENT || BLE_EMB_PRESENT)) + +#include // for mem* functions +#include "common_endian.h" +#include "common_error.h" +#include "architect.h" // arch definition +#include "dbg_task.h" // debug task definition +#include "dbg.h" // debug block definition +#include "rwip.h" // RF API definitions +#include "kernel.h" // kernel definitions +#include "kernel_mem.h" // kernel memory management + +#if (RW_DEBUG_FLASH) +#include "flash.h" // flash functions and macros +#endif //RW_DEBUG_FLASH + +#if (RW_DEBUG_NVDS) +#if (NVDS_SUPPORT) +#include "nvds.h" // NVDS definitions +#endif // NVDS_SUPPORT +#endif //RW_DEBUG_NVDS + +#if (BLE_EMB_PRESENT) +#include "ble_reg_access.h" // access registers +#endif // BLE_EMB_PRESENT + +#if (BLE_EMB_PRESENT) +#include "reg_blecore.h" +#include "reg_ble_em_cs.h" +#include "lld.h" +#include "lld_evt.h" +#include "lld_util.h" +#include "llm_util.h" +#include "llc_util.h" +#include "llcontrl.h" +#if (BLE_AUDIO) +#include "audio.h" +#endif +#endif //BLE_EMB_PRESENT + +#if (RW_WLAN_COEX_TEST || RW_MWS_COEX_TEST) +#include "dbg_mwsgen.h" +#endif //(RW_WLAN_COEX_TEST || RW_MWS_COEX_TEST) + + +#if (HCI_PRESENT) +#include "hci.h" +#endif //(HCI_PRESENT) + + +/* + * DEFINES + **************************************************************************************** + */ + +/// 8 bit access types +#define _8_Bit 8 +/// 16 bit access types +#define _16_Bit 16 +/// 32 bit access types +#define _32_Bit 32 + +/// PLATFORM RESET REASON: Reset and load FW from flash +#define PLATFORM_RESET_TO_FW (0) +/// PLATFORM RESET REASON: Reset and stay in ROM code +#define PLATFORM_RESET_TO_ROM (1) + + +/* + * GLOBAL VARIABLE DEFINITIONS + **************************************************************************************** + */ + + +/* + * LOCAL FUNCTION DEFINITIONS + **************************************************************************************** + */ +#if (BLE_EMB_PRESENT) +/** + **************************************************************************************** + * @brief Update the TX power field of the event passed as parameter with the requested + * value of TX power + * + * @param[in] conhdl The connection handle for which the TX power is updated + * @param[in] tx_pwr The TX power to be applied to this event + * + * @return The status + * + **************************************************************************************** + */ +static uint8_t dbg_task_txpwr_update(uint16_t conhdl, uint8_t tx_pwr) +{ + // Event allocated for the link + struct lld_evt_tag *evt = NULL; + uint8_t status = COMMON_ERROR_NO_ERROR; + if (conhdl == BLE_CONNECTION_MAX) + { + // Address of the element is stored in the LLM environment + evt = LLD_EVT_ENV_ADDR_GET(llm_le_env.elt); + } + #if (BLE_CENTRAL || BLE_PERIPHERAL) + else + { + // Check if the connection exists + if(llc_util_get_element_ptr(conhdl) != NULL) + { + evt = LLD_EVT_ENV_ADDR_GET(llc_util_get_element_ptr(conhdl)); + } + else + { + status = COMMON_ERROR_UNKNOWN_CONNECTION_ID; + } + } + #endif //(BLE_CENTRAL || BLE_PERIPHERAL) + // Update Power in the event structure + if(evt) + { + evt->tx_pwr = tx_pwr; + } + return(status); +} +#endif// (BLE_EMB_PRESENT) + +/* + * MESSAGE HANDLERS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Handle the reception of the vendor specific command read from memory. + * + * @param[in] msgid Id of the message received (probably unused). + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (probably unused). + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int +hci_dbg_rd_mem_cmd_handler(kernel_msg_id_t const msgid, struct hci_dbg_rd_mem_cmd const *param, + kernel_task_id_t const dest_id, kernel_task_id_t const src_id) +{ + #if (RW_DEBUG_MEM) + uint8_t length = 0; + uint32_t init_addr = 0; + uint32_t value = 0; + uint32_t i = 0; + #endif //RW_DEBUG_MEM + + // structure type for the complete command event + struct hci_dbg_basic_rd_data_cmd_cmp_evt *event = KERNEL_MSG_ALLOC(HCI_CMD_CMP_EVENT , 0, src_id, hci_dbg_basic_rd_data_cmd_cmp_evt); + + #if (RW_DEBUG_MEM) + init_addr = param->start_addr; + length = param->length; + + + /* Check that data length is not null or too big before reading */ + if ((length == 0)|| + (length > (sizeof(struct buffer_tag)- sizeof(uint8_t)))) + { + event->status = COMMON_ERROR_INVALID_HCI_PARAM; + } + else + { + /* Check type of data to be read */ + if (param->type == _8_Bit) + { + /* Read bytes */ + for (i = 0; i < length; i++) + { + /* Read value at @ set in Param1+i */ + event->buf.data[i] = *(volatile uint8_t *)(init_addr+i); + } + } + else if (param->type == _16_Bit) + { + for (i = 0; i < length; i += 2) + { + /* Read value at @ set in Param1+i */ + value = (*(volatile uint16_t *)(init_addr+i)); + + /* store in the buffer */ + event->buf.data[i] = (uint8_t) value; + value >>= 8; + event->buf.data[i+1] = (uint8_t) value; + } + } + else if (param->type == _32_Bit) + { + /* Read 32 bit word */ + for (i = 0; i < length; i += 4) + { + value = (*(volatile uint32_t *)(init_addr+i)); + + /* store in the buffer */ + event->buf.data[i] = (uint8_t) value; + value >>= 8; + event->buf.data[i+1] = (uint8_t) value; + value >>= 8; + event->buf.data[i+2] = (uint8_t) value; + value >>= 8; + event->buf.data[i+3] = (uint8_t) value; + } + } + event->buf.length = length; + event->status = COMMON_ERROR_NO_ERROR; + } + #else //RW_DEBUG_MEM + event->status = COMMON_ERROR_UNSUPPORTED; + #endif //RW_DEBUG_MEM + + // sends the message + hci_send_2_host(event); + + return (KERNEL_MSG_CONSUMED); +} + +/** + **************************************************************************************** + * @brief Handle the reception of the vendor specific command write to memory. + * + * @param[in] msgid Id of the message received (probably unused). + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (probably unused). + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int +hci_dbg_wr_mem_cmd_handler(kernel_msg_id_t const msgid, struct hci_dbg_wr_mem_cmd const *param, + kernel_task_id_t const dest_id, kernel_task_id_t const src_id) +{ + #if (RW_DEBUG_MEM) + uint32_t value = 0; + uint32_t length = 0; + uint32_t init_addr = 0; + uint8_t *data_buf; + uint32_t i = 0; + #endif //RW_DEBUG_MEM + + // structure type for the complete command event + struct hci_basic_cmd_cmp_evt *event = KERNEL_MSG_ALLOC(HCI_CMD_CMP_EVENT , 0, HCI_DBG_WR_MEM_CMD_OPCODE, hci_basic_cmd_cmp_evt); + + #if (RW_DEBUG_MEM) + length = param->buf.length; + data_buf = (uint8_t*)¶m->buf.data[0]; + init_addr = param->start_addr; + + /* Check that data length is not null or too big before reading */ + if ((length == 0)|| (length > (sizeof(struct buffer_tag)- sizeof(uint8_t)))) + { + event->status = COMMON_ERROR_INVALID_HCI_PARAM; + } + else + { + /* Check type of data to be written */ + if (param->type == _8_Bit) + { + /* Write bytes */ + for (i = 0; i < length; i++) + { + /* Set value type at @ Param1 */ + *(volatile uint8_t *)(init_addr+i) = data_buf[i]; + } + } + else if (param->type == _16_Bit) + { + /* Write 16 bits word */ + for (i = 0; i < length; i += 2) + { + /* Set value type at @ Param1 */ + value = ((uint32_t)data_buf[i+1]); + value <<= 8; + value |= ((uint32_t)data_buf[i+0]); + *(volatile uint16_t *)(init_addr+i) = value; + } + } + else if(param->type == _32_Bit) + { + /* Write 32 bit word */ + for (i = 0; i < length; i += 4) + { + /* Set value at @ Param1 */ + value = ((uint32_t)data_buf[i+3]); + value <<= 8; + value |= ((uint32_t)data_buf[i+2]); + value <<= 8; + value |= ((uint32_t)data_buf[i+1]); + value <<= 8; + value |= ((uint32_t)data_buf[i+0]); + *(volatile uint32_t *)(init_addr+i) = value; + } + } + event->status = COMMON_ERROR_NO_ERROR; + } + #else //RW_DEBUG_MEM + event->status = COMMON_ERROR_UNSUPPORTED; + #endif //RW_DEBUG_MEM + + // sends the message + hci_send_2_host(event); + + return (KERNEL_MSG_CONSUMED); +} + +/** + **************************************************************************************** + * @brief Handle the reception of the vendor specific command delete param. + * + * @param[in] msgid Id of the message received (probably unused). + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (probably unused). + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int +hci_dbg_del_par_cmd_handler(kernel_msg_id_t const msgid, struct hci_dbg_del_param_cmd const *param, + kernel_task_id_t const dest_id, kernel_task_id_t const src_id) +{ + // structure type for the complete command event + struct hci_basic_cmd_cmp_evt *event = KERNEL_MSG_ALLOC(HCI_CMD_CMP_EVENT , 0, HCI_DBG_DEL_PAR_CMD_OPCODE, hci_basic_cmd_cmp_evt); + + #if (NVDS_SUPPORT && RW_DEBUG_NVDS && NVDS_READ_WRITE) + nvds_del(param->param_tag); + event->status = COMMON_ERROR_NO_ERROR; + #else + event->status = COMMON_ERROR_UNSUPPORTED; + #endif // RW_DEBUG_NVDS && NVDS_READ_WRITE + + // sends the message + hci_send_2_host(event); + + return (KERNEL_MSG_CONSUMED); +} + +/** + **************************************************************************************** + * @brief Handle the reception of the vendor specific command id flash. + * + * @param[in] msgid Id of the message received (probably unused). + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (probably unused). + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int +hci_dbg_id_flash_cmd_handler(kernel_msg_id_t const msgid, void const *param, kernel_task_id_t const dest_id, kernel_task_id_t const src_id) +{ + // structure type for the complete command event + struct hci_dbg_id_flash_cmd_cmp_evt *event = KERNEL_MSG_ALLOC(HCI_CMD_CMP_EVENT , 0, src_id, hci_dbg_id_flash_cmd_cmp_evt); + + #if (RW_DEBUG_FLASH) + flash_identify(&event->flash_id, NULL); + event->status = (event->flash_id != FLASH_TYPE_UNKNOWN)?COMMON_ERROR_NO_ERROR : COMMON_ERROR_HARDWARE_FAILURE; + #else //RW_DEBUG_FLASH + event->status = COMMON_ERROR_UNSUPPORTED; + #endif //RW_DEBUG_FLASH + + // sends the message + hci_send_2_host(event); + + return (KERNEL_MSG_CONSUMED); +} + +/** + **************************************************************************************** + * @brief Handle the reception of the vendor specific command flash erase. + * + * @param[in] msgid Id of the message received (probably unused). + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (probably unused). + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int +hci_dbg_er_flash_cmd_handler(kernel_msg_id_t const msgid, struct hci_dbg_er_flash_cmd const *param, + kernel_task_id_t const dest_id, kernel_task_id_t const src_id) +{ + // structure type for the complete command event + struct hci_basic_cmd_cmp_evt *event = KERNEL_MSG_ALLOC(HCI_CMD_CMP_EVENT , 0, src_id, hci_basic_cmd_cmp_evt); + + #if (RW_DEBUG_FLASH) + event->status = flash_erase(param->flashtype, param->startoffset,param->size, NULL); + #else //RW_DEBUG_FLASH + event->status = COMMON_ERROR_UNSUPPORTED; + #endif //RW_DEBUG_FLASH + + // sends the message + hci_send_2_host(event); + + return (KERNEL_MSG_CONSUMED); +} + +/** + **************************************************************************************** + * @brief Handle the reception of the vendor specific command write flash. + * + * @param[in] msgid Id of the message received (probably unused). + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (probably unused). + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int +hci_dbg_wr_flash_cmd_handler(kernel_msg_id_t const msgid, struct hci_dbg_wr_flash_cmd const *param, + kernel_task_id_t const dest_id, kernel_task_id_t const src_id) +{ + // structure type for the complete command event + struct hci_basic_cmd_cmp_evt *event = KERNEL_MSG_ALLOC(HCI_CMD_CMP_EVENT , 0, src_id, hci_basic_cmd_cmp_evt); + + #if (RW_DEBUG_FLASH) + event->status = flash_write(param->flashtype, param->startoffset, param->buf.length, (uint8_t*)¶m->buf.data[0], NULL); + #else //RW_DEBUG_FLASH + event->status = COMMON_ERROR_UNSUPPORTED; + #endif //RW_DEBUG_FLASH + + // sends the message + hci_send_2_host(event); + + return (KERNEL_MSG_CONSUMED); +} + +/** + **************************************************************************************** + * @brief Handle the reception of the vendor specific command read flash. + * + * Read the requested number of byte from flash. + * + * @param[in] msgid Id of the message received (probably unused). + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (probably unused). + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int +hci_dbg_rd_flash_cmd_handler(kernel_msg_id_t const msgid, struct hci_dbg_rd_flash_cmd const *param, + kernel_task_id_t const dest_id, kernel_task_id_t const src_id) +{ + // structure type for the complete command event + struct hci_dbg_basic_rd_data_cmd_cmp_evt *event = KERNEL_MSG_ALLOC(HCI_CMD_CMP_EVENT , 0, src_id, hci_dbg_basic_rd_data_cmd_cmp_evt); + + #if (RW_DEBUG_FLASH) + event->buf.length = param->size; + event->status = flash_read(param->flashtype, param->startoffset, param->size, (uint8_t*)&event->buf.data[0], NULL); + #else //RW_DEBUG_FLASH + event->status = COMMON_ERROR_UNSUPPORTED; + #endif //RW_DEBUG_FLASH + + // sends the message + hci_send_2_host(event); + + return (KERNEL_MSG_CONSUMED); +} + +/** + **************************************************************************************** + * @brief Handle the reception of the vendor specific command read + * parameter request. + * + * @param[in] msgid Id of the message received (probably unused). + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (probably unused). + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int +hci_dbg_rd_par_cmd_handler(kernel_msg_id_t const msgid, struct hci_dbg_rd_par_cmd const *param, + kernel_task_id_t const dest_id, kernel_task_id_t const src_id) +{ + // structure type for the complete command event + struct hci_dbg_basic_rd_data_cmd_cmp_evt *event = KERNEL_MSG_ALLOC(HCI_CMD_CMP_EVENT , 0, src_id, hci_dbg_basic_rd_data_cmd_cmp_evt); + + #if (NVDS_SUPPORT && RW_DEBUG_NVDS) + event->buf.length = sizeof(event->buf.data); + nvds_get(param->param_tag, (uint8_t*)&event->buf.length, (uint8_t*)&event->buf.data[0]); + event->status = COMMON_ERROR_NO_ERROR; + #else //RW_DEBUG_NVDS + event->buf.length = 0; + event->status = COMMON_ERROR_UNSUPPORTED; + #endif //RW_DEBUG_NVDS + + // sends the message + hci_send_2_host(event); + + return (KERNEL_MSG_CONSUMED); +} + +/** + **************************************************************************************** + * @brief Handle the reception of the vendor specific command write + * parameter request. + * + * @param[in] msgid Id of the message received (probably unused). + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (probably unused). + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int +hci_dbg_wr_par_cmd_handler(kernel_msg_id_t const msgid, struct hci_dbg_wr_par_cmd const *param, + kernel_task_id_t const dest_id, kernel_task_id_t const src_id) +{ + // structure type for the complete command event + struct hci_basic_cmd_cmp_evt *event = KERNEL_MSG_ALLOC(HCI_CMD_CMP_EVENT , 0, src_id, hci_basic_cmd_cmp_evt); + + #if (NVDS_SUPPORT && RW_DEBUG_NVDS && NVDS_READ_WRITE) + nvds_put(param->param_tag, param->buf.length, (uint8_t*)¶m->buf.data[0]); + event->status = COMMON_ERROR_NO_ERROR; + #else + event->status = COMMON_ERROR_UNSUPPORTED; + #endif // RW_DEBUG_NVDS && NVDS_READ_WRITE + + // sends the message + hci_send_2_host(event); + + return (KERNEL_MSG_CONSUMED); +} + + +/** + **************************************************************************************** + * @brief Handle the reception of the vendor specific command Read Kernel Stats + * + * @param[in] msgid Id of the message received (probably unused). + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (probably unused). + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int +hci_dbg_rd_kernel_stats_cmd_handler(kernel_msg_id_t const msgid, void const *param, + kernel_task_id_t const dest_id, kernel_task_id_t const src_id) +{ + // structure type for the complete command event + struct hci_dbg_rd_kernel_stats_cmd_cmp_evt *event = KERNEL_MSG_ALLOC(HCI_CMD_CMP_EVENT, 0, HCI_DBG_RD_KERNEL_STATS_CMD_OPCODE, hci_dbg_rd_kernel_stats_cmd_cmp_evt); + + #if (KERNEL_PROFILING) + if(kernel_stats_get(&event->max_msg_sent, &event->max_msg_saved, &event->max_timer_used, &event->max_heap_used) == KERNEL_SUCCESS) + { + event->status = COMMON_ERROR_NO_ERROR; + } + else + { + event->status = COMMON_ERROR_UNSUPPORTED; + event->max_msg_sent = 0; + event->max_msg_saved = 0; + event->max_timer_used = 0; + event->max_heap_used = 0; + } + #if (RW_DEBUG_STACK_PROF) + event->max_stack_used = get_stack_usage(); + #else //RW_DEBUG_STACK_PROF + event->max_stack_used = 0; + #endif //RW_DEBUG_STACK_PROF + #else //KERNEL_PROFILING + event->status = COMMON_ERROR_UNSUPPORTED; + event->max_msg_sent = 0; + event->max_msg_saved = 0; + event->max_timer_used = 0; + event->max_heap_used = 0; + event->max_stack_used = 0; + #endif //KERNEL_PROFILING + + // sends the message + hci_send_2_host(event); + + return (KERNEL_MSG_CONSUMED); +} + +/** + **************************************************************************************** + * @brief Handle the reception of the vendor specific command Read Memory info + * + * @param[in] msgid Id of the message received (probably unused). + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (probably unused). + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int hci_dbg_rd_mem_info_cmd_handler(kernel_msg_id_t const msgid, void const *param, + kernel_task_id_t const dest_id, kernel_task_id_t const src_id) +{ + struct hci_dbg_rd_mem_info_cmd_cmp_evt * meminfo_msg; + #if (KERNEL_PROFILING) + uint8_t cursor; + struct hci_dbg_rd_mem_info_cmd_cmp_evt meminfo; + + // First remove command message in order to be sure it's not taken in account. + kernel_msg_free(kernel_param2msg(param)); + + // Then retrieve memory information from kernel + meminfo.max_mem_used = kernel_get_max_mem_usage(); + + for(cursor = 0; cursor < KERNEL_MEM_BLOCK_MAX ; cursor++) + { + meminfo.mem_used[cursor] = kernel_get_mem_usage(cursor); + } + #endif // (KERNEL_PROFILING) + // Finally send indication to application that request memory information + meminfo_msg = KERNEL_MSG_ALLOC(HCI_CMD_CMP_EVENT , 0, HCI_DBG_RD_MEM_INFO_CMD_OPCODE, hci_dbg_rd_mem_info_cmd_cmp_evt); + + #if (KERNEL_PROFILING) + memcpy(meminfo_msg, &meminfo, sizeof(struct hci_dbg_rd_mem_info_cmd_cmp_evt)); + meminfo_msg->status = COMMON_ERROR_NO_ERROR; + #else + meminfo_msg->status = COMMON_ERROR_UNSUPPORTED; + #endif // (KERNEL_PROFILING) + + // sends the message + hci_send_2_host(meminfo_msg); + + // source message already free + return (KERNEL_MSG_NO_FREE); +} + +/** + **************************************************************************************** + * @brief Handle the reception of the vendor specific command Read RF Register value. + * + * @param[in] msgid Id of the message received (probably unused). + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (probably unused). + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int +hci_dbg_rf_reg_rd_cmd_handler(kernel_msg_id_t const msgid, struct hci_dbg_rf_reg_rd_cmd const *param, + kernel_task_id_t const dest_id, kernel_task_id_t const src_id) +{ + // structure type for the complete command event + struct hci_dbg_rf_reg_rd_cmd_cmp_evt *event = KERNEL_MSG_ALLOC(HCI_CMD_CMP_EVENT , 0, HCI_DBG_RF_REG_RD_CMD_OPCODE, hci_dbg_rf_reg_rd_cmd_cmp_evt); + + #if (BLE_STD_MODE && BLE_EMB_PRESENT) + // Unlock BLE<->RF SPI access + #endif //BLE_STD_MODE && BLE_EMB_PRESENT + // Read RF register + event->value = common_htobl(rwip_rf.reg_rd(common_btohs(param->addr))); + + #if (BLE_STD_MODE && BLE_EMB_PRESENT) + // Restore BLE<->RF SPI access lock + #endif //BLE_STD_MODE && BLE_EMB_PRESENT + + event->addr = param->addr; + event->status = COMMON_ERROR_NO_ERROR; + + // sends the message + hci_send_2_host(event); + + return (KERNEL_MSG_CONSUMED); +} + +/** + **************************************************************************************** + * @brief Handle the reception of the vendor specific command Write RF Register value. + * @param[in] msgid Id of the message received (probably unused). + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (probably unused). + * @param[in] src_id ID of the sending task instance. + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int +hci_dbg_rf_reg_wr_cmd_handler(kernel_msg_id_t const msgid, struct hci_dbg_rf_reg_wr_cmd const *param, + kernel_task_id_t const dest_id, kernel_task_id_t const src_id) +{ + // structure type for the complete command event + struct hci_dbg_rf_reg_wr_cmd_cmp_evt *event = KERNEL_MSG_ALLOC(HCI_CMD_CMP_EVENT , 0, HCI_DBG_RF_REG_WR_CMD_OPCODE, hci_dbg_rf_reg_wr_cmd_cmp_evt); + + #if (BLE_STD_MODE && BLE_EMB_PRESENT) + // Unlock BLE<->RF SPI access + #endif //BLE_STD_MODE && BLE_EMB_PRESENT + + // Write RF register + rwip_rf.reg_wr(common_btohs(param->addr), common_btohl(param->value)); + + #if (BLE_STD_MODE && BLE_EMB_PRESENT) + // Restore BLE<->RF SPI access lock + #endif //BLE_STD_MODE && BLE_EMB_PRESENT + + event->addr = param->addr; + event->status = COMMON_ERROR_NO_ERROR; + + // sends the message + hci_send_2_host(event); + + return (KERNEL_MSG_CONSUMED); +} + +/** + **************************************************************************************** + * @brief Handle the reception of the vendor specific command platform reset. + * This command reset FW and return to ROM code. + * + * @note command complete(success) is sent by ROM code. + * + * @param[in] msgid Id of the message received (probably unused). + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (probably unused). + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int +hci_dbg_plf_reset_cmd_handler(kernel_msg_id_t const msgid, struct hci_dbg_plf_reset_cmd const *param, + kernel_task_id_t const dest_id, kernel_task_id_t const src_id) +{ + uint32_t error_code = RESET_NO_ERROR; + + // structure type for the complete command event + struct hci_basic_cmd_cmp_evt *event = KERNEL_MSG_ALLOC(HCI_CMD_CMP_EVENT , src_id, HCI_DBG_PLF_RESET_CMD_OPCODE, hci_basic_cmd_cmp_evt); + + switch(param->reason) + { + case PLATFORM_RESET_TO_FW: error_code = RESET_AND_LOAD_FW; break; + case PLATFORM_RESET_TO_ROM: error_code = RESET_TO_ROM; break; + default: break; + } + + if(error_code != RESET_NO_ERROR) + { + // Perform platform Reset (return to ROM code) + platform_reset(error_code); + } + + // If reason is not valid, returns a CC event with bad status + event->status = COMMON_ERROR_INVALID_HCI_PARAM; + + // sends the message + hci_send_2_host(event); + + return (KERNEL_MSG_CONSUMED); +} + +#if (BLE_EMB_PRESENT) +/** + **************************************************************************************** + * @brief Handle the reception of the vendor specific command read hw register. + * Return the value of the register requested in the command. + * @param[in] msgid Id of the message received (probably unused). + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (probably unused). + * @param[in] src_id ID of the sending task instance. + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int +hci_dbg_hw_reg_rd_cmd_handler(kernel_msg_id_t const msgid, + struct hci_dbg_hw_reg_rd_cmd const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + // structure type for the complete command event + struct hci_dbg_hw_reg_rd_cmd_cmp_evt *event; + + // allocate the status event message + event = KERNEL_MSG_ALLOC(HCI_CMD_CMP_EVENT , src_id, HCI_DBG_HW_REG_RD_CMD_OPCODE, hci_dbg_hw_reg_rd_cmd_cmp_evt); + + event->reg_value = common_htobl(REG_BLE_RD(REG_BLECORE_BASE_ADDR + common_btohs(param->reg_addr))); + event->reg_addr = param->reg_addr; + event->status = COMMON_ERROR_NO_ERROR; + // sends the message + hci_send_2_host(event); + + return (KERNEL_MSG_CONSUMED); +} + +/** + **************************************************************************************** + * @brief Handle the reception of the vendor specific command write hw register. + * Write the requested value in the register passed in the command parameter. + * @param[in] msgid Id of the message received (probably unused). + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (probably unused). + * @param[in] src_id ID of the sending task instance. + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int +hci_dbg_hw_reg_wr_cmd_handler(kernel_msg_id_t const msgid, + struct hci_dbg_hw_reg_wr_cmd const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + // structure type for the complete command event + struct hci_dbg_hw_reg_wr_cmd_cmp_evt *event; + + // allocate the status event message + event = KERNEL_MSG_ALLOC(HCI_CMD_CMP_EVENT , src_id, HCI_DBG_HW_REG_WR_CMD_OPCODE, hci_dbg_hw_reg_wr_cmd_cmp_evt); + + #if (BLE_EMB_PRESENT) + REG_BLE_WR(REG_BLECORE_BASE_ADDR + common_btohs(param->reg_addr), common_btohl(param->reg_value)); + #endif //BLE_EMB_PRESENT + + + event->reg_addr = param->reg_addr; + event->status = COMMON_ERROR_NO_ERROR; + // sends the message + hci_send_2_host(event); + + return (KERNEL_MSG_CONSUMED); +} + +/** + **************************************************************************************** + * @brief Handle the reception of the vendor specific command set bd address. + * Write the requested bd address in the dedicated registers. + * @param[in] msgid Id of the message received (probably unused). + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (probably unused). + * @param[in] src_id ID of the sending task instance. + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int +hci_dbg_set_bd_addr_cmd_handler(kernel_msg_id_t const msgid, + struct hci_dbg_set_bd_addr_cmd const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + // structure type for the complete command event + struct hci_basic_cmd_cmp_evt *event; + + // Set public address + llm_util_set_public_addr((struct bd_addr *) ¶m->addr); + + // Sends the CC event + event = KERNEL_MSG_ALLOC(HCI_CMD_CMP_EVENT , src_id, HCI_DBG_SET_BD_ADDR_CMD_OPCODE, hci_basic_cmd_cmp_evt); + event->status = COMMON_ERROR_NO_ERROR; + hci_send_2_host(event); + + return (KERNEL_MSG_CONSUMED); +} + +/** + **************************************************************************************** + * @brief Handle the reception of the vendor specific command set crc. + * Write the requested crc in the dedicated registers. + * @param[in] msgid Id of the message received (probably unused). + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (probably unused). + * @param[in] src_id ID of the sending task instance. + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int +hci_dbg_set_crc_cmd_handler(kernel_msg_id_t const msgid, + struct hci_dbg_set_crc_cmd const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + // structure type for the complete command event + struct hci_basic_cmd_cmp_evt *event; + uint16_t conhdl; + + // Check if the command is for the advertising channel or a connection link + if (param->conhdl >= BLE_CONNECTION_MAX) + conhdl = LLD_ADV_HDL; + else + conhdl = param->conhdl; + + // Set the random address in the environment variable + // Initialize the crcinit in the CS + ble_crcinit0_set(conhdl, common_htobs(common_read16p(¶m->crc.crc[0]))); + ble_crcinit1_setf(conhdl,param->crc.crc[2]); + // allocate the status event message + event = KERNEL_MSG_ALLOC(HCI_CMD_CMP_EVENT , src_id, HCI_DBG_SET_CRC_CMD_OPCODE, hci_basic_cmd_cmp_evt); + event->status = COMMON_ERROR_NO_ERROR; + // sends the message + hci_send_2_host(event); + + kernel_state_set(dest_id, DBG_IDLE); + return (KERNEL_MSG_CONSUMED); +} +#if (BLE_PERIPHERAL || BLE_CENTRAL) +/** + **************************************************************************************** + * @brief Handle the reception of the vendor specific command llcp discard. + * Write the requested crc in the dedicated registers. + * @param[in] msgid Id of the message received (probably unused). + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (probably unused). + * @param[in] src_id ID of the sending task instance. + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int +hci_dbg_llcp_discard_cmd_handler(kernel_msg_id_t const msgid, + struct hci_dbg_llcp_discard_cmd const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + // structure type for the complete command event + struct hci_basic_cmd_cmp_evt *event; + + // Set the LLCP discard flag in the LLC environment + llc_util_set_llcp_discard_enable(param->conhdl, param->enable); + + // allocate the status event message + event = KERNEL_MSG_ALLOC(HCI_CMD_CMP_EVENT , src_id, HCI_DBG_LLCP_DISCARD_CMD_OPCODE, hci_basic_cmd_cmp_evt); + event->status = COMMON_ERROR_NO_ERROR; + // sends the message + hci_send_2_host(event); + + return (KERNEL_MSG_CONSUMED); +} + +/** + **************************************************************************************** + * @brief Handle the reception of the vendor specific command write DLE info. + * This command update the default value of the DLE + * + * @note command complete(success) is sent by ROM code. + * + * @param[in] msgid Id of the message received (probably unused). + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (probably unused). + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int +hci_dbg_wr_dle_dft_value_cmd_handler(kernel_msg_id_t const msgid, struct hci_dbg_wr_dle_dft_value_cmd const *param, + kernel_task_id_t const dest_id, kernel_task_id_t const src_id) +{ + + // structure type for the complete command event + struct hci_basic_cmd_cmp_evt *event = KERNEL_MSG_ALLOC(HCI_CMD_CMP_EVENT , src_id, HCI_DBG_WR_DLE_DFT_VALUE_CMD_OPCODE, hci_basic_cmd_cmp_evt); + + if( (param->suppted_max_rx_octets < BLE_MIN_OCTETS ) || (param->suppted_max_rx_octets > BLE_MAX_OCTETS) + || (param->suppted_max_tx_octets < BLE_MIN_OCTETS ) || (param->suppted_max_tx_octets > BLE_MAX_OCTETS) + || (param->suppted_max_rx_time < BLE_MIN_TIME) || (param->suppted_max_rx_time > BLE_MAX_TIME) + || (param->suppted_max_tx_time < BLE_MIN_TIME) || (param->suppted_max_tx_time > BLE_MAX_TIME)) + { + event->status = COMMON_ERROR_INVALID_HCI_PARAM; + } + else + { + + if (param->suppted_max_tx_octets < llm_le_env.data_len_val.conn_initial_max_tx_octets) + llm_le_env.data_len_val.conn_initial_max_tx_octets = param->suppted_max_tx_octets; + + if (param->suppted_max_tx_time < llm_le_env.data_len_val.conn_initial_max_tx_time) + llm_le_env.data_len_val.conn_initial_max_tx_time = param->suppted_max_tx_time; + + llm_le_env.data_len_val.suppted_max_rx_octets = param->suppted_max_rx_octets; + llm_le_env.data_len_val.suppted_max_rx_time = param->suppted_max_rx_time; + llm_le_env.data_len_val.suppted_max_tx_octets = param->suppted_max_tx_octets; + llm_le_env.data_len_val.suppted_max_tx_time = param->suppted_max_tx_time; + // If reason is not valid, returns a CC event with bad status + event->status = COMMON_ERROR_NO_ERROR; + } + hci_send_2_host(event); + + return (KERNEL_MSG_CONSUMED); +} +#endif // #if (BLE_PERIPHERAL || BLE_CENTRAL) +/** + **************************************************************************************** + * @brief Handle the reception of the vendor specific command reset rx counter in the CS. + * @param[in] msgid Id of the message received (probably unused). + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (probably unused). + * @param[in] src_id ID of the sending task instance. + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int +hci_dbg_reset_rx_cnt_cmd_handler(kernel_msg_id_t const msgid, + struct hci_dbg_reset_rx_cnt_cmd const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + // structure type for the complete command event + struct hci_basic_cmd_cmp_evt *event; + + // allocate the status event message + event = KERNEL_MSG_ALLOC(HCI_CMD_CMP_EVENT , src_id, HCI_DBG_RESET_RX_CNT_CMD_OPCODE, hci_basic_cmd_cmp_evt); + ble_rxccmpktcnt0_set((uint8_t)param->conhdl,0); + ble_rxccmpktcnt1_set((uint8_t)param->conhdl,0); + ble_rxccmpktcnt2_set((uint8_t)param->conhdl,0); + event->status = COMMON_ERROR_NO_ERROR; + // sends the message + hci_send_2_host(event); + + return (KERNEL_MSG_CONSUMED); +} + +/** + **************************************************************************************** + * @brief Handle the reception of the vendor specific command reset tx counter in the CS. + * @param[in] msgid Id of the message received (probably unused). + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (probably unused). + * @param[in] src_id ID of the sending task instance. + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int +hci_dbg_reset_tx_cnt_cmd_handler(kernel_msg_id_t const msgid, + struct hci_dbg_reset_tx_cnt_cmd const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + // structure type for the complete command event + struct hci_basic_cmd_cmp_evt *event; + + // allocate the status event message + event = KERNEL_MSG_ALLOC(HCI_CMD_CMP_EVENT , src_id, HCI_DBG_RESET_TX_CNT_CMD_OPCODE, hci_basic_cmd_cmp_evt); + ble_txccmpktcnt0_set((uint8_t)param->conhdl,0); + ble_txccmpktcnt1_set((uint8_t)param->conhdl,0); + ble_txccmpktcnt2_set((uint8_t)param->conhdl,0); + event->status = COMMON_ERROR_NO_ERROR; + // sends the message + hci_send_2_host(event); + + return (KERNEL_MSG_CONSUMED); +} +#if (BLE_OBSERVER || BLE_CENTRAL || BLE_PERIPHERAL) +/** + **************************************************************************************** + * @brief Handle the reception of the vendor specific command Set Tx power Level in CS. + * @param[in] msgid Id of the message received (probably unused). + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (probably unused). + * @param[in] src_id ID of the sending task instance. + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int +hci_dbg_set_tx_pw_cmd_handler (kernel_msg_id_t const msgid, + struct hci_dbg_set_tx_pw_cmd const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + // structure type for the complete command event + struct hci_basic_cmd_cmp_evt *event= KERNEL_MSG_ALLOC(HCI_CMD_CMP_EVENT , src_id, HCI_DBG_SET_TX_PW_CMD_OPCODE, hci_basic_cmd_cmp_evt); + + // Check if the command is for the advertising channel or a connection link + if (param->conhdl > LLD_ADV_HDL) + { + event->status = dbg_task_txpwr_update(param->conhdl, param->pw_lvl); + } + else + { + event->status = COMMON_ERROR_INVALID_HCI_PARAM; + } + + // send the message + hci_send_2_host(event); + + // Go to the IDLE state + kernel_state_set(dest_id, DBG_IDLE); + + return (KERNEL_MSG_CONSUMED); +} +#endif //(BLE_OBSERVER || BLE_CENTRAL || BLE_PERIPHERAL) +#endif //BLE_EMB_PRESENT + +#if (RW_WLAN_COEX) +/** + **************************************************************************************** + * @brief Handle the reception of the vendor specific command wlan coexistence. + * This command set the coexistence state. + * + * @note command complete(success) is sent by ROM code. + * + * @param[in] msgid Id of the message received (probably unused). + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (probably unused). + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int +hci_dbg_wlan_coex_cmd_handler(kernel_msg_id_t const msgid, struct hci_dbg_wlan_coex_cmd const *param, + kernel_task_id_t const dest_id, kernel_task_id_t const src_id) +{ + // structure type for the complete command event + struct hci_basic_cmd_cmp_evt *event = KERNEL_MSG_ALLOC(HCI_CMD_CMP_EVENT , src_id, HCI_DBG_WLAN_COEX_CMD_OPCODE, hci_basic_cmd_cmp_evt); + + rwip_wlcoex_set(param->state); + + // If reason is not valid, returns a CC event with bad status + event->status = COMMON_ERROR_NO_ERROR; + hci_send_2_host(event); + + return (KERNEL_MSG_CONSUMED); +} + +#if (RW_WLAN_COEX_TEST) +/** + **************************************************************************************** + * @brief Handle the reception of the vendor specific command wlan coexistence. + * This command set the coexistence state. + * + * @note command complete(success) is sent by ROM code. + * + * @param[in] msgid Id of the message received (probably unused). + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (probably unused). + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int +hci_dbg_wlan_coextst_scen_cmd_handler(kernel_msg_id_t const msgid, struct hci_dbg_wlan_coextst_scen_cmd const *param, + kernel_task_id_t const dest_id, kernel_task_id_t const src_id) +{ + + // structure type for the complete command event + struct hci_basic_cmd_cmp_evt *event = KERNEL_MSG_ALLOC(HCI_CMD_CMP_EVENT , src_id, HCI_DBG_WLAN_COEXTST_SCEN_CMD_OPCODE, hci_basic_cmd_cmp_evt); + + event->status = dbg_wlcoex_scen_set(param->scenario); + + // sends the message + hci_send_2_host(event); + + return (KERNEL_MSG_CONSUMED); +} +#endif //RW_WLAN_COEX_TEST +#endif //RW_WLAN_COEX + +#if (RW_MWS_COEX) +/** + **************************************************************************************** + * @brief Handle the reception of the vendor specific command mws coexistence. + * This command set the coexistence state. + * + * @note command complete(success) is sent by ROM code. + * + * @param[in] msgid Id of the message received (probably unused). + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (probably unused). + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int +hci_dbg_mws_coex_cmd_handler(kernel_msg_id_t const msgid, struct hci_dbg_mws_coex_cmd const *param, + kernel_task_id_t const dest_id, kernel_task_id_t const src_id) +{ + + // structure type for the complete command event + struct hci_basic_cmd_cmp_evt *event = KERNEL_MSG_ALLOC(HCI_CMD_CMP_EVENT , src_id, HCI_DBG_MWS_COEX_CMD_OPCODE, hci_basic_cmd_cmp_evt); + + rwip_mwscoex_set(param->state); + + // If reason is not valid, returns a CC event with bad status + event->status = COMMON_ERROR_NO_ERROR; + hci_send_2_host(event); + + return (KERNEL_MSG_CONSUMED); +} + +#if (RW_MWS_COEX_TEST) +/** + **************************************************************************************** + * @brief Handle the reception of the vendor specific command mws coexistence. + * This command set the coexistence state. + * + * @note command complete(success) is sent by ROM code. + * + * @param[in] msgid Id of the message received (probably unused). + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (probably unused). + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int +hci_dbg_mws_coextst_scen_cmd_handler(kernel_msg_id_t const msgid, struct hci_dbg_mws_coextst_scen_cmd const *param, + kernel_task_id_t const dest_id, kernel_task_id_t const src_id) +{ + + // structure type for the complete command event + struct hci_basic_cmd_cmp_evt *event = KERNEL_MSG_ALLOC(HCI_CMD_CMP_EVENT , src_id, HCI_DBG_MWS_COEXTST_SCEN_CMD_OPCODE, hci_basic_cmd_cmp_evt); + + event->status = dbg_mwscoex_scen_set(param->scenario); + + // sends the message + hci_send_2_host(event); + + return (KERNEL_MSG_CONSUMED); +} +#endif //RW_MWS_COEX_TEST +#endif //RW_MWS_COEX + +#if (BLE_EMB_PRESENT) +#if (BLE_AUDIO) +/** + **************************************************************************************** + * @brief Handle the reception of the vendor specific command configure + * audio link request. + * + * @param[in] msgid Id of the message received (probably unused). + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (probably unused). + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int +hci_vs_audio_configure_cmd_handler(kernel_msg_id_t const msgid, struct hci_vs_audio_configure_cmd const *param, + kernel_task_id_t const dest_id, kernel_task_id_t const src_id) +{ + // structure type for the complete command event + struct hci_basic_conhdl_cmd_cmp_evt *event = + KERNEL_MSG_ALLOC(HCI_CMD_CMP_EVENT , param->conhdl, msgid, hci_basic_conhdl_cmd_cmp_evt); + + event->status = audio_configure(param->voice_channel,(struct audio_configure_tag*)¶m->tx_size); + event->conhdl = param->conhdl; + + // sends the message + hci_send_2_host(event); + + return (KERNEL_MSG_CONSUMED); +} +/** + **************************************************************************************** + * @brief Handle the reception of the vendor specific command configure + * audio link request. + * + * @param[in] msgid Id of the message received (probably unused). + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (probably unused). + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int +hci_vs_audio_set_pointer_cmd_handler(kernel_msg_id_t const msgid, struct hci_vs_audio_set_pointer_cmd const *param, + kernel_task_id_t const dest_id, kernel_task_id_t const src_id) +{ + // structure type for the complete command event + struct hci_basic_conhdl_cmd_cmp_evt *event = + KERNEL_MSG_ALLOC(HCI_CMD_CMP_EVENT , param->conhdl, msgid, hci_basic_conhdl_cmd_cmp_evt); + + event->status = audio_set_pointer(param->voice_channel,param->rx_tx_select,param->tog,param->em_ptr); + event->conhdl = param->conhdl; + + // sends the message + hci_send_2_host(event); + + return (KERNEL_MSG_CONSUMED); +} + +/** + **************************************************************************************** + * @brief Handle the reception of the vendor specific command configure + * audio link request. + * + * @param[in] msgid Id of the message received (probably unused). + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (probably unused). + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int +hci_vs_audio_get_buffer_range_cmd_handler(kernel_msg_id_t const msgid, struct hci_vs_audio_get_buffer_range_cmd const *param, + kernel_task_id_t const dest_id, kernel_task_id_t const src_id) +{ + // structure type for the complete command event + struct hci_vs_audio_get_buffer_range_cmd_cmp_evt *event = + KERNEL_MSG_ALLOC(HCI_CMD_CMP_EVENT, 0, msgid, hci_vs_audio_get_buffer_range_cmd_cmp_evt); + + event->status = audio_get_buffer_range(param->rx_tx_select,&event->base_address,&event->end_address); + + // sends the message + hci_send_2_host(event); + + return (KERNEL_MSG_CONSUMED); +} +/** + **************************************************************************************** + * @brief Handle the reception of the vendor specific command set + * audio link mode request. + * + * @param[in] msgid Id of the message received (probably unused). + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (probably unused). + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int +hci_vs_audio_set_mode_cmd_handler(kernel_msg_id_t const msgid, struct hci_vs_audio_set_mode_cmd const *param, + kernel_task_id_t const dest_id, kernel_task_id_t const src_id) +{ + // structure type for the complete command event + struct hci_basic_conhdl_cmd_cmp_evt *event = + KERNEL_MSG_ALLOC(HCI_CMD_CMP_EVENT , param->conhdl, msgid, hci_basic_conhdl_cmd_cmp_evt); + + event->status = audio_set_mode(param->voice_channel,param->mode); + event->conhdl = param->conhdl; + + // sends the message + hci_send_2_host(event); + + return (KERNEL_MSG_CONSUMED); +} + + +/** + **************************************************************************************** + * @brief Handle the reception of the vendor specific command set + * audio link mode request. + * + * @param[in] msgid Id of the message received (probably unused). + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (probably unused). + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int +hci_vs_audio_reset_cmd_handler(kernel_msg_id_t const msgid, struct hci_vs_audio_reset_cmd const *param, + kernel_task_id_t const dest_id, kernel_task_id_t const src_id) +{ + // structure type for the complete command event + struct hci_basic_conhdl_cmd_cmp_evt *event = + KERNEL_MSG_ALLOC(HCI_CMD_CMP_EVENT , param->conhdl, msgid, hci_basic_conhdl_cmd_cmp_evt); + + event->status = audio_reset(param->voice_channel); + event->conhdl = param->conhdl; + + // sends the message + hci_send_2_host(event); + + return (KERNEL_MSG_CONSUMED); +} + +/** + **************************************************************************************** + * @brief Handle the reception of the vendor specific command set + * audio link mode request. + * + * @param[in] msgid Id of the message received (probably unused). + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (probably unused). + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int +hci_vs_audio_allocate_cmd_handler(kernel_msg_id_t const msgid, struct hci_vs_audio_allocate_cmd const *param, + kernel_task_id_t const dest_id, kernel_task_id_t const src_id) +{ + // structure type for the complete command event + struct hci_vs_audio_allocate_cmd_cmp_evt *event = + KERNEL_MSG_ALLOC(HCI_CMD_CMP_EVENT, param->conhdl, msgid, hci_vs_audio_allocate_cmd_cmp_evt); + uint8_t voice_channel; + event->status = audio_allocate(param->conhdl, AUDIO_MODE_0, &voice_channel); + event->voice_channel = voice_channel; + event->conhdl = param->conhdl; + + // sends the message + hci_send_2_host(event); + + return (KERNEL_MSG_CONSUMED); +} +#endif // (BLE_AUDIO) +#endif //BLE_EMB_PRESENT + +/// The message handlers for HCI command complete events +static const struct kernel_msg_handler dbg_hci_command_handler_tab[] = +{ + {HCI_DBG_RD_MEM_CMD_OPCODE, (kernel_msg_func_t)hci_dbg_rd_mem_cmd_handler}, + {HCI_DBG_WR_MEM_CMD_OPCODE, (kernel_msg_func_t)hci_dbg_wr_mem_cmd_handler}, + {HCI_DBG_DEL_PAR_CMD_OPCODE, (kernel_msg_func_t)hci_dbg_del_par_cmd_handler}, + {HCI_DBG_ID_FLASH_CMD_OPCODE, (kernel_msg_func_t)hci_dbg_id_flash_cmd_handler}, + {HCI_DBG_ER_FLASH_CMD_OPCODE, (kernel_msg_func_t)hci_dbg_er_flash_cmd_handler}, + {HCI_DBG_WR_FLASH_CMD_OPCODE, (kernel_msg_func_t)hci_dbg_wr_flash_cmd_handler}, + {HCI_DBG_RD_FLASH_CMD_OPCODE, (kernel_msg_func_t)hci_dbg_rd_flash_cmd_handler}, + {HCI_DBG_RD_PAR_CMD_OPCODE, (kernel_msg_func_t)hci_dbg_rd_par_cmd_handler}, + {HCI_DBG_WR_PAR_CMD_OPCODE, (kernel_msg_func_t)hci_dbg_wr_par_cmd_handler}, + {HCI_DBG_RD_KERNEL_STATS_CMD_OPCODE, (kernel_msg_func_t)hci_dbg_rd_kernel_stats_cmd_handler}, + {HCI_DBG_RF_REG_RD_CMD_OPCODE, (kernel_msg_func_t)hci_dbg_rf_reg_rd_cmd_handler}, + {HCI_DBG_RF_REG_WR_CMD_OPCODE, (kernel_msg_func_t)hci_dbg_rf_reg_wr_cmd_handler}, + {HCI_DBG_PLF_RESET_CMD_OPCODE, (kernel_msg_func_t)hci_dbg_plf_reset_cmd_handler}, + #if (BLE_EMB_PRESENT) + {HCI_DBG_HW_REG_RD_CMD_OPCODE, (kernel_msg_func_t)hci_dbg_hw_reg_rd_cmd_handler}, + {HCI_DBG_HW_REG_WR_CMD_OPCODE, (kernel_msg_func_t)hci_dbg_hw_reg_wr_cmd_handler}, + {HCI_DBG_SET_BD_ADDR_CMD_OPCODE, (kernel_msg_func_t)hci_dbg_set_bd_addr_cmd_handler}, + {HCI_DBG_SET_CRC_CMD_OPCODE, (kernel_msg_func_t)hci_dbg_set_crc_cmd_handler}, + #if (BLE_PERIPHERAL || BLE_CENTRAL) + {HCI_DBG_LLCP_DISCARD_CMD_OPCODE, (kernel_msg_func_t)hci_dbg_llcp_discard_cmd_handler}, + #endif // #if (BLE_PERIPHERAL || BLE_CENTRAL) + {HCI_DBG_RESET_RX_CNT_CMD_OPCODE, (kernel_msg_func_t)hci_dbg_reset_rx_cnt_cmd_handler}, + {HCI_DBG_RESET_TX_CNT_CMD_OPCODE, (kernel_msg_func_t)hci_dbg_reset_tx_cnt_cmd_handler}, + #if (BLE_OBSERVER || BLE_CENTRAL || BLE_PERIPHERAL) + {HCI_DBG_SET_TX_PW_CMD_OPCODE, (kernel_msg_func_t)hci_dbg_set_tx_pw_cmd_handler}, + #endif //(BLE_OBSERVER || BLE_CENTRAL || BLE_PERIPHERAL) + #endif //BLE_EMB_PRESENT + #if (RW_WLAN_COEX) + {HCI_DBG_WLAN_COEX_CMD_OPCODE, (kernel_msg_func_t)hci_dbg_wlan_coex_cmd_handler}, + #if (RW_WLAN_COEX_TEST) + {HCI_DBG_WLAN_COEXTST_SCEN_CMD_OPCODE, (kernel_msg_func_t)hci_dbg_wlan_coextst_scen_cmd_handler}, + #endif //RW_WLAN_COEX_TEST + #endif //RW_WLAN_COEX + #if (RW_MWS_COEX) + {HCI_DBG_MWS_COEX_CMD_OPCODE, (kernel_msg_func_t)hci_dbg_mws_coex_cmd_handler}, + #if (RW_MWS_COEX_TEST) + {HCI_DBG_MWS_COEXTST_SCEN_CMD_OPCODE, (kernel_msg_func_t)hci_dbg_mws_coextst_scen_cmd_handler}, + #endif //RW_MWS_COEX_TEST + #endif //RW_MWS_COEX + {HCI_DBG_RD_MEM_INFO_CMD_OPCODE, (kernel_msg_func_t)hci_dbg_rd_mem_info_cmd_handler}, + #if (BLE_EMB_PRESENT) + #if (BLE_PERIPHERAL || BLE_CENTRAL) + {HCI_DBG_WR_DLE_DFT_VALUE_CMD_OPCODE, (kernel_msg_func_t)hci_dbg_wr_dle_dft_value_cmd_handler}, + #if(BLE_AUDIO) + {HCI_VS_AUDIO_ALLOCATE_CMD_OPCODE, (kernel_msg_func_t)hci_vs_audio_allocate_cmd_handler}, + {HCI_VS_AUDIO_CONFIGURE_CMD_OPCODE, (kernel_msg_func_t)hci_vs_audio_configure_cmd_handler}, + {HCI_VS_AUDIO_SET_MODE_CMD_OPCODE, (kernel_msg_func_t)hci_vs_audio_set_mode_cmd_handler}, + {HCI_VS_AUDIO_RESET_CMD_OPCODE, (kernel_msg_func_t)hci_vs_audio_reset_cmd_handler}, + {HCI_VS_AUDIO_SET_POINTER_CMD_OPCODE, (kernel_msg_func_t)hci_vs_audio_set_pointer_cmd_handler}, + {HCI_VS_AUDIO_GET_BUFFER_RANGE_CMD_OPCODE, (kernel_msg_func_t)hci_vs_audio_get_buffer_range_cmd_handler}, + #endif // #if (BLE_AUDIO) + #endif // #if (BLE_PERIPHERAL || BLE_CENTRAL) + #endif +}; + +/** + **************************************************************************************** + * @brief Handles any HCI command + * + * @param[in] msgid Id of the message received (probably unused). + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (probably unused). + * @param[in] src_id ID of the sending task instance. + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int +hci_command_handler(kernel_msg_id_t const msgid, + void const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + int return_status = KERNEL_MSG_CONSUMED; + + // Check if there is a handler corresponding to the original command opcode + for(int i = 0; i < (sizeof(dbg_hci_command_handler_tab)/sizeof(dbg_hci_command_handler_tab[0])); i++) + { + // Check if opcode matches + if(dbg_hci_command_handler_tab[i].id == src_id) + { + // Check if there is a handler function + if(dbg_hci_command_handler_tab[i].func != NULL) + { + // Call handler + return_status = dbg_hci_command_handler_tab[i].func(src_id, param, dest_id, src_id); + } + break; + } + } + + return return_status; +} + +/* + * TASK DESCRIPTOR DEFINITIONS + **************************************************************************************** + */ + +/// Specifies the message handlers that are common to all states. +static const struct kernel_msg_handler dbg_default_state[] = +{ + {HCI_COMMAND, (kernel_msg_func_t)hci_command_handler}, +}; + +/// Specifies the message handlers that are common to all states. +const struct kernel_state_handler dbg_default_handler = KERNEL_STATE_HANDLER(dbg_default_state); + +/// Defines the placeholder for the states of all the task instances. +kernel_state_t dbg_state[DBG_IDX_MAX]; + +#endif // (RW_DEBUG && (BT_EMB_PRESENT || BLE_EMB_PRESENT)) +/// @} DBGTASK diff --git a/beken_os/beken378/driver/ble/ble_pub/modules/ecc_p256/api/ecc_p256.h b/beken_os/beken378/driver/ble/ble_pub/modules/ecc_p256/api/ecc_p256.h new file mode 100755 index 0000000..41947f8 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/modules/ecc_p256/api/ecc_p256.h @@ -0,0 +1,129 @@ +/** + **************************************************************************************** + * + * @file ecc_p256.h + * + * @brief ECC functions for P256 + * + * Copyright (C) RivieraWaves 2009-2015 + * + **************************************************************************************** + */ + +#ifndef ECC_P256_H_ +#define ECC_P256_H_ + + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_config.h" +#if (SECURE_CONNECTIONS) + +#include +#include +#include "kernel_task.h" + +/* + * DEFINES + **************************************************************************************** + */ +//#define CFG_ECC_SIM_ACCEL + +#define ECC_4BIT_WIN_OPT 0 + +#define ECC_PUBLICKEY_GENERATION 0x01 +#define ECC_DHKEY_GENERATION 0x02 +#define ECC_4BIT_TABLE_GENERATION_PT1 0x03 +#define ECC_4BIT_TABLE_GENERATION_PT2 0x04 +#define ECC_DHKEY_GENERATION_USING_TABLE 0x05 + + +/* + * STRUCTURE DEFINITIONS + **************************************************************************************** + */ + +/// Multiplication result message structure +struct ecc_result_ind +{ + uint8_t key_res_x[32]; + uint8_t key_res_y[32]; +}; + + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * Initialize Elliptic Curve algorithm + **************************************************************************************** + */ +void ecc_init(bool reset); + +/** + **************************************************************************************** + * @brief Generate a Secret Key compliant with ECC P256 algorithm + * + * If key is forced, just check its validity + * + * @param[out] secret_key Private key - MSB First + * @param[in] forced True if provided key is forced, else generate it. + **************************************************************************************** + */ +void ecc_gen_new_secret_key(uint8_t* secret_key, bool forced); + +/** + **************************************************************************************** + * @brief Generate a new Public key pair using ECC P256 algorithm + * + * @param[in] secret_key Private key - MSB First + * @param[in] blocking Force to run full algorithm without continue mode + **************************************************************************************** + */ +void ecc_gen_new_public_key(uint8_t* secret_key256, kernel_msg_id_t msg_id, kernel_task_id_t task_id); + +/** + **************************************************************************************** + * @brief Generate a new DHKey using ECC P256 algorithm + * + * @param[in] secret_key Private key - MSB First + * @param[in] pub_key_x Peer public key x coordinate - LSB First + * @param[in] pub_key_y Peer public key y coordinate - LSB First + * @param[in] msg_id Message task ID for the result indication + * @param[in] task_id Client task ID (Task type + instance) + **************************************************************************************** + */ +#if (ECC_4BIT_WIN_OPT==1) +uint8_t ecc_generate_key256(uint8_t key_type, const uint8_t *secret_key, const uint8_t *public_key_x, const uint8_t *public_key_y, kernel_msg_id_t msg_id, kernel_task_id_t task_id); +#else +uint8_t ecc_generate_key256(const uint8_t *secret_key, const uint8_t *public_key_x, const uint8_t *public_key_y, kernel_msg_id_t msg_id, kernel_task_id_t task_id); +#endif + +/** + **************************************************************************************** + * @brief Abort a current DHKey generation procedure + * + * @param[in] task_id Client task ID (Task type + instance) + **************************************************************************************** + */ +void ecc_abort_key256_generation(kernel_task_id_t task_id); + +/** + **************************************************************************************** + * @brief Retrieve debug private and public keys + * + * @param[out] secret_key Private key - MSB First + * @param[out] pub_key_x Public key x coordinate - LSB First + * @param[out] pub_key_y Public key y coordinate - LSB First + **************************************************************************************** + */ +void ecc_get_debug_Keys(uint8_t *secret_key, uint8_t *pub_key_x, uint8_t *pub_key_y); +#endif // (SECURE_CONNECTIONS) + + +#endif /* ECC_P256_H_ */ diff --git a/beken_os/beken378/driver/ble/ble_pub/modules/ecc_p256/src/ecc_p256.c b/beken_os/beken378/driver/ble/ble_pub/modules/ecc_p256/src/ecc_p256.c new file mode 100755 index 0000000..da14490 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/modules/ecc_p256/src/ecc_p256.c @@ -0,0 +1,2851 @@ +/** + **************************************************************************************** + * + * @file ecc_p256.h + * + * @brief ECC function definitions for P256 + * + * Copyright (C) RivieraWaves 2009-2015 + * + **************************************************************************************** + */ + + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" +#if (SECURE_CONNECTIONS) + +#include "ecc_p256.h" +#include +#include +#include +#include +#include "architect.h" + +#include "kernel_mem.h" +#include "common_math.h" +#include "common_utils.h" +#include "common_list.h" +#include "kernel_event.h" + +#include "dbg_swdiag.h" // Software diag + +/* + * DEFINES + **************************************************************************************** + */ + +#define __INLINE__ __INLINE + + +/********************************************************************************* + * The length of P256 numbers stored. + * P256 numbers are stored in uint_32 arrays, with one more element than required. + * The extra element is used to store overflow's and thus simplify addition, subtraction + * + *********************************************************************************/ +#if (ECC_MULT_ALGO_TYPE == 16) +#define MAX_OCTETS256 34 +#define MAX_DIGITS_256 68 // ( (9+9) * 4 ) +#define ELEMENTS_BIG_HEX256 (MAX_OCTETS256/2) // 17 +#define HIGHEST_INDEX_BIG_HEX256 ELEMENTS_BIG_HEX256 - 1 // 16 +#elif (ECC_MULT_ALGO_TYPE == 32) +#define MAX_OCTETS256 36 +#define MAX_DIGITS_256 72 // ( (9+9) * 4 ) +#define ELEMENTS_BIG_HEX256 (MAX_OCTETS256/4) // 9 +#define HIGHEST_INDEX_BIG_HEX256 (MAX_OCTETS256/4 )- 1 // 8 +#else +#error "ECC Multiplication Algorithm configuration Not Supported" +#endif // (ECC_MULT_ALGO_TYPE == 16) + +/* + * MACROS + **************************************************************************************** + */ + +/********************************************************************** + * Typedef and macro for 64 bit number handling + **********************************************************************/ + +#define _LL(x) x##ll + +/************************************************************************************ + * Simple Macros to determine + * a/ if a 'big hex number' is even. + * b/ get the most significant uint32 element + ************************************************************************************/ +#define ISBIGHEXEVEN256(x) (!((x.num[HIGHEST_INDEX_BIG_HEX256]) & 0x01)) + +#if (ECC_MULT_ALGO_TYPE == 16) +#define GETMOSTSIGNIGICANTU16_256(tmpHexA) tmpHexA->num[ELEMENTS_BIG_HEX256-tmpHexA->len] +#elif (ECC_MULT_ALGO_TYPE == 32) +#define GETMOSTSIGNIGICANTU32_256(tmpHexA) tmpHexA->num[ELEMENTS_BIG_HEX256-tmpHexA->len] +#endif // (ECC_MULT_ALGO_TYPE == 16) + + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + +typedef unsigned long long int u64; + +typedef uint8_t u_int8; +typedef uint16_t u_int16; +typedef uint32_t u_int32; +typedef bool boolean; + +/* + * Signed types + */ + +typedef signed char s_int8; +typedef signed short s_int16; +typedef signed int s_int32; + +#if (ECC_MULT_ALGO_TYPE == 16) + +typedef struct bigHex256 +{ + u_int16 num[MAX_OCTETS256 / 2]; + u_int32 len; + u_int32 sign; +} bigHex256; + +typedef struct veryBigHex256 +{ + u_int16 num[MAX_OCTETS256 / 1]; + u_int32 len; + u_int32 sign; +} veryBigHex256; + + +#elif (ECC_MULT_ALGO_TYPE == 32) +typedef struct bigHex256 +{ + u_int32 num[MAX_OCTETS256 / 4]; + u_int32 len; + u_int32 sign; +} bigHex256; + +typedef struct veryBigHex256 +{ + u_int32 num[MAX_OCTETS256 / 2]; + u_int32 len; + u_int32 sign; +} veryBigHex256; + +#endif // (ECC_MULT_ALGO_TYPE == 16) + +typedef struct ECC_Point256 +{ + bigHex256 x; + bigHex256 y; +} ECC_Point256; + +typedef struct ECC_Jacobian_Point256 +{ + bigHex256 x; + bigHex256 y; + bigHex256 z; +} ECC_Jacobian_Point256; + + + +/// ECC multiplication element +struct ecc_elt_tag +{ + /// List element for chaining in the ECC environment + struct common_list_hdr hdr; + + u_int32 Point_Mul_Word256; + + // ECC points Q and R in Jacobian format. + ECC_Jacobian_Point256 Jacobian_PointQ256; + ECC_Jacobian_Point256 Jacobian_PointR256; + + // The Private/Secret Key used during calculations + bigHex256 Pk256; + + /// Return message identifier + kernel_msg_id_t msg_id; + /// Client task identifier + kernel_task_id_t client_id; + +#if (ECC_MULT_ALGO_TYPE == 16) + uint16_t current_val; + uint16_t bit_cursor; +#elif (ECC_MULT_ALGO_TYPE == 32) + uint32_t current_val; + uint32_t bit_cursor; +#endif // (ECC_MULT_ALGO_TYPE == 16) +#if (ECC_4BIT_WIN_OPT==1) + uint8_t key_type; + ECC_Jacobian_Point256 *win_4_table; +#endif +}; + + +/// ECC environment structure +struct ecc_env_tag +{ + /// List of ongoing multiplications + struct common_list ongoing_mul; +}; + + +/* + * GLOBAL VARIABLE DEFINITIONS + **************************************************************************************** + */ + + +/***************************************************************************** + * CONSTs REQUIRED FOR ECC P256 + ****************************************************************************/ + +// Base Points for the ECC P256 Curve. - LSB first +const u_int8 BasePoint_x_256[32] = {0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4, 0xA0, 0x33, 0xEB, 0x2D, 0x81, 0x7D, 0x03, 0x77, 0xF2, 0x40, 0xA4, 0x63, 0xE5, 0xE6, 0xBC, 0xF8, 0x47, 0x42, 0x2C, 0xE1, 0xF2, 0xD1, 0x17, 0x6B}; +const u_int8 BasePoint_y_256[32] = {0xF5, 0x51, 0xBF, 0x37, 0x68, 0x40, 0xB6, 0xCB, 0xCE, 0x5E, 0x31, 0x6B, 0x57, 0x33, 0xCE, 0x2B, 0x16, 0x9E, 0x0F, 0x7C, 0x4A, 0xEB, 0xE7, 0x8E, 0x9B, 0x7F, 0x1A, 0xFE, 0xE2, 0x42, 0xE3, 0x4F}; +// Maximum Secret Key Value - LSB first +const u_int8 maxSecretKey_256[32] = {0xA8, 0x92, 0x31, 0x7E, 0x61, 0xe5, 0xdc, 0x79, 0x42, 0xcf, 0x8b, 0xd3, 0x56, 0x7d, 0x73, 0xde, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x7f}; +// Debug Public Keys - used when SSP debug mode is enabled - LSB first +const u_int8 DebugE256PublicKey_x[32] = {0xE6, 0x9D, 0x35, 0x0E, 0x48, 0x01, 0x03, 0xCC, 0xDB, 0xFD, 0xF4, 0xAC, 0x11, 0x91, 0xF4, 0xEF, 0xB9, 0xA5, 0xF9, 0xE9, 0xA7, 0x83, 0x2C, 0x5E, 0x2C, 0xBE, 0x97, 0xF2, 0xD2, 0x03, 0xB0, 0x20}; +const u_int8 DebugE256PublicKey_y[32] = {0x8B, 0xD2, 0x89, 0x15, 0xD0, 0x8E, 0x1C, 0x74, 0x24, 0x30, 0xED, 0x8F, 0xC2, 0x45, 0x63, 0x76, 0x5C, 0x15, 0x52, 0x5A, 0xBF, 0x9A, 0x32, 0x63, 0x6D, 0xEB, 0x2A, 0x65, 0x49, 0x9C, 0x80, 0xDC}; +// Debug Private Key - used when SSP debug mode is enabled - LSB first +const u_int8 DebugE256SecretKey[32] = {0xBD, 0x1A, 0x3C, 0xCD, 0xA6, 0xB8, 0x99, 0x58, 0x99, 0xB7, 0x40, 0xEB, 0x7B, 0x60, 0xFF, 0x4A, 0x50, 0x3F, 0x10, 0xD2, 0xE3, 0xB3, 0xC9, 0x74, 0x38, 0x5F, 0xC5, 0xA3, 0xD4, 0xF6, 0x49, 0x3F}; + + +#if (ECC_MULT_ALGO_TYPE == 16) +const bigHex256 coef_B = {{ 0x0000, 0x5ac6, 0x35d8, 0xaa3a, 0x93e7, 0xb3eb, 0xbd55, 0x7698, 0x86bc, 0x651d, 0x06b0, 0xcc53, 0xb0f6, 0x3bce, 0x3c3e, 0x27d2, 0x604b}, + 16, 0 +}; +#else +const bigHex256 coef_B = {{ 0x0000, 0x5ac635d8, 0xaa3a93e7, 0xb3ebbd55, 0x769886bc, 0x651d06b0, 0xcc53b0f6, 0x3bce3c3e, 0x27d2604b}, + 8, 0 +}; +#endif + + + +#if (ECC_MULT_ALGO_TYPE == 16) +// Value P which is used in mod operations to reflect points back into the Galois Field of the curve. +const bigHex256 bigHexP256 = {{ 0x0000, 0xFFFF, 0xFFFF, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF}, + 16, 0 +}; + + +const veryBigHex256 veryBigHexP256 = +{ + { + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0xFFFF, 0xFFFF, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF + }, + 16, 0 +}; + +// Point of infinity in the Jacobian system +const ECC_Jacobian_Point256 ecc_Jacobian_InfinityPoint256 = { {{0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, 0x00, 0x00}, + {{0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001 }, 0x01, 0x00}, + {{0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }, 0x00, 0x00} +}; + + +#elif (ECC_MULT_ALGO_TYPE == 32) +// Value P which is used in mod operations to reflect points back into the Galois Field of the curve. +const bigHex256 bigHexP256 = {{ 0x00000000, 0xFFFFFFFF, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}, + 8, 0 +}; +const veryBigHex256 veryBigHexP256 = +{ + { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0xFFFFFFFF, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF + }, + 8, 0 +}; + +// Point of infinity in the Jacobian system +const ECC_Jacobian_Point256 ecc_Jacobian_InfinityPoint256 = { {{0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, 0x00, 0x00}, + {{0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001 }, 0x01, 0x00}, + {{0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, 0x00, 0x00} +}; +#endif // (ECC_MULT_ALGO_TYPE == 16) + + +#if (ECC_4BIT_WIN_OPT==1) + +#if (ECC_MULT_ALGO_TYPE == 16) +const ECC_Jacobian_Point256 ECC_4Win_Look_up_table[15] = +{ +//0x0001 + { + /* num */ + /* x */ {{ 0x0000, 0x6b17, 0xd1f2, 0xe12c, 0x4247, 0xf8bc, 0xe6e5, 0x63a4, 0x40f2, 0x7703, 0x7d81, 0x2deb, 0x33a0, 0xf4a1, 0x3945, 0xd898, 0xc296 }, 16, 0x00}, + /* y */ {{ 0x0000, 0x4fe3, 0x42e2, 0xfe1a, 0x7f9b, 0x8ee7, 0xeb4a, 0x7c0f, 0x9e16, 0x2bce, 0x3357, 0x6b31, 0x5ece, 0xcbb6, 0x4068, 0x37bf, 0x51f5 }, 16, 0x00}, + /* Z */ {{ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001 }, 1, 0x00} + }, +//0x0002 + { + /* num */ + /* x */ {{ 0x0000, 0x8f22, 0x8205, 0x98a6, 0x0fe3, 0xc582, 0xa4e4, 0xe495, 0xf299, 0x7b48, 0xa1de, 0x9650, 0x59a9, 0x18c3, 0xc50b, 0xb251, 0xa29d }, 16, 0x00}, + /* y */ {{ 0x0000, 0x468a, 0xb3e5, 0x1fcb, 0x4722, 0x9871, 0xe7e9, 0x5bf2, 0x8286, 0xcd44, 0x8ed3, 0xeb0c, 0x78ec, 0xd34e, 0xac12, 0x1d28, 0x5bc2 }, 16, 0x00}, + /* z */ {{ 0x0000, 0xc297, 0x492c, 0x20cc, 0xe496, 0x6ae2, 0xcd2b, 0x58b7, 0x5e48, 0xffbd, 0x5489, 0x95ef, 0x960d, 0x41e2, 0x74dc, 0x1e5b, 0x3ed6 }, 16, 0x00} + }, +//0x0003 + { + /* num */ + /* x */ {{ 0x0000, 0x0bad, 0x26fb, 0xd93b, 0x1ab7, 0xe844, 0x8e98, 0xe098, 0xc19f, 0x90e3, 0x156a, 0x94ae, 0x76e3, 0x56e8, 0xbcaa, 0x5d21, 0x0197 }, 16, 0x00}, + /* y */ {{ 0x0000, 0x4a1d, 0x6bbe, 0xdf46, 0xa06f, 0x7d76, 0x1828, 0x7a69, 0xfd83, 0x346c, 0x8ed1, 0xef77, 0x4189, 0xb0e3, 0x6138, 0x55bd, 0x8d83 }, 16, 0x00}, + /* Z */ {{ 0x0000, 0x3093, 0x9029, 0xdb21, 0x4543, 0x2131, 0x3957, 0xaec9, 0xc854, 0xa4b2, 0x3170, 0xb0ce, 0xe4c4, 0x6f2e, 0xc46c, 0xdf0d, 0x9342 }, 16, 0x00} + }, +// 0x0004 + { + /* num */ + /* x */ {{ 0x0000, 0xe1aa, 0x8f71, 0x41bf, 0xe1ed, 0x0ab4, 0x8559, 0x9b57, 0x79eb, 0xec8b, 0x9353, 0x3c5b, 0xde62, 0x423d, 0xf00d, 0x2b1c, 0xb5f2 }, 16, 0x00}, + /* y */ {{ 0x0000, 0xd2f1, 0x22ef, 0x8038, 0x5047, 0x8290, 0xab2a, 0x6277, 0x71ec, 0x4ecc, 0xef63, 0x34a3, 0xd343, 0xc0a9, 0xf7e6, 0x5610, 0x3895 }, 16, 0x00}, + /* z */ {{ 0x0000, 0x9182, 0xb500, 0x3bc1, 0xda72, 0xe3be, 0x14e0, 0xfb0c, 0x2593, 0x3305, 0x22bd, 0x8332, 0x6ee2, 0xe245, 0x7d8e, 0x6de1, 0x783e }, 16, 0x00}, + }, +//0x0005 + { + /* num */ + /* x */ {{ 0x0000, 0x6a14, 0x0c55, 0x70ae, 0x60a6, 0x1eab, 0x131d, 0xf0a7, 0xb995, 0x5ca5, 0x2eee, 0x3a03, 0xb007, 0xa6fc, 0x97e6, 0x0ddc, 0xd000}, 16, 0x00}, + /* y */ {{ 0x0000, 0x3266, 0x5be0, 0xdea1, 0x11a9, 0xf1de, 0x8948, 0xb015, 0x14c3, 0x6e69, 0x3bab, 0xf68c, 0x4db9, 0xed63, 0x07a3, 0xe9ec, 0x3df5}, 16, 0x00}, + /* z */ {{ 0x0000, 0xc53b, 0xb6c4, 0x0c02, 0x8674, 0xca4d, 0xbb66, 0x2166, 0x24f8, 0x9394, 0x09db, 0x2e75, 0xd7fa, 0x62d4, 0xb5e6, 0xa887, 0x0ac3}, 16, 0x00} + }, +//0x0006 + { + /* num */ + /* x */ {{ 0x0000, 0xcca1, 0x5363, 0x5063, 0x27c1, 0xcb6a, 0x22b4, 0x5277, 0xe102, 0x2794, 0x82b5, 0xedc0, 0xaff9, 0xa43c, 0x31e5, 0xee4c, 0x7f21}, 16, 0x00}, + /* y */ {{ 0x0000, 0x5f70, 0x6301, 0x91f1, 0xe4f4, 0xa011, 0xb402, 0x2042, 0x3775, 0xf79c, 0x950c, 0x421d, 0xf6a0, 0x03e8, 0x67c6, 0x4d00, 0xc6a6}, 16, 0x00}, + /* z */ {{ 0x0000, 0xd1c5, 0x92c6, 0xf4fc, 0x29af, 0x17c2, 0xbd51, 0xf6c8, 0xa5ea, 0x9916, 0x9413, 0xcc8f, 0xbce7, 0x8d14, 0x6d21, 0x3159, 0x2204}, 16, 0x00} + }, +//0x0007 + { + /* num */ + /* x */ {{ 0x0000, 0xf8af, 0x31df, 0x7a18, 0x9edd, 0xb7a3, 0xdec5, 0x8223, 0x22ab, 0x6881, 0x1a4a, 0xb165, 0xdd62, 0x16e9, 0x3bed, 0xa632, 0x7b8f}, 16, 0x00}, + /* y */ {{ 0x0000, 0x4f09, 0xa05f, 0xac18, 0x0f41, 0x62aa, 0x8320, 0xe134, 0xa671, 0x366e, 0x374f, 0xff2a, 0x6698, 0x68ee, 0x233e, 0x77bf, 0x98d2}, 16, 0x00}, + /* z */ {{ 0x0000, 0xc13e, 0xd81b, 0xdf7b, 0xdf9f, 0x50f3, 0xb993, 0x8aed, 0x5397, 0x8b06, 0xec6c, 0x01b7, 0xc151, 0x11c4, 0x2b81, 0x3f40, 0xf476}, 16, 0x00} + }, +//0x0008 + { + /* num */ + /* x */ {{ 0x0000, 0x3d01, 0xd0ab, 0xc595, 0x3e53, 0xe5d1, 0x38e3, 0xd692, 0xd41a, 0x616f, 0x5757, 0x559b, 0xc2d9, 0x2888, 0xc2bc, 0xc4e2, 0xafba}, 16, 0x00}, + /* y */ {{ 0x0000, 0x193f, 0x2d8a, 0x1f2e, 0xb204, 0x8247, 0xf138, 0x028c, 0xf01a, 0x45ce, 0x2623, 0x6dd5, 0xa56f, 0x7074, 0x3576, 0x8cdf, 0xbfbf}, 16, 0x00}, + /* z */ {{ 0x0000, 0x4a03, 0xbfe8, 0x5bdb, 0x2daa, 0x2679, 0xf907, 0x08a9, 0x2d0d, 0xd6ca, 0x8939, 0x7a68, 0xfb2d, 0xf14a, 0x32d8, 0x08ed, 0x7f2f}, 16, 0x00} + }, +//0x0009 + { + /* num */ + /* x */ {{ 0x0000, 0x339d, 0x3514, 0x3ab7, 0x894b, 0x6d62, 0x618d, 0x19a5, 0xf8d6, 0xbc4c, 0xb6e5, 0x2a11, 0xea88, 0xc6bb, 0xa46d, 0x0ca3, 0x52d1}, 16, 0x00}, + /* y */ {{ 0x0000, 0xdc93, 0xa482, 0xde79, 0xb694, 0x5961, 0xa59f, 0xde26, 0x70e0, 0x4efa, 0xcd9f, 0xa462, 0xea51, 0x4b7d, 0xc4a3, 0xc108, 0xc7bb}, 16, 0x00}, + /* z */ {{ 0x0000, 0xce26, 0x909e, 0x040d, 0x04a8, 0x1f89, 0x0e57, 0xc1da, 0x3605, 0x6fcc, 0x9c5b, 0x6e87, 0x0e7d, 0xdbef, 0xc849, 0xc416, 0x7fe7}, 16, 0x00} + }, +//0x000A + { + /* num */ + /* x */ {{ 0x0000, 0xfd00, 0xadb9, 0xb973, 0x01c9, 0xa9cc, 0x2bcc, 0x6007, 0xda4f, 0x30ec, 0x4dbf, 0x3125, 0x9407, 0xba73, 0x2617, 0x928f, 0x48bb}, 16, 0x00}, + /* y */ {{ 0x0000, 0x880d, 0xf759, 0x2b7b, 0x4d98, 0xb051, 0xaed9, 0x3df1, 0xdddc, 0x56c9, 0x3d8f, 0x1714, 0x8250, 0x867c, 0x1c89, 0xc3bf, 0xd08b}, 16, 0x00}, + /* z */ {{ 0x0000, 0xfcae, 0x15e2, 0xdc42, 0xb476, 0xc8c6, 0x8143, 0xcfcc, 0x9446, 0xa73f, 0xea01, 0x4537, 0x0be0, 0x9e1d, 0x98cb, 0xe781, 0xfd4b}, 16, 0x00} + }, +//0x000B + { + /* num */ + /* x */ {{ 0x0000, 0xd201, 0x5a57, 0xf4f6, 0x398f, 0xb1e1, 0xd191, 0x4a78, 0x41e7, 0x463c, 0x9536, 0xc59c, 0xe39d, 0x41f5, 0x5168, 0xe5be, 0x91e1}, 16, 0x00}, + /* y */ {{ 0x0000, 0x06b9, 0xac4a, 0x0b8a, 0x2038, 0xae86, 0x45b7, 0x4673, 0x2630, 0x83f5, 0x8c9f, 0xdc27, 0x15a4, 0x11cd, 0x96d4, 0x6ae3, 0xedb0}, 16, 0x00}, + /* z */ {{ 0x0000, 0x2a8b, 0x67f7, 0xe052, 0x6c09, 0x0cea, 0x0b00, 0x2ebf, 0x997d, 0x85d2, 0xd9d6, 0x7600, 0x7cca, 0x2645, 0x36cc, 0x109c, 0xee08}, 16, 0x00} + }, +//0x000C + { + /* num */ + /* x */ {{ 0x0000, 0xffcb, 0x0a9a, 0x7dfe, 0x6606, 0xeecf, 0x47ad, 0x4c3c, 0x4a4e, 0x39a6, 0x21a3, 0xc310, 0xb661, 0x115a, 0x0335, 0x6f55, 0xf312}, 16, 0x00}, + /* y */ {{ 0x0000, 0xe572, 0xe4df, 0x8328, 0x6cb4, 0x0dde, 0xa98c, 0x8958, 0xc6b3, 0xaa07, 0x51fa, 0xb237, 0x93d8, 0x7f73, 0x946e, 0xc5cc, 0xf9f8}, 16, 0x00}, + /* z */ {{ 0x0000, 0xef20, 0xaf4e, 0x7295, 0xb11e, 0x8f6d, 0x3d02, 0x240a, 0x3dac, 0x0349, 0xcce0, 0xf30b, 0x0638, 0x136b, 0x84c0, 0x966e, 0x7415}, 16, 0x00}, + }, +//0x000D + { + /* num */ + /* x */ {{ 0x0000, 0xc94d, 0x5b90, 0xb318, 0xd9ea, 0x9dd2, 0x7189, 0x1ae7, 0x1799, 0xbf5c, 0xe7a4, 0xd629, 0x696e, 0xa97d, 0x5e61, 0x7021, 0xcf29}, 16, 0x00}, + /* y */ {{ 0x0000, 0x56f3, 0xc6fe, 0xcafa, 0x2a29, 0x0159, 0x021d, 0x82bd, 0x1799, 0xff69, 0x74d1, 0x5e49, 0x646b, 0x5dea, 0x5f0b, 0x32e8, 0x8933}, 16, 0x00}, + /* z */ {{ 0x0000, 0x1c13, 0x5301, 0x5f85, 0x8c20, 0x4d43, 0x52f5, 0xc186, 0xb6ca, 0x582f, 0x44e2, 0xc250, 0x446a, 0x4973, 0x3d20, 0xaadc, 0xe543}, 16, 0x00}, + }, +//0x000E + { + /* num */ + /* x */ {{ 0x0000, 0xbe6e, 0x27b3, 0x2cdf, 0x8dba, 0xfc10, 0x56e5, 0x9f0a, 0x28b2, 0x1b69, 0xf4ba, 0x15cd, 0x8668, 0x702a, 0xa678, 0xa297, 0x7270 }, 16, 0x00}, + /* y */ {{ 0x0000, 0x7f5b, 0x3426, 0x7b6a, 0x8b10, 0xfbf9, 0x7ffd, 0xc6fd, 0xe4b3, 0x4e95, 0x9e1d, 0xa067, 0xb6e1, 0x869c, 0x4fbe, 0x272a, 0xb43a }, 16, 0x00}, + /* z */ {{ 0x0000, 0xe389, 0x2e89, 0xb6d2, 0xb79d, 0xb0e0, 0x674d, 0x1287, 0x752e, 0x66d4, 0x2cc6, 0xabe0, 0xdb83, 0x5de7, 0x4ac4, 0x9c6d, 0x041d }, 16, 0x00} + }, +//0x000F + { + /* num */ + /* x */ {{ 0x0000, 0x2436, 0x6156, 0xcb65, 0x9023, 0xf21b, 0xe5dd, 0xa2b9, 0xfe84, 0xb402, 0x833f, 0x46a7, 0xb876, 0xb948, 0x8cde, 0x4727, 0xa595 }, 16, 0x00}, + /* y */ {{ 0x0000, 0xf0fa, 0x6956, 0xd8c7, 0xaf3e, 0xe73b, 0xc2d4, 0xec91, 0x1c8f, 0x3744, 0x2d40, 0x7daa, 0xd19c, 0xa479, 0x10e1, 0xa5c5, 0xe688 }, 16, 0x00}, + /* z */ {{ 0x0000, 0x5884, 0xf036, 0xbd33, 0xa657, 0x6f1f, 0x822e, 0x6fb9, 0xcaa5, 0xfdd2, 0xa20e, 0xc14b, 0xde4d, 0xe2d3, 0xef31, 0xaf45, 0x54fb }, 16, 0x00} + } + +}; + +#elif (ECC_MULT_ALGO_TYPE == 32) +const ECC_Jacobian_Point256 ECC_4Win_Look_up_table[15] = +{ +//0x0001 + { + /* num */ + /* x */ {{ 0x00000000, 0x6b17d1f2, 0xe12c4247, 0xf8bce6e5, 0x63a440f2, 0x77037d81, 0x2deb33a0, 0xf4a13945, 0xd898c296 }, 0x8, 0x00}, + /* y */ {{ 0x00000000, 0x4fe342e2, 0xfe1a7f9b, 0x8ee7eb4a, 0x7c0f9e16, 0x2bce3357, 0x6b315ece, 0xcbb64068, 0x37bf51f5 }, 0x8, 0x00}, + /* Z */ {{ 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000001 }, 0x1, 0x00} + }, +//0x0002 + { + /* num */ + /* x */ {{ 0x00000000, 0x8f228205, 0x98a60fe3, 0xc582a4e4, 0xe495f299, 0x7b48a1de, 0x965059a9, 0x18c3c50b, 0xb251a29d }, 0x8, 0x00}, + /* y */ {{ 0x00000000, 0x468ab3e5, 0x1fcb4722, 0x9871e7e9, 0x5bf28286, 0xcd448ed3, 0xeb0c78ec, 0xd34eac12, 0x1d285bc2 }, 0x8, 0x00}, + /* z */ {{ 0x00000000, 0xc297492c, 0x20cce496, 0x6ae2cd2b, 0x58b75e48, 0xffbd5489, 0x95ef960d, 0x41e274dc, 0x1e5b3ed6 }, 0x8, 0x00} + }, +//0x0003 + { + /* num */ + /* x */ {{ 0x00000000, 0x0bad26fb, 0xd93b1ab7, 0xe8448e98, 0xe098c19f, 0x90e3156a, 0x94ae76e3, 0x56e8bcaa, 0x5d210197}, 0x8, 0x00}, + /* y */ {{ 0x00000000, 0x4a1d6bbe, 0xdf46a06f, 0x7d761828, 0x7a69fd83, 0x346c8ed1, 0xef774189, 0xb0e36138, 0x55bd8d83}, 0x8, 0x00}, + /* Z */ {{ 0x00000000, 0x30939029, 0xdb214543, 0x21313957, 0xaec9c854, 0xa4b23170, 0xb0cee4c4, 0x6f2ec46c, 0xdf0d9342}, 0x8, 0x00} + }, +// 0x0004 + { + /* num */ + /* x */ {{ 0x00000000, 0xe1aa8f71, 0x41bfe1ed, 0x0ab48559, 0x9b5779eb, 0xec8b9353, 0x3c5bde62, 0x423df00d, 0x2b1cb5f2}, 0x8, 0x00}, + /* y */ {{ 0x00000000, 0xd2f122ef, 0x80385047, 0x8290ab2a, 0x627771ec, 0x4eccef63, 0x34a3d343, 0xc0a9f7e6, 0x56103895}, 0x8, 0x00}, + /* z */ {{ 0x00000000, 0x9182b500, 0x3bc1da72, 0xe3be14e0, 0xfb0c2593, 0x330522bd, 0x83326ee2, 0xe2457d8e, 0x6de1783e}, 0x8, 0x00}, + }, +//0x0005 + { + /* num */ + /* x */ {{ 0x00000000, 0x6a140c55, 0x70ae60a6, 0x1eab131d, 0xf0a7b995, 0x5ca52eee, 0x3a03b007, 0xa6fc97e6, 0x0ddcd000}, 0x8, 0x00}, + /* y */ {{ 0x00000000, 0x32665be0, 0xdea111a9, 0xf1de8948, 0xb01514c3, 0x6e693bab, 0xf68c4db9, 0xed6307a3, 0xe9ec3df5}, 0x8, 0x00}, + /* z */ {{ 0x00000000, 0xc53bb6c4, 0x0c028674, 0xca4dbb66, 0x216624f8, 0x939409db, 0x2e75d7fa, 0x62d4b5e6, 0xa8870ac3}, 0x8, 0x00} + }, +//0x0006 + { + /* num */ + /* x */ {{ 0x00000000, 0xcca15363, 0x506327c1, 0xcb6a22b4, 0x5277e102, 0x279482b5, 0xedc0aff9, 0xa43c31e5, 0xee4c7f21 }, 0x8, 0x00}, + /* y */ {{ 0x00000000, 0x5f706301, 0x91f1e4f4, 0xa011b402, 0x20423775, 0xf79c950c, 0x421df6a0, 0x03e867c6, 0x4d00c6a6 }, 0x8, 0x00}, + /* z */ {{ 0x00000000, 0xd1c592c6, 0xf4fc29af, 0x17c2bd51, 0xf6c8a5ea, 0x99169413, 0xcc8fbce7, 0x8d146d21, 0x31592204 }, 0x8, 0x00} + }, +//0x0007 + { + /* num */ + /* x */ {{ 0x00000000, 0xf8af31df, 0x7a189edd, 0xb7a3dec5, 0x822322ab, 0x68811a4a, 0xb165dd62, 0x16e93bed, 0xa6327b8f }, 0x8, 0x00}, + /* y */ {{ 0x00000000, 0x4f09a05f, 0xac180f41, 0x62aa8320, 0xe134a671, 0x366e374f, 0xff2a6698, 0x68ee233e, 0x77bf98d2 }, 0x8, 0x00}, + /* z */ {{ 0x00000000, 0xc13ed81b, 0xdf7bdf9f, 0x50f3b993, 0x8aed5397, 0x8b06ec6c, 0x01b7c151, 0x11c42b81, 0x3f40f476 }, 0x8, 0x00} + }, +//0x0008 + { + /* num */ + /* x */ {{ 0x00000000, 0x3d01d0ab, 0xc5953e53, 0xe5d138e3, 0xd692d41a, 0x616f5757, 0x559bc2d9, 0x2888c2bc, 0xc4e2afba }, 0x8, 0x00}, + /* y */ {{ 0x00000000, 0x193f2d8a, 0x1f2eb204, 0x8247f138, 0x028cf01a, 0x45ce2623, 0x6dd5a56f, 0x70743576, 0x8cdfbfbf }, 0x8, 0x00}, + /* z */ {{ 0x00000000, 0x4a03bfe8, 0x5bdb2daa, 0x2679f907, 0x08a92d0d, 0xd6ca8939, 0x7a68fb2d, 0xf14a32d8, 0x08ed7f2f }, 0x8, 0x00} + }, +//0x0009 + { + /* num */ + /* x */ {{ 0x00000000, 0x339d3514, 0x3ab7894b, 0x6d62618d, 0x19a5f8d6, 0xbc4cb6e5, 0x2a11ea88, 0xc6bba46d, 0x0ca352d1 }, 0x8, 0x00}, + /* y */ {{ 0x00000000, 0xdc93a482, 0xde79b694, 0x5961a59f, 0xde2670e0, 0x4efacd9f, 0xa462ea51, 0x4b7dc4a3, 0xc108c7bb }, 0x8, 0x00}, + /* z */ {{ 0x00000000, 0xce26909e, 0x040d04a8, 0x1f890e57, 0xc1da3605, 0x6fcc9c5b, 0x6e870e7d, 0xdbefc849, 0xc4167fe7 }, 0x8, 0x00} + }, +//0x000A + { + /* num */ + /* x */ {{ 0x00000000, 0xfd00adb9, 0xb97301c9, 0xa9cc2bcc, 0x6007da4f, 0x30ec4dbf, 0x31259407, 0xba732617, 0x928f48bb }, 0x8, 0x00}, + /* y */ {{ 0x00000000, 0x880df759, 0x2b7b4d98, 0xb051aed9, 0x3df1dddc, 0x56c93d8f, 0x17148250, 0x867c1c89, 0xc3bfd08b }, 0x8, 0x00}, + /* z */ {{ 0x00000000, 0xfcae15e2, 0xdc42b476, 0xc8c68143, 0xcfcc9446, 0xa73fea01, 0x45370be0, 0x9e1d98cb, 0xe781fd4b }, 0x8, 0x00} + }, +//0x000B + { + /* num */ + /* x */ {{ 0x00000000, 0xd2015a57, 0xf4f6398f, 0xb1e1d191, 0x4a7841e7, 0x463c9536, 0xc59ce39d, 0x41f55168, 0xe5be91e1 }, 0x8, 0x00}, + /* y */ {{ 0x00000000, 0x06b9ac4a, 0x0b8a2038, 0xae8645b7, 0x46732630, 0x83f58c9f, 0xdc2715a4, 0x11cd96d4, 0x6ae3edb0 }, 0x8, 0x00}, + /* z */ {{ 0x00000000, 0x2a8b67f7, 0xe0526c09, 0x0cea0b00, 0x2ebf997d, 0x85d2d9d6, 0x76007cca, 0x264536cc, 0x109cee08 }, 0x8, 0x00} + }, +//0x000C + { + /* num */ + /* x */ {{ 0x00000000, 0xffcb0a9a, 0x7dfe6606, 0xeecf47ad, 0x4c3c4a4e, 0x39a621a3, 0xc310b661, 0x115a0335, 0x6f55f312 }, 0x8, 0x00}, + /* y */ {{ 0x00000000, 0xe572e4df, 0x83286cb4, 0x0ddea98c, 0x8958c6b3, 0xaa0751fa, 0xb23793d8, 0x7f73946e, 0xc5ccf9f8 }, 0x8, 0x00}, + /* z */ {{ 0x00000000, 0xef20af4e, 0x7295b11e, 0x8f6d3d02, 0x240a3dac, 0x0349cce0, 0xf30b0638, 0x136b84c0, 0x966e7415 }, 0x8, 0x00}, + }, +//0x000D + { + /* num */ + /* x */ {{ 0x00000000, 0xc94d5b90, 0xb318d9ea, 0x9dd27189, 0x1ae71799, 0xbf5ce7a4, 0xd629696e, 0xa97d5e61, 0x7021cf29 }, 0x8, 0x00}, + /* y */ {{ 0x00000000, 0x56f3c6fe, 0xcafa2a29, 0x0159021d, 0x82bd1799, 0xff6974d1, 0x5e49646b, 0x5dea5f0b, 0x32e88933 }, 0x8, 0x00}, + /* z */ {{ 0x00000000, 0x1c135301, 0x5f858c20, 0x4d4352f5, 0xc186b6ca, 0x582f44e2, 0xc250446a, 0x49733d20, 0xaadce543 }, 0x8, 0x00}, + }, +//0x000E + { + /* num */ + /* x */ {{ 0x00000000, 0xbe6e27b3, 0x2cdf8dba, 0xfc1056e5, 0x9f0a28b2, 0x1b69f4ba, 0x15cd8668, 0x702aa678, 0xa2977270 }, 0x8, 0x00}, + /* y */ {{ 0x00000000, 0x7f5b3426, 0x7b6a8b10, 0xfbf97ffd, 0xc6fde4b3, 0x4e959e1d, 0xa067b6e1, 0x869c4fbe, 0x272ab43a }, 0x8, 0x00}, + /* z */ {{ 0x00000000, 0xe3892e89, 0xb6d2b79d, 0xb0e0674d, 0x1287752e, 0x66d42cc6, 0xabe0db83, 0x5de74ac4, 0x9c6d041d }, 0x8, 0x00} + }, +//0x000F + { + /* num */ + /* x */ {{ 0x00000000, 0x24366156, 0xcb659023, 0xf21be5dd, 0xa2b9fe84, 0xb402833f, 0x46a7b876, 0xb9488cde, 0x4727a595 }, 0x8, 0x00}, + /* y */ {{ 0x00000000, 0xf0fa6956, 0xd8c7af3e, 0xe73bc2d4, 0xec911c8f, 0x37442d40, 0x7daad19c, 0xa47910e1, 0xa5c5e688 }, 0x8, 0x00}, + /* z */ {{ 0x00000000, 0x5884f036, 0xbd33a657, 0x6f1f822e, 0x6fb9caa5, 0xfdd2a20e, 0xc14bde4d, 0xe2d3ef31, 0xaf4554fb }, 0x8, 0x00} + } + +}; +#endif +#endif + +// local environment variable +struct ecc_env_tag ecc_env; + + +/* + * LOCAL FUNCTIONS DEFINITIONS + **************************************************************************************** + */ + + +/**************************************************************************** + * Prototypes for local functions + * These perform the bulk of the maths for ECC + ****************************************************************************/ +void AddBigHex256(const bigHex256 *bigHexA, const bigHex256 *bigHexB, bigHex256 *BigHexResult); +void SubtractBigHex256( const bigHex256 *bigHexA, const bigHex256 *bigHexB, bigHex256 *BigHexResult); +void bigHexInversion256( bigHex256 *bigHexA, bigHex256 *pResult); +void Add2SelfBigHex256( bigHex256 *bigHexA, const bigHex256 *bigHexB); +void AddP256( bigHex256 *bigHexA); +void SubtractBigHexMod256(const bigHex256 *bigHexA, const bigHex256 *bigHexB, bigHex256 *BigHexResult); +void SubtractFromSelfBigHex256(bigHex256 *bigHexA, const bigHex256 *bigHexB); +void SubtractFromSelfBigHexSign256( bigHex256 *bigHexA, const bigHex256 *bigHexB); +void MultiplyBigHexModP256(const bigHex256 *bigHexA, const bigHex256 *bigHexB, bigHex256 *BigHexResult); +#if (ECC_MULT_ALGO_TYPE == 16) +void MultiplyByU16ModP256(const u_int16 N, bigHex256 *result); +#elif (ECC_MULT_ALGO_TYPE == 32) +void MultiplyByU32ModP256(const u_int32 N, bigHex256 *result); +#endif // (ECC_MULT_ALGO_TYPE == 16) +void specialModP256(bigHex256 *tmpHexA); +void AddPdiv2_256(bigHex256 *bigHexA); + +static int isValidSecretKey_256(u_int8 *secretKey); + +/**************************************************************************** + * Prototypes for local inline functions + * There are small functions which are frequently called + ****************************************************************************/ +__INLINE__ void initBigNumber256(bigHex256 *BigHexResult); +__INLINE__ void setBigNumberLength256( bigHex256 *BigHexResult); +__INLINE__ void setVeryBigNumberLength256(veryBigHex256 *BigHexResult); +__INLINE__ void copyBigHex256(const bigHex256 *source, bigHex256 *destination); +__INLINE__ void shiftLeftOneArrayElement256(bigHex256 *input); +__INLINE__ void divideByTwo256(bigHex256 *A); + +__INLINE__ int isGreaterThan256(const bigHex256 *bigHexA, const bigHex256 *bigHexB); +__INLINE__ int isGreaterThanOrEqual256(const bigHex256 *bigHexA, const bigHex256 *bigHexB); +__INLINE__ int isVeryBigHexGreaterThanOrEqual256(const veryBigHex256 *bigHexA, const veryBigHex256 *bigHexB); + +__INLINE__ void GF_Setup_Jacobian_Infinity_Point256(ECC_Jacobian_Point256 *infinity); +__INLINE__ void GF_Affine_To_Jacobian_Point_Copy256(const ECC_Point256 *source, ECC_Jacobian_Point256 *destination); +__INLINE__ void GF_Jacobian_Point_Copy256(const ECC_Jacobian_Point256 *source, ECC_Jacobian_Point256 *destination); + + + + +// Gaulois Field Operands +int GF_Jacobian_Point_Double256(const ECC_Jacobian_Point256 *pPointP, ECC_Jacobian_Point256 *pResultPoint); + +int isValidSecretKey_256(u_int8 *secretKey) +{ + // First check that the secret key is not all zeros. + // + int i; + + for (i = 31; i >= 0; i--) + { + if (secretKey[i] != 0) + { + break; + } + } + + if ((i == -1) && (secretKey[0] == 0)) + { + return 0; + } + + for (i = 31; i >= 0; i--) + { + if (secretKey[i] > maxSecretKey_256[i]) + { + return 0; + } + else if (secretKey[i] < maxSecretKey_256[i]) + { + return 1; + } + } + return 1; +} + +/****************************************************************************** + * Section of functions for BASIC big number handling + * These do not consider the Finite Field or ECC + * + * Mod P is not performed + * Sign is not considered -- all inputs and results are assumed to be positive + * + * AddBigHex - This adds two 15*u16 positive numbers. + * AddVeryBigHex - This adds two 30*u16 positive numbers. + * + * SubtractBigHex - This subtracts two 15*u16 positive numbers + * To ensure a +ive result we assume A >= B + * SubtractVeryBigHex - This subtracts two 30*u16 positive numbers + * To ensure a +ive result we assume A >= B + * MultiplyBigHex - This multiplies two 15*u16 positive numbers to produce + * a 30*u16 positive result + * + ******************************************************************************/ + +// +// +// Inputs - Format of the inputs that they begin with the LEAST significant bytes in the 0 entry of the array. +// +__RAM_ECDH void AddBigHex256( const bigHex256 *bigHexA, const bigHex256 *bigHexB, bigHex256 *BigHexResult) +{ + u_int32 carry = 0; + s_int32 i; +#if (ECC_MULT_ALGO_TYPE == 16) + u_int32 tmp; + const u_int16 *numA = bigHexA->num; + const u_int16 *numB = bigHexB->num; + u_int16 *result = BigHexResult->num; +#elif (ECC_MULT_ALGO_TYPE == 32) + u64 tmp; + const u_int32 *numA = bigHexA->num; + const u_int32 *numB = bigHexB->num; + u_int32 *result = BigHexResult->num; +#endif // (ECC_MULT_ALGO_TYPE == 16) + + for (i = (ELEMENTS_BIG_HEX256 - 1); i >= 0; i--) + { +#if (ECC_MULT_ALGO_TYPE == 16) + tmp = (u_int32)((u_int32)(numA[i]) + (u_int32)(numB[i]) + carry); + if (tmp & 0x10000) + { + carry = 0x01; + } + else + { + carry = 0x00; + } + + result[i] = (tmp & 0xFFFF); +#elif (ECC_MULT_ALGO_TYPE == 32) + tmp = (u64)((u64)(numA[i]) + (u64)(numB[i]) + carry); + if (tmp & _LL(0x100000000)) + { + carry = 0x01; + } + else + { + carry = 0x00; + } + + result[i] = (tmp & 0xFFFFFFFF); +#endif // (ECC_MULT_ALGO_TYPE == 16) + } + setBigNumberLength256(BigHexResult); + BigHexResult->sign = 0; +} + +__RAM_ECDH void AddBigHexModP256( const bigHex256 *bigHexA, const bigHex256 *bigHexB, bigHex256 *BigHexResult) +{ + AddBigHex256(bigHexA, bigHexB, BigHexResult); + + if (BigHexResult->sign == 0x00) // Positive Number + { + if (isGreaterThanOrEqual256(BigHexResult, &bigHexP256)) + { + //SubtractFromSelfBigHexSign(BigHexResult,&bigHexP); + SubtractFromSelfBigHex256(BigHexResult, &bigHexP256); + } + } + else + { + AddP256(BigHexResult); + } +} +// A = A + B +__RAM_ECDH void Add2SelfBigHex256( bigHex256 *bigHexA, const bigHex256 *bigHexB) +{ +#if (ECC_MULT_ALGO_TYPE == 16) + u_int32 tmp; + u_int16 carry = 0; + s_int32 i; + u_int16 *numA = bigHexA->num; + const u_int16 *numB = bigHexB->num; + + for (i = (ELEMENTS_BIG_HEX256 - 1); i >= 0; i--) + { + tmp = (u_int32)((u_int32)(numA[i]) + (u_int32)(numB[i]) + carry); + if (tmp & 0x10000) + { + carry = 0x01; + } + else + { + carry = 0x00; + } + + numA[i] = (tmp & 0xFFFF); + } +#elif (ECC_MULT_ALGO_TYPE == 32) + u64 tmp; + u_int32 carry = 0; + s_int32 i; + u_int32 *numA = bigHexA->num; + const u_int32 *numB = bigHexB->num; + + for (i = (ELEMENTS_BIG_HEX256 - 1); i >= 0; i--) + { + tmp = (u64)((u64)(numA[i]) + (u64)(numB[i]) + carry); + if (tmp & _LL(0x100000000)) + { + carry = 0x01; + } + else + { + carry = 0x00; + } + + numA[i] = (tmp & 0xFFFFFFFF); + } +#endif // (ECC_MULT_ALGO_TYPE == 16) + setBigNumberLength256(bigHexA); +} + +__RAM_ECDH void SubtractBigHex256(const bigHex256 *bigHexA, const bigHex256 *bigHexB, bigHex256 *BigHexResult) +{ +#if (ECC_MULT_ALGO_TYPE == 16) + // Due to the nature of the GF we have to assume both inputs are +ive. + u_int16 borrow = 0; + s_int32 i; + const u_int16 *pBigNum = bigHexA->num; + const u_int16 *pSmallNum = bigHexB->num; + u_int16 *pResult = BigHexResult->num; + + for (i = (ELEMENTS_BIG_HEX256 - 1); i >= 0; i--) + { + if (((u_int32)((u_int32)(pSmallNum[i]) + (u_int32)borrow)) > (pBigNum[i])) + { + pResult[i] = (((u_int32)(pBigNum[i] + 0x10000)) - (pSmallNum[i] + borrow)) & 0xFFFF; + borrow = 0x01; + } + else + { + pResult[i] = ((pBigNum[i]) - (pSmallNum[i] + borrow)) & 0xFFFF; + borrow = 0x00; + } + } +#elif (ECC_MULT_ALGO_TYPE == 32) + // Due to the nature of the GF we have to assume both inputs are +ive. + u_int32 borrow = 0; + s_int32 i; + const u_int32 *pBigNum = bigHexA->num; + const u_int32 *pSmallNum = bigHexB->num; + u_int32 *pResult = BigHexResult->num; + + for (i = (ELEMENTS_BIG_HEX256 - 1); i >= 0; i--) + { + if (((u64)((u64)(pSmallNum[i]) + (u64)borrow)) > (pBigNum[i])) + { + pResult[i] = (((u64)(pBigNum[i] + _LL(0x100000000))) - (pSmallNum[i] + borrow)) & 0xFFFFFFFF; + borrow = 0x01; + } + else + { + pResult[i] = ((pBigNum[i]) - (pSmallNum[i] + borrow)) & 0xFFFFFFFF; + borrow = 0x00; + } + } +#endif // (ECC_MULT_ALGO_TYPE == 16) + setBigNumberLength256(BigHexResult); +} + +// A = A - B +__RAM_ECDH void SubtractFromSelfBigHex256(bigHex256 *bigHexA, const bigHex256 *bigHexB) +{ +#if (ECC_MULT_ALGO_TYPE == 16) + u_int16 borrow = 0; + s_int32 i; + u_int16 *pBigNum = bigHexA->num; + const u_int16 *pSmallNum = bigHexB->num; + + for (i = (ELEMENTS_BIG_HEX256 - 1); i >= 0; i--) + { + if (((u_int32)((u_int32)(pSmallNum[i]) + (u_int32)borrow)) > (pBigNum[i])) + { + pBigNum[i] = (((u_int32)(pBigNum[i] + 0x10000)) - (pSmallNum[i] + borrow)) & 0xFFFF; + borrow = 0x01; + } + else + { + pBigNum[i] = ((pBigNum[i]) - (pSmallNum[i] + borrow)) & 0xFFFF; + borrow = 0x00; + } + } +#elif (ECC_MULT_ALGO_TYPE == 32) + // Due to the nature of the GF we have to assume both inputs are +ive. + u_int32 borrow = 0; + s_int32 i; + u_int32 *pBigNum = bigHexA->num; + const u_int32 *pSmallNum = bigHexB->num; + + for (i = (ELEMENTS_BIG_HEX256 - 1); i >= 0; i--) + { + if (((u64)((u64)(pSmallNum[i]) + (u64)borrow)) > (pBigNum[i])) + { + pBigNum[i] = (((u64)(pBigNum[i] + _LL(0x100000000))) - (pSmallNum[i] + borrow)) & 0xFFFFFFFF; + borrow = 0x01; + } + else + { + pBigNum[i] = ((pBigNum[i]) - (pSmallNum[i] + borrow)) & 0xFFFFFFFF; + borrow = 0x00; + } + } +#endif // (ECC_MULT_ALGO_TYPE == 16) + setBigNumberLength256(bigHexA); +} + +/********************************************************************************** + * This section extends of the basic functions provided previously to support + * sign. We concentrate on the Add and Subtract functions for both 15*u16 and 30*u16 + * numbers. + * + * AddBigHexSign - Adds two 15*u16 numbers considering the sign. + * SubtractBigHexSign - Subtracts two 15*u16 numbers considering the sign + * AddVeryBigHexSign + * SubtractVeryBigHexSign + * MultiplyBigHexSign - Multiplies two 15*u16 numbers considering the sign. + **********************************************************************************/ + +// AddP is only invoked when the sign of A is -ive +// A is always less than P +// +__RAM_ECDH void AddP256( bigHex256 *bigHexA) +{ + bigHex256 BigHexResult; + SubtractBigHex256(&bigHexP256, bigHexA, &BigHexResult); + copyBigHex256(&BigHexResult, bigHexA); + bigHexA->sign = 0; +} + +__RAM_ECDH void AddPdiv2_256( bigHex256 *bigHexA) +{ +#if (ECC_MULT_ALGO_TYPE == 16) + u_int16 *numA = bigHexA->num; + const u_int16 *numB = bigHexP256.num; + + if (bigHexA->sign == 0) + { + u_int32 tmp; + u_int16 carry; + s_int32 i; + + carry = 0; + + for (i = (ELEMENTS_BIG_HEX256 - 1); i >= 0; i--) + { + tmp = (u_int32)((u_int32)(numA[i]) + (u_int32)(numB[i]) + carry); + if (tmp & 0x10000) + { + carry = 0x01; + } + else + { + carry = 0x00; + } + + numA[i] = (tmp & 0xFFFF); + } + } + else // if (bigHexA->sign == 1) + { + if ( isGreaterThan256(bigHexA, &bigHexP256)) + { + // Due to the nature of the GF we have to assume both inputs are +ive. + u_int16 borrow = 0; + s_int32 i; + + for (i = (ELEMENTS_BIG_HEX256 - 1); i >= 0; i--) + { + if (((u_int32)((u_int32)(numB[i]) + (u_int32)borrow)) > (numA[i])) + { + numA[i] = (((u_int32)(numA[i] + 0x10000)) - (numB[i] + borrow)) & 0xFFFF; + borrow = 0x01; + } + else + { + numA[i] = ((numA[i]) - (numB[i] + borrow)) & 0xFFFF; + borrow = 0x00; + } + } + } + else + { + bigHex256 BigHexResult; + + SubtractBigHex256(&bigHexP256, bigHexA, &BigHexResult); + copyBigHex256(&BigHexResult, bigHexA); + bigHexA->sign = 0; + } + } + // divide by 2 + // divideByTwo(bigHexA); + { + u_int16 rem = 0; + u_int32 val; + u_int32 i; + + for (i = 0; i < (ELEMENTS_BIG_HEX256); i++) + { + val = (u_int32)((u_int32)(numA[i]) + ((u_int32)rem * 0x10000)); + + numA[i] = (u_int16)(val >> 1); + rem = (u_int32)(val - ((val >> 1) << 1)); + } + + // We need to re-calculate the length. + setBigNumberLength256(bigHexA); + } +#elif (ECC_MULT_ALGO_TYPE == 32) + u_int32 *numA = bigHexA->num; + const u_int32 *numB = bigHexP256.num; + + if (bigHexA->sign == 0) + { + u64 tmp; + u_int32 carry; + s_int32 i; + + carry = 0; + + for (i = (ELEMENTS_BIG_HEX256 - 1); i >= 0; i--) + { + tmp = (u64)((u64)(numA[i]) + (u64)(numB[i]) + carry); + if (tmp & _LL(0x100000000)) + { + carry = 0x01; + } + else + { + carry = 0x00; + } + + numA[i] = (tmp & 0xFFFFFFFF); + } + } + else // if (bigHexA->sign == 1) + { + if ( isGreaterThan256(bigHexA, &bigHexP256)) + { + + // Due to the nature of the GF we have to assume both inputs are +ive. + u_int32 borrow = 0; + s_int32 i; + + for (i = (ELEMENTS_BIG_HEX256 - 1); i >= 0; i--) + { + if (((u64)((u64)(numB[i]) + (u64)borrow)) > (numA[i])) + { + numA[i] = (((u64)(numA[i] + _LL(0x100000000))) - (numB[i] + borrow)) & 0xFFFFFFFF; + borrow = 0x01; + } + else + { + numA[i] = ((numA[i]) - (numB[i] + borrow)) & 0xFFFFFFFF; + borrow = 0x00; + } + } + } + else + { + bigHex256 BigHexResult; + + SubtractBigHex256(&bigHexP256, bigHexA, &BigHexResult); + copyBigHex256(&BigHexResult, bigHexA); + bigHexA->sign = 0; + } + } + // divide by 2 + // divideByTwo(bigHexA); + { + u_int32 rem = 0; + u64 u64val; + u_int32 i; + + for (i = 0; i < (ELEMENTS_BIG_HEX256); i++) + { + u64val = (u64)((u64)(numA[i]) + ((u64)rem * _LL(0x100000000))); + + numA[i] = (u_int32)(u64val >> 1); + rem = (u64)(u64val - ((u64val >> 1) << 1)); + } + + // We need to re-calculate the length. + setBigNumberLength256(bigHexA); + } +#endif // (ECC_MULT_ALGO_TYPE == 16) +} + +__RAM_ECDH void SubtractFromSelfBigHexSign256( bigHex256 *bigHexA, const bigHex256 *bigHexB) +{ + // This function uses use the basis AddBigHex and SubtractBigHex to implement a full + // Addition which considers sign and mod. + // + if (bigHexA->sign == 0) + { + if (bigHexB->sign == 0) + { + if ( isGreaterThanOrEqual256(bigHexA, bigHexB)) + { + SubtractFromSelfBigHex256(bigHexA, bigHexB); + } + else + { + bigHex256 BigHexResult; + + SubtractBigHex256(bigHexB, bigHexA, &BigHexResult); + copyBigHex256(&BigHexResult, bigHexA); + bigHexA->sign = 1; + } + } + else + { + // 3/ if A is + and B is - C = A+B Mod + Add2SelfBigHex256(bigHexA, bigHexB); + } + } + else // if (bigHexA->sign == 1) + { + if (bigHexB->sign == 0) + { + Add2SelfBigHex256(bigHexA, bigHexB); + } + else + { + if ( isGreaterThanOrEqual256(bigHexB, bigHexA)) + { + bigHex256 BigHexResult; + + SubtractBigHex256(bigHexB, bigHexA, &BigHexResult); + copyBigHex256(&BigHexResult, bigHexA); + bigHexA->sign = 0; + } + else + { + SubtractFromSelfBigHex256(bigHexA, bigHexB); + } + } + } +} +/***************************************************************************** + * Following functions further extend on the basic functions to include Mod P. + * + * AddBigHexMod -- This function takes A and B which can be signed and output + * a result C which is less than P. + * It call AddBigHexSign and then perform Mod P on the output. + * If the output is -ive it recursively add P until we get a +ive + * number which is less than P. + * If the output is +ive it recursively subtracts P until we get + * a +number which is less than P. + * + * SubtractBigHexMod -- This function takes A and B which can be signed and output + * a result C which is less than P. + * It calls SubtractBigHexSign and then performs Mod P on the output. + * If the output is -ive it recursively add P until we get a +ive + * number which is less than P. + * If the output is +ive it recursively subtracts P until we get + * a +number which is less than P. + * + * MultiplyBigHexMod + ****************************************************************************/ +__RAM_ECDH void SubtractBigHexMod256(const bigHex256 *bigHexA, const bigHex256 *bigHexB, bigHex256 *BigHexResult) +{ + if (bigHexA->sign == 0) + { + if (bigHexB->sign == 0) + { + if ( isGreaterThanOrEqual256(bigHexA, bigHexB)) + { + SubtractBigHex256(bigHexA, bigHexB, BigHexResult); + BigHexResult->sign = 0; + } + else + { + SubtractBigHex256(bigHexB, bigHexA, BigHexResult); + BigHexResult->sign = 1; + } + } + else + { + // 3/ if A is + and B is - C = A+B Mod + AddBigHex256(bigHexA, bigHexB, BigHexResult); + BigHexResult->sign = 0; + } + } + else // if (bigHexA->sign == 1) + { + if (bigHexB->sign == 0) + { + AddBigHex256(bigHexA, bigHexB, BigHexResult); + BigHexResult->sign = 1; + } + else + { + if ( isGreaterThanOrEqual256(bigHexB, bigHexA)) + { + SubtractBigHex256(bigHexB, bigHexA, BigHexResult); + BigHexResult->sign = 0; + } + else + { + SubtractBigHex256(bigHexA, bigHexB, BigHexResult); + BigHexResult->sign = 1; + } + } + } + + if (BigHexResult->sign == 0x00) // Positive Number + { + if (isGreaterThanOrEqual256(BigHexResult, &bigHexP256)) + { + //SubtractFromSelfBigHexSign(BigHexResult,&bigHexP); + SubtractFromSelfBigHex256(BigHexResult, &bigHexP256); + } + } + else + { + AddP256(BigHexResult); + } +} + +// From curren t usage we can safely assume both inputs are positive. + +void SubtractBigHexUint32_256(const bigHex256 *bigHexA, const u_int32 numB, bigHex256 *BigHexResult) +{ + initBigNumber256(BigHexResult); + + if (bigHexA->num[HIGHEST_INDEX_BIG_HEX256] >= numB) + { + copyBigHex256(bigHexA, BigHexResult); + BigHexResult->num[ELEMENTS_BIG_HEX256 - 1] = bigHexA->num[ELEMENTS_BIG_HEX256 - 1] - numB; + } + else + { + bigHex256 N; + + initBigNumber256(&N); + + N.len = 1; + N.num[HIGHEST_INDEX_BIG_HEX256] = numB; + SubtractBigHexMod256(bigHexA, &N, BigHexResult); + } +} + + +__RAM_ECDH void MultiplyBigHexModP256(const bigHex256 *bigHexA, const bigHex256 *bigHexB, bigHex256 *BigHexResult) +{ + veryBigHex256 tmpResult; + { + s_int32 k; +#if (ECC_MULT_ALGO_TYPE == 16) + const u_int16 *numA = bigHexA->num; + const u_int16 *numB = bigHexB->num; + u_int16 *result = tmpResult.num; +#elif (ECC_MULT_ALGO_TYPE == 32) + const u_int32 *numA = bigHexA->num; + const u_int32 *numB = bigHexB->num; + u_int32 *result = tmpResult.num; +#endif // (ECC_MULT_ALGO_TYPE == 16) + memset(tmpResult.num, 0, sizeof(tmpResult.num)); + tmpResult.len = 0; + tmpResult.sign = 0; + // + // Below Optimisations seem to degrade performance on Windows by a factor of 2. + // + for (k = (ELEMENTS_BIG_HEX256 - 1); k >= 0; k--) + { + u_int32 mcarry = 0; + s_int32 j = 0; + + // The inner loop multiplies each byte of HexB by a single byte of + // HexA + for (j = (ELEMENTS_BIG_HEX256 - 1); j >= 0; j--) + { +#if (ECC_MULT_ALGO_TYPE == 16) + u_int32 val; + + val = (((u_int32)(numA[k]) ) * ((u_int32)(numB[j]))) + result[j + k + 1] + mcarry; + result[j + k + 1] = (val & 0xFFFF); + mcarry = (u_int16)( val >> 16); +#elif (ECC_MULT_ALGO_TYPE == 32) + u64 val; + + val = (((u64)(numA[k]) ) * ((u64)(numB[j]))) + result[j + k + 1] + mcarry; + result[j + k + 1] = (val & 0xFFFFFFFF); + mcarry = (u_int32)( val >> 32); +#endif // (ECC_MULT_ALGO_TYPE == 16) + } + } + setVeryBigNumberLength256(&tmpResult); + tmpResult.sign = (bigHexA->sign != bigHexB->sign); + } + + { + u_int32 i = 0; + bigHex256 tmpResult2; + + while ((tmpResult.num[i] == 0x00) && (i < (ELEMENTS_BIG_HEX256))) + { + i++; + } + + // Take the next 13 elements + // + tmpResult2.sign = tmpResult.sign; + + if (isVeryBigHexGreaterThanOrEqual256(&tmpResult, &veryBigHexP256)) + { + while (tmpResult.num[i] == 0x00) + { + i++; + } + } + memcpy(tmpResult2.num, tmpResult.num + i, sizeof(tmpResult2.num)); + setBigNumberLength256(&tmpResult2); + +#if (ECC_MULT_ALGO_TYPE == 16) + while ((i + ELEMENTS_BIG_HEX256) < (MAX_OCTETS256)) +#elif (ECC_MULT_ALGO_TYPE == 32) + while ((i + ELEMENTS_BIG_HEX256) < (MAX_OCTETS256 / 2)) +#endif // (ECC_MULT_ALGO_TYPE == 16) + { + specialModP256(&tmpResult2); + shiftLeftOneArrayElement256(&tmpResult2); + + // Add the next byte from A in left_over; + tmpResult2.num[HIGHEST_INDEX_BIG_HEX256] = tmpResult.num[i + ELEMENTS_BIG_HEX256]; + i++; + setBigNumberLength256(&tmpResult2); + } + + specialModP256(&tmpResult2); + copyBigHex256(&tmpResult2, BigHexResult); + } +} + + +__RAM_ECDH void MultiplyBigHexByUint32_256(const bigHex256 *bigHexA, const u_int32 numB, bigHex256 *BigHexResult) +{ +#if (ECC_MULT_ALGO_TYPE == 16) + s_int32 k; + const u_int16 *numA = bigHexA->num; + u_int16 *result = BigHexResult->num; + u_int16 mcarry = 0; + + // + // Below Optimisations seem to degrade performance on Windows by a factor of 2. + // + for (k = HIGHEST_INDEX_BIG_HEX256; k >= 0; k--) + { + u_int32 val; + + val = (((u_int32)(numA[k]) ) * ((u_int32)numB)) + mcarry; + result[k] = (val & 0xFFFF); + mcarry = (u_int16)( val >> 16); + + } +#elif (ECC_MULT_ALGO_TYPE == 32) + s_int32 k; + const u_int32 *numA = bigHexA->num; + u_int32 *result = BigHexResult->num; + u_int32 mcarry = 0; + + // + // Below Optimisations seem to degrade performance on Windows by a factor of 2. + // + for (k = HIGHEST_INDEX_BIG_HEX256; k >= 0; k--) + { + u64 val; + + val = (((u64)(numA[k]) ) * ((u64)numB)) + mcarry; + result[k] = (val & 0xFFFFFFFF); + mcarry = (u_int32)( val >> 32); + } +#endif // (ECC_MULT_ALGO_TYPE == 16) + setBigNumberLength256(BigHexResult); + BigHexResult->sign = bigHexA->sign; + specialModP256(BigHexResult); +} + + +__INLINE__ void shiftLeftOneArrayElement256(bigHex256 *input) +{ + memcpy(input->num, (input->num + 1), (8 * sizeof(u_int32))); +} + +// +// This function adds N * Mod P to a number. +// +// The left_over = tmpHexA % P + +__RAM_ECDH void specialModP256(bigHex256 *tmpHexA) +{ + bigHex256 NModP; +#if (ECC_MULT_ALGO_TYPE == 16) + u_int16 SignificantU16; +#elif (ECC_MULT_ALGO_TYPE == 32) + u_int32 SignificantU32; +#endif // (ECC_MULT_ALGO_TYPE == 16) + + initBigNumber256(&NModP); + if (((tmpHexA->sign == 0) && isGreaterThanOrEqual256(tmpHexA, &bigHexP256)) || + (tmpHexA->sign == 1)) + { + // If I multiply the most significant u_int16 of A by the Mod P and then subtract from A + // this is equivalent to an iteractive subtraction - but much faster. + if (tmpHexA->len > bigHexP256.len) + { + // approach +#if (ECC_MULT_ALGO_TYPE == 16) + SignificantU16 = GETMOSTSIGNIGICANTU16_256(tmpHexA); + MultiplyByU16ModP256(SignificantU16, &NModP); +#elif (ECC_MULT_ALGO_TYPE == 32) + SignificantU32 = GETMOSTSIGNIGICANTU32_256(tmpHexA); + MultiplyByU32ModP256(SignificantU32, &NModP); +#endif // (ECC_MULT_ALGO_TYPE == 16) + //tmpHexA->num[0] = 0x00; + + if (tmpHexA->sign == 0) + { + SubtractFromSelfBigHexSign256(tmpHexA, &NModP); + } + else + { + // Change sign of A to +ive + // Perform Subtraction + // Change sign of A back to -ive + tmpHexA->sign = 0; + SubtractFromSelfBigHexSign256(tmpHexA, &NModP); + tmpHexA->sign = 1; + } + } + + + if (((tmpHexA->sign == 0) && isGreaterThanOrEqual256(tmpHexA, &bigHexP256)) || + (tmpHexA->sign == 1)) + { + // It is implicit that the sign is negative. + // so we can remove the check. + // + if (tmpHexA->sign == 1) + { + AddP256(tmpHexA); + } + else + { + // Can this be replaced by Adding the invert of P + SubtractFromSelfBigHex256(tmpHexA, &bigHexP256); + } + } + } +} +#if (ECC_MULT_ALGO_TYPE == 32) +__RAM_ECDH void MultiplyByU32ModP256(const u_int32 N, bigHex256* result) +{ + u_int32 tempVal = (0xFFFFFFFF - N) + 1; + + result->num[0] = N - 1; + result->num[1] = (u_int32)tempVal; + result->num[2] = N ; + result->num[3] = 0x00 ; + result->num[4] = 0x00 ; + result->num[5] = N - 1; + result->num[6] = 0xFFFFFFFF; + result->num[7] = 0xFFFFFFFF; + result->num[8] = (u_int32)tempVal; + + result->sign = 0x00; + if (result->num[0]) + { + result->len = 0x9; + } + else + { + result->len = 0x8; + } +} +#endif + +#if (ECC_MULT_ALGO_TYPE == 16) +__RAM_ECDH void MultiplyByU16ModP256(const u_int16 N, bigHex256* result) +{ + + result->num[0] = N - 1; + result->num[1] = 0xFFFF; + result->num[2] = 0xFFFF - (N - 1); + result->num[3] = 0; + result->num[4] = N; + result->num[5] = 0; + result->num[6] = 0; + result->num[7] = 0; + result->num[8] = 0; + result->num[9] = 0; + result->num[10] = N - 1; + result->num[11] = 0xFFFF; + result->num[12] = 0xFFFF; + result->num[13] = 0xFFFF; + result->num[14] = 0xFFFF; + result->num[15] = 0xFFFF; + result->num[16] = 0xFFFF - (N - 1); + + result->sign = 0x00; + if (result->num[0]) + { + result->len = 17; + } + else + { + result->len = 16; + } +} +#endif // (ECC_MULT_ALGO_TYPE == 16) + +__RAM_ECDH __INLINE__ void copyBigHex256(const bigHex256 *source, bigHex256 *destination) +{ + memcpy(destination->num, source->num, sizeof(destination->num)); //for P256 max_octets = 36 + + destination->len = source->len; + destination->sign = source->sign; +} + +__RAM_ECDH __INLINE__ void initBigNumber256(bigHex256 *BigHexResult) +{ + memset(BigHexResult->num, 0, sizeof(BigHexResult->num)); + + BigHexResult->len = 0; + BigHexResult->sign = 0; +} + +__RAM_ECDH __INLINE__ void setBigNumberLength256(bigHex256 *BigHexResult) +{ + int i; + + for (i = 0; i < (ELEMENTS_BIG_HEX256); i++) + { + if (BigHexResult->num[i] != 0x00) + { + break; + } + } + BigHexResult->len = (ELEMENTS_BIG_HEX256) - i; +} + +__RAM_ECDH __INLINE__ void setVeryBigNumberLength256(veryBigHex256 *BigHexResult) +{ + int i; + +#if (ECC_MULT_ALGO_TYPE == 16) + for (i = 0; i < (MAX_OCTETS256); i++) +#elif (ECC_MULT_ALGO_TYPE == 32) + for (i = 0; i < (MAX_OCTETS256 / 2); i++) +#endif // (ECC_MULT_ALGO_TYPE == 16) + { + if (BigHexResult->num[i] != 0x00) + { + break; + } + } +#if (ECC_MULT_ALGO_TYPE == 16) + BigHexResult->len = (MAX_OCTETS256) - i; +#elif (ECC_MULT_ALGO_TYPE == 32) + BigHexResult->len = (MAX_OCTETS256 / 2) - i; +#endif // (ECC_MULT_ALGO_TYPE == 16) +} + +// +// if A > B return TRUE +// + +__RAM_ECDH __INLINE__ int isGreaterThan256(const bigHex256 *bigHexA, const bigHex256 *bigHexB) +{ + + u_int32 i; + u_int32 A_len = bigHexA->len; + u_int32 B_len = bigHexB->len; + + if (A_len > B_len) + { + return 1; + } + else if (A_len < B_len) + { + return 0; + } + + // Now we have two equal sized arrays which we need to compare. + // . + for (i = ((ELEMENTS_BIG_HEX256) - A_len); i < (ELEMENTS_BIG_HEX256); i++) + { + if (bigHexB->num[i] > bigHexA->num[i]) + { + return 0; + } + else if (bigHexB->num[i] < bigHexA->num[i]) + { + return 1; + } + } + return 0; +} + + +__RAM_ECDH __INLINE__ int isGreaterThanOrEqual256(const bigHex256 *bigHexA, const bigHex256 *bigHexB) +{ + u_int32 i; + u_int32 A_len = bigHexA->len; + u_int32 B_len = bigHexB->len; + + if (A_len > B_len) + { + return 1; + } + else if (A_len < B_len) + { + return 0; + } + + // Now we have two equal sized arrays which we need to compare. + // . + + for (i = ((ELEMENTS_BIG_HEX256) - A_len); i < (ELEMENTS_BIG_HEX256); i++) + { + if (bigHexB->num[i] > bigHexA->num[i]) + { + return 0; + } + else if (bigHexB->num[i] < bigHexA->num[i]) + { + return 1; + } + } + return 1; +} + + +__RAM_ECDH __INLINE__ int isVeryBigHexGreaterThanOrEqual256(const veryBigHex256 *bigHexA, const veryBigHex256 *bigHexB) +{ + int i; + u_int32 A_len = bigHexA->len; + u_int32 B_len = bigHexB->len; + + if (A_len > B_len) + { + return 1; + } + else if (A_len < B_len) + { + return 0; + } + + // Now we have two equal sized arrays which we need to compare. + // +#if (ECC_MULT_ALGO_TYPE == 16) + for (i = ((MAX_OCTETS256) - A_len); i < (MAX_OCTETS256); i++) +#elif (ECC_MULT_ALGO_TYPE == 32) + for (i = ((MAX_OCTETS256 / 2) - A_len); i < (MAX_OCTETS256 / 2); i++) +#endif // (ECC_MULT_ALGO_TYPE == 16) + { + + if (bigHexB->num[i] != bigHexA->num[i]) + { + return (bigHexB->num[i] < bigHexA->num[i]); + } + + } + return 1; +} + + +/*__INLINE__*/__RAM_ECDH int notEqual256(const bigHex256 *bigHexA, const bigHex256 *bigHexB) +{ + u_int32 i; + + for (i = 0; i < (ELEMENTS_BIG_HEX256); i++) + { + if (bigHexA->num[i] != bigHexB->num[i]) + { + return 1; + } + } + return 0; +} + +__RAM_ECDH __INLINE__ int Is_Infinite256(const ECC_Jacobian_Point256* pPointP) +{ + return ( (!notEqual256(&pPointP->x, &ecc_Jacobian_InfinityPoint256.x)) && (!notEqual256(&pPointP->y, &ecc_Jacobian_InfinityPoint256.y)) && (!notEqual256(&pPointP->z, &ecc_Jacobian_InfinityPoint256.z))); +} + +//isLessThan +__RAM_ECDH __INLINE__ int isLessThan256(const bigHex256 *bigHexA, const bigHex256 *bigHexB) +{ + u_int32 i; + + if (bigHexA->len < bigHexB->len) + { + return 1; + } + else if (bigHexA->len > bigHexB->len) + { + return 0; + } + + // Now we have two equal sized arrays which we need to compare. + // Start at the last entry is each array and compare. + + for (i = bigHexA->len; i != 0; i--) + { + if (bigHexB->num[i] < bigHexA->num[i]) + { + return 0; + } + break; + } + return 1; +} + +/*********** JACOBIAN ******/ +__RAM_ECDH int GF_Jacobian_Point_Addition256(const ECC_Jacobian_Point256* pPointP, const ECC_Jacobian_Point256* pPointQ, ECC_Jacobian_Point256* pResultPoint) +{ + +// This should be 12 Multiplications and 2 Squares +// currently implemented as 12 Muls and 2 Squares and one cube +// Let (X1, Y1, Z1) and (X2, Y2, Z2) be two points (both unequal to the 'point at infinity') represented in 'Standard Projective Coordinates'. Then the sum (X3, Y3, Z3) can be calculated by +// +// U1 = Y2*Z1 +// U2 = Y1*Z2 +// V1 = X2*Z1 +// V2 = X1*Z2 +// if (V1 == V2) +// if (U1 != U2) +// return POINT_AT_INFINITY +// else +// return POINT_DOUBLE(X1, Y1, Z1) +// U = U1 - U2 +// V = V1 - V2 +// W = Z1*Z2 + +// A = U^2*W - V^3 - 2*V^2*V2 +// X3 = V*A +// Y3 = U*(V^2*V2 - A) - V^3*U2 +// Z3 = V^3*W +// return (X3, Y3, Z3) + + bigHex256 jac_U1; + bigHex256 jac_U2; + bigHex256 jac_V1; + bigHex256 jac_V2; + bigHex256 jac_U; + bigHex256 jac_V; + bigHex256 jac_A; + bigHex256 jac_W; + bigHex256 V_sqr; + bigHex256 V_cube; + bigHex256 U_sqr; + bigHex256 V_sqr_mult_by_V2; + + const bigHex256 *pJac_PointX1 = &pPointP->x; + const bigHex256 *pJac_PointY1 = &pPointP->y; + const bigHex256 *pJac_PointZ1 = &pPointP->z; + + const bigHex256 *pJac_PointX2 = &pPointQ->x; + const bigHex256 *pJac_PointY2 = &pPointQ->y; + const bigHex256 *pJac_PointZ2 = &pPointQ->z; + + initBigNumber256(&pResultPoint->x); + initBigNumber256(&pResultPoint->y); + initBigNumber256(&pResultPoint->z); + + initBigNumber256(&jac_U1); + initBigNumber256(&jac_U2); + initBigNumber256(&jac_V1); + initBigNumber256(&jac_V2); + + initBigNumber256(&jac_U); + initBigNumber256(&jac_V); + initBigNumber256(&jac_A); + initBigNumber256(&jac_W); + + initBigNumber256(&V_sqr); + initBigNumber256(&V_cube); + initBigNumber256(&U_sqr); + initBigNumber256(&V_sqr_mult_by_V2); + + + // First Handle points of infinity + /* + P1 and P2 are both infinite: P3=infinite. + P1 is infinite: P3=P2. + P2 is infinite: P3=P1. + P1 and P2 have the same x coordinate, but different y coordinates or both y coordinates equal 0: P3=infinite. + + */ + if (Is_Infinite256(pPointP)) + { + if (Is_Infinite256(pPointQ)) + { + // Result = Infinity + //pResultPoint = Infinity + GF_Jacobian_Point_Copy256(&ecc_Jacobian_InfinityPoint256, pResultPoint); + return 0; + } + else + { + // Result = pPointQ + // pResultPoint = pPointQ + GF_Jacobian_Point_Copy256(pPointQ, pResultPoint); + return 0; + } + } + else if (Is_Infinite256(pPointQ)) + { + // Result = pPointP + // pResultPoint = pPointP; + GF_Jacobian_Point_Copy256(pPointP, pResultPoint); + return 0; + } + + if (!notEqual256(&pPointQ->x, &pPointP->x)) // Same X coordinate + { + if (notEqual256(&pPointQ->y, &pPointP->y)) // Different Y coordinates + { + // Result = Infinity + GF_Jacobian_Point_Copy256(&ecc_Jacobian_InfinityPoint256, pResultPoint); + return 0; + + } + else if ((pPointQ->y.len <= 1) && (pPointQ->y.num[HIGHEST_INDEX_BIG_HEX256] == 0)) // Y co-ords = 0 + { + // Result = Infinity + GF_Jacobian_Point_Copy256(&ecc_Jacobian_InfinityPoint256, pResultPoint); + return 0; + } + } + +// U1 = Y2*Z1 +// U2 = Y1*Z2 +// V1 = X2*Z1 +// V2 = X1*Z2 + + MultiplyBigHexModP256(pJac_PointY2, pJac_PointZ1, &jac_U1); + MultiplyBigHexModP256(pJac_PointY1, pJac_PointZ2, &jac_U2); + MultiplyBigHexModP256(pJac_PointX2, pJac_PointZ1, &jac_V1); + MultiplyBigHexModP256(pJac_PointX1, pJac_PointZ2, &jac_V2); + +// if (V1 == V2) +// if (U1 != U2) +// return POINT_AT_INFINITY +// else +// return POINT_DOUBLE(X1, Y1, Z1) + + if (!notEqual256(&jac_V1, &jac_V2)) + { + if (notEqual256(&jac_U1, &jac_U2)) + { + // Result = Infinity + GF_Jacobian_Point_Copy256(&ecc_Jacobian_InfinityPoint256, pResultPoint); + return 0; + } + else + { + GF_Jacobian_Point_Double256(pPointP, pResultPoint); + return 0; //POINT_DOUBLE(&jac_PointX1,&jac_PointY1,&jac_PointZ1); + } + } + +// U = U1 - U2 +// V = V1 - V2 +// W = Z1*Z2 ( 5 muls to here ) +// A = U^2*W - V^3 - 2*V^2*V2 + + SubtractBigHexMod256(&(jac_U1), &(jac_U2), &jac_U); + SubtractBigHexMod256(&(jac_V1), &(jac_V2), &jac_V); + + MultiplyBigHexModP256(pJac_PointZ1, pJac_PointZ2, &jac_W); + + { + // Determine A + // A = U^2*W - V^3 - 2*V^2*V2 + // V_sqr = V^2 + // V_cube = V^3 + // U_sqr = U^2 + // int1 = V_sqr * V2 + // int2 = 2 * int1 -- (2*V^2*V2) + // int3 = U_sqr * W + // int4 = int3 - V_cube + // A = int4 - int2 + + // X3 = D^2 - int3 + + bigHex256 int1; + bigHex256 int3; + bigHex256 int4; + bigHex256 Double_V_sqr_mult_by_V2; + + initBigNumber256(&int1); + initBigNumber256(&int3); + initBigNumber256(&int4); + initBigNumber256(&Double_V_sqr_mult_by_V2); + + MultiplyBigHexModP256(&jac_V, &jac_V, &V_sqr); + MultiplyBigHexModP256(&V_sqr, &jac_V, &V_cube); + MultiplyBigHexModP256(&jac_U, &jac_U, &U_sqr); + + MultiplyBigHexModP256(&V_sqr, &jac_V2, &V_sqr_mult_by_V2); // V^2 * V2 + + MultiplyBigHexByUint32_256(&V_sqr_mult_by_V2, 0x02, &Double_V_sqr_mult_by_V2); // 2 * V^2 * V2 + MultiplyBigHexModP256(&U_sqr, &jac_W, &int3); // U^2 * W + SubtractBigHexMod256(&int3, &V_cube, &int4); // (U^2 * W) - V^3 + SubtractBigHexMod256(&int4, &Double_V_sqr_mult_by_V2, &jac_A); // A = U^2*W - V^3 - 2*V^2*V2 + } + + // Determine X3 + { + // X3 = V*A + + MultiplyBigHexModP256(&jac_V, &jac_A, &(pResultPoint->x)); + } + // Determine Y3 + { + // Y3 = U*(V^2*V2 - A) - V^3*U2 + // int1 = (V^2*V2 - A) + // int2 = U*(V^2*V2 - A) + // int3 = V^3*U2 + bigHex256 int1; + bigHex256 int2; + bigHex256 int3; + + initBigNumber256(&int1); + initBigNumber256(&int2); + initBigNumber256(&int3); + + SubtractBigHexMod256(&V_sqr_mult_by_V2, &jac_A, &int1); // int1 =( V^2*V2 - A) + // Below line was incorrect + + MultiplyBigHexModP256(&jac_U, &int1, &int2); // int2 = U * ( V^2*V2 - A) + // + MultiplyBigHexModP256(&V_cube, &jac_U2, &int3); // int3 = V^3 * U2 + SubtractBigHexMod256(&int2, &int3, &(pResultPoint->y)); + } + + + // Determine Z3 + { + // Z3 = V^3*W + MultiplyBigHexModP256(&V_cube, &jac_W, &(pResultPoint->z)); + } + + return 1; +} + +__RAM_ECDH int GF_Jacobian_Point_Double256(const ECC_Jacobian_Point256* pPointP, ECC_Jacobian_Point256* pResultPoint) +{ +//if (Y == 0) +// return POINT_AT_INFINITY +//W = a*Z^2 + 3*X^2 +// if a = -3, then W can also be calculated as W = 3*(X + Z)*(X - Z), saving 2 field squarings +// THUS +//W = 3*(X+Z)*(X-Z) +//S = Y*Z +//B = X*Y*S +//H = W^2 - 8*B +//X' = 2*H*S +//Y' = W*(4*B - H) - 8*Y^2*S^2 +//Z' = 8*S^3 +//return (X', Y', Z') + + const bigHex256 *pJac_PointX1 = &pPointP->x; + const bigHex256 *pJac_PointY1 = &pPointP->y; + const bigHex256 *pJac_PointZ1 = &pPointP->z; + + bigHex256 W; + bigHex256 S; + bigHex256 B; + bigHex256 H; + bigHex256 S_sqr; + + if (((pJac_PointY1->len <= 1) && (pJac_PointY1->num[HIGHEST_INDEX_BIG_HEX256] == 0x00)) || + Is_Infinite256(pPointP)) + { + // Point at Infinity + // pResultPoint = Infinity + GF_Jacobian_Point_Copy256(&ecc_Jacobian_InfinityPoint256, pResultPoint); + return 0; + } + + // Determine W + { + bigHex256 X_plus_Z; + bigHex256 X_minus_Z; + bigHex256 int1; + + // Need to convert below to AddBigHexModP to consider sign and mod.. + AddBigHexModP256(pJac_PointX1, pJac_PointZ1, &X_plus_Z); + SubtractBigHexMod256(pJac_PointX1, pJac_PointZ1, &X_minus_Z); + MultiplyBigHexModP256(&X_plus_Z, &X_minus_Z, &int1); + MultiplyBigHexByUint32_256(&(int1), 0x03, &W); + } + // Determine S + { + MultiplyBigHexModP256(pJac_PointY1, pJac_PointZ1, &S); + } + // Determine B + { + bigHex256 int1; + + //B = X*Y*S + MultiplyBigHexModP256(pJac_PointY1, &S, &int1); + MultiplyBigHexModP256(pJac_PointX1, &int1, &B); + } + + // Determine H + { + //H = W^2 - 8*B + bigHex256 W_sqr; + bigHex256 Eight_B; + + MultiplyBigHexModP256(&W, &W, &W_sqr); + MultiplyBigHexByUint32_256(&B, 8, &Eight_B); + + SubtractBigHexMod256(&W_sqr, &Eight_B, &H); + } + // Determine X + //X = 2*H*S + { + bigHex256 int1; + + MultiplyBigHexModP256(&H, &S, &int1); + MultiplyBigHexByUint32_256((const bigHex256 *)(&int1), 0x02, &pResultPoint->x); + + } + // Determine Y + // Y' = W*(4*B - H) - 8*Y^2*S^2 + + { + bigHex256 Y_sqr; + bigHex256 int1; + bigHex256 int2; // 8*Y^2*S^2 + bigHex256 int3; + bigHex256 int4; + bigHex256 int5; + + // 8*Y^2*S^2 + MultiplyBigHexModP256(pJac_PointY1, pJac_PointY1, &Y_sqr); + MultiplyBigHexModP256(&S, &S, &S_sqr); + MultiplyBigHexModP256(&Y_sqr, &S_sqr, &int1); + MultiplyBigHexByUint32_256(&(int1), 0x08, &int2); + + // 4 * B + MultiplyBigHexByUint32_256(&B, 0x04, &int3); + // (4*B - H) + SubtractBigHexMod256(&int3, &H, &int4); + // W * (4*B - H) + MultiplyBigHexModP256(&W, &int4, &int5); + + SubtractBigHexMod256((const bigHex256 *)&int5, (const bigHex256 *)&int2, &pResultPoint->y); + + } + + // Determine Z + { + //Z1 = 8*S^3 + bigHex256 int1; + + MultiplyBigHexModP256(&S_sqr, &S, &int1); + MultiplyBigHexByUint32_256(&int1, 0x08, &pResultPoint->z); + } + return 0; +} + +__RAM_ECDH void GF_Point_Jacobian_To_Affine256(ECC_Jacobian_Point256* pJacPoint, bigHex256* pX_common_ord_affine, bigHex256* pY_common_ord_affine ) +{ + bigHex256 inverted_Z_jacobian; + + // x_affine = X_jacobian/Z_jacobian + // y_affine = Y_jacobian/Z_jacobian + + DBG_SWDIAG(ECDH, INV, 1); + // First Determine 1/Z_jacobian + bigHexInversion256(&pJacPoint->z, &inverted_Z_jacobian); + DBG_SWDIAG(ECDH, INV, 0); + + MultiplyBigHexModP256(&pJacPoint->x, &inverted_Z_jacobian, pX_common_ord_affine); + MultiplyBigHexModP256(&pJacPoint->y, &inverted_Z_jacobian, pY_common_ord_affine); + +} + + +__RAM_ECDH __INLINE__ void GF_Point_Copy256(const ECC_Point256 *source, ECC_Point256 *destination) +{ + copyBigHex256(&source->x, &destination->x); + copyBigHex256(&source->y, &destination->y); +} + + +__RAM_ECDH __INLINE__ void GF_Jacobian_Point_Copy256(const ECC_Jacobian_Point256 *source, ECC_Jacobian_Point256 *destination) +{ + copyBigHex256(&source->x, &destination->x); + copyBigHex256(&source->y, &destination->y); + copyBigHex256(&source->z, &destination->z); +} + +__RAM_ECDH __INLINE__ void GF_Affine_To_Jacobian_Point_Copy256(const ECC_Point256 *source, ECC_Jacobian_Point256 *destination) +{ + bigHex256 BigHex_1; + + BigHex_1.len = 0x01; + BigHex_1.sign = 0; // Positive Number + memset(BigHex_1.num, 0, sizeof(BigHex_1.num) ); + BigHex_1.num[HIGHEST_INDEX_BIG_HEX256] = 0x01; + copyBigHex256(&source->x, &destination->x); + copyBigHex256(&source->y, &destination->y); + copyBigHex256(&BigHex_1, &destination->z); +} + +__RAM_ECDH __INLINE__ void GF_Setup_Jacobian_Infinity_Point256(ECC_Jacobian_Point256 *infinity) +{ + bigHex256 BigHex_1; + + BigHex_1.len = 0x01; + BigHex_1.sign = 0; // Positive Number + memset(BigHex_1.num, 0, sizeof(BigHex_1.num) ); + BigHex_1.num[HIGHEST_INDEX_BIG_HEX256] = 0x00; + copyBigHex256(&BigHex_1, &infinity->x); + BigHex_1.num[HIGHEST_INDEX_BIG_HEX256] = 0x01; + copyBigHex256(&BigHex_1, &infinity->y); + BigHex_1.num[HIGHEST_INDEX_BIG_HEX256] = 0x00; + copyBigHex256(&BigHex_1, &infinity->z); + +} + +/************************************************************** + * Function :- bigHexInversion + * + * Parameters :- bigHexA - a pointer to bigHex - the input + * pResult - a pointer to bigHex - the output + * + * Description + * This function performs the inversion of a bigHex number. The output multiplied + * by the input will result in '1', as the output is Moded by P. + * + * ( bigHexA * pResult ) % P = 1. + * + * Ref " Software Implementation of the NIST Elliptical " + * Input : Prime P (bigHexP), a (bigHexA) E [1, p-1] + * Output : a^-1 mod P + ************************************************************************/ + +__RAM_ECDH void bigHexInversion256( bigHex256* bigHexA, bigHex256* pResult) +{ + bigHex256 u; + bigHex256 v; + bigHex256 A; + bigHex256 C; + + // Change the sign to positive + bigHexA->sign = 0; + + // Step 1 + // u <-- a, v <-- p, A <-- 1, C <-- 0. + // + initBigNumber256(&A); + initBigNumber256(&C); + + copyBigHex256(bigHexA, &u); + copyBigHex256(&bigHexP256, &v); + + A.num[HIGHEST_INDEX_BIG_HEX256] = 1; + C.num[HIGHEST_INDEX_BIG_HEX256] = 0; + A.len = 1; + C.len = 1; + + // + // Step 2. + // While u != 0 do + // 2.1 While u is even do : + // u <-- u/2. If A is even then A <-- A/2; else A <-- (A+P)/2 + // 2.2 While v is even do : + // v <-- v/2. If C is even then C <-- C/2; else C <-- (C+P)/2 + // 2.3 If u >= v then : u <-- u - v, A <-- A - C; else v <-- v - u, C <-- C - A + // + while (u.len != 0) + { + while (ISBIGHEXEVEN256(u)) + { + divideByTwo256(&u); + if (ISBIGHEXEVEN256(A)) + { + // A = A/2 + divideByTwo256(&A); + } + else + { + AddPdiv2_256(&A); + } + } + while (ISBIGHEXEVEN256(v)) + { + divideByTwo256(&v); + if (ISBIGHEXEVEN256(C)) + { + divideByTwo256(&C); + } + else + { + AddPdiv2_256(&C); + } + } + if (isGreaterThanOrEqual256(&u, &v)) + { + SubtractFromSelfBigHex256(&u, &v); + SubtractFromSelfBigHexSign256(&A, &C); + } + else + { + SubtractFromSelfBigHex256(&v, &u); + SubtractFromSelfBigHexSign256(&C, &A); + } + } + // Step 3 :- Now perform Mod P + // pResult = C % P + { + // If the Mod P is greater than bigHexA then return with + // C unmodified. + + if (C.sign == 0) + { + if (isGreaterThan256(&bigHexP256, &C)) + { + copyBigHex256(&C, pResult); + return; + } + else // Positive Number thus subtract P iteratively. + { + specialModP256(&C); + } + } + else // Negative Number + { + specialModP256(&C); + } + copyBigHex256(&C, pResult); + } +} + +/******************************************************************* + * Funcion :- divideByTwo + * + * Parameters :- A - a bigHex pointer - which is the divided by two + * + *******************************************************************/ + +__RAM_ECDH void divideByTwo256(bigHex256* A) +{ +#if (ECC_MULT_ALGO_TYPE == 16) + u_int16 rem = 0; + u_int32 val; + u_int32 i; + + for (i = 0; i < (ELEMENTS_BIG_HEX256); i++) + { + val = (u_int32)((u_int32)(A->num[i]) + ((u_int32)(rem << 16))); + + A->num[i] = (u_int16)(val >> 1); + rem = (u_int32)(val - ((val >> 1) << 1)); + } +#elif (ECC_MULT_ALGO_TYPE == 32) + u_int32 rem = 0; + u64 u64val; + u_int32 i; + + for (i = 0; i < (ELEMENTS_BIG_HEX256); i++) + { + u64val = (u64)((u64)(A->num[i]) + ((u64)rem * _LL(0x100000000))); + + A->num[i] = (u_int32)(u64val >> 1); + rem = (u64)(u64val - ((u64val >> 1) << 1)); + } +#endif // (ECC_MULT_ALGO_TYPE == 16) + // We need to re-calculate the length. + setBigNumberLength256(A); +} + +// Q = kP +// +/******************************************************** + * Function :- ECC_Point_Multiplication + * + * Parameters :- pk - a pointer to a bigHex which the point should be multiplied by. + * pPointP - pointer to the point which is to be multiplied by pk + * + * Description + * This function performs ECC point multiplication. It uses the Scalar Multiplication + * algorithm. Scalar multiplication works is way through the bits of a BigHex starting with the LSB. + * For each bit (irrespective of Value) a point Doubling is performed, if the bit has a value = 1 then + * a point addition is also performed. + * + * Scalar Multiplication: LSB first + * - Require k=(km-1,km-2,?k0)2, km=1 + * - Compute Q=kP + * - Q=0, R=P + * - For i=0 to m-1 + * - If ki=1 then + * - Q=Q+R + * - End if + * - R=2R + * - End for + * - Return Q + ******************************************************************************************/ +#if (ECC_4BIT_WIN_OPT == 0) +/** + **************************************************************************************** + * @brief Outer function for ECC point multiplications, both multiply an ECC point by 8 bits. + * + * Used to continue ECC P256 algorithm. + **************************************************************************************** + */ +__RAM_ECDH static void ecc_point_multiplication_uint8_256(struct ecc_elt_tag* ecc_elt) +{ + ECC_Jacobian_Point256 tmpResultPoint; + ECC_Jacobian_Point256 tmpResultPoint2; + ECC_Jacobian_Point256 *jPointQ256 = &(ecc_elt->Jacobian_PointQ256); + ECC_Jacobian_Point256 *jPointR256 = &(ecc_elt->Jacobian_PointR256); + + if (ecc_elt->bit_cursor == 0) + { + ecc_elt->current_val = ecc_elt->Pk256.num[ecc_elt->Point_Mul_Word256 - 1]; + ecc_elt->bit_cursor = ECC_MULT_ALGO_TYPE; + } + + // check if bit in current val is set + if (ecc_elt->current_val & 0x1) + { + // Q = Q + R + GF_Jacobian_Point_Addition256(jPointQ256, jPointR256, &tmpResultPoint); + // Copy ResultPoint to PointQ + GF_Jacobian_Point_Copy256(&tmpResultPoint, jPointQ256); + } + // Point Doubling + // R = 2R + GF_Jacobian_Point_Double256(jPointR256, &tmpResultPoint2); + // Copy Result point to PointR + GF_Jacobian_Point_Copy256(&tmpResultPoint2, jPointR256); + + // update current value to check next bit + ecc_elt->current_val = ecc_elt->current_val >> 1; + ecc_elt->bit_cursor--; + + // check if a full word has been calculated + if (ecc_elt->bit_cursor == 0) + { + // decrement the counter + ecc_elt->Point_Mul_Word256--; + } +} +#endif + +#if (ECC_4BIT_WIN_OPT == 1) + +__RAM_ECDH static void ecc_point_multiplication_win_256(struct ecc_elt_tag* ecc_elt) +{ + ECC_Jacobian_Point256 tmpResultPoint; + ECC_Jacobian_Point256 tmpResultPoint2; + ECC_Jacobian_Point256 *ecc_lookup_table; + ECC_Jacobian_Point256 *jPointQ256 = &(ecc_elt->Jacobian_PointQ256); + + u_int8 IndexVal; +#if (ECC_MULT_ALGO_TYPE == 16) + uint16_t i = ecc_elt->bit_cursor; +#else + uint32_t i = ecc_elt->bit_cursor; +#endif + // Give i -- need to work out the index val. + // i = 0 -> indexVal = bit192:bit128;bit64:bit0 + // i = 1 -> indexVal = bit193:bit129;bit65:bit1 + + if ((ecc_elt->key_type == ECC_PUBLICKEY_GENERATION) || (ecc_elt->key_type == ECC_DHKEY_GENERATION)) + { + if (ecc_elt->key_type == ECC_PUBLICKEY_GENERATION) + { + ecc_lookup_table = (ECC_Jacobian_Point256 *)&ECC_4Win_Look_up_table[0]; + } + else + { + ecc_lookup_table = &ecc_elt->win_4_table[0]; + } + + IndexVal = ((ecc_elt->Pk256.num[((255 - i) / ECC_MULT_ALGO_TYPE) + 1] >> (i % ECC_MULT_ALGO_TYPE)) & 0x01) + + (((ecc_elt->Pk256.num[((191 - i) / ECC_MULT_ALGO_TYPE) + 1] >> (i % ECC_MULT_ALGO_TYPE)) & 0x01 ) * 0x02) + + (((ecc_elt->Pk256.num[((127 - i) / ECC_MULT_ALGO_TYPE) + 1] >> (i % ECC_MULT_ALGO_TYPE)) & 0x01 ) * 0x04) + + (((ecc_elt->Pk256.num[((63 - i) / ECC_MULT_ALGO_TYPE) + 1] >> (i % ECC_MULT_ALGO_TYPE)) & 0x01 ) * 0x08); + + if (IndexVal != 0) + { + GF_Jacobian_Point_Copy256(&ecc_lookup_table[IndexVal - 1], &tmpResultPoint); + GF_Jacobian_Point_Addition256(&tmpResultPoint, jPointQ256, &tmpResultPoint2); + GF_Jacobian_Point_Copy256(&tmpResultPoint2, jPointQ256); + } + + if (ecc_elt->bit_cursor != 0) + { + // Point Doubling + // R = 2R + GF_Jacobian_Point_Double256(jPointQ256, &tmpResultPoint2); + // Copy Result point to PointR + GF_Jacobian_Point_Copy256(&tmpResultPoint2, jPointQ256); + ecc_elt->bit_cursor--; + } + else + { + ecc_elt->Point_Mul_Word256 = 0; + } + } + else if (ecc_elt->key_type == ECC_4BIT_TABLE_GENERATION_PT1) + { + /// + /// Perform Double of the point R - copy result to R. + GF_Jacobian_Point_Double256(&ecc_elt->Jacobian_PointR256, &tmpResultPoint); + GF_Jacobian_Point_Copy256(&tmpResultPoint, &ecc_elt->Jacobian_PointR256); + ecc_elt->bit_cursor++; + + if (ecc_elt->bit_cursor == 64) + { + GF_Jacobian_Point_Copy256(&ecc_elt->Jacobian_PointR256, &ecc_elt->win_4_table[1]); + } + else if (ecc_elt->bit_cursor == 128) + { + + GF_Jacobian_Point_Copy256(&ecc_elt->Jacobian_PointR256, &ecc_elt->win_4_table[3]); + } + else if (ecc_elt->bit_cursor == 192) + { + + GF_Jacobian_Point_Copy256(&ecc_elt->Jacobian_PointR256, &ecc_elt->win_4_table[7]); + + // Now move onto second part of generating the table - + ecc_elt->key_type = ECC_4BIT_TABLE_GENERATION_PT2; + ecc_elt->bit_cursor = 3; + } + + } + else if (ecc_elt->key_type == ECC_4BIT_TABLE_GENERATION_PT2) + { + + if (ecc_elt->bit_cursor == 3) // Construct - table entry corresponding to BitVal = 0011 (table index 2) + { + GF_Jacobian_Point_Addition256(&ecc_elt->win_4_table[0], &ecc_elt->win_4_table[1], &ecc_elt->win_4_table[2]); + // Next entry is BitVal == 0101 - Table Index 4 + ecc_elt->bit_cursor = 5; + } + + else if (ecc_elt->bit_cursor == 5) + { + GF_Jacobian_Point_Addition256(&ecc_elt->win_4_table[0], &ecc_elt->win_4_table[3], &ecc_elt->win_4_table[4]); + // Next entry is BitVal == 0110 - Table Index 5 + ecc_elt->bit_cursor = 6; + } + else if (ecc_elt->bit_cursor == 6) + { + // Was 1 + 3 = 5 0010 + 0100 =0110 + + GF_Jacobian_Point_Addition256(&ecc_elt->win_4_table[1], &ecc_elt->win_4_table[3], &ecc_elt->win_4_table[5]); + // Next entry is BitVal == 0111 - Table Index 6 + ecc_elt->bit_cursor = 7; + } + else if (ecc_elt->bit_cursor == 7) + { + GF_Jacobian_Point_Addition256(&ecc_elt->win_4_table[0], &ecc_elt->win_4_table[5], &ecc_elt->win_4_table[6]); + // Next entry is BitVal == 1001 - Table Index 8 + ecc_elt->bit_cursor = 9; + } + else if ((ecc_elt->bit_cursor >= 9) && (ecc_elt->bit_cursor <= 15)) // between 1001b and 1111b + { + GF_Jacobian_Point_Addition256(&ecc_elt->win_4_table[7], &ecc_elt->win_4_table[ecc_elt->bit_cursor - 9], &ecc_elt->win_4_table[ecc_elt->bit_cursor - 1]); + if (ecc_elt->bit_cursor == 15) // TABLE Generation complete + { + // Move on to the usage of the Table to generate the DH_KEY + ecc_elt->key_type = ECC_DHKEY_GENERATION; + ecc_elt->bit_cursor = 63; + } + else + { + ecc_elt->bit_cursor++; + } + } + } + +} + +#endif + +__RAM_ECDH static bool ecc_is_valid_point(bigHex256* X_coord, bigHex256* Y_coord) +{ + // Check to see if X and Y point exist on the ECDH curve. + // This is only required for Public Keys recieved from the peer. + // Y^2 = X^3 - 3X + b + + bigHex256 Y_square; + bigHex256 X_square; + bigHex256 X_cube; + bigHex256 double_X; + bigHex256 tripple_X; + bigHex256 interim_result1; + bigHex256 interim_result2; + + initBigNumber256(&Y_square); + initBigNumber256(&X_square); + initBigNumber256(&X_cube); + + initBigNumber256(&double_X); + initBigNumber256(&tripple_X); + initBigNumber256(&interim_result1); + initBigNumber256(&interim_result2); + + // First Determine Y^2 + MultiplyBigHexModP256(Y_coord, Y_coord, &Y_square); + + // Now Determine X^3 + MultiplyBigHexModP256(X_coord, X_coord, &X_square); + MultiplyBigHexModP256(X_coord, &X_square, &X_cube); + + // Determine 3x + AddBigHexModP256(X_coord, X_coord, &double_X); + AddBigHexModP256(&double_X, X_coord, &tripple_X); + + // X^3 -3x + SubtractBigHexMod256(&X_cube, &tripple_X, &interim_result1); + + // interim_result + coeficient_b + AddBigHexModP256(&interim_result1, &coef_B, &interim_result2); + + // Now check if Y^2 = interim_result2 (x^3 -3x + b) + return (memcmp(&Y_square.num[0], &interim_result2.num[0], MAX_OCTETS256) == 0); +} + +/** + **************************************************************************************** + * @brief ECC ecc_multiplication event handler + **************************************************************************************** + */ +__RAM_ECDH static void ecc_multiplication_event_handler(void) +{ + DBG_SWDIAG(ECDH, COMPUTE, 1); + // Clear the event + kernel_event_clear(KERNEL_EVENT_ECC_MULTIPLICATION); + + + // Take the next multiplication + struct ecc_elt_tag* ecc_elt = (struct ecc_elt_tag*) common_list_pop_front(&ecc_env.ongoing_mul); + + + // Check if element is present + if (ecc_elt != NULL) + { + // Check that current multiplication is not finished + if (ecc_elt->Point_Mul_Word256 > 0) + { + DBG_SWDIAG(ECDH, MULT, 1); + +#if (ECC_4BIT_WIN_OPT==1) + // Execute 1 multiplication step (with 4 bits at a time) + ecc_point_multiplication_win_256(ecc_elt); +#else + // Execute 1 multiplication step + ecc_point_multiplication_uint8_256(ecc_elt); +#endif + // Re-insert the multiplication at the end of the list + common_list_push_back(&ecc_env.ongoing_mul, &ecc_elt->hdr); + DBG_SWDIAG(ECDH, MULT, 0); + } + else + { + DBG_SWDIAG(ECDH, END, 1); + // stack_printf("ecc_multiplication_event_handler end\r\n"); + // Multiplication completed, report to the client task + if(ecc_elt->client_id != TASK_BLE_NONE) + { + int32_t i, j; + ECC_Point256 pointQ256; + + struct ecc_result_ind* ind = KERNEL_MSG_ALLOC(ecc_elt->msg_id, ecc_elt->client_id, TASK_BLE_NONE, ecc_result_ind); + + initBigNumber256(&pointQ256.x); + initBigNumber256(&pointQ256.y); + + GF_Point_Jacobian_To_Affine256(&(ecc_elt->Jacobian_PointQ256), &pointQ256.x, &pointQ256.y); + + // Free the memory previously allocated for Jacobian points Q and R and the private key +#if (ECC_4BIT_WIN_OPT==1) + if (ecc_elt->win_4_table != NULL) + { + kernel_free(ecc_elt->win_4_table); + } +#endif + kernel_free(ecc_elt); + + // Copy result keys X coordinate # LSB first + for (i = 31, j = 1; i >= 0;) // Keys Res is MSB - make it in LSB + { +#if (ECC_MULT_ALGO_TYPE == 16) + ind->key_res_x[i] = ((pointQ256.x.num[j] & 0xFF00) >> 8); + ind->key_res_x[i - 1] = (pointQ256.x.num[j] & 0x00FF); + i -= 2; + j++; +#elif (ECC_MULT_ALGO_TYPE == 32) + ind->key_res_x[i] = ((pointQ256.x.num[j] & 0xFF000000) >> 24); + ind->key_res_x[i - 1] = ((pointQ256.x.num[j] & 0x00FF0000) >> 16); + ind->key_res_x[i - 2] = ((pointQ256.x.num[j] & 0x0000FF00) >> 8); + ind->key_res_x[i - 3] = ( pointQ256.x.num[j] & 0x000000FF); + i -= 4; + j++; +#endif // (ECC_MULT_ALGO_TYPE == 16) + } + + // Copy result keys Y coordinate + for (i = 31, j = 1; i >= 0;) // Keys Res is MSB - make it in LSB + { +#if (ECC_MULT_ALGO_TYPE == 16) + ind->key_res_y[i] = ((pointQ256.y.num[j] & 0xFF00) >> 8); + ind->key_res_y[i - 1] = (pointQ256.y.num[j] & 0x00FF); + + i -= 2; + j++; +#elif (ECC_MULT_ALGO_TYPE == 32) + ind->key_res_y[i] = ((pointQ256.y.num[j] & 0xFF000000) >> 24); + ind->key_res_y[i - 1] = ((pointQ256.y.num[j] & 0x00FF0000) >> 16); + ind->key_res_y[i - 2] = ((pointQ256.y.num[j] & 0x0000FF00) >> 8); + ind->key_res_y[i - 3] = ( pointQ256.y.num[j] & 0x000000FF); + i -= 4; + j++; +#endif // (ECC_MULT_ALGO_TYPE == 16) + } + + kernel_msg_send(ind); + } + + DBG_SWDIAG(ECDH, END, 0); + } + } + else + { + ASSERT_ERR(0); + } + + // Restart the event in case there is multiplication to perform + if(!common_list_is_empty(&ecc_env.ongoing_mul)) + { + kernel_event_set(KERNEL_EVENT_ECC_MULTIPLICATION); + } + else + { + DBG_SWDIAG(ECDH, BUSY, 0); + } + DBG_SWDIAG(ECDH, COMPUTE, 0); + + +} + + +/* + * GLOBAL FUNCTIONS DEFINITIONS + **************************************************************************************** + */ + +void ecc_init(bool reset) +{ + if (reset) + { + kernel_event_clear(KERNEL_EVENT_ECC_MULTIPLICATION); + // Empty multiplications list + while(!common_list_is_empty(&ecc_env.ongoing_mul)) + { + // Free allocated memory + struct ecc_elt_tag* elt = (struct ecc_elt_tag*) common_list_pop_front(&ecc_env.ongoing_mul); + +#if (ECC_4BIT_WIN_OPT==1) + // Free the memory previously allocated for Jacobian points Q and R and the private key + if (elt->win_4_table != NULL) + { + kernel_free(elt->win_4_table); + } +#endif // (ECC_4BIT_WIN_OPT==1) + + kernel_free(elt); + } + } + + // Initialize multiplications list + common_list_init(&ecc_env.ongoing_mul); + + // Register event to handle multiplication steps + kernel_event_callback_set(KERNEL_EVENT_ECC_MULTIPLICATION, &ecc_multiplication_event_handler); +} +#if (ECC_4BIT_WIN_OPT==1) +__RAM_ECDH uint8_t ecc_generate_key256(u_int8 key_type, const u_int8* secret_key, const u_int8* public_key_x, const u_int8* public_key_y, kernel_msg_id_t msg_id, kernel_task_id_t task_id) +#else +uint8_t ecc_generate_key256(const u_int8 *secret_key, const u_int8 *public_key_x, const u_int8 *public_key_y, kernel_msg_id_t msg_id, kernel_task_id_t task_id) +#endif +{ +// stack_printf("ecc_generate_key256 start\r\n"); + uint8_t status = COMMON_ERROR_INVALID_HCI_PARAM; +#ifdef CFG_ECC_SIM_ACCEL + struct ecc_result_ind *ind = KERNEL_MSG_ALLOC(msg_id, task_id, TASK_BLE_NONE, ecc_result_ind); + ecc_priv_ptr_setf((uint32_t)secret_key); + ecc_pub_x_ptr_setf((uint32_t)public_key_x); + ecc_pub_y_ptr_setf((uint32_t)public_key_y); + ecc_result_setf((uint32_t)ind); + ecc_start_setf(1); + kernel_msg_send(ind); +#else // !CFG_ECC_SIM_ACCEL + + u_int32 big_num_offset = 1; + int32_t i, j; + bigHex256 PrivateKey256; + ECC_Point256 PublicKey256; + + // Now Copy the Public Key and Secret Key coordinates to ECC point format. + PrivateKey256.num[0] = 0; + PublicKey256.x.num[0] = 0; + PublicKey256.y.num[0] = 0; + + DBG_SWDIAG(ECDH, BUSY, 1); + + for (i = 31, j = big_num_offset; i >= 0;) // Public and Private Keys Are LSB - make it in MSB + { +#if (ECC_MULT_ALGO_TYPE == 16) + PrivateKey256.num[j] = (u_int32) + ((((*(secret_key + i )) << 8) & 0xFF00) + + (((*(secret_key + (i - 1) )) & 0x00FF))); + + PublicKey256.x.num[j] = (u_int32) + ( (((*(public_key_x + i )) << 8) & 0xFF00) + + (((*(public_key_x + (i - 1) )) & 0x00FF))); + + PublicKey256.y.num[j] = (u_int32) + ( (((*(public_key_y + i )) << 8) & 0xFF00) + + (((*(public_key_y + (i - 1) )) & 0x00FF))); + + i -= 2; + j++; +#elif (ECC_MULT_ALGO_TYPE == 32) + PrivateKey256.num[j] = (u_int32) + ((((*(secret_key + i )) << 24) & 0xFF000000) + + (((*(secret_key + (i - 1))) << 16) & 0x00FF0000) + + (((*(secret_key + (i - 2))) << 8) & 0x0000FF00) + + (( *(secret_key + (i - 3))) & 0x000000FF)); + + PublicKey256.x.num[j] = (u_int32) + ((((*(public_key_x + i )) << 24) & 0xFF000000) + + (((*(public_key_x + (i - 1))) << 16) & 0x00FF0000) + + (((*(public_key_x + (i - 2))) << 8) & 0x0000FF00) + + (( *(public_key_x + (i - 3))) & 0x000000FF)); + + PublicKey256.y.num[j] = (u_int32) + ((((*(public_key_y + i )) << 24) & 0xFF000000) + + (((*(public_key_y + (i - 1))) << 16) & 0x00FF0000) + + (((*(public_key_y + (i - 2))) << 8) & 0x0000FF00) + + (( *(public_key_y + (i - 3))) & 0x000000FF)); + i -= 4; + j++; +#endif // (ECC_MULT_ALGO_TYPE == 16) + } + + setBigNumberLength256(&PrivateKey256); + setBigNumberLength256(&PublicKey256.x); + setBigNumberLength256(&PublicKey256.y); + PublicKey256.x.sign = 0; + PublicKey256.y.sign = 0; + + + if (ecc_is_valid_point(&PublicKey256.x, &PublicKey256.y)) + { + ECC_Jacobian_Point256 PointP_Jacobian; + ECC_Jacobian_Point256 *pPointP_Jacobian = &PointP_Jacobian; + + // Allocate Memory for Jacobian Points P, Q, R + struct ecc_elt_tag* ecc_elt = (struct ecc_elt_tag*) kernel_malloc(sizeof(struct ecc_elt_tag), KERNEL_MEM_NON_RETENTION); + + // Store client message/task ID +#if (ECC_4BIT_WIN_OPT == 1) + ecc_elt->win_4_table = NULL; + ecc_elt->key_type = key_type; +#endif + ecc_elt->msg_id = msg_id; + ecc_elt->client_id = task_id; + + // Need to map from Affine Point to Jacobian Point + GF_Affine_To_Jacobian_Point_Copy256(&PublicKey256, pPointP_Jacobian); + + GF_Jacobian_Point_Copy256(pPointP_Jacobian, &(ecc_elt->Jacobian_PointR256)); + + copyBigHex256(&PrivateKey256, &(ecc_elt->Pk256)); + + GF_Setup_Jacobian_Infinity_Point256(&(ecc_elt->Jacobian_PointQ256)); + + // Initialize cursor +#if (ECC_4BIT_WIN_OPT == 1) + ecc_elt->bit_cursor = 63; // 64 interations of the 4 Bit Window +#else + ecc_elt->bit_cursor = 0; +#endif + ecc_elt->current_val = 0; + ecc_elt->Point_Mul_Word256 = ELEMENTS_BIG_HEX256; + { +#if (ECC_4BIT_WIN_OPT == 1) // DH_KEY_GENERATION + +// ecc_elt->win_4_table = NULL; + + if (ecc_elt->key_type == ECC_DHKEY_GENERATION) + { + // First determine the table + /// Allocate memory for the ECC Key Generation Table + ecc_elt->win_4_table = (ECC_Jacobian_Point256 *) kernel_malloc((sizeof(ECC_Jacobian_Point256) * 15), KERNEL_MEM_NON_RETENTION); + /// First step is to generate the 16 entry table to be used for Key Calculation + /// -- First part of this is to determine index table values 0x0000,0x0001,0x0010,0x0100,0x1000 + + GF_Jacobian_Point_Copy256(&ecc_elt->Jacobian_PointR256, &ecc_elt->win_4_table[0]); + + ecc_elt->key_type = ECC_4BIT_TABLE_GENERATION_PT1; + ecc_elt->bit_cursor = 0; + + } +#endif + // Insert the multiplication at the end of the list + common_list_push_back(&ecc_env.ongoing_mul, &ecc_elt->hdr); + + // Start the event + kernel_event_set(KERNEL_EVENT_ECC_MULTIPLICATION); + } + + status = COMMON_ERROR_NO_ERROR; + } + else + { + bk_printf("====== Invalid public key value. ===== \n"); + } +#endif // CFG_ECC_SIM_ACCEL + // bk_printf("ecc_generate_key256 end\r\n"); + return status; +} + +__RAM_ECDH void ecc_abort_key256_generation(kernel_task_id_t task_id) +{ + struct ecc_elt_tag *prev = NULL; + struct ecc_elt_tag* elt = (struct ecc_elt_tag*) common_list_pick(&ecc_env.ongoing_mul); + + // Empty multiplications list + while (elt != NULL) + { + // Check if the element correspond to the abort request + if (elt->client_id == task_id) + { + // Extract element from the list + common_list_extract_after(&ecc_env.ongoing_mul, &prev->hdr, &elt->hdr); +#if (ECC_4BIT_WIN_OPT == 1) + // if DH_Key Generation - ensure any memory assigned for Table is freed + if (elt->win_4_table != NULL) + { + kernel_free(elt->win_4_table); + } +#endif + // Free allocated memory + kernel_free(elt); + + // Check if list is empty + if(common_list_is_empty(&ecc_env.ongoing_mul)) + { + // Clear the event + kernel_event_clear(KERNEL_EVENT_ECC_MULTIPLICATION); + } + + break; + } + + // Jump to next + prev = elt; + elt = (struct ecc_elt_tag*) common_list_next(&elt->hdr); + } +} + +__RAM_ECDH void ecc_gen_new_public_key(u_int8* secret_key, kernel_msg_id_t msg_id, kernel_task_id_t task_id) +{ +#if (ECC_4BIT_WIN_OPT == 1) + ecc_generate_key256(ECC_PUBLICKEY_GENERATION, secret_key, BasePoint_x_256, BasePoint_y_256, msg_id, task_id); +#else + ecc_generate_key256(secret_key, BasePoint_x_256, BasePoint_y_256, msg_id, task_id); +#endif +} + + +__RAM_ECDH void ecc_gen_new_secret_key(uint8_t* secret_key256, bool forced) +{ + // Secure key is forced + if (forced) + { + // check its validity +// if(!isValidSecretKey_256(secret_key256)) +// { +// ASSERT_ERR(0); +// } + } + else + { + // Need to get a 32 Byte random number - which we will use as the secret key. + // We then ECC multiply this by the Base Points, to get a new Public Key. + // + do + { + common_write32p(&secret_key256[0], common_rand_word()); + common_write32p(&secret_key256[4], common_rand_word()); + common_write32p(&secret_key256[8], common_rand_word()); + common_write32p(&secret_key256[12], common_rand_word()); + common_write32p(&secret_key256[16], common_rand_word()); + common_write32p(&secret_key256[20], common_rand_word()); + common_write32p(&secret_key256[24], common_rand_word()); + common_write32p(&secret_key256[28], common_rand_word()); + } + while (!isValidSecretKey_256(secret_key256)); + } +} + +__RAM_ECDH void ecc_get_debug_Keys(uint8_t*secret_key, uint8_t* pub_key_x, uint8_t* pub_key_y) +{ + int8_t i; + + for (i = 31; i >= 0; i--) + { + pub_key_x[i] = DebugE256PublicKey_x[i]; + pub_key_y[i] = DebugE256PublicKey_y[i]; + secret_key[i] = DebugE256SecretKey[i]; + } +} +#endif // (SECURE_CONNECTIONS) diff --git a/beken_os/beken378/driver/ble/ble_pub/modules/rf/api/ble_rf.h b/beken_os/beken378/driver/ble/ble_pub/modules/rf/api/ble_rf.h new file mode 100755 index 0000000..eac2850 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/modules/rf/api/ble_rf.h @@ -0,0 +1,64 @@ +/** + **************************************************************************************** + * + * @file ble_rf.h + * + * @brief Common header file for all radios. + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef BLE_RF_H_ +#define BLE_RF_H_ + +/** + **************************************************************************************** + * @addtogroup RF + * @ingroup DRIVERS + * @brief Common definitions for radio modules. + * + * This module declares the functions and constants that have to be defined for all RF. + * + * @{ + **************************************************************************************** + */ + + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +struct rwip_rf_api; // forward declaration to avoid including rw.h + +/** + ***************************************************************************************** + * @brief Initialization of RF. + * + * This function initializes the RF and fills the structure containing the function + * pointers and parameters required by the RW BT stack. + * + * @param[out] api Pointer to the BT RF API structure + * + ***************************************************************************************** + */ +void rf_init(struct rwip_rf_api *api); + + +void initial_xver_BK3435V2_openLoop(void); + + +void Delay(int num); + +void Delay_ms(int num); + +void Delay_us(int num); + +void mcu_use_48m(void); + +/// @} BLE_RF + +#endif // BLE_RF_H_ diff --git a/beken_os/beken378/driver/ble/ble_pub/modules/rf/src/ble_rf_xvr.c b/beken_os/beken378/driver/ble/ble_pub/modules/rf/src/ble_rf_xvr.c new file mode 100755 index 0000000..975a3b9 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/modules/rf/src/ble_rf_xvr.c @@ -0,0 +1,425 @@ +/** +**************************************************************************************** +* +* @file rf_xvras.c +* +* @brief Atlas radio initialization and specific functions +* +* Copyright (C) Beken 2009-2015 +* +* $Rev: $ +* +**************************************************************************************** +*/ + +/** +**************************************************************************************** +* @addtogroup RF_XVR +* @ingroup RF +* @brief Radio Driver +* +* This is the driver block for radio +* @{ +**************************************************************************************** +*/ + +/** + ***************************************************************************************** + * INCLUDE FILES + ***************************************************************************************** + */ +#include // for memcpy +#include "common_endian.h" // endian definitions +#include "common_math.h" // common math functions +#include "common_utils.h" // common utility definition +#include "ble_rf.h" // RF interface +#include "em_map.h" // RF area mapping + +#include "rwip.h" // for RF API structure definition +#include "reg_blecore.h" // ble core registers +#include "reg_ble_em_cs.h" // control structure definitions + +#include "BK3435_reg.h" // Platform register +#include "ble_icu.h" +#include "rwip_config.h" // stack configuration + +/** + **************************************************************************************** + * DEFINES + **************************************************************************************** + **/ + + + + + +/** +**************************************************************************************** +* MACROS +***************************************************************************************** +*/ + + +#define RPL_POWER_MAX 0x0c + +/** + **************************************************************************************** + * GLOBAL VARIABLE DEFINITIONS + ***************************************************************************************** + **/ + + + + + +/** + **************************************************************************************** + * FUNCTION DEFINITIONS + **************************************************************************************** + */ + +void CLK32K_AutoCali_init(void); + + +/** + ***************************************************************************************** + * @brief Init RF sequence after reset. + ***************************************************************************************** + */ + +static void rf_reset(void) +{ +} + +/** + **************************************************************************************** + * @brief ISR to be called in BLE ISR routine when RF Interrupt occurs. + ***************************************************************************************** + */ + + +/** + ***************************************************************************************** + * @brief Get TX power in dBm from the index in the control structure + * + * @param[in] txpwr_idx Index of the TX power in the control structure + * @param[in] modulation Modulation: 1 or 2 or 3 MBPS + * + * @return The TX power in dBm + * + ***************************************************************************************** + */ + +static uint8_t rf_txpwr_dbm_get(uint8_t txpwr_idx, uint8_t modulation) +{ + // Power table should be provided + return(0); +} + +/** + ***************************************************************************************** + * @brief Sleep function for RF. + ***************************************************************************************** + */ + +static void rf_sleep(void) +{ + #if defined(CFG_BLE) + ble_deepslcntl_set(ble_deepslcntl_get() | + BLE_DEEP_SLEEP_ON_BIT | // RW BLE Core sleep + BLE_RADIO_SLEEP_EN_BIT | // Radio sleep + BLE_OSC_SLEEP_EN_BIT); // Oscillator sleep + #endif // CFG_BLE +} + + +/** + ***************************************************************************************** + * @brief Convert RSSI to dBm + * + * @param[in] rssi_reg RSSI read from the HW registers + * + * @return The converted RSSI + * + ***************************************************************************************** + */ + +static int8_t rf_rssi_convert (uint8_t rssi_reg) +{ + uint8_t RssidBm = 0; + + RssidBm = ((rssi_reg) >> 1) - 118; + + return(RssidBm); +} + + +static uint32_t rf_rpl_reg_rd (uint16_t addr) +{ + uint32_t ret; + + ret = REG_PL_RD(((unsigned int)addr)); + + return ret; +} + +static void rf_rpl_reg_wr (uint16_t addr, uint32_t value) +{ + REG_PL_WR(((unsigned int)addr), value); +} +/** + **************************************************************************************** + * RADIO FUNCTION INTERFACE + **************************************************************************************** + **/ + +static void rf_force_agc_enable(bool en) +{ + + ble_forceagc_en_setf(en); + +} +void rf_init(struct rwip_rf_api *api) +{ + // Initialize the RF driver API structure + api->reg_rd = rf_rpl_reg_rd; + api->reg_wr = rf_rpl_reg_wr; + api->txpwr_dbm_get = rf_txpwr_dbm_get; + api->txpwr_max = RPL_POWER_MAX; + api->sleep = rf_sleep; + api->reset = rf_reset; + + #if defined(CFG_BLE) + api->force_agc_enable = rf_force_agc_enable; + #endif //CFG_BLE + + api->rssi_convert = rf_rssi_convert; + + //initial_xver_BK3435V2_openLoop(); +} + +void Delay_us(int num) +{ + int x, y; + for(y = 0; y < num; y ++ ) + { + for(x = 0; x < 10; x++); + } +} + +void Delay(int num) +{ + int x, y; + for(y = 0; y < num; y ++ ) + { + for(x = 0; x < 50; x++); + } +} + +void Delay_ms(int num) //sync from svn revision 18 +{ + int x, y; + for(y = 0; y < num; y ++ ) + { + for(x = 0; x < 3260; x++); + } + +} + +volatile uint32_t XVR_ANALOG_REG_BAK[16] = {0}; + + +#define RF_TEST 0 +#define TEST_RC 0 + + +void init_analog_xvr_reg(void) +{ + Delay_ms(20); + mHWreg_Assign_XVR_Regsiter(00, 0xC3A03210); + XVR_ANALOG_REG_BAK[0x00] = 0xC3A03210; + + mHWreg_Assign_XVR_Regsiter(01, 0x8295C100);// + XVR_ANALOG_REG_BAK[0x01] = 0x8295C100; + + mHWreg_Assign_XVR_Regsiter(02, 0x2f42AF00); + XVR_ANALOG_REG_BAK[0x02] = 0x2f42AF00; + + mHWreg_Assign_XVR_Regsiter(03, 0x6A1CD462); //audio + XVR_ANALOG_REG_BAK[0x03] = 0x6A1CD462; + + + mHWreg_Assign_XVR_Regsiter(04, 0x7F9156B3);// 0x5F915727 + XVR_ANALOG_REG_BAK[0x04] = 0x5F9156B3; + + //mHWreg_Assign_XVR_Regsiter(04, 0x7F9116B3);// 0x5F915727 + //XVR_ANALOG_REG_BAK[0x04] = 0x5F9116B3; + + mHWreg_Assign_XVR_Regsiter(05, 0x48295540);// 0x48285540 + XVR_ANALOG_REG_BAK[0x05] = 0x48295540; + + //mHWreg_Assign_XVR_Regsiter(06, 0x88D68C00); // + //XVR_ANALOG_REG_BAK[0x06] = 0x88D68C00;// + mHWreg_Assign_XVR_Regsiter(06, 0x88D68C10); // for adc + XVR_ANALOG_REG_BAK[0x06] = 0x88D68C10;// + + mHWreg_Assign_XVR_Regsiter(07, 0x0010Bfc7);//0x0000Bfc7); + XVR_ANALOG_REG_BAK[0x07] = 0x0010Bfc7;//0x0000Bfc7; + mHWreg_Assign_XVR_Regsiter(08, 0X2DD04005);//0x3FB84005); + XVR_ANALOG_REG_BAK[0x08] = 0X2DD04005;//0x3FB84005; + +#if (MCU_DEFAULT_CLK == MCU_CLK_16M) + mHWreg_Assign_XVR_Regsiter(09, 0x74203C08);//0x70203C08 rc // 0x74203C08 xtal + XVR_ANALOG_REG_BAK[0x09] = 0x74203C08; // 0x74203C08 + +#elif (MCU_DEFAULT_CLK == MCU_CLK_32M ) + mHWreg_Assign_XVR_Regsiter(09, 0x74203C4A);//0x70203C08 rc // 0x74203C08 xtal + XVR_ANALOG_REG_BAK[0x09] = 0x74203C4A; // 0x74203C08 + +#elif (MCU_DEFAULT_CLK == MCU_CLK_64M ) + mHWreg_Assign_XVR_Regsiter(09, 0x74203C4A);//0x70203C08 rc // 0x74203C08 xtal + XVR_ANALOG_REG_BAK[0x09] = 0x74203C4A; // 0x74203C08 +#endif + + //mHWreg_Assign_XVR_Regsiter(0A, 0x1C07EC25); //0x1C07ED35 0x1C07EC25 + //XVR_ANALOG_REG_BAK[0x0A] = 0x1C07EC25; + mHWreg_Assign_XVR_Regsiter(0A, 0x1C07EC27); //for adc + XVR_ANALOG_REG_BAK[0x0A] = 0x1C07EC27; + + mHWreg_Assign_XVR_Regsiter(0B, 0xd1Fd240C); //0xD3DD240C 71FD240C + XVR_ANALOG_REG_BAK[0x0B] = 0xd1Fd240C; + + mHWreg_Assign_XVR_Regsiter(0C, 0x80009008); //0x8000D008 0x80009008 + XVR_ANALOG_REG_BAK[0x0C] = 0x80009008; + + mHWreg_Assign_XVR_Regsiter(0D, 0x04413F23);//0x84413F23 + XVR_ANALOG_REG_BAK[0x0D] = 0x04413F23; + + mHWreg_Assign_XVR_Regsiter(0E, 0x00309350); //------------------------------------------------------- + XVR_ANALOG_REG_BAK[0x0E] = 0x00309350; + + mHWreg_Assign_XVR_Regsiter(0F, 0x3126E978); + XVR_ANALOG_REG_BAK[0x0F] = 0x3126E978; + + Delay_ms(20); +} +void initial_xver_BK3435V2_openLoop(void) +{ + + uint32_t cfg ; + Delay_ms(20); + + init_analog_xvr_reg(); + + //mHWreg_Assign_XVR_Regsiter(10, 0x00083435); + //mHWreg_Assign_XVR_Regsiter(11, 0x16810020); + //mHWreg_Assign_XVR_Regsiter(12, 0x00003C00); + //mHWreg_Assign_XVR_Regsiter(13, 0x00000000); + //mHWreg_Assign_XVR_Regsiter(14, 0x00080000); + //mHWreg_Assign_XVR_Regsiter(15, 0x00000000); + //mHWreg_Assign_XVR_Regsiter(16, 0x00000000); + //mHWreg_Assign_XVR_Regsiter(17, 0x00000000); + //mHWreg_Assign_XVR_Regsiter(18, 0x000001FF); + //mHWreg_Assign_XVR_Regsiter(19, 0x00000000); + //mHWreg_Assign_XVR_Regsiter(1A, 0x00000000); + //mHWreg_Assign_XVR_Regsiter(1B, 0x00000000); + //mHWreg_Assign_XVR_Regsiter(1C, 0x00000000); + //mHWreg_Assign_XVR_Regsiter(1D, 0x00000000); + //mHWreg_Assign_XVR_Regsiter(1E, 0x00000000); + //mHWreg_Assign_XVR_Regsiter(1F, 0x00000000); + mHWreg_Assign_XVR_Regsiter(20, 0x8E89BED6); + mHWreg_Assign_XVR_Regsiter(21, 0x96000000); + //mHWreg_Assign_XVR_Regsiter(22, 0x78000000); + mHWreg_Assign_XVR_Regsiter(22, 0x78010000); + mHWreg_Assign_XVR_Regsiter(23, 0xA0000000); + mHWreg_Assign_XVR_Regsiter(24, 0x001E0782); + mHWreg_Assign_XVR_Regsiter(25, 0x00000000); + mHWreg_Assign_XVR_Regsiter(26, 0x10200505); + mHWreg_Assign_XVR_Regsiter(27, 0x0008C900); + mHWreg_Assign_XVR_Regsiter(28, 0x01011010); + mHWreg_Assign_XVR_Regsiter(29, 0x3C104E00); + mHWreg_Assign_XVR_Regsiter(2A, 0x0e103D68); + mHWreg_Assign_XVR_Regsiter(2B, 0x00000408); + mHWreg_Assign_XVR_Regsiter(2C, 0x00000000); + mHWreg_Assign_XVR_Regsiter(2D, 0x082CC444); + mHWreg_Assign_XVR_Regsiter(2E, 0x00000000); + mHWreg_Assign_XVR_Regsiter(2F, 0x00000000); + mHWreg_Assign_XVR_Regsiter(30, 0x10010001); + mHWreg_Assign_XVR_Regsiter(31, 0x00000000); + mHWreg_Assign_XVR_Regsiter(32, 0x00000000); + mHWreg_Assign_XVR_Regsiter(33, 0x00000000); + mHWreg_Assign_XVR_Regsiter(34, 0x00000000); + mHWreg_Assign_XVR_Regsiter(35, 0x00000000); + mHWreg_Assign_XVR_Regsiter(36, 0x00000000); + mHWreg_Assign_XVR_Regsiter(37, 0x00000000); + mHWreg_Assign_XVR_Regsiter(38, 0x00000000); + mHWreg_Assign_XVR_Regsiter(39, 0x00000000); + mHWreg_Assign_XVR_Regsiter(3A, 0x00128000); + mHWreg_Assign_XVR_Regsiter(3B, 0x22341048); + mHWreg_Assign_XVR_Regsiter(3C, 0x01FF1c00); + mHWreg_Assign_XVR_Regsiter(3D, 0x00000000); + mHWreg_Assign_XVR_Regsiter(3E, 0x00000000); + mHWreg_Assign_XVR_Regsiter(3F, 0x00000000); + mHWreg_Assign_XVR_Regsiter(40, 0x01000000); + mHWreg_Assign_XVR_Regsiter(41, 0x07050402); + mHWreg_Assign_XVR_Regsiter(42, 0x120F0C0A); + mHWreg_Assign_XVR_Regsiter(43, 0x221E1A16); + mHWreg_Assign_XVR_Regsiter(44, 0x35302B26); + mHWreg_Assign_XVR_Regsiter(45, 0x4B45403A); + mHWreg_Assign_XVR_Regsiter(46, 0x635D5751); + mHWreg_Assign_XVR_Regsiter(47, 0x7C767069); + mHWreg_Assign_XVR_Regsiter(48, 0x968F8983); + mHWreg_Assign_XVR_Regsiter(49, 0xAEA8A29C); + mHWreg_Assign_XVR_Regsiter(4A, 0xC5BFBAB4); + mHWreg_Assign_XVR_Regsiter(4B, 0xD9D4CFCA); + mHWreg_Assign_XVR_Regsiter(4C, 0xE9E5E1DD); + mHWreg_Assign_XVR_Regsiter(4D, 0xF5F3F0ED); + mHWreg_Assign_XVR_Regsiter(4E, 0xFDFBFAF8); + mHWreg_Assign_XVR_Regsiter(4F, 0xFFFFFFFE); + +#if RF_TEST + cfg = REG_AHB0_ICU_ANALOG_MODE; + cfg |= ((0x01 << 18 ) | (0x01 << 17 ) | (0x01 << 21 ) | (0x01 << 23 )); + + REG_AHB0_ICU_ANALOG_MODE = cfg; + + cfg = REG_AHB0_ICU_ANALOG0_PWD; + cfg &= ~ ((0x01 << 18 ) | (0x01 << 17 ) | (0x01 << 21 )| (0x01 << 23 )); + REG_AHB0_ICU_ANALOG0_PWD = cfg; + +#else + cfg = REG_AHB0_ICU_ANALOG_MODE; + cfg |= ((0x01 << 18 )); + REG_AHB0_ICU_ANALOG_MODE = cfg; + + cfg = REG_AHB0_ICU_ANALOG0_PWD; + + cfg &= ~ ((0x01 << 18 ) ); + REG_AHB0_ICU_ANALOG0_PWD = cfg; + +#endif + + #if (HZ32000) + CLK32K_AutoCali_init(); + #endif + Delay_ms(200); + + +} + + +void CLK32K_AutoCali_init(void) +{ + XVR_ANALOG_REG_BAK[0x09] &= ~(0x01 << 26); + XVR_REG09 = XVR_ANALOG_REG_BAK[0x09]; + + XVR_ANALOG_REG_BAK[0x0C] &= ~(0X01 << 14); + XVR_REG0C = XVR_ANALOG_REG_BAK[0x0C]; + + + XVR_ANALOG_REG_BAK[0x0C] |= (0X01 << 15); + XVR_REG0C = XVR_ANALOG_REG_BAK[0x0C]; + +} + + diff --git a/beken_os/beken378/driver/ble/ble_pub/modules/rwip/api/rwip.h b/beken_os/beken378/driver/ble/ble_pub/modules/rwip/api/rwip.h new file mode 100755 index 0000000..0661fc7 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/modules/rwip/api/rwip.h @@ -0,0 +1,485 @@ +/** +**************************************************************************************** +* +* @file rwip.h +* +* @brief RW IP SW main module +* +* Copyright (C) RivieraWaves 2009-2015 +* +* +**************************************************************************************** +*/ +#ifndef _RWIP_H_ +#define _RWIP_H_ + +/** + **************************************************************************************** + * @addtogroup ROOT + * @brief Entry points of the RW IP stacks/modules + * + * This module contains the primitives that allow an application accessing and running the + * RW IP protocol stacks / modules. + * + * @{ + **************************************************************************************** + */ + +#include "rwip_config.h" // stack configuration + +#include // standard integer definitions +#include // standard boolean definitions + +/// retrieve 10ms time according to clock time +#define RWIP_CLOCK_TO_10MS_TIME(clock) ((clock) >> 4) +/// retrieve clock time according to 10ms time +#define RWIP_10MS_TIME_TO_CLOCK(time) ((time) << 4) +/// Invalid target time +#define RWIP_INVALID_TARGET_TIME (0xFFFFFFFFL) + +#if (DEEP_SLEEP) +/// Definition of the bits preventing the system from sleeping +enum prevent_sleep +{ + /// Flag indicating that the wake up process is ongoing + RW_WAKERNEL_UP_ONGOING = 0x0001, + /// Flag indicating that an TX transfer is ongoing on Transport Layer + RW_TL_TX_ONGOING = 0x0002, + /// Flag indicating that an RX transfer is ongoing on Transport Layer + RW_TL_RX_ONGOING = 0x0004, + /// Flag indicating HCI timeout is ongoing + RW_AHI_TIMEOUT = 0x0008, + /// Flag indicating that an encryption is ongoing + RW_CRYPT_ONGOING = 0x0010, + /// Flag indicating that a element deletion is on going + RW_DELETE_ELT_ONGOING = 0x0020, + /// Flag indicating that controller shall not sleep due to not CSB LPO_Allowed + RW_CSB_NOT_LPO_ALLOWED = 0x0040, + /// Flag indicating the MWS/WLAN Event Generator is in operation + RW_MWS_WLAN_EVENT_GENERATOR_ACTIVE = 0x0080, + /// Flag sleep ongoing + RW_SLEEP_EVENT_ONGOING = 0x0100, + /// Flag sleep ongoing + RW_GLOBEL_EVENT_ONGOING = 0x0200, + // Flag indicating + BK_DRIVER_TIMER_ACTIVE = 0x0300, + // Flag indicating + BK_MESH_ACTIVE = 0x0400, +}; + + + + + + +#endif //DEEP_SLEEP + +enum rwip_sleep_type +{ + RW_NO_SLEEP = 0, + RW_MCU_IDLE_SLEEP = (0x01 << 0), + RW_MCU_DEEP_SLEEP = (0x01 << 1), + + +}; + +enum system_run_mode +{ + RW_NO_MODE = 0, + RW_DUT_MODE = 1, + RW_PN9_MODE = 2, + RW_FCC_MODE = 3, +}; + +/** + * External interface type types. + */ +enum rwip_eif_types +{ + /// Host Controller Interface - Controller part + RWIP_EIF_HCIC, + + /// Host Controller Interface - Host part + RWIP_EIF_HCIH, + + /// Application Host interface + RWIP_EIF_AHI, +}; + + +/// Enumeration of External Interface status codes +enum rwip_eif_status +{ + /// EIF status OK + RWIP_EIF_STATUS_OK, + /// EIF status KO + RWIP_EIF_STATUS_ERROR, + +#if (BLE_EMB_PRESENT == 0) + /// External interface detached + RWIP_EIF_STATUS_DETACHED, + /// External interface attached + RWIP_EIF_STATUS_ATTACHED, +#endif // (BLE_EMB_PRESENT == 0) +}; + +/// Enumeration of RF modulations +enum rwip_rf_mod +{ + MOD_GFSK = 0x01, + MOD_DQPSK = 0x02, + MOD_8DPSK = 0x03, +}; + +/// API functions of the RF driver that are used by the BLE or BT software +struct rwip_rf_api +{ + /// Function called upon HCI reset command reception + void (*reset)(void); + /// Function called to enable/disable force AGC mechanism (true: en / false : dis) + void (*force_agc_enable)(bool); + /// Function called when TX power has to be decreased for a specific link id + bool (*txpwr_dec)(uint8_t); + /// Function called when TX power has to be increased for a specific link id + bool (*txpwr_inc)(uint8_t); + /// Function called when TX power has to be set to max for a specific link id + void (*txpwr_max_set)(uint8_t); + /// Function called to convert a TX power CS power field into the corresponding value in dBm + uint8_t (*txpwr_dbm_get)(uint8_t, uint8_t); + /// Function called to convert a power in dBm into a control structure tx power field + uint8_t (*txpwr_cs_get)(int8_t); + /// Function called to convert the RSSI read from the control structure into a real RSSI + int8_t (*rssi_convert)(uint8_t); + /// Function used to read a RF register + uint32_t (*reg_rd)(uint16_t); + /// Function used to write a RF register + void (*reg_wr)(uint16_t, uint32_t); + /// Function called to put the RF in deep sleep mode + void (*sleep)(void); + /// Index of maximum TX power + uint8_t txpwr_max; + /// RSSI high threshold ('real' signed value in dBm) + int8_t rssi_high_thr; + /// RSSI low threshold ('real' signed value in dBm) + int8_t rssi_low_thr; + /// interferer threshold ('real' signed value in dBm) + int8_t rssi_interf_thr; + /// RF wakeup delay (in slots) + uint8_t wakeup_delay; +}; + +/// Internal API for priority +struct rwip_prio +{ + ///value + uint8_t value; + ///Increment + uint8_t increment; +}; + +/// Internal API for COEX +struct rwip_coex +{ + ///Coexistence control field + uint8_t coex_cntl; +}; + + +/** + **************************************************************************************** + * @brief Function called when packet transmission/reception is finished. + + * @param[in] dummy Dummy data pointer returned to callback when operation is over. + * @param[in] status Ok if action correctly performed, else reason status code. + ***************************************************************************************** + */ +typedef void (*rwip_eif_callback) (void*, uint8_t); + +/** + * Transport layer communication interface. + */ +struct rwip_eif_api +{ + /** + ************************************************************************************* + * @brief Starts a data reception. + * + * @param[out] bufptr Pointer to the RX buffer + * @param[in] size Size of the expected reception + * @param[in] callback Pointer to the function called back when transfer finished + * @param[in] dummy Dummy data pointer returned to callback when reception is finished + ************************************************************************************* + */ + void (*read) (uint8_t *bufptr, uint32_t size, rwip_eif_callback callback, void* dummy); + + /** + ************************************************************************************* + * @brief Starts a data transmission. + * + * @param[in] bufptr Pointer to the TX buffer + * @param[in] size Size of the transmission + * @param[in] callback Pointer to the function called back when transfer finished + * @param[in] dummy Dummy data pointer returned to callback when transmission is finished + ************************************************************************************* + */ + void (*write)(uint8_t *bufptr, uint32_t size, rwip_eif_callback callback, void* dummy); + + /** + ************************************************************************************* + * @brief Enable Interface flow. + ************************************************************************************* + */ + void (*flow_on)(void); + + /** + ************************************************************************************* + * @brief Disable Interface flow. + * + * @return True if flow has been disabled, False else. + ************************************************************************************* + */ + bool (*flow_off)(void); +}; + +/* + * VARIABLE DECLARATION +***************************************************************************************** + */ + +/// API for RF driver +extern struct rwip_rf_api rwip_rf; +#if (BLE_EMB_PRESENT || BT_EMB_PRESENT) +/// API for dual mode priority +extern const struct rwip_prio rwip_priority[RWIP_PRIO_IDX_MAX]; +/// API for COEX +extern const uint8_t rwip_coex_cfg[RWIP_COEX_CFG_MAX]; +#endif //#if (BLE_EMB_PRESENT || BT_EMB_PRESENT) + +/* + * MACROS + **************************************************************************************** + */ + +/// Get Event status flag +#define RWIP_COEX_GET(coex_cfg_idx, bit_field) \ + (uint8_t)(((rwip_coex_cfg[RWIP_COEX_ ## coex_cfg_idx ##_IDX]) >> RWIP_ ## bit_field ## _POS ) & RWIP_COEX_BIT_MASK) + +/* + * FUNCTION DECLARATION +***************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Initializes the RW BT SW. + * + **************************************************************************************** + */ +void rwip_init(uint32_t error); + +void rwip_reg_init(void); +void rwip_reg_deinit(void); + +/** + **************************************************************************************** + * @brief Reset the RW BT SW. + * + **************************************************************************************** + */ +void rwip_reset(void); + +/** + **************************************************************************************** + * @brief Gives FW/HW versions of RW-BT stack. + * + **************************************************************************************** + */ +void rwip_version(uint8_t* fw_version, uint8_t* hw_version); + +/** + **************************************************************************************** + * @brief Schedule all pending events. + * + **************************************************************************************** + */ +void rwip_schedule(void); + +/** + **************************************************************************************** + * @brief Invoke the sleep function. + * + * @return true: processor sleep allowed, false otherwise + **************************************************************************************** + */ +uint8_t rwip_sleep(void); + +#if DEEP_SLEEP +/** + **************************************************************************************** + * @brief Handle wake-up. + **************************************************************************************** + */ +void rwip_wakeup(void); + +/** + **************************************************************************************** + * @brief Handle end of wake-up. + **************************************************************************************** + */ +void rwip_wakeup_end(void); + +/** + **************************************************************************************** + * @brief Set the wake-up delay + * + * @param[in] wakeup_delay Wake-up delay in us + **************************************************************************************** + */ +void rwip_wakeup_delay_set(uint16_t wakeup_delay); + +/** + **************************************************************************************** + * @brief Set a bit in the prevent sleep bit field, in order to prevent the system from + * going to sleep + * + * @param[in] prv_slp_bit Bit to be set in the prevent sleep bit field + **************************************************************************************** + */ +void rwip_prevent_sleep_set(uint16_t prv_slp_bit); + +/** + **************************************************************************************** + * @brief Clears a bit in the prevent sleep bit field, in order to allow the system + * going to sleep + * + * @param[in] prv_slp_bit Bit to be cleared in the prevent sleep bit field + **************************************************************************************** + */ +void rwip_prevent_sleep_clear(uint16_t prv_slp_bit); + +/** + **************************************************************************************** + * @brief Check if sleep mode is enable + * + * @return true if sleep is enable, false otherwise + **************************************************************************************** + */ +bool rwip_sleep_enable(void); + +/** + **************************************************************************************** + * @brief Check if external wake-up is enable + * + * @return true if external wakeup is enable, false otherwise + **************************************************************************************** + */ +bool rwip_ext_wakeup_enable(void); + +/** + **************************************************************************************** + * @brief Converts a duration in lp cycles into a duration is us. + * + * The function converts a duration in lp cycles into a duration is us, according to the + * low power clock frequency (32768Hz or 32000Hz). + * + * To do this the following formulae are applied: + * + * Tus = x*30.517578125 = 30*x + x/2 + x/64 + x/512 for a 32.768kHz clock or + * Tus = x*31.25 = 31*x + x/4 for a 32kHz clock + * + * @note This function is also performing a compensation of accumulated drift created by + * rounding present in the algorithm + * + * @param[in] lpcycles duration in lp cycles + * + * @return duration in us + **************************************************************************************** + */ +uint32_t rwip_sleep_lpcycles_2_us(uint32_t lpcycles); + + +/** + **************************************************************************************** + * @brief Converts a duration in us into a duration in lp cycles. + * + * The function converts a duration in us into a duration is lp cycles, according to the + * low power clock frequency (32768Hz or 32000Hz). + * + * @param[in] us duration in us + * + * @return duration in lpcycles + **************************************************************************************** + */ +uint32_t rwip_us_2_lpcycles(uint32_t us); +#endif // DEEP_SLEEP + +#if (BT_EMB_PRESENT) + +#if PCA_SUPPORT +/** + **************************************************************************************** + * @brief Check if clock dragging limitation + * + * @return true if clock dragging must be used + **************************************************************************************** + */ +bool rwip_pca_clock_dragging_only(void); +#endif //PCA_SUPPORT +#endif // (BT_EMB_PRESENT) + +#if (BT_EMB_PRESENT || BLE_EMB_PRESENT) +#if (RW_MWS_COEX) +/** + **************************************************************************************** + * @brief Enable/Disable the MWS coexistence interface. + * + * @param[in] CoexSetting Coexistence value + * + **************************************************************************************** + */ +void rwip_mwscoex_set(bool state); +#endif //RW_MWS_COEX + +#if (RW_WLAN_COEX) +/** + **************************************************************************************** + * @brief Enable/Disable the Wireless LAN coexistence interface. + * + * @param[in] CoexSetting Coexistence value + * + **************************************************************************************** + */ +void rwip_wlcoex_set(bool state); +#endif //RW_WLAN_COEX +#endif //(BT_EMB_PRESENT || BLE_EMB_PRESENT) + +/** + **************************************************************************************** + * @brief Function to implement in platform in order to retrieve expected external + * interface such as UART for Host Control Interface. + * + * @param[in] type external interface type (@see rwip_eif_types) + * + * @return External interface api structure + **************************************************************************************** + */ +extern const struct rwip_eif_api* rwip_eif_get(uint8_t type); + +#if RW_DEBUG +/** + **************************************************************************************** + * @brief Raises an assertion message to the control interface (if present) + * + * @param[in] file File name + * @param[in] line Line number + * @param[in] param0 Parameter 0 (custom value given by the assert instruction) + * @param[in] param1 Parameter 1 (custom value given by the assert instruction) + **************************************************************************************** + */ +void rwip_assert_err(const char * file, int line, int param0, int param1); +#endif //RW_DEBUG + + +///@} ROOT + +#endif // _RWIP_H_ diff --git a/beken_os/beken378/driver/ble/ble_pub/modules/rwip/api/rwip_config.h b/beken_os/beken378/driver/ble/ble_pub/modules/rwip/api/rwip_config.h new file mode 100755 index 0000000..ef05f6a --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/modules/rwip/api/rwip_config.h @@ -0,0 +1,1243 @@ +/** + **************************************************************************************** + * + * @file rwip_config.h + * + * @brief Configuration of the RW IP SW + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef RWIP_CONFIG_H_ +#define RWIP_CONFIG_H_ + +#include + +/** + **************************************************************************************** + * @addtogroup ROOT + * @{ + * + * Information about RW SW IP options and flags + * + * BT_DUAL_MODE BT/BLE Dual Mode + * BT_STD_MODE BT Only + * BLE_STD_MODE BLE Only + * + * BT_EMB_PRESENT BT controller exists + * BLE_EMB_PRESENT BLE controller exists + * BLE_HOST_PRESENT BLE host exists + * + * @name RW Stack Configuration + * @{ + **************************************************************************************** + */ + +/* + * DEFINES + **************************************************************************************** + */ +//#define UART_PRINTF printf +/******************************************************************************************/ +/* -------------------------- GENERAL SETUP --------------------------------------*/ +/* ------------------------- don't change format -------------------------------*/ +/******************************************************************************************/ + +// <<< Use Configuration Wizard in Context Menu >>> + + +// CW_CFG_RW_IP_VALUE +// CFG_APP +// +#if ( 1 ) +#define CFG_APP +#endif + +// CFG_BLE Role +// <0=> BROADCASTER +// <1=> OBSERVER +// <2=> PERIPHERAL +// <3=> CENTRAL +// <4=> ALLROLES +// Select Role +#define CFG_ROLE 4 + +#if ( CFG_ROLE == 0) +#define CFG_BROADCASTER +#endif + +#if ( CFG_ROLE == 1) +#define CFG_OBSERVER +#endif + +#if ( CFG_ROLE == 2) +#define CFG_PERIPHERAL +#endif + +#if ( CFG_ROLE == 3) +#define CFG_CENTRAL +#endif + +#if ( CFG_ROLE == 4) +#define CFG_ALLROLES +#endif +// + +// CFG_EMB +// enable Exchange Memeory +// +#if ( 1 ) +#define CFG_EMB +#endif + +// CFG_BLE +// select BLE or BT MODE +// +#if ( 1 ) +#define CFG_BLE +#endif + +// CFG_BLE_2MBPS +// select BLE at 2MBPS Mode +// +#if ( 0 ) +#define CFG_BLE_2MBPS +#endif + + +// CFG_CHNL_ASSESS +// select BLE CHNL_ASSESS +// +#if ( 1 ) +#define CFG_CHNL_ASSESS +#endif + + + +// CFG_SEC_CON +// select BLE SEC CON +// +#if ( 1 ) +#define CFG_SEC_CON +#endif + + +// CFG_HOST +// enable BLE HOST +// +#if ( 1 ) +#define CFG_HOST +#endif + +// CFG_AHITL +// enable Application Host Interface +// +#if ( 1 ) +#define CFG_AHITL +#endif + +// CFG_HCITL +// enable Host Controller Interface Support +// +#if ( 1 ) +#define CFG_HCITL +#endif + + +// CFG_HW_AUDIO +// enable HW_AUDIO +// +#if ( 0 ) +#define CFG_HW_AUDIO +#endif + +// CFG_NVDS +// enable NVDS +// +#if ( 0 ) +#define CFG_NVDS +#endif + +// CFG_PRF +// enable PRF +// +#if ( 1 ) +#define CFG_PRF +#endif + +// CFG_NB_PRF <0-10> +// CFG_NB_PRF (0 -- 10) +#define CFG_NB_PRF 10 + + + +// CFG_BLE_TESTER(DUT) +// enable BLE_TESTER +// +#if ( 1 ) +#define CFG_BLE_TESTER +#endif + + + +// CFG_SLEEP +// enable DEEP_SLEEP +// +#if ( CFG_USE_BLE_PS ) +#define CFG_SLEEP +#endif + +// + + + +// Config MAX Connect Device Numble +// CFG_CON <1-10> +// CFG MAX CONNECT NUM (1 -- 10) +#define CFG_CON 1 +// + + + +// Config Updata Connect Param + +// CFG_UPDATA +// enable UPDATA +// +#if ( 1 ) +#define CFG_UPDATA +#endif + +// MIN_INTVALUE <6-3200> +// CFG MIN_INTVALUE (6 -- 3200) +#define BLE_UAPDATA_MIN_INTVALUE 6 +// MAX_INTVALUE <6-3200> +// CFG MAX_INTVALUE (6 -- 3200) +#define BLE_UAPDATA_MAX_INTVALUE 10 +// LATENCY <0-500> +// CFG LATENCY NUM (0 -- 500) + +#define BLE_UAPDATA_LATENCY 180 +// TIMEOUT <10-3200> +// (1 + connSlaveLatency) * connInterval * 2. + +#define BLE_UAPDATA_TIMEOUT 600 + +// + + +// Config DEBUG MODOLUE + +// CFG_DBG_PRINTF +// enable CFG_DBG_PRINTF +// + +#if ( 0 ) +#define CFG_UART_DBG_PRINTF +#endif + +// CFG_GPIO_DEBUG_MSG +// enable CFG_GPIO_DEBUG_MSG +// + + + +#if ( 0 ) +#define CFG_GPIO_DEBUG_MSG +#endif + + + +// + + +#if defined(CFG_UART_DBG_PRINTF) +#define CFG_DBG +#endif + + +#ifdef CFG_BLE_TESTER + #define BLE_DUT_TEST 1 +#else + #define BLE_DUT_TEST 0 +#endif + +#ifdef CFG_UPDATA + #define UPDATE_CONNENCT_PARAM 1 +#else + #define UPDATE_CONNENCT_PARAM 0 +#endif + +#ifdef CFG_GPIO_DEBUG_MSG + #define GPIO_DBG_MSG 1 +#else + #define GPIO_DBG_MSG 0 +#endif + +#ifdef CFG_UART_DBG_PRINTF + #if GPIO_DBG_MSG + #define UART_PRINTF_EN 0 + #else + #define UART_PRINTF_EN 1 + #endif //GPIO_DBG_MSG +#else + #define UART_PRINTF_EN 0 +#endif //CFG_UART_DBG_PRINTF + + + + + + +/******************************************************************************************/ +/* -------------------------- GENERAL SETUP --------------------------------------*/ +/* ------------------------- don't change format -------------------------------*/ +/******************************************************************************************/ + + +#define BLE_QUALIF 0 + +/// Flag indicating if stack is compiled in dual or single mode +#if defined(CFG_BT) + #define BLE_STD_MODE 0 + #if defined(CFG_BLE) + #define BT_DUAL_MODE 1 + #define BT_STD_MODE 0 + #else // CFG_BLE + #define BT_DUAL_MODE 0 + #define BT_STD_MODE 1 + #endif // CFG_BLE +#elif defined(CFG_BLE) + #define BT_DUAL_MODE 0 + #define BT_STD_MODE 0 + #define BLE_STD_MODE 1 +#endif // CFG_BT + +/******************************************************************************************/ +/* ------------------------- STACK PARTITIONING -----------------------------------*/ +/******************************************************************************************/ + +#if (BT_DUAL_MODE) + #define BT_EMB_PRESENT 1 + #define BLE_EMB_PRESENT 1 + #define HCI_PRESENT 1 + #define BLE_HOST_PRESENT 0 + #define BLE_APP_PRESENT 0 +#elif (BT_STD_MODE) + #define BT_EMB_PRESENT 1 + #define BLE_EMB_PRESENT 0 + #define HCI_PRESENT 1 + #define BLE_HOST_PRESENT 0 + #define BLE_APP_PRESENT 0 +#elif (BLE_STD_MODE) + #define BT_EMB_PRESENT 0 + #define HCI_PRESENT 1 + #if defined(CFG_EMB) + #define BLE_EMB_PRESENT 1 + #else + #define BLE_EMB_PRESENT 0 + #endif //CFG_EMB + #if defined(CFG_HOST) + #define BLE_HOST_PRESENT 1 + #else + #define BLE_HOST_PRESENT 0 + #endif //CFG_HOST + #if defined(CFG_APP) + #define BLE_APP_PRESENT 1 + #else + #define BLE_APP_PRESENT 0 + #endif //CFG_APP +#endif // BT_DUAL_MODE / BT_STD_MODE / BLE_STD_MODE + +#define EA_PRESENT (BT_EMB_PRESENT || BLE_EMB_PRESENT) + +/******************************************************************************************/ +/* ------------------------- INTERFACES DEFINITIONS -------------------------------*/ +/******************************************************************************************/ + +/// Application Host Interface +#if defined(CFG_AHITL) +#define AHI_TL_SUPPORT 1 +#else // defined(CFG_AHITL) +#define AHI_TL_SUPPORT 0 +#endif // defined(CFG_AHITL) + + +/// Host Controller Interface Support (defines if HCI parser is present or not) +#if defined(CFG_HCITL) +#define HCI_TL_SUPPORT 1 +#else //defined(CFG_HCITL) +#define HCI_TL_SUPPORT 0 +#endif //defined(CFG_HCITL) + + +#if BLE_HOST_PRESENT +#if BLE_EMB_PRESENT +#define H4TL_SUPPORT (AHI_TL_SUPPORT) +#else // !BLE_EMB_PRESENT +#define H4TL_SUPPORT ((AHI_TL_SUPPORT) + (HCI_TL_SUPPORT)) +#endif // BLE_EMB_PRESENT +#else // !BLE_HOST_PRESENT +#define H4TL_SUPPORT (HCI_TL_SUPPORT) +#endif // BLE_HOST_PRESENT + +/// TCI LMP trace support +#define TCI_LMP_ENABLED 0 + +/******************************************************************************************/ +/* -------------------------- BLE COMMON DEFINITIONS ------------------------------*/ +/******************************************************************************************/ +/// Kernel Heap memory sized reserved for allocate dynamically connection environment +#define KERNEL_HEAP_MEM_RESERVED (4) + +#if defined(CFG_BLE) +/// Application role definitions +#define BLE_BROADCASTER (defined(CFG_BROADCASTER) || defined(CFG_ALLROLES)) +#define BLE_OBSERVER (defined(CFG_OBSERVER) || defined(CFG_ALLROLES)) +#define BLE_PERIPHERAL (defined(CFG_PERIPHERAL) || defined(CFG_ALLROLES)) +#define BLE_CENTRAL (defined(CFG_CENTRAL) || defined(CFG_ALLROLES)) + +#if (!BLE_BROADCASTER) && (!BLE_OBSERVER) && (!BLE_PERIPHERAL) && (!BLE_CENTRAL) + #error "No application role defined" +#endif /* #if (!BLE_BROADCASTER) && (!BLE_OBSERVER) && (!BLE_PERIPHERAL) && (!BLE_CENTRAL) */ + + +/// Maximum number of simultaneous connections +#if (BLE_CENTRAL) + #define BLE_CONNECTION_MAX (CFG_CON) +#elif (BLE_PERIPHERAL) + #define BLE_CONNECTION_MAX (1) +#else + #define BLE_CONNECTION_MAX (0) +#endif /* #if (BLE_CENTRAL) */ + +/// Maximum number of audio connections + +#if defined(CFG_AUDIO) +#if (BLE_CENTRAL || BLE_PERIPHERAL) +#define BLE_AUDIO (1) +#define BLE_AUDIO_CONNECT_MAX (CFG_AUDIO_CON) +#else +#define BLE_AUDIO (0) +#endif /*(BLE_CENTRAL || BLE_PERIPHERAL)*/ +#else +#define BLE_AUDIO (0) +#endif /*defined(CFG_AUDIO)*/ + +/// Number of TX data buffer +#if ((BLE_CONNECTION_MAX == 1) || (BLE_CONNECTION_MAX == 0)) +#if (BLE_CENTRAL || BLE_PERIPHERAL) +#define BLE_TX_BUFF_DATA (6) //default 3, add 6 +#else +#define BLE_TX_BUFF_DATA (0) +#endif //(BLE_CENTRAL || BLE_PERIPHERAL) +#else +#define BLE_TX_BUFF_DATA (BLE_CONNECTION_MAX) // Worst case (one way 251 bytes every 7.5ms) +#endif //((BLE_CONNECTION_MAX == 1) || (BLE_CONNECTION_MAX == 0)) + +#if (BLE_CENTRAL || BLE_PERIPHERAL) +/// Number of TX advertising buffer +#define BLE_TX_BUFF_ADV (3) // Worst case (1 for CONNECT_REQ, 1 for ADV_DATA and 1 for SCAN_RESP_DATA) +/// Number of TX control buffer +#define BLE_TX_BUFF_CNTL (BLE_CONNECTION_MAX) // Worst case (1 dedicated packet by link) +#else +/// Margin used for LL fragmentation (DLE feature) +//#define BLE_TX_DESC_MARGING_DLE (0) +#if (BLE_BROADCASTER) +/// Number of TX advertising descriptors +#define BLE_TX_BUFF_ADV (2) +/// Number of TX control descriptors +#define BLE_TX_BUFF_CNTL (0) +#else +/// Number of TX advertising descriptors +#define BLE_TX_BUFF_ADV (1) +/// Number of TX control descriptors +#define BLE_TX_BUFF_CNTL (0) +#endif // BLE_BROADCASTER +#endif //(BLE_CENTRAL || BLE_PERIPHERAL) + +/// Number of elements in the TX Descriptor pool +// Dedicated for DATA +// Worst case (3 packets (251 bytes) fragmented into 27 byte = 10) +#define BLE_TX_DESC_DATA ((BLE_TX_BUFF_DATA) * 10) +// Dedicated for CONTROL +#define BLE_TX_DESC_CNTL (BLE_TX_BUFF_CNTL) +// Dedicated for ADVERTISING +#define BLE_TX_DESC_ADV (BLE_TX_BUFF_ADV) + +/// Number of TX Buffers +#define BLE_TX_BUFFER_CNT (BLE_TX_BUFF_DATA) + +/// Total number of elements in the TX Descriptor pool +#define BLE_TX_DESC_CNT (BLE_TX_DESC_CNTL + BLE_TX_DESC_ADV + BLE_TX_DESC_DATA) + + +/// Number of receive buffers in the RX ring. This number defines the interrupt +/// rate during a connection event. An interrupt is asserted every BLE_RX_BUFFER_CNT/2 +/// reception. This number has an impact on the size of the exchange memory. This number +/// may have to be increased when CPU is very slow to free the received data, in order not +/// to overflow the RX ring of buffers. + +#if (BLE_CENTRAL || BLE_PERIPHERAL) + /// Number of RX Descriptors + #define BLE_RX_DESC_CNT (4) +#elif (BLE_BROADCASTER) + #define BLE_RX_DESC_CNT (1) +#else + #define BLE_RX_DESC_CNT (4) +#endif //(BLE_CENTRAL || BLE_PERIPHERAL) +/// Number of RX Buffers +#define BLE_RX_BUFFER_CNT (BLE_RX_DESC_CNT) + +/// Max advertising reports before sending the info to the host +#define BLE_ADV_REPORTS_MAX 1 + + +/// Define Number of AUDIO TX/RX buffers per voice channel + +#if (BLE_AUDIO) + #if defined(CFG_AUDIO_AOAHI) + // 3 buffers per connection using audio over AHI TL + #define BLE_NB_INPUT_BUFF_PER_VC (3) + #define BLE_NB_OUTPUT_BUFF_PER_VC (3) + #else // defined(CFG_AUDIO_AOAHI) + // 2 buffers if a codec is available + #define BLE_NB_INPUT_BUFF_PER_VC (2) + #define BLE_NB_OUTPUT_BUFF_PER_VC (2) + #endif // defined(CFG_AUDIO_AOAHI) + // add one more buffer for fake reception and fake transmit + #define BLE_TX_AUDIO_BUFFER_CNT ((BLE_AUDIO_CONNECT_MAX * BLE_NB_INPUT_BUFF_PER_VC) + 1) + #define BLE_RX_AUDIO_BUFFER_CNT ((BLE_AUDIO_CONNECT_MAX * BLE_NB_OUTPUT_BUFF_PER_VC) + 1) +#endif // (BLE_AUDIO) +#endif //defined(CFG_BLE) + +#if defined(CFG_BLE_2MBPS) && (!BLE_QUALIF) + #define BLE_2MBPS (1) +#else + #define BLE_2MBPS (0) + +#endif + + +/******************************************************************************************/ +/* -------------------------- RTC SETUP -------------------------------------*/ +/******************************************************************************************/ + +/// RTC enable/disable +#if defined(CFG_RTC) +#define RTC_SUPPORT 1 +#else +#define RTC_SUPPORT 0 +#endif //CFG_DISPLAY + +/******************************************************************************************/ +/* -------------------------- PS2 SETUP -------------------------------------*/ +/******************************************************************************************/ + +/// PS2 enable/disable +#if defined(CFG_PS2) +#define PS2_SUPPORT 1 +#else +#define PS2_SUPPORT 0 +#endif //CFG_PS2 + + +/******************************************************************************************/ +/* ------------------------- DEEP SLEEP SETUP -------------------------------------*/ +/******************************************************************************************/ + +/// DEEP SLEEP enable +#if defined(CFG_SLEEP) && (BLE_EMB_PRESENT || BT_EMB_PRESENT) + + #define DEEP_SLEEP 1 +#else + #define DEEP_SLEEP 0 +#endif /* CFG_SLEEP */ + + +/// Use 32K Hz Clock if set to 1 else 32,768k is used +#define HZ32000 1 + + +/// Time to wake-up Radio Module (in us) +#define SLEEP_RM_WAKEUP_DELAY 625 +/// Time for stabilization of the high frequency oscillator following a sleep-timer expiry (in us) +#define SLEEP_OSC_NORMAL_WAKEUP_DELAY 5000 +/// Time for stabilization of the high frequency oscillator following an external wake-up request (in us) +#define SLEEP_OSC_EXT_WAKEUP_DELAY 5000 + + +/******************************************************************************************/ +/* ------------------------- PROCESSOR SETUP -------------------------------------*/ +/******************************************************************************************/ + +/// 8 BIT processor +#define PROC_8BITS 0 + +/******************************************************************************************/ +/* -------------------------- RADIO SETUP ----------------------------------------*/ +/******************************************************************************************/ + +/// Power control features +#define RF_TXPWR 1 +/// Class of device +#define RF_CLASS1 0 + +/******************************************************************************************/ +/* ------------------------- COEXISTENCE SETUP ------------------------------------*/ +/******************************************************************************************/ + +/// WLAN Coexistence +#define RW_WLAN_COEX (defined(CFG_WLAN_COEX)) +///WLAN test mode +#if defined(CFG_WLAN_COEX) + #define RW_WLAN_COEX_TEST (defined(CFG_WLAN_COEX_TEST)) +#else + #define RW_WLAN_COEX_TEST 0 +#endif // defined(CFG_WLAN_COEX) + +/// MWS Coexistence +#define RW_MWS_COEX (defined(CFG_MWS_COEX)) +///NWS test mode +#if defined(CFG_MWS_COEX) + #define RW_MWS_COEX_TEST (defined(CFG_MWS_COEX_TEST)) +#else + #define RW_MWS_COEX_TEST 0 +#endif // defined(CFG_MWS_COEX) + +/******************************************************************************************/ +/* ------------------------- DM ARBITRATION SETUP ---------------------------------*/ +/******************************************************************************************/ + +#if BT_DUAL_MODE +/** + * Dual mode arbitration margin (in us) + * + * BREDRMARGIN/BLEMARGIN corresponding to a timing value that allows the RF to power-down properly before any other + * activity. This is radio dependent. + */ +#define DM_ARB_MARGIN 40 +#endif //BT_DUAL_MODE + +/******************************************************************************************/ +/* ------------------------- CHANNEL ASSESSMENT SETUP -----------------------------*/ +/******************************************************************************************/ + +/// Channel Assessment +#if defined(CFG_BLE) +#if (defined(CFG_CHNL_ASSESS) && BLE_CENTRAL) + #define BLE_CHNL_ASSESS (1) +#else + #define BLE_CHNL_ASSESS (0) +#endif //(defined(CFG_CHNL_ASSESS) && BLE_CENTRAL) +#endif //defined(CFG_BLE) + +/******************************************************************************************/ +/* -------------------- SECURE CONNECTIONS SETUP --------------------------------------*/ +/******************************************************************************************/ +#if defined(CFG_SEC_CON) +#define SECURE_CONNECTIONS (1) +#if defined(CFG_ECC_16_BITS_ALGO) +#define ECC_MULT_ALGO_TYPE (16) +#else // !defined(CFG_ECC_16_BITS_ALGO) +#define ECC_MULT_ALGO_TYPE (32) +#endif // defined(CFG_ECC_16_BITS_ALGO) +#if defined(CFG_CRYPTO_UT) +#define CRYPTO_UT (1) +#else //defined(CFG_CRYPTO_UT) +#define CRYPTO_UT (0) +#endif //defined(CFG_CRYPTO_UT) +#else // !defined(CFG_SEC_CON) +#define SECURE_CONNECTIONS (0) +#define CRYPTO_UT (0) +#endif // defined(CFG_SEC_CON) + +/******************************************************************************************/ +/* ---------------------------- AUDIO SETUP ------------------------------------*/ +/******************************************************************************************/ + +/// Flag indicating if audio is available or not +#if defined(CFG_HW_AUDIO) +#define HW_AUDIO 1 +#else // defined (CFG_BLE_AUDIO) +#define HW_AUDIO 0 +#endif // defined (CFG_BLE_AUDIO) + +/******************************************************************************************/ +/* -------------------------- DEBUG SETUP ----------------------------------------*/ +/******************************************************************************************/ + +/// Flag indicating if debug mode is activated or not +#if defined(CFG_DBG) + #define RW_DEBUG ((BLE_EMB_PRESENT) || (BT_EMB_PRESENT) || (BLE_HOST_PRESENT)) +#if (BLE_EMB_PRESENT || BT_EMB_PRESENT) + #define RW_SWDIAG 1 +#else + #define RW_SWDIAG 0 +#endif + #define KERNEL_PROFILING 1 +#else + #define RW_DEBUG 0 + #define RW_SWDIAG 0 + #define KERNEL_PROFILING 0 +#endif /* CFG_DBG */ + +/// Flag indicating if Read/Write memory commands are supported or not +#if defined(CFG_DBG_MEM) + #define RW_DEBUG_MEM 1 +#else //CFG_DBG_MEM + #define RW_DEBUG_MEM 0 +#endif //CFG_DBG_MEM + +/// Flag indicating if Flash debug commands are supported or not +#if defined(CFG_DBG_FLASH) + #define RW_DEBUG_FLASH 1 +#else //CFG_DBG_FLASH + #define RW_DEBUG_FLASH 0 +#endif //CFG_DBG_FLASH + +/// Flag indicating if NVDS feature is supported or not +#if defined(CFG_DBG_NVDS) + #define RW_DEBUG_NVDS 1 +#else //CFG_DBG_NVDS + #define RW_DEBUG_NVDS 0 +#endif //CFG_DBG_NVDS + +/// Flag indicating if CPU stack profiling commands are supported or not +#if defined(CFG_DBG_STACK_PROF) + #define RW_DEBUG_STACK_PROF 1 +#else + #define RW_DEBUG_STACK_PROF 0 +#endif // defined (CFG_DBG_STACK_PROF) + +/// Modem back to back setup +#define MODEM2MODEM 0 +/// Special clock testing +#define CLK_WRAPPING 0 + +/******************************************************************************************/ +/* -------------------------- NVDS SETUP --------------------------------------*/ +/******************************************************************************************/ + +/// Flag indicating if NVDS feature is supported or not +#if defined(CFG_NVDS) + #define NVDS_SUPPORT 1 +#else //CFG_DBG_NVDS + #define NVDS_SUPPORT 0 +#endif //CFG_DBG_NVDS + +/******************************************************************************************/ +/* -------------------------- MISC SETUP --------------------------------------*/ +/******************************************************************************************/ +/// Manufacturer: RivieraWaves SAS +#define RW_COMP_ID 0x0060 + +/// Bluetooth technologies version +#define RW_BT40_VERSION (6) +#define RW_BT41_VERSION (7) +#define RW_BT42_VERSION (8) + +/******************************************************************************************/ +/* ------------------------- BT / BLE / BLE HL CONFIG -------------------------------*/ +/******************************************************************************************/ + +#if (BT_EMB_PRESENT) +#include "rwbt_config.h" // bt stack configuration +#endif //BT_EMB_PRESENT + +#if (BLE_EMB_PRESENT) || (BLE_HOST_PRESENT) +#include "rwble_config.h" // ble stack configuration +#endif //BLE_EMB_PRESENT + +#if (BLE_HOST_PRESENT) +#include "rwble_hl_config.h" // ble Host stack configuration +#endif //BLE_HOST_PRESENT + +#if defined(CFG_AUDIO_AM0) +#include "rwam0_config.h" // Audio Mode 0 configuration +#endif // defined(CFG_AUDIO_AM0) + +#if defined(CFG_APP) +#include "rwapp_config.h" // Audio Mode 0 configuration +#endif // defined(CFG_APP) + + + +/******************************************************************************************/ +/* ------------------------- KERNEL SETUP -------------------------------------*/ +/******************************************************************************************/ + +/// Flag indicating Kernel is supported +#define KERNEL_SUPPORT (BLE_EMB_PRESENT || BT_EMB_PRESENT || BLE_HOST_PRESENT || BLE_APP_PRESENT) + + +/// Event types definition +enum KERNEL_EVENT_TYPE +{ + #if DISPLAY_SUPPORT + KERNEL_EVENT_DISPLAY = 1 , + #endif //DISPLAY_SUPPORT + + #if RTC_SUPPORT + KERNEL_EVENT_RTC_1S_TICK = 2 , + #endif //RTC_SUPPORT + + #ifdef CFG_AUDIO_RSA + KERNEL_EVENT_RSA_SIGN = 3, + #endif // CFG_AUDIO_RSA + + #if SECURE_CONNECTIONS + KERNEL_EVENT_ECC_MULTIPLICATION = 4, + #endif // SECURE_CONNECTIONS + + #if BLE_EMB_PRESENT + KERNEL_EVENT_BLE_CRYPT = 5, + #endif //BLE_EMB_PRESENT + + KERNEL_EVENT_KERNEL_MESSAGE = 6 , + KERNEL_EVENT_KERNEL_TIMER = 7, + + #if (AHI_TL_SUPPORT) + KERNEL_EVENT_AHI_TX_DONE = 8 , + #endif //(AHI_TL_SUPPORT) + + + #if H4TL_SUPPORT + KERNEL_EVENT_H4TL_TX = 9, + #if (BLE_EMB_PRESENT || BT_EMB_PRESENT) + KERNEL_EVENT_H4TL_CMD_HDR_RX = 10, + KERNEL_EVENT_H4TL_CMD_PLD_RX = 11, + #endif //(BLE_EMB_PRESENT || BT_EMB_PRESENT) + #endif //H4TL_SUPPORT + + #if (BLE_HOST_PRESENT) + #if (BLE_L2CC) + KERNEL_EVENT_L2CAP_TX = 12 , + #endif //(BLE_L2CC) + #endif// (BLE_HOST_PRESENT) + + #if BT_EMB_PRESENT + KERNEL_EVENT_BT_PSCAN_PROC = 13, + #endif //BT_EMB_PRESENT + + #if BLE_EMB_PRESENT + KERNEL_EVENT_BLE_EVT_DEFER = 14, + KERNEL_EVENT_BLE_EVT_DELETE = 15, + #endif //BLE_EMB_PRESENT + + #if defined(CFG_AUDIO_AOAHI) + KERNEL_EVENT_BLE_AUDIO_DEFER = 16, + #endif // defined(CFG_AUDIO_AOAHI) + + KERNEL_EVENT_MAX , +}; + +/// Tasks types definition +enum KERNEL_TASK_TYPE +{ +#if (BT_EMB_PRESENT) + // BT Controller Tasks + TASK_LM, + TASK_LC, + TASK_LB, + TASK_LD, + TASK_HCI, +#endif // (BT_EMB_PRESENT) + +#if (BLE_EMB_PRESENT) + // Link Layer Tasks + TASK_LLM = 0, + TASK_LLC = 1, + TASK_LLD = 2, +#else // !(BLE_EMB_PRESENT) + // Link Layer Tasks + TASK_LLM = 0, + TASK_LLC = 1, + TASK_LLD = 2, +#endif // (BLE_EMB_PRESENT) + +#if ((BLE_EMB_PRESENT) || (BT_EMB_PRESENT)) + TASK_DBG = 3, +#else // !((BLE_EMB_PRESENT) && (BT_EMB_PRESENT)) + TASK_DBG = 3, +#endif // ((BLE_EMB_PRESENT) || (BT_EMB_PRESENT)) + +#if (DISPLAY_SUPPORT) + TASK_DISPLAY = 4, +#else //!(DISPLAY_SUPPORT) + TASK_DISPLAY = 4, +#endif // (DISPLAY_SUPPORT) + +#if (BLE_APP_PRESENT) + TASK_APP = 5, +#else // !(BLE_APP_PRESENT) + TASK_APP = 5, +#endif // (BLE_APP_PRESENT) + +#if (BLE_HOST_PRESENT) + TASK_L2CC = 6, // L2CAP Controller Task + TASK_GATTM = 7, // Generic Attribute Profile Manager Task + TASK_GATTC = 8, // Generic Attribute Profile Controller Task + TASK_GAPM = 9, // Generic Access Profile Manager + TASK_GAPC = 10, // Generic Access Profile Controller + + // allocate a certain number of profiles task + TASK_PRF_MAX = (TASK_GAPC + BLE_NB_PROFILES),//BLE_NB_PROFILES MAX ROM USE == 6 + + #ifdef BLE_AUDIO_AM0_TASK + TASK_AM0 = TASK_PRF_MAX + 1, // BLE Audio Mode 0 Task + #endif // BLE_AUDIO_AM0_TASK +#endif // (BLE_HOST_PRESENT) + +#if (AHI_TL_SUPPORT) + TASK_AHI , +#endif // (AHI_TL_SUPPORT) + + /// Maximum number of tasks + TASK_BLE_MAX, + + TASK_BLE_NONE = 0xFF, +}; + +/// Kernel memory heaps types. +enum +{ + /// Memory allocated for environment variables + KERNEL_MEM_ENV, + #if (BLE_HOST_PRESENT) + /// Memory allocated for Attribute database + KERNEL_MEM_ATT_DB, + #endif // (BLE_HOST_PRESENT) + /// Memory allocated for kernel messages + KERNEL_MEM_KERNEL_MSG, + /// Non Retention memory block + KERNEL_MEM_NON_RETENTION, + KERNEL_MEM_BLOCK_MAX, +}; + + + +#if (BT_EMB_PRESENT) +#define BT_HEAP_MSG_SIZE_ BT_HEAP_MSG_SIZE +#define BT_HEAP_ENV_SIZE_ BT_HEAP_ENV_SIZE +#else +#define BT_HEAP_MSG_SIZE_ 0 +#define BT_HEAP_ENV_SIZE_ 0 +#endif //BT_EMB_PRESENT + +#if (BLE_EMB_PRESENT) +#define BLE_HEAP_MSG_SIZE_ BLE_HEAP_MSG_SIZE +#define BLE_HEAP_ENV_SIZE_ BLE_HEAP_ENV_SIZE +#else +#define BLE_HEAP_MSG_SIZE_ 0 +#define BLE_HEAP_ENV_SIZE_ 0 +#endif //BLE_EMB_PRESENT + +#if (BLE_HOST_PRESENT) +#define BLEHL_HEAP_MSG_SIZE_ BLEHL_HEAP_MSG_SIZE +#define BLEHL_HEAP_ENV_SIZE_ BLEHL_HEAP_ENV_SIZE +#define BLEHL_HEAP_DB_SIZE_ BLEHL_HEAP_DB_SIZE +#else +#define BLEHL_HEAP_MSG_SIZE_ 0 +#define BLEHL_HEAP_ENV_SIZE_ 0 +#define BLEHL_HEAP_DB_SIZE_ 0 +#endif //BLE_HOST_PRESENT + + +/// Kernel Message Heap +#define RWIP_HEAP_MSG_SIZE ( BT_HEAP_MSG_SIZE_ + \ + BLE_HEAP_MSG_SIZE_ + \ + BLEHL_HEAP_MSG_SIZE_ ) + +/// Number of link in kernel environment +#define KERNEL_NB_LINK_IN_HEAP_ENV 2 + +/// Size of Environment heap +#define RWIP_HEAP_ENV_SIZE ( BT_HEAP_ENV_SIZE_ + \ + ( BLE_HEAP_ENV_SIZE_ + \ + BLEHL_HEAP_ENV_SIZE_ ) \ + * KERNEL_NB_LINK_IN_HEAP_ENV ) + +/// Size of Attribute database heap +#define RWIP_HEAP_DB_SIZE ( BLEHL_HEAP_DB_SIZE ) + +/// Size of non retention heap - 512 bytes per ble link plus 4096 bytes for data throughput should be sufficient and should be tuned +#if (BLE_EMB_PRESENT || BLE_HOST_PRESENT) +#define RWIP_HEAP_NON_RET_SIZE (( 512 * BLE_CONNECTION_MAX ) + 4096) +#else +#define RWIP_HEAP_NON_RET_SIZE ( 512 ) +#endif + +/// Minimum sleep time to enter in deep sleep (in half slot). +#define RWIP_MINIMUM_SLEEP_TIME (1) + +/******************************************************************************************/ +/* ------------------------- BT-BLE COEX -----------------------------------*/ +/******************************************************************************************/ +#if (BLE_EMB_PRESENT || BT_EMB_PRESENT) + +/// Enable and diable definition for the PTI +///Enable TX busy signal +#define RWIP_PTI_TXEN 1 +///Disable TX busy signal +#define RWIP_PTI_TXDIS 0 +/// Tx busy position +#define RWIP_TXBSY_POS 0 + +///Enable RX busy signal +#define RWIP_PTI_RXEN 1 +///Disable RX busy signal +#define RWIP_PTI_RXDIS 0 +/// Rx busy position +#define RWIP_RXBSY_POS 1 + +///Enable do not abort TX +#define RWIP_PTI_DNABORTEN 1 +///Disable do not abort TX +#define RWIP_PTI_DNABORTDIS 0 +/// Do not abort busy position +#define RWIP_DNABORT_POS 2 + +///Allows Tx operation in the current frame. +#define RWIP_MWS_TXEN 0 +///Prevent from any Tx operation in the current frame. +#define RWIP_MWS_TXDIS 1 +/// MWS transmit disable position +#define RWIP_MWSTXDSB_POS 3 + +///Allows Rx operation in the current frame. +#define RWIP_MWS_RXEN 0 +///Prevent from any Rx operation in the current frame. +#define RWIP_MWS_RXDIS 1 +/// MWS transmit disable position +#define RWIP_MWSRXDSB_POS 4 + +/// Bit masking +#define RWIP_COEX_BIT_MASK 1 + +/// Coex configuration index +enum rwip_coex_config_idx +{ + #if (BT_EMB_PRESENT) + RWIP_COEX_MSSWITCH_IDX , + RWIP_COEX_SNIFFATT_IDX , + RWIP_COEX_PAGE_IDX, + RWIP_COEX_PSCAN_IDX, + RWIP_COEX_INQ_IDX, + RWIP_COEX_INQRES_IDX, + RWIP_COEX_SCORSVD_IDX, + RWIP_COEX_BCAST_IDX, + RWIP_COEX_CONNECT_IDX, + #endif //#if (BT_EMB_PRESENT) + #if (BLE_EMB_PRESENT) + RWIP_COEX_CON_IDX, + RWIP_COEX_CON_DATA_IDX, + RWIP_COEX_ADV_IDX, + RWIP_COEX_SCAN_IDX, + RWIP_COEX_INIT_IDX, + #endif // #if (BLE_EMB_PRESENT) + /// Max configuration index + RWIP_COEX_CFG_MAX, +}; +/******************************************************************************************/ +/* ------------------------- BT-BLE PRIORITIES -----------------------------------*/ +/******************************************************************************************/ +/// Priority index definition +enum rwip_prio_idx +{ + #if (BT_EMB_PRESENT) + /// ACL event default priority + RWIP_PRIO_ACL_DFT_IDX, + /// ACL event priority with activity + RWIP_PRIO_ACL_ACT_IDX, + /// ACL Role Switch event default priority + RWIP_PRIO_ACL_RSW_IDX, + /// ACL sniff event default priority + RWIP_PRIO_ACL_SNIFF_DFT_IDX, + /// ACL sniff transition event default priority + RWIP_PRIO_ACL_SNIFF_TRANS_IDX, + #if MAX_NB_SYNC + /// SCO event default priority + RWIP_PRIO_SCOMMON_DFT_IDX, + #endif //MAX_NB_SYNC + /// Broadcast ACL event default priority + RWIP_PRIO_BCST_DFT_IDX, + /// Broadcast ACL event with LMP activity priority + RWIP_PRIO_BCST_ACT_IDX, + /// CSB RX event default priority + RWIP_PRIO_CSB_RX_DFT_IDX, + /// CSB TX event default priority + RWIP_PRIO_CSB_TX_DFT_IDX, + /// Inquiry event default priority + RWIP_PRIO_INQ_DFT_IDX, + /// Inquiry Scan event default priority + RWIP_PRIO_ISCAN_DFT_IDX, + /// Page event default priority + RWIP_PRIO_PAGE_DFT_IDX, + /// Page event default priority + RWIP_PRIO_PAGE_1ST_PKT_IDX, + /// Page first packet event default priority + RWIP_PRIO_PCA_DFT_IDX, + /// Page scan event default priority + RWIP_PRIO_PSCAN_DFT_IDX, + /// Page scan event priority increment when canceled + RWIP_PRIO_PSCAN_1ST_PKT_IDX, + /// Synchronization Scan event default priority + RWIP_PRIO_SSCAN_DFT_IDX, + /// Synchronization Train event default priority + RWIP_PRIO_STRAIN_DFT_IDX, + #endif //#if (BT_EMB_PRESENT) + #if (BLE_EMB_PRESENT) + /// Default priority for scanning events + RWIP_PRIO_SCAN_IDX, + /// Default priority for initiating events + RWIP_PRIO_INIT_IDX, + /// Default priority for Le connection establishment + RWIP_PRIO_LE_ESTAB_IDX, + /// Default priority for Idle connection + RWIP_PRIO_LE_CON_IDLE_IDX, + /// Default priority for active connect events + RWIP_PRIO_LE_CON_ACT_IDX, + /// Default priority for advertising events + RWIP_PRIO_ADV_IDX, + /// Default priority for advertising high duty cycle events + RWIP_PRIO_ADV_HDC_IDX, + #endif // #if (BLE_EMB_PRESENT) + RWIP_PRIO_IDX_MAX +}; +/// Default priority value definition +enum rwip_prio_dft +{ + #if (BT_EMB_PRESENT) + /// ACL event default priority + RWIP_PRIO_ACL_DFT = 5, + /// ACL event priority with activity + RWIP_PRIO_ACL_ACT = 10, + /// ACL Role Switch event default priority + RWIP_PRIO_ACL_RSW = 20, + /// ACL sniff event default priority + RWIP_PRIO_ACL_SNIFF_DFT = 15, + /// ACL sniff transition event default priority + RWIP_PRIO_ACL_SNIFF_TRANS = 10, + #if MAX_NB_SYNC + /// SCO event default priority + RWIP_PRIO_SCOMMON_DFT = 18, + #endif //MAX_NB_SYNC + /// Broadcast ACL event default priority + RWIP_PRIO_BCST_DFT = 5, + /// Broadcast ACL event with LMP activity priority + RWIP_PRIO_BCST_ACT = 10, + /// CSB RX event default priority + RWIP_PRIO_CSB_RX_DFT = 10, + /// CSB TX event default priority + RWIP_PRIO_CSB_TX_DFT = 10, + /// Inquiry event default priority + RWIP_PRIO_INQ_DFT = 5, + /// Inquiry Scan event default priority + RWIP_PRIO_ISCAN_DFT = 5, + /// Page event default priority + RWIP_PRIO_PAGE_DFT = 8, + /// Page first packet event default priority + RWIP_PRIO_PAGE_1ST_PKT = 20, + /// PCA event default priority + RWIP_PRIO_PCA_DFT = 20, + /// Page scan event default priority + RWIP_PRIO_PSCAN_DFT = 8, + /// Page scan event priority increment when canceled + RWIP_PRIO_PSCAN_1ST_PKT = 20, + /// Synchronization Scan event default priority + RWIP_PRIO_SSCAN_DFT = 10, + /// Synchronization Train event default priority + RWIP_PRIO_STRAIN_DFT = 10, + #endif //#if (BT_EMB_PRESENT) + #if (BLE_EMB_PRESENT) + /// Default priority for scanning events + RWIP_PRIO_SCAN_DFT = 5, + /// Default priority for initiating events + RWIP_PRIO_INIT_DFT = 10, + /// Default priority for LE connection establishment + RWIP_PRIO_LE_ESTAB_DFT = 20, + /// Default priority for Idle connection + RWIP_PRIO_LE_CON_IDLE_DFT = 10, + /// Default priority for active connect events + RWIP_PRIO_LE_CON_ACT_DFT = 15, + /// Default priority for advertising events + RWIP_PRIO_ADV_DFT = 5, + /// Default priority for advertising high duty cycle events + RWIP_PRIO_ADV_HDC_DFT = 10, + #endif // #if (BLE_EMB_PRESENT) + /// Max priority + RWIP_PRIO_MAX = 31, +}; + +/// Default increment value definition +enum rwip_incr_dft +{ + #if (BT_EMB_PRESENT) + /// ACL event default increment + RWIP_INCR_ACL_DFT = 1, + /// ACL event increment with activity + RWIP_INCR_ACL_ACT = 1, + /// ACL Role Switch event default increment + RWIP_INCR_ACL_RSW = 1, + /// ACL sniff event default increment + RWIP_INCR_ACL_SNIFF_DFT = 1, + /// ACL sniff transition event default increment + RWIP_INCR_ACL_SNIFF_TRANS = 1, + #if MAX_NB_SYNC + /// SCO event default increment + RWIP_INCR_SCOMMON_DFT = 1, + #endif //MAX_NB_SYNC + /// Broadcast ACL event default increment + RWIP_INCR_BCST_DFT = 1, + /// Broadcast ACL event with LMP activity increment + RWIP_INCR_BCST_ACT = 1, + /// CSB RX event default increment + RWIP_INCR_CSB_RX_DFT = 1, + /// CSB TX event default increment + RWIP_INCR_CSB_TX_DFT = 1, + /// Inquiry event default increment + RWIP_INCR_INQ_DFT = 1, + /// Inquiry Scan event default increment + RWIP_INCR_ISCAN_DFT = 1, + /// Page event default increment + RWIP_INCR_PAGE_DFT = 1, + /// Page event default increment + RWIP_INCR_PAGE_1ST_PKT = 2, + /// Page first packet event default increment + RWIP_INCR_PCA_DFT = 1, + /// Page scan event default increment + RWIP_INCR_PSCAN_DFT = 1, + /// Page scan event increment increment when canceled + RWIP_INCR_PSCAN_1ST_PKT = 1, + /// Synchronization Scan event default increment + RWIP_INCR_SSCAN_DFT = 1, + /// Synchronization Train event default increment + RWIP_INCR_STRAIN_DFT = 1, + #endif //#if (BT_EMB_PRESENT) + #if (BLE_EMB_PRESENT) + /// Default increment for scanning events + RWIP_INCR_SCAN_DFT = 1, + /// Default increment for initiating events + RWIP_INCR_INIT_DFT = 1, + /// Default increment for LE connection establishment + RWIP_INCR_LE_ESTAB_DFT = 1, + /// Default increment for Idle connection + RWIP_INCR_LE_CON_IDLE_DFT = 1, + /// Default increment for active connect events + RWIP_INCR_LE_CON_ACT_DFT = 11, + /// Default increment for advertising events + RWIP_INCR_ADV_DFT = 1, + /// Default increment for advertising high duty cycle events + RWIP_INCR_ADV_HDC_PRIO_DFT = 1, + #endif // #if (BLE_EMB_PRESENT) +}; +#endif //#if (BLE_EMB_PRESENT || BT_EMB_PRESENT) +/// @} BT Stack Configuration +/// @} ROOT + +#endif //RWIP_CONFIG_H_ + diff --git a/beken_os/beken378/driver/ble/ble_pub/modules/rwip/api/rwip_task.h b/beken_os/beken378/driver/ble/ble_pub/modules/rwip/api/rwip_task.h new file mode 100755 index 0000000..3a2ffa5 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/modules/rwip/api/rwip_task.h @@ -0,0 +1,182 @@ +/** + **************************************************************************************** + * + * @file rwip_task.h + * + * @brief Task Identifier description for the RW IP + * + * Copyright (C) RivieraWaves 2009-2016 + * + **************************************************************************************** + */ + +#ifndef RWIP_TASK_H_ +#define RWIP_TASK_H_ + +/** + **************************************************************************************** + * @addtogroup ROOT + * @{ + * + * Information about RW SW TASK + * + * @name RW TASK Configuration + * @{ + **************************************************************************************** + */ + +#include + +/* + * DEFINES + **************************************************************************************** + */ + + +/// Build the first message ID of a task. (in fact a kernel_msg_id_t) +#define TASK_FIRST_MSG(task) ((uint16_t)((task) << 8)) + +/// Builds the task identifier from the type and the index of that task. +#define TASK_BUILD(type, index) ((uint16_t)(((index) << 8)|(type)) ) + +/// Retrieves task type from task id. +#define TASK_TYPE_GET(kernel_task_id) ((uint16_t) & 0xFF) + +/// Retrieves task index number from task id. +#define TASK_IDX_GET(kernel_task_id) (((uint16_t) >> 8) & 0xFF) + + +/// Tasks types definition, this value shall be in [0-254] range +enum TASK_API_ID +{ + // Link Layer Tasks + TASK_ID_LLM = 0, + TASK_ID_LLC = 1, + TASK_ID_LLD = 2, + TASK_ID_DBG = 3, + + // BT Controller Tasks + TASK_ID_LM = 4, + TASK_ID_LC = 5, + TASK_ID_LB = 6, + TASK_ID_LD = 7, + + TASK_ID_HCI = 8, + TASK_ID_DISPLAY = 9, + + // ----------------------------------------------------------------------------------- + // --------------------- BLE HL TASK API Identifiers --------------------------------- + // ----------------------------------------------------------------------------------- + + TASK_ID_L2CC = 10, // L2CAP Controller Task + TASK_ID_GATTM = 11, // Generic Attribute Profile Manager Task + TASK_ID_GATTC = 12, // Generic Attribute Profile Controller Task + TASK_ID_GAPM = 13, // Generic Access Profile Manager + TASK_ID_GAPC = 14, // Generic Access Profile Controller + + TASK_ID_APP = 15, // Application API + TASK_ID_AHI = 16, // Application Host Interface + + // ----------------------------------------------------------------------------------- + // --------------------- BLE Profile TASK API Identifiers ---------------------------- + // ----------------------------------------------------------------------------------- + TASK_ID_DISS = 20, // Device Information Service Server Task + TASK_ID_DISC = 21, // Device Information Service Client Task + + TASK_ID_PROXM = 22, // Proximity Monitor Task + TASK_ID_PROXR = 23, // Proximity Reporter Task + + TASK_ID_FINDL = 24, // Find Me Locator Task + TASK_ID_FINDT = 25, // Find Me Target Task + + TASK_ID_HTPC = 26, // Health Thermometer Collector Task + TASK_ID_HTPT = 27, // Health Thermometer Sensor Task + + TASK_ID_BLPS = 28, // Blood Pressure Sensor Task + TASK_ID_BLPC = 29, // Blood Pressure Collector Task + + TASK_ID_HRPS = 30, // Heart Rate Sensor Task + TASK_ID_HRPC = 31, // Heart Rate Collector Task + + TASK_ID_TIPS = 32, // Time Server Task + TASK_ID_TIPC = 33, // Time Client Task + + TASK_ID_SCPPS = 34, // Scan Parameter Profile Server Task + TASK_ID_SCPPC = 35, // Scan Parameter Profile Client Task + + TASK_ID_BASS = 36, // Battery Service Server Task + TASK_ID_BASC = 37, // Battery Service Client Task + + TASK_ID_HOGPD = 38, // HID Device Task + TASK_ID_HOGPBH = 39, // HID Boot Host Task + TASK_ID_HOGPRH = 40, // HID Report Host Task + + TASK_ID_GLPS = 41, // Glucose Profile Sensor Task + TASK_ID_GLPC = 42, // Glucose Profile Collector Task + + TASK_ID_RSCPS = 43, // Running Speed and Cadence Profile Server Task + TASK_ID_RSCPC = 44, // Running Speed and Cadence Profile Collector Task + + TASK_ID_CSCPS = 45, // Cycling Speed and Cadence Profile Server Task + TASK_ID_CSCPC = 46, // Cycling Speed and Cadence Profile Client Task + + TASK_ID_ANPS = 47, // Alert Notification Profile Server Task + TASK_ID_ANPC = 48, // Alert Notification Profile Client Task + + TASK_ID_PASPS = 49, // Phone Alert Status Profile Server Task + TASK_ID_PASPC = 50, // Phone Alert Status Profile Client Task + + TASK_ID_CPPS = 51, // Cycling Power Profile Server Task + TASK_ID_CPPC = 52, // Cycling Power Profile Client Task + + TASK_ID_LANS = 53, // Location and Navigation Profile Server Task + TASK_ID_LANC = 54, // Location and Navigation Profile Client Task + + TASK_ID_IPSS = 55, // Internet Protocol Support Profile Server Task + TASK_ID_IPSC = 56, // Internet Protocol Support Profile Client Task + + TASK_ID_ENVS = 57, // Environmental Sensing Profile Server Task + TASK_ID_ENVC = 58, // Environmental Sensing Profile Client Task + + TASK_ID_WSCS = 59, // Weight Scale Profile Server Task + TASK_ID_WSCC = 60, // Weight Scale Profile Client Task + + TASK_ID_UDSS = 61, // User Data Service Server Task + TASK_ID_UDSC = 62, // User Data Service Client Task + + TASK_ID_BCSS = 63, // Body Composition Server Task + TASK_ID_BCSC = 64, // Body Composition Client Task + + TASK_ID_WPTS = 65, // Wireless Power Transfer Profile Server Task + TASK_ID_WPTC = 66, // Wireless Power Transfer Profile Client Task + + TASK_ID_PLXS = 67, // Pulse Oximeter Profile Server Task + TASK_ID_PLXC = 68, // Pulse Oximeter Profile Client Task + + TASK_ID_FFF0S = 69, // FFF0 Profile Server Task + + TASK_ID_FFE0S = 70, // FFE0 Profile Server Task + + TASK_ID_OADS = 71, // OADS Profile Server Task + + TASK_ID_ANCSC = 72, // ANCS Profile Client Task + +#if (BLE_SDP_CLIENT) + TASK_ID_SDP = 100, // SDP Client Task +#endif + +#if (BLE_COMM_SERVER) + TASK_ID_COMMON = 200, +#endif + + /* 240 -> 241 reserved for Audio Mode 0 */ + TASK_ID_AM0 = 240, // BLE Audio Mode 0 Task + TASK_ID_AM0_HAS = 241, // BLE Audio Mode 0 Hearing Aid Service Task + + TASK_ID_INVALID = 0xFF, // Invalid Task Identifier +}; + +/// @} BT Stack Configuration +/// @} ROOT + +#endif //RWIP_CONFIG_H_ diff --git a/beken_os/beken378/driver/ble/ble_pub/modules/rwip/src/rwip.c b/beken_os/beken378/driver/ble/ble_pub/modules/rwip/src/rwip.c new file mode 100755 index 0000000..81fec0d --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/modules/rwip/src/rwip.c @@ -0,0 +1,1074 @@ +/** +**************************************************************************************** +* +* @file rwip.c +* +* @brief RW IP SW main module +* +* Copyright (C) RivieraWaves 2009-2015 +* +* +**************************************************************************************** +*/ + +/** + **************************************************************************************** + * @addtogroup RW IP SW main module + * @ingroup ROOT + * @brief The RW IP SW main module. + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" // RW SW configuration + +#include // for mem* functions +#include "rwip.h" // RW definitions +#include "architect.h" // Platform architecture definition +#include "BK3435_reg.h" +#include "ble_rf.h" + +#if (NVDS_SUPPORT) +#include "nvds.h" // NVDS definitions +#endif // NVDS_SUPPORT + +#if (BT_EMB_PRESENT) +#include "rwbt.h" // rwbt definitions +#endif //BT_EMB_PRESENT + +#if (BLE_EMB_PRESENT) +#include "rwble.h" // rwble definitions +#endif //BLE_EMB_PRESENT + +#if (BLE_HOST_PRESENT) +#include "rwble_hl.h" // BLE HL definitions +#include "gapc.h" +#include "gattc.h" +#include "l2cc.h" +#endif //BLE_HOST_PRESENT + +#if (BLE_APP_PRESENT) +#include "application.h" // Application definitions +#endif //BLE_APP_PRESENT + +#if (DEEP_SLEEP) +#if (BLE_EMB_PRESENT) +#include "lld_sleep.h" // definitions for sleep mode +#endif //BLE_EMB_PRESENT +#endif //DEEP_SLEEP + +#if (BLE_EMB_PRESENT) +#include "llcontrl.h" +#endif //BLE_EMB_PRESENT + +#if (BLE_EMB_PRESENT) +#include "lld_wlcoex.h" +#endif //BLE_EMB_PRESENT +#if (BT_EMB_PRESENT) +#include "ld.h" +#endif //BT_EMB_PRESENT + +#if (DISPLAY_SUPPORT) +#include "display.h" // display definitions +#endif //DISPLAY_SUPPORT + +#if (EA_PRESENT) +#include "ea.h" // Event Arbiter definitions +#endif //EA_PRESENT + +#if (BT_EMB_PRESENT || BLE_EMB_PRESENT) +#include "plf.h" // platform definition + +#endif //BT_EMB_PRESENT || BLE_EMB_PRESENT + +#if (H4TL_SUPPORT) +#include "h4tl.h" +#endif //H4TL_SUPPORT + +#if (AHI_TL_SUPPORT) +#include "ahi.h" +#endif //AHI_TL_SUPPORT + +#if (HCI_PRESENT) +#include "hci.h" // HCI definition +#endif //HCI_PRESENT + +#if (KERNEL_SUPPORT) +#include "kernel.h" // kernel definition +#include "kernel_event.h" // kernel event +#include "kernel_timer.h" // definitions for timer +#include "kernel_mem.h" // kernel memory manager +#endif //KERNEL_SUPPORT + +#if (SECURE_CONNECTIONS && (BT_EMB_PRESENT || BLE_EMB_PRESENT)) +#include "ecc_p256.h" // ECC P256 library +#endif // (SECURE_CONNECTIONS && (BT_EMB_PRESENT || BLE_EMB_PRESENT)) + +#include "dbg.h" // debug definition + +#include "driver_sys_ctrl.h" +#include "uart_pub.h" +#include "ble.h" +#include "ble_pub.h" +#include "ble_api.h" + +/* + * DEFINES + **************************************************************************************** + */ + +/// Time information +typedef struct +{ + /// Time in 625 us step. + uint32_t time; + /// number of us before getting next tick + uint32_t next_tick; +} rwip_time_t; + + +#if (DEEP_SLEEP) +/// Sleep Duration Value in periodic wake-up mode +#define MAX_SLEEP_DURATION_PERIODIC_WAKEUP 0x0320*20 //10s // 0.5s +/// Sleep Duration Value in external wake-up mode +#define MAX_SLEEP_DURATION_EXTERNAL_WAKEUP 0x3E80*3 //30s //10s + +#define MAX_SLEEP_DURATION_SHORT_WAKEUP 160 + +#endif //DEEP_SLEEP + + + +// Heap header size is 12 bytes +#define RWIP_HEAP_HEADER (12 / sizeof(uint32_t)) +// ceil(len/sizeof(uint32_t)) + RWIP_HEAP_HEADER +#define RWIP_CALC_HEAP_LEN(len) ((((len) + (sizeof(uint32_t) - 1)) / sizeof(uint32_t)) + RWIP_HEAP_HEADER) + +/* + * STRUCT DEFINITIONS + **************************************************************************************** + */ +#if (BLE_EMB_PRESENT || BT_EMB_PRESENT) +/* +/// Local supported commands +const struct rwip_prio rwip_priority[RWIP_PRIO_IDX_MAX]={ + #if (BT_EMB_PRESENT) + {RWIP_PRIO_ACL_DFT, RWIP_INCR_ACL_DFT}, + {RWIP_PRIO_ACL_ACT, RWIP_INCR_ACL_ACT}, + {RWIP_PRIO_ACL_RSW, RWIP_INCR_ACL_RSW}, + {RWIP_PRIO_ACL_SNIFF_DFT, RWIP_INCR_ACL_SNIFF_DFT}, + {RWIP_PRIO_ACL_SNIFF_TRANS,RWIP_INCR_ACL_SNIFF_TRANS}, + #if MAX_NB_SYNC + {RWIP_PRIO_SCO_DFT, RWIP_INCR_SCO_DFT}, + #endif //MAX_NB_SYNC + {RWIP_PRIO_BCST_DFT, RWIP_INCR_BCST_DFT}, + {RWIP_PRIO_BCST_ACT, RWIP_INCR_BCST_ACT}, + {RWIP_PRIO_CSB_RX_DFT, RWIP_INCR_CSB_RX_DFT}, + {RWIP_PRIO_CSB_TX_DFT, RWIP_INCR_CSB_TX_DFT}, + {RWIP_PRIO_INQ_DFT, RWIP_INCR_INQ_DFT}, + {RWIP_PRIO_ISCAN_DFT, RWIP_INCR_ISCAN_DFT}, + {RWIP_PRIO_PAGE_DFT, RWIP_INCR_PAGE_DFT}, +{RWIP_PRIO_PAGE_1ST_PKT, RWIP_INCR_PAGE_1ST_PKT}, + {RWIP_PRIO_PCA_DFT, RWIP_INCR_PCA_DFT}, + {RWIP_PRIO_PSCAN_DFT, RWIP_INCR_PSCAN_DFT}, + {RWIP_PRIO_PSCAN_1ST_PKT, RWIP_INCR_PSCAN_1ST_PKT}, + {RWIP_PRIO_SSCAN_DFT, RWIP_INCR_SSCAN_DFT}, + {RWIP_PRIO_STRAIN_DFT, RWIP_INCR_STRAIN_DFT}, + #endif // #if (BT_EMB_PRESENT) + #if (BLE_EMB_PRESENT) + {RWIP_PRIO_SCAN_DFT, RWIP_INCR_SCAN_DFT}, + {RWIP_PRIO_INIT_DFT, RWIP_INCR_INIT_DFT}, + {RWIP_PRIO_LE_ESTAB_DFT, RWIP_INCR_LE_ESTAB_DFT}, + {RWIP_PRIO_LE_CON_IDLE_DFT, RWIP_INCR_LE_CON_IDLE_DFT}, + {RWIP_PRIO_LE_CON_ACT_DFT, RWIP_INCR_LE_CON_ACT_DFT}, + {RWIP_PRIO_ADV_DFT, RWIP_INCR_ADV_DFT}, + {RWIP_PRIO_ADV_HDC_DFT, RWIP_INCR_ADV_HDC_PRIO_DFT}, + #endif // #if (BLE_EMB_PRESENT) +}; +*/ +/* +const uint8_t rwip_coex_cfg[RWIP_COEX_CFG_MAX]={ + #if (BT_EMB_PRESENT) + [RWIP_COEX_MSSWITCH_IDX] = (RWIP_PTI_TXEN << RWIP_TXBSY_POS) | (RWIP_PTI_RXEN << RWIP_RXBSY_POS) | (RWIP_PTI_DNABORTDIS << RWIP_DNABORT_POS) \ + | (RWIP_MWS_TXEN << RWIP_MWSTXDSB_POS) | (RWIP_MWS_RXEN << RWIP_MWSRXDSB_POS), + [RWIP_COEX_SNIFFATT_IDX] = (RWIP_PTI_TXEN << RWIP_TXBSY_POS) | (RWIP_PTI_RXEN << RWIP_RXBSY_POS) | (RWIP_PTI_DNABORTDIS << RWIP_DNABORT_POS) \ + | (RWIP_MWS_TXEN << RWIP_MWSTXDSB_POS) | (RWIP_MWS_RXEN << RWIP_MWSRXDSB_POS), + [RWIP_COEX_PAGE_IDX ] = (RWIP_PTI_TXEN << RWIP_TXBSY_POS) | (RWIP_PTI_RXEN << RWIP_RXBSY_POS) | (RWIP_PTI_DNABORTEN << RWIP_DNABORT_POS) \ + | (RWIP_MWS_TXEN << RWIP_MWSTXDSB_POS) | (RWIP_MWS_RXEN << RWIP_MWSRXDSB_POS), + [RWIP_COEX_PSCAN_IDX ] = (RWIP_PTI_TXEN << RWIP_TXBSY_POS) | (RWIP_PTI_RXEN << RWIP_RXBSY_POS) | (RWIP_PTI_DNABORTDIS << RWIP_DNABORT_POS) \ + | (RWIP_MWS_TXEN << RWIP_MWSTXDSB_POS) | (RWIP_MWS_RXEN << RWIP_MWSRXDSB_POS), + [RWIP_COEX_INQ_IDX ] = (RWIP_PTI_TXEN << RWIP_TXBSY_POS) | (RWIP_PTI_RXEN << RWIP_RXBSY_POS) | (RWIP_PTI_DNABORTDIS << RWIP_DNABORT_POS) \ + | (RWIP_MWS_TXEN << RWIP_MWSTXDSB_POS) | (RWIP_MWS_RXEN << RWIP_MWSRXDSB_POS), + [RWIP_COEX_INQRES_IDX ] = (RWIP_PTI_TXEN << RWIP_TXBSY_POS) | (RWIP_PTI_RXEN << RWIP_RXBSY_POS) | (RWIP_PTI_DNABORTDIS << RWIP_DNABORT_POS) \ + | (RWIP_MWS_TXEN << RWIP_MWSTXDSB_POS) | (RWIP_MWS_RXEN << RWIP_MWSRXDSB_POS), + [RWIP_COEX_SCORSVD_IDX ] = (RWIP_PTI_TXEN << RWIP_TXBSY_POS) | (RWIP_PTI_RXEN << RWIP_RXBSY_POS) | (RWIP_PTI_DNABORTDIS << RWIP_DNABORT_POS) \ + | (RWIP_MWS_TXEN << RWIP_MWSTXDSB_POS) | (RWIP_MWS_RXEN << RWIP_MWSRXDSB_POS), + [RWIP_COEX_BCAST_IDX ] = (RWIP_PTI_TXEN << RWIP_TXBSY_POS) | (RWIP_PTI_RXEN << RWIP_RXBSY_POS) | (RWIP_PTI_DNABORTDIS << RWIP_DNABORT_POS) \ + | (RWIP_MWS_TXEN << RWIP_MWSTXDSB_POS) | (RWIP_MWS_RXEN << RWIP_MWSRXDSB_POS), + [RWIP_COEX_CONNECT_IDX ] = (RWIP_PTI_TXEN << RWIP_TXBSY_POS) | (RWIP_PTI_RXEN << RWIP_RXBSY_POS) | (RWIP_PTI_DNABORTDIS << RWIP_DNABORT_POS) \ + | (RWIP_MWS_TXEN << RWIP_MWSTXDSB_POS) | (RWIP_MWS_RXEN << RWIP_MWSRXDSB_POS), + #endif // #if (BT_EMB_PRESENT) + #if (BLE_EMB_PRESENT) + [RWIP_COEX_CON_IDX] = (uint8_t)((RWIP_PTI_TXDIS << RWIP_TXBSY_POS) | (RWIP_PTI_RXDIS << RWIP_RXBSY_POS) | (RWIP_PTI_DNABORTDIS << RWIP_DNABORT_POS)), + [RWIP_COEX_CON_DATA_IDX]= (uint8_t)((RWIP_PTI_TXEN << RWIP_TXBSY_POS) | (RWIP_PTI_RXEN << RWIP_RXBSY_POS) | (RWIP_PTI_DNABORTDIS << RWIP_DNABORT_POS)), + [RWIP_COEX_ADV_IDX] = (uint8_t)((RWIP_PTI_TXEN << RWIP_TXBSY_POS) | (RWIP_PTI_RXDIS << RWIP_RXBSY_POS) | (RWIP_PTI_DNABORTDIS << RWIP_DNABORT_POS)), + [RWIP_COEX_SCAN_IDX] = (uint8_t)((RWIP_PTI_TXDIS << RWIP_TXBSY_POS) | (RWIP_PTI_RXEN << RWIP_RXBSY_POS) | (RWIP_PTI_DNABORTDIS << RWIP_DNABORT_POS)), + [RWIP_COEX_INIT_IDX] = (uint8_t)((RWIP_PTI_TXEN << RWIP_TXBSY_POS) | (RWIP_PTI_RXEN << RWIP_RXBSY_POS) | (RWIP_PTI_DNABORTDIS << RWIP_DNABORT_POS)), + #endif // #if (BLE_EMB_PRESENT) +}; + +*/ +#endif//#if (BLE_EMB_PRESENT || BT_EMB_PRESENT) + +/// RWBT Environment +#if (DEEP_SLEEP) +struct rwip_env_tag +{ + /// Power_up delay + uint32_t lp_cycle_wakeup_delay; + /// Contains sleep duration accumulated timing error + uint32_t sleep_acc_error; + /// Duration of sleep and wake-up algorithm (depends on CPU speed) expressed in us. + uint16_t sleep_algo_dur; + /// Prevent sleep bit field + uint16_t prevent_sleep; + uint8_t wakeup_delay; + bool sleep_enable; + bool ext_wakeup_enable; +}; +#endif //DEEP_SLEEP +/* + * GLOBAL VARIABLES + **************************************************************************************** + */ +#if 0 +#define KERNEL_HEAP __attribute__((section("kernel_heap"),zero_init)) +#else +#define KERNEL_HEAP +#endif + + +#if (DEEP_SLEEP) +/// RW SW environment +static struct rwip_env_tag rwip_env; +#endif //DEEP_SLEEP +/// RF API +struct rwip_rf_api rwip_rf; + +/// Heap definitions - use uint32 to ensure that memory blocks are 32bits aligned. +#if (KERNEL_MEM_RW) + +/// Memory allocated for environment variables +uint32_t KERNEL_HEAP rwip_heap_env[RWIP_CALC_HEAP_LEN(RWIP_HEAP_ENV_SIZE)]; +//uint32_t rwip_heap_env[RWIP_CALC_HEAP_LEN(RWIP_HEAP_ENV_SIZE)]; +#if (BLE_HOST_PRESENT) +/// Memory allocated for Attribute database +uint32_t KERNEL_HEAP rwip_heap_db[RWIP_CALC_HEAP_LEN(RWIP_HEAP_DB_SIZE)]; +//uint32_t rwip_heap_db[RWIP_CALC_HEAP_LEN(RWIP_HEAP_DB_SIZE)]; +#endif // (BLE_HOST_PRESENT) + +/// Memory allocated for kernel messages +//uint32_t rwip_heap_msg[RWIP_CALC_HEAP_LEN(RWIP_HEAP_MSG_SIZE)]; +/// Non Retention memory block +//uint32_t rwip_heap_non_ret[RWIP_CALC_HEAP_LEN(RWIP_HEAP_NON_RET_SIZE)]; + +/// Memory allocated for kernel messages +uint32_t KERNEL_HEAP rwip_heap_msg[RWIP_CALC_HEAP_LEN(RWIP_HEAP_MSG_SIZE)]; +/// Non Retention memory block +uint32_t KERNEL_HEAP rwip_heap_non_ret[RWIP_CALC_HEAP_LEN(RWIP_HEAP_NON_RET_SIZE)]; + +#endif // (KERNEL_MEM_RW) + +/* + * LOCAL FUNCTION DEFINITIONS + **************************************************************************************** + */ + + +#if (DEEP_SLEEP && BLE_EMB_PRESENT) +/** + **************************************************************************************** + * @brief check If the fine counter is close the 3/4 of the slot boundary (624 >> 2) * 3 = 468 + * + * @return when boundary wak-up is ok + **************************************************************************************** + */ +bool rwip_check_wakeup_boundary(void) +{ + //Sample the base time count + ble_samp_setf(1); + while (ble_samp_getf()); + return ((ble_finetimecnt_get() < 468) ? false : true); +} +#endif //DEEP_SLEEP && BLE_EMB_PRESENT + + +#if (DEEP_SLEEP) +/** + **************************************************************************************** + * @brief Converts a duration in slots into a number of low power clock cycles. + * The function converts a duration in slots into a number of low power clock cycles. + * Sleep clock runs at either 32768Hz or 32000Hz, so this function divides the value in + * slots by 20.48 or 20 depending on the case. + * To do this the following formulae are applied: + * + * N = x * 20.48 = (2048 * x)/100 for a 32.768kHz clock or + * N = x * 20 for a 32kHz clock + * + * @param[in] slot_cnt The value in slot count + * + * @return The number of low power clock cycles corresponding to the slot count + * + **************************************************************************************** + */ +static uint32_t rwip_slot_2_lpcycles(uint32_t slot_cnt) +{ + uint32_t lpcycles; + + // Sanity check: The number of slots should not be too high to avoid overflow + ASSERT_ERR(slot_cnt < 1000000); + + #if HZ32000 + // Compute the low power clock cycles - case of a 32kHz clock + lpcycles = slot_cnt * 20; + #else //HZ32000 + // Compute the low power clock cycles - case of a 32.768kHz clock + lpcycles = (slot_cnt << 11)/100; + #endif //HZ32000 + + // Corner case, Sleep duration is exactly on slot boundary so slot interrupt will not + // be generated on expected slot (but next one). + + // So reduce little bit sleep duration in order to allow fine time compensation + // Note compensation will be in range of [1 , 2[ lp cycles + + lpcycles--; + + return(lpcycles); +} +#endif //(DEEP_SLEEP) + +void rwip_reg_init(void) +{ + ble_set_power_up(1); + + //ICU_TL410_BLE_CLK = 0x0; //enable ble clock icu 0x04 + ble_clk_power_up(); + + //REG_ICU_INT_ENABLE |= (1<<30); //enable ble INT icu 0x10 + ble_intc_set(1); + + REG_BLE_XVR_SLOT_TIME = 0x0D123B6D; // BLE_XVR 0x2a + REG_BLE_XVR_TX_CONFIG = REG_BLE_XVR_TX_CONFIG | 0x80; // BLE_XVR 0x30 + REG_BLE_XVR_AGC_CONFIG = 0x03371C02; // BLE_XVR 0x3c + + //ble_switch_rf_to_ble(); +} + +void rwip_reg_deinit(void) +{ + ble_switch_rf_to_wifi(); + + ble_intc_set(0); + + ble_clk_power_down(); + + ble_set_power_up(0); +} + +void rwip_reg_reinit(void) +{ + ble_clk_power_up(); + + ble_intc_set(1); + //ble_switch_rf_to_ble(); +} + +/* + * EXPORTED FUNCTION DEFINITIONS + **************************************************************************************** + */ +extern uint8_t cur_read_buf_idx; + +void rwip_init(uint32_t error) +{ + #if (NVDS_SUPPORT && DEEP_SLEEP) + uint8_t length = 1; + uint8_t sleep_enable; + uint8_t ext_wakeup_enable; + #endif //NVDS_SUPPORT && DEEP_SLEEP + #if (DEEP_SLEEP) + // Reset RW environment + memset(&rwip_env, 0, sizeof(rwip_env)); + #endif //DEEPSLEEP + #if (KERNEL_SUPPORT) + // Initialize kernel + kernel_init(); + // Initialize memory heap used by kernel. + #if (KERNEL_MEM_RW) + // Memory allocated for environment variables + kernel_mem_init(KERNEL_MEM_ENV, (uint8_t*)rwip_heap_env, RWIP_HEAP_ENV_SIZE); + #if (BLE_HOST_PRESENT) + // Memory allocated for Attribute database + kernel_mem_init(KERNEL_MEM_ATT_DB, (uint8_t*)rwip_heap_db, RWIP_HEAP_DB_SIZE); + #endif // (BLE_HOST_PRESENT) + // Memory allocated for kernel messages + kernel_mem_init(KERNEL_MEM_KERNEL_MSG, (uint8_t*)rwip_heap_msg, RWIP_HEAP_MSG_SIZE); + // Non Retention memory block + kernel_mem_init(KERNEL_MEM_NON_RETENTION, (uint8_t*)rwip_heap_non_ret, RWIP_HEAP_NON_RET_SIZE); + #endif // (KERNEL_MEM_RW) + #endif //KERNEL_SUPPORT + // Initialize RF + #if (BT_EMB_PRESENT || BLE_EMB_PRESENT) + rf_init(&rwip_rf); + #endif //BT_EMB_PRESENT || BLE_EMB_PRESENT + + #if (SECURE_CONNECTIONS && (BT_EMB_PRESENT || BLE_EMB_PRESENT)) + // Initialize Diffie Hellman Elliptic Curve Algorithm + ecc_init(false); + #endif // (SECURE_CONNECTIONS && (BT_EMB_PRESENT || BLE_EMB_PRESENT)) + // Initialize H4 TL + #if (H4TL_SUPPORT) + #if (BLE_HOST_PRESENT) + #if (BLE_EMB_PRESENT) // FULL HOST + h4tl_init(H4TL_TYPE_AHI, rwip_eif_get(RWIP_EIF_AHI),&cur_read_buf_idx); + #else // !(BLE_EMB_PRESENT) // SPLIT HOST + #if(AHI_TL_SUPPORT) + h4tl_init(H4TL_TYPE_AHI, rwip_eif_get(RWIP_EIF_AHI),&cur_read_buf_idx); + #endif // AHI_TL_SUPPORT + h4tl_init(H4TL_TYPE_HCI, rwip_eif_get(RWIP_EIF_HCIH),&cur_read_buf_idx); + #endif // (BLE_EMB_PRESENT) + #else // !(BLE_HOST_PRESENT) // SPLIT EMB + h4tl_init(H4TL_TYPE_HCI, rwip_eif_get(RWIP_EIF_HCIC),&cur_read_buf_idx); + #endif // (BLE_HOST_PRESENT) + #endif //(H4TL_SUPPORT) + #if (HCI_PRESENT) + // Initialize the HCI + hci_init(); + #endif //HCI_PRESENT + + #if (AHI_TL_SUPPORT) + // Initialize the Application Host Interface + // ahi_init(); + #endif //AHI_TL_SUPPORT + + #if (BLE_HOST_PRESENT) + // Initialize BLE Host stack + rwble_hl_init(); + #endif //BLE_HOST_PRESENT + #if (BT_EMB_PRESENT) + // Initialize BT + rwbt_init(); + #endif //BT_EMB_PRESENT + + #if (BLE_EMB_PRESENT) + // Initialize BLE + rwble_init(); + #endif //BLE_EMB_PRESENT + #if (BT_EMB_PRESENT || BLE_EMB_PRESENT) + #if (RW_DEBUG) + // Initialize the debug process + dbg_init(); + #endif //(RW_DEBUG) + #endif //(BT_EMB_PRESENT || BLE_EMB_PRESENT) + + #if (EA_PRESENT) + //Initialize Event arbiter + ea_init(false); + #endif //(EA_PRESENT) + + #if 0// (NVDS_SUPPORT && DEEP_SLEEP) + // Activate deep sleep feature if enabled in NVDS + if(nvds_get(NVDS_TAG_SLEEP_ENABLE, &length, &sleep_enable) == NVDS_OK) + { + if(sleep_enable != 0) + { + rwip_env.sleep_enable = true; + + // Set max sleep duration depending on wake-up mode + if(nvds_get(NVDS_TAG_EXT_WAKEUP_ENABLE, &length, &ext_wakeup_enable) == NVDS_OK) + { + if(ext_wakeup_enable != 0) + { + rwip_env.ext_wakeup_enable = true; + } + } + } + } + + #endif //NVDS_SUPPORT && DEEP_SLEEP + + + #if ( DEEP_SLEEP) + rwip_env.sleep_enable = true; + rwip_env.ext_wakeup_enable = true; + rwip_env.wakeup_delay = 3;///16; + #endif + + //rwip_env.ext_wakeup_enable = true; + #if (BT_EMB_PRESENT || (BLE_EMB_PRESENT && !BLE_HOST_PRESENT)) + // If FW initializes due to FW reset, send the message to Host + if(error != RESET_NO_ERROR) + { + if(error == RESET_TO_ROM || error == RESET_AND_LOAD_FW) + { + // Send platform reset command complete if requested by user + //// + } + else + { + // Allocate a message structure for hardware error event + struct hci_hw_err_evt *evt = KERNEL_MSG_ALLOC(HCI_EVENT, 0, HCI_HW_ERR_EVT_CODE, hci_hw_err_evt); + + // Fill the HW error code + switch(error) + { + case RESET_MEM_ALLOC_FAIL: evt->hw_code = COMMON_ERROR_HW_MEM_ALLOC_FAIL; break; + default: ASSERT_INFO(0, error, 0); break; + } + + // Send the message + hci_send_2_host(evt); + } + } + #endif //(BT_EMB_PRESENT || (BLE_EMB_PRESENT && !BLE_HOST_PRESENT)) + /* + ************************************************************************************ + * Application initialization + ************************************************************************************ + */ + #if (BLE_APP_PRESENT) + // Initialize APP + appm_init(); + #endif //BLE_APP_PRESENT +} + +void rwip_reset(void) +{ +#if (NVDS_SUPPORT && DEEP_SLEEP) + //uint8_t length = 1; + //uint8_t sleep_enable; + //uint8_t ext_wakeup_enable; + #endif //NVDS_SUPPORT && DEEP_SLEEP + + + // Disable interrupts until reset procedure is completed + GLOBAL_INT_DIS(); + + #if (KERNEL_SUPPORT) + //Clear all message and timer pending + kernel_flush(); + #endif //KERNEL_SUPPORT + + #if (SECURE_CONNECTIONS && (BT_EMB_PRESENT || BLE_EMB_PRESENT)) + // Reset Diffie Hellman Elliptic Curve Algorithm + ecc_init(true); + #endif // (SECURE_CONNECTIONS && (BT_EMB_PRESENT || BLE_EMB_PRESENT)) + + #if (HCI_PRESENT) + // Reset the HCI + hci_reset(); + #endif //HCI_PRESENT + + #if (BT_EMB_PRESENT) + // Reset BT + rwbt_reset(); + #endif //BT_EMB_PRESENT + + #if (BLE_EMB_PRESENT) + // Reset BLE + rwble_reset(); + #endif //BLE_EMB_PRESENT + +#if 0 + #if (NVDS_SUPPORT && DEEP_SLEEP) + // Activate deep sleep feature if enabled in NVDS + if(nvds_get(NVDS_TAG_SLEEP_ENABLE, &length, &sleep_enable) == NVDS_OK) + { + if(sleep_enable != 0) + { + rwip_env.sleep_enable = true; + rwip_env.sleep_acc_error = 0; + + // Set max sleep duration depending on wake-up mode + if(nvds_get(NVDS_TAG_EXT_WAKEUP_ENABLE, &length, &ext_wakeup_enable) == NVDS_OK) + { + if(ext_wakeup_enable != 0) + { + rwip_env.ext_wakeup_enable = true; + } + } + + // Set max sleep duration depending on wake-up mode + length = NVDS_LEN_SLEEP_ALGO_DUR; + if(nvds_get(NVDS_TAG_SLEEP_ALGO_DUR, &length, (uint8_t*) &rwip_env.sleep_algo_dur) != NVDS_OK) + { + // set a default duration: 200 us + rwip_env.sleep_algo_dur = 200; + } + } + } + #endif //NVDS_SUPPORT && DEEP_SLEEP +#endif + + #if (EA_PRESENT) + ea_init(true); + #endif //(EA_PRESENT) + + // Reset the RF + rwip_rf.reset(); + + #if (DISPLAY_SUPPORT) + // Restart display module + display_resume(); + #endif //DISPLAY_SUPPORT + + // Restore interrupts once reset procedure is completed + GLOBAL_INT_RES(); +} + +void rwip_version(uint8_t* fw_version, uint8_t* hw_version) +{ + #if (BT_EMB_PRESENT) + rwbt_version(fw_version , hw_version); + #elif (BLE_EMB_PRESENT) + rwble_version(fw_version , hw_version); + #endif //BT_EMB_PRESENT / BLE_EMB_PRESENT +} + +uint32_t rwip_get_current_time(void) +{ + return (ea_time_get_halfslot_rounded()); +} + +uint32_t rwip_get_next_target_time(void) +{ + return (ea_timer_next_target_get()); +} + +void rwip_schedule(void) +{ + #if (KERNEL_SUPPORT) + #if (DEEP_SLEEP) + // If system is waking up, delay the handling + if ((rwip_env.prevent_sleep & RW_WAKERNEL_UP_ONGOING) == 0) + #endif // DEEP_SLEEP + + { + // schedule all pending events + kernel_event_schedule(); + + } + #endif //KERNEL_SUPPORT +} + +uint8_t rwip_sleep(void) +{ + uint8_t proc_sleep = RW_NO_SLEEP; + #if (DEEP_SLEEP) + uint32_t sleep_duration; + if(ble_ps_enabled()) + { + sleep_duration = MAX_SLEEP_DURATION_EXTERNAL_WAKEUP;///MAX_SLEEP_DURATION_SHORT_WAKEUP; + } + else + { + sleep_duration = MAX_SLEEP_DURATION_EXTERNAL_WAKEUP; //10s + } + #endif //DEEP_SLEEP + + DBG_SWDIAG(SLEEP, ALGO, 0); + + do + { + /************************************************************************ + ************** CHECK KERNEL EVENTS ************** + ************************************************************************/ + // Check if some kernel processing is ongoing + if (!kernel_sleep_check()) + { + ble_ps_forbid_trace(BLE_PS_FORBID_KRL); + break; + } + + //Processor sleep can be enabled + proc_sleep |= RW_MCU_IDLE_SLEEP; + + DBG_SWDIAG(SLEEP, ALGO, 1); + + #if (DEEP_SLEEP) + /************************************************************************ + ************** CHECK ENABLE FLAG ************** + ************************************************************************/ + // Check sleep enable flag + if(!rwip_env.sleep_enable) + { + ble_ps_forbid_trace(BLE_PS_FORBID_ENABLED); + break; + } + /************************************************************************ + ************** CHECK RW FLAGS ************** + ************************************************************************/ + // First check if no pending procedure prevent from going to sleep + if (rwip_env.prevent_sleep != 0) + { + //proc_sleep |= RW_MCU_IDLE_SLEEP; + ble_ps_forbid_trace(BLE_PS_FORBID_PREVENT); + break; + } + + DBG_SWDIAG(SLEEP, ALGO, 2); + /************************************************************************ + ************** CHECK EXT WAKEUP FLAG ************** + ************************************************************************/ + /* If external wakeup enable, sleep duration can be set to maximum, otherwise + * system should be woken-up periodically to poll incoming packets from HCI */ + if(!rwip_env.ext_wakeup_enable) + sleep_duration = MAX_SLEEP_DURATION_PERIODIC_WAKEUP; + + #if (BLE_EMB_PRESENT) + /************************************************************************ + * Wait until there's enough time for SLP to restore clocks when the chip + * wakes up. + ************************************************************************/ + while(!rwip_check_wakeup_boundary()); + #endif //(BLE_EMB_PRESENT) + + /************************************************************************ + ************** CHECK KERNEL TIMERS ************** + ************************************************************************/ + // Compute the duration up to the next software timer expires + if (!kernel_timer_sleep_check(&sleep_duration, rwip_env.wakeup_delay)) + { + ble_ps_forbid_trace(BLE_PS_FORBID_TM); + break; + } + + DBG_SWDIAG(SLEEP, ALGO, 3); + + #if (BT_EMB_PRESENT) + /************************************************************************ + ************** CHECK BT ************** + ************************************************************************/ + if (!rwbt_sleep_check()) + { + ble_ps_forbid_trace(BLE_PS_FORBID_RWBT); + break; + } + #endif //BT_EMB_PRESENT + + #if (BLE_EMB_PRESENT) + /************************************************************************ + ************** CHECK BLE ************** + ************************************************************************/ + if (!rwble_sleep_check()) + { + proc_sleep = RW_NO_SLEEP; + ble_ps_forbid_trace(BLE_PS_FORBID_RWBLE); + break; + } + #endif //(BLE_EMB_PRESENT) + DBG_SWDIAG(SLEEP, ALGO, 4); + + /************************************************************************ + ************** CHECK EA ************** + ************************************************************************/ + if (!ea_sleep_check(&sleep_duration, rwip_env.wakeup_delay)) + { + //proc_sleep = false; + ble_ps_forbid_trace(BLE_PS_FORBID_EA); + break; + + } + + DBG_SWDIAG(SLEEP, ALGO, 5); + + #if (H4TL_SUPPORT) + /************************************************************************ + ************** CHECK TL ************** + ************************************************************************/ + // Try to switch off TL + if (!h4tl_stop()) + { + proc_sleep = RW_NO_SLEEP; + ble_ps_forbid_trace(BLE_PS_FORBID_H4TL); + break; + } + #endif //H4TL_SUPPORT + + #if 0 + /************************************************************************ + ************** CHECK UART ************** + ************************************************************************/ + // Try to switch off TL + if (!check_uart_stop()) + { + proc_sleep = false; + break; + } + #endif //PLF_UART + + DBG_SWDIAG(SLEEP, ALGO, 6); + + /************************************************************************ + ************** PROGRAM CORE DEEP SLEEP ************** + ************************************************************************/ + + // Put BT core into deep sleep + lld_sleep_enter(rwip_slot_2_lpcycles(sleep_duration), rwip_env.ext_wakeup_enable); + rwip_prevent_sleep_set(RW_SLEEP_EVENT_ONGOING); + + DBG_SWDIAG(SLEEP, SLEEP, 1); + + /************************************************************************ + ************** SWITCH OFF RF ************** + ************************************************************************/ + rwip_rf.sleep(); + proc_sleep |= RW_MCU_DEEP_SLEEP; + #endif // DEEP_SLEEP + + } while(0); + + return proc_sleep; +} + +#if (DEEP_SLEEP) +void rwip_wakeup(void) +{ + DBG_SWDIAG(SLEEP, SLEEP, 0); + + // Prevent going to deep sleep until a slot interrupt is received + rwip_prevent_sleep_set(RW_WAKERNEL_UP_ONGOING); + + #if (BT_EMB_PRESENT) + // Wake-up BT core + rwbt_sleep_wakeup(); + #elif (BLE_EMB_PRESENT) + // Wake-up BLE core + lld_sleep_wakeup(); + #endif //BT_EMB_PRESENT / BLE_EMB_PRESENT +} + +void rwip_wakeup_end(void) +{ + if(rwip_env.prevent_sleep & RW_WAKERNEL_UP_ONGOING) + { + #if (BT_EMB_PRESENT) + rwbt_sleep_wakeup_end(); + #elif (BLE_EMB_PRESENT) + // Wake-up BLE core + lld_sleep_wakeup_end(); + #endif //BT_EMB_PRESENT / BLE_EMB_PRESENT + + // Schedule the kernel timers + kernel_event_set(KERNEL_EVENT_KERNEL_TIMER); + + // Wake up is complete now, so we allow the deep sleep again + rwip_prevent_sleep_clear(RW_WAKERNEL_UP_ONGOING); + + } +} + +void rwip_wakeup_delay_set(uint16_t wakeup_delay) +{ + rwip_env.lp_cycle_wakeup_delay = rwip_us_2_lpcycles(wakeup_delay); +} + +void rwip_prevent_sleep_set(uint16_t prv_slp_bit) +{ + GLOBAL_INT_DIS(); + rwip_env.prevent_sleep |= prv_slp_bit; + DBG_SWDIAG(SLEEP, PREVENT, rwip_env.prevent_sleep); + GLOBAL_INT_RES(); +} + +void rwip_prevent_sleep_clear(uint16_t prv_slp_bit) +{ + GLOBAL_INT_DIS(); + rwip_env.prevent_sleep &= ~prv_slp_bit; + DBG_SWDIAG(SLEEP, PREVENT, rwip_env.prevent_sleep); + GLOBAL_INT_RES(); +} + +bool rwip_sleep_enable(void) +{ + return rwip_env.sleep_enable; +} + +bool rwip_ext_wakeup_enable(void) +{ + return rwip_env.ext_wakeup_enable; +} + +void ble_rwip_ps_dump(void) +{ + os_printf("bleprevent:%x sleep_enable:%x ext_wakeup_enable:%x\r\n", + rwip_env.prevent_sleep,rwip_env.sleep_enable,rwip_env.ext_wakeup_enable); +} + +/** + **************************************************************************************** + * @brief Converts a duration in lp cycles into a duration is us. + * + * The function converts a duration in lp cycles into a duration is us, according to the + * low power clock frequency (32768Hz or 32000Hz). + * + * To do this the following formulae are applied: + * + * Tus = x*30.517578125 = 30*x + x/2 + x/64 + x/512 for a 32.768kHz clock or + * Tus = x*31.25 = 31*x + x/4 for a 32kHz clock + * + * + * @param[in] lpcycles duration in lp cycles + * + * @return duration in us + **************************************************************************************** + */ +uint32_t rwip_sleep_lpcycles_2_us(uint32_t lpcycles) +{ + uint32_t res; + + // Sanity check: The number of lp cycles should not be too high to avoid overflow + ASSERT_ERR(lpcycles < 1000000); + + #if (HZ32000) + // Compute the sleep duration in us - case of a 32kHz clock and insert previous computed error + rwip_env.sleep_acc_error = lpcycles + rwip_env.sleep_acc_error; + // get the truncated value + res = rwip_env.sleep_acc_error >> 2; + // retrieve new inserted error + rwip_env.sleep_acc_error = rwip_env.sleep_acc_error - (res << 2); + // finish computation + res = (31 * lpcycles) + res; + #else //HZ32000 + // Compute the sleep duration in half us - case of a 32.768kHz clock and insert previous computed error + rwip_env.sleep_acc_error = ((lpcycles << 8) + (lpcycles << 3) + lpcycles) + rwip_env.sleep_acc_error; + // get the truncated value + res = rwip_env.sleep_acc_error >> 9; + // retrieve new inserted error + rwip_env.sleep_acc_error = rwip_env.sleep_acc_error - (res << 9); + // finish computation + res = (30 * lpcycles) + res; + #endif //HZ32000 + + return res; +} + + +/** + **************************************************************************************** + * @brief Converts a duration in us into a duration in lp cycles. + * + * The function converts a duration in us into a duration is lp cycles, according to the + * low power clock frequency (32768Hz or 32000Hz). + * + * @param[in] us duration in us + * + * @return duration in lpcycles + **************************************************************************************** + */ +uint32_t rwip_us_2_lpcycles(uint32_t us) +{ + uint32_t lpcycles; + + #if (HZ32000) + // Compute the low power clock cycles - case of a 32kHz clock + lpcycles = (us * 32) / 1000; + #else //HZ32000 + // Compute the low power clock cycles - case of a 32.768kHz clock + lpcycles = (us * 32768) / 1000000; + #endif //HZ32000 + + return(lpcycles); +} + +#else // DEEP_SLEEP + +void rwip_wakeup_delay_set(uint16_t wakeup_delay) +{ + +} + +void rwip_prevent_sleep_set(uint16_t prv_slp_bit) +{ + +} + +void rwip_prevent_sleep_clear(uint16_t prv_slp_bit) +{ + +} + +uint32_t rwip_sleep_lpcycles_2_us(uint32_t lpcycles) +{ + return 1; +} + +uint32_t rwip_us_2_lpcycles(uint32_t us) +{ + return 1; +} + +#endif// DEEP_SLEEP + +#if (BT_EMB_PRESENT) + +#if PCA_SUPPORT +bool rwip_pca_clock_dragging_only(void) +{ +#if (BLE_EMB_PRESENT) + return rwble_activity_ongoing_check(); +#else + return false; +#endif // BLE_EMB_PRESENT +} +#endif // PCA_SUPPORT +#endif // BT_EMB_PRESENT + +#if (BT_EMB_PRESENT || BLE_EMB_PRESENT) +#if (RW_MWS_COEX) +void rwip_mwscoex_set(bool state) +{ +#if (BLE_EMB_PRESENT) + lld_mwscoex_set(state); +#endif // BLE_EMB_PRESENT +#if (BT_EMB_PRESENT) + ld_mwscoex_set(state); +#endif // BT_EMB_PRESENT +} +#endif // RW_MWS_COEX +#if (RW_WLAN_COEX) +void rwip_wlcoex_set(bool state) +{ +#if (BLE_EMB_PRESENT) + lld_wlcoex_set(state); +#endif // BLE_EMB_PRESENT +#if (BT_EMB_PRESENT) + ld_wlcoex_set(state); +#endif // BT_EMB_PRESENT +} +#endif // RW_WLAN_COEX +#endif // (BT_EMB_PRESENT || BLE_EMB_PRESENT) + +#if RW_DEBUG +void rwip_assert_err(const char * file, int line, int param0, int param1) +{ + #if (BT_EMB_PRESENT || (BLE_EMB_PRESENT && !BLE_HOST_PRESENT)) + struct hci_dbg_assert_err_evt *evt = KERNEL_MSG_ALLOC_DYN(HCI_DBG_EVT, 0, 0, hci_dbg_assert_err_evt, sizeof(struct hci_dbg_assert_err_evt) + strlen(file)); + evt->subcode = HCI_DBG_ASSERT_ERR_EVT_SUBCODE; + evt->line = line; + evt->param0 = param0; + evt->param1 = param1; + strcpy((char *) evt->file, file); + hci_send_2_host(evt); + #endif //(BT_EMB_PRESENT || (BLE_EMB_PRESENT && !BLE_HOST_PRESENT)) +} +#endif //RW_DEBUG + +///@} RW diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/arch/BK3435_reg.h b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/arch/BK3435_reg.h new file mode 100755 index 0000000..ef4de50 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/arch/BK3435_reg.h @@ -0,0 +1,827 @@ + +#ifndef _BK3433_REG_H_ +#define _BK3433_REG_H_ + + + +///////////////////////////////////////////////////////////////////////////// +//memory layout +///////////////////////////////////////////////////////////////////////////// +#define ROM_START_ADDR 0x00000000 +#define RAM_START_ADDR 0x00400000 + +#define AHB0_ICU_BASE 0x00800000 +#define AHB1_XVR_BASE 0x00801400 +#define AHB_FLASH_BASE 0x00802000 +#define AHB6_AHB2APB_BASE 0x00806000 +#define AHB10_RW_REG_BASE 0x00810000 +#define AHB14_RW_EM_BASE 0x00814000 + +#define APB0_WDT_BASE 0x00806000 +#define APB1_PWM_BASE 0x00806100 +#define APB2_SPI_BASE 0x00806200 +#define APB3_UART_BASE 0x00806300 +#define APB4_I2C_BASE 0x00806400 +#define APB5_GPIO_BASE 0x00806500 +#define APB6_RTC_BASE 0x00806600 +#define APB7_ADC_BASE 0x00806700 + +#define APB_BLE_BASE 0x00802000 + +#define p_AHB0_ICU_BASE (*((volatile unsigned long *) 0x00800000)) +#define p_AHB1_XVR_BASE (*((volatile unsigned long *) 0x00801400)) +#define p_AHB3_MFC_BASE (*((volatile unsigned long *) 0x00803000)) +#define p_AHB6_AHB2APB_BASE (*((volatile unsigned long *) 0x00806000)) +#define p_AHB1_RW_REG_BASE (*((volatile unsigned long *) 0x00810000)) +#define p_AHB1_RW_EM_BASE (*((volatile unsigned long *) 0x00814000)) + +#define p_APB0_WDT_BASE (*((volatile unsigned long *) 0x00806000)) +#define p_APB1_PWM_BASE (*((volatile unsigned long *) 0x00806100)) +#define p_APB2_SPI_BASE (*((volatile unsigned long *) 0x00806200)) +#define p_APB3_UART_BASE (*((volatile unsigned long *) 0x00806300)) +#define p_APB4_I2C_BASE (*((volatile unsigned long *) 0x00806400)) +#define p_APB5_GPIO_BASE (*((volatile unsigned long *) 0x00806500)) +#define p_APB6_RTC_BASE (*((volatile unsigned long *) 0x00806600)) +#define p_APB7_ADC_BASE (*((volatile unsigned long *) 0x00806700)) + +///////////////////////////////////////////////////////////////////////////// +//register definition +///////////////////////////////////////////////////////////////////////////// +//ICU register definitions +#define REG_AHB0_ICU_CLKSRCSEL (*((volatile unsigned long *) 0x00800000)) +#define SET_CLK_SEL_32K 0x0 +#define SET_CLK_SEL_16M 0x1 +#define SET_CLK_SEL_48M 0x3 + +#define REG_AHB0_ICU_CORECLKCON (*((volatile unsigned long *) 0x00800004)) +#define BIT_CORE_CLK_DIV 1 + +#define REG_AHB0_ICU_ADCCLKCON (*((volatile unsigned long *) 0x00800008)) +#define REG_AHB0_ICU_UARTCLKCON (*((volatile unsigned long *) 0x0080000c)) +#define REG_AHB0_ICU_I2CCLKCON (*((volatile unsigned long *) 0x00800010)) +#define REG_AHB0_ICU_SPICLKCON (*((volatile unsigned long *) 0x00800014)) +#define REG_AHB0_ICU_BLECLKCON (*((volatile unsigned long *) 0x00800018)) +#define REG_AHB0_ICU_WDTCLKCON (*((volatile unsigned long *) 0x0080001c)) +#define REG_AHB0_ICU_RNGCLKCON (*((volatile unsigned long *) 0x00800020)) +#define REG_AHB0_ICU_PWMCLKCON (*((volatile unsigned long *) 0x00800024)) +#define BIT_PWM_CLK_SEL 1 +#define SET_PWM_CLK_SEL (0x1 << BIT_PWM_CLK_SEL) + +#define REG_AHB0_ICU_RTCCLKCON (*((volatile unsigned long *) 0x00800028)) + +#define REG_AHB0_ICU_LPO_CLK_ON (*((volatile unsigned long *) 0x0080002C)) + +#define REG_AHB0_ICU_CLK32K_SEL (*((volatile unsigned long *) 0x00800030)) +#define REG_AHB0_ICU_ANA_CTL (*((volatile unsigned long *) 0x00800034)) + +#define REG_AHB0_ICU_CPU_STATUS (*((volatile unsigned long *) 0x00800038)) + +#define REG_AHB0_ICU_INT_ENABLE (*((volatile unsigned long *) 0x00800040)) +#define REG_AHB0_ICU_IRQ_ENABLE (*((volatile unsigned long *) 0x00800044)) +#define REG_AHB0_ICU_INT_FLAG (*((volatile unsigned long *) 0x00800048)) +#define REG_AHB0_ICU_FLASH (*((volatile unsigned long *) 0x0080004c)) +#define REG_AHB0_ICU_ANALOG_MODE (*((volatile unsigned long *) 0x00800050)) +#define REG_AHB0_ICU_ANALOG0_PWD (*((volatile unsigned long *) 0x00800054)) +#define REG_AHB0_ICU_ANALOG1_PWD (*((volatile unsigned long *) 0x00800058)) +#define REG_AHB0_ICU_DIGITAL_PWD (*((volatile unsigned long *) 0x0080005c)) + +//Digital PWD Bit +#define BIT_ANA_TEST_PIN 5 +#define BIT_BB_TEST_PIN 4 +#define BIT_CLK16M_PWD 3 +#define BIT_HP_LDO_PWD 2 +#define BIT_CLK48M_PWD 1 +#define BIT_CB_BAIS_PWD 0 +#define SET_ANA_TEST_PIN (0x01 << BIT_ANA_TEST_PIN) +#define SET_BB_TEST_PIN (0x01 << BIT_BB_TEST_PIN) +#define SET_CLK16M_PWD (0x01 << BIT_CLK16M_PWD ) +#define SET_HP_LDO_PWD (0x01 << BIT_HP_LDO_PWD ) +#define SET_CLK48M_PWD (0x01 << BIT_CLK48M_PWD ) +#define SET_CB_BAIS_PWD (0x01 << BIT_CB_BAIS_PWD) + + +#define ICU_POWER_CONTROL_JTAG_MODE_POSI 9 +#define ICU_POWER_CONTROL_JTAG_MODE_MASK (0x01UL << ICU_POWER_CONTROL_JTAG_MODE_POSI) + +#define CLOSE_JTAG_MODE() do {REG_AHB0_ICU_CLKSRCSEL &= (~ICU_POWER_CONTROL_JTAG_MODE_MASK);} while(0) +#define OPEN_JTAG_MODE() do {REG_AHB0_ICU_CLKSRCSEL |= ( ICU_POWER_CONTROL_JTAG_MODE_MASK);} while(0) + + + +// DEEP_SLEEP0 is GPIO-A to GPIO-D deep sleep wake-en +// DEEP_SLEEP1 is GPIO-E deep sleep wake-en and deep sleep word +#define REG_AHB0_ICU_DEEP_SLEEP0 (*((volatile unsigned long *) 0x00800060)) +#define REG_AHB0_ICU_DEEP_SLEEP1 (*((volatile unsigned long *) 0x00800064)) +#define BIT_GPIOA_WAKERNEL_EN 0 +#define BIT_GPIOB_WAKERNEL_EN 8 +#define BIT_GPIOC_WAKERNEL_EN 16 +#define BIT_GPIOD_WAKERNEL_EN 24 +#define BIT_GPIOE_WAKERNEL_EN 0 +#define BIT_DEEP_SLEEP_WORD 16 +#define SET_DEEP_SLEEP_WORD (0xFFFF << BIT_DEEP_SLEEP_WORD) + +#define REG_AHB0_ICU_RC32K_CONFG (*((volatile unsigned long *) 0x00800068)) +#define REG_AHB0_ICU_SLEEP_TIME (*((volatile unsigned long *) 0x0080006C)) +#define BIT_MANU_FIN 8 +#define BIT_MANU_CIN 3 +#define BIT_MANU_EN 2 +#define BIT_CALI_MODE 1 +#define BIT_SPI_TRIG 0 +#define SET_MANU_FIN (0x1FF<< BIT_MANU_FIN ) +#define SET_MANU_CIN (0x1F << BIT_MANU_CIN ) +#define SET_MANU_EN (0x1 << BIT_MANU_EN ) +#define SET_CALI_MODE (0x1 << BIT_CALI_MODE) +#define SET_SPI_TRIG (0x1 << BIT_SPI_TRIG ) + + + +//FIQ +#define INT_STATUS_PWM0_bit (0x01<<0) +#define INT_STATUS_LBD_bit (0x01<<10) +#define INT_STATUS_BLE_bit (0x01<<30) +//IRQ + +#define INT_STATUS_SDM_bit (0x01<<17) +#define INT_STATUS_RTC_bit (0x01<<12) +#define INT_STATUS_RNG_bit (0x01<<11) +#define INT_STATUS_GPIO_bit (0x01<< 9) +#define INT_STATUS_ADC_bit (0x01<< 8) +#define INT_STATUS_I2C_bit (0x01<< 7) +#define INT_STATUS_SPI_bit (0x01<< 6) +#define INT_STATUS_UART_bit (0x01<< 5) +#define INT_STATUS_PWM4_bit (0x01<< 4) +#define INT_STATUS_PWM3_bit (0x01<< 3) +#define INT_STATUS_PWM2_bit (0x01<< 2) +#define INT_STATUS_PWM1_bit (0x01<< 1) + +#define INT_IRQ_BIT (0x01<<0) +#define FIQ_IRQ_BIT (0x01<<1) + +//RF register definitions +//===================================================================================== + + + +//===================================================================================== +//FLASH +//===================================================================================== +#define REG_FLASH_OPERATE_SW (*((volatile unsigned long *) (AHB_FLASH_BASE+0*4))) +#define REG_FLASH_DATA_SW_FLASH (*((volatile unsigned long *) (AHB_FLASH_BASE+1*4))) +#define REG_FLASH_DATA_FLASH_SW (*((volatile unsigned long *) (AHB_FLASH_BASE+2*4))) +#define REG_FLASH_RDID_DATA_FLASH (*((volatile unsigned long *) (AHB_FLASH_BASE+4*4))) +#define REG_FLASH_SR_DATA_CRC_CNT (*((volatile unsigned long *) (AHB_FLASH_BASE+5*4))) +#define REG_FLASH_CONF (*((volatile unsigned long *) (AHB_FLASH_BASE+7*4))) +#define flash_200k_ADDR (*((volatile unsigned long *) (0x00032000))) +#define BIT_ADDRESS_SW 0 +#define BIT_OP_TYPE_SW 24 +#define BIT_OP_SW 29 +#define BIT_WP_VALUE 30 +#define BIT_BUSY_SW 31 + +#define SET_ADDRESS_SW 0xFFFFFF << BIT_ADDRESS_SW +#define SET_OP_TYPE_SW 0x1F << BIT_OP_TYPE_SW +#define SET_OP_SW 0x1 << BIT_OP_SW +#define SET_WP_VALUE 0x1 << BIT_WP_VALUE +#define SET_BUSY_SW 0x1 << BIT_BUSY_SW + +#define BIT_FLASH_CLK_CONF 0 +#define BIT_MODE_SEL 4 +#define BIT_FWREN_FLASH_CPU 9 +#define BIT_WRSR_DATA 10 +#define BIT_CRC_EN 26 + +#define SET_FLASH_CLK_CONF 0xF << BIT_FLASH_CLK_CONF +#define SET_MODE_SEL 0x1F << BIT_MODE_SEL +#define SET_FWREN_FLASH_CPU 0x1 << BIT_FWREN_FLASH_CPU +#define SET_WRSR_DATA 0xFFFF << BIT_WRSR_DATA +#define SET_CRC_EN 0x1 << BIT_CRC_EN + +#define BIT_SR_DATA_FLASH 0 +#define BIT_CRC_ERR_COUNTER 8 +#define BIT_DATA_FLASH_SW_SEL 16 +#define BIT_DATA_SW_FLASH_SEL 19 + +#define SET_SR_DATA_FLASH 0xFF << BIT_SR_DATA_FLASH +#define SET_CRC_ERR_COUNTER 0xFF << BIT_CRC_ERR_COUNTER +#define SET_DATA_FLASH_SW_SEL 0x7 << BIT_DATA_FLASH_SW_SEL +#define SET_DATA_SW_FLASH_SEL 0x7 << BIT_DATA_SW_FLASH_SEL + +//WDT +#define REG_APB0_WDT_CFG (*((volatile unsigned long *) 0x00806000)) + + +//===================================================================================== +//PWM +//===================================================================================== + + +#define REG_APB1_PWM_CFG (*((volatile unsigned long *) (APB1_PWM_BASE + 0*0x04))) + +#define REG_APB1_PWM_INT_STATUS (*((volatile unsigned long *) (APB1_PWM_BASE + 0x01*0x04))) + +#define REG_APB1_PWM0_VALUE_CFG (*((volatile unsigned long *) (APB1_PWM_BASE + 0x02*0x04))) +#define REG_APB1_PWM0_CAP_OUT (*((volatile unsigned long *) (APB1_PWM_BASE + 0x03*0x04))) + +#define REG_APB1_PWM1_VALUE_CFG (*((volatile unsigned long *) (APB1_PWM_BASE + 0x04*0x04))) +#define REG_APB1_PWM1_CAP_OUT (*((volatile unsigned long *) (APB1_PWM_BASE + 0x05*0x04))) + + +#define REG_APB1_PWM2_VALUE_CFG (*((volatile unsigned long *) (APB1_PWM_BASE + 0x06*0x04))) +#define REG_APB1_PWM2_CAP_OUT (*((volatile unsigned long *) (APB1_PWM_BASE + 0x07*0x04))) + +#define REG_APB1_PWM3_VALUE_CFG (*((volatile unsigned long *) (APB1_PWM_BASE + 0x08*0x04))) +#define REG_APB1_PWM3_CAP_OUT (*((volatile unsigned long *) (APB1_PWM_BASE + 0x09*0x04))) + +#define REG_APB1_PWM4_VALUE_CFG (*((volatile unsigned long *) (APB1_PWM_BASE + 0x0a*0x04))) +#define REG_APB1_PWM4_CAP_OUT (*((volatile unsigned long *) (APB1_PWM_BASE + 0x0b*0x04))) + +#define REG_APB1_PWM5_VALUE_CFG (*((volatile unsigned long *) (APB1_PWM_BASE + 0x0c*0x04))) +#define REG_APB1_PWM5_CAP_OUT (*((volatile unsigned long *) (APB1_PWM_BASE + 0x0d*0x04))) + + + +#define DC_VALUE_CFG(v) (((v)&0xffff) << 16) +#define END_VALUE_CFG(v) (((v)&0xffff) << 0) + +#define PT0_MODE_BIT 2 +#define PT1_MODE_BIT 6 +#define PT2_MODE_BIT 10 +#define PT3_MODE_BIT 14 +#define PT4_MODE_BIT 18 +#define PT5_MODE_BIT 22 + +#define PT0_ENABLE_BIT 0 +#define PT1_ENABLE_BIT 4 +#define PT2_ENABLE_BIT 8 +#define PT3_ENABLE_BIT 12 +#define PT4_ENABLE_BIT 16 +#define PT5_ENABLE_BIT 20 + +#define PT0_INT_ENABLE_BIT 1 +#define PT1_INT_ENABLE_BIT 5 +#define PT2_INT_ENABLE_BIT 9 +#define PT3_INT_ENABLE_BIT 13 +#define PT4_INT_ENABLE_BIT 17 +#define PT5_INT_ENABLE_BIT 21 + +#define PT_CLK_DIV_BIT 8 +#define PT0_INT_FLAG (1<<0) +#define PT1_INT_FLAG (1<<1) +#define PT2_INT_FLAG (1<<2) +#define PT3_INT_FLAG (1<<3) +#define PT4_INT_FLAG (1<<4) +#define PT5_INT_FLAG (1<<5) +#define SET_PT_CLK_DIV (0xF << PT_CLK_DIV_BIT) + + +// PWM Test Firmware Definition +#define BK_PWM_MODE 0 +#define BK_TIMER_MODE 1 +#define BK_CAP_P_MODE 2 +#define BK_CAP_N_MODE 3 + +#define PWM_CLK_SEL32K 0 +#define PWM_CLK_SEL16M 1 + + +//===================================================================================== + + +//SPI +#define REG_APB2_SPI_CTRL (*((volatile unsigned long *) 0x00806200)) +#define REG_APB2_SPI_STAT (*((volatile unsigned long *) 0x00806204)) +#define REG_APB2_SPI_DAT (*((volatile unsigned long *) 0x00806208)) + +#define BIT_SPI_CTRL_SPIEN 23 +#define BIT_SPI_CTRL_MSTEN 22 +#define BIT_SPI_CTRL_CKPHA 21 +#define BIT_SPI_CTRL_CKPOL 20 +#define BIT_SPI_CTRL_BIT_WIDTH 18 +#define BIT_SPI_CTRL_NSSMD 16 +#define BIT_SPI_CTRL_SPI_CKR 8 +#define BIT_SPI_CTRL_RXINT_EN 7 +#define BIT_SPI_CTRL_TXINT_EN 6 +#define BIT_SPI_CTRL_RXOVR_EN 5 +#define BIT_SPI_CTRL_TXOVR_EN 4 +#define BIT_SPI_CTRL_RXINT_MODE 2 +#define BIT_SPI_CTRL_TXINT_MODE 0 + + +#define BIT_SPI_STAT_SPI_BUSY 15 +#define BIT_SPI_STAT_SLVSEL 14 +#define BIT_SPI_STAT_RXOVR 12 +#define BIT_SPI_STAT_TXOVR 11 +#define BIT_SPI_STAT_MODF 10 +#define BIT_SPI_STAT_RXINT 9 +#define BIT_SPI_STAT_TXINT 8 +#define BIT_SPI_STAT_RXFIFO_FULL 3 +#define BIT_SPI_STAT_RXFIFO_EMPTY 2 +#define BIT_SPI_STAT_TXFIFO_FULL 1 +#define BIT_SPI_STAT_TXFIFO_EMPTY 0 + +#define BIT_PMU_SPI_PWD (1<<0) + +#define SPI_TX_FIFO_EMPTY (REG_APB2_SPI_STAT & (0x01 << BIT_SPI_STAT_TXFIFO_EMPTY)) +#define SPI_TX_FIFO_FULL (REG_APB2_SPI_STAT & (0x01 << BIT_SPI_STAT_TXFIFO_FULL)) +#define SPI_RX_FIFO_EMPTY (REG_APB2_SPI_STAT & (0x01 << BIT_SPI_STAT_RXFIFO_EMPTY)) +#define SPI_RX_FIFO_FULL (REG_APB2_SPI_STAT & (0x01 << BIT_SPI_STAT_RXFIFO_FULL)) + +#define GET_SPI_TX_INT_STAT() (REG_APB2_SPI_STAT & (0x01 << BIT_SPI_STAT_TXINT)) +#define CLEAR_SPI_TX_INT_STAT() ((REG_APB2_SPI_STAT &= ~(0x01 << BIT_SPI_STAT_TXINT))) + + +//===================================================================================== +// UART +//===================================================================================== +#include "ble.h" +#if (BLE_DUT_UART_PORT == PORT_UART2) +#define REG_APB3_UART_CFG (*((volatile unsigned long *) 0x00802200)) +#define REG_APB3_UART_FIFO_CFG (*((volatile unsigned long *) 0x00802204)) +#define REG_APB3_UART_FIFO_STAT (*((volatile unsigned long *) 0x00802208)) +#define REG_APB3_UART_PORT (*((volatile unsigned long *) 0x0080220C)) +#define REG_APB3_UART_INT_ENABLE (*((volatile unsigned long *) 0x00802210)) +#define REG_APB3_UART_INT_STAT (*((volatile unsigned long *) 0x00802214)) +#define REG_APB3_UART_FLOW_CFG (*((volatile unsigned long *) 0x00802218)) +#define REG_APB3_UART_WAKERNEL_CFG (*((volatile unsigned long *) 0x0080221c)) +#else +#define REG_APB3_UART_CFG (*((volatile unsigned long *) 0x00802100)) +#define REG_APB3_UART_FIFO_CFG (*((volatile unsigned long *) 0x00802104)) +#define REG_APB3_UART_FIFO_STAT (*((volatile unsigned long *) 0x00802108)) +#define REG_APB3_UART_PORT (*((volatile unsigned long *) 0x0080210C)) +#define REG_APB3_UART_INT_ENABLE (*((volatile unsigned long *) 0x00802110)) +#define REG_APB3_UART_INT_STAT (*((volatile unsigned long *) 0x00802114)) +#define REG_APB3_UART_FLOW_CFG (*((volatile unsigned long *) 0x00802118)) +#define REG_APB3_UART_WAKERNEL_CFG (*((volatile unsigned long *) 0x0080211c)) +#endif // (BLE_DUT_UART_PORT == PORT_UART2) + +#define BIT_UART_TX_ENABLE 0 +#define BIT_UART_RX_ENABLE 1 +#define BIT_UART_IRDA 2 +#define BIT_UART_LEN 3 +#define BIT_UART_PAR_EN 5 +#define BIT_UART_PAR_MODE 6 +#define BIT_UART_STOP_LEN 7 +#define BIT_UART_CLK_DIVID 8 +#define SET_UART_TX_ENABLE (0x1 << BIT_UART_TX_ENABLE) +#define SET_UART_TX_DISABLE (0x0 << BIT_UART_TX_ENABLE) +#define SET_UART_RX_ENABLE (0x1 << BIT_UART_RX_ENABLE) +#define SET_UART_RX_DISABLE (0x0 << BIT_UART_RX_ENABLE) +#define SET_UART_IRDA (0x1 << BIT_UART_IRDA ) +#define SET_UART_LEN (0x3 << BIT_UART_LEN ) +#define SET_UART_PAR_EN (0x1 << BIT_UART_PAR_EN ) +#define SET_UART_PAR_MODE (0x1 << BIT_UART_PAR_MODE ) +#define SET_UART_STOP_LEN (0x1 << BIT_UART_STOP_LEN ) +#define SET_UART_CLK_DIVID (0x1FFF< // standard integer definition +#include "ble_compiler.h" // inline functions + +/* + * CPU WORD SIZE + **************************************************************************************** + */ +/// ARM is a 32-bit CPU +#define CPU_WORD_SIZE 4 + +/* + * CPU Endianness + **************************************************************************************** + */ +/// ARM is little endian +#define CPU_LE 1 + +/* + * DEBUG configuration + **************************************************************************************** + */ +#if defined(CFG_DBG) +#define PLF_DEBUG 1 +#else //CFG_DBG +#define PLF_DEBUG 0 +#endif //CFG_DBG + + +/* + * NVDS + **************************************************************************************** + */ + +/// NVDS +#ifdef CFG_NVDS +#define PLF_NVDS 1 +#else // CFG_NVDS +#define PLF_NVDS 0 +#endif // CFG_NVDS + + +/* + * UART + **************************************************************************************** + */ + +/// UART +#define PLF_UART 0 + +/* + * DEFINES + **************************************************************************************** + */ + +/// Possible errors detected by FW +#define RESET_NO_ERROR 0x00000000 +#define RESET_MEM_ALLOC_FAIL 0xF2F2F2F2 + +/// Reset platform and stay in ROM +#define RESET_TO_ROM 0xA5A5A5A5 +/// Reset platform and reload FW +#define RESET_AND_LOAD_FW 0xC3C3C3C3 + +/// Exchange memory size limit +#define EM_SIZE_LIMIT 0x8000 +/* + * EXPORTED FUNCTION DECLARATION + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Compute size of SW stack used. + * + * This function is compute the maximum size stack used by SW. + * + * @return Size of stack used (in bytes) + **************************************************************************************** + */ +uint16_t get_stack_usage(void); + +/** + **************************************************************************************** + * @brief Re-boot FW. + * + * This function is used to re-boot the FW when error has been detected, it is the end of + * the current FW execution. + * After waiting transfers on UART to be finished, and storing the information that + * FW has re-booted by itself in a non-loaded area, the FW restart by branching at FW + * entry point. + * + * Note: when calling this function, the code after it will not be executed. + * + * @param[in] error Error detected by FW + **************************************************************************************** + */ +void platform_reset(uint32_t error); + +//#if PLF_DEBUG +/** + **************************************************************************************** + * @brief Print the assertion error reason and loop forever. + * + * @param condition C string containing the condition. + * @param file C string containing file where the assertion is located. + * @param line Line number in the file where the assertion is located. + **************************************************************************************** + */ +void assert_err(const char *condition, const char * file, int line); + +/** + **************************************************************************************** + * @brief Print the assertion error reason and loop forever. + * The parameter value that is causing the assertion will also be disclosed. + * + * @param param0 parameter value 0. + * @param param1 parameter value 1. + * @param file C string containing file where the assertion is located. + * @param line Line number in the file where the assertion is located. + **************************************************************************************** + */ +void assert_param(int param0, int param1, const char * file, int line); + +/** + **************************************************************************************** + * @brief Print the assertion warning reason. + * + * @param param0 parameter value 0. + * @param param1 parameter value 1. + * @param file C string containing file where the assertion is located. + * @param line Line number in the file where the assertion is located. + **************************************************************************************** + */ +void assert_warn(int param0, int param1, const char * file, int line); + + +/** + **************************************************************************************** + * @brief Dump data value into FW. + * + * @param data start pointer of the data. + * @param length data size to dump + **************************************************************************************** + */ +void dump_data(uint8_t* data, uint16_t length); +//#endif //PLF_DEBUG + + +/* + * ASSERTION CHECK + **************************************************************************************** + */ +#if PLF_DEBUG +/// Assertions showing a critical error that could require a full system reset +#ifdef ASSERT_ERR +#undef ASSERT_ERR +#endif +#define ASSERT_ERR(cond) ASSERT(cond) + +/// Assertions showing a critical error that could require a full system reset +#define ASSERT_INFO(cond, param0, param1) \ + do { \ + if (!(cond)) { \ + assert_param((int)param0, (int)param1, __MODULE__, __LINE__); \ + } \ + } while(0) + +/// Assertions showing a non-critical problem that has to be fixed by the SW +#define ASSERT_WARN(cond) ASSERT(cond) + +#define DUMP_DATA(data, length) \ + dump_data((uint8_t*)data, length) + +#else +/// Assertions showing a critical error that could require a full system reset +#ifdef ASSERT_ERR +#undef ASSERT_ERR +#endif +#define ASSERT_ERR(cond) + +/// Assertions showing a critical error that could require a full system reset +#define ASSERT_INFO(cond, param0, param1) + +#ifndef ASSERT_WARN +#undef ASSERT_WARN +#endif +/// Assertions showing a non-critical problem that has to be fixed by the SW +#define ASSERT_WARN(cond) + +/// DUMP data array present in the SW. +#define DUMP_DATA(data, length) +#endif //PLF_DEBUG + +#define FAST_MAIN_ENTRY __attribute__((section("sys_main_entry"))) +#define FAST_IRQ_ENTRY __attribute__((section("sys_irq_entry"))) +#define FAST_FIQ_ENTRY __attribute__((section("sys_fiq_entry"))) + + +/// Object allocated in shared memory - check linker script +#define __SHARED __attribute__ ((section("shram"))) + +// required to define GLOBAL_INT_** macros as inline assembly. This file is included after +// definition of ASSERT macros as they are used inside ll.h +#include "ll.h" // ll definitions +/// @} DRIVERS +#endif // _ARCH_H_ diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/arch/boot/boot.h b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/arch/boot/boot.h new file mode 100755 index 0000000..4b13ca3 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/arch/boot/boot.h @@ -0,0 +1,97 @@ +/** + **************************************************************************************** + * + * @file boot.h + * + * @brief This file contains the declarations of the boot related variables. + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef _BOOT_H_ +#define _BOOT_H_ + +#if 0 +/// Address of beginning of the CODE +extern char code_base; +#define CODE_BASE (&(code_base)) + +/// Address of the end of the CODE +extern char code_end; +#define CODE_END (&(code_end)) + +/// Length of the code +#define CODE_LENGTH ((CODE_END) - (CODE_BASE)) + +/// Address of beginning of the DATA +extern char data_base; +#define DATA_BASE (&(data_base)) + +/// Address of the end of the DATA +extern char data_end; +#define DATA_END (&(data_end)) + +/// Length of the DATA +#define DATA_LENGTH ((DATA_END) - (DATA_BASE)) + +/// Unloaded RAM area base address +extern char unloaded_area_start; +#define RAM_UNLOADED_BASE (&(unloaded_area_start)) + +/// Stack base address + + + +#endif + + + +#if 0 +/// Length of the code +extern const unsigned int Image$$ROM$$Length[]; +#define CODE_LENGTH ((uint32_t)Image$$ROM$$Length) + +/// Length of the RW data +extern const unsigned int Image$$RAM_DATA$$Length[]; +#define DATA_LENGTH ((uint32_t)Image$$RAM_DATA$$Length) + +/// Unloaded RAM area base address +extern const unsigned int Image$$RAM_UNLOADED$$Base[]; +#define RAM_UNLOADED_BASE ((uint32_t)Image$$RAM_UNLOADED$$Base) + +/// Stack base address and len of UNUSED +extern const unsigned int boot_stack_base_UNUSED; +#define STACK_BASE_UNUSED ((uint32_t)boot_stack_base_UNUSED) +extern const unsigned int boot_stack_len_UNUSED; +#define STACK_LEN_UNUSED ((uint32_t)boot_stack_len_UNUSED) + +/// Stack base address and len of SVC +extern const unsigned int boot_stack_base_SVC ; +#define STACK_BASE_SVC ((uint32_t)boot_stack_base_SVC) +extern const unsigned int boot_stack_len_SVC; +#define STACK_LEN_SVC ((uint32_t)boot_stack_len_SVC) + +/// Stack base address and len of IRQ +extern const unsigned int boot_stack_base_IRQ; +#define STACK_BASE_IRQ ((uint32_t)boot_stack_base_IRQ) +extern const unsigned int boot_stack_len_IRQ; +#define STACK_LEN_IRQ ((uint32_t)boot_stack_len_IRQ) + +/// Stack base address and len of FIQ +extern const unsigned int boot_stack_base_FIQ; +#define STACK_BASE_FIQ ((uint32_t)boot_stack_base_FIQ) +extern const unsigned int boot_stack_len_FIQ; +#define STACK_LEN_FIQ ((uint32_t)boot_stack_len_FIQ) + +#define BOOT_PATTERN_UNUSED 0xAAAAAAAA // Pattern to fill UNUSED stack +#define BOOT_PATTERN_SVC 0xBBBBBBBB // Pattern to fill SVC stack +#define BOOT_PATTERN_IRQ 0xCCCCCCCC // Pattern to fill IRQ stack +#define BOOT_PATTERN_FIQ 0xDDDDDDDD // Pattern to fill FIQ stack + +#endif + + +#endif // _BOOT_H_ diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/arch/compiler/ble_compiler.h b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/arch/compiler/ble_compiler.h new file mode 100755 index 0000000..9d25b8a --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/arch/compiler/ble_compiler.h @@ -0,0 +1,67 @@ +/** + **************************************************************************************** + * + * @file gnuarm/compiler.h + * + * @brief Definitions of compiler specific directives. + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef _BLE_COMPILER_H_ +#define _BLE_COMPILER_H_ + + +/// define the static keyword for this compiler +#define __STATIC static + +/// define the force inlining attribute for this compiler +//#define __INLINE static __attribute__((__always_inline__)) inline + +/// define the force inlining attribute for this compiler +#define __INLINE static inline +#define inline + +/// define the IRQ handler attribute for this compiler +//#define __IRQ __attribute__((__interrupt__("IRQ"))) +#define __IRQ __irq + +/// define the BLE IRQ handler attribute for this compiler +#define __BTIRQ + +/// define the BLE IRQ handler attribute for this compiler +#define __BLEIRQ + +/// define the FIQ handler attribute for this compiler +//#define __FIQ __attribute__((__interrupt__("FIQ"))) +#define __FIQ __irq +/// define size of an empty array (used to declare structure with an array size not defined) +#define __ARRAY_EMPTY + +/// Function returns struct in registers (4 in rvds, var with gnuarm). +/// With Gnuarm, feature depends on command line options and +/// impacts ALL functions returning 2-words max structs +/// (check -freg-struct-return and -mabi=xxx) +#define __BLEVIR + +#define __RAM_ECDH + +/// function has no side effect and return depends only on arguments +#define __BLEPURE __attribute__((const)) + +/// Align instantiated lvalue or struct member on 4 bytes +#define __ALIGN4 __attribute__((aligned(4))) + +/// __MODULE__ comes from the RVDS compiler that supports it +//#define __MODULE__ __BASE_FILE__ + +/// Pack a structure field +#define __BLEPACKED __attribute__ ((__packed__)) + +/// Put a variable in a memory maintained during deep sleep +#define __LOWPOWER_SAVED + +#endif // _COMPILER_H_ diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/arch/ll/ll.h b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/arch/ll/ll.h new file mode 100755 index 0000000..bf888c6 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/arch/ll/ll.h @@ -0,0 +1,87 @@ +/** + **************************************************************************************** + * + * @file ll.h + * + * @brief Declaration of low level functions. + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef LL_H_ +#define LL_H_ + + + +#include + + +#include "ble_compiler.h" + +#define KEIL_INTRINSICS_INTERRUPT + + +/** @brief Enable interrupts globally in the system. + * This macro must be used when the initialization phase is over and the interrupts + * can start being handled by the system. + */ + +/* keil Compiler intrinsics for controlling IRQ and FIQ interrupts +*/ + + +#define GLOBAL_INT_START(); \ +do { \ + portENABLE_FIQ(); \ + portENABLE_IRQ(); \ +} while(0); + +/** @brief Disable interrupts globally in the system. + * This macro must be used when the system wants to disable all the interrupt + * it could handle. + */ + +#define GLOBAL_INT_STOP(); \ +do { \ + portDISABLE_FIQ(); \ + portDISABLE_IRQ(); \ +} while(0); + +/* * @brief Disable interrupts globally in the system. + * This macro must be used in conjunction with the @ref GLOBAL_INT_RESTORE macro since this + * last one will close the brace that the current macro opens. This means that both + * macros must be located at the same scope level. + */ +#define GLOBAL_INT_DIS(); \ +do { \ + uint32_t fiq_tmp; \ + uint32_t irq_tmp; \ + fiq_tmp = portDISABLE_FIQ();\ + irq_tmp = portDISABLE_IRQ(); + +#define GLOBAL_INT_RES(); \ + if(!fiq_tmp) \ + { \ + portENABLE_FIQ(); \ + } \ + if(!irq_tmp) \ + { \ + portENABLE_IRQ(); \ + } \ +} while(0) ; + + +/** @brief Invoke the wait for interrupt procedure of the processor. + * + * @warning It is suggested that this macro is called while the interrupts are disabled + * to have performed the checks necessary to decide to move to sleep mode. + * + */ + + +#endif // LL_H_ + + diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/arch/plf.h b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/arch/plf.h new file mode 100755 index 0000000..f218b16 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/arch/plf.h @@ -0,0 +1,40 @@ +/** + **************************************************************************************** + * + * @file plf.h + * + * @brief This file contains the definitions of the macros and functions that are + * platform dependent. The implementation of those is implemented in the + * appropriate platform directory. + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ +#ifndef _PLF_H_ +#define _PLF_H_ + +/** + **************************************************************************************** + * @defgroup PLF + * @ingroup DRIVERS + * + * @brief Platform register driver + * + * @{ + * + **************************************************************************************** + */ + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +#define plf_read_rf_board_id() 0 +#define plf_rf_switch() 1 + +/// @} PLF + +#endif // _PLF_H_ diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/bim/bim_app.c b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/bim/bim_app.c new file mode 100755 index 0000000..6b8b4cf --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/bim/bim_app.c @@ -0,0 +1,43 @@ + + +#include +#include "bim_com.h" +#include "bim_updataImage.h" +#include "bim_application.h" +#include "BK3435_reg.h" +#include "bim_uart.h" + +#define Uart_Write_Byte(v) (REG_APB3_UART_PORT=v) + +typedef void (*FUNCPTR)(void); + +void delay(uint32_t t) +{ + for(int i = 1000;i> 0;i--) + { + for(int j = 0;j< t;j++) + { + ; + } + } +} + +void bim_main(void) +{ + int32_t main_point = SEC_IMAGE_RUN_CADDR; + + udi_init_bim_env(ICU_CLK_16M); + + flash_wr_protect_none(); + + if(1 == udi_select_sec()) + { + udi_init_bim_env(ICU_CLK_16M); + (*(FUNCPTR)main_point)(); + } + else + { + } +} +// eof + diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/bim/bim_app.h b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/bim/bim_app.h new file mode 100755 index 0000000..e69de29 diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/bim/bim_com.c b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/bim/bim_com.c new file mode 100755 index 0000000..866d6f3 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/bim/bim_com.c @@ -0,0 +1,792 @@ + +#include +#include +#include "bim_com.h" +#include "BK3435_reg.h" +#include "bim_uart.h" + + + +#define GD_FLASH_1 0XC84013 +#define MX_FLASH_1 0XC22314 +#define XTX_FLASH_1 0X1C3113 + +#define BY25Q80 0xe04014 +#define PN25f04 0xe04013 +#define MX_FLASH_4M 0XC22313 + +#define FLASH_LINE_1 1 +#define FLASH_LINE_2 2 +#define FLASH_LINE_4 4 + +#define DEFAULT_LINE_MODE FLASH_LINE_4 + +uint32_t flash_mid = 0; + +void *udi_memcpy(void *dest, const void *src, size_t count) +{ + char *tmp = dest; + const char *s = src; + while (count--) + { + *tmp++ = *s++; + } + return dest; +} + +void * udi_memset32(void * dest, uint32_t value, size_t size) +{ + uint32_t *_u8_dest = (uint32_t *)dest; + uint32_t *_u8_end = (uint32_t *)dest + size * 4; + while (_u8_dest < _u8_end) + { + *_u8_dest++ = value; + } + return dest; +} + + +void udi_delay_us(uint32 num) +{ + volatile uint32_t i, j; + for(i = 0; i < num; i++) + for(j = 0; j < 3; j++) + { + ; + } +} + +void udi_delay_ms(unsigned int tt) +{ + volatile unsigned int i, j; + while(tt--) + { + for (j = 0; j < 1000/10; j++) + { + for (i = 0; i < 12; i++) + { + ; + } + } + } +} + + +static void udi_icu_init(uint8_t clk) +{ + + if(ICU_CLK_64M == clk) + { + //REG_AHB0_ICU_LPO_CLK_ON |= (0x01 << 4); + REG_AHB0_ICU_FLASH &= ~(0xff << 16); + REG_AHB0_ICU_FLASH |= (0x15 << 16); + REG_AHB0_ICU_CPU_STATUS = 0x611; // spi vol + + + REG_AHB0_ICU_DIGITAL_PWD = REG_AHB0_ICU_DIGITAL_PWD & (~0X02); + + REG_AHB0_ICU_CORECLKCON = 0X00; //clk div 0 + + REG_AHB0_ICU_CLKSRCSEL = 0X000005B7; //usr PLL CLK SELT 64M + + + REG_AHB0_ICU_ANA_CTL |= (0X01 << 6); + } + else + { + //REG_AHB0_ICU_LPO_CLK_ON |= (0x01 << 4); + REG_AHB0_ICU_FLASH &= ~(0xff << 16); + REG_AHB0_ICU_FLASH |= (0x15 << 16); + REG_AHB0_ICU_CPU_STATUS = 0x611; // spi vol hh + + REG_AHB0_ICU_DIGITAL_PWD = REG_AHB0_ICU_DIGITAL_PWD & (~0X02); + + REG_AHB0_ICU_CORECLKCON = 0X00; + + REG_AHB0_ICU_CLKSRCSEL = 0X000001B5; //usr 16m + + REG_AHB0_ICU_ANA_CTL &= ~(0X01 << 6); + + } + +} + + +static void udi_flash_init(uint8_t clk) +{ + + flash_mid = fflash_get_id(); + + if(ICU_CLK_64M == clk) + { + flash_clk_conf(0,0,0); //USE 64M + + }else + { + flash_clk_conf(1,1,0); //USE 16M + } + + //UART_PRINTF("flash_mid = 0x%x\r\n",flash_mid); +// flash_wr_protect_none(); +} + + + +void udi_init_bim_env(uint8_t clk) +{ + if(ICU_CLK_64M == clk) + { + udi_icu_init(ICU_CLK_64M); + udi_flash_init(ICU_CLK_64M); + + }else + { + udi_icu_init(ICU_CLK_16M); + udi_flash_init(ICU_CLK_16M); + } + +} +void flash_clk_conf(uint8_t clk_sel,uint8_t clk_src,uint8_t div) +{ + uint32_t cfg; + cfg = REG_FLASH_CONF; + //UART_PRINTF("read_cfg = 0x%x\r\n",cfg); + cfg &= ~(0x0f << BIT_FLASH_CLK_CONF); + + cfg |= ((clk_sel << 0x03)| (clk_src << 0x02) | ( div << 0x0)); + //UART_PRINTF("write_cfg = 0x%x\r\n",cfg); + REG_FLASH_CONF = cfg; +} + +uint32 fflash_get_id(void) +{ + REG_FLASH_OPERATE_SW = ( (FLASH_OPCODE_RDID << BIT_OP_TYPE_SW) + | (0x1 << BIT_OP_SW) + | (0x1 << BIT_WP_VALUE)); // make WP equal 1 not protect SRP + while(REG_FLASH_OPERATE_SW & 0x80000000) + { + ; + } + udi_delay_ms(50); + + return REG_FLASH_RDID_DATA_FLASH >> 0 ; + // return REG_FLASH_RDID_DATA_FLASH >> 16 ; +} + +void fflash_wr_enable( void ) +{ + REG_FLASH_OPERATE_SW = ((FLASH_OPCODE_WREN << BIT_OP_TYPE_SW) + | (0x1 << BIT_OP_SW) + | (0x1 << BIT_WP_VALUE)); + while(REG_FLASH_OPERATE_SW & 0x80000000) + { + ; + } +} + +void fflash_wr_disable( void ) +{ + REG_FLASH_OPERATE_SW = ((FLASH_OPCODE_WRDI << BIT_OP_TYPE_SW) + | (0x1 << BIT_OP_SW) + | (0x1 << BIT_WP_VALUE)); + while(REG_FLASH_OPERATE_SW & 0x80000000) + { + ; + } +} + +void fflash_wr_sr( uint8_t bytes, uint16_t val ) +{ + switch(flash_mid) + { + case MX_FLASH_4M: + case MX_FLASH_1: //MG xx + REG_FLASH_CONF &= 0xffdf0fff; + break; + case XTX_FLASH_1: //XTX xx + REG_FLASH_CONF &= 0xffff0fff; + break; + case GD_FLASH_1: //QD xx , + case BY25Q80: + case PN25f04: + default: + REG_FLASH_CONF &= 0xfefe0fff; + break; + } + REG_FLASH_CONF |= (val << BIT_WRSR_DATA)|SET_FWREN_FLASH_CPU; + while(REG_FLASH_OPERATE_SW & 0x80000000) + { + ; + } + if( bytes == 1 ) + { + REG_FLASH_OPERATE_SW = ((FLASH_OPCODE_WRSR << BIT_OP_TYPE_SW) + | (0x1<< BIT_OP_SW) + | (0x1<< BIT_WP_VALUE)); + + } + else if(bytes == 2 ) + { + REG_FLASH_OPERATE_SW = ((FLASH_OPCODE_WRSR2 << BIT_OP_TYPE_SW) + | (0x1<< BIT_OP_SW) + | (0x1<< BIT_WP_VALUE)); + } + + while(REG_FLASH_OPERATE_SW & 0x80000000); +} + + + +void fflash_wr_protect_16k( void ) +{ + switch(flash_mid) + { + case MX_FLASH_4M: + case MX_FLASH_1: //MG xx + fflash_wr_sr( 2, 0x0804 ); + break; + case XTX_FLASH_1: //XTX xx + fflash_wr_sr( 1, 0x24 ); + break; + case GD_FLASH_1: //QD xx , + case BY25Q80: + case PN25f04: + default: + fflash_wr_sr( 2, 0x0024 );// 64K⣬16K + break; + } +} + +void flash_wr_protect_none( void) +{ + switch(flash_mid) + { + case MX_FLASH_4M: + case MX_FLASH_1: //MG xx + fflash_wr_sr( 2, 0x0000 ); + break; + case XTX_FLASH_1: //XTX xx + fflash_wr_sr( 1, 0x00 ); + break; + case GD_FLASH_1: //QD xx , + case BY25Q80: + case PN25f04: + default: + fflash_wr_sr( 2, 0X0000 ); + break; + } +} + +void fflash_wp_ALL( void ) +{ + switch(flash_mid) + { + case MX_FLASH_4M: + case MX_FLASH_1: //MG xx + fflash_wr_sr( 2, 0x003c ); + break; + case XTX_FLASH_1: //XTX xx + fflash_wr_sr( 1, 0x3C ); + break; + case GD_FLASH_1: //QD xx , + case BY25Q80: + case PN25f04: + default: + fflash_wr_sr( 2, 0x0014 ); + break; + } +} + + +void set_flash_qwfr(void) +{ + //ֻ MCU, SRд REG_FLASH_OPERATE_SW + uint32_t temp0,mod_sel; + temp0 = REG_FLASH_CONF; + mod_sel = temp0 & (0xC << BIT_MODE_SEL); + mod_sel |= (0x2 << BIT_MODE_SEL); + while(REG_FLASH_OPERATE_SW & 0x80000000); + REG_FLASH_CONF = ( (temp0 & SET_FLASH_CLK_CONF) + | mod_sel //QWFRMODE use QWFR to fetch data. For GigaDevice (GD) Flash + | (temp0 & SET_FWREN_FLASH_CPU) + | (temp0 & SET_WRSR_DATA) + | (temp0 & SET_CRC_EN)); +} + +void clr_flash_qwfr(void) +{ + uint32_t temp0,mod_sel; + + temp0 = REG_FLASH_CONF; + while(REG_FLASH_OPERATE_SW & 0x80000000){;} + mod_sel = temp0 & (0xC << BIT_MODE_SEL); //??3ymode_sel?D + mod_sel |= (0x1 << BIT_MODE_SEL); + REG_FLASH_CONF = ( (temp0 & SET_FLASH_CLK_CONF) + | mod_sel + | (temp0 & SET_FWREN_FLASH_CPU) + | (temp0 & SET_WRSR_DATA) + | (temp0 & SET_CRC_EN)); + //reset flash + temp0 = REG_FLASH_OPERATE_SW; + if(flash_mid == XTX_FLASH_1) + { + REG_FLASH_OPERATE_SW = ( (0<< BIT_ADDRESS_SW) + | (FLASH_OPCODE_CRMR << BIT_OP_TYPE_SW) + | (0x1 << BIT_OP_SW) + | (temp0 & SET_WP_VALUE)); + } + else + { + REG_FLASH_OPERATE_SW = ( (0<< BIT_ADDRESS_SW) + | (FLASH_OPCODE_CRMR2 << BIT_OP_TYPE_SW) + | (0x1 << BIT_OP_SW) + | (temp0 & SET_WP_VALUE)); + } + + while(REG_FLASH_OPERATE_SW & 0x80000000); +} + + + +void fflash_set_line_method(uint8 mode) +{ + +//XTX_FLASH_1 û QEҪ EQPI(38h) CMD +//MX_FLASH_1 MX_FLASH_4MXTX_FLASH_1Ч +//Ҫд XTX_FLASH_1 λãΪqe״̬ + return ; +#if 0 + switch(mode) + { + case FLASH_LINE_1: + clr_flash_qwfr(); + break; + case FLASH_LINE_2: + clr_flash_qwfr(); + REG_FLASH_CONF &= (~(7< 32 * (j + 1)) + { + udi_memcpy(&buffer[k], buf, 32); + } + else + { + udi_memcpy(&buffer[k], buf, len - k); + } + k += 32; + } +} + +void fflash_rd_data(uint8_t *buffer, uint32_t address, uint32_t len) +{ + uint32_t pre_address; + uint32_t post_address; + uint32_t pre_len; + uint32_t post_len; + uint32_t page0; + uint32_t page1; + page0 = address &(~FLASH_PAGE_MASK); + page1 = (address + len) &(~FLASH_PAGE_MASK); + if(page0 != page1) + { + pre_address = address; + pre_len = page1 - address; + fflash_rd_data_in_page(buffer, pre_address, pre_len); + post_address = page1; + post_len = address + len - page1; + fflash_rd_data_in_page((buffer + pre_len), post_address, post_len); + } + else + { + fflash_rd_data_in_page(buffer, address, len); + } +} +void fflash_wr_data_in_page (uint8 *buffer, uint32 address, uint32 len) +{ + uint32_t i, j, k, reg_value; + uint32_t addr = address; + uint32_t buf[8]; + k = 0; + if(0 == len) + { + + return; + } + fflash_unlock(); + while(REG_FLASH_OPERATE_SW & 0x80000000) + { + ; + } + for(j = 0; j < ((len - 1) / 32 + 1); j++) + { + if(len > 32 * (j + 1)) + { + udi_memcpy(buf, &buffer[k], 32); + } + else + { + for(i=0;i<8;i++) + buf[i]=0xffffffff; + udi_memcpy(buf, &buffer[k], len-k); + } + + k += 32; + for (i = 0; i < 8; i++) + { + REG_FLASH_DATA_SW_FLASH = buf[i]; + } + while(REG_FLASH_OPERATE_SW & 0x80000000) + { + ; + } + + reg_value = REG_FLASH_OPERATE_SW; + REG_FLASH_OPERATE_SW = ( (addr << BIT_ADDRESS_SW) + | (FLASH_OPCODE_PP << BIT_OP_TYPE_SW) + | (0x1 << BIT_OP_SW) + | (0x1 << BIT_WP_VALUE) // make WP equal 1 not protect SRP + | (reg_value & SET_WP_VALUE)); + while(REG_FLASH_OPERATE_SW & 0x80000000) + { + ; + } + + addr += 32; + } + fflash_lock(); +} +void fflash_wr_data (uint8_t *buffer, uint32_t address, uint32_t len) +{ + uint32_t pre_address; + uint32_t post_address; + uint32_t pre_len; + uint32_t post_len; + uint32_t page0; + uint32_t page1; + page0 = address &(~FLASH_PAGE_MASK); + page1 = (address + len) &(~FLASH_PAGE_MASK); + if(page0 != page1) + { + pre_address = address; + pre_len = page1 - address; + fflash_wr_data_in_page(buffer, pre_address, pre_len); + + post_address = page1; + post_len = address + len - page1; + fflash_wr_data_in_page((buffer + pre_len), post_address, post_len); + + } + else + { + fflash_wr_data_in_page(buffer, address, len); + + } +} + + +void udi_exchange_fdata_to_adjoining_next_sector(uint32_t data_addr, uint32_t len, uint32_t wr_point_inpage) +{ + /* assume: the space, from address(current sector) to next sector, can be operated */ + uint8_t tmp[UPDATE_CHUNK_SIZE]; + int next_sector_addr; + int rd_addr; + int wr_addr; + int total_cnt; + int sub_cnt; + int wr_point = wr_point_inpage; + if((len > FLASH_ERASE_SECTOR_SIZE) + || (0 == len)) + { + return; + } + next_sector_addr = (data_addr & (~FLASH_ERASE_SECTOR_SIZE_MASK)) + FLASH_ERASE_SECTOR_SIZE; + fflash_erase_one_sector(next_sector_addr); + total_cnt = len; + rd_addr = data_addr; + wr_point = wr_point & FLASH_ERASE_SECTOR_SIZE_MASK; + wr_addr = next_sector_addr + wr_point; + while(total_cnt > 0) + { + sub_cnt = MIN(UPDATE_CHUNK_SIZE, total_cnt); + fflash_rd_data(tmp, rd_addr, sub_cnt); + fflash_wr_data(tmp, wr_addr, sub_cnt); + total_cnt -= sub_cnt; + rd_addr += sub_cnt; + wr_addr += sub_cnt; + } +} +void udi_exchange_fdata_to_adjoining_previous_sector(uint32_t data_addr, uint32_t len, uint32_t wr_point_inpage) +{ + /* assume: the space, from previous sector to address+len, can be operated */ + uint8_t tmp[UPDATE_CHUNK_SIZE]; + uint32_t pre_sector_addr; + uint32_t rd_addr; + uint32_t wr_addr; + uint32_t total_cnt; + uint32_t sub_cnt; + uint32_t wr_point = wr_point_inpage; + if((len > FLASH_ERASE_SECTOR_SIZE) + || (0 == len)) + { + return; + } + pre_sector_addr = (data_addr & (~FLASH_ERASE_SECTOR_SIZE_MASK)) - (uint32_t)FLASH_ERASE_SECTOR_SIZE; + fflash_erase_one_sector(pre_sector_addr); + total_cnt = len; + rd_addr = data_addr; + wr_point = wr_point & FLASH_ERASE_SECTOR_SIZE_MASK; + wr_addr = pre_sector_addr + wr_point; + while(total_cnt > 0) + { + sub_cnt = MIN(UPDATE_CHUNK_SIZE, total_cnt); + fflash_rd_data(tmp, rd_addr, sub_cnt); + fflash_wr_data(tmp, wr_addr, sub_cnt); + + total_cnt -= sub_cnt; + rd_addr += sub_cnt; + wr_addr += sub_cnt; + } +} + +uint32_t udi_erase_section(uint32_t address, uint32_t len) +{ + /* assume: the worst span is four sectors*/ + int first_len; + int first_addr; + int last_len; + int last_addr; + int mid_addr; + int erase_addr; + int erase_len; + int wr_point; + first_len = address & FLASH_ERASE_SECTOR_SIZE_MASK; + first_addr = address & (~FLASH_ERASE_SECTOR_SIZE_MASK); + mid_addr = first_addr + FLASH_ERASE_SECTOR_SIZE; + wr_point = 0; + if(first_len) + { + udi_exchange_fdata_to_adjoining_next_sector(first_addr, first_len, wr_point); + udi_exchange_fdata_to_adjoining_previous_sector(mid_addr, first_len, wr_point); + erase_addr = mid_addr; + erase_len = len - (FLASH_ERASE_SECTOR_SIZE - first_len); + + } + else + { + erase_addr = address; + erase_len = len; + } + do + { + int i; + int erase_whole_sector_cnt; + erase_whole_sector_cnt = erase_len >> FLASH_ERASE_SECTOR_SIZE_RSL_BIT_CNT; + for(i = 0; i < erase_whole_sector_cnt; i ++) + { + fflash_erase_one_sector(erase_addr); + erase_addr += FLASH_ERASE_SECTOR_SIZE; + erase_len -= FLASH_ERASE_SECTOR_SIZE; + } + } + while(0); + do + { + if(0 == erase_len) + { + break; + } + last_len = FLASH_ERASE_SECTOR_SIZE - erase_len; + last_addr = erase_addr + erase_len; + wr_point = 0; + udi_exchange_fdata_to_adjoining_previous_sector(last_addr, last_len, wr_point); + last_addr = erase_addr - FLASH_ERASE_SECTOR_SIZE; + wr_point = erase_len; + udi_exchange_fdata_to_adjoining_next_sector(last_addr, last_len, wr_point); + fflash_erase_one_sector(last_addr); + } + while(0); + return len; +} + + + + +void udi_wdt_disable(void) +{ + REG_AHB0_ICU_WDTCLKCON = 0x1 ; // Step1. WDT clock enable + REG_APB0_WDT_CFG = 0x005A0000;// Step3. Feed dog. Write WDT key: 0x5A firstly and 0xA5 secondly. + REG_APB0_WDT_CFG = 0x00A50000; +} +void udi_wdt_enable(uint16 wdt_cnt) +{ + //the timer is 48uS @1 CLK + //0xffff: 3s + REG_AHB0_ICU_WDTCLKCON = 0x0 ; // Step1. WDT clock enable,16M + REG_APB0_WDT_CFG = wdt_cnt; // Step2. Set WDT period=0xFF + // Do two things together: 1. Set WDT period. 2. Write WDT key to feed dog. + // Write WDT key: 0x5A firstly and 0xA5 secondly. + REG_APB0_WDT_CFG = (0x5A<<16) + wdt_cnt; + REG_APB0_WDT_CFG = (0xA5<<16) + wdt_cnt; +} + + + +#define MAX_SIZE 100 + +#define TEST_FLASH_ADDRESS 0x44000 + +void flash_rw_test(void) +{ + + //UART_PRINTF("flash_rw_test bim\r\n"); + uint16_t i; + uint8_t data[MAX_SIZE]; + uint8_t data2[MAX_SIZE]; + + for(i=0; i // standard integer functions +#include "BK3435_reg.h" +//#include "icu.h" +/** + **************************************************************************************** + * @addtogroup FLASH + * @ingroup DRIVERS + * + * @brief Flash memory driver + * + * @{ + **************************************************************************************** + */ + +/* + * DEFINES + **************************************************************************************** + */ +#if (MCU_DEFAULT_CLK == MCU_CLK_16M) +#define FLASH_CLK_16M +#else +#define FLASH_CLK_64M +#endif + +///Flash type code used to select the correct erasing and programming algorithm +#define FLASH_TYPE_UNKNOWN 0 +#define FLASH_SPACE_TYPE_MAIN 0x3435 +#define FLASH_TYPE_EMBEN_BK3435 FLASH_SPACE_TYPE_MAIN + + +///Base address of Flash on system bus +#define FLASH_MAIN_BASE_ADDR 0x00000000 + + + +#define FLASH_MAIN_SIZE 0x00040000 + +/// Common for EMBED BEKEN FLASH Family + +#define FLASH_SECT_SIZE2 0x00001000 // 4 KByte +#define FLASH_BOUNDARY256B 0x00000100 // 256 Byte + +#define FLASH_PAGE_SIZE (256) +#define FLASH_PAGE_MASK (FLASH_PAGE_SIZE - 1) +#define FLASH_ERASE_SECTOR_SIZE_RSL_BIT_CNT (12) +#define FLASH_ERASE_SECTOR_SIZE (4096) +#define FLASH_ERASE_SECTOR_SIZE_MASK (FLASH_ERASE_SECTOR_SIZE - 1) +#define UPDATE_CHUNK_SIZE (32) + +#define MAX(x, y) (((x) > (y)) ? (x) : (y)) +#define MIN(x, y) (((x) < (y)) ? (x) : (y)) +#define max(x, y) (((x) > (y)) ? (x) : (y)) +#define min(x, y) (((x) < (y)) ? (x) : (y)) + +/// flash operation command type(decimal) +typedef enum { + FLASH_OPCODE_WREN = 1, + FLASH_OPCODE_WRDI = 2, + FLASH_OPCODE_RDSR = 3, + FLASH_OPCODE_WRSR = 4, + FLASH_OPCODE_READ = 5, + FLASH_OPCODE_RDSR2 = 6, + FLASH_OPCODE_WRSR2 = 7, + FLASH_OPCODE_PP = 12, + FLASH_OPCODE_SE = 13, + FLASH_OPCODE_BE1 = 14, + FLASH_OPCODE_BE2 = 15, + FLASH_OPCODE_CE = 16, + FLASH_OPCODE_DP = 17, + FLASH_OPCODE_RFDP = 18, + FLASH_OPCODE_RDID = 20, + FLASH_OPCODE_HPM = 21, + FLASH_OPCODE_CRMR = 22, + FLASH_OPCODE_CRMR2 = 23, +} FLASH_OPCODE; + + + +enum +{ + ICU_CLK_16M, + ICU_CLK_64M, + +}; +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Initialize flash driver. + **************************************************************************************** + */ + +uint32 fflash_get_id(void); +void fflash_rd_data(uint8_t *buffer, uint32_t address, uint32_t len); +void fflash_wr_data (uint8_t *buffer, uint32_t address, uint32_t len); +uint32_t udi_erase_section(uint32_t address, uint32_t len); +void fflash_erase_one_sector(uint32_t address); +void fflash_erase_half_block(uint32_t address); +void fflash_erase_one_block(uint32_t address); + +void flash_wr_protect_none( void); + +void fflash_wr_protect_16k( void ); +void fflash_wp_ALL( void ); +void flash_clk_conf(uint8_t clk_sel,uint8_t clk_src,uint8_t div); + + +void udi_wdt_enable(uint16_t wdt_cnt); + +void udi_init_bim_env(uint8_t clk); +void flash_rw_test(void); + +/// @} FLASH + +#endif // FLASH_H_ diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/bim/bim_intc.c b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/bim/bim_intc.c new file mode 100755 index 0000000..97d4915 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/bim/bim_intc.c @@ -0,0 +1,66 @@ +/** + **************************************************************************************** + * + * @file bim_intc.c + * + * @brief Definition of the Interrupt Controller (INTCTRL) API. + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#include "bim_intc.h" + + +typedef void (*FUNCPTR_T)(void); + + +void Undefined_Exception(void) +{ + while(1) + { + //UART_PRINTF("%s \r\n",__func__); + //uart_putchar("Undefined_Exception\r\n"); + } + +} +void SoftwareInterrupt_Exception(void) +{ + while(1) + { + //UART_PRINTF("%s \r\n",__func__); + //uart_putchar("SoftwareInterrupt_Exception\r\n"); + } + +} +void PrefetchAbort_Exception(void) +{ + while(1) + { + //UART_PRINTF("%s \r\n",__func__); + //uart_putchar("PrefetchAbort_Exception\r\n"); + } + +} +void DataAbort_Exception(void) +{ + while(1) + { + //UART_PRINTF("%s \r\n",__func__); + //uart_putchar("DataAbort_Exception\r\n"); + } + +} + +void Reserved_Exception(void) +{ + while(1) + { + //UART_PRINTF("%s \r\n",__func__); + //uart_putchar("Reserved_Exception\r\n"); + } + +} + diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/bim/bim_intc.h b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/bim/bim_intc.h new file mode 100755 index 0000000..52fdd62 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/bim/bim_intc.h @@ -0,0 +1,15 @@ +/** + **************************************************************************************** + * + * @file bim_intc.c + * + * @brief Definition of the Interrupt Controller (INTCTRL) API. + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ +#include +#include "ble_compiler.h" +#include "BK3435_reg.h" diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/bim/bim_uart.c b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/bim/bim_uart.c new file mode 100755 index 0000000..3ec303c --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/bim/bim_uart.c @@ -0,0 +1,342 @@ +/** + **************************************************************************************** + * + * @file bim_uart.c + * + * @brief UART driver + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @addtogroup UART + * @{ + **************************************************************************************** + */ +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include // standard definition +#include "timer.h" // timer definition +#include "bim_uart.h" // uart definition +#include "BK3435_reg.h" +//#include "reg_uart.h" // uart register + + +/* + * DEFINES + ***************************************************************************************** + */ + +/// Max baudrate supported by this UART (in bps) +#define UART_BAUD_MAX 3500000 +/// Min baudrate supported by this UART (in bps) +#define UART_BAUD_MIN 9600 + +/// Duration of 1 byte transfer over UART (10 bits) in us (for 921600 default baudrate) +#define UART_CHAR_DURATION 11 + +/* + * ENUMERATION DEFINITIONS + ***************************************************************************************** + */ + + /* + * common.c + * + * Created on: 2013-5-7 + * Author: pujie + */ + +#include +#include +#include "BK3435_reg.h" +#include "bim_uart.h" + + + + + + +#define Uart_Write_Byte(v) (REG_APB3_UART_PORT=v) + +#define UART_TX_FIFO_COUNT (REG_APB3_UART_FIFO_STAT&0xff) +#define UART_RX_FIFO_COUNT ((REG_APB3_UART_FIFO_STAT>>8)&0xff) +#define UART_TX_FIFO_FULL (REG_APB3_UART_FIFO_STAT&0x00010000) +#define UART_TX_FIFO_EMPTY (REG_APB3_UART_FIFO_STAT&0x00020000) +#define UART_RX_FIFO_FULL (REG_APB3_UART_FIFO_STAT&0x00040000) +#define UART_RX_FIFO_EMPTY (REG_APB3_UART_FIFO_STAT&0x00080000) +#define UART_TX_WRITE_READY (REG_APB3_UART_FIFO_STAT&0x00100000) +#define UART_RX_READ_READY (REG_APB3_UART_FIFO_STAT&0x00200000) +#define bit_UART_TXFIFO_NEED_WRITE 0x01 +#define bit_UART_RXFIFO_NEED_READ 0x02 +#define bit_UART_RXFIFO_OVER_FLOW 0x04 +#define bit_UART_RX_PARITY_ERROR 0x08 +#define bit_UART_RX_STOP_ERROR 0x10 +#define bit_UART_TX_PACKET_END 0x20 +#define bit_UART_RX_PACKET_END 0x40 +#define bit_UART_RXD_WAKEUP_DETECT 0x80 + + + + +#define uart_tx_en 0x1 // 0: Disable TX, 1: Enable TX +#define uart_rx_en 0x1 // 0: Disable RX, 1: Enable RX +#define irda_mode 0x0 // 0: UART MODE, 1: IRDA MODE +#define data_len 0x3 // 0: 5 bits, 1: 6 bits, 2: 7 bits, 3: 8 bits +#define parity_en 0x1 // 0: NO Parity, 1: Enable Parity +#define parity_mode 0x1 // 0: Odd Check, 1: Even Check +#define stop_bits 0x0 // 0: 1 stop-bit, 1: 2 stop-bit +#define uart_clks 16000000 // UART's Main-Freq, 26M +#define baud_rate 115200 // UART's Baud-Rate, 1M + + + + +unsigned char uart_rx_buf[UART0_RX_FIFO_MAX_COUNT]; +unsigned char uart_tx_buf[UART0_TX_FIFO_MAX_COUNT]; +volatile bool uart_rx_done = 0; +volatile unsigned long uart_rx_index = 0; +uint8_t cur_read_buf_idx = 0; +uint8_t Read_Uart_Buf(void) +{ + return uart_rx_buf[cur_read_buf_idx++]; +} + +uint8_t Uart_Read_Byte(void) +{ + return (REG_APB3_UART_PORT&0xff); +} + +#define UART_READ_BYTE() (REG_APB3_UART_PORT&0xff) + + +char uart_buff[128]; +int uart_putchar(char * st) +{ + uint8_t num = 0; + + while (*st) + { + if(UART_TX_WRITE_READY) + { + REG_APB3_UART_PORT = *st; + st++; + num++; + } + } + + return num; +} + +int uart_printf(const char *fmt,...) +{ + int n; + va_list ap; + va_start(ap, fmt); + n=vsprintf(uart_buff, fmt, ap); + va_end(ap); + uart_putchar(uart_buff); + if(n > sizeof(uart_buff)) + { + uart_putchar("buff full \r\n"); + } + + return n; +} +int uart_printf_null(const char *fmt,...) +{ + return 0; +} + + +char *hex2Str( uint8_t data) +{ + + char hex[] = "0123456789ABCDEF"; + static char str[3]; + char *pStr = str; + + *pStr++ = hex[data >> 4]; + *pStr++ = hex[data & 0x0F]; + *pStr = 0; + + return str; +} + +void uart_print_int(unsigned int num) +{ + + uint8_t i; + uint8_t m; + + uart_putchar((char *)"0x"); + for (i = 4;i > 0;i--) + { + m = ((num >> (8 * (i - 1)))& 0xff); + uart_putchar(hex2Str(m)); + } + uart_putchar("\r\n"); +} + + + +void cpu_delay( volatile unsigned int times) +{ + while(times--) + { + for(uint32_t i = 0;i < 1000;i++) + ; + } +} + + + +///UART Character format +enum UART_CHARFORMAT +{ + UART_CHARFORMAT_8 = 0, + UART_CHARFORMAT_7 = 1 +}; + +///UART Stop bit +enum UART_STOPBITS +{ + UART_STOPBITS_1 = 0, + UART_STOPBITS_2 = 1 /* Note: The number of stop bits is 1.5 if a character format + with 5 bit is chosen*/ +}; + +///UART Parity enable +enum UART_PARITY +{ + UART_PARITY_DISABLED = 0, + UART_PARITY_ENABLED = 1 +}; + +///UART Parity type +enum UART_PARITYBIT +{ + UART_PARITYBIT_EVEN = 0, + UART_PARITYBIT_ODD = 1, + UART_PARITYBIT_SPACE = 2, // The parity bit is always 0. + UART_PARITYBIT_MARK = 3 // The parity bit is always 1. +}; + +///UART HW flow control +enum UART_HW_FLOW_CNTL +{ + UART_HW_FLOW_CNTL_DISABLED = 0, + UART_HW_FLOW_CNTL_ENABLED = 1 +}; + +///UART Input clock select +enum UART_INPUT_CLK_SEL +{ + UART_INPUT_CLK_SEL_0 = 0, + UART_INPUT_CLK_SEL_1 = 1, + UART_INPUT_CLK_SEL_2 = 2, + UART_INPUT_CLK_SEL_3 = 3 +}; + +///UART Interrupt enable/disable +enum UART_INT +{ + UART_INT_DISABLE = 0, + UART_INT_ENABLE = 1 +}; + +///UART Error detection +enum UART_ERROR_DETECT +{ + UART_ERROR_DETECT_DISABLED = 0, + UART_ERROR_DETECT_ENABLED = 1 +}; + +/* + * STRUCT DEFINITIONS + ***************************************************************************************** + */ +/* TX and RX channel class holding data used for asynchronous read and write data + * transactions + */ +/// UART TX RX Channel +struct uart_txrxchannel +{ + /// call back function pointer + void (*callback) (void*, uint8_t); + /// Dummy data pointer returned to callback when operation is over. + void* dummy; +}; + +/// UART environment structure +struct uart_env_tag +{ + /// tx channel + struct uart_txrxchannel tx; + /// rx channel + struct uart_txrxchannel rx; + /// error detect + uint8_t errordetect; + /// external wakeup + bool ext_wakeup; +}; + +/* + * GLOBAL VARIABLE DEFINITIONS + **************************************************************************************** + */ +/// uart environment structure +struct uart_env_tag uart_env; + +/* + * LOCAL FUNCTION DEFINITIONS + **************************************************************************************** + */ + + +/* + * EXPORTED FUNCTION DEFINITIONS + **************************************************************************************** + */ + + +void uart_init(uint32_t baudrate) +{ +#if UART_PRINTF_EN + unsigned int baud_divisor ; + REG_AHB0_ICU_UARTCLKCON &= ~(0x1 << 0) ; // Enable Uart's Clocks + baud_divisor = 0x8a;//uart_clks/baud_rate ; + baud_divisor = baud_divisor-1 ; + REG_APB3_UART_CFG = (baud_divisor<<8) + + (stop_bits <<7) + + //(parity_mode <<6) + + //(parity_en <<5) + + (data_len <<3) + + (irda_mode <<2) + + (uart_rx_en <<1) + + uart_tx_en ; + REG_APB3_UART_FIFO_CFG = 0x00002001 ; // Set Fifo threshold 8 + REG_APB3_UART_INT_ENABLE = ((0x01 << 1) | (0x01 << 6) | (0x01 << 7)); //need read / stop end /rxd wake up + REG_APB3_UART_FLOW_CFG = 0x00000000 ; // No Flow Control + REG_APB3_UART_WAKERNEL_CFG = ((0x01 << 0 )| (0x01 << 20) | (0x01 << 21)| (0x01 << 22)); // No Wake Control + + REG_APB5_GPIOA_CFG &= ~((0x3< // standard boolean definitions +#include // standard integer functions +#include "rwip_config.h" + + +#if UART_PRINTF_EN + +#if !BLE_TESTER +#define UART_PRINTF uart_printf_null +#else +#define UART_PRINTF uart_printf +#endif //!BLE_TESTER + +#else +#define UART_PRINTF uart_printf_null +#endif // #if UART_PRINTF_EN + + +/* + * ENUMERATION DEFINITIONS + ***************************************************************************************** + */ + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Initializes the UART to default values. + ***************************************************************************************** + */ +void uart_init(uint32_t baudrate); + +void dbg_initial(void); + +void uart_clear_rxfifo(void); + +uint8_t Uart_Read_Byte(void); +uint8_t Read_Uart_Buf(void); + +int dbg_putchar(char * st); +int uart_putchar(char * st); +int uart_printf(const char *fmt,...); +int uart_printf_null(const char *fmt,...); +int dbg_printf(const char *fmt,...); +void uart_print_int(unsigned int num); +uint8_t check_uart_stop(void); + +void cpu_delay( volatile unsigned int times); + + +/****** REG ****************/ +void uart_send(unsigned char *buff, int len); +void TRAhcit_UART_Rx(void); + +#define UART0_RX_FIFO_MAX_COUNT 128 + +#define UART0_TX_FIFO_MAX_COUNT 128 + +extern unsigned char uart_rx_buf[UART0_RX_FIFO_MAX_COUNT]; +extern unsigned char uart_tx_buf[UART0_TX_FIFO_MAX_COUNT]; +extern volatile bool uart_rx_done ; +extern volatile unsigned long uart_rx_index ; +/****** REG ****************/ + + + +#ifndef CFG_ROM +/** + **************************************************************************************** + * @brief Enable UART flow. + ***************************************************************************************** + */ +void uart_flow_on(void); + +/** + **************************************************************************************** + * @brief Disable UART flow. + ***************************************************************************************** + */ +bool uart_flow_off(void); +#endif //CFG_ROM + +/** + **************************************************************************************** + * @brief Finish current UART transfers + ***************************************************************************************** + */ +void uart_finish_transfers(void); + +/** + **************************************************************************************** + * @brief Starts a data reception. + * + * @param[out] bufptr Pointer to the RX buffer + * @param[in] size Size of the expected reception + * @param[in] callback Pointer to the function called back when transfer finished + * @param[in] dummy Dummy data pointer returned to callback when reception is finished + ***************************************************************************************** + */ +void uart_read(uint8_t *bufptr, uint32_t size, void (*callback) (void*, uint8_t), void* dummy); + +/** + **************************************************************************************** + * @brief Starts a data transmission. + * + * @param[in] bufptr Pointer to the TX buffer + * @param[in] size Size of the transmission + * @param[in] callback Pointer to the function called back when transfer finished + * @param[in] dummy Dummy data pointer returned to callback when transmission is finished + ***************************************************************************************** + */ +void uart_write(uint8_t *bufptr, uint32_t size, void (*callback) (void*, uint8_t), void* dummy); + +#if defined(CFG_ROM) +/** + **************************************************************************************** + * @brief Poll UART on reception and transmission. + * + * This function is used to poll UART for reception and transmission. + * It is used when IRQ are not used to detect incoming bytes. + ***************************************************************************************** + */ +void uart_poll(void); +#endif //CFG_ROM + +/** + **************************************************************************************** + * @brief Serves the data transfer interrupt requests. + * + * It clears the requests and executes the appropriate callback function. + ***************************************************************************************** + */ +void uart_isr(void); + + +/// @} UART +#endif /* _UART_H_ */ diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/bim/bim_updataImage.c b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/bim/bim_updataImage.c new file mode 100755 index 0000000..3d19bd0 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/bim/bim_updataImage.c @@ -0,0 +1,652 @@ + + +#include "bim_updataImage.h" +#include "bim_com.h" +#include "bim_uart.h" + +#include + + +img_hdr_t hdr_img; +img_hdr_t hdr_back; + +uint32_t udi_get_psec_image_header(void) +{ + //UART_PRINTF("udi_get_psec_image_header ADDR = 0x%x\r\n",SEC_IMAGE_OAD_HEADER_FADDR); + fflash_rd_data((uint8_t *)&hdr_img,SEC_IMAGE_OAD_HEADER_FADDR,sizeof(img_hdr_t)); + + //UART_PRINTF("hdr_img.crc = 0x%x.\r\n",hdr_img.crc); + //UART_PRINTF("hdr_img.crc_status = 0x%x.\r\n",hdr_img.crc_status); + //UART_PRINTF("hdr_img.len = 0x%x.\r\n",hdr_img.len); + //UART_PRINTF("hdr_img.res0 = 0x%x.\r\n",hdr_img.res[0]); + //UART_PRINTF("hdr_img.res1 = 0x%x.\r\n",hdr_img.res[1]); + //UART_PRINTF("hdr_img.sec_status = 0x%x.\r\n",hdr_img.sec_status); + //UART_PRINTF("hdr_img.ver = 0x%x.\r\n",hdr_img.ver); + //UART_PRINTF("hdr_img.uid = 0x%x.\r\n",hdr_img.uid); + return 0; +} + +uint32_t udi_get_psec_backup_header(void) +{ + //UART_PRINTF("udi_get_psec_backup_header addr = 0x%x\r\n",SEC_BACKUP_OAD_HEADER_FADDR); + fflash_rd_data((uint8_t *)&hdr_back,SEC_BACKUP_OAD_HEADER_FADDR,sizeof(img_hdr_t)); + + //UART_PRINTF("hdr_back.crc = 0x%x.\r\n",hdr_back.crc); + //UART_PRINTF("hdr_back.crc_status = 0x%x.\r\n",hdr_back.crc_status); + //UART_PRINTF("hdr_back.len = 0x%x.\r\n",hdr_back.len); + //UART_PRINTF("hdr_back.res0 = 0x%x.\r\n",hdr_back.res[0]); + //UART_PRINTF("hdr_back.res1 = 0x%x.\r\n",hdr_back.res[1]); + //UART_PRINTF("hdr_back.sec_status = 0x%x.\r\n",hdr_back.sec_status); + //UART_PRINTF("hdr_back.ver = 0x%x.\r\n",hdr_back.ver); + //UART_PRINTF("hdr_back.uid = 0x%x.\r\n",hdr_back.uid); + return 0; +} + +int makernel_crc32_table(void); +uint32_t makernel_crc32(uint32_t crc,unsigned char *string,uint32_t size); +uint32_t calc_image_sec_crc(void) +{ + + //UART_PRINTF("%s\r\n",__func__); + uint8_t data[BLOCK_SIZE]; + uint8_t tmp_data[BLOCK_SIZE]; + uint32_t block_total; + uint32_t read_addr; + uint32_t calcuCrc = 0xffffffff; + makernel_crc32_table(); + block_total = hdr_img.len / 4 - 1;// not clac HDR + +// block_total = hdr_img.len * 4 - 16; + read_addr = SEC_IMAGE_RUN_FADDR; + //UART_PRINTF("read start addr = 0x%x\r\n",read_addr); + for(uint32_t i = 0;i < block_total; i++) + { + fflash_rd_data(data,read_addr,BLOCK_SIZE); + fflash_rd_data(tmp_data,read_addr,BLOCK_SIZE); + calcuCrc = makernel_crc32(calcuCrc,data,BLOCK_SIZE); + + if(memcmp(data,tmp_data,BLOCK_SIZE) != 0) + { + //UART_PRINTF("read_addr error = 0x08%x\r\n",read_addr); + for(int a=0;a block_total - 0x20) +// { +// UART_PRINTF("read start addr = 0x%x ",read_addr); +// for(int a=0;a<16;a++) +// { +// UART_PRINTF("%02x ",data[a]); +// } +// UART_PRINTF("calcuCrc = 0x%08x\r\n",calcuCrc); +// } +// for(int a=0;a block_total - 0x20) +// { +// UART_PRINTF("read start addr = 0x%x ",read_addr); +// for(int a=0;a<16;a++) +// { +// UART_PRINTF("%02x ",data[a]); +// } +// UART_PRINTF("calcuCrc = 0x%08x\r\n",calcuCrc); +// } + } + //UART_PRINTF("read end addr = 0x%x,calcuCrc = 0x%08x\r\n",read_addr,calcuCrc); + + return calcuCrc; +} + + +uint8_t udi_check_image_sec_status(void) +{ + udi_get_psec_image_header(); + //return SSTATUS_SECT_NORMAL; + + if(CRC_UNCHECK == hdr_img.crc_status) // image not crc check and image is exist ,do crc calc + { + if(hdr_img.len != 0xffff && (hdr_img.len / 4)<= SEC_MAX_FSIZE_BLOCK) + { + //UART_PRINTF("hdr_img.len = 0x%x,crc = 0x%08x!!!\r\n",hdr_img.len,hdr_img.crc); + if(hdr_img.crc == calc_image_sec_crc()) // crc ok + { + + //UART_PRINTF("check crc OK!!!\r\n"); + hdr_img.crc_status = CRC_CHECK_OK; + hdr_img.sec_status = SECT_NORMAL; + fflash_wr_data((uint8_t *)&hdr_img,SEC_IMAGE_OAD_HEADER_FADDR,sizeof(img_hdr_t)); + fflash_rd_data((uint8_t *)&hdr_img,SEC_IMAGE_OAD_HEADER_FADDR,sizeof(img_hdr_t)); + udi_get_psec_image_header(); + return SSTATUS_SECT_NORMAL; + }else{ + + hdr_img.crc_status = CRC_CHECK_FAIL; + hdr_img.sec_status = SECT_ABNORMAL; + fflash_wr_data((uint8_t *)&hdr_img,SEC_IMAGE_OAD_HEADER_FADDR,sizeof(img_hdr_t)); + fflash_rd_data((uint8_t *)&hdr_img,SEC_IMAGE_OAD_HEADER_FADDR,sizeof(img_hdr_t)); + + return SSTATUS_SECT_ABNORMAL; + } + } + else if(hdr_img.res[0] == 0xff && hdr_img.res[1] == 0xff) + { + return SSTATUS_SECT_ERASED; + }else + { + hdr_img.crc_status = CRC_CHECK_FAIL; + hdr_img.sec_status = SECT_ABNORMAL; + fflash_wr_data((uint8_t *)&hdr_img,SEC_IMAGE_OAD_HEADER_FADDR,sizeof(img_hdr_t)); + fflash_rd_data((uint8_t *)&hdr_img,SEC_IMAGE_OAD_HEADER_FADDR,sizeof(img_hdr_t)); + return SSTATUS_SECT_ABNORMAL; + } + + } + else if(CRC_CHECK_FAIL == hdr_img.crc_status) + { + hdr_img.crc_status = CRC_CHECK_FAIL; + hdr_img.sec_status = SECT_ABNORMAL; + fflash_wr_data((uint8_t *)&hdr_img,SEC_IMAGE_OAD_HEADER_FADDR,sizeof(img_hdr_t)); + fflash_rd_data((uint8_t *)&hdr_img,SEC_IMAGE_OAD_HEADER_FADDR,sizeof(img_hdr_t)); + return SSTATUS_SECT_ABNORMAL; + } + else if(CRC_CHECK_OK == hdr_img.crc_status) + { + hdr_img.crc_status = CRC_CHECK_OK; + hdr_img.sec_status = SECT_NORMAL; + fflash_wr_data((uint8_t *)&hdr_img,SEC_IMAGE_OAD_HEADER_FADDR,sizeof(img_hdr_t)); + fflash_rd_data((uint8_t *)&hdr_img,SEC_IMAGE_OAD_HEADER_FADDR,sizeof(img_hdr_t)); + return SSTATUS_SECT_NORMAL; + }else + { + hdr_img.crc_status = CRC_CHECK_FAIL; + hdr_img.sec_status = SECT_ABNORMAL; + fflash_wr_data((uint8_t *)&hdr_img,SEC_IMAGE_OAD_HEADER_FADDR,sizeof(img_hdr_t)); + fflash_rd_data((uint8_t *)&hdr_img,SEC_IMAGE_OAD_HEADER_FADDR,sizeof(img_hdr_t)); + return SSTATUS_SECT_ABNORMAL; + } +} + + +uint8_t udi_check_backup_sec_status(void)//NOT WRITE INFO TO FLASH +{ + udi_get_psec_backup_header(); + if(CRC_UNCHECK == hdr_back.crc_status) // image not crc check and image is exist ,do crc calc + { + if(hdr_back.len != 0xffff && (hdr_back.len / 4) <= SEC_MAX_FSIZE_BLOCK) + { + if(hdr_back.crc == calc_backup_sec_crc()) // crc ok + { + hdr_back.crc_status = CRC_CHECK_OK; + hdr_back.sec_status = SECT_NORMAL; + return SSTATUS_SECT_NORMAL; + }else + { + + hdr_back.crc_status = CRC_CHECK_FAIL; + hdr_back.sec_status = SECT_ABNORMAL; + return SSTATUS_SECT_ABNORMAL; + } + }else if(hdr_back.res[0] == 0xff && hdr_back.res[1] == 0xff) + { + return SSTATUS_SECT_ERASED; + }else + { + hdr_back.crc_status = CRC_CHECK_FAIL; + hdr_back.sec_status = SECT_ABNORMAL; + return SSTATUS_SECT_ABNORMAL; + } + } + else if(CRC_CHECK_FAIL == hdr_back.crc_status) + { + hdr_back.crc_status = CRC_CHECK_FAIL; + hdr_back.sec_status = SECT_ABNORMAL; + return SSTATUS_SECT_ABNORMAL; + } + else if(CRC_CHECK_OK == hdr_back.crc_status) + { + hdr_back.crc_status = CRC_CHECK_OK; + hdr_back.sec_status = SECT_NORMAL; + return SSTATUS_SECT_NORMAL; + }else + { + hdr_back.crc_status = CRC_CHECK_FAIL; + hdr_back.sec_status = SECT_ABNORMAL; + return SSTATUS_SECT_ABNORMAL; + } +} + + +#if 1 +void udi_erase_image_sec(void) +{ + //UART_PRINTF("udi_erase_image_sec \r\n"); + uint32_t addr = SEC_IMAGE_ALLOC_END_FADDR - FLASH_SEC_SIZE ; + + //UART_PRINTF("START addr = 0x%08x\r\n",addr); + for(;addr >= SEC_IMAGE_ALLOC_START_FADDR;addr-= FLASH_SEC_SIZE ) + { + udi_erase_section(addr,FLASH_SEC_SIZE); + } + //UART_PRINTF("END addr = 0x%08x\r\n",addr); +} + + + +void udi_erase_backup_sec(void) +{ + //UART_PRINTF("udi_erase_backup_sec \r\n"); + uint32_t addr = SEC_BACKUP_ALLOC_END_FADDR - FLASH_SEC_SIZE ; + //UART_PRINTF("START addr = 0x%08x\r\n",addr); + for(;addr >= SEC_BACKUP_ALLOC_START_FADDR;addr-= FLASH_SEC_SIZE ) + { + udi_erase_section(addr,FLASH_SEC_SIZE); + + } + //UART_PRINTF("END addr = 0x%08x\r\n",addr); +} + +#else + +void udi_erase_image_sec(void) // erase 240K (3 * 64K + 32K + 4 *4K) +{ + UART_PRINTF("udi_erase_image_sec \r\n"); + uint32_t addr = SEC_IMAGE_ALLOC_END_FADDR - FLASH_ONE_BLOCK_SIZE ; + + UART_PRINTF("START addr = 0x%08x\r\n",addr); + //////////3 * 64K //////////////////////////// + fflash_erase_one_block(addr); + addr-= FLASH_ONE_BLOCK_SIZE; + fflash_erase_one_block(addr); + addr-= FLASH_ONE_BLOCK_SIZE; + fflash_erase_one_block(addr); + + + /////////// 32K/////////////////////////////// + addr-=FLASH_HALF_BLOCK_SIZE; + fflash_erase_half_block(addr); + + //////////////// 4 * 4K////////////////////////////// + addr-=FLASH_HALF_BLOCK_SIZE; + udi_erase_section(addr,FLASH_HALF_BLOCK_SIZE); + + UART_PRINTF("END addr = 0x%08x\r\n",addr); +} + + + +void udi_erase_backup_sec(void) +{ + UART_PRINTF("udi_erase_backup_sec \r\n"); + uint32_t addr = SEC_BACKUP_ALLOC_END_FADDR - FLASH_ONE_BLOCK_SIZE ; + + UART_PRINTF("START addr = 0x%08x\r\n",addr); + //////////3 * 64K //////////////////////////// + fflash_erase_one_block(addr); + addr-= FLASH_ONE_BLOCK_SIZE; + fflash_erase_one_block(addr); + addr-= FLASH_ONE_BLOCK_SIZE; + fflash_erase_one_block(addr); + + + /////////// 32K/////////////////////////////// + addr-=FLASH_HALF_BLOCK_SIZE; + fflash_erase_half_block(addr); + + //////////////// 4 * 4K////////////////////////////// + addr-=FLASH_HALF_BLOCK_SIZE; + udi_erase_section(addr,FLASH_HALF_BLOCK_SIZE); + + UART_PRINTF("END addr = 0x%08x\r\n",addr); +} + +#endif + + +void udi_updata_backup_to_image_sec(void) +{ + //UART_PRINTF("udi_updata_backup_to_image_sec\r\n"); + uint8_t data[BLOCK_SIZE]; + uint32_t backup_size = hdr_back.len * 4; + uint32_t read_end_addr = SEC_BACKUP_OAD_HEADER_FADDR + backup_size; + + uint32_t write_addr = SEC_IMAGE_OAD_HEADER_FADDR; + //UART_PRINTF("write_addr = 0x%x\r\n",write_addr); + + for(uint32_t read_addr = SEC_BACKUP_OAD_HEADER_FADDR;read_addr < read_end_addr;) + { + fflash_rd_data(data,read_addr,BLOCK_SIZE); + fflash_wr_data(data,write_addr,BLOCK_SIZE); + write_addr += BLOCK_SIZE; + read_addr += BLOCK_SIZE; + + } + //UART_PRINTF("udi_updata_backup_to_image_sec end\r\n"); +} + +/* +void udi_updata_image_to_backup_sec(void) +{ + UART_PRINTF("udi_updata_image_to_backup_sec\r\n"); + uint8_t data[BLOCK_SIZE]; + uint32_t backup_size = hdr_back.len * 4; + uint32_t read_end_addr = SEC_IMAGE_OAD_HEADER_FADDR + 0x24000;//backup_size; + + uint32_t write_addr = SEC_BACKUP_OAD_HEADER_FADDR; + UART_PRINTF("write_addr = 0x%x\r\n",write_addr); + + for(uint32_t read_addr = SEC_IMAGE_OAD_HEADER_FADDR;read_addr < read_end_addr;) + { + fflash_rd_data(data,read_addr,BLOCK_SIZE); + fflash_wr_data(data,write_addr,BLOCK_SIZE); + write_addr += BLOCK_SIZE; + read_addr += BLOCK_SIZE; + + } + UART_PRINTF("udi_updata_image_to_backup_sec end,write_addr = 0x%08x\r\n",write_addr); +} +*/ +uint8_t udi_select_sec(void) +{ + uint8_t isec_status,bsec_status; + uint8_t status = 0; + + isec_status = udi_check_image_sec_status(); + bsec_status = udi_check_backup_sec_status(); + + //isec_status = SSTATUS_SECT_NORMAL; + + switch(isec_status) + { + case SSTATUS_SECT_NORMAL: + { + switch(bsec_status) + { + case SSTATUS_SECT_NORMAL: // 1:I NORMAL ,B NORMAL,updata B -> I,RUN I + { + udi_erase_image_sec(); + udi_updata_backup_to_image_sec(); + if(SSTATUS_SECT_NORMAL == udi_check_image_sec_status()) + { + udi_erase_backup_sec(); + status = 1; + }else + { + udi_wdt_enable(500); + } //reset// + + //UART_PRINTF("TYPE = 1\r\n"); + }break; + + case SSTATUS_SECT_ABNORMAL://://2 :I NORMAL,B ABNORMAL ,ERASE B,RUN I + { + udi_erase_backup_sec(); + status = 1; + //UART_PRINTF("TYPE = 2\r\n"); + }break; + + case SSTATUS_SECT_ERASED://://3:I NORMAL,B ERASED,RUN I + { + status = 1; + //UART_PRINTF("TYPE = 3\r\n"); + }break; + + default: + //UART_PRINTF("TYPE B unkown\r\n"); + break; + + } + + }break; + + case SSTATUS_SECT_ABNORMAL: + { + switch(bsec_status) + { + case SSTATUS_SECT_NORMAL: //://4:I ABNORMAL,B NORMAL,updata B -> I,RUN I + { + udi_erase_image_sec(); + + udi_updata_backup_to_image_sec(); + + if(SSTATUS_SECT_NORMAL == udi_check_image_sec_status()) + { + udi_erase_backup_sec(); + status = 1; + }else + { + udi_wdt_enable(500); + } //reset// + + //UART_PRINTF("TYPE = 4\r\n"); + }break; + + case SSTATUS_SECT_ABNORMAL://5:I ABNORMAL,B ABNORMAL,ERASE I,B(NOT HAPPEN) + { + udi_erase_image_sec(); + udi_erase_backup_sec(); + //UART_PRINTF("TYPE = 5\r\n"); + }break; + + case SSTATUS_SECT_ERASED://6:I ABNORMAL,B ERASED,ERASE I (NOT HAPPEN) + { + udi_erase_image_sec(); + + //UART_PRINTF("TYPE = 6\r\n"); + }break; + + default: + //UART_PRINTF("TYPE B unkown\r\n"); + break; + + } + + }break; + + case SSTATUS_SECT_ERASED: + { + switch(bsec_status) + { + case SSTATUS_SECT_NORMAL://7:I ERASED,B NORMAL,updata B -> I,RUN I + { + udi_erase_image_sec(); + udi_updata_backup_to_image_sec(); + if(SSTATUS_SECT_NORMAL == udi_check_image_sec_status()) + { + udi_erase_backup_sec(); + status = 1; + }else + { + udi_wdt_enable(500); + } //reset// + + //UART_PRINTF("TYPE = 7\r\n"); + }break; + + case SSTATUS_SECT_ABNORMAL://8:I ERASED,B ABNORMAL,ERASE B (NOT HAPPEN) + { + udi_erase_backup_sec(); + //UART_PRINTF("TYPE = 8\r\n"); + }break; + + case SSTATUS_SECT_ERASED://9:I ERASED,B ERASED,(NOT HAPPEN) + { + //UART_PRINTF("TYPE = 9\r\n"); + }break; + + default: + //UART_PRINTF("TYPE B unkown\r\n"); + break; + + } + + }break; + + default: + //UART_PRINTF("TYPE A unkown\r\n"); + break; + + } + + return status ; + +} +uint32_t crc32_table[256]; +int makernel_crc32_table(void) +{ + uint32_t c; + int i = 0; + int bit = 0; + for(i = 0; i < 256; i++) + { + c = (uint32_t)i; + for(bit = 0; bit < 8; bit++) + { + if(c&1) + { + c = (c>>1)^(0xEDB88320); + } + else + { + c = c >> 1; + } + } + crc32_table[i] = c; + + //UART_PRINTF("crc32_table[%d] = 0x%08x\r\n",i,crc32_table[i]); + //uart_print_int_debug(i,c); + } + return 0; +} +uint32_t makernel_crc32(uint32_t crc,unsigned char *string,uint32_t size) +{ + while(size--) + { + crc = (crc >> 8)^(crc32_table[(crc^*string++)&0xff]); + } + return crc; +} + +void test_crc(void) +{ + //UART_PRINTF("test_crc start\r\n"); + + uint8_t buf[100]; + + uint32_t crc = 0xffffffff; + + for(int i = 0;i < 100; i ++) + { + buf[i] = i; + } + makernel_crc32_table(); + + for(int j = 0;j<100;j+=4) + { + crc = makernel_crc32(crc,(uint8_t*)&(buf[j]),4); + //UART_PRINTF("crc[%d] = 0x%08x\r\n",j,crc); + } + + //UART_PRINTF("test_crc end\r\n"); + +} + + + +void test_erase_time(void) +{ + uint32_t addr; + addr = 0x40000; + //UART_PRINTF("fflash_erase_one_block start addr = 0x%x\r\n",addr); + fflash_erase_one_block(addr); + addr += 0x10000; + + //UART_PRINTF("fflash_erase_one_block start addr = 0x%x\r\n",addr); + fflash_erase_one_block(addr); + addr += 0x10000; + + //UART_PRINTF("fflash_erase_one_block start addr = 0x%x\r\n",addr); + fflash_erase_one_block(addr); + addr += 0x8000; + + //UART_PRINTF("fflash_erase_half_block start addr = 0x%x\r\n",addr); + fflash_erase_half_block(addr); + //UART_PRINTF("fflash_erase_half_block end\r\n"); + + + addr+= 0x1000; + //UART_PRINTF("fflash_erase_one_sector start addr = 0x%x\r\n",addr); + fflash_erase_one_sector(addr); + addr+= 0x1000; + //UART_PRINTF("fflash_erase_one_sector start addr = 0x%x\r\n",addr); + fflash_erase_one_sector(addr); + addr+= 0x1000; + //UART_PRINTF("fflash_erase_one_sector start addr = 0x%x\r\n",addr); + fflash_erase_one_sector(addr); + addr+= 0x1000; + //UART_PRINTF("fflash_erase_one_sector start addr = 0x%x\r\n",addr); + fflash_erase_one_sector(addr); + //UART_PRINTF("fflash_erase_one_sector end\r\n"); + + + addr = 0x40000; + //UART_PRINTF("fflash_erase_one_sector start addr = 0x%x\r\n",addr); + for(addr = 0x40000;addr < 240 *1024 + 0x40000;addr+=0x1000) + { + //fflash_erase_one_sector(addr); + + } + //UART_PRINTF("fflash_erase_one_sector end addr = 0x%x\r\n",addr); + +} + +//uint32_t check_data_crc(uint8_t *data,uint32_t size) +//{ +// uint32_t calcuCrc = 0xffffffff; +// calcuCrc = makernel_crc32(calcuCrc,data,size); +//// uart_print_int_debug(CALCUCRC_VALUE,calcuCrc); +// return calcuCrc; +//} + + diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/bim/bim_updataImage.h b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/bim/bim_updataImage.h new file mode 100755 index 0000000..bc8ea8d --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/bim/bim_updataImage.h @@ -0,0 +1,112 @@ + +#include + + + +#define BIM_FSIZE_16K + +#ifdef BIM_FSIZE_16K + +#define FLASH_SEC_SIZE (0X1000) +#define FLASH_HALF_BLOCK_SIZE (0X8000) +#define FLASH_ONE_BLOCK_SIZE (0X10000) + + +#define SEC_MAX_FSIZE_4K (240) //240KB +#define SEC_MAX_FSIZE_BLOCK (0X3C00) //240 * 1024 f000 +#define SEC_MAX_FSIZE_BYTE (0X3C000) //240 * 1024 + +#define SEC_IMAGE_RUN_CADDR (0x3C60) +#define SEC_IMAGE_RUN_FADDR (0x4026) //( 0x3C60 * 0X22 / 0X20) + +#define SEC_IMAGE_OAD_HEADER_FADDR (0x4016) //(0x4026 - 0X10) + +#define SEC_IMAGE_ALLOC_START_FADDR (0x4000) //(16KB) +#define SEC_IMAGE_ALLOC_END_FADDR (0x40000) //(256KB) + +#define SEC_BACKUP_OAD_HEADER_FADDR (0x44000) //272kb * 1024 = 270336 +#define SEC_BACKUP_OAD_IMAGE_FADDR (0x44010) //272kb * 1024 + 0X10 = 270336 +#define SEC_BACKUP_ALLOC_START_FADDR (0x44000) //(272KB) +#define SEC_BACKUP_ALLOC_END_FADDR (0x80000) //(512KB) + +#else + + + +#define FLASH_SEC_SIZE (0X1000) +#define SEC_MAX_FSIZE_4K (248) //248KB +#define SEC_MAX_FSIZE_BLOCK 0xffff //(0X3E00) //248 * 1024 +#define SEC_MAX_FSIZE_BYTE (0X3E000) //248 * 1024 + +#define SEC_IMAGE_RUN_CADDR (0x1E40) +#define SEC_IMAGE_RUN_FADDR (0x2024) //( 0x1E40 * 0X22 / 0X20) + +#define SEC_IMAGE_OAD_HEADER_FADDR (0x2014) //(0x2024 - 0X10) + +#define SEC_IMAGE_ALLOC_START_FADDR (0x2000) //(8KB) +#define SEC_IMAGE_ALLOC_END_FADDR (0x40000) //(256KB) + + +#define SEC_BACKUP_OAD_HEADER_FADDR (0x42000) //264kb * 1024 = 270336 +#define SEC_BACKUP_ALLOC_START_FADDR (0x42000) //(264KB) +#define SEC_BACKUP_ALLOC_END_FADDR (0x80000) //(512KB) + +#endif// + + +/********************************************************************* + * TYPEDEFS + */ +// The Image Header will not be encrypted, but it will be included in a Signature. +typedef struct +{ + // Secure OAD uses the Signature for image validation instead of calculating a CRC, but the use + // of CRC==CRC-Shadow for quick boot-up determination of a validated image is still used. + uint32_t crc; // CRC must not be 0x0000 or 0xFFFF. + // User-defined Image Version Number - default logic uses simple a '!=' comparison to start an OAD. + uint16_t ver; + + uint16_t len; // Image length in 4-byte blocks (i.e. HAL_FLASH_WORD_SIZE blocks). + + uint32_t uid; // User-defined Image Identification bytes. + uint8_t crc_status; // cur image crc status + uint8_t sec_status; // cur image sec status + uint8_t res[2]; // Reserved space for future use. +} img_hdr_t; + + + + +#define BLOCK_SIZE 0X10 + +#define CRC_UNCHECK 0xFF +#define CRC_CHECK_OK 0xAA +#define CRC_CHECK_FAIL 0x55 + +#define SECT_UNKNOW 0xFF +#define SECT_NORMAL 0xAA +#define SECT_ABNORMAL 0x55 + +enum +{ + SSTATUS_SECT_NORMAL = 0, + SSTATUS_SECT_ERASED, + SSTATUS_SECT_ABNORMAL, + SSTATUS_SECT_UNKOWN , +}; + + +void udi_erase_image_sec(void); + +void udi_erase_backup_sec(void); + +void udi_updata_backup_to_image_sec(void); + +void udi_updata_image_to_backup_sec(void); + +void test_crc(void); + +void test_erase_time(void); + +uint8_t udi_select_sec(void); + diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/bim/boot_bim.h b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/bim/boot_bim.h new file mode 100755 index 0000000..4901df1 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/bim/boot_bim.h @@ -0,0 +1,94 @@ +/** + **************************************************************************************** + * + * @file boot.h + * + * @brief This file contains the declarations of the boot related variables. + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef _BOOT_H_ +#define _BOOT_H_ + +#if 0 +/// Address of beginning of the CODE +extern char code_base; +#define CODE_BASE (&(code_base)) + +/// Address of the end of the CODE +extern char code_end; +#define CODE_END (&(code_end)) + +/// Length of the code +#define CODE_LENGTH ((CODE_END) - (CODE_BASE)) + +/// Address of beginning of the DATA +extern char data_base; +#define DATA_BASE (&(data_base)) + +/// Address of the end of the DATA +extern char data_end; +#define DATA_END (&(data_end)) + +/// Length of the DATA +#define DATA_LENGTH ((DATA_END) - (DATA_BASE)) + +/// Unloaded RAM area base address +extern char unloaded_area_start; +#define RAM_UNLOADED_BASE (&(unloaded_area_start)) + +/// Stack base address + + + +#endif + + + + +/// Length of the code +extern const unsigned int Image$$ROM$$Length[]; +#define CODE_LENGTH ((uint32_t)Image$$ROM$$Length) + +/// Length of the RW data +extern const unsigned int Image$$RAM_DATA$$Length[]; +#define DATA_LENGTH ((uint32_t)Image$$RAM_DATA$$Length) + +/// Unloaded RAM area base address +extern const unsigned int Image$$RAM_UNLOADED$$Base[]; +#define RAM_UNLOADED_BASE ((uint32_t)Image$$RAM_UNLOADED$$Base) + +/// Stack base address and len of UNUSED +extern const unsigned int boot_stack_base_UNUSED; +#define STACK_BASE_UNUSED ((uint32_t)boot_stack_base_UNUSED) +extern const unsigned int boot_stack_len_UNUSED; +#define STACK_LEN_UNUSED ((uint32_t)boot_stack_len_UNUSED) + +/// Stack base address and len of SVC +extern const unsigned int boot_stack_base_SVC ; +#define STACK_BASE_SVC ((uint32_t)boot_stack_base_SVC) +extern const unsigned int boot_stack_len_SVC; +#define STACK_LEN_SVC ((uint32_t)boot_stack_len_SVC) + +/// Stack base address and len of IRQ +extern const unsigned int boot_stack_base_IRQ; +#define STACK_BASE_IRQ ((uint32_t)boot_stack_base_IRQ) +extern const unsigned int boot_stack_len_IRQ; +#define STACK_LEN_IRQ ((uint32_t)boot_stack_len_IRQ) + +/// Stack base address and len of FIQ +extern const unsigned int boot_stack_base_FIQ; +#define STACK_BASE_FIQ ((uint32_t)boot_stack_base_FIQ) +extern const unsigned int boot_stack_len_FIQ; +#define STACK_LEN_FIQ ((uint32_t)boot_stack_len_FIQ) + +#define BOOT_PATTERN_UNUSED 0xAAAAAAAA // Pattern to fill UNUSED stack +#define BOOT_PATTERN_SVC 0xBBBBBBBB // Pattern to fill SVC stack +#define BOOT_PATTERN_IRQ 0xCCCCCCCC // Pattern to fill IRQ stack +#define BOOT_PATTERN_FIQ 0xDDDDDDDD // Pattern to fill FIQ stack + +#endif // _BOOT_H_ diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_assert_mgr.h b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_assert_mgr.h new file mode 100755 index 0000000..0b01699 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_assert_mgr.h @@ -0,0 +1,10 @@ +#ifndef __REG_ASSERT_MGR_H_ +#define __REG_ASSERT_MGR_H_ + +#define REG_ASSERT_MGR_SIZE 16 + +#define REG_ASSERT_MGR_BASE_ADDR 0x1000D000 + + +#endif // __REG_ASSERT_MGR_H_ + diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_ble_em_cs.h b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_ble_em_cs.h new file mode 100755 index 0000000..82371f0 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_ble_em_cs.h @@ -0,0 +1,10 @@ +#ifndef __REG_BLE_EM_CS_H_ +#define __REG_BLE_EM_CS_H_ + +#define REG_BLE_EM_CS_SIZE 92 + +#define REG_BLE_EM_CS_BASE_ADDR 0x00814000 + + +#endif // __REG_BLE_EM_CS_H_ + diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_ble_em_ral.h b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_ble_em_ral.h new file mode 100755 index 0000000..67d2365 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_ble_em_ral.h @@ -0,0 +1,10 @@ +#ifndef __REG_BLE_EM_RAL_H_ +#define __REG_BLE_EM_RAL_H_ + +#define REG_BLE_EM_RAL_SIZE 52 + +#define REG_BLE_EM_RAL_BASE_ADDR 0x00814000 + + +#endif // __REG_BLE_EM_RAL_H_ + diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_ble_em_rx_audio_buffer.h b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_ble_em_rx_audio_buffer.h new file mode 100755 index 0000000..23b4a39 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_ble_em_rx_audio_buffer.h @@ -0,0 +1,10 @@ +#ifndef __REG_BLE_EM_RX_AUDIO_BUFFER_H_ +#define __REG_BLE_EM_RX_AUDIO_BUFFER_H_ + +#define REG_BLE_EM_RX_AUDIO_BUFFER_SIZE 64 + +#define REG_BLE_EM_RX_AUDIO_BUFFER_BASE_ADDR 0x00814000 + + +#endif // __REG_BLE_EM_RX_AUDIO_BUFFER_H_ + diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_ble_em_rx_buffer.h b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_ble_em_rx_buffer.h new file mode 100755 index 0000000..75302cc --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_ble_em_rx_buffer.h @@ -0,0 +1,10 @@ +#ifndef __REG_BLE_EM_RX_BUFFER_H_ +#define __REG_BLE_EM_RX_BUFFER_H_ + +#define REG_BLE_EM_RX_BUFFER_SIZE 260 + +#define REG_BLE_EM_RX_BUFFER_BASE_ADDR 0x00814000 + + +#endif // __REG_BLE_EM_RX_BUFFER_H_ + diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_ble_em_rx_desc.h b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_ble_em_rx_desc.h new file mode 100755 index 0000000..292284c --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_ble_em_rx_desc.h @@ -0,0 +1,10 @@ +#ifndef __REG_BLE_EM_RX_DESC_H_ +#define __REG_BLE_EM_RX_DESC_H_ + +#define REG_BLE_EM_RX_DESC_SIZE 12 + +#define REG_BLE_EM_RX_DESC_BASE_ADDR 0x00814000 + + +#endif // __REG_BLE_EM_RX_DESC_H_ + diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_ble_em_tx_audio_buffer.h b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_ble_em_tx_audio_buffer.h new file mode 100755 index 0000000..f4d8197 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_ble_em_tx_audio_buffer.h @@ -0,0 +1,10 @@ +#ifndef __REG_BLE_EM_TX_AUDIO_BUFFER_H_ +#define __REG_BLE_EM_TX_AUDIO_BUFFER_H_ + +#define REG_BLE_EM_TX_AUDIO_BUFFER_SIZE 64 + +#define REG_BLE_EM_TX_AUDIO_BUFFER_BASE_ADDR 0x00814000 + + +#endif // __REG_BLE_EM_TX_AUDIO_BUFFER_H_ + diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_ble_em_tx_buffer_cntl.h b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_ble_em_tx_buffer_cntl.h new file mode 100755 index 0000000..03dd5cb --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_ble_em_tx_buffer_cntl.h @@ -0,0 +1,10 @@ +#ifndef __REG_BLE_EM_TX_BUFFER_CNTL_H_ +#define __REG_BLE_EM_TX_BUFFER_CNTL_H_ + +#define REG_BLE_EM_TX_BUFFER_CNTL_SIZE 38 + +#define REG_BLE_EM_TX_BUFFER_CNTL_BASE_ADDR 0x00814000 + + +#endif // __REG_BLE_EM_TX_BUFFER_CNTL_H_ + diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_ble_em_tx_buffer_data.h b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_ble_em_tx_buffer_data.h new file mode 100755 index 0000000..a1f8fc7 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_ble_em_tx_buffer_data.h @@ -0,0 +1,10 @@ +#ifndef __REG_BLE_EM_TX_BUFFER_DATA_H_ +#define __REG_BLE_EM_TX_BUFFER_DATA_H_ + +#define REG_BLE_EM_TX_BUFFER_DATA_SIZE 260 + +#define REG_BLE_EM_TX_BUFFER_DATA_BASE_ADDR 0x00814000 + + +#endif // __REG_BLE_EM_TX_BUFFER_DATA_H_ + diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_ble_em_tx_desc.h b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_ble_em_tx_desc.h new file mode 100755 index 0000000..2291313 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_ble_em_tx_desc.h @@ -0,0 +1,10 @@ +#ifndef __REG_BLE_EM_TX_DESC_H_ +#define __REG_BLE_EM_TX_DESC_H_ + +#define REG_BLE_EM_TX_DESC_SIZE 8 + +#define REG_BLE_EM_TX_DESC_BASE_ADDR 0x00814000 + + +#endif // __REG_BLE_EM_TX_DESC_H_ + diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_ble_em_wpb.h b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_ble_em_wpb.h new file mode 100755 index 0000000..302273a --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_ble_em_wpb.h @@ -0,0 +1,10 @@ +#ifndef __REG_BLE_EM_WPB_H_ +#define __REG_BLE_EM_WPB_H_ + +#define REG_BLE_EM_WPB_SIZE 6 + +#define REG_BLE_EM_WPB_BASE_ADDR 0x00814000 + + +#endif // __REG_BLE_EM_WPB_H_ + diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_ble_em_wpv.h b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_ble_em_wpv.h new file mode 100755 index 0000000..07069ab --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_ble_em_wpv.h @@ -0,0 +1,10 @@ +#ifndef __REG_BLE_EM_WPV_H_ +#define __REG_BLE_EM_WPV_H_ + +#define REG_BLE_EM_WPV_SIZE 6 + +#define REG_BLE_EM_WPV_BASE_ADDR 0x00814000 + + +#endif // __REG_BLE_EM_WPV_H_ + diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_blecore.h b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_blecore.h new file mode 100755 index 0000000..02ee718 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_blecore.h @@ -0,0 +1,10 @@ +#ifndef __REG_BLECORE_H_ +#define __REG_BLECORE_H_ + +#define REG_BLECORE_SIZE 428 + +#define REG_BLECORE_BASE_ADDR 0x00810000 + + +#endif // __REG_BLECORE_H_ + diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_common_em_et.h b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_common_em_et.h new file mode 100755 index 0000000..090c8d0 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_common_em_et.h @@ -0,0 +1,11 @@ +#ifndef __REG_COMMON_EM_ET_BASE_H_ +#define __REG_COMMON_EM_ET_BASE_H_ + + +#define REG_COMMON_EM_ET_SIZE 4 + +#define REG_COMMON_EM_ET_BASE_ADDR 0x00814000 + + +#endif // __REG_COMMON_EM_ET_H_ + diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_intc.h b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_intc.h new file mode 100755 index 0000000..aee65b1 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_intc.h @@ -0,0 +1,10 @@ +#ifndef __REG_INTC_H_ +#define __REG_INTC_H_ + +#define REG_INTC_SIZE 32 + +#define REG_INTC_BASE_ADDR 0x00800048 + + +#endif // __REG_INTC_H_ + diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_modem.h b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_modem.h new file mode 100755 index 0000000..7f2c251 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_modem.h @@ -0,0 +1,10 @@ +#ifndef __REG_MODEM_H_ +#define __REG_MODEM_H_ + +#define REG_MODEM_SIZE 85 + +#define REG_MODEM_BASE_ADDR 0x00000000 + + +#endif // __REG_MODEM_H_ + diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_ripple.h b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_ripple.h new file mode 100755 index 0000000..3aad96e --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_ripple.h @@ -0,0 +1,10 @@ +#ifndef __REG_RIPPLE_H_ +#define __REG_RIPPLE_H_ + +#define REG_RIPPLE_SIZE 154 + +#define REG_RIPPLE_BASE_ADDR 0x00000000 + + +#endif // __REG_RIPPLE_H_ + diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_timer.h b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_timer.h new file mode 100755 index 0000000..6da9b14 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_timer.h @@ -0,0 +1,10 @@ +#ifndef __REG_TIMER_H_ +#define __REG_TIMER_H_ + +#define REG_TIMER_SIZE 16 + +#define REG_TIMER_BASE_ADDR 0x1000E000 + + +#endif // __REG_TIMER_H_ + diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_uart.h b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_uart.h new file mode 100755 index 0000000..1dbea35 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/_reg_uart.h @@ -0,0 +1,10 @@ +#ifndef __REG_UART_H_ +#define __REG_UART_H_ + +#define REG_UART_SIZE 36 + +#define REG_UART_BASE_ADDR 0x00806300 + + +#endif // __REG_UART_H_ + diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/reg_assert_mgr.h b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/reg_assert_mgr.h new file mode 100755 index 0000000..b14a979 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/reg_assert_mgr.h @@ -0,0 +1,273 @@ +#ifndef _REG_ASSERT_MGR_H_ +#define _REG_ASSERT_MGR_H_ + +#include +#include "_reg_assert_mgr.h" +#include "ble_compiler.h" +#include "architect.h" +#include "ble_reg_access.h" + +#define REG_ASSERT_MGR_COUNT 4 + +#define REG_ASSERT_MGR_DECODING_MASK 0x0000000F + +/** + * @brief ASSERT register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:08             txt_size   0x0
+ *     02               params   0
+ *     01                 warn   0
+ *     00                trigg   0
+ * 
+ */ +#define ASRT_ASSERT_ADDR 0x1000D000 +#define ASRT_ASSERT_OFFSET 0x00000000 +#define ASRT_ASSERT_INDEX 0x00000000 +#define ASRT_ASSERT_RESET 0x00000000 + +__INLINE uint32_t asrt_assert_get(void) +{ + return REG_PL_RD(ASRT_ASSERT_ADDR); +} + +__INLINE void asrt_assert_set(uint32_t value) +{ + REG_PL_WR(ASRT_ASSERT_ADDR, value); +} + +// field definitions +#define ASRT_TXT_SIZE_MASK ((uint32_t)0x0000FF00) +#define ASRT_TXT_SIZE_LSB 8 +#define ASRT_TXT_SIZE_WIDTH ((uint32_t)0x00000008) +#define ASRT_PARAMS_BIT ((uint32_t)0x00000004) +#define ASRT_PARAMS_POS 2 +#define ASRT_WARN_BIT ((uint32_t)0x00000002) +#define ASRT_WARN_POS 1 +#define ASRT_TRIGG_BIT ((uint32_t)0x00000001) +#define ASRT_TRIGG_POS 0 + +#define ASRT_TXT_SIZE_RST 0x0 +#define ASRT_PARAMS_RST 0x0 +#define ASRT_WARN_RST 0x0 +#define ASRT_TRIGG_RST 0x0 + +__INLINE void asrt_assert_pack(uint8_t txtsize, uint8_t params, uint8_t warn, uint8_t trigg) +{ + ASSERT_ERR((((uint32_t)txtsize << 8) & ~((uint32_t)0x0000FF00)) == 0); + ASSERT_ERR((((uint32_t)params << 2) & ~((uint32_t)0x00000004)) == 0); + ASSERT_ERR((((uint32_t)warn << 1) & ~((uint32_t)0x00000002)) == 0); + ASSERT_ERR((((uint32_t)trigg << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(ASRT_ASSERT_ADDR, ((uint32_t)txtsize << 8) | ((uint32_t)params << 2) | ((uint32_t)warn << 1) | ((uint32_t)trigg << 0)); +} + +__INLINE void asrt_assert_unpack(uint8_t* txtsize, uint8_t* params, uint8_t* warn, uint8_t* trigg) +{ + uint32_t localVal = REG_PL_RD(ASRT_ASSERT_ADDR); + + *txtsize = (localVal & ((uint32_t)0x0000FF00)) >> 8; + *params = (localVal & ((uint32_t)0x00000004)) >> 2; + *warn = (localVal & ((uint32_t)0x00000002)) >> 1; + *trigg = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +__INLINE uint8_t asrt_txt_size_getf(void) +{ + uint32_t localVal = REG_PL_RD(ASRT_ASSERT_ADDR); + return ((localVal & ((uint32_t)0x0000FF00)) >> 8); +} + +__INLINE void asrt_txt_size_setf(uint8_t txtsize) +{ + ASSERT_ERR((((uint32_t)txtsize << 8) & ~((uint32_t)0x0000FF00)) == 0); + REG_PL_WR(ASRT_ASSERT_ADDR, (REG_PL_RD(ASRT_ASSERT_ADDR) & ~((uint32_t)0x0000FF00)) | ((uint32_t)txtsize << 8)); +} + +__INLINE uint8_t asrt_params_getf(void) +{ + uint32_t localVal = REG_PL_RD(ASRT_ASSERT_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +__INLINE void asrt_params_setf(uint8_t params) +{ + ASSERT_ERR((((uint32_t)params << 2) & ~((uint32_t)0x00000004)) == 0); + REG_PL_WR(ASRT_ASSERT_ADDR, (REG_PL_RD(ASRT_ASSERT_ADDR) & ~((uint32_t)0x00000004)) | ((uint32_t)params << 2)); +} + +__INLINE void asrt_warn_setf(uint8_t warn) +{ + ASSERT_ERR((((uint32_t)warn << 1) & ~((uint32_t)0x00000002)) == 0); + REG_PL_WR(ASRT_ASSERT_ADDR, (REG_PL_RD(ASRT_ASSERT_ADDR) & ~((uint32_t)0x00000002)) | ((uint32_t)warn << 1)); +} + +__INLINE void asrt_trigg_setf(uint8_t trigg) +{ + ASSERT_ERR((((uint32_t)trigg << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(ASRT_ASSERT_ADDR, (REG_PL_RD(ASRT_ASSERT_ADDR) & ~((uint32_t)0x00000001)) | ((uint32_t)trigg << 0)); +} + +/** + * @brief PARAM register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:16               param2   0x0
+ *  15:00               param1   0x0
+ * 
+ */ +#define ASRT_PARAM_ADDR 0x1000D004 +#define ASRT_PARAM_OFFSET 0x00000004 +#define ASRT_PARAM_INDEX 0x00000001 +#define ASRT_PARAM_RESET 0x00000000 + +__INLINE uint32_t asrt_param_get(void) +{ + return REG_PL_RD(ASRT_PARAM_ADDR); +} + +__INLINE void asrt_param_set(uint32_t value) +{ + REG_PL_WR(ASRT_PARAM_ADDR, value); +} + +// field definitions +#define ASRT_PARAM_2_MASK ((uint32_t)0xFFFF0000) +#define ASRT_PARAM_2_LSB 16 +#define ASRT_PARAM_2_WIDTH ((uint32_t)0x00000010) +#define ASRT_PARAM_1_MASK ((uint32_t)0x0000FFFF) +#define ASRT_PARAM_1_LSB 0 +#define ASRT_PARAM_1_WIDTH ((uint32_t)0x00000010) + +#define ASRT_PARAM_2_RST 0x0 +#define ASRT_PARAM_1_RST 0x0 + +__INLINE void asrt_param_pack(uint16_t param2, uint16_t param1) +{ + ASSERT_ERR((((uint32_t)param2 << 16) & ~((uint32_t)0xFFFF0000)) == 0); + ASSERT_ERR((((uint32_t)param1 << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_PL_WR(ASRT_PARAM_ADDR, ((uint32_t)param2 << 16) | ((uint32_t)param1 << 0)); +} + +__INLINE void asrt_param_unpack(uint16_t* param2, uint16_t* param1) +{ + uint32_t localVal = REG_PL_RD(ASRT_PARAM_ADDR); + + *param2 = (localVal & ((uint32_t)0xFFFF0000)) >> 16; + *param1 = (localVal & ((uint32_t)0x0000FFFF)) >> 0; +} + +__INLINE uint16_t asrt_param_2_getf(void) +{ + uint32_t localVal = REG_PL_RD(ASRT_PARAM_ADDR); + return ((localVal & ((uint32_t)0xFFFF0000)) >> 16); +} + +__INLINE void asrt_param_2_setf(uint16_t param2) +{ + ASSERT_ERR((((uint32_t)param2 << 16) & ~((uint32_t)0xFFFF0000)) == 0); + REG_PL_WR(ASRT_PARAM_ADDR, (REG_PL_RD(ASRT_PARAM_ADDR) & ~((uint32_t)0xFFFF0000)) | ((uint32_t)param2 << 16)); +} + +__INLINE uint16_t asrt_param_1_getf(void) +{ + uint32_t localVal = REG_PL_RD(ASRT_PARAM_ADDR); + return ((localVal & ((uint32_t)0x0000FFFF)) >> 0); +} + +__INLINE void asrt_param_1_setf(uint16_t param1) +{ + ASSERT_ERR((((uint32_t)param1 << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_PL_WR(ASRT_PARAM_ADDR, (REG_PL_RD(ASRT_PARAM_ADDR) & ~((uint32_t)0x0000FFFF)) | ((uint32_t)param1 << 0)); +} + +/** + * @brief LINE register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00                 line   0x0
+ * 
+ */ +#define ASRT_LINE_ADDR 0x1000D008 +#define ASRT_LINE_OFFSET 0x00000008 +#define ASRT_LINE_INDEX 0x00000002 +#define ASRT_LINE_RESET 0x00000000 + +__INLINE uint32_t asrt_line_get(void) +{ + return REG_PL_RD(ASRT_LINE_ADDR); +} + +__INLINE void asrt_line_set(uint32_t value) +{ + REG_PL_WR(ASRT_LINE_ADDR, value); +} + +// field definitions +#define ASRT_LINE_MASK ((uint32_t)0xFFFFFFFF) +#define ASRT_LINE_LSB 0 +#define ASRT_LINE_WIDTH ((uint32_t)0x00000020) + +#define ASRT_LINE_RST 0x0 + +__INLINE uint32_t asrt_line_getf(void) +{ + uint32_t localVal = REG_PL_RD(ASRT_LINE_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void asrt_line_setf(uint32_t line) +{ + ASSERT_ERR((((uint32_t)line << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(ASRT_LINE_ADDR, (uint32_t)line << 0); +} + +/** + * @brief TEXT register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00                 addr   0x0
+ * 
+ */ +#define ASRT_TEXT_ADDR 0x1000D00C +#define ASRT_TEXT_OFFSET 0x0000000C +#define ASRT_TEXT_INDEX 0x00000003 +#define ASRT_TEXT_RESET 0x00000000 + +__INLINE uint32_t asrt_text_get(void) +{ + return REG_PL_RD(ASRT_TEXT_ADDR); +} + +__INLINE void asrt_text_set(uint32_t value) +{ + REG_PL_WR(ASRT_TEXT_ADDR, value); +} + +// field definitions +#define ASRT_ADDR_MASK ((uint32_t)0xFFFFFFFF) +#define ASRT_ADDR_LSB 0 +#define ASRT_ADDR_WIDTH ((uint32_t)0x00000020) + +#define ASRT_ADDR_RST 0x0 + +__INLINE uint32_t asrt_addr_getf(void) +{ + uint32_t localVal = REG_PL_RD(ASRT_TEXT_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void asrt_addr_setf(uint32_t addr) +{ + ASSERT_ERR((((uint32_t)addr << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(ASRT_TEXT_ADDR, (uint32_t)addr << 0); +} + + +#endif // _REG_ASSERT_MGR_H_ + diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/reg_ble_em_cs.h b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/reg_ble_em_cs.h new file mode 100755 index 0000000..92e6618 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/reg_ble_em_cs.h @@ -0,0 +1,2625 @@ +#ifndef _REG_BLE_EM_CS_H_ +#define _REG_BLE_EM_CS_H_ + +#include +#include "_reg_ble_em_cs.h" +#include "ble_compiler.h" +#include "architect.h" +#include "em_map.h" +#include "ble_reg_access.h" + +#define REG_BLE_EM_CS_COUNT 46 + +#define REG_BLE_EM_CS_DECODING_MASK 0x0000007F + +#define REG_BLE_EM_CS_ADDR_GET(idx) (EM_BLE_CS_OFFSET + (idx) * REG_BLE_EM_CS_SIZE) + +/** + * @brief CNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:12                  PTI   0x0
+ *     10             TXBSY_EN   0
+ *     09             RXBSY_EN   0
+ *     08              DNABORT   0
+ *  04:00               FORMAT   0x0
+ * 
+ */ +#define BLE_CNTL_ADDR (0x00814000 + EM_BLE_CS_OFFSET) +#define BLE_CNTL_INDEX 0x00000000 +#define BLE_CNTL_RESET 0x00000000 + +__INLINE uint16_t ble_cntl_get(int elt_idx) +{ + return EM_BLE_RD(BLE_CNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); +} + +__INLINE void ble_cntl_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_CNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, value); +} + +// field definitions +#define BLE_PTI_MASK ((uint16_t)0x0000F000) +#define BLE_PTI_LSB 12 +#define BLE_PTI_WIDTH ((uint16_t)0x00000004) +#define BLE_TXBSY_EN_BIT ((uint16_t)0x00000400) +#define BLE_TXBSY_EN_POS 10 +#define BLE_RXBSY_EN_BIT ((uint16_t)0x00000200) +#define BLE_RXBSY_EN_POS 9 +#define BLE_DNABORT_BIT ((uint16_t)0x00000100) +#define BLE_DNABORT_POS 8 +#define BLE_FORMAT_MASK ((uint16_t)0x0000001F) +#define BLE_FORMAT_LSB 0 +#define BLE_FORMAT_WIDTH ((uint16_t)0x00000005) + +#define BLE_PTI_RST 0x0 +#define BLE_TXBSY_EN_RST 0x0 +#define BLE_RXBSY_EN_RST 0x0 +#define BLE_DNABORT_RST 0x0 +#define BLE_FORMAT_RST 0x0 + +__INLINE void ble_cntl_pack(int elt_idx, uint8_t pti, uint8_t txbsyen, uint8_t rxbsyen, uint8_t dnabort, uint8_t format) +{ + ASSERT_ERR((((uint16_t)pti << 12) & ~((uint16_t)0x0000F000)) == 0); + ASSERT_ERR((((uint16_t)txbsyen << 10) & ~((uint16_t)0x00000400)) == 0); + ASSERT_ERR((((uint16_t)rxbsyen << 9) & ~((uint16_t)0x00000200)) == 0); + ASSERT_ERR((((uint16_t)dnabort << 8) & ~((uint16_t)0x00000100)) == 0); + ASSERT_ERR((((uint16_t)format << 0) & ~((uint16_t)0x0000001F)) == 0); + EM_BLE_WR(BLE_CNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, ((uint16_t)pti << 12) | ((uint16_t)txbsyen << 10) | ((uint16_t)rxbsyen << 9) | ((uint16_t)dnabort << 8) | ((uint16_t)format << 0)); +} + +__INLINE void ble_cntl_unpack(int elt_idx, uint8_t* pti, uint8_t* txbsyen, uint8_t* rxbsyen, uint8_t* dnabort, uint8_t* format) +{ + uint16_t localVal = EM_BLE_RD(BLE_CNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + + *pti = (localVal & ((uint16_t)0x0000F000)) >> 12; + *txbsyen = (localVal & ((uint16_t)0x00000400)) >> 10; + *rxbsyen = (localVal & ((uint16_t)0x00000200)) >> 9; + *dnabort = (localVal & ((uint16_t)0x00000100)) >> 8; + *format = (localVal & ((uint16_t)0x0000001F)) >> 0; +} + +__INLINE uint8_t ble_pti_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_CNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + return ((localVal & ((uint16_t)0x0000F000)) >> 12); +} + +__INLINE void ble_pti_setf(int elt_idx, uint8_t pti) +{ + ASSERT_ERR((((uint16_t)pti << 12) & ~((uint16_t)0x0000F000)) == 0); + EM_BLE_WR(BLE_CNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (EM_BLE_RD(BLE_CNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE) & ~((uint16_t)0x0000F000)) | ((uint16_t)pti << 12)); +} + +__INLINE uint8_t ble_txbsy_en_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_CNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + return ((localVal & ((uint16_t)0x00000400)) >> 10); +} + +__INLINE void ble_txbsy_en_setf(int elt_idx, uint8_t txbsyen) +{ + ASSERT_ERR((((uint16_t)txbsyen << 10) & ~((uint16_t)0x00000400)) == 0); + EM_BLE_WR(BLE_CNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (EM_BLE_RD(BLE_CNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE) & ~((uint16_t)0x00000400)) | ((uint16_t)txbsyen << 10)); +} + +__INLINE uint8_t ble_rxbsy_en_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_CNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + return ((localVal & ((uint16_t)0x00000200)) >> 9); +} + +__INLINE void ble_rxbsy_en_setf(int elt_idx, uint8_t rxbsyen) +{ + ASSERT_ERR((((uint16_t)rxbsyen << 9) & ~((uint16_t)0x00000200)) == 0); + EM_BLE_WR(BLE_CNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (EM_BLE_RD(BLE_CNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE) & ~((uint16_t)0x00000200)) | ((uint16_t)rxbsyen << 9)); +} + +__INLINE uint8_t ble_dnabort_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_CNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + return ((localVal & ((uint16_t)0x00000100)) >> 8); +} + +__INLINE void ble_dnabort_setf(int elt_idx, uint8_t dnabort) +{ + ASSERT_ERR((((uint16_t)dnabort << 8) & ~((uint16_t)0x00000100)) == 0); + EM_BLE_WR(BLE_CNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (EM_BLE_RD(BLE_CNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE) & ~((uint16_t)0x00000100)) | ((uint16_t)dnabort << 8)); +} + +__INLINE uint8_t ble_format_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_CNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + return ((localVal & ((uint16_t)0x0000001F)) >> 0); +} + +__INLINE void ble_format_setf(int elt_idx, uint8_t format) +{ + ASSERT_ERR((((uint16_t)format << 0) & ~((uint16_t)0x0000001F)) == 0); + EM_BLE_WR(BLE_CNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (EM_BLE_RD(BLE_CNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE) & ~((uint16_t)0x0000001F)) | ((uint16_t)format << 0)); +} + +/** + * @brief FCNTOFFSET register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  09:00           FCNTOFFSET   0x0
+ * 
+ */ +#define BLE_FCNTOFFSET_ADDR (0x00814002 + EM_BLE_CS_OFFSET) +#define BLE_FCNTOFFSET_INDEX 0x00000001 +#define BLE_FCNTOFFSET_RESET 0x00000000 + +__INLINE uint16_t ble_fcntoffset_get(int elt_idx) +{ + return EM_BLE_RD(BLE_FCNTOFFSET_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); +} + +__INLINE void ble_fcntoffset_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_FCNTOFFSET_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, value); +} + +// field definitions +#define BLE_FCNTOFFSET_MASK ((uint16_t)0x000003FF) +#define BLE_FCNTOFFSET_LSB 0 +#define BLE_FCNTOFFSET_WIDTH ((uint16_t)0x0000000A) + +#define BLE_FCNTOFFSET_RST 0x0 + +__INLINE uint16_t ble_fcntoffset_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_FCNTOFFSET_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + ASSERT_ERR((localVal & ~((uint16_t)0x000003FF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_fcntoffset_setf(int elt_idx, uint16_t fcntoffset) +{ + ASSERT_ERR((((uint16_t)fcntoffset << 0) & ~((uint16_t)0x000003FF)) == 0); + EM_BLE_WR(BLE_FCNTOFFSET_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (uint16_t)fcntoffset << 0); +} + +/** + * @brief LINK register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     11        NULLRXLLIDFLT   0
+ *     10           CRYPT_MODE   0
+ *     09           TXCRYPT_EN   0
+ *     08           RXCRYPT_EN   0
+ *  04:00              LINKLBL   0x0
+ * 
+ */ +#define BLE_LINK_ADDR (0x00814004 + EM_BLE_CS_OFFSET) +#define BLE_LINK_INDEX 0x00000002 +#define BLE_LINK_RESET 0x00000000 + +__INLINE uint16_t ble_link_get(int elt_idx) +{ + return EM_BLE_RD(BLE_LINK_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); +} + +__INLINE void ble_link_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_LINK_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, value); +} + +// field definitions +#define BLE_NULLRXLLIDFLT_BIT ((uint16_t)0x00000800) +#define BLE_NULLRXLLIDFLT_POS 11 +#define BLE_CRYPT_MODE_BIT ((uint16_t)0x00000400) +#define BLE_CRYPT_MODE_POS 10 +#define BLE_TXCRYPT_EN_BIT ((uint16_t)0x00000200) +#define BLE_TXCRYPT_EN_POS 9 +#define BLE_RXCRYPT_EN_BIT ((uint16_t)0x00000100) +#define BLE_RXCRYPT_EN_POS 8 +#define BLE_LINKLBL_MASK ((uint16_t)0x0000001F) +#define BLE_LINKLBL_LSB 0 +#define BLE_LINKLBL_WIDTH ((uint16_t)0x00000005) + +#define BLE_NULLRXLLIDFLT_RST 0x0 +#define BLE_CRYPT_MODE_RST 0x0 +#define BLE_TXCRYPT_EN_RST 0x0 +#define BLE_RXCRYPT_EN_RST 0x0 +#define BLE_LINKLBL_RST 0x0 + +__INLINE void ble_link_pack(int elt_idx, uint8_t nullrxllidflt, uint8_t cryptmode, uint8_t txcrypten, uint8_t rxcrypten, uint8_t linklbl) +{ + ASSERT_ERR((((uint16_t)nullrxllidflt << 11) & ~((uint16_t)0x00000800)) == 0); + ASSERT_ERR((((uint16_t)cryptmode << 10) & ~((uint16_t)0x00000400)) == 0); + ASSERT_ERR((((uint16_t)txcrypten << 9) & ~((uint16_t)0x00000200)) == 0); + ASSERT_ERR((((uint16_t)rxcrypten << 8) & ~((uint16_t)0x00000100)) == 0); + ASSERT_ERR((((uint16_t)linklbl << 0) & ~((uint16_t)0x0000001F)) == 0); + EM_BLE_WR(BLE_LINK_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, ((uint16_t)nullrxllidflt << 11) | ((uint16_t)cryptmode << 10) | ((uint16_t)txcrypten << 9) | ((uint16_t)rxcrypten << 8) | ((uint16_t)linklbl << 0)); +} + +__INLINE void ble_link_unpack(int elt_idx, uint8_t* nullrxllidflt, uint8_t* cryptmode, uint8_t* txcrypten, uint8_t* rxcrypten, uint8_t* linklbl) +{ + uint16_t localVal = EM_BLE_RD(BLE_LINK_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + + *nullrxllidflt = (localVal & ((uint16_t)0x00000800)) >> 11; + *cryptmode = (localVal & ((uint16_t)0x00000400)) >> 10; + *txcrypten = (localVal & ((uint16_t)0x00000200)) >> 9; + *rxcrypten = (localVal & ((uint16_t)0x00000100)) >> 8; + *linklbl = (localVal & ((uint16_t)0x0000001F)) >> 0; +} + +__INLINE uint8_t ble_nullrxllidflt_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_LINK_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + return ((localVal & ((uint16_t)0x00000800)) >> 11); +} + +__INLINE void ble_nullrxllidflt_setf(int elt_idx, uint8_t nullrxllidflt) +{ + ASSERT_ERR((((uint16_t)nullrxllidflt << 11) & ~((uint16_t)0x00000800)) == 0); + EM_BLE_WR(BLE_LINK_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (EM_BLE_RD(BLE_LINK_ADDR + elt_idx * REG_BLE_EM_CS_SIZE) & ~((uint16_t)0x00000800)) | ((uint16_t)nullrxllidflt << 11)); +} + +__INLINE uint8_t ble_crypt_mode_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_LINK_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + return ((localVal & ((uint16_t)0x00000400)) >> 10); +} + +__INLINE void ble_crypt_mode_setf(int elt_idx, uint8_t cryptmode) +{ + ASSERT_ERR((((uint16_t)cryptmode << 10) & ~((uint16_t)0x00000400)) == 0); + EM_BLE_WR(BLE_LINK_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (EM_BLE_RD(BLE_LINK_ADDR + elt_idx * REG_BLE_EM_CS_SIZE) & ~((uint16_t)0x00000400)) | ((uint16_t)cryptmode << 10)); +} + +__INLINE uint8_t ble_txcrypt_en_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_LINK_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + return ((localVal & ((uint16_t)0x00000200)) >> 9); +} + +__INLINE void ble_txcrypt_en_setf(int elt_idx, uint8_t txcrypten) +{ + ASSERT_ERR((((uint16_t)txcrypten << 9) & ~((uint16_t)0x00000200)) == 0); + EM_BLE_WR(BLE_LINK_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (EM_BLE_RD(BLE_LINK_ADDR + elt_idx * REG_BLE_EM_CS_SIZE) & ~((uint16_t)0x00000200)) | ((uint16_t)txcrypten << 9)); +} + +__INLINE uint8_t ble_rxcrypt_en_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_LINK_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + return ((localVal & ((uint16_t)0x00000100)) >> 8); +} + +__INLINE void ble_rxcrypt_en_setf(int elt_idx, uint8_t rxcrypten) +{ + ASSERT_ERR((((uint16_t)rxcrypten << 8) & ~((uint16_t)0x00000100)) == 0); + EM_BLE_WR(BLE_LINK_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (EM_BLE_RD(BLE_LINK_ADDR + elt_idx * REG_BLE_EM_CS_SIZE) & ~((uint16_t)0x00000100)) | ((uint16_t)rxcrypten << 8)); +} + +__INLINE uint8_t ble_linklbl_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_LINK_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + return ((localVal & ((uint16_t)0x0000001F)) >> 0); +} + +__INLINE void ble_linklbl_setf(int elt_idx, uint8_t linklbl) +{ + ASSERT_ERR((((uint16_t)linklbl << 0) & ~((uint16_t)0x0000001F)) == 0); + EM_BLE_WR(BLE_LINK_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (EM_BLE_RD(BLE_LINK_ADDR + elt_idx * REG_BLE_EM_CS_SIZE) & ~((uint16_t)0x0000001F)) | ((uint16_t)linklbl << 0)); +} + +/** + * @brief THRCNTL_RATECNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:12                RXTHR   0x0
+ *  03:02               RXRATE   0x0
+ *  01:00               TXRATE   0x0
+ * 
+ */ +#define BLE_THRCNTL_RATECNTL_ADDR (0x00814006 + EM_BLE_CS_OFFSET) +#define BLE_THRCNTL_RATECNTL_INDEX 0x00000003 +#define BLE_THRCNTL_RATECNTL_RESET 0x00000000 + +__INLINE uint16_t ble_thrcntl_ratecntl_get(int elt_idx) +{ + return EM_BLE_RD(BLE_THRCNTL_RATECNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); +} + +__INLINE void ble_thrcntl_ratecntl_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_THRCNTL_RATECNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, value); +} + +// field definitions +#define BLE_RXTHR_MASK ((uint16_t)0x0000F000) +#define BLE_RXTHR_LSB 12 +#define BLE_RXTHR_WIDTH ((uint16_t)0x00000004) +#define BLE_RXRATE_MASK ((uint16_t)0x0000000C) +#define BLE_RXRATE_LSB 2 +#define BLE_RXRATE_WIDTH ((uint16_t)0x00000002) +#define BLE_TXRATE_MASK ((uint16_t)0x00000003) +#define BLE_TXRATE_LSB 0 +#define BLE_TXRATE_WIDTH ((uint16_t)0x00000002) + +#define BLE_RXTHR_RST 0x0 +#define BLE_RXRATE_RST 0x0 +#define BLE_TXRATE_RST 0x0 + +__INLINE void ble_thrcntl_ratecntl_pack(int elt_idx, uint8_t rxthr, uint8_t rxrate, uint8_t txrate) +{ + ASSERT_ERR((((uint16_t)rxthr << 12) & ~((uint16_t)0x0000F000)) == 0); + ASSERT_ERR((((uint16_t)rxrate << 2) & ~((uint16_t)0x0000000C)) == 0); + ASSERT_ERR((((uint16_t)txrate << 0) & ~((uint16_t)0x00000003)) == 0); + EM_BLE_WR(BLE_THRCNTL_RATECNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, ((uint16_t)rxthr << 12) | ((uint16_t)rxrate << 2) | ((uint16_t)txrate << 0)); +} + +__INLINE void ble_thrcntl_ratecntl_unpack(int elt_idx, uint8_t* rxthr, uint8_t* rxrate, uint8_t* txrate) +{ + uint16_t localVal = EM_BLE_RD(BLE_THRCNTL_RATECNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + + *rxthr = (localVal & ((uint16_t)0x0000F000)) >> 12; + *rxrate = (localVal & ((uint16_t)0x0000000C)) >> 2; + *txrate = (localVal & ((uint16_t)0x00000003)) >> 0; +} + +__INLINE uint8_t ble_rxthr_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_THRCNTL_RATECNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + return ((localVal & ((uint16_t)0x0000F000)) >> 12); +} + +__INLINE void ble_rxthr_setf(int elt_idx, uint8_t rxthr) +{ + ASSERT_ERR((((uint16_t)rxthr << 12) & ~((uint16_t)0x0000F000)) == 0); + EM_BLE_WR(BLE_THRCNTL_RATECNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (EM_BLE_RD(BLE_THRCNTL_RATECNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE) & ~((uint16_t)0x0000F000)) | ((uint16_t)rxthr << 12)); +} + +__INLINE uint8_t ble_rxrate_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_THRCNTL_RATECNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + return ((localVal & ((uint16_t)0x0000000C)) >> 2); +} + +__INLINE void ble_rxrate_setf(int elt_idx, uint8_t rxrate) +{ + ASSERT_ERR((((uint16_t)rxrate << 2) & ~((uint16_t)0x0000000C)) == 0); + EM_BLE_WR(BLE_THRCNTL_RATECNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (EM_BLE_RD(BLE_THRCNTL_RATECNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE) & ~((uint16_t)0x0000000C)) | ((uint16_t)rxrate << 2)); +} + +__INLINE uint8_t ble_txrate_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_THRCNTL_RATECNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + return ((localVal & ((uint16_t)0x00000003)) >> 0); +} + +__INLINE void ble_txrate_setf(int elt_idx, uint8_t txrate) +{ + ASSERT_ERR((((uint16_t)txrate << 0) & ~((uint16_t)0x00000003)) == 0); + EM_BLE_WR(BLE_THRCNTL_RATECNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (EM_BLE_RD(BLE_THRCNTL_RATECNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE) & ~((uint16_t)0x00000003)) | ((uint16_t)txrate << 0)); +} + +/** + * @brief SYNCWL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00            SYNCWORDL   0x0
+ * 
+ */ +#define BLE_SYNCWL_ADDR (0x00814008 + EM_BLE_CS_OFFSET) +#define BLE_SYNCWL_INDEX 0x00000004 +#define BLE_SYNCWL_RESET 0x00000000 + +__INLINE uint16_t ble_syncwl_get(int elt_idx) +{ + return EM_BLE_RD(BLE_SYNCWL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); +} + +__INLINE void ble_syncwl_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_SYNCWL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, value); +} + +// field definitions +#define BLE_SYNCWORDL_MASK ((uint16_t)0x0000FFFF) +#define BLE_SYNCWORDL_LSB 0 +#define BLE_SYNCWORDL_WIDTH ((uint16_t)0x00000010) + +#define BLE_SYNCWORDL_RST 0x0 + +__INLINE uint16_t ble_syncwordl_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_SYNCWL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_syncwordl_setf(int elt_idx, uint16_t syncwordl) +{ + ASSERT_ERR((((uint16_t)syncwordl << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(BLE_SYNCWL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (uint16_t)syncwordl << 0); +} + +/** + * @brief SYNCWH register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00            SYNCWORDH   0x0
+ * 
+ */ +#define BLE_SYNCWH_ADDR (0x0081400A + EM_BLE_CS_OFFSET) +#define BLE_SYNCWH_INDEX 0x00000005 +#define BLE_SYNCWH_RESET 0x00000000 + +__INLINE uint16_t ble_syncwh_get(int elt_idx) +{ + return EM_BLE_RD(BLE_SYNCWH_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); +} + +__INLINE void ble_syncwh_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_SYNCWH_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, value); +} + +// field definitions +#define BLE_SYNCWORDH_MASK ((uint16_t)0x0000FFFF) +#define BLE_SYNCWORDH_LSB 0 +#define BLE_SYNCWORDH_WIDTH ((uint16_t)0x00000010) + +#define BLE_SYNCWORDH_RST 0x0 + +__INLINE uint16_t ble_syncwordh_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_SYNCWH_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_syncwordh_setf(int elt_idx, uint16_t syncwordh) +{ + ASSERT_ERR((((uint16_t)syncwordh << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(BLE_SYNCWH_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (uint16_t)syncwordh << 0); +} + +/** + * @brief CRCINIT0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00             CRCINIT0   0x0
+ * 
+ */ +#define BLE_CRCINIT0_ADDR (0x0081400C + EM_BLE_CS_OFFSET) +#define BLE_CRCINIT0_INDEX 0x00000006 +#define BLE_CRCINIT0_RESET 0x00000000 + +__INLINE uint16_t ble_crcinit0_get(int elt_idx) +{ + return EM_BLE_RD(BLE_CRCINIT0_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); +} + +__INLINE void ble_crcinit0_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_CRCINIT0_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, value); +} + +// field definitions +#define BLE_CRCINIT0_MASK ((uint16_t)0x0000FFFF) +#define BLE_CRCINIT0_LSB 0 +#define BLE_CRCINIT0_WIDTH ((uint16_t)0x00000010) + +#define BLE_CRCINIT0_RST 0x0 + +__INLINE uint16_t ble_crcinit0_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_CRCINIT0_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_crcinit0_setf(int elt_idx, uint16_t crcinit0) +{ + ASSERT_ERR((((uint16_t)crcinit0 << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(BLE_CRCINIT0_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (uint16_t)crcinit0 << 0); +} + +/** + * @brief CRCINIT1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  07:00             CRCINIT1   0x0
+ * 
+ */ +#define BLE_CRCINIT1_ADDR (0x0081400E + EM_BLE_CS_OFFSET) +#define BLE_CRCINIT1_INDEX 0x00000007 +#define BLE_CRCINIT1_RESET 0x00000000 + +__INLINE uint16_t ble_crcinit1_get(int elt_idx) +{ + return EM_BLE_RD(BLE_CRCINIT1_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); +} + +__INLINE void ble_crcinit1_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_CRCINIT1_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, value); +} + +// field definitions +#define BLE_CRCINIT1_MASK ((uint16_t)0x000000FF) +#define BLE_CRCINIT1_LSB 0 +#define BLE_CRCINIT1_WIDTH ((uint16_t)0x00000008) + +#define BLE_CRCINIT1_RST 0x0 + +__INLINE uint8_t ble_crcinit1_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_CRCINIT1_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + ASSERT_ERR((localVal & ~((uint16_t)0x000000FF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_crcinit1_setf(int elt_idx, uint8_t crcinit1) +{ + ASSERT_ERR((((uint16_t)crcinit1 << 0) & ~((uint16_t)0x000000FF)) == 0); + EM_BLE_WR(BLE_CRCINIT1_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (uint16_t)crcinit1 << 0); +} + +/** + * @brief FILTPOL_RALCNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:08        FILTER_POLICY   0x0
+ *     02        LOCAL_RPA_SEL   0
+ *     01             RAL_MODE   0
+ *     00               RAL_EN   0
+ * 
+ */ +#define BLE_FILTPOL_RALCNTL_ADDR (0x00814010 + EM_BLE_CS_OFFSET) +#define BLE_FILTPOL_RALCNTL_INDEX 0x00000008 +#define BLE_FILTPOL_RALCNTL_RESET 0x00000000 + +__INLINE uint16_t ble_filtpol_ralcntl_get(int elt_idx) +{ + return EM_BLE_RD(BLE_FILTPOL_RALCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); +} + +__INLINE void ble_filtpol_ralcntl_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_FILTPOL_RALCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, value); +} + +// field definitions +#define BLE_FILTER_POLICY_MASK ((uint16_t)0x0000FF00) +#define BLE_FILTER_POLICY_LSB 8 +#define BLE_FILTER_POLICY_WIDTH ((uint16_t)0x00000008) +#define BLE_LOCAL_RPA_SEL_BIT ((uint16_t)0x00000004) +#define BLE_LOCAL_RPA_SEL_POS 2 +#define BLE_RAL_MODE_BIT ((uint16_t)0x00000002) +#define BLE_RAL_MODE_POS 1 +#define BLE_RAL_EN_BIT ((uint16_t)0x00000001) +#define BLE_RAL_EN_POS 0 + +#define BLE_FILTER_POLICY_RST 0x0 +#define BLE_LOCAL_RPA_SEL_RST 0x0 +#define BLE_RAL_MODE_RST 0x0 +#define BLE_RAL_EN_RST 0x0 + +__INLINE void ble_filtpol_ralcntl_pack(int elt_idx, uint8_t filterpolicy, uint8_t localrpasel, uint8_t ralmode, uint8_t ralen) +{ + ASSERT_ERR((((uint16_t)filterpolicy << 8) & ~((uint16_t)0x0000FF00)) == 0); + ASSERT_ERR((((uint16_t)localrpasel << 2) & ~((uint16_t)0x00000004)) == 0); + ASSERT_ERR((((uint16_t)ralmode << 1) & ~((uint16_t)0x00000002)) == 0); + ASSERT_ERR((((uint16_t)ralen << 0) & ~((uint16_t)0x00000001)) == 0); + EM_BLE_WR(BLE_FILTPOL_RALCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, ((uint16_t)filterpolicy << 8) | ((uint16_t)localrpasel << 2) | ((uint16_t)ralmode << 1) | ((uint16_t)ralen << 0)); +} + +__INLINE void ble_filtpol_ralcntl_unpack(int elt_idx, uint8_t* filterpolicy, uint8_t* localrpasel, uint8_t* ralmode, uint8_t* ralen) +{ + uint16_t localVal = EM_BLE_RD(BLE_FILTPOL_RALCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + + *filterpolicy = (localVal & ((uint16_t)0x0000FF00)) >> 8; + *localrpasel = (localVal & ((uint16_t)0x00000004)) >> 2; + *ralmode = (localVal & ((uint16_t)0x00000002)) >> 1; + *ralen = (localVal & ((uint16_t)0x00000001)) >> 0; +} + +__INLINE uint8_t ble_filter_policy_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_FILTPOL_RALCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + return ((localVal & ((uint16_t)0x0000FF00)) >> 8); +} + +__INLINE void ble_filter_policy_setf(int elt_idx, uint8_t filterpolicy) +{ + ASSERT_ERR((((uint16_t)filterpolicy << 8) & ~((uint16_t)0x0000FF00)) == 0); + EM_BLE_WR(BLE_FILTPOL_RALCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (EM_BLE_RD(BLE_FILTPOL_RALCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE) & ~((uint16_t)0x0000FF00)) | ((uint16_t)filterpolicy << 8)); +} + +__INLINE uint8_t ble_local_rpa_sel_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_FILTPOL_RALCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + return ((localVal & ((uint16_t)0x00000004)) >> 2); +} + +__INLINE void ble_local_rpa_sel_setf(int elt_idx, uint8_t localrpasel) +{ + ASSERT_ERR((((uint16_t)localrpasel << 2) & ~((uint16_t)0x00000004)) == 0); + EM_BLE_WR(BLE_FILTPOL_RALCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (EM_BLE_RD(BLE_FILTPOL_RALCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE) & ~((uint16_t)0x00000004)) | ((uint16_t)localrpasel << 2)); +} + +__INLINE uint8_t ble_ral_mode_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_FILTPOL_RALCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + return ((localVal & ((uint16_t)0x00000002)) >> 1); +} + +__INLINE void ble_ral_mode_setf(int elt_idx, uint8_t ralmode) +{ + ASSERT_ERR((((uint16_t)ralmode << 1) & ~((uint16_t)0x00000002)) == 0); + EM_BLE_WR(BLE_FILTPOL_RALCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (EM_BLE_RD(BLE_FILTPOL_RALCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE) & ~((uint16_t)0x00000002)) | ((uint16_t)ralmode << 1)); +} + +__INLINE uint8_t ble_ral_en_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_FILTPOL_RALCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + return ((localVal & ((uint16_t)0x00000001)) >> 0); +} + +__INLINE void ble_ral_en_setf(int elt_idx, uint8_t ralen) +{ + ASSERT_ERR((((uint16_t)ralen << 0) & ~((uint16_t)0x00000001)) == 0); + EM_BLE_WR(BLE_FILTPOL_RALCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (EM_BLE_RD(BLE_FILTPOL_RALCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE) & ~((uint16_t)0x00000001)) | ((uint16_t)ralen << 0)); +} + +/** + * @brief HOPCNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     15                FH_EN   0
+ *  12:08              HOP_INT   0x0
+ *  05:00               CH_IDX   0x0
+ * 
+ */ +#define BLE_HOPCNTL_ADDR (0x00814012 + EM_BLE_CS_OFFSET) +#define BLE_HOPCNTL_INDEX 0x00000009 +#define BLE_HOPCNTL_RESET 0x00000000 + +__INLINE uint16_t ble_hopcntl_get(int elt_idx) +{ + return EM_BLE_RD(BLE_HOPCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); +} + +__INLINE void ble_hopcntl_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_HOPCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, value); +} + +// field definitions +#define BLE_FH_EN_BIT ((uint16_t)0x00008000) +#define BLE_FH_EN_POS 15 +#define BLE_HOP_INT_MASK ((uint16_t)0x00001F00) +#define BLE_HOP_INT_LSB 8 +#define BLE_HOP_INT_WIDTH ((uint16_t)0x00000005) +#define BLE_CH_IDX_MASK ((uint16_t)0x0000003F) +#define BLE_CH_IDX_LSB 0 +#define BLE_CH_IDX_WIDTH ((uint16_t)0x00000006) + +#define BLE_FH_EN_RST 0x0 +#define BLE_HOP_INT_RST 0x0 +#define BLE_CH_IDX_RST 0x0 + +__INLINE void ble_hopcntl_pack(int elt_idx, uint8_t fhen, uint8_t hopint, uint8_t chidx) +{ + ASSERT_ERR((((uint16_t)fhen << 15) & ~((uint16_t)0x00008000)) == 0); + ASSERT_ERR((((uint16_t)hopint << 8) & ~((uint16_t)0x00001F00)) == 0); + ASSERT_ERR((((uint16_t)chidx << 0) & ~((uint16_t)0x0000003F)) == 0); + EM_BLE_WR(BLE_HOPCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, ((uint16_t)fhen << 15) | ((uint16_t)hopint << 8) | ((uint16_t)chidx << 0)); +} + +__INLINE void ble_hopcntl_unpack(int elt_idx, uint8_t* fhen, uint8_t* hopint, uint8_t* chidx) +{ + uint16_t localVal = EM_BLE_RD(BLE_HOPCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + + *fhen = (localVal & ((uint16_t)0x00008000)) >> 15; + *hopint = (localVal & ((uint16_t)0x00001F00)) >> 8; + *chidx = (localVal & ((uint16_t)0x0000003F)) >> 0; +} + +__INLINE uint8_t ble_fh_en_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_HOPCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + return ((localVal & ((uint16_t)0x00008000)) >> 15); +} + +__INLINE void ble_fh_en_setf(int elt_idx, uint8_t fhen) +{ + ASSERT_ERR((((uint16_t)fhen << 15) & ~((uint16_t)0x00008000)) == 0); + EM_BLE_WR(BLE_HOPCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (EM_BLE_RD(BLE_HOPCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE) & ~((uint16_t)0x00008000)) | ((uint16_t)fhen << 15)); +} + +__INLINE uint8_t ble_hop_int_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_HOPCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + return ((localVal & ((uint16_t)0x00001F00)) >> 8); +} + +__INLINE void ble_hop_int_setf(int elt_idx, uint8_t hopint) +{ + ASSERT_ERR((((uint16_t)hopint << 8) & ~((uint16_t)0x00001F00)) == 0); + EM_BLE_WR(BLE_HOPCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (EM_BLE_RD(BLE_HOPCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE) & ~((uint16_t)0x00001F00)) | ((uint16_t)hopint << 8)); +} + +__INLINE uint8_t ble_ch_idx_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_HOPCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + return ((localVal & ((uint16_t)0x0000003F)) >> 0); +} + +__INLINE void ble_ch_idx_setf(int elt_idx, uint8_t chidx) +{ + ASSERT_ERR((((uint16_t)chidx << 0) & ~((uint16_t)0x0000003F)) == 0); + EM_BLE_WR(BLE_HOPCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (EM_BLE_RD(BLE_HOPCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE) & ~((uint16_t)0x0000003F)) | ((uint16_t)chidx << 0)); +} + +/** + * @brief TXRXCNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     15          RXBUFF_FULL   0
+ *     14            LASTEMPTY   0
+ *     13                   SN   0
+ *     12                 NESN   0
+ *     11           RXBFMICERR   0
+ *  07:00                TXPWR   0x0
+ * 
+ */ +#define BLE_TXRXCNTL_ADDR (0x00814014 + EM_BLE_CS_OFFSET) +#define BLE_TXRXCNTL_INDEX 0x0000000A +#define BLE_TXRXCNTL_RESET 0x00000000 + +__INLINE uint16_t ble_txrxcntl_get(int elt_idx) +{ + return EM_BLE_RD(BLE_TXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); +} + +__INLINE void ble_txrxcntl_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_TXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, value); +} + +// field definitions +#define BLE_RXBUFF_FULL_BIT ((uint16_t)0x00008000) +#define BLE_RXBUFF_FULL_POS 15 +#define BLE_LASTEMPTY_BIT ((uint16_t)0x00004000) +#define BLE_LASTEMPTY_POS 14 +#define BLE_SN_BIT ((uint16_t)0x00002000) +#define BLE_SN_POS 13 +#define BLE_NESN_BIT ((uint16_t)0x00001000) +#define BLE_NESN_POS 12 +#define BLE_RXBFMICERR_BIT ((uint16_t)0x00000800) +#define BLE_RXBFMICERR_POS 11 +#define BLE_TXPWR_MASK ((uint16_t)0x000000FF) +#define BLE_TXPWR_LSB 0 +#define BLE_TXPWR_WIDTH ((uint16_t)0x00000008) + +#define BLE_RXBUFF_FULL_RST 0x0 +#define BLE_LASTEMPTY_RST 0x0 +#define BLE_SN_RST 0x0 +#define BLE_NESN_RST 0x0 +#define BLE_RXBFMICERR_RST 0x0 +#define BLE_TXPWR_RST 0x0 + +__INLINE void ble_txrxcntl_pack(int elt_idx, uint8_t rxbufffull, uint8_t lastempty, uint8_t sn, uint8_t nesn, uint8_t txpwr) +{ + ASSERT_ERR((((uint16_t)rxbufffull << 15) & ~((uint16_t)0x00008000)) == 0); + ASSERT_ERR((((uint16_t)lastempty << 14) & ~((uint16_t)0x00004000)) == 0); + ASSERT_ERR((((uint16_t)sn << 13) & ~((uint16_t)0x00002000)) == 0); + ASSERT_ERR((((uint16_t)nesn << 12) & ~((uint16_t)0x00001000)) == 0); + ASSERT_ERR((((uint16_t)txpwr << 0) & ~((uint16_t)0x000000FF)) == 0); + EM_BLE_WR(BLE_TXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, ((uint16_t)rxbufffull << 15) | ((uint16_t)lastempty << 14) | ((uint16_t)sn << 13) | ((uint16_t)nesn << 12) | ((uint16_t)txpwr << 0)); +} + +__INLINE void ble_txrxcntl_unpack(int elt_idx, uint8_t* rxbufffull, uint8_t* lastempty, uint8_t* sn, uint8_t* nesn, uint8_t* rxbfmicerr, uint8_t* txpwr) +{ + uint16_t localVal = EM_BLE_RD(BLE_TXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + + *rxbufffull = (localVal & ((uint16_t)0x00008000)) >> 15; + *lastempty = (localVal & ((uint16_t)0x00004000)) >> 14; + *sn = (localVal & ((uint16_t)0x00002000)) >> 13; + *nesn = (localVal & ((uint16_t)0x00001000)) >> 12; + *rxbfmicerr = (localVal & ((uint16_t)0x00000800)) >> 11; + *txpwr = (localVal & ((uint16_t)0x000000FF)) >> 0; +} + +__INLINE uint8_t ble_rxbuff_full_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_TXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + return ((localVal & ((uint16_t)0x00008000)) >> 15); +} + +__INLINE void ble_rxbuff_full_setf(int elt_idx, uint8_t rxbufffull) +{ + ASSERT_ERR((((uint16_t)rxbufffull << 15) & ~((uint16_t)0x00008000)) == 0); + EM_BLE_WR(BLE_TXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (EM_BLE_RD(BLE_TXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE) & ~((uint16_t)0x00008000)) | ((uint16_t)rxbufffull << 15)); +} + +__INLINE uint8_t ble_lastempty_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_TXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + return ((localVal & ((uint16_t)0x00004000)) >> 14); +} + +__INLINE void ble_lastempty_setf(int elt_idx, uint8_t lastempty) +{ + ASSERT_ERR((((uint16_t)lastempty << 14) & ~((uint16_t)0x00004000)) == 0); + EM_BLE_WR(BLE_TXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (EM_BLE_RD(BLE_TXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE) & ~((uint16_t)0x00004000)) | ((uint16_t)lastempty << 14)); +} + +__INLINE uint8_t ble_sn_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_TXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + return ((localVal & ((uint16_t)0x00002000)) >> 13); +} + +__INLINE void ble_sn_setf(int elt_idx, uint8_t sn) +{ + ASSERT_ERR((((uint16_t)sn << 13) & ~((uint16_t)0x00002000)) == 0); + EM_BLE_WR(BLE_TXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (EM_BLE_RD(BLE_TXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE) & ~((uint16_t)0x00002000)) | ((uint16_t)sn << 13)); +} + +__INLINE uint8_t ble_nesn_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_TXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + return ((localVal & ((uint16_t)0x00001000)) >> 12); +} + +__INLINE void ble_nesn_setf(int elt_idx, uint8_t nesn) +{ + ASSERT_ERR((((uint16_t)nesn << 12) & ~((uint16_t)0x00001000)) == 0); + EM_BLE_WR(BLE_TXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (EM_BLE_RD(BLE_TXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE) & ~((uint16_t)0x00001000)) | ((uint16_t)nesn << 12)); +} + +__INLINE uint8_t ble_rxbfmicerr_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_TXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + return ((localVal & ((uint16_t)0x00000800)) >> 11); +} + +__INLINE uint8_t ble_txpwr_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_TXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + return ((localVal & ((uint16_t)0x000000FF)) >> 0); +} + +__INLINE void ble_txpwr_setf(int elt_idx, uint8_t txpwr) +{ + ASSERT_ERR((((uint16_t)txpwr << 0) & ~((uint16_t)0x000000FF)) == 0); + EM_BLE_WR(BLE_TXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (EM_BLE_RD(BLE_TXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE) & ~((uint16_t)0x000000FF)) | ((uint16_t)txpwr << 0)); +} + +/** + * @brief RXWINCNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     15               RXWIDE   0
+ *  13:00              RXWINSZ   0x0
+ * 
+ */ +#define BLE_RXWINCNTL_ADDR (0x00814016 + EM_BLE_CS_OFFSET) +#define BLE_RXWINCNTL_INDEX 0x0000000B +#define BLE_RXWINCNTL_RESET 0x00000000 + +__INLINE uint16_t ble_rxwincntl_get(int elt_idx) +{ + return EM_BLE_RD(BLE_RXWINCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); +} + +__INLINE void ble_rxwincntl_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_RXWINCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, value); +} + +// field definitions +#define BLE_RXWIDE_BIT ((uint16_t)0x00008000) +#define BLE_RXWIDE_POS 15 +#define BLE_RXWINSZ_MASK ((uint16_t)0x00001F)//((uint16_t)0x00003FFF) +#define BLE_RXWINSZ_LSB 0 +#define BLE_RXWINSZ_WIDTH ((uint16_t)0x0000000E) + +#define BLE_RXWIDE_RST 0x0 +#define BLE_RXWINSZ_RST 0x0 + +__INLINE void ble_rxwincntl_pack(int elt_idx, uint8_t rxwide, uint16_t rxwinsz) +{ + ASSERT_ERR((((uint16_t)rxwide << 15) & ~((uint16_t)0x00008000)) == 0); + ASSERT_ERR((((uint16_t)rxwinsz << 0) & ~((uint16_t)0x00003FFF)) == 0); + EM_BLE_WR(BLE_RXWINCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, ((uint16_t)rxwide << 15) | ((uint16_t)rxwinsz << 0)); +} + +__INLINE void ble_rxwincntl_unpack(int elt_idx, uint8_t* rxwide, uint16_t* rxwinsz) +{ + uint16_t localVal = EM_BLE_RD(BLE_RXWINCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + + *rxwide = (localVal & ((uint16_t)0x00008000)) >> 15; + *rxwinsz = (localVal & ((uint16_t)0x00003FFF)) >> 0; +} + +__INLINE uint8_t ble_rxwide_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_RXWINCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + return ((localVal & ((uint16_t)0x00008000)) >> 15); +} + +__INLINE void ble_rxwide_setf(int elt_idx, uint8_t rxwide) +{ + ASSERT_ERR((((uint16_t)rxwide << 15) & ~((uint16_t)0x00008000)) == 0); + EM_BLE_WR(BLE_RXWINCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (EM_BLE_RD(BLE_RXWINCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE) & ~((uint16_t)0x00008000)) | ((uint16_t)rxwide << 15)); +} + +__INLINE uint16_t ble_rxwinsz_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_RXWINCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + return ((localVal & ((uint16_t)0x00003FFF)) >> 0); +} + +__INLINE void ble_rxwinsz_setf(int elt_idx, uint16_t rxwinsz) +{ + ASSERT_ERR((((uint16_t)rxwinsz << 0) & ~((uint16_t)0x00003FFF)) == 0); + EM_BLE_WR(BLE_RXWINCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (EM_BLE_RD(BLE_RXWINCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE) & ~((uint16_t)0x00003FFF)) | ((uint16_t)rxwinsz << 0)); +} + +/** + * @brief TXDESCPTR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  14:00            TXDESCPTR   0x0
+ * 
+ */ +#define BLE_TXDESCPTR_ADDR (0x00814018 + EM_BLE_CS_OFFSET) +#define BLE_TXDESCPTR_INDEX 0x0000000C +#define BLE_TXDESCPTR_RESET 0x00000000 + +__INLINE uint16_t ble_txdescptr_get(int elt_idx) +{ + return EM_BLE_RD(BLE_TXDESCPTR_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); +} + +__INLINE void ble_txdescptr_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_TXDESCPTR_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, value); +} + +// field definitions +#define BLE_TXDESCPTR_MASK ((uint16_t)0x00007FFF) +#define BLE_TXDESCPTR_LSB 0 +#define BLE_TXDESCPTR_WIDTH ((uint16_t)0x0000000F) + +#define BLE_TXDESCPTR_RST 0x0 + +__INLINE uint16_t ble_txdescptr_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_TXDESCPTR_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + ASSERT_ERR((localVal & ~((uint16_t)0x00007FFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_txdescptr_setf(int elt_idx, uint16_t txdescptr) +{ + ASSERT_ERR((((uint16_t)txdescptr << 0) & ~((uint16_t)0x00007FFF)) == 0); + EM_BLE_WR(BLE_TXDESCPTR_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (uint16_t)txdescptr << 0); +} + +/** + * @brief WINOFFSET register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00            WINOFFSET   0x0
+ * 
+ */ +#define BLE_WINOFFSET_ADDR (0x0081401A + EM_BLE_CS_OFFSET) +#define BLE_WINOFFSET_INDEX 0x0000000D +#define BLE_WINOFFSET_RESET 0x00000000 + +__INLINE uint16_t ble_winoffset_get(int elt_idx) +{ + return EM_BLE_RD(BLE_WINOFFSET_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); +} + +__INLINE void ble_winoffset_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_WINOFFSET_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, value); +} + +// field definitions +#define BLE_WINOFFSET_MASK ((uint16_t)0x0000FFFF) +#define BLE_WINOFFSET_LSB 0 +#define BLE_WINOFFSET_WIDTH ((uint16_t)0x00000010) + +#define BLE_WINOFFSET_RST 0x0 + +__INLINE uint16_t ble_winoffset_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_WINOFFSET_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_winoffset_setf(int elt_idx, uint16_t winoffset) +{ + ASSERT_ERR((((uint16_t)winoffset << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(BLE_WINOFFSET_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (uint16_t)winoffset << 0); +} + +/** + * @brief MINEVTIME register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00            MINEVTIME   0x0
+ * 
+ */ +#define BLE_MINEVTIME_ADDR (0x0081401A + EM_BLE_CS_OFFSET) +#define BLE_MINEVTIME_INDEX 0x0000000D +#define BLE_MINEVTIME_RESET 0x00000000 + +__INLINE uint16_t ble_minevtime_get(int elt_idx) +{ + return EM_BLE_RD(BLE_MINEVTIME_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); +} + +__INLINE void ble_minevtime_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_MINEVTIME_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, value); +} + +// field definitions +#define BLE_MINEVTIME_MASK ((uint16_t)0x0000FFFF) +#define BLE_MINEVTIME_LSB 0 +#define BLE_MINEVTIME_WIDTH ((uint16_t)0x00000010) + +#define BLE_MINEVTIME_RST 0x0 + +__INLINE uint16_t ble_minevtime_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_MINEVTIME_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_minevtime_setf(int elt_idx, uint16_t minevtime) +{ + ASSERT_ERR((((uint16_t)minevtime << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(BLE_MINEVTIME_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (uint16_t)minevtime << 0); +} + +/** + * @brief MAXEVTIME register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00            MAXEVTIME   0x0
+ * 
+ */ +#define BLE_MAXEVTIME_ADDR (0x0081401C + EM_BLE_CS_OFFSET) +#define BLE_MAXEVTIME_INDEX 0x0000000E +#define BLE_MAXEVTIME_RESET 0x00000000 + +__INLINE uint16_t ble_maxevtime_get(int elt_idx) +{ + return EM_BLE_RD(BLE_MAXEVTIME_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); +} + +__INLINE void ble_maxevtime_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_MAXEVTIME_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, value); +} + +// field definitions +#define BLE_MAXEVTIME_MASK ((uint16_t)0x0000FFFF) +#define BLE_MAXEVTIME_LSB 0 +#define BLE_MAXEVTIME_WIDTH ((uint16_t)0x00000010) + +#define BLE_MAXEVTIME_RST 0x0 + +__INLINE uint16_t ble_maxevtime_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_MAXEVTIME_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_maxevtime_setf(int elt_idx, uint16_t maxevtime) +{ + ASSERT_ERR((((uint16_t)maxevtime << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(BLE_MAXEVTIME_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (uint16_t)maxevtime << 0); +} + +/** + * @brief CONNINTERVAL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00         CONNINTERVAL   0x0
+ * 
+ */ +#define BLE_CONNINTERVAL_ADDR (0x0081401E + EM_BLE_CS_OFFSET) +#define BLE_CONNINTERVAL_INDEX 0x0000000F +#define BLE_CONNINTERVAL_RESET 0x00000000 + +__INLINE uint16_t ble_conninterval_get(int elt_idx) +{ + return EM_BLE_RD(BLE_CONNINTERVAL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); +} + +__INLINE void ble_conninterval_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_CONNINTERVAL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, value); +} + +// field definitions +#define BLE_CONNINTERVAL_MASK ((uint16_t)0x0000FFFF) +#define BLE_CONNINTERVAL_LSB 0 +#define BLE_CONNINTERVAL_WIDTH ((uint16_t)0x00000010) + +#define BLE_CONNINTERVAL_RST 0x0 + +__INLINE uint16_t ble_conninterval_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_CONNINTERVAL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_conninterval_setf(int elt_idx, uint16_t conninterval) +{ + ASSERT_ERR((((uint16_t)conninterval << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(BLE_CONNINTERVAL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (uint16_t)conninterval << 0); +} + +/** + * @brief CHMAP0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00             LLCHMAP0   0xFFFF
+ * 
+ */ +#define BLE_CHMAP0_ADDR (0x0081401E + EM_BLE_CS_OFFSET) +#define BLE_CHMAP0_INDEX 0x0000000F +#define BLE_CHMAP0_RESET 0x0000FFFF + +__INLINE uint16_t ble_chmap0_get(int elt_idx) +{ + return EM_BLE_RD(BLE_CHMAP0_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); +} + +__INLINE void ble_chmap0_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_CHMAP0_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, value); +} + +// field definitions +#define BLE_LLCHMAP0_MASK ((uint16_t)0x0000FFFF) +#define BLE_LLCHMAP0_LSB 0 +#define BLE_LLCHMAP0_WIDTH ((uint16_t)0x00000010) + +#define BLE_LLCHMAP0_RST 0xFFFF + +__INLINE uint16_t ble_llchmap0_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_CHMAP0_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_llchmap0_setf(int elt_idx, uint16_t llchmap0) +{ + ASSERT_ERR((((uint16_t)llchmap0 << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(BLE_CHMAP0_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (uint16_t)llchmap0 << 0); +} + +/** + * @brief CHMAP1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00             LLCHMAP1   0xFFFF
+ * 
+ */ +#define BLE_CHMAP1_ADDR (0x00814020 + EM_BLE_CS_OFFSET) +#define BLE_CHMAP1_INDEX 0x00000010 +#define BLE_CHMAP1_RESET 0x0000FFFF + +__INLINE uint16_t ble_chmap1_get(int elt_idx) +{ + return EM_BLE_RD(BLE_CHMAP1_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); +} + +__INLINE void ble_chmap1_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_CHMAP1_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, value); +} + +// field definitions +#define BLE_LLCHMAP1_MASK ((uint16_t)0x0000FFFF) +#define BLE_LLCHMAP1_LSB 0 +#define BLE_LLCHMAP1_WIDTH ((uint16_t)0x00000010) + +#define BLE_LLCHMAP1_RST 0xFFFF + +__INLINE uint16_t ble_llchmap1_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_CHMAP1_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_llchmap1_setf(int elt_idx, uint16_t llchmap1) +{ + ASSERT_ERR((((uint16_t)llchmap1 << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(BLE_CHMAP1_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (uint16_t)llchmap1 << 0); +} + +/** + * @brief CHMAP2 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  13:08             NBCHGOOD   0x25
+ *  04:00             LLCHMAP3   0x1F
+ * 
+ */ +#define BLE_CHMAP2_ADDR (0x00814022 + EM_BLE_CS_OFFSET) +#define BLE_CHMAP2_INDEX 0x00000011 +#define BLE_CHMAP2_RESET 0x0000251F + +__INLINE uint16_t ble_chmap2_get(int elt_idx) +{ + return EM_BLE_RD(BLE_CHMAP2_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); +} + +__INLINE void ble_chmap2_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_CHMAP2_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, value); +} + +// field definitions +#define BLE_NBCHGOOD_MASK ((uint16_t)0x00003F00) +#define BLE_NBCHGOOD_LSB 8 +#define BLE_NBCHGOOD_WIDTH ((uint16_t)0x00000006) +#define BLE_LLCHMAP3_MASK ((uint16_t)0x0000001F) +#define BLE_LLCHMAP3_LSB 0 +#define BLE_LLCHMAP3_WIDTH ((uint16_t)0x00000005) + +#define BLE_NBCHGOOD_RST 0x25 +#define BLE_LLCHMAP3_RST 0x1F + +__INLINE void ble_chmap2_pack(int elt_idx, uint8_t nbchgood, uint8_t llchmap3) +{ + ASSERT_ERR((((uint16_t)nbchgood << 8) & ~((uint16_t)0x00003F00)) == 0); + ASSERT_ERR((((uint16_t)llchmap3 << 0) & ~((uint16_t)0x0000001F)) == 0); + EM_BLE_WR(BLE_CHMAP2_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, ((uint16_t)nbchgood << 8) | ((uint16_t)llchmap3 << 0)); +} + +__INLINE void ble_chmap2_unpack(int elt_idx, uint8_t* nbchgood, uint8_t* llchmap3) +{ + uint16_t localVal = EM_BLE_RD(BLE_CHMAP2_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + + *nbchgood = (localVal & ((uint16_t)0x00003F00)) >> 8; + *llchmap3 = (localVal & ((uint16_t)0x0000001F)) >> 0; +} + +__INLINE uint8_t ble_nbchgood_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_CHMAP2_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + return ((localVal & ((uint16_t)0x00003F00)) >> 8); +} + +__INLINE void ble_nbchgood_setf(int elt_idx, uint8_t nbchgood) +{ + ASSERT_ERR((((uint16_t)nbchgood << 8) & ~((uint16_t)0x00003F00)) == 0); + EM_BLE_WR(BLE_CHMAP2_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (EM_BLE_RD(BLE_CHMAP2_ADDR + elt_idx * REG_BLE_EM_CS_SIZE) & ~((uint16_t)0x00003F00)) | ((uint16_t)nbchgood << 8)); +} + +__INLINE uint8_t ble_llchmap3_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_CHMAP2_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + return ((localVal & ((uint16_t)0x0000001F)) >> 0); +} + +__INLINE void ble_llchmap3_setf(int elt_idx, uint8_t llchmap3) +{ + ASSERT_ERR((((uint16_t)llchmap3 << 0) & ~((uint16_t)0x0000001F)) == 0); + EM_BLE_WR(BLE_CHMAP2_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (EM_BLE_RD(BLE_CHMAP2_ADDR + elt_idx * REG_BLE_EM_CS_SIZE) & ~((uint16_t)0x0000001F)) | ((uint16_t)llchmap3 << 0)); +} + +/** + * @brief RXMAXBUF register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  07:00             RXMAXBUF   0x0
+ * 
+ */ +#define BLE_RXMAXBUF_ADDR (0x00814024 + EM_BLE_CS_OFFSET) +#define BLE_RXMAXBUF_INDEX 0x00000012 +#define BLE_RXMAXBUF_RESET 0x00000000 + +__INLINE uint16_t ble_rxmaxbuf_get(int elt_idx) +{ + return EM_BLE_RD(BLE_RXMAXBUF_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); +} + +__INLINE void ble_rxmaxbuf_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_RXMAXBUF_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, value); +} + +// field definitions +#define BLE_RXMAXBUF_MASK ((uint16_t)0x000000FF) +#define BLE_RXMAXBUF_LSB 0 +#define BLE_RXMAXBUF_WIDTH ((uint16_t)0x00000008) + +#define BLE_RXMAXBUF_RST 0x0 + +__INLINE uint8_t ble_rxmaxbuf_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_RXMAXBUF_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + ASSERT_ERR((localVal & ~((uint16_t)0x000000FF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_rxmaxbuf_setf(int elt_idx, uint8_t rxmaxbuf) +{ + ASSERT_ERR((((uint16_t)rxmaxbuf << 0) & ~((uint16_t)0x000000FF)) == 0); + EM_BLE_WR(BLE_RXMAXBUF_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (uint16_t)rxmaxbuf << 0); +} + +/** + * @brief RXMAXTIME register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  12:00            RXMAXTIME   0x0
+ * 
+ */ +#define BLE_RXMAXTIME_ADDR (0x00814026 + EM_BLE_CS_OFFSET) +#define BLE_RXMAXTIME_INDEX 0x00000013 +#define BLE_RXMAXTIME_RESET 0x00000000 + +__INLINE uint16_t ble_rxmaxtime_get(int elt_idx) +{ + return EM_BLE_RD(BLE_RXMAXTIME_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); +} + +__INLINE void ble_rxmaxtime_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_RXMAXTIME_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, value); +} + +// field definitions +#define BLE_RXMAXTIME_MASK ((uint16_t)0x00001FFF) +#define BLE_RXMAXTIME_LSB 0 +#define BLE_RXMAXTIME_WIDTH ((uint16_t)0x0000000D) + +#define BLE_RXMAXTIME_RST 0x0 + +__INLINE uint16_t ble_rxmaxtime_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_RXMAXTIME_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + ASSERT_ERR((localVal & ~((uint16_t)0x00001FFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_rxmaxtime_setf(int elt_idx, uint16_t rxmaxtime) +{ + ASSERT_ERR((((uint16_t)rxmaxtime << 0) & ~((uint16_t)0x00001FFF)) == 0); + EM_BLE_WR(BLE_RXMAXTIME_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (uint16_t)rxmaxtime << 0); +} + +/** + * @brief SK register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00                   SK   0x0
+ * 
+ */ +#define BLE_SK_ADDR (0x00814028 + EM_BLE_CS_OFFSET) +#define BLE_SK_INDEX 0x00000014 +#define BLE_SK_RESET 0x00000000 +#define BLE_SK_COUNT 8 + +__INLINE uint16_t ble_sk_get(int elt_idx, int reg_idx) +{ + ASSERT_ERR(reg_idx <= 7); + return EM_BLE_RD(BLE_SK_ADDR + elt_idx * REG_BLE_EM_CS_SIZE + reg_idx * 2); +} + +__INLINE void ble_sk_set(int elt_idx, int reg_idx, uint16_t value) +{ + ASSERT_ERR(reg_idx <= 7); + EM_BLE_WR(BLE_SK_ADDR + elt_idx * REG_BLE_EM_CS_SIZE + reg_idx * 2, value); +} + +// field definitions +#define BLE_SK_MASK ((uint16_t)0x0000FFFF) +#define BLE_SK_LSB 0 +#define BLE_SK_WIDTH ((uint16_t)0x00000010) + +#define BLE_SK_RST 0x0 + +__INLINE uint16_t ble_sk_getf(int elt_idx, int reg_idx) +{ + ASSERT_ERR(reg_idx <= 7); + uint16_t localVal = EM_BLE_RD(BLE_SK_ADDR + elt_idx * REG_BLE_EM_CS_SIZE + reg_idx * 2); + ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_sk_setf(int elt_idx, int reg_idx, uint16_t sk) +{ + ASSERT_ERR(reg_idx <= 7); + ASSERT_ERR((((uint16_t)sk << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(BLE_SK_ADDR + elt_idx * REG_BLE_EM_CS_SIZE + reg_idx * 2, (uint16_t)sk << 0); +} + +/** + * @brief ADV_BD_ADDR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00          ADV_BD_ADDR   0x0
+ * 
+ */ +#define BLE_ADV_BD_ADDR_ADDR (0x00814028 + EM_BLE_CS_OFFSET) +#define BLE_ADV_BD_ADDR_INDEX 0x00000014 +#define BLE_ADV_BD_ADDR_RESET 0x00000000 +#define BLE_ADV_BD_ADDR_COUNT 3 + +__INLINE uint16_t ble_adv_bd_addr_get(int elt_idx, int reg_idx) +{ + ASSERT_ERR(reg_idx <= 2); + return EM_BLE_RD(BLE_ADV_BD_ADDR_ADDR + elt_idx * REG_BLE_EM_CS_SIZE + reg_idx * 2); +} + +__INLINE void ble_adv_bd_addr_set(int elt_idx, int reg_idx, uint16_t value) +{ + ASSERT_ERR(reg_idx <= 2); + EM_BLE_WR(BLE_ADV_BD_ADDR_ADDR + elt_idx * REG_BLE_EM_CS_SIZE + reg_idx * 2, value); +} + +// field definitions +#define BLE_ADV_BD_ADDR_MASK ((uint16_t)0x0000FFFF) +#define BLE_ADV_BD_ADDR_LSB 0 +#define BLE_ADV_BD_ADDR_WIDTH ((uint16_t)0x00000010) + +#define BLE_ADV_BD_ADDR_RST 0x0 + +__INLINE uint16_t ble_adv_bd_addr_getf(int elt_idx, int reg_idx) +{ + ASSERT_ERR(reg_idx <= 2); + uint16_t localVal = EM_BLE_RD(BLE_ADV_BD_ADDR_ADDR + elt_idx * REG_BLE_EM_CS_SIZE + reg_idx * 2); + ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_adv_bd_addr_setf(int elt_idx, int reg_idx, uint16_t advbdaddr) +{ + ASSERT_ERR(reg_idx <= 2); + ASSERT_ERR((((uint16_t)advbdaddr << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(BLE_ADV_BD_ADDR_ADDR + elt_idx * REG_BLE_EM_CS_SIZE + reg_idx * 2, (uint16_t)advbdaddr << 0); +} + +/** + * @brief PEER_RALPTR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00          PEER_RALPTR   0x0
+ * 
+ */ +#define BLE_PEER_RALPTR_ADDR (0x00814028 + EM_BLE_CS_OFFSET) +#define BLE_PEER_RALPTR_INDEX 0x00000014 +#define BLE_PEER_RALPTR_RESET 0x00000000 + +__INLINE uint16_t ble_peer_ralptr_get(int elt_idx) +{ + return EM_BLE_RD(BLE_PEER_RALPTR_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); +} + +__INLINE void ble_peer_ralptr_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_PEER_RALPTR_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, value); +} + +// field definitions +#define BLE_PEER_RALPTR_MASK ((uint16_t)0x0000FFFF) +#define BLE_PEER_RALPTR_LSB 0 +#define BLE_PEER_RALPTR_WIDTH ((uint16_t)0x00000010) + +#define BLE_PEER_RALPTR_RST 0x0 + +__INLINE uint16_t ble_peer_ralptr_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_PEER_RALPTR_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_peer_ralptr_setf(int elt_idx, uint16_t peerralptr) +{ + ASSERT_ERR((((uint16_t)peerralptr << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(BLE_PEER_RALPTR_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (uint16_t)peerralptr << 0); +} + +/** + * @brief ADV_BD_ADDR_TYPE register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     00     ADV_BD_ADDR_TYPE   0
+ * 
+ */ +#define BLE_ADV_BD_ADDR_TYPE_ADDR (0x0081402E + EM_BLE_CS_OFFSET) +#define BLE_ADV_BD_ADDR_TYPE_INDEX 0x00000017 +#define BLE_ADV_BD_ADDR_TYPE_RESET 0x00000000 + +__INLINE uint16_t ble_adv_bd_addr_type_get(int elt_idx) +{ + return EM_BLE_RD(BLE_ADV_BD_ADDR_TYPE_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); +} + +__INLINE void ble_adv_bd_addr_type_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_ADV_BD_ADDR_TYPE_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, value); +} + +// field definitions +#define BLE_ADV_BD_ADDR_TYPE_BIT ((uint16_t)0x00000001) +#define BLE_ADV_BD_ADDR_TYPE_POS 0 + +#define BLE_ADV_BD_ADDR_TYPE_RST 0x0 + +__INLINE uint8_t ble_adv_bd_addr_type_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_ADV_BD_ADDR_TYPE_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + ASSERT_ERR((localVal & ~((uint16_t)0x00000001)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_adv_bd_addr_type_setf(int elt_idx, uint8_t advbdaddrtype) +{ + ASSERT_ERR((((uint16_t)advbdaddrtype << 0) & ~((uint16_t)0x00000001)) == 0); + EM_BLE_WR(BLE_ADV_BD_ADDR_TYPE_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (uint16_t)advbdaddrtype << 0); +} + +/** + * @brief IV register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00                   IV   0x0
+ * 
+ */ +#define BLE_IV_ADDR (0x00814038 + EM_BLE_CS_OFFSET) +#define BLE_IV_INDEX 0x0000001C +#define BLE_IV_RESET 0x00000000 +#define BLE_IV_COUNT 4 + +__INLINE uint16_t ble_iv_get(int elt_idx, int reg_idx) +{ + ASSERT_ERR(reg_idx <= 3); + return EM_BLE_RD(BLE_IV_ADDR + elt_idx * REG_BLE_EM_CS_SIZE + reg_idx * 2); +} + +__INLINE void ble_iv_set(int elt_idx, int reg_idx, uint16_t value) +{ + ASSERT_ERR(reg_idx <= 3); + EM_BLE_WR(BLE_IV_ADDR + elt_idx * REG_BLE_EM_CS_SIZE + reg_idx * 2, value); +} + +// field definitions +#define BLE_IV_MASK ((uint16_t)0x0000FFFF) +#define BLE_IV_LSB 0 +#define BLE_IV_WIDTH ((uint16_t)0x00000010) + +#define BLE_IV_RST 0x0 + +__INLINE uint16_t ble_iv_getf(int elt_idx, int reg_idx) +{ + ASSERT_ERR(reg_idx <= 3); + uint16_t localVal = EM_BLE_RD(BLE_IV_ADDR + elt_idx * REG_BLE_EM_CS_SIZE + reg_idx * 2); + ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_iv_setf(int elt_idx, int reg_idx, uint16_t iv) +{ + ASSERT_ERR(reg_idx <= 3); + ASSERT_ERR((((uint16_t)iv << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(BLE_IV_ADDR + elt_idx * REG_BLE_EM_CS_SIZE + reg_idx * 2, (uint16_t)iv << 0); +} + +/** + * @brief TXWINOFFSET register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00          TXWINOFFSET   0x0
+ * 
+ */ +#define BLE_TXWINOFFSET_ADDR (0x00814040 + EM_BLE_CS_OFFSET) +#define BLE_TXWINOFFSET_INDEX 0x00000020 +#define BLE_TXWINOFFSET_RESET 0x00000000 + +__INLINE uint16_t ble_txwinoffset_get(int elt_idx) +{ + return EM_BLE_RD(BLE_TXWINOFFSET_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); +} + +__INLINE void ble_txwinoffset_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_TXWINOFFSET_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, value); +} + +// field definitions +#define BLE_TXWINOFFSET_MASK ((uint16_t)0x0000FFFF) +#define BLE_TXWINOFFSET_LSB 0 +#define BLE_TXWINOFFSET_WIDTH ((uint16_t)0x00000010) + +#define BLE_TXWINOFFSET_RST 0x0 + +__INLINE uint16_t ble_txwinoffset_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_TXWINOFFSET_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_txwinoffset_setf(int elt_idx, uint16_t txwinoffset) +{ + ASSERT_ERR((((uint16_t)txwinoffset << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(BLE_TXWINOFFSET_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (uint16_t)txwinoffset << 0); +} + +/** + * @brief TXCCMPKTCNT0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00         TXCCMPKTCNT0   0x0
+ * 
+ */ +#define BLE_TXCCMPKTCNT0_ADDR (0x00814040 + EM_BLE_CS_OFFSET) +#define BLE_TXCCMPKTCNT0_INDEX 0x00000020 +#define BLE_TXCCMPKTCNT0_RESET 0x00000000 + +__INLINE uint16_t ble_txccmpktcnt0_get(int elt_idx) +{ + return EM_BLE_RD(BLE_TXCCMPKTCNT0_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); +} + +__INLINE void ble_txccmpktcnt0_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_TXCCMPKTCNT0_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, value); +} + +// field definitions +#define BLE_TXCCMPKTCNT0_MASK ((uint16_t)0x0000FFFF) +#define BLE_TXCCMPKTCNT0_LSB 0 +#define BLE_TXCCMPKTCNT0_WIDTH ((uint16_t)0x00000010) + +#define BLE_TXCCMPKTCNT0_RST 0x0 + +__INLINE uint16_t ble_txccmpktcnt0_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_TXCCMPKTCNT0_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_txccmpktcnt0_setf(int elt_idx, uint16_t txccmpktcnt0) +{ + ASSERT_ERR((((uint16_t)txccmpktcnt0 << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(BLE_TXCCMPKTCNT0_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (uint16_t)txccmpktcnt0 << 0); +} + +/** + * @brief TXCCMPKTCNT1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00         TXCCMPKTCNT1   0x0
+ * 
+ */ +#define BLE_TXCCMPKTCNT1_ADDR (0x00814042 + EM_BLE_CS_OFFSET) +#define BLE_TXCCMPKTCNT1_INDEX 0x00000021 +#define BLE_TXCCMPKTCNT1_RESET 0x00000000 + +__INLINE uint16_t ble_txccmpktcnt1_get(int elt_idx) +{ + return EM_BLE_RD(BLE_TXCCMPKTCNT1_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); +} + +__INLINE void ble_txccmpktcnt1_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_TXCCMPKTCNT1_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, value); +} + +// field definitions +#define BLE_TXCCMPKTCNT1_MASK ((uint16_t)0x0000FFFF) +#define BLE_TXCCMPKTCNT1_LSB 0 +#define BLE_TXCCMPKTCNT1_WIDTH ((uint16_t)0x00000010) + +#define BLE_TXCCMPKTCNT1_RST 0x0 + +__INLINE uint16_t ble_txccmpktcnt1_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_TXCCMPKTCNT1_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_txccmpktcnt1_setf(int elt_idx, uint16_t txccmpktcnt1) +{ + ASSERT_ERR((((uint16_t)txccmpktcnt1 << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(BLE_TXCCMPKTCNT1_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (uint16_t)txccmpktcnt1 << 0); +} + +/** + * @brief TXCCMPKTCNT2 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  06:00         TXCCMPKTCNT2   0x0
+ * 
+ */ +#define BLE_TXCCMPKTCNT2_ADDR (0x00814044 + EM_BLE_CS_OFFSET) +#define BLE_TXCCMPKTCNT2_INDEX 0x00000022 +#define BLE_TXCCMPKTCNT2_RESET 0x00000000 + +__INLINE uint16_t ble_txccmpktcnt2_get(int elt_idx) +{ + return EM_BLE_RD(BLE_TXCCMPKTCNT2_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); +} + +__INLINE void ble_txccmpktcnt2_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_TXCCMPKTCNT2_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, value); +} + +// field definitions +#define BLE_TXCCMPKTCNT2_MASK ((uint16_t)0x0000007F) +#define BLE_TXCCMPKTCNT2_LSB 0 +#define BLE_TXCCMPKTCNT2_WIDTH ((uint16_t)0x00000007) + +#define BLE_TXCCMPKTCNT2_RST 0x0 + +__INLINE uint8_t ble_txccmpktcnt2_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_TXCCMPKTCNT2_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + ASSERT_ERR((localVal & ~((uint16_t)0x0000007F)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_txccmpktcnt2_setf(int elt_idx, uint8_t txccmpktcnt2) +{ + ASSERT_ERR((((uint16_t)txccmpktcnt2 << 0) & ~((uint16_t)0x0000007F)) == 0); + EM_BLE_WR(BLE_TXCCMPKTCNT2_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (uint16_t)txccmpktcnt2 << 0); +} + +/** + * @brief RXCCMPKTCNT0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00         RXCCMPKTCNT0   0x0
+ * 
+ */ +#define BLE_RXCCMPKTCNT0_ADDR (0x00814046 + EM_BLE_CS_OFFSET) +#define BLE_RXCCMPKTCNT0_INDEX 0x00000023 +#define BLE_RXCCMPKTCNT0_RESET 0x00000000 + +__INLINE uint16_t ble_rxccmpktcnt0_get(int elt_idx) +{ + return EM_BLE_RD(BLE_RXCCMPKTCNT0_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); +} + +__INLINE void ble_rxccmpktcnt0_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_RXCCMPKTCNT0_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, value); +} + +// field definitions +#define BLE_RXCCMPKTCNT0_MASK ((uint16_t)0x0000FFFF) +#define BLE_RXCCMPKTCNT0_LSB 0 +#define BLE_RXCCMPKTCNT0_WIDTH ((uint16_t)0x00000010) + +#define BLE_RXCCMPKTCNT0_RST 0x0 + +__INLINE uint16_t ble_rxccmpktcnt0_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_RXCCMPKTCNT0_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_rxccmpktcnt0_setf(int elt_idx, uint16_t rxccmpktcnt0) +{ + ASSERT_ERR((((uint16_t)rxccmpktcnt0 << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(BLE_RXCCMPKTCNT0_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (uint16_t)rxccmpktcnt0 << 0); +} + +/** + * @brief RXCCMPKTCNT1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00         RXCCMPKTCNT1   0x0
+ * 
+ */ +#define BLE_RXCCMPKTCNT1_ADDR (0x00814048 + EM_BLE_CS_OFFSET) +#define BLE_RXCCMPKTCNT1_INDEX 0x00000024 +#define BLE_RXCCMPKTCNT1_RESET 0x00000000 + +__INLINE uint16_t ble_rxccmpktcnt1_get(int elt_idx) +{ + return EM_BLE_RD(BLE_RXCCMPKTCNT1_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); +} + +__INLINE void ble_rxccmpktcnt1_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_RXCCMPKTCNT1_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, value); +} + +// field definitions +#define BLE_RXCCMPKTCNT1_MASK ((uint16_t)0x0000FFFF) +#define BLE_RXCCMPKTCNT1_LSB 0 +#define BLE_RXCCMPKTCNT1_WIDTH ((uint16_t)0x00000010) + +#define BLE_RXCCMPKTCNT1_RST 0x0 + +__INLINE uint16_t ble_rxccmpktcnt1_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_RXCCMPKTCNT1_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_rxccmpktcnt1_setf(int elt_idx, uint16_t rxccmpktcnt1) +{ + ASSERT_ERR((((uint16_t)rxccmpktcnt1 << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(BLE_RXCCMPKTCNT1_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (uint16_t)rxccmpktcnt1 << 0); +} + +/** + * @brief RXCCMPKTCNT2 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  06:00         RXCCMPKTCNT2   0x0
+ * 
+ */ +#define BLE_RXCCMPKTCNT2_ADDR (0x0081404A + EM_BLE_CS_OFFSET) +#define BLE_RXCCMPKTCNT2_INDEX 0x00000025 +#define BLE_RXCCMPKTCNT2_RESET 0x00000000 + +__INLINE uint16_t ble_rxccmpktcnt2_get(int elt_idx) +{ + return EM_BLE_RD(BLE_RXCCMPKTCNT2_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); +} + +__INLINE void ble_rxccmpktcnt2_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_RXCCMPKTCNT2_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, value); +} + +// field definitions +#define BLE_RXCCMPKTCNT2_MASK ((uint16_t)0x0000007F) +#define BLE_RXCCMPKTCNT2_LSB 0 +#define BLE_RXCCMPKTCNT2_WIDTH ((uint16_t)0x00000007) + +#define BLE_RXCCMPKTCNT2_RST 0x0 + +__INLINE uint8_t ble_rxccmpktcnt2_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_RXCCMPKTCNT2_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + ASSERT_ERR((localVal & ~((uint16_t)0x0000007F)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_rxccmpktcnt2_setf(int elt_idx, uint8_t rxccmpktcnt2) +{ + ASSERT_ERR((((uint16_t)rxccmpktcnt2 << 0) & ~((uint16_t)0x0000007F)) == 0); + EM_BLE_WR(BLE_RXCCMPKTCNT2_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (uint16_t)rxccmpktcnt2 << 0); +} + +/** + * @brief EVTCNT register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00              EVT_CNT   0x0
+ * 
+ */ +#define BLE_EVTCNT_ADDR (0x0081404C + EM_BLE_CS_OFFSET) +#define BLE_EVTCNT_INDEX 0x00000026 +#define BLE_EVTCNT_RESET 0x00000000 + +__INLINE uint16_t ble_evtcnt_get(int elt_idx) +{ + return EM_BLE_RD(BLE_EVTCNT_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); +} + +__INLINE void ble_evtcnt_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_EVTCNT_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, value); +} + +// field definitions +#define BLE_EVT_CNT_MASK ((uint16_t)0x0000FFFF) +#define BLE_EVT_CNT_LSB 0 +#define BLE_EVT_CNT_WIDTH ((uint16_t)0x00000010) + +#define BLE_EVT_CNT_RST 0x0 + +__INLINE uint16_t ble_evt_cnt_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_EVTCNT_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_evt_cnt_setf(int elt_idx, uint16_t evtcnt) +{ + ASSERT_ERR((((uint16_t)evtcnt << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(BLE_EVTCNT_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (uint16_t)evtcnt << 0); +} + +/** + * @brief ISOTXRXCNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     15       ISORXBUFF_FULL   0
+ *     14         ISOLASTEMPTY   0
+ *     13                ISOMD   0
+ *     12                ISOSN   0
+ *     11              ISONESN   0
+ *     09              ISORETX   0
+ *     08              ISORSVD   0
+ *     03           ISOWAITACK   0
+ *     02            ISOLASTMD   0
+ *     01          ISOLASTNESN   0
+ *     00            ISOLASTSN   0
+ * 
+ */ +#define BLE_ISOTXRXCNTL_ADDR (0x0081404E + EM_BLE_CS_OFFSET) +#define BLE_ISOTXRXCNTL_INDEX 0x00000027 +#define BLE_ISOTXRXCNTL_RESET 0x00000000 + +__INLINE uint16_t ble_isotxrxcntl_get(int elt_idx) +{ + return EM_BLE_RD(BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); +} + +__INLINE void ble_isotxrxcntl_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, value); +} + +// field definitions +#define BLE_ISORXBUFF_FULL_BIT ((uint16_t)0x00008000) +#define BLE_ISORXBUFF_FULL_POS 15 +#define BLE_ISOLASTEMPTY_BIT ((uint16_t)0x00004000) +#define BLE_ISOLASTEMPTY_POS 14 +#define BLE_ISOMD_BIT ((uint16_t)0x00002000) +#define BLE_ISOMD_POS 13 +#define BLE_ISOSN_BIT ((uint16_t)0x00001000) +#define BLE_ISOSN_POS 12 +#define BLE_ISONESN_BIT ((uint16_t)0x00000800) +#define BLE_ISONESN_POS 11 +#define BLE_ISORETX_BIT ((uint16_t)0x00000200) +#define BLE_ISORETX_POS 9 +#define BLE_ISORSVD_BIT ((uint16_t)0x00000100) +#define BLE_ISORSVD_POS 8 +#define BLE_ISOWAITACK_BIT ((uint16_t)0x00000008) +#define BLE_ISOWAITACK_POS 3 +#define BLE_ISOLASTMD_BIT ((uint16_t)0x00000004) +#define BLE_ISOLASTMD_POS 2 +#define BLE_ISOLASTNESN_BIT ((uint16_t)0x00000002) +#define BLE_ISOLASTNESN_POS 1 +#define BLE_ISOLASTSN_BIT ((uint16_t)0x00000001) +#define BLE_ISOLASTSN_POS 0 + +#define BLE_ISORXBUFF_FULL_RST 0x0 +#define BLE_ISOLASTEMPTY_RST 0x0 +#define BLE_ISOMD_RST 0x0 +#define BLE_ISOSN_RST 0x0 +#define BLE_ISONESN_RST 0x0 +#define BLE_ISORETX_RST 0x0 +#define BLE_ISORSVD_RST 0x0 +#define BLE_ISOWAITACK_RST 0x0 +#define BLE_ISOLASTMD_RST 0x0 +#define BLE_ISOLASTNESN_RST 0x0 +#define BLE_ISOLASTSN_RST 0x0 + +__INLINE void ble_isotxrxcntl_pack(int elt_idx, uint8_t isorxbufffull, uint8_t isolastempty, uint8_t isomd, uint8_t isosn, uint8_t isonesn, uint8_t isoretx, uint8_t isorsvd, uint8_t isowaitack, uint8_t isolastmd, uint8_t isolastnesn, uint8_t isolastsn) +{ + ASSERT_ERR((((uint16_t)isorxbufffull << 15) & ~((uint16_t)0x00008000)) == 0); + ASSERT_ERR((((uint16_t)isolastempty << 14) & ~((uint16_t)0x00004000)) == 0); + ASSERT_ERR((((uint16_t)isomd << 13) & ~((uint16_t)0x00002000)) == 0); + ASSERT_ERR((((uint16_t)isosn << 12) & ~((uint16_t)0x00001000)) == 0); + ASSERT_ERR((((uint16_t)isonesn << 11) & ~((uint16_t)0x00000800)) == 0); + ASSERT_ERR((((uint16_t)isoretx << 9) & ~((uint16_t)0x00000200)) == 0); + ASSERT_ERR((((uint16_t)isorsvd << 8) & ~((uint16_t)0x00000100)) == 0); + ASSERT_ERR((((uint16_t)isowaitack << 3) & ~((uint16_t)0x00000008)) == 0); + ASSERT_ERR((((uint16_t)isolastmd << 2) & ~((uint16_t)0x00000004)) == 0); + ASSERT_ERR((((uint16_t)isolastnesn << 1) & ~((uint16_t)0x00000002)) == 0); + ASSERT_ERR((((uint16_t)isolastsn << 0) & ~((uint16_t)0x00000001)) == 0); + EM_BLE_WR(BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, ((uint16_t)isorxbufffull << 15) | ((uint16_t)isolastempty << 14) | ((uint16_t)isomd << 13) | ((uint16_t)isosn << 12) | ((uint16_t)isonesn << 11) | ((uint16_t)isoretx << 9) | ((uint16_t)isorsvd << 8) | ((uint16_t)isowaitack << 3) | ((uint16_t)isolastmd << 2) | ((uint16_t)isolastnesn << 1) | ((uint16_t)isolastsn << 0)); +} + +__INLINE void ble_isotxrxcntl_unpack(int elt_idx, uint8_t* isorxbufffull, uint8_t* isolastempty, uint8_t* isomd, uint8_t* isosn, uint8_t* isonesn, uint8_t* isoretx, uint8_t* isorsvd, uint8_t* isowaitack, uint8_t* isolastmd, uint8_t* isolastnesn, uint8_t* isolastsn) +{ + uint16_t localVal = EM_BLE_RD(BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + + *isorxbufffull = (localVal & ((uint16_t)0x00008000)) >> 15; + *isolastempty = (localVal & ((uint16_t)0x00004000)) >> 14; + *isomd = (localVal & ((uint16_t)0x00002000)) >> 13; + *isosn = (localVal & ((uint16_t)0x00001000)) >> 12; + *isonesn = (localVal & ((uint16_t)0x00000800)) >> 11; + *isoretx = (localVal & ((uint16_t)0x00000200)) >> 9; + *isorsvd = (localVal & ((uint16_t)0x00000100)) >> 8; + *isowaitack = (localVal & ((uint16_t)0x00000008)) >> 3; + *isolastmd = (localVal & ((uint16_t)0x00000004)) >> 2; + *isolastnesn = (localVal & ((uint16_t)0x00000002)) >> 1; + *isolastsn = (localVal & ((uint16_t)0x00000001)) >> 0; +} + +__INLINE uint8_t ble_isorxbuff_full_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + return ((localVal & ((uint16_t)0x00008000)) >> 15); +} + +__INLINE void ble_isorxbuff_full_setf(int elt_idx, uint8_t isorxbufffull) +{ + ASSERT_ERR((((uint16_t)isorxbufffull << 15) & ~((uint16_t)0x00008000)) == 0); + EM_BLE_WR(BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (EM_BLE_RD(BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE) & ~((uint16_t)0x00008000)) | ((uint16_t)isorxbufffull << 15)); +} + +__INLINE uint8_t ble_isolastempty_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + return ((localVal & ((uint16_t)0x00004000)) >> 14); +} + +__INLINE void ble_isolastempty_setf(int elt_idx, uint8_t isolastempty) +{ + ASSERT_ERR((((uint16_t)isolastempty << 14) & ~((uint16_t)0x00004000)) == 0); + EM_BLE_WR(BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (EM_BLE_RD(BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE) & ~((uint16_t)0x00004000)) | ((uint16_t)isolastempty << 14)); +} + +__INLINE uint8_t ble_isomd_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + return ((localVal & ((uint16_t)0x00002000)) >> 13); +} + +__INLINE void ble_isomd_setf(int elt_idx, uint8_t isomd) +{ + ASSERT_ERR((((uint16_t)isomd << 13) & ~((uint16_t)0x00002000)) == 0); + EM_BLE_WR(BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (EM_BLE_RD(BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE) & ~((uint16_t)0x00002000)) | ((uint16_t)isomd << 13)); +} + +__INLINE uint8_t ble_isosn_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + return ((localVal & ((uint16_t)0x00001000)) >> 12); +} + +__INLINE void ble_isosn_setf(int elt_idx, uint8_t isosn) +{ + ASSERT_ERR((((uint16_t)isosn << 12) & ~((uint16_t)0x00001000)) == 0); + EM_BLE_WR(BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (EM_BLE_RD(BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE) & ~((uint16_t)0x00001000)) | ((uint16_t)isosn << 12)); +} + +__INLINE uint8_t ble_isonesn_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + return ((localVal & ((uint16_t)0x00000800)) >> 11); +} + +__INLINE void ble_isonesn_setf(int elt_idx, uint8_t isonesn) +{ + ASSERT_ERR((((uint16_t)isonesn << 11) & ~((uint16_t)0x00000800)) == 0); + EM_BLE_WR(BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (EM_BLE_RD(BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE) & ~((uint16_t)0x00000800)) | ((uint16_t)isonesn << 11)); +} + +__INLINE uint8_t ble_isoretx_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + return ((localVal & ((uint16_t)0x00000200)) >> 9); +} + +__INLINE void ble_isoretx_setf(int elt_idx, uint8_t isoretx) +{ + ASSERT_ERR((((uint16_t)isoretx << 9) & ~((uint16_t)0x00000200)) == 0); + EM_BLE_WR(BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (EM_BLE_RD(BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE) & ~((uint16_t)0x00000200)) | ((uint16_t)isoretx << 9)); +} + +__INLINE uint8_t ble_isorsvd_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + return ((localVal & ((uint16_t)0x00000100)) >> 8); +} + +__INLINE void ble_isorsvd_setf(int elt_idx, uint8_t isorsvd) +{ + ASSERT_ERR((((uint16_t)isorsvd << 8) & ~((uint16_t)0x00000100)) == 0); + EM_BLE_WR(BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (EM_BLE_RD(BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE) & ~((uint16_t)0x00000100)) | ((uint16_t)isorsvd << 8)); +} + +__INLINE uint8_t ble_isowaitack_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + return ((localVal & ((uint16_t)0x00000008)) >> 3); +} + +__INLINE void ble_isowaitack_setf(int elt_idx, uint8_t isowaitack) +{ + ASSERT_ERR((((uint16_t)isowaitack << 3) & ~((uint16_t)0x00000008)) == 0); + EM_BLE_WR(BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (EM_BLE_RD(BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE) & ~((uint16_t)0x00000008)) | ((uint16_t)isowaitack << 3)); +} + +__INLINE uint8_t ble_isolastmd_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + return ((localVal & ((uint16_t)0x00000004)) >> 2); +} + +__INLINE void ble_isolastmd_setf(int elt_idx, uint8_t isolastmd) +{ + ASSERT_ERR((((uint16_t)isolastmd << 2) & ~((uint16_t)0x00000004)) == 0); + EM_BLE_WR(BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (EM_BLE_RD(BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE) & ~((uint16_t)0x00000004)) | ((uint16_t)isolastmd << 2)); +} + +__INLINE uint8_t ble_isolastnesn_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + return ((localVal & ((uint16_t)0x00000002)) >> 1); +} + +__INLINE void ble_isolastnesn_setf(int elt_idx, uint8_t isolastnesn) +{ + ASSERT_ERR((((uint16_t)isolastnesn << 1) & ~((uint16_t)0x00000002)) == 0); + EM_BLE_WR(BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (EM_BLE_RD(BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE) & ~((uint16_t)0x00000002)) | ((uint16_t)isolastnesn << 1)); +} + +__INLINE uint8_t ble_isolastsn_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + return ((localVal & ((uint16_t)0x00000001)) >> 0); +} + +__INLINE void ble_isolastsn_setf(int elt_idx, uint8_t isolastsn) +{ + ASSERT_ERR((((uint16_t)isolastsn << 0) & ~((uint16_t)0x00000001)) == 0); + EM_BLE_WR(BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (EM_BLE_RD(BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE) & ~((uint16_t)0x00000001)) | ((uint16_t)isolastsn << 0)); +} + +/** + * @brief BTCNTSYNC0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00           BTCNTSYNC0   0x0
+ * 
+ */ +#define BLE_BTCNTSYNC0_ADDR (0x00814050 + EM_BLE_CS_OFFSET) +#define BLE_BTCNTSYNC0_INDEX 0x00000028 +#define BLE_BTCNTSYNC0_RESET 0x00000000 + +__INLINE uint16_t ble_btcntsync0_get(int elt_idx) +{ + return EM_BLE_RD(BLE_BTCNTSYNC0_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); +} + +__INLINE void ble_btcntsync0_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_BTCNTSYNC0_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, value); +} + +// field definitions +#define BLE_BTCNTSYNC0_MASK ((uint16_t)0x0000FFFF) +#define BLE_BTCNTSYNC0_LSB 0 +#define BLE_BTCNTSYNC0_WIDTH ((uint16_t)0x00000010) + +#define BLE_BTCNTSYNC0_RST 0x0 + +__INLINE uint16_t ble_btcntsync0_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_BTCNTSYNC0_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_btcntsync0_setf(int elt_idx, uint16_t btcntsync0) +{ + ASSERT_ERR((((uint16_t)btcntsync0 << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(BLE_BTCNTSYNC0_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (uint16_t)btcntsync0 << 0); +} + +/** + * @brief BTCNTSYNC1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  10:00           BTCNTSYNC1   0x0
+ * 
+ */ +#define BLE_BTCNTSYNC1_ADDR (0x00814052 + EM_BLE_CS_OFFSET) +#define BLE_BTCNTSYNC1_INDEX 0x00000029 +#define BLE_BTCNTSYNC1_RESET 0x00000000 + +__INLINE uint16_t ble_btcntsync1_get(int elt_idx) +{ + return EM_BLE_RD(BLE_BTCNTSYNC1_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); +} + +__INLINE void ble_btcntsync1_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_BTCNTSYNC1_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, value); +} + +// field definitions +#define BLE_BTCNTSYNC1_MASK ((uint16_t)0x000007FF) +#define BLE_BTCNTSYNC1_LSB 0 +#define BLE_BTCNTSYNC1_WIDTH ((uint16_t)0x0000000B) + +#define BLE_BTCNTSYNC1_RST 0x0 + +__INLINE uint16_t ble_btcntsync1_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_BTCNTSYNC1_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + ASSERT_ERR((localVal & ~((uint16_t)0x000007FF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_btcntsync1_setf(int elt_idx, uint16_t btcntsync1) +{ + ASSERT_ERR((((uint16_t)btcntsync1 << 0) & ~((uint16_t)0x000007FF)) == 0); + EM_BLE_WR(BLE_BTCNTSYNC1_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (uint16_t)btcntsync1 << 0); +} + +/** + * @brief FCNTSYNC register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     15              EVTRXOK   0
+ *  09:00           FCNTRXSYNC   0x0
+ * 
+ */ +#define BLE_FCNTSYNC_ADDR (0x00814054 + EM_BLE_CS_OFFSET) +#define BLE_FCNTSYNC_INDEX 0x0000002A +#define BLE_FCNTSYNC_RESET 0x00000000 + +__INLINE uint16_t ble_fcntsync_get(int elt_idx) +{ + return EM_BLE_RD(BLE_FCNTSYNC_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); +} + +__INLINE void ble_fcntsync_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_FCNTSYNC_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, value); +} + +// field definitions +#define BLE_EVTRXOK_BIT ((uint16_t)0x00008000) +#define BLE_EVTRXOK_POS 15 +#define BLE_FCNTRXSYNC_MASK ((uint16_t)0x000003FF) +#define BLE_FCNTRXSYNC_LSB 0 +#define BLE_FCNTRXSYNC_WIDTH ((uint16_t)0x0000000A) + +#define BLE_EVTRXOK_RST 0x0 +#define BLE_FCNTRXSYNC_RST 0x0 + +__INLINE void ble_fcntsync_unpack(int elt_idx, uint8_t* evtrxok, uint16_t* fcntrxsync) +{ + uint16_t localVal = EM_BLE_RD(BLE_FCNTSYNC_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + + *evtrxok = (localVal & ((uint16_t)0x00008000)) >> 15; + *fcntrxsync = (localVal & ((uint16_t)0x000003FF)) >> 0; +} + +__INLINE uint8_t ble_evtrxok_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_FCNTSYNC_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + return ((localVal & ((uint16_t)0x00008000)) >> 15); +} + +__INLINE uint16_t ble_fcntrxsync_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_FCNTSYNC_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + return ((localVal & ((uint16_t)0x000003FF)) >> 0); +} + +__INLINE void ble_fcntrxsync_setf(int elt_idx, uint16_t fcntrxsync) +{ + ASSERT_ERR((((uint16_t)fcntrxsync << 0) & ~((uint16_t)0x000003FF)) == 0); + EM_BLE_WR(BLE_FCNTSYNC_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (uint16_t)fcntrxsync << 0); +} + +/** + * @brief TXRXDESCCNT register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:08         ACLRXDESCCNT   0x0
+ *  07:00         ACLTXDESCCNT   0x0
+ * 
+ */ +#define BLE_TXRXDESCCNT_ADDR (0x00814056 + EM_BLE_CS_OFFSET) +#define BLE_TXRXDESCCNT_INDEX 0x0000002B +#define BLE_TXRXDESCCNT_RESET 0x00000000 + +__INLINE uint16_t ble_txrxdesccnt_get(int elt_idx) +{ + return EM_BLE_RD(BLE_TXRXDESCCNT_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); +} + +__INLINE void ble_txrxdesccnt_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_TXRXDESCCNT_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, value); +} + +// field definitions +#define BLE_ACLRXDESCCNT_MASK ((uint16_t)0x0000FF00) +#define BLE_ACLRXDESCCNT_LSB 8 +#define BLE_ACLRXDESCCNT_WIDTH ((uint16_t)0x00000008) +#define BLE_ACLTXDESCCNT_MASK ((uint16_t)0x000000FF) +#define BLE_ACLTXDESCCNT_LSB 0 +#define BLE_ACLTXDESCCNT_WIDTH ((uint16_t)0x00000008) + +#define BLE_ACLRXDESCCNT_RST 0x0 +#define BLE_ACLTXDESCCNT_RST 0x0 + +__INLINE void ble_txrxdesccnt_pack(int elt_idx, uint8_t aclrxdesccnt, uint8_t acltxdesccnt) +{ + ASSERT_ERR((((uint16_t)aclrxdesccnt << 8) & ~((uint16_t)0x0000FF00)) == 0); + ASSERT_ERR((((uint16_t)acltxdesccnt << 0) & ~((uint16_t)0x000000FF)) == 0); + EM_BLE_WR(BLE_TXRXDESCCNT_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, ((uint16_t)aclrxdesccnt << 8) | ((uint16_t)acltxdesccnt << 0)); +} + +__INLINE void ble_txrxdesccnt_unpack(int elt_idx, uint8_t* aclrxdesccnt, uint8_t* acltxdesccnt) +{ + uint16_t localVal = EM_BLE_RD(BLE_TXRXDESCCNT_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + + *aclrxdesccnt = (localVal & ((uint16_t)0x0000FF00)) >> 8; + *acltxdesccnt = (localVal & ((uint16_t)0x000000FF)) >> 0; +} + +__INLINE uint8_t ble_aclrxdesccnt_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_TXRXDESCCNT_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + return ((localVal & ((uint16_t)0x0000FF00)) >> 8); +} + +__INLINE void ble_aclrxdesccnt_setf(int elt_idx, uint8_t aclrxdesccnt) +{ + ASSERT_ERR((((uint16_t)aclrxdesccnt << 8) & ~((uint16_t)0x0000FF00)) == 0); + EM_BLE_WR(BLE_TXRXDESCCNT_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (EM_BLE_RD(BLE_TXRXDESCCNT_ADDR + elt_idx * REG_BLE_EM_CS_SIZE) & ~((uint16_t)0x0000FF00)) | ((uint16_t)aclrxdesccnt << 8)); +} + +__INLINE uint8_t ble_acltxdesccnt_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_TXRXDESCCNT_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + return ((localVal & ((uint16_t)0x000000FF)) >> 0); +} + +__INLINE void ble_acltxdesccnt_setf(int elt_idx, uint8_t acltxdesccnt) +{ + ASSERT_ERR((((uint16_t)acltxdesccnt << 0) & ~((uint16_t)0x000000FF)) == 0); + EM_BLE_WR(BLE_TXRXDESCCNT_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (EM_BLE_RD(BLE_TXRXDESCCNT_ADDR + elt_idx * REG_BLE_EM_CS_SIZE) & ~((uint16_t)0x000000FF)) | ((uint16_t)acltxdesccnt << 0)); +} + +/** + * @brief ISOTXRXPKTCNT register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:08         ISORXPKTCNTL   0x0
+ *  07:00         ISOTXPKTCNTL   0x0
+ * 
+ */ +#define BLE_ISOTXRXPKTCNT_ADDR (0x00814058 + EM_BLE_CS_OFFSET) +#define BLE_ISOTXRXPKTCNT_INDEX 0x0000002C +#define BLE_ISOTXRXPKTCNT_RESET 0x00000000 + +__INLINE uint16_t ble_isotxrxpktcnt_get(int elt_idx) +{ + return EM_BLE_RD(BLE_ISOTXRXPKTCNT_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); +} + +__INLINE void ble_isotxrxpktcnt_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_ISOTXRXPKTCNT_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, value); +} + +// field definitions +#define BLE_ISORXPKTCNTL_MASK ((uint16_t)0x0000FF00) +#define BLE_ISORXPKTCNTL_LSB 8 +#define BLE_ISORXPKTCNTL_WIDTH ((uint16_t)0x00000008) +#define BLE_ISOTXPKTCNTL_MASK ((uint16_t)0x000000FF) +#define BLE_ISOTXPKTCNTL_LSB 0 +#define BLE_ISOTXPKTCNTL_WIDTH ((uint16_t)0x00000008) + +#define BLE_ISORXPKTCNTL_RST 0x0 +#define BLE_ISOTXPKTCNTL_RST 0x0 + +__INLINE void ble_isotxrxpktcnt_pack(int elt_idx, uint8_t isorxpktcntl, uint8_t isotxpktcntl) +{ + ASSERT_ERR((((uint16_t)isorxpktcntl << 8) & ~((uint16_t)0x0000FF00)) == 0); + ASSERT_ERR((((uint16_t)isotxpktcntl << 0) & ~((uint16_t)0x000000FF)) == 0); + EM_BLE_WR(BLE_ISOTXRXPKTCNT_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, ((uint16_t)isorxpktcntl << 8) | ((uint16_t)isotxpktcntl << 0)); +} + +__INLINE void ble_isotxrxpktcnt_unpack(int elt_idx, uint8_t* isorxpktcntl, uint8_t* isotxpktcntl) +{ + uint16_t localVal = EM_BLE_RD(BLE_ISOTXRXPKTCNT_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + + *isorxpktcntl = (localVal & ((uint16_t)0x0000FF00)) >> 8; + *isotxpktcntl = (localVal & ((uint16_t)0x000000FF)) >> 0; +} + +__INLINE uint8_t ble_isorxpktcntl_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_ISOTXRXPKTCNT_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + return ((localVal & ((uint16_t)0x0000FF00)) >> 8); +} + +__INLINE void ble_isorxpktcntl_setf(int elt_idx, uint8_t isorxpktcntl) +{ + ASSERT_ERR((((uint16_t)isorxpktcntl << 8) & ~((uint16_t)0x0000FF00)) == 0); + EM_BLE_WR(BLE_ISOTXRXPKTCNT_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (EM_BLE_RD(BLE_ISOTXRXPKTCNT_ADDR + elt_idx * REG_BLE_EM_CS_SIZE) & ~((uint16_t)0x0000FF00)) | ((uint16_t)isorxpktcntl << 8)); +} + +__INLINE uint8_t ble_isotxpktcntl_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_ISOTXRXPKTCNT_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + return ((localVal & ((uint16_t)0x000000FF)) >> 0); +} + +__INLINE void ble_isotxpktcntl_setf(int elt_idx, uint8_t isotxpktcntl) +{ + ASSERT_ERR((((uint16_t)isotxpktcntl << 0) & ~((uint16_t)0x000000FF)) == 0); + EM_BLE_WR(BLE_ISOTXRXPKTCNT_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (EM_BLE_RD(BLE_ISOTXRXPKTCNT_ADDR + elt_idx * REG_BLE_EM_CS_SIZE) & ~((uint16_t)0x000000FF)) | ((uint16_t)isotxpktcntl << 0)); +} + +/** + * @brief DMPRIOCNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:13          PRIOINCSTEP   0x0
+ *  12:08              MINPRIO   0x0
+ *     07             CONFLICT   0
+ *  04:00          CURRENTPRIO   0x0
+ * 
+ */ +#define BLE_DMPRIOCNTL_ADDR (0x0081405A + EM_BLE_CS_OFFSET) +#define BLE_DMPRIOCNTL_INDEX 0x0000002D +#define BLE_DMPRIOCNTL_RESET 0x00000000 + +__INLINE uint16_t ble_dmpriocntl_get(int elt_idx) +{ + return EM_BLE_RD(BLE_DMPRIOCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); +} + +__INLINE void ble_dmpriocntl_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_DMPRIOCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, value); +} + +// field definitions +#define BLE_PRIOINCSTEP_MASK ((uint16_t)0x0000E000) +#define BLE_PRIOINCSTEP_LSB 13 +#define BLE_PRIOINCSTEP_WIDTH ((uint16_t)0x00000003) +#define BLE_MINPRIO_MASK ((uint16_t)0x00001F00) +#define BLE_MINPRIO_LSB 8 +#define BLE_MINPRIO_WIDTH ((uint16_t)0x00000005) +#define BLE_CONFLICT_BIT ((uint16_t)0x00000080) +#define BLE_CONFLICT_POS 7 +#define BLE_CURRENTPRIO_MASK ((uint16_t)0x0000001F) +#define BLE_CURRENTPRIO_LSB 0 +#define BLE_CURRENTPRIO_WIDTH ((uint16_t)0x00000005) + +#define BLE_PRIOINCSTEP_RST 0x0 +#define BLE_MINPRIO_RST 0x0 +#define BLE_CONFLICT_RST 0x0 +#define BLE_CURRENTPRIO_RST 0x0 + +__INLINE void ble_dmpriocntl_pack(int elt_idx, uint8_t prioincstep, uint8_t minprio, uint8_t conflict, uint8_t currentprio) +{ + ASSERT_ERR((((uint16_t)prioincstep << 13) & ~((uint16_t)0x0000E000)) == 0); + ASSERT_ERR((((uint16_t)minprio << 8) & ~((uint16_t)0x00001F00)) == 0); + ASSERT_ERR((((uint16_t)conflict << 7) & ~((uint16_t)0x00000080)) == 0); + ASSERT_ERR((((uint16_t)currentprio << 0) & ~((uint16_t)0x0000001F)) == 0); + EM_BLE_WR(BLE_DMPRIOCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, ((uint16_t)prioincstep << 13) | ((uint16_t)minprio << 8) | ((uint16_t)conflict << 7) | ((uint16_t)currentprio << 0)); +} + +__INLINE void ble_dmpriocntl_unpack(int elt_idx, uint8_t* prioincstep, uint8_t* minprio, uint8_t* conflict, uint8_t* currentprio) +{ + uint16_t localVal = EM_BLE_RD(BLE_DMPRIOCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + + *prioincstep = (localVal & ((uint16_t)0x0000E000)) >> 13; + *minprio = (localVal & ((uint16_t)0x00001F00)) >> 8; + *conflict = (localVal & ((uint16_t)0x00000080)) >> 7; + *currentprio = (localVal & ((uint16_t)0x0000001F)) >> 0; +} + +__INLINE uint8_t ble_prioincstep_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_DMPRIOCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + return ((localVal & ((uint16_t)0x0000E000)) >> 13); +} + +__INLINE void ble_prioincstep_setf(int elt_idx, uint8_t prioincstep) +{ + ASSERT_ERR((((uint16_t)prioincstep << 13) & ~((uint16_t)0x0000E000)) == 0); + EM_BLE_WR(BLE_DMPRIOCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (EM_BLE_RD(BLE_DMPRIOCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE) & ~((uint16_t)0x0000E000)) | ((uint16_t)prioincstep << 13)); +} + +__INLINE uint8_t ble_minprio_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_DMPRIOCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + return ((localVal & ((uint16_t)0x00001F00)) >> 8); +} + +__INLINE void ble_minprio_setf(int elt_idx, uint8_t minprio) +{ + ASSERT_ERR((((uint16_t)minprio << 8) & ~((uint16_t)0x00001F00)) == 0); + EM_BLE_WR(BLE_DMPRIOCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (EM_BLE_RD(BLE_DMPRIOCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE) & ~((uint16_t)0x00001F00)) | ((uint16_t)minprio << 8)); +} + +__INLINE uint8_t ble_conflict_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_DMPRIOCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + return ((localVal & ((uint16_t)0x00000080)) >> 7); +} + +__INLINE void ble_conflict_setf(int elt_idx, uint8_t conflict) +{ + ASSERT_ERR((((uint16_t)conflict << 7) & ~((uint16_t)0x00000080)) == 0); + EM_BLE_WR(BLE_DMPRIOCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (EM_BLE_RD(BLE_DMPRIOCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE) & ~((uint16_t)0x00000080)) | ((uint16_t)conflict << 7)); +} + +__INLINE uint8_t ble_currentprio_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_DMPRIOCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE); + return ((localVal & ((uint16_t)0x0000001F)) >> 0); +} + +__INLINE void ble_currentprio_setf(int elt_idx, uint8_t currentprio) +{ + ASSERT_ERR((((uint16_t)currentprio << 0) & ~((uint16_t)0x0000001F)) == 0); + EM_BLE_WR(BLE_DMPRIOCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE, (EM_BLE_RD(BLE_DMPRIOCNTL_ADDR + elt_idx * REG_BLE_EM_CS_SIZE) & ~((uint16_t)0x0000001F)) | ((uint16_t)currentprio << 0)); +} + + +#endif // _REG_BLE_EM_CS_H_ + diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/reg_ble_em_ral.h b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/reg_ble_em_ral.h new file mode 100755 index 0000000..289b731 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/reg_ble_em_ral.h @@ -0,0 +1,469 @@ +#ifndef _REG_BLE_EM_RAL_H_ +#define _REG_BLE_EM_RAL_H_ + +#include +#include "_reg_ble_em_ral.h" +#include "ble_compiler.h" +#include "architect.h" +#include "em_map.h" +#include "ble_reg_access.h" + +#define REG_BLE_EM_RAL_COUNT 24 + +#define REG_BLE_EM_RAL_DECODING_MASK 0x0000003F + +#define REG_BLE_EM_RAL_ADDR_GET(idx) (EM_BLE_RAL_OFFSET + (idx) * REG_BLE_EM_RAL_SIZE) + +/** + * @brief RAL_INFO register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     15          ENTRY_VALID   0
+ *     14            CONNECTED   0
+ *     13            IN_WHLIST   0
+ *     07      LOCAL_RPA_VALID   0
+ *     06      LOCAL_RPA_RENEW   0
+ *     05      LOCAL_IRK_VALID   0
+ *     03       PEER_RPA_VALID   0
+ *     02       PEER_RPA_RENEW   0
+ *     01       PEER_IRK_VALID   0
+ *     00         PEER_ID_TYPE   0
+ * 
+ */ +#define BLE_RAL_INFO_ADDR (0x00814000 + EM_BLE_RAL_OFFSET) +#define BLE_RAL_INFO_INDEX 0x00000000 +#define BLE_RAL_INFO_RESET 0x00000000 + +__INLINE uint16_t ble_ral_info_get(int elt_idx) +{ + return EM_BLE_RD(BLE_RAL_INFO_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE); +} + +__INLINE void ble_ral_info_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_RAL_INFO_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE, value); +} + +// field definitions +#define BLE_ENTRY_VALID_BIT ((uint16_t)0x00008000) +#define BLE_ENTRY_VALID_POS 15 +#define BLE_CONNECTED_BIT ((uint16_t)0x00004000) +#define BLE_CONNECTED_POS 14 +#define BLE_IN_WHLIST_BIT ((uint16_t)0x00002000) +#define BLE_IN_WHLIST_POS 13 +#define BLE_LOCAL_RPA_VALID_BIT ((uint16_t)0x00000080) +#define BLE_LOCAL_RPA_VALID_POS 7 +#define BLE_LOCAL_RPA_RENEW_BIT ((uint16_t)0x00000040) +#define BLE_LOCAL_RPA_RENEW_POS 6 +#define BLE_LOCAL_IRK_VALID_BIT ((uint16_t)0x00000020) +#define BLE_LOCAL_IRK_VALID_POS 5 +#define BLE_PEER_RPA_VALID_BIT ((uint16_t)0x00000008) +#define BLE_PEER_RPA_VALID_POS 3 +#define BLE_PEER_RPA_RENEW_BIT ((uint16_t)0x00000004) +#define BLE_PEER_RPA_RENEW_POS 2 +#define BLE_PEER_IRK_VALID_BIT ((uint16_t)0x00000002) +#define BLE_PEER_IRK_VALID_POS 1 +#define BLE_PEER_ID_TYPE_BIT ((uint16_t)0x00000001) +#define BLE_PEER_ID_TYPE_POS 0 + +#define BLE_ENTRY_VALID_RST 0x0 +#define BLE_CONNECTED_RST 0x0 +#define BLE_IN_WHLIST_RST 0x0 +#define BLE_LOCAL_RPA_VALID_RST 0x0 +#define BLE_LOCAL_RPA_RENEW_RST 0x0 +#define BLE_LOCAL_IRK_VALID_RST 0x0 +#define BLE_PEER_RPA_VALID_RST 0x0 +#define BLE_PEER_RPA_RENEW_RST 0x0 +#define BLE_PEER_IRK_VALID_RST 0x0 +#define BLE_PEER_ID_TYPE_RST 0x0 + +__INLINE void ble_ral_info_pack(int elt_idx, uint8_t entryvalid, uint8_t connected, uint8_t inwhlist, uint8_t localrpavalid, uint8_t localrparenew, uint8_t localirkvalid, uint8_t peerrpavalid, uint8_t peerrparenew, uint8_t peerirkvalid, uint8_t peeridtype) +{ + ASSERT_ERR((((uint16_t)entryvalid << 15) & ~((uint16_t)0x00008000)) == 0); + ASSERT_ERR((((uint16_t)connected << 14) & ~((uint16_t)0x00004000)) == 0); + ASSERT_ERR((((uint16_t)inwhlist << 13) & ~((uint16_t)0x00002000)) == 0); + ASSERT_ERR((((uint16_t)localrpavalid << 7) & ~((uint16_t)0x00000080)) == 0); + ASSERT_ERR((((uint16_t)localrparenew << 6) & ~((uint16_t)0x00000040)) == 0); + ASSERT_ERR((((uint16_t)localirkvalid << 5) & ~((uint16_t)0x00000020)) == 0); + ASSERT_ERR((((uint16_t)peerrpavalid << 3) & ~((uint16_t)0x00000008)) == 0); + ASSERT_ERR((((uint16_t)peerrparenew << 2) & ~((uint16_t)0x00000004)) == 0); + ASSERT_ERR((((uint16_t)peerirkvalid << 1) & ~((uint16_t)0x00000002)) == 0); + ASSERT_ERR((((uint16_t)peeridtype << 0) & ~((uint16_t)0x00000001)) == 0); + EM_BLE_WR(BLE_RAL_INFO_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE, ((uint16_t)entryvalid << 15) | ((uint16_t)connected << 14) | ((uint16_t)inwhlist << 13) | ((uint16_t)localrpavalid << 7) | ((uint16_t)localrparenew << 6) | ((uint16_t)localirkvalid << 5) | ((uint16_t)peerrpavalid << 3) | ((uint16_t)peerrparenew << 2) | ((uint16_t)peerirkvalid << 1) | ((uint16_t)peeridtype << 0)); +} + +__INLINE void ble_ral_info_unpack(int elt_idx, uint8_t* entryvalid, uint8_t* connected, uint8_t* inwhlist, uint8_t* localrpavalid, uint8_t* localrparenew, uint8_t* localirkvalid, uint8_t* peerrpavalid, uint8_t* peerrparenew, uint8_t* peerirkvalid, uint8_t* peeridtype) +{ + uint16_t localVal = EM_BLE_RD(BLE_RAL_INFO_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE); + + *entryvalid = (localVal & ((uint16_t)0x00008000)) >> 15; + *connected = (localVal & ((uint16_t)0x00004000)) >> 14; + *inwhlist = (localVal & ((uint16_t)0x00002000)) >> 13; + *localrpavalid = (localVal & ((uint16_t)0x00000080)) >> 7; + *localrparenew = (localVal & ((uint16_t)0x00000040)) >> 6; + *localirkvalid = (localVal & ((uint16_t)0x00000020)) >> 5; + *peerrpavalid = (localVal & ((uint16_t)0x00000008)) >> 3; + *peerrparenew = (localVal & ((uint16_t)0x00000004)) >> 2; + *peerirkvalid = (localVal & ((uint16_t)0x00000002)) >> 1; + *peeridtype = (localVal & ((uint16_t)0x00000001)) >> 0; +} + +__INLINE uint8_t ble_entry_valid_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_RAL_INFO_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE); + return ((localVal & ((uint16_t)0x00008000)) >> 15); +} + +__INLINE void ble_entry_valid_setf(int elt_idx, uint8_t entryvalid) +{ + ASSERT_ERR((((uint16_t)entryvalid << 15) & ~((uint16_t)0x00008000)) == 0); + EM_BLE_WR(BLE_RAL_INFO_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE, (EM_BLE_RD(BLE_RAL_INFO_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE) & ~((uint16_t)0x00008000)) | ((uint16_t)entryvalid << 15)); +} + +__INLINE uint8_t ble_connected_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_RAL_INFO_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE); + return ((localVal & ((uint16_t)0x00004000)) >> 14); +} + +__INLINE void ble_connected_setf(int elt_idx, uint8_t connected) +{ + ASSERT_ERR((((uint16_t)connected << 14) & ~((uint16_t)0x00004000)) == 0); + EM_BLE_WR(BLE_RAL_INFO_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE, (EM_BLE_RD(BLE_RAL_INFO_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE) & ~((uint16_t)0x00004000)) | ((uint16_t)connected << 14)); +} + +__INLINE uint8_t ble_in_whlist_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_RAL_INFO_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE); + return ((localVal & ((uint16_t)0x00002000)) >> 13); +} + +__INLINE void ble_in_whlist_setf(int elt_idx, uint8_t inwhlist) +{ + ASSERT_ERR((((uint16_t)inwhlist << 13) & ~((uint16_t)0x00002000)) == 0); + EM_BLE_WR(BLE_RAL_INFO_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE, (EM_BLE_RD(BLE_RAL_INFO_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE) & ~((uint16_t)0x00002000)) | ((uint16_t)inwhlist << 13)); +} + +__INLINE uint8_t ble_local_rpa_valid_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_RAL_INFO_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE); + return ((localVal & ((uint16_t)0x00000080)) >> 7); +} + +__INLINE void ble_local_rpa_valid_setf(int elt_idx, uint8_t localrpavalid) +{ + ASSERT_ERR((((uint16_t)localrpavalid << 7) & ~((uint16_t)0x00000080)) == 0); + EM_BLE_WR(BLE_RAL_INFO_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE, (EM_BLE_RD(BLE_RAL_INFO_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE) & ~((uint16_t)0x00000080)) | ((uint16_t)localrpavalid << 7)); +} + +__INLINE uint8_t ble_local_rpa_renew_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_RAL_INFO_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE); + return ((localVal & ((uint16_t)0x00000040)) >> 6); +} + +__INLINE void ble_local_rpa_renew_setf(int elt_idx, uint8_t localrparenew) +{ + ASSERT_ERR((((uint16_t)localrparenew << 6) & ~((uint16_t)0x00000040)) == 0); + EM_BLE_WR(BLE_RAL_INFO_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE, (EM_BLE_RD(BLE_RAL_INFO_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE) & ~((uint16_t)0x00000040)) | ((uint16_t)localrparenew << 6)); +} + +__INLINE uint8_t ble_local_irk_valid_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_RAL_INFO_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE); + return ((localVal & ((uint16_t)0x00000020)) >> 5); +} + +__INLINE void ble_local_irk_valid_setf(int elt_idx, uint8_t localirkvalid) +{ + ASSERT_ERR((((uint16_t)localirkvalid << 5) & ~((uint16_t)0x00000020)) == 0); + EM_BLE_WR(BLE_RAL_INFO_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE, (EM_BLE_RD(BLE_RAL_INFO_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE) & ~((uint16_t)0x00000020)) | ((uint16_t)localirkvalid << 5)); +} + +__INLINE uint8_t ble_peer_rpa_valid_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_RAL_INFO_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE); + return ((localVal & ((uint16_t)0x00000008)) >> 3); +} + +__INLINE void ble_peer_rpa_valid_setf(int elt_idx, uint8_t peerrpavalid) +{ + ASSERT_ERR((((uint16_t)peerrpavalid << 3) & ~((uint16_t)0x00000008)) == 0); + EM_BLE_WR(BLE_RAL_INFO_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE, (EM_BLE_RD(BLE_RAL_INFO_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE) & ~((uint16_t)0x00000008)) | ((uint16_t)peerrpavalid << 3)); +} + +__INLINE uint8_t ble_peer_rpa_renew_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_RAL_INFO_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE); + return ((localVal & ((uint16_t)0x00000004)) >> 2); +} + +__INLINE void ble_peer_rpa_renew_setf(int elt_idx, uint8_t peerrparenew) +{ + ASSERT_ERR((((uint16_t)peerrparenew << 2) & ~((uint16_t)0x00000004)) == 0); + EM_BLE_WR(BLE_RAL_INFO_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE, (EM_BLE_RD(BLE_RAL_INFO_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE) & ~((uint16_t)0x00000004)) | ((uint16_t)peerrparenew << 2)); +} + +__INLINE uint8_t ble_peer_irk_valid_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_RAL_INFO_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE); + return ((localVal & ((uint16_t)0x00000002)) >> 1); +} + +__INLINE void ble_peer_irk_valid_setf(int elt_idx, uint8_t peerirkvalid) +{ + ASSERT_ERR((((uint16_t)peerirkvalid << 1) & ~((uint16_t)0x00000002)) == 0); + EM_BLE_WR(BLE_RAL_INFO_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE, (EM_BLE_RD(BLE_RAL_INFO_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE) & ~((uint16_t)0x00000002)) | ((uint16_t)peerirkvalid << 1)); +} + +__INLINE uint8_t ble_peer_id_type_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_RAL_INFO_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE); + return ((localVal & ((uint16_t)0x00000001)) >> 0); +} + +__INLINE void ble_peer_id_type_setf(int elt_idx, uint8_t peeridtype) +{ + ASSERT_ERR((((uint16_t)peeridtype << 0) & ~((uint16_t)0x00000001)) == 0); + EM_BLE_WR(BLE_RAL_INFO_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE, (EM_BLE_RD(BLE_RAL_INFO_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE) & ~((uint16_t)0x00000001)) | ((uint16_t)peeridtype << 0)); +} + +/** + * @brief RAL_PEER_IRK register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00             PEER_IRK   0x0
+ * 
+ */ +#define BLE_RAL_PEER_IRK_ADDR (0x00814002 + EM_BLE_RAL_OFFSET) +#define BLE_RAL_PEER_IRK_INDEX 0x00000001 +#define BLE_RAL_PEER_IRK_RESET 0x00000000 +#define BLE_RAL_PEER_IRK_COUNT 8 + +__INLINE uint16_t ble_ral_peer_irk_get(int elt_idx, int reg_idx) +{ + ASSERT_ERR(reg_idx <= 7); + return EM_BLE_RD(BLE_RAL_PEER_IRK_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE + reg_idx * 2); +} + +__INLINE void ble_ral_peer_irk_set(int elt_idx, int reg_idx, uint16_t value) +{ + ASSERT_ERR(reg_idx <= 7); + EM_BLE_WR(BLE_RAL_PEER_IRK_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE + reg_idx * 2, value); +} + +// field definitions +#define BLE_PEER_IRK_MASK ((uint16_t)0x0000FFFF) +#define BLE_PEER_IRK_LSB 0 +#define BLE_PEER_IRK_WIDTH ((uint16_t)0x00000010) + +#define BLE_PEER_IRK_RST 0x0 + +__INLINE uint16_t ble_peer_irk_getf(int elt_idx, int reg_idx) +{ + ASSERT_ERR(reg_idx <= 7); + uint16_t localVal = EM_BLE_RD(BLE_RAL_PEER_IRK_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE + reg_idx * 2); + ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_peer_irk_setf(int elt_idx, int reg_idx, uint16_t peerirk) +{ + ASSERT_ERR(reg_idx <= 7); + ASSERT_ERR((((uint16_t)peerirk << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(BLE_RAL_PEER_IRK_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE + reg_idx * 2, (uint16_t)peerirk << 0); +} + +/** + * @brief RAL_PEER_RPA register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00             PEER_RPA   0x0
+ * 
+ */ +#define BLE_RAL_PEER_RPA_ADDR (0x00814012 + EM_BLE_RAL_OFFSET) +#define BLE_RAL_PEER_RPA_INDEX 0x00000009 +#define BLE_RAL_PEER_RPA_RESET 0x00000000 +#define BLE_RAL_PEER_RPA_COUNT 3 + +__INLINE uint16_t ble_ral_peer_rpa_get(int elt_idx, int reg_idx) +{ + ASSERT_ERR(reg_idx <= 2); + return EM_BLE_RD(BLE_RAL_PEER_RPA_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE + reg_idx * 2); +} + +__INLINE void ble_ral_peer_rpa_set(int elt_idx, int reg_idx, uint16_t value) +{ + ASSERT_ERR(reg_idx <= 2); + EM_BLE_WR(BLE_RAL_PEER_RPA_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE + reg_idx * 2, value); +} + +// field definitions +#define BLE_PEER_RPA_MASK ((uint16_t)0x0000FFFF) +#define BLE_PEER_RPA_LSB 0 +#define BLE_PEER_RPA_WIDTH ((uint16_t)0x00000010) + +#define BLE_PEER_RPA_RST 0x0 + +__INLINE uint16_t ble_peer_rpa_getf(int elt_idx, int reg_idx) +{ + ASSERT_ERR(reg_idx <= 2); + uint16_t localVal = EM_BLE_RD(BLE_RAL_PEER_RPA_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE + reg_idx * 2); + ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_peer_rpa_setf(int elt_idx, int reg_idx, uint16_t peerrpa) +{ + ASSERT_ERR(reg_idx <= 2); + ASSERT_ERR((((uint16_t)peerrpa << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(BLE_RAL_PEER_RPA_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE + reg_idx * 2, (uint16_t)peerrpa << 0); +} + +/** + * @brief RAL_PEER_ID register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00              PEER_ID   0x0
+ * 
+ */ +#define BLE_RAL_PEER_ID_ADDR (0x00814018 + EM_BLE_RAL_OFFSET) +#define BLE_RAL_PEER_ID_INDEX 0x0000000C +#define BLE_RAL_PEER_ID_RESET 0x00000000 +#define BLE_RAL_PEER_ID_COUNT 3 + +__INLINE uint16_t ble_ral_peer_id_get(int elt_idx, int reg_idx) +{ + ASSERT_ERR(reg_idx <= 2); + return EM_BLE_RD(BLE_RAL_PEER_ID_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE + reg_idx * 2); +} + +__INLINE void ble_ral_peer_id_set(int elt_idx, int reg_idx, uint16_t value) +{ + ASSERT_ERR(reg_idx <= 2); + EM_BLE_WR(BLE_RAL_PEER_ID_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE + reg_idx * 2, value); +} + +// field definitions +#define BLE_PEER_ID_MASK ((uint16_t)0x0000FFFF) +#define BLE_PEER_ID_LSB 0 +#define BLE_PEER_ID_WIDTH ((uint16_t)0x00000010) + +#define BLE_PEER_ID_RST 0x0 + +__INLINE uint16_t ble_peer_id_getf(int elt_idx, int reg_idx) +{ + ASSERT_ERR(reg_idx <= 2); + uint16_t localVal = EM_BLE_RD(BLE_RAL_PEER_ID_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE + reg_idx * 2); + ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_peer_id_setf(int elt_idx, int reg_idx, uint16_t peerid) +{ + ASSERT_ERR(reg_idx <= 2); + ASSERT_ERR((((uint16_t)peerid << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(BLE_RAL_PEER_ID_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE + reg_idx * 2, (uint16_t)peerid << 0); +} + +/** + * @brief RAL_LOCAL_IRK register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00            LOCAL_IRK   0x0
+ * 
+ */ +#define BLE_RAL_LOCAL_IRK_ADDR (0x0081401E + EM_BLE_RAL_OFFSET) +#define BLE_RAL_LOCAL_IRK_INDEX 0x0000000F +#define BLE_RAL_LOCAL_IRK_RESET 0x00000000 +#define BLE_RAL_LOCAL_IRK_COUNT 8 + +__INLINE uint16_t ble_ral_local_irk_get(int elt_idx, int reg_idx) +{ + ASSERT_ERR(reg_idx <= 7); + return EM_BLE_RD(BLE_RAL_LOCAL_IRK_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE + reg_idx * 2); +} + +__INLINE void ble_ral_local_irk_set(int elt_idx, int reg_idx, uint16_t value) +{ + ASSERT_ERR(reg_idx <= 7); + EM_BLE_WR(BLE_RAL_LOCAL_IRK_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE + reg_idx * 2, value); +} + +// field definitions +#define BLE_LOCAL_IRK_MASK ((uint16_t)0x0000FFFF) +#define BLE_LOCAL_IRK_LSB 0 +#define BLE_LOCAL_IRK_WIDTH ((uint16_t)0x00000010) + +#define BLE_LOCAL_IRK_RST 0x0 + +__INLINE uint16_t ble_local_irk_getf(int elt_idx, int reg_idx) +{ + ASSERT_ERR(reg_idx <= 7); + uint16_t localVal = EM_BLE_RD(BLE_RAL_LOCAL_IRK_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE + reg_idx * 2); + ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_local_irk_setf(int elt_idx, int reg_idx, uint16_t localirk) +{ + ASSERT_ERR(reg_idx <= 7); + ASSERT_ERR((((uint16_t)localirk << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(BLE_RAL_LOCAL_IRK_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE + reg_idx * 2, (uint16_t)localirk << 0); +} + +/** + * @brief RAL_LOCAL_RPA register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00            LOCAL_RPA   0x0
+ * 
+ */ +#define BLE_RAL_LOCAL_RPA_ADDR (0x0081402E + EM_BLE_RAL_OFFSET) +#define BLE_RAL_LOCAL_RPA_INDEX 0x00000017 +#define BLE_RAL_LOCAL_RPA_RESET 0x00000000 +#define BLE_RAL_LOCAL_RPA_COUNT 3 + +__INLINE uint16_t ble_ral_local_rpa_get(int elt_idx, int reg_idx) +{ + ASSERT_ERR(reg_idx <= 2); + return EM_BLE_RD(BLE_RAL_LOCAL_RPA_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE + reg_idx * 2); +} + +__INLINE void ble_ral_local_rpa_set(int elt_idx, int reg_idx, uint16_t value) +{ + ASSERT_ERR(reg_idx <= 2); + EM_BLE_WR(BLE_RAL_LOCAL_RPA_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE + reg_idx * 2, value); +} + +// field definitions +#define BLE_LOCAL_RPA_MASK ((uint16_t)0x0000FFFF) +#define BLE_LOCAL_RPA_LSB 0 +#define BLE_LOCAL_RPA_WIDTH ((uint16_t)0x00000010) + +#define BLE_LOCAL_RPA_RST 0x0 + +__INLINE uint16_t ble_local_rpa_getf(int elt_idx, int reg_idx) +{ + ASSERT_ERR(reg_idx <= 2); + uint16_t localVal = EM_BLE_RD(BLE_RAL_LOCAL_RPA_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE + reg_idx * 2); + ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_local_rpa_setf(int elt_idx, int reg_idx, uint16_t localrpa) +{ + ASSERT_ERR(reg_idx <= 2); + ASSERT_ERR((((uint16_t)localrpa << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(BLE_RAL_LOCAL_RPA_ADDR + elt_idx * REG_BLE_EM_RAL_SIZE + reg_idx * 2, (uint16_t)localrpa << 0); +} + + +#endif // _REG_BLE_EM_RAL_H_ + diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/reg_ble_em_rx_audio_buffer.h b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/reg_ble_em_rx_audio_buffer.h new file mode 100755 index 0000000..3996856 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/reg_ble_em_rx_audio_buffer.h @@ -0,0 +1,66 @@ +#ifndef _REG_BLE_EM_RX_AUDIO_BUFFER_H_ +#define _REG_BLE_EM_RX_AUDIO_BUFFER_H_ + +#include +#include "_reg_ble_em_rx_audio_buffer.h" +#include "ble_compiler.h" +#include "architect.h" +#include "em_map.h" +#include "ble_reg_access.h" + +#define REG_BLE_EM_RX_AUDIO_BUFFER_COUNT 1 + +#define REG_BLE_EM_RX_AUDIO_BUFFER_DECODING_MASK 0x00000000 + +#define REG_BLE_EM_RX_AUDIO_BUFFER_ADDR_GET(idx) (EM_BLE_RX_AUDIO_BUFFER_OFFSET + (idx) * REG_BLE_EM_RX_AUDIO_BUFFER_SIZE) + +/** + * @brief RXAUDIOBUF register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00           RXAUDIOBUF   0x0
+ * 
+ */ +#define BLE_RXAUDIOBUF_ADDR (0x00814000 + EM_BLE_RX_AUDIO_BUFFER_OFFSET) +#define BLE_RXAUDIOBUF_INDEX 0x00000000 +#define BLE_RXAUDIOBUF_RESET 0x00000000 +#define BLE_RXAUDIOBUF_COUNT 32 + +__INLINE uint16_t ble_rxaudiobuf_get(int elt_idx, int reg_idx) +{ + ASSERT_ERR(reg_idx <= 31); + return EM_BLE_RD(BLE_RXAUDIOBUF_ADDR + elt_idx * REG_BLE_EM_RX_AUDIO_BUFFER_SIZE + reg_idx * 2); +} + +__INLINE void ble_rxaudiobuf_set(int elt_idx, int reg_idx, uint16_t value) +{ + ASSERT_ERR(reg_idx <= 31); + EM_BLE_WR(BLE_RXAUDIOBUF_ADDR + elt_idx * REG_BLE_EM_RX_AUDIO_BUFFER_SIZE + reg_idx * 2, value); +} + +// field definitions +#define BLE_RXAUDIOBUF_MASK ((uint16_t)0x0000FFFF) +#define BLE_RXAUDIOBUF_LSB 0 +#define BLE_RXAUDIOBUF_WIDTH ((uint16_t)0x00000010) + +#define BLE_RXAUDIOBUF_RST 0x0 + +__INLINE uint16_t ble_rxaudiobuf_getf(int elt_idx, int reg_idx) +{ + ASSERT_ERR(reg_idx <= 31); + uint16_t localVal = EM_BLE_RD(BLE_RXAUDIOBUF_ADDR + elt_idx * REG_BLE_EM_RX_AUDIO_BUFFER_SIZE + reg_idx * 2); + ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_rxaudiobuf_setf(int elt_idx, int reg_idx, uint16_t rxaudiobuf) +{ + ASSERT_ERR(reg_idx <= 31); + ASSERT_ERR((((uint16_t)rxaudiobuf << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(BLE_RXAUDIOBUF_ADDR + elt_idx * REG_BLE_EM_RX_AUDIO_BUFFER_SIZE + reg_idx * 2, (uint16_t)rxaudiobuf << 0); +} + + +#endif // _REG_BLE_EM_RX_AUDIO_BUFFER_H_ + diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/reg_ble_em_rx_buffer.h b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/reg_ble_em_rx_buffer.h new file mode 100755 index 0000000..fe5cd9d --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/reg_ble_em_rx_buffer.h @@ -0,0 +1,66 @@ +#ifndef _REG_BLE_EM_RX_BUFFER_H_ +#define _REG_BLE_EM_RX_BUFFER_H_ + +#include +#include "_reg_ble_em_rx_buffer.h" +#include "ble_compiler.h" +#include "architect.h" +#include "em_map.h" +#include "ble_reg_access.h" + +#define REG_BLE_EM_RX_BUFFER_COUNT 1 + +#define REG_BLE_EM_RX_BUFFER_DECODING_MASK 0x00000000 + +#define REG_BLE_EM_RX_BUFFER_ADDR_GET(idx) (EM_BLE_RX_BUFFER_OFFSET + (idx) * REG_BLE_EM_RX_BUFFER_SIZE) + +/** + * @brief RXBUF register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00                RXBUF   0x0
+ * 
+ */ +#define BLE_RXBUF_ADDR (0x00814000 + EM_BLE_RX_BUFFER_OFFSET) +#define BLE_RXBUF_INDEX 0x00000000 +#define BLE_RXBUF_RESET 0x00000000 +#define BLE_RXBUF_COUNT 130 + +__INLINE uint16_t ble_rxbuf_get(int elt_idx, int reg_idx) +{ + ASSERT_ERR(reg_idx <= 129); + return EM_BLE_RD(BLE_RXBUF_ADDR + elt_idx * REG_BLE_EM_RX_BUFFER_SIZE + reg_idx * 2); +} + +__INLINE void ble_rxbuf_set(int elt_idx, int reg_idx, uint16_t value) +{ + ASSERT_ERR(reg_idx <= 129); + EM_BLE_WR(BLE_RXBUF_ADDR + elt_idx * REG_BLE_EM_RX_BUFFER_SIZE + reg_idx * 2, value); +} + +// field definitions +#define BLE_RXBUF_MASK ((uint16_t)0x0000FFFF) +#define BLE_RXBUF_LSB 0 +#define BLE_RXBUF_WIDTH ((uint16_t)0x00000010) + +#define BLE_RXBUF_RST 0x0 + +__INLINE uint16_t ble_rxbuf_getf(int elt_idx, int reg_idx) +{ + ASSERT_ERR(reg_idx <= 129); + uint16_t localVal = EM_BLE_RD(BLE_RXBUF_ADDR + elt_idx * REG_BLE_EM_RX_BUFFER_SIZE + reg_idx * 2); + ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_rxbuf_setf(int elt_idx, int reg_idx, uint16_t rxbuf) +{ + ASSERT_ERR(reg_idx <= 129); + ASSERT_ERR((((uint16_t)rxbuf << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(BLE_RXBUF_ADDR + elt_idx * REG_BLE_EM_RX_BUFFER_SIZE + reg_idx * 2, (uint16_t)rxbuf << 0); +} + + +#endif // _REG_BLE_EM_RX_BUFFER_H_ + diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/reg_ble_em_rx_desc.h b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/reg_ble_em_rx_desc.h new file mode 100755 index 0000000..86ed178 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/reg_ble_em_rx_desc.h @@ -0,0 +1,754 @@ +#ifndef _REG_BLE_EM_RX_DESC_H_ +#define _REG_BLE_EM_RX_DESC_H_ + +#include +#include "_reg_ble_em_rx_desc.h" +#include "ble_compiler.h" +#include "architect.h" +#include "em_map.h" +#include "ble_reg_access.h" + +#define REG_BLE_EM_RX_DESC_COUNT 6 + +#define REG_BLE_EM_RX_DESC_DECODING_MASK 0x0000000F + +#define REG_BLE_EM_RX_DESC_ADDR_GET(idx) (EM_BLE_RX_DESC_OFFSET + (idx) * REG_BLE_EM_RX_DESC_SIZE) + +/** + * @brief RXCNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     15               RXDONE   0
+ *  14:00            RXNEXTPTR   0x0
+ * 
+ */ +#define BLE_RXCNTL_ADDR (0x00814000 + EM_BLE_RX_DESC_OFFSET) +#define BLE_RXCNTL_INDEX 0x00000000 +#define BLE_RXCNTL_RESET 0x00000000 + +__INLINE uint16_t ble_rxcntl_get(int elt_idx) +{ + return EM_BLE_RD(BLE_RXCNTL_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE); +} + +__INLINE void ble_rxcntl_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_RXCNTL_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE, value); +} + +// field definitions +#define BLE_RXDONE_BIT ((uint16_t)0x00008000) +#define BLE_RXDONE_POS 15 +#define BLE_RXNEXTPTR_MASK ((uint16_t)0x00007FFF) +#define BLE_RXNEXTPTR_LSB 0 +#define BLE_RXNEXTPTR_WIDTH ((uint16_t)0x0000000F) + +#define BLE_RXDONE_RST 0x0 +#define BLE_RXNEXTPTR_RST 0x0 + +__INLINE void ble_rxcntl_pack(int elt_idx, uint8_t rxdone, uint16_t rxnextptr) +{ + ASSERT_ERR((((uint16_t)rxdone << 15) & ~((uint16_t)0x00008000)) == 0); + ASSERT_ERR((((uint16_t)rxnextptr << 0) & ~((uint16_t)0x00007FFF)) == 0); + EM_BLE_WR(BLE_RXCNTL_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE, ((uint16_t)rxdone << 15) | ((uint16_t)rxnextptr << 0)); +} + +__INLINE void ble_rxcntl_unpack(int elt_idx, uint8_t* rxdone, uint16_t* rxnextptr) +{ + uint16_t localVal = EM_BLE_RD(BLE_RXCNTL_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE); + + *rxdone = (localVal & ((uint16_t)0x00008000)) >> 15; + *rxnextptr = (localVal & ((uint16_t)0x00007FFF)) >> 0; +} + +__INLINE uint8_t ble_rxdone_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_RXCNTL_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00008000)) >> 15); +} + +__INLINE void ble_rxdone_setf(int elt_idx, uint8_t rxdone) +{ + ASSERT_ERR((((uint16_t)rxdone << 15) & ~((uint16_t)0x00008000)) == 0); + EM_BLE_WR(BLE_RXCNTL_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE, (EM_BLE_RD(BLE_RXCNTL_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE) & ~((uint16_t)0x00008000)) | ((uint16_t)rxdone << 15)); +} + +__INLINE uint16_t ble_rxnextptr_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_RXCNTL_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00007FFF)) >> 0); +} + +__INLINE void ble_rxnextptr_setf(int elt_idx, uint16_t rxnextptr) +{ + ASSERT_ERR((((uint16_t)rxnextptr << 0) & ~((uint16_t)0x00007FFF)) == 0); + EM_BLE_WR(BLE_RXCNTL_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE, (EM_BLE_RD(BLE_RXCNTL_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE) & ~((uint16_t)0x00007FFF)) | ((uint16_t)rxnextptr << 0)); +} + +/** + * @brief RXSTAT register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:11            RXLINKLBL   0x0
+ *     10       PEER_ADD_MATCH   0
+ *     09           PRIV_ERROR   0
+ *     08            RXTIMEERR   0
+ *     07         BDADDR_MATCH   0
+ *     06             NESN_ERR   0
+ *     05               SN_ERR   0
+ *     04              MIC_ERR   0
+ *     03              CRC_ERR   0
+ *     02              LEN_ERR   0
+ *     01             TYPE_ERR   0
+ *     00             SYNC_ERR   0
+ * 
+ */ +#define BLE_RXSTAT_ADDR (0x00814002 + EM_BLE_RX_DESC_OFFSET) +#define BLE_RXSTAT_INDEX 0x00000001 +#define BLE_RXSTAT_RESET 0x00000000 + +__INLINE uint16_t ble_rxstat_get(int elt_idx) +{ + return EM_BLE_RD(BLE_RXSTAT_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE); +} + +__INLINE void ble_rxstat_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_RXSTAT_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE, value); +} + +// field definitions +#define BLE_RXLINKLBL_MASK ((uint16_t)0x0000F800) +#define BLE_RXLINKLBL_LSB 11 +#define BLE_RXLINKLBL_WIDTH ((uint16_t)0x00000005) +#define BLE_PEER_ADD_MATCH_BIT ((uint16_t)0x00000400) +#define BLE_PEER_ADD_MATCH_POS 10 +#define BLE_PRIV_ERROR_BIT ((uint16_t)0x00000200) +#define BLE_PRIV_ERROR_POS 9 +#define BLE_RXTIMEERR_BIT ((uint16_t)0x00000100) +#define BLE_RXTIMEERR_POS 8 +#define BLE_BDADDR_MATCH_BIT ((uint16_t)0x00000080) +#define BLE_BDADDR_MATCH_POS 7 +#define BLE_NESN_ERR_BIT ((uint16_t)0x00000040) +#define BLE_NESN_ERR_POS 6 +#define BLE_SN_ERR_BIT ((uint16_t)0x00000020) +#define BLE_SN_ERR_POS 5 +#define BLE_MIC_ERR_BIT ((uint16_t)0x00000010) +#define BLE_MIC_ERR_POS 4 +#define BLE_CRC_ERR_BIT ((uint16_t)0x00000008) +#define BLE_CRC_ERR_POS 3 +#define BLE_LEN_ERR_BIT ((uint16_t)0x00000004) +#define BLE_LEN_ERR_POS 2 +#define BLE_TYPE_ERR_BIT ((uint16_t)0x00000002) +#define BLE_TYPE_ERR_POS 1 +#define BLE_SYNC_ERR_BIT ((uint16_t)0x00000001) +#define BLE_SYNC_ERR_POS 0 + +#define BLE_RXLINKLBL_RST 0x0 +#define BLE_PEER_ADD_MATCH_RST 0x0 +#define BLE_PRIV_ERROR_RST 0x0 +#define BLE_RXTIMEERR_RST 0x0 +#define BLE_BDADDR_MATCH_RST 0x0 +#define BLE_NESN_ERR_RST 0x0 +#define BLE_SN_ERR_RST 0x0 +#define BLE_MIC_ERR_RST 0x0 +#define BLE_CRC_ERR_RST 0x0 +#define BLE_LEN_ERR_RST 0x0 +#define BLE_TYPE_ERR_RST 0x0 +#define BLE_SYNC_ERR_RST 0x0 + +__INLINE void ble_rxstat_pack(int elt_idx, uint8_t rxlinklbl, uint8_t peeraddmatch, uint8_t priverror, uint8_t rxtimeerr, uint8_t bdaddrmatch, uint8_t nesnerr, uint8_t snerr, uint8_t micerr, uint8_t crcerr, uint8_t lenerr, uint8_t typeerr, uint8_t syncerr) +{ + ASSERT_ERR((((uint16_t)rxlinklbl << 11) & ~((uint16_t)0x0000F800)) == 0); + ASSERT_ERR((((uint16_t)peeraddmatch << 10) & ~((uint16_t)0x00000400)) == 0); + ASSERT_ERR((((uint16_t)priverror << 9) & ~((uint16_t)0x00000200)) == 0); + ASSERT_ERR((((uint16_t)rxtimeerr << 8) & ~((uint16_t)0x00000100)) == 0); + ASSERT_ERR((((uint16_t)bdaddrmatch << 7) & ~((uint16_t)0x00000080)) == 0); + ASSERT_ERR((((uint16_t)nesnerr << 6) & ~((uint16_t)0x00000040)) == 0); + ASSERT_ERR((((uint16_t)snerr << 5) & ~((uint16_t)0x00000020)) == 0); + ASSERT_ERR((((uint16_t)micerr << 4) & ~((uint16_t)0x00000010)) == 0); + ASSERT_ERR((((uint16_t)crcerr << 3) & ~((uint16_t)0x00000008)) == 0); + ASSERT_ERR((((uint16_t)lenerr << 2) & ~((uint16_t)0x00000004)) == 0); + ASSERT_ERR((((uint16_t)typeerr << 1) & ~((uint16_t)0x00000002)) == 0); + ASSERT_ERR((((uint16_t)syncerr << 0) & ~((uint16_t)0x00000001)) == 0); + EM_BLE_WR(BLE_RXSTAT_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE, ((uint16_t)rxlinklbl << 11) | ((uint16_t)peeraddmatch << 10) | ((uint16_t)priverror << 9) | ((uint16_t)rxtimeerr << 8) | ((uint16_t)bdaddrmatch << 7) | ((uint16_t)nesnerr << 6) | ((uint16_t)snerr << 5) | ((uint16_t)micerr << 4) | ((uint16_t)crcerr << 3) | ((uint16_t)lenerr << 2) | ((uint16_t)typeerr << 1) | ((uint16_t)syncerr << 0)); +} + +__INLINE void ble_rxstat_unpack(int elt_idx, uint8_t* rxlinklbl, uint8_t* peeraddmatch, uint8_t* priverror, uint8_t* rxtimeerr, uint8_t* bdaddrmatch, uint8_t* nesnerr, uint8_t* snerr, uint8_t* micerr, uint8_t* crcerr, uint8_t* lenerr, uint8_t* typeerr, uint8_t* syncerr) +{ + uint16_t localVal = EM_BLE_RD(BLE_RXSTAT_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE); + + *rxlinklbl = (localVal & ((uint16_t)0x0000F800)) >> 11; + *peeraddmatch = (localVal & ((uint16_t)0x00000400)) >> 10; + *priverror = (localVal & ((uint16_t)0x00000200)) >> 9; + *rxtimeerr = (localVal & ((uint16_t)0x00000100)) >> 8; + *bdaddrmatch = (localVal & ((uint16_t)0x00000080)) >> 7; + *nesnerr = (localVal & ((uint16_t)0x00000040)) >> 6; + *snerr = (localVal & ((uint16_t)0x00000020)) >> 5; + *micerr = (localVal & ((uint16_t)0x00000010)) >> 4; + *crcerr = (localVal & ((uint16_t)0x00000008)) >> 3; + *lenerr = (localVal & ((uint16_t)0x00000004)) >> 2; + *typeerr = (localVal & ((uint16_t)0x00000002)) >> 1; + *syncerr = (localVal & ((uint16_t)0x00000001)) >> 0; +} + +__INLINE uint8_t ble_rxlinklbl_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_RXSTAT_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x0000F800)) >> 11); +} + +__INLINE void ble_rxlinklbl_setf(int elt_idx, uint8_t rxlinklbl) +{ + ASSERT_ERR((((uint16_t)rxlinklbl << 11) & ~((uint16_t)0x0000F800)) == 0); + EM_BLE_WR(BLE_RXSTAT_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE, (EM_BLE_RD(BLE_RXSTAT_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE) & ~((uint16_t)0x0000F800)) | ((uint16_t)rxlinklbl << 11)); +} + +__INLINE uint8_t ble_peer_add_match_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_RXSTAT_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000400)) >> 10); +} + +__INLINE void ble_peer_add_match_setf(int elt_idx, uint8_t peeraddmatch) +{ + ASSERT_ERR((((uint16_t)peeraddmatch << 10) & ~((uint16_t)0x00000400)) == 0); + EM_BLE_WR(BLE_RXSTAT_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE, (EM_BLE_RD(BLE_RXSTAT_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE) & ~((uint16_t)0x00000400)) | ((uint16_t)peeraddmatch << 10)); +} + +__INLINE uint8_t ble_priv_error_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_RXSTAT_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000200)) >> 9); +} + +__INLINE void ble_priv_error_setf(int elt_idx, uint8_t priverror) +{ + ASSERT_ERR((((uint16_t)priverror << 9) & ~((uint16_t)0x00000200)) == 0); + EM_BLE_WR(BLE_RXSTAT_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE, (EM_BLE_RD(BLE_RXSTAT_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE) & ~((uint16_t)0x00000200)) | ((uint16_t)priverror << 9)); +} + +__INLINE uint8_t ble_rxtimeerr_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_RXSTAT_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000100)) >> 8); +} + +__INLINE void ble_rxtimeerr_setf(int elt_idx, uint8_t rxtimeerr) +{ + ASSERT_ERR((((uint16_t)rxtimeerr << 8) & ~((uint16_t)0x00000100)) == 0); + EM_BLE_WR(BLE_RXSTAT_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE, (EM_BLE_RD(BLE_RXSTAT_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE) & ~((uint16_t)0x00000100)) | ((uint16_t)rxtimeerr << 8)); +} + +__INLINE uint8_t ble_bdaddr_match_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_RXSTAT_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000080)) >> 7); +} + +__INLINE void ble_bdaddr_match_setf(int elt_idx, uint8_t bdaddrmatch) +{ + ASSERT_ERR((((uint16_t)bdaddrmatch << 7) & ~((uint16_t)0x00000080)) == 0); + EM_BLE_WR(BLE_RXSTAT_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE, (EM_BLE_RD(BLE_RXSTAT_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE) & ~((uint16_t)0x00000080)) | ((uint16_t)bdaddrmatch << 7)); +} + +__INLINE uint8_t ble_nesn_err_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_RXSTAT_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000040)) >> 6); +} + +__INLINE void ble_nesn_err_setf(int elt_idx, uint8_t nesnerr) +{ + ASSERT_ERR((((uint16_t)nesnerr << 6) & ~((uint16_t)0x00000040)) == 0); + EM_BLE_WR(BLE_RXSTAT_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE, (EM_BLE_RD(BLE_RXSTAT_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE) & ~((uint16_t)0x00000040)) | ((uint16_t)nesnerr << 6)); +} + +__INLINE uint8_t ble_sn_err_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_RXSTAT_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000020)) >> 5); +} + +__INLINE void ble_sn_err_setf(int elt_idx, uint8_t snerr) +{ + ASSERT_ERR((((uint16_t)snerr << 5) & ~((uint16_t)0x00000020)) == 0); + EM_BLE_WR(BLE_RXSTAT_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE, (EM_BLE_RD(BLE_RXSTAT_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE) & ~((uint16_t)0x00000020)) | ((uint16_t)snerr << 5)); +} + +__INLINE uint8_t ble_mic_err_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_RXSTAT_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000010)) >> 4); +} + +__INLINE void ble_mic_err_setf(int elt_idx, uint8_t micerr) +{ + ASSERT_ERR((((uint16_t)micerr << 4) & ~((uint16_t)0x00000010)) == 0); + EM_BLE_WR(BLE_RXSTAT_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE, (EM_BLE_RD(BLE_RXSTAT_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE) & ~((uint16_t)0x00000010)) | ((uint16_t)micerr << 4)); +} + +__INLINE uint8_t ble_crc_err_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_RXSTAT_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000008)) >> 3); +} + +__INLINE void ble_crc_err_setf(int elt_idx, uint8_t crcerr) +{ + ASSERT_ERR((((uint16_t)crcerr << 3) & ~((uint16_t)0x00000008)) == 0); + EM_BLE_WR(BLE_RXSTAT_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE, (EM_BLE_RD(BLE_RXSTAT_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE) & ~((uint16_t)0x00000008)) | ((uint16_t)crcerr << 3)); +} + +__INLINE uint8_t ble_len_err_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_RXSTAT_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000004)) >> 2); +} + +__INLINE void ble_len_err_setf(int elt_idx, uint8_t lenerr) +{ + ASSERT_ERR((((uint16_t)lenerr << 2) & ~((uint16_t)0x00000004)) == 0); + EM_BLE_WR(BLE_RXSTAT_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE, (EM_BLE_RD(BLE_RXSTAT_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE) & ~((uint16_t)0x00000004)) | ((uint16_t)lenerr << 2)); +} + +__INLINE uint8_t ble_type_err_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_RXSTAT_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000002)) >> 1); +} + +__INLINE void ble_type_err_setf(int elt_idx, uint8_t typeerr) +{ + ASSERT_ERR((((uint16_t)typeerr << 1) & ~((uint16_t)0x00000002)) == 0); + EM_BLE_WR(BLE_RXSTAT_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE, (EM_BLE_RD(BLE_RXSTAT_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE) & ~((uint16_t)0x00000002)) | ((uint16_t)typeerr << 1)); +} + +__INLINE uint8_t ble_sync_err_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_RXSTAT_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000001)) >> 0); +} + +__INLINE void ble_sync_err_setf(int elt_idx, uint8_t syncerr) +{ + ASSERT_ERR((((uint16_t)syncerr << 0) & ~((uint16_t)0x00000001)) == 0); + EM_BLE_WR(BLE_RXSTAT_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE, (EM_BLE_RD(BLE_RXSTAT_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE) & ~((uint16_t)0x00000001)) | ((uint16_t)syncerr << 0)); +} + +/** + * @brief RXPHCE register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:08                RXLEN   0x0
+ *     04                 RXMD   0
+ *     03                 RXSN   0
+ *     02               RXNESN   0
+ *  01:00               RXLLID   0x0
+ * 
+ */ +#define BLE_RXPHCE_ADDR (0x00814004 + EM_BLE_RX_DESC_OFFSET) +#define BLE_RXPHCE_INDEX 0x00000002 +#define BLE_RXPHCE_RESET 0x00000000 + +__INLINE uint16_t ble_rxphce_get(int elt_idx) +{ + return EM_BLE_RD(BLE_RXPHCE_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE); +} + +__INLINE void ble_rxphce_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_RXPHCE_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE, value); +} + +// field definitions +#define BLE_RXLEN_MASK ((uint16_t)0x0000FF00) +#define BLE_RXLEN_LSB 8 +#define BLE_RXLEN_WIDTH ((uint16_t)0x00000008) +#define BLE_RXMD_BIT ((uint16_t)0x00000010) +#define BLE_RXMD_POS 4 +#define BLE_RXSN_BIT ((uint16_t)0x00000008) +#define BLE_RXSN_POS 3 +#define BLE_RXNESN_BIT ((uint16_t)0x00000004) +#define BLE_RXNESN_POS 2 +#define BLE_RXLLID_MASK ((uint16_t)0x00000003) +#define BLE_RXLLID_LSB 0 +#define BLE_RXLLID_WIDTH ((uint16_t)0x00000002) + +#define BLE_RXLEN_RST 0x0 +#define BLE_RXMD_RST 0x0 +#define BLE_RXSN_RST 0x0 +#define BLE_RXNESN_RST 0x0 +#define BLE_RXLLID_RST 0x0 + +__INLINE void ble_rxphce_pack(int elt_idx, uint8_t rxlen, uint8_t rxmd, uint8_t rxsn, uint8_t rxnesn, uint8_t rxllid) +{ + ASSERT_ERR((((uint16_t)rxlen << 8) & ~((uint16_t)0x0000FF00)) == 0); + ASSERT_ERR((((uint16_t)rxmd << 4) & ~((uint16_t)0x00000010)) == 0); + ASSERT_ERR((((uint16_t)rxsn << 3) & ~((uint16_t)0x00000008)) == 0); + ASSERT_ERR((((uint16_t)rxnesn << 2) & ~((uint16_t)0x00000004)) == 0); + ASSERT_ERR((((uint16_t)rxllid << 0) & ~((uint16_t)0x00000003)) == 0); + EM_BLE_WR(BLE_RXPHCE_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE, ((uint16_t)rxlen << 8) | ((uint16_t)rxmd << 4) | ((uint16_t)rxsn << 3) | ((uint16_t)rxnesn << 2) | ((uint16_t)rxllid << 0)); +} + +__INLINE void ble_rxphce_unpack(int elt_idx, uint8_t* rxlen, uint8_t* rxmd, uint8_t* rxsn, uint8_t* rxnesn, uint8_t* rxllid) +{ + uint16_t localVal = EM_BLE_RD(BLE_RXPHCE_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE); + + *rxlen = (localVal & ((uint16_t)0x0000FF00)) >> 8; + *rxmd = (localVal & ((uint16_t)0x00000010)) >> 4; + *rxsn = (localVal & ((uint16_t)0x00000008)) >> 3; + *rxnesn = (localVal & ((uint16_t)0x00000004)) >> 2; + *rxllid = (localVal & ((uint16_t)0x00000003)) >> 0; +} + +__INLINE uint8_t ble_rxlen_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_RXPHCE_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x0000FF00)) >> 8); +} + +__INLINE void ble_rxlen_setf(int elt_idx, uint8_t rxlen) +{ + ASSERT_ERR((((uint16_t)rxlen << 8) & ~((uint16_t)0x0000FF00)) == 0); + EM_BLE_WR(BLE_RXPHCE_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE, (EM_BLE_RD(BLE_RXPHCE_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE) & ~((uint16_t)0x0000FF00)) | ((uint16_t)rxlen << 8)); +} + +__INLINE uint8_t ble_rxmd_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_RXPHCE_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000010)) >> 4); +} + +__INLINE void ble_rxmd_setf(int elt_idx, uint8_t rxmd) +{ + ASSERT_ERR((((uint16_t)rxmd << 4) & ~((uint16_t)0x00000010)) == 0); + EM_BLE_WR(BLE_RXPHCE_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE, (EM_BLE_RD(BLE_RXPHCE_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE) & ~((uint16_t)0x00000010)) | ((uint16_t)rxmd << 4)); +} + +__INLINE uint8_t ble_rxsn_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_RXPHCE_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000008)) >> 3); +} + +__INLINE void ble_rxsn_setf(int elt_idx, uint8_t rxsn) +{ + ASSERT_ERR((((uint16_t)rxsn << 3) & ~((uint16_t)0x00000008)) == 0); + EM_BLE_WR(BLE_RXPHCE_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE, (EM_BLE_RD(BLE_RXPHCE_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE) & ~((uint16_t)0x00000008)) | ((uint16_t)rxsn << 3)); +} + +__INLINE uint8_t ble_rxnesn_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_RXPHCE_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000004)) >> 2); +} + +__INLINE void ble_rxnesn_setf(int elt_idx, uint8_t rxnesn) +{ + ASSERT_ERR((((uint16_t)rxnesn << 2) & ~((uint16_t)0x00000004)) == 0); + EM_BLE_WR(BLE_RXPHCE_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE, (EM_BLE_RD(BLE_RXPHCE_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE) & ~((uint16_t)0x00000004)) | ((uint16_t)rxnesn << 2)); +} + +__INLINE uint8_t ble_rxllid_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_RXPHCE_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000003)) >> 0); +} + +__INLINE void ble_rxllid_setf(int elt_idx, uint8_t rxllid) +{ + ASSERT_ERR((((uint16_t)rxllid << 0) & ~((uint16_t)0x00000003)) == 0); + EM_BLE_WR(BLE_RXPHCE_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE, (EM_BLE_RD(BLE_RXPHCE_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE) & ~((uint16_t)0x00000003)) | ((uint16_t)rxllid << 0)); +} + +/** + * @brief RXPHADV register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:08             RXADVLEN   0x0
+ *     07              RXRXADD   0
+ *     06              RXTXADD   0
+ *  03:00               RXTYPE   0x0
+ * 
+ */ +#define BLE_RXPHADV_ADDR (0x00814004 + EM_BLE_RX_DESC_OFFSET) +#define BLE_RXPHADV_INDEX 0x00000002 +#define BLE_RXPHADV_RESET 0x00000000 + +__INLINE uint16_t ble_rxphadv_get(int elt_idx) +{ + return EM_BLE_RD(BLE_RXPHADV_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE); +} + +__INLINE void ble_rxphadv_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_RXPHADV_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE, value); +} + +// field definitions +#define BLE_RXADVLEN_MASK ((uint16_t)0x0000FF00) +#define BLE_RXADVLEN_LSB 8 +#define BLE_RXADVLEN_WIDTH ((uint16_t)0x00000008) +#define BLE_RXRXADD_BIT ((uint16_t)0x00000080) +#define BLE_RXRXADD_POS 7 +#define BLE_RXTXADD_BIT ((uint16_t)0x00000040) +#define BLE_RXTXADD_POS 6 +#define BLE_RXTYPE_MASK ((uint16_t)0x0000000F) +#define BLE_RXTYPE_LSB 0 +#define BLE_RXTYPE_WIDTH ((uint16_t)0x00000004) + +#define BLE_RXADVLEN_RST 0x0 +#define BLE_RXRXADD_RST 0x0 +#define BLE_RXTXADD_RST 0x0 +#define BLE_RXTYPE_RST 0x0 + +__INLINE void ble_rxphadv_pack(int elt_idx, uint8_t rxadvlen, uint8_t rxrxadd, uint8_t rxtxadd, uint8_t rxtype) +{ + ASSERT_ERR((((uint16_t)rxadvlen << 8) & ~((uint16_t)0x0000FF00)) == 0); + ASSERT_ERR((((uint16_t)rxrxadd << 7) & ~((uint16_t)0x00000080)) == 0); + ASSERT_ERR((((uint16_t)rxtxadd << 6) & ~((uint16_t)0x00000040)) == 0); + ASSERT_ERR((((uint16_t)rxtype << 0) & ~((uint16_t)0x0000000F)) == 0); + EM_BLE_WR(BLE_RXPHADV_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE, ((uint16_t)rxadvlen << 8) | ((uint16_t)rxrxadd << 7) | ((uint16_t)rxtxadd << 6) | ((uint16_t)rxtype << 0)); +} + +__INLINE void ble_rxphadv_unpack(int elt_idx, uint8_t* rxadvlen, uint8_t* rxrxadd, uint8_t* rxtxadd, uint8_t* rxtype) +{ + uint16_t localVal = EM_BLE_RD(BLE_RXPHADV_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE); + + *rxadvlen = (localVal & ((uint16_t)0x0000FF00)) >> 8; + *rxrxadd = (localVal & ((uint16_t)0x00000080)) >> 7; + *rxtxadd = (localVal & ((uint16_t)0x00000040)) >> 6; + *rxtype = (localVal & ((uint16_t)0x0000000F)) >> 0; +} + +__INLINE uint8_t ble_rxadvlen_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_RXPHADV_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x0000FF00)) >> 8); +} + +__INLINE void ble_rxadvlen_setf(int elt_idx, uint8_t rxadvlen) +{ + ASSERT_ERR((((uint16_t)rxadvlen << 8) & ~((uint16_t)0x0000FF00)) == 0); + EM_BLE_WR(BLE_RXPHADV_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE, (EM_BLE_RD(BLE_RXPHADV_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE) & ~((uint16_t)0x0000FF00)) | ((uint16_t)rxadvlen << 8)); +} + +__INLINE uint8_t ble_rxrxadd_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_RXPHADV_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000080)) >> 7); +} + +__INLINE void ble_rxrxadd_setf(int elt_idx, uint8_t rxrxadd) +{ + ASSERT_ERR((((uint16_t)rxrxadd << 7) & ~((uint16_t)0x00000080)) == 0); + EM_BLE_WR(BLE_RXPHADV_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE, (EM_BLE_RD(BLE_RXPHADV_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE) & ~((uint16_t)0x00000080)) | ((uint16_t)rxrxadd << 7)); +} + +__INLINE uint8_t ble_rxtxadd_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_RXPHADV_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000040)) >> 6); +} + +__INLINE void ble_rxtxadd_setf(int elt_idx, uint8_t rxtxadd) +{ + ASSERT_ERR((((uint16_t)rxtxadd << 6) & ~((uint16_t)0x00000040)) == 0); + EM_BLE_WR(BLE_RXPHADV_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE, (EM_BLE_RD(BLE_RXPHADV_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE) & ~((uint16_t)0x00000040)) | ((uint16_t)rxtxadd << 6)); +} + +__INLINE uint8_t ble_rxtype_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_RXPHADV_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x0000000F)) >> 0); +} + +__INLINE void ble_rxtype_setf(int elt_idx, uint8_t rxtype) +{ + ASSERT_ERR((((uint16_t)rxtype << 0) & ~((uint16_t)0x0000000F)) == 0); + EM_BLE_WR(BLE_RXPHADV_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE, (EM_BLE_RD(BLE_RXPHADV_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE) & ~((uint16_t)0x0000000F)) | ((uint16_t)rxtype << 0)); +} + +/** + * @brief RXCHASS register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     15               IS_ISO   0
+ *  13:08          USED_CH_IDX   0x0
+ *  07:00                 RSSI   0x0
+ * 
+ */ +#define BLE_RXCHASS_ADDR (0x00814006 + EM_BLE_RX_DESC_OFFSET) +#define BLE_RXCHASS_INDEX 0x00000003 +#define BLE_RXCHASS_RESET 0x00000000 + +__INLINE uint16_t ble_rxchass_get(int elt_idx) +{ + return EM_BLE_RD(BLE_RXCHASS_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE); +} + +__INLINE void ble_rxchass_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_RXCHASS_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE, value); +} + +// field definitions +#define BLE_IS_ISO_BIT ((uint16_t)0x00008000) +#define BLE_IS_ISO_POS 15 +#define BLE_USED_CH_IDX_MASK ((uint16_t)0x00003F00) +#define BLE_USED_CH_IDX_LSB 8 +#define BLE_USED_CH_IDX_WIDTH ((uint16_t)0x00000006) +#define BLE_RSSI_MASK ((uint16_t)0x000000FF) +#define BLE_RSSI_LSB 0 +#define BLE_RSSI_WIDTH ((uint16_t)0x00000008) + +#define BLE_IS_ISO_RST 0x0 +#define BLE_USED_CH_IDX_RST 0x0 +#define BLE_RSSI_RST 0x0 + +__INLINE void ble_rxchass_pack(int elt_idx, uint8_t isiso, uint8_t usedchidx, uint8_t rssi) +{ + ASSERT_ERR((((uint16_t)isiso << 15) & ~((uint16_t)0x00008000)) == 0); + ASSERT_ERR((((uint16_t)usedchidx << 8) & ~((uint16_t)0x00003F00)) == 0); + ASSERT_ERR((((uint16_t)rssi << 0) & ~((uint16_t)0x000000FF)) == 0); + EM_BLE_WR(BLE_RXCHASS_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE, ((uint16_t)isiso << 15) | ((uint16_t)usedchidx << 8) | ((uint16_t)rssi << 0)); +} + +__INLINE void ble_rxchass_unpack(int elt_idx, uint8_t* isiso, uint8_t* usedchidx, uint8_t* rssi) +{ + uint16_t localVal = EM_BLE_RD(BLE_RXCHASS_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE); + + *isiso = (localVal & ((uint16_t)0x00008000)) >> 15; + *usedchidx = (localVal & ((uint16_t)0x00003F00)) >> 8; + *rssi = (localVal & ((uint16_t)0x000000FF)) >> 0; +} + +__INLINE uint8_t ble_is_iso_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_RXCHASS_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00008000)) >> 15); +} + +__INLINE void ble_is_iso_setf(int elt_idx, uint8_t isiso) +{ + ASSERT_ERR((((uint16_t)isiso << 15) & ~((uint16_t)0x00008000)) == 0); + EM_BLE_WR(BLE_RXCHASS_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE, (EM_BLE_RD(BLE_RXCHASS_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE) & ~((uint16_t)0x00008000)) | ((uint16_t)isiso << 15)); +} + +__INLINE uint8_t ble_used_ch_idx_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_RXCHASS_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00003F00)) >> 8); +} + +__INLINE void ble_used_ch_idx_setf(int elt_idx, uint8_t usedchidx) +{ + ASSERT_ERR((((uint16_t)usedchidx << 8) & ~((uint16_t)0x00003F00)) == 0); + EM_BLE_WR(BLE_RXCHASS_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE, (EM_BLE_RD(BLE_RXCHASS_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE) & ~((uint16_t)0x00003F00)) | ((uint16_t)usedchidx << 8)); +} + +__INLINE uint8_t ble_rssi_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_RXCHASS_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x000000FF)) >> 0); +} + +__INLINE void ble_rssi_setf(int elt_idx, uint8_t rssi) +{ + ASSERT_ERR((((uint16_t)rssi << 0) & ~((uint16_t)0x000000FF)) == 0); + EM_BLE_WR(BLE_RXCHASS_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE, (EM_BLE_RD(BLE_RXCHASS_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE) & ~((uint16_t)0x000000FF)) | ((uint16_t)rssi << 0)); +} + +/** + * @brief RXDATAPTR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00            RXDATAPTR   0x0
+ * 
+ */ +#define BLE_RXDATAPTR_ADDR (0x00814008 + EM_BLE_RX_DESC_OFFSET) +#define BLE_RXDATAPTR_INDEX 0x00000004 +#define BLE_RXDATAPTR_RESET 0x00000000 + +__INLINE uint16_t ble_rxdataptr_get(int elt_idx) +{ + return EM_BLE_RD(BLE_RXDATAPTR_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE); +} + +__INLINE void ble_rxdataptr_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_RXDATAPTR_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE, value); +} + +// field definitions +#define BLE_RXDATAPTR_MASK ((uint16_t)0x0000FFFF) +#define BLE_RXDATAPTR_LSB 0 +#define BLE_RXDATAPTR_WIDTH ((uint16_t)0x00000010) + +#define BLE_RXDATAPTR_RST 0x0 + +__INLINE uint16_t ble_rxdataptr_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_RXDATAPTR_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE); + ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_rxdataptr_setf(int elt_idx, uint16_t rxdataptr) +{ + ASSERT_ERR((((uint16_t)rxdataptr << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(BLE_RXDATAPTR_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE, (uint16_t)rxdataptr << 0); +} + +/** + * @brief RXRALPTR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00             RXRALPTR   0x0
+ * 
+ */ +#define BLE_RXRALPTR_ADDR (0x0081400A + EM_BLE_RX_DESC_OFFSET) +#define BLE_RXRALPTR_INDEX 0x00000005 +#define BLE_RXRALPTR_RESET 0x00000000 + +__INLINE uint16_t ble_rxralptr_get(int elt_idx) +{ + return EM_BLE_RD(BLE_RXRALPTR_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE); +} + +__INLINE void ble_rxralptr_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_RXRALPTR_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE, value); +} + +// field definitions +#define BLE_RXRALPTR_MASK ((uint16_t)0x0000FFFF) +#define BLE_RXRALPTR_LSB 0 +#define BLE_RXRALPTR_WIDTH ((uint16_t)0x00000010) + +#define BLE_RXRALPTR_RST 0x0 + +__INLINE uint16_t ble_rxralptr_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_RXRALPTR_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE); + ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_rxralptr_setf(int elt_idx, uint16_t rxralptr) +{ + ASSERT_ERR((((uint16_t)rxralptr << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(BLE_RXRALPTR_ADDR + elt_idx * REG_BLE_EM_RX_DESC_SIZE, (uint16_t)rxralptr << 0); +} + + +#endif // _REG_BLE_EM_RX_DESC_H_ + diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/reg_ble_em_tx_audio_buffer.h b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/reg_ble_em_tx_audio_buffer.h new file mode 100755 index 0000000..8834885 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/reg_ble_em_tx_audio_buffer.h @@ -0,0 +1,66 @@ +#ifndef _REG_BLE_EM_TX_AUDIO_BUFFER_H_ +#define _REG_BLE_EM_TX_AUDIO_BUFFER_H_ + +#include +#include "_reg_ble_em_tx_audio_buffer.h" +#include "ble_compiler.h" +#include "architect.h" +#include "em_map.h" +#include "ble_reg_access.h" + +#define REG_BLE_EM_TX_AUDIO_BUFFER_COUNT 1 + +#define REG_BLE_EM_TX_AUDIO_BUFFER_DECODING_MASK 0x00000000 + +#define REG_BLE_EM_TX_AUDIO_BUFFER_ADDR_GET(idx) (EM_BLE_TX_AUDIO_BUFFER_OFFSET + (idx) * REG_BLE_EM_TX_AUDIO_BUFFER_SIZE) + +/** + * @brief TXAUDIOBUF register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00           TXAUDIOBUF   0x0
+ * 
+ */ +#define BLE_TXAUDIOBUF_ADDR (0x00814000 + EM_BLE_TX_AUDIO_BUFFER_OFFSET) +#define BLE_TXAUDIOBUF_INDEX 0x00000000 +#define BLE_TXAUDIOBUF_RESET 0x00000000 +#define BLE_TXAUDIOBUF_COUNT 32 + +__INLINE uint16_t ble_txaudiobuf_get(int elt_idx, int reg_idx) +{ + ASSERT_ERR(reg_idx <= 31); + return EM_BLE_RD(BLE_TXAUDIOBUF_ADDR + elt_idx * REG_BLE_EM_TX_AUDIO_BUFFER_SIZE + reg_idx * 2); +} + +__INLINE void ble_txaudiobuf_set(int elt_idx, int reg_idx, uint16_t value) +{ + ASSERT_ERR(reg_idx <= 31); + EM_BLE_WR(BLE_TXAUDIOBUF_ADDR + elt_idx * REG_BLE_EM_TX_AUDIO_BUFFER_SIZE + reg_idx * 2, value); +} + +// field definitions +#define BLE_TXAUDIOBUF_MASK ((uint16_t)0x0000FFFF) +#define BLE_TXAUDIOBUF_LSB 0 +#define BLE_TXAUDIOBUF_WIDTH ((uint16_t)0x00000010) + +#define BLE_TXAUDIOBUF_RST 0x0 + +__INLINE uint16_t ble_txaudiobuf_getf(int elt_idx, int reg_idx) +{ + ASSERT_ERR(reg_idx <= 31); + uint16_t localVal = EM_BLE_RD(BLE_TXAUDIOBUF_ADDR + elt_idx * REG_BLE_EM_TX_AUDIO_BUFFER_SIZE + reg_idx * 2); + ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_txaudiobuf_setf(int elt_idx, int reg_idx, uint16_t txaudiobuf) +{ + ASSERT_ERR(reg_idx <= 31); + ASSERT_ERR((((uint16_t)txaudiobuf << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(BLE_TXAUDIOBUF_ADDR + elt_idx * REG_BLE_EM_TX_AUDIO_BUFFER_SIZE + reg_idx * 2, (uint16_t)txaudiobuf << 0); +} + + +#endif // _REG_BLE_EM_TX_AUDIO_BUFFER_H_ + diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/reg_ble_em_tx_buffer_cntl.h b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/reg_ble_em_tx_buffer_cntl.h new file mode 100755 index 0000000..c6fc855 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/reg_ble_em_tx_buffer_cntl.h @@ -0,0 +1,66 @@ +#ifndef _REG_BLE_EM_TX_BUFFER_CNTL_H_ +#define _REG_BLE_EM_TX_BUFFER_CNTL_H_ + +#include +#include "_reg_ble_em_tx_buffer_cntl.h" +#include "ble_compiler.h" +#include "architect.h" +#include "em_map.h" +#include "ble_reg_access.h" + +#define REG_BLE_EM_TX_BUFFER_CNTL_COUNT 1 + +#define REG_BLE_EM_TX_BUFFER_CNTL_DECODING_MASK 0x00000000 + +#define REG_BLE_EM_TX_BUFFER_CNTL_ADDR_GET(idx) (EM_BLE_TX_BUFFER_CNTL_OFFSET + (idx) * REG_BLE_EM_TX_BUFFER_CNTL_SIZE) + +/** + * @brief TXBUFCNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00            TXBUFCNTL   0x0
+ * 
+ */ +#define BLE_TXBUFCNTL_ADDR (0x00814000 + EM_BLE_TX_BUFFER_CNTL_OFFSET) +#define BLE_TXBUFCNTL_INDEX 0x00000000 +#define BLE_TXBUFCNTL_RESET 0x00000000 +#define BLE_TXBUFCNTL_COUNT 19 + +__INLINE uint16_t ble_txbufcntl_get(int elt_idx, int reg_idx) +{ + ASSERT_ERR(reg_idx <= 18); + return EM_BLE_RD(BLE_TXBUFCNTL_ADDR + elt_idx * REG_BLE_EM_TX_BUFFER_CNTL_SIZE + reg_idx * 2); +} + +__INLINE void ble_txbufcntl_set(int elt_idx, int reg_idx, uint16_t value) +{ + ASSERT_ERR(reg_idx <= 18); + EM_BLE_WR(BLE_TXBUFCNTL_ADDR + elt_idx * REG_BLE_EM_TX_BUFFER_CNTL_SIZE + reg_idx * 2, value); +} + +// field definitions +#define BLE_TXBUFCNTL_MASK ((uint16_t)0x0000FFFF) +#define BLE_TXBUFCNTL_LSB 0 +#define BLE_TXBUFCNTL_WIDTH ((uint16_t)0x00000010) + +#define BLE_TXBUFCNTL_RST 0x0 + +__INLINE uint16_t ble_txbufcntl_getf(int elt_idx, int reg_idx) +{ + ASSERT_ERR(reg_idx <= 18); + uint16_t localVal = EM_BLE_RD(BLE_TXBUFCNTL_ADDR + elt_idx * REG_BLE_EM_TX_BUFFER_CNTL_SIZE + reg_idx * 2); + ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_txbufcntl_setf(int elt_idx, int reg_idx, uint16_t txbufcntl) +{ + ASSERT_ERR(reg_idx <= 18); + ASSERT_ERR((((uint16_t)txbufcntl << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(BLE_TXBUFCNTL_ADDR + elt_idx * REG_BLE_EM_TX_BUFFER_CNTL_SIZE + reg_idx * 2, (uint16_t)txbufcntl << 0); +} + + +#endif // _REG_BLE_EM_TX_BUFFER_CNTL_H_ + diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/reg_ble_em_tx_buffer_data.h b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/reg_ble_em_tx_buffer_data.h new file mode 100755 index 0000000..f9ce20a --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/reg_ble_em_tx_buffer_data.h @@ -0,0 +1,66 @@ +#ifndef _REG_BLE_EM_TX_BUFFER_DATA_H_ +#define _REG_BLE_EM_TX_BUFFER_DATA_H_ + +#include +#include "_reg_ble_em_tx_buffer_data.h" +#include "ble_compiler.h" +#include "architect.h" +#include "em_map.h" +#include "ble_reg_access.h" + +#define REG_BLE_EM_TX_BUFFER_DATA_COUNT 1 + +#define REG_BLE_EM_TX_BUFFER_DATA_DECODING_MASK 0x00000000 + +#define REG_BLE_EM_TX_BUFFER_DATA_ADDR_GET(idx) (EM_BLE_TX_BUFFER_DATA_OFFSET + (idx) * REG_BLE_EM_TX_BUFFER_DATA_SIZE) + +/** + * @brief TXBUF register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00                TXBUF   0x0
+ * 
+ */ +#define BLE_TXBUF_ADDR (0x00814000 + EM_BLE_TX_BUFFER_DATA_OFFSET) +#define BLE_TXBUF_INDEX 0x00000000 +#define BLE_TXBUF_RESET 0x00000000 +#define BLE_TXBUF_COUNT 130 + +__INLINE uint16_t ble_txbuf_get(int elt_idx, int reg_idx) +{ + ASSERT_ERR(reg_idx <= 129); + return EM_BLE_RD(BLE_TXBUF_ADDR + elt_idx * REG_BLE_EM_TX_BUFFER_DATA_SIZE + reg_idx * 2); +} + +__INLINE void ble_txbuf_set(int elt_idx, int reg_idx, uint16_t value) +{ + ASSERT_ERR(reg_idx <= 129); + EM_BLE_WR(BLE_TXBUF_ADDR + elt_idx * REG_BLE_EM_TX_BUFFER_DATA_SIZE + reg_idx * 2, value); +} + +// field definitions +#define BLE_TXBUF_MASK ((uint16_t)0x0000FFFF) +#define BLE_TXBUF_LSB 0 +#define BLE_TXBUF_WIDTH ((uint16_t)0x00000010) + +#define BLE_TXBUF_RST 0x0 + +__INLINE uint16_t ble_txbuf_getf(int elt_idx, int reg_idx) +{ + ASSERT_ERR(reg_idx <= 129); + uint16_t localVal = EM_BLE_RD(BLE_TXBUF_ADDR + elt_idx * REG_BLE_EM_TX_BUFFER_DATA_SIZE + reg_idx * 2); + ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_txbuf_setf(int elt_idx, int reg_idx, uint16_t txbuf) +{ + ASSERT_ERR(reg_idx <= 129); + ASSERT_ERR((((uint16_t)txbuf << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(BLE_TXBUF_ADDR + elt_idx * REG_BLE_EM_TX_BUFFER_DATA_SIZE + reg_idx * 2, (uint16_t)txbuf << 0); +} + + +#endif // _REG_BLE_EM_TX_BUFFER_DATA_H_ + diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/reg_ble_em_tx_desc.h b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/reg_ble_em_tx_desc.h new file mode 100755 index 0000000..0177dcb --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/reg_ble_em_tx_desc.h @@ -0,0 +1,460 @@ +#ifndef _REG_BLE_EM_TX_DESC_H_ +#define _REG_BLE_EM_TX_DESC_H_ + +#include +#include "_reg_ble_em_tx_desc.h" +#include "ble_compiler.h" +#include "architect.h" +#include "em_map.h" +#include "ble_reg_access.h" + +#define REG_BLE_EM_TX_DESC_COUNT 4 + +#define REG_BLE_EM_TX_DESC_DECODING_MASK 0x00000007 + +#define REG_BLE_EM_TX_DESC_ADDR_GET(idx) (EM_BLE_TX_DESC_OFFSET + (idx) * REG_BLE_EM_TX_DESC_SIZE) + +/** + * @brief TXCNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     15               TXDONE   0
+ *  14:00              NEXTPTR   0x0
+ * 
+ */ +#define BLE_TXCNTL_ADDR (0x00814000 + EM_BLE_TX_DESC_OFFSET) +#define BLE_TXCNTL_INDEX 0x00000000 +#define BLE_TXCNTL_RESET 0x00000000 + +__INLINE uint16_t ble_txcntl_get(int elt_idx) +{ + return EM_BLE_RD(BLE_TXCNTL_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE); +} + +__INLINE void ble_txcntl_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_TXCNTL_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE, value); +} + +// field definitions +#define BLE_TXDONE_BIT ((uint16_t)0x00008000) +#define BLE_TXDONE_POS 15 +#define BLE_NEXTPTR_MASK ((uint16_t)0x00007FFF) +#define BLE_NEXTPTR_LSB 0 +#define BLE_NEXTPTR_WIDTH ((uint16_t)0x0000000F) + +#define BLE_TXDONE_RST 0x0 +#define BLE_NEXTPTR_RST 0x0 + +__INLINE void ble_txcntl_pack(int elt_idx, uint8_t txdone, uint16_t nextptr) +{ + ASSERT_ERR((((uint16_t)txdone << 15) & ~((uint16_t)0x00008000)) == 0); + ASSERT_ERR((((uint16_t)nextptr << 0) & ~((uint16_t)0x00007FFF)) == 0); + EM_BLE_WR(BLE_TXCNTL_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE, ((uint16_t)txdone << 15) | ((uint16_t)nextptr << 0)); +} + +__INLINE void ble_txcntl_unpack(int elt_idx, uint8_t* txdone, uint16_t* nextptr) +{ + uint16_t localVal = EM_BLE_RD(BLE_TXCNTL_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE); + + *txdone = (localVal & ((uint16_t)0x00008000)) >> 15; + *nextptr = (localVal & ((uint16_t)0x00007FFF)) >> 0; +} + +__INLINE uint8_t ble_txdone_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_TXCNTL_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00008000)) >> 15); +} + +__INLINE void ble_txdone_setf(int elt_idx, uint8_t txdone) +{ + ASSERT_ERR((((uint16_t)txdone << 15) & ~((uint16_t)0x00008000)) == 0); + EM_BLE_WR(BLE_TXCNTL_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE, (EM_BLE_RD(BLE_TXCNTL_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE) & ~((uint16_t)0x00008000)) | ((uint16_t)txdone << 15)); +} + +__INLINE uint16_t ble_nextptr_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_TXCNTL_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00007FFF)) >> 0); +} + +__INLINE void ble_nextptr_setf(int elt_idx, uint16_t nextptr) +{ + ASSERT_ERR((((uint16_t)nextptr << 0) & ~((uint16_t)0x00007FFF)) == 0); + EM_BLE_WR(BLE_TXCNTL_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE, (EM_BLE_RD(BLE_TXCNTL_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE) & ~((uint16_t)0x00007FFF)) | ((uint16_t)nextptr << 0)); +} + +/** + * @brief TXPHCE register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:08                TXLEN   0x0
+ *     04                 TXMD   0
+ *     03                 TXSN   0
+ *     02               TXNESN   0
+ *  01:00               TXLLID   0x0
+ * 
+ */ +#define BLE_TXPHCE_ADDR (0x00814002 + EM_BLE_TX_DESC_OFFSET) +#define BLE_TXPHCE_INDEX 0x00000001 +#define BLE_TXPHCE_RESET 0x00000000 + +__INLINE uint16_t ble_txphce_get(int elt_idx) +{ + return EM_BLE_RD(BLE_TXPHCE_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE); +} + +__INLINE void ble_txphce_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_TXPHCE_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE, value); +} + +// field definitions +#define BLE_TXLEN_MASK ((uint16_t)0x0000FF00) +#define BLE_TXLEN_LSB 8 +#define BLE_TXLEN_WIDTH ((uint16_t)0x00000008) +#define BLE_TXMD_BIT ((uint16_t)0x00000010) +#define BLE_TXMD_POS 4 +#define BLE_TXSN_BIT ((uint16_t)0x00000008) +#define BLE_TXSN_POS 3 +#define BLE_TXNESN_BIT ((uint16_t)0x00000004) +#define BLE_TXNESN_POS 2 +#define BLE_TXLLID_MASK ((uint16_t)0x00000003) +#define BLE_TXLLID_LSB 0 +#define BLE_TXLLID_WIDTH ((uint16_t)0x00000002) + +#define BLE_TXLEN_RST 0x0 +#define BLE_TXMD_RST 0x0 +#define BLE_TXSN_RST 0x0 +#define BLE_TXNESN_RST 0x0 +#define BLE_TXLLID_RST 0x0 + +__INLINE void ble_txphce_pack(int elt_idx, uint8_t txlen, uint8_t txmd, uint8_t txsn, uint8_t txnesn, uint8_t txllid) +{ + ASSERT_ERR((((uint16_t)txlen << 8) & ~((uint16_t)0x0000FF00)) == 0); + ASSERT_ERR((((uint16_t)txmd << 4) & ~((uint16_t)0x00000010)) == 0); + ASSERT_ERR((((uint16_t)txsn << 3) & ~((uint16_t)0x00000008)) == 0); + ASSERT_ERR((((uint16_t)txnesn << 2) & ~((uint16_t)0x00000004)) == 0); + ASSERT_ERR((((uint16_t)txllid << 0) & ~((uint16_t)0x00000003)) == 0); + EM_BLE_WR(BLE_TXPHCE_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE, ((uint16_t)txlen << 8) | ((uint16_t)txmd << 4) | ((uint16_t)txsn << 3) | ((uint16_t)txnesn << 2) | ((uint16_t)txllid << 0)); +} + +__INLINE void ble_txphce_unpack(int elt_idx, uint8_t* txlen, uint8_t* txmd, uint8_t* txsn, uint8_t* txnesn, uint8_t* txllid) +{ + uint16_t localVal = EM_BLE_RD(BLE_TXPHCE_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE); + + *txlen = (localVal & ((uint16_t)0x0000FF00)) >> 8; + *txmd = (localVal & ((uint16_t)0x00000010)) >> 4; + *txsn = (localVal & ((uint16_t)0x00000008)) >> 3; + *txnesn = (localVal & ((uint16_t)0x00000004)) >> 2; + *txllid = (localVal & ((uint16_t)0x00000003)) >> 0; +} + +__INLINE uint8_t ble_txlen_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_TXPHCE_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE); + return ((localVal & ((uint16_t)0x0000FF00)) >> 8); +} + +__INLINE void ble_txlen_setf(int elt_idx, uint8_t txlen) +{ + ASSERT_ERR((((uint16_t)txlen << 8) & ~((uint16_t)0x0000FF00)) == 0); + EM_BLE_WR(BLE_TXPHCE_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE, (EM_BLE_RD(BLE_TXPHCE_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE) & ~((uint16_t)0x0000FF00)) | ((uint16_t)txlen << 8)); +} + +__INLINE uint8_t ble_txmd_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_TXPHCE_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000010)) >> 4); +} + +__INLINE void ble_txmd_setf(int elt_idx, uint8_t txmd) +{ + ASSERT_ERR((((uint16_t)txmd << 4) & ~((uint16_t)0x00000010)) == 0); + EM_BLE_WR(BLE_TXPHCE_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE, (EM_BLE_RD(BLE_TXPHCE_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE) & ~((uint16_t)0x00000010)) | ((uint16_t)txmd << 4)); +} + +__INLINE uint8_t ble_txsn_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_TXPHCE_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000008)) >> 3); +} + +__INLINE void ble_txsn_setf(int elt_idx, uint8_t txsn) +{ + ASSERT_ERR((((uint16_t)txsn << 3) & ~((uint16_t)0x00000008)) == 0); + EM_BLE_WR(BLE_TXPHCE_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE, (EM_BLE_RD(BLE_TXPHCE_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE) & ~((uint16_t)0x00000008)) | ((uint16_t)txsn << 3)); +} + +__INLINE uint8_t ble_txnesn_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_TXPHCE_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000004)) >> 2); +} + +__INLINE void ble_txnesn_setf(int elt_idx, uint8_t txnesn) +{ + ASSERT_ERR((((uint16_t)txnesn << 2) & ~((uint16_t)0x00000004)) == 0); + EM_BLE_WR(BLE_TXPHCE_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE, (EM_BLE_RD(BLE_TXPHCE_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE) & ~((uint16_t)0x00000004)) | ((uint16_t)txnesn << 2)); +} + +__INLINE uint8_t ble_txllid_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_TXPHCE_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000003)) >> 0); +} + +__INLINE void ble_txllid_setf(int elt_idx, uint8_t txllid) +{ + ASSERT_ERR((((uint16_t)txllid << 0) & ~((uint16_t)0x00000003)) == 0); + EM_BLE_WR(BLE_TXPHCE_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE, (EM_BLE_RD(BLE_TXPHCE_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE) & ~((uint16_t)0x00000003)) | ((uint16_t)txllid << 0)); +} + +/** + * @brief TXPHADV register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:08             TXADVLEN   0x0
+ *     07              TXRXADD   0
+ *     06              TXTXADD   0
+ *  03:00               TXTYPE   0x0
+ * 
+ */ +#define BLE_TXPHADV_ADDR (0x00814002 + EM_BLE_TX_DESC_OFFSET) +#define BLE_TXPHADV_INDEX 0x00000001 +#define BLE_TXPHADV_RESET 0x00000000 + +__INLINE uint16_t ble_txphadv_get(int elt_idx) +{ + return EM_BLE_RD(BLE_TXPHADV_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE); +} + +__INLINE void ble_txphadv_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_TXPHADV_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE, value); +} + +// field definitions +#define BLE_TXADVLEN_MASK ((uint16_t)0x0000FF00) +#define BLE_TXADVLEN_LSB 8 +#define BLE_TXADVLEN_WIDTH ((uint16_t)0x00000008) +#define BLE_TXRXADD_BIT ((uint16_t)0x00000080) +#define BLE_TXRXADD_POS 7 +#define BLE_TXTXADD_BIT ((uint16_t)0x00000040) +#define BLE_TXTXADD_POS 6 +#define BLE_TXTYPE_MASK ((uint16_t)0x0000000F) +#define BLE_TXTYPE_LSB 0 +#define BLE_TXTYPE_WIDTH ((uint16_t)0x00000004) + +#define BLE_TXADVLEN_RST 0x0 +#define BLE_TXRXADD_RST 0x0 +#define BLE_TXTXADD_RST 0x0 +#define BLE_TXTYPE_RST 0x0 + +__INLINE void ble_txphadv_pack(int elt_idx, uint8_t txadvlen, uint8_t txrxadd, uint8_t txtxadd, uint8_t txtype) +{ + ASSERT_ERR((((uint16_t)txadvlen << 8) & ~((uint16_t)0x0000FF00)) == 0); + ASSERT_ERR((((uint16_t)txrxadd << 7) & ~((uint16_t)0x00000080)) == 0); + ASSERT_ERR((((uint16_t)txtxadd << 6) & ~((uint16_t)0x00000040)) == 0); + ASSERT_ERR((((uint16_t)txtype << 0) & ~((uint16_t)0x0000000F)) == 0); + EM_BLE_WR(BLE_TXPHADV_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE, ((uint16_t)txadvlen << 8) | ((uint16_t)txrxadd << 7) | ((uint16_t)txtxadd << 6) | ((uint16_t)txtype << 0)); +} + +__INLINE void ble_txphadv_unpack(int elt_idx, uint8_t* txadvlen, uint8_t* txrxadd, uint8_t* txtxadd, uint8_t* txtype) +{ + uint16_t localVal = EM_BLE_RD(BLE_TXPHADV_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE); + + *txadvlen = (localVal & ((uint16_t)0x0000FF00)) >> 8; + *txrxadd = (localVal & ((uint16_t)0x00000080)) >> 7; + *txtxadd = (localVal & ((uint16_t)0x00000040)) >> 6; + *txtype = (localVal & ((uint16_t)0x0000000F)) >> 0; +} + +__INLINE uint8_t ble_txadvlen_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_TXPHADV_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE); + return ((localVal & ((uint16_t)0x0000FF00)) >> 8); +} + +__INLINE void ble_txadvlen_setf(int elt_idx, uint8_t txadvlen) +{ + ASSERT_ERR((((uint16_t)txadvlen << 8) & ~((uint16_t)0x0000FF00)) == 0); + EM_BLE_WR(BLE_TXPHADV_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE, (EM_BLE_RD(BLE_TXPHADV_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE) & ~((uint16_t)0x0000FF00)) | ((uint16_t)txadvlen << 8)); +} + +__INLINE uint8_t ble_txrxadd_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_TXPHADV_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000080)) >> 7); +} + +__INLINE void ble_txrxadd_setf(int elt_idx, uint8_t txrxadd) +{ + ASSERT_ERR((((uint16_t)txrxadd << 7) & ~((uint16_t)0x00000080)) == 0); + EM_BLE_WR(BLE_TXPHADV_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE, (EM_BLE_RD(BLE_TXPHADV_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE) & ~((uint16_t)0x00000080)) | ((uint16_t)txrxadd << 7)); +} + +__INLINE uint8_t ble_txtxadd_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_TXPHADV_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000040)) >> 6); +} + +__INLINE void ble_txtxadd_setf(int elt_idx, uint8_t txtxadd) +{ + ASSERT_ERR((((uint16_t)txtxadd << 6) & ~((uint16_t)0x00000040)) == 0); + EM_BLE_WR(BLE_TXPHADV_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE, (EM_BLE_RD(BLE_TXPHADV_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE) & ~((uint16_t)0x00000040)) | ((uint16_t)txtxadd << 6)); +} + +__INLINE uint8_t ble_txtype_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_TXPHADV_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE); + return ((localVal & ((uint16_t)0x0000000F)) >> 0); +} + +__INLINE void ble_txtype_setf(int elt_idx, uint8_t txtype) +{ + ASSERT_ERR((((uint16_t)txtype << 0) & ~((uint16_t)0x0000000F)) == 0); + EM_BLE_WR(BLE_TXPHADV_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE, (EM_BLE_RD(BLE_TXPHADV_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE) & ~((uint16_t)0x0000000F)) | ((uint16_t)txtype << 0)); +} + +/** + * @brief TXDATAPTR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00            TXDATAPTR   0x0
+ * 
+ */ +#define BLE_TXDATAPTR_ADDR (0x00814004 + EM_BLE_TX_DESC_OFFSET) +#define BLE_TXDATAPTR_INDEX 0x00000002 +#define BLE_TXDATAPTR_RESET 0x00000000 + +__INLINE uint16_t ble_txdataptr_get(int elt_idx) +{ + return EM_BLE_RD(BLE_TXDATAPTR_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE); +} + +__INLINE void ble_txdataptr_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_TXDATAPTR_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE, value); +} + +// field definitions +#define BLE_TXDATAPTR_MASK ((uint16_t)0x0000FFFF) +#define BLE_TXDATAPTR_LSB 0 +#define BLE_TXDATAPTR_WIDTH ((uint16_t)0x00000010) + +#define BLE_TXDATAPTR_RST 0x0 + +__INLINE uint16_t ble_txdataptr_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_TXDATAPTR_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE); + ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_txdataptr_setf(int elt_idx, uint16_t txdataptr) +{ + ASSERT_ERR((((uint16_t)txdataptr << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(BLE_TXDATAPTR_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE, (uint16_t)txdataptr << 0); +} + +/** + * @brief TXDLE register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     15             FREEBUFF   0
+ *  11:08              FRAGCNT   0x0
+ *  07:00              BUFFIDX   0x0
+ * 
+ */ +#define BLE_TXDLE_ADDR (0x00814006 + EM_BLE_TX_DESC_OFFSET) +#define BLE_TXDLE_INDEX 0x00000003 +#define BLE_TXDLE_RESET 0x00000000 + +__INLINE uint16_t ble_txdle_get(int elt_idx) +{ + return EM_BLE_RD(BLE_TXDLE_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE); +} + +__INLINE void ble_txdle_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(BLE_TXDLE_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE, value); +} + +// field definitions +#define BLE_FREEBUFF_BIT ((uint16_t)0x00008000) +#define BLE_FREEBUFF_POS 15 +#define BLE_FRAGCNT_MASK ((uint16_t)0x00000F00) +#define BLE_FRAGCNT_LSB 8 +#define BLE_FRAGCNT_WIDTH ((uint16_t)0x00000004) +#define BLE_BUFFIDX_MASK ((uint16_t)0x000000FF) +#define BLE_BUFFIDX_LSB 0 +#define BLE_BUFFIDX_WIDTH ((uint16_t)0x00000008) + +#define BLE_FREEBUFF_RST 0x0 +#define BLE_FRAGCNT_RST 0x0 +#define BLE_BUFFIDX_RST 0x0 + +__INLINE void ble_txdle_pack(int elt_idx, uint8_t freebuff, uint8_t fragcnt, uint8_t buffidx) +{ + ASSERT_ERR((((uint16_t)freebuff << 15) & ~((uint16_t)0x00008000)) == 0); + ASSERT_ERR((((uint16_t)fragcnt << 8) & ~((uint16_t)0x00000F00)) == 0); + ASSERT_ERR((((uint16_t)buffidx << 0) & ~((uint16_t)0x000000FF)) == 0); + EM_BLE_WR(BLE_TXDLE_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE, ((uint16_t)freebuff << 15) | ((uint16_t)fragcnt << 8) | ((uint16_t)buffidx << 0)); +} + +__INLINE void ble_txdle_unpack(int elt_idx, uint8_t* freebuff, uint8_t* fragcnt, uint8_t* buffidx) +{ + uint16_t localVal = EM_BLE_RD(BLE_TXDLE_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE); + + *freebuff = (localVal & ((uint16_t)0x00008000)) >> 15; + *fragcnt = (localVal & ((uint16_t)0x00000F00)) >> 8; + *buffidx = (localVal & ((uint16_t)0x000000FF)) >> 0; +} + +__INLINE uint8_t ble_freebuff_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_TXDLE_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00008000)) >> 15); +} + +__INLINE void ble_freebuff_setf(int elt_idx, uint8_t freebuff) +{ + ASSERT_ERR((((uint16_t)freebuff << 15) & ~((uint16_t)0x00008000)) == 0); + EM_BLE_WR(BLE_TXDLE_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE, (EM_BLE_RD(BLE_TXDLE_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE) & ~((uint16_t)0x00008000)) | ((uint16_t)freebuff << 15)); +} + +__INLINE uint8_t ble_fragcnt_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_TXDLE_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000F00)) >> 8); +} + +__INLINE void ble_fragcnt_setf(int elt_idx, uint8_t fragcnt) +{ + ASSERT_ERR((((uint16_t)fragcnt << 8) & ~((uint16_t)0x00000F00)) == 0); + EM_BLE_WR(BLE_TXDLE_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE, (EM_BLE_RD(BLE_TXDLE_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE) & ~((uint16_t)0x00000F00)) | ((uint16_t)fragcnt << 8)); +} + +__INLINE uint8_t ble_buffidx_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(BLE_TXDLE_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE); + return ((localVal & ((uint16_t)0x000000FF)) >> 0); +} + +__INLINE void ble_buffidx_setf(int elt_idx, uint8_t buffidx) +{ + ASSERT_ERR((((uint16_t)buffidx << 0) & ~((uint16_t)0x000000FF)) == 0); + EM_BLE_WR(BLE_TXDLE_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE, (EM_BLE_RD(BLE_TXDLE_ADDR + elt_idx * REG_BLE_EM_TX_DESC_SIZE) & ~((uint16_t)0x000000FF)) | ((uint16_t)buffidx << 0)); +} + + +#endif // _REG_BLE_EM_TX_DESC_H_ + diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/reg_ble_em_wpb.h b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/reg_ble_em_wpb.h new file mode 100755 index 0000000..4a3802b --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/reg_ble_em_wpb.h @@ -0,0 +1,66 @@ +#ifndef _REG_BLE_EM_WPB_H_ +#define _REG_BLE_EM_WPB_H_ + +#include +#include "_reg_ble_em_wpb.h" +#include "ble_compiler.h" +#include "architect.h" +#include "em_map.h" +#include "ble_reg_access.h" + +#define REG_BLE_EM_WPB_COUNT 1 + +#define REG_BLE_EM_WPB_DECODING_MASK 0x00000000 + +#define REG_BLE_EM_WPB_ADDR_GET(idx) (EM_BLE_WPB_OFFSET + (idx) * REG_BLE_EM_WPB_SIZE) + +/** + * @brief WLPUB register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00                WLPUB   0x0
+ * 
+ */ +#define BLE_WLPUB_ADDR (0x00814000 + EM_BLE_WPB_OFFSET) +#define BLE_WLPUB_INDEX 0x00000000 +#define BLE_WLPUB_RESET 0x00000000 +#define BLE_WLPUB_COUNT 3 + +__INLINE uint16_t ble_wlpub_get(int elt_idx, int reg_idx) +{ + ASSERT_ERR(reg_idx <= 2); + return EM_BLE_RD(BLE_WLPUB_ADDR + elt_idx * REG_BLE_EM_WPB_SIZE + reg_idx * 2); +} + +__INLINE void ble_wlpub_set(int elt_idx, int reg_idx, uint16_t value) +{ + ASSERT_ERR(reg_idx <= 2); + EM_BLE_WR(BLE_WLPUB_ADDR + elt_idx * REG_BLE_EM_WPB_SIZE + reg_idx * 2, value); +} + +// field definitions +#define BLE_WLPUB_MASK ((uint16_t)0x0000FFFF) +#define BLE_WLPUB_LSB 0 +#define BLE_WLPUB_WIDTH ((uint16_t)0x00000010) + +#define BLE_WLPUB_RST 0x0 + +__INLINE uint16_t ble_wlpub_getf(int elt_idx, int reg_idx) +{ + ASSERT_ERR(reg_idx <= 2); + uint16_t localVal = EM_BLE_RD(BLE_WLPUB_ADDR + elt_idx * REG_BLE_EM_WPB_SIZE + reg_idx * 2); + ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_wlpub_setf(int elt_idx, int reg_idx, uint16_t wlpub) +{ + ASSERT_ERR(reg_idx <= 2); + ASSERT_ERR((((uint16_t)wlpub << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(BLE_WLPUB_ADDR + elt_idx * REG_BLE_EM_WPB_SIZE + reg_idx * 2, (uint16_t)wlpub << 0); +} + + +#endif // _REG_BLE_EM_WPB_H_ + diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/reg_ble_em_wpv.h b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/reg_ble_em_wpv.h new file mode 100755 index 0000000..6b2d057 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/reg_ble_em_wpv.h @@ -0,0 +1,66 @@ +#ifndef _REG_BLE_EM_WPV_H_ +#define _REG_BLE_EM_WPV_H_ + +#include +#include "_reg_ble_em_wpv.h" +#include "ble_compiler.h" +#include "architect.h" +#include "em_map.h" +#include "ble_reg_access.h" + +#define REG_BLE_EM_WPV_COUNT 1 + +#define REG_BLE_EM_WPV_DECODING_MASK 0x00000000 + +#define REG_BLE_EM_WPV_ADDR_GET(idx) (EM_BLE_WPV_OFFSET + (idx) * REG_BLE_EM_WPV_SIZE) + +/** + * @brief WLPRV register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00                WLPRV   0x0
+ * 
+ */ +#define BLE_WLPRV_ADDR (0x00814000 + EM_BLE_WPV_OFFSET) +#define BLE_WLPRV_INDEX 0x00000000 +#define BLE_WLPRV_RESET 0x00000000 +#define BLE_WLPRV_COUNT 3 + +__INLINE uint16_t ble_wlprv_get(int elt_idx, int reg_idx) +{ + ASSERT_ERR(reg_idx <= 2); + return EM_BLE_RD(BLE_WLPRV_ADDR + elt_idx * REG_BLE_EM_WPV_SIZE + reg_idx * 2); +} + +__INLINE void ble_wlprv_set(int elt_idx, int reg_idx, uint16_t value) +{ + ASSERT_ERR(reg_idx <= 2); + EM_BLE_WR(BLE_WLPRV_ADDR + elt_idx * REG_BLE_EM_WPV_SIZE + reg_idx * 2, value); +} + +// field definitions +#define BLE_WLPRV_MASK ((uint16_t)0x0000FFFF) +#define BLE_WLPRV_LSB 0 +#define BLE_WLPRV_WIDTH ((uint16_t)0x00000010) + +#define BLE_WLPRV_RST 0x0 + +__INLINE uint16_t ble_wlprv_getf(int elt_idx, int reg_idx) +{ + ASSERT_ERR(reg_idx <= 2); + uint16_t localVal = EM_BLE_RD(BLE_WLPRV_ADDR + elt_idx * REG_BLE_EM_WPV_SIZE + reg_idx * 2); + ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_wlprv_setf(int elt_idx, int reg_idx, uint16_t wlprv) +{ + ASSERT_ERR(reg_idx <= 2); + ASSERT_ERR((((uint16_t)wlprv << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(BLE_WLPRV_ADDR + elt_idx * REG_BLE_EM_WPV_SIZE + reg_idx * 2, (uint16_t)wlprv << 0); +} + + +#endif // _REG_BLE_EM_WPV_H_ + diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/reg_blecore.h b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/reg_blecore.h new file mode 100755 index 0000000..a512f8f --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/reg_blecore.h @@ -0,0 +1,8271 @@ +#ifndef _REG_BLECORE_H_ +#define _REG_BLECORE_H_ + +#include +#include "_reg_blecore.h" +#include "ble_compiler.h" +#include "architect.h" +#include "ble_reg_access.h" + +#define REG_BLECORE_COUNT 107 + +#define REG_BLECORE_DECODING_MASK 0x000001FF + +/** + * @brief RWBLECNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31      MASTER_SOFT_RST   0
+ *     30    MASTER_TGSOFT_RST   0
+ *     29         REG_SOFT_RST   0
+ *     28            SWINT_REQ   0
+ *     26         RFTEST_ABORT   0
+ *     25         ADVERT_ABORT   0
+ *     24           SCAN_ABORT   0
+ *     22               MD_DSB   0
+ *     21               SN_DSB   0
+ *     20             NESN_DSB   0
+ *     19            CRYPT_DSB   0
+ *     18             WHIT_DSB   0
+ *     17              CRC_DSB   0
+ *     16        HOP_REMAP_DSB   0
+ *     09        ADVERTFILT_EN   0
+ *     08             RWBLE_EN   0
+ *  07:04           RXWINSZDEF   0x0
+ *  02:00              SYNCERR   0x0
+ * 
+ */ +#define BLE_RWBLECNTL_ADDR 0x00810000 +#define BLE_RWBLECNTL_OFFSET 0x00000000 +#define BLE_RWBLECNTL_INDEX 0x00000000 +#define BLE_RWBLECNTL_RESET 0x00000000 + +__INLINE uint32_t ble_rwblecntl_get(void) +{ + return REG_BLE_RD(BLE_RWBLECNTL_ADDR); +} + +__INLINE void ble_rwblecntl_set(uint32_t value) +{ + REG_BLE_WR(BLE_RWBLECNTL_ADDR, value); +} + +// field definitions +#define BLE_MASTER_SOFT_RST_BIT ((uint32_t)0x80000000) +#define BLE_MASTER_SOFT_RST_POS 31 +#define BLE_MASTER_TGSOFT_RST_BIT ((uint32_t)0x40000000) +#define BLE_MASTER_TGSOFT_RST_POS 30 +#define BLE_REG_SOFT_RST_BIT ((uint32_t)0x20000000) +#define BLE_REG_SOFT_RST_POS 29 +#define BLE_SWINT_REQ_BIT ((uint32_t)0x10000000) +#define BLE_SWINT_REQ_POS 28 +#define BLE_RFTEST_ABORT_BIT ((uint32_t)0x04000000) +#define BLE_RFTEST_ABORT_POS 26 +#define BLE_ADVERT_ABORT_BIT ((uint32_t)0x02000000) +#define BLE_ADVERT_ABORT_POS 25 +#define BLE_SCAN_ABORT_BIT ((uint32_t)0x01000000) +#define BLE_SCAN_ABORT_POS 24 +#define BLE_MD_DSB_BIT ((uint32_t)0x00400000) +#define BLE_MD_DSB_POS 22 +#define BLE_SN_DSB_BIT ((uint32_t)0x00200000) +#define BLE_SN_DSB_POS 21 +#define BLE_NESN_DSB_BIT ((uint32_t)0x00100000) +#define BLE_NESN_DSB_POS 20 +#define BLE_CRYPT_DSB_BIT ((uint32_t)0x00080000) +#define BLE_CRYPT_DSB_POS 19 +#define BLE_WHIT_DSB_BIT ((uint32_t)0x00040000) +#define BLE_WHIT_DSB_POS 18 +#define BLE_CRC_DSB_BIT ((uint32_t)0x00020000) +#define BLE_CRC_DSB_POS 17 +#define BLE_HOP_REMAP_DSB_BIT ((uint32_t)0x00010000) +#define BLE_HOP_REMAP_DSB_POS 16 +#define BLE_ADVERTFILT_EN_BIT ((uint32_t)0x00000200) +#define BLE_ADVERTFILT_EN_POS 9 +#define BLE_RWBLE_EN_BIT ((uint32_t)0x00000100) +#define BLE_RWBLE_EN_POS 8 +#define BLE_RXWINSZDEF_MASK ((uint32_t)0x000000F0) +#define BLE_RXWINSZDEF_LSB 4 +#define BLE_RXWINSZDEF_WIDTH ((uint32_t)0x00000004) +#define BLE_SYNCERR_MASK ((uint32_t)0x00000007) +#define BLE_SYNCERR_LSB 0 +#define BLE_SYNCERR_WIDTH ((uint32_t)0x00000003) + +#define BLE_MASTER_SOFT_RST_RST 0x0 +#define BLE_MASTER_TGSOFT_RST_RST 0x0 +#define BLE_REG_SOFT_RST_RST 0x0 +#define BLE_SWINT_REQ_RST 0x0 +#define BLE_RFTEST_ABORT_RST 0x0 +#define BLE_ADVERT_ABORT_RST 0x0 +#define BLE_SCAN_ABORT_RST 0x0 +#define BLE_MD_DSB_RST 0x0 +#define BLE_SN_DSB_RST 0x0 +#define BLE_NESN_DSB_RST 0x0 +#define BLE_CRYPT_DSB_RST 0x0 +#define BLE_WHIT_DSB_RST 0x0 +#define BLE_CRC_DSB_RST 0x0 +#define BLE_HOP_REMAP_DSB_RST 0x0 +#define BLE_ADVERTFILT_EN_RST 0x0 +#define BLE_RWBLE_EN_RST 0x0 +#define BLE_RXWINSZDEF_RST 0x0 +#define BLE_SYNCERR_RST 0x0 + +__INLINE void ble_rwblecntl_pack(uint8_t mastersoftrst, uint8_t mastertgsoftrst, uint8_t regsoftrst, uint8_t swintreq, uint8_t rftestabort, uint8_t advertabort, uint8_t scanabort, uint8_t mddsb, uint8_t sndsb, uint8_t nesndsb, uint8_t cryptdsb, uint8_t whitdsb, uint8_t crcdsb, uint8_t hopremapdsb, uint8_t advertfilten, uint8_t rwbleen, uint8_t rxwinszdef, uint8_t syncerr) +{ + ASSERT_ERR((((uint32_t)mastersoftrst << 31) & ~((uint32_t)0x80000000)) == 0); + ASSERT_ERR((((uint32_t)mastertgsoftrst << 30) & ~((uint32_t)0x40000000)) == 0); + ASSERT_ERR((((uint32_t)regsoftrst << 29) & ~((uint32_t)0x20000000)) == 0); + ASSERT_ERR((((uint32_t)swintreq << 28) & ~((uint32_t)0x10000000)) == 0); + ASSERT_ERR((((uint32_t)rftestabort << 26) & ~((uint32_t)0x04000000)) == 0); + ASSERT_ERR((((uint32_t)advertabort << 25) & ~((uint32_t)0x02000000)) == 0); + ASSERT_ERR((((uint32_t)scanabort << 24) & ~((uint32_t)0x01000000)) == 0); + ASSERT_ERR((((uint32_t)mddsb << 22) & ~((uint32_t)0x00400000)) == 0); + ASSERT_ERR((((uint32_t)sndsb << 21) & ~((uint32_t)0x00200000)) == 0); + ASSERT_ERR((((uint32_t)nesndsb << 20) & ~((uint32_t)0x00100000)) == 0); + ASSERT_ERR((((uint32_t)cryptdsb << 19) & ~((uint32_t)0x00080000)) == 0); + ASSERT_ERR((((uint32_t)whitdsb << 18) & ~((uint32_t)0x00040000)) == 0); + ASSERT_ERR((((uint32_t)crcdsb << 17) & ~((uint32_t)0x00020000)) == 0); + ASSERT_ERR((((uint32_t)hopremapdsb << 16) & ~((uint32_t)0x00010000)) == 0); + ASSERT_ERR((((uint32_t)advertfilten << 9) & ~((uint32_t)0x00000200)) == 0); + ASSERT_ERR((((uint32_t)rwbleen << 8) & ~((uint32_t)0x00000100)) == 0); + ASSERT_ERR((((uint32_t)rxwinszdef << 4) & ~((uint32_t)0x000000F0)) == 0); + ASSERT_ERR((((uint32_t)syncerr << 0) & ~((uint32_t)0x00000007)) == 0); + REG_BLE_WR(BLE_RWBLECNTL_ADDR, ((uint32_t)mastersoftrst << 31) | ((uint32_t)mastertgsoftrst << 30) | ((uint32_t)regsoftrst << 29) | ((uint32_t)swintreq << 28) | ((uint32_t)rftestabort << 26) | ((uint32_t)advertabort << 25) | ((uint32_t)scanabort << 24) | ((uint32_t)mddsb << 22) | ((uint32_t)sndsb << 21) | ((uint32_t)nesndsb << 20) | ((uint32_t)cryptdsb << 19) | ((uint32_t)whitdsb << 18) | ((uint32_t)crcdsb << 17) | ((uint32_t)hopremapdsb << 16) | ((uint32_t)advertfilten << 9) | ((uint32_t)rwbleen << 8) | ((uint32_t)rxwinszdef << 4) | ((uint32_t)syncerr << 0)); +} + +__INLINE void ble_rwblecntl_unpack(uint8_t* mastersoftrst, uint8_t* mastertgsoftrst, uint8_t* regsoftrst, uint8_t* swintreq, uint8_t* rftestabort, uint8_t* advertabort, uint8_t* scanabort, uint8_t* mddsb, uint8_t* sndsb, uint8_t* nesndsb, uint8_t* cryptdsb, uint8_t* whitdsb, uint8_t* crcdsb, uint8_t* hopremapdsb, uint8_t* advertfilten, uint8_t* rwbleen, uint8_t* rxwinszdef, uint8_t* syncerr) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECNTL_ADDR); + + *mastersoftrst = (localVal & ((uint32_t)0x80000000)) >> 31; + *mastertgsoftrst = (localVal & ((uint32_t)0x40000000)) >> 30; + *regsoftrst = (localVal & ((uint32_t)0x20000000)) >> 29; + *swintreq = (localVal & ((uint32_t)0x10000000)) >> 28; + *rftestabort = (localVal & ((uint32_t)0x04000000)) >> 26; + *advertabort = (localVal & ((uint32_t)0x02000000)) >> 25; + *scanabort = (localVal & ((uint32_t)0x01000000)) >> 24; + *mddsb = (localVal & ((uint32_t)0x00400000)) >> 22; + *sndsb = (localVal & ((uint32_t)0x00200000)) >> 21; + *nesndsb = (localVal & ((uint32_t)0x00100000)) >> 20; + *cryptdsb = (localVal & ((uint32_t)0x00080000)) >> 19; + *whitdsb = (localVal & ((uint32_t)0x00040000)) >> 18; + *crcdsb = (localVal & ((uint32_t)0x00020000)) >> 17; + *hopremapdsb = (localVal & ((uint32_t)0x00010000)) >> 16; + *advertfilten = (localVal & ((uint32_t)0x00000200)) >> 9; + *rwbleen = (localVal & ((uint32_t)0x00000100)) >> 8; + *rxwinszdef = (localVal & ((uint32_t)0x000000F0)) >> 4; + *syncerr = (localVal & ((uint32_t)0x00000007)) >> 0; +} + +__INLINE uint8_t ble_master_soft_rst_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECNTL_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +__INLINE void ble_master_soft_rst_setf(uint8_t mastersoftrst) +{ + ASSERT_ERR((((uint32_t)mastersoftrst << 31) & ~((uint32_t)0x80000000)) == 0); + REG_BLE_WR(BLE_RWBLECNTL_ADDR, (REG_BLE_RD(BLE_RWBLECNTL_ADDR) & ~((uint32_t)0x80000000)) | ((uint32_t)mastersoftrst << 31)); +} + +__INLINE uint8_t ble_master_tgsoft_rst_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECNTL_ADDR); + return ((localVal & ((uint32_t)0x40000000)) >> 30); +} + +__INLINE void ble_master_tgsoft_rst_setf(uint8_t mastertgsoftrst) +{ + ASSERT_ERR((((uint32_t)mastertgsoftrst << 30) & ~((uint32_t)0x40000000)) == 0); + REG_BLE_WR(BLE_RWBLECNTL_ADDR, (REG_BLE_RD(BLE_RWBLECNTL_ADDR) & ~((uint32_t)0x40000000)) | ((uint32_t)mastertgsoftrst << 30)); +} + +__INLINE uint8_t ble_reg_soft_rst_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECNTL_ADDR); + return ((localVal & ((uint32_t)0x20000000)) >> 29); +} + +__INLINE void ble_reg_soft_rst_setf(uint8_t regsoftrst) +{ + ASSERT_ERR((((uint32_t)regsoftrst << 29) & ~((uint32_t)0x20000000)) == 0); + REG_BLE_WR(BLE_RWBLECNTL_ADDR, (REG_BLE_RD(BLE_RWBLECNTL_ADDR) & ~((uint32_t)0x20000000)) | ((uint32_t)regsoftrst << 29)); +} + +__INLINE uint8_t ble_swint_req_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECNTL_ADDR); + return ((localVal & ((uint32_t)0x10000000)) >> 28); +} + +__INLINE void ble_swint_req_setf(uint8_t swintreq) +{ + ASSERT_ERR((((uint32_t)swintreq << 28) & ~((uint32_t)0x10000000)) == 0); + REG_BLE_WR(BLE_RWBLECNTL_ADDR, (REG_BLE_RD(BLE_RWBLECNTL_ADDR) & ~((uint32_t)0x10000000)) | ((uint32_t)swintreq << 28)); +} + +__INLINE uint8_t ble_rftest_abort_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECNTL_ADDR); + return ((localVal & ((uint32_t)0x04000000)) >> 26); +} + +__INLINE void ble_rftest_abort_setf(uint8_t rftestabort) +{ + ASSERT_ERR((((uint32_t)rftestabort << 26) & ~((uint32_t)0x04000000)) == 0); + REG_BLE_WR(BLE_RWBLECNTL_ADDR, (REG_BLE_RD(BLE_RWBLECNTL_ADDR) & ~((uint32_t)0x04000000)) | ((uint32_t)rftestabort << 26)); +} + +__INLINE uint8_t ble_advert_abort_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECNTL_ADDR); + return ((localVal & ((uint32_t)0x02000000)) >> 25); +} + +__INLINE void ble_advert_abort_setf(uint8_t advertabort) +{ + ASSERT_ERR((((uint32_t)advertabort << 25) & ~((uint32_t)0x02000000)) == 0); + REG_BLE_WR(BLE_RWBLECNTL_ADDR, (REG_BLE_RD(BLE_RWBLECNTL_ADDR) & ~((uint32_t)0x02000000)) | ((uint32_t)advertabort << 25)); +} + +__INLINE uint8_t ble_scan_abort_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECNTL_ADDR); + return ((localVal & ((uint32_t)0x01000000)) >> 24); +} + +__INLINE void ble_scan_abort_setf(uint8_t scanabort) +{ + ASSERT_ERR((((uint32_t)scanabort << 24) & ~((uint32_t)0x01000000)) == 0); + REG_BLE_WR(BLE_RWBLECNTL_ADDR, (REG_BLE_RD(BLE_RWBLECNTL_ADDR) & ~((uint32_t)0x01000000)) | ((uint32_t)scanabort << 24)); +} + +__INLINE uint8_t ble_md_dsb_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECNTL_ADDR); + return ((localVal & ((uint32_t)0x00400000)) >> 22); +} + +__INLINE void ble_md_dsb_setf(uint8_t mddsb) +{ + ASSERT_ERR((((uint32_t)mddsb << 22) & ~((uint32_t)0x00400000)) == 0); + REG_BLE_WR(BLE_RWBLECNTL_ADDR, (REG_BLE_RD(BLE_RWBLECNTL_ADDR) & ~((uint32_t)0x00400000)) | ((uint32_t)mddsb << 22)); +} + +__INLINE uint8_t ble_sn_dsb_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECNTL_ADDR); + return ((localVal & ((uint32_t)0x00200000)) >> 21); +} + +__INLINE void ble_sn_dsb_setf(uint8_t sndsb) +{ + ASSERT_ERR((((uint32_t)sndsb << 21) & ~((uint32_t)0x00200000)) == 0); + REG_BLE_WR(BLE_RWBLECNTL_ADDR, (REG_BLE_RD(BLE_RWBLECNTL_ADDR) & ~((uint32_t)0x00200000)) | ((uint32_t)sndsb << 21)); +} + +__INLINE uint8_t ble_nesn_dsb_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECNTL_ADDR); + return ((localVal & ((uint32_t)0x00100000)) >> 20); +} + +__INLINE void ble_nesn_dsb_setf(uint8_t nesndsb) +{ + ASSERT_ERR((((uint32_t)nesndsb << 20) & ~((uint32_t)0x00100000)) == 0); + REG_BLE_WR(BLE_RWBLECNTL_ADDR, (REG_BLE_RD(BLE_RWBLECNTL_ADDR) & ~((uint32_t)0x00100000)) | ((uint32_t)nesndsb << 20)); +} + +__INLINE uint8_t ble_crypt_dsb_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECNTL_ADDR); + return ((localVal & ((uint32_t)0x00080000)) >> 19); +} + +__INLINE void ble_crypt_dsb_setf(uint8_t cryptdsb) +{ + ASSERT_ERR((((uint32_t)cryptdsb << 19) & ~((uint32_t)0x00080000)) == 0); + REG_BLE_WR(BLE_RWBLECNTL_ADDR, (REG_BLE_RD(BLE_RWBLECNTL_ADDR) & ~((uint32_t)0x00080000)) | ((uint32_t)cryptdsb << 19)); +} + +__INLINE uint8_t ble_whit_dsb_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECNTL_ADDR); + return ((localVal & ((uint32_t)0x00040000)) >> 18); +} + +__INLINE void ble_whit_dsb_setf(uint8_t whitdsb) +{ + ASSERT_ERR((((uint32_t)whitdsb << 18) & ~((uint32_t)0x00040000)) == 0); + REG_BLE_WR(BLE_RWBLECNTL_ADDR, (REG_BLE_RD(BLE_RWBLECNTL_ADDR) & ~((uint32_t)0x00040000)) | ((uint32_t)whitdsb << 18)); +} + +__INLINE uint8_t ble_crc_dsb_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECNTL_ADDR); + return ((localVal & ((uint32_t)0x00020000)) >> 17); +} + +__INLINE void ble_crc_dsb_setf(uint8_t crcdsb) +{ + ASSERT_ERR((((uint32_t)crcdsb << 17) & ~((uint32_t)0x00020000)) == 0); + REG_BLE_WR(BLE_RWBLECNTL_ADDR, (REG_BLE_RD(BLE_RWBLECNTL_ADDR) & ~((uint32_t)0x00020000)) | ((uint32_t)crcdsb << 17)); +} + +__INLINE uint8_t ble_hop_remap_dsb_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECNTL_ADDR); + return ((localVal & ((uint32_t)0x00010000)) >> 16); +} + +__INLINE void ble_hop_remap_dsb_setf(uint8_t hopremapdsb) +{ + ASSERT_ERR((((uint32_t)hopremapdsb << 16) & ~((uint32_t)0x00010000)) == 0); + REG_BLE_WR(BLE_RWBLECNTL_ADDR, (REG_BLE_RD(BLE_RWBLECNTL_ADDR) & ~((uint32_t)0x00010000)) | ((uint32_t)hopremapdsb << 16)); +} + +__INLINE uint8_t ble_advertfilt_en_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECNTL_ADDR); + return ((localVal & ((uint32_t)0x00000200)) >> 9); +} + +__INLINE void ble_advertfilt_en_setf(uint8_t advertfilten) +{ + ASSERT_ERR((((uint32_t)advertfilten << 9) & ~((uint32_t)0x00000200)) == 0); + REG_BLE_WR(BLE_RWBLECNTL_ADDR, (REG_BLE_RD(BLE_RWBLECNTL_ADDR) & ~((uint32_t)0x00000200)) | ((uint32_t)advertfilten << 9)); +} + +__INLINE uint8_t ble_rwble_en_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECNTL_ADDR); + return ((localVal & ((uint32_t)0x00000100)) >> 8); +} + +__INLINE void ble_rwble_en_setf(uint8_t rwbleen) +{ + ASSERT_ERR((((uint32_t)rwbleen << 8) & ~((uint32_t)0x00000100)) == 0); + REG_BLE_WR(BLE_RWBLECNTL_ADDR, (REG_BLE_RD(BLE_RWBLECNTL_ADDR) & ~((uint32_t)0x00000100)) | ((uint32_t)rwbleen << 8)); +} + +__INLINE uint8_t ble_rxwinszdef_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECNTL_ADDR); + return ((localVal & ((uint32_t)0x000000F0)) >> 4); +} + +__INLINE void ble_rxwinszdef_setf(uint8_t rxwinszdef) +{ + ASSERT_ERR((((uint32_t)rxwinszdef << 4) & ~((uint32_t)0x000000F0)) == 0); + REG_BLE_WR(BLE_RWBLECNTL_ADDR, (REG_BLE_RD(BLE_RWBLECNTL_ADDR) & ~((uint32_t)0x000000F0)) | ((uint32_t)rxwinszdef << 4)); +} + +__INLINE uint8_t ble_syncerr_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECNTL_ADDR); + return ((localVal & ((uint32_t)0x00000007)) >> 0); +} + +__INLINE void ble_syncerr_setf(uint8_t syncerr) +{ + ASSERT_ERR((((uint32_t)syncerr << 0) & ~((uint32_t)0x00000007)) == 0); + REG_BLE_WR(BLE_RWBLECNTL_ADDR, (REG_BLE_RD(BLE_RWBLECNTL_ADDR) & ~((uint32_t)0x00000007)) | ((uint32_t)syncerr << 0)); +} + +/** + * @brief VERSION register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:24                  TYP   0x8
+ *  23:16                  REL   0x0
+ *  15:08                  UPG   0xA
+ *  07:00                BUILD   0x1
+ * 
+ */ +#define BLE_VERSION_ADDR 0x00810004 +#define BLE_VERSION_OFFSET 0x00000004 +#define BLE_VERSION_INDEX 0x00000001 +#define BLE_VERSION_RESET 0x08000A01 + +__INLINE uint32_t ble_version_get(void) +{ + return REG_BLE_RD(BLE_VERSION_ADDR); +} + +// field definitions +#define BLE_TYP_MASK ((uint32_t)0xFF000000) +#define BLE_TYP_LSB 24 +#define BLE_TYP_WIDTH ((uint32_t)0x00000008) +#define BLE_REL_MASK ((uint32_t)0x00FF0000) +#define BLE_REL_LSB 16 +#define BLE_REL_WIDTH ((uint32_t)0x00000008) +#define BLE_UPG_MASK ((uint32_t)0x0000FF00) +#define BLE_UPG_LSB 8 +#define BLE_UPG_WIDTH ((uint32_t)0x00000008) +#define BLE_BUILD_MASK ((uint32_t)0x000000FF) +#define BLE_BUILD_LSB 0 +#define BLE_BUILD_WIDTH ((uint32_t)0x00000008) + +#define BLE_TYP_RST 0x8 +#define BLE_REL_RST 0x0 +#define BLE_UPG_RST 0xA +#define BLE_BUILD_RST 0x1 + +__INLINE void ble_version_unpack(uint8_t* typ, uint8_t* rel, uint8_t* upg, uint8_t* build) +{ + uint32_t localVal = REG_BLE_RD(BLE_VERSION_ADDR); + + *typ = (localVal & ((uint32_t)0xFF000000)) >> 24; + *rel = (localVal & ((uint32_t)0x00FF0000)) >> 16; + *upg = (localVal & ((uint32_t)0x0000FF00)) >> 8; + *build = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +__INLINE uint8_t ble_typ_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_VERSION_ADDR); + return ((localVal & ((uint32_t)0xFF000000)) >> 24); +} + +__INLINE uint8_t ble_rel_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_VERSION_ADDR); + return ((localVal & ((uint32_t)0x00FF0000)) >> 16); +} + +__INLINE uint8_t ble_upg_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_VERSION_ADDR); + return ((localVal & ((uint32_t)0x0000FF00)) >> 8); +} + +__INLINE uint8_t ble_build_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_VERSION_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +/** + * @brief RWBLECONF register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31               DMMODE   0
+ *  25:24            ISOPORTNB   0x3
+ *     23             DECIPHER   1
+ *     21             WLANCOEX   1
+ *  20:16                 RFIF   0x1
+ *     15               USEDBG   1
+ *     14             USECRYPT   0
+ *  13:08              CLK_SEL   0xD
+ *     07              INTMODE   1
+ *     06             BUS_TYPE   0
+ *     05           DATA_WIDTH   0
+ *  04:00           ADDR_WIDTH   0xD
+ * 
+ */ +#define BLE_RWBLECONF_ADDR 0x00810008 +#define BLE_RWBLECONF_OFFSET 0x00000008 +#define BLE_RWBLECONF_INDEX 0x00000002 +#define BLE_RWBLECONF_RESET 0x03A18D8D + +__INLINE uint32_t ble_rwbleconf_get(void) +{ + return REG_BLE_RD(BLE_RWBLECONF_ADDR); +} + +// field definitions +#define BLE_DMMODE_BIT ((uint32_t)0x80000000) +#define BLE_DMMODE_POS 31 +#define BLE_ISOPORTNB_MASK ((uint32_t)0x03000000) +#define BLE_ISOPORTNB_LSB 24 +#define BLE_ISOPORTNB_WIDTH ((uint32_t)0x00000002) +#define BLE_DECIPHER_BIT ((uint32_t)0x00800000) +#define BLE_DECIPHER_POS 23 +#define BLE_WLANCOEX_BIT ((uint32_t)0x00200000) +#define BLE_WLANCOEX_POS 21 +#define BLE_RFIF_MASK ((uint32_t)0x001F0000) +#define BLE_RFIF_LSB 16 +#define BLE_RFIF_WIDTH ((uint32_t)0x00000005) +#define BLE_USEDBG_BIT ((uint32_t)0x00008000) +#define BLE_USEDBG_POS 15 +#define BLE_USECRYPT_BIT ((uint32_t)0x00004000) +#define BLE_USECRYPT_POS 14 +#define BLE_CLK_SEL_MASK ((uint32_t)0x00003F00) +#define BLE_CLK_SEL_LSB 8 +#define BLE_CLK_SEL_WIDTH ((uint32_t)0x00000006) +#define BLE_INTMODE_BIT ((uint32_t)0x00000080) +#define BLE_INTMODE_POS 7 +#define BLE_BUS_TYPE_BIT ((uint32_t)0x00000040) +#define BLE_BUS_TYPE_POS 6 +#define BLE_DATA_WIDTH_BIT ((uint32_t)0x00000020) +#define BLE_DATA_WIDTH_POS 5 +#define BLE_ADDR_WIDTH_MASK ((uint32_t)0x0000001F) +#define BLE_ADDR_WIDTH_LSB 0 +#define BLE_ADDR_WIDTH_WIDTH ((uint32_t)0x00000005) + +#define BLE_DMMODE_RST 0x0 +#define BLE_ISOPORTNB_RST 0x3 +#define BLE_DECIPHER_RST 0x1 +#define BLE_WLANCOEX_RST 0x1 +#define BLE_RFIF_RST 0x1 +#define BLE_USEDBG_RST 0x1 +#define BLE_USECRYPT_RST 0x0 +#define BLE_CLK_SEL_RST 0xD +#define BLE_INTMODE_RST 0x1 +#define BLE_BUS_TYPE_RST 0x0 +#define BLE_DATA_WIDTH_RST 0x0 +#define BLE_ADDR_WIDTH_RST 0xD + +__INLINE void ble_rwbleconf_unpack(uint8_t* dmmode, uint8_t* isoportnb, uint8_t* decipher, uint8_t* wlancoex, uint8_t* rfif, uint8_t* usedbg, uint8_t* usecrypt, uint8_t* clksel, uint8_t* intmode, uint8_t* bustype, uint8_t* datawidth, uint8_t* addrwidth) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECONF_ADDR); + + *dmmode = (localVal & ((uint32_t)0x80000000)) >> 31; + *isoportnb = (localVal & ((uint32_t)0x03000000)) >> 24; + *decipher = (localVal & ((uint32_t)0x00800000)) >> 23; + *wlancoex = (localVal & ((uint32_t)0x00200000)) >> 21; + *rfif = (localVal & ((uint32_t)0x001F0000)) >> 16; + *usedbg = (localVal & ((uint32_t)0x00008000)) >> 15; + *usecrypt = (localVal & ((uint32_t)0x00004000)) >> 14; + *clksel = (localVal & ((uint32_t)0x00003F00)) >> 8; + *intmode = (localVal & ((uint32_t)0x00000080)) >> 7; + *bustype = (localVal & ((uint32_t)0x00000040)) >> 6; + *datawidth = (localVal & ((uint32_t)0x00000020)) >> 5; + *addrwidth = (localVal & ((uint32_t)0x0000001F)) >> 0; +} + +__INLINE uint8_t ble_dmmode_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECONF_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +__INLINE uint8_t ble_isoportnb_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECONF_ADDR); + return ((localVal & ((uint32_t)0x03000000)) >> 24); +} + +__INLINE uint8_t ble_decipher_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECONF_ADDR); + return ((localVal & ((uint32_t)0x00800000)) >> 23); +} + +__INLINE uint8_t ble_wlancoex_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECONF_ADDR); + return ((localVal & ((uint32_t)0x00200000)) >> 21); +} + +__INLINE uint8_t ble_rfif_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECONF_ADDR); + return ((localVal & ((uint32_t)0x001F0000)) >> 16); +} + +__INLINE uint8_t ble_usedbg_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECONF_ADDR); + return ((localVal & ((uint32_t)0x00008000)) >> 15); +} + +__INLINE uint8_t ble_usecrypt_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECONF_ADDR); + return ((localVal & ((uint32_t)0x00004000)) >> 14); +} + +__INLINE uint8_t ble_clk_sel_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECONF_ADDR); + return ((localVal & ((uint32_t)0x00003F00)) >> 8); +} + +__INLINE uint8_t ble_intmode_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECONF_ADDR); + return ((localVal & ((uint32_t)0x00000080)) >> 7); +} + +__INLINE uint8_t ble_bus_type_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECONF_ADDR); + return ((localVal & ((uint32_t)0x00000040)) >> 6); +} + +__INLINE uint8_t ble_data_width_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECONF_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +__INLINE uint8_t ble_addr_width_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECONF_ADDR); + return ((localVal & ((uint32_t)0x0000001F)) >> 0); +} + +/** + * @brief INTCNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     15          CSCNTDEVMSK   1
+ *     12         AUDIOINT2MSK   0
+ *     11         AUDIOINT1MSK   0
+ *     10         AUDIOINT0MSK   0
+ *     09             SWINTMSK   0
+ *     08      EVENTAPFAINTMSK   1
+ *     07      FINETGTIMINTMSK   0
+ *     06     GROSSTGTIMINTMSK   0
+ *     05          ERRORINTMSK   0
+ *     04          CRYPTINTMSK   1
+ *     03          EVENTINTMSK   1
+ *     02            SLPINTMSK   1
+ *     01             RXINTMSK   1
+ *     00          CSCNTINTMSK   1
+ * 
+ */ +#define BLE_INTCNTL_ADDR 0x0081000C +#define BLE_INTCNTL_OFFSET 0x0000000C +#define BLE_INTCNTL_INDEX 0x00000003 +#define BLE_INTCNTL_RESET 0x0000811F + +__INLINE uint32_t ble_intcntl_get(void) +{ + return REG_BLE_RD(BLE_INTCNTL_ADDR); +} + +__INLINE void ble_intcntl_set(uint32_t value) +{ + REG_BLE_WR(BLE_INTCNTL_ADDR, value); +} + +// field definitions +#define BLE_CSCNTDEVMSK_BIT ((uint32_t)0x00008000) +#define BLE_CSCNTDEVMSK_POS 15 +#define BLE_AUDIOINT2MSK_BIT ((uint32_t)0x00001000) +#define BLE_AUDIOINT2MSK_POS 12 +#define BLE_AUDIOINT1MSK_BIT ((uint32_t)0x00000800) +#define BLE_AUDIOINT1MSK_POS 11 +#define BLE_AUDIOINT0MSK_BIT ((uint32_t)0x00000400) +#define BLE_AUDIOINT0MSK_POS 10 +#define BLE_SWINTMSK_BIT ((uint32_t)0x00000200) +#define BLE_SWINTMSK_POS 9 +#define BLE_EVENTAPFAINTMSK_BIT ((uint32_t)0x00000100) +#define BLE_EVENTAPFAINTMSK_POS 8 +#define BLE_FINETGTIMINTMSK_BIT ((uint32_t)0x00000080) +#define BLE_FINETGTIMINTMSK_POS 7 +#define BLE_GROSSTGTIMINTMSK_BIT ((uint32_t)0x00000040) +#define BLE_GROSSTGTIMINTMSK_POS 6 +#define BLE_ERRORINTMSK_BIT ((uint32_t)0x00000020) +#define BLE_ERRORINTMSK_POS 5 +#define BLE_CRYPTINTMSK_BIT ((uint32_t)0x00000010) +#define BLE_CRYPTINTMSK_POS 4 +#define BLE_EVENTINTMSK_BIT ((uint32_t)0x00000008) +#define BLE_EVENTINTMSK_POS 3 +#define BLE_SLPINTMSK_BIT ((uint32_t)0x00000004) +#define BLE_SLPINTMSK_POS 2 +#define BLE_RXINTMSK_BIT ((uint32_t)0x00000002) +#define BLE_RXINTMSK_POS 1 +#define BLE_CSCNTINTMSK_BIT ((uint32_t)0x00000001) +#define BLE_CSCNTINTMSK_POS 0 + +#define BLE_CSCNTDEVMSK_RST 0x1 +#define BLE_AUDIOINT2MSK_RST 0x0 +#define BLE_AUDIOINT1MSK_RST 0x0 +#define BLE_AUDIOINT0MSK_RST 0x0 +#define BLE_SWINTMSK_RST 0x0 +#define BLE_EVENTAPFAINTMSK_RST 0x1 +#define BLE_FINETGTIMINTMSK_RST 0x0 +#define BLE_GROSSTGTIMINTMSK_RST 0x0 +#define BLE_ERRORINTMSK_RST 0x0 +#define BLE_CRYPTINTMSK_RST 0x1 +#define BLE_EVENTINTMSK_RST 0x1 +#define BLE_SLPINTMSK_RST 0x1 +#define BLE_RXINTMSK_RST 0x1 +#define BLE_CSCNTINTMSK_RST 0x1 + +__INLINE void ble_intcntl_pack(uint8_t cscntdevmsk, uint8_t audioint2msk, uint8_t audioint1msk, uint8_t audioint0msk, uint8_t swintmsk, uint8_t eventapfaintmsk, uint8_t finetgtimintmsk, uint8_t grosstgtimintmsk, uint8_t errorintmsk, uint8_t cryptintmsk, uint8_t eventintmsk, uint8_t slpintmsk, uint8_t rxintmsk, uint8_t cscntintmsk) +{ + ASSERT_ERR((((uint32_t)cscntdevmsk << 15) & ~((uint32_t)0x00008000)) == 0); + ASSERT_ERR((((uint32_t)audioint2msk << 12) & ~((uint32_t)0x00001000)) == 0); + ASSERT_ERR((((uint32_t)audioint1msk << 11) & ~((uint32_t)0x00000800)) == 0); + ASSERT_ERR((((uint32_t)audioint0msk << 10) & ~((uint32_t)0x00000400)) == 0); + ASSERT_ERR((((uint32_t)swintmsk << 9) & ~((uint32_t)0x00000200)) == 0); + ASSERT_ERR((((uint32_t)eventapfaintmsk << 8) & ~((uint32_t)0x00000100)) == 0); + ASSERT_ERR((((uint32_t)finetgtimintmsk << 7) & ~((uint32_t)0x00000080)) == 0); + ASSERT_ERR((((uint32_t)grosstgtimintmsk << 6) & ~((uint32_t)0x00000040)) == 0); + ASSERT_ERR((((uint32_t)errorintmsk << 5) & ~((uint32_t)0x00000020)) == 0); + ASSERT_ERR((((uint32_t)cryptintmsk << 4) & ~((uint32_t)0x00000010)) == 0); + ASSERT_ERR((((uint32_t)eventintmsk << 3) & ~((uint32_t)0x00000008)) == 0); + ASSERT_ERR((((uint32_t)slpintmsk << 2) & ~((uint32_t)0x00000004)) == 0); + ASSERT_ERR((((uint32_t)rxintmsk << 1) & ~((uint32_t)0x00000002)) == 0); + ASSERT_ERR((((uint32_t)cscntintmsk << 0) & ~((uint32_t)0x00000001)) == 0); + REG_BLE_WR(BLE_INTCNTL_ADDR, ((uint32_t)cscntdevmsk << 15) | ((uint32_t)audioint2msk << 12) | ((uint32_t)audioint1msk << 11) | ((uint32_t)audioint0msk << 10) | ((uint32_t)swintmsk << 9) | ((uint32_t)eventapfaintmsk << 8) | ((uint32_t)finetgtimintmsk << 7) | ((uint32_t)grosstgtimintmsk << 6) | ((uint32_t)errorintmsk << 5) | ((uint32_t)cryptintmsk << 4) | ((uint32_t)eventintmsk << 3) | ((uint32_t)slpintmsk << 2) | ((uint32_t)rxintmsk << 1) | ((uint32_t)cscntintmsk << 0)); +} + +__INLINE void ble_intcntl_unpack(uint8_t* cscntdevmsk, uint8_t* audioint2msk, uint8_t* audioint1msk, uint8_t* audioint0msk, uint8_t* swintmsk, uint8_t* eventapfaintmsk, uint8_t* finetgtimintmsk, uint8_t* grosstgtimintmsk, uint8_t* errorintmsk, uint8_t* cryptintmsk, uint8_t* eventintmsk, uint8_t* slpintmsk, uint8_t* rxintmsk, uint8_t* cscntintmsk) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTCNTL_ADDR); + + *cscntdevmsk = (localVal & ((uint32_t)0x00008000)) >> 15; + *audioint2msk = (localVal & ((uint32_t)0x00001000)) >> 12; + *audioint1msk = (localVal & ((uint32_t)0x00000800)) >> 11; + *audioint0msk = (localVal & ((uint32_t)0x00000400)) >> 10; + *swintmsk = (localVal & ((uint32_t)0x00000200)) >> 9; + *eventapfaintmsk = (localVal & ((uint32_t)0x00000100)) >> 8; + *finetgtimintmsk = (localVal & ((uint32_t)0x00000080)) >> 7; + *grosstgtimintmsk = (localVal & ((uint32_t)0x00000040)) >> 6; + *errorintmsk = (localVal & ((uint32_t)0x00000020)) >> 5; + *cryptintmsk = (localVal & ((uint32_t)0x00000010)) >> 4; + *eventintmsk = (localVal & ((uint32_t)0x00000008)) >> 3; + *slpintmsk = (localVal & ((uint32_t)0x00000004)) >> 2; + *rxintmsk = (localVal & ((uint32_t)0x00000002)) >> 1; + *cscntintmsk = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +__INLINE uint8_t ble_cscntdevmsk_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTCNTL_ADDR); + return ((localVal & ((uint32_t)0x00008000)) >> 15); +} + +__INLINE void ble_cscntdevmsk_setf(uint8_t cscntdevmsk) +{ + ASSERT_ERR((((uint32_t)cscntdevmsk << 15) & ~((uint32_t)0x00008000)) == 0); + REG_BLE_WR(BLE_INTCNTL_ADDR, (REG_BLE_RD(BLE_INTCNTL_ADDR) & ~((uint32_t)0x00008000)) | ((uint32_t)cscntdevmsk << 15)); +} + +__INLINE uint8_t ble_audioint2msk_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTCNTL_ADDR); + return ((localVal & ((uint32_t)0x00001000)) >> 12); +} + +__INLINE void ble_audioint2msk_setf(uint8_t audioint2msk) +{ + ASSERT_ERR((((uint32_t)audioint2msk << 12) & ~((uint32_t)0x00001000)) == 0); + REG_BLE_WR(BLE_INTCNTL_ADDR, (REG_BLE_RD(BLE_INTCNTL_ADDR) & ~((uint32_t)0x00001000)) | ((uint32_t)audioint2msk << 12)); +} + +__INLINE uint8_t ble_audioint1msk_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTCNTL_ADDR); + return ((localVal & ((uint32_t)0x00000800)) >> 11); +} + +__INLINE void ble_audioint1msk_setf(uint8_t audioint1msk) +{ + ASSERT_ERR((((uint32_t)audioint1msk << 11) & ~((uint32_t)0x00000800)) == 0); + REG_BLE_WR(BLE_INTCNTL_ADDR, (REG_BLE_RD(BLE_INTCNTL_ADDR) & ~((uint32_t)0x00000800)) | ((uint32_t)audioint1msk << 11)); +} + +__INLINE uint8_t ble_audioint0msk_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTCNTL_ADDR); + return ((localVal & ((uint32_t)0x00000400)) >> 10); +} + +__INLINE void ble_audioint0msk_setf(uint8_t audioint0msk) +{ + ASSERT_ERR((((uint32_t)audioint0msk << 10) & ~((uint32_t)0x00000400)) == 0); + REG_BLE_WR(BLE_INTCNTL_ADDR, (REG_BLE_RD(BLE_INTCNTL_ADDR) & ~((uint32_t)0x00000400)) | ((uint32_t)audioint0msk << 10)); +} + +__INLINE uint8_t ble_swintmsk_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTCNTL_ADDR); + return ((localVal & ((uint32_t)0x00000200)) >> 9); +} + +__INLINE void ble_swintmsk_setf(uint8_t swintmsk) +{ + ASSERT_ERR((((uint32_t)swintmsk << 9) & ~((uint32_t)0x00000200)) == 0); + REG_BLE_WR(BLE_INTCNTL_ADDR, (REG_BLE_RD(BLE_INTCNTL_ADDR) & ~((uint32_t)0x00000200)) | ((uint32_t)swintmsk << 9)); +} + +__INLINE uint8_t ble_eventapfaintmsk_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTCNTL_ADDR); + return ((localVal & ((uint32_t)0x00000100)) >> 8); +} + +__INLINE void ble_eventapfaintmsk_setf(uint8_t eventapfaintmsk) +{ + ASSERT_ERR((((uint32_t)eventapfaintmsk << 8) & ~((uint32_t)0x00000100)) == 0); + REG_BLE_WR(BLE_INTCNTL_ADDR, (REG_BLE_RD(BLE_INTCNTL_ADDR) & ~((uint32_t)0x00000100)) | ((uint32_t)eventapfaintmsk << 8)); +} + +__INLINE uint8_t ble_finetgtimintmsk_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTCNTL_ADDR); + return ((localVal & ((uint32_t)0x00000080)) >> 7); +} + +__INLINE void ble_finetgtimintmsk_setf(uint8_t finetgtimintmsk) +{ + ASSERT_ERR((((uint32_t)finetgtimintmsk << 7) & ~((uint32_t)0x00000080)) == 0); + REG_BLE_WR(BLE_INTCNTL_ADDR, (REG_BLE_RD(BLE_INTCNTL_ADDR) & ~((uint32_t)0x00000080)) | ((uint32_t)finetgtimintmsk << 7)); +} + +__INLINE uint8_t ble_grosstgtimintmsk_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTCNTL_ADDR); + return ((localVal & ((uint32_t)0x00000040)) >> 6); +} + +__INLINE void ble_grosstgtimintmsk_setf(uint8_t grosstgtimintmsk) +{ + ASSERT_ERR((((uint32_t)grosstgtimintmsk << 6) & ~((uint32_t)0x00000040)) == 0); + REG_BLE_WR(BLE_INTCNTL_ADDR, (REG_BLE_RD(BLE_INTCNTL_ADDR) & ~((uint32_t)0x00000040)) | ((uint32_t)grosstgtimintmsk << 6)); +} + +__INLINE uint8_t ble_errorintmsk_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTCNTL_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +__INLINE void ble_errorintmsk_setf(uint8_t errorintmsk) +{ + ASSERT_ERR((((uint32_t)errorintmsk << 5) & ~((uint32_t)0x00000020)) == 0); + REG_BLE_WR(BLE_INTCNTL_ADDR, (REG_BLE_RD(BLE_INTCNTL_ADDR) & ~((uint32_t)0x00000020)) | ((uint32_t)errorintmsk << 5)); +} + +__INLINE uint8_t ble_cryptintmsk_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTCNTL_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +__INLINE void ble_cryptintmsk_setf(uint8_t cryptintmsk) +{ + ASSERT_ERR((((uint32_t)cryptintmsk << 4) & ~((uint32_t)0x00000010)) == 0); + REG_BLE_WR(BLE_INTCNTL_ADDR, (REG_BLE_RD(BLE_INTCNTL_ADDR) & ~((uint32_t)0x00000010)) | ((uint32_t)cryptintmsk << 4)); +} + +__INLINE uint8_t ble_eventintmsk_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTCNTL_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +__INLINE void ble_eventintmsk_setf(uint8_t eventintmsk) +{ + ASSERT_ERR((((uint32_t)eventintmsk << 3) & ~((uint32_t)0x00000008)) == 0); + REG_BLE_WR(BLE_INTCNTL_ADDR, (REG_BLE_RD(BLE_INTCNTL_ADDR) & ~((uint32_t)0x00000008)) | ((uint32_t)eventintmsk << 3)); +} + +__INLINE uint8_t ble_slpintmsk_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTCNTL_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +__INLINE void ble_slpintmsk_setf(uint8_t slpintmsk) +{ + ASSERT_ERR((((uint32_t)slpintmsk << 2) & ~((uint32_t)0x00000004)) == 0); + REG_BLE_WR(BLE_INTCNTL_ADDR, (REG_BLE_RD(BLE_INTCNTL_ADDR) & ~((uint32_t)0x00000004)) | ((uint32_t)slpintmsk << 2)); +} + +__INLINE uint8_t ble_rxintmsk_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTCNTL_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +__INLINE void ble_rxintmsk_setf(uint8_t rxintmsk) +{ + ASSERT_ERR((((uint32_t)rxintmsk << 1) & ~((uint32_t)0x00000002)) == 0); + REG_BLE_WR(BLE_INTCNTL_ADDR, (REG_BLE_RD(BLE_INTCNTL_ADDR) & ~((uint32_t)0x00000002)) | ((uint32_t)rxintmsk << 1)); +} + +__INLINE uint8_t ble_cscntintmsk_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTCNTL_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +__INLINE void ble_cscntintmsk_setf(uint8_t cscntintmsk) +{ + ASSERT_ERR((((uint32_t)cscntintmsk << 0) & ~((uint32_t)0x00000001)) == 0); + REG_BLE_WR(BLE_INTCNTL_ADDR, (REG_BLE_RD(BLE_INTCNTL_ADDR) & ~((uint32_t)0x00000001)) | ((uint32_t)cscntintmsk << 0)); +} + +/** + * @brief INTSTAT register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     12        AUDIOINT2STAT   0
+ *     11        AUDIOINT1STAT   0
+ *     10        AUDIOINT0STAT   0
+ *     09            SWINTSTAT   0
+ *     08     EVENTAPFAINTSTAT   0
+ *     07     FINETGTIMINTSTAT   0
+ *     06    GROSSTGTIMINTSTAT   0
+ *     05         ERRORINTSTAT   0
+ *     04         CRYPTINTSTAT   0
+ *     03         EVENTINTSTAT   0
+ *     02           SLPINTSTAT   0
+ *     01            RXINTSTAT   0
+ *     00         CSCNTINTSTAT   0
+ * 
+ */ +#define BLE_INTSTAT_ADDR 0x00810010 +#define BLE_INTSTAT_OFFSET 0x00000010 +#define BLE_INTSTAT_INDEX 0x00000004 +#define BLE_INTSTAT_RESET 0x00000000 + +__INLINE uint32_t ble_intstat_get(void) +{ + return REG_BLE_RD(BLE_INTSTAT_ADDR); +} + +// field definitions +#define BLE_AUDIOINT2STAT_BIT ((uint32_t)0x00001000) +#define BLE_AUDIOINT2STAT_POS 12 +#define BLE_AUDIOINT1STAT_BIT ((uint32_t)0x00000800) +#define BLE_AUDIOINT1STAT_POS 11 +#define BLE_AUDIOINT0STAT_BIT ((uint32_t)0x00000400) +#define BLE_AUDIOINT0STAT_POS 10 +#define BLE_SWINTSTAT_BIT ((uint32_t)0x00000200) +#define BLE_SWINTSTAT_POS 9 +#define BLE_EVENTAPFAINTSTAT_BIT ((uint32_t)0x00000100) +#define BLE_EVENTAPFAINTSTAT_POS 8 +#define BLE_FINETGTIMINTSTAT_BIT ((uint32_t)0x00000080) +#define BLE_FINETGTIMINTSTAT_POS 7 +#define BLE_GROSSTGTIMINTSTAT_BIT ((uint32_t)0x00000040) +#define BLE_GROSSTGTIMINTSTAT_POS 6 +#define BLE_ERRORINTSTAT_BIT ((uint32_t)0x00000020) +#define BLE_ERRORINTSTAT_POS 5 +#define BLE_CRYPTINTSTAT_BIT ((uint32_t)0x00000010) +#define BLE_CRYPTINTSTAT_POS 4 +#define BLE_EVENTINTSTAT_BIT ((uint32_t)0x00000008) +#define BLE_EVENTINTSTAT_POS 3 +#define BLE_SLPINTSTAT_BIT ((uint32_t)0x00000004) +#define BLE_SLPINTSTAT_POS 2 +#define BLE_RXINTSTAT_BIT ((uint32_t)0x00000002) +#define BLE_RXINTSTAT_POS 1 +#define BLE_CSCNTINTSTAT_BIT ((uint32_t)0x00000001) +#define BLE_CSCNTINTSTAT_POS 0 + +#define BLE_AUDIOINT2STAT_RST 0x0 +#define BLE_AUDIOINT1STAT_RST 0x0 +#define BLE_AUDIOINT0STAT_RST 0x0 +#define BLE_SWINTSTAT_RST 0x0 +#define BLE_EVENTAPFAINTSTAT_RST 0x0 +#define BLE_FINETGTIMINTSTAT_RST 0x0 +#define BLE_GROSSTGTIMINTSTAT_RST 0x0 +#define BLE_ERRORINTSTAT_RST 0x0 +#define BLE_CRYPTINTSTAT_RST 0x0 +#define BLE_EVENTINTSTAT_RST 0x0 +#define BLE_SLPINTSTAT_RST 0x0 +#define BLE_RXINTSTAT_RST 0x0 +#define BLE_CSCNTINTSTAT_RST 0x0 + +__INLINE void ble_intstat_unpack(uint8_t* audioint2stat, uint8_t* audioint1stat, uint8_t* audioint0stat, uint8_t* swintstat, uint8_t* eventapfaintstat, uint8_t* finetgtimintstat, uint8_t* grosstgtimintstat, uint8_t* errorintstat, uint8_t* cryptintstat, uint8_t* eventintstat, uint8_t* slpintstat, uint8_t* rxintstat, uint8_t* cscntintstat) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTSTAT_ADDR); + + *audioint2stat = (localVal & ((uint32_t)0x00001000)) >> 12; + *audioint1stat = (localVal & ((uint32_t)0x00000800)) >> 11; + *audioint0stat = (localVal & ((uint32_t)0x00000400)) >> 10; + *swintstat = (localVal & ((uint32_t)0x00000200)) >> 9; + *eventapfaintstat = (localVal & ((uint32_t)0x00000100)) >> 8; + *finetgtimintstat = (localVal & ((uint32_t)0x00000080)) >> 7; + *grosstgtimintstat = (localVal & ((uint32_t)0x00000040)) >> 6; + *errorintstat = (localVal & ((uint32_t)0x00000020)) >> 5; + *cryptintstat = (localVal & ((uint32_t)0x00000010)) >> 4; + *eventintstat = (localVal & ((uint32_t)0x00000008)) >> 3; + *slpintstat = (localVal & ((uint32_t)0x00000004)) >> 2; + *rxintstat = (localVal & ((uint32_t)0x00000002)) >> 1; + *cscntintstat = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +__INLINE uint8_t ble_audioint2stat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTSTAT_ADDR); + return ((localVal & ((uint32_t)0x00001000)) >> 12); +} + +__INLINE uint8_t ble_audioint1stat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000800)) >> 11); +} + +__INLINE uint8_t ble_audioint0stat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000400)) >> 10); +} + +__INLINE uint8_t ble_swintstat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000200)) >> 9); +} + +__INLINE uint8_t ble_eventapfaintstat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000100)) >> 8); +} + +__INLINE uint8_t ble_finetgtimintstat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000080)) >> 7); +} + +__INLINE uint8_t ble_grosstgtimintstat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000040)) >> 6); +} + +__INLINE uint8_t ble_errorintstat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +__INLINE uint8_t ble_cryptintstat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +__INLINE uint8_t ble_eventintstat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +__INLINE uint8_t ble_slpintstat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +__INLINE uint8_t ble_rxintstat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +__INLINE uint8_t ble_cscntintstat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/** + * @brief INTRAWSTAT register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     12     AUDIOINT2RAWSTAT   0
+ *     11     AUDIOINT1RAWSTAT   0
+ *     10     AUDIOINT0RAWSTAT   0
+ *     09         SWINTRAWSTAT   0
+ *     08   EVENTAPFAINTRAWSTAT   0
+ *     07   FINETGTIMINTRAWSTAT   0
+ *     06   GROSSTGTIMINTRAWSTAT   0
+ *     05      ERRORINTRAWSTAT   0
+ *     04      CRYPTINTRAWSTAT   0
+ *     03      EVENTINTRAWSTAT   0
+ *     02        SLPINTRAWSTAT   0
+ *     01         RXINTRAWSTAT   0
+ *     00      CSCNTINTRAWSTAT   0
+ * 
+ */ +#define BLE_INTRAWSTAT_ADDR 0x00810014 +#define BLE_INTRAWSTAT_OFFSET 0x00000014 +#define BLE_INTRAWSTAT_INDEX 0x00000005 +#define BLE_INTRAWSTAT_RESET 0x00000000 + +__INLINE uint32_t ble_intrawstat_get(void) +{ + return REG_BLE_RD(BLE_INTRAWSTAT_ADDR); +} + +// field definitions +#define BLE_AUDIOINT2RAWSTAT_BIT ((uint32_t)0x00001000) +#define BLE_AUDIOINT2RAWSTAT_POS 12 +#define BLE_AUDIOINT1RAWSTAT_BIT ((uint32_t)0x00000800) +#define BLE_AUDIOINT1RAWSTAT_POS 11 +#define BLE_AUDIOINT0RAWSTAT_BIT ((uint32_t)0x00000400) +#define BLE_AUDIOINT0RAWSTAT_POS 10 +#define BLE_SWINTRAWSTAT_BIT ((uint32_t)0x00000200) +#define BLE_SWINTRAWSTAT_POS 9 +#define BLE_EVENTAPFAINTRAWSTAT_BIT ((uint32_t)0x00000100) +#define BLE_EVENTAPFAINTRAWSTAT_POS 8 +#define BLE_FINETGTIMINTRAWSTAT_BIT ((uint32_t)0x00000080) +#define BLE_FINETGTIMINTRAWSTAT_POS 7 +#define BLE_GROSSTGTIMINTRAWSTAT_BIT ((uint32_t)0x00000040) +#define BLE_GROSSTGTIMINTRAWSTAT_POS 6 +#define BLE_ERRORINTRAWSTAT_BIT ((uint32_t)0x00000020) +#define BLE_ERRORINTRAWSTAT_POS 5 +#define BLE_CRYPTINTRAWSTAT_BIT ((uint32_t)0x00000010) +#define BLE_CRYPTINTRAWSTAT_POS 4 +#define BLE_EVENTINTRAWSTAT_BIT ((uint32_t)0x00000008) +#define BLE_EVENTINTRAWSTAT_POS 3 +#define BLE_SLPINTRAWSTAT_BIT ((uint32_t)0x00000004) +#define BLE_SLPINTRAWSTAT_POS 2 +#define BLE_RXINTRAWSTAT_BIT ((uint32_t)0x00000002) +#define BLE_RXINTRAWSTAT_POS 1 +#define BLE_CSCNTINTRAWSTAT_BIT ((uint32_t)0x00000001) +#define BLE_CSCNTINTRAWSTAT_POS 0 + +#define BLE_AUDIOINT2RAWSTAT_RST 0x0 +#define BLE_AUDIOINT1RAWSTAT_RST 0x0 +#define BLE_AUDIOINT0RAWSTAT_RST 0x0 +#define BLE_SWINTRAWSTAT_RST 0x0 +#define BLE_EVENTAPFAINTRAWSTAT_RST 0x0 +#define BLE_FINETGTIMINTRAWSTAT_RST 0x0 +#define BLE_GROSSTGTIMINTRAWSTAT_RST 0x0 +#define BLE_ERRORINTRAWSTAT_RST 0x0 +#define BLE_CRYPTINTRAWSTAT_RST 0x0 +#define BLE_EVENTINTRAWSTAT_RST 0x0 +#define BLE_SLPINTRAWSTAT_RST 0x0 +#define BLE_RXINTRAWSTAT_RST 0x0 +#define BLE_CSCNTINTRAWSTAT_RST 0x0 + +__INLINE void ble_intrawstat_unpack(uint8_t* audioint2rawstat, uint8_t* audioint1rawstat, uint8_t* audioint0rawstat, uint8_t* swintrawstat, uint8_t* eventapfaintrawstat, uint8_t* finetgtimintrawstat, uint8_t* grosstgtimintrawstat, uint8_t* errorintrawstat, uint8_t* cryptintrawstat, uint8_t* eventintrawstat, uint8_t* slpintrawstat, uint8_t* rxintrawstat, uint8_t* cscntintrawstat) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTRAWSTAT_ADDR); + + *audioint2rawstat = (localVal & ((uint32_t)0x00001000)) >> 12; + *audioint1rawstat = (localVal & ((uint32_t)0x00000800)) >> 11; + *audioint0rawstat = (localVal & ((uint32_t)0x00000400)) >> 10; + *swintrawstat = (localVal & ((uint32_t)0x00000200)) >> 9; + *eventapfaintrawstat = (localVal & ((uint32_t)0x00000100)) >> 8; + *finetgtimintrawstat = (localVal & ((uint32_t)0x00000080)) >> 7; + *grosstgtimintrawstat = (localVal & ((uint32_t)0x00000040)) >> 6; + *errorintrawstat = (localVal & ((uint32_t)0x00000020)) >> 5; + *cryptintrawstat = (localVal & ((uint32_t)0x00000010)) >> 4; + *eventintrawstat = (localVal & ((uint32_t)0x00000008)) >> 3; + *slpintrawstat = (localVal & ((uint32_t)0x00000004)) >> 2; + *rxintrawstat = (localVal & ((uint32_t)0x00000002)) >> 1; + *cscntintrawstat = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +__INLINE uint8_t ble_audioint2rawstat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTRAWSTAT_ADDR); + return ((localVal & ((uint32_t)0x00001000)) >> 12); +} + +__INLINE uint8_t ble_audioint1rawstat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTRAWSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000800)) >> 11); +} + +__INLINE uint8_t ble_audioint0rawstat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTRAWSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000400)) >> 10); +} + +__INLINE uint8_t ble_swintrawstat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTRAWSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000200)) >> 9); +} + +__INLINE uint8_t ble_eventapfaintrawstat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTRAWSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000100)) >> 8); +} + +__INLINE uint8_t ble_finetgtimintrawstat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTRAWSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000080)) >> 7); +} + +__INLINE uint8_t ble_grosstgtimintrawstat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTRAWSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000040)) >> 6); +} + +__INLINE uint8_t ble_errorintrawstat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTRAWSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +__INLINE uint8_t ble_cryptintrawstat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTRAWSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +__INLINE uint8_t ble_eventintrawstat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTRAWSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +__INLINE uint8_t ble_slpintrawstat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTRAWSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +__INLINE uint8_t ble_rxintrawstat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTRAWSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +__INLINE uint8_t ble_cscntintrawstat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTRAWSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/** + * @brief INTACK register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     12         AUDIOINT2ACK   0
+ *     11         AUDIOINT1ACK   0
+ *     10         AUDIOINT0ACK   0
+ *     09             SWINTACK   0
+ *     08      EVENTAPFAINTACK   0
+ *     07      FINETGTIMINTACK   0
+ *     06     GROSSTGTIMINTACK   0
+ *     05          ERRORINTACK   0
+ *     04          CRYPTINTACK   0
+ *     03          EVENTINTACK   0
+ *     02            SLPINTACK   0
+ *     01             RXINTACK   0
+ *     00          CSCNTINTACK   0
+ * 
+ */ +#define BLE_INTACK_ADDR 0x00810018 +#define BLE_INTACK_OFFSET 0x00000018 +#define BLE_INTACK_INDEX 0x00000006 +#define BLE_INTACK_RESET 0x00000000 + +__INLINE uint32_t ble_intack_get(void) +{ + return REG_BLE_RD(BLE_INTACK_ADDR); +} + +__INLINE void ble_intack_clear(uint32_t value) +{ + REG_BLE_WR(BLE_INTACK_ADDR, value); +} + +// field definitions +#define BLE_AUDIOINT2ACK_BIT ((uint32_t)0x00001000) +#define BLE_AUDIOINT2ACK_POS 12 +#define BLE_AUDIOINT1ACK_BIT ((uint32_t)0x00000800) +#define BLE_AUDIOINT1ACK_POS 11 +#define BLE_AUDIOINT0ACK_BIT ((uint32_t)0x00000400) +#define BLE_AUDIOINT0ACK_POS 10 +#define BLE_SWINTACK_BIT ((uint32_t)0x00000200) +#define BLE_SWINTACK_POS 9 +#define BLE_EVENTAPFAINTACK_BIT ((uint32_t)0x00000100) +#define BLE_EVENTAPFAINTACK_POS 8 +#define BLE_FINETGTIMINTACK_BIT ((uint32_t)0x00000080) +#define BLE_FINETGTIMINTACK_POS 7 +#define BLE_GROSSTGTIMINTACK_BIT ((uint32_t)0x00000040) +#define BLE_GROSSTGTIMINTACK_POS 6 +#define BLE_ERRORINTACK_BIT ((uint32_t)0x00000020) +#define BLE_ERRORINTACK_POS 5 +#define BLE_CRYPTINTACK_BIT ((uint32_t)0x00000010) +#define BLE_CRYPTINTACK_POS 4 +#define BLE_EVENTINTACK_BIT ((uint32_t)0x00000008) +#define BLE_EVENTINTACK_POS 3 +#define BLE_SLPINTACK_BIT ((uint32_t)0x00000004) +#define BLE_SLPINTACK_POS 2 +#define BLE_RXINTACK_BIT ((uint32_t)0x00000002) +#define BLE_RXINTACK_POS 1 +#define BLE_CSCNTINTACK_BIT ((uint32_t)0x00000001) +#define BLE_CSCNTINTACK_POS 0 + +#define BLE_AUDIOINT2ACK_RST 0x0 +#define BLE_AUDIOINT1ACK_RST 0x0 +#define BLE_AUDIOINT0ACK_RST 0x0 +#define BLE_SWINTACK_RST 0x0 +#define BLE_EVENTAPFAINTACK_RST 0x0 +#define BLE_FINETGTIMINTACK_RST 0x0 +#define BLE_GROSSTGTIMINTACK_RST 0x0 +#define BLE_ERRORINTACK_RST 0x0 +#define BLE_CRYPTINTACK_RST 0x0 +#define BLE_EVENTINTACK_RST 0x0 +#define BLE_SLPINTACK_RST 0x0 +#define BLE_RXINTACK_RST 0x0 +#define BLE_CSCNTINTACK_RST 0x0 + +__INLINE void ble_intack_pack(uint8_t audioint2ack, uint8_t audioint1ack, uint8_t audioint0ack, uint8_t swintack, uint8_t eventapfaintack, uint8_t finetgtimintack, uint8_t grosstgtimintack, uint8_t errorintack, uint8_t cryptintack, uint8_t eventintack, uint8_t slpintack, uint8_t rxintack, uint8_t cscntintack) +{ + ASSERT_ERR((((uint32_t)audioint2ack << 12) & ~((uint32_t)0x00001000)) == 0); + ASSERT_ERR((((uint32_t)audioint1ack << 11) & ~((uint32_t)0x00000800)) == 0); + ASSERT_ERR((((uint32_t)audioint0ack << 10) & ~((uint32_t)0x00000400)) == 0); + ASSERT_ERR((((uint32_t)swintack << 9) & ~((uint32_t)0x00000200)) == 0); + ASSERT_ERR((((uint32_t)eventapfaintack << 8) & ~((uint32_t)0x00000100)) == 0); + ASSERT_ERR((((uint32_t)finetgtimintack << 7) & ~((uint32_t)0x00000080)) == 0); + ASSERT_ERR((((uint32_t)grosstgtimintack << 6) & ~((uint32_t)0x00000040)) == 0); + ASSERT_ERR((((uint32_t)errorintack << 5) & ~((uint32_t)0x00000020)) == 0); + ASSERT_ERR((((uint32_t)cryptintack << 4) & ~((uint32_t)0x00000010)) == 0); + ASSERT_ERR((((uint32_t)eventintack << 3) & ~((uint32_t)0x00000008)) == 0); + ASSERT_ERR((((uint32_t)slpintack << 2) & ~((uint32_t)0x00000004)) == 0); + ASSERT_ERR((((uint32_t)rxintack << 1) & ~((uint32_t)0x00000002)) == 0); + ASSERT_ERR((((uint32_t)cscntintack << 0) & ~((uint32_t)0x00000001)) == 0); + REG_BLE_WR(BLE_INTACK_ADDR, ((uint32_t)audioint2ack << 12) | ((uint32_t)audioint1ack << 11) | ((uint32_t)audioint0ack << 10) | ((uint32_t)swintack << 9) | ((uint32_t)eventapfaintack << 8) | ((uint32_t)finetgtimintack << 7) | ((uint32_t)grosstgtimintack << 6) | ((uint32_t)errorintack << 5) | ((uint32_t)cryptintack << 4) | ((uint32_t)eventintack << 3) | ((uint32_t)slpintack << 2) | ((uint32_t)rxintack << 1) | ((uint32_t)cscntintack << 0)); +} + +__INLINE void ble_intack_unpack(uint8_t* audioint2ack, uint8_t* audioint1ack, uint8_t* audioint0ack, uint8_t* swintack, uint8_t* eventapfaintack, uint8_t* finetgtimintack, uint8_t* grosstgtimintack, uint8_t* errorintack, uint8_t* cryptintack, uint8_t* eventintack, uint8_t* slpintack, uint8_t* rxintack, uint8_t* cscntintack) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTACK_ADDR); + + *audioint2ack = (localVal & ((uint32_t)0x00001000)) >> 12; + *audioint1ack = (localVal & ((uint32_t)0x00000800)) >> 11; + *audioint0ack = (localVal & ((uint32_t)0x00000400)) >> 10; + *swintack = (localVal & ((uint32_t)0x00000200)) >> 9; + *eventapfaintack = (localVal & ((uint32_t)0x00000100)) >> 8; + *finetgtimintack = (localVal & ((uint32_t)0x00000080)) >> 7; + *grosstgtimintack = (localVal & ((uint32_t)0x00000040)) >> 6; + *errorintack = (localVal & ((uint32_t)0x00000020)) >> 5; + *cryptintack = (localVal & ((uint32_t)0x00000010)) >> 4; + *eventintack = (localVal & ((uint32_t)0x00000008)) >> 3; + *slpintack = (localVal & ((uint32_t)0x00000004)) >> 2; + *rxintack = (localVal & ((uint32_t)0x00000002)) >> 1; + *cscntintack = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +__INLINE uint8_t ble_audioint2ack_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTACK_ADDR); + return ((localVal & ((uint32_t)0x00001000)) >> 12); +} + +__INLINE void ble_audioint2ack_clearf(uint8_t audioint2ack) +{ + ASSERT_ERR((((uint32_t)audioint2ack << 12) & ~((uint32_t)0x00001000)) == 0); + REG_BLE_WR(BLE_INTACK_ADDR, (uint32_t)audioint2ack << 12); +} + +__INLINE uint8_t ble_audioint1ack_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTACK_ADDR); + return ((localVal & ((uint32_t)0x00000800)) >> 11); +} + +__INLINE void ble_audioint1ack_clearf(uint8_t audioint1ack) +{ + ASSERT_ERR((((uint32_t)audioint1ack << 11) & ~((uint32_t)0x00000800)) == 0); + REG_BLE_WR(BLE_INTACK_ADDR, (uint32_t)audioint1ack << 11); +} + +__INLINE uint8_t ble_audioint0ack_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTACK_ADDR); + return ((localVal & ((uint32_t)0x00000400)) >> 10); +} + +__INLINE void ble_audioint0ack_clearf(uint8_t audioint0ack) +{ + ASSERT_ERR((((uint32_t)audioint0ack << 10) & ~((uint32_t)0x00000400)) == 0); + REG_BLE_WR(BLE_INTACK_ADDR, (uint32_t)audioint0ack << 10); +} + +__INLINE uint8_t ble_swintack_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTACK_ADDR); + return ((localVal & ((uint32_t)0x00000200)) >> 9); +} + +__INLINE void ble_swintack_clearf(uint8_t swintack) +{ + ASSERT_ERR((((uint32_t)swintack << 9) & ~((uint32_t)0x00000200)) == 0); + REG_BLE_WR(BLE_INTACK_ADDR, (uint32_t)swintack << 9); +} + +__INLINE uint8_t ble_eventapfaintack_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTACK_ADDR); + return ((localVal & ((uint32_t)0x00000100)) >> 8); +} + +__INLINE void ble_eventapfaintack_clearf(uint8_t eventapfaintack) +{ + ASSERT_ERR((((uint32_t)eventapfaintack << 8) & ~((uint32_t)0x00000100)) == 0); + REG_BLE_WR(BLE_INTACK_ADDR, (uint32_t)eventapfaintack << 8); +} + +__INLINE uint8_t ble_finetgtimintack_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTACK_ADDR); + return ((localVal & ((uint32_t)0x00000080)) >> 7); +} + +__INLINE void ble_finetgtimintack_clearf(uint8_t finetgtimintack) +{ + ASSERT_ERR((((uint32_t)finetgtimintack << 7) & ~((uint32_t)0x00000080)) == 0); + REG_BLE_WR(BLE_INTACK_ADDR, (uint32_t)finetgtimintack << 7); +} + +__INLINE uint8_t ble_grosstgtimintack_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTACK_ADDR); + return ((localVal & ((uint32_t)0x00000040)) >> 6); +} + +__INLINE void ble_grosstgtimintack_clearf(uint8_t grosstgtimintack) +{ + ASSERT_ERR((((uint32_t)grosstgtimintack << 6) & ~((uint32_t)0x00000040)) == 0); + REG_BLE_WR(BLE_INTACK_ADDR, (uint32_t)grosstgtimintack << 6); +} + +__INLINE uint8_t ble_errorintack_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTACK_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +__INLINE void ble_errorintack_clearf(uint8_t errorintack) +{ + ASSERT_ERR((((uint32_t)errorintack << 5) & ~((uint32_t)0x00000020)) == 0); + REG_BLE_WR(BLE_INTACK_ADDR, (uint32_t)errorintack << 5); +} + +__INLINE uint8_t ble_cryptintack_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTACK_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +__INLINE void ble_cryptintack_clearf(uint8_t cryptintack) +{ + ASSERT_ERR((((uint32_t)cryptintack << 4) & ~((uint32_t)0x00000010)) == 0); + REG_BLE_WR(BLE_INTACK_ADDR, (uint32_t)cryptintack << 4); +} + +__INLINE uint8_t ble_eventintack_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTACK_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +__INLINE void ble_eventintack_clearf(uint8_t eventintack) +{ + ASSERT_ERR((((uint32_t)eventintack << 3) & ~((uint32_t)0x00000008)) == 0); + REG_BLE_WR(BLE_INTACK_ADDR, (uint32_t)eventintack << 3); +} + +__INLINE uint8_t ble_slpintack_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTACK_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +__INLINE void ble_slpintack_clearf(uint8_t slpintack) +{ + ASSERT_ERR((((uint32_t)slpintack << 2) & ~((uint32_t)0x00000004)) == 0); + REG_BLE_WR(BLE_INTACK_ADDR, (uint32_t)slpintack << 2); +} + +__INLINE uint8_t ble_rxintack_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTACK_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +__INLINE void ble_rxintack_clearf(uint8_t rxintack) +{ + ASSERT_ERR((((uint32_t)rxintack << 1) & ~((uint32_t)0x00000002)) == 0); + REG_BLE_WR(BLE_INTACK_ADDR, (uint32_t)rxintack << 1); +} + +__INLINE uint8_t ble_cscntintack_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTACK_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +__INLINE void ble_cscntintack_clearf(uint8_t cscntintack) +{ + ASSERT_ERR((((uint32_t)cscntintack << 0) & ~((uint32_t)0x00000001)) == 0); + REG_BLE_WR(BLE_INTACK_ADDR, (uint32_t)cscntintack << 0); +} + +/** + * @brief BASETIMECNT register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31                 SAMP   0
+ *  26:00          BASETIMECNT   0x0
+ * 
+ */ +#define BLE_BASETIMECNT_ADDR 0x0081001C +#define BLE_BASETIMECNT_OFFSET 0x0000001C +#define BLE_BASETIMECNT_INDEX 0x00000007 +#define BLE_BASETIMECNT_RESET 0x00000000 + +__INLINE uint32_t ble_basetimecnt_get(void) +{ + return REG_BLE_RD(BLE_BASETIMECNT_ADDR); +} + +__INLINE void ble_basetimecnt_set(uint32_t value) +{ + REG_BLE_WR(BLE_BASETIMECNT_ADDR, value); +} + +// field definitions +#define BLE_SAMP_BIT ((uint32_t)0x80000000) +#define BLE_SAMP_POS 31 +#define BLE_BASETIMECNT_MASK ((uint32_t)0x07FFFFFF) +#define BLE_BASETIMECNT_LSB 0 +#define BLE_BASETIMECNT_WIDTH ((uint32_t)0x0000001B) + +#define BLE_SAMP_RST 0x0 +#define BLE_BASETIMECNT_RST 0x0 + +__INLINE void ble_basetimecnt_unpack(uint8_t* samp, uint32_t* basetimecnt) +{ + uint32_t localVal = REG_BLE_RD(BLE_BASETIMECNT_ADDR); + + *samp = (localVal & ((uint32_t)0x80000000)) >> 31; + *basetimecnt = (localVal & ((uint32_t)0x07FFFFFF)) >> 0; +} + +__INLINE uint8_t ble_samp_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_BASETIMECNT_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +__INLINE void ble_samp_setf(uint8_t samp) +{ + ASSERT_ERR((((uint32_t)samp << 31) & ~((uint32_t)0x80000000)) == 0); + REG_BLE_WR(BLE_BASETIMECNT_ADDR, (uint32_t)samp << 31); +} + +__INLINE uint32_t ble_basetimecnt_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_BASETIMECNT_ADDR); + return ((localVal & ((uint32_t)0x07FFFFFF)) >> 0); +} + +/** + * @brief FINETIMECNT register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  09:00              FINECNT   0x0
+ * 
+ */ +#define BLE_FINETIMECNT_ADDR 0x00810020 +#define BLE_FINETIMECNT_OFFSET 0x00000020 +#define BLE_FINETIMECNT_INDEX 0x00000008 +#define BLE_FINETIMECNT_RESET 0x00000000 + +__INLINE uint32_t ble_finetimecnt_get(void) +{ + return REG_BLE_RD(BLE_FINETIMECNT_ADDR); +} + +// field definitions +#define BLE_FINECNT_MASK ((uint32_t)0x000003FF) +#define BLE_FINECNT_LSB 0 +#define BLE_FINECNT_WIDTH ((uint32_t)0x0000000A) + +#define BLE_FINECNT_RST 0x0 + +__INLINE uint16_t ble_finecnt_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_FINETIMECNT_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x000003FF)) == 0); + return (localVal >> 0); +} + +/** + * @brief BDADDRL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00              BDADDRL   0x0
+ * 
+ */ +#define BLE_BDADDRL_ADDR 0x00810024 +#define BLE_BDADDRL_OFFSET 0x00000024 +#define BLE_BDADDRL_INDEX 0x00000009 +#define BLE_BDADDRL_RESET 0x00000000 + +__INLINE uint32_t ble_bdaddrl_get(void) +{ + return REG_BLE_RD(BLE_BDADDRL_ADDR); +} + +__INLINE void ble_bdaddrl_set(uint32_t value) +{ + REG_BLE_WR(BLE_BDADDRL_ADDR, value); +} + +// field definitions +#define BLE_BDADDRL_MASK ((uint32_t)0xFFFFFFFF) +#define BLE_BDADDRL_LSB 0 +#define BLE_BDADDRL_WIDTH ((uint32_t)0x00000020) + +#define BLE_BDADDRL_RST 0x0 + +__INLINE uint32_t ble_bdaddrl_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_BDADDRL_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_bdaddrl_setf(uint32_t bdaddrl) +{ + ASSERT_ERR((((uint32_t)bdaddrl << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_BLE_WR(BLE_BDADDRL_ADDR, (uint32_t)bdaddrl << 0); +} + +/** + * @brief BDADDRU register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     16            PRIV_NPUB   0
+ *  15:00              BDADDRU   0x0
+ * 
+ */ +#define BLE_BDADDRU_ADDR 0x00810028 +#define BLE_BDADDRU_OFFSET 0x00000028 +#define BLE_BDADDRU_INDEX 0x0000000A +#define BLE_BDADDRU_RESET 0x00000000 + +__INLINE uint32_t ble_bdaddru_get(void) +{ + return REG_BLE_RD(BLE_BDADDRU_ADDR); +} + +__INLINE void ble_bdaddru_set(uint32_t value) +{ + REG_BLE_WR(BLE_BDADDRU_ADDR, value); +} + +// field definitions +#define BLE_PRIV_NPUB_BIT ((uint32_t)0x00010000) +#define BLE_PRIV_NPUB_POS 16 +#define BLE_BDADDRU_MASK ((uint32_t)0x0000FFFF) +#define BLE_BDADDRU_LSB 0 +#define BLE_BDADDRU_WIDTH ((uint32_t)0x00000010) + +#define BLE_PRIV_NPUB_RST 0x0 +#define BLE_BDADDRU_RST 0x0 + +__INLINE void ble_bdaddru_pack(uint8_t privnpub, uint16_t bdaddru) +{ + ASSERT_ERR((((uint32_t)privnpub << 16) & ~((uint32_t)0x00010000)) == 0); + ASSERT_ERR((((uint32_t)bdaddru << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_BLE_WR(BLE_BDADDRU_ADDR, ((uint32_t)privnpub << 16) | ((uint32_t)bdaddru << 0)); +} + +__INLINE void ble_bdaddru_unpack(uint8_t* privnpub, uint16_t* bdaddru) +{ + uint32_t localVal = REG_BLE_RD(BLE_BDADDRU_ADDR); + + *privnpub = (localVal & ((uint32_t)0x00010000)) >> 16; + *bdaddru = (localVal & ((uint32_t)0x0000FFFF)) >> 0; +} + +__INLINE uint8_t ble_priv_npub_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_BDADDRU_ADDR); + return ((localVal & ((uint32_t)0x00010000)) >> 16); +} + +__INLINE void ble_priv_npub_setf(uint8_t privnpub) +{ + ASSERT_ERR((((uint32_t)privnpub << 16) & ~((uint32_t)0x00010000)) == 0); + REG_BLE_WR(BLE_BDADDRU_ADDR, (REG_BLE_RD(BLE_BDADDRU_ADDR) & ~((uint32_t)0x00010000)) | ((uint32_t)privnpub << 16)); +} + +__INLINE uint16_t ble_bdaddru_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_BDADDRU_ADDR); + return ((localVal & ((uint32_t)0x0000FFFF)) >> 0); +} + +__INLINE void ble_bdaddru_setf(uint16_t bdaddru) +{ + ASSERT_ERR((((uint32_t)bdaddru << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_BLE_WR(BLE_BDADDRU_ADDR, (REG_BLE_RD(BLE_BDADDRU_ADDR) & ~((uint32_t)0x0000FFFF)) | ((uint32_t)bdaddru << 0)); +} + +/** + * @brief ET_CURRENTRXDESCPTR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:16                ETPTR   0x0
+ *  14:00     CURRENTRXDESCPTR   0x0
+ * 
+ */ +#define BLE_ET_CURRENTRXDESCPTR_ADDR 0x0081002C +#define BLE_ET_CURRENTRXDESCPTR_OFFSET 0x0000002C +#define BLE_ET_CURRENTRXDESCPTR_INDEX 0x0000000B +#define BLE_ET_CURRENTRXDESCPTR_RESET 0x00000000 + +__INLINE uint32_t ble_et_currentrxdescptr_get(void) +{ + return REG_BLE_RD(BLE_ET_CURRENTRXDESCPTR_ADDR); +} + +__INLINE void ble_et_currentrxdescptr_set(uint32_t value) +{ + REG_BLE_WR(BLE_ET_CURRENTRXDESCPTR_ADDR, value); +} + +// field definitions +#define BLE_ETPTR_MASK ((uint32_t)0xFFFF0000) +#define BLE_ETPTR_LSB 16 +#define BLE_ETPTR_WIDTH ((uint32_t)0x00000010) +#define BLE_CURRENTRXDESCPTR_MASK ((uint32_t)0x00007FFF) +#define BLE_CURRENTRXDESCPTR_LSB 0 +#define BLE_CURRENTRXDESCPTR_WIDTH ((uint32_t)0x0000000F) + +#define BLE_ETPTR_RST 0x0 +#define BLE_CURRENTRXDESCPTR_RST 0x0 + +__INLINE void ble_et_currentrxdescptr_pack(uint16_t etptr, uint16_t currentrxdescptr) +{ + ASSERT_ERR((((uint32_t)etptr << 16) & ~((uint32_t)0xFFFF0000)) == 0); + ASSERT_ERR((((uint32_t)currentrxdescptr << 0) & ~((uint32_t)0x00007FFF)) == 0); + REG_BLE_WR(BLE_ET_CURRENTRXDESCPTR_ADDR, ((uint32_t)etptr << 16) | ((uint32_t)currentrxdescptr << 0)); +} + +__INLINE void ble_et_currentrxdescptr_unpack(uint16_t* etptr, uint16_t* currentrxdescptr) +{ + uint32_t localVal = REG_BLE_RD(BLE_ET_CURRENTRXDESCPTR_ADDR); + + *etptr = (localVal & ((uint32_t)0xFFFF0000)) >> 16; + *currentrxdescptr = (localVal & ((uint32_t)0x00007FFF)) >> 0; +} + +__INLINE uint16_t ble_etptr_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ET_CURRENTRXDESCPTR_ADDR); + return ((localVal & ((uint32_t)0xFFFF0000)) >> 16); +} + +__INLINE void ble_etptr_setf(uint16_t etptr) +{ + ASSERT_ERR((((uint32_t)etptr << 16) & ~((uint32_t)0xFFFF0000)) == 0); + REG_BLE_WR(BLE_ET_CURRENTRXDESCPTR_ADDR, (REG_BLE_RD(BLE_ET_CURRENTRXDESCPTR_ADDR) & ~((uint32_t)0xFFFF0000)) | ((uint32_t)etptr << 16)); +} + +__INLINE uint16_t ble_currentrxdescptr_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ET_CURRENTRXDESCPTR_ADDR); + return ((localVal & ((uint32_t)0x00007FFF)) >> 0); +} + +__INLINE void ble_currentrxdescptr_setf(uint16_t currentrxdescptr) +{ + ASSERT_ERR((((uint32_t)currentrxdescptr << 0) & ~((uint32_t)0x00007FFF)) == 0); + REG_BLE_WR(BLE_ET_CURRENTRXDESCPTR_ADDR, (REG_BLE_RD(BLE_ET_CURRENTRXDESCPTR_ADDR) & ~((uint32_t)0x00007FFF)) | ((uint32_t)currentrxdescptr << 0)); +} + +/** + * @brief DEEPSLCNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31           EXTWKUPDSB   0
+ *     15      DEEP_SLEEP_STAT   0
+ *     04      SOFT_WAKEUP_REQ   0
+ *     03   DEEP_SLEEP_CORR_EN   0
+ *     02        DEEP_SLEEP_ON   0
+ *     01       RADIO_SLEEP_EN   0
+ *     00         OSC_SLEEP_EN   0
+ * 
+ */ +#define BLE_DEEPSLCNTL_ADDR 0x00810030 +#define BLE_DEEPSLCNTL_OFFSET 0x00000030 +#define BLE_DEEPSLCNTL_INDEX 0x0000000C +#define BLE_DEEPSLCNTL_RESET 0x00000000 + +__INLINE uint32_t ble_deepslcntl_get(void) +{ + return REG_BLE_RD(BLE_DEEPSLCNTL_ADDR); +} + +__INLINE void ble_deepslcntl_set(uint32_t value) +{ + REG_BLE_WR(BLE_DEEPSLCNTL_ADDR, value); +} + +// field definitions +#define BLE_EXTWKUPDSB_BIT ((uint32_t)0x80000000) +#define BLE_EXTWKUPDSB_POS 31 +#define BLE_DEEP_SLEEP_STAT_BIT ((uint32_t)0x00008000) +#define BLE_DEEP_SLEEP_STAT_POS 15 +#define BLE_SOFT_WAKEUP_REQ_BIT ((uint32_t)0x00000010) +#define BLE_SOFT_WAKEUP_REQ_POS 4 +#define BLE_DEEP_SLEEP_CORR_EN_BIT ((uint32_t)0x00000008) +#define BLE_DEEP_SLEEP_CORR_EN_POS 3 +#define BLE_DEEP_SLEEP_ON_BIT ((uint32_t)0x00000004) +#define BLE_DEEP_SLEEP_ON_POS 2 +#define BLE_RADIO_SLEEP_EN_BIT ((uint32_t)0x00000002) +#define BLE_RADIO_SLEEP_EN_POS 1 +#define BLE_OSC_SLEEP_EN_BIT ((uint32_t)0x00000001) +#define BLE_OSC_SLEEP_EN_POS 0 + +#define BLE_EXTWKUPDSB_RST 0x0 +#define BLE_DEEP_SLEEP_STAT_RST 0x0 +#define BLE_SOFT_WAKEUP_REQ_RST 0x0 +#define BLE_DEEP_SLEEP_CORR_EN_RST 0x0 +#define BLE_DEEP_SLEEP_ON_RST 0x0 +#define BLE_RADIO_SLEEP_EN_RST 0x0 +#define BLE_OSC_SLEEP_EN_RST 0x0 + +__INLINE void ble_deepslcntl_pack(uint8_t extwkupdsb, uint8_t softwakeupreq, uint8_t deepsleepcorren, uint8_t deepsleepon, uint8_t radiosleepen, uint8_t oscsleepen) +{ + ASSERT_ERR((((uint32_t)extwkupdsb << 31) & ~((uint32_t)0x80000000)) == 0); + ASSERT_ERR((((uint32_t)softwakeupreq << 4) & ~((uint32_t)0x00000010)) == 0); + ASSERT_ERR((((uint32_t)deepsleepcorren << 3) & ~((uint32_t)0x00000008)) == 0); + ASSERT_ERR((((uint32_t)deepsleepon << 2) & ~((uint32_t)0x00000004)) == 0); + ASSERT_ERR((((uint32_t)radiosleepen << 1) & ~((uint32_t)0x00000002)) == 0); + ASSERT_ERR((((uint32_t)oscsleepen << 0) & ~((uint32_t)0x00000001)) == 0); + REG_BLE_WR(BLE_DEEPSLCNTL_ADDR, ((uint32_t)extwkupdsb << 31) | ((uint32_t)softwakeupreq << 4) | ((uint32_t)deepsleepcorren << 3) | ((uint32_t)deepsleepon << 2) | ((uint32_t)radiosleepen << 1) | ((uint32_t)oscsleepen << 0)); +} + +__INLINE void ble_deepslcntl_unpack(uint8_t* extwkupdsb, uint8_t* deepsleepstat, uint8_t* softwakeupreq, uint8_t* deepsleepcorren, uint8_t* deepsleepon, uint8_t* radiosleepen, uint8_t* oscsleepen) +{ + uint32_t localVal = REG_BLE_RD(BLE_DEEPSLCNTL_ADDR); + + *extwkupdsb = (localVal & ((uint32_t)0x80000000)) >> 31; + *deepsleepstat = (localVal & ((uint32_t)0x00008000)) >> 15; + *softwakeupreq = (localVal & ((uint32_t)0x00000010)) >> 4; + *deepsleepcorren = (localVal & ((uint32_t)0x00000008)) >> 3; + *deepsleepon = (localVal & ((uint32_t)0x00000004)) >> 2; + *radiosleepen = (localVal & ((uint32_t)0x00000002)) >> 1; + *oscsleepen = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +__INLINE uint8_t ble_extwkupdsb_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DEEPSLCNTL_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +__INLINE void ble_extwkupdsb_setf(uint8_t extwkupdsb) +{ + ASSERT_ERR((((uint32_t)extwkupdsb << 31) & ~((uint32_t)0x80000000)) == 0); + REG_BLE_WR(BLE_DEEPSLCNTL_ADDR, (REG_BLE_RD(BLE_DEEPSLCNTL_ADDR) & ~((uint32_t)0x80000000)) | ((uint32_t)extwkupdsb << 31)); +} + +__INLINE uint8_t ble_deep_sleep_stat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DEEPSLCNTL_ADDR); + return ((localVal & ((uint32_t)0x00008000)) >> 15); +} + +__INLINE uint8_t ble_soft_wakeup_req_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DEEPSLCNTL_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +__INLINE void ble_soft_wakeup_req_setf(uint8_t softwakeupreq) +{ + ASSERT_ERR((((uint32_t)softwakeupreq << 4) & ~((uint32_t)0x00000010)) == 0); + REG_BLE_WR(BLE_DEEPSLCNTL_ADDR, (REG_BLE_RD(BLE_DEEPSLCNTL_ADDR) & ~((uint32_t)0x00000010)) | ((uint32_t)softwakeupreq << 4)); +} + +__INLINE uint8_t ble_deep_sleep_corr_en_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DEEPSLCNTL_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +__INLINE void ble_deep_sleep_corr_en_setf(uint8_t deepsleepcorren) +{ + ASSERT_ERR((((uint32_t)deepsleepcorren << 3) & ~((uint32_t)0x00000008)) == 0); + REG_BLE_WR(BLE_DEEPSLCNTL_ADDR, (REG_BLE_RD(BLE_DEEPSLCNTL_ADDR) & ~((uint32_t)0x00000008)) | ((uint32_t)deepsleepcorren << 3)); +} + +__INLINE uint8_t ble_deep_sleep_on_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DEEPSLCNTL_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +__INLINE void ble_deep_sleep_on_setf(uint8_t deepsleepon) +{ + ASSERT_ERR((((uint32_t)deepsleepon << 2) & ~((uint32_t)0x00000004)) == 0); + REG_BLE_WR(BLE_DEEPSLCNTL_ADDR, (REG_BLE_RD(BLE_DEEPSLCNTL_ADDR) & ~((uint32_t)0x00000004)) | ((uint32_t)deepsleepon << 2)); +} + +__INLINE uint8_t ble_radio_sleep_en_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DEEPSLCNTL_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +__INLINE void ble_radio_sleep_en_setf(uint8_t radiosleepen) +{ + ASSERT_ERR((((uint32_t)radiosleepen << 1) & ~((uint32_t)0x00000002)) == 0); + REG_BLE_WR(BLE_DEEPSLCNTL_ADDR, (REG_BLE_RD(BLE_DEEPSLCNTL_ADDR) & ~((uint32_t)0x00000002)) | ((uint32_t)radiosleepen << 1)); +} + +__INLINE uint8_t ble_osc_sleep_en_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DEEPSLCNTL_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +__INLINE void ble_osc_sleep_en_setf(uint8_t oscsleepen) +{ + ASSERT_ERR((((uint32_t)oscsleepen << 0) & ~((uint32_t)0x00000001)) == 0); + REG_BLE_WR(BLE_DEEPSLCNTL_ADDR, (REG_BLE_RD(BLE_DEEPSLCNTL_ADDR) & ~((uint32_t)0x00000001)) | ((uint32_t)oscsleepen << 0)); +} + +/** + * @brief DEEPSLWKUP register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00           DEEPSLTIME   0x0
+ * 
+ */ +#define BLE_DEEPSLWKUP_ADDR 0x00810034 +#define BLE_DEEPSLWKUP_OFFSET 0x00000034 +#define BLE_DEEPSLWKUP_INDEX 0x0000000D +#define BLE_DEEPSLWKUP_RESET 0x00000000 + +__INLINE uint32_t ble_deepslwkup_get(void) +{ + return REG_BLE_RD(BLE_DEEPSLWKUP_ADDR); +} + +__INLINE void ble_deepslwkup_set(uint32_t value) +{ + REG_BLE_WR(BLE_DEEPSLWKUP_ADDR, value); +} + +// field definitions +#define BLE_DEEPSLTIME_MASK ((uint32_t)0xFFFFFFFF) +#define BLE_DEEPSLTIME_LSB 0 +#define BLE_DEEPSLTIME_WIDTH ((uint32_t)0x00000020) + +#define BLE_DEEPSLTIME_RST 0x0 + +__INLINE uint32_t ble_deepsltime_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DEEPSLWKUP_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_deepsltime_setf(uint32_t deepsltime) +{ + ASSERT_ERR((((uint32_t)deepsltime << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_BLE_WR(BLE_DEEPSLWKUP_ADDR, (uint32_t)deepsltime << 0); +} + +/** + * @brief DEEPSLSTAT register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00            DEEPSLDUR   0x0
+ * 
+ */ +#define BLE_DEEPSLSTAT_ADDR 0x00810038 +#define BLE_DEEPSLSTAT_OFFSET 0x00000038 +#define BLE_DEEPSLSTAT_INDEX 0x0000000E +#define BLE_DEEPSLSTAT_RESET 0x00000000 + +__INLINE uint32_t ble_deepslstat_get(void) +{ + return REG_BLE_RD(BLE_DEEPSLSTAT_ADDR); +} + +// field definitions +#define BLE_DEEPSLDUR_MASK ((uint32_t)0xFFFFFFFF) +#define BLE_DEEPSLDUR_LSB 0 +#define BLE_DEEPSLDUR_WIDTH ((uint32_t)0x00000020) + +#define BLE_DEEPSLDUR_RST 0x0 + +__INLINE uint32_t ble_deepsldur_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DEEPSLSTAT_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief ENBPRESET register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:21                TWEXT   0x0
+ *  20:10                TWOSC   0x0
+ *  09:00                 TWRM   0x0
+ * 
+ */ +#define BLE_ENBPRESET_ADDR 0x0081003C +#define BLE_ENBPRESET_OFFSET 0x0000003C +#define BLE_ENBPRESET_INDEX 0x0000000F +#define BLE_ENBPRESET_RESET 0x00000000 + +__INLINE uint32_t ble_enbpreset_get(void) +{ + return REG_BLE_RD(BLE_ENBPRESET_ADDR); +} + +__INLINE void ble_enbpreset_set(uint32_t value) +{ + REG_BLE_WR(BLE_ENBPRESET_ADDR, value); +} + +// field definitions +#define BLE_TWEXT_MASK ((uint32_t)0xFFE00000) +#define BLE_TWEXT_LSB 21 +#define BLE_TWEXT_WIDTH ((uint32_t)0x0000000B) +#define BLE_TWOSC_MASK ((uint32_t)0x001FFC00) +#define BLE_TWOSC_LSB 10 +#define BLE_TWOSC_WIDTH ((uint32_t)0x0000000B) +#define BLE_TWRM_MASK ((uint32_t)0x000003FF) +#define BLE_TWRM_LSB 0 +#define BLE_TWRM_WIDTH ((uint32_t)0x0000000A) + +#define BLE_TWEXT_RST 0x0 +#define BLE_TWOSC_RST 0x0 +#define BLE_TWRM_RST 0x0 + +__INLINE void ble_enbpreset_pack(uint16_t twext, uint16_t twosc, uint16_t twrm) +{ + ASSERT_ERR((((uint32_t)twext << 21) & ~((uint32_t)0xFFE00000)) == 0); + ASSERT_ERR((((uint32_t)twosc << 10) & ~((uint32_t)0x001FFC00)) == 0); + ASSERT_ERR((((uint32_t)twrm << 0) & ~((uint32_t)0x000003FF)) == 0); + REG_BLE_WR(BLE_ENBPRESET_ADDR, ((uint32_t)twext << 21) | ((uint32_t)twosc << 10) | ((uint32_t)twrm << 0)); +} + +__INLINE void ble_enbpreset_unpack(uint16_t* twext, uint16_t* twosc, uint16_t* twrm) +{ + uint32_t localVal = REG_BLE_RD(BLE_ENBPRESET_ADDR); + + *twext = (localVal & ((uint32_t)0xFFE00000)) >> 21; + *twosc = (localVal & ((uint32_t)0x001FFC00)) >> 10; + *twrm = (localVal & ((uint32_t)0x000003FF)) >> 0; +} + +__INLINE uint16_t ble_twext_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ENBPRESET_ADDR); + return ((localVal & ((uint32_t)0xFFE00000)) >> 21); +} + +__INLINE void ble_twext_setf(uint16_t twext) +{ + ASSERT_ERR((((uint32_t)twext << 21) & ~((uint32_t)0xFFE00000)) == 0); + REG_BLE_WR(BLE_ENBPRESET_ADDR, (REG_BLE_RD(BLE_ENBPRESET_ADDR) & ~((uint32_t)0xFFE00000)) | ((uint32_t)twext << 21)); +} + +__INLINE uint16_t ble_twosc_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ENBPRESET_ADDR); + return ((localVal & ((uint32_t)0x001FFC00)) >> 10); +} + +__INLINE void ble_twosc_setf(uint16_t twosc) +{ + ASSERT_ERR((((uint32_t)twosc << 10) & ~((uint32_t)0x001FFC00)) == 0); + REG_BLE_WR(BLE_ENBPRESET_ADDR, (REG_BLE_RD(BLE_ENBPRESET_ADDR) & ~((uint32_t)0x001FFC00)) | ((uint32_t)twosc << 10)); +} + +__INLINE uint16_t ble_twrm_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ENBPRESET_ADDR); + return ((localVal & ((uint32_t)0x000003FF)) >> 0); +} + +__INLINE void ble_twrm_setf(uint16_t twrm) +{ + ASSERT_ERR((((uint32_t)twrm << 0) & ~((uint32_t)0x000003FF)) == 0); + REG_BLE_WR(BLE_ENBPRESET_ADDR, (REG_BLE_RD(BLE_ENBPRESET_ADDR) & ~((uint32_t)0x000003FF)) | ((uint32_t)twrm << 0)); +} + +/** + * @brief FINECNTCORR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  09:00          FINECNTCORR   0x0
+ * 
+ */ +#define BLE_FINECNTCORR_ADDR 0x00810040 +#define BLE_FINECNTCORR_OFFSET 0x00000040 +#define BLE_FINECNTCORR_INDEX 0x00000010 +#define BLE_FINECNTCORR_RESET 0x00000000 + +__INLINE uint32_t ble_finecntcorr_get(void) +{ + return REG_BLE_RD(BLE_FINECNTCORR_ADDR); +} + +__INLINE void ble_finecntcorr_set(uint32_t value) +{ + REG_BLE_WR(BLE_FINECNTCORR_ADDR, value); +} + +// field definitions +#define BLE_FINECNTCORR_MASK ((uint32_t)0x000003FF) +#define BLE_FINECNTCORR_LSB 0 +#define BLE_FINECNTCORR_WIDTH ((uint32_t)0x0000000A) + +#define BLE_FINECNTCORR_RST 0x0 + +__INLINE uint16_t ble_finecntcorr_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_FINECNTCORR_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x000003FF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_finecntcorr_setf(uint16_t finecntcorr) +{ + ASSERT_ERR((((uint32_t)finecntcorr << 0) & ~((uint32_t)0x000003FF)) == 0); + REG_BLE_WR(BLE_FINECNTCORR_ADDR, (uint32_t)finecntcorr << 0); +} + +/** + * @brief BASETIMECNTCORR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  26:00      BASETIMECNTCORR   0x0
+ * 
+ */ +#define BLE_BASETIMECNTCORR_ADDR 0x00810044 +#define BLE_BASETIMECNTCORR_OFFSET 0x00000044 +#define BLE_BASETIMECNTCORR_INDEX 0x00000011 +#define BLE_BASETIMECNTCORR_RESET 0x00000000 + +__INLINE uint32_t ble_basetimecntcorr_get(void) +{ + return REG_BLE_RD(BLE_BASETIMECNTCORR_ADDR); +} + +__INLINE void ble_basetimecntcorr_set(uint32_t value) +{ + REG_BLE_WR(BLE_BASETIMECNTCORR_ADDR, value); +} + +// field definitions +#define BLE_BASETIMECNTCORR_MASK ((uint32_t)0x07FFFFFF) +#define BLE_BASETIMECNTCORR_LSB 0 +#define BLE_BASETIMECNTCORR_WIDTH ((uint32_t)0x0000001B) + +#define BLE_BASETIMECNTCORR_RST 0x0 + +__INLINE uint32_t ble_basetimecntcorr_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_BASETIMECNTCORR_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x07FFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_basetimecntcorr_setf(uint32_t basetimecntcorr) +{ + ASSERT_ERR((((uint32_t)basetimecntcorr << 0) & ~((uint32_t)0x07FFFFFF)) == 0); + REG_BLE_WR(BLE_BASETIMECNTCORR_ADDR, (uint32_t)basetimecntcorr << 0); +} + +/** + * @brief DIAGCNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31             DIAG3_EN   0
+ *  29:24                DIAG3   0x0
+ *     23             DIAG2_EN   0
+ *  21:16                DIAG2   0x0
+ *     15             DIAG1_EN   0
+ *  13:08                DIAG1   0x0
+ *     07             DIAG0_EN   0
+ *  05:00                DIAG0   0x0
+ * 
+ */ +#define BLE_DIAGCNTL_ADDR 0x00810050 +#define BLE_DIAGCNTL_OFFSET 0x00000050 +#define BLE_DIAGCNTL_INDEX 0x00000014 +#define BLE_DIAGCNTL_RESET 0x00000000 + +__INLINE uint32_t ble_diagcntl_get(void) +{ + return REG_BLE_RD(BLE_DIAGCNTL_ADDR); +} + +__INLINE void ble_diagcntl_set(uint32_t value) +{ + REG_BLE_WR(BLE_DIAGCNTL_ADDR, value); +} + +// field definitions +#define BLE_DIAG3_EN_BIT ((uint32_t)0x80000000) +#define BLE_DIAG3_EN_POS 31 +#define BLE_DIAG3_MASK ((uint32_t)0x3F000000) +#define BLE_DIAG3_LSB 24 +#define BLE_DIAG3_WIDTH ((uint32_t)0x00000006) +#define BLE_DIAG2_EN_BIT ((uint32_t)0x00800000) +#define BLE_DIAG2_EN_POS 23 +#define BLE_DIAG2_MASK ((uint32_t)0x003F0000) +#define BLE_DIAG2_LSB 16 +#define BLE_DIAG2_WIDTH ((uint32_t)0x00000006) +#define BLE_DIAG1_EN_BIT ((uint32_t)0x00008000) +#define BLE_DIAG1_EN_POS 15 +#define BLE_DIAG1_MASK ((uint32_t)0x00003F00) +#define BLE_DIAG1_LSB 8 +#define BLE_DIAG1_WIDTH ((uint32_t)0x00000006) +#define BLE_DIAG0_EN_BIT ((uint32_t)0x00000080) +#define BLE_DIAG0_EN_POS 7 +#define BLE_DIAG0_MASK ((uint32_t)0x0000003F) +#define BLE_DIAG0_LSB 0 +#define BLE_DIAG0_WIDTH ((uint32_t)0x00000006) + +#define BLE_DIAG3_EN_RST 0x0 +#define BLE_DIAG3_RST 0x0 +#define BLE_DIAG2_EN_RST 0x0 +#define BLE_DIAG2_RST 0x0 +#define BLE_DIAG1_EN_RST 0x0 +#define BLE_DIAG1_RST 0x0 +#define BLE_DIAG0_EN_RST 0x0 +#define BLE_DIAG0_RST 0x0 + +__INLINE void ble_diagcntl_pack(uint8_t diag3en, uint8_t diag3, uint8_t diag2en, uint8_t diag2, uint8_t diag1en, uint8_t diag1, uint8_t diag0en, uint8_t diag0) +{ + ASSERT_ERR((((uint32_t)diag3en << 31) & ~((uint32_t)0x80000000)) == 0); + ASSERT_ERR((((uint32_t)diag3 << 24) & ~((uint32_t)0x3F000000)) == 0); + ASSERT_ERR((((uint32_t)diag2en << 23) & ~((uint32_t)0x00800000)) == 0); + ASSERT_ERR((((uint32_t)diag2 << 16) & ~((uint32_t)0x003F0000)) == 0); + ASSERT_ERR((((uint32_t)diag1en << 15) & ~((uint32_t)0x00008000)) == 0); + ASSERT_ERR((((uint32_t)diag1 << 8) & ~((uint32_t)0x00003F00)) == 0); + ASSERT_ERR((((uint32_t)diag0en << 7) & ~((uint32_t)0x00000080)) == 0); + ASSERT_ERR((((uint32_t)diag0 << 0) & ~((uint32_t)0x0000003F)) == 0); + REG_BLE_WR(BLE_DIAGCNTL_ADDR, ((uint32_t)diag3en << 31) | ((uint32_t)diag3 << 24) | ((uint32_t)diag2en << 23) | ((uint32_t)diag2 << 16) | ((uint32_t)diag1en << 15) | ((uint32_t)diag1 << 8) | ((uint32_t)diag0en << 7) | ((uint32_t)diag0 << 0)); +} + +__INLINE void ble_diagcntl_unpack(uint8_t* diag3en, uint8_t* diag3, uint8_t* diag2en, uint8_t* diag2, uint8_t* diag1en, uint8_t* diag1, uint8_t* diag0en, uint8_t* diag0) +{ + uint32_t localVal = REG_BLE_RD(BLE_DIAGCNTL_ADDR); + + *diag3en = (localVal & ((uint32_t)0x80000000)) >> 31; + *diag3 = (localVal & ((uint32_t)0x3F000000)) >> 24; + *diag2en = (localVal & ((uint32_t)0x00800000)) >> 23; + *diag2 = (localVal & ((uint32_t)0x003F0000)) >> 16; + *diag1en = (localVal & ((uint32_t)0x00008000)) >> 15; + *diag1 = (localVal & ((uint32_t)0x00003F00)) >> 8; + *diag0en = (localVal & ((uint32_t)0x00000080)) >> 7; + *diag0 = (localVal & ((uint32_t)0x0000003F)) >> 0; +} + +__INLINE uint8_t ble_diag3_en_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DIAGCNTL_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +__INLINE void ble_diag3_en_setf(uint8_t diag3en) +{ + ASSERT_ERR((((uint32_t)diag3en << 31) & ~((uint32_t)0x80000000)) == 0); + REG_BLE_WR(BLE_DIAGCNTL_ADDR, (REG_BLE_RD(BLE_DIAGCNTL_ADDR) & ~((uint32_t)0x80000000)) | ((uint32_t)diag3en << 31)); +} + +__INLINE uint8_t ble_diag3_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DIAGCNTL_ADDR); + return ((localVal & ((uint32_t)0x3F000000)) >> 24); +} + +__INLINE void ble_diag3_setf(uint8_t diag3) +{ + ASSERT_ERR((((uint32_t)diag3 << 24) & ~((uint32_t)0x3F000000)) == 0); + REG_BLE_WR(BLE_DIAGCNTL_ADDR, (REG_BLE_RD(BLE_DIAGCNTL_ADDR) & ~((uint32_t)0x3F000000)) | ((uint32_t)diag3 << 24)); +} + +__INLINE uint8_t ble_diag2_en_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DIAGCNTL_ADDR); + return ((localVal & ((uint32_t)0x00800000)) >> 23); +} + +__INLINE void ble_diag2_en_setf(uint8_t diag2en) +{ + ASSERT_ERR((((uint32_t)diag2en << 23) & ~((uint32_t)0x00800000)) == 0); + REG_BLE_WR(BLE_DIAGCNTL_ADDR, (REG_BLE_RD(BLE_DIAGCNTL_ADDR) & ~((uint32_t)0x00800000)) | ((uint32_t)diag2en << 23)); +} + +__INLINE uint8_t ble_diag2_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DIAGCNTL_ADDR); + return ((localVal & ((uint32_t)0x003F0000)) >> 16); +} + +__INLINE void ble_diag2_setf(uint8_t diag2) +{ + ASSERT_ERR((((uint32_t)diag2 << 16) & ~((uint32_t)0x003F0000)) == 0); + REG_BLE_WR(BLE_DIAGCNTL_ADDR, (REG_BLE_RD(BLE_DIAGCNTL_ADDR) & ~((uint32_t)0x003F0000)) | ((uint32_t)diag2 << 16)); +} + +__INLINE uint8_t ble_diag1_en_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DIAGCNTL_ADDR); + return ((localVal & ((uint32_t)0x00008000)) >> 15); +} + +__INLINE void ble_diag1_en_setf(uint8_t diag1en) +{ + ASSERT_ERR((((uint32_t)diag1en << 15) & ~((uint32_t)0x00008000)) == 0); + REG_BLE_WR(BLE_DIAGCNTL_ADDR, (REG_BLE_RD(BLE_DIAGCNTL_ADDR) & ~((uint32_t)0x00008000)) | ((uint32_t)diag1en << 15)); +} + +__INLINE uint8_t ble_diag1_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DIAGCNTL_ADDR); + return ((localVal & ((uint32_t)0x00003F00)) >> 8); +} + +__INLINE void ble_diag1_setf(uint8_t diag1) +{ + ASSERT_ERR((((uint32_t)diag1 << 8) & ~((uint32_t)0x00003F00)) == 0); + REG_BLE_WR(BLE_DIAGCNTL_ADDR, (REG_BLE_RD(BLE_DIAGCNTL_ADDR) & ~((uint32_t)0x00003F00)) | ((uint32_t)diag1 << 8)); +} + +__INLINE uint8_t ble_diag0_en_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DIAGCNTL_ADDR); + return ((localVal & ((uint32_t)0x00000080)) >> 7); +} + +__INLINE void ble_diag0_en_setf(uint8_t diag0en) +{ + ASSERT_ERR((((uint32_t)diag0en << 7) & ~((uint32_t)0x00000080)) == 0); + REG_BLE_WR(BLE_DIAGCNTL_ADDR, (REG_BLE_RD(BLE_DIAGCNTL_ADDR) & ~((uint32_t)0x00000080)) | ((uint32_t)diag0en << 7)); +} + +__INLINE uint8_t ble_diag0_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DIAGCNTL_ADDR); + return ((localVal & ((uint32_t)0x0000003F)) >> 0); +} + +__INLINE void ble_diag0_setf(uint8_t diag0) +{ + ASSERT_ERR((((uint32_t)diag0 << 0) & ~((uint32_t)0x0000003F)) == 0); + REG_BLE_WR(BLE_DIAGCNTL_ADDR, (REG_BLE_RD(BLE_DIAGCNTL_ADDR) & ~((uint32_t)0x0000003F)) | ((uint32_t)diag0 << 0)); +} + +/** + * @brief DIAGSTAT register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:24            DIAG3STAT   0x0
+ *  23:16            DIAG2STAT   0x0
+ *  15:08            DIAG1STAT   0x0
+ *  07:00            DIAG0STAT   0x0
+ * 
+ */ +#define BLE_DIAGSTAT_ADDR 0x00810054 +#define BLE_DIAGSTAT_OFFSET 0x00000054 +#define BLE_DIAGSTAT_INDEX 0x00000015 +#define BLE_DIAGSTAT_RESET 0x00000000 + +__INLINE uint32_t ble_diagstat_get(void) +{ + return REG_BLE_RD(BLE_DIAGSTAT_ADDR); +} + +// field definitions +#define BLE_DIAG3STAT_MASK ((uint32_t)0xFF000000) +#define BLE_DIAG3STAT_LSB 24 +#define BLE_DIAG3STAT_WIDTH ((uint32_t)0x00000008) +#define BLE_DIAG2STAT_MASK ((uint32_t)0x00FF0000) +#define BLE_DIAG2STAT_LSB 16 +#define BLE_DIAG2STAT_WIDTH ((uint32_t)0x00000008) +#define BLE_DIAG1STAT_MASK ((uint32_t)0x0000FF00) +#define BLE_DIAG1STAT_LSB 8 +#define BLE_DIAG1STAT_WIDTH ((uint32_t)0x00000008) +#define BLE_DIAG0STAT_MASK ((uint32_t)0x000000FF) +#define BLE_DIAG0STAT_LSB 0 +#define BLE_DIAG0STAT_WIDTH ((uint32_t)0x00000008) + +#define BLE_DIAG3STAT_RST 0x0 +#define BLE_DIAG2STAT_RST 0x0 +#define BLE_DIAG1STAT_RST 0x0 +#define BLE_DIAG0STAT_RST 0x0 + +__INLINE void ble_diagstat_unpack(uint8_t* diag3stat, uint8_t* diag2stat, uint8_t* diag1stat, uint8_t* diag0stat) +{ + uint32_t localVal = REG_BLE_RD(BLE_DIAGSTAT_ADDR); + + *diag3stat = (localVal & ((uint32_t)0xFF000000)) >> 24; + *diag2stat = (localVal & ((uint32_t)0x00FF0000)) >> 16; + *diag1stat = (localVal & ((uint32_t)0x0000FF00)) >> 8; + *diag0stat = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +__INLINE uint8_t ble_diag3stat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DIAGSTAT_ADDR); + return ((localVal & ((uint32_t)0xFF000000)) >> 24); +} + +__INLINE uint8_t ble_diag2stat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DIAGSTAT_ADDR); + return ((localVal & ((uint32_t)0x00FF0000)) >> 16); +} + +__INLINE uint8_t ble_diag1stat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DIAGSTAT_ADDR); + return ((localVal & ((uint32_t)0x0000FF00)) >> 8); +} + +__INLINE uint8_t ble_diag0stat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DIAGSTAT_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +/** + * @brief DEBUGADDMAX register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:16           REG_ADDMAX   0x0
+ *  15:00            EM_ADDMAX   0x0
+ * 
+ */ +#define BLE_DEBUGADDMAX_ADDR 0x00810058 +#define BLE_DEBUGADDMAX_OFFSET 0x00000058 +#define BLE_DEBUGADDMAX_INDEX 0x00000016 +#define BLE_DEBUGADDMAX_RESET 0x00000000 + +__INLINE uint32_t ble_debugaddmax_get(void) +{ + return REG_BLE_RD(BLE_DEBUGADDMAX_ADDR); +} + +__INLINE void ble_debugaddmax_set(uint32_t value) +{ + REG_BLE_WR(BLE_DEBUGADDMAX_ADDR, value); +} + +// field definitions +#define BLE_REG_ADDMAX_MASK ((uint32_t)0xFFFF0000) +#define BLE_REG_ADDMAX_LSB 16 +#define BLE_REG_ADDMAX_WIDTH ((uint32_t)0x00000010) +#define BLE_EM_ADDMAX_MASK ((uint32_t)0x0000FFFF) +#define BLE_EM_ADDMAX_LSB 0 +#define BLE_EM_ADDMAX_WIDTH ((uint32_t)0x00000010) + +#define BLE_REG_ADDMAX_RST 0x0 +#define BLE_EM_ADDMAX_RST 0x0 + +__INLINE void ble_debugaddmax_pack(uint16_t regaddmax, uint16_t emaddmax) +{ + ASSERT_ERR((((uint32_t)regaddmax << 16) & ~((uint32_t)0xFFFF0000)) == 0); + ASSERT_ERR((((uint32_t)emaddmax << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_BLE_WR(BLE_DEBUGADDMAX_ADDR, ((uint32_t)regaddmax << 16) | ((uint32_t)emaddmax << 0)); +} + +__INLINE void ble_debugaddmax_unpack(uint16_t* regaddmax, uint16_t* emaddmax) +{ + uint32_t localVal = REG_BLE_RD(BLE_DEBUGADDMAX_ADDR); + + *regaddmax = (localVal & ((uint32_t)0xFFFF0000)) >> 16; + *emaddmax = (localVal & ((uint32_t)0x0000FFFF)) >> 0; +} + +__INLINE uint16_t ble_reg_addmax_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DEBUGADDMAX_ADDR); + return ((localVal & ((uint32_t)0xFFFF0000)) >> 16); +} + +__INLINE void ble_reg_addmax_setf(uint16_t regaddmax) +{ + ASSERT_ERR((((uint32_t)regaddmax << 16) & ~((uint32_t)0xFFFF0000)) == 0); + REG_BLE_WR(BLE_DEBUGADDMAX_ADDR, (REG_BLE_RD(BLE_DEBUGADDMAX_ADDR) & ~((uint32_t)0xFFFF0000)) | ((uint32_t)regaddmax << 16)); +} + +__INLINE uint16_t ble_em_addmax_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DEBUGADDMAX_ADDR); + return ((localVal & ((uint32_t)0x0000FFFF)) >> 0); +} + +__INLINE void ble_em_addmax_setf(uint16_t emaddmax) +{ + ASSERT_ERR((((uint32_t)emaddmax << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_BLE_WR(BLE_DEBUGADDMAX_ADDR, (REG_BLE_RD(BLE_DEBUGADDMAX_ADDR) & ~((uint32_t)0x0000FFFF)) | ((uint32_t)emaddmax << 0)); +} + +/** + * @brief DEBUGADDMIN register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:16           REG_ADDMIN   0x0
+ *  15:00            EM_ADDMIN   0x0
+ * 
+ */ +#define BLE_DEBUGADDMIN_ADDR 0x0081005C +#define BLE_DEBUGADDMIN_OFFSET 0x0000005C +#define BLE_DEBUGADDMIN_INDEX 0x00000017 +#define BLE_DEBUGADDMIN_RESET 0x00000000 + +__INLINE uint32_t ble_debugaddmin_get(void) +{ + return REG_BLE_RD(BLE_DEBUGADDMIN_ADDR); +} + +__INLINE void ble_debugaddmin_set(uint32_t value) +{ + REG_BLE_WR(BLE_DEBUGADDMIN_ADDR, value); +} + +// field definitions +#define BLE_REG_ADDMIN_MASK ((uint32_t)0xFFFF0000) +#define BLE_REG_ADDMIN_LSB 16 +#define BLE_REG_ADDMIN_WIDTH ((uint32_t)0x00000010) +#define BLE_EM_ADDMIN_MASK ((uint32_t)0x0000FFFF) +#define BLE_EM_ADDMIN_LSB 0 +#define BLE_EM_ADDMIN_WIDTH ((uint32_t)0x00000010) + +#define BLE_REG_ADDMIN_RST 0x0 +#define BLE_EM_ADDMIN_RST 0x0 + +__INLINE void ble_debugaddmin_pack(uint16_t regaddmin, uint16_t emaddmin) +{ + ASSERT_ERR((((uint32_t)regaddmin << 16) & ~((uint32_t)0xFFFF0000)) == 0); + ASSERT_ERR((((uint32_t)emaddmin << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_BLE_WR(BLE_DEBUGADDMIN_ADDR, ((uint32_t)regaddmin << 16) | ((uint32_t)emaddmin << 0)); +} + +__INLINE void ble_debugaddmin_unpack(uint16_t* regaddmin, uint16_t* emaddmin) +{ + uint32_t localVal = REG_BLE_RD(BLE_DEBUGADDMIN_ADDR); + + *regaddmin = (localVal & ((uint32_t)0xFFFF0000)) >> 16; + *emaddmin = (localVal & ((uint32_t)0x0000FFFF)) >> 0; +} + +__INLINE uint16_t ble_reg_addmin_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DEBUGADDMIN_ADDR); + return ((localVal & ((uint32_t)0xFFFF0000)) >> 16); +} + +__INLINE void ble_reg_addmin_setf(uint16_t regaddmin) +{ + ASSERT_ERR((((uint32_t)regaddmin << 16) & ~((uint32_t)0xFFFF0000)) == 0); + REG_BLE_WR(BLE_DEBUGADDMIN_ADDR, (REG_BLE_RD(BLE_DEBUGADDMIN_ADDR) & ~((uint32_t)0xFFFF0000)) | ((uint32_t)regaddmin << 16)); +} + +__INLINE uint16_t ble_em_addmin_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DEBUGADDMIN_ADDR); + return ((localVal & ((uint32_t)0x0000FFFF)) >> 0); +} + +__INLINE void ble_em_addmin_setf(uint16_t emaddmin) +{ + ASSERT_ERR((((uint32_t)emaddmin << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_BLE_WR(BLE_DEBUGADDMIN_ADDR, (REG_BLE_RD(BLE_DEBUGADDMIN_ADDR) & ~((uint32_t)0x0000FFFF)) | ((uint32_t)emaddmin << 0)); +} + +/** + * @brief ERRORTYPESTAT register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     19         RAL_UNDERRUN   0
+ *     18            RAL_ERROR   0
+ *     17     CONCEVTIRQ_ERROR   0
+ *     16     RXDATA_PTR_ERROR   0
+ *     15     TXDATA_PTR_ERROR   0
+ *     14   RXDESC_EMPTY_ERROR   0
+ *     13   TXDESC_EMPTY_ERROR   0
+ *     12       CSFORMAT_ERROR   0
+ *     11        LLCHMAP_ERROR   0
+ *     10         ADV_UNDERRUN   0
+ *     09         IFS_UNDERRUN   0
+ *     08      WHITELIST_ERROR   0
+ *     07   EVT_CNTL_APFM_ERROR   0
+ *     06   EVT_SCHDL_APFM_ERROR   0
+ *     05   EVT_SCHDL_ENTRY_ERROR   0
+ *     04   EVT_SCHDL_EMACC_ERROR   0
+ *     03    RADIO_EMACC_ERROR   0
+ *     02   PKTCNTL_EMACC_ERROR   0
+ *     01        RXCRYPT_ERROR   0
+ *     00        TXCRYPT_ERROR   0
+ * 
+ */ +#define BLE_ERRORTYPESTAT_ADDR 0x00810060 +#define BLE_ERRORTYPESTAT_OFFSET 0x00000060 +#define BLE_ERRORTYPESTAT_INDEX 0x00000018 +#define BLE_ERRORTYPESTAT_RESET 0x00000000 + +__INLINE uint32_t ble_errortypestat_get(void) +{ + return REG_BLE_RD(BLE_ERRORTYPESTAT_ADDR); +} + +// field definitions +#define BLE_RAL_UNDERRUN_BIT ((uint32_t)0x00080000) +#define BLE_RAL_UNDERRUN_POS 19 +#define BLE_RAL_ERROR_BIT ((uint32_t)0x00040000) +#define BLE_RAL_ERROR_POS 18 +#define BLE_CONCEVTIRQ_ERROR_BIT ((uint32_t)0x00020000) +#define BLE_CONCEVTIRQ_ERROR_POS 17 +#define BLE_RXDATA_PTR_ERROR_BIT ((uint32_t)0x00010000) +#define BLE_RXDATA_PTR_ERROR_POS 16 +#define BLE_TXDATA_PTR_ERROR_BIT ((uint32_t)0x00008000) +#define BLE_TXDATA_PTR_ERROR_POS 15 +#define BLE_RXDESC_EMPTY_ERROR_BIT ((uint32_t)0x00004000) +#define BLE_RXDESC_EMPTY_ERROR_POS 14 +#define BLE_TXDESC_EMPTY_ERROR_BIT ((uint32_t)0x00002000) +#define BLE_TXDESC_EMPTY_ERROR_POS 13 +#define BLE_CSFORMAT_ERROR_BIT ((uint32_t)0x00001000) +#define BLE_CSFORMAT_ERROR_POS 12 +#define BLE_LLCHMAP_ERROR_BIT ((uint32_t)0x00000800) +#define BLE_LLCHMAP_ERROR_POS 11 +#define BLE_ADV_UNDERRUN_BIT ((uint32_t)0x00000400) +#define BLE_ADV_UNDERRUN_POS 10 +#define BLE_IFS_UNDERRUN_BIT ((uint32_t)0x00000200) +#define BLE_IFS_UNDERRUN_POS 9 +#define BLE_WHITELIST_ERROR_BIT ((uint32_t)0x00000100) +#define BLE_WHITELIST_ERROR_POS 8 +#define BLE_EVT_CNTL_APFM_ERROR_BIT ((uint32_t)0x00000080) +#define BLE_EVT_CNTL_APFM_ERROR_POS 7 +#define BLE_EVT_SCHDL_APFM_ERROR_BIT ((uint32_t)0x00000040) +#define BLE_EVT_SCHDL_APFM_ERROR_POS 6 +#define BLE_EVT_SCHDL_ENTRY_ERROR_BIT ((uint32_t)0x00000020) +#define BLE_EVT_SCHDL_ENTRY_ERROR_POS 5 +#define BLE_EVT_SCHDL_EMACC_ERROR_BIT ((uint32_t)0x00000010) +#define BLE_EVT_SCHDL_EMACC_ERROR_POS 4 +#define BLE_RADIO_EMACC_ERROR_BIT ((uint32_t)0x00000008) +#define BLE_RADIO_EMACC_ERROR_POS 3 +#define BLE_PKTCNTL_EMACC_ERROR_BIT ((uint32_t)0x00000004) +#define BLE_PKTCNTL_EMACC_ERROR_POS 2 +#define BLE_RXCRYPT_ERROR_BIT ((uint32_t)0x00000002) +#define BLE_RXCRYPT_ERROR_POS 1 +#define BLE_TXCRYPT_ERROR_BIT ((uint32_t)0x00000001) +#define BLE_TXCRYPT_ERROR_POS 0 + +#define BLE_RAL_UNDERRUN_RST 0x0 +#define BLE_RAL_ERROR_RST 0x0 +#define BLE_CONCEVTIRQ_ERROR_RST 0x0 +#define BLE_RXDATA_PTR_ERROR_RST 0x0 +#define BLE_TXDATA_PTR_ERROR_RST 0x0 +#define BLE_RXDESC_EMPTY_ERROR_RST 0x0 +#define BLE_TXDESC_EMPTY_ERROR_RST 0x0 +#define BLE_CSFORMAT_ERROR_RST 0x0 +#define BLE_LLCHMAP_ERROR_RST 0x0 +#define BLE_ADV_UNDERRUN_RST 0x0 +#define BLE_IFS_UNDERRUN_RST 0x0 +#define BLE_WHITELIST_ERROR_RST 0x0 +#define BLE_EVT_CNTL_APFM_ERROR_RST 0x0 +#define BLE_EVT_SCHDL_APFM_ERROR_RST 0x0 +#define BLE_EVT_SCHDL_ENTRY_ERROR_RST 0x0 +#define BLE_EVT_SCHDL_EMACC_ERROR_RST 0x0 +#define BLE_RADIO_EMACC_ERROR_RST 0x0 +#define BLE_PKTCNTL_EMACC_ERROR_RST 0x0 +#define BLE_RXCRYPT_ERROR_RST 0x0 +#define BLE_TXCRYPT_ERROR_RST 0x0 + +__INLINE void ble_errortypestat_unpack(uint8_t* ralunderrun, uint8_t* ralerror, uint8_t* concevtirqerror, uint8_t* rxdataptrerror, uint8_t* txdataptrerror, uint8_t* rxdescemptyerror, uint8_t* txdescemptyerror, uint8_t* csformaterror, uint8_t* llchmaperror, uint8_t* advunderrun, uint8_t* ifsunderrun, uint8_t* whitelisterror, uint8_t* evtcntlapfmerror, uint8_t* evtschdlapfmerror, uint8_t* evtschdlentryerror, uint8_t* evtschdlemaccerror, uint8_t* radioemaccerror, uint8_t* pktcntlemaccerror, uint8_t* rxcrypterror, uint8_t* txcrypterror) +{ + uint32_t localVal = REG_BLE_RD(BLE_ERRORTYPESTAT_ADDR); + + *ralunderrun = (localVal & ((uint32_t)0x00080000)) >> 19; + *ralerror = (localVal & ((uint32_t)0x00040000)) >> 18; + *concevtirqerror = (localVal & ((uint32_t)0x00020000)) >> 17; + *rxdataptrerror = (localVal & ((uint32_t)0x00010000)) >> 16; + *txdataptrerror = (localVal & ((uint32_t)0x00008000)) >> 15; + *rxdescemptyerror = (localVal & ((uint32_t)0x00004000)) >> 14; + *txdescemptyerror = (localVal & ((uint32_t)0x00002000)) >> 13; + *csformaterror = (localVal & ((uint32_t)0x00001000)) >> 12; + *llchmaperror = (localVal & ((uint32_t)0x00000800)) >> 11; + *advunderrun = (localVal & ((uint32_t)0x00000400)) >> 10; + *ifsunderrun = (localVal & ((uint32_t)0x00000200)) >> 9; + *whitelisterror = (localVal & ((uint32_t)0x00000100)) >> 8; + *evtcntlapfmerror = (localVal & ((uint32_t)0x00000080)) >> 7; + *evtschdlapfmerror = (localVal & ((uint32_t)0x00000040)) >> 6; + *evtschdlentryerror = (localVal & ((uint32_t)0x00000020)) >> 5; + *evtschdlemaccerror = (localVal & ((uint32_t)0x00000010)) >> 4; + *radioemaccerror = (localVal & ((uint32_t)0x00000008)) >> 3; + *pktcntlemaccerror = (localVal & ((uint32_t)0x00000004)) >> 2; + *rxcrypterror = (localVal & ((uint32_t)0x00000002)) >> 1; + *txcrypterror = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +__INLINE uint8_t ble_ral_underrun_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ERRORTYPESTAT_ADDR); + return ((localVal & ((uint32_t)0x00080000)) >> 19); +} + +__INLINE uint8_t ble_ral_error_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ERRORTYPESTAT_ADDR); + return ((localVal & ((uint32_t)0x00040000)) >> 18); +} + +__INLINE uint8_t ble_concevtirq_error_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ERRORTYPESTAT_ADDR); + return ((localVal & ((uint32_t)0x00020000)) >> 17); +} + +__INLINE uint8_t ble_rxdata_ptr_error_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ERRORTYPESTAT_ADDR); + return ((localVal & ((uint32_t)0x00010000)) >> 16); +} + +__INLINE uint8_t ble_txdata_ptr_error_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ERRORTYPESTAT_ADDR); + return ((localVal & ((uint32_t)0x00008000)) >> 15); +} + +__INLINE uint8_t ble_rxdesc_empty_error_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ERRORTYPESTAT_ADDR); + return ((localVal & ((uint32_t)0x00004000)) >> 14); +} + +__INLINE uint8_t ble_txdesc_empty_error_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ERRORTYPESTAT_ADDR); + return ((localVal & ((uint32_t)0x00002000)) >> 13); +} + +__INLINE uint8_t ble_csformat_error_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ERRORTYPESTAT_ADDR); + return ((localVal & ((uint32_t)0x00001000)) >> 12); +} + +__INLINE uint8_t ble_llchmap_error_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ERRORTYPESTAT_ADDR); + return ((localVal & ((uint32_t)0x00000800)) >> 11); +} + +__INLINE uint8_t ble_adv_underrun_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ERRORTYPESTAT_ADDR); + return ((localVal & ((uint32_t)0x00000400)) >> 10); +} + +__INLINE uint8_t ble_ifs_underrun_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ERRORTYPESTAT_ADDR); + return ((localVal & ((uint32_t)0x00000200)) >> 9); +} + +__INLINE uint8_t ble_whitelist_error_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ERRORTYPESTAT_ADDR); + return ((localVal & ((uint32_t)0x00000100)) >> 8); +} + +__INLINE uint8_t ble_evt_cntl_apfm_error_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ERRORTYPESTAT_ADDR); + return ((localVal & ((uint32_t)0x00000080)) >> 7); +} + +__INLINE uint8_t ble_evt_schdl_apfm_error_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ERRORTYPESTAT_ADDR); + return ((localVal & ((uint32_t)0x00000040)) >> 6); +} + +__INLINE uint8_t ble_evt_schdl_entry_error_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ERRORTYPESTAT_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +__INLINE uint8_t ble_evt_schdl_emacc_error_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ERRORTYPESTAT_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +__INLINE uint8_t ble_radio_emacc_error_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ERRORTYPESTAT_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +__INLINE uint8_t ble_pktcntl_emacc_error_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ERRORTYPESTAT_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +__INLINE uint8_t ble_rxcrypt_error_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ERRORTYPESTAT_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +__INLINE uint8_t ble_txcrypt_error_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ERRORTYPESTAT_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/** + * @brief SWPROFILING register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31             SWPROF31   0
+ *     30             SWPROF30   0
+ *     29             SWPROF29   0
+ *     28             SWPROF28   0
+ *     27             SWPROF27   0
+ *     26             SWPROF26   0
+ *     25             SWPROF25   0
+ *     24             SWPROF24   0
+ *     23             SWPROF23   0
+ *     22             SWPROF22   0
+ *     21             SWPROF21   0
+ *     20             SWPROF20   0
+ *     19             SWPROF19   0
+ *     18             SWPROF18   0
+ *     17             SWPROF17   0
+ *     16             SWPROF16   0
+ *     15             SWPROF15   0
+ *     14             SWPROF14   0
+ *     13             SWPROF13   0
+ *     12             SWPROF12   0
+ *     11             SWPROF11   0
+ *     10             SWPROF10   0
+ *     09              SWPROF9   0
+ *     08              SWPROF8   0
+ *     07              SWPROF7   0
+ *     06              SWPROF6   0
+ *     05              SWPROF5   0
+ *     04              SWPROF4   0
+ *     03              SWPROF3   0
+ *     02              SWPROF2   0
+ *     01              SWPROF1   0
+ *     00              SWPROF0   0
+ * 
+ */ +#define BLE_SWPROFILING_ADDR 0x00810064 +#define BLE_SWPROFILING_OFFSET 0x00000064 +#define BLE_SWPROFILING_INDEX 0x00000019 +#define BLE_SWPROFILING_RESET 0x00000000 + +__INLINE uint32_t ble_swprofiling_get(void) +{ + return REG_BLE_RD(BLE_SWPROFILING_ADDR); +} + +__INLINE void ble_swprofiling_set(uint32_t value) +{ + REG_BLE_WR(BLE_SWPROFILING_ADDR, value); +} + +// field definitions +#define BLE_SWPROF31_BIT ((uint32_t)0x80000000) +#define BLE_SWPROF31_POS 31 +#define BLE_SWPROF30_BIT ((uint32_t)0x40000000) +#define BLE_SWPROF30_POS 30 +#define BLE_SWPROF29_BIT ((uint32_t)0x20000000) +#define BLE_SWPROF29_POS 29 +#define BLE_SWPROF28_BIT ((uint32_t)0x10000000) +#define BLE_SWPROF28_POS 28 +#define BLE_SWPROF27_BIT ((uint32_t)0x08000000) +#define BLE_SWPROF27_POS 27 +#define BLE_SWPROF26_BIT ((uint32_t)0x04000000) +#define BLE_SWPROF26_POS 26 +#define BLE_SWPROF25_BIT ((uint32_t)0x02000000) +#define BLE_SWPROF25_POS 25 +#define BLE_SWPROF24_BIT ((uint32_t)0x01000000) +#define BLE_SWPROF24_POS 24 +#define BLE_SWPROF23_BIT ((uint32_t)0x00800000) +#define BLE_SWPROF23_POS 23 +#define BLE_SWPROF22_BIT ((uint32_t)0x00400000) +#define BLE_SWPROF22_POS 22 +#define BLE_SWPROF21_BIT ((uint32_t)0x00200000) +#define BLE_SWPROF21_POS 21 +#define BLE_SWPROF20_BIT ((uint32_t)0x00100000) +#define BLE_SWPROF20_POS 20 +#define BLE_SWPROF19_BIT ((uint32_t)0x00080000) +#define BLE_SWPROF19_POS 19 +#define BLE_SWPROF18_BIT ((uint32_t)0x00040000) +#define BLE_SWPROF18_POS 18 +#define BLE_SWPROF17_BIT ((uint32_t)0x00020000) +#define BLE_SWPROF17_POS 17 +#define BLE_SWPROF16_BIT ((uint32_t)0x00010000) +#define BLE_SWPROF16_POS 16 +#define BLE_SWPROF15_BIT ((uint32_t)0x00008000) +#define BLE_SWPROF15_POS 15 +#define BLE_SWPROF14_BIT ((uint32_t)0x00004000) +#define BLE_SWPROF14_POS 14 +#define BLE_SWPROF13_BIT ((uint32_t)0x00002000) +#define BLE_SWPROF13_POS 13 +#define BLE_SWPROF12_BIT ((uint32_t)0x00001000) +#define BLE_SWPROF12_POS 12 +#define BLE_SWPROF11_BIT ((uint32_t)0x00000800) +#define BLE_SWPROF11_POS 11 +#define BLE_SWPROF10_BIT ((uint32_t)0x00000400) +#define BLE_SWPROF10_POS 10 +#define BLE_SWPROF9_BIT ((uint32_t)0x00000200) +#define BLE_SWPROF9_POS 9 +#define BLE_SWPROF8_BIT ((uint32_t)0x00000100) +#define BLE_SWPROF8_POS 8 +#define BLE_SWPROF7_BIT ((uint32_t)0x00000080) +#define BLE_SWPROF7_POS 7 +#define BLE_SWPROF6_BIT ((uint32_t)0x00000040) +#define BLE_SWPROF6_POS 6 +#define BLE_SWPROF5_BIT ((uint32_t)0x00000020) +#define BLE_SWPROF5_POS 5 +#define BLE_SWPROF4_BIT ((uint32_t)0x00000010) +#define BLE_SWPROF4_POS 4 +#define BLE_SWPROF3_BIT ((uint32_t)0x00000008) +#define BLE_SWPROF3_POS 3 +#define BLE_SWPROF2_BIT ((uint32_t)0x00000004) +#define BLE_SWPROF2_POS 2 +#define BLE_SWPROF1_BIT ((uint32_t)0x00000002) +#define BLE_SWPROF1_POS 1 +#define BLE_SWPROF0_BIT ((uint32_t)0x00000001) +#define BLE_SWPROF0_POS 0 + +#define BLE_SWPROF31_RST 0x0 +#define BLE_SWPROF30_RST 0x0 +#define BLE_SWPROF29_RST 0x0 +#define BLE_SWPROF28_RST 0x0 +#define BLE_SWPROF27_RST 0x0 +#define BLE_SWPROF26_RST 0x0 +#define BLE_SWPROF25_RST 0x0 +#define BLE_SWPROF24_RST 0x0 +#define BLE_SWPROF23_RST 0x0 +#define BLE_SWPROF22_RST 0x0 +#define BLE_SWPROF21_RST 0x0 +#define BLE_SWPROF20_RST 0x0 +#define BLE_SWPROF19_RST 0x0 +#define BLE_SWPROF18_RST 0x0 +#define BLE_SWPROF17_RST 0x0 +#define BLE_SWPROF16_RST 0x0 +#define BLE_SWPROF15_RST 0x0 +#define BLE_SWPROF14_RST 0x0 +#define BLE_SWPROF13_RST 0x0 +#define BLE_SWPROF12_RST 0x0 +#define BLE_SWPROF11_RST 0x0 +#define BLE_SWPROF10_RST 0x0 +#define BLE_SWPROF9_RST 0x0 +#define BLE_SWPROF8_RST 0x0 +#define BLE_SWPROF7_RST 0x0 +#define BLE_SWPROF6_RST 0x0 +#define BLE_SWPROF5_RST 0x0 +#define BLE_SWPROF4_RST 0x0 +#define BLE_SWPROF3_RST 0x0 +#define BLE_SWPROF2_RST 0x0 +#define BLE_SWPROF1_RST 0x0 +#define BLE_SWPROF0_RST 0x0 + +__INLINE void ble_swprofiling_pack(uint8_t swprof31, uint8_t swprof30, uint8_t swprof29, uint8_t swprof28, uint8_t swprof27, uint8_t swprof26, uint8_t swprof25, uint8_t swprof24, uint8_t swprof23, uint8_t swprof22, uint8_t swprof21, uint8_t swprof20, uint8_t swprof19, uint8_t swprof18, uint8_t swprof17, uint8_t swprof16, uint8_t swprof15, uint8_t swprof14, uint8_t swprof13, uint8_t swprof12, uint8_t swprof11, uint8_t swprof10, uint8_t swprof9, uint8_t swprof8, uint8_t swprof7, uint8_t swprof6, uint8_t swprof5, uint8_t swprof4, uint8_t swprof3, uint8_t swprof2, uint8_t swprof1, uint8_t swprof0) +{ + ASSERT_ERR((((uint32_t)swprof31 << 31) & ~((uint32_t)0x80000000)) == 0); + ASSERT_ERR((((uint32_t)swprof30 << 30) & ~((uint32_t)0x40000000)) == 0); + ASSERT_ERR((((uint32_t)swprof29 << 29) & ~((uint32_t)0x20000000)) == 0); + ASSERT_ERR((((uint32_t)swprof28 << 28) & ~((uint32_t)0x10000000)) == 0); + ASSERT_ERR((((uint32_t)swprof27 << 27) & ~((uint32_t)0x08000000)) == 0); + ASSERT_ERR((((uint32_t)swprof26 << 26) & ~((uint32_t)0x04000000)) == 0); + ASSERT_ERR((((uint32_t)swprof25 << 25) & ~((uint32_t)0x02000000)) == 0); + ASSERT_ERR((((uint32_t)swprof24 << 24) & ~((uint32_t)0x01000000)) == 0); + ASSERT_ERR((((uint32_t)swprof23 << 23) & ~((uint32_t)0x00800000)) == 0); + ASSERT_ERR((((uint32_t)swprof22 << 22) & ~((uint32_t)0x00400000)) == 0); + ASSERT_ERR((((uint32_t)swprof21 << 21) & ~((uint32_t)0x00200000)) == 0); + ASSERT_ERR((((uint32_t)swprof20 << 20) & ~((uint32_t)0x00100000)) == 0); + ASSERT_ERR((((uint32_t)swprof19 << 19) & ~((uint32_t)0x00080000)) == 0); + ASSERT_ERR((((uint32_t)swprof18 << 18) & ~((uint32_t)0x00040000)) == 0); + ASSERT_ERR((((uint32_t)swprof17 << 17) & ~((uint32_t)0x00020000)) == 0); + ASSERT_ERR((((uint32_t)swprof16 << 16) & ~((uint32_t)0x00010000)) == 0); + ASSERT_ERR((((uint32_t)swprof15 << 15) & ~((uint32_t)0x00008000)) == 0); + ASSERT_ERR((((uint32_t)swprof14 << 14) & ~((uint32_t)0x00004000)) == 0); + ASSERT_ERR((((uint32_t)swprof13 << 13) & ~((uint32_t)0x00002000)) == 0); + ASSERT_ERR((((uint32_t)swprof12 << 12) & ~((uint32_t)0x00001000)) == 0); + ASSERT_ERR((((uint32_t)swprof11 << 11) & ~((uint32_t)0x00000800)) == 0); + ASSERT_ERR((((uint32_t)swprof10 << 10) & ~((uint32_t)0x00000400)) == 0); + ASSERT_ERR((((uint32_t)swprof9 << 9) & ~((uint32_t)0x00000200)) == 0); + ASSERT_ERR((((uint32_t)swprof8 << 8) & ~((uint32_t)0x00000100)) == 0); + ASSERT_ERR((((uint32_t)swprof7 << 7) & ~((uint32_t)0x00000080)) == 0); + ASSERT_ERR((((uint32_t)swprof6 << 6) & ~((uint32_t)0x00000040)) == 0); + ASSERT_ERR((((uint32_t)swprof5 << 5) & ~((uint32_t)0x00000020)) == 0); + ASSERT_ERR((((uint32_t)swprof4 << 4) & ~((uint32_t)0x00000010)) == 0); + ASSERT_ERR((((uint32_t)swprof3 << 3) & ~((uint32_t)0x00000008)) == 0); + ASSERT_ERR((((uint32_t)swprof2 << 2) & ~((uint32_t)0x00000004)) == 0); + ASSERT_ERR((((uint32_t)swprof1 << 1) & ~((uint32_t)0x00000002)) == 0); + ASSERT_ERR((((uint32_t)swprof0 << 0) & ~((uint32_t)0x00000001)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, ((uint32_t)swprof31 << 31) | ((uint32_t)swprof30 << 30) | ((uint32_t)swprof29 << 29) | ((uint32_t)swprof28 << 28) | ((uint32_t)swprof27 << 27) | ((uint32_t)swprof26 << 26) | ((uint32_t)swprof25 << 25) | ((uint32_t)swprof24 << 24) | ((uint32_t)swprof23 << 23) | ((uint32_t)swprof22 << 22) | ((uint32_t)swprof21 << 21) | ((uint32_t)swprof20 << 20) | ((uint32_t)swprof19 << 19) | ((uint32_t)swprof18 << 18) | ((uint32_t)swprof17 << 17) | ((uint32_t)swprof16 << 16) | ((uint32_t)swprof15 << 15) | ((uint32_t)swprof14 << 14) | ((uint32_t)swprof13 << 13) | ((uint32_t)swprof12 << 12) | ((uint32_t)swprof11 << 11) | ((uint32_t)swprof10 << 10) | ((uint32_t)swprof9 << 9) | ((uint32_t)swprof8 << 8) | ((uint32_t)swprof7 << 7) | ((uint32_t)swprof6 << 6) | ((uint32_t)swprof5 << 5) | ((uint32_t)swprof4 << 4) | ((uint32_t)swprof3 << 3) | ((uint32_t)swprof2 << 2) | ((uint32_t)swprof1 << 1) | ((uint32_t)swprof0 << 0)); +} + +__INLINE void ble_swprofiling_unpack(uint8_t* swprof31, uint8_t* swprof30, uint8_t* swprof29, uint8_t* swprof28, uint8_t* swprof27, uint8_t* swprof26, uint8_t* swprof25, uint8_t* swprof24, uint8_t* swprof23, uint8_t* swprof22, uint8_t* swprof21, uint8_t* swprof20, uint8_t* swprof19, uint8_t* swprof18, uint8_t* swprof17, uint8_t* swprof16, uint8_t* swprof15, uint8_t* swprof14, uint8_t* swprof13, uint8_t* swprof12, uint8_t* swprof11, uint8_t* swprof10, uint8_t* swprof9, uint8_t* swprof8, uint8_t* swprof7, uint8_t* swprof6, uint8_t* swprof5, uint8_t* swprof4, uint8_t* swprof3, uint8_t* swprof2, uint8_t* swprof1, uint8_t* swprof0) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + + *swprof31 = (localVal & ((uint32_t)0x80000000)) >> 31; + *swprof30 = (localVal & ((uint32_t)0x40000000)) >> 30; + *swprof29 = (localVal & ((uint32_t)0x20000000)) >> 29; + *swprof28 = (localVal & ((uint32_t)0x10000000)) >> 28; + *swprof27 = (localVal & ((uint32_t)0x08000000)) >> 27; + *swprof26 = (localVal & ((uint32_t)0x04000000)) >> 26; + *swprof25 = (localVal & ((uint32_t)0x02000000)) >> 25; + *swprof24 = (localVal & ((uint32_t)0x01000000)) >> 24; + *swprof23 = (localVal & ((uint32_t)0x00800000)) >> 23; + *swprof22 = (localVal & ((uint32_t)0x00400000)) >> 22; + *swprof21 = (localVal & ((uint32_t)0x00200000)) >> 21; + *swprof20 = (localVal & ((uint32_t)0x00100000)) >> 20; + *swprof19 = (localVal & ((uint32_t)0x00080000)) >> 19; + *swprof18 = (localVal & ((uint32_t)0x00040000)) >> 18; + *swprof17 = (localVal & ((uint32_t)0x00020000)) >> 17; + *swprof16 = (localVal & ((uint32_t)0x00010000)) >> 16; + *swprof15 = (localVal & ((uint32_t)0x00008000)) >> 15; + *swprof14 = (localVal & ((uint32_t)0x00004000)) >> 14; + *swprof13 = (localVal & ((uint32_t)0x00002000)) >> 13; + *swprof12 = (localVal & ((uint32_t)0x00001000)) >> 12; + *swprof11 = (localVal & ((uint32_t)0x00000800)) >> 11; + *swprof10 = (localVal & ((uint32_t)0x00000400)) >> 10; + *swprof9 = (localVal & ((uint32_t)0x00000200)) >> 9; + *swprof8 = (localVal & ((uint32_t)0x00000100)) >> 8; + *swprof7 = (localVal & ((uint32_t)0x00000080)) >> 7; + *swprof6 = (localVal & ((uint32_t)0x00000040)) >> 6; + *swprof5 = (localVal & ((uint32_t)0x00000020)) >> 5; + *swprof4 = (localVal & ((uint32_t)0x00000010)) >> 4; + *swprof3 = (localVal & ((uint32_t)0x00000008)) >> 3; + *swprof2 = (localVal & ((uint32_t)0x00000004)) >> 2; + *swprof1 = (localVal & ((uint32_t)0x00000002)) >> 1; + *swprof0 = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +__INLINE uint8_t ble_swprof31_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +__INLINE void ble_swprof31_setf(uint8_t swprof31) +{ + ASSERT_ERR((((uint32_t)swprof31 << 31) & ~((uint32_t)0x80000000)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x80000000)) | ((uint32_t)swprof31 << 31)); +} + +__INLINE uint8_t ble_swprof30_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x40000000)) >> 30); +} + +__INLINE void ble_swprof30_setf(uint8_t swprof30) +{ + ASSERT_ERR((((uint32_t)swprof30 << 30) & ~((uint32_t)0x40000000)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x40000000)) | ((uint32_t)swprof30 << 30)); +} + +__INLINE uint8_t ble_swprof29_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x20000000)) >> 29); +} + +__INLINE void ble_swprof29_setf(uint8_t swprof29) +{ + ASSERT_ERR((((uint32_t)swprof29 << 29) & ~((uint32_t)0x20000000)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x20000000)) | ((uint32_t)swprof29 << 29)); +} + +__INLINE uint8_t ble_swprof28_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x10000000)) >> 28); +} + +__INLINE void ble_swprof28_setf(uint8_t swprof28) +{ + ASSERT_ERR((((uint32_t)swprof28 << 28) & ~((uint32_t)0x10000000)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x10000000)) | ((uint32_t)swprof28 << 28)); +} + +__INLINE uint8_t ble_swprof27_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x08000000)) >> 27); +} + +__INLINE void ble_swprof27_setf(uint8_t swprof27) +{ + ASSERT_ERR((((uint32_t)swprof27 << 27) & ~((uint32_t)0x08000000)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x08000000)) | ((uint32_t)swprof27 << 27)); +} + +__INLINE uint8_t ble_swprof26_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x04000000)) >> 26); +} + +__INLINE void ble_swprof26_setf(uint8_t swprof26) +{ + ASSERT_ERR((((uint32_t)swprof26 << 26) & ~((uint32_t)0x04000000)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x04000000)) | ((uint32_t)swprof26 << 26)); +} + +__INLINE uint8_t ble_swprof25_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x02000000)) >> 25); +} + +__INLINE void ble_swprof25_setf(uint8_t swprof25) +{ + ASSERT_ERR((((uint32_t)swprof25 << 25) & ~((uint32_t)0x02000000)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x02000000)) | ((uint32_t)swprof25 << 25)); +} + +__INLINE uint8_t ble_swprof24_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x01000000)) >> 24); +} + +__INLINE void ble_swprof24_setf(uint8_t swprof24) +{ + ASSERT_ERR((((uint32_t)swprof24 << 24) & ~((uint32_t)0x01000000)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x01000000)) | ((uint32_t)swprof24 << 24)); +} + +__INLINE uint8_t ble_swprof23_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00800000)) >> 23); +} + +__INLINE void ble_swprof23_setf(uint8_t swprof23) +{ + ASSERT_ERR((((uint32_t)swprof23 << 23) & ~((uint32_t)0x00800000)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x00800000)) | ((uint32_t)swprof23 << 23)); +} + +__INLINE uint8_t ble_swprof22_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00400000)) >> 22); +} + +__INLINE void ble_swprof22_setf(uint8_t swprof22) +{ + ASSERT_ERR((((uint32_t)swprof22 << 22) & ~((uint32_t)0x00400000)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x00400000)) | ((uint32_t)swprof22 << 22)); +} + +__INLINE uint8_t ble_swprof21_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00200000)) >> 21); +} + +__INLINE void ble_swprof21_setf(uint8_t swprof21) +{ + ASSERT_ERR((((uint32_t)swprof21 << 21) & ~((uint32_t)0x00200000)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x00200000)) | ((uint32_t)swprof21 << 21)); +} + +__INLINE uint8_t ble_swprof20_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00100000)) >> 20); +} + +__INLINE void ble_swprof20_setf(uint8_t swprof20) +{ + ASSERT_ERR((((uint32_t)swprof20 << 20) & ~((uint32_t)0x00100000)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x00100000)) | ((uint32_t)swprof20 << 20)); +} + +__INLINE uint8_t ble_swprof19_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00080000)) >> 19); +} + +__INLINE void ble_swprof19_setf(uint8_t swprof19) +{ + ASSERT_ERR((((uint32_t)swprof19 << 19) & ~((uint32_t)0x00080000)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x00080000)) | ((uint32_t)swprof19 << 19)); +} + +__INLINE uint8_t ble_swprof18_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00040000)) >> 18); +} + +__INLINE void ble_swprof18_setf(uint8_t swprof18) +{ + ASSERT_ERR((((uint32_t)swprof18 << 18) & ~((uint32_t)0x00040000)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x00040000)) | ((uint32_t)swprof18 << 18)); +} + +__INLINE uint8_t ble_swprof17_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00020000)) >> 17); +} + +__INLINE void ble_swprof17_setf(uint8_t swprof17) +{ + ASSERT_ERR((((uint32_t)swprof17 << 17) & ~((uint32_t)0x00020000)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x00020000)) | ((uint32_t)swprof17 << 17)); +} + +__INLINE uint8_t ble_swprof16_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00010000)) >> 16); +} + +__INLINE void ble_swprof16_setf(uint8_t swprof16) +{ + ASSERT_ERR((((uint32_t)swprof16 << 16) & ~((uint32_t)0x00010000)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x00010000)) | ((uint32_t)swprof16 << 16)); +} + +__INLINE uint8_t ble_swprof15_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00008000)) >> 15); +} + +__INLINE void ble_swprof15_setf(uint8_t swprof15) +{ + ASSERT_ERR((((uint32_t)swprof15 << 15) & ~((uint32_t)0x00008000)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x00008000)) | ((uint32_t)swprof15 << 15)); +} + +__INLINE uint8_t ble_swprof14_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00004000)) >> 14); +} + +__INLINE void ble_swprof14_setf(uint8_t swprof14) +{ + ASSERT_ERR((((uint32_t)swprof14 << 14) & ~((uint32_t)0x00004000)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x00004000)) | ((uint32_t)swprof14 << 14)); +} + +__INLINE uint8_t ble_swprof13_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00002000)) >> 13); +} + +__INLINE void ble_swprof13_setf(uint8_t swprof13) +{ + ASSERT_ERR((((uint32_t)swprof13 << 13) & ~((uint32_t)0x00002000)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x00002000)) | ((uint32_t)swprof13 << 13)); +} + +__INLINE uint8_t ble_swprof12_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00001000)) >> 12); +} + +__INLINE void ble_swprof12_setf(uint8_t swprof12) +{ + ASSERT_ERR((((uint32_t)swprof12 << 12) & ~((uint32_t)0x00001000)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x00001000)) | ((uint32_t)swprof12 << 12)); +} + +__INLINE uint8_t ble_swprof11_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000800)) >> 11); +} + +__INLINE void ble_swprof11_setf(uint8_t swprof11) +{ + ASSERT_ERR((((uint32_t)swprof11 << 11) & ~((uint32_t)0x00000800)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x00000800)) | ((uint32_t)swprof11 << 11)); +} + +__INLINE uint8_t ble_swprof10_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000400)) >> 10); +} + +__INLINE void ble_swprof10_setf(uint8_t swprof10) +{ + ASSERT_ERR((((uint32_t)swprof10 << 10) & ~((uint32_t)0x00000400)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x00000400)) | ((uint32_t)swprof10 << 10)); +} + +__INLINE uint8_t ble_swprof9_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000200)) >> 9); +} + +__INLINE void ble_swprof9_setf(uint8_t swprof9) +{ + ASSERT_ERR((((uint32_t)swprof9 << 9) & ~((uint32_t)0x00000200)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x00000200)) | ((uint32_t)swprof9 << 9)); +} + +__INLINE uint8_t ble_swprof8_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000100)) >> 8); +} + +__INLINE void ble_swprof8_setf(uint8_t swprof8) +{ + ASSERT_ERR((((uint32_t)swprof8 << 8) & ~((uint32_t)0x00000100)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x00000100)) | ((uint32_t)swprof8 << 8)); +} + +__INLINE uint8_t ble_swprof7_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000080)) >> 7); +} + +__INLINE void ble_swprof7_setf(uint8_t swprof7) +{ + ASSERT_ERR((((uint32_t)swprof7 << 7) & ~((uint32_t)0x00000080)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x00000080)) | ((uint32_t)swprof7 << 7)); +} + +__INLINE uint8_t ble_swprof6_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000040)) >> 6); +} + +__INLINE void ble_swprof6_setf(uint8_t swprof6) +{ + ASSERT_ERR((((uint32_t)swprof6 << 6) & ~((uint32_t)0x00000040)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x00000040)) | ((uint32_t)swprof6 << 6)); +} + +__INLINE uint8_t ble_swprof5_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +__INLINE void ble_swprof5_setf(uint8_t swprof5) +{ + ASSERT_ERR((((uint32_t)swprof5 << 5) & ~((uint32_t)0x00000020)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x00000020)) | ((uint32_t)swprof5 << 5)); +} + +__INLINE uint8_t ble_swprof4_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +__INLINE void ble_swprof4_setf(uint8_t swprof4) +{ + ASSERT_ERR((((uint32_t)swprof4 << 4) & ~((uint32_t)0x00000010)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x00000010)) | ((uint32_t)swprof4 << 4)); +} + +__INLINE uint8_t ble_swprof3_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +__INLINE void ble_swprof3_setf(uint8_t swprof3) +{ + ASSERT_ERR((((uint32_t)swprof3 << 3) & ~((uint32_t)0x00000008)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x00000008)) | ((uint32_t)swprof3 << 3)); +} + +__INLINE uint8_t ble_swprof2_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +__INLINE void ble_swprof2_setf(uint8_t swprof2) +{ + ASSERT_ERR((((uint32_t)swprof2 << 2) & ~((uint32_t)0x00000004)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x00000004)) | ((uint32_t)swprof2 << 2)); +} + +__INLINE uint8_t ble_swprof1_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +__INLINE void ble_swprof1_setf(uint8_t swprof1) +{ + ASSERT_ERR((((uint32_t)swprof1 << 1) & ~((uint32_t)0x00000002)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x00000002)) | ((uint32_t)swprof1 << 1)); +} + +__INLINE uint8_t ble_swprof0_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +__INLINE void ble_swprof0_setf(uint8_t swprof0) +{ + ASSERT_ERR((((uint32_t)swprof0 << 0) & ~((uint32_t)0x00000001)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x00000001)) | ((uint32_t)swprof0 << 0)); +} + +/** + * @brief RADIOCNTL0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:16               SPIPTR   0x0
+ *  05:04              SPIFREQ   0x0
+ *     01              SPICOMP   1
+ *     00                SPIGO   0
+ * 
+ */ +#define BLE_RADIOCNTL0_ADDR 0x00810070 +#define BLE_RADIOCNTL0_OFFSET 0x00000070 +#define BLE_RADIOCNTL0_INDEX 0x0000001C +#define BLE_RADIOCNTL0_RESET 0x00000002 + +__INLINE uint32_t ble_radiocntl0_get(void) +{ + return REG_BLE_RD(BLE_RADIOCNTL0_ADDR); +} + +__INLINE void ble_radiocntl0_set(uint32_t value) +{ + REG_BLE_WR(BLE_RADIOCNTL0_ADDR, value); +} + +// field definitions +#define BLE_SPIPTR_MASK ((uint32_t)0xFFFF0000) +#define BLE_SPIPTR_LSB 16 +#define BLE_SPIPTR_WIDTH ((uint32_t)0x00000010) +#define BLE_SPIFREQ_MASK ((uint32_t)0x00000030) +#define BLE_SPIFREQ_LSB 4 +#define BLE_SPIFREQ_WIDTH ((uint32_t)0x00000002) +#define BLE_SPICOMP_BIT ((uint32_t)0x00000002) +#define BLE_SPICOMP_POS 1 +#define BLE_SPIGO_BIT ((uint32_t)0x00000001) +#define BLE_SPIGO_POS 0 + +#define BLE_SPIPTR_RST 0x0 +#define BLE_SPIFREQ_RST 0x0 +#define BLE_SPICOMP_RST 0x1 +#define BLE_SPIGO_RST 0x0 + +__INLINE void ble_radiocntl0_pack(uint16_t spiptr, uint8_t spifreq, uint8_t spigo) +{ + ASSERT_ERR((((uint32_t)spiptr << 16) & ~((uint32_t)0xFFFF0000)) == 0); + ASSERT_ERR((((uint32_t)spifreq << 4) & ~((uint32_t)0x00000030)) == 0); + ASSERT_ERR((((uint32_t)spigo << 0) & ~((uint32_t)0x00000001)) == 0); + REG_BLE_WR(BLE_RADIOCNTL0_ADDR, ((uint32_t)spiptr << 16) | ((uint32_t)spifreq << 4) | ((uint32_t)spigo << 0)); +} + +__INLINE void ble_radiocntl0_unpack(uint16_t* spiptr, uint8_t* spifreq, uint8_t* spicomp, uint8_t* spigo) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL0_ADDR); + + *spiptr = (localVal & ((uint32_t)0xFFFF0000)) >> 16; + *spifreq = (localVal & ((uint32_t)0x00000030)) >> 4; + *spicomp = (localVal & ((uint32_t)0x00000002)) >> 1; + *spigo = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +__INLINE uint16_t ble_spiptr_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL0_ADDR); + return ((localVal & ((uint32_t)0xFFFF0000)) >> 16); +} + +__INLINE void ble_spiptr_setf(uint16_t spiptr) +{ + ASSERT_ERR((((uint32_t)spiptr << 16) & ~((uint32_t)0xFFFF0000)) == 0); + REG_BLE_WR(BLE_RADIOCNTL0_ADDR, (REG_BLE_RD(BLE_RADIOCNTL0_ADDR) & ~((uint32_t)0xFFFF0000)) | ((uint32_t)spiptr << 16)); +} + +__INLINE uint8_t ble_spifreq_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL0_ADDR); + return ((localVal & ((uint32_t)0x00000030)) >> 4); +} + +__INLINE void ble_spifreq_setf(uint8_t spifreq) +{ + ASSERT_ERR((((uint32_t)spifreq << 4) & ~((uint32_t)0x00000030)) == 0); + REG_BLE_WR(BLE_RADIOCNTL0_ADDR, (REG_BLE_RD(BLE_RADIOCNTL0_ADDR) & ~((uint32_t)0x00000030)) | ((uint32_t)spifreq << 4)); +} + +__INLINE uint8_t ble_spicomp_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL0_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +__INLINE uint8_t ble_spigo_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL0_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +__INLINE void ble_spigo_setf(uint8_t spigo) +{ + ASSERT_ERR((((uint32_t)spigo << 0) & ~((uint32_t)0x00000001)) == 0); + REG_BLE_WR(BLE_RADIOCNTL0_ADDR, (REG_BLE_RD(BLE_RADIOCNTL0_ADDR) & ~((uint32_t)0x00000001)) | ((uint32_t)spigo << 0)); +} + +/** + * @brief RADIOCNTL1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31          FORCEAGC_EN   0
+ *     30           FORCEBLEIQ   0
+ *  27:16      FORCEAGC_LENGTH   0x0
+ *     15      SYNC_PULSE_MODE   0
+ *     13            DPCORR_EN   0
+ *     12           JEF_SELECT   0
+ *  08:04               XRFSEL   0x0
+ *  03:00           SUBVERSION   0x0
+ * 
+ */ +#define BLE_RADIOCNTL1_ADDR 0x00810074 +#define BLE_RADIOCNTL1_OFFSET 0x00000074 +#define BLE_RADIOCNTL1_INDEX 0x0000001D +#define BLE_RADIOCNTL1_RESET 0x00000000 + +__INLINE uint32_t ble_radiocntl1_get(void) +{ + return REG_BLE_RD(BLE_RADIOCNTL1_ADDR); +} + +__INLINE void ble_radiocntl1_set(uint32_t value) +{ + REG_BLE_WR(BLE_RADIOCNTL1_ADDR, value); +} + +// field definitions +#define BLE_FORCEAGC_EN_BIT ((uint32_t)0x80000000) +#define BLE_FORCEAGC_EN_POS 31 +#define BLE_FORCEBLEIQ_BIT ((uint32_t)0x40000000) +#define BLE_FORCEBLEIQ_POS 30 +#define BLE_FORCEAGC_LENGTH_MASK ((uint32_t)0x0FFF0000) +#define BLE_FORCEAGC_LENGTH_LSB 16 +#define BLE_FORCEAGC_LENGTH_WIDTH ((uint32_t)0x0000000C) +#define BLE_SYNC_PULSE_MODE_BIT ((uint32_t)0x00008000) +#define BLE_SYNC_PULSE_MODE_POS 15 +#define BLE_DPCORR_EN_BIT ((uint32_t)0x00002000) +#define BLE_DPCORR_EN_POS 13 +#define BLE_JEF_SELECT_BIT ((uint32_t)0x00001000) +#define BLE_JEF_SELECT_POS 12 +#define BLE_XRFSEL_MASK ((uint32_t)0x000001F0) +#define BLE_XRFSEL_LSB 4 +#define BLE_XRFSEL_WIDTH ((uint32_t)0x00000005) +#define BLE_SUBVERSION_MASK ((uint32_t)0x0000000F) +#define BLE_SUBVERSION_LSB 0 +#define BLE_SUBVERSION_WIDTH ((uint32_t)0x00000004) + +#define BLE_FORCEAGC_EN_RST 0x0 +#define BLE_FORCEBLEIQ_RST 0x0 +#define BLE_FORCEAGC_LENGTH_RST 0x0 +#define BLE_SYNC_PULSE_MODE_RST 0x0 +#define BLE_DPCORR_EN_RST 0x0 +#define BLE_JEF_SELECT_RST 0x0 +#define BLE_XRFSEL_RST 0x0 +#define BLE_SUBVERSION_RST 0x0 + +__INLINE void ble_radiocntl1_pack(uint8_t forceagcen, uint8_t forcebleiq, uint16_t forceagclength, uint8_t syncpulsemode, uint8_t dpcorren, uint8_t jefselect, uint8_t xrfsel, uint8_t subversion) +{ + ASSERT_ERR((((uint32_t)forceagcen << 31) & ~((uint32_t)0x80000000)) == 0); + ASSERT_ERR((((uint32_t)forcebleiq << 30) & ~((uint32_t)0x40000000)) == 0); + ASSERT_ERR((((uint32_t)forceagclength << 16) & ~((uint32_t)0x0FFF0000)) == 0); + ASSERT_ERR((((uint32_t)syncpulsemode << 15) & ~((uint32_t)0x00008000)) == 0); + ASSERT_ERR((((uint32_t)dpcorren << 13) & ~((uint32_t)0x00002000)) == 0); + ASSERT_ERR((((uint32_t)jefselect << 12) & ~((uint32_t)0x00001000)) == 0); + ASSERT_ERR((((uint32_t)xrfsel << 4) & ~((uint32_t)0x000001F0)) == 0); + ASSERT_ERR((((uint32_t)subversion << 0) & ~((uint32_t)0x0000000F)) == 0); + REG_BLE_WR(BLE_RADIOCNTL1_ADDR, ((uint32_t)forceagcen << 31) | ((uint32_t)forcebleiq << 30) | ((uint32_t)forceagclength << 16) | ((uint32_t)syncpulsemode << 15) | ((uint32_t)dpcorren << 13) | ((uint32_t)jefselect << 12) | ((uint32_t)xrfsel << 4) | ((uint32_t)subversion << 0)); +} + +__INLINE void ble_radiocntl1_unpack(uint8_t* forceagcen, uint8_t* forcebleiq, uint16_t* forceagclength, uint8_t* syncpulsemode, uint8_t* dpcorren, uint8_t* jefselect, uint8_t* xrfsel, uint8_t* subversion) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL1_ADDR); + + *forceagcen = (localVal & ((uint32_t)0x80000000)) >> 31; + *forcebleiq = (localVal & ((uint32_t)0x40000000)) >> 30; + *forceagclength = (localVal & ((uint32_t)0x0FFF0000)) >> 16; + *syncpulsemode = (localVal & ((uint32_t)0x00008000)) >> 15; + *dpcorren = (localVal & ((uint32_t)0x00002000)) >> 13; + *jefselect = (localVal & ((uint32_t)0x00001000)) >> 12; + *xrfsel = (localVal & ((uint32_t)0x000001F0)) >> 4; + *subversion = (localVal & ((uint32_t)0x0000000F)) >> 0; +} + +__INLINE uint8_t ble_forceagc_en_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL1_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +__INLINE void ble_forceagc_en_setf(uint8_t forceagcen) +{ + ASSERT_ERR((((uint32_t)forceagcen << 31) & ~((uint32_t)0x80000000)) == 0); + REG_BLE_WR(BLE_RADIOCNTL1_ADDR, (REG_BLE_RD(BLE_RADIOCNTL1_ADDR) & ~((uint32_t)0x80000000)) | ((uint32_t)forceagcen << 31)); +} + +__INLINE uint8_t ble_forcebleiq_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL1_ADDR); + return ((localVal & ((uint32_t)0x40000000)) >> 30); +} + +__INLINE void ble_forcebleiq_setf(uint8_t forcebleiq) +{ + ASSERT_ERR((((uint32_t)forcebleiq << 30) & ~((uint32_t)0x40000000)) == 0); + REG_BLE_WR(BLE_RADIOCNTL1_ADDR, (REG_BLE_RD(BLE_RADIOCNTL1_ADDR) & ~((uint32_t)0x40000000)) | ((uint32_t)forcebleiq << 30)); +} + +__INLINE uint16_t ble_forceagc_length_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL1_ADDR); + return ((localVal & ((uint32_t)0x0FFF0000)) >> 16); +} + +__INLINE void ble_forceagc_length_setf(uint16_t forceagclength) +{ + ASSERT_ERR((((uint32_t)forceagclength << 16) & ~((uint32_t)0x0FFF0000)) == 0); + REG_BLE_WR(BLE_RADIOCNTL1_ADDR, (REG_BLE_RD(BLE_RADIOCNTL1_ADDR) & ~((uint32_t)0x0FFF0000)) | ((uint32_t)forceagclength << 16)); +} + +__INLINE uint8_t ble_sync_pulse_mode_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL1_ADDR); + return ((localVal & ((uint32_t)0x00008000)) >> 15); +} + +__INLINE void ble_sync_pulse_mode_setf(uint8_t syncpulsemode) +{ + ASSERT_ERR((((uint32_t)syncpulsemode << 15) & ~((uint32_t)0x00008000)) == 0); + REG_BLE_WR(BLE_RADIOCNTL1_ADDR, (REG_BLE_RD(BLE_RADIOCNTL1_ADDR) & ~((uint32_t)0x00008000)) | ((uint32_t)syncpulsemode << 15)); +} + +__INLINE uint8_t ble_dpcorr_en_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL1_ADDR); + return ((localVal & ((uint32_t)0x00002000)) >> 13); +} + +__INLINE void ble_dpcorr_en_setf(uint8_t dpcorren) +{ + ASSERT_ERR((((uint32_t)dpcorren << 13) & ~((uint32_t)0x00002000)) == 0); + REG_BLE_WR(BLE_RADIOCNTL1_ADDR, (REG_BLE_RD(BLE_RADIOCNTL1_ADDR) & ~((uint32_t)0x00002000)) | ((uint32_t)dpcorren << 13)); +} + +__INLINE uint8_t ble_jef_select_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL1_ADDR); + return ((localVal & ((uint32_t)0x00001000)) >> 12); +} + +__INLINE void ble_jef_select_setf(uint8_t jefselect) +{ + ASSERT_ERR((((uint32_t)jefselect << 12) & ~((uint32_t)0x00001000)) == 0); + REG_BLE_WR(BLE_RADIOCNTL1_ADDR, (REG_BLE_RD(BLE_RADIOCNTL1_ADDR) & ~((uint32_t)0x00001000)) | ((uint32_t)jefselect << 12)); +} + +__INLINE uint8_t ble_xrfsel_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL1_ADDR); + return ((localVal & ((uint32_t)0x000001F0)) >> 4); +} + +__INLINE void ble_xrfsel_setf(uint8_t xrfsel) +{ + ASSERT_ERR((((uint32_t)xrfsel << 4) & ~((uint32_t)0x000001F0)) == 0); + REG_BLE_WR(BLE_RADIOCNTL1_ADDR, (REG_BLE_RD(BLE_RADIOCNTL1_ADDR) & ~((uint32_t)0x000001F0)) | ((uint32_t)xrfsel << 4)); +} + +__INLINE uint8_t ble_subversion_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL1_ADDR); + return ((localVal & ((uint32_t)0x0000000F)) >> 0); +} + +__INLINE void ble_subversion_setf(uint8_t subversion) +{ + ASSERT_ERR((((uint32_t)subversion << 0) & ~((uint32_t)0x0000000F)) == 0); + REG_BLE_WR(BLE_RADIOCNTL1_ADDR, (REG_BLE_RD(BLE_RADIOCNTL1_ADDR) & ~((uint32_t)0x0000000F)) | ((uint32_t)subversion << 0)); +} + +/** + * @brief RADIOCNTL2 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00        FREQTABLE_PTR   0x40
+ * 
+ */ +#define BLE_RADIOCNTL2_ADDR 0x00810078 +#define BLE_RADIOCNTL2_OFFSET 0x00000078 +#define BLE_RADIOCNTL2_INDEX 0x0000001E +#define BLE_RADIOCNTL2_RESET 0x00000040 + +__INLINE uint32_t ble_radiocntl2_get(void) +{ + return REG_BLE_RD(BLE_RADIOCNTL2_ADDR); +} + +__INLINE void ble_radiocntl2_set(uint32_t value) +{ + REG_BLE_WR(BLE_RADIOCNTL2_ADDR, value); +} + +// field definitions +#define BLE_FREQTABLE_PTR_MASK ((uint32_t)0x0000FFFF) +#define BLE_FREQTABLE_PTR_LSB 0 +#define BLE_FREQTABLE_PTR_WIDTH ((uint32_t)0x00000010) + +#define BLE_FREQTABLE_PTR_RST 0x40 + +__INLINE uint16_t ble_freqtable_ptr_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL2_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_freqtable_ptr_setf(uint16_t freqtableptr) +{ + ASSERT_ERR((((uint32_t)freqtableptr << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_BLE_WR(BLE_RADIOCNTL2_ADDR, (uint32_t)freqtableptr << 0); +} + +/** + * @brief RADIOCNTL3 register definition + */ +#define BLE_RADIOCNTL3_ADDR 0x0081007C +#define BLE_RADIOCNTL3_OFFSET 0x0000007C +#define BLE_RADIOCNTL3_INDEX 0x0000001F +#define BLE_RADIOCNTL3_RESET 0x00000000 + +__INLINE uint32_t ble_radiocntl3_get(void) +{ + return REG_BLE_RD(BLE_RADIOCNTL3_ADDR); +} + +__INLINE void ble_radiocntl3_set(uint32_t value) +{ + REG_BLE_WR(BLE_RADIOCNTL3_ADDR, value); +} + +/** + * @brief RADIOPWRUPDN0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  23:16             RXPWRUP0   0x0
+ *  12:08             TXPWRDN0   0x0
+ *  07:00             TXPWRUP0   0x0
+ * 
+ */ +#define BLE_RADIOPWRUPDN0_ADDR 0x00810080 +#define BLE_RADIOPWRUPDN0_OFFSET 0x00000080 +#define BLE_RADIOPWRUPDN0_INDEX 0x00000020 +#define BLE_RADIOPWRUPDN0_RESET 0x00000000 + +__INLINE uint32_t ble_radiopwrupdn0_get(void) +{ + return REG_BLE_RD(BLE_RADIOPWRUPDN0_ADDR); +} + +__INLINE void ble_radiopwrupdn0_set(uint32_t value) +{ + REG_BLE_WR(BLE_RADIOPWRUPDN0_ADDR, value); +} + +// field definitions +#define BLE_RXPWRUP0_MASK ((uint32_t)0x00FF0000) +#define BLE_RXPWRUP0_LSB 16 +#define BLE_RXPWRUP0_WIDTH ((uint32_t)0x00000008) +#define BLE_TXPWRDN0_MASK ((uint32_t)0x00001F00) +#define BLE_TXPWRDN0_LSB 8 +#define BLE_TXPWRDN0_WIDTH ((uint32_t)0x00000005) +#define BLE_TXPWRUP0_MASK ((uint32_t)0x000000FF) +#define BLE_TXPWRUP0_LSB 0 +#define BLE_TXPWRUP0_WIDTH ((uint32_t)0x00000008) + +#define BLE_RXPWRUP0_RST 0x0 +#define BLE_TXPWRDN0_RST 0x0 +#define BLE_TXPWRUP0_RST 0x0 + +__INLINE void ble_radiopwrupdn0_pack(uint8_t rxpwrup0, uint8_t txpwrdn0, uint8_t txpwrup0) +{ + ASSERT_ERR((((uint32_t)rxpwrup0 << 16) & ~((uint32_t)0x00FF0000)) == 0); + ASSERT_ERR((((uint32_t)txpwrdn0 << 8) & ~((uint32_t)0x00001F00)) == 0); + ASSERT_ERR((((uint32_t)txpwrup0 << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_BLE_WR(BLE_RADIOPWRUPDN0_ADDR, ((uint32_t)rxpwrup0 << 16) | ((uint32_t)txpwrdn0 << 8) | ((uint32_t)txpwrup0 << 0)); +} + +__INLINE void ble_radiopwrupdn0_unpack(uint8_t* rxpwrup0, uint8_t* txpwrdn0, uint8_t* txpwrup0) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOPWRUPDN0_ADDR); + + *rxpwrup0 = (localVal & ((uint32_t)0x00FF0000)) >> 16; + *txpwrdn0 = (localVal & ((uint32_t)0x00001F00)) >> 8; + *txpwrup0 = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +__INLINE uint8_t ble_rxpwrup0_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOPWRUPDN0_ADDR); + return ((localVal & ((uint32_t)0x00FF0000)) >> 16); +} + +__INLINE void ble_rxpwrup0_setf(uint8_t rxpwrup0) +{ + ASSERT_ERR((((uint32_t)rxpwrup0 << 16) & ~((uint32_t)0x00FF0000)) == 0); + REG_BLE_WR(BLE_RADIOPWRUPDN0_ADDR, (REG_BLE_RD(BLE_RADIOPWRUPDN0_ADDR) & ~((uint32_t)0x00FF0000)) | ((uint32_t)rxpwrup0 << 16)); +} + +__INLINE uint8_t ble_txpwrdn0_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOPWRUPDN0_ADDR); + return ((localVal & ((uint32_t)0x00001F00)) >> 8); +} + +__INLINE void ble_txpwrdn0_setf(uint8_t txpwrdn0) +{ + ASSERT_ERR((((uint32_t)txpwrdn0 << 8) & ~((uint32_t)0x00001F00)) == 0); + REG_BLE_WR(BLE_RADIOPWRUPDN0_ADDR, (REG_BLE_RD(BLE_RADIOPWRUPDN0_ADDR) & ~((uint32_t)0x00001F00)) | ((uint32_t)txpwrdn0 << 8)); +} + +__INLINE uint8_t ble_txpwrup0_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOPWRUPDN0_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +__INLINE void ble_txpwrup0_setf(uint8_t txpwrup0) +{ + ASSERT_ERR((((uint32_t)txpwrup0 << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_BLE_WR(BLE_RADIOPWRUPDN0_ADDR, (REG_BLE_RD(BLE_RADIOPWRUPDN0_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)txpwrup0 << 0)); +} + +/** + * @brief RADIOPWRUPDN1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  23:16             RXPWRUP1   0x0
+ *  12:08             TXPWRDN1   0x0
+ *  07:00             TXPWRUP1   0x0
+ * 
+ */ +#define BLE_RADIOPWRUPDN1_ADDR 0x00810084 +#define BLE_RADIOPWRUPDN1_OFFSET 0x00000084 +#define BLE_RADIOPWRUPDN1_INDEX 0x00000021 +#define BLE_RADIOPWRUPDN1_RESET 0x00000000 + +__INLINE uint32_t ble_radiopwrupdn1_get(void) +{ + return REG_BLE_RD(BLE_RADIOPWRUPDN1_ADDR); +} + +__INLINE void ble_radiopwrupdn1_set(uint32_t value) +{ + REG_BLE_WR(BLE_RADIOPWRUPDN1_ADDR, value); +} + +// field definitions +#define BLE_RXPWRUP1_MASK ((uint32_t)0x00FF0000) +#define BLE_RXPWRUP1_LSB 16 +#define BLE_RXPWRUP1_WIDTH ((uint32_t)0x00000008) +#define BLE_TXPWRDN1_MASK ((uint32_t)0x00001F00) +#define BLE_TXPWRDN1_LSB 8 +#define BLE_TXPWRDN1_WIDTH ((uint32_t)0x00000005) +#define BLE_TXPWRUP1_MASK ((uint32_t)0x000000FF) +#define BLE_TXPWRUP1_LSB 0 +#define BLE_TXPWRUP1_WIDTH ((uint32_t)0x00000008) + +#define BLE_RXPWRUP1_RST 0x0 +#define BLE_TXPWRDN1_RST 0x0 +#define BLE_TXPWRUP1_RST 0x0 + +__INLINE void ble_radiopwrupdn1_pack(uint8_t rxpwrup1, uint8_t txpwrdn1, uint8_t txpwrup1) +{ + ASSERT_ERR((((uint32_t)rxpwrup1 << 16) & ~((uint32_t)0x00FF0000)) == 0); + ASSERT_ERR((((uint32_t)txpwrdn1 << 8) & ~((uint32_t)0x00001F00)) == 0); + ASSERT_ERR((((uint32_t)txpwrup1 << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_BLE_WR(BLE_RADIOPWRUPDN1_ADDR, ((uint32_t)rxpwrup1 << 16) | ((uint32_t)txpwrdn1 << 8) | ((uint32_t)txpwrup1 << 0)); +} + +__INLINE void ble_radiopwrupdn1_unpack(uint8_t* rxpwrup1, uint8_t* txpwrdn1, uint8_t* txpwrup1) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOPWRUPDN1_ADDR); + + *rxpwrup1 = (localVal & ((uint32_t)0x00FF0000)) >> 16; + *txpwrdn1 = (localVal & ((uint32_t)0x00001F00)) >> 8; + *txpwrup1 = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +__INLINE uint8_t ble_rxpwrup1_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOPWRUPDN1_ADDR); + return ((localVal & ((uint32_t)0x00FF0000)) >> 16); +} + +__INLINE void ble_rxpwrup1_setf(uint8_t rxpwrup1) +{ + ASSERT_ERR((((uint32_t)rxpwrup1 << 16) & ~((uint32_t)0x00FF0000)) == 0); + REG_BLE_WR(BLE_RADIOPWRUPDN1_ADDR, (REG_BLE_RD(BLE_RADIOPWRUPDN1_ADDR) & ~((uint32_t)0x00FF0000)) | ((uint32_t)rxpwrup1 << 16)); +} + +__INLINE uint8_t ble_txpwrdn1_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOPWRUPDN1_ADDR); + return ((localVal & ((uint32_t)0x00001F00)) >> 8); +} + +__INLINE void ble_txpwrdn1_setf(uint8_t txpwrdn1) +{ + ASSERT_ERR((((uint32_t)txpwrdn1 << 8) & ~((uint32_t)0x00001F00)) == 0); + REG_BLE_WR(BLE_RADIOPWRUPDN1_ADDR, (REG_BLE_RD(BLE_RADIOPWRUPDN1_ADDR) & ~((uint32_t)0x00001F00)) | ((uint32_t)txpwrdn1 << 8)); +} + +__INLINE uint8_t ble_txpwrup1_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOPWRUPDN1_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +__INLINE void ble_txpwrup1_setf(uint8_t txpwrup1) +{ + ASSERT_ERR((((uint32_t)txpwrup1 << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_BLE_WR(BLE_RADIOPWRUPDN1_ADDR, (REG_BLE_RD(BLE_RADIOPWRUPDN1_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)txpwrup1 << 0)); +} + +/** + * @brief RADIOPWRUPDN2 register definition + */ +#define BLE_RADIOPWRUPDN2_ADDR 0x00810088 +#define BLE_RADIOPWRUPDN2_OFFSET 0x00000088 +#define BLE_RADIOPWRUPDN2_INDEX 0x00000022 +#define BLE_RADIOPWRUPDN2_RESET 0x00000000 + +__INLINE uint32_t ble_radiopwrupdn2_get(void) +{ + return REG_BLE_RD(BLE_RADIOPWRUPDN2_ADDR); +} + +__INLINE void ble_radiopwrupdn2_set(uint32_t value) +{ + REG_BLE_WR(BLE_RADIOPWRUPDN2_ADDR, value); +} + +/** + * @brief RADIOPWRUPDN3 register definition + */ +#define BLE_RADIOPWRUPDN3_ADDR 0x0081008C +#define BLE_RADIOPWRUPDN3_OFFSET 0x0000008C +#define BLE_RADIOPWRUPDN3_INDEX 0x00000023 +#define BLE_RADIOPWRUPDN3_RESET 0x00000000 + +__INLINE uint32_t ble_radiopwrupdn3_get(void) +{ + return REG_BLE_RD(BLE_RADIOPWRUPDN3_ADDR); +} + +__INLINE void ble_radiopwrupdn3_set(uint32_t value) +{ + REG_BLE_WR(BLE_RADIOPWRUPDN3_ADDR, value); +} + +/** + * @brief RADIOTXRXTIM0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:24       SYNC_POSITION0   0x0
+ *  20:16            RFRXTMDA0   0x0
+ *  14:08           RXPATHDLY0   0x0
+ *  06:00           TXPATHDLY0   0x0
+ * 
+ */ +#define BLE_RADIOTXRXTIM0_ADDR 0x00810090 +#define BLE_RADIOTXRXTIM0_OFFSET 0x00000090 +#define BLE_RADIOTXRXTIM0_INDEX 0x00000024 +#define BLE_RADIOTXRXTIM0_RESET 0x00000000 + +__INLINE uint32_t ble_radiotxrxtim0_get(void) +{ + return REG_BLE_RD(BLE_RADIOTXRXTIM0_ADDR); +} + +__INLINE void ble_radiotxrxtim0_set(uint32_t value) +{ + REG_BLE_WR(BLE_RADIOTXRXTIM0_ADDR, value); +} + +// field definitions +#define BLE_SYNC_POSITION0_MASK ((uint32_t)0xFF000000) +#define BLE_SYNC_POSITION0_LSB 24 +#define BLE_SYNC_POSITION0_WIDTH ((uint32_t)0x00000008) +#define BLE_RFRXTMDA0_MASK ((uint32_t)0x001F0000) +#define BLE_RFRXTMDA0_LSB 16 +#define BLE_RFRXTMDA0_WIDTH ((uint32_t)0x00000005) +#define BLE_RXPATHDLY0_MASK ((uint32_t)0x00007F00) +#define BLE_RXPATHDLY0_LSB 8 +#define BLE_RXPATHDLY0_WIDTH ((uint32_t)0x00000007) +#define BLE_TXPATHDLY0_MASK ((uint32_t)0x0000007F) +#define BLE_TXPATHDLY0_LSB 0 +#define BLE_TXPATHDLY0_WIDTH ((uint32_t)0x00000007) + +#define BLE_SYNC_POSITION0_RST 0x0 +#define BLE_RFRXTMDA0_RST 0x0 +#define BLE_RXPATHDLY0_RST 0x0 +#define BLE_TXPATHDLY0_RST 0x0 + +__INLINE void ble_radiotxrxtim0_pack(uint8_t syncposition0, uint8_t rfrxtmda0, uint8_t rxpathdly0, uint8_t txpathdly0) +{ + ASSERT_ERR((((uint32_t)syncposition0 << 24) & ~((uint32_t)0xFF000000)) == 0); + ASSERT_ERR((((uint32_t)rfrxtmda0 << 16) & ~((uint32_t)0x001F0000)) == 0); + ASSERT_ERR((((uint32_t)rxpathdly0 << 8) & ~((uint32_t)0x00007F00)) == 0); + ASSERT_ERR((((uint32_t)txpathdly0 << 0) & ~((uint32_t)0x0000007F)) == 0); + REG_BLE_WR(BLE_RADIOTXRXTIM0_ADDR, ((uint32_t)syncposition0 << 24) | ((uint32_t)rfrxtmda0 << 16) | ((uint32_t)rxpathdly0 << 8) | ((uint32_t)txpathdly0 << 0)); +} + +__INLINE void ble_radiotxrxtim0_unpack(uint8_t* syncposition0, uint8_t* rfrxtmda0, uint8_t* rxpathdly0, uint8_t* txpathdly0) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOTXRXTIM0_ADDR); + + *syncposition0 = (localVal & ((uint32_t)0xFF000000)) >> 24; + *rfrxtmda0 = (localVal & ((uint32_t)0x001F0000)) >> 16; + *rxpathdly0 = (localVal & ((uint32_t)0x00007F00)) >> 8; + *txpathdly0 = (localVal & ((uint32_t)0x0000007F)) >> 0; +} + +__INLINE uint8_t ble_sync_position0_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOTXRXTIM0_ADDR); + return ((localVal & ((uint32_t)0xFF000000)) >> 24); +} + +__INLINE void ble_sync_position0_setf(uint8_t syncposition0) +{ + ASSERT_ERR((((uint32_t)syncposition0 << 24) & ~((uint32_t)0xFF000000)) == 0); + REG_BLE_WR(BLE_RADIOTXRXTIM0_ADDR, (REG_BLE_RD(BLE_RADIOTXRXTIM0_ADDR) & ~((uint32_t)0xFF000000)) | ((uint32_t)syncposition0 << 24)); +} + +__INLINE uint8_t ble_rfrxtmda0_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOTXRXTIM0_ADDR); + return ((localVal & ((uint32_t)0x001F0000)) >> 16); +} + +__INLINE void ble_rfrxtmda0_setf(uint8_t rfrxtmda0) +{ + ASSERT_ERR((((uint32_t)rfrxtmda0 << 16) & ~((uint32_t)0x001F0000)) == 0); + REG_BLE_WR(BLE_RADIOTXRXTIM0_ADDR, (REG_BLE_RD(BLE_RADIOTXRXTIM0_ADDR) & ~((uint32_t)0x001F0000)) | ((uint32_t)rfrxtmda0 << 16)); +} + +__INLINE uint8_t ble_rxpathdly0_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOTXRXTIM0_ADDR); + return ((localVal & ((uint32_t)0x00007F00)) >> 8); +} + +__INLINE void ble_rxpathdly0_setf(uint8_t rxpathdly0) +{ + ASSERT_ERR((((uint32_t)rxpathdly0 << 8) & ~((uint32_t)0x00007F00)) == 0); + REG_BLE_WR(BLE_RADIOTXRXTIM0_ADDR, (REG_BLE_RD(BLE_RADIOTXRXTIM0_ADDR) & ~((uint32_t)0x00007F00)) | ((uint32_t)rxpathdly0 << 8)); +} + +__INLINE uint8_t ble_txpathdly0_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOTXRXTIM0_ADDR); + return ((localVal & ((uint32_t)0x0000007F)) >> 0); +} + +__INLINE void ble_txpathdly0_setf(uint8_t txpathdly0) +{ + ASSERT_ERR((((uint32_t)txpathdly0 << 0) & ~((uint32_t)0x0000007F)) == 0); + REG_BLE_WR(BLE_RADIOTXRXTIM0_ADDR, (REG_BLE_RD(BLE_RADIOTXRXTIM0_ADDR) & ~((uint32_t)0x0000007F)) | ((uint32_t)txpathdly0 << 0)); +} + +/** + * @brief RADIOTXRXTIM1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:24       SYNC_POSITION1   0x0
+ *  20:16            RFRXTMDA1   0x0
+ *  14:08           RXPATHDLY1   0x0
+ *  06:00           TXPATHDLY1   0x0
+ * 
+ */ +#define BLE_RADIOTXRXTIM1_ADDR 0x00810094 +#define BLE_RADIOTXRXTIM1_OFFSET 0x00000094 +#define BLE_RADIOTXRXTIM1_INDEX 0x00000025 +#define BLE_RADIOTXRXTIM1_RESET 0x00000000 + +__INLINE uint32_t ble_radiotxrxtim1_get(void) +{ + return REG_BLE_RD(BLE_RADIOTXRXTIM1_ADDR); +} + +__INLINE void ble_radiotxrxtim1_set(uint32_t value) +{ + REG_BLE_WR(BLE_RADIOTXRXTIM1_ADDR, value); +} + +// field definitions +#define BLE_SYNC_POSITION1_MASK ((uint32_t)0xFF000000) +#define BLE_SYNC_POSITION1_LSB 24 +#define BLE_SYNC_POSITION1_WIDTH ((uint32_t)0x00000008) +#define BLE_RFRXTMDA1_MASK ((uint32_t)0x001F0000) +#define BLE_RFRXTMDA1_LSB 16 +#define BLE_RFRXTMDA1_WIDTH ((uint32_t)0x00000005) +#define BLE_RXPATHDLY1_MASK ((uint32_t)0x00007F00) +#define BLE_RXPATHDLY1_LSB 8 +#define BLE_RXPATHDLY1_WIDTH ((uint32_t)0x00000007) +#define BLE_TXPATHDLY1_MASK ((uint32_t)0x0000007F) +#define BLE_TXPATHDLY1_LSB 0 +#define BLE_TXPATHDLY1_WIDTH ((uint32_t)0x00000007) + +#define BLE_SYNC_POSITION1_RST 0x0 +#define BLE_RFRXTMDA1_RST 0x0 +#define BLE_RXPATHDLY1_RST 0x0 +#define BLE_TXPATHDLY1_RST 0x0 + +__INLINE void ble_radiotxrxtim1_pack(uint8_t syncposition1, uint8_t rfrxtmda1, uint8_t rxpathdly1, uint8_t txpathdly1) +{ + ASSERT_ERR((((uint32_t)syncposition1 << 24) & ~((uint32_t)0xFF000000)) == 0); + ASSERT_ERR((((uint32_t)rfrxtmda1 << 16) & ~((uint32_t)0x001F0000)) == 0); + ASSERT_ERR((((uint32_t)rxpathdly1 << 8) & ~((uint32_t)0x00007F00)) == 0); + ASSERT_ERR((((uint32_t)txpathdly1 << 0) & ~((uint32_t)0x0000007F)) == 0); + REG_BLE_WR(BLE_RADIOTXRXTIM1_ADDR, ((uint32_t)syncposition1 << 24) | ((uint32_t)rfrxtmda1 << 16) | ((uint32_t)rxpathdly1 << 8) | ((uint32_t)txpathdly1 << 0)); +} + +__INLINE void ble_radiotxrxtim1_unpack(uint8_t* syncposition1, uint8_t* rfrxtmda1, uint8_t* rxpathdly1, uint8_t* txpathdly1) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOTXRXTIM1_ADDR); + + *syncposition1 = (localVal & ((uint32_t)0xFF000000)) >> 24; + *rfrxtmda1 = (localVal & ((uint32_t)0x001F0000)) >> 16; + *rxpathdly1 = (localVal & ((uint32_t)0x00007F00)) >> 8; + *txpathdly1 = (localVal & ((uint32_t)0x0000007F)) >> 0; +} + +__INLINE uint8_t ble_sync_position1_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOTXRXTIM1_ADDR); + return ((localVal & ((uint32_t)0xFF000000)) >> 24); +} + +__INLINE void ble_sync_position1_setf(uint8_t syncposition1) +{ + ASSERT_ERR((((uint32_t)syncposition1 << 24) & ~((uint32_t)0xFF000000)) == 0); + REG_BLE_WR(BLE_RADIOTXRXTIM1_ADDR, (REG_BLE_RD(BLE_RADIOTXRXTIM1_ADDR) & ~((uint32_t)0xFF000000)) | ((uint32_t)syncposition1 << 24)); +} + +__INLINE uint8_t ble_rfrxtmda1_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOTXRXTIM1_ADDR); + return ((localVal & ((uint32_t)0x001F0000)) >> 16); +} + +__INLINE void ble_rfrxtmda1_setf(uint8_t rfrxtmda1) +{ + ASSERT_ERR((((uint32_t)rfrxtmda1 << 16) & ~((uint32_t)0x001F0000)) == 0); + REG_BLE_WR(BLE_RADIOTXRXTIM1_ADDR, (REG_BLE_RD(BLE_RADIOTXRXTIM1_ADDR) & ~((uint32_t)0x001F0000)) | ((uint32_t)rfrxtmda1 << 16)); +} + +__INLINE uint8_t ble_rxpathdly1_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOTXRXTIM1_ADDR); + return ((localVal & ((uint32_t)0x00007F00)) >> 8); +} + +__INLINE void ble_rxpathdly1_setf(uint8_t rxpathdly1) +{ + ASSERT_ERR((((uint32_t)rxpathdly1 << 8) & ~((uint32_t)0x00007F00)) == 0); + REG_BLE_WR(BLE_RADIOTXRXTIM1_ADDR, (REG_BLE_RD(BLE_RADIOTXRXTIM1_ADDR) & ~((uint32_t)0x00007F00)) | ((uint32_t)rxpathdly1 << 8)); +} + +__INLINE uint8_t ble_txpathdly1_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOTXRXTIM1_ADDR); + return ((localVal & ((uint32_t)0x0000007F)) >> 0); +} + +__INLINE void ble_txpathdly1_setf(uint8_t txpathdly1) +{ + ASSERT_ERR((((uint32_t)txpathdly1 << 0) & ~((uint32_t)0x0000007F)) == 0); + REG_BLE_WR(BLE_RADIOTXRXTIM1_ADDR, (REG_BLE_RD(BLE_RADIOTXRXTIM1_ADDR) & ~((uint32_t)0x0000007F)) | ((uint32_t)txpathdly1 << 0)); +} + +/** + * @brief RADIOTXRXTIM2 register definition + */ +#define BLE_RADIOTXRXTIM2_ADDR 0x00810098 +#define BLE_RADIOTXRXTIM2_OFFSET 0x00000098 +#define BLE_RADIOTXRXTIM2_INDEX 0x00000026 +#define BLE_RADIOTXRXTIM2_RESET 0x00000000 + +__INLINE uint32_t ble_radiotxrxtim2_get(void) +{ + return REG_BLE_RD(BLE_RADIOTXRXTIM2_ADDR); +} + +__INLINE void ble_radiotxrxtim2_set(uint32_t value) +{ + REG_BLE_WR(BLE_RADIOTXRXTIM2_ADDR, value); +} + +/** + * @brief RADIOTXRXTIM3 register definition + */ +#define BLE_RADIOTXRXTIM3_ADDR 0x0081009C +#define BLE_RADIOTXRXTIM3_OFFSET 0x0000009C +#define BLE_RADIOTXRXTIM3_INDEX 0x00000027 +#define BLE_RADIOTXRXTIM3_RESET 0x00000000 + +__INLINE uint32_t ble_radiotxrxtim3_get(void) +{ + return REG_BLE_RD(BLE_RADIOTXRXTIM3_ADDR); +} + +__INLINE void ble_radiotxrxtim3_set(uint32_t value) +{ + REG_BLE_WR(BLE_RADIOTXRXTIM3_ADDR, value); +} + +/** + * @brief SPIPTRCNTL0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:16             TXOFFPTR   0x0
+ *  15:00              TXONPTR   0x0
+ * 
+ */ +#define BLE_SPIPTRCNTL0_ADDR 0x008100A0 +#define BLE_SPIPTRCNTL0_OFFSET 0x000000A0 +#define BLE_SPIPTRCNTL0_INDEX 0x00000028 +#define BLE_SPIPTRCNTL0_RESET 0x00000000 + +__INLINE uint32_t ble_spiptrcntl0_get(void) +{ + return REG_BLE_RD(BLE_SPIPTRCNTL0_ADDR); +} + +__INLINE void ble_spiptrcntl0_set(uint32_t value) +{ + REG_BLE_WR(BLE_SPIPTRCNTL0_ADDR, value); +} + +// field definitions +#define BLE_TXOFFPTR_MASK ((uint32_t)0xFFFF0000) +#define BLE_TXOFFPTR_LSB 16 +#define BLE_TXOFFPTR_WIDTH ((uint32_t)0x00000010) +#define BLE_TXONPTR_MASK ((uint32_t)0x0000FFFF) +#define BLE_TXONPTR_LSB 0 +#define BLE_TXONPTR_WIDTH ((uint32_t)0x00000010) + +#define BLE_TXOFFPTR_RST 0x0 +#define BLE_TXONPTR_RST 0x0 + +__INLINE void ble_spiptrcntl0_pack(uint16_t txoffptr, uint16_t txonptr) +{ + ASSERT_ERR((((uint32_t)txoffptr << 16) & ~((uint32_t)0xFFFF0000)) == 0); + ASSERT_ERR((((uint32_t)txonptr << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_BLE_WR(BLE_SPIPTRCNTL0_ADDR, ((uint32_t)txoffptr << 16) | ((uint32_t)txonptr << 0)); +} + +__INLINE void ble_spiptrcntl0_unpack(uint16_t* txoffptr, uint16_t* txonptr) +{ + uint32_t localVal = REG_BLE_RD(BLE_SPIPTRCNTL0_ADDR); + + *txoffptr = (localVal & ((uint32_t)0xFFFF0000)) >> 16; + *txonptr = (localVal & ((uint32_t)0x0000FFFF)) >> 0; +} + +__INLINE uint16_t ble_txoffptr_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SPIPTRCNTL0_ADDR); + return ((localVal & ((uint32_t)0xFFFF0000)) >> 16); +} + +__INLINE void ble_txoffptr_setf(uint16_t txoffptr) +{ + ASSERT_ERR((((uint32_t)txoffptr << 16) & ~((uint32_t)0xFFFF0000)) == 0); + REG_BLE_WR(BLE_SPIPTRCNTL0_ADDR, (REG_BLE_RD(BLE_SPIPTRCNTL0_ADDR) & ~((uint32_t)0xFFFF0000)) | ((uint32_t)txoffptr << 16)); +} + +__INLINE uint16_t ble_txonptr_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SPIPTRCNTL0_ADDR); + return ((localVal & ((uint32_t)0x0000FFFF)) >> 0); +} + +__INLINE void ble_txonptr_setf(uint16_t txonptr) +{ + ASSERT_ERR((((uint32_t)txonptr << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_BLE_WR(BLE_SPIPTRCNTL0_ADDR, (REG_BLE_RD(BLE_SPIPTRCNTL0_ADDR) & ~((uint32_t)0x0000FFFF)) | ((uint32_t)txonptr << 0)); +} + +/** + * @brief SPIPTRCNTL1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:16             RXOFFPTR   0x0
+ *  15:00              RXONPTR   0x0
+ * 
+ */ +#define BLE_SPIPTRCNTL1_ADDR 0x008100A4 +#define BLE_SPIPTRCNTL1_OFFSET 0x000000A4 +#define BLE_SPIPTRCNTL1_INDEX 0x00000029 +#define BLE_SPIPTRCNTL1_RESET 0x00000000 + +__INLINE uint32_t ble_spiptrcntl1_get(void) +{ + return REG_BLE_RD(BLE_SPIPTRCNTL1_ADDR); +} + +__INLINE void ble_spiptrcntl1_set(uint32_t value) +{ + REG_BLE_WR(BLE_SPIPTRCNTL1_ADDR, value); +} + +// field definitions +#define BLE_RXOFFPTR_MASK ((uint32_t)0xFFFF0000) +#define BLE_RXOFFPTR_LSB 16 +#define BLE_RXOFFPTR_WIDTH ((uint32_t)0x00000010) +#define BLE_RXONPTR_MASK ((uint32_t)0x0000FFFF) +#define BLE_RXONPTR_LSB 0 +#define BLE_RXONPTR_WIDTH ((uint32_t)0x00000010) + +#define BLE_RXOFFPTR_RST 0x0 +#define BLE_RXONPTR_RST 0x0 + +__INLINE void ble_spiptrcntl1_pack(uint16_t rxoffptr, uint16_t rxonptr) +{ + ASSERT_ERR((((uint32_t)rxoffptr << 16) & ~((uint32_t)0xFFFF0000)) == 0); + ASSERT_ERR((((uint32_t)rxonptr << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_BLE_WR(BLE_SPIPTRCNTL1_ADDR, ((uint32_t)rxoffptr << 16) | ((uint32_t)rxonptr << 0)); +} + +__INLINE void ble_spiptrcntl1_unpack(uint16_t* rxoffptr, uint16_t* rxonptr) +{ + uint32_t localVal = REG_BLE_RD(BLE_SPIPTRCNTL1_ADDR); + + *rxoffptr = (localVal & ((uint32_t)0xFFFF0000)) >> 16; + *rxonptr = (localVal & ((uint32_t)0x0000FFFF)) >> 0; +} + +__INLINE uint16_t ble_rxoffptr_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SPIPTRCNTL1_ADDR); + return ((localVal & ((uint32_t)0xFFFF0000)) >> 16); +} + +__INLINE void ble_rxoffptr_setf(uint16_t rxoffptr) +{ + ASSERT_ERR((((uint32_t)rxoffptr << 16) & ~((uint32_t)0xFFFF0000)) == 0); + REG_BLE_WR(BLE_SPIPTRCNTL1_ADDR, (REG_BLE_RD(BLE_SPIPTRCNTL1_ADDR) & ~((uint32_t)0xFFFF0000)) | ((uint32_t)rxoffptr << 16)); +} + +__INLINE uint16_t ble_rxonptr_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SPIPTRCNTL1_ADDR); + return ((localVal & ((uint32_t)0x0000FFFF)) >> 0); +} + +__INLINE void ble_rxonptr_setf(uint16_t rxonptr) +{ + ASSERT_ERR((((uint32_t)rxonptr << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_BLE_WR(BLE_SPIPTRCNTL1_ADDR, (REG_BLE_RD(BLE_SPIPTRCNTL1_ADDR) & ~((uint32_t)0x0000FFFF)) | ((uint32_t)rxonptr << 0)); +} + +/** + * @brief SPIPTRCNTL2 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00              RSSIPTR   0x0
+ * 
+ */ +#define BLE_SPIPTRCNTL2_ADDR 0x008100A8 +#define BLE_SPIPTRCNTL2_OFFSET 0x000000A8 +#define BLE_SPIPTRCNTL2_INDEX 0x0000002A +#define BLE_SPIPTRCNTL2_RESET 0x00000000 + +__INLINE uint32_t ble_spiptrcntl2_get(void) +{ + return REG_BLE_RD(BLE_SPIPTRCNTL2_ADDR); +} + +__INLINE void ble_spiptrcntl2_set(uint32_t value) +{ + REG_BLE_WR(BLE_SPIPTRCNTL2_ADDR, value); +} + +// field definitions +#define BLE_RSSIPTR_MASK ((uint32_t)0x0000FFFF) +#define BLE_RSSIPTR_LSB 0 +#define BLE_RSSIPTR_WIDTH ((uint32_t)0x00000010) + +#define BLE_RSSIPTR_RST 0x0 + +__INLINE uint16_t ble_rssiptr_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SPIPTRCNTL2_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_rssiptr_setf(uint16_t rssiptr) +{ + ASSERT_ERR((((uint32_t)rssiptr << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_BLE_WR(BLE_SPIPTRCNTL2_ADDR, (uint32_t)rssiptr << 0); +} + +/** + * @brief ADVCHMAP register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  02:00             ADVCHMAP   0x7
+ * 
+ */ +#define BLE_ADVCHMAP_ADDR 0x008100B0 +#define BLE_ADVCHMAP_OFFSET 0x000000B0 +#define BLE_ADVCHMAP_INDEX 0x0000002C +#define BLE_ADVCHMAP_RESET 0x00000007 + +__INLINE uint32_t ble_advchmap_get(void) +{ + return REG_BLE_RD(BLE_ADVCHMAP_ADDR); +} + +__INLINE void ble_advchmap_set(uint32_t value) +{ + REG_BLE_WR(BLE_ADVCHMAP_ADDR, value); +} + +// field definitions +#define BLE_ADVCHMAP_MASK ((uint32_t)0x00000007) +#define BLE_ADVCHMAP_LSB 0 +#define BLE_ADVCHMAP_WIDTH ((uint32_t)0x00000003) + +#define BLE_ADVCHMAP_RST 0x7 + +__INLINE uint8_t ble_advchmap_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ADVCHMAP_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x00000007)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_advchmap_setf(uint8_t advchmap) +{ + ASSERT_ERR((((uint32_t)advchmap << 0) & ~((uint32_t)0x00000007)) == 0); + REG_BLE_WR(BLE_ADVCHMAP_ADDR, (uint32_t)advchmap << 0); +} + +/** + * @brief ADVTIM register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  13:00               ADVINT   0x0
+ * 
+ */ +#define BLE_ADVTIM_ADDR 0x008100C0 +#define BLE_ADVTIM_OFFSET 0x000000C0 +#define BLE_ADVTIM_INDEX 0x00000030 +#define BLE_ADVTIM_RESET 0x00000000 + +__INLINE uint32_t ble_advtim_get(void) +{ + return REG_BLE_RD(BLE_ADVTIM_ADDR); +} + +__INLINE void ble_advtim_set(uint32_t value) +{ + REG_BLE_WR(BLE_ADVTIM_ADDR, value); +} + +// field definitions +#define BLE_ADVINT_MASK ((uint32_t)0x00003FFF) +#define BLE_ADVINT_LSB 0 +#define BLE_ADVINT_WIDTH ((uint32_t)0x0000000E) + +#define BLE_ADVINT_RST 0x0 + +__INLINE uint16_t ble_advint_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ADVTIM_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x00003FFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_advint_setf(uint16_t advint) +{ + ASSERT_ERR((((uint32_t)advint << 0) & ~((uint32_t)0x00003FFF)) == 0); + REG_BLE_WR(BLE_ADVTIM_ADDR, (uint32_t)advint << 0); +} + +/** + * @brief ACTSCANSTAT register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  24:16              BACKOFF   0x1
+ *  08:00           UPPERLIMIT   0x1
+ * 
+ */ +#define BLE_ACTSCANSTAT_ADDR 0x008100C4 +#define BLE_ACTSCANSTAT_OFFSET 0x000000C4 +#define BLE_ACTSCANSTAT_INDEX 0x00000031 +#define BLE_ACTSCANSTAT_RESET 0x00010001 + +__INLINE uint32_t ble_actscanstat_get(void) +{ + return REG_BLE_RD(BLE_ACTSCANSTAT_ADDR); +} + +// field definitions +#define BLE_BACKOFF_MASK ((uint32_t)0x01FF0000) +#define BLE_BACKOFF_LSB 16 +#define BLE_BACKOFF_WIDTH ((uint32_t)0x00000009) +#define BLE_UPPERLIMIT_MASK ((uint32_t)0x000001FF) +#define BLE_UPPERLIMIT_LSB 0 +#define BLE_UPPERLIMIT_WIDTH ((uint32_t)0x00000009) + +#define BLE_BACKOFF_RST 0x1 +#define BLE_UPPERLIMIT_RST 0x1 + +__INLINE void ble_actscanstat_unpack(uint16_t* backoff, uint16_t* upperlimit) +{ + uint32_t localVal = REG_BLE_RD(BLE_ACTSCANSTAT_ADDR); + + *backoff = (localVal & ((uint32_t)0x01FF0000)) >> 16; + *upperlimit = (localVal & ((uint32_t)0x000001FF)) >> 0; +} + +__INLINE uint16_t ble_backoff_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ACTSCANSTAT_ADDR); + return ((localVal & ((uint32_t)0x01FF0000)) >> 16); +} + +__INLINE uint16_t ble_upperlimit_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ACTSCANSTAT_ADDR); + return ((localVal & ((uint32_t)0x000001FF)) >> 0); +} + +/** + * @brief WLPUBADDPTR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00          WLPUBADDPTR   0x0
+ * 
+ */ +#define BLE_WLPUBADDPTR_ADDR 0x008100D0 +#define BLE_WLPUBADDPTR_OFFSET 0x000000D0 +#define BLE_WLPUBADDPTR_INDEX 0x00000034 +#define BLE_WLPUBADDPTR_RESET 0x00000000 + +__INLINE uint32_t ble_wlpubaddptr_get(void) +{ + return REG_BLE_RD(BLE_WLPUBADDPTR_ADDR); +} + +__INLINE void ble_wlpubaddptr_set(uint32_t value) +{ + REG_BLE_WR(BLE_WLPUBADDPTR_ADDR, value); +} + +// field definitions +#define BLE_WLPUBADDPTR_MASK ((uint32_t)0x0000FFFF) +#define BLE_WLPUBADDPTR_LSB 0 +#define BLE_WLPUBADDPTR_WIDTH ((uint32_t)0x00000010) + +#define BLE_WLPUBADDPTR_RST 0x0 + +__INLINE uint16_t ble_wlpubaddptr_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_WLPUBADDPTR_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_wlpubaddptr_setf(uint16_t wlpubaddptr) +{ + ASSERT_ERR((((uint32_t)wlpubaddptr << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_BLE_WR(BLE_WLPUBADDPTR_ADDR, (uint32_t)wlpubaddptr << 0); +} + +/** + * @brief WLPRIVADDPTR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00         WLPRIVADDPTR   0x0
+ * 
+ */ +#define BLE_WLPRIVADDPTR_ADDR 0x008100D4 +#define BLE_WLPRIVADDPTR_OFFSET 0x000000D4 +#define BLE_WLPRIVADDPTR_INDEX 0x00000035 +#define BLE_WLPRIVADDPTR_RESET 0x00000000 + +__INLINE uint32_t ble_wlprivaddptr_get(void) +{ + return REG_BLE_RD(BLE_WLPRIVADDPTR_ADDR); +} + +__INLINE void ble_wlprivaddptr_set(uint32_t value) +{ + REG_BLE_WR(BLE_WLPRIVADDPTR_ADDR, value); +} + +// field definitions +#define BLE_WLPRIVADDPTR_MASK ((uint32_t)0x0000FFFF) +#define BLE_WLPRIVADDPTR_LSB 0 +#define BLE_WLPRIVADDPTR_WIDTH ((uint32_t)0x00000010) + +#define BLE_WLPRIVADDPTR_RST 0x0 + +__INLINE uint16_t ble_wlprivaddptr_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_WLPRIVADDPTR_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_wlprivaddptr_setf(uint16_t wlprivaddptr) +{ + ASSERT_ERR((((uint32_t)wlprivaddptr << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_BLE_WR(BLE_WLPRIVADDPTR_ADDR, (uint32_t)wlprivaddptr << 0); +} + +/** + * @brief WLNBDEV register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:08            NBPRIVDEV   0x0
+ *  07:00             NBPUBDEV   0x0
+ * 
+ */ +#define BLE_WLNBDEV_ADDR 0x008100D8 +#define BLE_WLNBDEV_OFFSET 0x000000D8 +#define BLE_WLNBDEV_INDEX 0x00000036 +#define BLE_WLNBDEV_RESET 0x00000000 + +__INLINE uint32_t ble_wlnbdev_get(void) +{ + return REG_BLE_RD(BLE_WLNBDEV_ADDR); +} + +__INLINE void ble_wlnbdev_set(uint32_t value) +{ + REG_BLE_WR(BLE_WLNBDEV_ADDR, value); +} + +// field definitions +#define BLE_NBPRIVDEV_MASK ((uint32_t)0x0000FF00) +#define BLE_NBPRIVDEV_LSB 8 +#define BLE_NBPRIVDEV_WIDTH ((uint32_t)0x00000008) +#define BLE_NBPUBDEV_MASK ((uint32_t)0x000000FF) +#define BLE_NBPUBDEV_LSB 0 +#define BLE_NBPUBDEV_WIDTH ((uint32_t)0x00000008) + +#define BLE_NBPRIVDEV_RST 0x0 +#define BLE_NBPUBDEV_RST 0x0 + +__INLINE void ble_wlnbdev_pack(uint8_t nbprivdev, uint8_t nbpubdev) +{ + ASSERT_ERR((((uint32_t)nbprivdev << 8) & ~((uint32_t)0x0000FF00)) == 0); + ASSERT_ERR((((uint32_t)nbpubdev << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_BLE_WR(BLE_WLNBDEV_ADDR, ((uint32_t)nbprivdev << 8) | ((uint32_t)nbpubdev << 0)); +} + +__INLINE void ble_wlnbdev_unpack(uint8_t* nbprivdev, uint8_t* nbpubdev) +{ + uint32_t localVal = REG_BLE_RD(BLE_WLNBDEV_ADDR); + + *nbprivdev = (localVal & ((uint32_t)0x0000FF00)) >> 8; + *nbpubdev = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +__INLINE uint8_t ble_nbprivdev_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_WLNBDEV_ADDR); + return ((localVal & ((uint32_t)0x0000FF00)) >> 8); +} + +__INLINE void ble_nbprivdev_setf(uint8_t nbprivdev) +{ + ASSERT_ERR((((uint32_t)nbprivdev << 8) & ~((uint32_t)0x0000FF00)) == 0); + REG_BLE_WR(BLE_WLNBDEV_ADDR, (REG_BLE_RD(BLE_WLNBDEV_ADDR) & ~((uint32_t)0x0000FF00)) | ((uint32_t)nbprivdev << 8)); +} + +__INLINE uint8_t ble_nbpubdev_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_WLNBDEV_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +__INLINE void ble_nbpubdev_setf(uint8_t nbpubdev) +{ + ASSERT_ERR((((uint32_t)nbpubdev << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_BLE_WR(BLE_WLNBDEV_ADDR, (REG_BLE_RD(BLE_WLNBDEV_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)nbpubdev << 0)); +} + +/** + * @brief AESCNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     01             AES_MODE   0
+ *     00            AES_START   0
+ * 
+ */ +#define BLE_AESCNTL_ADDR 0x008100E0 +#define BLE_AESCNTL_OFFSET 0x000000E0 +#define BLE_AESCNTL_INDEX 0x00000038 +#define BLE_AESCNTL_RESET 0x00000000 + +__INLINE uint32_t ble_aescntl_get(void) +{ + return REG_BLE_RD(BLE_AESCNTL_ADDR); +} + +__INLINE void ble_aescntl_set(uint32_t value) +{ + REG_BLE_WR(BLE_AESCNTL_ADDR, value); +} + +// field definitions +#define BLE_AES_MODE_BIT ((uint32_t)0x00000002) +#define BLE_AES_MODE_POS 1 +#define BLE_AES_START_BIT ((uint32_t)0x00000001) +#define BLE_AES_START_POS 0 + +#define BLE_AES_MODE_RST 0x0 +#define BLE_AES_START_RST 0x0 + +__INLINE void ble_aescntl_pack(uint8_t aesmode, uint8_t aesstart) +{ + ASSERT_ERR((((uint32_t)aesmode << 1) & ~((uint32_t)0x00000002)) == 0); + ASSERT_ERR((((uint32_t)aesstart << 0) & ~((uint32_t)0x00000001)) == 0); + REG_BLE_WR(BLE_AESCNTL_ADDR, ((uint32_t)aesmode << 1) | ((uint32_t)aesstart << 0)); +} + +__INLINE void ble_aescntl_unpack(uint8_t* aesmode, uint8_t* aesstart) +{ + uint32_t localVal = REG_BLE_RD(BLE_AESCNTL_ADDR); + + *aesmode = (localVal & ((uint32_t)0x00000002)) >> 1; + *aesstart = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +__INLINE uint8_t ble_aes_mode_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_AESCNTL_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +__INLINE void ble_aes_mode_setf(uint8_t aesmode) +{ + ASSERT_ERR((((uint32_t)aesmode << 1) & ~((uint32_t)0x00000002)) == 0); + REG_BLE_WR(BLE_AESCNTL_ADDR, (REG_BLE_RD(BLE_AESCNTL_ADDR) & ~((uint32_t)0x00000002)) | ((uint32_t)aesmode << 1)); +} + +__INLINE uint8_t ble_aes_start_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_AESCNTL_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +__INLINE void ble_aes_start_setf(uint8_t aesstart) +{ + ASSERT_ERR((((uint32_t)aesstart << 0) & ~((uint32_t)0x00000001)) == 0); + REG_BLE_WR(BLE_AESCNTL_ADDR, (REG_BLE_RD(BLE_AESCNTL_ADDR) & ~((uint32_t)0x00000001)) | ((uint32_t)aesstart << 0)); +} + +/** + * @brief AESKEY31_0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00           AESKEY31_0   0x0
+ * 
+ */ +#define BLE_AESKEY31_0_ADDR 0x008100E4 +#define BLE_AESKEY31_0_OFFSET 0x000000E4 +#define BLE_AESKEY31_0_INDEX 0x00000039 +#define BLE_AESKEY31_0_RESET 0x00000000 + +__INLINE uint32_t ble_aeskey31_0_get(void) +{ + return REG_BLE_RD(BLE_AESKEY31_0_ADDR); +} + +__INLINE void ble_aeskey31_0_set(uint32_t value) +{ + REG_BLE_WR(BLE_AESKEY31_0_ADDR, value); +} + +// field definitions +#define BLE_AESKEY31_0_MASK ((uint32_t)0xFFFFFFFF) +#define BLE_AESKEY31_0_LSB 0 +#define BLE_AESKEY31_0_WIDTH ((uint32_t)0x00000020) + +#define BLE_AESKEY31_0_RST 0x0 + +__INLINE uint32_t ble_aeskey31_0_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_AESKEY31_0_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_aeskey31_0_setf(uint32_t aeskey310) +{ + ASSERT_ERR((((uint32_t)aeskey310 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_BLE_WR(BLE_AESKEY31_0_ADDR, (uint32_t)aeskey310 << 0); +} + +/** + * @brief AESKEY63_32 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00          AESKEY63_32   0x0
+ * 
+ */ +#define BLE_AESKEY63_32_ADDR 0x008100E8 +#define BLE_AESKEY63_32_OFFSET 0x000000E8 +#define BLE_AESKEY63_32_INDEX 0x0000003A +#define BLE_AESKEY63_32_RESET 0x00000000 + +__INLINE uint32_t ble_aeskey63_32_get(void) +{ + return REG_BLE_RD(BLE_AESKEY63_32_ADDR); +} + +__INLINE void ble_aeskey63_32_set(uint32_t value) +{ + REG_BLE_WR(BLE_AESKEY63_32_ADDR, value); +} + +// field definitions +#define BLE_AESKEY63_32_MASK ((uint32_t)0xFFFFFFFF) +#define BLE_AESKEY63_32_LSB 0 +#define BLE_AESKEY63_32_WIDTH ((uint32_t)0x00000020) + +#define BLE_AESKEY63_32_RST 0x0 + +__INLINE uint32_t ble_aeskey63_32_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_AESKEY63_32_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_aeskey63_32_setf(uint32_t aeskey6332) +{ + ASSERT_ERR((((uint32_t)aeskey6332 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_BLE_WR(BLE_AESKEY63_32_ADDR, (uint32_t)aeskey6332 << 0); +} + +/** + * @brief AESKEY95_64 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00          AESKEY95_64   0x0
+ * 
+ */ +#define BLE_AESKEY95_64_ADDR 0x008100EC +#define BLE_AESKEY95_64_OFFSET 0x000000EC +#define BLE_AESKEY95_64_INDEX 0x0000003B +#define BLE_AESKEY95_64_RESET 0x00000000 + +__INLINE uint32_t ble_aeskey95_64_get(void) +{ + return REG_BLE_RD(BLE_AESKEY95_64_ADDR); +} + +__INLINE void ble_aeskey95_64_set(uint32_t value) +{ + REG_BLE_WR(BLE_AESKEY95_64_ADDR, value); +} + +// field definitions +#define BLE_AESKEY95_64_MASK ((uint32_t)0xFFFFFFFF) +#define BLE_AESKEY95_64_LSB 0 +#define BLE_AESKEY95_64_WIDTH ((uint32_t)0x00000020) + +#define BLE_AESKEY95_64_RST 0x0 + +__INLINE uint32_t ble_aeskey95_64_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_AESKEY95_64_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_aeskey95_64_setf(uint32_t aeskey9564) +{ + ASSERT_ERR((((uint32_t)aeskey9564 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_BLE_WR(BLE_AESKEY95_64_ADDR, (uint32_t)aeskey9564 << 0); +} + +/** + * @brief AESKEY127_96 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00         AESKEY127_96   0x0
+ * 
+ */ +#define BLE_AESKEY127_96_ADDR 0x008100F0 +#define BLE_AESKEY127_96_OFFSET 0x000000F0 +#define BLE_AESKEY127_96_INDEX 0x0000003C +#define BLE_AESKEY127_96_RESET 0x00000000 + +__INLINE uint32_t ble_aeskey127_96_get(void) +{ + return REG_BLE_RD(BLE_AESKEY127_96_ADDR); +} + +__INLINE void ble_aeskey127_96_set(uint32_t value) +{ + REG_BLE_WR(BLE_AESKEY127_96_ADDR, value); +} + +// field definitions +#define BLE_AESKEY127_96_MASK ((uint32_t)0xFFFFFFFF) +#define BLE_AESKEY127_96_LSB 0 +#define BLE_AESKEY127_96_WIDTH ((uint32_t)0x00000020) + +#define BLE_AESKEY127_96_RST 0x0 + +__INLINE uint32_t ble_aeskey127_96_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_AESKEY127_96_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_aeskey127_96_setf(uint32_t aeskey12796) +{ + ASSERT_ERR((((uint32_t)aeskey12796 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_BLE_WR(BLE_AESKEY127_96_ADDR, (uint32_t)aeskey12796 << 0); +} + +/** + * @brief AESPTR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00               AESPTR   0x0
+ * 
+ */ +#define BLE_AESPTR_ADDR 0x008100F4 +#define BLE_AESPTR_OFFSET 0x000000F4 +#define BLE_AESPTR_INDEX 0x0000003D +#define BLE_AESPTR_RESET 0x00000000 + +__INLINE uint32_t ble_aesptr_get(void) +{ + return REG_BLE_RD(BLE_AESPTR_ADDR); +} + +__INLINE void ble_aesptr_set(uint32_t value) +{ + REG_BLE_WR(BLE_AESPTR_ADDR, value); +} + +// field definitions +#define BLE_AESPTR_MASK ((uint32_t)0x0000FFFF) +#define BLE_AESPTR_LSB 0 +#define BLE_AESPTR_WIDTH ((uint32_t)0x00000010) + +#define BLE_AESPTR_RST 0x0 + +__INLINE uint16_t ble_aesptr_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_AESPTR_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_aesptr_setf(uint16_t aesptr) +{ + ASSERT_ERR((((uint32_t)aesptr << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_BLE_WR(BLE_AESPTR_ADDR, (uint32_t)aesptr << 0); +} + +/** + * @brief TXMICVAL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00             TXMICVAL   0x0
+ * 
+ */ +#define BLE_TXMICVAL_ADDR 0x008100F8 +#define BLE_TXMICVAL_OFFSET 0x000000F8 +#define BLE_TXMICVAL_INDEX 0x0000003E +#define BLE_TXMICVAL_RESET 0x00000000 + +__INLINE uint32_t ble_txmicval_get(void) +{ + return REG_BLE_RD(BLE_TXMICVAL_ADDR); +} + +// field definitions +#define BLE_TXMICVAL_MASK ((uint32_t)0xFFFFFFFF) +#define BLE_TXMICVAL_LSB 0 +#define BLE_TXMICVAL_WIDTH ((uint32_t)0x00000020) + +#define BLE_TXMICVAL_RST 0x0 + +__INLINE uint32_t ble_txmicval_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_TXMICVAL_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief RXMICVAL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00             RXMICVAL   0x0
+ * 
+ */ +#define BLE_RXMICVAL_ADDR 0x008100FC +#define BLE_RXMICVAL_OFFSET 0x000000FC +#define BLE_RXMICVAL_INDEX 0x0000003F +#define BLE_RXMICVAL_RESET 0x00000000 + +__INLINE uint32_t ble_rxmicval_get(void) +{ + return REG_BLE_RD(BLE_RXMICVAL_ADDR); +} + +// field definitions +#define BLE_RXMICVAL_MASK ((uint32_t)0xFFFFFFFF) +#define BLE_RXMICVAL_LSB 0 +#define BLE_RXMICVAL_WIDTH ((uint32_t)0x00000020) + +#define BLE_RXMICVAL_RST 0x0 + +__INLINE uint32_t ble_rxmicval_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RXMICVAL_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief RFTESTCNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31           INFINITERX   0
+ *     27           RXPKTCNTEN   0
+ *     15           INFINITETX   0
+ *     14          TXLENGTHSRC   0
+ *     13             PRBSTYPE   0
+ *     12             TXPLDSRC   0
+ *     11           TXPKTCNTEN   0
+ *  08:00             TXLENGTH   0x0
+ * 
+ */ +#define BLE_RFTESTCNTL_ADDR 0x00810100 +#define BLE_RFTESTCNTL_OFFSET 0x00000100 +#define BLE_RFTESTCNTL_INDEX 0x00000040 +#define BLE_RFTESTCNTL_RESET 0x00000000 + +__INLINE uint32_t ble_rftestcntl_get(void) +{ + return REG_BLE_RD(BLE_RFTESTCNTL_ADDR); +} + +__INLINE void ble_rftestcntl_set(uint32_t value) +{ + REG_BLE_WR(BLE_RFTESTCNTL_ADDR, value); +} + +// field definitions +#define BLE_INFINITERX_BIT ((uint32_t)0x80000000) +#define BLE_INFINITERX_POS 31 +#define BLE_RXPKTCNTEN_BIT ((uint32_t)0x08000000) +#define BLE_RXPKTCNTEN_POS 27 +#define BLE_INFINITETX_BIT ((uint32_t)0x00008000) +#define BLE_INFINITETX_POS 15 +#define BLE_TXLENGTHSRC_BIT ((uint32_t)0x00004000) +#define BLE_TXLENGTHSRC_POS 14 +#define BLE_PRBSTYPE_BIT ((uint32_t)0x00002000) +#define BLE_PRBSTYPE_POS 13 +#define BLE_TXPLDSRC_BIT ((uint32_t)0x00001000) +#define BLE_TXPLDSRC_POS 12 +#define BLE_TXPKTCNTEN_BIT ((uint32_t)0x00000800) +#define BLE_TXPKTCNTEN_POS 11 +#define BLE_TXLENGTH_MASK ((uint32_t)0x000001FF) +#define BLE_TXLENGTH_LSB 0 +#define BLE_TXLENGTH_WIDTH ((uint32_t)0x00000009) + +#define BLE_INFINITERX_RST 0x0 +#define BLE_RXPKTCNTEN_RST 0x0 +#define BLE_INFINITETX_RST 0x0 +#define BLE_TXLENGTHSRC_RST 0x0 +#define BLE_PRBSTYPE_RST 0x0 +#define BLE_TXPLDSRC_RST 0x0 +#define BLE_TXPKTCNTEN_RST 0x0 +#define BLE_TXLENGTH_RST 0x0 + +__INLINE void ble_rftestcntl_pack(uint8_t infiniterx, uint8_t rxpktcnten, uint8_t infinitetx, uint8_t txlengthsrc, uint8_t prbstype, uint8_t txpldsrc, uint8_t txpktcnten, uint16_t txlength) +{ + ASSERT_ERR((((uint32_t)infiniterx << 31) & ~((uint32_t)0x80000000)) == 0); + ASSERT_ERR((((uint32_t)rxpktcnten << 27) & ~((uint32_t)0x08000000)) == 0); + ASSERT_ERR((((uint32_t)infinitetx << 15) & ~((uint32_t)0x00008000)) == 0); + ASSERT_ERR((((uint32_t)txlengthsrc << 14) & ~((uint32_t)0x00004000)) == 0); + ASSERT_ERR((((uint32_t)prbstype << 13) & ~((uint32_t)0x00002000)) == 0); + ASSERT_ERR((((uint32_t)txpldsrc << 12) & ~((uint32_t)0x00001000)) == 0); + ASSERT_ERR((((uint32_t)txpktcnten << 11) & ~((uint32_t)0x00000800)) == 0); + ASSERT_ERR((((uint32_t)txlength << 0) & ~((uint32_t)0x000001FF)) == 0); + REG_BLE_WR(BLE_RFTESTCNTL_ADDR, ((uint32_t)infiniterx << 31) | ((uint32_t)rxpktcnten << 27) | ((uint32_t)infinitetx << 15) | ((uint32_t)txlengthsrc << 14) | ((uint32_t)prbstype << 13) | ((uint32_t)txpldsrc << 12) | ((uint32_t)txpktcnten << 11) | ((uint32_t)txlength << 0)); +} + +__INLINE void ble_rftestcntl_unpack(uint8_t* infiniterx, uint8_t* rxpktcnten, uint8_t* infinitetx, uint8_t* txlengthsrc, uint8_t* prbstype, uint8_t* txpldsrc, uint8_t* txpktcnten, uint16_t* txlength) +{ + uint32_t localVal = REG_BLE_RD(BLE_RFTESTCNTL_ADDR); + + *infiniterx = (localVal & ((uint32_t)0x80000000)) >> 31; + *rxpktcnten = (localVal & ((uint32_t)0x08000000)) >> 27; + *infinitetx = (localVal & ((uint32_t)0x00008000)) >> 15; + *txlengthsrc = (localVal & ((uint32_t)0x00004000)) >> 14; + *prbstype = (localVal & ((uint32_t)0x00002000)) >> 13; + *txpldsrc = (localVal & ((uint32_t)0x00001000)) >> 12; + *txpktcnten = (localVal & ((uint32_t)0x00000800)) >> 11; + *txlength = (localVal & ((uint32_t)0x000001FF)) >> 0; +} + +__INLINE uint8_t ble_infiniterx_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RFTESTCNTL_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +__INLINE void ble_infiniterx_setf(uint8_t infiniterx) +{ + ASSERT_ERR((((uint32_t)infiniterx << 31) & ~((uint32_t)0x80000000)) == 0); + REG_BLE_WR(BLE_RFTESTCNTL_ADDR, (REG_BLE_RD(BLE_RFTESTCNTL_ADDR) & ~((uint32_t)0x80000000)) | ((uint32_t)infiniterx << 31)); +} + +__INLINE uint8_t ble_rxpktcnten_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RFTESTCNTL_ADDR); + return ((localVal & ((uint32_t)0x08000000)) >> 27); +} + +__INLINE void ble_rxpktcnten_setf(uint8_t rxpktcnten) +{ + ASSERT_ERR((((uint32_t)rxpktcnten << 27) & ~((uint32_t)0x08000000)) == 0); + REG_BLE_WR(BLE_RFTESTCNTL_ADDR, (REG_BLE_RD(BLE_RFTESTCNTL_ADDR) & ~((uint32_t)0x08000000)) | ((uint32_t)rxpktcnten << 27)); +} + +__INLINE uint8_t ble_infinitetx_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RFTESTCNTL_ADDR); + return ((localVal & ((uint32_t)0x00008000)) >> 15); +} + +__INLINE void ble_infinitetx_setf(uint8_t infinitetx) +{ + ASSERT_ERR((((uint32_t)infinitetx << 15) & ~((uint32_t)0x00008000)) == 0); + REG_BLE_WR(BLE_RFTESTCNTL_ADDR, (REG_BLE_RD(BLE_RFTESTCNTL_ADDR) & ~((uint32_t)0x00008000)) | ((uint32_t)infinitetx << 15)); +} + +__INLINE uint8_t ble_txlengthsrc_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RFTESTCNTL_ADDR); + return ((localVal & ((uint32_t)0x00004000)) >> 14); +} + +__INLINE void ble_txlengthsrc_setf(uint8_t txlengthsrc) +{ + ASSERT_ERR((((uint32_t)txlengthsrc << 14) & ~((uint32_t)0x00004000)) == 0); + REG_BLE_WR(BLE_RFTESTCNTL_ADDR, (REG_BLE_RD(BLE_RFTESTCNTL_ADDR) & ~((uint32_t)0x00004000)) | ((uint32_t)txlengthsrc << 14)); +} + +__INLINE uint8_t ble_prbstype_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RFTESTCNTL_ADDR); + return ((localVal & ((uint32_t)0x00002000)) >> 13); +} + +__INLINE void ble_prbstype_setf(uint8_t prbstype) +{ + ASSERT_ERR((((uint32_t)prbstype << 13) & ~((uint32_t)0x00002000)) == 0); + REG_BLE_WR(BLE_RFTESTCNTL_ADDR, (REG_BLE_RD(BLE_RFTESTCNTL_ADDR) & ~((uint32_t)0x00002000)) | ((uint32_t)prbstype << 13)); +} + +__INLINE uint8_t ble_txpldsrc_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RFTESTCNTL_ADDR); + return ((localVal & ((uint32_t)0x00001000)) >> 12); +} + +__INLINE void ble_txpldsrc_setf(uint8_t txpldsrc) +{ + ASSERT_ERR((((uint32_t)txpldsrc << 12) & ~((uint32_t)0x00001000)) == 0); + REG_BLE_WR(BLE_RFTESTCNTL_ADDR, (REG_BLE_RD(BLE_RFTESTCNTL_ADDR) & ~((uint32_t)0x00001000)) | ((uint32_t)txpldsrc << 12)); +} + +__INLINE uint8_t ble_txpktcnten_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RFTESTCNTL_ADDR); + return ((localVal & ((uint32_t)0x00000800)) >> 11); +} + +__INLINE void ble_txpktcnten_setf(uint8_t txpktcnten) +{ + ASSERT_ERR((((uint32_t)txpktcnten << 11) & ~((uint32_t)0x00000800)) == 0); + REG_BLE_WR(BLE_RFTESTCNTL_ADDR, (REG_BLE_RD(BLE_RFTESTCNTL_ADDR) & ~((uint32_t)0x00000800)) | ((uint32_t)txpktcnten << 11)); +} + +__INLINE uint16_t ble_txlength_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RFTESTCNTL_ADDR); + return ((localVal & ((uint32_t)0x000001FF)) >> 0); +} + +__INLINE void ble_txlength_setf(uint16_t txlength) +{ + ASSERT_ERR((((uint32_t)txlength << 0) & ~((uint32_t)0x000001FF)) == 0); + REG_BLE_WR(BLE_RFTESTCNTL_ADDR, (REG_BLE_RD(BLE_RFTESTCNTL_ADDR) & ~((uint32_t)0x000001FF)) | ((uint32_t)txlength << 0)); +} + +/** + * @brief RFTESTTXSTAT register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00             TXPKTCNT   0x0
+ * 
+ */ +#define BLE_RFTESTTXSTAT_ADDR 0x00810104 +#define BLE_RFTESTTXSTAT_OFFSET 0x00000104 +#define BLE_RFTESTTXSTAT_INDEX 0x00000041 +#define BLE_RFTESTTXSTAT_RESET 0x00000000 + +__INLINE uint32_t ble_rftesttxstat_get(void) +{ + return REG_BLE_RD(BLE_RFTESTTXSTAT_ADDR); +} + +// field definitions +#define BLE_TXPKTCNT_MASK ((uint32_t)0xFFFFFFFF) +#define BLE_TXPKTCNT_LSB 0 +#define BLE_TXPKTCNT_WIDTH ((uint32_t)0x00000020) + +#define BLE_TXPKTCNT_RST 0x0 + +__INLINE uint32_t ble_txpktcnt_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RFTESTTXSTAT_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief RFTESTRXSTAT register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00             RXPKTCNT   0x0
+ * 
+ */ +#define BLE_RFTESTRXSTAT_ADDR 0x00810108 +#define BLE_RFTESTRXSTAT_OFFSET 0x00000108 +#define BLE_RFTESTRXSTAT_INDEX 0x00000042 +#define BLE_RFTESTRXSTAT_RESET 0x00000000 + +__INLINE uint32_t ble_rftestrxstat_get(void) +{ + return REG_BLE_RD(BLE_RFTESTRXSTAT_ADDR); +} + +// field definitions +#define BLE_RXPKTCNT_MASK ((uint32_t)0xFFFFFFFF) +#define BLE_RXPKTCNT_LSB 0 +#define BLE_RXPKTCNT_WIDTH ((uint32_t)0x00000020) + +#define BLE_RXPKTCNT_RST 0x0 + +__INLINE uint32_t ble_rxpktcnt_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RFTESTRXSTAT_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief TIMGENCNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31              APFM_EN   1
+ *  25:16   PREFETCHABORT_TIME   0x1FE
+ *  08:00        PREFETCH_TIME   0x96
+ * 
+ */ +#define BLE_TIMGENCNTL_ADDR 0x00810110 +#define BLE_TIMGENCNTL_OFFSET 0x00000110 +#define BLE_TIMGENCNTL_INDEX 0x00000044 +#define BLE_TIMGENCNTL_RESET 0x81FE0096 + +__INLINE uint32_t ble_timgencntl_get(void) +{ + return REG_BLE_RD(BLE_TIMGENCNTL_ADDR); +} + +__INLINE void ble_timgencntl_set(uint32_t value) +{ + REG_BLE_WR(BLE_TIMGENCNTL_ADDR, value); +} + +// field definitions +#define BLE_APFM_EN_BIT ((uint32_t)0x80000000) +#define BLE_APFM_EN_POS 31 +#define BLE_PREFETCHABORT_TIME_MASK ((uint32_t)0x03FF0000) +#define BLE_PREFETCHABORT_TIME_LSB 16 +#define BLE_PREFETCHABORT_TIME_WIDTH ((uint32_t)0x0000000A) +#define BLE_PREFETCH_TIME_MASK ((uint32_t)0x000001FF) +#define BLE_PREFETCH_TIME_LSB 0 +#define BLE_PREFETCH_TIME_WIDTH ((uint32_t)0x00000009) + +#define BLE_APFM_EN_RST 0x1 +#define BLE_PREFETCHABORT_TIME_RST 0x1FE +#define BLE_PREFETCH_TIME_RST 0x96 + +__INLINE void ble_timgencntl_pack(uint8_t apfmen, uint16_t prefetchaborttime, uint16_t prefetchtime) +{ + ASSERT_ERR((((uint32_t)apfmen << 31) & ~((uint32_t)0x80000000)) == 0); + ASSERT_ERR((((uint32_t)prefetchaborttime << 16) & ~((uint32_t)0x03FF0000)) == 0); + ASSERT_ERR((((uint32_t)prefetchtime << 0) & ~((uint32_t)0x000001FF)) == 0); + REG_BLE_WR(BLE_TIMGENCNTL_ADDR, ((uint32_t)apfmen << 31) | ((uint32_t)prefetchaborttime << 16) | ((uint32_t)prefetchtime << 0)); +} + +__INLINE void ble_timgencntl_unpack(uint8_t* apfmen, uint16_t* prefetchaborttime, uint16_t* prefetchtime) +{ + uint32_t localVal = REG_BLE_RD(BLE_TIMGENCNTL_ADDR); + + *apfmen = (localVal & ((uint32_t)0x80000000)) >> 31; + *prefetchaborttime = (localVal & ((uint32_t)0x03FF0000)) >> 16; + *prefetchtime = (localVal & ((uint32_t)0x000001FF)) >> 0; +} + +__INLINE uint8_t ble_apfm_en_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_TIMGENCNTL_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +__INLINE void ble_apfm_en_setf(uint8_t apfmen) +{ + ASSERT_ERR((((uint32_t)apfmen << 31) & ~((uint32_t)0x80000000)) == 0); + REG_BLE_WR(BLE_TIMGENCNTL_ADDR, (REG_BLE_RD(BLE_TIMGENCNTL_ADDR) & ~((uint32_t)0x80000000)) | ((uint32_t)apfmen << 31)); +} + +__INLINE uint16_t ble_prefetchabort_time_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_TIMGENCNTL_ADDR); + return ((localVal & ((uint32_t)0x03FF0000)) >> 16); +} + +__INLINE void ble_prefetchabort_time_setf(uint16_t prefetchaborttime) +{ + ASSERT_ERR((((uint32_t)prefetchaborttime << 16) & ~((uint32_t)0x03FF0000)) == 0); + REG_BLE_WR(BLE_TIMGENCNTL_ADDR, (REG_BLE_RD(BLE_TIMGENCNTL_ADDR) & ~((uint32_t)0x03FF0000)) | ((uint32_t)prefetchaborttime << 16)); +} + +__INLINE uint16_t ble_prefetch_time_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_TIMGENCNTL_ADDR); + return ((localVal & ((uint32_t)0x000001FF)) >> 0); +} + +__INLINE void ble_prefetch_time_setf(uint16_t prefetchtime) +{ + ASSERT_ERR((((uint32_t)prefetchtime << 0) & ~((uint32_t)0x000001FF)) == 0); + REG_BLE_WR(BLE_TIMGENCNTL_ADDR, (REG_BLE_RD(BLE_TIMGENCNTL_ADDR) & ~((uint32_t)0x000001FF)) | ((uint32_t)prefetchtime << 0)); +} + +/** + * @brief GROSSTIMTGT register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  22:00          GROSSTARGET   0x0
+ * 
+ */ +#define BLE_GROSSTIMTGT_ADDR 0x00810114 +#define BLE_GROSSTIMTGT_OFFSET 0x00000114 +#define BLE_GROSSTIMTGT_INDEX 0x00000045 +#define BLE_GROSSTIMTGT_RESET 0x00000000 + +__INLINE uint32_t ble_grosstimtgt_get(void) +{ + return REG_BLE_RD(BLE_GROSSTIMTGT_ADDR); +} + +__INLINE void ble_grosstimtgt_set(uint32_t value) +{ + REG_BLE_WR(BLE_GROSSTIMTGT_ADDR, value); +} + +// field definitions +#define BLE_GROSSTARGET_MASK ((uint32_t)0x007FFFFF) +#define BLE_GROSSTARGET_LSB 0 +#define BLE_GROSSTARGET_WIDTH ((uint32_t)0x00000017) + +#define BLE_GROSSTARGET_RST 0x0 + +__INLINE uint32_t ble_grosstarget_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_GROSSTIMTGT_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x007FFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_grosstarget_setf(uint32_t grosstarget) +{ + ASSERT_ERR((((uint32_t)grosstarget << 0) & ~((uint32_t)0x007FFFFF)) == 0); + REG_BLE_WR(BLE_GROSSTIMTGT_ADDR, (uint32_t)grosstarget << 0); +} + +/** + * @brief FINETIMTGT register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  26:00           FINETARGET   0x0
+ * 
+ */ +#define BLE_FINETIMTGT_ADDR 0x00810118 +#define BLE_FINETIMTGT_OFFSET 0x00000118 +#define BLE_FINETIMTGT_INDEX 0x00000046 +#define BLE_FINETIMTGT_RESET 0x00000000 + +__INLINE uint32_t ble_finetimtgt_get(void) +{ + return REG_BLE_RD(BLE_FINETIMTGT_ADDR); +} + +__INLINE void ble_finetimtgt_set(uint32_t value) +{ + REG_BLE_WR(BLE_FINETIMTGT_ADDR, value); +} + +// field definitions +#define BLE_FINETARGET_MASK ((uint32_t)0x07FFFFFF) +#define BLE_FINETARGET_LSB 0 +#define BLE_FINETARGET_WIDTH ((uint32_t)0x0000001B) + +#define BLE_FINETARGET_RST 0x0 + +__INLINE uint32_t ble_finetarget_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_FINETIMTGT_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x07FFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_finetarget_setf(uint32_t finetarget) +{ + ASSERT_ERR((((uint32_t)finetarget << 0) & ~((uint32_t)0x07FFFFFF)) == 0); + REG_BLE_WR(BLE_FINETIMTGT_ADDR, (uint32_t)finetarget << 0); +} + +/** + * @brief COEXIFCNTL0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  25:24       MWSSCANFREQMSK   0x0
+ *  21:20        WLCRXPRIOMODE   0x0
+ *  17:16        WLCTXPRIOMODE   0x0
+ *  15:14          MWSTXFRQMSK   0x0
+ *  13:12          MWSRXFRQMSK   0x0
+ *  11:10             MWSTXMSK   0x0
+ *  09:08             MWSRXMSK   0x0
+ *  07:06            WLANTXMSK   0x0
+ *  05:04            WLANRXMSK   0x1
+ *     03            MWSWCI_EN   0
+ *     02           MWSCOEX_EN   0
+ *     01           SYNCGEN_EN   0
+ *     00          WLANCOEX_EN   0
+ * 
+ */ +#define BLE_COEXIFCNTL0_ADDR 0x00810120 +#define BLE_COEXIFCNTL0_OFFSET 0x00000120 +#define BLE_COEXIFCNTL0_INDEX 0x00000048 +#define BLE_COEXIFCNTL0_RESET 0x00000010 + +__INLINE uint32_t ble_coexifcntl0_get(void) +{ + return REG_BLE_RD(BLE_COEXIFCNTL0_ADDR); +} + +__INLINE void ble_coexifcntl0_set(uint32_t value) +{ + REG_BLE_WR(BLE_COEXIFCNTL0_ADDR, value); +} + +// field definitions +#define BLE_MWSSCANFREQMSK_MASK ((uint32_t)0x03000000) +#define BLE_MWSSCANFREQMSK_LSB 24 +#define BLE_MWSSCANFREQMSK_WIDTH ((uint32_t)0x00000002) +#define BLE_WLCRXPRIOMODE_MASK ((uint32_t)0x00300000) +#define BLE_WLCRXPRIOMODE_LSB 20 +#define BLE_WLCRXPRIOMODE_WIDTH ((uint32_t)0x00000002) +#define BLE_WLCTXPRIOMODE_MASK ((uint32_t)0x00030000) +#define BLE_WLCTXPRIOMODE_LSB 16 +#define BLE_WLCTXPRIOMODE_WIDTH ((uint32_t)0x00000002) +#define BLE_MWSTXFRQMSK_MASK ((uint32_t)0x0000C000) +#define BLE_MWSTXFRQMSK_LSB 14 +#define BLE_MWSTXFRQMSK_WIDTH ((uint32_t)0x00000002) +#define BLE_MWSRXFRQMSK_MASK ((uint32_t)0x00003000) +#define BLE_MWSRXFRQMSK_LSB 12 +#define BLE_MWSRXFRQMSK_WIDTH ((uint32_t)0x00000002) +#define BLE_MWSTXMSK_MASK ((uint32_t)0x00000C00) +#define BLE_MWSTXMSK_LSB 10 +#define BLE_MWSTXMSK_WIDTH ((uint32_t)0x00000002) +#define BLE_MWSRXMSK_MASK ((uint32_t)0x00000300) +#define BLE_MWSRXMSK_LSB 8 +#define BLE_MWSRXMSK_WIDTH ((uint32_t)0x00000002) +#define BLE_WLANTXMSK_MASK ((uint32_t)0x000000C0) +#define BLE_WLANTXMSK_LSB 6 +#define BLE_WLANTXMSK_WIDTH ((uint32_t)0x00000002) +#define BLE_WLANRXMSK_MASK ((uint32_t)0x00000030) +#define BLE_WLANRXMSK_LSB 4 +#define BLE_WLANRXMSK_WIDTH ((uint32_t)0x00000002) +#define BLE_MWSWCI_EN_BIT ((uint32_t)0x00000008) +#define BLE_MWSWCI_EN_POS 3 +#define BLE_MWSCOEX_EN_BIT ((uint32_t)0x00000004) +#define BLE_MWSCOEX_EN_POS 2 +#define BLE_SYNCGEN_EN_BIT ((uint32_t)0x00000002) +#define BLE_SYNCGEN_EN_POS 1 +#define BLE_WLANCOEX_EN_BIT ((uint32_t)0x00000001) +#define BLE_WLANCOEX_EN_POS 0 + +#define BLE_MWSSCANFREQMSK_RST 0x0 +#define BLE_WLCRXPRIOMODE_RST 0x0 +#define BLE_WLCTXPRIOMODE_RST 0x0 +#define BLE_MWSTXFRQMSK_RST 0x0 +#define BLE_MWSRXFRQMSK_RST 0x0 +#define BLE_MWSTXMSK_RST 0x0 +#define BLE_MWSRXMSK_RST 0x0 +#define BLE_WLANTXMSK_RST 0x0 +#define BLE_WLANRXMSK_RST 0x1 +#define BLE_MWSWCI_EN_RST 0x0 +#define BLE_MWSCOEX_EN_RST 0x0 +#define BLE_SYNCGEN_EN_RST 0x0 +#define BLE_WLANCOEX_EN_RST 0x0 + +__INLINE void ble_coexifcntl0_pack(uint8_t mwsscanfreqmsk, uint8_t wlcrxpriomode, uint8_t wlctxpriomode, uint8_t mwstxfrqmsk, uint8_t mwsrxfrqmsk, uint8_t mwstxmsk, uint8_t mwsrxmsk, uint8_t wlantxmsk, uint8_t wlanrxmsk, uint8_t mwswcien, uint8_t mwscoexen, uint8_t syncgenen, uint8_t wlancoexen) +{ + ASSERT_ERR((((uint32_t)mwsscanfreqmsk << 24) & ~((uint32_t)0x03000000)) == 0); + ASSERT_ERR((((uint32_t)wlcrxpriomode << 20) & ~((uint32_t)0x00300000)) == 0); + ASSERT_ERR((((uint32_t)wlctxpriomode << 16) & ~((uint32_t)0x00030000)) == 0); + ASSERT_ERR((((uint32_t)mwstxfrqmsk << 14) & ~((uint32_t)0x0000C000)) == 0); + ASSERT_ERR((((uint32_t)mwsrxfrqmsk << 12) & ~((uint32_t)0x00003000)) == 0); + ASSERT_ERR((((uint32_t)mwstxmsk << 10) & ~((uint32_t)0x00000C00)) == 0); + ASSERT_ERR((((uint32_t)mwsrxmsk << 8) & ~((uint32_t)0x00000300)) == 0); + ASSERT_ERR((((uint32_t)wlantxmsk << 6) & ~((uint32_t)0x000000C0)) == 0); + ASSERT_ERR((((uint32_t)wlanrxmsk << 4) & ~((uint32_t)0x00000030)) == 0); + ASSERT_ERR((((uint32_t)mwswcien << 3) & ~((uint32_t)0x00000008)) == 0); + ASSERT_ERR((((uint32_t)mwscoexen << 2) & ~((uint32_t)0x00000004)) == 0); + ASSERT_ERR((((uint32_t)syncgenen << 1) & ~((uint32_t)0x00000002)) == 0); + ASSERT_ERR((((uint32_t)wlancoexen << 0) & ~((uint32_t)0x00000001)) == 0); + REG_BLE_WR(BLE_COEXIFCNTL0_ADDR, ((uint32_t)mwsscanfreqmsk << 24) | ((uint32_t)wlcrxpriomode << 20) | ((uint32_t)wlctxpriomode << 16) | ((uint32_t)mwstxfrqmsk << 14) | ((uint32_t)mwsrxfrqmsk << 12) | ((uint32_t)mwstxmsk << 10) | ((uint32_t)mwsrxmsk << 8) | ((uint32_t)wlantxmsk << 6) | ((uint32_t)wlanrxmsk << 4) | ((uint32_t)mwswcien << 3) | ((uint32_t)mwscoexen << 2) | ((uint32_t)syncgenen << 1) | ((uint32_t)wlancoexen << 0)); +} + +__INLINE void ble_coexifcntl0_unpack(uint8_t* mwsscanfreqmsk, uint8_t* wlcrxpriomode, uint8_t* wlctxpriomode, uint8_t* mwstxfrqmsk, uint8_t* mwsrxfrqmsk, uint8_t* mwstxmsk, uint8_t* mwsrxmsk, uint8_t* wlantxmsk, uint8_t* wlanrxmsk, uint8_t* mwswcien, uint8_t* mwscoexen, uint8_t* syncgenen, uint8_t* wlancoexen) +{ + uint32_t localVal = REG_BLE_RD(BLE_COEXIFCNTL0_ADDR); + + *mwsscanfreqmsk = (localVal & ((uint32_t)0x03000000)) >> 24; + *wlcrxpriomode = (localVal & ((uint32_t)0x00300000)) >> 20; + *wlctxpriomode = (localVal & ((uint32_t)0x00030000)) >> 16; + *mwstxfrqmsk = (localVal & ((uint32_t)0x0000C000)) >> 14; + *mwsrxfrqmsk = (localVal & ((uint32_t)0x00003000)) >> 12; + *mwstxmsk = (localVal & ((uint32_t)0x00000C00)) >> 10; + *mwsrxmsk = (localVal & ((uint32_t)0x00000300)) >> 8; + *wlantxmsk = (localVal & ((uint32_t)0x000000C0)) >> 6; + *wlanrxmsk = (localVal & ((uint32_t)0x00000030)) >> 4; + *mwswcien = (localVal & ((uint32_t)0x00000008)) >> 3; + *mwscoexen = (localVal & ((uint32_t)0x00000004)) >> 2; + *syncgenen = (localVal & ((uint32_t)0x00000002)) >> 1; + *wlancoexen = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +__INLINE uint8_t ble_mwsscanfreqmsk_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_COEXIFCNTL0_ADDR); + return ((localVal & ((uint32_t)0x03000000)) >> 24); +} + +__INLINE void ble_mwsscanfreqmsk_setf(uint8_t mwsscanfreqmsk) +{ + ASSERT_ERR((((uint32_t)mwsscanfreqmsk << 24) & ~((uint32_t)0x03000000)) == 0); + REG_BLE_WR(BLE_COEXIFCNTL0_ADDR, (REG_BLE_RD(BLE_COEXIFCNTL0_ADDR) & ~((uint32_t)0x03000000)) | ((uint32_t)mwsscanfreqmsk << 24)); +} + +__INLINE uint8_t ble_wlcrxpriomode_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_COEXIFCNTL0_ADDR); + return ((localVal & ((uint32_t)0x00300000)) >> 20); +} + +__INLINE void ble_wlcrxpriomode_setf(uint8_t wlcrxpriomode) +{ + ASSERT_ERR((((uint32_t)wlcrxpriomode << 20) & ~((uint32_t)0x00300000)) == 0); + REG_BLE_WR(BLE_COEXIFCNTL0_ADDR, (REG_BLE_RD(BLE_COEXIFCNTL0_ADDR) & ~((uint32_t)0x00300000)) | ((uint32_t)wlcrxpriomode << 20)); +} + +__INLINE uint8_t ble_wlctxpriomode_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_COEXIFCNTL0_ADDR); + return ((localVal & ((uint32_t)0x00030000)) >> 16); +} + +__INLINE void ble_wlctxpriomode_setf(uint8_t wlctxpriomode) +{ + ASSERT_ERR((((uint32_t)wlctxpriomode << 16) & ~((uint32_t)0x00030000)) == 0); + REG_BLE_WR(BLE_COEXIFCNTL0_ADDR, (REG_BLE_RD(BLE_COEXIFCNTL0_ADDR) & ~((uint32_t)0x00030000)) | ((uint32_t)wlctxpriomode << 16)); +} + +__INLINE uint8_t ble_mwstxfrqmsk_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_COEXIFCNTL0_ADDR); + return ((localVal & ((uint32_t)0x0000C000)) >> 14); +} + +__INLINE void ble_mwstxfrqmsk_setf(uint8_t mwstxfrqmsk) +{ + ASSERT_ERR((((uint32_t)mwstxfrqmsk << 14) & ~((uint32_t)0x0000C000)) == 0); + REG_BLE_WR(BLE_COEXIFCNTL0_ADDR, (REG_BLE_RD(BLE_COEXIFCNTL0_ADDR) & ~((uint32_t)0x0000C000)) | ((uint32_t)mwstxfrqmsk << 14)); +} + +__INLINE uint8_t ble_mwsrxfrqmsk_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_COEXIFCNTL0_ADDR); + return ((localVal & ((uint32_t)0x00003000)) >> 12); +} + +__INLINE void ble_mwsrxfrqmsk_setf(uint8_t mwsrxfrqmsk) +{ + ASSERT_ERR((((uint32_t)mwsrxfrqmsk << 12) & ~((uint32_t)0x00003000)) == 0); + REG_BLE_WR(BLE_COEXIFCNTL0_ADDR, (REG_BLE_RD(BLE_COEXIFCNTL0_ADDR) & ~((uint32_t)0x00003000)) | ((uint32_t)mwsrxfrqmsk << 12)); +} + +__INLINE uint8_t ble_mwstxmsk_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_COEXIFCNTL0_ADDR); + return ((localVal & ((uint32_t)0x00000C00)) >> 10); +} + +__INLINE void ble_mwstxmsk_setf(uint8_t mwstxmsk) +{ + ASSERT_ERR((((uint32_t)mwstxmsk << 10) & ~((uint32_t)0x00000C00)) == 0); + REG_BLE_WR(BLE_COEXIFCNTL0_ADDR, (REG_BLE_RD(BLE_COEXIFCNTL0_ADDR) & ~((uint32_t)0x00000C00)) | ((uint32_t)mwstxmsk << 10)); +} + +__INLINE uint8_t ble_mwsrxmsk_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_COEXIFCNTL0_ADDR); + return ((localVal & ((uint32_t)0x00000300)) >> 8); +} + +__INLINE void ble_mwsrxmsk_setf(uint8_t mwsrxmsk) +{ + ASSERT_ERR((((uint32_t)mwsrxmsk << 8) & ~((uint32_t)0x00000300)) == 0); + REG_BLE_WR(BLE_COEXIFCNTL0_ADDR, (REG_BLE_RD(BLE_COEXIFCNTL0_ADDR) & ~((uint32_t)0x00000300)) | ((uint32_t)mwsrxmsk << 8)); +} + +__INLINE uint8_t ble_wlantxmsk_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_COEXIFCNTL0_ADDR); + return ((localVal & ((uint32_t)0x000000C0)) >> 6); +} + +__INLINE void ble_wlantxmsk_setf(uint8_t wlantxmsk) +{ + ASSERT_ERR((((uint32_t)wlantxmsk << 6) & ~((uint32_t)0x000000C0)) == 0); + REG_BLE_WR(BLE_COEXIFCNTL0_ADDR, (REG_BLE_RD(BLE_COEXIFCNTL0_ADDR) & ~((uint32_t)0x000000C0)) | ((uint32_t)wlantxmsk << 6)); +} + +__INLINE uint8_t ble_wlanrxmsk_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_COEXIFCNTL0_ADDR); + return ((localVal & ((uint32_t)0x00000030)) >> 4); +} + +__INLINE void ble_wlanrxmsk_setf(uint8_t wlanrxmsk) +{ + ASSERT_ERR((((uint32_t)wlanrxmsk << 4) & ~((uint32_t)0x00000030)) == 0); + REG_BLE_WR(BLE_COEXIFCNTL0_ADDR, (REG_BLE_RD(BLE_COEXIFCNTL0_ADDR) & ~((uint32_t)0x00000030)) | ((uint32_t)wlanrxmsk << 4)); +} + +__INLINE uint8_t ble_mwswci_en_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_COEXIFCNTL0_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +__INLINE void ble_mwswci_en_setf(uint8_t mwswcien) +{ + ASSERT_ERR((((uint32_t)mwswcien << 3) & ~((uint32_t)0x00000008)) == 0); + REG_BLE_WR(BLE_COEXIFCNTL0_ADDR, (REG_BLE_RD(BLE_COEXIFCNTL0_ADDR) & ~((uint32_t)0x00000008)) | ((uint32_t)mwswcien << 3)); +} + +__INLINE uint8_t ble_mwscoex_en_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_COEXIFCNTL0_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +__INLINE void ble_mwscoex_en_setf(uint8_t mwscoexen) +{ + ASSERT_ERR((((uint32_t)mwscoexen << 2) & ~((uint32_t)0x00000004)) == 0); + REG_BLE_WR(BLE_COEXIFCNTL0_ADDR, (REG_BLE_RD(BLE_COEXIFCNTL0_ADDR) & ~((uint32_t)0x00000004)) | ((uint32_t)mwscoexen << 2)); +} + +__INLINE uint8_t ble_syncgen_en_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_COEXIFCNTL0_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +__INLINE void ble_syncgen_en_setf(uint8_t syncgenen) +{ + ASSERT_ERR((((uint32_t)syncgenen << 1) & ~((uint32_t)0x00000002)) == 0); + REG_BLE_WR(BLE_COEXIFCNTL0_ADDR, (REG_BLE_RD(BLE_COEXIFCNTL0_ADDR) & ~((uint32_t)0x00000002)) | ((uint32_t)syncgenen << 1)); +} + +__INLINE uint8_t ble_wlancoex_en_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_COEXIFCNTL0_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +__INLINE void ble_wlancoex_en_setf(uint8_t wlancoexen) +{ + ASSERT_ERR((((uint32_t)wlancoexen << 0) & ~((uint32_t)0x00000001)) == 0); + REG_BLE_WR(BLE_COEXIFCNTL0_ADDR, (REG_BLE_RD(BLE_COEXIFCNTL0_ADDR) & ~((uint32_t)0x00000001)) | ((uint32_t)wlancoexen << 0)); +} + +/** + * @brief COEXIFCNTL1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  28:24            WLCPRXTHR   0x0
+ *  20:16            WLCPTXTHR   0x0
+ *  14:08         WLCPDURATION   0x0
+ *  06:00            WLCPDELAY   0x0
+ * 
+ */ +#define BLE_COEXIFCNTL1_ADDR 0x00810124 +#define BLE_COEXIFCNTL1_OFFSET 0x00000124 +#define BLE_COEXIFCNTL1_INDEX 0x00000049 +#define BLE_COEXIFCNTL1_RESET 0x00000000 + +__INLINE uint32_t ble_coexifcntl1_get(void) +{ + return REG_BLE_RD(BLE_COEXIFCNTL1_ADDR); +} + +__INLINE void ble_coexifcntl1_set(uint32_t value) +{ + REG_BLE_WR(BLE_COEXIFCNTL1_ADDR, value); +} + +// field definitions +#define BLE_WLCPRXTHR_MASK ((uint32_t)0x1F000000) +#define BLE_WLCPRXTHR_LSB 24 +#define BLE_WLCPRXTHR_WIDTH ((uint32_t)0x00000005) +#define BLE_WLCPTXTHR_MASK ((uint32_t)0x001F0000) +#define BLE_WLCPTXTHR_LSB 16 +#define BLE_WLCPTXTHR_WIDTH ((uint32_t)0x00000005) +#define BLE_WLCPDURATION_MASK ((uint32_t)0x00007F00) +#define BLE_WLCPDURATION_LSB 8 +#define BLE_WLCPDURATION_WIDTH ((uint32_t)0x00000007) +#define BLE_WLCPDELAY_MASK ((uint32_t)0x0000007F) +#define BLE_WLCPDELAY_LSB 0 +#define BLE_WLCPDELAY_WIDTH ((uint32_t)0x00000007) + +#define BLE_WLCPRXTHR_RST 0x0 +#define BLE_WLCPTXTHR_RST 0x0 +#define BLE_WLCPDURATION_RST 0x0 +#define BLE_WLCPDELAY_RST 0x0 + +__INLINE void ble_coexifcntl1_pack(uint8_t wlcprxthr, uint8_t wlcptxthr, uint8_t wlcpduration, uint8_t wlcpdelay) +{ + ASSERT_ERR((((uint32_t)wlcprxthr << 24) & ~((uint32_t)0x1F000000)) == 0); + ASSERT_ERR((((uint32_t)wlcptxthr << 16) & ~((uint32_t)0x001F0000)) == 0); + ASSERT_ERR((((uint32_t)wlcpduration << 8) & ~((uint32_t)0x00007F00)) == 0); + ASSERT_ERR((((uint32_t)wlcpdelay << 0) & ~((uint32_t)0x0000007F)) == 0); + REG_BLE_WR(BLE_COEXIFCNTL1_ADDR, ((uint32_t)wlcprxthr << 24) | ((uint32_t)wlcptxthr << 16) | ((uint32_t)wlcpduration << 8) | ((uint32_t)wlcpdelay << 0)); +} + +__INLINE void ble_coexifcntl1_unpack(uint8_t* wlcprxthr, uint8_t* wlcptxthr, uint8_t* wlcpduration, uint8_t* wlcpdelay) +{ + uint32_t localVal = REG_BLE_RD(BLE_COEXIFCNTL1_ADDR); + + *wlcprxthr = (localVal & ((uint32_t)0x1F000000)) >> 24; + *wlcptxthr = (localVal & ((uint32_t)0x001F0000)) >> 16; + *wlcpduration = (localVal & ((uint32_t)0x00007F00)) >> 8; + *wlcpdelay = (localVal & ((uint32_t)0x0000007F)) >> 0; +} + +__INLINE uint8_t ble_wlcprxthr_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_COEXIFCNTL1_ADDR); + return ((localVal & ((uint32_t)0x1F000000)) >> 24); +} + +__INLINE void ble_wlcprxthr_setf(uint8_t wlcprxthr) +{ + ASSERT_ERR((((uint32_t)wlcprxthr << 24) & ~((uint32_t)0x1F000000)) == 0); + REG_BLE_WR(BLE_COEXIFCNTL1_ADDR, (REG_BLE_RD(BLE_COEXIFCNTL1_ADDR) & ~((uint32_t)0x1F000000)) | ((uint32_t)wlcprxthr << 24)); +} + +__INLINE uint8_t ble_wlcptxthr_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_COEXIFCNTL1_ADDR); + return ((localVal & ((uint32_t)0x001F0000)) >> 16); +} + +__INLINE void ble_wlcptxthr_setf(uint8_t wlcptxthr) +{ + ASSERT_ERR((((uint32_t)wlcptxthr << 16) & ~((uint32_t)0x001F0000)) == 0); + REG_BLE_WR(BLE_COEXIFCNTL1_ADDR, (REG_BLE_RD(BLE_COEXIFCNTL1_ADDR) & ~((uint32_t)0x001F0000)) | ((uint32_t)wlcptxthr << 16)); +} + +__INLINE uint8_t ble_wlcpduration_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_COEXIFCNTL1_ADDR); + return ((localVal & ((uint32_t)0x00007F00)) >> 8); +} + +__INLINE void ble_wlcpduration_setf(uint8_t wlcpduration) +{ + ASSERT_ERR((((uint32_t)wlcpduration << 8) & ~((uint32_t)0x00007F00)) == 0); + REG_BLE_WR(BLE_COEXIFCNTL1_ADDR, (REG_BLE_RD(BLE_COEXIFCNTL1_ADDR) & ~((uint32_t)0x00007F00)) | ((uint32_t)wlcpduration << 8)); +} + +__INLINE uint8_t ble_wlcpdelay_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_COEXIFCNTL1_ADDR); + return ((localVal & ((uint32_t)0x0000007F)) >> 0); +} + +__INLINE void ble_wlcpdelay_setf(uint8_t wlcpdelay) +{ + ASSERT_ERR((((uint32_t)wlcpdelay << 0) & ~((uint32_t)0x0000007F)) == 0); + REG_BLE_WR(BLE_COEXIFCNTL1_ADDR, (REG_BLE_RD(BLE_COEXIFCNTL1_ADDR) & ~((uint32_t)0x0000007F)) | ((uint32_t)wlcpdelay << 0)); +} + +/** + * @brief COEXIFCNTL2 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  11:08         RX_ANT_DELAY   0x0
+ *  03:00         TX_ANT_DELAY   0x0
+ * 
+ */ +#define BLE_COEXIFCNTL2_ADDR 0x00810128 +#define BLE_COEXIFCNTL2_OFFSET 0x00000128 +#define BLE_COEXIFCNTL2_INDEX 0x0000004A +#define BLE_COEXIFCNTL2_RESET 0x00000000 + +__INLINE uint32_t ble_coexifcntl2_get(void) +{ + return REG_BLE_RD(BLE_COEXIFCNTL2_ADDR); +} + +__INLINE void ble_coexifcntl2_set(uint32_t value) +{ + REG_BLE_WR(BLE_COEXIFCNTL2_ADDR, value); +} + +// field definitions +#define BLE_RX_ANT_DELAY_MASK ((uint32_t)0x00000F00) +#define BLE_RX_ANT_DELAY_LSB 8 +#define BLE_RX_ANT_DELAY_WIDTH ((uint32_t)0x00000004) +#define BLE_TX_ANT_DELAY_MASK ((uint32_t)0x0000000F) +#define BLE_TX_ANT_DELAY_LSB 0 +#define BLE_TX_ANT_DELAY_WIDTH ((uint32_t)0x00000004) + +#define BLE_RX_ANT_DELAY_RST 0x0 +#define BLE_TX_ANT_DELAY_RST 0x0 + +__INLINE void ble_coexifcntl2_pack(uint8_t rxantdelay, uint8_t txantdelay) +{ + ASSERT_ERR((((uint32_t)rxantdelay << 8) & ~((uint32_t)0x00000F00)) == 0); + ASSERT_ERR((((uint32_t)txantdelay << 0) & ~((uint32_t)0x0000000F)) == 0); + REG_BLE_WR(BLE_COEXIFCNTL2_ADDR, ((uint32_t)rxantdelay << 8) | ((uint32_t)txantdelay << 0)); +} + +__INLINE void ble_coexifcntl2_unpack(uint8_t* rxantdelay, uint8_t* txantdelay) +{ + uint32_t localVal = REG_BLE_RD(BLE_COEXIFCNTL2_ADDR); + + *rxantdelay = (localVal & ((uint32_t)0x00000F00)) >> 8; + *txantdelay = (localVal & ((uint32_t)0x0000000F)) >> 0; +} + +__INLINE uint8_t ble_rx_ant_delay_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_COEXIFCNTL2_ADDR); + return ((localVal & ((uint32_t)0x00000F00)) >> 8); +} + +__INLINE void ble_rx_ant_delay_setf(uint8_t rxantdelay) +{ + ASSERT_ERR((((uint32_t)rxantdelay << 8) & ~((uint32_t)0x00000F00)) == 0); + REG_BLE_WR(BLE_COEXIFCNTL2_ADDR, (REG_BLE_RD(BLE_COEXIFCNTL2_ADDR) & ~((uint32_t)0x00000F00)) | ((uint32_t)rxantdelay << 8)); +} + +__INLINE uint8_t ble_tx_ant_delay_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_COEXIFCNTL2_ADDR); + return ((localVal & ((uint32_t)0x0000000F)) >> 0); +} + +__INLINE void ble_tx_ant_delay_setf(uint8_t txantdelay) +{ + ASSERT_ERR((((uint32_t)txantdelay << 0) & ~((uint32_t)0x0000000F)) == 0); + REG_BLE_WR(BLE_COEXIFCNTL2_ADDR, (REG_BLE_RD(BLE_COEXIFCNTL2_ADDR) & ~((uint32_t)0x0000000F)) | ((uint32_t)txantdelay << 0)); +} + +/** + * @brief BLEMPRIO0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:28                BLEM7   0x3
+ *  27:24                BLEM6   0x4
+ *  23:20                BLEM5   0x8
+ *  19:16                BLEM4   0x9
+ *  15:12                BLEM3   0xA
+ *  11:08                BLEM2   0xD
+ *  07:04                BLEM1   0xE
+ *  03:00                BLEM0   0xF
+ * 
+ */ +#define BLE_BLEMPRIO0_ADDR 0x0081012C +#define BLE_BLEMPRIO0_OFFSET 0x0000012C +#define BLE_BLEMPRIO0_INDEX 0x0000004B +#define BLE_BLEMPRIO0_RESET 0x3489ADEF + +__INLINE uint32_t ble_blemprio0_get(void) +{ + return REG_BLE_RD(BLE_BLEMPRIO0_ADDR); +} + +__INLINE void ble_blemprio0_set(uint32_t value) +{ + REG_BLE_WR(BLE_BLEMPRIO0_ADDR, value); +} + +// field definitions +#define BLE_BLEM7_MASK ((uint32_t)0xF0000000) +#define BLE_BLEM7_LSB 28 +#define BLE_BLEM7_WIDTH ((uint32_t)0x00000004) +#define BLE_BLEM6_MASK ((uint32_t)0x0F000000) +#define BLE_BLEM6_LSB 24 +#define BLE_BLEM6_WIDTH ((uint32_t)0x00000004) +#define BLE_BLEM5_MASK ((uint32_t)0x00F00000) +#define BLE_BLEM5_LSB 20 +#define BLE_BLEM5_WIDTH ((uint32_t)0x00000004) +#define BLE_BLEM4_MASK ((uint32_t)0x000F0000) +#define BLE_BLEM4_LSB 16 +#define BLE_BLEM4_WIDTH ((uint32_t)0x00000004) +#define BLE_BLEM3_MASK ((uint32_t)0x0000F000) +#define BLE_BLEM3_LSB 12 +#define BLE_BLEM3_WIDTH ((uint32_t)0x00000004) +#define BLE_BLEM2_MASK ((uint32_t)0x00000F00) +#define BLE_BLEM2_LSB 8 +#define BLE_BLEM2_WIDTH ((uint32_t)0x00000004) +#define BLE_BLEM1_MASK ((uint32_t)0x000000F0) +#define BLE_BLEM1_LSB 4 +#define BLE_BLEM1_WIDTH ((uint32_t)0x00000004) +#define BLE_BLEM0_MASK ((uint32_t)0x0000000F) +#define BLE_BLEM0_LSB 0 +#define BLE_BLEM0_WIDTH ((uint32_t)0x00000004) + +#define BLE_BLEM7_RST 0x3 +#define BLE_BLEM6_RST 0x4 +#define BLE_BLEM5_RST 0x8 +#define BLE_BLEM4_RST 0x9 +#define BLE_BLEM3_RST 0xA +#define BLE_BLEM2_RST 0xD +#define BLE_BLEM1_RST 0xE +#define BLE_BLEM0_RST 0xF + +__INLINE void ble_blemprio0_pack(uint8_t blem7, uint8_t blem6, uint8_t blem5, uint8_t blem4, uint8_t blem3, uint8_t blem2, uint8_t blem1, uint8_t blem0) +{ + ASSERT_ERR((((uint32_t)blem7 << 28) & ~((uint32_t)0xF0000000)) == 0); + ASSERT_ERR((((uint32_t)blem6 << 24) & ~((uint32_t)0x0F000000)) == 0); + ASSERT_ERR((((uint32_t)blem5 << 20) & ~((uint32_t)0x00F00000)) == 0); + ASSERT_ERR((((uint32_t)blem4 << 16) & ~((uint32_t)0x000F0000)) == 0); + ASSERT_ERR((((uint32_t)blem3 << 12) & ~((uint32_t)0x0000F000)) == 0); + ASSERT_ERR((((uint32_t)blem2 << 8) & ~((uint32_t)0x00000F00)) == 0); + ASSERT_ERR((((uint32_t)blem1 << 4) & ~((uint32_t)0x000000F0)) == 0); + ASSERT_ERR((((uint32_t)blem0 << 0) & ~((uint32_t)0x0000000F)) == 0); + REG_BLE_WR(BLE_BLEMPRIO0_ADDR, ((uint32_t)blem7 << 28) | ((uint32_t)blem6 << 24) | ((uint32_t)blem5 << 20) | ((uint32_t)blem4 << 16) | ((uint32_t)blem3 << 12) | ((uint32_t)blem2 << 8) | ((uint32_t)blem1 << 4) | ((uint32_t)blem0 << 0)); +} + +__INLINE void ble_blemprio0_unpack(uint8_t* blem7, uint8_t* blem6, uint8_t* blem5, uint8_t* blem4, uint8_t* blem3, uint8_t* blem2, uint8_t* blem1, uint8_t* blem0) +{ + uint32_t localVal = REG_BLE_RD(BLE_BLEMPRIO0_ADDR); + + *blem7 = (localVal & ((uint32_t)0xF0000000)) >> 28; + *blem6 = (localVal & ((uint32_t)0x0F000000)) >> 24; + *blem5 = (localVal & ((uint32_t)0x00F00000)) >> 20; + *blem4 = (localVal & ((uint32_t)0x000F0000)) >> 16; + *blem3 = (localVal & ((uint32_t)0x0000F000)) >> 12; + *blem2 = (localVal & ((uint32_t)0x00000F00)) >> 8; + *blem1 = (localVal & ((uint32_t)0x000000F0)) >> 4; + *blem0 = (localVal & ((uint32_t)0x0000000F)) >> 0; +} + +__INLINE uint8_t ble_blem7_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_BLEMPRIO0_ADDR); + return ((localVal & ((uint32_t)0xF0000000)) >> 28); +} + +__INLINE void ble_blem7_setf(uint8_t blem7) +{ + ASSERT_ERR((((uint32_t)blem7 << 28) & ~((uint32_t)0xF0000000)) == 0); + REG_BLE_WR(BLE_BLEMPRIO0_ADDR, (REG_BLE_RD(BLE_BLEMPRIO0_ADDR) & ~((uint32_t)0xF0000000)) | ((uint32_t)blem7 << 28)); +} + +__INLINE uint8_t ble_blem6_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_BLEMPRIO0_ADDR); + return ((localVal & ((uint32_t)0x0F000000)) >> 24); +} + +__INLINE void ble_blem6_setf(uint8_t blem6) +{ + ASSERT_ERR((((uint32_t)blem6 << 24) & ~((uint32_t)0x0F000000)) == 0); + REG_BLE_WR(BLE_BLEMPRIO0_ADDR, (REG_BLE_RD(BLE_BLEMPRIO0_ADDR) & ~((uint32_t)0x0F000000)) | ((uint32_t)blem6 << 24)); +} + +__INLINE uint8_t ble_blem5_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_BLEMPRIO0_ADDR); + return ((localVal & ((uint32_t)0x00F00000)) >> 20); +} + +__INLINE void ble_blem5_setf(uint8_t blem5) +{ + ASSERT_ERR((((uint32_t)blem5 << 20) & ~((uint32_t)0x00F00000)) == 0); + REG_BLE_WR(BLE_BLEMPRIO0_ADDR, (REG_BLE_RD(BLE_BLEMPRIO0_ADDR) & ~((uint32_t)0x00F00000)) | ((uint32_t)blem5 << 20)); +} + +__INLINE uint8_t ble_blem4_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_BLEMPRIO0_ADDR); + return ((localVal & ((uint32_t)0x000F0000)) >> 16); +} + +__INLINE void ble_blem4_setf(uint8_t blem4) +{ + ASSERT_ERR((((uint32_t)blem4 << 16) & ~((uint32_t)0x000F0000)) == 0); + REG_BLE_WR(BLE_BLEMPRIO0_ADDR, (REG_BLE_RD(BLE_BLEMPRIO0_ADDR) & ~((uint32_t)0x000F0000)) | ((uint32_t)blem4 << 16)); +} + +__INLINE uint8_t ble_blem3_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_BLEMPRIO0_ADDR); + return ((localVal & ((uint32_t)0x0000F000)) >> 12); +} + +__INLINE void ble_blem3_setf(uint8_t blem3) +{ + ASSERT_ERR((((uint32_t)blem3 << 12) & ~((uint32_t)0x0000F000)) == 0); + REG_BLE_WR(BLE_BLEMPRIO0_ADDR, (REG_BLE_RD(BLE_BLEMPRIO0_ADDR) & ~((uint32_t)0x0000F000)) | ((uint32_t)blem3 << 12)); +} + +__INLINE uint8_t ble_blem2_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_BLEMPRIO0_ADDR); + return ((localVal & ((uint32_t)0x00000F00)) >> 8); +} + +__INLINE void ble_blem2_setf(uint8_t blem2) +{ + ASSERT_ERR((((uint32_t)blem2 << 8) & ~((uint32_t)0x00000F00)) == 0); + REG_BLE_WR(BLE_BLEMPRIO0_ADDR, (REG_BLE_RD(BLE_BLEMPRIO0_ADDR) & ~((uint32_t)0x00000F00)) | ((uint32_t)blem2 << 8)); +} + +__INLINE uint8_t ble_blem1_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_BLEMPRIO0_ADDR); + return ((localVal & ((uint32_t)0x000000F0)) >> 4); +} + +__INLINE void ble_blem1_setf(uint8_t blem1) +{ + ASSERT_ERR((((uint32_t)blem1 << 4) & ~((uint32_t)0x000000F0)) == 0); + REG_BLE_WR(BLE_BLEMPRIO0_ADDR, (REG_BLE_RD(BLE_BLEMPRIO0_ADDR) & ~((uint32_t)0x000000F0)) | ((uint32_t)blem1 << 4)); +} + +__INLINE uint8_t ble_blem0_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_BLEMPRIO0_ADDR); + return ((localVal & ((uint32_t)0x0000000F)) >> 0); +} + +__INLINE void ble_blem0_setf(uint8_t blem0) +{ + ASSERT_ERR((((uint32_t)blem0 << 0) & ~((uint32_t)0x0000000F)) == 0); + REG_BLE_WR(BLE_BLEMPRIO0_ADDR, (REG_BLE_RD(BLE_BLEMPRIO0_ADDR) & ~((uint32_t)0x0000000F)) | ((uint32_t)blem0 << 0)); +} + +/** + * @brief BLEMPRIO1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:28          BLEMDEFAULT   0x3
+ *  07:04                BLEM9   0xD
+ *  03:00                BLEM8   0xC
+ * 
+ */ +#define BLE_BLEMPRIO1_ADDR 0x00810130 +#define BLE_BLEMPRIO1_OFFSET 0x00000130 +#define BLE_BLEMPRIO1_INDEX 0x0000004C +#define BLE_BLEMPRIO1_RESET 0x300000DC + +__INLINE uint32_t ble_blemprio1_get(void) +{ + return REG_BLE_RD(BLE_BLEMPRIO1_ADDR); +} + +__INLINE void ble_blemprio1_set(uint32_t value) +{ + REG_BLE_WR(BLE_BLEMPRIO1_ADDR, value); +} + +// field definitions +#define BLE_BLEMDEFAULT_MASK ((uint32_t)0xF0000000) +#define BLE_BLEMDEFAULT_LSB 28 +#define BLE_BLEMDEFAULT_WIDTH ((uint32_t)0x00000004) +#define BLE_BLEM9_MASK ((uint32_t)0x000000F0) +#define BLE_BLEM9_LSB 4 +#define BLE_BLEM9_WIDTH ((uint32_t)0x00000004) +#define BLE_BLEM8_MASK ((uint32_t)0x0000000F) +#define BLE_BLEM8_LSB 0 +#define BLE_BLEM8_WIDTH ((uint32_t)0x00000004) + +#define BLE_BLEMDEFAULT_RST 0x3 +#define BLE_BLEM9_RST 0xD +#define BLE_BLEM8_RST 0xC + +__INLINE void ble_blemprio1_pack(uint8_t blemdefault, uint8_t blem9, uint8_t blem8) +{ + ASSERT_ERR((((uint32_t)blemdefault << 28) & ~((uint32_t)0xF0000000)) == 0); + ASSERT_ERR((((uint32_t)blem9 << 4) & ~((uint32_t)0x000000F0)) == 0); + ASSERT_ERR((((uint32_t)blem8 << 0) & ~((uint32_t)0x0000000F)) == 0); + REG_BLE_WR(BLE_BLEMPRIO1_ADDR, ((uint32_t)blemdefault << 28) | ((uint32_t)blem9 << 4) | ((uint32_t)blem8 << 0)); +} + +__INLINE void ble_blemprio1_unpack(uint8_t* blemdefault, uint8_t* blem9, uint8_t* blem8) +{ + uint32_t localVal = REG_BLE_RD(BLE_BLEMPRIO1_ADDR); + + *blemdefault = (localVal & ((uint32_t)0xF0000000)) >> 28; + *blem9 = (localVal & ((uint32_t)0x000000F0)) >> 4; + *blem8 = (localVal & ((uint32_t)0x0000000F)) >> 0; +} + +__INLINE uint8_t ble_blemdefault_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_BLEMPRIO1_ADDR); + return ((localVal & ((uint32_t)0xF0000000)) >> 28); +} + +__INLINE void ble_blemdefault_setf(uint8_t blemdefault) +{ + ASSERT_ERR((((uint32_t)blemdefault << 28) & ~((uint32_t)0xF0000000)) == 0); + REG_BLE_WR(BLE_BLEMPRIO1_ADDR, (REG_BLE_RD(BLE_BLEMPRIO1_ADDR) & ~((uint32_t)0xF0000000)) | ((uint32_t)blemdefault << 28)); +} + +__INLINE uint8_t ble_blem9_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_BLEMPRIO1_ADDR); + return ((localVal & ((uint32_t)0x000000F0)) >> 4); +} + +__INLINE void ble_blem9_setf(uint8_t blem9) +{ + ASSERT_ERR((((uint32_t)blem9 << 4) & ~((uint32_t)0x000000F0)) == 0); + REG_BLE_WR(BLE_BLEMPRIO1_ADDR, (REG_BLE_RD(BLE_BLEMPRIO1_ADDR) & ~((uint32_t)0x000000F0)) | ((uint32_t)blem9 << 4)); +} + +__INLINE uint8_t ble_blem8_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_BLEMPRIO1_ADDR); + return ((localVal & ((uint32_t)0x0000000F)) >> 0); +} + +__INLINE void ble_blem8_setf(uint8_t blem8) +{ + ASSERT_ERR((((uint32_t)blem8 << 0) & ~((uint32_t)0x0000000F)) == 0); + REG_BLE_WR(BLE_BLEMPRIO1_ADDR, (REG_BLE_RD(BLE_BLEMPRIO1_ADDR) & ~((uint32_t)0x0000000F)) | ((uint32_t)blem8 << 0)); +} + +/** + * @brief RALPTR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00               RALPTR   0x0
+ * 
+ */ +#define BLE_RALPTR_ADDR 0x00810140 +#define BLE_RALPTR_OFFSET 0x00000140 +#define BLE_RALPTR_INDEX 0x00000050 +#define BLE_RALPTR_RESET 0x00000000 + +__INLINE uint32_t ble_ralptr_get(void) +{ + return REG_BLE_RD(BLE_RALPTR_ADDR); +} + +__INLINE void ble_ralptr_set(uint32_t value) +{ + REG_BLE_WR(BLE_RALPTR_ADDR, value); +} + +// field definitions +#define BLE_RALPTR_MASK ((uint32_t)0x0000FFFF) +#define BLE_RALPTR_LSB 0 +#define BLE_RALPTR_WIDTH ((uint32_t)0x00000010) + +#define BLE_RALPTR_RST 0x0 + +__INLINE uint16_t ble_ralptr_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RALPTR_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_ralptr_setf(uint16_t ralptr) +{ + ASSERT_ERR((((uint32_t)ralptr << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_BLE_WR(BLE_RALPTR_ADDR, (uint32_t)ralptr << 0); +} + +/** + * @brief RALNBDEV register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  07:00             NBRALDEV   0x0
+ * 
+ */ +#define BLE_RALNBDEV_ADDR 0x00810144 +#define BLE_RALNBDEV_OFFSET 0x00000144 +#define BLE_RALNBDEV_INDEX 0x00000051 +#define BLE_RALNBDEV_RESET 0x00000000 + +__INLINE uint32_t ble_ralnbdev_get(void) +{ + return REG_BLE_RD(BLE_RALNBDEV_ADDR); +} + +__INLINE void ble_ralnbdev_set(uint32_t value) +{ + REG_BLE_WR(BLE_RALNBDEV_ADDR, value); +} + +// field definitions +#define BLE_NBRALDEV_MASK ((uint32_t)0x000000FF) +#define BLE_NBRALDEV_LSB 0 +#define BLE_NBRALDEV_WIDTH ((uint32_t)0x00000008) + +#define BLE_NBRALDEV_RST 0x0 + +__INLINE uint8_t ble_nbraldev_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RALNBDEV_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x000000FF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_nbraldev_setf(uint8_t nbraldev) +{ + ASSERT_ERR((((uint32_t)nbraldev << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_BLE_WR(BLE_RALNBDEV_ADDR, (uint32_t)nbraldev << 0); +} + +/** + * @brief RAL_LOCAL_RND register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31            LRND_INIT   0
+ *  21:00             LRND_VAL   0x3F0F0F
+ * 
+ */ +#define BLE_RAL_LOCAL_RND_ADDR 0x00810148 +#define BLE_RAL_LOCAL_RND_OFFSET 0x00000148 +#define BLE_RAL_LOCAL_RND_INDEX 0x00000052 +#define BLE_RAL_LOCAL_RND_RESET 0x003F0F0F + +__INLINE uint32_t ble_ral_local_rnd_get(void) +{ + return REG_BLE_RD(BLE_RAL_LOCAL_RND_ADDR); +} + +__INLINE void ble_ral_local_rnd_set(uint32_t value) +{ + REG_BLE_WR(BLE_RAL_LOCAL_RND_ADDR, value); +} + +// field definitions +#define BLE_LRND_INIT_BIT ((uint32_t)0x80000000) +#define BLE_LRND_INIT_POS 31 +#define BLE_LRND_VAL_MASK ((uint32_t)0x003FFFFF) +#define BLE_LRND_VAL_LSB 0 +#define BLE_LRND_VAL_WIDTH ((uint32_t)0x00000016) + +#define BLE_LRND_INIT_RST 0x0 +#define BLE_LRND_VAL_RST 0x3F0F0F + +__INLINE void ble_ral_local_rnd_pack(uint8_t lrndinit, uint32_t lrndval) +{ + ASSERT_ERR((((uint32_t)lrndinit << 31) & ~((uint32_t)0x80000000)) == 0); + ASSERT_ERR((((uint32_t)lrndval << 0) & ~((uint32_t)0x003FFFFF)) == 0); + REG_BLE_WR(BLE_RAL_LOCAL_RND_ADDR, ((uint32_t)lrndinit << 31) | ((uint32_t)lrndval << 0)); +} + +__INLINE void ble_ral_local_rnd_unpack(uint8_t* lrndinit, uint32_t* lrndval) +{ + uint32_t localVal = REG_BLE_RD(BLE_RAL_LOCAL_RND_ADDR); + + *lrndinit = (localVal & ((uint32_t)0x80000000)) >> 31; + *lrndval = (localVal & ((uint32_t)0x003FFFFF)) >> 0; +} + +__INLINE uint8_t ble_lrnd_init_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RAL_LOCAL_RND_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +__INLINE void ble_lrnd_init_setf(uint8_t lrndinit) +{ + ASSERT_ERR((((uint32_t)lrndinit << 31) & ~((uint32_t)0x80000000)) == 0); + REG_BLE_WR(BLE_RAL_LOCAL_RND_ADDR, (REG_BLE_RD(BLE_RAL_LOCAL_RND_ADDR) & ~((uint32_t)0x80000000)) | ((uint32_t)lrndinit << 31)); +} + +__INLINE uint32_t ble_lrnd_val_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RAL_LOCAL_RND_ADDR); + return ((localVal & ((uint32_t)0x003FFFFF)) >> 0); +} + +__INLINE void ble_lrnd_val_setf(uint32_t lrndval) +{ + ASSERT_ERR((((uint32_t)lrndval << 0) & ~((uint32_t)0x003FFFFF)) == 0); + REG_BLE_WR(BLE_RAL_LOCAL_RND_ADDR, (REG_BLE_RD(BLE_RAL_LOCAL_RND_ADDR) & ~((uint32_t)0x003FFFFF)) | ((uint32_t)lrndval << 0)); +} + +/** + * @brief RAL_PEER_RND register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31            PRND_INIT   0
+ *  21:00             PRND_VAL   0x30F0F0
+ * 
+ */ +#define BLE_RAL_PEER_RND_ADDR 0x0081014C +#define BLE_RAL_PEER_RND_OFFSET 0x0000014C +#define BLE_RAL_PEER_RND_INDEX 0x00000053 +#define BLE_RAL_PEER_RND_RESET 0x0030F0F0 + +__INLINE uint32_t ble_ral_peer_rnd_get(void) +{ + return REG_BLE_RD(BLE_RAL_PEER_RND_ADDR); +} + +__INLINE void ble_ral_peer_rnd_set(uint32_t value) +{ + REG_BLE_WR(BLE_RAL_PEER_RND_ADDR, value); +} + +// field definitions +#define BLE_PRND_INIT_BIT ((uint32_t)0x80000000) +#define BLE_PRND_INIT_POS 31 +#define BLE_PRND_VAL_MASK ((uint32_t)0x003FFFFF) +#define BLE_PRND_VAL_LSB 0 +#define BLE_PRND_VAL_WIDTH ((uint32_t)0x00000016) + +#define BLE_PRND_INIT_RST 0x0 +#define BLE_PRND_VAL_RST 0x30F0F0 + +__INLINE void ble_ral_peer_rnd_pack(uint8_t prndinit, uint32_t prndval) +{ + ASSERT_ERR((((uint32_t)prndinit << 31) & ~((uint32_t)0x80000000)) == 0); + ASSERT_ERR((((uint32_t)prndval << 0) & ~((uint32_t)0x003FFFFF)) == 0); + REG_BLE_WR(BLE_RAL_PEER_RND_ADDR, ((uint32_t)prndinit << 31) | ((uint32_t)prndval << 0)); +} + +__INLINE void ble_ral_peer_rnd_unpack(uint8_t* prndinit, uint32_t* prndval) +{ + uint32_t localVal = REG_BLE_RD(BLE_RAL_PEER_RND_ADDR); + + *prndinit = (localVal & ((uint32_t)0x80000000)) >> 31; + *prndval = (localVal & ((uint32_t)0x003FFFFF)) >> 0; +} + +__INLINE uint8_t ble_prnd_init_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RAL_PEER_RND_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +__INLINE void ble_prnd_init_setf(uint8_t prndinit) +{ + ASSERT_ERR((((uint32_t)prndinit << 31) & ~((uint32_t)0x80000000)) == 0); + REG_BLE_WR(BLE_RAL_PEER_RND_ADDR, (REG_BLE_RD(BLE_RAL_PEER_RND_ADDR) & ~((uint32_t)0x80000000)) | ((uint32_t)prndinit << 31)); +} + +__INLINE uint32_t ble_prnd_val_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RAL_PEER_RND_ADDR); + return ((localVal & ((uint32_t)0x003FFFFF)) >> 0); +} + +__INLINE void ble_prnd_val_setf(uint32_t prndval) +{ + ASSERT_ERR((((uint32_t)prndval << 0) & ~((uint32_t)0x003FFFFF)) == 0); + REG_BLE_WR(BLE_RAL_PEER_RND_ADDR, (REG_BLE_RD(BLE_RAL_PEER_RND_ADDR) & ~((uint32_t)0x003FFFFF)) | ((uint32_t)prndval << 0)); +} + +/** + * @brief ISOCHANCNTL0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     04           RETXACKEN0   0
+ *     03             SYNCGEN0   0
+ *     02           ISOCHANEN0   0
+ *  01:00             ISOTYPE0   0x0
+ * 
+ */ +#define BLE_ISOCHANCNTL0_ADDR 0x00810150 +#define BLE_ISOCHANCNTL0_OFFSET 0x00000150 +#define BLE_ISOCHANCNTL0_INDEX 0x00000054 +#define BLE_ISOCHANCNTL0_RESET 0x00000000 + +__INLINE uint32_t ble_isochancntl0_get(void) +{ + return REG_BLE_RD(BLE_ISOCHANCNTL0_ADDR); +} + +__INLINE void ble_isochancntl0_set(uint32_t value) +{ + REG_BLE_WR(BLE_ISOCHANCNTL0_ADDR, value); +} + +// field definitions +#define BLE_RETXACKEN0_BIT ((uint32_t)0x00000010) +#define BLE_RETXACKEN0_POS 4 +#define BLE_SYNCGEN0_BIT ((uint32_t)0x00000008) +#define BLE_SYNCGEN0_POS 3 +#define BLE_ISOCHANEN0_BIT ((uint32_t)0x00000004) +#define BLE_ISOCHANEN0_POS 2 +#define BLE_ISOTYPE0_MASK ((uint32_t)0x00000003) +#define BLE_ISOTYPE0_LSB 0 +#define BLE_ISOTYPE0_WIDTH ((uint32_t)0x00000002) + +#define BLE_RETXACKEN0_RST 0x0 +#define BLE_SYNCGEN0_RST 0x0 +#define BLE_ISOCHANEN0_RST 0x0 +#define BLE_ISOTYPE0_RST 0x0 + +__INLINE void ble_isochancntl0_pack(uint8_t retxacken0, uint8_t syncgen0, uint8_t isochanen0, uint8_t isotype0) +{ + ASSERT_ERR((((uint32_t)retxacken0 << 4) & ~((uint32_t)0x00000010)) == 0); + ASSERT_ERR((((uint32_t)syncgen0 << 3) & ~((uint32_t)0x00000008)) == 0); + ASSERT_ERR((((uint32_t)isochanen0 << 2) & ~((uint32_t)0x00000004)) == 0); + ASSERT_ERR((((uint32_t)isotype0 << 0) & ~((uint32_t)0x00000003)) == 0); + REG_BLE_WR(BLE_ISOCHANCNTL0_ADDR, ((uint32_t)retxacken0 << 4) | ((uint32_t)syncgen0 << 3) | ((uint32_t)isochanen0 << 2) | ((uint32_t)isotype0 << 0)); +} + +__INLINE void ble_isochancntl0_unpack(uint8_t* retxacken0, uint8_t* syncgen0, uint8_t* isochanen0, uint8_t* isotype0) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOCHANCNTL0_ADDR); + + *retxacken0 = (localVal & ((uint32_t)0x00000010)) >> 4; + *syncgen0 = (localVal & ((uint32_t)0x00000008)) >> 3; + *isochanen0 = (localVal & ((uint32_t)0x00000004)) >> 2; + *isotype0 = (localVal & ((uint32_t)0x00000003)) >> 0; +} + +__INLINE uint8_t ble_retxacken0_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOCHANCNTL0_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +__INLINE void ble_retxacken0_setf(uint8_t retxacken0) +{ + ASSERT_ERR((((uint32_t)retxacken0 << 4) & ~((uint32_t)0x00000010)) == 0); + REG_BLE_WR(BLE_ISOCHANCNTL0_ADDR, (REG_BLE_RD(BLE_ISOCHANCNTL0_ADDR) & ~((uint32_t)0x00000010)) | ((uint32_t)retxacken0 << 4)); +} + +__INLINE uint8_t ble_syncgen0_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOCHANCNTL0_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +__INLINE void ble_syncgen0_setf(uint8_t syncgen0) +{ + ASSERT_ERR((((uint32_t)syncgen0 << 3) & ~((uint32_t)0x00000008)) == 0); + REG_BLE_WR(BLE_ISOCHANCNTL0_ADDR, (REG_BLE_RD(BLE_ISOCHANCNTL0_ADDR) & ~((uint32_t)0x00000008)) | ((uint32_t)syncgen0 << 3)); +} + +__INLINE uint8_t ble_isochanen0_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOCHANCNTL0_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +__INLINE void ble_isochanen0_setf(uint8_t isochanen0) +{ + ASSERT_ERR((((uint32_t)isochanen0 << 2) & ~((uint32_t)0x00000004)) == 0); + REG_BLE_WR(BLE_ISOCHANCNTL0_ADDR, (REG_BLE_RD(BLE_ISOCHANCNTL0_ADDR) & ~((uint32_t)0x00000004)) | ((uint32_t)isochanen0 << 2)); +} + +__INLINE uint8_t ble_isotype0_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOCHANCNTL0_ADDR); + return ((localVal & ((uint32_t)0x00000003)) >> 0); +} + +__INLINE void ble_isotype0_setf(uint8_t isotype0) +{ + ASSERT_ERR((((uint32_t)isotype0 << 0) & ~((uint32_t)0x00000003)) == 0); + REG_BLE_WR(BLE_ISOCHANCNTL0_ADDR, (REG_BLE_RD(BLE_ISOCHANCNTL0_ADDR) & ~((uint32_t)0x00000003)) | ((uint32_t)isotype0 << 0)); +} + +/** + * @brief ISOMUTECNTL0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31                 TOG0   0
+ *     19           MUTE_SINK0   0
+ *     18         MUTE_SOURCE0   0
+ *     17              INVL0_1   1
+ *     16              INVL0_0   1
+ *  07:00        MUTE_PATTERN0   0x0
+ * 
+ */ +#define BLE_ISOMUTECNTL0_ADDR 0x00810154 +#define BLE_ISOMUTECNTL0_OFFSET 0x00000154 +#define BLE_ISOMUTECNTL0_INDEX 0x00000055 +#define BLE_ISOMUTECNTL0_RESET 0x00030000 + +__INLINE uint32_t ble_isomutecntl0_get(void) +{ + return REG_BLE_RD(BLE_ISOMUTECNTL0_ADDR); +} + +__INLINE void ble_isomutecntl0_set(uint32_t value) +{ + REG_BLE_WR(BLE_ISOMUTECNTL0_ADDR, value); +} + +// field definitions +#define BLE_TOG0_BIT ((uint32_t)0x80000000) +#define BLE_TOG0_POS 31 +#define BLE_MUTE_SINK0_BIT ((uint32_t)0x00080000) +#define BLE_MUTE_SINK0_POS 19 +#define BLE_MUTE_SOURCE0_BIT ((uint32_t)0x00040000) +#define BLE_MUTE_SOURCE0_POS 18 +#define BLE_INVL0_1_BIT ((uint32_t)0x00020000) +#define BLE_INVL0_1_POS 17 +#define BLE_INVL0_0_BIT ((uint32_t)0x00010000) +#define BLE_INVL0_0_POS 16 +#define BLE_MUTE_PATTERN0_MASK ((uint32_t)0x000000FF) +#define BLE_MUTE_PATTERN0_LSB 0 +#define BLE_MUTE_PATTERN0_WIDTH ((uint32_t)0x00000008) + +#define BLE_TOG0_RST 0x0 +#define BLE_MUTE_SINK0_RST 0x0 +#define BLE_MUTE_SOURCE0_RST 0x0 +#define BLE_INVL0_1_RST 0x1 +#define BLE_INVL0_0_RST 0x1 +#define BLE_MUTE_PATTERN0_RST 0x0 + +__INLINE void ble_isomutecntl0_pack(uint8_t mutesink0, uint8_t mutesource0, uint8_t invl01, uint8_t invl00, uint8_t mutepattern0) +{ + ASSERT_ERR((((uint32_t)mutesink0 << 19) & ~((uint32_t)0x00080000)) == 0); + ASSERT_ERR((((uint32_t)mutesource0 << 18) & ~((uint32_t)0x00040000)) == 0); + ASSERT_ERR((((uint32_t)invl01 << 17) & ~((uint32_t)0x00020000)) == 0); + ASSERT_ERR((((uint32_t)invl00 << 16) & ~((uint32_t)0x00010000)) == 0); + ASSERT_ERR((((uint32_t)mutepattern0 << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_BLE_WR(BLE_ISOMUTECNTL0_ADDR, ((uint32_t)mutesink0 << 19) | ((uint32_t)mutesource0 << 18) | ((uint32_t)invl01 << 17) | ((uint32_t)invl00 << 16) | ((uint32_t)mutepattern0 << 0)); +} + +__INLINE void ble_isomutecntl0_unpack(uint8_t* tog0, uint8_t* mutesink0, uint8_t* mutesource0, uint8_t* invl01, uint8_t* invl00, uint8_t* mutepattern0) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOMUTECNTL0_ADDR); + + *tog0 = (localVal & ((uint32_t)0x80000000)) >> 31; + *mutesink0 = (localVal & ((uint32_t)0x00080000)) >> 19; + *mutesource0 = (localVal & ((uint32_t)0x00040000)) >> 18; + *invl01 = (localVal & ((uint32_t)0x00020000)) >> 17; + *invl00 = (localVal & ((uint32_t)0x00010000)) >> 16; + *mutepattern0 = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +__INLINE uint8_t ble_tog0_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOMUTECNTL0_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +__INLINE uint8_t ble_mute_sink0_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOMUTECNTL0_ADDR); + return ((localVal & ((uint32_t)0x00080000)) >> 19); +} + +__INLINE void ble_mute_sink0_setf(uint8_t mutesink0) +{ + ASSERT_ERR((((uint32_t)mutesink0 << 19) & ~((uint32_t)0x00080000)) == 0); + REG_BLE_WR(BLE_ISOMUTECNTL0_ADDR, (REG_BLE_RD(BLE_ISOMUTECNTL0_ADDR) & ~((uint32_t)0x00080000)) | ((uint32_t)mutesink0 << 19)); +} + +__INLINE uint8_t ble_mute_source0_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOMUTECNTL0_ADDR); + return ((localVal & ((uint32_t)0x00040000)) >> 18); +} + +__INLINE void ble_mute_source0_setf(uint8_t mutesource0) +{ + ASSERT_ERR((((uint32_t)mutesource0 << 18) & ~((uint32_t)0x00040000)) == 0); + REG_BLE_WR(BLE_ISOMUTECNTL0_ADDR, (REG_BLE_RD(BLE_ISOMUTECNTL0_ADDR) & ~((uint32_t)0x00040000)) | ((uint32_t)mutesource0 << 18)); +} + +__INLINE uint8_t ble_invl0_1_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOMUTECNTL0_ADDR); + return ((localVal & ((uint32_t)0x00020000)) >> 17); +} + +__INLINE void ble_invl0_1_setf(uint8_t invl01) +{ + ASSERT_ERR((((uint32_t)invl01 << 17) & ~((uint32_t)0x00020000)) == 0); + REG_BLE_WR(BLE_ISOMUTECNTL0_ADDR, (REG_BLE_RD(BLE_ISOMUTECNTL0_ADDR) & ~((uint32_t)0x00020000)) | ((uint32_t)invl01 << 17)); +} + +__INLINE uint8_t ble_invl0_0_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOMUTECNTL0_ADDR); + return ((localVal & ((uint32_t)0x00010000)) >> 16); +} + +__INLINE void ble_invl0_0_setf(uint8_t invl00) +{ + ASSERT_ERR((((uint32_t)invl00 << 16) & ~((uint32_t)0x00010000)) == 0); + REG_BLE_WR(BLE_ISOMUTECNTL0_ADDR, (REG_BLE_RD(BLE_ISOMUTECNTL0_ADDR) & ~((uint32_t)0x00010000)) | ((uint32_t)invl00 << 16)); +} + +__INLINE uint8_t ble_mute_pattern0_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOMUTECNTL0_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +__INLINE void ble_mute_pattern0_setf(uint8_t mutepattern0) +{ + ASSERT_ERR((((uint32_t)mutepattern0 << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_BLE_WR(BLE_ISOMUTECNTL0_ADDR, (REG_BLE_RD(BLE_ISOMUTECNTL0_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)mutepattern0 << 0)); +} + +/** + * @brief ISOCURRENTTXPTR0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:16           ISO0TXPTR1   0x0
+ *  15:00           ISO0TXPTR0   0x0
+ * 
+ */ +#define BLE_ISOCURRENTTXPTR0_ADDR 0x00810158 +#define BLE_ISOCURRENTTXPTR0_OFFSET 0x00000158 +#define BLE_ISOCURRENTTXPTR0_INDEX 0x00000056 +#define BLE_ISOCURRENTTXPTR0_RESET 0x00000000 + +__INLINE uint32_t ble_isocurrenttxptr0_get(void) +{ + return REG_BLE_RD(BLE_ISOCURRENTTXPTR0_ADDR); +} + +__INLINE void ble_isocurrenttxptr0_set(uint32_t value) +{ + REG_BLE_WR(BLE_ISOCURRENTTXPTR0_ADDR, value); +} + +// field definitions +#define BLE_ISO0TXPTR1_MASK ((uint32_t)0xFFFF0000) +#define BLE_ISO0TXPTR1_LSB 16 +#define BLE_ISO0TXPTR1_WIDTH ((uint32_t)0x00000010) +#define BLE_ISO0TXPTR0_MASK ((uint32_t)0x0000FFFF) +#define BLE_ISO0TXPTR0_LSB 0 +#define BLE_ISO0TXPTR0_WIDTH ((uint32_t)0x00000010) + +#define BLE_ISO0TXPTR1_RST 0x0 +#define BLE_ISO0TXPTR0_RST 0x0 + +__INLINE void ble_isocurrenttxptr0_pack(uint16_t iso0txptr1, uint16_t iso0txptr0) +{ + ASSERT_ERR((((uint32_t)iso0txptr1 << 16) & ~((uint32_t)0xFFFF0000)) == 0); + ASSERT_ERR((((uint32_t)iso0txptr0 << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_BLE_WR(BLE_ISOCURRENTTXPTR0_ADDR, ((uint32_t)iso0txptr1 << 16) | ((uint32_t)iso0txptr0 << 0)); +} + +__INLINE void ble_isocurrenttxptr0_unpack(uint16_t* iso0txptr1, uint16_t* iso0txptr0) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOCURRENTTXPTR0_ADDR); + + *iso0txptr1 = (localVal & ((uint32_t)0xFFFF0000)) >> 16; + *iso0txptr0 = (localVal & ((uint32_t)0x0000FFFF)) >> 0; +} + +__INLINE uint16_t ble_iso0txptr1_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOCURRENTTXPTR0_ADDR); + return ((localVal & ((uint32_t)0xFFFF0000)) >> 16); +} + +__INLINE void ble_iso0txptr1_setf(uint16_t iso0txptr1) +{ + ASSERT_ERR((((uint32_t)iso0txptr1 << 16) & ~((uint32_t)0xFFFF0000)) == 0); + REG_BLE_WR(BLE_ISOCURRENTTXPTR0_ADDR, (REG_BLE_RD(BLE_ISOCURRENTTXPTR0_ADDR) & ~((uint32_t)0xFFFF0000)) | ((uint32_t)iso0txptr1 << 16)); +} + +__INLINE uint16_t ble_iso0txptr0_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOCURRENTTXPTR0_ADDR); + return ((localVal & ((uint32_t)0x0000FFFF)) >> 0); +} + +__INLINE void ble_iso0txptr0_setf(uint16_t iso0txptr0) +{ + ASSERT_ERR((((uint32_t)iso0txptr0 << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_BLE_WR(BLE_ISOCURRENTTXPTR0_ADDR, (REG_BLE_RD(BLE_ISOCURRENTTXPTR0_ADDR) & ~((uint32_t)0x0000FFFF)) | ((uint32_t)iso0txptr0 << 0)); +} + +/** + * @brief ISOCURRENTRXPTR0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:16           ISO0RXPTR1   0x0
+ *  15:00           ISO0RXPTR0   0x0
+ * 
+ */ +#define BLE_ISOCURRENTRXPTR0_ADDR 0x0081015C +#define BLE_ISOCURRENTRXPTR0_OFFSET 0x0000015C +#define BLE_ISOCURRENTRXPTR0_INDEX 0x00000057 +#define BLE_ISOCURRENTRXPTR0_RESET 0x00000000 + +__INLINE uint32_t ble_isocurrentrxptr0_get(void) +{ + return REG_BLE_RD(BLE_ISOCURRENTRXPTR0_ADDR); +} + +__INLINE void ble_isocurrentrxptr0_set(uint32_t value) +{ + REG_BLE_WR(BLE_ISOCURRENTRXPTR0_ADDR, value); +} + +// field definitions +#define BLE_ISO0RXPTR1_MASK ((uint32_t)0xFFFF0000) +#define BLE_ISO0RXPTR1_LSB 16 +#define BLE_ISO0RXPTR1_WIDTH ((uint32_t)0x00000010) +#define BLE_ISO0RXPTR0_MASK ((uint32_t)0x0000FFFF) +#define BLE_ISO0RXPTR0_LSB 0 +#define BLE_ISO0RXPTR0_WIDTH ((uint32_t)0x00000010) + +#define BLE_ISO0RXPTR1_RST 0x0 +#define BLE_ISO0RXPTR0_RST 0x0 + +__INLINE void ble_isocurrentrxptr0_pack(uint16_t iso0rxptr1, uint16_t iso0rxptr0) +{ + ASSERT_ERR((((uint32_t)iso0rxptr1 << 16) & ~((uint32_t)0xFFFF0000)) == 0); + ASSERT_ERR((((uint32_t)iso0rxptr0 << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_BLE_WR(BLE_ISOCURRENTRXPTR0_ADDR, ((uint32_t)iso0rxptr1 << 16) | ((uint32_t)iso0rxptr0 << 0)); +} + +__INLINE void ble_isocurrentrxptr0_unpack(uint16_t* iso0rxptr1, uint16_t* iso0rxptr0) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOCURRENTRXPTR0_ADDR); + + *iso0rxptr1 = (localVal & ((uint32_t)0xFFFF0000)) >> 16; + *iso0rxptr0 = (localVal & ((uint32_t)0x0000FFFF)) >> 0; +} + +__INLINE uint16_t ble_iso0rxptr1_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOCURRENTRXPTR0_ADDR); + return ((localVal & ((uint32_t)0xFFFF0000)) >> 16); +} + +__INLINE void ble_iso0rxptr1_setf(uint16_t iso0rxptr1) +{ + ASSERT_ERR((((uint32_t)iso0rxptr1 << 16) & ~((uint32_t)0xFFFF0000)) == 0); + REG_BLE_WR(BLE_ISOCURRENTRXPTR0_ADDR, (REG_BLE_RD(BLE_ISOCURRENTRXPTR0_ADDR) & ~((uint32_t)0xFFFF0000)) | ((uint32_t)iso0rxptr1 << 16)); +} + +__INLINE uint16_t ble_iso0rxptr0_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOCURRENTRXPTR0_ADDR); + return ((localVal & ((uint32_t)0x0000FFFF)) >> 0); +} + +__INLINE void ble_iso0rxptr0_setf(uint16_t iso0rxptr0) +{ + ASSERT_ERR((((uint32_t)iso0rxptr0 << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_BLE_WR(BLE_ISOCURRENTRXPTR0_ADDR, (REG_BLE_RD(BLE_ISOCURRENTRXPTR0_ADDR) & ~((uint32_t)0x0000FFFF)) | ((uint32_t)iso0rxptr0 << 0)); +} + +/** + * @brief ISOTRCNTL0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  23:16            ISO0RXLEN   0x0
+ *  07:00            ISO0TXLEN   0x0
+ * 
+ */ +#define BLE_ISOTRCNTL0_ADDR 0x00810160 +#define BLE_ISOTRCNTL0_OFFSET 0x00000160 +#define BLE_ISOTRCNTL0_INDEX 0x00000058 +#define BLE_ISOTRCNTL0_RESET 0x00000000 + +__INLINE uint32_t ble_isotrcntl0_get(void) +{ + return REG_BLE_RD(BLE_ISOTRCNTL0_ADDR); +} + +__INLINE void ble_isotrcntl0_set(uint32_t value) +{ + REG_BLE_WR(BLE_ISOTRCNTL0_ADDR, value); +} + +// field definitions +#define BLE_ISO0RXLEN_MASK ((uint32_t)0x00FF0000) +#define BLE_ISO0RXLEN_LSB 16 +#define BLE_ISO0RXLEN_WIDTH ((uint32_t)0x00000008) +#define BLE_ISO0TXLEN_MASK ((uint32_t)0x000000FF) +#define BLE_ISO0TXLEN_LSB 0 +#define BLE_ISO0TXLEN_WIDTH ((uint32_t)0x00000008) + +#define BLE_ISO0RXLEN_RST 0x0 +#define BLE_ISO0TXLEN_RST 0x0 + +__INLINE void ble_isotrcntl0_pack(uint8_t iso0rxlen, uint8_t iso0txlen) +{ + ASSERT_ERR((((uint32_t)iso0rxlen << 16) & ~((uint32_t)0x00FF0000)) == 0); + ASSERT_ERR((((uint32_t)iso0txlen << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_BLE_WR(BLE_ISOTRCNTL0_ADDR, ((uint32_t)iso0rxlen << 16) | ((uint32_t)iso0txlen << 0)); +} + +__INLINE void ble_isotrcntl0_unpack(uint8_t* iso0rxlen, uint8_t* iso0txlen) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOTRCNTL0_ADDR); + + *iso0rxlen = (localVal & ((uint32_t)0x00FF0000)) >> 16; + *iso0txlen = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +__INLINE uint8_t ble_iso0rxlen_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOTRCNTL0_ADDR); + return ((localVal & ((uint32_t)0x00FF0000)) >> 16); +} + +__INLINE void ble_iso0rxlen_setf(uint8_t iso0rxlen) +{ + ASSERT_ERR((((uint32_t)iso0rxlen << 16) & ~((uint32_t)0x00FF0000)) == 0); + REG_BLE_WR(BLE_ISOTRCNTL0_ADDR, (REG_BLE_RD(BLE_ISOTRCNTL0_ADDR) & ~((uint32_t)0x00FF0000)) | ((uint32_t)iso0rxlen << 16)); +} + +__INLINE uint8_t ble_iso0txlen_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOTRCNTL0_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +__INLINE void ble_iso0txlen_setf(uint8_t iso0txlen) +{ + ASSERT_ERR((((uint32_t)iso0txlen << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_BLE_WR(BLE_ISOTRCNTL0_ADDR, (REG_BLE_RD(BLE_ISOTRCNTL0_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)iso0txlen << 0)); +} + +/** + * @brief ISOEVTCNTOFFSETL0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00     EVT_CNT_OFFSETL0   0x0
+ * 
+ */ +#define BLE_ISOEVTCNTOFFSETL0_ADDR 0x00810164 +#define BLE_ISOEVTCNTOFFSETL0_OFFSET 0x00000164 +#define BLE_ISOEVTCNTOFFSETL0_INDEX 0x00000059 +#define BLE_ISOEVTCNTOFFSETL0_RESET 0x00000000 + +__INLINE uint32_t ble_isoevtcntoffsetl0_get(void) +{ + return REG_BLE_RD(BLE_ISOEVTCNTOFFSETL0_ADDR); +} + +__INLINE void ble_isoevtcntoffsetl0_set(uint32_t value) +{ + REG_BLE_WR(BLE_ISOEVTCNTOFFSETL0_ADDR, value); +} + +// field definitions +#define BLE_EVT_CNT_OFFSETL0_MASK ((uint32_t)0xFFFFFFFF) +#define BLE_EVT_CNT_OFFSETL0_LSB 0 +#define BLE_EVT_CNT_OFFSETL0_WIDTH ((uint32_t)0x00000020) + +#define BLE_EVT_CNT_OFFSETL0_RST 0x0 + +__INLINE uint32_t ble_evt_cnt_offsetl0_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOEVTCNTOFFSETL0_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_evt_cnt_offsetl0_setf(uint32_t evtcntoffsetl0) +{ + ASSERT_ERR((((uint32_t)evtcntoffsetl0 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_BLE_WR(BLE_ISOEVTCNTOFFSETL0_ADDR, (uint32_t)evtcntoffsetl0 << 0); +} + +/** + * @brief ISOEVTCNTOFFSETU0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  06:00     EVT_CNT_OFFSETU0   0x0
+ * 
+ */ +#define BLE_ISOEVTCNTOFFSETU0_ADDR 0x00810168 +#define BLE_ISOEVTCNTOFFSETU0_OFFSET 0x00000168 +#define BLE_ISOEVTCNTOFFSETU0_INDEX 0x0000005A +#define BLE_ISOEVTCNTOFFSETU0_RESET 0x00000000 + +__INLINE uint32_t ble_isoevtcntoffsetu0_get(void) +{ + return REG_BLE_RD(BLE_ISOEVTCNTOFFSETU0_ADDR); +} + +__INLINE void ble_isoevtcntoffsetu0_set(uint32_t value) +{ + REG_BLE_WR(BLE_ISOEVTCNTOFFSETU0_ADDR, value); +} + +// field definitions +#define BLE_EVT_CNT_OFFSETU0_MASK ((uint32_t)0x0000007F) +#define BLE_EVT_CNT_OFFSETU0_LSB 0 +#define BLE_EVT_CNT_OFFSETU0_WIDTH ((uint32_t)0x00000007) + +#define BLE_EVT_CNT_OFFSETU0_RST 0x0 + +__INLINE uint8_t ble_evt_cnt_offsetu0_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOEVTCNTOFFSETU0_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x0000007F)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_evt_cnt_offsetu0_setf(uint8_t evtcntoffsetu0) +{ + ASSERT_ERR((((uint32_t)evtcntoffsetu0 << 0) & ~((uint32_t)0x0000007F)) == 0); + REG_BLE_WR(BLE_ISOEVTCNTOFFSETU0_ADDR, (uint32_t)evtcntoffsetu0 << 0); +} + +/** + * @brief ISOCHANCNTL1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     04           RETXACKEN1   0
+ *     03             SYNCGEN1   0
+ *     02           ISOCHANEN1   0
+ *  01:00             ISOTYPE1   0x0
+ * 
+ */ +#define BLE_ISOCHANCNTL1_ADDR 0x00810170 +#define BLE_ISOCHANCNTL1_OFFSET 0x00000170 +#define BLE_ISOCHANCNTL1_INDEX 0x0000005C +#define BLE_ISOCHANCNTL1_RESET 0x00000000 + +__INLINE uint32_t ble_isochancntl1_get(void) +{ + return REG_BLE_RD(BLE_ISOCHANCNTL1_ADDR); +} + +__INLINE void ble_isochancntl1_set(uint32_t value) +{ + REG_BLE_WR(BLE_ISOCHANCNTL1_ADDR, value); +} + +// field definitions +#define BLE_RETXACKEN1_BIT ((uint32_t)0x00000010) +#define BLE_RETXACKEN1_POS 4 +#define BLE_SYNCGEN1_BIT ((uint32_t)0x00000008) +#define BLE_SYNCGEN1_POS 3 +#define BLE_ISOCHANEN1_BIT ((uint32_t)0x00000004) +#define BLE_ISOCHANEN1_POS 2 +#define BLE_ISOTYPE1_MASK ((uint32_t)0x00000003) +#define BLE_ISOTYPE1_LSB 0 +#define BLE_ISOTYPE1_WIDTH ((uint32_t)0x00000002) + +#define BLE_RETXACKEN1_RST 0x0 +#define BLE_SYNCGEN1_RST 0x0 +#define BLE_ISOCHANEN1_RST 0x0 +#define BLE_ISOTYPE1_RST 0x0 + +__INLINE void ble_isochancntl1_pack(uint8_t retxacken1, uint8_t syncgen1, uint8_t isochanen1, uint8_t isotype1) +{ + ASSERT_ERR((((uint32_t)retxacken1 << 4) & ~((uint32_t)0x00000010)) == 0); + ASSERT_ERR((((uint32_t)syncgen1 << 3) & ~((uint32_t)0x00000008)) == 0); + ASSERT_ERR((((uint32_t)isochanen1 << 2) & ~((uint32_t)0x00000004)) == 0); + ASSERT_ERR((((uint32_t)isotype1 << 0) & ~((uint32_t)0x00000003)) == 0); + REG_BLE_WR(BLE_ISOCHANCNTL1_ADDR, ((uint32_t)retxacken1 << 4) | ((uint32_t)syncgen1 << 3) | ((uint32_t)isochanen1 << 2) | ((uint32_t)isotype1 << 0)); +} + +__INLINE void ble_isochancntl1_unpack(uint8_t* retxacken1, uint8_t* syncgen1, uint8_t* isochanen1, uint8_t* isotype1) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOCHANCNTL1_ADDR); + + *retxacken1 = (localVal & ((uint32_t)0x00000010)) >> 4; + *syncgen1 = (localVal & ((uint32_t)0x00000008)) >> 3; + *isochanen1 = (localVal & ((uint32_t)0x00000004)) >> 2; + *isotype1 = (localVal & ((uint32_t)0x00000003)) >> 0; +} + +__INLINE uint8_t ble_retxacken1_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOCHANCNTL1_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +__INLINE void ble_retxacken1_setf(uint8_t retxacken1) +{ + ASSERT_ERR((((uint32_t)retxacken1 << 4) & ~((uint32_t)0x00000010)) == 0); + REG_BLE_WR(BLE_ISOCHANCNTL1_ADDR, (REG_BLE_RD(BLE_ISOCHANCNTL1_ADDR) & ~((uint32_t)0x00000010)) | ((uint32_t)retxacken1 << 4)); +} + +__INLINE uint8_t ble_syncgen1_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOCHANCNTL1_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +__INLINE void ble_syncgen1_setf(uint8_t syncgen1) +{ + ASSERT_ERR((((uint32_t)syncgen1 << 3) & ~((uint32_t)0x00000008)) == 0); + REG_BLE_WR(BLE_ISOCHANCNTL1_ADDR, (REG_BLE_RD(BLE_ISOCHANCNTL1_ADDR) & ~((uint32_t)0x00000008)) | ((uint32_t)syncgen1 << 3)); +} + +__INLINE uint8_t ble_isochanen1_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOCHANCNTL1_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +__INLINE void ble_isochanen1_setf(uint8_t isochanen1) +{ + ASSERT_ERR((((uint32_t)isochanen1 << 2) & ~((uint32_t)0x00000004)) == 0); + REG_BLE_WR(BLE_ISOCHANCNTL1_ADDR, (REG_BLE_RD(BLE_ISOCHANCNTL1_ADDR) & ~((uint32_t)0x00000004)) | ((uint32_t)isochanen1 << 2)); +} + +__INLINE uint8_t ble_isotype1_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOCHANCNTL1_ADDR); + return ((localVal & ((uint32_t)0x00000003)) >> 0); +} + +__INLINE void ble_isotype1_setf(uint8_t isotype1) +{ + ASSERT_ERR((((uint32_t)isotype1 << 0) & ~((uint32_t)0x00000003)) == 0); + REG_BLE_WR(BLE_ISOCHANCNTL1_ADDR, (REG_BLE_RD(BLE_ISOCHANCNTL1_ADDR) & ~((uint32_t)0x00000003)) | ((uint32_t)isotype1 << 0)); +} + +/** + * @brief ISOMUTECNTL1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31                 TOG1   0
+ *     19           MUTE_SINK1   0
+ *     18         MUTE_SOURCE1   0
+ *     17              INVL1_1   1
+ *     16              INVL1_0   1
+ *  07:00        MUTE_PATTERN1   0x0
+ * 
+ */ +#define BLE_ISOMUTECNTL1_ADDR 0x00810174 +#define BLE_ISOMUTECNTL1_OFFSET 0x00000174 +#define BLE_ISOMUTECNTL1_INDEX 0x0000005D +#define BLE_ISOMUTECNTL1_RESET 0x00030000 + +__INLINE uint32_t ble_isomutecntl1_get(void) +{ + return REG_BLE_RD(BLE_ISOMUTECNTL1_ADDR); +} + +__INLINE void ble_isomutecntl1_set(uint32_t value) +{ + REG_BLE_WR(BLE_ISOMUTECNTL1_ADDR, value); +} + +// field definitions +#define BLE_TOG1_BIT ((uint32_t)0x80000000) +#define BLE_TOG1_POS 31 +#define BLE_MUTE_SINK1_BIT ((uint32_t)0x00080000) +#define BLE_MUTE_SINK1_POS 19 +#define BLE_MUTE_SOURCE1_BIT ((uint32_t)0x00040000) +#define BLE_MUTE_SOURCE1_POS 18 +#define BLE_INVL1_1_BIT ((uint32_t)0x00020000) +#define BLE_INVL1_1_POS 17 +#define BLE_INVL1_0_BIT ((uint32_t)0x00010000) +#define BLE_INVL1_0_POS 16 +#define BLE_MUTE_PATTERN1_MASK ((uint32_t)0x000000FF) +#define BLE_MUTE_PATTERN1_LSB 0 +#define BLE_MUTE_PATTERN1_WIDTH ((uint32_t)0x00000008) + +#define BLE_TOG1_RST 0x0 +#define BLE_MUTE_SINK1_RST 0x0 +#define BLE_MUTE_SOURCE1_RST 0x0 +#define BLE_INVL1_1_RST 0x1 +#define BLE_INVL1_0_RST 0x1 +#define BLE_MUTE_PATTERN1_RST 0x0 + +__INLINE void ble_isomutecntl1_pack(uint8_t mutesink1, uint8_t mutesource1, uint8_t invl11, uint8_t invl10, uint8_t mutepattern1) +{ + ASSERT_ERR((((uint32_t)mutesink1 << 19) & ~((uint32_t)0x00080000)) == 0); + ASSERT_ERR((((uint32_t)mutesource1 << 18) & ~((uint32_t)0x00040000)) == 0); + ASSERT_ERR((((uint32_t)invl11 << 17) & ~((uint32_t)0x00020000)) == 0); + ASSERT_ERR((((uint32_t)invl10 << 16) & ~((uint32_t)0x00010000)) == 0); + ASSERT_ERR((((uint32_t)mutepattern1 << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_BLE_WR(BLE_ISOMUTECNTL1_ADDR, ((uint32_t)mutesink1 << 19) | ((uint32_t)mutesource1 << 18) | ((uint32_t)invl11 << 17) | ((uint32_t)invl10 << 16) | ((uint32_t)mutepattern1 << 0)); +} + +__INLINE void ble_isomutecntl1_unpack(uint8_t* tog1, uint8_t* mutesink1, uint8_t* mutesource1, uint8_t* invl11, uint8_t* invl10, uint8_t* mutepattern1) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOMUTECNTL1_ADDR); + + *tog1 = (localVal & ((uint32_t)0x80000000)) >> 31; + *mutesink1 = (localVal & ((uint32_t)0x00080000)) >> 19; + *mutesource1 = (localVal & ((uint32_t)0x00040000)) >> 18; + *invl11 = (localVal & ((uint32_t)0x00020000)) >> 17; + *invl10 = (localVal & ((uint32_t)0x00010000)) >> 16; + *mutepattern1 = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +__INLINE uint8_t ble_tog1_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOMUTECNTL1_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +__INLINE uint8_t ble_mute_sink1_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOMUTECNTL1_ADDR); + return ((localVal & ((uint32_t)0x00080000)) >> 19); +} + +__INLINE void ble_mute_sink1_setf(uint8_t mutesink1) +{ + ASSERT_ERR((((uint32_t)mutesink1 << 19) & ~((uint32_t)0x00080000)) == 0); + REG_BLE_WR(BLE_ISOMUTECNTL1_ADDR, (REG_BLE_RD(BLE_ISOMUTECNTL1_ADDR) & ~((uint32_t)0x00080000)) | ((uint32_t)mutesink1 << 19)); +} + +__INLINE uint8_t ble_mute_source1_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOMUTECNTL1_ADDR); + return ((localVal & ((uint32_t)0x00040000)) >> 18); +} + +__INLINE void ble_mute_source1_setf(uint8_t mutesource1) +{ + ASSERT_ERR((((uint32_t)mutesource1 << 18) & ~((uint32_t)0x00040000)) == 0); + REG_BLE_WR(BLE_ISOMUTECNTL1_ADDR, (REG_BLE_RD(BLE_ISOMUTECNTL1_ADDR) & ~((uint32_t)0x00040000)) | ((uint32_t)mutesource1 << 18)); +} + +__INLINE uint8_t ble_invl1_1_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOMUTECNTL1_ADDR); + return ((localVal & ((uint32_t)0x00020000)) >> 17); +} + +__INLINE void ble_invl1_1_setf(uint8_t invl11) +{ + ASSERT_ERR((((uint32_t)invl11 << 17) & ~((uint32_t)0x00020000)) == 0); + REG_BLE_WR(BLE_ISOMUTECNTL1_ADDR, (REG_BLE_RD(BLE_ISOMUTECNTL1_ADDR) & ~((uint32_t)0x00020000)) | ((uint32_t)invl11 << 17)); +} + +__INLINE uint8_t ble_invl1_0_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOMUTECNTL1_ADDR); + return ((localVal & ((uint32_t)0x00010000)) >> 16); +} + +__INLINE void ble_invl1_0_setf(uint8_t invl10) +{ + ASSERT_ERR((((uint32_t)invl10 << 16) & ~((uint32_t)0x00010000)) == 0); + REG_BLE_WR(BLE_ISOMUTECNTL1_ADDR, (REG_BLE_RD(BLE_ISOMUTECNTL1_ADDR) & ~((uint32_t)0x00010000)) | ((uint32_t)invl10 << 16)); +} + +__INLINE uint8_t ble_mute_pattern1_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOMUTECNTL1_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +__INLINE void ble_mute_pattern1_setf(uint8_t mutepattern1) +{ + ASSERT_ERR((((uint32_t)mutepattern1 << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_BLE_WR(BLE_ISOMUTECNTL1_ADDR, (REG_BLE_RD(BLE_ISOMUTECNTL1_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)mutepattern1 << 0)); +} + +/** + * @brief ISOCURRENTTXPTR1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:16           ISO1TXPTR1   0x0
+ *  15:00           ISO1TXPTR0   0x0
+ * 
+ */ +#define BLE_ISOCURRENTTXPTR1_ADDR 0x00810178 +#define BLE_ISOCURRENTTXPTR1_OFFSET 0x00000178 +#define BLE_ISOCURRENTTXPTR1_INDEX 0x0000005E +#define BLE_ISOCURRENTTXPTR1_RESET 0x00000000 + +__INLINE uint32_t ble_isocurrenttxptr1_get(void) +{ + return REG_BLE_RD(BLE_ISOCURRENTTXPTR1_ADDR); +} + +__INLINE void ble_isocurrenttxptr1_set(uint32_t value) +{ + REG_BLE_WR(BLE_ISOCURRENTTXPTR1_ADDR, value); +} + +// field definitions +#define BLE_ISO1TXPTR1_MASK ((uint32_t)0xFFFF0000) +#define BLE_ISO1TXPTR1_LSB 16 +#define BLE_ISO1TXPTR1_WIDTH ((uint32_t)0x00000010) +#define BLE_ISO1TXPTR0_MASK ((uint32_t)0x0000FFFF) +#define BLE_ISO1TXPTR0_LSB 0 +#define BLE_ISO1TXPTR0_WIDTH ((uint32_t)0x00000010) + +#define BLE_ISO1TXPTR1_RST 0x0 +#define BLE_ISO1TXPTR0_RST 0x0 + +__INLINE void ble_isocurrenttxptr1_pack(uint16_t iso1txptr1, uint16_t iso1txptr0) +{ + ASSERT_ERR((((uint32_t)iso1txptr1 << 16) & ~((uint32_t)0xFFFF0000)) == 0); + ASSERT_ERR((((uint32_t)iso1txptr0 << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_BLE_WR(BLE_ISOCURRENTTXPTR1_ADDR, ((uint32_t)iso1txptr1 << 16) | ((uint32_t)iso1txptr0 << 0)); +} + +__INLINE void ble_isocurrenttxptr1_unpack(uint16_t* iso1txptr1, uint16_t* iso1txptr0) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOCURRENTTXPTR1_ADDR); + + *iso1txptr1 = (localVal & ((uint32_t)0xFFFF0000)) >> 16; + *iso1txptr0 = (localVal & ((uint32_t)0x0000FFFF)) >> 0; +} + +__INLINE uint16_t ble_iso1txptr1_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOCURRENTTXPTR1_ADDR); + return ((localVal & ((uint32_t)0xFFFF0000)) >> 16); +} + +__INLINE void ble_iso1txptr1_setf(uint16_t iso1txptr1) +{ + ASSERT_ERR((((uint32_t)iso1txptr1 << 16) & ~((uint32_t)0xFFFF0000)) == 0); + REG_BLE_WR(BLE_ISOCURRENTTXPTR1_ADDR, (REG_BLE_RD(BLE_ISOCURRENTTXPTR1_ADDR) & ~((uint32_t)0xFFFF0000)) | ((uint32_t)iso1txptr1 << 16)); +} + +__INLINE uint16_t ble_iso1txptr0_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOCURRENTTXPTR1_ADDR); + return ((localVal & ((uint32_t)0x0000FFFF)) >> 0); +} + +__INLINE void ble_iso1txptr0_setf(uint16_t iso1txptr0) +{ + ASSERT_ERR((((uint32_t)iso1txptr0 << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_BLE_WR(BLE_ISOCURRENTTXPTR1_ADDR, (REG_BLE_RD(BLE_ISOCURRENTTXPTR1_ADDR) & ~((uint32_t)0x0000FFFF)) | ((uint32_t)iso1txptr0 << 0)); +} + +/** + * @brief ISOCURRENTRXPTR1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:16           ISO1RXPTR1   0x0
+ *  15:00           ISO1RXPTR0   0x0
+ * 
+ */ +#define BLE_ISOCURRENTRXPTR1_ADDR 0x0081017C +#define BLE_ISOCURRENTRXPTR1_OFFSET 0x0000017C +#define BLE_ISOCURRENTRXPTR1_INDEX 0x0000005F +#define BLE_ISOCURRENTRXPTR1_RESET 0x00000000 + +__INLINE uint32_t ble_isocurrentrxptr1_get(void) +{ + return REG_BLE_RD(BLE_ISOCURRENTRXPTR1_ADDR); +} + +__INLINE void ble_isocurrentrxptr1_set(uint32_t value) +{ + REG_BLE_WR(BLE_ISOCURRENTRXPTR1_ADDR, value); +} + +// field definitions +#define BLE_ISO1RXPTR1_MASK ((uint32_t)0xFFFF0000) +#define BLE_ISO1RXPTR1_LSB 16 +#define BLE_ISO1RXPTR1_WIDTH ((uint32_t)0x00000010) +#define BLE_ISO1RXPTR0_MASK ((uint32_t)0x0000FFFF) +#define BLE_ISO1RXPTR0_LSB 0 +#define BLE_ISO1RXPTR0_WIDTH ((uint32_t)0x00000010) + +#define BLE_ISO1RXPTR1_RST 0x0 +#define BLE_ISO1RXPTR0_RST 0x0 + +__INLINE void ble_isocurrentrxptr1_pack(uint16_t iso1rxptr1, uint16_t iso1rxptr0) +{ + ASSERT_ERR((((uint32_t)iso1rxptr1 << 16) & ~((uint32_t)0xFFFF0000)) == 0); + ASSERT_ERR((((uint32_t)iso1rxptr0 << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_BLE_WR(BLE_ISOCURRENTRXPTR1_ADDR, ((uint32_t)iso1rxptr1 << 16) | ((uint32_t)iso1rxptr0 << 0)); +} + +__INLINE void ble_isocurrentrxptr1_unpack(uint16_t* iso1rxptr1, uint16_t* iso1rxptr0) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOCURRENTRXPTR1_ADDR); + + *iso1rxptr1 = (localVal & ((uint32_t)0xFFFF0000)) >> 16; + *iso1rxptr0 = (localVal & ((uint32_t)0x0000FFFF)) >> 0; +} + +__INLINE uint16_t ble_iso1rxptr1_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOCURRENTRXPTR1_ADDR); + return ((localVal & ((uint32_t)0xFFFF0000)) >> 16); +} + +__INLINE void ble_iso1rxptr1_setf(uint16_t iso1rxptr1) +{ + ASSERT_ERR((((uint32_t)iso1rxptr1 << 16) & ~((uint32_t)0xFFFF0000)) == 0); + REG_BLE_WR(BLE_ISOCURRENTRXPTR1_ADDR, (REG_BLE_RD(BLE_ISOCURRENTRXPTR1_ADDR) & ~((uint32_t)0xFFFF0000)) | ((uint32_t)iso1rxptr1 << 16)); +} + +__INLINE uint16_t ble_iso1rxptr0_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOCURRENTRXPTR1_ADDR); + return ((localVal & ((uint32_t)0x0000FFFF)) >> 0); +} + +__INLINE void ble_iso1rxptr0_setf(uint16_t iso1rxptr0) +{ + ASSERT_ERR((((uint32_t)iso1rxptr0 << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_BLE_WR(BLE_ISOCURRENTRXPTR1_ADDR, (REG_BLE_RD(BLE_ISOCURRENTRXPTR1_ADDR) & ~((uint32_t)0x0000FFFF)) | ((uint32_t)iso1rxptr0 << 0)); +} + +/** + * @brief ISOTRCNTL1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  23:16            ISO1RXLEN   0x0
+ *  07:00            ISO1TXLEN   0x0
+ * 
+ */ +#define BLE_ISOTRCNTL1_ADDR 0x00810180 +#define BLE_ISOTRCNTL1_OFFSET 0x00000180 +#define BLE_ISOTRCNTL1_INDEX 0x00000060 +#define BLE_ISOTRCNTL1_RESET 0x00000000 + +__INLINE uint32_t ble_isotrcntl1_get(void) +{ + return REG_BLE_RD(BLE_ISOTRCNTL1_ADDR); +} + +__INLINE void ble_isotrcntl1_set(uint32_t value) +{ + REG_BLE_WR(BLE_ISOTRCNTL1_ADDR, value); +} + +// field definitions +#define BLE_ISO1RXLEN_MASK ((uint32_t)0x00FF0000) +#define BLE_ISO1RXLEN_LSB 16 +#define BLE_ISO1RXLEN_WIDTH ((uint32_t)0x00000008) +#define BLE_ISO1TXLEN_MASK ((uint32_t)0x000000FF) +#define BLE_ISO1TXLEN_LSB 0 +#define BLE_ISO1TXLEN_WIDTH ((uint32_t)0x00000008) + +#define BLE_ISO1RXLEN_RST 0x0 +#define BLE_ISO1TXLEN_RST 0x0 + +__INLINE void ble_isotrcntl1_pack(uint8_t iso1rxlen, uint8_t iso1txlen) +{ + ASSERT_ERR((((uint32_t)iso1rxlen << 16) & ~((uint32_t)0x00FF0000)) == 0); + ASSERT_ERR((((uint32_t)iso1txlen << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_BLE_WR(BLE_ISOTRCNTL1_ADDR, ((uint32_t)iso1rxlen << 16) | ((uint32_t)iso1txlen << 0)); +} + +__INLINE void ble_isotrcntl1_unpack(uint8_t* iso1rxlen, uint8_t* iso1txlen) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOTRCNTL1_ADDR); + + *iso1rxlen = (localVal & ((uint32_t)0x00FF0000)) >> 16; + *iso1txlen = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +__INLINE uint8_t ble_iso1rxlen_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOTRCNTL1_ADDR); + return ((localVal & ((uint32_t)0x00FF0000)) >> 16); +} + +__INLINE void ble_iso1rxlen_setf(uint8_t iso1rxlen) +{ + ASSERT_ERR((((uint32_t)iso1rxlen << 16) & ~((uint32_t)0x00FF0000)) == 0); + REG_BLE_WR(BLE_ISOTRCNTL1_ADDR, (REG_BLE_RD(BLE_ISOTRCNTL1_ADDR) & ~((uint32_t)0x00FF0000)) | ((uint32_t)iso1rxlen << 16)); +} + +__INLINE uint8_t ble_iso1txlen_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOTRCNTL1_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +__INLINE void ble_iso1txlen_setf(uint8_t iso1txlen) +{ + ASSERT_ERR((((uint32_t)iso1txlen << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_BLE_WR(BLE_ISOTRCNTL1_ADDR, (REG_BLE_RD(BLE_ISOTRCNTL1_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)iso1txlen << 0)); +} + +/** + * @brief ISOEVTCNTOFFSETL1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00     EVT_CNT_OFFSETL1   0x0
+ * 
+ */ +#define BLE_ISOEVTCNTOFFSETL1_ADDR 0x00810184 +#define BLE_ISOEVTCNTOFFSETL1_OFFSET 0x00000184 +#define BLE_ISOEVTCNTOFFSETL1_INDEX 0x00000061 +#define BLE_ISOEVTCNTOFFSETL1_RESET 0x00000000 + +__INLINE uint32_t ble_isoevtcntoffsetl1_get(void) +{ + return REG_BLE_RD(BLE_ISOEVTCNTOFFSETL1_ADDR); +} + +__INLINE void ble_isoevtcntoffsetl1_set(uint32_t value) +{ + REG_BLE_WR(BLE_ISOEVTCNTOFFSETL1_ADDR, value); +} + +// field definitions +#define BLE_EVT_CNT_OFFSETL1_MASK ((uint32_t)0xFFFFFFFF) +#define BLE_EVT_CNT_OFFSETL1_LSB 0 +#define BLE_EVT_CNT_OFFSETL1_WIDTH ((uint32_t)0x00000020) + +#define BLE_EVT_CNT_OFFSETL1_RST 0x0 + +__INLINE uint32_t ble_evt_cnt_offsetl1_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOEVTCNTOFFSETL1_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_evt_cnt_offsetl1_setf(uint32_t evtcntoffsetl1) +{ + ASSERT_ERR((((uint32_t)evtcntoffsetl1 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_BLE_WR(BLE_ISOEVTCNTOFFSETL1_ADDR, (uint32_t)evtcntoffsetl1 << 0); +} + +/** + * @brief ISOEVTCNTOFFSETU1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  06:00     EVT_CNT_OFFSETU1   0x0
+ * 
+ */ +#define BLE_ISOEVTCNTOFFSETU1_ADDR 0x00810188 +#define BLE_ISOEVTCNTOFFSETU1_OFFSET 0x00000188 +#define BLE_ISOEVTCNTOFFSETU1_INDEX 0x00000062 +#define BLE_ISOEVTCNTOFFSETU1_RESET 0x00000000 + +__INLINE uint32_t ble_isoevtcntoffsetu1_get(void) +{ + return REG_BLE_RD(BLE_ISOEVTCNTOFFSETU1_ADDR); +} + +__INLINE void ble_isoevtcntoffsetu1_set(uint32_t value) +{ + REG_BLE_WR(BLE_ISOEVTCNTOFFSETU1_ADDR, value); +} + +// field definitions +#define BLE_EVT_CNT_OFFSETU1_MASK ((uint32_t)0x0000007F) +#define BLE_EVT_CNT_OFFSETU1_LSB 0 +#define BLE_EVT_CNT_OFFSETU1_WIDTH ((uint32_t)0x00000007) + +#define BLE_EVT_CNT_OFFSETU1_RST 0x0 + +__INLINE uint8_t ble_evt_cnt_offsetu1_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOEVTCNTOFFSETU1_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x0000007F)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_evt_cnt_offsetu1_setf(uint8_t evtcntoffsetu1) +{ + ASSERT_ERR((((uint32_t)evtcntoffsetu1 << 0) & ~((uint32_t)0x0000007F)) == 0); + REG_BLE_WR(BLE_ISOEVTCNTOFFSETU1_ADDR, (uint32_t)evtcntoffsetu1 << 0); +} + +/** + * @brief ISOCHANCNTL2 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     04           RETXACKEN2   0
+ *     03             SYNCGEN2   0
+ *     02           ISOCHANEN2   0
+ *  01:00             ISOTYPE2   0x0
+ * 
+ */ +#define BLE_ISOCHANCNTL2_ADDR 0x00810190 +#define BLE_ISOCHANCNTL2_OFFSET 0x00000190 +#define BLE_ISOCHANCNTL2_INDEX 0x00000064 +#define BLE_ISOCHANCNTL2_RESET 0x00000000 + +__INLINE uint32_t ble_isochancntl2_get(void) +{ + return REG_BLE_RD(BLE_ISOCHANCNTL2_ADDR); +} + +__INLINE void ble_isochancntl2_set(uint32_t value) +{ + REG_BLE_WR(BLE_ISOCHANCNTL2_ADDR, value); +} + +// field definitions +#define BLE_RETXACKEN2_BIT ((uint32_t)0x00000010) +#define BLE_RETXACKEN2_POS 4 +#define BLE_SYNCGEN2_BIT ((uint32_t)0x00000008) +#define BLE_SYNCGEN2_POS 3 +#define BLE_ISOCHANEN2_BIT ((uint32_t)0x00000004) +#define BLE_ISOCHANEN2_POS 2 +#define BLE_ISOTYPE2_MASK ((uint32_t)0x00000003) +#define BLE_ISOTYPE2_LSB 0 +#define BLE_ISOTYPE2_WIDTH ((uint32_t)0x00000002) + +#define BLE_RETXACKEN2_RST 0x0 +#define BLE_SYNCGEN2_RST 0x0 +#define BLE_ISOCHANEN2_RST 0x0 +#define BLE_ISOTYPE2_RST 0x0 + +__INLINE void ble_isochancntl2_pack(uint8_t retxacken2, uint8_t syncgen2, uint8_t isochanen2, uint8_t isotype2) +{ + ASSERT_ERR((((uint32_t)retxacken2 << 4) & ~((uint32_t)0x00000010)) == 0); + ASSERT_ERR((((uint32_t)syncgen2 << 3) & ~((uint32_t)0x00000008)) == 0); + ASSERT_ERR((((uint32_t)isochanen2 << 2) & ~((uint32_t)0x00000004)) == 0); + ASSERT_ERR((((uint32_t)isotype2 << 0) & ~((uint32_t)0x00000003)) == 0); + REG_BLE_WR(BLE_ISOCHANCNTL2_ADDR, ((uint32_t)retxacken2 << 4) | ((uint32_t)syncgen2 << 3) | ((uint32_t)isochanen2 << 2) | ((uint32_t)isotype2 << 0)); +} + +__INLINE void ble_isochancntl2_unpack(uint8_t* retxacken2, uint8_t* syncgen2, uint8_t* isochanen2, uint8_t* isotype2) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOCHANCNTL2_ADDR); + + *retxacken2 = (localVal & ((uint32_t)0x00000010)) >> 4; + *syncgen2 = (localVal & ((uint32_t)0x00000008)) >> 3; + *isochanen2 = (localVal & ((uint32_t)0x00000004)) >> 2; + *isotype2 = (localVal & ((uint32_t)0x00000003)) >> 0; +} + +__INLINE uint8_t ble_retxacken2_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOCHANCNTL2_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +__INLINE void ble_retxacken2_setf(uint8_t retxacken2) +{ + ASSERT_ERR((((uint32_t)retxacken2 << 4) & ~((uint32_t)0x00000010)) == 0); + REG_BLE_WR(BLE_ISOCHANCNTL2_ADDR, (REG_BLE_RD(BLE_ISOCHANCNTL2_ADDR) & ~((uint32_t)0x00000010)) | ((uint32_t)retxacken2 << 4)); +} + +__INLINE uint8_t ble_syncgen2_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOCHANCNTL2_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +__INLINE void ble_syncgen2_setf(uint8_t syncgen2) +{ + ASSERT_ERR((((uint32_t)syncgen2 << 3) & ~((uint32_t)0x00000008)) == 0); + REG_BLE_WR(BLE_ISOCHANCNTL2_ADDR, (REG_BLE_RD(BLE_ISOCHANCNTL2_ADDR) & ~((uint32_t)0x00000008)) | ((uint32_t)syncgen2 << 3)); +} + +__INLINE uint8_t ble_isochanen2_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOCHANCNTL2_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +__INLINE void ble_isochanen2_setf(uint8_t isochanen2) +{ + ASSERT_ERR((((uint32_t)isochanen2 << 2) & ~((uint32_t)0x00000004)) == 0); + REG_BLE_WR(BLE_ISOCHANCNTL2_ADDR, (REG_BLE_RD(BLE_ISOCHANCNTL2_ADDR) & ~((uint32_t)0x00000004)) | ((uint32_t)isochanen2 << 2)); +} + +__INLINE uint8_t ble_isotype2_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOCHANCNTL2_ADDR); + return ((localVal & ((uint32_t)0x00000003)) >> 0); +} + +__INLINE void ble_isotype2_setf(uint8_t isotype2) +{ + ASSERT_ERR((((uint32_t)isotype2 << 0) & ~((uint32_t)0x00000003)) == 0); + REG_BLE_WR(BLE_ISOCHANCNTL2_ADDR, (REG_BLE_RD(BLE_ISOCHANCNTL2_ADDR) & ~((uint32_t)0x00000003)) | ((uint32_t)isotype2 << 0)); +} + +/** + * @brief ISOMUTECNTL2 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31                 TOG2   0
+ *     19           MUTE_SINK2   0
+ *     18         MUTE_SOURCE2   0
+ *     17              INVL2_1   1
+ *     16              INVL2_0   1
+ *  07:00        MUTE_PATTERN2   0x0
+ * 
+ */ +#define BLE_ISOMUTECNTL2_ADDR 0x00810194 +#define BLE_ISOMUTECNTL2_OFFSET 0x00000194 +#define BLE_ISOMUTECNTL2_INDEX 0x00000065 +#define BLE_ISOMUTECNTL2_RESET 0x00030000 + +__INLINE uint32_t ble_isomutecntl2_get(void) +{ + return REG_BLE_RD(BLE_ISOMUTECNTL2_ADDR); +} + +__INLINE void ble_isomutecntl2_set(uint32_t value) +{ + REG_BLE_WR(BLE_ISOMUTECNTL2_ADDR, value); +} + +// field definitions +#define BLE_TOG2_BIT ((uint32_t)0x80000000) +#define BLE_TOG2_POS 31 +#define BLE_MUTE_SINK2_BIT ((uint32_t)0x00080000) +#define BLE_MUTE_SINK2_POS 19 +#define BLE_MUTE_SOURCE2_BIT ((uint32_t)0x00040000) +#define BLE_MUTE_SOURCE2_POS 18 +#define BLE_INVL2_1_BIT ((uint32_t)0x00020000) +#define BLE_INVL2_1_POS 17 +#define BLE_INVL2_0_BIT ((uint32_t)0x00010000) +#define BLE_INVL2_0_POS 16 +#define BLE_MUTE_PATTERN2_MASK ((uint32_t)0x000000FF) +#define BLE_MUTE_PATTERN2_LSB 0 +#define BLE_MUTE_PATTERN2_WIDTH ((uint32_t)0x00000008) + +#define BLE_TOG2_RST 0x0 +#define BLE_MUTE_SINK2_RST 0x0 +#define BLE_MUTE_SOURCE2_RST 0x0 +#define BLE_INVL2_1_RST 0x1 +#define BLE_INVL2_0_RST 0x1 +#define BLE_MUTE_PATTERN2_RST 0x0 + +__INLINE void ble_isomutecntl2_pack(uint8_t mutesink2, uint8_t mutesource2, uint8_t invl21, uint8_t invl20, uint8_t mutepattern2) +{ + ASSERT_ERR((((uint32_t)mutesink2 << 19) & ~((uint32_t)0x00080000)) == 0); + ASSERT_ERR((((uint32_t)mutesource2 << 18) & ~((uint32_t)0x00040000)) == 0); + ASSERT_ERR((((uint32_t)invl21 << 17) & ~((uint32_t)0x00020000)) == 0); + ASSERT_ERR((((uint32_t)invl20 << 16) & ~((uint32_t)0x00010000)) == 0); + ASSERT_ERR((((uint32_t)mutepattern2 << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_BLE_WR(BLE_ISOMUTECNTL2_ADDR, ((uint32_t)mutesink2 << 19) | ((uint32_t)mutesource2 << 18) | ((uint32_t)invl21 << 17) | ((uint32_t)invl20 << 16) | ((uint32_t)mutepattern2 << 0)); +} + +__INLINE void ble_isomutecntl2_unpack(uint8_t* tog2, uint8_t* mutesink2, uint8_t* mutesource2, uint8_t* invl21, uint8_t* invl20, uint8_t* mutepattern2) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOMUTECNTL2_ADDR); + + *tog2 = (localVal & ((uint32_t)0x80000000)) >> 31; + *mutesink2 = (localVal & ((uint32_t)0x00080000)) >> 19; + *mutesource2 = (localVal & ((uint32_t)0x00040000)) >> 18; + *invl21 = (localVal & ((uint32_t)0x00020000)) >> 17; + *invl20 = (localVal & ((uint32_t)0x00010000)) >> 16; + *mutepattern2 = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +__INLINE uint8_t ble_tog2_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOMUTECNTL2_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +__INLINE uint8_t ble_mute_sink2_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOMUTECNTL2_ADDR); + return ((localVal & ((uint32_t)0x00080000)) >> 19); +} + +__INLINE void ble_mute_sink2_setf(uint8_t mutesink2) +{ + ASSERT_ERR((((uint32_t)mutesink2 << 19) & ~((uint32_t)0x00080000)) == 0); + REG_BLE_WR(BLE_ISOMUTECNTL2_ADDR, (REG_BLE_RD(BLE_ISOMUTECNTL2_ADDR) & ~((uint32_t)0x00080000)) | ((uint32_t)mutesink2 << 19)); +} + +__INLINE uint8_t ble_mute_source2_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOMUTECNTL2_ADDR); + return ((localVal & ((uint32_t)0x00040000)) >> 18); +} + +__INLINE void ble_mute_source2_setf(uint8_t mutesource2) +{ + ASSERT_ERR((((uint32_t)mutesource2 << 18) & ~((uint32_t)0x00040000)) == 0); + REG_BLE_WR(BLE_ISOMUTECNTL2_ADDR, (REG_BLE_RD(BLE_ISOMUTECNTL2_ADDR) & ~((uint32_t)0x00040000)) | ((uint32_t)mutesource2 << 18)); +} + +__INLINE uint8_t ble_invl2_1_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOMUTECNTL2_ADDR); + return ((localVal & ((uint32_t)0x00020000)) >> 17); +} + +__INLINE void ble_invl2_1_setf(uint8_t invl21) +{ + ASSERT_ERR((((uint32_t)invl21 << 17) & ~((uint32_t)0x00020000)) == 0); + REG_BLE_WR(BLE_ISOMUTECNTL2_ADDR, (REG_BLE_RD(BLE_ISOMUTECNTL2_ADDR) & ~((uint32_t)0x00020000)) | ((uint32_t)invl21 << 17)); +} + +__INLINE uint8_t ble_invl2_0_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOMUTECNTL2_ADDR); + return ((localVal & ((uint32_t)0x00010000)) >> 16); +} + +__INLINE void ble_invl2_0_setf(uint8_t invl20) +{ + ASSERT_ERR((((uint32_t)invl20 << 16) & ~((uint32_t)0x00010000)) == 0); + REG_BLE_WR(BLE_ISOMUTECNTL2_ADDR, (REG_BLE_RD(BLE_ISOMUTECNTL2_ADDR) & ~((uint32_t)0x00010000)) | ((uint32_t)invl20 << 16)); +} + +__INLINE uint8_t ble_mute_pattern2_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOMUTECNTL2_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +__INLINE void ble_mute_pattern2_setf(uint8_t mutepattern2) +{ + ASSERT_ERR((((uint32_t)mutepattern2 << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_BLE_WR(BLE_ISOMUTECNTL2_ADDR, (REG_BLE_RD(BLE_ISOMUTECNTL2_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)mutepattern2 << 0)); +} + +/** + * @brief ISOCURRENTTXPTR2 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:16           ISO2TXPTR1   0x0
+ *  15:00           ISO2TXPTR0   0x0
+ * 
+ */ +#define BLE_ISOCURRENTTXPTR2_ADDR 0x00810198 +#define BLE_ISOCURRENTTXPTR2_OFFSET 0x00000198 +#define BLE_ISOCURRENTTXPTR2_INDEX 0x00000066 +#define BLE_ISOCURRENTTXPTR2_RESET 0x00000000 + +__INLINE uint32_t ble_isocurrenttxptr2_get(void) +{ + return REG_BLE_RD(BLE_ISOCURRENTTXPTR2_ADDR); +} + +__INLINE void ble_isocurrenttxptr2_set(uint32_t value) +{ + REG_BLE_WR(BLE_ISOCURRENTTXPTR2_ADDR, value); +} + +// field definitions +#define BLE_ISO2TXPTR1_MASK ((uint32_t)0xFFFF0000) +#define BLE_ISO2TXPTR1_LSB 16 +#define BLE_ISO2TXPTR1_WIDTH ((uint32_t)0x00000010) +#define BLE_ISO2TXPTR0_MASK ((uint32_t)0x0000FFFF) +#define BLE_ISO2TXPTR0_LSB 0 +#define BLE_ISO2TXPTR0_WIDTH ((uint32_t)0x00000010) + +#define BLE_ISO2TXPTR1_RST 0x0 +#define BLE_ISO2TXPTR0_RST 0x0 + +__INLINE void ble_isocurrenttxptr2_pack(uint16_t iso2txptr1, uint16_t iso2txptr0) +{ + ASSERT_ERR((((uint32_t)iso2txptr1 << 16) & ~((uint32_t)0xFFFF0000)) == 0); + ASSERT_ERR((((uint32_t)iso2txptr0 << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_BLE_WR(BLE_ISOCURRENTTXPTR2_ADDR, ((uint32_t)iso2txptr1 << 16) | ((uint32_t)iso2txptr0 << 0)); +} + +__INLINE void ble_isocurrenttxptr2_unpack(uint16_t* iso2txptr1, uint16_t* iso2txptr0) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOCURRENTTXPTR2_ADDR); + + *iso2txptr1 = (localVal & ((uint32_t)0xFFFF0000)) >> 16; + *iso2txptr0 = (localVal & ((uint32_t)0x0000FFFF)) >> 0; +} + +__INLINE uint16_t ble_iso2txptr1_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOCURRENTTXPTR2_ADDR); + return ((localVal & ((uint32_t)0xFFFF0000)) >> 16); +} + +__INLINE void ble_iso2txptr1_setf(uint16_t iso2txptr1) +{ + ASSERT_ERR((((uint32_t)iso2txptr1 << 16) & ~((uint32_t)0xFFFF0000)) == 0); + REG_BLE_WR(BLE_ISOCURRENTTXPTR2_ADDR, (REG_BLE_RD(BLE_ISOCURRENTTXPTR2_ADDR) & ~((uint32_t)0xFFFF0000)) | ((uint32_t)iso2txptr1 << 16)); +} + +__INLINE uint16_t ble_iso2txptr0_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOCURRENTTXPTR2_ADDR); + return ((localVal & ((uint32_t)0x0000FFFF)) >> 0); +} + +__INLINE void ble_iso2txptr0_setf(uint16_t iso2txptr0) +{ + ASSERT_ERR((((uint32_t)iso2txptr0 << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_BLE_WR(BLE_ISOCURRENTTXPTR2_ADDR, (REG_BLE_RD(BLE_ISOCURRENTTXPTR2_ADDR) & ~((uint32_t)0x0000FFFF)) | ((uint32_t)iso2txptr0 << 0)); +} + +/** + * @brief ISOCURRENTRXPTR2 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:16           ISO2RXPTR1   0x0
+ *  15:00           ISO2RXPTR0   0x0
+ * 
+ */ +#define BLE_ISOCURRENTRXPTR2_ADDR 0x0081019C +#define BLE_ISOCURRENTRXPTR2_OFFSET 0x0000019C +#define BLE_ISOCURRENTRXPTR2_INDEX 0x00000067 +#define BLE_ISOCURRENTRXPTR2_RESET 0x00000000 + +__INLINE uint32_t ble_isocurrentrxptr2_get(void) +{ + return REG_BLE_RD(BLE_ISOCURRENTRXPTR2_ADDR); +} + +__INLINE void ble_isocurrentrxptr2_set(uint32_t value) +{ + REG_BLE_WR(BLE_ISOCURRENTRXPTR2_ADDR, value); +} + +// field definitions +#define BLE_ISO2RXPTR1_MASK ((uint32_t)0xFFFF0000) +#define BLE_ISO2RXPTR1_LSB 16 +#define BLE_ISO2RXPTR1_WIDTH ((uint32_t)0x00000010) +#define BLE_ISO2RXPTR0_MASK ((uint32_t)0x0000FFFF) +#define BLE_ISO2RXPTR0_LSB 0 +#define BLE_ISO2RXPTR0_WIDTH ((uint32_t)0x00000010) + +#define BLE_ISO2RXPTR1_RST 0x0 +#define BLE_ISO2RXPTR0_RST 0x0 + +__INLINE void ble_isocurrentrxptr2_pack(uint16_t iso2rxptr1, uint16_t iso2rxptr0) +{ + ASSERT_ERR((((uint32_t)iso2rxptr1 << 16) & ~((uint32_t)0xFFFF0000)) == 0); + ASSERT_ERR((((uint32_t)iso2rxptr0 << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_BLE_WR(BLE_ISOCURRENTRXPTR2_ADDR, ((uint32_t)iso2rxptr1 << 16) | ((uint32_t)iso2rxptr0 << 0)); +} + +__INLINE void ble_isocurrentrxptr2_unpack(uint16_t* iso2rxptr1, uint16_t* iso2rxptr0) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOCURRENTRXPTR2_ADDR); + + *iso2rxptr1 = (localVal & ((uint32_t)0xFFFF0000)) >> 16; + *iso2rxptr0 = (localVal & ((uint32_t)0x0000FFFF)) >> 0; +} + +__INLINE uint16_t ble_iso2rxptr1_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOCURRENTRXPTR2_ADDR); + return ((localVal & ((uint32_t)0xFFFF0000)) >> 16); +} + +__INLINE void ble_iso2rxptr1_setf(uint16_t iso2rxptr1) +{ + ASSERT_ERR((((uint32_t)iso2rxptr1 << 16) & ~((uint32_t)0xFFFF0000)) == 0); + REG_BLE_WR(BLE_ISOCURRENTRXPTR2_ADDR, (REG_BLE_RD(BLE_ISOCURRENTRXPTR2_ADDR) & ~((uint32_t)0xFFFF0000)) | ((uint32_t)iso2rxptr1 << 16)); +} + +__INLINE uint16_t ble_iso2rxptr0_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOCURRENTRXPTR2_ADDR); + return ((localVal & ((uint32_t)0x0000FFFF)) >> 0); +} + +__INLINE void ble_iso2rxptr0_setf(uint16_t iso2rxptr0) +{ + ASSERT_ERR((((uint32_t)iso2rxptr0 << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_BLE_WR(BLE_ISOCURRENTRXPTR2_ADDR, (REG_BLE_RD(BLE_ISOCURRENTRXPTR2_ADDR) & ~((uint32_t)0x0000FFFF)) | ((uint32_t)iso2rxptr0 << 0)); +} + +/** + * @brief ISOTRCNTL2 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  23:16            ISO2RXLEN   0x0
+ *  07:00            ISO2TXLEN   0x0
+ * 
+ */ +#define BLE_ISOTRCNTL2_ADDR 0x008101A0 +#define BLE_ISOTRCNTL2_OFFSET 0x000001A0 +#define BLE_ISOTRCNTL2_INDEX 0x00000068 +#define BLE_ISOTRCNTL2_RESET 0x00000000 + +__INLINE uint32_t ble_isotrcntl2_get(void) +{ + return REG_BLE_RD(BLE_ISOTRCNTL2_ADDR); +} + +__INLINE void ble_isotrcntl2_set(uint32_t value) +{ + REG_BLE_WR(BLE_ISOTRCNTL2_ADDR, value); +} + +// field definitions +#define BLE_ISO2RXLEN_MASK ((uint32_t)0x00FF0000) +#define BLE_ISO2RXLEN_LSB 16 +#define BLE_ISO2RXLEN_WIDTH ((uint32_t)0x00000008) +#define BLE_ISO2TXLEN_MASK ((uint32_t)0x000000FF) +#define BLE_ISO2TXLEN_LSB 0 +#define BLE_ISO2TXLEN_WIDTH ((uint32_t)0x00000008) + +#define BLE_ISO2RXLEN_RST 0x0 +#define BLE_ISO2TXLEN_RST 0x0 + +__INLINE void ble_isotrcntl2_pack(uint8_t iso2rxlen, uint8_t iso2txlen) +{ + ASSERT_ERR((((uint32_t)iso2rxlen << 16) & ~((uint32_t)0x00FF0000)) == 0); + ASSERT_ERR((((uint32_t)iso2txlen << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_BLE_WR(BLE_ISOTRCNTL2_ADDR, ((uint32_t)iso2rxlen << 16) | ((uint32_t)iso2txlen << 0)); +} + +__INLINE void ble_isotrcntl2_unpack(uint8_t* iso2rxlen, uint8_t* iso2txlen) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOTRCNTL2_ADDR); + + *iso2rxlen = (localVal & ((uint32_t)0x00FF0000)) >> 16; + *iso2txlen = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +__INLINE uint8_t ble_iso2rxlen_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOTRCNTL2_ADDR); + return ((localVal & ((uint32_t)0x00FF0000)) >> 16); +} + +__INLINE void ble_iso2rxlen_setf(uint8_t iso2rxlen) +{ + ASSERT_ERR((((uint32_t)iso2rxlen << 16) & ~((uint32_t)0x00FF0000)) == 0); + REG_BLE_WR(BLE_ISOTRCNTL2_ADDR, (REG_BLE_RD(BLE_ISOTRCNTL2_ADDR) & ~((uint32_t)0x00FF0000)) | ((uint32_t)iso2rxlen << 16)); +} + +__INLINE uint8_t ble_iso2txlen_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOTRCNTL2_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +__INLINE void ble_iso2txlen_setf(uint8_t iso2txlen) +{ + ASSERT_ERR((((uint32_t)iso2txlen << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_BLE_WR(BLE_ISOTRCNTL2_ADDR, (REG_BLE_RD(BLE_ISOTRCNTL2_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)iso2txlen << 0)); +} + +/** + * @brief ISOEVTCNTOFFSETL2 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00     EVT_CNT_OFFSETL2   0x0
+ * 
+ */ +#define BLE_ISOEVTCNTOFFSETL2_ADDR 0x008101A4 +#define BLE_ISOEVTCNTOFFSETL2_OFFSET 0x000001A4 +#define BLE_ISOEVTCNTOFFSETL2_INDEX 0x00000069 +#define BLE_ISOEVTCNTOFFSETL2_RESET 0x00000000 + +__INLINE uint32_t ble_isoevtcntoffsetl2_get(void) +{ + return REG_BLE_RD(BLE_ISOEVTCNTOFFSETL2_ADDR); +} + +__INLINE void ble_isoevtcntoffsetl2_set(uint32_t value) +{ + REG_BLE_WR(BLE_ISOEVTCNTOFFSETL2_ADDR, value); +} + +// field definitions +#define BLE_EVT_CNT_OFFSETL2_MASK ((uint32_t)0xFFFFFFFF) +#define BLE_EVT_CNT_OFFSETL2_LSB 0 +#define BLE_EVT_CNT_OFFSETL2_WIDTH ((uint32_t)0x00000020) + +#define BLE_EVT_CNT_OFFSETL2_RST 0x0 + +__INLINE uint32_t ble_evt_cnt_offsetl2_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOEVTCNTOFFSETL2_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_evt_cnt_offsetl2_setf(uint32_t evtcntoffsetl2) +{ + ASSERT_ERR((((uint32_t)evtcntoffsetl2 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_BLE_WR(BLE_ISOEVTCNTOFFSETL2_ADDR, (uint32_t)evtcntoffsetl2 << 0); +} + +/** + * @brief ISOEVTCNTOFFSETU2 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  06:00     EVT_CNT_OFFSETU2   0x0
+ * 
+ */ +#define BLE_ISOEVTCNTOFFSETU2_ADDR 0x008101A8 +#define BLE_ISOEVTCNTOFFSETU2_OFFSET 0x000001A8 +#define BLE_ISOEVTCNTOFFSETU2_INDEX 0x0000006A +#define BLE_ISOEVTCNTOFFSETU2_RESET 0x00000000 + +__INLINE uint32_t ble_isoevtcntoffsetu2_get(void) +{ + return REG_BLE_RD(BLE_ISOEVTCNTOFFSETU2_ADDR); +} + +__INLINE void ble_isoevtcntoffsetu2_set(uint32_t value) +{ + REG_BLE_WR(BLE_ISOEVTCNTOFFSETU2_ADDR, value); +} + +// field definitions +#define BLE_EVT_CNT_OFFSETU2_MASK ((uint32_t)0x0000007F) +#define BLE_EVT_CNT_OFFSETU2_LSB 0 +#define BLE_EVT_CNT_OFFSETU2_WIDTH ((uint32_t)0x00000007) + +#define BLE_EVT_CNT_OFFSETU2_RST 0x0 + +__INLINE uint8_t ble_evt_cnt_offsetu2_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ISOEVTCNTOFFSETU2_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x0000007F)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_evt_cnt_offsetu2_setf(uint8_t evtcntoffsetu2) +{ + ASSERT_ERR((((uint32_t)evtcntoffsetu2 << 0) & ~((uint32_t)0x0000007F)) == 0); + REG_BLE_WR(BLE_ISOEVTCNTOFFSETU2_ADDR, (uint32_t)evtcntoffsetu2 << 0); +} + +/** + * @brief BLEPRIOSCHARB register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     15          BLEPRIOMODE   0
+ *  07:00            BLEMARGIN   0x0
+ * 
+ */ +#define BLE_BLEPRIOSCHARB_ADDR 0x00810190 +#define BLE_BLEPRIOSCHARB_OFFSET 0x00000190 +#define BLE_BLEPRIOSCHARB_INDEX 0x00000064 +#define BLE_BLEPRIOSCHARB_RESET 0x00000000 + +__INLINE uint32_t ble_bleprioscharb_get(void) +{ + return REG_BLE_RD(BLE_BLEPRIOSCHARB_ADDR); +} + +__INLINE void ble_bleprioscharb_set(uint32_t value) +{ + REG_BLE_WR(BLE_BLEPRIOSCHARB_ADDR, value); +} + +// field definitions +#define BLE_BLEPRIOMODE_BIT ((uint32_t)0x00008000) +#define BLE_BLEPRIOMODE_POS 15 +#define BLE_BLEMARGIN_MASK ((uint32_t)0x000000FF) +#define BLE_BLEMARGIN_LSB 0 +#define BLE_BLEMARGIN_WIDTH ((uint32_t)0x00000008) + +#define BLE_BLEPRIOMODE_RST 0x0 +#define BLE_BLEMARGIN_RST 0x0 + +__INLINE void ble_bleprioscharb_pack(uint8_t blepriomode, uint8_t blemargin) +{ + ASSERT_ERR((((uint32_t)blepriomode << 15) & ~((uint32_t)0x00008000)) == 0); + ASSERT_ERR((((uint32_t)blemargin << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_BLE_WR(BLE_BLEPRIOSCHARB_ADDR, ((uint32_t)blepriomode << 15) | ((uint32_t)blemargin << 0)); +} + +__INLINE void ble_bleprioscharb_unpack(uint8_t* blepriomode, uint8_t* blemargin) +{ + uint32_t localVal = REG_BLE_RD(BLE_BLEPRIOSCHARB_ADDR); + + *blepriomode = (localVal & ((uint32_t)0x00008000)) >> 15; + *blemargin = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +__INLINE uint8_t ble_blepriomode_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_BLEPRIOSCHARB_ADDR); + return ((localVal & ((uint32_t)0x00008000)) >> 15); +} + +__INLINE void ble_blepriomode_setf(uint8_t blepriomode) +{ + ASSERT_ERR((((uint32_t)blepriomode << 15) & ~((uint32_t)0x00008000)) == 0); + REG_BLE_WR(BLE_BLEPRIOSCHARB_ADDR, (REG_BLE_RD(BLE_BLEPRIOSCHARB_ADDR) & ~((uint32_t)0x00008000)) | ((uint32_t)blepriomode << 15)); +} + +__INLINE uint8_t ble_blemargin_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_BLEPRIOSCHARB_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +__INLINE void ble_blemargin_setf(uint8_t blemargin) +{ + ASSERT_ERR((((uint32_t)blemargin << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_BLE_WR(BLE_BLEPRIOSCHARB_ADDR, (REG_BLE_RD(BLE_BLEPRIOSCHARB_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)blemargin << 0)); +} + + +#endif // _REG_BLECORE_H_ + diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/reg_common_em_et.h b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/reg_common_em_et.h new file mode 100755 index 0000000..ae153d9 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/reg_common_em_et.h @@ -0,0 +1,164 @@ +#ifndef _REG_COMMON_EM_ET_H_ +#define _REG_COMMON_EM_ET_H_ + +#include +#include "_reg_common_em_et.h" +#include "ble_compiler.h" +#include "architect.h" +#include "em_map.h" +#include "ble_reg_access.h" + +#define REG_COMMON_EM_ET_COUNT 2 + +#define REG_COMMON_EM_ET_DECODING_MASK 0x00000003 + +#define REG_COMMON_EM_ET_ADDR_GET(idx) (EM_ET_OFFSET + (idx) * REG_COMMON_EM_ET_SIZE) + +/** + * @brief EXTAB0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  05:04               STATUS   0x0
+ *  03:00                 MODE   0x0
+ * 
+ */ +#define EM_COMMON_EXTAB0_ADDR (0x00814000 + EM_ET_OFFSET) +#define EM_COMMON_EXTAB0_INDEX 0x00000000 +#define EM_COMMON_EXTAB0_RESET 0x00000000 + +__INLINE uint16_t em_common_extab0_get(int elt_idx) +{ + return EM_RD(EM_COMMON_EXTAB0_ADDR + elt_idx * REG_COMMON_EM_ET_SIZE); +} + +__INLINE void em_common_extab0_set(int elt_idx, uint16_t value) +{ + EM_WR(EM_COMMON_EXTAB0_ADDR + elt_idx * REG_COMMON_EM_ET_SIZE, value); +} + +// field definitions +#define EM_COMMON_STATUS_MASK ((uint16_t)0x00000030) +#define EM_COMMON_STATUS_LSB 4 +#define EM_COMMON_STATUS_WIDTH ((uint16_t)0x00000002) +#define EM_COMMON_MODE_MASK ((uint16_t)0x0000000F) +#define EM_COMMON_MODE_LSB 0 +#define EM_COMMON_MODE_WIDTH ((uint16_t)0x00000004) + +#define EM_COMMON_STATUS_RST 0x0 +#define EM_COMMON_MODE_RST 0x0 + +__INLINE void em_common_extab0_pack(int elt_idx, uint8_t status, uint8_t mode) +{ + ASSERT_ERR((((uint16_t)status << 4) & ~((uint16_t)0x00000030)) == 0); + ASSERT_ERR((((uint16_t)mode << 0) & ~((uint16_t)0x0000000F)) == 0); + EM_WR(EM_COMMON_EXTAB0_ADDR + elt_idx * REG_COMMON_EM_ET_SIZE, ((uint16_t)status << 4) | ((uint16_t)mode << 0)); +} + +__INLINE void em_common_extab0_unpack(int elt_idx, uint8_t* status, uint8_t* mode) +{ + uint16_t localVal = EM_RD(EM_COMMON_EXTAB0_ADDR + elt_idx * REG_COMMON_EM_ET_SIZE); + + *status = (localVal & ((uint16_t)0x00000030)) >> 4; + *mode = (localVal & ((uint16_t)0x0000000F)) >> 0; +} + +__INLINE uint8_t em_common_extab0_status_getf(int elt_idx) +{ + uint16_t localVal = EM_RD(EM_COMMON_EXTAB0_ADDR + elt_idx * REG_COMMON_EM_ET_SIZE); + return ((localVal & ((uint16_t)0x00000030)) >> 4); +} + +__INLINE void em_common_extab0_status_setf(int elt_idx, uint8_t status) +{ + ASSERT_ERR((((uint16_t)status << 4) & ~((uint16_t)0x00000030)) == 0); + EM_WR(EM_COMMON_EXTAB0_ADDR + elt_idx * REG_COMMON_EM_ET_SIZE, (EM_RD(EM_COMMON_EXTAB0_ADDR + elt_idx * REG_COMMON_EM_ET_SIZE) & ~((uint16_t)0x00000030)) | ((uint16_t)status << 4)); +} + +__INLINE uint8_t em_common_extab0_mode_getf(int elt_idx) +{ + uint16_t localVal = EM_RD(EM_COMMON_EXTAB0_ADDR + elt_idx * REG_COMMON_EM_ET_SIZE); + return ((localVal & ((uint16_t)0x0000000F)) >> 0); +} + +__INLINE void em_common_extab0_mode_setf(int elt_idx, uint8_t mode) +{ + ASSERT_ERR((((uint16_t)mode << 0) & ~((uint16_t)0x0000000F)) == 0); + EM_WR(EM_COMMON_EXTAB0_ADDR + elt_idx * REG_COMMON_EM_ET_SIZE, (EM_RD(EM_COMMON_EXTAB0_ADDR + elt_idx * REG_COMMON_EM_ET_SIZE) & ~((uint16_t)0x0000000F)) | ((uint16_t)mode << 0)); +} + +/** + * @brief EXTAB1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     15           EXCPTRNRDY   0
+ *  14:00                CSPTR   0x0
+ * 
+ */ +#define EM_COMMON_EXTAB1_ADDR (0x00814002 + EM_ET_OFFSET) +#define EM_COMMON_EXTAB1_INDEX 0x00000001 +#define EM_COMMON_EXTAB1_RESET 0x00000000 + +__INLINE uint16_t em_common_extab1_get(int elt_idx) +{ + return EM_RD(EM_COMMON_EXTAB1_ADDR + elt_idx * REG_COMMON_EM_ET_SIZE); +} + +__INLINE void em_common_extab1_set(int elt_idx, uint16_t value) +{ + EM_WR(EM_COMMON_EXTAB1_ADDR + elt_idx * REG_COMMON_EM_ET_SIZE, value); +} + +// field definitions +#define EM_COMMON_EXCPTRNRDY_BIT ((uint16_t)0x00008000) +#define EM_COMMON_EXCPTRNRDY_POS 15 +#define EM_COMMON_CSPTR_MASK ((uint16_t)0x00007FFF) +#define EM_COMMON_CSPTR_LSB 0 +#define EM_COMMON_CSPTR_WIDTH ((uint16_t)0x0000000F) + +#define EM_COMMON_EXCPTRNRDY_RST 0x0 +#define EM_COMMON_CSPTR_RST 0x0 + +__INLINE void em_common_extab1_pack(int elt_idx, uint8_t excptrnrdy, uint16_t csptr) +{ + ASSERT_ERR((((uint16_t)excptrnrdy << 15) & ~((uint16_t)0x00008000)) == 0); + ASSERT_ERR((((uint16_t)csptr << 0) & ~((uint16_t)0x00007FFF)) == 0); + EM_WR(EM_COMMON_EXTAB1_ADDR + elt_idx * REG_COMMON_EM_ET_SIZE, ((uint16_t)excptrnrdy << 15) | ((uint16_t)csptr << 0)); +} + +__INLINE void em_common_extab1_unpack(int elt_idx, uint8_t* excptrnrdy, uint16_t* csptr) +{ + uint16_t localVal = EM_RD(EM_COMMON_EXTAB1_ADDR + elt_idx * REG_COMMON_EM_ET_SIZE); + + *excptrnrdy = (localVal & ((uint16_t)0x00008000)) >> 15; + *csptr = (localVal & ((uint16_t)0x00007FFF)) >> 0; +} + +__INLINE uint8_t em_common_extab1_excptrnrdy_getf(int elt_idx) +{ + uint16_t localVal = EM_RD(EM_COMMON_EXTAB1_ADDR + elt_idx * REG_COMMON_EM_ET_SIZE); + return ((localVal & ((uint16_t)0x00008000)) >> 15); +} + +__INLINE void em_common_extab1_excptrnrdy_setf(int elt_idx, uint8_t excptrnrdy) +{ + ASSERT_ERR((((uint16_t)excptrnrdy << 15) & ~((uint16_t)0x00008000)) == 0); + EM_WR(EM_COMMON_EXTAB1_ADDR + elt_idx * REG_COMMON_EM_ET_SIZE, (EM_RD(EM_COMMON_EXTAB1_ADDR + elt_idx * REG_COMMON_EM_ET_SIZE) & ~((uint16_t)0x00008000)) | ((uint16_t)excptrnrdy << 15)); +} + +__INLINE uint16_t em_common_extab1_csptr_getf(int elt_idx) +{ + uint16_t localVal = EM_RD(EM_COMMON_EXTAB1_ADDR + elt_idx * REG_COMMON_EM_ET_SIZE); + return ((localVal & ((uint16_t)0x00007FFF)) >> 0); +} + +__INLINE void em_common_extab1_csptr_setf(int elt_idx, uint16_t csptr) +{ + ASSERT_ERR((((uint16_t)csptr << 0) & ~((uint16_t)0x00007FFF)) == 0); + EM_WR(EM_COMMON_EXTAB1_ADDR + elt_idx * REG_COMMON_EM_ET_SIZE, (EM_RD(EM_COMMON_EXTAB1_ADDR + elt_idx * REG_COMMON_EM_ET_SIZE) & ~((uint16_t)0x00007FFF)) | ((uint16_t)csptr << 0)); +} + + +#endif // _REG_COMMON_EM_ET_H_ + diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/reg_intc.h b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/reg_intc.h new file mode 100755 index 0000000..d69479c --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/reg_intc.h @@ -0,0 +1,128 @@ +#ifndef _REG_INTC_H_ +#define _REG_INTC_H_ + +#include +#include "_reg_intc.h" +#include "ble_compiler.h" +#include "architect.h" +#include "ble_reg_access.h" + +#define REG_INTC_COUNT 16 + + +/** + * @brief INTSTATUS register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  16:00              INTSTAT   0x0
+ * 
+ */ +#define INTC_INTSTATUS_ADDR 0x00800048 + +__INLINE uint32_t intc_status_get(void) +{ + return REG_PL_RD(INTC_INTSTATUS_ADDR); +} + +__INLINE void intc_status_clear(uint32_t status) +{ + REG_PL_WR(INTC_INTSTATUS_ADDR,status); +} + + + + +/** + * @brief IRQENABLESET register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  16:00         								   0x0
+ * 
+ */ +#define INTC_FIQIRQENABLE_ADDR 0x00800044 + + +__INLINE void intc_enable_set(uint32_t value) +{ + uint32_t reg; + reg = REG_PL_RD(INTC_FIQIRQENABLE_ADDR); + reg |= value; + REG_PL_WR(INTC_FIQIRQENABLE_ADDR, reg); +} + +__INLINE uint32_t intc_enable_get(void) +{ + return REG_PL_RD(INTC_FIQIRQENABLE_ADDR); +} + + + +/** + * @brief IRQENABLECLEAR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  16:00        									   0x0
+ * 
+ */ + +__INLINE void intc_enable_clear(uint32_t value) +{ + + uint32_t reg; + reg = REG_PL_RD(INTC_FIQIRQENABLE_ADDR); + reg &= ~value ; + REG_PL_WR(INTC_FIQIRQENABLE_ADDR, reg); +} + + +/** + * @brief IRQENABLESET register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  16:00         							   0x0
+ * 
+ */ +#define INTC_MODULEENABLE_ADDR 0x00800040 + + +__INLINE void intc_module_enable_set(uint32_t value) +{ + uint32_t reg; + reg = REG_PL_RD(INTC_MODULEENABLE_ADDR); + reg |= value; + REG_PL_WR(INTC_MODULEENABLE_ADDR, reg); +} + +__INLINE uint32_t intc_module_enable_get(void) +{ + return REG_PL_RD(INTC_MODULEENABLE_ADDR); +} + + + +/** + * @brief register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  16:00       				   0x0
+ * 
+ */ + +__INLINE void intc_module_enable_clear(uint32_t value) +{ + + uint32_t reg; + reg = REG_PL_RD(INTC_MODULEENABLE_ADDR); + reg &= ~value ; + REG_PL_WR(INTC_MODULEENABLE_ADDR, reg); +} + + + +#endif // _REG_INTC_H_ + diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/reg_timer.h b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/reg_timer.h new file mode 100755 index 0000000..653ea7a --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/reg_timer.h @@ -0,0 +1,180 @@ +#ifndef _REG_TIMER_H_ +#define _REG_TIMER_H_ + +#include +#include "_reg_timer.h" +#include "ble_compiler.h" +#include "architect.h" +#include "ble_reg_access.h" + +#define REG_TIMER_COUNT 4 + +#define REG_TIMER_DECODING_MASK 0x0000000F + +/** + * @brief TIME_CTRL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     00               ENABLE   0
+ * 
+ */ +#define TMR_TIME_CTRL_ADDR 0x1000E000 +#define TMR_TIME_CTRL_OFFSET 0x00000000 +#define TMR_TIME_CTRL_INDEX 0x00000000 +#define TMR_TIME_CTRL_RESET 0x00000000 + +__INLINE uint32_t tmr_time_ctrl_get(void) +{ + return REG_PL_RD(TMR_TIME_CTRL_ADDR); +} + +__INLINE void tmr_time_ctrl_set(uint32_t value) +{ + REG_PL_WR(TMR_TIME_CTRL_ADDR, value); +} + +// field definitions +#define TMR_ENABLE_BIT ((uint32_t)0x00000001) +#define TMR_ENABLE_POS 0 + +#define TMR_ENABLE_RST 0x0 + +__INLINE uint8_t tmr_enable_getf(void) +{ + uint32_t localVal = REG_PL_RD(TMR_TIME_CTRL_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x00000001)) == 0); + return (localVal >> 0); +} + +__INLINE void tmr_enable_setf(uint8_t enable) +{ + ASSERT_ERR((((uint32_t)enable << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(TMR_TIME_CTRL_ADDR, (uint32_t)enable << 0); +} + +/** + * @brief CURRENT_TIME register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  23:00                 time   0x0
+ * 
+ */ +#define TMR_CURRENT_TIME_ADDR 0x1000E004 +#define TMR_CURRENT_TIME_OFFSET 0x00000004 +#define TMR_CURRENT_TIME_INDEX 0x00000001 +#define TMR_CURRENT_TIME_RESET 0x00000000 + +__INLINE uint32_t tmr_current_time_get(void) +{ + return REG_PL_RD(TMR_CURRENT_TIME_ADDR); +} + +__INLINE void tmr_current_time_set(uint32_t value) +{ + REG_PL_WR(TMR_CURRENT_TIME_ADDR, value); +} + +// field definitions +#define TMR_TIME_MASK ((uint32_t)0x00FFFFFF) +#define TMR_TIME_LSB 0 +#define TMR_TIME_WIDTH ((uint32_t)0x00000018) + +#define TMR_TIME_RST 0x0 + +__INLINE uint32_t tmr_time_getf(void) +{ + uint32_t localVal = REG_PL_RD(TMR_CURRENT_TIME_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x00FFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief GROSS_TIME register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  23:00                gross   0x0
+ * 
+ */ +#define TMR_GROSS_TIME_ADDR 0x1000E008 +#define TMR_GROSS_TIME_OFFSET 0x00000008 +#define TMR_GROSS_TIME_INDEX 0x00000002 +#define TMR_GROSS_TIME_RESET 0x00000000 + +__INLINE uint32_t tmr_gross_time_get(void) +{ + return REG_PL_RD(TMR_GROSS_TIME_ADDR); +} + +__INLINE void tmr_gross_time_set(uint32_t value) +{ + REG_PL_WR(TMR_GROSS_TIME_ADDR, value); +} + +// field definitions +#define TMR_GROSS_MASK ((uint32_t)0x00FFFFFF) +#define TMR_GROSS_LSB 0 +#define TMR_GROSS_WIDTH ((uint32_t)0x00000018) + +#define TMR_GROSS_RST 0x0 + +__INLINE uint32_t tmr_gross_getf(void) +{ + uint32_t localVal = REG_PL_RD(TMR_GROSS_TIME_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x00FFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void tmr_gross_setf(uint32_t gross) +{ + ASSERT_ERR((((uint32_t)gross << 0) & ~((uint32_t)0x00FFFFFF)) == 0); + REG_PL_WR(TMR_GROSS_TIME_ADDR, (uint32_t)gross << 0); +} + +/** + * @brief STATUS register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     00               expire   0
+ * 
+ */ +#define TMR_STATUS_ADDR 0x1000E00C +#define TMR_STATUS_OFFSET 0x0000000C +#define TMR_STATUS_INDEX 0x00000003 +#define TMR_STATUS_RESET 0x00000000 + +__INLINE uint32_t tmr_status_get(void) +{ + return REG_PL_RD(TMR_STATUS_ADDR); +} + +__INLINE void tmr_status_set(uint32_t value) +{ + REG_PL_WR(TMR_STATUS_ADDR, value); +} + +// field definitions +#define TMR_EXPIRE_BIT ((uint32_t)0x00000001) +#define TMR_EXPIRE_POS 0 + +#define TMR_EXPIRE_RST 0x0 + +__INLINE uint8_t tmr_expire_getf(void) +{ + uint32_t localVal = REG_PL_RD(TMR_STATUS_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x00000001)) == 0); + return (localVal >> 0); +} + +__INLINE void tmr_expire_setf(uint8_t expire) +{ + ASSERT_ERR((((uint32_t)expire << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(TMR_STATUS_ADDR, (uint32_t)expire << 0); +} + + +#endif // _REG_TIMER_H_ + diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/reg_uart.h b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/reg_uart.h new file mode 100755 index 0000000..cc0502a --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/build/ble_full/reg/fw/reg_uart.h @@ -0,0 +1,509 @@ +#ifndef _REG_UART_H_ +#define _REG_UART_H_ + +#include +#include "_reg_uart.h" +#include "ble_compiler.h" +#include "architect.h" +#include "ble_reg_access.h" +#include "ble.h" + +#define REG_UART_COUNT 9 + +#define REG_UART_DECODING_MASK 0x0000003F + +/** + * @brief UART conf register definition + *
+ *   Bits           Field Name   Reset Value  
+ *  -----   ------------------   -----------
+ *	20:8					UART_CLK_DIVID	0        UART_CLK_DIVID=(UART_CLK/BAND - 1)
+ *  		7         UART_STOP_LEN   0				0: 1bit 1:2bits
+ *  		6         UART_PAR_MODE   0				0x0:ż 0x1
+ *  		5         UART_PAR_EN   	0
+ *  04:03         UART_LEN    		0  0:5bit 1:6bit 2:7bit 3:8bit
+ *     02         UART_IRDA  			 0
+ *     01        	UART_RX_ENABLE   0
+ *     00         UART_TX_ENABLE   0					
+ * 
+ */ +#if (BLE_DUT_UART_PORT == PORT_UART2) +#define UART_CONF_ADDR 0x00802200 +#else +#define UART_CONF_ADDR 0x00802100 +#endif // (BLE_DUT_UART_PORT == PORT_UART2) + +#define UART_CONF_OFFSET 0x00000000 +#define UART_CONF_INDEX 0x00000000 +#define UART_CONF_RESET 0x00000000 + +__INLINE uint32_t uart_conf_get(void) +{ + return REG_PL_RD(UART_CONF_ADDR); +} + +__INLINE void uart_conf_set(uint32_t value) +{ + REG_PL_WR(UART_CONF_ADDR, value); +} + + + +__INLINE void uart_conf_pack(uint8_t txen, uint8_t rxen, uint8_t irda, + uint8_t bitlen, uint8_t paren, uint8_t parmode,uint8_t stoplen,uint16_t clkdiv) +{ + + ASSERT_ERR((((uint32_t)clkdiv << 8) & ~((uint32_t)0x001FFF00)) == 0); + ASSERT_ERR((((uint32_t)stoplen << 7) & ~((uint32_t)0x00000080)) == 0); + ASSERT_ERR((((uint32_t)parmode << 6) & ~((uint32_t)0x00000040)) == 0); + ASSERT_ERR((((uint32_t)paren << 5) & ~((uint32_t)0x00000020)) == 0); + + ASSERT_ERR((((uint32_t)bitlen << 3) & ~((uint32_t)0x00000018)) == 0); + ASSERT_ERR((((uint32_t)irda << 2) & ~((uint32_t)0x00000004)) == 0); + ASSERT_ERR((((uint32_t)rxen << 1) & ~((uint32_t)0x00000002)) == 0); + ASSERT_ERR((((uint32_t)txen << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(UART_CONF_ADDR, ((uint32_t)clkdiv << 8) | ((uint32_t)stoplen << 7) | ((uint32_t)parmode << 6) | + ((uint32_t)paren << 5) | ((uint32_t)bitlen << 3) | ((uint32_t)irda << 2) | + ((uint32_t)rxen << 1) | ((uint32_t)txen << 0)); +} + +#if (BLE_DUT_UART_PORT == PORT_UART2) +#define UART_FIFO_CONF_ADDR 0x00802204 +#else +#define UART_FIFO_CONF_ADDR 0x00802104 +#endif // (BLE_DUT_UART_PORT == PORT_UART2) + + +__INLINE void uart_fifo_conf_pack(uint8_t tx_threshold, uint8_t rx_threshold, uint8_t rx_detect_time) +{ + ASSERT_ERR((((uint32_t)rx_detect_time << 9) & ~((uint32_t)0x00010000)) == 0); + ASSERT_ERR((((uint32_t)rx_threshold << 8) & ~((uint32_t)0x0000FF00)) == 0); + ASSERT_ERR((((uint32_t)tx_threshold << 0) & ~((uint32_t)0x00000000)) == 0); + + REG_PL_WR(UART_FIFO_CONF_ADDR, ((uint32_t)rx_detect_time << 9) | ((uint32_t)rx_threshold << 8) | ((uint32_t)tx_threshold << 0)); + +} + +__INLINE void uart_tx_fifo_threshold_setf(uint8_t threshold) +{ + ASSERT_ERR((((uint32_t)threshold << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(UART_FIFO_CONF_ADDR, (REG_PL_RD(UART_FIFO_CONF_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)threshold << 0)); +} + +__INLINE void uart_rx_fifo_threshold_setf(uint8_t threshold) +{ + ASSERT_ERR((((uint32_t)threshold << 8) & ~((uint32_t)0x0000FF00)) == 0); + REG_PL_WR(UART_FIFO_CONF_ADDR, (REG_PL_RD(UART_FIFO_CONF_ADDR) & ~((uint32_t)0x0000FF00)) | ((uint32_t)threshold << 8)); +} + +__INLINE void uart_rx_stop_edtect_time_setf(uint8_t time) +{ + ASSERT_ERR((((uint32_t)time << 9) & ~((uint32_t)0x00010000)) == 0); + REG_PL_WR(UART_FIFO_CONF_ADDR, (REG_PL_RD(UART_FIFO_CONF_ADDR) & ~((uint32_t)0x00010000)) | ((uint32_t)time << 8)); +} + + + + + + +#if (BLE_DUT_UART_PORT == PORT_UART2) +#define UART_FLOW_CONF_ADDR 0x00802218 +#else +#define UART_FLOW_CONF_ADDR 0x00802118 +#endif // (BLE_DUT_UART_PORT == PORT_UART2) + +__INLINE void uart_flow_en_setf(uint8_t forcerts) +{ + ASSERT_ERR((((uint32_t)forcerts << 16) & ~((uint32_t)0x00010000)) == 0); + REG_PL_WR(UART_FLOW_CONF_ADDR, (REG_PL_RD(UART_FLOW_CONF_ADDR) & ~((uint32_t)0x00010000)) | ((uint32_t)forcerts << 16)); +} + +__INLINE void uart_flow_cnt_low_setf(uint8_t cnt) +{ + ASSERT_ERR((((uint32_t)cnt << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(UART_FLOW_CONF_ADDR, (REG_PL_RD(UART_FLOW_CONF_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)cnt << 0)); +} + +__INLINE void uart_flow_cnt_high_setf(uint8_t cnt) +{ + ASSERT_ERR((((uint32_t)cnt << 8) & ~((uint32_t)0x0000FF00)) == 0); + REG_PL_WR(UART_FLOW_CONF_ADDR, (REG_PL_RD(UART_FLOW_CONF_ADDR) & ~((uint32_t)0x0000FF00)) | ((uint32_t)cnt << 8)); +} + + +__INLINE void uart_flow_rts_polarity_setf(uint8_t rts) +{ + ASSERT_ERR((((uint32_t)rts << 17) & ~((uint32_t)0x00010000)) == 0); + REG_PL_WR(UART_FLOW_CONF_ADDR, (REG_PL_RD(UART_FLOW_CONF_ADDR) & ~((uint32_t)0x00010000)) | ((uint32_t)rts << 17)); +} + +__INLINE void uart_flow_cts_polarity_setf(uint8_t cts) +{ + ASSERT_ERR((((uint32_t)cts << 18) & ~((uint32_t)0x00020000)) == 0); + REG_PL_WR(UART_FLOW_CONF_ADDR, (REG_PL_RD(UART_FLOW_CONF_ADDR) & ~((uint32_t)0x00020000)) | ((uint32_t)cts << 18)); +} + + + +/** + * @brief FIFO_STATUS register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     21       FIFO_RD_READY   0
+ *     20       FIFO_WR_READY   0
+ *     19       RX_FIFO_EMPTY   0
+ *     18       RX_FIFO_FULL   0
+ *     17       TX_FIFO_EMPTY   0
+ *     16       TX_FIFO_FULL  0
+ *     8-15     RX_FIFO_COUNT   0
+ *     0-7      TX_FIFO_COUNT   0
+ * 
+ */ +#if (BLE_DUT_UART_PORT == PORT_UART2) +#define UART_FIFO_STATUS_ADDR 0x00802208 +#else +#define UART_FIFO_STATUS_ADDR 0x00802108 +#endif // (BLE_DUT_UART_PORT == PORT_UART2) + +__INLINE uint8_t uart_tx_fifo_count_getf(void) +{ + uint32_t localVal = REG_PL_RD(UART_FIFO_STATUS_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +__INLINE uint8_t uart_rx_fifo_count_getf(void) +{ + uint32_t localVal = REG_PL_RD(UART_FIFO_STATUS_ADDR); + return ((localVal & ((uint32_t)0x0000FF00)) >> 8); +} + + +__INLINE uint8_t uart_tx_fifo_full_getf(void) +{ + uint32_t localVal = REG_PL_RD(UART_FIFO_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00010000)) >> 16); +} +__INLINE uint8_t uart_tx_fifo_empty_getf(void) +{ + uint32_t localVal = REG_PL_RD(UART_FIFO_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00020000)) >> 17); +} + +__INLINE uint8_t uart_rx_fifo_full_getf(void) +{ + uint32_t localVal = REG_PL_RD(UART_FIFO_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00040000)) >> 18); +} + +__INLINE uint8_t uart_rx_fifo_empty_getf(void) +{ + uint32_t localVal = REG_PL_RD(UART_FIFO_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00080000)) >> 19); +} + +__INLINE uint8_t uart_tx_fifo_wr_ready_getf(void) +{ + uint32_t localVal = REG_PL_RD(UART_FIFO_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00100000)) >> 20); +} + +__INLINE uint8_t uart_rx_fifo_rd_ready_getf(void) +{ + uint32_t localVal = REG_PL_RD(UART_FIFO_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00200000)) >> 21); +} + + +__INLINE uint8_t uart_ext_wakeup_getf() +{ + return 0 ; +} + + +/** + * @brief CLK register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00                 FREQ   0x0
+ * 
+ */ + + +__INLINE uint32_t uart_clk_get(void) +{ + return 16000000; +} + + +/** + * @brief INT_STATUS register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     07    UART_RXD_WAKEUP   0
+ *     06    UART_RX_STOP_END   0
+ *     05    UART_TX_STOP_END  0
+ *     04    UART_RX_STOP_ERROR   0
+ *     03    UART_RX_PARITY_ERROR   0
+ *     02    RX_FIFO_OVER_FLOW          0
+ *     01    RX_FIFO_NEED_READ   0
+ *     00    TX_FIFO_NEED_WRITE   0
+ * 
+ */ +#if (BLE_DUT_UART_PORT == PORT_UART2) +#define UART_ISR_STAT_ADDR 0x00802214 +#else +#define UART_ISR_STAT_ADDR 0x00802114 +#endif // (BLE_DUT_UART_PORT == PORT_UART2) + + +__INLINE uint32_t uart_isr_stat_get(void) +{ + return REG_PL_RD(UART_ISR_STAT_ADDR); +} + +__INLINE void uart_isr_stat_set( uint8_t stat) +{ + ASSERT_ERR((((uint32_t)stat << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(UART_ISR_STAT_ADDR, (REG_PL_RD(UART_ISR_STAT_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)stat << 0)); + //(*(volatile uint32_t *)(UART_ISR_STAT_ADDR)) = stat; +} + +__INLINE uint8_t uart_tx_fifo_need_wr_isr_getf(void) +{ + uint32_t localVal = REG_PL_RD(UART_ISR_STAT_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +__INLINE uint8_t uart_rx_fifo_need_rd_isr_getf(void) +{ + uint32_t localVal = REG_PL_RD(UART_ISR_STAT_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + + +__INLINE uint8_t uart_rx_fifo_over_isr_getf(void) +{ + uint32_t localVal = REG_PL_RD(UART_ISR_STAT_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +__INLINE void uart_rx_fifo_over_isr_clr_setf(uint8_t rx_fifo_over) +{ + ASSERT_ERR((((uint32_t)rx_fifo_over << 2) & ~((uint32_t)0x00000004)) == 0); + REG_PL_WR(UART_ISR_STAT_ADDR, (REG_PL_RD(UART_ISR_STAT_ADDR) & ~((uint32_t)0x00000004)) | ((uint32_t)rx_fifo_over << 2)); + +} + + +__INLINE uint8_t uart_rx_parity_err_isr_getf(void) +{ + uint32_t localVal = REG_PL_RD(UART_ISR_STAT_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +__INLINE void uart_rx_parity_err_isr_clr_setf(uint8_t rx_parity_err) +{ + ASSERT_ERR((((uint32_t)rx_parity_err << 3) & ~((uint32_t)0x00000008)) == 0); + REG_PL_WR(UART_ISR_STAT_ADDR, (REG_PL_RD(UART_ISR_STAT_ADDR) & ~((uint32_t)0x00000008)) | ((uint32_t)rx_parity_err << 3)); +} + +__INLINE uint8_t uart_rx_stopbit_err_isr_getf(void) +{ + uint32_t localVal = REG_PL_RD(UART_ISR_STAT_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +__INLINE void uart_rx_stopbit_err_isr_clr_setf(uint8_t rx_stopbit_err) +{ + ASSERT_ERR((((uint32_t)rx_stopbit_err << 4) & ~((uint32_t)0x00000010)) == 0); + REG_PL_WR(UART_ISR_STAT_ADDR, (REG_PL_RD(UART_ISR_STAT_ADDR) & ~((uint32_t)0x00000010)) | ((uint32_t)rx_stopbit_err << 4)); +} + + +__INLINE uint8_t uart_tx_end_isr_getf(void) +{ + uint32_t localVal = REG_PL_RD(UART_ISR_STAT_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +__INLINE void uart_tx_end_isr_clr_setf(uint8_t tx_end) +{ + ASSERT_ERR((((uint32_t)tx_end << 5) & ~((uint32_t)0x00000020)) == 0); + REG_PL_WR(UART_ISR_STAT_ADDR, (REG_PL_RD(UART_ISR_STAT_ADDR) & ~((uint32_t)0x00000020)) | ((uint32_t)tx_end << 5)); +} + +__INLINE uint8_t uart_rx_end_isr_getf(void) +{ + uint32_t localVal = REG_PL_RD(UART_ISR_STAT_ADDR); + return ((localVal & ((uint32_t)0x00000040)) >> 6); +} +__INLINE void uart_rx_end_isr_clr_setf(uint8_t rx_end) +{ + ASSERT_ERR((((uint32_t)rx_end << 6) & ~((uint32_t)0x00000040)) == 0); + REG_PL_WR(UART_ISR_STAT_ADDR, (REG_PL_RD(UART_ISR_STAT_ADDR) & ~((uint32_t)0x00000040)) | ((uint32_t)rx_end << 6)); +} + +__INLINE uint8_t uart_rxd_wakeup_isr_getf(void) +{ + uint32_t localVal = REG_PL_RD(UART_ISR_STAT_ADDR); + return ((localVal & ((uint32_t)0x00000080)) >> 7); +} + +__INLINE void uart_rxd_wakeup_isr_clr_setf(uint8_t rxd_wakeup) +{ + ASSERT_ERR((((uint32_t)rxd_wakeup << 7) & ~((uint32_t)0x00000080)) == 0); + REG_PL_WR(UART_ISR_STAT_ADDR, (REG_PL_RD(UART_ISR_STAT_ADDR) & ~((uint32_t)0x00000080)) | ((uint32_t)rxd_wakeup << 7)); +} + + +/** + * @brief ISR_EN register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     
+ * 
+ */ +#if (BLE_DUT_UART_PORT == PORT_UART2) +#define UART_ISR_EN_ADDR 0x00802210 +#else +#define UART_ISR_EN_ADDR 0x00802110 +#endif // (BLE_DUT_UART_PORT == PORT_UART2) + + +__INLINE void uart_isr_en_set(uint32_t value) +{ + REG_PL_WR(UART_ISR_EN_ADDR, value); +} + + + +__INLINE void uart_isr_en_pack(uint8_t rx_need_rd, uint8_t tx_need_wr, uint8_t rx_over, + uint8_t rx_parity_err, uint8_t rx_stopbit_err, uint8_t tx_end, uint8_t rx_end, + uint8_t rxd_wakeup) +{ + ASSERT_ERR((((uint32_t)rxd_wakeup << 7) & ~((uint32_t)0x00000080)) == 0); + + ASSERT_ERR((((uint32_t)rx_end << 6) & ~((uint32_t)0x00000040)) == 0); + ASSERT_ERR((((uint32_t)tx_end << 5) & ~((uint32_t)0x00000020)) == 0); + ASSERT_ERR((((uint32_t)rx_stopbit_err << 4) & ~((uint32_t)0x00000010)) == 0); + ASSERT_ERR((((uint32_t)rx_parity_err << 3) & ~((uint32_t)0x00000008)) == 0); + ASSERT_ERR((((uint32_t)rx_over << 2) & ~((uint32_t)0x00000004)) == 0); + ASSERT_ERR((((uint32_t)tx_need_wr << 1) & ~((uint32_t)0x00000002)) == 0); + ASSERT_ERR((((uint32_t)rx_need_rd << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(UART_ISR_EN_ADDR, ((uint32_t)rxd_wakeup << 7) | ((uint32_t)rx_end << 6) | + ((uint32_t)tx_end << 5) | ((uint32_t)rx_stopbit_err << 4) | ((uint32_t)rx_parity_err << 3) | + ((uint32_t)rx_over << 2) |((uint32_t)tx_need_wr << 1) |((uint32_t)rx_need_rd << 0)); +} + + +__INLINE uint8_t uart_rx_wakeup_en_getf(void) +{ + uint32_t localVal = REG_PL_RD(UART_ISR_EN_ADDR); + return ((localVal & ((uint32_t)0x00000080)) >> 7); +} + +__INLINE void uart_rx_wakeup_en_setf(uint8_t wakernel_up) +{ + ASSERT_ERR((((uint32_t)wakernel_up << 7) & ~((uint32_t)0x00000080)) == 0); + REG_PL_WR(UART_ISR_EN_ADDR, (REG_PL_RD(UART_ISR_EN_ADDR) & ~((uint32_t)0x00000080)) | ((uint32_t)wakernel_up << 7)); +} + + +__INLINE uint8_t uart_rx_end_en_getf(void) +{ + uint32_t localVal = REG_PL_RD(UART_ISR_EN_ADDR); + return ((localVal & ((uint32_t)0x00000040)) >> 6); +} + +__INLINE void uart_rx_end_en_setf(uint8_t rx_end) +{ + ASSERT_ERR((((uint32_t)rx_end << 6) & ~((uint32_t)0x00000040)) == 0); + REG_PL_WR(UART_ISR_EN_ADDR, (REG_PL_RD(UART_ISR_EN_ADDR) & ~((uint32_t)0x00000040)) | ((uint32_t)rx_end << 6)); +} + +__INLINE uint8_t uart_tx_end_en_getf(void) +{ + uint32_t localVal = REG_PL_RD(UART_ISR_EN_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +__INLINE void uart_tx_end_en_setf(uint8_t tx_end) +{ + ASSERT_ERR((((uint32_t)tx_end << 5) & ~((uint32_t)0x00000020)) == 0); + REG_PL_WR(UART_ISR_EN_ADDR, (REG_PL_RD(UART_ISR_EN_ADDR) & ~((uint32_t)0x00000020)) | ((uint32_t)tx_end << 5)); +} + + +__INLINE uint8_t uart_rx_stopbit_err_en_getf(void) +{ + uint32_t localVal = REG_PL_RD(UART_ISR_EN_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +__INLINE void uart_rx_stopbit_err_en_setf(uint8_t rx_stopbit_err) +{ + ASSERT_ERR((((uint32_t)rx_stopbit_err << 4) & ~((uint32_t)0x00000010)) == 0); + REG_PL_WR(UART_ISR_EN_ADDR, (REG_PL_RD(UART_ISR_EN_ADDR) & ~((uint32_t)0x00000010)) | ((uint32_t)rx_stopbit_err << 4)); +} + + +__INLINE uint8_t uart_rx_parity_err_en_getf(void) +{ + uint32_t localVal = REG_PL_RD(UART_ISR_EN_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +__INLINE void uart_rx_parity_err_en_setf(uint8_t rx_parity_err) +{ + ASSERT_ERR((((uint32_t)rx_parity_err << 3) & ~((uint32_t)0x00000008)) == 0); + REG_PL_WR(UART_ISR_EN_ADDR, (REG_PL_RD(UART_ISR_EN_ADDR) & ~((uint32_t)0x00000008)) | ((uint32_t)rx_parity_err << 3)); +} + + +__INLINE uint8_t uart_rx_over_en_getf(void) +{ + uint32_t localVal = REG_PL_RD(UART_ISR_EN_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +__INLINE void uart_rx_over_en_setf(uint8_t rx_over) +{ + ASSERT_ERR((((uint32_t)rx_over << 2) & ~((uint32_t)0x00000004)) == 0); + REG_PL_WR(UART_ISR_EN_ADDR, (REG_PL_RD(UART_ISR_EN_ADDR) & ~((uint32_t)0x00000004)) | ((uint32_t)rx_over << 2)); +} + + +__INLINE uint8_t uart_tx_need_wr_en_getf(void) +{ + uint32_t localVal = REG_PL_RD(UART_ISR_EN_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +__INLINE void uart_tx_need_wr_en_setf(uint8_t tx_need_wr) +{ + ASSERT_ERR((((uint32_t)tx_need_wr << 1) & ~((uint32_t)0x00000002)) == 0); + REG_PL_WR(UART_ISR_EN_ADDR, (REG_PL_RD(UART_ISR_EN_ADDR) & ~((uint32_t)0x00000002)) | ((uint32_t)tx_need_wr << 1)); +} + + +__INLINE uint8_t uart_rx_need_rd_en_getf(void) +{ + uint32_t localVal = REG_PL_RD(UART_ISR_EN_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +__INLINE void uart_rx_need_rd_en_setf(uint8_t rx_need_rd) +{ + ASSERT_ERR((((uint32_t)rx_need_rd << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(UART_ISR_EN_ADDR, (REG_PL_RD(UART_ISR_EN_ADDR) & ~((uint32_t)0x00000001)) | ((uint32_t)rx_need_rd << 0)); +} + + + +#endif // _REG_UART_H_ + diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/driver/ble_icu/ble_icu.c b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/driver/ble_icu/ble_icu.c new file mode 100755 index 0000000..f1f8b29 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/driver/ble_icu/ble_icu.c @@ -0,0 +1,197 @@ +/** +**************************************************************************************** +* +* @file icu.c +* +* @brief icu initialization and specific functions +* +* Copyright (C) Beken 2009-2016 +* +* $Rev: $ +* +**************************************************************************************** +*/ + +/** +**************************************************************************************** +* @addtogroup ICU +* @ingroup ICU +* @brief ICU +* +* This is the driver block for ICU +* @{ +**************************************************************************************** +*/ + + +#include // standard definition + +#include "driver_sys_ctrl.h" + + + + +void DelayNops(volatile unsigned long nops) +{ + while (nops --) + { + } +} + + +void DelayUS(volatile unsigned long timesUS) +{ + volatile unsigned long i; + + // unsigned long tick_cnt = 8; // 24MHz, DelayUS(1000)ƽDelayUS(1) = 1.052us + #if (MCU_CLK == MCU_CLK_26MHz) + // unsigned long tick_cnt_us = 3; // 26MHz, DelayUS(1000)ƽDelayUS(1) = 1.028us + #define tick_cnt_us 3 + #elif (MCU_CLK == MCU_CLK_120MHz) /* #if (MCU_CLK == MCU_CLK_26MHz) */ + #define tick_cnt_us 28 + #endif /* #if (MCU_CLK == MCU_CLK_26MHz) */ +// printf("tick_cnt = 0x%x\r\n", tick_cnt); + while (timesUS --) + { + i = 0; + while (i < tick_cnt_us) + { + i++; + } + } +} + + +// set CPU clk to DPLL +void set_CPU_clk_DPLL(void) +{ + REG_SYS_CTRL_BLOCK_EN = (REG_SYS_CTRL_BLOCK_EN + & (~SYS_CTRL_BLOCK_EN_VALID_MASK)) + | SYS_CTRL_BLOCK_EN_VALID_SET + | SYS_CTRL_BLOCK_EN_SW_XTAL_26MHz; + + REG_SYS_CTRL_ANALOG_REG0 = 0x0819A54B; + REG_SYS_CTRL_ANALOG_REG1 = 0x6AC03102; +// REG_SYS_CTRL_ANALOG_REG2 = 0x24006000; + REG_SYS_CTRL_ANALOG_REG2 = 0x27006000; + REG_SYS_CTRL_ANALOG_REG3 = 0x4FE06C50; + REG_SYS_CTRL_ANALOG_REG4 = 0x59E04520; + DelayNops(100); + REG_SYS_CTRL_ANALOG_REG0 = 0x0811A54B; + DelayNops(100); + REG_SYS_CTRL_ANALOG_REG0 = 0x0819A54B; + DelayNops(1000); + + DelayUS(100); + REG_SYS_CTRL_CLK_SET = (REG_SYS_CTRL_CLK_SET + & (~SYS_CTRL_CLK_SET_MCLK_MASK) + & (~SYS_CTRL_CLK_SET_MCLK_DIV_MASK)) +// | (5 << SYS_CTRL_CLK_SET_MCLK_DIV_POSI) + | SYS_CTRL_CLK_SET_MCLK_DPLL; + DelayUS(100); +} + + +// set PCLK to XTAL 26MHz +void set_PCLK_clk_XTAL_26MHz(void) +{ + REG_ICU_PERI_CLK_MUX = ICU_PERI_CLK_MUX_SEL_XTAL_26M; +} + +// set PCLK to DCO clock +void set_PCLK_clk_DCO_CLK(void) +{ + REG_ICU_PERI_CLK_MUX = ICU_PERI_CLK_MUX_SEL_DCO_CLK; +} + + +void set_LPO_clk_ROSC_32KHz(void) +{ + REG_SYS_CTRL_LPO_CLK = SYS_CTRL_LPO_CLK_MUX_ROSC_32KHz; + REG_SYS_CTRL_ROSC_CONFIG = 0x37; +} + +void set_LPO_clk_XTAL_32KHz(void) +{ + REG_SYS_CTRL_LPO_CLK = SYS_CTRL_LPO_CLK_MUX_XTAL_32KHz; +} + +void set_LPO_clk_32KHz_div_from_XTAL_26MHz(void) +{ + REG_SYS_CTRL_LPO_CLK = SYS_CTRL_LPO_CLK_MUX_DIV_32KHz; +} + + +// set CPU clk to XTAL 26MHz +void set_CPU_clk_XTAL_26MHz(void) +{ + REG_SYS_CTRL_BLOCK_EN = (REG_SYS_CTRL_BLOCK_EN + & (~SYS_CTRL_BLOCK_EN_VALID_MASK)) + | SYS_CTRL_BLOCK_EN_VALID_SET + | SYS_CTRL_BLOCK_EN_SW_XTAL_26MHz; + DelayUS(100); + REG_SYS_CTRL_CLK_SET = (REG_SYS_CTRL_CLK_SET + & (~SYS_CTRL_CLK_SET_MCLK_MASK)) + | SYS_CTRL_CLK_SET_MCLK_XTAL_26M; + DelayUS(100); +} + + + + + +void ble_icu_init(void) +{ +/* REG_SYS_CTRL_BLOCK_EN = (REG_SYS_CTRL_BLOCK_EN + & (~SYS_CTRL_BLOCK_EN_VALID_MASK)) + | SYS_CTRL_BLOCK_EN_VALID_SET + | SYS_CTRL_BLOCK_EN_SW_FLASH + | SYS_CTRL_BLOCK_EN_SW_DCO_26MHz + | SYS_CTRL_BLOCK_EN_SW_DPLL + | SYS_CTRL_BLOCK_EN_SW_XTAL_TO_RF + | SYS_CTRL_BLOCK_EN_SW_ROSC_32KHz + | SYS_CTRL_BLOCK_EN_SW_XTAL_26MHz + | SYS_CTRL_BLOCK_EN_SW_XTAL_32KHz;*/ + REG_WIFI_PWD = 0x0; + REG_DSP_PWD = 0x0; + REG_USB_PWD = 0x0; + (*((volatile unsigned long *) 0x01050000)) = 0x09; + + DelayUS(100); + + set_LPO_clk_ROSC_32KHz(); + +#if (MCU_CLK == MCU_CLK_26MHz) + set_CPU_clk_XTAL_26MHz(); + REG_SYS_CTRL_ANALOG_REG4 = 0x59E04520; +#elif (MCU_CLK == MCU_CLK_120MHz) + set_CPU_clk_DPLL(); +#endif + +#if (PER_CLK == PER_CLK_26MHz) + set_PCLK_clk_XTAL_26MHz(); +#elif (PER_CLK == PER_CLK_120MHz) + DcoCalib(DCO_CALIB_120M); + set_PCLK_clk_DCO_CLK(); +#endif + DelayUS(100); +// REG_SYS_CTRL_CLK_SET |= SYS_CTRL_CLK_SET_AHB_CLK_DIV_MASK; + + REG_SYS_CTRL_BIAS_CALIB = (REG_SYS_CTRL_BIAS_CALIB + & (~(SYS_CTRL_BIAS_CALIB_MANUAL_MASK | SYS_CTRL_BIAS_CALIB_SETTING_MASK))) + | (0x01 << SYS_CTRL_BIAS_CALIB_MANUAL_POSI) + | (0x14 << SYS_CTRL_BIAS_CALIB_SETTING_POSI); + + // REG_ICU_INT_ENABLE = 1<<30; + // REG_ICU_INT_GLOBAL_ENABLE = (ICU_INT_GLOBAL_ENABLE_IRQ_MASK | ICU_INT_GLOBAL_ENABLE_FIQ_MASK); + +} + + + + + + + + + diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/driver/ble_icu/ble_icu.h b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/driver/ble_icu/ble_icu.h new file mode 100755 index 0000000..7c50d78 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/driver/ble_icu/ble_icu.h @@ -0,0 +1,65 @@ +#ifndef _BLE_ICU_H_ +#define _BLE_ICU_H_ + +#include "stdint.h" + + +#define MCU_CLK_16M 1 +#define MCU_CLK_64M 2 +#define MCU_CLK_32M 3 +#define MCU_CLK_48M 4 + + +#define DEBUG_HW 0 + +#define MCU_DEFAULT_CLK MCU_CLK_16M //MCU_CLK_64M + +#define MCU_CLK_32KHz 32000 +#define MCU_CLK_16MHz 16000000 +#define MCU_CLK_26MHz 26000000 +#define MCU_CLK_48MHz 48000000 +#define MCU_CLK_96MHz 96000000 +#define MCU_CLK_120MHz 120000000 + +#define MCU_CLK MCU_CLK_26MHz// MCU_CLK_120MHz + + +#define PER_CLK_32KHz 32000 +#define PER_CLK_16MHz 16000000 +#define PER_CLK_26MHz 26000000 +#define PER_CLK_48MHz 48000000 +#define PER_CLK_96MHz 96000000 +#define PER_CLK_120MHz 120000000 + +#define PER_CLK PER_CLK_26MHz + + + + + + + + + + + +void ble_sleep(void); + +void ble_icu_init(void); + +void cpu_reduce_voltage_sleep(void); + +void cpu_idle_sleep(void); + +void cpu_wakeup(void); + +void mcu_clk_config(void); + +void udi_wdt_enable(uint16_t wdt_cnt); + +void switch_clk(uint8_t clk); + +void bk3435_singleWaveCfg(uint8_t freq, uint8_t power_level); + +#endif + diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/driver/ble_icu/driver_sys_ctrl.h b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/driver/ble_icu/driver_sys_ctrl.h new file mode 100755 index 0000000..dd29726 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/driver/ble_icu/driver_sys_ctrl.h @@ -0,0 +1,298 @@ +/************************************************************* + * @file driver_sys_ctrl.h + * @brief Header file of driver_sys_ctrl.c + * @author GuWenFu + * @version V1.0 + * @date 2016-09-29 + * @par + * @attention + * + * @history 2016-09-29 gwf create this file + */ + +#ifndef __DRIVER_SYS_CTRL_H__ + +#define __DRIVER_SYS_CTRL_H__ + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + + + + +#define REG_SYS_CTRL_BASE_ADDR (0x00800000UL) + + +#define REG_SYS_CTRL_CHIP_ID_ADDR (REG_SYS_CTRL_BASE_ADDR + 0x00 * 4) +#define REG_SYS_CTRL_CHIP_ID_MASK 0xFFFFFFFFUL +#define REG_SYS_CTRL_CHIP_ID (*((volatile unsigned long *) REG_SYS_CTRL_CHIP_ID_ADDR)) + + +#define REG_SYS_CTRL_DEVICE_ID_ADDR (REG_SYS_CTRL_BASE_ADDR + 0x01 * 4) +#define REG_SYS_CTRL_DEVICE_ID_MASK 0xFFFFFFFFUL +#define REG_SYS_CTRL_DEVICE_ID (*((volatile unsigned long *) REG_SYS_CTRL_DEVICE_ID_ADDR)) + + +#define REG_SYS_CTRL_CLK_SET_ADDR (REG_SYS_CTRL_BASE_ADDR + 0x02 * 4) +#define REG_SYS_CTRL_CLK_SET_MASK 0x00003FF3UL +#define REG_SYS_CTRL_CLK_SET (*((volatile unsigned long *) REG_SYS_CTRL_CLK_SET_ADDR)) + +#define SYS_CTRL_CLK_SET_MCLK_POSI 0 +#define SYS_CTRL_CLK_SET_MCLK_MASK (0x03UL << SYS_CTRL_CLK_SET_MCLK_POSI) +#define SYS_CTRL_CLK_SET_MCLK_DCO (0x00UL << SYS_CTRL_CLK_SET_MCLK_POSI) +#define SYS_CTRL_CLK_SET_MCLK_XTAL_26M (0x01UL << SYS_CTRL_CLK_SET_MCLK_POSI) +#define SYS_CTRL_CLK_SET_MCLK_DPLL (0x02UL << SYS_CTRL_CLK_SET_MCLK_POSI) +#define SYS_CTRL_CLK_SET_MCLK_LPO (0x03UL << SYS_CTRL_CLK_SET_MCLK_POSI) + +#define SYS_CTRL_CLK_SET_MCLK_DIV_POSI 4 +#define SYS_CTRL_CLK_SET_MCLK_DIV_MASK (0x0FUL << SYS_CTRL_CLK_SET_MCLK_DIV_POSI) + +#define SYS_CTRL_CLK_SET_FLASH_26M_POSI 8 +#define SYS_CTRL_CLK_SET_FLASH_26M_MASK (0x01UL << SYS_CTRL_CLK_SET_FLASH_26M_POSI) + +#define SYS_CTRL_CLK_SET_AHB_CLK_DIV_POSI 9 +#define SYS_CTRL_CLK_SET_AHB_CLK_DIV_MASK (0x01UL << SYS_CTRL_CLK_SET_AHB_CLK_DIV_POSI) + +#define SYS_CTRL_CLK_SET_MODEM_PWD_POSI 10 +#define SYS_CTRL_CLK_SET_MODEM_PWD_MASK (0x01UL << SYS_CTRL_CLK_SET_MODEM_PWD_POSI) + +#define SYS_CTRL_CLK_SET_MAC_PWD_POSI 11 +#define SYS_CTRL_CLK_SET_MAC_PWD_MASK (0x01UL << SYS_CTRL_CLK_SET_MAC_PWD_POSI) + +#define SYS_CTRL_CLK_SET_MPIF_CLK_POSI 12 +#define SYS_CTRL_CLK_SET_MPIF_CLK_MASK (0x01UL << SYS_CTRL_CLK_SET_MPIF_CLK_POSI) + +#define SYS_CTRL_CLK_SET_SDIO_CLK_POSI 13 +#define SYS_CTRL_CLK_SET_SDIO_CLK_MASK (0x01UL << SYS_CTRL_CLK_SET_SDIO_CLK_POSI) + + +#define REG_SYS_CTRL_RESET_ADDR (REG_SYS_CTRL_BASE_ADDR + 0x04 * 4) +#define REG_SYS_CTRL_RESET_MASK 0x000000FFUL +#define REG_SYS_CTRL_RESET (*((volatile unsigned long *) REG_SYS_CTRL_RESET_ADDR)) + +#define SYS_CTRL_MODEM_SUBCHIP_RESET_POSI 0 +#define SYS_CTRL_MODEM_SUBCHIP_RESET_MASK (0x01UL << SYS_CTRL_MODEM_SUBCHIP_RESET_POSI) + +#define SYS_CTRL_DSP_SUBSYS_RESET_POSI 1 +#define SYS_CTRL_DSP_SUBSYS_RESET_MASK (0x01UL << SYS_CTRL_DSP_SUBSYS_RESET_POSI) + +#define SYS_CTRL_MAC_SUBSYS_RESET_POSI 2 +#define SYS_CTRL_MAC_SUBSYS_RESET_MASK (0x01UL << SYS_CTRL_MAC_SUBSYS_RESET_POSI) + +#define SYS_CTRL_TL410_BOOT_POSI 3 +#define SYS_CTRL_TL410_BOOT_MASK (0x01UL << SYS_CTRL_TL410_BOOT_POSI) +#define SYS_CTRL_TL410_BOOT_CLEAR (0x00UL << SYS_CTRL_TL410_BOOT_POSI) +#define SYS_CTRL_TL410_BOOT_SET (0x01UL << SYS_CTRL_TL410_BOOT_POSI) + +#define SYS_CTRL_USB_SUBSYS_RESET_POSI 4 +#define SYS_CTRL_USB_SUBSYS_RESET_MASK (0x01UL << SYS_CTRL_USB_SUBSYS_RESET_POSI) + +#define SYS_CTRL_TL410_EXT_WAIT_POSI 5 +#define SYS_CTRL_TL410_EXT_WAIT_MASK (0x01UL << SYS_CTRL_TL410_EXT_WAIT_POSI) +#define SYS_CTRL_TL410_EXT_WAIT_CLEAR (0x00UL << SYS_CTRL_TL410_EXT_WAIT_POSI) +#define SYS_CTRL_TL410_EXT_WAIT_SET (0x01UL << SYS_CTRL_TL410_EXT_WAIT_POSI) + +#define SYS_CTRL_MODEM_CORE_RESET_POSI 6 +#define SYS_CTRL_MODEM_CORE_RESET_MASK (0x01UL << SYS_CTRL_MODEM_CORE_RESET_POSI) + +#define SYS_CTRL_MAC_WAKEUP_ARM_POSI 7 +#define SYS_CTRL_MAC_WAKEUP_ARM_MASK (0x01UL << SYS_CTRL_MAC_WAKEUP_ARM_POSI) +#define SYS_CTRL_MAC_WAKEUP_ARM_CLEAR (0x00UL << SYS_CTRL_MAC_WAKEUP_ARM_POSI) +#define SYS_CTRL_MAC_WAKEUP_ARM_SET (0x01UL << SYS_CTRL_MAC_WAKEUP_ARM_POSI) + + +#define REG_SYS_CTRL_DSP_SUBSYS_RESET_REQ_ADDR (REG_SYS_CTRL_BASE_ADDR + 0x0B * 4) +#define REG_SYS_CTRL_DSP_SUBSYS_RESET_REQ_MASK 0xFFFFFFFFUL +#define REG_SYS_CTRL_DSP_SUBSYS_RESET_REQ (*((volatile unsigned long *) REG_SYS_CTRL_DSP_SUBSYS_RESET_REQ_ADDR)) + +#define DSP_SUBSYS_RESET_REQ_WORD_POSI 0 +#define DSP_SUBSYS_RESET_REQ_WORD_MASK (0xFFFFFFFFUL << DSP_SUBSYS_RESET_REQ_WORD_POSI) +#define DSP_SUBSYS_RESET_REQ_WORD 0x7111C410UL + + +#define REG_SYS_CTRL_ANALOG_REG0_ADDR (REG_SYS_CTRL_BASE_ADDR + 0x16 * 4) +#define REG_SYS_CTRL_ANALOG_REG0_MASK 0xFFFFFFFFUL +#define REG_SYS_CTRL_ANALOG_REG0 (*((volatile unsigned long *) REG_SYS_CTRL_ANALOG_REG0_ADDR)) + + +#define REG_SYS_CTRL_ANALOG_REG1_ADDR (REG_SYS_CTRL_BASE_ADDR + 0x17 * 4) +#define REG_SYS_CTRL_ANALOG_REG1_MASK 0xFFFFFFFFUL +#define REG_SYS_CTRL_ANALOG_REG1 (*((volatile unsigned long *) REG_SYS_CTRL_ANALOG_REG1_ADDR)) + + +#define REG_SYS_CTRL_ANALOG_REG2_ADDR (REG_SYS_CTRL_BASE_ADDR + 0x18 * 4) +#define REG_SYS_CTRL_ANALOG_REG2_MASK 0xFFFFFFFFUL +#define REG_SYS_CTRL_ANALOG_REG2 (*((volatile unsigned long *) REG_SYS_CTRL_ANALOG_REG2_ADDR)) + + +#define REG_SYS_CTRL_ANALOG_REG3_ADDR (REG_SYS_CTRL_BASE_ADDR + 0x19 * 4) +#define REG_SYS_CTRL_ANALOG_REG3_MASK 0xFFFFFFFFUL +#define REG_SYS_CTRL_ANALOG_REG3 (*((volatile unsigned long *) REG_SYS_CTRL_ANALOG_REG3_ADDR)) + + +#define REG_SYS_CTRL_ANALOG_REG4_ADDR (REG_SYS_CTRL_BASE_ADDR + 0x1A * 4) +#define REG_SYS_CTRL_ANALOG_REG4_MASK 0xFFFFFFFFUL +#define REG_SYS_CTRL_ANALOG_REG4 (*((volatile unsigned long *) REG_SYS_CTRL_ANALOG_REG4_ADDR)) + +#define REG_SYS_CTRL_BLE_SUBSYS_ADDR (REG_SYS_CTRL_BASE_ADDR + 0x20 * 4) +#define REG_SYS_CTRL_BLE_SUBSYS_MASK 0xFFFFFFFFUL +#define REG_SYS_CTRL_BLE_SUBSYS (*((volatile unsigned long *) REG_SYS_CTRL_BLE_SUBSYS_ADDR)) + +#define REG_SYS_CTRL_LPO_CLK_ADDR (REG_SYS_CTRL_BASE_ADDR + 0x40 * 4) +#define REG_SYS_CTRL_LPO_CLK_MASK 0x03UL +#define REG_SYS_CTRL_LPO_CLK (*((volatile unsigned long *) REG_SYS_CTRL_LPO_CLK_ADDR)) + +#define SYS_CTRL_LPO_CLK_MUX_POSI 0 +#define SYS_CTRL_LPO_CLK_MUX_MASK (0x03UL << SYS_CTRL_LPO_CLK_MUX_POSI) +#define SYS_CTRL_LPO_CLK_MUX_ROSC_32KHz (0x00UL << SYS_CTRL_LPO_CLK_MUX_POSI) +#define SYS_CTRL_LPO_CLK_MUX_XTAL_32KHz (0x01UL << SYS_CTRL_LPO_CLK_MUX_POSI) +#define SYS_CTRL_LPO_CLK_MUX_DIV_32KHz (0x02UL << SYS_CTRL_LPO_CLK_MUX_POSI) + + +#define REG_SYS_CTRL_SLEEP_ADDR (REG_SYS_CTRL_BASE_ADDR + 0x41 * 4) +#define REG_SYS_CTRL_SLEEP_MASK 0x00F7FFFFUL +#define REG_SYS_CTRL_SLEEP (*((volatile unsigned long *) REG_SYS_CTRL_SLEEP_ADDR)) + +#define SYS_CTRL_SLEEP_SLEEP_MODE_POSI 0 +#define SYS_CTRL_SLEEP_SLEEP_MODE_MASK (0x0000FFFF << SYS_CTRL_SLEEP_SLEEP_MODE_POSI) +#define SYS_CTRL_SLEEP_SLEEP_MODE_NORMAL (0x00004F89 << SYS_CTRL_SLEEP_SLEEP_MODE_POSI) +#define SYS_CTRL_SLEEP_SLEEP_MODE_LOW (0x0000B706 << SYS_CTRL_SLEEP_SLEEP_MODE_POSI) +#define SYS_CTRL_SLEEP_SLEEP_MODE_DEEPSLEEP (0x0000ADC1 << SYS_CTRL_SLEEP_SLEEP_MODE_POSI) + +#define SYS_CTRL_SLEEP_ROSC_PWD_POSI 16 +#define SYS_CTRL_SLEEP_ROSC_PWD_MASK (0x01UL << SYS_CTRL_SLEEP_ROSC_PWD_POSI) +#define SYS_CTRL_SLEEP_ROSC_PWD_SET (0x01UL << SYS_CTRL_SLEEP_ROSC_PWD_POSI) + +#define SYS_CTRL_SLEEP_FLASH_PWD_POSI 17 +#define SYS_CTRL_SLEEP_FLASH_PWD_MASK (0x01UL << SYS_CTRL_SLEEP_FLASH_PWD_POSI) +#define SYS_CTRL_SLEEP_FLASH_PWD_SET (0x01UL << SYS_CTRL_SLEEP_FLASH_PWD_POSI) + +#define SYS_CTRL_SLEEP_DCO_PWD_POSI 18 +#define SYS_CTRL_SLEEP_DCO_PWD_MASK (0x01UL << SYS_CTRL_SLEEP_DCO_PWD_POSI) +#define SYS_CTRL_SLEEP_DCO_PWD_SET (0x01UL << SYS_CTRL_SLEEP_DCO_PWD_POSI) + +#define SYS_CTRL_SLEEP_POR_CORE_DLY_POSI 20 +#define SYS_CTRL_SLEEP_POR_CORE_DLY_MASK (0x0FUL << SYS_CTRL_SLEEP_POR_CORE_DLY_POSI) +#define SYS_CTRL_SLEEP_POR_CORE_DLY_SET (0x0FUL << SYS_CTRL_SLEEP_POR_CORE_DLY_POSI) + + +#define REG_WIFI_PWD_ADDR (REG_SYS_CTRL_BASE_ADDR + 0x43 * 4) +#define REG_DSP_PWD_ADDR (REG_SYS_CTRL_BASE_ADDR + 0x44 * 4) +#define REG_USB_PWD_ADDR (REG_SYS_CTRL_BASE_ADDR + 0x45 * 4) + +#define REG_WIFI_PWD (*((volatile unsigned long *) REG_WIFI_PWD_ADDR)) +#define REG_DSP_PWD (*((volatile unsigned long *) REG_DSP_PWD_ADDR)) +#define REG_USB_PWD (*((volatile unsigned long *) REG_USB_PWD_ADDR)) + + +#define REG_SYS_CTRL_BLOCK_EN_ADDR (REG_SYS_CTRL_BASE_ADDR + 0x4B * 4) +#define REG_SYS_CTRL_BLOCK_EN_MASK 0xFFFFBFBFUL +#define REG_SYS_CTRL_BLOCK_EN (*((volatile unsigned long *) REG_SYS_CTRL_BLOCK_EN_ADDR)) + +#define SYS_CTRL_BLOCK_EN_SW_POSI 0 +#define SYS_CTRL_BLOCK_EN_SW_MASK (0x000FBFBF << SYS_CTRL_BLOCK_EN_SW_POSI) +#define SYS_CTRL_BLOCK_EN_SW_FLASH 0x00000001 +#define SYS_CTRL_BLOCK_EN_SW_DCO_26MHz 0x00000002 +#define SYS_CTRL_BLOCK_EN_SW_ROSC_32KHz 0x00000004 +#define SYS_CTRL_BLOCK_EN_SW_XTAL_26MHz 0x00000008 +#define SYS_CTRL_BLOCK_EN_SW_XTAL_32KHz 0x00000010 +#define SYS_CTRL_BLOCK_EN_SW_DPLL 0x00000020 +#define SYS_CTRL_BLOCK_EN_SW_DIGITAL_LDO 0x00000080 +#define SYS_CTRL_BLOCK_EN_SW_ANALOG_LDO 0x00000100 +#define SYS_CTRL_BLOCK_EN_SW_IO_LDO 0x00000200 +#define SYS_CTRL_BLOCK_EN_SW_XTAL_TO_RF 0x00000400 +#define SYS_CTRL_BLOCK_EN_SW_XTAL_26MHz_LOW_POWER 0x00000800 +#define SYS_CTRL_BLOCK_EN_SW_TEMP_SENSOR 0x00001000 +#define SYS_CTRL_BLOCK_EN_SW_ADC_ENABLE 0x00002000 +#define SYS_CTRL_BLOCK_EN_SW_AUDIO_L_CHNNEL 0x00008000 +#define SYS_CTRL_BLOCK_EN_SW_AUDIO_R_CHNNEL 0x00010000 +#define SYS_CTRL_BLOCK_EN_SW_MIC_L_CHNNEL 0x00020000 +#define SYS_CTRL_BLOCK_EN_SW_MIC_R_CHNNEL 0x00040000 +#define SYS_CTRL_BLOCK_EN_SW_LINE_IN 0x00080000 + +#define SYS_CTRL_BLOCK_EN_VALID_POSI 20 +#define SYS_CTRL_BLOCK_EN_VALID_MASK (0x0FFFUL << SYS_CTRL_BLOCK_EN_VALID_POSI) +#define SYS_CTRL_BLOCK_EN_VALID_SET (0x0A5CUL << SYS_CTRL_BLOCK_EN_VALID_POSI) + + +#define REG_SYS_CTRL_BIAS_CALIB_ADDR (REG_SYS_CTRL_BASE_ADDR + 0x4C * 4) +#define REG_SYS_CTRL_BIAS_CALIB_MASK 0x001F1F11UL +#define REG_SYS_CTRL_BIAS_CALIB (*((volatile unsigned long *) REG_SYS_CTRL_BIAS_CALIB_ADDR)) + +#define SYS_CTRL_BIAS_CALIB_TRIG_POSI 0 +#define SYS_CTRL_BIAS_CALIB_TRIG_MASK (0x01UL << SYS_CTRL_BIAS_CALIB_TRIG_POSI) +#define SYS_CTRL_BIAS_CALIB_TRIG_SET (0x01UL << SYS_CTRL_BIAS_CALIB_TRIG_POSI) + +#define SYS_CTRL_BIAS_CALIB_MANUAL_POSI 4 +#define SYS_CTRL_BIAS_CALIB_MANUAL_MASK (0x01UL << SYS_CTRL_BIAS_CALIB_MANUAL_POSI) +#define SYS_CTRL_BIAS_CALIB_MANUAL_SET (0x01UL << SYS_CTRL_BIAS_CALIB_MANUAL_POSI) + +#define SYS_CTRL_BIAS_CALIB_SETTING_POSI 8 +#define SYS_CTRL_BIAS_CALIB_SETTING_MASK (0x1FUL << SYS_CTRL_BIAS_CALIB_SETTING_POSI) + +#define SYS_CTRL_BIAS_CALIB_RESULT_POSI 16 +#define SYS_CTRL_BIAS_CALIB_RESULT_MASK (0x1FUL << SYS_CTRL_BIAS_CALIB_RESULT_POSI) + + +#define REG_SYS_CTRL_ROSC_CONFIG_ADDR (REG_SYS_CTRL_BASE_ADDR + 0x4D * 4) +#define REG_SYS_CTRL_ROSC_CONFIG_MASK 0x7FFF0077UL +#define REG_SYS_CTRL_ROSC_CONFIG (*((volatile unsigned long *) REG_SYS_CTRL_ROSC_CONFIG_ADDR)) + + + +#define REG_ICU_BASE_ADDR (0x00802000UL) + + +#define REG_ICU_PERI_CLK_MUX_ADDR (REG_ICU_BASE_ADDR + 0x0 * 4) +#define REG_ICU_PERI_CLK_MUX_MASK 0x00000001UL +#define REG_ICU_PERI_CLK_MUX (*((volatile unsigned long *) REG_ICU_PERI_CLK_MUX_ADDR)) + +#define ICU_PERI_CLK_MUX_SEL_POSI 0 +#define ICU_PERI_CLK_MUX_SEL_MASK (0x01UL << ICU_PERI_CLK_MUX_SEL_POSI) +#define ICU_PERI_CLK_MUX_SEL_DCO_CLK (0x00UL << ICU_PERI_CLK_MUX_SEL_POSI) +#define ICU_PERI_CLK_MUX_SEL_XTAL_26M (0x01UL << ICU_PERI_CLK_MUX_SEL_POSI) + +#define ICU_TL410_BLE_CLK_ADDR (REG_ICU_BASE_ADDR + 0x04 * 4) +#define ICU_TL410_BLE_CLK_MASK 0x03UL +#define ICU_TL410_BLE_CLK (*((volatile unsigned long *) ICU_TL410_BLE_CLK_ADDR)) + + +#define REG_ICU_INT_ENABLE_ADDR (REG_ICU_BASE_ADDR + 0x10 * 4) +#define REG_ICU_INT_ENABLE_MASK 0x07FF7FFFUL +#define REG_ICU_INT_ENABLE (*((volatile unsigned long *) REG_ICU_INT_ENABLE_ADDR)) + +#define REG_ICU_INT_GLOBAL_ENABLE_ADDR (REG_ICU_BASE_ADDR + 0x11 * 4) +#define REG_ICU_INT_GLOBAL_ENABLE_MASK 0x0003UL +#define REG_ICU_INT_GLOBAL_ENABLE (*((volatile unsigned long *) REG_ICU_INT_GLOBAL_ENABLE_ADDR)) + +#define ICU_INT_GLOBAL_ENABLE_IRQ_POSI 0 +#define ICU_INT_GLOBAL_ENABLE_IRQ_MASK (0x01UL << ICU_INT_GLOBAL_ENABLE_IRQ_POSI) +#define ICU_INT_GLOBAL_ENABLE_IRQ_SET (0x01UL << ICU_INT_GLOBAL_ENABLE_IRQ_POSI) + +#define ICU_INT_GLOBAL_ENABLE_FIQ_POSI 1 +#define ICU_INT_GLOBAL_ENABLE_FIQ_MASK (0x01UL << ICU_INT_GLOBAL_ENABLE_FIQ_POSI) +#define ICU_INT_GLOBAL_ENABLE_FIQ_SET (0x01UL << ICU_INT_GLOBAL_ENABLE_FIQ_POSI) + +#define REG_BLE_XVR_BASE_ADDR (0x0080B400) + +#define REG_BLE_XVR_SLOT_TIME_ADDR (REG_BLE_XVR_BASE_ADDR + 0x2a * 4) +#define REG_BLE_XVR_SLOT_TIME_MASK 0xFFFFFFFF +#define REG_BLE_XVR_SLOT_TIME (*((volatile unsigned long *) REG_BLE_XVR_SLOT_TIME_ADDR)) + +#define REG_BLE_XVR_TX_CONFIG_ADDR (REG_BLE_XVR_BASE_ADDR + 0x30 * 4) +#define REG_BLE_XVR_TX_CONFIG_MASK 0xFFFFFFFF +#define REG_BLE_XVR_TX_CONFIG (*((volatile unsigned long *) REG_BLE_XVR_AGC_CONFIG_ADDR)) + +#define REG_BLE_XVR_AGC_CONFIG_ADDR (REG_BLE_XVR_BASE_ADDR + 0x3c * 4) +#define REG_BLE_XVR_AGC_CONFIG_MASK 0xFFFFFFFF +#define REG_BLE_XVR_AGC_CONFIG (*((volatile unsigned long *) REG_BLE_XVR_AGC_CONFIG_ADDR)) + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __DRIVER_SYS_CTRL_H__ */ diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/driver/reg/ble_reg_access.h b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/driver/reg/ble_reg_access.h new file mode 100755 index 0000000..57494a6 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/driver/reg/ble_reg_access.h @@ -0,0 +1,143 @@ +/** + **************************************************************************************** + * + * @file ble_reg_access.h + * + * @brief File implementing the basic primitives for register accesses + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef BLE_REG_ACCESS_H_ +#define BLE_REG_ACCESS_H_ + +/** + **************************************************************************************** + * @addtogroup REG REG_ACCESS + * @ingroup DRIVERS + * + * @brief Basic primitives for register access + * + * @{ + **************************************************************************************** + */ + + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include // string functions + +#if defined(CFG_EMB) +#include "common_utils.h" +#include "em_map.h" // EM Map +#endif // defined(CFG_EMB) +/* + * DEFINES + **************************************************************************************** + */ + +/* + * MACROS + **************************************************************************************** + */ +/// Macro to read a platform register +#define REG_PL_RD(addr) (*(volatile uint32_t *)(addr)) + + +/// Macro to write a platform register +#define REG_PL_WR(addr, value) (*(volatile uint32_t *)(addr)) = (value) + +/// Macro to read a BLE register +#define REG_BLE_RD(addr) (*(volatile uint32_t *)(addr)) + +/// Macro to write a BLE register +#define REG_BLE_WR(addr, value) (*(volatile uint32_t *)(addr)) = (value) + +/// Macro to read a BLE control structure field (16-bit wide) +#define EM_BLE_RD(addr) (*(volatile uint16_t *)(addr)) + +/// Macro to write a BLE control structure field (16-bit wide) +#define EM_BLE_WR(addr, value) (*(volatile uint16_t *)(addr)) = (value) + +/// Macro to read a BT register +#define REG_BT_RD(addr) (*(volatile uint32_t *)(addr)) + +/// Macro to write a BT register +#define REG_BT_WR(addr, value) (*(volatile uint32_t *)(addr)) = (value) + +/// Macro to read a BT control structure field (16-bit wide) +#define EM_BT_RD(addr) (*(volatile uint16_t *)(addr)) + +/// Macro to write a BT control structure field (16-bit wide) +#define EM_BT_WR(addr, value) (*(volatile uint16_t *)(addr)) = (value) + +/// Macro to read a EM field (16-bit wide) +#define EM_RD(addr) (*(volatile uint16_t *)(addr)) + +/// Macro to write a EM field (16-bit wide) +#define EM_WR(addr, value) (*(volatile uint16_t *)(addr)) = (value) +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +#if (defined(CFG_BT) || (defined(CFG_BLE) && defined(CFG_EMB))) +/// Read bytes from EM +__INLINE void em_rd(void *sys_addr, uint16_t em_addr, uint16_t len) +{ + memcpy(sys_addr, (void *)(em_addr + EM_BASE_ADDR), len); +} +/// Write bytes to EM +__INLINE void em_wr(void const *sys_addr, uint16_t em_addr, uint16_t len) +{ + memcpy((void *)(em_addr + EM_BASE_ADDR), sys_addr, len); +} + +/// Fill an EM space with the same value +__INLINE void em_set(int value, uint16_t em_addr, uint16_t len) +{ + memset((void *)(em_addr + EM_BASE_ADDR), value, len); +} + +/// Read 32-bits value from EM +__INLINE uint32_t em_rd32p(uint16_t em_addr) +{ + return common_read32p((void *)(em_addr + EM_BASE_ADDR)); +} +/// Write 32-bits value to EM +__INLINE void em_wr32p(uint16_t em_addr, uint32_t value) +{ + common_write32p((void *)(em_addr + EM_BASE_ADDR), value); +} + +/// Read 16-bits value from EM +__INLINE uint16_t em_rd16p(uint16_t em_addr) +{ + return common_read16p((void *)(em_addr + EM_BASE_ADDR)); +} +/// Write 16-bits value to EM +__INLINE void em_wr16p(uint16_t em_addr, uint16_t value) +{ + common_write16p((void *)(em_addr + EM_BASE_ADDR), value); +} + +/// Read 8-bits value from EM +__INLINE uint8_t em_rd8p(uint16_t em_addr) +{ + return *((uint8_t *)(em_addr + EM_BASE_ADDR)); +} +/// Write 8-bits value to EM +__INLINE void em_wr8p(uint16_t em_addr, uint8_t value) +{ + *(uint8_t *)(em_addr + EM_BASE_ADDR) = value; +} +#endif // (defined(CFG_BT) || (defined(CFG_BLE) && defined(CFG_EMB))) + +/// @} REG + +#endif // REG_ACCESS_H_ diff --git a/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/driver/uart/uart.c b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/driver/uart/uart.c new file mode 100755 index 0000000..fa50b81 --- /dev/null +++ b/beken_os/beken378/driver/ble/ble_pub/plf/refip/src/driver/uart/uart.c @@ -0,0 +1,512 @@ +/** + **************************************************************************************** + * + * @file uart.c + * + * @brief UART driver + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @addtogroup UART + * @{ + **************************************************************************************** + */ +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include // standard definition +#include "uart.h" // uart definition +#include "BK3435_reg.h" +#include "reg_uart.h" // uart register +#include "rwip.h" // SW interface +#include "h4tl.h" +#if (PLF_NVDS) +#include "nvds.h" // NVDS +#endif // (PLF_NVDS) + +#include "dbg.h" + +/* + * DEFINES + ***************************************************************************************** + */ + +/// Max baudrate supported by this UART (in bps) +#define UART_BAUD_MAX 3500000 +/// Min baudrate supported by this UART (in bps) +#define UART_BAUD_MIN 9600 + +/// Duration of 1 byte transfer over UART (10 bits) in us (for 921600 default baudrate) +#define UART_CHAR_DURATION 11 + +/* + * ENUMERATION DEFINITIONS + ***************************************************************************************** + */ + + /* + * common.c + * + * Created on: 2013-5-7 + * Author: pujie + */ + +#include +#include +#include "BK3435_reg.h" + +#include "ea.h" + + + +#define Uart_Write_Byte(v) (REG_APB3_UART_PORT=v) + +#define UART_TX_FIFO_COUNT (REG_APB3_UART_FIFO_STAT&0xff) +#define UART_RX_FIFO_COUNT ((REG_APB3_UART_FIFO_STAT>>8)&0xff) +#define UART_TX_FIFO_FULL (REG_APB3_UART_FIFO_STAT&0x00010000) +#define UART_TX_FIFO_EMPTY (REG_APB3_UART_FIFO_STAT&0x00020000) +#define UART_RX_FIFO_FULL (REG_APB3_UART_FIFO_STAT&0x00040000) +#define UART_RX_FIFO_EMPTY (REG_APB3_UART_FIFO_STAT&0x00080000) +#define UART_TX_WRITE_READY (REG_APB3_UART_FIFO_STAT&0x00100000) +#define UART_RX_READ_READY (REG_APB3_UART_FIFO_STAT&0x00200000) +#define bit_UART_TXFIFO_NEED_WRITE 0x01 +#define bit_UART_RXFIFO_NEED_READ 0x02 +#define bit_UART_RXFIFO_OVER_FLOW 0x04 +#define bit_UART_RX_PARITY_ERROR 0x08 +#define bit_UART_RX_STOP_ERROR 0x10 +#define bit_UART_TX_PACKET_END 0x20 +#define bit_UART_RX_PACKET_END 0x40 +#define bit_UART_RXD_WAKEUP_DETECT 0x80 + + +#define uart_tx_en 0x1 // 0: Disable TX, 1: Enable TX +#define uart_rx_en 0x1 // 0: Disable RX, 1: Enable RX +#define irda_mode 0x0 // 0: UART MODE, 1: IRDA MODE +#define data_len 0x3 // 0: 5 bits, 1: 6 bits, 2: 7 bits, 3: 8 bits +#define parity_en 0x0 // 0: NO Parity, 1: Enable Parity +#define parity_mode 0x1 // 0: Odd Check, 1: Even Check +#define stop_bits 0x0 // 0: 1 stop-bit, 1: 2 stop-bit +#define uart_clks 16000000 // UART's Main-Freq, 26M +#define baud_rate 115200 // UART's Baud-Rate, 1M + + +unsigned char uart_rx_buf[UART0_RX_FIFO_MAX_COUNT]; +unsigned char uart_tx_buf[UART0_TX_FIFO_MAX_COUNT]; +volatile bool uart_rx_done = 0; +volatile unsigned long uart_rx_index = 0; +uint8_t cur_read_buf_idx = 0; + + +#define UART_READ_BYTE() (REG_APB3_UART_PORT&0xff) + + +///UART Character format +enum UART_CHARFORMAT +{ + UART_CHARFORMAT_8 = 0, + UART_CHARFORMAT_7 = 1 +}; + +///UART Stop bit +enum UART_STOPBITS +{ + UART_STOPBITS_1 = 0, + UART_STOPBITS_2 = 1 /* Note: The number of stop bits is 1.5 if a character format + with 5 bit is chosen*/ +}; + +///UART Parity enable +enum UART_PARITY +{ + UART_PARITY_DISABLED = 0, + UART_PARITY_ENABLED = 1 +}; + +///UART Parity type +enum UART_PARITYBIT +{ + UART_PARITYBIT_EVEN = 0, + UART_PARITYBIT_ODD = 1, + UART_PARITYBIT_SPACE = 2, // The parity bit is always 0. + UART_PARITYBIT_MARK = 3 // The parity bit is always 1. +}; + +///UART HW flow control +enum UART_HW_FLOW_CNTL +{ + UART_HW_FLOW_CNTL_DISABLED = 0, + UART_HW_FLOW_CNTL_ENABLED = 1 +}; + +///UART Input clock select +enum UART_INPUT_CLK_SEL +{ + UART_INPUT_CLK_SEL_0 = 0, + UART_INPUT_CLK_SEL_1 = 1, + UART_INPUT_CLK_SEL_2 = 2, + UART_INPUT_CLK_SEL_3 = 3 +}; + +///UART Interrupt enable/disable +enum UART_INT +{ + UART_INT_DISABLE = 0, + UART_INT_ENABLE = 1 +}; + +///UART Error detection +enum UART_ERROR_DETECT +{ + UART_ERROR_DETECT_DISABLED = 0, + UART_ERROR_DETECT_ENABLED = 1 +}; + +/* + * STRUCT DEFINITIONS + ***************************************************************************************** + */ +/* TX and RX channel class holding data used for asynchronous read and write data + * transactions + */ +/// UART TX RX Channel +struct uart_txrxchannel +{ + /// call back function pointer + uint8_t (*callback) (void*, uint8_t); + /// Dummy data pointer returned to callback when operation is over. + void* dummy; +}; + +/// UART environment structure +struct uart_env_tag +{ + /// tx channel + struct uart_txrxchannel tx; + /// rx channel + struct uart_txrxchannel rx; + /// error detect + uint8_t errordetect; + /// external wakeup + bool ext_wakeup; +}; + +/* + * GLOBAL VARIABLE DEFINITIONS + **************************************************************************************** + */ + +/// uart environment structure +struct uart_env_tag uart_env; + +char uart_buff[128]; + + +/* + * LOCAL FUNCTION DEFINITIONS + **************************************************************************************** + */ + + +/* + * EXPORTED FUNCTION DEFINITIONS + **************************************************************************************** + */ +uint16_t Read_Uart_Buf(uint8_t *buf, uint16_t len) +{ + + memcpy(buf, &(uart_rx_buf[cur_read_buf_idx]), len); + cur_read_buf_idx+= len; + return len; +} + +uint8_t Uart_Read_Byte(void) +{ + return (REG_APB3_UART_PORT&0xff); +} + + +int uart_putchar(char * st) +{ + uint8_t num = 0; +#if UART_PRINTF_EN + while (*st) + { + if(UART_TX_WRITE_READY) + { + REG_APB3_UART_PORT = *st; + st++; + num++; + } + } +#endif + return num; +} + +int uart_printf(const char *fmt,...) +{ + int n; +#if UART_PRINTF_EN + va_list ap; + va_start(ap, fmt); + n=vsprintf(uart_buff, fmt, ap); + va_end(ap); + uart_putchar(uart_buff); + if(n > sizeof(uart_buff)) + { + uart_putchar("buff full \r\n"); + } +#else + n = 0; +#endif + + return n; +} + +int uart_printf_null(const char *fmt,...) +{ + return 0; +} + + +char *hex2Str( uint8_t data) +{ + + char hex[] = "0123456789ABCDEF"; + static char str[3]; + char *pStr = str; + + *pStr++ = hex[data >> 4]; + *pStr++ = hex[data & 0x0F]; + *pStr = 0; + + return str; +} + +void uart_print_int(unsigned int num) +{ + uint8_t i; + uint8_t m; + + uart_putchar((char *)"0x"); + for (i = 4;i > 0;i--) + { + m = ((num >> (8 * (i - 1)))& 0xff); + uart_putchar(hex2Str(m)); + } + uart_putchar("\r\n"); +} + + + +void cpu_delay( volatile unsigned int times) +{ + while(times--) + { + for(uint32_t i = 0;i < 1000;i++) + ; + } +} + + +void uart_init(uint32_t baudrate) +{ +#if UART_PRINTF_EN + unsigned int baud_divisor ; + REG_AHB0_ICU_UARTCLKCON &= ~(0x1 << 0) ; // Enable Uart's Clocks + switch(baudrate) + { + case 9600: + case 19200: + case 38400: + case 57600: + case 115200: + baud_divisor = 0x89; + break; + case 921600: + baud_divisor = 0x10; + break; + default: + baud_divisor = 0x89; + break; + } + REG_APB3_UART_CFG = (baud_divisor<<8) + + (stop_bits <<7) + + //(parity_mode <<6) + + //(parity_en <<5) + + (data_len <<3) + + (irda_mode <<2) + + (uart_rx_en <<1) + + uart_tx_en ; + + REG_APB3_UART_FIFO_CFG = (1< // standard boolean definitions +#include // standard integer functions +#include "rwip_config.h" + + +#if UART_PRINTF_EN + +#if !BLE_TESTER +#define UART_PRINTF uart_printf //uart_printf +#else +#define UART_PRINTF uart_printf_null //uart_printf +#endif //!BLE_TESTER + +#else +#define UART_PRINTF uart_printf_null +#endif // #if UART_PRINTF_EN + +/* + * ENUMERATION DEFINITIONS + ***************************************************************************************** + */ + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Initializes the UART to default values. + ***************************************************************************************** + */ +void uart_init(uint32_t baudrate); + +void dbg_initial(void); + +void uart_clear_rxfifo(void); + +uint8_t Uart_Read_Byte(void); +uint16_t Read_Uart_Buf(uint8_t *buf, uint16_t len); + +int dbg_putchar(char * st); +int uart_putchar(char * st); +int uart_printf(const char *fmt,...); +int uart_printf_null(const char *fmt,...); +int dbg_printf(const char *fmt,...); +void uart_print_int(unsigned int num); +uint8_t check_uart_stop(void); + +void cpu_delay( volatile unsigned int times); + + +/****** REG ****************/ +void uart_send(unsigned char *buff, int len); +void TRAhcit_UART_Rx(void); + +#define UART0_RX_FIFO_MAX_COUNT 128 + +#define UART0_TX_FIFO_MAX_COUNT 128 + +extern unsigned char uart_rx_buf[UART0_RX_FIFO_MAX_COUNT]; +extern unsigned char uart_tx_buf[UART0_TX_FIFO_MAX_COUNT]; +extern volatile bool uart_rx_done ; +extern volatile unsigned long uart_rx_index ; +/****** REG ****************/ + + + +#ifndef CFG_ROM +/** + **************************************************************************************** + * @brief Enable UART flow. + ***************************************************************************************** + */ +void uart_flow_on(void); + +/** + **************************************************************************************** + * @brief Disable UART flow. + ***************************************************************************************** + */ +bool uart_flow_off(void); +#endif //CFG_ROM + +/** + **************************************************************************************** + * @brief Finish current UART transfers + ***************************************************************************************** + */ +void uart_finish_transfers(void); + +/** + **************************************************************************************** + * @brief Starts a data reception. + * + * @param[out] bufptr Pointer to the RX buffer + * @param[in] size Size of the expected reception + * @param[in] callback Pointer to the function called back when transfer finished + * @param[in] dummy Dummy data pointer returned to callback when reception is finished + ***************************************************************************************** + */ +void uart_read(uint8_t *bufptr, uint32_t size, uint8_t (*callback) (void*, uint8_t), void* dummy); + +/** + **************************************************************************************** + * @brief Starts a data transmission. + * + * @param[in] bufptr Pointer to the TX buffer + * @param[in] size Size of the transmission + * @param[in] callback Pointer to the function called back when transfer finished + * @param[in] dummy Dummy data pointer returned to callback when transmission is finished + ***************************************************************************************** + */ +void uart_write(uint8_t *bufptr, uint32_t size, uint8_t (*callback) (void*, uint8_t), void* dummy); + +#if defined(CFG_ROM) +/** + **************************************************************************************** + * @brief Poll UART on reception and transmission. + * + * This function is used to poll UART for reception and transmission. + * It is used when IRQ are not used to detect incoming bytes. + ***************************************************************************************** + */ +void uart_poll(void); +#endif //CFG_ROM + +/** + **************************************************************************************** + * @brief Serves the data transfer interrupt requests. + * + * It clears the requests and executes the appropriate callback function. + ***************************************************************************************** + */ +void uart_isr(void); + + +/// @} UART +#endif /* _UART_H_ */ diff --git a/beken_os/beken378/driver/ble_5_x_rw/arch/armv5/architect.h b/beken_os/beken378/driver/ble_5_x_rw/arch/armv5/architect.h new file mode 100755 index 0000000..558f560 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/arch/armv5/architect.h @@ -0,0 +1,113 @@ +/** + **************************************************************************************** + * + * @file architect.h + * + * @brief This file contains the definitions of the macros and functions that are + * architecture dependent. The implementation of those is implemented in the + * appropriate architecture directory. + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + + +#ifndef _ARCHITECT_H_ +#define _ARCHITECT_H_ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include // standard integer definition +#include "compiler.h" // inline functions +#include "lowlevel.h" +#include "typedef.h" + +/* + * CPU WORD SIZE + **************************************************************************************** + */ +/// ARM is a 32-bit CPU +#define CPU_WORD_SIZE 4 + +/* + * CPU Endianness + **************************************************************************************** + */ +/// ARM is little endian +#define CPU_LE 1 + +/// Possible errors detected by FW +#define RESET_NO_ERROR 0x00000000 +#define RESET_MEM_ALLOC_FAIL 0xF2F2F2F2 + +/// Reset platform and stay in ROM +#define RESET_TO_ROM 0xA5A5A5A5 +/// Reset platform and reload FW +#define RESET_AND_LOAD_FW 0xC3C3C3C3 + +/** + **************************************************************************************** + * @brief Print the assertion error reason and loop forever. + * + * @param condition C string containing the condition. + * @param file C string containing file where the assertion is located. + * @param line Line number in the file where the assertion is located. + **************************************************************************************** + */ +void assert_err(const char *condition, const char * file, int line); + +/** + **************************************************************************************** + * @brief Print the assertion error reason and loop forever. + * The parameter value that is causing the assertion will also be disclosed. + * + * @param param0 parameter value 0. + * @param param1 parameter value 1. + * @param file C string containing file where the assertion is located. + * @param line Line number in the file where the assertion is located. + **************************************************************************************** + */ +void assert_param(int param0, int param1, const char * file, int line); + +/** + **************************************************************************************** + * @brief Print the assertion warning reason. + * + * @param param0 parameter value 0. + * @param param1 parameter value 1. + * @param file C string containing file where the assertion is located. + * @param line Line number in the file where the assertion is located. + **************************************************************************************** + */ +void assert_warn(int param0, int param1, const char * file, int line); + +void platform_reset(uint32_t error); + +#define BLE_ASSERT_ERR(cond) \ + do { \ + if (!(cond)) { \ + assert_err(#cond, __MODULE__, __LINE__); \ + } \ + } while(0) + +/// Assertions showing a critical error that could require a full system reset +#define BLE_ASSERT_INFO(cond, param0, param1) \ + do { \ + if (!(cond)) { \ + assert_param((int)param0, (int)param1, __MODULE__, __LINE__); \ + } \ + } while(0) + +/// Assertions showing a non-critical problem that has to be fixed by the SW +#define BLE_ASSERT_WARN(cond, param0, param1) \ + do { \ + if (!(cond)) { \ + assert_warn((int)param0, (int)param1, __MODULE__, __LINE__); \ + } \ + } while(0) + +#endif // _ARCHITECT_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/arch/armv5/compiler/ble_compiler.h b/beken_os/beken378/driver/ble_5_x_rw/arch/armv5/compiler/ble_compiler.h new file mode 100755 index 0000000..6a6f752 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/arch/armv5/compiler/ble_compiler.h @@ -0,0 +1,66 @@ +/** + **************************************************************************************** + * + * @file gnuarm/compiler.h + * + * @brief Definitions of compiler specific directives. + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef _BLE_COMPILER_H_ +#define _BLE_COMPILER_H_ + + +/// define the static keyword for this compiler +#define __STATIC static + +/// define the force inlining attribute for this compiler +#define __INLINE static __attribute__((__always_inline__)) inline + +/// define the force inlining attribute for this compiler +//#define __INLINE __forceinline static +#define inline + +/// define the IRQ handler attribute for this compiler +#define __IRQ __attribute__((__interrupt__("IRQ"))) +//#define __IRQ __irq + +/// define the BLE IRQ handler attribute for this compiler +#define __BTIRQ + +/// define the BLE IRQ handler attribute for this compiler +#define __BLEIRQ + +/// define the FIQ handler attribute for this compiler +#define __FIQ __attribute__((__interrupt__("FIQ"))) +//#define __FIQ __irq +/// define size of an empty array (used to declare structure with an array size not defined) +#define __ARRAY_EMPTY + +/// Function returns struct in registers (4 in rvds, var with gnuarm). +/// With Gnuarm, feature depends on command line options and +/// impacts ALL functions returning 2-words max structs +/// (check -freg-struct-return and -mabi=xxx) +#define __VIR + +/// function has no side effect and return depends only on arguments +#define __PURE __attribute__((const)) + +/// Align instantiated lvalue or struct member on 4 bytes +#define __ALIGN4 __attribute__((aligned(4))) + +/// __MODULE__ comes from the RVDS compiler that supports it +#define __MODULE__ __BASE_FILE__ + +/// Pack a structure field +#define __PACKED16 __attribute__ ((__packed__)) +#define __PACKED __attribute__ ((__packed__)) + +/// Put a variable in a memory maintained during deep sleep +#define __LOWPOWER_SAVED + +#endif // _BLE_COMPILER_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/arch/armv5/ll/ll.s b/beken_os/beken378/driver/ble_5_x_rw/arch/armv5/ll/ll.s new file mode 100755 index 0000000..4611b19 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/arch/armv5/ll/ll.s @@ -0,0 +1,15 @@ +/** + **************************************************************************************** + * + * @file ll.s + * + * @brief ARM low level functions. + * + * Copyright (C) RivieraWaves 2009-2015 + * + * $Rev: $ + * + **************************************************************************************** + */ +.text + .align 4 diff --git a/beken_os/beken378/driver/ble_5_x_rw/arch/armv5/ll/lowlevel.h b/beken_os/beken378/driver/ble_5_x_rw/arch/armv5/ll/lowlevel.h new file mode 100755 index 0000000..89c8340 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/arch/armv5/ll/lowlevel.h @@ -0,0 +1,82 @@ +/** + **************************************************************************************** + * + * @file ll.h + * + * @brief Declaration of low level functions. + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef LL_H_ +#define LL_H_ + + +#include "arch.h" +#include + +#include "compiler.h" + +#define KEIL_INTRINSICS_INTERRUPT + + +/** @brief Enable interrupts globally in the system. + * This macro must be used when the initialization phase is over and the interrupts + * can start being handled by the system. + */ + +/* keil Compiler intrinsics for controlling IRQ and FIQ interrupts +*/ + +//extern void __enable_irq(void); +//extern void __enable_fiq(void); +//extern int __disable_irq(void); +//extern int __disable_fiq(void); + +#define __enable_irq portENABLE_IRQ +#define __enable_fiq portENABLE_FIQ +#define __disable_irq portDISABLE_IRQ +#define __disable_fiq portDISABLE_FIQ + +#define GLOBAL_INT_DIS(); \ +do { \ + uint32_t fiq_tmp; \ + uint32_t irq_tmp; \ + fiq_tmp = __disable_fiq(); \ + irq_tmp = __disable_irq(); + +#define GLOBAL_INT_RES(); \ + if(!fiq_tmp) \ + { \ + __enable_fiq(); \ + } \ + if(!irq_tmp) \ + { \ + __enable_irq(); \ + } \ +} while(0) ; + +#define GLOBAL_INT_DECLARATION_N() uint32_t fiq_tmp, irq_tmp +#define GLOBAL_INT_DISABLE_N() do{\ + fiq_tmp = portDISABLE_FIQ();\ + irq_tmp = portDISABLE_IRQ();\ + }while(0) + + +#define GLOBAL_INT_RESTORE_N() do{ \ + if(!fiq_tmp) \ + { \ + portENABLE_FIQ(); \ + } \ + if(!irq_tmp) \ + { \ + portENABLE_IRQ(); \ + } \ + }while(0) + +#endif // LL_H_ + + diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/api/att.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/api/att.h new file mode 100755 index 0000000..54b1030 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/api/att.h @@ -0,0 +1,1176 @@ +/** + **************************************************************************************** + * + * @file att.h + * + * @brief Header file - ATT. + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + +#ifndef ATT_H_ +#define ATT_H_ + +/** + **************************************************************************************** + * @addtogroup ATT Attribute Protocol + * @ingroup HOST + * @brief Attribute Protocol. + * + * The ATT block contains the procedures for discovering, reading, writing + * and indicating attributes to peer device . It also defines a number of items + * that caters to the security aspect of the block as access to some information + * may require both authorization and an authenticated and encrypted physical + * link before an attribute can be read or written + * + * @{ + * + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include + +/* + * DEFINES + **************************************************************************************** + */ + +/// Macro used to convert CPU integer define to LSB first 16-bits UUID +#define ATT_UUID_16(uuid) (uuid) + +/// Invalid attribute handle +#define ATT_INVALID_HDL (0x0000) +/// Invalid attribute idx (used for profiles) +#define ATT_INVALID_IDX (0xff) + +#define ATT_1ST_REQ_START_HDL 0x0001 +#define ATT_1ST_REQ_END_HDL 0xFFFF + +/// Maximum possible attribute handle +#define ATT_MAX_ATTR_HDL ATT_1ST_REQ_END_HDL + +/// Offset of value in signed PDU +#define ATT_SIGNED_PDU_VAL_OFFSET 0x03 + +/// Attribute Features +#define ATT_SERVER_CONFIG 0x0001 +#define ATT_SERVICE_DISC 0x0002 +#define ATT_RELATIONSHIP_DISC 0x0004 +#define ATT_CHAR_DISC 0x0008 +#define ATT_CHAR_DESC_DISC 0x0010 +#define ATT_RD_CHAR_VALUE 0x0020 +#define ATT_WR_CHAR_VALUE 0x0040 +#define ATT_NOTIF_CHAR_VALUE 0x0080 +#define ATT_IND_CHAR_VALUE 0x0100 +#define ATT_RD_CHAR_DESC 0x0200 +#define ATT_WR_CHAR_DESC 0x0400 + +/// Length, number, offset defines +#define ATT_SVC_VALUE_MAX_LEN 0x0030 +#define ATT_CHAR_NAME_MAX_LEN 0x0030 +#define ATT_UUID_16_LEN 0x0002 +#define ATT_UUID_32_LEN 0x0004 +#define ATT_UUID_128_LEN 0x0010 + +/// offset - l2cap header and ATT code +#define ATT_PDU_DATA_OFFSET 0x05 + +/// Characteristic Properties Bit +#define ATT_CHAR_PROP_BCAST 0x01 +#define ATT_CHAR_PROP_RD 0x02 +#define ATT_CHAR_PROP_WR_NO_RESP 0x04 +#define ATT_CHAR_PROP_WR 0x08 +#define ATT_CHAR_PROP_NTF 0x10 +#define ATT_CHAR_PROP_IND 0x20 +#define ATT_CHAR_PROP_AUTH 0x40 +#define ATT_CHAR_PROP_EXT_PROP 0x80 +/// Invalid Attribute Handle +#define ATT_INVALID_SEARCH_HANDLE 0x0000 +#define ATT_INVALID_HANDLE 0x0000 +/// Read Information Request +#define ATT_UUID_FILTER_0 0x00 +#define ATT_UUID_FILTER_2 0x02 +#define ATT_UUID_FILTER_16 0x10 +/// Read Information Response +#define ATT_FORMAT_LEN 0x0001 +#define ATT_FORMAT_16BIT_UUID 0x01 +#define ATT_FORMAT_128BIT_UUID 0x02 +/// For No fix length PDU +#define ATT_HANDLE_LEN 0x0002 +#define ATT_EACHLEN_LEN 0x0001 +#define ATT_PROP_LEN 0x0001 +#define ATT_CODE_LEN 0x0001 +#define ATT_CODE_AND_DATA_LEN 0x0002 +#define ATT_CODE_AND_HANDLE_LEN 0x0003 +#define ATT_CODE_AND_HANDLE_LEN_AND_OFFSET 0x0005 +#define ATT_SIGNATURE_LEN 0x0C + +/// extended characteristics +#define ATT_EXT_RELIABLE_WRITE 0x0001 +#define ATT_EXT_WRITABLE_AUX 0x0002 +#define ATT_EXT_RFU 0xFFFC + +/// PDU size for error response +#define ATT_ERROR_RESP_LEN 0x05 + +/// Offset of value in signed PDU +#define ATT_SIGNED_PDU_VAL_OFFSET 0x03 + +/// Attribute operation code - Method (bit 5 - 0) +#define ATT_OPCODE_METHOD_MASK 0x3F +#define ATT_OPCODE_METHOD_LSB 0 +/// Attribute operation code - Command Flag (bit 6) +#define ATT_OPCODE_CMD_FLAG_BIT 0x40 +#define ATT_OPCODE_CMD_FLAG_POS 6 +/// Attribute operation code - Authentication Signature Flag (bit 7) +#define ATT_OPCODE_AUTH_SIGNATURE_FLAG_BIT 0x80 +#define ATT_OPCODE_AUTH_SIGNATURE_FLAG_POS 7 + +#define ATT_BT_UUID_128 {0xFB, 0x34, 0x9B, 0x5F, 0x80, 0x00, 0x00, 0x80, \ + 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} + +// TI Base 128-bit UUID: F000XXXX-0451-4000-B000-000000000000 +#define TI_BASE_UUID_1281 {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB0, \ + 0x00, 0x40, 0x51, 0x04, 0x00, 0x00, 0x00, 0xF0} + +/// MAC length +#define ATT_SIGN_MAC_LEN (8) +/// SignCounter length +#define ATT_SIGN_COUNTER_LEN (4) +/// Signature length +#define ATT_SIGN_LEN (ATT_SIGN_MAC_LEN + ATT_SIGN_COUNTER_LEN) + +/// This value ensure to have up to 128 client feature supported would be sufficient for several years. +#define ATT_MAX_CLI_FEAT_LEN 16 + +/* Attribute Specification Defines */ + +/// Common 16-bit Universal Unique Identifier +enum { + ATT_INVALID_UUID = ATT_UUID_16(0x0000), + /*----------------- SERVICES ---------------------*/ + /// Generic Access Profile + ATT_SVC_GENERIC_ACCESS = ATT_UUID_16(0x1800), + /// Attribute Profile + ATT_SVC_GENERIC_ATTRIBUTE = ATT_UUID_16(0x1801), + /// Immediate alert Service + ATT_SVC_IMMEDIATE_ALERT = ATT_UUID_16(0x1802), + /// Link Loss Service + ATT_SVC_LINK_LOSS = ATT_UUID_16(0x1803), + /// Tx Power Service + ATT_SVC_TX_POWER = ATT_UUID_16(0x1804), + /// Current Time Service Service + ATT_SVC_CURRENT_TIME = ATT_UUID_16(0x1805), + /// Reference Time Update Service + ATT_SVC_REF_TIME_UPDATE = ATT_UUID_16(0x1806), + /// Next DST Change Service + ATT_SVC_NEXT_DST_CHANGE = ATT_UUID_16(0x1807), + /// Glucose Service + ATT_SVC_GLUCOSE = ATT_UUID_16(0x1808), + /// Health Thermometer Service + ATT_SVC_HEALTH_THERMOM = ATT_UUID_16(0x1809), + /// Device Information Service + ATT_SVC_DEVICE_INFO = ATT_UUID_16(0x180A), + /// Heart Rate Service + ATT_SVC_HEART_RATE = ATT_UUID_16(0x180D), + /// Phone Alert Status Service + ATT_SVC_PHONE_ALERT_STATUS = ATT_UUID_16(0x180E), + /// Battery Service + ATT_SVC_BATTERY_SERVICE = ATT_UUID_16(0x180F), + /// Blood Pressure Service + ATT_SVC_BLOOD_PRESSURE = ATT_UUID_16(0x1810), + /// Alert Notification Service + ATT_SVC_ALERT_NTF = ATT_UUID_16(0x1811), + /// HID Service + ATT_SVC_HID = ATT_UUID_16(0x1812), + /// Scan Parameters Service + ATT_SVC_SCAN_PARAMETERS = ATT_UUID_16(0x1813), + /// Running Speed and Cadence Service + ATT_SVC_RUNNING_SPEED_CADENCE = ATT_UUID_16(0x1814), + /// Cycling Speed and Cadence Service + ATT_SVC_CYCLING_SPEED_CADENCE = ATT_UUID_16(0x1816), + /// Cycling Power Service + ATT_SVC_CYCLING_POWER = ATT_UUID_16(0x1818), + /// Location and Navigation Service + ATT_SVC_LOCATION_AND_NAVIGATION = ATT_UUID_16(0x1819), + /// Environmental Sensing Service + ATT_SVC_ENVIRONMENTAL_SENSING = ATT_UUID_16(0x181A), + /// Body Composition Service + ATT_SVC_BODY_COMPOSITION = ATT_UUID_16(0x181B), + /// User Data Service + ATT_SVC_USER_DATA = ATT_UUID_16(0x181C), + /// Weight Scale Service + ATT_SVC_WEIGHT_SCALE = ATT_UUID_16(0x181D), + /// Bond Management Service + ATT_SVC_BOND_MANAGEMENT = ATT_UUID_16(0x181E), + /// Continuous Glucose Monitoring Service + ATT_SVC_CONTINUOUS_GLUCOSE_MONITORING = ATT_UUID_16(0x181F), + /// Internet Protocol Support Service + ATT_SVC_IP_SUPPORT = ATT_UUID_16(0x1820), + /// Indoor Positioning Service + ATT_SVC_INDOOR_POSITIONING = ATT_UUID_16(0x1821), + /// Pulse Oximeter Service + ATT_SVC_PULSE_OXIMETER = ATT_UUID_16(0x1822), + /// HTTP Proxy Service + ATT_SVC_HTTP_PROXY = ATT_UUID_16(0x1823), + /// Transport Discovery Service + ATT_SVC_TRANSPORT_DISCOVERY = ATT_UUID_16(0x1824), + /// Object Transfer Service + ATT_SVC_OBJECT_TRANSFER = ATT_UUID_16(0x1825), + /// Mesh Provisioning Service + ATT_SVC_MESH_PROVISIONING = ATT_UUID_16(0x1827), + /// Mesh Proxy Service + ATT_SVC_MESH_PROXY = ATT_UUID_16(0x1828), + + /*------------------- UNITS ---------------------*/ + /// No defined unit + ATT_UNIT_UNITLESS = ATT_UUID_16(0x2700), + /// Length Unit - Metre + ATT_UNIT_METRE = ATT_UUID_16(0x2701), + ///Mass unit - Kilogram + ATT_UNIT_KG = ATT_UUID_16(0x2702), + ///Time unit - second + ATT_UNIT_SECOND = ATT_UUID_16(0x2703), + ///Electric current unit - Ampere + ATT_UNIT_AMPERE = ATT_UUID_16(0x2704), + ///Thermodynamic Temperature unit - Kelvin + ATT_UNIT_KELVIN = ATT_UUID_16(0x2705), + /// Amount of substance unit - mole + ATT_UNIT_MOLE = ATT_UUID_16(0x2706), + ///Luminous intensity unit - candela + ATT_UNIT_CANDELA = ATT_UUID_16(0x2707), + ///Area unit - square metres + ATT_UNIT_SQ_METRE = ATT_UUID_16(0x2710), + ///Colume unit - cubic metres + ATT_UNIT_CUBIC_METRE = ATT_UUID_16(0x2710), + ///Velocity unit - metres per second + ATT_UNIT_METRE_PER_SECOND = ATT_UUID_16(0x2711), + ///Acceleration unit - metres per second squared + ATT_UNIT_METRES_PER_SEC_SQ = ATT_UUID_16(0x2712), + ///Wavenumber unit - reciprocal metre + ATT_UNIT_RECIPROCAL_METRE = ATT_UUID_16(0x2713), + ///Density unit - kilogram per cubic metre + ATT_UNIT_DENS_KG_PER_CUBIC_METRE = ATT_UUID_16(0x2714), + ///Surface density unit - kilogram per square metre + ATT_UNIT_KG_PER_SQ_METRE = ATT_UUID_16(0x2715), + ///Specific volume unit - cubic metre per kilogram + ATT_UNIT_CUBIC_METRE_PER_KG = ATT_UUID_16(0x2716), + ///Current density unit - ampere per square metre + ATT_UNIT_AMPERE_PER_SQ_METRE = ATT_UUID_16(0x2717), + ///Magnetic field strength unit - Ampere per metre + ATT_UNIT_AMPERE_PER_METRE = ATT_UUID_16(0x2718), + ///Amount concentration unit - mole per cubic metre + ATT_UNIT_MOLE_PER_CUBIC_METRE = ATT_UUID_16(0x2719), + ///Mass Concentration unit - kilogram per cubic metre + ATT_UNIT_MASS_KG_PER_CUBIC_METRE = ATT_UUID_16(0x271A), + ///Luminance unit - candela per square metre + ATT_UNIT_CANDELA_PER_SQ_METRE = ATT_UUID_16(0x271B), + ///Refractive index unit + ATT_UNIT_REFRACTIVE_INDEX = ATT_UUID_16(0x271C), + ///Relative permeability unit + ATT_UNIT_RELATIVE_PERMEABILITY = ATT_UUID_16(0x271D), + ///Plane angle unit - radian + ATT_UNIT_RADIAN = ATT_UUID_16(0x2720), + ///Solid angle unit - steradian + ATT_UNIT_STERADIAN = ATT_UUID_16(0x2721), + ///Frequency unit - Hertz + ATT_UNIT_HERTZ = ATT_UUID_16(0x2722), + ///Force unit - Newton + ATT_UNIT_NEWTON = ATT_UUID_16(0x2723), + ///Pressure unit - Pascal + ATT_UNIT_PASCAL = ATT_UUID_16(0x2724), + ///Energy unit - Joule + ATT_UNIT_JOULE = ATT_UUID_16(0x2725), + ///Power unit - Watt + ATT_UNIT_WATT = ATT_UUID_16(0x2726), + ///electric Charge unit - Coulomb + ATT_UNIT_COULOMB = ATT_UUID_16(0x2727), + ///Electric potential difference - Volt + ATT_UNIT_VOLT = ATT_UUID_16(0x2728), + ///Capacitance unit - Farad + ATT_UNIT_FARAD = ATT_UUID_16(0x2729), + ///electric resistance unit - Ohm + ATT_UNIT_OHM = ATT_UUID_16(0x272A), + ///Electric conductance - Siemens + ATT_UNIT_SIEMENS = ATT_UUID_16(0x272B), + ///Magnetic flux unit - Weber + ATT_UNIT_WEBER = ATT_UUID_16(0x272C), + ///Magnetic flux density unit - Tesla + ATT_UNIT_TESLA = ATT_UUID_16(0x272D), + ///Inductance unit - Henry + ATT_UNIT_HENRY = ATT_UUID_16(0x272E), + ///Temperature unit - degree Celsius + ATT_UNIT_CELSIUS = ATT_UUID_16(0x272F), + ///Luminous flux unit - lumen + ATT_UNIT_LUMEN = ATT_UUID_16(0x2730), + ///Illuminance unit - lux + ATT_UNIT_LUX = ATT_UUID_16(0x2731), + ///Activity referred to a radionuclide unit - becquerel + ATT_UNIT_BECQUEREL = ATT_UUID_16(0x2732), + ///Absorbed dose unit - Gray + ATT_UNIT_GRAY = ATT_UUID_16(0x2733), + ///Dose equivalent unit - Sievert + ATT_UNIT_SIEVERT = ATT_UUID_16(0x2734), + ///Catalytic activity unit - Katal + ATT_UNIT_KATAL = ATT_UUID_16(0x2735), + ///Synamic viscosity unit - Pascal second + ATT_UNIT_PASCAL_SECOND = ATT_UUID_16(0x2740), + ///Moment of force unit - Newton metre + ATT_UNIT_NEWTON_METRE = ATT_UUID_16(0x2741), + ///surface tension unit - Newton per metre + ATT_UNIT_NEWTON_PER_METRE = ATT_UUID_16(0x2742), + ///Angular velocity unit - radian per second + ATT_UNIT_RADIAN_PER_SECOND = ATT_UUID_16(0x2743), + ///Angular acceleration unit - radian per second squared + ATT_UNIT_RADIAN_PER_SECOND_SQ = ATT_UUID_16(0x2744), + ///Heat flux density unit - Watt per square metre + ATT_UNIT_WATT_PER_SQ_METRE = ATT_UUID_16(0x2745), + ///HEat capacity unit - Joule per Kelvin + ATT_UNIT_JOULE_PER_KELVIN = ATT_UUID_16(0x2746), + ///Specific heat capacity unit - Joule per kilogram kelvin + ATT_UNIT_JOULE_PER_KG_KELVIN = ATT_UUID_16(0x2747), + ///Specific Energy unit - Joule per kilogram + ATT_UNIT_JOULE_PER_KG = ATT_UUID_16(0x2748), + ///Thermal conductivity - Watt per metre Kelvin + ATT_UNIT_WATT_PER_METRE_KELVIN = ATT_UUID_16(0x2749), + ///Energy Density unit - joule per cubic metre + ATT_UNIT_JOULE_PER_CUBIC_METRE = ATT_UUID_16(0x274A), + ///Electric field strength unit - volt per metre + ATT_UNIT_VOLT_PER_METRE = ATT_UUID_16(0x274B), + ///Electric charge density unit - coulomb per cubic metre + ATT_UNIT_COULOMB_PER_CUBIC_METRE = ATT_UUID_16(0x274C), + ///Surface charge density unit - coulomb per square metre + ATT_UNIT_SURF_COULOMB_PER_SQ_METRE = ATT_UUID_16(0x274D), + ///Electric flux density unit - coulomb per square metre + ATT_UNIT_FLUX_COULOMB_PER_SQ_METRE = ATT_UUID_16(0x274E), + ///Permittivity unit - farad per metre + ATT_UNIT_FARAD_PER_METRE = ATT_UUID_16(0x274F), + ///Permeability unit - henry per metre + ATT_UNIT_HENRY_PER_METRE = ATT_UUID_16(0x2750), + ///Molar energy unit - joule per mole + ATT_UNIT_JOULE_PER_MOLE = ATT_UUID_16(0x2751), + ///Molar entropy unit - joule per mole kelvin + ATT_UNIT_JOULE_PER_MOLE_KELVIN = ATT_UUID_16(0x2752), + ///Exposure unit - coulomb per kilogram + ATT_UNIT_COULOMB_PER_KG = ATT_UUID_16(0x2753), + ///Absorbed dose rate unit - gray per second + ATT_UNIT_GRAY_PER_SECOND = ATT_UUID_16(0x2754), + ///Radiant intensity unit - watt per steradian + ATT_UNIT_WATT_PER_STERADIAN = ATT_UUID_16(0x2755), + ///Radiance unit - watt per square meter steradian + ATT_UNIT_WATT_PER_SQ_METRE_STERADIAN = ATT_UUID_16(0x2756), + ///Catalytic activity concentration unit - katal per cubic metre + ATT_UNIT_KATAL_PER_CUBIC_METRE = ATT_UUID_16(0x2757), + ///Time unit - minute + ATT_UNIT_MINUTE = ATT_UUID_16(0x2760), + ///Time unit - hour + ATT_UNIT_HOUR = ATT_UUID_16(0x2761), + ///Time unit - day + ATT_UNIT_DAY = ATT_UUID_16(0x2762), + ///Plane angle unit - degree + ATT_UNIT_ANGLE_DEGREE = ATT_UUID_16(0x2763), + ///Plane angle unit - minute + ATT_UNIT_ANGLE_MINUTE = ATT_UUID_16(0x2764), + ///Plane angle unit - second + ATT_UNIT_ANGLE_SECOND = ATT_UUID_16(0x2765), + ///Area unit - hectare + ATT_UNIT_HECTARE = ATT_UUID_16(0x2766), + ///Volume unit - litre + ATT_UNIT_LITRE = ATT_UUID_16(0x2767), + ///Mass unit - tonne + ATT_UNIT_TONNE = ATT_UUID_16(0x2768), + ///Pressure unit - bar + ATT_UNIT_BAR = ATT_UUID_16(0x2780), + ///Pressure unit - millimetre of mercury + ATT_UNIT_MM_MERCURY = ATT_UUID_16(0x2781), + ///Length unit - angstrom + ATT_UNIT_ANGSTROM = ATT_UUID_16(0x2782), + ///Length unit - nautical mile + ATT_UNIT_NAUTICAL_MILE = ATT_UUID_16(0x2783), + ///Area unit - barn + ATT_UNIT_BARN = ATT_UUID_16(0x2784), + ///Velocity unit - knot + ATT_UNIT_KNOT = ATT_UUID_16(0x2785), + ///Logarithmic radio quantity unit - neper + ATT_UNIT_NEPER = ATT_UUID_16(0x2786), + ///Logarithmic radio quantity unit - bel + ATT_UNIT_BEL = ATT_UUID_16(0x2787), + ///Length unit - yard + ATT_UNIT_YARD = ATT_UUID_16(0x27A0), + ///Length unit - parsec + ATT_UNIT_PARSEC = ATT_UUID_16(0x27A1), + ///length unit - inch + ATT_UNIT_INCH = ATT_UUID_16(0x27A2), + ///length unit - foot + ATT_UNIT_FOOT = ATT_UUID_16(0x27A3), + ///length unit - mile + ATT_UNIT_MILE = ATT_UUID_16(0x27A4), + ///pressure unit - pound-force per square inch + ATT_UNIT_POUND_FORCE_PER_SQ_INCH = ATT_UUID_16(0x27A5), + ///velocity unit - kilometre per hour + ATT_UNIT_KM_PER_HOUR = ATT_UUID_16(0x27A6), + ///velocity unit - mile per hour + ATT_UNIT_MILE_PER_HOUR = ATT_UUID_16(0x27A7), + ///angular velocity unit - revolution per minute + ATT_UNIT_REVOLUTION_PER_MINUTE = ATT_UUID_16(0x27A8), + ///energy unit - gram calorie + ATT_UNIT_GRAM_CALORIE = ATT_UUID_16(0x27A9), + ///energy unit - kilogram calorie + ATT_UNIT_KG_CALORIE = ATT_UUID_16(0x27AA), + /// energy unit - kilowatt hour + ATT_UNIT_KILOWATT_HOUR = ATT_UUID_16(0x27AB), + ///thermodynamic temperature unit - degree Fahrenheit + ATT_UNIT_FAHRENHEIT = ATT_UUID_16(0x27AC), + ///percentage + ATT_UNIT_PERCENTAGE = ATT_UUID_16(0x27AD), + ///per mille + ATT_UNIT_PER_MILLE = ATT_UUID_16(0x27AE), + ///period unit - beats per minute) + ATT_UNIT_BEATS_PER_MINUTE = ATT_UUID_16(0x27AF), + ///electric charge unit - ampere hours + ATT_UNIT_AMPERE_HOURS = ATT_UUID_16(0x27B0), + ///mass density unit - milligram per decilitre + ATT_UNIT_MILLIGRAM_PER_DECILITRE = ATT_UUID_16(0x27B1), + ///mass density unit - millimole per litre + ATT_UNIT_MILLIMOLE_PER_LITRE = ATT_UUID_16(0x27B2), + ///time unit - year + ATT_UNIT_YEAR = ATT_UUID_16(0x27B3), + ////time unit - month + ATT_UNIT_MONTH = ATT_UUID_16(0x27B4), + + + /*---------------- DECLARATIONS -----------------*/ + /// Primary service Declaration + ATT_DECL_PRIMARY_SERVICE = ATT_UUID_16(0x2800), + /// Secondary service Declaration + ATT_DECL_SECONDARY_SERVICE = ATT_UUID_16(0x2801), + /// Include Declaration + ATT_DECL_INCLUDE = ATT_UUID_16(0x2802), + /// Characteristic Declaration + ATT_DECL_CHARACTERISTIC = ATT_UUID_16(0x2803), + + + /*----------------- DESCRIPTORS -----------------*/ + /// Characteristic extended properties + ATT_DESC_CHAR_EXT_PROPERTIES = ATT_UUID_16(0x2900), + /// Characteristic user description + ATT_DESC_CHAR_USER_DESCRIPTION = ATT_UUID_16(0x2901), + /// Client characteristic configuration + ATT_DESC_CLIENT_CHAR_CFG = ATT_UUID_16(0x2902), + /// Server characteristic configuration + ATT_DESC_SERVER_CHAR_CFG = ATT_UUID_16(0x2903), + /// Characteristic Presentation Format + ATT_DESC_CHAR_PRES_FORMAT = ATT_UUID_16(0x2904), + /// Characteristic Aggregate Format + ATT_DESC_CHAR_AGGREGATE_FORMAT = ATT_UUID_16(0x2905), + /// Valid Range + ATT_DESC_VALID_RANGE = ATT_UUID_16(0x2906), + /// External Report Reference + ATT_DESC_EXT_REPORT_REF = ATT_UUID_16(0x2907), + /// Report Reference + ATT_DESC_REPORT_REF = ATT_UUID_16(0x2908), + /// Environmental Sensing Configuration + ATT_DESC_ES_CONFIGURATION = ATT_UUID_16(0x290B), + /// Environmental Sensing Measurement + ATT_DESC_ES_MEASUREMENT = ATT_UUID_16(0x290C), + /// Environmental Sensing Trigger Setting + ATT_DESC_ES_TRIGGER_SETTING = ATT_UUID_16(0x290D), + + + /*--------------- CHARACTERISTICS ---------------*/ + /// Device name + ATT_CHAR_DEVICE_NAME = ATT_UUID_16(0x2A00), + /// Appearance + ATT_CHAR_APPEARANCE = ATT_UUID_16(0x2A01), + /// Privacy flag + ATT_CHAR_PRIVACY_FLAG = ATT_UUID_16(0x2A02), + /// Reconnection address + ATT_CHAR_RECONNECTION_ADDR = ATT_UUID_16(0x2A03), + /// Peripheral preferred connection parameters + ATT_CHAR_PERIPH_PREF_CON_PARAM = ATT_UUID_16(0x2A04), + /// Service handles changed + ATT_CHAR_SERVICE_CHANGED = ATT_UUID_16(0x2A05), + /// Alert Level characteristic + ATT_CHAR_ALERT_LEVEL = ATT_UUID_16(0x2A06), + /// Tx Power Level + ATT_CHAR_TX_POWER_LEVEL = ATT_UUID_16(0x2A07), + /// Date Time + ATT_CHAR_DATE_TIME = ATT_UUID_16(0x2A08), + /// Day of Week + ATT_CHAR_DAY_WEEK = ATT_UUID_16(0x2A09), + /// Day Date Time + ATT_CHAR_DAY_DATE_TIME = ATT_UUID_16(0x2A0A), + /// Exact time 256 + ATT_CHAR_EXACT_TIME_256 = ATT_UUID_16(0x2A0C), + /// DST Offset + ATT_CHAR_DST_OFFSET = ATT_UUID_16(0x2A0D), + /// Time zone + ATT_CHAR_TIME_ZONE = ATT_UUID_16(0x2A0E), + /// Local time Information + ATT_CHAR_LOCAL_TIME_INFO = ATT_UUID_16(0x2A0F), + /// Time with DST + ATT_CHAR_TIME_WITH_DST = ATT_UUID_16(0x2A11), + /// Time Accuracy + ATT_CHAR_TIME_ACCURACY = ATT_UUID_16(0x2A12), + ///Time Source + ATT_CHAR_TIME_SOURCE = ATT_UUID_16(0x2A13), + /// Reference Time Information + ATT_CHAR_REFERENCE_TIME_INFO = ATT_UUID_16(0x2A14), + /// Time Update Control Point + ATT_CHAR_TIME_UPDATE_CNTL_POINT = ATT_UUID_16(0x2A16), + /// Time Update State + ATT_CHAR_TIME_UPDATE_STATE = ATT_UUID_16(0x2A17), + /// Glucose Measurement + ATT_CHAR_GLUCOSE_MEAS = ATT_UUID_16(0x2A18), + /// Battery Level + ATT_CHAR_BATTERY_LEVEL = ATT_UUID_16(0x2A19), + /// Temperature Measurement + ATT_CHAR_TEMPERATURE_MEAS = ATT_UUID_16(0x2A1C), + /// Temperature Type + ATT_CHAR_TEMPERATURE_TYPE = ATT_UUID_16(0x2A1D), + /// Intermediate Temperature + ATT_CHAR_INTERMED_TEMPERATURE = ATT_UUID_16(0x2A1E), + /// Measurement Interval + ATT_CHAR_MEAS_INTERVAL = ATT_UUID_16(0x2A21), + /// Boot Keyboard Input Report + ATT_CHAR_BOOT_KB_IN_REPORT = ATT_UUID_16(0x2A22), + /// System ID + ATT_CHAR_SYS_ID = ATT_UUID_16(0x2A23), + /// Model Number String + ATT_CHAR_MODEL_NB = ATT_UUID_16(0x2A24), + /// Serial Number String + ATT_CHAR_SERIAL_NB = ATT_UUID_16(0x2A25), + /// Firmware Revision String + ATT_CHAR_FW_REV = ATT_UUID_16(0x2A26), + /// Hardware revision String + ATT_CHAR_HW_REV = ATT_UUID_16(0x2A27), + /// Software Revision String + ATT_CHAR_SW_REV = ATT_UUID_16(0x2A28), + /// Manufacturer Name String + ATT_CHAR_MANUF_NAME = ATT_UUID_16(0x2A29), + /// IEEE Regulatory Certification Data List + ATT_CHAR_IEEE_CERTIF = ATT_UUID_16(0x2A2A), + /// CT Time + ATT_CHAR_CT_TIME = ATT_UUID_16(0x2A2B), + /// Magnetic Declination + ATT_CHAR_MAGN_DECLINE = ATT_UUID_16(0x2A2C), + /// Scan Refresh + ATT_CHAR_SCAN_REFRESH = ATT_UUID_16(0x2A31), + /// Boot Keyboard Output Report + ATT_CHAR_BOOT_KB_OUT_REPORT = ATT_UUID_16(0x2A32), + /// Boot Mouse Input Report + ATT_CHAR_BOOT_MOUSE_IN_REPORT = ATT_UUID_16(0x2A33), + /// Glucose Measurement Context + ATT_CHAR_GLUCOSE_MEAS_CTX = ATT_UUID_16(0x2A34), + /// Blood Pressure Measurement + ATT_CHAR_BLOOD_PRESSURE_MEAS = ATT_UUID_16(0x2A35), + /// Intermediate Cuff Pressure + ATT_CHAR_INTERMEDIATE_CUFF_PRESSURE = ATT_UUID_16(0x2A36), + /// Heart Rate Measurement + ATT_CHAR_HEART_RATE_MEAS = ATT_UUID_16(0x2A37), + /// Body Sensor Location + ATT_CHAR_BODY_SENSOR_LOCATION = ATT_UUID_16(0x2A38), + /// Heart Rate Control Point + ATT_CHAR_HEART_RATE_CNTL_POINT = ATT_UUID_16(0x2A39), + /// Alert Status + ATT_CHAR_ALERT_STATUS = ATT_UUID_16(0x2A3F), + /// Ringer Control Point + ATT_CHAR_RINGER_CNTL_POINT = ATT_UUID_16(0x2A40), + /// Ringer Setting + ATT_CHAR_RINGER_SETTING = ATT_UUID_16(0x2A41), + /// Alert Category ID Bit Mask + ATT_CHAR_ALERT_CAT_ID_BIT_MASK = ATT_UUID_16(0x2A42), + /// Alert Category ID + ATT_CHAR_ALERT_CAT_ID = ATT_UUID_16(0x2A43), + /// Alert Notification Control Point + ATT_CHAR_ALERT_NTF_CTNL_PT = ATT_UUID_16(0x2A44), + /// Unread Alert Status + ATT_CHAR_UNREAD_ALERT_STATUS = ATT_UUID_16(0x2A45), + /// New Alert + ATT_CHAR_NEW_ALERT = ATT_UUID_16(0x2A46), + /// Supported New Alert Category + ATT_CHAR_SUP_NEW_ALERT_CAT = ATT_UUID_16(0x2A47), + /// Supported Unread Alert Category + ATT_CHAR_SUP_UNREAD_ALERT_CAT = ATT_UUID_16(0x2A48), + /// Blood Pressure Feature + ATT_CHAR_BLOOD_PRESSURE_FEATURE = ATT_UUID_16(0x2A49), + /// HID Information + ATT_CHAR_HID_INFO = ATT_UUID_16(0x2A4A), + /// Report Map + ATT_CHAR_REPORT_MAP = ATT_UUID_16(0x2A4B), + /// HID Control Point + ATT_CHAR_HID_CTNL_PT = ATT_UUID_16(0x2A4C), + /// Report + ATT_CHAR_REPORT = ATT_UUID_16(0x2A4D), + /// Protocol Mode + ATT_CHAR_PROTOCOL_MODE = ATT_UUID_16(0x2A4E), + /// Scan Interval Window + ATT_CHAR_SCAN_INTV_WD = ATT_UUID_16(0x2A4F), + /// PnP ID + ATT_CHAR_PNP_ID = ATT_UUID_16(0x2A50), + /// Glucose Feature + ATT_CHAR_GLUCOSE_FEATURE = ATT_UUID_16(0x2A51), + /// Record access control point + ATT_CHAR_REC_ACCESS_CTRL_PT = ATT_UUID_16(0x2A52), + /// RSC Measurement + ATT_CHAR_RSC_MEAS = ATT_UUID_16(0x2A53), + /// RSC Feature + ATT_CHAR_RSC_FEAT = ATT_UUID_16(0x2A54), + /// SC Control Point + ATT_CHAR_SC_CNTL_PT = ATT_UUID_16(0x2A55), + /// CSC Measurement + ATT_CHAR_CSC_MEAS = ATT_UUID_16(0x2A5B), + /// CSC Feature + ATT_CHAR_CSC_FEAT = ATT_UUID_16(0x2A5C), + /// Sensor Location + ATT_CHAR_SENSOR_LOC = ATT_UUID_16(0x2A5D), + /// PLX Spot-Check Measurement + ATT_CHAR_PLX_SPOT_CHECK_MEASUREMENT_LOC = ATT_UUID_16(0x2A5E), + /// PLX Continuous Measurement + ATT_CHAR_PLX_CONTINUOUS_MEASUREMENT_LOC = ATT_UUID_16(0x2A5F), + /// PLX Features + ATT_CHAR_PLX_FEATURES_LOC = ATT_UUID_16(0x2A60), + /// CP Measurement + ATT_CHAR_CP_MEAS = ATT_UUID_16(0x2A63), + /// CP Vector + ATT_CHAR_CP_VECTOR = ATT_UUID_16(0x2A64), + /// CP Feature + ATT_CHAR_CP_FEAT = ATT_UUID_16(0x2A65), + /// CP Control Point + ATT_CHAR_CP_CNTL_PT = ATT_UUID_16(0x2A66), + /// Location and Speed + ATT_CHAR_LOC_SPEED = ATT_UUID_16(0x2A67), + /// Navigation + ATT_CHAR_NAVIGATION = ATT_UUID_16(0x2A68), + /// Position Quality + ATT_CHAR_POS_QUALITY = ATT_UUID_16(0x2A69), + /// LN Feature + ATT_CHAR_LN_FEAT = ATT_UUID_16(0x2A6A), + /// LN Control Point + ATT_CHAR_LN_CNTL_PT = ATT_UUID_16(0x2A6B), + /// Elevation + ATT_CHAR_ELEVATION = ATT_UUID_16(0x2A6C), + /// Pressure + ATT_CHAR_PRESSURE = ATT_UUID_16(0x2A6D), + /// Temperature + ATT_CHAR_TEMPERATURE = ATT_UUID_16(0x2A6E), + /// Humidity + ATT_CHAR_HUMIDITY = ATT_UUID_16(0x2A6F), + /// True Wind Speed + ATT_CHAR_TRUE_WIND_SPEED = ATT_UUID_16(0x2A70), + /// True Wind Direction + ATT_CHAR_TRUE_WIND_DIR = ATT_UUID_16(0x2A71), + /// Apparent Wind Speed + ATT_CHAR_APRNT_WIND_SPEED = ATT_UUID_16(0x2A72), + /// Apparent Wind Direction + ATT_CHAR_APRNT_WIND_DIRECTION = ATT_UUID_16(0x2A73), + /// Gust Factor + ATT_CHAR_GUST_FACTOR = ATT_UUID_16(0x2A74), + /// Pollen Concentration + ATT_CHAR_POLLEN_CONC = ATT_UUID_16(0x2A75), + /// UV Index + ATT_CHAR_UV_INDEX = ATT_UUID_16(0x2A76), + /// Irradiance + ATT_CHAR_IRRADIANCE = ATT_UUID_16(0x2A77), + /// Rainfall + ATT_CHAR_RAINFALL = ATT_UUID_16(0x2A78), + /// Wind Chill + ATT_CHAR_WIND_CHILL = ATT_UUID_16(0x2A79), + /// Heat Index + ATT_CHAR_HEAT_INDEX = ATT_UUID_16(0x2A7A), + /// Dew Point + ATT_CHAR_DEW_POINT = ATT_UUID_16(0x2A7B), + /// Descriptor Value Changed + ATT_CHAR_DESCRIPTOR_VALUE_CHANGED = ATT_UUID_16(0x2A7D), + /// Aerobic Heart Rate Lower Limit + ATT_CHAR_AEROBIC_HEART_RATE_LOWER_LIMIT = ATT_UUID_16(0x2A7E), + /// Aerobic Threshhold + ATT_CHAR_AEROBIC_THRESHHOLD = ATT_UUID_16(0x2A7F), + /// Age + ATT_CHAR_AGE = ATT_UUID_16(0x2A80), + /// Anaerobic Heart Rate Lower Limit + ATT_CHAR_ANAEROBIC_HEART_RATE_LOWER_LIMIT = ATT_UUID_16(0x2A81), + /// Anaerobic Heart Rate Upper Limit + ATT_CHAR_ANAEROBIC_HEART_RATE_UPPER_LIMIT = ATT_UUID_16(0x2A82), + /// Anaerobic Threshhold + ATT_CHAR_ANAEROBIC_THRESHHOLD = ATT_UUID_16(0x2A83), + /// Aerobic Heart Rate Upper Limit + ATT_CHAR_AEROBIC_HEART_RATE_UPPER_LIMIT = ATT_UUID_16(0x2A84), + /// Date Of Birth + ATT_CHAR_DATE_OF_BIRTH = ATT_UUID_16(0x2A85), + /// Date Of Threshold Assessment + ATT_CHAR_DATE_OF_THRESHOLD_ASSESSMENT = ATT_UUID_16(0x2A86), + /// Email Address + ATT_CHAR_EMAIL_ADDRESS = ATT_UUID_16(0x2A87), + /// Fat Burn Heart Rate Lower Limit + ATT_CHAR_FAT_BURN_HEART_RATE_LOWER_LIMIT = ATT_UUID_16(0x2A88), + /// Fat Burn Heart Rate Upper Limit + ATT_CHAR_FAT_BURN_HEART_RATE_UPPER_LIMIT = ATT_UUID_16(0x2A89), + /// First Name + ATT_CHAR_FIRST_NAME = ATT_UUID_16(0x2A8A), + /// Five Zone Heart Rate Limits + ATT_CHAR_FIVE_ZONE_HEART_RATE_LIMITS = ATT_UUID_16(0x2A8B), + /// Gender + ATT_CHAR_GENDER = ATT_UUID_16(0x2A8C), + /// Max Heart Rate + ATT_CHAR_MAX_HEART_RATE = ATT_UUID_16(0x2A8D), + /// Height + ATT_CHAR_HEIGHT = ATT_UUID_16(0x2A8E), + /// Hip Circumference + ATT_CHAR_HIP_CIRCUMFERENCE = ATT_UUID_16(0x2A8F), + /// Last Name + ATT_CHAR_LAST_NAME = ATT_UUID_16(0x2A90), + /// Maximum Recommended Heart Rate + ATT_CHAR_MAXIMUM_RECOMMENDED_HEART_RATE = ATT_UUID_16(0x2A91), + /// Resting Heart Rate + ATT_CHAR_RESTING_HEART_RATE = ATT_UUID_16(0x2A92), + /// Sport Type For Aerobic And Anaerobic Thresholds + ATT_CHAR_SPORT_TYPE_FOR_AEROBIC_AND_ANAEROBIC_THRESHOLDS = ATT_UUID_16(0x2A93), + /// Three Zone Heart Rate Limits + ATT_CHAR_THREE_ZONE_HEART_RATE_LIMITS = ATT_UUID_16(0x2A94), + /// Two Zone Heart Rate Limit + ATT_CHAR_TWO_ZONE_HEART_RATE_LIMIT = ATT_UUID_16(0x2A95), + /// Vo2 Max + ATT_CHAR_VO2_MAX = ATT_UUID_16(0x2A96), + /// Waist Circumference + ATT_CHAR_WAIST_CIRCUMFERENCE = ATT_UUID_16(0x2A97), + /// Weight + ATT_CHAR_WEIGHT = ATT_UUID_16(0x2A98), + /// Database Change Increment + ATT_CHAR_DATABASE_CHANGE_INCREMENT = ATT_UUID_16(0x2A99), + /// User Index + ATT_CHAR_USER_INDEX = ATT_UUID_16(0x2A9A), + /// Body Composition Feature + ATT_CHAR_BODY_COMPOSITION_FEATURE = ATT_UUID_16(0x2A9B), + /// Body Composition Measurement + ATT_CHAR_BODY_COMPOSITION_MEASUREMENT = ATT_UUID_16(0x2A9C), + /// Weight Measurement + ATT_CHAR_WEIGHT_MEASUREMENT = ATT_UUID_16(0x2A9D), + /// Weight Scale Feature + ATT_CHAR_WEIGHT_SCALE_FEATURE = ATT_UUID_16(0x2A9E), + /// User Control Point + ATT_CHAR_USER_CONTROL_POINT = ATT_UUID_16(0x2A9F), + /// Flux Density - 2D + ATT_CHAR_MAGN_FLUX_2D = ATT_UUID_16(0x2AA0), + /// Magnetic Flux Density - 3D + ATT_CHAR_MAGN_FLUX_3D = ATT_UUID_16(0x2AA1), + /// Language string + ATT_CHAR_LANGUAGE = ATT_UUID_16(0x2AA2), + /// Barometric Pressure Trend + ATT_CHAR_BAR_PRES_TREND = ATT_UUID_16(0x2AA3), + /// Central Address Resolution Support + ATT_CHAR_CTL_ADDR_RESOL_SUPP = ATT_UUID_16(0x2AA6), + /// CGM Measurement + ATT_CHAR_CGM_MEASUREMENT = ATT_UUID_16(0x2AA7), + /// CGM Features + ATT_CHAR_CGM_FEATURES = ATT_UUID_16(0x2AA8), + /// CGM Status + ATT_CHAR_CGM_STATUS = ATT_UUID_16(0x2AA9), + /// CGM Session Start + ATT_CHAR_CGM_SESSION_START = ATT_UUID_16(0x2AAA), + /// CGM Session Run + ATT_CHAR_CGM_SESSION_RUN = ATT_UUID_16(0x2AAB), + /// CGM Specific Ops Control Point + ATT_CHAR_CGM_SPECIFIC_OPS_CTRL_PT = ATT_UUID_16(0x2AAC), + /// Resolvable Private Address only + ATT_CHAR_RSLV_PRIV_ADDR_ONLY = ATT_UUID_16(0x2AC9), + /// Mesh Provisioning Data In + ATT_CHAR_MESH_PROV_DATA_IN = ATT_UUID_16(0x2ADB), + /// Mesh Provisioning Data Out + ATT_CHAR_MESH_PROV_DATA_OUT = ATT_UUID_16(0x2ADC), + /// Mesh Proxy Data In + ATT_CHAR_MESH_PROXY_DATA_IN = ATT_UUID_16(0x2ADD), + /// Mesh Proxy Data Out + ATT_CHAR_MESH_PROXY_DATA_OUT = ATT_UUID_16(0x2ADE), + + /// Client Supported Features + ATT_CHAR_CLI_SUP_FEAT = ATT_UUID_16(0x2B29), + /// Database Hash + ATT_CHAR_DB_HASH = ATT_UUID_16(0x2B2A), +}; + +/// Format for Characteristic Presentation +enum { + /// unsigned 1-bit: true or false + ATT_FORMAT_BOOL = 0x01, + /// unsigned 2-bit integer + ATT_FORMAT_2BIT, + /// unsigned 4-bit integer + ATT_FORMAT_NIBBLE, + /// unsigned 8-bit integer + ATT_FORMAT_UINT8, + /// unsigned 12-bit integer + ATT_FORMAT_UINT12, + /// unsigned 16-bit integer + ATT_FORMAT_UINT16, + /// unsigned 24-bit integer + ATT_FORMAT_UINT24, + /// unsigned 32-bit integer + ATT_FORMAT_UINT32, + /// unsigned 48-bit integer + ATT_FORMAT_UINT48, + /// unsigned 64-bit integer + ATT_FORMAT_UINT64, + /// unsigned 128-bit integer + ATT_FORMAT_UINT128, + /// signed 8-bit integer + ATT_FORMAT_SINT8, + /// signed 12-bit integer + ATT_FORMAT_SINT12, + /// signed 16-bit integer + ATT_FORMAT_SINT16, + /// signed 24-bit integer + ATT_FORMAT_SINT24, + /// signed 32-bit integer + ATT_FORMAT_SINT32, + /// signed 48-bit integer + ATT_FORMAT_SINT48, + /// signed 64-bit integer + ATT_FORMAT_SINT64, + /// signed 128-bit integer + ATT_FORMAT_SINT128, + /// IEEE-754 32-bit floating point + ATT_FORMAT_FLOAT32, + /// IEEE-754 64-bit floating point + ATT_FORMAT_FLOAT64, + /// IEEE-11073 16-bit SFLOAT + ATT_FORMAT_SFLOAT, + /// IEEE-11073 32-bit FLOAT + ATT_FORMAT_FLOAT, + /// IEEE-20601 format + ATT_FORMAT_DUINT16, + /// UTF-8 string + ATT_FORMAT_UTF8S, + /// UTF-16 string + ATT_FORMAT_UTF16S, + /// Opaque structure + ATT_FORMAT_STRUCT, + /// Last format + ATT_FORMAT_LAST +}; + + +/// Client Characteristic Configuration Codes +enum att_ccc_val +{ + /// Stop notification/indication + ATT_CCC_STOP_NTFIND = 0x0000, + /// Start notification + ATT_CCC_START_NTF, + /// Start indication + ATT_CCC_START_IND +}; + +/* + * Type Definition + **************************************************************************************** + */ + +/// Attribute length type +typedef uint16_t att_size_t; + + +/// UUID - 128-bit type +struct att_uuid_128 +{ + /// 128-bit UUID + uint8_t uuid[ATT_UUID_128_LEN]; +}; + +/// UUID - 32-bit type +struct att_uuid_32 +{ + /// 32-bit UUID + uint8_t uuid[ATT_UUID_32_LEN]; +}; + + + +/// Characteristic Value Descriptor +struct att_char_desc +{ + /// properties + uint8_t prop; + /// attribute handle + uint8_t attr_hdl[ATT_HANDLE_LEN]; + /// attribute type + uint8_t attr_type[ATT_UUID_16_LEN]; +}; + +/// Characteristic Value Descriptor +struct att_char128_desc +{ + /// properties + uint8_t prop; + /// attribute handle + uint8_t attr_hdl[ATT_HANDLE_LEN]; + /// attribute type + uint8_t attr_type[ATT_UUID_128_LEN]; +}; + +/// Service Value Descriptor - 16-bit +typedef uint16_t att_svc_desc_t; + +/// include service entry element +struct att_incl_desc +{ + /// start handle value of included service + uint16_t start_hdl; + /// end handle value of included service + uint16_t end_hdl; + /// attribute value UUID + uint16_t uuid; +}; + +/// include service entry element +struct att_incl128_desc +{ + /// start handle value of included service + uint16_t start_hdl; + /// end handle value of included service + uint16_t end_hdl; +}; + + +// -------------------------- PDU HANDLER Definition -------------------------- + +/// used to know if PDU handler has been found +#define ATT_PDU_HANDLER_NOT_FOUND (0xff) + +/// Format of a pdu handler function +typedef int (*att_func_t)(uint8_t conidx, void *pdu); + +/// Element of a pdu handler table. +struct att_pdu_handler +{ + /// PDU identifier of the message + uint8_t pdu_id; + /// Pointer to the handler function for the pdu above. + att_func_t handler; +}; + + +// --------------------------- Database permissions ----------------------------- + +/// Macro used to retrieve access permission rights +#define PERM_GET(perm, access)\ + (((perm) & (PERM_MASK_ ## access)) >> (PERM_POS_ ## access)) + +/// Macro used to set a permission value +#define PERM_SET(perm, access, value)\ + perm = ((perm & ~(PERM_MASK_ ## access)) | ((value << (PERM_POS_ ## access)) & (PERM_MASK_ ## access))) + +/// Macro used to retrieve permission value from access and rights on attribute. +#define PERM(access, right) \ + (((PERM_RIGHT_ ## right) << (PERM_POS_ ## access)) & (PERM_MASK_ ## access)) + +/// Macro used know if permission is set or not. +#define PERM_IS_SET(perm, access, right) \ + (((perm) & (((PERM_RIGHT_ ## right) << (PERM_POS_ ## access))) \ + & (PERM_MASK_ ## access)) == PERM(access, right)) + +/// Retrieve attribute security level from attribute right and service right +#define ATT_GET_SEC_LVL(att_right, svc_right) \ + common_max(((att_right) & PERM_RIGHT_AUTH), ((svc_right) & PERM_RIGHT_AUTH)); + +/// Retrieve UUID LEN from UUID Length Permission +#define ATT_UUID_LEN(uuid_len_perm) ((uuid_len_perm == 0) ? ATT_UUID_16_LEN : \ + ((uuid_len_perm == 1) ? ATT_UUID_32_LEN : \ + ((uuid_len_perm == 2) ? ATT_UUID_128_LEN : 0))) + +/// Initialization of attribute element +#define ATT_ELEMT_INIT {{NULL}, false} + +/** + * 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + * +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + * |EXT | WS | I | N | WR | WC | RD | B | NP | IP | WP | RP | + * +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + * + * Bit [0-1] : Read Permission (0 = NO_AUTH, 1 = UNAUTH, 2 = AUTH, 3 = SEC_CON) + * Bit [2-3] : Write Permission (0 = NO_AUTH, 1 = UNAUTH, 2 = AUTH, 3 = SEC_CON) + * Bit [4-5] : Indication Permission (0 = NO_AUTH, 1 = UNAUTH, 2 = AUTH, 3 = SEC_CON) + * Bit [6-7] : Notification Permission (0 = NO_AUTH, 1 = UNAUTH, 2 = AUTH, 3 = SEC_CON) + * + * Bit [8] : Extended properties present (only relevant for a characteristic value) + * Bit [9] : Broadcast permission (only relevant for a characteristic value) + * Bit [10] : Write Command accepted + * Bit [11] : Write Signed accepted + * Bit [12] : Write Request accepted + * Bit [13] : Encryption key Size must be 16 bytes + */ +enum attm_perm_mask +{ + /// retrieve all permission info + PERM_MASK_ALL = 0x0000, + /// Read Permission Mask + PERM_MASK_RP = 0x0003, + PERM_POS_RP = 0, + /// Write Permission Mask + PERM_MASK_WP = 0x000C, + PERM_POS_WP = 2, + /// Indication Access Mask + PERM_MASK_IP = 0x0030, + PERM_POS_IP = 4, + /// Notification Access Mask + PERM_MASK_NP = 0x00C0, + PERM_POS_NP = 6, + /// Broadcast descriptor present + PERM_MASK_BROADCAST = 0x0100, + PERM_POS_BROADCAST = 8, + /// Read Access Mask + PERM_MASK_RD = 0x0200, + PERM_POS_RD = 9, + /// Write Command Enabled attribute Mask + PERM_MASK_WRITE_COMMAND = 0x0400, + PERM_POS_WRITE_COMMAND = 10, + /// Write Request Enabled attribute Mask + PERM_MASK_WRITE_REQ = 0x0800, + PERM_POS_WRITE_REQ = 11, + /// Notification Access Mask + PERM_MASK_NTF = 0x1000, + PERM_POS_NTF = 12, + /// Indication Access Mask + PERM_MASK_IND = 0x2000, + PERM_POS_IND = 13, + /// Write Signed Enabled attribute Mask + PERM_MASK_WRITE_SIGNED = 0x4000, + PERM_POS_WRITE_SIGNED = 14, + /// Extended properties descriptor present + PERM_MASK_EXT = 0x8000, + PERM_POS_EXT = 15, + + /// Properties + PERM_MASK_PROP = 0xFF00, + PERM_POS_PROP = 8, +}; + +/** + * Value permission bit field + * + * 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + * +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + * | RI |UUID_LEN |EKS | MAX_LEN (RI = 1) / Value Offset (RI = 0) | + * +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + * + * Bit [0-11] : Maximum Attribute Length or Value Offset pointer + * Bit [12] : Encryption key Size must be 16 bytes + * Bit [14-13]: UUID Length (0 = 16 bits, 1 = 32 bits, 2 = 128 bits, 3 = RFU) + * Bit [15] : Trigger Read Indication (0 = Value present in Database, 1 = Value not present in Database) + */ +enum attm_value_perm_mask +{ + /// Maximum Attribute Length + PERM_MASK_MAX_LEN = 0x0FFF, + PERM_POS_MAX_LEN = 0, + /// Attribute value Offset + PERM_MASK_VAL_OFFSET = 0x0FFF, + PERM_POS_VAL_OFFSET = 0, + /// Check Encryption key size Mask + PERM_MASK_EKS = 0x1000, + PERM_POS_EKS = 12, + /// UUID Length + PERM_MASK_UUID_LEN = 0x6000, + PERM_POS_UUID_LEN = 13, + /// Read trigger Indication + PERM_MASK_RI = 0x8000, + PERM_POS_RI = 15, +}; + + +/** + * Service permissions + * + * 7 6 5 4 3 2 1 0 + * +----+----+----+----+----+----+----+----+ + * |SEC |UUID_LEN |DIS | AUTH |EKS | MI | + * +----+----+----+----+----+----+----+----+ + * + * Bit [0] : Task that manage service is multi-instantiated (Connection index is conveyed) + * Bit [1] : Encryption key Size must be 16 bytes + * Bit [2-3]: Service Permission (0 = NO_AUTH, 1 = UNAUTH, 2 = AUTH, 3 = Secure Connect) + * Bit [4] : Disable the service + * Bit [5-6]: UUID Length (0 = 16 bits, 1 = 32 bits, 2 = 128 bits, 3 = RFU) + * Bit [7] : Secondary Service (0 = Primary Service, 1 = Secondary Service) + */ +enum attm_svc_perm_mask +{ + /// Task that manage service is multi-instantiated + PERM_MASK_SVC_MI = 0x01, + PERM_POS_SVC_MI = 0, + /// Check Encryption key size for service Access + PERM_MASK_SVC_EKS = 0x02, + PERM_POS_SVC_EKS = 1, + /// Service Permission authentication + PERM_MASK_SVC_AUTH = 0x0C, + PERM_POS_SVC_AUTH = 2, + /// Disable the service + PERM_MASK_SVC_DIS = 0x10, + PERM_POS_SVC_DIS = 4, + /// Service UUID Length + PERM_MASK_SVC_UUID_LEN = 0x60, + PERM_POS_SVC_UUID_LEN = 5, + /// Service type Secondary + PERM_MASK_SVC_SECONDARY = 0x80, + PERM_POS_SVC_SECONDARY = 7, +}; + + +/// Attribute & Service access mode +enum +{ + /// Disable access + PERM_RIGHT_DISABLE = 0, + /// Enable access + PERM_RIGHT_ENABLE = 1, +}; + +/// Attribute & Service access rights +enum +{ + /// No Authentication + PERM_RIGHT_NO_AUTH = 0, + /// Access Requires Unauthenticated link + PERM_RIGHT_UNAUTH = 1, + /// Access Requires Authenticated link + PERM_RIGHT_AUTH = 2, + /// Access Requires Secure Connection link + PERM_RIGHT_SEC_CON = 3, +}; + +/// Attribute & Service UUID Length +enum +{ + /// 16 bits UUID + PERM_UUID_16 = 0, + PERM_RIGHT_UUID_16 = 0, + /// 32 bits UUID + PERM_UUID_32 = 1, + PERM_RIGHT_UUID_32 = 1, + /// 128 bits UUID + PERM_UUID_128 = 2, + PERM_RIGHT_UUID_128 = 2, + /// Invalid + PERM_UUID_RFU = 3, +}; + +/// execute flags +enum +{ + /// Cancel All the Reliable Writes + ATT_CANCEL_ALL_PREPARED_WRITES = 0x00, + /// Write All the Reliable Writes + ATT_EXECUTE_ALL_PREPARED_WRITES +}; + + + +/// @} ATT +#endif // ATT_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/api/gap.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/api/gap.h new file mode 100755 index 0000000..b349194 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/api/gap.h @@ -0,0 +1,660 @@ +/** + **************************************************************************************** + * + * @file gap.h + * + * @brief Header file - GAP. + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ +#ifndef GAP_H_ +#define GAP_H_ +/** + **************************************************************************************** + * @addtogroup HOST + * @ingroup ROOT + * @brief Bluetooth Low Energy Host + * + * The HOST layer of the stack contains the higher layer protocols (@ref ATT "ATT", + * @ref SMP "SMP") and transport module (@ref L2C "L2C"). It also includes the Generic + * Access Profile (@ref GAP "GAP"), used for scanning/connection operations. + **************************************************************************************** + */ +/** + **************************************************************************************** + * @addtogroup GAP Generic Access Profile + * @ingroup HOST + * @brief Generic Access Profile. + * + * The GAP module is responsible for providing an API to the application in order to + * configure the device in the desired mode (discoverable, connectable, etc.) and perform + * required actions (scanning, connection, pairing, etc.). To achieve this, the GAP + * interfaces with both the @ref SMP "SMP", @ref L2C "L2C" and the @ref CONTROLLER "CONTROLLER" + * + * @{ + **************************************************************************************** + */ + +#include +#include "compiler.h" + +/* + * DEFINES + **************************************************************************************** + */ + +/// BD address length +#define GAP_BD_ADDR_LEN (6) +/// LE Channel map length +#define GAP_LE_CHNL_MAP_LEN (0x05) +/// LE Feature Flags Length +#define GAP_LE_FEATS_LEN (0x08) +/// ADV Data and Scan Response length +#define GAP_ADV_DATA_LEN (0x1F) +#define GAP_SCAN_RSP_DATA_LEN (0x1F) +/// Random number length +#define GAP_RAND_NB_LEN (0x08) +/// Key length +#define GAP_KEY_LEN (16) +/// P256 Key Len +#define GAP_P256_KEY_LEN (0x20) + + +///***** AD Type Flag - Bit set *******/ +/// Limited discovery flag - AD Flag +#define GAP_LE_LIM_DISCOVERABLE_FLG 0x01 +/// General discovery flag - AD Flag +#define GAP_LE_GEN_DISCOVERABLE_FLG 0x02 +/// Legacy BT not supported - AD Flag +#define GAP_BR_EDR_NOT_SUPPORTED 0x04 +/// Dual mode for controller supported (BR/EDR/LE) - AD Flag +#define GAP_SIMUL_BR_EDR_LE_CONTROLLER 0x08 +/// Dual mode for host supported (BR/EDR/LE) - AD Flag +#define GAP_SIMUL_BR_EDR_LE_HOST 0x10 + +/*********** GAP Miscellaneous Defines *************/ +/// Invalid activity index +#define GAP_INVALID_ACTV_IDX 0xFF +/// Invalid connection index +#define GAP_INVALID_CONIDX 0xFF + +/// Invalid connection handle +#define GAP_INVALID_CONHDL 0xFFFF + +/// Connection interval min (N*1.250ms) +#define GAP_CNX_INTERVAL_MIN 6 //(0x06) +/// Connection interval Max (N*1.250ms) +#define GAP_CNX_INTERVAL_MAX 3200 //(0xC80) +/// Connection latency min (N*cnx evt) +#define GAP_CNX_LATENCY_MIN 0 //(0x00) +/// Connection latency Max (N*cnx evt +#define GAP_CNX_LATENCY_MAX 499 //(0x1F3) +/// Supervision TO min (N*10ms) +#define GAP_CNX_SUP_TO_MIN 10 //(0x0A) +/// Supervision TO Max (N*10ms) +#define GAP_CNX_SUP_TO_MAX 3200 //(0xC80) + + + +/// Length of resolvable random address prand part +#define GAP_ADDR_PRAND_LEN (3) +/// Length of resolvable random address hash part +#define GAP_ADDR_HASH_LEN (3) + +/// Number of bytes needed for a bit field indicated presence of a given Advertising Flag value +/// in the Advertising or the Scan Response data +/// Advertising Flags is a 8-bit value, hence 256 value are possible +/// -> 256 / 8 bytes = 32 bytes are needed +#define GAP_AD_TYPE_BITFIELD_BYTES (32) + +/* + * DEFINES - Optional for BLE application usage + **************************************************************************************** + */ + +/// Central idle timer +/// TGAP(conn_pause_central) +/// recommended value: 1 s: (100 for ke timer) +#define GAP_TMR_CONN_PAUSE_CT 0x0064 + +/// Minimum time upon connection establishment before the peripheral +/// starts a connection update procedure: TGAP(conn_pause_peripheral) +/// recommended value: 5 s: (500 for ke timer) +#define GAP_TMR_CONN_PAUSE_PH 0x01F4 + +/// Minimum time to perform scanning when user initiated +/// TGAP(scan_fast_period) +/// recommended value: 30.72 s: (3072 for ke timer) +#define GAP_TMR_SCAN_FAST_PERIOD 0x0C00 + +/// Minimum time to perform advertising when user initiated +/// TGAP(adv_fast_period) +/// recommended value: 30 s: (3000 for ke timer) +#define GAP_TMR_ADV_FAST_PERIOD 0x0BB8 + +/// Scan interval used during Link Layer Scanning State when +/// performing the Limited Discovery procedure +/// TGAP(lim_disc_scan_int) +/// recommended value: 11.25ms; (18 decimal) +#define GAP_LIM_DISC_SCAN_INT 0x0012 + +/// Scan interval in any discovery or connection establishment +/// procedure when user initiated: TGAP(scan_fast_interval) +/// recommended value: 30 to 60 ms; N * 0.625 +#define GAP_SCAN_FAST_INTV 0x0030 + +/// Scan window in any discovery or connection establishment +/// procedure when user initiated: TGAP(scan_fast_window) +/// recommended value: 30 ms; N * 0.625 +#define GAP_SCAN_FAST_WIND 0x0030 + +/// Scan interval in any discovery or connection establishment +/// procedure when background scanning: TGAP(scan_slow_interval1) +/// recommended value: 1.28 s : 0x00CD (205); N * 0.625 +#define GAP_SCAN_SLOW_INTV1 0x00CD + +/// Scan interval in any discovery or connection establishment +/// procedure when background scanning: TGAP(scan_slow_interval2) +/// recommended value: 2.56 s : 0x019A (410); N * 0.625 +#define GAP_SCAN_SLOW_INTV2 0x019A + +/// Scan window in any discovery or connection establishment +/// procedure when background scanning: TGAP(scan_slow_window1) +/// recommended value: 11.25 ms : 0x0012 (18); N * 0.625 +#define GAP_SCAN_SLOW_WIND1 0x0012 + +/// Scan window in any discovery or connection establishment +/// procedure when background scanning: TGAP(scan_slow_window2) +/// recommended value: 22.5 ms : 0x0024 (36); N * 0.625 +#define GAP_SCAN_SLOW_WIND2 0x0024 + +/// Minimum to maximum advertisement interval in any discoverable +/// or connectable mode when user initiated: TGAP(adv_fast_interval1) +/// recommended value: 30 to 60 ms; N * 0.625 +#define GAP_ADV_FAST_INTV1 0x0030 + +/// Minimum to maximum advertisement interval in any discoverable +/// or connectable mode when user initiated: TGAP(adv_fast_interval2) +/// recommended value: 100 to 150 ms; N * 0.625 +#define GAP_ADV_FAST_INTV2 0x0064 + +/// Minimum to maximum advertisement interval in any discoverable or +/// connectable mode when background advertising: TGAP(adv_slow_interval) +/// recommended value: 1 to 1.2 s : 0x00B0 (176); N * 0.625 +#define GAP_ADV_SLOW_INTV 0x00B0 + +/// Minimum to maximum connection interval upon any connection +/// establishment: TGAP(initial_conn_interval) +/// recommended value: 30 to 50 ms ; N * 1.25 ms +#define GAP_INIT_CONN_MIN_INTV 0x0018 +#define GAP_INIT_CONN_MAX_INTV 0x0028 + +/// RW Defines +#define GAP_INQ_SCAN_INTV 0x0012 +#define GAP_INQ_SCAN_WIND 0x0012 + +/// Connection supervision timeout +/// recommended value: 20s +#define GAP_CONN_SUPERV_TIMEOUT 0x07D0 + +/// Minimum connection event +/// default value: 0x0000 +#define GAP_CONN_MIN_CE 0x0000 + +/// Maximum connection event +/// default value: 0xFFFF +#define GAP_CONN_MAX_CE 0xFFFF + +/// Connection latency +/// default value: 0x0000 +#define GAP_CONN_LATENCY 0x0000 + +/// GAP Device name Characteristic +/// Default device name +#define GAP_DEV_NAME "RIVIERAWAVES-BLE" + +/// GAP Appearance or Icon Characteristic - 2 octets +/// Current appearance value is 0x0000 (unknown appearance) +/// Description: +/// http://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.gap.appearance.xml +#define GAP_APPEARANCE 0x0000 + +///GAP Peripheral Preferred Connection Parameter - 8 octets +#define GAP_PPCP_CONN_INTV_MAX 0x0064 +#define GAP_PPCP_CONN_INTV_MIN 0x00C8 +#define GAP_PPCP_SLAVE_LATENCY 0x0000 +#define GAP_PPCP_STO_MULT 0x07D0 + +/* + * Macros + **************************************************************************************** + */ + +#define GAP_AD_TYPE_SET_BIT(bitfield, adv_flag) \ + bitfield[adv_flag / 8] |= COMMON_BIT(adv_flag % 8) + +#define GAP_AD_TYPE_CHECK_BIT(bitfield, adv_flag) \ + (bitfield[adv_flag / 8] & COMMON_BIT(adv_flag % 8)) + +/* + * Enumerations + **************************************************************************************** + */ +/// GAP Advertising Flags +enum gap_ad_type +{ + /// Flag + GAP_AD_TYPE_FLAGS = 0x01,//!< GAP_AD_TYPE_FLAGS + /// Use of more than 16 bits UUID + GAP_AD_TYPE_MORE_16_BIT_UUID = 0x02,//!< GAP_AD_TYPE_MORE_16_BIT_UUID + /// Complete list of 16 bit UUID + GAP_AD_TYPE_COMPLETE_LIST_16_BIT_UUID = 0x03,//!< GAP_AD_TYPE_COMPLETE_LIST_16_BIT_UUID + /// Use of more than 32 bit UUD + GAP_AD_TYPE_MORE_32_BIT_UUID = 0x04,//!< GAP_AD_TYPE_MORE_32_BIT_UUID + /// Complete list of 32 bit UUID + GAP_AD_TYPE_COMPLETE_LIST_32_BIT_UUID = 0x05,//!< GAP_AD_TYPE_COMPLETE_LIST_32_BIT_UUID + /// Use of more than 128 bit UUID + GAP_AD_TYPE_MORE_128_BIT_UUID = 0x06,//!< GAP_AD_TYPE_MORE_128_BIT_UUID + /// Complete list of 128 bit UUID + GAP_AD_TYPE_COMPLETE_LIST_128_BIT_UUID = 0x07,//!< GAP_AD_TYPE_COMPLETE_LIST_128_BIT_UUID + /// Shortened device name + GAP_AD_TYPE_SHORTENED_NAME = 0x08,//!< GAP_AD_TYPE_SHORTENED_NAME + /// Complete device name + GAP_AD_TYPE_COMPLETE_NAME = 0x09,//!< GAP_AD_TYPE_COMPLETE_NAME + /// Transmit power + GAP_AD_TYPE_TRANSMIT_POWER = 0x0A,//!< GAP_AD_TYPE_TRANSMIT_POWER + /// Class of device + GAP_AD_TYPE_CLASS_OF_DEVICE = 0x0D,//!< GAP_AD_TYPE_CLASS_OF_DEVICE + /// Simple Pairing Hash C + GAP_AD_TYPE_SP_HASH_C = 0x0E,//!< GAP_AD_TYPE_SP_HASH_C + /// Simple Pairing Randomizer + GAP_AD_TYPE_SP_RANDOMIZER_R = 0x0F,//!< GAP_AD_TYPE_SP_RANDOMIZER_R + /// Temporary key value + GAP_AD_TYPE_TK_VALUE = 0x10,//!< GAP_AD_TYPE_TK_VALUE + /// Out of Band Flag + GAP_AD_TYPE_OOB_FLAGS = 0x11,//!< GAP_AD_TYPE_OOB_FLAGS + /// Slave connection interval range + GAP_AD_TYPE_SLAVE_CONN_INT_RANGE = 0x12,//!< GAP_AD_TYPE_SLAVE_CONN_INT_RANGE + /// Require 16 bit service UUID + GAP_AD_TYPE_RQRD_16_BIT_SVC_UUID = 0x14,//!< GAP_AD_TYPE_RQRD_16_BIT_SVC_UUID + /// Require 32 bit service UUID + GAP_AD_TYPE_RQRD_32_BIT_SVC_UUID = 0x1F,//!< GAP_AD_TYPE_RQRD_32_BIT_SVC_UUID + /// Require 128 bit service UUID + GAP_AD_TYPE_RQRD_128_BIT_SVC_UUID = 0x15,//!< GAP_AD_TYPE_RQRD_128_BIT_SVC_UUID + /// Service data 16-bit UUID + GAP_AD_TYPE_SERVICE_16_BIT_DATA = 0x16,//!< GAP_AD_TYPE_SERVICE_16_BIT_DATA + /// Service data 32-bit UUID + GAP_AD_TYPE_SERVICE_32_BIT_DATA = 0x20,//!< GAP_AD_TYPE_SERVICE_32_BIT_DATA + /// Service data 128-bit UUID + GAP_AD_TYPE_SERVICE_128_BIT_DATA = 0x21,//!< GAP_AD_TYPE_SERVICE_128_BIT_DATA + /// Public Target Address + GAP_AD_TYPE_PUB_TGT_ADDR = 0x17,//!< GAP_AD_TYPE_PUB_TGT_ADDR + /// Random Target Address + GAP_AD_TYPE_RAND_TGT_ADDR = 0x18,//!< GAP_AD_TYPE_RAND_TGT_ADDR + /// Appearance + GAP_AD_TYPE_APPEARANCE = 0x19,//!< GAP_AD_TYPE_APPEARANCE + /// Advertising Interval + GAP_AD_TYPE_ADV_INTV = 0x1A,//!< GAP_AD_TYPE_ADV_INTV + /// LE Bluetooth Device Address + GAP_AD_TYPE_LE_BT_ADDR = 0x1B,//!< GAP_AD_TYPE_LE_BT_ADDR + /// LE Role + GAP_AD_TYPE_LE_ROLE = 0x1C,//!< GAP_AD_TYPE_LE_ROLE + /// Simple Pairing Hash C-256 + GAP_AD_TYPE_SPAIR_HASH = 0x1D,//!< GAP_AD_TYPE_SPAIR_HASH + /// Simple Pairing Randomizer R-256 + GAP_AD_TYPE_SPAIR_RAND = 0x1E,//!< GAP_AD_TYPE_SPAIR_RAND + /// 3D Information Data + GAP_AD_TYPE_3D_INFO = 0x3D,//!< GAP_AD_TYPE_3D_INFO + + /// Manufacturer specific data + GAP_AD_TYPE_MANU_SPECIFIC_DATA = 0xFF,//!< GAP_AD_TYPE_MANU_SPECIFIC_DATA +}; + +/// Boolean value set +enum +{ + /// Disable + GAP_DISABLE = 0x00, + /// Enable + GAP_ENABLE +}; + + +/// GAP Attribute database handles +/// Generic Access Profile Service +enum +{ + GAP_IDX_PRIM_SVC, + GAP_IDX_CHAR_DEVNAME, + GAP_IDX_DEVNAME, + GAP_IDX_CHAR_ICON, + GAP_IDX_ICON, + GAP_IDX_CHAR_SLAVE_PREF_PARAM, + GAP_IDX_SLAVE_PREF_PARAM, + GAP_IDX_CHAR_CNT_ADDR_RESOL, + GAP_IDX_CNT_ADDR_RESOL, + GAP_IDX_CHAR_RSLV_PRIV_ADDR_ONLY, + GAP_IDX_RSLV_PRIV_ADDR_ONLY, + GAP_IDX_NUMBER +}; + + + +/****************** GAP Role **********************/ +enum gap_role +{ + /// No role set yet + GAP_ROLE_NONE = 0x00, + + /// Observer role + GAP_ROLE_OBSERVER = 0x01, + + /// Broadcaster role + GAP_ROLE_BROADCASTER = 0x02, + + /// Master/Central role + GAP_ROLE_CENTRAL = (0x04 | GAP_ROLE_OBSERVER), + + /// Peripheral/Slave role + GAP_ROLE_PERIPHERAL = (0x08 | GAP_ROLE_BROADCASTER), + + /// Device has all role, both peripheral and central + GAP_ROLE_ALL = (GAP_ROLE_CENTRAL | GAP_ROLE_PERIPHERAL), +}; + +/// IO Capability Values +enum gap_io_cap +{ + /// Display Only + GAP_IO_CAP_DISPLAY_ONLY = 0x00, + /// Display Yes No + GAP_IO_CAP_DISPLAY_YES_NO, + /// Keyboard Only + GAP_IO_CAP_KB_ONLY, + /// No Input No Output + GAP_IO_CAP_NO_INPUT_NO_OUTPUT, + /// Keyboard Display + GAP_IO_CAP_KB_DISPLAY, + GAP_IO_CAP_LAST +}; + +/// TK Type +enum gap_tk_type +{ + /// TK get from out of band method + GAP_TK_OOB = 0x00, + /// TK generated and shall be displayed by local device + GAP_TK_DISPLAY, + /// TK shall be entered by user using device keyboard + GAP_TK_KEY_ENTRY +}; + +/// OOB Data Present Flag Values +enum gap_oob +{ + /// OOB Data not present + GAP_OOB_AUTH_DATA_NOT_PRESENT = 0x00, + /// OOB data present + GAP_OOB_AUTH_DATA_PRESENT, + GAP_OOB_AUTH_DATA_LAST +}; + +/// Authentication mask +enum gap_auth_mask +{ + /// No Flag set + GAP_AUTH_NONE = 0, + /// Bond authentication + GAP_AUTH_BOND = (1 << 0), + /// Man In the middle protection + GAP_AUTH_MITM = (1 << 2), + /// Secure Connection + GAP_AUTH_SEC_CON = (1 << 3), + /// Key Notification + GAP_AUTH_KEY_NOTIF = (1 << 4) +}; + +/// Security Link Level +enum gap_lk_sec_lvl +{ + /// No authentication + GAP_LK_NO_AUTH = 0, + /// Unauthenticated link + GAP_LK_UNAUTH, + /// Authenticated link + GAP_LK_AUTH, + /// Secure Connection link + GAP_LK_SEC_CON, +}; + +/// Authentication Requirements +enum gap_auth +{ + /// No MITM No Bonding + GAP_AUTH_REQ_NO_MITM_NO_BOND = (GAP_AUTH_NONE), + /// No MITM Bonding + GAP_AUTH_REQ_NO_MITM_BOND = (GAP_AUTH_BOND), + /// MITM No Bonding + GAP_AUTH_REQ_MITM_NO_BOND = (GAP_AUTH_MITM), + /// MITM and Bonding + GAP_AUTH_REQ_MITM_BOND = (GAP_AUTH_MITM | GAP_AUTH_BOND), + /// SEC_CON and No Bonding + GAP_AUTH_REQ_SEC_CON_NO_BOND = (GAP_AUTH_SEC_CON | GAP_AUTH_MITM), + /// SEC_CON and Bonding + GAP_AUTH_REQ_SEC_CON_BOND = (GAP_AUTH_SEC_CON | GAP_AUTH_MITM | GAP_AUTH_BOND), + + GAP_AUTH_REQ_LAST, + + /// Mask of authentication features without reserved flag + GAP_AUTH_REQ_MASK = 0x1F, +}; + +/// Key Distribution Flags +enum gap_kdist +{ + /// No Keys to distribute + GAP_KDIST_NONE = 0x00, + /// Encryption key in distribution + GAP_KDIST_ENCKEY = (1 << 0), + /// IRK (ID key)in distribution + GAP_KDIST_IDKEY = (1 << 1), + /// CSRK(Signature key) in distribution + GAP_KDIST_SIGNKEY= (1 << 2), + /// LTK in distribution + GAP_KDIST_LINKKEY= (1 << 3), + + GAP_KDIST_LAST = (1 << 4) +}; + +/// Security Defines +enum gap_sec_req +{ + /// No security (no authentication and encryption) + GAP_NO_SEC = 0x00, + /// Unauthenticated pairing with encryption + GAP_SEC1_NOAUTH_PAIR_ENC, + /// Authenticated pairing with encryption + GAP_SEC1_AUTH_PAIR_ENC, + /// Unauthenticated pairing with data signing + GAP_SEC2_NOAUTH_DATA_SGN, + /// Authentication pairing with data signing + GAP_SEC2_AUTH_DATA_SGN, + /// Secure Connection pairing with encryption + GAP_SEC1_SEC_CON_PAIR_ENC, +}; + +/// Bit field use to select the preferred TX or RX LE PHY. 0 means no preferences +enum gap_phy +{ + /// No preferred PHY + GAP_PHY_ANY = 0x00, + /// LE 1M PHY preferred for an active link + GAP_PHY_LE_1MBPS = (1 << 0), + /// LE 2M PHY preferred for an active link + GAP_PHY_LE_2MBPS = (1 << 1), + /// LE Coded PHY preferred for an active link + GAP_PHY_LE_CODED = (1 << 2), +}; + +/// Enumeration of TX/RX PHY values +enum gap_phy_val +{ + /// LE 1M PHY (TX or RX) + GAP_PHY_1MBPS = 1, + /// LE 2M PHY (TX or RX) + GAP_PHY_2MBPS = 2, + /// LE Coded PHY (RX Only) + GAP_PHY_CODED = 3, + /// LE Coded PHY with S=8 data coding (TX Only) + GAP_PHY_125KBPS = 3, + /// LE Coded PHY with S=2 data coding (TX Only) + GAP_PHY_500KBPS = 4, +}; + +/// Modulation index +enum gap_modulation_idx +{ + /// Assume transmitter will have a standard modulation index + GAP_MODULATION_STANDARD, + /// Assume transmitter will have a stable modulation index + GAP_MODULATION_STABLE, +}; + +/// Packet Payload type for test mode +enum gap_pkt_pld_type +{ + /// PRBS9 sequence "11111111100000111101..." (in transmission order) + GAP_PKT_PLD_PRBS9, + /// Repeated "11110000" (in transmission order) + GAP_PKT_PLD_REPEATED_11110000, + /// Repeated "10101010" (in transmission order) + GAP_PKT_PLD_REPEATED_10101010, + /// PRBS15 sequence + GAP_PKT_PLD_PRBS15, + /// Repeated "11111111" (in transmission order) sequence + GAP_PKT_PLD_REPEATED_11111111, + /// Repeated "00000000" (in transmission order) sequence + GAP_PKT_PLD_REPEATED_00000000, + /// Repeated "00001111" (in transmission order) sequence + GAP_PKT_PLD_REPEATED_00001111, + /// Repeated "01010101" (in transmission order) sequence + GAP_PKT_PLD_REPEATED_01010101, +}; + +/// Constant Tone Extension type +enum gap_cte_type +{ + /// Allow AoA Constant Tone Extension Response + GAP_CTE_AOA = (1 << 0), + /// Allow AoD Constant Tone Extension Response with 1 us slots + GAP_CTE_AOD_1US_SLOT = (1 << 1), + /// Allow AoD Constant Tone Extension Response with 2 us slots + GAP_CTE_AOD_2US_SLOT = (1 << 2), +}; + +/*************** GAP Structures ********************/ + +/// Device name +/*@TRACE*/ +struct gap_dev_name +{ + /// name length + uint16_t length; + /// name value + uint8_t value[__ARRAY_EMPTY]; +}; + +/// Slave preferred connection parameters +/*@TRACE*/ +struct gap_slv_pref +{ + /// Connection interval minimum + uint16_t con_intv_min; + /// Connection interval maximum + uint16_t con_intv_max; + /// Slave latency + uint16_t slave_latency; + /// Connection supervision timeout multiplier + uint16_t conn_timeout; +}; + +///BD Address structure +/*@TRACE*/ +typedef struct +{ + ///6-byte array address value + uint8_t addr[GAP_BD_ADDR_LEN]; +} bd_addr_t; + +///Channel map structure +/*@TRACE*/ +typedef struct +{ + ///5-byte channel map array + uint8_t map[GAP_LE_CHNL_MAP_LEN]; +} le_chnl_map_t; + + +///Random number structure +/*@TRACE*/ +typedef struct +{ + ///8-byte array for random number + uint8_t nb[GAP_RAND_NB_LEN]; +} rand_nb_t; + +/// P256 Public key data format +typedef struct +{ + /// X Coordinate of the key + uint8_t x[GAP_P256_KEY_LEN]; + /// X Coordinate of the key + uint8_t y[GAP_P256_KEY_LEN]; +} public_key_t; + +/// Address information about a device address +/*@TRACE*/ +struct gap_bdaddr +{ + /// BD Address of device + bd_addr_t addr; + /// Address type of the device 0=public/1=private random + uint8_t addr_type; +}; + +/// Resolving list device information +/*@TRACE*/ +struct gap_ral_dev_info +{ + /// Device identity + struct gap_bdaddr addr; + /// Privacy Mode + uint8_t priv_mode; + /// Peer IRK + uint8_t peer_irk[GAP_KEY_LEN]; + /// Local IRK + uint8_t local_irk[GAP_KEY_LEN]; +}; + +/// Generic Security key structure +/*@TRACE*/ +struct gap_sec_key +{ + /// Key value MSB -> LSB + uint8_t key[GAP_KEY_LEN]; +}; + +/// I/Q sample +/*@TRACE*/ +struct gap_iq_sample +{ + /// I sample + uint8_t i; + /// Q sample + uint8_t q; +}; +/// @} GAP +#endif // GAP_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/api/gapc_task.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/api/gapc_task.h new file mode 100755 index 0000000..b47beef --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/api/gapc_task.h @@ -0,0 +1,1279 @@ +/** + **************************************************************************************** + * + * @file gapc_task.h + * + * @brief Generic Access Profile Controller Task Header. + * + * Copyright (C) RivieraWaves 2009-2016 + * + **************************************************************************************** + */ +#ifndef _GAPC_TASK_H_ +#define _GAPC_TASK_H_ + +/** + **************************************************************************************** + * @addtogroup GAPC_TASK Generic Access Profile Controller Task + * @ingroup GAPC + * @brief Handles ALL messages to/from GAP Controller block. + * + * It handles messages from lower and higher layers related to an ongoing connection. + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_task.h" // Task definitions +#include "gap.h" +#include +#include "kernel_msg.h" + +/* + * MACROS + **************************************************************************************** + */ + +/* + * DEFINES + **************************************************************************************** + */ + + +/// GAP Controller Task messages +/*@TRACE*/ +enum gapc_msg_id +{ + /* Default event */ + /// Command Complete event + GAPC_CMP_EVT = MSG_ID(GAPC, 0x00), + + /* Connection state information */ + /// Indicate that a connection has been established + GAPC_CONNECTION_REQ_IND = MSG_ID(GAPC, 0x01), + /// Set specific link data configuration. + GAPC_CONNECTION_CFM = MSG_ID(GAPC, 0x02), + + /// Indicate that a link has been disconnected + GAPC_DISCONNECT_IND = MSG_ID(GAPC, 0x03), + + /* Link management command */ + /// Request disconnection of current link command. + GAPC_DISCONNECT_CMD = MSG_ID(GAPC, 0x04), + + /* Peer device info */ + /// Retrieve information command + GAPC_GET_INFO_CMD = MSG_ID(GAPC, 0x05), + /// Peer device attribute DB info such as Device Name, Appearance or Slave Preferred Parameters + GAPC_PEER_ATT_INFO_IND = MSG_ID(GAPC, 0x06), + /// Indication of peer version info + GAPC_PEER_VERSION_IND = MSG_ID(GAPC, 0x07), + /// Indication of peer features info + GAPC_PEER_FEATURES_IND = MSG_ID(GAPC, 0x08), + /// Indication of ongoing connection RSSI + GAPC_CON_RSSI_IND = MSG_ID(GAPC, 0x09), + + /* Device Name Management */ + /// Peer device request local device info such as name, appearance or slave preferred parameters + GAPC_GET_DEV_INFO_REQ_IND = MSG_ID(GAPC, 0x0A), + /// Send requested info to peer device + GAPC_GET_DEV_INFO_CFM = MSG_ID(GAPC, 0x0B), + /// Peer device request to modify local device info such as name or appearance + GAPC_SET_DEV_INFO_REQ_IND = MSG_ID(GAPC, 0x0C), + /// Local device accept or reject device info modification + GAPC_SET_DEV_INFO_CFM = MSG_ID(GAPC, 0x0D), + + /* Connection parameters update */ + /// Perform update of connection parameters command + GAPC_PARAM_UPDATE_CMD = MSG_ID(GAPC, 0x0E), + /// Request of updating connection parameters indication + GAPC_PARAM_UPDATE_REQ_IND = MSG_ID(GAPC, 0x0F), + /// Master confirm or not that parameters proposed by slave are accepted or not + GAPC_PARAM_UPDATE_CFM = MSG_ID(GAPC, 0x10), + /// Connection parameters updated indication + GAPC_PARAM_UPDATED_IND = MSG_ID(GAPC, 0x11), + + /* Bonding procedure */ + /// Start Bonding command procedure + GAPC_BOND_CMD = MSG_ID(GAPC, 0x12), + /// Bonding requested by peer device indication message. + GAPC_BOND_REQ_IND = MSG_ID(GAPC, 0x13), + /// Confirm requested bond information. + GAPC_BOND_CFM = MSG_ID(GAPC, 0x14), + /// Bonding information indication message + GAPC_BOND_IND = MSG_ID(GAPC, 0x15), + + /* Encryption procedure */ + /// Start Encryption command procedure + GAPC_ENCRYPT_CMD = MSG_ID(GAPC, 0x16), + /// Encryption requested by peer device indication message. + GAPC_ENCRYPT_REQ_IND = MSG_ID(GAPC, 0x17), + /// Confirm requested Encryption information. + GAPC_ENCRYPT_CFM = MSG_ID(GAPC, 0x18), + /// Encryption information indication message + GAPC_ENCRYPT_IND = MSG_ID(GAPC, 0x19), + + /* Security request procedure */ + /// Start Security Request command procedure + GAPC_SECURITY_CMD = MSG_ID(GAPC, 0x1A), + /// Security requested by peer device indication message + GAPC_SECURITY_IND = MSG_ID(GAPC, 0x1B), + + /* Signature procedure */ + /// Indicate the current sign counters to the application + GAPC_SIGN_COUNTER_IND = MSG_ID(GAPC, 0x1C), + + /* Device information */ + /// Indication of ongoing connection Channel Map + GAPC_CON_CHANNEL_MAP_IND = MSG_ID(GAPC, 0x1D), + + /* LE Ping */ + /// Update LE Ping timeout value + GAPC_SET_LE_PING_TO_CMD = MSG_ID(GAPC, 0x28), + /// LE Ping timeout indication + GAPC_LE_PING_TO_VAL_IND = MSG_ID(GAPC, 0x29), + /// LE Ping timeout expires indication + GAPC_LE_PING_TO_IND = MSG_ID(GAPC, 0x2A), + + /* LE Data Length extension*/ + /// LE Set Data Length Command + GAPC_SET_LE_PKT_SIZE_CMD = MSG_ID(GAPC, 0x2B), + /// LE Set Data Length Indication + GAPC_LE_PKT_SIZE_IND = MSG_ID(GAPC, 0x2C), + + /* Secure Connections */ + /// Request to inform the remote device when keys have been entered or erased + GAPC_KEY_PRESS_NOTIFICATION_CMD = MSG_ID(GAPC, 0x2D), + /// Indication that a KeyPress has been performed on the peer device. + GAPC_KEY_PRESS_NOTIFICATION_IND = MSG_ID(GAPC, 0x2E), + + /* PHY Management */ + /// Set the PHY configuration for current active link + GAPC_SET_PHY_CMD = MSG_ID(GAPC, 0x2F), + /// Active link PHY configuration. Triggered when configuration is read or during an update. + GAPC_LE_PHY_IND = MSG_ID(GAPC, 0x30), + + /* Channel Selection Algorithm */ + /// Indication of currently used channel selection algorithm + /// @see struct gapc_chan_sel_algo_ind + GAPC_CHAN_SEL_ALGO_IND = MSG_ID(GAPC, 0x31), + + /* Preferred Slave Latency */ + /// Set the preferred slave latency (for slave only, with RW controller) + GAPC_SET_PREF_SLAVE_LATENCY_CMD = MSG_ID(GAPC, 0x32), + /// Set the preferred slave event duration (for slave only, with RW controller) + GAPC_SET_PREF_SLAVE_EVT_DUR_CMD = MSG_ID(GAPC, 0x33), + + /// Indication to the task that sends the unknown message + GAPC_UNKNOWN_MSG_IND = MSG_ID(GAPC, 0x34), + + /* Periodic Sync Transfer */ + /// Transfer periodic advertising sync information to peer device + GAPC_PER_ADV_SYNC_TRANS_CMD = MSG_ID(GAPC, 0x35), + + /* Constant Tone Extension */ + /// Constant Tone Extension Transmission configuration command + GAPC_CTE_TX_CFG_CMD = MSG_ID(GAPC, 0x38), + /// Constant Tone Extension Reception configuration command + GAPC_CTE_RX_CFG_CMD = MSG_ID(GAPC, 0x39), + /// Constant Tone Extension request control command (enable / disable) + GAPC_CTE_REQ_CTRL_CMD = MSG_ID(GAPC, 0x3A), + /// Constant Tone Extension Response control command (enable / disable) + GAPC_CTE_RSP_CTRL_CMD = MSG_ID(GAPC, 0x3B), + /// Indicate reception of a IQ Report event over a ble connection + GAPC_CTE_IQ_REPORT_IND = MSG_ID(GAPC, 0x3C), + + // ---------------------- INTERNAL API ------------------------ + /* Internal messages for timer events, not part of API*/ + /// Signature procedure + GAPC_SIGN_CMD = MSG_ID(GAPC, 0xF0), + /// Signature result + GAPC_SIGN_IND = MSG_ID(GAPC, 0xF1), + + /// Parameter update procedure timeout indication + GAPC_PARAM_UPDATE_TO_IND = MSG_ID(GAPC, 0xF2), + /// Pairing procedure timeout indication + GAPC_SMP_TIMEOUT_TIMER_IND = MSG_ID(GAPC, 0xF3), + /// Pairing repeated attempts procedure timeout indication + GAPC_SMP_REP_ATTEMPTS_TIMER_IND = MSG_ID(GAPC, 0xF4), +}; + + + + +/// request operation type - application interface +/*@TRACE*/ +enum gapc_operation +{ + /* Operation Flags */ + /* No Operation (if nothing has been requested) */ + /* ************************************************ */ + /// No operation + GAPC_NO_OP = 0x00, + + /* Connection management */ + /// Disconnect link + GAPC_DISCONNECT = 0x01, + + /* Connection information */ + /// Retrieve name of peer device. + GAPC_GET_PEER_NAME = 0x02, + /// Retrieve peer device version info. + GAPC_GET_PEER_VERSION = 0x03, + /// Retrieve peer device features. + GAPC_GET_PEER_FEATURES = 0x04, + /// Get Peer device appearance + GAPC_GET_PEER_APPEARANCE = 0x05, + /// Get Peer device Slaved Preferred Parameters + GAPC_GET_PEER_SLV_PREF_PARAMS = 0x06, + /// Retrieve connection RSSI. + GAPC_GET_CON_RSSI = 0x07, + /// Retrieve Connection Channel MAP. + GAPC_GET_CON_CHANNEL_MAP = 0x08, + + /* Connection parameters update */ + /// Perform update of connection parameters. + GAPC_UPDATE_PARAMS = 0x09, + + /* Security procedures */ + /// Start bonding procedure. + GAPC_BOND = 0x0A, + /// Start encryption procedure. + GAPC_ENCRYPT = 0x0B, + /// Start security request procedure + GAPC_SECURITY_REQ = 0x0C, + + /* LE Ping*/ + /// get timer timeout value + GAPC_GET_LE_PING_TO = 0x12, + /// set timer timeout value + GAPC_SET_LE_PING_TO = 0x13, + + /* LE Data Length extension*/ + /// LE Set Data Length + GAPC_SET_LE_PKT_SIZE = 0x14, + + /* Central Address resolution supported*/ + GAPC_GET_ADDR_RESOL_SUPP = 0x15, + + /* Secure Connections */ + /// Request to inform the remote device when keys have been entered or erased + GAPC_KEY_PRESS_NOTIFICATION = 0x16, + + /* PHY Management */ + /// Set the PHY configuration for current active link + GAPC_SET_PHY = 0x17, + /// Retrieve PHY configuration of active link + GAPC_GET_PHY = 0x18, + + /* Channel Selection Algorithm */ + /// Retrieve Channel Selection Algorithm + GAPC_GET_CHAN_SEL_ALGO = 0x19, + + /* Preferred slave latency */ + /// Set the preferred slave latency (for slave only, with RW controller) + GAPC_SET_PREF_SLAVE_LATENCY = 0x1A, + /// Set the preferred slave event duration (for slave only, with RW controller) + GAPC_SET_PREF_SLAVE_EVT_DUR = 0x1B, + + /* Periodic Sync Transfer */ + /// Transfer periodic advertising sync information to peer device + GAPC_PER_ADV_SYNC_TRANS = 0x1C, + + /* Constant Tone Extension */ + /// Constant Tone Extension Transmission configuration + GAPC_CTE_TX_CFG = 0x20, + /// Constant Tone Extension Reception configuration + GAPC_CTE_RX_CFG = 0x21, + /// Constant Tone Extension request control (enable / disable) + GAPC_CTE_REQ_CTRL = 0x22, + /// Constant Tone Extension Response control (enable / disable) + GAPC_CTE_RSP_CTRL = 0x23, + + // ---------------------- INTERNAL API ------------------------ + /* Packet signature */ + /// sign an attribute packet + GAPC_SIGN_PACKET = 0xF0, + /// Verify signature or an attribute packet + GAPC_SIGN_CHECK = 0xF1, +}; + +/// Bond event type. +/*@TRACE*/ +enum gapc_bond +{ + /// Bond Pairing request + GAPC_PAIRING_REQ, + /// Respond to Pairing request + GAPC_PAIRING_RSP, + + /// Pairing Finished information + GAPC_PAIRING_SUCCEED, + /// Pairing Failed information + GAPC_PAIRING_FAILED, + + /// Used to retrieve pairing Temporary Key + GAPC_TK_EXCH, + /// Used for Identity Resolving Key exchange + GAPC_IRK_EXCH, + /// Used for Connection Signature Resolving Key exchange + GAPC_CSRK_EXCH, + /// Used for Long Term Key exchange + GAPC_LTK_EXCH, + + /// Bond Pairing request issue, Repeated attempt + GAPC_REPEATED_ATTEMPT, + + /// Out of Band - exchange of confirm and rand. + GAPC_OOB_EXCH, + + /// Numeric Comparison - Exchange of Numeric Value - + GAPC_NC_EXCH +}; + +/// List of device info that should be provided by application +/*@TRACE*/ +enum gapc_dev_info +{ + /// Device Name + GAPC_DEV_NAME, + /// Device Appearance Icon + GAPC_DEV_APPEARANCE, + /// Device Slave preferred parameters + GAPC_DEV_SLV_PREF_PARAMS, + /// Device Central address resolution + GAPC_DEV_CTL_ADDR_RESOL, + /// maximum device info parameter + GAPC_DEV_INFO_MAX, +}; + +/// List of features available on a device +enum gapc_features_list +{ + /// LE encryption + GAPC_ENCRYPT_FEAT_MASK = (1 << 0), + /// Connection Parameters Request Procedure + GAPC_CONN_PARAM_REQ_FEAT_MASK = (1 << 1), + /// Extended Reject Indication + GAPC_EXT_REJECT_IND_FEAT_MASK = (1 << 2), + /// Slave-initiated Features Exchange + GAPC_SLAVE_FEAT_EXCH_FEAT_MASK = (1 << 3), + /// LE ping + GAPC_LE_PING_FEAT_MASK = (1 << 4) +}; + +/// Option for PHY configuration +enum gapc_phy_option +{ + /// No preference for rate used when transmitting on the LE Coded PHY + GAPC_PHY_OPT_LE_CODED_ALL_RATES = (1 << 0), + /// 500kbps rate preferred when transmitting on the LE Coded PHY + GAPC_PHY_OPT_LE_CODED_500K_RATE = (1 << 1), + /// 125kbps when transmitting on the LE Coded PHY + GAPC_PHY_OPT_LE_CODED_125K_RATE = (1 << 2), +}; + +/// Keypress Notification types +enum gapc_key_ntf_type +{ + /// Passkey entry started + GAPC_KEY_NTF_ENTRY_STARTED = 0x00, + /// Passkey digit entered + GAPC_KEY_NTF_DIGIT_ENTERED, + /// Passkey digit erased + GAPC_KEY_NTF_DIGIT_ERASED, + /// Passkey cleared + GAPC_KEY_NTF_CLEARED, + /// Passkey entry completed + GAPC_KEY_NTF_ENTRY_COMPLETED +}; + +/// Client bond information +enum gapc_cli_info +{ + /// Service changed indication enabled + GAPC_SVC_CHANGED_IND_EN_BIT = (1 << 0), + GAPC_SVC_CHANGED_IND_EN_POS = 0, + /// Database updated since last connection + GAPC_DB_UPDATED_BIT = (1 << 1), + GAPC_DB_UPDATED_POS = 1, +}; + +/// Client supported features +enum gapc_cli_feat +{ + /// Robust Cache feature enabled + GAPC_ROBUST_CACHE_EN_BIT = (1 << 0), + GAPC_ROBUST_CACHE_EN_POS = 0, +}; + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + +/// Operation command structure in order to keep requested operation. +struct gapc_operation_cmd +{ + /// GAP request type + uint8_t operation; +}; + + +/// Command complete event data structure +/*@TRACE*/ +struct gapc_cmp_evt +{ + /// GAP request type + uint8_t operation; + /// Status of the request + uint8_t status; +}; + +/// Indicate that an unknown message has been received +/*@TRACE*/ +struct gapc_unknown_msg_ind +{ + /// Unknown message id + kernel_msg_id_t unknown_msg_id; +}; + +/// Indicate that a connection has been established +/*@TRACE*/ +struct gapc_connection_req_ind +{ + /// Connection handle + uint16_t conhdl; + /// Connection interval + uint16_t con_interval; + /// Connection latency + uint16_t con_latency; + /// Link supervision timeout + uint16_t sup_to; + /// Clock accuracy + uint8_t clk_accuracy; + /// Peer address type + uint8_t peer_addr_type; + /// Peer BT address + bd_addr_t peer_addr; + /// Role of device in connection (0 = Master / 1 = Slave) + uint8_t role; +}; + + +/// Set specific link data configuration. +/*@TRACE*/ +struct gapc_connection_cfm +{ + /// Local CSRK value + struct gap_sec_key lcsrk; + /// Local signature counter value + uint32_t lsign_counter; + /// Remote CSRK value + struct gap_sec_key rcsrk; + /// Remote signature counter value + uint32_t rsign_counter; + /// Authentication (@see enum gap_auth) + uint8_t auth; + /// Client bond data information (@see enum gapc_cli_info) + uint8_t cli_info; + /// LTK exchanged during pairing. + bool ltk_present; + /// Client supported features (@see enum gapc_cli_feat) + uint8_t cli_feat; + /// Peer GATT Service Start handle + uint16_t gatt_start_handle; + /// Peer GATT Service End Handle + uint16_t gatt_end_handle; + /// Peer Service Change value handle + uint16_t svc_chg_handle; +}; + +/// Request disconnection of current link command. +/*@TRACE*/ +struct gapc_disconnect_cmd +{ + /// GAP request type: + /// - GAPC_DISCONNECT: Disconnect link. + uint8_t operation; + + /// Reason of disconnection + uint8_t reason; +}; + + +/// Indicate that a link has been disconnected +/*@TRACE*/ +struct gapc_disconnect_ind +{ + /// Connection handle + uint16_t conhdl; + /// Reason of disconnection + uint8_t reason; +}; + + +/// Retrieve information command +/*@TRACE*/ +struct gapc_get_info_cmd +{ + /// GAP request type: + /// - GAPC_GET_PEER_NAME: Retrieve name of peer device. + /// - GAPC_GET_PEER_VERSION: Retrieve peer device version info. + /// - GAPC_GET_PEER_FEATURES: Retrieve peer device features. + /// - GAPC_GET_CON_RSSI: Retrieve connection RSSI. + /// - GAPC_GET_CON_CHANNEL_MAP: Retrieve Connection Channel MAP. + /// - GAPC_GET_PEER_APPEARANCE: Get Peer device appearance + /// - GAPC_GET_PEER_SLV_PREF_PARAMS: Get Peer device Slaved Preferred Parameters + /// - GAPC_GET_ADDR_RESOL_SUPP: Address Resolution Supported + /// - GAPC_GET_LE_PING_TIMEOUT: Retrieve LE Ping Timeout Value + uint8_t operation; +}; + +/// device information data +/*@TRACE + @trc_ref gapc_dev_info*/ +union gapc_dev_info_val +{ + /// Device name + //@trc_union parent.req == GAPC_DEV_NAME + struct gap_dev_name name; + /// Appearance Icon + //@trc_union parent.req == GAPC_DEV_APPEARANCE + uint16_t appearance; + /// Slave preferred parameters + //@trc_union parent.req == GAPC_DEV_SLV_PREF_PARAMS + struct gap_slv_pref slv_pref_params; + /// Central address resolution + //@trc_union parent.req == GAPC_DEV_CTL_ADDR_RESOL + uint8_t ctl_addr_resol; +}; + +/// Peer device attribute DB info such as Device Name, Appearance or Slave Preferred Parameters +/*@TRACE*/ +struct gapc_peer_att_info_ind +{ + /// Requested information + /// - GAPC_DEV_NAME: Device Name + /// - GAPC_DEV_APPEARANCE: Device Appearance Icon + /// - GAPC_DEV_SLV_PREF_PARAMS: Device Slave preferred parameters + /// - GAPC_GET_ADDR_RESOL_SUPP: Address resolution supported + uint8_t req; + /// Attribute handle + uint16_t handle; + + /// device information data + union gapc_dev_info_val info; +}; + +/// Indication of peer version info +/*@TRACE*/ +struct gapc_peer_version_ind +{ + /// Manufacturer name + uint16_t compid; + /// LMP subversion + uint16_t lmp_subvers; + /// LMP version + uint8_t lmp_vers; +}; + +/// Indication of peer features info +/*@TRACE*/ +struct gapc_peer_features_ind +{ + /// 8-byte array for LE features + uint8_t features[GAP_LE_FEATS_LEN]; +}; + +/// Indication of ongoing connection RSSI +/*@TRACE*/ +struct gapc_con_rssi_ind +{ + /// RSSI value + int8_t rssi; +}; + +/// Indication of ongoing connection Channel Map +/*@TRACE*/ +struct gapc_con_channel_map_ind +{ + /// channel map value + le_chnl_map_t ch_map; +}; + +/// Sign counter value changed due to packet signing or signature verification. +struct gapc_sign_counter_updated_ind +{ + /// New Local signature counter value + uint32_t lsign_counter; + /// New Remote signature counter value + uint32_t rsign_counter; +}; + +/// Indication of LE Ping +/*@TRACE*/ +struct gapc_le_ping_to_val_ind +{ + ///Authenticated payload timeout + uint16_t timeout; +}; + + +/// Peer device request local device info such as name, appearance or slave preferred parameters +/*@TRACE*/ +struct gapc_get_dev_info_req_ind +{ + /// Requested information + /// - GAPC_DEV_NAME: Device Name + /// - GAPC_DEV_APPEARANCE: Device Appearance Icon + /// - GAPC_DEV_SLV_PREF_PARAMS: Device Slave preferred parameters + uint8_t req; +}; + + + +/// Send requested info to peer device +/*@TRACE*/ +struct gapc_get_dev_info_cfm +{ + /// Requested information + /// - GAPC_DEV_NAME: Device Name + /// - GAPC_DEV_APPEARANCE: Device Appearance Icon + /// - GAPC_DEV_SLV_PREF_PARAMS: Device Slave preferred parameters + uint8_t req; + + /// Peer device information data + union gapc_dev_info_val info; +}; + +/// device information data +/*@TRACE + @trc_ref gapc_dev_info*/ +union gapc_set_dev_info +{ + /// Device name + //@trc_union parent.req == GAPC_DEV_NAME + struct gap_dev_name name; + /// Appearance Icon + //@trc_union parent.req == GAPC_DEV_APPEARANCE + uint16_t appearance; +}; + +/// Peer device request to modify local device info such as name or appearance +/*@TRACE*/ +struct gapc_set_dev_info_req_ind +{ + /// Requested information + /// - GAPC_DEV_NAME: Device Name + /// - GAPC_DEV_APPEARANCE: Device Appearance Icon + uint8_t req; + + /// device information data + union gapc_set_dev_info info; +}; + +/// Local device accept or reject device info modification +/*@TRACE*/ +struct gapc_set_dev_info_cfm +{ + /// Requested information + /// - GAPC_DEV_NAME: Device Name + /// - GAPC_DEV_APPEARANCE: Device Appearance Icon + uint8_t req; + + /// Status code used to know if requested has been accepted or not + uint8_t status; +}; + +/// Connection Parameter used to update connection parameters +struct gapc_conn_param +{ + /// Connection interval minimum + uint16_t intv_min; + /// Connection interval maximum + uint16_t intv_max; + /// Latency + uint16_t latency; + /// Supervision timeout + uint16_t time_out; +}; + +/// Perform update of connection parameters command +/*@TRACE*/ +struct gapc_param_update_cmd +{ + /// GAP request type: + /// - GAPC_UPDATE_PARAMS: Perform update of connection parameters. + uint8_t operation; + /// Internal parameter used to manage internally l2cap packet identifier for signaling + uint8_t pkt_id; + /// Connection interval minimum + uint16_t intv_min; + /// Connection interval maximum + uint16_t intv_max; + /// Latency + uint16_t latency; + /// Supervision timeout + uint16_t time_out; + /// Minimum Connection Event Duration + uint16_t ce_len_min; + /// Maximum Connection Event Duration + uint16_t ce_len_max; +}; + +/// Request of updating connection parameters indication +/*@TRACE*/ +struct gapc_param_update_req_ind +{ + /// Connection interval minimum + uint16_t intv_min; + /// Connection interval maximum + uint16_t intv_max; + /// Latency + uint16_t latency; + /// Supervision timeout + uint16_t time_out; +}; + +/// Connection parameters updated indication +/*@TRACE*/ +struct gapc_param_updated_ind +{ + ///Connection interval value + uint16_t con_interval; + ///Connection latency value + uint16_t con_latency; + ///Supervision timeout + uint16_t sup_to; +}; + +/// Master confirm or not that parameters proposed by slave are accepted or not +/*@TRACE*/ +struct gapc_param_update_cfm +{ + /// True to accept slave connection parameters, False else. + bool accept; + /// Minimum Connection Event Duration + uint16_t ce_len_min; + /// Maximum Connection Event Duration + uint16_t ce_len_max; +}; + +/// Parameters of the @ref GAPC_SET_PREF_SLAVE_LATENCY_CMD message +/*@TRACE*/ +struct gapc_set_pref_slave_latency_cmd +{ + /// GAP request type: + /// - GAPC_SET_PREF_SLAVE_LATENCY_CMD : Set preferred slave latency + uint8_t operation; + /// Preferred latency that the controller should use on a connection (in number of connection events) + uint16_t latency; +}; + +/// Parameters of the @ref GAPC_SET_PREF_SLAVE_EVT_DUR_CMD message +/*@TRACE*/ +struct gapc_set_pref_slave_evt_dur_cmd +{ + /// GAP request type: + /// - GAPC_SET_PREF_SLAVE_EVT_DUR_CMD : Set preferred slave event duration + uint8_t operation; + /// Preferred event duration that the controller should use on a connection (N * 0.625 ms) + uint16_t duration; + /// Slave transmits a single packet per connection event (False/True) + uint8_t single_tx; +}; + + +/// Parameters of the @ref GAPC_PER_ADV_SYNC_TRANS_CMD message +/*@TRACE*/ +struct gapc_per_adv_sync_trans_cmd +{ + /// GAP request type: + /// - GAPC_PER_ADV_SYNC_TRANS : Periodic Advertising Sync Transfer + uint8_t operation; + /// Periodic Advertising or Periodic Sync activity index + uint8_t actv_idx; + /// A value provided by application + uint16_t service_data; +}; + +/// Parameters of the @ref GAPC_CTE_TX_CFG_CMD message +/*@TRACE*/ +struct gapc_cte_tx_cfg_cmd +{ + /// GAP request type: + /// - GAPC_CTE_TX_CFG: Constant Tone Extension Transmission configuration + uint8_t operation; + /// CTE types (bit0: AOA | bit1: AOD-1us | bit2: AOD-2us) (@see enum gap_cte_type) + uint8_t cte_types; + /// Length of switching pattern (number of antenna IDs in the pattern) + uint8_t switching_pattern_len; + /// Antenna IDs + uint8_t antenna_id[__ARRAY_EMPTY]; +}; + +/// Parameters of the @ref GAPC_CTE_RX_CFG_CMD message +/*@TRACE*/ +struct gapc_cte_rx_cfg_cmd +{ + /// GAP request type: + /// - GAPC_CTE_RX_CFG: Constant Tone Extension Reception configuration + uint8_t operation; + /// Sampling enable + bool sample_en; + /// Slot durations (1: 1us | 2: 2us) + uint8_t slot_dur; + /// Length of switching pattern (number of antenna IDs in the pattern) + uint8_t switching_pattern_len; + /// Antenna IDs + uint8_t antenna_id[__ARRAY_EMPTY]; +}; + +/// Parameters of the @ref GAPC_CTE_REQ_CTRL_CMD message +/*@TRACE*/ +struct gapc_cte_req_ctrl_cmd +{ + /// GAP request type: + /// - GAPC_CTE_REQ_CTRL: Constant Tone Extension request control (enable / disable) + uint8_t operation; + /// True to enable TX or RX Constant Tone Extension, False to disable + bool enable; + /// CTE request interval (in number of connection events) + uint16_t interval; + /// Requested CTE length (in 8us unit) + uint8_t cte_len; + /// Requested CTE type (0: AOA | 1: AOD-1us | 2: AOD-2us) (@see enum gap_cte_type) + uint8_t cte_type; +}; + +/// Parameters of the @ref GAPC_CTE_RSP_CTRL_CMD message +/*@TRACE*/ +struct gapc_cte_rsp_ctrl_cmd +{ + /// GAP request type: + /// - GAPC_CTE_RSP_CTRL: Constant Tone Extension response control (enable / disable) + uint8_t operation; + /// True to enable TX or RX Constant Tone Extension, False to disable + bool enable; +}; + +/// Indicate reception of a IQ Report event over a BLE connection +/*@TRACE*/ +struct gapc_cte_iq_report_ind +{ + /// Rx PHY (@see enum gap_phy_val) + uint8_t rx_phy; + /// Data channel index + uint8_t data_channel_idx; + /// RSSI (in 0.1 dBm) + int16_t rssi; + /// RSSI antenna ID + uint8_t rssi_antenna_id; + /// CTE type (0: AOA | 1: AOD-1us | 2: AOD-2us) (@see enum gap_cte_type) + uint8_t cte_type; + /// Slot durations (1: 1us | 2: 2us) + uint8_t slot_dur; + /// Packet status + uint8_t pkt_status; + /// Connection event counter + uint16_t con_evt_cnt; + /// Number of samples + uint8_t nb_samples; + /// I/Q sample + struct gap_iq_sample sample[__ARRAY_EMPTY]; +}; + +/// Pairing parameters +/*@TRACE*/ +struct gapc_pairing +{ + /// IO capabilities (@see gap_io_cap) + uint8_t iocap; + /// OOB information (@see gap_oob) + uint8_t oob; + /// Authentication (@see gap_auth) + /// Note in BT 4.1 the Auth Field is extended to include 'Key Notification' and + /// and 'Secure Connections'. + uint8_t auth; + /// Encryption key size (7 to 16) + uint8_t key_size; + ///Initiator key distribution (@see gap_kdist) + uint8_t ikey_dist; + ///Responder key distribution (@see gap_kdist) + uint8_t rkey_dist; + + /// Device security requirements (minimum security level). (@see gap_sec_req) + uint8_t sec_req; +}; + +/// Long Term Key information +/*@TRACE*/ +struct gapc_ltk +{ + /// Long Term Key + struct gap_sec_key ltk; + /// Encryption Diversifier + uint16_t ediv; + /// Random Number + rand_nb_t randnb; + /// Encryption key size (7 to 16) + uint8_t key_size; +}; +/// Out of Band Information +/*@TRACE*/ +struct gapc_oob +{ + /// Confirm Value + uint8_t conf[GAP_KEY_LEN]; + /// Random Number + uint8_t rand[GAP_KEY_LEN]; +}; + +/*@TRACE*/ +struct gapc_nc +{ + uint8_t value[4]; +}; + +/// Identity Resolving Key information +/*@TRACE*/ +struct gapc_irk +{ + /// Identity Resolving Key + struct gap_sec_key irk; + /// Device BD Identity Address + struct gap_bdaddr addr; +}; + + +/// Start Bonding command procedure +/*@TRACE*/ +struct gapc_bond_cmd +{ + /// GAP request type: + /// - GAPC_BOND: Start bonding procedure. + uint8_t operation; + /// Pairing information + struct gapc_pairing pairing; +}; + +/// Bond procedure requested information data +/*@TRACE + @trc_ref gapc_bond*/ +union gapc_bond_req_data +{ + /// Authentication level (@see gap_auth) (if request = GAPC_PAIRING_REQ) + //@trc_union parent.request == GAPC_PAIRING_REQ + uint8_t auth_req; + /// LTK Key Size (if request = GAPC_LTK_EXCH) + //@trc_union parent.request == GAPC_LTK_EXCH + uint8_t key_size; + /// Device IO used to get TK: (if request = GAPC_TK_EXCH) + /// - GAP_TK_OOB: TK get from out of band method + /// - GAP_TK_DISPLAY: TK generated and shall be displayed by local device + /// - GAP_TK_KEY_ENTRY: TK shall be entered by user using device keyboard + //@trc_union parent.request == GAPC_TK_EXCH + uint8_t tk_type; + + /// Addition OOB Data for the OOB Conf and Rand values + //@trc_union parent.request == GAPC_OOB_EXCH + struct gapc_oob oob_data; + /// Numeric Comparison Data + //@trc_union parent.request == GAPC_NC_EXCH + struct gapc_nc nc_data; +}; + +/// Bonding requested by peer device indication message. +/*@TRACE*/ +struct gapc_bond_req_ind +{ + /// Bond request type (@see gapc_bond) + uint8_t request; + + /// Bond procedure requested information data + union gapc_bond_req_data data; +}; + +/*@TRACE + @trc_ref gapc_bond +*/ +union gapc_bond_cfm_data +{ + /// Pairing Features (request = GAPC_PAIRING_RSP) + //@trc_union parent.request == GAPC_PAIRING_RSP + struct gapc_pairing pairing_feat; + /// LTK (request = GAPC_LTK_EXCH) + //@trc_union parent.request == GAPC_LTK_EXCH + struct gapc_ltk ltk; + /// CSRK (request = GAPC_CSRK_EXCH) + //@trc_union parent.request == GAPC_CSRK_EXCH + struct gap_sec_key csrk; + /// TK (request = GAPC_TK_EXCH) + //@trc_union parent.request == GAPC_TK_EXCH + struct gap_sec_key tk; + /// IRK (request = GAPC_IRK_EXCH) + //@trc_union parent.request == GAPC_IRK_EXCH + struct gapc_irk irk; + /// OOB Confirm and Random from the peer (request = GAPC_OOB_EXCH) + //@trc_union parent.request == GAPC_OOB_EXCH + struct gapc_oob oob; +}; + +/// Confirm requested bond information. +/*@TRACE*/ +struct gapc_bond_cfm +{ + /// Bond request type (@see gapc_bond) + uint8_t request; + /// Request accepted + uint8_t accept; + + /// Bond procedure information data + union gapc_bond_cfm_data data; +}; + +/** + * Authentication information + */ +/*@TRACE*/ +struct gapc_bond_auth +{ + /// Authentication information (@see gap_auth) + uint8_t info; + + /// LTK exchanged during pairing. + bool ltk_present; +}; + +/// Bond procedure information data +/*@TRACE + @trc_ref gapc_bond*/ +union gapc_bond_data +{ + /// Authentication information (@see gap_auth) + /// (if info = GAPC_PAIRING_SUCCEED) + //@trc_union parent.info == GAPC_PAIRING_SUCCEED + struct gapc_bond_auth auth; + /// Pairing failed reason (if info = GAPC_PAIRING_FAILED) + //@trc_union parent.info == GAPC_PAIRING_FAILED + uint8_t reason; + /// Long Term Key information (if info = GAPC_LTK_EXCH) + //@trc_union parent.info == GAPC_LTK_EXCH + struct gapc_ltk ltk; + /// Identity Resolving Key information (if info = GAPC_IRK_EXCH) + //@trc_union parent.info == GAPC_IRK_EXCH + struct gapc_irk irk; + /// Connection Signature Resolving Key information (if info = GAPC_CSRK_EXCH) + //@trc_union parent.info == GAPC_CSRK_EXCH + struct gap_sec_key csrk; +}; + +/// Bonding information indication message +/*@TRACE*/ +struct gapc_bond_ind +{ + /// Bond information type (@see gapc_bond) + uint8_t info; + + /// Bond procedure information data + union gapc_bond_data data; +}; + +/// Start Encryption command procedure +/*@TRACE*/ +struct gapc_encrypt_cmd +{ + /// GAP request type: + /// - GAPC_ENCRYPT: Start encryption procedure. + uint8_t operation; + /// Long Term Key information + struct gapc_ltk ltk; +}; + +/// Encryption requested by peer device indication message. +/*@TRACE*/ +struct gapc_encrypt_req_ind +{ + /// Encryption Diversifier + uint16_t ediv; + /// Random Number + rand_nb_t rand_nb; +}; + +/// Confirm requested Encryption information. +/*@TRACE*/ +struct gapc_encrypt_cfm +{ + /// Indicate if a LTK has been found for the peer device + uint8_t found; + /// Long Term Key + struct gap_sec_key ltk; + /// LTK Key Size + uint8_t key_size; +}; + +/// Encryption information indication message +/*@TRACE*/ +struct gapc_encrypt_ind +{ + /// Authentication level (@see gap_auth) + uint8_t auth; +}; + +/// Start Security Request command procedure +/*@TRACE*/ +struct gapc_security_cmd +{ + /// GAP request type: + /// - GAPC_SECURITY_REQ: Start security request procedure + uint8_t operation; + /// Authentication level (@see gap_auth) + uint8_t auth; +}; +/// Security requested by peer device indication message +/*@TRACE*/ +struct gapc_security_ind +{ + /// Authentication level (@see gap_auth) + uint8_t auth; +}; + +/// Parameters of the @ref GAPC_SIGN_COUNTER_IND message +/*@TRACE*/ +struct gapc_sign_counter_ind +{ + /// Local SignCounter value + uint32_t local_sign_counter; + /// Peer SignCounter value + uint32_t peer_sign_counter; +}; + + +/// Parameters of the @ref GAPC_SET_LE_PING_TO_CMD message +/*@TRACE*/ +struct gapc_set_le_ping_to_cmd +{ + /// GAP request type: + /// - GAPC_SET_LE_PING_TO : Set the LE Ping timeout value + uint8_t operation; + /// Authenticated payload timeout + uint16_t timeout; +}; + +/// Parameters of the @ref GAPC_SET_LE_PKT_SIZE_CMD message +/*@TRACE*/ +struct gapc_set_le_pkt_size_cmd +{ + /// GAP request type: + /// - GAPC_SET_LE_PKT_SIZE : Set the LE Data length value + uint8_t operation; + ///Preferred maximum number of payload octets that the local Controller should include + ///in a single Link Layer Data Channel PDU. + uint16_t tx_octets; + ///Preferred maximum number of microseconds that the local Controller should use to transmit + ///a single Link Layer Data Channel PDU + uint16_t tx_time; +}; + +/// Parameters of the @ref GAPC_LE_PKT_SIZE_IND message +/*@TRACE*/ +struct gapc_le_pkt_size_ind +{ + ///The maximum number of payload octets in TX + uint16_t max_tx_octets; + ///The maximum time that the local Controller will take to TX + uint16_t max_tx_time; + ///The maximum number of payload octets in RX + uint16_t max_rx_octets; + ///The maximum time that the local Controller will take to RX + uint16_t max_rx_time; +}; + +/// Parameters of the @ref GAPC_KEY_PRESS_NOTIFICATION_CMD message +/*@TRACE*/ +struct gapc_key_press_notif_cmd +{ + /// GAP request type: + /// - GAPC_KEY_PRESS_NOTIFICATION_CMD : Inform the remote device when keys have been entered or erased + uint8_t operation; + /// notification type + uint8_t notification_type; +}; + +/// Parameters of the @ref GAPC_KEY_PRESS_NOTIFICATION_IND message +/*@TRACE*/ +struct gapc_key_press_notif_ind +{ + /// notification type + uint8_t notification_type; +}; + +/// Set the PHY configuration for current active link +/*@TRACE*/ +struct gapc_set_phy_cmd +{ + /// GAP request type: + /// - GAPC_SET_PHY : Set the PHY configuration for current active link + uint8_t operation; + /// Supported LE PHY for data transmission (@see enum gap_phy) + uint8_t tx_phy; + /// Supported LE PHY for data reception (@see enum gap_phy) + uint8_t rx_phy; + /// PHY options (@see enum gapc_phy_option) + uint8_t phy_opt; +}; + +/// Active link PHY configuration. Triggered when configuration is read or during an update. +/*@TRACE*/ +struct gapc_le_phy_ind +{ + /// LE PHY for data transmission (@see enum gap_phy) + uint8_t tx_phy; + /// LE PHY for data reception (@see enum gap_phy) + uint8_t rx_phy; +}; + +/// Parameters of the @ref GAPC_SIGN_CMD message +/*@TRACE*/ +struct gapc_sign_cmd +{ + /// GAP request type: + /// - GAPC_SIGN_PACKET: Sign an attribute packet + /// - GAPC_SIGN_CHECK: Verify signature or an attribute packet + uint8_t operation; + /// Data PDU length (Bytes) + uint16_t byte_len; + /// Data PDU + SignCounter if generation, Data PDU + SignCounter + MAC if verification + uint8_t msg[__ARRAY_EMPTY]; +}; + +/// Parameters of the @ref GAPC_SIGN_IND message +/*@TRACE*/ +struct gapc_sign_ind +{ + /// GAP request type: + /// - GAPC_SIGN_PACKET: Sign an attribute packet + /// - GAPC_SIGN_CHECK: Verify signature or an attribute packet + uint8_t operation; + /// Data PDU length (Bytes) + uint16_t byte_len; + /// Data PDU + SignCounter + MAC + uint8_t signed_msg[__ARRAY_EMPTY]; +}; + +/// Parameters of the @ref GAPC_CHAN_SEL_ALGO_IND +/*@TRACE*/ +struct gapc_chan_sel_algo_ind +{ + /// Used channel selection algorithm + uint8_t chan_sel_algo; +}; + +/// @} GAPC_TASK + +#endif /* _GAPC_TASK_H_ */ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/api/gapm_task.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/api/gapm_task.h new file mode 100755 index 0000000..e728e8a --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/api/gapm_task.h @@ -0,0 +1,2018 @@ +/** + **************************************************************************************** + * + * @file gapm_task.h + * + * @brief Generic Access Profile Manager Task Header. + * + * Copyright (C) RivieraWaves 2009-2016 + * + **************************************************************************************** + */ + + +#ifndef _GAPM_TASK_H_ +#define _GAPM_TASK_H_ + +/** + **************************************************************************************** + * @addtogroup GAPM_TASK Generic Access Profile Manager Task + * @ingroup GAPM + * @brief Handles ALL messages to/from GAP Manager block. + * + * It handles messages from lower and higher layers not related to an ongoing connection. + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_task.h" // Task definitions +#include "gap.h" +#include "common_math.h" +#include "kernel_msg.h" + +/* + * DEFINES + **************************************************************************************** + */ + +/* + * ENUMERATIONS + **************************************************************************************** + */ + +/// GAP Manager Message Interface +/*@TRACE*/ +enum gapm_msg_id +{ + /* Default event */ + /// Command Complete event + GAPM_CMP_EVT = MSG_ID(GAPM, 0x00), + + /* Default commands */ + /// Reset link layer and the host command + GAPM_RESET_CMD = MSG_ID(GAPM, 0x02), + + /* Device Configuration */ + /// Set device configuration command + GAPM_SET_DEV_CONFIG_CMD = MSG_ID(GAPM, 0x04), + /// Set device channel map + GAPM_SET_CHANNEL_MAP_CMD = MSG_ID(GAPM, 0x05), + + /* Local device information */ + /// Get local device info command + GAPM_GET_DEV_INFO_CMD = MSG_ID(GAPM, 0x06), + /// Local device version indication event + GAPM_DEV_VERSION_IND = MSG_ID(GAPM, 0x07), + /// Local device BD Address indication event + GAPM_DEV_BDADDR_IND = MSG_ID(GAPM, 0x08), + /// Advertising channel Tx power level + GAPM_DEV_ADV_TX_POWER_IND = MSG_ID(GAPM, 0x09), + /// Indication containing information about memory usage. + GAPM_DBG_MEM_INFO_IND = MSG_ID(GAPM, 0x0A), + /// Indication containing controller antenna information + GAPM_ANTENNA_INF_IND = MSG_ID(GAPM, 0x0B), + + /// Name of peer device indication + GAPM_PEER_NAME_IND = MSG_ID(GAPM, 0x12), + + /* Security / Encryption Toolbox */ + /// Resolve address command + GAPM_RESOLV_ADDR_CMD = MSG_ID(GAPM, 0x14), + /// Indicate that resolvable random address has been solved + GAPM_ADDR_SOLVED_IND = MSG_ID(GAPM, 0x15), + /// Generate a random address. + GAPM_GEN_RAND_ADDR_CMD = MSG_ID(GAPM, 0x16), + /// Use the AES-128 block in the controller + GAPM_USE_ENC_BLOCK_CMD = MSG_ID(GAPM, 0x17), + /// AES-128 block result indication + GAPM_USE_ENC_BLOCK_IND = MSG_ID(GAPM, 0x18), + /// Generate a 8-byte random number + GAPM_GEN_RAND_NB_CMD = MSG_ID(GAPM, 0x19), + /// Random Number Indication + GAPM_GEN_RAND_NB_IND = MSG_ID(GAPM, 0x1A), + + /* Profile Management */ + /// Create new task for specific profile + GAPM_PROFILE_TASK_ADD_CMD = MSG_ID(GAPM, 0x1B), + /// Inform that profile task has been added. + GAPM_PROFILE_ADDED_IND = MSG_ID(GAPM, 0x1C), + + /// Indicate that a message has been received on an unknown task + GAPM_UNKNOWN_TASK_IND = MSG_ID(GAPM, 0x1D), + + /* Data Length Extension */ + /// Suggested Default Data Length indication + GAPM_SUGG_DFLT_DATA_LEN_IND = MSG_ID(GAPM, 0x1E), + /// Maximum Data Length indication + GAPM_MAX_DATA_LEN_IND = MSG_ID(GAPM, 0x1F), + + /* Resolving list for controller-based privacy*/ + /// Resolving address list address indication + GAPM_RAL_ADDR_IND = MSG_ID(GAPM, 0x22), + + /* Set new IRK */ + /// Modify current IRK + GAPM_SET_IRK_CMD = MSG_ID(GAPM, 0x23), + + /* LE Protocol/Service Multiplexer Management */ + /// Register a LE Protocol/Service Multiplexer command + GAPM_LEPSM_REGISTER_CMD = MSG_ID(GAPM, 0x24), + /// Unregister a LE Protocol/Service Multiplexer command + GAPM_LEPSM_UNREGISTER_CMD = MSG_ID(GAPM, 0x25), + + /* LE Test Mode */ + /// Control of the test mode command + GAPM_LE_TEST_MODE_CTRL_CMD = MSG_ID(GAPM, 0x26), + /// Indicate end of test mode + GAPM_LE_TEST_END_IND = MSG_ID(GAPM, 0x27), + + /// Provide statistic information about ISO exchange + GAPM_ISO_STAT_IND = MSG_ID(GAPM, 0x28), + + /* Secure Connections */ + /// Request to provide DH Key + GAPM_GEN_DH_KEY_CMD = MSG_ID(GAPM, 0x29), + /// Indicates the DH Key computation is complete and available + GAPM_GEN_DH_KEY_IND = MSG_ID(GAPM, 0x2A), + /// Retrieve Public Key + GAPM_GET_PUB_KEY_CMD = MSG_ID(GAPM, 0x2B), + /// Indicates the Public Key Pair value + GAPM_PUB_KEY_IND = MSG_ID(GAPM, 0x2C), + + + /* ************************************************ */ + /* ------------ NEW COMMANDS FOR BLE 5 ------------ */ + /* ************************************************ */ + + /* List Management Operations */ + /// Get local or peer address + /// @see struct gapm_get_ral_addr_cmd + GAPM_GET_RAL_ADDR_CMD = MSG_ID(GAPM, 0x90), + /// Set content of either white list or resolving list or periodic advertiser list + /// @see struct gapm_list_set_wl_cmd + /// @see struct gapm_list_set_ral_cmd + /// @see struct gapm_list_set_pal_cmd + GAPM_LIST_SET_CMD = MSG_ID(GAPM, 0x91), + /// Indicate size of list indicated in GAPM_GET_DEV_CONFIG_CMD message + /// @see struct gapm_list_size_ind + GAPM_LIST_SIZE_IND = MSG_ID(GAPM, 0x92), + + /* Extended Air Operations */ + /// Create an advertising, a scanning, an initiating or a periodic synchronization activity + /// @see struct gapm_activity_create_cmd + /// @see struct gapm_activity_create_adv_cmd + GAPM_ACTIVITY_CREATE_CMD = MSG_ID(GAPM, 0xA0), + /// Start a previously created activity + /// @see struct gapm_activity_start_cmd + GAPM_ACTIVITY_START_CMD = MSG_ID(GAPM, 0xA1), + /// Stop either a given activity or all existing activities + /// @see struct gapm_activity_stop_cmd + GAPM_ACTIVITY_STOP_CMD = MSG_ID(GAPM, 0xA2), + /// Delete either a given activity or all existing activities + /// @see struct gapm_activity_delete_cmd + GAPM_ACTIVITY_DELETE_CMD = MSG_ID(GAPM, 0xA3), + /// Indicate that an activity has well been created + /// @see struct gapm_activity_create_ind + GAPM_ACTIVITY_CREATED_IND = MSG_ID(GAPM, 0xA4), + /// Indicate that an activity has been stopped and can be restarted + /// @see struct gapm_activity_stopped_ind + GAPM_ACTIVITY_STOPPED_IND = MSG_ID(GAPM, 0xA5), + /// Set either advertising data or scan response data or periodic advertising data + /// @see struct gapm_set_adv_data_cmd + GAPM_SET_ADV_DATA_CMD = MSG_ID(GAPM, 0xA6), + /// Indicate reception of an advertising report (periodic or not), a scan response report + /// @see struct gapm_ext_adv_report_ind + GAPM_EXT_ADV_REPORT_IND = MSG_ID(GAPM, 0xA7), + /// Indicate reception of a scan request + /// @see struct gapm_scan_request_ind + GAPM_SCAN_REQUEST_IND = MSG_ID(GAPM, 0xA8), + /// Indicate that synchronization has been successfully established with a periodic advertiser + /// @see struct gapm_sync_established_ind + GAPM_SYNC_ESTABLISHED_IND = MSG_ID(GAPM, 0xA9), + /// Indicate maximum advertising data length supported by controller + /// @see struct gapm_max_adv_data_len_ind + GAPM_MAX_ADV_DATA_LEN_IND = MSG_ID(GAPM, 0xAA), + /// Indicate number of available advertising sets + /// @see struct gapm_nb_adv_sets_ind + GAPM_NB_ADV_SETS_IND = MSG_ID(GAPM, 0xAB), + /// Indicate the transmit powers supported by the controller + /// @see struct gapm_dev_tx_power_ind + GAPM_DEV_TX_PWR_IND = MSG_ID(GAPM, 0xAC), + /// Indicate the RF path compensation values + /// @see struct gapm_dev_rf_path_comp_ind + GAPM_DEV_RF_PATH_COMP_IND = MSG_ID(GAPM, 0xAD), + /// Indication to the task that sends the unknown message + /// @see struct gapm_unknown_msg_ind + GAPM_UNKNOWN_MSG_IND = MSG_ID(GAPM, 0xAE), + /// Control reception or not of Periodic Advertising Report in a Periodic Advertising Sync activity + /// @see struct gapm_per_adv_report_ctrl_cmd + GAPM_PER_ADV_REPORT_CTRL_CMD = MSG_ID(GAPM, 0xAF), + /// Control capturing IQ samples from the Constant Tone Extension of periodic advertising packets + GAPM_PER_SYNC_IQ_SAMPLING_CTRL_CMD = MSG_ID(GAPM, 0xB0), + /// Indicate reception of a IQ Report event over a periodic advertising sync activity + GAPM_PER_ADV_IQ_REPORT_IND = MSG_ID(GAPM, 0xB1), + /// Control CTE transmission in a periodic advertising activity + GAPM_PER_ADV_CTE_TX_CTL_CMD = MSG_ID(GAPM, 0xB2), + + /* ************************************************ */ + /* ---------------- DEBUG COMMANDS ---------------- */ + /* ************************************************ */ + /// Configure the Debug Platform I&Q Sampling generator + GAPM_DBG_IQGEN_CFG_CMD = MSG_ID(GAPM, 0x50), + + /* ************************************************ */ + /* -------------- Internal usage only ------------- */ + /* ************************************************ */ + /// Message received to unknown task received + GAPM_UNKNOWN_TASK_MSG = MSG_ID(GAPM, 0xF0), + + /* Internal messages for timer events, not part of API */ + /// Address renewal timeout indication + GAPM_ADDR_RENEW_TO_IND = MSG_ID(GAPM, 0xF1), + /// Automatic connection establishment timeout indication + GAPM_AUTO_CONN_TO_IND = MSG_ID(GAPM, 0xF2), + + /* Addresses Management */ + /// Renew random private addresses + /// @see struct gapm_addr_renew_cmd + GAPM_ADDR_RENEW_CMD = MSG_ID(GAPM, 0xF3), +}; + + +/// GAP Manager operation type - application interface +/*@TRACE*/ +enum gapm_operation +{ + /* No Operation (if nothing has been requested) */ + /* ************************************************ */ + /// No operation. + GAPM_NO_OP = 0x00, + + /* Default operations */ + /* ************************************************ */ + /// Reset BLE subsystem: LL and HL. + GAPM_RESET = 0x01, + + /* Configuration operations */ + /* ************************************************ */ + /// Set device configuration + GAPM_SET_DEV_CONFIG = 0x03, + /// Set device channel map + GAPM_SET_CHANNEL_MAP = 0x04, + + /* Retrieve device information */ + /* ************************************************ */ + /// Get Local device version + GAPM_GET_DEV_VERSION = 0x05, + /// Get Local device BD Address + GAPM_GET_DEV_BDADDR = 0x06, + /// Get device advertising power level + GAPM_GET_DEV_ADV_TX_POWER = 0x07, + /// Get White List Size. + GAPM_GET_WLIST_SIZE = 0x08, + /// Retrieve Antenna information + GAPM_GET_ANTENNA_INFO = 0x09, + + /* Security / Encryption Toolbox */ + /* ************************************************ */ + /// Resolve device address + GAPM_RESOLV_ADDR = 0x17, + /// Generate a random address + GAPM_GEN_RAND_ADDR = 0x18, + /// Use the controller's AES-128 block + GAPM_USE_ENC_BLOCK = 0x19, + /// Generate a 8-byte random number + GAPM_GEN_RAND_NB = 0x1A, + + /* Profile Management */ + /* ************************************************ */ + /// Create new task for specific profile + GAPM_PROFILE_TASK_ADD = 0x1B, + + /* DEBUG */ + /* ************************************************ */ + /// Get memory usage + GAPM_DBG_GET_MEM_INFO = 0x1C, + /// Perform a platform reset + GAPM_PLF_RESET = 0x1D, + + /* Data Length Extension */ + /* ************************************************ */ + /// Set Suggested Default LE Data Length + GAPM_SET_SUGGESTED_DFLT_LE_DATA_LEN = 0x1E, + /// Get Suggested Default LE Data Length + GAPM_GET_SUGGESTED_DFLT_LE_DATA_LEN = 0x1F, + /// Get Maximum LE Data Length + GAPM_GET_MAX_LE_DATA_LEN = 0x20, + + /* Operation on Resolving List */ + /* ************************************************ */ + /// Get resolving address list size + GAPM_GET_RAL_SIZE = 0x21, + /// Get resolving local address + GAPM_GET_RAL_LOC_ADDR = 0x22, + /// Get resolving peer address + GAPM_GET_RAL_PEER_ADDR = 0x23, + + /* Change current IRK */ + /* ************************************************ */ + /// Set IRK + GAPM_SET_IRK = 0x28, + + /* LE Protocol/Service Multiplexer management */ + /* ************************************************ */ + /// Register a LE Protocol/Service Multiplexer + GAPM_LEPSM_REG = 0x29, + /// Unregister a LE Protocol/Service Multiplexer + GAPM_LEPSM_UNREG = 0x2A, + + /* LE Direct Test Mode */ + /* ************************************************ */ + /// Stop the test mode + GAPM_LE_TEST_STOP = 0x2B, + /// Start RX Test Mode + GAPM_LE_TEST_RX_START = 0x2C, + /// Start TX Test Mode + GAPM_LE_TEST_TX_START = 0x2D, + + /* Secure Connection */ + /* ************************************************ */ + /// Generate DH_Key + GAPM_GEN_DH_KEY = 0x2E, + /// Retrieve Public Key + GAPM_GET_PUB_KEY = 0x2F, + + /* List Management */ + /* ************************************************ */ + /// Set content of white list + GAPM_SET_WL = 0x90, + /// Set content of resolving list + GAPM_SET_RAL = 0x91, + /// Set content of periodic advertiser list + GAPM_SET_PAL = 0x92, + /// Get periodic advertiser list size + GAPM_GET_PAL_SIZE = 0x95, + + /* Air Operations */ + /* ************************************************ */ + /// Create advertising activity + GAPM_CREATE_ADV_ACTIVITY = 0xA0, + /// Create scanning activity + GAPM_CREATE_SCAN_ACTIVITY = 0xA1, + /// Create initiating activity + GAPM_CREATE_INIT_ACTIVITY = 0xA2, + /// Create periodic synchronization activity + GAPM_CREATE_PERIOD_SYNC_ACTIVITY = 0xA3, + /// Start an activity + GAPM_START_ACTIVITY = 0xA4, + /// Stop an activity + GAPM_STOP_ACTIVITY = 0xA5, + /// Stop all activities + GAPM_STOP_ALL_ACTIVITIES = 0xA6, + /// Delete an activity + GAPM_DELETE_ACTIVITY = 0xA7, + /// Delete all activities + GAPM_DELETE_ALL_ACTIVITIES = 0xA8, + /// Set advertising data + GAPM_SET_ADV_DATA = 0xA9, + /// Set scan response data + GAPM_SET_SCAN_RSP_DATA = 0xAA, + /// Set periodic advertising data + GAPM_SET_PERIOD_ADV_DATA = 0xAB, + /// Get number of available advertising sets + GAPM_GET_NB_ADV_SETS = 0xAC, + /// Get maximum advertising data length supported by the controller + GAPM_GET_MAX_LE_ADV_DATA_LEN = 0xAD, + /// Get minimum and maximum transmit powers supported by the controller + GAPM_GET_DEV_TX_PWR = 0xAE, + /// Get the RF Path Compensation values used in the TX Power Level and RSSI calculation + GAPM_GET_DEV_RF_PATH_COMP = 0xAF, + /// Enable/Disable reception of periodic advertising report + GAPM_PER_ADV_REPORT_CTRL = 0xB0, + /// Enable / Disable IQ sampling + GAPM_PER_SYNC_IQ_SAMPLING_CTRL = 0xB1, + /// Enable / Disable CTE transmission + GAPM_PER_ADV_CTE_TX_CTL = 0xB2, + + /* Debug Commands */ + /* ************************************************ */ + /// Configure the Debug Platform I&Q Sampling generator + GAPM_DBG_IQGEN_CFG = 0x50, + + /* Internal Operations */ + /* ************************************************ */ + /// Renew random addresses + GAPM_RENEW_ADDR = 0xF0, +}; + +/// Own BD address source of the device +enum gapm_own_addr +{ + /// Public or Private Static Address according to device address configuration + GAPM_STATIC_ADDR, + /// Generated resolvable private random address + GAPM_GEN_RSLV_ADDR, + /// Generated non-resolvable private random address + GAPM_GEN_NON_RSLV_ADDR, +}; + +/// Device Attribute write permission requirement +enum gapm_write_att_perm +{ + /// Disable write access + GAPM_WRITE_DISABLE = 0, + /// Enable write access - no authentication required + GAPM_WRITE_NO_AUTH = 1, + /// Write access requires unauthenticated link + GAPM_WRITE_UNAUTH = 2, + /// Write access requires authenticated link + GAPM_WRITE_AUTH = 3, + /// Write access requires secure connected link + GAPM_WRITE_SEC_CON = 4 +}; + +/// Attribute database configuration +/// 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +/// +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ +/// | DBG|DBGT| RFU |PCP | APP_PERM | NAME_PERM | +/// +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ +/// - Bit [0-2] : Device Name write permission requirements for peer device (@see gapm_write_att_perm) +/// - Bit [3-5] : Device Appearance write permission requirements for peer device (@see gapm_write_att_perm) +/// - Bit [6] : Slave Preferred Connection Parameters present +/// - Bit [7-13]: Reserved +/// - Bit [14] : if Debug Mode enabled, forward all L2cap traffic to application +/// - Bit [15] : Enable Debug Mode +enum gapm_att_cfg_flag +{ + /// Device Name write permission requirements for peer device (@see gapm_write_att_perm) + GAPM_ATT_NAME_PERM_MASK = 0x0007, + GAPM_ATT_NAME_PERM_LSB = 0x00, + /// Device Appearance write permission requirements for peer device (@see gapm_write_att_perm) + GAPM_ATT_APPEARENCE_PERM_MASK = 0x0038, + GAPM_ATT_APPEARENCE_PERM_LSB = 0x03, + /// Slave Preferred Connection Parameters present in GAP attribute database. + GAPM_ATT_SLV_PREF_CON_PAR_EN_MASK = 0x0040, + GAPM_ATT_SLV_PREF_CON_PAR_EN_LSB = 0x06, + /// if Debug Mode enabled, forward all L2cap traffic to application + GAPM_ATT_DBG_L2CAP_TRAFFIC_EN_MASK = 0x4000, + GAPM_ATT_DBG_L2CAP_TRAFFIC_EN_LSB = 0x0E, + /// Enable Debug Mode + GAPM_ATT_DBG_MODE_EN_MASK = 0x8000, + GAPM_ATT_DBG_MODE_EN_LSB = 0x0F, +}; + +/// Pairing mode authorized on the device +/// 7 6 5 4 3 2 1 0 +/// +----+----+----+----+----+----+----+----+ +/// | RFU | SCP| LP | +/// +----+----+----+----+----+----+----+----+ +enum gapm_pairing_mode +{ + /// No pairing authorized + GAPM_PAIRING_DISABLE = 0, + /// Legacy pairing Authorized + GAPM_PAIRING_LEGACY = (1 << 0), + /// Secure Connection pairing Authorized + GAPM_PAIRING_SEC_CON = (1 << 1), +}; + +/// LE Audio Mode Configuration +/// 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +/// +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ +/// | RFU | AM0| +/// +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ +enum gapm_audio_cfg_flag +{ + /// LE Audio Mode 0 Supported + GAPM_MASK_AUDIO_AM0_SUP = 0x0001, + GAPM_POS_AUDIO_AM0_SUP = 0x00, +}; + +/// Security level +/// 7 6 5 4 3 2 1 0 +/// +---+---+---+---+---+---+---+---+ +/// |MI | RFU |EKS|SEC_LVL| +/// +---+---+---+---+---+---+---+---+ +/// bit[0-1]: Security level requirement (0=NO_AUTH, 1=UNAUTH, 2=AUTH, 3=SEC_CON) +/// bit[2] : Encryption Key Size length must have 16 bytes +/// bit[7] : Multi-instantiated task +enum gapm_le_psm_sec_mask +{ + /// bit[0-1]: Security level requirement (0=NO_AUTH, 1=UNAUTH, 2=AUTH, 3=SEC_CON) + /// bit[2] : Encryption Key Size length must have 16 bytes + GAPM_LE_PSM_SEC_LVL_MASK = 0x07, + /// bit[7] : Multi-instantiated task + GAPM_LE_PSM_MI_TASK_MASK = 0x80, +}; + +/// Type of activities that can be created +/*@TRACE*/ +enum gapm_actv_type +{ + /// Advertising activity + GAPM_ACTV_TYPE_ADV = 0, + /// Scanning activity + GAPM_ACTV_TYPE_SCAN, + /// Initiating activity + GAPM_ACTV_TYPE_INIT, + /// Periodic synchronization activity + GAPM_ACTV_TYPE_PER_SYNC, +}; + +/// Type of advertising that can be created +enum gapm_adv_type +{ + /// Legacy advertising + GAPM_ADV_TYPE_LEGACY = 0, + /// Extended advertising + GAPM_ADV_TYPE_EXTENDED, + /// Periodic advertising + GAPM_ADV_TYPE_PERIODIC, +}; + +/// Advertising report type +enum gapm_adv_report_type +{ + /// Extended advertising report + GAPM_REPORT_TYPE_ADV_EXT = 0, + /// Legacy advertising report + GAPM_REPORT_TYPE_ADV_LEG, + /// Extended scan response report + GAPM_REPORT_TYPE_SCAN_RSP_EXT, + /// Legacy scan response report + GAPM_REPORT_TYPE_SCAN_RSP_LEG, + /// Periodic advertising report + GAPM_REPORT_TYPE_PER_ADV, +}; + +/// Advertising properties bit field bit positions +enum gapm_adv_prop_bf +{ + /// Indicate that advertising is connectable, reception of CONNECT_REQ or AUX_CONNECT_REQ + /// PDUs is accepted. Not applicable for periodic advertising. + GAPM_ADV_PROP_CONNECTABLE_POS = 0, + GAPM_ADV_PROP_CONNECTABLE_BIT = COMMON_BIT(GAPM_ADV_PROP_CONNECTABLE_POS), + + /// Indicate that advertising is scannable, reception of SCAN_REQ or AUX_SCAN_REQ PDUs is + /// accepted + GAPM_ADV_PROP_SCANNABLE_POS = 1, + GAPM_ADV_PROP_SCANNABLE_BIT = COMMON_BIT(GAPM_ADV_PROP_SCANNABLE_POS), + + /// Indicate that advertising targets a specific device. Only apply in following cases: + /// - Legacy advertising: if connectable + /// - Extended advertising: connectable or (non connectable and non discoverable) + GAPM_ADV_PROP_DIRECTED_POS = 2, + GAPM_ADV_PROP_DIRECTED_BIT = COMMON_BIT(GAPM_ADV_PROP_DIRECTED_POS), + + /// Indicate that High Duty Cycle has to be used for advertising on primary channel + /// Apply only if created advertising is not an extended advertising + GAPM_ADV_PROP_HDC_POS = 3, + GAPM_ADV_PROP_HDC_BIT = COMMON_BIT(GAPM_ADV_PROP_HDC_POS), + + /// Bit 4 is reserved + GAPM_ADV_PROP_RESERVED_4_POS = 4, + GAPM_ADV_PROP_RESERVED_4_BIT = COMMON_BIT(GAPM_ADV_PROP_RESERVED_4_POS), + + /// Enable anonymous mode. Device address won't appear in send PDUs + /// Valid only if created advertising is an extended advertising + GAPM_ADV_PROP_ANONYMOUS_POS = 5, + GAPM_ADV_PROP_ANONYMOUS_BIT = COMMON_BIT(GAPM_ADV_PROP_ANONYMOUS_POS), + + /// Include TX Power in the extended header of the advertising PDU. + /// Valid only if created advertising is not a legacy advertising + GAPM_ADV_PROP_TX_PWR_POS = 6, + GAPM_ADV_PROP_TX_PWR_BIT = COMMON_BIT(GAPM_ADV_PROP_TX_PWR_POS), + + /// Include TX Power in the periodic advertising PDU. + /// Valid only if created advertising is a periodic advertising + GAPM_ADV_PROP_PER_TX_PWR_POS = 7, + GAPM_ADV_PROP_PER_TX_PWR_BIT = COMMON_BIT(GAPM_ADV_PROP_PER_TX_PWR_POS), + + /// Indicate if application must be informed about received scan requests PDUs + GAPM_ADV_PROP_SCAN_REQ_NTF_EN_POS = 8, + GAPM_ADV_PROP_SCAN_REQ_NTF_EN_BIT = COMMON_BIT(GAPM_ADV_PROP_SCAN_REQ_NTF_EN_POS), +}; + +/// Advertising discovery mode +enum gapm_adv_disc_mode +{ + /// Mode in non-discoverable + GAPM_ADV_MODE_NON_DISC = 0, + /// Mode in general discoverable + GAPM_ADV_MODE_GEN_DISC, + /// Mode in limited discoverable + GAPM_ADV_MODE_LIM_DISC, + /// Broadcast mode without presence of AD_TYPE_FLAG in advertising data + GAPM_ADV_MODE_BEACON, + GAPM_ADV_MODE_MAX, +}; + +/// Scanning Types +enum gapm_scan_type +{ + /// General discovery + GAPM_SCAN_TYPE_GEN_DISC = 0, + /// Limited discovery + GAPM_SCAN_TYPE_LIM_DISC, + /// Observer + GAPM_SCAN_TYPE_OBSERVER, + /// Selective observer + GAPM_SCAN_TYPE_SEL_OBSERVER, + /// Connectable discovery + GAPM_SCAN_TYPE_CONN_DISC, + /// Selective connectable discovery + GAPM_SCAN_TYPE_SEL_CONN_DISC, +}; + +/// Scanning properties bit field bit value +enum gapm_scan_prop +{ + /// Scan advertisement on the LE 1M PHY + GAPM_SCAN_PROP_PHY_1M_BIT = (1 << 0), + /// Scan advertisement on the LE Coded PHY + GAPM_SCAN_PROP_PHY_CODED_BIT = (1 << 1), + /// Active scan on LE 1M PHY (Scan Request PDUs may be sent) + GAPM_SCAN_PROP_ACTIVE_1M_BIT = (1 << 2), + /// Active scan on LE Coded PHY (Scan Request PDUs may be sent) + GAPM_SCAN_PROP_ACTIVE_CODED_BIT = (1 << 3), + /// Accept directed advertising packets if we use a RPA and target address cannot be solved by the + /// controller + GAPM_SCAN_PROP_ACCEPT_RPA_BIT = (1 << 4), + /// Filter truncated advertising or scan response reports + GAPM_SCAN_PROP_FILT_TRUNC_BIT = (1 << 5), +}; + +/// Initiating Types +enum gapm_init_type +{ + /// Direct connection establishment, establish a connection with an indicated device + GAPM_INIT_TYPE_DIRECT_CONN_EST = 0, + /// Automatic connection establishment, establish a connection with all devices whose address is + /// present in the white list + GAPM_INIT_TYPE_AUTO_CONN_EST, + /// Name discovery, Establish a connection with an indicated device in order to read content of its + /// Device Name characteristic. Connection is closed once this operation is stopped. + GAPM_INIT_TYPE_NAME_DISC, +}; + +/// Initiating Properties +enum gapm_init_prop +{ + /// Scan connectable advertisements on the LE 1M PHY. Connection parameters for the LE 1M PHY are provided + GAPM_INIT_PROP_1M_BIT = (1 << 0), + /// Connection parameters for the LE 2M PHY are provided + GAPM_INIT_PROP_2M_BIT = (1 << 1), + /// Scan connectable advertisements on the LE Coded PHY. Connection parameters for the LE Coded PHY are provided + GAPM_INIT_PROP_CODED_BIT = (1 << 2), +}; + +/// Advertising report information +enum gapm_adv_report_info +{ + /// Report Type + GAPM_REPORT_INFO_REPORT_TYPE_MASK = 0x07, + /// Report is complete + GAPM_REPORT_INFO_COMPLETE_BIT = (1 << 3), + /// Connectable advertising + GAPM_REPORT_INFO_CONN_ADV_BIT = (1 << 4), + /// Scannable advertising + GAPM_REPORT_INFO_SCAN_ADV_BIT = (1 << 5), + /// Directed advertising + GAPM_REPORT_INFO_DIR_ADV_BIT = (1 << 6), +}; + +/// Filtering policy for duplicated packets +enum gapm_dup_filter_pol +{ + /// Disable filtering of duplicated packets + GAPM_DUP_FILT_DIS = 0, + /// Enable filtering of duplicated packets + GAPM_DUP_FILT_EN, + /// Enable filtering of duplicated packets, reset for each scan period + GAPM_DUP_FILT_EN_PERIOD, +}; + +/// Periodic synchronization types +enum gapm_per_sync_type +{ + /// Do not use periodic advertiser list for synchronization. Use advertiser information provided + /// in the GAPM_ACTIVITY_START_CMD. + GAPM_PER_SYNC_TYPE_GENERAL = 0, + /// Use periodic advertiser list for synchronization + GAPM_PER_SYNC_TYPE_SELECTIVE, + /// Use Periodic advertising sync transfer information send through connection for synchronization + GAPM_PER_SYNC_TYPE_PAST, +}; + +/// PHY Type +enum gapm_phy_type +{ + /// LE 1M + GAPM_PHY_TYPE_LE_1M = 0, + /// LE 2M + GAPM_PHY_TYPE_LE_2M, + /// LE Coded + GAPM_PHY_TYPE_LE_CODED, +}; + +/// ------------------------------------------------------------------------------------- +/// Masks for advertising properties +/// ------------------------------------------------------------------------------------- + +/// Advertising properties configurations for legacy advertising +enum gapm_leg_adv_prop +{ + /// Non connectable non scannable advertising + GAPM_ADV_PROP_NON_CONN_NON_SCAN_MASK = 0x0000, + /// Broadcast non scannable advertising - Discovery mode must be Non Discoverable + GAPM_ADV_PROP_BROADCAST_NON_SCAN_MASK = GAPM_ADV_PROP_NON_CONN_NON_SCAN_MASK, + /// Non connectable scannable advertising + GAPM_ADV_PROP_NON_CONN_SCAN_MASK = GAPM_ADV_PROP_SCANNABLE_BIT, + /// Broadcast non scannable advertising - Discovery mode must be Non Discoverable + GAPM_ADV_PROP_BROADCAST_SCAN_MASK = GAPM_ADV_PROP_NON_CONN_SCAN_MASK, + /// Undirected connectable advertising + GAPM_ADV_PROP_UNDIR_CONN_MASK = GAPM_ADV_PROP_CONNECTABLE_BIT | GAPM_ADV_PROP_SCANNABLE_BIT, + /// Directed connectable advertising + GAPM_ADV_PROP_DIR_CONN_MASK = GAPM_ADV_PROP_DIRECTED_BIT | GAPM_ADV_PROP_CONNECTABLE_BIT, + /// Directed connectable with Low Duty Cycle + GAPM_ADV_PROP_DIR_CONN_LDC_MASK = GAPM_ADV_PROP_DIR_CONN_MASK, + /// Directed connectable with High Duty Cycle + GAPM_ADV_PROP_DIR_CONN_HDC_MASK = GAPM_ADV_PROP_DIR_CONN_MASK | GAPM_ADV_PROP_HDC_BIT, +}; + +/// Advertising properties configurations for extended advertising +enum gapm_ext_adv_prop +{ + /// Non connectable non scannable extended advertising + GAPM_EXT_ADV_PROP_NON_CONN_NON_SCAN_MASK = 0x0000, + /// Non connectable scannable extended advertising + GAPM_EXT_ADV_PROP_NON_CONN_SCAN_MASK = GAPM_ADV_PROP_SCANNABLE_BIT, + /// Non connectable scannable directed extended advertising + GAPM_EXT_ADV_PROP_NON_CONN_SCAN_DIR_MASK = GAPM_ADV_PROP_SCANNABLE_BIT | GAPM_ADV_PROP_DIRECTED_BIT, + /// Non connectable anonymous directed extended advertising + GAPM_EXT_ADV_PROP_ANONYM_DIR_MASK = GAPM_ADV_PROP_ANONYMOUS_BIT | GAPM_ADV_PROP_DIRECTED_BIT, + /// Undirected connectable extended advertising + GAPM_EXT_ADV_PROP_UNDIR_CONN_MASK = GAPM_ADV_PROP_CONNECTABLE_BIT, + /// Directed connectable extended advertising + GAPM_EXT_ADV_PROP_DIR_CONN_MASK = GAPM_ADV_PROP_CONNECTABLE_BIT | GAPM_ADV_PROP_DIRECTED_BIT, +}; + +/// Advertising properties configurations for periodic advertising +enum gapm_per_adv_prop +{ + /// Undirected periodic advertising + GAPM_PER_ADV_PROP_UNDIR_MASK = 0x0000, + /// Directed periodic advertising + GAPM_PER_ADV_PROP_DIR_MASK = GAPM_ADV_PROP_DIRECTED_BIT, +}; + +/// Clock accuracy values +enum gapm_clk_acc +{ + /// 500 ppm + GAPM_CLK_ACC_500 = 0, + /// 250 ppm + GAPM_CLK_ACC_250, + /// 150 ppm + GAPM_CLK_ACC_150, + /// 100 ppm + GAPM_CLK_ACC_100, + /// 75 ppm + GAPM_CLK_ACC_75, + /// 50 ppm + GAPM_CLK_ACC_50, + /// 30 ppm + GAPM_CLK_ACC_30, + /// 20 ppm + GAPM_CLK_ACC_20, +}; + +/// Privacy configuration +enum gapm_priv_cfg +{ + /// Indicate if identity address is a public (0) or static private random (1) address + GAPM_PRIV_CFG_PRIV_ADDR_BIT = (1 << 0), + /// Reserved + GAPM_PRIV_CFG_RSVD = (1 << 1), + /// Indicate if controller privacy is enabled + GAPM_PRIV_CFG_PRIV_EN_BIT = (1 << 2), +}; + +/// Constant Tone Extension sync filtering type +enum gapm_sync_cte_type +{ + /// Do not sync to packets with an AoA Constant Tone Extension + GAPM_CTE_NO_SYNC_WITH_AOA = (1 << 0), + /// Do not sync to packets with an AoD Constant Tone Extension with 1 us slots + GAPM_CTE_NO_SYNC_WITH_AOD_1US_SLOT = (1 << 1), + /// Do not sync to packets with an AoD Constant Tone Extension with 2 us slots + GAPM_CTE_NO_SYNC_WITH_AOD_2US_SLOT = (1 << 2), + /// Do not sync to packets with a type 3 Constant Tone Extension (currently reserved for future use) + GAPM_CTE_NO_SYNC_WITH_TYPE_3 = (1 << 3), + /// Do not sync to packets without a Constant Tone Extension + GAPM_CTE_NO_SYNC_WITHOUT_CTE = (1 << 4), +}; + +/// Supported AoA AoD switching sampling rate +enum gapm_switch_sampling_rate +{ + /// 1 us switching supported for AoD transmission + GAPM_AOD_TX_1_US = (1 << 0), + /// 1 us sampling supported for AoD reception + GAPM_AOD_RX_1_US = (1 << 1), + /// 1 us switching and sampling supported for AoA reception + GAPM_AOA_RX_1_US = (1 << 2), +}; + + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + +/// Configuration for advertising on primary channel +/*@TRACE*/ +struct gapm_adv_prim_cfg +{ + /// Minimum advertising interval (in unit of 625us). Must be greater than 20ms + uint32_t adv_intv_min; + /// Maximum advertising interval (in unit of 625us). Must be greater than 20ms + uint32_t adv_intv_max; + /// Bit field indicating the channel mapping + uint8_t chnl_map; + /// Indicate on which PHY primary advertising has to be performed (@see enum gapm_phy_type) + /// Note that LE 2M PHY is not allowed and that legacy advertising only support LE 1M PHY + uint8_t phy; +}; + +/// Configuration for advertising on secondary channel +/*@TRACE*/ +struct gapm_adv_second_cfg +{ + /// Maximum number of advertising events the controller can skip before sending the + /// AUX_ADV_IND packets. 0 means that AUX_ADV_IND PDUs shall be sent prior each + /// advertising events + uint8_t max_skip; + /// Indicate on which PHY secondary advertising has to be performed (@see enum gapm_phy_type) + uint8_t phy; + /// Advertising SID + uint8_t adv_sid; +}; + +/// Configuration for periodic advertising +/*@TRACE*/ +struct gapm_adv_period_cfg +{ + /// Minimum advertising interval (in unit of 1.25ms). Must be greater than 20ms + uint16_t adv_intv_min; + /// Maximum advertising interval (in unit of 1.25ms). Must be greater than 20ms + uint16_t adv_intv_max; + /// CTE count (number of CTEs to transmit in each periodic advertising interval, range 0x01 to 0x10) + /// 0 to disable CTE transmission + uint8_t cte_count; + /// CTE type (0: AOA | 1: AOD-1us | 2: AOD-2us) (@see enum gap_cte_type) + uint8_t cte_type; + /// CTE length (in 8us unit) + uint8_t cte_len; + /// Length of switching pattern (number of antenna IDs in the pattern) + uint8_t switching_pattern_len; + /// Antenna IDs + uint8_t antenna_id[__ARRAY_EMPTY]; +}; + +/// Advertising parameters for advertising creation +/*@TRACE*/ +struct gapm_adv_create_param +{ + /// Advertising type (@see enum gapm_adv_type) + uint8_t type; + /// Discovery mode (@see enum gapm_adv_disc_mode) + uint8_t disc_mode; + /// Bit field value provided advertising properties (@see enum gapm_adv_prop for bit signification) + uint16_t prop; + /// Maximum power level at which the advertising packets have to be transmitted + /// (between -127 and 126 dBm) + int8_t max_tx_pwr; + /// Advertising filtering policy (@see enum adv_filter_policy) + uint8_t filter_pol; + /// Peer address configuration (only used in case of directed advertising) + struct gap_bdaddr peer_addr; + /// Configuration for primary advertising + struct gapm_adv_prim_cfg prim_cfg; + /// Configuration for secondary advertising (valid only if advertising type is + /// GAPM_ADV_TYPE_EXTENDED or GAPM_ADV_TYPE_PERIODIC) + struct gapm_adv_second_cfg second_cfg; + /// Configuration for periodic advertising (valid only if advertising type os + /// GAPM_ADV_TYPE_PERIODIC) + struct gapm_adv_period_cfg period_cfg; +}; + +/// Additional advertising parameters +/*@TRACE*/ +struct gapm_adv_param +{ + /// Advertising duration (in unit of 10ms). 0 means that advertising continues + /// until the host disable it + uint16_t duration; + /// Maximum number of extended advertising events the controller shall attempt to send prior to + /// terminating the extending advertising + /// Valid only if extended advertising + uint8_t max_adv_evt; +}; + +/// Scan Window operation parameters +/*@TRACE*/ +struct gapm_scan_wd_op_param +{ + /// Scan interval + uint16_t scan_intv; + /// Scan window + uint16_t scan_wd; +}; + +/// Scanning parameters +/*@TRACE*/ +struct gapm_scan_param +{ + /// Type of scanning to be started (@see enum gapm_scan_type) + uint8_t type; + /// Properties for the scan procedure (@see enum gapm_scan_prop for bit signification) + uint8_t prop; + /// Duplicate packet filtering policy + uint8_t dup_filt_pol; + /// Reserved for future use + uint8_t rsvd; + /// Scan window opening parameters for LE 1M PHY + struct gapm_scan_wd_op_param scan_param_1m; + /// Scan window opening parameters for LE Coded PHY + struct gapm_scan_wd_op_param scan_param_coded; + /// Scan duration (in unit of 10ms). 0 means that the controller will scan continuously until + /// reception of a stop command from the application + uint16_t duration; + /// Scan period (in unit of 1.28s). Time interval betweem two consequent starts of a scan duration + /// by the controller. 0 means that the scan procedure is not periodic + uint16_t period; +}; + +/// Connection parameters +/*@TRACE*/ +struct gapm_conn_param +{ + /// Minimum value for the connection interval (in unit of 1.25ms). Shall be less than or equal to + /// conn_intv_max value. Allowed range is 7.5ms to 4s. + uint16_t conn_intv_min; + /// Maximum value for the connection interval (in unit of 1.25ms). Shall be greater than or equal to + /// conn_intv_min value. Allowed range is 7.5ms to 4s. + uint16_t conn_intv_max; + /// Slave latency. Number of events that can be missed by a connected slave device + uint16_t conn_latency; + /// Link supervision timeout (in unit of 10ms). Allowed range is 100ms to 32s + uint16_t supervision_to; + /// Recommended minimum duration of connection events (in unit of 625us) + uint16_t ce_len_min; + /// Recommended maximum duration of connection events (in unit of 625us) + uint16_t ce_len_max; +}; + +/// Initiating parameters +/*@TRACE*/ +struct gapm_init_param +{ + /// Initiating type (@see enum gapm_init_type) + uint8_t type; + /// Properties for the initiating procedure (@see enum gapm_init_prop for bit signification) + uint8_t prop; + /// Timeout for automatic connection establishment (in unit of 10ms). Cancel the procedure if not all + /// indicated devices have been connected when the timeout occurs. 0 means there is no timeout + uint16_t conn_to; + /// Scan window opening parameters for LE 1M PHY + struct gapm_scan_wd_op_param scan_param_1m; + /// Scan window opening parameters for LE Coded PHY + struct gapm_scan_wd_op_param scan_param_coded; + /// Connection parameters for LE 1M PHY + struct gapm_conn_param conn_param_1m; + /// Connection parameters for LE 2M PHY + struct gapm_conn_param conn_param_2m; + /// Connection parameters for LE Coded PHY + struct gapm_conn_param conn_param_coded; + /// Address of peer device in case white list is not used for connection + struct gap_bdaddr peer_addr; +}; + +/// Periodic advertising information +/*@TRACE*/ +struct gapm_period_adv_addr_cfg +{ + /// Advertiser address information + struct gap_bdaddr addr; + /// Advertising SID + uint8_t adv_sid; +}; + +/// Periodic synchronization parameters +/*@TRACE*/ +struct gapm_per_sync_param +{ + /// Number of periodic advertising that can be skipped after a successful receive. Maximum authorized + /// value is 499 + uint16_t skip; + /// Synchronization timeout for the periodic advertising (in unit of 10ms between 100ms and 163.84s) + uint16_t sync_to; + /// Periodic synchronization type (@see enum gapm_per_sync_type) + uint8_t type; + /// Connection index used for periodic sync info reception (only valid for GAPM_PER_SYNC_TYPE_PAST) + uint8_t conidx; + /// Address of advertiser with which synchronization has to be established (used only if use_pal is false) + struct gapm_period_adv_addr_cfg adv_addr; + /// 1 to disable periodic advertising report, 0 to enable them by default + uint8_t report_disable; + /// Type of Constant Tone Extension device should sync on (@see enum gapm_sync_cte_type). + uint8_t cte_type; +}; + +/// Operation command structure in order to keep requested operation. +struct gapm_operation_cmd +{ + /// GAP request type + uint8_t operation; +}; + +/// Command complete event data structure +/*@TRACE*/ +struct gapm_cmp_evt +{ + /// GAP requested operation + uint8_t operation; + /// Status of the request + uint8_t status; +}; + +/// Reset link layer and the host command +/*@TRACE*/ +struct gapm_reset_cmd +{ + /// GAPM requested operation: + /// - GAPM_RESET: Reset BLE subsystem: LL and HL. + uint8_t operation; +}; + +/// Set device configuration command +/*@TRACE*/ +struct gapm_set_dev_config_cmd +{ + /// GAPM requested operation: + /// - GAPM_SET_DEV_CONFIG: Set device configuration + uint8_t operation; + /// Device Role: Central, Peripheral, Observer, Broadcaster or All roles. + uint8_t role; + + /// -------------- Privacy Config ----------------------- + /// Duration before regenerate device address when privacy is enabled. - in seconds + uint16_t renew_dur; + /// Provided own static private random address + bd_addr_t addr; + /// Device IRK used for resolvable random BD address generation (LSB first) + struct gap_sec_key irk; + /// Privacy configuration bit field (@see enum gapm_priv_cfg for bit signification) + uint8_t privacy_cfg; + + /// -------------- Security Config ----------------------- + + /// Pairing mode authorized (@see enum gapm_pairing_mode) + uint8_t pairing_mode; + + /// -------------- ATT Database Config ----------------------- + + /// GAP service start handle + uint16_t gap_start_hdl; + /// GATT service start handle + uint16_t gatt_start_hdl; + + /// Attribute database configuration (@see enum gapm_att_cfg_flag) + uint16_t att_cfg; + + /// -------------- LE Data Length Extension ----------------------- + ///Suggested value for the Controller's maximum transmitted number of payload octets to be used + uint16_t sugg_max_tx_octets; + ///Suggested value for the Controller's maximum packet transmission time to be used + uint16_t sugg_max_tx_time; + + /// --------------- L2CAP Configuration --------------------------- + /// Maximal MTU acceptable for device + uint16_t max_mtu; + /// Maximal MPS Packet size acceptable for device + uint16_t max_mps; + /// Maximum number of LE Credit based connection that can be established + uint8_t max_nb_lecb; + + /// --------------- LE Audio Mode Supported ----------------------- + /// + /// LE Audio Mode Configuration (@see gapm_audio_cfg_flag) + uint16_t audio_cfg; + + /// ------------------ LE PHY Management ------------------------- + /// Preferred LE PHY for data transmission (@see enum gap_phy) + uint8_t tx_pref_phy; + /// Preferred LE PHY for data reception (@see enum gap_phy) + uint8_t rx_pref_phy; + + /// ------------------ Miscellaneous 2 ---------------------------- + /// RF TX Path Compensation value (from -128dB to 128dB, unit is 0.1dB) + uint16_t tx_path_comp; + /// RF RX Path Compensation value (from -128dB to 128dB, unit is 0.1dB) + uint16_t rx_path_comp; +}; + +/// Set new IRK +/*@TRACE*/ +struct gapm_set_irk_cmd +{ + /// GAPM requested operation: + /// - GAPM_SET_IRK: Set device configuration + uint8_t operation; + /// Device IRK used for resolvable random BD address generation (LSB first) + struct gap_sec_key irk; +}; + +/// Set device channel map +/*@TRACE*/ +struct gapm_set_channel_map_cmd +{ + /// GAPM requested operation: + /// - GAPM_SET_CHANNEL_MAP: Set device channel map. + /// - GAPM_GET_SUGGESTED_DFLT_LE_DATA_LEN: Get Suggested Default LE Data Length + /// - GAPM_GET_MAX_LE_DATA_LEN: Get Maximum LE Data Length + /// - GAPM_GET_NB_ADV_SETS: Read number of advertising sets currently supported by the controller + /// - GAPM_GET_MAX_LE_ADV_DATA_LEN: Get maximum data length for advertising data + + /// + /// - GAPM_GET_ANTENNA_INFO: + uint8_t operation; + /// Channel map + le_chnl_map_t chmap; +}; + +/// Get local device info command +/*@TRACE*/ +struct gapm_get_dev_info_cmd +{ + /// GAPM requested operation: + /// - GAPM_GET_DEV_VERSION: Get Local device version + /// - GAPM_GET_DEV_BDADDR: Get Local device BD Address + /// - GAPM_GET_DEV_ADV_TX_POWER: Get device advertising power level + /// - GAPM_DBG_GET_MEM_INFO: Get memory usage (debug only) + uint8_t operation; +}; + +/// Local device version indication event +/*@TRACE*/ +struct gapm_dev_version_ind +{ + /// HCI version + uint8_t hci_ver; + /// LMP version + uint8_t lmp_ver; + /// Host version + uint8_t host_ver; + /// HCI revision + uint16_t hci_subver; + /// LMP subversion + uint16_t lmp_subver; + /// Host revision + uint16_t host_subver; + /// Manufacturer name + uint16_t manuf_name; +}; + +/// Local device BD Address indication event +/*@TRACE*/ +struct gapm_dev_bdaddr_ind +{ + /// Local device address information + struct gap_bdaddr addr; + /// Activity index + uint8_t actv_idx; +}; + +/// Advertising channel Tx power level indication event +/*@TRACE*/ +struct gapm_dev_adv_tx_power_ind +{ + /// Advertising channel Tx power level + int8_t power_lvl; +}; + + +/// Indication containing controller antenna information +/*@TRACE*/ +struct gapm_antenna_inf_ind +{ + /// Supported switching sampling rates bit field (@see enum gapm_switch_sampling_rate) + uint8_t supp_switching_sampl_rates; + /// Number of antennae + uint8_t antennae_num; + /// Max length of switching pattern (number of antenna IDs in the pattern) + uint8_t max_switching_pattern_len; + /// Max CTE length + uint8_t max_cte_len; +}; + +/// Resolving Address indication event +/*@TRACE*/ +struct gapm_ral_addr_ind +{ + /// Peer or local read operation + uint8_t operation; + /// Resolving List address + struct gap_bdaddr addr; +}; + +/// Resolve Address command +/*@TRACE*/ +struct gapm_resolv_addr_cmd +{ + /// GAPM requested operation: + /// - GAPM_RESOLV_ADDR: Resolve device address + uint8_t operation; + /// Number of provided IRK (sahlle be > 0) + uint8_t nb_key; + /// Resolvable random address to solve + bd_addr_t addr; + /// Array of IRK used for address resolution (MSB -> LSB) + struct gap_sec_key irk[__ARRAY_EMPTY]; +}; + +/// Indicate that resolvable random address has been solved +/*@TRACE*/ +struct gapm_addr_solved_ind +{ + /// Resolvable random address solved + bd_addr_t addr; + /// IRK that correctly solved the random address + struct gap_sec_key irk; +}; + +/// Name of peer device indication +/*@TRACE*/ +struct gapm_peer_name_ind +{ + /// peer device bd address + bd_addr_t addr; + /// peer device address type + uint8_t addr_type; + /// peer device name length + uint8_t name_len; + /// peer device name + uint8_t name[__ARRAY_EMPTY]; +}; + +/// Generate a random address. +/*@TRACE*/ +struct gapm_gen_rand_addr_cmd +{ + /// GAPM requested operation: + /// - GAPM_GEN_RAND_ADDR: Generate a random address + uint8_t operation; + /// Dummy parameter used to store the prand part of the address + uint8_t prand[GAP_ADDR_PRAND_LEN]; + /// Random address type @see gap_rnd_addr_type + /// - BD_ADDR_STATIC: Static random address + /// - BD_ADDR_NON_RSLV: Private non resolvable address + /// - BD_ADDR_RSLV: Private resolvable address + uint8_t rnd_type; +}; + +/// Parameters of the @ref GAPM_USE_ENC_BLOCK_CMD message +/*@TRACE*/ +struct gapm_use_enc_block_cmd +{ + /// Command Operation Code (shall be GAPM_USE_ENC_BLOCK) + uint8_t operation; + /// Operand 1 + uint8_t operand_1[GAP_KEY_LEN]; + /// Operand 2 + uint8_t operand_2[GAP_KEY_LEN]; +}; + +/// Parameters of the @ref GAPM_USE_ENC_BLOCK_IND message +/*@TRACE*/ +struct gapm_use_enc_block_ind +{ + /// Result (16 bytes) + uint8_t result[GAP_KEY_LEN]; +}; + +/// Parameters of the @ref GAPM_GEN_DH_KEY_CMD message +/*@TRACE*/ +struct gapm_gen_dh_key_cmd +{ + /// Command Operation Code (shall be GAPM_GEN_DH_KEY) + uint8_t operation; + /// X coordinate + uint8_t operand_1[GAP_P256_KEY_LEN]; + /// Y coordinate + uint8_t operand_2[GAP_P256_KEY_LEN]; +}; + +/// Parameters of the @ref GAPM_GEN_DH_KEY_IND message +/*@TRACE*/ +struct gapm_gen_dh_key_ind +{ + /// Result (32 bytes) + uint8_t result[GAP_P256_KEY_LEN]; +}; + +/// Parameters of the @ref GAPM_GET_PUB_KEY_CMD message +/*@TRACE*/ +struct gapm_get_pub_key_cmd +{ + /// Command Operation Code (shall be GAPM_GET_PUB_KEY) + uint8_t operation; +}; + +/// Parameters of the @ref GAPM_PUB_KEY_IND message +/*@TRACE*/ +struct gapm_pub_key_ind +{ + /// X coordinate + uint8_t pub_key_x[GAP_P256_KEY_LEN]; + /// Y coordinate + uint8_t pub_key_y[GAP_P256_KEY_LEN]; +}; + +/// Parameters of the @ref GAPM_GEN_RAND_NB_CMD message +/*@TRACE*/ +struct gapm_gen_rand_nb_cmd +{ + /// Command Operation Code (shall be GAPM_GEN_RAND_NB) + uint8_t operation; +}; + +/// Parameters of the @ref GAPM_GEN_RAND_NB_IND message +/*@TRACE*/ +struct gapm_gen_rand_nb_ind +{ + /// Generation Random Number (8 bytes) + rand_nb_t randnb; +}; + +/// Create new task for specific profile +/*@TRACE*/ +struct gapm_profile_task_add_cmd +{ + /// GAPM requested operation: + /// - GAPM_PROFILE_TASK_ADD: Add new profile task + uint8_t operation; + /// Security Level : + /// 7 6 5 4 3 2 1 0 + /// +----+----+----+----+----+----+----+----+ + /// | Reserved |DIS | AUTH |EKS | MI | + /// +----+----+----+----+----+----+----+----+ + /// + /// - MI: 1 - Application task is a Multi-Instantiated task, 0 - Mono-Instantiated + /// Only applies for service - Ignored by collectors: + /// - EKS: Service needs a 16 bytes encryption key + /// - AUTH: 0 - Disable, 1 - Enable, 2 - Unauth, 3 - Auth + /// - DIS: Disable the service + uint8_t sec_lvl; + /// Profile task identifier + uint16_t prf_task_id; + /// Application task number + uint16_t app_task; + /// Service start handle + /// Only applies for services - Ignored by collectors + /// 0: dynamically allocated in Attribute database + uint16_t start_hdl; + uint32_t role; + /// 32 bits value that contains value to initialize profile (database parameters, etc...) + uint32_t param[__ARRAY_EMPTY]; +}; + +/// Inform that profile task has been added. +/*@TRACE*/ +struct gapm_profile_added_ind +{ + /// Profile task identifier + uint16_t prf_task_id; + /// Profile task number allocated + uint16_t prf_task_nb; + + uint8_t status; + /// Service start handle + /// Only applies for services - Ignored by collectors + uint16_t start_hdl; + uint32_t role; +}; + +/// Indicate that a message has been received on an unknown task +/*@TRACE*/ +struct gapm_unknown_task_ind +{ + /// Message identifier + uint16_t msg_id; + /// Task identifier + uint16_t task_id; +}; + +/// Indicates suggested default data length +/*@TRACE*/ +struct gapm_sugg_dflt_data_len_ind +{ + ///Host's suggested value for the Controller's maximum transmitted number of payload octets + uint16_t suggted_max_tx_octets; + ///Host's suggested value for the Controller's maximum packet transmission time + uint16_t suggted_max_tx_time; +}; + +/// Indicates maximum data length +/*@TRACE*/ +struct gapm_max_data_len_ind +{ + ///Maximum number of payload octets that the local Controller supports for transmission + uint16_t suppted_max_tx_octets; + ///Maximum time, in microseconds, that the local Controller supports for transmission + uint16_t suppted_max_tx_time; + ///Maximum number of payload octets that the local Controller supports for reception + uint16_t suppted_max_rx_octets; + ///Maximum time, in microseconds, that the local Controller supports for reception + uint16_t suppted_max_rx_time; +}; + +/// Register a LE Protocol/Service Multiplexer command +/*@TRACE*/ +struct gapm_lepsm_register_cmd +{ + /// GAPM requested operation: + /// - GAPM_LEPSM_REG: Register a LE Protocol/Service Multiplexer + uint8_t operation; + /// LE Protocol/Service Multiplexer + uint16_t le_psm; + /// Application task number + uint16_t app_task; + /// Security level + /// 7 6 5 4 3 2 1 0 + /// +---+---+---+---+---+---+---+---+ + /// |MI | RFU |EKS|SEC_LVL| + /// +---+---+---+---+---+---+---+---+ + /// bit[0-1]: Security level requirement (0=NO_AUTH, 1=UNAUTH, 2=AUTH, 3=SEC_CON) + /// bit[2] : Encryption Key Size length must have 16 bytes + /// bit[7] : Does the application task is multi-instantiated or not + uint8_t sec_lvl; +}; + +/// Unregister a LE Protocol/Service Multiplexer command +/*@TRACE*/ +struct gapm_lepsm_unregister_cmd +{ + /// GAPM requested operation: + /// - GAPM_LEPSM_UNREG: Unregister a LE Protocol/Service Multiplexer + uint8_t operation; + /// LE Protocol/Service Multiplexer + uint16_t le_psm; +}; + +/// Control LE Test Mode command +struct gapm_le_test_mode_ctrl_cmd +{ + /// GAPM requested operation: + /// - GAPM_LE_TEST_STOP: Unregister a LE Protocol/Service Multiplexer + /// - GAPM_LE_TEST_RX_START: Start RX Test Mode + /// - GAPM_LE_TEST_TX_START: Start TX Test Mode + uint8_t operation; + /// Tx or Rx Channel (Range 0x00 to 0x27) + uint8_t channel; + /// Length in bytes of payload data in each packet (only valid for TX mode, range 0x00-0xFF) + uint8_t tx_data_length; + /// Packet Payload type (only valid for TX mode @see enum gap_pkt_pld_type) + uint8_t tx_pkt_payload; + /// Test PHY rate (@see enum gap_phy_val) + uint8_t phy; + /// Modulation Index (only valid for RX mode @see enum gap_modulation_idx) + uint8_t modulation_idx; + /// CTE length (in 8us unit) (Expected for RX Mode) + uint8_t cte_len; + /// CTE type (0: AOA | 1: AOD-1us | 2: AOD-2us) (Expected for TX Mode) + uint8_t cte_type; + /// Slot durations (only valid for RX mode) + uint8_t slot_dur; + /// Length of switching pattern (number of antenna IDs in the pattern) + uint8_t switching_pattern_len; + /// Antenna IDs + uint8_t antenna_id[__ARRAY_EMPTY]; +}; + +/// Indicate end of test mode event +struct gapm_le_test_end_ind +{ + /// Number of received packets + uint16_t nb_packet_received; +}; + +/// Provide statistic information about ISO exchange +struct gapm_iso_stat_ind +{ + /// ISO Handle of the isochronous channel (Range 0x0000-0x0EFF) + uint16_t iso_hdl; + + /// Statistics - Number of transmission attempts + uint32_t nb_tx; + /// Statistics - Number of transmission attempts that succeed + uint32_t nb_tx_ok; + /// Statistics - Number of Not granted packet packets + uint32_t nb_tx_not_granted; + + /// Statistics - Number of reception attempt + uint32_t nb_rx; + /// Statistics - Number of reception attempts that succeed + uint32_t nb_rx_ok; + /// Statistics - Number of Not granted packet packets + uint32_t nb_rx_not_granted; + /// Statistics - Number of wrongly received packet (invalid data) + uint32_t nb_rx_data_err; + /// Statistics - Number of CRC Errors + uint32_t nb_rx_crc_err; + /// Statistics - Number of SYNC Errors + uint32_t nb_rx_sync_err; + /// Statistics - Number of received empty packets + uint32_t nb_rx_empty; +}; + +/// Create an advertising, a scanning, an initiating, a periodic synchonization activity command (common) +/*@TRACE*/ +struct gapm_activity_create_cmd +{ + /// GAPM request operation: + /// - GAPM_CREATE_ADV_ACTIVITY: Create advertising activity + /// - GAPM_CREATE_SCAN_ACTIVITY: Create scanning activity + /// - GAPM_CREATE_INIT_ACTIVITY: Create initiating activity + /// - GAPM_CREATE_PERIOD_SYNC_ACTIVITY: Create periodic synchronization activity + uint8_t operation; + /// Own address type (@see enum gapm_own_addr) + uint8_t own_addr_type; +}; + +/// Create an advertising activity command +struct gapm_activity_create_adv_cmd +{ + /// GAPM request operation: + /// - GAPM_CREATE_ADV_ACTIVITY: Create advertising activity + uint8_t operation; + /// Own address type (@see enum gapm_own_addr) + uint8_t own_addr_type; + /// Advertising parameters (optional, shall be present only if operation is GAPM_CREATE_ADV_ACTIVITY) + /// For prop parameter, @see enum gapm_leg_adv_prop, @see enum gapm_ext_adv_prop and @see enum gapm_per_adv_prop for help + struct gapm_adv_create_param adv_param; +}; + +/// Activity parameters +/*@TRACE + @trc_ref gapm_actv_type + */ +union gapm_u_param +{ + /// Additional advertising parameters (for advertising activity) + //@trc_union @activity_map[$parent.actv_idx] == GAPM_ACTV_TYPE_ADV + struct gapm_adv_param adv_add_param; + /// Scan parameters (for scanning activity) + //@trc_union @activity_map[$parent.actv_idx] == GAPM_ACTV_TYPE_SCAN + struct gapm_scan_param scan_param; + /// Initiating parameters (for initiating activity) + //@trc_union @activity_map[$parent.actv_idx] == GAPM_ACTV_TYPE_INIT + struct gapm_init_param init_param; + /// Periodic synchronization parameters (for periodic synchronization activity) + //@trc_union @activity_map[$parent.actv_idx] == GAPM_ACTV_TYPE_PER_SYNC + struct gapm_per_sync_param per_sync_param; +}; + +/// Start a given activity command +/*@TRACE*/ +struct gapm_activity_start_cmd +{ + /// GAPM request operation: + /// - GAPM_START_ACTIVITY: Start a given activity + uint8_t operation; + /// Activity identifier + uint8_t actv_idx; + /// Activity parameters + union gapm_u_param u_param; +}; + +/// Stop one or all activity(ies) command +/*@TRACE*/ +struct gapm_activity_stop_cmd +{ + /// GAPM request operation: + /// - GAPM_STOP_ACTIVITY: Stop a given activity + /// - GAPM_STOP_ALL_ACTIVITIES: Stop all existing activities + uint8_t operation; + /// Activity identifier - used only if operation is GAPM_STOP_ACTIVITY + uint8_t actv_idx; +}; + +/// Delete one or all activity(ies) command +/*@TRACE*/ +struct gapm_activity_delete_cmd +{ + /// GAPM request operation: + /// - GAPM_DELETE_ACTIVITY: Delete a given activity + /// - GAPM_DELETE_ALL_ACTIVITIES: Delete all existing activities + uint8_t operation; + /// Activity identifier - used only if operation is GAPM_STOP_ACTIVITY + uint8_t actv_idx; +}; + +/// Indicate creation of an activity +/*@TRACE + @trc_exec activity_map[$actv_idx] = $actv_type + activity_map = {}*/ +struct gapm_activity_created_ind +{ + /// Activity identifier + uint8_t actv_idx; + /// Activity type (@see enum gapm_actv_type) + uint8_t actv_type; + /// Selected TX power for advertising activity + int8_t tx_pwr; +}; + +/// Indicate that an activity has been stopped +/*@TRACE*/ +struct gapm_activity_stopped_ind +{ + /// Activity identifier + uint8_t actv_idx; + /// Activity type (@see enum gapm_actv_type) + uint8_t actv_type; + /// Activity stop reason + uint8_t reason; + /// In case of periodic advertising, indicate if periodic advertising has been stopped + uint8_t per_adv_stop; +}; + +/// Set advertising, scan response or periodic advertising data command +/*@TRACE*/ +struct gapm_set_adv_data_cmd +{ + /// GAPM request operation: + /// - GAPM_SET_ADV_DATA: Set advertising data + /// - GAPM_SET_SCAN_RSP_DATA: Set scan response data + /// - GAPM_SET_PERIOD_ADV_DATA: Set periodic advertising data + uint8_t operation; + /// Activity identifier + uint8_t actv_idx; + /// Data length + uint16_t length; + /// Data + uint8_t data[__ARRAY_EMPTY]; +}; + +/// Indicate reception of scan request +/*@TRACE*/ +struct gapm_scan_request_ind +{ + /// Activity identifier + uint8_t actv_idx; + /// Transmitter device address + struct gap_bdaddr trans_addr; +}; + +/// Indicate reception of advertising, scan response or periodic advertising data +/*@TRACE*/ +struct gapm_ext_adv_report_ind +{ + /// Activity identifier + uint8_t actv_idx; + /// Bit field providing information about the received report (@see enum gapm_adv_report_info) + uint8_t info; + /// Transmitter device address + struct gap_bdaddr trans_addr; + /// Target address (in case of a directed advertising report) + struct gap_bdaddr target_addr; + /// TX power (in dBm) + int8_t tx_pwr; + /// RSSI (between -127 and +20 dBm) + int8_t rssi; + uint8_t channel_idx; + /// Primary PHY on which advertising report has been received + uint8_t phy_prim; + /// Secondary PHY on which advertising report has been received + uint8_t phy_second; + /// Advertising SID + /// Valid only for periodic advertising report + uint8_t adv_sid; + /// Periodic advertising interval (in unit of 1.25ms, min is 7.5ms) + /// Valid only for periodic advertising report + uint16_t period_adv_intv; + /// Report length + uint16_t length; + /// Report + uint8_t data[__ARRAY_EMPTY]; +}; + +/// Indicate that synchronization has been established with a periodic advertiser +/*@TRACE*/ +struct gapm_sync_established_ind +{ + /// Activity identifier + uint8_t actv_idx; + /// PHY on which synchronization has been established (@see gap_phy_type) + uint8_t phy; + /// Periodic advertising interval (in unit of 1.25ms, min is 7.5ms) + uint16_t intv; + /// Advertising SID + uint8_t adv_sid; + /// Advertiser clock accuracy (@see enum gapm_clk_acc) + uint8_t clk_acc; + /// Advertiser address + struct gap_bdaddr addr; + /// Only valid for a periodic sync transfer sync, else ignore + uint16_t serv_data; +}; + +/// Read local or peer address +/*@TRACE*/ +struct gapm_get_ral_addr_cmd +{ + /// GAPM request operation: + /// - GAPM_GET_RAL_LOC_ADDR: Get resolving local address + /// - GAPM_GET_RAL_PEER_ADDR: Get resolving peer address + uint8_t operation; + /// Peer device identity + struct gap_bdaddr peer_identity; +}; + +/// Set content of either white list or resolving list or periodic advertiser list command (common part) +struct gapm_list_set_cmd +{ + /// GAPM request operation: + /// - GAPM_SET_WHITE_LIST: Set white list content + /// - GAPM_SET_RAL: Set resolving list content + /// - GAPM_SET_PAL: Set periodic advertiser list content + uint8_t operation; + /// Number of entries to be added in the list. 0 means that list content has to be cleared + uint8_t size; +}; + +/// Set content of white list +/*@TRACE*/ +struct gapm_list_set_wl_cmd +{ + /// GAPM request operation: + /// - GAPM_SET_WHITE_LIST: Set white list content + uint8_t operation; + /// Number of entries to be added in the list. 0 means that list content has to be cleared + uint8_t size; + /// List of entries to be added in the list + struct gap_bdaddr wl_info[__ARRAY_EMPTY]; +}; + +/// Set content of resolving list command +/*@TRACE*/ +struct gapm_list_set_ral_cmd +{ + /// GAPM request operation: + /// - GAPM_SET_RAL: Set resolving list content + uint8_t operation; + /// Number of entries to be added in the list. 0 means that list content has to be cleared + uint8_t size; + /// List of entries to be added in the list + struct gap_ral_dev_info ral_info[__ARRAY_EMPTY]; +}; + +/// Set content of periodic advertiser list command +/*@TRACE*/ +struct gapm_list_set_pal_cmd +{ + /// GAPM request operation: + /// - GAPM_SET_PAL: Set periodic advertiser list content + uint8_t operation; + /// Number of entries to be added in the list. 0 means that list content has to be cleared + uint8_t size; + /// List of entries to be added in the list + struct gapm_period_adv_addr_cfg pal_info[__ARRAY_EMPTY]; +}; + +/*@TRACE + @trc_ref gapm_operation + gapm_list_set_cmd = gapm_u_list_set +*/ +union gapm_u_list_set +{ + uint8_t operation; + + //@trc_union operation == GAPM_SET_WL + struct gapm_list_set_wl_cmd list_set_wl_cmd; + //@trc_union operation == GAPM_SET_RAL + struct gapm_list_set_ral_cmd list_set_ral_cmd; + //@trc_union operation == GAPM_SET_PAL + struct gapm_list_set_pal_cmd list_set_pal_cmd; +}; + +/// List Size indication event +/*@TRACE*/ +struct gapm_list_size_ind +{ + /// Operation code, indicate list for which size has been read + /// - GAPM_SET_WHITE_LIST + /// - GAPM_SET_RAL + /// - GAPM_SET_PAL + uint8_t operation; + /// List size + uint8_t size; +}; + +/// Maximum advertising data length indication event +/*@TRACE*/ +struct gapm_max_adv_data_len_ind +{ + /// Maximum advertising data length supported by controller + uint16_t length; +}; + +/// Number of available advertising sets indication event +/*@TRACE*/ +struct gapm_nb_adv_sets_ind +{ + /// Number of available advertising sets + uint8_t nb_adv_sets; +}; + +/// Indicate the transmit powers supported by the controller +/*@TRACE*/ +struct gapm_dev_tx_pwr_ind +{ + /// Minimum TX power + int8_t min_tx_pwr; + /// Maximum TX power + int8_t max_tx_pwr; +}; + +/// Indicate the RF path compensation values +/*@TRACE*/ +struct gapm_dev_rf_path_comp_ind +{ + /// RF TX path compensation + uint16_t tx_path_comp; + /// RF RX path compensation + uint16_t rx_path_comp; +}; + +/// Indicate that an unknown message has been received +/*@TRACE*/ +struct gapm_unknown_msg_ind +{ + /// Unknown message id + kernel_msg_id_t unknown_msg_id; +}; + +/// Control reception or not of Periodic Advertising Report in a Periodic Advertising Sync activity +/*@TRACE*/ +struct gapm_per_adv_report_ctrl_cmd +{ + /// GAPM request operation: + /// - GAPM_PER_ADV_REPORT_CTRL: Enable / Disable reception of periodic advertising report + uint8_t operation; + /// Activity identifier + uint8_t actv_idx; + /// True to enable reception of periodic advertising report, false to disable + uint8_t enable; +}; + +/// Control capturing IQ samples from the Constant Tone Extension of periodic advertising packets +/*@TRACE*/ +struct gapm_per_sync_iq_sampling_ctrl_cmd +{ + /// GAPM request operation: + /// - GAPM_PER_SYNC_IQ_SAMPLING_CTRL: Enable / Disable IQ sampling + uint8_t operation; + /// Activity identifier + uint8_t actv_idx; + /// True to enable IQ sampling, false to disable + uint8_t enable; + /// Slot durations (1: 1us | 2: 2us) + uint8_t slot_dur; + /// Max sampled CTEs + uint8_t max_sampl_cte; + /// Length of switching pattern + uint8_t switching_pattern_len; + /// Antenna IDs + uint8_t antenna_id[__ARRAY_EMPTY]; +}; + +/// Indicate reception of a IQ Report event over a periodic advertising sync activity +/*@TRACE*/ +struct gapm_per_adv_iq_report_ind +{ + /// Activity identifier + uint8_t actv_idx; + /// Data channel index + uint8_t channel_idx; + /// RSSI (in 0.1 dBm) + int16_t rssi; + /// RSSI antenna ID + uint8_t rssi_antenna_id; + /// CTE type (0: AOA | 1: AOD-1us | 2: AOD-2us) (@see enum gap_cte_type) + uint8_t cte_type; + /// Slot durations (1: 1us | 2: 2us) + uint8_t slot_dur; + /// Packet status + uint8_t pkt_status; + /// Periodic Adv Event Counter + uint16_t pa_evt_cnt; + /// Number of samples + uint8_t nb_samples; + /// I/Q sample + struct gap_iq_sample sample[__ARRAY_EMPTY]; +}; + +/// Control CTE transmission in a periodic advertising activity +/*@TRACE*/ +struct gapm_per_adv_cte_tx_ctl_cmd +{ + /// GAPM request operation: + /// - GAPM_PER_ADV_CTE_TX_CTL: Control CTE transmission in a periodic advertising activity + uint8_t operation; + /// Activity identifier + uint8_t actv_idx; + /// True to enable CTE transmission, false to disable + uint8_t enable; +}; + +/// Request to renew all currently used random private addresses (non-resolvable or resolvable) +/// For internal use only +/*@TRACE*/ +struct gapm_addr_renew_cmd +{ + /// GAPM request operation: + /// - GAPM_RENEW_ADDR: Renew random private addresses + uint8_t operation; + /// Activity index, used by GAPM ADDR state machine in order to remind for which activity + /// a new address has been generated + uint8_t actv_idx; + /// Index of first created initiating/scanning for which address has been renewed, + /// any initiating/scanning met after shall use the same address if it uses a random + /// address + uint8_t init_scan_actv_idx; +}; + +/// Debug I/Q sample control +/*@TRACE*/ +struct gapm_dbg_iq_ctrl +{ + /// I-sample control + /// 0: up-count from 0x01 + /// 1: down-count from 0xFF + /// 2: Fixed value 0x00 + /// 3: PRBS pattern + /// 4..0xFF: Fixed value + uint8_t i; + /// Q-sample control + /// 0: up-count from 0x01 + /// 1: down-count from 0xFF + /// 2: Fixed value 0x00 + /// 3: PRBS pattern + /// 4..0xFF: Fixed value + uint8_t q; +}; +/// Configure the Debug Platform I&Q Sampling generator +/*@TRACE*/ +struct gapm_dbg_iqgen_cfg_cmd +{ + + /// GAPM request operation: + /// - GAPM_DBG_IQGEN_CFG: Configure the Debug Platform I&Q Sampling generator + uint8_t operation; + /// Number of antenna patterns + uint8_t nb_antenna; + /// Antenna switch/sample control + /// bit[0]: 0: up-sweep; 1: up-down sweep (internal switching mode) + /// bit[1]: 0: 1us intervals; 1: 2us intervals (internal switching mode) + /// bit[2]: 0: internal switching mode; 1: baseband switching mode + uint8_t mode; + /// I/Q sample control + struct gapm_dbg_iq_ctrl iq_ctrl[__ARRAY_EMPTY]; +}; + +/* + * MACROS + **************************************************************************************** + */ + +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/// @} GAPM_TASK + +#endif /* _GAPM_TASK_H_ */ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/api/gattc_task.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/api/gattc_task.h new file mode 100755 index 0000000..6254226 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/api/gattc_task.h @@ -0,0 +1,842 @@ +/** + **************************************************************************************** + * + * @file gattc_task.h + * + * @brief Header file - GATTCTASK. + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + +#ifndef GATTC_TASK_H_ +#define GATTC_TASK_H_ + +/** + **************************************************************************************** + * @addtogroup GATTCTASK Task + * @ingroup GATTC + * @brief Handles ALL messages to/from GATT Controller block. + * + * The GATTCTASK is responsible for managing the messages coming from + * the attribute layer and host-level layers for dedicated connection. + * The task includes services and characteristic discovery, configuration exchanges + * and attribute value access operations (reading, writing, notification and indication). + * + * Messages may originate from @ref ATTC "ATTC", @ref ATTS "ATTS", @ref GAP "GAP" + * and Application. + * + * @{ + **************************************************************************************** + */ +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "att.h" +#include "gap.h" +#include "rwip_task.h" // Task definitions +#include "compiler.h" +#include +#include "kernel_msg.h" + +/* + * DEFINES + **************************************************************************************** + */ + +/// GATT Task messages +/*@TRACE*/ +enum gattc_msg_id +{ + /* Default event */ + /// Command Complete event + GATTC_CMP_EVT = MSG_ID(GATTC, 0x00), + + /* ATTRIBUTE CLIENT */ + /// Server configuration request + GATTC_EXC_MTU_CMD = MSG_ID(GATTC, 0x01), + /// Indicate that the ATT MTU has been updated (negotiated) + GATTC_MTU_CHANGED_IND = MSG_ID(GATTC, 0x02), + + /*Discover All Services */ + /*Discover Services by Service UUID*/ + /*Find Included Services*/ + /*Discover Characteristics by UUID*/ + /*Discover All Characteristics of a Service*/ + /*Discover All Characteristic Descriptors*/ + /// Discovery command + GATTC_DISC_CMD = MSG_ID(GATTC, 0x03), + /* GATT -> HL: Events to Upper layer */ + /*Discover All Services*/ + /// Discovery services indication + GATTC_DISC_SVC_IND = MSG_ID(GATTC, 0x04), + /*Find Included Services*/ + /// Discover included services indication + GATTC_DISC_SVC_INCL_IND = MSG_ID(GATTC, 0x05), + /*Discover All Characteristics of a Service*/ + /// Discover characteristic indication + GATTC_DISC_CHAR_IND = MSG_ID(GATTC, 0x06), + /*Discover All Characteristic Descriptors*/ + /// Discovery characteristic descriptor indication + GATTC_DISC_CHAR_DESC_IND = MSG_ID(GATTC, 0x07), + + /*Read Value*/ + /*Read Using UUID*/ + /*Read Long Value*/ + /*Read Multiple Values*/ + /// Read command + GATTC_READ_CMD = MSG_ID(GATTC, 0x08), + /// Read response + GATTC_READ_IND = MSG_ID(GATTC, 0x09), + + /*Write without response*/ + /*Write without response with Authentication*/ + /*Write Characteristic Value*/ + /*Signed Write Characteristic Value*/ + /*Write Long Characteristic Value*/ + /*Characteristic Value Reliable Write*/ + /*Write Characteristic Descriptors*/ + /*Write Long Characteristic Descriptors*/ + /*Characteristic Value Reliable Write*/ + /// Write command request + GATTC_WRITE_CMD = MSG_ID(GATTC, 0x0A), + + /* Cancel / Execute pending write operations */ + /// Execute write characteristic request + GATTC_EXECUTE_WRITE_CMD = MSG_ID(GATTC, 0x0B), + + /* Reception of an indication or notification from peer device. */ + /// peer device triggers an event (notification) + GATTC_EVENT_IND = MSG_ID(GATTC, 0x0C), + /// peer device triggers an event that requires a confirmation (indication) + GATTC_EVENT_REQ_IND = MSG_ID(GATTC, 0x0D), + /// Confirm reception of event (trigger a confirmation message) + GATTC_EVENT_CFM = MSG_ID(GATTC, 0x0E), + + /// Registration to peer device events (Indication/Notification). + GATTC_REG_TO_PEER_EVT_CMD = MSG_ID(GATTC, 0x0F), + + /* -------------------------- ATTRIBUTE SERVER ------------------------------- */ + /*Notify Characteristic*/ + /*Indicate Characteristic*/ + /// send an event to peer device + GATTC_SEND_EVT_CMD = MSG_ID(GATTC, 0x10), + + + /* Indicate that read operation is requested. */ + /// Read command indicated to upper layers. + GATTC_READ_REQ_IND = MSG_ID(GATTC, 0x13), + /// REad command confirmation from upper layers. + GATTC_READ_CFM = MSG_ID(GATTC, 0x14), + + /* Indicate that write operation is requested. */ + /// Write command indicated to upper layers. + GATTC_WRITE_REQ_IND = MSG_ID(GATTC, 0x15), + /// Write command confirmation from upper layers. + GATTC_WRITE_CFM = MSG_ID(GATTC, 0x16), + + /* Indicate that write operation is requested. */ + /// Request Attribute info to upper layer - could be trigger during prepare write + GATTC_ATT_INFO_REQ_IND = MSG_ID(GATTC, 0x17), + /// Attribute info from upper layer confirmation + GATTC_ATT_INFO_CFM = MSG_ID(GATTC, 0x18), + + /* ----------------------- SERVICE DISCOVERY PROCEDURE --------------------------- */ + /// Service Discovery command + GATTC_SDP_SVC_DISC_CMD = MSG_ID(GATTC, 0x19), + /// Service Discovery indicate that a service has been found. + GATTC_SDP_SVC_IND = MSG_ID(GATTC, 0x1A), + + /* -------------------------- TRANSACTION ERROR EVENT ----------------------------- */ + /// Transaction Timeout Error Event no more transaction will be accepted + GATTC_TRANSACTION_TO_ERROR_IND = MSG_ID(GATTC, 0x1B), + /// Indication to the task that sends the unknown message + GATTC_UNKNOWN_MSG_IND = MSG_ID(GATTC, 0x1C), + + /* --------------------------------- ROBUST CACHE --------------------------------- */ + /// Command used to read peer database hash + GATTC_READ_DB_HASH_CMD = MSG_ID(GATTC, 0x20), + /// Provide value of the peer database hash + GATTC_DB_HASH_IND = MSG_ID(GATTC, 0x21), + /// Command used to enable Robust database caching + /// (Register to service changed, Set client supported features and read database hash) + GATTC_ROBUST_DB_CACHE_EN_CMD = MSG_ID(GATTC, 0x22), + /// Informs that peer database updated and need to be refreshed + /// This also means that no more indication/notification will be received till database hash isn't read + GATTC_DB_CACHE_OUT_OF_SYNC_IND = MSG_ID(GATTC, 0x23), + /// Informs that peer device database updated using service changed indication + GATTC_SVC_CHG_REQ_IND = MSG_ID(GATTC, 0x24), + /// Message used to confirm that database updated is understood by application + GATTC_SVC_CHG_CFM = MSG_ID(GATTC, 0x25), + + /* ----------------------------------- GATT INFO ---------------------------------- */ + /// Provide information about GATT for current connection that can be reuse on another connection + GATTC_CON_INFO_IND = MSG_ID(GATTC, 0x28), + + /* ------------------------------- INTERNAL API ----------------------------------- */ + /// Client Response timeout indication + GATTC_CLIENT_RTX_IND = MSG_ID(GATTC, 0x40), + /// Server indication confirmation timeout indication + GATTC_SERVER_RTX_IND = MSG_ID(GATTC, 0x41), +}; + + +/// request operation type - application interface +/*@TRACE*/ +enum gattc_operation +{ + /* Attribute Client Flags */ + /* No Operation (if nothing has been requested) */ + /* ************************************************ */ + /// No operation + GATTC_NO_OP = 0x00, + + /* Operation flags for MTU Exchange */ + /* ************************************************ */ + /// Perform MTU exchange + GATTC_MTU_EXCH = 0x01, + + /* Operation flags for discovery operation */ + /* ************************************************ */ + /// Discover all services + GATTC_DISC_ALL_SVC = 0x02, + /// Discover services by UUID + GATTC_DISC_BY_UUID_SVC = 0x03, + /// Discover included services + GATTC_DISC_INCLUDED_SVC = 0x04, + /// Discover all characteristics + GATTC_DISC_ALL_CHAR = 0x05, + /// Discover characteristic by UUID + GATTC_DISC_BY_UUID_CHAR = 0x06, + /// Discover characteristic descriptor + GATTC_DISC_DESC_CHAR = 0x07, + + /* Operation flags for reading attributes */ + /* ************************************************ */ + /// Read attribute + GATTC_READ = 0x08, + /// Read long attribute + GATTC_READ_LONG = 0x09, + /// Read attribute by UUID + GATTC_READ_BY_UUID = 0x0A, + /// Read multiple attribute + GATTC_READ_MULTIPLE = 0x0B, + + /* Operation flags for writing/modifying attributes */ + /* ************************************************ */ + /// Write attribute + GATTC_WRITE = 0x0C, + /// Write no response + GATTC_WRITE_NO_RESPONSE = 0x0D, + /// Write signed + GATTC_WRITE_SIGNED = 0x0E, + /// Execute write + GATTC_EXEC_WRITE = 0x0F, + + /* Operation flags for registering to peer device */ + /* events */ + /* ************************************************ */ + /// Register to peer device events + GATTC_REGISTER = 0x10, + /// Unregister from peer device events + GATTC_UNREGISTER = 0x11, + + /* Operation flags for sending events to peer device*/ + /* ************************************************ */ + /// Send an attribute notification + GATTC_NOTIFY = 0x12, + /// Send an attribute indication + GATTC_INDICATE = 0x13, + + /* Service Discovery Procedure */ + /* ************************************************ */ + /// Search specific service + GATTC_SDP_DISC_SVC = 0x15, + /// Search for all services + GATTC_SDP_DISC_SVC_ALL = 0x16, + /// Cancel Service Discovery Procedure + GATTC_SDP_DISC_CANCEL = 0x17, + + /* Robust Cache */ + /* ************************************************ */ + /// Read peer database hash + GATTC_READ_DB_HASH = 0x20, + /// Enable Robust database cache feature + GATTC_ROBUST_DB_CACHE_EN = 0x21, + + /* Internal API */ + /* ************************************************ */ + /// Send a service changed indication + GATTC_SVC_CHANGED = 0x40, +}; + +/// Service Discovery Attribute type +/*@TRACE*/ +enum gattc_sdp_att_type +{ + /// No Attribute Information + GATTC_SDP_NONE, + /// Included Service Information + GATTC_SDP_INC_SVC, + /// Characteristic Declaration + GATTC_SDP_ATT_CHAR, + /// Attribute Value + GATTC_SDP_ATT_VAL, + /// Attribute Descriptor + GATTC_SDP_ATT_DESC, +}; + +/// Command complete event data structure +struct gattc_op_cmd +{ + /// GATT request type + uint8_t operation; + /// operation sequence number + uint16_t seq_num; +}; + +/// Command complete event data structure +/*@TRACE*/ +struct gattc_cmp_evt +{ + /// GATT request type + uint8_t operation; + /// Status of the request + uint8_t status; + /// operation sequence number - provided when operation is started + uint16_t seq_num; +}; + + +/// Service Discovery Command Structure +/*@TRACE*/ +struct gattc_exc_mtu_cmd +{ + /// GATT request type + uint8_t operation; + /// operation sequence number + uint16_t seq_num; +}; + +/// Indicate that the ATT MTU has been updated (negotiated) +/*@TRACE*/ +struct gattc_mtu_changed_ind +{ + /// Exchanged MTU value + uint16_t mtu; + /// operation sequence number + uint16_t seq_num; +}; + +/// Service Discovery Command Structure +/*@TRACE*/ +struct gattc_disc_cmd +{ + /// GATT request type + uint8_t operation; + /// UUID length + uint8_t uuid_len; + /// operation sequence number + uint16_t seq_num; + /// start handle range + uint16_t start_hdl; + /// start handle range + uint16_t end_hdl; + /// UUID + uint8_t uuid[__ARRAY_EMPTY]; +}; + + +/// Discover Service indication Structure +/*@TRACE*/ +struct gattc_disc_svc_ind +{ + /// start handle + uint16_t start_hdl; + /// end handle + uint16_t end_hdl; + /// UUID length + uint8_t uuid_len; + /// service UUID + uint8_t uuid[__ARRAY_EMPTY]; +}; + +/// Discover Service indication Structure +/*@TRACE*/ +struct gattc_disc_svc_incl_ind +{ + /// element handle + uint16_t attr_hdl; + /// start handle + uint16_t start_hdl; + /// end handle + uint16_t end_hdl; + /// UUID length + uint8_t uuid_len; + /// included service UUID + uint8_t uuid[__ARRAY_EMPTY]; +}; + +/// Discovery All Characteristic indication Structure +/*@TRACE*/ +struct gattc_disc_char_ind +{ + /// database element handle + uint16_t attr_hdl; + /// pointer attribute handle to UUID + uint16_t pointer_hdl; + /// properties + uint8_t prop; + /// UUID length + uint8_t uuid_len; + /// characteristic UUID + uint8_t uuid[__ARRAY_EMPTY]; +}; + +/// Discovery Characteristic Descriptor indication Structure +/*@TRACE*/ +struct gattc_disc_char_desc_ind +{ + /// database element handle + uint16_t attr_hdl; + /// UUID length + uint8_t uuid_len; + /// Descriptor UUID + uint8_t uuid[__ARRAY_EMPTY]; +}; + + +/// Simple Read (GATTC_READ or GATTC_READ_LONG) +/*@TRACE + gattc_read = gattc_read_simple + gattc_read_long = gattc_read_simple*/ +struct gattc_read_simple +{ + /// attribute handle + uint16_t handle; + /// start offset in data payload + uint16_t offset; + /// Length of data to read (0 = read all) + uint16_t length; +}; + +/// Read by UUID: search UUID and read it's characteristic value (GATTC_READ_BY_UUID) +/// Note: it doesn't perform an automatic read long. +/*@TRACE*/ +struct gattc_read_by_uuid +{ + /// Start handle + uint16_t start_hdl; + /// End handle + uint16_t end_hdl; + /// Size of UUID + uint8_t uuid_len; + /// UUID value + uint8_t uuid[__ARRAY_EMPTY]; +}; + +/// Read Multiple short characteristic (GATTC_READ_MULTIPLE) +/*@TRACE*/ +struct gattc_read_multiple +{ + /// attribute handle + uint16_t handle; + /// Known Handle length (shall be != 0) + uint16_t len; +}; + +/// request union according to read type +/*@TRACE + @trc_ref gattc_operation + */ +union gattc_read_req +{ + /// Simple Read (GATTC_READ or GATTC_READ_LONG) + //@trc_union parent.operation == GATTC_READ or parent.operation == GATTC_READ_LONG + struct gattc_read_simple simple; + /// Read by UUID (GATTC_READ_BY_UUID) + //@trc_union parent.operation == GATTC_READ_BY_UUID + struct gattc_read_by_uuid by_uuid; + /// Read Multiple short characteristic (GATTC_READ_MULTIPLE) + //@trc_union parent.operation == GATTC_READ_MULTIPLE + struct gattc_read_multiple multiple[1]; +}; + +/// Read command (Simple, Long, Multiple, or by UUID) +/*@TRACE*/ +struct gattc_read_cmd +{ + /// request type + uint8_t operation; + /// number of read (only used for multiple read) + uint8_t nb; + /// operation sequence number + uint16_t seq_num; + /// request union according to read type + union gattc_read_req req; +}; + +/// Attribute value read indication +/*@TRACE*/ +struct gattc_read_ind +{ + /// Attribute handle + uint16_t handle; + /// Read offset + uint16_t offset; + /// Read length + uint16_t length; + /// Handle value + uint8_t value[__ARRAY_EMPTY]; +}; + +/// Write peer attribute value command +/*@TRACE*/ +struct gattc_write_cmd +{ + /// Request type + uint8_t operation; + /// Perform automatic execution + /// (if false, an ATT Prepare Write will be used this shall be use for reliable write) + bool auto_execute; + /// operation sequence number + uint16_t seq_num; + /// Attribute handle + uint16_t handle; + /// Write offset + uint16_t offset; + /// Write length + uint16_t length; + /// Internal write cursor shall be initialized to 0 + uint16_t cursor; + /// Value to write + uint8_t value[__ARRAY_EMPTY]; +}; + +/// Write peer attribute value command +/*@TRACE*/ +struct gattc_execute_write_cmd +{ + /// Request type + uint8_t operation; + + /// [True = perform/False cancel] pending write operations + bool execute; + /// operation sequence number + uint16_t seq_num; +}; +/// peer device triggers an event (notification) +/*@TRACE*/ +struct gattc_event_ind +{ + /// Event Type + uint8_t type; + /// Data length + uint16_t length; + /// Attribute handle + uint16_t handle; + /// Event Value + uint8_t value[__ARRAY_EMPTY]; +}; + +/// peer device triggers an event that requires a confirmation (indication) +/*@TRACE*/ +struct gattc_event_req_ind +{ + /// Event Type + uint8_t type; + /// Data length + uint16_t length; + /// Attribute handle + uint16_t handle; + /// Event Value + uint8_t value[__ARRAY_EMPTY]; +}; + +/// Confirm reception of event (trigger a confirmation message) +/*@TRACE*/ +struct gattc_event_cfm +{ + /// Attribute handle + uint16_t handle; +}; + +/// Register to peer device events command +/*@TRACE*/ +struct gattc_reg_to_peer_evt_cmd +{ + /// Request type + uint8_t operation; + /// operation sequence number + uint16_t seq_num; + /// attribute start handle + uint16_t start_hdl; + /// attribute end handle + uint16_t end_hdl; +}; + +/// Send an event to peer device +/*@TRACE*/ +struct gattc_send_evt_cmd +{ + /// Request type (notification / indication) + uint8_t operation; + /// operation sequence number + uint16_t seq_num; + /// characteristic handle + uint16_t handle; + /// length of packet to send + uint16_t length; + /// data value + uint8_t value[__ARRAY_EMPTY]; +}; + +/// Inform that attribute value is requested by lower layers. +/*@TRACE*/ +struct gattc_read_req_ind +{ + /// Handle of the attribute that has to be read + uint16_t handle; +}; + +/// Confirm Read Request requested by GATT to profile +/*@TRACE*/ +struct gattc_read_cfm +{ + /// Handle of the attribute read + uint16_t handle; + /// Data length read + uint16_t length; + /// Status of read command execution by upper layers + uint8_t status; + /// attribute data value + uint8_t value[__ARRAY_EMPTY]; +}; + +/// Inform that a modification of database has been requested by peer device. +/*@TRACE*/ +struct gattc_write_req_ind +{ + /// Handle of the attribute that has to be written + uint16_t handle; + /// offset at which the data has to be written + uint16_t offset; + /// Data length to be written + uint16_t length; + /// Data to be written in attribute database + uint8_t value[__ARRAY_EMPTY]; +}; + +/// Confirm modification of database from upper layer when requested by peer device. +/*@TRACE*/ +struct gattc_write_cfm +{ + /// Handle of the attribute written + uint16_t handle; + /// Status of write command execution by upper layers + uint8_t status; +}; + +/// Request Attribute info to upper layer - could be trigger during prepare write +/*@TRACE*/ +struct gattc_att_info_req_ind +{ + /// Handle of the attribute for which info are requested + uint16_t handle; +}; + +/// Attribute info from upper layer confirmation +/*@TRACE*/ +struct gattc_att_info_cfm +{ + /// Handle of the attribute + uint16_t handle; + /// Current length of the attribute + uint16_t length; + /// use to know if it's possible to modify the attribute + /// can contains authorization or application error code. + uint8_t status; +}; + + +/// Service Discovery command +/*@TRACE*/ +struct gattc_sdp_svc_disc_cmd +{ + /// GATT Request Type + /// - GATTC_SDP_DISC_SVC Search specific service + /// - GATTC_SDP_DISC_SVC_ALL Search for all services + /// - GATTC_SDP_DISC_CANCEL Cancel Service Discovery Procedure + uint8_t operation; + /// Service UUID Length + uint8_t uuid_len; + /// operation sequence number + uint16_t seq_num; + /// Search start handle + uint16_t start_hdl; + /// Search end handle + uint16_t end_hdl; + /// Service UUID + uint8_t uuid[ATT_UUID_128_LEN]; +}; + + +/// Information about included service +/*@TRACE*/ +struct gattc_sdp_include_svc +{ + /// Attribute Type + /// - GATTC_SDP_INC_SVC: Included Service Information + uint8_t att_type; + /// Included service UUID Length + uint8_t uuid_len; + /// Included Service UUID + uint8_t uuid[ATT_UUID_128_LEN]; + /// Included service Start Handle + uint16_t start_hdl; + /// Included service End Handle + uint16_t end_hdl; +}; + +/// Information about attribute characteristic +/*@TRACE*/ +struct gattc_sdp_att_char +{ + /// Attribute Type + /// - GATTC_SDP_ATT_CHAR: Characteristic Declaration + uint8_t att_type; + /// Value property + uint8_t prop; + /// Value Handle + uint16_t handle; +}; + +/// Information about attribute +/*@TRACE*/ +struct gattc_sdp_att +{ + /// Attribute Type + /// - GATTC_SDP_ATT_VAL: Attribute Value + /// - GATTC_SDP_ATT_DESC: Attribute Descriptor + uint8_t att_type; + /// Attribute UUID Length + uint8_t uuid_len; + /// Attribute UUID + uint8_t uuid[ATT_UUID_128_LEN]; +}; + +/// Attribute information +/*@TRACE + @trc_ref gattc_sdp_att_type + */ +union gattc_sdp_att_info +{ + /// Attribute Type + uint8_t att_type; + /// Information about attribute characteristic + //@trc_union att_type == GATTC_SDP_ATT_CHAR + struct gattc_sdp_att_char att_char; + /// Information about included service + //@trc_union att_type == GATTC_SDP_INC_SVC + struct gattc_sdp_include_svc inc_svc; + /// Information about attribute + //@trc_union att_type == GATTC_SDP_ATT_VAL or att_type == GATTC_SDP_ATT_DESC + struct gattc_sdp_att att; +}; + + +/// Service Discovery indicate that a service has been found. +/*@TRACE + @trc_arr info $end_hdl - $start_hdl + */ +struct gattc_sdp_svc_ind +{ + /// Service UUID Length + uint8_t uuid_len; + /// Service UUID + uint8_t uuid[ATT_UUID_128_LEN]; + /// Service start handle + uint16_t start_hdl; + /// Service end handle + uint16_t end_hdl; + /// attribute information present in the service + /// (length = end_hdl - start_hdl) + union gattc_sdp_att_info info[__ARRAY_EMPTY]; +}; + +/// Indicate that an unknown message has been received +/*@TRACE*/ +struct gattc_unknown_msg_ind +{ + /// Unknown message id + kernel_msg_id_t unknown_msg_id; +}; + +/// Command used to enable Robust database caching +/// (Register to service changed, Set client supported features and read database hash) +/*@TRACE*/ +struct gattc_robust_db_cache_en_cmd +{ + /// GATT Request Type + /// - GATTC_ROBUST_DB_CACHE_EN Enable Robust database caching + uint8_t operation; + /// operation sequence number + uint16_t seq_num; +}; + +/// Command used to read peer database hash +/*@TRACE*/ +struct gattc_read_db_hash_cmd +{ + /// GATT Request Type + /// - GATTC_READ_DB_HASH Read peer database hash + uint8_t operation; + /// operation sequence number + uint16_t seq_num; +}; + +/// Provide value of the peer database hash +/*@TRACE*/ +struct gattc_db_hash_ind +{ + /// Database Hash + uint8_t hash[GAP_KEY_LEN]; +}; + +/// Informs that peer device database updated using service changed indication +/*@TRACE + @trc_arr info $end_hdl - $start_hdl + */ +struct gattc_svc_chg_req_ind +{ + /// Start handle + uint16_t start_handle; + /// End Handle + uint16_t end_handle; +}; + +/// Provide information about GATT for current connection that can be reuse on another connection +/*@TRACE*/ +struct gattc_con_info_ind +{ + // GATT Client Side + /// Peer GATT Service Start handle + uint16_t gatt_start_handle; + /// Peer GATT Service End Handle + uint16_t gatt_end_handle; + /// Peer Service Change value handle + uint16_t svc_chg_handle; + + // GATT Service Side + /// Client bond data information (@see enum gapc_cli_info) + uint8_t cli_info; + /// Client supported features (@see enum gapc_cli_feat) + uint8_t cli_feat; +}; + + +/// @} GATTCTASK +#endif // GATTC_TASK_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/api/gattm_task.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/api/gattm_task.h new file mode 100755 index 0000000..82c1444 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/api/gattm_task.h @@ -0,0 +1,465 @@ +/** + **************************************************************************************** + * + * @file gattm_task.h + * + * @brief Header file - GATTMTASK. + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + +#ifndef GATTM_TASK_H_ +#define GATTM_TASK_H_ + +/** + **************************************************************************************** + * @addtogroup GATTMTASK Task + * @ingroup GATTM + * @brief Handles ALL GATT block operations not related to a connection. + * + * The GATTMTASK is responsible for managing internal attribute database and state of + * GATT controller which manage GATT block operations related to a connection. + * + * Messages may originate from @ref ATTM "ATTM", @ref GAP "GAP" and Application. + * + * @{ + **************************************************************************************** + */ +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_task.h" // Task definitions +#include "att.h" +#include "gap.h" +#include "kernel_msg.h" + +/* + * DEFINES + **************************************************************************************** + */ + + +/// GATT Task messages +/*@TRACE*/ +enum gattm_msg_id +{ + /* Database Management */ + /// Add service in database request + GATTM_ADD_SVC_REQ = MSG_ID(GATTM, 0x00), + /// Add service in database response + GATTM_ADD_SVC_RSP = MSG_ID(GATTM, 0x01), + + /* Service management */ + /// Get permission settings of service request + GATTM_SVC_GET_PERMISSION_REQ = MSG_ID(GATTM, 0x02), + /// Get permission settings of service response + GATTM_SVC_GET_PERMISSION_RSP = MSG_ID(GATTM, 0x03), + /// Set permission settings of service request + GATTM_SVC_SET_PERMISSION_REQ = MSG_ID(GATTM, 0x04), + /// Set permission settings of service response + GATTM_SVC_SET_PERMISSION_RSP = MSG_ID(GATTM, 0x05), + + /* Attribute Manipulation */ + /// Get permission settings of attribute request + GATTM_ATT_GET_PERMISSION_REQ = MSG_ID(GATTM, 0x06), + /// Get permission settings of attribute response + GATTM_ATT_GET_PERMISSION_RSP = MSG_ID(GATTM, 0x07), + /// Set permission settings of attribute request + GATTM_ATT_SET_PERMISSION_REQ = MSG_ID(GATTM, 0x08), + /// Set permission settings of attribute response + GATTM_ATT_SET_PERMISSION_RSP = MSG_ID(GATTM, 0x09), + + /// Get attribute value request + GATTM_ATT_GET_VALUE_REQ = MSG_ID(GATTM, 0x0A), + /// Get attribute value response + GATTM_ATT_GET_VALUE_RSP = MSG_ID(GATTM, 0x0B), + /// Set attribute value request + GATTM_ATT_SET_VALUE_REQ = MSG_ID(GATTM, 0x0C), + /// Set attribute value response + GATTM_ATT_SET_VALUE_RSP = MSG_ID(GATTM, 0x0D), + /// Indication to the task that sends the unknown message + GATTM_UNKNOWN_MSG_IND = MSG_ID(GATTM, 0x0E), + + /* Debug messages */ + /// DEBUG ONLY: Destroy Attribute database request + GATTM_DESTROY_DB_REQ = MSG_ID(GATTM, 0x0F), + /// DEBUG ONLY: Destroy Attribute database response + GATTM_DESTROY_DB_RSP = MSG_ID(GATTM, 0x10), + /// DEBUG ONLY: Retrieve list of services request + GATTM_SVC_GET_LIST_REQ = MSG_ID(GATTM, 0x11), + /// DEBUG ONLY: Retrieve list of services response + GATTM_SVC_GET_LIST_RSP = MSG_ID(GATTM, 0x12), + /// DEBUG ONLY: Retrieve information of attribute request + GATTM_ATT_GET_INFO_REQ = MSG_ID(GATTM, 0x13), + /// DEBUG ONLY: Retrieve information of attribute response + GATTM_ATT_GET_INFO_RSP = MSG_ID(GATTM, 0x14), + /// DEBUG ONLY: Set Service visibility request + GATTM_SVC_VISIBILITY_SET_REQ = MSG_ID(GATTM, 0x15), + /// DEBUG ONLY: Set Service visibility response + GATTM_SVC_VISIBILITY_SET_RSP = MSG_ID(GATTM, 0x16), + + /* GATT Caching */ + /// Compute hash value of the attribute database request + GATTM_ATT_DB_HASH_COMP_REQ = MSG_ID(GATTM, 0x20), + /// Compute hash value of the attribute database response + GATTM_ATT_DB_HASH_COMP_RSP = MSG_ID(GATTM, 0x21), +}; + + +/** + * Attribute Description + */ +/*@TRACE*/ +struct gattm_att_desc +{ + /** Attribute UUID (LSB First) */ + uint8_t uuid[ATT_UUID_128_LEN]; + + /** + * Attribute Permission (@see attm_perm_mask) + */ + uint16_t perm; + + + /** + * Maximum length of the attribute + * + * Note: + * For Included Services and Characteristic Declarations, this field contains targeted + * handle. + * + * For Characteristic Extended Properties, this field contains 2 byte value + * + * Not used Client Characteristic Configuration and Server Characteristic Configuration, + * this field is not used. + */ + uint16_t max_len; + + /** + * Attribute Extended permissions + * + * Extended Value permission bit field + * + * 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + * +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + * | RI |UUID_LEN |EKS | Reserved | + * +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + * + * Bit [0-11] : Reserved + * Bit [12] : Encryption key Size must be 16 bytes + * Bit [13-14]: UUID Length (0 = 16 bits, 1 = 32 bits, 2 = 128 bits, 3 = RFU) + * Bit [15] : Trigger Read Indication (0 = Value present in Database, 1 = Value not present in Database) + */ + uint16_t ext_perm; +}; + +/** + * Service description + */ +/*@TRACE + @trc_arr atts $nb_att*/ +struct gattm_svc_desc +{ + /// Attribute Start Handle (0 = dynamically allocated) + uint16_t start_hdl; + /// Task identifier that manages service + uint16_t task_id; + + /** + * 7 6 5 4 3 2 1 0 + * +----+----+----+----+----+----+----+----+ + * |SEC |UUID_LEN |DIS | AUTH |EKS | MI | + * +----+----+----+----+----+----+----+----+ + * + * Bit [0] : Task that manage service is multi-instantiated (Connection index is conveyed) + * Bit [1] : Encryption key Size must be 16 bytes + * Bit [2-3]: Service Permission (0 = NO_AUTH, 1 = UNAUTH, 2 = AUTH, 3 = Secure Connect) + * Bit [4] : Disable the service + * Bit [5-6]: UUID Length (0 = 16 bits, 1 = 32 bits, 2 = 128 bits, 3 = RFU) + * Bit [7] : Secondary Service (0 = Primary Service, 1 = Secondary Service) + */ + uint8_t perm; + + /// Number of attributes + uint8_t nb_att; + + /** Service UUID */ + uint8_t uuid[ATT_UUID_128_LEN]; + + /** + * List of attribute description present in service. + */ + struct gattm_att_desc atts[__ARRAY_EMPTY]; +}; + + +/// Add service in database request +/*@TRACE*/ +struct gattm_add_svc_req +{ + /// service description + struct gattm_svc_desc svc_desc; +}; + +/// Add service in database response +/*@TRACE*/ +struct gattm_add_svc_rsp +{ + /// Start handle of allocated service in attribute database + uint16_t start_hdl; + /// Return status of service allocation in attribute database. + uint8_t status; +}; + +/* Service management */ +/// Get permission settings of service request +/*@TRACE*/ +struct gattm_svc_get_permission_req +{ + /// Service start attribute handle + uint16_t start_hdl; +}; + +/// Get permission settings of service response +/*@TRACE*/ +struct gattm_svc_get_permission_rsp +{ + /// Service start attribute handle + uint16_t start_hdl; + /// service permission + uint8_t perm; + /// Return status + uint8_t status; +}; + +/// Set permission settings of service request +/*@TRACE*/ +struct gattm_svc_set_permission_req +{ + /// Service start attribute handle + uint16_t start_hdl; + /// service permission + uint8_t perm; +}; + +/// Set permission settings of service response +/*@TRACE*/ +struct gattm_svc_set_permission_rsp +{ + /// Service start attribute handle + uint16_t start_hdl; + /// Return status + uint8_t status; +}; + + +/* Attribute management */ +/// Get permission settings of attribute request +/*@TRACE*/ +struct gattm_att_get_permission_req +{ + /// Handle of the attribute + uint16_t handle; +}; + +/// Get permission settings of attribute response +/*@TRACE*/ +struct gattm_att_get_permission_rsp +{ + /// Handle of the attribute + uint16_t handle; + /// Attribute permission + uint16_t perm; + /// Extended Attribute permission + uint16_t ext_perm; + /// Return status + uint8_t status; +}; + +/// Set permission settings of attribute request +/*@TRACE*/ +struct gattm_att_set_permission_req +{ + /// Handle of the attribute + uint16_t handle; + /// Attribute permission + uint16_t perm; + /// Extended Attribute permission + uint16_t ext_perm; +}; + +/// Set permission settings of attribute response +/*@TRACE*/ +struct gattm_att_set_permission_rsp +{ + /// Handle of the attribute + uint16_t handle; + /// Return status + uint8_t status; +}; + + +/// Get attribute value request +/*@TRACE*/ +struct gattm_att_get_value_req +{ + /// Handle of the attribute + uint16_t handle; +}; + +/// Get attribute value response +/*@TRACE*/ +struct gattm_att_get_value_rsp +{ + /// Handle of the attribute + uint16_t handle; + /// Attribute value length + uint16_t length; + /// Return status + uint8_t status; + /// Attribute value + uint8_t value[__ARRAY_EMPTY]; +}; + +/// Set attribute value request +/*@TRACE*/ +struct gattm_att_set_value_req +{ + /// Handle of the attribute + uint16_t handle; + /// Attribute value length + uint16_t length; + /// Attribute value + uint8_t value[__ARRAY_EMPTY]; +}; + +/// Set attribute value response +/*@TRACE*/ +struct gattm_att_set_value_rsp +{ + /// Handle of the attribute + uint16_t handle; + /// Return status + uint8_t status; +}; + +/// Indicate that an unknown message has been received +/*@TRACE*/ +struct gattm_unknown_msg_ind +{ + /// Unknown message id + kernel_msg_id_t unknown_msg_id; +}; + +/// DEBUG ONLY: Destroy Attribute database request +/*@TRACE*/ +struct gattm_destroy_db_req +{ + /// New Gap Start Handle + uint16_t gap_hdl; + /// New Gatt Start Handle + uint16_t gatt_hdl; +}; + +/// DEBUG ONLY: Destroy Attribute database Response +/*@TRACE*/ +struct gattm_destroy_db_rsp +{ + /// Return status + uint8_t status; +}; + + +/// Service information +/*@TRACE*/ +struct gattm_svc_info +{ + /// Service start handle + uint16_t start_hdl; + /// Service end handle + uint16_t end_hdl; + /// Service task_id + uint16_t task_id; + /// Service permission + uint8_t perm; +}; + +/// DEBUG ONLY: Retrieve list of services response +/*@TRACE*/ +struct gattm_svc_get_list_rsp +{ + /// Return status + uint8_t status; + /// Number of services + uint8_t nb_svc; + /// Array of information about services + struct gattm_svc_info svc[__ARRAY_EMPTY]; +}; + +/// DEBUG ONLY: Retrieve information of attribute request +/*@TRACE*/ +struct gattm_att_get_info_req +{ + /// Attribute Handle + uint16_t handle; +}; + +/// DEBUG ONLY: Retrieve information of attribute response +/*@TRACE*/ +struct gattm_att_get_info_rsp +{ + /// Return status + uint8_t status; + /// UUID Length + uint8_t uuid_len; + /// Attribute Handle + uint16_t handle; + /// Attribute Permissions + uint16_t perm; + /// Extended Attribute permission + uint16_t ext_perm; + /// UUID value + uint8_t uuid[ATT_UUID_128_LEN]; +}; + +/// DEBUG ONLY: Set Service visibility request +/*@TRACE*/ +struct gattm_svc_visibility_set_req +{ + /// Service handle + uint16_t handle; + /// True to set service visible, false to hide it + bool visible; +}; + +/// DEBUG ONLY: Set Service visibility response +/*@TRACE*/ +struct gattm_svc_visibility_set_rsp +{ + /// Return status + uint8_t status; + /// Service handle + uint16_t handle; +}; + +/// Compute hash value of the attribute database response +/*@TRACE*/ +struct gattm_att_db_hash_comp_rsp +{ + /// Return status + uint8_t status; + /// Computed hash value (valid if status is GAP_ERR_NO_ERROR) + uint8_t hash[GAP_KEY_LEN]; +}; + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/// @} GATTMTASK +#endif // GATTM_TASK_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/api/l2cc_task.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/api/l2cc_task.h new file mode 100755 index 0000000..3e93984 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/api/l2cc_task.h @@ -0,0 +1,326 @@ +/** + **************************************************************************************** + * + * @file l2cc_task.h + * + * @brief Header file - L2CCTASK. + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + +#ifndef L2CC_TASK_H_ +#define L2CC_TASK_H_ + +/** + **************************************************************************************** + * @addtogroup L2CCTASK Task + * @ingroup L2CC + * @brief Handles ALL messages to/from L2CC block. + * + * The L2CC task is responsible for L2CAP attribute and security block handling. + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_task.h" // Task definitions +#include "compiler.h" + +#include +#include "kernel_msg.h" + +/* + * MACRO DEFINITIONS + **************************************************************************************** + */ + +/// Number of L2CC Deprecated messages +#define L2CC_NB_DEPRECATED_MSG (4) + +/* + * STATES + **************************************************************************************** + */ + +/* + * MESSAGES + **************************************************************************************** + */ + +/// Message API of the L2CC task +/*@TRACE*/ +enum l2cc_msg_id +{ + /// L2CAP Operation completed event + L2CC_CMP_EVT = TASK_BLE_FIRST_MSG(TASK_BLE_ID_L2CC) + L2CC_NB_DEPRECATED_MSG,//!< L2CC_CMP_EVT + + /* ************* LE Credit Based API ************* */ + /// LE credit based connection request + L2CC_LECB_CONNECT_CMD, //!< L2CC_LECB_CONNECT_CMD + /// LE credit based connection request indication + L2CC_LECB_CONNECT_REQ_IND, //!< L2CC_LECB_CONNECT_REQ_IND + /// LE credit based connection request confirmation + L2CC_LECB_CONNECT_CFM, //!< L2CC_LECB_CONNECT_CFM + /// LE credit based connection indication + L2CC_LECB_CONNECT_IND, //!< L2CC_LECB_CONNECT_IND + /// LE credit based disconnect request + L2CC_LECB_DISCONNECT_CMD, //!< L2CC_LECB_DISCONNECT_CMD + /// LE credit based disconnect indication + L2CC_LECB_DISCONNECT_IND, //!< L2CC_LECB_DISCONNECT_IND + /// LE credit based credit addition + L2CC_LECB_ADD_CMD, //!< L2CC_LECB_ADD_CMD + /// LE credit based credit addition indication + L2CC_LECB_ADD_IND, //!< L2CC_LECB_ADD_IND + + /// Send data over an LE Credit Based Connection + L2CC_LECB_SDU_SEND_CMD, //!< L2CC_LECB_SDU_SEND_CMD + /// Inform that a data packet has been received from a LE Credit Based connection. + L2CC_LECB_SDU_RECV_IND, //!< L2CC_LECB_SDU_RECV_IND + /// Indication to the task that sends the unknown message + L2CC_UNKNOWN_MSG_IND, //!< L2CC_UNKNOWN_MSG_IND + + /* ******************* Debug API ******************* */ + /// Send Debug PDU data + L2CC_DBG_PDU_SEND_CMD, //!< L2CC_DBG_PDU_SEND_CMD + /// Debug PDU data received + L2CC_DBG_PDU_RECV_IND, //!< L2CC_DBG_PDU_RECV_IND + + + /* **************** PDU Internal API ****************** */ + /// Send Legacy PDU data + L2CC_PDU_SEND_CMD, //!< L2CC_PDU_SEND_CMD + /// Legacy PDU data received + L2CC_PDU_RECV_IND, //!< L2CC_PDU_RECV_IND + + /// Timeout indication for a transaction on signaling channel + L2CC_SIGNALING_TRANS_TO_IND, //!< L2CC_SIGNALING_TRANS_TO_IND +}; + + +/// request operation type - application interface +enum l2cc_operation +{ + /* Operation Flags */ + /* No Operation (if nothing has been requested) */ + /* ************************************************ */ + /// No operation + L2CC_NO_OP = 0x00, + + /* LE Credit Based */ + /* ************************************************ */ + /// LE credit based connection request + L2CC_LECB_CONNECT, + /// LE credit based disconnection request + L2CC_LECB_DISCONNECT, + /// LE credit addition request + L2CC_LECB_CREDIT_ADD, + /// Send SDU + L2CC_LECB_SDU_SEND, + + /* Debug PDU Transmission (internal) */ + /* ************************************************ */ + /// Send a Debug PDU + L2CC_DBG_PDU_SEND, + + /* PDU Transmission (internal) */ + /* ************************************************ */ + /// Send internal LE Legacy PDU + L2CC_PDU_SEND, +}; + + +/// Default L2Cap SDU definition +/*@TRACE*/ +struct l2cc_sdu +{ + /// Channel Identifier + uint16_t cid; + /// Number of credit used + uint16_t credit; + /// SDU Data length + uint16_t length; + /// data + uint8_t data[__ARRAY_EMPTY]; +}; + + +/// Operation completed event +/*@TRACE*/ +struct l2cc_cmp_evt +{ + /// L2CC request type (@see enum l2cc_operation) + uint8_t operation; + /// Status of request. + uint8_t status; + /// Channel ID + uint16_t cid; + /// Number of peer credit used - only relevant for LECB + uint16_t credit; +}; + +/// LE credit based connection request +/*@TRACE*/ +struct l2cc_lecb_connect_cmd +{ + /// L2CC request type: + /// - L2CC_LECB_CONNECT: LE credit connection + uint8_t operation; + /// parameter used for internal usage + uint8_t pkt_id; + /// LE Protocol/Service Multiplexer + uint16_t le_psm; + /// Local Channel identifier (0: automatically allocate a free channel) + uint16_t local_cid; + /// Credit allocated for the LE Credit Based Connection + /// Shall be at least: floor(((SDU + 2) + (MPS - 1)) / MPS) + 1 + /// To be sure that 1 SDU can be fully received without requesting credits to application + uint16_t local_credit; + /// Maximum SDU size - Shall not exceed device MTU + uint16_t local_mtu; + /// Maximum Packet size - Shall not exceed device MPS + uint16_t local_mps; +}; + +/// LE credit based connection request indication +/*@TRACE*/ +struct l2cc_lecb_connect_req_ind +{ + /// LE Protocol/Service Multiplexer + uint16_t le_psm; + /// Peer Channel identifier + uint16_t peer_cid; + /// Maximum SDU size + uint16_t peer_mtu; + /// Maximum Packet size + uint16_t peer_mps; +}; + +/// LE credit based connection request confirmation +/*@TRACE*/ +struct l2cc_lecb_connect_cfm +{ + /// Peer Channel identifier + uint16_t peer_cid; + /// True to accept the incoming connection, False else + bool accept; + /// Local Channel identifier (0: automatically allocate a free channel) + uint16_t local_cid; + /// Credit allocated for the LE Credit Based Connection + /// Shall be at least: floor(((SDU + 2) + (MPS - 1)) / MPS) + 1 + /// To be sure that 1 SDU can be fully received without requesting credits to application + uint16_t local_credit; + /// Maximum SDU size - Shall not exceed device MTU + uint16_t local_mtu; + /// Maximum Packet size - Shall not exceed device MPS + uint16_t local_mps; +}; + +/// LE credit based connection indication +/*@TRACE*/ +struct l2cc_lecb_connect_ind +{ + /// Status + uint8_t status; + /// LE Protocol/Service Multiplexer + uint16_t le_psm; + /// Local Channel identifier + uint16_t local_cid; + /// Destination Credit for the LE Credit Based Connection + uint16_t peer_credit; + /// Maximum SDU size + uint16_t peer_mtu; + /// Maximum Packet size + uint16_t peer_mps; +}; + +/// LE credit based disconnect request +/*@TRACE*/ +struct l2cc_lecb_disconnect_cmd +{ + /// L2CC request type: + /// - L2CC_LECB_DISCONNECT: LE credit disconnection + uint8_t operation; + /// parameter used for internal usage + uint8_t pkt_id; + /// Local Channel identifier + uint16_t local_cid; +}; + +/// LE credit based disconnect indication +/*@TRACE*/ +struct l2cc_lecb_disconnect_ind +{ + /// Local Channel identifier + uint16_t local_cid; + /// Reason + uint8_t reason; +}; + +/// LE credit based credit addition +/*@TRACE*/ +struct l2cc_lecb_add_cmd +{ + /// L2CC request type: + /// - L2CC_LECB_CREDIT_ADD: LE credit addition + uint8_t operation; + /// parameter used for internal usage + uint8_t pkt_id; + /// Local Channel identifier + uint16_t local_cid; + /// Credit added locally for channel identifier + uint16_t credit; +}; + +///LE credit based credit addition indication +/*@TRACE*/ +struct l2cc_lecb_add_ind +{ + /// Local Channel identifier + uint16_t local_cid; + /// Destination added credit (relative value) + uint16_t peer_added_credit; +}; + +/// Send data over an LE Credit Based Connection +/*@TRACE*/ +struct l2cc_lecb_sdu_send_cmd +{ + /// L2CC request type (@see enum l2cc_operation): + /// - L2CC_LECB_SDU_SEND: Send a SDU + uint8_t operation; + /// offset value information - for internal use only + uint16_t offset; + /// SDU information + struct l2cc_sdu sdu; +}; + +/// Inform that a data packet has been received from a LE Credit Based connection. +/*@TRACE*/ +struct l2cc_lecb_sdu_recv_ind +{ + /// Status information + uint8_t status; + /// offset value information + uint16_t offset; + /// SDU information + struct l2cc_sdu sdu; +}; + +/// Indicate that an unknown message has been received +/*@TRACE*/ +struct l2cc_unknown_msg_ind +{ + /// Unknown message id + kernel_msg_id_t unknown_msg_id; +}; + +/// @} L2CCTASK + +#endif // L2CC_TASK_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/api/rwble_hl_error.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/api/rwble_hl_error.h new file mode 100755 index 0000000..d4ccfce --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/api/rwble_hl_error.h @@ -0,0 +1,530 @@ +/** + **************************************************************************************** + * + * @file rwble_hl_error.h + * + * @brief File that contains all error codes. + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + +#ifndef RWBLE_HL_ERROR_H_ +#define RWBLE_HL_ERROR_H_ + + +/** + **************************************************************************************** + * @addtogroup ROOT + * @brief High layer error codes + * + * This module contains the primitives that allow an application accessing and running the + * BLE protocol stack + * + * @{ + **************************************************************************************** + */ + + + +/// Error code from HCI TO HL Range - from 0x90 to 0xD0 +#define RW_ERR_HCI_TO_HL(err) (((err) != 0) ? ((err) + 0x90) : (0)) + + +/// Error code from HL TO HCI Range - from 0x90 to 0xD0 +#define RW_ERR_HL_TO_HCI(err) (((err) > 0x90) ? ((err) - 0x90) : (0)) + +/** + * SMP Pairing Failed Reasons + */ +enum smp_pair_fail_reason +{ + /** + * Passkey Entry Failed (0x01) + * The user input of passkey failed, for example, the user cancelled the operation. + */ + SMP_ERROR_PASSKEY_ENTRY_FAILED = 0x01, + /** + * OOB Not Available (0x02) + * The OOB Data is not available. + */ + SMP_ERROR_OOB_NOT_AVAILABLE, + /** + * Authentication Requirements (0x03) + * The pairing procedure cannot be performed as authentication requirements cannot be + * met due to IO capabilities of one or both devices. + */ + SMP_ERROR_AUTH_REQ, + /** + * Confirm Value Failed (0x04) + * The confirm value does not match the calculated confirm value. + */ + SMP_ERROR_CONF_VAL_FAILED, + /** + * Pairing Not Supported (0x05) + * Pairing is not supported by the device. + */ + SMP_ERROR_PAIRING_NOT_SUPP, + /** + * Encryption Key Size (0x06) + * The resultant encryption key size is insufficient for the security requirements of + * this device. + */ + SMP_ERROR_ENC_KEY_SIZE, + /** + * Command Not Supported (0x07) + * The SMP command received is not supported on this device. + */ + SMP_ERROR_CMD_NOT_SUPPORTED, + /** + * Unspecified Reason (0x08) + * Pairing failed due to an unspecified reason. + */ + SMP_ERROR_UNSPECIFIED_REASON, + /** + * Repeated Attempts (0x09) + * Pairing or Authentication procedure is disallowed because too little time has elapsed + * since last pairing request or security request. + */ + SMP_ERROR_REPEATED_ATTEMPTS, + /** + * Invalid Parameters (0x0A) + * The command length is invalid or a parameter is outside of the specified range. + */ + SMP_ERROR_INVALID_PARAM, + /** + * DHKey Check Failed (0x0B) + * Indicates to the remote device that the DHKey Check value received doesn't + * match the one calculated by the local device. + */ + SMP_ERROR_DHKEY_CHECK_FAILED, + /** + * Numeric Comparison Failed (0x0C) + * Indicates that the confirm values in the numeric comparison protocol do not match. + */ + SMP_ERROR_NUMERIC_COMPARISON_FAILED, + /** + * BR/EDR pairing in progress (0x0D) + * Indicates that the pairing over the LE transport failed due to a Pairing Request sent + * over the BR/EDR transport in process. + */ + SMP_ERROR_BREDR_PAIRING_IN_PROGRESS, + /** + * Cross-transport Key Derivation/Generation not allowed (0x0E) + * + * Indicates that the BR/EDR Link Key generated on the BR/EDR transport cannot be + * used to derive and distribute keys for the LE transport. + */ + SMP_ERROR_CROSS_TRANSPORT_KEY_GENERATION_NOT_ALLOWED, +}; + +/** + * List all HL error codes + */ +enum hl_err +{ + /// No error + GAP_ERR_NO_ERROR = 0x00, + + // ---------------------------------------------------------------------------------- + // ------------------------- ATT Specific Error ------------------------------------ + // ---------------------------------------------------------------------------------- + /// No error + ATT_ERR_NO_ERROR = 0x00, + /// 0x01: Handle is invalid + ATT_ERR_INVALID_HANDLE = 0x01, + /// 0x02: Read permission disabled + ATT_ERR_READ_NOT_PERMITTED = 0x02, + /// 0x03: Write permission disabled + ATT_ERR_WRITE_NOT_PERMITTED = 0x03, + /// 0x04: Incorrect PDU + ATT_ERR_INVALID_PDU = 0x04, + /// 0x05: Authentication privilege not enough + ATT_ERR_INSUFF_AUTHEN = 0x05, + /// 0x06: Request not supported or not understood + ATT_ERR_REQUEST_NOT_SUPPORTED = 0x06, + /// 0x07: Incorrect offset value + ATT_ERR_INVALID_OFFSET = 0x07, + /// 0x08: Authorization privilege not enough + ATT_ERR_INSUFF_AUTHOR = 0x08, + /// 0x09: Capacity queue for reliable write reached + ATT_ERR_PREPARE_QUEUE_FULL = 0x09, + /// 0x0A: Attribute requested not existing + ATT_ERR_ATTRIBUTE_NOT_FOUND = 0x0A, + /// 0x0B: Attribute requested not long + ATT_ERR_ATTRIBUTE_NOT_LONG = 0x0B, + /// 0x0C: Encryption size not sufficient + ATT_ERR_INSUFF_ENC_KEY_SIZE = 0x0C, + /// 0x0D: Invalid length of the attribute value + ATT_ERR_INVALID_ATTRIBUTE_VAL_LEN = 0x0D, + /// 0x0E: Operation not fit to condition + ATT_ERR_UNLIKELY_ERR = 0x0E, + /// 0x0F: Attribute requires encryption before operation + ATT_ERR_INSUFF_ENC = 0x0F, + /// 0x10: Attribute grouping not supported + ATT_ERR_UNSUPP_GRP_TYPE = 0x10, + /// 0x11: Resources not sufficient to complete the request + ATT_ERR_INSUFF_RESOURCE = 0x11, + /// 0x12: The server requests the client to rediscover the database. + ATT_ERR_DB_OUT_OF_SYNC = 0x12, + /// 0x13: The attribute parameter value was not allowed. + ATT_ERR_VALUE_NOT_ALLOWED = 0x13, + /// 0x80: Application error (also used in PRF Errors) + ATT_ERR_APP_ERROR = 0x80, + + // ---------------------------------------------------------------------------------- + // -------------------------- L2C Specific Error ------------------------------------ + // ---------------------------------------------------------------------------------- + /// Message cannot be sent because connection lost. (disconnected) + L2C_ERR_CONNECTION_LOST = 0x30, + /// Invalid PDU length exceed MTU + L2C_ERR_INVALID_MTU_EXCEED = 0x31, + /// Invalid PDU length exceed MPS + L2C_ERR_INVALID_MPS_EXCEED = 0x32, + /// Invalid Channel ID + L2C_ERR_INVALID_CID = 0x33, + /// Invalid PDU + L2C_ERR_INVALID_PDU = 0x34, + /// Connection refused - no resources available + L2C_ERR_NO_RES_AVAIL = 0x35, + /// Connection refused - insufficient authentication + L2C_ERR_INSUFF_AUTHEN = 0x36, + /// Connection refused - insufficient authorization + L2C_ERR_INSUFF_AUTHOR = 0x37, + /// Connection refused - insufficient encryption key size + L2C_ERR_INSUFF_ENC_KEY_SIZE = 0x38, + /// Connection Refused - insufficient encryption + L2C_ERR_INSUFF_ENC = 0x39, + /// Connection refused - LE_PSM not supported + L2C_ERR_LEPSM_NOT_SUPP = 0x3A, + /// No more credit + L2C_ERR_INSUFF_CREDIT = 0x3B, + /// Command not understood by peer device + L2C_ERR_NOT_UNDERSTOOD = 0x3C, + /// Credit error, invalid number of credit received + L2C_ERR_CREDIT_ERROR = 0x3D, + /// Channel identifier already allocated + L2C_ERR_CID_ALREADY_ALLOC = 0x3E, + /// Unknown PDU + L2C_ERR_UNKNOWN_PDU = 0x3F, + + + // ---------------------------------------------------------------------------------- + // -------------------------- GAP Specific Error ------------------------------------ + // ---------------------------------------------------------------------------------- + /// Invalid parameters set + GAP_ERR_INVALID_PARAM = 0x40, + /// Problem with protocol exchange, get unexpected response + GAP_ERR_PROTOCOL_PROBLEM = 0x41, + /// Request not supported by software configuration + GAP_ERR_NOT_SUPPORTED = 0x42, + /// Request not allowed in current state. + GAP_ERR_COMMAND_DISALLOWED = 0x43, + /// Requested operation canceled. + GAP_ERR_CANCELED = 0x44, + /// Requested operation timeout. + GAP_ERR_TIMEOUT = 0x45, + /// Link connection lost during operation. + GAP_ERR_DISCONNECTED = 0x46, + /// Search algorithm finished, but no result found + GAP_ERR_NOT_FOUND = 0x47, + /// Request rejected by peer device + GAP_ERR_REJECTED = 0x48, + /// Problem with privacy configuration + GAP_ERR_PRIVACY_CFG_PB = 0x49, + /// Duplicate or invalid advertising data + GAP_ERR_ADV_DATA_INVALID = 0x4A, + /// Insufficient resources + GAP_ERR_INSUFF_RESOURCES = 0x4B, + /// Unexpected Error + GAP_ERR_UNEXPECTED = 0x4C, + /// Feature mismatch + GAP_ERR_MISMATCH = 0x4D, + + // ---------------------------------------------------------------------------------- + // ------------------------- GATT Specific Error ------------------------------------ + // ---------------------------------------------------------------------------------- + /// Problem with ATTC protocol response + GATT_ERR_INVALID_ATT_LEN = 0x50, + /// Error in service search + GATT_ERR_INVALID_TYPE_IN_SVC_SEARCH = 0x51, + /// Invalid write data + GATT_ERR_WRITE = 0x52, + /// Signed write error + GATT_ERR_SIGNED_WRITE = 0x53, + /// No attribute client defined + GATT_ERR_ATTRIBUTE_CLIENT_MISSING = 0x54, + /// No attribute server defined + GATT_ERR_ATTRIBUTE_SERVER_MISSING = 0x55, + /// Permission set in service/attribute are invalid + GATT_ERR_INVALID_PERM = 0x56, + + // ---------------------------------------------------------------------------------- + // ------------------------- SMP Specific Error ------------------------------------- + // ---------------------------------------------------------------------------------- + // SMP Protocol Errors detected on local device + /// The user input of pass key failed, for example, the user canceled the operation. + SMP_ERROR_LOC_PASSKEY_ENTRY_FAILED = 0x61, + /// The OOB Data is not available. + SMP_ERROR_LOC_OOB_NOT_AVAILABLE = 0x62, + /// The pairing procedure cannot be performed as authentication requirements cannot be met + /// due to IO capabilities of one or both devices. + SMP_ERROR_LOC_AUTH_REQ = 0x63, + /// The confirm value does not match the calculated confirm value. + SMP_ERROR_LOC_CONF_VAL_FAILED = 0x64, + /// Pairing is not supported by the device. + SMP_ERROR_LOC_PAIRING_NOT_SUPP = 0x65, + /// The resultant encryption key size is insufficient for the security requirements of + /// this device. + SMP_ERROR_LOC_ENC_KEY_SIZE = 0x66, + /// The SMP command received is not supported on this device. + SMP_ERROR_LOC_CMD_NOT_SUPPORTED = 0x67, + /// Pairing failed due to an unspecified reason. + SMP_ERROR_LOC_UNSPECIFIED_REASON = 0x68, + /// Pairing or Authentication procedure is disallowed because too little time has elapsed + /// since last pairing request or security request. + SMP_ERROR_LOC_REPEATED_ATTEMPTS = 0x69, + /// The command length is invalid or a parameter is outside of the specified range. + SMP_ERROR_LOC_INVALID_PARAM = 0x6A, + /// Indicates to the remote device that the DHKey Check value received doesn't + /// match the one calculated by the local device. + SMP_ERROR_LOC_DHKEY_CHECK_FAILED = 0x6B, + /// Indicates that the confirm values in the numeric comparison protocol do not match. + SMP_ERROR_LOC_NUMERIC_COMPARISON_FAILED = 0x6C, + /// Indicates that the pairing over the LE transport failed due to a Pairing Request sent + /// over the BR/EDR transport in process. + SMP_ERROR_LOC_BREDR_PAIRING_IN_PROGRESS = 0x6D, + /// Indicates that the BR/EDR Link Key generated on the BR/EDR transport cannot be + /// used to derive and distribute keys for the LE transport. + SMP_ERROR_LOC_CROSS_TRANSPORT_KEY_GENERATION_NOT_ALLOWED = 0x6E, + // SMP Protocol Errors detected by remote device + /// The user input of passkey failed, for example, the user canceled the operation. + SMP_ERROR_REM_PASSKEY_ENTRY_FAILED = 0x71, + /// The OOB Data is not available. + SMP_ERROR_REM_OOB_NOT_AVAILABLE = 0x72, + /// The pairing procedure cannot be performed as authentication requirements cannot be + /// met due to IO capabilities of one or both devices. + SMP_ERROR_REM_AUTH_REQ = 0x73, + /// The confirm value does not match the calculated confirm value. + SMP_ERROR_REM_CONF_VAL_FAILED = 0x74, + /// Pairing is not supported by the device. + SMP_ERROR_REM_PAIRING_NOT_SUPP = 0x75, + /// The resultant encryption key size is insufficient for the security requirements of + /// this device. + SMP_ERROR_REM_ENC_KEY_SIZE = 0x76, + /// The SMP command received is not supported on this device. + SMP_ERROR_REM_CMD_NOT_SUPPORTED = 0x77, + /// Pairing failed due to an unspecified reason. + SMP_ERROR_REM_UNSPECIFIED_REASON = 0x78, + /// Pairing or Authentication procedure is disallowed because too little time has elapsed + /// since last pairing request or security request. + SMP_ERROR_REM_REPEATED_ATTEMPTS = 0x79, + /// The command length is invalid or a parameter is outside of the specified range. + SMP_ERROR_REM_INVALID_PARAM = 0x7A, + /// Indicates to the remote device that the DHKey Check value received doesn't + /// match the one calculated by the local device. + SMP_ERROR_REM_DHKEY_CHECK_FAILED = 0x7B, + /// Indicates that the confirm values in the numeric comparison protocol do not match. + SMP_ERROR_REM_NUMERIC_COMPARISON_FAILED = 0x7C, + /// Indicates that the pairing over the LE transport failed due to a Pairing Request sent + /// over the BR/EDR transport in process. + SMP_ERROR_REM_BREDR_PAIRING_IN_PROGRESS = 0x7D, + /// Indicates that the BR/EDR Link Key generated on the BR/EDR transport cannot be + /// used to derive and distribute keys for the LE transport. + SMP_ERROR_REM_CROSS_TRANSPORT_KEY_GENERATION_NOT_ALLOWED = 0x7E, + // SMP Errors triggered by local device + /// The provided resolvable address has not been resolved. + SMP_ERROR_ADDR_RESOLV_FAIL = 0x20, + /// The Signature Verification Failed + SMP_ERROR_SIGN_VERIF_FAIL = 0x21, + /// The encryption procedure failed because the slave device didn't find the LTK + /// needed to start an encryption session. + SMP_ERROR_ENC_KEY_MISSING = 0x22, + /// The encryption procedure failed because the slave device doesn't support the + /// encryption feature. + SMP_ERROR_ENC_NOT_SUPPORTED = 0x23, + /// A timeout has occurred during the start encryption session. + SMP_ERROR_ENC_TIMEOUT = 0x24, + + // ---------------------------------------------------------------------------------- + //------------------------ Profiles specific error codes ---------------------------- + // ---------------------------------------------------------------------------------- + /// Application Error + PRF_APP_ERROR = 0x80, + /// Invalid parameter in request + PRF_ERR_INVALID_PARAM = 0x81, + /// Inexistent handle for sending a read/write characteristic request + PRF_ERR_INEXISTENT_HDL = 0x82, + /// Discovery stopped due to missing attribute according to specification + PRF_ERR_STOP_DISC_CHAR_MISSING = 0x83, + /// Too many SVC instances found -> protocol violation + PRF_ERR_MULTIPLE_SVC = 0x84, + /// Discovery stopped due to found attribute with incorrect properties + PRF_ERR_STOP_DISC_WRONG_CHAR_PROP = 0x85, + /// Too many Char. instances found-> protocol violation + PRF_ERR_MULTIPLE_CHAR = 0x86, + /// Attribute write not allowed + PRF_ERR_NOT_WRITABLE = 0x87, + /// Attribute read not allowed + PRF_ERR_NOT_READABLE = 0x88, + /// Request not allowed + PRF_ERR_REQ_DISALLOWED = 0x89, + /// Notification Not Enabled + PRF_ERR_NTF_DISABLED = 0x8A, + /// Indication Not Enabled + PRF_ERR_IND_DISABLED = 0x8B, + /// Feature not supported by profile + PRF_ERR_FEATURE_NOT_SUPPORTED = 0x8C, + /// Read value has an unexpected length + PRF_ERR_UNEXPECTED_LEN = 0x8D, + /// Disconnection occurs + PRF_ERR_DISCONNECTED = 0x8E, + /// Procedure Timeout + PRF_ERR_PROC_TIMEOUT = 0x8F, + /// Client characteristic configuration improperly configured + PRF_CCCD_IMPR_CONFIGURED = 0xFD, + /// Procedure already in progress + PRF_PROC_IN_PROGRESS = 0xFE, + /// Out of Range + PRF_OUT_OF_RANGE = 0xFF, + + // ---------------------------------------------------------------------------------- + //-------------------- LL Error codes conveyed to upper layer ----------------------- + // ---------------------------------------------------------------------------------- + /// Unknown HCI Command + LL_ERR_UNKNOWN_HCI_COMMAND = 0x91, + /// Unknown Connection Identifier + LL_ERR_UNKNOWN_CONNECTION_ID = 0x92, + /// Hardware Failure + LL_ERR_HARDWARE_FAILURE = 0x93, + /// BT Page Timeout + LL_ERR_PAGE_TIMEOUT = 0x94, + /// Authentication failure + LL_ERR_AUTH_FAILURE = 0x95, + /// Pin code missing + LL_ERR_PIN_MISSING = 0x96, + /// Memory capacity exceed + LL_ERR_MEMORY_CAPA_EXCEED = 0x97, + /// Connection Timeout + LL_ERR_CON_TIMEOUT = 0x98, + /// Connection limit Exceed + LL_ERR_CON_LIMIT_EXCEED = 0x99, + /// Synchronous Connection limit exceed + LL_ERR_SYNC_CON_LIMIT_DEV_EXCEED = 0x9A, + /// ACL Connection exits + LL_ERR_ACL_CON_EXISTS = 0x9B, + /// Command Disallowed + LL_ERR_COMMAND_DISALLOWED = 0x9C, + /// Connection rejected due to limited resources + LL_ERR_CONN_REJ_LIMITED_RESOURCES = 0x9D, + /// Connection rejected due to security reason + LL_ERR_CONN_REJ_SECURITY_REASONS = 0x9E, + /// Connection rejected due to unacceptable BD Addr + LL_ERR_CONN_REJ_UNACCEPTABLE_BDADDR = 0x9F, + /// Connection rejected due to Accept connection timeout + LL_ERR_CONN_ACCEPT_TIMEOUT_EXCEED = 0xA0, + /// Not Supported + LL_ERR_UNSUPPORTED = 0xA1, + /// invalid parameters + LL_ERR_INVALID_HCI_PARAM = 0xA2, + /// Remote user terminate connection + LL_ERR_REMOTE_USER_TERM_CON = 0xA3, + /// Remote device terminate connection due to low resources + LL_ERR_REMOTE_DEV_TERM_LOW_RESOURCES = 0xA4, + /// Remote device terminate connection due to power off + LL_ERR_REMOTE_DEV_POWER_OFF = 0xA5, + /// Connection terminated by local host + LL_ERR_CON_TERM_BY_LOCAL_HOST = 0xA6, + /// Repeated attempts + LL_ERR_REPEATED_ATTEMPTS = 0xA7, + /// Pairing not Allowed + LL_ERR_PAIRING_NOT_ALLOWED = 0xA8, + /// Unknown PDU Error + LL_ERR_UNKNOWN_LMP_PDU = 0xA9, + /// Unsupported remote feature + LL_ERR_UNSUPPORTED_REMOTE_FEATURE = 0xAA, + /// Sco Offset rejected + LL_ERR_SCO_OFFSET_REJECTED = 0xAB, + /// SCO Interval Rejected + LL_ERR_SCO_INTERVAL_REJECTED = 0xAC, + /// SCO air mode Rejected + LL_ERR_SCO_AIR_MODE_REJECTED = 0xAD, + /// Invalid LMP parameters + LL_ERR_INVALID_LMP_PARAM = 0xAE, + /// Unspecified error + LL_ERR_UNSPECIFIED_ERROR = 0xAF, + /// Unsupported LMP Parameter value + LL_ERR_UNSUPPORTED_LMP_PARAM_VALUE = 0xB0, + /// Role Change Not allowed + LL_ERR_ROLE_CHANGE_NOT_ALLOWED = 0xB1, + /// LMP Response timeout + LL_ERR_LMP_RSP_TIMEOUT = 0xB2, + /// LMP Collision + LL_ERR_LMP_COLLISION = 0xB3, + /// LMP Pdu not allowed + LL_ERR_LMP_PDU_NOT_ALLOWED = 0xB4, + /// Encryption mode not accepted + LL_ERR_ENC_MODE_NOT_ACCEPT = 0xB5, + /// Link Key Cannot be changed + LL_ERR_LINK_KEY_CANT_CHANGE = 0xB6, + /// Quality of Service not supported + LL_ERR_QOS_NOT_SUPPORTED = 0xB7, + /// Error, instant passed + LL_ERR_INSTANT_PASSED = 0xB8, + /// Pairing with unit key not supported + LL_ERR_PAIRING_WITH_UNIT_KEY_NOT_SUP = 0xB9, + /// Transaction collision + LL_ERR_DIFF_TRANSACTION_COLLISION = 0xBA, + /// Unacceptable parameters + LL_ERR_QOS_UNACCEPTABLE_PARAM = 0xBC, + /// Quality of Service rejected + LL_ERR_QOS_REJECTED = 0xBD, + /// Channel class not supported + LL_ERR_CHANNEL_CLASS_NOT_SUP = 0xBE, + /// Insufficient security + LL_ERR_INSUFFICIENT_SECURITY = 0xBF, + /// Parameters out of mandatory range + LL_ERR_PARAM_OUT_OF_MAND_RANGE = 0xC0, + /// Role switch pending + LL_ERR_ROLE_SWITCH_PEND = 0xC2, + /// Reserved slot violation + LL_ERR_RESERVED_SLOT_VIOLATION = 0xC4, + /// Role Switch fail + LL_ERR_ROLE_SWITCH_FAIL = 0xC5, + /// Error, EIR too large + LL_ERR_EIR_TOO_LARGE = 0xC6, + /// Simple pairing not supported by host + LL_ERR_SP_NOT_SUPPORTED_HOST = 0xC7, + /// Host pairing is busy + LL_ERR_HOST_BUSY_PAIRING = 0xC8, + /// Controller is busy + LL_ERR_CONTROLLER_BUSY = 0xCA, + /// Unacceptable connection initialization + LL_ERR_UNACCEPTABLE_CONN_INT = 0xCB, + /// Direct Advertising Timeout + LL_ERR_DIRECT_ADV_TO = 0xCC, + /// Connection Terminated due to a MIC failure + LL_ERR_TERMINATED_MIC_FAILURE = 0xCD, + /// Connection failed to be established + LL_ERR_CONN_FAILED_TO_BE_EST = 0xCE, + /// MAC Connection Failed + LL_ERR_MAC_CONN_FAILED = 0xCF, + /// Coarse Clock Adjustment Rejected but Will Try to Adjust Using Clock Dragging + LL_ERR_CCA_REJ_USE_CLOCK_DRAG = 0xD0, + /// Type0 Submap Not Defined + LL_ERR_TYPE0_SUBMAP_NOT_DEFINED = 0xD1, + /// Unknown Advertising Identifier + LL_ERR_UNKNOWN_ADVERTISING_ID = 0xD2, + /// Limit Reached + LL_ERR_LIMIT_REACHED = 0xD3, + /// Operation Cancelled by Host + LL_ERR_OPERATION_CANCELED_BY_HOST = 0xD4, + /// Packet Too Long + LL_ERR_PKT_TOO_LONG = 0xD5, +}; + +/// @} RWBLE_HL_ERROR_H + +#endif // RWBLE_HL_ERROR_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/inc/attm.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/inc/attm.h new file mode 100755 index 0000000..1c6b34b --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/inc/attm.h @@ -0,0 +1,432 @@ +/** + **************************************************************************************** + * + * @file attm.h + * + * @brief Header file - ATTM. + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + +#ifndef ATTM_H_ +#define ATTM_H_ + +/** + **************************************************************************************** + * @addtogroup ATTM Attribute Manager + * @ingroup ATT + * @brief Attribute Manager + * + * The ATTM is the attribute manager of the Attribute Profile block and + * is responsible for managing messages and providing generic attribute + * functionalities to @ref ATTC "ATTC" and @ref ATTS "ATTS". + * + * + * @{ + * + **************************************************************************************** + */ + + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_config.h" +#include +#include + +#include "common_error.h" +#include "att.h" +#include "kernel_task.h" + +/* + * DEFINES + **************************************************************************************** + */ + +/// update attribute permission on specific handle +#define ATTMDB_UPDATE_PERM(handle, access, right)\ + attm_att_update_perm(handle, (PERM_MASK_ ## access), PERM(access, right)) + +#define ATTMDB_UPDATE_PERM_VAL(handle, access, val)\ + attm_att_update_perm(handle, (PERM_MASK_ ## access), ((val) << (PERM_POS_ ## access))) + + + +/* + * DATA STRUCTURES + **************************************************************************************** + */ + +/// Internal 16bits UUID service description +struct attm_desc +{ + /// 16 bits UUID LSB First + uint16_t uuid; + /// Attribute Permissions (@see enum attm_perm_mask) + uint16_t perm; + /// Attribute Extended Permissions (@see enum attm_value_perm_mask) + uint16_t ext_perm; + /// Attribute Max Size + /// note: for characteristic declaration contains handle offset + /// note: for included service, contains target service handle + uint16_t max_size; +}; + + +/// Internal 128bits UUID service description +struct attm_desc_128 +{ + /// 128 bits UUID LSB First + uint8_t uuid[ATT_UUID_128_LEN]; + /// Attribute Permissions (@see enum attm_perm_mask) + uint16_t perm; + /// Attribute Extended Permissions (@see enum attm_value_perm_mask) + uint16_t ext_perm; + /// Attribute Max Size + /// note: for characteristic declaration contains handle offset + /// note: for included service, contains target service handle + uint16_t max_size; +}; + + + +#if (BLE_CENTRAL || BLE_PERIPHERAL) +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + + +/** + **************************************************************************************** + * @brief Compare if two UUIDs matches + * + * @param[in] uuid_a UUID A value + * @param[in] uuid_a_len UUID A length + * @param[in] uuid_b UUID B value + * @param[in] uuid_b_len UUID B length + * + * @return true if UUIDs matches, false otherwise + **************************************************************************************** + */ +bool attm_uuid_comp(const uint8_t *uuid_a, uint8_t uuid_a_len, const uint8_t *uuid_b, uint8_t uuid_b_len); + + +/** + **************************************************************************************** + * @brief Check if two UUIDs matches (2nd UUID is a 16 bits UUID with LSB First) + * + * @param[in] uuid_a UUID A value + * @param[in] uuid_a_len UUID A length + * @param[in] uuid_b UUID B 16 bit value + * + * @return true if UUIDs matches, false otherwise + **************************************************************************************** + */ +bool attm_uuid16_comp(const uint8_t *uuid_a, uint8_t uuid_a_len, uint16_t uuid_b); + + +/** + **************************************************************************************** + * @brief Convert UUID value to 128 bit UUID + * + * @param[out] uuid128 converted 32-bit Bluetooth UUID to 128-bit UUID + * @param[in] uuid UUID to convert to 128-bit UUID + * @param[in] uuid_len UUID length + * + **************************************************************************************** + */ +void attm_convert_to128(uint8_t *uuid128, const uint8_t *uuid, uint8_t uuid_len); + +/** + **************************************************************************************** + * @brief Check if it's a Bluetooth 16-bits UUID for 128-bit input + * + * @param[in] uuid 128-bit UUID + * + * @return true if uuid is a Bluetooth 16-bit UUID, false else. + **************************************************************************************** + */ +bool attm_is_bt16_uuid(const uint8_t *uuid); + +/** + **************************************************************************************** + * @brief Check if it's a Bluetooth 32 bits UUID for 128-bit input + * + * @param[in] uuid 128-bit UUID + * + * @return true if uuid is a Bluetooth 32-bits UUID, false else. + **************************************************************************************** + */ +bool attm_is_bt32_uuid(const uint8_t *uuid); + + +#if (BLE_ATTS) +/** + **************************************************************************************** + * @brief Function use to ease service database creation. + * Use @see attmdb_add_service function of attmdb module to create service database, + * then use @see attmdb_add_attribute function of attmdb module to create attributes + * according to database description array given in parameter. + * + * @note: database description array shall be const to reduce memory consumption (only ROM) + * @note: It supports only 16 bits UUIDs + * + * @note: If shdl = 0, it return handle using first available handle (shdl is + * modified); else it verifies if start handle given can be used to allocates handle range. + * + * @param[in|out] shdl Service start handle. + * @param[in] uuid Service UUID + * @param[in|out] cfg_flag Configuration Flag, each bit matches with an attribute of + * att_db (Max: 32 attributes); if the bit is set to 1, the + * attribute will be added in the service. + * @param[in] max_nb_att Number of attributes in the service + * @param[in|out] att_tbl Array which will be fulfilled with the difference between + * each characteristic handle and the service start handle. + * This array is useful if several characteristics are optional + * within the service, can be set to NULL if not needed. + * @param[in] dest_id Task ID linked to the service. This task will be notified + * each time the service content is modified by a peer device. + * @param[in|out] att_db Table containing all attributes information + * @param[in] svc_perm Service permission (@see enum attm_svc_perm_mask) + * + * @return Command status code: + * - @ref ATT_ERR_NO_ERROR: If database creation succeeds. + * - @ref ATT_ERR_INVALID_HANDLE: If start_hdl given in parameter + nb of attribute override + * some existing services handles. + * - @ref ATT_ERR_INSUFF_RESOURCE: There is not enough memory to allocate service buffer. + * or of new attribute cannot be added because all expected + * attributes already added or buffer overflow detected during + * allocation + **************************************************************************************** + */ +uint8_t attm_svc_create_db(uint16_t *shdl, uint16_t uuid, uint8_t *cfg_flag, uint8_t max_nb_att, + uint8_t *att_tbl, kernel_task_id_t const dest_id, + const struct attm_desc *att_db, uint8_t svc_perm); + + +/** + **************************************************************************************** + * @brief Function use to ease service database creation. + * Use @see attmdb_add_service function of attmdb module to create service database, + * then use @see attmdb_add_attribute function of attmdb module to create attributes + * according to database description array given in parameter. + * + * @note: database description array shall be const to reduce memory consumption (only ROM) + * @note: It supports 128, 32 and 16 bits UUIDs + * + * @note: If shdl = 0, it return handle using first available handle (shdl is + * modified); else it verifies if start handle given can be used to allocates handle range. + * + * @param[in|out] shdl Service start handle. + * @param[in] uuid Service UUID + * @param[in|out] cfg_flag Configuration Flag, each bit matches with an attribute of + * att_db (Max: 32 attributes); if the bit is set to 1, the + * attribute will be added in the service. + * @param[in] max_nb_att Number of attributes in the service + * @param[in|out] att_tbl Array which will be fulfilled with the difference between + * each characteristic handle and the service start handle. + * This array is useful if several characteristics are optional + * within the service, can be set to NULL if not needed. + * @param[in] dest_id Task ID linked to the service. This task will be notified + * each time the service content is modified by a peer device. + * @param[in|out] att_db Table containing all attributes information + * @param[in] svc_perm Service permission (@see enum attm_svc_perm_mask) + * + * @return Command status code: + * - @ref ATT_ERR_NO_ERROR: If database creation succeeds. + * - @ref ATT_ERR_INVALID_HANDLE: If start_hdl given in parameter + nb of attribute override + * some existing services handles. + * - @ref ATT_ERR_INSUFF_RESOURCE: There is not enough memory to allocate service buffer. + * or of new attribute cannot be added because all expected + * attributes already added or buffer overflow detected during + * allocation + **************************************************************************************** + */ +uint8_t attm_svc_create_db_128(uint16_t *shdl, const uint8_t* uuid, uint8_t *cfg_flag, uint8_t max_nb_att, + uint8_t *att_tbl, kernel_task_id_t const dest_id, + const struct attm_desc_128 *att_db, uint8_t svc_perm); + + +uint8_t attm_svc_create_db128(uint16_t *shdl, uint16_t uuid, uint8_t *cfg_flag, uint8_t max_nb_att, + uint8_t *att_tbl, kernel_task_id_t const dest_id, + const struct attm_desc *att_db, uint8_t svc_perm); + +/** + **************************************************************************************** + * @brief Control visibility of a service from peer device. service present in database + * but cannot be access by a peer device. + * + * @param[in] handle Service handle. + * @param[in] hide True to hide the service, False to restore visibility + * + * @return Command status code: + * - @ref ATT_ERR_NO_ERROR: If service allocation succeeds. + * - @ref ATT_ERR_INVALID_HANDLE: If start_hdl given in parameter or UUIDs value invalid + **************************************************************************************** + */ +uint8_t attmdb_svc_visibility_set(uint16_t handle, bool hide); + +/** + **************************************************************************************** + * @brief Function use to verify if several services can be allocated on a contiguous + * handle range. If this command succeed, it means that service allocation will succeed. + * + * If start_hdl = 0, it return handle using first available handle (start_hdl is + * modified); else it verifies if start handle given can be used to allocates handle range. + * + * @param[in|out] start_hdl Service start handle. + * @param[in] nb_att Number of handle to allocate (containing service handles) + * + * @return Command status code: + * - @ref ATT_ERR_NO_ERROR: If service allocation succeeds. + * - @ref ATT_ERR_INVALID_HANDLE: If start_hdl given in parameter or UUIDs value invalid + **************************************************************************************** + */ +uint8_t attm_reserve_handle_range(uint16_t* start_hdl, uint8_t nb_att); + + + +/** + **************************************************************************************** + * @brief Update attribute value + * + * Updating attribute value do not trigger any notification or indication, this shall be + * handled by GATT task. + * + * @param[in] handle Attribute handle. + * @param[in] length Size of new attribute value + * @param[in] offset Data offset of in the payload to set + * @param[in] value Attribute value payload + * + * @return Command status code: + * - @ref ATT_ERR_NO_ERROR: If attribute value update succeeds + * - @ref ATT_ERR_INVALID_HANDLE: If handle doesn't exist in database + * - @ref ATT_ERR_REQUEST_NOT_SUPPORTED: If attribute data not present in database or + * cannot be modified + * - @ref ATT_ERR_INVALID_ATTRIBUTE_VAL_LEN: If new value length exceeds maximum attribute + * value length. + * + **************************************************************************************** + */ +uint8_t attm_att_set_value(uint16_t handle, att_size_t length, att_size_t offset, uint8_t* value); + +/** + **************************************************************************************** + * @brief Retrieve attribute value + + * + * @param[in] handle Attribute handle. + * @param[out] length Size of attribute value + * @param[out] value Pointer to attribute value payload + * + * @return Command status code: + * - @ref ATT_ERR_NO_ERROR: If request succeeds + * - @ref ATT_ERR_INVALID_HANDLE: If handle doesn't exist in database + * - @ref ATT_ERR_REQUEST_NOT_SUPPORTED: If attribute data not present in database + **************************************************************************************** + */ +uint8_t attm_get_value(uint16_t handle, att_size_t* length, uint8_t** value); + + +/** + **************************************************************************************** + * @brief Update attribute permission + * + * @param[in] handle Attribute handle. + * - @ref ATT_ERR_REQUEST_NOT_SUPPORTED: If attribute data not present in database + * @param[in] perm New attribute permission + * @param[in] ext_perm New attribute extended permission + * + * @return Command status code: + * - @ref ATT_ERR_NO_ERROR: If request succeeds + * - @ref ATT_ERR_INVALID_HANDLE: If handle doesn't exist in database + * - @ref ATT_ERR_REQUEST_NOT_SUPPORTED: If attribute permission is fixed + **************************************************************************************** + */ +uint8_t attm_att_set_permission(uint16_t handle, uint16_t perm, uint16_t ext_perm); + + +/** + **************************************************************************************** + * @brief Reset some permissions bit in the Handle passed as parameter. + * + * @param[in] handle Attribute handle. + * @param[in] access_mask Access mask of permission to update + * @param[in] perm New value of the permission to update + * + * + * @return Command status code: + * - @ref ATT_ERR_NO_ERROR: If request succeeds + * - @ref ATT_ERR_INVALID_HANDLE: If handle doesn't exist in database + * - @ref ATT_ERR_REQUEST_NOT_SUPPORTED: If attribute permission is fixed + **************************************************************************************** + */ +uint8_t attm_att_update_perm(uint16_t handle, uint16_t access_mask, uint16_t perm); + +/** + **************************************************************************************** + * @brief Update attribute service permission + * + * @param[in] handle Attribute handle. + * @param[in] perm New attribute permission + * + * @return Command status code: + * - @ref ATT_ERR_NO_ERROR: If request succeeds + * - @ref ATT_ERR_INVALID_HANDLE: If handle doesn't exist in database + **************************************************************************************** + */ +uint8_t attm_svc_set_permission(uint16_t handle, uint8_t perm); + + +/** + **************************************************************************************** + * @brief Retrieve attribute service permission + * + * @param[in] handle Attribute handle. + * @param[out] perm Permission value to return + * + * @return Command status code: + * - @ref ATT_ERR_NO_ERROR: If request succeeds + * - @ref ATT_ERR_INVALID_HANDLE: If handle doesn't exist in database + **************************************************************************************** + */ +uint8_t attm_svc_get_permission(uint16_t handle, uint8_t* perm); + + +/** + **************************************************************************************** + * @brief Clear database + * + * For debug purpose only, this function clear the database and unalloc all services + * within database. + * + * This function shall be used only for qualification and tests in order to manually + * change database without modifying software. + **************************************************************************************** + */ +void attmdb_destroy(void); + +/** + **************************************************************************************** + * @brief Initialize Attribute Database (clear it) + * + * @param[in] init_type Type of initialization (@see enum rwip_init_type) + **************************************************************************************** + */ +void attm_init(uint8_t reset); +#endif // (BLE_ATTS) + +#endif // #if (BLE_CENTRAL || BLE_PERIPHERAL) +/// @} ATTM +#endif // ATTM_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/inc/gapc.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/inc/gapc.h new file mode 100755 index 0000000..6724a6f --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/inc/gapc.h @@ -0,0 +1,282 @@ +/** + **************************************************************************************** + * + * @file gapc.h + * + * @brief Generic Access Profile Controller Header. + * + * Copyright (C) RivieraWaves 2009-2016 + * + **************************************************************************************** + */ + + +#ifndef _GAPC_H_ +#define _GAPC_H_ + +/** + **************************************************************************************** + * @addtogroup GAPC Generic Access Profile Controller + * @ingroup GAP + * @brief Generic Access Profile Controller. + * + * The GAP Controller module is responsible for providing an API to the application in + * to perform GAP action related to a BLE connection (pairing, update parameters, + * disconnect ...). GAP controller is multi-instantiated, one task instance per BLE + * connection. + * + * @{ + **************************************************************************************** + */ + + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_config.h" + +#if (BLE_GAPC) + +#include "kernel_task.h" +#include "gap.h" + +/* + * DEFINES + **************************************************************************************** + */ + + +/// Operation type +enum gapc_op_type +{ + /// Operation used to manage Link (update params, get peer info) + GAPC_OP_LINK_INFO = 0x00, + + /// Operation used to manage SMP + GAPC_OP_SMP = 0x01, + + /// Operation used to manage connection update + GAPC_OP_LINK_UPD = 0x02, + + /// Max number of operations + GAPC_OP_MAX +}; + +/// Link security status. This status represents the authentication/authorization/bonding levels of the connection +enum gapc_lk_sec_req +{ + /// Link is bonded + GAPC_LK_BONDED, + /// Link is Encrypted + GAPC_LK_ENCRYPTED, + /// Link LTK Exchanged during pairing + GAPC_LK_LTK_PRESENT, +}; + +/// Information source. +enum gapc_smp_addr_src +{ + /// Local info. + GAPC_SMP_INFO_LOCAL, + /// Peer info. + GAPC_SMP_INFO_PEER, + /// Maximum info source. + GAPC_SMP_INFO_MAX +}; + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + +/// Pairing Information +struct gapc_smp_pair_info; + + +/// GAPC_SMP environment structure +struct gapc_smp_env +{ + /** + * Pairing Information - This structure is allocated at the beginning of a pairing + * or procedure. It is freed when a disconnection occurs or at the end of + * the pairing procedure. If not enough memory can be found, the procedure will fail + * with an "Unspecified Reason" error + */ + struct gapc_smp_pair_info* pair; + + /// CSRK values (Local and remote) + struct gap_sec_key csrk[GAPC_SMP_INFO_MAX]; + + /// signature counter values (Local and remote) + uint32_t sign_counter[GAPC_SMP_INFO_MAX]; + + /// Repeated Attempt Timer value + uint16_t rep_att_timer_val; + + /// Encryption key size + uint8_t key_size; + + /** + * Contains the current state of the two timers needed in the GAPC_SMP task + * Bit 0 - Is Timeout Timer running + * Bit 1 - Is Repeated Attempt Timer running + * Bit 2 - Has task reached a SMP Timeout + */ + uint8_t timer_state; + + /// State of the current procedure + uint8_t state; +}; + +/// GAP controller environment variable structure. +struct gapc_env_tag +{ + /// Request operation Kernel message + void* operation[GAPC_OP_MAX]; + + /// Source task id of requested disconnection + kernel_task_id_t disc_requester; + /// Destination task ID for asynchronous events not linked to an operation + kernel_task_id_t dest_task_id; + + /* Connection parameters to keep */ + + /// Security Management Protocol environment variables + struct gapc_smp_env smp; + + /// connection handle + uint16_t conhdl; + + /// Configuration fields (@see enum gapc_fields) + uint8_t fields; + + /// BD Address used for the link that should be kept + struct gap_bdaddr src[GAPC_SMP_INFO_MAX]; + + /// Relevant information of peer LE features 8-byte array + uint8_t features; + /// Channel Selection Algorithm + uint8_t chan_sel_algo; +}; + + + +/* + * MACROS + **************************************************************************************** + */ + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Retrieve connection index from connection handle. + * + * @param[in] conhdl Connection handle + * + * @return Return found connection index, GAP_INVALID_CONIDX if not found. + **************************************************************************************** + */ +uint8_t gapc_get_conidx(uint16_t conhdl); + +/** + **************************************************************************************** + * @brief Retrieve connection handle from connection index. + * + * @param[in] conidx Connection index + * + * @return Return found connection handle, GAP_INVALID_CONHDL if not found. + **************************************************************************************** + */ +uint16_t gapc_get_conhdl(uint8_t conidx); + +/** + **************************************************************************************** + * @brief Retrieve connection role from connection index. + * + * @param[in] conidx Connection index + * + * @return Return found connection role + **************************************************************************************** + */ +uint8_t gapc_get_role(uint8_t conidx); + +/** + **************************************************************************************** + * @brief Set resolvable address used for connection establishment as local address. + * + * @brief conidx Connection index + * @brief p_addr Pointer to the resolvable address used by either advertising activity or + * resolvable activity. + **************************************************************************************** + */ +void gapc_set_local_addr(uint8_t conidx, uint8_t *p_addr); + +/** + **************************************************************************************** + * @brief Retrieve connection address information on current link. + * + * @param[in] conidx Connection index + * @param[in] src Connection information source + * + * @return Return found connection address + **************************************************************************************** + */ +struct gap_bdaddr* gapc_get_bdaddr(uint8_t conidx, uint8_t src); + +/** + **************************************************************************************** + * @brief Get destination task id for asynchronous event, meaning events that are not + * linked to an operation. + * Note the provided connection index shall be valid (gapc_env[conidx] is not NULL) + * + * @param[in] conidx Connection Index + * + * @return ID of the destination task. + **************************************************************************************** + */ +kernel_task_id_t gapc_get_dest_task(uint8_t conidx); + +/** + **************************************************************************************** + * @brief Check if current link support security requirements. + * + * @param[in] conidx Connection index + * @param[in] sec_req Link security requirement to test + * + * @return True if link requirement is supported, False else. + **************************************************************************************** + */ +bool gapc_is_sec_set(uint8_t conidx, uint8_t sec_req); + +/** + **************************************************************************************** + * @brief Retrieve Link Security level + * + * @param[in] conidx Connection index + * + * @return Link Security level. + **************************************************************************************** + */ +uint8_t gapc_lk_sec_lvl_get(uint8_t conidx); + +/** + **************************************************************************************** + * @brief Retrieve the encryption key size of the connection + * + * @param[in] conidx Connection index + * + * @return encryption key size (size is 7 - 16 byte range) + * + **************************************************************************************** + */ +uint8_t gapc_enc_keysize_get(uint8_t conidx); + +#endif // (BLE_GAPC) +/// @} GAPC + +#endif /* _GAPC_H_ */ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/inc/gapm.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/inc/gapm.h new file mode 100755 index 0000000..b0637cb --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/inc/gapm.h @@ -0,0 +1,438 @@ +/** + **************************************************************************************** + * + * @file gapm.h + * + * @brief Generic Access Profile Manager Header. + * + * Copyright (C) RivieraWaves 2009-2016 + * + **************************************************************************************** + */ + + +#ifndef _GAPM_H_ +#define _GAPM_H_ + +/** + **************************************************************************************** + * @addtogroup GAPM Generic Access Profile Manager + * @ingroup GAP + * @brief Generic Access Profile Manager. + * + * The GAP Manager module is responsible for providing an API to the application in order + * to manage all non connected stuff such as configuring device to go in desired mode + * (discoverable, connectable, etc.) and perform required actions (scanning, connection, + * etc.). GAP Manager is also responsible of managing GAP Controller state according to + * corresponding BLE connection states. + * + * @{ + **************************************************************************************** + */ + + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_config.h" +#include "kernel_task.h" +#include "gap.h" +#include "gapm_task.h" + +/* + * DEFINES + **************************************************************************************** + */ +/// Bit checking +#define GAPM_ISBITSET(flag, mask) (((flag)&(mask)) == mask) +/// Maximum number of advertising reports from different advertisers that can be reassembled in parallel +#define GAPM_REPORT_NB_MAX (5) + +/* + * STRUCTURE DEFINITION + **************************************************************************************** + */ + +/// Contain a received fragment of advertising or scan response report +struct gapm_report_elem +{ + /// List Header + struct common_list_hdr list_hdr; + /// Data length + uint8_t data_len; + /// Data + uint8_t data[]; +}; + +/// Contain a list of fragments received for an advertising or scan response report sent +/// by a given advertiser +struct gapm_report_list +{ + /// List of received reports (@see struct gapm_report_elem) + struct common_list report_list; + /// Advertiser address + struct gap_bdaddr adv_addr; + /// Received length + uint16_t length; +}; + +/// GAP Manager activity structure (common part for advertising, scanning, +/// initiating and periodic synchronization activities) +struct gapm_actv_tag +{ + /// Function to be called for activity start + uint8_t (*cb_actv_start)(struct gapm_actv_tag *, struct gapm_activity_start_cmd *); + /// Function to be called for activity stop + void (*cb_actv_stop)(struct gapm_actv_tag *); + /// Function to be called for activity delete + void (*cb_actv_delete)(struct gapm_actv_tag *); + + /// Identifier + uint8_t idx; + /// Type (@see enum gapm_actv_type) + uint8_t type; + /// Subtype - meaning depends on activity type + /// - Advertising activity: @see enum gapm_adv_type + /// - Scanning activity: @see enum gapm_scan_type + /// - Initiating activity: @see enum gapm_init_type + /// - Periodic Synchronization activity: @see enum gapm_per_sync_type + uint8_t subtype; + /// State (@see enum gapm_actv_state) + uint8_t state; + /// Information bit field, meaning depends on activity type + uint8_t info; + /// Own address type + uint8_t own_addr_type; + /// Next expected HCI event opcode + uint16_t next_exp_opcode; + /// Task ID of task that has requested creation of the activity + kernel_task_id_t requester; + /// BD Address used by the activity (can be different if controller privacy is used and + /// application chose to use a resolvable private address) + bd_addr_t addr; +}; + +/// GAP Manager activity structure for advertising activity +struct gapm_actv_adv_tag +{ + /// Common activity parameters + struct gapm_actv_tag common; + /// Data offset for the set advertising data procedure + uint16_t data_offset; + /// Advertising mode (@see enum gapm_adv_disc_mode) + uint8_t mode; + /// Stored status + uint8_t kept_status; + /// Selected TX power + uint8_t tx_pwr; + /// Additional information (@see enum gapm_adv_add_info_bf) + uint8_t add_info; +}; + +/// GAP Manager activity structure for scanning activity +struct gapm_actv_scan_tag +{ + /// Common activity parameters + struct gapm_actv_tag common; + /// Lists containing fragments for GAPM_REPORT_NB_MAX reports that can be received in parallel + struct gapm_report_list report_lists[GAPM_REPORT_NB_MAX]; + /// Scan filtering Array + struct gap_bdaddr *p_scan_filter; +}; + +/// GAP Manager activity structure for initiating activity +struct gapm_actv_init_tag +{ + /// Common activity parameters + struct gapm_actv_tag common; + /// Initiating parameters + struct gapm_init_param init_param; + /// Number of connection to be established for automatic connection + /// -> Number of devices in the white list when GAPM_ACTIVITY_START_CMD is received + uint8_t nb_auto_conn; + /// Stored status + uint8_t kept_status; +}; + +/// GAP Manager activity structure for periodic synchronization activity +struct gapm_actv_per_sync_tag +{ + /// Common activity parameters + struct gapm_actv_tag common; + /// List of received reports fragment (@see struct gapm_report_elem) + struct common_list report_list; + /// Received length + uint16_t length; + /// Synchronization Handle + uint16_t sync_hdl; + #if (BLE_CENTRAL || BLE_PERIPHERAL) + /// Connection index where PAST sync info is expected + uint8_t conidx; + #endif // (BLE_CENTRAL || BLE_PERIPHERAL) + +}; + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Initialize Generic Access Profile Manager Module. + * + * @param[in] init_type Type of initialization (@see enum rwip_init_type) + **************************************************************************************** + */ +void gapm_init(uint8_t init_type); + + +/** + **************************************************************************************** + * @brief Retrieve Task Identifier from Task number + * (automatically update index of task in returned task id) + * + * @param task Task number + * @return Task Identifier + **************************************************************************************** + */ +kernel_task_id_t gapm_get_id_from_task(kernel_msg_id_t task); + +/** + **************************************************************************************** + * @brief Retrieve Task Number from Task Identifier + * (automatically update index of task in returned task id) + * + * @param id Task Identifier + * @return Task Number + **************************************************************************************** + */ +kernel_task_id_t gapm_get_task_from_id(kernel_msg_id_t id); + + + +#if (BLE_GAPC) + + +/** + **************************************************************************************** + * @brief A link has been disconnected, clean-up host stack for this connection. + * + * @param[in] conidx Connection Index + * @param[in] conhdl Connection Handle + * @param[in] reason Reason of the disconnection + * + **************************************************************************************** + */ +void gapm_con_cleanup(uint8_t conidx, uint16_t conhdl, uint8_t reason); + +#endif // (BLE_GAPC) + + +/** + **************************************************************************************** + * @brief Retrieve device identity key. + * + * @return Device Identity Key + **************************************************************************************** + */ +struct gap_sec_key* gapm_get_irk(void); + + +/** + **************************************************************************************** + * @brief Retrieve local public address. + * + * @return Return local public address + **************************************************************************************** + */ +bd_addr_t* gapm_get_bdaddr(void); + + + +#if (BLE_ISO_MODE_0_PROTOCOL) +/** + **************************************************************************************** + * @brief Return if LE Audio Mode 0 is supported or not + * + * @return True if supported, False else + **************************************************************************************** + */ +bool gapm_is_audio_am0_sup(void); +#endif // (BLE_ISO_MODE_0_PROTOCOL) + +/** + **************************************************************************************** + * @brief Retrieve the device address type (@see enum gapm_addr_type) + * + * @return address type + **************************************************************************************** + */ +uint8_t gapm_get_address_type(void); + + +#if (BLE_ATTS) + +/** + **************************************************************************************** + * @brief Get if preferred connection parameters present in GAP ATT database + * + * @return True if referred connection parameters present in GAP ATT database, False else + **************************************************************************************** + */ +bool gapm_is_pref_con_param_pres(void); + +/** + **************************************************************************************** + * @brief retrieve gap attribute handle from attribute index. + * + * @param[in] att_idx Attribute index + * + * @return Attribute handle + **************************************************************************************** + */ +uint16_t gapm_get_att_handle(uint8_t att_idx); + +#endif // (BLE_ATTS) + +/** + **************************************************************************************** + * @brief Retrieve if Legacy pairing is supported on local device + * + * @return True if legacy pairing is supported + **************************************************************************************** + */ +bool gapm_is_legacy_pairing_supp(void); + + +/** + **************************************************************************************** + * @brief Retrieve if Secure Connection pairing is supported on local device + * + * @return True if Secure Connection pairing is supported + **************************************************************************************** + */ +bool gapm_is_sec_con_pairing_supp(void); + + +#if (BLE_LECB) +/** + **************************************************************************************** + * @brief Check if LECB connection can be registered (established) + * + * @param[in] le_psm LE Protocol/Service Multiplexer + * @param[in] conidx Connection index for app_task computation + * @param[out] app_task Destination application/profile task + * @param[out] sec_lvl Security level requirements + * + * + * @return GAP_ERR_NOT_FOUND if LE_PSM not register, GAP_ERR_NO_ERROR else + **************************************************************************************** + */ +uint8_t gapm_le_psm_get_info(uint16_t le_psm, uint8_t conidx, kernel_task_id_t *app_task, uint8_t *sec_lvl); + + +/** + **************************************************************************************** + * @brief Check if LECB connection can be registered (established) + * + * @param[in] le_psm LE Protocol/Service Multiplexer + * @param[in] peer_con_init Info to know if connection is initiated by peer device + * + * @return L2C_ERR_NO_RES_AVAIL if all LECB link are established, GAP_ERR_NO_ERROR else + **************************************************************************************** + */ +uint8_t gapm_lecb_register(uint16_t le_psm, bool peer_con_init); + + +/** + **************************************************************************************** + * @brief Unregister an existing LECB connection + * + * @param[in] le_psm LE Protocol/Service Multiplexer + * @param[in] peer_con_init Info to know if connection is initiated by peer device + * + * @return GAP_ERR_NO_ERROR + **************************************************************************************** + */ +uint8_t gapm_lecb_unregister(uint16_t le_psm, bool peer_con_init); + +#endif // (BLE_LECB) + +/** + **************************************************************************************** + * @brief Return the maximal MTU value + * + * @param[out] Maximal MTU value + **************************************************************************************** + */ +uint16_t gapm_get_max_mtu(void); + +/** + **************************************************************************************** + * @brief Return the maximal MPS value + * + * @param[out] Maximal MPS value + **************************************************************************************** + */ +uint16_t gapm_get_max_mps(void); + +#if (RW_DEBUG) +/** + **************************************************************************************** + * @brief Check If Debug mode feature is enabled or not + * + * @return true if enabled, false else. + * + **************************************************************************************** + */ +bool gapm_dbg_mode_en(void); + +/** + **************************************************************************************** + * @brief Check If received L2CAP packet must be forwarded to the application + * + * @return true if enabled, false else. + * + **************************************************************************************** + */ +bool gapm_dbg_fwd_traffic(void); + +/** + **************************************************************************************** + * @brief Force the GAP service start handle + **************************************************************************************** + */ +void gapm_set_svc_start_hdl(uint16_t start_hdl); +#endif // (RW_DEBUG) + +/** + **************************************************************************************** + * Retrieve if current connection index is used for a discovery purpose such as + * Name discovery + * + * @param conidx Index of the specific connection + * + * @return true if connection has a discovery purpose, False else + **************************************************************************************** + */ +bool gapm_is_disc_connection(uint8_t conidx); + +/** + **************************************************************************************** + * @brief Get information about a non connected activity + * + * @param[in] actv_idx Activity Identifier + * @param[in] p_act_type Activity Type (enum gapm_actv_type) + * @param[in] p_act_sub_type Activity Sub Type, depends on activity + * @param[in] p_handle Lower Layer activity handle (adv_handle, sync_handle) + * + * @return GAP_ERR_NO_ERROR if activity exists else GAP_ERR_COMMAND_DISALLOWED + **************************************************************************************** + */ +uint8_t gapm_actv_info_get(uint8_t actv_idx, uint8_t* p_act_type, uint8_t* p_act_sub_type, uint16_t *p_handle); + +/// @} GAPM + +#endif /* _GAPM_H_ */ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/inc/gattc.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/inc/gattc.h new file mode 100755 index 0000000..1a9985b --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/inc/gattc.h @@ -0,0 +1,207 @@ +/** + **************************************************************************************** + * + * @file gattc.h + * + * @brief Header file - GATT Controller. + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + +#ifndef GATTC_H_ +#define GATTC_H_ + +/** + **************************************************************************************** + * @addtogroup GATTC Generic Attribute Profile Controller + * @ingroup GATT + * @brief Generic Attribute Profile Controller. + * + * This GATT module is responsible for providing an API for all attribute related operations + * related to a BLE connection. + * It is responsible for all the service framework activities using the Attribute protocol + * for discovering services and for reading and writing characteristic values on a peer device. + * To achieve this, the GATT interfaces with @ref ATTC "ATTC" and the @ref ATTS "ATTS". + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +/* kernel task */ +#include "rwip_config.h" +#if (BLE_GATTC) + +#include "common_list.h" + + +/* + * DEFINES + **************************************************************************************** + */ + +/// Operation type +enum gattc_op_type +{ + #if (BLE_ATTS) + /// Operation used to Server Request operations + GATTC_OP_SERVER, + #endif // (BLE_ATTS) + + #if (BLE_ATTC) + /// Operation used to Client Request operations + GATTC_OP_CLIENT, + /// Service Discovery Procedure operation + GATTC_OP_SDP, + /// Operation used to enable Client features + GATTC_OP_FEAT, + #endif // (BLE_ATTC) + + /// Max number of operations + GATTC_OP_MAX +}; + +/* + * TYPES DEFINITIONS + **************************************************************************************** + */ + +#if (BLE_ATTC) +/// Attribute Client environment variable requirements +struct attc_env +{ + /// List of ATT message used to aggregate long value in a single buffer. + struct common_list rsp_list; + /// List that contains peer device event registration + struct common_list reg_evt; + /// List that contains data for service discovery + struct common_list sdp_data; + + /// GATT Service Start handle + uint16_t gatt_start_handle; + /// Number of attributes present in GATT service + uint8_t gatt_nb_att; + /// Service Change value handle offset + uint8_t svc_chg_offset; +}; +#endif // (BLE_ATTC) + + +#if (BLE_ATTS) +/// Attribute server environment variables +struct atts_env +{ + /// This is used to merge save all the prepare write request received , + /// before receiving the execute or cancel or disconnection. + struct common_list prep_wr_req_list; + /// This list is used to put any data in order to send a response to peer device + struct common_list rsp; + /// List of PDU to process + struct common_list pdu_queue; + /// This structure is used to store in cache latest attribute read value + struct gattc_read_cfm* read_cache; + /// Number of attributes found + uint8_t nb_att_fd; + + /// Client bond data information (@see enum gattc_cli_info) + uint8_t cli_info; +}; +#endif // (BLE_ATTS) + +/// GATT controller environment variable structure. +struct gattc_env_tag +{ + /// Request operation Kernel message + void* operation[GATTC_OP_MAX]; + + #if (BLE_ATTC) + /// Client specific environment + struct attc_env client; + #endif // (BLE_ATTC) + + #if (BLE_ATTS) + /// Server specific environment + struct atts_env server; + #endif // (BLE_ATTS) + + /// Current MTU Size + uint16_t mtu_size; + + /// A transaction timeout occurs, reject next attribute commands + bool trans_timeout; + /// Used to know if MTU exchange already done. + bool mtu_exch; +}; + +/* + * MACRO DEFINITIONS + **************************************************************************************** + */ + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Created link connection parameters (from bond data) has been set, connection ready to be used. + * + * @note cli_info and cli_feat are considered only if bond == true + * + * @param[in] conidx Connection Index + * @param[in] bond Used to know if link correspond to a bonded device + * @param[in] cli_info Client bond information (@see enum gapc_cli_info) + * @param[in] cli_feat Get Peer client supported features enabled in previous link (@see enum gapc_cli_feat) + * @param[in] gatt_start_handle Peer GATT Service Start handle + * @param[in] gatt_end_handle Peer GATT Service End Handle + * @param[in] svc_chg_handle Peer Service Change value handle + **************************************************************************************** + */ +void gattc_con_enable(uint8_t conidx, bool bond, uint8_t cli_info, uint8_t cli_feat, + uint16_t gatt_start_handle, uint16_t gatt_end_handle, uint16_t svc_chg_handle); + +/** + **************************************************************************************** + * @brief Gets the negotiated MTU. This function gets the negotiated MTU. + * + * @param[in] conidx connection index + * + * @return MTU negotiated + * + **************************************************************************************** + */ +uint16_t gattc_get_mtu(uint8_t conidx); + +/** + **************************************************************************************** + * @brief Sets the negotiated MTU This function stores the negotiated MTU. + * + * @param[in] conidx connection index + * @param[in] mtu negotiated MTU + * + * @return status indicates if the MTU setting operation is successful + * + **************************************************************************************** + */ +void gattc_set_mtu(uint8_t conidx, uint16_t mtu); + +/** + **************************************************************************************** + * @brief Informs peer device database has been updated + * + * @param[in] conidx connection index + **************************************************************************************** + */ +void gattc_db_updated(uint8_t conidx); + +#endif /* (BLE_GATTC) */ + +/// @} GATTC +#endif // GATTC_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/inc/gattm.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/inc/gattm.h new file mode 100755 index 0000000..cc5fa9a --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/inc/gattm.h @@ -0,0 +1,132 @@ +/** + **************************************************************************************** + * + * @file gattm.h + * + * @brief Header file - GATT Manager. + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + +#ifndef GATTM_H_ +#define GATTM_H_ + + + +/** + **************************************************************************************** + * @addtogroup GATTM Generic Attribute Profile Manager + * @ingroup GATT + * @brief Generic Attribute Profile. + * + * The GATT manager module is responsible for providing an API for all action operations + * not related to a connection. It's responsible to managing internal database. + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +/* kernel task */ +#include "rwip_config.h" + +#if (BLE_CENTRAL || BLE_PERIPHERAL) +#include +#include + +/* + * DEFINES + **************************************************************************************** + */ + + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Initialization of the GATT manager module. + * This function performs all the initialization steps of the GATT module. + * + * @param[in] init_type Type of initialization (@see enum rwip_init_type) + * + **************************************************************************************** + */ +void gattm_init(uint8_t init_type); + + +/** + **************************************************************************************** + * @brief Initialize GATT attribute database + * + * @param[in] start_hdl Service Start Handle + * + * @return status code of attribute database initialization + * Command status code: + * - @ref ATT_ERR_NO_ERROR: If database creation succeeds. + * - @ref ATT_ERR_INVALID_HANDLE: If start_hdl given in parameter + nb of attribute override + * some existing services handles. + * - @ref ATT_ERR_INSUFF_RESOURCE: There is not enough memory to allocate service buffer. + * or of new attribute cannot be added because all expected + * attributes already add + **************************************************************************************** + */ +uint8_t gattm_init_attr(uint16_t start_hdl); + +/** + **************************************************************************************** + * @brief Initialize GATT resources for connection. + * + * @param[in] conidx connection record index + * @param[in] role device role after connection establishment + * + **************************************************************************************** + */ +void gattm_create(uint8_t conidx); +/** + **************************************************************************************** + * @brief Cleanup GATT resources for connection + * + * @param[in] conidx connection record index + * + **************************************************************************************** + */ +void gattm_cleanup(uint8_t conidx); + + +#if (BLE_ATTS) + +/** + **************************************************************************************** + * @brief Convert attribute handle to GATT database attribute index. + * + * @param[in] handle Attribute Handle + * + * @return GATT database attribute index (ATT_INVALID_IDX if not found) + **************************************************************************************** + */ +uint8_t gattm_att_hdl_to_idx(uint16_t handle); + +/** + **************************************************************************************** + * @brief Convert GATT database attribute index to attribute handle. + * + * @param[in] att_idx GATT database attribute index + * + * @return Attribute Handle (ATT_INVALID_HANDLE if not found) + **************************************************************************************** + */ +uint16_t gattm_att_idx_to_hdl(uint8_t att_idx); +#endif //(BLE_ATTS) +#endif /* (BLE_CENTRAL || BLE_PERIPHERAL) */ + +/// @} GATTM +#endif // GATTM_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/inc/l2cc.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/inc/l2cc.h new file mode 100755 index 0000000..820e8c7 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/inc/l2cc.h @@ -0,0 +1,263 @@ +/** + **************************************************************************************** + * + * @file l2cc.h + * + * @brief Header file - L2CC. + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + +#ifndef L2CC_H_ +#define L2CC_H_ + +/** + **************************************************************************************** + * @addtogroup L2CC L2CAP Controller + * @ingroup L2C + * @brief L2CAP block for data processing and per device connection + * + * The L2CC is responsible for all the data processing related + * functions of the L2CAP block per device connection. + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" + +#if (BLE_L2CC) + +#include "l2cc_task.h" +#include "l2cc_pdu.h" + +#include +#include +#include "common_list.h" +#include "kernel_task.h" + +/* + * DEFINES + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Generic way to creates and allocate a Signaling PDU message that can be then + * sent to peer device + * + * @param[in] conidx Connection Index + * @param[in] code PDU code + * @param[in] src_id Source task ID + * + * @return Pointer to the PDU payload + **************************************************************************************** + */ +#define L2CC_SIG_PDU_ALLOC(conidx, code, src_id, type) \ + ((struct type*) l2cc_pdu_alloc(conidx, L2C_CID_LE_SIGNALING, code, src_id, 0)) + +/// from PDU, retrieve the send command +#define L2CC_PDU_TO_CMD(_pdu) \ + ((struct l2cc_pdu_send_cmd*) (((uint8_t*)_pdu) - offsetof(struct l2cc_pdu_send_cmd, pdu.data.code))) + +/// from PDU, retrieve the receive indication +#define L2CC_PDU_TO_IND(_pdu) \ + ((struct l2cc_pdu_recv_ind*) (((uint8_t*)_pdu) - offsetof(struct l2cc_pdu_recv_ind, pdu.data.code))) + + +/** + **************************************************************************************** + * @brief Generic way to creates and allocate a SMP PDU message that can be then sent to + * peer device + * + * @param[in] conidx Connection Index + * @param[in] code PDU code + * @param[in] src_id Source task ID + * + * @return Pointer to the PDU payload + **************************************************************************************** + */ +#define L2CC_SMP_PDU_ALLOC(conidx, code, src_id, type) \ + ((struct type*) l2cc_pdu_alloc(conidx, L2C_CID_SECURITY, code, src_id, 0)) + + +/** + **************************************************************************************** + * @brief Generic way to creates and allocate an ATT PDU message that can be then sent to + * peer device + * + * @param[in] conidx Connection Index + * @param[in] code PDU code + * @param[in] src_id Source task ID + * + * @return Pointer to the PDU payload + **************************************************************************************** + */ +#define L2CC_ATT_PDU_ALLOC(conidx, code, src_id, type)\ + ((struct type*) l2cc_pdu_alloc(conidx, L2C_CID_ATTRIBUTE, code, src_id, 0)) + + +/** + **************************************************************************************** + * @brief Generic way to creates and allocate an ATT PDU message that can be then sent to + * peer device + * + * @param[in] conidx Connection Index + * @param[in] code PDU code + * @param[in] src_id Source task ID + * @param[in] length Dynamic payload length to allocate + * + * @return Pointer to the PDU payload + **************************************************************************************** + */ +#define L2CC_ATT_PDU_ALLOC_DYN(conidx, code, src_id, type, length)\ + ((struct type*) l2cc_pdu_alloc(conidx, L2C_CID_ATTRIBUTE, code, src_id, length)) + +/* + * INTERNAL MESSAGES API TYPES + **************************************************************************************** + */ + + + +/// Send Debug PDU data +/*@TRACE*/ +struct l2cc_dbg_pdu_send_cmd +{ + /// L2CC request type (@see enum l2cc_operation): + /// - L2CC_DBG_PDU_SEND: Send a PDU + uint8_t operation; + /// offset value information + uint16_t offset; + /// PDU Data + struct l2cc_dbg_pdu pdu; +}; + +/// Debug PDU data received +/*@TRACE*/ +struct l2cc_dbg_pdu_recv_ind +{ + /// Status information + uint8_t status; + /// offset value information + uint16_t offset; + /// PDU Data + struct l2cc_dbg_pdu pdu; +}; + +/// Send Legacy PDU data +/*@TRACE*/ +struct l2cc_pdu_send_cmd +{ + /// L2CC request type (@see enum l2cc_operation): + /// - L2CC_PDU_SEND: Send internal LE Legacy PDU + uint8_t operation; + /// offset value information + uint16_t offset; + /// PDU Data + struct l2cc_pdu pdu; +}; + + +/// Legacy PDU data received +/*@TRACE*/ +struct l2cc_pdu_recv_ind +{ + /// Status information + uint8_t status; + /// offset value information + uint16_t offset; + /// PDU Data + struct l2cc_pdu pdu; +}; + +/// Operation type +enum l2cc_op_type +{ + /// Operation used for signaling protocol message exchange + L2CC_OP_SIG = 0x00, + /// Max number of operations + L2CC_OP_MAX, +}; + +/* + * STRUCTURES + **************************************************************************************** + */ + + + +/// L2CAP environment structure +struct l2cc_env_tag +{ + /// Ongoing operation + void* operation[L2CC_OP_MAX]; + + /// Buffer in TX queue + struct common_list tx_queue; + /// Buffer currently receiving data + struct kernel_msg* rx_buffer; + #if (BLE_LECB) + /// List of LE credit based connections + struct common_list lecb_list; + #endif // (BLE_LECB) + + /// Length of PDU still expected + uint16_t rx_pdu_rem_len; + /// Number of ACL buffer waiting to be transmitted. + uint8_t nb_tx_pending; + + /// Cursor into the the received header + uint8_t rx_cursor; + /// Expected cursor header length + uint8_t rx_exp_len; + /// Temporary buffer for reception of an l2cap packet + uint8_t rx_buf[L2C_HEADER_LEN + L2C_MIN_LE_MTUSIG]; +}; + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Generic way to creates and allocate a PDU message that can be then sent to peer + * device + * + * @note use L2CC_SIG_PDU_ALLOC, L2CC_SMP_PDU_ALLOC, L2CC_ATT_PDU_ALLOC + * or L2CC_ATT_PDU_ALLOC_DYN instead of direct function call + * + * @param[in] conidx Connection Index + * @param[in] cid Channel Identifier + * @param[in] code PDU code + * @param[in] src_id Source task ID + * @param[in] length Dynamic payload length to allocate + * + * @return Generic pointer to the PDU payload + **************************************************************************************** + */ +void* l2cc_pdu_alloc(uint8_t conidx, uint16_t cid, uint8_t code, kernel_task_id_t src_id, uint16_t length); + +/** + **************************************************************************************** + * @brief Generic way to send the PDU message + * + * @param[in] pdu PDU message to send to peer device + **************************************************************************************** + */ +void l2cc_pdu_send(void* pdu); + +#endif //(BLE_L2CC) + +/// @} L2CC + +#endif // L2CC_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/inc/l2cc_pdu.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/inc/l2cc_pdu.h new file mode 100755 index 0000000..60893dc --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/inc/l2cc_pdu.h @@ -0,0 +1,1226 @@ +/** + **************************************************************************************** + * + * @file l2cc_pdu.h + * + * @brief Header file - L2CAP Controller PDU packer / unpacker + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + + +#ifndef _L2CC_PDU_H_ +#define _L2CC_PDU_H_ + +/** + **************************************************************************************** + * @addtogroup L2CC_PDU L2Cap Controller PDU generator/extractor + * @ingroup L2CC + * @brief This module is in charge to pack or unpack L2CAP packets + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "common_bt.h" +#include "gap.h" +#include "att.h" +#include "compiler.h" + +/* + * MACROS + **************************************************************************************** + */ + + +/* + * DEFINES + **************************************************************************************** + */ + +/// Minimal authorized MTU value (defined by Bluetooth SIG) +#define L2C_MIN_LE_MTUSIG (23) +/// Minimal authorized MTU value if secure connection is supported +#define L2C_MIN_LE_MTU_SEC_CON (65) + +/// L2CAP mode supported for BLE - only mode accepted +#define L2C_MODE_BASIC_L2CAP (0x00) + +/// Packet partition +#define L2C_CID_LEN (2) +#define L2C_LENGTH_LEN (2) +#define L2C_CODE_LEN (1) +#define L2C_HEADER_LEN (L2C_CID_LEN + L2C_LENGTH_LEN) +#define L2C_SDU_LEN (2) +#define L2C_LECB_HEADER_LEN (L2C_HEADER_LEN + L2C_SDU_LEN) + +/// Maximum credit +#define L2C_LECB_MAX_CREDIT 0xFFFF + + +/* result for connection parameter update response */ +#define L2C_CONN_PARAM_ACCEPT 0x0000 +#define L2C_CONN_PARAM_REJECT 0x0001 + +/* command reject reasons */ +enum l2cc_pdu_err +{ + L2C_CMD_NOT_UNDERSTOOD = 0x0000, + L2C_MTU_SIG_EXCEEDED = 0x0001, + L2C_INVALID_CID = 0x0002, +}; + +/// Check if channel ID is within the correct range +#define L2C_IS_DYNAMIC_CID(cid) ((cid >= L2C_CID_DYN_MIN) && (cid <= L2C_CID_DYN_MAX)) + +/// Check if LE PSM is within the correct range +#define L2C_IS_VALID_LEPSM(lepsm) (lepsm != L2C_LEPSM_RESERVED) + +/* + * ENUMERATIONS + **************************************************************************************** + */ + +/** L2CAP LE PSM limits */ +enum l2cc_lepsm_limits +{ + /// Reserved + L2C_LEPSM_RESERVED = 0x0000, + /// Fixed minimum range SIG assigned + L2C_LEPSM_FIXED_MIN = 0x0001, + /// Fixed maximum range SIG assigned + L2C_LEPSM_FIXED_MAX = 0x007F, + /// Dynamic minimum range SIG assigned + L2C_LEPSM_DYN_MIN = 0x0080, + /// Dynamic maximum range SIG assigned + L2C_LEPSM_DYN_MAX = 0x00FF, + /// Reserved minimum range SIG assigned + L2C_LEPSM_RSV_MIN = 0x0100, + /// Reserved maximum range SIG assigned + L2C_LEPSM_RSV_MAX = 0xFFFF, +}; + +/** L2CAP channels id */ +/*@TRACE*/ +enum l2cc_cid +{ + /// Reserved channel id + L2C_CID_RESERVED = 0x0000, + /// Attribute channel id + L2C_CID_ATTRIBUTE = 0x0004, + /// Signaling channel id + L2C_CID_LE_SIGNALING = 0x0005, + /// Security channel id + L2C_CID_SECURITY = 0x0006, + /// Dynamically allocated minimum range + L2C_CID_DYN_MIN = 0x0040, + /// Dynamically allocated maximum range + L2C_CID_DYN_MAX = 0x007F, +}; + + +/// signaling codes +/*@TRACE*/ +enum l2cc_signaling_code +{ + /// Reserved code + L2C_CODE_RESERVED = 0x00, + /// Reject request + L2C_CODE_REJECT = 0x01, + /// Connection request + L2C_CODE_CONNECTION_REQ = 0x02, + /// Connection response + L2C_CODE_CONNECTION_RESP = 0x03, + /// Configuration request + L2C_CODE_CONFIGURATION_REQ = 0x04, + /// Configuration response + L2C_CODE_CONFIGURATION_RESP = 0x05, + /// Disconnection request + L2C_CODE_DISCONNECTION_REQ = 0x06, + /// Disconnection response + L2C_CODE_DISCONNECTION_RESP = 0x07, + /// Echo request + L2C_CODE_ECHO_REQ = 0x08, + /// Echo response + L2C_CODE_ECHO_RESP = 0x09, + /// Information request + L2C_CODE_INFORMATION_REQ = 0x0A, + /// Information response + L2C_CODE_INFORMATION_RESP = 0x0B, + /// Create channel request + L2C_CODE_CREATE_CHANNEL_REQ = 0x0C, + /// Create channel response + L2C_CODE_CREATE_CHANNEL_RESP = 0x0D, + /// Move channel request + L2C_CODE_MOVE_CHANNEL_REQ = 0x0E, + /// Move channel response + L2C_CODE_MOVE_CHANNEL_RESP = 0x0F, + /// Move channel confirmation + L2C_CODE_MOVE_CHANNEL_CFM = 0x10, + /// Move channel confirmation response + L2C_CODE_MOVE_CHANNEL_CFM_RESP = 0x11, + /// Connection Parameter Update Request + L2C_CODE_CONN_PARAM_UPD_REQ = 0x12, + /// Connection Parameter Update Response + L2C_CODE_CONN_PARAM_UPD_RESP = 0x13, + /// LE Credit Based Connection request + L2C_CODE_LE_CB_CONN_REQ = 0x14, + /// LE Credit Based Connection response + L2C_CODE_LE_CB_CONN_RESP = 0x15, + /// LE Flow Control Credit + L2C_CODE_LE_FLOW_CONTROL_CREDIT = 0x16, + + /// max number of signaling codes + L2C_CODE_SIGNALING_MAX +}; + + +/// security codes +/*@TRACE*/ +enum l2cc_security_code +{ + /// Pairing Request + L2C_CODE_PAIRING_REQ = 0x01, + /// Pairing Response + L2C_CODE_PAIRING_RESP = 0x02, + /// Pairing Confirm + L2C_CODE_PAIRING_CFM = 0x03, + /// Pairing Random + L2C_CODE_PAIRING_RANDOM = 0x04, + /// Pairing Failed + L2C_CODE_PAIRING_FAILED = 0x05, + /// Encryption Information + L2C_CODE_ENCRYPTION_INF = 0x06, + /// Master Identification + L2C_CODE_MASTER_ID = 0x07, + /// Identity Information + L2C_CODE_IDENTITY_INF = 0x08, + /// Identity Address Information + L2C_CODE_ID_ADDR_INF = 0x09, + /// Signing Information + L2C_CODE_SIGNING_INF = 0x0A, + /// Security Request + L2C_CODE_SECURITY_REQ = 0x0B, + /// Pairing Public Keys + L2C_CODE_PUBLIC_KEY = 0x0C, + /// Pairing DHKey Check + L2C_CODE_DHKEY_CHECK = 0x0D, + /// Pairing Keypress Notification + L2C_CODE_KEYPRESS_NOTIFICATION = 0x0E, + /// max number of security codes + L2C_CODE_SECURITY_MAX +}; + + +/// attribute protocol PDU codes +/*@TRACE*/ +enum l2cc_attribute_code +{ + /// Error response + L2C_CODE_ATT_ERR_RSP = 0x01, + /// Exchange MTU Request + L2C_CODE_ATT_MTU_REQ = 0x02, + /// Exchange MTU Response + L2C_CODE_ATT_MTU_RSP = 0x03, + /// Find Information Request + L2C_CODE_ATT_FIND_INFO_REQ = 0x04, + /// Find Information Response + L2C_CODE_ATT_FIND_INFO_RSP = 0x05, + /// Find By Type Value Request + L2C_CODE_ATT_FIND_BY_TYPE_REQ = 0x06, + /// Find By Type Value Response + L2C_CODE_ATT_FIND_BY_TYPE_RSP = 0x07, + /// Read By Type Request + L2C_CODE_ATT_RD_BY_TYPE_REQ = 0x08, + /// Read By Type Response + L2C_CODE_ATT_RD_BY_TYPE_RSP = 0x09, + /// Read Request + L2C_CODE_ATT_RD_REQ = 0x0A, + /// Read Response + L2C_CODE_ATT_RD_RSP = 0x0B, + /// Read Blob Request + L2C_CODE_ATT_RD_BLOB_REQ = 0x0C, + /// Read Blob Response + L2C_CODE_ATT_RD_BLOB_RSP = 0x0D, + /// Read Multiple Request + L2C_CODE_ATT_RD_MULT_REQ = 0x0E, + /// Read Multiple Response + L2C_CODE_ATT_RD_MULT_RSP = 0x0F, + /// Read by Group Type Request + L2C_CODE_ATT_RD_BY_GRP_TYPE_REQ = 0x10, + /// Read By Group Type Response + L2C_CODE_ATT_RD_BY_GRP_TYPE_RSP = 0x11, + /// Write Request + L2C_CODE_ATT_WR_REQ = 0x12, + /// Write Response + L2C_CODE_ATT_WR_RSP = 0x13, + /// Write Command + L2C_CODE_ATT_WR_CMD_INFO = 0x14, + L2C_CODE_ATT_WR_CMD = 0x52, + /// Signed Write Command + L2C_CODE_ATT_SIGN_WR_CMD_INFO = 0x15, + L2C_CODE_ATT_SIGN_WR_CMD = 0xD2, + /// Prepare Write Request + L2C_CODE_ATT_PREP_WR_REQ = 0x16, + /// Prepare Write Response + L2C_CODE_ATT_PREP_WR_RSP = 0x17, + /// Execute Write Request + L2C_CODE_ATT_EXE_WR_REQ = 0x18, + /// Execute Write Response + L2C_CODE_ATT_EXE_WR_RSP = 0x19, + /// Handle Value Notification + L2C_CODE_ATT_HDL_VAL_NTF = 0x1B, + /// Handle Value Indication + L2C_CODE_ATT_HDL_VAL_IND = 0x1D, + /// Handle Value Confirmation + L2C_CODE_ATT_HDL_VAL_CFM = 0x1E, + + /// max number of security codes + L2C_CODE_ATT_MAX +}; + +/// LE Connection oriented PDU codes +enum l2cc_le_connor_code +{ + /// Data frame + L2C_CODE_CON_DATA = 0x01, + + /// max number of connection oriented codes + L2C_CODE_CON_MAX +}; + +/// Result values for LE Credit Based Connection Response +enum l2cc_cb_resp_value +{ + /// connection successful + L2C_CB_CON_SUCCESS = 0x0000, + /// Reserved + L2C_CB_CON_RSV1, + /// Connection refused - LE_PSM not supported + L2C_CB_CON_LEPSM_NOT_SUPP, + /// Reserved + L2C_CB_CON_RSV2, + /// Connection refused - no resources available + L2C_CB_CON_NO_RES_AVAIL, + /// Connection refused - insufficient authentication + L2C_CB_CON_INS_AUTH, + /// Connection refused - insufficient authorization + L2C_CB_CON_INS_AUTHOR, + /// Connection refused - insufficient encryption key size + L2C_CB_CON_INS_EKS, + /// Connection Refused - insufficient encryption + L2C_CB_CON_INS_ENCRYPTION, + + /* ESR 09 error codes */ + /// Connection Refused - invalid Source CID + L2C_CB_CON_INVALID_SRC_CID, + /// Connection Refused - Source CID already allocated + L2C_CB_CON_SRC_CID_ALREADY_ALLOC, + /// Connection Refused - Unacceptable parameters + L2C_CB_CON_UNACCEPTABLE_PARAM +}; + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + +/// Disconnection Request +/*@TRACE*/ +struct l2cc_disconnection_req +{ + /// Signaling code - 0x06 + uint8_t code; + /// Packet Identifier + uint8_t pkt_id; + /// data length + uint16_t length; + /// Destination CID + uint16_t dcid; + /// Source CID + uint16_t scid; +}; + +/// Disconnection Response +/*@TRACE*/ +struct l2cc_disconnection_resp +{ + /// Signaling code - 0x07 + uint8_t code; + /// Packet Identifier + uint8_t pkt_id; + /// data length + uint16_t length; + /// Destination CID + uint16_t dcid; + /// Source CID + uint16_t scid; +}; + +/// Connection Parameter Update Request +/*@TRACE*/ +struct l2cc_conn_param_upd_req +{ + /// Signaling code - 0x12 + uint8_t code; + /// Packet Identifier + uint8_t pkt_id; + /// data length + uint16_t length; + /// minimum value for the connection event interval + uint16_t intv_min; + /// maximum value for the connection event interval + uint16_t intv_max; + /// slave latency parameter + uint16_t latency; + /// connection timeout parameter + uint16_t timeout; +}; + +/// Connection Parameter Update Response +/*@TRACE*/ +struct l2cc_conn_param_upd_resp +{ + /// Signaling code - 0x13 + uint8_t code; + /// Packet Identifier + uint8_t pkt_id; + /// data length + uint16_t length; + /// Result field indicates the response to the Connection Parameter Update Request + /// - 0x0000 Connection Parameters accepted + /// - 0x0001 Connection Parameters rejected + uint16_t response; +}; + +/// LE Credit based connection request +/*@TRACE*/ +struct l2cc_le_cb_conn_req +{ + /// Signaling code - 0x14 + uint8_t code; + /// Packet Identifier + uint8_t pkt_id; + /// data length + uint16_t length; + /// LE Protocol/Service Multiplexer + uint16_t le_psm; + /// Source CID + uint16_t scid; + /// Maximum Transmission Unit + uint16_t mtu; + /// Maximum PDU Size + uint16_t mps; + /// Initial credits + uint16_t initial_credits; +}; + +/// LE Credit based connection response +/*@TRACE*/ +struct l2cc_le_cb_conn_resp +{ + /// Signaling code - 0x15 + uint8_t code; + /// Packet Identifier + uint8_t pkt_id; + /// data length + uint16_t length; + /// Destination CID + uint16_t dcid; + /// Maximum Transmission Unit + uint16_t mtu; + /// Maximum PDU Size + uint16_t mps; + /// Initial credits + uint16_t initial_credits; + /// Result + uint16_t result; +}; + +/// LE Flow Control Credit +/*@TRACE*/ +struct l2cc_le_flow_control_credit +{ + /// Signaling code - 0x16 + uint8_t code; + /// Packet Identifier + uint8_t pkt_id; + /// data length + uint16_t length; + /// CID + uint16_t cid; + /// Credits + uint16_t credits; +}; + +/// Command Reject +/*@TRACE*/ +struct l2cc_reject +{ + /// Signaling code - 0x01 + uint8_t code; + /// Packet Identifier + uint8_t pkt_id; + /// data length + uint16_t length; + /// The Reason field describes why the Request packet was rejected + /// - 0x0000 Command not understood + /// - 0x0001 Signaling MTU exceeded + /// - 0x0002 Invalid CID in request + uint16_t reason; + /// Optional parameters total length + uint16_t opt_len; + ///16-byte array for optional parameters + uint8_t opt[__ARRAY_EMPTY]; +}; + + +/// Pairing Request +/*@TRACE*/ +struct l2cc_pairing_req +{ + /// security code - 0x01 + uint8_t code; + /// IO Capability + uint8_t iocap; + /// OOB data flag + uint8_t oob; + /// AuthReq + uint8_t auth; + /// Maximum Encryption Key Size + uint8_t key_size; + /// Initiator Key Distribution + uint8_t ikey_dist; + /// Responder Key Distribution + uint8_t rkey_dist; +}; +/// Pairing Response +/*@TRACE*/ +struct l2cc_pairing_resp +{ + /// security code - 0x02 + uint8_t code; + /// IO Capability + uint8_t iocap; + /// OOB data flag + uint8_t oob; + /// AuthReq + uint8_t auth; + /// Maximum Encryption Key Size + uint8_t key_size; + /// Initiator Key Distribution + uint8_t ikey_dist; + /// Responder Key Distribution + uint8_t rkey_dist; +}; +/// Pairing Confirm +/*@TRACE*/ +struct l2cc_pairing_cfm +{ + /// security code - 0x03 + uint8_t code; + ///Confirm value + uint8_t cfm_val[CFM_LEN]; +}; +/// Pairing Random +/*@TRACE*/ +struct l2cc_pairing_random +{ + /// security code - 0x04 + uint8_t code; + ///Random value + uint8_t random[RAND_VAL_LEN]; +}; +/// Pairing Failed +/*@TRACE*/ +struct l2cc_pairing_failed +{ + /// security code - 0x05 + uint8_t code; + /// The Reason field indicates why the pairing failed + uint8_t reason; +}; +/// Encryption Information +/*@TRACE*/ +struct l2cc_encryption_inf +{ + /// security code - 0x06 + uint8_t code; + ///16-byte array for LTK value + uint8_t ltk[GAP_KEY_LEN]; +}; +/// Master Identification +/*@TRACE*/ +struct l2cc_master_id +{ + /// security code - 0x07 + uint8_t code; + /// key diversifier + uint16_t ediv; + ///8-byte array for random number + uint8_t nb[GAP_RAND_NB_LEN]; +}; +/// Identity Information +/*@TRACE*/ +struct l2cc_identity_inf +{ + /// security code - 0x08 + uint8_t code; + ///16-byte array for IRK value + uint8_t irk[GAP_KEY_LEN]; +}; +/// Identity Address Information +/*@TRACE*/ +struct l2cc_id_addr_inf +{ + /// security code - 0x09 + uint8_t code; + /// BD Address Type + uint8_t addr_type; + /// BD Address + bd_addr_t addr; +}; +/// Signing Information +/*@TRACE*/ +struct l2cc_signing_inf +{ + /// security code - 0x0A + uint8_t code; + ///16-byte array for CSRK value + uint8_t csrk[GAP_KEY_LEN]; +}; +/// Security Request +/*@TRACE*/ +struct l2cc_security_req +{ + /// security code - 0x0B + uint8_t code; + /// AuthReq + uint8_t auth; +}; + +/// Public Key (x,y) +/*@TRACE*/ +struct l2cc_public_key +{ + /// security code - 0x0C + uint8_t code; + /// X and Y co-ordinates of the Public Key + uint8_t x[GAP_P256_KEY_LEN]; + uint8_t y[GAP_P256_KEY_LEN]; +}; + +/// DH Key Check +/*@TRACE*/ +struct l2cc_dhkey_check +{ + /// security code - 0x0D + uint8_t code; + uint8_t check[DHKEY_CHECK_LEN]; +}; +/// Keypress Notification - PassKey method only +/*@TRACE*/ +struct l2cc_keypress_notification +{ + /// security code - 0x0E + uint8_t code; + + uint8_t notification_type; +}; + + +/* Attribute protocol PDUs */ + +/// Error response +/*@TRACE*/ +struct l2cc_att_err_rsp +{ + /// Error Response - 0x01 + uint8_t code; + /// The request that generated this error response + uint8_t op_code; + /// The attribute handle that generated this error response + uint16_t handle; + ///The reason why the request has generated an error response + uint8_t reason; +}; + +/// Exchange MTU Request +/*@TRACE*/ +struct l2cc_att_mtu_req +{ + /// Exchange MTU Request - 0x02 + uint8_t code; + /// Client Rx MTU size + uint16_t mtu_size; +}; + +/// Exchange MTU Response +/*@TRACE*/ +struct l2cc_att_mtu_rsp +{ + /// Exchange MTU Response - 0x03 + uint8_t code; + /// Server Rx MTU size + uint16_t mtu_size; +}; + +/// Find Information Request +/*@TRACE*/ +struct l2cc_att_find_info_req +{ + /// Find Information Request - 0x04 + uint8_t code; + /// First requested handle number + uint16_t shdl; + /// Last requested handle number + uint16_t ehdl; +}; + +/// Find Information Response +/*@TRACE*/ +struct l2cc_att_find_info_rsp +{ + /// Find Information Response - 0x05 + uint8_t code; + /// The format of the information data. + uint8_t format; + /// Data length + uint16_t data_len; + ///The information data whose format is determined by the Format field + uint8_t data[__ARRAY_EMPTY]; +}; + +/// Find By Type Value Request +/*@TRACE*/ +struct l2cc_att_find_by_type_req +{ + /// Find By Type Value Request - 0x06 + uint8_t code; + /// First requested handle number + uint16_t shdl; + /// Last requested handle number + uint16_t ehdl; + /// 2 octet UUID to find + uint16_t type; + /// Attribute value length + uint16_t val_len; + /// Attribute value to find + uint8_t val[__ARRAY_EMPTY]; +}; + +/// Find By Type Value Response +/*@TRACE*/ +struct l2cc_att_find_by_type_rsp +{ + /// Find By Type Value Response - 0x07 + uint8_t code; + /// data length + uint16_t data_len; + /// A list of 1 or more Handle Informations. + uint8_t data[__ARRAY_EMPTY]; +}; + +/// Read By Type Request +/*@TRACE*/ +struct l2cc_att_rd_by_type_req +{ + /// Read By Type Request - 0x08 + uint8_t code; + /// Starting Handle + uint16_t shdl; + /// Ending Handle + uint16_t ehdl; + /// Attribute uuid length + uint16_t uuid_len; + /// Attribute type uuid + uint8_t uuid[__ARRAY_EMPTY]; +}; + +/// Read By Type Response +/*@TRACE*/ +struct l2cc_att_rd_by_type_rsp +{ + /// Read By Type Response - 0x09 + uint8_t code; + /// size of each attribute handle listed + uint8_t each_len; + /// Attribute Data length + uint16_t data_len; + /// A list of Attribute Data. + uint8_t data[__ARRAY_EMPTY]; +}; + +/// Read Request +/*@TRACE*/ +struct l2cc_att_rd_req +{ + /// Read Request - 0x0A + uint8_t code; + /// Attribute Handle + uint16_t handle; +}; + +/// Read Response +/*@TRACE*/ +struct l2cc_att_rd_rsp +{ + /// Read Response - 0x0B + uint8_t code; + /// value length + uint16_t value_len; + /// The value of the attribute with the handle given + uint8_t value[__ARRAY_EMPTY]; +}; + +/// Read Blob Request +/*@TRACE*/ +struct l2cc_att_rd_blob_req +{ + /// Read Blob Request - 0x0C + uint8_t code; + /// Attribute Handle + uint16_t handle; + /// The offset of the first octet to be read + uint16_t offset; +}; + +/// Read Blob Response +/*@TRACE*/ +struct l2cc_att_rd_blob_rsp +{ + /// Read Blob Response - 0x0D + uint8_t code; + /// value length + uint16_t value_len; + /// Part of the value of the attribute with the handle given + uint8_t value[__ARRAY_EMPTY]; +}; + +/// Read Multiple Request +/*@TRACE*/ +struct l2cc_att_rd_mult_req +{ + /// Read Multiple Request - 0x0E + uint8_t code; + /// Number of handles + uint16_t nb_handles; + /// A set of two or more attribute handles. + uint16_t handles[__ARRAY_EMPTY]; +}; + +/// Read Multiple Response +/*@TRACE*/ +struct l2cc_att_rd_mult_rsp +{ + /// Read Multiple Response - 0x0F + uint8_t code; + /// value length + uint16_t value_len; + /// A set of two or more values. + uint8_t value[__ARRAY_EMPTY]; +}; + +/// Read by Group Type Request +/*@TRACE*/ +struct l2cc_att_rd_by_grp_type_req +{ + /// Read by Group Type Request - 0x10 + uint8_t code; + /// First requested handle number + uint16_t shdl; + /// Last requested handle number + uint16_t ehdl; + /// Attribute uuid length + uint16_t uuid_len; + /// Attribute type uuid (2 or 16 octet UUID) + uint8_t uuid[__ARRAY_EMPTY]; +}; + +/// Read By Group Type Response +/*@TRACE*/ +struct l2cc_att_rd_by_grp_type_rsp +{ + /// Read By Group Type Response - 0x11 + uint8_t code; + /// size of each attribute handle listed + uint8_t each_len; + /// Attribute Data length + uint16_t data_len; + /// A list of Attribute Data. + uint8_t data[__ARRAY_EMPTY]; +}; + +/// Write Request +/*@TRACE*/ +struct l2cc_att_wr_req +{ + /// Write Request - 0x12 + uint8_t code; + /// The handle of the attribute to be written + uint16_t handle; + /// Value length + uint16_t value_len; + /// The value to be written to the attribute + uint8_t value[__ARRAY_EMPTY]; +}; + +/// Write Response +/*@TRACE*/ +struct l2cc_att_wr_rsp +{ + /// Write Response - 0x13 + uint8_t code; +}; + +/// Write Command +/*@TRACE + * l2cc_att_wr_cmd_info = l2cc_att_wr_cmd + */ +struct l2cc_att_wr_cmd +{ + /// Write Command - 0x52 + uint8_t code; + /// The handle of the attribute to be written + uint16_t handle; + /// Value length + uint16_t value_len; + /// The value to be written to the attribute + uint8_t value[__ARRAY_EMPTY]; +}; + +/// Signed Write Command +/*@TRACE + * l2cc_att_sign_wr_cmd_info = l2cc_att_sign_wr_cmd + */ +struct l2cc_att_sign_wr_cmd +{ + /// Write Command - 0xD2 + uint8_t code; + /// The handle of the attribute to be written + uint16_t handle; + /// Attribute Data length + uint16_t value_len; + /// The value to be written to the attribute + /// + 12 bytes of signatures: + /// Authentication signature for the Attribute Upload, Attribute Handle and Attribute + /// Value Parameters + uint8_t value[__ARRAY_EMPTY]; +}; + +/// Prepare Write Request +/*@TRACE*/ +struct l2cc_att_prep_wr_req +{ + /// Prepare Write Request - 0x16 + uint8_t code; + /// The handle of the attribute to be written + uint16_t handle; + /// The offset of the first octet to be written + uint16_t offset; + /// Value length + uint16_t value_len; + /// The value to be written to the attribute + uint8_t value[__ARRAY_EMPTY]; +}; + +/// Prepare Write Response +/*@TRACE*/ +struct l2cc_att_prep_wr_rsp +{ + /// Prepare Write Response - 0x17 + uint8_t code; + /// The handle of the attribute to be written + uint16_t handle; + /// The offset of the first octet to be written + uint16_t offset; + /// Value length + uint16_t value_len; + /// The value to be written to the attribute + uint8_t value[__ARRAY_EMPTY]; +}; + +/// Execute Write Request +/*@TRACE*/ +struct l2cc_att_exe_wr_req +{ + /// Execute Write Request - 0x18 + uint8_t code; + /// 0x00 - Cancel all prepared writes + /// 0x01 - Immediately write all pending prepared values + uint8_t flags; +}; + +/// Execute Write Response +/*@TRACE*/ +struct l2cc_att_exe_wr_rsp +{ + /// Prepare Write Response - 0x19 + uint8_t code; +}; + +/// Handle Value Notification +/*@TRACE*/ +struct l2cc_att_hdl_val_ntf +{ + /// Handle Value Notification - 0x1B + uint8_t code; + /// The handle of the attribute to be written + uint16_t handle; + /// Value length + uint16_t value_len; + /// The current value of the attribute + uint8_t value[__ARRAY_EMPTY]; +}; + +/// Handle Value Indication +/*@TRACE*/ +struct l2cc_att_hdl_val_ind +{ + /// Handle Value Indication - 0x1D + uint8_t code; + /// The handle of the attribute to be written + uint16_t handle; + /// Value length + uint16_t value_len; + /// The current value of the attribute + uint8_t value[__ARRAY_EMPTY]; +}; + +/// Handle Value Confirmation +/*@TRACE*/ +struct l2cc_att_hdl_val_cfm +{ + /// Handle Value Confirmation - 0x1E + uint8_t code; +}; + +/* LE Credit Based PDUs */ + +/// LE Generic send data request (includes total SDU Length) +/*@TRACE*/ +struct l2cc_lecb_send_data_req +{ + /// Code variable (RFU) + uint8_t code; + /// SDU data length + uint16_t sdu_data_len; + /// Data + uint8_t sdu_data[__ARRAY_EMPTY]; +}; + + +struct l2cc_pdu_data_t +{ + /// L2Cap packet code. + uint8_t code; +}; + +/*@TRACE + @trc_ref l2cc_cid, l2cc_signaling_code, l2cc_attribute_code, l2cc_security_code + */ +union l2cc_pdu_data +{ + /// L2Cap packet code. + uint8_t code; + + /* LE Credit Based packets */ + /// LE send first frame + //@trc_union parent.chan_id >= L2C_CID_DYN_MIN and parent.chan_id <= L2C_CID_DYN_MAX + struct l2cc_lecb_send_data_req send_lecb_data_req; + + /* Connection Signaling Packets */ + /// Command Reject + //@trc_union code == L2C_CODE_REJECT and parent.chan_id == L2C_CID_LE_SIGNALING + struct l2cc_reject reject; + /// Connection Parameter Update Request + //@trc_union code == L2C_CODE_CONN_PARAM_UPD_REQ and parent.chan_id == L2C_CID_LE_SIGNALING + struct l2cc_conn_param_upd_req update_req; + /// Connection Parameter Update Response + //@trc_union code == L2C_CODE_CONN_PARAM_UPD_RESP and parent.chan_id == L2C_CID_LE_SIGNALING + struct l2cc_conn_param_upd_resp update_rsp; + /// LE Credit based connection request + //@trc_union code == L2C_CODE_LE_CB_CONN_REQ and parent.chan_id == L2C_CID_LE_SIGNALING + struct l2cc_le_cb_conn_req credit_con_req; + /// LE Credit based connection response + //@trc_union code == L2C_CODE_LE_CB_CONN_RESP and parent.chan_id == L2C_CID_LE_SIGNALING + struct l2cc_le_cb_conn_resp credit_con_rsp; + /// LE Flow Control Credit + //@trc_union code == L2C_CODE_LE_FLOW_CONTROL_CREDIT and parent.chan_id == L2C_CID_LE_SIGNALING + struct l2cc_le_flow_control_credit flow_ctl_credit; + /// LE disconnection request + //@trc_union code == L2C_CODE_DISCONNECTION_REQ and parent.chan_id == L2C_CID_LE_SIGNALING + struct l2cc_disconnection_req disc_req; + /// LE disconnection response + //@trc_union code == L2C_CODE_DISCONNECTION_RESP and parent.chan_id == L2C_CID_LE_SIGNALING + struct l2cc_disconnection_resp disc_rsp; + + /* Security manager PDUs */ + /// Pairing Request + //@trc_union code == L2C_CODE_PAIRING_REQ and parent.chan_id == L2C_CID_SECURITY + struct l2cc_pairing_req pairing_req; + /// Pairing Response + //@trc_union code == L2C_CODE_PAIRING_RESP and parent.chan_id == L2C_CID_SECURITY + struct l2cc_pairing_resp pairing_rsp; + /// Pairing Confirm + //@trc_union code == L2C_CODE_PAIRING_CFM and parent.chan_id == L2C_CID_SECURITY + struct l2cc_pairing_cfm pairing_cfm; + /// Pairing Random + //@trc_union code == L2C_CODE_PAIRING_RANDOM and parent.chan_id == L2C_CID_SECURITY + struct l2cc_pairing_random pairing_random; + /// Pairing Failed + //@trc_union code == L2C_CODE_PAIRING_FAILED and parent.chan_id == L2C_CID_SECURITY + struct l2cc_pairing_failed pairing_failed; + /// Encryption Information + //@trc_union code == L2C_CODE_ENCRYPTION_INF and parent.chan_id == L2C_CID_SECURITY + struct l2cc_encryption_inf encryption_inf; + /// Master Identification + //@trc_union code == L2C_CODE_MASTER_ID and parent.chan_id == L2C_CID_SECURITY + struct l2cc_master_id master_id; + /// Identity Information + //@trc_union code == L2C_CODE_IDENTITY_INF and parent.chan_id == L2C_CID_SECURITY + struct l2cc_identity_inf identity_inf; + /// Identity Address Information + //@trc_union code == L2C_CODE_ID_ADDR_INF and parent.chan_id == L2C_CID_SECURITY + struct l2cc_id_addr_inf id_addr_inf; + /// Signing Information + //@trc_union code == L2C_CODE_SIGNING_INF and parent.chan_id == L2C_CID_SECURITY + struct l2cc_signing_inf signing_inf; + /// Security Request + //@trc_union code == L2C_CODE_SECURITY_REQ and parent.chan_id == L2C_CID_SECURITY + struct l2cc_security_req security_req; + /// Public Keys + //@trc_union code == L2C_CODE_PUBLIC_KEY and parent.chan_id == L2C_CID_SECURITY + struct l2cc_public_key public_key; + /// Key Press Notification + //@trc_union code == L2C_CODE_KEYPRESS_NOTIFICATION and parent.chan_id == L2C_CID_SECURITY + struct l2cc_keypress_notification keypress_notification; + /// DH Key Check + //@trc_union code == L2C_CODE_DHKEY_CHECK and parent.chan_id == L2C_CID_SECURITY + struct l2cc_dhkey_check dhkey_check; + + /* Attribute protocol PDUs */ + /// Error response + //@trc_union code == L2C_CODE_ATT_ERR_RSP and parent.chan_id == L2C_CID_ATTRIBUTE + struct l2cc_att_err_rsp err_rsp; + /// Exchange MTU Request + //@trc_union code == L2C_CODE_ATT_MTU_REQ and parent.chan_id == L2C_CID_ATTRIBUTE + struct l2cc_att_mtu_req mtu_req; + /// Exchange MTU Response + //@trc_union code == L2C_CODE_ATT_MTU_RSP and parent.chan_id == L2C_CID_ATTRIBUTE + struct l2cc_att_mtu_rsp mtu_rsp; + /// Find Information Request + //@trc_union code == L2C_CODE_ATT_FIND_INFO_REQ and parent.chan_id == L2C_CID_ATTRIBUTE + struct l2cc_att_find_info_req find_info_req; + /// Find Information Response + //@trc_union code == L2C_CODE_ATT_FIND_INFO_RSP and parent.chan_id == L2C_CID_ATTRIBUTE + struct l2cc_att_find_info_rsp find_info_rsp; + /// Find By Type Value Request + //@trc_union code == L2C_CODE_ATT_FIND_BY_TYPE_REQ and parent.chan_id == L2C_CID_ATTRIBUTE + struct l2cc_att_find_by_type_req find_by_type_req; + /// Find By Type Value Response + //@trc_union code == L2C_CODE_ATT_FIND_BY_TYPE_RSP and parent.chan_id == L2C_CID_ATTRIBUTE + struct l2cc_att_find_by_type_rsp find_by_type_rsp; + /// Read By Type Request + //@trc_union code == L2C_CODE_ATT_RD_BY_TYPE_REQ and parent.chan_id == L2C_CID_ATTRIBUTE + struct l2cc_att_rd_by_type_req rd_by_type_req; + /// Read By Type Response + //@trc_union code == L2C_CODE_ATT_RD_BY_TYPE_RSP and parent.chan_id == L2C_CID_ATTRIBUTE + struct l2cc_att_rd_by_type_rsp rd_by_type_rsp; + /// Read Request + //@trc_union code == L2C_CODE_ATT_RD_REQ and parent.chan_id == L2C_CID_ATTRIBUTE + struct l2cc_att_rd_req rd_req; + /// Read Response + //@trc_union code == L2C_CODE_ATT_RD_RSP and parent.chan_id == L2C_CID_ATTRIBUTE + struct l2cc_att_rd_rsp rd_rsp; + /// Read Blob Request + //@trc_union code == L2C_CODE_ATT_RD_BLOB_REQ and parent.chan_id == L2C_CID_ATTRIBUTE + struct l2cc_att_rd_blob_req rd_blob_req; + /// Read Blob Response + //@trc_union code == L2C_CODE_ATT_RD_BLOB_RSP and parent.chan_id == L2C_CID_ATTRIBUTE + struct l2cc_att_rd_blob_rsp rd_blob_rsp; + /// Read Multiple Request + //@trc_union code == L2C_CODE_ATT_RD_MULT_REQ and parent.chan_id == L2C_CID_ATTRIBUTE + struct l2cc_att_rd_mult_req rd_mult_req; + /// Read Multiple Response + //@trc_union code == L2C_CODE_ATT_RD_MULT_RSP and parent.chan_id == L2C_CID_ATTRIBUTE + struct l2cc_att_rd_mult_rsp rd_mult_rsp; + /// Read by Group Type Request + //@trc_union code == L2C_CODE_ATT_RD_BY_GRP_TYPE_REQ and parent.chan_id == L2C_CID_ATTRIBUTE + struct l2cc_att_rd_by_grp_type_req rd_by_grp_type_req; + /// Read By Group Type Response + //@trc_union code == L2C_CODE_ATT_RD_BY_GRP_TYPE_RSP and parent.chan_id == L2C_CID_ATTRIBUTE + struct l2cc_att_rd_by_grp_type_rsp rd_by_grp_type_rsp; + /// Write Request + //@trc_union code == L2C_CODE_ATT_WR_REQ and parent.chan_id == L2C_CID_ATTRIBUTE + struct l2cc_att_wr_req wr_req; + /// Write Response + //@trc_union code == L2C_CODE_ATT_WR_RSP and parent.chan_id == L2C_CID_ATTRIBUTE + struct l2cc_att_wr_rsp wr_rsp; + /// Write Command + //@trc_union code == L2C_CODE_ATT_WR_CMD and parent.chan_id == L2C_CID_ATTRIBUTE + struct l2cc_att_wr_cmd wr_cmd; + /// Signed Write Command + //@trc_union code == L2C_CODE_ATT_SIGN_WR_CMD and parent.chan_id == L2C_CID_ATTRIBUTE + struct l2cc_att_sign_wr_cmd sign_wr_cmd; + /// Prepare Write Request + //@trc_union code == L2C_CODE_ATT_PREP_WR_REQ and parent.chan_id == L2C_CID_ATTRIBUTE + struct l2cc_att_prep_wr_req prep_wr_req; + /// Prepare Write Response + //@trc_union code == L2C_CODE_ATT_PREP_WR_RSP and parent.chan_id == L2C_CID_ATTRIBUTE + struct l2cc_att_prep_wr_rsp prep_wr_rsp; + /// Execute Write Request + //@trc_union code == L2C_CODE_ATT_EXE_WR_REQ and parent.chan_id == L2C_CID_ATTRIBUTE + struct l2cc_att_exe_wr_req exe_wr_req; + /// Execute Write Response + //@trc_union code == L2C_CODE_ATT_EXE_WR_RSP and parent.chan_id == L2C_CID_ATTRIBUTE + struct l2cc_att_exe_wr_rsp exe_wr_rsp; + /// Handle Value Notification + //@trc_union code == L2C_CODE_ATT_HDL_VAL_NTF and parent.chan_id == L2C_CID_ATTRIBUTE + struct l2cc_att_hdl_val_ntf hdl_val_ntf; + /// Handle Value Indication + //@trc_union code == L2C_CODE_ATT_HDL_VAL_IND and parent.chan_id == L2C_CID_ATTRIBUTE + struct l2cc_att_hdl_val_ind hdl_val_ind; + /// Handle Value Confirmation + //@trc_union code == L2C_CODE_ATT_HDL_VAL_CFM and parent.chan_id == L2C_CID_ATTRIBUTE + struct l2cc_att_hdl_val_cfm hdl_val_cfm; +}; + +/// Default L2Cap PDU definition +/*@TRACE*/ +struct l2cc_pdu +{ + /// L2Cap Payload Length + uint16_t payld_len; + /// L2Cap Channel ID + uint16_t chan_id; + /// Data PDU definition + union l2cc_pdu_data data; +}; + + +/// Default L2Cap DBG pdu definition +/*@TRACE*/ +struct l2cc_dbg_pdu +{ + /// Data length + uint16_t length; + /// data + uint8_t data[__ARRAY_EMPTY]; +}; + +/// Default L2Cap SDU definition +struct l2cc_sdu; + + +/// @} L2CC_PDU + + +#endif /* _L2CC_PDU_H_ */ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/inc/l2cm.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/inc/l2cm.h new file mode 100755 index 0000000..7a11dab --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/inc/l2cm.h @@ -0,0 +1,127 @@ +/** + **************************************************************************************** + * + * @file l2cm.h + * + * @brief Header file - L2CM. + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + +#ifndef L2CM_H_ +#define L2CM_H_ + +/** + **************************************************************************************** + * @addtogroup L2C Logical Link Control and Adaptation Protocol + * @ingroup HOST + * @brief Logical Link Control and Adaptation Protocol - BLE Host. + * + * The L2C module is responsible for L2CAP provides connection-oriented + * and connection-less data services to upper layer protocols with protocol + * multiplexing capability and segmentation and re-assembly operation. + * + * @{ + **************************************************************************************** + */ +/** + **************************************************************************************** + * @addtogroup L2CM L2CAP Manager + * @ingroup L2C + * @brief L2CAP block for signaling and resource management functions + * + * The L2CM is an internal L2CAP block responsible for managing + * the signaling messages and propagation of connection and disconnection + * related L2CAP messages within the Host. + * + * @{ + **************************************************************************************** + */ +#include "rwip_config.h" + +#if (BLE_L2CM) +#include +#include + +/* + * INCLUDE FILES + **************************************************************************************** + */ + + +/* + * DEFINES + **************************************************************************************** + */ + +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Create and Initialize the L2CAP manager task. + * + * @param[in] init_type Type of initialization (@see enum rwip_init_type) + * + **************************************************************************************** + */ +void l2cm_init(uint8_t init_type); + + + +/** + **************************************************************************************** + * @brief Allocates an L2CAP resource. + * + * @param[in] conidx connection index + * + **************************************************************************************** + */ +void l2cm_create(uint8_t conidx); + +/** + **************************************************************************************** + * @brief De-initializes the L2CAP resources for specified link. + * + * @param[in] conidx connection index + * + **************************************************************************************** + */ +void l2cm_cleanup(uint8_t conidx); + + +/** + **************************************************************************************** + * @brief Sets link layer buffer size capacity + * + * @param[in] pkt_len length of the packet + * @param[in] nb_acl number of acl + * + **************************************************************************************** + */ +void l2cm_set_link_layer_buff_size(uint16_t pkt_len, uint16_t nb_acl); + +/** + **************************************************************************************** + * @brief Retrieve number of low layer buffer available + * + * @return Number of low layer buffer available + **************************************************************************************** + */ +uint16_t l2cm_get_nb_buffer_available(void); + +/// @} L2CM + +#endif //(BLE_L2CM) + +#endif // L2CM_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/inc/rwble_hl.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/inc/rwble_hl.h new file mode 100755 index 0000000..483c219 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/inc/rwble_hl.h @@ -0,0 +1,54 @@ +/** + **************************************************************************************** + * + * @file rwble_hl.h + * + * @brief Entry points of the BLE HL software + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + +#ifndef RWBLE_HL_H_ +#define RWBLE_HL_H_ + +#include +#include // standard boolean definitions +/** + **************************************************************************************** + * @addtogroup ROOT + * @brief Entry points of the BLE Host stack + * + * This module contains the primitives that allow an application accessing and running the + * BLE protocol stack + * + * @{ + **************************************************************************************** + */ + + +/* + * DEFINES + **************************************************************************************** + */ + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + + +/** + **************************************************************************************** + * @brief Initialize the BLE Host stack. + * + * @param[in] init_type Type of initialization (@see enum rwip_init_type) + **************************************************************************************** + */ +void rwble_hl_init(uint8_t init_type); + +/// @} RWBLE_HL + +#endif // RWBLE_HL_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/inc/rwble_hl_config.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/inc/rwble_hl_config.h new file mode 100755 index 0000000..13f2edc --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/inc/rwble_hl_config.h @@ -0,0 +1,274 @@ +/** + **************************************************************************************** + * + * @file rwble_hl_config.h + * + * @brief Configuration of the BLE protocol stack (max number of supported connections, + * type of partitioning, etc.) + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + +#ifndef RWBLE_HL_CONFIG_H_ +#define RWBLE_HL_CONFIG_H_ + +/** + **************************************************************************************** + * @addtogroup ROOT + * @{ + * @name BLE stack configuration + * @{ + **************************************************************************************** + */ + +#include "rwble_hl_error.h" + +/* + * DEFINES - Mandatory for BLE Host Layers + **************************************************************************************** + */ + +/// Maximum time to remain advertising when in the Limited +/// Discover able mode: TGAP(lim_adv_timeout) +/// required value: 180s: (18000 for ke timer) +#define GAP_TMR_LIM_ADV_TIMEOUT 0x4650 + +/// Minimum time to perform scanning when performing +/// the General Discovery procedure: TGAP(gen_disc_scan_min) +/// recommended value: 10.24s: (1024 for ke timer) +#define GAP_TMR_GEN_DISC_SCAN 0x0400 + +/// Minimum time to perform scanning when performing the +/// Limited Discovery procedure: TGAP(lim_disc_scan_min) +/// recommended value: 10.24s: (1024 for ke timer) +#define GAP_TMR_LIM_DISC_SCAN 0x0400 + +/// Minimum time interval between private address change +/// TGAP(private_addr_int) +/// recommended value: 15 minutes +/// Minimum value 150s +#define GAP_TMR_PRIV_ADDR_MIN (150) +/// Maximum time interval between private address change +/// 0xA1B8 (approximately 11.5 hours) +#define GAP_TMR_PRIV_ADDR_MAX (0xA1B8) + + +/// Timer used in connection parameter update procedure +/// TGAP(conn_param_timeout) +/// recommended value: 30 s: (3000 for ke timer) +#define GAP_TMR_CONN_PARAM_TIMEOUT 0x0BB8 + +/// Timer used in LE credit based connection procedure +/// TGAP(lecb_conn_timeout) +/// recommended value: 30 s: (3000 for ke timer) +#define GAP_TMR_LECB_CONN_TIMEOUT 0x0BB8 + +/// Timer used in LE credit based disconnection procedure +/// TGAP(lecb_disconn_timeout) +/// recommended value: 30 s: (3000 for ke timer) +#define GAP_TMR_LECB_DISCONN_TIMEOUT 0x0BB8 + +/// Maximal authorized MTU value - Implementation supports up to (2^12 -1) = 4095 bytes +#define GAP_MAX_LE_MTU (2048) + +/// Maximum GAP device name size +#define GAP_MAX_NAME_SIZE (0x20) + + + + +/// Maximum Transmission Unit +#define ATT_DEFAULT_MTU (23) +/// 30 seconds transaction timer +#define ATT_TRANS_RTX (0x0BB8) +/// Acceptable encryption key size - strict access +#define ATT_SEC_ENC_KEY_SIZE (0x10) + + +/// Maximum attribute value length +#define ATT_MAX_VALUE (GAP_MAX_LE_MTU) + + +/******************************************************************************************/ +/* ------------------------- BLE PARTITIONING -------------------------------------*/ +/******************************************************************************************/ + + +/******************************************************************************************/ +/* -------------------------- INTERFACES ----------------------------------------*/ +/******************************************************************************************/ + + +#if BLE_APP_PRESENT +#define APP_MAIN_TASK TASK_BLE_APP +#else // BLE_APP_PRESENT +#define APP_MAIN_TASK TASK_BLE_AHI +#endif // BLE_APP_PRESENT + +// Host Controller Interface (Host side) +#define BLEHL_HCIH_ITF HCIH_ITF + +/******************************************************************************************/ +/* -------------------------- COEX SETUP ----------------------------------------*/ +/******************************************************************************************/ + +///WLAN coex +#define BLEHL_WLAN_COEX RW_WLAN_COEX +///WLAN test mode +#define BLEHL_WLAN_COEX_TEST RW_WLAN_COEX_TEST + +/******************************************************************************************/ +/* -------------------------- HOST MODULES ----------------------------------------*/ +/******************************************************************************************/ + +#define BLE_GAPM 1 +#if (BLE_OBSERVER) +#define BLE_GAPM_HEAP_ENV_SIZE (sizeof(struct gapm_actv_scan_tag) + KERNEL_HEAP_MEM_RESERVED) +#elif (BLE_PERIPHERAL) +#define BLE_GAPM_HEAP_ENV_SIZE (sizeof(struct gapm_actv_adv_tag) + KERNEL_HEAP_MEM_RESERVED) +#else //(BLE_PERIPHERAL) +#define BLE_GAPM_HEAP_ENV_SIZE 0 +#endif //(BLE_PERIPHERAL) + +#if (BLE_CENTRAL || BLE_PERIPHERAL) +#define BLE_GAPC 1 +#define BLE_GAPC_HEAP_ENV_SIZE (sizeof(struct gapc_env_tag) + KERNEL_HEAP_MEM_RESERVED) +#else //(BLE_CENTRAL || BLE_PERIPHERAL) +#define BLE_GAPC 0 +#define BLE_GAPC_HEAP_ENV_SIZE 0 +#endif //(BLE_CENTRAL || BLE_PERIPHERAL) + +#if (BLE_CENTRAL || BLE_PERIPHERAL) +#define BLE_L2CM 1 +#define BLE_L2CC 1 +#define BLE_ATTM 1 +#define BLE_GATTM 1 +#define BLE_GATTC 1 +#define BLE_GATTC_HEAP_ENV_SIZE (sizeof(struct gattc_env_tag) + KERNEL_HEAP_MEM_RESERVED) +#define BLE_L2CC_HEAP_ENV_SIZE (sizeof(struct l2cc_env_tag) + KERNEL_HEAP_MEM_RESERVED) +#else //(BLE_CENTRAL || BLE_PERIPHERAL) +#define BLE_L2CM 0 +#define BLE_L2CC 0 +#define BLE_ATTC 0 +#define BLE_ATTS 0 +#define BLE_ATTM 0 +#define BLE_GATTM 0 +#define BLE_GATTC 0 +#define BLE_GATTC_HEAP_ENV_SIZE 0 +#define BLE_L2CC_HEAP_ENV_SIZE 0 +#endif //(BLE_CENTRAL || BLE_PERIPHERAL) + +/******************************************************************************************/ +/* -------------------------- ATT DB ----------------------------------------*/ +/******************************************************************************************/ + +//ATT DB,Testing and Qualification related flags +#if (BLE_CENTRAL || BLE_PERIPHERAL) + /// Support of External DB Management + #if defined(CFG_EXT_DB) + #define BLE_EXT_ATT_DB 1 + #else + #define BLE_EXT_ATT_DB 0 + #endif // defined(CFG_EXT_DB) +#else + #define BLE_EXT_ATT_DB 0 +#endif // (BLE_CENTRAL || BLE_PERIPHERAL) +/******************************************************************************************/ +/* -------------------------- PROFILES ----------------------------------------*/ +/******************************************************************************************/ +#ifdef CFG_PRF +#define BLE_PROFILES (1) +/// Number of Profile tasks managed by GAP manager. +#define BLE_NB_PROFILES (CFG_NB_PRF) +#include "rwprf_config.h" +#else +#define BLE_PROFILES (0) +#define BLE_NB_PROFILES (0) +#endif // CFG_PRF + + +#ifndef BLE_ATTS +#if (BLE_CENTRAL || BLE_PERIPHERAL || defined(CFG_ATTS)) +#define BLE_ATTS 1 +#else +#define BLE_ATTS 0 +#endif // (BLE_CENTRAL || BLE_PERIPHERAL || defined(CFG_ATTS)) +#endif // BLE_ATTS + + +#ifndef BLE_ATTC +#if (BLE_CENTRAL || defined(CFG_ATTC)) +#define BLE_ATTC 1 +#else +#define BLE_ATTC 0 +#endif // (BLE_CENTRAL || defined(CFG_ATTC)) +#endif // BLE_ATTC + +#ifndef BLE_LECB +#if (BLE_CENTRAL || BLE_PERIPHERAL) +#define BLE_LECB 1 +#else +#define BLE_LECB 0 +#endif // (BLE_CENTRAL || defined(CFG_ATTC)) +#endif // BLE_ATTC + + +/// Attribute Server +#if (BLE_ATTS) +#define BLE_ATTS 1 +#else +#define BLE_ATTS 0 +#endif //(BLE_ATTS) + + +/// Size of the heap +#if (BLE_CENTRAL || BLE_PERIPHERAL) + /// some heap must be reserved for attribute database + #if (BLE_ATTS || BLE_ATTC) + /// Can be tuned based on supported profiles + #define BLEHL_HEAP_DB_SIZE (3072) + #else + #define BLEHL_HEAP_DB_SIZE (0) + #endif /* (BLE_ATTS || BLE_ATTC) */ + + #if (BLE_EMB_PRESENT) + /// Needed "security" heap size for reception of max supported MTU through prepare write procedure + /// If retention memory is used, this additionnal heap can be part of the size allocated for the retention memory + #define BLEHL_HEAP_DATA_THP_SIZE (3 * GAP_MAX_LE_MTU) + #else // !(BLE_EMB_PRESENT) + #define BLEHL_HEAP_DATA_THP_SIZE (4 * GAP_MAX_LE_MTU) + #endif // (BLE_EMB_PRESENT) + + /// message size per connection + #define BLEHL_HEAP_MSG_SIZE_PER_CON (400) + + #define BLEHL_HEAP_MSG_SIZE (((BLEHL_HEAP_MSG_SIZE_PER_CON * BLE_CONNECTION_MAX) > BLEHL_HEAP_DATA_THP_SIZE) \ + ? (BLEHL_HEAP_MSG_SIZE_PER_CON * BLE_CONNECTION_MAX) : BLEHL_HEAP_DATA_THP_SIZE) +#elif (BLE_MESH) + #define BLEHL_HEAP_MSG_SIZE (1024) + #define BLEHL_HEAP_DB_SIZE (3072) +#else + #define BLEHL_HEAP_MSG_SIZE (256) + #define BLEHL_HEAP_DB_SIZE (0) +#endif /* #if (BLE_CENTRAL || BLE_PERIPHERAL) */ + + + + +/// Number of BLE HL tasks +#define BLEHL_TASK_SIZE BLE_HOST_TASK_SIZE + BLE_PRF_TASK_SIZE + +/// Size of environment variable needed on BLE Host Stack for one link +#define BLEHL_HEAP_ENV_SIZE ( BLE_CONNECTION_MAX * ( BLE_GAPC_HEAP_ENV_SIZE \ + + BLE_GATTC_HEAP_ENV_SIZE \ + + BLE_L2CC_HEAP_ENV_SIZE ) \ + + BLE_ACTIVITY_MAX * BLE_GAPM_HEAP_ENV_SIZE ) + + +/// @} BLE stack configuration +/// @} ROOT + +#endif // RWBLE_HL_CONFIG_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gap/gapc/gapc_int.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gap/gapc/gapc_int.h new file mode 100755 index 0000000..bbde7ce --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gap/gapc/gapc_int.h @@ -0,0 +1,394 @@ +/** + **************************************************************************************** + * + * @file gapc_int.h + * + * @brief Generic Access Profile Controller Internal Header. + * + * Copyright (C) RivieraWaves 2009-2016 + * + **************************************************************************************** + */ +#ifndef _GAPC_INT_H_ +#define _GAPC_INT_H_ + +/** + **************************************************************************************** + * @addtogroup GAPC_INT Generic Access Profile Controller Internals + * @ingroup GAPC + * @brief Handles ALL Internal GAPC API + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_config.h" +#if (BLE_GAPC) +#include "gapc.h" +#include "gapc_task.h" +#include "common_bt.h" +/* + * MACROS + **************************************************************************************** + */ + + +/* + * DEFINES + **************************************************************************************** + */ + +/// number of GAP Controller Process +#define GAPC_IDX_MAX BLE_CONNECTION_MAX + + +/** + * Repeated Attempts Timer Configuration + */ +/// Repeated Attempts Timer default value (x10ms) +#define GAPC_SMP_REP_ATTEMPTS_TIMER_DEF_VAL (200) //2s +/// Repeated Attempts Timer max value (x10ms) +#define GAPC_SMP_REP_ATTEMPTS_TIMER_MAX_VAL (3000) //30s +/// Repeated Attempts Timer multiplier +#define GAPC_SMP_REP_ATTEMPTS_TIMER_MULT (2) + + +/// states of GAP Controller task +enum gapc_state_id +{ + /// Connection ready state + GAPC_READY, + + /// Link Operation on-going + GAPC_LINK_INFO_BUSY = (1 << GAPC_OP_LINK_INFO), + /// SMP Operation on-going + GAPC_SMP_BUSY = (1 << GAPC_OP_SMP), + /// Update Operation on-going + GAPC_LINK_UPD_BUSY = (1 << GAPC_OP_LINK_UPD), + /// SMP start encryption on-going + GAPC_ENCRYPT_BUSY = (1 << GAPC_OP_MAX), + + /// Disconnection on-going + GAPC_DISC_BUSY = 0x1F, + /// Free state + GAPC_FREE = 0X3F, + + /// Number of defined states. + GAPC_STATE_MAX +}; + +/// fields definitions. +/// Configuration fields: +/// 7 6 5 4 3 2 1 0 +/// +----+----+----+----+----+----+----+----+ +/// |RFU |SCEN|ROLE|LTK |ENC |BOND| SEC_LVL | +/// +----+----+----+----+----+----+----+----+ +enum gapc_fields +{ + /// Link Security Level + GAPC_SEC_LVL_LSB = 0, + GAPC_SEC_LVL_MASK = 0x03, + /// Link Bonded or not + GAPC_BONDED_POS = 2, + GAPC_BONDED_BIT = 0x04, + /// Encrypted connection or not + GAPC_ENCRYPTED_POS = 3, + GAPC_ENCRYPTED_BIT = 0x08, + /// Ltk present and exchanged during pairing + GAPC_LTK_PRESENT_POS = 4, + GAPC_LTK_PRESENT_BIT = 0x10, + /// Local connection role + GAPC_ROLE_POS = 5, + GAPC_ROLE_BIT = 0x20, + /// Used to know if secure connection is enabled + GAPC_SC_EN_POS = 6, + GAPC_SC_EN_BIT = 0x40, +}; +/* + * TYPE DECLARATIONS + **************************************************************************************** + */ + +struct l2cc_pdu; + +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ +extern struct gapc_env_tag* gapc_env[GAPC_IDX_MAX]; + + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Initialize Generic Access Profile Controller Module. + * + * @param[in] init_type Type of initialization (@see enum rwip_init_type) + * + **************************************************************************************** + */ +void gapc_init(uint8_t init_type); + + +/** + **************************************************************************************** + * @brief A connection has been created, initialize Controller task. + * + * This function find first available task index available for new connection. + * It triggers also connection event to task that has requested the connection. + * + * @param[in] msgid Message id for normal or enhanced privacy + * @param[in] con_params Connection parameters from lower layers + * @param[in] requester Task that request the connection to send indication(s) + * @param[in] laddr Local BD Address + * @param[in] laddr_type Local BD Address Type (PUBLIC or RAND) + * + * @return Connection index allocated to the new connection. + **************************************************************************************** + */ +uint8_t gapc_con_create(kernel_msg_id_t const msgid, struct hci_le_enh_con_cmp_evt const *con_params, + kernel_task_id_t requester, bd_addr_t* laddr, uint8_t laddr_type); + +/** + **************************************************************************************** + * @brief A connection has been disconnected, uninitialized Controller task. + * + * unregister connection, and destroy environment variable allocated for current connection. + * + * @param[in] conidx Connection index + * + * @return Connection index of the connection. + **************************************************************************************** + */ +uint8_t gapc_con_cleanup(uint8_t conidx); + + +/** + **************************************************************************************** + * @brief Send Disconnection indication to specific task + * + * @param[in] conidx Connection index + * @param[in] reason Disconnection reason + * @param[in] conhdl Connection handle + * @param[in] dest_id Message destination ID + * + **************************************************************************************** + */ +void gapc_send_disconect_ind(uint8_t conidx, uint8_t reason, uint8_t conhdl, + kernel_task_id_t dest_id); + + + +/** + * @brief Send a complete event of ongoing executed operation to requester. + * It also clean-up variable used for ongoing operation. + * + * @param[in] conidx Connection index + * @param[in] op_type Operation type. + * @param[in] status Status of completed operation + */ +void gapc_send_complete_evt(uint8_t conidx, uint8_t op_type, uint8_t status); + +/** + **************************************************************************************** + * @brief Send operation completed message with status error code not related to a + * running operation. + * + * @param[in] conidx Connection index + * @param[in] operation Operation code + * @param[in] requester requester of operation + * @param[in] status Error status code + **************************************************************************************** + */ +void gapc_send_error_evt(uint8_t conidx, uint8_t operation, const kernel_task_id_t requester, uint8_t status); + + +/** + **************************************************************************************** + * @brief Get operation on going + * + * @param[in] conidx Connection Index + * @param[in] op_type Operation type. + * + * @return operation code on going + **************************************************************************************** + */ +uint8_t gapc_get_operation(uint8_t conidx, uint8_t op_type); + +/** + **************************************************************************************** + * @brief Get operation pointer + * + * @param[in] conidx Connection Index + * @param[in] op_type Operation type. + * + * @return operation pointer on going + **************************************************************************************** + */ +void* gapc_get_operation_ptr(uint8_t conidx, uint8_t op_type); + + +/** + **************************************************************************************** + * @brief Set operation pointer + * + * @param[in] conidx Connection Index + * @param[in] op_type Operation type. + * @param[in] op Operation pointer. + * + **************************************************************************************** + */ +void gapc_set_operation_ptr(uint8_t conidx, uint8_t op_type, void* op); + +/** + **************************************************************************************** + * @brief Operation execution not finish, request kernel to reschedule it in order to + * continue its execution + * + * @param[in] conidx Connection Index + * @param[in] op_type Operation type. + * + * @return if operation has been rescheduled (not done if operation pointer is null) + **************************************************************************************** + */ +bool gapc_reschedule_operation(uint8_t conidx, uint8_t op_type); + +/** + **************************************************************************************** + * @brief Get requester of on going operation + * + * @param[in] conidx Connection Index + * @param[in] op_type Operation type. + * + * @return ID of task that requested to execute the operation + **************************************************************************************** + */ +kernel_task_id_t gapc_get_requester(uint8_t conidx, uint8_t op_type); + +/** + **************************************************************************************** + * @brief Update link authentication level + * + * @param[in] conidx Connection index + * @param[in] auth Link authentication level + * @param[in] ltk_present Link paired and an LTK has been exchanged + * + **************************************************************************************** + */ +void gapc_auth_set(uint8_t conidx, uint8_t auth, bool ltk_present); + +/** + **************************************************************************************** + * @brief Retrieve link authentication level + * + * @param[in] conidx Connection index + * @return Link authentication level + **************************************************************************************** + */ +uint8_t gapc_auth_get(uint8_t conidx); + +/** + **************************************************************************************** + * @brief Update task state + * + * @param[in] conidx Connection index + * @param[in] state to update + * @param[in] set state to busy (true) or idle (false) + * + **************************************************************************************** + */ +void gapc_update_state(uint8_t conidx, kernel_state_t state, bool busy); + + +/** + **************************************************************************************** + * @brief Checks connection parameters values + * + * @param[in] intv_max maximum interval + * @param[in] intv_min minimum interval + * @param[in] latency latency + * @param[in] timeout timeout value + * + * @return true if OK, false if not OK + **************************************************************************************** + */ +bool gapc_param_update_sanity(uint16_t intv_max, uint16_t intv_min, uint16_t latency, uint16_t timeout); + +/** + **************************************************************************************** + * @brief Get channel selection algorithm used for a given connection identified + * by its connection index + * + * @param[in] conidx Connection index + * + * @return Channel selection algorithm used (0 if algo #1, 1 if algo #2) + **************************************************************************************** + */ +uint8_t gapc_get_chan_sel_algo(uint8_t conidx); + + +/** + **************************************************************************************** + * @brief Handle reception of a SMP PDU sent by the peer device. + * + * @param[in] conidx Connection Index + * @param[in] pdu Unpacked PDU + * @param[in] status status of the execution + **************************************************************************************** + */ +void gapc_smp_pdu_recv(uint8_t conidx, struct l2cc_pdu *pdu, uint8_t status); + +/** + **************************************************************************************** + * @brief Clean-up SMP operation + * + * @param[in] conidx Connection Index + **************************************************************************************** + */ +void gapc_smp_cleanup(uint8_t conidx); + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Check if current operation can be processed or not. + * if it can be proceed, initialize an operation request. + * If a command complete event with error code can be triggered. + * + * Function returns how the message should be handled by message handler. + * + * @param[in] conidx Connection Index + * @param[in] op_type Operation type. + * @param[in] op_msg Requested operation message (note op_msg cannot be null) + * @param[in] supp_ops Supported operations array. + * Latest array value shall be GAPC_NO_OP. + * + * @return operation can be executed if message status equals KERNEL_MSG_NO_FREE, + * else nothing to do, just exit from the handler. + **************************************************************************************** + */ +int gapc_process_op(uint8_t conidx, uint8_t op_type, void* op_msg, enum gapc_operation* supp_ops); + + + + +/* + * TASK DESCRIPTOR DECLARATIONS + **************************************************************************************** + */ + +#endif // (BLE_GAPC) +/// @} GAPC_INT + +#endif /* _GAPC_INT_H_ */ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gap/gapc/gapc_sig.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gap/gapc/gapc_sig.h new file mode 100755 index 0000000..352724f --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gap/gapc/gapc_sig.h @@ -0,0 +1,64 @@ +/** + **************************************************************************************** + * + * @file gapc_sig.h + * + * @brief Generic Access Profile Controller Signaling PDU Handler. + * + * Copyright (C) RivieraWaves 2009-2016 + * + **************************************************************************************** + */ + +#ifndef _GAPC_SIG_H_ +#define _GAPC_SIG_H_ + + +/** + **************************************************************************************** + * @addtogroup GAPC_SIG Generic Access Profile Controller Signaling PDU Handler. + * @ingroup GAPC + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_config.h" + +#if (BLE_GAPC) +#include "l2cc_pdu.h" + + +#if (BLE_CENTRAL) +/** + **************************************************************************************** + * @brief Sends parameter response + * + * @param[in] conidx connection index + * @param[in] result response result + * @param[in] pkt_id Packet identifier + **************************************************************************************** + */ +void gapc_sig_send_param_resp(uint8_t conidx, uint16_t result, uint8_t pkt_id); +#endif // (BLE_CENTRAL) + +/** + **************************************************************************************** + * @brief Handles reception of L2CAP signaling messages from peer device. + * + * @param[in] conidx Connection Index + * @param[in] pdu PDU Received + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +int gapc_sig_pdu_recv_handler(uint8_t conidx, struct l2cc_pdu *pdu); + +#endif // (BLE_GAPC) + +#endif // _GAPC_SIG_H_ + +/// @} GAPC_SIG diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gap/gapm/gapm_int.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gap/gapm/gapm_int.h new file mode 100755 index 0000000..71727d4 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gap/gapm/gapm_int.h @@ -0,0 +1,797 @@ +/** + **************************************************************************************** + * + * @file gapm_int.h + * + * @brief Generic Access Profile Manager Internal Header. + * + * Copyright (C) RivieraWaves 2009-2016 + * + **************************************************************************************** + */ + + +#ifndef _GAPM_INT_H_ +#define _GAPM_INT_H_ + +/** + **************************************************************************************** + * @addtogroup GAPM_INT Generic Access Profile Manager Internal + * @ingroup GAPM + * @brief defines for internal GAPM usage + * + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "gapm.h" +#include "gapm_task.h" +#include "common_bt.h" + + +/* + * DEFINES + **************************************************************************************** + */ + +/// Maximum number of GAP Manager process +#define GAPM_IDX_MAX 0x01 + +/// Scan filter size +#define GAPM_SCAN_FILTER_SIZE 10 + +/// check if current role is supported by configuration +#define GAPM_IS_ROLE_SUPPORTED(role_type)\ + ((gapm_env.role & (role_type)) == (role_type)) + +/// Number of supported activities in host +#define GAPM_ACTV_NB (BLE_ACTIVITY_MAX) +/// Invalid activity identifier +#define GAPM_ACTV_INVALID_IDX (0xFF) + +/* + * INTERNAL API TYPES + **************************************************************************************** + */ + + +/// Retrieve information about memory usage +struct gapm_dbg_get_mem_info_cmd +{ + /// GAPM requested operation: + /// - GAPM_DBG_GET_MEM_INFO: Get memory usage + uint8_t operation; +}; + +/// Indication containing information about memory usage. +/*@TRACE*/ +struct gapm_dbg_mem_info_ind +{ + /// peak of memory usage measured + uint32_t max_mem_used; + /// memory size currently used into each heaps. + uint16_t mem_used[KERNEL_MEM_BLOCK_MAX]; +}; + + +/// Operation type +enum gapm_op_type +{ + /// Configuration operation + GAPM_OP_CFG = 0x00, + + /// Air mode operation (scanning, advertising, connection establishment) + /// Note: Restriction, only one air operation supported. + GAPM_OP_AIR = 0x01, + /// GAP State for DH Key Generation + GAPM_OP_DHKEY = 0x02, + /// Max number of operations + GAPM_OP_MAX +}; + +/// GAPM states +enum gapm_state_id +{ + /// Idle state - no on going operation + GAPM_IDLE, + + /// Busy state - Configuration operation on going + GAPM_CFG_BUSY = 1 << GAPM_OP_CFG, + /// Busy state - Air operation on going + GAPM_AIR_BUSY = 1 << GAPM_OP_AIR, + /// Busy state - DH Key Calculation operation on going + GAPM_DHKEY_BUSY = 1 << GAPM_OP_DHKEY, + + /// Reset state - Reset operation on going + GAPM_DEVICE_SETUP = 1 << GAPM_OP_MAX, + + GAPM_STATE_MAX +}; + +/// Device configuration flags +/// 7 6 5 4 3 2 1 0 +/// +-----+----+----+----+----+----+----+----+ +/// | RFU | SC | CP | GA | RE |CTLP|HSTP|ADDR| +/// +-----+----+----+----+----+----+----+----+ +/// - Bit [0-2]: Address Type @see enum gapm_cfg_flag +/// Bit 0: 0 = Public address, 1 = Private address +/// Bit 2: 0 = Controller-based Privacy disabled, 1 = enabled +/// +/// - Bit [3] : Address to renew (only if privacy is enabled, 1 address to renew else 0) +/// - Bit [4] : Generated Address type (1 = Resolvable, 0 = Non Resolvable) +/// - Bit [5] : Preferred Connection parameters present in GAP DB +/// - Bit [6] : Service Change feature present +/// Configuration flag bit description +enum gapm_cfg_flag_def +{ + /// Address Type + GAPM_ADDR_TYPE_MASK = 0x07, + GAPM_ADDR_TYPE_LSB = 0x00, + /// Address to renew + GAPM_ADDR_RENEW_MASK = 0x08, + GAPM_ADDR_RENEW_LSB = 0x03, + /// Generated Address type + GAPM_RESOLV_ADDR_MASK = 0x10, + GAPM_RESOLV_ADDR_LSB = 0x04, + /// Preferred Connection parameters present in GAP DB + GAPM_PREF_CON_PAR_PRES_MASK = 0x20, + GAPM_PREF_CON_PAR_PRES_LSB = 0x05, +}; + +#if (RW_DEBUG) +/// Device configuration flags +/// 7 6 5 4 3 2 1 0 +/// +-----+----+----+----+----+----+----+----+ +/// | RFU |DBGT| DBG| +/// +-----+----+----+----+----+----+----+----+ +/// - Bit [0]: Enable Debug mode +/// - Bit [1]: Forward all L2cap traffic +enum gapm_dbg_cfg +{ + /// Enable Debug mode + GAPM_DBG_MODE_EN_MASK = 0x01, + GAPM_DBG_MODE_EN_LSB = 0x00, + + /// Enable Debug mode + GAPM_DBG_L2CAP_TRAFFIC_FWD_EN_MASK = 0x02, + GAPM_DBG_L2CAP_TRAFFIC_FWD_EN_LSB = 0x01, +}; +#endif // (RW_DEBUG) + +/// Activity states +enum gapm_actv_state +{ + /// Activity is being created - next state is CREATED + GAPM_ACTV_CREATING = 0, + /// Activity has been successfully created + GAPM_ACTV_CREATED, + /// Activity is being started - next state is STARTED + GAPM_ACTV_STARTING, + /// Activity has been successfully started + GAPM_ACTV_STARTED, + /// Activity is being stopped - next state is CREATED + GAPM_ACTV_STOPPING, + /// Activity is being deleted - no next state + GAPM_ACTV_DELETING, +}; + +/// Connection role +enum gapm_conn_role +{ + /// Master + GAPM_ROLE_MASTER = 0, + /// Slave + GAPM_ROLE_SLAVE, +}; + +/* + * MACROS + **************************************************************************************** + */ +/// Macro used to retrieve field +#define GAPM_F_GET(data, field)\ + (((data) & (GAPM_MASK_ ## field)) >> (GAPM_POS_ ## field)) + +/// Macro used to set field +#define GAPM_F_SET(data, field, val)\ + (data) = (((data) & ~(GAPM_MASK_ ## field)) \ + | ((val << (GAPM_POS_ ## field)) & (GAPM_MASK_ ## field))) + + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + +/// Information about registered LE_PSM +struct gapm_le_psm_info +{ + /// List header structure to put information within a list + struct common_list_hdr hdr; + + /// LE Protocol/Service Multiplexer + uint16_t le_psm; + + /// Registered task identifier + kernel_task_id_t task_id; + + /// Security level + /// 7 6 5 4 3 2 1 0 + /// +---+---+---+---+---+---+---+---+ + /// |MI | RFU |EKS|SEC_LVL| + /// +---+---+---+---+---+---+---+---+ + /// bit[0-1]: Security level requirement (0=NO_AUTH, 1=UNAUTH, 2=AUTH, 3=SEC_CON) + /// bit[2] : Encryption Key Size length must have 16 bytes + /// bit[7] : Multi-instantiated task + uint8_t sec_lvl; + + /// Number of established link + uint8_t nb_est_lk; +}; + +/// GAP Manager environment structure +struct gapm_env_tag +{ + /// Request operation Kernel message + void* operation[GAPM_OP_MAX]; + + /// Array of pointers to the allocated activities + struct gapm_actv_tag *actvs[GAPM_ACTV_NB]; + + #if (BLE_LECB) + /// Registered list of LE Protocol/Service Multiplexer for LE Credit Based Connection + struct common_list reg_le_psm; + #endif // (BLE_LECB) + + #if (BLE_CENTRAL || BLE_PERIPHERAL) + /// Bit field use to know if periodic ADV sync transfer establishment on-going onto a specific connection index + uint32_t past_estab_bf; + #endif // (BLE_CENTRAL || BLE_PERIPHERAL) + + #if (BLE_ATTS) + /// GAP service start handle + uint16_t svc_start_hdl; + #endif // (BLE_ATTS) + + #if (BLE_BROADCASTER) + /// Maximum length of advertising data that can be pushed to the controller + uint16_t max_adv_data_len; + #endif //(BLE_BROADCASTER) + + /// Duration before regenerate device address when privacy is enabled. - in seconds + uint16_t renew_dur; + /// Device IRK used for resolvable random BD address generation (MSB -> LSB) + struct gap_sec_key irk; + + /// Current device Address + bd_addr_t addr; + /// Device Role + uint8_t role; + /// Number of BLE connection + uint8_t connections; + /// Device configuration flags - (@see enum gapm_cfg_flag_def) + uint8_t cfg_flags; + /// Pairing mode authorized (see enum gapm_pairing_mode) + uint8_t pairing_mode; + /// Maximum device MTU size + uint16_t max_mtu; + /// Maximum device MPS size + uint16_t max_mps; + + #if(BLE_ISO_MODE_0_PROTOCOL) + /// Audio configuration flag (see gapm_audio_cfg_flag) + uint16_t audio_cfg; + #endif // (BLE_ISO_MODE_0_PROTOCOL) + + #if (BLE_LECB) + /// Maximum number of allowed LE Credit Based channels + uint8_t max_nb_lecb; + /// Current number of LE Credit Based channel connections established + uint8_t nb_lecb; + #endif // (BLE_LECB) + + #if (BLE_BROADCASTER) + /// Number of advertising sets supported by controller + uint8_t max_adv_set; + /// Number of created advertising activities + uint8_t nb_adv_actv; + #endif //(BLE_BROADCASTER) + #if (BLE_OBSERVER) + /// Activity identifier for currently started scanning activity + uint8_t scan_actv_idx; + #endif //(BLE_OBSERVER) + #if (BLE_CENTRAL) + /// Activity identifier for currently started initiating activity + uint8_t init_actv_idx; + #endif //(BLE_CENTRAL) + /// Activity identifier currently used for air operation + uint8_t actv_idx; + + #if (BLE_OBSERVER) + /// Activity in Periodic sync establishment state + uint8_t per_sync_estab_actv_idx; + #endif //(BLE_OBSERVER) + + /// Number of created activities + uint8_t created_actvs; + /// Number of started activities + uint8_t started_actvs; + /// Number of started activities that can lead to connection establishment (connectable + /// advertising or initiating) + uint8_t connect_actvs; + /// Number of devices in the white list + uint8_t nb_dev_wl; + /// State of GAPM ADDR module + uint8_t gapm_addr_state; + + #if (RW_DEBUG) + /// Debug configuration @see gapm_dbg_cfg + uint8_t dbg_cfg; + #endif // (RW_DEBUG) +}; + +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ +/// GAP Manager environment variable. +extern struct gapm_env_tag gapm_env; + + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Initialize GAP attribute database + * + * @param[in] start_hdl Service Start Handle + * @param[in] feat Attribute database features + * + * @return status code of attribute database initialization + * - @ref ATT_ERR_NO_ERROR: If database creation succeeds. + * - @ref ATT_ERR_INVALID_HANDLE: If start_hdl given in parameter + nb of attribute override + * some existing services handles. + * - @ref ATT_ERR_INSUFF_RESOURCE: There is not enough memory to allocate service buffer. + * or of new attribute cannot be added because all expected + * attributes already add + **************************************************************************************** + */ +uint8_t gapm_init_attr(uint16_t start_hdl, uint32_t feat); + +/** + **************************************************************************************** + * @brief Send operation completed message according to operation type. + * Perform also am operation clean-up + * + * @param[in] op_type Operation type + * @param[in] status Command status + ***************************************************************************************** + */ +void gapm_send_complete_evt(uint8_t op_type, uint8_t status); + +/** + **************************************************************************************** + * @brief Send operation completed message with status error code not related to a + * running operation. + * + * @param[in] operation Operation code + * @param[in] requester requester of operation + * @param[in] status Error status code + **************************************************************************************** + */ +void gapm_send_error_evt(uint8_t operation, const kernel_task_id_t requester, uint8_t status); + + +/** + **************************************************************************************** + * @brief Get operation pointer + * + * @param[in] op_type Operation type. + * + * @return operation pointer on going + **************************************************************************************** + */ +__INLINE void* gapm_get_operation_ptr(uint8_t op_type) +{ + BLE_ASSERT_ERR(op_type < GAPM_OP_MAX); + // return operation pointer + return gapm_env.operation[op_type]; +} + + +/** + **************************************************************************************** + * @brief Set operation pointer + * + * @param[in] op_type Operation type. + * @param[in] op Operation pointer. + * + **************************************************************************************** + */ +__INLINE void gapm_set_operation_ptr(uint8_t op_type, void* op) +{ + BLE_ASSERT_ERR(op_type < GAPM_OP_MAX); + // update operation pointer + gapm_env.operation[op_type] = op; +} + + +/** + **************************************************************************************** + * @brief Check if current operation can be processed or not. + * if it can be proceed, initialize an operation request. + * If a command complete event with error code can be triggered. + * + * Function returns how the message should be handled by message handler. + * + * @param[in] op_type Operation type. + * @param[in] op_msg Requested operation message (note op_msg cannot be null) + * @param[in] supp_ops Supported operations array. + * Latest array value shall be GAPM_NO_OP. + * + * @return operation can be executed if message status equals KERNEL_MSG_NO_FREE, + * else nothing to do, just exit from the handler. + **************************************************************************************** + */ +int gapm_process_op(uint8_t op_type, void* op_msg, enum gapm_operation* supp_ops); + +/** + **************************************************************************************** + * @brief Get operation on going + * + * @param[in] op_type Operation type. + * + * @return operation code on going + **************************************************************************************** + */ +uint8_t gapm_get_operation(uint8_t op_type); + +/** + **************************************************************************************** + * @brief Get requester of on going operation + * + * @param[in] op_type Operation type. + * + * @return task that requests to execute the operation + **************************************************************************************** + */ +kernel_task_id_t gapm_get_requester(uint8_t op_type); + + + + +#if (BLE_GAPC) +/** + **************************************************************************************** + * @brief A connection has been created, initialize host stack to be ready for connection. + * + * @param[in] msgid Message id + * @param[in] con_params Connection parameters from lower layers + * + * @return Connection index allocated to the new connection. + **************************************************************************************** + */ +uint8_t gapm_con_create(kernel_msg_id_t const msgid, struct hci_le_enh_con_cmp_evt const *con_params); +#endif // (BLE_GAPC) + +/** + **************************************************************************************** + * @brief Checks validity of the address type + * + * @param[in] addr_type Address type + **************************************************************************************** + */ +uint8_t gapm_addr_check( uint8_t addr_type); + +/** + **************************************************************************************** + * @brief Checks validity of the Data Length Suggested values + * + * @param[in] sugg_oct Suggested octets + * @param[in] sugg_time Suggested time + **************************************************************************************** + */ +uint8_t gapm_dle_val_check(uint16_t sugg_oct, uint16_t sugg_time); + + + +/** + **************************************************************************************** + * @brief Update task state + * + * @param[in] operation that modify the state + * @param[in] set state to busy (true) or idle (false) + * + **************************************************************************************** + */ +void gapm_update_state(uint8_t operation, bool busy); + + + +#if (BLE_LECB) + + +/** + **************************************************************************************** + * @brief Find Information about LE_PSM registered in GAPM + * + * @param[in] le_psm LE Protocol/Service Multiplexer + * + * @return Null if not found or LE_PSM info structure + **************************************************************************************** + */ +struct gapm_le_psm_info* gapm_le_psm_find(uint16_t le_psm); + + +/** + **************************************************************************************** + * @brief Remove all registered LE_PSM + **************************************************************************************** + */ +void gapm_le_psm_cleanup(void); +#endif // (BLE_LECB) + +/** + **************************************************************************************** + * @brief Reset the environment by cleaning all existing activities + * + * @param[in] init_type Type of initialization (@see enum rwip_init_type) + **************************************************************************************** + */ +void gapm_actv_reset(uint8_t init_type); + +/** + **************************************************************************************** + * @brief Allocate an activity structure for a given identifier. Provided identifer is + * then no more marked as available. + * It is considered here that provided activity identifier is an available one. + * + * @param[in] actv_idx Activity index + * @param[in] size Size of the activity structure to be allocated + * + * @return Pointer to the allocated activity structure + **************************************************************************************** + */ +struct gapm_actv_tag *gapm_actv_alloc(uint8_t actv_idx, uint8_t size); + +/** + **************************************************************************************** + * @brief Retrieve activity for which an HCI command complete event has been received. + * Note that at any time only one HCI command complete event can be expected by GAPM. + * Hence only one activity can be found. + * This function also check that the operation code of the complete command well + * match with the command that has been sent for the foun activity. + * + * @param[in|out] pp_actv Pointer to the variable that will contain address of + * activity structure for which command complete event + * has been received. + * @param[in] opcode Command operation code for which a command complete event has + * been received + * + * @return true if activity has been retrieved, else false + **************************************************************************************** + */ +bool gapm_actv_retrieve_cmd_cmp_evt(struct gapm_actv_tag **pp_actv, uint16_t opcode); + +/** + **************************************************************************************** + * @brief Get own address type to be sent in HCI commands. + * + * @param[in] app_addr_type Address type provided by application using GAPM_SET_DEV_CONFIG_CMD. + * + * @return Own address type value + * - 0: Public Device Address + * - 1: Random Device Address + * - 2: Controller generates the RPA based on the local IRK from the resolving list. + * If the resolving list contains no matching entry, use the public address + * - 3: Controller generates the RPA based on the local IRK from the resolving list. + * If the resolving list contains no matching entry, use the random address that has + * been set using HCI LE Set Advertising Set Random Address. + **************************************************************************************** + */ +uint8_t gapm_actv_get_hci_own_addr_type(uint8_t app_addr_type); + +/** + **************************************************************************************** + * @brief Notify the activity module that activity creation procedure is over. + * + * @param[in] p_actv Pointer to the structure describing the created activity + * @param[in] error Indicate if an error has been raised during activity creation + **************************************************************************************** + */ +void gapm_actv_created(struct gapm_actv_tag *p_actv, uint8_t error); + +/** + **************************************************************************************** + * @brief Notify the activity module that a start activity procedure is over + * + * @param[in] p_actv Pointer to the structure describing the started activity + * @param[in] error Indicate if an error has been raised during activity start procedure + **************************************************************************************** + */ +void gapm_actv_started(struct gapm_actv_tag *p_actv, uint8_t error); + +/** + **************************************************************************************** + * @brief Notify the activity module that an activity has well been stopped. + * + * @param[in] p_actv Pointer to the structure describing the stopped activity + * @param[in] status Activity stop operation status + **************************************************************************************** + */ +void gapm_actv_stopped(struct gapm_actv_tag *p_actv, uint8_t status); + +/** + **************************************************************************************** + * @brief Function used once an activity has been cleaned and can be deleted + * + * @param[in] p_actv Pointer to the structure describing the stopped activity + * @param[in] error Indicate if activity has well been stopped + **************************************************************************************** + */ +void gapm_actv_deleted(struct gapm_actv_tag *p_actv); + +/** + **************************************************************************************** + * @brief Callback function used by GAPM ADDR module in order to inform the GAPM ACTV + * module that a random address (generated or not) has been set in the controller + * upon its request. + * + * @param[in] p_actv Pointer to the activity structure for which random address has + * been set. + **************************************************************************************** + */ +void gapm_actv_rand_addr_set_ind(struct gapm_actv_tag *p_actv); + +#if (BLE_BROADCASTER) +/** + **************************************************************************************** + * @brief Allocate an activity structure to be used for an advertising activity. + * + * @param[in] actv_idx Allocated activity identifier + * @param[in] p_param GAPM_ACTIVITY_CREATE_CMD message parameters + **************************************************************************************** + */ +uint8_t gapm_adv_create(uint8_t actv_idx, struct gapm_activity_create_adv_cmd *p_param); +#endif //(BLE_BROADCASTER) + +#if (BLE_OBSERVER) +/** + **************************************************************************************** + * @brief Clean content of a scan activity, more specifically the stored fragments + * of advertising report and the filtering list. + * + * @param[in] p_actv Pointer to the scanning activity structure. + **************************************************************************************** + */ +void gapm_scan_actv_clean(struct gapm_actv_tag *p_actv); + +/** + **************************************************************************************** + * @brief Allocate an activity structure to be used for a scanning activity. + * + * @param[in] actv_idx Allocated activity identifier + * @param[in] p_param GAPM_ACTIVITY_CREATE_CMD message parameters + * + * @return GAP_ERR_NO_ERROR if creation of activity can be started, + * GAP_ERR_COMMAND_DISALLOWED if activity cannot be started + * GAP_ERR_INSUFF_RESOURCES if not enough memory is found for activity structure + * allocation. + **************************************************************************************** + */ +uint8_t gapm_scan_create(uint8_t actv_idx, struct gapm_activity_create_cmd *p_param); +#endif //(BLE_OBSERVER) + +#if (BLE_CENTRAL) +/** + **************************************************************************************** + * @brief Allocate an activity structure to be used for an initiating activity. + * + * @param[in] actv_idx Allocated activity identifier + * @param[in] p_param GAPM_ACTIVITY_CREATE_CMD message parameters + **************************************************************************************** + */ +uint8_t gapm_init_create(uint8_t actv_idx, struct gapm_activity_create_cmd *p_param); + +/** + **************************************************************************************** + * @brief Function used by GAPM_ACTV module to inform GAPM_INIT that a new connection + * has been established. + * If current initiating type is a name discovery, it triggers sending of a GAPC_GET_INFO_CMD + * in order to retrieve the peer device name. + * If current initiating type is an automatic connection establishment, a new HCI LE + * Extended Create Connection command will be sent to the controller if not all device in + * the white list have been connected. + * If no more connection is expected, the activity is stopped. + * + * @param[in] conidx Connection index allocated for the newly established connection + * + * @return True if the activity has to be stopped, else false. + **************************************************************************************** + */ +bool gapm_init_connection_ind(uint8_t conidx); +#endif //(BLE_CENTRAL) + +#if (BLE_OBSERVER) + /** + **************************************************************************************** + * @brief Allocate an activity structure to be used for a periodic synchronization activity. + * + * @param[in] actv_idx Allocated activity identifier + * @param[in] p_param GAPM_ACTIVITY_CREATE_CMD message parameters + * + * @return GAP_ERR_NO_ERROR if activity creation has ended properly, GAP_ERR_INSUFF_RESOURCES + * if no available memory has been found for activity allocation. + **************************************************************************************** + */ +uint8_t gapm_per_sync_create(uint8_t actv_idx, struct gapm_activity_create_cmd *p_param); + +/** + **************************************************************************************** + * @brief Request to clear all report fragments stored in the periodic synchronization + * activity + * + * @param[in] p_actv_per_sync Pointer to the activity structure + **************************************************************************************** + */ +void gapm_per_sync_clear_fragments(struct gapm_actv_per_sync_tag *p_actv_per_sync); +#endif //(BLE_OBSERVER) + +/** + **************************************************************************************** + * @brief Initialize GAPM address manager module + **************************************************************************************** + */ +void gapm_addr_init(void); + +/** + **************************************************************************************** + * @brief Function to be used to check if address type provided for a scanning or an + * initiating activity is valid or not. + * As a same address shall be shared between all these activities, all created scanning and + * initiating activities shall have the same address type. + * + * @param[in] addr_type Address type to be checked + * + * @return true if provided address type is valid, else false + **************************************************************************************** + */ +bool gapm_is_addr_type_valid(uint8_t addr_type); + +/** + **************************************************************************************** + * @brief Request to clear all report fragments stored in the periodic synchronization + * activity + * + * @param[in] p_actv Pointer to the activity structure for which a random has to be + * generated and/or set in the controller. + **************************************************************************************** + */ +void gapm_addr_set_rand_addr(struct gapm_actv_tag *p_actv); + +/** + **************************************************************************************** + * @brief Sends a basic HCI command (with no parameter) + * + * @param[in] opcode Command opcode + **************************************************************************************** + */ +void hci_basic_cmd_send_2_controller(uint16_t opcode); + + +/* + * TASK DESCRIPTOR DECLARATIONS + **************************************************************************************** + */ + +/// @} GAPM_INT + +#endif /* _GAPM_INT_H_ */ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gatt/attc/attc.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gatt/attc/attc.h new file mode 100755 index 0000000..075e353 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gatt/attc/attc.h @@ -0,0 +1,127 @@ +/** + **************************************************************************************** + * + * @file attc.h + * + * @brief Header file - ATTC. + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + +#ifndef ATTC_H_ +#define ATTC_H_ + +/** + **************************************************************************************** + * @addtogroup ATTC Attribute Client + * @ingroup ATT + * @brief Attribute Protocol Client + * + * The ATTC module is responsible for handling messages intended for the attribute + * profile client. It has defined interfaces with @ref ATTM "ATTM". + * + * @{ + * + **************************************************************************************** + */ +#include "rwip_config.h" + +#include +#include "l2cc.h" +#include "kernel_task.h" + +#if (BLE_ATTC) +/* + * INCLUDE FILES + **************************************************************************************** + */ +/* + * DEFINES + **************************************************************************************** + */ + +/// Allocate a Attribute PDU packet for a specific attribute request. +#define ATTC_ALLOCATE_ATT_REQ(conidx, opcode, pdu_type, value_len)\ + L2CC_ATT_PDU_ALLOC_DYN(conidx, opcode, KERNEL_BUILD_ID(TASK_BLE_GATTC, conidx), pdu_type, value_len) + +/* + * DATA STRUCTURES + **************************************************************************************** + */ + +/// Peer device event registration +struct attc_register_evt +{ + /// list header + struct common_list_hdr hdr; + /// Attribute start handle + uint16_t start_hdl; + /// Attribute end handle + uint16_t end_hdl; + /// Task to be notified + kernel_task_id_t task; +}; + + +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ +/** + **************************************************************************************** + * @brief Sends Indication reception confirmation message + * + * @param[in] conidx connection index + * + **************************************************************************************** + */ +void attc_send_hdl_cfm(uint8_t conidx); + +/** + **************************************************************************************** + * @brief Sends write execute. + * + * @param[in] conidx connection index + * @param[in] flag write execute flag (write or discard) + * + **************************************************************************************** + */ +void attc_send_execute(uint8_t conidx, uint8_t flag); + + +/** + **************************************************************************************** + * @brief Send a PDU Attribute request packet + * + * @param[in] conidx Index of the connection with the peer device + * @param[in] pdu PDU Packet + **************************************************************************************** + */ +void attc_send_att_req(uint8_t conidx, void *pdu); + +#endif /* (BLE_ATTC) */ + +#if (BLE_CENTRAL || BLE_PERIPHERAL) +/** + **************************************************************************************** + * @brief Handles reception of PDU Packet + * + * @param[in] conidx Index of the connection with the peer device + * @param[in] param Received PDU Packet + * + * @return If message has been proceed or consumed + **************************************************************************************** + */ +int attc_l2cc_pdu_recv_handler(uint8_t conidx, struct l2cc_pdu_recv_ind *param); +#endif /* #if (BLE_CENTRAL || BLE_PERIPHERAL) */ + +/// @} ATTC +#endif // ATT_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gatt/attm/attm_db.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gatt/attm/attm_db.h new file mode 100755 index 0000000..62cbb71 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gatt/attm/attm_db.h @@ -0,0 +1,420 @@ +/** + **************************************************************************************** + * + * @file attm_db.h + * + * @brief Header file - ATTM. + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + +#ifndef ATTM_DB_H_ +#define ATTM_DB_H_ + +/** + **************************************************************************************** + * @addtogroup ATTDB Database + * @ingroup ATTM + * @brief Attribute Protocol Database + * + * The ATTDB module is responsible for providing different sets of attribute databases + * for Attribute Profile server. + * + * This module can be tailored by client, to match the requirement of the desired database. + * + * @{ + * + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_config.h" +#if (BLE_ATTS) +#include +#include "rwip_config.h" +#include "kernel_task.h" +#include "attm.h" +#include "gattm_task.h" +#include "common_bt.h" + +/* + * DEFINES + **************************************************************************************** + */ + +/** + * Extended Service permissions + * + * 7 6 5 4 3 2 1 0 + * +----+----+----+----+----+----+----+----+ + * | RFU |HIDE| + * +----+----+----+----+----+----+----+----+ + * + * Bit [0] : Hide service visibility + * Bit [1-7]: Reserved for future use + */ +enum attm_ext_svc_perm_mask +{ + /// Service visibility - Hide = 1 + PERM_MASK_EXT_SVC_HIDE = 0x01, + PERM_POS_EXT_SVC_HIDE = 0, +}; + + +/* + * TYPE DEFINITION + **************************************************************************************** + */ +#if(BLE_ATTS) + +/** + **************************************************************************************** + * @brief Callback definition used to retrieve value of database hash + * + * @param[in] status Execution status + * @param[in] p_hash Hash value computed + * @param[in] cb_info Source info used to retrieve requester + **************************************************************************************** + */ +typedef void (*attmdb_hash_res_cb) (uint8_t status, const uint8_t* p_hash, uint32_t cb_info); + +/** + * Attribute Description + */ +struct attm_att_desc +{ + /** + * 16 bits UUID or data offset used to retrieve 32 or 128 bits UUID in service memory block + */ + uint16_t uuid; + + /** + * Attribute Permission (@see attm_perm_mask) + */ + uint16_t perm; + + /** + * value information (@see attm_value_perm_mask) + */ + union att_info + { + /// attribute max length (RI = 1) + uint16_t max_length; + + /// attribute value offset pointer (RI = 0) + uint16_t offset; + } info; +}; + +/// attribute value if present in database +struct attm_att_value +{ + /// Maximum attribute length + uint16_t max_length; + /// currrent attribute length that can be read. + uint16_t length; + ///value data pointer + uint8_t value[__ARRAY_EMPTY]; +}; + +/// service description +struct attm_svc_desc +{ + /// Service Start Handle + uint16_t start_hdl; + /// Service End Handle + uint16_t end_hdl; + /// Task identifier that manages service + uint16_t task_id; + + /// Service Permission (@see attm_svc_perm_mask) + uint8_t perm; + /// Extended Service Permission (@see attm_ext_svc_perm_mask) + uint8_t ext_perm; + + /// Service 16 bits UUID (LSB First) or data offset used to retrieve 32 or 128 bits + /// UUID in service memory block + uint16_t uuid; +}; + +/** + * Service description present in attribute database + */ +struct attm_svc +{ + /// Next Service + struct attm_svc* next; + /// service description + struct attm_svc_desc svc; + /// List of attribute description present in service. + struct attm_att_desc atts[__ARRAY_EMPTY]; +}; + +/// Attribute element information +struct attm_elmt +{ + /// element info + union elem_info + { + /// attribute info pointer + struct attm_att_desc* att; + + /// service info pointer + struct attm_svc_desc* svc; + } info; + + /// use to know if current element is a service or an attribute + bool service; +}; + +/// Structure use to compute data hash +struct attm_db_hash_input +{ + /// function that handle computation result + attmdb_hash_res_cb res_cb; + /// value of the hash to compute + uint8_t value[__ARRAY_EMPTY]; +}; + + +/// ATTM General Information Manager +struct attm_db +{ + /// Hash input pointer used for hash computation + struct attm_db_hash_input* p_hash_input; + + /** + * ************************************************************************************** + * @brief Attribute database + * + * The Attribute database is a list of attribute services sorted by handle number. + * This database shall be initiate by GAP, GATT, profiles and application process at + * startup and must not change during runtime. + * + * Database initialization shall be deterministic in order to always have service handle + * at same position in database during all product life-cycle. This is required since + * database client can save position of services in database to not perform service + * discovery at each connection. + *************************************************************************************** + */ + struct attm_svc* svcs; + + /** + *************************************************************************************** + * Last attribute service searched. + * + * Used as a cached variable, it's used to reduce handle search duration. + *************************************************************************************** + */ + struct attm_svc* cache; + + /// Database hash value + uint8_t hash[KEY_LEN]; + + /// Used to know if database hash is valid or not + bool hash_valid; + + /** + * Temporary value used for read operation on service and characteristics attributes + */ + uint8_t temp_val[ATT_UUID_128_LEN + ATT_HANDLE_LEN + ATT_HANDLE_LEN]; +}; + + + + + +#endif //(BLE_ATTS) + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + * Check if Service handle Range can be allocated in Database, and if handle should be + * dynamically allocated, calculate first available handle range. + * + * @param[in|out] svc_desc Service information to add in DB + * + * @return status of operation + */ +uint8_t attmdb_svc_check_hdl(struct gattm_svc_desc* svc_desc); + +/** + **************************************************************************************** + * @brief Add a service in database. + * + * According to service start handle and number of attribute, ATTM DB allocate a set of + * attribute handles, then using other parameters it allocate a buffer used to describe + * service, and allocate attributes + their values. + * + * If start_hdl = 0, it allocated service using first available handle (start_hdl is + * modified); else it will allocate service according to given start handle. + * + * + * @param[in|out] svc_desc Service description. + * + * @return Command status code: + * - @ref ATT_ERR_NO_ERROR: If service allocation succeeds. + * - @ref ATT_ERR_INVALID_HANDLE: If start_hdl given in parameter or UUIDs value invalid + * - @ref ATT_ERR_INSUFF_RESOURCE: There is not enough memory to allocate service buffer. + **************************************************************************************** + */ +uint8_t attmdb_add_service(struct gattm_svc_desc* svc_desc); + +/** + **************************************************************************************** + * @brief Compute Hash of the internal database. + * + * + * @param[in] res_cb Callback that will handle the result. + * @param[in] cb_info Requester source information value returned in callback + * + * @return Command status code (if GAP_ERR_NO_ERROR, wait for callback execution) + **************************************************************************************** + */ +uint8_t attmdb_hash_compute(attmdb_hash_res_cb res_cb, uint32_t cb_info); + +/** + **************************************************************************************** + * @brief Search in database from which service attribute handle comes from. + * + * @param[in] handle Attribute handle. + * + * @return Services that contains attribute handle; NULL if handle not available in + * database. + **************************************************************************************** + */ +struct attm_svc * attmdb_get_service(uint16_t handle); + +/** + **************************************************************************************** + * @brief Search in database Attribute pointer using attribute handle. + * + * @param[in] handle Attribute handle. + * @param[out] elmt Attribute element to fill + * + * @return Command status code: + * - @ref ATT_ERR_NO_ERROR: If attribute found. + * - @ref ATT_ERR_INVALID_HANDLE: If No Attribute found + **************************************************************************************** + */ +uint8_t attmdb_get_attribute(uint16_t handle, struct attm_elmt*elmt); + +/** + **************************************************************************************** + * @brief Retrieve attribute at or after specified handle + * + * Retrieve first attribute with handle >= parameter handle. + * Parameter handle is updated according found attribute. + * + * @param[in|out] handle Attribute handle. + * @param[out] elmt Attribute element to fill + * + * @return Command status code: + * - @ref ATT_ERR_NO_ERROR: If attribute found. + * - @ref ATT_ERR_INVALID_HANDLE: If No Attribute found + **************************************************************************************** + */ +uint8_t attmdb_get_next_att(uint16_t * handle, struct attm_elmt*elmt); + +/** + **************************************************************************************** + * Check if attribute element UUID is equals to uuid given in parameter. + * + * @param elmt Attribute element that can be a UUID 16 or 128 bits + * @param uuid16 UUID 16 bits to compare + * + * @return True if UUIDs matches, False else. + **************************************************************************************** + */ +bool attmdb_uuid16_comp(struct attm_elmt *elmt, uint16_t uuid16); + +/** + **************************************************************************************** + * @brief Retrieve attribute value Max Length + * + * @param[in] elmt Attribute element information + * @param[out] length Max length Size of attribute value + * + * @return Command status code: + * - @ref ATT_ERR_NO_ERROR: If request succeeds + * - @ref ATT_ERR_REQUEST_NOT_SUPPORTED: If attribute is read only + **************************************************************************************** + */ +uint8_t attmdb_get_max_len(struct attm_elmt* elmt, att_size_t* length); + + +/** + **************************************************************************************** + * @brief Retrieve attribute UUID + * + * @param[in] elmt Attribute information. + * @param[out] uuid_len Size of attribute UUID + * @param[out] uuid UUID value to update + * @param[in] srv_uuid For a service, if set, return service UUID + * @param[in] air Prepare UUID for the air (For a 32 bit UUID, returns a 128 bit UUID) + * + * @return Command status code: + * - @ref ATT_ERR_NO_ERROR: If request succeeds + * - @ref ATT_ERR_INVALID_HANDLE: If handle doesn't exist in database + **************************************************************************************** + */ +uint8_t attmdb_get_uuid(struct attm_elmt *elmt, uint8_t* uuid_len, uint8_t* uuid, bool srv_uuid, bool air); + +/** + **************************************************************************************** + * @brief Retrieve attribute permission + * If access mask is set, service authentication or encryption key size value can be loaded. + * + * @param[in] handle Attribute handle. + * @param[out] perm Permission value to return + * @param[in] mode_mask Mode Access mask to check type of access + * parameter (0 return full attribute permission) + * @param[in] perm_mask Permission Access mask to check only specific permission + * @param[in|out] elmt Attribute information + * + * @return Command status code: + * - @ref ATT_ERR_NO_ERROR: If request succeeds + * - @ref ATT_ERR_INVALID_HANDLE: If handle doesn't exist in database. + * - @ref ATT_ERR_REQUEST_NOT_SUPPORTED: If mode is disabled. + * - @ref ATT_ERR_INSUFF_AUTHOR: when service is disabled. + * - @ref ATT_ERR_INSUFF_ENC_KEY_SIZE: + **************************************************************************************** + */ +uint8_t attmdb_att_get_permission(uint16_t handle, uint16_t* perm, uint16_t mode_mask, + uint16_t perm_mask, struct attm_elmt *elmt); + + +#if (RW_DEBUG) + +/** + **************************************************************************************** + * @brief Retrieve number of services. + * + * @return number of services + **************************************************************************************** + */ +uint8_t attmdb_get_nb_svc(void); + +/** + **************************************************************************************** + * @brief Retrieve services informations + * + * @param[in] svc_info Services information array to update + **************************************************************************************** + */ +void attmdb_get_svc_info(struct gattm_svc_info* svc_info); +#endif /* (RW_DEBUG) */ + +#endif // #if (BLE_ATTS) + +/// @} ATTDB +#endif // ATTM_DB_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gatt/atts/atts.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gatt/atts/atts.h new file mode 100755 index 0000000..767d488 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gatt/atts/atts.h @@ -0,0 +1,157 @@ +/** + **************************************************************************************** + * + * @file atts.h + * + * @brief Header file - ATTS. + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + +#ifndef ATTS_H_ +#define ATTS_H_ + +/** + **************************************************************************************** + * @addtogroup ATTS Attribute Server + * @ingroup ATT + * @brief Attribute Protocol Server + * + * The ATTS module is responsible for handling messages intended for the attribute + * profile server. It has defined interfaces with @ref ATTM "ATTM". + * + * + * @{ + * + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_config.h" +#if (BLE_ATTS) +#include "att.h" +#include "compiler.h" +#include +#include "common_list.h" +#include "gattc_task.h" +#include "l2cc.h" + +/* + * DEFINES + **************************************************************************************** + */ + + + +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ + + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + + +/** + * Confirmation of write signed (signature verified) + * + * @param[in] conidx Connection Index + * @param[in] length Signed Data Length + * @param[in] sign_data Signed Data + */ +void atts_write_signed_cfm(uint8_t conidx, uint16_t length, uint8_t* sign_data); + + +/** + **************************************************************************************** + * @brief Send an attribute error response to peer. + * + * @param[in] conidx Index of the connection with the peer device + * @param[in] opcode failing operation code + * @param[in] uuid attribute UUID + * @param[in] error error code + **************************************************************************************** + */ +void atts_send_error(uint8_t conidx, uint8_t opcode, uint16_t uuid, uint8_t error); + + +/** + **************************************************************************************** + * @brief Format the Write Response PDU and send it after receiving a Write Request PDU + * @param[in] conidx Index of the connection with the peer device + * @param[in] atthdl Attribute handle for which to send the response + * @param[in] status ATT error code + **************************************************************************************** + */ +void atts_write_rsp_send(uint8_t conidx, uint16_t atthdl, uint8_t status); + + +/** + **************************************************************************************** + * @brief Sends a value notification/indication command + * + * @param[in] conidx Connection Index + * @param[in] event Event parameters to send + * + * @return If notification can be sent or not + **************************************************************************************** + */ +uint8_t atts_send_event(uint8_t conidx, struct gattc_send_evt_cmd *event); + + +/** + * @brief Clear allocated prepare write temporary data. + * + * @param[in] conidx connection index + */ +void atts_clear_prep_data(uint8_t conidx); + + +/** + * @brief Clear allocated temporary data used for ATTS response. + * + * @param[in] conidx connection index + */ +void atts_clear_rsp_data(uint8_t conidx); + +/** + * @brief Clear temporary attribute read data present in cache. + * + * @param[in] conidx connection index + */ +void atts_clear_read_cache(uint8_t conidx); + +/** + * @brief Process execution of a received ATTS PDU. + * + * @param conidx connection index + */ +void atts_process_pdu(uint8_t conidx); + +/// @} ATTS +#endif /* (BLE_ATTS) */ + +#if (BLE_CENTRAL || BLE_PERIPHERAL) +/** + **************************************************************************************** + * @brief Handles reception of PDU Packet + * + * @param[in] conidx Index of the connection with the peer device + * @param[in] param Received PDU Packet + * + * @return If message has been proceed or consumed + **************************************************************************************** + */ +int atts_l2cc_pdu_recv_handler(uint8_t conidx, struct l2cc_pdu_recv_ind *param); +#endif /* #if (BLE_CENTRAL || BLE_PERIPHERAL) */ + +#endif // ATTS_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gatt/gatt.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gatt/gatt.h new file mode 100755 index 0000000..34577eb --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gatt/gatt.h @@ -0,0 +1,72 @@ +/** + **************************************************************************************** + * + * @file gatt.h + * + * @brief Header file - GATT. + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + +#ifndef GATT_H_ +#define GATT_H_ + +/** + **************************************************************************************** + * @addtogroup GATT Generic Attribute Profile + * @ingroup HOST + * @brief Generic Attribute Profile. + * + * The GATT module is responsible for providing an API for all attribute related operations. + * It is responsible for all the service framework activities using the Attribute protocol + * for discovering services and for reading and writing characteristic values on a peer device. + * To achieve this, the GATT interfaces with @ref ATTM "ATTM", @ref ATTC "ATTC" and the + * @ref ATTS "ATTS". + * + * @{ + **************************************************************************************** + */ +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_config.h" +#include "att.h" + + +/* + * DEFINE DECLARATIONS + **************************************************************************************** + */ + +#if (BLE_ATTS) +/// GATT Attribute database handles +/// Generic Attribute Profile Service +enum gatt_db_att +{ + GATT_IDX_PRIM_SVC, + + GATT_IDX_CHAR_SVC_CHANGED, + GATT_IDX_SVC_CHANGED, + GATT_IDX_SVC_CHANGED_CFG, + + GATT_IDX_CHAR_CLI_SUP_FEAT, + GATT_IDX_CLI_SUP_FEAT, + + GATT_IDX_CHAR_DB_HASH, + GATT_IDX_DB_HASH, + + GATT_IDX_NUMBER +}; +#endif /* (BLE_ATTS)*/ + +/* + * Type Definition + **************************************************************************************** + */ + +/// @} GATT +#endif // GATT_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gatt/gattc/gattc_int.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gatt/gattc/gattc_int.h new file mode 100755 index 0000000..e1e2b94 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gatt/gattc/gattc_int.h @@ -0,0 +1,321 @@ +/** + **************************************************************************************** + * + * @file gattc_int.h + * + * @brief Header file - GATTC_INT. + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + +#ifndef GATTC_TASK_INT_H_ +#define GATTC_TASK_INT_H_ + +/** + **************************************************************************************** + * @addtogroup GATTC_INT Internals + * @ingroup GATTC + * @brief Internal features of the GATTC module + * + * @{ + **************************************************************************************** + */ +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_config.h" + +#if (BLE_GATTC) +#include "gattc.h" +#include "gattc_task.h" +#include "kernel_task.h" + +/* + * DEFINES + **************************************************************************************** + */ +/// retrieve on-going operation command +#define GATT_OPERATION_CMD(conidx, op_type, cmd) \ + ((struct cmd*) gattc_get_operation_ptr(conidx, op_type)) + +#define GATT_WRITE_ERROR_CODE (0xFFFF) + + +/// number of GATT Controller Process +#define GATTC_IDX_MAX BLE_CONNECTION_MAX + + + +/// states of GATT Controller task +enum gattc_state_id +{ + /// Connection ready state + GATTC_READY = 0, + #if (BLE_ATTC) + /// Client operation on-going + GATTC_CLIENT_BUSY = (1 << GATTC_OP_CLIENT), + /// Service Discovery Procedure operation on-going + GATTC_SDP_BUSY = (1 << GATTC_OP_SDP), + #endif // (BLE_ATTC) + #if (BLE_ATTS) + /// Server operation on-going + GATTC_SERVER_BUSY = (1 << GATTC_OP_SERVER), + #endif // (BLE_ATTS) + /// Connection started but ATTS not ready + GATTC_CONNECTED = (1 << (GATTC_OP_MAX + 1)), + + /// Free state + GATTC_FREE = (1 << (GATTC_OP_MAX + 2)), + /// Number of defined states. + GATTC_STATE_MAX +}; + +/// GATT Client information +enum gattc_cli_info +{ + /// Service changed indication enabled by client + GATTC_CLI_SVC_CHANGED_IND_EN_BIT = (1 << 0), + GATTC_CLI_SVC_CHANGED_IND_EN_POS = 0, + /// Robust Cache feature enabled + GATTC_CLI_ROBUST_CACHE_EN_BIT = (1 << 1), + GATTC_CLI_ROBUST_CACHE_EN_POS = 1, + /// Client is change aware (or not, used if robust cache enabled) + GATTC_CLI_CHG_AWARE_BIT = (1 << 2), + GATTC_CLI_CHG_AWARE_POS = 2, + /// If database has changed and peer supports robust cache, first ATT request must trigger a + /// Database out of sync error + GATTC_CLI_ATT_REQ_ALLOWED_BIT = (1 << 3), + GATTC_CLI_ATT_REQ_ALLOWED_POS = 3, +}; + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + + + +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ +extern struct gattc_env_tag* gattc_env[GATTC_IDX_MAX]; + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + + +/** + **************************************************************************************** + * @brief Initialization of the GATT controller module. + * This function performs all the initialization steps of the GATT module. + * + * @param[in] init_type Type of initialization (@see enum rwip_init_type) + * + **************************************************************************************** + */ +void gattc_init(uint8_t init_type); + + +/** + **************************************************************************************** + * @brief Initialize GATT controller for connection. + * + * @param[in] conidx connection record index + * @param[in] role device role after connection establishment + * + **************************************************************************************** + */ +void gattc_create(uint8_t conidx); + + + +/** + **************************************************************************************** + * @brief Cleanup GATT controller resources for connection + * + * @param[in] conidx connection record index + * @param[in] disconnect True if disconnection occurs else request due to init or reset + * + **************************************************************************************** + */ +void gattc_cleanup(uint8_t conidx, bool disconnect); + +/** + * @brief Send a complete event of ongoing executed operation to requester. + * It also clean-up variable used for ongoing operation. + * + * @param[in] conidx Connection index + * @param[in] op_type Operation type. + * @param[in] status Status of completed operation + */ +void gattc_send_complete_evt(uint8_t conidx, uint8_t op_type, uint8_t status); + +/** + **************************************************************************************** + * @brief Send operation completed message with status error code not related to a + * running operation. + * + * @param[in] conidx Connection index + * @param[in] operation Operation code + * @param[in] seq_num Operation sequence number + * @param[in] requester requester of operation + * @param[in] status Error status code + **************************************************************************************** + */ +void gattc_send_error_evt(uint8_t conidx, uint8_t operation, uint16_t seq_num, const kernel_task_id_t requester, uint8_t status); + +/** + **************************************************************************************** + * @brief Check if current operation can be processed or not. + * if it can be proceed, initialize an operation request. + * If a command complete event with error code can be triggered. + * + * Function returns how the message should be handled by message handler. + * + * @param[in] conidx Connection Index + * @param[in] op_type Operation type. + * @param[in] op_msg Requested operation message (note op_msg cannot be null) + * @param[in] supp_ops Supported operations array. + * Latest array value shall be GATTC_NO_OP. + * + * @return operation can be executed if message status equals KERNEL_MSG_NO_FREE, + * else nothing to do, just exit from the handler. + **************************************************************************************** + */ +int gattc_process_op(uint8_t conidx, uint8_t op_type, void* op_msg, enum gattc_operation* supp_ops); + +/** + **************************************************************************************** + * @brief Get operation on going + * + * @param[in] conidx Connection Index + * @param[in] op_type Operation type. + * + * @return operation code on going + **************************************************************************************** + */ +uint8_t gattc_get_operation(uint8_t conidx, uint8_t op_type); + +/** + **************************************************************************************** + * @brief Get operation pointer + * + * @param[in] conidx Connection Index + * @param[in] op_type Operation type. + * + * @return operation pointer on going + **************************************************************************************** + */ +void* gattc_get_operation_ptr(uint8_t conidx, uint8_t op_type); + + +/** + **************************************************************************************** + * @brief Set operation pointer + * + * @param[in] conidx Connection Index + * @param[in] op_type Operation type. + * @param[in] op Operation pointer. + * + **************************************************************************************** + */ +void gattc_set_operation_ptr(uint8_t conidx, uint8_t op_type, void* op); + +/** + **************************************************************************************** + * @brief Operation execution not finish, request kernel to reschedule it in order to + * continue its execution + * + * @param[in] conidx Connection Index + * @param[in] op_type Operation type. + * + * @return if operation has been rescheduled (not done if operation pointer is null) + **************************************************************************************** + */ +bool gattc_reschedule_operation(uint8_t conidx, uint8_t op_type); + +/** + **************************************************************************************** + * @brief Get requester of on going operation + * + * @param[in] conidx Connection Index + * @param[in] op_type Operation type. + * + * @return task that requests to execute the operation + **************************************************************************************** + */ +kernel_task_id_t gattc_get_requester(uint8_t conidx, uint8_t op_type); + + + +/** + **************************************************************************************** + * @brief Get Operation Sequence Number + * + * @param[in] conidx Connection Index + * @param[in] op_type Operation type. + * + * @return Sequence number provided for operation execution + **************************************************************************************** + */ +uint16_t gattc_get_op_seq_num(uint8_t conidx, uint8_t op_type); + + +/** + **************************************************************************************** + * @brief Update task state + * + * @param[in] conidx Connection index + * @param[in] state to update + * @param[in] set state to busy (true) or idle (false) + * + **************************************************************************************** + */ +void gattc_update_state(uint8_t conidx, kernel_state_t state, bool busy); + +#if (BLE_ATTS) +/** + **************************************************************************************** + * @brief Check if we have a database out of sync error + * + * @param[in] conidx Connection index + * @param[in] code Attribute request + * @param[in] handle Attribute handle requested + * + * @return true if we have a database out of sync error, else false + **************************************************************************************** + */ +bool gattc_is_db_out_of_sync(uint8_t conidx, uint8_t code, uint16_t handle); + +/** + **************************************************************************************** + * @brief Sends the service change indication to peer client device + * + * @param[in] conidx Connection index + * @param[in] start_handle Database Start handle + * @param[in] end_handle Database End handle + **************************************************************************************** + */ +void gattc_svc_chg_ind_send(uint8_t conidx, uint16_t start_handle, uint16_t end_handle); +#endif // (BLE_ATTS) + +/** + **************************************************************************************** + * @brief Send to application the connection information related to GATT + * + * @param[in] conidx Connection index + **************************************************************************************** + */ +void gattc_con_info_send(uint8_t conidx); + +#endif // (BLE_GATTC) + +/// @} GATTCTASK +#endif // GATTC_INT diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gatt/gattm/gattm_int.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gatt/gattm/gattm_int.h new file mode 100755 index 0000000..aa344eb --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/gatt/gattm/gattm_int.h @@ -0,0 +1,88 @@ +/** + **************************************************************************************** + * + * @file gattm_int.h + * + * @brief Internal Header file - GATTM. + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + +#ifndef GATTM_INT_H_ +#define GATTM_INT_H_ + +/** + **************************************************************************************** + * @addtogroup GATTM_INT Task + * @ingroup GATTM + * @brief Internal function required for GATTM usage + * @{ + **************************************************************************************** + */ +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "kernel_task.h" +#include "gattm_task.h" + +#include "../attm/attm_db.h" + +/* + * DEFINES + **************************************************************************************** + */ + +/// number of GATT Process +#define GATTM_IDX_MAX 0x01 + + +/// GATT database default features +#define GATT_DB_DEFAULT_FEAT 0x00FF + +/// states of GATT task +enum gattm_state_id +{ + /// idle state + GATTM_IDLE, + /// busy state + GATTM_BUSY, + /// Number of defined states. + GATTM_STATE_MAX +}; + +/// GATT General Information Manager +struct gattm_env_tag +{ + #if (BLE_ATTS) + /// Environment data needed by attribute database + struct attm_db db; + + /// GATT service start handle + uint16_t svc_start_hdl; + #endif // (BLE_ATTS) +}; + +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ +extern struct gattm_env_tag gattm_env; + +/* + * FUNCTIONS DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Informs that database has been updated + **************************************************************************************** + */ +void gattm_db_updated(void); + +/// @} GATTM_INT +#endif // GATTM_INT_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/l2c/l2cc/l2cc_int.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/l2c/l2cc/l2cc_int.h new file mode 100755 index 0000000..e4cd652 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/l2c/l2cc/l2cc_int.h @@ -0,0 +1,210 @@ +/** + **************************************************************************************** + * + * @file l2cc_int.h + * + * @brief Header file - L2CCTASK that contains internal API. + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + +#ifndef L2CC_INT_H_ +#define L2CC_INT_H_ + +/** + **************************************************************************************** + * @addtogroup L2CCINT Internals + * @ingroup L2CC + * @brief Internal API for L2CC module + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_config.h" +#if (BLE_L2CC) + +#include "l2cc_task.h" +#include "l2cc.h" + +/* + * MACRO DEFINITIONS + **************************************************************************************** + */ + + +/// Maximum number of instances of the L2CC task +#define L2CC_IDX_MAX (BLE_CONNECTION_MAX) + +/* + * STATES + **************************************************************************************** + */ + + + +/// states of L2CAP Controller task +enum l2cc_state_id +{ + /// Connection ready state + L2CC_READY, + /// LE signaling protocol busy + L2CC_SIG_BUSY = (1 << L2CC_OP_SIG), + /// Free state + L2CC_FREE = 0X3F, + + /// Number of defined states. + L2CC_STATE_MAX +}; + +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ + +/// L2CAP environment pool +extern struct l2cc_env_tag *l2cc_env[L2CC_IDX_MAX]; + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Create and Initialize the L2CAP controller task. + * + * @param[in] init_type Type of initialization (@see enum rwip_init_type) + * + **************************************************************************************** + */ +void l2cc_init(uint8_t init_type); + +/** +struct l2cc_pdu_recv_ind; + * + **************************************************************************************** + * @brief Initialize the link layer controller task. + * + * @param[in] conidx Connection index + * + **************************************************************************************** + */ +void l2cc_create(uint8_t conidx); + +/** + **************************************************************************************** + * @brief De-initialize the task. + * + * @param[in] conidx Connection index + * @param[in] reset true if it's requested by a reset; false if it's boot initialization + **************************************************************************************** + */ +void l2cc_cleanup(uint8_t conidx, bool reset); + +/** + **************************************************************************************** + * @brief Update task state + * + * @param[in] conidx Connection index + * @param[in] state to update + * @param[in] set state to busy (true) or idle (false) + * + **************************************************************************************** + */ +void l2cc_update_state(uint8_t conidx, kernel_state_t state, bool busy); + + +/** + * @brief Complete the operation by cleanning-up variable used and end a complete event to operation requester. + * + * @param[in] conidx Connection index + * @param[in] op_type Operation type. + * @param[in] status Status of completed operation + */ +void l2cc_op_complete(uint8_t conidx, uint8_t op_type, uint8_t status); + +/** + **************************************************************************************** + * @brief Send operation completed message with status error code not related to a + * running operation. + * + * @param[in] conidx Connection index + * @param[in] operation Operation code + * @param[in] requester requester of operation + * @param[in] status Error status code + * @param[in] cid Channel Identifier + * @param[in] credit number of used credit (0 on signaling channel) + **************************************************************************************** + */ +void l2cc_send_cmp_evt(uint8_t conidx, uint8_t operation, const kernel_task_id_t requester, uint8_t status, uint16_t cid, + uint16_t credit); + + +/** + **************************************************************************************** + * @brief Get operation on going + * + * @param[in] conidx Connection Index + * @param[in] op_type Operation type. + * + * @return operation code on going + **************************************************************************************** + */ +uint8_t l2cc_get_operation(uint8_t conidx, uint8_t op_type); + +/** + **************************************************************************************** + * @brief Get operation pointer + * + * @param[in] conidx Connection Index + * @param[in] op_type Operation type. + * + * @return operation pointer on going + **************************************************************************************** + */ +void* l2cc_get_operation_ptr(uint8_t conidx, uint8_t op_type); + + +/** + **************************************************************************************** + * @brief Set operation pointer + * + * @param[in] conidx Connection Index + * @param[in] op_type Operation type. + * @param[in] op Operation pointer. + * + **************************************************************************************** + */ +void l2cc_set_operation_ptr(uint8_t conidx, uint8_t op_type, void* op); + + + + +/** + **************************************************************************************** + * @brief Perform data packet TX over HCI (call of this function is handled by L2CM + * + * @param[in] conidx Connection Index + * @param[in] nb_buffer Number of available TX buffers + **************************************************************************************** + */ +void l2cc_data_send(uint8_t conidx, uint8_t nb_buffer); + + + + + + +#endif //(BLE_L2CC) + +/// @} L2CCINT + +#endif // L2CC_INT_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/l2c/l2cc/l2cc_lecb.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/l2c/l2cc/l2cc_lecb.h new file mode 100755 index 0000000..0360c12 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/l2c/l2cc/l2cc_lecb.h @@ -0,0 +1,262 @@ +/** + **************************************************************************************** + * + * @file l2cc_pdu.h + * + * @brief Header file - L2CAP LE Credit Based connection management + * + * Copyright (C) RivieraWaves 2009-2016 + * + **************************************************************************************** + */ + + +#ifndef _L2CC_LECB_H_ +#define _L2CC_LECB_H_ + +/** + **************************************************************************************** + * @addtogroup L2CC_LECB L2Cap Controller LE Credit Based connection management + * @ingroup L2CC + * @brief This module is in charge of LECB connection management + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" + +#if (BLE_LECB) + +/* + * DEFINES + **************************************************************************************** + */ +/// LE Credit Based fields. +enum l2cc_lecb_fields +{ + /// LE Protocol Service Multiplexer + L2CC_LECB_LEPSM, + /// Local channel ID + L2CC_LECB_LOCAL_CID, + /// Peer channel ID + L2CC_LECB_PEER_CID, +}; + + +/// Status of the LE Credit Based connection +/// +/// 7 6 5 4 3 2 1 0 +/// +----+----+----+----+----+----+----+----+ +/// | RFU |P_I |TX_W|CON | +/// +----+----+----+----+----+----+----+----+ +/// +/// bit [2] : Local(0)/Peer (1) initiated connection +/// bit [1] : TX in Wait state (segment transmission not finished) +/// bit [0] : LECB Connected +enum l2cc_lecb_state +{ + /// Peer initiated connection + L2CC_LECB_PEER_INIT_BIT = (1<<2), + L2CC_LECB_PEER_INIT_POS = (2), + + /// TX in Wait state (segment transmission not finished) + L2CC_LECB_TX_WAIT_BIT = (1<<1), + L2CC_LECB_TX_WAIT_POS = (1), + + /// Channel Connected + L2CC_LECB_CONNECTED_BIT = (1<<0), + L2CC_LECB_CONNECTED_POS = (0), +}; + + + + + +/* + * MACRO DEFINITIONS + **************************************************************************************** + */ + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + + + +/// LE credit based information for a link started or on-going. +struct l2cc_lecb_info +{ + /// Pointer to the following list + struct common_list_hdr hdr; + /// SDU waiting to be transfered (required for segmentation algorithm) + struct l2cc_lecb_sdu_send_cmd* tx_sdu; + /// SDU waiting to be received (required for reassembly algorithm) + struct l2cc_lecb_sdu_recv_ind* rx_sdu; + + /// LE Protocol/Service Multiplexer + uint16_t le_psm; + + /// Local channel ID + uint16_t local_cid; + /// Local Maximum Transmission Unit + uint16_t local_mtu; + /// Local Maximum Packet Size + uint16_t local_mps; + /// Local credit + uint16_t local_credit; + + /// Peer channel ID + uint16_t peer_cid; + /// Peer Maximum Transmission Unit + uint16_t peer_mtu; + /// Peer Maximum Packet Size + uint16_t peer_mps; + /// Peer credit + uint16_t peer_credit; + + /// Task id requested connection + kernel_task_id_t task_id; + + /// Status of the LE Credit Based connection (@see enum l2cc_lecb_state) + uint8_t state; + + /// disconnection reason + uint8_t disc_reason; + + /// Packet identifier - used for LECB negotiation + uint8_t pkt_id; +}; + + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Search LE Credit Based channel depending on the parameter + * + * @param[in] conidx Connection Index + * @param[in] field Search field (@see enum l2cc_lecb_fields) + * @param[in] value Field value to search + * + * @return Returns NULL or pointer to the LE Credit Based channel info + **************************************************************************************** + */ +struct l2cc_lecb_info* l2cc_lecb_find(uint8_t conidx, uint8_t field, uint16_t value); + +/** + **************************************************************************************** + * @brief End of LECB Connection, free information, and send disconnect indication + * + * @param[in] conidx Connection Index + * @param[in] lecb LE Credit Based Connection information + * @param[in] disconnect_ind True, sends disconnect indication + **************************************************************************************** + */ +void l2cc_lecb_free(uint8_t conidx, struct l2cc_lecb_info* lecb, bool disconnect_ind); + + +/** + **************************************************************************************** + * @brief Sends LE credit based connection request + * + * @param[in] conidx connection index + * @param[in] pkt_id Packet identifier + * @param[in] scid Source channel ID + * @param[in] credits Credits + * @param[in] mps Maximum Packet Size + * @param[in] mtu Maximum Transfer Unit + **************************************************************************************** + */ +void l2cc_lecb_send_con_req(uint8_t conidx, uint8_t pkt_id, uint16_t le_psm, uint16_t scid, uint16_t credits, + uint16_t mps, uint16_t mtu); + +/** + **************************************************************************************** + * @brief Sends LE credit based connection response + * + * @param[in] conidx connection index + * @param[in] status status of the connection + * @param[in] pkt_id Packet identifier + * @param[in] dcid Destination channel ID + * @param[in] credits Credits + * @param[in] mps Maximum Packet Size + * @param[in] mtu Maximum Transfer Unit + **************************************************************************************** + */ +void l2cc_lecb_send_con_rsp(uint8_t conidx, uint16_t status, uint8_t pkt_id, + uint16_t dcid, uint16_t credits, uint16_t mps, uint16_t mtu); + +/** + **************************************************************************************** + * @brief Sends LE credit based disconnection request + * + * @param[in] conidx connection index + * @param[in] pkt_id Packet identifier + * @param[in] dcid Destination channel ID + * @param[in] scid Source channel ID + **************************************************************************************** + */ +void l2cc_lecb_send_disc_req(uint8_t conidx, uint8_t pkt_id, uint16_t scid, uint16_t dcid); + +/** + **************************************************************************************** + * @brief Sends LE credit based disconnection response + * + * @param[in] conidx connection index + * @param[in] pkt_id Packet identifier + * @param[in] dcid Destination channel ID + * @param[in] scid Source channel ID + **************************************************************************************** + */ +void l2cc_lecb_send_disc_rsp(uint8_t conidx, uint8_t pkt_id, uint16_t dcid, uint16_t scid); +/** + **************************************************************************************** + * @brief Sends LE credit based Flow Control credit add message + * + * @param[in] conidx connection index + * @param[in] pkt_id Packet identifier + * @param[in] cid Source Channel ID + * @param[in] credits Credits + **************************************************************************************** + */ +void l2cc_lecb_send_credit_add(uint8_t conidx, uint8_t pkt_id, uint16_t cid, uint16_t credits); + + +/** + **************************************************************************************** + * @brief Due to an error on LECB link, initiate a disconnection of the channel + * + * @param[in] conidx connection index + * @param[in] lecb Information of the channel + * @param[in] disc_reason Disconnection reason + * + **************************************************************************************** + */ +void l2cc_lecb_init_disconnect(uint8_t conidx, struct l2cc_lecb_info* lecb, uint8_t disc_reason); + +/** + **************************************************************************************** + * @brief Retrieve LECB error Code from Host error code + * + * @param[in] h_err Host Error code + * + * @return LECB Error code + **************************************************************************************** + */ +uint16_t l2cc_lecb_h2l_err(uint8_t h_err); + +#endif //(BLE_LECB) + +/// @} L2CC_LECB + +#endif /* _L2CC_LECB_H_ */ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/l2c/l2cc/l2cc_pdu_int.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/l2c/l2cc/l2cc_pdu_int.h new file mode 100755 index 0000000..d509ef2 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/l2c/l2cc/l2cc_pdu_int.h @@ -0,0 +1,193 @@ +/** + **************************************************************************************** + * + * @file l2cc_pdu_int.h + * + * @brief Header file - L2CAP Controller PDU packer / unpacker (internal) + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + + +#ifndef _L2CC_PDU_INT_H_ +#define _L2CC_PDU_INT_H_ + +/** + **************************************************************************************** + * @addtogroup L2CC_PDU_INT L2Cap Controller (internal) + * @ingroup L2CC + * @brief This module is in charge to pack or unpack L2CAP packets + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" + +#if (BLE_L2CC) + +#include "l2cc_pdu.h" + +/* + * MACROS + **************************************************************************************** + */ + + +/* + * DEFINES + **************************************************************************************** + */ + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * Pack PDU from firmware readable data to a L2CAP packet using generic method. + * (no segmentation) + * + * @param[in] p_pdu Pointer to the unpacked PDU structure + * @param[in|out] p_offset Pointer to address where the next part of PDU will be read + * @param[in|out] p_length Pointer to the length of payload that has been packed + * @param[in|out] p_buffer Pointer to address where the next part of PDU will be written + * @param[in|out] pb_flag Packet Boundary flags + * + * @return GAP_ERR_NO_ERROR if packing succeed, else another error code. + **************************************************************************************** + */ +uint8_t l2cc_pdu_pack(struct l2cc_pdu *p_pdu, uint16_t *p_offset, uint16_t *p_length, uint8_t *p_buffer, uint8_t *pb_flag); + +/** + **************************************************************************************** + * Unpack L2Cap PDU in a generic format that can be used by firmware using generic method. + * (no reassembly) + * + * @param[in] conidx Connection Index + * @param[in] p_pdu Pointer to the unpacked PDU structure + * @param[in|out] p_offset Pointer to address where the next part of PDU will be written + * @param[in|out] p_rem_len Pointer to the remaining length value of PDU to receive + * @param[in|out] p_buffer Pointer to address where the next part of PDU will be read + * @param[in] pkt_length Length of the received packet + * @param[in] pb_flag Packet Boundary flags + * + * @return GAP_ERR_NO_ERROR if packing succeed, else another error code. + **************************************************************************************** + */ +uint8_t l2cc_pdu_unpack(uint8_t conidx, struct l2cc_pdu *p_pdu, uint16_t *p_offset, uint16_t *p_rem_len, + const uint8_t *p_buffer, uint16_t pkt_length, uint8_t pb_flag); + +#if (RW_DEBUG) +/** + **************************************************************************************** + * Pack DBG PDU (any kind of PDU generated by Host) from firmware readable data to a L2CAP + * packet (no segmentation) + * + * @param[in] conidx Connection Index + * @param[in] pdu Pointer to the Debug PDU to send + * @param[in|out] p_length Pointer to the length of payload that has been packed + * @param[in|out] buffer Pointer to address where the next part of PDU will be written + * @param[in|out] offset Pointer to address where the next part of PDU will be read + * @param[in|out] pb_flag Packet Boundary flags + * + * @return GAP_ERR_NO_ERROR if packing succeed, else another error code. + **************************************************************************************** + */ +uint8_t l2cc_dbg_pdu_pack(struct l2cc_dbg_pdu *pdu, uint16_t *length, uint8_t *buffer, uint16_t* offset,uint8_t *pb_flag); + + +/** + **************************************************************************************** + * Unpack L2Cap PDU in a generic format that can be used by firmware for debugging + * (no reassembly) + * + * @param[in|out] sdu Pointer to the unpacked SDU structure + * @param[in] buffer Pointer to address where the next part of PDU will be read + * @param[in] length Length of the received packet + * @param[in|out] offset Pointer to address where the next part of PDU will be written + * @param[in] pb_flag Packet Boundary flags + * + * @return GAP_ERR_NO_ERROR if packing succeed, else another error code. + **************************************************************************************** + */ +uint8_t l2cc_dbg_pdu_unpack(struct l2cc_dbg_pdu *pdu, uint8_t *buffer, uint16_t length, uint16_t* offset, uint8_t pb_flag); +#endif // (RW_DEBUG) + +#if (BLE_LECB) +/** + **************************************************************************************** + * Pack LE Credit Based channel PDU from firmware readable data to a L2CAP packet + * + * @param[in] conidx Connection Index + * @param[in] pdu Pointer to the SDU to send + * @param[out] length Pointer to the length of payload that has been packed + * @param[in|out] buffer Pointer to address where the next part of PDU will be written + * @param[in|out] offset Pointer to address where the next part of PDU will be read + * @param[in|out] pdu_len PDU length to transmitt + * @param[in] pb_flag Packet Boundary flags + * + * @return GAP_ERR_NO_ERROR if packing succeed, else another error code. + **************************************************************************************** + */ +uint8_t l2cc_lecb_pdu_pack(uint8_t conidx, struct l2cc_sdu *sdu, uint16_t *length, uint8_t *buffer, uint16_t* offset, + uint16_t pdu_len, uint8_t pb_flag); + + +/** + **************************************************************************************** + * Unpack L2Cap LECB SDU in a generic format that can be used by firmware + * + * @param[in|out] sdu Pointer to the unpacked SDU structure + * @param[in] buffer Pointer to address where the next part of PDU will be read + * @param[in] length Length of the received packet + * @param[in|out] offset Pointer to address where the next part of PDU will be written + * @param[in|out] pdu_remain_len Pointer to the data length still expected on segment + * @param[in] pb_flag Packet Boundary flags + * + * @return GAP_ERR_NO_ERROR if packing succeed, else another error code. + **************************************************************************************** + */ +uint8_t l2cc_lecb_pdu_unpack(uint8_t conidx, struct l2cc_sdu *sdu, uint8_t *buffer, uint16_t length, uint16_t* offset, + uint16_t* pdu_remain_len, uint8_t pb_flag); + +#endif //(BLE_LECB) + +/** + **************************************************************************************** + * @brief New message received, initialize reception of the buffer + * - if a PDU not fully received, drop it. + * + * @param[in] conidx Connection Index + **************************************************************************************** + */ +void l2cc_pdu_rx_init(uint8_t conidx); + +/** + **************************************************************************************** + * @brief Check the PDU packet header channel ID, Length, in order to: + * - verify if no error detected + * - allocate or retrieve the RX message for expected destination task + * + * @param[in] conidx Connection Index + * @param[in|out] pp_buffer Buffer received, pointer updated according to header length + * @param[in|out] p_rx_length Received length, updated according to extracted header length + **************************************************************************************** + */ +void l2cc_pdu_header_check(uint8_t conidx, uint8_t** pp_buffer, uint16_t* p_rx_length); + + +/// @} L2CC_PDU_INT + +#endif //(BLE_L2CC) + +#endif /* _L2CC_PDU_INT_H_ */ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/l2c/l2cc/l2cc_sig.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/l2c/l2cc/l2cc_sig.h new file mode 100755 index 0000000..e16bfeb --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/l2c/l2cc/l2cc_sig.h @@ -0,0 +1,96 @@ +/** + **************************************************************************************** + * + * @file l2cc_sig.h + * + * @brief L2CAP Controller Controller Signaling PDU Handler. + * + * Copyright (C) RivieraWaves 2009-2016 + * + **************************************************************************************** + */ + +#ifndef _L2CC_SIG_H_ +#define _L2CC_SIG_H_ + + +/** + **************************************************************************************** + * @addtogroup L2CC_SIG L2CAP Controller Signaling PDU Handler. + * @ingroup L2CC + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_config.h" + +#if (BLE_L2CC) + +#include "l2cc.h" +#include "l2cc_task.h" + +/* + * DEFINES + **************************************************************************************** + */ + +/* + * MACRO DEFINITIONS + **************************************************************************************** + */ + + + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + + + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + + +/** + **************************************************************************************** + * @brief Send an L2Cap command rejected signaling packet with command not understood + * error code. + * + * @param[in] conidx Connection Index + * @param[in] pkt_id Packet identifier + * + * @param[in] reason The Reason field describes why the Request packet was rejected + * @param[in] opt1 Optional param 1 + * @param[in] opt2 Optional param 2 + **************************************************************************************** + */ +void l2cc_sig_send_cmd_reject(uint8_t conidx, uint8_t pkt_id, uint16_t reason, uint16_t opt1, uint16_t opt2); + + +/** + **************************************************************************************** + * @brief Handles reception of L2CAP signaling messages from peer device. + * + * @param[in] conidx Connection Index + * @param[in] pdu PDU Received + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +int l2cc_sig_pdu_recv_handler(uint8_t conidx, struct l2cc_pdu *pdu); + + + + +#endif // (BLE_L2CC) + +#endif // _L2CC_SIG_H_ + +/// @} L2CC_SIG diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/l2c/l2cm/l2cm_int.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/l2c/l2cm/l2cm_int.h new file mode 100755 index 0000000..dd38887 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/hl/src/l2c/l2cm/l2cm_int.h @@ -0,0 +1,128 @@ +/** + **************************************************************************************** + * + * @file l2cm_int.h + * + * @brief Header file - L2CM internal. + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + +#ifndef L2CM_INT_H_ +#define L2CM_INT_H_ + +/** + **************************************************************************************** + * @addtogroup L2C_INT Logical Link Control and Adaptation Protocol internals + * @ingroup HOST + * @brief Logical Link Control and Adaptation Protocol - Internal API. + * + * @{ + **************************************************************************************** + */ +#include "rwip_config.h" + +#if (BLE_L2CM) +#include +#include +#include "compiler.h" +#include "l2cm.h" + +/* + * INCLUDE FILES + **************************************************************************************** + */ + + +/* + * DEFINES + **************************************************************************************** + */ + +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ + +/// L2CAP Manager environment structure to be saved +struct l2cm_env_tag +{ + #if (BLE_L2CC) + /// bit field used to know per connection if TX activity is on-going + uint32_t con_tx_state; + #endif // (BLE_L2CC) + /// Lower Layer buffers length + uint16_t le_acl_data_pkt_len; + /// Total number of available Lower Layer buffers + uint16_t le_acl_total_nb_acl_pkt; + /// Number of available Lower Layer buffers + uint16_t nb_buffer_avail; + }; + +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ +extern struct l2cm_env_tag l2cm_env; +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Acquire low layer LE ACL packet + **************************************************************************************** + */ +__INLINE void l2cm_buffer_acquire(void) +{ + l2cm_env.nb_buffer_avail--; +} + +/** + **************************************************************************************** + * @brief Release low layer LE ACL packet + * + * @parm[in] nb Number of buffer to release. + **************************************************************************************** + */ +__INLINE void l2cm_buffer_release(uint16_t nb) +{ + l2cm_env.nb_buffer_avail += nb; +} + + +/** + **************************************************************************************** + * @brief Retrieve low layer LE ACL Buffers size + * + * @return size of LE ACL Buffers + **************************************************************************************** + */ + __INLINE uint16_t l2cm_get_buffer_size(void) + { + return l2cm_env.le_acl_data_pkt_len; + } + + +/** + **************************************************************************************** + * @brief Set if TX queue for specific connection is empty or not. + * + * If not empty, it will request L2CM to start transmission of buffers + * + * @param[in] conidx Connection index + * @param[in] busy False if TX buffer queue is empty, True else + * + **************************************************************************************** + */ +void l2cm_tx_status(uint8_t conidx, bool busy); + +/// @} L2CM_INT + +#endif //(BLE_L2CM) + +#endif // L2CM_INT_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/api/em_map_ble.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/api/em_map_ble.h new file mode 100755 index 0000000..6cde768 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/api/em_map_ble.h @@ -0,0 +1,390 @@ +/** + **************************************************************************************** + * + * @file em_map_ble.h + * + * @brief Mapping of BLE section in exchange memory + * + * Copyright (C) RivieraWaves 2009-2016 + * + **************************************************************************************** + */ + +#ifndef EM_MAP_BLE_H_ +#define EM_MAP_BLE_H_ + +/** + **************************************************************************************** + * @addtogroup EM Exchange Memory + * @ingroup CONTROLLER + * @brief Mapping of BLE section in exchange memory + * + * @{ + **************************************************************************************** + */ + + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" + +#include // integer +#include "common_llcp.h" +#include "common_math.h" // For use of COMMON_ALIGN4_HI +#include "_reg_em_ble_cs.h" // EM Control Structure +#include "_reg_em_ble_tx_desc.h" // BLE EM TX descriptors +#include "_reg_em_ble_rx_desc.h" // BLE EM RX descriptors +#include "_reg_em_ble_rx_cte_desc.h" // BLE EM RX CTE descriptors +#include "_reg_em_ble_wpal.h" // BLE EM White and periodic list +#include "_reg_em_ble_ral.h" // BLE EM resolving list + +#if (BLE_ISO_PRESENT) +#include "_reg_em_ble_tx_iso_desc.h" // BLE EM TX ISO descriptors +#include "_reg_em_ble_rx_iso_desc.h" // BLE EM RX ISO descriptors +#include "_reg_em_ble_tx_iso_buf.h" // BLE EM TX Buffer description +#include "_reg_em_ble_rx_iso_buf.h" // BLE EM RX Buffer description +#endif // (BLE_ISO_PRESENT) + +/* + * CONTROL STRUCTURES + **************************************************************************************** + */ + +/** + * Control Structures area definition + * + * - LINK (N) + * - SCAN/INIT + */ +#define EM_BLE_CS_OFFSET (EM_BLE_OFFSET) +#define EM_BLE_CS_NB (BLE_ACTIVITY_MAX + (BLE_OBSERVER*3) + BLE_CENTRAL) +#define EM_BLE_CS_END (EM_BLE_CS_OFFSET + EM_BLE_CS_NB * REG_EM_BLE_CS_SIZE) + + +#if ((REG_EM_BLE_CS_SIZE % 4) != 0) +#error "CS Pointers must be 32 bits aligned" +#endif // ((REG_EM_BLE_CS_SIZE % 4) != 0) + +/** + * Control Structures indexes definition + */ +#define EM_BLE_CS_ACT_ID_TO_INDEX(act_id) (act_id) +#define EM_BLE_CS_IDX_TO_ACT_ID(cs_idx) (cs_idx) + +#if (BLE_OBSERVER) +#define EM_BLE_CS_EXT_SCAN_IDX2 (EM_BLE_CS_NB - 1) +#define EM_BLE_CS_AUX_SCAN_IDX1 (EM_BLE_CS_NB - 2) +#define EM_BLE_CS_AUX_SCAN_IDX2 (EM_BLE_CS_NB - 3) +#endif // (BLE_OBSERVER) +#if (BLE_CENTRAL) +#define EM_BLE_CS_EXT_INIT_IDX2 (EM_BLE_CS_NB - 4) +#endif // (BLE_CENTRAL) + +#define EM_BLE_CS_INDEX_MAX (EM_BLE_CS_NB) + +/** + * Frame Format + * Bluetooth state and device activity used for frequency selection and TDD frame format. See section 3.5 for further details + * Note this field is automatically updated by the RW-BT Core when changing from Page to Master Page Response mode. + * + * - 0000x: Do not use + * - 00010: Master Connect + * - 00011: Slave Connect + * - 00100: Low Duty Cycle Advertiser + * - 00101: High Duty Cycle Advertiser + * - 00110: Extended Advertiser + * - 00111: Do not use + * - 01000: Passive Scanner + * - 01001: Active Scanner + * - 01010: Extended Passive Scanner + * - 01011: Extended Active Scanner + * - 0110x: Do not use + * - 01110: Initiator + * - 01111: Extended Initiator + * - 10xxx: Do not use + * - 110xx: Do not use + * - 11100: Tx Test Mode + * - 11101: Rx Test Mode + * - 11110: Tx / Rx Test Mode + * - 11111: Do not use + */ +enum em_ble_cd_fmt +{ + EM_BLE_CS_FMT_MST_CONNECT = (0x02), + EM_BLE_CS_FMT_SLV_CONNECT = (0x03), + EM_BLE_CS_FMT_LDC_ADV = (0x04), + EM_BLE_CS_FMT_HDC_ADV = (0x05), + EM_BLE_CS_FMT_EXT_ADV = (0x06), + EM_BLE_CS_FMT_PASSIVE_SCAN = (0x08), + EM_BLE_CS_FMT_ACTIVE_SCAN = (0x09), + EM_BLE_CS_FMT_EXT_PASSIVE_SCAN = (0x0A), + EM_BLE_CS_FMT_EXT_ACTIVE_SCAN = (0x0B), + EM_BLE_CS_FMT_CHAN_SCAN = (0x0C), + EM_BLE_CS_FMT_INITIATOR = (0x0E), + EM_BLE_CS_FMT_EXT_INITIATOR = (0x0F), + EM_BLE_CS_FMT_TX_TEST = (0x1C), + EM_BLE_CS_FMT_RX_TEST = (0x1D), + EM_BLE_CS_FMT_TXRX_TEXT = (0x1E), +}; + +/// Maximum value of RXWINSZ field (16383) +#define EM_BLE_CS_RXWINSZ_MAX ((1 << 14)-1) + +/// Maximum value of MAXFRMTIME field (65535) +#define EM_BLE_CS_MAXEVTIME_MAX ((1 << 16)-1) + + /// MIC Mode +enum ENC_MIC +{ + /// AES-CCM with MIC + ENC_MIC_PRESENT = 0, + /// AES-CCM MIC-less + ENC_MIC_LESS = 1, +}; + +/// Encryption Mode +enum ENC_MODE +{ + /// AES-CCM nonce use Packet/Payload counter + ENC_MODE_PKT_PLD_CNT = 0, + /// AES-CCM nonce use Event counter + ENC_MODE_EVT_CNT = 1, +}; + + +/* + * WHITE LIST + **************************************************************************************** + */ + +/// White list area definition +#define EM_BLE_WPAL_OFFSET COMMON_ALIGN4_HI(EM_BLE_CS_END) +#define EM_BLE_WPAL_SIZE (BLE_WHITELIST_MAX * REG_EM_BLE_WPAL_SIZE) +#define EM_BLE_WPAL_END (EM_BLE_WPAL_OFFSET + EM_BLE_WPAL_SIZE) + +#if ((REG_EM_BLE_WPAL_SIZE % 4) != 0) +#error "WPAL Pointers must be 32 bits aligned" +#endif // ((REG_EM_BLE_WPAL_SIZE % 4) != 0) +/* + * RESOLVING LIST + **************************************************************************************** + */ + +/// Resolving list area definition +#define EM_BLE_RAL_OFFSET COMMON_ALIGN4_HI(EM_BLE_WPAL_END) +#define EM_BLE_RAL_SIZE (BLE_RESOL_ADDR_LIST_MAX * REG_EM_BLE_RAL_SIZE) +#define EM_BLE_RAL_END (EM_BLE_RAL_OFFSET + EM_BLE_RAL_SIZE) + +#if ((REG_EM_BLE_RAL_SIZE % 4) != 0) +#error "RAL Pointers must be 32 bits aligned" +#endif // ((REG_EM_BLE_RAL_SIZE % 4) != 0) +/* + * RX DESCRIPTORS + **************************************************************************************** + */ + +/// RX Descriptors area definition +#define EM_BLE_RX_DESC_OFFSET COMMON_ALIGN4_HI(EM_BLE_RAL_END) +#define EM_BLE_RX_DESC_NB (BLE_RX_DESC_NB) +#define EM_BLE_RX_DESC_END (EM_BLE_RX_DESC_OFFSET + EM_BLE_RX_DESC_NB * REG_EM_BLE_RX_DESC_SIZE) + +#if ((REG_EM_BLE_RX_DESC_SIZE % 4) != 0) +#error "RX Descriptors must be 32 bits aligned" +#endif // ((REG_EM_BLE_TX_DESC_SIZE % 4) != 0) +/* + * TX DESCRIPTORS + **************************************************************************************** + */ + +/** + * TX Descriptors area definition + * + * - N per connection + * - 1 per advertising data buffer + */ +#define EM_BLE_TX_DESC_OFFSET COMMON_ALIGN4_HI(EM_BLE_RX_DESC_END) +#define EM_BLE_TX_DESC_NB (BLE_TX_DESC_NB) +#define EM_BLE_TX_DESC_END (EM_BLE_TX_DESC_OFFSET + EM_BLE_TX_DESC_NB * REG_EM_BLE_TX_DESC_SIZE) + +#define EM_BLE_TXDESC_INDEX(act_id, idx) (BLE_NB_TX_DESC_PER_ACT * act_id + idx) + +#if ((REG_EM_BLE_TX_DESC_SIZE % 4) != 0) +#error "TX Descriptors must be 32 bits aligned" +#endif // ((REG_EM_BLE_TX_DESC_SIZE % 4) != 0) +/* + * LLCP TX BUFFERS + **************************************************************************************** + */ + +/// LLCP TX buffers area definition +#define EM_BLE_LLCPTXBUF_OFFSET COMMON_ALIGN4_HI(EM_BLE_TX_DESC_END) +#define EM_BLE_LLCPTXBUF_NB (2*BLE_ACTIVITY_MAX) +#define EM_BLE_LLCPTXBUF_SIZE (LL_PDU_LENGTH_MAX) +#define EM_BLE_LLCPTXBUF_END (EM_BLE_LLCPTXBUF_OFFSET + EM_BLE_LLCPTXBUF_NB * EM_BLE_LLCPTXBUF_SIZE) + + +/* + * ADV EXTENDED HEADERS TX BUFFER + **************************************************************************************** + */ + +/// Advertising TX buffer area definition +#define EM_BLE_ADVEXTHDRTXBUF_OFFSET COMMON_ALIGN4_HI(EM_BLE_LLCPTXBUF_END) +#define EM_BLE_ADVEXTHDRTXBUF_NB (BLE_ACTIVITY_MAX) +#define EM_BLE_ADVEXTHDRTXBUF_SIZE (39 + 6*(BLE_ADV_FRAG_NB_TX - 1)) +#define EM_BLE_ADVEXTHDRTXBUF_END (EM_BLE_ADVEXTHDRTXBUF_OFFSET + EM_BLE_ADVEXTHDRTXBUF_NB * EM_BLE_ADVEXTHDRTXBUF_SIZE) + +#define EM_BLE_ADVEXTHDRTXBUF_OFF(act_id) (EM_BLE_ADVEXTHDRTXBUF_OFFSET + act_id * EM_BLE_ADVEXTHDRTXBUF_SIZE) + +/* + * ADVERTISING DATA TX BUFFERS + **************************************************************************************** + */ + + /// Advertising data TX buffers area definition + #define EM_BLE_ADVDATATXBUF_OFFSET COMMON_ALIGN4_HI(EM_BLE_ADVEXTHDRTXBUF_END) + #define EM_BLE_ADVDATATXBUF_NB (BLE_ADV_BUF_NB_TX) + #define EM_BLE_ADVDATATXBUF_SIZE (BLE_ADV_FRAG_NB_TX*BLE_ADV_FRAG_SIZE_TX) + #define EM_BLE_ADVDATATXBUF_END (EM_BLE_ADVDATATXBUF_OFFSET + EM_BLE_ADVDATATXBUF_NB * EM_BLE_ADVDATATXBUF_SIZE) + + +/* + * AUX_CONNECT_REQ TX BUFFER + **************************************************************************************** + */ + +/// Aux Connect Req TX buffer area definition +#define EM_BLE_AUXCONNECTREQTXBUF_OFFSET COMMON_ALIGN4_HI(EM_BLE_ADVDATATXBUF_END) +#define EM_BLE_AUXCONNECTREQTXBUF_NB (1) +#define EM_BLE_AUXCONNECTREQTXBUF_SIZE (0x66) // 3 * PDU_CON_REQ_LEN +#define EM_BLE_AUXCONNECTREQTXBUF_END (EM_BLE_AUXCONNECTREQTXBUF_OFFSET + EM_BLE_AUXCONNECTREQTXBUF_NB * EM_BLE_AUXCONNECTREQTXBUF_SIZE) + + +/* + * ACL RX BUFFERS + **************************************************************************************** + */ + +/// Data RX buffers area definition +#define EM_BLE_DATARXBUF_OFFSET COMMON_ALIGN4_HI(EM_BLE_AUXCONNECTREQTXBUF_END) +#define EM_BLE_DATARXBUF_NB (BLE_DATA_BUF_NB_RX) +#define EM_BLE_DATARXBUF_SIZE (256) +#define EM_BLE_DATARXBUF_END (EM_BLE_DATARXBUF_OFFSET + EM_BLE_DATARXBUF_NB * EM_BLE_DATARXBUF_SIZE) + +/* + * ACL TX BUFFERS + **************************************************************************************** + */ + +/// ACL TX buffers area definition +#define EM_BLE_ACLTXBUF_OFFSET COMMON_ALIGN4_HI(EM_BLE_DATARXBUF_END) +#define EM_BLE_ACLTXBUF_NB (BLE_ACL_BUF_NB_TX) +#define EM_BLE_ACLTXBUF_SIZE (256) +#define EM_BLE_ACLTXBUF_END (EM_BLE_ACLTXBUF_OFFSET + EM_BLE_ACLTXBUF_NB * EM_BLE_ACLTXBUF_SIZE) + + +#if (BLE_ISO_PRESENT) + +/* + * ISO TX/RX Descriptors + **************************************************************************************** + */ +/** + * ISO Descriptors area definition + * Pool to be used for TX and RX ISO descriptors. It is assumed that both kind of descriptors + * have exactly the same length. + * For each ICO channel or ISO Mode 0 connection, 2 RX ISO descriptors and 2 TX ISO descriptors will be taken from this pool + * For each ICL channel, either 4 RX ISO descriptors or 4 TX ISO descriptors will be taken from this pool. + */ +#define EM_BLE_ISO_DESC_OFFSET COMMON_ALIGN4_HI(EM_BLE_ACLTXBUF_END) +#define EM_BLE_ISO_DESC_NB (BLE_ISO_DESC_NB) +#define EM_BLE_ISO_DESC_SIZE (REG_EM_BLE_TX_ISO_DESC_SIZE) +#define EM_BLE_ISO_DESC_END (EM_BLE_ISO_DESC_OFFSET + EM_BLE_ISO_DESC_NB * EM_BLE_ISO_DESC_SIZE) + +/// !!!! REMINDER: TX and RX ISO descriptors have the same size !!!! Can use REG_EM_BLE_TX_ISO_DESC_SIZE and REG_EM_BLE_RX_ISO_DESC_SIZE +#define EM_BLE_TX_ISO_DESC_OFFSET (EM_BLE_ISO_DESC_OFFSET) +#define EM_BLE_RX_ISO_DESC_OFFSET (EM_BLE_ISO_DESC_OFFSET) +#if (REG_EM_BLE_TX_ISO_DESC_SIZE != REG_EM_BLE_RX_ISO_DESC_SIZE) +#error "TX and RX ISO descriptors shall have the same size" +#endif // (REG_EM_BLE_TX_ISO_DESC_SIZE != REG_EM_BLE_RX_ISO_DESC_SIZE) +#if ((REG_EM_BLE_TX_ISO_DESC_SIZE % 4) != 0) +#error "TX/RX ISO Descriptor must be 32 bits aligned" +#endif // ((REG_EM_BLE_TX_ISO_DESC_SIZE % 4) != 0) + +/* + * ISO TX/RX DATA BUFFERS + **************************************************************************************** + */ +/// RX/TX Isochronous buffer area definition +#define EM_BLE_ISO_BUF_OFFSET COMMON_ALIGN4_HI(EM_BLE_ISO_DESC_END) +#define EM_BLE_ISO_BUFFER_NB (BLE_ISO_BUF_NB) +#define EM_BLE_ISO_BUFFER_SIZE (REG_EM_BLE_TX_ISO_BUF_SIZE) +#define EM_BLE_ISO_BUFFER_END (EM_BLE_ISO_BUF_OFFSET + EM_BLE_ISO_BUFFER_NB * EM_BLE_ISO_BUFFER_SIZE) + +/// !!!! REMINDER: TX and RX ISO buffer have the same size !!!! Can use REG_EM_BLE_TX_ISO_BUF_SIZE and REG_EM_BLE_RX_ISO_BUF_SIZE +#define EM_BLE_TX_ISO_BUF_OFFSET (EM_BLE_ISO_BUF_OFFSET) +#define EM_BLE_RX_ISO_BUF_OFFSET (EM_BLE_ISO_BUF_OFFSET) +#if (REG_EM_BLE_TX_ISO_BUF_SIZE != REG_EM_BLE_RX_ISO_BUF_SIZE) +#error "TX and RX ISO buffer shall have the same size" +#endif // (REG_EM_BLE_TX_ISO_DESC_SIZE != REG_EM_BLE_RX_ISO_DESC_SIZE) +#if ((REG_EM_BLE_TX_ISO_BUF_SIZE % 4) != 0) +#error "TX/RX ISO Buffers must be 32 bits aligned" +#endif // ((REG_EM_BLE_TX_ISO_BUF_SIZE % 4) != 0) + +#else +#define EM_BLE_ISO_BUFFER_END (EM_BLE_ACLTXBUF_END) +#endif // (BLE_ISO_PRESENT) + +/* + * RX DESCRIPTORS FOR DIRECTION FINDING + **************************************************************************************** + */ +/// RX CTE Descriptors area definition +#define EM_BLE_RX_CTE_DESC_OFFSET COMMON_ALIGN4_HI(EM_BLE_ISO_BUFFER_END) +#if (BLE_CON_CTE_REQ | BLE_CONLESS_CTE_RX) +#define EM_BLE_RX_CTE_DESC_NB (BLE_RX_CTE_DESC_NB) +#define EM_BLE_RX_CTE_DESC_END (EM_BLE_RX_CTE_DESC_OFFSET + EM_BLE_RX_CTE_DESC_NB * REG_EM_BLE_RX_CTE_DESC_SIZE) +#else // (BLE_CON_CTE_REQ | BLE_CONLESS_CTE_RX) +#define EM_BLE_RX_CTE_DESC_END (EM_BLE_RX_CTE_DESC_OFFSET) +#endif // (BLE_CON_CTE_REQ | BLE_CONLESS_CTE_RX) + +/* + * ANTENNA IDs FOR DIRECTION FINDING + **************************************************************************************** + */ +/// Area definition for Tx antenna IDs +#define EM_BLE_TX_ANTENNA_ID_OFFSET COMMON_ALIGN4_HI(EM_BLE_RX_CTE_DESC_END) +#if (BLE_AOA | BLE_AOD) +#define EM_BLE_TX_ANTENNA_ID_NB (BLE_MAX_SW_PAT_LEN) +#define EM_BLE_TX_ANTENNA_ID_END (EM_BLE_TX_ANTENNA_ID_OFFSET + EM_BLE_TX_ANTENNA_ID_NB) +#else // (BLE_CON_CTE_REQ | BLE_CONLESS_CTE_RX) +#define EM_BLE_TX_ANTENNA_ID_END (EM_BLE_TX_ANTENNA_ID_OFFSET) +#endif // (BLE_CON_CTE_REQ | BLE_CONLESS_CTE_RX) + +/// Area definition for Rx antenna IDs +#define EM_BLE_RX_ANTENNA_ID_OFFSET COMMON_ALIGN4_HI(EM_BLE_TX_ANTENNA_ID_END) +#if (BLE_AOA | BLE_AOD) +#define EM_BLE_RX_ANTENNA_ID_NB (BLE_MAX_SW_PAT_LEN) +#define EM_BLE_RX_ANTENNA_ID_END (EM_BLE_RX_ANTENNA_ID_OFFSET + EM_BLE_RX_ANTENNA_ID_NB) +#else // (BLE_CON_CTE_REQ | BLE_CONLESS_CTE_RX) +#define EM_BLE_RX_ANTENNA_ID_END (EM_BLE_RX_ANTENNA_ID_OFFSET) +#endif // (BLE_CON_CTE_REQ | BLE_CONLESS_CTE_RX) + +/* + * END + **************************************************************************************** + */ +#define EM_BLE_END (EM_BLE_RX_ANTENNA_ID_END) +#define EM_SIZE 0x4000 +#if 0 +#if (EM_BLE_END > EM_SIZE)//20200729 check EM 16K bytes bondary + #error "BLE EM Out of 16K byte" +#endif //(EM_BLE_END > 0x4000)//20200729 check EM 16K bytes bondary +#endif + +/// @} EM + +#endif // EM_MAP_BLE_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/api/rwble.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/api/rwble.h new file mode 100755 index 0000000..79a85d0 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/api/rwble.h @@ -0,0 +1,79 @@ +/** + **************************************************************************************** + * + * @file rwble.h + * + * @brief Entry points of the BLE software + * + * Copyright (C) RivieraWaves 2009-2016 + * + **************************************************************************************** + */ + +#ifndef RWBLE_H_ +#define RWBLE_H_ + +/** + **************************************************************************************** + * @addtogroup ROOT + * @brief Entry points of the BLE stack + * + * This module contains the primitives that allow an application accessing and running the + * BLE protocol stack + * + * @{ + **************************************************************************************** + */ + + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include // standard integer definitions +#include // standard boolean definitions +#include "rwip_config.h" // stack configuration +#include "compiler.h" + +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Initialize the BLE stack. + * + * @param[in] init_type Type of initialization (@see enum rwip_init_type) + **************************************************************************************** + */ +void rwble_init(uint8_t init_type); + + +/** + **************************************************************************************** + * @brief Return true if no BLE activity on going + * + **************************************************************************************** + */ +bool rwble_activity_ongoing_check(void); + +/** + **************************************************************************************** + * @brief RWBLE interrupt service routine + * + * This function is the interrupt service handler of RWBLE. + * + **************************************************************************************** + */ +__BLEIRQ void rwble_isr(void); + +/// @} RWBLE + +#endif // RWBLE_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/api/rwble_config.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/api/rwble_config.h new file mode 100755 index 0000000..680fac7 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/api/rwble_config.h @@ -0,0 +1,461 @@ +/** + **************************************************************************************** + * + * @file rwble_config.h + * + * @brief Configuration of the BLE lower layer stack + * + * Copyright (C) RivieraWaves 2009-2016 + * + **************************************************************************************** + */ + +#ifndef RWBLE_CONFIG_H_ +#define RWBLE_CONFIG_H_ + +/** + **************************************************************************************** + * @addtogroup ROOT + * @{ + * @name BLE LL stack configuration + * @{ + **************************************************************************************** + */ +/******************************************************************************************/ +/* -------------------------- FEATURE SETUP --------------------------------------*/ +/******************************************************************************************/ + +/// Features byte 0 +#define BLE_FEATURES_BYTE0 ( (1 << BLE_FEAT_ENC ) \ + | (1 << BLE_FEAT_CON_PARAM_REQ_PROC ) \ + | (1 << BLE_FEAT_EXT_REJ_IND ) \ + | (1 << BLE_FEAT_SLAVE_INIT_FEAT_EXCHG ) \ + | (1 << BLE_FEAT_PING ) \ + | (1 << BLE_FEAT_DATA_PKT_LEN_EXT ) \ + | (1 << BLE_FEAT_LL_PRIVACY ) \ + | (1 << BLE_FEAT_EXT_SCAN_FILT_POLICY ) ) + +/// Features byte 1 +#define BLE_FEATURES_BYTE1 ( (BLE_PHY_2MBPS_SUPPORT << (BLE_FEAT_2M_PHY - 8) ) \ + | (BLE_STABLE_MOD_IDX_TX_SUPPORT << (BLE_FEAT_STABLE_MOD_IDX_TX - 8) ) \ + | (BLE_STABLE_MOD_IDX_RX_SUPPORT << (BLE_FEAT_STABLE_MOD_IDX_RX - 8) ) \ + | (BLE_PHY_CODED_SUPPORT << (BLE_FEAT_CODED_PHY - 8) ) \ + | (1 << (BLE_FEAT_EXT_ADV - 8) ) \ + | (1 << (BLE_FEAT_PER_ADV - 8) ) \ + | (1 << (BLE_FEAT_CHAN_SEL_ALGO_2 - 8) ) \ + | (1 << (BLE_FEAT_PWR_CLASS_1 - 8) ) ) + +/// Features byte 2 +#define BLE_FEATURES_BYTE2 ( (1 << (BLE_FEAT_MIN_NUM_USED_CHAN_PROC - 16) ) \ + | (BLE_CON_CTE_REQ << (BLE_FEAT_CON_CTE_REQ - 16) ) \ + | (BLE_CON_CTE_RSP << (BLE_FEAT_CON_CTE_RSP - 16) ) \ + | (BLE_CONLESS_CTE_TX << (BLE_FEAT_CONLESS_CTE_TX - 16) ) \ + | (BLE_CONLESS_CTE_RX << (BLE_FEAT_CONLESS_CTE_RX - 16) ) \ + | (BLE_AOD << (BLE_FEAT_AOD - 16) ) \ + | (BLE_AOA << (BLE_FEAT_AOA - 16) ) \ + | ((BLE_CON_CTE_REQ | BLE_CONLESS_CTE_RX) << (BLE_FEAT_CTE_RX - 16) ) ) + +/// Features byte 3 +#define BLE_FEATURES_BYTE3 ( (1 << (BLE_FEAT_PER_ADV_SYNC_TRANSF_TX - 24) ) \ + | (1 << (BLE_FEAT_PER_ADV_SYNC_TRANSF_RX - 24) ) \ + | (1 << (BLE_FEAT_SLEEP_CLK_ACC_UPD - 24) ) \ + | (1 << (BLE_FEAT_PUB_KEY_VALID - 24) ) ) + +/// Features byte 4 +#define BLE_FEATURES_BYTE4 (0) + +/// Features byte 5 +#define BLE_FEATURES_BYTE5 (0) + +/// Features byte 6 +#define BLE_FEATURES_BYTE6 (0) + +/// Features byte 7 +#define BLE_FEATURES_BYTE7 (0) + +/// States byte 0 +#define BLE_STATES_BYTE0 ( BLE_NON_CON_ADV_STATE | BLE_DISC_ADV_STATE\ + | BLE_CON_ADV_STATE | BLE_HDC_DIRECT_ADV_STATE\ + | BLE_PASS_SCAN_STATE | BLE_ACTIV_SCAN_STATE\ + | BLE_INIT_MASTER_STATE | BLE_CON_SLAVE_STATE) + +/// States byte 1 +#define BLE_STATES_BYTE1 ( BLE_NON_CON_ADV_PASS_SCAN_STATE | BLE_DISC_ADV_PASS_SCAN_STATE\ + | BLE_CON_ADV_PASS_SCAN_STATE | BLE_HDC_DIRECT_ADV_PASS_SCAN_STATE\ + | BLE_NON_CON_ADV_ACTIV_SCAN_STATE | BLE_DISC_ADV_ACTIV_SCAN_STATE\ + | BLE_CON_ADV_ACTIV_SCAN_STATE | BLE_HDC_DIRECT_ADV_ACTIV_SCAN_STATE) + +/// States byte 2 +#define BLE_STATES_BYTE2 ( BLE_NON_CON_ADV_INIT_STATE | BLE_DISC_ADV_INIT_STATE\ + | BLE_NON_CON_ADV_MASTER_STATE | BLE_DISC_ADV_MASTER_STATE\ + | BLE_NON_CON_ADV_SLAVE_STATE | BLE_DISC_ADV_SLAVE_STATE\ + | BLE_PASS_SCAN_INIT_STATE | BLE_ACTIV_SCAN_INIT_STATE) + +/// States byte 3 +#define BLE_STATES_BYTE3 ( BLE_PASS_SCAN_MASTER_STATE | BLE_ACTIV_SCAN_MASTER_STATE\ + | BLE_PASS_SCAN_SLAVE_STATE | BLE_ACTIV_SCAN_SLAVE_STATE\ + | BLE_INIT_MASTER_MASTER_STATE | BLE_LDC_DIRECT_ADV_STATE\ + | BLE_LDC_DIRECT_ADV_PASS_SCAN_STATE | BLE_LDC_DIRECT_ADV_ACTIV_SCAN_STATE) + +/// States byte 4 +#define BLE_STATES_BYTE4 ( BLE_CON_ADV_INIT_MASTER_SLAVE_STATE | BLE_HDC_DIRECT_ADV_INIT_MASTER_SLAVE_STATE\ + | BLE_LDC_DIRECT_ADV_INIT_MASTER_SLAVE_STATE | BLE_CON_ADV_MASTER_SLAVE_STATE\ + | BLE_HDC_DIRECT_ADV_MASTER_SLAVE_STATE | BLE_LDC_DIRECT_ADV_MASTER_SLAVE_STATE\ + | BLE_CON_ADV_SLAVE_SLAVE_STATE | BLE_HDC_DIRECT_ADV_SLAVE_SLAVE_STATE) + +/// States byte 5 +#define BLE_STATES_BYTE5 ( BLE_LDC_DIRECT_ADV_SLAVE_SLAVE_STATE | BLE_INIT_MASTER_SLAVE_STATE) + +/// States byte 6 +#define BLE_STATES_BYTE6 0x0 +/// States byte 7 +#define BLE_STATES_BYTE7 0x0 + + +/******************************************************************************************/ +/* -------------------------- GENERAL SETUP --------------------------------------*/ +/******************************************************************************************/ + +/************************************ + * KE message heap * + ************************************ + * + * LLD->LLC/LLM messages: + * - connection < 6 + * - advertising adv end 56 + * - scan max adv chain 1650 + * - initiating init end 56 + * - per adv tx 2 + * - per adv rx max adv chain 1650 + * - encryption 16 + * => 1650 + 16 + (N-1) x 56 + * + * HCI params stored by LLM: + * - advertising 26 + * - scan 16 + * - initiating 58 + * - per adv tx 8 + * - per adv rx 14 + * => 58 + (N-1) x 26 + * + * LLCP TX queue: + * - Max 3 LLCP in the queue per link + * - Average 10 bytes per PDU + * - N x 3 x (12 + 10) = N x 66 + * + * HCI commands reception: + * - N commands of max 255 bytes + * - N x 255 + * + * HCI events: + * - Max advertising reports in TX queue: N x 255 + * - + 1 100-bytes event per activity: N x 100 + * + * Kernel timers: + * - 1 timer per connection + * - N x 12 + * + * Due to high probability of fragmentation, and sizes of the Kernel message headers, the total of above additions is + * doubled. + */ + +#define BLE_HEAP_MSG_SIZE ( 1650*BLE_OBSERVER \ + + 2 * ( (16 + (BLE_ACTIVITY_MAX-1) * 56) \ + + (58 + (BLE_ACTIVITY_MAX-1) * 26) \ + + (BLE_ACTIVITY_MAX * 66) \ + + (HCI_NB_CMD_PKTS * 255) \ + + (BLE_OBSERVER * BLE_MAX_NB_ADV_REP_FRAG * 255 + BLE_ACTIVITY_MAX * 100) \ + + (BLE_ACTIVITY_MAX * 12) \ + ) ) + +/************************************ + * Environments heap * + ************************************ + * + * Max env usage per activity: + * - connection 84 (LLC) + 144 228 + * - advertising 140 140 + * - scan 32 + 2 x 108 + 16 264 + * - initiating 84 + 3 x 80 324 + * - per adv tx 80 80 + * - per adv rx 96 96 + * + * It is possible to have one initiating + 1 scan + (N-2) other activities. + * Add 2 activities to consider Heap fragmentation. + * + * Heap size = 330 + 270 + (N-2 x 230) + 2 x 230 = 600 + N x 230 + */ +#define BLE_HEAP_ENV_SIZE (330*BLE_CENTRAL + 270*BLE_OBSERVER + BLE_ACTIVITY_MAX * 230) + +/// Normal Rx window size (in us) +#define BLE_NORMAL_WIN_SIZE 14 +/// Normal Rx window size for coded phy (in us) +// In Long Range, the symbol for the Access Address is 8 times longer than the symbol for 1Mbps. +#define BLE_PHY_CODED_NORMAL_WIN_SIZE (BLE_NORMAL_WIN_SIZE * 8) + + +/// Number of devices in the white list +#define BLE_WHITELIST_MAX (BLE_ACTIVITY_MAX + 2) + +/// Number of devices in the Resolution Address List +/// This have to be tuned according to the core frequency. Worst case is having in scan mode +/// all IRK and valid in resolving list and device receive a Direct Adv Report that contains +/// RPAs for InitA and AdvA +#define BLE_RESOL_ADDR_LIST_MAX (BLE_RAL_MAX) + +/// Number of RX data buffers (common for all activities) +#define BLE_DATA_BUF_NB_RX (BLE_RX_DESC_NB + 3) +/// Guard space reserved for HCI ACL header in BLE RX buffers +#define BLE_ACL_RX_BUF_HEADER_SPACE (HCI_ACL_HDR_LEN + 1) + +/// Number of TX ACL data buffers +#define BLE_ACL_BUF_NB_TX (BLE_ACTIVITY_MAX + 6) + +/// Number of advertising data buffers +#define BLE_ADV_BUF_NB_TX (BLE_ACTIVITY_MAX * 2 + 1) +/// Number of advertising or scan response data fragments in extended advertising PDU chain +#define BLE_ADV_FRAG_NB_TX (5) +/// Size of advertising or scan response data fragments in extended advertising PDU chain +#define BLE_ADV_FRAG_SIZE_TX (254) +/// Maximum advertising data length +#define BLE_CFG_MAX_ADV_DATA_LEN (BLE_ADV_FRAG_NB_TX * BLE_ADV_FRAG_SIZE_TX) + +/// Maximum number of Rx Descriptors that can be used during the reception of Auxiliary chained +/// advertising packet on Secondary advertising channels (0: no limit) +#define BLE_ADV_FRAG_NB_RX_MAX (7) + +/// Define the AUX Frame Space duration +#if defined(CFG_AFS_EXT) +// Aux Frame Space extended for scanner Aux offload testing +#define BLE_AFS_DUR (3000) // 3.0ms +#else // !(CFG_DBG_AUX_OFFLOAD) +// Packed advertising - Minimum AUX Frame Space +#define BLE_AFS_DUR (BLE_MAFS_DUR) +#endif // (CFG_DBG_AUX_OFFLOAD) + +/// Data packet transmission size and duration +/// These values represent what the device supports +#define BLE_MIN_OCTETS (27) // number of octets +#define BLE_MIN_TIME (328) // in us +#define BLE_MAX_OCTETS (251) // number of octets +#define BLE_MAX_TIME (17040) // in us + +/// Number of devices capacity for the scan duplicate filtering +#if (BLE_OBSERVER) +#define BLE_DUPLICATE_FILTER_MAX (10) +#endif //(BLE_OBSERVER) + +/// Number of TX descriptors per BLE connection [2|3|4] +#define BLE_NB_TX_DESC_PER_CON 2 + +/// Number of TX descriptors per advertising set +#define BLE_NB_TX_DESC_PER_ADV (2+BLE_ADV_FRAG_NB_TX) + +/// Number of TX descriptors per BLE activity (maximum needed for connection or advertising) +#if (BLE_NB_TX_DESC_PER_CON > BLE_NB_TX_DESC_PER_ADV) +#define BLE_NB_TX_DESC_PER_ACT (BLE_NB_TX_DESC_PER_CON) +#else //(BLE_NB_TX_DESC_PER_CON > BLE_NB_TX_DESC_PER_ADV) +#define BLE_NB_TX_DESC_PER_ACT (BLE_NB_TX_DESC_PER_ADV) +#endif //(BLE_NB_TX_DESC_PER_CON > BLE_NB_TX_DESC_PER_ADV) + +/// Number of RX descriptors +#define BLE_RX_DESC_NB (6) +/// Number of TX descriptors +#define BLE_TX_DESC_NB (BLE_NB_TX_DESC_PER_ACT * BLE_ACTIVITY_MAX) + +/// Legacy advertising HCI interface +#define BLE_ADV_LEGACY_ITF 1 + +/// Low energy event mask (should be the standard value if device is in controller-only) +#if ((BLE_EMB_PRESENT) && (!BLE_HOST_PRESENT)) +#define BLE_EVT_MASK {0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} +#else // (!(BLE_EMB_PRESENT) || (BLE_HOST_PRESENT)) +/// Low energy event mask (should be the custom mask if device is in full-stack) +#define BLE_EVT_MASK {0xFF, 0xFF, 0xFF, 0x07, 0x00, 0x00, 0x00, 0x00} +#endif // ((BLE_EMB_PRESENT) && (!BLE_HOST_PRESENT)) + +/******************************************************************************************/ +/* -------------------------- DEBUG SETUP ----------------------------------------*/ +/******************************************************************************************/ + +#define BLE_TEST_MODE_SUPPORT (1) + +/******************************************************************************************/ +/* -------------------- CHANNEL ASSESSMENT SETUP --------------------------*/ +/******************************************************************************************/ + +/// RSSI threshold for interference detection (in dBm) +#define BLE_CH_ASSESS_RSSI_INTERF_THR (-70) + +/// Channel map update period (in sec) +#define BLE_CH_MAP_UPDATE_PERIOD 4 + +/// Maximum duration without receiving a packet before considering a channel quality unknown (in slots) (2 secs) +#define BLE_CH_ASSESS_VALID_TO 0x1900 + +/// Maximum duration without receiving a packet before reintroducing a channel to the map (in slots) (20 secs) +#define BLE_CH_REASSESS_TO 0x7D00 + +/// Maximum counter value for channel assessment +#define BLE_CH_ASSESS_COUNT_MAX 4 +/// Counter threshold to consider a channel good +#define BLE_CH_ASSESS_COUNT_THR_GOOD 2 +/// Counter threshold to consider a channel bad +#define BLE_CH_ASSESS_COUNT_THR_BAD -2 +/// Minimum counter value for channel assessment +#define BLE_CH_ASSESS_COUNT_MIN -4 + + +/******************************************************************************************/ +/* -------------------------- Direction finding (AoA/AoD) -------------------------*/ +/******************************************************************************************/ + +/// Number of antennae used for constant tone extension transmission or reception +#define BLE_ANTENNA_NB 4 + +/// Maximum length of switching pattern +#define BLE_MAX_SW_PAT_LEN 12 + +/// Number of RX descriptors used for constant tone extension reception +#define BLE_RX_CTE_DESC_NB BLE_RX_DESC_NB + + +/******************************************************************************************/ +/* ----------------------- SUPPORTED HCI COMMANDS --------------------------------*/ +/******************************************************************************************/ + +//byte0 +#define BLE_CMDS_BYTE0 BLE_DISC_CMD +//byte2 +#define BLE_CMDS_BYTE2 BLE_RD_REM_VERS_CMD +//byte5 +#define BLE_CMDS_BYTE5 (BLE_SET_EVT_MSK_CMD | BLE_RESET_CMD) +//byte10 +#define BLE_CMDS_BYTE10 (BLE_HL_NB_CMP_PKT_CMD | BLE_RD_TX_PWR_CMD\ + |BLE_HL_BUF_SIZE_CMD | BLE_SET_CTRL_TO_HL_FCTRL_CMD) +//byte14 +#define BLE_CMDS_BYTE14 (BLE_RD_LOC_VERS_CMD | BLE_RD_LOC_SUP_FEAT_CMD) +//byte15 +#define BLE_CMDS_BYTE15 (BLE_RD_BD_ADDR_CMD | BLE_RD_RSSI_CMD) +//byte22 +#define BLE_CMDS_BYTE22 (BLE_SET_EVT_MSK_PG2_CMD) +//byte25 +#define BLE_CMDS_BYTE25 (BLE_LE_SET_EVT_MSK_CMD | BLE_LE_RD_BUF_SIZE_CMD\ + |BLE_LE_RD_LOC_SUP_FEAT_CMD | BLE_LE_SET_RAND_ADDR_CMD\ + |BLE_LE_SET_ADV_PARAM_CMD | BLE_LE_RD_ADV_TX_PWR_CMD\ + |BLE_LE_SET_ADV_DATA_CMD) +//byte26 +#define BLE_CMDS_BYTE26 (BLE_LE_SET_SC_RSP_DATA_CMD | BLE_LE_SET_ADV_EN_CMD\ + |BLE_LE_SET_SC_PARAM_CMD | BLE_LE_SET_SC_EN_CMD\ + |BLE_LE_CREAT_CNX_CMD | BLE_LE_CREAT_CNX_CNL_CMD\ + |BLE_LE_RD_WL_SIZE_CMD | BLE_LE_CLEAR_WL_CMD) +//byte27 +#define BLE_CMDS_BYTE27 (BLE_LE_ADD_DEV_WL_CMD | BLE_LE_REM_DEV_WL_CMD\ + |BLE_LE_CNX_UPDATE_CMD | BLE_LE_SET_HL_CH_CLASS_CMD\ + |BLE_LE_RD_CH_MAP_CMD | BLE_LE_RD_REM_FEAT_CMD\ + |BLE_LE_ENCRYPT_CMD | BLE_LE_RAND_CMD) +//byte28 +#define BLE_CMDS_BYTE28 (BLE_LE_START_ENC_CMD | BLE_LE_LTK_REQ_RPLY_CMD\ + |BLE_LE_LTK_REQ_NEG_RPLY_CMD | BLE_LE_RD_SUPP_STATES_CMD\ + |BLE_LE_RX_TEST_V1_CMD | BLE_LE_TX_TEST_V1_CMD\ + |BLE_LE_STOP_TEST_CMD) +//byte32 +#define BLE_CMDS_BYTE32 (BLE_RD_AUTH_PAYL_TO_CMD | BLE_WR_AUTH_PAYL_TO_CMD) +//byte33 +#define BLE_CMDS_BYTE33 (BLE_LE_REM_CON_PARA_REQ_RPLY_CMD | BLE_LE_REM_CON_PARA_REQ_NEG_RPLY_CMD\ + | BLE_LE_SET_DATA_LEN_CMD | BLE_LE_RD_SUGGTED_DFT_DATA_LEN_CMD) +//byte34 +#define BLE_CMDS_BYTE34 ( BLE_LE_WR_SUGGTED_DFT_DATA_LEN_CMD \ + | BLE_LE_RD_LOC_P256_PUB_KEY_CMD \ + | BLE_LE_GEN_DHKEY_V1_CMD \ + | BLE_LE_ADD_DEV_TO_RESOLV_LIST_CMD \ + | BLE_LE_REM_DEV_FROM_RESOLV_LIST_CMD \ + | BLE_LE_CLEAR_RESOLV_LIST_CMD \ + | BLE_LE_RD_RESOLV_LIST_SIZE_CMD \ + | BLE_LE_RD_PEER_RESOLV_ADDR_CMD ) +//byte35 +#define BLE_CMDS_BYTE35 ( BLE_LE_RD_LOCAL_RESOLV_ADDR_CMD \ + | BLE_LE_SET_ADDR_RESOL_CMD \ + | BLE_LE_SET_RESOLV_PRIV_ADDR_TO_CMD \ + | BLE_LE_RD_MAX_DATA_LEN_CMD \ + | BLE_LE_RD_PHY_CMD \ + | BLE_LE_SET_DFT_PHY_CMD \ + | BLE_LE_SET_PHY_CMD \ + | BLE_LE_RX_TEST_V2_CMD ) +//byte36 +#define BLE_CMDS_BYTE36 ( BLE_LE_TX_TEST_V2_CMD \ + | BLE_LE_SET_ADV_SET_RAND_ADDR_CMD \ + | BLE_LE_SET_EXT_ADV_PARAM_CMD \ + | BLE_LE_SET_EXT_ADV_DATA_CMD \ + | BLE_LE_SET_EXT_SCAN_RSP_DATA_CMD \ + | BLE_LE_SET_EXT_ADV_EN_CMD \ + | BLE_LE_RD_MAX_ADV_DATA_LEN_CMD \ + | BLE_LE_RD_NB_SUPP_ADV_SETS_CMD ) +//byte37 +#define BLE_CMDS_BYTE37 ( BLE_LE_RMV_ADV_SET_CMD \ + | BLE_LE_CLEAR_ADV_SETS_CMD \ + | BLE_LE_SET_PER_ADV_PARAM_CMD \ + | BLE_LE_SET_PER_ADV_DATA_CMD \ + | BLE_LE_SET_PER_ADV_EN_CMD \ + | BLE_LE_SET_EXT_SCAN_PARAM_CMD \ + | BLE_LE_SET_EXT_SCAN_EN_CMD \ + | BLE_LE_EXT_CREATE_CON_CMD ) +//byte38 +#define BLE_CMDS_BYTE38 ( BLE_LE_PER_ADV_CREATE_SYNC_CMD \ + | BLE_LE_PER_ADV_CREATE_SYNC_CANCEL_CMD \ + | BLE_LE_PER_ADV_TERM_SYNC_CMD \ + | BLE_LE_ADD_DEV_TO_PER_ADV_LIST_CMD \ + | BLE_LE_RMV_DEV_FROM_PER_ADV_LIST_CMD \ + | BLE_LE_CLEAR_PER_ADV_LIST_CMD \ + | BLE_LE_RD_PER_ADV_LIST_SIZE_CMD \ + | BLE_LE_RD_TX_PWR_CMD ) +//byte39 +#define BLE_CMDS_BYTE39 ( BLE_LE_RD_RF_PATH_COMP_CMD \ + | BLE_LE_WR_RF_PATH_COMP_CMD \ + | BLE_LE_SET_PRIV_MODE_CMD \ + | BLE_LE_RX_TEST_V3_CMD \ + | BLE_LE_TX_TEST_V3_CMD \ + | BLE_LE_SET_CONLESS_CTE_TX_PARAM_CMD \ + | BLE_LE_SET_CONLESS_CTE_TX_EN_CMD \ + | BLE_LE_SET_CONLESS_IQ_SAMPL_EN_CMD ) +//byte40 +#define BLE_CMDS_BYTE40 ( BLE_LE_SET_CON_CTE_RX_PARAM_CMD \ + | BLE_LE_SET_CON_CTE_TX_PARAM_CMD \ + | BLE_LE_CON_CTE_REQ_EN_CMD \ + | BLE_LE_CON_CTE_RSP_EN_CMD \ + | BLE_LE_RD_ANTENNA_INF_CMD \ + | BLE_LE_SET_PER_ADV_RX_EN_CMD \ + | BLE_LE_PER_ADV_SYNC_TRANSF_CMD \ + | BLE_LE_PER_ADV_SET_INFO_TRANSF_CMD ) +//byte41 +#define BLE_CMDS_BYTE41 ( BLE_LE_SET_PER_ADV_SYNC_TRANSF_PARAM_CMD \ + | BLE_LE_SET_DFT_PER_ADV_SYNC_TRANSF_PARAM_CMD \ + | BLE_LE_GEN_DHKEY_V2_CMD \ + | BLE_LE_MOD_SLP_CLK_ACC_CMD ) + + +/******************************************************************************************/ +/* ------------------------ CONNECTION HANDLE ----------------------------------------*/ +/******************************************************************************************/ + +/// Bit set for BLE connection handles +#define BLE_CONHDL_MIN (0) +#define BLE_CONHDL_MAX (BLE_CONHDL_MIN + BLE_ACTIVITY_MAX - 1) +#define BLE_LINKID_TO_CONHDL(link_id) ((uint16_t) (BLE_CONHDL_MIN + (link_id))) +#define BLE_CONHDL_TO_LINKID(conhdl) ((uint8_t) ((conhdl) - BLE_CONHDL_MIN)) + +/// Bit set for BLE sync handles (used in periodic advertising receiver mode) +#define BLE_SYNCHDL_MIN (0) +#define BLE_SYNCHDL_MAX (BLE_SYNCHDL_MIN + BLE_ACTIVITY_MAX - 1) +#define BLE_ACTID_TO_SYNCHDL(act_id) ((uint16_t) (BLE_SYNCHDL_MIN + (act_id))) +#define BLE_SYNCHDL_TO_ACTID(synchdl) ((uint8_t) ((synchdl) - BLE_SYNCHDL_MIN)) + +/// AM0 Channel handle mapping +#define BLE_AM0HDL_MIN (0x300) +#define BLE_CHANHDL_TO_AM0HDL(chanhdl) ((uint16_t) (BLE_AM0HDL_MIN + (chanhdl))) +#define BLE_AM0HDL_TO_CHANHDL(am0) ((uint8_t) ((am0) - BLE_AM0HDL_MIN)) + +/// @} BLE stack configuration +/// @} ROOT + +#endif // RWBLE_CONFIG_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/RW-BLE-CORE-EM.xls b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/RW-BLE-CORE-EM.xls new file mode 100755 index 0000000..2331839 Binary files /dev/null and b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/RW-BLE-CORE-EM.xls differ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/RW-BLE-CORE-REG.xls b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/RW-BLE-CORE-REG.xls new file mode 100755 index 0000000..3b76f26 Binary files /dev/null and b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/RW-BLE-CORE-REG.xls differ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_blecore.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_blecore.h new file mode 100755 index 0000000..f146663 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_blecore.h @@ -0,0 +1,10 @@ +#ifndef __REG_BLECORE_H_ +#define __REG_BLECORE_H_ + +#define REG_BLECORE_SIZE 396 + +#define REG_BLECORE_BASE_ADDR 0x00900800 + + +#endif // __REG_BLECORE_H_ + diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_em_ble_cs.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_em_ble_cs.h new file mode 100755 index 0000000..5c69a2b --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_em_ble_cs.h @@ -0,0 +1,10 @@ +#ifndef __REG_EM_BLE_CS_H_ +#define __REG_EM_BLE_CS_H_ + +#define REG_EM_BLE_CS_SIZE 112 + +#define REG_EM_BLE_CS_BASE_ADDR 0x00910000 + + +#endif // __REG_EM_BLE_CS_H_ + diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_em_ble_et.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_em_ble_et.h new file mode 100755 index 0000000..6177540 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_em_ble_et.h @@ -0,0 +1,10 @@ +#ifndef __REG_EM_BLE_ET_H_ +#define __REG_EM_BLE_ET_H_ + +#define REG_EM_BLE_ET_SIZE 16 + +#define REG_EM_BLE_ET_BASE_ADDR 0x00910000 + + +#endif // __REG_EM_BLE_ET_H_ + diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_em_ble_ft.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_em_ble_ft.h new file mode 100755 index 0000000..7584738 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_em_ble_ft.h @@ -0,0 +1,10 @@ +#ifndef __REG_EM_BLE_FT_H_ +#define __REG_EM_BLE_FT_H_ + +#define REG_EM_BLE_FT_SIZE 40 + +#define REG_EM_BLE_FT_BASE_ADDR 0x00910000 + + +#endif // __REG_EM_BLE_FT_H_ + diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_em_ble_ral.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_em_ble_ral.h new file mode 100755 index 0000000..038a5e7 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_em_ble_ral.h @@ -0,0 +1,10 @@ +#ifndef __REG_EM_BLE_RAL_H_ +#define __REG_EM_BLE_RAL_H_ + +#define REG_EM_BLE_RAL_SIZE 56 + +#define REG_EM_BLE_RAL_BASE_ADDR 0x00910000 + + +#endif // __REG_EM_BLE_RAL_H_ + diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_em_ble_rx_audio_buf.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_em_ble_rx_audio_buf.h new file mode 100755 index 0000000..179a6ff --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_em_ble_rx_audio_buf.h @@ -0,0 +1,10 @@ +#ifndef __REG_EM_BLE_RX_AUDIO_BUF_H_ +#define __REG_EM_BLE_RX_AUDIO_BUF_H_ + +#define REG_EM_BLE_RX_AUDIO_BUF_SIZE 64 + +#define REG_EM_BLE_RX_AUDIO_BUF_BASE_ADDR 0x00910000 + + +#endif // __REG_EM_BLE_RX_AUDIO_BUF_H_ + diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_em_ble_rx_buf.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_em_ble_rx_buf.h new file mode 100755 index 0000000..a535de3 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_em_ble_rx_buf.h @@ -0,0 +1,10 @@ +#ifndef __REG_EM_BLE_RX_BUF_H_ +#define __REG_EM_BLE_RX_BUF_H_ + +#define REG_EM_BLE_RX_BUF_SIZE 260 + +#define REG_EM_BLE_RX_BUF_BASE_ADDR 0x00910000 + + +#endif // __REG_EM_BLE_RX_BUF_H_ + diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_em_ble_rx_cte_desc.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_em_ble_rx_cte_desc.h new file mode 100755 index 0000000..364e303 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_em_ble_rx_cte_desc.h @@ -0,0 +1,10 @@ +#ifndef __REG_EM_BLE_RX_CTE_DESC_H_ +#define __REG_EM_BLE_RX_CTE_DESC_H_ + +#define REG_EM_BLE_RX_CTE_DESC_SIZE 168 + +#define REG_EM_BLE_RX_CTE_DESC_BASE_ADDR 0x00910000 + + +#endif // __REG_EM_BLE_RX_CTE_DESC_H_ + diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_em_ble_rx_desc.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_em_ble_rx_desc.h new file mode 100755 index 0000000..fd23f7f --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_em_ble_rx_desc.h @@ -0,0 +1,10 @@ +#ifndef __REG_EM_BLE_RX_DESC_H_ +#define __REG_EM_BLE_RX_DESC_H_ + +#define REG_EM_BLE_RX_DESC_SIZE 28 + +#define REG_EM_BLE_RX_DESC_BASE_ADDR 0x00910000 + + +#endif // __REG_EM_BLE_RX_DESC_H_ + diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_em_ble_rx_iso_buf.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_em_ble_rx_iso_buf.h new file mode 100755 index 0000000..2995c5f --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_em_ble_rx_iso_buf.h @@ -0,0 +1,10 @@ +#ifndef __REG_EM_BLE_RX_ISO_BUF_H_ +#define __REG_EM_BLE_RX_ISO_BUF_H_ + +#define REG_EM_BLE_RX_ISO_BUF_SIZE 68 + +#define REG_EM_BLE_RX_ISO_BUF_BASE_ADDR 0x00910000 + + +#endif // __REG_EM_BLE_RX_ISO_BUF_H_ + diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_em_ble_rx_iso_desc.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_em_ble_rx_iso_desc.h new file mode 100755 index 0000000..20ccb1f --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_em_ble_rx_iso_desc.h @@ -0,0 +1,10 @@ +#ifndef __REG_EM_BLE_RX_ISO_DESC_H_ +#define __REG_EM_BLE_RX_ISO_DESC_H_ + +#define REG_EM_BLE_RX_ISO_DESC_SIZE 12 + +#define REG_EM_BLE_RX_ISO_DESC_BASE_ADDR 0x00910000 + + +#endif // __REG_EM_BLE_RX_ISO_DESC_H_ + diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_em_ble_tx_audio_buf.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_em_ble_tx_audio_buf.h new file mode 100755 index 0000000..1e5da68 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_em_ble_tx_audio_buf.h @@ -0,0 +1,10 @@ +#ifndef __REG_EM_BLE_TX_AUDIO_BUF_H_ +#define __REG_EM_BLE_TX_AUDIO_BUF_H_ + +#define REG_EM_BLE_TX_AUDIO_BUF_SIZE 64 + +#define REG_EM_BLE_TX_AUDIO_BUF_BASE_ADDR 0x00910000 + + +#endif // __REG_EM_BLE_TX_AUDIO_BUF_H_ + diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_em_ble_tx_buf.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_em_ble_tx_buf.h new file mode 100755 index 0000000..99c0ed3 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_em_ble_tx_buf.h @@ -0,0 +1,10 @@ +#ifndef __REG_EM_BLE_TX_BUF_H_ +#define __REG_EM_BLE_TX_BUF_H_ + +#define REG_EM_BLE_TX_BUF_SIZE 38 + +#define REG_EM_BLE_TX_BUF_BASE_ADDR 0x00910000 + + +#endif // __REG_EM_BLE_TX_BUF_H_ + diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_em_ble_tx_buf_cntl.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_em_ble_tx_buf_cntl.h new file mode 100755 index 0000000..e4cdb85 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_em_ble_tx_buf_cntl.h @@ -0,0 +1,10 @@ +#ifndef __REG_EM_BLE_TX_BUF_CNTL_H_ +#define __REG_EM_BLE_TX_BUF_CNTL_H_ + +#define REG_EM_BLE_TX_BUF_CNTL_SIZE 38 + +#define REG_EM_BLE_TX_BUF_CNTL_BASE_ADDR 0x00910000 + + +#endif // __REG_EM_BLE_TX_BUF_CNTL_H_ + diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_em_ble_tx_desc.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_em_ble_tx_desc.h new file mode 100755 index 0000000..e45f1e6 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_em_ble_tx_desc.h @@ -0,0 +1,10 @@ +#ifndef __REG_EM_BLE_TX_DESC_H_ +#define __REG_EM_BLE_TX_DESC_H_ + +#define REG_EM_BLE_TX_DESC_SIZE 16 + +#define REG_EM_BLE_TX_DESC_BASE_ADDR 0x00910000 + + +#endif // __REG_EM_BLE_TX_DESC_H_ + diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_em_ble_tx_iso_buf.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_em_ble_tx_iso_buf.h new file mode 100755 index 0000000..7a75a3e --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_em_ble_tx_iso_buf.h @@ -0,0 +1,10 @@ +#ifndef __REG_EM_BLE_TX_ISO_BUF_H_ +#define __REG_EM_BLE_TX_ISO_BUF_H_ + +#define REG_EM_BLE_TX_ISO_BUF_SIZE 68 + +#define REG_EM_BLE_TX_ISO_BUF_BASE_ADDR 0x00910000 + + +#endif // __REG_EM_BLE_TX_ISO_BUF_H_ + diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_em_ble_tx_iso_desc.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_em_ble_tx_iso_desc.h new file mode 100755 index 0000000..e888145 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_em_ble_tx_iso_desc.h @@ -0,0 +1,10 @@ +#ifndef __REG_EM_BLE_TX_ISO_DESC_H_ +#define __REG_EM_BLE_TX_ISO_DESC_H_ + +#define REG_EM_BLE_TX_ISO_DESC_SIZE 12 + +#define REG_EM_BLE_TX_ISO_DESC_BASE_ADDR 0x00910000 + + +#endif // __REG_EM_BLE_TX_ISO_DESC_H_ + diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_em_ble_wpal.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_em_ble_wpal.h new file mode 100755 index 0000000..9b14877 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/_reg_em_ble_wpal.h @@ -0,0 +1,10 @@ +#ifndef __REG_EM_BLE_WPAL_H_ +#define __REG_EM_BLE_WPAL_H_ + +#define REG_EM_BLE_WPAL_SIZE 12 + +#define REG_EM_BLE_WPAL_BASE_ADDR 0x00910000 + + +#endif // __REG_EM_BLE_WPAL_H_ + diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_blecore.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_blecore.h new file mode 100755 index 0000000..e4a24e2 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_blecore.h @@ -0,0 +1,8806 @@ +#ifndef _REG_BLECORE_H_ +#define _REG_BLECORE_H_ + +#include +#include "_reg_blecore.h" +#include "compiler.h" +#include "architect.h" +#include "ble_reg_access.h" + +#define REG_BLECORE_COUNT 99 + +#define REG_BLECORE_DECODING_MASK 0x000001FF + +/** + * @brief RWBLECNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31      MASTER_SOFT_RST   0
+ *     30    MASTER_TGSOFT_RST   0
+ *     29         REG_SOFT_RST   0
+ *     28   RADIOCNTL_SOFT_RST   0
+ *     27            SWINT_REQ   0
+ *     26         RFTEST_ABORT   0
+ *     25         ADVERT_ABORT   0
+ *     24           SCAN_ABORT   0
+ *     20               MD_DSB   0
+ *     19               SN_DSB   0
+ *     18             NESN_DSB   0
+ *     17            CRYPT_DSB   0
+ *     16           LRPMAP_DSB   0
+ *     15            LRFEC_DSB   0
+ *     14             WHIT_DSB   0
+ *     13              CRC_DSB   0
+ *     12        HOP_REMAP_DSB   0
+ *     11     RXCTEERR_RETX_EN   0
+ *     10   ANONYMOUS_ADV_FILT_EN   0
+ *     09        ADVERTFILT_EN   0
+ *     08             RWBLE_EN   0
+ *  03:00           RXWINSZDEF   0x0
+ * 
+ */ +#define BLE_RWBLECNTL_ADDR 0x00900800 +#define BLE_RWBLECNTL_OFFSET 0x00000000 +#define BLE_RWBLECNTL_INDEX 0x00000000 +#define BLE_RWBLECNTL_RESET 0x00000000 + +__INLINE uint32_t ble_rwblecntl_get(void) +{ + return REG_BLE_RD(BLE_RWBLECNTL_ADDR); +} + +__INLINE void ble_rwblecntl_set(uint32_t value) +{ + REG_BLE_WR(BLE_RWBLECNTL_ADDR, value); +} + +// field definitions +#define BLE_MASTER_SOFT_RST_BIT ((uint32_t)0x80000000) +#define BLE_MASTER_SOFT_RST_POS 31 +#define BLE_MASTER_TGSOFT_RST_BIT ((uint32_t)0x40000000) +#define BLE_MASTER_TGSOFT_RST_POS 30 +#define BLE_REG_SOFT_RST_BIT ((uint32_t)0x20000000) +#define BLE_REG_SOFT_RST_POS 29 +#define BLE_RADIOCNTL_SOFT_RST_BIT ((uint32_t)0x10000000) +#define BLE_RADIOCNTL_SOFT_RST_POS 28 +#define BLE_SWINT_REQ_BIT ((uint32_t)0x08000000) +#define BLE_SWINT_REQ_POS 27 +#define BLE_RFTEST_ABORT_BIT ((uint32_t)0x04000000) +#define BLE_RFTEST_ABORT_POS 26 +#define BLE_ADVERT_ABORT_BIT ((uint32_t)0x02000000) +#define BLE_ADVERT_ABORT_POS 25 +#define BLE_SCAN_ABORT_BIT ((uint32_t)0x01000000) +#define BLE_SCAN_ABORT_POS 24 +#define BLE_MD_DSB_BIT ((uint32_t)0x00100000) +#define BLE_MD_DSB_POS 20 +#define BLE_SN_DSB_BIT ((uint32_t)0x00080000) +#define BLE_SN_DSB_POS 19 +#define BLE_NESN_DSB_BIT ((uint32_t)0x00040000) +#define BLE_NESN_DSB_POS 18 +#define BLE_CRYPT_DSB_BIT ((uint32_t)0x00020000) +#define BLE_CRYPT_DSB_POS 17 +#define BLE_LRPMAP_DSB_BIT ((uint32_t)0x00010000) +#define BLE_LRPMAP_DSB_POS 16 +#define BLE_LRFEC_DSB_BIT ((uint32_t)0x00008000) +#define BLE_LRFEC_DSB_POS 15 +#define BLE_WHIT_DSB_BIT ((uint32_t)0x00004000) +#define BLE_WHIT_DSB_POS 14 +#define BLE_CRC_DSB_BIT ((uint32_t)0x00002000) +#define BLE_CRC_DSB_POS 13 +#define BLE_HOP_REMAP_DSB_BIT ((uint32_t)0x00001000) +#define BLE_HOP_REMAP_DSB_POS 12 +#define BLE_RXCTEERR_RETX_EN_BIT ((uint32_t)0x00000800) +#define BLE_RXCTEERR_RETX_EN_POS 11 +#define BLE_ANONYMOUS_ADV_FILT_EN_BIT ((uint32_t)0x00000400) +#define BLE_ANONYMOUS_ADV_FILT_EN_POS 10 +#define BLE_ADVERTFILT_EN_BIT ((uint32_t)0x00000200) +#define BLE_ADVERTFILT_EN_POS 9 +#define BLE_RWBLE_EN_BIT ((uint32_t)0x00000100) +#define BLE_RWBLE_EN_POS 8 +#define BLE_RXWINSZDEF_MASK ((uint32_t)0x0000000F) +#define BLE_RXWINSZDEF_LSB 0 +#define BLE_RXWINSZDEF_WIDTH ((uint32_t)0x00000004) + +#define BLE_MASTER_SOFT_RST_RST 0x0 +#define BLE_MASTER_TGSOFT_RST_RST 0x0 +#define BLE_REG_SOFT_RST_RST 0x0 +#define BLE_RADIOCNTL_SOFT_RST_RST 0x0 +#define BLE_SWINT_REQ_RST 0x0 +#define BLE_RFTEST_ABORT_RST 0x0 +#define BLE_ADVERT_ABORT_RST 0x0 +#define BLE_SCAN_ABORT_RST 0x0 +#define BLE_MD_DSB_RST 0x0 +#define BLE_SN_DSB_RST 0x0 +#define BLE_NESN_DSB_RST 0x0 +#define BLE_CRYPT_DSB_RST 0x0 +#define BLE_LRPMAP_DSB_RST 0x0 +#define BLE_LRFEC_DSB_RST 0x0 +#define BLE_WHIT_DSB_RST 0x0 +#define BLE_CRC_DSB_RST 0x0 +#define BLE_HOP_REMAP_DSB_RST 0x0 +#define BLE_RXCTEERR_RETX_EN_RST 0x0 +#define BLE_ANONYMOUS_ADV_FILT_EN_RST 0x0 +#define BLE_ADVERTFILT_EN_RST 0x0 +#define BLE_RWBLE_EN_RST 0x0 +#define BLE_RXWINSZDEF_RST 0x0 + +__INLINE void ble_rwblecntl_pack(uint8_t mastersoftrst, uint8_t mastertgsoftrst, uint8_t regsoftrst, uint8_t radiocntlsoftrst, uint8_t swintreq, uint8_t rftestabort, uint8_t advertabort, uint8_t scanabort, uint8_t mddsb, uint8_t sndsb, uint8_t nesndsb, uint8_t cryptdsb, uint8_t lrpmapdsb, uint8_t lrfecdsb, uint8_t whitdsb, uint8_t crcdsb, uint8_t hopremapdsb, uint8_t rxcteerrretxen, uint8_t anonymousadvfilten, uint8_t advertfilten, uint8_t rwbleen, uint8_t rxwinszdef) +{ + BLE_ASSERT_ERR((((uint32_t)mastersoftrst << 31) & ~((uint32_t)0x80000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)mastertgsoftrst << 30) & ~((uint32_t)0x40000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)regsoftrst << 29) & ~((uint32_t)0x20000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)radiocntlsoftrst << 28) & ~((uint32_t)0x10000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)swintreq << 27) & ~((uint32_t)0x08000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)rftestabort << 26) & ~((uint32_t)0x04000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)advertabort << 25) & ~((uint32_t)0x02000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)scanabort << 24) & ~((uint32_t)0x01000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)mddsb << 20) & ~((uint32_t)0x00100000)) == 0); + BLE_ASSERT_ERR((((uint32_t)sndsb << 19) & ~((uint32_t)0x00080000)) == 0); + BLE_ASSERT_ERR((((uint32_t)nesndsb << 18) & ~((uint32_t)0x00040000)) == 0); + BLE_ASSERT_ERR((((uint32_t)cryptdsb << 17) & ~((uint32_t)0x00020000)) == 0); + BLE_ASSERT_ERR((((uint32_t)lrpmapdsb << 16) & ~((uint32_t)0x00010000)) == 0); + BLE_ASSERT_ERR((((uint32_t)lrfecdsb << 15) & ~((uint32_t)0x00008000)) == 0); + BLE_ASSERT_ERR((((uint32_t)whitdsb << 14) & ~((uint32_t)0x00004000)) == 0); + BLE_ASSERT_ERR((((uint32_t)crcdsb << 13) & ~((uint32_t)0x00002000)) == 0); + BLE_ASSERT_ERR((((uint32_t)hopremapdsb << 12) & ~((uint32_t)0x00001000)) == 0); + BLE_ASSERT_ERR((((uint32_t)rxcteerrretxen << 11) & ~((uint32_t)0x00000800)) == 0); + BLE_ASSERT_ERR((((uint32_t)anonymousadvfilten << 10) & ~((uint32_t)0x00000400)) == 0); + BLE_ASSERT_ERR((((uint32_t)advertfilten << 9) & ~((uint32_t)0x00000200)) == 0); + BLE_ASSERT_ERR((((uint32_t)rwbleen << 8) & ~((uint32_t)0x00000100)) == 0); + BLE_ASSERT_ERR((((uint32_t)rxwinszdef << 0) & ~((uint32_t)0x0000000F)) == 0); + REG_BLE_WR(BLE_RWBLECNTL_ADDR, ((uint32_t)mastersoftrst << 31) | ((uint32_t)mastertgsoftrst << 30) | ((uint32_t)regsoftrst << 29) | ((uint32_t)radiocntlsoftrst << 28) | ((uint32_t)swintreq << 27) | ((uint32_t)rftestabort << 26) | ((uint32_t)advertabort << 25) | ((uint32_t)scanabort << 24) | ((uint32_t)mddsb << 20) | ((uint32_t)sndsb << 19) | ((uint32_t)nesndsb << 18) | ((uint32_t)cryptdsb << 17) | ((uint32_t)lrpmapdsb << 16) | ((uint32_t)lrfecdsb << 15) | ((uint32_t)whitdsb << 14) | ((uint32_t)crcdsb << 13) | ((uint32_t)hopremapdsb << 12) | ((uint32_t)rxcteerrretxen << 11) | ((uint32_t)anonymousadvfilten << 10) | ((uint32_t)advertfilten << 9) | ((uint32_t)rwbleen << 8) | ((uint32_t)rxwinszdef << 0)); +} + +__INLINE void ble_rwblecntl_unpack(uint8_t* mastersoftrst, uint8_t* mastertgsoftrst, uint8_t* regsoftrst, uint8_t* radiocntlsoftrst, uint8_t* swintreq, uint8_t* rftestabort, uint8_t* advertabort, uint8_t* scanabort, uint8_t* mddsb, uint8_t* sndsb, uint8_t* nesndsb, uint8_t* cryptdsb, uint8_t* lrpmapdsb, uint8_t* lrfecdsb, uint8_t* whitdsb, uint8_t* crcdsb, uint8_t* hopremapdsb, uint8_t* rxcteerrretxen, uint8_t* anonymousadvfilten, uint8_t* advertfilten, uint8_t* rwbleen, uint8_t* rxwinszdef) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECNTL_ADDR); + + *mastersoftrst = (localVal & ((uint32_t)0x80000000)) >> 31; + *mastertgsoftrst = (localVal & ((uint32_t)0x40000000)) >> 30; + *regsoftrst = (localVal & ((uint32_t)0x20000000)) >> 29; + *radiocntlsoftrst = (localVal & ((uint32_t)0x10000000)) >> 28; + *swintreq = (localVal & ((uint32_t)0x08000000)) >> 27; + *rftestabort = (localVal & ((uint32_t)0x04000000)) >> 26; + *advertabort = (localVal & ((uint32_t)0x02000000)) >> 25; + *scanabort = (localVal & ((uint32_t)0x01000000)) >> 24; + *mddsb = (localVal & ((uint32_t)0x00100000)) >> 20; + *sndsb = (localVal & ((uint32_t)0x00080000)) >> 19; + *nesndsb = (localVal & ((uint32_t)0x00040000)) >> 18; + *cryptdsb = (localVal & ((uint32_t)0x00020000)) >> 17; + *lrpmapdsb = (localVal & ((uint32_t)0x00010000)) >> 16; + *lrfecdsb = (localVal & ((uint32_t)0x00008000)) >> 15; + *whitdsb = (localVal & ((uint32_t)0x00004000)) >> 14; + *crcdsb = (localVal & ((uint32_t)0x00002000)) >> 13; + *hopremapdsb = (localVal & ((uint32_t)0x00001000)) >> 12; + *rxcteerrretxen = (localVal & ((uint32_t)0x00000800)) >> 11; + *anonymousadvfilten = (localVal & ((uint32_t)0x00000400)) >> 10; + *advertfilten = (localVal & ((uint32_t)0x00000200)) >> 9; + *rwbleen = (localVal & ((uint32_t)0x00000100)) >> 8; + *rxwinszdef = (localVal & ((uint32_t)0x0000000F)) >> 0; +} + +__INLINE uint8_t ble_rwblecntl_master_soft_rst_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECNTL_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +__INLINE void ble_rwblecntl_master_soft_rst_setf(uint8_t mastersoftrst) +{ + BLE_ASSERT_ERR((((uint32_t)mastersoftrst << 31) & ~((uint32_t)0x80000000)) == 0); + REG_BLE_WR(BLE_RWBLECNTL_ADDR, (REG_BLE_RD(BLE_RWBLECNTL_ADDR) & ~((uint32_t)0x80000000)) | ((uint32_t)mastersoftrst << 31)); +} + +__INLINE uint8_t ble_rwblecntl_master_tgsoft_rst_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECNTL_ADDR); + return ((localVal & ((uint32_t)0x40000000)) >> 30); +} + +__INLINE void ble_rwblecntl_master_tgsoft_rst_setf(uint8_t mastertgsoftrst) +{ + BLE_ASSERT_ERR((((uint32_t)mastertgsoftrst << 30) & ~((uint32_t)0x40000000)) == 0); + REG_BLE_WR(BLE_RWBLECNTL_ADDR, (REG_BLE_RD(BLE_RWBLECNTL_ADDR) & ~((uint32_t)0x40000000)) | ((uint32_t)mastertgsoftrst << 30)); +} + +__INLINE uint8_t ble_rwblecntl_reg_soft_rst_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECNTL_ADDR); + return ((localVal & ((uint32_t)0x20000000)) >> 29); +} + +__INLINE void ble_rwblecntl_reg_soft_rst_setf(uint8_t regsoftrst) +{ + BLE_ASSERT_ERR((((uint32_t)regsoftrst << 29) & ~((uint32_t)0x20000000)) == 0); + REG_BLE_WR(BLE_RWBLECNTL_ADDR, (REG_BLE_RD(BLE_RWBLECNTL_ADDR) & ~((uint32_t)0x20000000)) | ((uint32_t)regsoftrst << 29)); +} + +__INLINE uint8_t ble_rwblecntl_radiocntl_soft_rst_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECNTL_ADDR); + return ((localVal & ((uint32_t)0x10000000)) >> 28); +} + +__INLINE void ble_rwblecntl_radiocntl_soft_rst_setf(uint8_t radiocntlsoftrst) +{ + BLE_ASSERT_ERR((((uint32_t)radiocntlsoftrst << 28) & ~((uint32_t)0x10000000)) == 0); + REG_BLE_WR(BLE_RWBLECNTL_ADDR, (REG_BLE_RD(BLE_RWBLECNTL_ADDR) & ~((uint32_t)0x10000000)) | ((uint32_t)radiocntlsoftrst << 28)); +} + +__INLINE uint8_t ble_rwblecntl_swint_req_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECNTL_ADDR); + return ((localVal & ((uint32_t)0x08000000)) >> 27); +} + +__INLINE void ble_rwblecntl_swint_req_setf(uint8_t swintreq) +{ + BLE_ASSERT_ERR((((uint32_t)swintreq << 27) & ~((uint32_t)0x08000000)) == 0); + REG_BLE_WR(BLE_RWBLECNTL_ADDR, (REG_BLE_RD(BLE_RWBLECNTL_ADDR) & ~((uint32_t)0x08000000)) | ((uint32_t)swintreq << 27)); +} + +__INLINE uint8_t ble_rwblecntl_rftest_abort_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECNTL_ADDR); + return ((localVal & ((uint32_t)0x04000000)) >> 26); +} + +__INLINE void ble_rwblecntl_rftest_abort_setf(uint8_t rftestabort) +{ + BLE_ASSERT_ERR((((uint32_t)rftestabort << 26) & ~((uint32_t)0x04000000)) == 0); + REG_BLE_WR(BLE_RWBLECNTL_ADDR, (REG_BLE_RD(BLE_RWBLECNTL_ADDR) & ~((uint32_t)0x04000000)) | ((uint32_t)rftestabort << 26)); +} + +__INLINE uint8_t ble_rwblecntl_advert_abort_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECNTL_ADDR); + return ((localVal & ((uint32_t)0x02000000)) >> 25); +} + +__INLINE void ble_rwblecntl_advert_abort_setf(uint8_t advertabort) +{ + BLE_ASSERT_ERR((((uint32_t)advertabort << 25) & ~((uint32_t)0x02000000)) == 0); + REG_BLE_WR(BLE_RWBLECNTL_ADDR, (REG_BLE_RD(BLE_RWBLECNTL_ADDR) & ~((uint32_t)0x02000000)) | ((uint32_t)advertabort << 25)); +} + +__INLINE uint8_t ble_rwblecntl_scan_abort_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECNTL_ADDR); + return ((localVal & ((uint32_t)0x01000000)) >> 24); +} + +__INLINE void ble_rwblecntl_scan_abort_setf(uint8_t scanabort) +{ + BLE_ASSERT_ERR((((uint32_t)scanabort << 24) & ~((uint32_t)0x01000000)) == 0); + REG_BLE_WR(BLE_RWBLECNTL_ADDR, (REG_BLE_RD(BLE_RWBLECNTL_ADDR) & ~((uint32_t)0x01000000)) | ((uint32_t)scanabort << 24)); +} + +__INLINE uint8_t ble_rwblecntl_md_dsb_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECNTL_ADDR); + return ((localVal & ((uint32_t)0x00100000)) >> 20); +} + +__INLINE void ble_rwblecntl_md_dsb_setf(uint8_t mddsb) +{ + BLE_ASSERT_ERR((((uint32_t)mddsb << 20) & ~((uint32_t)0x00100000)) == 0); + REG_BLE_WR(BLE_RWBLECNTL_ADDR, (REG_BLE_RD(BLE_RWBLECNTL_ADDR) & ~((uint32_t)0x00100000)) | ((uint32_t)mddsb << 20)); +} + +__INLINE uint8_t ble_rwblecntl_sn_dsb_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECNTL_ADDR); + return ((localVal & ((uint32_t)0x00080000)) >> 19); +} + +__INLINE void ble_rwblecntl_sn_dsb_setf(uint8_t sndsb) +{ + BLE_ASSERT_ERR((((uint32_t)sndsb << 19) & ~((uint32_t)0x00080000)) == 0); + REG_BLE_WR(BLE_RWBLECNTL_ADDR, (REG_BLE_RD(BLE_RWBLECNTL_ADDR) & ~((uint32_t)0x00080000)) | ((uint32_t)sndsb << 19)); +} + +__INLINE uint8_t ble_rwblecntl_nesn_dsb_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECNTL_ADDR); + return ((localVal & ((uint32_t)0x00040000)) >> 18); +} + +__INLINE void ble_rwblecntl_nesn_dsb_setf(uint8_t nesndsb) +{ + BLE_ASSERT_ERR((((uint32_t)nesndsb << 18) & ~((uint32_t)0x00040000)) == 0); + REG_BLE_WR(BLE_RWBLECNTL_ADDR, (REG_BLE_RD(BLE_RWBLECNTL_ADDR) & ~((uint32_t)0x00040000)) | ((uint32_t)nesndsb << 18)); +} + +__INLINE uint8_t ble_rwblecntl_crypt_dsb_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECNTL_ADDR); + return ((localVal & ((uint32_t)0x00020000)) >> 17); +} + +__INLINE void ble_rwblecntl_crypt_dsb_setf(uint8_t cryptdsb) +{ + BLE_ASSERT_ERR((((uint32_t)cryptdsb << 17) & ~((uint32_t)0x00020000)) == 0); + REG_BLE_WR(BLE_RWBLECNTL_ADDR, (REG_BLE_RD(BLE_RWBLECNTL_ADDR) & ~((uint32_t)0x00020000)) | ((uint32_t)cryptdsb << 17)); +} + +__INLINE uint8_t ble_rwblecntl_lrpmap_dsb_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECNTL_ADDR); + return ((localVal & ((uint32_t)0x00010000)) >> 16); +} + +__INLINE void ble_rwblecntl_lrpmap_dsb_setf(uint8_t lrpmapdsb) +{ + BLE_ASSERT_ERR((((uint32_t)lrpmapdsb << 16) & ~((uint32_t)0x00010000)) == 0); + REG_BLE_WR(BLE_RWBLECNTL_ADDR, (REG_BLE_RD(BLE_RWBLECNTL_ADDR) & ~((uint32_t)0x00010000)) | ((uint32_t)lrpmapdsb << 16)); +} + +__INLINE uint8_t ble_rwblecntl_lrfec_dsb_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECNTL_ADDR); + return ((localVal & ((uint32_t)0x00008000)) >> 15); +} + +__INLINE void ble_rwblecntl_lrfec_dsb_setf(uint8_t lrfecdsb) +{ + BLE_ASSERT_ERR((((uint32_t)lrfecdsb << 15) & ~((uint32_t)0x00008000)) == 0); + REG_BLE_WR(BLE_RWBLECNTL_ADDR, (REG_BLE_RD(BLE_RWBLECNTL_ADDR) & ~((uint32_t)0x00008000)) | ((uint32_t)lrfecdsb << 15)); +} + +__INLINE uint8_t ble_rwblecntl_whit_dsb_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECNTL_ADDR); + return ((localVal & ((uint32_t)0x00004000)) >> 14); +} + +__INLINE void ble_rwblecntl_whit_dsb_setf(uint8_t whitdsb) +{ + BLE_ASSERT_ERR((((uint32_t)whitdsb << 14) & ~((uint32_t)0x00004000)) == 0); + REG_BLE_WR(BLE_RWBLECNTL_ADDR, (REG_BLE_RD(BLE_RWBLECNTL_ADDR) & ~((uint32_t)0x00004000)) | ((uint32_t)whitdsb << 14)); +} + +__INLINE uint8_t ble_rwblecntl_crc_dsb_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECNTL_ADDR); + return ((localVal & ((uint32_t)0x00002000)) >> 13); +} + +__INLINE void ble_rwblecntl_crc_dsb_setf(uint8_t crcdsb) +{ + BLE_ASSERT_ERR((((uint32_t)crcdsb << 13) & ~((uint32_t)0x00002000)) == 0); + REG_BLE_WR(BLE_RWBLECNTL_ADDR, (REG_BLE_RD(BLE_RWBLECNTL_ADDR) & ~((uint32_t)0x00002000)) | ((uint32_t)crcdsb << 13)); +} + +__INLINE uint8_t ble_rwblecntl_hop_remap_dsb_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECNTL_ADDR); + return ((localVal & ((uint32_t)0x00001000)) >> 12); +} + +__INLINE void ble_rwblecntl_hop_remap_dsb_setf(uint8_t hopremapdsb) +{ + BLE_ASSERT_ERR((((uint32_t)hopremapdsb << 12) & ~((uint32_t)0x00001000)) == 0); + REG_BLE_WR(BLE_RWBLECNTL_ADDR, (REG_BLE_RD(BLE_RWBLECNTL_ADDR) & ~((uint32_t)0x00001000)) | ((uint32_t)hopremapdsb << 12)); +} + +__INLINE uint8_t ble_rwblecntl_rxcteerr_retx_en_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECNTL_ADDR); + return ((localVal & ((uint32_t)0x00000800)) >> 11); +} + +__INLINE void ble_rwblecntl_rxcteerr_retx_en_setf(uint8_t rxcteerrretxen) +{ + BLE_ASSERT_ERR((((uint32_t)rxcteerrretxen << 11) & ~((uint32_t)0x00000800)) == 0); + REG_BLE_WR(BLE_RWBLECNTL_ADDR, (REG_BLE_RD(BLE_RWBLECNTL_ADDR) & ~((uint32_t)0x00000800)) | ((uint32_t)rxcteerrretxen << 11)); +} + +__INLINE uint8_t ble_rwblecntl_anonymous_adv_filt_en_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECNTL_ADDR); + return ((localVal & ((uint32_t)0x00000400)) >> 10); +} + +__INLINE void ble_rwblecntl_anonymous_adv_filt_en_setf(uint8_t anonymousadvfilten) +{ + BLE_ASSERT_ERR((((uint32_t)anonymousadvfilten << 10) & ~((uint32_t)0x00000400)) == 0); + REG_BLE_WR(BLE_RWBLECNTL_ADDR, (REG_BLE_RD(BLE_RWBLECNTL_ADDR) & ~((uint32_t)0x00000400)) | ((uint32_t)anonymousadvfilten << 10)); +} + +__INLINE uint8_t ble_rwblecntl_advertfilt_en_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECNTL_ADDR); + return ((localVal & ((uint32_t)0x00000200)) >> 9); +} + +__INLINE void ble_rwblecntl_advertfilt_en_setf(uint8_t advertfilten) +{ + BLE_ASSERT_ERR((((uint32_t)advertfilten << 9) & ~((uint32_t)0x00000200)) == 0); + REG_BLE_WR(BLE_RWBLECNTL_ADDR, (REG_BLE_RD(BLE_RWBLECNTL_ADDR) & ~((uint32_t)0x00000200)) | ((uint32_t)advertfilten << 9)); +} + +__INLINE uint8_t ble_rwblecntl_rwble_en_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECNTL_ADDR); + return ((localVal & ((uint32_t)0x00000100)) >> 8); +} + +__INLINE void ble_rwblecntl_rwble_en_setf(uint8_t rwbleen) +{ + BLE_ASSERT_ERR((((uint32_t)rwbleen << 8) & ~((uint32_t)0x00000100)) == 0); + REG_BLE_WR(BLE_RWBLECNTL_ADDR, (REG_BLE_RD(BLE_RWBLECNTL_ADDR) & ~((uint32_t)0x00000100)) | ((uint32_t)rwbleen << 8)); +} + +__INLINE uint8_t ble_rwblecntl_rxwinszdef_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECNTL_ADDR); + return ((localVal & ((uint32_t)0x0000000F)) >> 0); +} + +__INLINE void ble_rwblecntl_rxwinszdef_setf(uint8_t rxwinszdef) +{ + BLE_ASSERT_ERR((((uint32_t)rxwinszdef << 0) & ~((uint32_t)0x0000000F)) == 0); + REG_BLE_WR(BLE_RWBLECNTL_ADDR, (REG_BLE_RD(BLE_RWBLECNTL_ADDR) & ~((uint32_t)0x0000000F)) | ((uint32_t)rxwinszdef << 0)); +} + +/** + * @brief VERSION register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:24                  TYP   0xA
+ *  23:16                  REL   0x0
+ *  15:08                  UPG   0xF
+ *  07:00                BUILD   0x0
+ * 
+ */ +#define BLE_VERSION_ADDR 0x00900804 +#define BLE_VERSION_OFFSET 0x00000004 +#define BLE_VERSION_INDEX 0x00000001 +#define BLE_VERSION_RESET 0x0A000F00 + +__INLINE uint32_t ble_version_get(void) +{ + return REG_BLE_RD(BLE_VERSION_ADDR); +} + +// field definitions +#define BLE_TYP_MASK ((uint32_t)0xFF000000) +#define BLE_TYP_LSB 24 +#define BLE_TYP_WIDTH ((uint32_t)0x00000008) +#define BLE_REL_MASK ((uint32_t)0x00FF0000) +#define BLE_REL_LSB 16 +#define BLE_REL_WIDTH ((uint32_t)0x00000008) +#define BLE_UPG_MASK ((uint32_t)0x0000FF00) +#define BLE_UPG_LSB 8 +#define BLE_UPG_WIDTH ((uint32_t)0x00000008) +#define BLE_BUILD_MASK ((uint32_t)0x000000FF) +#define BLE_BUILD_LSB 0 +#define BLE_BUILD_WIDTH ((uint32_t)0x00000008) + +#define BLE_TYP_RST 0xA +#define BLE_REL_RST 0x0 +#define BLE_UPG_RST 0xF +#define BLE_BUILD_RST 0x0 + +__INLINE void ble_version_unpack(uint8_t* typ, uint8_t* rel, uint8_t* upg, uint8_t* build) +{ + uint32_t localVal = REG_BLE_RD(BLE_VERSION_ADDR); + + *typ = (localVal & ((uint32_t)0xFF000000)) >> 24; + *rel = (localVal & ((uint32_t)0x00FF0000)) >> 16; + *upg = (localVal & ((uint32_t)0x0000FF00)) >> 8; + *build = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +__INLINE uint8_t ble_version_typ_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_VERSION_ADDR); + return ((localVal & ((uint32_t)0xFF000000)) >> 24); +} + +__INLINE uint8_t ble_version_rel_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_VERSION_ADDR); + return ((localVal & ((uint32_t)0x00FF0000)) >> 16); +} + +__INLINE uint8_t ble_version_upg_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_VERSION_ADDR); + return ((localVal & ((uint32_t)0x0000FF00)) >> 8); +} + +__INLINE uint8_t ble_version_build_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_VERSION_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +/** + * @brief RWBLECONF register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31               DMMODE   0
+ *     28           CORRELATOR   1
+ *     27              USERXLR   1
+ *     26              USETXLR   1
+ *     24               USEISO   1
+ *     21             WLANCOEX   1
+ *  20:16                 RFIF   0x1
+ *     15               USEDBG   1
+ *     14             DECIPHER   0
+ *  13:08              CLK_SEL   0x8
+ *     07              INTMODE   1
+ *     06             BUS_TYPE   0
+ *  04:00           ADDR_WIDTH   0xD
+ * 
+ */ +#define BLE_RWBLECONF_ADDR 0x00900808 +#define BLE_RWBLECONF_OFFSET 0x00000008 +#define BLE_RWBLECONF_INDEX 0x00000002 +#define BLE_RWBLECONF_RESET 0x1D21888D + +__INLINE uint32_t ble_rwbleconf_get(void) +{ + return REG_BLE_RD(BLE_RWBLECONF_ADDR); +} + +// field definitions +#define BLE_DMMODE_BIT ((uint32_t)0x80000000) +#define BLE_DMMODE_POS 31 +#define BLE_CORRELATOR_BIT ((uint32_t)0x10000000) +#define BLE_CORRELATOR_POS 28 +#define BLE_USERXLR_BIT ((uint32_t)0x08000000) +#define BLE_USERXLR_POS 27 +#define BLE_USETXLR_BIT ((uint32_t)0x04000000) +#define BLE_USETXLR_POS 26 +#define BLE_USEISO_BIT ((uint32_t)0x01000000) +#define BLE_USEISO_POS 24 +#define BLE_WLANCOEX_BIT ((uint32_t)0x00200000) +#define BLE_WLANCOEX_POS 21 +#define BLE_RFIF_MASK ((uint32_t)0x001F0000) +#define BLE_RFIF_LSB 16 +#define BLE_RFIF_WIDTH ((uint32_t)0x00000005) +#define BLE_USEDBG_BIT ((uint32_t)0x00008000) +#define BLE_USEDBG_POS 15 +#define BLE_DECIPHER_BIT ((uint32_t)0x00004000) +#define BLE_DECIPHER_POS 14 +#define BLE_CLK_SEL_MASK ((uint32_t)0x00003F00) +#define BLE_CLK_SEL_LSB 8 +#define BLE_CLK_SEL_WIDTH ((uint32_t)0x00000006) +#define BLE_INTMODE_BIT ((uint32_t)0x00000080) +#define BLE_INTMODE_POS 7 +#define BLE_BUS_TYPE_BIT ((uint32_t)0x00000040) +#define BLE_BUS_TYPE_POS 6 +#define BLE_ADDR_WIDTH_MASK ((uint32_t)0x0000001F) +#define BLE_ADDR_WIDTH_LSB 0 +#define BLE_ADDR_WIDTH_WIDTH ((uint32_t)0x00000005) + +#define BLE_DMMODE_RST 0x0 +#define BLE_CORRELATOR_RST 0x1 +#define BLE_USERXLR_RST 0x1 +#define BLE_USETXLR_RST 0x1 +#define BLE_USEISO_RST 0x1 +#define BLE_WLANCOEX_RST 0x1 +#define BLE_RFIF_RST 0x1 +#define BLE_USEDBG_RST 0x1 +#define BLE_DECIPHER_RST 0x0 +#define BLE_CLK_SEL_RST 0x8 +#define BLE_INTMODE_RST 0x1 +#define BLE_BUS_TYPE_RST 0x0 +#define BLE_ADDR_WIDTH_RST 0xD + +__INLINE void ble_rwbleconf_unpack(uint8_t* dmmode, uint8_t* correlator, uint8_t* userxlr, uint8_t* usetxlr, uint8_t* useiso, uint8_t* wlancoex, uint8_t* rfif, uint8_t* usedbg, uint8_t* decipher, uint8_t* clksel, uint8_t* intmode, uint8_t* bustype, uint8_t* addrwidth) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECONF_ADDR); + + *dmmode = (localVal & ((uint32_t)0x80000000)) >> 31; + *correlator = (localVal & ((uint32_t)0x10000000)) >> 28; + *userxlr = (localVal & ((uint32_t)0x08000000)) >> 27; + *usetxlr = (localVal & ((uint32_t)0x04000000)) >> 26; + *useiso = (localVal & ((uint32_t)0x01000000)) >> 24; + *wlancoex = (localVal & ((uint32_t)0x00200000)) >> 21; + *rfif = (localVal & ((uint32_t)0x001F0000)) >> 16; + *usedbg = (localVal & ((uint32_t)0x00008000)) >> 15; + *decipher = (localVal & ((uint32_t)0x00004000)) >> 14; + *clksel = (localVal & ((uint32_t)0x00003F00)) >> 8; + *intmode = (localVal & ((uint32_t)0x00000080)) >> 7; + *bustype = (localVal & ((uint32_t)0x00000040)) >> 6; + *addrwidth = (localVal & ((uint32_t)0x0000001F)) >> 0; +} + +__INLINE uint8_t ble_rwbleconf_dmmode_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECONF_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +__INLINE uint8_t ble_rwbleconf_correlator_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECONF_ADDR); + return ((localVal & ((uint32_t)0x10000000)) >> 28); +} + +__INLINE uint8_t ble_rwbleconf_userxlr_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECONF_ADDR); + return ((localVal & ((uint32_t)0x08000000)) >> 27); +} + +__INLINE uint8_t ble_rwbleconf_usetxlr_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECONF_ADDR); + return ((localVal & ((uint32_t)0x04000000)) >> 26); +} + +__INLINE uint8_t ble_rwbleconf_useiso_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECONF_ADDR); + return ((localVal & ((uint32_t)0x01000000)) >> 24); +} + +__INLINE uint8_t ble_rwbleconf_wlancoex_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECONF_ADDR); + return ((localVal & ((uint32_t)0x00200000)) >> 21); +} + +__INLINE uint8_t ble_rwbleconf_rfif_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECONF_ADDR); + return ((localVal & ((uint32_t)0x001F0000)) >> 16); +} + +__INLINE uint8_t ble_rwbleconf_usedbg_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECONF_ADDR); + return ((localVal & ((uint32_t)0x00008000)) >> 15); +} + +__INLINE uint8_t ble_rwbleconf_decipher_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECONF_ADDR); + return ((localVal & ((uint32_t)0x00004000)) >> 14); +} + +__INLINE uint8_t ble_rwbleconf_clk_sel_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECONF_ADDR); + return ((localVal & ((uint32_t)0x00003F00)) >> 8); +} + +__INLINE uint8_t ble_rwbleconf_intmode_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECONF_ADDR); + return ((localVal & ((uint32_t)0x00000080)) >> 7); +} + +__INLINE uint8_t ble_rwbleconf_bus_type_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECONF_ADDR); + return ((localVal & ((uint32_t)0x00000040)) >> 6); +} + +__INLINE uint8_t ble_rwbleconf_addr_width_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RWBLECONF_ADDR); + return ((localVal & ((uint32_t)0x0000001F)) >> 0); +} + +/** + * @brief INTCNTL0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     16          ERRORINTMSK   0
+ *     06          ISORXINTMSK   0
+ *     05          ISOTXINTMSK   0
+ *     04             RXINTMSK   0
+ *     03             TXINTMSK   0
+ *     02        SKIPEVTINTMSK   0
+ *     01         ENDEVTINTMSK   1
+ *     00       STARTEVTINTMSK   1
+ * 
+ */ +#define BLE_INTCNTL0_ADDR 0x0090080C +#define BLE_INTCNTL0_OFFSET 0x0000000C +#define BLE_INTCNTL0_INDEX 0x00000003 +#define BLE_INTCNTL0_RESET 0x00000003 + +__INLINE uint32_t ble_intcntl0_get(void) +{ + return REG_BLE_RD(BLE_INTCNTL0_ADDR); +} + +__INLINE void ble_intcntl0_set(uint32_t value) +{ + REG_BLE_WR(BLE_INTCNTL0_ADDR, value); +} + +// field definitions +#define BLE_ERRORINTMSK_BIT ((uint32_t)0x00010000) +#define BLE_ERRORINTMSK_POS 16 +#define BLE_ISORXINTMSK_BIT ((uint32_t)0x00000040) +#define BLE_ISORXINTMSK_POS 6 +#define BLE_ISOTXINTMSK_BIT ((uint32_t)0x00000020) +#define BLE_ISOTXINTMSK_POS 5 +#define BLE_RXINTMSK_BIT ((uint32_t)0x00000010) +#define BLE_RXINTMSK_POS 4 +#define BLE_TXINTMSK_BIT ((uint32_t)0x00000008) +#define BLE_TXINTMSK_POS 3 +#define BLE_SKIPEVTINTMSK_BIT ((uint32_t)0x00000004) +#define BLE_SKIPEVTINTMSK_POS 2 +#define BLE_ENDEVTINTMSK_BIT ((uint32_t)0x00000002) +#define BLE_ENDEVTINTMSK_POS 1 +#define BLE_STARTEVTINTMSK_BIT ((uint32_t)0x00000001) +#define BLE_STARTEVTINTMSK_POS 0 + +#define BLE_ERRORINTMSK_RST 0x0 +#define BLE_ISORXINTMSK_RST 0x0 +#define BLE_ISOTXINTMSK_RST 0x0 +#define BLE_RXINTMSK_RST 0x0 +#define BLE_TXINTMSK_RST 0x0 +#define BLE_SKIPEVTINTMSK_RST 0x0 +#define BLE_ENDEVTINTMSK_RST 0x1 +#define BLE_STARTEVTINTMSK_RST 0x1 + +__INLINE void ble_intcntl0_pack(uint8_t errorintmsk, uint8_t isorxintmsk, uint8_t isotxintmsk, uint8_t rxintmsk, uint8_t txintmsk, uint8_t skipevtintmsk, uint8_t endevtintmsk, uint8_t startevtintmsk) +{ + BLE_ASSERT_ERR((((uint32_t)errorintmsk << 16) & ~((uint32_t)0x00010000)) == 0); + BLE_ASSERT_ERR((((uint32_t)isorxintmsk << 6) & ~((uint32_t)0x00000040)) == 0); + BLE_ASSERT_ERR((((uint32_t)isotxintmsk << 5) & ~((uint32_t)0x00000020)) == 0); + BLE_ASSERT_ERR((((uint32_t)rxintmsk << 4) & ~((uint32_t)0x00000010)) == 0); + BLE_ASSERT_ERR((((uint32_t)txintmsk << 3) & ~((uint32_t)0x00000008)) == 0); + BLE_ASSERT_ERR((((uint32_t)skipevtintmsk << 2) & ~((uint32_t)0x00000004)) == 0); + BLE_ASSERT_ERR((((uint32_t)endevtintmsk << 1) & ~((uint32_t)0x00000002)) == 0); + BLE_ASSERT_ERR((((uint32_t)startevtintmsk << 0) & ~((uint32_t)0x00000001)) == 0); + REG_BLE_WR(BLE_INTCNTL0_ADDR, ((uint32_t)errorintmsk << 16) | ((uint32_t)isorxintmsk << 6) | ((uint32_t)isotxintmsk << 5) | ((uint32_t)rxintmsk << 4) | ((uint32_t)txintmsk << 3) | ((uint32_t)skipevtintmsk << 2) | ((uint32_t)endevtintmsk << 1) | ((uint32_t)startevtintmsk << 0)); +} + +__INLINE void ble_intcntl0_unpack(uint8_t* errorintmsk, uint8_t* isorxintmsk, uint8_t* isotxintmsk, uint8_t* rxintmsk, uint8_t* txintmsk, uint8_t* skipevtintmsk, uint8_t* endevtintmsk, uint8_t* startevtintmsk) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTCNTL0_ADDR); + + *errorintmsk = (localVal & ((uint32_t)0x00010000)) >> 16; + *isorxintmsk = (localVal & ((uint32_t)0x00000040)) >> 6; + *isotxintmsk = (localVal & ((uint32_t)0x00000020)) >> 5; + *rxintmsk = (localVal & ((uint32_t)0x00000010)) >> 4; + *txintmsk = (localVal & ((uint32_t)0x00000008)) >> 3; + *skipevtintmsk = (localVal & ((uint32_t)0x00000004)) >> 2; + *endevtintmsk = (localVal & ((uint32_t)0x00000002)) >> 1; + *startevtintmsk = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +__INLINE uint8_t ble_intcntl0_errorintmsk_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTCNTL0_ADDR); + return ((localVal & ((uint32_t)0x00010000)) >> 16); +} + +__INLINE void ble_intcntl0_errorintmsk_setf(uint8_t errorintmsk) +{ + BLE_ASSERT_ERR((((uint32_t)errorintmsk << 16) & ~((uint32_t)0x00010000)) == 0); + REG_BLE_WR(BLE_INTCNTL0_ADDR, (REG_BLE_RD(BLE_INTCNTL0_ADDR) & ~((uint32_t)0x00010000)) | ((uint32_t)errorintmsk << 16)); +} + +__INLINE uint8_t ble_intcntl0_isorxintmsk_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTCNTL0_ADDR); + return ((localVal & ((uint32_t)0x00000040)) >> 6); +} + +__INLINE void ble_intcntl0_isorxintmsk_setf(uint8_t isorxintmsk) +{ + BLE_ASSERT_ERR((((uint32_t)isorxintmsk << 6) & ~((uint32_t)0x00000040)) == 0); + REG_BLE_WR(BLE_INTCNTL0_ADDR, (REG_BLE_RD(BLE_INTCNTL0_ADDR) & ~((uint32_t)0x00000040)) | ((uint32_t)isorxintmsk << 6)); +} + +__INLINE uint8_t ble_intcntl0_isotxintmsk_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTCNTL0_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +__INLINE void ble_intcntl0_isotxintmsk_setf(uint8_t isotxintmsk) +{ + BLE_ASSERT_ERR((((uint32_t)isotxintmsk << 5) & ~((uint32_t)0x00000020)) == 0); + REG_BLE_WR(BLE_INTCNTL0_ADDR, (REG_BLE_RD(BLE_INTCNTL0_ADDR) & ~((uint32_t)0x00000020)) | ((uint32_t)isotxintmsk << 5)); +} + +__INLINE uint8_t ble_intcntl0_rxintmsk_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTCNTL0_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +__INLINE void ble_intcntl0_rxintmsk_setf(uint8_t rxintmsk) +{ + BLE_ASSERT_ERR((((uint32_t)rxintmsk << 4) & ~((uint32_t)0x00000010)) == 0); + REG_BLE_WR(BLE_INTCNTL0_ADDR, (REG_BLE_RD(BLE_INTCNTL0_ADDR) & ~((uint32_t)0x00000010)) | ((uint32_t)rxintmsk << 4)); +} + +__INLINE uint8_t ble_intcntl0_txintmsk_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTCNTL0_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +__INLINE void ble_intcntl0_txintmsk_setf(uint8_t txintmsk) +{ + BLE_ASSERT_ERR((((uint32_t)txintmsk << 3) & ~((uint32_t)0x00000008)) == 0); + REG_BLE_WR(BLE_INTCNTL0_ADDR, (REG_BLE_RD(BLE_INTCNTL0_ADDR) & ~((uint32_t)0x00000008)) | ((uint32_t)txintmsk << 3)); +} + +__INLINE uint8_t ble_intcntl0_skipevtintmsk_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTCNTL0_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +__INLINE void ble_intcntl0_skipevtintmsk_setf(uint8_t skipevtintmsk) +{ + BLE_ASSERT_ERR((((uint32_t)skipevtintmsk << 2) & ~((uint32_t)0x00000004)) == 0); + REG_BLE_WR(BLE_INTCNTL0_ADDR, (REG_BLE_RD(BLE_INTCNTL0_ADDR) & ~((uint32_t)0x00000004)) | ((uint32_t)skipevtintmsk << 2)); +} + +__INLINE uint8_t ble_intcntl0_endevtintmsk_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTCNTL0_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +__INLINE void ble_intcntl0_endevtintmsk_setf(uint8_t endevtintmsk) +{ + BLE_ASSERT_ERR((((uint32_t)endevtintmsk << 1) & ~((uint32_t)0x00000002)) == 0); + REG_BLE_WR(BLE_INTCNTL0_ADDR, (REG_BLE_RD(BLE_INTCNTL0_ADDR) & ~((uint32_t)0x00000002)) | ((uint32_t)endevtintmsk << 1)); +} + +__INLINE uint8_t ble_intcntl0_startevtintmsk_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTCNTL0_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +__INLINE void ble_intcntl0_startevtintmsk_setf(uint8_t startevtintmsk) +{ + BLE_ASSERT_ERR((((uint32_t)startevtintmsk << 0) & ~((uint32_t)0x00000001)) == 0); + REG_BLE_WR(BLE_INTCNTL0_ADDR, (REG_BLE_RD(BLE_INTCNTL0_ADDR) & ~((uint32_t)0x00000001)) | ((uint32_t)startevtintmsk << 0)); +} + +/** + * @brief INTSTAT0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     16         ERRORINTSTAT   0
+ * 
+ */ +#define BLE_INTSTAT0_ADDR 0x00900810 +#define BLE_INTSTAT0_OFFSET 0x00000010 +#define BLE_INTSTAT0_INDEX 0x00000004 +#define BLE_INTSTAT0_RESET 0x00000000 + +__INLINE uint32_t ble_intstat0_get(void) +{ + return REG_BLE_RD(BLE_INTSTAT0_ADDR); +} + +// field definitions +#define BLE_ERRORINTSTAT_BIT ((uint32_t)0x00010000) +#define BLE_ERRORINTSTAT_POS 16 + +#define BLE_ERRORINTSTAT_RST 0x0 + +__INLINE uint8_t ble_intstat0_errorintstat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTSTAT0_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0x00010000)) == 0); + return (localVal >> 16); +} + +/** + * @brief INTACK0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     16          ERRORINTACK   0
+ * 
+ */ +#define BLE_INTACK0_ADDR 0x00900814 +#define BLE_INTACK0_OFFSET 0x00000014 +#define BLE_INTACK0_INDEX 0x00000005 +#define BLE_INTACK0_RESET 0x00000000 + +__INLINE uint32_t ble_intack0_get(void) +{ + return REG_BLE_RD(BLE_INTACK0_ADDR); +} + +__INLINE void ble_intack0_clear(uint32_t value) +{ + REG_BLE_WR(BLE_INTACK0_ADDR, value); +} + +// field definitions +#define BLE_ERRORINTACK_BIT ((uint32_t)0x00010000) +#define BLE_ERRORINTACK_POS 16 + +#define BLE_ERRORINTACK_RST 0x0 + +__INLINE uint8_t ble_intack0_errorintack_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTACK0_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0x00010000)) == 0); + return (localVal >> 16); +} + +__INLINE void ble_intack0_errorintack_clearf(uint8_t errorintack) +{ + BLE_ASSERT_ERR((((uint32_t)errorintack << 16) & ~((uint32_t)0x00010000)) == 0); + REG_BLE_WR(BLE_INTACK0_ADDR, (uint32_t)errorintack << 16); +} + +/** + * @brief INTCNTL1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  30:28         CLKNINTSRMSK   0x0
+ *  27:24         CLKNINTSRVAL   0x0
+ *     15           FIFOINTMSK   1
+ *     06   TIMESTAMPTGT2INTMSK   0
+ *     05   TIMESTAMPTGT1INTMSK   0
+ *     04        FINETGTINTMSK   0
+ *     03             SWINTMSK   0
+ *     02          CRYPTINTMSK   0
+ *     01            SLPINTMSK   1
+ *     00           CLKNINTMSK   1
+ * 
+ */ +#define BLE_INTCNTL1_ADDR 0x00900818 +#define BLE_INTCNTL1_OFFSET 0x00000018 +#define BLE_INTCNTL1_INDEX 0x00000006 +#define BLE_INTCNTL1_RESET 0x00008003 + +__INLINE uint32_t ble_intcntl1_get(void) +{ + return REG_BLE_RD(BLE_INTCNTL1_ADDR); +} + +__INLINE void ble_intcntl1_set(uint32_t value) +{ + REG_BLE_WR(BLE_INTCNTL1_ADDR, value); +} + +// field definitions +#define BLE_CLKNINTSRMSK_MASK ((uint32_t)0x70000000) +#define BLE_CLKNINTSRMSK_LSB 28 +#define BLE_CLKNINTSRMSK_WIDTH ((uint32_t)0x00000003) +#define BLE_CLKNINTSRVAL_MASK ((uint32_t)0x0F000000) +#define BLE_CLKNINTSRVAL_LSB 24 +#define BLE_CLKNINTSRVAL_WIDTH ((uint32_t)0x00000004) +#define BLE_FIFOINTMSK_BIT ((uint32_t)0x00008000) +#define BLE_FIFOINTMSK_POS 15 +#define BLE_TIMESTAMPTGT2INTMSK_BIT ((uint32_t)0x00000040) +#define BLE_TIMESTAMPTGT2INTMSK_POS 6 +#define BLE_TIMESTAMPTGT1INTMSK_BIT ((uint32_t)0x00000020) +#define BLE_TIMESTAMPTGT1INTMSK_POS 5 +#define BLE_FINETGTINTMSK_BIT ((uint32_t)0x00000010) +#define BLE_FINETGTINTMSK_POS 4 +#define BLE_SWINTMSK_BIT ((uint32_t)0x00000008) +#define BLE_SWINTMSK_POS 3 +#define BLE_CRYPTINTMSK_BIT ((uint32_t)0x00000004) +#define BLE_CRYPTINTMSK_POS 2 +#define BLE_SLPINTMSK_BIT ((uint32_t)0x00000002) +#define BLE_SLPINTMSK_POS 1 +#define BLE_CLKNINTMSK_BIT ((uint32_t)0x00000001) +#define BLE_CLKNINTMSK_POS 0 + +#define BLE_CLKNINTSRMSK_RST 0x0 +#define BLE_CLKNINTSRVAL_RST 0x0 +#define BLE_FIFOINTMSK_RST 0x1 +#define BLE_TIMESTAMPTGT2INTMSK_RST 0x0 +#define BLE_TIMESTAMPTGT1INTMSK_RST 0x0 +#define BLE_FINETGTINTMSK_RST 0x0 +#define BLE_SWINTMSK_RST 0x0 +#define BLE_CRYPTINTMSK_RST 0x0 +#define BLE_SLPINTMSK_RST 0x1 +#define BLE_CLKNINTMSK_RST 0x1 + +__INLINE void ble_intcntl1_pack(uint8_t clknintsrmsk, uint8_t clknintsrval, uint8_t fifointmsk, uint8_t timestamptgt2intmsk, uint8_t timestamptgt1intmsk, uint8_t finetgtintmsk, uint8_t swintmsk, uint8_t cryptintmsk, uint8_t slpintmsk, uint8_t clknintmsk) +{ + BLE_ASSERT_ERR((((uint32_t)clknintsrmsk << 28) & ~((uint32_t)0x70000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)clknintsrval << 24) & ~((uint32_t)0x0F000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)fifointmsk << 15) & ~((uint32_t)0x00008000)) == 0); + BLE_ASSERT_ERR((((uint32_t)timestamptgt2intmsk << 6) & ~((uint32_t)0x00000040)) == 0); + BLE_ASSERT_ERR((((uint32_t)timestamptgt1intmsk << 5) & ~((uint32_t)0x00000020)) == 0); + BLE_ASSERT_ERR((((uint32_t)finetgtintmsk << 4) & ~((uint32_t)0x00000010)) == 0); + BLE_ASSERT_ERR((((uint32_t)swintmsk << 3) & ~((uint32_t)0x00000008)) == 0); + BLE_ASSERT_ERR((((uint32_t)cryptintmsk << 2) & ~((uint32_t)0x00000004)) == 0); + BLE_ASSERT_ERR((((uint32_t)slpintmsk << 1) & ~((uint32_t)0x00000002)) == 0); + BLE_ASSERT_ERR((((uint32_t)clknintmsk << 0) & ~((uint32_t)0x00000001)) == 0); + REG_BLE_WR(BLE_INTCNTL1_ADDR, ((uint32_t)clknintsrmsk << 28) | ((uint32_t)clknintsrval << 24) | ((uint32_t)fifointmsk << 15) | ((uint32_t)timestamptgt2intmsk << 6) | ((uint32_t)timestamptgt1intmsk << 5) | ((uint32_t)finetgtintmsk << 4) | ((uint32_t)swintmsk << 3) | ((uint32_t)cryptintmsk << 2) | ((uint32_t)slpintmsk << 1) | ((uint32_t)clknintmsk << 0)); +} + +__INLINE void ble_intcntl1_unpack(uint8_t* clknintsrmsk, uint8_t* clknintsrval, uint8_t* fifointmsk, uint8_t* timestamptgt2intmsk, uint8_t* timestamptgt1intmsk, uint8_t* finetgtintmsk, uint8_t* swintmsk, uint8_t* cryptintmsk, uint8_t* slpintmsk, uint8_t* clknintmsk) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTCNTL1_ADDR); + + *clknintsrmsk = (localVal & ((uint32_t)0x70000000)) >> 28; + *clknintsrval = (localVal & ((uint32_t)0x0F000000)) >> 24; + *fifointmsk = (localVal & ((uint32_t)0x00008000)) >> 15; + *timestamptgt2intmsk = (localVal & ((uint32_t)0x00000040)) >> 6; + *timestamptgt1intmsk = (localVal & ((uint32_t)0x00000020)) >> 5; + *finetgtintmsk = (localVal & ((uint32_t)0x00000010)) >> 4; + *swintmsk = (localVal & ((uint32_t)0x00000008)) >> 3; + *cryptintmsk = (localVal & ((uint32_t)0x00000004)) >> 2; + *slpintmsk = (localVal & ((uint32_t)0x00000002)) >> 1; + *clknintmsk = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +__INLINE uint8_t ble_intcntl1_clknintsrmsk_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTCNTL1_ADDR); + return ((localVal & ((uint32_t)0x70000000)) >> 28); +} + +__INLINE void ble_intcntl1_clknintsrmsk_setf(uint8_t clknintsrmsk) +{ + BLE_ASSERT_ERR((((uint32_t)clknintsrmsk << 28) & ~((uint32_t)0x70000000)) == 0); + REG_BLE_WR(BLE_INTCNTL1_ADDR, (REG_BLE_RD(BLE_INTCNTL1_ADDR) & ~((uint32_t)0x70000000)) | ((uint32_t)clknintsrmsk << 28)); +} + +__INLINE uint8_t ble_intcntl1_clknintsrval_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTCNTL1_ADDR); + return ((localVal & ((uint32_t)0x0F000000)) >> 24); +} + +__INLINE void ble_intcntl1_clknintsrval_setf(uint8_t clknintsrval) +{ + BLE_ASSERT_ERR((((uint32_t)clknintsrval << 24) & ~((uint32_t)0x0F000000)) == 0); + REG_BLE_WR(BLE_INTCNTL1_ADDR, (REG_BLE_RD(BLE_INTCNTL1_ADDR) & ~((uint32_t)0x0F000000)) | ((uint32_t)clknintsrval << 24)); +} + +__INLINE uint8_t ble_intcntl1_fifointmsk_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTCNTL1_ADDR); + return ((localVal & ((uint32_t)0x00008000)) >> 15); +} + +__INLINE void ble_intcntl1_fifointmsk_setf(uint8_t fifointmsk) +{ + BLE_ASSERT_ERR((((uint32_t)fifointmsk << 15) & ~((uint32_t)0x00008000)) == 0); + REG_BLE_WR(BLE_INTCNTL1_ADDR, (REG_BLE_RD(BLE_INTCNTL1_ADDR) & ~((uint32_t)0x00008000)) | ((uint32_t)fifointmsk << 15)); +} + +__INLINE uint8_t ble_intcntl1_timestamptgt2intmsk_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTCNTL1_ADDR); + return ((localVal & ((uint32_t)0x00000040)) >> 6); +} + +__INLINE void ble_intcntl1_timestamptgt2intmsk_setf(uint8_t timestamptgt2intmsk) +{ + BLE_ASSERT_ERR((((uint32_t)timestamptgt2intmsk << 6) & ~((uint32_t)0x00000040)) == 0); + REG_BLE_WR(BLE_INTCNTL1_ADDR, (REG_BLE_RD(BLE_INTCNTL1_ADDR) & ~((uint32_t)0x00000040)) | ((uint32_t)timestamptgt2intmsk << 6)); +} + +__INLINE uint8_t ble_intcntl1_timestamptgt1intmsk_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTCNTL1_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +__INLINE void ble_intcntl1_timestamptgt1intmsk_setf(uint8_t timestamptgt1intmsk) +{ + BLE_ASSERT_ERR((((uint32_t)timestamptgt1intmsk << 5) & ~((uint32_t)0x00000020)) == 0); + REG_BLE_WR(BLE_INTCNTL1_ADDR, (REG_BLE_RD(BLE_INTCNTL1_ADDR) & ~((uint32_t)0x00000020)) | ((uint32_t)timestamptgt1intmsk << 5)); +} + +__INLINE uint8_t ble_intcntl1_finetgtintmsk_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTCNTL1_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +__INLINE void ble_intcntl1_finetgtintmsk_setf(uint8_t finetgtintmsk) +{ + BLE_ASSERT_ERR((((uint32_t)finetgtintmsk << 4) & ~((uint32_t)0x00000010)) == 0); + REG_BLE_WR(BLE_INTCNTL1_ADDR, (REG_BLE_RD(BLE_INTCNTL1_ADDR) & ~((uint32_t)0x00000010)) | ((uint32_t)finetgtintmsk << 4)); +} + +__INLINE uint8_t ble_intcntl1_swintmsk_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTCNTL1_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +__INLINE void ble_intcntl1_swintmsk_setf(uint8_t swintmsk) +{ + BLE_ASSERT_ERR((((uint32_t)swintmsk << 3) & ~((uint32_t)0x00000008)) == 0); + REG_BLE_WR(BLE_INTCNTL1_ADDR, (REG_BLE_RD(BLE_INTCNTL1_ADDR) & ~((uint32_t)0x00000008)) | ((uint32_t)swintmsk << 3)); +} + +__INLINE uint8_t ble_intcntl1_cryptintmsk_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTCNTL1_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +__INLINE void ble_intcntl1_cryptintmsk_setf(uint8_t cryptintmsk) +{ + BLE_ASSERT_ERR((((uint32_t)cryptintmsk << 2) & ~((uint32_t)0x00000004)) == 0); + REG_BLE_WR(BLE_INTCNTL1_ADDR, (REG_BLE_RD(BLE_INTCNTL1_ADDR) & ~((uint32_t)0x00000004)) | ((uint32_t)cryptintmsk << 2)); +} + +__INLINE uint8_t ble_intcntl1_slpintmsk_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTCNTL1_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +__INLINE void ble_intcntl1_slpintmsk_setf(uint8_t slpintmsk) +{ + BLE_ASSERT_ERR((((uint32_t)slpintmsk << 1) & ~((uint32_t)0x00000002)) == 0); + REG_BLE_WR(BLE_INTCNTL1_ADDR, (REG_BLE_RD(BLE_INTCNTL1_ADDR) & ~((uint32_t)0x00000002)) | ((uint32_t)slpintmsk << 1)); +} + +__INLINE uint8_t ble_intcntl1_clknintmsk_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTCNTL1_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +__INLINE void ble_intcntl1_clknintmsk_setf(uint8_t clknintmsk) +{ + BLE_ASSERT_ERR((((uint32_t)clknintmsk << 0) & ~((uint32_t)0x00000001)) == 0); + REG_BLE_WR(BLE_INTCNTL1_ADDR, (REG_BLE_RD(BLE_INTCNTL1_ADDR) & ~((uint32_t)0x00000001)) | ((uint32_t)clknintmsk << 0)); +} + +/** + * @brief INTSTAT1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     15          FIFOINTSTAT   0
+ *     06   TIMESTAMPTGT2INTSTAT   0
+ *     05   TIMESTAMPTGT1INTSTAT   0
+ *     04       FINETGTINTSTAT   0
+ *     03            SWINTSTAT   0
+ *     02         CRYPTINTSTAT   0
+ *     01           SLPINTSTAT   0
+ *     00          CLKNINTSTAT   0
+ * 
+ */ +#define BLE_INTSTAT1_ADDR 0x0090081C +#define BLE_INTSTAT1_OFFSET 0x0000001C +#define BLE_INTSTAT1_INDEX 0x00000007 +#define BLE_INTSTAT1_RESET 0x00000000 + +__INLINE uint32_t ble_intstat1_get(void) +{ + return REG_BLE_RD(BLE_INTSTAT1_ADDR); +} + +// field definitions +#define BLE_FIFOINTSTAT_BIT ((uint32_t)0x00008000) +#define BLE_FIFOINTSTAT_POS 15 +#define BLE_TIMESTAMPTGT2INTSTAT_BIT ((uint32_t)0x00000040) +#define BLE_TIMESTAMPTGT2INTSTAT_POS 6 +#define BLE_TIMESTAMPTGT1INTSTAT_BIT ((uint32_t)0x00000020) +#define BLE_TIMESTAMPTGT1INTSTAT_POS 5 +#define BLE_FINETGTINTSTAT_BIT ((uint32_t)0x00000010) +#define BLE_FINETGTINTSTAT_POS 4 +#define BLE_SWINTSTAT_BIT ((uint32_t)0x00000008) +#define BLE_SWINTSTAT_POS 3 +#define BLE_CRYPTINTSTAT_BIT ((uint32_t)0x00000004) +#define BLE_CRYPTINTSTAT_POS 2 +#define BLE_SLPINTSTAT_BIT ((uint32_t)0x00000002) +#define BLE_SLPINTSTAT_POS 1 +#define BLE_CLKNINTSTAT_BIT ((uint32_t)0x00000001) +#define BLE_CLKNINTSTAT_POS 0 + +#define BLE_FIFOINTSTAT_RST 0x0 +#define BLE_TIMESTAMPTGT2INTSTAT_RST 0x0 +#define BLE_TIMESTAMPTGT1INTSTAT_RST 0x0 +#define BLE_FINETGTINTSTAT_RST 0x0 +#define BLE_SWINTSTAT_RST 0x0 +#define BLE_CRYPTINTSTAT_RST 0x0 +#define BLE_SLPINTSTAT_RST 0x0 +#define BLE_CLKNINTSTAT_RST 0x0 + +__INLINE void ble_intstat1_unpack(uint8_t* fifointstat, uint8_t* timestamptgt2intstat, uint8_t* timestamptgt1intstat, uint8_t* finetgtintstat, uint8_t* swintstat, uint8_t* cryptintstat, uint8_t* slpintstat, uint8_t* clknintstat) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTSTAT1_ADDR); + + *fifointstat = (localVal & ((uint32_t)0x00008000)) >> 15; + *timestamptgt2intstat = (localVal & ((uint32_t)0x00000040)) >> 6; + *timestamptgt1intstat = (localVal & ((uint32_t)0x00000020)) >> 5; + *finetgtintstat = (localVal & ((uint32_t)0x00000010)) >> 4; + *swintstat = (localVal & ((uint32_t)0x00000008)) >> 3; + *cryptintstat = (localVal & ((uint32_t)0x00000004)) >> 2; + *slpintstat = (localVal & ((uint32_t)0x00000002)) >> 1; + *clknintstat = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +__INLINE uint8_t ble_intstat1_fifointstat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTSTAT1_ADDR); + return ((localVal & ((uint32_t)0x00008000)) >> 15); +} + +__INLINE uint8_t ble_intstat1_timestamptgt2intstat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTSTAT1_ADDR); + return ((localVal & ((uint32_t)0x00000040)) >> 6); +} + +__INLINE uint8_t ble_intstat1_timestamptgt1intstat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTSTAT1_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +__INLINE uint8_t ble_intstat1_finetgtintstat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTSTAT1_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +__INLINE uint8_t ble_intstat1_swintstat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTSTAT1_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +__INLINE uint8_t ble_intstat1_cryptintstat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTSTAT1_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +__INLINE uint8_t ble_intstat1_slpintstat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTSTAT1_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +__INLINE uint8_t ble_intstat1_clknintstat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTSTAT1_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/** + * @brief INTACK1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     15           FIFOINTACK   0
+ *     06   TIMESTAMPTGT2INTACK   0
+ *     05   TIMESTAMPTGT1INTACK   0
+ *     04        FINETGTINTACK   0
+ *     03             SWINTACK   0
+ *     02          CRYPTINTACK   0
+ *     01            SLPINTACK   0
+ *     00           CLKNINTACK   0
+ * 
+ */ +#define BLE_INTACK1_ADDR 0x00900820 +#define BLE_INTACK1_OFFSET 0x00000020 +#define BLE_INTACK1_INDEX 0x00000008 +#define BLE_INTACK1_RESET 0x00000000 + +__INLINE uint32_t ble_intack1_get(void) +{ + return REG_BLE_RD(BLE_INTACK1_ADDR); +} + +__INLINE void ble_intack1_clear(uint32_t value) +{ + REG_BLE_WR(BLE_INTACK1_ADDR, value); +} + +// field definitions +#define BLE_FIFOINTACK_BIT ((uint32_t)0x00008000) +#define BLE_FIFOINTACK_POS 15 +#define BLE_TIMESTAMPTGT2INTACK_BIT ((uint32_t)0x00000040) +#define BLE_TIMESTAMPTGT2INTACK_POS 6 +#define BLE_TIMESTAMPTGT1INTACK_BIT ((uint32_t)0x00000020) +#define BLE_TIMESTAMPTGT1INTACK_POS 5 +#define BLE_FINETGTINTACK_BIT ((uint32_t)0x00000010) +#define BLE_FINETGTINTACK_POS 4 +#define BLE_SWINTACK_BIT ((uint32_t)0x00000008) +#define BLE_SWINTACK_POS 3 +#define BLE_CRYPTINTACK_BIT ((uint32_t)0x00000004) +#define BLE_CRYPTINTACK_POS 2 +#define BLE_SLPINTACK_BIT ((uint32_t)0x00000002) +#define BLE_SLPINTACK_POS 1 +#define BLE_CLKNINTACK_BIT ((uint32_t)0x00000001) +#define BLE_CLKNINTACK_POS 0 + +#define BLE_FIFOINTACK_RST 0x0 +#define BLE_TIMESTAMPTGT2INTACK_RST 0x0 +#define BLE_TIMESTAMPTGT1INTACK_RST 0x0 +#define BLE_FINETGTINTACK_RST 0x0 +#define BLE_SWINTACK_RST 0x0 +#define BLE_CRYPTINTACK_RST 0x0 +#define BLE_SLPINTACK_RST 0x0 +#define BLE_CLKNINTACK_RST 0x0 + +__INLINE void ble_intack1_pack(uint8_t fifointack, uint8_t timestamptgt2intack, uint8_t timestamptgt1intack, uint8_t finetgtintack, uint8_t swintack, uint8_t cryptintack, uint8_t slpintack, uint8_t clknintack) +{ + BLE_ASSERT_ERR((((uint32_t)fifointack << 15) & ~((uint32_t)0x00008000)) == 0); + BLE_ASSERT_ERR((((uint32_t)timestamptgt2intack << 6) & ~((uint32_t)0x00000040)) == 0); + BLE_ASSERT_ERR((((uint32_t)timestamptgt1intack << 5) & ~((uint32_t)0x00000020)) == 0); + BLE_ASSERT_ERR((((uint32_t)finetgtintack << 4) & ~((uint32_t)0x00000010)) == 0); + BLE_ASSERT_ERR((((uint32_t)swintack << 3) & ~((uint32_t)0x00000008)) == 0); + BLE_ASSERT_ERR((((uint32_t)cryptintack << 2) & ~((uint32_t)0x00000004)) == 0); + BLE_ASSERT_ERR((((uint32_t)slpintack << 1) & ~((uint32_t)0x00000002)) == 0); + BLE_ASSERT_ERR((((uint32_t)clknintack << 0) & ~((uint32_t)0x00000001)) == 0); + REG_BLE_WR(BLE_INTACK1_ADDR, ((uint32_t)fifointack << 15) | ((uint32_t)timestamptgt2intack << 6) | ((uint32_t)timestamptgt1intack << 5) | ((uint32_t)finetgtintack << 4) | ((uint32_t)swintack << 3) | ((uint32_t)cryptintack << 2) | ((uint32_t)slpintack << 1) | ((uint32_t)clknintack << 0)); +} + +__INLINE void ble_intack1_unpack(uint8_t* fifointack, uint8_t* timestamptgt2intack, uint8_t* timestamptgt1intack, uint8_t* finetgtintack, uint8_t* swintack, uint8_t* cryptintack, uint8_t* slpintack, uint8_t* clknintack) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTACK1_ADDR); + + *fifointack = (localVal & ((uint32_t)0x00008000)) >> 15; + *timestamptgt2intack = (localVal & ((uint32_t)0x00000040)) >> 6; + *timestamptgt1intack = (localVal & ((uint32_t)0x00000020)) >> 5; + *finetgtintack = (localVal & ((uint32_t)0x00000010)) >> 4; + *swintack = (localVal & ((uint32_t)0x00000008)) >> 3; + *cryptintack = (localVal & ((uint32_t)0x00000004)) >> 2; + *slpintack = (localVal & ((uint32_t)0x00000002)) >> 1; + *clknintack = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +__INLINE uint8_t ble_intack1_fifointack_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTACK1_ADDR); + return ((localVal & ((uint32_t)0x00008000)) >> 15); +} + +__INLINE void ble_intack1_fifointack_clearf(uint8_t fifointack) +{ + BLE_ASSERT_ERR((((uint32_t)fifointack << 15) & ~((uint32_t)0x00008000)) == 0); + REG_BLE_WR(BLE_INTACK1_ADDR, (uint32_t)fifointack << 15); +} + +__INLINE uint8_t ble_intack1_timestamptgt2intack_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTACK1_ADDR); + return ((localVal & ((uint32_t)0x00000040)) >> 6); +} + +__INLINE void ble_intack1_timestamptgt2intack_clearf(uint8_t timestamptgt2intack) +{ + BLE_ASSERT_ERR((((uint32_t)timestamptgt2intack << 6) & ~((uint32_t)0x00000040)) == 0); + REG_BLE_WR(BLE_INTACK1_ADDR, (uint32_t)timestamptgt2intack << 6); +} + +__INLINE uint8_t ble_intack1_timestamptgt1intack_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTACK1_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +__INLINE void ble_intack1_timestamptgt1intack_clearf(uint8_t timestamptgt1intack) +{ + BLE_ASSERT_ERR((((uint32_t)timestamptgt1intack << 5) & ~((uint32_t)0x00000020)) == 0); + REG_BLE_WR(BLE_INTACK1_ADDR, (uint32_t)timestamptgt1intack << 5); +} + +__INLINE uint8_t ble_intack1_finetgtintack_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTACK1_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +__INLINE void ble_intack1_finetgtintack_clearf(uint8_t finetgtintack) +{ + BLE_ASSERT_ERR((((uint32_t)finetgtintack << 4) & ~((uint32_t)0x00000010)) == 0); + REG_BLE_WR(BLE_INTACK1_ADDR, (uint32_t)finetgtintack << 4); +} + +__INLINE uint8_t ble_intack1_swintack_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTACK1_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +__INLINE void ble_intack1_swintack_clearf(uint8_t swintack) +{ + BLE_ASSERT_ERR((((uint32_t)swintack << 3) & ~((uint32_t)0x00000008)) == 0); + REG_BLE_WR(BLE_INTACK1_ADDR, (uint32_t)swintack << 3); +} + +__INLINE uint8_t ble_intack1_cryptintack_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTACK1_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +__INLINE void ble_intack1_cryptintack_clearf(uint8_t cryptintack) +{ + BLE_ASSERT_ERR((((uint32_t)cryptintack << 2) & ~((uint32_t)0x00000004)) == 0); + REG_BLE_WR(BLE_INTACK1_ADDR, (uint32_t)cryptintack << 2); +} + +__INLINE uint8_t ble_intack1_slpintack_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTACK1_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +__INLINE void ble_intack1_slpintack_clearf(uint8_t slpintack) +{ + BLE_ASSERT_ERR((((uint32_t)slpintack << 1) & ~((uint32_t)0x00000002)) == 0); + REG_BLE_WR(BLE_INTACK1_ADDR, (uint32_t)slpintack << 1); +} + +__INLINE uint8_t ble_intack1_clknintack_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_INTACK1_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +__INLINE void ble_intack1_clknintack_clearf(uint8_t clknintack) +{ + BLE_ASSERT_ERR((((uint32_t)clknintack << 0) & ~((uint32_t)0x00000001)) == 0); + REG_BLE_WR(BLE_INTACK1_ADDR, (uint32_t)clknintack << 0); +} + +/** + * @brief ACTFIFOSTAT register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:28          SKIP_ET_IDX   0x0
+ *  27:24       CURRENT_ET_IDX   0x0
+ *     15              ACTFLAG   0
+ *     06         ISORXINTSTAT   0
+ *     05         ISOTXINTSTAT   0
+ *     04            RXINTSTAT   0
+ *     03            TXINTSTAT   0
+ *     02       SKIPACTINTSTAT   0
+ *     01        ENDACTINTSTAT   0
+ *     00      STARTACTINTSTAT   0
+ * 
+ */ +#define BLE_ACTFIFOSTAT_ADDR 0x00900824 +#define BLE_ACTFIFOSTAT_OFFSET 0x00000024 +#define BLE_ACTFIFOSTAT_INDEX 0x00000009 +#define BLE_ACTFIFOSTAT_RESET 0x00000000 + +__INLINE uint32_t ble_actfifostat_get(void) +{ + return REG_BLE_RD(BLE_ACTFIFOSTAT_ADDR); +} + +// field definitions +#define BLE_SKIP_ET_IDX_MASK ((uint32_t)0xF0000000) +#define BLE_SKIP_ET_IDX_LSB 28 +#define BLE_SKIP_ET_IDX_WIDTH ((uint32_t)0x00000004) +#define BLE_CURRENT_ET_IDX_MASK ((uint32_t)0x0F000000) +#define BLE_CURRENT_ET_IDX_LSB 24 +#define BLE_CURRENT_ET_IDX_WIDTH ((uint32_t)0x00000004) +#define BLE_ACTFLAG_BIT ((uint32_t)0x00008000) +#define BLE_ACTFLAG_POS 15 +#define BLE_ISORXINTSTAT_BIT ((uint32_t)0x00000040) +#define BLE_ISORXINTSTAT_POS 6 +#define BLE_ISOTXINTSTAT_BIT ((uint32_t)0x00000020) +#define BLE_ISOTXINTSTAT_POS 5 +#define BLE_RXINTSTAT_BIT ((uint32_t)0x00000010) +#define BLE_RXINTSTAT_POS 4 +#define BLE_TXINTSTAT_BIT ((uint32_t)0x00000008) +#define BLE_TXINTSTAT_POS 3 +#define BLE_SKIPACTINTSTAT_BIT ((uint32_t)0x00000004) +#define BLE_SKIPACTINTSTAT_POS 2 +#define BLE_ENDACTINTSTAT_BIT ((uint32_t)0x00000002) +#define BLE_ENDACTINTSTAT_POS 1 +#define BLE_STARTACTINTSTAT_BIT ((uint32_t)0x00000001) +#define BLE_STARTACTINTSTAT_POS 0 + +#define BLE_SKIP_ET_IDX_RST 0x0 +#define BLE_CURRENT_ET_IDX_RST 0x0 +#define BLE_ACTFLAG_RST 0x0 +#define BLE_ISORXINTSTAT_RST 0x0 +#define BLE_ISOTXINTSTAT_RST 0x0 +#define BLE_RXINTSTAT_RST 0x0 +#define BLE_TXINTSTAT_RST 0x0 +#define BLE_SKIPACTINTSTAT_RST 0x0 +#define BLE_ENDACTINTSTAT_RST 0x0 +#define BLE_STARTACTINTSTAT_RST 0x0 + +__INLINE void ble_actfifostat_unpack(uint8_t* skipetidx, uint8_t* currentetidx, uint8_t* actflag, uint8_t* isorxintstat, uint8_t* isotxintstat, uint8_t* rxintstat, uint8_t* txintstat, uint8_t* skipactintstat, uint8_t* endactintstat, uint8_t* startactintstat) +{ + uint32_t localVal = REG_BLE_RD(BLE_ACTFIFOSTAT_ADDR); + + *skipetidx = (localVal & ((uint32_t)0xF0000000)) >> 28; + *currentetidx = (localVal & ((uint32_t)0x0F000000)) >> 24; + *actflag = (localVal & ((uint32_t)0x00008000)) >> 15; + *isorxintstat = (localVal & ((uint32_t)0x00000040)) >> 6; + *isotxintstat = (localVal & ((uint32_t)0x00000020)) >> 5; + *rxintstat = (localVal & ((uint32_t)0x00000010)) >> 4; + *txintstat = (localVal & ((uint32_t)0x00000008)) >> 3; + *skipactintstat = (localVal & ((uint32_t)0x00000004)) >> 2; + *endactintstat = (localVal & ((uint32_t)0x00000002)) >> 1; + *startactintstat = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +__INLINE uint8_t ble_actfifostat_skip_et_idx_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ACTFIFOSTAT_ADDR); + return ((localVal & ((uint32_t)0xF0000000)) >> 28); +} + +__INLINE uint8_t ble_actfifostat_current_et_idx_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ACTFIFOSTAT_ADDR); + return ((localVal & ((uint32_t)0x0F000000)) >> 24); +} + +__INLINE uint8_t ble_actfifostat_actflag_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ACTFIFOSTAT_ADDR); + return ((localVal & ((uint32_t)0x00008000)) >> 15); +} + +__INLINE uint8_t ble_actfifostat_isorxintstat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ACTFIFOSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000040)) >> 6); +} + +__INLINE uint8_t ble_actfifostat_isotxintstat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ACTFIFOSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +__INLINE uint8_t ble_actfifostat_rxintstat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ACTFIFOSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +__INLINE uint8_t ble_actfifostat_txintstat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ACTFIFOSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +__INLINE uint8_t ble_actfifostat_skipactintstat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ACTFIFOSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +__INLINE uint8_t ble_actfifostat_endactintstat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ACTFIFOSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +__INLINE uint8_t ble_actfifostat_startactintstat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ACTFIFOSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/** + * @brief CURRENTRXDESCPTR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  13:00     CURRENTRXDESCPTR   0x0
+ * 
+ */ +#define BLE_CURRENTRXDESCPTR_ADDR 0x00900828 +#define BLE_CURRENTRXDESCPTR_OFFSET 0x00000028 +#define BLE_CURRENTRXDESCPTR_INDEX 0x0000000A +#define BLE_CURRENTRXDESCPTR_RESET 0x00000000 + +__INLINE uint32_t ble_currentrxdescptr_get(void) +{ + return REG_BLE_RD(BLE_CURRENTRXDESCPTR_ADDR); +} + +__INLINE void ble_currentrxdescptr_set(uint32_t value) +{ + REG_BLE_WR(BLE_CURRENTRXDESCPTR_ADDR, value); +} + +// field definitions +#define BLE_CURRENTRXDESCPTR_MASK ((uint32_t)0x00003FFF) +#define BLE_CURRENTRXDESCPTR_LSB 0 +#define BLE_CURRENTRXDESCPTR_WIDTH ((uint32_t)0x0000000E) + +#define BLE_CURRENTRXDESCPTR_RST 0x0 + +__INLINE uint16_t ble_currentrxdescptr_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_CURRENTRXDESCPTR_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0x00003FFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_currentrxdescptr_setf(uint16_t currentrxdescptr) +{ + BLE_ASSERT_ERR((((uint32_t)currentrxdescptr << 0) & ~((uint32_t)0x00003FFF)) == 0); + REG_BLE_WR(BLE_CURRENTRXDESCPTR_ADDR, (uint32_t)currentrxdescptr << 0); +} + +/** + * @brief ETPTR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  13:00                ETPTR   0x0
+ * 
+ */ +#define BLE_ETPTR_ADDR 0x0090082C +#define BLE_ETPTR_OFFSET 0x0000002C +#define BLE_ETPTR_INDEX 0x0000000B +#define BLE_ETPTR_RESET 0x00000000 + +__INLINE uint32_t ble_etptr_get(void) +{ + return REG_BLE_RD(BLE_ETPTR_ADDR); +} + +__INLINE void ble_etptr_set(uint32_t value) +{ + REG_BLE_WR(BLE_ETPTR_ADDR, value); +} + +// field definitions +#define BLE_ETPTR_MASK ((uint32_t)0x00003FFF) +#define BLE_ETPTR_LSB 0 +#define BLE_ETPTR_WIDTH ((uint32_t)0x0000000E) + +#define BLE_ETPTR_RST 0x0 + +__INLINE uint16_t ble_etptr_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ETPTR_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0x00003FFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_etptr_setf(uint16_t etptr) +{ + BLE_ASSERT_ERR((((uint32_t)etptr << 0) & ~((uint32_t)0x00003FFF)) == 0); + REG_BLE_WR(BLE_ETPTR_ADDR, (uint32_t)etptr << 0); +} + +/** + * @brief DEEPSLCNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31           EXTWKUPDSB   0
+ *     15      DEEP_SLEEP_STAT   0
+ *     03   DEEP_SLEEP_CORR_EN   0
+ *     02        DEEP_SLEEP_ON   0
+ *     01       RADIO_SLEEP_EN   0
+ *     00         OSC_SLEEP_EN   0
+ * 
+ */ +#define BLE_DEEPSLCNTL_ADDR 0x00900830 +#define BLE_DEEPSLCNTL_OFFSET 0x00000030 +#define BLE_DEEPSLCNTL_INDEX 0x0000000C +#define BLE_DEEPSLCNTL_RESET 0x00000000 + +__INLINE uint32_t ble_deepslcntl_get(void) +{ + return REG_BLE_RD(BLE_DEEPSLCNTL_ADDR); +} + +__INLINE void ble_deepslcntl_set(uint32_t value) +{ + REG_BLE_WR(BLE_DEEPSLCNTL_ADDR, value); +} + +// field definitions +#define BLE_EXTWKUPDSB_BIT ((uint32_t)0x80000000) +#define BLE_EXTWKUPDSB_POS 31 +#define BLE_DEEP_SLEEP_STAT_BIT ((uint32_t)0x00008000) +#define BLE_DEEP_SLEEP_STAT_POS 15 +#define BLE_DEEP_SLEEP_CORR_EN_BIT ((uint32_t)0x00000008) +#define BLE_DEEP_SLEEP_CORR_EN_POS 3 +#define BLE_DEEP_SLEEP_ON_BIT ((uint32_t)0x00000004) +#define BLE_DEEP_SLEEP_ON_POS 2 +#define BLE_RADIO_SLEEP_EN_BIT ((uint32_t)0x00000002) +#define BLE_RADIO_SLEEP_EN_POS 1 +#define BLE_OSC_SLEEP_EN_BIT ((uint32_t)0x00000001) +#define BLE_OSC_SLEEP_EN_POS 0 + +#define BLE_EXTWKUPDSB_RST 0x0 +#define BLE_DEEP_SLEEP_STAT_RST 0x0 +#define BLE_DEEP_SLEEP_CORR_EN_RST 0x0 +#define BLE_DEEP_SLEEP_ON_RST 0x0 +#define BLE_RADIO_SLEEP_EN_RST 0x0 +#define BLE_OSC_SLEEP_EN_RST 0x0 + +__INLINE void ble_deepslcntl_pack(uint8_t extwkupdsb, uint8_t deepsleepcorren, uint8_t deepsleepon, uint8_t radiosleepen, uint8_t oscsleepen) +{ + BLE_ASSERT_ERR((((uint32_t)extwkupdsb << 31) & ~((uint32_t)0x80000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)deepsleepcorren << 3) & ~((uint32_t)0x00000008)) == 0); + BLE_ASSERT_ERR((((uint32_t)deepsleepon << 2) & ~((uint32_t)0x00000004)) == 0); + BLE_ASSERT_ERR((((uint32_t)radiosleepen << 1) & ~((uint32_t)0x00000002)) == 0); + BLE_ASSERT_ERR((((uint32_t)oscsleepen << 0) & ~((uint32_t)0x00000001)) == 0); + REG_BLE_WR(BLE_DEEPSLCNTL_ADDR, ((uint32_t)extwkupdsb << 31) | ((uint32_t)deepsleepcorren << 3) | ((uint32_t)deepsleepon << 2) | ((uint32_t)radiosleepen << 1) | ((uint32_t)oscsleepen << 0)); +} + +__INLINE void ble_deepslcntl_unpack(uint8_t* extwkupdsb, uint8_t* deepsleepstat, uint8_t* deepsleepcorren, uint8_t* deepsleepon, uint8_t* radiosleepen, uint8_t* oscsleepen) +{ + uint32_t localVal = REG_BLE_RD(BLE_DEEPSLCNTL_ADDR); + + *extwkupdsb = (localVal & ((uint32_t)0x80000000)) >> 31; + *deepsleepstat = (localVal & ((uint32_t)0x00008000)) >> 15; + *deepsleepcorren = (localVal & ((uint32_t)0x00000008)) >> 3; + *deepsleepon = (localVal & ((uint32_t)0x00000004)) >> 2; + *radiosleepen = (localVal & ((uint32_t)0x00000002)) >> 1; + *oscsleepen = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +__INLINE uint8_t ble_deepslcntl_extwkupdsb_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DEEPSLCNTL_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +__INLINE void ble_deepslcntl_extwkupdsb_setf(uint8_t extwkupdsb) +{ + BLE_ASSERT_ERR((((uint32_t)extwkupdsb << 31) & ~((uint32_t)0x80000000)) == 0); + REG_BLE_WR(BLE_DEEPSLCNTL_ADDR, (REG_BLE_RD(BLE_DEEPSLCNTL_ADDR) & ~((uint32_t)0x80000000)) | ((uint32_t)extwkupdsb << 31)); +} + +__INLINE uint8_t ble_deepslcntl_deep_sleep_stat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DEEPSLCNTL_ADDR); + return ((localVal & ((uint32_t)0x00008000)) >> 15); +} + +__INLINE uint8_t ble_deepslcntl_deep_sleep_corr_en_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DEEPSLCNTL_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +__INLINE void ble_deepslcntl_deep_sleep_corr_en_setf(uint8_t deepsleepcorren) +{ + BLE_ASSERT_ERR((((uint32_t)deepsleepcorren << 3) & ~((uint32_t)0x00000008)) == 0); + REG_BLE_WR(BLE_DEEPSLCNTL_ADDR, (REG_BLE_RD(BLE_DEEPSLCNTL_ADDR) & ~((uint32_t)0x00000008)) | ((uint32_t)deepsleepcorren << 3)); +} + +__INLINE uint8_t ble_deepslcntl_deep_sleep_on_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DEEPSLCNTL_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +__INLINE void ble_deepslcntl_deep_sleep_on_setf(uint8_t deepsleepon) +{ + BLE_ASSERT_ERR((((uint32_t)deepsleepon << 2) & ~((uint32_t)0x00000004)) == 0); + REG_BLE_WR(BLE_DEEPSLCNTL_ADDR, (REG_BLE_RD(BLE_DEEPSLCNTL_ADDR) & ~((uint32_t)0x00000004)) | ((uint32_t)deepsleepon << 2)); +} + +__INLINE uint8_t ble_deepslcntl_radio_sleep_en_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DEEPSLCNTL_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +__INLINE void ble_deepslcntl_radio_sleep_en_setf(uint8_t radiosleepen) +{ + BLE_ASSERT_ERR((((uint32_t)radiosleepen << 1) & ~((uint32_t)0x00000002)) == 0); + REG_BLE_WR(BLE_DEEPSLCNTL_ADDR, (REG_BLE_RD(BLE_DEEPSLCNTL_ADDR) & ~((uint32_t)0x00000002)) | ((uint32_t)radiosleepen << 1)); +} + +__INLINE uint8_t ble_deepslcntl_osc_sleep_en_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DEEPSLCNTL_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +__INLINE void ble_deepslcntl_osc_sleep_en_setf(uint8_t oscsleepen) +{ + BLE_ASSERT_ERR((((uint32_t)oscsleepen << 0) & ~((uint32_t)0x00000001)) == 0); + REG_BLE_WR(BLE_DEEPSLCNTL_ADDR, (REG_BLE_RD(BLE_DEEPSLCNTL_ADDR) & ~((uint32_t)0x00000001)) | ((uint32_t)oscsleepen << 0)); +} + +/** + * @brief DEEPSLWKUP register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00           DEEPSLTIME   0x0
+ * 
+ */ +#define BLE_DEEPSLWKUP_ADDR 0x00900834 +#define BLE_DEEPSLWKUP_OFFSET 0x00000034 +#define BLE_DEEPSLWKUP_INDEX 0x0000000D +#define BLE_DEEPSLWKUP_RESET 0x00000000 + +__INLINE uint32_t ble_deepslwkup_get(void) +{ + return REG_BLE_RD(BLE_DEEPSLWKUP_ADDR); +} + +__INLINE void ble_deepslwkup_set(uint32_t value) +{ + REG_BLE_WR(BLE_DEEPSLWKUP_ADDR, value); +} + +// field definitions +#define BLE_DEEPSLTIME_MASK ((uint32_t)0xFFFFFFFF) +#define BLE_DEEPSLTIME_LSB 0 +#define BLE_DEEPSLTIME_WIDTH ((uint32_t)0x00000020) + +#define BLE_DEEPSLTIME_RST 0x0 + +__INLINE uint32_t ble_deepslwkup_deepsltime_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DEEPSLWKUP_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_deepslwkup_deepsltime_setf(uint32_t deepsltime) +{ + BLE_ASSERT_ERR((((uint32_t)deepsltime << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_BLE_WR(BLE_DEEPSLWKUP_ADDR, (uint32_t)deepsltime << 0); +} + +/** + * @brief DEEPSLSTAT register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00            DEEPSLDUR   0x0
+ * 
+ */ +#define BLE_DEEPSLSTAT_ADDR 0x00900838 +#define BLE_DEEPSLSTAT_OFFSET 0x00000038 +#define BLE_DEEPSLSTAT_INDEX 0x0000000E +#define BLE_DEEPSLSTAT_RESET 0x00000000 + +__INLINE uint32_t ble_deepslstat_get(void) +{ + return REG_BLE_RD(BLE_DEEPSLSTAT_ADDR); +} + +// field definitions +#define BLE_DEEPSLDUR_MASK ((uint32_t)0xFFFFFFFF) +#define BLE_DEEPSLDUR_LSB 0 +#define BLE_DEEPSLDUR_WIDTH ((uint32_t)0x00000020) + +#define BLE_DEEPSLDUR_RST 0x0 + +__INLINE uint32_t ble_deepslstat_deepsldur_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DEEPSLSTAT_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief ENBPRESET register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:21                TWEXT   0x0
+ *  20:10                TWOSC   0x0
+ *  09:00                 TWRM   0x0
+ * 
+ */ +#define BLE_ENBPRESET_ADDR 0x0090083C +#define BLE_ENBPRESET_OFFSET 0x0000003C +#define BLE_ENBPRESET_INDEX 0x0000000F +#define BLE_ENBPRESET_RESET 0x00000000 + +__INLINE uint32_t ble_enbpreset_get(void) +{ + return REG_BLE_RD(BLE_ENBPRESET_ADDR); +} + +__INLINE void ble_enbpreset_set(uint32_t value) +{ + REG_BLE_WR(BLE_ENBPRESET_ADDR, value); +} + +// field definitions +#define BLE_TWEXT_MASK ((uint32_t)0xFFE00000) +#define BLE_TWEXT_LSB 21 +#define BLE_TWEXT_WIDTH ((uint32_t)0x0000000B) +#define BLE_TWOSC_MASK ((uint32_t)0x001FFC00) +#define BLE_TWOSC_LSB 10 +#define BLE_TWOSC_WIDTH ((uint32_t)0x0000000B) +#define BLE_TWRM_MASK ((uint32_t)0x000003FF) +#define BLE_TWRM_LSB 0 +#define BLE_TWRM_WIDTH ((uint32_t)0x0000000A) + +#define BLE_TWEXT_RST 0x0 +#define BLE_TWOSC_RST 0x0 +#define BLE_TWRM_RST 0x0 + +__INLINE void ble_enbpreset_pack(uint16_t twext, uint16_t twosc, uint16_t twrm) +{ + BLE_ASSERT_ERR((((uint32_t)twext << 21) & ~((uint32_t)0xFFE00000)) == 0); + BLE_ASSERT_ERR((((uint32_t)twosc << 10) & ~((uint32_t)0x001FFC00)) == 0); + BLE_ASSERT_ERR((((uint32_t)twrm << 0) & ~((uint32_t)0x000003FF)) == 0); + REG_BLE_WR(BLE_ENBPRESET_ADDR, ((uint32_t)twext << 21) | ((uint32_t)twosc << 10) | ((uint32_t)twrm << 0)); +} + +__INLINE void ble_enbpreset_unpack(uint16_t* twext, uint16_t* twosc, uint16_t* twrm) +{ + uint32_t localVal = REG_BLE_RD(BLE_ENBPRESET_ADDR); + + *twext = (localVal & ((uint32_t)0xFFE00000)) >> 21; + *twosc = (localVal & ((uint32_t)0x001FFC00)) >> 10; + *twrm = (localVal & ((uint32_t)0x000003FF)) >> 0; +} + +__INLINE uint16_t ble_enbpreset_twext_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ENBPRESET_ADDR); + return ((localVal & ((uint32_t)0xFFE00000)) >> 21); +} + +__INLINE void ble_enbpreset_twext_setf(uint16_t twext) +{ + BLE_ASSERT_ERR((((uint32_t)twext << 21) & ~((uint32_t)0xFFE00000)) == 0); + REG_BLE_WR(BLE_ENBPRESET_ADDR, (REG_BLE_RD(BLE_ENBPRESET_ADDR) & ~((uint32_t)0xFFE00000)) | ((uint32_t)twext << 21)); +} + +__INLINE uint16_t ble_enbpreset_twosc_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ENBPRESET_ADDR); + return ((localVal & ((uint32_t)0x001FFC00)) >> 10); +} + +__INLINE void ble_enbpreset_twosc_setf(uint16_t twosc) +{ + BLE_ASSERT_ERR((((uint32_t)twosc << 10) & ~((uint32_t)0x001FFC00)) == 0); + REG_BLE_WR(BLE_ENBPRESET_ADDR, (REG_BLE_RD(BLE_ENBPRESET_ADDR) & ~((uint32_t)0x001FFC00)) | ((uint32_t)twosc << 10)); +} + +__INLINE uint16_t ble_enbpreset_twrm_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ENBPRESET_ADDR); + return ((localVal & ((uint32_t)0x000003FF)) >> 0); +} + +__INLINE void ble_enbpreset_twrm_setf(uint16_t twrm) +{ + BLE_ASSERT_ERR((((uint32_t)twrm << 0) & ~((uint32_t)0x000003FF)) == 0); + REG_BLE_WR(BLE_ENBPRESET_ADDR, (REG_BLE_RD(BLE_ENBPRESET_ADDR) & ~((uint32_t)0x000003FF)) | ((uint32_t)twrm << 0)); +} + +/** + * @brief FINECNTCORR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  09:00          FINECNTCORR   0x0
+ * 
+ */ +#define BLE_FINECNTCORR_ADDR 0x00900840 +#define BLE_FINECNTCORR_OFFSET 0x00000040 +#define BLE_FINECNTCORR_INDEX 0x00000010 +#define BLE_FINECNTCORR_RESET 0x00000000 + +__INLINE uint32_t ble_finecntcorr_get(void) +{ + return REG_BLE_RD(BLE_FINECNTCORR_ADDR); +} + +__INLINE void ble_finecntcorr_set(uint32_t value) +{ + REG_BLE_WR(BLE_FINECNTCORR_ADDR, value); +} + +// field definitions +#define BLE_FINECNTCORR_MASK ((uint32_t)0x000003FF) +#define BLE_FINECNTCORR_LSB 0 +#define BLE_FINECNTCORR_WIDTH ((uint32_t)0x0000000A) + +#define BLE_FINECNTCORR_RST 0x0 + +__INLINE uint16_t ble_finecntcorr_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_FINECNTCORR_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0x000003FF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_finecntcorr_setf(uint16_t finecntcorr) +{ + BLE_ASSERT_ERR((((uint32_t)finecntcorr << 0) & ~((uint32_t)0x000003FF)) == 0); + REG_BLE_WR(BLE_FINECNTCORR_ADDR, (uint32_t)finecntcorr << 0); +} + +/** + * @brief CLKNCNTCORR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31            ABS_DELTA   0
+ *  27:00          CLKNCNTCORR   0x0
+ * 
+ */ +#define BLE_CLKNCNTCORR_ADDR 0x00900844 +#define BLE_CLKNCNTCORR_OFFSET 0x00000044 +#define BLE_CLKNCNTCORR_INDEX 0x00000011 +#define BLE_CLKNCNTCORR_RESET 0x00000000 + +__INLINE uint32_t ble_clkncntcorr_get(void) +{ + return REG_BLE_RD(BLE_CLKNCNTCORR_ADDR); +} + +__INLINE void ble_clkncntcorr_set(uint32_t value) +{ + REG_BLE_WR(BLE_CLKNCNTCORR_ADDR, value); +} + +// field definitions +#define BLE_ABS_DELTA_BIT ((uint32_t)0x80000000) +#define BLE_ABS_DELTA_POS 31 +#define BLE_CLKNCNTCORR_MASK ((uint32_t)0x0FFFFFFF) +#define BLE_CLKNCNTCORR_LSB 0 +#define BLE_CLKNCNTCORR_WIDTH ((uint32_t)0x0000001C) + +#define BLE_ABS_DELTA_RST 0x0 +#define BLE_CLKNCNTCORR_RST 0x0 + +__INLINE void ble_clkncntcorr_pack(uint8_t absdelta, uint32_t clkncntcorr) +{ + BLE_ASSERT_ERR((((uint32_t)absdelta << 31) & ~((uint32_t)0x80000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)clkncntcorr << 0) & ~((uint32_t)0x0FFFFFFF)) == 0); + REG_BLE_WR(BLE_CLKNCNTCORR_ADDR, ((uint32_t)absdelta << 31) | ((uint32_t)clkncntcorr << 0)); +} + +__INLINE void ble_clkncntcorr_unpack(uint8_t* absdelta, uint32_t* clkncntcorr) +{ + uint32_t localVal = REG_BLE_RD(BLE_CLKNCNTCORR_ADDR); + + *absdelta = (localVal & ((uint32_t)0x80000000)) >> 31; + *clkncntcorr = (localVal & ((uint32_t)0x0FFFFFFF)) >> 0; +} + +__INLINE uint8_t ble_clkncntcorr_abs_delta_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_CLKNCNTCORR_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +__INLINE void ble_clkncntcorr_abs_delta_setf(uint8_t absdelta) +{ + BLE_ASSERT_ERR((((uint32_t)absdelta << 31) & ~((uint32_t)0x80000000)) == 0); + REG_BLE_WR(BLE_CLKNCNTCORR_ADDR, (REG_BLE_RD(BLE_CLKNCNTCORR_ADDR) & ~((uint32_t)0x80000000)) | ((uint32_t)absdelta << 31)); +} + +__INLINE uint32_t ble_clkncntcorr_clkncntcorr_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_CLKNCNTCORR_ADDR); + return ((localVal & ((uint32_t)0x0FFFFFFF)) >> 0); +} + +__INLINE void ble_clkncntcorr_clkncntcorr_setf(uint32_t clkncntcorr) +{ + BLE_ASSERT_ERR((((uint32_t)clkncntcorr << 0) & ~((uint32_t)0x0FFFFFFF)) == 0); + REG_BLE_WR(BLE_CLKNCNTCORR_ADDR, (REG_BLE_RD(BLE_CLKNCNTCORR_ADDR) & ~((uint32_t)0x0FFFFFFF)) | ((uint32_t)clkncntcorr << 0)); +} + +/** + * @brief DIAGCNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31             DIAG3_EN   0
+ *  30:24                DIAG3   0x0
+ *     23             DIAG2_EN   0
+ *  22:16                DIAG2   0x0
+ *     15             DIAG1_EN   0
+ *  14:08                DIAG1   0x0
+ *     07             DIAG0_EN   0
+ *  06:00                DIAG0   0x0
+ * 
+ */ +#define BLE_DIAGCNTL_ADDR 0x00900850 +#define BLE_DIAGCNTL_OFFSET 0x00000050 +#define BLE_DIAGCNTL_INDEX 0x00000014 +#define BLE_DIAGCNTL_RESET 0x00000000 + +__INLINE uint32_t ble_diagcntl_get(void) +{ + return REG_BLE_RD(BLE_DIAGCNTL_ADDR); +} + +__INLINE void ble_diagcntl_set(uint32_t value) +{ + REG_BLE_WR(BLE_DIAGCNTL_ADDR, value); +} + +// field definitions +#define BLE_DIAG3_EN_BIT ((uint32_t)0x80000000) +#define BLE_DIAG3_EN_POS 31 +#define BLE_DIAG3_MASK ((uint32_t)0x7F000000) +#define BLE_DIAG3_LSB 24 +#define BLE_DIAG3_WIDTH ((uint32_t)0x00000007) +#define BLE_DIAG2_EN_BIT ((uint32_t)0x00800000) +#define BLE_DIAG2_EN_POS 23 +#define BLE_DIAG2_MASK ((uint32_t)0x007F0000) +#define BLE_DIAG2_LSB 16 +#define BLE_DIAG2_WIDTH ((uint32_t)0x00000007) +#define BLE_DIAG1_EN_BIT ((uint32_t)0x00008000) +#define BLE_DIAG1_EN_POS 15 +#define BLE_DIAG1_MASK ((uint32_t)0x00007F00) +#define BLE_DIAG1_LSB 8 +#define BLE_DIAG1_WIDTH ((uint32_t)0x00000007) +#define BLE_DIAG0_EN_BIT ((uint32_t)0x00000080) +#define BLE_DIAG0_EN_POS 7 +#define BLE_DIAG0_MASK ((uint32_t)0x0000007F) +#define BLE_DIAG0_LSB 0 +#define BLE_DIAG0_WIDTH ((uint32_t)0x00000007) + +#define BLE_DIAG3_EN_RST 0x0 +#define BLE_DIAG3_RST 0x0 +#define BLE_DIAG2_EN_RST 0x0 +#define BLE_DIAG2_RST 0x0 +#define BLE_DIAG1_EN_RST 0x0 +#define BLE_DIAG1_RST 0x0 +#define BLE_DIAG0_EN_RST 0x0 +#define BLE_DIAG0_RST 0x0 + +__INLINE void ble_diagcntl_pack(uint8_t diag3en, uint8_t diag3, uint8_t diag2en, uint8_t diag2, uint8_t diag1en, uint8_t diag1, uint8_t diag0en, uint8_t diag0) +{ + BLE_ASSERT_ERR((((uint32_t)diag3en << 31) & ~((uint32_t)0x80000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)diag3 << 24) & ~((uint32_t)0x7F000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)diag2en << 23) & ~((uint32_t)0x00800000)) == 0); + BLE_ASSERT_ERR((((uint32_t)diag2 << 16) & ~((uint32_t)0x007F0000)) == 0); + BLE_ASSERT_ERR((((uint32_t)diag1en << 15) & ~((uint32_t)0x00008000)) == 0); + BLE_ASSERT_ERR((((uint32_t)diag1 << 8) & ~((uint32_t)0x00007F00)) == 0); + BLE_ASSERT_ERR((((uint32_t)diag0en << 7) & ~((uint32_t)0x00000080)) == 0); + BLE_ASSERT_ERR((((uint32_t)diag0 << 0) & ~((uint32_t)0x0000007F)) == 0); + REG_BLE_WR(BLE_DIAGCNTL_ADDR, ((uint32_t)diag3en << 31) | ((uint32_t)diag3 << 24) | ((uint32_t)diag2en << 23) | ((uint32_t)diag2 << 16) | ((uint32_t)diag1en << 15) | ((uint32_t)diag1 << 8) | ((uint32_t)diag0en << 7) | ((uint32_t)diag0 << 0)); +} + +__INLINE void ble_diagcntl_unpack(uint8_t* diag3en, uint8_t* diag3, uint8_t* diag2en, uint8_t* diag2, uint8_t* diag1en, uint8_t* diag1, uint8_t* diag0en, uint8_t* diag0) +{ + uint32_t localVal = REG_BLE_RD(BLE_DIAGCNTL_ADDR); + + *diag3en = (localVal & ((uint32_t)0x80000000)) >> 31; + *diag3 = (localVal & ((uint32_t)0x7F000000)) >> 24; + *diag2en = (localVal & ((uint32_t)0x00800000)) >> 23; + *diag2 = (localVal & ((uint32_t)0x007F0000)) >> 16; + *diag1en = (localVal & ((uint32_t)0x00008000)) >> 15; + *diag1 = (localVal & ((uint32_t)0x00007F00)) >> 8; + *diag0en = (localVal & ((uint32_t)0x00000080)) >> 7; + *diag0 = (localVal & ((uint32_t)0x0000007F)) >> 0; +} + +__INLINE uint8_t ble_diagcntl_diag3_en_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DIAGCNTL_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +__INLINE void ble_diagcntl_diag3_en_setf(uint8_t diag3en) +{ + BLE_ASSERT_ERR((((uint32_t)diag3en << 31) & ~((uint32_t)0x80000000)) == 0); + REG_BLE_WR(BLE_DIAGCNTL_ADDR, (REG_BLE_RD(BLE_DIAGCNTL_ADDR) & ~((uint32_t)0x80000000)) | ((uint32_t)diag3en << 31)); +} + +__INLINE uint8_t ble_diagcntl_diag3_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DIAGCNTL_ADDR); + return ((localVal & ((uint32_t)0x7F000000)) >> 24); +} + +__INLINE void ble_diagcntl_diag3_setf(uint8_t diag3) +{ + BLE_ASSERT_ERR((((uint32_t)diag3 << 24) & ~((uint32_t)0x7F000000)) == 0); + REG_BLE_WR(BLE_DIAGCNTL_ADDR, (REG_BLE_RD(BLE_DIAGCNTL_ADDR) & ~((uint32_t)0x7F000000)) | ((uint32_t)diag3 << 24)); +} + +__INLINE uint8_t ble_diagcntl_diag2_en_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DIAGCNTL_ADDR); + return ((localVal & ((uint32_t)0x00800000)) >> 23); +} + +__INLINE void ble_diagcntl_diag2_en_setf(uint8_t diag2en) +{ + BLE_ASSERT_ERR((((uint32_t)diag2en << 23) & ~((uint32_t)0x00800000)) == 0); + REG_BLE_WR(BLE_DIAGCNTL_ADDR, (REG_BLE_RD(BLE_DIAGCNTL_ADDR) & ~((uint32_t)0x00800000)) | ((uint32_t)diag2en << 23)); +} + +__INLINE uint8_t ble_diagcntl_diag2_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DIAGCNTL_ADDR); + return ((localVal & ((uint32_t)0x007F0000)) >> 16); +} + +__INLINE void ble_diagcntl_diag2_setf(uint8_t diag2) +{ + BLE_ASSERT_ERR((((uint32_t)diag2 << 16) & ~((uint32_t)0x007F0000)) == 0); + REG_BLE_WR(BLE_DIAGCNTL_ADDR, (REG_BLE_RD(BLE_DIAGCNTL_ADDR) & ~((uint32_t)0x007F0000)) | ((uint32_t)diag2 << 16)); +} + +__INLINE uint8_t ble_diagcntl_diag1_en_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DIAGCNTL_ADDR); + return ((localVal & ((uint32_t)0x00008000)) >> 15); +} + +__INLINE void ble_diagcntl_diag1_en_setf(uint8_t diag1en) +{ + BLE_ASSERT_ERR((((uint32_t)diag1en << 15) & ~((uint32_t)0x00008000)) == 0); + REG_BLE_WR(BLE_DIAGCNTL_ADDR, (REG_BLE_RD(BLE_DIAGCNTL_ADDR) & ~((uint32_t)0x00008000)) | ((uint32_t)diag1en << 15)); +} + +__INLINE uint8_t ble_diagcntl_diag1_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DIAGCNTL_ADDR); + return ((localVal & ((uint32_t)0x00007F00)) >> 8); +} + +__INLINE void ble_diagcntl_diag1_setf(uint8_t diag1) +{ + BLE_ASSERT_ERR((((uint32_t)diag1 << 8) & ~((uint32_t)0x00007F00)) == 0); + REG_BLE_WR(BLE_DIAGCNTL_ADDR, (REG_BLE_RD(BLE_DIAGCNTL_ADDR) & ~((uint32_t)0x00007F00)) | ((uint32_t)diag1 << 8)); +} + +__INLINE uint8_t ble_diagcntl_diag0_en_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DIAGCNTL_ADDR); + return ((localVal & ((uint32_t)0x00000080)) >> 7); +} + +__INLINE void ble_diagcntl_diag0_en_setf(uint8_t diag0en) +{ + BLE_ASSERT_ERR((((uint32_t)diag0en << 7) & ~((uint32_t)0x00000080)) == 0); + REG_BLE_WR(BLE_DIAGCNTL_ADDR, (REG_BLE_RD(BLE_DIAGCNTL_ADDR) & ~((uint32_t)0x00000080)) | ((uint32_t)diag0en << 7)); +} + +__INLINE uint8_t ble_diagcntl_diag0_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DIAGCNTL_ADDR); + return ((localVal & ((uint32_t)0x0000007F)) >> 0); +} + +__INLINE void ble_diagcntl_diag0_setf(uint8_t diag0) +{ + BLE_ASSERT_ERR((((uint32_t)diag0 << 0) & ~((uint32_t)0x0000007F)) == 0); + REG_BLE_WR(BLE_DIAGCNTL_ADDR, (REG_BLE_RD(BLE_DIAGCNTL_ADDR) & ~((uint32_t)0x0000007F)) | ((uint32_t)diag0 << 0)); +} + +/** + * @brief DIAGSTAT register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:24            DIAG3STAT   0x0
+ *  23:16            DIAG2STAT   0x0
+ *  15:08            DIAG1STAT   0x0
+ *  07:00            DIAG0STAT   0x0
+ * 
+ */ +#define BLE_DIAGSTAT_ADDR 0x00900854 +#define BLE_DIAGSTAT_OFFSET 0x00000054 +#define BLE_DIAGSTAT_INDEX 0x00000015 +#define BLE_DIAGSTAT_RESET 0x00000000 + +__INLINE uint32_t ble_diagstat_get(void) +{ + return REG_BLE_RD(BLE_DIAGSTAT_ADDR); +} + +// field definitions +#define BLE_DIAG3STAT_MASK ((uint32_t)0xFF000000) +#define BLE_DIAG3STAT_LSB 24 +#define BLE_DIAG3STAT_WIDTH ((uint32_t)0x00000008) +#define BLE_DIAG2STAT_MASK ((uint32_t)0x00FF0000) +#define BLE_DIAG2STAT_LSB 16 +#define BLE_DIAG2STAT_WIDTH ((uint32_t)0x00000008) +#define BLE_DIAG1STAT_MASK ((uint32_t)0x0000FF00) +#define BLE_DIAG1STAT_LSB 8 +#define BLE_DIAG1STAT_WIDTH ((uint32_t)0x00000008) +#define BLE_DIAG0STAT_MASK ((uint32_t)0x000000FF) +#define BLE_DIAG0STAT_LSB 0 +#define BLE_DIAG0STAT_WIDTH ((uint32_t)0x00000008) + +#define BLE_DIAG3STAT_RST 0x0 +#define BLE_DIAG2STAT_RST 0x0 +#define BLE_DIAG1STAT_RST 0x0 +#define BLE_DIAG0STAT_RST 0x0 + +__INLINE void ble_diagstat_unpack(uint8_t* diag3stat, uint8_t* diag2stat, uint8_t* diag1stat, uint8_t* diag0stat) +{ + uint32_t localVal = REG_BLE_RD(BLE_DIAGSTAT_ADDR); + + *diag3stat = (localVal & ((uint32_t)0xFF000000)) >> 24; + *diag2stat = (localVal & ((uint32_t)0x00FF0000)) >> 16; + *diag1stat = (localVal & ((uint32_t)0x0000FF00)) >> 8; + *diag0stat = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +__INLINE uint8_t ble_diagstat_diag3stat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DIAGSTAT_ADDR); + return ((localVal & ((uint32_t)0xFF000000)) >> 24); +} + +__INLINE uint8_t ble_diagstat_diag2stat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DIAGSTAT_ADDR); + return ((localVal & ((uint32_t)0x00FF0000)) >> 16); +} + +__INLINE uint8_t ble_diagstat_diag1stat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DIAGSTAT_ADDR); + return ((localVal & ((uint32_t)0x0000FF00)) >> 8); +} + +__INLINE uint8_t ble_diagstat_diag0stat_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DIAGSTAT_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +/** + * @brief DEBUGADDMAX register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:16           REG_ADDMAX   0x0
+ *  15:00            EM_ADDMAX   0x0
+ * 
+ */ +#define BLE_DEBUGADDMAX_ADDR 0x00900858 +#define BLE_DEBUGADDMAX_OFFSET 0x00000058 +#define BLE_DEBUGADDMAX_INDEX 0x00000016 +#define BLE_DEBUGADDMAX_RESET 0x00000000 + +__INLINE uint32_t ble_debugaddmax_get(void) +{ + return REG_BLE_RD(BLE_DEBUGADDMAX_ADDR); +} + +__INLINE void ble_debugaddmax_set(uint32_t value) +{ + REG_BLE_WR(BLE_DEBUGADDMAX_ADDR, value); +} + +// field definitions +#define BLE_REG_ADDMAX_MASK ((uint32_t)0xFFFF0000) +#define BLE_REG_ADDMAX_LSB 16 +#define BLE_REG_ADDMAX_WIDTH ((uint32_t)0x00000010) +#define BLE_EM_ADDMAX_MASK ((uint32_t)0x0000FFFF) +#define BLE_EM_ADDMAX_LSB 0 +#define BLE_EM_ADDMAX_WIDTH ((uint32_t)0x00000010) + +#define BLE_REG_ADDMAX_RST 0x0 +#define BLE_EM_ADDMAX_RST 0x0 + +__INLINE void ble_debugaddmax_pack(uint16_t regaddmax, uint16_t emaddmax) +{ + BLE_ASSERT_ERR((((uint32_t)regaddmax << 16) & ~((uint32_t)0xFFFF0000)) == 0); + BLE_ASSERT_ERR((((uint32_t)emaddmax << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_BLE_WR(BLE_DEBUGADDMAX_ADDR, ((uint32_t)regaddmax << 16) | ((uint32_t)emaddmax << 0)); +} + +__INLINE void ble_debugaddmax_unpack(uint16_t* regaddmax, uint16_t* emaddmax) +{ + uint32_t localVal = REG_BLE_RD(BLE_DEBUGADDMAX_ADDR); + + *regaddmax = (localVal & ((uint32_t)0xFFFF0000)) >> 16; + *emaddmax = (localVal & ((uint32_t)0x0000FFFF)) >> 0; +} + +__INLINE uint16_t ble_debugaddmax_reg_addmax_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DEBUGADDMAX_ADDR); + return ((localVal & ((uint32_t)0xFFFF0000)) >> 16); +} + +__INLINE void ble_debugaddmax_reg_addmax_setf(uint16_t regaddmax) +{ + BLE_ASSERT_ERR((((uint32_t)regaddmax << 16) & ~((uint32_t)0xFFFF0000)) == 0); + REG_BLE_WR(BLE_DEBUGADDMAX_ADDR, (REG_BLE_RD(BLE_DEBUGADDMAX_ADDR) & ~((uint32_t)0xFFFF0000)) | ((uint32_t)regaddmax << 16)); +} + +__INLINE uint16_t ble_debugaddmax_em_addmax_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DEBUGADDMAX_ADDR); + return ((localVal & ((uint32_t)0x0000FFFF)) >> 0); +} + +__INLINE void ble_debugaddmax_em_addmax_setf(uint16_t emaddmax) +{ + BLE_ASSERT_ERR((((uint32_t)emaddmax << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_BLE_WR(BLE_DEBUGADDMAX_ADDR, (REG_BLE_RD(BLE_DEBUGADDMAX_ADDR) & ~((uint32_t)0x0000FFFF)) | ((uint32_t)emaddmax << 0)); +} + +/** + * @brief DEBUGADDMIN register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:16           REG_ADDMIN   0x0
+ *  15:00            EM_ADDMIN   0x0
+ * 
+ */ +#define BLE_DEBUGADDMIN_ADDR 0x0090085C +#define BLE_DEBUGADDMIN_OFFSET 0x0000005C +#define BLE_DEBUGADDMIN_INDEX 0x00000017 +#define BLE_DEBUGADDMIN_RESET 0x00000000 + +__INLINE uint32_t ble_debugaddmin_get(void) +{ + return REG_BLE_RD(BLE_DEBUGADDMIN_ADDR); +} + +__INLINE void ble_debugaddmin_set(uint32_t value) +{ + REG_BLE_WR(BLE_DEBUGADDMIN_ADDR, value); +} + +// field definitions +#define BLE_REG_ADDMIN_MASK ((uint32_t)0xFFFF0000) +#define BLE_REG_ADDMIN_LSB 16 +#define BLE_REG_ADDMIN_WIDTH ((uint32_t)0x00000010) +#define BLE_EM_ADDMIN_MASK ((uint32_t)0x0000FFFF) +#define BLE_EM_ADDMIN_LSB 0 +#define BLE_EM_ADDMIN_WIDTH ((uint32_t)0x00000010) + +#define BLE_REG_ADDMIN_RST 0x0 +#define BLE_EM_ADDMIN_RST 0x0 + +__INLINE void ble_debugaddmin_pack(uint16_t regaddmin, uint16_t emaddmin) +{ + BLE_ASSERT_ERR((((uint32_t)regaddmin << 16) & ~((uint32_t)0xFFFF0000)) == 0); + BLE_ASSERT_ERR((((uint32_t)emaddmin << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_BLE_WR(BLE_DEBUGADDMIN_ADDR, ((uint32_t)regaddmin << 16) | ((uint32_t)emaddmin << 0)); +} + +__INLINE void ble_debugaddmin_unpack(uint16_t* regaddmin, uint16_t* emaddmin) +{ + uint32_t localVal = REG_BLE_RD(BLE_DEBUGADDMIN_ADDR); + + *regaddmin = (localVal & ((uint32_t)0xFFFF0000)) >> 16; + *emaddmin = (localVal & ((uint32_t)0x0000FFFF)) >> 0; +} + +__INLINE uint16_t ble_debugaddmin_reg_addmin_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DEBUGADDMIN_ADDR); + return ((localVal & ((uint32_t)0xFFFF0000)) >> 16); +} + +__INLINE void ble_debugaddmin_reg_addmin_setf(uint16_t regaddmin) +{ + BLE_ASSERT_ERR((((uint32_t)regaddmin << 16) & ~((uint32_t)0xFFFF0000)) == 0); + REG_BLE_WR(BLE_DEBUGADDMIN_ADDR, (REG_BLE_RD(BLE_DEBUGADDMIN_ADDR) & ~((uint32_t)0xFFFF0000)) | ((uint32_t)regaddmin << 16)); +} + +__INLINE uint16_t ble_debugaddmin_em_addmin_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DEBUGADDMIN_ADDR); + return ((localVal & ((uint32_t)0x0000FFFF)) >> 0); +} + +__INLINE void ble_debugaddmin_em_addmin_setf(uint16_t emaddmin) +{ + BLE_ASSERT_ERR((((uint32_t)emaddmin << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_BLE_WR(BLE_DEBUGADDMIN_ADDR, (REG_BLE_RD(BLE_DEBUGADDMIN_ADDR) & ~((uint32_t)0x0000FFFF)) | ((uint32_t)emaddmin << 0)); +} + +/** + * @brief ERRORTYPESTAT register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     22   DFCNTL_EMACC_ERROR   0
+ *     21           FIFOINTOVF   0
+ *     20            PHY_ERROR   0
+ *     19   TXAEHEADER_PTR_ERROR   0
+ *     18       TMAFS_UNDERRUN   0
+ *     17         RAL_UNDERRUN   0
+ *     16            RAL_ERROR   0
+ *     15     RXDATA_PTR_ERROR   0
+ *     14     TXDATA_PTR_ERROR   0
+ *     13   RXDESC_EMPTY_ERROR   0
+ *     12   TXDESC_EMPTY_ERROR   0
+ *     11       CSFORMAT_ERROR   0
+ *     10        LLCHMAP_ERROR   0
+ *     09         ADV_UNDERRUN   0
+ *     08         IFS_UNDERRUN   0
+ *     07           LIST_ERROR   0
+ *     06   EVT_CNTL_APFM_ERROR   0
+ *     05   ACT_SCHDL_APFM_ERROR   0
+ *     04   ACT_SCHDL_ENTRY_ERROR   0
+ *     03    RADIO_EMACC_ERROR   0
+ *     02   PKTCNTL_EMACC_ERROR   0
+ *     01        RXCRYPT_ERROR   0
+ *     00        TXCRYPT_ERROR   0
+ * 
+ */ +#define BLE_ERRORTYPESTAT_ADDR 0x00900860 +#define BLE_ERRORTYPESTAT_OFFSET 0x00000060 +#define BLE_ERRORTYPESTAT_INDEX 0x00000018 +#define BLE_ERRORTYPESTAT_RESET 0x00000000 + +__INLINE uint32_t ble_errortypestat_get(void) +{ + return REG_BLE_RD(BLE_ERRORTYPESTAT_ADDR); +} + +// field definitions +#define BLE_DFCNTL_EMACC_ERROR_BIT ((uint32_t)0x00400000) +#define BLE_DFCNTL_EMACC_ERROR_POS 22 +#define BLE_FIFOINTOVF_BIT ((uint32_t)0x00200000) +#define BLE_FIFOINTOVF_POS 21 +#define BLE_PHY_ERROR_BIT ((uint32_t)0x00100000) +#define BLE_PHY_ERROR_POS 20 +#define BLE_TXAEHEADER_PTR_ERROR_BIT ((uint32_t)0x00080000) +#define BLE_TXAEHEADER_PTR_ERROR_POS 19 +#define BLE_TMAFS_UNDERRUN_BIT ((uint32_t)0x00040000) +#define BLE_TMAFS_UNDERRUN_POS 18 +#define BLE_RAL_UNDERRUN_BIT ((uint32_t)0x00020000) +#define BLE_RAL_UNDERRUN_POS 17 +#define BLE_RAL_ERROR_BIT ((uint32_t)0x00010000) +#define BLE_RAL_ERROR_POS 16 +#define BLE_RXDATA_PTR_ERROR_BIT ((uint32_t)0x00008000) +#define BLE_RXDATA_PTR_ERROR_POS 15 +#define BLE_TXDATA_PTR_ERROR_BIT ((uint32_t)0x00004000) +#define BLE_TXDATA_PTR_ERROR_POS 14 +#define BLE_RXDESC_EMPTY_ERROR_BIT ((uint32_t)0x00002000) +#define BLE_RXDESC_EMPTY_ERROR_POS 13 +#define BLE_TXDESC_EMPTY_ERROR_BIT ((uint32_t)0x00001000) +#define BLE_TXDESC_EMPTY_ERROR_POS 12 +#define BLE_CSFORMAT_ERROR_BIT ((uint32_t)0x00000800) +#define BLE_CSFORMAT_ERROR_POS 11 +#define BLE_LLCHMAP_ERROR_BIT ((uint32_t)0x00000400) +#define BLE_LLCHMAP_ERROR_POS 10 +#define BLE_ADV_UNDERRUN_BIT ((uint32_t)0x00000200) +#define BLE_ADV_UNDERRUN_POS 9 +#define BLE_IFS_UNDERRUN_BIT ((uint32_t)0x00000100) +#define BLE_IFS_UNDERRUN_POS 8 +#define BLE_LIST_ERROR_BIT ((uint32_t)0x00000080) +#define BLE_LIST_ERROR_POS 7 +#define BLE_EVT_CNTL_APFM_ERROR_BIT ((uint32_t)0x00000040) +#define BLE_EVT_CNTL_APFM_ERROR_POS 6 +#define BLE_ACT_SCHDL_APFM_ERROR_BIT ((uint32_t)0x00000020) +#define BLE_ACT_SCHDL_APFM_ERROR_POS 5 +#define BLE_ACT_SCHDL_ENTRY_ERROR_BIT ((uint32_t)0x00000010) +#define BLE_ACT_SCHDL_ENTRY_ERROR_POS 4 +#define BLE_RADIO_EMACC_ERROR_BIT ((uint32_t)0x00000008) +#define BLE_RADIO_EMACC_ERROR_POS 3 +#define BLE_PKTCNTL_EMACC_ERROR_BIT ((uint32_t)0x00000004) +#define BLE_PKTCNTL_EMACC_ERROR_POS 2 +#define BLE_RXCRYPT_ERROR_BIT ((uint32_t)0x00000002) +#define BLE_RXCRYPT_ERROR_POS 1 +#define BLE_TXCRYPT_ERROR_BIT ((uint32_t)0x00000001) +#define BLE_TXCRYPT_ERROR_POS 0 + +#define BLE_DFCNTL_EMACC_ERROR_RST 0x0 +#define BLE_FIFOINTOVF_RST 0x0 +#define BLE_PHY_ERROR_RST 0x0 +#define BLE_TXAEHEADER_PTR_ERROR_RST 0x0 +#define BLE_TMAFS_UNDERRUN_RST 0x0 +#define BLE_RAL_UNDERRUN_RST 0x0 +#define BLE_RAL_ERROR_RST 0x0 +#define BLE_RXDATA_PTR_ERROR_RST 0x0 +#define BLE_TXDATA_PTR_ERROR_RST 0x0 +#define BLE_RXDESC_EMPTY_ERROR_RST 0x0 +#define BLE_TXDESC_EMPTY_ERROR_RST 0x0 +#define BLE_CSFORMAT_ERROR_RST 0x0 +#define BLE_LLCHMAP_ERROR_RST 0x0 +#define BLE_ADV_UNDERRUN_RST 0x0 +#define BLE_IFS_UNDERRUN_RST 0x0 +#define BLE_LIST_ERROR_RST 0x0 +#define BLE_EVT_CNTL_APFM_ERROR_RST 0x0 +#define BLE_ACT_SCHDL_APFM_ERROR_RST 0x0 +#define BLE_ACT_SCHDL_ENTRY_ERROR_RST 0x0 +#define BLE_RADIO_EMACC_ERROR_RST 0x0 +#define BLE_PKTCNTL_EMACC_ERROR_RST 0x0 +#define BLE_RXCRYPT_ERROR_RST 0x0 +#define BLE_TXCRYPT_ERROR_RST 0x0 + +__INLINE void ble_errortypestat_unpack(uint8_t* dfcntlemaccerror, uint8_t* fifointovf, uint8_t* phyerror, uint8_t* txaeheaderptrerror, uint8_t* tmafsunderrun, uint8_t* ralunderrun, uint8_t* ralerror, uint8_t* rxdataptrerror, uint8_t* txdataptrerror, uint8_t* rxdescemptyerror, uint8_t* txdescemptyerror, uint8_t* csformaterror, uint8_t* llchmaperror, uint8_t* advunderrun, uint8_t* ifsunderrun, uint8_t* listerror, uint8_t* evtcntlapfmerror, uint8_t* actschdlapfmerror, uint8_t* actschdlentryerror, uint8_t* radioemaccerror, uint8_t* pktcntlemaccerror, uint8_t* rxcrypterror, uint8_t* txcrypterror) +{ + uint32_t localVal = REG_BLE_RD(BLE_ERRORTYPESTAT_ADDR); + + *dfcntlemaccerror = (localVal & ((uint32_t)0x00400000)) >> 22; + *fifointovf = (localVal & ((uint32_t)0x00200000)) >> 21; + *phyerror = (localVal & ((uint32_t)0x00100000)) >> 20; + *txaeheaderptrerror = (localVal & ((uint32_t)0x00080000)) >> 19; + *tmafsunderrun = (localVal & ((uint32_t)0x00040000)) >> 18; + *ralunderrun = (localVal & ((uint32_t)0x00020000)) >> 17; + *ralerror = (localVal & ((uint32_t)0x00010000)) >> 16; + *rxdataptrerror = (localVal & ((uint32_t)0x00008000)) >> 15; + *txdataptrerror = (localVal & ((uint32_t)0x00004000)) >> 14; + *rxdescemptyerror = (localVal & ((uint32_t)0x00002000)) >> 13; + *txdescemptyerror = (localVal & ((uint32_t)0x00001000)) >> 12; + *csformaterror = (localVal & ((uint32_t)0x00000800)) >> 11; + *llchmaperror = (localVal & ((uint32_t)0x00000400)) >> 10; + *advunderrun = (localVal & ((uint32_t)0x00000200)) >> 9; + *ifsunderrun = (localVal & ((uint32_t)0x00000100)) >> 8; + *listerror = (localVal & ((uint32_t)0x00000080)) >> 7; + *evtcntlapfmerror = (localVal & ((uint32_t)0x00000040)) >> 6; + *actschdlapfmerror = (localVal & ((uint32_t)0x00000020)) >> 5; + *actschdlentryerror = (localVal & ((uint32_t)0x00000010)) >> 4; + *radioemaccerror = (localVal & ((uint32_t)0x00000008)) >> 3; + *pktcntlemaccerror = (localVal & ((uint32_t)0x00000004)) >> 2; + *rxcrypterror = (localVal & ((uint32_t)0x00000002)) >> 1; + *txcrypterror = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +__INLINE uint8_t ble_errortypestat_dfcntl_emacc_error_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ERRORTYPESTAT_ADDR); + return ((localVal & ((uint32_t)0x00400000)) >> 22); +} + +__INLINE uint8_t ble_errortypestat_fifointovf_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ERRORTYPESTAT_ADDR); + return ((localVal & ((uint32_t)0x00200000)) >> 21); +} + +__INLINE uint8_t ble_errortypestat_phy_error_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ERRORTYPESTAT_ADDR); + return ((localVal & ((uint32_t)0x00100000)) >> 20); +} + +__INLINE uint8_t ble_errortypestat_txaeheader_ptr_error_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ERRORTYPESTAT_ADDR); + return ((localVal & ((uint32_t)0x00080000)) >> 19); +} + +__INLINE uint8_t ble_errortypestat_tmafs_underrun_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ERRORTYPESTAT_ADDR); + return ((localVal & ((uint32_t)0x00040000)) >> 18); +} + +__INLINE uint8_t ble_errortypestat_ral_underrun_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ERRORTYPESTAT_ADDR); + return ((localVal & ((uint32_t)0x00020000)) >> 17); +} + +__INLINE uint8_t ble_errortypestat_ral_error_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ERRORTYPESTAT_ADDR); + return ((localVal & ((uint32_t)0x00010000)) >> 16); +} + +__INLINE uint8_t ble_errortypestat_rxdata_ptr_error_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ERRORTYPESTAT_ADDR); + return ((localVal & ((uint32_t)0x00008000)) >> 15); +} + +__INLINE uint8_t ble_errortypestat_txdata_ptr_error_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ERRORTYPESTAT_ADDR); + return ((localVal & ((uint32_t)0x00004000)) >> 14); +} + +__INLINE uint8_t ble_errortypestat_rxdesc_empty_error_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ERRORTYPESTAT_ADDR); + return ((localVal & ((uint32_t)0x00002000)) >> 13); +} + +__INLINE uint8_t ble_errortypestat_txdesc_empty_error_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ERRORTYPESTAT_ADDR); + return ((localVal & ((uint32_t)0x00001000)) >> 12); +} + +__INLINE uint8_t ble_errortypestat_csformat_error_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ERRORTYPESTAT_ADDR); + return ((localVal & ((uint32_t)0x00000800)) >> 11); +} + +__INLINE uint8_t ble_errortypestat_llchmap_error_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ERRORTYPESTAT_ADDR); + return ((localVal & ((uint32_t)0x00000400)) >> 10); +} + +__INLINE uint8_t ble_errortypestat_adv_underrun_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ERRORTYPESTAT_ADDR); + return ((localVal & ((uint32_t)0x00000200)) >> 9); +} + +__INLINE uint8_t ble_errortypestat_ifs_underrun_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ERRORTYPESTAT_ADDR); + return ((localVal & ((uint32_t)0x00000100)) >> 8); +} + +__INLINE uint8_t ble_errortypestat_list_error_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ERRORTYPESTAT_ADDR); + return ((localVal & ((uint32_t)0x00000080)) >> 7); +} + +__INLINE uint8_t ble_errortypestat_evt_cntl_apfm_error_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ERRORTYPESTAT_ADDR); + return ((localVal & ((uint32_t)0x00000040)) >> 6); +} + +__INLINE uint8_t ble_errortypestat_act_schdl_apfm_error_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ERRORTYPESTAT_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +__INLINE uint8_t ble_errortypestat_act_schdl_entry_error_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ERRORTYPESTAT_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +__INLINE uint8_t ble_errortypestat_radio_emacc_error_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ERRORTYPESTAT_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +__INLINE uint8_t ble_errortypestat_pktcntl_emacc_error_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ERRORTYPESTAT_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +__INLINE uint8_t ble_errortypestat_rxcrypt_error_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ERRORTYPESTAT_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +__INLINE uint8_t ble_errortypestat_txcrypt_error_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ERRORTYPESTAT_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/** + * @brief SWPROFILING register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31             SWPROF31   0
+ *     30             SWPROF30   0
+ *     29             SWPROF29   0
+ *     28             SWPROF28   0
+ *     27             SWPROF27   0
+ *     26             SWPROF26   0
+ *     25             SWPROF25   0
+ *     24             SWPROF24   0
+ *     23             SWPROF23   0
+ *     22             SWPROF22   0
+ *     21             SWPROF21   0
+ *     20             SWPROF20   0
+ *     19             SWPROF19   0
+ *     18             SWPROF18   0
+ *     17             SWPROF17   0
+ *     16             SWPROF16   0
+ *     15             SWPROF15   0
+ *     14             SWPROF14   0
+ *     13             SWPROF13   0
+ *     12             SWPROF12   0
+ *     11             SWPROF11   0
+ *     10             SWPROF10   0
+ *     09              SWPROF9   0
+ *     08              SWPROF8   0
+ *     07              SWPROF7   0
+ *     06              SWPROF6   0
+ *     05              SWPROF5   0
+ *     04              SWPROF4   0
+ *     03              SWPROF3   0
+ *     02              SWPROF2   0
+ *     01              SWPROF1   0
+ *     00              SWPROF0   0
+ * 
+ */ +#define BLE_SWPROFILING_ADDR 0x00900864 +#define BLE_SWPROFILING_OFFSET 0x00000064 +#define BLE_SWPROFILING_INDEX 0x00000019 +#define BLE_SWPROFILING_RESET 0x00000000 + +__INLINE uint32_t ble_swprofiling_get(void) +{ + return REG_BLE_RD(BLE_SWPROFILING_ADDR); +} + +__INLINE void ble_swprofiling_set(uint32_t value) +{ + REG_BLE_WR(BLE_SWPROFILING_ADDR, value); +} + +// field definitions +#define BLE_SWPROF31_BIT ((uint32_t)0x80000000) +#define BLE_SWPROF31_POS 31 +#define BLE_SWPROF30_BIT ((uint32_t)0x40000000) +#define BLE_SWPROF30_POS 30 +#define BLE_SWPROF29_BIT ((uint32_t)0x20000000) +#define BLE_SWPROF29_POS 29 +#define BLE_SWPROF28_BIT ((uint32_t)0x10000000) +#define BLE_SWPROF28_POS 28 +#define BLE_SWPROF27_BIT ((uint32_t)0x08000000) +#define BLE_SWPROF27_POS 27 +#define BLE_SWPROF26_BIT ((uint32_t)0x04000000) +#define BLE_SWPROF26_POS 26 +#define BLE_SWPROF25_BIT ((uint32_t)0x02000000) +#define BLE_SWPROF25_POS 25 +#define BLE_SWPROF24_BIT ((uint32_t)0x01000000) +#define BLE_SWPROF24_POS 24 +#define BLE_SWPROF23_BIT ((uint32_t)0x00800000) +#define BLE_SWPROF23_POS 23 +#define BLE_SWPROF22_BIT ((uint32_t)0x00400000) +#define BLE_SWPROF22_POS 22 +#define BLE_SWPROF21_BIT ((uint32_t)0x00200000) +#define BLE_SWPROF21_POS 21 +#define BLE_SWPROF20_BIT ((uint32_t)0x00100000) +#define BLE_SWPROF20_POS 20 +#define BLE_SWPROF19_BIT ((uint32_t)0x00080000) +#define BLE_SWPROF19_POS 19 +#define BLE_SWPROF18_BIT ((uint32_t)0x00040000) +#define BLE_SWPROF18_POS 18 +#define BLE_SWPROF17_BIT ((uint32_t)0x00020000) +#define BLE_SWPROF17_POS 17 +#define BLE_SWPROF16_BIT ((uint32_t)0x00010000) +#define BLE_SWPROF16_POS 16 +#define BLE_SWPROF15_BIT ((uint32_t)0x00008000) +#define BLE_SWPROF15_POS 15 +#define BLE_SWPROF14_BIT ((uint32_t)0x00004000) +#define BLE_SWPROF14_POS 14 +#define BLE_SWPROF13_BIT ((uint32_t)0x00002000) +#define BLE_SWPROF13_POS 13 +#define BLE_SWPROF12_BIT ((uint32_t)0x00001000) +#define BLE_SWPROF12_POS 12 +#define BLE_SWPROF11_BIT ((uint32_t)0x00000800) +#define BLE_SWPROF11_POS 11 +#define BLE_SWPROF10_BIT ((uint32_t)0x00000400) +#define BLE_SWPROF10_POS 10 +#define BLE_SWPROF9_BIT ((uint32_t)0x00000200) +#define BLE_SWPROF9_POS 9 +#define BLE_SWPROF8_BIT ((uint32_t)0x00000100) +#define BLE_SWPROF8_POS 8 +#define BLE_SWPROF7_BIT ((uint32_t)0x00000080) +#define BLE_SWPROF7_POS 7 +#define BLE_SWPROF6_BIT ((uint32_t)0x00000040) +#define BLE_SWPROF6_POS 6 +#define BLE_SWPROF5_BIT ((uint32_t)0x00000020) +#define BLE_SWPROF5_POS 5 +#define BLE_SWPROF4_BIT ((uint32_t)0x00000010) +#define BLE_SWPROF4_POS 4 +#define BLE_SWPROF3_BIT ((uint32_t)0x00000008) +#define BLE_SWPROF3_POS 3 +#define BLE_SWPROF2_BIT ((uint32_t)0x00000004) +#define BLE_SWPROF2_POS 2 +#define BLE_SWPROF1_BIT ((uint32_t)0x00000002) +#define BLE_SWPROF1_POS 1 +#define BLE_SWPROF0_BIT ((uint32_t)0x00000001) +#define BLE_SWPROF0_POS 0 + +#define BLE_SWPROF31_RST 0x0 +#define BLE_SWPROF30_RST 0x0 +#define BLE_SWPROF29_RST 0x0 +#define BLE_SWPROF28_RST 0x0 +#define BLE_SWPROF27_RST 0x0 +#define BLE_SWPROF26_RST 0x0 +#define BLE_SWPROF25_RST 0x0 +#define BLE_SWPROF24_RST 0x0 +#define BLE_SWPROF23_RST 0x0 +#define BLE_SWPROF22_RST 0x0 +#define BLE_SWPROF21_RST 0x0 +#define BLE_SWPROF20_RST 0x0 +#define BLE_SWPROF19_RST 0x0 +#define BLE_SWPROF18_RST 0x0 +#define BLE_SWPROF17_RST 0x0 +#define BLE_SWPROF16_RST 0x0 +#define BLE_SWPROF15_RST 0x0 +#define BLE_SWPROF14_RST 0x0 +#define BLE_SWPROF13_RST 0x0 +#define BLE_SWPROF12_RST 0x0 +#define BLE_SWPROF11_RST 0x0 +#define BLE_SWPROF10_RST 0x0 +#define BLE_SWPROF9_RST 0x0 +#define BLE_SWPROF8_RST 0x0 +#define BLE_SWPROF7_RST 0x0 +#define BLE_SWPROF6_RST 0x0 +#define BLE_SWPROF5_RST 0x0 +#define BLE_SWPROF4_RST 0x0 +#define BLE_SWPROF3_RST 0x0 +#define BLE_SWPROF2_RST 0x0 +#define BLE_SWPROF1_RST 0x0 +#define BLE_SWPROF0_RST 0x0 + +__INLINE void ble_swprofiling_pack(uint8_t swprof31, uint8_t swprof30, uint8_t swprof29, uint8_t swprof28, uint8_t swprof27, uint8_t swprof26, uint8_t swprof25, uint8_t swprof24, uint8_t swprof23, uint8_t swprof22, uint8_t swprof21, uint8_t swprof20, uint8_t swprof19, uint8_t swprof18, uint8_t swprof17, uint8_t swprof16, uint8_t swprof15, uint8_t swprof14, uint8_t swprof13, uint8_t swprof12, uint8_t swprof11, uint8_t swprof10, uint8_t swprof9, uint8_t swprof8, uint8_t swprof7, uint8_t swprof6, uint8_t swprof5, uint8_t swprof4, uint8_t swprof3, uint8_t swprof2, uint8_t swprof1, uint8_t swprof0) +{ + BLE_ASSERT_ERR((((uint32_t)swprof31 << 31) & ~((uint32_t)0x80000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof30 << 30) & ~((uint32_t)0x40000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof29 << 29) & ~((uint32_t)0x20000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof28 << 28) & ~((uint32_t)0x10000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof27 << 27) & ~((uint32_t)0x08000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof26 << 26) & ~((uint32_t)0x04000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof25 << 25) & ~((uint32_t)0x02000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof24 << 24) & ~((uint32_t)0x01000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof23 << 23) & ~((uint32_t)0x00800000)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof22 << 22) & ~((uint32_t)0x00400000)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof21 << 21) & ~((uint32_t)0x00200000)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof20 << 20) & ~((uint32_t)0x00100000)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof19 << 19) & ~((uint32_t)0x00080000)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof18 << 18) & ~((uint32_t)0x00040000)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof17 << 17) & ~((uint32_t)0x00020000)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof16 << 16) & ~((uint32_t)0x00010000)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof15 << 15) & ~((uint32_t)0x00008000)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof14 << 14) & ~((uint32_t)0x00004000)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof13 << 13) & ~((uint32_t)0x00002000)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof12 << 12) & ~((uint32_t)0x00001000)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof11 << 11) & ~((uint32_t)0x00000800)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof10 << 10) & ~((uint32_t)0x00000400)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof9 << 9) & ~((uint32_t)0x00000200)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof8 << 8) & ~((uint32_t)0x00000100)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof7 << 7) & ~((uint32_t)0x00000080)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof6 << 6) & ~((uint32_t)0x00000040)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof5 << 5) & ~((uint32_t)0x00000020)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof4 << 4) & ~((uint32_t)0x00000010)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof3 << 3) & ~((uint32_t)0x00000008)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof2 << 2) & ~((uint32_t)0x00000004)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof1 << 1) & ~((uint32_t)0x00000002)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof0 << 0) & ~((uint32_t)0x00000001)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, ((uint32_t)swprof31 << 31) | ((uint32_t)swprof30 << 30) | ((uint32_t)swprof29 << 29) | ((uint32_t)swprof28 << 28) | ((uint32_t)swprof27 << 27) | ((uint32_t)swprof26 << 26) | ((uint32_t)swprof25 << 25) | ((uint32_t)swprof24 << 24) | ((uint32_t)swprof23 << 23) | ((uint32_t)swprof22 << 22) | ((uint32_t)swprof21 << 21) | ((uint32_t)swprof20 << 20) | ((uint32_t)swprof19 << 19) | ((uint32_t)swprof18 << 18) | ((uint32_t)swprof17 << 17) | ((uint32_t)swprof16 << 16) | ((uint32_t)swprof15 << 15) | ((uint32_t)swprof14 << 14) | ((uint32_t)swprof13 << 13) | ((uint32_t)swprof12 << 12) | ((uint32_t)swprof11 << 11) | ((uint32_t)swprof10 << 10) | ((uint32_t)swprof9 << 9) | ((uint32_t)swprof8 << 8) | ((uint32_t)swprof7 << 7) | ((uint32_t)swprof6 << 6) | ((uint32_t)swprof5 << 5) | ((uint32_t)swprof4 << 4) | ((uint32_t)swprof3 << 3) | ((uint32_t)swprof2 << 2) | ((uint32_t)swprof1 << 1) | ((uint32_t)swprof0 << 0)); +} + +__INLINE void ble_swprofiling_unpack(uint8_t* swprof31, uint8_t* swprof30, uint8_t* swprof29, uint8_t* swprof28, uint8_t* swprof27, uint8_t* swprof26, uint8_t* swprof25, uint8_t* swprof24, uint8_t* swprof23, uint8_t* swprof22, uint8_t* swprof21, uint8_t* swprof20, uint8_t* swprof19, uint8_t* swprof18, uint8_t* swprof17, uint8_t* swprof16, uint8_t* swprof15, uint8_t* swprof14, uint8_t* swprof13, uint8_t* swprof12, uint8_t* swprof11, uint8_t* swprof10, uint8_t* swprof9, uint8_t* swprof8, uint8_t* swprof7, uint8_t* swprof6, uint8_t* swprof5, uint8_t* swprof4, uint8_t* swprof3, uint8_t* swprof2, uint8_t* swprof1, uint8_t* swprof0) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + + *swprof31 = (localVal & ((uint32_t)0x80000000)) >> 31; + *swprof30 = (localVal & ((uint32_t)0x40000000)) >> 30; + *swprof29 = (localVal & ((uint32_t)0x20000000)) >> 29; + *swprof28 = (localVal & ((uint32_t)0x10000000)) >> 28; + *swprof27 = (localVal & ((uint32_t)0x08000000)) >> 27; + *swprof26 = (localVal & ((uint32_t)0x04000000)) >> 26; + *swprof25 = (localVal & ((uint32_t)0x02000000)) >> 25; + *swprof24 = (localVal & ((uint32_t)0x01000000)) >> 24; + *swprof23 = (localVal & ((uint32_t)0x00800000)) >> 23; + *swprof22 = (localVal & ((uint32_t)0x00400000)) >> 22; + *swprof21 = (localVal & ((uint32_t)0x00200000)) >> 21; + *swprof20 = (localVal & ((uint32_t)0x00100000)) >> 20; + *swprof19 = (localVal & ((uint32_t)0x00080000)) >> 19; + *swprof18 = (localVal & ((uint32_t)0x00040000)) >> 18; + *swprof17 = (localVal & ((uint32_t)0x00020000)) >> 17; + *swprof16 = (localVal & ((uint32_t)0x00010000)) >> 16; + *swprof15 = (localVal & ((uint32_t)0x00008000)) >> 15; + *swprof14 = (localVal & ((uint32_t)0x00004000)) >> 14; + *swprof13 = (localVal & ((uint32_t)0x00002000)) >> 13; + *swprof12 = (localVal & ((uint32_t)0x00001000)) >> 12; + *swprof11 = (localVal & ((uint32_t)0x00000800)) >> 11; + *swprof10 = (localVal & ((uint32_t)0x00000400)) >> 10; + *swprof9 = (localVal & ((uint32_t)0x00000200)) >> 9; + *swprof8 = (localVal & ((uint32_t)0x00000100)) >> 8; + *swprof7 = (localVal & ((uint32_t)0x00000080)) >> 7; + *swprof6 = (localVal & ((uint32_t)0x00000040)) >> 6; + *swprof5 = (localVal & ((uint32_t)0x00000020)) >> 5; + *swprof4 = (localVal & ((uint32_t)0x00000010)) >> 4; + *swprof3 = (localVal & ((uint32_t)0x00000008)) >> 3; + *swprof2 = (localVal & ((uint32_t)0x00000004)) >> 2; + *swprof1 = (localVal & ((uint32_t)0x00000002)) >> 1; + *swprof0 = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +__INLINE uint8_t ble_swprofiling_swprof31_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +__INLINE void ble_swprofiling_swprof31_setf(uint8_t swprof31) +{ + BLE_ASSERT_ERR((((uint32_t)swprof31 << 31) & ~((uint32_t)0x80000000)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x80000000)) | ((uint32_t)swprof31 << 31)); +} + +__INLINE uint8_t ble_swprofiling_swprof30_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x40000000)) >> 30); +} + +__INLINE void ble_swprofiling_swprof30_setf(uint8_t swprof30) +{ + BLE_ASSERT_ERR((((uint32_t)swprof30 << 30) & ~((uint32_t)0x40000000)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x40000000)) | ((uint32_t)swprof30 << 30)); +} + +__INLINE uint8_t ble_swprofiling_swprof29_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x20000000)) >> 29); +} + +__INLINE void ble_swprofiling_swprof29_setf(uint8_t swprof29) +{ + BLE_ASSERT_ERR((((uint32_t)swprof29 << 29) & ~((uint32_t)0x20000000)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x20000000)) | ((uint32_t)swprof29 << 29)); +} + +__INLINE uint8_t ble_swprofiling_swprof28_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x10000000)) >> 28); +} + +__INLINE void ble_swprofiling_swprof28_setf(uint8_t swprof28) +{ + BLE_ASSERT_ERR((((uint32_t)swprof28 << 28) & ~((uint32_t)0x10000000)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x10000000)) | ((uint32_t)swprof28 << 28)); +} + +__INLINE uint8_t ble_swprofiling_swprof27_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x08000000)) >> 27); +} + +__INLINE void ble_swprofiling_swprof27_setf(uint8_t swprof27) +{ + BLE_ASSERT_ERR((((uint32_t)swprof27 << 27) & ~((uint32_t)0x08000000)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x08000000)) | ((uint32_t)swprof27 << 27)); +} + +__INLINE uint8_t ble_swprofiling_swprof26_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x04000000)) >> 26); +} + +__INLINE void ble_swprofiling_swprof26_setf(uint8_t swprof26) +{ + BLE_ASSERT_ERR((((uint32_t)swprof26 << 26) & ~((uint32_t)0x04000000)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x04000000)) | ((uint32_t)swprof26 << 26)); +} + +__INLINE uint8_t ble_swprofiling_swprof25_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x02000000)) >> 25); +} + +__INLINE void ble_swprofiling_swprof25_setf(uint8_t swprof25) +{ + BLE_ASSERT_ERR((((uint32_t)swprof25 << 25) & ~((uint32_t)0x02000000)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x02000000)) | ((uint32_t)swprof25 << 25)); +} + +__INLINE uint8_t ble_swprofiling_swprof24_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x01000000)) >> 24); +} + +__INLINE void ble_swprofiling_swprof24_setf(uint8_t swprof24) +{ + BLE_ASSERT_ERR((((uint32_t)swprof24 << 24) & ~((uint32_t)0x01000000)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x01000000)) | ((uint32_t)swprof24 << 24)); +} + +__INLINE uint8_t ble_swprofiling_swprof23_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00800000)) >> 23); +} + +__INLINE void ble_swprofiling_swprof23_setf(uint8_t swprof23) +{ + BLE_ASSERT_ERR((((uint32_t)swprof23 << 23) & ~((uint32_t)0x00800000)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x00800000)) | ((uint32_t)swprof23 << 23)); +} + +__INLINE uint8_t ble_swprofiling_swprof22_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00400000)) >> 22); +} + +__INLINE void ble_swprofiling_swprof22_setf(uint8_t swprof22) +{ + BLE_ASSERT_ERR((((uint32_t)swprof22 << 22) & ~((uint32_t)0x00400000)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x00400000)) | ((uint32_t)swprof22 << 22)); +} + +__INLINE uint8_t ble_swprofiling_swprof21_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00200000)) >> 21); +} + +__INLINE void ble_swprofiling_swprof21_setf(uint8_t swprof21) +{ + BLE_ASSERT_ERR((((uint32_t)swprof21 << 21) & ~((uint32_t)0x00200000)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x00200000)) | ((uint32_t)swprof21 << 21)); +} + +__INLINE uint8_t ble_swprofiling_swprof20_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00100000)) >> 20); +} + +__INLINE void ble_swprofiling_swprof20_setf(uint8_t swprof20) +{ + BLE_ASSERT_ERR((((uint32_t)swprof20 << 20) & ~((uint32_t)0x00100000)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x00100000)) | ((uint32_t)swprof20 << 20)); +} + +__INLINE uint8_t ble_swprofiling_swprof19_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00080000)) >> 19); +} + +__INLINE void ble_swprofiling_swprof19_setf(uint8_t swprof19) +{ + BLE_ASSERT_ERR((((uint32_t)swprof19 << 19) & ~((uint32_t)0x00080000)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x00080000)) | ((uint32_t)swprof19 << 19)); +} + +__INLINE uint8_t ble_swprofiling_swprof18_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00040000)) >> 18); +} + +__INLINE void ble_swprofiling_swprof18_setf(uint8_t swprof18) +{ + BLE_ASSERT_ERR((((uint32_t)swprof18 << 18) & ~((uint32_t)0x00040000)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x00040000)) | ((uint32_t)swprof18 << 18)); +} + +__INLINE uint8_t ble_swprofiling_swprof17_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00020000)) >> 17); +} + +__INLINE void ble_swprofiling_swprof17_setf(uint8_t swprof17) +{ + BLE_ASSERT_ERR((((uint32_t)swprof17 << 17) & ~((uint32_t)0x00020000)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x00020000)) | ((uint32_t)swprof17 << 17)); +} + +__INLINE uint8_t ble_swprofiling_swprof16_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00010000)) >> 16); +} + +__INLINE void ble_swprofiling_swprof16_setf(uint8_t swprof16) +{ + BLE_ASSERT_ERR((((uint32_t)swprof16 << 16) & ~((uint32_t)0x00010000)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x00010000)) | ((uint32_t)swprof16 << 16)); +} + +__INLINE uint8_t ble_swprofiling_swprof15_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00008000)) >> 15); +} + +__INLINE void ble_swprofiling_swprof15_setf(uint8_t swprof15) +{ + BLE_ASSERT_ERR((((uint32_t)swprof15 << 15) & ~((uint32_t)0x00008000)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x00008000)) | ((uint32_t)swprof15 << 15)); +} + +__INLINE uint8_t ble_swprofiling_swprof14_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00004000)) >> 14); +} + +__INLINE void ble_swprofiling_swprof14_setf(uint8_t swprof14) +{ + BLE_ASSERT_ERR((((uint32_t)swprof14 << 14) & ~((uint32_t)0x00004000)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x00004000)) | ((uint32_t)swprof14 << 14)); +} + +__INLINE uint8_t ble_swprofiling_swprof13_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00002000)) >> 13); +} + +__INLINE void ble_swprofiling_swprof13_setf(uint8_t swprof13) +{ + BLE_ASSERT_ERR((((uint32_t)swprof13 << 13) & ~((uint32_t)0x00002000)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x00002000)) | ((uint32_t)swprof13 << 13)); +} + +__INLINE uint8_t ble_swprofiling_swprof12_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00001000)) >> 12); +} + +__INLINE void ble_swprofiling_swprof12_setf(uint8_t swprof12) +{ + BLE_ASSERT_ERR((((uint32_t)swprof12 << 12) & ~((uint32_t)0x00001000)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x00001000)) | ((uint32_t)swprof12 << 12)); +} + +__INLINE uint8_t ble_swprofiling_swprof11_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000800)) >> 11); +} + +__INLINE void ble_swprofiling_swprof11_setf(uint8_t swprof11) +{ + BLE_ASSERT_ERR((((uint32_t)swprof11 << 11) & ~((uint32_t)0x00000800)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x00000800)) | ((uint32_t)swprof11 << 11)); +} + +__INLINE uint8_t ble_swprofiling_swprof10_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000400)) >> 10); +} + +__INLINE void ble_swprofiling_swprof10_setf(uint8_t swprof10) +{ + BLE_ASSERT_ERR((((uint32_t)swprof10 << 10) & ~((uint32_t)0x00000400)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x00000400)) | ((uint32_t)swprof10 << 10)); +} + +__INLINE uint8_t ble_swprofiling_swprof9_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000200)) >> 9); +} + +__INLINE void ble_swprofiling_swprof9_setf(uint8_t swprof9) +{ + BLE_ASSERT_ERR((((uint32_t)swprof9 << 9) & ~((uint32_t)0x00000200)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x00000200)) | ((uint32_t)swprof9 << 9)); +} + +__INLINE uint8_t ble_swprofiling_swprof8_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000100)) >> 8); +} + +__INLINE void ble_swprofiling_swprof8_setf(uint8_t swprof8) +{ + BLE_ASSERT_ERR((((uint32_t)swprof8 << 8) & ~((uint32_t)0x00000100)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x00000100)) | ((uint32_t)swprof8 << 8)); +} + +__INLINE uint8_t ble_swprofiling_swprof7_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000080)) >> 7); +} + +__INLINE void ble_swprofiling_swprof7_setf(uint8_t swprof7) +{ + BLE_ASSERT_ERR((((uint32_t)swprof7 << 7) & ~((uint32_t)0x00000080)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x00000080)) | ((uint32_t)swprof7 << 7)); +} + +__INLINE uint8_t ble_swprofiling_swprof6_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000040)) >> 6); +} + +__INLINE void ble_swprofiling_swprof6_setf(uint8_t swprof6) +{ + BLE_ASSERT_ERR((((uint32_t)swprof6 << 6) & ~((uint32_t)0x00000040)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x00000040)) | ((uint32_t)swprof6 << 6)); +} + +__INLINE uint8_t ble_swprofiling_swprof5_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +__INLINE void ble_swprofiling_swprof5_setf(uint8_t swprof5) +{ + BLE_ASSERT_ERR((((uint32_t)swprof5 << 5) & ~((uint32_t)0x00000020)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x00000020)) | ((uint32_t)swprof5 << 5)); +} + +__INLINE uint8_t ble_swprofiling_swprof4_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +__INLINE void ble_swprofiling_swprof4_setf(uint8_t swprof4) +{ + BLE_ASSERT_ERR((((uint32_t)swprof4 << 4) & ~((uint32_t)0x00000010)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x00000010)) | ((uint32_t)swprof4 << 4)); +} + +__INLINE uint8_t ble_swprofiling_swprof3_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +__INLINE void ble_swprofiling_swprof3_setf(uint8_t swprof3) +{ + BLE_ASSERT_ERR((((uint32_t)swprof3 << 3) & ~((uint32_t)0x00000008)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x00000008)) | ((uint32_t)swprof3 << 3)); +} + +__INLINE uint8_t ble_swprofiling_swprof2_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +__INLINE void ble_swprofiling_swprof2_setf(uint8_t swprof2) +{ + BLE_ASSERT_ERR((((uint32_t)swprof2 << 2) & ~((uint32_t)0x00000004)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x00000004)) | ((uint32_t)swprof2 << 2)); +} + +__INLINE uint8_t ble_swprofiling_swprof1_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +__INLINE void ble_swprofiling_swprof1_setf(uint8_t swprof1) +{ + BLE_ASSERT_ERR((((uint32_t)swprof1 << 1) & ~((uint32_t)0x00000002)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x00000002)) | ((uint32_t)swprof1 << 1)); +} + +__INLINE uint8_t ble_swprofiling_swprof0_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +__INLINE void ble_swprofiling_swprof0_setf(uint8_t swprof0) +{ + BLE_ASSERT_ERR((((uint32_t)swprof0 << 0) & ~((uint32_t)0x00000001)) == 0); + REG_BLE_WR(BLE_SWPROFILING_ADDR, (REG_BLE_RD(BLE_SWPROFILING_ADDR) & ~((uint32_t)0x00000001)) | ((uint32_t)swprof0 << 0)); +} + +/** + * @brief RADIOCNTL0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  29:16               SPIPTR   0x0
+ *     07               SPICFG   0
+ *  05:04              SPIFREQ   0x0
+ *     01              SPICOMP   1
+ *     00                SPIGO   0
+ * 
+ */ +#define BLE_RADIOCNTL0_ADDR 0x00900870 +#define BLE_RADIOCNTL0_OFFSET 0x00000070 +#define BLE_RADIOCNTL0_INDEX 0x0000001C +#define BLE_RADIOCNTL0_RESET 0x00000002 + +__INLINE uint32_t ble_radiocntl0_get(void) +{ + return REG_BLE_RD(BLE_RADIOCNTL0_ADDR); +} + +__INLINE void ble_radiocntl0_set(uint32_t value) +{ + REG_BLE_WR(BLE_RADIOCNTL0_ADDR, value); +} + +// field definitions +#define BLE_SPIPTR_MASK ((uint32_t)0x3FFF0000) +#define BLE_SPIPTR_LSB 16 +#define BLE_SPIPTR_WIDTH ((uint32_t)0x0000000E) +#define BLE_SPICFG_BIT ((uint32_t)0x00000080) +#define BLE_SPICFG_POS 7 +#define BLE_SPIFREQ_MASK ((uint32_t)0x00000030) +#define BLE_SPIFREQ_LSB 4 +#define BLE_SPIFREQ_WIDTH ((uint32_t)0x00000002) +#define BLE_SPICOMP_BIT ((uint32_t)0x00000002) +#define BLE_SPICOMP_POS 1 +#define BLE_SPIGO_BIT ((uint32_t)0x00000001) +#define BLE_SPIGO_POS 0 + +#define BLE_SPIPTR_RST 0x0 +#define BLE_SPICFG_RST 0x0 +#define BLE_SPIFREQ_RST 0x0 +#define BLE_SPICOMP_RST 0x1 +#define BLE_SPIGO_RST 0x0 + +__INLINE void ble_radiocntl0_pack(uint16_t spiptr, uint8_t spicfg, uint8_t spifreq, uint8_t spigo) +{ + BLE_ASSERT_ERR((((uint32_t)spiptr << 16) & ~((uint32_t)0x3FFF0000)) == 0); + BLE_ASSERT_ERR((((uint32_t)spicfg << 7) & ~((uint32_t)0x00000080)) == 0); + BLE_ASSERT_ERR((((uint32_t)spifreq << 4) & ~((uint32_t)0x00000030)) == 0); + BLE_ASSERT_ERR((((uint32_t)spigo << 0) & ~((uint32_t)0x00000001)) == 0); + REG_BLE_WR(BLE_RADIOCNTL0_ADDR, ((uint32_t)spiptr << 16) | ((uint32_t)spicfg << 7) | ((uint32_t)spifreq << 4) | ((uint32_t)spigo << 0)); +} + +__INLINE void ble_radiocntl0_unpack(uint16_t* spiptr, uint8_t* spicfg, uint8_t* spifreq, uint8_t* spicomp, uint8_t* spigo) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL0_ADDR); + + *spiptr = (localVal & ((uint32_t)0x3FFF0000)) >> 16; + *spicfg = (localVal & ((uint32_t)0x00000080)) >> 7; + *spifreq = (localVal & ((uint32_t)0x00000030)) >> 4; + *spicomp = (localVal & ((uint32_t)0x00000002)) >> 1; + *spigo = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +__INLINE uint16_t ble_radiocntl0_spiptr_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL0_ADDR); + return ((localVal & ((uint32_t)0x3FFF0000)) >> 16); +} + +__INLINE void ble_radiocntl0_spiptr_setf(uint16_t spiptr) +{ + BLE_ASSERT_ERR((((uint32_t)spiptr << 16) & ~((uint32_t)0x3FFF0000)) == 0); + REG_BLE_WR(BLE_RADIOCNTL0_ADDR, (REG_BLE_RD(BLE_RADIOCNTL0_ADDR) & ~((uint32_t)0x3FFF0000)) | ((uint32_t)spiptr << 16)); +} + +__INLINE uint8_t ble_radiocntl0_spicfg_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL0_ADDR); + return ((localVal & ((uint32_t)0x00000080)) >> 7); +} + +__INLINE void ble_radiocntl0_spicfg_setf(uint8_t spicfg) +{ + BLE_ASSERT_ERR((((uint32_t)spicfg << 7) & ~((uint32_t)0x00000080)) == 0); + REG_BLE_WR(BLE_RADIOCNTL0_ADDR, (REG_BLE_RD(BLE_RADIOCNTL0_ADDR) & ~((uint32_t)0x00000080)) | ((uint32_t)spicfg << 7)); +} + +__INLINE uint8_t ble_radiocntl0_spifreq_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL0_ADDR); + return ((localVal & ((uint32_t)0x00000030)) >> 4); +} + +__INLINE void ble_radiocntl0_spifreq_setf(uint8_t spifreq) +{ + BLE_ASSERT_ERR((((uint32_t)spifreq << 4) & ~((uint32_t)0x00000030)) == 0); + REG_BLE_WR(BLE_RADIOCNTL0_ADDR, (REG_BLE_RD(BLE_RADIOCNTL0_ADDR) & ~((uint32_t)0x00000030)) | ((uint32_t)spifreq << 4)); +} + +__INLINE uint8_t ble_radiocntl0_spicomp_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL0_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +__INLINE uint8_t ble_radiocntl0_spigo_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL0_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +__INLINE void ble_radiocntl0_spigo_setf(uint8_t spigo) +{ + BLE_ASSERT_ERR((((uint32_t)spigo << 0) & ~((uint32_t)0x00000001)) == 0); + REG_BLE_WR(BLE_RADIOCNTL0_ADDR, (REG_BLE_RD(BLE_RADIOCNTL0_ADDR) & ~((uint32_t)0x00000001)) | ((uint32_t)spigo << 0)); +} + +/** + * @brief RADIOCNTL1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31          FORCEAGC_EN   0
+ *     30              FORCEIQ   0
+ *     29               RXDNSL   0
+ *     28               TXDNSL   0
+ *  27:16      FORCEAGC_LENGTH   0x0
+ *     15      SYNC_PULSE_MODE   0
+ *     14       SYNC_PULSE_SRC   0
+ *     13            DPCORR_EN   0
+ *     12           JEF_SELECT   0
+ *  09:04               XRFSEL   0x0
+ *  03:00           SUBVERSION   0x0
+ * 
+ */ +#define BLE_RADIOCNTL1_ADDR 0x00900874 +#define BLE_RADIOCNTL1_OFFSET 0x00000074 +#define BLE_RADIOCNTL1_INDEX 0x0000001D +#define BLE_RADIOCNTL1_RESET 0x00000000 + +__INLINE uint32_t ble_radiocntl1_get(void) +{ + return REG_BLE_RD(BLE_RADIOCNTL1_ADDR); +} + +__INLINE void ble_radiocntl1_set(uint32_t value) +{ + REG_BLE_WR(BLE_RADIOCNTL1_ADDR, value); +} + +// field definitions +#define BLE_FORCEAGC_EN_BIT ((uint32_t)0x80000000) +#define BLE_FORCEAGC_EN_POS 31 +#define BLE_FORCEIQ_BIT ((uint32_t)0x40000000) +#define BLE_FORCEIQ_POS 30 +#define BLE_RXDNSL_BIT ((uint32_t)0x20000000) +#define BLE_RXDNSL_POS 29 +#define BLE_TXDNSL_BIT ((uint32_t)0x10000000) +#define BLE_TXDNSL_POS 28 +#define BLE_FORCEAGC_LENGTH_MASK ((uint32_t)0x0FFF0000) +#define BLE_FORCEAGC_LENGTH_LSB 16 +#define BLE_FORCEAGC_LENGTH_WIDTH ((uint32_t)0x0000000C) +#define BLE_SYNC_PULSE_MODE_BIT ((uint32_t)0x00008000) +#define BLE_SYNC_PULSE_MODE_POS 15 +#define BLE_SYNC_PULSE_SRC_BIT ((uint32_t)0x00004000) +#define BLE_SYNC_PULSE_SRC_POS 14 +#define BLE_DPCORR_EN_BIT ((uint32_t)0x00002000) +#define BLE_DPCORR_EN_POS 13 +#define BLE_JEF_SELECT_BIT ((uint32_t)0x00001000) +#define BLE_JEF_SELECT_POS 12 +#define BLE_XRFSEL_MASK ((uint32_t)0x000003F0) +#define BLE_XRFSEL_LSB 4 +#define BLE_XRFSEL_WIDTH ((uint32_t)0x00000006) +#define BLE_SUBVERSION_MASK ((uint32_t)0x0000000F) +#define BLE_SUBVERSION_LSB 0 +#define BLE_SUBVERSION_WIDTH ((uint32_t)0x00000004) + +#define BLE_FORCEAGC_EN_RST 0x0 +#define BLE_FORCEIQ_RST 0x0 +#define BLE_RXDNSL_RST 0x0 +#define BLE_TXDNSL_RST 0x0 +#define BLE_FORCEAGC_LENGTH_RST 0x0 +#define BLE_SYNC_PULSE_MODE_RST 0x0 +#define BLE_SYNC_PULSE_SRC_RST 0x0 +#define BLE_DPCORR_EN_RST 0x0 +#define BLE_JEF_SELECT_RST 0x0 +#define BLE_XRFSEL_RST 0x0 +#define BLE_SUBVERSION_RST 0x0 + +__INLINE void ble_radiocntl1_pack(uint8_t forceagcen, uint8_t forceiq, uint8_t rxdnsl, uint8_t txdnsl, uint16_t forceagclength, uint8_t syncpulsemode, uint8_t syncpulsesrc, uint8_t dpcorren, uint8_t jefselect, uint8_t xrfsel, uint8_t subversion) +{ + BLE_ASSERT_ERR((((uint32_t)forceagcen << 31) & ~((uint32_t)0x80000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)forceiq << 30) & ~((uint32_t)0x40000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)rxdnsl << 29) & ~((uint32_t)0x20000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)txdnsl << 28) & ~((uint32_t)0x10000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)forceagclength << 16) & ~((uint32_t)0x0FFF0000)) == 0); + BLE_ASSERT_ERR((((uint32_t)syncpulsemode << 15) & ~((uint32_t)0x00008000)) == 0); + BLE_ASSERT_ERR((((uint32_t)syncpulsesrc << 14) & ~((uint32_t)0x00004000)) == 0); + BLE_ASSERT_ERR((((uint32_t)dpcorren << 13) & ~((uint32_t)0x00002000)) == 0); + BLE_ASSERT_ERR((((uint32_t)jefselect << 12) & ~((uint32_t)0x00001000)) == 0); + BLE_ASSERT_ERR((((uint32_t)xrfsel << 4) & ~((uint32_t)0x000003F0)) == 0); + BLE_ASSERT_ERR((((uint32_t)subversion << 0) & ~((uint32_t)0x0000000F)) == 0); + REG_BLE_WR(BLE_RADIOCNTL1_ADDR, ((uint32_t)forceagcen << 31) | ((uint32_t)forceiq << 30) | ((uint32_t)rxdnsl << 29) | ((uint32_t)txdnsl << 28) | ((uint32_t)forceagclength << 16) | ((uint32_t)syncpulsemode << 15) | ((uint32_t)syncpulsesrc << 14) | ((uint32_t)dpcorren << 13) | ((uint32_t)jefselect << 12) | ((uint32_t)xrfsel << 4) | ((uint32_t)subversion << 0)); +} + +__INLINE void ble_radiocntl1_unpack(uint8_t* forceagcen, uint8_t* forceiq, uint8_t* rxdnsl, uint8_t* txdnsl, uint16_t* forceagclength, uint8_t* syncpulsemode, uint8_t* syncpulsesrc, uint8_t* dpcorren, uint8_t* jefselect, uint8_t* xrfsel, uint8_t* subversion) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL1_ADDR); + + *forceagcen = (localVal & ((uint32_t)0x80000000)) >> 31; + *forceiq = (localVal & ((uint32_t)0x40000000)) >> 30; + *rxdnsl = (localVal & ((uint32_t)0x20000000)) >> 29; + *txdnsl = (localVal & ((uint32_t)0x10000000)) >> 28; + *forceagclength = (localVal & ((uint32_t)0x0FFF0000)) >> 16; + *syncpulsemode = (localVal & ((uint32_t)0x00008000)) >> 15; + *syncpulsesrc = (localVal & ((uint32_t)0x00004000)) >> 14; + *dpcorren = (localVal & ((uint32_t)0x00002000)) >> 13; + *jefselect = (localVal & ((uint32_t)0x00001000)) >> 12; + *xrfsel = (localVal & ((uint32_t)0x000003F0)) >> 4; + *subversion = (localVal & ((uint32_t)0x0000000F)) >> 0; +} + +__INLINE uint8_t ble_radiocntl1_forceagc_en_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL1_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +__INLINE void ble_radiocntl1_forceagc_en_setf(uint8_t forceagcen) +{ + BLE_ASSERT_ERR((((uint32_t)forceagcen << 31) & ~((uint32_t)0x80000000)) == 0); + REG_BLE_WR(BLE_RADIOCNTL1_ADDR, (REG_BLE_RD(BLE_RADIOCNTL1_ADDR) & ~((uint32_t)0x80000000)) | ((uint32_t)forceagcen << 31)); +} + +__INLINE uint8_t ble_radiocntl1_forceiq_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL1_ADDR); + return ((localVal & ((uint32_t)0x40000000)) >> 30); +} + +__INLINE void ble_radiocntl1_forceiq_setf(uint8_t forceiq) +{ + BLE_ASSERT_ERR((((uint32_t)forceiq << 30) & ~((uint32_t)0x40000000)) == 0); + REG_BLE_WR(BLE_RADIOCNTL1_ADDR, (REG_BLE_RD(BLE_RADIOCNTL1_ADDR) & ~((uint32_t)0x40000000)) | ((uint32_t)forceiq << 30)); +} + +__INLINE uint8_t ble_radiocntl1_rxdnsl_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL1_ADDR); + return ((localVal & ((uint32_t)0x20000000)) >> 29); +} + +__INLINE void ble_radiocntl1_rxdnsl_setf(uint8_t rxdnsl) +{ + BLE_ASSERT_ERR((((uint32_t)rxdnsl << 29) & ~((uint32_t)0x20000000)) == 0); + REG_BLE_WR(BLE_RADIOCNTL1_ADDR, (REG_BLE_RD(BLE_RADIOCNTL1_ADDR) & ~((uint32_t)0x20000000)) | ((uint32_t)rxdnsl << 29)); +} + +__INLINE uint8_t ble_radiocntl1_txdnsl_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL1_ADDR); + return ((localVal & ((uint32_t)0x10000000)) >> 28); +} + +__INLINE void ble_radiocntl1_txdnsl_setf(uint8_t txdnsl) +{ + BLE_ASSERT_ERR((((uint32_t)txdnsl << 28) & ~((uint32_t)0x10000000)) == 0); + REG_BLE_WR(BLE_RADIOCNTL1_ADDR, (REG_BLE_RD(BLE_RADIOCNTL1_ADDR) & ~((uint32_t)0x10000000)) | ((uint32_t)txdnsl << 28)); +} + +__INLINE uint16_t ble_radiocntl1_forceagc_length_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL1_ADDR); + return ((localVal & ((uint32_t)0x0FFF0000)) >> 16); +} + +__INLINE void ble_radiocntl1_forceagc_length_setf(uint16_t forceagclength) +{ + BLE_ASSERT_ERR((((uint32_t)forceagclength << 16) & ~((uint32_t)0x0FFF0000)) == 0); + REG_BLE_WR(BLE_RADIOCNTL1_ADDR, (REG_BLE_RD(BLE_RADIOCNTL1_ADDR) & ~((uint32_t)0x0FFF0000)) | ((uint32_t)forceagclength << 16)); +} + +__INLINE uint8_t ble_radiocntl1_sync_pulse_mode_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL1_ADDR); + return ((localVal & ((uint32_t)0x00008000)) >> 15); +} + +__INLINE void ble_radiocntl1_sync_pulse_mode_setf(uint8_t syncpulsemode) +{ + BLE_ASSERT_ERR((((uint32_t)syncpulsemode << 15) & ~((uint32_t)0x00008000)) == 0); + REG_BLE_WR(BLE_RADIOCNTL1_ADDR, (REG_BLE_RD(BLE_RADIOCNTL1_ADDR) & ~((uint32_t)0x00008000)) | ((uint32_t)syncpulsemode << 15)); +} + +__INLINE uint8_t ble_radiocntl1_sync_pulse_src_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL1_ADDR); + return ((localVal & ((uint32_t)0x00004000)) >> 14); +} + +__INLINE void ble_radiocntl1_sync_pulse_src_setf(uint8_t syncpulsesrc) +{ + BLE_ASSERT_ERR((((uint32_t)syncpulsesrc << 14) & ~((uint32_t)0x00004000)) == 0); + REG_BLE_WR(BLE_RADIOCNTL1_ADDR, (REG_BLE_RD(BLE_RADIOCNTL1_ADDR) & ~((uint32_t)0x00004000)) | ((uint32_t)syncpulsesrc << 14)); +} + +__INLINE uint8_t ble_radiocntl1_dpcorr_en_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL1_ADDR); + return ((localVal & ((uint32_t)0x00002000)) >> 13); +} + +__INLINE void ble_radiocntl1_dpcorr_en_setf(uint8_t dpcorren) +{ + BLE_ASSERT_ERR((((uint32_t)dpcorren << 13) & ~((uint32_t)0x00002000)) == 0); + REG_BLE_WR(BLE_RADIOCNTL1_ADDR, (REG_BLE_RD(BLE_RADIOCNTL1_ADDR) & ~((uint32_t)0x00002000)) | ((uint32_t)dpcorren << 13)); +} + +__INLINE uint8_t ble_radiocntl1_jef_select_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL1_ADDR); + return ((localVal & ((uint32_t)0x00001000)) >> 12); +} + +__INLINE void ble_radiocntl1_jef_select_setf(uint8_t jefselect) +{ + BLE_ASSERT_ERR((((uint32_t)jefselect << 12) & ~((uint32_t)0x00001000)) == 0); + REG_BLE_WR(BLE_RADIOCNTL1_ADDR, (REG_BLE_RD(BLE_RADIOCNTL1_ADDR) & ~((uint32_t)0x00001000)) | ((uint32_t)jefselect << 12)); +} + +__INLINE uint8_t ble_radiocntl1_xrfsel_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL1_ADDR); + return ((localVal & ((uint32_t)0x000003F0)) >> 4); +} + +__INLINE void ble_radiocntl1_xrfsel_setf(uint8_t xrfsel) +{ + BLE_ASSERT_ERR((((uint32_t)xrfsel << 4) & ~((uint32_t)0x000003F0)) == 0); + REG_BLE_WR(BLE_RADIOCNTL1_ADDR, (REG_BLE_RD(BLE_RADIOCNTL1_ADDR) & ~((uint32_t)0x000003F0)) | ((uint32_t)xrfsel << 4)); +} + +__INLINE uint8_t ble_radiocntl1_subversion_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL1_ADDR); + return ((localVal & ((uint32_t)0x0000000F)) >> 0); +} + +__INLINE void ble_radiocntl1_subversion_setf(uint8_t subversion) +{ + BLE_ASSERT_ERR((((uint32_t)subversion << 0) & ~((uint32_t)0x0000000F)) == 0); + REG_BLE_WR(BLE_RADIOCNTL1_ADDR, (REG_BLE_RD(BLE_RADIOCNTL1_ADDR) & ~((uint32_t)0x0000000F)) | ((uint32_t)subversion << 0)); +} + +/** + * @brief RADIOCNTL2 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:30       LRSYNCCOMPMODE   0x3
+ *     29       RXCITERMBYPASS   0
+ *  28:24           LRVTBFLUSH   0x8
+ *  23:22               PHYMSK   0x0
+ *  21:20            LRSYNCERR   0x0
+ *  18:16              SYNCERR   0x0
+ *  13:00        FREQTABLE_PTR   0x40
+ * 
+ */ +#define BLE_RADIOCNTL2_ADDR 0x00900878 +#define BLE_RADIOCNTL2_OFFSET 0x00000078 +#define BLE_RADIOCNTL2_INDEX 0x0000001E +#define BLE_RADIOCNTL2_RESET 0xC8000040 + +__INLINE uint32_t ble_radiocntl2_get(void) +{ + return REG_BLE_RD(BLE_RADIOCNTL2_ADDR); +} + +__INLINE void ble_radiocntl2_set(uint32_t value) +{ + REG_BLE_WR(BLE_RADIOCNTL2_ADDR, value); +} + +// field definitions +#define BLE_LRSYNCCOMPMODE_MASK ((uint32_t)0xC0000000) +#define BLE_LRSYNCCOMPMODE_LSB 30 +#define BLE_LRSYNCCOMPMODE_WIDTH ((uint32_t)0x00000002) +#define BLE_RXCITERMBYPASS_BIT ((uint32_t)0x20000000) +#define BLE_RXCITERMBYPASS_POS 29 +#define BLE_LRVTBFLUSH_MASK ((uint32_t)0x1F000000) +#define BLE_LRVTBFLUSH_LSB 24 +#define BLE_LRVTBFLUSH_WIDTH ((uint32_t)0x00000005) +#define BLE_PHYMSK_MASK ((uint32_t)0x00C00000) +#define BLE_PHYMSK_LSB 22 +#define BLE_PHYMSK_WIDTH ((uint32_t)0x00000002) +#define BLE_LRSYNCERR_MASK ((uint32_t)0x00300000) +#define BLE_LRSYNCERR_LSB 20 +#define BLE_LRSYNCERR_WIDTH ((uint32_t)0x00000002) +#define BLE_SYNCERR_MASK ((uint32_t)0x00070000) +#define BLE_SYNCERR_LSB 16 +#define BLE_SYNCERR_WIDTH ((uint32_t)0x00000003) +#define BLE_FREQTABLE_PTR_MASK ((uint32_t)0x00003FFF) +#define BLE_FREQTABLE_PTR_LSB 0 +#define BLE_FREQTABLE_PTR_WIDTH ((uint32_t)0x0000000E) + +#define BLE_LRSYNCCOMPMODE_RST 0x3 +#define BLE_RXCITERMBYPASS_RST 0x0 +#define BLE_LRVTBFLUSH_RST 0x8 +#define BLE_PHYMSK_RST 0x0 +#define BLE_LRSYNCERR_RST 0x0 +#define BLE_SYNCERR_RST 0x0 +#define BLE_FREQTABLE_PTR_RST 0x40 + +__INLINE void ble_radiocntl2_pack(uint8_t lrsynccompmode, uint8_t rxcitermbypass, uint8_t lrvtbflush, uint8_t phymsk, uint8_t lrsyncerr, uint8_t syncerr, uint16_t freqtableptr) +{ + BLE_ASSERT_ERR((((uint32_t)lrsynccompmode << 30) & ~((uint32_t)0xC0000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)rxcitermbypass << 29) & ~((uint32_t)0x20000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)lrvtbflush << 24) & ~((uint32_t)0x1F000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)phymsk << 22) & ~((uint32_t)0x00C00000)) == 0); + BLE_ASSERT_ERR((((uint32_t)lrsyncerr << 20) & ~((uint32_t)0x00300000)) == 0); + BLE_ASSERT_ERR((((uint32_t)syncerr << 16) & ~((uint32_t)0x00070000)) == 0); + BLE_ASSERT_ERR((((uint32_t)freqtableptr << 0) & ~((uint32_t)0x00003FFF)) == 0); + REG_BLE_WR(BLE_RADIOCNTL2_ADDR, ((uint32_t)lrsynccompmode << 30) | ((uint32_t)rxcitermbypass << 29) | ((uint32_t)lrvtbflush << 24) | ((uint32_t)phymsk << 22) | ((uint32_t)lrsyncerr << 20) | ((uint32_t)syncerr << 16) | ((uint32_t)freqtableptr << 0)); +} + +__INLINE void ble_radiocntl2_unpack(uint8_t* lrsynccompmode, uint8_t* rxcitermbypass, uint8_t* lrvtbflush, uint8_t* phymsk, uint8_t* lrsyncerr, uint8_t* syncerr, uint16_t* freqtableptr) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL2_ADDR); + + *lrsynccompmode = (localVal & ((uint32_t)0xC0000000)) >> 30; + *rxcitermbypass = (localVal & ((uint32_t)0x20000000)) >> 29; + *lrvtbflush = (localVal & ((uint32_t)0x1F000000)) >> 24; + *phymsk = (localVal & ((uint32_t)0x00C00000)) >> 22; + *lrsyncerr = (localVal & ((uint32_t)0x00300000)) >> 20; + *syncerr = (localVal & ((uint32_t)0x00070000)) >> 16; + *freqtableptr = (localVal & ((uint32_t)0x00003FFF)) >> 0; +} + +__INLINE uint8_t ble_radiocntl2_lrsynccompmode_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL2_ADDR); + return ((localVal & ((uint32_t)0xC0000000)) >> 30); +} + +__INLINE void ble_radiocntl2_lrsynccompmode_setf(uint8_t lrsynccompmode) +{ + BLE_ASSERT_ERR((((uint32_t)lrsynccompmode << 30) & ~((uint32_t)0xC0000000)) == 0); + REG_BLE_WR(BLE_RADIOCNTL2_ADDR, (REG_BLE_RD(BLE_RADIOCNTL2_ADDR) & ~((uint32_t)0xC0000000)) | ((uint32_t)lrsynccompmode << 30)); +} + +__INLINE uint8_t ble_radiocntl2_rxcitermbypass_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL2_ADDR); + return ((localVal & ((uint32_t)0x20000000)) >> 29); +} + +__INLINE void ble_radiocntl2_rxcitermbypass_setf(uint8_t rxcitermbypass) +{ + BLE_ASSERT_ERR((((uint32_t)rxcitermbypass << 29) & ~((uint32_t)0x20000000)) == 0); + REG_BLE_WR(BLE_RADIOCNTL2_ADDR, (REG_BLE_RD(BLE_RADIOCNTL2_ADDR) & ~((uint32_t)0x20000000)) | ((uint32_t)rxcitermbypass << 29)); +} + +__INLINE uint8_t ble_radiocntl2_lrvtbflush_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL2_ADDR); + return ((localVal & ((uint32_t)0x1F000000)) >> 24); +} + +__INLINE void ble_radiocntl2_lrvtbflush_setf(uint8_t lrvtbflush) +{ + BLE_ASSERT_ERR((((uint32_t)lrvtbflush << 24) & ~((uint32_t)0x1F000000)) == 0); + REG_BLE_WR(BLE_RADIOCNTL2_ADDR, (REG_BLE_RD(BLE_RADIOCNTL2_ADDR) & ~((uint32_t)0x1F000000)) | ((uint32_t)lrvtbflush << 24)); +} + +__INLINE uint8_t ble_radiocntl2_phymsk_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL2_ADDR); + return ((localVal & ((uint32_t)0x00C00000)) >> 22); +} + +__INLINE void ble_radiocntl2_phymsk_setf(uint8_t phymsk) +{ + BLE_ASSERT_ERR((((uint32_t)phymsk << 22) & ~((uint32_t)0x00C00000)) == 0); + REG_BLE_WR(BLE_RADIOCNTL2_ADDR, (REG_BLE_RD(BLE_RADIOCNTL2_ADDR) & ~((uint32_t)0x00C00000)) | ((uint32_t)phymsk << 22)); +} + +__INLINE uint8_t ble_radiocntl2_lrsyncerr_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL2_ADDR); + return ((localVal & ((uint32_t)0x00300000)) >> 20); +} + +__INLINE void ble_radiocntl2_lrsyncerr_setf(uint8_t lrsyncerr) +{ + BLE_ASSERT_ERR((((uint32_t)lrsyncerr << 20) & ~((uint32_t)0x00300000)) == 0); + REG_BLE_WR(BLE_RADIOCNTL2_ADDR, (REG_BLE_RD(BLE_RADIOCNTL2_ADDR) & ~((uint32_t)0x00300000)) | ((uint32_t)lrsyncerr << 20)); +} + +__INLINE uint8_t ble_radiocntl2_syncerr_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL2_ADDR); + return ((localVal & ((uint32_t)0x00070000)) >> 16); +} + +__INLINE void ble_radiocntl2_syncerr_setf(uint8_t syncerr) +{ + BLE_ASSERT_ERR((((uint32_t)syncerr << 16) & ~((uint32_t)0x00070000)) == 0); + REG_BLE_WR(BLE_RADIOCNTL2_ADDR, (REG_BLE_RD(BLE_RADIOCNTL2_ADDR) & ~((uint32_t)0x00070000)) | ((uint32_t)syncerr << 16)); +} + +__INLINE uint16_t ble_radiocntl2_freqtable_ptr_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL2_ADDR); + return ((localVal & ((uint32_t)0x00003FFF)) >> 0); +} + +__INLINE void ble_radiocntl2_freqtable_ptr_setf(uint16_t freqtableptr) +{ + BLE_ASSERT_ERR((((uint32_t)freqtableptr << 0) & ~((uint32_t)0x00003FFF)) == 0); + REG_BLE_WR(BLE_RADIOCNTL2_ADDR, (REG_BLE_RD(BLE_RADIOCNTL2_ADDR) & ~((uint32_t)0x00003FFF)) | ((uint32_t)freqtableptr << 0)); +} + +/** + * @brief RADIOCNTL3 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:30           RXRATE3CFG   0x3
+ *  29:28           RXRATE2CFG   0x2
+ *  27:26           RXRATE1CFG   0x1
+ *  25:24           RXRATE0CFG   0x0
+ *  22:20         GETRSSIDELAY   0x4
+ *     18       RXSYNC_ROUTING   0
+ *  17:16          RXVALID_BEH   0x0
+ *  15:14           TXRATE3CFG   0x3
+ *  13:12           TXRATE2CFG   0x2
+ *  11:10           TXRATE1CFG   0x1
+ *  09:08           TXRATE0CFG   0x0
+ *  01:00          TXVALID_BEH   0x0
+ * 
+ */ +#define BLE_RADIOCNTL3_ADDR 0x0090087C +#define BLE_RADIOCNTL3_OFFSET 0x0000007C +#define BLE_RADIOCNTL3_INDEX 0x0000001F +#define BLE_RADIOCNTL3_RESET 0xE440E400 + +__INLINE uint32_t ble_radiocntl3_get(void) +{ + return REG_BLE_RD(BLE_RADIOCNTL3_ADDR); +} + +__INLINE void ble_radiocntl3_set(uint32_t value) +{ + REG_BLE_WR(BLE_RADIOCNTL3_ADDR, value); +} + +// field definitions +#define BLE_RXRATE3CFG_MASK ((uint32_t)0xC0000000) +#define BLE_RXRATE3CFG_LSB 30 +#define BLE_RXRATE3CFG_WIDTH ((uint32_t)0x00000002) +#define BLE_RXRATE2CFG_MASK ((uint32_t)0x30000000) +#define BLE_RXRATE2CFG_LSB 28 +#define BLE_RXRATE2CFG_WIDTH ((uint32_t)0x00000002) +#define BLE_RXRATE1CFG_MASK ((uint32_t)0x0C000000) +#define BLE_RXRATE1CFG_LSB 26 +#define BLE_RXRATE1CFG_WIDTH ((uint32_t)0x00000002) +#define BLE_RXRATE0CFG_MASK ((uint32_t)0x03000000) +#define BLE_RXRATE0CFG_LSB 24 +#define BLE_RXRATE0CFG_WIDTH ((uint32_t)0x00000002) +#define BLE_GETRSSIDELAY_MASK ((uint32_t)0x00700000) +#define BLE_GETRSSIDELAY_LSB 20 +#define BLE_GETRSSIDELAY_WIDTH ((uint32_t)0x00000003) +#define BLE_RXSYNC_ROUTING_BIT ((uint32_t)0x00040000) +#define BLE_RXSYNC_ROUTING_POS 18 +#define BLE_RXVALID_BEH_MASK ((uint32_t)0x00030000) +#define BLE_RXVALID_BEH_LSB 16 +#define BLE_RXVALID_BEH_WIDTH ((uint32_t)0x00000002) +#define BLE_TXRATE3CFG_MASK ((uint32_t)0x0000C000) +#define BLE_TXRATE3CFG_LSB 14 +#define BLE_TXRATE3CFG_WIDTH ((uint32_t)0x00000002) +#define BLE_TXRATE2CFG_MASK ((uint32_t)0x00003000) +#define BLE_TXRATE2CFG_LSB 12 +#define BLE_TXRATE2CFG_WIDTH ((uint32_t)0x00000002) +#define BLE_TXRATE1CFG_MASK ((uint32_t)0x00000C00) +#define BLE_TXRATE1CFG_LSB 10 +#define BLE_TXRATE1CFG_WIDTH ((uint32_t)0x00000002) +#define BLE_TXRATE0CFG_MASK ((uint32_t)0x00000300) +#define BLE_TXRATE0CFG_LSB 8 +#define BLE_TXRATE0CFG_WIDTH ((uint32_t)0x00000002) +#define BLE_TXVALID_BEH_MASK ((uint32_t)0x00000003) +#define BLE_TXVALID_BEH_LSB 0 +#define BLE_TXVALID_BEH_WIDTH ((uint32_t)0x00000002) + +#define BLE_RXRATE3CFG_RST 0x3 +#define BLE_RXRATE2CFG_RST 0x2 +#define BLE_RXRATE1CFG_RST 0x1 +#define BLE_RXRATE0CFG_RST 0x0 +#define BLE_GETRSSIDELAY_RST 0x4 +#define BLE_RXSYNC_ROUTING_RST 0x0 +#define BLE_RXVALID_BEH_RST 0x0 +#define BLE_TXRATE3CFG_RST 0x3 +#define BLE_TXRATE2CFG_RST 0x2 +#define BLE_TXRATE1CFG_RST 0x1 +#define BLE_TXRATE0CFG_RST 0x0 +#define BLE_TXVALID_BEH_RST 0x0 + +__INLINE void ble_radiocntl3_pack(uint8_t rxrate3cfg, uint8_t rxrate2cfg, uint8_t rxrate1cfg, uint8_t rxrate0cfg, uint8_t getrssidelay, uint8_t rxsyncrouting, uint8_t rxvalidbeh, uint8_t txrate3cfg, uint8_t txrate2cfg, uint8_t txrate1cfg, uint8_t txrate0cfg, uint8_t txvalidbeh) +{ + BLE_ASSERT_ERR((((uint32_t)rxrate3cfg << 30) & ~((uint32_t)0xC0000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)rxrate2cfg << 28) & ~((uint32_t)0x30000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)rxrate1cfg << 26) & ~((uint32_t)0x0C000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)rxrate0cfg << 24) & ~((uint32_t)0x03000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)getrssidelay << 20) & ~((uint32_t)0x00700000)) == 0); + BLE_ASSERT_ERR((((uint32_t)rxsyncrouting << 18) & ~((uint32_t)0x00040000)) == 0); + BLE_ASSERT_ERR((((uint32_t)rxvalidbeh << 16) & ~((uint32_t)0x00030000)) == 0); + BLE_ASSERT_ERR((((uint32_t)txrate3cfg << 14) & ~((uint32_t)0x0000C000)) == 0); + BLE_ASSERT_ERR((((uint32_t)txrate2cfg << 12) & ~((uint32_t)0x00003000)) == 0); + BLE_ASSERT_ERR((((uint32_t)txrate1cfg << 10) & ~((uint32_t)0x00000C00)) == 0); + BLE_ASSERT_ERR((((uint32_t)txrate0cfg << 8) & ~((uint32_t)0x00000300)) == 0); + BLE_ASSERT_ERR((((uint32_t)txvalidbeh << 0) & ~((uint32_t)0x00000003)) == 0); + REG_BLE_WR(BLE_RADIOCNTL3_ADDR, ((uint32_t)rxrate3cfg << 30) | ((uint32_t)rxrate2cfg << 28) | ((uint32_t)rxrate1cfg << 26) | ((uint32_t)rxrate0cfg << 24) | ((uint32_t)getrssidelay << 20) | ((uint32_t)rxsyncrouting << 18) | ((uint32_t)rxvalidbeh << 16) | ((uint32_t)txrate3cfg << 14) | ((uint32_t)txrate2cfg << 12) | ((uint32_t)txrate1cfg << 10) | ((uint32_t)txrate0cfg << 8) | ((uint32_t)txvalidbeh << 0)); +} + +__INLINE void ble_radiocntl3_unpack(uint8_t* rxrate3cfg, uint8_t* rxrate2cfg, uint8_t* rxrate1cfg, uint8_t* rxrate0cfg, uint8_t* getrssidelay, uint8_t* rxsyncrouting, uint8_t* rxvalidbeh, uint8_t* txrate3cfg, uint8_t* txrate2cfg, uint8_t* txrate1cfg, uint8_t* txrate0cfg, uint8_t* txvalidbeh) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL3_ADDR); + + *rxrate3cfg = (localVal & ((uint32_t)0xC0000000)) >> 30; + *rxrate2cfg = (localVal & ((uint32_t)0x30000000)) >> 28; + *rxrate1cfg = (localVal & ((uint32_t)0x0C000000)) >> 26; + *rxrate0cfg = (localVal & ((uint32_t)0x03000000)) >> 24; + *getrssidelay = (localVal & ((uint32_t)0x00700000)) >> 20; + *rxsyncrouting = (localVal & ((uint32_t)0x00040000)) >> 18; + *rxvalidbeh = (localVal & ((uint32_t)0x00030000)) >> 16; + *txrate3cfg = (localVal & ((uint32_t)0x0000C000)) >> 14; + *txrate2cfg = (localVal & ((uint32_t)0x00003000)) >> 12; + *txrate1cfg = (localVal & ((uint32_t)0x00000C00)) >> 10; + *txrate0cfg = (localVal & ((uint32_t)0x00000300)) >> 8; + *txvalidbeh = (localVal & ((uint32_t)0x00000003)) >> 0; +} + +__INLINE uint8_t ble_radiocntl3_rxrate3cfg_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL3_ADDR); + return ((localVal & ((uint32_t)0xC0000000)) >> 30); +} + +__INLINE void ble_radiocntl3_rxrate3cfg_setf(uint8_t rxrate3cfg) +{ + BLE_ASSERT_ERR((((uint32_t)rxrate3cfg << 30) & ~((uint32_t)0xC0000000)) == 0); + REG_BLE_WR(BLE_RADIOCNTL3_ADDR, (REG_BLE_RD(BLE_RADIOCNTL3_ADDR) & ~((uint32_t)0xC0000000)) | ((uint32_t)rxrate3cfg << 30)); +} + +__INLINE uint8_t ble_radiocntl3_rxrate2cfg_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL3_ADDR); + return ((localVal & ((uint32_t)0x30000000)) >> 28); +} + +__INLINE void ble_radiocntl3_rxrate2cfg_setf(uint8_t rxrate2cfg) +{ + BLE_ASSERT_ERR((((uint32_t)rxrate2cfg << 28) & ~((uint32_t)0x30000000)) == 0); + REG_BLE_WR(BLE_RADIOCNTL3_ADDR, (REG_BLE_RD(BLE_RADIOCNTL3_ADDR) & ~((uint32_t)0x30000000)) | ((uint32_t)rxrate2cfg << 28)); +} + +__INLINE uint8_t ble_radiocntl3_rxrate1cfg_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL3_ADDR); + return ((localVal & ((uint32_t)0x0C000000)) >> 26); +} + +__INLINE void ble_radiocntl3_rxrate1cfg_setf(uint8_t rxrate1cfg) +{ + BLE_ASSERT_ERR((((uint32_t)rxrate1cfg << 26) & ~((uint32_t)0x0C000000)) == 0); + REG_BLE_WR(BLE_RADIOCNTL3_ADDR, (REG_BLE_RD(BLE_RADIOCNTL3_ADDR) & ~((uint32_t)0x0C000000)) | ((uint32_t)rxrate1cfg << 26)); +} + +__INLINE uint8_t ble_radiocntl3_rxrate0cfg_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL3_ADDR); + return ((localVal & ((uint32_t)0x03000000)) >> 24); +} + +__INLINE void ble_radiocntl3_rxrate0cfg_setf(uint8_t rxrate0cfg) +{ + BLE_ASSERT_ERR((((uint32_t)rxrate0cfg << 24) & ~((uint32_t)0x03000000)) == 0); + REG_BLE_WR(BLE_RADIOCNTL3_ADDR, (REG_BLE_RD(BLE_RADIOCNTL3_ADDR) & ~((uint32_t)0x03000000)) | ((uint32_t)rxrate0cfg << 24)); +} + +__INLINE uint8_t ble_radiocntl3_getrssidelay_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL3_ADDR); + return ((localVal & ((uint32_t)0x00700000)) >> 20); +} + +__INLINE void ble_radiocntl3_getrssidelay_setf(uint8_t getrssidelay) +{ + BLE_ASSERT_ERR((((uint32_t)getrssidelay << 20) & ~((uint32_t)0x00700000)) == 0); + REG_BLE_WR(BLE_RADIOCNTL3_ADDR, (REG_BLE_RD(BLE_RADIOCNTL3_ADDR) & ~((uint32_t)0x00700000)) | ((uint32_t)getrssidelay << 20)); +} + +__INLINE uint8_t ble_radiocntl3_rxsync_routing_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL3_ADDR); + return ((localVal & ((uint32_t)0x00040000)) >> 18); +} + +__INLINE void ble_radiocntl3_rxsync_routing_setf(uint8_t rxsyncrouting) +{ + BLE_ASSERT_ERR((((uint32_t)rxsyncrouting << 18) & ~((uint32_t)0x00040000)) == 0); + REG_BLE_WR(BLE_RADIOCNTL3_ADDR, (REG_BLE_RD(BLE_RADIOCNTL3_ADDR) & ~((uint32_t)0x00040000)) | ((uint32_t)rxsyncrouting << 18)); +} + +__INLINE uint8_t ble_radiocntl3_rxvalid_beh_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL3_ADDR); + return ((localVal & ((uint32_t)0x00030000)) >> 16); +} + +__INLINE void ble_radiocntl3_rxvalid_beh_setf(uint8_t rxvalidbeh) +{ + BLE_ASSERT_ERR((((uint32_t)rxvalidbeh << 16) & ~((uint32_t)0x00030000)) == 0); + REG_BLE_WR(BLE_RADIOCNTL3_ADDR, (REG_BLE_RD(BLE_RADIOCNTL3_ADDR) & ~((uint32_t)0x00030000)) | ((uint32_t)rxvalidbeh << 16)); +} + +__INLINE uint8_t ble_radiocntl3_txrate3cfg_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL3_ADDR); + return ((localVal & ((uint32_t)0x0000C000)) >> 14); +} + +__INLINE void ble_radiocntl3_txrate3cfg_setf(uint8_t txrate3cfg) +{ + BLE_ASSERT_ERR((((uint32_t)txrate3cfg << 14) & ~((uint32_t)0x0000C000)) == 0); + REG_BLE_WR(BLE_RADIOCNTL3_ADDR, (REG_BLE_RD(BLE_RADIOCNTL3_ADDR) & ~((uint32_t)0x0000C000)) | ((uint32_t)txrate3cfg << 14)); +} + +__INLINE uint8_t ble_radiocntl3_txrate2cfg_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL3_ADDR); + return ((localVal & ((uint32_t)0x00003000)) >> 12); +} + +__INLINE void ble_radiocntl3_txrate2cfg_setf(uint8_t txrate2cfg) +{ + BLE_ASSERT_ERR((((uint32_t)txrate2cfg << 12) & ~((uint32_t)0x00003000)) == 0); + REG_BLE_WR(BLE_RADIOCNTL3_ADDR, (REG_BLE_RD(BLE_RADIOCNTL3_ADDR) & ~((uint32_t)0x00003000)) | ((uint32_t)txrate2cfg << 12)); +} + +__INLINE uint8_t ble_radiocntl3_txrate1cfg_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL3_ADDR); + return ((localVal & ((uint32_t)0x00000C00)) >> 10); +} + +__INLINE void ble_radiocntl3_txrate1cfg_setf(uint8_t txrate1cfg) +{ + BLE_ASSERT_ERR((((uint32_t)txrate1cfg << 10) & ~((uint32_t)0x00000C00)) == 0); + REG_BLE_WR(BLE_RADIOCNTL3_ADDR, (REG_BLE_RD(BLE_RADIOCNTL3_ADDR) & ~((uint32_t)0x00000C00)) | ((uint32_t)txrate1cfg << 10)); +} + +__INLINE uint8_t ble_radiocntl3_txrate0cfg_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL3_ADDR); + return ((localVal & ((uint32_t)0x00000300)) >> 8); +} + +__INLINE void ble_radiocntl3_txrate0cfg_setf(uint8_t txrate0cfg) +{ + BLE_ASSERT_ERR((((uint32_t)txrate0cfg << 8) & ~((uint32_t)0x00000300)) == 0); + REG_BLE_WR(BLE_RADIOCNTL3_ADDR, (REG_BLE_RD(BLE_RADIOCNTL3_ADDR) & ~((uint32_t)0x00000300)) | ((uint32_t)txrate0cfg << 8)); +} + +__INLINE uint8_t ble_radiocntl3_txvalid_beh_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOCNTL3_ADDR); + return ((localVal & ((uint32_t)0x00000003)) >> 0); +} + +__INLINE void ble_radiocntl3_txvalid_beh_setf(uint8_t txvalidbeh) +{ + BLE_ASSERT_ERR((((uint32_t)txvalidbeh << 0) & ~((uint32_t)0x00000003)) == 0); + REG_BLE_WR(BLE_RADIOCNTL3_ADDR, (REG_BLE_RD(BLE_RADIOCNTL3_ADDR) & ~((uint32_t)0x00000003)) | ((uint32_t)txvalidbeh << 0)); +} + +/** + * @brief RADIOPWRUPDN0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:24       SYNC_POSITION0   0x0
+ *  23:16             RXPWRUP0   0x0
+ *  14:08             TXPWRDN0   0x0
+ *  07:00             TXPWRUP0   0x0
+ * 
+ */ +#define BLE_RADIOPWRUPDN0_ADDR 0x00900880 +#define BLE_RADIOPWRUPDN0_OFFSET 0x00000080 +#define BLE_RADIOPWRUPDN0_INDEX 0x00000020 +#define BLE_RADIOPWRUPDN0_RESET 0x00000000 + +__INLINE uint32_t ble_radiopwrupdn0_get(void) +{ + return REG_BLE_RD(BLE_RADIOPWRUPDN0_ADDR); +} + +__INLINE void ble_radiopwrupdn0_set(uint32_t value) +{ + REG_BLE_WR(BLE_RADIOPWRUPDN0_ADDR, value); +} + +// field definitions +#define BLE_SYNC_POSITION0_MASK ((uint32_t)0xFF000000) +#define BLE_SYNC_POSITION0_LSB 24 +#define BLE_SYNC_POSITION0_WIDTH ((uint32_t)0x00000008) +#define BLE_RXPWRUP0_MASK ((uint32_t)0x00FF0000) +#define BLE_RXPWRUP0_LSB 16 +#define BLE_RXPWRUP0_WIDTH ((uint32_t)0x00000008) +#define BLE_TXPWRDN0_MASK ((uint32_t)0x00007F00) +#define BLE_TXPWRDN0_LSB 8 +#define BLE_TXPWRDN0_WIDTH ((uint32_t)0x00000007) +#define BLE_TXPWRUP0_MASK ((uint32_t)0x000000FF) +#define BLE_TXPWRUP0_LSB 0 +#define BLE_TXPWRUP0_WIDTH ((uint32_t)0x00000008) + +#define BLE_SYNC_POSITION0_RST 0x0 +#define BLE_RXPWRUP0_RST 0x0 +#define BLE_TXPWRDN0_RST 0x0 +#define BLE_TXPWRUP0_RST 0x0 + +__INLINE void ble_radiopwrupdn0_pack(uint8_t syncposition0, uint8_t rxpwrup0, uint8_t txpwrdn0, uint8_t txpwrup0) +{ + BLE_ASSERT_ERR((((uint32_t)syncposition0 << 24) & ~((uint32_t)0xFF000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)rxpwrup0 << 16) & ~((uint32_t)0x00FF0000)) == 0); + BLE_ASSERT_ERR((((uint32_t)txpwrdn0 << 8) & ~((uint32_t)0x00007F00)) == 0); + BLE_ASSERT_ERR((((uint32_t)txpwrup0 << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_BLE_WR(BLE_RADIOPWRUPDN0_ADDR, ((uint32_t)syncposition0 << 24) | ((uint32_t)rxpwrup0 << 16) | ((uint32_t)txpwrdn0 << 8) | ((uint32_t)txpwrup0 << 0)); +} + +__INLINE void ble_radiopwrupdn0_unpack(uint8_t* syncposition0, uint8_t* rxpwrup0, uint8_t* txpwrdn0, uint8_t* txpwrup0) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOPWRUPDN0_ADDR); + + *syncposition0 = (localVal & ((uint32_t)0xFF000000)) >> 24; + *rxpwrup0 = (localVal & ((uint32_t)0x00FF0000)) >> 16; + *txpwrdn0 = (localVal & ((uint32_t)0x00007F00)) >> 8; + *txpwrup0 = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +__INLINE uint8_t ble_radiopwrupdn0_sync_position0_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOPWRUPDN0_ADDR); + return ((localVal & ((uint32_t)0xFF000000)) >> 24); +} + +__INLINE void ble_radiopwrupdn0_sync_position0_setf(uint8_t syncposition0) +{ + BLE_ASSERT_ERR((((uint32_t)syncposition0 << 24) & ~((uint32_t)0xFF000000)) == 0); + REG_BLE_WR(BLE_RADIOPWRUPDN0_ADDR, (REG_BLE_RD(BLE_RADIOPWRUPDN0_ADDR) & ~((uint32_t)0xFF000000)) | ((uint32_t)syncposition0 << 24)); +} + +__INLINE uint8_t ble_radiopwrupdn0_rxpwrup0_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOPWRUPDN0_ADDR); + return ((localVal & ((uint32_t)0x00FF0000)) >> 16); +} + +__INLINE void ble_radiopwrupdn0_rxpwrup0_setf(uint8_t rxpwrup0) +{ + BLE_ASSERT_ERR((((uint32_t)rxpwrup0 << 16) & ~((uint32_t)0x00FF0000)) == 0); + REG_BLE_WR(BLE_RADIOPWRUPDN0_ADDR, (REG_BLE_RD(BLE_RADIOPWRUPDN0_ADDR) & ~((uint32_t)0x00FF0000)) | ((uint32_t)rxpwrup0 << 16)); +} + +__INLINE uint8_t ble_radiopwrupdn0_txpwrdn0_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOPWRUPDN0_ADDR); + return ((localVal & ((uint32_t)0x00007F00)) >> 8); +} + +__INLINE void ble_radiopwrupdn0_txpwrdn0_setf(uint8_t txpwrdn0) +{ + BLE_ASSERT_ERR((((uint32_t)txpwrdn0 << 8) & ~((uint32_t)0x00007F00)) == 0); + REG_BLE_WR(BLE_RADIOPWRUPDN0_ADDR, (REG_BLE_RD(BLE_RADIOPWRUPDN0_ADDR) & ~((uint32_t)0x00007F00)) | ((uint32_t)txpwrdn0 << 8)); +} + +__INLINE uint8_t ble_radiopwrupdn0_txpwrup0_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOPWRUPDN0_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +__INLINE void ble_radiopwrupdn0_txpwrup0_setf(uint8_t txpwrup0) +{ + BLE_ASSERT_ERR((((uint32_t)txpwrup0 << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_BLE_WR(BLE_RADIOPWRUPDN0_ADDR, (REG_BLE_RD(BLE_RADIOPWRUPDN0_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)txpwrup0 << 0)); +} + +/** + * @brief RADIOPWRUPDN1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:24       SYNC_POSITION1   0x0
+ *  23:16             RXPWRUP1   0x0
+ *  14:08             TXPWRDN1   0x0
+ *  07:00             TXPWRUP1   0x0
+ * 
+ */ +#define BLE_RADIOPWRUPDN1_ADDR 0x00900884 +#define BLE_RADIOPWRUPDN1_OFFSET 0x00000084 +#define BLE_RADIOPWRUPDN1_INDEX 0x00000021 +#define BLE_RADIOPWRUPDN1_RESET 0x00000000 + +__INLINE uint32_t ble_radiopwrupdn1_get(void) +{ + return REG_BLE_RD(BLE_RADIOPWRUPDN1_ADDR); +} + +__INLINE void ble_radiopwrupdn1_set(uint32_t value) +{ + REG_BLE_WR(BLE_RADIOPWRUPDN1_ADDR, value); +} + +// field definitions +#define BLE_SYNC_POSITION1_MASK ((uint32_t)0xFF000000) +#define BLE_SYNC_POSITION1_LSB 24 +#define BLE_SYNC_POSITION1_WIDTH ((uint32_t)0x00000008) +#define BLE_RXPWRUP1_MASK ((uint32_t)0x00FF0000) +#define BLE_RXPWRUP1_LSB 16 +#define BLE_RXPWRUP1_WIDTH ((uint32_t)0x00000008) +#define BLE_TXPWRDN1_MASK ((uint32_t)0x00007F00) +#define BLE_TXPWRDN1_LSB 8 +#define BLE_TXPWRDN1_WIDTH ((uint32_t)0x00000007) +#define BLE_TXPWRUP1_MASK ((uint32_t)0x000000FF) +#define BLE_TXPWRUP1_LSB 0 +#define BLE_TXPWRUP1_WIDTH ((uint32_t)0x00000008) + +#define BLE_SYNC_POSITION1_RST 0x0 +#define BLE_RXPWRUP1_RST 0x0 +#define BLE_TXPWRDN1_RST 0x0 +#define BLE_TXPWRUP1_RST 0x0 + +__INLINE void ble_radiopwrupdn1_pack(uint8_t syncposition1, uint8_t rxpwrup1, uint8_t txpwrdn1, uint8_t txpwrup1) +{ + BLE_ASSERT_ERR((((uint32_t)syncposition1 << 24) & ~((uint32_t)0xFF000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)rxpwrup1 << 16) & ~((uint32_t)0x00FF0000)) == 0); + BLE_ASSERT_ERR((((uint32_t)txpwrdn1 << 8) & ~((uint32_t)0x00007F00)) == 0); + BLE_ASSERT_ERR((((uint32_t)txpwrup1 << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_BLE_WR(BLE_RADIOPWRUPDN1_ADDR, ((uint32_t)syncposition1 << 24) | ((uint32_t)rxpwrup1 << 16) | ((uint32_t)txpwrdn1 << 8) | ((uint32_t)txpwrup1 << 0)); +} + +__INLINE void ble_radiopwrupdn1_unpack(uint8_t* syncposition1, uint8_t* rxpwrup1, uint8_t* txpwrdn1, uint8_t* txpwrup1) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOPWRUPDN1_ADDR); + + *syncposition1 = (localVal & ((uint32_t)0xFF000000)) >> 24; + *rxpwrup1 = (localVal & ((uint32_t)0x00FF0000)) >> 16; + *txpwrdn1 = (localVal & ((uint32_t)0x00007F00)) >> 8; + *txpwrup1 = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +__INLINE uint8_t ble_radiopwrupdn1_sync_position1_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOPWRUPDN1_ADDR); + return ((localVal & ((uint32_t)0xFF000000)) >> 24); +} + +__INLINE void ble_radiopwrupdn1_sync_position1_setf(uint8_t syncposition1) +{ + BLE_ASSERT_ERR((((uint32_t)syncposition1 << 24) & ~((uint32_t)0xFF000000)) == 0); + REG_BLE_WR(BLE_RADIOPWRUPDN1_ADDR, (REG_BLE_RD(BLE_RADIOPWRUPDN1_ADDR) & ~((uint32_t)0xFF000000)) | ((uint32_t)syncposition1 << 24)); +} + +__INLINE uint8_t ble_radiopwrupdn1_rxpwrup1_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOPWRUPDN1_ADDR); + return ((localVal & ((uint32_t)0x00FF0000)) >> 16); +} + +__INLINE void ble_radiopwrupdn1_rxpwrup1_setf(uint8_t rxpwrup1) +{ + BLE_ASSERT_ERR((((uint32_t)rxpwrup1 << 16) & ~((uint32_t)0x00FF0000)) == 0); + REG_BLE_WR(BLE_RADIOPWRUPDN1_ADDR, (REG_BLE_RD(BLE_RADIOPWRUPDN1_ADDR) & ~((uint32_t)0x00FF0000)) | ((uint32_t)rxpwrup1 << 16)); +} + +__INLINE uint8_t ble_radiopwrupdn1_txpwrdn1_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOPWRUPDN1_ADDR); + return ((localVal & ((uint32_t)0x00007F00)) >> 8); +} + +__INLINE void ble_radiopwrupdn1_txpwrdn1_setf(uint8_t txpwrdn1) +{ + BLE_ASSERT_ERR((((uint32_t)txpwrdn1 << 8) & ~((uint32_t)0x00007F00)) == 0); + REG_BLE_WR(BLE_RADIOPWRUPDN1_ADDR, (REG_BLE_RD(BLE_RADIOPWRUPDN1_ADDR) & ~((uint32_t)0x00007F00)) | ((uint32_t)txpwrdn1 << 8)); +} + +__INLINE uint8_t ble_radiopwrupdn1_txpwrup1_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOPWRUPDN1_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +__INLINE void ble_radiopwrupdn1_txpwrup1_setf(uint8_t txpwrup1) +{ + BLE_ASSERT_ERR((((uint32_t)txpwrup1 << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_BLE_WR(BLE_RADIOPWRUPDN1_ADDR, (REG_BLE_RD(BLE_RADIOPWRUPDN1_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)txpwrup1 << 0)); +} + +/** + * @brief RADIOPWRUPDN2 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:24       SYNC_POSITION2   0x0
+ *  23:16             RXPWRUP2   0x0
+ *  14:08             TXPWRDN2   0x0
+ *  07:00             TXPWRUP2   0x0
+ * 
+ */ +#define BLE_RADIOPWRUPDN2_ADDR 0x00900888 +#define BLE_RADIOPWRUPDN2_OFFSET 0x00000088 +#define BLE_RADIOPWRUPDN2_INDEX 0x00000022 +#define BLE_RADIOPWRUPDN2_RESET 0x00000000 + +__INLINE uint32_t ble_radiopwrupdn2_get(void) +{ + return REG_BLE_RD(BLE_RADIOPWRUPDN2_ADDR); +} + +__INLINE void ble_radiopwrupdn2_set(uint32_t value) +{ + REG_BLE_WR(BLE_RADIOPWRUPDN2_ADDR, value); +} + +// field definitions +#define BLE_SYNC_POSITION2_MASK ((uint32_t)0xFF000000) +#define BLE_SYNC_POSITION2_LSB 24 +#define BLE_SYNC_POSITION2_WIDTH ((uint32_t)0x00000008) +#define BLE_RXPWRUP2_MASK ((uint32_t)0x00FF0000) +#define BLE_RXPWRUP2_LSB 16 +#define BLE_RXPWRUP2_WIDTH ((uint32_t)0x00000008) +#define BLE_TXPWRDN2_MASK ((uint32_t)0x00007F00) +#define BLE_TXPWRDN2_LSB 8 +#define BLE_TXPWRDN2_WIDTH ((uint32_t)0x00000007) +#define BLE_TXPWRUP2_MASK ((uint32_t)0x000000FF) +#define BLE_TXPWRUP2_LSB 0 +#define BLE_TXPWRUP2_WIDTH ((uint32_t)0x00000008) + +#define BLE_SYNC_POSITION2_RST 0x0 +#define BLE_RXPWRUP2_RST 0x0 +#define BLE_TXPWRDN2_RST 0x0 +#define BLE_TXPWRUP2_RST 0x0 + +__INLINE void ble_radiopwrupdn2_pack(uint8_t syncposition2, uint8_t rxpwrup2, uint8_t txpwrdn2, uint8_t txpwrup2) +{ + BLE_ASSERT_ERR((((uint32_t)syncposition2 << 24) & ~((uint32_t)0xFF000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)rxpwrup2 << 16) & ~((uint32_t)0x00FF0000)) == 0); + BLE_ASSERT_ERR((((uint32_t)txpwrdn2 << 8) & ~((uint32_t)0x00007F00)) == 0); + BLE_ASSERT_ERR((((uint32_t)txpwrup2 << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_BLE_WR(BLE_RADIOPWRUPDN2_ADDR, ((uint32_t)syncposition2 << 24) | ((uint32_t)rxpwrup2 << 16) | ((uint32_t)txpwrdn2 << 8) | ((uint32_t)txpwrup2 << 0)); +} + +__INLINE void ble_radiopwrupdn2_unpack(uint8_t* syncposition2, uint8_t* rxpwrup2, uint8_t* txpwrdn2, uint8_t* txpwrup2) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOPWRUPDN2_ADDR); + + *syncposition2 = (localVal & ((uint32_t)0xFF000000)) >> 24; + *rxpwrup2 = (localVal & ((uint32_t)0x00FF0000)) >> 16; + *txpwrdn2 = (localVal & ((uint32_t)0x00007F00)) >> 8; + *txpwrup2 = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +__INLINE uint8_t ble_radiopwrupdn2_sync_position2_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOPWRUPDN2_ADDR); + return ((localVal & ((uint32_t)0xFF000000)) >> 24); +} + +__INLINE void ble_radiopwrupdn2_sync_position2_setf(uint8_t syncposition2) +{ + BLE_ASSERT_ERR((((uint32_t)syncposition2 << 24) & ~((uint32_t)0xFF000000)) == 0); + REG_BLE_WR(BLE_RADIOPWRUPDN2_ADDR, (REG_BLE_RD(BLE_RADIOPWRUPDN2_ADDR) & ~((uint32_t)0xFF000000)) | ((uint32_t)syncposition2 << 24)); +} + +__INLINE uint8_t ble_radiopwrupdn2_rxpwrup2_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOPWRUPDN2_ADDR); + return ((localVal & ((uint32_t)0x00FF0000)) >> 16); +} + +__INLINE void ble_radiopwrupdn2_rxpwrup2_setf(uint8_t rxpwrup2) +{ + BLE_ASSERT_ERR((((uint32_t)rxpwrup2 << 16) & ~((uint32_t)0x00FF0000)) == 0); + REG_BLE_WR(BLE_RADIOPWRUPDN2_ADDR, (REG_BLE_RD(BLE_RADIOPWRUPDN2_ADDR) & ~((uint32_t)0x00FF0000)) | ((uint32_t)rxpwrup2 << 16)); +} + +__INLINE uint8_t ble_radiopwrupdn2_txpwrdn2_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOPWRUPDN2_ADDR); + return ((localVal & ((uint32_t)0x00007F00)) >> 8); +} + +__INLINE void ble_radiopwrupdn2_txpwrdn2_setf(uint8_t txpwrdn2) +{ + BLE_ASSERT_ERR((((uint32_t)txpwrdn2 << 8) & ~((uint32_t)0x00007F00)) == 0); + REG_BLE_WR(BLE_RADIOPWRUPDN2_ADDR, (REG_BLE_RD(BLE_RADIOPWRUPDN2_ADDR) & ~((uint32_t)0x00007F00)) | ((uint32_t)txpwrdn2 << 8)); +} + +__INLINE uint8_t ble_radiopwrupdn2_txpwrup2_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOPWRUPDN2_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +__INLINE void ble_radiopwrupdn2_txpwrup2_setf(uint8_t txpwrup2) +{ + BLE_ASSERT_ERR((((uint32_t)txpwrup2 << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_BLE_WR(BLE_RADIOPWRUPDN2_ADDR, (REG_BLE_RD(BLE_RADIOPWRUPDN2_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)txpwrup2 << 0)); +} + +/** + * @brief RADIOPWRUPDN3 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  14:08             TXPWRDN3   0x0
+ *  07:00             TXPWRUP3   0x0
+ * 
+ */ +#define BLE_RADIOPWRUPDN3_ADDR 0x0090088C +#define BLE_RADIOPWRUPDN3_OFFSET 0x0000008C +#define BLE_RADIOPWRUPDN3_INDEX 0x00000023 +#define BLE_RADIOPWRUPDN3_RESET 0x00000000 + +__INLINE uint32_t ble_radiopwrupdn3_get(void) +{ + return REG_BLE_RD(BLE_RADIOPWRUPDN3_ADDR); +} + +__INLINE void ble_radiopwrupdn3_set(uint32_t value) +{ + REG_BLE_WR(BLE_RADIOPWRUPDN3_ADDR, value); +} + +// field definitions +#define BLE_TXPWRDN3_MASK ((uint32_t)0x00007F00) +#define BLE_TXPWRDN3_LSB 8 +#define BLE_TXPWRDN3_WIDTH ((uint32_t)0x00000007) +#define BLE_TXPWRUP3_MASK ((uint32_t)0x000000FF) +#define BLE_TXPWRUP3_LSB 0 +#define BLE_TXPWRUP3_WIDTH ((uint32_t)0x00000008) + +#define BLE_TXPWRDN3_RST 0x0 +#define BLE_TXPWRUP3_RST 0x0 + +__INLINE void ble_radiopwrupdn3_pack(uint8_t txpwrdn3, uint8_t txpwrup3) +{ + BLE_ASSERT_ERR((((uint32_t)txpwrdn3 << 8) & ~((uint32_t)0x00007F00)) == 0); + BLE_ASSERT_ERR((((uint32_t)txpwrup3 << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_BLE_WR(BLE_RADIOPWRUPDN3_ADDR, ((uint32_t)txpwrdn3 << 8) | ((uint32_t)txpwrup3 << 0)); +} + +__INLINE void ble_radiopwrupdn3_unpack(uint8_t* txpwrdn3, uint8_t* txpwrup3) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOPWRUPDN3_ADDR); + + *txpwrdn3 = (localVal & ((uint32_t)0x00007F00)) >> 8; + *txpwrup3 = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +__INLINE uint8_t ble_radiopwrupdn3_txpwrdn3_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOPWRUPDN3_ADDR); + return ((localVal & ((uint32_t)0x00007F00)) >> 8); +} + +__INLINE void ble_radiopwrupdn3_txpwrdn3_setf(uint8_t txpwrdn3) +{ + BLE_ASSERT_ERR((((uint32_t)txpwrdn3 << 8) & ~((uint32_t)0x00007F00)) == 0); + REG_BLE_WR(BLE_RADIOPWRUPDN3_ADDR, (REG_BLE_RD(BLE_RADIOPWRUPDN3_ADDR) & ~((uint32_t)0x00007F00)) | ((uint32_t)txpwrdn3 << 8)); +} + +__INLINE uint8_t ble_radiopwrupdn3_txpwrup3_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOPWRUPDN3_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +__INLINE void ble_radiopwrupdn3_txpwrup3_setf(uint8_t txpwrup3) +{ + BLE_ASSERT_ERR((((uint32_t)txpwrup3 << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_BLE_WR(BLE_RADIOPWRUPDN3_ADDR, (REG_BLE_RD(BLE_RADIOPWRUPDN3_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)txpwrup3 << 0)); +} + +/** + * @brief RADIOTXRXTIM0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  22:16            RFRXTMDA0   0x0
+ *  14:08           RXPATHDLY0   0x0
+ *  06:00           TXPATHDLY0   0x0
+ * 
+ */ +#define BLE_RADIOTXRXTIM0_ADDR 0x00900890 +#define BLE_RADIOTXRXTIM0_OFFSET 0x00000090 +#define BLE_RADIOTXRXTIM0_INDEX 0x00000024 +#define BLE_RADIOTXRXTIM0_RESET 0x00000000 + +__INLINE uint32_t ble_radiotxrxtim0_get(void) +{ + return REG_BLE_RD(BLE_RADIOTXRXTIM0_ADDR); +} + +__INLINE void ble_radiotxrxtim0_set(uint32_t value) +{ + REG_BLE_WR(BLE_RADIOTXRXTIM0_ADDR, value); +} + +// field definitions +#define BLE_RFRXTMDA0_MASK ((uint32_t)0x007F0000) +#define BLE_RFRXTMDA0_LSB 16 +#define BLE_RFRXTMDA0_WIDTH ((uint32_t)0x00000007) +#define BLE_RXPATHDLY0_MASK ((uint32_t)0x00007F00) +#define BLE_RXPATHDLY0_LSB 8 +#define BLE_RXPATHDLY0_WIDTH ((uint32_t)0x00000007) +#define BLE_TXPATHDLY0_MASK ((uint32_t)0x0000007F) +#define BLE_TXPATHDLY0_LSB 0 +#define BLE_TXPATHDLY0_WIDTH ((uint32_t)0x00000007) + +#define BLE_RFRXTMDA0_RST 0x0 +#define BLE_RXPATHDLY0_RST 0x0 +#define BLE_TXPATHDLY0_RST 0x0 + +__INLINE void ble_radiotxrxtim0_pack(uint8_t rfrxtmda0, uint8_t rxpathdly0, uint8_t txpathdly0) +{ + BLE_ASSERT_ERR((((uint32_t)rfrxtmda0 << 16) & ~((uint32_t)0x007F0000)) == 0); + BLE_ASSERT_ERR((((uint32_t)rxpathdly0 << 8) & ~((uint32_t)0x00007F00)) == 0); + BLE_ASSERT_ERR((((uint32_t)txpathdly0 << 0) & ~((uint32_t)0x0000007F)) == 0); + REG_BLE_WR(BLE_RADIOTXRXTIM0_ADDR, ((uint32_t)rfrxtmda0 << 16) | ((uint32_t)rxpathdly0 << 8) | ((uint32_t)txpathdly0 << 0)); +} + +__INLINE void ble_radiotxrxtim0_unpack(uint8_t* rfrxtmda0, uint8_t* rxpathdly0, uint8_t* txpathdly0) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOTXRXTIM0_ADDR); + + *rfrxtmda0 = (localVal & ((uint32_t)0x007F0000)) >> 16; + *rxpathdly0 = (localVal & ((uint32_t)0x00007F00)) >> 8; + *txpathdly0 = (localVal & ((uint32_t)0x0000007F)) >> 0; +} + +__INLINE uint8_t ble_radiotxrxtim0_rfrxtmda0_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOTXRXTIM0_ADDR); + return ((localVal & ((uint32_t)0x007F0000)) >> 16); +} + +__INLINE void ble_radiotxrxtim0_rfrxtmda0_setf(uint8_t rfrxtmda0) +{ + BLE_ASSERT_ERR((((uint32_t)rfrxtmda0 << 16) & ~((uint32_t)0x007F0000)) == 0); + REG_BLE_WR(BLE_RADIOTXRXTIM0_ADDR, (REG_BLE_RD(BLE_RADIOTXRXTIM0_ADDR) & ~((uint32_t)0x007F0000)) | ((uint32_t)rfrxtmda0 << 16)); +} + +__INLINE uint8_t ble_radiotxrxtim0_rxpathdly0_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOTXRXTIM0_ADDR); + return ((localVal & ((uint32_t)0x00007F00)) >> 8); +} + +__INLINE void ble_radiotxrxtim0_rxpathdly0_setf(uint8_t rxpathdly0) +{ + BLE_ASSERT_ERR((((uint32_t)rxpathdly0 << 8) & ~((uint32_t)0x00007F00)) == 0); + REG_BLE_WR(BLE_RADIOTXRXTIM0_ADDR, (REG_BLE_RD(BLE_RADIOTXRXTIM0_ADDR) & ~((uint32_t)0x00007F00)) | ((uint32_t)rxpathdly0 << 8)); +} + +__INLINE uint8_t ble_radiotxrxtim0_txpathdly0_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOTXRXTIM0_ADDR); + return ((localVal & ((uint32_t)0x0000007F)) >> 0); +} + +__INLINE void ble_radiotxrxtim0_txpathdly0_setf(uint8_t txpathdly0) +{ + BLE_ASSERT_ERR((((uint32_t)txpathdly0 << 0) & ~((uint32_t)0x0000007F)) == 0); + REG_BLE_WR(BLE_RADIOTXRXTIM0_ADDR, (REG_BLE_RD(BLE_RADIOTXRXTIM0_ADDR) & ~((uint32_t)0x0000007F)) | ((uint32_t)txpathdly0 << 0)); +} + +/** + * @brief RADIOTXRXTIM1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  22:16            RFRXTMDA1   0x0
+ *  14:08           RXPATHDLY1   0x0
+ *  06:00           TXPATHDLY1   0x0
+ * 
+ */ +#define BLE_RADIOTXRXTIM1_ADDR 0x00900894 +#define BLE_RADIOTXRXTIM1_OFFSET 0x00000094 +#define BLE_RADIOTXRXTIM1_INDEX 0x00000025 +#define BLE_RADIOTXRXTIM1_RESET 0x00000000 + +__INLINE uint32_t ble_radiotxrxtim1_get(void) +{ + return REG_BLE_RD(BLE_RADIOTXRXTIM1_ADDR); +} + +__INLINE void ble_radiotxrxtim1_set(uint32_t value) +{ + REG_BLE_WR(BLE_RADIOTXRXTIM1_ADDR, value); +} + +// field definitions +#define BLE_RFRXTMDA1_MASK ((uint32_t)0x007F0000) +#define BLE_RFRXTMDA1_LSB 16 +#define BLE_RFRXTMDA1_WIDTH ((uint32_t)0x00000007) +#define BLE_RXPATHDLY1_MASK ((uint32_t)0x00007F00) +#define BLE_RXPATHDLY1_LSB 8 +#define BLE_RXPATHDLY1_WIDTH ((uint32_t)0x00000007) +#define BLE_TXPATHDLY1_MASK ((uint32_t)0x0000007F) +#define BLE_TXPATHDLY1_LSB 0 +#define BLE_TXPATHDLY1_WIDTH ((uint32_t)0x00000007) + +#define BLE_RFRXTMDA1_RST 0x0 +#define BLE_RXPATHDLY1_RST 0x0 +#define BLE_TXPATHDLY1_RST 0x0 + +__INLINE void ble_radiotxrxtim1_pack(uint8_t rfrxtmda1, uint8_t rxpathdly1, uint8_t txpathdly1) +{ + BLE_ASSERT_ERR((((uint32_t)rfrxtmda1 << 16) & ~((uint32_t)0x007F0000)) == 0); + BLE_ASSERT_ERR((((uint32_t)rxpathdly1 << 8) & ~((uint32_t)0x00007F00)) == 0); + BLE_ASSERT_ERR((((uint32_t)txpathdly1 << 0) & ~((uint32_t)0x0000007F)) == 0); + REG_BLE_WR(BLE_RADIOTXRXTIM1_ADDR, ((uint32_t)rfrxtmda1 << 16) | ((uint32_t)rxpathdly1 << 8) | ((uint32_t)txpathdly1 << 0)); +} + +__INLINE void ble_radiotxrxtim1_unpack(uint8_t* rfrxtmda1, uint8_t* rxpathdly1, uint8_t* txpathdly1) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOTXRXTIM1_ADDR); + + *rfrxtmda1 = (localVal & ((uint32_t)0x007F0000)) >> 16; + *rxpathdly1 = (localVal & ((uint32_t)0x00007F00)) >> 8; + *txpathdly1 = (localVal & ((uint32_t)0x0000007F)) >> 0; +} + +__INLINE uint8_t ble_radiotxrxtim1_rfrxtmda1_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOTXRXTIM1_ADDR); + return ((localVal & ((uint32_t)0x007F0000)) >> 16); +} + +__INLINE void ble_radiotxrxtim1_rfrxtmda1_setf(uint8_t rfrxtmda1) +{ + BLE_ASSERT_ERR((((uint32_t)rfrxtmda1 << 16) & ~((uint32_t)0x007F0000)) == 0); + REG_BLE_WR(BLE_RADIOTXRXTIM1_ADDR, (REG_BLE_RD(BLE_RADIOTXRXTIM1_ADDR) & ~((uint32_t)0x007F0000)) | ((uint32_t)rfrxtmda1 << 16)); +} + +__INLINE uint8_t ble_radiotxrxtim1_rxpathdly1_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOTXRXTIM1_ADDR); + return ((localVal & ((uint32_t)0x00007F00)) >> 8); +} + +__INLINE void ble_radiotxrxtim1_rxpathdly1_setf(uint8_t rxpathdly1) +{ + BLE_ASSERT_ERR((((uint32_t)rxpathdly1 << 8) & ~((uint32_t)0x00007F00)) == 0); + REG_BLE_WR(BLE_RADIOTXRXTIM1_ADDR, (REG_BLE_RD(BLE_RADIOTXRXTIM1_ADDR) & ~((uint32_t)0x00007F00)) | ((uint32_t)rxpathdly1 << 8)); +} + +__INLINE uint8_t ble_radiotxrxtim1_txpathdly1_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOTXRXTIM1_ADDR); + return ((localVal & ((uint32_t)0x0000007F)) >> 0); +} + +__INLINE void ble_radiotxrxtim1_txpathdly1_setf(uint8_t txpathdly1) +{ + BLE_ASSERT_ERR((((uint32_t)txpathdly1 << 0) & ~((uint32_t)0x0000007F)) == 0); + REG_BLE_WR(BLE_RADIOTXRXTIM1_ADDR, (REG_BLE_RD(BLE_RADIOTXRXTIM1_ADDR) & ~((uint32_t)0x0000007F)) | ((uint32_t)txpathdly1 << 0)); +} + +/** + * @brief RADIOTXRXTIM2 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:24      RXFLUSHPATHDLY2   0x0
+ *  23:16            RFRXTMDA2   0x0
+ *  15:08           RXPATHDLY2   0x0
+ *  06:00           TXPATHDLY2   0x0
+ * 
+ */ +#define BLE_RADIOTXRXTIM2_ADDR 0x00900898 +#define BLE_RADIOTXRXTIM2_OFFSET 0x00000098 +#define BLE_RADIOTXRXTIM2_INDEX 0x00000026 +#define BLE_RADIOTXRXTIM2_RESET 0x00000000 + +__INLINE uint32_t ble_radiotxrxtim2_get(void) +{ + return REG_BLE_RD(BLE_RADIOTXRXTIM2_ADDR); +} + +__INLINE void ble_radiotxrxtim2_set(uint32_t value) +{ + REG_BLE_WR(BLE_RADIOTXRXTIM2_ADDR, value); +} + +// field definitions +#define BLE_RXFLUSHPATHDLY2_MASK ((uint32_t)0xFF000000) +#define BLE_RXFLUSHPATHDLY2_LSB 24 +#define BLE_RXFLUSHPATHDLY2_WIDTH ((uint32_t)0x00000008) +#define BLE_RFRXTMDA2_MASK ((uint32_t)0x00FF0000) +#define BLE_RFRXTMDA2_LSB 16 +#define BLE_RFRXTMDA2_WIDTH ((uint32_t)0x00000008) +#define BLE_RXPATHDLY2_MASK ((uint32_t)0x0000FF00) +#define BLE_RXPATHDLY2_LSB 8 +#define BLE_RXPATHDLY2_WIDTH ((uint32_t)0x00000008) +#define BLE_TXPATHDLY2_MASK ((uint32_t)0x0000007F) +#define BLE_TXPATHDLY2_LSB 0 +#define BLE_TXPATHDLY2_WIDTH ((uint32_t)0x00000007) + +#define BLE_RXFLUSHPATHDLY2_RST 0x0 +#define BLE_RFRXTMDA2_RST 0x0 +#define BLE_RXPATHDLY2_RST 0x0 +#define BLE_TXPATHDLY2_RST 0x0 + +__INLINE void ble_radiotxrxtim2_pack(uint8_t rxflushpathdly2, uint8_t rfrxtmda2, uint8_t rxpathdly2, uint8_t txpathdly2) +{ + BLE_ASSERT_ERR((((uint32_t)rxflushpathdly2 << 24) & ~((uint32_t)0xFF000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)rfrxtmda2 << 16) & ~((uint32_t)0x00FF0000)) == 0); + BLE_ASSERT_ERR((((uint32_t)rxpathdly2 << 8) & ~((uint32_t)0x0000FF00)) == 0); + BLE_ASSERT_ERR((((uint32_t)txpathdly2 << 0) & ~((uint32_t)0x0000007F)) == 0); + REG_BLE_WR(BLE_RADIOTXRXTIM2_ADDR, ((uint32_t)rxflushpathdly2 << 24) | ((uint32_t)rfrxtmda2 << 16) | ((uint32_t)rxpathdly2 << 8) | ((uint32_t)txpathdly2 << 0)); +} + +__INLINE void ble_radiotxrxtim2_unpack(uint8_t* rxflushpathdly2, uint8_t* rfrxtmda2, uint8_t* rxpathdly2, uint8_t* txpathdly2) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOTXRXTIM2_ADDR); + + *rxflushpathdly2 = (localVal & ((uint32_t)0xFF000000)) >> 24; + *rfrxtmda2 = (localVal & ((uint32_t)0x00FF0000)) >> 16; + *rxpathdly2 = (localVal & ((uint32_t)0x0000FF00)) >> 8; + *txpathdly2 = (localVal & ((uint32_t)0x0000007F)) >> 0; +} + +__INLINE uint8_t ble_radiotxrxtim2_rxflushpathdly2_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOTXRXTIM2_ADDR); + return ((localVal & ((uint32_t)0xFF000000)) >> 24); +} + +__INLINE void ble_radiotxrxtim2_rxflushpathdly2_setf(uint8_t rxflushpathdly2) +{ + BLE_ASSERT_ERR((((uint32_t)rxflushpathdly2 << 24) & ~((uint32_t)0xFF000000)) == 0); + REG_BLE_WR(BLE_RADIOTXRXTIM2_ADDR, (REG_BLE_RD(BLE_RADIOTXRXTIM2_ADDR) & ~((uint32_t)0xFF000000)) | ((uint32_t)rxflushpathdly2 << 24)); +} + +__INLINE uint8_t ble_radiotxrxtim2_rfrxtmda2_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOTXRXTIM2_ADDR); + return ((localVal & ((uint32_t)0x00FF0000)) >> 16); +} + +__INLINE void ble_radiotxrxtim2_rfrxtmda2_setf(uint8_t rfrxtmda2) +{ + BLE_ASSERT_ERR((((uint32_t)rfrxtmda2 << 16) & ~((uint32_t)0x00FF0000)) == 0); + REG_BLE_WR(BLE_RADIOTXRXTIM2_ADDR, (REG_BLE_RD(BLE_RADIOTXRXTIM2_ADDR) & ~((uint32_t)0x00FF0000)) | ((uint32_t)rfrxtmda2 << 16)); +} + +__INLINE uint8_t ble_radiotxrxtim2_rxpathdly2_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOTXRXTIM2_ADDR); + return ((localVal & ((uint32_t)0x0000FF00)) >> 8); +} + +__INLINE void ble_radiotxrxtim2_rxpathdly2_setf(uint8_t rxpathdly2) +{ + BLE_ASSERT_ERR((((uint32_t)rxpathdly2 << 8) & ~((uint32_t)0x0000FF00)) == 0); + REG_BLE_WR(BLE_RADIOTXRXTIM2_ADDR, (REG_BLE_RD(BLE_RADIOTXRXTIM2_ADDR) & ~((uint32_t)0x0000FF00)) | ((uint32_t)rxpathdly2 << 8)); +} + +__INLINE uint8_t ble_radiotxrxtim2_txpathdly2_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOTXRXTIM2_ADDR); + return ((localVal & ((uint32_t)0x0000007F)) >> 0); +} + +__INLINE void ble_radiotxrxtim2_txpathdly2_setf(uint8_t txpathdly2) +{ + BLE_ASSERT_ERR((((uint32_t)txpathdly2 << 0) & ~((uint32_t)0x0000007F)) == 0); + REG_BLE_WR(BLE_RADIOTXRXTIM2_ADDR, (REG_BLE_RD(BLE_RADIOTXRXTIM2_ADDR) & ~((uint32_t)0x0000007F)) | ((uint32_t)txpathdly2 << 0)); +} + +/** + * @brief RADIOTXRXTIM3 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:24      RXFLUSHPATHDLY3   0x0
+ *  22:16            RFRXTMDA3   0x0
+ *  06:00           TXPATHDLY3   0x0
+ * 
+ */ +#define BLE_RADIOTXRXTIM3_ADDR 0x0090089C +#define BLE_RADIOTXRXTIM3_OFFSET 0x0000009C +#define BLE_RADIOTXRXTIM3_INDEX 0x00000027 +#define BLE_RADIOTXRXTIM3_RESET 0x00000000 + +__INLINE uint32_t ble_radiotxrxtim3_get(void) +{ + return REG_BLE_RD(BLE_RADIOTXRXTIM3_ADDR); +} + +__INLINE void ble_radiotxrxtim3_set(uint32_t value) +{ + REG_BLE_WR(BLE_RADIOTXRXTIM3_ADDR, value); +} + +#define BK_BLE_ADDREG0_ADDR 0x00900990 + +__INLINE uint32_t bk_ble_addtion_reg0_get(void) +{ + return REG_BLE_RD(BK_BLE_ADDREG0_ADDR); +} + +__INLINE void bk_ble_addtion_reg0_set(uint32_t value) +{ + REG_BLE_WR(BK_BLE_ADDREG0_ADDR, value); +} + +// field definitions +#define BLE_RXFLUSHPATHDLY3_MASK ((uint32_t)0xFF000000) +#define BLE_RXFLUSHPATHDLY3_LSB 24 +#define BLE_RXFLUSHPATHDLY3_WIDTH ((uint32_t)0x00000008) +#define BLE_RFRXTMDA3_MASK ((uint32_t)0x007F0000) +#define BLE_RFRXTMDA3_LSB 16 +#define BLE_RFRXTMDA3_WIDTH ((uint32_t)0x00000007) +#define BLE_TXPATHDLY3_MASK ((uint32_t)0x0000007F) +#define BLE_TXPATHDLY3_LSB 0 +#define BLE_TXPATHDLY3_WIDTH ((uint32_t)0x00000007) + +#define BLE_RXFLUSHPATHDLY3_RST 0x0 +#define BLE_RFRXTMDA3_RST 0x0 +#define BLE_TXPATHDLY3_RST 0x0 + +__INLINE void ble_radiotxrxtim3_pack(uint8_t rxflushpathdly3, uint8_t rfrxtmda3, uint8_t txpathdly3) +{ + BLE_ASSERT_ERR((((uint32_t)rxflushpathdly3 << 24) & ~((uint32_t)0xFF000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)rfrxtmda3 << 16) & ~((uint32_t)0x007F0000)) == 0); + BLE_ASSERT_ERR((((uint32_t)txpathdly3 << 0) & ~((uint32_t)0x0000007F)) == 0); + REG_BLE_WR(BLE_RADIOTXRXTIM3_ADDR, ((uint32_t)rxflushpathdly3 << 24) | ((uint32_t)rfrxtmda3 << 16) | ((uint32_t)txpathdly3 << 0)); +} + +__INLINE void ble_radiotxrxtim3_unpack(uint8_t* rxflushpathdly3, uint8_t* rfrxtmda3, uint8_t* txpathdly3) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOTXRXTIM3_ADDR); + + *rxflushpathdly3 = (localVal & ((uint32_t)0xFF000000)) >> 24; + *rfrxtmda3 = (localVal & ((uint32_t)0x007F0000)) >> 16; + *txpathdly3 = (localVal & ((uint32_t)0x0000007F)) >> 0; +} + +__INLINE uint8_t ble_radiotxrxtim3_rxflushpathdly3_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOTXRXTIM3_ADDR); + return ((localVal & ((uint32_t)0xFF000000)) >> 24); +} + +__INLINE void ble_radiotxrxtim3_rxflushpathdly3_setf(uint8_t rxflushpathdly3) +{ + BLE_ASSERT_ERR((((uint32_t)rxflushpathdly3 << 24) & ~((uint32_t)0xFF000000)) == 0); + REG_BLE_WR(BLE_RADIOTXRXTIM3_ADDR, (REG_BLE_RD(BLE_RADIOTXRXTIM3_ADDR) & ~((uint32_t)0xFF000000)) | ((uint32_t)rxflushpathdly3 << 24)); +} + +__INLINE uint8_t ble_radiotxrxtim3_rfrxtmda3_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOTXRXTIM3_ADDR); + return ((localVal & ((uint32_t)0x007F0000)) >> 16); +} + +__INLINE void ble_radiotxrxtim3_rfrxtmda3_setf(uint8_t rfrxtmda3) +{ + BLE_ASSERT_ERR((((uint32_t)rfrxtmda3 << 16) & ~((uint32_t)0x007F0000)) == 0); + REG_BLE_WR(BLE_RADIOTXRXTIM3_ADDR, (REG_BLE_RD(BLE_RADIOTXRXTIM3_ADDR) & ~((uint32_t)0x007F0000)) | ((uint32_t)rfrxtmda3 << 16)); +} + +__INLINE uint8_t ble_radiotxrxtim3_txpathdly3_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RADIOTXRXTIM3_ADDR); + return ((localVal & ((uint32_t)0x0000007F)) >> 0); +} + +__INLINE void ble_radiotxrxtim3_txpathdly3_setf(uint8_t txpathdly3) +{ + BLE_ASSERT_ERR((((uint32_t)txpathdly3 << 0) & ~((uint32_t)0x0000007F)) == 0); + REG_BLE_WR(BLE_RADIOTXRXTIM3_ADDR, (REG_BLE_RD(BLE_RADIOTXRXTIM3_ADDR) & ~((uint32_t)0x0000007F)) | ((uint32_t)txpathdly3 << 0)); +} + +/** + * @brief SPIPTRCNTL0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  29:16             TXOFFPTR   0x0
+ *  13:00              TXONPTR   0x0
+ * 
+ */ +#define BLE_SPIPTRCNTL0_ADDR 0x009008A0 +#define BLE_SPIPTRCNTL0_OFFSET 0x000000A0 +#define BLE_SPIPTRCNTL0_INDEX 0x00000028 +#define BLE_SPIPTRCNTL0_RESET 0x00000000 + +__INLINE uint32_t ble_spiptrcntl0_get(void) +{ + return REG_BLE_RD(BLE_SPIPTRCNTL0_ADDR); +} + +__INLINE void ble_spiptrcntl0_set(uint32_t value) +{ + REG_BLE_WR(BLE_SPIPTRCNTL0_ADDR, value); +} + +// field definitions +#define BLE_TXOFFPTR_MASK ((uint32_t)0x3FFF0000) +#define BLE_TXOFFPTR_LSB 16 +#define BLE_TXOFFPTR_WIDTH ((uint32_t)0x0000000E) +#define BLE_TXONPTR_MASK ((uint32_t)0x00003FFF) +#define BLE_TXONPTR_LSB 0 +#define BLE_TXONPTR_WIDTH ((uint32_t)0x0000000E) + +#define BLE_TXOFFPTR_RST 0x0 +#define BLE_TXONPTR_RST 0x0 + +__INLINE void ble_spiptrcntl0_pack(uint16_t txoffptr, uint16_t txonptr) +{ + BLE_ASSERT_ERR((((uint32_t)txoffptr << 16) & ~((uint32_t)0x3FFF0000)) == 0); + BLE_ASSERT_ERR((((uint32_t)txonptr << 0) & ~((uint32_t)0x00003FFF)) == 0); + REG_BLE_WR(BLE_SPIPTRCNTL0_ADDR, ((uint32_t)txoffptr << 16) | ((uint32_t)txonptr << 0)); +} + +__INLINE void ble_spiptrcntl0_unpack(uint16_t* txoffptr, uint16_t* txonptr) +{ + uint32_t localVal = REG_BLE_RD(BLE_SPIPTRCNTL0_ADDR); + + *txoffptr = (localVal & ((uint32_t)0x3FFF0000)) >> 16; + *txonptr = (localVal & ((uint32_t)0x00003FFF)) >> 0; +} + +__INLINE uint16_t ble_spiptrcntl0_txoffptr_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SPIPTRCNTL0_ADDR); + return ((localVal & ((uint32_t)0x3FFF0000)) >> 16); +} + +__INLINE void ble_spiptrcntl0_txoffptr_setf(uint16_t txoffptr) +{ + BLE_ASSERT_ERR((((uint32_t)txoffptr << 16) & ~((uint32_t)0x3FFF0000)) == 0); + REG_BLE_WR(BLE_SPIPTRCNTL0_ADDR, (REG_BLE_RD(BLE_SPIPTRCNTL0_ADDR) & ~((uint32_t)0x3FFF0000)) | ((uint32_t)txoffptr << 16)); +} + +__INLINE uint16_t ble_spiptrcntl0_txonptr_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SPIPTRCNTL0_ADDR); + return ((localVal & ((uint32_t)0x00003FFF)) >> 0); +} + +__INLINE void ble_spiptrcntl0_txonptr_setf(uint16_t txonptr) +{ + BLE_ASSERT_ERR((((uint32_t)txonptr << 0) & ~((uint32_t)0x00003FFF)) == 0); + REG_BLE_WR(BLE_SPIPTRCNTL0_ADDR, (REG_BLE_RD(BLE_SPIPTRCNTL0_ADDR) & ~((uint32_t)0x00003FFF)) | ((uint32_t)txonptr << 0)); +} + +/** + * @brief SPIPTRCNTL1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  29:16             RXOFFPTR   0x0
+ *  13:00              RXONPTR   0x0
+ * 
+ */ +#define BLE_SPIPTRCNTL1_ADDR 0x009008A4 +#define BLE_SPIPTRCNTL1_OFFSET 0x000000A4 +#define BLE_SPIPTRCNTL1_INDEX 0x00000029 +#define BLE_SPIPTRCNTL1_RESET 0x00000000 + +__INLINE uint32_t ble_spiptrcntl1_get(void) +{ + return REG_BLE_RD(BLE_SPIPTRCNTL1_ADDR); +} + +__INLINE void ble_spiptrcntl1_set(uint32_t value) +{ + REG_BLE_WR(BLE_SPIPTRCNTL1_ADDR, value); +} + +// field definitions +#define BLE_RXOFFPTR_MASK ((uint32_t)0x3FFF0000) +#define BLE_RXOFFPTR_LSB 16 +#define BLE_RXOFFPTR_WIDTH ((uint32_t)0x0000000E) +#define BLE_RXONPTR_MASK ((uint32_t)0x00003FFF) +#define BLE_RXONPTR_LSB 0 +#define BLE_RXONPTR_WIDTH ((uint32_t)0x0000000E) + +#define BLE_RXOFFPTR_RST 0x0 +#define BLE_RXONPTR_RST 0x0 + +__INLINE void ble_spiptrcntl1_pack(uint16_t rxoffptr, uint16_t rxonptr) +{ + BLE_ASSERT_ERR((((uint32_t)rxoffptr << 16) & ~((uint32_t)0x3FFF0000)) == 0); + BLE_ASSERT_ERR((((uint32_t)rxonptr << 0) & ~((uint32_t)0x00003FFF)) == 0); + REG_BLE_WR(BLE_SPIPTRCNTL1_ADDR, ((uint32_t)rxoffptr << 16) | ((uint32_t)rxonptr << 0)); +} + +__INLINE void ble_spiptrcntl1_unpack(uint16_t* rxoffptr, uint16_t* rxonptr) +{ + uint32_t localVal = REG_BLE_RD(BLE_SPIPTRCNTL1_ADDR); + + *rxoffptr = (localVal & ((uint32_t)0x3FFF0000)) >> 16; + *rxonptr = (localVal & ((uint32_t)0x00003FFF)) >> 0; +} + +__INLINE uint16_t ble_spiptrcntl1_rxoffptr_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SPIPTRCNTL1_ADDR); + return ((localVal & ((uint32_t)0x3FFF0000)) >> 16); +} + +__INLINE void ble_spiptrcntl1_rxoffptr_setf(uint16_t rxoffptr) +{ + BLE_ASSERT_ERR((((uint32_t)rxoffptr << 16) & ~((uint32_t)0x3FFF0000)) == 0); + REG_BLE_WR(BLE_SPIPTRCNTL1_ADDR, (REG_BLE_RD(BLE_SPIPTRCNTL1_ADDR) & ~((uint32_t)0x3FFF0000)) | ((uint32_t)rxoffptr << 16)); +} + +__INLINE uint16_t ble_spiptrcntl1_rxonptr_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SPIPTRCNTL1_ADDR); + return ((localVal & ((uint32_t)0x00003FFF)) >> 0); +} + +__INLINE void ble_spiptrcntl1_rxonptr_setf(uint16_t rxonptr) +{ + BLE_ASSERT_ERR((((uint32_t)rxonptr << 0) & ~((uint32_t)0x00003FFF)) == 0); + REG_BLE_WR(BLE_SPIPTRCNTL1_ADDR, (REG_BLE_RD(BLE_SPIPTRCNTL1_ADDR) & ~((uint32_t)0x00003FFF)) | ((uint32_t)rxonptr << 0)); +} + +/** + * @brief SPIPTRCNTL2 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  29:16          RXLENGTHPTR   0x0
+ *  13:00              RSSIPTR   0x0
+ * 
+ */ +#define BLE_SPIPTRCNTL2_ADDR 0x009008A8 +#define BLE_SPIPTRCNTL2_OFFSET 0x000000A8 +#define BLE_SPIPTRCNTL2_INDEX 0x0000002A +#define BLE_SPIPTRCNTL2_RESET 0x00000000 + +__INLINE uint32_t ble_spiptrcntl2_get(void) +{ + return REG_BLE_RD(BLE_SPIPTRCNTL2_ADDR); +} + +__INLINE void ble_spiptrcntl2_set(uint32_t value) +{ + REG_BLE_WR(BLE_SPIPTRCNTL2_ADDR, value); +} + +// field definitions +#define BLE_RXLENGTHPTR_MASK ((uint32_t)0x3FFF0000) +#define BLE_RXLENGTHPTR_LSB 16 +#define BLE_RXLENGTHPTR_WIDTH ((uint32_t)0x0000000E) +#define BLE_RSSIPTR_MASK ((uint32_t)0x00003FFF) +#define BLE_RSSIPTR_LSB 0 +#define BLE_RSSIPTR_WIDTH ((uint32_t)0x0000000E) + +#define BLE_RXLENGTHPTR_RST 0x0 +#define BLE_RSSIPTR_RST 0x0 + +__INLINE void ble_spiptrcntl2_pack(uint16_t rxlengthptr, uint16_t rssiptr) +{ + BLE_ASSERT_ERR((((uint32_t)rxlengthptr << 16) & ~((uint32_t)0x3FFF0000)) == 0); + BLE_ASSERT_ERR((((uint32_t)rssiptr << 0) & ~((uint32_t)0x00003FFF)) == 0); + REG_BLE_WR(BLE_SPIPTRCNTL2_ADDR, ((uint32_t)rxlengthptr << 16) | ((uint32_t)rssiptr << 0)); +} + +__INLINE void ble_spiptrcntl2_unpack(uint16_t* rxlengthptr, uint16_t* rssiptr) +{ + uint32_t localVal = REG_BLE_RD(BLE_SPIPTRCNTL2_ADDR); + + *rxlengthptr = (localVal & ((uint32_t)0x3FFF0000)) >> 16; + *rssiptr = (localVal & ((uint32_t)0x00003FFF)) >> 0; +} + +__INLINE uint16_t ble_spiptrcntl2_rxlengthptr_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SPIPTRCNTL2_ADDR); + return ((localVal & ((uint32_t)0x3FFF0000)) >> 16); +} + +__INLINE void ble_spiptrcntl2_rxlengthptr_setf(uint16_t rxlengthptr) +{ + BLE_ASSERT_ERR((((uint32_t)rxlengthptr << 16) & ~((uint32_t)0x3FFF0000)) == 0); + REG_BLE_WR(BLE_SPIPTRCNTL2_ADDR, (REG_BLE_RD(BLE_SPIPTRCNTL2_ADDR) & ~((uint32_t)0x3FFF0000)) | ((uint32_t)rxlengthptr << 16)); +} + +__INLINE uint16_t ble_spiptrcntl2_rssiptr_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SPIPTRCNTL2_ADDR); + return ((localVal & ((uint32_t)0x00003FFF)) >> 0); +} + +__INLINE void ble_spiptrcntl2_rssiptr_setf(uint16_t rssiptr) +{ + BLE_ASSERT_ERR((((uint32_t)rssiptr << 0) & ~((uint32_t)0x00003FFF)) == 0); + REG_BLE_WR(BLE_SPIPTRCNTL2_ADDR, (REG_BLE_RD(BLE_SPIPTRCNTL2_ADDR) & ~((uint32_t)0x00003FFF)) | ((uint32_t)rssiptr << 0)); +} + +/** + * @brief SPIPTRCNTL3 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  29:16           CTESAMPPTR   0x0
+ *  13:00          RXPKTTYPPTR   0x0
+ * 
+ */ +#define BLE_SPIPTRCNTL3_ADDR 0x009008AC +#define BLE_SPIPTRCNTL3_OFFSET 0x000000AC +#define BLE_SPIPTRCNTL3_INDEX 0x0000002B +#define BLE_SPIPTRCNTL3_RESET 0x00000000 + +__INLINE uint32_t ble_spiptrcntl3_get(void) +{ + return REG_BLE_RD(BLE_SPIPTRCNTL3_ADDR); +} + +__INLINE void ble_spiptrcntl3_set(uint32_t value) +{ + REG_BLE_WR(BLE_SPIPTRCNTL3_ADDR, value); +} + +// field definitions +#define BLE_CTESAMPPTR_MASK ((uint32_t)0x3FFF0000) +#define BLE_CTESAMPPTR_LSB 16 +#define BLE_CTESAMPPTR_WIDTH ((uint32_t)0x0000000E) +#define BLE_RXPKTTYPPTR_MASK ((uint32_t)0x00003FFF) +#define BLE_RXPKTTYPPTR_LSB 0 +#define BLE_RXPKTTYPPTR_WIDTH ((uint32_t)0x0000000E) + +#define BLE_CTESAMPPTR_RST 0x0 +#define BLE_RXPKTTYPPTR_RST 0x0 + +__INLINE void ble_spiptrcntl3_pack(uint16_t ctesampptr, uint16_t rxpkttypptr) +{ + BLE_ASSERT_ERR((((uint32_t)ctesampptr << 16) & ~((uint32_t)0x3FFF0000)) == 0); + BLE_ASSERT_ERR((((uint32_t)rxpkttypptr << 0) & ~((uint32_t)0x00003FFF)) == 0); + REG_BLE_WR(BLE_SPIPTRCNTL3_ADDR, ((uint32_t)ctesampptr << 16) | ((uint32_t)rxpkttypptr << 0)); +} + +__INLINE void ble_spiptrcntl3_unpack(uint16_t* ctesampptr, uint16_t* rxpkttypptr) +{ + uint32_t localVal = REG_BLE_RD(BLE_SPIPTRCNTL3_ADDR); + + *ctesampptr = (localVal & ((uint32_t)0x3FFF0000)) >> 16; + *rxpkttypptr = (localVal & ((uint32_t)0x00003FFF)) >> 0; +} + +__INLINE uint16_t ble_spiptrcntl3_ctesampptr_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SPIPTRCNTL3_ADDR); + return ((localVal & ((uint32_t)0x3FFF0000)) >> 16); +} + +__INLINE void ble_spiptrcntl3_ctesampptr_setf(uint16_t ctesampptr) +{ + BLE_ASSERT_ERR((((uint32_t)ctesampptr << 16) & ~((uint32_t)0x3FFF0000)) == 0); + REG_BLE_WR(BLE_SPIPTRCNTL3_ADDR, (REG_BLE_RD(BLE_SPIPTRCNTL3_ADDR) & ~((uint32_t)0x3FFF0000)) | ((uint32_t)ctesampptr << 16)); +} + +__INLINE uint16_t ble_spiptrcntl3_rxpkttypptr_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SPIPTRCNTL3_ADDR); + return ((localVal & ((uint32_t)0x00003FFF)) >> 0); +} + +__INLINE void ble_spiptrcntl3_rxpkttypptr_setf(uint16_t rxpkttypptr) +{ + BLE_ASSERT_ERR((((uint32_t)rxpkttypptr << 0) & ~((uint32_t)0x00003FFF)) == 0); + REG_BLE_WR(BLE_SPIPTRCNTL3_ADDR, (REG_BLE_RD(BLE_SPIPTRCNTL3_ADDR) & ~((uint32_t)0x00003FFF)) | ((uint32_t)rxpkttypptr << 0)); +} + +/** + * @brief AESCNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     01             AES_MODE   0
+ *     00            AES_START   0
+ * 
+ */ +#define BLE_AESCNTL_ADDR 0x009008B0 +#define BLE_AESCNTL_OFFSET 0x000000B0 +#define BLE_AESCNTL_INDEX 0x0000002C +#define BLE_AESCNTL_RESET 0x00000000 + +__INLINE uint32_t ble_aescntl_get(void) +{ + return REG_BLE_RD(BLE_AESCNTL_ADDR); +} + +__INLINE void ble_aescntl_set(uint32_t value) +{ + REG_BLE_WR(BLE_AESCNTL_ADDR, value); +} + +// field definitions +#define BLE_AES_MODE_BIT ((uint32_t)0x00000002) +#define BLE_AES_MODE_POS 1 +#define BLE_AES_START_BIT ((uint32_t)0x00000001) +#define BLE_AES_START_POS 0 + +#define BLE_AES_MODE_RST 0x0 +#define BLE_AES_START_RST 0x0 + +__INLINE void ble_aescntl_pack(uint8_t aesmode, uint8_t aesstart) +{ + BLE_ASSERT_ERR((((uint32_t)aesmode << 1) & ~((uint32_t)0x00000002)) == 0); + BLE_ASSERT_ERR((((uint32_t)aesstart << 0) & ~((uint32_t)0x00000001)) == 0); + REG_BLE_WR(BLE_AESCNTL_ADDR, ((uint32_t)aesmode << 1) | ((uint32_t)aesstart << 0)); +} + +__INLINE void ble_aescntl_unpack(uint8_t* aesmode, uint8_t* aesstart) +{ + uint32_t localVal = REG_BLE_RD(BLE_AESCNTL_ADDR); + + *aesmode = (localVal & ((uint32_t)0x00000002)) >> 1; + *aesstart = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +__INLINE uint8_t ble_aescntl_aes_mode_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_AESCNTL_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +__INLINE void ble_aescntl_aes_mode_setf(uint8_t aesmode) +{ + BLE_ASSERT_ERR((((uint32_t)aesmode << 1) & ~((uint32_t)0x00000002)) == 0); + REG_BLE_WR(BLE_AESCNTL_ADDR, (REG_BLE_RD(BLE_AESCNTL_ADDR) & ~((uint32_t)0x00000002)) | ((uint32_t)aesmode << 1)); +} + +__INLINE uint8_t ble_aescntl_aes_start_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_AESCNTL_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +__INLINE void ble_aescntl_aes_start_setf(uint8_t aesstart) +{ + BLE_ASSERT_ERR((((uint32_t)aesstart << 0) & ~((uint32_t)0x00000001)) == 0); + REG_BLE_WR(BLE_AESCNTL_ADDR, (REG_BLE_RD(BLE_AESCNTL_ADDR) & ~((uint32_t)0x00000001)) | ((uint32_t)aesstart << 0)); +} + +/** + * @brief AESKEY31_0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00           AESKEY31_0   0x0
+ * 
+ */ +#define BLE_AESKEY31_0_ADDR 0x009008B4 +#define BLE_AESKEY31_0_OFFSET 0x000000B4 +#define BLE_AESKEY31_0_INDEX 0x0000002D +#define BLE_AESKEY31_0_RESET 0x00000000 + +__INLINE uint32_t ble_aeskey31_0_get(void) +{ + return REG_BLE_RD(BLE_AESKEY31_0_ADDR); +} + +__INLINE void ble_aeskey31_0_set(uint32_t value) +{ + REG_BLE_WR(BLE_AESKEY31_0_ADDR, value); +} + +// field definitions +#define BLE_AESKEY31_0_MASK ((uint32_t)0xFFFFFFFF) +#define BLE_AESKEY31_0_LSB 0 +#define BLE_AESKEY31_0_WIDTH ((uint32_t)0x00000020) + +#define BLE_AESKEY31_0_RST 0x0 + +__INLINE uint32_t ble_aeskey31_0_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_AESKEY31_0_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_aeskey31_0_setf(uint32_t aeskey310) +{ + BLE_ASSERT_ERR((((uint32_t)aeskey310 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_BLE_WR(BLE_AESKEY31_0_ADDR, (uint32_t)aeskey310 << 0); +} + +/** + * @brief AESKEY63_32 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00          AESKEY63_32   0x0
+ * 
+ */ +#define BLE_AESKEY63_32_ADDR 0x009008B8 +#define BLE_AESKEY63_32_OFFSET 0x000000B8 +#define BLE_AESKEY63_32_INDEX 0x0000002E +#define BLE_AESKEY63_32_RESET 0x00000000 + +__INLINE uint32_t ble_aeskey63_32_get(void) +{ + return REG_BLE_RD(BLE_AESKEY63_32_ADDR); +} + +__INLINE void ble_aeskey63_32_set(uint32_t value) +{ + REG_BLE_WR(BLE_AESKEY63_32_ADDR, value); +} + +// field definitions +#define BLE_AESKEY63_32_MASK ((uint32_t)0xFFFFFFFF) +#define BLE_AESKEY63_32_LSB 0 +#define BLE_AESKEY63_32_WIDTH ((uint32_t)0x00000020) + +#define BLE_AESKEY63_32_RST 0x0 + +__INLINE uint32_t ble_aeskey63_32_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_AESKEY63_32_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_aeskey63_32_setf(uint32_t aeskey6332) +{ + BLE_ASSERT_ERR((((uint32_t)aeskey6332 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_BLE_WR(BLE_AESKEY63_32_ADDR, (uint32_t)aeskey6332 << 0); +} + +/** + * @brief AESKEY95_64 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00          AESKEY95_64   0x0
+ * 
+ */ +#define BLE_AESKEY95_64_ADDR 0x009008BC +#define BLE_AESKEY95_64_OFFSET 0x000000BC +#define BLE_AESKEY95_64_INDEX 0x0000002F +#define BLE_AESKEY95_64_RESET 0x00000000 + +__INLINE uint32_t ble_aeskey95_64_get(void) +{ + return REG_BLE_RD(BLE_AESKEY95_64_ADDR); +} + +__INLINE void ble_aeskey95_64_set(uint32_t value) +{ + REG_BLE_WR(BLE_AESKEY95_64_ADDR, value); +} + +// field definitions +#define BLE_AESKEY95_64_MASK ((uint32_t)0xFFFFFFFF) +#define BLE_AESKEY95_64_LSB 0 +#define BLE_AESKEY95_64_WIDTH ((uint32_t)0x00000020) + +#define BLE_AESKEY95_64_RST 0x0 + +__INLINE uint32_t ble_aeskey95_64_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_AESKEY95_64_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_aeskey95_64_setf(uint32_t aeskey9564) +{ + BLE_ASSERT_ERR((((uint32_t)aeskey9564 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_BLE_WR(BLE_AESKEY95_64_ADDR, (uint32_t)aeskey9564 << 0); +} + +/** + * @brief AESKEY127_96 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00         AESKEY127_96   0x0
+ * 
+ */ +#define BLE_AESKEY127_96_ADDR 0x009008C0 +#define BLE_AESKEY127_96_OFFSET 0x000000C0 +#define BLE_AESKEY127_96_INDEX 0x00000030 +#define BLE_AESKEY127_96_RESET 0x00000000 + +__INLINE uint32_t ble_aeskey127_96_get(void) +{ + return REG_BLE_RD(BLE_AESKEY127_96_ADDR); +} + +__INLINE void ble_aeskey127_96_set(uint32_t value) +{ + REG_BLE_WR(BLE_AESKEY127_96_ADDR, value); +} + +// field definitions +#define BLE_AESKEY127_96_MASK ((uint32_t)0xFFFFFFFF) +#define BLE_AESKEY127_96_LSB 0 +#define BLE_AESKEY127_96_WIDTH ((uint32_t)0x00000020) + +#define BLE_AESKEY127_96_RST 0x0 + +__INLINE uint32_t ble_aeskey127_96_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_AESKEY127_96_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_aeskey127_96_setf(uint32_t aeskey12796) +{ + BLE_ASSERT_ERR((((uint32_t)aeskey12796 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_BLE_WR(BLE_AESKEY127_96_ADDR, (uint32_t)aeskey12796 << 0); +} + +/** + * @brief AESPTR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  13:00               AESPTR   0x0
+ * 
+ */ +#define BLE_AESPTR_ADDR 0x009008C4 +#define BLE_AESPTR_OFFSET 0x000000C4 +#define BLE_AESPTR_INDEX 0x00000031 +#define BLE_AESPTR_RESET 0x00000000 + +__INLINE uint32_t ble_aesptr_get(void) +{ + return REG_BLE_RD(BLE_AESPTR_ADDR); +} + +__INLINE void ble_aesptr_set(uint32_t value) +{ + REG_BLE_WR(BLE_AESPTR_ADDR, value); +} + +// field definitions +#define BLE_AESPTR_MASK ((uint32_t)0x00003FFF) +#define BLE_AESPTR_LSB 0 +#define BLE_AESPTR_WIDTH ((uint32_t)0x0000000E) + +#define BLE_AESPTR_RST 0x0 + +__INLINE uint16_t ble_aesptr_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_AESPTR_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0x00003FFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_aesptr_setf(uint16_t aesptr) +{ + BLE_ASSERT_ERR((((uint32_t)aesptr << 0) & ~((uint32_t)0x00003FFF)) == 0); + REG_BLE_WR(BLE_AESPTR_ADDR, (uint32_t)aesptr << 0); +} + +/** + * @brief TXMICVAL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00             TXMICVAL   0x0
+ * 
+ */ +#define BLE_TXMICVAL_ADDR 0x009008C8 +#define BLE_TXMICVAL_OFFSET 0x000000C8 +#define BLE_TXMICVAL_INDEX 0x00000032 +#define BLE_TXMICVAL_RESET 0x00000000 + +__INLINE uint32_t ble_txmicval_get(void) +{ + return REG_BLE_RD(BLE_TXMICVAL_ADDR); +} + +// field definitions +#define BLE_TXMICVAL_MASK ((uint32_t)0xFFFFFFFF) +#define BLE_TXMICVAL_LSB 0 +#define BLE_TXMICVAL_WIDTH ((uint32_t)0x00000020) + +#define BLE_TXMICVAL_RST 0x0 + +__INLINE uint32_t ble_txmicval_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_TXMICVAL_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief RXMICVAL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00             RXMICVAL   0x0
+ * 
+ */ +#define BLE_RXMICVAL_ADDR 0x009008CC +#define BLE_RXMICVAL_OFFSET 0x000000CC +#define BLE_RXMICVAL_INDEX 0x00000033 +#define BLE_RXMICVAL_RESET 0x00000000 + +__INLINE uint32_t ble_rxmicval_get(void) +{ + return REG_BLE_RD(BLE_RXMICVAL_ADDR); +} + +// field definitions +#define BLE_RXMICVAL_MASK ((uint32_t)0xFFFFFFFF) +#define BLE_RXMICVAL_LSB 0 +#define BLE_RXMICVAL_WIDTH ((uint32_t)0x00000020) + +#define BLE_RXMICVAL_RST 0x0 + +__INLINE uint32_t ble_rxmicval_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RXMICVAL_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief RFTESTCNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31           INFINITERX   0
+ *     27           RXPKTCNTEN   0
+ *  25:24        PERCOUNT_MODE   0x0
+ *     15           INFINITETX   0
+ *     14          TXLENGTHSRC   0
+ *     13             PRBSTYPE   0
+ *     12             TXPLDSRC   0
+ *     11           TXPKTCNTEN   0
+ *  07:00             TXLENGTH   0x0
+ * 
+ */ +#define BLE_RFTESTCNTL_ADDR 0x009008D0 +#define BLE_RFTESTCNTL_OFFSET 0x000000D0 +#define BLE_RFTESTCNTL_INDEX 0x00000034 +#define BLE_RFTESTCNTL_RESET 0x00000000 + +__INLINE uint32_t ble_rftestcntl_get(void) +{ + return REG_BLE_RD(BLE_RFTESTCNTL_ADDR); +} + +__INLINE void ble_rftestcntl_set(uint32_t value) +{ + REG_BLE_WR(BLE_RFTESTCNTL_ADDR, value); +} + +// field definitions +#define BLE_INFINITERX_BIT ((uint32_t)0x80000000) +#define BLE_INFINITERX_POS 31 +#define BLE_RXPKTCNTEN_BIT ((uint32_t)0x08000000) +#define BLE_RXPKTCNTEN_POS 27 +#define BLE_PERCOUNT_MODE_MASK ((uint32_t)0x03000000) +#define BLE_PERCOUNT_MODE_LSB 24 +#define BLE_PERCOUNT_MODE_WIDTH ((uint32_t)0x00000002) +#define BLE_INFINITETX_BIT ((uint32_t)0x00008000) +#define BLE_INFINITETX_POS 15 +#define BLE_TXLENGTHSRC_BIT ((uint32_t)0x00004000) +#define BLE_TXLENGTHSRC_POS 14 +#define BLE_PRBSTYPE_BIT ((uint32_t)0x00002000) +#define BLE_PRBSTYPE_POS 13 +#define BLE_TXPLDSRC_BIT ((uint32_t)0x00001000) +#define BLE_TXPLDSRC_POS 12 +#define BLE_TXPKTCNTEN_BIT ((uint32_t)0x00000800) +#define BLE_TXPKTCNTEN_POS 11 +#define BLE_TXLENGTH_MASK ((uint32_t)0x000000FF) +#define BLE_TXLENGTH_LSB 0 +#define BLE_TXLENGTH_WIDTH ((uint32_t)0x00000008) + +#define BLE_INFINITERX_RST 0x0 +#define BLE_RXPKTCNTEN_RST 0x0 +#define BLE_PERCOUNT_MODE_RST 0x0 +#define BLE_INFINITETX_RST 0x0 +#define BLE_TXLENGTHSRC_RST 0x0 +#define BLE_PRBSTYPE_RST 0x0 +#define BLE_TXPLDSRC_RST 0x0 +#define BLE_TXPKTCNTEN_RST 0x0 +#define BLE_TXLENGTH_RST 0x0 + +__INLINE void ble_rftestcntl_pack(uint8_t infiniterx, uint8_t rxpktcnten, uint8_t percountmode, uint8_t infinitetx, uint8_t txlengthsrc, uint8_t prbstype, uint8_t txpldsrc, uint8_t txpktcnten, uint8_t txlength) +{ + BLE_ASSERT_ERR((((uint32_t)infiniterx << 31) & ~((uint32_t)0x80000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)rxpktcnten << 27) & ~((uint32_t)0x08000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)percountmode << 24) & ~((uint32_t)0x03000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)infinitetx << 15) & ~((uint32_t)0x00008000)) == 0); + BLE_ASSERT_ERR((((uint32_t)txlengthsrc << 14) & ~((uint32_t)0x00004000)) == 0); + BLE_ASSERT_ERR((((uint32_t)prbstype << 13) & ~((uint32_t)0x00002000)) == 0); + BLE_ASSERT_ERR((((uint32_t)txpldsrc << 12) & ~((uint32_t)0x00001000)) == 0); + BLE_ASSERT_ERR((((uint32_t)txpktcnten << 11) & ~((uint32_t)0x00000800)) == 0); + BLE_ASSERT_ERR((((uint32_t)txlength << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_BLE_WR(BLE_RFTESTCNTL_ADDR, ((uint32_t)infiniterx << 31) | ((uint32_t)rxpktcnten << 27) | ((uint32_t)percountmode << 24) | ((uint32_t)infinitetx << 15) | ((uint32_t)txlengthsrc << 14) | ((uint32_t)prbstype << 13) | ((uint32_t)txpldsrc << 12) | ((uint32_t)txpktcnten << 11) | ((uint32_t)txlength << 0)); +} + +__INLINE void ble_rftestcntl_unpack(uint8_t* infiniterx, uint8_t* rxpktcnten, uint8_t* percountmode, uint8_t* infinitetx, uint8_t* txlengthsrc, uint8_t* prbstype, uint8_t* txpldsrc, uint8_t* txpktcnten, uint8_t* txlength) +{ + uint32_t localVal = REG_BLE_RD(BLE_RFTESTCNTL_ADDR); + + *infiniterx = (localVal & ((uint32_t)0x80000000)) >> 31; + *rxpktcnten = (localVal & ((uint32_t)0x08000000)) >> 27; + *percountmode = (localVal & ((uint32_t)0x03000000)) >> 24; + *infinitetx = (localVal & ((uint32_t)0x00008000)) >> 15; + *txlengthsrc = (localVal & ((uint32_t)0x00004000)) >> 14; + *prbstype = (localVal & ((uint32_t)0x00002000)) >> 13; + *txpldsrc = (localVal & ((uint32_t)0x00001000)) >> 12; + *txpktcnten = (localVal & ((uint32_t)0x00000800)) >> 11; + *txlength = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +__INLINE uint8_t ble_rftestcntl_infiniterx_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RFTESTCNTL_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +__INLINE void ble_rftestcntl_infiniterx_setf(uint8_t infiniterx) +{ + BLE_ASSERT_ERR((((uint32_t)infiniterx << 31) & ~((uint32_t)0x80000000)) == 0); + REG_BLE_WR(BLE_RFTESTCNTL_ADDR, (REG_BLE_RD(BLE_RFTESTCNTL_ADDR) & ~((uint32_t)0x80000000)) | ((uint32_t)infiniterx << 31)); +} + +__INLINE uint8_t ble_rftestcntl_rxpktcnten_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RFTESTCNTL_ADDR); + return ((localVal & ((uint32_t)0x08000000)) >> 27); +} + +__INLINE void ble_rftestcntl_rxpktcnten_setf(uint8_t rxpktcnten) +{ + BLE_ASSERT_ERR((((uint32_t)rxpktcnten << 27) & ~((uint32_t)0x08000000)) == 0); + REG_BLE_WR(BLE_RFTESTCNTL_ADDR, (REG_BLE_RD(BLE_RFTESTCNTL_ADDR) & ~((uint32_t)0x08000000)) | ((uint32_t)rxpktcnten << 27)); +} + +__INLINE uint8_t ble_rftestcntl_percount_mode_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RFTESTCNTL_ADDR); + return ((localVal & ((uint32_t)0x03000000)) >> 24); +} + +__INLINE void ble_rftestcntl_percount_mode_setf(uint8_t percountmode) +{ + BLE_ASSERT_ERR((((uint32_t)percountmode << 24) & ~((uint32_t)0x03000000)) == 0); + REG_BLE_WR(BLE_RFTESTCNTL_ADDR, (REG_BLE_RD(BLE_RFTESTCNTL_ADDR) & ~((uint32_t)0x03000000)) | ((uint32_t)percountmode << 24)); +} + +__INLINE uint8_t ble_rftestcntl_infinitetx_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RFTESTCNTL_ADDR); + return ((localVal & ((uint32_t)0x00008000)) >> 15); +} + +__INLINE void ble_rftestcntl_infinitetx_setf(uint8_t infinitetx) +{ + BLE_ASSERT_ERR((((uint32_t)infinitetx << 15) & ~((uint32_t)0x00008000)) == 0); + REG_BLE_WR(BLE_RFTESTCNTL_ADDR, (REG_BLE_RD(BLE_RFTESTCNTL_ADDR) & ~((uint32_t)0x00008000)) | ((uint32_t)infinitetx << 15)); +} + +__INLINE uint8_t ble_rftestcntl_txlengthsrc_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RFTESTCNTL_ADDR); + return ((localVal & ((uint32_t)0x00004000)) >> 14); +} + +__INLINE void ble_rftestcntl_txlengthsrc_setf(uint8_t txlengthsrc) +{ + BLE_ASSERT_ERR((((uint32_t)txlengthsrc << 14) & ~((uint32_t)0x00004000)) == 0); + REG_BLE_WR(BLE_RFTESTCNTL_ADDR, (REG_BLE_RD(BLE_RFTESTCNTL_ADDR) & ~((uint32_t)0x00004000)) | ((uint32_t)txlengthsrc << 14)); +} + +__INLINE uint8_t ble_rftestcntl_prbstype_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RFTESTCNTL_ADDR); + return ((localVal & ((uint32_t)0x00002000)) >> 13); +} + +__INLINE void ble_rftestcntl_prbstype_setf(uint8_t prbstype) +{ + BLE_ASSERT_ERR((((uint32_t)prbstype << 13) & ~((uint32_t)0x00002000)) == 0); + REG_BLE_WR(BLE_RFTESTCNTL_ADDR, (REG_BLE_RD(BLE_RFTESTCNTL_ADDR) & ~((uint32_t)0x00002000)) | ((uint32_t)prbstype << 13)); +} + +__INLINE uint8_t ble_rftestcntl_txpldsrc_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RFTESTCNTL_ADDR); + return ((localVal & ((uint32_t)0x00001000)) >> 12); +} + +__INLINE void ble_rftestcntl_txpldsrc_setf(uint8_t txpldsrc) +{ + BLE_ASSERT_ERR((((uint32_t)txpldsrc << 12) & ~((uint32_t)0x00001000)) == 0); + REG_BLE_WR(BLE_RFTESTCNTL_ADDR, (REG_BLE_RD(BLE_RFTESTCNTL_ADDR) & ~((uint32_t)0x00001000)) | ((uint32_t)txpldsrc << 12)); +} + +__INLINE uint8_t ble_rftestcntl_txpktcnten_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RFTESTCNTL_ADDR); + return ((localVal & ((uint32_t)0x00000800)) >> 11); +} + +__INLINE void ble_rftestcntl_txpktcnten_setf(uint8_t txpktcnten) +{ + BLE_ASSERT_ERR((((uint32_t)txpktcnten << 11) & ~((uint32_t)0x00000800)) == 0); + REG_BLE_WR(BLE_RFTESTCNTL_ADDR, (REG_BLE_RD(BLE_RFTESTCNTL_ADDR) & ~((uint32_t)0x00000800)) | ((uint32_t)txpktcnten << 11)); +} + +__INLINE uint8_t ble_rftestcntl_txlength_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RFTESTCNTL_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +__INLINE void ble_rftestcntl_txlength_setf(uint8_t txlength) +{ + BLE_ASSERT_ERR((((uint32_t)txlength << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_BLE_WR(BLE_RFTESTCNTL_ADDR, (REG_BLE_RD(BLE_RFTESTCNTL_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)txlength << 0)); +} + +/** + * @brief RFTESTTXSTAT register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00             TXPKTCNT   0x0
+ * 
+ */ +#define BLE_RFTESTTXSTAT_ADDR 0x009008D4 +#define BLE_RFTESTTXSTAT_OFFSET 0x000000D4 +#define BLE_RFTESTTXSTAT_INDEX 0x00000035 +#define BLE_RFTESTTXSTAT_RESET 0x00000000 + +__INLINE uint32_t ble_rftesttxstat_get(void) +{ + return REG_BLE_RD(BLE_RFTESTTXSTAT_ADDR); +} + +// field definitions +#define BLE_TXPKTCNT_MASK ((uint32_t)0xFFFFFFFF) +#define BLE_TXPKTCNT_LSB 0 +#define BLE_TXPKTCNT_WIDTH ((uint32_t)0x00000020) + +#define BLE_TXPKTCNT_RST 0x0 + +__INLINE uint32_t ble_rftesttxstat_txpktcnt_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RFTESTTXSTAT_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief RFTESTRXSTAT register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00             RXPKTCNT   0x0
+ * 
+ */ +#define BLE_RFTESTRXSTAT_ADDR 0x009008D8 +#define BLE_RFTESTRXSTAT_OFFSET 0x000000D8 +#define BLE_RFTESTRXSTAT_INDEX 0x00000036 +#define BLE_RFTESTRXSTAT_RESET 0x00000000 + +__INLINE uint32_t ble_rftestrxstat_get(void) +{ + return REG_BLE_RD(BLE_RFTESTRXSTAT_ADDR); +} + +// field definitions +#define BLE_RXPKTCNT_MASK ((uint32_t)0xFFFFFFFF) +#define BLE_RXPKTCNT_LSB 0 +#define BLE_RXPKTCNT_WIDTH ((uint32_t)0x00000020) + +#define BLE_RXPKTCNT_RST 0x0 + +__INLINE uint32_t ble_rftestrxstat_rxpktcnt_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RFTESTRXSTAT_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief TIMGENCNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  25:16   PREFETCHABORT_TIME   0x1FE
+ *  08:00        PREFETCH_TIME   0x96
+ * 
+ */ +#define BLE_TIMGENCNTL_ADDR 0x009008E0 +#define BLE_TIMGENCNTL_OFFSET 0x000000E0 +#define BLE_TIMGENCNTL_INDEX 0x00000038 +#define BLE_TIMGENCNTL_RESET 0x01FE0096 + +__INLINE uint32_t ble_timgencntl_get(void) +{ + return REG_BLE_RD(BLE_TIMGENCNTL_ADDR); +} + +__INLINE void ble_timgencntl_set(uint32_t value) +{ + REG_BLE_WR(BLE_TIMGENCNTL_ADDR, value); +} + +// field definitions +#define BLE_PREFETCHABORT_TIME_MASK ((uint32_t)0x03FF0000) +#define BLE_PREFETCHABORT_TIME_LSB 16 +#define BLE_PREFETCHABORT_TIME_WIDTH ((uint32_t)0x0000000A) +#define BLE_PREFETCH_TIME_MASK ((uint32_t)0x000001FF) +#define BLE_PREFETCH_TIME_LSB 0 +#define BLE_PREFETCH_TIME_WIDTH ((uint32_t)0x00000009) + +#define BLE_PREFETCHABORT_TIME_RST 0x1FE +#define BLE_PREFETCH_TIME_RST 0x96 + +__INLINE void ble_timgencntl_pack(uint16_t prefetchaborttime, uint16_t prefetchtime) +{ + BLE_ASSERT_ERR((((uint32_t)prefetchaborttime << 16) & ~((uint32_t)0x03FF0000)) == 0); + BLE_ASSERT_ERR((((uint32_t)prefetchtime << 0) & ~((uint32_t)0x000001FF)) == 0); + REG_BLE_WR(BLE_TIMGENCNTL_ADDR, ((uint32_t)prefetchaborttime << 16) | ((uint32_t)prefetchtime << 0)); +} + +__INLINE void ble_timgencntl_unpack(uint16_t* prefetchaborttime, uint16_t* prefetchtime) +{ + uint32_t localVal = REG_BLE_RD(BLE_TIMGENCNTL_ADDR); + + *prefetchaborttime = (localVal & ((uint32_t)0x03FF0000)) >> 16; + *prefetchtime = (localVal & ((uint32_t)0x000001FF)) >> 0; +} + +__INLINE uint16_t ble_timgencntl_prefetchabort_time_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_TIMGENCNTL_ADDR); + return ((localVal & ((uint32_t)0x03FF0000)) >> 16); +} + +__INLINE void ble_timgencntl_prefetchabort_time_setf(uint16_t prefetchaborttime) +{ + BLE_ASSERT_ERR((((uint32_t)prefetchaborttime << 16) & ~((uint32_t)0x03FF0000)) == 0); + REG_BLE_WR(BLE_TIMGENCNTL_ADDR, (REG_BLE_RD(BLE_TIMGENCNTL_ADDR) & ~((uint32_t)0x03FF0000)) | ((uint32_t)prefetchaborttime << 16)); +} + +__INLINE uint16_t ble_timgencntl_prefetch_time_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_TIMGENCNTL_ADDR); + return ((localVal & ((uint32_t)0x000001FF)) >> 0); +} + +__INLINE void ble_timgencntl_prefetch_time_setf(uint16_t prefetchtime) +{ + BLE_ASSERT_ERR((((uint32_t)prefetchtime << 0) & ~((uint32_t)0x000001FF)) == 0); + REG_BLE_WR(BLE_TIMGENCNTL_ADDR, (REG_BLE_RD(BLE_TIMGENCNTL_ADDR) & ~((uint32_t)0x000001FF)) | ((uint32_t)prefetchtime << 0)); +} + +/** + * @brief FINETIMTGT register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  27:00           FINETARGET   0x0
+ * 
+ */ +#define BLE_FINETIMTGT_ADDR 0x009008E4 +#define BLE_FINETIMTGT_OFFSET 0x000000E4 +#define BLE_FINETIMTGT_INDEX 0x00000039 +#define BLE_FINETIMTGT_RESET 0x00000000 + +__INLINE uint32_t ble_finetimtgt_get(void) +{ + return REG_BLE_RD(BLE_FINETIMTGT_ADDR); +} + +__INLINE void ble_finetimtgt_set(uint32_t value) +{ + REG_BLE_WR(BLE_FINETIMTGT_ADDR, value); +} + +// field definitions +#define BLE_FINETARGET_MASK ((uint32_t)0x0FFFFFFF) +#define BLE_FINETARGET_LSB 0 +#define BLE_FINETARGET_WIDTH ((uint32_t)0x0000001C) + +#define BLE_FINETARGET_RST 0x0 + +__INLINE uint32_t ble_finetimtgt_finetarget_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_FINETIMTGT_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0x0FFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_finetimtgt_finetarget_setf(uint32_t finetarget) +{ + BLE_ASSERT_ERR((((uint32_t)finetarget << 0) & ~((uint32_t)0x0FFFFFFF)) == 0); + REG_BLE_WR(BLE_FINETIMTGT_ADDR, (uint32_t)finetarget << 0); +} + +/** + * @brief CLKNTGT1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  27:00             CLKNTGT1   0x0
+ * 
+ */ +#define BLE_CLKNTGT1_ADDR 0x009008E8 +#define BLE_CLKNTGT1_OFFSET 0x000000E8 +#define BLE_CLKNTGT1_INDEX 0x0000003A +#define BLE_CLKNTGT1_RESET 0x00000000 + +__INLINE uint32_t ble_clkntgt1_get(void) +{ + return REG_BLE_RD(BLE_CLKNTGT1_ADDR); +} + +__INLINE void ble_clkntgt1_set(uint32_t value) +{ + REG_BLE_WR(BLE_CLKNTGT1_ADDR, value); +} + +// field definitions +#define BLE_CLKNTGT1_MASK ((uint32_t)0x0FFFFFFF) +#define BLE_CLKNTGT1_LSB 0 +#define BLE_CLKNTGT1_WIDTH ((uint32_t)0x0000001C) + +#define BLE_CLKNTGT1_RST 0x0 + +__INLINE uint32_t ble_clkntgt1_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_CLKNTGT1_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0x0FFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_clkntgt1_setf(uint32_t clkntgt1) +{ + BLE_ASSERT_ERR((((uint32_t)clkntgt1 << 0) & ~((uint32_t)0x0FFFFFFF)) == 0); + REG_BLE_WR(BLE_CLKNTGT1_ADDR, (uint32_t)clkntgt1 << 0); +} + +/** + * @brief HMICROSECTGT1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  09:00        HMICROSECTGT1   0x0
+ * 
+ */ +#define BLE_HMICROSECTGT1_ADDR 0x009008EC +#define BLE_HMICROSECTGT1_OFFSET 0x000000EC +#define BLE_HMICROSECTGT1_INDEX 0x0000003B +#define BLE_HMICROSECTGT1_RESET 0x00000000 + +__INLINE uint32_t ble_hmicrosectgt1_get(void) +{ + return REG_BLE_RD(BLE_HMICROSECTGT1_ADDR); +} + +__INLINE void ble_hmicrosectgt1_set(uint32_t value) +{ + REG_BLE_WR(BLE_HMICROSECTGT1_ADDR, value); +} + +// field definitions +#define BLE_HMICROSECTGT1_MASK ((uint32_t)0x000003FF) +#define BLE_HMICROSECTGT1_LSB 0 +#define BLE_HMICROSECTGT1_WIDTH ((uint32_t)0x0000000A) + +#define BLE_HMICROSECTGT1_RST 0x0 + +__INLINE uint16_t ble_hmicrosectgt1_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_HMICROSECTGT1_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0x000003FF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_hmicrosectgt1_setf(uint16_t hmicrosectgt1) +{ + BLE_ASSERT_ERR((((uint32_t)hmicrosectgt1 << 0) & ~((uint32_t)0x000003FF)) == 0); + REG_BLE_WR(BLE_HMICROSECTGT1_ADDR, (uint32_t)hmicrosectgt1 << 0); +} + +/** + * @brief CLKNTGT2 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  27:00             CLKNTGT2   0x0
+ * 
+ */ +#define BLE_CLKNTGT2_ADDR 0x009008F0 +#define BLE_CLKNTGT2_OFFSET 0x000000F0 +#define BLE_CLKNTGT2_INDEX 0x0000003C +#define BLE_CLKNTGT2_RESET 0x00000000 + +__INLINE uint32_t ble_clkntgt2_get(void) +{ + return REG_BLE_RD(BLE_CLKNTGT2_ADDR); +} + +__INLINE void ble_clkntgt2_set(uint32_t value) +{ + REG_BLE_WR(BLE_CLKNTGT2_ADDR, value); +} + +// field definitions +#define BLE_CLKNTGT2_MASK ((uint32_t)0x0FFFFFFF) +#define BLE_CLKNTGT2_LSB 0 +#define BLE_CLKNTGT2_WIDTH ((uint32_t)0x0000001C) + +#define BLE_CLKNTGT2_RST 0x0 + +__INLINE uint32_t ble_clkntgt2_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_CLKNTGT2_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0x0FFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_clkntgt2_setf(uint32_t clkntgt2) +{ + BLE_ASSERT_ERR((((uint32_t)clkntgt2 << 0) & ~((uint32_t)0x0FFFFFFF)) == 0); + REG_BLE_WR(BLE_CLKNTGT2_ADDR, (uint32_t)clkntgt2 << 0); +} + +/** + * @brief HMICROSECTGT2 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  09:00        HMICROSECTGT2   0x0
+ * 
+ */ +#define BLE_HMICROSECTGT2_ADDR 0x009008F4 +#define BLE_HMICROSECTGT2_OFFSET 0x000000F4 +#define BLE_HMICROSECTGT2_INDEX 0x0000003D +#define BLE_HMICROSECTGT2_RESET 0x00000000 + +__INLINE uint32_t ble_hmicrosectgt2_get(void) +{ + return REG_BLE_RD(BLE_HMICROSECTGT2_ADDR); +} + +__INLINE void ble_hmicrosectgt2_set(uint32_t value) +{ + REG_BLE_WR(BLE_HMICROSECTGT2_ADDR, value); +} + +// field definitions +#define BLE_HMICROSECTGT2_MASK ((uint32_t)0x000003FF) +#define BLE_HMICROSECTGT2_LSB 0 +#define BLE_HMICROSECTGT2_WIDTH ((uint32_t)0x0000000A) + +#define BLE_HMICROSECTGT2_RST 0x0 + +__INLINE uint16_t ble_hmicrosectgt2_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_HMICROSECTGT2_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0x000003FF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_hmicrosectgt2_setf(uint16_t hmicrosectgt2) +{ + BLE_ASSERT_ERR((((uint32_t)hmicrosectgt2 << 0) & ~((uint32_t)0x000003FF)) == 0); + REG_BLE_WR(BLE_HMICROSECTGT2_ADDR, (uint32_t)hmicrosectgt2 << 0); +} + +/** + * @brief SLOTCLK register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31                 SAMP   0
+ *     30             CLKN_UPD   0
+ *  27:00                 SCLK   0x0
+ * 
+ */ +#define BLE_SLOTCLK_ADDR 0x009008F8 +#define BLE_SLOTCLK_OFFSET 0x000000F8 +#define BLE_SLOTCLK_INDEX 0x0000003E +#define BLE_SLOTCLK_RESET 0x00000000 + +__INLINE uint32_t ble_slotclk_get(void) +{ + return REG_BLE_RD(BLE_SLOTCLK_ADDR); +} + +__INLINE void ble_slotclk_set(uint32_t value) +{ + REG_BLE_WR(BLE_SLOTCLK_ADDR, value); +} + +// field definitions +#define BLE_SAMP_BIT ((uint32_t)0x80000000) +#define BLE_SAMP_POS 31 +#define BLE_CLKN_UPD_BIT ((uint32_t)0x40000000) +#define BLE_CLKN_UPD_POS 30 +#define BLE_SCLK_MASK ((uint32_t)0x0FFFFFFF) +#define BLE_SCLK_LSB 0 +#define BLE_SCLK_WIDTH ((uint32_t)0x0000001C) + +#define BLE_SAMP_RST 0x0 +#define BLE_CLKN_UPD_RST 0x0 +#define BLE_SCLK_RST 0x0 + +__INLINE void ble_slotclk_pack(uint8_t samp, uint8_t clknupd, uint32_t sclk) +{ + BLE_ASSERT_ERR((((uint32_t)samp << 31) & ~((uint32_t)0x80000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)clknupd << 30) & ~((uint32_t)0x40000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)sclk << 0) & ~((uint32_t)0x0FFFFFFF)) == 0); + REG_BLE_WR(BLE_SLOTCLK_ADDR, ((uint32_t)samp << 31) | ((uint32_t)clknupd << 30) | ((uint32_t)sclk << 0)); +} + +__INLINE void ble_slotclk_unpack(uint8_t* samp, uint8_t* clknupd, uint32_t* sclk) +{ + uint32_t localVal = REG_BLE_RD(BLE_SLOTCLK_ADDR); + + *samp = (localVal & ((uint32_t)0x80000000)) >> 31; + *clknupd = (localVal & ((uint32_t)0x40000000)) >> 30; + *sclk = (localVal & ((uint32_t)0x0FFFFFFF)) >> 0; +} + +__INLINE uint8_t ble_slotclk_samp_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SLOTCLK_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +__INLINE void ble_slotclk_samp_setf(uint8_t samp) +{ + BLE_ASSERT_ERR((((uint32_t)samp << 31) & ~((uint32_t)0x80000000)) == 0); + REG_BLE_WR(BLE_SLOTCLK_ADDR, (REG_BLE_RD(BLE_SLOTCLK_ADDR) & ~((uint32_t)0x80000000)) | ((uint32_t)samp << 31)); +} + +__INLINE uint8_t ble_slotclk_clkn_upd_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SLOTCLK_ADDR); + return ((localVal & ((uint32_t)0x40000000)) >> 30); +} + +__INLINE void ble_slotclk_clkn_upd_setf(uint8_t clknupd) +{ + BLE_ASSERT_ERR((((uint32_t)clknupd << 30) & ~((uint32_t)0x40000000)) == 0); + REG_BLE_WR(BLE_SLOTCLK_ADDR, (REG_BLE_RD(BLE_SLOTCLK_ADDR) & ~((uint32_t)0x40000000)) | ((uint32_t)clknupd << 30)); +} + +__INLINE uint32_t ble_slotclk_sclk_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SLOTCLK_ADDR); + return ((localVal & ((uint32_t)0x0FFFFFFF)) >> 0); +} + +__INLINE void ble_slotclk_sclk_setf(uint32_t sclk) +{ + BLE_ASSERT_ERR((((uint32_t)sclk << 0) & ~((uint32_t)0x0FFFFFFF)) == 0); + REG_BLE_WR(BLE_SLOTCLK_ADDR, (REG_BLE_RD(BLE_SLOTCLK_ADDR) & ~((uint32_t)0x0FFFFFFF)) | ((uint32_t)sclk << 0)); +} + +/** + * @brief FINETIMECNT register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  09:00              FINECNT   0x0
+ * 
+ */ +#define BLE_FINETIMECNT_ADDR 0x009008FC +#define BLE_FINETIMECNT_OFFSET 0x000000FC +#define BLE_FINETIMECNT_INDEX 0x0000003F +#define BLE_FINETIMECNT_RESET 0x00000000 + +__INLINE uint32_t ble_finetimecnt_get(void) +{ + return REG_BLE_RD(BLE_FINETIMECNT_ADDR); +} + +// field definitions +#define BLE_FINECNT_MASK ((uint32_t)0x000003FF) +#define BLE_FINECNT_LSB 0 +#define BLE_FINECNT_WIDTH ((uint32_t)0x0000000A) + +#define BLE_FINECNT_RST 0x0 + +__INLINE uint16_t ble_finetimecnt_finecnt_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_FINETIMECNT_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0x000003FF)) == 0); + return (localVal >> 0); +} + +/** + * @brief ACTSCHCNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31            START_ACT   0
+ *  03:00            ENTRY_IDX   0x0
+ * 
+ */ +#define BLE_ACTSCHCNTL_ADDR 0x00900900 +#define BLE_ACTSCHCNTL_OFFSET 0x00000100 +#define BLE_ACTSCHCNTL_INDEX 0x00000040 +#define BLE_ACTSCHCNTL_RESET 0x00000000 + +__INLINE uint32_t ble_actschcntl_get(void) +{ + return REG_BLE_RD(BLE_ACTSCHCNTL_ADDR); +} + +__INLINE void ble_actschcntl_set(uint32_t value) +{ + REG_BLE_WR(BLE_ACTSCHCNTL_ADDR, value); +} + +// field definitions +#define BLE_START_ACT_BIT ((uint32_t)0x80000000) +#define BLE_START_ACT_POS 31 +#define BLE_ENTRY_IDX_MASK ((uint32_t)0x0000000F) +#define BLE_ENTRY_IDX_LSB 0 +#define BLE_ENTRY_IDX_WIDTH ((uint32_t)0x00000004) + +#define BLE_START_ACT_RST 0x0 +#define BLE_ENTRY_IDX_RST 0x0 + +__INLINE void ble_actschcntl_pack(uint8_t startact, uint8_t entryidx) +{ + BLE_ASSERT_ERR((((uint32_t)startact << 31) & ~((uint32_t)0x80000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)entryidx << 0) & ~((uint32_t)0x0000000F)) == 0); + REG_BLE_WR(BLE_ACTSCHCNTL_ADDR, ((uint32_t)startact << 31) | ((uint32_t)entryidx << 0)); +} + +__INLINE void ble_actschcntl_unpack(uint8_t* startact, uint8_t* entryidx) +{ + uint32_t localVal = REG_BLE_RD(BLE_ACTSCHCNTL_ADDR); + + *startact = (localVal & ((uint32_t)0x80000000)) >> 31; + *entryidx = (localVal & ((uint32_t)0x0000000F)) >> 0; +} + +__INLINE uint8_t ble_actschcntl_start_act_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ACTSCHCNTL_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +__INLINE void ble_actschcntl_start_act_setf(uint8_t startact) +{ + BLE_ASSERT_ERR((((uint32_t)startact << 31) & ~((uint32_t)0x80000000)) == 0); + REG_BLE_WR(BLE_ACTSCHCNTL_ADDR, (REG_BLE_RD(BLE_ACTSCHCNTL_ADDR) & ~((uint32_t)0x80000000)) | ((uint32_t)startact << 31)); +} + +__INLINE uint8_t ble_actschcntl_entry_idx_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ACTSCHCNTL_ADDR); + return ((localVal & ((uint32_t)0x0000000F)) >> 0); +} + +__INLINE void ble_actschcntl_entry_idx_setf(uint8_t entryidx) +{ + BLE_ASSERT_ERR((((uint32_t)entryidx << 0) & ~((uint32_t)0x0000000F)) == 0); + REG_BLE_WR(BLE_ACTSCHCNTL_ADDR, (REG_BLE_RD(BLE_ACTSCHCNTL_ADDR) & ~((uint32_t)0x0000000F)) | ((uint32_t)entryidx << 0)); +} + +/** + * @brief STARTEVTCLKNTS register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  27:00       STARTEVTCLKNTS   0x0
+ * 
+ */ +#define BLE_STARTEVTCLKNTS_ADDR 0x00900904 +#define BLE_STARTEVTCLKNTS_OFFSET 0x00000104 +#define BLE_STARTEVTCLKNTS_INDEX 0x00000041 +#define BLE_STARTEVTCLKNTS_RESET 0x00000000 + +__INLINE uint32_t ble_startevtclknts_get(void) +{ + return REG_BLE_RD(BLE_STARTEVTCLKNTS_ADDR); +} + +// field definitions +#define BLE_STARTEVTCLKNTS_MASK ((uint32_t)0x0FFFFFFF) +#define BLE_STARTEVTCLKNTS_LSB 0 +#define BLE_STARTEVTCLKNTS_WIDTH ((uint32_t)0x0000001C) + +#define BLE_STARTEVTCLKNTS_RST 0x0 + +__INLINE uint32_t ble_startevtclknts_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_STARTEVTCLKNTS_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0x0FFFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief STARTEVTFINECNTTS register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  09:00    STARTEVTFINECNTTS   0x0
+ * 
+ */ +#define BLE_STARTEVTFINECNTTS_ADDR 0x00900908 +#define BLE_STARTEVTFINECNTTS_OFFSET 0x00000108 +#define BLE_STARTEVTFINECNTTS_INDEX 0x00000042 +#define BLE_STARTEVTFINECNTTS_RESET 0x00000000 + +__INLINE uint32_t ble_startevtfinecntts_get(void) +{ + return REG_BLE_RD(BLE_STARTEVTFINECNTTS_ADDR); +} + +// field definitions +#define BLE_STARTEVTFINECNTTS_MASK ((uint32_t)0x000003FF) +#define BLE_STARTEVTFINECNTTS_LSB 0 +#define BLE_STARTEVTFINECNTTS_WIDTH ((uint32_t)0x0000000A) + +#define BLE_STARTEVTFINECNTTS_RST 0x0 + +__INLINE uint16_t ble_startevtfinecntts_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_STARTEVTFINECNTTS_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0x000003FF)) == 0); + return (localVal >> 0); +} + +/** + * @brief ENDEVTCLKNTS register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  27:00         ENDEVTCLKNTS   0x0
+ * 
+ */ +#define BLE_ENDEVTCLKNTS_ADDR 0x0090090C +#define BLE_ENDEVTCLKNTS_OFFSET 0x0000010C +#define BLE_ENDEVTCLKNTS_INDEX 0x00000043 +#define BLE_ENDEVTCLKNTS_RESET 0x00000000 + +__INLINE uint32_t ble_endevtclknts_get(void) +{ + return REG_BLE_RD(BLE_ENDEVTCLKNTS_ADDR); +} + +// field definitions +#define BLE_ENDEVTCLKNTS_MASK ((uint32_t)0x0FFFFFFF) +#define BLE_ENDEVTCLKNTS_LSB 0 +#define BLE_ENDEVTCLKNTS_WIDTH ((uint32_t)0x0000001C) + +#define BLE_ENDEVTCLKNTS_RST 0x0 + +__INLINE uint32_t ble_endevtclknts_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ENDEVTCLKNTS_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0x0FFFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief ENDEVTFINECNTTS register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  09:00      ENDEVTFINECNTTS   0x0
+ * 
+ */ +#define BLE_ENDEVTFINECNTTS_ADDR 0x00900910 +#define BLE_ENDEVTFINECNTTS_OFFSET 0x00000110 +#define BLE_ENDEVTFINECNTTS_INDEX 0x00000044 +#define BLE_ENDEVTFINECNTTS_RESET 0x00000000 + +__INLINE uint32_t ble_endevtfinecntts_get(void) +{ + return REG_BLE_RD(BLE_ENDEVTFINECNTTS_ADDR); +} + +// field definitions +#define BLE_ENDEVTFINECNTTS_MASK ((uint32_t)0x000003FF) +#define BLE_ENDEVTFINECNTTS_LSB 0 +#define BLE_ENDEVTFINECNTTS_WIDTH ((uint32_t)0x0000000A) + +#define BLE_ENDEVTFINECNTTS_RST 0x0 + +__INLINE uint16_t ble_endevtfinecntts_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ENDEVTFINECNTTS_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0x000003FF)) == 0); + return (localVal >> 0); +} + +/** + * @brief SKIPEVTCLKNTS register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  27:00        SKIPEVTCLKNTS   0x0
+ * 
+ */ +#define BLE_SKIPEVTCLKNTS_ADDR 0x00900914 +#define BLE_SKIPEVTCLKNTS_OFFSET 0x00000114 +#define BLE_SKIPEVTCLKNTS_INDEX 0x00000045 +#define BLE_SKIPEVTCLKNTS_RESET 0x00000000 + +__INLINE uint32_t ble_skipevtclknts_get(void) +{ + return REG_BLE_RD(BLE_SKIPEVTCLKNTS_ADDR); +} + +// field definitions +#define BLE_SKIPEVTCLKNTS_MASK ((uint32_t)0x0FFFFFFF) +#define BLE_SKIPEVTCLKNTS_LSB 0 +#define BLE_SKIPEVTCLKNTS_WIDTH ((uint32_t)0x0000001C) + +#define BLE_SKIPEVTCLKNTS_RST 0x0 + +__INLINE uint32_t ble_skipevtclknts_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SKIPEVTCLKNTS_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0x0FFFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief SKIPEVTFINECNTTS register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  09:00     SKIPEVTFINECNTTS   0x0
+ * 
+ */ +#define BLE_SKIPEVTFINECNTTS_ADDR 0x00900918 +#define BLE_SKIPEVTFINECNTTS_OFFSET 0x00000118 +#define BLE_SKIPEVTFINECNTTS_INDEX 0x00000046 +#define BLE_SKIPEVTFINECNTTS_RESET 0x00000000 + +__INLINE uint32_t ble_skipevtfinecntts_get(void) +{ + return REG_BLE_RD(BLE_SKIPEVTFINECNTTS_ADDR); +} + +// field definitions +#define BLE_SKIPEVTFINECNTTS_MASK ((uint32_t)0x000003FF) +#define BLE_SKIPEVTFINECNTTS_LSB 0 +#define BLE_SKIPEVTFINECNTTS_WIDTH ((uint32_t)0x0000000A) + +#define BLE_SKIPEVTFINECNTTS_RST 0x0 + +__INLINE uint16_t ble_skipevtfinecntts_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SKIPEVTFINECNTTS_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0x000003FF)) == 0); + return (localVal >> 0); +} + +/** + * @brief ADVTIM register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:24        TX_AUXPTR_THR   0x0
+ *  23:16        RX_AUXPTR_THR   0x0
+ *  13:00               ADVINT   0x0
+ * 
+ */ +#define BLE_ADVTIM_ADDR 0x00900920 +#define BLE_ADVTIM_OFFSET 0x00000120 +#define BLE_ADVTIM_INDEX 0x00000048 +#define BLE_ADVTIM_RESET 0x00000000 + +__INLINE uint32_t ble_advtim_get(void) +{ + return REG_BLE_RD(BLE_ADVTIM_ADDR); +} + +__INLINE void ble_advtim_set(uint32_t value) +{ + REG_BLE_WR(BLE_ADVTIM_ADDR, value); +} + +// field definitions +#define BLE_TX_AUXPTR_THR_MASK ((uint32_t)0xFF000000) +#define BLE_TX_AUXPTR_THR_LSB 24 +#define BLE_TX_AUXPTR_THR_WIDTH ((uint32_t)0x00000008) +#define BLE_RX_AUXPTR_THR_MASK ((uint32_t)0x00FF0000) +#define BLE_RX_AUXPTR_THR_LSB 16 +#define BLE_RX_AUXPTR_THR_WIDTH ((uint32_t)0x00000008) +#define BLE_ADVINT_MASK ((uint32_t)0x00003FFF) +#define BLE_ADVINT_LSB 0 +#define BLE_ADVINT_WIDTH ((uint32_t)0x0000000E) + +#define BLE_TX_AUXPTR_THR_RST 0x0 +#define BLE_RX_AUXPTR_THR_RST 0x0 +#define BLE_ADVINT_RST 0x0 + +__INLINE void ble_advtim_pack(uint8_t txauxptrthr, uint8_t rxauxptrthr, uint16_t advint) +{ + BLE_ASSERT_ERR((((uint32_t)txauxptrthr << 24) & ~((uint32_t)0xFF000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)rxauxptrthr << 16) & ~((uint32_t)0x00FF0000)) == 0); + BLE_ASSERT_ERR((((uint32_t)advint << 0) & ~((uint32_t)0x00003FFF)) == 0); + REG_BLE_WR(BLE_ADVTIM_ADDR, ((uint32_t)txauxptrthr << 24) | ((uint32_t)rxauxptrthr << 16) | ((uint32_t)advint << 0)); +} + +__INLINE void ble_advtim_unpack(uint8_t* txauxptrthr, uint8_t* rxauxptrthr, uint16_t* advint) +{ + uint32_t localVal = REG_BLE_RD(BLE_ADVTIM_ADDR); + + *txauxptrthr = (localVal & ((uint32_t)0xFF000000)) >> 24; + *rxauxptrthr = (localVal & ((uint32_t)0x00FF0000)) >> 16; + *advint = (localVal & ((uint32_t)0x00003FFF)) >> 0; +} + +__INLINE uint8_t ble_advtim_tx_auxptr_thr_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ADVTIM_ADDR); + return ((localVal & ((uint32_t)0xFF000000)) >> 24); +} + +__INLINE void ble_advtim_tx_auxptr_thr_setf(uint8_t txauxptrthr) +{ + BLE_ASSERT_ERR((((uint32_t)txauxptrthr << 24) & ~((uint32_t)0xFF000000)) == 0); + REG_BLE_WR(BLE_ADVTIM_ADDR, (REG_BLE_RD(BLE_ADVTIM_ADDR) & ~((uint32_t)0xFF000000)) | ((uint32_t)txauxptrthr << 24)); +} + +__INLINE uint8_t ble_advtim_rx_auxptr_thr_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ADVTIM_ADDR); + return ((localVal & ((uint32_t)0x00FF0000)) >> 16); +} + +__INLINE void ble_advtim_rx_auxptr_thr_setf(uint8_t rxauxptrthr) +{ + BLE_ASSERT_ERR((((uint32_t)rxauxptrthr << 16) & ~((uint32_t)0x00FF0000)) == 0); + REG_BLE_WR(BLE_ADVTIM_ADDR, (REG_BLE_RD(BLE_ADVTIM_ADDR) & ~((uint32_t)0x00FF0000)) | ((uint32_t)rxauxptrthr << 16)); +} + +__INLINE uint16_t ble_advtim_advint_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ADVTIM_ADDR); + return ((localVal & ((uint32_t)0x00003FFF)) >> 0); +} + +__INLINE void ble_advtim_advint_setf(uint16_t advint) +{ + BLE_ASSERT_ERR((((uint32_t)advint << 0) & ~((uint32_t)0x00003FFF)) == 0); + REG_BLE_WR(BLE_ADVTIM_ADDR, (REG_BLE_RD(BLE_ADVTIM_ADDR) & ~((uint32_t)0x00003FFF)) | ((uint32_t)advint << 0)); +} + +/** + * @brief ACTSCANCNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  24:16              BACKOFF   0x1
+ *  08:00           UPPERLIMIT   0x1
+ * 
+ */ +#define BLE_ACTSCANCNTL_ADDR 0x00900924 +#define BLE_ACTSCANCNTL_OFFSET 0x00000124 +#define BLE_ACTSCANCNTL_INDEX 0x00000049 +#define BLE_ACTSCANCNTL_RESET 0x00010001 + +__INLINE uint32_t ble_actscancntl_get(void) +{ + return REG_BLE_RD(BLE_ACTSCANCNTL_ADDR); +} + +__INLINE void ble_actscancntl_set(uint32_t value) +{ + REG_BLE_WR(BLE_ACTSCANCNTL_ADDR, value); +} + +// field definitions +#define BLE_BACKOFF_MASK ((uint32_t)0x01FF0000) +#define BLE_BACKOFF_LSB 16 +#define BLE_BACKOFF_WIDTH ((uint32_t)0x00000009) +#define BLE_UPPERLIMIT_MASK ((uint32_t)0x000001FF) +#define BLE_UPPERLIMIT_LSB 0 +#define BLE_UPPERLIMIT_WIDTH ((uint32_t)0x00000009) + +#define BLE_BACKOFF_RST 0x1 +#define BLE_UPPERLIMIT_RST 0x1 + +__INLINE void ble_actscancntl_pack(uint16_t backoff, uint16_t upperlimit) +{ + BLE_ASSERT_ERR((((uint32_t)backoff << 16) & ~((uint32_t)0x01FF0000)) == 0); + BLE_ASSERT_ERR((((uint32_t)upperlimit << 0) & ~((uint32_t)0x000001FF)) == 0); + REG_BLE_WR(BLE_ACTSCANCNTL_ADDR, ((uint32_t)backoff << 16) | ((uint32_t)upperlimit << 0)); +} + +__INLINE void ble_actscancntl_unpack(uint16_t* backoff, uint16_t* upperlimit) +{ + uint32_t localVal = REG_BLE_RD(BLE_ACTSCANCNTL_ADDR); + + *backoff = (localVal & ((uint32_t)0x01FF0000)) >> 16; + *upperlimit = (localVal & ((uint32_t)0x000001FF)) >> 0; +} + +__INLINE uint16_t ble_actscancntl_backoff_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ACTSCANCNTL_ADDR); + return ((localVal & ((uint32_t)0x01FF0000)) >> 16); +} + +__INLINE void ble_actscancntl_backoff_setf(uint16_t backoff) +{ + BLE_ASSERT_ERR((((uint32_t)backoff << 16) & ~((uint32_t)0x01FF0000)) == 0); + REG_BLE_WR(BLE_ACTSCANCNTL_ADDR, (REG_BLE_RD(BLE_ACTSCANCNTL_ADDR) & ~((uint32_t)0x01FF0000)) | ((uint32_t)backoff << 16)); +} + +__INLINE uint16_t ble_actscancntl_upperlimit_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_ACTSCANCNTL_ADDR); + return ((localVal & ((uint32_t)0x000001FF)) >> 0); +} + +__INLINE void ble_actscancntl_upperlimit_setf(uint16_t upperlimit) +{ + BLE_ASSERT_ERR((((uint32_t)upperlimit << 0) & ~((uint32_t)0x000001FF)) == 0); + REG_BLE_WR(BLE_ACTSCANCNTL_ADDR, (REG_BLE_RD(BLE_ACTSCANCNTL_ADDR) & ~((uint32_t)0x000001FF)) | ((uint32_t)upperlimit << 0)); +} + +/** + * @brief WPALCNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  23:16            WPALNBDEV   0x0
+ *  13:00          WPALBASEPTR   0x0
+ * 
+ */ +#define BLE_WPALCNTL_ADDR 0x00900930 +#define BLE_WPALCNTL_OFFSET 0x00000130 +#define BLE_WPALCNTL_INDEX 0x0000004C +#define BLE_WPALCNTL_RESET 0x00000000 + +__INLINE uint32_t ble_wpalcntl_get(void) +{ + return REG_BLE_RD(BLE_WPALCNTL_ADDR); +} + +__INLINE void ble_wpalcntl_set(uint32_t value) +{ + REG_BLE_WR(BLE_WPALCNTL_ADDR, value); +} + +// field definitions +#define BLE_WPALNBDEV_MASK ((uint32_t)0x00FF0000) +#define BLE_WPALNBDEV_LSB 16 +#define BLE_WPALNBDEV_WIDTH ((uint32_t)0x00000008) +#define BLE_WPALBASEPTR_MASK ((uint32_t)0x00003FFF) +#define BLE_WPALBASEPTR_LSB 0 +#define BLE_WPALBASEPTR_WIDTH ((uint32_t)0x0000000E) + +#define BLE_WPALNBDEV_RST 0x0 +#define BLE_WPALBASEPTR_RST 0x0 + +__INLINE void ble_wpalcntl_pack(uint8_t wpalnbdev, uint16_t wpalbaseptr) +{ + BLE_ASSERT_ERR((((uint32_t)wpalnbdev << 16) & ~((uint32_t)0x00FF0000)) == 0); + BLE_ASSERT_ERR((((uint32_t)wpalbaseptr << 0) & ~((uint32_t)0x00003FFF)) == 0); + REG_BLE_WR(BLE_WPALCNTL_ADDR, ((uint32_t)wpalnbdev << 16) | ((uint32_t)wpalbaseptr << 0)); +} + +__INLINE void ble_wpalcntl_unpack(uint8_t* wpalnbdev, uint16_t* wpalbaseptr) +{ + uint32_t localVal = REG_BLE_RD(BLE_WPALCNTL_ADDR); + + *wpalnbdev = (localVal & ((uint32_t)0x00FF0000)) >> 16; + *wpalbaseptr = (localVal & ((uint32_t)0x00003FFF)) >> 0; +} + +__INLINE uint8_t ble_wpalcntl_wpalnbdev_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_WPALCNTL_ADDR); + return ((localVal & ((uint32_t)0x00FF0000)) >> 16); +} + +__INLINE void ble_wpalcntl_wpalnbdev_setf(uint8_t wpalnbdev) +{ + BLE_ASSERT_ERR((((uint32_t)wpalnbdev << 16) & ~((uint32_t)0x00FF0000)) == 0); + REG_BLE_WR(BLE_WPALCNTL_ADDR, (REG_BLE_RD(BLE_WPALCNTL_ADDR) & ~((uint32_t)0x00FF0000)) | ((uint32_t)wpalnbdev << 16)); +} + +__INLINE uint16_t ble_wpalcntl_wpalbaseptr_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_WPALCNTL_ADDR); + return ((localVal & ((uint32_t)0x00003FFF)) >> 0); +} + +__INLINE void ble_wpalcntl_wpalbaseptr_setf(uint16_t wpalbaseptr) +{ + BLE_ASSERT_ERR((((uint32_t)wpalbaseptr << 0) & ~((uint32_t)0x00003FFF)) == 0); + REG_BLE_WR(BLE_WPALCNTL_ADDR, (REG_BLE_RD(BLE_WPALCNTL_ADDR) & ~((uint32_t)0x00003FFF)) | ((uint32_t)wpalbaseptr << 0)); +} + +/** + * @brief WPALCURRENTPTR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  13:00       WPALCURRENTPTR   0x0
+ * 
+ */ +#define BLE_WPALCURRENTPTR_ADDR 0x00900934 +#define BLE_WPALCURRENTPTR_OFFSET 0x00000134 +#define BLE_WPALCURRENTPTR_INDEX 0x0000004D +#define BLE_WPALCURRENTPTR_RESET 0x00000000 + +__INLINE uint32_t ble_wpalcurrentptr_get(void) +{ + return REG_BLE_RD(BLE_WPALCURRENTPTR_ADDR); +} + +__INLINE void ble_wpalcurrentptr_set(uint32_t value) +{ + REG_BLE_WR(BLE_WPALCURRENTPTR_ADDR, value); +} + +// field definitions +#define BLE_WPALCURRENTPTR_MASK ((uint32_t)0x00003FFF) +#define BLE_WPALCURRENTPTR_LSB 0 +#define BLE_WPALCURRENTPTR_WIDTH ((uint32_t)0x0000000E) + +#define BLE_WPALCURRENTPTR_RST 0x0 + +__INLINE uint16_t ble_wpalcurrentptr_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_WPALCURRENTPTR_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0x00003FFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_wpalcurrentptr_setf(uint16_t wpalcurrentptr) +{ + BLE_ASSERT_ERR((((uint32_t)wpalcurrentptr << 0) & ~((uint32_t)0x00003FFF)) == 0); + REG_BLE_WR(BLE_WPALCURRENTPTR_ADDR, (uint32_t)wpalcurrentptr << 0); +} + +/** + * @brief SEARCH_TIMEOUT register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  05:00       SEARCH_TIMEOUT   0x10
+ * 
+ */ +#define BLE_SEARCH_TIMEOUT_ADDR 0x00900938 +#define BLE_SEARCH_TIMEOUT_OFFSET 0x00000138 +#define BLE_SEARCH_TIMEOUT_INDEX 0x0000004E +#define BLE_SEARCH_TIMEOUT_RESET 0x00000010 + +__INLINE uint32_t ble_search_timeout_get(void) +{ + return REG_BLE_RD(BLE_SEARCH_TIMEOUT_ADDR); +} + +__INLINE void ble_search_timeout_set(uint32_t value) +{ + REG_BLE_WR(BLE_SEARCH_TIMEOUT_ADDR, value); +} + +// field definitions +#define BLE_SEARCH_TIMEOUT_MASK ((uint32_t)0x0000003F) +#define BLE_SEARCH_TIMEOUT_LSB 0 +#define BLE_SEARCH_TIMEOUT_WIDTH ((uint32_t)0x00000006) + +#define BLE_SEARCH_TIMEOUT_RST 0x10 + +__INLINE uint8_t ble_search_timeout_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_SEARCH_TIMEOUT_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0x0000003F)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_search_timeout_setf(uint8_t searchtimeout) +{ + BLE_ASSERT_ERR((((uint32_t)searchtimeout << 0) & ~((uint32_t)0x0000003F)) == 0); + REG_BLE_WR(BLE_SEARCH_TIMEOUT_ADDR, (uint32_t)searchtimeout << 0); +} + +/** + * @brief COEXIFCNTL0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  21:20       MWSSCANFREQMSK   0x0
+ *  19:18        WLCRXPRIOMODE   0x0
+ *  17:16        WLCTXPRIOMODE   0x0
+ *  15:14          MWSTXFRQMSK   0x0
+ *  13:12          MWSRXFRQMSK   0x0
+ *  11:10             MWSTXMSK   0x0
+ *  09:08             MWSRXMSK   0x0
+ *  07:06            WLANTXMSK   0x0
+ *  05:04            WLANRXMSK   0x1
+ *     03            MWSWCI_EN   0
+ *     02           MWSCOEX_EN   0
+ *     01           SYNCGEN_EN   0
+ *     00          WLANCOEX_EN   0
+ * 
+ */ +#define BLE_COEXIFCNTL0_ADDR 0x00900940 +#define BLE_COEXIFCNTL0_OFFSET 0x00000140 +#define BLE_COEXIFCNTL0_INDEX 0x00000050 +#define BLE_COEXIFCNTL0_RESET 0x00000010 + +__INLINE uint32_t ble_coexifcntl0_get(void) +{ + return REG_BLE_RD(BLE_COEXIFCNTL0_ADDR); +} + +__INLINE void ble_coexifcntl0_set(uint32_t value) +{ + REG_BLE_WR(BLE_COEXIFCNTL0_ADDR, value); +} + +// field definitions +#define BLE_MWSSCANFREQMSK_MASK ((uint32_t)0x00300000) +#define BLE_MWSSCANFREQMSK_LSB 20 +#define BLE_MWSSCANFREQMSK_WIDTH ((uint32_t)0x00000002) +#define BLE_WLCRXPRIOMODE_MASK ((uint32_t)0x000C0000) +#define BLE_WLCRXPRIOMODE_LSB 18 +#define BLE_WLCRXPRIOMODE_WIDTH ((uint32_t)0x00000002) +#define BLE_WLCTXPRIOMODE_MASK ((uint32_t)0x00030000) +#define BLE_WLCTXPRIOMODE_LSB 16 +#define BLE_WLCTXPRIOMODE_WIDTH ((uint32_t)0x00000002) +#define BLE_MWSTXFRQMSK_MASK ((uint32_t)0x0000C000) +#define BLE_MWSTXFRQMSK_LSB 14 +#define BLE_MWSTXFRQMSK_WIDTH ((uint32_t)0x00000002) +#define BLE_MWSRXFRQMSK_MASK ((uint32_t)0x00003000) +#define BLE_MWSRXFRQMSK_LSB 12 +#define BLE_MWSRXFRQMSK_WIDTH ((uint32_t)0x00000002) +#define BLE_MWSTXMSK_MASK ((uint32_t)0x00000C00) +#define BLE_MWSTXMSK_LSB 10 +#define BLE_MWSTXMSK_WIDTH ((uint32_t)0x00000002) +#define BLE_MWSRXMSK_MASK ((uint32_t)0x00000300) +#define BLE_MWSRXMSK_LSB 8 +#define BLE_MWSRXMSK_WIDTH ((uint32_t)0x00000002) +#define BLE_WLANTXMSK_MASK ((uint32_t)0x000000C0) +#define BLE_WLANTXMSK_LSB 6 +#define BLE_WLANTXMSK_WIDTH ((uint32_t)0x00000002) +#define BLE_WLANRXMSK_MASK ((uint32_t)0x00000030) +#define BLE_WLANRXMSK_LSB 4 +#define BLE_WLANRXMSK_WIDTH ((uint32_t)0x00000002) +#define BLE_MWSWCI_EN_BIT ((uint32_t)0x00000008) +#define BLE_MWSWCI_EN_POS 3 +#define BLE_MWSCOEX_EN_BIT ((uint32_t)0x00000004) +#define BLE_MWSCOEX_EN_POS 2 +#define BLE_SYNCGEN_EN_BIT ((uint32_t)0x00000002) +#define BLE_SYNCGEN_EN_POS 1 +#define BLE_WLANCOEX_EN_BIT ((uint32_t)0x00000001) +#define BLE_WLANCOEX_EN_POS 0 + +#define BLE_MWSSCANFREQMSK_RST 0x0 +#define BLE_WLCRXPRIOMODE_RST 0x0 +#define BLE_WLCTXPRIOMODE_RST 0x0 +#define BLE_MWSTXFRQMSK_RST 0x0 +#define BLE_MWSRXFRQMSK_RST 0x0 +#define BLE_MWSTXMSK_RST 0x0 +#define BLE_MWSRXMSK_RST 0x0 +#define BLE_WLANTXMSK_RST 0x0 +#define BLE_WLANRXMSK_RST 0x1 +#define BLE_MWSWCI_EN_RST 0x0 +#define BLE_MWSCOEX_EN_RST 0x0 +#define BLE_SYNCGEN_EN_RST 0x0 +#define BLE_WLANCOEX_EN_RST 0x0 + +__INLINE void ble_coexifcntl0_pack(uint8_t mwsscanfreqmsk, uint8_t wlcrxpriomode, uint8_t wlctxpriomode, uint8_t mwstxfrqmsk, uint8_t mwsrxfrqmsk, uint8_t mwstxmsk, uint8_t mwsrxmsk, uint8_t wlantxmsk, uint8_t wlanrxmsk, uint8_t mwswcien, uint8_t mwscoexen, uint8_t syncgenen, uint8_t wlancoexen) +{ + BLE_ASSERT_ERR((((uint32_t)mwsscanfreqmsk << 20) & ~((uint32_t)0x00300000)) == 0); + BLE_ASSERT_ERR((((uint32_t)wlcrxpriomode << 18) & ~((uint32_t)0x000C0000)) == 0); + BLE_ASSERT_ERR((((uint32_t)wlctxpriomode << 16) & ~((uint32_t)0x00030000)) == 0); + BLE_ASSERT_ERR((((uint32_t)mwstxfrqmsk << 14) & ~((uint32_t)0x0000C000)) == 0); + BLE_ASSERT_ERR((((uint32_t)mwsrxfrqmsk << 12) & ~((uint32_t)0x00003000)) == 0); + BLE_ASSERT_ERR((((uint32_t)mwstxmsk << 10) & ~((uint32_t)0x00000C00)) == 0); + BLE_ASSERT_ERR((((uint32_t)mwsrxmsk << 8) & ~((uint32_t)0x00000300)) == 0); + BLE_ASSERT_ERR((((uint32_t)wlantxmsk << 6) & ~((uint32_t)0x000000C0)) == 0); + BLE_ASSERT_ERR((((uint32_t)wlanrxmsk << 4) & ~((uint32_t)0x00000030)) == 0); + BLE_ASSERT_ERR((((uint32_t)mwswcien << 3) & ~((uint32_t)0x00000008)) == 0); + BLE_ASSERT_ERR((((uint32_t)mwscoexen << 2) & ~((uint32_t)0x00000004)) == 0); + BLE_ASSERT_ERR((((uint32_t)syncgenen << 1) & ~((uint32_t)0x00000002)) == 0); + BLE_ASSERT_ERR((((uint32_t)wlancoexen << 0) & ~((uint32_t)0x00000001)) == 0); + REG_BLE_WR(BLE_COEXIFCNTL0_ADDR, ((uint32_t)mwsscanfreqmsk << 20) | ((uint32_t)wlcrxpriomode << 18) | ((uint32_t)wlctxpriomode << 16) | ((uint32_t)mwstxfrqmsk << 14) | ((uint32_t)mwsrxfrqmsk << 12) | ((uint32_t)mwstxmsk << 10) | ((uint32_t)mwsrxmsk << 8) | ((uint32_t)wlantxmsk << 6) | ((uint32_t)wlanrxmsk << 4) | ((uint32_t)mwswcien << 3) | ((uint32_t)mwscoexen << 2) | ((uint32_t)syncgenen << 1) | ((uint32_t)wlancoexen << 0)); +} + +__INLINE void ble_coexifcntl0_unpack(uint8_t* mwsscanfreqmsk, uint8_t* wlcrxpriomode, uint8_t* wlctxpriomode, uint8_t* mwstxfrqmsk, uint8_t* mwsrxfrqmsk, uint8_t* mwstxmsk, uint8_t* mwsrxmsk, uint8_t* wlantxmsk, uint8_t* wlanrxmsk, uint8_t* mwswcien, uint8_t* mwscoexen, uint8_t* syncgenen, uint8_t* wlancoexen) +{ + uint32_t localVal = REG_BLE_RD(BLE_COEXIFCNTL0_ADDR); + + *mwsscanfreqmsk = (localVal & ((uint32_t)0x00300000)) >> 20; + *wlcrxpriomode = (localVal & ((uint32_t)0x000C0000)) >> 18; + *wlctxpriomode = (localVal & ((uint32_t)0x00030000)) >> 16; + *mwstxfrqmsk = (localVal & ((uint32_t)0x0000C000)) >> 14; + *mwsrxfrqmsk = (localVal & ((uint32_t)0x00003000)) >> 12; + *mwstxmsk = (localVal & ((uint32_t)0x00000C00)) >> 10; + *mwsrxmsk = (localVal & ((uint32_t)0x00000300)) >> 8; + *wlantxmsk = (localVal & ((uint32_t)0x000000C0)) >> 6; + *wlanrxmsk = (localVal & ((uint32_t)0x00000030)) >> 4; + *mwswcien = (localVal & ((uint32_t)0x00000008)) >> 3; + *mwscoexen = (localVal & ((uint32_t)0x00000004)) >> 2; + *syncgenen = (localVal & ((uint32_t)0x00000002)) >> 1; + *wlancoexen = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +__INLINE uint8_t ble_coexifcntl0_mwsscanfreqmsk_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_COEXIFCNTL0_ADDR); + return ((localVal & ((uint32_t)0x00300000)) >> 20); +} + +__INLINE void ble_coexifcntl0_mwsscanfreqmsk_setf(uint8_t mwsscanfreqmsk) +{ + BLE_ASSERT_ERR((((uint32_t)mwsscanfreqmsk << 20) & ~((uint32_t)0x00300000)) == 0); + REG_BLE_WR(BLE_COEXIFCNTL0_ADDR, (REG_BLE_RD(BLE_COEXIFCNTL0_ADDR) & ~((uint32_t)0x00300000)) | ((uint32_t)mwsscanfreqmsk << 20)); +} + +__INLINE uint8_t ble_coexifcntl0_wlcrxpriomode_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_COEXIFCNTL0_ADDR); + return ((localVal & ((uint32_t)0x000C0000)) >> 18); +} + +__INLINE void ble_coexifcntl0_wlcrxpriomode_setf(uint8_t wlcrxpriomode) +{ + BLE_ASSERT_ERR((((uint32_t)wlcrxpriomode << 18) & ~((uint32_t)0x000C0000)) == 0); + REG_BLE_WR(BLE_COEXIFCNTL0_ADDR, (REG_BLE_RD(BLE_COEXIFCNTL0_ADDR) & ~((uint32_t)0x000C0000)) | ((uint32_t)wlcrxpriomode << 18)); +} + +__INLINE uint8_t ble_coexifcntl0_wlctxpriomode_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_COEXIFCNTL0_ADDR); + return ((localVal & ((uint32_t)0x00030000)) >> 16); +} + +__INLINE void ble_coexifcntl0_wlctxpriomode_setf(uint8_t wlctxpriomode) +{ + BLE_ASSERT_ERR((((uint32_t)wlctxpriomode << 16) & ~((uint32_t)0x00030000)) == 0); + REG_BLE_WR(BLE_COEXIFCNTL0_ADDR, (REG_BLE_RD(BLE_COEXIFCNTL0_ADDR) & ~((uint32_t)0x00030000)) | ((uint32_t)wlctxpriomode << 16)); +} + +__INLINE uint8_t ble_coexifcntl0_mwstxfrqmsk_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_COEXIFCNTL0_ADDR); + return ((localVal & ((uint32_t)0x0000C000)) >> 14); +} + +__INLINE void ble_coexifcntl0_mwstxfrqmsk_setf(uint8_t mwstxfrqmsk) +{ + BLE_ASSERT_ERR((((uint32_t)mwstxfrqmsk << 14) & ~((uint32_t)0x0000C000)) == 0); + REG_BLE_WR(BLE_COEXIFCNTL0_ADDR, (REG_BLE_RD(BLE_COEXIFCNTL0_ADDR) & ~((uint32_t)0x0000C000)) | ((uint32_t)mwstxfrqmsk << 14)); +} + +__INLINE uint8_t ble_coexifcntl0_mwsrxfrqmsk_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_COEXIFCNTL0_ADDR); + return ((localVal & ((uint32_t)0x00003000)) >> 12); +} + +__INLINE void ble_coexifcntl0_mwsrxfrqmsk_setf(uint8_t mwsrxfrqmsk) +{ + BLE_ASSERT_ERR((((uint32_t)mwsrxfrqmsk << 12) & ~((uint32_t)0x00003000)) == 0); + REG_BLE_WR(BLE_COEXIFCNTL0_ADDR, (REG_BLE_RD(BLE_COEXIFCNTL0_ADDR) & ~((uint32_t)0x00003000)) | ((uint32_t)mwsrxfrqmsk << 12)); +} + +__INLINE uint8_t ble_coexifcntl0_mwstxmsk_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_COEXIFCNTL0_ADDR); + return ((localVal & ((uint32_t)0x00000C00)) >> 10); +} + +__INLINE void ble_coexifcntl0_mwstxmsk_setf(uint8_t mwstxmsk) +{ + BLE_ASSERT_ERR((((uint32_t)mwstxmsk << 10) & ~((uint32_t)0x00000C00)) == 0); + REG_BLE_WR(BLE_COEXIFCNTL0_ADDR, (REG_BLE_RD(BLE_COEXIFCNTL0_ADDR) & ~((uint32_t)0x00000C00)) | ((uint32_t)mwstxmsk << 10)); +} + +__INLINE uint8_t ble_coexifcntl0_mwsrxmsk_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_COEXIFCNTL0_ADDR); + return ((localVal & ((uint32_t)0x00000300)) >> 8); +} + +__INLINE void ble_coexifcntl0_mwsrxmsk_setf(uint8_t mwsrxmsk) +{ + BLE_ASSERT_ERR((((uint32_t)mwsrxmsk << 8) & ~((uint32_t)0x00000300)) == 0); + REG_BLE_WR(BLE_COEXIFCNTL0_ADDR, (REG_BLE_RD(BLE_COEXIFCNTL0_ADDR) & ~((uint32_t)0x00000300)) | ((uint32_t)mwsrxmsk << 8)); +} + +__INLINE uint8_t ble_coexifcntl0_wlantxmsk_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_COEXIFCNTL0_ADDR); + return ((localVal & ((uint32_t)0x000000C0)) >> 6); +} + +__INLINE void ble_coexifcntl0_wlantxmsk_setf(uint8_t wlantxmsk) +{ + BLE_ASSERT_ERR((((uint32_t)wlantxmsk << 6) & ~((uint32_t)0x000000C0)) == 0); + REG_BLE_WR(BLE_COEXIFCNTL0_ADDR, (REG_BLE_RD(BLE_COEXIFCNTL0_ADDR) & ~((uint32_t)0x000000C0)) | ((uint32_t)wlantxmsk << 6)); +} + +__INLINE uint8_t ble_coexifcntl0_wlanrxmsk_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_COEXIFCNTL0_ADDR); + return ((localVal & ((uint32_t)0x00000030)) >> 4); +} + +__INLINE void ble_coexifcntl0_wlanrxmsk_setf(uint8_t wlanrxmsk) +{ + BLE_ASSERT_ERR((((uint32_t)wlanrxmsk << 4) & ~((uint32_t)0x00000030)) == 0); + REG_BLE_WR(BLE_COEXIFCNTL0_ADDR, (REG_BLE_RD(BLE_COEXIFCNTL0_ADDR) & ~((uint32_t)0x00000030)) | ((uint32_t)wlanrxmsk << 4)); +} + +__INLINE uint8_t ble_coexifcntl0_mwswci_en_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_COEXIFCNTL0_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +__INLINE void ble_coexifcntl0_mwswci_en_setf(uint8_t mwswcien) +{ + BLE_ASSERT_ERR((((uint32_t)mwswcien << 3) & ~((uint32_t)0x00000008)) == 0); + REG_BLE_WR(BLE_COEXIFCNTL0_ADDR, (REG_BLE_RD(BLE_COEXIFCNTL0_ADDR) & ~((uint32_t)0x00000008)) | ((uint32_t)mwswcien << 3)); +} + +__INLINE uint8_t ble_coexifcntl0_mwscoex_en_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_COEXIFCNTL0_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +__INLINE void ble_coexifcntl0_mwscoex_en_setf(uint8_t mwscoexen) +{ + BLE_ASSERT_ERR((((uint32_t)mwscoexen << 2) & ~((uint32_t)0x00000004)) == 0); + REG_BLE_WR(BLE_COEXIFCNTL0_ADDR, (REG_BLE_RD(BLE_COEXIFCNTL0_ADDR) & ~((uint32_t)0x00000004)) | ((uint32_t)mwscoexen << 2)); +} + +__INLINE uint8_t ble_coexifcntl0_syncgen_en_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_COEXIFCNTL0_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +__INLINE void ble_coexifcntl0_syncgen_en_setf(uint8_t syncgenen) +{ + BLE_ASSERT_ERR((((uint32_t)syncgenen << 1) & ~((uint32_t)0x00000002)) == 0); + REG_BLE_WR(BLE_COEXIFCNTL0_ADDR, (REG_BLE_RD(BLE_COEXIFCNTL0_ADDR) & ~((uint32_t)0x00000002)) | ((uint32_t)syncgenen << 1)); +} + +__INLINE uint8_t ble_coexifcntl0_wlancoex_en_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_COEXIFCNTL0_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +__INLINE void ble_coexifcntl0_wlancoex_en_setf(uint8_t wlancoexen) +{ + BLE_ASSERT_ERR((((uint32_t)wlancoexen << 0) & ~((uint32_t)0x00000001)) == 0); + REG_BLE_WR(BLE_COEXIFCNTL0_ADDR, (REG_BLE_RD(BLE_COEXIFCNTL0_ADDR) & ~((uint32_t)0x00000001)) | ((uint32_t)wlancoexen << 0)); +} + +/** + * @brief COEXIFCNTL1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  28:24            WLCPRXTHR   0x0
+ *  20:16            WLCPTXTHR   0x0
+ *  14:08         WLCPDURATION   0x0
+ *  06:00            WLCPDELAY   0x0
+ * 
+ */ +#define BLE_COEXIFCNTL1_ADDR 0x00900944 +#define BLE_COEXIFCNTL1_OFFSET 0x00000144 +#define BLE_COEXIFCNTL1_INDEX 0x00000051 +#define BLE_COEXIFCNTL1_RESET 0x00000000 + +__INLINE uint32_t ble_coexifcntl1_get(void) +{ + return REG_BLE_RD(BLE_COEXIFCNTL1_ADDR); +} + +__INLINE void ble_coexifcntl1_set(uint32_t value) +{ + REG_BLE_WR(BLE_COEXIFCNTL1_ADDR, value); +} + +// field definitions +#define BLE_WLCPRXTHR_MASK ((uint32_t)0x1F000000) +#define BLE_WLCPRXTHR_LSB 24 +#define BLE_WLCPRXTHR_WIDTH ((uint32_t)0x00000005) +#define BLE_WLCPTXTHR_MASK ((uint32_t)0x001F0000) +#define BLE_WLCPTXTHR_LSB 16 +#define BLE_WLCPTXTHR_WIDTH ((uint32_t)0x00000005) +#define BLE_WLCPDURATION_MASK ((uint32_t)0x00007F00) +#define BLE_WLCPDURATION_LSB 8 +#define BLE_WLCPDURATION_WIDTH ((uint32_t)0x00000007) +#define BLE_WLCPDELAY_MASK ((uint32_t)0x0000007F) +#define BLE_WLCPDELAY_LSB 0 +#define BLE_WLCPDELAY_WIDTH ((uint32_t)0x00000007) + +#define BLE_WLCPRXTHR_RST 0x0 +#define BLE_WLCPTXTHR_RST 0x0 +#define BLE_WLCPDURATION_RST 0x0 +#define BLE_WLCPDELAY_RST 0x0 + +__INLINE void ble_coexifcntl1_pack(uint8_t wlcprxthr, uint8_t wlcptxthr, uint8_t wlcpduration, uint8_t wlcpdelay) +{ + BLE_ASSERT_ERR((((uint32_t)wlcprxthr << 24) & ~((uint32_t)0x1F000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)wlcptxthr << 16) & ~((uint32_t)0x001F0000)) == 0); + BLE_ASSERT_ERR((((uint32_t)wlcpduration << 8) & ~((uint32_t)0x00007F00)) == 0); + BLE_ASSERT_ERR((((uint32_t)wlcpdelay << 0) & ~((uint32_t)0x0000007F)) == 0); + REG_BLE_WR(BLE_COEXIFCNTL1_ADDR, ((uint32_t)wlcprxthr << 24) | ((uint32_t)wlcptxthr << 16) | ((uint32_t)wlcpduration << 8) | ((uint32_t)wlcpdelay << 0)); +} + +__INLINE void ble_coexifcntl1_unpack(uint8_t* wlcprxthr, uint8_t* wlcptxthr, uint8_t* wlcpduration, uint8_t* wlcpdelay) +{ + uint32_t localVal = REG_BLE_RD(BLE_COEXIFCNTL1_ADDR); + + *wlcprxthr = (localVal & ((uint32_t)0x1F000000)) >> 24; + *wlcptxthr = (localVal & ((uint32_t)0x001F0000)) >> 16; + *wlcpduration = (localVal & ((uint32_t)0x00007F00)) >> 8; + *wlcpdelay = (localVal & ((uint32_t)0x0000007F)) >> 0; +} + +__INLINE uint8_t ble_coexifcntl1_wlcprxthr_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_COEXIFCNTL1_ADDR); + return ((localVal & ((uint32_t)0x1F000000)) >> 24); +} + +__INLINE void ble_coexifcntl1_wlcprxthr_setf(uint8_t wlcprxthr) +{ + BLE_ASSERT_ERR((((uint32_t)wlcprxthr << 24) & ~((uint32_t)0x1F000000)) == 0); + REG_BLE_WR(BLE_COEXIFCNTL1_ADDR, (REG_BLE_RD(BLE_COEXIFCNTL1_ADDR) & ~((uint32_t)0x1F000000)) | ((uint32_t)wlcprxthr << 24)); +} + +__INLINE uint8_t ble_coexifcntl1_wlcptxthr_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_COEXIFCNTL1_ADDR); + return ((localVal & ((uint32_t)0x001F0000)) >> 16); +} + +__INLINE void ble_coexifcntl1_wlcptxthr_setf(uint8_t wlcptxthr) +{ + BLE_ASSERT_ERR((((uint32_t)wlcptxthr << 16) & ~((uint32_t)0x001F0000)) == 0); + REG_BLE_WR(BLE_COEXIFCNTL1_ADDR, (REG_BLE_RD(BLE_COEXIFCNTL1_ADDR) & ~((uint32_t)0x001F0000)) | ((uint32_t)wlcptxthr << 16)); +} + +__INLINE uint8_t ble_coexifcntl1_wlcpduration_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_COEXIFCNTL1_ADDR); + return ((localVal & ((uint32_t)0x00007F00)) >> 8); +} + +__INLINE void ble_coexifcntl1_wlcpduration_setf(uint8_t wlcpduration) +{ + BLE_ASSERT_ERR((((uint32_t)wlcpduration << 8) & ~((uint32_t)0x00007F00)) == 0); + REG_BLE_WR(BLE_COEXIFCNTL1_ADDR, (REG_BLE_RD(BLE_COEXIFCNTL1_ADDR) & ~((uint32_t)0x00007F00)) | ((uint32_t)wlcpduration << 8)); +} + +__INLINE uint8_t ble_coexifcntl1_wlcpdelay_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_COEXIFCNTL1_ADDR); + return ((localVal & ((uint32_t)0x0000007F)) >> 0); +} + +__INLINE void ble_coexifcntl1_wlcpdelay_setf(uint8_t wlcpdelay) +{ + BLE_ASSERT_ERR((((uint32_t)wlcpdelay << 0) & ~((uint32_t)0x0000007F)) == 0); + REG_BLE_WR(BLE_COEXIFCNTL1_ADDR, (REG_BLE_RD(BLE_COEXIFCNTL1_ADDR) & ~((uint32_t)0x0000007F)) | ((uint32_t)wlcpdelay << 0)); +} + +/** + * @brief COEXIFCNTL2 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  11:08         RX_ANT_DELAY   0x0
+ *  03:00         TX_ANT_DELAY   0x0
+ * 
+ */ +#define BLE_COEXIFCNTL2_ADDR 0x00900948 +#define BLE_COEXIFCNTL2_OFFSET 0x00000148 +#define BLE_COEXIFCNTL2_INDEX 0x00000052 +#define BLE_COEXIFCNTL2_RESET 0x00000000 + +__INLINE uint32_t ble_coexifcntl2_get(void) +{ + return REG_BLE_RD(BLE_COEXIFCNTL2_ADDR); +} + +__INLINE void ble_coexifcntl2_set(uint32_t value) +{ + REG_BLE_WR(BLE_COEXIFCNTL2_ADDR, value); +} + +// field definitions +#define BLE_RX_ANT_DELAY_MASK ((uint32_t)0x00000F00) +#define BLE_RX_ANT_DELAY_LSB 8 +#define BLE_RX_ANT_DELAY_WIDTH ((uint32_t)0x00000004) +#define BLE_TX_ANT_DELAY_MASK ((uint32_t)0x0000000F) +#define BLE_TX_ANT_DELAY_LSB 0 +#define BLE_TX_ANT_DELAY_WIDTH ((uint32_t)0x00000004) + +#define BLE_RX_ANT_DELAY_RST 0x0 +#define BLE_TX_ANT_DELAY_RST 0x0 + +__INLINE void ble_coexifcntl2_pack(uint8_t rxantdelay, uint8_t txantdelay) +{ + BLE_ASSERT_ERR((((uint32_t)rxantdelay << 8) & ~((uint32_t)0x00000F00)) == 0); + BLE_ASSERT_ERR((((uint32_t)txantdelay << 0) & ~((uint32_t)0x0000000F)) == 0); + REG_BLE_WR(BLE_COEXIFCNTL2_ADDR, ((uint32_t)rxantdelay << 8) | ((uint32_t)txantdelay << 0)); +} + +__INLINE void ble_coexifcntl2_unpack(uint8_t* rxantdelay, uint8_t* txantdelay) +{ + uint32_t localVal = REG_BLE_RD(BLE_COEXIFCNTL2_ADDR); + + *rxantdelay = (localVal & ((uint32_t)0x00000F00)) >> 8; + *txantdelay = (localVal & ((uint32_t)0x0000000F)) >> 0; +} + +__INLINE uint8_t ble_coexifcntl2_rx_ant_delay_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_COEXIFCNTL2_ADDR); + return ((localVal & ((uint32_t)0x00000F00)) >> 8); +} + +__INLINE void ble_coexifcntl2_rx_ant_delay_setf(uint8_t rxantdelay) +{ + BLE_ASSERT_ERR((((uint32_t)rxantdelay << 8) & ~((uint32_t)0x00000F00)) == 0); + REG_BLE_WR(BLE_COEXIFCNTL2_ADDR, (REG_BLE_RD(BLE_COEXIFCNTL2_ADDR) & ~((uint32_t)0x00000F00)) | ((uint32_t)rxantdelay << 8)); +} + +__INLINE uint8_t ble_coexifcntl2_tx_ant_delay_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_COEXIFCNTL2_ADDR); + return ((localVal & ((uint32_t)0x0000000F)) >> 0); +} + +__INLINE void ble_coexifcntl2_tx_ant_delay_setf(uint8_t txantdelay) +{ + BLE_ASSERT_ERR((((uint32_t)txantdelay << 0) & ~((uint32_t)0x0000000F)) == 0); + REG_BLE_WR(BLE_COEXIFCNTL2_ADDR, (REG_BLE_RD(BLE_COEXIFCNTL2_ADDR) & ~((uint32_t)0x0000000F)) | ((uint32_t)txantdelay << 0)); +} + +/** + * @brief BLEMPRIO0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:28                BLEM7   0x3
+ *  27:24                BLEM6   0x4
+ *  23:20                BLEM5   0x8
+ *  19:16                BLEM4   0x9
+ *  15:12                BLEM3   0xA
+ *  11:08                BLEM2   0xD
+ *  07:04                BLEM1   0xE
+ *  03:00                BLEM0   0xF
+ * 
+ */ +#define BLE_BLEMPRIO0_ADDR 0x0090094C +#define BLE_BLEMPRIO0_OFFSET 0x0000014C +#define BLE_BLEMPRIO0_INDEX 0x00000053 +#define BLE_BLEMPRIO0_RESET 0x3489ADEF + +__INLINE uint32_t ble_blemprio0_get(void) +{ + return REG_BLE_RD(BLE_BLEMPRIO0_ADDR); +} + +__INLINE void ble_blemprio0_set(uint32_t value) +{ + REG_BLE_WR(BLE_BLEMPRIO0_ADDR, value); +} + +// field definitions +#define BLE_BLEM7_MASK ((uint32_t)0xF0000000) +#define BLE_BLEM7_LSB 28 +#define BLE_BLEM7_WIDTH ((uint32_t)0x00000004) +#define BLE_BLEM6_MASK ((uint32_t)0x0F000000) +#define BLE_BLEM6_LSB 24 +#define BLE_BLEM6_WIDTH ((uint32_t)0x00000004) +#define BLE_BLEM5_MASK ((uint32_t)0x00F00000) +#define BLE_BLEM5_LSB 20 +#define BLE_BLEM5_WIDTH ((uint32_t)0x00000004) +#define BLE_BLEM4_MASK ((uint32_t)0x000F0000) +#define BLE_BLEM4_LSB 16 +#define BLE_BLEM4_WIDTH ((uint32_t)0x00000004) +#define BLE_BLEM3_MASK ((uint32_t)0x0000F000) +#define BLE_BLEM3_LSB 12 +#define BLE_BLEM3_WIDTH ((uint32_t)0x00000004) +#define BLE_BLEM2_MASK ((uint32_t)0x00000F00) +#define BLE_BLEM2_LSB 8 +#define BLE_BLEM2_WIDTH ((uint32_t)0x00000004) +#define BLE_BLEM1_MASK ((uint32_t)0x000000F0) +#define BLE_BLEM1_LSB 4 +#define BLE_BLEM1_WIDTH ((uint32_t)0x00000004) +#define BLE_BLEM0_MASK ((uint32_t)0x0000000F) +#define BLE_BLEM0_LSB 0 +#define BLE_BLEM0_WIDTH ((uint32_t)0x00000004) + +#define BLE_BLEM7_RST 0x3 +#define BLE_BLEM6_RST 0x4 +#define BLE_BLEM5_RST 0x8 +#define BLE_BLEM4_RST 0x9 +#define BLE_BLEM3_RST 0xA +#define BLE_BLEM2_RST 0xD +#define BLE_BLEM1_RST 0xE +#define BLE_BLEM0_RST 0xF + +__INLINE void ble_blemprio0_pack(uint8_t blem7, uint8_t blem6, uint8_t blem5, uint8_t blem4, uint8_t blem3, uint8_t blem2, uint8_t blem1, uint8_t blem0) +{ + BLE_ASSERT_ERR((((uint32_t)blem7 << 28) & ~((uint32_t)0xF0000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)blem6 << 24) & ~((uint32_t)0x0F000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)blem5 << 20) & ~((uint32_t)0x00F00000)) == 0); + BLE_ASSERT_ERR((((uint32_t)blem4 << 16) & ~((uint32_t)0x000F0000)) == 0); + BLE_ASSERT_ERR((((uint32_t)blem3 << 12) & ~((uint32_t)0x0000F000)) == 0); + BLE_ASSERT_ERR((((uint32_t)blem2 << 8) & ~((uint32_t)0x00000F00)) == 0); + BLE_ASSERT_ERR((((uint32_t)blem1 << 4) & ~((uint32_t)0x000000F0)) == 0); + BLE_ASSERT_ERR((((uint32_t)blem0 << 0) & ~((uint32_t)0x0000000F)) == 0); + REG_BLE_WR(BLE_BLEMPRIO0_ADDR, ((uint32_t)blem7 << 28) | ((uint32_t)blem6 << 24) | ((uint32_t)blem5 << 20) | ((uint32_t)blem4 << 16) | ((uint32_t)blem3 << 12) | ((uint32_t)blem2 << 8) | ((uint32_t)blem1 << 4) | ((uint32_t)blem0 << 0)); +} + +__INLINE void ble_blemprio0_unpack(uint8_t* blem7, uint8_t* blem6, uint8_t* blem5, uint8_t* blem4, uint8_t* blem3, uint8_t* blem2, uint8_t* blem1, uint8_t* blem0) +{ + uint32_t localVal = REG_BLE_RD(BLE_BLEMPRIO0_ADDR); + + *blem7 = (localVal & ((uint32_t)0xF0000000)) >> 28; + *blem6 = (localVal & ((uint32_t)0x0F000000)) >> 24; + *blem5 = (localVal & ((uint32_t)0x00F00000)) >> 20; + *blem4 = (localVal & ((uint32_t)0x000F0000)) >> 16; + *blem3 = (localVal & ((uint32_t)0x0000F000)) >> 12; + *blem2 = (localVal & ((uint32_t)0x00000F00)) >> 8; + *blem1 = (localVal & ((uint32_t)0x000000F0)) >> 4; + *blem0 = (localVal & ((uint32_t)0x0000000F)) >> 0; +} + +__INLINE uint8_t ble_blemprio0_blem7_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_BLEMPRIO0_ADDR); + return ((localVal & ((uint32_t)0xF0000000)) >> 28); +} + +__INLINE void ble_blemprio0_blem7_setf(uint8_t blem7) +{ + BLE_ASSERT_ERR((((uint32_t)blem7 << 28) & ~((uint32_t)0xF0000000)) == 0); + REG_BLE_WR(BLE_BLEMPRIO0_ADDR, (REG_BLE_RD(BLE_BLEMPRIO0_ADDR) & ~((uint32_t)0xF0000000)) | ((uint32_t)blem7 << 28)); +} + +__INLINE uint8_t ble_blemprio0_blem6_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_BLEMPRIO0_ADDR); + return ((localVal & ((uint32_t)0x0F000000)) >> 24); +} + +__INLINE void ble_blemprio0_blem6_setf(uint8_t blem6) +{ + BLE_ASSERT_ERR((((uint32_t)blem6 << 24) & ~((uint32_t)0x0F000000)) == 0); + REG_BLE_WR(BLE_BLEMPRIO0_ADDR, (REG_BLE_RD(BLE_BLEMPRIO0_ADDR) & ~((uint32_t)0x0F000000)) | ((uint32_t)blem6 << 24)); +} + +__INLINE uint8_t ble_blemprio0_blem5_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_BLEMPRIO0_ADDR); + return ((localVal & ((uint32_t)0x00F00000)) >> 20); +} + +__INLINE void ble_blemprio0_blem5_setf(uint8_t blem5) +{ + BLE_ASSERT_ERR((((uint32_t)blem5 << 20) & ~((uint32_t)0x00F00000)) == 0); + REG_BLE_WR(BLE_BLEMPRIO0_ADDR, (REG_BLE_RD(BLE_BLEMPRIO0_ADDR) & ~((uint32_t)0x00F00000)) | ((uint32_t)blem5 << 20)); +} + +__INLINE uint8_t ble_blemprio0_blem4_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_BLEMPRIO0_ADDR); + return ((localVal & ((uint32_t)0x000F0000)) >> 16); +} + +__INLINE void ble_blemprio0_blem4_setf(uint8_t blem4) +{ + BLE_ASSERT_ERR((((uint32_t)blem4 << 16) & ~((uint32_t)0x000F0000)) == 0); + REG_BLE_WR(BLE_BLEMPRIO0_ADDR, (REG_BLE_RD(BLE_BLEMPRIO0_ADDR) & ~((uint32_t)0x000F0000)) | ((uint32_t)blem4 << 16)); +} + +__INLINE uint8_t ble_blemprio0_blem3_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_BLEMPRIO0_ADDR); + return ((localVal & ((uint32_t)0x0000F000)) >> 12); +} + +__INLINE void ble_blemprio0_blem3_setf(uint8_t blem3) +{ + BLE_ASSERT_ERR((((uint32_t)blem3 << 12) & ~((uint32_t)0x0000F000)) == 0); + REG_BLE_WR(BLE_BLEMPRIO0_ADDR, (REG_BLE_RD(BLE_BLEMPRIO0_ADDR) & ~((uint32_t)0x0000F000)) | ((uint32_t)blem3 << 12)); +} + +__INLINE uint8_t ble_blemprio0_blem2_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_BLEMPRIO0_ADDR); + return ((localVal & ((uint32_t)0x00000F00)) >> 8); +} + +__INLINE void ble_blemprio0_blem2_setf(uint8_t blem2) +{ + BLE_ASSERT_ERR((((uint32_t)blem2 << 8) & ~((uint32_t)0x00000F00)) == 0); + REG_BLE_WR(BLE_BLEMPRIO0_ADDR, (REG_BLE_RD(BLE_BLEMPRIO0_ADDR) & ~((uint32_t)0x00000F00)) | ((uint32_t)blem2 << 8)); +} + +__INLINE uint8_t ble_blemprio0_blem1_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_BLEMPRIO0_ADDR); + return ((localVal & ((uint32_t)0x000000F0)) >> 4); +} + +__INLINE void ble_blemprio0_blem1_setf(uint8_t blem1) +{ + BLE_ASSERT_ERR((((uint32_t)blem1 << 4) & ~((uint32_t)0x000000F0)) == 0); + REG_BLE_WR(BLE_BLEMPRIO0_ADDR, (REG_BLE_RD(BLE_BLEMPRIO0_ADDR) & ~((uint32_t)0x000000F0)) | ((uint32_t)blem1 << 4)); +} + +__INLINE uint8_t ble_blemprio0_blem0_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_BLEMPRIO0_ADDR); + return ((localVal & ((uint32_t)0x0000000F)) >> 0); +} + +__INLINE void ble_blemprio0_blem0_setf(uint8_t blem0) +{ + BLE_ASSERT_ERR((((uint32_t)blem0 << 0) & ~((uint32_t)0x0000000F)) == 0); + REG_BLE_WR(BLE_BLEMPRIO0_ADDR, (REG_BLE_RD(BLE_BLEMPRIO0_ADDR) & ~((uint32_t)0x0000000F)) | ((uint32_t)blem0 << 0)); +} + +/** + * @brief BLEMPRIO1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:28               BLEM15   0x3
+ *  27:24               BLEM14   0x4
+ *  23:20               BLEM13   0x8
+ *  19:16               BLEM12   0x9
+ *  15:12               BLEM11   0xA
+ *  11:08               BLEM10   0xF
+ *  07:04                BLEM9   0xD
+ *  03:00                BLEM8   0xC
+ * 
+ */ +#define BLE_BLEMPRIO1_ADDR 0x00900950 +#define BLE_BLEMPRIO1_OFFSET 0x00000150 +#define BLE_BLEMPRIO1_INDEX 0x00000054 +#define BLE_BLEMPRIO1_RESET 0x3489AFDC + +__INLINE uint32_t ble_blemprio1_get(void) +{ + return REG_BLE_RD(BLE_BLEMPRIO1_ADDR); +} + +__INLINE void ble_blemprio1_set(uint32_t value) +{ + REG_BLE_WR(BLE_BLEMPRIO1_ADDR, value); +} + +// field definitions +#define BLE_BLEM15_MASK ((uint32_t)0xF0000000) +#define BLE_BLEM15_LSB 28 +#define BLE_BLEM15_WIDTH ((uint32_t)0x00000004) +#define BLE_BLEM14_MASK ((uint32_t)0x0F000000) +#define BLE_BLEM14_LSB 24 +#define BLE_BLEM14_WIDTH ((uint32_t)0x00000004) +#define BLE_BLEM13_MASK ((uint32_t)0x00F00000) +#define BLE_BLEM13_LSB 20 +#define BLE_BLEM13_WIDTH ((uint32_t)0x00000004) +#define BLE_BLEM12_MASK ((uint32_t)0x000F0000) +#define BLE_BLEM12_LSB 16 +#define BLE_BLEM12_WIDTH ((uint32_t)0x00000004) +#define BLE_BLEM11_MASK ((uint32_t)0x0000F000) +#define BLE_BLEM11_LSB 12 +#define BLE_BLEM11_WIDTH ((uint32_t)0x00000004) +#define BLE_BLEM10_MASK ((uint32_t)0x00000F00) +#define BLE_BLEM10_LSB 8 +#define BLE_BLEM10_WIDTH ((uint32_t)0x00000004) +#define BLE_BLEM9_MASK ((uint32_t)0x000000F0) +#define BLE_BLEM9_LSB 4 +#define BLE_BLEM9_WIDTH ((uint32_t)0x00000004) +#define BLE_BLEM8_MASK ((uint32_t)0x0000000F) +#define BLE_BLEM8_LSB 0 +#define BLE_BLEM8_WIDTH ((uint32_t)0x00000004) + +#define BLE_BLEM15_RST 0x3 +#define BLE_BLEM14_RST 0x4 +#define BLE_BLEM13_RST 0x8 +#define BLE_BLEM12_RST 0x9 +#define BLE_BLEM11_RST 0xA +#define BLE_BLEM10_RST 0xF +#define BLE_BLEM9_RST 0xD +#define BLE_BLEM8_RST 0xC + +__INLINE void ble_blemprio1_pack(uint8_t blem15, uint8_t blem14, uint8_t blem13, uint8_t blem12, uint8_t blem11, uint8_t blem10, uint8_t blem9, uint8_t blem8) +{ + BLE_ASSERT_ERR((((uint32_t)blem15 << 28) & ~((uint32_t)0xF0000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)blem14 << 24) & ~((uint32_t)0x0F000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)blem13 << 20) & ~((uint32_t)0x00F00000)) == 0); + BLE_ASSERT_ERR((((uint32_t)blem12 << 16) & ~((uint32_t)0x000F0000)) == 0); + BLE_ASSERT_ERR((((uint32_t)blem11 << 12) & ~((uint32_t)0x0000F000)) == 0); + BLE_ASSERT_ERR((((uint32_t)blem10 << 8) & ~((uint32_t)0x00000F00)) == 0); + BLE_ASSERT_ERR((((uint32_t)blem9 << 4) & ~((uint32_t)0x000000F0)) == 0); + BLE_ASSERT_ERR((((uint32_t)blem8 << 0) & ~((uint32_t)0x0000000F)) == 0); + REG_BLE_WR(BLE_BLEMPRIO1_ADDR, ((uint32_t)blem15 << 28) | ((uint32_t)blem14 << 24) | ((uint32_t)blem13 << 20) | ((uint32_t)blem12 << 16) | ((uint32_t)blem11 << 12) | ((uint32_t)blem10 << 8) | ((uint32_t)blem9 << 4) | ((uint32_t)blem8 << 0)); +} + +__INLINE void ble_blemprio1_unpack(uint8_t* blem15, uint8_t* blem14, uint8_t* blem13, uint8_t* blem12, uint8_t* blem11, uint8_t* blem10, uint8_t* blem9, uint8_t* blem8) +{ + uint32_t localVal = REG_BLE_RD(BLE_BLEMPRIO1_ADDR); + + *blem15 = (localVal & ((uint32_t)0xF0000000)) >> 28; + *blem14 = (localVal & ((uint32_t)0x0F000000)) >> 24; + *blem13 = (localVal & ((uint32_t)0x00F00000)) >> 20; + *blem12 = (localVal & ((uint32_t)0x000F0000)) >> 16; + *blem11 = (localVal & ((uint32_t)0x0000F000)) >> 12; + *blem10 = (localVal & ((uint32_t)0x00000F00)) >> 8; + *blem9 = (localVal & ((uint32_t)0x000000F0)) >> 4; + *blem8 = (localVal & ((uint32_t)0x0000000F)) >> 0; +} + +__INLINE uint8_t ble_blemprio1_blem15_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_BLEMPRIO1_ADDR); + return ((localVal & ((uint32_t)0xF0000000)) >> 28); +} + +__INLINE void ble_blemprio1_blem15_setf(uint8_t blem15) +{ + BLE_ASSERT_ERR((((uint32_t)blem15 << 28) & ~((uint32_t)0xF0000000)) == 0); + REG_BLE_WR(BLE_BLEMPRIO1_ADDR, (REG_BLE_RD(BLE_BLEMPRIO1_ADDR) & ~((uint32_t)0xF0000000)) | ((uint32_t)blem15 << 28)); +} + +__INLINE uint8_t ble_blemprio1_blem14_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_BLEMPRIO1_ADDR); + return ((localVal & ((uint32_t)0x0F000000)) >> 24); +} + +__INLINE void ble_blemprio1_blem14_setf(uint8_t blem14) +{ + BLE_ASSERT_ERR((((uint32_t)blem14 << 24) & ~((uint32_t)0x0F000000)) == 0); + REG_BLE_WR(BLE_BLEMPRIO1_ADDR, (REG_BLE_RD(BLE_BLEMPRIO1_ADDR) & ~((uint32_t)0x0F000000)) | ((uint32_t)blem14 << 24)); +} + +__INLINE uint8_t ble_blemprio1_blem13_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_BLEMPRIO1_ADDR); + return ((localVal & ((uint32_t)0x00F00000)) >> 20); +} + +__INLINE void ble_blemprio1_blem13_setf(uint8_t blem13) +{ + BLE_ASSERT_ERR((((uint32_t)blem13 << 20) & ~((uint32_t)0x00F00000)) == 0); + REG_BLE_WR(BLE_BLEMPRIO1_ADDR, (REG_BLE_RD(BLE_BLEMPRIO1_ADDR) & ~((uint32_t)0x00F00000)) | ((uint32_t)blem13 << 20)); +} + +__INLINE uint8_t ble_blemprio1_blem12_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_BLEMPRIO1_ADDR); + return ((localVal & ((uint32_t)0x000F0000)) >> 16); +} + +__INLINE void ble_blemprio1_blem12_setf(uint8_t blem12) +{ + BLE_ASSERT_ERR((((uint32_t)blem12 << 16) & ~((uint32_t)0x000F0000)) == 0); + REG_BLE_WR(BLE_BLEMPRIO1_ADDR, (REG_BLE_RD(BLE_BLEMPRIO1_ADDR) & ~((uint32_t)0x000F0000)) | ((uint32_t)blem12 << 16)); +} + +__INLINE uint8_t ble_blemprio1_blem11_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_BLEMPRIO1_ADDR); + return ((localVal & ((uint32_t)0x0000F000)) >> 12); +} + +__INLINE void ble_blemprio1_blem11_setf(uint8_t blem11) +{ + BLE_ASSERT_ERR((((uint32_t)blem11 << 12) & ~((uint32_t)0x0000F000)) == 0); + REG_BLE_WR(BLE_BLEMPRIO1_ADDR, (REG_BLE_RD(BLE_BLEMPRIO1_ADDR) & ~((uint32_t)0x0000F000)) | ((uint32_t)blem11 << 12)); +} + +__INLINE uint8_t ble_blemprio1_blem10_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_BLEMPRIO1_ADDR); + return ((localVal & ((uint32_t)0x00000F00)) >> 8); +} + +__INLINE void ble_blemprio1_blem10_setf(uint8_t blem10) +{ + BLE_ASSERT_ERR((((uint32_t)blem10 << 8) & ~((uint32_t)0x00000F00)) == 0); + REG_BLE_WR(BLE_BLEMPRIO1_ADDR, (REG_BLE_RD(BLE_BLEMPRIO1_ADDR) & ~((uint32_t)0x00000F00)) | ((uint32_t)blem10 << 8)); +} + +__INLINE uint8_t ble_blemprio1_blem9_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_BLEMPRIO1_ADDR); + return ((localVal & ((uint32_t)0x000000F0)) >> 4); +} + +__INLINE void ble_blemprio1_blem9_setf(uint8_t blem9) +{ + BLE_ASSERT_ERR((((uint32_t)blem9 << 4) & ~((uint32_t)0x000000F0)) == 0); + REG_BLE_WR(BLE_BLEMPRIO1_ADDR, (REG_BLE_RD(BLE_BLEMPRIO1_ADDR) & ~((uint32_t)0x000000F0)) | ((uint32_t)blem9 << 4)); +} + +__INLINE uint8_t ble_blemprio1_blem8_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_BLEMPRIO1_ADDR); + return ((localVal & ((uint32_t)0x0000000F)) >> 0); +} + +__INLINE void ble_blemprio1_blem8_setf(uint8_t blem8) +{ + BLE_ASSERT_ERR((((uint32_t)blem8 << 0) & ~((uint32_t)0x0000000F)) == 0); + REG_BLE_WR(BLE_BLEMPRIO1_ADDR, (REG_BLE_RD(BLE_BLEMPRIO1_ADDR) & ~((uint32_t)0x0000000F)) | ((uint32_t)blem8 << 0)); +} + +/** + * @brief BLEMPRIO2 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:28          BLEMDEFAULT   0x3
+ *  11:08               BLEM18   0x2
+ *  07:04               BLEM17   0x7
+ *  03:00               BLEM16   0x7
+ * 
+ */ +#define BLE_BLEMPRIO2_ADDR 0x00900954 +#define BLE_BLEMPRIO2_OFFSET 0x00000154 +#define BLE_BLEMPRIO2_INDEX 0x00000055 +#define BLE_BLEMPRIO2_RESET 0x30000277 + +__INLINE uint32_t ble_blemprio2_get(void) +{ + return REG_BLE_RD(BLE_BLEMPRIO2_ADDR); +} + +__INLINE void ble_blemprio2_set(uint32_t value) +{ + REG_BLE_WR(BLE_BLEMPRIO2_ADDR, value); +} + +// field definitions +#define BLE_BLEMDEFAULT_MASK ((uint32_t)0xF0000000) +#define BLE_BLEMDEFAULT_LSB 28 +#define BLE_BLEMDEFAULT_WIDTH ((uint32_t)0x00000004) +#define BLE_BLEM18_MASK ((uint32_t)0x00000F00) +#define BLE_BLEM18_LSB 8 +#define BLE_BLEM18_WIDTH ((uint32_t)0x00000004) +#define BLE_BLEM17_MASK ((uint32_t)0x000000F0) +#define BLE_BLEM17_LSB 4 +#define BLE_BLEM17_WIDTH ((uint32_t)0x00000004) +#define BLE_BLEM16_MASK ((uint32_t)0x0000000F) +#define BLE_BLEM16_LSB 0 +#define BLE_BLEM16_WIDTH ((uint32_t)0x00000004) + +#define BLE_BLEMDEFAULT_RST 0x3 +#define BLE_BLEM18_RST 0x2 +#define BLE_BLEM17_RST 0x7 +#define BLE_BLEM16_RST 0x7 + +__INLINE void ble_blemprio2_pack(uint8_t blemdefault, uint8_t blem18, uint8_t blem17, uint8_t blem16) +{ + BLE_ASSERT_ERR((((uint32_t)blemdefault << 28) & ~((uint32_t)0xF0000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)blem18 << 8) & ~((uint32_t)0x00000F00)) == 0); + BLE_ASSERT_ERR((((uint32_t)blem17 << 4) & ~((uint32_t)0x000000F0)) == 0); + BLE_ASSERT_ERR((((uint32_t)blem16 << 0) & ~((uint32_t)0x0000000F)) == 0); + REG_BLE_WR(BLE_BLEMPRIO2_ADDR, ((uint32_t)blemdefault << 28) | ((uint32_t)blem18 << 8) | ((uint32_t)blem17 << 4) | ((uint32_t)blem16 << 0)); +} + +__INLINE void ble_blemprio2_unpack(uint8_t* blemdefault, uint8_t* blem18, uint8_t* blem17, uint8_t* blem16) +{ + uint32_t localVal = REG_BLE_RD(BLE_BLEMPRIO2_ADDR); + + *blemdefault = (localVal & ((uint32_t)0xF0000000)) >> 28; + *blem18 = (localVal & ((uint32_t)0x00000F00)) >> 8; + *blem17 = (localVal & ((uint32_t)0x000000F0)) >> 4; + *blem16 = (localVal & ((uint32_t)0x0000000F)) >> 0; +} + +__INLINE uint8_t ble_blemprio2_blemdefault_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_BLEMPRIO2_ADDR); + return ((localVal & ((uint32_t)0xF0000000)) >> 28); +} + +__INLINE void ble_blemprio2_blemdefault_setf(uint8_t blemdefault) +{ + BLE_ASSERT_ERR((((uint32_t)blemdefault << 28) & ~((uint32_t)0xF0000000)) == 0); + REG_BLE_WR(BLE_BLEMPRIO2_ADDR, (REG_BLE_RD(BLE_BLEMPRIO2_ADDR) & ~((uint32_t)0xF0000000)) | ((uint32_t)blemdefault << 28)); +} + +__INLINE uint8_t ble_blemprio2_blem18_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_BLEMPRIO2_ADDR); + return ((localVal & ((uint32_t)0x00000F00)) >> 8); +} + +__INLINE void ble_blemprio2_blem18_setf(uint8_t blem18) +{ + BLE_ASSERT_ERR((((uint32_t)blem18 << 8) & ~((uint32_t)0x00000F00)) == 0); + REG_BLE_WR(BLE_BLEMPRIO2_ADDR, (REG_BLE_RD(BLE_BLEMPRIO2_ADDR) & ~((uint32_t)0x00000F00)) | ((uint32_t)blem18 << 8)); +} + +__INLINE uint8_t ble_blemprio2_blem17_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_BLEMPRIO2_ADDR); + return ((localVal & ((uint32_t)0x000000F0)) >> 4); +} + +__INLINE void ble_blemprio2_blem17_setf(uint8_t blem17) +{ + BLE_ASSERT_ERR((((uint32_t)blem17 << 4) & ~((uint32_t)0x000000F0)) == 0); + REG_BLE_WR(BLE_BLEMPRIO2_ADDR, (REG_BLE_RD(BLE_BLEMPRIO2_ADDR) & ~((uint32_t)0x000000F0)) | ((uint32_t)blem17 << 4)); +} + +__INLINE uint8_t ble_blemprio2_blem16_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_BLEMPRIO2_ADDR); + return ((localVal & ((uint32_t)0x0000000F)) >> 0); +} + +__INLINE void ble_blemprio2_blem16_setf(uint8_t blem16) +{ + BLE_ASSERT_ERR((((uint32_t)blem16 << 0) & ~((uint32_t)0x0000000F)) == 0); + REG_BLE_WR(BLE_BLEMPRIO2_ADDR, (REG_BLE_RD(BLE_BLEMPRIO2_ADDR) & ~((uint32_t)0x0000000F)) | ((uint32_t)blem16 << 0)); +} + +/** + * @brief RALCNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  23:16             RALNBDEV   0x0
+ *  13:00           RALBASEPTR   0x0
+ * 
+ */ +#define BLE_RALCNTL_ADDR 0x00900960 +#define BLE_RALCNTL_OFFSET 0x00000160 +#define BLE_RALCNTL_INDEX 0x00000058 +#define BLE_RALCNTL_RESET 0x00000000 + +__INLINE uint32_t ble_ralcntl_get(void) +{ + return REG_BLE_RD(BLE_RALCNTL_ADDR); +} + +__INLINE void ble_ralcntl_set(uint32_t value) +{ + REG_BLE_WR(BLE_RALCNTL_ADDR, value); +} + +// field definitions +#define BLE_RALNBDEV_MASK ((uint32_t)0x00FF0000) +#define BLE_RALNBDEV_LSB 16 +#define BLE_RALNBDEV_WIDTH ((uint32_t)0x00000008) +#define BLE_RALBASEPTR_MASK ((uint32_t)0x00003FFF) +#define BLE_RALBASEPTR_LSB 0 +#define BLE_RALBASEPTR_WIDTH ((uint32_t)0x0000000E) + +#define BLE_RALNBDEV_RST 0x0 +#define BLE_RALBASEPTR_RST 0x0 + +__INLINE void ble_ralcntl_pack(uint8_t ralnbdev, uint16_t ralbaseptr) +{ + BLE_ASSERT_ERR((((uint32_t)ralnbdev << 16) & ~((uint32_t)0x00FF0000)) == 0); + BLE_ASSERT_ERR((((uint32_t)ralbaseptr << 0) & ~((uint32_t)0x00003FFF)) == 0); + REG_BLE_WR(BLE_RALCNTL_ADDR, ((uint32_t)ralnbdev << 16) | ((uint32_t)ralbaseptr << 0)); +} + +__INLINE void ble_ralcntl_unpack(uint8_t* ralnbdev, uint16_t* ralbaseptr) +{ + uint32_t localVal = REG_BLE_RD(BLE_RALCNTL_ADDR); + + *ralnbdev = (localVal & ((uint32_t)0x00FF0000)) >> 16; + *ralbaseptr = (localVal & ((uint32_t)0x00003FFF)) >> 0; +} + +__INLINE uint8_t ble_ralcntl_ralnbdev_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RALCNTL_ADDR); + return ((localVal & ((uint32_t)0x00FF0000)) >> 16); +} + +__INLINE void ble_ralcntl_ralnbdev_setf(uint8_t ralnbdev) +{ + BLE_ASSERT_ERR((((uint32_t)ralnbdev << 16) & ~((uint32_t)0x00FF0000)) == 0); + REG_BLE_WR(BLE_RALCNTL_ADDR, (REG_BLE_RD(BLE_RALCNTL_ADDR) & ~((uint32_t)0x00FF0000)) | ((uint32_t)ralnbdev << 16)); +} + +__INLINE uint16_t ble_ralcntl_ralbaseptr_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RALCNTL_ADDR); + return ((localVal & ((uint32_t)0x00003FFF)) >> 0); +} + +__INLINE void ble_ralcntl_ralbaseptr_setf(uint16_t ralbaseptr) +{ + BLE_ASSERT_ERR((((uint32_t)ralbaseptr << 0) & ~((uint32_t)0x00003FFF)) == 0); + REG_BLE_WR(BLE_RALCNTL_ADDR, (REG_BLE_RD(BLE_RALCNTL_ADDR) & ~((uint32_t)0x00003FFF)) | ((uint32_t)ralbaseptr << 0)); +} + +/** + * @brief RALCURRENTPTR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  13:00        RALCURRENTPTR   0x0
+ * 
+ */ +#define BLE_RALCURRENTPTR_ADDR 0x00900964 +#define BLE_RALCURRENTPTR_OFFSET 0x00000164 +#define BLE_RALCURRENTPTR_INDEX 0x00000059 +#define BLE_RALCURRENTPTR_RESET 0x00000000 + +__INLINE uint32_t ble_ralcurrentptr_get(void) +{ + return REG_BLE_RD(BLE_RALCURRENTPTR_ADDR); +} + +__INLINE void ble_ralcurrentptr_set(uint32_t value) +{ + REG_BLE_WR(BLE_RALCURRENTPTR_ADDR, value); +} + +// field definitions +#define BLE_RALCURRENTPTR_MASK ((uint32_t)0x00003FFF) +#define BLE_RALCURRENTPTR_LSB 0 +#define BLE_RALCURRENTPTR_WIDTH ((uint32_t)0x0000000E) + +#define BLE_RALCURRENTPTR_RST 0x0 + +__INLINE uint16_t ble_ralcurrentptr_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RALCURRENTPTR_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0x00003FFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_ralcurrentptr_setf(uint16_t ralcurrentptr) +{ + BLE_ASSERT_ERR((((uint32_t)ralcurrentptr << 0) & ~((uint32_t)0x00003FFF)) == 0); + REG_BLE_WR(BLE_RALCURRENTPTR_ADDR, (uint32_t)ralcurrentptr << 0); +} + +/** + * @brief RAL_LOCAL_RND register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31            LRND_INIT   0
+ *  21:00             LRND_VAL   0x3F0F0F
+ * 
+ */ +#define BLE_RAL_LOCAL_RND_ADDR 0x00900968 +#define BLE_RAL_LOCAL_RND_OFFSET 0x00000168 +#define BLE_RAL_LOCAL_RND_INDEX 0x0000005A +#define BLE_RAL_LOCAL_RND_RESET 0x003F0F0F + +__INLINE uint32_t ble_ral_local_rnd_get(void) +{ + return REG_BLE_RD(BLE_RAL_LOCAL_RND_ADDR); +} + +__INLINE void ble_ral_local_rnd_set(uint32_t value) +{ + REG_BLE_WR(BLE_RAL_LOCAL_RND_ADDR, value); +} + +// field definitions +#define BLE_LRND_INIT_BIT ((uint32_t)0x80000000) +#define BLE_LRND_INIT_POS 31 +#define BLE_LRND_VAL_MASK ((uint32_t)0x003FFFFF) +#define BLE_LRND_VAL_LSB 0 +#define BLE_LRND_VAL_WIDTH ((uint32_t)0x00000016) + +#define BLE_LRND_INIT_RST 0x0 +#define BLE_LRND_VAL_RST 0x3F0F0F + +__INLINE void ble_ral_local_rnd_pack(uint8_t lrndinit, uint32_t lrndval) +{ + BLE_ASSERT_ERR((((uint32_t)lrndinit << 31) & ~((uint32_t)0x80000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)lrndval << 0) & ~((uint32_t)0x003FFFFF)) == 0); + REG_BLE_WR(BLE_RAL_LOCAL_RND_ADDR, ((uint32_t)lrndinit << 31) | ((uint32_t)lrndval << 0)); +} + +__INLINE void ble_ral_local_rnd_unpack(uint8_t* lrndinit, uint32_t* lrndval) +{ + uint32_t localVal = REG_BLE_RD(BLE_RAL_LOCAL_RND_ADDR); + + *lrndinit = (localVal & ((uint32_t)0x80000000)) >> 31; + *lrndval = (localVal & ((uint32_t)0x003FFFFF)) >> 0; +} + +__INLINE uint8_t ble_ral_local_rnd_lrnd_init_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RAL_LOCAL_RND_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +__INLINE void ble_ral_local_rnd_lrnd_init_setf(uint8_t lrndinit) +{ + BLE_ASSERT_ERR((((uint32_t)lrndinit << 31) & ~((uint32_t)0x80000000)) == 0); + REG_BLE_WR(BLE_RAL_LOCAL_RND_ADDR, (REG_BLE_RD(BLE_RAL_LOCAL_RND_ADDR) & ~((uint32_t)0x80000000)) | ((uint32_t)lrndinit << 31)); +} + +__INLINE uint32_t ble_ral_local_rnd_lrnd_val_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RAL_LOCAL_RND_ADDR); + return ((localVal & ((uint32_t)0x003FFFFF)) >> 0); +} + +__INLINE void ble_ral_local_rnd_lrnd_val_setf(uint32_t lrndval) +{ + BLE_ASSERT_ERR((((uint32_t)lrndval << 0) & ~((uint32_t)0x003FFFFF)) == 0); + REG_BLE_WR(BLE_RAL_LOCAL_RND_ADDR, (REG_BLE_RD(BLE_RAL_LOCAL_RND_ADDR) & ~((uint32_t)0x003FFFFF)) | ((uint32_t)lrndval << 0)); +} + +/** + * @brief RAL_PEER_RND register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31            PRND_INIT   0
+ *  21:00             PRND_VAL   0x30F0F0
+ * 
+ */ +#define BLE_RAL_PEER_RND_ADDR 0x0090096C +#define BLE_RAL_PEER_RND_OFFSET 0x0000016C +#define BLE_RAL_PEER_RND_INDEX 0x0000005B +#define BLE_RAL_PEER_RND_RESET 0x0030F0F0 + +__INLINE uint32_t ble_ral_peer_rnd_get(void) +{ + return REG_BLE_RD(BLE_RAL_PEER_RND_ADDR); +} + +__INLINE void ble_ral_peer_rnd_set(uint32_t value) +{ + REG_BLE_WR(BLE_RAL_PEER_RND_ADDR, value); +} + +// field definitions +#define BLE_PRND_INIT_BIT ((uint32_t)0x80000000) +#define BLE_PRND_INIT_POS 31 +#define BLE_PRND_VAL_MASK ((uint32_t)0x003FFFFF) +#define BLE_PRND_VAL_LSB 0 +#define BLE_PRND_VAL_WIDTH ((uint32_t)0x00000016) + +#define BLE_PRND_INIT_RST 0x0 +#define BLE_PRND_VAL_RST 0x30F0F0 + +__INLINE void ble_ral_peer_rnd_pack(uint8_t prndinit, uint32_t prndval) +{ + BLE_ASSERT_ERR((((uint32_t)prndinit << 31) & ~((uint32_t)0x80000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)prndval << 0) & ~((uint32_t)0x003FFFFF)) == 0); + REG_BLE_WR(BLE_RAL_PEER_RND_ADDR, ((uint32_t)prndinit << 31) | ((uint32_t)prndval << 0)); +} + +__INLINE void ble_ral_peer_rnd_unpack(uint8_t* prndinit, uint32_t* prndval) +{ + uint32_t localVal = REG_BLE_RD(BLE_RAL_PEER_RND_ADDR); + + *prndinit = (localVal & ((uint32_t)0x80000000)) >> 31; + *prndval = (localVal & ((uint32_t)0x003FFFFF)) >> 0; +} + +__INLINE uint8_t ble_ral_peer_rnd_prnd_init_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RAL_PEER_RND_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +__INLINE void ble_ral_peer_rnd_prnd_init_setf(uint8_t prndinit) +{ + BLE_ASSERT_ERR((((uint32_t)prndinit << 31) & ~((uint32_t)0x80000000)) == 0); + REG_BLE_WR(BLE_RAL_PEER_RND_ADDR, (REG_BLE_RD(BLE_RAL_PEER_RND_ADDR) & ~((uint32_t)0x80000000)) | ((uint32_t)prndinit << 31)); +} + +__INLINE uint32_t ble_ral_peer_rnd_prnd_val_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_RAL_PEER_RND_ADDR); + return ((localVal & ((uint32_t)0x003FFFFF)) >> 0); +} + +__INLINE void ble_ral_peer_rnd_prnd_val_setf(uint32_t prndval) +{ + BLE_ASSERT_ERR((((uint32_t)prndval << 0) & ~((uint32_t)0x003FFFFF)) == 0); + REG_BLE_WR(BLE_RAL_PEER_RND_ADDR, (REG_BLE_RD(BLE_RAL_PEER_RND_ADDR) & ~((uint32_t)0x003FFFFF)) | ((uint32_t)prndval << 0)); +} + +/** + * @brief DFCNTL0_1US register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:24    RXSAMPSTINST0_1US   0x0
+ *  23:16      RXSWSTINST0_1US   0x0
+ *  07:00      TXSWSTINST0_1US   0x0
+ * 
+ */ +#define BLE_DFCNTL0_1US_ADDR 0x00900970 +#define BLE_DFCNTL0_1US_OFFSET 0x00000170 +#define BLE_DFCNTL0_1US_INDEX 0x0000005C +#define BLE_DFCNTL0_1US_RESET 0x00000000 + +__INLINE uint32_t ble_dfcntl0_1us_get(void) +{ + return REG_BLE_RD(BLE_DFCNTL0_1US_ADDR); +} + +__INLINE void ble_dfcntl0_1us_set(uint32_t value) +{ + REG_BLE_WR(BLE_DFCNTL0_1US_ADDR, value); +} + +// field definitions +#define BLE_RXSAMPSTINST0_1US_MASK ((uint32_t)0xFF000000) +#define BLE_RXSAMPSTINST0_1US_LSB 24 +#define BLE_RXSAMPSTINST0_1US_WIDTH ((uint32_t)0x00000008) +#define BLE_RXSWSTINST0_1US_MASK ((uint32_t)0x00FF0000) +#define BLE_RXSWSTINST0_1US_LSB 16 +#define BLE_RXSWSTINST0_1US_WIDTH ((uint32_t)0x00000008) +#define BLE_TXSWSTINST0_1US_MASK ((uint32_t)0x000000FF) +#define BLE_TXSWSTINST0_1US_LSB 0 +#define BLE_TXSWSTINST0_1US_WIDTH ((uint32_t)0x00000008) + +#define BLE_RXSAMPSTINST0_1US_RST 0x0 +#define BLE_RXSWSTINST0_1US_RST 0x0 +#define BLE_TXSWSTINST0_1US_RST 0x0 + +__INLINE void ble_dfcntl0_1us_pack(uint8_t rxsampstinst01us, uint8_t rxswstinst01us, uint8_t txswstinst01us) +{ + BLE_ASSERT_ERR((((uint32_t)rxsampstinst01us << 24) & ~((uint32_t)0xFF000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)rxswstinst01us << 16) & ~((uint32_t)0x00FF0000)) == 0); + BLE_ASSERT_ERR((((uint32_t)txswstinst01us << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_BLE_WR(BLE_DFCNTL0_1US_ADDR, ((uint32_t)rxsampstinst01us << 24) | ((uint32_t)rxswstinst01us << 16) | ((uint32_t)txswstinst01us << 0)); +} + +__INLINE void ble_dfcntl0_1us_unpack(uint8_t* rxsampstinst01us, uint8_t* rxswstinst01us, uint8_t* txswstinst01us) +{ + uint32_t localVal = REG_BLE_RD(BLE_DFCNTL0_1US_ADDR); + + *rxsampstinst01us = (localVal & ((uint32_t)0xFF000000)) >> 24; + *rxswstinst01us = (localVal & ((uint32_t)0x00FF0000)) >> 16; + *txswstinst01us = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +__INLINE uint8_t ble_dfcntl0_1us_rxsampstinst0_1us_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DFCNTL0_1US_ADDR); + return ((localVal & ((uint32_t)0xFF000000)) >> 24); +} + +__INLINE void ble_dfcntl0_1us_rxsampstinst0_1us_setf(uint8_t rxsampstinst01us) +{ + BLE_ASSERT_ERR((((uint32_t)rxsampstinst01us << 24) & ~((uint32_t)0xFF000000)) == 0); + REG_BLE_WR(BLE_DFCNTL0_1US_ADDR, (REG_BLE_RD(BLE_DFCNTL0_1US_ADDR) & ~((uint32_t)0xFF000000)) | ((uint32_t)rxsampstinst01us << 24)); +} + +__INLINE uint8_t ble_dfcntl0_1us_rxswstinst0_1us_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DFCNTL0_1US_ADDR); + return ((localVal & ((uint32_t)0x00FF0000)) >> 16); +} + +__INLINE void ble_dfcntl0_1us_rxswstinst0_1us_setf(uint8_t rxswstinst01us) +{ + BLE_ASSERT_ERR((((uint32_t)rxswstinst01us << 16) & ~((uint32_t)0x00FF0000)) == 0); + REG_BLE_WR(BLE_DFCNTL0_1US_ADDR, (REG_BLE_RD(BLE_DFCNTL0_1US_ADDR) & ~((uint32_t)0x00FF0000)) | ((uint32_t)rxswstinst01us << 16)); +} + +__INLINE uint8_t ble_dfcntl0_1us_txswstinst0_1us_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DFCNTL0_1US_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +__INLINE void ble_dfcntl0_1us_txswstinst0_1us_setf(uint8_t txswstinst01us) +{ + BLE_ASSERT_ERR((((uint32_t)txswstinst01us << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_BLE_WR(BLE_DFCNTL0_1US_ADDR, (REG_BLE_RD(BLE_DFCNTL0_1US_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)txswstinst01us << 0)); +} + +/** + * @brief DFCNTL0_2US register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:24    RXSAMPSTINST0_2US   0x0
+ *  23:16      RXSWSTINST0_2US   0x0
+ *  07:00      TXSWSTINST0_2US   0x0
+ * 
+ */ +#define BLE_DFCNTL0_2US_ADDR 0x00900974 +#define BLE_DFCNTL0_2US_OFFSET 0x00000174 +#define BLE_DFCNTL0_2US_INDEX 0x0000005D +#define BLE_DFCNTL0_2US_RESET 0x00000000 + +__INLINE uint32_t ble_dfcntl0_2us_get(void) +{ + return REG_BLE_RD(BLE_DFCNTL0_2US_ADDR); +} + +__INLINE void ble_dfcntl0_2us_set(uint32_t value) +{ + REG_BLE_WR(BLE_DFCNTL0_2US_ADDR, value); +} + +// field definitions +#define BLE_RXSAMPSTINST0_2US_MASK ((uint32_t)0xFF000000) +#define BLE_RXSAMPSTINST0_2US_LSB 24 +#define BLE_RXSAMPSTINST0_2US_WIDTH ((uint32_t)0x00000008) +#define BLE_RXSWSTINST0_2US_MASK ((uint32_t)0x00FF0000) +#define BLE_RXSWSTINST0_2US_LSB 16 +#define BLE_RXSWSTINST0_2US_WIDTH ((uint32_t)0x00000008) +#define BLE_TXSWSTINST0_2US_MASK ((uint32_t)0x000000FF) +#define BLE_TXSWSTINST0_2US_LSB 0 +#define BLE_TXSWSTINST0_2US_WIDTH ((uint32_t)0x00000008) + +#define BLE_RXSAMPSTINST0_2US_RST 0x0 +#define BLE_RXSWSTINST0_2US_RST 0x0 +#define BLE_TXSWSTINST0_2US_RST 0x0 + +__INLINE void ble_dfcntl0_2us_pack(uint8_t rxsampstinst02us, uint8_t rxswstinst02us, uint8_t txswstinst02us) +{ + BLE_ASSERT_ERR((((uint32_t)rxsampstinst02us << 24) & ~((uint32_t)0xFF000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)rxswstinst02us << 16) & ~((uint32_t)0x00FF0000)) == 0); + BLE_ASSERT_ERR((((uint32_t)txswstinst02us << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_BLE_WR(BLE_DFCNTL0_2US_ADDR, ((uint32_t)rxsampstinst02us << 24) | ((uint32_t)rxswstinst02us << 16) | ((uint32_t)txswstinst02us << 0)); +} + +__INLINE void ble_dfcntl0_2us_unpack(uint8_t* rxsampstinst02us, uint8_t* rxswstinst02us, uint8_t* txswstinst02us) +{ + uint32_t localVal = REG_BLE_RD(BLE_DFCNTL0_2US_ADDR); + + *rxsampstinst02us = (localVal & ((uint32_t)0xFF000000)) >> 24; + *rxswstinst02us = (localVal & ((uint32_t)0x00FF0000)) >> 16; + *txswstinst02us = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +__INLINE uint8_t ble_dfcntl0_2us_rxsampstinst0_2us_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DFCNTL0_2US_ADDR); + return ((localVal & ((uint32_t)0xFF000000)) >> 24); +} + +__INLINE void ble_dfcntl0_2us_rxsampstinst0_2us_setf(uint8_t rxsampstinst02us) +{ + BLE_ASSERT_ERR((((uint32_t)rxsampstinst02us << 24) & ~((uint32_t)0xFF000000)) == 0); + REG_BLE_WR(BLE_DFCNTL0_2US_ADDR, (REG_BLE_RD(BLE_DFCNTL0_2US_ADDR) & ~((uint32_t)0xFF000000)) | ((uint32_t)rxsampstinst02us << 24)); +} + +__INLINE uint8_t ble_dfcntl0_2us_rxswstinst0_2us_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DFCNTL0_2US_ADDR); + return ((localVal & ((uint32_t)0x00FF0000)) >> 16); +} + +__INLINE void ble_dfcntl0_2us_rxswstinst0_2us_setf(uint8_t rxswstinst02us) +{ + BLE_ASSERT_ERR((((uint32_t)rxswstinst02us << 16) & ~((uint32_t)0x00FF0000)) == 0); + REG_BLE_WR(BLE_DFCNTL0_2US_ADDR, (REG_BLE_RD(BLE_DFCNTL0_2US_ADDR) & ~((uint32_t)0x00FF0000)) | ((uint32_t)rxswstinst02us << 16)); +} + +__INLINE uint8_t ble_dfcntl0_2us_txswstinst0_2us_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DFCNTL0_2US_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +__INLINE void ble_dfcntl0_2us_txswstinst0_2us_setf(uint8_t txswstinst02us) +{ + BLE_ASSERT_ERR((((uint32_t)txswstinst02us << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_BLE_WR(BLE_DFCNTL0_2US_ADDR, (REG_BLE_RD(BLE_DFCNTL0_2US_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)txswstinst02us << 0)); +} + +/** + * @brief DFCNTL1_1US register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:24    RXSAMPSTINST1_1US   0x0
+ *  23:16      RXSWSTINST1_1US   0x0
+ *  07:00      TXSWSTINST1_1US   0x0
+ * 
+ */ +#define BLE_DFCNTL1_1US_ADDR 0x00900978 +#define BLE_DFCNTL1_1US_OFFSET 0x00000178 +#define BLE_DFCNTL1_1US_INDEX 0x0000005E +#define BLE_DFCNTL1_1US_RESET 0x00000000 + +__INLINE uint32_t ble_dfcntl1_1us_get(void) +{ + return REG_BLE_RD(BLE_DFCNTL1_1US_ADDR); +} + +__INLINE void ble_dfcntl1_1us_set(uint32_t value) +{ + REG_BLE_WR(BLE_DFCNTL1_1US_ADDR, value); +} + +// field definitions +#define BLE_RXSAMPSTINST1_1US_MASK ((uint32_t)0xFF000000) +#define BLE_RXSAMPSTINST1_1US_LSB 24 +#define BLE_RXSAMPSTINST1_1US_WIDTH ((uint32_t)0x00000008) +#define BLE_RXSWSTINST1_1US_MASK ((uint32_t)0x00FF0000) +#define BLE_RXSWSTINST1_1US_LSB 16 +#define BLE_RXSWSTINST1_1US_WIDTH ((uint32_t)0x00000008) +#define BLE_TXSWSTINST1_1US_MASK ((uint32_t)0x000000FF) +#define BLE_TXSWSTINST1_1US_LSB 0 +#define BLE_TXSWSTINST1_1US_WIDTH ((uint32_t)0x00000008) + +#define BLE_RXSAMPSTINST1_1US_RST 0x0 +#define BLE_RXSWSTINST1_1US_RST 0x0 +#define BLE_TXSWSTINST1_1US_RST 0x0 + +__INLINE void ble_dfcntl1_1us_pack(uint8_t rxsampstinst11us, uint8_t rxswstinst11us, uint8_t txswstinst11us) +{ + BLE_ASSERT_ERR((((uint32_t)rxsampstinst11us << 24) & ~((uint32_t)0xFF000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)rxswstinst11us << 16) & ~((uint32_t)0x00FF0000)) == 0); + BLE_ASSERT_ERR((((uint32_t)txswstinst11us << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_BLE_WR(BLE_DFCNTL1_1US_ADDR, ((uint32_t)rxsampstinst11us << 24) | ((uint32_t)rxswstinst11us << 16) | ((uint32_t)txswstinst11us << 0)); +} + +__INLINE void ble_dfcntl1_1us_unpack(uint8_t* rxsampstinst11us, uint8_t* rxswstinst11us, uint8_t* txswstinst11us) +{ + uint32_t localVal = REG_BLE_RD(BLE_DFCNTL1_1US_ADDR); + + *rxsampstinst11us = (localVal & ((uint32_t)0xFF000000)) >> 24; + *rxswstinst11us = (localVal & ((uint32_t)0x00FF0000)) >> 16; + *txswstinst11us = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +__INLINE uint8_t ble_dfcntl1_1us_rxsampstinst1_1us_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DFCNTL1_1US_ADDR); + return ((localVal & ((uint32_t)0xFF000000)) >> 24); +} + +__INLINE void ble_dfcntl1_1us_rxsampstinst1_1us_setf(uint8_t rxsampstinst11us) +{ + BLE_ASSERT_ERR((((uint32_t)rxsampstinst11us << 24) & ~((uint32_t)0xFF000000)) == 0); + REG_BLE_WR(BLE_DFCNTL1_1US_ADDR, (REG_BLE_RD(BLE_DFCNTL1_1US_ADDR) & ~((uint32_t)0xFF000000)) | ((uint32_t)rxsampstinst11us << 24)); +} + +__INLINE uint8_t ble_dfcntl1_1us_rxswstinst1_1us_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DFCNTL1_1US_ADDR); + return ((localVal & ((uint32_t)0x00FF0000)) >> 16); +} + +__INLINE void ble_dfcntl1_1us_rxswstinst1_1us_setf(uint8_t rxswstinst11us) +{ + BLE_ASSERT_ERR((((uint32_t)rxswstinst11us << 16) & ~((uint32_t)0x00FF0000)) == 0); + REG_BLE_WR(BLE_DFCNTL1_1US_ADDR, (REG_BLE_RD(BLE_DFCNTL1_1US_ADDR) & ~((uint32_t)0x00FF0000)) | ((uint32_t)rxswstinst11us << 16)); +} + +__INLINE uint8_t ble_dfcntl1_1us_txswstinst1_1us_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DFCNTL1_1US_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +__INLINE void ble_dfcntl1_1us_txswstinst1_1us_setf(uint8_t txswstinst11us) +{ + BLE_ASSERT_ERR((((uint32_t)txswstinst11us << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_BLE_WR(BLE_DFCNTL1_1US_ADDR, (REG_BLE_RD(BLE_DFCNTL1_1US_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)txswstinst11us << 0)); +} + +/** + * @brief DFCNTL1_2US register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:24    RXSAMPSTINST1_2US   0x0
+ *  23:16      RXSWSTINST1_2US   0x0
+ *  07:00      TXSWSTINST1_2US   0x0
+ * 
+ */ +#define BLE_DFCNTL1_2US_ADDR 0x0090097C +#define BLE_DFCNTL1_2US_OFFSET 0x0000017C +#define BLE_DFCNTL1_2US_INDEX 0x0000005F +#define BLE_DFCNTL1_2US_RESET 0x00000000 + +__INLINE uint32_t ble_dfcntl1_2us_get(void) +{ + return REG_BLE_RD(BLE_DFCNTL1_2US_ADDR); +} + +__INLINE void ble_dfcntl1_2us_set(uint32_t value) +{ + REG_BLE_WR(BLE_DFCNTL1_2US_ADDR, value); +} + +// field definitions +#define BLE_RXSAMPSTINST1_2US_MASK ((uint32_t)0xFF000000) +#define BLE_RXSAMPSTINST1_2US_LSB 24 +#define BLE_RXSAMPSTINST1_2US_WIDTH ((uint32_t)0x00000008) +#define BLE_RXSWSTINST1_2US_MASK ((uint32_t)0x00FF0000) +#define BLE_RXSWSTINST1_2US_LSB 16 +#define BLE_RXSWSTINST1_2US_WIDTH ((uint32_t)0x00000008) +#define BLE_TXSWSTINST1_2US_MASK ((uint32_t)0x000000FF) +#define BLE_TXSWSTINST1_2US_LSB 0 +#define BLE_TXSWSTINST1_2US_WIDTH ((uint32_t)0x00000008) + +#define BLE_RXSAMPSTINST1_2US_RST 0x0 +#define BLE_RXSWSTINST1_2US_RST 0x0 +#define BLE_TXSWSTINST1_2US_RST 0x0 + +__INLINE void ble_dfcntl1_2us_pack(uint8_t rxsampstinst12us, uint8_t rxswstinst12us, uint8_t txswstinst12us) +{ + BLE_ASSERT_ERR((((uint32_t)rxsampstinst12us << 24) & ~((uint32_t)0xFF000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)rxswstinst12us << 16) & ~((uint32_t)0x00FF0000)) == 0); + BLE_ASSERT_ERR((((uint32_t)txswstinst12us << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_BLE_WR(BLE_DFCNTL1_2US_ADDR, ((uint32_t)rxsampstinst12us << 24) | ((uint32_t)rxswstinst12us << 16) | ((uint32_t)txswstinst12us << 0)); +} + +__INLINE void ble_dfcntl1_2us_unpack(uint8_t* rxsampstinst12us, uint8_t* rxswstinst12us, uint8_t* txswstinst12us) +{ + uint32_t localVal = REG_BLE_RD(BLE_DFCNTL1_2US_ADDR); + + *rxsampstinst12us = (localVal & ((uint32_t)0xFF000000)) >> 24; + *rxswstinst12us = (localVal & ((uint32_t)0x00FF0000)) >> 16; + *txswstinst12us = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +__INLINE uint8_t ble_dfcntl1_2us_rxsampstinst1_2us_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DFCNTL1_2US_ADDR); + return ((localVal & ((uint32_t)0xFF000000)) >> 24); +} + +__INLINE void ble_dfcntl1_2us_rxsampstinst1_2us_setf(uint8_t rxsampstinst12us) +{ + BLE_ASSERT_ERR((((uint32_t)rxsampstinst12us << 24) & ~((uint32_t)0xFF000000)) == 0); + REG_BLE_WR(BLE_DFCNTL1_2US_ADDR, (REG_BLE_RD(BLE_DFCNTL1_2US_ADDR) & ~((uint32_t)0xFF000000)) | ((uint32_t)rxsampstinst12us << 24)); +} + +__INLINE uint8_t ble_dfcntl1_2us_rxswstinst1_2us_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DFCNTL1_2US_ADDR); + return ((localVal & ((uint32_t)0x00FF0000)) >> 16); +} + +__INLINE void ble_dfcntl1_2us_rxswstinst1_2us_setf(uint8_t rxswstinst12us) +{ + BLE_ASSERT_ERR((((uint32_t)rxswstinst12us << 16) & ~((uint32_t)0x00FF0000)) == 0); + REG_BLE_WR(BLE_DFCNTL1_2US_ADDR, (REG_BLE_RD(BLE_DFCNTL1_2US_ADDR) & ~((uint32_t)0x00FF0000)) | ((uint32_t)rxswstinst12us << 16)); +} + +__INLINE uint8_t ble_dfcntl1_2us_txswstinst1_2us_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DFCNTL1_2US_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +__INLINE void ble_dfcntl1_2us_txswstinst1_2us_setf(uint8_t txswstinst12us) +{ + BLE_ASSERT_ERR((((uint32_t)txswstinst12us << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_BLE_WR(BLE_DFCNTL1_2US_ADDR, (REG_BLE_RD(BLE_DFCNTL1_2US_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)txswstinst12us << 0)); +} + +/** + * @brief DFCURRENTPTR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  13:00         DFCURRENTPTR   0x0
+ * 
+ */ +#define BLE_DFCURRENTPTR_ADDR 0x00900980 +#define BLE_DFCURRENTPTR_OFFSET 0x00000180 +#define BLE_DFCURRENTPTR_INDEX 0x00000060 +#define BLE_DFCURRENTPTR_RESET 0x00000000 + +__INLINE uint32_t ble_dfcurrentptr_get(void) +{ + return REG_BLE_RD(BLE_DFCURRENTPTR_ADDR); +} + +__INLINE void ble_dfcurrentptr_set(uint32_t value) +{ + REG_BLE_WR(BLE_DFCURRENTPTR_ADDR, value); +} + +// field definitions +#define BLE_DFCURRENTPTR_MASK ((uint32_t)0x00003FFF) +#define BLE_DFCURRENTPTR_LSB 0 +#define BLE_DFCURRENTPTR_WIDTH ((uint32_t)0x0000000E) + +#define BLE_DFCURRENTPTR_RST 0x0 + +__INLINE uint16_t ble_dfcurrentptr_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DFCURRENTPTR_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0x00003FFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ble_dfcurrentptr_setf(uint16_t dfcurrentptr) +{ + BLE_ASSERT_ERR((((uint32_t)dfcurrentptr << 0) & ~((uint32_t)0x00003FFF)) == 0); + REG_BLE_WR(BLE_DFCURRENTPTR_ADDR, (uint32_t)dfcurrentptr << 0); +} + +/** + * @brief DFANTCNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     15       RXPRIMIDCNTLEN   0
+ *  14:08          RXPRIMANTID   0x0
+ *     07       TXPRIMIDCNTLEN   0
+ *  06:00          TXPRIMANTID   0x0
+ * 
+ */ +#define BLE_DFANTCNTL_ADDR 0x00900984 +#define BLE_DFANTCNTL_OFFSET 0x00000184 +#define BLE_DFANTCNTL_INDEX 0x00000061 +#define BLE_DFANTCNTL_RESET 0x00000000 + +__INLINE uint32_t ble_dfantcntl_get(void) +{ + return REG_BLE_RD(BLE_DFANTCNTL_ADDR); +} + +__INLINE void ble_dfantcntl_set(uint32_t value) +{ + REG_BLE_WR(BLE_DFANTCNTL_ADDR, value); +} + +// field definitions +#define BLE_RXPRIMIDCNTLEN_BIT ((uint32_t)0x00008000) +#define BLE_RXPRIMIDCNTLEN_POS 15 +#define BLE_RXPRIMANTID_MASK ((uint32_t)0x00007F00) +#define BLE_RXPRIMANTID_LSB 8 +#define BLE_RXPRIMANTID_WIDTH ((uint32_t)0x00000007) +#define BLE_TXPRIMIDCNTLEN_BIT ((uint32_t)0x00000080) +#define BLE_TXPRIMIDCNTLEN_POS 7 +#define BLE_TXPRIMANTID_MASK ((uint32_t)0x0000007F) +#define BLE_TXPRIMANTID_LSB 0 +#define BLE_TXPRIMANTID_WIDTH ((uint32_t)0x00000007) + +#define BLE_RXPRIMIDCNTLEN_RST 0x0 +#define BLE_RXPRIMANTID_RST 0x0 +#define BLE_TXPRIMIDCNTLEN_RST 0x0 +#define BLE_TXPRIMANTID_RST 0x0 + +__INLINE void ble_dfantcntl_pack(uint8_t rxprimidcntlen, uint8_t rxprimantid, uint8_t txprimidcntlen, uint8_t txprimantid) +{ + BLE_ASSERT_ERR((((uint32_t)rxprimidcntlen << 15) & ~((uint32_t)0x00008000)) == 0); + BLE_ASSERT_ERR((((uint32_t)rxprimantid << 8) & ~((uint32_t)0x00007F00)) == 0); + BLE_ASSERT_ERR((((uint32_t)txprimidcntlen << 7) & ~((uint32_t)0x00000080)) == 0); + BLE_ASSERT_ERR((((uint32_t)txprimantid << 0) & ~((uint32_t)0x0000007F)) == 0); + REG_BLE_WR(BLE_DFANTCNTL_ADDR, ((uint32_t)rxprimidcntlen << 15) | ((uint32_t)rxprimantid << 8) | ((uint32_t)txprimidcntlen << 7) | ((uint32_t)txprimantid << 0)); +} + +__INLINE void ble_dfantcntl_unpack(uint8_t* rxprimidcntlen, uint8_t* rxprimantid, uint8_t* txprimidcntlen, uint8_t* txprimantid) +{ + uint32_t localVal = REG_BLE_RD(BLE_DFANTCNTL_ADDR); + + *rxprimidcntlen = (localVal & ((uint32_t)0x00008000)) >> 15; + *rxprimantid = (localVal & ((uint32_t)0x00007F00)) >> 8; + *txprimidcntlen = (localVal & ((uint32_t)0x00000080)) >> 7; + *txprimantid = (localVal & ((uint32_t)0x0000007F)) >> 0; +} + +__INLINE uint8_t ble_dfantcntl_rxprimidcntlen_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DFANTCNTL_ADDR); + return ((localVal & ((uint32_t)0x00008000)) >> 15); +} + +__INLINE void ble_dfantcntl_rxprimidcntlen_setf(uint8_t rxprimidcntlen) +{ + BLE_ASSERT_ERR((((uint32_t)rxprimidcntlen << 15) & ~((uint32_t)0x00008000)) == 0); + REG_BLE_WR(BLE_DFANTCNTL_ADDR, (REG_BLE_RD(BLE_DFANTCNTL_ADDR) & ~((uint32_t)0x00008000)) | ((uint32_t)rxprimidcntlen << 15)); +} + +__INLINE uint8_t ble_dfantcntl_rxprimantid_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DFANTCNTL_ADDR); + return ((localVal & ((uint32_t)0x00007F00)) >> 8); +} + +__INLINE void ble_dfantcntl_rxprimantid_setf(uint8_t rxprimantid) +{ + BLE_ASSERT_ERR((((uint32_t)rxprimantid << 8) & ~((uint32_t)0x00007F00)) == 0); + REG_BLE_WR(BLE_DFANTCNTL_ADDR, (REG_BLE_RD(BLE_DFANTCNTL_ADDR) & ~((uint32_t)0x00007F00)) | ((uint32_t)rxprimantid << 8)); +} + +__INLINE uint8_t ble_dfantcntl_txprimidcntlen_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DFANTCNTL_ADDR); + return ((localVal & ((uint32_t)0x00000080)) >> 7); +} + +__INLINE void ble_dfantcntl_txprimidcntlen_setf(uint8_t txprimidcntlen) +{ + BLE_ASSERT_ERR((((uint32_t)txprimidcntlen << 7) & ~((uint32_t)0x00000080)) == 0); + REG_BLE_WR(BLE_DFANTCNTL_ADDR, (REG_BLE_RD(BLE_DFANTCNTL_ADDR) & ~((uint32_t)0x00000080)) | ((uint32_t)txprimidcntlen << 7)); +} + +__INLINE uint8_t ble_dfantcntl_txprimantid_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DFANTCNTL_ADDR); + return ((localVal & ((uint32_t)0x0000007F)) >> 0); +} + +__INLINE void ble_dfantcntl_txprimantid_setf(uint8_t txprimantid) +{ + BLE_ASSERT_ERR((((uint32_t)txprimantid << 0) & ~((uint32_t)0x0000007F)) == 0); + REG_BLE_WR(BLE_DFANTCNTL_ADDR, (REG_BLE_RD(BLE_DFANTCNTL_ADDR) & ~((uint32_t)0x0000007F)) | ((uint32_t)txprimantid << 0)); +} + +/** + * @brief DFIFCNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     07        ANTSWITCH_BEH   0
+ *     06          SAMPREQ_BEH   0
+ *  05:04        SAMPVALID_BEH   0x0
+ *  03:02             IF_WIDTH   0x3
+ *     01        MSB_LSB_ORDER   0
+ *     00         SYMBOL_ORDER   0
+ * 
+ */ +#define BLE_DFIFCNTL_ADDR 0x00900988 +#define BLE_DFIFCNTL_OFFSET 0x00000188 +#define BLE_DFIFCNTL_INDEX 0x00000062 +#define BLE_DFIFCNTL_RESET 0x0000000C + +__INLINE uint32_t ble_dfifcntl_get(void) +{ + return REG_BLE_RD(BLE_DFIFCNTL_ADDR); +} + +__INLINE void ble_dfifcntl_set(uint32_t value) +{ + REG_BLE_WR(BLE_DFIFCNTL_ADDR, value); +} + +// field definitions +#define BLE_ANTSWITCH_BEH_BIT ((uint32_t)0x00000080) +#define BLE_ANTSWITCH_BEH_POS 7 +#define BLE_SAMPREQ_BEH_BIT ((uint32_t)0x00000040) +#define BLE_SAMPREQ_BEH_POS 6 +#define BLE_SAMPVALID_BEH_MASK ((uint32_t)0x00000030) +#define BLE_SAMPVALID_BEH_LSB 4 +#define BLE_SAMPVALID_BEH_WIDTH ((uint32_t)0x00000002) +#define BLE_IF_WIDTH_MASK ((uint32_t)0x0000000C) +#define BLE_IF_WIDTH_LSB 2 +#define BLE_IF_WIDTH_WIDTH ((uint32_t)0x00000002) +#define BLE_MSB_LSB_ORDER_BIT ((uint32_t)0x00000002) +#define BLE_MSB_LSB_ORDER_POS 1 +#define BLE_SYMBOL_ORDER_BIT ((uint32_t)0x00000001) +#define BLE_SYMBOL_ORDER_POS 0 + +#define BLE_ANTSWITCH_BEH_RST 0x0 +#define BLE_SAMPREQ_BEH_RST 0x0 +#define BLE_SAMPVALID_BEH_RST 0x0 +#define BLE_IF_WIDTH_RST 0x3 +#define BLE_MSB_LSB_ORDER_RST 0x0 +#define BLE_SYMBOL_ORDER_RST 0x0 + +__INLINE void ble_dfifcntl_pack(uint8_t antswitchbeh, uint8_t sampreqbeh, uint8_t sampvalidbeh, uint8_t ifwidth, uint8_t msblsborder, uint8_t symbolorder) +{ + BLE_ASSERT_ERR((((uint32_t)antswitchbeh << 7) & ~((uint32_t)0x00000080)) == 0); + BLE_ASSERT_ERR((((uint32_t)sampreqbeh << 6) & ~((uint32_t)0x00000040)) == 0); + BLE_ASSERT_ERR((((uint32_t)sampvalidbeh << 4) & ~((uint32_t)0x00000030)) == 0); + BLE_ASSERT_ERR((((uint32_t)ifwidth << 2) & ~((uint32_t)0x0000000C)) == 0); + BLE_ASSERT_ERR((((uint32_t)msblsborder << 1) & ~((uint32_t)0x00000002)) == 0); + BLE_ASSERT_ERR((((uint32_t)symbolorder << 0) & ~((uint32_t)0x00000001)) == 0); + REG_BLE_WR(BLE_DFIFCNTL_ADDR, ((uint32_t)antswitchbeh << 7) | ((uint32_t)sampreqbeh << 6) | ((uint32_t)sampvalidbeh << 4) | ((uint32_t)ifwidth << 2) | ((uint32_t)msblsborder << 1) | ((uint32_t)symbolorder << 0)); +} + +__INLINE void ble_dfifcntl_unpack(uint8_t* antswitchbeh, uint8_t* sampreqbeh, uint8_t* sampvalidbeh, uint8_t* ifwidth, uint8_t* msblsborder, uint8_t* symbolorder) +{ + uint32_t localVal = REG_BLE_RD(BLE_DFIFCNTL_ADDR); + + *antswitchbeh = (localVal & ((uint32_t)0x00000080)) >> 7; + *sampreqbeh = (localVal & ((uint32_t)0x00000040)) >> 6; + *sampvalidbeh = (localVal & ((uint32_t)0x00000030)) >> 4; + *ifwidth = (localVal & ((uint32_t)0x0000000C)) >> 2; + *msblsborder = (localVal & ((uint32_t)0x00000002)) >> 1; + *symbolorder = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +__INLINE uint8_t ble_dfifcntl_antswitch_beh_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DFIFCNTL_ADDR); + return ((localVal & ((uint32_t)0x00000080)) >> 7); +} + +__INLINE void ble_dfifcntl_antswitch_beh_setf(uint8_t antswitchbeh) +{ + BLE_ASSERT_ERR((((uint32_t)antswitchbeh << 7) & ~((uint32_t)0x00000080)) == 0); + REG_BLE_WR(BLE_DFIFCNTL_ADDR, (REG_BLE_RD(BLE_DFIFCNTL_ADDR) & ~((uint32_t)0x00000080)) | ((uint32_t)antswitchbeh << 7)); +} + +__INLINE uint8_t ble_dfifcntl_sampreq_beh_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DFIFCNTL_ADDR); + return ((localVal & ((uint32_t)0x00000040)) >> 6); +} + +__INLINE void ble_dfifcntl_sampreq_beh_setf(uint8_t sampreqbeh) +{ + BLE_ASSERT_ERR((((uint32_t)sampreqbeh << 6) & ~((uint32_t)0x00000040)) == 0); + REG_BLE_WR(BLE_DFIFCNTL_ADDR, (REG_BLE_RD(BLE_DFIFCNTL_ADDR) & ~((uint32_t)0x00000040)) | ((uint32_t)sampreqbeh << 6)); +} + +__INLINE uint8_t ble_dfifcntl_sampvalid_beh_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DFIFCNTL_ADDR); + return ((localVal & ((uint32_t)0x00000030)) >> 4); +} + +__INLINE void ble_dfifcntl_sampvalid_beh_setf(uint8_t sampvalidbeh) +{ + BLE_ASSERT_ERR((((uint32_t)sampvalidbeh << 4) & ~((uint32_t)0x00000030)) == 0); + REG_BLE_WR(BLE_DFIFCNTL_ADDR, (REG_BLE_RD(BLE_DFIFCNTL_ADDR) & ~((uint32_t)0x00000030)) | ((uint32_t)sampvalidbeh << 4)); +} + +__INLINE uint8_t ble_dfifcntl_if_width_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DFIFCNTL_ADDR); + return ((localVal & ((uint32_t)0x0000000C)) >> 2); +} + +__INLINE void ble_dfifcntl_if_width_setf(uint8_t ifwidth) +{ + BLE_ASSERT_ERR((((uint32_t)ifwidth << 2) & ~((uint32_t)0x0000000C)) == 0); + REG_BLE_WR(BLE_DFIFCNTL_ADDR, (REG_BLE_RD(BLE_DFIFCNTL_ADDR) & ~((uint32_t)0x0000000C)) | ((uint32_t)ifwidth << 2)); +} + +__INLINE uint8_t ble_dfifcntl_msb_lsb_order_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DFIFCNTL_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +__INLINE void ble_dfifcntl_msb_lsb_order_setf(uint8_t msblsborder) +{ + BLE_ASSERT_ERR((((uint32_t)msblsborder << 1) & ~((uint32_t)0x00000002)) == 0); + REG_BLE_WR(BLE_DFIFCNTL_ADDR, (REG_BLE_RD(BLE_DFIFCNTL_ADDR) & ~((uint32_t)0x00000002)) | ((uint32_t)msblsborder << 1)); +} + +__INLINE uint8_t ble_dfifcntl_symbol_order_getf(void) +{ + uint32_t localVal = REG_BLE_RD(BLE_DFIFCNTL_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +__INLINE void ble_dfifcntl_symbol_order_setf(uint8_t symbolorder) +{ + BLE_ASSERT_ERR((((uint32_t)symbolorder << 0) & ~((uint32_t)0x00000001)) == 0); + REG_BLE_WR(BLE_DFIFCNTL_ADDR, (REG_BLE_RD(BLE_DFIFCNTL_ADDR) & ~((uint32_t)0x00000001)) | ((uint32_t)symbolorder << 0)); +} + + +#endif // _REG_BLECORE_H_ + diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_em_ble_cs.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_em_ble_cs.h new file mode 100755 index 0000000..40a8667 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_em_ble_cs.h @@ -0,0 +1,3783 @@ +#ifndef _REG_EM_BLE_CS_H_ +#define _REG_EM_BLE_CS_H_ + +#include +#include "_reg_em_ble_cs.h" +#include "compiler.h" +#include "architect.h" +#include "em_map.h" +#include "ble_reg_access.h" + +#define REG_EM_BLE_CS_COUNT 56 + +#define REG_EM_BLE_CS_DECODING_MASK 0x0000007F + +#define REG_EM_BLE_CS_ADDR_GET(idx) (EM_BLE_CS_OFFSET + (idx) * REG_EM_BLE_CS_SIZE) + +/** + * @brief CNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     10             TXBSY_EN   0
+ *     09             RXBSY_EN   0
+ *     08              DNABORT   0
+ *  04:00               FORMAT   0x0
+ * 
+ */ +#define EM_BLE_CNTL_ADDR (0x00910000 + EM_BLE_CS_OFFSET) +#define EM_BLE_CNTL_INDEX 0x00000000 +#define EM_BLE_CNTL_RESET 0x00000000 + +__INLINE uint16_t em_ble_cntl_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_CNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +__INLINE void em_ble_cntl_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_CNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, value); +} + +// field definitions +#define EM_BLE_TXBSY_EN_BIT ((uint16_t)0x00000400) +#define EM_BLE_TXBSY_EN_POS 10 +#define EM_BLE_RXBSY_EN_BIT ((uint16_t)0x00000200) +#define EM_BLE_RXBSY_EN_POS 9 +#define EM_BLE_DNABORT_BIT ((uint16_t)0x00000100) +#define EM_BLE_DNABORT_POS 8 +#define EM_BLE_FORMAT_MASK ((uint16_t)0x0000001F) +#define EM_BLE_FORMAT_LSB 0 +#define EM_BLE_FORMAT_WIDTH ((uint16_t)0x00000005) + +#define EM_BLE_TXBSY_EN_RST 0x0 +#define EM_BLE_RXBSY_EN_RST 0x0 +#define EM_BLE_DNABORT_RST 0x0 +#define EM_BLE_FORMAT_RST 0x0 + +__INLINE void em_ble_cntl_pack(int elt_idx, uint8_t txbsyen, uint8_t rxbsyen, uint8_t dnabort, uint8_t format) +{ + BLE_ASSERT_ERR((((uint16_t)txbsyen << 10) & ~((uint16_t)0x00000400)) == 0); + BLE_ASSERT_ERR((((uint16_t)rxbsyen << 9) & ~((uint16_t)0x00000200)) == 0); + BLE_ASSERT_ERR((((uint16_t)dnabort << 8) & ~((uint16_t)0x00000100)) == 0); + BLE_ASSERT_ERR((((uint16_t)format << 0) & ~((uint16_t)0x0000001F)) == 0); + EM_BLE_WR(EM_BLE_CNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, ((uint16_t)txbsyen << 10) | ((uint16_t)rxbsyen << 9) | ((uint16_t)dnabort << 8) | ((uint16_t)format << 0)); +} + +__INLINE void em_ble_cntl_unpack(int elt_idx, uint8_t* txbsyen, uint8_t* rxbsyen, uint8_t* dnabort, uint8_t* format) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_CNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + + *txbsyen = (localVal & ((uint16_t)0x00000400)) >> 10; + *rxbsyen = (localVal & ((uint16_t)0x00000200)) >> 9; + *dnabort = (localVal & ((uint16_t)0x00000100)) >> 8; + *format = (localVal & ((uint16_t)0x0000001F)) >> 0; +} + +__INLINE uint8_t em_ble_cntl_txbsy_en_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_CNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00000400)) >> 10); +} + +__INLINE void em_ble_cntl_txbsy_en_setf(int elt_idx, uint8_t txbsyen) +{ + BLE_ASSERT_ERR((((uint16_t)txbsyen << 10) & ~((uint16_t)0x00000400)) == 0); + EM_BLE_WR(EM_BLE_CNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_CNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00000400)) | ((uint16_t)txbsyen << 10)); +} + +__INLINE uint8_t em_ble_cntl_rxbsy_en_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_CNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00000200)) >> 9); +} + +__INLINE void em_ble_cntl_rxbsy_en_setf(int elt_idx, uint8_t rxbsyen) +{ + BLE_ASSERT_ERR((((uint16_t)rxbsyen << 9) & ~((uint16_t)0x00000200)) == 0); + EM_BLE_WR(EM_BLE_CNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_CNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00000200)) | ((uint16_t)rxbsyen << 9)); +} + +__INLINE uint8_t em_ble_cntl_dnabort_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_CNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00000100)) >> 8); +} + +__INLINE void em_ble_cntl_dnabort_setf(int elt_idx, uint8_t dnabort) +{ + BLE_ASSERT_ERR((((uint16_t)dnabort << 8) & ~((uint16_t)0x00000100)) == 0); + EM_BLE_WR(EM_BLE_CNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_CNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00000100)) | ((uint16_t)dnabort << 8)); +} + +__INLINE uint8_t em_ble_cntl_format_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_CNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x0000001F)) >> 0); +} + +__INLINE void em_ble_cntl_format_setf(int elt_idx, uint8_t format) +{ + BLE_ASSERT_ERR((((uint16_t)format << 0) & ~((uint16_t)0x0000001F)) == 0); + EM_BLE_WR(EM_BLE_CNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_CNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x0000001F)) | ((uint16_t)format << 0)); +} + +/** + * @brief LINKCNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  12:08              LINKLBL   0x0
+ *     06                  SAS   0
+ *     05        NULLRXLLIDFLT   0
+ *     04             MIC_MODE   0
+ *     03           CRYPT_MODE   0
+ *     02           TXCRYPT_EN   0
+ *     01           RXCRYPT_EN   0
+ *     00            PRIV_NPUB   0
+ * 
+ */ +#define EM_BLE_LINKCNTL_ADDR (0x00910002 + EM_BLE_CS_OFFSET) +#define EM_BLE_LINKCNTL_INDEX 0x00000001 +#define EM_BLE_LINKCNTL_RESET 0x00000000 + +__INLINE uint16_t em_ble_linkcntl_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_LINKCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +__INLINE void em_ble_linkcntl_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_LINKCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, value); +} + +// field definitions +#define EM_BLE_LINKLBL_MASK ((uint16_t)0x00001F00) +#define EM_BLE_LINKLBL_LSB 8 +#define EM_BLE_LINKLBL_WIDTH ((uint16_t)0x00000005) +#define EM_BLE_SAS_BIT ((uint16_t)0x00000040) +#define EM_BLE_SAS_POS 6 +#define EM_BLE_NULLRXLLIDFLT_BIT ((uint16_t)0x00000020) +#define EM_BLE_NULLRXLLIDFLT_POS 5 +#define EM_BLE_MIC_MODE_BIT ((uint16_t)0x00000010) +#define EM_BLE_MIC_MODE_POS 4 +#define EM_BLE_CRYPT_MODE_BIT ((uint16_t)0x00000008) +#define EM_BLE_CRYPT_MODE_POS 3 +#define EM_BLE_TXCRYPT_EN_BIT ((uint16_t)0x00000004) +#define EM_BLE_TXCRYPT_EN_POS 2 +#define EM_BLE_RXCRYPT_EN_BIT ((uint16_t)0x00000002) +#define EM_BLE_RXCRYPT_EN_POS 1 +#define EM_BLE_PRIV_NPUB_BIT ((uint16_t)0x00000001) +#define EM_BLE_PRIV_NPUB_POS 0 + +#define EM_BLE_LINKLBL_RST 0x0 +#define EM_BLE_SAS_RST 0x0 +#define EM_BLE_NULLRXLLIDFLT_RST 0x0 +#define EM_BLE_MIC_MODE_RST 0x0 +#define EM_BLE_CRYPT_MODE_RST 0x0 +#define EM_BLE_TXCRYPT_EN_RST 0x0 +#define EM_BLE_RXCRYPT_EN_RST 0x0 +#define EM_BLE_PRIV_NPUB_RST 0x0 + +__INLINE void em_ble_linkcntl_pack(int elt_idx, uint8_t linklbl, uint8_t sas, uint8_t nullrxllidflt, uint8_t micmode, uint8_t cryptmode, uint8_t txcrypten, uint8_t rxcrypten, uint8_t privnpub) +{ + BLE_ASSERT_ERR((((uint16_t)linklbl << 8) & ~((uint16_t)0x00001F00)) == 0); + BLE_ASSERT_ERR((((uint16_t)sas << 6) & ~((uint16_t)0x00000040)) == 0); + BLE_ASSERT_ERR((((uint16_t)nullrxllidflt << 5) & ~((uint16_t)0x00000020)) == 0); + BLE_ASSERT_ERR((((uint16_t)micmode << 4) & ~((uint16_t)0x00000010)) == 0); + BLE_ASSERT_ERR((((uint16_t)cryptmode << 3) & ~((uint16_t)0x00000008)) == 0); + BLE_ASSERT_ERR((((uint16_t)txcrypten << 2) & ~((uint16_t)0x00000004)) == 0); + BLE_ASSERT_ERR((((uint16_t)rxcrypten << 1) & ~((uint16_t)0x00000002)) == 0); + BLE_ASSERT_ERR((((uint16_t)privnpub << 0) & ~((uint16_t)0x00000001)) == 0); + EM_BLE_WR(EM_BLE_LINKCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, ((uint16_t)linklbl << 8) | ((uint16_t)sas << 6) | ((uint16_t)nullrxllidflt << 5) | ((uint16_t)micmode << 4) | ((uint16_t)cryptmode << 3) | ((uint16_t)txcrypten << 2) | ((uint16_t)rxcrypten << 1) | ((uint16_t)privnpub << 0)); +} + +__INLINE void em_ble_linkcntl_unpack(int elt_idx, uint8_t* linklbl, uint8_t* sas, uint8_t* nullrxllidflt, uint8_t* micmode, uint8_t* cryptmode, uint8_t* txcrypten, uint8_t* rxcrypten, uint8_t* privnpub) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_LINKCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + + *linklbl = (localVal & ((uint16_t)0x00001F00)) >> 8; + *sas = (localVal & ((uint16_t)0x00000040)) >> 6; + *nullrxllidflt = (localVal & ((uint16_t)0x00000020)) >> 5; + *micmode = (localVal & ((uint16_t)0x00000010)) >> 4; + *cryptmode = (localVal & ((uint16_t)0x00000008)) >> 3; + *txcrypten = (localVal & ((uint16_t)0x00000004)) >> 2; + *rxcrypten = (localVal & ((uint16_t)0x00000002)) >> 1; + *privnpub = (localVal & ((uint16_t)0x00000001)) >> 0; +} + +__INLINE uint8_t em_ble_linkcntl_linklbl_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_LINKCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00001F00)) >> 8); +} + +__INLINE void em_ble_linkcntl_linklbl_setf(int elt_idx, uint8_t linklbl) +{ + BLE_ASSERT_ERR((((uint16_t)linklbl << 8) & ~((uint16_t)0x00001F00)) == 0); + EM_BLE_WR(EM_BLE_LINKCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_LINKCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00001F00)) | ((uint16_t)linklbl << 8)); +} + +__INLINE uint8_t em_ble_linkcntl_sas_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_LINKCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00000040)) >> 6); +} + +__INLINE void em_ble_linkcntl_sas_setf(int elt_idx, uint8_t sas) +{ + BLE_ASSERT_ERR((((uint16_t)sas << 6) & ~((uint16_t)0x00000040)) == 0); + EM_BLE_WR(EM_BLE_LINKCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_LINKCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00000040)) | ((uint16_t)sas << 6)); +} + +__INLINE uint8_t em_ble_linkcntl_nullrxllidflt_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_LINKCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00000020)) >> 5); +} + +__INLINE void em_ble_linkcntl_nullrxllidflt_setf(int elt_idx, uint8_t nullrxllidflt) +{ + BLE_ASSERT_ERR((((uint16_t)nullrxllidflt << 5) & ~((uint16_t)0x00000020)) == 0); + EM_BLE_WR(EM_BLE_LINKCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_LINKCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00000020)) | ((uint16_t)nullrxllidflt << 5)); +} + +__INLINE uint8_t em_ble_linkcntl_mic_mode_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_LINKCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00000010)) >> 4); +} + +__INLINE void em_ble_linkcntl_mic_mode_setf(int elt_idx, uint8_t micmode) +{ + BLE_ASSERT_ERR((((uint16_t)micmode << 4) & ~((uint16_t)0x00000010)) == 0); + EM_BLE_WR(EM_BLE_LINKCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_LINKCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00000010)) | ((uint16_t)micmode << 4)); +} + +__INLINE uint8_t em_ble_linkcntl_crypt_mode_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_LINKCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00000008)) >> 3); +} + +__INLINE void em_ble_linkcntl_crypt_mode_setf(int elt_idx, uint8_t cryptmode) +{ + BLE_ASSERT_ERR((((uint16_t)cryptmode << 3) & ~((uint16_t)0x00000008)) == 0); + EM_BLE_WR(EM_BLE_LINKCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_LINKCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00000008)) | ((uint16_t)cryptmode << 3)); +} + +__INLINE uint8_t em_ble_linkcntl_txcrypt_en_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_LINKCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00000004)) >> 2); +} + +__INLINE void em_ble_linkcntl_txcrypt_en_setf(int elt_idx, uint8_t txcrypten) +{ + BLE_ASSERT_ERR((((uint16_t)txcrypten << 2) & ~((uint16_t)0x00000004)) == 0); + EM_BLE_WR(EM_BLE_LINKCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_LINKCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00000004)) | ((uint16_t)txcrypten << 2)); +} + +__INLINE uint8_t em_ble_linkcntl_rxcrypt_en_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_LINKCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00000002)) >> 1); +} + +__INLINE void em_ble_linkcntl_rxcrypt_en_setf(int elt_idx, uint8_t rxcrypten) +{ + BLE_ASSERT_ERR((((uint16_t)rxcrypten << 1) & ~((uint16_t)0x00000002)) == 0); + EM_BLE_WR(EM_BLE_LINKCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_LINKCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00000002)) | ((uint16_t)rxcrypten << 1)); +} + +__INLINE uint8_t em_ble_linkcntl_priv_npub_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_LINKCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00000001)) >> 0); +} + +__INLINE void em_ble_linkcntl_priv_npub_setf(int elt_idx, uint8_t privnpub) +{ + BLE_ASSERT_ERR((((uint16_t)privnpub << 0) & ~((uint16_t)0x00000001)) == 0); + EM_BLE_WR(EM_BLE_LINKCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_LINKCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00000001)) | ((uint16_t)privnpub << 0)); +} + +/** + * @brief ISOLINKCNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:11           STREAM_LBL   0x0
+ *  10:08            GROUP_LBL   0x0
+ *     03          ISOSYNCMODE   0
+ *     02            ISOSYNCEN   0
+ *  01:00              ISOTYPE   0x0
+ * 
+ */ +#define EM_BLE_ISOLINKCNTL_ADDR (0x00910004 + EM_BLE_CS_OFFSET) +#define EM_BLE_ISOLINKCNTL_INDEX 0x00000002 +#define EM_BLE_ISOLINKCNTL_RESET 0x00000000 + +__INLINE uint16_t em_ble_isolinkcntl_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_ISOLINKCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +__INLINE void em_ble_isolinkcntl_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_ISOLINKCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, value); +} + +// field definitions +#define EM_BLE_STREAM_LBL_MASK ((uint16_t)0x0000F800) +#define EM_BLE_STREAM_LBL_LSB 11 +#define EM_BLE_STREAM_LBL_WIDTH ((uint16_t)0x00000005) +#define EM_BLE_GROUP_LBL_MASK ((uint16_t)0x00000700) +#define EM_BLE_GROUP_LBL_LSB 8 +#define EM_BLE_GROUP_LBL_WIDTH ((uint16_t)0x00000003) +#define EM_BLE_ISOSYNCMODE_BIT ((uint16_t)0x00000008) +#define EM_BLE_ISOSYNCMODE_POS 3 +#define EM_BLE_ISOSYNCEN_BIT ((uint16_t)0x00000004) +#define EM_BLE_ISOSYNCEN_POS 2 +#define EM_BLE_ISOTYPE_MASK ((uint16_t)0x00000003) +#define EM_BLE_ISOTYPE_LSB 0 +#define EM_BLE_ISOTYPE_WIDTH ((uint16_t)0x00000002) + +#define EM_BLE_STREAM_LBL_RST 0x0 +#define EM_BLE_GROUP_LBL_RST 0x0 +#define EM_BLE_ISOSYNCMODE_RST 0x0 +#define EM_BLE_ISOSYNCEN_RST 0x0 +#define EM_BLE_ISOTYPE_RST 0x0 + +__INLINE void em_ble_isolinkcntl_pack(int elt_idx, uint8_t streamlbl, uint8_t grouplbl, uint8_t isosyncmode, uint8_t isosyncen, uint8_t isotype) +{ + BLE_ASSERT_ERR((((uint16_t)streamlbl << 11) & ~((uint16_t)0x0000F800)) == 0); + BLE_ASSERT_ERR((((uint16_t)grouplbl << 8) & ~((uint16_t)0x00000700)) == 0); + BLE_ASSERT_ERR((((uint16_t)isosyncmode << 3) & ~((uint16_t)0x00000008)) == 0); + BLE_ASSERT_ERR((((uint16_t)isosyncen << 2) & ~((uint16_t)0x00000004)) == 0); + BLE_ASSERT_ERR((((uint16_t)isotype << 0) & ~((uint16_t)0x00000003)) == 0); + EM_BLE_WR(EM_BLE_ISOLINKCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, ((uint16_t)streamlbl << 11) | ((uint16_t)grouplbl << 8) | ((uint16_t)isosyncmode << 3) | ((uint16_t)isosyncen << 2) | ((uint16_t)isotype << 0)); +} + +__INLINE void em_ble_isolinkcntl_unpack(int elt_idx, uint8_t* streamlbl, uint8_t* grouplbl, uint8_t* isosyncmode, uint8_t* isosyncen, uint8_t* isotype) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_ISOLINKCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + + *streamlbl = (localVal & ((uint16_t)0x0000F800)) >> 11; + *grouplbl = (localVal & ((uint16_t)0x00000700)) >> 8; + *isosyncmode = (localVal & ((uint16_t)0x00000008)) >> 3; + *isosyncen = (localVal & ((uint16_t)0x00000004)) >> 2; + *isotype = (localVal & ((uint16_t)0x00000003)) >> 0; +} + +__INLINE uint8_t em_ble_isolinkcntl_stream_lbl_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_ISOLINKCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x0000F800)) >> 11); +} + +__INLINE void em_ble_isolinkcntl_stream_lbl_setf(int elt_idx, uint8_t streamlbl) +{ + BLE_ASSERT_ERR((((uint16_t)streamlbl << 11) & ~((uint16_t)0x0000F800)) == 0); + EM_BLE_WR(EM_BLE_ISOLINKCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_ISOLINKCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x0000F800)) | ((uint16_t)streamlbl << 11)); +} + +__INLINE uint8_t em_ble_isolinkcntl_group_lbl_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_ISOLINKCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00000700)) >> 8); +} + +__INLINE void em_ble_isolinkcntl_group_lbl_setf(int elt_idx, uint8_t grouplbl) +{ + BLE_ASSERT_ERR((((uint16_t)grouplbl << 8) & ~((uint16_t)0x00000700)) == 0); + EM_BLE_WR(EM_BLE_ISOLINKCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_ISOLINKCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00000700)) | ((uint16_t)grouplbl << 8)); +} + +__INLINE uint8_t em_ble_isolinkcntl_isosyncmode_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_ISOLINKCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00000008)) >> 3); +} + +__INLINE void em_ble_isolinkcntl_isosyncmode_setf(int elt_idx, uint8_t isosyncmode) +{ + BLE_ASSERT_ERR((((uint16_t)isosyncmode << 3) & ~((uint16_t)0x00000008)) == 0); + EM_BLE_WR(EM_BLE_ISOLINKCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_ISOLINKCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00000008)) | ((uint16_t)isosyncmode << 3)); +} + +__INLINE uint8_t em_ble_isolinkcntl_isosyncen_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_ISOLINKCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00000004)) >> 2); +} + +__INLINE void em_ble_isolinkcntl_isosyncen_setf(int elt_idx, uint8_t isosyncen) +{ + BLE_ASSERT_ERR((((uint16_t)isosyncen << 2) & ~((uint16_t)0x00000004)) == 0); + EM_BLE_WR(EM_BLE_ISOLINKCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_ISOLINKCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00000004)) | ((uint16_t)isosyncen << 2)); +} + +__INLINE uint8_t em_ble_isolinkcntl_isotype_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_ISOLINKCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00000003)) >> 0); +} + +__INLINE void em_ble_isolinkcntl_isotype_setf(int elt_idx, uint8_t isotype) +{ + BLE_ASSERT_ERR((((uint16_t)isotype << 0) & ~((uint16_t)0x00000003)) == 0); + EM_BLE_WR(EM_BLE_ISOLINKCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_ISOLINKCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00000003)) | ((uint16_t)isotype << 0)); +} + +/** + * @brief THRCNTL_RATECNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:12                RXTHR   0x0
+ *  11:08                TXTHR   0x0
+ *  05:04             AUX_RATE   0x0
+ *  03:02               RXRATE   0x0
+ *  01:00               TXRATE   0x0
+ * 
+ */ +#define EM_BLE_THRCNTL_RATECNTL_ADDR (0x00910006 + EM_BLE_CS_OFFSET) +#define EM_BLE_THRCNTL_RATECNTL_INDEX 0x00000003 +#define EM_BLE_THRCNTL_RATECNTL_RESET 0x00000000 + +__INLINE uint16_t em_ble_thrcntl_ratecntl_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_THRCNTL_RATECNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +__INLINE void em_ble_thrcntl_ratecntl_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_THRCNTL_RATECNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, value); +} + +// field definitions +#define EM_BLE_RXTHR_MASK ((uint16_t)0x0000F000) +#define EM_BLE_RXTHR_LSB 12 +#define EM_BLE_RXTHR_WIDTH ((uint16_t)0x00000004) +#define EM_BLE_TXTHR_MASK ((uint16_t)0x00000F00) +#define EM_BLE_TXTHR_LSB 8 +#define EM_BLE_TXTHR_WIDTH ((uint16_t)0x00000004) +#define EM_BLE_AUX_RATE_MASK ((uint16_t)0x00000030) +#define EM_BLE_AUX_RATE_LSB 4 +#define EM_BLE_AUX_RATE_WIDTH ((uint16_t)0x00000002) +#define EM_BLE_RXRATE_MASK ((uint16_t)0x0000000C) +#define EM_BLE_RXRATE_LSB 2 +#define EM_BLE_RXRATE_WIDTH ((uint16_t)0x00000002) +#define EM_BLE_TXRATE_MASK ((uint16_t)0x00000003) +#define EM_BLE_TXRATE_LSB 0 +#define EM_BLE_TXRATE_WIDTH ((uint16_t)0x00000002) + +#define EM_BLE_RXTHR_RST 0x0 +#define EM_BLE_TXTHR_RST 0x0 +#define EM_BLE_AUX_RATE_RST 0x0 +#define EM_BLE_RXRATE_RST 0x0 +#define EM_BLE_TXRATE_RST 0x0 + +__INLINE void em_ble_thrcntl_ratecntl_pack(int elt_idx, uint8_t rxthr, uint8_t txthr, uint8_t auxrate, uint8_t rxrate, uint8_t txrate) +{ + BLE_ASSERT_ERR((((uint16_t)rxthr << 12) & ~((uint16_t)0x0000F000)) == 0); + BLE_ASSERT_ERR((((uint16_t)txthr << 8) & ~((uint16_t)0x00000F00)) == 0); + BLE_ASSERT_ERR((((uint16_t)auxrate << 4) & ~((uint16_t)0x00000030)) == 0); + BLE_ASSERT_ERR((((uint16_t)rxrate << 2) & ~((uint16_t)0x0000000C)) == 0); + BLE_ASSERT_ERR((((uint16_t)txrate << 0) & ~((uint16_t)0x00000003)) == 0); + EM_BLE_WR(EM_BLE_THRCNTL_RATECNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, ((uint16_t)rxthr << 12) | ((uint16_t)txthr << 8) | ((uint16_t)auxrate << 4) | ((uint16_t)rxrate << 2) | ((uint16_t)txrate << 0)); +} + +__INLINE void em_ble_thrcntl_ratecntl_unpack(int elt_idx, uint8_t* rxthr, uint8_t* txthr, uint8_t* auxrate, uint8_t* rxrate, uint8_t* txrate) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_THRCNTL_RATECNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + + *rxthr = (localVal & ((uint16_t)0x0000F000)) >> 12; + *txthr = (localVal & ((uint16_t)0x00000F00)) >> 8; + *auxrate = (localVal & ((uint16_t)0x00000030)) >> 4; + *rxrate = (localVal & ((uint16_t)0x0000000C)) >> 2; + *txrate = (localVal & ((uint16_t)0x00000003)) >> 0; +} + +__INLINE uint8_t em_ble_thrcntl_ratecntl_rxthr_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_THRCNTL_RATECNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x0000F000)) >> 12); +} + +__INLINE void em_ble_thrcntl_ratecntl_rxthr_setf(int elt_idx, uint8_t rxthr) +{ + BLE_ASSERT_ERR((((uint16_t)rxthr << 12) & ~((uint16_t)0x0000F000)) == 0); + EM_BLE_WR(EM_BLE_THRCNTL_RATECNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_THRCNTL_RATECNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x0000F000)) | ((uint16_t)rxthr << 12)); +} + +__INLINE uint8_t em_ble_thrcntl_ratecntl_txthr_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_THRCNTL_RATECNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00000F00)) >> 8); +} + +__INLINE void em_ble_thrcntl_ratecntl_txthr_setf(int elt_idx, uint8_t txthr) +{ + BLE_ASSERT_ERR((((uint16_t)txthr << 8) & ~((uint16_t)0x00000F00)) == 0); + EM_BLE_WR(EM_BLE_THRCNTL_RATECNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_THRCNTL_RATECNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00000F00)) | ((uint16_t)txthr << 8)); +} + +__INLINE uint8_t em_ble_thrcntl_ratecntl_aux_rate_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_THRCNTL_RATECNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00000030)) >> 4); +} + +__INLINE void em_ble_thrcntl_ratecntl_aux_rate_setf(int elt_idx, uint8_t auxrate) +{ + BLE_ASSERT_ERR((((uint16_t)auxrate << 4) & ~((uint16_t)0x00000030)) == 0); + EM_BLE_WR(EM_BLE_THRCNTL_RATECNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_THRCNTL_RATECNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00000030)) | ((uint16_t)auxrate << 4)); +} + +__INLINE uint8_t em_ble_thrcntl_ratecntl_rxrate_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_THRCNTL_RATECNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x0000000C)) >> 2); +} + +__INLINE void em_ble_thrcntl_ratecntl_rxrate_setf(int elt_idx, uint8_t rxrate) +{ + BLE_ASSERT_ERR((((uint16_t)rxrate << 2) & ~((uint16_t)0x0000000C)) == 0); + EM_BLE_WR(EM_BLE_THRCNTL_RATECNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_THRCNTL_RATECNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x0000000C)) | ((uint16_t)rxrate << 2)); +} + +__INLINE uint8_t em_ble_thrcntl_ratecntl_txrate_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_THRCNTL_RATECNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00000003)) >> 0); +} + +__INLINE void em_ble_thrcntl_ratecntl_txrate_setf(int elt_idx, uint8_t txrate) +{ + BLE_ASSERT_ERR((((uint16_t)txrate << 0) & ~((uint16_t)0x00000003)) == 0); + EM_BLE_WR(EM_BLE_THRCNTL_RATECNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_THRCNTL_RATECNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00000003)) | ((uint16_t)txrate << 0)); +} + +/** + * @brief LEBDADDR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00               BDADDR   0x0
+ * 
+ */ +#define EM_BLE_LEBDADDR_ADDR (0x00910008 + EM_BLE_CS_OFFSET) +#define EM_BLE_LEBDADDR_INDEX 0x00000004 +#define EM_BLE_LEBDADDR_RESET 0x00000000 +#define EM_BLE_LEBDADDR_COUNT 3 + +__INLINE uint16_t em_ble_lebdaddr_get(int elt_idx, int reg_idx) +{ + BLE_ASSERT_ERR(reg_idx <= 2); + return EM_BLE_RD(EM_BLE_LEBDADDR_ADDR + elt_idx * REG_EM_BLE_CS_SIZE + reg_idx * 2); +} + +__INLINE void em_ble_lebdaddr_set(int elt_idx, int reg_idx, uint16_t value) +{ + BLE_ASSERT_ERR(reg_idx <= 2); + EM_BLE_WR(EM_BLE_LEBDADDR_ADDR + elt_idx * REG_EM_BLE_CS_SIZE + reg_idx * 2, value); +} + +// field definitions +#define EM_BLE_BDADDR_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_BDADDR_LSB 0 +#define EM_BLE_BDADDR_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_BDADDR_RST 0x0 + +__INLINE uint16_t em_ble_lebdaddr_bdaddr_getf(int elt_idx, int reg_idx) +{ + BLE_ASSERT_ERR(reg_idx <= 2); + uint16_t localVal = EM_BLE_RD(EM_BLE_LEBDADDR_ADDR + elt_idx * REG_EM_BLE_CS_SIZE + reg_idx * 2); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_lebdaddr_bdaddr_setf(int elt_idx, int reg_idx, uint16_t bdaddr) +{ + BLE_ASSERT_ERR(reg_idx <= 2); + BLE_ASSERT_ERR((((uint16_t)bdaddr << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_LEBDADDR_ADDR + elt_idx * REG_EM_BLE_CS_SIZE + reg_idx * 2, (uint16_t)bdaddr << 0); +} + +/** + * @brief SYNCWL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00            SYNCWORDL   0x0
+ * 
+ */ +#define EM_BLE_SYNCWL_ADDR (0x0091000E + EM_BLE_CS_OFFSET) +#define EM_BLE_SYNCWL_INDEX 0x00000007 +#define EM_BLE_SYNCWL_RESET 0x00000000 + +__INLINE uint16_t em_ble_syncwl_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_SYNCWL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +__INLINE void em_ble_syncwl_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_SYNCWL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, value); +} + +// field definitions +#define EM_BLE_SYNCWORDL_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_SYNCWORDL_LSB 0 +#define EM_BLE_SYNCWORDL_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_SYNCWORDL_RST 0x0 + +__INLINE uint16_t em_ble_syncwl_syncwordl_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_SYNCWL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_syncwl_syncwordl_setf(int elt_idx, uint16_t syncwordl) +{ + BLE_ASSERT_ERR((((uint16_t)syncwordl << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_SYNCWL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (uint16_t)syncwordl << 0); +} + +/** + * @brief SYNCWH register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00            SYNCWORDH   0x0
+ * 
+ */ +#define EM_BLE_SYNCWH_ADDR (0x00910010 + EM_BLE_CS_OFFSET) +#define EM_BLE_SYNCWH_INDEX 0x00000008 +#define EM_BLE_SYNCWH_RESET 0x00000000 + +__INLINE uint16_t em_ble_syncwh_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_SYNCWH_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +__INLINE void em_ble_syncwh_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_SYNCWH_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, value); +} + +// field definitions +#define EM_BLE_SYNCWORDH_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_SYNCWORDH_LSB 0 +#define EM_BLE_SYNCWORDH_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_SYNCWORDH_RST 0x0 + +__INLINE uint16_t em_ble_syncwh_syncwordh_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_SYNCWH_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_syncwh_syncwordh_setf(int elt_idx, uint16_t syncwordh) +{ + BLE_ASSERT_ERR((((uint16_t)syncwordh << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_SYNCWH_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (uint16_t)syncwordh << 0); +} + +/** + * @brief CRCINIT0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00             CRCINIT0   0x0
+ * 
+ */ +#define EM_BLE_CRCINIT0_ADDR (0x00910012 + EM_BLE_CS_OFFSET) +#define EM_BLE_CRCINIT0_INDEX 0x00000009 +#define EM_BLE_CRCINIT0_RESET 0x00000000 + +__INLINE uint16_t em_ble_crcinit0_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_CRCINIT0_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +__INLINE void em_ble_crcinit0_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_CRCINIT0_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, value); +} + +// field definitions +#define EM_BLE_CRCINIT0_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_CRCINIT0_LSB 0 +#define EM_BLE_CRCINIT0_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_CRCINIT0_RST 0x0 + +__INLINE uint16_t em_ble_crcinit0_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_CRCINIT0_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_crcinit0_setf(int elt_idx, uint16_t crcinit0) +{ + BLE_ASSERT_ERR((((uint16_t)crcinit0 << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_CRCINIT0_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (uint16_t)crcinit0 << 0); +} + +/** + * @brief CRCINIT1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:08          RXMAXCTEBUF   0x0
+ *  07:00             CRCINIT1   0x0
+ * 
+ */ +#define EM_BLE_CRCINIT1_ADDR (0x00910014 + EM_BLE_CS_OFFSET) +#define EM_BLE_CRCINIT1_INDEX 0x0000000A +#define EM_BLE_CRCINIT1_RESET 0x00000000 + +__INLINE uint16_t em_ble_crcinit1_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_CRCINIT1_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +__INLINE void em_ble_crcinit1_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_CRCINIT1_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, value); +} + +// field definitions +#define EM_BLE_RXMAXCTEBUF_MASK ((uint16_t)0x0000FF00) +#define EM_BLE_RXMAXCTEBUF_LSB 8 +#define EM_BLE_RXMAXCTEBUF_WIDTH ((uint16_t)0x00000008) +#define EM_BLE_CRCINIT1_MASK ((uint16_t)0x000000FF) +#define EM_BLE_CRCINIT1_LSB 0 +#define EM_BLE_CRCINIT1_WIDTH ((uint16_t)0x00000008) + +#define EM_BLE_RXMAXCTEBUF_RST 0x0 +#define EM_BLE_CRCINIT1_RST 0x0 + +__INLINE void em_ble_crcinit1_pack(int elt_idx, uint8_t rxmaxctebuf, uint8_t crcinit1) +{ + BLE_ASSERT_ERR((((uint16_t)rxmaxctebuf << 8) & ~((uint16_t)0x0000FF00)) == 0); + BLE_ASSERT_ERR((((uint16_t)crcinit1 << 0) & ~((uint16_t)0x000000FF)) == 0); + EM_BLE_WR(EM_BLE_CRCINIT1_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, ((uint16_t)rxmaxctebuf << 8) | ((uint16_t)crcinit1 << 0)); +} + +__INLINE void em_ble_crcinit1_unpack(int elt_idx, uint8_t* rxmaxctebuf, uint8_t* crcinit1) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_CRCINIT1_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + + *rxmaxctebuf = (localVal & ((uint16_t)0x0000FF00)) >> 8; + *crcinit1 = (localVal & ((uint16_t)0x000000FF)) >> 0; +} + +__INLINE uint8_t em_ble_crcinit1_rxmaxctebuf_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_CRCINIT1_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x0000FF00)) >> 8); +} + +__INLINE void em_ble_crcinit1_rxmaxctebuf_setf(int elt_idx, uint8_t rxmaxctebuf) +{ + BLE_ASSERT_ERR((((uint16_t)rxmaxctebuf << 8) & ~((uint16_t)0x0000FF00)) == 0); + EM_BLE_WR(EM_BLE_CRCINIT1_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_CRCINIT1_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x0000FF00)) | ((uint16_t)rxmaxctebuf << 8)); +} + +__INLINE uint8_t em_ble_crcinit1_crcinit1_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_CRCINIT1_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x000000FF)) >> 0); +} + +__INLINE void em_ble_crcinit1_crcinit1_setf(int elt_idx, uint8_t crcinit1) +{ + BLE_ASSERT_ERR((((uint16_t)crcinit1 << 0) & ~((uint16_t)0x000000FF)) == 0); + EM_BLE_WR(EM_BLE_CRCINIT1_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_CRCINIT1_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x000000FF)) | ((uint16_t)crcinit1 << 0)); +} + +/** + * @brief FILTPOL_RALCNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:08        FILTER_POLICY   0x0
+ *     04         RAL_RESOL_EN   0
+ *     03       PERADV_FILT_EN   0
+ *     02        LOCAL_RPA_SEL   0
+ *     01             RAL_MODE   0
+ *     00               RAL_EN   0
+ * 
+ */ +#define EM_BLE_FILTPOL_RALCNTL_ADDR (0x00910016 + EM_BLE_CS_OFFSET) +#define EM_BLE_FILTPOL_RALCNTL_INDEX 0x0000000B +#define EM_BLE_FILTPOL_RALCNTL_RESET 0x00000000 + +__INLINE uint16_t em_ble_filtpol_ralcntl_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_FILTPOL_RALCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +__INLINE void em_ble_filtpol_ralcntl_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_FILTPOL_RALCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, value); +} + +// field definitions +#define EM_BLE_FILTER_POLICY_MASK ((uint16_t)0x0000FF00) +#define EM_BLE_FILTER_POLICY_LSB 8 +#define EM_BLE_FILTER_POLICY_WIDTH ((uint16_t)0x00000008) +#define EM_BLE_RAL_RESOL_EN_BIT ((uint16_t)0x00000010) +#define EM_BLE_RAL_RESOL_EN_POS 4 +#define EM_BLE_PERADV_FILT_EN_BIT ((uint16_t)0x00000008) +#define EM_BLE_PERADV_FILT_EN_POS 3 +#define EM_BLE_LOCAL_RPA_SEL_BIT ((uint16_t)0x00000004) +#define EM_BLE_LOCAL_RPA_SEL_POS 2 +#define EM_BLE_RAL_MODE_BIT ((uint16_t)0x00000002) +#define EM_BLE_RAL_MODE_POS 1 +#define EM_BLE_RAL_EN_BIT ((uint16_t)0x00000001) +#define EM_BLE_RAL_EN_POS 0 + +#define EM_BLE_FILTER_POLICY_RST 0x0 +#define EM_BLE_RAL_RESOL_EN_RST 0x0 +#define EM_BLE_PERADV_FILT_EN_RST 0x0 +#define EM_BLE_LOCAL_RPA_SEL_RST 0x0 +#define EM_BLE_RAL_MODE_RST 0x0 +#define EM_BLE_RAL_EN_RST 0x0 + +__INLINE void em_ble_filtpol_ralcntl_pack(int elt_idx, uint8_t filterpolicy, uint8_t ralresolen, uint8_t peradvfilten, uint8_t localrpasel, uint8_t ralmode, uint8_t ralen) +{ + BLE_ASSERT_ERR((((uint16_t)filterpolicy << 8) & ~((uint16_t)0x0000FF00)) == 0); + BLE_ASSERT_ERR((((uint16_t)ralresolen << 4) & ~((uint16_t)0x00000010)) == 0); + BLE_ASSERT_ERR((((uint16_t)peradvfilten << 3) & ~((uint16_t)0x00000008)) == 0); + BLE_ASSERT_ERR((((uint16_t)localrpasel << 2) & ~((uint16_t)0x00000004)) == 0); + BLE_ASSERT_ERR((((uint16_t)ralmode << 1) & ~((uint16_t)0x00000002)) == 0); + BLE_ASSERT_ERR((((uint16_t)ralen << 0) & ~((uint16_t)0x00000001)) == 0); + EM_BLE_WR(EM_BLE_FILTPOL_RALCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, ((uint16_t)filterpolicy << 8) | ((uint16_t)ralresolen << 4) | ((uint16_t)peradvfilten << 3) | ((uint16_t)localrpasel << 2) | ((uint16_t)ralmode << 1) | ((uint16_t)ralen << 0)); +} + +__INLINE void em_ble_filtpol_ralcntl_unpack(int elt_idx, uint8_t* filterpolicy, uint8_t* ralresolen, uint8_t* peradvfilten, uint8_t* localrpasel, uint8_t* ralmode, uint8_t* ralen) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_FILTPOL_RALCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + + *filterpolicy = (localVal & ((uint16_t)0x0000FF00)) >> 8; + *ralresolen = (localVal & ((uint16_t)0x00000010)) >> 4; + *peradvfilten = (localVal & ((uint16_t)0x00000008)) >> 3; + *localrpasel = (localVal & ((uint16_t)0x00000004)) >> 2; + *ralmode = (localVal & ((uint16_t)0x00000002)) >> 1; + *ralen = (localVal & ((uint16_t)0x00000001)) >> 0; +} + +__INLINE uint8_t em_ble_filtpol_ralcntl_filter_policy_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_FILTPOL_RALCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x0000FF00)) >> 8); +} + +__INLINE void em_ble_filtpol_ralcntl_filter_policy_setf(int elt_idx, uint8_t filterpolicy) +{ + BLE_ASSERT_ERR((((uint16_t)filterpolicy << 8) & ~((uint16_t)0x0000FF00)) == 0); + EM_BLE_WR(EM_BLE_FILTPOL_RALCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_FILTPOL_RALCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x0000FF00)) | ((uint16_t)filterpolicy << 8)); +} + +__INLINE uint8_t em_ble_filtpol_ralcntl_ral_resol_en_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_FILTPOL_RALCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00000010)) >> 4); +} + +__INLINE void em_ble_filtpol_ralcntl_ral_resol_en_setf(int elt_idx, uint8_t ralresolen) +{ + BLE_ASSERT_ERR((((uint16_t)ralresolen << 4) & ~((uint16_t)0x00000010)) == 0); + EM_BLE_WR(EM_BLE_FILTPOL_RALCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_FILTPOL_RALCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00000010)) | ((uint16_t)ralresolen << 4)); +} + +__INLINE uint8_t em_ble_filtpol_ralcntl_peradv_filt_en_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_FILTPOL_RALCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00000008)) >> 3); +} + +__INLINE void em_ble_filtpol_ralcntl_peradv_filt_en_setf(int elt_idx, uint8_t peradvfilten) +{ + BLE_ASSERT_ERR((((uint16_t)peradvfilten << 3) & ~((uint16_t)0x00000008)) == 0); + EM_BLE_WR(EM_BLE_FILTPOL_RALCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_FILTPOL_RALCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00000008)) | ((uint16_t)peradvfilten << 3)); +} + +__INLINE uint8_t em_ble_filtpol_ralcntl_local_rpa_sel_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_FILTPOL_RALCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00000004)) >> 2); +} + +__INLINE void em_ble_filtpol_ralcntl_local_rpa_sel_setf(int elt_idx, uint8_t localrpasel) +{ + BLE_ASSERT_ERR((((uint16_t)localrpasel << 2) & ~((uint16_t)0x00000004)) == 0); + EM_BLE_WR(EM_BLE_FILTPOL_RALCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_FILTPOL_RALCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00000004)) | ((uint16_t)localrpasel << 2)); +} + +__INLINE uint8_t em_ble_filtpol_ralcntl_ral_mode_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_FILTPOL_RALCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00000002)) >> 1); +} + +__INLINE void em_ble_filtpol_ralcntl_ral_mode_setf(int elt_idx, uint8_t ralmode) +{ + BLE_ASSERT_ERR((((uint16_t)ralmode << 1) & ~((uint16_t)0x00000002)) == 0); + EM_BLE_WR(EM_BLE_FILTPOL_RALCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_FILTPOL_RALCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00000002)) | ((uint16_t)ralmode << 1)); +} + +__INLINE uint8_t em_ble_filtpol_ralcntl_ral_en_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_FILTPOL_RALCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00000001)) >> 0); +} + +__INLINE void em_ble_filtpol_ralcntl_ral_en_setf(int elt_idx, uint8_t ralen) +{ + BLE_ASSERT_ERR((((uint16_t)ralen << 0) & ~((uint16_t)0x00000001)) == 0); + EM_BLE_WR(EM_BLE_FILTPOL_RALCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_FILTPOL_RALCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00000001)) | ((uint16_t)ralen << 0)); +} + +/** + * @brief HOPCNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     15                FH_EN   0
+ *  14:13             HOP_MODE   0x0
+ *  12:08              HOP_INT   0x0
+ *  05:00               CH_IDX   0x0
+ * 
+ */ +#define EM_BLE_HOPCNTL_ADDR (0x00910018 + EM_BLE_CS_OFFSET) +#define EM_BLE_HOPCNTL_INDEX 0x0000000C +#define EM_BLE_HOPCNTL_RESET 0x00000000 + +__INLINE uint16_t em_ble_hopcntl_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_HOPCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +__INLINE void em_ble_hopcntl_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_HOPCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, value); +} + +// field definitions +#define EM_BLE_FH_EN_BIT ((uint16_t)0x00008000) +#define EM_BLE_FH_EN_POS 15 +#define EM_BLE_HOP_MODE_MASK ((uint16_t)0x00006000) +#define EM_BLE_HOP_MODE_LSB 13 +#define EM_BLE_HOP_MODE_WIDTH ((uint16_t)0x00000002) +#define EM_BLE_HOP_INT_MASK ((uint16_t)0x00001F00) +#define EM_BLE_HOP_INT_LSB 8 +#define EM_BLE_HOP_INT_WIDTH ((uint16_t)0x00000005) +#define EM_BLE_CH_IDX_MASK ((uint16_t)0x0000003F) +#define EM_BLE_CH_IDX_LSB 0 +#define EM_BLE_CH_IDX_WIDTH ((uint16_t)0x00000006) + +#define EM_BLE_FH_EN_RST 0x0 +#define EM_BLE_HOP_MODE_RST 0x0 +#define EM_BLE_HOP_INT_RST 0x0 +#define EM_BLE_CH_IDX_RST 0x0 + +__INLINE void em_ble_hopcntl_pack(int elt_idx, uint8_t fhen, uint8_t hopmode, uint8_t hopint, uint8_t chidx) +{ + BLE_ASSERT_ERR((((uint16_t)fhen << 15) & ~((uint16_t)0x00008000)) == 0); + BLE_ASSERT_ERR((((uint16_t)hopmode << 13) & ~((uint16_t)0x00006000)) == 0); + BLE_ASSERT_ERR((((uint16_t)hopint << 8) & ~((uint16_t)0x00001F00)) == 0); + BLE_ASSERT_ERR((((uint16_t)chidx << 0) & ~((uint16_t)0x0000003F)) == 0); + EM_BLE_WR(EM_BLE_HOPCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, ((uint16_t)fhen << 15) | ((uint16_t)hopmode << 13) | ((uint16_t)hopint << 8) | ((uint16_t)chidx << 0)); +} + +__INLINE void em_ble_hopcntl_unpack(int elt_idx, uint8_t* fhen, uint8_t* hopmode, uint8_t* hopint, uint8_t* chidx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_HOPCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + + *fhen = (localVal & ((uint16_t)0x00008000)) >> 15; + *hopmode = (localVal & ((uint16_t)0x00006000)) >> 13; + *hopint = (localVal & ((uint16_t)0x00001F00)) >> 8; + *chidx = (localVal & ((uint16_t)0x0000003F)) >> 0; +} + +__INLINE uint8_t em_ble_hopcntl_fh_en_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_HOPCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00008000)) >> 15); +} + +__INLINE void em_ble_hopcntl_fh_en_setf(int elt_idx, uint8_t fhen) +{ + BLE_ASSERT_ERR((((uint16_t)fhen << 15) & ~((uint16_t)0x00008000)) == 0); + EM_BLE_WR(EM_BLE_HOPCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_HOPCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00008000)) | ((uint16_t)fhen << 15)); +} + +__INLINE uint8_t em_ble_hopcntl_hop_mode_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_HOPCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00006000)) >> 13); +} + +__INLINE void em_ble_hopcntl_hop_mode_setf(int elt_idx, uint8_t hopmode) +{ + BLE_ASSERT_ERR((((uint16_t)hopmode << 13) & ~((uint16_t)0x00006000)) == 0); + EM_BLE_WR(EM_BLE_HOPCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_HOPCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00006000)) | ((uint16_t)hopmode << 13)); +} + +__INLINE uint8_t em_ble_hopcntl_hop_int_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_HOPCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00001F00)) >> 8); +} + +__INLINE void em_ble_hopcntl_hop_int_setf(int elt_idx, uint8_t hopint) +{ + BLE_ASSERT_ERR((((uint16_t)hopint << 8) & ~((uint16_t)0x00001F00)) == 0); + EM_BLE_WR(EM_BLE_HOPCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_HOPCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00001F00)) | ((uint16_t)hopint << 8)); +} + +__INLINE uint8_t em_ble_hopcntl_ch_idx_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_HOPCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x0000003F)) >> 0); +} + +__INLINE void em_ble_hopcntl_ch_idx_setf(int elt_idx, uint8_t chidx) +{ + BLE_ASSERT_ERR((((uint16_t)chidx << 0) & ~((uint16_t)0x0000003F)) == 0); + EM_BLE_WR(EM_BLE_HOPCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_HOPCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x0000003F)) | ((uint16_t)chidx << 0)); +} + +/** + * @brief TXRXCNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     15          RXBUFF_FULL   0
+ *     14            LASTEMPTY   0
+ *     13                   SN   0
+ *     12                 NESN   0
+ *     11           RXBFMICERR   0
+ *     10            RXMAFSERR   0
+ *     09          ENDS_ON_SAC   0
+ *     08            EXT_PA_EN   0
+ *  07:00                TXPWR   0x0
+ * 
+ */ +#define EM_BLE_TXRXCNTL_ADDR (0x0091001A + EM_BLE_CS_OFFSET) +#define EM_BLE_TXRXCNTL_INDEX 0x0000000D +#define EM_BLE_TXRXCNTL_RESET 0x00000000 + +__INLINE uint16_t em_ble_txrxcntl_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_TXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +__INLINE void em_ble_txrxcntl_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_TXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, value); +} + +// field definitions +#define EM_BLE_RXBUFF_FULL_BIT ((uint16_t)0x00008000) +#define EM_BLE_RXBUFF_FULL_POS 15 +#define EM_BLE_LASTEMPTY_BIT ((uint16_t)0x00004000) +#define EM_BLE_LASTEMPTY_POS 14 +#define EM_BLE_SN_BIT ((uint16_t)0x00002000) +#define EM_BLE_SN_POS 13 +#define EM_BLE_NESN_BIT ((uint16_t)0x00001000) +#define EM_BLE_NESN_POS 12 +#define EM_BLE_RXBFMICERR_BIT ((uint16_t)0x00000800) +#define EM_BLE_RXBFMICERR_POS 11 +#define EM_BLE_RXMAFSERR_BIT ((uint16_t)0x00000400) +#define EM_BLE_RXMAFSERR_POS 10 +#define EM_BLE_ENDS_ON_SAC_BIT ((uint16_t)0x00000200) +#define EM_BLE_ENDS_ON_SAC_POS 9 +#define EM_BLE_EXT_PA_EN_BIT ((uint16_t)0x00000100) +#define EM_BLE_EXT_PA_EN_POS 8 +#define EM_BLE_TXPWR_MASK ((uint16_t)0x000000FF) +#define EM_BLE_TXPWR_LSB 0 +#define EM_BLE_TXPWR_WIDTH ((uint16_t)0x00000008) + +#define EM_BLE_RXBUFF_FULL_RST 0x0 +#define EM_BLE_LASTEMPTY_RST 0x0 +#define EM_BLE_SN_RST 0x0 +#define EM_BLE_NESN_RST 0x0 +#define EM_BLE_RXBFMICERR_RST 0x0 +#define EM_BLE_RXMAFSERR_RST 0x0 +#define EM_BLE_ENDS_ON_SAC_RST 0x0 +#define EM_BLE_EXT_PA_EN_RST 0x0 +#define EM_BLE_TXPWR_RST 0x0 + +__INLINE void em_ble_txrxcntl_pack(int elt_idx, uint8_t rxbufffull, uint8_t lastempty, uint8_t sn, uint8_t nesn, uint8_t rxbfmicerr, uint8_t rxmafserr, uint8_t endsonsac, uint8_t extpaen, uint8_t txpwr) +{ + BLE_ASSERT_ERR((((uint16_t)rxbufffull << 15) & ~((uint16_t)0x00008000)) == 0); + BLE_ASSERT_ERR((((uint16_t)lastempty << 14) & ~((uint16_t)0x00004000)) == 0); + BLE_ASSERT_ERR((((uint16_t)sn << 13) & ~((uint16_t)0x00002000)) == 0); + BLE_ASSERT_ERR((((uint16_t)nesn << 12) & ~((uint16_t)0x00001000)) == 0); + BLE_ASSERT_ERR((((uint16_t)rxbfmicerr << 11) & ~((uint16_t)0x00000800)) == 0); + BLE_ASSERT_ERR((((uint16_t)rxmafserr << 10) & ~((uint16_t)0x00000400)) == 0); + BLE_ASSERT_ERR((((uint16_t)endsonsac << 9) & ~((uint16_t)0x00000200)) == 0); + BLE_ASSERT_ERR((((uint16_t)extpaen << 8) & ~((uint16_t)0x00000100)) == 0); + BLE_ASSERT_ERR((((uint16_t)txpwr << 0) & ~((uint16_t)0x000000FF)) == 0); + EM_BLE_WR(EM_BLE_TXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, ((uint16_t)rxbufffull << 15) | ((uint16_t)lastempty << 14) | ((uint16_t)sn << 13) | ((uint16_t)nesn << 12) | ((uint16_t)rxbfmicerr << 11) | ((uint16_t)rxmafserr << 10) | ((uint16_t)endsonsac << 9) | ((uint16_t)extpaen << 8) | ((uint16_t)txpwr << 0)); +} + +__INLINE void em_ble_txrxcntl_unpack(int elt_idx, uint8_t* rxbufffull, uint8_t* lastempty, uint8_t* sn, uint8_t* nesn, uint8_t* rxbfmicerr, uint8_t* rxmafserr, uint8_t* endsonsac, uint8_t* extpaen, uint8_t* txpwr) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + + *rxbufffull = (localVal & ((uint16_t)0x00008000)) >> 15; + *lastempty = (localVal & ((uint16_t)0x00004000)) >> 14; + *sn = (localVal & ((uint16_t)0x00002000)) >> 13; + *nesn = (localVal & ((uint16_t)0x00001000)) >> 12; + *rxbfmicerr = (localVal & ((uint16_t)0x00000800)) >> 11; + *rxmafserr = (localVal & ((uint16_t)0x00000400)) >> 10; + *endsonsac = (localVal & ((uint16_t)0x00000200)) >> 9; + *extpaen = (localVal & ((uint16_t)0x00000100)) >> 8; + *txpwr = (localVal & ((uint16_t)0x000000FF)) >> 0; +} + +__INLINE uint8_t em_ble_txrxcntl_rxbuff_full_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00008000)) >> 15); +} + +__INLINE void em_ble_txrxcntl_rxbuff_full_setf(int elt_idx, uint8_t rxbufffull) +{ + BLE_ASSERT_ERR((((uint16_t)rxbufffull << 15) & ~((uint16_t)0x00008000)) == 0); + EM_BLE_WR(EM_BLE_TXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_TXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00008000)) | ((uint16_t)rxbufffull << 15)); +} + +__INLINE uint8_t em_ble_txrxcntl_lastempty_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00004000)) >> 14); +} + +__INLINE void em_ble_txrxcntl_lastempty_setf(int elt_idx, uint8_t lastempty) +{ + BLE_ASSERT_ERR((((uint16_t)lastempty << 14) & ~((uint16_t)0x00004000)) == 0); + EM_BLE_WR(EM_BLE_TXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_TXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00004000)) | ((uint16_t)lastempty << 14)); +} + +__INLINE uint8_t em_ble_txrxcntl_sn_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00002000)) >> 13); +} + +__INLINE void em_ble_txrxcntl_sn_setf(int elt_idx, uint8_t sn) +{ + BLE_ASSERT_ERR((((uint16_t)sn << 13) & ~((uint16_t)0x00002000)) == 0); + EM_BLE_WR(EM_BLE_TXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_TXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00002000)) | ((uint16_t)sn << 13)); +} + +__INLINE uint8_t em_ble_txrxcntl_nesn_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00001000)) >> 12); +} + +__INLINE void em_ble_txrxcntl_nesn_setf(int elt_idx, uint8_t nesn) +{ + BLE_ASSERT_ERR((((uint16_t)nesn << 12) & ~((uint16_t)0x00001000)) == 0); + EM_BLE_WR(EM_BLE_TXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_TXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00001000)) | ((uint16_t)nesn << 12)); +} + +__INLINE uint8_t em_ble_txrxcntl_rxbfmicerr_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00000800)) >> 11); +} + +__INLINE void em_ble_txrxcntl_rxbfmicerr_setf(int elt_idx, uint8_t rxbfmicerr) +{ + BLE_ASSERT_ERR((((uint16_t)rxbfmicerr << 11) & ~((uint16_t)0x00000800)) == 0); + EM_BLE_WR(EM_BLE_TXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_TXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00000800)) | ((uint16_t)rxbfmicerr << 11)); +} + +__INLINE uint8_t em_ble_txrxcntl_rxmafserr_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00000400)) >> 10); +} + +__INLINE void em_ble_txrxcntl_rxmafserr_setf(int elt_idx, uint8_t rxmafserr) +{ + BLE_ASSERT_ERR((((uint16_t)rxmafserr << 10) & ~((uint16_t)0x00000400)) == 0); + EM_BLE_WR(EM_BLE_TXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_TXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00000400)) | ((uint16_t)rxmafserr << 10)); +} + +__INLINE uint8_t em_ble_txrxcntl_ends_on_sac_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00000200)) >> 9); +} + +__INLINE void em_ble_txrxcntl_ends_on_sac_setf(int elt_idx, uint8_t endsonsac) +{ + BLE_ASSERT_ERR((((uint16_t)endsonsac << 9) & ~((uint16_t)0x00000200)) == 0); + EM_BLE_WR(EM_BLE_TXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_TXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00000200)) | ((uint16_t)endsonsac << 9)); +} + +__INLINE uint8_t em_ble_txrxcntl_ext_pa_en_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00000100)) >> 8); +} + +__INLINE void em_ble_txrxcntl_ext_pa_en_setf(int elt_idx, uint8_t extpaen) +{ + BLE_ASSERT_ERR((((uint16_t)extpaen << 8) & ~((uint16_t)0x00000100)) == 0); + EM_BLE_WR(EM_BLE_TXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_TXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00000100)) | ((uint16_t)extpaen << 8)); +} + +__INLINE uint8_t em_ble_txrxcntl_txpwr_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x000000FF)) >> 0); +} + +__INLINE void em_ble_txrxcntl_txpwr_setf(int elt_idx, uint8_t txpwr) +{ + BLE_ASSERT_ERR((((uint16_t)txpwr << 0) & ~((uint16_t)0x000000FF)) == 0); + EM_BLE_WR(EM_BLE_TXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_TXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x000000FF)) | ((uint16_t)txpwr << 0)); +} + +/** + * @brief RXDFCNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     08              DFRSPEN   0
+ *  07:06             DFSWCNTL   0x0
+ *  05:04           DFSAMPCNTL   0x0
+ *  03:02               DFTYPE   0x0
+ *     01           DFFILTEREN   0
+ *     00                 DFEN   0
+ * 
+ */ +#define EM_BLE_RXDFCNTL_ADDR (0x0091001C + EM_BLE_CS_OFFSET) +#define EM_BLE_RXDFCNTL_INDEX 0x0000000E +#define EM_BLE_RXDFCNTL_RESET 0x00000000 + +__INLINE uint16_t em_ble_rxdfcntl_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_RXDFCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +__INLINE void em_ble_rxdfcntl_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_RXDFCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, value); +} + +// field definitions +#define EM_BLE_DFRSPEN_BIT ((uint16_t)0x00000100) +#define EM_BLE_DFRSPEN_POS 8 +#define EM_BLE_DFSWCNTL_MASK ((uint16_t)0x000000C0) +#define EM_BLE_DFSWCNTL_LSB 6 +#define EM_BLE_DFSWCNTL_WIDTH ((uint16_t)0x00000002) +#define EM_BLE_DFSAMPCNTL_MASK ((uint16_t)0x00000030) +#define EM_BLE_DFSAMPCNTL_LSB 4 +#define EM_BLE_DFSAMPCNTL_WIDTH ((uint16_t)0x00000002) +#define EM_BLE_DFTYPE_MASK ((uint16_t)0x0000000C) +#define EM_BLE_DFTYPE_LSB 2 +#define EM_BLE_DFTYPE_WIDTH ((uint16_t)0x00000002) +#define EM_BLE_DFFILTEREN_BIT ((uint16_t)0x00000002) +#define EM_BLE_DFFILTEREN_POS 1 +#define EM_BLE_DFEN_BIT ((uint16_t)0x00000001) +#define EM_BLE_DFEN_POS 0 + +#define EM_BLE_DFRSPEN_RST 0x0 +#define EM_BLE_DFSWCNTL_RST 0x0 +#define EM_BLE_DFSAMPCNTL_RST 0x0 +#define EM_BLE_DFTYPE_RST 0x0 +#define EM_BLE_DFFILTEREN_RST 0x0 +#define EM_BLE_DFEN_RST 0x0 + +__INLINE void em_ble_rxdfcntl_pack(int elt_idx, uint8_t dfrspen, uint8_t dfswcntl, uint8_t dfsampcntl, uint8_t dftype, uint8_t dffilteren, uint8_t dfen) +{ + BLE_ASSERT_ERR((((uint16_t)dfrspen << 8) & ~((uint16_t)0x00000100)) == 0); + BLE_ASSERT_ERR((((uint16_t)dfswcntl << 6) & ~((uint16_t)0x000000C0)) == 0); + BLE_ASSERT_ERR((((uint16_t)dfsampcntl << 4) & ~((uint16_t)0x00000030)) == 0); + BLE_ASSERT_ERR((((uint16_t)dftype << 2) & ~((uint16_t)0x0000000C)) == 0); + BLE_ASSERT_ERR((((uint16_t)dffilteren << 1) & ~((uint16_t)0x00000002)) == 0); + BLE_ASSERT_ERR((((uint16_t)dfen << 0) & ~((uint16_t)0x00000001)) == 0); + EM_BLE_WR(EM_BLE_RXDFCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, ((uint16_t)dfrspen << 8) | ((uint16_t)dfswcntl << 6) | ((uint16_t)dfsampcntl << 4) | ((uint16_t)dftype << 2) | ((uint16_t)dffilteren << 1) | ((uint16_t)dfen << 0)); +} + +__INLINE void em_ble_rxdfcntl_unpack(int elt_idx, uint8_t* dfrspen, uint8_t* dfswcntl, uint8_t* dfsampcntl, uint8_t* dftype, uint8_t* dffilteren, uint8_t* dfen) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXDFCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + + *dfrspen = (localVal & ((uint16_t)0x00000100)) >> 8; + *dfswcntl = (localVal & ((uint16_t)0x000000C0)) >> 6; + *dfsampcntl = (localVal & ((uint16_t)0x00000030)) >> 4; + *dftype = (localVal & ((uint16_t)0x0000000C)) >> 2; + *dffilteren = (localVal & ((uint16_t)0x00000002)) >> 1; + *dfen = (localVal & ((uint16_t)0x00000001)) >> 0; +} + +__INLINE uint8_t em_ble_rxdfcntl_dfrspen_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXDFCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00000100)) >> 8); +} + +__INLINE void em_ble_rxdfcntl_dfrspen_setf(int elt_idx, uint8_t dfrspen) +{ + BLE_ASSERT_ERR((((uint16_t)dfrspen << 8) & ~((uint16_t)0x00000100)) == 0); + EM_BLE_WR(EM_BLE_RXDFCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_RXDFCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00000100)) | ((uint16_t)dfrspen << 8)); +} + +__INLINE uint8_t em_ble_rxdfcntl_dfswcntl_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXDFCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x000000C0)) >> 6); +} + +__INLINE void em_ble_rxdfcntl_dfswcntl_setf(int elt_idx, uint8_t dfswcntl) +{ + BLE_ASSERT_ERR((((uint16_t)dfswcntl << 6) & ~((uint16_t)0x000000C0)) == 0); + EM_BLE_WR(EM_BLE_RXDFCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_RXDFCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x000000C0)) | ((uint16_t)dfswcntl << 6)); +} + +__INLINE uint8_t em_ble_rxdfcntl_dfsampcntl_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXDFCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00000030)) >> 4); +} + +__INLINE void em_ble_rxdfcntl_dfsampcntl_setf(int elt_idx, uint8_t dfsampcntl) +{ + BLE_ASSERT_ERR((((uint16_t)dfsampcntl << 4) & ~((uint16_t)0x00000030)) == 0); + EM_BLE_WR(EM_BLE_RXDFCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_RXDFCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00000030)) | ((uint16_t)dfsampcntl << 4)); +} + +__INLINE uint8_t em_ble_rxdfcntl_dftype_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXDFCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x0000000C)) >> 2); +} + +__INLINE void em_ble_rxdfcntl_dftype_setf(int elt_idx, uint8_t dftype) +{ + BLE_ASSERT_ERR((((uint16_t)dftype << 2) & ~((uint16_t)0x0000000C)) == 0); + EM_BLE_WR(EM_BLE_RXDFCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_RXDFCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x0000000C)) | ((uint16_t)dftype << 2)); +} + +__INLINE uint8_t em_ble_rxdfcntl_dffilteren_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXDFCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00000002)) >> 1); +} + +__INLINE void em_ble_rxdfcntl_dffilteren_setf(int elt_idx, uint8_t dffilteren) +{ + BLE_ASSERT_ERR((((uint16_t)dffilteren << 1) & ~((uint16_t)0x00000002)) == 0); + EM_BLE_WR(EM_BLE_RXDFCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_RXDFCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00000002)) | ((uint16_t)dffilteren << 1)); +} + +__INLINE uint8_t em_ble_rxdfcntl_dfen_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXDFCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00000001)) >> 0); +} + +__INLINE void em_ble_rxdfcntl_dfen_setf(int elt_idx, uint8_t dfen) +{ + BLE_ASSERT_ERR((((uint16_t)dfen << 0) & ~((uint16_t)0x00000001)) == 0); + EM_BLE_WR(EM_BLE_RXDFCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_RXDFCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00000001)) | ((uint16_t)dfen << 0)); +} + +/** + * @brief RXWINCNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     15               RXWIDE   0
+ *  14:00              RXWINSZ   0x0
+ * 
+ */ +#define EM_BLE_RXWINCNTL_ADDR (0x0091001E + EM_BLE_CS_OFFSET) +#define EM_BLE_RXWINCNTL_INDEX 0x0000000F +#define EM_BLE_RXWINCNTL_RESET 0x00000000 + +__INLINE uint16_t em_ble_rxwincntl_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_RXWINCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +__INLINE void em_ble_rxwincntl_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_RXWINCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, value); +} + +// field definitions +#define EM_BLE_RXWIDE_BIT ((uint16_t)0x00008000) +#define EM_BLE_RXWIDE_POS 15 +#define EM_BLE_RXWINSZ_MASK ((uint16_t)0x00007FFF) +#define EM_BLE_RXWINSZ_LSB 0 +#define EM_BLE_RXWINSZ_WIDTH ((uint16_t)0x0000000F) + +#define EM_BLE_RXWIDE_RST 0x0 +#define EM_BLE_RXWINSZ_RST 0x0 + +__INLINE void em_ble_rxwincntl_pack(int elt_idx, uint8_t rxwide, uint16_t rxwinsz) +{ + BLE_ASSERT_ERR((((uint16_t)rxwide << 15) & ~((uint16_t)0x00008000)) == 0); + BLE_ASSERT_ERR((((uint16_t)rxwinsz << 0) & ~((uint16_t)0x00007FFF)) == 0); + EM_BLE_WR(EM_BLE_RXWINCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, ((uint16_t)rxwide << 15) | ((uint16_t)rxwinsz << 0)); +} + +__INLINE void em_ble_rxwincntl_unpack(int elt_idx, uint8_t* rxwide, uint16_t* rxwinsz) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXWINCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + + *rxwide = (localVal & ((uint16_t)0x00008000)) >> 15; + *rxwinsz = (localVal & ((uint16_t)0x00007FFF)) >> 0; +} + +__INLINE uint8_t em_ble_rxwincntl_rxwide_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXWINCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00008000)) >> 15); +} + +__INLINE void em_ble_rxwincntl_rxwide_setf(int elt_idx, uint8_t rxwide) +{ + BLE_ASSERT_ERR((((uint16_t)rxwide << 15) & ~((uint16_t)0x00008000)) == 0); + EM_BLE_WR(EM_BLE_RXWINCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_RXWINCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00008000)) | ((uint16_t)rxwide << 15)); +} + +__INLINE uint16_t em_ble_rxwincntl_rxwinsz_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXWINCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00007FFF)) >> 0); +} + +__INLINE void em_ble_rxwincntl_rxwinsz_setf(int elt_idx, uint16_t rxwinsz) +{ + BLE_ASSERT_ERR((((uint16_t)rxwinsz << 0) & ~((uint16_t)0x00007FFF)) == 0); + EM_BLE_WR(EM_BLE_RXWINCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_RXWINCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00007FFF)) | ((uint16_t)rxwinsz << 0)); +} + +/** + * @brief ISOTXDESCPTR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  13:00         ISOTXDESCPTR   0x0
+ * 
+ */ +#define EM_BLE_ISOTXDESCPTR_ADDR (0x00910020 + EM_BLE_CS_OFFSET) +#define EM_BLE_ISOTXDESCPTR_INDEX 0x00000010 +#define EM_BLE_ISOTXDESCPTR_RESET 0x00000000 + +__INLINE uint16_t em_ble_isotxdescptr_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_ISOTXDESCPTR_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +__INLINE void em_ble_isotxdescptr_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_ISOTXDESCPTR_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, value); +} + +// field definitions +#define EM_BLE_ISOTXDESCPTR_MASK ((uint16_t)0x00003FFF) +#define EM_BLE_ISOTXDESCPTR_LSB 0 +#define EM_BLE_ISOTXDESCPTR_WIDTH ((uint16_t)0x0000000E) + +#define EM_BLE_ISOTXDESCPTR_RST 0x0 + +__INLINE uint16_t em_ble_isotxdescptr_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_ISOTXDESCPTR_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x00003FFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_isotxdescptr_setf(int elt_idx, uint16_t isotxdescptr) +{ + BLE_ASSERT_ERR((((uint16_t)isotxdescptr << 0) & ~((uint16_t)0x00003FFF)) == 0); + EM_BLE_WR(EM_BLE_ISOTXDESCPTR_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (uint16_t)isotxdescptr << 0); +} + +/** + * @brief ISORXDESCPTR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  13:00         ISORXDESCPTR   0x0
+ * 
+ */ +#define EM_BLE_ISORXDESCPTR_ADDR (0x00910022 + EM_BLE_CS_OFFSET) +#define EM_BLE_ISORXDESCPTR_INDEX 0x00000011 +#define EM_BLE_ISORXDESCPTR_RESET 0x00000000 + +__INLINE uint16_t em_ble_isorxdescptr_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_ISORXDESCPTR_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +__INLINE void em_ble_isorxdescptr_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_ISORXDESCPTR_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, value); +} + +// field definitions +#define EM_BLE_ISORXDESCPTR_MASK ((uint16_t)0x00003FFF) +#define EM_BLE_ISORXDESCPTR_LSB 0 +#define EM_BLE_ISORXDESCPTR_WIDTH ((uint16_t)0x0000000E) + +#define EM_BLE_ISORXDESCPTR_RST 0x0 + +__INLINE uint16_t em_ble_isorxdescptr_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_ISORXDESCPTR_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x00003FFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_isorxdescptr_setf(int elt_idx, uint16_t isorxdescptr) +{ + BLE_ASSERT_ERR((((uint16_t)isorxdescptr << 0) & ~((uint16_t)0x00003FFF)) == 0); + EM_BLE_WR(EM_BLE_ISORXDESCPTR_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (uint16_t)isorxdescptr << 0); +} + +/** + * @brief ACLTXDESCPTR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  13:00         ACLTXDESCPTR   0x0
+ * 
+ */ +#define EM_BLE_ACLTXDESCPTR_ADDR (0x00910024 + EM_BLE_CS_OFFSET) +#define EM_BLE_ACLTXDESCPTR_INDEX 0x00000012 +#define EM_BLE_ACLTXDESCPTR_RESET 0x00000000 + +__INLINE uint16_t em_ble_acltxdescptr_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_ACLTXDESCPTR_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +__INLINE void em_ble_acltxdescptr_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_ACLTXDESCPTR_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, value); +} + +// field definitions +#define EM_BLE_ACLTXDESCPTR_MASK ((uint16_t)0x00003FFF) +#define EM_BLE_ACLTXDESCPTR_LSB 0 +#define EM_BLE_ACLTXDESCPTR_WIDTH ((uint16_t)0x0000000E) + +#define EM_BLE_ACLTXDESCPTR_RST 0x0 + +__INLINE uint16_t em_ble_acltxdescptr_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_ACLTXDESCPTR_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x00003FFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_acltxdescptr_setf(int elt_idx, uint16_t acltxdescptr) +{ + BLE_ASSERT_ERR((((uint16_t)acltxdescptr << 0) & ~((uint16_t)0x00003FFF)) == 0); + EM_BLE_WR(EM_BLE_ACLTXDESCPTR_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (uint16_t)acltxdescptr << 0); +} + +/** + * @brief RXDFANTPATTCNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     15                DFRSP   0
+ *  12:08         MAX_SAMP_CTE   0x0
+ *  06:00   RX_ANT_PATT_LENGTH   0x0
+ * 
+ */ +#define EM_BLE_RXDFANTPATTCNTL_ADDR (0x00910026 + EM_BLE_CS_OFFSET) +#define EM_BLE_RXDFANTPATTCNTL_INDEX 0x00000013 +#define EM_BLE_RXDFANTPATTCNTL_RESET 0x00000000 + +__INLINE uint16_t em_ble_rxdfantpattcntl_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_RXDFANTPATTCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +__INLINE void em_ble_rxdfantpattcntl_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_RXDFANTPATTCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, value); +} + +// field definitions +#define EM_BLE_DFRSP_BIT ((uint16_t)0x00008000) +#define EM_BLE_DFRSP_POS 15 +#define EM_BLE_MAX_SAMP_CTE_MASK ((uint16_t)0x00001F00) +#define EM_BLE_MAX_SAMP_CTE_LSB 8 +#define EM_BLE_MAX_SAMP_CTE_WIDTH ((uint16_t)0x00000005) +#define EM_BLE_RX_ANT_PATT_LENGTH_MASK ((uint16_t)0x0000007F) +#define EM_BLE_RX_ANT_PATT_LENGTH_LSB 0 +#define EM_BLE_RX_ANT_PATT_LENGTH_WIDTH ((uint16_t)0x00000007) + +#define EM_BLE_DFRSP_RST 0x0 +#define EM_BLE_MAX_SAMP_CTE_RST 0x0 +#define EM_BLE_RX_ANT_PATT_LENGTH_RST 0x0 + +__INLINE void em_ble_rxdfantpattcntl_pack(int elt_idx, uint8_t dfrsp, uint8_t maxsampcte, uint8_t rxantpattlength) +{ + BLE_ASSERT_ERR((((uint16_t)dfrsp << 15) & ~((uint16_t)0x00008000)) == 0); + BLE_ASSERT_ERR((((uint16_t)maxsampcte << 8) & ~((uint16_t)0x00001F00)) == 0); + BLE_ASSERT_ERR((((uint16_t)rxantpattlength << 0) & ~((uint16_t)0x0000007F)) == 0); + EM_BLE_WR(EM_BLE_RXDFANTPATTCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, ((uint16_t)dfrsp << 15) | ((uint16_t)maxsampcte << 8) | ((uint16_t)rxantpattlength << 0)); +} + +__INLINE void em_ble_rxdfantpattcntl_unpack(int elt_idx, uint8_t* dfrsp, uint8_t* maxsampcte, uint8_t* rxantpattlength) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXDFANTPATTCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + + *dfrsp = (localVal & ((uint16_t)0x00008000)) >> 15; + *maxsampcte = (localVal & ((uint16_t)0x00001F00)) >> 8; + *rxantpattlength = (localVal & ((uint16_t)0x0000007F)) >> 0; +} + +__INLINE uint8_t em_ble_rxdfantpattcntl_dfrsp_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXDFANTPATTCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00008000)) >> 15); +} + +__INLINE void em_ble_rxdfantpattcntl_dfrsp_setf(int elt_idx, uint8_t dfrsp) +{ + BLE_ASSERT_ERR((((uint16_t)dfrsp << 15) & ~((uint16_t)0x00008000)) == 0); + EM_BLE_WR(EM_BLE_RXDFANTPATTCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_RXDFANTPATTCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00008000)) | ((uint16_t)dfrsp << 15)); +} + +__INLINE uint8_t em_ble_rxdfantpattcntl_max_samp_cte_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXDFANTPATTCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00001F00)) >> 8); +} + +__INLINE void em_ble_rxdfantpattcntl_max_samp_cte_setf(int elt_idx, uint8_t maxsampcte) +{ + BLE_ASSERT_ERR((((uint16_t)maxsampcte << 8) & ~((uint16_t)0x00001F00)) == 0); + EM_BLE_WR(EM_BLE_RXDFANTPATTCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_RXDFANTPATTCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00001F00)) | ((uint16_t)maxsampcte << 8)); +} + +__INLINE uint8_t em_ble_rxdfantpattcntl_rx_ant_patt_length_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXDFANTPATTCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x0000007F)) >> 0); +} + +__INLINE void em_ble_rxdfantpattcntl_rx_ant_patt_length_setf(int elt_idx, uint8_t rxantpattlength) +{ + BLE_ASSERT_ERR((((uint16_t)rxantpattlength << 0) & ~((uint16_t)0x0000007F)) == 0); + EM_BLE_WR(EM_BLE_RXDFANTPATTCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_RXDFANTPATTCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x0000007F)) | ((uint16_t)rxantpattlength << 0)); +} + +/** + * @brief RXDFANTSWPTR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  13:00    RX_ANTENNA_ID_PTR   0x0
+ * 
+ */ +#define EM_BLE_RXDFANTSWPTR_ADDR (0x00910028 + EM_BLE_CS_OFFSET) +#define EM_BLE_RXDFANTSWPTR_INDEX 0x00000014 +#define EM_BLE_RXDFANTSWPTR_RESET 0x00000000 + +__INLINE uint16_t em_ble_rxdfantswptr_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_RXDFANTSWPTR_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +__INLINE void em_ble_rxdfantswptr_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_RXDFANTSWPTR_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, value); +} + +// field definitions +#define EM_BLE_RX_ANTENNA_ID_PTR_MASK ((uint16_t)0x00003FFF) +#define EM_BLE_RX_ANTENNA_ID_PTR_LSB 0 +#define EM_BLE_RX_ANTENNA_ID_PTR_WIDTH ((uint16_t)0x0000000E) + +#define EM_BLE_RX_ANTENNA_ID_PTR_RST 0x0 + +__INLINE uint16_t em_ble_rxdfantswptr_rx_antenna_id_ptr_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXDFANTSWPTR_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x00003FFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_rxdfantswptr_rx_antenna_id_ptr_setf(int elt_idx, uint16_t rxantennaidptr) +{ + BLE_ASSERT_ERR((((uint16_t)rxantennaidptr << 0) & ~((uint16_t)0x00003FFF)) == 0); + EM_BLE_WR(EM_BLE_RXDFANTSWPTR_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (uint16_t)rxantennaidptr << 0); +} + +/** + * @brief TXDFANTPATTCNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  06:00   TX_ANT_PATT_LENGTH   0x0
+ * 
+ */ +#define EM_BLE_TXDFANTPATTCNTL_ADDR (0x0091002A + EM_BLE_CS_OFFSET) +#define EM_BLE_TXDFANTPATTCNTL_INDEX 0x00000015 +#define EM_BLE_TXDFANTPATTCNTL_RESET 0x00000000 + +__INLINE uint16_t em_ble_txdfantpattcntl_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_TXDFANTPATTCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +__INLINE void em_ble_txdfantpattcntl_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_TXDFANTPATTCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, value); +} + +// field definitions +#define EM_BLE_TX_ANT_PATT_LENGTH_MASK ((uint16_t)0x0000007F) +#define EM_BLE_TX_ANT_PATT_LENGTH_LSB 0 +#define EM_BLE_TX_ANT_PATT_LENGTH_WIDTH ((uint16_t)0x00000007) + +#define EM_BLE_TX_ANT_PATT_LENGTH_RST 0x0 + +__INLINE uint8_t em_ble_txdfantpattcntl_tx_ant_patt_length_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXDFANTPATTCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000007F)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_txdfantpattcntl_tx_ant_patt_length_setf(int elt_idx, uint8_t txantpattlength) +{ + BLE_ASSERT_ERR((((uint16_t)txantpattlength << 0) & ~((uint16_t)0x0000007F)) == 0); + EM_BLE_WR(EM_BLE_TXDFANTPATTCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (uint16_t)txantpattlength << 0); +} + +/** + * @brief TXDFANTSWPTR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  13:00    TX_ANTENNA_ID_PTR   0x0
+ * 
+ */ +#define EM_BLE_TXDFANTSWPTR_ADDR (0x0091002C + EM_BLE_CS_OFFSET) +#define EM_BLE_TXDFANTSWPTR_INDEX 0x00000016 +#define EM_BLE_TXDFANTSWPTR_RESET 0x00000000 + +__INLINE uint16_t em_ble_txdfantswptr_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_TXDFANTSWPTR_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +__INLINE void em_ble_txdfantswptr_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_TXDFANTSWPTR_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, value); +} + +// field definitions +#define EM_BLE_TX_ANTENNA_ID_PTR_MASK ((uint16_t)0x00003FFF) +#define EM_BLE_TX_ANTENNA_ID_PTR_LSB 0 +#define EM_BLE_TX_ANTENNA_ID_PTR_WIDTH ((uint16_t)0x0000000E) + +#define EM_BLE_TX_ANTENNA_ID_PTR_RST 0x0 + +__INLINE uint16_t em_ble_txdfantswptr_tx_antenna_id_ptr_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXDFANTSWPTR_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x00003FFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_txdfantswptr_tx_antenna_id_ptr_setf(int elt_idx, uint16_t txantennaidptr) +{ + BLE_ASSERT_ERR((((uint16_t)txantennaidptr << 0) & ~((uint16_t)0x00003FFF)) == 0); + EM_BLE_WR(EM_BLE_TXDFANTSWPTR_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (uint16_t)txantennaidptr << 0); +} + +/** + * @brief WINOFFSET register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00            WINOFFSET   0x0
+ * 
+ */ +#define EM_BLE_WINOFFSET_ADDR (0x0091002E + EM_BLE_CS_OFFSET) +#define EM_BLE_WINOFFSET_INDEX 0x00000017 +#define EM_BLE_WINOFFSET_RESET 0x00000000 + +__INLINE uint16_t em_ble_winoffset_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_WINOFFSET_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +__INLINE void em_ble_winoffset_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_WINOFFSET_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, value); +} + +// field definitions +#define EM_BLE_WINOFFSET_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_WINOFFSET_LSB 0 +#define EM_BLE_WINOFFSET_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_WINOFFSET_RST 0x0 + +__INLINE uint16_t em_ble_winoffset_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_WINOFFSET_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_winoffset_setf(int elt_idx, uint16_t winoffset) +{ + BLE_ASSERT_ERR((((uint16_t)winoffset << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_WINOFFSET_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (uint16_t)winoffset << 0); +} + +/** + * @brief MINEVTIME register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00            MINEVTIME   0x0
+ * 
+ */ +#define EM_BLE_MINEVTIME_ADDR (0x0091002E + EM_BLE_CS_OFFSET) +#define EM_BLE_MINEVTIME_INDEX 0x00000017 +#define EM_BLE_MINEVTIME_RESET 0x00000000 + +__INLINE uint16_t em_ble_minevtime_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_MINEVTIME_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +__INLINE void em_ble_minevtime_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_MINEVTIME_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, value); +} + +// field definitions +#define EM_BLE_MINEVTIME_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_MINEVTIME_LSB 0 +#define EM_BLE_MINEVTIME_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_MINEVTIME_RST 0x0 + +__INLINE uint16_t em_ble_minevtime_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_MINEVTIME_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_minevtime_setf(int elt_idx, uint16_t minevtime) +{ + BLE_ASSERT_ERR((((uint16_t)minevtime << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_MINEVTIME_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (uint16_t)minevtime << 0); +} + +/** + * @brief MAXEVTIME register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00            MAXEVTIME   0x0
+ * 
+ */ +#define EM_BLE_MAXEVTIME_ADDR (0x00910030 + EM_BLE_CS_OFFSET) +#define EM_BLE_MAXEVTIME_INDEX 0x00000018 +#define EM_BLE_MAXEVTIME_RESET 0x00000000 + +__INLINE uint16_t em_ble_maxevtime_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_MAXEVTIME_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +__INLINE void em_ble_maxevtime_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_MAXEVTIME_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, value); +} + +// field definitions +#define EM_BLE_MAXEVTIME_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_MAXEVTIME_LSB 0 +#define EM_BLE_MAXEVTIME_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_MAXEVTIME_RST 0x0 + +__INLINE uint16_t em_ble_maxevtime_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_MAXEVTIME_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_maxevtime_setf(int elt_idx, uint16_t maxevtime) +{ + BLE_ASSERT_ERR((((uint16_t)maxevtime << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_MAXEVTIME_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (uint16_t)maxevtime << 0); +} + +/** + * @brief CONNINTERVAL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00         CONNINTERVAL   0x0
+ * 
+ */ +#define EM_BLE_CONNINTERVAL_ADDR (0x00910032 + EM_BLE_CS_OFFSET) +#define EM_BLE_CONNINTERVAL_INDEX 0x00000019 +#define EM_BLE_CONNINTERVAL_RESET 0x00000000 + +__INLINE uint16_t em_ble_conninterval_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_CONNINTERVAL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +__INLINE void em_ble_conninterval_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_CONNINTERVAL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, value); +} + +// field definitions +#define EM_BLE_CONNINTERVAL_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_CONNINTERVAL_LSB 0 +#define EM_BLE_CONNINTERVAL_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_CONNINTERVAL_RST 0x0 + +__INLINE uint16_t em_ble_conninterval_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_CONNINTERVAL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_conninterval_setf(int elt_idx, uint16_t conninterval) +{ + BLE_ASSERT_ERR((((uint16_t)conninterval << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_CONNINTERVAL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (uint16_t)conninterval << 0); +} + +/** + * @brief CHMAP0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00             LLCHMAP0   0xFFFF
+ * 
+ */ +#define EM_BLE_CHMAP0_ADDR (0x00910032 + EM_BLE_CS_OFFSET) +#define EM_BLE_CHMAP0_INDEX 0x00000019 +#define EM_BLE_CHMAP0_RESET 0x0000FFFF + +__INLINE uint16_t em_ble_chmap0_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_CHMAP0_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +__INLINE void em_ble_chmap0_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_CHMAP0_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, value); +} + +// field definitions +#define EM_BLE_LLCHMAP0_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_LLCHMAP0_LSB 0 +#define EM_BLE_LLCHMAP0_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_LLCHMAP0_RST 0xFFFF + +__INLINE uint16_t em_ble_chmap0_llchmap0_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_CHMAP0_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_chmap0_llchmap0_setf(int elt_idx, uint16_t llchmap0) +{ + BLE_ASSERT_ERR((((uint16_t)llchmap0 << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_CHMAP0_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (uint16_t)llchmap0 << 0); +} + +/** + * @brief CHMAP1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00             LLCHMAP1   0xFFFF
+ * 
+ */ +#define EM_BLE_CHMAP1_ADDR (0x00910034 + EM_BLE_CS_OFFSET) +#define EM_BLE_CHMAP1_INDEX 0x0000001A +#define EM_BLE_CHMAP1_RESET 0x0000FFFF + +__INLINE uint16_t em_ble_chmap1_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_CHMAP1_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +__INLINE void em_ble_chmap1_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_CHMAP1_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, value); +} + +// field definitions +#define EM_BLE_LLCHMAP1_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_LLCHMAP1_LSB 0 +#define EM_BLE_LLCHMAP1_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_LLCHMAP1_RST 0xFFFF + +__INLINE uint16_t em_ble_chmap1_llchmap1_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_CHMAP1_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_chmap1_llchmap1_setf(int elt_idx, uint16_t llchmap1) +{ + BLE_ASSERT_ERR((((uint16_t)llchmap1 << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_CHMAP1_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (uint16_t)llchmap1 << 0); +} + +/** + * @brief CHMAP2 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:10               CH_AUX   0x0
+ *  07:05             ADVCHMAP   0x7
+ *  04:00             LLCHMAP2   0x1F
+ * 
+ */ +#define EM_BLE_CHMAP2_ADDR (0x00910036 + EM_BLE_CS_OFFSET) +#define EM_BLE_CHMAP2_INDEX 0x0000001B +#define EM_BLE_CHMAP2_RESET 0x000000FF + +__INLINE uint16_t em_ble_chmap2_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_CHMAP2_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +__INLINE void em_ble_chmap2_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_CHMAP2_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, value); +} + +// field definitions +#define EM_BLE_CH_AUX_MASK ((uint16_t)0x0000FC00) +#define EM_BLE_CH_AUX_LSB 10 +#define EM_BLE_CH_AUX_WIDTH ((uint16_t)0x00000006) +#define EM_BLE_ADVCHMAP_MASK ((uint16_t)0x000000E0) +#define EM_BLE_ADVCHMAP_LSB 5 +#define EM_BLE_ADVCHMAP_WIDTH ((uint16_t)0x00000003) +#define EM_BLE_LLCHMAP2_MASK ((uint16_t)0x0000001F) +#define EM_BLE_LLCHMAP2_LSB 0 +#define EM_BLE_LLCHMAP2_WIDTH ((uint16_t)0x00000005) + +#define EM_BLE_CH_AUX_RST 0x0 +#define EM_BLE_ADVCHMAP_RST 0x7 +#define EM_BLE_LLCHMAP2_RST 0x1F + +__INLINE void em_ble_chmap2_pack(int elt_idx, uint8_t chaux, uint8_t advchmap, uint8_t llchmap2) +{ + BLE_ASSERT_ERR((((uint16_t)chaux << 10) & ~((uint16_t)0x0000FC00)) == 0); + BLE_ASSERT_ERR((((uint16_t)advchmap << 5) & ~((uint16_t)0x000000E0)) == 0); + BLE_ASSERT_ERR((((uint16_t)llchmap2 << 0) & ~((uint16_t)0x0000001F)) == 0); + EM_BLE_WR(EM_BLE_CHMAP2_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, ((uint16_t)chaux << 10) | ((uint16_t)advchmap << 5) | ((uint16_t)llchmap2 << 0)); +} + +__INLINE void em_ble_chmap2_unpack(int elt_idx, uint8_t* chaux, uint8_t* advchmap, uint8_t* llchmap2) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_CHMAP2_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + + *chaux = (localVal & ((uint16_t)0x0000FC00)) >> 10; + *advchmap = (localVal & ((uint16_t)0x000000E0)) >> 5; + *llchmap2 = (localVal & ((uint16_t)0x0000001F)) >> 0; +} + +__INLINE uint8_t em_ble_chmap2_ch_aux_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_CHMAP2_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x0000FC00)) >> 10); +} + +__INLINE void em_ble_chmap2_ch_aux_setf(int elt_idx, uint8_t chaux) +{ + BLE_ASSERT_ERR((((uint16_t)chaux << 10) & ~((uint16_t)0x0000FC00)) == 0); + EM_BLE_WR(EM_BLE_CHMAP2_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_CHMAP2_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x0000FC00)) | ((uint16_t)chaux << 10)); +} + +__INLINE uint8_t em_ble_chmap2_advchmap_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_CHMAP2_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x000000E0)) >> 5); +} + +__INLINE void em_ble_chmap2_advchmap_setf(int elt_idx, uint8_t advchmap) +{ + BLE_ASSERT_ERR((((uint16_t)advchmap << 5) & ~((uint16_t)0x000000E0)) == 0); + EM_BLE_WR(EM_BLE_CHMAP2_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_CHMAP2_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x000000E0)) | ((uint16_t)advchmap << 5)); +} + +__INLINE uint8_t em_ble_chmap2_llchmap2_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_CHMAP2_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x0000001F)) >> 0); +} + +__INLINE void em_ble_chmap2_llchmap2_setf(int elt_idx, uint8_t llchmap2) +{ + BLE_ASSERT_ERR((((uint16_t)llchmap2 << 0) & ~((uint16_t)0x0000001F)) == 0); + EM_BLE_WR(EM_BLE_CHMAP2_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_CHMAP2_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x0000001F)) | ((uint16_t)llchmap2 << 0)); +} + +/** + * @brief RXMAXAUXCHAIN register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:11          MAXRXCHDESC   0x0
+ *  10:00          MAXRXCHBYTE   0x0
+ * 
+ */ +#define EM_BLE_RXMAXAUXCHAIN_ADDR (0x00910038 + EM_BLE_CS_OFFSET) +#define EM_BLE_RXMAXAUXCHAIN_INDEX 0x0000001C +#define EM_BLE_RXMAXAUXCHAIN_RESET 0x00000000 + +__INLINE uint16_t em_ble_rxmaxauxchain_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_RXMAXAUXCHAIN_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +__INLINE void em_ble_rxmaxauxchain_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_RXMAXAUXCHAIN_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, value); +} + +// field definitions +#define EM_BLE_MAXRXCHDESC_MASK ((uint16_t)0x0000F800) +#define EM_BLE_MAXRXCHDESC_LSB 11 +#define EM_BLE_MAXRXCHDESC_WIDTH ((uint16_t)0x00000005) +#define EM_BLE_MAXRXCHBYTE_MASK ((uint16_t)0x000007FF) +#define EM_BLE_MAXRXCHBYTE_LSB 0 +#define EM_BLE_MAXRXCHBYTE_WIDTH ((uint16_t)0x0000000B) + +#define EM_BLE_MAXRXCHDESC_RST 0x0 +#define EM_BLE_MAXRXCHBYTE_RST 0x0 + +__INLINE void em_ble_rxmaxauxchain_pack(int elt_idx, uint8_t maxrxchdesc, uint16_t maxrxchbyte) +{ + BLE_ASSERT_ERR((((uint16_t)maxrxchdesc << 11) & ~((uint16_t)0x0000F800)) == 0); + BLE_ASSERT_ERR((((uint16_t)maxrxchbyte << 0) & ~((uint16_t)0x000007FF)) == 0); + EM_BLE_WR(EM_BLE_RXMAXAUXCHAIN_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, ((uint16_t)maxrxchdesc << 11) | ((uint16_t)maxrxchbyte << 0)); +} + +__INLINE void em_ble_rxmaxauxchain_unpack(int elt_idx, uint8_t* maxrxchdesc, uint16_t* maxrxchbyte) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXMAXAUXCHAIN_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + + *maxrxchdesc = (localVal & ((uint16_t)0x0000F800)) >> 11; + *maxrxchbyte = (localVal & ((uint16_t)0x000007FF)) >> 0; +} + +__INLINE uint8_t em_ble_rxmaxauxchain_maxrxchdesc_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXMAXAUXCHAIN_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x0000F800)) >> 11); +} + +__INLINE void em_ble_rxmaxauxchain_maxrxchdesc_setf(int elt_idx, uint8_t maxrxchdesc) +{ + BLE_ASSERT_ERR((((uint16_t)maxrxchdesc << 11) & ~((uint16_t)0x0000F800)) == 0); + EM_BLE_WR(EM_BLE_RXMAXAUXCHAIN_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_RXMAXAUXCHAIN_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x0000F800)) | ((uint16_t)maxrxchdesc << 11)); +} + +__INLINE uint16_t em_ble_rxmaxauxchain_maxrxchbyte_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXMAXAUXCHAIN_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x000007FF)) >> 0); +} + +__INLINE void em_ble_rxmaxauxchain_maxrxchbyte_setf(int elt_idx, uint16_t maxrxchbyte) +{ + BLE_ASSERT_ERR((((uint16_t)maxrxchbyte << 0) & ~((uint16_t)0x000007FF)) == 0); + EM_BLE_WR(EM_BLE_RXMAXAUXCHAIN_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_RXMAXAUXCHAIN_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x000007FF)) | ((uint16_t)maxrxchbyte << 0)); +} + +/** + * @brief RXMAXBUF register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:08          ISORXMAXBUF   0x0
+ *  07:00          ACLRXMAXBUF   0x0
+ * 
+ */ +#define EM_BLE_RXMAXBUF_ADDR (0x00910038 + EM_BLE_CS_OFFSET) +#define EM_BLE_RXMAXBUF_INDEX 0x0000001C +#define EM_BLE_RXMAXBUF_RESET 0x00000000 + +__INLINE uint16_t em_ble_rxmaxbuf_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_RXMAXBUF_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +__INLINE void em_ble_rxmaxbuf_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_RXMAXBUF_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, value); +} + +// field definitions +#define EM_BLE_ISORXMAXBUF_MASK ((uint16_t)0x0000FF00) +#define EM_BLE_ISORXMAXBUF_LSB 8 +#define EM_BLE_ISORXMAXBUF_WIDTH ((uint16_t)0x00000008) +#define EM_BLE_ACLRXMAXBUF_MASK ((uint16_t)0x000000FF) +#define EM_BLE_ACLRXMAXBUF_LSB 0 +#define EM_BLE_ACLRXMAXBUF_WIDTH ((uint16_t)0x00000008) + +#define EM_BLE_ISORXMAXBUF_RST 0x0 +#define EM_BLE_ACLRXMAXBUF_RST 0x0 + +__INLINE void em_ble_rxmaxbuf_pack(int elt_idx, uint8_t isorxmaxbuf, uint8_t aclrxmaxbuf) +{ + BLE_ASSERT_ERR((((uint16_t)isorxmaxbuf << 8) & ~((uint16_t)0x0000FF00)) == 0); + BLE_ASSERT_ERR((((uint16_t)aclrxmaxbuf << 0) & ~((uint16_t)0x000000FF)) == 0); + EM_BLE_WR(EM_BLE_RXMAXBUF_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, ((uint16_t)isorxmaxbuf << 8) | ((uint16_t)aclrxmaxbuf << 0)); +} + +__INLINE void em_ble_rxmaxbuf_unpack(int elt_idx, uint8_t* isorxmaxbuf, uint8_t* aclrxmaxbuf) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXMAXBUF_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + + *isorxmaxbuf = (localVal & ((uint16_t)0x0000FF00)) >> 8; + *aclrxmaxbuf = (localVal & ((uint16_t)0x000000FF)) >> 0; +} + +__INLINE uint8_t em_ble_rxmaxbuf_isorxmaxbuf_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXMAXBUF_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x0000FF00)) >> 8); +} + +__INLINE void em_ble_rxmaxbuf_isorxmaxbuf_setf(int elt_idx, uint8_t isorxmaxbuf) +{ + BLE_ASSERT_ERR((((uint16_t)isorxmaxbuf << 8) & ~((uint16_t)0x0000FF00)) == 0); + EM_BLE_WR(EM_BLE_RXMAXBUF_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_RXMAXBUF_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x0000FF00)) | ((uint16_t)isorxmaxbuf << 8)); +} + +__INLINE uint8_t em_ble_rxmaxbuf_aclrxmaxbuf_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXMAXBUF_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x000000FF)) >> 0); +} + +__INLINE void em_ble_rxmaxbuf_aclrxmaxbuf_setf(int elt_idx, uint8_t aclrxmaxbuf) +{ + BLE_ASSERT_ERR((((uint16_t)aclrxmaxbuf << 0) & ~((uint16_t)0x000000FF)) == 0); + EM_BLE_WR(EM_BLE_RXMAXBUF_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_RXMAXBUF_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x000000FF)) | ((uint16_t)aclrxmaxbuf << 0)); +} + +/** + * @brief RXMAXTIME register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  12:00            RXMAXTIME   0x0
+ * 
+ */ +#define EM_BLE_RXMAXTIME_ADDR (0x0091003A + EM_BLE_CS_OFFSET) +#define EM_BLE_RXMAXTIME_INDEX 0x0000001D +#define EM_BLE_RXMAXTIME_RESET 0x00000000 + +__INLINE uint16_t em_ble_rxmaxtime_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_RXMAXTIME_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +__INLINE void em_ble_rxmaxtime_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_RXMAXTIME_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, value); +} + +// field definitions +#define EM_BLE_RXMAXTIME_MASK ((uint16_t)0x00001FFF) +#define EM_BLE_RXMAXTIME_LSB 0 +#define EM_BLE_RXMAXTIME_WIDTH ((uint16_t)0x0000000D) + +#define EM_BLE_RXMAXTIME_RST 0x0 + +__INLINE uint16_t em_ble_rxmaxtime_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXMAXTIME_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x00001FFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_rxmaxtime_setf(int elt_idx, uint16_t rxmaxtime) +{ + BLE_ASSERT_ERR((((uint16_t)rxmaxtime << 0) & ~((uint16_t)0x00001FFF)) == 0); + EM_BLE_WR(EM_BLE_RXMAXTIME_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (uint16_t)rxmaxtime << 0); +} + +/** + * @brief SK register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00                   SK   0x0
+ * 
+ */ +#define EM_BLE_SK_ADDR (0x0091003C + EM_BLE_CS_OFFSET) +#define EM_BLE_SK_INDEX 0x0000001E +#define EM_BLE_SK_RESET 0x00000000 +#define EM_BLE_SK_COUNT 8 + +__INLINE uint16_t em_ble_sk_get(int elt_idx, int reg_idx) +{ + BLE_ASSERT_ERR(reg_idx <= 7); + return EM_BLE_RD(EM_BLE_SK_ADDR + elt_idx * REG_EM_BLE_CS_SIZE + reg_idx * 2); +} + +__INLINE void em_ble_sk_set(int elt_idx, int reg_idx, uint16_t value) +{ + BLE_ASSERT_ERR(reg_idx <= 7); + EM_BLE_WR(EM_BLE_SK_ADDR + elt_idx * REG_EM_BLE_CS_SIZE + reg_idx * 2, value); +} + +// field definitions +#define EM_BLE_SK_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_SK_LSB 0 +#define EM_BLE_SK_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_SK_RST 0x0 + +__INLINE uint16_t em_ble_sk_getf(int elt_idx, int reg_idx) +{ + BLE_ASSERT_ERR(reg_idx <= 7); + uint16_t localVal = EM_BLE_RD(EM_BLE_SK_ADDR + elt_idx * REG_EM_BLE_CS_SIZE + reg_idx * 2); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_sk_setf(int elt_idx, int reg_idx, uint16_t sk) +{ + BLE_ASSERT_ERR(reg_idx <= 7); + BLE_ASSERT_ERR((((uint16_t)sk << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_SK_ADDR + elt_idx * REG_EM_BLE_CS_SIZE + reg_idx * 2, (uint16_t)sk << 0); +} + +/** + * @brief ADV_BD_ADDR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00          ADV_BD_ADDR   0x0
+ * 
+ */ +#define EM_BLE_ADV_BD_ADDR_ADDR (0x0091003C + EM_BLE_CS_OFFSET) +#define EM_BLE_ADV_BD_ADDR_INDEX 0x0000001E +#define EM_BLE_ADV_BD_ADDR_RESET 0x00000000 +#define EM_BLE_ADV_BD_ADDR_COUNT 3 + +__INLINE uint16_t em_ble_adv_bd_addr_get(int elt_idx, int reg_idx) +{ + BLE_ASSERT_ERR(reg_idx <= 2); + return EM_BLE_RD(EM_BLE_ADV_BD_ADDR_ADDR + elt_idx * REG_EM_BLE_CS_SIZE + reg_idx * 2); +} + +__INLINE void em_ble_adv_bd_addr_set(int elt_idx, int reg_idx, uint16_t value) +{ + BLE_ASSERT_ERR(reg_idx <= 2); + EM_BLE_WR(EM_BLE_ADV_BD_ADDR_ADDR + elt_idx * REG_EM_BLE_CS_SIZE + reg_idx * 2, value); +} + +// field definitions +#define EM_BLE_ADV_BD_ADDR_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_ADV_BD_ADDR_LSB 0 +#define EM_BLE_ADV_BD_ADDR_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_ADV_BD_ADDR_RST 0x0 + +__INLINE uint16_t em_ble_adv_bd_addr_getf(int elt_idx, int reg_idx) +{ + BLE_ASSERT_ERR(reg_idx <= 2); + uint16_t localVal = EM_BLE_RD(EM_BLE_ADV_BD_ADDR_ADDR + elt_idx * REG_EM_BLE_CS_SIZE + reg_idx * 2); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_adv_bd_addr_setf(int elt_idx, int reg_idx, uint16_t advbdaddr) +{ + BLE_ASSERT_ERR(reg_idx <= 2); + BLE_ASSERT_ERR((((uint16_t)advbdaddr << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_ADV_BD_ADDR_ADDR + elt_idx * REG_EM_BLE_CS_SIZE + reg_idx * 2, (uint16_t)advbdaddr << 0); +} + +/** + * @brief PEER_RALPTR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  13:00          PEER_RALPTR   0x0
+ * 
+ */ +#define EM_BLE_PEER_RALPTR_ADDR (0x0091003C + EM_BLE_CS_OFFSET) +#define EM_BLE_PEER_RALPTR_INDEX 0x0000001E +#define EM_BLE_PEER_RALPTR_RESET 0x00000000 + +__INLINE uint16_t em_ble_peer_ralptr_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_PEER_RALPTR_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +__INLINE void em_ble_peer_ralptr_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_PEER_RALPTR_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, value); +} + +// field definitions +#define EM_BLE_PEER_RALPTR_MASK ((uint16_t)0x00003FFF) +#define EM_BLE_PEER_RALPTR_LSB 0 +#define EM_BLE_PEER_RALPTR_WIDTH ((uint16_t)0x0000000E) + +#define EM_BLE_PEER_RALPTR_RST 0x0 + +__INLINE uint16_t em_ble_peer_ralptr_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_PEER_RALPTR_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x00003FFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_peer_ralptr_setf(int elt_idx, uint16_t peerralptr) +{ + BLE_ASSERT_ERR((((uint16_t)peerralptr << 0) & ~((uint16_t)0x00003FFF)) == 0); + EM_BLE_WR(EM_BLE_PEER_RALPTR_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (uint16_t)peerralptr << 0); +} + +/** + * @brief ADV_BD_ADDR_TYPE register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     00     ADV_BD_ADDR_TYPE   0
+ * 
+ */ +#define EM_BLE_ADV_BD_ADDR_TYPE_ADDR (0x00910042 + EM_BLE_CS_OFFSET) +#define EM_BLE_ADV_BD_ADDR_TYPE_INDEX 0x00000021 +#define EM_BLE_ADV_BD_ADDR_TYPE_RESET 0x00000000 + +__INLINE uint16_t em_ble_adv_bd_addr_type_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_ADV_BD_ADDR_TYPE_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +__INLINE void em_ble_adv_bd_addr_type_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_ADV_BD_ADDR_TYPE_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, value); +} + +// field definitions +#define EM_BLE_ADV_BD_ADDR_TYPE_BIT ((uint16_t)0x00000001) +#define EM_BLE_ADV_BD_ADDR_TYPE_POS 0 + +#define EM_BLE_ADV_BD_ADDR_TYPE_RST 0x0 + +__INLINE uint8_t em_ble_adv_bd_addr_type_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_ADV_BD_ADDR_TYPE_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x00000001)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_adv_bd_addr_type_setf(int elt_idx, uint8_t advbdaddrtype) +{ + BLE_ASSERT_ERR((((uint16_t)advbdaddrtype << 0) & ~((uint16_t)0x00000001)) == 0); + EM_BLE_WR(EM_BLE_ADV_BD_ADDR_TYPE_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (uint16_t)advbdaddrtype << 0); +} + +/** + * @brief AUXTXDESCPTR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  13:00         AUXTXDESCPTR   0x0
+ * 
+ */ +#define EM_BLE_AUXTXDESCPTR_ADDR (0x00910044 + EM_BLE_CS_OFFSET) +#define EM_BLE_AUXTXDESCPTR_INDEX 0x00000022 +#define EM_BLE_AUXTXDESCPTR_RESET 0x00000000 + +__INLINE uint16_t em_ble_auxtxdescptr_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_AUXTXDESCPTR_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +__INLINE void em_ble_auxtxdescptr_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_AUXTXDESCPTR_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, value); +} + +// field definitions +#define EM_BLE_AUXTXDESCPTR_MASK ((uint16_t)0x00003FFF) +#define EM_BLE_AUXTXDESCPTR_LSB 0 +#define EM_BLE_AUXTXDESCPTR_WIDTH ((uint16_t)0x0000000E) + +#define EM_BLE_AUXTXDESCPTR_RST 0x0 + +__INLINE uint16_t em_ble_auxtxdescptr_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_AUXTXDESCPTR_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x00003FFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_auxtxdescptr_setf(int elt_idx, uint16_t auxtxdescptr) +{ + BLE_ASSERT_ERR((((uint16_t)auxtxdescptr << 0) & ~((uint16_t)0x00003FFF)) == 0); + EM_BLE_WR(EM_BLE_AUXTXDESCPTR_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (uint16_t)auxtxdescptr << 0); +} + +/** + * @brief IV register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00                   IV   0x0
+ * 
+ */ +#define EM_BLE_IV_ADDR (0x0091004C + EM_BLE_CS_OFFSET) +#define EM_BLE_IV_INDEX 0x00000026 +#define EM_BLE_IV_RESET 0x00000000 +#define EM_BLE_IV_COUNT 4 + +__INLINE uint16_t em_ble_iv_get(int elt_idx, int reg_idx) +{ + BLE_ASSERT_ERR(reg_idx <= 3); + return EM_BLE_RD(EM_BLE_IV_ADDR + elt_idx * REG_EM_BLE_CS_SIZE + reg_idx * 2); +} + +__INLINE void em_ble_iv_set(int elt_idx, int reg_idx, uint16_t value) +{ + BLE_ASSERT_ERR(reg_idx <= 3); + EM_BLE_WR(EM_BLE_IV_ADDR + elt_idx * REG_EM_BLE_CS_SIZE + reg_idx * 2, value); +} + +// field definitions +#define EM_BLE_IV_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_IV_LSB 0 +#define EM_BLE_IV_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_IV_RST 0x0 + +__INLINE uint16_t em_ble_iv_getf(int elt_idx, int reg_idx) +{ + BLE_ASSERT_ERR(reg_idx <= 3); + uint16_t localVal = EM_BLE_RD(EM_BLE_IV_ADDR + elt_idx * REG_EM_BLE_CS_SIZE + reg_idx * 2); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_iv_setf(int elt_idx, int reg_idx, uint16_t iv) +{ + BLE_ASSERT_ERR(reg_idx <= 3); + BLE_ASSERT_ERR((((uint16_t)iv << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_IV_ADDR + elt_idx * REG_EM_BLE_CS_SIZE + reg_idx * 2, (uint16_t)iv << 0); +} + +/** + * @brief WINOFFSET_2M register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00         WINOFFSET_2M   0x0
+ * 
+ */ +#define EM_BLE_WINOFFSET_2M_ADDR (0x00910046 + EM_BLE_CS_OFFSET) +#define EM_BLE_WINOFFSET_2M_INDEX 0x00000023 +#define EM_BLE_WINOFFSET_2M_RESET 0x00000000 + +__INLINE uint16_t em_ble_winoffset_2m_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_WINOFFSET_2M_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +__INLINE void em_ble_winoffset_2m_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_WINOFFSET_2M_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, value); +} + +// field definitions +#define EM_BLE_WINOFFSET_2M_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_WINOFFSET_2M_LSB 0 +#define EM_BLE_WINOFFSET_2M_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_WINOFFSET_2M_RST 0x0 + +__INLINE uint16_t em_ble_winoffset_2m_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_WINOFFSET_2M_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_winoffset_2m_setf(int elt_idx, uint16_t winoffset2m) +{ + BLE_ASSERT_ERR((((uint16_t)winoffset2m << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_WINOFFSET_2M_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (uint16_t)winoffset2m << 0); +} + +/** + * @brief CONNINTERVAL_2M register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00      CONNINTERVAL_2M   0x0
+ * 
+ */ +#define EM_BLE_CONNINTERVAL_2M_ADDR (0x00910048 + EM_BLE_CS_OFFSET) +#define EM_BLE_CONNINTERVAL_2M_INDEX 0x00000024 +#define EM_BLE_CONNINTERVAL_2M_RESET 0x00000000 + +__INLINE uint16_t em_ble_conninterval_2m_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_CONNINTERVAL_2M_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +__INLINE void em_ble_conninterval_2m_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_CONNINTERVAL_2M_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, value); +} + +// field definitions +#define EM_BLE_CONNINTERVAL_2M_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_CONNINTERVAL_2M_LSB 0 +#define EM_BLE_CONNINTERVAL_2M_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_CONNINTERVAL_2M_RST 0x0 + +__INLINE uint16_t em_ble_conninterval_2m_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_CONNINTERVAL_2M_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_conninterval_2m_setf(int elt_idx, uint16_t conninterval2m) +{ + BLE_ASSERT_ERR((((uint16_t)conninterval2m << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_CONNINTERVAL_2M_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (uint16_t)conninterval2m << 0); +} + +/** + * @brief WINOFFSET_LR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00         WINOFFSET_LR   0x0
+ * 
+ */ +#define EM_BLE_WINOFFSET_LR_ADDR (0x0091004A + EM_BLE_CS_OFFSET) +#define EM_BLE_WINOFFSET_LR_INDEX 0x00000025 +#define EM_BLE_WINOFFSET_LR_RESET 0x00000000 + +__INLINE uint16_t em_ble_winoffset_lr_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_WINOFFSET_LR_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +__INLINE void em_ble_winoffset_lr_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_WINOFFSET_LR_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, value); +} + +// field definitions +#define EM_BLE_WINOFFSET_LR_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_WINOFFSET_LR_LSB 0 +#define EM_BLE_WINOFFSET_LR_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_WINOFFSET_LR_RST 0x0 + +__INLINE uint16_t em_ble_winoffset_lr_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_WINOFFSET_LR_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_winoffset_lr_setf(int elt_idx, uint16_t winoffsetlr) +{ + BLE_ASSERT_ERR((((uint16_t)winoffsetlr << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_WINOFFSET_LR_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (uint16_t)winoffsetlr << 0); +} + +/** + * @brief CONNINTERVAL_LR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00      CONNINTERVAL_LR   0x0
+ * 
+ */ +#define EM_BLE_CONNINTERVAL_LR_ADDR (0x0091004C + EM_BLE_CS_OFFSET) +#define EM_BLE_CONNINTERVAL_LR_INDEX 0x00000026 +#define EM_BLE_CONNINTERVAL_LR_RESET 0x00000000 + +__INLINE uint16_t em_ble_conninterval_lr_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_CONNINTERVAL_LR_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +__INLINE void em_ble_conninterval_lr_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_CONNINTERVAL_LR_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, value); +} + +// field definitions +#define EM_BLE_CONNINTERVAL_LR_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_CONNINTERVAL_LR_LSB 0 +#define EM_BLE_CONNINTERVAL_LR_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_CONNINTERVAL_LR_RST 0x0 + +__INLINE uint16_t em_ble_conninterval_lr_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_CONNINTERVAL_LR_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_conninterval_lr_setf(int elt_idx, uint16_t connintervallr) +{ + BLE_ASSERT_ERR((((uint16_t)connintervallr << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_CONNINTERVAL_LR_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (uint16_t)connintervallr << 0); +} + +/** + * @brief TXWINOFFSET register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00          TXWINOFFSET   0x0
+ * 
+ */ +#define EM_BLE_TXWINOFFSET_ADDR (0x00910054 + EM_BLE_CS_OFFSET) +#define EM_BLE_TXWINOFFSET_INDEX 0x0000002A +#define EM_BLE_TXWINOFFSET_RESET 0x00000000 + +__INLINE uint16_t em_ble_txwinoffset_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_TXWINOFFSET_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +__INLINE void em_ble_txwinoffset_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_TXWINOFFSET_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, value); +} + +// field definitions +#define EM_BLE_TXWINOFFSET_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_TXWINOFFSET_LSB 0 +#define EM_BLE_TXWINOFFSET_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_TXWINOFFSET_RST 0x0 + +__INLINE uint16_t em_ble_txwinoffset_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXWINOFFSET_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_txwinoffset_setf(int elt_idx, uint16_t txwinoffset) +{ + BLE_ASSERT_ERR((((uint16_t)txwinoffset << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_TXWINOFFSET_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (uint16_t)txwinoffset << 0); +} + +/** + * @brief TXCCMPKTCNT0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00         TXCCMPKTCNT0   0x0
+ * 
+ */ +#define EM_BLE_TXCCMPKTCNT0_ADDR (0x00910054 + EM_BLE_CS_OFFSET) +#define EM_BLE_TXCCMPKTCNT0_INDEX 0x0000002A +#define EM_BLE_TXCCMPKTCNT0_RESET 0x00000000 + +__INLINE uint16_t em_ble_txccmpktcnt0_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_TXCCMPKTCNT0_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +__INLINE void em_ble_txccmpktcnt0_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_TXCCMPKTCNT0_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, value); +} + +// field definitions +#define EM_BLE_TXCCMPKTCNT0_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_TXCCMPKTCNT0_LSB 0 +#define EM_BLE_TXCCMPKTCNT0_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_TXCCMPKTCNT0_RST 0x0 + +__INLINE uint16_t em_ble_txccmpktcnt0_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXCCMPKTCNT0_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_txccmpktcnt0_setf(int elt_idx, uint16_t txccmpktcnt0) +{ + BLE_ASSERT_ERR((((uint16_t)txccmpktcnt0 << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_TXCCMPKTCNT0_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (uint16_t)txccmpktcnt0 << 0); +} + +/** + * @brief EXTADVSTAT register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     07             PREV_CTE   0
+ *     06             PREV_PAM   0
+ *     05             PREV_LAM   0
+ *  04:03        PREV_ADV_MODE   0x0
+ *  02:00    PREV_ADV_PKT_TYPE   0x0
+ * 
+ */ +#define EM_BLE_EXTADVSTAT_ADDR (0x00910056 + EM_BLE_CS_OFFSET) +#define EM_BLE_EXTADVSTAT_INDEX 0x0000002B +#define EM_BLE_EXTADVSTAT_RESET 0x00000000 + +__INLINE uint16_t em_ble_extadvstat_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_EXTADVSTAT_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +__INLINE void em_ble_extadvstat_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_EXTADVSTAT_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, value); +} + +// field definitions +#define EM_BLE_PREV_CTE_BIT ((uint16_t)0x00000080) +#define EM_BLE_PREV_CTE_POS 7 +#define EM_BLE_PREV_PAM_BIT ((uint16_t)0x00000040) +#define EM_BLE_PREV_PAM_POS 6 +#define EM_BLE_PREV_LAM_BIT ((uint16_t)0x00000020) +#define EM_BLE_PREV_LAM_POS 5 +#define EM_BLE_PREV_ADV_MODE_MASK ((uint16_t)0x00000018) +#define EM_BLE_PREV_ADV_MODE_LSB 3 +#define EM_BLE_PREV_ADV_MODE_WIDTH ((uint16_t)0x00000002) +#define EM_BLE_PREV_ADV_PKT_TYPE_MASK ((uint16_t)0x00000007) +#define EM_BLE_PREV_ADV_PKT_TYPE_LSB 0 +#define EM_BLE_PREV_ADV_PKT_TYPE_WIDTH ((uint16_t)0x00000003) + +#define EM_BLE_PREV_CTE_RST 0x0 +#define EM_BLE_PREV_PAM_RST 0x0 +#define EM_BLE_PREV_LAM_RST 0x0 +#define EM_BLE_PREV_ADV_MODE_RST 0x0 +#define EM_BLE_PREV_ADV_PKT_TYPE_RST 0x0 + +__INLINE void em_ble_extadvstat_pack(int elt_idx, uint8_t prevcte, uint8_t prevpam, uint8_t prevlam, uint8_t prevadvmode, uint8_t prevadvpkttype) +{ + BLE_ASSERT_ERR((((uint16_t)prevcte << 7) & ~((uint16_t)0x00000080)) == 0); + BLE_ASSERT_ERR((((uint16_t)prevpam << 6) & ~((uint16_t)0x00000040)) == 0); + BLE_ASSERT_ERR((((uint16_t)prevlam << 5) & ~((uint16_t)0x00000020)) == 0); + BLE_ASSERT_ERR((((uint16_t)prevadvmode << 3) & ~((uint16_t)0x00000018)) == 0); + BLE_ASSERT_ERR((((uint16_t)prevadvpkttype << 0) & ~((uint16_t)0x00000007)) == 0); + EM_BLE_WR(EM_BLE_EXTADVSTAT_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, ((uint16_t)prevcte << 7) | ((uint16_t)prevpam << 6) | ((uint16_t)prevlam << 5) | ((uint16_t)prevadvmode << 3) | ((uint16_t)prevadvpkttype << 0)); +} + +__INLINE void em_ble_extadvstat_unpack(int elt_idx, uint8_t* prevcte, uint8_t* prevpam, uint8_t* prevlam, uint8_t* prevadvmode, uint8_t* prevadvpkttype) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_EXTADVSTAT_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + + *prevcte = (localVal & ((uint16_t)0x00000080)) >> 7; + *prevpam = (localVal & ((uint16_t)0x00000040)) >> 6; + *prevlam = (localVal & ((uint16_t)0x00000020)) >> 5; + *prevadvmode = (localVal & ((uint16_t)0x00000018)) >> 3; + *prevadvpkttype = (localVal & ((uint16_t)0x00000007)) >> 0; +} + +__INLINE uint8_t em_ble_extadvstat_prev_cte_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_EXTADVSTAT_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00000080)) >> 7); +} + +__INLINE void em_ble_extadvstat_prev_cte_setf(int elt_idx, uint8_t prevcte) +{ + BLE_ASSERT_ERR((((uint16_t)prevcte << 7) & ~((uint16_t)0x00000080)) == 0); + EM_BLE_WR(EM_BLE_EXTADVSTAT_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_EXTADVSTAT_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00000080)) | ((uint16_t)prevcte << 7)); +} + +__INLINE uint8_t em_ble_extadvstat_prev_pam_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_EXTADVSTAT_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00000040)) >> 6); +} + +__INLINE void em_ble_extadvstat_prev_pam_setf(int elt_idx, uint8_t prevpam) +{ + BLE_ASSERT_ERR((((uint16_t)prevpam << 6) & ~((uint16_t)0x00000040)) == 0); + EM_BLE_WR(EM_BLE_EXTADVSTAT_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_EXTADVSTAT_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00000040)) | ((uint16_t)prevpam << 6)); +} + +__INLINE uint8_t em_ble_extadvstat_prev_lam_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_EXTADVSTAT_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00000020)) >> 5); +} + +__INLINE void em_ble_extadvstat_prev_lam_setf(int elt_idx, uint8_t prevlam) +{ + BLE_ASSERT_ERR((((uint16_t)prevlam << 5) & ~((uint16_t)0x00000020)) == 0); + EM_BLE_WR(EM_BLE_EXTADVSTAT_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_EXTADVSTAT_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00000020)) | ((uint16_t)prevlam << 5)); +} + +__INLINE uint8_t em_ble_extadvstat_prev_adv_mode_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_EXTADVSTAT_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00000018)) >> 3); +} + +__INLINE void em_ble_extadvstat_prev_adv_mode_setf(int elt_idx, uint8_t prevadvmode) +{ + BLE_ASSERT_ERR((((uint16_t)prevadvmode << 3) & ~((uint16_t)0x00000018)) == 0); + EM_BLE_WR(EM_BLE_EXTADVSTAT_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_EXTADVSTAT_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00000018)) | ((uint16_t)prevadvmode << 3)); +} + +__INLINE uint8_t em_ble_extadvstat_prev_adv_pkt_type_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_EXTADVSTAT_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00000007)) >> 0); +} + +__INLINE void em_ble_extadvstat_prev_adv_pkt_type_setf(int elt_idx, uint8_t prevadvpkttype) +{ + BLE_ASSERT_ERR((((uint16_t)prevadvpkttype << 0) & ~((uint16_t)0x00000007)) == 0); + EM_BLE_WR(EM_BLE_EXTADVSTAT_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_EXTADVSTAT_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00000007)) | ((uint16_t)prevadvpkttype << 0)); +} + +/** + * @brief TXCCMPKTCNT1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00         TXCCMPKTCNT1   0x0
+ * 
+ */ +#define EM_BLE_TXCCMPKTCNT1_ADDR (0x00910056 + EM_BLE_CS_OFFSET) +#define EM_BLE_TXCCMPKTCNT1_INDEX 0x0000002B +#define EM_BLE_TXCCMPKTCNT1_RESET 0x00000000 + +__INLINE uint16_t em_ble_txccmpktcnt1_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_TXCCMPKTCNT1_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +__INLINE void em_ble_txccmpktcnt1_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_TXCCMPKTCNT1_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, value); +} + +// field definitions +#define EM_BLE_TXCCMPKTCNT1_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_TXCCMPKTCNT1_LSB 0 +#define EM_BLE_TXCCMPKTCNT1_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_TXCCMPKTCNT1_RST 0x0 + +__INLINE uint16_t em_ble_txccmpktcnt1_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXCCMPKTCNT1_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_txccmpktcnt1_setf(int elt_idx, uint16_t txccmpktcnt1) +{ + BLE_ASSERT_ERR((((uint16_t)txccmpktcnt1 << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_TXCCMPKTCNT1_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (uint16_t)txccmpktcnt1 << 0); +} + +/** + * @brief TXCCMPKTCNT2 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  06:00         TXCCMPKTCNT2   0x0
+ * 
+ */ +#define EM_BLE_TXCCMPKTCNT2_ADDR (0x00910058 + EM_BLE_CS_OFFSET) +#define EM_BLE_TXCCMPKTCNT2_INDEX 0x0000002C +#define EM_BLE_TXCCMPKTCNT2_RESET 0x00000000 + +__INLINE uint16_t em_ble_txccmpktcnt2_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_TXCCMPKTCNT2_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +__INLINE void em_ble_txccmpktcnt2_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_TXCCMPKTCNT2_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, value); +} + +// field definitions +#define EM_BLE_TXCCMPKTCNT2_MASK ((uint16_t)0x0000007F) +#define EM_BLE_TXCCMPKTCNT2_LSB 0 +#define EM_BLE_TXCCMPKTCNT2_WIDTH ((uint16_t)0x00000007) + +#define EM_BLE_TXCCMPKTCNT2_RST 0x0 + +__INLINE uint8_t em_ble_txccmpktcnt2_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXCCMPKTCNT2_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000007F)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_txccmpktcnt2_setf(int elt_idx, uint8_t txccmpktcnt2) +{ + BLE_ASSERT_ERR((((uint16_t)txccmpktcnt2 << 0) & ~((uint16_t)0x0000007F)) == 0); + EM_BLE_WR(EM_BLE_TXCCMPKTCNT2_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (uint16_t)txccmpktcnt2 << 0); +} + +/** + * @brief RXCCMPKTCNT0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00         RXCCMPKTCNT0   0x0
+ * 
+ */ +#define EM_BLE_RXCCMPKTCNT0_ADDR (0x0091005A + EM_BLE_CS_OFFSET) +#define EM_BLE_RXCCMPKTCNT0_INDEX 0x0000002D +#define EM_BLE_RXCCMPKTCNT0_RESET 0x00000000 + +__INLINE uint16_t em_ble_rxccmpktcnt0_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_RXCCMPKTCNT0_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +__INLINE void em_ble_rxccmpktcnt0_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_RXCCMPKTCNT0_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, value); +} + +// field definitions +#define EM_BLE_RXCCMPKTCNT0_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_RXCCMPKTCNT0_LSB 0 +#define EM_BLE_RXCCMPKTCNT0_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_RXCCMPKTCNT0_RST 0x0 + +__INLINE uint16_t em_ble_rxccmpktcnt0_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXCCMPKTCNT0_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_rxccmpktcnt0_setf(int elt_idx, uint16_t rxccmpktcnt0) +{ + BLE_ASSERT_ERR((((uint16_t)rxccmpktcnt0 << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_RXCCMPKTCNT0_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (uint16_t)rxccmpktcnt0 << 0); +} + +/** + * @brief RXCCMPKTCNT1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00         RXCCMPKTCNT1   0x0
+ * 
+ */ +#define EM_BLE_RXCCMPKTCNT1_ADDR (0x0091005C + EM_BLE_CS_OFFSET) +#define EM_BLE_RXCCMPKTCNT1_INDEX 0x0000002E +#define EM_BLE_RXCCMPKTCNT1_RESET 0x00000000 + +__INLINE uint16_t em_ble_rxccmpktcnt1_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_RXCCMPKTCNT1_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +__INLINE void em_ble_rxccmpktcnt1_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_RXCCMPKTCNT1_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, value); +} + +// field definitions +#define EM_BLE_RXCCMPKTCNT1_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_RXCCMPKTCNT1_LSB 0 +#define EM_BLE_RXCCMPKTCNT1_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_RXCCMPKTCNT1_RST 0x0 + +__INLINE uint16_t em_ble_rxccmpktcnt1_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXCCMPKTCNT1_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_rxccmpktcnt1_setf(int elt_idx, uint16_t rxccmpktcnt1) +{ + BLE_ASSERT_ERR((((uint16_t)rxccmpktcnt1 << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_RXCCMPKTCNT1_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (uint16_t)rxccmpktcnt1 << 0); +} + +/** + * @brief RXCCMPKTCNT2 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  06:00         RXCCMPKTCNT2   0x0
+ * 
+ */ +#define EM_BLE_RXCCMPKTCNT2_ADDR (0x0091005E + EM_BLE_CS_OFFSET) +#define EM_BLE_RXCCMPKTCNT2_INDEX 0x0000002F +#define EM_BLE_RXCCMPKTCNT2_RESET 0x00000000 + +__INLINE uint16_t em_ble_rxccmpktcnt2_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_RXCCMPKTCNT2_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +__INLINE void em_ble_rxccmpktcnt2_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_RXCCMPKTCNT2_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, value); +} + +// field definitions +#define EM_BLE_RXCCMPKTCNT2_MASK ((uint16_t)0x0000007F) +#define EM_BLE_RXCCMPKTCNT2_LSB 0 +#define EM_BLE_RXCCMPKTCNT2_WIDTH ((uint16_t)0x00000007) + +#define EM_BLE_RXCCMPKTCNT2_RST 0x0 + +__INLINE uint8_t em_ble_rxccmpktcnt2_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXCCMPKTCNT2_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000007F)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_rxccmpktcnt2_setf(int elt_idx, uint8_t rxccmpktcnt2) +{ + BLE_ASSERT_ERR((((uint16_t)rxccmpktcnt2 << 0) & ~((uint16_t)0x0000007F)) == 0); + EM_BLE_WR(EM_BLE_RXCCMPKTCNT2_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (uint16_t)rxccmpktcnt2 << 0); +} + +/** + * @brief EVTCNT register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00               EVTCNT   0x0
+ * 
+ */ +#define EM_BLE_EVTCNT_ADDR (0x00910060 + EM_BLE_CS_OFFSET) +#define EM_BLE_EVTCNT_INDEX 0x00000030 +#define EM_BLE_EVTCNT_RESET 0x00000000 + +__INLINE uint16_t em_ble_evtcnt_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_EVTCNT_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +__INLINE void em_ble_evtcnt_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_EVTCNT_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, value); +} + +// field definitions +#define EM_BLE_EVTCNT_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_EVTCNT_LSB 0 +#define EM_BLE_EVTCNT_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_EVTCNT_RST 0x0 + +__INLINE uint16_t em_ble_evtcnt_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_EVTCNT_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_evtcnt_setf(int elt_idx, uint16_t evtcnt) +{ + BLE_ASSERT_ERR((((uint16_t)evtcnt << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_EVTCNT_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (uint16_t)evtcnt << 0); +} + +/** + * @brief EVTCNT_OFFSET0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00       EVTCNT_OFFSET0   0x0
+ * 
+ */ +#define EM_BLE_EVTCNT_OFFSET0_ADDR (0x00910062 + EM_BLE_CS_OFFSET) +#define EM_BLE_EVTCNT_OFFSET0_INDEX 0x00000031 +#define EM_BLE_EVTCNT_OFFSET0_RESET 0x00000000 + +__INLINE uint16_t em_ble_evtcnt_offset0_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_EVTCNT_OFFSET0_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +__INLINE void em_ble_evtcnt_offset0_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_EVTCNT_OFFSET0_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, value); +} + +// field definitions +#define EM_BLE_EVTCNT_OFFSET0_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_EVTCNT_OFFSET0_LSB 0 +#define EM_BLE_EVTCNT_OFFSET0_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_EVTCNT_OFFSET0_RST 0x0 + +__INLINE uint16_t em_ble_evtcnt_offset0_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_EVTCNT_OFFSET0_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_evtcnt_offset0_setf(int elt_idx, uint16_t evtcntoffset0) +{ + BLE_ASSERT_ERR((((uint16_t)evtcntoffset0 << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_EVTCNT_OFFSET0_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (uint16_t)evtcntoffset0 << 0); +} + +/** + * @brief EVTCNT_OFFSET1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00       EVTCNT_OFFSET1   0x0
+ * 
+ */ +#define EM_BLE_EVTCNT_OFFSET1_ADDR (0x00910064 + EM_BLE_CS_OFFSET) +#define EM_BLE_EVTCNT_OFFSET1_INDEX 0x00000032 +#define EM_BLE_EVTCNT_OFFSET1_RESET 0x00000000 + +__INLINE uint16_t em_ble_evtcnt_offset1_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_EVTCNT_OFFSET1_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +__INLINE void em_ble_evtcnt_offset1_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_EVTCNT_OFFSET1_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, value); +} + +// field definitions +#define EM_BLE_EVTCNT_OFFSET1_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_EVTCNT_OFFSET1_LSB 0 +#define EM_BLE_EVTCNT_OFFSET1_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_EVTCNT_OFFSET1_RST 0x0 + +__INLINE uint16_t em_ble_evtcnt_offset1_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_EVTCNT_OFFSET1_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_evtcnt_offset1_setf(int elt_idx, uint16_t evtcntoffset1) +{ + BLE_ASSERT_ERR((((uint16_t)evtcntoffset1 << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_EVTCNT_OFFSET1_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (uint16_t)evtcntoffset1 << 0); +} + +/** + * @brief EVTCNT_OFFSET2 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  06:00       EVTCNT_OFFSET2   0x0
+ * 
+ */ +#define EM_BLE_EVTCNT_OFFSET2_ADDR (0x00910066 + EM_BLE_CS_OFFSET) +#define EM_BLE_EVTCNT_OFFSET2_INDEX 0x00000033 +#define EM_BLE_EVTCNT_OFFSET2_RESET 0x00000000 + +__INLINE uint16_t em_ble_evtcnt_offset2_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_EVTCNT_OFFSET2_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +__INLINE void em_ble_evtcnt_offset2_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_EVTCNT_OFFSET2_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, value); +} + +// field definitions +#define EM_BLE_EVTCNT_OFFSET2_MASK ((uint16_t)0x0000007F) +#define EM_BLE_EVTCNT_OFFSET2_LSB 0 +#define EM_BLE_EVTCNT_OFFSET2_WIDTH ((uint16_t)0x00000007) + +#define EM_BLE_EVTCNT_OFFSET2_RST 0x0 + +__INLINE uint8_t em_ble_evtcnt_offset2_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_EVTCNT_OFFSET2_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000007F)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_evtcnt_offset2_setf(int elt_idx, uint8_t evtcntoffset2) +{ + BLE_ASSERT_ERR((((uint16_t)evtcntoffset2 << 0) & ~((uint16_t)0x0000007F)) == 0); + EM_BLE_WR(EM_BLE_EVTCNT_OFFSET2_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (uint16_t)evtcntoffset2 << 0); +} + +/** + * @brief ISOEVTCNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:08             FLUSHCNT   0x0
+ *  07:00            SUBEVTCNT   0x0
+ * 
+ */ +#define EM_BLE_ISOEVTCNTL_ADDR (0x00910068 + EM_BLE_CS_OFFSET) +#define EM_BLE_ISOEVTCNTL_INDEX 0x00000034 +#define EM_BLE_ISOEVTCNTL_RESET 0x00000000 + +__INLINE uint16_t em_ble_isoevtcntl_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_ISOEVTCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +__INLINE void em_ble_isoevtcntl_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_ISOEVTCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, value); +} + +// field definitions +#define EM_BLE_FLUSHCNT_MASK ((uint16_t)0x0000FF00) +#define EM_BLE_FLUSHCNT_LSB 8 +#define EM_BLE_FLUSHCNT_WIDTH ((uint16_t)0x00000008) +#define EM_BLE_SUBEVTCNT_MASK ((uint16_t)0x000000FF) +#define EM_BLE_SUBEVTCNT_LSB 0 +#define EM_BLE_SUBEVTCNT_WIDTH ((uint16_t)0x00000008) + +#define EM_BLE_FLUSHCNT_RST 0x0 +#define EM_BLE_SUBEVTCNT_RST 0x0 + +__INLINE void em_ble_isoevtcntl_pack(int elt_idx, uint8_t flushcnt, uint8_t subevtcnt) +{ + BLE_ASSERT_ERR((((uint16_t)flushcnt << 8) & ~((uint16_t)0x0000FF00)) == 0); + BLE_ASSERT_ERR((((uint16_t)subevtcnt << 0) & ~((uint16_t)0x000000FF)) == 0); + EM_BLE_WR(EM_BLE_ISOEVTCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, ((uint16_t)flushcnt << 8) | ((uint16_t)subevtcnt << 0)); +} + +__INLINE void em_ble_isoevtcntl_unpack(int elt_idx, uint8_t* flushcnt, uint8_t* subevtcnt) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_ISOEVTCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + + *flushcnt = (localVal & ((uint16_t)0x0000FF00)) >> 8; + *subevtcnt = (localVal & ((uint16_t)0x000000FF)) >> 0; +} + +__INLINE uint8_t em_ble_isoevtcntl_flushcnt_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_ISOEVTCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x0000FF00)) >> 8); +} + +__INLINE void em_ble_isoevtcntl_flushcnt_setf(int elt_idx, uint8_t flushcnt) +{ + BLE_ASSERT_ERR((((uint16_t)flushcnt << 8) & ~((uint16_t)0x0000FF00)) == 0); + EM_BLE_WR(EM_BLE_ISOEVTCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_ISOEVTCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x0000FF00)) | ((uint16_t)flushcnt << 8)); +} + +__INLINE uint8_t em_ble_isoevtcntl_subevtcnt_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_ISOEVTCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x000000FF)) >> 0); +} + +__INLINE void em_ble_isoevtcntl_subevtcnt_setf(int elt_idx, uint8_t subevtcnt) +{ + BLE_ASSERT_ERR((((uint16_t)subevtcnt << 0) & ~((uint16_t)0x000000FF)) == 0); + EM_BLE_WR(EM_BLE_ISOEVTCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_ISOEVTCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x000000FF)) | ((uint16_t)subevtcnt << 0)); +} + +/** + * @brief ISOTXRXCNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     15       ISORXBUFF_FULL   0
+ *     14         ISOLASTEMPTY   0
+ *     13                ISOMD   0
+ *     12                ISOSN   0
+ *     11              ISONESN   0
+ *     09              ISORETX   0
+ *     08              ISORSVD   0
+ *     03           ISOWAITACK   0
+ *     02            ISOLASTMD   0
+ *     01          ISOLASTNESN   0
+ *     00            ISOLASTSN   0
+ * 
+ */ +#define EM_BLE_ISOTXRXCNTL_ADDR (0x0091006A + EM_BLE_CS_OFFSET) +#define EM_BLE_ISOTXRXCNTL_INDEX 0x00000035 +#define EM_BLE_ISOTXRXCNTL_RESET 0x00000000 + +__INLINE uint16_t em_ble_isotxrxcntl_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +__INLINE void em_ble_isotxrxcntl_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, value); +} + +// field definitions +#define EM_BLE_ISORXBUFF_FULL_BIT ((uint16_t)0x00008000) +#define EM_BLE_ISORXBUFF_FULL_POS 15 +#define EM_BLE_ISOLASTEMPTY_BIT ((uint16_t)0x00004000) +#define EM_BLE_ISOLASTEMPTY_POS 14 +#define EM_BLE_ISOMD_BIT ((uint16_t)0x00002000) +#define EM_BLE_ISOMD_POS 13 +#define EM_BLE_ISOSN_BIT ((uint16_t)0x00001000) +#define EM_BLE_ISOSN_POS 12 +#define EM_BLE_ISONESN_BIT ((uint16_t)0x00000800) +#define EM_BLE_ISONESN_POS 11 +#define EM_BLE_ISORETX_BIT ((uint16_t)0x00000200) +#define EM_BLE_ISORETX_POS 9 +#define EM_BLE_ISORSVD_BIT ((uint16_t)0x00000100) +#define EM_BLE_ISORSVD_POS 8 +#define EM_BLE_ISOWAITACK_BIT ((uint16_t)0x00000008) +#define EM_BLE_ISOWAITACK_POS 3 +#define EM_BLE_ISOLASTMD_BIT ((uint16_t)0x00000004) +#define EM_BLE_ISOLASTMD_POS 2 +#define EM_BLE_ISOLASTNESN_BIT ((uint16_t)0x00000002) +#define EM_BLE_ISOLASTNESN_POS 1 +#define EM_BLE_ISOLASTSN_BIT ((uint16_t)0x00000001) +#define EM_BLE_ISOLASTSN_POS 0 + +#define EM_BLE_ISORXBUFF_FULL_RST 0x0 +#define EM_BLE_ISOLASTEMPTY_RST 0x0 +#define EM_BLE_ISOMD_RST 0x0 +#define EM_BLE_ISOSN_RST 0x0 +#define EM_BLE_ISONESN_RST 0x0 +#define EM_BLE_ISORETX_RST 0x0 +#define EM_BLE_ISORSVD_RST 0x0 +#define EM_BLE_ISOWAITACK_RST 0x0 +#define EM_BLE_ISOLASTMD_RST 0x0 +#define EM_BLE_ISOLASTNESN_RST 0x0 +#define EM_BLE_ISOLASTSN_RST 0x0 + +__INLINE void em_ble_isotxrxcntl_pack(int elt_idx, uint8_t isorxbufffull, uint8_t isolastempty, uint8_t isomd, uint8_t isosn, uint8_t isonesn, uint8_t isoretx, uint8_t isorsvd, uint8_t isowaitack, uint8_t isolastmd, uint8_t isolastnesn, uint8_t isolastsn) +{ + BLE_ASSERT_ERR((((uint16_t)isorxbufffull << 15) & ~((uint16_t)0x00008000)) == 0); + BLE_ASSERT_ERR((((uint16_t)isolastempty << 14) & ~((uint16_t)0x00004000)) == 0); + BLE_ASSERT_ERR((((uint16_t)isomd << 13) & ~((uint16_t)0x00002000)) == 0); + BLE_ASSERT_ERR((((uint16_t)isosn << 12) & ~((uint16_t)0x00001000)) == 0); + BLE_ASSERT_ERR((((uint16_t)isonesn << 11) & ~((uint16_t)0x00000800)) == 0); + BLE_ASSERT_ERR((((uint16_t)isoretx << 9) & ~((uint16_t)0x00000200)) == 0); + BLE_ASSERT_ERR((((uint16_t)isorsvd << 8) & ~((uint16_t)0x00000100)) == 0); + BLE_ASSERT_ERR((((uint16_t)isowaitack << 3) & ~((uint16_t)0x00000008)) == 0); + BLE_ASSERT_ERR((((uint16_t)isolastmd << 2) & ~((uint16_t)0x00000004)) == 0); + BLE_ASSERT_ERR((((uint16_t)isolastnesn << 1) & ~((uint16_t)0x00000002)) == 0); + BLE_ASSERT_ERR((((uint16_t)isolastsn << 0) & ~((uint16_t)0x00000001)) == 0); + EM_BLE_WR(EM_BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, ((uint16_t)isorxbufffull << 15) | ((uint16_t)isolastempty << 14) | ((uint16_t)isomd << 13) | ((uint16_t)isosn << 12) | ((uint16_t)isonesn << 11) | ((uint16_t)isoretx << 9) | ((uint16_t)isorsvd << 8) | ((uint16_t)isowaitack << 3) | ((uint16_t)isolastmd << 2) | ((uint16_t)isolastnesn << 1) | ((uint16_t)isolastsn << 0)); +} + +__INLINE void em_ble_isotxrxcntl_unpack(int elt_idx, uint8_t* isorxbufffull, uint8_t* isolastempty, uint8_t* isomd, uint8_t* isosn, uint8_t* isonesn, uint8_t* isoretx, uint8_t* isorsvd, uint8_t* isowaitack, uint8_t* isolastmd, uint8_t* isolastnesn, uint8_t* isolastsn) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + + *isorxbufffull = (localVal & ((uint16_t)0x00008000)) >> 15; + *isolastempty = (localVal & ((uint16_t)0x00004000)) >> 14; + *isomd = (localVal & ((uint16_t)0x00002000)) >> 13; + *isosn = (localVal & ((uint16_t)0x00001000)) >> 12; + *isonesn = (localVal & ((uint16_t)0x00000800)) >> 11; + *isoretx = (localVal & ((uint16_t)0x00000200)) >> 9; + *isorsvd = (localVal & ((uint16_t)0x00000100)) >> 8; + *isowaitack = (localVal & ((uint16_t)0x00000008)) >> 3; + *isolastmd = (localVal & ((uint16_t)0x00000004)) >> 2; + *isolastnesn = (localVal & ((uint16_t)0x00000002)) >> 1; + *isolastsn = (localVal & ((uint16_t)0x00000001)) >> 0; +} + +__INLINE uint8_t em_ble_isotxrxcntl_isorxbuff_full_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00008000)) >> 15); +} + +__INLINE void em_ble_isotxrxcntl_isorxbuff_full_setf(int elt_idx, uint8_t isorxbufffull) +{ + BLE_ASSERT_ERR((((uint16_t)isorxbufffull << 15) & ~((uint16_t)0x00008000)) == 0); + EM_BLE_WR(EM_BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00008000)) | ((uint16_t)isorxbufffull << 15)); +} + +__INLINE uint8_t em_ble_isotxrxcntl_isolastempty_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00004000)) >> 14); +} + +__INLINE void em_ble_isotxrxcntl_isolastempty_setf(int elt_idx, uint8_t isolastempty) +{ + BLE_ASSERT_ERR((((uint16_t)isolastempty << 14) & ~((uint16_t)0x00004000)) == 0); + EM_BLE_WR(EM_BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00004000)) | ((uint16_t)isolastempty << 14)); +} + +__INLINE uint8_t em_ble_isotxrxcntl_isomd_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00002000)) >> 13); +} + +__INLINE void em_ble_isotxrxcntl_isomd_setf(int elt_idx, uint8_t isomd) +{ + BLE_ASSERT_ERR((((uint16_t)isomd << 13) & ~((uint16_t)0x00002000)) == 0); + EM_BLE_WR(EM_BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00002000)) | ((uint16_t)isomd << 13)); +} + +__INLINE uint8_t em_ble_isotxrxcntl_isosn_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00001000)) >> 12); +} + +__INLINE void em_ble_isotxrxcntl_isosn_setf(int elt_idx, uint8_t isosn) +{ + BLE_ASSERT_ERR((((uint16_t)isosn << 12) & ~((uint16_t)0x00001000)) == 0); + EM_BLE_WR(EM_BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00001000)) | ((uint16_t)isosn << 12)); +} + +__INLINE uint8_t em_ble_isotxrxcntl_isonesn_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00000800)) >> 11); +} + +__INLINE void em_ble_isotxrxcntl_isonesn_setf(int elt_idx, uint8_t isonesn) +{ + BLE_ASSERT_ERR((((uint16_t)isonesn << 11) & ~((uint16_t)0x00000800)) == 0); + EM_BLE_WR(EM_BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00000800)) | ((uint16_t)isonesn << 11)); +} + +__INLINE uint8_t em_ble_isotxrxcntl_isoretx_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00000200)) >> 9); +} + +__INLINE void em_ble_isotxrxcntl_isoretx_setf(int elt_idx, uint8_t isoretx) +{ + BLE_ASSERT_ERR((((uint16_t)isoretx << 9) & ~((uint16_t)0x00000200)) == 0); + EM_BLE_WR(EM_BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00000200)) | ((uint16_t)isoretx << 9)); +} + +__INLINE uint8_t em_ble_isotxrxcntl_isorsvd_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00000100)) >> 8); +} + +__INLINE void em_ble_isotxrxcntl_isorsvd_setf(int elt_idx, uint8_t isorsvd) +{ + BLE_ASSERT_ERR((((uint16_t)isorsvd << 8) & ~((uint16_t)0x00000100)) == 0); + EM_BLE_WR(EM_BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00000100)) | ((uint16_t)isorsvd << 8)); +} + +__INLINE uint8_t em_ble_isotxrxcntl_isowaitack_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00000008)) >> 3); +} + +__INLINE void em_ble_isotxrxcntl_isowaitack_setf(int elt_idx, uint8_t isowaitack) +{ + BLE_ASSERT_ERR((((uint16_t)isowaitack << 3) & ~((uint16_t)0x00000008)) == 0); + EM_BLE_WR(EM_BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00000008)) | ((uint16_t)isowaitack << 3)); +} + +__INLINE uint8_t em_ble_isotxrxcntl_isolastmd_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00000004)) >> 2); +} + +__INLINE void em_ble_isotxrxcntl_isolastmd_setf(int elt_idx, uint8_t isolastmd) +{ + BLE_ASSERT_ERR((((uint16_t)isolastmd << 2) & ~((uint16_t)0x00000004)) == 0); + EM_BLE_WR(EM_BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00000004)) | ((uint16_t)isolastmd << 2)); +} + +__INLINE uint8_t em_ble_isotxrxcntl_isolastnesn_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00000002)) >> 1); +} + +__INLINE void em_ble_isotxrxcntl_isolastnesn_setf(int elt_idx, uint8_t isolastnesn) +{ + BLE_ASSERT_ERR((((uint16_t)isolastnesn << 1) & ~((uint16_t)0x00000002)) == 0); + EM_BLE_WR(EM_BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00000002)) | ((uint16_t)isolastnesn << 1)); +} + +__INLINE uint8_t em_ble_isotxrxcntl_isolastsn_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x00000001)) >> 0); +} + +__INLINE void em_ble_isotxrxcntl_isolastsn_setf(int elt_idx, uint8_t isolastsn) +{ + BLE_ASSERT_ERR((((uint16_t)isolastsn << 0) & ~((uint16_t)0x00000001)) == 0); + EM_BLE_WR(EM_BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE, (EM_BLE_RD(EM_BLE_ISOTXRXCNTL_ADDR + elt_idx * REG_EM_BLE_CS_SIZE) & ~((uint16_t)0x00000001)) | ((uint16_t)isolastsn << 0)); +} + +/** + * @brief TXRXDESCCNT register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:08         ACLRXDESCCNT   0x0
+ *  07:00         ACLTXDESCCNT   0x0
+ * 
+ */ +#define EM_BLE_TXRXDESCCNT_ADDR (0x0091006C + EM_BLE_CS_OFFSET) +#define EM_BLE_TXRXDESCCNT_INDEX 0x00000036 +#define EM_BLE_TXRXDESCCNT_RESET 0x00000000 + +__INLINE uint16_t em_ble_txrxdesccnt_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_TXRXDESCCNT_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +// field definitions +#define EM_BLE_ACLRXDESCCNT_MASK ((uint16_t)0x0000FF00) +#define EM_BLE_ACLRXDESCCNT_LSB 8 +#define EM_BLE_ACLRXDESCCNT_WIDTH ((uint16_t)0x00000008) +#define EM_BLE_ACLTXDESCCNT_MASK ((uint16_t)0x000000FF) +#define EM_BLE_ACLTXDESCCNT_LSB 0 +#define EM_BLE_ACLTXDESCCNT_WIDTH ((uint16_t)0x00000008) + +#define EM_BLE_ACLRXDESCCNT_RST 0x0 +#define EM_BLE_ACLTXDESCCNT_RST 0x0 + +__INLINE void em_ble_txrxdesccnt_unpack(int elt_idx, uint8_t* aclrxdesccnt, uint8_t* acltxdesccnt) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXRXDESCCNT_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + + *aclrxdesccnt = (localVal & ((uint16_t)0x0000FF00)) >> 8; + *acltxdesccnt = (localVal & ((uint16_t)0x000000FF)) >> 0; +} + +__INLINE uint8_t em_ble_txrxdesccnt_aclrxdesccnt_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXRXDESCCNT_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x0000FF00)) >> 8); +} + +__INLINE uint8_t em_ble_txrxdesccnt_acltxdesccnt_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXRXDESCCNT_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x000000FF)) >> 0); +} + +/** + * @brief ISOTXRXPKTCNT register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:08         ISORXPKTCNTL   0x0
+ *  07:00         ISOTXPKTCNTL   0x0
+ * 
+ */ +#define EM_BLE_ISOTXRXPKTCNT_ADDR (0x0091006E + EM_BLE_CS_OFFSET) +#define EM_BLE_ISOTXRXPKTCNT_INDEX 0x00000037 +#define EM_BLE_ISOTXRXPKTCNT_RESET 0x00000000 + +__INLINE uint16_t em_ble_isotxrxpktcnt_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_ISOTXRXPKTCNT_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); +} + +// field definitions +#define EM_BLE_ISORXPKTCNTL_MASK ((uint16_t)0x0000FF00) +#define EM_BLE_ISORXPKTCNTL_LSB 8 +#define EM_BLE_ISORXPKTCNTL_WIDTH ((uint16_t)0x00000008) +#define EM_BLE_ISOTXPKTCNTL_MASK ((uint16_t)0x000000FF) +#define EM_BLE_ISOTXPKTCNTL_LSB 0 +#define EM_BLE_ISOTXPKTCNTL_WIDTH ((uint16_t)0x00000008) + +#define EM_BLE_ISORXPKTCNTL_RST 0x0 +#define EM_BLE_ISOTXPKTCNTL_RST 0x0 + +__INLINE void em_ble_isotxrxpktcnt_unpack(int elt_idx, uint8_t* isorxpktcntl, uint8_t* isotxpktcntl) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_ISOTXRXPKTCNT_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + + *isorxpktcntl = (localVal & ((uint16_t)0x0000FF00)) >> 8; + *isotxpktcntl = (localVal & ((uint16_t)0x000000FF)) >> 0; +} + +__INLINE uint8_t em_ble_isotxrxpktcnt_isorxpktcntl_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_ISOTXRXPKTCNT_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x0000FF00)) >> 8); +} + +__INLINE uint8_t em_ble_isotxrxpktcnt_isotxpktcntl_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_ISOTXRXPKTCNT_ADDR + elt_idx * REG_EM_BLE_CS_SIZE); + return ((localVal & ((uint16_t)0x000000FF)) >> 0); +} + + +#endif // _REG_EM_BLE_CS_H_ + diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_em_ble_et.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_em_ble_et.h new file mode 100755 index 0000000..1215ae9 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_em_ble_et.h @@ -0,0 +1,538 @@ +#ifndef _REG_EM_BLE_ET_H_ +#define _REG_EM_BLE_ET_H_ + +#include +#include "_reg_em_ble_et.h" +#include "compiler.h" +#include "architect.h" +#include "em_map.h" +#include "ble_reg_access.h" + +#define REG_EM_BLE_ET_COUNT 8 + +#define REG_EM_BLE_ET_DECODING_MASK 0x0000000F + +#define REG_EM_BLE_ET_ADDR_GET(idx) (EM_BLE_ET_OFFSET + (idx) * REG_EM_BLE_ET_SIZE) + +/** + * @brief LE_EXTAB register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:11            SCH_PRIO1   0x0
+ *     10                  SPA   0
+ *     08               AE_NPS   0
+ *     07                 RSVD   0
+ *     06                  ISO   0
+ *  05:03               STATUS   0x0
+ *  02:00                 MODE   0x0
+ * 
+ */ +#define EM_BLE_LE_EXTAB_ADDR (0x00910000 + EM_BLE_ET_OFFSET) +#define EM_BLE_LE_EXTAB_INDEX 0x00000000 +#define EM_BLE_LE_EXTAB_RESET 0x00000000 + +__INLINE uint16_t em_ble_le_extab_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_LE_EXTAB_ADDR + elt_idx * REG_EM_BLE_ET_SIZE); +} + +__INLINE void em_ble_le_extab_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_LE_EXTAB_ADDR + elt_idx * REG_EM_BLE_ET_SIZE, value); +} + +// field definitions +#define EM_BLE_SCH_PRIO1_MASK ((uint16_t)0x0000F800) +#define EM_BLE_SCH_PRIO1_LSB 11 +#define EM_BLE_SCH_PRIO1_WIDTH ((uint16_t)0x00000005) +#define EM_BLE_SPA_BIT ((uint16_t)0x00000400) +#define EM_BLE_SPA_POS 10 +#define EM_BLE_AE_NPS_BIT ((uint16_t)0x00000100) +#define EM_BLE_AE_NPS_POS 8 +#define EM_BLE_RSVD_BIT ((uint16_t)0x00000080) +#define EM_BLE_RSVD_POS 7 +#define EM_BLE_ISO_BIT ((uint16_t)0x00000040) +#define EM_BLE_ISO_POS 6 +#define EM_BLE_STATUS_MASK ((uint16_t)0x00000038) +#define EM_BLE_STATUS_LSB 3 +#define EM_BLE_STATUS_WIDTH ((uint16_t)0x00000003) +#define EM_BLE_MODE_MASK ((uint16_t)0x00000007) +#define EM_BLE_MODE_LSB 0 +#define EM_BLE_MODE_WIDTH ((uint16_t)0x00000003) + +#define EM_BLE_SCH_PRIO1_RST 0x0 +#define EM_BLE_SPA_RST 0x0 +#define EM_BLE_AE_NPS_RST 0x0 +#define EM_BLE_RSVD_RST 0x0 +#define EM_BLE_ISO_RST 0x0 +#define EM_BLE_STATUS_RST 0x0 +#define EM_BLE_MODE_RST 0x0 + +__INLINE void em_ble_le_extab_pack(int elt_idx, uint8_t schprio1, uint8_t spa, uint8_t aenps, uint8_t rsvd, uint8_t iso, uint8_t status, uint8_t mode) +{ + BLE_ASSERT_ERR((((uint16_t)schprio1 << 11) & ~((uint16_t)0x0000F800)) == 0); + BLE_ASSERT_ERR((((uint16_t)spa << 10) & ~((uint16_t)0x00000400)) == 0); + BLE_ASSERT_ERR((((uint16_t)aenps << 8) & ~((uint16_t)0x00000100)) == 0); + BLE_ASSERT_ERR((((uint16_t)rsvd << 7) & ~((uint16_t)0x00000080)) == 0); + BLE_ASSERT_ERR((((uint16_t)iso << 6) & ~((uint16_t)0x00000040)) == 0); + BLE_ASSERT_ERR((((uint16_t)status << 3) & ~((uint16_t)0x00000038)) == 0); + BLE_ASSERT_ERR((((uint16_t)mode << 0) & ~((uint16_t)0x00000007)) == 0); + EM_BLE_WR(EM_BLE_LE_EXTAB_ADDR + elt_idx * REG_EM_BLE_ET_SIZE, ((uint16_t)schprio1 << 11) | ((uint16_t)spa << 10) | ((uint16_t)aenps << 8) | ((uint16_t)rsvd << 7) | ((uint16_t)iso << 6) | ((uint16_t)status << 3) | ((uint16_t)mode << 0)); +} + +__INLINE void em_ble_le_extab_unpack(int elt_idx, uint8_t* schprio1, uint8_t* spa, uint8_t* aenps, uint8_t* rsvd, uint8_t* iso, uint8_t* status, uint8_t* mode) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_LE_EXTAB_ADDR + elt_idx * REG_EM_BLE_ET_SIZE); + + *schprio1 = (localVal & ((uint16_t)0x0000F800)) >> 11; + *spa = (localVal & ((uint16_t)0x00000400)) >> 10; + *aenps = (localVal & ((uint16_t)0x00000100)) >> 8; + *rsvd = (localVal & ((uint16_t)0x00000080)) >> 7; + *iso = (localVal & ((uint16_t)0x00000040)) >> 6; + *status = (localVal & ((uint16_t)0x00000038)) >> 3; + *mode = (localVal & ((uint16_t)0x00000007)) >> 0; +} + +__INLINE uint8_t em_ble_le_extab_sch_prio1_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_LE_EXTAB_ADDR + elt_idx * REG_EM_BLE_ET_SIZE); + return ((localVal & ((uint16_t)0x0000F800)) >> 11); +} + +__INLINE void em_ble_le_extab_sch_prio1_setf(int elt_idx, uint8_t schprio1) +{ + BLE_ASSERT_ERR((((uint16_t)schprio1 << 11) & ~((uint16_t)0x0000F800)) == 0); + EM_BLE_WR(EM_BLE_LE_EXTAB_ADDR + elt_idx * REG_EM_BLE_ET_SIZE, (EM_BLE_RD(EM_BLE_LE_EXTAB_ADDR + elt_idx * REG_EM_BLE_ET_SIZE) & ~((uint16_t)0x0000F800)) | ((uint16_t)schprio1 << 11)); +} + +__INLINE uint8_t em_ble_le_extab_spa_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_LE_EXTAB_ADDR + elt_idx * REG_EM_BLE_ET_SIZE); + return ((localVal & ((uint16_t)0x00000400)) >> 10); +} + +__INLINE void em_ble_le_extab_spa_setf(int elt_idx, uint8_t spa) +{ + BLE_ASSERT_ERR((((uint16_t)spa << 10) & ~((uint16_t)0x00000400)) == 0); + EM_BLE_WR(EM_BLE_LE_EXTAB_ADDR + elt_idx * REG_EM_BLE_ET_SIZE, (EM_BLE_RD(EM_BLE_LE_EXTAB_ADDR + elt_idx * REG_EM_BLE_ET_SIZE) & ~((uint16_t)0x00000400)) | ((uint16_t)spa << 10)); +} + +__INLINE uint8_t em_ble_le_extab_ae_nps_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_LE_EXTAB_ADDR + elt_idx * REG_EM_BLE_ET_SIZE); + return ((localVal & ((uint16_t)0x00000100)) >> 8); +} + +__INLINE void em_ble_le_extab_ae_nps_setf(int elt_idx, uint8_t aenps) +{ + BLE_ASSERT_ERR((((uint16_t)aenps << 8) & ~((uint16_t)0x00000100)) == 0); + EM_BLE_WR(EM_BLE_LE_EXTAB_ADDR + elt_idx * REG_EM_BLE_ET_SIZE, (EM_BLE_RD(EM_BLE_LE_EXTAB_ADDR + elt_idx * REG_EM_BLE_ET_SIZE) & ~((uint16_t)0x00000100)) | ((uint16_t)aenps << 8)); +} + +__INLINE uint8_t em_ble_le_extab_rsvd_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_LE_EXTAB_ADDR + elt_idx * REG_EM_BLE_ET_SIZE); + return ((localVal & ((uint16_t)0x00000080)) >> 7); +} + +__INLINE void em_ble_le_extab_rsvd_setf(int elt_idx, uint8_t rsvd) +{ + BLE_ASSERT_ERR((((uint16_t)rsvd << 7) & ~((uint16_t)0x00000080)) == 0); + EM_BLE_WR(EM_BLE_LE_EXTAB_ADDR + elt_idx * REG_EM_BLE_ET_SIZE, (EM_BLE_RD(EM_BLE_LE_EXTAB_ADDR + elt_idx * REG_EM_BLE_ET_SIZE) & ~((uint16_t)0x00000080)) | ((uint16_t)rsvd << 7)); +} + +__INLINE uint8_t em_ble_le_extab_iso_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_LE_EXTAB_ADDR + elt_idx * REG_EM_BLE_ET_SIZE); + return ((localVal & ((uint16_t)0x00000040)) >> 6); +} + +__INLINE void em_ble_le_extab_iso_setf(int elt_idx, uint8_t iso) +{ + BLE_ASSERT_ERR((((uint16_t)iso << 6) & ~((uint16_t)0x00000040)) == 0); + EM_BLE_WR(EM_BLE_LE_EXTAB_ADDR + elt_idx * REG_EM_BLE_ET_SIZE, (EM_BLE_RD(EM_BLE_LE_EXTAB_ADDR + elt_idx * REG_EM_BLE_ET_SIZE) & ~((uint16_t)0x00000040)) | ((uint16_t)iso << 6)); +} + +__INLINE uint8_t em_ble_le_extab_status_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_LE_EXTAB_ADDR + elt_idx * REG_EM_BLE_ET_SIZE); + return ((localVal & ((uint16_t)0x00000038)) >> 3); +} + +__INLINE void em_ble_le_extab_status_setf(int elt_idx, uint8_t status) +{ + BLE_ASSERT_ERR((((uint16_t)status << 3) & ~((uint16_t)0x00000038)) == 0); + EM_BLE_WR(EM_BLE_LE_EXTAB_ADDR + elt_idx * REG_EM_BLE_ET_SIZE, (EM_BLE_RD(EM_BLE_LE_EXTAB_ADDR + elt_idx * REG_EM_BLE_ET_SIZE) & ~((uint16_t)0x00000038)) | ((uint16_t)status << 3)); +} + +__INLINE uint8_t em_ble_le_extab_mode_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_LE_EXTAB_ADDR + elt_idx * REG_EM_BLE_ET_SIZE); + return ((localVal & ((uint16_t)0x00000007)) >> 0); +} + +__INLINE void em_ble_le_extab_mode_setf(int elt_idx, uint8_t mode) +{ + BLE_ASSERT_ERR((((uint16_t)mode << 0) & ~((uint16_t)0x00000007)) == 0); + EM_BLE_WR(EM_BLE_LE_EXTAB_ADDR + elt_idx * REG_EM_BLE_ET_SIZE, (EM_BLE_RD(EM_BLE_LE_EXTAB_ADDR + elt_idx * REG_EM_BLE_ET_SIZE) & ~((uint16_t)0x00000007)) | ((uint16_t)mode << 0)); +} + +/** + * @brief RAWSTP0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00              RAWSTP0   0x0
+ * 
+ */ +#define EM_BLE_RAWSTP0_ADDR (0x00910002 + EM_BLE_ET_OFFSET) +#define EM_BLE_RAWSTP0_INDEX 0x00000001 +#define EM_BLE_RAWSTP0_RESET 0x00000000 + +__INLINE uint16_t em_ble_rawstp0_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_RAWSTP0_ADDR + elt_idx * REG_EM_BLE_ET_SIZE); +} + +__INLINE void em_ble_rawstp0_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_RAWSTP0_ADDR + elt_idx * REG_EM_BLE_ET_SIZE, value); +} + +// field definitions +#define EM_BLE_RAWSTP0_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_RAWSTP0_LSB 0 +#define EM_BLE_RAWSTP0_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_RAWSTP0_RST 0x0 + +__INLINE uint16_t em_ble_rawstp0_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RAWSTP0_ADDR + elt_idx * REG_EM_BLE_ET_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_rawstp0_setf(int elt_idx, uint16_t rawstp0) +{ + BLE_ASSERT_ERR((((uint16_t)rawstp0 << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_RAWSTP0_ADDR + elt_idx * REG_EM_BLE_ET_SIZE, (uint16_t)rawstp0 << 0); +} + +/** + * @brief RAWSTP1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  11:00              RAWSTP1   0x0
+ * 
+ */ +#define EM_BLE_RAWSTP1_ADDR (0x00910004 + EM_BLE_ET_OFFSET) +#define EM_BLE_RAWSTP1_INDEX 0x00000002 +#define EM_BLE_RAWSTP1_RESET 0x00000000 + +__INLINE uint16_t em_ble_rawstp1_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_RAWSTP1_ADDR + elt_idx * REG_EM_BLE_ET_SIZE); +} + +__INLINE void em_ble_rawstp1_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_RAWSTP1_ADDR + elt_idx * REG_EM_BLE_ET_SIZE, value); +} + +// field definitions +#define EM_BLE_RAWSTP1_MASK ((uint16_t)0x00000FFF) +#define EM_BLE_RAWSTP1_LSB 0 +#define EM_BLE_RAWSTP1_WIDTH ((uint16_t)0x0000000C) + +#define EM_BLE_RAWSTP1_RST 0x0 + +__INLINE uint16_t em_ble_rawstp1_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RAWSTP1_ADDR + elt_idx * REG_EM_BLE_ET_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x00000FFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_rawstp1_setf(int elt_idx, uint16_t rawstp1) +{ + BLE_ASSERT_ERR((((uint16_t)rawstp1 << 0) & ~((uint16_t)0x00000FFF)) == 0); + EM_BLE_WR(EM_BLE_RAWSTP1_ADDR + elt_idx * REG_EM_BLE_ET_SIZE, (uint16_t)rawstp1 << 0); +} + +/** + * @brief FINESTP register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  09:00              FINESTP   0x0
+ * 
+ */ +#define EM_BLE_FINESTP_ADDR (0x00910006 + EM_BLE_ET_OFFSET) +#define EM_BLE_FINESTP_INDEX 0x00000003 +#define EM_BLE_FINESTP_RESET 0x00000000 + +__INLINE uint16_t em_ble_finestp_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_FINESTP_ADDR + elt_idx * REG_EM_BLE_ET_SIZE); +} + +__INLINE void em_ble_finestp_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_FINESTP_ADDR + elt_idx * REG_EM_BLE_ET_SIZE, value); +} + +// field definitions +#define EM_BLE_FINESTP_MASK ((uint16_t)0x000003FF) +#define EM_BLE_FINESTP_LSB 0 +#define EM_BLE_FINESTP_WIDTH ((uint16_t)0x0000000A) + +#define EM_BLE_FINESTP_RST 0x0 + +__INLINE uint16_t em_ble_finestp_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_FINESTP_ADDR + elt_idx * REG_EM_BLE_ET_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x000003FF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_finestp_setf(int elt_idx, uint16_t finestp) +{ + BLE_ASSERT_ERR((((uint16_t)finestp << 0) & ~((uint16_t)0x000003FF)) == 0); + EM_BLE_WR(EM_BLE_FINESTP_ADDR + elt_idx * REG_EM_BLE_ET_SIZE, (uint16_t)finestp << 0); +} + +/** + * @brief CSPTR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  13:00                CSPTR   0x0
+ * 
+ */ +#define EM_BLE_CSPTR_ADDR (0x00910008 + EM_BLE_ET_OFFSET) +#define EM_BLE_CSPTR_INDEX 0x00000004 +#define EM_BLE_CSPTR_RESET 0x00000000 + +__INLINE uint16_t em_ble_csptr_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_CSPTR_ADDR + elt_idx * REG_EM_BLE_ET_SIZE); +} + +__INLINE void em_ble_csptr_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_CSPTR_ADDR + elt_idx * REG_EM_BLE_ET_SIZE, value); +} + +// field definitions +#define EM_BLE_CSPTR_MASK ((uint16_t)0x00003FFF) +#define EM_BLE_CSPTR_LSB 0 +#define EM_BLE_CSPTR_WIDTH ((uint16_t)0x0000000E) + +#define EM_BLE_CSPTR_RST 0x0 + +__INLINE uint16_t em_ble_csptr_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_CSPTR_ADDR + elt_idx * REG_EM_BLE_ET_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x00003FFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_csptr_setf(int elt_idx, uint16_t csptr) +{ + BLE_ASSERT_ERR((((uint16_t)csptr << 0) & ~((uint16_t)0x00003FFF)) == 0); + EM_BLE_WR(EM_BLE_CSPTR_ADDR + elt_idx * REG_EM_BLE_ET_SIZE, (uint16_t)csptr << 0); +} + +/** + * @brief PRIOBW register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     15          PRIO1D_UNIT   0
+ *  14:00               PRIO1D   0x0
+ * 
+ */ +#define EM_BLE_PRIOBW_ADDR (0x0091000A + EM_BLE_ET_OFFSET) +#define EM_BLE_PRIOBW_INDEX 0x00000005 +#define EM_BLE_PRIOBW_RESET 0x00000000 + +__INLINE uint16_t em_ble_priobw_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_PRIOBW_ADDR + elt_idx * REG_EM_BLE_ET_SIZE); +} + +__INLINE void em_ble_priobw_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_PRIOBW_ADDR + elt_idx * REG_EM_BLE_ET_SIZE, value); +} + +// field definitions +#define EM_BLE_PRIO1D_UNIT_BIT ((uint16_t)0x00008000) +#define EM_BLE_PRIO1D_UNIT_POS 15 +#define EM_BLE_PRIO1D_MASK ((uint16_t)0x00007FFF) +#define EM_BLE_PRIO1D_LSB 0 +#define EM_BLE_PRIO1D_WIDTH ((uint16_t)0x0000000F) + +#define EM_BLE_PRIO1D_UNIT_RST 0x0 +#define EM_BLE_PRIO1D_RST 0x0 + +__INLINE void em_ble_priobw_pack(int elt_idx, uint8_t prio1dunit, uint16_t prio1d) +{ + BLE_ASSERT_ERR((((uint16_t)prio1dunit << 15) & ~((uint16_t)0x00008000)) == 0); + BLE_ASSERT_ERR((((uint16_t)prio1d << 0) & ~((uint16_t)0x00007FFF)) == 0); + EM_BLE_WR(EM_BLE_PRIOBW_ADDR + elt_idx * REG_EM_BLE_ET_SIZE, ((uint16_t)prio1dunit << 15) | ((uint16_t)prio1d << 0)); +} + +__INLINE void em_ble_priobw_unpack(int elt_idx, uint8_t* prio1dunit, uint16_t* prio1d) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_PRIOBW_ADDR + elt_idx * REG_EM_BLE_ET_SIZE); + + *prio1dunit = (localVal & ((uint16_t)0x00008000)) >> 15; + *prio1d = (localVal & ((uint16_t)0x00007FFF)) >> 0; +} + +__INLINE uint8_t em_ble_priobw_prio1d_unit_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_PRIOBW_ADDR + elt_idx * REG_EM_BLE_ET_SIZE); + return ((localVal & ((uint16_t)0x00008000)) >> 15); +} + +__INLINE void em_ble_priobw_prio1d_unit_setf(int elt_idx, uint8_t prio1dunit) +{ + BLE_ASSERT_ERR((((uint16_t)prio1dunit << 15) & ~((uint16_t)0x00008000)) == 0); + EM_BLE_WR(EM_BLE_PRIOBW_ADDR + elt_idx * REG_EM_BLE_ET_SIZE, (EM_BLE_RD(EM_BLE_PRIOBW_ADDR + elt_idx * REG_EM_BLE_ET_SIZE) & ~((uint16_t)0x00008000)) | ((uint16_t)prio1dunit << 15)); +} + +__INLINE uint16_t em_ble_priobw_prio1d_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_PRIOBW_ADDR + elt_idx * REG_EM_BLE_ET_SIZE); + return ((localVal & ((uint16_t)0x00007FFF)) >> 0); +} + +__INLINE void em_ble_priobw_prio1d_setf(int elt_idx, uint16_t prio1d) +{ + BLE_ASSERT_ERR((((uint16_t)prio1d << 0) & ~((uint16_t)0x00007FFF)) == 0); + EM_BLE_WR(EM_BLE_PRIOBW_ADDR + elt_idx * REG_EM_BLE_ET_SIZE, (EM_BLE_RD(EM_BLE_PRIOBW_ADDR + elt_idx * REG_EM_BLE_ET_SIZE) & ~((uint16_t)0x00007FFF)) | ((uint16_t)prio1d << 0)); +} + +/** + * @brief PRIOLVL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  12:08            SCH_PRIO3   0x0
+ *  04:00            SCH_PRIO2   0x0
+ * 
+ */ +#define EM_BLE_PRIOLVL_ADDR (0x0091000C + EM_BLE_ET_OFFSET) +#define EM_BLE_PRIOLVL_INDEX 0x00000006 +#define EM_BLE_PRIOLVL_RESET 0x00000000 + +__INLINE uint16_t em_ble_priolvl_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_PRIOLVL_ADDR + elt_idx * REG_EM_BLE_ET_SIZE); +} + +__INLINE void em_ble_priolvl_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_PRIOLVL_ADDR + elt_idx * REG_EM_BLE_ET_SIZE, value); +} + +// field definitions +#define EM_BLE_SCH_PRIO3_MASK ((uint16_t)0x00001F00) +#define EM_BLE_SCH_PRIO3_LSB 8 +#define EM_BLE_SCH_PRIO3_WIDTH ((uint16_t)0x00000005) +#define EM_BLE_SCH_PRIO2_MASK ((uint16_t)0x0000001F) +#define EM_BLE_SCH_PRIO2_LSB 0 +#define EM_BLE_SCH_PRIO2_WIDTH ((uint16_t)0x00000005) + +#define EM_BLE_SCH_PRIO3_RST 0x0 +#define EM_BLE_SCH_PRIO2_RST 0x0 + +__INLINE void em_ble_priolvl_pack(int elt_idx, uint8_t schprio3, uint8_t schprio2) +{ + BLE_ASSERT_ERR((((uint16_t)schprio3 << 8) & ~((uint16_t)0x00001F00)) == 0); + BLE_ASSERT_ERR((((uint16_t)schprio2 << 0) & ~((uint16_t)0x0000001F)) == 0); + EM_BLE_WR(EM_BLE_PRIOLVL_ADDR + elt_idx * REG_EM_BLE_ET_SIZE, ((uint16_t)schprio3 << 8) | ((uint16_t)schprio2 << 0)); +} + +__INLINE void em_ble_priolvl_unpack(int elt_idx, uint8_t* schprio3, uint8_t* schprio2) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_PRIOLVL_ADDR + elt_idx * REG_EM_BLE_ET_SIZE); + + *schprio3 = (localVal & ((uint16_t)0x00001F00)) >> 8; + *schprio2 = (localVal & ((uint16_t)0x0000001F)) >> 0; +} + +__INLINE uint8_t em_ble_priolvl_sch_prio3_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_PRIOLVL_ADDR + elt_idx * REG_EM_BLE_ET_SIZE); + return ((localVal & ((uint16_t)0x00001F00)) >> 8); +} + +__INLINE void em_ble_priolvl_sch_prio3_setf(int elt_idx, uint8_t schprio3) +{ + BLE_ASSERT_ERR((((uint16_t)schprio3 << 8) & ~((uint16_t)0x00001F00)) == 0); + EM_BLE_WR(EM_BLE_PRIOLVL_ADDR + elt_idx * REG_EM_BLE_ET_SIZE, (EM_BLE_RD(EM_BLE_PRIOLVL_ADDR + elt_idx * REG_EM_BLE_ET_SIZE) & ~((uint16_t)0x00001F00)) | ((uint16_t)schprio3 << 8)); +} + +__INLINE uint8_t em_ble_priolvl_sch_prio2_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_PRIOLVL_ADDR + elt_idx * REG_EM_BLE_ET_SIZE); + return ((localVal & ((uint16_t)0x0000001F)) >> 0); +} + +__INLINE void em_ble_priolvl_sch_prio2_setf(int elt_idx, uint8_t schprio2) +{ + BLE_ASSERT_ERR((((uint16_t)schprio2 << 0) & ~((uint16_t)0x0000001F)) == 0); + EM_BLE_WR(EM_BLE_PRIOLVL_ADDR + elt_idx * REG_EM_BLE_ET_SIZE, (EM_BLE_RD(EM_BLE_PRIOLVL_ADDR + elt_idx * REG_EM_BLE_ET_SIZE) & ~((uint16_t)0x0000001F)) | ((uint16_t)schprio2 << 0)); +} + +/** + * @brief PRIOPTI register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  12:08             PTI_PRIO   0x0
+ * 
+ */ +#define EM_BLE_PRIOPTI_ADDR (0x0091000E + EM_BLE_ET_OFFSET) +#define EM_BLE_PRIOPTI_INDEX 0x00000007 +#define EM_BLE_PRIOPTI_RESET 0x00000000 + +__INLINE uint16_t em_ble_priopti_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_PRIOPTI_ADDR + elt_idx * REG_EM_BLE_ET_SIZE); +} + +__INLINE void em_ble_priopti_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_PRIOPTI_ADDR + elt_idx * REG_EM_BLE_ET_SIZE, value); +} + +// field definitions +#define EM_BLE_PTI_PRIO_MASK ((uint16_t)0x00001F00) +#define EM_BLE_PTI_PRIO_LSB 8 +#define EM_BLE_PTI_PRIO_WIDTH ((uint16_t)0x00000005) + +#define EM_BLE_PTI_PRIO_RST 0x0 + +__INLINE uint8_t em_ble_priopti_pti_prio_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_PRIOPTI_ADDR + elt_idx * REG_EM_BLE_ET_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x00001F00)) == 0); + return (localVal >> 8); +} + +__INLINE void em_ble_priopti_pti_prio_setf(int elt_idx, uint8_t ptiprio) +{ + BLE_ASSERT_ERR((((uint16_t)ptiprio << 8) & ~((uint16_t)0x00001F00)) == 0); + EM_BLE_WR(EM_BLE_PRIOPTI_ADDR + elt_idx * REG_EM_BLE_ET_SIZE, (uint16_t)ptiprio << 8); +} + + +#endif // _REG_EM_BLE_ET_H_ + diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_em_ble_ft.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_em_ble_ft.h new file mode 100755 index 0000000..5a20b6c --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_em_ble_ft.h @@ -0,0 +1,101 @@ +#ifndef _REG_EM_BLE_FT_H_ +#define _REG_EM_BLE_FT_H_ + +#include +#include "_reg_em_ble_ft.h" +#include "compiler.h" +#include "architect.h" +#include "em_map.h" +#include "ble_reg_access.h" + +#define REG_EM_BLE_FT_COUNT 1 + +#define REG_EM_BLE_FT_DECODING_MASK 0x00000000 + +#define REG_EM_BLE_FT_ADDR_GET(idx) (EM_BLE_FT_OFFSET + (idx) * REG_EM_BLE_FT_SIZE) + +/** + * @brief FREQTAB register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:08              FREQODD   0x0
+ *  07:00             FREQEVEN   0x0
+ * 
+ */ +#define EM_BLE_FREQTAB_ADDR (0x00910000 + EM_BLE_FT_OFFSET) +#define EM_BLE_FREQTAB_INDEX 0x00000000 +#define EM_BLE_FREQTAB_RESET 0x00000000 +#define EM_BLE_FREQTAB_COUNT 20 + +__INLINE uint16_t em_ble_freqtab_get(int elt_idx, int reg_idx) +{ + BLE_ASSERT_ERR(reg_idx <= 19); + return EM_BLE_RD(EM_BLE_FREQTAB_ADDR + elt_idx * REG_EM_BLE_FT_SIZE + reg_idx * 2); +} + +__INLINE void em_ble_freqtab_set(int elt_idx, int reg_idx, uint16_t value) +{ + BLE_ASSERT_ERR(reg_idx <= 19); + EM_BLE_WR(EM_BLE_FREQTAB_ADDR + elt_idx * REG_EM_BLE_FT_SIZE + reg_idx * 2, value); +} + +// field definitions +#define EM_BLE_FREQODD_MASK ((uint16_t)0x0000FF00) +#define EM_BLE_FREQODD_LSB 8 +#define EM_BLE_FREQODD_WIDTH ((uint16_t)0x00000008) +#define EM_BLE_FREQEVEN_MASK ((uint16_t)0x000000FF) +#define EM_BLE_FREQEVEN_LSB 0 +#define EM_BLE_FREQEVEN_WIDTH ((uint16_t)0x00000008) + +#define EM_BLE_FREQODD_RST 0x0 +#define EM_BLE_FREQEVEN_RST 0x0 + +__INLINE void em_ble_freqtab_pack(int elt_idx, int reg_idx, uint8_t freqodd, uint8_t freqeven) +{ + BLE_ASSERT_ERR(reg_idx <= 19); + BLE_ASSERT_ERR((((uint16_t)freqodd << 8) & ~((uint16_t)0x0000FF00)) == 0); + BLE_ASSERT_ERR((((uint16_t)freqeven << 0) & ~((uint16_t)0x000000FF)) == 0); + EM_BLE_WR(EM_BLE_FREQTAB_ADDR + elt_idx * REG_EM_BLE_FT_SIZE + reg_idx * 2, ((uint16_t)freqodd << 8) | ((uint16_t)freqeven << 0)); +} + +__INLINE void em_ble_freqtab_unpack(int elt_idx, int reg_idx, uint8_t* freqodd, uint8_t* freqeven) +{ + BLE_ASSERT_ERR(reg_idx <= 19); + uint16_t localVal = EM_BLE_RD(EM_BLE_FREQTAB_ADDR + elt_idx * REG_EM_BLE_FT_SIZE + reg_idx * 2); + + *freqodd = (localVal & ((uint16_t)0x0000FF00)) >> 8; + *freqeven = (localVal & ((uint16_t)0x000000FF)) >> 0; +} + +__INLINE uint8_t em_ble_freqtab_freqodd_getf(int elt_idx, int reg_idx) +{ + BLE_ASSERT_ERR(reg_idx <= 19); + uint16_t localVal = EM_BLE_RD(EM_BLE_FREQTAB_ADDR + elt_idx * REG_EM_BLE_FT_SIZE + reg_idx * 2); + return ((localVal & ((uint16_t)0x0000FF00)) >> 8); +} + +__INLINE void em_ble_freqtab_freqodd_setf(int elt_idx, int reg_idx, uint8_t freqodd) +{ + BLE_ASSERT_ERR(reg_idx <= 19); + BLE_ASSERT_ERR((((uint16_t)freqodd << 8) & ~((uint16_t)0x0000FF00)) == 0); + EM_BLE_WR(EM_BLE_FREQTAB_ADDR + elt_idx * REG_EM_BLE_FT_SIZE + reg_idx * 2, (EM_BLE_RD(EM_BLE_FREQTAB_ADDR + elt_idx * REG_EM_BLE_FT_SIZE + reg_idx * 2) & ~((uint16_t)0x0000FF00)) | ((uint16_t)freqodd << 8)); +} + +__INLINE uint8_t em_ble_freqtab_freqeven_getf(int elt_idx, int reg_idx) +{ + BLE_ASSERT_ERR(reg_idx <= 19); + uint16_t localVal = EM_BLE_RD(EM_BLE_FREQTAB_ADDR + elt_idx * REG_EM_BLE_FT_SIZE + reg_idx * 2); + return ((localVal & ((uint16_t)0x000000FF)) >> 0); +} + +__INLINE void em_ble_freqtab_freqeven_setf(int elt_idx, int reg_idx, uint8_t freqeven) +{ + BLE_ASSERT_ERR(reg_idx <= 19); + BLE_ASSERT_ERR((((uint16_t)freqeven << 0) & ~((uint16_t)0x000000FF)) == 0); + EM_BLE_WR(EM_BLE_FREQTAB_ADDR + elt_idx * REG_EM_BLE_FT_SIZE + reg_idx * 2, (EM_BLE_RD(EM_BLE_FREQTAB_ADDR + elt_idx * REG_EM_BLE_FT_SIZE + reg_idx * 2) & ~((uint16_t)0x000000FF)) | ((uint16_t)freqeven << 0)); +} + + +#endif // _REG_EM_BLE_FT_H_ + diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_em_ble_ral.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_em_ble_ral.h new file mode 100755 index 0000000..6ec0e5c --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_em_ble_ral.h @@ -0,0 +1,547 @@ +#ifndef _REG_EM_BLE_RAL_H_ +#define _REG_EM_BLE_RAL_H_ + +#include +#include "_reg_em_ble_ral.h" +#include "compiler.h" +#include "architect.h" +#include "em_map.h" +#include "ble_reg_access.h" + +#define REG_EM_BLE_RAL_COUNT 28 + +#define REG_EM_BLE_RAL_DECODING_MASK 0x0000003F + +#define REG_EM_BLE_RAL_ADDR_GET(idx) (EM_BLE_RAL_OFFSET + (idx) * REG_EM_BLE_RAL_SIZE) + +/** + * @brief RAL_INFO register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     15          ENTRY_VALID   0
+ *     14            CONNECTED   0
+ *     13            IN_WHLIST   0
+ *     12       IN_PERADV_LIST   0
+ *     11                  PEF   0
+ *     07      LOCAL_RPA_VALID   0
+ *     06      LOCAL_RPA_RENEW   0
+ *     05      LOCAL_IRK_VALID   0
+ *     03       PEER_RPA_VALID   0
+ *     02       PEER_RPA_RENEW   0
+ *     01       PEER_IRK_VALID   0
+ *     00         PEER_ID_TYPE   0
+ * 
+ */ +#define EM_BLE_RAL_INFO_ADDR (0x00910000 + EM_BLE_RAL_OFFSET) +#define EM_BLE_RAL_INFO_INDEX 0x00000000 +#define EM_BLE_RAL_INFO_RESET 0x00000000 + +__INLINE uint16_t em_ble_ral_info_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_RAL_INFO_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE); +} + +__INLINE void em_ble_ral_info_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_RAL_INFO_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE, value); +} + +// field definitions +#define EM_BLE_ENTRY_VALID_BIT ((uint16_t)0x00008000) +#define EM_BLE_ENTRY_VALID_POS 15 +#define EM_BLE_CONNECTED_BIT ((uint16_t)0x00004000) +#define EM_BLE_CONNECTED_POS 14 +#define EM_BLE_IN_WHLIST_BIT ((uint16_t)0x00002000) +#define EM_BLE_IN_WHLIST_POS 13 +#define EM_BLE_IN_PERADV_LIST_BIT ((uint16_t)0x00001000) +#define EM_BLE_IN_PERADV_LIST_POS 12 +#define EM_BLE_PEF_BIT ((uint16_t)0x00000800) +#define EM_BLE_PEF_POS 11 +#define EM_BLE_LOCAL_RPA_VALID_BIT ((uint16_t)0x00000080) +#define EM_BLE_LOCAL_RPA_VALID_POS 7 +#define EM_BLE_LOCAL_RPA_RENEW_BIT ((uint16_t)0x00000040) +#define EM_BLE_LOCAL_RPA_RENEW_POS 6 +#define EM_BLE_LOCAL_IRK_VALID_BIT ((uint16_t)0x00000020) +#define EM_BLE_LOCAL_IRK_VALID_POS 5 +#define EM_BLE_PEER_RPA_VALID_BIT ((uint16_t)0x00000008) +#define EM_BLE_PEER_RPA_VALID_POS 3 +#define EM_BLE_PEER_RPA_RENEW_BIT ((uint16_t)0x00000004) +#define EM_BLE_PEER_RPA_RENEW_POS 2 +#define EM_BLE_PEER_IRK_VALID_BIT ((uint16_t)0x00000002) +#define EM_BLE_PEER_IRK_VALID_POS 1 +#define EM_BLE_PEER_ID_TYPE_BIT ((uint16_t)0x00000001) +#define EM_BLE_PEER_ID_TYPE_POS 0 + +#define EM_BLE_ENTRY_VALID_RST 0x0 +#define EM_BLE_CONNECTED_RST 0x0 +#define EM_BLE_IN_WHLIST_RST 0x0 +#define EM_BLE_IN_PERADV_LIST_RST 0x0 +#define EM_BLE_PEF_RST 0x0 +#define EM_BLE_LOCAL_RPA_VALID_RST 0x0 +#define EM_BLE_LOCAL_RPA_RENEW_RST 0x0 +#define EM_BLE_LOCAL_IRK_VALID_RST 0x0 +#define EM_BLE_PEER_RPA_VALID_RST 0x0 +#define EM_BLE_PEER_RPA_RENEW_RST 0x0 +#define EM_BLE_PEER_IRK_VALID_RST 0x0 +#define EM_BLE_PEER_ID_TYPE_RST 0x0 + +__INLINE void em_ble_ral_info_pack(int elt_idx, uint8_t entryvalid, uint8_t connected, uint8_t inwhlist, uint8_t inperadvlist, uint8_t pef, uint8_t localrpavalid, uint8_t localrparenew, uint8_t localirkvalid, uint8_t peerrpavalid, uint8_t peerrparenew, uint8_t peerirkvalid, uint8_t peeridtype) +{ + BLE_ASSERT_ERR((((uint16_t)entryvalid << 15) & ~((uint16_t)0x00008000)) == 0); + BLE_ASSERT_ERR((((uint16_t)connected << 14) & ~((uint16_t)0x00004000)) == 0); + BLE_ASSERT_ERR((((uint16_t)inwhlist << 13) & ~((uint16_t)0x00002000)) == 0); + BLE_ASSERT_ERR((((uint16_t)inperadvlist << 12) & ~((uint16_t)0x00001000)) == 0); + BLE_ASSERT_ERR((((uint16_t)pef << 11) & ~((uint16_t)0x00000800)) == 0); + BLE_ASSERT_ERR((((uint16_t)localrpavalid << 7) & ~((uint16_t)0x00000080)) == 0); + BLE_ASSERT_ERR((((uint16_t)localrparenew << 6) & ~((uint16_t)0x00000040)) == 0); + BLE_ASSERT_ERR((((uint16_t)localirkvalid << 5) & ~((uint16_t)0x00000020)) == 0); + BLE_ASSERT_ERR((((uint16_t)peerrpavalid << 3) & ~((uint16_t)0x00000008)) == 0); + BLE_ASSERT_ERR((((uint16_t)peerrparenew << 2) & ~((uint16_t)0x00000004)) == 0); + BLE_ASSERT_ERR((((uint16_t)peerirkvalid << 1) & ~((uint16_t)0x00000002)) == 0); + BLE_ASSERT_ERR((((uint16_t)peeridtype << 0) & ~((uint16_t)0x00000001)) == 0); + EM_BLE_WR(EM_BLE_RAL_INFO_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE, ((uint16_t)entryvalid << 15) | ((uint16_t)connected << 14) | ((uint16_t)inwhlist << 13) | ((uint16_t)inperadvlist << 12) | ((uint16_t)pef << 11) | ((uint16_t)localrpavalid << 7) | ((uint16_t)localrparenew << 6) | ((uint16_t)localirkvalid << 5) | ((uint16_t)peerrpavalid << 3) | ((uint16_t)peerrparenew << 2) | ((uint16_t)peerirkvalid << 1) | ((uint16_t)peeridtype << 0)); +} + +__INLINE void em_ble_ral_info_unpack(int elt_idx, uint8_t* entryvalid, uint8_t* connected, uint8_t* inwhlist, uint8_t* inperadvlist, uint8_t* pef, uint8_t* localrpavalid, uint8_t* localrparenew, uint8_t* localirkvalid, uint8_t* peerrpavalid, uint8_t* peerrparenew, uint8_t* peerirkvalid, uint8_t* peeridtype) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RAL_INFO_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE); + + *entryvalid = (localVal & ((uint16_t)0x00008000)) >> 15; + *connected = (localVal & ((uint16_t)0x00004000)) >> 14; + *inwhlist = (localVal & ((uint16_t)0x00002000)) >> 13; + *inperadvlist = (localVal & ((uint16_t)0x00001000)) >> 12; + *pef = (localVal & ((uint16_t)0x00000800)) >> 11; + *localrpavalid = (localVal & ((uint16_t)0x00000080)) >> 7; + *localrparenew = (localVal & ((uint16_t)0x00000040)) >> 6; + *localirkvalid = (localVal & ((uint16_t)0x00000020)) >> 5; + *peerrpavalid = (localVal & ((uint16_t)0x00000008)) >> 3; + *peerrparenew = (localVal & ((uint16_t)0x00000004)) >> 2; + *peerirkvalid = (localVal & ((uint16_t)0x00000002)) >> 1; + *peeridtype = (localVal & ((uint16_t)0x00000001)) >> 0; +} + +__INLINE uint8_t em_ble_ral_info_entry_valid_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RAL_INFO_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE); + return ((localVal & ((uint16_t)0x00008000)) >> 15); +} + +__INLINE void em_ble_ral_info_entry_valid_setf(int elt_idx, uint8_t entryvalid) +{ + BLE_ASSERT_ERR((((uint16_t)entryvalid << 15) & ~((uint16_t)0x00008000)) == 0); + EM_BLE_WR(EM_BLE_RAL_INFO_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE, (EM_BLE_RD(EM_BLE_RAL_INFO_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE) & ~((uint16_t)0x00008000)) | ((uint16_t)entryvalid << 15)); +} + +__INLINE uint8_t em_ble_ral_info_connected_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RAL_INFO_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE); + return ((localVal & ((uint16_t)0x00004000)) >> 14); +} + +__INLINE void em_ble_ral_info_connected_setf(int elt_idx, uint8_t connected) +{ + BLE_ASSERT_ERR((((uint16_t)connected << 14) & ~((uint16_t)0x00004000)) == 0); + EM_BLE_WR(EM_BLE_RAL_INFO_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE, (EM_BLE_RD(EM_BLE_RAL_INFO_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE) & ~((uint16_t)0x00004000)) | ((uint16_t)connected << 14)); +} + +__INLINE uint8_t em_ble_ral_info_in_whlist_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RAL_INFO_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE); + return ((localVal & ((uint16_t)0x00002000)) >> 13); +} + +__INLINE void em_ble_ral_info_in_whlist_setf(int elt_idx, uint8_t inwhlist) +{ + BLE_ASSERT_ERR((((uint16_t)inwhlist << 13) & ~((uint16_t)0x00002000)) == 0); + EM_BLE_WR(EM_BLE_RAL_INFO_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE, (EM_BLE_RD(EM_BLE_RAL_INFO_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE) & ~((uint16_t)0x00002000)) | ((uint16_t)inwhlist << 13)); +} + +__INLINE uint8_t em_ble_ral_info_in_peradv_list_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RAL_INFO_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE); + return ((localVal & ((uint16_t)0x00001000)) >> 12); +} + +__INLINE void em_ble_ral_info_in_peradv_list_setf(int elt_idx, uint8_t inperadvlist) +{ + BLE_ASSERT_ERR((((uint16_t)inperadvlist << 12) & ~((uint16_t)0x00001000)) == 0); + EM_BLE_WR(EM_BLE_RAL_INFO_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE, (EM_BLE_RD(EM_BLE_RAL_INFO_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE) & ~((uint16_t)0x00001000)) | ((uint16_t)inperadvlist << 12)); +} + +__INLINE uint8_t em_ble_ral_info_pef_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RAL_INFO_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE); + return ((localVal & ((uint16_t)0x00000800)) >> 11); +} + +__INLINE void em_ble_ral_info_pef_setf(int elt_idx, uint8_t pef) +{ + BLE_ASSERT_ERR((((uint16_t)pef << 11) & ~((uint16_t)0x00000800)) == 0); + EM_BLE_WR(EM_BLE_RAL_INFO_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE, (EM_BLE_RD(EM_BLE_RAL_INFO_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE) & ~((uint16_t)0x00000800)) | ((uint16_t)pef << 11)); +} + +__INLINE uint8_t em_ble_ral_info_local_rpa_valid_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RAL_INFO_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE); + return ((localVal & ((uint16_t)0x00000080)) >> 7); +} + +__INLINE void em_ble_ral_info_local_rpa_valid_setf(int elt_idx, uint8_t localrpavalid) +{ + BLE_ASSERT_ERR((((uint16_t)localrpavalid << 7) & ~((uint16_t)0x00000080)) == 0); + EM_BLE_WR(EM_BLE_RAL_INFO_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE, (EM_BLE_RD(EM_BLE_RAL_INFO_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE) & ~((uint16_t)0x00000080)) | ((uint16_t)localrpavalid << 7)); +} + +__INLINE uint8_t em_ble_ral_info_local_rpa_renew_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RAL_INFO_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE); + return ((localVal & ((uint16_t)0x00000040)) >> 6); +} + +__INLINE void em_ble_ral_info_local_rpa_renew_setf(int elt_idx, uint8_t localrparenew) +{ + BLE_ASSERT_ERR((((uint16_t)localrparenew << 6) & ~((uint16_t)0x00000040)) == 0); + EM_BLE_WR(EM_BLE_RAL_INFO_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE, (EM_BLE_RD(EM_BLE_RAL_INFO_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE) & ~((uint16_t)0x00000040)) | ((uint16_t)localrparenew << 6)); +} + +__INLINE uint8_t em_ble_ral_info_local_irk_valid_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RAL_INFO_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE); + return ((localVal & ((uint16_t)0x00000020)) >> 5); +} + +__INLINE void em_ble_ral_info_local_irk_valid_setf(int elt_idx, uint8_t localirkvalid) +{ + BLE_ASSERT_ERR((((uint16_t)localirkvalid << 5) & ~((uint16_t)0x00000020)) == 0); + EM_BLE_WR(EM_BLE_RAL_INFO_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE, (EM_BLE_RD(EM_BLE_RAL_INFO_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE) & ~((uint16_t)0x00000020)) | ((uint16_t)localirkvalid << 5)); +} + +__INLINE uint8_t em_ble_ral_info_peer_rpa_valid_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RAL_INFO_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE); + return ((localVal & ((uint16_t)0x00000008)) >> 3); +} + +__INLINE void em_ble_ral_info_peer_rpa_valid_setf(int elt_idx, uint8_t peerrpavalid) +{ + BLE_ASSERT_ERR((((uint16_t)peerrpavalid << 3) & ~((uint16_t)0x00000008)) == 0); + EM_BLE_WR(EM_BLE_RAL_INFO_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE, (EM_BLE_RD(EM_BLE_RAL_INFO_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE) & ~((uint16_t)0x00000008)) | ((uint16_t)peerrpavalid << 3)); +} + +__INLINE uint8_t em_ble_ral_info_peer_rpa_renew_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RAL_INFO_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE); + return ((localVal & ((uint16_t)0x00000004)) >> 2); +} + +__INLINE void em_ble_ral_info_peer_rpa_renew_setf(int elt_idx, uint8_t peerrparenew) +{ + BLE_ASSERT_ERR((((uint16_t)peerrparenew << 2) & ~((uint16_t)0x00000004)) == 0); + EM_BLE_WR(EM_BLE_RAL_INFO_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE, (EM_BLE_RD(EM_BLE_RAL_INFO_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE) & ~((uint16_t)0x00000004)) | ((uint16_t)peerrparenew << 2)); +} + +__INLINE uint8_t em_ble_ral_info_peer_irk_valid_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RAL_INFO_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE); + return ((localVal & ((uint16_t)0x00000002)) >> 1); +} + +__INLINE void em_ble_ral_info_peer_irk_valid_setf(int elt_idx, uint8_t peerirkvalid) +{ + BLE_ASSERT_ERR((((uint16_t)peerirkvalid << 1) & ~((uint16_t)0x00000002)) == 0); + EM_BLE_WR(EM_BLE_RAL_INFO_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE, (EM_BLE_RD(EM_BLE_RAL_INFO_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE) & ~((uint16_t)0x00000002)) | ((uint16_t)peerirkvalid << 1)); +} + +__INLINE uint8_t em_ble_ral_info_peer_id_type_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RAL_INFO_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE); + return ((localVal & ((uint16_t)0x00000001)) >> 0); +} + +__INLINE void em_ble_ral_info_peer_id_type_setf(int elt_idx, uint8_t peeridtype) +{ + BLE_ASSERT_ERR((((uint16_t)peeridtype << 0) & ~((uint16_t)0x00000001)) == 0); + EM_BLE_WR(EM_BLE_RAL_INFO_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE, (EM_BLE_RD(EM_BLE_RAL_INFO_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE) & ~((uint16_t)0x00000001)) | ((uint16_t)peeridtype << 0)); +} + +/** + * @brief RAL_PEER_SID register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00         RAL_PEER_SID   0x0
+ * 
+ */ +#define EM_BLE_RAL_PEER_SID_ADDR (0x00910002 + EM_BLE_RAL_OFFSET) +#define EM_BLE_RAL_PEER_SID_INDEX 0x00000001 +#define EM_BLE_RAL_PEER_SID_RESET 0x00000000 + +__INLINE uint16_t em_ble_ral_peer_sid_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_RAL_PEER_SID_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE); +} + +__INLINE void em_ble_ral_peer_sid_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_RAL_PEER_SID_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE, value); +} + +// field definitions +#define EM_BLE_RAL_PEER_SID_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_RAL_PEER_SID_LSB 0 +#define EM_BLE_RAL_PEER_SID_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_RAL_PEER_SID_RST 0x0 + +__INLINE uint16_t em_ble_ral_peer_sid_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RAL_PEER_SID_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_ral_peer_sid_setf(int elt_idx, uint16_t ralpeersid) +{ + BLE_ASSERT_ERR((((uint16_t)ralpeersid << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_RAL_PEER_SID_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE, (uint16_t)ralpeersid << 0); +} + +/** + * @brief RAL_PEER_IRK register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00             PEER_IRK   0x0
+ * 
+ */ +#define EM_BLE_RAL_PEER_IRK_ADDR (0x00910004 + EM_BLE_RAL_OFFSET) +#define EM_BLE_RAL_PEER_IRK_INDEX 0x00000002 +#define EM_BLE_RAL_PEER_IRK_RESET 0x00000000 +#define EM_BLE_RAL_PEER_IRK_COUNT 8 + +__INLINE uint16_t em_ble_ral_peer_irk_get(int elt_idx, int reg_idx) +{ + BLE_ASSERT_ERR(reg_idx <= 7); + return EM_BLE_RD(EM_BLE_RAL_PEER_IRK_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE + reg_idx * 2); +} + +__INLINE void em_ble_ral_peer_irk_set(int elt_idx, int reg_idx, uint16_t value) +{ + BLE_ASSERT_ERR(reg_idx <= 7); + EM_BLE_WR(EM_BLE_RAL_PEER_IRK_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE + reg_idx * 2, value); +} + +// field definitions +#define EM_BLE_PEER_IRK_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_PEER_IRK_LSB 0 +#define EM_BLE_PEER_IRK_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_PEER_IRK_RST 0x0 + +__INLINE uint16_t em_ble_ral_peer_irk_peer_irk_getf(int elt_idx, int reg_idx) +{ + BLE_ASSERT_ERR(reg_idx <= 7); + uint16_t localVal = EM_BLE_RD(EM_BLE_RAL_PEER_IRK_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE + reg_idx * 2); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_ral_peer_irk_peer_irk_setf(int elt_idx, int reg_idx, uint16_t peerirk) +{ + BLE_ASSERT_ERR(reg_idx <= 7); + BLE_ASSERT_ERR((((uint16_t)peerirk << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_RAL_PEER_IRK_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE + reg_idx * 2, (uint16_t)peerirk << 0); +} + +/** + * @brief RAL_PEER_RPA register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00             PEER_RPA   0x0
+ * 
+ */ +#define EM_BLE_RAL_PEER_RPA_ADDR (0x00910014 + EM_BLE_RAL_OFFSET) +#define EM_BLE_RAL_PEER_RPA_INDEX 0x0000000A +#define EM_BLE_RAL_PEER_RPA_RESET 0x00000000 +#define EM_BLE_RAL_PEER_RPA_COUNT 3 + +__INLINE uint16_t em_ble_ral_peer_rpa_get(int elt_idx, int reg_idx) +{ + BLE_ASSERT_ERR(reg_idx <= 2); + return EM_BLE_RD(EM_BLE_RAL_PEER_RPA_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE + reg_idx * 2); +} + +__INLINE void em_ble_ral_peer_rpa_set(int elt_idx, int reg_idx, uint16_t value) +{ + BLE_ASSERT_ERR(reg_idx <= 2); + EM_BLE_WR(EM_BLE_RAL_PEER_RPA_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE + reg_idx * 2, value); +} + +// field definitions +#define EM_BLE_PEER_RPA_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_PEER_RPA_LSB 0 +#define EM_BLE_PEER_RPA_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_PEER_RPA_RST 0x0 + +__INLINE uint16_t em_ble_ral_peer_rpa_peer_rpa_getf(int elt_idx, int reg_idx) +{ + BLE_ASSERT_ERR(reg_idx <= 2); + uint16_t localVal = EM_BLE_RD(EM_BLE_RAL_PEER_RPA_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE + reg_idx * 2); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_ral_peer_rpa_peer_rpa_setf(int elt_idx, int reg_idx, uint16_t peerrpa) +{ + BLE_ASSERT_ERR(reg_idx <= 2); + BLE_ASSERT_ERR((((uint16_t)peerrpa << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_RAL_PEER_RPA_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE + reg_idx * 2, (uint16_t)peerrpa << 0); +} + +/** + * @brief RAL_PEER_ID register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00              PEER_ID   0x0
+ * 
+ */ +#define EM_BLE_RAL_PEER_ID_ADDR (0x0091001A + EM_BLE_RAL_OFFSET) +#define EM_BLE_RAL_PEER_ID_INDEX 0x0000000D +#define EM_BLE_RAL_PEER_ID_RESET 0x00000000 +#define EM_BLE_RAL_PEER_ID_COUNT 3 + +__INLINE uint16_t em_ble_ral_peer_id_get(int elt_idx, int reg_idx) +{ + BLE_ASSERT_ERR(reg_idx <= 2); + return EM_BLE_RD(EM_BLE_RAL_PEER_ID_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE + reg_idx * 2); +} + +__INLINE void em_ble_ral_peer_id_set(int elt_idx, int reg_idx, uint16_t value) +{ + BLE_ASSERT_ERR(reg_idx <= 2); + EM_BLE_WR(EM_BLE_RAL_PEER_ID_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE + reg_idx * 2, value); +} + +// field definitions +#define EM_BLE_PEER_ID_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_PEER_ID_LSB 0 +#define EM_BLE_PEER_ID_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_PEER_ID_RST 0x0 + +__INLINE uint16_t em_ble_ral_peer_id_peer_id_getf(int elt_idx, int reg_idx) +{ + BLE_ASSERT_ERR(reg_idx <= 2); + uint16_t localVal = EM_BLE_RD(EM_BLE_RAL_PEER_ID_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE + reg_idx * 2); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_ral_peer_id_peer_id_setf(int elt_idx, int reg_idx, uint16_t peerid) +{ + BLE_ASSERT_ERR(reg_idx <= 2); + BLE_ASSERT_ERR((((uint16_t)peerid << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_RAL_PEER_ID_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE + reg_idx * 2, (uint16_t)peerid << 0); +} + +/** + * @brief RAL_LOCAL_IRK register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00            LOCAL_IRK   0x0
+ * 
+ */ +#define EM_BLE_RAL_LOCAL_IRK_ADDR (0x00910020 + EM_BLE_RAL_OFFSET) +#define EM_BLE_RAL_LOCAL_IRK_INDEX 0x00000010 +#define EM_BLE_RAL_LOCAL_IRK_RESET 0x00000000 +#define EM_BLE_RAL_LOCAL_IRK_COUNT 8 + +__INLINE uint16_t em_ble_ral_local_irk_get(int elt_idx, int reg_idx) +{ + BLE_ASSERT_ERR(reg_idx <= 7); + return EM_BLE_RD(EM_BLE_RAL_LOCAL_IRK_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE + reg_idx * 2); +} + +__INLINE void em_ble_ral_local_irk_set(int elt_idx, int reg_idx, uint16_t value) +{ + BLE_ASSERT_ERR(reg_idx <= 7); + EM_BLE_WR(EM_BLE_RAL_LOCAL_IRK_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE + reg_idx * 2, value); +} + +// field definitions +#define EM_BLE_LOCAL_IRK_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_LOCAL_IRK_LSB 0 +#define EM_BLE_LOCAL_IRK_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_LOCAL_IRK_RST 0x0 + +__INLINE uint16_t em_ble_ral_local_irk_local_irk_getf(int elt_idx, int reg_idx) +{ + BLE_ASSERT_ERR(reg_idx <= 7); + uint16_t localVal = EM_BLE_RD(EM_BLE_RAL_LOCAL_IRK_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE + reg_idx * 2); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_ral_local_irk_local_irk_setf(int elt_idx, int reg_idx, uint16_t localirk) +{ + BLE_ASSERT_ERR(reg_idx <= 7); + BLE_ASSERT_ERR((((uint16_t)localirk << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_RAL_LOCAL_IRK_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE + reg_idx * 2, (uint16_t)localirk << 0); +} + +/** + * @brief RAL_LOCAL_RPA register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00            LOCAL_RPA   0x0
+ * 
+ */ +#define EM_BLE_RAL_LOCAL_RPA_ADDR (0x00910030 + EM_BLE_RAL_OFFSET) +#define EM_BLE_RAL_LOCAL_RPA_INDEX 0x00000018 +#define EM_BLE_RAL_LOCAL_RPA_RESET 0x00000000 +#define EM_BLE_RAL_LOCAL_RPA_COUNT 3 + +__INLINE uint16_t em_ble_ral_local_rpa_get(int elt_idx, int reg_idx) +{ + BLE_ASSERT_ERR(reg_idx <= 2); + return EM_BLE_RD(EM_BLE_RAL_LOCAL_RPA_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE + reg_idx * 2); +} + +__INLINE void em_ble_ral_local_rpa_set(int elt_idx, int reg_idx, uint16_t value) +{ + BLE_ASSERT_ERR(reg_idx <= 2); + EM_BLE_WR(EM_BLE_RAL_LOCAL_RPA_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE + reg_idx * 2, value); +} + +// field definitions +#define EM_BLE_LOCAL_RPA_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_LOCAL_RPA_LSB 0 +#define EM_BLE_LOCAL_RPA_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_LOCAL_RPA_RST 0x0 + +__INLINE uint16_t em_ble_ral_local_rpa_local_rpa_getf(int elt_idx, int reg_idx) +{ + BLE_ASSERT_ERR(reg_idx <= 2); + uint16_t localVal = EM_BLE_RD(EM_BLE_RAL_LOCAL_RPA_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE + reg_idx * 2); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_ral_local_rpa_local_rpa_setf(int elt_idx, int reg_idx, uint16_t localrpa) +{ + BLE_ASSERT_ERR(reg_idx <= 2); + BLE_ASSERT_ERR((((uint16_t)localrpa << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_RAL_LOCAL_RPA_ADDR + elt_idx * REG_EM_BLE_RAL_SIZE + reg_idx * 2, (uint16_t)localrpa << 0); +} + + +#endif // _REG_EM_BLE_RAL_H_ + diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_em_ble_rx_audio_buf.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_em_ble_rx_audio_buf.h new file mode 100755 index 0000000..04aac84 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_em_ble_rx_audio_buf.h @@ -0,0 +1,66 @@ +#ifndef _REG_EM_BLE_RX_AUDIO_BUF_H_ +#define _REG_EM_BLE_RX_AUDIO_BUF_H_ + +#include +#include "_reg_em_ble_rx_audio_buf.h" +#include "compiler.h" +#include "architect.h" +#include "em_map.h" +#include "ble_reg_access.h" + +#define REG_EM_BLE_RX_AUDIO_BUF_COUNT 1 + +#define REG_EM_BLE_RX_AUDIO_BUF_DECODING_MASK 0x00000000 + +#define REG_EM_BLE_RX_AUDIO_BUF_ADDR_GET(idx) (EM_BLE_RX_AUDIO_BUFFER_OFFSET + (idx) * REG_EM_BLE_RX_AUDIO_BUF_SIZE) + +/** + * @brief RXAUDIOBUF register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00           RXAUDIOBUF   0x0
+ * 
+ */ +#define EM_BLE_RXAUDIOBUF_ADDR (0x00910000 + EM_BLE_RX_AUDIO_BUFFER_OFFSET) +#define EM_BLE_RXAUDIOBUF_INDEX 0x00000000 +#define EM_BLE_RXAUDIOBUF_RESET 0x00000000 +#define EM_BLE_RXAUDIOBUF_COUNT 32 + +__INLINE uint16_t em_ble_rxaudiobuf_get(int elt_idx, int reg_idx) +{ + BLE_ASSERT_ERR(reg_idx <= 31); + return EM_BLE_RD(EM_BLE_RXAUDIOBUF_ADDR + elt_idx * REG_EM_BLE_RX_AUDIO_BUF_SIZE + reg_idx * 2); +} + +__INLINE void em_ble_rxaudiobuf_set(int elt_idx, int reg_idx, uint16_t value) +{ + BLE_ASSERT_ERR(reg_idx <= 31); + EM_BLE_WR(EM_BLE_RXAUDIOBUF_ADDR + elt_idx * REG_EM_BLE_RX_AUDIO_BUF_SIZE + reg_idx * 2, value); +} + +// field definitions +#define EM_BLE_RXAUDIOBUF_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_RXAUDIOBUF_LSB 0 +#define EM_BLE_RXAUDIOBUF_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_RXAUDIOBUF_RST 0x0 + +__INLINE uint16_t em_ble_rxaudiobuf_getf(int elt_idx, int reg_idx) +{ + BLE_ASSERT_ERR(reg_idx <= 31); + uint16_t localVal = EM_BLE_RD(EM_BLE_RXAUDIOBUF_ADDR + elt_idx * REG_EM_BLE_RX_AUDIO_BUF_SIZE + reg_idx * 2); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_rxaudiobuf_setf(int elt_idx, int reg_idx, uint16_t rxaudiobuf) +{ + BLE_ASSERT_ERR(reg_idx <= 31); + BLE_ASSERT_ERR((((uint16_t)rxaudiobuf << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_RXAUDIOBUF_ADDR + elt_idx * REG_EM_BLE_RX_AUDIO_BUF_SIZE + reg_idx * 2, (uint16_t)rxaudiobuf << 0); +} + + +#endif // _REG_EM_BLE_RX_AUDIO_BUF_H_ + diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_em_ble_rx_buf.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_em_ble_rx_buf.h new file mode 100755 index 0000000..f4d7b64 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_em_ble_rx_buf.h @@ -0,0 +1,66 @@ +#ifndef _REG_EM_BLE_RX_BUF_H_ +#define _REG_EM_BLE_RX_BUF_H_ + +#include +#include "_reg_em_ble_rx_buf.h" +#include "compiler.h" +#include "architect.h" +#include "em_map.h" +#include "ble_reg_access.h" + +#define REG_EM_BLE_RX_BUF_COUNT 1 + +#define REG_EM_BLE_RX_BUF_DECODING_MASK 0x00000000 + +#define REG_EM_BLE_RX_BUF_ADDR_GET(idx) (EM_BLE_RX_BUFFER_OFFSET + (idx) * REG_EM_BLE_RX_BUF_SIZE) + +/** + * @brief RXBUF register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00                RXBUF   0x0
+ * 
+ */ +#define EM_BLE_RXBUF_ADDR (0x00910000 + EM_BLE_RX_BUFFER_OFFSET) +#define EM_BLE_RXBUF_INDEX 0x00000000 +#define EM_BLE_RXBUF_RESET 0x00000000 +#define EM_BLE_RXBUF_COUNT 130 + +__INLINE uint16_t em_ble_rxbuf_get(int elt_idx, int reg_idx) +{ + BLE_ASSERT_ERR(reg_idx <= 129); + return EM_BLE_RD(EM_BLE_RXBUF_ADDR + elt_idx * REG_EM_BLE_RX_BUF_SIZE + reg_idx * 2); +} + +__INLINE void em_ble_rxbuf_set(int elt_idx, int reg_idx, uint16_t value) +{ + BLE_ASSERT_ERR(reg_idx <= 129); + EM_BLE_WR(EM_BLE_RXBUF_ADDR + elt_idx * REG_EM_BLE_RX_BUF_SIZE + reg_idx * 2, value); +} + +// field definitions +#define EM_BLE_RXBUF_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_RXBUF_LSB 0 +#define EM_BLE_RXBUF_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_RXBUF_RST 0x0 + +__INLINE uint16_t em_ble_rxbuf_getf(int elt_idx, int reg_idx) +{ + BLE_ASSERT_ERR(reg_idx <= 129); + uint16_t localVal = EM_BLE_RD(EM_BLE_RXBUF_ADDR + elt_idx * REG_EM_BLE_RX_BUF_SIZE + reg_idx * 2); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_rxbuf_setf(int elt_idx, int reg_idx, uint16_t rxbuf) +{ + BLE_ASSERT_ERR(reg_idx <= 129); + BLE_ASSERT_ERR((((uint16_t)rxbuf << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_RXBUF_ADDR + elt_idx * REG_EM_BLE_RX_BUF_SIZE + reg_idx * 2, (uint16_t)rxbuf << 0); +} + + +#endif // _REG_EM_BLE_RX_BUF_H_ + diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_em_ble_rx_cte_desc.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_em_ble_rx_cte_desc.h new file mode 100755 index 0000000..a4eba5d --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_em_ble_rx_cte_desc.h @@ -0,0 +1,173 @@ +#ifndef _REG_EM_BLE_RX_CTE_DESC_H_ +#define _REG_EM_BLE_RX_CTE_DESC_H_ + +#include +#include "_reg_em_ble_rx_cte_desc.h" +#include "compiler.h" +#include "architect.h" +#include "em_map.h" +#include "ble_reg_access.h" + +#define REG_EM_BLE_RX_CTE_DESC_COUNT 3 + +#define REG_EM_BLE_RX_CTE_DESC_DECODING_MASK 0x00000007 + +#define REG_EM_BLE_RX_CTE_DESC_ADDR_GET(idx) (EM_BLE_RX_CTE_DESC_OFFSET + (idx) * REG_EM_BLE_RX_CTE_DESC_SIZE) + +/** + * @brief RXCTECNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     15               RXDONE   0
+ *  13:00            RXNEXTPTR   0x0
+ * 
+ */ +#define EM_BLE_RXCTECNTL_ADDR (0x00910000 + EM_BLE_RX_CTE_DESC_OFFSET) +#define EM_BLE_RXCTECNTL_INDEX 0x00000000 +#define EM_BLE_RXCTECNTL_RESET 0x00000000 + +__INLINE uint16_t em_ble_rxctecntl_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_RXCTECNTL_ADDR + elt_idx * REG_EM_BLE_RX_CTE_DESC_SIZE); +} + +__INLINE void em_ble_rxctecntl_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_RXCTECNTL_ADDR + elt_idx * REG_EM_BLE_RX_CTE_DESC_SIZE, value); +} + +// field definitions +#define EM_BLE_RXDONE_BIT ((uint16_t)0x00008000) +#define EM_BLE_RXDONE_POS 15 +#define EM_BLE_RXNEXTPTR_MASK ((uint16_t)0x00003FFF) +#define EM_BLE_RXNEXTPTR_LSB 0 +#define EM_BLE_RXNEXTPTR_WIDTH ((uint16_t)0x0000000E) + +#define EM_BLE_RXDONE_RST 0x0 +#define EM_BLE_RXNEXTPTR_RST 0x0 + +__INLINE void em_ble_rxctecntl_pack(int elt_idx, uint8_t rxdone, uint16_t rxnextptr) +{ + BLE_ASSERT_ERR((((uint16_t)rxdone << 15) & ~((uint16_t)0x00008000)) == 0); + BLE_ASSERT_ERR((((uint16_t)rxnextptr << 0) & ~((uint16_t)0x00003FFF)) == 0); + EM_BLE_WR(EM_BLE_RXCTECNTL_ADDR + elt_idx * REG_EM_BLE_RX_CTE_DESC_SIZE, ((uint16_t)rxdone << 15) | ((uint16_t)rxnextptr << 0)); +} + +__INLINE void em_ble_rxctecntl_unpack(int elt_idx, uint8_t* rxdone, uint16_t* rxnextptr) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXCTECNTL_ADDR + elt_idx * REG_EM_BLE_RX_CTE_DESC_SIZE); + + *rxdone = (localVal & ((uint16_t)0x00008000)) >> 15; + *rxnextptr = (localVal & ((uint16_t)0x00003FFF)) >> 0; +} + +__INLINE uint8_t em_ble_rxctecntl_rxdone_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXCTECNTL_ADDR + elt_idx * REG_EM_BLE_RX_CTE_DESC_SIZE); + return ((localVal & ((uint16_t)0x00008000)) >> 15); +} + +__INLINE void em_ble_rxctecntl_rxdone_setf(int elt_idx, uint8_t rxdone) +{ + BLE_ASSERT_ERR((((uint16_t)rxdone << 15) & ~((uint16_t)0x00008000)) == 0); + EM_BLE_WR(EM_BLE_RXCTECNTL_ADDR + elt_idx * REG_EM_BLE_RX_CTE_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXCTECNTL_ADDR + elt_idx * REG_EM_BLE_RX_CTE_DESC_SIZE) & ~((uint16_t)0x00008000)) | ((uint16_t)rxdone << 15)); +} + +__INLINE uint16_t em_ble_rxctecntl_rxnextptr_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXCTECNTL_ADDR + elt_idx * REG_EM_BLE_RX_CTE_DESC_SIZE); + return ((localVal & ((uint16_t)0x00003FFF)) >> 0); +} + +__INLINE void em_ble_rxctecntl_rxnextptr_setf(int elt_idx, uint16_t rxnextptr) +{ + BLE_ASSERT_ERR((((uint16_t)rxnextptr << 0) & ~((uint16_t)0x00003FFF)) == 0); + EM_BLE_WR(EM_BLE_RXCTECNTL_ADDR + elt_idx * REG_EM_BLE_RX_CTE_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXCTECNTL_ADDR + elt_idx * REG_EM_BLE_RX_CTE_DESC_SIZE) & ~((uint16_t)0x00003FFF)) | ((uint16_t)rxnextptr << 0)); +} + +/** + * @brief RXCTESAMPBUF register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:08                 RX_Q   0x0
+ *  07:00                 RX_I   0x0
+ * 
+ */ +#define EM_BLE_RXCTESAMPBUF_ADDR (0x00910004 + EM_BLE_RX_CTE_DESC_OFFSET) +#define EM_BLE_RXCTESAMPBUF_INDEX 0x00000002 +#define EM_BLE_RXCTESAMPBUF_RESET 0x00000000 +#define EM_BLE_RXCTESAMPBUF_COUNT 82 + +__INLINE uint16_t em_ble_rxctesampbuf_get(int elt_idx, int reg_idx) +{ + BLE_ASSERT_ERR(reg_idx <= 81); + return EM_BLE_RD(EM_BLE_RXCTESAMPBUF_ADDR + elt_idx * REG_EM_BLE_RX_CTE_DESC_SIZE + reg_idx * 2); +} + +__INLINE void em_ble_rxctesampbuf_set(int elt_idx, int reg_idx, uint16_t value) +{ + BLE_ASSERT_ERR(reg_idx <= 81); + EM_BLE_WR(EM_BLE_RXCTESAMPBUF_ADDR + elt_idx * REG_EM_BLE_RX_CTE_DESC_SIZE + reg_idx * 2, value); +} + +// field definitions +#define EM_BLE_RX_Q_MASK ((uint16_t)0x0000FF00) +#define EM_BLE_RX_Q_LSB 8 +#define EM_BLE_RX_Q_WIDTH ((uint16_t)0x00000008) +#define EM_BLE_RX_I_MASK ((uint16_t)0x000000FF) +#define EM_BLE_RX_I_LSB 0 +#define EM_BLE_RX_I_WIDTH ((uint16_t)0x00000008) + +#define EM_BLE_RX_Q_RST 0x0 +#define EM_BLE_RX_I_RST 0x0 + +__INLINE void em_ble_rxctesampbuf_pack(int elt_idx, int reg_idx, uint8_t rxq, uint8_t rxi) +{ + BLE_ASSERT_ERR(reg_idx <= 81); + BLE_ASSERT_ERR((((uint16_t)rxq << 8) & ~((uint16_t)0x0000FF00)) == 0); + BLE_ASSERT_ERR((((uint16_t)rxi << 0) & ~((uint16_t)0x000000FF)) == 0); + EM_BLE_WR(EM_BLE_RXCTESAMPBUF_ADDR + elt_idx * REG_EM_BLE_RX_CTE_DESC_SIZE + reg_idx * 2, ((uint16_t)rxq << 8) | ((uint16_t)rxi << 0)); +} + +__INLINE void em_ble_rxctesampbuf_unpack(int elt_idx, int reg_idx, uint8_t* rxq, uint8_t* rxi) +{ + BLE_ASSERT_ERR(reg_idx <= 81); + uint16_t localVal = EM_BLE_RD(EM_BLE_RXCTESAMPBUF_ADDR + elt_idx * REG_EM_BLE_RX_CTE_DESC_SIZE + reg_idx * 2); + + *rxq = (localVal & ((uint16_t)0x0000FF00)) >> 8; + *rxi = (localVal & ((uint16_t)0x000000FF)) >> 0; +} + +__INLINE uint8_t em_ble_rxctesampbuf_rx_q_getf(int elt_idx, int reg_idx) +{ + BLE_ASSERT_ERR(reg_idx <= 81); + uint16_t localVal = EM_BLE_RD(EM_BLE_RXCTESAMPBUF_ADDR + elt_idx * REG_EM_BLE_RX_CTE_DESC_SIZE + reg_idx * 2); + return ((localVal & ((uint16_t)0x0000FF00)) >> 8); +} + +__INLINE void em_ble_rxctesampbuf_rx_q_setf(int elt_idx, int reg_idx, uint8_t rxq) +{ + BLE_ASSERT_ERR(reg_idx <= 81); + BLE_ASSERT_ERR((((uint16_t)rxq << 8) & ~((uint16_t)0x0000FF00)) == 0); + EM_BLE_WR(EM_BLE_RXCTESAMPBUF_ADDR + elt_idx * REG_EM_BLE_RX_CTE_DESC_SIZE + reg_idx * 2, (EM_BLE_RD(EM_BLE_RXCTESAMPBUF_ADDR + elt_idx * REG_EM_BLE_RX_CTE_DESC_SIZE + reg_idx * 2) & ~((uint16_t)0x0000FF00)) | ((uint16_t)rxq << 8)); +} + +__INLINE uint8_t em_ble_rxctesampbuf_rx_i_getf(int elt_idx, int reg_idx) +{ + BLE_ASSERT_ERR(reg_idx <= 81); + uint16_t localVal = EM_BLE_RD(EM_BLE_RXCTESAMPBUF_ADDR + elt_idx * REG_EM_BLE_RX_CTE_DESC_SIZE + reg_idx * 2); + return ((localVal & ((uint16_t)0x000000FF)) >> 0); +} + +__INLINE void em_ble_rxctesampbuf_rx_i_setf(int elt_idx, int reg_idx, uint8_t rxi) +{ + BLE_ASSERT_ERR(reg_idx <= 81); + BLE_ASSERT_ERR((((uint16_t)rxi << 0) & ~((uint16_t)0x000000FF)) == 0); + EM_BLE_WR(EM_BLE_RXCTESAMPBUF_ADDR + elt_idx * REG_EM_BLE_RX_CTE_DESC_SIZE + reg_idx * 2, (EM_BLE_RD(EM_BLE_RXCTESAMPBUF_ADDR + elt_idx * REG_EM_BLE_RX_CTE_DESC_SIZE + reg_idx * 2) & ~((uint16_t)0x000000FF)) | ((uint16_t)rxi << 0)); +} + + +#endif // _REG_EM_BLE_RX_CTE_DESC_H_ + diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_em_ble_rx_desc.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_em_ble_rx_desc.h new file mode 100755 index 0000000..a18b768 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_em_ble_rx_desc.h @@ -0,0 +1,1969 @@ +#ifndef _REG_EM_BLE_RX_DESC_H_ +#define _REG_EM_BLE_RX_DESC_H_ + +#include +#include "_reg_em_ble_rx_desc.h" +#include "compiler.h" +#include "architect.h" +#include "em_map.h" +#include "ble_reg_access.h" + +#define REG_EM_BLE_RX_DESC_COUNT 14 + +#define REG_EM_BLE_RX_DESC_DECODING_MASK 0x0000001F + +#define REG_EM_BLE_RX_DESC_ADDR_GET(idx) (EM_BLE_RX_DESC_OFFSET + (idx) * REG_EM_BLE_RX_DESC_SIZE) + +/** + * @brief RXCNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     15               RXDONE   0
+ *  13:00            RXNEXTPTR   0x0
+ * 
+ */ +#define EM_BLE_RXCNTL_ADDR (0x00910000 + EM_BLE_RX_DESC_OFFSET) +#define EM_BLE_RXCNTL_INDEX 0x00000000 +#define EM_BLE_RXCNTL_RESET 0x00000000 + +__INLINE uint16_t em_ble_rxcntl_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_RXCNTL_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); +} + +__INLINE void em_ble_rxcntl_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_RXCNTL_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, value); +} + +// field definitions +#define EM_BLE_RXDONE_BIT ((uint16_t)0x00008000) +#define EM_BLE_RXDONE_POS 15 +#define EM_BLE_RXNEXTPTR_MASK ((uint16_t)0x00003FFF) +#define EM_BLE_RXNEXTPTR_LSB 0 +#define EM_BLE_RXNEXTPTR_WIDTH ((uint16_t)0x0000000E) + +#define EM_BLE_RXDONE_RST 0x0 +#define EM_BLE_RXNEXTPTR_RST 0x0 + +__INLINE void em_ble_rxcntl_pack(int elt_idx, uint8_t rxdone, uint16_t rxnextptr) +{ + BLE_ASSERT_ERR((((uint16_t)rxdone << 15) & ~((uint16_t)0x00008000)) == 0); + BLE_ASSERT_ERR((((uint16_t)rxnextptr << 0) & ~((uint16_t)0x00003FFF)) == 0); + EM_BLE_WR(EM_BLE_RXCNTL_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, ((uint16_t)rxdone << 15) | ((uint16_t)rxnextptr << 0)); +} + +__INLINE void em_ble_rxcntl_unpack(int elt_idx, uint8_t* rxdone, uint16_t* rxnextptr) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXCNTL_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + + *rxdone = (localVal & ((uint16_t)0x00008000)) >> 15; + *rxnextptr = (localVal & ((uint16_t)0x00003FFF)) >> 0; +} + +__INLINE uint8_t em_ble_rxcntl_rxdone_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXCNTL_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00008000)) >> 15); +} + +__INLINE void em_ble_rxcntl_rxdone_setf(int elt_idx, uint8_t rxdone) +{ + BLE_ASSERT_ERR((((uint16_t)rxdone << 15) & ~((uint16_t)0x00008000)) == 0); + EM_BLE_WR(EM_BLE_RXCNTL_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXCNTL_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00008000)) | ((uint16_t)rxdone << 15)); +} + +__INLINE uint16_t em_ble_rxcntl_rxnextptr_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXCNTL_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00003FFF)) >> 0); +} + +__INLINE void em_ble_rxcntl_rxnextptr_setf(int elt_idx, uint16_t rxnextptr) +{ + BLE_ASSERT_ERR((((uint16_t)rxnextptr << 0) & ~((uint16_t)0x00003FFF)) == 0); + EM_BLE_WR(EM_BLE_RXCNTL_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXCNTL_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00003FFF)) | ((uint16_t)rxnextptr << 0)); +} + +/** + * @brief RXSTATCE register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     15             RXCTEERR   0
+ *     07             NESN_ERR   0
+ *     06               SN_ERR   0
+ *     05             LLID_ERR   0
+ *     04              MIC_ERR   0
+ *     03              CRC_ERR   0
+ *     02              LEN_ERR   0
+ *     01           RXTIME_ERR   0
+ *     00             SYNC_ERR   0
+ * 
+ */ +#define EM_BLE_RXSTATCE_ADDR (0x00910002 + EM_BLE_RX_DESC_OFFSET) +#define EM_BLE_RXSTATCE_INDEX 0x00000001 +#define EM_BLE_RXSTATCE_RESET 0x00000000 + +__INLINE uint16_t em_ble_rxstatce_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_RXSTATCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); +} + +__INLINE void em_ble_rxstatce_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_RXSTATCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, value); +} + +// field definitions +#define EM_BLE_RXCTEERR_BIT ((uint16_t)0x00008000) +#define EM_BLE_RXCTEERR_POS 15 +#define EM_BLE_NESN_ERR_BIT ((uint16_t)0x00000080) +#define EM_BLE_NESN_ERR_POS 7 +#define EM_BLE_SN_ERR_BIT ((uint16_t)0x00000040) +#define EM_BLE_SN_ERR_POS 6 +#define EM_BLE_LLID_ERR_BIT ((uint16_t)0x00000020) +#define EM_BLE_LLID_ERR_POS 5 +#define EM_BLE_MIC_ERR_BIT ((uint16_t)0x00000010) +#define EM_BLE_MIC_ERR_POS 4 +#define EM_BLE_CRC_ERR_BIT ((uint16_t)0x00000008) +#define EM_BLE_CRC_ERR_POS 3 +#define EM_BLE_LEN_ERR_BIT ((uint16_t)0x00000004) +#define EM_BLE_LEN_ERR_POS 2 +#define EM_BLE_RXTIME_ERR_BIT ((uint16_t)0x00000002) +#define EM_BLE_RXTIME_ERR_POS 1 +#define EM_BLE_SYNC_ERR_BIT ((uint16_t)0x00000001) +#define EM_BLE_SYNC_ERR_POS 0 + +#define EM_BLE_RXCTEERR_RST 0x0 +#define EM_BLE_NESN_ERR_RST 0x0 +#define EM_BLE_SN_ERR_RST 0x0 +#define EM_BLE_LLID_ERR_RST 0x0 +#define EM_BLE_MIC_ERR_RST 0x0 +#define EM_BLE_CRC_ERR_RST 0x0 +#define EM_BLE_LEN_ERR_RST 0x0 +#define EM_BLE_RXTIME_ERR_RST 0x0 +#define EM_BLE_SYNC_ERR_RST 0x0 + +__INLINE void em_ble_rxstatce_pack(int elt_idx, uint8_t rxcteerr, uint8_t nesnerr, uint8_t snerr, uint8_t lliderr, uint8_t micerr, uint8_t crcerr, uint8_t lenerr, uint8_t rxtimeerr, uint8_t syncerr) +{ + BLE_ASSERT_ERR((((uint16_t)rxcteerr << 15) & ~((uint16_t)0x00008000)) == 0); + BLE_ASSERT_ERR((((uint16_t)nesnerr << 7) & ~((uint16_t)0x00000080)) == 0); + BLE_ASSERT_ERR((((uint16_t)snerr << 6) & ~((uint16_t)0x00000040)) == 0); + BLE_ASSERT_ERR((((uint16_t)lliderr << 5) & ~((uint16_t)0x00000020)) == 0); + BLE_ASSERT_ERR((((uint16_t)micerr << 4) & ~((uint16_t)0x00000010)) == 0); + BLE_ASSERT_ERR((((uint16_t)crcerr << 3) & ~((uint16_t)0x00000008)) == 0); + BLE_ASSERT_ERR((((uint16_t)lenerr << 2) & ~((uint16_t)0x00000004)) == 0); + BLE_ASSERT_ERR((((uint16_t)rxtimeerr << 1) & ~((uint16_t)0x00000002)) == 0); + BLE_ASSERT_ERR((((uint16_t)syncerr << 0) & ~((uint16_t)0x00000001)) == 0); + EM_BLE_WR(EM_BLE_RXSTATCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, ((uint16_t)rxcteerr << 15) | ((uint16_t)nesnerr << 7) | ((uint16_t)snerr << 6) | ((uint16_t)lliderr << 5) | ((uint16_t)micerr << 4) | ((uint16_t)crcerr << 3) | ((uint16_t)lenerr << 2) | ((uint16_t)rxtimeerr << 1) | ((uint16_t)syncerr << 0)); +} + +__INLINE void em_ble_rxstatce_unpack(int elt_idx, uint8_t* rxcteerr, uint8_t* nesnerr, uint8_t* snerr, uint8_t* lliderr, uint8_t* micerr, uint8_t* crcerr, uint8_t* lenerr, uint8_t* rxtimeerr, uint8_t* syncerr) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXSTATCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + + *rxcteerr = (localVal & ((uint16_t)0x00008000)) >> 15; + *nesnerr = (localVal & ((uint16_t)0x00000080)) >> 7; + *snerr = (localVal & ((uint16_t)0x00000040)) >> 6; + *lliderr = (localVal & ((uint16_t)0x00000020)) >> 5; + *micerr = (localVal & ((uint16_t)0x00000010)) >> 4; + *crcerr = (localVal & ((uint16_t)0x00000008)) >> 3; + *lenerr = (localVal & ((uint16_t)0x00000004)) >> 2; + *rxtimeerr = (localVal & ((uint16_t)0x00000002)) >> 1; + *syncerr = (localVal & ((uint16_t)0x00000001)) >> 0; +} + +__INLINE uint8_t em_ble_rxstatce_rxcteerr_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXSTATCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00008000)) >> 15); +} + +__INLINE void em_ble_rxstatce_rxcteerr_setf(int elt_idx, uint8_t rxcteerr) +{ + BLE_ASSERT_ERR((((uint16_t)rxcteerr << 15) & ~((uint16_t)0x00008000)) == 0); + EM_BLE_WR(EM_BLE_RXSTATCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXSTATCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00008000)) | ((uint16_t)rxcteerr << 15)); +} + +__INLINE uint8_t em_ble_rxstatce_nesn_err_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXSTATCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000080)) >> 7); +} + +__INLINE void em_ble_rxstatce_nesn_err_setf(int elt_idx, uint8_t nesnerr) +{ + BLE_ASSERT_ERR((((uint16_t)nesnerr << 7) & ~((uint16_t)0x00000080)) == 0); + EM_BLE_WR(EM_BLE_RXSTATCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXSTATCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00000080)) | ((uint16_t)nesnerr << 7)); +} + +__INLINE uint8_t em_ble_rxstatce_sn_err_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXSTATCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000040)) >> 6); +} + +__INLINE void em_ble_rxstatce_sn_err_setf(int elt_idx, uint8_t snerr) +{ + BLE_ASSERT_ERR((((uint16_t)snerr << 6) & ~((uint16_t)0x00000040)) == 0); + EM_BLE_WR(EM_BLE_RXSTATCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXSTATCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00000040)) | ((uint16_t)snerr << 6)); +} + +__INLINE uint8_t em_ble_rxstatce_llid_err_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXSTATCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000020)) >> 5); +} + +__INLINE void em_ble_rxstatce_llid_err_setf(int elt_idx, uint8_t lliderr) +{ + BLE_ASSERT_ERR((((uint16_t)lliderr << 5) & ~((uint16_t)0x00000020)) == 0); + EM_BLE_WR(EM_BLE_RXSTATCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXSTATCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00000020)) | ((uint16_t)lliderr << 5)); +} + +__INLINE uint8_t em_ble_rxstatce_mic_err_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXSTATCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000010)) >> 4); +} + +__INLINE void em_ble_rxstatce_mic_err_setf(int elt_idx, uint8_t micerr) +{ + BLE_ASSERT_ERR((((uint16_t)micerr << 4) & ~((uint16_t)0x00000010)) == 0); + EM_BLE_WR(EM_BLE_RXSTATCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXSTATCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00000010)) | ((uint16_t)micerr << 4)); +} + +__INLINE uint8_t em_ble_rxstatce_crc_err_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXSTATCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000008)) >> 3); +} + +__INLINE void em_ble_rxstatce_crc_err_setf(int elt_idx, uint8_t crcerr) +{ + BLE_ASSERT_ERR((((uint16_t)crcerr << 3) & ~((uint16_t)0x00000008)) == 0); + EM_BLE_WR(EM_BLE_RXSTATCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXSTATCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00000008)) | ((uint16_t)crcerr << 3)); +} + +__INLINE uint8_t em_ble_rxstatce_len_err_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXSTATCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000004)) >> 2); +} + +__INLINE void em_ble_rxstatce_len_err_setf(int elt_idx, uint8_t lenerr) +{ + BLE_ASSERT_ERR((((uint16_t)lenerr << 2) & ~((uint16_t)0x00000004)) == 0); + EM_BLE_WR(EM_BLE_RXSTATCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXSTATCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00000004)) | ((uint16_t)lenerr << 2)); +} + +__INLINE uint8_t em_ble_rxstatce_rxtime_err_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXSTATCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000002)) >> 1); +} + +__INLINE void em_ble_rxstatce_rxtime_err_setf(int elt_idx, uint8_t rxtimeerr) +{ + BLE_ASSERT_ERR((((uint16_t)rxtimeerr << 1) & ~((uint16_t)0x00000002)) == 0); + EM_BLE_WR(EM_BLE_RXSTATCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXSTATCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00000002)) | ((uint16_t)rxtimeerr << 1)); +} + +__INLINE uint8_t em_ble_rxstatce_sync_err_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXSTATCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000001)) >> 0); +} + +__INLINE void em_ble_rxstatce_sync_err_setf(int elt_idx, uint8_t syncerr) +{ + BLE_ASSERT_ERR((((uint16_t)syncerr << 0) & ~((uint16_t)0x00000001)) == 0); + EM_BLE_WR(EM_BLE_RXSTATCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXSTATCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00000001)) | ((uint16_t)syncerr << 0)); +} + +/** + * @brief RXSTATADV register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     15             RXCTEERR   0
+ *     11         FOLLOWAUXPTR   0
+ *     10     DEV_FILTERING_OK   0
+ *     09               IN_WHL   0
+ *     08          IN_PERADVAL   0
+ *     07       PEER_ADD_MATCH   0
+ *     06         BDADDR_MATCH   0
+ *     05             TYPE_ERR   0
+ *     04             PRIV_ERR   0
+ *     03              CRC_ERR   0
+ *     02              LEN_ERR   0
+ *     01           RXTIME_ERR   0
+ *     00             SYNC_ERR   0
+ * 
+ */ +#define EM_BLE_RXSTATADV_ADDR (0x00910002 + EM_BLE_RX_DESC_OFFSET) +#define EM_BLE_RXSTATADV_INDEX 0x00000001 +#define EM_BLE_RXSTATADV_RESET 0x00000000 + +__INLINE uint16_t em_ble_rxstatadv_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_RXSTATADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); +} + +__INLINE void em_ble_rxstatadv_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_RXSTATADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, value); +} + +// field definitions +#define EM_BLE_RXCTEERR_BIT ((uint16_t)0x00008000) +#define EM_BLE_RXCTEERR_POS 15 +#define EM_BLE_FOLLOWAUXPTR_BIT ((uint16_t)0x00000800) +#define EM_BLE_FOLLOWAUXPTR_POS 11 +#define EM_BLE_DEV_FILTERING_OK_BIT ((uint16_t)0x00000400) +#define EM_BLE_DEV_FILTERING_OK_POS 10 +#define EM_BLE_IN_WHL_BIT ((uint16_t)0x00000200) +#define EM_BLE_IN_WHL_POS 9 +#define EM_BLE_IN_PERADVAL_BIT ((uint16_t)0x00000100) +#define EM_BLE_IN_PERADVAL_POS 8 +#define EM_BLE_PEER_ADD_MATCH_BIT ((uint16_t)0x00000080) +#define EM_BLE_PEER_ADD_MATCH_POS 7 +#define EM_BLE_BDADDR_MATCH_BIT ((uint16_t)0x00000040) +#define EM_BLE_BDADDR_MATCH_POS 6 +#define EM_BLE_TYPE_ERR_BIT ((uint16_t)0x00000020) +#define EM_BLE_TYPE_ERR_POS 5 +#define EM_BLE_PRIV_ERR_BIT ((uint16_t)0x00000010) +#define EM_BLE_PRIV_ERR_POS 4 +#define EM_BLE_CRC_ERR_BIT ((uint16_t)0x00000008) +#define EM_BLE_CRC_ERR_POS 3 +#define EM_BLE_LEN_ERR_BIT ((uint16_t)0x00000004) +#define EM_BLE_LEN_ERR_POS 2 +#define EM_BLE_RXTIME_ERR_BIT ((uint16_t)0x00000002) +#define EM_BLE_RXTIME_ERR_POS 1 +#define EM_BLE_SYNC_ERR_BIT ((uint16_t)0x00000001) +#define EM_BLE_SYNC_ERR_POS 0 + +#define EM_BLE_RXCTEERR_RST 0x0 +#define EM_BLE_FOLLOWAUXPTR_RST 0x0 +#define EM_BLE_DEV_FILTERING_OK_RST 0x0 +#define EM_BLE_IN_WHL_RST 0x0 +#define EM_BLE_IN_PERADVAL_RST 0x0 +#define EM_BLE_PEER_ADD_MATCH_RST 0x0 +#define EM_BLE_BDADDR_MATCH_RST 0x0 +#define EM_BLE_TYPE_ERR_RST 0x0 +#define EM_BLE_PRIV_ERR_RST 0x0 +#define EM_BLE_CRC_ERR_RST 0x0 +#define EM_BLE_LEN_ERR_RST 0x0 +#define EM_BLE_RXTIME_ERR_RST 0x0 +#define EM_BLE_SYNC_ERR_RST 0x0 + +__INLINE void em_ble_rxstatadv_pack(int elt_idx, uint8_t rxcteerr, uint8_t followauxptr, uint8_t devfilteringok, uint8_t inwhl, uint8_t inperadval, uint8_t peeraddmatch, uint8_t bdaddrmatch, uint8_t typeerr, uint8_t priverr, uint8_t crcerr, uint8_t lenerr, uint8_t rxtimeerr, uint8_t syncerr) +{ + BLE_ASSERT_ERR((((uint16_t)rxcteerr << 15) & ~((uint16_t)0x00008000)) == 0); + BLE_ASSERT_ERR((((uint16_t)followauxptr << 11) & ~((uint16_t)0x00000800)) == 0); + BLE_ASSERT_ERR((((uint16_t)devfilteringok << 10) & ~((uint16_t)0x00000400)) == 0); + BLE_ASSERT_ERR((((uint16_t)inwhl << 9) & ~((uint16_t)0x00000200)) == 0); + BLE_ASSERT_ERR((((uint16_t)inperadval << 8) & ~((uint16_t)0x00000100)) == 0); + BLE_ASSERT_ERR((((uint16_t)peeraddmatch << 7) & ~((uint16_t)0x00000080)) == 0); + BLE_ASSERT_ERR((((uint16_t)bdaddrmatch << 6) & ~((uint16_t)0x00000040)) == 0); + BLE_ASSERT_ERR((((uint16_t)typeerr << 5) & ~((uint16_t)0x00000020)) == 0); + BLE_ASSERT_ERR((((uint16_t)priverr << 4) & ~((uint16_t)0x00000010)) == 0); + BLE_ASSERT_ERR((((uint16_t)crcerr << 3) & ~((uint16_t)0x00000008)) == 0); + BLE_ASSERT_ERR((((uint16_t)lenerr << 2) & ~((uint16_t)0x00000004)) == 0); + BLE_ASSERT_ERR((((uint16_t)rxtimeerr << 1) & ~((uint16_t)0x00000002)) == 0); + BLE_ASSERT_ERR((((uint16_t)syncerr << 0) & ~((uint16_t)0x00000001)) == 0); + EM_BLE_WR(EM_BLE_RXSTATADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, ((uint16_t)rxcteerr << 15) | ((uint16_t)followauxptr << 11) | ((uint16_t)devfilteringok << 10) | ((uint16_t)inwhl << 9) | ((uint16_t)inperadval << 8) | ((uint16_t)peeraddmatch << 7) | ((uint16_t)bdaddrmatch << 6) | ((uint16_t)typeerr << 5) | ((uint16_t)priverr << 4) | ((uint16_t)crcerr << 3) | ((uint16_t)lenerr << 2) | ((uint16_t)rxtimeerr << 1) | ((uint16_t)syncerr << 0)); +} + +__INLINE void em_ble_rxstatadv_unpack(int elt_idx, uint8_t* rxcteerr, uint8_t* followauxptr, uint8_t* devfilteringok, uint8_t* inwhl, uint8_t* inperadval, uint8_t* peeraddmatch, uint8_t* bdaddrmatch, uint8_t* typeerr, uint8_t* priverr, uint8_t* crcerr, uint8_t* lenerr, uint8_t* rxtimeerr, uint8_t* syncerr) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXSTATADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + + *rxcteerr = (localVal & ((uint16_t)0x00008000)) >> 15; + *followauxptr = (localVal & ((uint16_t)0x00000800)) >> 11; + *devfilteringok = (localVal & ((uint16_t)0x00000400)) >> 10; + *inwhl = (localVal & ((uint16_t)0x00000200)) >> 9; + *inperadval = (localVal & ((uint16_t)0x00000100)) >> 8; + *peeraddmatch = (localVal & ((uint16_t)0x00000080)) >> 7; + *bdaddrmatch = (localVal & ((uint16_t)0x00000040)) >> 6; + *typeerr = (localVal & ((uint16_t)0x00000020)) >> 5; + *priverr = (localVal & ((uint16_t)0x00000010)) >> 4; + *crcerr = (localVal & ((uint16_t)0x00000008)) >> 3; + *lenerr = (localVal & ((uint16_t)0x00000004)) >> 2; + *rxtimeerr = (localVal & ((uint16_t)0x00000002)) >> 1; + *syncerr = (localVal & ((uint16_t)0x00000001)) >> 0; +} + +__INLINE uint8_t em_ble_rxstatadv_rxcteerr_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXSTATADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00008000)) >> 15); +} + +__INLINE void em_ble_rxstatadv_rxcteerr_setf(int elt_idx, uint8_t rxcteerr) +{ + BLE_ASSERT_ERR((((uint16_t)rxcteerr << 15) & ~((uint16_t)0x00008000)) == 0); + EM_BLE_WR(EM_BLE_RXSTATADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXSTATADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00008000)) | ((uint16_t)rxcteerr << 15)); +} + +__INLINE uint8_t em_ble_rxstatadv_followauxptr_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXSTATADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000800)) >> 11); +} + +__INLINE void em_ble_rxstatadv_followauxptr_setf(int elt_idx, uint8_t followauxptr) +{ + BLE_ASSERT_ERR((((uint16_t)followauxptr << 11) & ~((uint16_t)0x00000800)) == 0); + EM_BLE_WR(EM_BLE_RXSTATADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXSTATADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00000800)) | ((uint16_t)followauxptr << 11)); +} + +__INLINE uint8_t em_ble_rxstatadv_dev_filtering_ok_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXSTATADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000400)) >> 10); +} + +__INLINE void em_ble_rxstatadv_dev_filtering_ok_setf(int elt_idx, uint8_t devfilteringok) +{ + BLE_ASSERT_ERR((((uint16_t)devfilteringok << 10) & ~((uint16_t)0x00000400)) == 0); + EM_BLE_WR(EM_BLE_RXSTATADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXSTATADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00000400)) | ((uint16_t)devfilteringok << 10)); +} + +__INLINE uint8_t em_ble_rxstatadv_in_whl_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXSTATADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000200)) >> 9); +} + +__INLINE void em_ble_rxstatadv_in_whl_setf(int elt_idx, uint8_t inwhl) +{ + BLE_ASSERT_ERR((((uint16_t)inwhl << 9) & ~((uint16_t)0x00000200)) == 0); + EM_BLE_WR(EM_BLE_RXSTATADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXSTATADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00000200)) | ((uint16_t)inwhl << 9)); +} + +__INLINE uint8_t em_ble_rxstatadv_in_peradval_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXSTATADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000100)) >> 8); +} + +__INLINE void em_ble_rxstatadv_in_peradval_setf(int elt_idx, uint8_t inperadval) +{ + BLE_ASSERT_ERR((((uint16_t)inperadval << 8) & ~((uint16_t)0x00000100)) == 0); + EM_BLE_WR(EM_BLE_RXSTATADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXSTATADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00000100)) | ((uint16_t)inperadval << 8)); +} + +__INLINE uint8_t em_ble_rxstatadv_peer_add_match_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXSTATADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000080)) >> 7); +} + +__INLINE void em_ble_rxstatadv_peer_add_match_setf(int elt_idx, uint8_t peeraddmatch) +{ + BLE_ASSERT_ERR((((uint16_t)peeraddmatch << 7) & ~((uint16_t)0x00000080)) == 0); + EM_BLE_WR(EM_BLE_RXSTATADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXSTATADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00000080)) | ((uint16_t)peeraddmatch << 7)); +} + +__INLINE uint8_t em_ble_rxstatadv_bdaddr_match_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXSTATADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000040)) >> 6); +} + +__INLINE void em_ble_rxstatadv_bdaddr_match_setf(int elt_idx, uint8_t bdaddrmatch) +{ + BLE_ASSERT_ERR((((uint16_t)bdaddrmatch << 6) & ~((uint16_t)0x00000040)) == 0); + EM_BLE_WR(EM_BLE_RXSTATADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXSTATADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00000040)) | ((uint16_t)bdaddrmatch << 6)); +} + +__INLINE uint8_t em_ble_rxstatadv_type_err_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXSTATADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000020)) >> 5); +} + +__INLINE void em_ble_rxstatadv_type_err_setf(int elt_idx, uint8_t typeerr) +{ + BLE_ASSERT_ERR((((uint16_t)typeerr << 5) & ~((uint16_t)0x00000020)) == 0); + EM_BLE_WR(EM_BLE_RXSTATADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXSTATADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00000020)) | ((uint16_t)typeerr << 5)); +} + +__INLINE uint8_t em_ble_rxstatadv_priv_err_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXSTATADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000010)) >> 4); +} + +__INLINE void em_ble_rxstatadv_priv_err_setf(int elt_idx, uint8_t priverr) +{ + BLE_ASSERT_ERR((((uint16_t)priverr << 4) & ~((uint16_t)0x00000010)) == 0); + EM_BLE_WR(EM_BLE_RXSTATADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXSTATADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00000010)) | ((uint16_t)priverr << 4)); +} + +__INLINE uint8_t em_ble_rxstatadv_crc_err_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXSTATADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000008)) >> 3); +} + +__INLINE void em_ble_rxstatadv_crc_err_setf(int elt_idx, uint8_t crcerr) +{ + BLE_ASSERT_ERR((((uint16_t)crcerr << 3) & ~((uint16_t)0x00000008)) == 0); + EM_BLE_WR(EM_BLE_RXSTATADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXSTATADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00000008)) | ((uint16_t)crcerr << 3)); +} + +__INLINE uint8_t em_ble_rxstatadv_len_err_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXSTATADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000004)) >> 2); +} + +__INLINE void em_ble_rxstatadv_len_err_setf(int elt_idx, uint8_t lenerr) +{ + BLE_ASSERT_ERR((((uint16_t)lenerr << 2) & ~((uint16_t)0x00000004)) == 0); + EM_BLE_WR(EM_BLE_RXSTATADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXSTATADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00000004)) | ((uint16_t)lenerr << 2)); +} + +__INLINE uint8_t em_ble_rxstatadv_rxtime_err_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXSTATADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000002)) >> 1); +} + +__INLINE void em_ble_rxstatadv_rxtime_err_setf(int elt_idx, uint8_t rxtimeerr) +{ + BLE_ASSERT_ERR((((uint16_t)rxtimeerr << 1) & ~((uint16_t)0x00000002)) == 0); + EM_BLE_WR(EM_BLE_RXSTATADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXSTATADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00000002)) | ((uint16_t)rxtimeerr << 1)); +} + +__INLINE uint8_t em_ble_rxstatadv_sync_err_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXSTATADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000001)) >> 0); +} + +__INLINE void em_ble_rxstatadv_sync_err_setf(int elt_idx, uint8_t syncerr) +{ + BLE_ASSERT_ERR((((uint16_t)syncerr << 0) & ~((uint16_t)0x00000001)) == 0); + EM_BLE_WR(EM_BLE_RXSTATADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXSTATADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00000001)) | ((uint16_t)syncerr << 0)); +} + +/** + * @brief RXSTATISOM0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:11         RXSTREAM_LBL   0x0
+ *  10:08          RXGROUP_LBL   0x0
+ *     07             NESN_ERR   0
+ *     06               SN_ERR   0
+ *     05             LLID_ERR   0
+ *     04              MIC_ERR   0
+ *     03              CRC_ERR   0
+ *     02              LEN_ERR   0
+ *     01           RXTIME_ERR   0
+ *     00             SYNC_ERR   0
+ * 
+ */ +#define EM_BLE_RXSTATISOM0_ADDR (0x00910002 + EM_BLE_RX_DESC_OFFSET) +#define EM_BLE_RXSTATISOM0_INDEX 0x00000001 +#define EM_BLE_RXSTATISOM0_RESET 0x00000000 + +__INLINE uint16_t em_ble_rxstatisom0_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_RXSTATISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); +} + +__INLINE void em_ble_rxstatisom0_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_RXSTATISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, value); +} + +// field definitions +#define EM_BLE_RXSTREAM_LBL_MASK ((uint16_t)0x0000F800) +#define EM_BLE_RXSTREAM_LBL_LSB 11 +#define EM_BLE_RXSTREAM_LBL_WIDTH ((uint16_t)0x00000005) +#define EM_BLE_RXGROUP_LBL_MASK ((uint16_t)0x00000700) +#define EM_BLE_RXGROUP_LBL_LSB 8 +#define EM_BLE_RXGROUP_LBL_WIDTH ((uint16_t)0x00000003) +#define EM_BLE_NESN_ERR_BIT ((uint16_t)0x00000080) +#define EM_BLE_NESN_ERR_POS 7 +#define EM_BLE_SN_ERR_BIT ((uint16_t)0x00000040) +#define EM_BLE_SN_ERR_POS 6 +#define EM_BLE_LLID_ERR_BIT ((uint16_t)0x00000020) +#define EM_BLE_LLID_ERR_POS 5 +#define EM_BLE_MIC_ERR_BIT ((uint16_t)0x00000010) +#define EM_BLE_MIC_ERR_POS 4 +#define EM_BLE_CRC_ERR_BIT ((uint16_t)0x00000008) +#define EM_BLE_CRC_ERR_POS 3 +#define EM_BLE_LEN_ERR_BIT ((uint16_t)0x00000004) +#define EM_BLE_LEN_ERR_POS 2 +#define EM_BLE_RXTIME_ERR_BIT ((uint16_t)0x00000002) +#define EM_BLE_RXTIME_ERR_POS 1 +#define EM_BLE_SYNC_ERR_BIT ((uint16_t)0x00000001) +#define EM_BLE_SYNC_ERR_POS 0 + +#define EM_BLE_RXSTREAM_LBL_RST 0x0 +#define EM_BLE_RXGROUP_LBL_RST 0x0 +#define EM_BLE_NESN_ERR_RST 0x0 +#define EM_BLE_SN_ERR_RST 0x0 +#define EM_BLE_LLID_ERR_RST 0x0 +#define EM_BLE_MIC_ERR_RST 0x0 +#define EM_BLE_CRC_ERR_RST 0x0 +#define EM_BLE_LEN_ERR_RST 0x0 +#define EM_BLE_RXTIME_ERR_RST 0x0 +#define EM_BLE_SYNC_ERR_RST 0x0 + +__INLINE void em_ble_rxstatisom0_pack(int elt_idx, uint8_t rxstreamlbl, uint8_t rxgrouplbl, uint8_t nesnerr, uint8_t snerr, uint8_t lliderr, uint8_t micerr, uint8_t crcerr, uint8_t lenerr, uint8_t rxtimeerr, uint8_t syncerr) +{ + BLE_ASSERT_ERR((((uint16_t)rxstreamlbl << 11) & ~((uint16_t)0x0000F800)) == 0); + BLE_ASSERT_ERR((((uint16_t)rxgrouplbl << 8) & ~((uint16_t)0x00000700)) == 0); + BLE_ASSERT_ERR((((uint16_t)nesnerr << 7) & ~((uint16_t)0x00000080)) == 0); + BLE_ASSERT_ERR((((uint16_t)snerr << 6) & ~((uint16_t)0x00000040)) == 0); + BLE_ASSERT_ERR((((uint16_t)lliderr << 5) & ~((uint16_t)0x00000020)) == 0); + BLE_ASSERT_ERR((((uint16_t)micerr << 4) & ~((uint16_t)0x00000010)) == 0); + BLE_ASSERT_ERR((((uint16_t)crcerr << 3) & ~((uint16_t)0x00000008)) == 0); + BLE_ASSERT_ERR((((uint16_t)lenerr << 2) & ~((uint16_t)0x00000004)) == 0); + BLE_ASSERT_ERR((((uint16_t)rxtimeerr << 1) & ~((uint16_t)0x00000002)) == 0); + BLE_ASSERT_ERR((((uint16_t)syncerr << 0) & ~((uint16_t)0x00000001)) == 0); + EM_BLE_WR(EM_BLE_RXSTATISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, ((uint16_t)rxstreamlbl << 11) | ((uint16_t)rxgrouplbl << 8) | ((uint16_t)nesnerr << 7) | ((uint16_t)snerr << 6) | ((uint16_t)lliderr << 5) | ((uint16_t)micerr << 4) | ((uint16_t)crcerr << 3) | ((uint16_t)lenerr << 2) | ((uint16_t)rxtimeerr << 1) | ((uint16_t)syncerr << 0)); +} + +__INLINE void em_ble_rxstatisom0_unpack(int elt_idx, uint8_t* rxstreamlbl, uint8_t* rxgrouplbl, uint8_t* nesnerr, uint8_t* snerr, uint8_t* lliderr, uint8_t* micerr, uint8_t* crcerr, uint8_t* lenerr, uint8_t* rxtimeerr, uint8_t* syncerr) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXSTATISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + + *rxstreamlbl = (localVal & ((uint16_t)0x0000F800)) >> 11; + *rxgrouplbl = (localVal & ((uint16_t)0x00000700)) >> 8; + *nesnerr = (localVal & ((uint16_t)0x00000080)) >> 7; + *snerr = (localVal & ((uint16_t)0x00000040)) >> 6; + *lliderr = (localVal & ((uint16_t)0x00000020)) >> 5; + *micerr = (localVal & ((uint16_t)0x00000010)) >> 4; + *crcerr = (localVal & ((uint16_t)0x00000008)) >> 3; + *lenerr = (localVal & ((uint16_t)0x00000004)) >> 2; + *rxtimeerr = (localVal & ((uint16_t)0x00000002)) >> 1; + *syncerr = (localVal & ((uint16_t)0x00000001)) >> 0; +} + +__INLINE uint8_t em_ble_rxstatisom0_rxstream_lbl_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXSTATISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x0000F800)) >> 11); +} + +__INLINE void em_ble_rxstatisom0_rxstream_lbl_setf(int elt_idx, uint8_t rxstreamlbl) +{ + BLE_ASSERT_ERR((((uint16_t)rxstreamlbl << 11) & ~((uint16_t)0x0000F800)) == 0); + EM_BLE_WR(EM_BLE_RXSTATISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXSTATISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x0000F800)) | ((uint16_t)rxstreamlbl << 11)); +} + +__INLINE uint8_t em_ble_rxstatisom0_rxgroup_lbl_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXSTATISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000700)) >> 8); +} + +__INLINE void em_ble_rxstatisom0_rxgroup_lbl_setf(int elt_idx, uint8_t rxgrouplbl) +{ + BLE_ASSERT_ERR((((uint16_t)rxgrouplbl << 8) & ~((uint16_t)0x00000700)) == 0); + EM_BLE_WR(EM_BLE_RXSTATISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXSTATISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00000700)) | ((uint16_t)rxgrouplbl << 8)); +} + +__INLINE uint8_t em_ble_rxstatisom0_nesn_err_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXSTATISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000080)) >> 7); +} + +__INLINE void em_ble_rxstatisom0_nesn_err_setf(int elt_idx, uint8_t nesnerr) +{ + BLE_ASSERT_ERR((((uint16_t)nesnerr << 7) & ~((uint16_t)0x00000080)) == 0); + EM_BLE_WR(EM_BLE_RXSTATISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXSTATISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00000080)) | ((uint16_t)nesnerr << 7)); +} + +__INLINE uint8_t em_ble_rxstatisom0_sn_err_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXSTATISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000040)) >> 6); +} + +__INLINE void em_ble_rxstatisom0_sn_err_setf(int elt_idx, uint8_t snerr) +{ + BLE_ASSERT_ERR((((uint16_t)snerr << 6) & ~((uint16_t)0x00000040)) == 0); + EM_BLE_WR(EM_BLE_RXSTATISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXSTATISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00000040)) | ((uint16_t)snerr << 6)); +} + +__INLINE uint8_t em_ble_rxstatisom0_llid_err_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXSTATISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000020)) >> 5); +} + +__INLINE void em_ble_rxstatisom0_llid_err_setf(int elt_idx, uint8_t lliderr) +{ + BLE_ASSERT_ERR((((uint16_t)lliderr << 5) & ~((uint16_t)0x00000020)) == 0); + EM_BLE_WR(EM_BLE_RXSTATISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXSTATISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00000020)) | ((uint16_t)lliderr << 5)); +} + +__INLINE uint8_t em_ble_rxstatisom0_mic_err_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXSTATISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000010)) >> 4); +} + +__INLINE void em_ble_rxstatisom0_mic_err_setf(int elt_idx, uint8_t micerr) +{ + BLE_ASSERT_ERR((((uint16_t)micerr << 4) & ~((uint16_t)0x00000010)) == 0); + EM_BLE_WR(EM_BLE_RXSTATISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXSTATISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00000010)) | ((uint16_t)micerr << 4)); +} + +__INLINE uint8_t em_ble_rxstatisom0_crc_err_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXSTATISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000008)) >> 3); +} + +__INLINE void em_ble_rxstatisom0_crc_err_setf(int elt_idx, uint8_t crcerr) +{ + BLE_ASSERT_ERR((((uint16_t)crcerr << 3) & ~((uint16_t)0x00000008)) == 0); + EM_BLE_WR(EM_BLE_RXSTATISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXSTATISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00000008)) | ((uint16_t)crcerr << 3)); +} + +__INLINE uint8_t em_ble_rxstatisom0_len_err_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXSTATISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000004)) >> 2); +} + +__INLINE void em_ble_rxstatisom0_len_err_setf(int elt_idx, uint8_t lenerr) +{ + BLE_ASSERT_ERR((((uint16_t)lenerr << 2) & ~((uint16_t)0x00000004)) == 0); + EM_BLE_WR(EM_BLE_RXSTATISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXSTATISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00000004)) | ((uint16_t)lenerr << 2)); +} + +__INLINE uint8_t em_ble_rxstatisom0_rxtime_err_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXSTATISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000002)) >> 1); +} + +__INLINE void em_ble_rxstatisom0_rxtime_err_setf(int elt_idx, uint8_t rxtimeerr) +{ + BLE_ASSERT_ERR((((uint16_t)rxtimeerr << 1) & ~((uint16_t)0x00000002)) == 0); + EM_BLE_WR(EM_BLE_RXSTATISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXSTATISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00000002)) | ((uint16_t)rxtimeerr << 1)); +} + +__INLINE uint8_t em_ble_rxstatisom0_sync_err_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXSTATISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000001)) >> 0); +} + +__INLINE void em_ble_rxstatisom0_sync_err_setf(int elt_idx, uint8_t syncerr) +{ + BLE_ASSERT_ERR((((uint16_t)syncerr << 0) & ~((uint16_t)0x00000001)) == 0); + EM_BLE_WR(EM_BLE_RXSTATISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXSTATISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00000001)) | ((uint16_t)syncerr << 0)); +} + +/** + * @brief RXPHCE register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:08                RXLEN   0x0
+ *  07:06             RXACLRFU   0x0
+ *     05                 RXCP   0
+ *     04                 RXMD   0
+ *     03                 RXSN   0
+ *     02               RXNESN   0
+ *  01:00               RXLLID   0x0
+ * 
+ */ +#define EM_BLE_RXPHCE_ADDR (0x00910004 + EM_BLE_RX_DESC_OFFSET) +#define EM_BLE_RXPHCE_INDEX 0x00000002 +#define EM_BLE_RXPHCE_RESET 0x00000000 + +__INLINE uint16_t em_ble_rxphce_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_RXPHCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); +} + +__INLINE void em_ble_rxphce_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_RXPHCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, value); +} + +// field definitions +#define EM_BLE_RXLEN_MASK ((uint16_t)0x0000FF00) +#define EM_BLE_RXLEN_LSB 8 +#define EM_BLE_RXLEN_WIDTH ((uint16_t)0x00000008) +#define EM_BLE_RXACLRFU_MASK ((uint16_t)0x000000C0) +#define EM_BLE_RXACLRFU_LSB 6 +#define EM_BLE_RXACLRFU_WIDTH ((uint16_t)0x00000002) +#define EM_BLE_RXCP_BIT ((uint16_t)0x00000020) +#define EM_BLE_RXCP_POS 5 +#define EM_BLE_RXMD_BIT ((uint16_t)0x00000010) +#define EM_BLE_RXMD_POS 4 +#define EM_BLE_RXSN_BIT ((uint16_t)0x00000008) +#define EM_BLE_RXSN_POS 3 +#define EM_BLE_RXNESN_BIT ((uint16_t)0x00000004) +#define EM_BLE_RXNESN_POS 2 +#define EM_BLE_RXLLID_MASK ((uint16_t)0x00000003) +#define EM_BLE_RXLLID_LSB 0 +#define EM_BLE_RXLLID_WIDTH ((uint16_t)0x00000002) + +#define EM_BLE_RXLEN_RST 0x0 +#define EM_BLE_RXACLRFU_RST 0x0 +#define EM_BLE_RXCP_RST 0x0 +#define EM_BLE_RXMD_RST 0x0 +#define EM_BLE_RXSN_RST 0x0 +#define EM_BLE_RXNESN_RST 0x0 +#define EM_BLE_RXLLID_RST 0x0 + +__INLINE void em_ble_rxphce_pack(int elt_idx, uint8_t rxlen, uint8_t rxaclrfu, uint8_t rxcp, uint8_t rxmd, uint8_t rxsn, uint8_t rxnesn, uint8_t rxllid) +{ + BLE_ASSERT_ERR((((uint16_t)rxlen << 8) & ~((uint16_t)0x0000FF00)) == 0); + BLE_ASSERT_ERR((((uint16_t)rxaclrfu << 6) & ~((uint16_t)0x000000C0)) == 0); + BLE_ASSERT_ERR((((uint16_t)rxcp << 5) & ~((uint16_t)0x00000020)) == 0); + BLE_ASSERT_ERR((((uint16_t)rxmd << 4) & ~((uint16_t)0x00000010)) == 0); + BLE_ASSERT_ERR((((uint16_t)rxsn << 3) & ~((uint16_t)0x00000008)) == 0); + BLE_ASSERT_ERR((((uint16_t)rxnesn << 2) & ~((uint16_t)0x00000004)) == 0); + BLE_ASSERT_ERR((((uint16_t)rxllid << 0) & ~((uint16_t)0x00000003)) == 0); + EM_BLE_WR(EM_BLE_RXPHCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, ((uint16_t)rxlen << 8) | ((uint16_t)rxaclrfu << 6) | ((uint16_t)rxcp << 5) | ((uint16_t)rxmd << 4) | ((uint16_t)rxsn << 3) | ((uint16_t)rxnesn << 2) | ((uint16_t)rxllid << 0)); +} + +__INLINE void em_ble_rxphce_unpack(int elt_idx, uint8_t* rxlen, uint8_t* rxaclrfu, uint8_t* rxcp, uint8_t* rxmd, uint8_t* rxsn, uint8_t* rxnesn, uint8_t* rxllid) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXPHCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + + *rxlen = (localVal & ((uint16_t)0x0000FF00)) >> 8; + *rxaclrfu = (localVal & ((uint16_t)0x000000C0)) >> 6; + *rxcp = (localVal & ((uint16_t)0x00000020)) >> 5; + *rxmd = (localVal & ((uint16_t)0x00000010)) >> 4; + *rxsn = (localVal & ((uint16_t)0x00000008)) >> 3; + *rxnesn = (localVal & ((uint16_t)0x00000004)) >> 2; + *rxllid = (localVal & ((uint16_t)0x00000003)) >> 0; +} + +__INLINE uint8_t em_ble_rxphce_rxlen_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXPHCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x0000FF00)) >> 8); +} + +__INLINE void em_ble_rxphce_rxlen_setf(int elt_idx, uint8_t rxlen) +{ + BLE_ASSERT_ERR((((uint16_t)rxlen << 8) & ~((uint16_t)0x0000FF00)) == 0); + EM_BLE_WR(EM_BLE_RXPHCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXPHCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x0000FF00)) | ((uint16_t)rxlen << 8)); +} + +__INLINE uint8_t em_ble_rxphce_rxaclrfu_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXPHCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x000000C0)) >> 6); +} + +__INLINE void em_ble_rxphce_rxaclrfu_setf(int elt_idx, uint8_t rxaclrfu) +{ + BLE_ASSERT_ERR((((uint16_t)rxaclrfu << 6) & ~((uint16_t)0x000000C0)) == 0); + EM_BLE_WR(EM_BLE_RXPHCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXPHCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x000000C0)) | ((uint16_t)rxaclrfu << 6)); +} + +__INLINE uint8_t em_ble_rxphce_rxcp_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXPHCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000020)) >> 5); +} + +__INLINE void em_ble_rxphce_rxcp_setf(int elt_idx, uint8_t rxcp) +{ + BLE_ASSERT_ERR((((uint16_t)rxcp << 5) & ~((uint16_t)0x00000020)) == 0); + EM_BLE_WR(EM_BLE_RXPHCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXPHCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00000020)) | ((uint16_t)rxcp << 5)); +} + +__INLINE uint8_t em_ble_rxphce_rxmd_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXPHCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000010)) >> 4); +} + +__INLINE void em_ble_rxphce_rxmd_setf(int elt_idx, uint8_t rxmd) +{ + BLE_ASSERT_ERR((((uint16_t)rxmd << 4) & ~((uint16_t)0x00000010)) == 0); + EM_BLE_WR(EM_BLE_RXPHCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXPHCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00000010)) | ((uint16_t)rxmd << 4)); +} + +__INLINE uint8_t em_ble_rxphce_rxsn_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXPHCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000008)) >> 3); +} + +__INLINE void em_ble_rxphce_rxsn_setf(int elt_idx, uint8_t rxsn) +{ + BLE_ASSERT_ERR((((uint16_t)rxsn << 3) & ~((uint16_t)0x00000008)) == 0); + EM_BLE_WR(EM_BLE_RXPHCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXPHCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00000008)) | ((uint16_t)rxsn << 3)); +} + +__INLINE uint8_t em_ble_rxphce_rxnesn_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXPHCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000004)) >> 2); +} + +__INLINE void em_ble_rxphce_rxnesn_setf(int elt_idx, uint8_t rxnesn) +{ + BLE_ASSERT_ERR((((uint16_t)rxnesn << 2) & ~((uint16_t)0x00000004)) == 0); + EM_BLE_WR(EM_BLE_RXPHCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXPHCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00000004)) | ((uint16_t)rxnesn << 2)); +} + +__INLINE uint8_t em_ble_rxphce_rxllid_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXPHCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000003)) >> 0); +} + +__INLINE void em_ble_rxphce_rxllid_setf(int elt_idx, uint8_t rxllid) +{ + BLE_ASSERT_ERR((((uint16_t)rxllid << 0) & ~((uint16_t)0x00000003)) == 0); + EM_BLE_WR(EM_BLE_RXPHCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXPHCE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00000003)) | ((uint16_t)rxllid << 0)); +} + +/** + * @brief RXPHADV register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:08             RXADVLEN   0x0
+ *     07              RXRXADD   0
+ *     06              RXTXADD   0
+ *     05             RXCHSEL2   0
+ *     04             RXADVRFU   0
+ *  03:00               RXTYPE   0x0
+ * 
+ */ +#define EM_BLE_RXPHADV_ADDR (0x00910004 + EM_BLE_RX_DESC_OFFSET) +#define EM_BLE_RXPHADV_INDEX 0x00000002 +#define EM_BLE_RXPHADV_RESET 0x00000000 + +__INLINE uint16_t em_ble_rxphadv_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_RXPHADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); +} + +__INLINE void em_ble_rxphadv_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_RXPHADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, value); +} + +// field definitions +#define EM_BLE_RXADVLEN_MASK ((uint16_t)0x0000FF00) +#define EM_BLE_RXADVLEN_LSB 8 +#define EM_BLE_RXADVLEN_WIDTH ((uint16_t)0x00000008) +#define EM_BLE_RXRXADD_BIT ((uint16_t)0x00000080) +#define EM_BLE_RXRXADD_POS 7 +#define EM_BLE_RXTXADD_BIT ((uint16_t)0x00000040) +#define EM_BLE_RXTXADD_POS 6 +#define EM_BLE_RXCHSEL2_BIT ((uint16_t)0x00000020) +#define EM_BLE_RXCHSEL2_POS 5 +#define EM_BLE_RXADVRFU_BIT ((uint16_t)0x00000010) +#define EM_BLE_RXADVRFU_POS 4 +#define EM_BLE_RXTYPE_MASK ((uint16_t)0x0000000F) +#define EM_BLE_RXTYPE_LSB 0 +#define EM_BLE_RXTYPE_WIDTH ((uint16_t)0x00000004) + +#define EM_BLE_RXADVLEN_RST 0x0 +#define EM_BLE_RXRXADD_RST 0x0 +#define EM_BLE_RXTXADD_RST 0x0 +#define EM_BLE_RXCHSEL2_RST 0x0 +#define EM_BLE_RXADVRFU_RST 0x0 +#define EM_BLE_RXTYPE_RST 0x0 + +__INLINE void em_ble_rxphadv_pack(int elt_idx, uint8_t rxadvlen, uint8_t rxrxadd, uint8_t rxtxadd, uint8_t rxchsel2, uint8_t rxadvrfu, uint8_t rxtype) +{ + BLE_ASSERT_ERR((((uint16_t)rxadvlen << 8) & ~((uint16_t)0x0000FF00)) == 0); + BLE_ASSERT_ERR((((uint16_t)rxrxadd << 7) & ~((uint16_t)0x00000080)) == 0); + BLE_ASSERT_ERR((((uint16_t)rxtxadd << 6) & ~((uint16_t)0x00000040)) == 0); + BLE_ASSERT_ERR((((uint16_t)rxchsel2 << 5) & ~((uint16_t)0x00000020)) == 0); + BLE_ASSERT_ERR((((uint16_t)rxadvrfu << 4) & ~((uint16_t)0x00000010)) == 0); + BLE_ASSERT_ERR((((uint16_t)rxtype << 0) & ~((uint16_t)0x0000000F)) == 0); + EM_BLE_WR(EM_BLE_RXPHADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, ((uint16_t)rxadvlen << 8) | ((uint16_t)rxrxadd << 7) | ((uint16_t)rxtxadd << 6) | ((uint16_t)rxchsel2 << 5) | ((uint16_t)rxadvrfu << 4) | ((uint16_t)rxtype << 0)); +} + +__INLINE void em_ble_rxphadv_unpack(int elt_idx, uint8_t* rxadvlen, uint8_t* rxrxadd, uint8_t* rxtxadd, uint8_t* rxchsel2, uint8_t* rxadvrfu, uint8_t* rxtype) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXPHADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + + *rxadvlen = (localVal & ((uint16_t)0x0000FF00)) >> 8; + *rxrxadd = (localVal & ((uint16_t)0x00000080)) >> 7; + *rxtxadd = (localVal & ((uint16_t)0x00000040)) >> 6; + *rxchsel2 = (localVal & ((uint16_t)0x00000020)) >> 5; + *rxadvrfu = (localVal & ((uint16_t)0x00000010)) >> 4; + *rxtype = (localVal & ((uint16_t)0x0000000F)) >> 0; +} + +__INLINE uint8_t em_ble_rxphadv_rxadvlen_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXPHADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x0000FF00)) >> 8); +} + +__INLINE void em_ble_rxphadv_rxadvlen_setf(int elt_idx, uint8_t rxadvlen) +{ + BLE_ASSERT_ERR((((uint16_t)rxadvlen << 8) & ~((uint16_t)0x0000FF00)) == 0); + EM_BLE_WR(EM_BLE_RXPHADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXPHADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x0000FF00)) | ((uint16_t)rxadvlen << 8)); +} + +__INLINE uint8_t em_ble_rxphadv_rxrxadd_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXPHADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000080)) >> 7); +} + +__INLINE void em_ble_rxphadv_rxrxadd_setf(int elt_idx, uint8_t rxrxadd) +{ + BLE_ASSERT_ERR((((uint16_t)rxrxadd << 7) & ~((uint16_t)0x00000080)) == 0); + EM_BLE_WR(EM_BLE_RXPHADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXPHADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00000080)) | ((uint16_t)rxrxadd << 7)); +} + +__INLINE uint8_t em_ble_rxphadv_rxtxadd_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXPHADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000040)) >> 6); +} + +__INLINE void em_ble_rxphadv_rxtxadd_setf(int elt_idx, uint8_t rxtxadd) +{ + BLE_ASSERT_ERR((((uint16_t)rxtxadd << 6) & ~((uint16_t)0x00000040)) == 0); + EM_BLE_WR(EM_BLE_RXPHADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXPHADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00000040)) | ((uint16_t)rxtxadd << 6)); +} + +__INLINE uint8_t em_ble_rxphadv_rxchsel2_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXPHADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000020)) >> 5); +} + +__INLINE void em_ble_rxphadv_rxchsel2_setf(int elt_idx, uint8_t rxchsel2) +{ + BLE_ASSERT_ERR((((uint16_t)rxchsel2 << 5) & ~((uint16_t)0x00000020)) == 0); + EM_BLE_WR(EM_BLE_RXPHADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXPHADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00000020)) | ((uint16_t)rxchsel2 << 5)); +} + +__INLINE uint8_t em_ble_rxphadv_rxadvrfu_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXPHADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000010)) >> 4); +} + +__INLINE void em_ble_rxphadv_rxadvrfu_setf(int elt_idx, uint8_t rxadvrfu) +{ + BLE_ASSERT_ERR((((uint16_t)rxadvrfu << 4) & ~((uint16_t)0x00000010)) == 0); + EM_BLE_WR(EM_BLE_RXPHADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXPHADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00000010)) | ((uint16_t)rxadvrfu << 4)); +} + +__INLINE uint8_t em_ble_rxphadv_rxtype_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXPHADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x0000000F)) >> 0); +} + +__INLINE void em_ble_rxphadv_rxtype_setf(int elt_idx, uint8_t rxtype) +{ + BLE_ASSERT_ERR((((uint16_t)rxtype << 0) & ~((uint16_t)0x0000000F)) == 0); + EM_BLE_WR(EM_BLE_RXPHADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXPHADV_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x0000000F)) | ((uint16_t)rxtype << 0)); +} + +/** + * @brief RXPHISOM0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:08                RXLEN   0x0
+ *  07:05           RXISOM0RFU   0x0
+ *     04                 RXMD   0
+ *     03                 RXSN   0
+ *     02               RXNESN   0
+ *  01:00               RXLLID   0x0
+ * 
+ */ +#define EM_BLE_RXPHISOM0_ADDR (0x00910004 + EM_BLE_RX_DESC_OFFSET) +#define EM_BLE_RXPHISOM0_INDEX 0x00000002 +#define EM_BLE_RXPHISOM0_RESET 0x00000000 + +__INLINE uint16_t em_ble_rxphisom0_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_RXPHISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); +} + +__INLINE void em_ble_rxphisom0_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_RXPHISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, value); +} + +// field definitions +#define EM_BLE_RXLEN_MASK ((uint16_t)0x0000FF00) +#define EM_BLE_RXLEN_LSB 8 +#define EM_BLE_RXLEN_WIDTH ((uint16_t)0x00000008) +#define EM_BLE_RXISOM0RFU_MASK ((uint16_t)0x000000E0) +#define EM_BLE_RXISOM0RFU_LSB 5 +#define EM_BLE_RXISOM0RFU_WIDTH ((uint16_t)0x00000003) +#define EM_BLE_RXMD_BIT ((uint16_t)0x00000010) +#define EM_BLE_RXMD_POS 4 +#define EM_BLE_RXSN_BIT ((uint16_t)0x00000008) +#define EM_BLE_RXSN_POS 3 +#define EM_BLE_RXNESN_BIT ((uint16_t)0x00000004) +#define EM_BLE_RXNESN_POS 2 +#define EM_BLE_RXLLID_MASK ((uint16_t)0x00000003) +#define EM_BLE_RXLLID_LSB 0 +#define EM_BLE_RXLLID_WIDTH ((uint16_t)0x00000002) + +#define EM_BLE_RXLEN_RST 0x0 +#define EM_BLE_RXISOM0RFU_RST 0x0 +#define EM_BLE_RXMD_RST 0x0 +#define EM_BLE_RXSN_RST 0x0 +#define EM_BLE_RXNESN_RST 0x0 +#define EM_BLE_RXLLID_RST 0x0 + +__INLINE void em_ble_rxphisom0_pack(int elt_idx, uint8_t rxlen, uint8_t rxisom0rfu, uint8_t rxmd, uint8_t rxsn, uint8_t rxnesn, uint8_t rxllid) +{ + BLE_ASSERT_ERR((((uint16_t)rxlen << 8) & ~((uint16_t)0x0000FF00)) == 0); + BLE_ASSERT_ERR((((uint16_t)rxisom0rfu << 5) & ~((uint16_t)0x000000E0)) == 0); + BLE_ASSERT_ERR((((uint16_t)rxmd << 4) & ~((uint16_t)0x00000010)) == 0); + BLE_ASSERT_ERR((((uint16_t)rxsn << 3) & ~((uint16_t)0x00000008)) == 0); + BLE_ASSERT_ERR((((uint16_t)rxnesn << 2) & ~((uint16_t)0x00000004)) == 0); + BLE_ASSERT_ERR((((uint16_t)rxllid << 0) & ~((uint16_t)0x00000003)) == 0); + EM_BLE_WR(EM_BLE_RXPHISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, ((uint16_t)rxlen << 8) | ((uint16_t)rxisom0rfu << 5) | ((uint16_t)rxmd << 4) | ((uint16_t)rxsn << 3) | ((uint16_t)rxnesn << 2) | ((uint16_t)rxllid << 0)); +} + +__INLINE void em_ble_rxphisom0_unpack(int elt_idx, uint8_t* rxlen, uint8_t* rxisom0rfu, uint8_t* rxmd, uint8_t* rxsn, uint8_t* rxnesn, uint8_t* rxllid) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXPHISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + + *rxlen = (localVal & ((uint16_t)0x0000FF00)) >> 8; + *rxisom0rfu = (localVal & ((uint16_t)0x000000E0)) >> 5; + *rxmd = (localVal & ((uint16_t)0x00000010)) >> 4; + *rxsn = (localVal & ((uint16_t)0x00000008)) >> 3; + *rxnesn = (localVal & ((uint16_t)0x00000004)) >> 2; + *rxllid = (localVal & ((uint16_t)0x00000003)) >> 0; +} + +__INLINE uint8_t em_ble_rxphisom0_rxlen_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXPHISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x0000FF00)) >> 8); +} + +__INLINE void em_ble_rxphisom0_rxlen_setf(int elt_idx, uint8_t rxlen) +{ + BLE_ASSERT_ERR((((uint16_t)rxlen << 8) & ~((uint16_t)0x0000FF00)) == 0); + EM_BLE_WR(EM_BLE_RXPHISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXPHISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x0000FF00)) | ((uint16_t)rxlen << 8)); +} + +__INLINE uint8_t em_ble_rxphisom0_rxisom0rfu_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXPHISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x000000E0)) >> 5); +} + +__INLINE void em_ble_rxphisom0_rxisom0rfu_setf(int elt_idx, uint8_t rxisom0rfu) +{ + BLE_ASSERT_ERR((((uint16_t)rxisom0rfu << 5) & ~((uint16_t)0x000000E0)) == 0); + EM_BLE_WR(EM_BLE_RXPHISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXPHISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x000000E0)) | ((uint16_t)rxisom0rfu << 5)); +} + +__INLINE uint8_t em_ble_rxphisom0_rxmd_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXPHISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000010)) >> 4); +} + +__INLINE void em_ble_rxphisom0_rxmd_setf(int elt_idx, uint8_t rxmd) +{ + BLE_ASSERT_ERR((((uint16_t)rxmd << 4) & ~((uint16_t)0x00000010)) == 0); + EM_BLE_WR(EM_BLE_RXPHISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXPHISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00000010)) | ((uint16_t)rxmd << 4)); +} + +__INLINE uint8_t em_ble_rxphisom0_rxsn_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXPHISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000008)) >> 3); +} + +__INLINE void em_ble_rxphisom0_rxsn_setf(int elt_idx, uint8_t rxsn) +{ + BLE_ASSERT_ERR((((uint16_t)rxsn << 3) & ~((uint16_t)0x00000008)) == 0); + EM_BLE_WR(EM_BLE_RXPHISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXPHISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00000008)) | ((uint16_t)rxsn << 3)); +} + +__INLINE uint8_t em_ble_rxphisom0_rxnesn_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXPHISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000004)) >> 2); +} + +__INLINE void em_ble_rxphisom0_rxnesn_setf(int elt_idx, uint8_t rxnesn) +{ + BLE_ASSERT_ERR((((uint16_t)rxnesn << 2) & ~((uint16_t)0x00000004)) == 0); + EM_BLE_WR(EM_BLE_RXPHISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXPHISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00000004)) | ((uint16_t)rxnesn << 2)); +} + +__INLINE uint8_t em_ble_rxphisom0_rxllid_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXPHISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000003)) >> 0); +} + +__INLINE void em_ble_rxphisom0_rxllid_setf(int elt_idx, uint8_t rxllid) +{ + BLE_ASSERT_ERR((((uint16_t)rxllid << 0) & ~((uint16_t)0x00000003)) == 0); + EM_BLE_WR(EM_BLE_RXPHISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXPHISOM0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00000003)) | ((uint16_t)rxllid << 0)); +} + +/** + * @brief RXCHASS register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:14                 RATE   0x0
+ *  13:08          USED_CH_IDX   0x0
+ *  07:00                 RSSI   0x0
+ * 
+ */ +#define EM_BLE_RXCHASS_ADDR (0x00910006 + EM_BLE_RX_DESC_OFFSET) +#define EM_BLE_RXCHASS_INDEX 0x00000003 +#define EM_BLE_RXCHASS_RESET 0x00000000 + +__INLINE uint16_t em_ble_rxchass_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_RXCHASS_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); +} + +__INLINE void em_ble_rxchass_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_RXCHASS_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, value); +} + +// field definitions +#define EM_BLE_RATE_MASK ((uint16_t)0x0000C000) +#define EM_BLE_RATE_LSB 14 +#define EM_BLE_RATE_WIDTH ((uint16_t)0x00000002) +#define EM_BLE_USED_CH_IDX_MASK ((uint16_t)0x00003F00) +#define EM_BLE_USED_CH_IDX_LSB 8 +#define EM_BLE_USED_CH_IDX_WIDTH ((uint16_t)0x00000006) +#define EM_BLE_RSSI_MASK ((uint16_t)0x000000FF) +#define EM_BLE_RSSI_LSB 0 +#define EM_BLE_RSSI_WIDTH ((uint16_t)0x00000008) + +#define EM_BLE_RATE_RST 0x0 +#define EM_BLE_USED_CH_IDX_RST 0x0 +#define EM_BLE_RSSI_RST 0x0 + +__INLINE void em_ble_rxchass_pack(int elt_idx, uint8_t rate, uint8_t usedchidx, uint8_t rssi) +{ + BLE_ASSERT_ERR((((uint16_t)rate << 14) & ~((uint16_t)0x0000C000)) == 0); + BLE_ASSERT_ERR((((uint16_t)usedchidx << 8) & ~((uint16_t)0x00003F00)) == 0); + BLE_ASSERT_ERR((((uint16_t)rssi << 0) & ~((uint16_t)0x000000FF)) == 0); + EM_BLE_WR(EM_BLE_RXCHASS_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, ((uint16_t)rate << 14) | ((uint16_t)usedchidx << 8) | ((uint16_t)rssi << 0)); +} + +__INLINE void em_ble_rxchass_unpack(int elt_idx, uint8_t* rate, uint8_t* usedchidx, uint8_t* rssi) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXCHASS_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + + *rate = (localVal & ((uint16_t)0x0000C000)) >> 14; + *usedchidx = (localVal & ((uint16_t)0x00003F00)) >> 8; + *rssi = (localVal & ((uint16_t)0x000000FF)) >> 0; +} + +__INLINE uint8_t em_ble_rxchass_rate_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXCHASS_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x0000C000)) >> 14); +} + +__INLINE void em_ble_rxchass_rate_setf(int elt_idx, uint8_t rate) +{ + BLE_ASSERT_ERR((((uint16_t)rate << 14) & ~((uint16_t)0x0000C000)) == 0); + EM_BLE_WR(EM_BLE_RXCHASS_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXCHASS_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x0000C000)) | ((uint16_t)rate << 14)); +} + +__INLINE uint8_t em_ble_rxchass_used_ch_idx_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXCHASS_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00003F00)) >> 8); +} + +__INLINE void em_ble_rxchass_used_ch_idx_setf(int elt_idx, uint8_t usedchidx) +{ + BLE_ASSERT_ERR((((uint16_t)usedchidx << 8) & ~((uint16_t)0x00003F00)) == 0); + EM_BLE_WR(EM_BLE_RXCHASS_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXCHASS_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00003F00)) | ((uint16_t)usedchidx << 8)); +} + +__INLINE uint8_t em_ble_rxchass_rssi_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXCHASS_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x000000FF)) >> 0); +} + +__INLINE void em_ble_rxchass_rssi_setf(int elt_idx, uint8_t rssi) +{ + BLE_ASSERT_ERR((((uint16_t)rssi << 0) & ~((uint16_t)0x000000FF)) == 0); + EM_BLE_WR(EM_BLE_RXCHASS_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXCHASS_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x000000FF)) | ((uint16_t)rssi << 0)); +} + +/** + * @brief RXCLKNSYNC0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00          CLKNRXSYNC0   0x0
+ * 
+ */ +#define EM_BLE_RXCLKNSYNC0_ADDR (0x00910008 + EM_BLE_RX_DESC_OFFSET) +#define EM_BLE_RXCLKNSYNC0_INDEX 0x00000004 +#define EM_BLE_RXCLKNSYNC0_RESET 0x00000000 + +__INLINE uint16_t em_ble_rxclknsync0_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_RXCLKNSYNC0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); +} + +// field definitions +#define EM_BLE_CLKNRXSYNC0_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_CLKNRXSYNC0_LSB 0 +#define EM_BLE_CLKNRXSYNC0_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_CLKNRXSYNC0_RST 0x0 + +__INLINE uint16_t em_ble_rxclknsync0_clknrxsync0_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXCLKNSYNC0_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief RXCLKNSYNC1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  11:00          CLKNRXSYNC1   0x0
+ * 
+ */ +#define EM_BLE_RXCLKNSYNC1_ADDR (0x0091000A + EM_BLE_RX_DESC_OFFSET) +#define EM_BLE_RXCLKNSYNC1_INDEX 0x00000005 +#define EM_BLE_RXCLKNSYNC1_RESET 0x00000000 + +__INLINE uint16_t em_ble_rxclknsync1_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_RXCLKNSYNC1_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); +} + +// field definitions +#define EM_BLE_CLKNRXSYNC1_MASK ((uint16_t)0x00000FFF) +#define EM_BLE_CLKNRXSYNC1_LSB 0 +#define EM_BLE_CLKNRXSYNC1_WIDTH ((uint16_t)0x0000000C) + +#define EM_BLE_CLKNRXSYNC1_RST 0x0 + +__INLINE uint16_t em_ble_rxclknsync1_clknrxsync1_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXCLKNSYNC1_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x00000FFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief RXFCNTSYNC register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:11            RXLINKLBL   0x0
+ *  09:00           FCNTRXSYNC   0x0
+ * 
+ */ +#define EM_BLE_RXFCNTSYNC_ADDR (0x0091000C + EM_BLE_RX_DESC_OFFSET) +#define EM_BLE_RXFCNTSYNC_INDEX 0x00000006 +#define EM_BLE_RXFCNTSYNC_RESET 0x00000000 + +__INLINE uint16_t em_ble_rxfcntsync_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_RXFCNTSYNC_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); +} + +// field definitions +#define EM_BLE_RXLINKLBL_MASK ((uint16_t)0x0000F800) +#define EM_BLE_RXLINKLBL_LSB 11 +#define EM_BLE_RXLINKLBL_WIDTH ((uint16_t)0x00000005) +#define EM_BLE_FCNTRXSYNC_MASK ((uint16_t)0x000003FF) +#define EM_BLE_FCNTRXSYNC_LSB 0 +#define EM_BLE_FCNTRXSYNC_WIDTH ((uint16_t)0x0000000A) + +#define EM_BLE_RXLINKLBL_RST 0x0 +#define EM_BLE_FCNTRXSYNC_RST 0x0 + +__INLINE void em_ble_rxfcntsync_unpack(int elt_idx, uint8_t* rxlinklbl, uint16_t* fcntrxsync) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXFCNTSYNC_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + + *rxlinklbl = (localVal & ((uint16_t)0x0000F800)) >> 11; + *fcntrxsync = (localVal & ((uint16_t)0x000003FF)) >> 0; +} + +__INLINE uint8_t em_ble_rxfcntsync_rxlinklbl_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXFCNTSYNC_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x0000F800)) >> 11); +} + +__INLINE uint16_t em_ble_rxfcntsync_fcntrxsync_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXFCNTSYNC_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x000003FF)) >> 0); +} + +/** + * @brief RXWPALPTR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00            RXWPALPTR   0x0
+ * 
+ */ +#define EM_BLE_RXWPALPTR_ADDR (0x0091000E + EM_BLE_RX_DESC_OFFSET) +#define EM_BLE_RXWPALPTR_INDEX 0x00000007 +#define EM_BLE_RXWPALPTR_RESET 0x00000000 + +__INLINE uint16_t em_ble_rxwpalptr_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_RXWPALPTR_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); +} + +__INLINE void em_ble_rxwpalptr_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_RXWPALPTR_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, value); +} + +// field definitions +#define EM_BLE_RXWPALPTR_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_RXWPALPTR_LSB 0 +#define EM_BLE_RXWPALPTR_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_RXWPALPTR_RST 0x0 + +__INLINE uint16_t em_ble_rxwpalptr_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXWPALPTR_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_rxwpalptr_setf(int elt_idx, uint16_t rxwpalptr) +{ + BLE_ASSERT_ERR((((uint16_t)rxwpalptr << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_RXWPALPTR_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (uint16_t)rxwpalptr << 0); +} + +/** + * @brief RXRALPTR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00             RXRALPTR   0x0
+ * 
+ */ +#define EM_BLE_RXRALPTR_ADDR (0x00910010 + EM_BLE_RX_DESC_OFFSET) +#define EM_BLE_RXRALPTR_INDEX 0x00000008 +#define EM_BLE_RXRALPTR_RESET 0x00000000 + +__INLINE uint16_t em_ble_rxralptr_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_RXRALPTR_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); +} + +__INLINE void em_ble_rxralptr_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_RXRALPTR_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, value); +} + +// field definitions +#define EM_BLE_RXRALPTR_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_RXRALPTR_LSB 0 +#define EM_BLE_RXRALPTR_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_RXRALPTR_RST 0x0 + +__INLINE uint16_t em_ble_rxralptr_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXRALPTR_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_rxralptr_setf(int elt_idx, uint16_t rxralptr) +{ + BLE_ASSERT_ERR((((uint16_t)rxralptr << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_RXRALPTR_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (uint16_t)rxralptr << 0); +} + +/** + * @brief RXAEHEADER register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     15               RXRSVD   0
+ *     14                RXPOW   0
+ *     13               RXSYNC   0
+ *     12             RXAUXPTR   0
+ *     11                RXADI   0
+ *     10                RXCTE   0
+ *     09               RXTGTA   0
+ *     08               RXADVA   0
+ *  07:06             RXAEMODE   0x0
+ *  05:00           RXAELENGTH   0x0
+ * 
+ */ +#define EM_BLE_RXAEHEADER_ADDR (0x00910012 + EM_BLE_RX_DESC_OFFSET) +#define EM_BLE_RXAEHEADER_INDEX 0x00000009 +#define EM_BLE_RXAEHEADER_RESET 0x00000000 + +__INLINE uint16_t em_ble_rxaeheader_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_RXAEHEADER_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); +} + +__INLINE void em_ble_rxaeheader_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_RXAEHEADER_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, value); +} + +// field definitions +#define EM_BLE_RXRSVD_BIT ((uint16_t)0x00008000) +#define EM_BLE_RXRSVD_POS 15 +#define EM_BLE_RXPOW_BIT ((uint16_t)0x00004000) +#define EM_BLE_RXPOW_POS 14 +#define EM_BLE_RXSYNC_BIT ((uint16_t)0x00002000) +#define EM_BLE_RXSYNC_POS 13 +#define EM_BLE_RXAUXPTR_BIT ((uint16_t)0x00001000) +#define EM_BLE_RXAUXPTR_POS 12 +#define EM_BLE_RXADI_BIT ((uint16_t)0x00000800) +#define EM_BLE_RXADI_POS 11 +#define EM_BLE_RXCTE_BIT ((uint16_t)0x00000400) +#define EM_BLE_RXCTE_POS 10 +#define EM_BLE_RXTGTA_BIT ((uint16_t)0x00000200) +#define EM_BLE_RXTGTA_POS 9 +#define EM_BLE_RXADVA_BIT ((uint16_t)0x00000100) +#define EM_BLE_RXADVA_POS 8 +#define EM_BLE_RXAEMODE_MASK ((uint16_t)0x000000C0) +#define EM_BLE_RXAEMODE_LSB 6 +#define EM_BLE_RXAEMODE_WIDTH ((uint16_t)0x00000002) +#define EM_BLE_RXAELENGTH_MASK ((uint16_t)0x0000003F) +#define EM_BLE_RXAELENGTH_LSB 0 +#define EM_BLE_RXAELENGTH_WIDTH ((uint16_t)0x00000006) + +#define EM_BLE_RXRSVD_RST 0x0 +#define EM_BLE_RXPOW_RST 0x0 +#define EM_BLE_RXSYNC_RST 0x0 +#define EM_BLE_RXAUXPTR_RST 0x0 +#define EM_BLE_RXADI_RST 0x0 +#define EM_BLE_RXCTE_RST 0x0 +#define EM_BLE_RXTGTA_RST 0x0 +#define EM_BLE_RXADVA_RST 0x0 +#define EM_BLE_RXAEMODE_RST 0x0 +#define EM_BLE_RXAELENGTH_RST 0x0 + +__INLINE void em_ble_rxaeheader_pack(int elt_idx, uint8_t rxrsvd, uint8_t rxpow, uint8_t rxsync, uint8_t rxauxptr, uint8_t rxadi, uint8_t rxcte, uint8_t rxtgta, uint8_t rxadva, uint8_t rxaemode, uint8_t rxaelength) +{ + BLE_ASSERT_ERR((((uint16_t)rxrsvd << 15) & ~((uint16_t)0x00008000)) == 0); + BLE_ASSERT_ERR((((uint16_t)rxpow << 14) & ~((uint16_t)0x00004000)) == 0); + BLE_ASSERT_ERR((((uint16_t)rxsync << 13) & ~((uint16_t)0x00002000)) == 0); + BLE_ASSERT_ERR((((uint16_t)rxauxptr << 12) & ~((uint16_t)0x00001000)) == 0); + BLE_ASSERT_ERR((((uint16_t)rxadi << 11) & ~((uint16_t)0x00000800)) == 0); + BLE_ASSERT_ERR((((uint16_t)rxcte << 10) & ~((uint16_t)0x00000400)) == 0); + BLE_ASSERT_ERR((((uint16_t)rxtgta << 9) & ~((uint16_t)0x00000200)) == 0); + BLE_ASSERT_ERR((((uint16_t)rxadva << 8) & ~((uint16_t)0x00000100)) == 0); + BLE_ASSERT_ERR((((uint16_t)rxaemode << 6) & ~((uint16_t)0x000000C0)) == 0); + BLE_ASSERT_ERR((((uint16_t)rxaelength << 0) & ~((uint16_t)0x0000003F)) == 0); + EM_BLE_WR(EM_BLE_RXAEHEADER_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, ((uint16_t)rxrsvd << 15) | ((uint16_t)rxpow << 14) | ((uint16_t)rxsync << 13) | ((uint16_t)rxauxptr << 12) | ((uint16_t)rxadi << 11) | ((uint16_t)rxcte << 10) | ((uint16_t)rxtgta << 9) | ((uint16_t)rxadva << 8) | ((uint16_t)rxaemode << 6) | ((uint16_t)rxaelength << 0)); +} + +__INLINE void em_ble_rxaeheader_unpack(int elt_idx, uint8_t* rxrsvd, uint8_t* rxpow, uint8_t* rxsync, uint8_t* rxauxptr, uint8_t* rxadi, uint8_t* rxcte, uint8_t* rxtgta, uint8_t* rxadva, uint8_t* rxaemode, uint8_t* rxaelength) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXAEHEADER_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + + *rxrsvd = (localVal & ((uint16_t)0x00008000)) >> 15; + *rxpow = (localVal & ((uint16_t)0x00004000)) >> 14; + *rxsync = (localVal & ((uint16_t)0x00002000)) >> 13; + *rxauxptr = (localVal & ((uint16_t)0x00001000)) >> 12; + *rxadi = (localVal & ((uint16_t)0x00000800)) >> 11; + *rxcte = (localVal & ((uint16_t)0x00000400)) >> 10; + *rxtgta = (localVal & ((uint16_t)0x00000200)) >> 9; + *rxadva = (localVal & ((uint16_t)0x00000100)) >> 8; + *rxaemode = (localVal & ((uint16_t)0x000000C0)) >> 6; + *rxaelength = (localVal & ((uint16_t)0x0000003F)) >> 0; +} + +__INLINE uint8_t em_ble_rxaeheader_rxrsvd_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXAEHEADER_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00008000)) >> 15); +} + +__INLINE void em_ble_rxaeheader_rxrsvd_setf(int elt_idx, uint8_t rxrsvd) +{ + BLE_ASSERT_ERR((((uint16_t)rxrsvd << 15) & ~((uint16_t)0x00008000)) == 0); + EM_BLE_WR(EM_BLE_RXAEHEADER_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXAEHEADER_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00008000)) | ((uint16_t)rxrsvd << 15)); +} + +__INLINE uint8_t em_ble_rxaeheader_rxpow_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXAEHEADER_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00004000)) >> 14); +} + +__INLINE void em_ble_rxaeheader_rxpow_setf(int elt_idx, uint8_t rxpow) +{ + BLE_ASSERT_ERR((((uint16_t)rxpow << 14) & ~((uint16_t)0x00004000)) == 0); + EM_BLE_WR(EM_BLE_RXAEHEADER_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXAEHEADER_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00004000)) | ((uint16_t)rxpow << 14)); +} + +__INLINE uint8_t em_ble_rxaeheader_rxsync_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXAEHEADER_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00002000)) >> 13); +} + +__INLINE void em_ble_rxaeheader_rxsync_setf(int elt_idx, uint8_t rxsync) +{ + BLE_ASSERT_ERR((((uint16_t)rxsync << 13) & ~((uint16_t)0x00002000)) == 0); + EM_BLE_WR(EM_BLE_RXAEHEADER_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXAEHEADER_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00002000)) | ((uint16_t)rxsync << 13)); +} + +__INLINE uint8_t em_ble_rxaeheader_rxauxptr_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXAEHEADER_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00001000)) >> 12); +} + +__INLINE void em_ble_rxaeheader_rxauxptr_setf(int elt_idx, uint8_t rxauxptr) +{ + BLE_ASSERT_ERR((((uint16_t)rxauxptr << 12) & ~((uint16_t)0x00001000)) == 0); + EM_BLE_WR(EM_BLE_RXAEHEADER_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXAEHEADER_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00001000)) | ((uint16_t)rxauxptr << 12)); +} + +__INLINE uint8_t em_ble_rxaeheader_rxadi_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXAEHEADER_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000800)) >> 11); +} + +__INLINE void em_ble_rxaeheader_rxadi_setf(int elt_idx, uint8_t rxadi) +{ + BLE_ASSERT_ERR((((uint16_t)rxadi << 11) & ~((uint16_t)0x00000800)) == 0); + EM_BLE_WR(EM_BLE_RXAEHEADER_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXAEHEADER_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00000800)) | ((uint16_t)rxadi << 11)); +} + +__INLINE uint8_t em_ble_rxaeheader_rxcte_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXAEHEADER_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000400)) >> 10); +} + +__INLINE void em_ble_rxaeheader_rxcte_setf(int elt_idx, uint8_t rxcte) +{ + BLE_ASSERT_ERR((((uint16_t)rxcte << 10) & ~((uint16_t)0x00000400)) == 0); + EM_BLE_WR(EM_BLE_RXAEHEADER_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXAEHEADER_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00000400)) | ((uint16_t)rxcte << 10)); +} + +__INLINE uint8_t em_ble_rxaeheader_rxtgta_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXAEHEADER_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000200)) >> 9); +} + +__INLINE void em_ble_rxaeheader_rxtgta_setf(int elt_idx, uint8_t rxtgta) +{ + BLE_ASSERT_ERR((((uint16_t)rxtgta << 9) & ~((uint16_t)0x00000200)) == 0); + EM_BLE_WR(EM_BLE_RXAEHEADER_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXAEHEADER_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00000200)) | ((uint16_t)rxtgta << 9)); +} + +__INLINE uint8_t em_ble_rxaeheader_rxadva_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXAEHEADER_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000100)) >> 8); +} + +__INLINE void em_ble_rxaeheader_rxadva_setf(int elt_idx, uint8_t rxadva) +{ + BLE_ASSERT_ERR((((uint16_t)rxadva << 8) & ~((uint16_t)0x00000100)) == 0); + EM_BLE_WR(EM_BLE_RXAEHEADER_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXAEHEADER_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00000100)) | ((uint16_t)rxadva << 8)); +} + +__INLINE uint8_t em_ble_rxaeheader_rxaemode_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXAEHEADER_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x000000C0)) >> 6); +} + +__INLINE void em_ble_rxaeheader_rxaemode_setf(int elt_idx, uint8_t rxaemode) +{ + BLE_ASSERT_ERR((((uint16_t)rxaemode << 6) & ~((uint16_t)0x000000C0)) == 0); + EM_BLE_WR(EM_BLE_RXAEHEADER_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXAEHEADER_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x000000C0)) | ((uint16_t)rxaemode << 6)); +} + +__INLINE uint8_t em_ble_rxaeheader_rxaelength_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXAEHEADER_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x0000003F)) >> 0); +} + +__INLINE void em_ble_rxaeheader_rxaelength_setf(int elt_idx, uint8_t rxaelength) +{ + BLE_ASSERT_ERR((((uint16_t)rxaelength << 0) & ~((uint16_t)0x0000003F)) == 0); + EM_BLE_WR(EM_BLE_RXAEHEADER_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXAEHEADER_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x0000003F)) | ((uint16_t)rxaelength << 0)); +} + +/** + * @brief RXDATAPTR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00            RXDATAPTR   0x0
+ * 
+ */ +#define EM_BLE_RXDATAPTR_ADDR (0x00910014 + EM_BLE_RX_DESC_OFFSET) +#define EM_BLE_RXDATAPTR_INDEX 0x0000000A +#define EM_BLE_RXDATAPTR_RESET 0x00000000 + +__INLINE uint16_t em_ble_rxdataptr_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_RXDATAPTR_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); +} + +__INLINE void em_ble_rxdataptr_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_RXDATAPTR_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, value); +} + +// field definitions +#define EM_BLE_RXDATAPTR_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_RXDATAPTR_LSB 0 +#define EM_BLE_RXDATAPTR_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_RXDATAPTR_RST 0x0 + +__INLINE uint16_t em_ble_rxdataptr_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXDATAPTR_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_rxdataptr_setf(int elt_idx, uint16_t rxdataptr) +{ + BLE_ASSERT_ERR((((uint16_t)rxdataptr << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_RXDATAPTR_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (uint16_t)rxdataptr << 0); +} + +/** + * @brief RXPHCTE register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:08           NBRXIQSAMP   0x0
+ *  07:06            RXCTETYPE   0x0
+ *     05             RXCTERFU   0
+ *  04:00            RXCTETIME   0x0
+ * 
+ */ +#define EM_BLE_RXPHCTE_ADDR (0x00910016 + EM_BLE_RX_DESC_OFFSET) +#define EM_BLE_RXPHCTE_INDEX 0x0000000B +#define EM_BLE_RXPHCTE_RESET 0x00000000 + +__INLINE uint16_t em_ble_rxphcte_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_RXPHCTE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); +} + +__INLINE void em_ble_rxphcte_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_RXPHCTE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, value); +} + +// field definitions +#define EM_BLE_NBRXIQSAMP_MASK ((uint16_t)0x0000FF00) +#define EM_BLE_NBRXIQSAMP_LSB 8 +#define EM_BLE_NBRXIQSAMP_WIDTH ((uint16_t)0x00000008) +#define EM_BLE_RXCTETYPE_MASK ((uint16_t)0x000000C0) +#define EM_BLE_RXCTETYPE_LSB 6 +#define EM_BLE_RXCTETYPE_WIDTH ((uint16_t)0x00000002) +#define EM_BLE_RXCTERFU_BIT ((uint16_t)0x00000020) +#define EM_BLE_RXCTERFU_POS 5 +#define EM_BLE_RXCTETIME_MASK ((uint16_t)0x0000001F) +#define EM_BLE_RXCTETIME_LSB 0 +#define EM_BLE_RXCTETIME_WIDTH ((uint16_t)0x00000005) + +#define EM_BLE_NBRXIQSAMP_RST 0x0 +#define EM_BLE_RXCTETYPE_RST 0x0 +#define EM_BLE_RXCTERFU_RST 0x0 +#define EM_BLE_RXCTETIME_RST 0x0 + +__INLINE void em_ble_rxphcte_pack(int elt_idx, uint8_t nbrxiqsamp, uint8_t rxctetype, uint8_t rxcterfu, uint8_t rxctetime) +{ + BLE_ASSERT_ERR((((uint16_t)nbrxiqsamp << 8) & ~((uint16_t)0x0000FF00)) == 0); + BLE_ASSERT_ERR((((uint16_t)rxctetype << 6) & ~((uint16_t)0x000000C0)) == 0); + BLE_ASSERT_ERR((((uint16_t)rxcterfu << 5) & ~((uint16_t)0x00000020)) == 0); + BLE_ASSERT_ERR((((uint16_t)rxctetime << 0) & ~((uint16_t)0x0000001F)) == 0); + EM_BLE_WR(EM_BLE_RXPHCTE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, ((uint16_t)nbrxiqsamp << 8) | ((uint16_t)rxctetype << 6) | ((uint16_t)rxcterfu << 5) | ((uint16_t)rxctetime << 0)); +} + +__INLINE void em_ble_rxphcte_unpack(int elt_idx, uint8_t* nbrxiqsamp, uint8_t* rxctetype, uint8_t* rxcterfu, uint8_t* rxctetime) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXPHCTE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + + *nbrxiqsamp = (localVal & ((uint16_t)0x0000FF00)) >> 8; + *rxctetype = (localVal & ((uint16_t)0x000000C0)) >> 6; + *rxcterfu = (localVal & ((uint16_t)0x00000020)) >> 5; + *rxctetime = (localVal & ((uint16_t)0x0000001F)) >> 0; +} + +__INLINE uint8_t em_ble_rxphcte_nbrxiqsamp_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXPHCTE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x0000FF00)) >> 8); +} + +__INLINE void em_ble_rxphcte_nbrxiqsamp_setf(int elt_idx, uint8_t nbrxiqsamp) +{ + BLE_ASSERT_ERR((((uint16_t)nbrxiqsamp << 8) & ~((uint16_t)0x0000FF00)) == 0); + EM_BLE_WR(EM_BLE_RXPHCTE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXPHCTE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x0000FF00)) | ((uint16_t)nbrxiqsamp << 8)); +} + +__INLINE uint8_t em_ble_rxphcte_rxctetype_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXPHCTE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x000000C0)) >> 6); +} + +__INLINE void em_ble_rxphcte_rxctetype_setf(int elt_idx, uint8_t rxctetype) +{ + BLE_ASSERT_ERR((((uint16_t)rxctetype << 6) & ~((uint16_t)0x000000C0)) == 0); + EM_BLE_WR(EM_BLE_RXPHCTE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXPHCTE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x000000C0)) | ((uint16_t)rxctetype << 6)); +} + +__INLINE uint8_t em_ble_rxphcte_rxcterfu_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXPHCTE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000020)) >> 5); +} + +__INLINE void em_ble_rxphcte_rxcterfu_setf(int elt_idx, uint8_t rxcterfu) +{ + BLE_ASSERT_ERR((((uint16_t)rxcterfu << 5) & ~((uint16_t)0x00000020)) == 0); + EM_BLE_WR(EM_BLE_RXPHCTE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXPHCTE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x00000020)) | ((uint16_t)rxcterfu << 5)); +} + +__INLINE uint8_t em_ble_rxphcte_rxctetime_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXPHCTE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + return ((localVal & ((uint16_t)0x0000001F)) >> 0); +} + +__INLINE void em_ble_rxphcte_rxctetime_setf(int elt_idx, uint8_t rxctetime) +{ + BLE_ASSERT_ERR((((uint16_t)rxctetime << 0) & ~((uint16_t)0x0000001F)) == 0); + EM_BLE_WR(EM_BLE_RXPHCTE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXPHCTE_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE) & ~((uint16_t)0x0000001F)) | ((uint16_t)rxctetime << 0)); +} + +/** + * @brief RXCTEPTR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00             RXCTEPTR   0x0
+ * 
+ */ +#define EM_BLE_RXCTEPTR_ADDR (0x00910018 + EM_BLE_RX_DESC_OFFSET) +#define EM_BLE_RXCTEPTR_INDEX 0x0000000C +#define EM_BLE_RXCTEPTR_RESET 0x00000000 + +__INLINE uint16_t em_ble_rxcteptr_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_RXCTEPTR_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); +} + +__INLINE void em_ble_rxcteptr_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_RXCTEPTR_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, value); +} + +// field definitions +#define EM_BLE_RXCTEPTR_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_RXCTEPTR_LSB 0 +#define EM_BLE_RXCTEPTR_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_RXCTEPTR_RST 0x0 + +__INLINE uint16_t em_ble_rxcteptr_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXCTEPTR_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_rxcteptr_setf(int elt_idx, uint16_t rxcteptr) +{ + BLE_ASSERT_ERR((((uint16_t)rxcteptr << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_RXCTEPTR_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (uint16_t)rxcteptr << 0); +} + +/** + * @brief RXRESERVED register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00                 RSVD   0x0
+ * 
+ */ +#define EM_BLE_RXRESERVED_ADDR (0x0091001A + EM_BLE_RX_DESC_OFFSET) +#define EM_BLE_RXRESERVED_INDEX 0x0000000D +#define EM_BLE_RXRESERVED_RESET 0x00000000 + +__INLINE uint16_t em_ble_rxreserved_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_RXRESERVED_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); +} + +__INLINE void em_ble_rxreserved_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_RXRESERVED_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, value); +} + +// field definitions +#define EM_BLE_RSVD_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_RSVD_LSB 0 +#define EM_BLE_RSVD_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_RSVD_RST 0x0 + +__INLINE uint16_t em_ble_rxreserved_rsvd_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXRESERVED_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_rxreserved_rsvd_setf(int elt_idx, uint16_t rsvd) +{ + BLE_ASSERT_ERR((((uint16_t)rsvd << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_RXRESERVED_ADDR + elt_idx * REG_EM_BLE_RX_DESC_SIZE, (uint16_t)rsvd << 0); +} + + +#endif // _REG_EM_BLE_RX_DESC_H_ + diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_em_ble_rx_iso_buf.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_em_ble_rx_iso_buf.h new file mode 100755 index 0000000..9c10fa9 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_em_ble_rx_iso_buf.h @@ -0,0 +1,273 @@ +#ifndef _REG_EM_BLE_RX_ISO_BUF_H_ +#define _REG_EM_BLE_RX_ISO_BUF_H_ + +#include +#include "_reg_em_ble_rx_iso_buf.h" +#include "compiler.h" +#include "architect.h" +#include "em_map.h" +#include "ble_reg_access.h" + +#define REG_EM_BLE_RX_ISO_BUF_COUNT 4 + +#define REG_EM_BLE_RX_ISO_BUF_DECODING_MASK 0x00000007 + +#define REG_EM_BLE_RX_ISO_BUF_ADDR_GET(idx) (EM_BLE_RX_ISO_BUF_OFFSET + (idx) * REG_EM_BLE_RX_ISO_BUF_SIZE) + +/** + * @brief RXISOBUFSTAT register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:14                 INVL   0x0
+ *  07:00          RXISOLENGTH   0x0
+ * 
+ */ +#define EM_BLE_RXISOBUFSTAT_ADDR (0x00910000 + EM_BLE_RX_ISO_BUF_OFFSET) +#define EM_BLE_RXISOBUFSTAT_INDEX 0x00000000 +#define EM_BLE_RXISOBUFSTAT_RESET 0x00000000 + +__INLINE uint16_t em_ble_rxisobufstat_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_RXISOBUFSTAT_ADDR + elt_idx * REG_EM_BLE_RX_ISO_BUF_SIZE); +} + +__INLINE void em_ble_rxisobufstat_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_RXISOBUFSTAT_ADDR + elt_idx * REG_EM_BLE_RX_ISO_BUF_SIZE, value); +} + +// field definitions +#define EM_BLE_INVL_MASK ((uint16_t)0x0000C000) +#define EM_BLE_INVL_LSB 14 +#define EM_BLE_INVL_WIDTH ((uint16_t)0x00000002) +#define EM_BLE_RXISOLENGTH_MASK ((uint16_t)0x000000FF) +#define EM_BLE_RXISOLENGTH_LSB 0 +#define EM_BLE_RXISOLENGTH_WIDTH ((uint16_t)0x00000008) + +#define EM_BLE_INVL_RST 0x0 +#define EM_BLE_RXISOLENGTH_RST 0x0 + +__INLINE void em_ble_rxisobufstat_pack(int elt_idx, uint8_t invl, uint8_t rxisolength) +{ + BLE_ASSERT_ERR((((uint16_t)invl << 14) & ~((uint16_t)0x0000C000)) == 0); + BLE_ASSERT_ERR((((uint16_t)rxisolength << 0) & ~((uint16_t)0x000000FF)) == 0); + EM_BLE_WR(EM_BLE_RXISOBUFSTAT_ADDR + elt_idx * REG_EM_BLE_RX_ISO_BUF_SIZE, ((uint16_t)invl << 14) | ((uint16_t)rxisolength << 0)); +} + +__INLINE void em_ble_rxisobufstat_unpack(int elt_idx, uint8_t* invl, uint8_t* rxisolength) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXISOBUFSTAT_ADDR + elt_idx * REG_EM_BLE_RX_ISO_BUF_SIZE); + + *invl = (localVal & ((uint16_t)0x0000C000)) >> 14; + *rxisolength = (localVal & ((uint16_t)0x000000FF)) >> 0; +} + +__INLINE uint8_t em_ble_rxisobufstat_invl_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXISOBUFSTAT_ADDR + elt_idx * REG_EM_BLE_RX_ISO_BUF_SIZE); + return ((localVal & ((uint16_t)0x0000C000)) >> 14); +} + +__INLINE void em_ble_rxisobufstat_invl_setf(int elt_idx, uint8_t invl) +{ + BLE_ASSERT_ERR((((uint16_t)invl << 14) & ~((uint16_t)0x0000C000)) == 0); + EM_BLE_WR(EM_BLE_RXISOBUFSTAT_ADDR + elt_idx * REG_EM_BLE_RX_ISO_BUF_SIZE, (EM_BLE_RD(EM_BLE_RXISOBUFSTAT_ADDR + elt_idx * REG_EM_BLE_RX_ISO_BUF_SIZE) & ~((uint16_t)0x0000C000)) | ((uint16_t)invl << 14)); +} + +__INLINE uint8_t em_ble_rxisobufstat_rxisolength_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXISOBUFSTAT_ADDR + elt_idx * REG_EM_BLE_RX_ISO_BUF_SIZE); + return ((localVal & ((uint16_t)0x000000FF)) >> 0); +} + +__INLINE void em_ble_rxisobufstat_rxisolength_setf(int elt_idx, uint8_t rxisolength) +{ + BLE_ASSERT_ERR((((uint16_t)rxisolength << 0) & ~((uint16_t)0x000000FF)) == 0); + EM_BLE_WR(EM_BLE_RXISOBUFSTAT_ADDR + elt_idx * REG_EM_BLE_RX_ISO_BUF_SIZE, (EM_BLE_RD(EM_BLE_RXISOBUFSTAT_ADDR + elt_idx * REG_EM_BLE_RX_ISO_BUF_SIZE) & ~((uint16_t)0x000000FF)) | ((uint16_t)rxisolength << 0)); +} + +/** + * @brief RXISOBUFLBL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  12:08         RXBUFLINKLBL   0x0
+ *  07:03      RXBUFSTREAM_LBL   0x0
+ *  02:00       RXBUFGROUP_LBL   0x0
+ * 
+ */ +#define EM_BLE_RXISOBUFLBL_ADDR (0x00910002 + EM_BLE_RX_ISO_BUF_OFFSET) +#define EM_BLE_RXISOBUFLBL_INDEX 0x00000001 +#define EM_BLE_RXISOBUFLBL_RESET 0x00000000 + +__INLINE uint16_t em_ble_rxisobuflbl_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_RXISOBUFLBL_ADDR + elt_idx * REG_EM_BLE_RX_ISO_BUF_SIZE); +} + +__INLINE void em_ble_rxisobuflbl_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_RXISOBUFLBL_ADDR + elt_idx * REG_EM_BLE_RX_ISO_BUF_SIZE, value); +} + +// field definitions +#define EM_BLE_RXBUFLINKLBL_MASK ((uint16_t)0x00001F00) +#define EM_BLE_RXBUFLINKLBL_LSB 8 +#define EM_BLE_RXBUFLINKLBL_WIDTH ((uint16_t)0x00000005) +#define EM_BLE_RXBUFSTREAM_LBL_MASK ((uint16_t)0x000000F8) +#define EM_BLE_RXBUFSTREAM_LBL_LSB 3 +#define EM_BLE_RXBUFSTREAM_LBL_WIDTH ((uint16_t)0x00000005) +#define EM_BLE_RXBUFGROUP_LBL_MASK ((uint16_t)0x00000007) +#define EM_BLE_RXBUFGROUP_LBL_LSB 0 +#define EM_BLE_RXBUFGROUP_LBL_WIDTH ((uint16_t)0x00000003) + +#define EM_BLE_RXBUFLINKLBL_RST 0x0 +#define EM_BLE_RXBUFSTREAM_LBL_RST 0x0 +#define EM_BLE_RXBUFGROUP_LBL_RST 0x0 + +__INLINE void em_ble_rxisobuflbl_pack(int elt_idx, uint8_t rxbuflinklbl, uint8_t rxbufstreamlbl, uint8_t rxbufgrouplbl) +{ + BLE_ASSERT_ERR((((uint16_t)rxbuflinklbl << 8) & ~((uint16_t)0x00001F00)) == 0); + BLE_ASSERT_ERR((((uint16_t)rxbufstreamlbl << 3) & ~((uint16_t)0x000000F8)) == 0); + BLE_ASSERT_ERR((((uint16_t)rxbufgrouplbl << 0) & ~((uint16_t)0x00000007)) == 0); + EM_BLE_WR(EM_BLE_RXISOBUFLBL_ADDR + elt_idx * REG_EM_BLE_RX_ISO_BUF_SIZE, ((uint16_t)rxbuflinklbl << 8) | ((uint16_t)rxbufstreamlbl << 3) | ((uint16_t)rxbufgrouplbl << 0)); +} + +__INLINE void em_ble_rxisobuflbl_unpack(int elt_idx, uint8_t* rxbuflinklbl, uint8_t* rxbufstreamlbl, uint8_t* rxbufgrouplbl) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXISOBUFLBL_ADDR + elt_idx * REG_EM_BLE_RX_ISO_BUF_SIZE); + + *rxbuflinklbl = (localVal & ((uint16_t)0x00001F00)) >> 8; + *rxbufstreamlbl = (localVal & ((uint16_t)0x000000F8)) >> 3; + *rxbufgrouplbl = (localVal & ((uint16_t)0x00000007)) >> 0; +} + +__INLINE uint8_t em_ble_rxisobuflbl_rxbuflinklbl_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXISOBUFLBL_ADDR + elt_idx * REG_EM_BLE_RX_ISO_BUF_SIZE); + return ((localVal & ((uint16_t)0x00001F00)) >> 8); +} + +__INLINE void em_ble_rxisobuflbl_rxbuflinklbl_setf(int elt_idx, uint8_t rxbuflinklbl) +{ + BLE_ASSERT_ERR((((uint16_t)rxbuflinklbl << 8) & ~((uint16_t)0x00001F00)) == 0); + EM_BLE_WR(EM_BLE_RXISOBUFLBL_ADDR + elt_idx * REG_EM_BLE_RX_ISO_BUF_SIZE, (EM_BLE_RD(EM_BLE_RXISOBUFLBL_ADDR + elt_idx * REG_EM_BLE_RX_ISO_BUF_SIZE) & ~((uint16_t)0x00001F00)) | ((uint16_t)rxbuflinklbl << 8)); +} + +__INLINE uint8_t em_ble_rxisobuflbl_rxbufstream_lbl_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXISOBUFLBL_ADDR + elt_idx * REG_EM_BLE_RX_ISO_BUF_SIZE); + return ((localVal & ((uint16_t)0x000000F8)) >> 3); +} + +__INLINE void em_ble_rxisobuflbl_rxbufstream_lbl_setf(int elt_idx, uint8_t rxbufstreamlbl) +{ + BLE_ASSERT_ERR((((uint16_t)rxbufstreamlbl << 3) & ~((uint16_t)0x000000F8)) == 0); + EM_BLE_WR(EM_BLE_RXISOBUFLBL_ADDR + elt_idx * REG_EM_BLE_RX_ISO_BUF_SIZE, (EM_BLE_RD(EM_BLE_RXISOBUFLBL_ADDR + elt_idx * REG_EM_BLE_RX_ISO_BUF_SIZE) & ~((uint16_t)0x000000F8)) | ((uint16_t)rxbufstreamlbl << 3)); +} + +__INLINE uint8_t em_ble_rxisobuflbl_rxbufgroup_lbl_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXISOBUFLBL_ADDR + elt_idx * REG_EM_BLE_RX_ISO_BUF_SIZE); + return ((localVal & ((uint16_t)0x00000007)) >> 0); +} + +__INLINE void em_ble_rxisobuflbl_rxbufgroup_lbl_setf(int elt_idx, uint8_t rxbufgrouplbl) +{ + BLE_ASSERT_ERR((((uint16_t)rxbufgrouplbl << 0) & ~((uint16_t)0x00000007)) == 0); + EM_BLE_WR(EM_BLE_RXISOBUFLBL_ADDR + elt_idx * REG_EM_BLE_RX_ISO_BUF_SIZE, (EM_BLE_RD(EM_BLE_RXISOBUFLBL_ADDR + elt_idx * REG_EM_BLE_RX_ISO_BUF_SIZE) & ~((uint16_t)0x00000007)) | ((uint16_t)rxbufgrouplbl << 0)); +} + +/** + * @brief RXISOSUBEVTCNT register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  07:00            SUBEVTCNT   0x0
+ * 
+ */ +#define EM_BLE_RXISOSUBEVTCNT_ADDR (0x00910004 + EM_BLE_RX_ISO_BUF_OFFSET) +#define EM_BLE_RXISOSUBEVTCNT_INDEX 0x00000002 +#define EM_BLE_RXISOSUBEVTCNT_RESET 0x00000000 + +__INLINE uint16_t em_ble_rxisosubevtcnt_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_RXISOSUBEVTCNT_ADDR + elt_idx * REG_EM_BLE_RX_ISO_BUF_SIZE); +} + +__INLINE void em_ble_rxisosubevtcnt_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_RXISOSUBEVTCNT_ADDR + elt_idx * REG_EM_BLE_RX_ISO_BUF_SIZE, value); +} + +// field definitions +#define EM_BLE_SUBEVTCNT_MASK ((uint16_t)0x000000FF) +#define EM_BLE_SUBEVTCNT_LSB 0 +#define EM_BLE_SUBEVTCNT_WIDTH ((uint16_t)0x00000008) + +#define EM_BLE_SUBEVTCNT_RST 0x0 + +__INLINE uint8_t em_ble_rxisosubevtcnt_subevtcnt_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXISOSUBEVTCNT_ADDR + elt_idx * REG_EM_BLE_RX_ISO_BUF_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x000000FF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_rxisosubevtcnt_subevtcnt_setf(int elt_idx, uint8_t subevtcnt) +{ + BLE_ASSERT_ERR((((uint16_t)subevtcnt << 0) & ~((uint16_t)0x000000FF)) == 0); + EM_BLE_WR(EM_BLE_RXISOSUBEVTCNT_ADDR + elt_idx * REG_EM_BLE_RX_ISO_BUF_SIZE, (uint16_t)subevtcnt << 0); +} + +/** + * @brief RXISODATABUF register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00         RXISODATABUF   0x0
+ * 
+ */ +#define EM_BLE_RXISODATABUF_ADDR (0x00910006 + EM_BLE_RX_ISO_BUF_OFFSET) +#define EM_BLE_RXISODATABUF_INDEX 0x00000003 +#define EM_BLE_RXISODATABUF_RESET 0x00000000 +#define EM_BLE_RXISODATABUF_COUNT 31 + +__INLINE uint16_t em_ble_rxisodatabuf_get(int elt_idx, int reg_idx) +{ + BLE_ASSERT_ERR(reg_idx <= 30); + return EM_BLE_RD(EM_BLE_RXISODATABUF_ADDR + elt_idx * REG_EM_BLE_RX_ISO_BUF_SIZE + reg_idx * 2); +} + +__INLINE void em_ble_rxisodatabuf_set(int elt_idx, int reg_idx, uint16_t value) +{ + BLE_ASSERT_ERR(reg_idx <= 30); + EM_BLE_WR(EM_BLE_RXISODATABUF_ADDR + elt_idx * REG_EM_BLE_RX_ISO_BUF_SIZE + reg_idx * 2, value); +} + +// field definitions +#define EM_BLE_RXISODATABUF_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_RXISODATABUF_LSB 0 +#define EM_BLE_RXISODATABUF_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_RXISODATABUF_RST 0x0 + +__INLINE uint16_t em_ble_rxisodatabuf_getf(int elt_idx, int reg_idx) +{ + BLE_ASSERT_ERR(reg_idx <= 30); + uint16_t localVal = EM_BLE_RD(EM_BLE_RXISODATABUF_ADDR + elt_idx * REG_EM_BLE_RX_ISO_BUF_SIZE + reg_idx * 2); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_rxisodatabuf_setf(int elt_idx, int reg_idx, uint16_t rxisodatabuf) +{ + BLE_ASSERT_ERR(reg_idx <= 30); + BLE_ASSERT_ERR((((uint16_t)rxisodatabuf << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_RXISODATABUF_ADDR + elt_idx * REG_EM_BLE_RX_ISO_BUF_SIZE + reg_idx * 2, (uint16_t)rxisodatabuf << 0); +} + + +#endif // _REG_EM_BLE_RX_ISO_BUF_H_ + diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_em_ble_rx_iso_desc.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_em_ble_rx_iso_desc.h new file mode 100755 index 0000000..20e5f99 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_em_ble_rx_iso_desc.h @@ -0,0 +1,332 @@ +#ifndef _REG_EM_BLE_RX_ISO_DESC_H_ +#define _REG_EM_BLE_RX_ISO_DESC_H_ + +#include +#include "_reg_em_ble_rx_iso_desc.h" +#include "compiler.h" +#include "architect.h" +#include "em_map.h" +#include "ble_reg_access.h" + +#define REG_EM_BLE_RX_ISO_DESC_COUNT 6 + +#define REG_EM_BLE_RX_ISO_DESC_DECODING_MASK 0x0000000F + +#define REG_EM_BLE_RX_ISO_DESC_ADDR_GET(idx) (EM_BLE_RX_ISO_DESC_OFFSET + (idx) * REG_EM_BLE_RX_ISO_DESC_SIZE) + +/** + * @brief RXISOPTR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     15               RXDONE   0
+ *  13:00            RXNEXTPTR   0x0
+ * 
+ */ +#define EM_BLE_RXISOPTR_ADDR (0x00910000 + EM_BLE_RX_ISO_DESC_OFFSET) +#define EM_BLE_RXISOPTR_INDEX 0x00000000 +#define EM_BLE_RXISOPTR_RESET 0x00000000 + +__INLINE uint16_t em_ble_rxisoptr_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_RXISOPTR_ADDR + elt_idx * REG_EM_BLE_RX_ISO_DESC_SIZE); +} + +__INLINE void em_ble_rxisoptr_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_RXISOPTR_ADDR + elt_idx * REG_EM_BLE_RX_ISO_DESC_SIZE, value); +} + +// field definitions +#define EM_BLE_RXDONE_BIT ((uint16_t)0x00008000) +#define EM_BLE_RXDONE_POS 15 +#define EM_BLE_RXNEXTPTR_MASK ((uint16_t)0x00003FFF) +#define EM_BLE_RXNEXTPTR_LSB 0 +#define EM_BLE_RXNEXTPTR_WIDTH ((uint16_t)0x0000000E) + +#define EM_BLE_RXDONE_RST 0x0 +#define EM_BLE_RXNEXTPTR_RST 0x0 + +__INLINE void em_ble_rxisoptr_pack(int elt_idx, uint8_t rxdone, uint16_t rxnextptr) +{ + BLE_ASSERT_ERR((((uint16_t)rxdone << 15) & ~((uint16_t)0x00008000)) == 0); + BLE_ASSERT_ERR((((uint16_t)rxnextptr << 0) & ~((uint16_t)0x00003FFF)) == 0); + EM_BLE_WR(EM_BLE_RXISOPTR_ADDR + elt_idx * REG_EM_BLE_RX_ISO_DESC_SIZE, ((uint16_t)rxdone << 15) | ((uint16_t)rxnextptr << 0)); +} + +__INLINE void em_ble_rxisoptr_unpack(int elt_idx, uint8_t* rxdone, uint16_t* rxnextptr) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXISOPTR_ADDR + elt_idx * REG_EM_BLE_RX_ISO_DESC_SIZE); + + *rxdone = (localVal & ((uint16_t)0x00008000)) >> 15; + *rxnextptr = (localVal & ((uint16_t)0x00003FFF)) >> 0; +} + +__INLINE uint8_t em_ble_rxisoptr_rxdone_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXISOPTR_ADDR + elt_idx * REG_EM_BLE_RX_ISO_DESC_SIZE); + return ((localVal & ((uint16_t)0x00008000)) >> 15); +} + +__INLINE void em_ble_rxisoptr_rxdone_setf(int elt_idx, uint8_t rxdone) +{ + BLE_ASSERT_ERR((((uint16_t)rxdone << 15) & ~((uint16_t)0x00008000)) == 0); + EM_BLE_WR(EM_BLE_RXISOPTR_ADDR + elt_idx * REG_EM_BLE_RX_ISO_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXISOPTR_ADDR + elt_idx * REG_EM_BLE_RX_ISO_DESC_SIZE) & ~((uint16_t)0x00008000)) | ((uint16_t)rxdone << 15)); +} + +__INLINE uint16_t em_ble_rxisoptr_rxnextptr_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXISOPTR_ADDR + elt_idx * REG_EM_BLE_RX_ISO_DESC_SIZE); + return ((localVal & ((uint16_t)0x00003FFF)) >> 0); +} + +__INLINE void em_ble_rxisoptr_rxnextptr_setf(int elt_idx, uint16_t rxnextptr) +{ + BLE_ASSERT_ERR((((uint16_t)rxnextptr << 0) & ~((uint16_t)0x00003FFF)) == 0); + EM_BLE_WR(EM_BLE_RXISOPTR_ADDR + elt_idx * REG_EM_BLE_RX_ISO_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXISOPTR_ADDR + elt_idx * REG_EM_BLE_RX_ISO_DESC_SIZE) & ~((uint16_t)0x00003FFF)) | ((uint16_t)rxnextptr << 0)); +} + +/** + * @brief RXISOCNT0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00           RXPLD_CNT0   0x0
+ * 
+ */ +#define EM_BLE_RXISOCNT0_ADDR (0x00910002 + EM_BLE_RX_ISO_DESC_OFFSET) +#define EM_BLE_RXISOCNT0_INDEX 0x00000001 +#define EM_BLE_RXISOCNT0_RESET 0x00000000 + +__INLINE uint16_t em_ble_rxisocnt0_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_RXISOCNT0_ADDR + elt_idx * REG_EM_BLE_RX_ISO_DESC_SIZE); +} + +__INLINE void em_ble_rxisocnt0_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_RXISOCNT0_ADDR + elt_idx * REG_EM_BLE_RX_ISO_DESC_SIZE, value); +} + +// field definitions +#define EM_BLE_RXPLD_CNT0_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_RXPLD_CNT0_LSB 0 +#define EM_BLE_RXPLD_CNT0_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_RXPLD_CNT0_RST 0x0 + +__INLINE uint16_t em_ble_rxisocnt0_rxpld_cnt0_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXISOCNT0_ADDR + elt_idx * REG_EM_BLE_RX_ISO_DESC_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_rxisocnt0_rxpld_cnt0_setf(int elt_idx, uint16_t rxpldcnt0) +{ + BLE_ASSERT_ERR((((uint16_t)rxpldcnt0 << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_RXISOCNT0_ADDR + elt_idx * REG_EM_BLE_RX_ISO_DESC_SIZE, (uint16_t)rxpldcnt0 << 0); +} + +/** + * @brief RXISOCNT1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00           RXPLD_CNT1   0x0
+ * 
+ */ +#define EM_BLE_RXISOCNT1_ADDR (0x00910004 + EM_BLE_RX_ISO_DESC_OFFSET) +#define EM_BLE_RXISOCNT1_INDEX 0x00000002 +#define EM_BLE_RXISOCNT1_RESET 0x00000000 + +__INLINE uint16_t em_ble_rxisocnt1_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_RXISOCNT1_ADDR + elt_idx * REG_EM_BLE_RX_ISO_DESC_SIZE); +} + +__INLINE void em_ble_rxisocnt1_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_RXISOCNT1_ADDR + elt_idx * REG_EM_BLE_RX_ISO_DESC_SIZE, value); +} + +// field definitions +#define EM_BLE_RXPLD_CNT1_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_RXPLD_CNT1_LSB 0 +#define EM_BLE_RXPLD_CNT1_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_RXPLD_CNT1_RST 0x0 + +__INLINE uint16_t em_ble_rxisocnt1_rxpld_cnt1_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXISOCNT1_ADDR + elt_idx * REG_EM_BLE_RX_ISO_DESC_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_rxisocnt1_rxpld_cnt1_setf(int elt_idx, uint16_t rxpldcnt1) +{ + BLE_ASSERT_ERR((((uint16_t)rxpldcnt1 << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_RXISOCNT1_ADDR + elt_idx * REG_EM_BLE_RX_ISO_DESC_SIZE, (uint16_t)rxpldcnt1 << 0); +} + +/** + * @brief RXISOCNT2 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:08       RXFLUSHINSTANT   0x0
+ *  06:00           RXPLD_CNT2   0x0
+ * 
+ */ +#define EM_BLE_RXISOCNT2_ADDR (0x00910006 + EM_BLE_RX_ISO_DESC_OFFSET) +#define EM_BLE_RXISOCNT2_INDEX 0x00000003 +#define EM_BLE_RXISOCNT2_RESET 0x00000000 + +__INLINE uint16_t em_ble_rxisocnt2_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_RXISOCNT2_ADDR + elt_idx * REG_EM_BLE_RX_ISO_DESC_SIZE); +} + +__INLINE void em_ble_rxisocnt2_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_RXISOCNT2_ADDR + elt_idx * REG_EM_BLE_RX_ISO_DESC_SIZE, value); +} + +// field definitions +#define EM_BLE_RXFLUSHINSTANT_MASK ((uint16_t)0x0000FF00) +#define EM_BLE_RXFLUSHINSTANT_LSB 8 +#define EM_BLE_RXFLUSHINSTANT_WIDTH ((uint16_t)0x00000008) +#define EM_BLE_RXPLD_CNT2_MASK ((uint16_t)0x0000007F) +#define EM_BLE_RXPLD_CNT2_LSB 0 +#define EM_BLE_RXPLD_CNT2_WIDTH ((uint16_t)0x00000007) + +#define EM_BLE_RXFLUSHINSTANT_RST 0x0 +#define EM_BLE_RXPLD_CNT2_RST 0x0 + +__INLINE void em_ble_rxisocnt2_pack(int elt_idx, uint8_t rxflushinstant, uint8_t rxpldcnt2) +{ + BLE_ASSERT_ERR((((uint16_t)rxflushinstant << 8) & ~((uint16_t)0x0000FF00)) == 0); + BLE_ASSERT_ERR((((uint16_t)rxpldcnt2 << 0) & ~((uint16_t)0x0000007F)) == 0); + EM_BLE_WR(EM_BLE_RXISOCNT2_ADDR + elt_idx * REG_EM_BLE_RX_ISO_DESC_SIZE, ((uint16_t)rxflushinstant << 8) | ((uint16_t)rxpldcnt2 << 0)); +} + +__INLINE void em_ble_rxisocnt2_unpack(int elt_idx, uint8_t* rxflushinstant, uint8_t* rxpldcnt2) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXISOCNT2_ADDR + elt_idx * REG_EM_BLE_RX_ISO_DESC_SIZE); + + *rxflushinstant = (localVal & ((uint16_t)0x0000FF00)) >> 8; + *rxpldcnt2 = (localVal & ((uint16_t)0x0000007F)) >> 0; +} + +__INLINE uint8_t em_ble_rxisocnt2_rxflushinstant_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXISOCNT2_ADDR + elt_idx * REG_EM_BLE_RX_ISO_DESC_SIZE); + return ((localVal & ((uint16_t)0x0000FF00)) >> 8); +} + +__INLINE void em_ble_rxisocnt2_rxflushinstant_setf(int elt_idx, uint8_t rxflushinstant) +{ + BLE_ASSERT_ERR((((uint16_t)rxflushinstant << 8) & ~((uint16_t)0x0000FF00)) == 0); + EM_BLE_WR(EM_BLE_RXISOCNT2_ADDR + elt_idx * REG_EM_BLE_RX_ISO_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXISOCNT2_ADDR + elt_idx * REG_EM_BLE_RX_ISO_DESC_SIZE) & ~((uint16_t)0x0000FF00)) | ((uint16_t)rxflushinstant << 8)); +} + +__INLINE uint8_t em_ble_rxisocnt2_rxpld_cnt2_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXISOCNT2_ADDR + elt_idx * REG_EM_BLE_RX_ISO_DESC_SIZE); + return ((localVal & ((uint16_t)0x0000007F)) >> 0); +} + +__INLINE void em_ble_rxisocnt2_rxpld_cnt2_setf(int elt_idx, uint8_t rxpldcnt2) +{ + BLE_ASSERT_ERR((((uint16_t)rxpldcnt2 << 0) & ~((uint16_t)0x0000007F)) == 0); + EM_BLE_WR(EM_BLE_RXISOCNT2_ADDR + elt_idx * REG_EM_BLE_RX_ISO_DESC_SIZE, (EM_BLE_RD(EM_BLE_RXISOCNT2_ADDR + elt_idx * REG_EM_BLE_RX_ISO_DESC_SIZE) & ~((uint16_t)0x0000007F)) | ((uint16_t)rxpldcnt2 << 0)); +} + +/** + * @brief RXISOBUFPTR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  13:00          RXISOBUFPTR   0x0
+ * 
+ */ +#define EM_BLE_RXISOBUFPTR_ADDR (0x00910008 + EM_BLE_RX_ISO_DESC_OFFSET) +#define EM_BLE_RXISOBUFPTR_INDEX 0x00000004 +#define EM_BLE_RXISOBUFPTR_RESET 0x00000000 + +__INLINE uint16_t em_ble_rxisobufptr_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_RXISOBUFPTR_ADDR + elt_idx * REG_EM_BLE_RX_ISO_DESC_SIZE); +} + +__INLINE void em_ble_rxisobufptr_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_RXISOBUFPTR_ADDR + elt_idx * REG_EM_BLE_RX_ISO_DESC_SIZE, value); +} + +// field definitions +#define EM_BLE_RXISOBUFPTR_MASK ((uint16_t)0x00003FFF) +#define EM_BLE_RXISOBUFPTR_LSB 0 +#define EM_BLE_RXISOBUFPTR_WIDTH ((uint16_t)0x0000000E) + +#define EM_BLE_RXISOBUFPTR_RST 0x0 + +__INLINE uint16_t em_ble_rxisobufptr_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXISOBUFPTR_ADDR + elt_idx * REG_EM_BLE_RX_ISO_DESC_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x00003FFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_rxisobufptr_setf(int elt_idx, uint16_t rxisobufptr) +{ + BLE_ASSERT_ERR((((uint16_t)rxisobufptr << 0) & ~((uint16_t)0x00003FFF)) == 0); + EM_BLE_WR(EM_BLE_RXISOBUFPTR_ADDR + elt_idx * REG_EM_BLE_RX_ISO_DESC_SIZE, (uint16_t)rxisobufptr << 0); +} + +/** + * @brief RXISORESERVED register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00                 RSVD   0x0
+ * 
+ */ +#define EM_BLE_RXISORESERVED_ADDR (0x0091000A + EM_BLE_RX_ISO_DESC_OFFSET) +#define EM_BLE_RXISORESERVED_INDEX 0x00000005 +#define EM_BLE_RXISORESERVED_RESET 0x00000000 + +__INLINE uint16_t em_ble_rxisoreserved_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_RXISORESERVED_ADDR + elt_idx * REG_EM_BLE_RX_ISO_DESC_SIZE); +} + +__INLINE void em_ble_rxisoreserved_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_RXISORESERVED_ADDR + elt_idx * REG_EM_BLE_RX_ISO_DESC_SIZE, value); +} + +// field definitions +#define EM_BLE_RSVD_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_RSVD_LSB 0 +#define EM_BLE_RSVD_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_RSVD_RST 0x0 + +__INLINE uint16_t em_ble_rxisoreserved_rsvd_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_RXISORESERVED_ADDR + elt_idx * REG_EM_BLE_RX_ISO_DESC_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_rxisoreserved_rsvd_setf(int elt_idx, uint16_t rsvd) +{ + BLE_ASSERT_ERR((((uint16_t)rsvd << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_RXISORESERVED_ADDR + elt_idx * REG_EM_BLE_RX_ISO_DESC_SIZE, (uint16_t)rsvd << 0); +} + + +#endif // _REG_EM_BLE_RX_ISO_DESC_H_ + diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_em_ble_tx_audio_buf.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_em_ble_tx_audio_buf.h new file mode 100755 index 0000000..f34b51b --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_em_ble_tx_audio_buf.h @@ -0,0 +1,66 @@ +#ifndef _REG_EM_BLE_TX_AUDIO_BUF_H_ +#define _REG_EM_BLE_TX_AUDIO_BUF_H_ + +#include +#include "_reg_em_ble_tx_audio_buf.h" +#include "compiler.h" +#include "architect.h" +#include "em_map.h" +#include "ble_reg_access.h" + +#define REG_EM_BLE_TX_AUDIO_BUF_COUNT 1 + +#define REG_EM_BLE_TX_AUDIO_BUF_DECODING_MASK 0x00000000 + +#define REG_EM_BLE_TX_AUDIO_BUF_ADDR_GET(idx) (EM_BLE_TX_AUDIO_BUFFER_OFFSET + (idx) * REG_EM_BLE_TX_AUDIO_BUF_SIZE) + +/** + * @brief TXAUDIOBUF register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00           TXAUDIOBUF   0x0
+ * 
+ */ +#define EM_BLE_TXAUDIOBUF_ADDR (0x00910000 + EM_BLE_TX_AUDIO_BUFFER_OFFSET) +#define EM_BLE_TXAUDIOBUF_INDEX 0x00000000 +#define EM_BLE_TXAUDIOBUF_RESET 0x00000000 +#define EM_BLE_TXAUDIOBUF_COUNT 32 + +__INLINE uint16_t em_ble_txaudiobuf_get(int elt_idx, int reg_idx) +{ + BLE_ASSERT_ERR(reg_idx <= 31); + return EM_BLE_RD(EM_BLE_TXAUDIOBUF_ADDR + elt_idx * REG_EM_BLE_TX_AUDIO_BUF_SIZE + reg_idx * 2); +} + +__INLINE void em_ble_txaudiobuf_set(int elt_idx, int reg_idx, uint16_t value) +{ + BLE_ASSERT_ERR(reg_idx <= 31); + EM_BLE_WR(EM_BLE_TXAUDIOBUF_ADDR + elt_idx * REG_EM_BLE_TX_AUDIO_BUF_SIZE + reg_idx * 2, value); +} + +// field definitions +#define EM_BLE_TXAUDIOBUF_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_TXAUDIOBUF_LSB 0 +#define EM_BLE_TXAUDIOBUF_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_TXAUDIOBUF_RST 0x0 + +__INLINE uint16_t em_ble_txaudiobuf_getf(int elt_idx, int reg_idx) +{ + BLE_ASSERT_ERR(reg_idx <= 31); + uint16_t localVal = EM_BLE_RD(EM_BLE_TXAUDIOBUF_ADDR + elt_idx * REG_EM_BLE_TX_AUDIO_BUF_SIZE + reg_idx * 2); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_txaudiobuf_setf(int elt_idx, int reg_idx, uint16_t txaudiobuf) +{ + BLE_ASSERT_ERR(reg_idx <= 31); + BLE_ASSERT_ERR((((uint16_t)txaudiobuf << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_TXAUDIOBUF_ADDR + elt_idx * REG_EM_BLE_TX_AUDIO_BUF_SIZE + reg_idx * 2, (uint16_t)txaudiobuf << 0); +} + + +#endif // _REG_EM_BLE_TX_AUDIO_BUF_H_ + diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_em_ble_tx_buf.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_em_ble_tx_buf.h new file mode 100755 index 0000000..f99726c --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_em_ble_tx_buf.h @@ -0,0 +1,66 @@ +#ifndef _REG_EM_BLE_TX_BUF_H_ +#define _REG_EM_BLE_TX_BUF_H_ + +#include +#include "_reg_em_ble_tx_buf.h" +#include "compiler.h" +#include "architect.h" +#include "em_map.h" +#include "ble_reg_access.h" + +#define REG_EM_BLE_TX_BUF_COUNT 1 + +#define REG_EM_BLE_TX_BUF_DECODING_MASK 0x00000000 + +#define REG_EM_BLE_TX_BUF_ADDR_GET(idx) (EM_BLE_TX_BUFFER_OFFSET + (idx) * REG_EM_BLE_TX_BUF_SIZE) + +/** + * @brief TXBUF register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00                TXBUF   0x0
+ * 
+ */ +#define EM_BLE_TXBUF_ADDR (0x00910000 + EM_BLE_TX_BUFFER_OFFSET) +#define EM_BLE_TXBUF_INDEX 0x00000000 +#define EM_BLE_TXBUF_RESET 0x00000000 +#define EM_BLE_TXBUF_COUNT 19 + +__INLINE uint16_t em_ble_txbuf_get(int elt_idx, int reg_idx) +{ + BLE_ASSERT_ERR(reg_idx <= 18); + return EM_BLE_RD(EM_BLE_TXBUF_ADDR + elt_idx * REG_EM_BLE_TX_BUF_SIZE + reg_idx * 2); +} + +__INLINE void em_ble_txbuf_set(int elt_idx, int reg_idx, uint16_t value) +{ + BLE_ASSERT_ERR(reg_idx <= 18); + EM_BLE_WR(EM_BLE_TXBUF_ADDR + elt_idx * REG_EM_BLE_TX_BUF_SIZE + reg_idx * 2, value); +} + +// field definitions +#define EM_BLE_TXBUF_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_TXBUF_LSB 0 +#define EM_BLE_TXBUF_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_TXBUF_RST 0x0 + +__INLINE uint16_t em_ble_txbuf_getf(int elt_idx, int reg_idx) +{ + BLE_ASSERT_ERR(reg_idx <= 18); + uint16_t localVal = EM_BLE_RD(EM_BLE_TXBUF_ADDR + elt_idx * REG_EM_BLE_TX_BUF_SIZE + reg_idx * 2); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_txbuf_setf(int elt_idx, int reg_idx, uint16_t txbuf) +{ + BLE_ASSERT_ERR(reg_idx <= 18); + BLE_ASSERT_ERR((((uint16_t)txbuf << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_TXBUF_ADDR + elt_idx * REG_EM_BLE_TX_BUF_SIZE + reg_idx * 2, (uint16_t)txbuf << 0); +} + + +#endif // _REG_EM_BLE_TX_BUF_H_ + diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_em_ble_tx_buf_cntl.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_em_ble_tx_buf_cntl.h new file mode 100755 index 0000000..7d0f432 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_em_ble_tx_buf_cntl.h @@ -0,0 +1,66 @@ +#ifndef _REG_EM_BLE_TX_BUF_CNTL_H_ +#define _REG_EM_BLE_TX_BUF_CNTL_H_ + +#include +#include "_reg_em_ble_tx_buf_cntl.h" +#include "compiler.h" +#include "architect.h" +#include "em_map.h" +#include "ble_reg_access.h" + +#define REG_EM_BLE_TX_BUF_CNTL_COUNT 1 + +#define REG_EM_BLE_TX_BUF_CNTL_DECODING_MASK 0x00000000 + +#define REG_EM_BLE_TX_BUF_CNTL_ADDR_GET(idx) (EM_BLE_TX_BUFFER_CNTL_OFFSET + (idx) * REG_EM_BLE_TX_BUF_CNTL_SIZE) + +/** + * @brief TXBUFCNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00            TXBUFCNTL   0x0
+ * 
+ */ +#define EM_BLE_TXBUFCNTL_ADDR (0x00910000 + EM_BLE_TX_BUFFER_CNTL_OFFSET) +#define EM_BLE_TXBUFCNTL_INDEX 0x00000000 +#define EM_BLE_TXBUFCNTL_RESET 0x00000000 +#define EM_BLE_TXBUFCNTL_COUNT 19 + +__INLINE uint16_t em_ble_txbufcntl_get(int elt_idx, int reg_idx) +{ + BLE_ASSERT_ERR(reg_idx <= 18); + return EM_BLE_RD(EM_BLE_TXBUFCNTL_ADDR + elt_idx * REG_EM_BLE_TX_BUF_CNTL_SIZE + reg_idx * 2); +} + +__INLINE void em_ble_txbufcntl_set(int elt_idx, int reg_idx, uint16_t value) +{ + BLE_ASSERT_ERR(reg_idx <= 18); + EM_BLE_WR(EM_BLE_TXBUFCNTL_ADDR + elt_idx * REG_EM_BLE_TX_BUF_CNTL_SIZE + reg_idx * 2, value); +} + +// field definitions +#define EM_BLE_TXBUFCNTL_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_TXBUFCNTL_LSB 0 +#define EM_BLE_TXBUFCNTL_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_TXBUFCNTL_RST 0x0 + +__INLINE uint16_t em_ble_txbufcntl_getf(int elt_idx, int reg_idx) +{ + BLE_ASSERT_ERR(reg_idx <= 18); + uint16_t localVal = EM_BLE_RD(EM_BLE_TXBUFCNTL_ADDR + elt_idx * REG_EM_BLE_TX_BUF_CNTL_SIZE + reg_idx * 2); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_txbufcntl_setf(int elt_idx, int reg_idx, uint16_t txbufcntl) +{ + BLE_ASSERT_ERR(reg_idx <= 18); + BLE_ASSERT_ERR((((uint16_t)txbufcntl << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_TXBUFCNTL_ADDR + elt_idx * REG_EM_BLE_TX_BUF_CNTL_SIZE + reg_idx * 2, (uint16_t)txbufcntl << 0); +} + + +#endif // _REG_EM_BLE_TX_BUF_CNTL_H_ + diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_em_ble_tx_desc.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_em_ble_tx_desc.h new file mode 100755 index 0000000..2c3c192 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_em_ble_tx_desc.h @@ -0,0 +1,974 @@ +#ifndef _REG_EM_BLE_TX_DESC_H_ +#define _REG_EM_BLE_TX_DESC_H_ + +#include +#include "_reg_em_ble_tx_desc.h" +#include "compiler.h" +#include "architect.h" +#include "em_map.h" +#include "ble_reg_access.h" + +#define REG_EM_BLE_TX_DESC_COUNT 8 + +#define REG_EM_BLE_TX_DESC_DECODING_MASK 0x0000000F + +#define REG_EM_BLE_TX_DESC_ADDR_GET(idx) (EM_BLE_TX_DESC_OFFSET + (idx) * REG_EM_BLE_TX_DESC_SIZE) + +/** + * @brief TXCNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     15               TXDONE   0
+ *  13:00             NEXT_PTR   0x0
+ * 
+ */ +#define EM_BLE_TXCNTL_ADDR (0x00910000 + EM_BLE_TX_DESC_OFFSET) +#define EM_BLE_TXCNTL_INDEX 0x00000000 +#define EM_BLE_TXCNTL_RESET 0x00000000 + +__INLINE uint16_t em_ble_txcntl_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_TXCNTL_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); +} + +__INLINE void em_ble_txcntl_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_TXCNTL_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, value); +} + +// field definitions +#define EM_BLE_TXDONE_BIT ((uint16_t)0x00008000) +#define EM_BLE_TXDONE_POS 15 +#define EM_BLE_NEXT_PTR_MASK ((uint16_t)0x00003FFF) +#define EM_BLE_NEXT_PTR_LSB 0 +#define EM_BLE_NEXT_PTR_WIDTH ((uint16_t)0x0000000E) + +#define EM_BLE_TXDONE_RST 0x0 +#define EM_BLE_NEXT_PTR_RST 0x0 + +__INLINE void em_ble_txcntl_pack(int elt_idx, uint8_t txdone, uint16_t nextptr) +{ + BLE_ASSERT_ERR((((uint16_t)txdone << 15) & ~((uint16_t)0x00008000)) == 0); + BLE_ASSERT_ERR((((uint16_t)nextptr << 0) & ~((uint16_t)0x00003FFF)) == 0); + EM_BLE_WR(EM_BLE_TXCNTL_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, ((uint16_t)txdone << 15) | ((uint16_t)nextptr << 0)); +} + +__INLINE void em_ble_txcntl_unpack(int elt_idx, uint8_t* txdone, uint16_t* nextptr) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXCNTL_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); + + *txdone = (localVal & ((uint16_t)0x00008000)) >> 15; + *nextptr = (localVal & ((uint16_t)0x00003FFF)) >> 0; +} + +__INLINE uint8_t em_ble_txcntl_txdone_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXCNTL_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00008000)) >> 15); +} + +__INLINE void em_ble_txcntl_txdone_setf(int elt_idx, uint8_t txdone) +{ + BLE_ASSERT_ERR((((uint16_t)txdone << 15) & ~((uint16_t)0x00008000)) == 0); + EM_BLE_WR(EM_BLE_TXCNTL_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, (EM_BLE_RD(EM_BLE_TXCNTL_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE) & ~((uint16_t)0x00008000)) | ((uint16_t)txdone << 15)); +} + +__INLINE uint16_t em_ble_txcntl_next_ptr_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXCNTL_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00003FFF)) >> 0); +} + +__INLINE void em_ble_txcntl_next_ptr_setf(int elt_idx, uint16_t nextptr) +{ + BLE_ASSERT_ERR((((uint16_t)nextptr << 0) & ~((uint16_t)0x00003FFF)) == 0); + EM_BLE_WR(EM_BLE_TXCNTL_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, (EM_BLE_RD(EM_BLE_TXCNTL_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE) & ~((uint16_t)0x00003FFF)) | ((uint16_t)nextptr << 0)); +} + +/** + * @brief TXPHCE register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:08                TXLEN   0x0
+ *  07:06             TXACLRFU   0x0
+ *     05                 TXCP   0
+ *     04                 TXMD   0
+ *     03                 TXSN   0
+ *     02               TXNESN   0
+ *  01:00               TXLLID   0x0
+ * 
+ */ +#define EM_BLE_TXPHCE_ADDR (0x00910002 + EM_BLE_TX_DESC_OFFSET) +#define EM_BLE_TXPHCE_INDEX 0x00000001 +#define EM_BLE_TXPHCE_RESET 0x00000000 + +__INLINE uint16_t em_ble_txphce_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_TXPHCE_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); +} + +__INLINE void em_ble_txphce_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_TXPHCE_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, value); +} + +// field definitions +#define EM_BLE_TXLEN_MASK ((uint16_t)0x0000FF00) +#define EM_BLE_TXLEN_LSB 8 +#define EM_BLE_TXLEN_WIDTH ((uint16_t)0x00000008) +#define EM_BLE_TXACLRFU_MASK ((uint16_t)0x000000C0) +#define EM_BLE_TXACLRFU_LSB 6 +#define EM_BLE_TXACLRFU_WIDTH ((uint16_t)0x00000002) +#define EM_BLE_TXCP_BIT ((uint16_t)0x00000020) +#define EM_BLE_TXCP_POS 5 +#define EM_BLE_TXMD_BIT ((uint16_t)0x00000010) +#define EM_BLE_TXMD_POS 4 +#define EM_BLE_TXSN_BIT ((uint16_t)0x00000008) +#define EM_BLE_TXSN_POS 3 +#define EM_BLE_TXNESN_BIT ((uint16_t)0x00000004) +#define EM_BLE_TXNESN_POS 2 +#define EM_BLE_TXLLID_MASK ((uint16_t)0x00000003) +#define EM_BLE_TXLLID_LSB 0 +#define EM_BLE_TXLLID_WIDTH ((uint16_t)0x00000002) + +#define EM_BLE_TXLEN_RST 0x0 +#define EM_BLE_TXACLRFU_RST 0x0 +#define EM_BLE_TXCP_RST 0x0 +#define EM_BLE_TXMD_RST 0x0 +#define EM_BLE_TXSN_RST 0x0 +#define EM_BLE_TXNESN_RST 0x0 +#define EM_BLE_TXLLID_RST 0x0 + +__INLINE void em_ble_txphce_pack(int elt_idx, uint8_t txlen, uint8_t txaclrfu, uint8_t txcp, uint8_t txmd, uint8_t txsn, uint8_t txnesn, uint8_t txllid) +{ + BLE_ASSERT_ERR((((uint16_t)txlen << 8) & ~((uint16_t)0x0000FF00)) == 0); + BLE_ASSERT_ERR((((uint16_t)txaclrfu << 6) & ~((uint16_t)0x000000C0)) == 0); + BLE_ASSERT_ERR((((uint16_t)txcp << 5) & ~((uint16_t)0x00000020)) == 0); + BLE_ASSERT_ERR((((uint16_t)txmd << 4) & ~((uint16_t)0x00000010)) == 0); + BLE_ASSERT_ERR((((uint16_t)txsn << 3) & ~((uint16_t)0x00000008)) == 0); + BLE_ASSERT_ERR((((uint16_t)txnesn << 2) & ~((uint16_t)0x00000004)) == 0); + BLE_ASSERT_ERR((((uint16_t)txllid << 0) & ~((uint16_t)0x00000003)) == 0); + EM_BLE_WR(EM_BLE_TXPHCE_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, ((uint16_t)txlen << 8) | ((uint16_t)txaclrfu << 6) | ((uint16_t)txcp << 5) | ((uint16_t)txmd << 4) | ((uint16_t)txsn << 3) | ((uint16_t)txnesn << 2) | ((uint16_t)txllid << 0)); +} + +__INLINE void em_ble_txphce_unpack(int elt_idx, uint8_t* txlen, uint8_t* txaclrfu, uint8_t* txcp, uint8_t* txmd, uint8_t* txsn, uint8_t* txnesn, uint8_t* txllid) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXPHCE_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); + + *txlen = (localVal & ((uint16_t)0x0000FF00)) >> 8; + *txaclrfu = (localVal & ((uint16_t)0x000000C0)) >> 6; + *txcp = (localVal & ((uint16_t)0x00000020)) >> 5; + *txmd = (localVal & ((uint16_t)0x00000010)) >> 4; + *txsn = (localVal & ((uint16_t)0x00000008)) >> 3; + *txnesn = (localVal & ((uint16_t)0x00000004)) >> 2; + *txllid = (localVal & ((uint16_t)0x00000003)) >> 0; +} + +__INLINE uint8_t em_ble_txphce_txlen_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXPHCE_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); + return ((localVal & ((uint16_t)0x0000FF00)) >> 8); +} + +__INLINE void em_ble_txphce_txlen_setf(int elt_idx, uint8_t txlen) +{ + BLE_ASSERT_ERR((((uint16_t)txlen << 8) & ~((uint16_t)0x0000FF00)) == 0); + EM_BLE_WR(EM_BLE_TXPHCE_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, (EM_BLE_RD(EM_BLE_TXPHCE_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE) & ~((uint16_t)0x0000FF00)) | ((uint16_t)txlen << 8)); +} + +__INLINE uint8_t em_ble_txphce_txaclrfu_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXPHCE_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); + return ((localVal & ((uint16_t)0x000000C0)) >> 6); +} + +__INLINE void em_ble_txphce_txaclrfu_setf(int elt_idx, uint8_t txaclrfu) +{ + BLE_ASSERT_ERR((((uint16_t)txaclrfu << 6) & ~((uint16_t)0x000000C0)) == 0); + EM_BLE_WR(EM_BLE_TXPHCE_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, (EM_BLE_RD(EM_BLE_TXPHCE_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE) & ~((uint16_t)0x000000C0)) | ((uint16_t)txaclrfu << 6)); +} + +__INLINE uint8_t em_ble_txphce_txcp_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXPHCE_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000020)) >> 5); +} + +__INLINE void em_ble_txphce_txcp_setf(int elt_idx, uint8_t txcp) +{ + BLE_ASSERT_ERR((((uint16_t)txcp << 5) & ~((uint16_t)0x00000020)) == 0); + EM_BLE_WR(EM_BLE_TXPHCE_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, (EM_BLE_RD(EM_BLE_TXPHCE_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE) & ~((uint16_t)0x00000020)) | ((uint16_t)txcp << 5)); +} + +__INLINE uint8_t em_ble_txphce_txmd_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXPHCE_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000010)) >> 4); +} + +__INLINE void em_ble_txphce_txmd_setf(int elt_idx, uint8_t txmd) +{ + BLE_ASSERT_ERR((((uint16_t)txmd << 4) & ~((uint16_t)0x00000010)) == 0); + EM_BLE_WR(EM_BLE_TXPHCE_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, (EM_BLE_RD(EM_BLE_TXPHCE_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE) & ~((uint16_t)0x00000010)) | ((uint16_t)txmd << 4)); +} + +__INLINE uint8_t em_ble_txphce_txsn_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXPHCE_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000008)) >> 3); +} + +__INLINE void em_ble_txphce_txsn_setf(int elt_idx, uint8_t txsn) +{ + BLE_ASSERT_ERR((((uint16_t)txsn << 3) & ~((uint16_t)0x00000008)) == 0); + EM_BLE_WR(EM_BLE_TXPHCE_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, (EM_BLE_RD(EM_BLE_TXPHCE_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE) & ~((uint16_t)0x00000008)) | ((uint16_t)txsn << 3)); +} + +__INLINE uint8_t em_ble_txphce_txnesn_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXPHCE_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000004)) >> 2); +} + +__INLINE void em_ble_txphce_txnesn_setf(int elt_idx, uint8_t txnesn) +{ + BLE_ASSERT_ERR((((uint16_t)txnesn << 2) & ~((uint16_t)0x00000004)) == 0); + EM_BLE_WR(EM_BLE_TXPHCE_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, (EM_BLE_RD(EM_BLE_TXPHCE_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE) & ~((uint16_t)0x00000004)) | ((uint16_t)txnesn << 2)); +} + +__INLINE uint8_t em_ble_txphce_txllid_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXPHCE_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000003)) >> 0); +} + +__INLINE void em_ble_txphce_txllid_setf(int elt_idx, uint8_t txllid) +{ + BLE_ASSERT_ERR((((uint16_t)txllid << 0) & ~((uint16_t)0x00000003)) == 0); + EM_BLE_WR(EM_BLE_TXPHCE_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, (EM_BLE_RD(EM_BLE_TXPHCE_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE) & ~((uint16_t)0x00000003)) | ((uint16_t)txllid << 0)); +} + +/** + * @brief TXPHADV register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:08             TXADVLEN   0x0
+ *     07              TXRXADD   0
+ *     06              TXTXADD   0
+ *     05             TXCHSEL2   0
+ *     04             TXADVRFU   0
+ *  03:00               TXTYPE   0x0
+ * 
+ */ +#define EM_BLE_TXPHADV_ADDR (0x00910002 + EM_BLE_TX_DESC_OFFSET) +#define EM_BLE_TXPHADV_INDEX 0x00000001 +#define EM_BLE_TXPHADV_RESET 0x00000000 + +__INLINE uint16_t em_ble_txphadv_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_TXPHADV_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); +} + +__INLINE void em_ble_txphadv_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_TXPHADV_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, value); +} + +// field definitions +#define EM_BLE_TXADVLEN_MASK ((uint16_t)0x0000FF00) +#define EM_BLE_TXADVLEN_LSB 8 +#define EM_BLE_TXADVLEN_WIDTH ((uint16_t)0x00000008) +#define EM_BLE_TXRXADD_BIT ((uint16_t)0x00000080) +#define EM_BLE_TXRXADD_POS 7 +#define EM_BLE_TXTXADD_BIT ((uint16_t)0x00000040) +#define EM_BLE_TXTXADD_POS 6 +#define EM_BLE_TXCHSEL2_BIT ((uint16_t)0x00000020) +#define EM_BLE_TXCHSEL2_POS 5 +#define EM_BLE_TXADVRFU_BIT ((uint16_t)0x00000010) +#define EM_BLE_TXADVRFU_POS 4 +#define EM_BLE_TXTYPE_MASK ((uint16_t)0x0000000F) +#define EM_BLE_TXTYPE_LSB 0 +#define EM_BLE_TXTYPE_WIDTH ((uint16_t)0x00000004) + +#define EM_BLE_TXADVLEN_RST 0x0 +#define EM_BLE_TXRXADD_RST 0x0 +#define EM_BLE_TXTXADD_RST 0x0 +#define EM_BLE_TXCHSEL2_RST 0x0 +#define EM_BLE_TXADVRFU_RST 0x0 +#define EM_BLE_TXTYPE_RST 0x0 + +__INLINE void em_ble_txphadv_pack(int elt_idx, uint8_t txadvlen, uint8_t txrxadd, uint8_t txtxadd, uint8_t txchsel2, uint8_t txadvrfu, uint8_t txtype) +{ + BLE_ASSERT_ERR((((uint16_t)txadvlen << 8) & ~((uint16_t)0x0000FF00)) == 0); + BLE_ASSERT_ERR((((uint16_t)txrxadd << 7) & ~((uint16_t)0x00000080)) == 0); + BLE_ASSERT_ERR((((uint16_t)txtxadd << 6) & ~((uint16_t)0x00000040)) == 0); + BLE_ASSERT_ERR((((uint16_t)txchsel2 << 5) & ~((uint16_t)0x00000020)) == 0); + BLE_ASSERT_ERR((((uint16_t)txadvrfu << 4) & ~((uint16_t)0x00000010)) == 0); + BLE_ASSERT_ERR((((uint16_t)txtype << 0) & ~((uint16_t)0x0000000F)) == 0); + EM_BLE_WR(EM_BLE_TXPHADV_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, ((uint16_t)txadvlen << 8) | ((uint16_t)txrxadd << 7) | ((uint16_t)txtxadd << 6) | ((uint16_t)txchsel2 << 5) | ((uint16_t)txadvrfu << 4) | ((uint16_t)txtype << 0)); +} + +__INLINE void em_ble_txphadv_unpack(int elt_idx, uint8_t* txadvlen, uint8_t* txrxadd, uint8_t* txtxadd, uint8_t* txchsel2, uint8_t* txadvrfu, uint8_t* txtype) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXPHADV_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); + + *txadvlen = (localVal & ((uint16_t)0x0000FF00)) >> 8; + *txrxadd = (localVal & ((uint16_t)0x00000080)) >> 7; + *txtxadd = (localVal & ((uint16_t)0x00000040)) >> 6; + *txchsel2 = (localVal & ((uint16_t)0x00000020)) >> 5; + *txadvrfu = (localVal & ((uint16_t)0x00000010)) >> 4; + *txtype = (localVal & ((uint16_t)0x0000000F)) >> 0; +} + +__INLINE uint8_t em_ble_txphadv_txadvlen_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXPHADV_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); + return ((localVal & ((uint16_t)0x0000FF00)) >> 8); +} + +__INLINE void em_ble_txphadv_txadvlen_setf(int elt_idx, uint8_t txadvlen) +{ + BLE_ASSERT_ERR((((uint16_t)txadvlen << 8) & ~((uint16_t)0x0000FF00)) == 0); + EM_BLE_WR(EM_BLE_TXPHADV_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, (EM_BLE_RD(EM_BLE_TXPHADV_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE) & ~((uint16_t)0x0000FF00)) | ((uint16_t)txadvlen << 8)); +} + +__INLINE uint8_t em_ble_txphadv_txrxadd_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXPHADV_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000080)) >> 7); +} + +__INLINE void em_ble_txphadv_txrxadd_setf(int elt_idx, uint8_t txrxadd) +{ + BLE_ASSERT_ERR((((uint16_t)txrxadd << 7) & ~((uint16_t)0x00000080)) == 0); + EM_BLE_WR(EM_BLE_TXPHADV_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, (EM_BLE_RD(EM_BLE_TXPHADV_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE) & ~((uint16_t)0x00000080)) | ((uint16_t)txrxadd << 7)); +} + +__INLINE uint8_t em_ble_txphadv_txtxadd_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXPHADV_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000040)) >> 6); +} + +__INLINE void em_ble_txphadv_txtxadd_setf(int elt_idx, uint8_t txtxadd) +{ + BLE_ASSERT_ERR((((uint16_t)txtxadd << 6) & ~((uint16_t)0x00000040)) == 0); + EM_BLE_WR(EM_BLE_TXPHADV_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, (EM_BLE_RD(EM_BLE_TXPHADV_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE) & ~((uint16_t)0x00000040)) | ((uint16_t)txtxadd << 6)); +} + +__INLINE uint8_t em_ble_txphadv_txchsel2_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXPHADV_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000020)) >> 5); +} + +__INLINE void em_ble_txphadv_txchsel2_setf(int elt_idx, uint8_t txchsel2) +{ + BLE_ASSERT_ERR((((uint16_t)txchsel2 << 5) & ~((uint16_t)0x00000020)) == 0); + EM_BLE_WR(EM_BLE_TXPHADV_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, (EM_BLE_RD(EM_BLE_TXPHADV_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE) & ~((uint16_t)0x00000020)) | ((uint16_t)txchsel2 << 5)); +} + +__INLINE uint8_t em_ble_txphadv_txadvrfu_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXPHADV_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000010)) >> 4); +} + +__INLINE void em_ble_txphadv_txadvrfu_setf(int elt_idx, uint8_t txadvrfu) +{ + BLE_ASSERT_ERR((((uint16_t)txadvrfu << 4) & ~((uint16_t)0x00000010)) == 0); + EM_BLE_WR(EM_BLE_TXPHADV_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, (EM_BLE_RD(EM_BLE_TXPHADV_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE) & ~((uint16_t)0x00000010)) | ((uint16_t)txadvrfu << 4)); +} + +__INLINE uint8_t em_ble_txphadv_txtype_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXPHADV_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); + return ((localVal & ((uint16_t)0x0000000F)) >> 0); +} + +__INLINE void em_ble_txphadv_txtype_setf(int elt_idx, uint8_t txtype) +{ + BLE_ASSERT_ERR((((uint16_t)txtype << 0) & ~((uint16_t)0x0000000F)) == 0); + EM_BLE_WR(EM_BLE_TXPHADV_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, (EM_BLE_RD(EM_BLE_TXPHADV_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE) & ~((uint16_t)0x0000000F)) | ((uint16_t)txtype << 0)); +} + +/** + * @brief TXDATAPTR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00            TXDATAPTR   0x0
+ * 
+ */ +#define EM_BLE_TXDATAPTR_ADDR (0x00910004 + EM_BLE_TX_DESC_OFFSET) +#define EM_BLE_TXDATAPTR_INDEX 0x00000002 +#define EM_BLE_TXDATAPTR_RESET 0x00000000 + +__INLINE uint16_t em_ble_txdataptr_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_TXDATAPTR_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); +} + +__INLINE void em_ble_txdataptr_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_TXDATAPTR_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, value); +} + +// field definitions +#define EM_BLE_TXDATAPTR_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_TXDATAPTR_LSB 0 +#define EM_BLE_TXDATAPTR_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_TXDATAPTR_RST 0x0 + +__INLINE uint16_t em_ble_txdataptr_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXDATAPTR_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_txdataptr_setf(int elt_idx, uint16_t txdataptr) +{ + BLE_ASSERT_ERR((((uint16_t)txdataptr << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_TXDATAPTR_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, (uint16_t)txdataptr << 0); +} + +/** + * @brief TXAEHEADER register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     15               TXRSVD   0
+ *     14                TXPOW   0
+ *     13               TXSYNC   0
+ *     12             TXAUXPTR   0
+ *     11                TXADI   0
+ *     10               TXSUPP   0
+ *     09               TXTGTA   0
+ *     08               TXADVA   0
+ *  07:06             TXAEMODE   0x0
+ *  05:00           TXAELENGTH   0x0
+ * 
+ */ +#define EM_BLE_TXAEHEADER_ADDR (0x00910006 + EM_BLE_TX_DESC_OFFSET) +#define EM_BLE_TXAEHEADER_INDEX 0x00000003 +#define EM_BLE_TXAEHEADER_RESET 0x00000000 + +__INLINE uint16_t em_ble_txaeheader_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_TXAEHEADER_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); +} + +__INLINE void em_ble_txaeheader_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_TXAEHEADER_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, value); +} + +// field definitions +#define EM_BLE_TXRSVD_BIT ((uint16_t)0x00008000) +#define EM_BLE_TXRSVD_POS 15 +#define EM_BLE_TXPOW_BIT ((uint16_t)0x00004000) +#define EM_BLE_TXPOW_POS 14 +#define EM_BLE_TXSYNC_BIT ((uint16_t)0x00002000) +#define EM_BLE_TXSYNC_POS 13 +#define EM_BLE_TXAUXPTR_BIT ((uint16_t)0x00001000) +#define EM_BLE_TXAUXPTR_POS 12 +#define EM_BLE_TXADI_BIT ((uint16_t)0x00000800) +#define EM_BLE_TXADI_POS 11 +#define EM_BLE_TXSUPP_BIT ((uint16_t)0x00000400) +#define EM_BLE_TXSUPP_POS 10 +#define EM_BLE_TXTGTA_BIT ((uint16_t)0x00000200) +#define EM_BLE_TXTGTA_POS 9 +#define EM_BLE_TXADVA_BIT ((uint16_t)0x00000100) +#define EM_BLE_TXADVA_POS 8 +#define EM_BLE_TXAEMODE_MASK ((uint16_t)0x000000C0) +#define EM_BLE_TXAEMODE_LSB 6 +#define EM_BLE_TXAEMODE_WIDTH ((uint16_t)0x00000002) +#define EM_BLE_TXAELENGTH_MASK ((uint16_t)0x0000003F) +#define EM_BLE_TXAELENGTH_LSB 0 +#define EM_BLE_TXAELENGTH_WIDTH ((uint16_t)0x00000006) + +#define EM_BLE_TXRSVD_RST 0x0 +#define EM_BLE_TXPOW_RST 0x0 +#define EM_BLE_TXSYNC_RST 0x0 +#define EM_BLE_TXAUXPTR_RST 0x0 +#define EM_BLE_TXADI_RST 0x0 +#define EM_BLE_TXSUPP_RST 0x0 +#define EM_BLE_TXTGTA_RST 0x0 +#define EM_BLE_TXADVA_RST 0x0 +#define EM_BLE_TXAEMODE_RST 0x0 +#define EM_BLE_TXAELENGTH_RST 0x0 + +__INLINE void em_ble_txaeheader_pack(int elt_idx, uint8_t txrsvd, uint8_t txpow, uint8_t txsync, uint8_t txauxptr, uint8_t txadi, uint8_t txsupp, uint8_t txtgta, uint8_t txadva, uint8_t txaemode, uint8_t txaelength) +{ + BLE_ASSERT_ERR((((uint16_t)txrsvd << 15) & ~((uint16_t)0x00008000)) == 0); + BLE_ASSERT_ERR((((uint16_t)txpow << 14) & ~((uint16_t)0x00004000)) == 0); + BLE_ASSERT_ERR((((uint16_t)txsync << 13) & ~((uint16_t)0x00002000)) == 0); + BLE_ASSERT_ERR((((uint16_t)txauxptr << 12) & ~((uint16_t)0x00001000)) == 0); + BLE_ASSERT_ERR((((uint16_t)txadi << 11) & ~((uint16_t)0x00000800)) == 0); + BLE_ASSERT_ERR((((uint16_t)txsupp << 10) & ~((uint16_t)0x00000400)) == 0); + BLE_ASSERT_ERR((((uint16_t)txtgta << 9) & ~((uint16_t)0x00000200)) == 0); + BLE_ASSERT_ERR((((uint16_t)txadva << 8) & ~((uint16_t)0x00000100)) == 0); + BLE_ASSERT_ERR((((uint16_t)txaemode << 6) & ~((uint16_t)0x000000C0)) == 0); + BLE_ASSERT_ERR((((uint16_t)txaelength << 0) & ~((uint16_t)0x0000003F)) == 0); + EM_BLE_WR(EM_BLE_TXAEHEADER_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, ((uint16_t)txrsvd << 15) | ((uint16_t)txpow << 14) | ((uint16_t)txsync << 13) | ((uint16_t)txauxptr << 12) | ((uint16_t)txadi << 11) | ((uint16_t)txsupp << 10) | ((uint16_t)txtgta << 9) | ((uint16_t)txadva << 8) | ((uint16_t)txaemode << 6) | ((uint16_t)txaelength << 0)); +} + +__INLINE void em_ble_txaeheader_unpack(int elt_idx, uint8_t* txrsvd, uint8_t* txpow, uint8_t* txsync, uint8_t* txauxptr, uint8_t* txadi, uint8_t* txsupp, uint8_t* txtgta, uint8_t* txadva, uint8_t* txaemode, uint8_t* txaelength) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXAEHEADER_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); + + *txrsvd = (localVal & ((uint16_t)0x00008000)) >> 15; + *txpow = (localVal & ((uint16_t)0x00004000)) >> 14; + *txsync = (localVal & ((uint16_t)0x00002000)) >> 13; + *txauxptr = (localVal & ((uint16_t)0x00001000)) >> 12; + *txadi = (localVal & ((uint16_t)0x00000800)) >> 11; + *txsupp = (localVal & ((uint16_t)0x00000400)) >> 10; + *txtgta = (localVal & ((uint16_t)0x00000200)) >> 9; + *txadva = (localVal & ((uint16_t)0x00000100)) >> 8; + *txaemode = (localVal & ((uint16_t)0x000000C0)) >> 6; + *txaelength = (localVal & ((uint16_t)0x0000003F)) >> 0; +} + +__INLINE uint8_t em_ble_txaeheader_txrsvd_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXAEHEADER_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00008000)) >> 15); +} + +__INLINE void em_ble_txaeheader_txrsvd_setf(int elt_idx, uint8_t txrsvd) +{ + BLE_ASSERT_ERR((((uint16_t)txrsvd << 15) & ~((uint16_t)0x00008000)) == 0); + EM_BLE_WR(EM_BLE_TXAEHEADER_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, (EM_BLE_RD(EM_BLE_TXAEHEADER_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE) & ~((uint16_t)0x00008000)) | ((uint16_t)txrsvd << 15)); +} + +__INLINE uint8_t em_ble_txaeheader_txpow_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXAEHEADER_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00004000)) >> 14); +} + +__INLINE void em_ble_txaeheader_txpow_setf(int elt_idx, uint8_t txpow) +{ + BLE_ASSERT_ERR((((uint16_t)txpow << 14) & ~((uint16_t)0x00004000)) == 0); + EM_BLE_WR(EM_BLE_TXAEHEADER_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, (EM_BLE_RD(EM_BLE_TXAEHEADER_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE) & ~((uint16_t)0x00004000)) | ((uint16_t)txpow << 14)); +} + +__INLINE uint8_t em_ble_txaeheader_txsync_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXAEHEADER_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00002000)) >> 13); +} + +__INLINE void em_ble_txaeheader_txsync_setf(int elt_idx, uint8_t txsync) +{ + BLE_ASSERT_ERR((((uint16_t)txsync << 13) & ~((uint16_t)0x00002000)) == 0); + EM_BLE_WR(EM_BLE_TXAEHEADER_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, (EM_BLE_RD(EM_BLE_TXAEHEADER_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE) & ~((uint16_t)0x00002000)) | ((uint16_t)txsync << 13)); +} + +__INLINE uint8_t em_ble_txaeheader_txauxptr_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXAEHEADER_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00001000)) >> 12); +} + +__INLINE void em_ble_txaeheader_txauxptr_setf(int elt_idx, uint8_t txauxptr) +{ + BLE_ASSERT_ERR((((uint16_t)txauxptr << 12) & ~((uint16_t)0x00001000)) == 0); + EM_BLE_WR(EM_BLE_TXAEHEADER_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, (EM_BLE_RD(EM_BLE_TXAEHEADER_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE) & ~((uint16_t)0x00001000)) | ((uint16_t)txauxptr << 12)); +} + +__INLINE uint8_t em_ble_txaeheader_txadi_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXAEHEADER_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000800)) >> 11); +} + +__INLINE void em_ble_txaeheader_txadi_setf(int elt_idx, uint8_t txadi) +{ + BLE_ASSERT_ERR((((uint16_t)txadi << 11) & ~((uint16_t)0x00000800)) == 0); + EM_BLE_WR(EM_BLE_TXAEHEADER_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, (EM_BLE_RD(EM_BLE_TXAEHEADER_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE) & ~((uint16_t)0x00000800)) | ((uint16_t)txadi << 11)); +} + +__INLINE uint8_t em_ble_txaeheader_txsupp_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXAEHEADER_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000400)) >> 10); +} + +__INLINE void em_ble_txaeheader_txsupp_setf(int elt_idx, uint8_t txsupp) +{ + BLE_ASSERT_ERR((((uint16_t)txsupp << 10) & ~((uint16_t)0x00000400)) == 0); + EM_BLE_WR(EM_BLE_TXAEHEADER_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, (EM_BLE_RD(EM_BLE_TXAEHEADER_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE) & ~((uint16_t)0x00000400)) | ((uint16_t)txsupp << 10)); +} + +__INLINE uint8_t em_ble_txaeheader_txtgta_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXAEHEADER_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000200)) >> 9); +} + +__INLINE void em_ble_txaeheader_txtgta_setf(int elt_idx, uint8_t txtgta) +{ + BLE_ASSERT_ERR((((uint16_t)txtgta << 9) & ~((uint16_t)0x00000200)) == 0); + EM_BLE_WR(EM_BLE_TXAEHEADER_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, (EM_BLE_RD(EM_BLE_TXAEHEADER_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE) & ~((uint16_t)0x00000200)) | ((uint16_t)txtgta << 9)); +} + +__INLINE uint8_t em_ble_txaeheader_txadva_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXAEHEADER_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000100)) >> 8); +} + +__INLINE void em_ble_txaeheader_txadva_setf(int elt_idx, uint8_t txadva) +{ + BLE_ASSERT_ERR((((uint16_t)txadva << 8) & ~((uint16_t)0x00000100)) == 0); + EM_BLE_WR(EM_BLE_TXAEHEADER_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, (EM_BLE_RD(EM_BLE_TXAEHEADER_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE) & ~((uint16_t)0x00000100)) | ((uint16_t)txadva << 8)); +} + +__INLINE uint8_t em_ble_txaeheader_txaemode_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXAEHEADER_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); + return ((localVal & ((uint16_t)0x000000C0)) >> 6); +} + +__INLINE void em_ble_txaeheader_txaemode_setf(int elt_idx, uint8_t txaemode) +{ + BLE_ASSERT_ERR((((uint16_t)txaemode << 6) & ~((uint16_t)0x000000C0)) == 0); + EM_BLE_WR(EM_BLE_TXAEHEADER_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, (EM_BLE_RD(EM_BLE_TXAEHEADER_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE) & ~((uint16_t)0x000000C0)) | ((uint16_t)txaemode << 6)); +} + +__INLINE uint8_t em_ble_txaeheader_txaelength_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXAEHEADER_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); + return ((localVal & ((uint16_t)0x0000003F)) >> 0); +} + +__INLINE void em_ble_txaeheader_txaelength_setf(int elt_idx, uint8_t txaelength) +{ + BLE_ASSERT_ERR((((uint16_t)txaelength << 0) & ~((uint16_t)0x0000003F)) == 0); + EM_BLE_WR(EM_BLE_TXAEHEADER_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, (EM_BLE_RD(EM_BLE_TXAEHEADER_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE) & ~((uint16_t)0x0000003F)) | ((uint16_t)txaelength << 0)); +} + +/** + * @brief TXAUXPTR0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:08      TXAUXOFFSET_LSB   0x0
+ *     07     TXAUXOFFSET_UNIT   0
+ *     06             TXAUX_CA   0
+ *  05:00             TX_LL_CH   0x0
+ * 
+ */ +#define EM_BLE_TXAUXPTR0_ADDR (0x00910008 + EM_BLE_TX_DESC_OFFSET) +#define EM_BLE_TXAUXPTR0_INDEX 0x00000004 +#define EM_BLE_TXAUXPTR0_RESET 0x00000000 + +__INLINE uint16_t em_ble_txauxptr0_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_TXAUXPTR0_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); +} + +__INLINE void em_ble_txauxptr0_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_TXAUXPTR0_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, value); +} + +// field definitions +#define EM_BLE_TXAUXOFFSET_LSB_MASK ((uint16_t)0x0000FF00) +#define EM_BLE_TXAUXOFFSET_LSB_LSB 8 +#define EM_BLE_TXAUXOFFSET_LSB_WIDTH ((uint16_t)0x00000008) +#define EM_BLE_TXAUXOFFSET_UNIT_BIT ((uint16_t)0x00000080) +#define EM_BLE_TXAUXOFFSET_UNIT_POS 7 +#define EM_BLE_TXAUX_CA_BIT ((uint16_t)0x00000040) +#define EM_BLE_TXAUX_CA_POS 6 +#define EM_BLE_TX_LL_CH_MASK ((uint16_t)0x0000003F) +#define EM_BLE_TX_LL_CH_LSB 0 +#define EM_BLE_TX_LL_CH_WIDTH ((uint16_t)0x00000006) + +#define EM_BLE_TXAUXOFFSET_LSB_RST 0x0 +#define EM_BLE_TXAUXOFFSET_UNIT_RST 0x0 +#define EM_BLE_TXAUX_CA_RST 0x0 +#define EM_BLE_TX_LL_CH_RST 0x0 + +__INLINE void em_ble_txauxptr0_pack(int elt_idx, uint8_t txauxoffsetlsb, uint8_t txauxoffsetunit, uint8_t txauxca, uint8_t txllch) +{ + BLE_ASSERT_ERR((((uint16_t)txauxoffsetlsb << 8) & ~((uint16_t)0x0000FF00)) == 0); + BLE_ASSERT_ERR((((uint16_t)txauxoffsetunit << 7) & ~((uint16_t)0x00000080)) == 0); + BLE_ASSERT_ERR((((uint16_t)txauxca << 6) & ~((uint16_t)0x00000040)) == 0); + BLE_ASSERT_ERR((((uint16_t)txllch << 0) & ~((uint16_t)0x0000003F)) == 0); + EM_BLE_WR(EM_BLE_TXAUXPTR0_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, ((uint16_t)txauxoffsetlsb << 8) | ((uint16_t)txauxoffsetunit << 7) | ((uint16_t)txauxca << 6) | ((uint16_t)txllch << 0)); +} + +__INLINE void em_ble_txauxptr0_unpack(int elt_idx, uint8_t* txauxoffsetlsb, uint8_t* txauxoffsetunit, uint8_t* txauxca, uint8_t* txllch) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXAUXPTR0_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); + + *txauxoffsetlsb = (localVal & ((uint16_t)0x0000FF00)) >> 8; + *txauxoffsetunit = (localVal & ((uint16_t)0x00000080)) >> 7; + *txauxca = (localVal & ((uint16_t)0x00000040)) >> 6; + *txllch = (localVal & ((uint16_t)0x0000003F)) >> 0; +} + +__INLINE uint8_t em_ble_txauxptr0_txauxoffset_lsb_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXAUXPTR0_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); + return ((localVal & ((uint16_t)0x0000FF00)) >> 8); +} + +__INLINE void em_ble_txauxptr0_txauxoffset_lsb_setf(int elt_idx, uint8_t txauxoffsetlsb) +{ + BLE_ASSERT_ERR((((uint16_t)txauxoffsetlsb << 8) & ~((uint16_t)0x0000FF00)) == 0); + EM_BLE_WR(EM_BLE_TXAUXPTR0_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, (EM_BLE_RD(EM_BLE_TXAUXPTR0_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE) & ~((uint16_t)0x0000FF00)) | ((uint16_t)txauxoffsetlsb << 8)); +} + +__INLINE uint8_t em_ble_txauxptr0_txauxoffset_unit_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXAUXPTR0_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000080)) >> 7); +} + +__INLINE void em_ble_txauxptr0_txauxoffset_unit_setf(int elt_idx, uint8_t txauxoffsetunit) +{ + BLE_ASSERT_ERR((((uint16_t)txauxoffsetunit << 7) & ~((uint16_t)0x00000080)) == 0); + EM_BLE_WR(EM_BLE_TXAUXPTR0_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, (EM_BLE_RD(EM_BLE_TXAUXPTR0_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE) & ~((uint16_t)0x00000080)) | ((uint16_t)txauxoffsetunit << 7)); +} + +__INLINE uint8_t em_ble_txauxptr0_txaux_ca_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXAUXPTR0_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000040)) >> 6); +} + +__INLINE void em_ble_txauxptr0_txaux_ca_setf(int elt_idx, uint8_t txauxca) +{ + BLE_ASSERT_ERR((((uint16_t)txauxca << 6) & ~((uint16_t)0x00000040)) == 0); + EM_BLE_WR(EM_BLE_TXAUXPTR0_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, (EM_BLE_RD(EM_BLE_TXAUXPTR0_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE) & ~((uint16_t)0x00000040)) | ((uint16_t)txauxca << 6)); +} + +__INLINE uint8_t em_ble_txauxptr0_tx_ll_ch_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXAUXPTR0_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); + return ((localVal & ((uint16_t)0x0000003F)) >> 0); +} + +__INLINE void em_ble_txauxptr0_tx_ll_ch_setf(int elt_idx, uint8_t txllch) +{ + BLE_ASSERT_ERR((((uint16_t)txllch << 0) & ~((uint16_t)0x0000003F)) == 0); + EM_BLE_WR(EM_BLE_TXAUXPTR0_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, (EM_BLE_RD(EM_BLE_TXAUXPTR0_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE) & ~((uint16_t)0x0000003F)) | ((uint16_t)txllch << 0)); +} + +/** + * @brief TXAUXPTR1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  07:05            TXAUX_PHY   0x0
+ *  04:00      TXAUXOFFSET_MSB   0x0
+ * 
+ */ +#define EM_BLE_TXAUXPTR1_ADDR (0x0091000A + EM_BLE_TX_DESC_OFFSET) +#define EM_BLE_TXAUXPTR1_INDEX 0x00000005 +#define EM_BLE_TXAUXPTR1_RESET 0x00000000 + +__INLINE uint16_t em_ble_txauxptr1_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_TXAUXPTR1_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); +} + +__INLINE void em_ble_txauxptr1_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_TXAUXPTR1_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, value); +} + +// field definitions +#define EM_BLE_TXAUX_PHY_MASK ((uint16_t)0x000000E0) +#define EM_BLE_TXAUX_PHY_LSB 5 +#define EM_BLE_TXAUX_PHY_WIDTH ((uint16_t)0x00000003) +#define EM_BLE_TXAUXOFFSET_MSB_MASK ((uint16_t)0x0000001F) +#define EM_BLE_TXAUXOFFSET_MSB_LSB 0 +#define EM_BLE_TXAUXOFFSET_MSB_WIDTH ((uint16_t)0x00000005) + +#define EM_BLE_TXAUX_PHY_RST 0x0 +#define EM_BLE_TXAUXOFFSET_MSB_RST 0x0 + +__INLINE void em_ble_txauxptr1_pack(int elt_idx, uint8_t txauxphy, uint8_t txauxoffsetmsb) +{ + BLE_ASSERT_ERR((((uint16_t)txauxphy << 5) & ~((uint16_t)0x000000E0)) == 0); + BLE_ASSERT_ERR((((uint16_t)txauxoffsetmsb << 0) & ~((uint16_t)0x0000001F)) == 0); + EM_BLE_WR(EM_BLE_TXAUXPTR1_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, ((uint16_t)txauxphy << 5) | ((uint16_t)txauxoffsetmsb << 0)); +} + +__INLINE void em_ble_txauxptr1_unpack(int elt_idx, uint8_t* txauxphy, uint8_t* txauxoffsetmsb) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXAUXPTR1_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); + + *txauxphy = (localVal & ((uint16_t)0x000000E0)) >> 5; + *txauxoffsetmsb = (localVal & ((uint16_t)0x0000001F)) >> 0; +} + +__INLINE uint8_t em_ble_txauxptr1_txaux_phy_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXAUXPTR1_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); + return ((localVal & ((uint16_t)0x000000E0)) >> 5); +} + +__INLINE void em_ble_txauxptr1_txaux_phy_setf(int elt_idx, uint8_t txauxphy) +{ + BLE_ASSERT_ERR((((uint16_t)txauxphy << 5) & ~((uint16_t)0x000000E0)) == 0); + EM_BLE_WR(EM_BLE_TXAUXPTR1_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, (EM_BLE_RD(EM_BLE_TXAUXPTR1_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE) & ~((uint16_t)0x000000E0)) | ((uint16_t)txauxphy << 5)); +} + +__INLINE uint8_t em_ble_txauxptr1_txauxoffset_msb_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXAUXPTR1_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); + return ((localVal & ((uint16_t)0x0000001F)) >> 0); +} + +__INLINE void em_ble_txauxptr1_txauxoffset_msb_setf(int elt_idx, uint8_t txauxoffsetmsb) +{ + BLE_ASSERT_ERR((((uint16_t)txauxoffsetmsb << 0) & ~((uint16_t)0x0000001F)) == 0); + EM_BLE_WR(EM_BLE_TXAUXPTR1_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, (EM_BLE_RD(EM_BLE_TXAUXPTR1_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE) & ~((uint16_t)0x0000001F)) | ((uint16_t)txauxoffsetmsb << 0)); +} + +/** + * @brief TXAEDATAPTR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00          TXAEDATAPTR   0x0
+ * 
+ */ +#define EM_BLE_TXAEDATAPTR_ADDR (0x0091000C + EM_BLE_TX_DESC_OFFSET) +#define EM_BLE_TXAEDATAPTR_INDEX 0x00000006 +#define EM_BLE_TXAEDATAPTR_RESET 0x00000000 + +__INLINE uint16_t em_ble_txaedataptr_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_TXAEDATAPTR_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); +} + +__INLINE void em_ble_txaedataptr_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_TXAEDATAPTR_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, value); +} + +// field definitions +#define EM_BLE_TXAEDATAPTR_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_TXAEDATAPTR_LSB 0 +#define EM_BLE_TXAEDATAPTR_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_TXAEDATAPTR_RST 0x0 + +__INLINE uint16_t em_ble_txaedataptr_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXAEDATAPTR_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_txaedataptr_setf(int elt_idx, uint16_t txaedataptr) +{ + BLE_ASSERT_ERR((((uint16_t)txaedataptr << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_TXAEDATAPTR_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, (uint16_t)txaedataptr << 0); +} + +/** + * @brief TXPHCTE register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  07:06            TXCTETYPE   0x0
+ *     05             TXCTERFU   0
+ *  04:00            TXCTETIME   0x0
+ * 
+ */ +#define EM_BLE_TXPHCTE_ADDR (0x0091000E + EM_BLE_TX_DESC_OFFSET) +#define EM_BLE_TXPHCTE_INDEX 0x00000007 +#define EM_BLE_TXPHCTE_RESET 0x00000000 + +__INLINE uint16_t em_ble_txphcte_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_TXPHCTE_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); +} + +__INLINE void em_ble_txphcte_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_TXPHCTE_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, value); +} + +// field definitions +#define EM_BLE_TXCTETYPE_MASK ((uint16_t)0x000000C0) +#define EM_BLE_TXCTETYPE_LSB 6 +#define EM_BLE_TXCTETYPE_WIDTH ((uint16_t)0x00000002) +#define EM_BLE_TXCTERFU_BIT ((uint16_t)0x00000020) +#define EM_BLE_TXCTERFU_POS 5 +#define EM_BLE_TXCTETIME_MASK ((uint16_t)0x0000001F) +#define EM_BLE_TXCTETIME_LSB 0 +#define EM_BLE_TXCTETIME_WIDTH ((uint16_t)0x00000005) + +#define EM_BLE_TXCTETYPE_RST 0x0 +#define EM_BLE_TXCTERFU_RST 0x0 +#define EM_BLE_TXCTETIME_RST 0x0 + +__INLINE void em_ble_txphcte_pack(int elt_idx, uint8_t txctetype, uint8_t txcterfu, uint8_t txctetime) +{ + BLE_ASSERT_ERR((((uint16_t)txctetype << 6) & ~((uint16_t)0x000000C0)) == 0); + BLE_ASSERT_ERR((((uint16_t)txcterfu << 5) & ~((uint16_t)0x00000020)) == 0); + BLE_ASSERT_ERR((((uint16_t)txctetime << 0) & ~((uint16_t)0x0000001F)) == 0); + EM_BLE_WR(EM_BLE_TXPHCTE_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, ((uint16_t)txctetype << 6) | ((uint16_t)txcterfu << 5) | ((uint16_t)txctetime << 0)); +} + +__INLINE void em_ble_txphcte_unpack(int elt_idx, uint8_t* txctetype, uint8_t* txcterfu, uint8_t* txctetime) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXPHCTE_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); + + *txctetype = (localVal & ((uint16_t)0x000000C0)) >> 6; + *txcterfu = (localVal & ((uint16_t)0x00000020)) >> 5; + *txctetime = (localVal & ((uint16_t)0x0000001F)) >> 0; +} + +__INLINE uint8_t em_ble_txphcte_txctetype_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXPHCTE_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); + return ((localVal & ((uint16_t)0x000000C0)) >> 6); +} + +__INLINE void em_ble_txphcte_txctetype_setf(int elt_idx, uint8_t txctetype) +{ + BLE_ASSERT_ERR((((uint16_t)txctetype << 6) & ~((uint16_t)0x000000C0)) == 0); + EM_BLE_WR(EM_BLE_TXPHCTE_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, (EM_BLE_RD(EM_BLE_TXPHCTE_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE) & ~((uint16_t)0x000000C0)) | ((uint16_t)txctetype << 6)); +} + +__INLINE uint8_t em_ble_txphcte_txcterfu_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXPHCTE_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000020)) >> 5); +} + +__INLINE void em_ble_txphcte_txcterfu_setf(int elt_idx, uint8_t txcterfu) +{ + BLE_ASSERT_ERR((((uint16_t)txcterfu << 5) & ~((uint16_t)0x00000020)) == 0); + EM_BLE_WR(EM_BLE_TXPHCTE_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, (EM_BLE_RD(EM_BLE_TXPHCTE_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE) & ~((uint16_t)0x00000020)) | ((uint16_t)txcterfu << 5)); +} + +__INLINE uint8_t em_ble_txphcte_txctetime_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXPHCTE_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE); + return ((localVal & ((uint16_t)0x0000001F)) >> 0); +} + +__INLINE void em_ble_txphcte_txctetime_setf(int elt_idx, uint8_t txctetime) +{ + BLE_ASSERT_ERR((((uint16_t)txctetime << 0) & ~((uint16_t)0x0000001F)) == 0); + EM_BLE_WR(EM_BLE_TXPHCTE_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE, (EM_BLE_RD(EM_BLE_TXPHCTE_ADDR + elt_idx * REG_EM_BLE_TX_DESC_SIZE) & ~((uint16_t)0x0000001F)) | ((uint16_t)txctetime << 0)); +} + + +#endif // _REG_EM_BLE_TX_DESC_H_ + diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_em_ble_tx_iso_buf.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_em_ble_tx_iso_buf.h new file mode 100755 index 0000000..96cdac0 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_em_ble_tx_iso_buf.h @@ -0,0 +1,138 @@ +#ifndef _REG_EM_BLE_TX_ISO_BUF_H_ +#define _REG_EM_BLE_TX_ISO_BUF_H_ + +#include +#include "_reg_em_ble_tx_iso_buf.h" +#include "compiler.h" +#include "architect.h" +#include "em_map.h" +#include "ble_reg_access.h" + +#define REG_EM_BLE_TX_ISO_BUF_COUNT 2 + +#define REG_EM_BLE_TX_ISO_BUF_DECODING_MASK 0x00000003 + +#define REG_EM_BLE_TX_ISO_BUF_ADDR_GET(idx) (EM_BLE_TX_ISO_BUF_OFFSET + (idx) * REG_EM_BLE_TX_ISO_BUF_SIZE) + +/** + * @brief TXISOBUFSETUP register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     08            TXISOMUTE   0
+ *  07:00          TXISOLENGTH   0x0
+ * 
+ */ +#define EM_BLE_TXISOBUFSETUP_ADDR (0x00910000 + EM_BLE_TX_ISO_BUF_OFFSET) +#define EM_BLE_TXISOBUFSETUP_INDEX 0x00000000 +#define EM_BLE_TXISOBUFSETUP_RESET 0x00000000 + +__INLINE uint16_t em_ble_txisobufsetup_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_TXISOBUFSETUP_ADDR + elt_idx * REG_EM_BLE_TX_ISO_BUF_SIZE); +} + +__INLINE void em_ble_txisobufsetup_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_TXISOBUFSETUP_ADDR + elt_idx * REG_EM_BLE_TX_ISO_BUF_SIZE, value); +} + +// field definitions +#define EM_BLE_TXISOMUTE_BIT ((uint16_t)0x00000100) +#define EM_BLE_TXISOMUTE_POS 8 +#define EM_BLE_TXISOLENGTH_MASK ((uint16_t)0x000000FF) +#define EM_BLE_TXISOLENGTH_LSB 0 +#define EM_BLE_TXISOLENGTH_WIDTH ((uint16_t)0x00000008) + +#define EM_BLE_TXISOMUTE_RST 0x0 +#define EM_BLE_TXISOLENGTH_RST 0x0 + +__INLINE void em_ble_txisobufsetup_pack(int elt_idx, uint8_t txisomute, uint8_t txisolength) +{ + BLE_ASSERT_ERR((((uint16_t)txisomute << 8) & ~((uint16_t)0x00000100)) == 0); + BLE_ASSERT_ERR((((uint16_t)txisolength << 0) & ~((uint16_t)0x000000FF)) == 0); + EM_BLE_WR(EM_BLE_TXISOBUFSETUP_ADDR + elt_idx * REG_EM_BLE_TX_ISO_BUF_SIZE, ((uint16_t)txisomute << 8) | ((uint16_t)txisolength << 0)); +} + +__INLINE void em_ble_txisobufsetup_unpack(int elt_idx, uint8_t* txisomute, uint8_t* txisolength) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXISOBUFSETUP_ADDR + elt_idx * REG_EM_BLE_TX_ISO_BUF_SIZE); + + *txisomute = (localVal & ((uint16_t)0x00000100)) >> 8; + *txisolength = (localVal & ((uint16_t)0x000000FF)) >> 0; +} + +__INLINE uint8_t em_ble_txisobufsetup_txisomute_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXISOBUFSETUP_ADDR + elt_idx * REG_EM_BLE_TX_ISO_BUF_SIZE); + return ((localVal & ((uint16_t)0x00000100)) >> 8); +} + +__INLINE void em_ble_txisobufsetup_txisomute_setf(int elt_idx, uint8_t txisomute) +{ + BLE_ASSERT_ERR((((uint16_t)txisomute << 8) & ~((uint16_t)0x00000100)) == 0); + EM_BLE_WR(EM_BLE_TXISOBUFSETUP_ADDR + elt_idx * REG_EM_BLE_TX_ISO_BUF_SIZE, (EM_BLE_RD(EM_BLE_TXISOBUFSETUP_ADDR + elt_idx * REG_EM_BLE_TX_ISO_BUF_SIZE) & ~((uint16_t)0x00000100)) | ((uint16_t)txisomute << 8)); +} + +__INLINE uint8_t em_ble_txisobufsetup_txisolength_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXISOBUFSETUP_ADDR + elt_idx * REG_EM_BLE_TX_ISO_BUF_SIZE); + return ((localVal & ((uint16_t)0x000000FF)) >> 0); +} + +__INLINE void em_ble_txisobufsetup_txisolength_setf(int elt_idx, uint8_t txisolength) +{ + BLE_ASSERT_ERR((((uint16_t)txisolength << 0) & ~((uint16_t)0x000000FF)) == 0); + EM_BLE_WR(EM_BLE_TXISOBUFSETUP_ADDR + elt_idx * REG_EM_BLE_TX_ISO_BUF_SIZE, (EM_BLE_RD(EM_BLE_TXISOBUFSETUP_ADDR + elt_idx * REG_EM_BLE_TX_ISO_BUF_SIZE) & ~((uint16_t)0x000000FF)) | ((uint16_t)txisolength << 0)); +} + +/** + * @brief TXISODATABUF register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00         TXISODATABUF   0x0
+ * 
+ */ +#define EM_BLE_TXISODATABUF_ADDR (0x00910002 + EM_BLE_TX_ISO_BUF_OFFSET) +#define EM_BLE_TXISODATABUF_INDEX 0x00000001 +#define EM_BLE_TXISODATABUF_RESET 0x00000000 +#define EM_BLE_TXISODATABUF_COUNT 33 + +__INLINE uint16_t em_ble_txisodatabuf_get(int elt_idx, int reg_idx) +{ + BLE_ASSERT_ERR(reg_idx <= 32); + return EM_BLE_RD(EM_BLE_TXISODATABUF_ADDR + elt_idx * REG_EM_BLE_TX_ISO_BUF_SIZE + reg_idx * 2); +} + +__INLINE void em_ble_txisodatabuf_set(int elt_idx, int reg_idx, uint16_t value) +{ + BLE_ASSERT_ERR(reg_idx <= 32); + EM_BLE_WR(EM_BLE_TXISODATABUF_ADDR + elt_idx * REG_EM_BLE_TX_ISO_BUF_SIZE + reg_idx * 2, value); +} + +// field definitions +#define EM_BLE_TXISODATABUF_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_TXISODATABUF_LSB 0 +#define EM_BLE_TXISODATABUF_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_TXISODATABUF_RST 0x0 + +__INLINE uint16_t em_ble_txisodatabuf_getf(int elt_idx, int reg_idx) +{ + BLE_ASSERT_ERR(reg_idx <= 32); + uint16_t localVal = EM_BLE_RD(EM_BLE_TXISODATABUF_ADDR + elt_idx * REG_EM_BLE_TX_ISO_BUF_SIZE + reg_idx * 2); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_txisodatabuf_setf(int elt_idx, int reg_idx, uint16_t txisodatabuf) +{ + BLE_ASSERT_ERR(reg_idx <= 32); + BLE_ASSERT_ERR((((uint16_t)txisodatabuf << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_TXISODATABUF_ADDR + elt_idx * REG_EM_BLE_TX_ISO_BUF_SIZE + reg_idx * 2, (uint16_t)txisodatabuf << 0); +} + + +#endif // _REG_EM_BLE_TX_ISO_BUF_H_ + diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_em_ble_tx_iso_desc.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_em_ble_tx_iso_desc.h new file mode 100755 index 0000000..4191610 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_em_ble_tx_iso_desc.h @@ -0,0 +1,417 @@ +#ifndef _REG_EM_BLE_TX_ISO_DESC_H_ +#define _REG_EM_BLE_TX_ISO_DESC_H_ + +#include +#include "_reg_em_ble_tx_iso_desc.h" +#include "compiler.h" +#include "architect.h" +#include "em_map.h" +#include "ble_reg_access.h" + +#define REG_EM_BLE_TX_ISO_DESC_COUNT 6 + +#define REG_EM_BLE_TX_ISO_DESC_DECODING_MASK 0x0000000F + +#define REG_EM_BLE_TX_ISO_DESC_ADDR_GET(idx) (EM_BLE_TX_ISO_DESC_OFFSET + (idx) * REG_EM_BLE_TX_ISO_DESC_SIZE) + +/** + * @brief TXISOPTR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     15               TXDONE   0
+ *  13:00             NEXT_PTR   0x0
+ * 
+ */ +#define EM_BLE_TXISOPTR_ADDR (0x00910000 + EM_BLE_TX_ISO_DESC_OFFSET) +#define EM_BLE_TXISOPTR_INDEX 0x00000000 +#define EM_BLE_TXISOPTR_RESET 0x00000000 + +__INLINE uint16_t em_ble_txisoptr_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_TXISOPTR_ADDR + elt_idx * REG_EM_BLE_TX_ISO_DESC_SIZE); +} + +__INLINE void em_ble_txisoptr_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_TXISOPTR_ADDR + elt_idx * REG_EM_BLE_TX_ISO_DESC_SIZE, value); +} + +// field definitions +#define EM_BLE_TXDONE_BIT ((uint16_t)0x00008000) +#define EM_BLE_TXDONE_POS 15 +#define EM_BLE_NEXT_PTR_MASK ((uint16_t)0x00003FFF) +#define EM_BLE_NEXT_PTR_LSB 0 +#define EM_BLE_NEXT_PTR_WIDTH ((uint16_t)0x0000000E) + +#define EM_BLE_TXDONE_RST 0x0 +#define EM_BLE_NEXT_PTR_RST 0x0 + +__INLINE void em_ble_txisoptr_pack(int elt_idx, uint8_t txdone, uint16_t nextptr) +{ + BLE_ASSERT_ERR((((uint16_t)txdone << 15) & ~((uint16_t)0x00008000)) == 0); + BLE_ASSERT_ERR((((uint16_t)nextptr << 0) & ~((uint16_t)0x00003FFF)) == 0); + EM_BLE_WR(EM_BLE_TXISOPTR_ADDR + elt_idx * REG_EM_BLE_TX_ISO_DESC_SIZE, ((uint16_t)txdone << 15) | ((uint16_t)nextptr << 0)); +} + +__INLINE void em_ble_txisoptr_unpack(int elt_idx, uint8_t* txdone, uint16_t* nextptr) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXISOPTR_ADDR + elt_idx * REG_EM_BLE_TX_ISO_DESC_SIZE); + + *txdone = (localVal & ((uint16_t)0x00008000)) >> 15; + *nextptr = (localVal & ((uint16_t)0x00003FFF)) >> 0; +} + +__INLINE uint8_t em_ble_txisoptr_txdone_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXISOPTR_ADDR + elt_idx * REG_EM_BLE_TX_ISO_DESC_SIZE); + return ((localVal & ((uint16_t)0x00008000)) >> 15); +} + +__INLINE void em_ble_txisoptr_txdone_setf(int elt_idx, uint8_t txdone) +{ + BLE_ASSERT_ERR((((uint16_t)txdone << 15) & ~((uint16_t)0x00008000)) == 0); + EM_BLE_WR(EM_BLE_TXISOPTR_ADDR + elt_idx * REG_EM_BLE_TX_ISO_DESC_SIZE, (EM_BLE_RD(EM_BLE_TXISOPTR_ADDR + elt_idx * REG_EM_BLE_TX_ISO_DESC_SIZE) & ~((uint16_t)0x00008000)) | ((uint16_t)txdone << 15)); +} + +__INLINE uint16_t em_ble_txisoptr_next_ptr_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXISOPTR_ADDR + elt_idx * REG_EM_BLE_TX_ISO_DESC_SIZE); + return ((localVal & ((uint16_t)0x00003FFF)) >> 0); +} + +__INLINE void em_ble_txisoptr_next_ptr_setf(int elt_idx, uint16_t nextptr) +{ + BLE_ASSERT_ERR((((uint16_t)nextptr << 0) & ~((uint16_t)0x00003FFF)) == 0); + EM_BLE_WR(EM_BLE_TXISOPTR_ADDR + elt_idx * REG_EM_BLE_TX_ISO_DESC_SIZE, (EM_BLE_RD(EM_BLE_TXISOPTR_ADDR + elt_idx * REG_EM_BLE_TX_ISO_DESC_SIZE) & ~((uint16_t)0x00003FFF)) | ((uint16_t)nextptr << 0)); +} + +/** + * @brief TXISOCNT0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00           TXPLD_CNT0   0x0
+ * 
+ */ +#define EM_BLE_TXISOCNT0_ADDR (0x00910002 + EM_BLE_TX_ISO_DESC_OFFSET) +#define EM_BLE_TXISOCNT0_INDEX 0x00000001 +#define EM_BLE_TXISOCNT0_RESET 0x00000000 + +__INLINE uint16_t em_ble_txisocnt0_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_TXISOCNT0_ADDR + elt_idx * REG_EM_BLE_TX_ISO_DESC_SIZE); +} + +__INLINE void em_ble_txisocnt0_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_TXISOCNT0_ADDR + elt_idx * REG_EM_BLE_TX_ISO_DESC_SIZE, value); +} + +// field definitions +#define EM_BLE_TXPLD_CNT0_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_TXPLD_CNT0_LSB 0 +#define EM_BLE_TXPLD_CNT0_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_TXPLD_CNT0_RST 0x0 + +__INLINE uint16_t em_ble_txisocnt0_txpld_cnt0_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXISOCNT0_ADDR + elt_idx * REG_EM_BLE_TX_ISO_DESC_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_txisocnt0_txpld_cnt0_setf(int elt_idx, uint16_t txpldcnt0) +{ + BLE_ASSERT_ERR((((uint16_t)txpldcnt0 << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_TXISOCNT0_ADDR + elt_idx * REG_EM_BLE_TX_ISO_DESC_SIZE, (uint16_t)txpldcnt0 << 0); +} + +/** + * @brief TXISOCNT1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00           TXPLD_CNT1   0x0
+ * 
+ */ +#define EM_BLE_TXISOCNT1_ADDR (0x00910004 + EM_BLE_TX_ISO_DESC_OFFSET) +#define EM_BLE_TXISOCNT1_INDEX 0x00000002 +#define EM_BLE_TXISOCNT1_RESET 0x00000000 + +__INLINE uint16_t em_ble_txisocnt1_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_TXISOCNT1_ADDR + elt_idx * REG_EM_BLE_TX_ISO_DESC_SIZE); +} + +__INLINE void em_ble_txisocnt1_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_TXISOCNT1_ADDR + elt_idx * REG_EM_BLE_TX_ISO_DESC_SIZE, value); +} + +// field definitions +#define EM_BLE_TXPLD_CNT1_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_TXPLD_CNT1_LSB 0 +#define EM_BLE_TXPLD_CNT1_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_TXPLD_CNT1_RST 0x0 + +__INLINE uint16_t em_ble_txisocnt1_txpld_cnt1_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXISOCNT1_ADDR + elt_idx * REG_EM_BLE_TX_ISO_DESC_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_txisocnt1_txpld_cnt1_setf(int elt_idx, uint16_t txpldcnt1) +{ + BLE_ASSERT_ERR((((uint16_t)txpldcnt1 << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_TXISOCNT1_ADDR + elt_idx * REG_EM_BLE_TX_ISO_DESC_SIZE, (uint16_t)txpldcnt1 << 0); +} + +/** + * @brief TXISOCNT2 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:08       TXFLUSHINSTANT   0x0
+ *  06:00            TXISOCNT2   0x0
+ * 
+ */ +#define EM_BLE_TXISOCNT2_ADDR (0x00910006 + EM_BLE_TX_ISO_DESC_OFFSET) +#define EM_BLE_TXISOCNT2_INDEX 0x00000003 +#define EM_BLE_TXISOCNT2_RESET 0x00000000 + +__INLINE uint16_t em_ble_txisocnt2_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_TXISOCNT2_ADDR + elt_idx * REG_EM_BLE_TX_ISO_DESC_SIZE); +} + +__INLINE void em_ble_txisocnt2_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_TXISOCNT2_ADDR + elt_idx * REG_EM_BLE_TX_ISO_DESC_SIZE, value); +} + +// field definitions +#define EM_BLE_TXFLUSHINSTANT_MASK ((uint16_t)0x0000FF00) +#define EM_BLE_TXFLUSHINSTANT_LSB 8 +#define EM_BLE_TXFLUSHINSTANT_WIDTH ((uint16_t)0x00000008) +#define EM_BLE_TXISOCNT2_MASK ((uint16_t)0x0000007F) +#define EM_BLE_TXISOCNT2_LSB 0 +#define EM_BLE_TXISOCNT2_WIDTH ((uint16_t)0x00000007) + +#define EM_BLE_TXFLUSHINSTANT_RST 0x0 +#define EM_BLE_TXISOCNT2_RST 0x0 + +__INLINE void em_ble_txisocnt2_pack(int elt_idx, uint8_t txflushinstant, uint8_t txisocnt2) +{ + BLE_ASSERT_ERR((((uint16_t)txflushinstant << 8) & ~((uint16_t)0x0000FF00)) == 0); + BLE_ASSERT_ERR((((uint16_t)txisocnt2 << 0) & ~((uint16_t)0x0000007F)) == 0); + EM_BLE_WR(EM_BLE_TXISOCNT2_ADDR + elt_idx * REG_EM_BLE_TX_ISO_DESC_SIZE, ((uint16_t)txflushinstant << 8) | ((uint16_t)txisocnt2 << 0)); +} + +__INLINE void em_ble_txisocnt2_unpack(int elt_idx, uint8_t* txflushinstant, uint8_t* txisocnt2) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXISOCNT2_ADDR + elt_idx * REG_EM_BLE_TX_ISO_DESC_SIZE); + + *txflushinstant = (localVal & ((uint16_t)0x0000FF00)) >> 8; + *txisocnt2 = (localVal & ((uint16_t)0x0000007F)) >> 0; +} + +__INLINE uint8_t em_ble_txisocnt2_txflushinstant_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXISOCNT2_ADDR + elt_idx * REG_EM_BLE_TX_ISO_DESC_SIZE); + return ((localVal & ((uint16_t)0x0000FF00)) >> 8); +} + +__INLINE void em_ble_txisocnt2_txflushinstant_setf(int elt_idx, uint8_t txflushinstant) +{ + BLE_ASSERT_ERR((((uint16_t)txflushinstant << 8) & ~((uint16_t)0x0000FF00)) == 0); + EM_BLE_WR(EM_BLE_TXISOCNT2_ADDR + elt_idx * REG_EM_BLE_TX_ISO_DESC_SIZE, (EM_BLE_RD(EM_BLE_TXISOCNT2_ADDR + elt_idx * REG_EM_BLE_TX_ISO_DESC_SIZE) & ~((uint16_t)0x0000FF00)) | ((uint16_t)txflushinstant << 8)); +} + +__INLINE uint8_t em_ble_txisocnt2_txisocnt2_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXISOCNT2_ADDR + elt_idx * REG_EM_BLE_TX_ISO_DESC_SIZE); + return ((localVal & ((uint16_t)0x0000007F)) >> 0); +} + +__INLINE void em_ble_txisocnt2_txisocnt2_setf(int elt_idx, uint8_t txisocnt2) +{ + BLE_ASSERT_ERR((((uint16_t)txisocnt2 << 0) & ~((uint16_t)0x0000007F)) == 0); + EM_BLE_WR(EM_BLE_TXISOCNT2_ADDR + elt_idx * REG_EM_BLE_TX_ISO_DESC_SIZE, (EM_BLE_RD(EM_BLE_TXISOCNT2_ADDR + elt_idx * REG_EM_BLE_TX_ISO_DESC_SIZE) & ~((uint16_t)0x0000007F)) | ((uint16_t)txisocnt2 << 0)); +} + +/** + * @brief TXISOPHM0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  07:05           TXISOM0RFU   0x0
+ *     04                 TXMD   0
+ *     03                 TXSN   0
+ *     02               TXNESN   0
+ *  01:00               TXLLID   0x0
+ * 
+ */ +#define EM_BLE_TXISOPHM0_ADDR (0x00910008 + EM_BLE_TX_ISO_DESC_OFFSET) +#define EM_BLE_TXISOPHM0_INDEX 0x00000004 +#define EM_BLE_TXISOPHM0_RESET 0x00000000 + +__INLINE uint16_t em_ble_txisophm0_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_TXISOPHM0_ADDR + elt_idx * REG_EM_BLE_TX_ISO_DESC_SIZE); +} + +__INLINE void em_ble_txisophm0_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_TXISOPHM0_ADDR + elt_idx * REG_EM_BLE_TX_ISO_DESC_SIZE, value); +} + +// field definitions +#define EM_BLE_TXISOM0RFU_MASK ((uint16_t)0x000000E0) +#define EM_BLE_TXISOM0RFU_LSB 5 +#define EM_BLE_TXISOM0RFU_WIDTH ((uint16_t)0x00000003) +#define EM_BLE_TXMD_BIT ((uint16_t)0x00000010) +#define EM_BLE_TXMD_POS 4 +#define EM_BLE_TXSN_BIT ((uint16_t)0x00000008) +#define EM_BLE_TXSN_POS 3 +#define EM_BLE_TXNESN_BIT ((uint16_t)0x00000004) +#define EM_BLE_TXNESN_POS 2 +#define EM_BLE_TXLLID_MASK ((uint16_t)0x00000003) +#define EM_BLE_TXLLID_LSB 0 +#define EM_BLE_TXLLID_WIDTH ((uint16_t)0x00000002) + +#define EM_BLE_TXISOM0RFU_RST 0x0 +#define EM_BLE_TXMD_RST 0x0 +#define EM_BLE_TXSN_RST 0x0 +#define EM_BLE_TXNESN_RST 0x0 +#define EM_BLE_TXLLID_RST 0x0 + +__INLINE void em_ble_txisophm0_pack(int elt_idx, uint8_t txisom0rfu, uint8_t txmd, uint8_t txsn, uint8_t txnesn, uint8_t txllid) +{ + BLE_ASSERT_ERR((((uint16_t)txisom0rfu << 5) & ~((uint16_t)0x000000E0)) == 0); + BLE_ASSERT_ERR((((uint16_t)txmd << 4) & ~((uint16_t)0x00000010)) == 0); + BLE_ASSERT_ERR((((uint16_t)txsn << 3) & ~((uint16_t)0x00000008)) == 0); + BLE_ASSERT_ERR((((uint16_t)txnesn << 2) & ~((uint16_t)0x00000004)) == 0); + BLE_ASSERT_ERR((((uint16_t)txllid << 0) & ~((uint16_t)0x00000003)) == 0); + EM_BLE_WR(EM_BLE_TXISOPHM0_ADDR + elt_idx * REG_EM_BLE_TX_ISO_DESC_SIZE, ((uint16_t)txisom0rfu << 5) | ((uint16_t)txmd << 4) | ((uint16_t)txsn << 3) | ((uint16_t)txnesn << 2) | ((uint16_t)txllid << 0)); +} + +__INLINE void em_ble_txisophm0_unpack(int elt_idx, uint8_t* txisom0rfu, uint8_t* txmd, uint8_t* txsn, uint8_t* txnesn, uint8_t* txllid) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXISOPHM0_ADDR + elt_idx * REG_EM_BLE_TX_ISO_DESC_SIZE); + + *txisom0rfu = (localVal & ((uint16_t)0x000000E0)) >> 5; + *txmd = (localVal & ((uint16_t)0x00000010)) >> 4; + *txsn = (localVal & ((uint16_t)0x00000008)) >> 3; + *txnesn = (localVal & ((uint16_t)0x00000004)) >> 2; + *txllid = (localVal & ((uint16_t)0x00000003)) >> 0; +} + +__INLINE uint8_t em_ble_txisophm0_txisom0rfu_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXISOPHM0_ADDR + elt_idx * REG_EM_BLE_TX_ISO_DESC_SIZE); + return ((localVal & ((uint16_t)0x000000E0)) >> 5); +} + +__INLINE void em_ble_txisophm0_txisom0rfu_setf(int elt_idx, uint8_t txisom0rfu) +{ + BLE_ASSERT_ERR((((uint16_t)txisom0rfu << 5) & ~((uint16_t)0x000000E0)) == 0); + EM_BLE_WR(EM_BLE_TXISOPHM0_ADDR + elt_idx * REG_EM_BLE_TX_ISO_DESC_SIZE, (EM_BLE_RD(EM_BLE_TXISOPHM0_ADDR + elt_idx * REG_EM_BLE_TX_ISO_DESC_SIZE) & ~((uint16_t)0x000000E0)) | ((uint16_t)txisom0rfu << 5)); +} + +__INLINE uint8_t em_ble_txisophm0_txmd_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXISOPHM0_ADDR + elt_idx * REG_EM_BLE_TX_ISO_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000010)) >> 4); +} + +__INLINE void em_ble_txisophm0_txmd_setf(int elt_idx, uint8_t txmd) +{ + BLE_ASSERT_ERR((((uint16_t)txmd << 4) & ~((uint16_t)0x00000010)) == 0); + EM_BLE_WR(EM_BLE_TXISOPHM0_ADDR + elt_idx * REG_EM_BLE_TX_ISO_DESC_SIZE, (EM_BLE_RD(EM_BLE_TXISOPHM0_ADDR + elt_idx * REG_EM_BLE_TX_ISO_DESC_SIZE) & ~((uint16_t)0x00000010)) | ((uint16_t)txmd << 4)); +} + +__INLINE uint8_t em_ble_txisophm0_txsn_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXISOPHM0_ADDR + elt_idx * REG_EM_BLE_TX_ISO_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000008)) >> 3); +} + +__INLINE void em_ble_txisophm0_txsn_setf(int elt_idx, uint8_t txsn) +{ + BLE_ASSERT_ERR((((uint16_t)txsn << 3) & ~((uint16_t)0x00000008)) == 0); + EM_BLE_WR(EM_BLE_TXISOPHM0_ADDR + elt_idx * REG_EM_BLE_TX_ISO_DESC_SIZE, (EM_BLE_RD(EM_BLE_TXISOPHM0_ADDR + elt_idx * REG_EM_BLE_TX_ISO_DESC_SIZE) & ~((uint16_t)0x00000008)) | ((uint16_t)txsn << 3)); +} + +__INLINE uint8_t em_ble_txisophm0_txnesn_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXISOPHM0_ADDR + elt_idx * REG_EM_BLE_TX_ISO_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000004)) >> 2); +} + +__INLINE void em_ble_txisophm0_txnesn_setf(int elt_idx, uint8_t txnesn) +{ + BLE_ASSERT_ERR((((uint16_t)txnesn << 2) & ~((uint16_t)0x00000004)) == 0); + EM_BLE_WR(EM_BLE_TXISOPHM0_ADDR + elt_idx * REG_EM_BLE_TX_ISO_DESC_SIZE, (EM_BLE_RD(EM_BLE_TXISOPHM0_ADDR + elt_idx * REG_EM_BLE_TX_ISO_DESC_SIZE) & ~((uint16_t)0x00000004)) | ((uint16_t)txnesn << 2)); +} + +__INLINE uint8_t em_ble_txisophm0_txllid_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXISOPHM0_ADDR + elt_idx * REG_EM_BLE_TX_ISO_DESC_SIZE); + return ((localVal & ((uint16_t)0x00000003)) >> 0); +} + +__INLINE void em_ble_txisophm0_txllid_setf(int elt_idx, uint8_t txllid) +{ + BLE_ASSERT_ERR((((uint16_t)txllid << 0) & ~((uint16_t)0x00000003)) == 0); + EM_BLE_WR(EM_BLE_TXISOPHM0_ADDR + elt_idx * REG_EM_BLE_TX_ISO_DESC_SIZE, (EM_BLE_RD(EM_BLE_TXISOPHM0_ADDR + elt_idx * REG_EM_BLE_TX_ISO_DESC_SIZE) & ~((uint16_t)0x00000003)) | ((uint16_t)txllid << 0)); +} + +/** + * @brief TXISOBUFPTR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  13:00          TXISOBUFPTR   0x0
+ * 
+ */ +#define EM_BLE_TXISOBUFPTR_ADDR (0x0091000A + EM_BLE_TX_ISO_DESC_OFFSET) +#define EM_BLE_TXISOBUFPTR_INDEX 0x00000005 +#define EM_BLE_TXISOBUFPTR_RESET 0x00000000 + +__INLINE uint16_t em_ble_txisobufptr_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_TXISOBUFPTR_ADDR + elt_idx * REG_EM_BLE_TX_ISO_DESC_SIZE); +} + +__INLINE void em_ble_txisobufptr_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_TXISOBUFPTR_ADDR + elt_idx * REG_EM_BLE_TX_ISO_DESC_SIZE, value); +} + +// field definitions +#define EM_BLE_TXISOBUFPTR_MASK ((uint16_t)0x00003FFF) +#define EM_BLE_TXISOBUFPTR_LSB 0 +#define EM_BLE_TXISOBUFPTR_WIDTH ((uint16_t)0x0000000E) + +#define EM_BLE_TXISOBUFPTR_RST 0x0 + +__INLINE uint16_t em_ble_txisobufptr_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_TXISOBUFPTR_ADDR + elt_idx * REG_EM_BLE_TX_ISO_DESC_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x00003FFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_txisobufptr_setf(int elt_idx, uint16_t txisobufptr) +{ + BLE_ASSERT_ERR((((uint16_t)txisobufptr << 0) & ~((uint16_t)0x00003FFF)) == 0); + EM_BLE_WR(EM_BLE_TXISOBUFPTR_ADDR + elt_idx * REG_EM_BLE_TX_ISO_DESC_SIZE, (uint16_t)txisobufptr << 0); +} + + +#endif // _REG_EM_BLE_TX_ISO_DESC_H_ + diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_em_ble_wpal.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_em_ble_wpal.h new file mode 100755 index 0000000..b7f410b --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/import/reg/ble_reg_em_ble_wpal.h @@ -0,0 +1,215 @@ +#ifndef _REG_EM_BLE_WPAL_H_ +#define _REG_EM_BLE_WPAL_H_ + +#include +#include "_reg_em_ble_wpal.h" +#include "compiler.h" +#include "architect.h" +#include "em_map.h" +#include "ble_reg_access.h" + +#define REG_EM_BLE_WPAL_COUNT 6 + +#define REG_EM_BLE_WPAL_DECODING_MASK 0x0000000F + +#define REG_EM_BLE_WPAL_ADDR_GET(idx) (EM_BLE_WPAL_OFFSET + (idx) * REG_EM_BLE_WPAL_SIZE) + +/** + * @brief LIST_INFO register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     15          ENTRY_VALID   0
+ *     14               IDTYPE   0
+ *     01                IN_WL   0
+ *     00           IN_PERADVL   0
+ * 
+ */ +#define EM_BLE_LIST_INFO_ADDR (0x00910000 + EM_BLE_WPAL_OFFSET) +#define EM_BLE_LIST_INFO_INDEX 0x00000000 +#define EM_BLE_LIST_INFO_RESET 0x00000000 + +__INLINE uint16_t em_ble_list_info_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_LIST_INFO_ADDR + elt_idx * REG_EM_BLE_WPAL_SIZE); +} + +__INLINE void em_ble_list_info_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_LIST_INFO_ADDR + elt_idx * REG_EM_BLE_WPAL_SIZE, value); +} + +// field definitions +#define EM_BLE_ENTRY_VALID_BIT ((uint16_t)0x00008000) +#define EM_BLE_ENTRY_VALID_POS 15 +#define EM_BLE_IDTYPE_BIT ((uint16_t)0x00004000) +#define EM_BLE_IDTYPE_POS 14 +#define EM_BLE_IN_WL_BIT ((uint16_t)0x00000002) +#define EM_BLE_IN_WL_POS 1 +#define EM_BLE_IN_PERADVL_BIT ((uint16_t)0x00000001) +#define EM_BLE_IN_PERADVL_POS 0 + +#define EM_BLE_ENTRY_VALID_RST 0x0 +#define EM_BLE_IDTYPE_RST 0x0 +#define EM_BLE_IN_WL_RST 0x0 +#define EM_BLE_IN_PERADVL_RST 0x0 + +__INLINE void em_ble_list_info_pack(int elt_idx, uint8_t entryvalid, uint8_t idtype, uint8_t inwl, uint8_t inperadvl) +{ + BLE_ASSERT_ERR((((uint16_t)entryvalid << 15) & ~((uint16_t)0x00008000)) == 0); + BLE_ASSERT_ERR((((uint16_t)idtype << 14) & ~((uint16_t)0x00004000)) == 0); + BLE_ASSERT_ERR((((uint16_t)inwl << 1) & ~((uint16_t)0x00000002)) == 0); + BLE_ASSERT_ERR((((uint16_t)inperadvl << 0) & ~((uint16_t)0x00000001)) == 0); + EM_BLE_WR(EM_BLE_LIST_INFO_ADDR + elt_idx * REG_EM_BLE_WPAL_SIZE, ((uint16_t)entryvalid << 15) | ((uint16_t)idtype << 14) | ((uint16_t)inwl << 1) | ((uint16_t)inperadvl << 0)); +} + +__INLINE void em_ble_list_info_unpack(int elt_idx, uint8_t* entryvalid, uint8_t* idtype, uint8_t* inwl, uint8_t* inperadvl) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_LIST_INFO_ADDR + elt_idx * REG_EM_BLE_WPAL_SIZE); + + *entryvalid = (localVal & ((uint16_t)0x00008000)) >> 15; + *idtype = (localVal & ((uint16_t)0x00004000)) >> 14; + *inwl = (localVal & ((uint16_t)0x00000002)) >> 1; + *inperadvl = (localVal & ((uint16_t)0x00000001)) >> 0; +} + +__INLINE uint8_t em_ble_list_info_entry_valid_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_LIST_INFO_ADDR + elt_idx * REG_EM_BLE_WPAL_SIZE); + return ((localVal & ((uint16_t)0x00008000)) >> 15); +} + +__INLINE void em_ble_list_info_entry_valid_setf(int elt_idx, uint8_t entryvalid) +{ + BLE_ASSERT_ERR((((uint16_t)entryvalid << 15) & ~((uint16_t)0x00008000)) == 0); + EM_BLE_WR(EM_BLE_LIST_INFO_ADDR + elt_idx * REG_EM_BLE_WPAL_SIZE, (EM_BLE_RD(EM_BLE_LIST_INFO_ADDR + elt_idx * REG_EM_BLE_WPAL_SIZE) & ~((uint16_t)0x00008000)) | ((uint16_t)entryvalid << 15)); +} + +__INLINE uint8_t em_ble_list_info_idtype_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_LIST_INFO_ADDR + elt_idx * REG_EM_BLE_WPAL_SIZE); + return ((localVal & ((uint16_t)0x00004000)) >> 14); +} + +__INLINE void em_ble_list_info_idtype_setf(int elt_idx, uint8_t idtype) +{ + BLE_ASSERT_ERR((((uint16_t)idtype << 14) & ~((uint16_t)0x00004000)) == 0); + EM_BLE_WR(EM_BLE_LIST_INFO_ADDR + elt_idx * REG_EM_BLE_WPAL_SIZE, (EM_BLE_RD(EM_BLE_LIST_INFO_ADDR + elt_idx * REG_EM_BLE_WPAL_SIZE) & ~((uint16_t)0x00004000)) | ((uint16_t)idtype << 14)); +} + +__INLINE uint8_t em_ble_list_info_in_wl_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_LIST_INFO_ADDR + elt_idx * REG_EM_BLE_WPAL_SIZE); + return ((localVal & ((uint16_t)0x00000002)) >> 1); +} + +__INLINE void em_ble_list_info_in_wl_setf(int elt_idx, uint8_t inwl) +{ + BLE_ASSERT_ERR((((uint16_t)inwl << 1) & ~((uint16_t)0x00000002)) == 0); + EM_BLE_WR(EM_BLE_LIST_INFO_ADDR + elt_idx * REG_EM_BLE_WPAL_SIZE, (EM_BLE_RD(EM_BLE_LIST_INFO_ADDR + elt_idx * REG_EM_BLE_WPAL_SIZE) & ~((uint16_t)0x00000002)) | ((uint16_t)inwl << 1)); +} + +__INLINE uint8_t em_ble_list_info_in_peradvl_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_LIST_INFO_ADDR + elt_idx * REG_EM_BLE_WPAL_SIZE); + return ((localVal & ((uint16_t)0x00000001)) >> 0); +} + +__INLINE void em_ble_list_info_in_peradvl_setf(int elt_idx, uint8_t inperadvl) +{ + BLE_ASSERT_ERR((((uint16_t)inperadvl << 0) & ~((uint16_t)0x00000001)) == 0); + EM_BLE_WR(EM_BLE_LIST_INFO_ADDR + elt_idx * REG_EM_BLE_WPAL_SIZE, (EM_BLE_RD(EM_BLE_LIST_INFO_ADDR + elt_idx * REG_EM_BLE_WPAL_SIZE) & ~((uint16_t)0x00000001)) | ((uint16_t)inperadvl << 0)); +} + +/** + * @brief LIST_BDADDR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00              LBDADDR   0x0
+ * 
+ */ +#define EM_BLE_LIST_BDADDR_ADDR (0x00910002 + EM_BLE_WPAL_OFFSET) +#define EM_BLE_LIST_BDADDR_INDEX 0x00000001 +#define EM_BLE_LIST_BDADDR_RESET 0x00000000 +#define EM_BLE_LIST_BDADDR_COUNT 3 + +__INLINE uint16_t em_ble_list_bdaddr_get(int elt_idx, int reg_idx) +{ + BLE_ASSERT_ERR(reg_idx <= 2); + return EM_BLE_RD(EM_BLE_LIST_BDADDR_ADDR + elt_idx * REG_EM_BLE_WPAL_SIZE + reg_idx * 2); +} + +__INLINE void em_ble_list_bdaddr_set(int elt_idx, int reg_idx, uint16_t value) +{ + BLE_ASSERT_ERR(reg_idx <= 2); + EM_BLE_WR(EM_BLE_LIST_BDADDR_ADDR + elt_idx * REG_EM_BLE_WPAL_SIZE + reg_idx * 2, value); +} + +// field definitions +#define EM_BLE_LBDADDR_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_LBDADDR_LSB 0 +#define EM_BLE_LBDADDR_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_LBDADDR_RST 0x0 + +__INLINE uint16_t em_ble_list_bdaddr_lbdaddr_getf(int elt_idx, int reg_idx) +{ + BLE_ASSERT_ERR(reg_idx <= 2); + uint16_t localVal = EM_BLE_RD(EM_BLE_LIST_BDADDR_ADDR + elt_idx * REG_EM_BLE_WPAL_SIZE + reg_idx * 2); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_list_bdaddr_lbdaddr_setf(int elt_idx, int reg_idx, uint16_t lbdaddr) +{ + BLE_ASSERT_ERR(reg_idx <= 2); + BLE_ASSERT_ERR((((uint16_t)lbdaddr << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_LIST_BDADDR_ADDR + elt_idx * REG_EM_BLE_WPAL_SIZE + reg_idx * 2, (uint16_t)lbdaddr << 0); +} + +/** + * @brief LIST_SID register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00                 LSID   0x0
+ * 
+ */ +#define EM_BLE_LIST_SID_ADDR (0x00910008 + EM_BLE_WPAL_OFFSET) +#define EM_BLE_LIST_SID_INDEX 0x00000004 +#define EM_BLE_LIST_SID_RESET 0x00000000 + +__INLINE uint16_t em_ble_list_sid_get(int elt_idx) +{ + return EM_BLE_RD(EM_BLE_LIST_SID_ADDR + elt_idx * REG_EM_BLE_WPAL_SIZE); +} + +__INLINE void em_ble_list_sid_set(int elt_idx, uint16_t value) +{ + EM_BLE_WR(EM_BLE_LIST_SID_ADDR + elt_idx * REG_EM_BLE_WPAL_SIZE, value); +} + +// field definitions +#define EM_BLE_LSID_MASK ((uint16_t)0x0000FFFF) +#define EM_BLE_LSID_LSB 0 +#define EM_BLE_LSID_WIDTH ((uint16_t)0x00000010) + +#define EM_BLE_LSID_RST 0x0 + +__INLINE uint16_t em_ble_list_sid_lsid_getf(int elt_idx) +{ + uint16_t localVal = EM_BLE_RD(EM_BLE_LIST_SID_ADDR + elt_idx * REG_EM_BLE_WPAL_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_ble_list_sid_lsid_setf(int elt_idx, uint16_t lsid) +{ + BLE_ASSERT_ERR((((uint16_t)lsid << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_BLE_WR(EM_BLE_LIST_SID_ADDR + elt_idx * REG_EM_BLE_WPAL_SIZE, (uint16_t)lsid << 0); +} + + +#endif // _REG_EM_BLE_WPAL_H_ + diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/ble_util_buf.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/ble_util_buf.h new file mode 100755 index 0000000..2506ed0 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/ble_util_buf.h @@ -0,0 +1,251 @@ +/** + **************************************************************************************** + * + * @file ble_util_buf.h + * + * @brief Main API file for the BLE EM buffer management system + * + * Copyright (C) RivieraWaves 2009-2016 + * + **************************************************************************************** + */ + +#ifndef BLE_UTIL_BUF_H_ +#define BLE_UTIL_BUF_H_ + +/** + **************************************************************************************** + * @defgroup BLE_UTIL_BUF BLE EM buffer management system + * @ingroup ROOT + * @brief BLE EM buffer management system + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include // standard integer +#include "common_list.h" // common list definition + +/* + * DEFINES + **************************************************************************************** + */ + +/// ACL data: handle and data length decoding +#define BLE_EM_ACL_DATA_LEN_LSB (0) +#define BLE_EM_ACL_DATA_LEN_MASK (0x03FF) +/// Packet boundary flag +#define BLE_EM_ACL_PBF_LSB (12) +#define BLE_EM_ACL_PBF_MASK (0x3000) +/// Broadcast flag +#define BLE_EM_ACL_BF_LSB (14) +#define BLE_EM_ACL_BF_MASK (0xC000) + +#if (BLE_ISO_PRESENT) +#define BLE_UTIL_ISODESC_INVALID 0xFF +#endif // (BLE_ISO_PRESENT) + +/* + * STRUCTURE DEFINITION + **************************************************************************************** + */ + +/// EM LLCP buffer element +struct ble_em_llcp_buf_elt +{ + /// List header + struct common_list_hdr hdr; + /// EM buffer pointer + uint16_t buf_ptr; + /// Data length (in bytes) + uint8_t length; +}; + +/// EM ACL buffer element +struct ble_em_acl_buf_elt +{ + /// List header + struct common_list_hdr hdr; + /// EM buffer pointer + uint16_t buf_ptr; + /// Data length (in bytes) + Data Flags (PBF + BF) + uint16_t data_len_flags; +}; + +/// EM advertising data buffer element +struct ble_em_adv_buf_elt +{ + /// List header + struct common_list_hdr hdr; + /// EM buffer pointer + uint16_t buf_ptr; + /// Data length (in bytes) + uint16_t length; +}; + +#if (BLE_ISO_PRESENT) +/// EM ISO TX/RX Buffer +struct ble_em_iso_buf_elt +{ + /// List header + struct common_list_hdr hdr; + /// EM buffer pointer + uint16_t buf_ptr; + /// Buffer index + uint8_t buf_idx; +}; +#endif // (BLE_ISO_PRESENT) + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Initialize BLE EM buffers management system + * + * @param[in] init_type Type of initialization (@see enum rwip_init_type) + **************************************************************************************** + */ +void ble_util_buf_init(uint8_t init_type); + +/** + **************************************************************************************** + * @brief Allocate a LLCP TX buffer + * + * @return Pointer to LLCP TX buffer, NULL if no buffer available + **************************************************************************************** + */ +struct ble_em_llcp_buf_elt* ble_util_buf_llcp_tx_alloc(void); + +/** + **************************************************************************************** + * @brief Free a LLCP TX buffer + * + * @param[in] buf Pointer to LLCP TX buffer + **************************************************************************************** + */ +void ble_util_buf_llcp_tx_free(uint16_t buf); + +/** + **************************************************************************************** + * @brief Allocate a RX buffer + * + * @return Pointer to RX buffer, NULL if no buffer available + **************************************************************************************** + */ +uint16_t ble_util_buf_rx_alloc(void); + +/** + **************************************************************************************** + * @brief Free a RX buffer + * + * @param[in] buf Pointer to RX buffer + **************************************************************************************** + */ +void ble_util_buf_rx_free(uint16_t buf); + +/** + **************************************************************************************** + * @brief Allocate a ACL TX buffer + * + * @return Pointer to ACL TX buffer, NULL if no buffer available + **************************************************************************************** + */ +uint16_t ble_util_buf_acl_tx_alloc(void); + + +/** + **************************************************************************************** + * @brief Retrieve TX buffer Element + * + * @return Pointer to ACL TX buffer element + **************************************************************************************** + */ +struct ble_em_acl_buf_elt* ble_util_buf_acl_tx_elt_get(uint16_t buf); + +/** + **************************************************************************************** + * @brief Free a ACL TX buffer + * + * @param[in] buf Pointer to ACL TX buffer + **************************************************************************************** + */ +void ble_util_buf_acl_tx_free(uint16_t buf); + +/** + **************************************************************************************** + * @brief Allocate an advertising data TX buffer + * + * @return Pointer to advertising data TX buffer, NULL if no buffer available + **************************************************************************************** + */ +uint16_t ble_util_buf_adv_tx_alloc(void); + +/** + **************************************************************************************** + * @brief Free an advertising data TX buffer + * + * @param[in] buf Pointer to advertising data TX buffer + **************************************************************************************** + */ +void ble_util_buf_adv_tx_free(uint16_t buf); + +#if (BLE_ISO_PRESENT) +/** + **************************************************************************************** + * @brief Allocate an Isochronous data TX/RX buffer + * + * @param[out] index Index of Isochronous data TX/RX buffer + * + * @return Pointer to Isochronous data TX/RX buffer, NULL if no buffer available + **************************************************************************************** + */ +uint16_t ble_util_buf_iso_alloc(uint8_t* index); + +/** + **************************************************************************************** + * @brief Free an Isochronous data TX/RX buffer + * + * @param[in] index Index of Isochronous data TX/RX buffer + **************************************************************************************** + */ +void ble_util_buf_iso_free(uint8_t index); + +/** + **************************************************************************************** + * @brief Initialize BLE ISO descriptors management system + * + * @param[in] init_type Type of initialization (@see enum rwip_init_type) + **************************************************************************************** + */ +void ble_util_isodesc_init(uint8_t init_type); + +/** + **************************************************************************************** + * @brief Allocate an ISO descriptor + * + * @return Descriptor index allocated + **************************************************************************************** + */ +uint8_t ble_util_isodesc_alloc(void); + +/** + **************************************************************************************** + * @brief Free an ISO descriptor + * + * @param[in] desc_idx Index number of ISO descriptor + **************************************************************************************** + */ +void ble_util_isodesc_free(uint8_t desc_idx); + +#endif // (BLE_ISO_PRESENT) + +/// @} BLE_UTIL_BUF + +#endif // BLE_UTIL_BUF_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/llc/llc_int.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/llc/llc_int.h new file mode 100755 index 0000000..454a3e6 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/llc/llc_int.h @@ -0,0 +1,1062 @@ +/** + **************************************************************************************** + * + * @file llc_int.h + * + * @brief Link layer controller internal definition + * + * Copyright (C) RivieraWaves 2009-2016 + * + **************************************************************************************** + */ + +#ifndef LLC_INT_H_ +#define LLC_INT_H_ + +/** + **************************************************************************************** + * @addtogroup LLC Link layer Controller + * @{ + **************************************************************************************** + */ +#include "rwip_task.h" // Task definitions + + + + + +/* + * INSTANCES + **************************************************************************************** + */ +/// Maximum number of instances of the LLC task +#define LLC_IDX_MAX BLE_ACTIVITY_MAX + +/* + * DEFINE + **************************************************************************************** + */ +///The master should allow a minimum of 6 connection events that the slave will be listening +///for before the instant occurs +#define LLC_PROC_SWITCH_INSTANT_DELAY (9) + +/* + * MESSAGES + **************************************************************************************** + */ + +/// Message API of the LLC task +/*@TRACE + * llc_encrypt_ind = ble_aes_func_res_ind */ +enum llc_msg_id +{ + LLC_MSG_ID_MSG_FIRST = TASK_BLE_FIRST_MSG(TASK_BLE_ID_LLC), + + /* + * ************** Msg LLC->LLC**************** + */ + /// Local procedure LLCP Time out + LLC_LOC_LLCP_RSP_TO = LLC_MSG_ID_MSG_FIRST, + /// Remote procedure LLCP Time out + LLC_REM_LLCP_RSP_TO, + /// Authenticated Payload timeout event + LLC_AUTH_PAYL_REAL_TO, + /// Authenticated Payload Near timeout event + LLC_AUTH_PAYL_NEARLY_TO, + /// Link is stopped, clean-up environment + LLC_STOPPED_IND, + /// Triggered when encryption has been performed + LLC_ENCRYPT_IND, + #if (BLE_CON_CTE_REQ) + /// Constant Tone Extension request timeout + LLC_CTE_REQ_TO, + #endif // (BLE_CON_CTE_REQ) + + /* + * ************ Local Procedures ************* + */ + /// Version exchange procedure + LLC_OP_VER_EXCH_IND, + /// Features exchange procedure + LLC_OP_FEATS_EXCH_IND, + /// Disconnection procedure + LLC_OP_DISCONNECT_IND, + /// Encryption procedure + LLC_OP_ENCRYPT_IND, + /// Data Length update procedure + LLC_OP_DL_UPD_IND, + /// Connection update procedure + LLC_OP_CON_UPD_IND, + /// LE Ping exchange + LLC_OP_LE_PING_IND, + /// Channel map update procedure + LLC_OP_CH_MAP_UPD_IND, + /// PHY update procedure + LLC_OP_PHY_UPD_IND, + #if (BLE_CON_CTE_REQ | BLE_CON_CTE_RSP) + /// Constant Tone Extension procedure + LLC_OP_CTE_IND, + #endif // (BLE_CON_CTE_REQ | BLE_CON_CTE_RSP) + /// Clock accuracy exchange procedure + LLC_OP_CLK_ACC_IND, + /// Periodic Advertising Sync Transfer procedure + LLC_OP_PAST_IND, +}; + + + + +/* + * STATES + **************************************************************************************** + */ +/// Procedures type definition +enum llc_proc_type +{ + /** Local initiated procedure + * + * @startuml llc_local_proc_init.png + * participant HCI + * participant LLC + * alt Procedure initiated by host + * HCI --> LLC : HCI_XXX_CMD + * LLC -> LLC: hci_xxx_cmd_handler() + * activate LLC + * note over LLC #aqua: Allocate and fill procedure message + * LLC --> LLC : LLC_OP_XXX_IND + * note right: send message to local task instance \nto flow control procedure + * LLC --> HCI : HCI_CMD_STAT_EVENT + * deactivate LLC + * else Procedure initiated by controller + * ... -> LLC: llc_xxx_proc_start() + * activate LLC + * note over LLC #aqua: Allocate and fill procedure message + * LLC --> LLC : LLC_OP_XXX_IND + * note right: send message to local task instance \nto flow control procedure + * deactivate LLC + * end + * @enduml + * + * Example of simple local procedure + * + * @startuml llc_local_proc_msc.png + * participant HCI + * participant ... + * participant LLC + * participant LLD + * ... --> LLC : LLC_OP_XXX_IND + * LLC -> LLC: llc_op_xxx_ind_handler() + * activate LLC + * hnote over LLC #lightgreen: Register Procedure\nLOCAL_PROC = busy + * LLC -> LLC: llc_op_xxx_continue(START) + * activate LLC + * note over LLC #aqua: state = WAIT_XXX_RSP\nStart transaction timer + * LLC --> LLD: LLCP_XXX_REQ + * deactivate LLC + * deactivate LLC + * ... wait for LLCP response ... + * LLD --> LLC: LLCP_XXX_RSP + * LLC -> LLC: llcp_xxx_rsp_handler() + * activate LLC + * note over LLC: copy information + * LLC -> LLC: llc_op_xxx_continue(XXX_RSP) + * activate LLC + * note over LLC #aqua: state = Done\nStop transaction timer + * hnote over LLC #lightgreen: Unregister Procedure\nLOCAL_PROC = idle + * LLC --> HCI: HCI_XXX_INFO_CMP_EVT + * deactivate LLC + * deactivate LLC + * @enduml + * + */ + LLC_PROC_LOCAL, + /** Remote initiated procedure + * + * + * Example of simple remote procedure + * + * @startuml llc_remote_proc_msc.png + * participant HCI + * participant LLC + * participant LLC_LLCP + * participant LLD + * LLD --> LLC: LLCP_XXX_REQ + * LLC -> LLC: llcp_xxx_req_handler() + * activate LLC + * hnote over LLC #lightgreen: Allocate procedure message\nRegister Procedure\nREMOTE_PROC = busy + * LLC -> LLC: llc_op_xxx_continue(START) + * activate LLC + * note over LLC #aqua: state = WAIT_HCI_XXX_RSP + * LLC --> HCI: HCI_XXX_REQ_EVT + * deactivate LLC + * deactivate LLC + * ... wait for HCI response ... + * HCI --> LLC: HCI_XXX_REQ_REPLY_CMD + * LLC -> LLC: hci_xxx_req_reply_cmd_handler() + * activate LLC + * note over LLC: copy information + * LLC --> HCI: HCI_CMD_CMP_EVT + * LLC -> LLC: llc_op_xxx_continue(HCI_XXX_RSP) + * activate LLC + * note over LLC #aqua: state = WAIT_LLCP_ACK + * LLC --> LLD: LLCP_XXX_RSP + * deactivate LLC + * deactivate LLC + * ... wait for LLCP Baseband ACK ... + * LLD --> LLC_LLCP: LLD_LLCP_TX_CFM + * LLC_LLCP -> LLC_LLCP: lld_llcp_tx_cfm_handler() + * activate LLC_LLCP + * LLC_LLCP -\ LLC: llcp_xxx_rsp_ack_handler() + * activate LLC + * LLC -> LLC: llc_op_xxx_continue(LLCP_ACK) + * activate LLC + * note over LLC #aqua: state = Done + * hnote over LLC #lightgreen: Unregister Procedure\nREMOTE_PROC = idle + * LLC -/ LLC_LLCP + * deactivate LLC + * deactivate LLC + * deactivate LLC_LLCP + * @enduml + * + */ + LLC_PROC_REMOTE, + /// Max number of operations + LLC_PROC_MAX +}; + +/// Possible states of the LLC task +enum llc_state_id +{ + /// Connection ready state + LLC_IDLE = 0x00, + /// Local procedure on-going + LLC_LOC_PROC_BUSY = (1 << LLC_PROC_LOCAL), + /// Remote procedure on-going + LLC_REM_PROC_BUSY = (1 << LLC_PROC_REMOTE), + + /// Not connected + LLC_FREE = 0xFF, +}; +// + + + +/// Procedure identifier +/*@TRACE*/ +enum llc_proc_id +{ + /// No procedure on-going + LLC_PROC_NONE, + /// Disconnection procedure + LLC_PROC_DISCONNECT, + /// Version Exchange procedure + LLC_PROC_VERSION_EXCHANGE, + /// Pause Encryption or Encryption Start procedure + LLC_PROC_ENCRYPT, + /// Feature Exchange procedure + LLC_PROC_FEATURE_EXCHANGE, + /// Connection update + LLC_PROC_CON_UPDATE, + /// Channel map update + LLC_PROC_CH_MAP_UPDATE, + /// Data Length update + LLC_PROC_DL_UPDATE, + /// LE Ping exchange + LLC_PROC_LE_PING, + /// PHY Update procedure + LLC_PROC_PHY_UPDATE, + #if (BLE_CON_CTE_REQ | BLE_CON_CTE_RSP) + /// Constant Tone Extension procedure + LLC_PROC_CTE, + #endif // (BLE_CON_CTE_REQ | BLE_CON_CTE_RSP) + /// Clock accuracy Exchange procedure + LLC_PROC_CLK_ACC, +}; + + +/// List of unexpected error received during a procedure +enum llc_error_type +{ + /// Disconnection detected + LLC_ERR_DISCONNECT, + /// LLCP Unknown PDU received + LLC_ERR_LLCP_UNKNOWN_RSP, + /// LLCP Reject PDU received + LLC_ERR_LLCP_REJECT_IND, + /// LLCP Reject Extended PDU received + LLC_ERR_LLCP_REJECT_IND_EXT, +}; + + +/** LLCP state used for some operation flow control + * + * @startuml llc_llcp_state.png + * state "IDLE" as idle + * state "PAUSE_ENC" as pause + * state "START_ENC" as enc + * state "TERMINATE" as terminate + * idle -down-> terminate : disconnect + * enc -down-> terminate : disconnect + * pause -down-> terminate : disconnect + * idle -right-> pause : re-encrypt + * idle --> enc : encrypt + * pause --> enc : paused + * enc --> idle : encrypted + * @enduml + * + */ +enum llc_llcp_state +{ + /// No specific on-going procedure + LLC_LLCP_IDLE, + /// Pause encryption procedure on-going + LLC_LLCP_PAUSE_ENC, + /// Start encryption procedure on-going + LLC_LLCP_START_ENC, + /// Link termination procedure on-going + LLC_LLCP_TERMINATE, +}; + +/// LLCP direction used to configure the flow control +enum llc_llcp_dir +{ + LLC_LLCP_DIR_RX = 0, + LLC_LLCP_DIR_TX = 1, + LLC_LLCP_DIR_BOTH = 2, +}; + +/// Bit field definitions for LLCP states +/// 7 6 5 4 3 2 1 0 +/// +----+----+----+----+----+----+----+----+ +/// | RFU | TX | RX | +/// +----+----+----+----+----+----+----+----+ +enum llc_llcp_state_bf +{ + /// RX field position + LLC_LLCP_RX_LSB = 0, + LLC_LLCP_RX_MASK = (0x3), + + /// TX field position + LLC_LLCP_TX_LSB = 2, + LLC_LLCP_TX_MASK = (0xC), +}; + + +/// Flow control bit field to flow control procedures requested by host and controller (autonomous) +/// +/// 7 6 5 4 3 2 1 0 +/// +-------+----+----+----+----+----+----+----+ +/// | L_C_UP| PHY|S_DL|C_UP|ENC |FEAT| VER|DISC| +/// +-------+----+----+----+----+----+----+----+ +/// +enum llc_flow_ctrl +{ + /// HCI Disconnect requested by host + LLC_HCI_DISCONNECT_REQ_POS = 0, + LLC_HCI_DISCONNECT_REQ_BIT = (1 << 0), + + /// HCI Read Remote Version requested by host + LLC_HCI_RD_REM_VER_REQ_POS = 1, + LLC_HCI_RD_REM_VER_REQ_BIT = (1 << 1), + + /// HCI Read Remote features requested by host + LLC_HCI_RD_REM_FEAT_REQ_POS = 2, + LLC_HCI_RD_REM_FEAT_REQ_BIT = (1 << 2), + + /// HCI Start Encryption requested by host + LLC_HCI_START_ENCRYPT_REQ_POS = 3, + LLC_HCI_START_ENCRYPT_REQ_BIT = (1 << 3), + + /// HCI Connection Update requested by host + LLC_HCI_CON_UPDATE_REQ_POS = 4, + LLC_HCI_CON_UPDATE_REQ_BIT = (1 << 4), + + /// HCI Set Data Length requested by host + LLC_HCI_SET_DATA_LEN_REQ_POS = 5, + LLC_HCI_SET_DATA_LEN_REQ_BIT = (1 << 5), + + /// HCI Set PHY requested by host + LLC_HCI_SET_PHY_REQ_POS = 6, + LLC_HCI_SET_PHY_REQ_BIT = (1 << 6), + + /// Local Connection Update requested by controller + LLC_LOC_CON_UPDATE_REQ_POS = 7, + LLC_LOC_CON_UPDATE_REQ_BIT = (1 << 7), +}; + + + + +/// Link information bit field +/// +/// 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 +/// +------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+ +/// | | | | | | CK_A | ENC_S|CH UPD| PF_R | LDIS | ENC | INST | LV_S | PV_R | TX_O | ROLE | +/// +------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+------+ +/// +enum llc_info +{ + /// Device is master of the link + LLC_INFO_MASTER_ROLE_POS = 0, + LLC_INFO_MASTER_ROLE_BIT = (1 << 0), + + /// LLCP buffer TX on-going + LLC_LLCP_TX_ONGOING_POS = 1, + LLC_LLCP_TX_ONGOING_BIT = (1 << 1), + + /// Peer version information received + LLC_INFO_PEER_VERSION_RECV_POS = 2, + LLC_INFO_PEER_VERSION_RECV_BIT = (1 << 2), + + /// Local version information sent + LLC_INFO_LOCAL_VERSION_SENT_POS = 3, + LLC_INFO_LOCAL_VERSION_SENT_BIT = (1 << 3), + + /// Procedure with instant on-going + LLC_INFO_INSTANT_PROC_POS = 4, + LLC_INFO_INSTANT_PROC_BIT = (1 << 4), + + /// Current Link is encrypted + LLC_INFO_LINK_ENCRYPTED_POS = 5, + LLC_INFO_LINK_ENCRYPTED_BIT = (1 << 5), + + /// Discard LLCP reception debug feature + LLC_INFO_DBG_LLCP_DISCARD_POS = 6, + LLC_INFO_DBG_LLCP_DISCARD_BIT = (1 << 6), + + /// Peer feature information received + LLC_INFO_PEER_FEATURE_RECV_POS = 7, + LLC_INFO_PEER_FEATURE_RECV_BIT = (1 << 7), + + /// Local channel map update ongoing + LLC_INFO_LOC_CH_MAP_UPD_POS = 8, + LLC_INFO_LOC_CH_MAP_UPD_BIT = (1 << 8), + + /// Encryption start ongoing + LLC_INFO_ENC_START_POS = 9, + LLC_INFO_ENC_START_BIT = (1 << 9), + + /// Accurate clock indicated + LLC_INFO_CLK_ACC_POS = 10, + LLC_INFO_CLK_ACC_BIT = (1 << 10), +}; + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + +/** + * Local or Remote procedure callback used to inform if an unexpected error is raised during procedure execution + * + * @param[in] link_id Link Identifier + * @param[in] error_type Error type (@see enum llc_error_type) + * @param[in] param Parameter according to error type: + * - LLC_ERR_DISCONNECT: reason + * - LLC_ERR_LLCP_UNKNOWN_RSP: struct ll_unknown_rsp* + * - LLC_ERR_LLCP_REJECT_IND: struct ll_reject_ind* + * - LLC_ERR_LLCP_REJECT_IND_EXT: struct ll_reject_ext_ind* + */ +/*@TRACE*/ +typedef void (*llc_proc_error_cb) (uint8_t link_id, uint8_t error_type, void* param); + + + +/// Version information structure +typedef struct +{ + /// LMP version + uint8_t lmp_vers; + /// Manufacturer ID + uint16_t compid; + /// LMP subversion + uint16_t subvers; +} llc_version_t; + + +/// Information about on-going procedure +/*@TRACE*/ +typedef struct +{ + /// Unexpected Error callback + llc_proc_error_cb error_cb; + /// Procedure identifier + //@trc_ref llc_proc_id + uint8_t id; + /// Current procedure state + uint8_t state; + /// Timer procedure state, shall not be modified by procedure (@see enum llc_timer_state) + //@trc_ref llc_timer_state + uint8_t timer_state; +} llc_procedure_t; + + +/// LE Ping information +typedef struct{ + /// Authenticated payload timeout (N*10ms) + uint16_t auth_payl_to; + /// Authenticated payload timeout (N*10ms), Near timer duration + uint16_t auth_near_payl_to; +} llc_le_ping_t; + + +#if (BLE_CON_CTE_REQ) +/// CTE information +typedef struct{ + /// RX parameters received + bool param_received; + /// Sampling enable + bool sampl_en; + /// Request active + bool req_active; + /// CTE request interval (in number of connection events) + uint16_t cte_req_intv; + /// Requested CTE length (in 8us unit) + uint8_t req_cte_len; + /// Requested CTE type (0: AOA | 1: AOD-1us | 2: AOD-2us) + uint8_t req_cte_type; + /// Slot durations (1: 1us | 2: 2us) + uint8_t slot_dur; + /// Length of switching pattern (number of antenna IDs in the pattern) + uint8_t switching_pattern_len; +} llc_cte_rx_t; +#endif // (BLE_CON_CTE_REQ) + +#if (BLE_CON_CTE_RSP) +/// CTE information +typedef struct{ + /// RX parameters received + bool param_received; + /// CTE TX enable + bool en; + /// Used CTE types (bit0: AOA | bit1: AOD-1us | bit2: AOD-2us) + uint8_t cte_types; + /// Length of switching pattern (number of antenna IDs in the pattern) + uint8_t switching_pattern_len; +} llc_cte_tx_t; +#endif // (BLE_CON_CTE_RSP) + +/// Information about connection parameters +typedef struct +{ + /// Current channel map used for connection + struct le_chnl_map ch_map; + + /// Interval (in units of 1,25 ms, i.e. 2 slots) + uint16_t interval; + /// Latency (in units of event) + uint16_t latency; + /// Link supervision timeout (in units of 10 ms) + uint16_t timeout; + + // **** Data Length Management **** + ///the maximum number of octets that the local device will send to the remote device + uint16_t max_tx_octets; + ///the maximum number of octets that the local device is able to receive from the remote device + uint16_t max_rx_octets; + + ///the maximum number of microsecond that the local device will take to transmit to the remote + uint16_t max_tx_time; + ///the maximum number of microsecond that the local device can take to receive from the remote device + uint16_t max_rx_time; + + // **** PHY Management **** + /// Current TX PHY (@see enum le_phy_value) + uint8_t tx_phy; + /// Current RX PHY (@see enum le_phy_value) + uint8_t rx_phy; + + // **** Min Used Channels Management **** + /// PHY(s) for which the slave has a minimum number of used channels requirement + uint8_t min_used_ch_phys; + /// minimum number of channels to be used on the specified PHY + uint8_t min_used_ch; + +} llc_con_params_t; + +/// Information received from LL_PER_SYNC_IND +typedef struct +{ + /// SyncInfo + struct sync_info syncinfo; + /// ID (provided by the Host) + uint16_t id; + /// Connection event counter of the LLCP reception + uint16_t con_evt_cnt_rx; + /// Connection event counter + uint16_t con_evt_cnt; + /// Last periodic advertising event counter + uint16_t last_pa_evt_cnt; + /// Advertising Set ID, advertiser address type and sleep clock accuracy + uint8_t sid_atype_sca; + /// Periodic advertising PHY (@see enum le_phy_mask) + uint8_t phy; + /// Periodic advertiser address + struct bd_addr adva; + /// Periodic advertiser RPA (unresolved RPA if advertiser address is a resolved identity address, 0 otherwise) + struct bd_addr adv_rpa; + /// Sync Connection event counter + uint16_t sync_con_evt_cnt; +} llc_past_rx_info_t; + +/// Periodic advertising sync transfer parameters +typedef struct +{ + /// Information received from LL_PER_SYNC_IND (temporarily stored during address resolution) + llc_past_rx_info_t rx_info; + + // **** PAST RX **** + /// Mode (@see enum per_adv_sync_info_rec_mode) + uint8_t mode; + /// The number of periodic advertising packets that can be skipped after a successful receive + uint16_t skip; + /// Sync timeout (Time=N*10ms) + uint16_t sync_to; + /// CTE type (@see enum sync_cte_type) + uint8_t cte_type; +} llc_past_param_t; + +/// LLC environment structure +struct llc_env_tag +{ + /// Procedure Kernel message saved + llc_procedure_t* procedure[LLC_PROC_MAX]; + /// Current connection parameters + llc_con_params_t con_params; + + /// Queue of LLCP to be sent + struct common_list llcp_tx_queue; + /// Remote device feature exchange and used by the stack + struct features rem_feats; + ///version exchange env + llc_version_t rem_ver; + /// LE Ping information + llc_le_ping_t le_ping; + #if (BLE_CON_CTE_REQ) + /// CTE RX information + llc_cte_rx_t cte_rx; + #endif // (BLE_CON_CTE_REQ) + #if (BLE_CON_CTE_RSP) + /// CTE TX information + llc_cte_tx_t cte_tx; + #endif // (BLE_CON_CTE_RSP) + + /// Periodic Advertising Sync Transfer parameters + llc_past_param_t past; + + // Data Length + /// Suggested value for the Controller's maximum transmitted number of payload octets + uint16_t suggested_max_tx_octets; + /// Suggested value for the Controller's maximum packet transmission time (in us) + uint16_t suggested_max_tx_time; + + // PHY Management + /// Phy options indicated by Host (@see enum le_phy_opt) (by default 0 if never set by Host) + uint16_t phy_opt; + /// Default TX preferred PHY to use (@see enum le_phy_mask) + uint8_t tx_phys; + /// Default RX preferred PHY to use (@see enum le_phy_mask) + uint8_t rx_phys; + + /// Information about current link status (@see enum llc_info) + uint16_t link_info; + /// Information about the current link state (@see enum llc_llcp_state) + uint8_t llcp_state; + /// Flow control information of HCI commands and local (autonomous) procedures (see enum llc_flow_ctrl) + uint8_t flow_ctrl; + /// Disconnection reason + uint8_t disc_reason; + /// Indicate L2CAP start fragment is pending + bool l2cap_start; +}; + +/// AES function execution result +struct llc_encrypt_ind +{ + /// Status of AES execution + uint8_t status; + /// Result of the + uint8_t result[KEY_LEN]; +}; + + +/* + * GLOBAL VARIABLE DECLARATIONS + ***************************************************************************************** + */ + +/// LLC task descriptor +extern const struct kernel_task_desc TASK_BLE_DESC_LLC; + +/// LLM environment variable +extern struct llc_env_tag* llc_env[]; + + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Perform a Link environment variable clean-up due to disconnection or reset + * + * @param[in] link_id Link Identifier + **************************************************************************************** + */ +void llc_cleanup(uint8_t link_id, bool reset); + + +/** + **************************************************************************************** + * @brief Stop the link to ensure that all host request are correctly answered. + * + * It restore the message queue to force finishing postponed operations and then + * send a message to fully stop the link. + * + * @param[in] link_id Link Identifier + **************************************************************************************** + */ +void llc_stop(uint8_t link_id); + +#if (BLE_CENTRAL || BLE_PERIPHERAL) +/** + **************************************************************************************** + * @brief Check if the feature is supported + * + * @param[in] link_id Link identifier + * @param[in] feature Feature to check (@see enum ble_feature) + * + * @return True if peer device feature support is expected, False if not supported + **************************************************************************************** + */ +__INLINE bool llc_le_feature_check(uint8_t link_id, uint8_t feature) +{ + bool ret = false; + + if(link_id < BLE_ACTIVITY_MAX) + { + struct llc_env_tag* llc_env_ptr = llc_env[link_id]; + if(llc_env_ptr != NULL) + { + ret = ((llc_env_ptr->rem_feats.feats[feature >> 3] & (1<<(feature & 0x7))) != 0) ? true : false; + } + } + return (ret); +} + +/** + **************************************************************************************** + * @brief Set/Force if peer feature is supported + * + * @param[in] link_id Link identifier + * @param[in] feature Feature to check (@see enum ble_feature) + * @param[in] enable True to enable the feature, false else + **************************************************************************************** + */ +__INLINE void llc_le_feature_set(uint8_t link_id, uint8_t feature, bool enable) +{ + if(link_id < BLE_ACTIVITY_MAX) + { + struct llc_env_tag* llc_env_ptr = llc_env[link_id]; + if(llc_env_ptr != NULL) + { + if(enable) + { + llc_env_ptr->rem_feats.feats[feature >> 3] |= (1<<(feature & 0x7)); + } + else + { + llc_env_ptr->rem_feats.feats[feature >> 3] &= ~(1<<(feature & 0x7)); + } + } + } +} + +/** + **************************************************************************************** + * @brief Check if the link is disconnecting or not established + * + * @param[in] link_id Link identifier + * + * @return True if a link is disconnecting or already in not connected state, False else + **************************************************************************************** + */ +__INLINE bool llc_is_disconnecting(uint8_t link_id) +{ + bool res = true; + if(link_id < BLE_ACTIVITY_MAX) + { + struct llc_env_tag* llc_env_ptr = llc_env[link_id]; + if(llc_env_ptr != NULL) + { + res = (GETF(llc_env_ptr->llcp_state, LLC_LLCP_RX) == LLC_LLCP_TERMINATE); + } + } + return (res); +} +#endif //(BLE_CENTRAL || BLE_PERIPHERAL) + +/** + **************************************************************************************** + * @brief Update the link state according to on-going activity + * + * When the state goes to terminate, it cannot return to another state. + * Also when LLCP TX state is updated, LLCP module in informed to update the TX Queue list + * if some LLCP transmission are paused. + * + * LLC can set asymmetric RX/TX configuration during encryption procedures. + * When setting Idle or Terminate states, both directions shall be configured at the same time. + * + * @param[in] link_id Link identifier + * @param[in] dir Direction (0:RX | 1:TX | 2:both) + * @param[in] state New state to apply + **************************************************************************************** + */ +void llc_llcp_state_set(uint8_t link_id, uint8_t dir, uint8_t state); + + +/* ************************************************************************************ */ +/* ******************** PROCEDURE MANAGEMENT ********************** */ +/* ************************************************************************************ */ + +/** + **************************************************************************************** + * @brief Register/Start a procedure + * + * @param[in] link_id Link identifier + * @param[in] proc_type Local or Remote Procedure (@see enum llc_proc_type) + * @param[in] params Procedure parameters + **************************************************************************************** + */ +void llc_proc_reg(uint8_t link_id, uint8_t proc_type, llc_procedure_t *params); + +/** + **************************************************************************************** + * @brief Unregister/finish a procedure + * + * @param[in] link_id Link identifier + * @param[in] proc_type Local or Remote Procedure (@see enum llc_proc_type) + **************************************************************************************** + */ +void llc_proc_unreg(uint8_t link_id, uint8_t proc_type); + +/** + **************************************************************************************** + * @brief Retrieve current procedure + * + * @param[in] link_id Link identifier + * @param[in] proc_type Local or Remote Procedure (@see enum llc_proc_type) + * + * @return current procedure type or LLC_PROC_NONE if not started (@see enum llc_proc_id_type) + **************************************************************************************** + */ +uint8_t llc_proc_id_get(uint8_t link_id, uint8_t proc_type); + +/** + **************************************************************************************** + * @brief Retrieve procedure state + * + * @param[in] proc procedure + * + * @return procedure state + **************************************************************************************** + */ +uint8_t llc_proc_state_get(llc_procedure_t *proc); + +/** + **************************************************************************************** + * @brief Set the procedure state + * + * @param[in] proc procedure + * @param[in] link_id link identifier + * @param[in] proc_state new procedure state + **************************************************************************************** + */ +void llc_proc_state_set(llc_procedure_t *proc, uint8_t link_id, uint8_t proc_state); + +/** + **************************************************************************************** + * @brief Retrieve pointer on the current procedure + * + * @param[in] link_id Link identifier + * @param[in] proc_type Local or Remote Procedure (@see enum llc_proc_type) + * + * @return Pointer on the current procedure type or NULL if not used + ***************************************************************************************** + */ +llc_procedure_t * llc_proc_get(uint8_t link_id, uint8_t proc_type); + + +/** + **************************************************************************************** + * @brief Inform on-going procedure that an unexpected error event happens + * + * @param[in] link_id Link identifier + * @param[in] proc_type Local or Remote Procedure (@see enum llc_proc_type) + * @param[in] error_type Type of procedure error detected (@see enum llc_error_type) + * @param[in] param Parameter according to error type (@see llc_proc_error_cb) + ***************************************************************************************** + */ +void llc_proc_err_ind(uint8_t link_id, uint8_t proc_type, uint8_t error_type, void* param); + +/** + **************************************************************************************** + * @brief Enable or Disable Local or Remote procedure LLCP transaction timer + * + * @param[in] link_id Link identifier + * @param[in] proc_type Local or Remote Procedure (@see enum llc_proc_type) + * @param[in] enable True to enable/restart the LLCP transaction timer, False to clear it + ***************************************************************************************** + */ +void llc_proc_timer_set(uint8_t link_id, uint8_t proc_type, bool enable); + +/** + **************************************************************************************** + * @brief Pause or Resume Local or Remote procedure LLCP transaction timer + * + * (if a timer is already started, it will be paused until resume is requested, see state + * machine described in @see enum llc_timer_state) + * + * @param[in] link_id Link identifier + * @param[in] proc_type Local or Remote Procedure (@see enum llc_proc_type) + * @param[in] enable True to pause the LLCP transaction timer, False to resume it + ***************************************************************************************** + */ +void llc_proc_timer_pause_set(uint8_t link_id, uint8_t proc_type, bool enable); +/** + **************************************************************************************** + * @brief Check if a procedure is not entering in collision with another one. + * + * @param[in] link_id Link Identifier + * @param[in] proc_id New procedure to start + * + * @return COMMON_ERROR_NO_ERROR if no collision; + * COMMON_ERROR_LMP_COLLISION or COMMON_ERROR_DIFF_TRANSACTION_COLLISION else. + **************************************************************************************** + */ +uint8_t llc_proc_collision_check(uint8_t link_id, uint8_t proc_id); + + + + +/* ************************************************************************************ */ +/* ************************* HCI HELPERS ********************** */ +/* ************************************************************************************ */ + + +/** + **************************************************************************************** + * @brief Send HCI CC event returning a status only + * + * @param[in] link_id Link Identifier + * @param[in] opcode HCI Operation code + * @param[in] status HCI CC status code + **************************************************************************************** + */ +void llc_cmd_cmp_send(uint8_t link_id, uint16_t opcode, uint8_t status); + +/** + **************************************************************************************** + * @brief Send HCI CS event + * + * @param[in] link_id Link Identifier + * @param[in] opcode HCI Operation code + * @param[in] status HCI CS status code + **************************************************************************************** + */ +void llc_cmd_stat_send(uint8_t link_id, uint16_t opcode, uint8_t status); + + + +/* ************************************************************************************ */ +/* ************************* Procedure start ********************** */ +/* ************************************************************************************ */ + +/** + **************************************************************************************** + * @brief Immediate Disconnection + * + * @param[in] link_id Link Identifier + * @param[in] reason Reason of disconnection + * @param[in] immediate True: Try to stop event as soon as possible + * False: Wait for new connection event to be programmed + **************************************************************************************** + */ +void llc_disconnect(uint8_t link_id, uint8_t reason, bool immediate); + +/** + **************************************************************************************** + * @brief Initiate the termination procedure + * + * @param[in] link_id Link Identifier + * @param[in] reason Reason of disconnection + **************************************************************************************** + */ +void llc_init_term_proc(uint8_t link_id, uint8_t reason); + +/** + **************************************************************************************** + * @brief Set the authenticated payload timeout and compute the timer margin. + * + * @param[in] link_id Link Identifier + * @param[in] auth_payl_to Authenticated payload timeout + * + * @return COMMON_ERROR_NO_ERROR if succeed; COMMON_ERROR_INVALID_HCI_PARAM else. + **************************************************************************************** + */ +uint8_t llc_le_ping_set(uint8_t link_id, uint16_t auth_payl_to); + +/** + **************************************************************************************** + * @brief Restart the authenticated payload timeout timer (and its margin timer) + * to check if encrypted link is still alive + * + * @param[in] link_id Link Identifier + * @param[in] auth_payl_to Authenticated payload timeout + **************************************************************************************** + */ +void llc_le_ping_restart(uint8_t link_id); + +/** + **************************************************************************************** + * Start PHY update procedure + * + * @param[in] link_id Link identifier + **************************************************************************************** + */ +void phy_upd_proc_start(uint8_t link_id); + +/** + **************************************************************************************** + * Start data length update procedure + * + * @param[in] link_id Link identifier + **************************************************************************************** + */ +void dl_upd_proc_start(uint8_t link_id); + +#if BLE_CON_CTE_REQ +/** + **************************************************************************************** + * @brief Disable CTE request + * + * @param[in] link_id Link Identifier + **************************************************************************************** + */ +void llc_cte_req_dis(uint8_t link_id); +#endif // BLE_CON_CTE_REQ +#if BLE_CON_CTE_RSP +/** + **************************************************************************************** + * @brief Disable CTE response + * + * @param[in] link_id Link Identifier + **************************************************************************************** + */ +void llc_cte_rsp_dis(uint8_t link_id); +#endif // BLE_CON_CTE_RSP + +/// @} LLC + +#endif // LLC_INT_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/llc/llc_llcp.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/llc/llc_llcp.h new file mode 100755 index 0000000..d377414 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/llc/llc_llcp.h @@ -0,0 +1,125 @@ +/** + **************************************************************************************** + * + * @file llc_llcp.h + * + * @brief Functions for control pdu transmission/reception handling + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef LLC_CNTL_H_ +#define LLC_CNTL_H_ + +/** + **************************************************************************************** + * @addtogroup LLCLLCP LLCLLCP + * @ingroup LLC + * @brief Functions for control pdu transmission/reception handling + * + * This module implements the functions allowing the handling of the transmission and + * reception of the control pdu. + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "common_llcp.h" + +#if (BLE_PERIPHERAL || BLE_CENTRAL) + +/* + * MACROS + **************************************************************************************** + */ + +/* + * type definition + **************************************************************************************** + */ +/** + **************************************************************************************** + * @brief Callback used to inform procedure when LLCP packet transmitted has been + * baseband acknowledged + * + * @param[in] link_id Link identifier on which the pdu will be sent. + * @param[in] op_code LLCP operation code + * + **************************************************************************************** + */ +typedef void (*llc_llcp_tx_cfm_cb) (uint8_t link_id, uint8_t op_code); + +/** + **************************************************************************************** + * @brief Callback used to handle LLCP message + * + * @param[in] link_id Link identifier on which the pdu will be sent. + * @param[in] pdu LLCP PDU information received + * @param[in] event_cnt Event counter value when PDU has been received + * + * @return status code of handler: + * - COMMON_ERROR_NO_ERROR: Nothing more to do + * - COMMON_ERROR_TERMINATED_MIC_FAILURE: Immediately disconnect the link + * - others: Send an LLCP_REJECT_IND or LLCP_REJECT_IND_EXT + **************************************************************************************** + */ +typedef uint8_t (*llc_llcp_pdu_handler_func_t)(uint8_t link_id, union llcp_pdu *pdu, uint16_t event_cnt); + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + + +/** + **************************************************************************************** + * @brief Sends the programmed LLCP PDU on the given link identifier. + * + * @param[in] link_id The link identifier on which the LLCP has to be transmitted + * @param[in] pdu Pointer on the PDU to be sent + * @param[in] tx_cfm_cb Pointer to the function to call when LLCP packet TX is done. + **************************************************************************************** + */ +void llc_llcp_send(uint8_t link_id, union llcp_pdu *pdu, llc_llcp_tx_cfm_cb tx_cfm_cb); + + + +/** + **************************************************************************************** + * @brief Link state have changed, check if some pending LLCP has to be transmitted + * + * @param[in] link_id The link identifier + **************************************************************************************** + */ +void llc_llcp_tx_check(uint8_t link_id); + + +/** + **************************************************************************************** + * @brief Sends the (extended) reject indication pdu. + * + * This function allocates an sets header and parameters of the pdu before pushing it in + * the tx queue. + * + * @param[in] link_id Link identifier on which the PDU will be sent. + * @param[in] rej_opcode Rejected Operation code. + * @param[in] reason The reason to be put in the Reject Indication PDU + * @param[in] tx_cfm_cb Pointer to the function to call when LLCP packet TX is done. + **************************************************************************************** + */ +void llc_ll_reject_ind_pdu_send(uint8_t link_id, uint8_t rej_opcode, uint8_t reason, llc_llcp_tx_cfm_cb tx_cfm_cb); + +#endif // #if (BLE_PERIPHERAL || BLE_CENTRAL) + + + +/// @} LLCLLCP + +#endif // LLC_CNTL_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/llctrl.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/llctrl.h new file mode 100755 index 0000000..c11827e --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/llctrl.h @@ -0,0 +1,194 @@ +/** + **************************************************************************************** + * + * @file llctrl.h + * + * @brief Main API file for the Link Layer Controller + * + * Copyright (C) RivieraWaves 2009-2016 + * + **************************************************************************************** + */ + +#ifndef LLC_H_ +#define LLC_H_ + +/** + **************************************************************************************** + * @defgroup LLC Link Layer Controller + * @ingroup ROOT + * @brief BLE Lower Layers + * + * The CONTROLLER contains the modules allowing the link establishment, maintenance and management. + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" +#if(BLE_CENTRAL || BLE_PERIPHERAL) +#include "kernel_task.h" // kernel task definitions +#include "common_bt.h" +#include "common_llcp.h" + +/* + * DEFINES + **************************************************************************************** + */ + + +/* + * ENUMERATION DEFINITIONS + **************************************************************************************** + */ + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + +/// API structure to be set by LLM and used by the LLC for each new link +struct llc_init_parameters +{ + /// Access address + struct access_addr aa; + + /// CRC init + struct crc_init crcinit; + + /// Window size (in units of 1,25 ms, i.e. 2 slots) + uint8_t winsize; + + /// Window offset (in units of 1,25 ms, i.e. 2 slots) + uint16_t winoffset; + + /// Interval (in units of 1,25 ms, i.e. 2 slots) + uint16_t interval; + + /// Latency + uint16_t latency; + + /// Timeout (in units of 10 ms, i.e. 16 slots) + uint16_t timeout; + + /// Channel mapping + struct le_chnl_map chm; + + /// Hopping increment (random value in the range of 5 to 16) + uint8_t hop_inc; + + /** + * Master Sleep clock accuracy (only for slave) + * 0 251 ppm to 500 ppm + * 1 151 ppm to 250 ppm + * 2 101 ppm to 150 ppm + * 3 76 ppm to 100 ppm + * 4 51 ppm to 75 ppm + * 5 31 ppm to 50 ppm + * 6 21 ppm to 30 ppm + * 7 0 ppm to 20 ppm + */ + uint8_t master_sca; + + /// CONNECT_REQ packet fine timer count (in us) + uint16_t fine_cnt_rxsync; + + /// CONNECT_REQ packet base timer count (timestamp, in slots) + uint32_t base_cnt_rxsync; + + /// First anchor point timestamp (in slots, master only) + uint32_t first_anchor_ts; + + /// Connection transmit/receive rate (@see enum lld_rate) + uint8_t rate; + + /// Role (0: Master | 1: Slave) + uint8_t role; + + /// Indicates whether channel selection algorithm #2 will be used or not + bool ch_sel_2; + + /// Indicates whether the AUX_CONNECT_REQ PDU was used or not (true for AUX_CONNECT_REQ, false for CONNECT_IND) + bool aux_connect_req; + + // Default Data Length parameters + /// Suggested value for the Controller's maximum transmitted number of payload octets + uint16_t suggested_max_tx_octets; + /// Suggested value for the Controller's maximum packet transmission time (in us) + uint16_t suggested_max_tx_time; + + // Default PHY parameters + /// Default TX preferred PHY to use (@see enum le_phy_mask) + uint8_t tx_phys; + /// Default RX preferred PHY to use (@see enum le_phy_mask) + uint8_t rx_phys; + + // Default PAST parameters + /// Mode (@see enum per_adv_sync_info_rec_mode) + uint8_t past_mode; + /// The number of periodic advertising packets that can be skipped after a successful receive + uint16_t past_skip; + /// Sync timeout (Time=N*10ms) + uint16_t past_sync_to; + /// CTE type (@see enum sync_cte_type) + uint8_t past_cte_type; +}; + + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ +/** + **************************************************************************************** + * @brief Initialization/Reset of the BLE LLC task + * + * This function initializes the LLC task, as well as the environment of the LLC + * + * @param[in] init_type Type of initialization (@see enum rwip_init_type) + **************************************************************************************** + */ +void llc_init(uint8_t init_type); + + +/** + **************************************************************************************** + * @brief Start an initialize a new LLC environment + * + * @param[in] link_id link identifier. + * @param[in] con_params All parameters needed to start the LLC + * @param[in] pref Link preferences (set by host) + * + * @return If the environment allocation and initialization has been done or not. + **************************************************************************************** + */ +uint8_t llc_start(uint8_t link_id, struct llc_init_parameters *con_params); + +/** + **************************************************************************************** + * @brief Handles a planner request to move the activity + * + * @param[in] id sch_plan identifier. + **************************************************************************************** + */ +void llc_con_move_cbk(uint16_t id); + +/** + **************************************************************************************** + * @brief Modify sleep clock accuracy + * + * @param[in] link_id Link identifier + * @param[in] action Switch to more or less accurate clock (@see enum clk_acc_action) + **************************************************************************************** + */ +void llc_clk_acc_modify(uint8_t link_id, uint8_t action); + +#endif// (BLE_CENTRAL || BLE_PERIPHERAL) + +/// @} LLC + +#endif // LLC_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/lld.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/lld.h new file mode 100755 index 0000000..0b704ef --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/lld.h @@ -0,0 +1,2132 @@ +/** +**************************************************************************************** +* +* @file lld.h +* +* @brief LLD API +* +* Copyright (C) RivieraWaves 2009-2016 +* +* +**************************************************************************************** +*/ + +#ifndef LLD_H_ +#define LLD_H_ + +/** + **************************************************************************************** + * @defgroup LLD Link Driver + * @ingroup ROOT + * @brief LLD module handles the real-time job of Bluetooth operations. + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" // stack configuration + +#include // integer +#include // boolean +#include // BLE standard definitions +#include "ble_util_buf.h" // BLE buffers management +#include "rwip_task.h" // Task definitions +#if (BLE_ISO_PRESENT) +#include "data_path.h" // Used for Isochronous channels +#endif // (BLE_ISO_PRESENT) + + + +/* + * DEFINES + ***************************************************************************************** + */ + +/* + * ENUMERATION DEFINITIONS + **************************************************************************************** + */ + + +/* + * MESSAGES IDENTIFIERS + **************************************************************************************** + */ + +/// Message API of the LLM task +/*@TRACE*/ +enum lld_msg_id +{ + LLD_MSG_ID_FIRST = TASK_BLE_FIRST_MSG(TASK_BLE_ID_LLD), + + /* + * ************** Msg LD->LLM**************** + */ + LLD_ADV_REP_IND, + LLD_SCAN_REQ_IND, +#if (CFG_BLE_PER_SYNC) + LLD_SYNC_START_REQ, + LLD_PER_ADV_REP_IND, + LLD_PER_ADV_RX_END_IND, +#endif + LLD_SCAN_END_IND, + LLD_ADV_END_IND, + LLD_PER_ADV_END_IND, + LLD_INIT_END_IND, + LLD_TEST_END_IND, + #if BLE_CONLESS_CTE_RX + LLD_CONLESS_CTE_RX_IND, + #endif // BLE_CONLESS_CTE_RX + + /* + * ************** Msg LLD->LLC**************** + */ + LLD_LLCP_RX_IND, + LLD_LLCP_TX_CFM, + LLD_ACL_RX_IND, + LLD_ACL_TX_CFM, + LLD_CON_PARAM_UPD_CFM, + LLD_CH_MAP_UPD_CFM, + LLD_PHY_UPD_CFM, + LLD_DISC_IND, + LLD_CON_ESTAB_IND, + LLD_CON_OFFSET_UPD_IND, + #if BLE_CON_CTE_REQ + LLD_CON_CTE_RX_IND, + #endif // BLE_CON_CTE_REQ +}; + +/* + * MESSAGES STRUCTURES + **************************************************************************************** + */ + +/// Advertising report indication structure +/*@TRACE*/ +struct lld_adv_rep_ind +{ + /// Peer device address match + bool peer_add_match; + + /// local add Match + bool local_add_match; + + /// Address of the RAL Structure for which RPA resolution is successful + uint16_t rxralptr; + + /// Peer device address + struct bd_addr peer_id_addr; + + /// Target device address + struct bd_addr target_id_addr; + + /// Advertising Data Info field (Data ID + Set ID) + uint16_t adi; + + /// Indicate if Advertising Data Info field is present + bool adi_present; + + /// Privacy error + bool priv_err; + + /// Activity identifier + uint8_t act_id; + + /** + * Bit + * 0 Connectable advertising + * 1 Scannable advertising + * 2 Directed advertising + * 3 Scan response + * 4 Legacy advertising PDUs used + */ + uint8_t evt_type; + + /** + * Data status + * 00b Complete + * 01b Incomplete, more data to come + * 10b Incomplete, data truncated, no more to come + * 11b Reserved for future use + */ + uint8_t data_status; + + /** + * Peer address type + * 0x00 Public Device Address + * 0x01 Random Device Address + * 0xFF None - Anonymous + */ + uint8_t addr_type; + + /// RxAdd (0: Public | 1: Random) + uint8_t rx_rxadd; + + /// Primary PHY (@see enum lld_rate) + uint8_t rate1; + + /// Secondary PHY (@see enum lld_rate) + uint8_t rate2; + + // Tx Power + uint8_t tx_power; + + /// Received signal strength in dBm + int8_t rssi; + + /// Periodic advertising interval + uint16_t interval; + + /// Data length in bytes + uint8_t data_len; + + /// Chain ID (differentiate interleaved chains - chain 1, chain 2) + uint8_t chain; + + /// EM buffer to read & free. Valid if data_len != 0. + uint16_t em_buf; + + /// Data offset + uint8_t data_offset; +}; + +// SyncInfo RX request for initiating a Periodic Scan +/*@TRACE*/ +struct lld_sync_start_req +{ + /// Activity identifier + uint8_t act_id; + + // SyncInfo + struct sync_info syncinfo; + + /// The clock value of the reference time (in half-slot) + uint32_t base_cnt; + + /// The fine timer value the reference time (in half-us) + uint16_t fine_cnt; + + /// The bit rate of periodic advertising (@see enum lld_rate) + uint8_t rate; + + /// Advertising SID + uint8_t adv_sid; + + /// Address of the RAL Structure for which RPA resolution is successful + uint16_t rxralptr; + + /// Advertising address type (0: public / 1: random) + uint8_t adv_addr_type; + + /// Advertiser address + struct bd_addr adv_addr; + + /// max Skip after receive + uint16_t skip; + + /// Sync timeout (Time=N*10ms) + uint16_t sync_to; +}; + +/// Periodic advertising report indication structure +/*@TRACE*/ +struct lld_per_adv_rep_ind +{ + /// Activity identifier + uint8_t act_id; + + /// Advertiser rate (@see enum lld_rate) + uint8_t rate; + + /// Periodic advertising interval (Time=N*1.25ms) + uint16_t interval; + + /// Activity offset in slots (625 us) + uint16_t act_offset; + + /// value of the sync event counter when the packet is received + uint16_t ref_evt_cnt; + + /// Advertiser clock accuracy + uint8_t adv_ca; + + /// Tx Power + uint8_t tx_power; + + /// RSSI + int8_t rssi; + + /// Data Status + uint8_t data_status; + + /// Data length in bytes + uint8_t data_len; + + /// EM buffer to read & free. Valid if data_len != 0. + uint16_t em_buf; + + /// Data offset + uint8_t data_offset; + + /// CTE Type (0x00: A0A, 0x01: AoD 1 us, 0x02: AoD 2us, 0xFF: No CTE, All other values: RFU) + uint8_t cte_type; + + /// Used to know if ACAD data present in the received ADV packet - 0 means not present + uint8_t acad_len; + + /// offset of ACAD data content in the EM Buffer + uint8_t acad_offset; +}; + +/// Periodic advertising RX end indication structure +/*@TRACE*/ +struct lld_per_adv_rx_end_ind +{ + /// Activity identifier + uint8_t act_id; + + /// Status of the advertising sync + uint8_t status; +}; + +/// Scan request indication structure +/*@TRACE*/ +struct lld_scan_req_ind +{ + /// Activity identifier + uint8_t act_id; + + /** + * Scanner address type + * 0x00 Public Device Address + * 0x01 Random Device Address + * 0x02 Public Identity Address (Corresponds to Resolved Private Address) + * 0x03 Random (static) Identity Address (Corresponds to Resolved Private Address) + * 0x04-0xFF Reserved for future use + */ + uint8_t addr_type; + + /// Scanner address + struct bd_addr addr; +}; + +/// Advertising end indication structure +/*@TRACE*/ +struct lld_adv_end_ind +{ + /// Activity identifier + uint8_t act_id; + + /// Status (BLE error code) + uint8_t status; + + /// Access address + struct access_addr aa; + + /// CRC init + struct crc_init crcinit; + + /// Local resolvable private address used for advertising + struct bd_addr local_rpa; + + /// Peer resolvable private address of initiator or peer address indicated in CONNECT_REQ packet + struct bd_addr peer_rpa; + + /// Initiator identity address + struct bd_addr peer_id_addr; + + /// Window size (in units of 1,25 ms, i.e. 2 slots) + uint8_t winsize; + + /// Window offset (in units of 1,25 ms, i.e. 2 slots) + uint16_t winoffset; + + /// Interval (in units of 1,25 ms, i.e. 2 slots) + uint16_t interval; + + /// Latency + uint16_t latency; + + /// Timeout (in units of 10 ms, i.e. 16 slots) + uint16_t timeout; + + /// Channel mapping + struct le_chnl_map chm; + + /// Hopping increment (random value in the range of 5 to 16) + uint8_t hop_inc; + + /** + * Master Sleep clock accuracy (only for slave) + * 0 251 ppm to 500 ppm + * 1 151 ppm to 250 ppm + * 2 101 ppm to 150 ppm + * 3 76 ppm to 100 ppm + * 4 51 ppm to 75 ppm + * 5 31 ppm to 50 ppm + * 6 21 ppm to 30 ppm + * 7 0 ppm to 20 ppm + */ + uint8_t master_sca; + + /// CONNECT_REQ packet fine timer count (in us) + uint16_t fine_cnt_rxsync; + + /// CONNECT_REQ packet base timer count (timestamp, in slots) + uint32_t base_cnt_rxsync; + + /// PHY rate to be used for the connection (0: 1Mbps | 1: 2 Mbps | 2: 125 Kbps | 3: 500 Kbps) + uint8_t con_rate; + + /// Connection status (True: device connected | False: device not connected) + bool connected; + + /// Indicates whether channel selection algorithm #2 will be used or not + bool ch_sel_2; + + /** + * Peer address type + * 0x00 Public Device Address + * 0x01 Random Device Address + * 0x02 Public Identity Address (Corresponds to peers Resolvable Private Address) + * 0x03 Random (static) Identity Address (Corresponds to peers Resolvable Private Address) + * 0x04 - 0xFF Reserved for future use + */ + uint8_t peer_addr_type; + + /// Number of completed extended advertising events + uint8_t nb_ext_adv_evts; +}; + +/// Periodic advertising end indication structure +struct lld_per_adv_end_ind +{ + /// Activity identifier + uint8_t act_id; + + /// Status (BLE error code) + uint8_t status; +}; + +/// Scanning end indication structure +/*@TRACE*/ +struct lld_scan_end_ind +{ + /// Status (BLE error code) + uint8_t status; + + /// Activity identifier used for advertising + uint8_t act_id; +}; + +/// Test mode end indication structure +/*@TRACE*/ +struct lld_test_end_ind +{ + /// Status (BLE error code) + uint8_t status; + + /// Number of packets received + uint16_t nb_pkt_recv; +}; + +/// Initiating end indication structure +/*@TRACE*/ +struct lld_init_end_ind +{ + /// Activity identifier + uint8_t act_id; + + /// Connection status (True: device connected | False: device not connected) + bool connected; + + /// Local resolvable private address used for initiating + struct bd_addr local_rpa; + + /// Peer resolvable private address of advertiser or peer address indicated in ADV packet + struct bd_addr peer_rpa; + + /// Advertiser identity address + struct bd_addr peer_id_addr; + + /// access address + struct access_addr aa; + + /// Connection interval (in units of 1,25 ms, i.e. 2 slots) + uint16_t con_intv; + + /// Connection offset in slots (625 us) + uint16_t con_offset; + + /// First anchor point (timestamp, in slots) + uint32_t base_con_txwin; + + /** + * Peer address type + * 0x00 Public Device Address + * 0x01 Random Device Address + * 0x02 Public Identity Address (Corresponds to peers Resolvable Private Address) + * 0x03 Random (static) Identity Address (Corresponds to peers Resolvable Private Address) + * 0x04 - 0xFF Reserved for future use + */ + uint8_t peer_addr_type; + + /// Channel map for use on the connection + struct le_chnl_map ch_map; + + /// Index of initiating PHY used + uint8_t phy_idx; + + /// PHY rate to be used for the connection (0: 1Mbps | 1: 2 Mbps | 2: 125 Kbps | 3: 500 Kbps) + uint8_t con_rate; + + /// Connection latency + uint16_t con_latency; + + /// Connection supervision timeout in 10ms (N * 10ms) + uint16_t superv_to; + + /// CRC init + struct crc_init crcinit; + + /// Window size + uint8_t winsize; + + /// Hopping increment + uint8_t hop_inc; + + /// Master sleep clock accuracy + uint8_t m_sca; + + /// TX power of peer device + uint8_t tx_power; + + /// ADI collision - mismatch on AdvDataInfo + bool adi_collision; + + /// Indicates whether channel selection algorithm #2 will be used or not + bool ch_sel_2; +}; + +/// LLD disconnection indication structure +/*@TRACE*/ +struct lld_disc_ind +{ + /// Driver disconnection reason + uint8_t reason; +}; + +/// LLD LLCP reception indication structure +/*@TRACE*/ +struct lld_llcp_rx_ind +{ + /// Event counter when the packet has been received + uint16_t event_cnt; + /// PDU length + uint8_t length; + /// EM buffer containing PDU + uint16_t em_buf; +}; + +/// LLD ACL reception indication structure +/*@TRACE*/ +struct lld_acl_rx_ind +{ + /// EM buffer containing PDU + uint16_t em_buf; + /// Data length + Data Flags (PBF + BF) + uint16_t data_len; + /// LLID + uint8_t llid; +}; + +/// LLD connection established indication structure +/*@TRACE*/ +struct lld_con_estab_ind +{ + /// Connection offset in slots (625 us) + uint16_t con_offset; +}; + +/// LLD connection offset update indication structure +/*@TRACE*/ +struct lld_con_offset_upd_ind +{ + /// Connection offset in slots (625 us) + uint16_t con_offset; +}; + +#if BLE_CON_CTE_REQ +/// LLD connection CTE RX indication structure +/*@TRACE*/ +struct lld_con_cte_rx_ind +{ + /// RX CTE descriptor index + uint8_t em_rx_cte_desc_idx; + /// CTE time (in 8us unit) + uint8_t cte_time; + /// CTE type (0: AOA | 1: AOD-1us | 2: AOD-2us) + uint8_t cte_type; + /// Number of IQ samples + uint8_t nb_iq_samp; + /// PHY (@see enum le_phy_value) + uint8_t phy; + /// Channel index + uint8_t channel_idx; + /// RSSI (in 0.1 dBm) + int16_t rssi; + /// RSSI antenna ID + uint8_t rssi_antenna_id; + /// connEventCounter + uint16_t con_evt_cnt; +}; +#endif // BLE_CON_CTE_REQ + +#if BLE_CONLESS_CTE_RX +/// LLD connection CTE RX indication structure +/*@TRACE*/ +struct lld_conless_cte_rx_ind +{ + /// Activity identifier + uint8_t act_id; + /// RX CTE descriptor index + uint8_t em_rx_cte_desc_idx; + /// Data channel index + uint8_t channel_idx; + /// RSSI (in 0.1 dBm) + int16_t rssi; + /// RSSI antenna ID + uint8_t rssi_antenna_id; + /// CTE type (0: AOA | 1: AOD-1us | 2: AOD-2us) + uint8_t cte_type; + /// Slot durations (1: 1us | 2: 2us) + uint8_t slot_dur; + /// paEventCounter + uint16_t pa_evt_cnt; + /// Sample_count + uint8_t sample_cnt; +}; +#endif // BLE_CONLESS_CTE_RX + +/* + * STRUCTURE DEFINITIONS + **************************************************************************************** + */ + +/// Channel assessment data +struct lld_ch_assess_data +{ + /// Timestamp of last received packet for each frequency + uint32_t timestamp[DATA_CHANNEL_NB]; + + /// Channel quality level for each frequency + int8_t level[DATA_CHANNEL_NB]; +}; + +/// Advertising parameters structure +struct lld_adv_params +{ + /// BD Address of the local device + struct bd_addr own_addr; + + /// BD Address of the peer device (only for directed advertising) + struct bd_addr peer_addr; + + /// Primary advertising interval + uint32_t prim_adv_intv; + + /// Initial advertising data buffer + uint16_t init_adv_data_buf; + + /// Initial scan response data buffer + uint16_t init_scan_rsp_data_buf; + + /// Initial advertising data length + uint16_t init_adv_data_len; + + /// Initial scan response data length + uint16_t init_scan_rsp_data_len; + + /// Advertising event properties + uint16_t adv_evt_properties; + + /// Duration (N * 10 ms), 0x0000 No advertising duration. Advertising to continue until the Host disables it. + uint16_t duration; + + /// Maximum number of extended advertising events + uint8_t max_ext_adv_evt; + + /// Primary advertising channel map + uint8_t prim_adv_ch_map; + + /** + * Local address type + * 0x00 Public Device Address (default) + * 0x01 Random Device Address + * 0x02 Controller generates Resolvable Private Address based on the local IRK from resolving list. If resolving + * list contains no matching entry, use public address. + * 0x03 Controller generates Resolvable Private Address based on the local IRK from resolving list. If resolving + * list contains no matching entry, use random address from LE_Set_Random_Address. + */ + uint8_t own_addr_type; + + /** + * Peer address type (only for directed advertising) + * 0x00 Public Device Address (default) or Public Identity Address + * 0x01 Random Device Address or Random (static) Identity Address + * 0x02 - 0xFF Reserved for future use + */ + uint8_t peer_addr_type; + + /** + * Advertising filter policy: + * 0x00 Process scan and connection requests from all devices (i.e., the White List is not in use) (default). + * 0x01 Process connection requests from all devices and only scan requests from devices that are in the White List. + * 0x02 Process scan requests from all devices and only connection requests from devices that are in the White List. + * 0x03 Process scan and connection requests only from devices in the White List. + * 0x04 - 0xFF Reserved for future use. + */ + uint8_t adv_filter_policy; + + /// Advertising Tx power + int8_t adv_tx_pwr; + + /// Primary advertising PHY + uint8_t prim_adv_phy; + + /// Secondary advertising max skip + uint8_t sec_adv_max_skip; + + /// Secondary advertising PHY + uint8_t sec_adv_phy; + + /// Advertising SID + uint8_t adv_sid; + + /// Scan request notification enable + uint8_t scan_req_notif_en; + + /// Address resolution enabled + bool addr_resolution_en; + + /// Index of the RAL entry corresponding to peer + uint8_t ral_idx; +}; + +#if BLE_CONLESS_CTE_TX +/// Periodic advertising CTE parameters structure +struct lld_per_adv_cte_params +{ + /// CTE length (in 8us unit) + uint8_t cte_len; + /// CTE type (0: AOA | 1: AOD-1us | 2: AOD-2us) + uint8_t cte_type; + /// CTE count (number of CTEs to transmit in each periodic advertising interval, range 0x01 to 0x10) + uint8_t cte_count; + /// Length of switching pattern (number of antenna IDs in the pattern) + uint8_t switching_pattern_len; + /// Antenna IDs + uint8_t antenna_id[BLE_MAX_SW_PAT_LEN]; +}; +#endif // BLE_CONLESS_CTE_TX + +/// Periodic advertising parameters structure +struct lld_per_adv_params +{ + /// Periodic advertising interval expressed in units of 1.25 ms + uint16_t per_adv_intv; + + /// Periodic advertising properties + uint16_t per_adv_properties; + + /// Initial periodic advertising data buffer + uint16_t init_adv_data_buf; + + /// Initial periodic advertising data length + uint16_t init_adv_data_len; + + /// Periodic advertising offset in slots (625 us) + uint16_t per_adv_offset; + + /** + * Local address type + * 0x00 Public Device Address (default) + * 0x01 Random Device Address + * 0x02 Controller generates Resolvable Private Address based on the local IRK from resolving list. If resolving + * list contains no matching entry, use public address. + * 0x03 Controller generates Resolvable Private Address based on the local IRK from resolving list. If resolving + * list contains no matching entry, use random address from LE_Set_Random_Address. + */ + uint8_t own_addr_type; + + /// Periodic advertising Tx power + int8_t adv_tx_pwr; + + /// Secondary advertising PHY + uint8_t sec_adv_phy; + + #if BLE_CONLESS_CTE_TX + struct lld_per_adv_cte_params cte_params; + #endif // BLE_CONLESS_CTE_TX +}; + +/// Scanning parameters structure +struct lld_scan_params +{ + /// BD Address of the local device + struct bd_addr own_addr; + + /// Extended scanning + bool ext_scan; + + /// Scanning PHYs (bit0: 1M PHY, bit2: coded PHY) + uint8_t scan_phys; + + /// Scan interval in slots (625 us) + uint16_t intv_1m; // 1M PHY + uint16_t intv_c; // coded PHY + + /// Scan window in slots (625 us) + uint16_t win_1m; // 1M PHY + uint16_t win_c; // coded PHY + + /** + * Scanning type + * 0x00 Passive Scanning. No SCAN_REQ packets shall be sent (default) + * 0x01 Active scanning. SCAN_REQ packets may be sent. + * 0x02 - 0xFF Reserved for future use + */ + uint8_t type_1m; // 1M PHY + uint8_t type_c; // coded PHY + + /** + * Local address type + * 0x00 Public Device Address (default) + * 0x01 Random Device Address + * 0x02 Controller generates Resolvable Private Address based on the local IRK from resolving list. If resolving + * list contains no matching entry, use public address. + * 0x03 Controller generates Resolvable Private Address based on the local IRK from resolving list. If resolving + * list contains no matching entry, use random address from LE_Set_Random_Address. + */ + uint8_t own_addr_type; + + /** + * Scan filter policy: + * 0x00 Accept all + * - advertisement packets except directed advertising packets not addressed to this device (default) + * 0x01 Accept only + * - advertisement packets from devices where the advertisers address is in the White list. + * - Directed advertising packets which are not addressed for this device shall be ignored. + * 0x02 Accept all + * - undirected advertisement packets, and + * - directed advertising packets where the initiator address is a resolvable private address, and + * - directed advertising packets addressed to this device. + * 0x03 Accept all + * - advertisement packets from devices where the advertisers address is in the White list, and + * - directed advertising packets where the initiator address is a resolvable private address, and + * - directed advertising packets addressed to this device. + * 0x04 - 0xFF Reserved for future use. + */ + uint8_t filter_policy; + + /// Address resolution enabled + bool addr_resolution_en; + + /// Scan duration (N * 10 ms) | 0x0000: Scan continuously until explicitly disable + uint16_t duration; +}; + +#if BLE_CONLESS_CTE_RX +/// Sync CTE parameters structure +struct lld_sync_cte_params +{ + /// Sampling enable + uint8_t sampl_en; + /// Slot durations (1: 1us | 2: 2us) + uint8_t slot_dur; + /// Max sampled CTEs + uint8_t max_sampl_cte; + /// Length of switching pattern + uint8_t switching_pattern_len; + /// Antenna IDs + uint8_t antenna_id[BLE_MAX_SW_PAT_LEN]; +}; +#endif // BLE_CONLESS_CTE_RX + +/// Sync parameters structure +struct lld_sync_params +{ + // SyncInfo + const struct sync_info* p_syncinfo; + + /// The clock value of the reference time (in half-slot) + uint32_t base_cnt; + + /// The fine timer value the reference time (in half-us) + uint16_t fine_cnt; + + /// The bit rate of periodic advertising (@see enum lld_rate) + uint8_t rate; + + /// Advertising SID + uint8_t adv_sid; + + /// max Skip after receive + uint16_t skip; + + /// Sync timeout (Time=N*10ms) + uint16_t sync_to; + + /// Additional drift to consider on given time reference (in half-us) + uint16_t add_drift; + + /// Specifies whether to only synchronize to periodic advertising with certain types of CTE (@see enum sync_cte_type) + uint8_t sync_cte_type; +}; + +/// Initiating parameters PHY sub-structure +struct lld_init_phy_params +{ + /// Scan interval in slots (625 us) + uint16_t intv; + + /// Scan window in slots (625 us) + uint16_t win; + + /// Connection interval (in units of 1,25 ms, i.e. 2 slots) + uint16_t con_intv; + + /// Connection offset in slots (625 us) + uint16_t con_offset; + + /// Connection latency + uint16_t con_latency; + + /// Connection supervision timeout in 10ms (N * 10ms) + uint16_t superv_to; +}; + +/// Initiating parameters structure +struct lld_init_params +{ + /// BD Address of the local device + struct bd_addr own_addr; + + /// BD Address of the peer device (only if White List is not used) + struct bd_addr peer_addr; + + /// Channel map to use for the connection + struct le_chnl_map ch_map; + + /// Extended initiating + bool ext_init; + + /// Scanning PHYs (bit0: 1M PHY, bit1: 2M PHY, bit2: coded PHY) + uint8_t init_phys; + + /// Activity identifier + uint8_t act_id; + + /** + * Local address type + * 0x00 Public Device Address (default) + * 0x01 Random Device Address + * 0x02 To generate RPA from resolving list. If no matching entry, use public address. + * 0x03 To generate RPA from resolving list. If no matching entry, use random address. + */ + uint8_t own_addr_type; + + /** + * Peer address type (only if White List is not used) + * 0x00 Public Device Address + * 0x01 Random Device Address + * 0x02 - 0xFF Reserved for future use + */ + uint8_t peer_addr_type; + + /** + * Initiator filter policy: + * 0x00 White list is not used to determine which advertiser to connect to. Peer_Address_Type and Peer_Address + * shall be used. + * 0x01 White list is used to determine which advertiser to connect to. Peer_Address_Type and Peer_Address shall + * be ignored. + * 0x02 - 0xFF Reserved for future use. + */ + uint8_t filter_policy; + + /** + * Parameters for Initiating PHY(s) + * The parameters are ordered in the same order as the set bits in the init_phys parameter, starting from bit 0. + * The number of elements is determined by the number of bits set in the Initiating_PHYs parameter. + */ + struct lld_init_phy_params phy[MAX_INIT_PHYS]; + + /// Address resolution enabled + bool addr_resolution_en; +}; + +/// Connection parameters structure +struct lld_con_params +{ + /// Access address + struct access_addr aa; + + /// CRC init + struct crc_init crcinit; + + /// Window size (in units of 1,25 ms, i.e. 2 slots) + uint8_t winsize; + + /// Window offset (in units of 1,25 ms, i.e. 2 slots) + uint16_t winoffset; + + /// Interval (in units of 1,25 ms, i.e. 2 slots) + uint16_t interval; + + /// Latency + uint16_t latency; + + /// Timeout (in units of 10 ms, i.e. 16 slots) + uint16_t timeout; + + /// Channel mapping + struct le_chnl_map chm; + + /// Hopping increment (random value in the range of 5 to 16) + uint8_t hop_inc; + + /** + * Master Sleep clock accuracy (only for slave) + * 0 251 ppm to 500 ppm + * 1 151 ppm to 250 ppm + * 2 101 ppm to 150 ppm + * 3 76 ppm to 100 ppm + * 4 51 ppm to 75 ppm + * 5 31 ppm to 50 ppm + * 6 21 ppm to 30 ppm + * 7 0 ppm to 20 ppm + */ + uint8_t master_sca; + + /// CONNECT_REQ packet fine timer count (in half-us) + uint16_t fine_cnt_rxsync; + + /// CONNECT_REQ packet base timer count (timestamp, in half-slots) + uint32_t base_cnt_rxsync; + + /// First anchor point timestamp (in half-slots, master only) + uint32_t first_anchor_ts; + + /// Role (0: Master | 1: Slave) + uint8_t role; + + /// Connection transmit/receive rate (@see enum lld_rate) + uint8_t rate; + + /// Indicates whether channel selection algorithm #2 will be used or not + bool ch_sel_2; + + /// Indicates whether the AUX_CONNECT_REQ PDU was used or not (true for AUX_CONNECT_REQ, false for CONNECT_IND) + bool aux_connect_req; +}; + +#if (BLE_ISO_MODE_0) +/// Audio parameters structure +struct lld_con_audio_params +{ + /// Reception Data Path : pointer must be filled + const struct data_path_itf* rx_dp; + /// Transmission Data Path : pointer must be filled + const struct data_path_itf* tx_dp; + /// Configure transmitter size in bytes + uint8_t tx_size; + /// Configure receiver size in bytes + uint8_t rx_size; + /// Salve audio source enabled + bool slv_src_enable; +}; +#endif //(BLE_ISO_MODE_0) + +/// Test mode parameters structure +struct lld_test_params +{ + /// Type (0: RX | 1: TX) + uint8_t type; + + /// RF channel, N = (F - 2402) / 2 + uint8_t channel; + + /// Length of test data + uint8_t data_len; + + /** + * Packet payload + * 0x00 PRBS9 sequence "11111111100000111101" (in transmission order) as described in [Vol 6] Part F, Section 4.1.5 + * 0x01 Repeated "11110000" (in transmission order) sequence as described in [Vol 6] Part F, Section 4.1.5 + * 0x02 Repeated "10101010" (in transmission order) sequence as described in [Vol 6] Part F, Section 4.1.5 + * 0x03 PRBS15 sequence as described in [Vol 6] Part F, Section 4.1.5 + * 0x04 Repeated "11111111" (in transmission order) sequence + * 0x05 Repeated "00000000" (in transmission order) sequence + * 0x06 Repeated "00001111" (in transmission order) sequence + * 0x07 Repeated "01010101" (in transmission order) sequence + * 0x08-0xFF Reserved for future use + */ + uint8_t payload; + + /** + * Tx/Rx PHY + * For Tx PHY: + * 0x00 Reserved for future use + * 0x01 LE 1M PHY + * 0x02 LE 2M PHY + * 0x03 LE Coded PHY with S=8 data coding + * 0x04 LE Coded PHY with S=2 data coding + * 0x05-0xFF Reserved for future use + * For Rx PHY: + * 0x00 Reserved for future use + * 0x01 LE 1M PHY + * 0x02 LE 2M PHY + * 0x03 LE Coded PHY + * 0x04-0xFF Reserved for future use + */ + uint8_t phy; + + /** + * CTE length + * 0x00 No Constant Tone Extension + * 0x02 - 0x14 Length of the Constant Tone Extension in 8 us units + * All other values Reserved for future use + */ + uint8_t cte_len; + + /** + * CTE type + * 0x00 AoA Constant Tone Extension + * 0x01 AoD Constant Tone Extension with 1 us slots + * 0x02 AoD Constant Tone Extension with 2 us slots + * All other values Reserved for future use + */ + uint8_t cte_type; + + /** + * Slot durations + * 0x01 Switching and sampling slots are 1 us each + * 0x02 Switching and sampling slots are 2 us each + * All other values Reserved for future use + */ + uint8_t slot_dur; + + /** + * Length of switching pattern + * 0x02 - 0x4B The number of Antenna IDs in the pattern + * All other values Reserved for future use + */ + uint8_t switching_pattern_len; + + /// Antenna IDs + uint8_t antenna_id[BLE_MAX_SW_PAT_LEN]; +}; + +/* + * EXPORTED VARIABLES DECALRATION + **************************************************************************************** + */ + +/* + * FUNCTIONS DECLARATION + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Initialize the LLD module + * + * @param[in] init_type Type of initialization (@see enum rwip_init_type) + **************************************************************************************** + */ +void lld_init(uint8_t init_type); + +/** + * *************************************************************************************** + * @brief Read BLE clock + * + * @return Clock value (in half-slots, i.e. units of 312.5 us) + **************************************************************************************** + */ +uint32_t lld_read_clock(void); + +/** + **************************************************************************************** + * @brief Get local SCA + * + * @return local_sca Local SCA, physical low power clock accuracy (@see enum SCA) + **************************************************************************************** + */ +uint8_t lld_local_sca_get(void); + + +/** + **************************************************************************************** + * @brief Get channel assessment + * + * @return Pointer to channel assessment data + **************************************************************************************** + */ +struct lld_ch_assess_data* lld_ch_assess_data_get(void); + +/** + * *************************************************************************************** + * @brief Renew the resolvable private addresses + **************************************************************************************** + */ +void lld_rpa_renew(void); + +/** + **************************************************************************************** + * @brief Add a device to white list + * + * @param[in] position Position of the device in the list + * @param[in] bd_addr BD Address + * @param[in] bd_addr_type BD Address type (0: public | 1: random | 0xFF: anonymous adv) + **************************************************************************************** + */ +void lld_white_list_add(uint8_t position, struct bd_addr *bd_addr, uint8_t bd_addr_type); + +/** + **************************************************************************************** + * @brief Remove a device from white list + * + * @param[in] position Position of the device in the list + * @param[in] bd_addr BD Address + * @param[in] bd_addr_type BD Address type (0: public | 1: random | 0xFF: anonymous adv) + **************************************************************************************** + */ +void lld_white_list_rem(uint8_t position, struct bd_addr *bd_addr, uint8_t bd_addr_type); + +/** + **************************************************************************************** + * @brief Add a device to periodic advertiser list + * + * @param[in] position Position of the device in the list + * @param[in] bd_addr BD Address + * @param[in] bd_addr_type BD Address type (0: public | 1: random) + * @param[in] adv_sid Advertising Set ID + **************************************************************************************** + */ +void lld_per_adv_list_add(uint8_t position, struct bd_addr *bd_addr, uint8_t bd_addr_type, uint8_t adv_sid); + +/** + **************************************************************************************** + * @brief Remove a device from periodic advertiser list + * + * @param[in] position Position of the device in the list + * @param[in] bd_addr BD Address + * @param[in] bd_addr_type BD Address type (0: public | 1: random) + * @param[in] adv_sids Bit field of advertising Set IDs to remove, 1 bit per ADV_SID + **************************************************************************************** + */ +void lld_per_adv_list_rem(uint8_t position, struct bd_addr *bd_addr, uint8_t bd_addr_type, uint16_t adv_sids); + +/** + **************************************************************************************** + * @brief Clear resolving list + **************************************************************************************** + */ +void lld_res_list_clear(void); + +/** + **************************************************************************************** + * @brief Add a device to resolving list + * + * @param[in] position Position in RAL + * @param[in] bd_addr Peer's BD Address + * @param[in] peer_irk Peer identification resolving key + * @param[in] localr_irk Local identification resolving key + * @param[in] bd_addr_type Peer's BD Address type (0: public | 1: random) + * @param[in] connected True: device is connected | false: not connected + * @param[in] in_wl True: device is in white list | false: not in white list + **************************************************************************************** + */ +void lld_res_list_add(uint8_t position, struct bd_addr const *bd_addr, struct irk const *peer_irk, struct irk const *local_irk, uint8_t bd_addr_type, bool connected, bool in_wl); + +/** + **************************************************************************************** + * @brief Remove a device from resolving list + * + * @param[in] position Position in RAL + * + * @return status 0: success | 1-255: error + **************************************************************************************** + */ +void lld_res_list_rem(uint8_t position); + +/** + **************************************************************************************** + * @brief Update status of a device privacy: network privacy or device privacy + * + * @param[in] position Position in RAL + * @param[in] privacy_mode 0: network privacy / 1: device privacy + **************************************************************************************** + */ +void lld_res_list_priv_mode_update(uint8_t position, uint8_t privacy_mode); + +/** + **************************************************************************************** + * @brief Update status of a device connected or disconnected + * + * @param[in] position Position in RAL + * @param[in] connected True: device connected / False: device disconnected + **************************************************************************************** + */ +void lld_res_list_peer_update(uint8_t position, bool connected); + +/** + **************************************************************************************** + * @brief Get the current peer resolvable address used for a peer device + * + * @param[in] position Position in RAL + * @param[out] peer_res_addr Peer resolvable address + * @return status 0: success | 1-255: error + **************************************************************************************** + */ +uint8_t lld_res_list_peer_rpa_get(uint8_t position, struct bd_addr *peer_res_addr); + +/** + **************************************************************************************** + * @brief Get the current local resolvable address used for a peer device + * + * @param[in] position Position in RAL + * @param[out] local_res_addr Local resolvable address + * @return status 0: success | 1-255: error + **************************************************************************************** + */ +uint8_t lld_res_list_local_rpa_get(uint8_t position, struct bd_addr *local_res_addr); + + +#if (BLE_BROADCASTER) +/** + **************************************************************************************** + * @brief Start Advertising + * + * @param[in] act_id Activity identifier + * @param[in] params Pointer to extended advertising parameters structure + * + * @return status 0: success | 1-255: error (BLE error code) + **************************************************************************************** + */ +uint8_t lld_adv_start(uint8_t act_id, struct lld_adv_params* params); + +/** + **************************************************************************************** + * @brief Stop Advertising + * + * @param[in] act_id Activity identifier + * + * @return status 0: success | 1-255: error + **************************************************************************************** + */ +uint8_t lld_adv_stop(uint8_t act_id); + +/** + **************************************************************************************** + * @brief Update Advertising data + * + * Note: the Host can only update the advertising data less than 252 bytes (see HCI:7.8.54) + * + * @param[in] act_id Activity identifier + * @param[in] len Length of the data, in range [0:252] + * @param[in] buffer EM buffer containing the data + **************************************************************************************** + */ +void lld_adv_adv_data_update(uint8_t act_id, uint8_t len, uint16_t buffer); + +/** + **************************************************************************************** + * @brief Update advertising duration + * + * @param[in] act_id Activity identifier + * @param[in] duration Advertising duration (N * 10 ms) | 0x0000: infinite + **************************************************************************************** + */ +void lld_adv_duration_update(uint8_t act_id, uint16_t duration); + +/** + **************************************************************************************** + * @brief Update advertising random address + * + * @param[in] act_id Activity identifier + * @param[in] addr Random address + **************************************************************************************** + */ +void lld_adv_rand_addr_update(uint8_t act_id, struct bd_addr addr); + +/** + **************************************************************************************** + * @brief Reset the event count, update the duration and the maximum number of extended advertising events + * + * @param[in] act_id Activity identifier + * @param[in] duration Advertising duration (N * 10 ms) | 0x0000: infinite + * @param[in] max_ext_adv_evt Maximum number of extended advertising events + **************************************************************************************** + */ +void lld_adv_restart(uint8_t act_id, uint16_t duration, uint8_t max_ext_adv_evt); + +/** + **************************************************************************************** + * @brief Update Scan response data + * + * Note: the Host may can only update the advertising data less than 252 bytes (see HCI:7.8.55) + * + * @param[in] act_id Activity identifier + * @param[in] len Length of the data, in range [0:252] + * @param[in] buffer EM buffer containing the data + **************************************************************************************** + */ +void lld_adv_scan_rsp_data_update(uint8_t act_id, uint8_t len, uint16_t buffer); + +/** + **************************************************************************************** + * @brief Read the TX power used for advertising + * + * @param[in] act_id Activity identifier + * + * @return Used TX power in dBm, signed integer, range between -70dBm and 20dBm. + **************************************************************************************** + */ +uint8_t lld_adv_tx_pwr_get(uint8_t act_id); + +/** + **************************************************************************************** + * @brief Start Periodic advertising + * + * @param[in] act_id Activity identifier + * @param[in] params Pointer to extended advertising parameters structure + * + * @return status 0: success | 1-255: error (BLE error code) + **************************************************************************************** + */ +uint8_t lld_per_adv_start(uint8_t act_id, struct lld_per_adv_params* params); + +/** + **************************************************************************************** + * @brief Stop Periodic advertising + * + * @param[in] act_id Activity identifier + * + * @return status 0: success | 1-255: error + **************************************************************************************** + */ +uint8_t lld_per_adv_stop(uint8_t act_id); + +/** + **************************************************************************************** + * @brief Update Periodic advertising data + * + * Note: the Host may can only update the advertising data less than 252 bytes (see HCI:7.8.54) + * + * @param[in] act_id Activity identifier + * @param[in] len Length of the data, in range [0:252] + * @param[in] buffer EM buffer containing the data + **************************************************************************************** + */ +void lld_per_adv_data_update(uint8_t act_id, uint8_t len, uint16_t buffer); + + +/** + **************************************************************************************** + * @brief Initiate periodic advertising channel map update + * + * @param[in] act_id Activity ID + * @param[in] map New channel map to be applied + * + * @return status 0: success | 1-255: error + **************************************************************************************** + */ +uint8_t lld_per_adv_ch_map_update(uint8_t act_id, struct le_chnl_map *map); + +/** + **************************************************************************************** + * @brief Get info from a periodic advertiser + * + * @param[in] act_id Activity ID + * @param[out] phy Periodic advertising PHY (@see enum lld_rate) + * @param[out] intv Periodic advertising interval in units of 1.25 ms + * @param[out] aa Periodic advertising Access Address + * @param[out] crcinit Periodic advertising CRC Initialization value + * @param[out] sync_ind_ts Timestamp of the AUX_SYNC_IND packet (in 312.5 us half-slots) + * @param[out] pa_evt_cnt Corresponding paEventCounter value (in half-us) + * @param[out] map Corresponding channel map + * + * @return status 0: success | 1-255: error + **************************************************************************************** + */ +uint8_t lld_per_adv_info_get(uint8_t act_id, uint8_t* phy, uint16_t* intv, struct access_addr* aa, struct crc_init* crcinit, uint32_t* sync_ind_ts, uint16_t* pa_evt_cnt, struct le_chnl_map *map); + +/** + **************************************************************************************** + * @brief Set the connectionless LLD channel map + * + * @param[in] map New channel map for connectionless activities + **************************************************************************************** + */ +void lld_ch_map_set(const struct le_chnl_map *map); + +/** + **************************************************************************************** + * @brief Update extended advertising sync info + * + * @param[in] act_id Extended advertising activity identifier + * @param[in] per_adv_id Periodic advertising activity identifier + * @param[in] per_adv_interval Periodic advertising interval + **************************************************************************************** + */ +void lld_adv_sync_info_update(uint8_t act_id, uint8_t per_adv_id, uint16_t per_adv_interval); + +#if BLE_CONLESS_CTE_TX +/** + **************************************************************************************** + * @brief Start Periodic advertising CTE Tx + * + * @param[in] act_id Activity identifier + * @param[in] params Pointer to periodic advertising CTE parameters structure + * + * @return status 0: success | 1-255: error (BLE error code) + **************************************************************************************** + */ +uint8_t lld_per_adv_cte_start(uint8_t act_id, struct lld_per_adv_cte_params* params); + +/** + **************************************************************************************** + * @brief Stop Periodic advertising CTE Tx + * + * @param[in] act_id Activity identifier + * + * @return status 0: success | 1-255: error (BLE error code) + **************************************************************************************** + */ +uint8_t lld_per_adv_cte_stop(uint8_t act_id); +#endif // BLE_CONLESS_CTE_TX +#endif // (BLE_BROADCASTER) + +#if (BLE_OBSERVER) +/** + **************************************************************************************** + * @brief Start Scanning + * + * @param[in] act_id Activitiy ID + * @param[in] params Pointer to Scanning parameters structure + * + * @return status 0: success | 1-255: error + **************************************************************************************** + */ +uint8_t lld_scan_start(uint8_t act_id, struct lld_scan_params* params); + +/** + **************************************************************************************** + * @brief Stop Scanning + * + * @return status 0: success | 1-255: error + **************************************************************************************** + */ +uint8_t lld_scan_stop(void); + +/** + **************************************************************************************** + * @brief Update scanning parameters + * + * @param[in] duration Scan duration (N * 10 ms) | 0x0000: Scan continuously until explicitly disable + * @param[in] period Scan period (N * 1.28 sec) | 0x0000: Periodic scanning disabled + * @param[in] bd_addr new random address | NULL: no update + **************************************************************************************** + */ +uint8_t lld_scan_params_update(uint16_t duration, uint16_t period, struct bd_addr *bd_addr); + +/** + **************************************************************************************** + * @brief Restart Scanning + * + * @return status 0: success | 1-255: error + **************************************************************************************** + */ +uint8_t lld_scan_restart(void); + +/** + **************************************************************************************** + * @brief Start Periodic Advertising RX (Create Sync) + * + * @param[in] act_id Activity ID + * @param[in] options Sync options (@see enum per_sync_opt) + * @param[in] adv_sid Advertising SID + * @param[in] adv_addr_type Advertising address type + * @param[in] adv_addr Advertiser address + * + * @return status 0: success | 1-255: error (BLE error code) + **************************************************************************************** + */ +uint8_t lld_scan_create_sync(uint8_t act_id, uint8_t options, uint8_t adv_sid, uint8_t adv_addr_type, struct bd_addr * adv_addr); + +/** + **************************************************************************************** + * @brief Stop Create Sync for Periodic Scan Rx (Cancel Sync) + * + * @param[in] act_id Activity ID + * + * @return status 0: success | 1-255: error (BLE error code) + **************************************************************************************** + */ +uint8_t lld_scan_create_sync_cancel(uint8_t act_id); + +/** + **************************************************************************************** + * @brief Start Periodic Advertising Rx + * + * @param[in] act_id Activity ID + * @param[in] params Pointer to Scanning parameters structure + * + * @return status 0: success | 1-255: error (BLE error code) +**************************************************************************************** +*/ +uint8_t lld_sync_start(uint8_t act_id, struct lld_sync_params* params); + +/** + **************************************************************************************** + * @brief Update channel map on a periodic advertiser + * + * @param[in] act_id Activity ID + * @param[in] map Pointer to the new channel map to be applied + * @param[in] instant Instant when the new channel map has to be applied + * + * @return status 0: success | 1-255: error + **************************************************************************************** + */ +uint8_t lld_sync_ch_map_update(uint8_t act_id, struct le_chnl_map *map, uint16_t instant); + +/** + **************************************************************************************** + * @brief Stop Periodic Advertising RX (Terminate Sync) + * + * @param[in] act_id Activity ID + * + * @return status 0: success | 1-255: error (BLE error code) + **************************************************************************************** + */ +uint8_t lld_sync_stop(uint8_t act_id); + +#if BLE_CONLESS_CTE_RX +/** + **************************************************************************************** + * @brief Start Periodic advertising IQ sampling + * + * @param[in] act_id Activity identifier + * @param[in] params Pointer to periodic advertising CTE parameters structure + * + * @return status 0: success | 1-255: error (BLE error code) + **************************************************************************************** + */ +uint8_t lld_sync_cte_start(uint8_t act_id, struct lld_sync_cte_params* params); + +/** + **************************************************************************************** + * @brief Stop Periodic advertising IQ sampling + * + * @param[in] act_id Activity identifier + * + * @return status 0: success | 1-255: error (BLE error code) + **************************************************************************************** + */ +uint8_t lld_sync_cte_stop(uint8_t act_id); +#endif // BLE_CONLESS_CTE_RX + +#endif // (BLE_OBSERVER) + + + +#if (BLE_CENTRAL) +/** + **************************************************************************************** + * @brief Start Initiating + * + * @param[in] params Pointer to Initiating parameters structure + * + * @return status 0: success | 1-255: error (BLE error code) + **************************************************************************************** + */ +uint8_t lld_init_start(struct lld_init_params* params); + +/** + **************************************************************************************** + * @brief Stop Initiating + * + * @return status 0: success | 1-255: error + **************************************************************************************** + */ +uint8_t lld_init_stop(void); + +#endif // (BLE_CENTRAL) + + +#if (BLE_CENTRAL || BLE_PERIPHERAL) +/** + **************************************************************************************** + * @brief Start link + * + * @param[in] link_id Link identifier + * @param[in] params Pointer to Connection parameters structure + * + * @return status 0: success | 1-255: error + **************************************************************************************** + */ +uint8_t lld_con_start(uint8_t link_id, struct lld_con_params* params); + +/** + **************************************************************************************** + * @brief Stop link + * + * @param[in] link_id Link identifier + * @param[in] immediate Immediate execution of the event stop + * + * @return status 0: success | 1-255: error + **************************************************************************************** + */ +uint8_t lld_con_stop(uint8_t link_id, bool immediate); + +/** + **************************************************************************************** + * @brief Send an LLCP packet + * + * @param[in] link_id Link identifier + * @param[in] buf_elt Buffer element of the LLCP to send + * + * @return status 0: success | 1-255: error + **************************************************************************************** + */ +uint8_t lld_con_llcp_tx(uint8_t link_id, struct ble_em_llcp_buf_elt* buf_elt); + +/** + **************************************************************************************** + * @brief Send an ACL packet + * + * @param[in] link_id Link identifier + * @param[in] buf_elt Buffer element of the data to send + * + * @return status 0: success | 1-255: error + **************************************************************************************** + */ +uint8_t lld_con_data_tx(uint8_t link_id, struct ble_em_acl_buf_elt* buf_elt); + +/** + **************************************************************************************** + * @brief Set ACL data flow + * + * @param[in] link_id Link identifier + * @param[in] enable True: data flow ON / False: data flow OFF + * + * @return status 0: success | 1-255: error + **************************************************************************************** + */ +uint8_t lld_con_data_flow_set(uint8_t link_id, bool enable); + +/** + **************************************************************************************** + * @brief Update link parameters + * + * @param[in] link_id Link identifier + * @param[in] win_size Window size (in units of 1,25 ms, i.e. 2 slots) + * @param[in] win_off Window offset (in units of 1,25 ms, i.e. 2 slots) + * @param[in] interval Interval (in units of 1,25 ms, i.e. 2 slots) + * @param[in] latency Slave latency + * @param[in] timeout Timeout (in units of 10 ms, i.e. 16 slots) + * @param[in] instant Instant when the new parameters have to be applied (when connection event counter equals the instant) + * + * @return status 0: success | 1-255: error + **************************************************************************************** + */ +uint8_t lld_con_param_update(uint8_t link_id, uint8_t win_size, uint16_t win_off, uint16_t interval, uint16_t latency, + uint16_t timeout, uint16_t instant); + +/** + **************************************************************************************** + * @brief Update channel map + * + * @param[in] link_id Link identifier + * @param[in] map Pointer to the new channel map to be applied + * @param[in] instant Instant when the new channel map has to be applied (when connection event counter equals the instant) + * + * @return status 0: success | 1-255: error + **************************************************************************************** + */ +uint8_t lld_con_ch_map_update(uint8_t link_id, struct le_chnl_map *map, uint16_t instant); + +/** + **************************************************************************************** + * @brief Update data length + * + * @param[in] link_id Link identifier + * @param[in] eff_tx_time Maximum effective transmit time (in us) + * @param[in] eff_tx_octets Maximum effective transmit size (in bytes) + * @param[in] eff_rx_time Maximum effective receive time (in us) + * @param[in] eff_rx_octets Maximum effective receive size (in bytes) + * + * @return status 0: success | 1-255: error + **************************************************************************************** + */ +uint8_t lld_con_data_len_update(uint8_t link_id, uint16_t eff_tx_time, uint16_t eff_tx_octets, uint16_t eff_rx_time, uint16_t eff_rx_octets); + +/** + **************************************************************************************** + * @brief Update PHYs + * + * @param[in] link_id Link identifier + * @param[in] tx_rate Transmit rate to be set (@see enum lld_rate) + * @param[in] rx_rate Receive rate to be set (@see enum lld_rate) + * @param[in] instant Instant where the new rates have to be applied (when connection event counter equals the instant) + * + * @return status 0: success | 1-255: error + **************************************************************************************** + */ +uint8_t lld_con_phys_update(uint8_t link_id, uint8_t tx_rate, uint8_t rx_rate, uint16_t instant); + +/** + **************************************************************************************** + * @brief Update TX length as per the new connection interval + * + * @param[in] link_id Link identifier + * @param[in] interval Interval (in units of 1,25 ms, i.e. 2 slots) + * + * @return status 0: success | 1-255: error + **************************************************************************************** + */ +uint8_t lld_con_tx_len_update_for_intv(uint8_t link_id, uint16_t interval); + +/** + **************************************************************************************** + * @brief Update TX length as per the new TX rate + * + * @param[in] link_id Link identifier + * @param[in] tx_rate Transmit rate to be set (@see enum lld_rate) + * + * @return status 0: success | 1-255: error + **************************************************************************************** + */ +uint8_t lld_con_tx_len_update_for_rate(uint8_t link_id, uint8_t tx_rate); + +/** + **************************************************************************************** + * @brief Gets current event counter + * + * @param[in] link_id Link identifier + * + * @return Current event counter value + **************************************************************************************** + */ +uint16_t lld_con_event_counter_get(uint8_t link_id); + +/** + **************************************************************************************** + * Compute offset between a connection instant and another activity event with provided + * interval reference that follows + * + * @param[in] link_id Link Identifier + * @param[in] evt_cnt Reference connection event counter + * @param[in] interval Activity interval (1.25ms unit) + * @param[in] act_offset Activity Offset (625us unit) + * + * @return Computed offset with connection interval and provided interval (us unit) + **************************************************************************************** + */ +int32_t lld_con_activity_offset_compute(uint8_t link_id, uint16_t evt_cnt, uint16_t interval, uint16_t act_offset); + +/** + * Compute planning activity offset of the activity to create according to a specific offset range in us. + * + * @param[in] link_id Link Identifier + * @param[in] evt_cnt Reference connection event counter + * @param[in] interval Activity interval (1.25ms unit) + * @param[in|out] offset_min New activity minimum offset in us after connection reference + * @param[in|out] offset_max New activity maximum offset in us after connection reference + * + * @return Computed Activity offset in slots + */ +uint16_t lld_con_activity_act_offset_compute(uint8_t link_id, uint16_t evt_cnt, uint16_t interval, + uint32_t *offset_min, uint32_t *offset_max); + +/** + **************************************************************************************** + * @brief Set encryption mode in TX direction + * + * @param[in] link_id Link identifier + * @param[in] enable false: disabled | true: enabled + **************************************************************************************** + */ +void lld_con_tx_enc(uint8_t link_id, bool enable); + +/** + **************************************************************************************** + * @brief Set encryption mode in RX direction + * + * @param[in] link_id Link identifier + * @param[in] enable false: disabled | true: enabled + **************************************************************************************** + */ +void lld_con_rx_enc(uint8_t link_id, bool enable); + +/** + **************************************************************************************** + * @brief Load encryption Key + * + * @param[in] link_id Link identifier + * @param[in] key Encryption key + * @param[in] iv Initialization Vector (for AES encryption only) + * + * @return status 0: success | 1-255: error + **************************************************************************************** + */ +void lld_con_enc_key_load(uint8_t link_id, struct ltk *key, struct initialization_vector *iv); + +/** + **************************************************************************************** + * @brief Get the current TX power + * + * @param[in] link_id Link identifier + * @param[in] modulation Modulation (1:GFSK | 2:DQPSK | 3:8DPSK) + * + * @return Current TX power in dBm + **************************************************************************************** + */ +uint8_t lld_con_current_tx_power_get(uint8_t link_id, uint8_t mod); + +/** + **************************************************************************************** + * @brief Get the received RSSI + * + * @param[in] link_id Link identifier + * + * @return rssi RSSI in dBm + **************************************************************************************** + */ +int8_t lld_con_rssi_get(uint8_t link_id); + +/** + **************************************************************************************** + * @brief Get the connection offset + * + * @param[in] link_id Link identifier + * + * @return con_offset Connection offset in slots (625 us) + **************************************************************************************** + */ +uint16_t lld_con_offset_get(uint8_t link_id); + +/** + **************************************************************************************** + * @brief Set peer SCA + * + * @param[in] link_id Link identifier + * @param[in] peer_sca Peer SCA (@see enum SCA) + **************************************************************************************** + */ +void lld_con_peer_sca_set(uint8_t link_id, uint8_t peer_sca); + +/** + **************************************************************************************** + * @brief Get connection event time + * + * @param[in] link_id Link identifier + * @param[out] con_evt_cnt Connection event counter + * @param[out] con_evt_time_hs Time of the connection event, in 312.5 us half-slots + * @param[out] con_evt_time_hus Time of the connection event, in half-us + * + * @return status 0: success | 1-255: error + **************************************************************************************** + */ +uint8_t lld_con_time_get(uint8_t link_id, uint16_t* con_evt_cnt, uint32_t* con_evt_time_hs, uint16_t* con_evt_time_hus); +#endif // (BLE_CENTRAL || BLE_PERIPHERAL) + +#if (BLE_PERIPHERAL) +/** + **************************************************************************************** + * @brief Set the preferred slave latency + * + * @param[in] link_id Link identifier + * @param[in] latency Preferred slave latency (in number of connection events) + **************************************************************************************** + */ +void lld_con_pref_slave_latency_set(uint8_t link_id, uint16_t latency); + +/** + **************************************************************************************** + * @brief Set the preferred slave event duration + * + * @param[in] link_id Link identifier + * @param[in] Duration Preferred slave event duration (N * 0.625 ms) + **************************************************************************************** + */ +void lld_con_pref_slave_evt_dur_set(uint8_t link_id, uint16_t duration, bool single_tx); +#endif // (BLE_PERIPHERAL) + +#if (BLE_ISO_MODE_0) + +/** + **************************************************************************************** + * @brief Inform that Isochronous mode is set-up and mic less encryption is required + * + * @param[in] link_id Link identifier + **************************************************************************************** + */ +void lld_con_audio_use_mic_less(uint8_t link_id); + +/** + **************************************************************************************** + * @brief Start audio + * + * @param[in] link_id Link identifier + * @param[in] iso_channel Isochronous channel + * @param[in] params Configuration parameters + * + * @return Executions status + **************************************************************************************** + */ +uint8_t lld_con_audio_start(uint8_t link_id, uint8_t iso_channel, struct lld_con_audio_params* params); + +/** + **************************************************************************************** + * @brief Stop audio + * + * @param[in] link_id Link identifier + * + * @return Excecutions status + **************************************************************************************** + */ +uint8_t lld_con_audio_stop(uint8_t link_id); + +#endif //(BLE_ISO_MODE_0) + +#if BLE_CON_CTE_REQ +/** + **************************************************************************************** + * @brief Enable reception of CTE on connection + * + * @param[in] link_id Link identifier + * @param[in] slot_dur Slot durations (1: 1us | 2: 2us) + * @param[in] switching_pattern_len Length of switching pattern (number of antenna IDs in the pattern) + ***************************************************************************************** + */ +void lld_con_cte_rx_en(uint8_t link_id, uint8_t slot_dur, uint8_t switching_pattern_len); + +/** + **************************************************************************************** + * @brief Disable reception of CTE on connection + * + * @param[in] link_id Link identifier + ***************************************************************************************** + */ +void lld_con_cte_rx_dis(uint8_t link_id); +#endif // BLE_CON_CTE_REQ + +#if BLE_CON_CTE_RSP +/** + **************************************************************************************** + * @brief Configure antenna switching for connection CTE Tx + * + * @param[in] link_id Link identifier + * @param[in] switching_pattern_len Length of switching pattern (number of antenna IDs in the pattern) + * @param[in] cte_types CTE types (bit0: AOA | bit1: AOD-1us | bit2: AOD-2us) + ***************************************************************************************** + */ +void lld_con_cte_tx_ant_switch_config(uint8_t link_id, uint8_t switching_pattern_len, uint8_t cte_types); + +/** + **************************************************************************************** + * @brief Set connection CTE Tx parameters + * + * @param[in] link_id Link identifier + * @param[in] cte_len CTE length in 8 us units (0: No CTE | Range: 0x02 - 0x14) + * @param[in] cte_type CTE type (0x00: AOA | 0x01: AOD-1us | 0x02: AOD-2us) + ***************************************************************************************** + */ +void lld_con_cte_tx_param_set(uint8_t link_id, uint8_t cte_len, uint8_t cte_type); +#endif // BLE_CON_CTE_RSP + +/** + **************************************************************************************** + * @brief Start test mode (RX or TX) + * + * @param[in] params Pointer to Scanning parameters structure + * + * @return status 0: success | 1-255: error + **************************************************************************************** + */ +uint8_t lld_test_start(struct lld_test_params* params); + +/** + **************************************************************************************** + * @brief Stop test mode + * + * @return status 0: success | 1-255: error + **************************************************************************************** + */ +uint8_t lld_test_stop(void); + +#if (RW_DEBUG) +/** + **************************************************************************************** + * @brief Read BLE core register + * + * @param[in] reg_addr Register address + * + * @return reg_value Register value + **************************************************************************************** + */ +uint16_t lld_reg_rd(uint16_t reg_addr); + +/** + **************************************************************************************** + * @brief Write BLE core register + * + * @param[in] reg_addr Register address + * @param[in] reg_value Register value + **************************************************************************************** + */ +void lld_reg_wr(uint16_t reg_addr, uint16_t reg_value); +#endif // (RW_DEBUG) + +/** + **************************************************************************************** + * @brief Get connection synchronization information + * + * @param[in] link_id Link identifier + * @param[in] ref_con_evt_cnt Reference connection event count + * @param[in] ref_con_evt_ts Reference connection event timestamp (in 312.5 us half-slots) + * @param[in] ref_con_evt_bit_off Reference connection event bit offset (in half-us) + * + * @return status 0: success | 1-255: error + **************************************************************************************** + */ +uint8_t lld_con_sync_info_get(uint8_t link_id, uint16_t* ref_con_evt_cnt, uint32_t* ref_con_evt_ts, uint16_t* ref_con_evt_bit_off); + +/** + **************************************************************************************** + * @brief Get sync info from a periodic sync activity + * + * @param[in] act_id Activity ID + * @param[out] phy Periodic advertising PHY (@see enum lld_rate) + * @param[out] intv Periodic advertising interval in units of 1.25 ms + * @param[out] aa Periodic advertising Access Address + * @param[out] crcinit Periodic advertising CRC Initialization value + * @param[out] sync_ind_ts Timestamp of the AUX_SYNC_IND packet (in 312.5 us half-slots) + * @param[out] sync_ind_bit_off Bit offset of the AUX_SYNC_IND packet (in half-us) + * @param[out] pa_evt_cnt Corresponding paEventCounter value + * @param[out] map Corresponding channel map + * @param[out] sca Periodic advertising Sleep Clock Accuracy + * + * @return status 0: success | 1-255: error + **************************************************************************************** + */ +uint8_t lld_sync_info_get(uint8_t act_id, uint8_t* phy, uint16_t* intv, struct access_addr* aa, struct crc_init* crcinit, uint32_t* sync_ind_ts, uint16_t* sync_ind_bit_off, uint16_t* pa_evt_cnt, struct le_chnl_map *map, uint8_t* sca); + +/// @} LLD +#endif // LLD_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/lld/lld_int.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/lld/lld_int.h new file mode 100755 index 0000000..ac3f6ad --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/lld/lld_int.h @@ -0,0 +1,400 @@ +/** +**************************************************************************************** +* +* @file lld_int.h +* +* @brief LLD Internal API +* +* Copyright (C) RivieraWaves 2009-2016 +* +**************************************************************************************** +*/ + +#ifndef LLD_INT_H_ +#define LLD_INT_H_ + +/** + **************************************************************************************** + * @addtogroup LLD + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" // stack configuration + +#include // integer +#include // boolean + +#include "lld.h" + + +/* + * MACROS + **************************************************************************************** + */ + + +/* + * CONSTANT DEFINITIONS + **************************************************************************************** + */ + +/// Allocate an event with an associated data structure +#define LLD_ALLOC_EVT(data_struct) (struct data_struct *) kernel_malloc(sizeof(struct data_struct), KERNEL_MEM_ENV); + +/// Initialize memory of an event and an associated data structure +#define LLD_INIT_EVT(evt, data_struct) memset(evt , 0, sizeof(struct data_struct)); + +#if 0 //(RW_BLE_WLAN_COEX) || (RW_BLE_MWS_COEX) +/// Coexistence disabled +#define BLECOEX_DISABLED 0 +/// Coexistence enabled +#define BLECOEX_ENABLED 1 + +/// Coexistence Definitions +#define BLEMPRIO_CONREQ 0 +#define BLEMPRIO_LLCP 1 +#define BLEMPRIO_DATA 2 +#define BLEMPRIO_INITSC 3 +#define BLEMPRIO_ACTSC 4 +#define BLEMPRIO_CONADV 5 +#define BLEMPRIO_NCONADV 6 +#define BLEMPRIO_PASSC 7 +#endif // (RW_BLE_WLAN_COEX) || (RW_BLE_MWS_COEX) + +/// Undefined BT clock value +#define LLD_CLOCK_UNDEF 0xFFFFFFFF + +/// Max fine counter value +#define LLD_FINECNT_MAX (HALF_SLOT_SIZE - 1) + +/// Adv packet error masking +#define LLD_ADV_ERR_MASK (EM_BLE_SYNC_ERR_BIT|EM_BLE_LEN_ERR_BIT|EM_BLE_CRC_ERR_BIT|EM_BLE_PRIV_ERR_BIT|EM_BLE_TYPE_ERR_BIT) + +/// ADV_INT (time between two ADV_XXX packets) in us +#define BLE_ADV_INT_US (729) + +/// Minimum scan window size when advertising using legacy PDUs in us +#define BLE_ADV_MIN_SCAN_WIN_SIZE_US (40) + +/// Calculate AUX OFFSET in usecs from AuxPtr AUX Offset and Offset Units fields +#define AUX_OFFSET_USECS(aux_offset, offset_units) ((aux_offset) * ((offset_units)?300:30)) + +/// AUX OFFSET Offset Units in usecs +#define AUX_OFFSET_UNIT_USECS(offset_units) ((offset_units)?300:30) + +/// Calculate drift in ppm from local drift and AuxPtr CA field +#define AUX_DRIFT_PPM(local_drift, ca) ((local_drift) + ((ca)?50:500)) + +/// Margin for event time reservation (in half-us) +#define BLE_RESERVATION_TIME_MARGIN_HUS (2 * IP_PREFETCHABORT_TIME_US) + +/// AUX_PTR Thresholds, below which HW manages AuxPtr automatically in same event (granularity 16us, 0 disabled) +#define LLD_TX_AUX_PTR_THR (0xFF) // 255 x 16 = 4080us (max value) +#define LLD_RX_AUX_PTR_THR (150) // 150 x 16 = 2520us (optimized for SW offload) + +/// Maximum supported CTE IQ samples - CTE RX descriptors dimensioned REG_EM_BLE_RX_CTE_DESC_SIZE to accommodate maximum +// An IQ sample is taken each usec during the reference period (8us) and one each sample slot thereafter. +// This results in 8 reference IQ samples, 1 to 37 IQ samples with 2 us slots, and 2 to 74 IQ samples with 1 us slots, meaning 9 to 82 samples in total. +#define LLD_MAX_CTE_IQ_SAMPLES (82) + +/// Hoping mode +enum lld_hop_mode +{ + /// Frequency Hopping Scheme #1 + LLD_HOP_MODE_CHAN_SEL_1 = 0, + /// Frequency Hopping Scheme #2 + LLD_HOP_MODE_CHAN_SEL_2 = 1, + /// Primary Advertising Channel randomized order mode + LLD_HOP_MODE_RAND_PRIM_ADV_CH = 3, +}; + +/* + * STRUCTURE DEFINITIONS + **************************************************************************************** + */ + +/// LLD environment structure +struct lld_env_tag +{ + /// Channel assessment data + struct lld_ch_assess_data ch_assess; + + /// ADV_SIDs bit field for PAL entries + uint16_t adv_sids[BLE_WHITELIST_MAX]; + + /// Maximum value of the local clock drift (in ppm) + uint16_t local_drift; + + /// Local sleep clock accuracy (see @enum SCA) + uint16_t local_sca; + + /// Current RX descriptor index [0:N-1] + uint8_t curr_rxdesc_index; + + /// LE Coded PHY 500 Kbps selection (false: 125 Kbps, true: 500 Kbps) + bool le_coded_phy_500; + + /// Connectionless channel map lookup table (more time-efficient than parsing a bitmap every time) + uint8_t ch_map_tab[DATA_CHANNEL_NB]; + + /// Number of used channels in the connectionless channel map + uint8_t nb_used_ch; +}; + +/// LLD Scheduling information for next AUX channel +struct lld_calc_aux_rx_out +{ + /// Timestamp (in half-slots) and delay (in half-us) from slot boundary for AUX offload channel receive + rwip_time_t time; + + /// Sync window size for the AUX offload channel (us) + uint32_t sync_win_size_us; + + /// Channel index for AUX offload channel + uint8_t ch_idx; + + /// PHY rate for AUX offload channel (@see enum lld_rate) + uint8_t rate; +}; + +/* + * VARIABLE DECLARATION + ***************************************************************************************** + */ + +/// Table indicating the expected sync position depending on the rate used +extern uint16_t lld_exp_sync_pos_tab[]; + +/// LLD environment variable +extern struct lld_env_tag lld_env; + +/* + * FUNCTIONS DECLARATION + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Free current RX descriptor + **************************************************************************************** + */ +void lld_rxdesc_free(void); + +/** + **************************************************************************************** + * @brief Check if the current RX descriptor is consumed by a given activity + * + * @param[in] label representing the activity (as indicated in the CS) + * + * @return True if current RX descriptor is consumed by the activity identified by label + **************************************************************************************** + */ +bool lld_rxdesc_check(uint8_t label); + +/** + **************************************************************************************** + * @brief Assess a RF channel + * + * @param[in] channel Channel index + * @param[in] rx_ok True: reception is correct | False: reception is corrupted + * @param[in] timestamp Timestamp of the assessment + * + * @return status 0: success | 1-255: error + **************************************************************************************** + */ +void lld_channel_assess(uint8_t channel, bool rx_ok, uint32_t timestamp); + +/** + **************************************************************************************** + * @brief Search if a device is in resolving address list + * + * @param[in] bd_addr BD Address + * @param[in] bd_addr_type BD Address type (0: public | 1: random) + * + * @return position of the device in the list (Max value if not found) + **************************************************************************************** + */ +uint8_t lld_ral_search(const struct bd_addr *bd_addr, uint8_t bd_addr_type); + +#if (BLE_BROADCASTER) +/** + **************************************************************************************** + * @brief Initialize advertising driver + * @param[in] init_type Type of initialization (@see enum rwip_init_type) + **************************************************************************************** + */ +void lld_adv_init(uint8_t init_type); + +/** + **************************************************************************************** + * @brief Initialize periodic advertising driver + * @param[in] init_type Type of initialization (@see enum rwip_init_type) + **************************************************************************************** + */ +void lld_per_adv_init(uint8_t init_type); + +/** + **************************************************************************************** + * @brief Get sync info from a periodic advertiser + * + * @param[in] act_id Activity ID + * @param[out] sync_ind_ts Timestamp of the AUX_SYNC_IND packet + * @param[out] pa_evt_cnt Corresponding paEventCounter value + * @param[out] map Corresponding channel map + * + * @return status 0: success | 1-255: error + **************************************************************************************** + */ +uint8_t lld_per_adv_sync_info_get(uint8_t act_id, uint32_t* sync_ind_ts, uint16_t* pa_evt_cnt, struct le_chnl_map *map); + +/** + **************************************************************************************** + * @brief Get initialization info from a periodic advertiser + * + * @param[in] act_id Activity ID + * @param[out] aa Periodic advertising Access Address + * @param[out] crcinit Periodic advertising CRC Initialization value + * @param[out] chm Periodic advertising Channel Map + * + * @return status 0: success | 1-255: error + **************************************************************************************** + */ +uint8_t lld_per_adv_init_info_get(uint8_t act_id, struct access_addr* aa, struct crc_init* crcinit, struct le_chnl_map* chm); + +/** + **************************************************************************************** + * @brief Select an auxiliary channel index + * + * @return ch_idx Selected channel index + **************************************************************************************** + */ +uint8_t lld_ch_idx_get(void); +#endif // (BLE_BROADCASTER) + +/** + **************************************************************************************** + * @brief Generating the Access Address for a new Link. + * + * The function will generate the following 4 bytes: + * |Byte 3 | Byte 2 | Byte 1 | Byte 0 | + * |CT1 | PRAND_4MSB | CT2 | PRAND_4LSB | CT2 | INCRAND_4MSB | CT2 | INCRAND_4LSB| + * + * The AA shall be a random 32-bit value, generated by the device in the Initiating State. + * It shall have no more than six consecutive zeros or ones. + * It shall not be the advertising channel packets Access Address. + * It shall not be a sequence that differs from the advertising channel packets Access Address by only one bit. + * It shall not have all four octets equal. + * It shall have no more than 24 transitions. + * It shall have a minimum of two transitions in the most significant six bits + * + * For each new generated AA, + * - PRAND is a pseudo random 1 byte number. + * - INCRAND is an initially generated random number, increased by 1 for each AA + * - CT2 is toggled between the two values + * - CT1 is again toggled between the 3 possible values + * + * Considering the formats of CT1 and CT2, the rules for AA generation are respected: + * - since CT2 is put between bytes, and has two equal bits on each half, + * it ensures no more than 6 consecutive bits inside the address. CT1 also. + * + * - CT2 and CT1 ensure that the newly generated address is different and at least 1 bit + * different from the advertising access address + * + * - since CT1 != CT2 , the four bytes of the AA can never be equal + * + * - Since in a 32 bit number there are 31 transitions, and the neighboring equal bits + * in CT1 and CT2 represent 7 transitions, there can never be more than 31-7=24 + * transitions in the AA + * + * - The format of CT1 ensures at least two transitions in the most significant 6 bits. + * + * BT5.0 Requirements: + * + * 1/ On an implementation that also supports the LE Coded PHY the Access Address shall also + * meet the following requirements: + * It shall have at least three ones in the least significant 8 bits. + * It shall have no more than eleven transitions in the least significant 16 bits. + * - CT2 format selected to satisfy these requirements. + * + * 2/ It shall not be the Access Address for any enabled periodic advertising. + * - The act_id is now passed as an arguemnt to AA generation to ensure unique values. + * + * @param acc_addr Pointer to the 4 byte array space for the AA. + * + * + ***************************************************************************************** + */ +void lld_aa_gen(uint8_t *acc_addr, uint8_t act_id); + +/** + **************************************************************************************** + * @brief Calculate an AUX RX activity + * + * @param[in] ux_rx_out Scheduling information for next AUX channel + * @param[out] index_pkt current RX descriptor index + * @param[out] aux_data received Aux data + * + * @return offload true: offload. false: no offload + **************************************************************************************** + */ +bool lld_calc_aux_rx(struct lld_calc_aux_rx_out* aux_rx_out, uint8_t index_pkt, uint32_t aux_data); + + +#if (BLE_OBSERVER) +/** + **************************************************************************************** + * @brief Initialize scanning driver + * @param[in] init_type Type of initialization (@see enum rwip_init_type) + **************************************************************************************** + */ + +void lld_scan_init(uint8_t init_type); + +/** +**************************************************************************************** +* @brief Initialize periodic advertising Rx driver +* @param[in] init_type Type of initialization (@see enum rwip_init_type) +**************************************************************************************** +*/ +void lld_sync_init(uint8_t init_type); + +#endif // (BLE_OBSERVER) + +#if (BLE_CENTRAL) +/** + **************************************************************************************** + * @brief Initialize initiating driver + * @param[in] init_type Type of initialization (@see enum rwip_init_type) + **************************************************************************************** + */ +void lld_init_init(uint8_t init_type); +#endif // (BLE_CENTRAL) + +#if (BLE_CENTRAL || BLE_PERIPHERAL) +/** + **************************************************************************************** + * @brief Initialize connection driver + * @param[in] init_type Type of initialization (@see enum rwip_init_type) + **************************************************************************************** + */ +void lld_con_init(uint8_t init_type); + +#endif // (BLE_CENTRAL || BLE_PERIPHERAL) + +/** + **************************************************************************************** + * @brief Initialize test driver + * @param[in] init_type Type of initialization (@see enum rwip_init_type) + **************************************************************************************** + */ +void lld_test_init(uint8_t init_type); + + +/// @} LLD +#endif // LLD_INT_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/lli.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/lli.h new file mode 100755 index 0000000..6e7db46 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/lli.h @@ -0,0 +1,101 @@ +/** + **************************************************************************************** + * + * @file lli.h + * + * @brief Main API file for the Link Layer ISO + * + * Copyright (C) RivieraWaves 2009-2015 + * + **************************************************************************************** + */ + +#ifndef LLI_H_ +#define LLI_H_ + +/** + **************************************************************************************** + * @defgroup LLI Link Layer ISO + * @ingroup ROOT + * @brief BLE Lower Layers + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" + +#if (BLE_ISO_PRESENT) + +#include "rwip_task.h" // Task definitions +#include "common_bt.h" // BLE standard definitions +#include "common_llcp.h" // Definition of LL_CIS_REQ PDU +#include "lld.h" // LLD Definitions + +/* + * DEFINES + **************************************************************************************** + */ + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Initialization of the BLE LLI task + * + * This function initializes the the LLI task. + * + * @param[in] reset True: reset | False: init + **************************************************************************************** + */ +void lli_init(bool reset); + +/** + **************************************************************************************** + * @brief Inform that a link has terminated to immediately stop corresponding ISO channels + * + * @param[in] link_id Link identifier + * @param[in] reason Link termination reason + **************************************************************************************** + */ +void lli_link_stop_ind(uint8_t link_id, uint8_t reason); + +#if (BLE_ISO_MODE_0) +/** + **************************************************************************************** + * @brief Check if link is used for audio mode 0 + * + * @param[in] link_id Link identifier + * + * @return True if link is used for audio mode 0 + **************************************************************************************** + */ +bool lli_am0_check(uint8_t link_id); +#endif // (BLE_ISO_MODE_0) + +/** + **************************************************************************************** + * @brief Retrieve number of available channels + * + * @return Number of channel that can be allocated + **************************************************************************************** + */ +uint8_t lli_nb_chan_ava_get(void); + +#endif //(BLE_ISO_PRESENT) + +/// @} LLI + +#endif // LLI_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/llm.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/llm.h new file mode 100755 index 0000000..2b22f6e --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/llm.h @@ -0,0 +1,402 @@ +/** + **************************************************************************************** + * + * @file llm.h + * + * @brief Main API file for the Link Layer manager + * + * Copyright (C) RivieraWaves 2009-2015 + * + **************************************************************************************** + */ + +#ifndef LLM_H_ +#define LLM_H_ + +/** + **************************************************************************************** + * @defgroup LLM Link Layer Manager + * @ingroup ROOT + * @brief BLE Lower Layers + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_task.h" // Task definitions +#include "common_bt.h" // BLE standard definitions + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + +/// Parameters for syncing to a periodic advertiser +struct llm_per_adv_sync_params +{ + /// Activity identifier + uint8_t act_id; + + /// SyncInfo + struct sync_info syncinfo; + + /// The clock value of the reference time (in half-slot) + uint32_t base_cnt; + + /// The fine timer value the reference time (in half-us) + uint16_t fine_cnt; + + /// ID (provided by the Host) + uint16_t id; + + /// The bit rate of periodic advertising (@see enum lld_rate) + uint8_t rate; + + /// Advertising SID + uint8_t adv_sid; + + /// Advertising address type (0: Public / 1: Random) + uint8_t adv_addr_type; + + /// Advertiser address + struct bd_addr adv_addr; + + /// Advertiser RPA (unresolved RPA if advertiser address is a resolved identity address, 0 otherwise) + struct bd_addr adv_rpa; + + /// max Skip after receive + uint16_t skip; + + /// Sync timeout (Time=N*10ms) + uint16_t sync_to; + + /// Additional drift to consider on given time reference (in half-us) + uint16_t add_drift; + + /// Advertising report initial state (enable/disable) + bool adv_rep_en; + + /// Specifies whether to only synchronize to periodic advertising with certain types of CTE (@see enum sync_cte_type) + uint8_t sync_cte_type; +}; + + +/* + * MESSAGES + **************************************************************************************** + */ + +/// Message API of the LLM task +/*@TRACE + * llm_pub_key_gen_ind = ecc_result_ind + * llm_dh_key_gen_ind = ecc_result_ind + * llm_encrypt_ind = ble_aes_func_res_ind*/ +enum llm_msg_id +{ + LLM_MSG_ID_FIRST = TASK_BLE_FIRST_MSG(TASK_BLE_ID_LLM),//!< LLM_MSG_ID_FIRST + + #if (BLE_OBSERVER) + /// Send ACAD Data information + LLM_ACAD_DATA_IND, //!< LLM_ACAD_DATA_IND + #endif // (BLE_OBSERVER) + + /* + * ************** Msg LLM->LLC**************** + */ + #if (BLE_CENTRAL || BLE_PERIPHERAL) + /// Indicate that the channel map has to be updated on link connection + LLM_CH_MAP_UPDATE_IND, //!< LLM_CH_MAP_UPDATE_IND + #endif //(BLE_CENTRAL || BLE_PERIPHERAL) + + /* + * ************** Msg LLM->LLM**************** + */ + LLM_SCAN_PERIOD_TO, //!< LLM_SCAN_PERIOD_TO + LLM_CH_MAP_TO, //!< LLM_CH_MAP_TO + #if (BLE_CENTRAL || BLE_BROADCASTER) + LLM_NEW_HOST_CLASS_TO, + #endif //(BLE_CENTRAL || BLE_BROADCASTER) + LLM_RPA_RENEW_TO, //!< LLM_RPA_RENEW_TO + /// Inform that encryption has been performed + LLM_ENCRYPT_IND, //!< LLM_ENCRYPT_IND + + LLM_PUB_KEY_GEN_IND, //!< LLM_PUB_KEY_GEN_IND + LLM_DH_KEY_GEN_IND, //!< LLM_DH_KEY_GEN_IND +}; + +/// LLM Encryption Request parameters structure +/*@TRACE*/ +struct llm_encrypt_req +{ + ///Long term key structure + struct ltk key; + ///Pointer to buffer with plain data to encrypt - 16 bytes + uint8_t plain_data[ENC_DATA_LEN]; +}; + +/// LLM Encryption indication structure +/*@TRACE*/ +struct llm_encrypt_rsp +{ + /// Status of the encryption + uint8_t status; + ///Encrypted data + uint8_t encrypted_data[ENC_DATA_LEN]; +}; + + +/// AES function execution result +/*@TRACE*/ +struct llm_encrypt_ind +{ + /// Status of AES execution + uint8_t status; + /// Result of the + uint8_t result[KEY_LEN]; +}; + + +#if (BLE_OBSERVER) +/// LLM ACAD data indication structure +/*@TRACE*/ +struct llm_acad_data_ind +{ + /// Sync handle + uint16_t sync_handle; + /// Status the indication - use to detect loss of periodic sync + uint8_t status; + /// ADV Data Type + uint8_t ad_type; + /// Reference event counter of the periodic advertiser when report received + uint16_t ref_evt_cnt; + + /// length of the data field + uint8_t data_len; + /// ACAD Data + uint8_t data[__ARRAY_EMPTY]; +}; +#endif // (BLE_OBSERVER) + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Initialization of the BLE LLM task + * + * This function initializes the the LLM task, as well as the environment of the LLM + * + * @param[in] init_type Type of initialization (@see enum rwip_init_type) + **************************************************************************************** + */ +void llm_init(uint8_t init_type); + +#if (BLE_CENTRAL || BLE_PERIPHERAL) +/** + **************************************************************************************** + * @brief This function handles LE link disconnection. + * + * @param[in] link_id Link Identifier + **************************************************************************************** + */ +void llm_link_disc(uint8_t link_id); + +/** + **************************************************************************************** + * @brief Indicate activity requires accurate clock + * + * @param[in] act_id Activity ID + * @param[in] clk_acc True if activity requires accurate clock + **************************************************************************************** + */ +void llm_clk_acc_set(uint8_t act_id, bool clk_acc); +#endif // (BLE_CENTRAL || BLE_PERIPHERAL) + +/** + **************************************************************************************** + * @brief This function is used to get the master channel map + * + * @return Pointer to master channel map + **************************************************************************************** + */ +struct le_chnl_map* llm_master_ch_map_get(void); + +/** + **************************************************************************************** + * @brief This function is used to check if an event is unmasked/masked + * + * @param[in] event_id Bit position of the event in the mask (see standard specification part II.E.7.8.1) + * + * @return True: event allowed | False: event masked + **************************************************************************************** + */ +bool llm_le_evt_mask_check(uint8_t event_id); + +/** + **************************************************************************************** + * @brief Retrieve LE Local Supported features + * + * @return Local feature mask + **************************************************************************************** + */ +const struct le_features* llm_le_features_get(void); + +/** + **************************************************************************************** + * @brief This function is used to get the RF Tx path compensation value + * + * @return RF Tx path compensation value (Range: -128.0 dB <= N <= 128.0 dB, Units: 0.1 dB) + **************************************************************************************** + */ +int16_t llm_tx_path_comp_get(void); + +/** + **************************************************************************************** + * @brief This function is used to get the RF Rx path compensation value + * + * @return RF Rx path compensation value (Range: -128.0 dB <= N <= 128.0 dB, Units: 0.1 dB) + **************************************************************************************** + */ +int16_t llm_rx_path_comp_get(void); + +/** + **************************************************************************************** + * @brief This function returns a pointer to the interval element of the link_id provided. + * + * @param[in] link_id Link Identifier + * + * @return Pointer to the associated interval element + **************************************************************************************** + */ +struct sch_plan_elt_tag *llm_plan_elt_get(uint8_t link_id); + +/** + **************************************************************************************** + * @brief Get available activity index + * + * @param[out] act_id Activity Identifier allocated + * + * @return - COMMON_ERROR_NO_ERROR: if succeed + * - COMMON_ERROR_CON_LIMIT_EXCEED: if no activity available + **************************************************************************************** + */ +uint8_t llm_activity_free_get(uint8_t* act_id); +/** + **************************************************************************************** + * @brief Free activity handle related to the activity + * + * @param[in] act_id Activity Identifier + **************************************************************************************** + */ +void llm_activity_free_set(uint8_t act_id); + +/** + **************************************************************************************** + * @brief Get advertising activity identifiers + * + * @param[in] adv_hdl Advertising handle + * @param[out] ext_adv_id Extended advertising ID + * @param[out] per_adv_id Periodic advertising ID + * + * @return - COMMON_ERROR_NO_ERROR: if succeed + * - COMMON_ERROR_UNKNOWN_ADVERTISING_ID: if no advertising set exists + * - COMMON_ERROR_COMMAND_DISALLOWED: if periodic advertising not in progress + **************************************************************************************** + */ +uint8_t llm_adv_act_id_get(uint8_t adv_hdl, uint8_t* ext_adv_id, uint8_t* per_adv_id); + +/** + **************************************************************************************** + * @brief Get periodic advertising train identifiers + * + * @param[in] act_id Activity ID of extended advertising + * @param[out] sid Advertising SID + * @param[out] atype Advertising address type (0: public, 1: random) + * @param[out] adva Advertising address (RPA if address is resolvable) + * + * @return - COMMON_ERROR_NO_ERROR: if succeed + * - COMMON_ERROR_COMMAND_DISALLOWED: if periodic advertising not in progress + **************************************************************************************** + */ +uint8_t llm_adv_set_id_get(uint8_t act_id, uint8_t* sid, uint8_t* atype, struct bd_addr* adva); + +#if (BLE_ISO_MODE_0) +/** + **************************************************************************************** + * @brief Get if Activity is an active link + * + * @param[out] act_id Activity Identifier + * + * @return true if in connected state, false else + **************************************************************************************** + */ +bool llm_iso_link_active(uint8_t act_id); +#endif // (BLE_ISO_MODE_0) + + +/** + **************************************************************************************** + * @brief Get if Activity is ongoing + * + * @return true if active + **************************************************************************************** + */ +bool llm_activity_ongoing_check(void); + +/** + **************************************************************************************** + * @brief Attach a task with a periodic scanner to receive specific AD Type data + * + * @param[in] sync_act_id Sync activity ID + * @param[in] ad_type AD Type to retrieve in ACAD data + * @param[in] task Task that expect the LLM_ACAD_DATA_IND message + * + * @return COMMON_ERROR_NO_ERROR if the periodic sync is found + **************************************************************************************** + */ +uint8_t llm_scan_sync_acad_attach(uint8_t sync_act_id, uint8_t ad_type, uint16_t task); + +/** + **************************************************************************************** + * @brief Get periodic sync information + * + * @param[in] sync_act_id Sync activity ID + * @param[out] sid Extended advertising set identifier + * @param[out] atype Extended advertiser address type (0: public | 1: random) + * @param[out] adva Extended advertiser address (for resolvable addresses, this is the unresolved version) + * + * @return - COMMON_ERROR_NO_ERROR: if succeed + * - COMMON_ERROR_UNKNOWN_ADVERTISING_ID: if the sync activity does not exist + **************************************************************************************** + */ +uint8_t llm_scan_sync_info_get(uint8_t sync_act_id, uint8_t* sid, uint8_t* atype, struct bd_addr* adva); + +/** + **************************************************************************************** + * @brief Synchronize to a periodic advertising + * + * param[in] params Input parameters (@see llm_per_adv_sync_params) + * + * @return 0 if synchronization attempt is started, >0 if issue + **************************************************************************************** + */ +uint8_t llm_per_adv_sync(struct llm_per_adv_sync_params * params); + +/** + **************************************************************************************** + * @brief Get pointer of the RAL table in RAM + * + * @return pointer of the RAL table in RAM + **************************************************************************************** + */ +struct ral_entry* llm_ral_get(void); + +/// @} LLM + +#endif // LLM_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/llm/llm_int.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/llm/llm_int.h new file mode 100755 index 0000000..e08d557 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/ble/ll/src/llm/llm_int.h @@ -0,0 +1,634 @@ +/** + **************************************************************************************** + * + * @file llm.h + * + * @brief Link layer manager internal definition + * + * Copyright (C) RivieraWaves 2009-2016 + * + **************************************************************************************** + */ + +#ifndef LLM_INT_H_ +#define LLM_INT_H_ + +/** + **************************************************************************************** + * @addtogroup LLM Link layer Manager + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include // standard integer +#include // standard boolean + +#include "common_bt.h" // BT defines +#include "sch_plan.h" // Scheduling Planner + +/* + * DEFINES + **************************************************************************************** + */ + +/// Maximum number of instances of the LLM task +#define LLM_IDX_MAX 1 + +/// Invalid activity identifier +#define LLM_ACT_IDX_INVL 0xFF + +/// Invalid advertising handle (assigned to legacy advertising for internal management) +#define LLM_ADV_HDL_INVL 0xFF + +/* + * ENUMERATIONS + **************************************************************************************** + */ + +/** + * Information bit field for advertising duplicate filtering + * 15:10 9:8 7:6 5:4 3:2 1 0 + * +---------------------------------------+--------------+--------------+--------------+--------------+------+------+ + * | | CHAIN2_CODED | CHAIN2_1M | CHAIN1_CODED | CHAIN1_1M | RST | EN | + * +---------------------------------------+--------------+--------------+--------------+--------------+------+------+ + */ +enum adv_dup_filt_info +{ + /// Duplicate filtering enabled + LLM_ADV_DUP_FILT_EN_POS = 0, + LLM_ADV_DUP_FILT_EN_BIT = (1 << 0), + + /// Duplicate filtering reset at each scan period + LLM_ADV_DUP_FILT_RST_POS = 1, + LLM_ADV_DUP_FILT_RST_BIT = (1 << 1), + + /// Advertising report chain status from 1M scan + LLM_ADV_DUP_FILT_CHAIN1_1M_LSB = 2, + LLM_ADV_DUP_FILT_CHAIN1_1M_MASK = (0x3 << 2), + + /// Advertising report chain status from coded scan + LLM_ADV_DUP_FILT_CHAIN1_CODED_LSB = 4, + LLM_ADV_DUP_FILT_CHAIN1_CODED_MASK = (0x3 << 4), + + /// Advertising report chain status from 1M scan + LLM_ADV_DUP_FILT_CHAIN2_1M_LSB = 6, + LLM_ADV_DUP_FILT_CHAIN2_1M_MASK = (0x3 << 6), + + /// Advertising report chain status from coded scan + LLM_ADV_DUP_FILT_CHAIN2_CODED_LSB = 8, + LLM_ADV_DUP_FILT_CHAIN2_CODED_MASK = (0x3 << 8), + + /** + * 0: No chain + * 1: A valid advertising report chain is ongoing + * 2: A filtered advertising report chain is ongoing + */ + LLM_ADV_CHAIN_NO = 0, + LLM_ADV_CHAIN_VALID = 1, + LLM_ADV_CHAIN_FILTERED = 2, +}; + +/// Status bits for a device list entry +/// +/// 7 6 5 4 3 2 1 0 +/// +------+------+------+------+------+-------+-------+------+ +/// | | | | | | IN_PL | IN_WL | USED | +/// +------+------+------+------+------+-------+-------+------+ +/// +enum dev_list_stat +{ + /// Device list entry is used + LLM_DEV_LIST_ENTRY_USED_POS = 0, + LLM_DEV_LIST_ENTRY_USED_BIT = (1 << 0), + + /// Device is in white list + LLM_DEV_IN_WL_POS = 1, + LLM_DEV_IN_WL_BIT = (1 << 1), + + /// Device is in periodic advertiser list + LLM_DEV_IN_PL_POS = 2, + LLM_DEV_IN_PL_BIT = (1 << 2), +}; + +/// Advertising interface version, see HCI:3.1.1 +enum adv_itf_version +{ + /// Interface not yet detected + LLM_ADV_ITF_UNKNOWN = 0, + /// Legacy interface + LLM_ADV_ITF_LEGACY, + /// Extended interface + LLM_ADV_ITF_EXTENDED, +}; + +/** + * Periodic advertising reports enable/disable (only used for periodic sync) + * + * 7..3 2 1 0 + * +--------------+-------+--------+------+ + * | RSVD | CHAIN | SWITCH | EN | + * +--------------+-------+--------+------+ + */ +enum per_adv_rep_en +{ + /// Reports enable/disable + LLM_PER_ADV_REP_EN_EN_POS = 0, + LLM_PER_ADV_REP_EN_EN_BIT = (1 << 0), + + /// Indicate a chain is ongoing + LLM_PER_ADV_REP_EN_CHAIN_POS = 1, + LLM_PER_ADV_REP_EN_CHAIN_BIT = (1 << 1), + + /// Reports enable/disable + LLM_PER_ADV_REP_EN_SWITCH_POS = 2, + LLM_PER_ADV_REP_EN_SWITCH_BIT = (1 << 2), +}; + +/// States of an activity +enum LLM_ACTIVITY_STATE +{ + LLM_FREE, + LLM_ADV_RSVD, + LLM_ADV_EN, + LLM_ADV_STOPPING, + LLM_CON_RSVD, + LLM_INITIATING, + LLM_SCAN_RSVD, + LLM_SCAN_EN, + LLM_SCAN_STOPPING, + LLM_CONNECTED, + LLM_PER_ADV_RSVD, + LLM_PER_ADV_PENDING, // This state means that the host has enabled per adv but the driver has not been started yet + LLM_PER_ADV_EN, + LLM_PER_ADV_STOPPING, + LLM_PER_SCAN_SYNCING, + LLM_PER_SCAN_SYNCED, + LLM_PER_SCAN_STOPPING, + LLM_PER_SCAN_SYNCING_FROM_SYNC_TRANSF, +}; + + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + +/// Device list entry structure +struct dev_list_entry +{ + /// BD address + struct bd_addr addr; + + /// Advertising Set IDs (for periodic advertiser list), 1 bit per ADV_SID + uint16_t adv_sids; + + /** Address type + * 0x00 Public Device Address or Public Identity Address + * 0x01 Random Device Address or Random (static) Identity Address + * 0xFF Address type of devices sending anonymous advertisements + */ + uint8_t addr_type; + + /** Bit field indicating: + * bit 0: entry is used + * bit 1: device is in white list + * bit 2: device is in periodic advertiser list + */ + uint8_t status; +}; + +/// Information about one single advertiser discovered +struct adv_dup_filt_entry +{ + /// Advertising device address + struct bd_addr adv_addr; + + /// Advertising Data ID (if Set ID is valid) + uint16_t did; + + /// Periodic advertising interval + uint16_t per_adv_intv; + + /** + * Bit + * 0 Connectable advertising + * 1 Scannable advertising + * 2 Directed advertising + * 3 Scan response + * 4 Legacy advertising PDUs used + */ + uint8_t adv_evt_type; + + /** + * Peer address type + * 0x00 Public Device Address + * 0x01 Random Device Address + * 0x02 Public Identity Address (Corresponds to Resolved Private Address) + * 0x03 Random (static) Identity Address (Corresponds to Resolved Private Address) + * 0x04-0xFF Reserved for future use + */ + uint8_t addr_type; + + /// Advertising Set ID + uint8_t sid; +}; + +#if (BLE_OBSERVER) +/// Advertising duplicate filtering table information structure +struct adv_dup_filt_tab_info +{ + /// Table listing all found advertisers + struct adv_dup_filt_entry tab[BLE_DUPLICATE_FILTER_MAX]; + + /// Current position in the table for placing the next discovered advertiser + uint8_t curr_pos; + + /// Number of discovered advertisers in the table + uint8_t nb_adv; +}; +#endif //(BLE_OBSERVER) + +/// Channel map parameters structure +struct llm_ch_map_info +{ + /// Channel classification from Host + struct le_chnl_map host_ch_class; + + /// Master channel map (map used for all master links) + struct le_chnl_map master_ch_map; + + /// Channel map management state + uint8_t active; + + /** + * Block the HCI LE Set Host Channel Classification Command during 1 second, as per standard + * The interval between two successive commands sent shall be at least one second. + */ + bool new_host_class; +}; + +/// Information about extended advertising data or scan response data received from Host +struct llm_adv_tx_info +{ + /// EM buffer containing complete advertising or extended scan response data received from Host + uint16_t curr_buf; + + /// Total length of advertising or scan response data in the current buffer + uint16_t curr_len; + + /// EM buffer containing advertising data or extended scan response data in construction from Host + uint16_t new_buf; + + /// Total length of advertising or scan response data in the new buffer + uint16_t new_len; +}; + +/// Specific information for advertiser +struct llm_adv_info +{ + /// Information about extended advertising data received from Host + struct llm_adv_tx_info adv_data; + + /// Information about extended scan response data received from Host + struct llm_adv_tx_info scan_rsp_data; + + /// Local BD address + struct bd_addr bd_addr; + + /// Local RPA + struct bd_addr local_rpa; + + #if BLE_CONLESS_CTE_TX + /// Pointer to CTE parameters received from the Host (field valid for ext adv only, not per adv) + struct hci_le_set_conless_cte_tx_param_cmd const *cte_tx_params; + + /// Indicates whether CTE has been enabled (true) or not (false) (field valid for ext adv only, not per adv) + bool cte_en; + #endif // BLE_CONLESS_CTE_TX + + /// Selected extended advertising Tx power (selected by LLM, applied by LLD) + int8_t tx_pwr; + + /// Per adv linked to the set: ID of the periodic advertising + uint8_t per_act_id; + + /// The ID of the resulting connection if advertising is connectable + uint8_t con_act_id; +}; + +/// Specific information for periodic advertiser +struct llm_per_adv_info +{ + /// Information about extended advertising data received from Host + struct llm_adv_tx_info adv_data; + + /** + * Associated activity ID: + */ + uint8_t ass_act_id; +}; + +/// Specific information for periodic synchronization +struct llm_sync_info +{ + #if BLE_CONLESS_CTE_RX + /// Pointer to CTE parameters received from the Host (for periodic scanning) + struct hci_le_set_conless_iq_sampl_en_cmd const *cte_rx_params; + #endif // BLE_CONLESS_CTE_RX + + /// Peer identity BD address + struct bd_addr bd_addr; + + /// Peer RPA (used by PAST feature) + struct bd_addr peer_rpa; + + /// Service data (value provided by the Host during periodic advertising sync transfer, stored temporarily during sync establishment) + uint16_t serv_data; + + /// Advertising SID (for periodic scanning) + uint8_t adv_sid; + + /// Periodic advertising PHY (for periodic scanning) + uint8_t per_adv_phy; + + // Periodic Sync ACAD data transfer: + /// Adv data type to transfer + uint8_t ad_type; + /// Task identifier that expect the advertising data. + /// - TASK_BLE_NONE ==> means no activity expect ACAD data + uint16_t dst_id; + /** + * Associated activity ID: + * + * Its meaning depends on the activity: + * - Scan: + * - not used + * - Periodic sync + * - Only when syncing from a periodic advertising sync transfer, it + * links to the connection where the info has been received from. Used + * to report synchronization result to the Host + */ + uint8_t ass_act_id; + + /// Periodic advertising reports enable/disable (only used for periodic sync) (@see enum per_adv_rep_en) + uint8_t per_adv_rep_en; + + /// Peer device address type (@see enum addr_type) + uint8_t addr_type; +}; + +/// Specific information for connection +struct llm_con_info +{ + /// Peer BD address (identity) + struct bd_addr bd_addr; + + /// Peer device address type (@see enum addr_type) + uint8_t addr_type; + + /// Role (0x00: MASTER / 0x01: SLAVE) (for connection) + uint8_t role; +}; + +/// Specific information for scanning +struct llm_scan_info +{ + ///Scan duration (Time=N*10ms) | 0x0000: Scan continuously until explicitly disable + uint16_t duration; + ///Scan period (Time=N*1.28sec) | 0x0000: Periodic scanning disabled + uint16_t period; +}; + + +/// State for all activities +struct llm_act_info +{ + /// Pointer to parameters received from the Host (advertising, scanning or initiating) + void const * host_params; + + /// Interval element linked to this activity + struct sch_plan_elt_tag plan_elt; + + union + { + /// Scanning specific activity info + struct llm_scan_info scan; + /// Advertising specific activity info + struct llm_adv_info adv; + /// Periodic advertising specific activity info + struct llm_per_adv_info per_adv; + /// Periodic sync specific activity info + struct llm_sync_info sync; + /// Connection specific activity info + struct llm_con_info con; + } info; + + + /// State + uint8_t state; +}; + +/// LLM environment structure +struct llm_env_tag +{ + /// RAL content + struct ral_entry ral[BLE_RESOL_ADDR_LIST_MAX]; + + /// Bit field indicating the accurate clock is required (for each activity, indexed by activity ID) + uint32_t act_clk_acc; + + /// LE Event mask + struct evt_mask le_event_mask; + + /// State and parameters for all activities + struct llm_act_info act_info[BLE_ACTIVITY_MAX]; + + /// Local public BD address + struct bd_addr local_pub_addr; + + /// Local random BD address + struct bd_addr local_rand_addr; + + /// Channel map management parameters + struct llm_ch_map_info ch_map_info; + + /// Device list information table + struct dev_list_entry dev_list[BLE_WHITELIST_MAX]; + + #if (BLE_CENTRAL || BLE_PERIPHERAL) + // Default Data Length parameters + /// Suggested value for the Controller's maximum transmitted number of payload octets + uint16_t suggested_max_tx_octets; + /// Suggested value for the Controller's maximum packet transmission time (in us) + uint16_t suggested_max_tx_time; + + // Default PHY parameters + /// Phy options indicated by Host (@see enum le_phy_opt) (by default 0 if never set by Host) + uint16_t phy_opt; + /// Default TX preferred PHY to use (@see enum le_phy_mask) + uint8_t tx_phys; + /// Default RX preferred PHY to use (@see enum le_phy_mask) + uint8_t rx_phys; + + // Default PAST parameters + /// Mode (@see enum per_adv_sync_info_rec_mode) + uint8_t past_mode; + /// The number of periodic advertising packets that can be skipped after a successful receive + uint16_t past_skip; + /// Sync timeout (Time=N*10ms) + uint16_t past_sync_to; + /// CTE type (@see enum sync_cte_type) + uint8_t past_cte_type; + #endif //(BLE_CENTRAL || BLE_PERIPHERAL) + + /// Private P256 key for secure connection + uint8_t secret_key256[PRIV_KEY_256_LEN]; + + /// Resolvable private addresses renew timeout (in seconds) + uint16_t rpa_renew_to; + /// Address resolution enabled + bool addr_resolution_en; + + /// RF Rx path compensation value (Range: -128.0 dB <= N <= 128.0 dB, Units: 0.1 dB) + int16_t rx_path_comp; + /// RF Tx path compensation value (Range: -128.0 dB <= N <= 128.0 dB, Units: 0.1 dB) + int16_t tx_path_comp; + + #if (BLE_OBSERVER) + /// Advertising duplicate filtering table information + struct adv_dup_filt_tab_info dup_filt; + + /// Information bit field for duplicate filtering (@see enum adv_dup_filt_info) + uint16_t adv_dup_filt_info; + + /// Enable scanning for extended advertising PDUs + bool ext_scan; + #endif //(BLE_OBSERVER) + + #if (BLE_BROADCASTER) + /// Number of extended advertising sets that are stopping + uint8_t nb_ext_adv_sets_stopping; + #endif //(BLE_BROADCASTER) + + #if (BLE_ADV_LEGACY_ITF) + /// Indicate if the interface version the Host is using (legacy/extended), see HCI:3.1.1 + uint8_t adv_itf_version; + #endif //(BLE_ADV_LEGACY_ITF) + + #if (BLE_CENTRAL || BLE_PERIPHERAL) + /// Connection move enable + uint8_t con_move_en; + #endif // (BLE_CENTRAL || BLE_PERIPHERAL) + + /// Enable channel assessment usage when building channel maps + bool ch_ass_en; +}; + + +/* + * GLOBAL VARIABLE DECLARATIONS + ***************************************************************************************** + */ + + /// LLM task message handlers table +extern const struct kernel_task_desc TASK_BLE_DESC_LLM; + +/// LLM environment variable +extern struct llm_env_tag llm_env; + +/// LLM local supported features +extern uint8_t const llm_local_supp_feats[FEATURE_PAGE_MAX][FEATS_LEN]; + + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +#if (BLE_BROADCASTER) +/** + **************************************************************************************** + * @brief Retrieve Advertising identifier from advertising handle. + * + * @param[in] adv_hdl Advertising Handle + * @param[out] adv_param if not null, used to return advertising parameter that correspond to the handle. + * + * @return Activity identifier, or invalid identifier if not found + **************************************************************************************** + */ +uint8_t llm_adv_hdl_to_id(uint16_t adv_hdl, struct hci_le_set_ext_adv_param_cmd** adv_param); +#endif // (BLE_BROADCASTER) + +/// Send HCI CC event returning a status only +void llm_cmd_cmp_send(uint16_t opcode, uint8_t status); + +/// Send HCI CS event +void llm_cmd_stat_send(uint16_t opcode, uint8_t status); + +#if (BLE_CENTRAL || BLE_PERIPHERAL || BLE_OBSERVER) +/// Check if a device is already connected +bool llm_is_dev_connected(struct bd_addr const *peer_addr, uint8_t peer_addr_type); +#endif //(BLE_CENTRAL || BLE_PERIPHERAL || BLE_OBSERVER) + +#if (BLE_OBSERVER) +/// Check if a device is a synchronized periodic advertiser +bool llm_is_dev_synced(struct bd_addr const *peer_addr, uint8_t peer_addr_type, uint8_t adv_sid); +#endif //(BLE_OBSERVER) + +/** + **************************************************************************************** + * @brief Find an empty entry in device list + * + * @return position of an empty entry in the list (Max value if not found) + **************************************************************************************** + */ +uint8_t llm_dev_list_empty_entry(void); + +/** + **************************************************************************************** + * @brief Search if a device is in device list + * + * @param[in] bd_addr BD Address + * @param[in] bd_addr_type BD Address type (0: public | 1: random) + * + * @return position of the device in the list (Max value if not found) + **************************************************************************************** + */ +uint8_t llm_dev_list_search(const struct bd_addr *bd_addr, uint8_t bd_addr_type); + +/** + **************************************************************************************** + * @brief Search if a device is in resolving address list + * + * @param[in] bd_addr BD Address + * @param[in] bd_addr_type BD Address type (0: public | 1: random) + * + * @return position of the device in the list (Max value if not found) + **************************************************************************************** + */ +uint8_t llm_ral_search(const struct bd_addr *bd_addr, uint8_t bd_addr_type); + +/** + **************************************************************************************** + * @brief Check if resolving list is empty + * + * @return True: empty | False: not empty + **************************************************************************************** + */ +bool llm_ral_is_empty(void); + +/** + **************************************************************************************** + * @brief Entry point to update the channel map + **************************************************************************************** + */ +void llm_ch_map_update(void); + +/// @} LLM + +#endif // LLM_INT_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/em/api/em_map.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/em/api/em_map.h new file mode 100755 index 0000000..752aa85 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/em/api/em_map.h @@ -0,0 +1,272 @@ +/** + **************************************************************************************** + * + * @file em_map.h + * + * @brief Mapping of the exchange memory + * + * Copyright (C) RivieraWaves 2009-2015 + * + **************************************************************************************** + */ + +#ifndef EM_MAP_H_ +#define EM_MAP_H_ + +/** + **************************************************************************************** + * @addtogroup EM EM + * @ingroup IP + * @brief Mapping of the different common area in the exchange memory + * + * @{ + **************************************************************************************** + */ +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_config.h" +#include +#include +#include +#include "common_math.h" // For use of COMMON_ALIGN4_HI + +#include "_reg_em_et.h" + +/// Retrieve Exchange memory address to set into HW interface +#define REG_EM_ADDR_GET(elem, idx) (REG_EM_##elem##_ADDR_GET(idx) >> 2) +/// Retrieve Exchange index from address load from HW interface +#define REG_EM_IDX_GET(elem, addr) ((((addr)<<2) - (EM_##elem##_OFFSET))/(REG_EM_##elem##_SIZE)) + +/// Exchange memory base address +#define EM_BASE_ADDR REG_EM_ET_BASE_ADDR + +/// Null pointer in EM offset space +#define EM_PTR_NULL (0x0000) + + +/* + **************************************************************************************** + ********************** Common EM part ********************** + **************************************************************************************** + */ +/// Start of the common EM part +#define EM_COMMON_OFFSET (0) + +/* + * EXCHANGE TABLE + **************************************************************************************** + */ + +/// Exchange table area definition +#define EM_EXCH_TABLE_LEN 16 +#define EM_ET_OFFSET (EM_COMMON_OFFSET) +#define EM_ET_END (EM_ET_OFFSET + EM_EXCH_TABLE_LEN * REG_EM_ET_SIZE) + +/** + * MODEn[3:0] + * + * 0x0: No mode selected, nothing to be performed + * 0x1: BR/EDR Mode + * 0x2: BLE Mode + * 0x3-0xF: Reserved for future use - + */ +#define EM_ET_MODE_NONE 0x00 +#define EM_ET_MODE_BREDR 0x01 +#define EM_ET_MODE_BLE 0x02 + +/// exchange table entry status +enum em_et_status +{ + /// 000: Exchange Table entry associated event is ready for processing. + EM_ET_STATUS_READY = 0x00,//!< EM_ET_STATUS_READY + /// 001: Exchange Table entry is waiting for start (already read by Event Scheduler) + EM_ET_STATUS_UNDER_PROCESS = 0x01,//!< EM_ET_STATUS_UNDER_PROCESS + /// 010: Exchange Table entry associated event is started + EM_ET_STATUS_STARTED = 0x02,//!< EM_ET_STATUS_STARTED + /// 011: Exchange Table entry associated event is terminated (normal termination) + EM_ET_STATUS_TERM_NORMAL = 0x03,//!< EM_ET_STATUS_TERM_NORMAL + /// 100: Exchange Table entry associated event is terminated (abort termination under prio bandwidth) + EM_ET_STATUS_TERM_ABORT_IN_PRIO_BW = 0x04,//!< EM_ET_STATUS_TERM_ABORT_IN_PRIO_BW + /// 101: Exchange Table entry associated event is terminated (abort termination after prio bandwidth) + EM_ET_STATUS_TERM_ABORT = 0x05,//!< EM_ET_STATUS_TERM_ABORT + /// 110: Exchange Table entry associated event is skipped + EM_ET_STATUS_SKIPPED = 0x06,//!< EM_ET_STATUS_SKIPPED + /// 111: Reserved for future use +}; + +/** + * ISOBUFSELn + * Used to select Isochronous channel Buffer Pointer + * 0x0: Uses ISO<0/1/2>PTR0 + * 0x1: Uses ISO<0/1/2>PTR1 + */ +#define EM_ET_ISO_PTR0 0x00 +#define EM_ET_ISO_PTR1 0x01 + +/** + * ISOn + * Indicates a Isochronous connection event is programmed + * 0x0: Not an Isochronous Channel event + * 0x1: Isochronous Channel event + */ +#define EM_ET_ISO_NOTPROGRAMMED 0x00 +#define EM_ET_ISO_PROGRAMMED 0x01 + +/** + * ISOCHANn[1:0] + * Meaningful if ISOn = 1 + * 00: Select Isochronous channel 0. + * 01: Select Isochronous channel 1. + * 10: Select Isochronous channel 2. + * 11: Trash received isochronous packet / Sent null length packet if ET-ISO = 1 / No Tx if ET-ISO = 0 + */ +#define EM_ET_ISO_CHANNEL_0 0x00 +#define EM_ET_ISO_CHANNEL_1 0x01 +#define EM_ET_ISO_CHANNEL_2 0x02 +#define EM_ET_ISO_NOCHANNEL 0x03 + + +/** + * RSVDn + * Indicates a reserved event + * 0x0: Not a reserved event (ISO connection re-Tx) + * 0x1: Reserved event (ISO connection primary event) + */ +#define EM_ET_ISO_NOT_RSVD 0x00 +#define EM_ET_ISO_RSVD 0x01 +/* + * FREQUENCY TABLE + **************************************************************************************** + */ + +/// Frequency table area definition +#define EM_FT_OFFSET (EM_ET_END) + +/// number of frequencies / Depends on RF target +#if defined(CFG_RF_ATLAS) + /// IcyTRx requires 40 x 32-bit words for Frequency table + 40 byte for VCO sub-band table + #define EM_RF_FREQ_TABLE_LEN 160 + #define EM_RF_VCO_TABLE_LEN 40 +#else + #if BT_EMB_PRESENT + /// Ripple/ExtRC requires 80 x 8-bit words for Frequency table / No VCO sub-band table + #define EM_RF_FREQ_TABLE_LEN 80 + #define EM_RF_VCO_TABLE_LEN 0 + #elif BLE_EMB_PRESENT + /// Ripple/ExtRC requires 40 x 8-bit words for Frequency table / No VCO sub-band table + #define EM_RF_FREQ_TABLE_LEN 40 + #define EM_RF_VCO_TABLE_LEN 0 + #endif // BT_EMB_PRESENT/BLE_EMB_PRESENT +#endif + +#define EM_FT_END (EM_FT_OFFSET + (EM_RF_VCO_TABLE_LEN + EM_RF_FREQ_TABLE_LEN) * sizeof(uint8_t)) + +/* + * RF SW SPI + **************************************************************************************** + */ +/// RF SW-Driven SPI transfers area definition +#if defined(CFG_RF_ATLAS) + /// IcyTYRx (Former Atlas) SW Driven SPI space + #define EM_RF_SW_SPI_OFFSET (EM_FT_END) + #define EM_RF_SW_SPI_SIZE_MAX 136 + #define EM_RF_SW_SPI_END (EM_RF_SW_SPI_OFFSET + EM_RF_SW_SPI_SIZE_MAX) + +#elif defined(CFG_RF_BTIPT) + /// BTIPT RF SW Driven SPI space + #define EM_RF_SW_SPI_OFFSET (EM_FT_END) + #define EM_RF_SW_SPI_SIZE_MAX 100 + #define EM_RF_SW_SPI_END (EM_RF_SW_SPI_OFFSET + EM_RF_SW_SPI_SIZE_MAX) +#else + /// Ripple SW Driven SPI space + /// RF-SW-SPI transfers area definition + #define EM_RF_SW_SPI_OFFSET (EM_FT_END) + #define EM_RF_SW_SPI_SIZE_MAX 8 + #define EM_RF_SW_SPI_END (EM_RF_SW_SPI_OFFSET + EM_RF_SW_SPI_SIZE_MAX) +#endif + + + +/* + * RF HW SPI + **************************************************************************************** + */ +/// RF HW-Driven SPI transfers area definition +#if defined(CFG_RF_ATLAS) + /// IcyTYRx (Former Atlas) SW Driven SPI space + #define EM_RF_HW_SPI_OFFSET (EM_RF_SW_SPI_END) + #define EM_RF_HW_SPI_SIZE_MAX 100 + #define EM_RF_HW_SPI_END (EM_RF_HW_SPI_OFFSET + EM_RF_HW_SPI_SIZE_MAX) + +#elif defined(CFG_RF_BTIPT) + /// BTIPT RF SW Driven SPI space + #define EM_RF_HW_SPI_OFFSET (EM_RF_SW_SPI_END) + #define EM_RF_HW_SPI_SIZE_MAX 0x100 + #define EM_RF_HW_SPI_END (EM_RF_HW_SPI_OFFSET + EM_RF_HW_SPI_SIZE_MAX) + +#else + /// Ripple SW Driven SPI space + /// RF-SW-SPI transfers area definition + #define EM_RF_HW_SPI_OFFSET (EM_RF_SW_SPI_END) + #define EM_RF_HW_SPI_SIZE_MAX 0 + #define EM_RF_HW_SPI_END (EM_RF_HW_SPI_OFFSET + EM_RF_HW_SPI_SIZE_MAX) +#endif + + +/// End of the common EM part +#define EM_COMMON_END (EM_RF_HW_SPI_END) + +#if (BLE_EMB_PRESENT || BT_EMB_PRESENT) +/* + * ENCRYPTION + **************************************************************************************** + */ + +/// Encryption area definition +#define EM_ENC_OFFSET COMMON_ALIGN4_HI(EM_COMMON_END) +#define EM_ENC_IN_OFFSET (EM_ENC_OFFSET) +#define EM_ENC_IN_SIZE (16) +#define EM_ENC_OUT_OFFSET (EM_ENC_IN_OFFSET + EM_ENC_IN_SIZE) +#define EM_ENC_OUT_SIZE (16) +#define EM_ENC_END (EM_ENC_OFFSET + EM_ENC_IN_SIZE + EM_ENC_OUT_SIZE) + +#endif // (BLE_EMB_PRESENT || BT_EMB_PRESENT) + +/* + **************************************************************************************** + ********************** BLE EM part ********************** + **************************************************************************************** + */ + +#define EM_BLE_OFFSET COMMON_ALIGN4_HI(EM_ENC_END) +#if BLE_EMB_PRESENT +#include "em_map_ble.h" +#else // BLE_EMB_PRESENT +#define EM_BLE_END (EM_BLE_OFFSET) +#endif // BLE_EMB_PRESENT + +/* + **************************************************************************************** + ********************** BT EM part ********************** + **************************************************************************************** + */ + +#define EM_BT_OFFSET COMMON_ALIGN4_HI(EM_BLE_END) +#if BT_EMB_PRESENT +#include "em_map_bt.h" +#else // BT_EMB_PRESENT +#define EM_BT_END (EM_BT_OFFSET) +#endif //BT_EMB_PRESENT + + +/* + * RF SPI part + **************************************************************************************** + */ + + +/// @} IPDEXMEM + +#endif // EM_MAP_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/hci/api/hci.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/hci/api/hci.h new file mode 100755 index 0000000..16f9cd2 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/hci/api/hci.h @@ -0,0 +1,848 @@ +#if (CFG_USE_BK_HOST) +/** + **************************************************************************************** + * + * @file hci.h + * + * @brief This file contains definitions related to the HCI module. + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef HCI_H_ +#define HCI_H_ + +/** + **************************************************************************************** + * @addtogroup HCI Host Controller Interface + * @ingroup ROOT + * @brief HCI module handling communication between lower and higher layers in split + * architecture. + * @{ + **************************************************************************************** + */ + + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" // SW configuration + +#if (HCI_PRESENT) + +#include // standard definition +#include // standard integer +#include "common_bt.h" // BT standard definitions + +#include "rwip_task.h" // Task definitions + +/* + * DEFINES + **************************************************************************************** + */ + +#if (BLE_EMB_PRESENT || BLE_HOST_PRESENT) +#if (BLE_CENTRAL || BLE_PERIPHERAL) +#define HCI_BLE_CON_SUPPORT 1 +#else // (BLE_CENTRAL || BLE_PERIPHERAL) +#define HCI_BLE_CON_SUPPORT 0 +#endif // (BLE_CENTRAL || BLE_PERIPHERAL) +#else //(BLE_EMB_PRESENT || BLE_HOST_PRESENT) +#define HCI_BLE_CON_SUPPORT 0 +#endif //(BLE_EMB_PRESENT || BLE_HOST_PRESENT) + +/// Length of HCI Reset Message +#define HCI_RESET_MSG_LEN 4 + +/// HCI Reset Message use to resync. +#define HCI_RESET_MSG_BUF {HCI_CMD_MSG_TYPE, (HCI_RESET_CMD_OPCODE & 0xFF), ((HCI_RESET_CMD_OPCODE >> 8) & 0xFF), 0} + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + +/// Message API of the HCI task +/*@TRACE*/ +enum hci_msg_id +{ + HCI_MSG_ID_FIRST = TASK_BLE_FIRST_MSG(TASK_BLE_ID_HCI), + + HCI_CMD_CMP_EVENT, + HCI_CMD_STAT_EVENT, + HCI_EVENT, + HCI_LE_EVENT, + + HCI_COMMAND, + + #if (HCI_BLE_CON_SUPPORT || BT_EMB_PRESENT) + HCI_ACL_DATA, + #endif // (HCI_BLE_CON_SUPPORT) + + #if BT_EMB_PRESENT + #if VOICE_OVER_HCI + HCI_SYNC_DATA, + #endif //VOICE_OVER_HCI + #endif //BT_EMB_PRESENT + + HCI_DBG_EVT, + + HCI_MSG_ID_LAST +}; + +/// Status of HCI command header processing +enum HCI_CMD_HDR +{ + /// Header is correct + HCI_CMD_HDR_STATUS_OK, + /// Opcode is unknown + HCI_CMD_HDR_STATUS_UNKNOWN, + /// Header is not correct + HCI_CMD_HDR_STATUS_FAIL +}; + + + +///HCI Command header components structure +struct hci_cmd_hdr +{ + /// Opcode field + uint16_t opcode; + ///Parameter length - the number of bytes of the command parameters + uint8_t parlen; +}; + +///HCI ACL data packets header structure +struct hci_acl_hdr +{ + ///Connection handle & Data Flags + uint16_t hdl_flags; + ///Data length in number of bytes + uint16_t datalen; +}; + +#if (BT_EMB_PRESENT) +#if (VOICE_OVER_HCI) +///HCI synchronous data packets header structure +struct hci_sync_hdr +{ + /// Connection handle & Data Flags + uint16_t conhdl_flags; + /// Data total length in number of bytes + uint8_t data_total_len; +}; +#endif // (VOICE_OVER_HCI) +#endif // (BT_EMB_PRESENT) + +///HCI Event header components structure - contains all details possible in an event +struct hci_evt_hdr +{ + ///Event code + uint8_t code; + ///Event parameters length + uint8_t parlen; +}; + +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ + + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** +**************************************************************************************** +* @brief Initialize HCI (including transport) +* +* @param[in] init_type Type of initialization (@see enum rwip_init_type) +***************************************************************************************** +*/ +void hci_init(uint8_t init_type); + +#if (BLE_EMB_PRESENT || BT_EMB_PRESENT) +/** + **************************************************************************************** + * @brief Function called when an internal task needs to send a HCI message to Host + * + * This function decides whether the message is sent externally onto HCI Transport Layer + * or redirected into an internal task of the other side of the HCI. + * + * The input message ID, length and parameters must be filled. + * In case the message is an HCI command or event, the source ID must be filled with the + * command opcode or event code. + * In case the message concerns a particular BT or BLE link, the destination ID must be + * filled with the associated link ID. + * + * @param[in] param Pointer to the parameters of the Kernel message carrying the HCI message + ***************************************************************************************** + */ +void hci_send_2_host(void *param); +#endif // (BLE_EMB_PRESENT || BT_EMB_PRESENT) + +#if BLE_HOST_PRESENT +/** + **************************************************************************************** + * @brief Function called when an internal task needs to send a HCI message to Controller + * + * This function decides whether the message is sent externally onto HCI Transport Layer + * or redirected into an internal task of the other side of the HCI. + * + * The input message ID, length and parameters must be filled. + * In case the message is an HCI command or event, the source ID must be filled with the + * command opcode or event code. + * In case the message concerns a particular BT or BLE link, the destination ID must be + * filled with the associated link ID. + * + * @param[in] param Pointer to the parameters of the Kernel message carrying the HCI message + ***************************************************************************************** + */ +void hci_send_2_controller(void *param); + +/** + **************************************************************************************** + * @brief function used to send a basic command, without parameters to the controller. + * + * @param[in] opcode Operation code of the command + ***************************************************************************************** + */ +void hci_basic_cmd_send_2_controller(uint16_t opcode); +#endif //BLE_HOST_PRESENT + +#if (BLE_EMB_PRESENT && HCI_BLE_CON_SUPPORT) +/** + **************************************************************************************** + * @brief Register connection handle for a BLE connection + * + * @param[in] link_id BLE connection link ID + ***************************************************************************************** + */ +void hci_ble_conhdl_register(uint8_t link_id); + +/** + **************************************************************************************** + * @brief Unregister a BLE connection + * + * @param[in] link_id BLE connection link ID + ***************************************************************************************** + */ +void hci_ble_conhdl_unregister(uint8_t link_id); +#endif //(BLE_EMB_PRESENT && !BLE_HOST_PRESENT && HCI_BLE_CON_SUPPORT) + +#if (BT_EMB_PRESENT) +/** + **************************************************************************************** + * @brief Register BD address for a BT ACL connection + * + * @param[in] link_id BT ACL connection link ID + * @param[in] bd_addr Pointer to the device BD address associated to the connection + ***************************************************************************************** + */ +void hci_bt_acl_bdaddr_register(uint8_t link_id, struct bd_addr* bd_addr); +/** + **************************************************************************************** + * @brief Register connection handle for a BT ACL connection + * + * @param[in] link_id BT ACL connection link ID + ***************************************************************************************** + */ +void hci_bt_acl_conhdl_register(uint8_t link_id); + +/** + **************************************************************************************** + * @brief Unregister a BT ACL connection + * + * @param[in] link_id BT ACL connection link ID + ***************************************************************************************** + */ +void hci_bt_acl_bdaddr_unregister(uint8_t link_id); + +#endif //(BT_EMB_PRESENT) + +/** + **************************************************************************************** + * @brief Set the event mask + * + * @param[in] evt_msk Pointer to the new event mask + * @param[in] page indicate which event page should be changed + * + * @return The status of the event mask saving + ***************************************************************************************** + */ +uint8_t hci_evt_mask_set(struct evt_mask const *evt_msk, uint8_t page); + +#if (BT_EMB_PRESENT) +/** + **************************************************************************************** + * @brief Add an event filter according to the parameters of the HCI command + * + * Note: the consistency of the parameters according to the input has already been checked by HCI during the special + * unpacking. + * + * @param[in] param Pointer to the HCI parameter + * + * @return The status of the filter addition + ***************************************************************************************** + */ +uint8_t hci_evt_filter_add(struct hci_set_evt_filter_cmd const *param); + +#if (MAX_NB_SYNC > 0) +/** + **************************************************************************************** + * @brief Get voice setting (for SCO auto-accept via event filter) + * + * @return Voice settings + ***************************************************************************************** + */ +uint16_t hci_voice_settings_get(void); + +/** + **************************************************************************************** + * @brief Set voice setting (for SCO auto-accept via event filter) + * + * @param[in] voice_settings Voice settings + * + * @return Status (0: Success | Others: failure) + ***************************************************************************************** + */ +uint8_t hci_voice_settings_set(uint16_t voice_settings); +#endif // (MAX_NB_SYNC > 0) +#endif //(BT_EMB_PRESENT) + +#if (HCI_TL_SUPPORT) +#if (BLE_EMB_PRESENT || BT_EMB_PRESENT) +/** + **************************************************************************************** + * @brief Get the maximum parameter size for a specific command + * + * This function is used by TL to know the theoretical maximum parameters size for a + * specific HCI command. + * Note: if the command is not supported by HCI (unknown), the maximum possible value of + * 255 bytes is returned. + * + * @param[in] opcode Opcode received + * + * @return The command maximum parameters size / 255 if command is unknown + ***************************************************************************************** + */ +uint8_t hci_cmd_get_max_param_size(uint16_t opcode); + +/** + **************************************************************************************** + * @brief Indicates that a HCI command has been received + * + * This function is used by TL to indicate the reception of a HCI command. + * + * @param[in] opcode Command Opcode + * @param[in] length Parameters length + * @param[in] payload Pointer to payload + ***************************************************************************************** + */ +void hci_cmd_received(uint16_t opcode, uint8_t length, uint8_t *payload); + +/** + **************************************************************************************** + * @brief Allocates the reception buffer for ACL TX data + * + * @param[in] hdl_flags Connection handle and data flags from HCI ACL packet header + * @param[in] len Length to receive (from HCI ACL packet header) + * + * @return Buffer for data reception (NULL if not possible to allocate one) + ***************************************************************************************** + */ +uint8_t* hci_acl_tx_data_alloc(uint16_t hdl_flags, uint16_t len); + +/** + **************************************************************************************** + * @brief Indicates that a HCI ACL TX data packet has been received + * + * This function is used by TL to indicate the reception of a HCI ACL TX data. + * + * @param[in] hdl_flags Connection handle and data flags from HCI ACL packet header + * @param[out] datalen Data length + * @param[in] payload Pointer to payload + ***************************************************************************************** + */ +void hci_acl_tx_data_received(uint16_t hdl_flags, uint16_t datalen, uint8_t * payload); + +#if (BT_EMB_PRESENT) +#if (VOICE_OVER_HCI) +/** + **************************************************************************************** + * @brief Allocates the reception buffer for Sync TX data + * + * @param[in] conhdl_flags Connection handle and data flags from HCI Sync packet header + * @param[in] len Length to receive (from HCI Sync packet header) + * + * @return Buffer for data reception (NULL if not possible to allocate one) + ***************************************************************************************** + */ +uint8_t* hci_sync_tx_data_alloc(uint16_t conhdl_flags, uint8_t len); + +/** + **************************************************************************************** + * @brief Indicates that a HCI Sync TX data packet has been received + * + * This function is used by TL to indicate the reception of a HCI Sync TX data. + * + * @param[in] conhdl_flags Connection handle and data flags from HCI Sync packet header + * @param[in] len Length to receive (from HCI Sync packet header) + * @param[in] payload Pointer to payload + ***************************************************************************************** + */ +void hci_sync_tx_data_received(uint16_t conhdl_flags, uint8_t len, uint8_t * payload); +#endif // (VOICE_OVER_HCI) +#endif // (BT_EMB_PRESENT) +#endif // (BLE_EMB_PRESENT || BT_EMB_PRESENT) + +#if ((BLE_HOST_PRESENT) && (!BLE_EMB_PRESENT)) +/** + **************************************************************************************** + * @brief Allocates the reception buffer for ACL RX data + * + * @param[in] hdl_flags Connection handle and data flags from HCI ACL RX packet header + * @param[in] len Length to receive (from HCI ACL packet header) + * + * @return Buffer for data reception (NULL if not possible to allocate one) + ***************************************************************************************** + */ +uint8_t* hci_acl_rx_data_alloc(uint16_t hdl_flags, uint16_t len); + +/** + **************************************************************************************** + * @brief Indicates that a HCI ACL RX data packet has been received + * + * This function is used by TL to indicate the reception of a HCI ACL RX data. + * + * @param[in] hdl_flags Connection handle and data flags from HCI ACL packet header + * @param[out] datalen Data length + * @param[in] payload Pointer to payload + ***************************************************************************************** + */ +void hci_acl_rx_data_received(uint16_t hdl_flags, uint16_t datalen, uint8_t * payload); + +/** + **************************************************************************************** + * @brief Indicates that a HCI event has been received + * + * This function is used by TL to indicate the reception of a HCI event. + * + * @param[in] code Event code + * @param[in] length Parameters length + * @param[in] payload Pointer to payload + * + * @return status of receive operation + ***************************************************************************************** + */ +uint8_t hci_evt_received(uint8_t code, uint8_t length, uint8_t *payload); +#endif // ((BLE_HOST_PRESENT) && (!BLE_EMB_PRESENT)) + +#endif // HCI_TL_SUPPORT + +//common for both BLE & BT +/** + **************************************************************************************** + * @brief process HostBufferSize + * + * @param[in] acl_pkt_len ACL packet length + * @param[in] nb_acl_pkts Number of ACL packets + * + * @return status + ***************************************************************************************** + */ +uint8_t hci_fc_acl_buf_size_set(uint16_t acl_pkt_len, uint16_t nb_acl_pkts); +/** + **************************************************************************************** + * @brief process HostBufferSize + * + * @param[in] sync_pkt_len SYNC packet length + * @param[in] nb_sync_pkts Number of SYNC packets + * + * @return status + ***************************************************************************************** + */ +uint8_t hci_fc_sync_buf_size_set(uint8_t sync_pkt_len, uint16_t nb_sync_pkts); + +/** + **************************************************************************************** + * @brief set the state of the ACL flow control + * + * @param[in] flow_enable boolean state of control + * + * @return status + ***************************************************************************************** + */ +uint8_t hci_fc_acl_en(bool flow_enable); + +/** + **************************************************************************************** + * @brief set the state of the SYNC flow control + * + * @param[in] flow_enable boolean state of control + ***************************************************************************************** + */ +void hci_fc_sync_en(bool flow_enable); + +/** + **************************************************************************************** + * @brief update data packet counters according to HostNumberOfCompletePackets + * + * @param[in] acl_pkt_nb accumulated number for ACL handles + ***************************************************************************************a** + */ +void hci_fc_host_nb_acl_pkts_complete(uint16_t acl_pkt_nb); + +/** + **************************************************************************************** + * @brief update data packet counters according to HostNumberOfCompletePackets + * + * @param[in] sync_pkt_nb accumulated number for SCO handles + ***************************************************************************************a** + */ +void hci_fc_host_nb_sync_pkts_complete(uint16_t sync_pkt_nb); + +#endif //HCI_PRESENT + +/// @} HCI + +#endif // HCI_H_ + +#else +#ifndef _BK72XX_HCI_EX_H_ +#define _BK72XX_HCI_EX_H_ + +#include "rtos_pub.h" + +#include "string.h" +#include "common_error.h" // error definition +#include "common_endian.h" // common endianess definition +#include "common_list.h" // list definition + +#include "uart_pub.h" +#include "common_bt_defines.h" +#include "rwip_config.h" // SW configuration + +#include // standard definition +#include // standard integer +#include "common_bt.h" // BT standard definitions + +#include "rwip_task.h" // Task definitions + +/* + * DEFINES + **************************************************************************************** + */ + +/** + * CONFIG_BT_RX_BUF_LEN: the max length for rx buffer + * range 73 to 2000 + */ +#ifndef CONFIG_BT_RX_BUF_LEN +#define CONFIG_BT_RX_BUF_LEN 250 +#endif + +#define _DEVICE_NAME_MAX_LEN (18) + +#define HCI_RECV_BUF_LEN CONFIG_BT_RX_BUF_LEN + +#ifndef HCI_LOG +#define HCI_LOG os_printf +#endif +#ifndef HCI_INFO +#define HCI_INFO HCI_LOG +#endif +#ifndef HCI_DBG +#define HCI_DBG HCI_LOG +#endif + +#define HCI_MALLOC(size) os_malloc(size) +#define HCI_FREE(ptr) os_free(ptr) + +#ifndef CONFIG_BK_HCI_TASK_PRI +#define CONFIG_BK_HCI_TASK_PRI (BEKEN_DEFAULT_WORKER_PRIORITY - 0) +#endif + +#ifndef CONFIG_BK_HCI_RECV_PRIO_TASK_PRI +#define CONFIG_BK_HCI_RECV_PRIO_TASK_PRI (BEKEN_DEFAULT_WORKER_PRIORITY - 0) +#endif + +#ifndef CONFIG_BK_HCI_RECV_TASK_PRI +#define CONFIG_BK_HCI_RECV_TASK_PRI (BEKEN_DEFAULT_WORKER_PRIORITY - 0) +#endif + +#ifndef CONFIG_BK_HCI_TASK_SEM_TIMEROUT +#define CONFIG_BK_HCI_TASK_SEM_TIMEROUT (SECONDS/10) +#endif + +#define CONFIG_BK_HCI_RECV_PRIO_TASK_STACK_SIZE 3 * 1024 +#define CONFIG_BK_HCI_RECV_TASK_STACK_SIZE 3 * 1024 +//#define CONFIG_BK_HCI_TASK_STACK_SIZE 3 * 1024 + +/** + * Destination field decoding + * + * bit | 7 6 | 5 4 | 3..0 | + * def | Rsvd (pkupk) | HL | LL | + */ +#define HCI_CMD_DEST_LL_POS 0 +#define HCI_CMD_DEST_LL_MASK 0x0F +#define HCI_CMD_DEST_HL_POS 4 +#define HCI_CMD_DEST_HL_MASK 0x30 + +/// Macro for building a command descriptor in full mode (without parameters packing/unpacking) +#define CMD(opcode, dest_ll, dest_hl) {HCI_##opcode##_CMD_OPCODE, (dest_ll << HCI_CMD_DEST_LL_POS) | (dest_hl << HCI_CMD_DEST_HL_POS)} + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ +/// Message API of the HCI task +/*@TRACE*/ +enum hci_msg_id { + HCI_MSG_ID_FIRST = TASK_BLE_FIRST_MSG(TASK_BLE_ID_HCI), + HCI_CMD_CMP_EVENT, + HCI_CMD_STAT_EVENT, + HCI_EVENT, + HCI_LE_EVENT, + + HCI_COMMAND, + + HCI_ACL_DATA, + +#if BT_EMB_PRESENT +#if VOICE_OVER_HCI + HCI_SYNC_DATA, +#endif //VOICE_OVER_HCI +#endif //BT_EMB_PRESENT + + HCI_DBG_EVT, + + HCI_MSG_ID_LAST +}; + +/// Possible destination field values within lower layers +enum HCI_MSG_DEST_LL { + MNG, + CTRL, + BLE_MNG, + BLE_CTRL, + BT_MNG, + BT_CTRL_CONHDL, + BT_CTRL_BD_ADDR, + BT_BCST, + DBG, + BLE_ISO, + LL_UNDEF, +}; + +/// Possible destination field values within higher layers +enum HCI_MSG_DEST_HL { + HL_MNG, + HL_CTRL, + HL_DATA, + HL_ISO0, + HL_UNDEF, +}; + +#pragma pack(push, 1) /* push current alignment to stack & set alignment to 1 byte boundary */ +///HCI Command header components structure +struct hci_cmd_hdr { + /// Opcode field + uint16_t opcode; + ///Parameter length - the number of bytes of the command parameters + uint8_t parlen; +}; + +///HCI ACL data packets header structure +struct hci_acl_hdr { + ///Connection handle & Data Flags + uint16_t hdl_flags; + ///Data length in number of bytes + uint16_t datalen; +}; + +#if (BT_EMB_PRESENT) +#if (VOICE_OVER_HCI) +///HCI synchronous data packets header structure +struct hci_sync_hdr { + /// Connection handle & Data Flags + uint16_t conhdl_flags; + /// Data total length in number of bytes + uint8_t data_total_len; +}; +#endif // (VOICE_OVER_HCI) +#endif // (BT_EMB_PRESENT) + +///HCI Event header components structure - contains all details possible in an event +struct hci_evt_hdr { + ///Event code + uint8_t code; + ///Event parameters length + uint8_t parlen; +}; +#pragma pack(pop) /* restore original alignment from stack */ + +typedef struct bk_ble_hci_buf_s { + /// list header + struct common_list_hdr hdr; + + uint8_t type; + uint16_t len; + uint8_t buf[]; +} bk_ble_hci_buf_t; + +/// HCI command descriptor structure +struct hci_cmd_desc_tab_ref { + /// OpCode Group Field (OGF) + uint8_t ogf; + + /// Number of commands supported in this group + uint16_t nb_cmds; + + /// Command descriptor table + const struct hci_cmd_desc_tag* cmd_desc_tab; +}; + +/// HCI command descriptor structure +struct hci_cmd_desc_tag { + /// Command opcode with flags indicating if a special packing or unpacking is needed + uint16_t opcode; + + /// Destination field (used to find the internal destination task) + uint8_t dest_field; +}; + +//hci event cb +typedef int (*hci_func_evt_cb)(uint8_t *p_buf, uint8_t buf_len); + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Function called when an internal task needs to send a HCI message to Host + * + * This function decides whether the message is sent externally onto HCI Transport Layer + * or redirected into an internal task of the other side of the HCI. + * + * The input message ID, length and parameters must be filled. + * In case the message is an HCI command or event, the source ID must be filled with the + * command opcode or event code. + * In case the message concerns a particular BT or BLE link, the destination ID must be + * filled with the associated link ID. + * + * @param[in] param Pointer to the parameters of the Kernel message carrying the HCI message + ***************************************************************************************** + */ + +void hci_send_2_host(void *param); + +/** + **************************************************************************************** + * @brief Function called when an internal task needs to send a HCI message to Controller + * + * This function decides whether the message is sent externally onto HCI Transport Layer + * or redirected into an internal task of the other side of the HCI. + * + * The input message ID, length and parameters must be filled. + * In case the message is an HCI command or event, the source ID must be filled with the + * command opcode or event code. + * In case the message concerns a particular BT or BLE link, the destination ID must be + * filled with the associated link ID. + * + * @param[in] param Pointer to the parameters of the Kernel message carrying the HCI message + ***************************************************************************************** + */ +void hci_send_2_controller(void *param); + +/** + **************************************************************************************** + * @brief Register connection handle for a BLE connection + * + * @param[in] link_id BLE connection link ID + ***************************************************************************************** + */ +void hci_ble_conhdl_register(uint8_t link_id); + +/** + **************************************************************************************** + * @brief Unregister a BLE connection + * + * @param[in] link_id BLE connection link ID + ***************************************************************************************** + */ +void hci_ble_conhdl_unregister(uint8_t link_id); + +/** + **************************************************************************************** + * @brief Set the event mask + * + * @param[in] evt_msk Pointer to the new event mask + * @param[in] page indicate which event page should be changed + * + * @return The status of the event mask saving + ***************************************************************************************** + */ +uint8_t hci_evt_mask_set(struct evt_mask const *evt_msk, uint8_t page); + +/** + **************************************************************************************** + * @brief set the state of the ACL flow control + * + * @param[in] flow_enable boolean state of control + * + * @return status + ***************************************************************************************** + */ +uint8_t hci_fc_acl_en(bool flow_enable); + +//common for both BLE & BT +/** + **************************************************************************************** + * @brief process HostBufferSize + * + * @param[in] acl_pkt_len ACL packet length + * @param[in] nb_acl_pkts Number of ACL packets + * + * @return status + ***************************************************************************************** + */ +uint8_t hci_fc_acl_buf_size_set(uint16_t acl_pkt_len, uint16_t nb_acl_pkts); + +/** + **************************************************************************************** + * @brief update data packet counters according to HostNumberOfCompletePackets + * + * @param[in] acl_pkt_nb accumulated number for ACL handles + ***************************************************************************************a** + */ +void hci_fc_host_nb_acl_pkts_complete(uint16_t acl_pkt_nb); + +int hci_driver_open(void); + +int hci_driver_send(uint8_t type, uint16_t len, uint8_t *buf); + +/** + **************************************************************************************** + * @brief set event cmd and acl data call back + * + * @param[in] sync_pkt_nb accumulated number for SCO handles + ***************************************************************************************a** + */ +void hci_set_event_callback(hci_func_evt_cb hci_cmd_cb, hci_func_evt_cb hci_acl_cb); + +#endif +#endif + +///Eof + diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/hci/src/hci.c b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/hci/src/hci.c new file mode 100755 index 0000000..4301fab --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/hci/src/hci.c @@ -0,0 +1,2889 @@ +/** + **************************************************************************************** + * + * @file hci.c + * + * @brief HCI module source file. + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @addtogroup HCI + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" // SW configuration + +#if (CFG_USE_BK_HOST) +#if (HCI_PRESENT) +#include "rwip.h" // IP definitions +#include // string manipulation +#include "common_error.h" // error definition +#include "common_utils.h" // common utility definition +#include "common_list.h" // list definition + +#include "hci.h" // hci definition +#include "hci_int.h" // hci internal definition + +#include "kernel_msg.h" // kernel message declaration +#include "kernel_task.h" // kernel task definition +#include "kernel_event.h" // kernel event definition +#include "kernel_mem.h" // kernel memory definition +#include "kernel_timer.h" // kernel timer definition + +#if (BLE_HOST_PRESENT) +#include "gapc.h" // use to retrieve the connection index from the connection handle +#endif //(BLE_HOST_PRESENT) + +#include "dbg.h" + +/* + * DEFINES + **************************************************************************************** + */ + + +/* + * ENUMERATIONS DEFINITIONS + **************************************************************************************** + */ + +/* + * STRUCTURES DEFINITIONS + **************************************************************************************** + */ + + + +/* + * CONSTANTS DEFINITIONS + **************************************************************************************** + */ + +/// Default event mask +static const struct evt_mask hci_def_evt_msk = {EVT_MASK_DEFAULT}; + +#if (BLE_EMB_PRESENT) +/// Default LE event mask +static const struct evt_mask hci_le_def_evt_msk = {BLE_EVT_MASK}; +#endif // (BLE_EMB_PRESENT) + +/// Reserved event mask +static const struct evt_mask hci_rsvd_evt_msk = {{0x00, 0x60, 0x04, 0x00, 0xF8, 0x07, 0x40, 0x02}}; + + +/* + * GLOBAL VARIABLE DEFINITIONS + **************************************************************************************** + */ + +#if (BLE_EMB_PRESENT && BLE_HOST_PRESENT && HCI_TL_SUPPORT) +/** + * Indicate if HCI is used by external Host, or internal Host. + * Used in Full mode only. By default HCI is used by internal Host. + * HCI switches to external host as soon as an HCI command is received. + * This variable should not be reset. + */ +bool hci_ext_host; +#endif // (BLE_EMB_PRESENT && BLE_HOST_PRESENT && HCI_TL_SUPPORT) + +///HCI environment context +struct hci_env_tag hci_env; + + +/* + * LOCAL FUNCTION DEFINITIONS + **************************************************************************************** + */ + +#if (BLE_EMB_PRESENT || BT_EMB_PRESENT) +/** + **************************************************************************************** + * @brief Check if the event to be sent to the host is masked or not + * + * @param[in] msg Pointer to the message containing the event + * + * @return true id the message has to be filtered out, false otherwise + ***************************************************************************************** + */ +static bool hci_evt_mask_check(struct kernel_msg *msg) +{ + bool masked = false; + uint8_t evt_code; + + switch(msg->id) + { + case HCI_LE_EVENT: + { + // LE meta event + evt_code = HCI_LE_META_EVT_CODE; + } + break; + case HCI_EVENT: + { + // Get event code + evt_code = msg->src_id; + } + break; + + default: + { + // Cannot be masked + return false; + } + } + + // Check if this event is maskable + if(evt_code < HCI_MAX_EVT_MSK_PAGE_1_CODE) + { + uint8_t index = evt_code - 1; + + //Checking if the event is masked or not + masked = ((hci_env.evt_msk.mask[index>>3] & (1<<(index & 0x07))) == 0x00); + + #if (BLE_EMB_PRESENT) + if (!masked && (evt_code == HCI_LE_META_EVT_CODE)) + { + // Get Sub-code of the mevent + uint8_t *subcode = (uint8_t*)kernel_msg2param(msg); + //Translate the subcode in index to parse the mask + uint8_t index = *subcode - 1; + //Checking if the event is masked or not + masked =((hci_env.le_evt_msk.mask[index>>3] & (1<<(index & 0x07))) == 0x00); + } + #endif // (BLE_EMB_PRESENT) + } + else if(evt_code < HCI_MAX_EVT_MSK_PAGE_2_CODE) + { + // In this area the evt code is in the range [EVT_MASK_CODE_MAX>3] & (1<<(index & 0x07))) == 0x00); + } + return masked; +} +#endif //(BLE_EMB_PRESENT || BT_EMB_PRESENT) + +#if BT_EMB_PRESENT +/** + **************************************************************************************** + * @brief Check if a connection request event has to be forwarded to the host or not + * This function also takes the required decisions according to the auto_accept parameter + * + * @param[in] bdaddr BDADDR contained in the inquiry result event + * @param[in] class Class of device contained in the inquiry result event + * @param[in] link_type Type of link that is requested (asynchronous or synchronous) + * + * @return true if the event has to be filtered out, false otherwise + ***************************************************************************************** + */ +static uint8_t hci_evt_filter_con_check(struct bd_addr *bdaddr, struct devclass *classofdev, uint8_t link_type, uint8_t link_id) +{ + uint8_t filtered = false; + uint8_t auto_accept = DO_NOT_AUTO_ACCEPT_CONNECTION; + + /* Check if a Connection type is present (start from last to first) */ + for (int i = HCI_FILTER_NB - 1 ; i >= 0 ; i--) + { + struct hci_evt_filter_tag *filter = &hci_env.evt_filter[i]; + + // If this filter is a ConnectionSetupFilter + if ((filter->in_use == true) && (filter->type == CONNECTION_FILTER_TYPE)) + { + // There is at least one connection filter set, so now we should reject by default unless + // the connection request matches one of the filters + auto_accept = 0xFF; + + // If the condition is a All Device type + if (filter->condition == ALL_FILTER_CONDITION_TYPE) + { + // This connection will not be rejected + auto_accept = filter->auto_accept; + break; + } + // If the condition is a ClassOfDevice type + else if (filter->condition == CLASS_FILTER_CONDITION_TYPE) + { + struct devclass class_masked; + struct classofdevcondition *cond = &filter->param.device_class; + + // Remove don't care bit of Class Of Device + class_masked.A[0] = classofdev->A[0] & cond->class_mask.A[0]; + class_masked.A[1] = classofdev->A[1] & cond->class_mask.A[1]; + class_masked.A[2] = classofdev->A[2] & cond->class_mask.A[2]; + + // Check if any device class is allowed or the Class of the filter matches the Class of the Inquiry result + if ( (cond->classofdev.A[0] == 0 && cond->classofdev.A[1] == 0 && cond->classofdev.A[2] == 0) + || !memcmp(&class_masked, &cond->classofdev, sizeof(struct devclass))) + { + // This connection will not be rejected + auto_accept = filter->auto_accept; + break; + } + } + /* If this filter is a ConnectionFilter */ + else if (filter->condition == BD_ADDR_FILTER_CONDITION_TYPE) + { + // Check if the BdAddr of the filter matches the BdAddr of the Connect req + if (!memcmp(bdaddr, &filter->param.bdaddr, sizeof(struct bd_addr))) + { + // This connection will not be rejected + auto_accept = filter->auto_accept; + break; + } + } + } + } + + if ((auto_accept == ACCEPT_CONNECTION_SLAVE) || (auto_accept == ACCEPT_CONNECTION_MASTER)) + { + // Auto accept the connection request + filtered = true; + + // If this is an ACL link + if (link_type == ACL_TYPE) + { + struct hci_accept_con_req_cmd *cmd = KERNEL_MSG_ALLOC(HCI_COMMAND, KERNEL_BUILD_ID(TASK_BLE_LC, link_id), HCI_ACCEPT_CON_REQ_CMD_OPCODE, hci_accept_con_req_cmd); + + // Fill-in the parameter structure + if (auto_accept == ACCEPT_CONNECTION_SLAVE) + { + cmd->role = ACCEPT_REMAIN_SLAVE; + } + else + { + cmd->role = ACCEPT_SWITCH_TO_MASTER; + } + cmd->bd_addr = *bdaddr; + + // Send the message + kernel_msg_send(cmd); + + // Save opcode, used to filter the returning CS event + hci_env.auto_accept_opcode = HCI_ACCEPT_CON_REQ_CMD_OPCODE; + } + #if (MAX_NB_SYNC > 0) + // If this is a Synchronous Link (SCO or eSCO) + else + { + struct hci_accept_sync_con_req_cmd *cmd = KERNEL_MSG_ALLOC(HCI_COMMAND, KERNEL_BUILD_ID(TASK_BLE_LC, link_id), HCI_ACCEPT_SYNC_CON_REQ_CMD_OPCODE, hci_accept_sync_con_req_cmd); + + // Fill in parameter structure + cmd->bd_addr = *bdaddr; + cmd->tx_bw = SYNC_BANDWIDTH_DONT_CARE; + cmd->rx_bw = SYNC_BANDWIDTH_DONT_CARE; + cmd->max_lat = SYNC_DONT_CARE_LATENCY; + cmd->vx_set = hci_env.voice_settings; + cmd->retx_eff = SYNC_RE_TX_DONT_CARE; + cmd->pkt_type = 0xFFFF; /// All packet type + + // Send the message + kernel_msg_send(cmd); + + // Save opcode, used to filter the returning CS event + hci_env.auto_accept_opcode = HCI_ACCEPT_SYNC_CON_REQ_CMD_OPCODE; + } + #endif // (MAX_NB_SYNC > 0) + } + else if (auto_accept != DO_NOT_AUTO_ACCEPT_CONNECTION) + { + // This Device does not match a filter => filtered and rejected + filtered = true; + + // If this is an ACL link + if (link_type == ACL_TYPE) + { + struct hci_reject_con_req_cmd *cmd = KERNEL_MSG_ALLOC(HCI_COMMAND, KERNEL_BUILD_ID(TASK_BLE_LC, link_id), HCI_REJECT_CON_REQ_CMD_OPCODE, hci_reject_con_req_cmd); + cmd->bd_addr = *bdaddr; + cmd->reason = COMMON_ERROR_CONN_REJ_UNACCEPTABLE_BDADDR; + kernel_msg_send(cmd); + + // Save opcode, used to filter the returning CS event + hci_env.auto_accept_opcode = HCI_REJECT_CON_REQ_CMD_OPCODE; + } + #if (MAX_NB_SYNC > 0) + // If this is a Synchronous Link (SCO or eSCO) + else + { + struct hci_reject_sync_con_req_cmd *cmd = KERNEL_MSG_ALLOC(HCI_COMMAND, KERNEL_BUILD_ID(TASK_BLE_LC, link_id), HCI_REJECT_SYNC_CON_REQ_CMD_OPCODE, hci_reject_sync_con_req_cmd); + cmd->bd_addr = *bdaddr; + cmd->reason = COMMON_ERROR_CONN_REJ_UNACCEPTABLE_BDADDR; + kernel_msg_send(cmd); + + // Save opcode, used to filter the returning CS event + hci_env.auto_accept_opcode = HCI_REJECT_SYNC_CON_REQ_CMD_OPCODE; + } + #endif // (MAX_NB_SYNC > 0) + } + + return(filtered); +} + +/** + **************************************************************************************** + * @brief Check if an inquiry result event has to be forwarded to the host or not + * + * @param[in] bdaddr BDADDR contained in the inquiry result event + * @param[in] class Class of device contained in the inquiry result event + * + * @return true if the event has to be filtered out, false otherwise + ***************************************************************************************** + */ +static uint8_t hci_evt_filter_inq_check(struct bd_addr *bdaddr, struct devclass *classofdev) +{ + int i; + uint8_t filtered = false; // By default the event is not filtered + struct devclass empty_classofdev = {{0,0,0}}; + + // Check if an inquiry filter type is present + for (i = 0; i < HCI_FILTER_NB; i++) + { + struct hci_evt_filter_tag *filter = &hci_env.evt_filter[i]; + + // If this filter is an InquiryFilter + if ((filter->in_use == true) && (filter->type == INQUIRY_FILTER_TYPE)) + { + // There is at least one inquiry filter set, so now we should filter unless + // the inquiry result matches one of the filters + filtered = true; + + // If the condition is a ClassOfDevice type + if (filter->condition == CLASS_FILTER_CONDITION_TYPE) + { + struct devclass class_masked; + struct classofdevcondition *cond = &filter->param.device_class; + + // Remove don't care bit of Class Of Device + class_masked.A[0] = classofdev->A[0] & cond->class_mask.A[0]; + class_masked.A[1] = classofdev->A[1] & cond->class_mask.A[1]; + class_masked.A[2] = classofdev->A[2] & cond->class_mask.A[2]; + + // Check if the Class of the filter match the Class of the Inquiry result + if ( !memcmp(&empty_classofdev.A[0], &cond->classofdev.A[0], sizeof(struct devclass)) + || !memcmp(&class_masked.A[0] , &cond->classofdev.A[0], sizeof(struct devclass)) ) + { + // This InquiryResult must NOT be filtered + filtered = false; + break; + } + } + // If this filter is a BDADDR type + else if (filter->condition == BD_ADDR_FILTER_CONDITION_TYPE) + { + // Check if the BdAddr of the filter match the BdAddr of the Inquiry res + if (!memcmp(bdaddr, &filter->param.bdaddr, sizeof(struct bd_addr))) + { + // This InquiryResult must NOT be filtered + filtered = false; + break; + } + } + } + } + + return(filtered); +} + +/** + **************************************************************************************** + * @brief Check if an event has to be forwarded to the host or not + * + * @param[in] msg Pointer to the event message to be transmitted to the host + * + * @return true if the event has to be filtered out, false otherwise + ***************************************************************************************** + */ +static uint8_t hci_evt_filter_check(struct kernel_msg *msg) +{ + uint8_t filtered = false; + + switch(msg->id) + { + case HCI_EVENT: + { + // Get event code + uint8_t evt_code = msg->src_id; + uint8_t *param = (uint8_t *)msg->param; + + switch(evt_code) + { + // InquiryResult Event + case HCI_INQ_RES_EVT_CODE: + case HCI_INQ_RES_WITH_RSSI_EVT_CODE: + case HCI_EXT_INQ_RES_EVT_CODE: + { + struct devclass *classofdev; + // Retrieve the information required for the filtering from the PDU + struct bd_addr * bdaddr = (struct bd_addr *)¶m[1]; + if(evt_code == HCI_INQ_RES_EVT_CODE) + { + struct hci_inq_res_evt *evt = (struct hci_inq_res_evt *) param; + classofdev = (struct devclass *)&evt->class_of_dev; + } + else + { + struct hci_ext_inq_res_evt *evt = (struct hci_ext_inq_res_evt *) param; + classofdev = (struct devclass *)&evt->class_of_dev; + } + + // Check if the event has to be filtered or not + filtered = hci_evt_filter_inq_check(bdaddr, classofdev); + } + break; + // Connection Request Event + case HCI_CON_REQ_EVT_CODE: + { + // Retrieve the information required for the filtering from the PDU + struct bd_addr * bdaddr = (struct bd_addr *)¶m[0]; + struct devclass *classofdev = (struct devclass *)¶m[6]; + uint8_t link_type = param[9]; + + // Check if the event has to be filtered or not + filtered = hci_evt_filter_con_check(bdaddr, classofdev, link_type, msg->dest_id); + } + break; + // Connection Complete Event + case HCI_CON_CMP_EVT_CODE: + { + // Check if a connection was auto-rejected + if(hci_env.auto_reject) + { + filtered = true; + hci_env.auto_reject = false; + } + } + break; + default: + { + // Nothing to do + } + } + } + break; + + case HCI_CMD_STAT_EVENT: + { + // Filter CS event associated to the current auto-accept command + if(msg->src_id == hci_env.auto_accept_opcode) + { + filtered = true; + hci_env.auto_accept_opcode = 0x0000; + + if(msg->src_id == HCI_REJECT_CON_REQ_CMD_OPCODE) + { + hci_env.auto_reject = true; + } + } + } + break; + + default: + { + // Not an event + } + break; + } + + return filtered; +} + +/** + **************************************************************************************** + * @brief Reset the list of event filters + * + * @return Status + ***************************************************************************************** + */ +static uint8_t hci_evt_filter_reset(void) +{ + for (int i = 0 ; i < HCI_FILTER_NB; i++) + { + hci_env.evt_filter[i].in_use = false; + } + return (COMMON_ERROR_NO_ERROR); +} + +/** + **************************************************************************************** + * @brief Allocate an event filter structure + * + * @return A pointer to the allocated filter, if any, NULL otherwise + ***************************************************************************************** + */ +static struct hci_evt_filter_tag *hci_evt_filter_alloc(void) +{ + int i; + struct hci_evt_filter_tag *evt_filter; + + for (i = 0; i < HCI_FILTER_NB; i++) + { + if (hci_env.evt_filter[i].in_use == false) + { + break; + } + } + if (i < HCI_FILTER_NB) + { + evt_filter = &hci_env.evt_filter[i]; + evt_filter->in_use = true; + } + else + { + evt_filter = NULL; + } + + return(evt_filter); +} + +/** + **************************************************************************************** + * @brief Add an inquiry event filter + * + * @param[in] condition Filter condition type + * @param[in] param Pointer to the condition parameters + * + * @return The status of the filter addition + ***************************************************************************************** + */ +static uint8_t hci_evt_filter_inq_add(struct inq_res_filter const * filter) +{ + uint8_t status = COMMON_ERROR_INVALID_HCI_PARAM; + struct hci_evt_filter_tag *evt_filter; + + switch (filter->cond_type) + { + case ALL_FILTER_CONDITION_TYPE: + { + // Remove all Inquiry type + for (int i = 0 ; i < HCI_FILTER_NB ; i++) + { + if (hci_env.evt_filter[i].type == INQUIRY_FILTER_TYPE) + { + hci_env.evt_filter[i].in_use = false; + } + } + + status = COMMON_ERROR_NO_ERROR; + } + break; + + case CLASS_FILTER_CONDITION_TYPE: + case BD_ADDR_FILTER_CONDITION_TYPE: + { + // Add the new filter + evt_filter = hci_evt_filter_alloc(); + if (evt_filter != NULL) + { + evt_filter->type = INQUIRY_FILTER_TYPE; + evt_filter->condition = filter->cond_type; + if (filter->cond_type == CLASS_FILTER_CONDITION_TYPE) + { + struct classofdevcondition *dev_class = &evt_filter->param.device_class; + // Store the mask + dev_class->class_mask = filter->cond.cond_1.class_of_dev_msk; + + // Store the class, masked with the class mask + dev_class->classofdev.A[0] = filter->cond.cond_1.class_of_dev.A[0] & filter->cond.cond_1.class_of_dev_msk.A[0]; + dev_class->classofdev.A[1] = filter->cond.cond_1.class_of_dev.A[1] & filter->cond.cond_1.class_of_dev_msk.A[1]; + dev_class->classofdev.A[2] = filter->cond.cond_1.class_of_dev.A[2] & filter->cond.cond_1.class_of_dev_msk.A[2]; + } + else + { + evt_filter->param.bdaddr = filter->cond.cond_2.bd_addr; + } + status = COMMON_ERROR_NO_ERROR; + } + else + { + status = COMMON_ERROR_MEMORY_CAPA_EXCEED; + } + } + break; + + default: + { + // Nothing to do + } + break; + } + return(status); +} + + +/** + **************************************************************************************** + * @brief Add a connection event filter + * + * @param[in] condition Filter condition type + * @param[in] param Pointer to the condition parameters + * + * @return The status of the filter addition + ***************************************************************************************** + */ +static uint8_t hci_evt_filter_con_add(struct con_set_filter const * filter) +{ + uint8_t status = COMMON_ERROR_NO_ERROR; + struct hci_evt_filter_tag *evt_filter; + + switch (filter->cond_type) + { + case ALL_FILTER_CONDITION_TYPE: + { + uint8_t auto_accept = filter->cond.cond_0.auto_accept; + // Check auto_accept parameter + if ((auto_accept >= DO_NOT_AUTO_ACCEPT_CONNECTION) && (auto_accept <= ACCEPT_CONNECTION_MASTER)) + { + // Remove all Connection type + for (int i = 0 ; i < HCI_FILTER_NB ; i++) + { + if (hci_env.evt_filter[i].type == CONNECTION_FILTER_TYPE) + { + hci_env.evt_filter[i].in_use = false; + } + } + // Add the new filter + evt_filter = hci_evt_filter_alloc(); + if (evt_filter != NULL) + { + evt_filter->type = CONNECTION_FILTER_TYPE; + evt_filter->condition = ALL_FILTER_CONDITION_TYPE; + evt_filter->auto_accept = auto_accept; + } + else + { + status = COMMON_ERROR_MEMORY_CAPA_EXCEED; + } + } + } + break; + + case CLASS_FILTER_CONDITION_TYPE: + case BD_ADDR_FILTER_CONDITION_TYPE: + { + uint8_t auto_accept = filter->cond.cond_1.auto_accept; + // Check auto_accept parameter + if ((auto_accept >= DO_NOT_AUTO_ACCEPT_CONNECTION) && (auto_accept <= ACCEPT_CONNECTION_MASTER)) + { + // Remove all Connection type with ALL_FILTER_CONDITION_TYPE set + for (int i = 0; i < HCI_FILTER_NB ; i++) + { + if ((hci_env.evt_filter[i].in_use == true) && + (hci_env.evt_filter[i].type == CONNECTION_FILTER_TYPE) && + (hci_env.evt_filter[i].condition == ALL_FILTER_CONDITION_TYPE)) + { + hci_env.evt_filter[i].in_use = false; + } + } + // Add the new filter + evt_filter = hci_evt_filter_alloc(); + if (evt_filter != NULL) + { + evt_filter->type = CONNECTION_FILTER_TYPE; + evt_filter->condition = filter->cond_type; + evt_filter->auto_accept = auto_accept; + if (filter->cond_type == CLASS_FILTER_CONDITION_TYPE) + { + struct classofdevcondition *dev_class = &evt_filter->param.device_class; + // Store the mask + dev_class->class_mask = filter->cond.cond_1.class_of_dev_msk; + + // Store the class, masked with the class mask + dev_class->classofdev.A[0] = filter->cond.cond_1.class_of_dev.A[0] & filter->cond.cond_1.class_of_dev_msk.A[0]; + dev_class->classofdev.A[1] = filter->cond.cond_1.class_of_dev.A[1] & filter->cond.cond_1.class_of_dev_msk.A[1]; + dev_class->classofdev.A[2] = filter->cond.cond_1.class_of_dev.A[2] & filter->cond.cond_1.class_of_dev_msk.A[2]; + } + else + { + evt_filter->param.bdaddr = filter->cond.cond_2.bd_addr; + } + } + else + { + status = COMMON_ERROR_MEMORY_CAPA_EXCEED; + } + } + else + { + status = COMMON_ERROR_INVALID_HCI_PARAM; + } + } + break; + + default: + { + // Nothing to do + } + break; + } + + return(status); +} +#endif //BT_EMB_PRESENT + + +/* + * MODULES INTERNAL FUNCTION DEFINITIONS + **************************************************************************************** + */ + + +/* + * EXPORTED FUNCTION DEFINITIONS + **************************************************************************************** + */ + +void hci_init(uint8_t init_type) +{ + switch (init_type) + { + case RWIP_INIT: + { + #if (BLE_EMB_PRESENT && BLE_HOST_PRESENT && HCI_TL_SUPPORT) + if(!init_type) + { + // HCI used by internal Host by default + hci_ext_host = false; + } + #endif // (BLE_EMB_PRESENT && BLE_HOST_PRESENT && HCI_TL_SUPPORT) + } + // No break + + case RWIP_RST: + { + memset(&hci_env, 0, sizeof(hci_env)); + + // Initialize event mask + hci_evt_mask_set(&hci_def_evt_msk, HCI_PAGE_DFT); + + #if (BLE_EMB_PRESENT) + // Initialize LE event mask + hci_evt_mask_set(&hci_le_def_evt_msk, HCI_PAGE_LE); + #endif // (BLE_EMB_PRESENT) + + #if (BT_EMB_PRESENT || BLE_EMB_PRESENT) + hci_fc_init(); + #endif //(BT_EMB_PRESENT || BLE_EMB_PRESENT) + } + break; + + case RWIP_1ST_RST: + { + // Do nothing + } + break; + + default: + { + // Do nothing + } + break; + } + + #if (HCI_TL_SUPPORT) + // Reset the HCI + hci_tl_init(init_type); + #endif //(HCI_TL_SUPPORT) +} + +#if (BLE_EMB_PRESENT || BT_EMB_PRESENT) +void hci_send_2_host(void *param) +{ + struct kernel_msg *msg = kernel_param2msg(param); + + if( hci_evt_mask_check(msg) + #if BT_EMB_PRESENT + || hci_evt_filter_check(msg) + #endif //BT_EMB_PRESENT + ) + { + // Free the kernel message space + kernel_msg_free(msg); + return; + } + + #if BLE_HOST_PRESENT + #if(BLE_EMB_PRESENT && HCI_TL_SUPPORT) + // check if communication is performed over embedded host + if(!hci_ext_host) + #endif // (BLE_EMB_PRESENT && HCI_TL_SUPPORT) + { + kernel_task_id_t dest = TASK_BLE_NONE; + uint8_t hl_type = HL_UNDEF; + + // The internal destination first depends on the message type (command, event, data) + switch(msg->id) + { + case HCI_CMD_STAT_EVENT: + case HCI_CMD_CMP_EVENT: + { + if(msg->src_id != HCI_NO_OPERATION_CMD_OPCODE) + { + // Find a command descriptor associated to the command opcode + const struct hci_cmd_desc_tag* cmd_desc = hci_look_for_cmd_desc(msg->src_id); + + // Check if the command is supported + if(cmd_desc != NULL) + { + hl_type = (cmd_desc->dest_field & HCI_CMD_DEST_HL_MASK) >> HCI_CMD_DEST_HL_POS; + } + } + else + { + hl_type = HL_MNG; + } + } + break; + case HCI_EVENT: + { + // Find an event descriptor associated to the event code + const struct hci_evt_desc_tag* evt_desc = hci_look_for_evt_desc(msg->src_id); + + // Check if the event is supported + if(evt_desc != NULL) + { + hl_type = (evt_desc->dest_field & HCI_EVT_DEST_HL_MASK) >> HCI_EVT_DEST_HL_POS; + } + } + break; + case HCI_LE_EVENT: + { + uint8_t subcode = *((uint8_t *)kernel_msg2param(msg)); + + // Find an LE event descriptor associated to the LE event subcode + const struct hci_evt_desc_tag* evt_desc = hci_look_for_le_evt_desc(subcode); + + // Check if the event is supported + if(evt_desc != NULL) + { + hl_type = (evt_desc->dest_field & HCI_EVT_DEST_HL_MASK) >> HCI_EVT_DEST_HL_POS; + } + } + break; + #if (RW_DEBUG || BLE_ISOGEN) + case HCI_DBG_EVT: + { + uint8_t subcode = *((uint8_t *)kernel_msg2param(msg)); + + // Find an VS event descriptor associated to the VS event subcode + const struct hci_evt_desc_tag* evt_desc = hci_look_for_dbg_evt_desc(subcode); + + // Check if the event is supported + if(evt_desc != NULL) + { + hl_type = (evt_desc->dest_field & HCI_EVT_DEST_HL_MASK) >> HCI_EVT_DEST_HL_POS; + } + } break; + #endif // (RW_DEBUG || BLE_ISOGEN) + #if (HCI_BLE_CON_SUPPORT) + case HCI_ACL_DATA: + { + hl_type = HL_DATA; + } + break; + #endif // (HCI_BLE_CON_SUPPORT) + + default: + { + // Nothing to do + } + break; + } + + // Find the higher layers destination task + switch(hl_type) + { + case HL_MNG: + { + // Build the destination task ID + dest = TASK_BLE_GAPM; + } + break; + + #if (HCI_BLE_CON_SUPPORT) + case HL_CTRL: + { + // Check if the link identifier in the dest_id field corresponds to an active BLE link + if(msg->dest_id < BLE_ACTIVITY_MAX) + { + #if (BLE_HOST_PRESENT) + uint8_t conidx = gapc_get_conidx(msg->dest_id); + + if (conidx != GAP_INVALID_CONIDX) + { + // Build the destination task ID + dest = KERNEL_BUILD_ID(TASK_BLE_GAPC, conidx); + } + else + { + // Send it to the first instance + dest = TASK_BLE_GAPC; + } + #else + #endif //() + } + else + { + BLE_ASSERT_INFO(0, msg->id, msg->dest_id); + } + } + break; + + case HL_DATA: + { + // Forward to L2CAP handler + dest = TASK_BLE_L2CC; + } + break; + #endif //(HCI_BLE_CON_SUPPORT) + #if (BLE_ISO_MODE_0) + case HL_ISO0: + { + // Check if the link identifier in the dest_id field corresponds to an active BLE link + if(msg->dest_id < BLE_ACTIVITY_MAX) + { + uint8_t conidx = gapc_get_conidx(msg->dest_id); + + if (conidx != GAP_INVALID_CONIDX) + { + // Build the destination task ID + dest = KERNEL_BUILD_ID(TASK_BLE_AM0, conidx); + } + else + { + // Send the message to the first instance + dest = TASK_BLE_AM0; + } + } + else + { + // Send the message to the first instance + dest = TASK_BLE_AM0; + } + } + break; + #endif // (BLE_ISO_MODE_0) + + default: + { + BLE_ASSERT_INFO(0, hl_type, msg->id); + } + break; + } + + // Check it the destination has been found + if(dest != TASK_BLE_NONE) + { + // Send the command to the internal destination task associated to this command + msg->dest_id = dest; + + switch(msg->id) + { + case HCI_CMD_STAT_EVENT: + { + TRC_REQ_HCI_CMD_STAT_EVT(msg->src_id, msg->param_len, msg->param); + } + break; + + case HCI_CMD_CMP_EVENT: + { + TRC_REQ_HCI_CMD_CMP_EVT(msg->src_id, msg->param_len, msg->param); + } + break; + + case HCI_EVENT: + { + TRC_REQ_HCI_EVT(msg->src_id, msg->param_len, msg->param); + } + break; + + case HCI_LE_EVENT: + { + #if (TRACER_PRESENT && TRC_HCI) + uint8_t subcode = *((uint8_t *)kernel_msg2param(msg)); + #endif + TRC_REQ_HCI_LE_EVT(subcode, msg->param_len, msg->param); + } + break; + + default: + { + // Nothing to do + } + break; + } + + kernel_msg_send(param); + } + else + { + BLE_ASSERT_INFO(0, msg->id, msg->src_id); + + // Free message to avoid memory leak + kernel_msg_free(msg); + } + } + #if(BLE_EMB_PRESENT && HCI_TL_SUPPORT) + else + #endif // (BLE_EMB_PRESENT && HCI_TL_SUPPORT) + #endif //BLE_HOST_PRESENT + #if (HCI_TL_SUPPORT) + { + // Send the HCI message over TL + hci_tl_send(msg); + } + #endif //(HCI_TL_SUPPORT) +} +#endif //(BLE_EMB_PRESENT || BT_EMB_PRESENT) + +#if BLE_HOST_PRESENT +void hci_send_2_controller(void *param) +{ + struct kernel_msg *msg = kernel_param2msg(param); + + #if (HCI_TL_SUPPORT && !BLE_EMB_PRESENT) + // Send the HCI message over TL + hci_tl_send(msg); + #else //(HCI_TL_SUPPORT) + #if BLE_EMB_PRESENT + + #if(BLE_EMB_PRESENT && HCI_TL_SUPPORT) + // check if communication is performed over embedded host + if(!hci_ext_host) + #endif // (BLE_EMB_PRESENT && HCI_TL_SUPPORT) + { + kernel_task_id_t dest = TASK_BLE_NONE; + uint8_t ll_type = LL_UNDEF; + + // The internal destination first depends on the message type (command, event, data) + switch(msg->id) + { + case HCI_COMMAND: + { + TRC_REQ_HCI_CMD(msg->src_id, msg->param_len, msg->param); + + // Find a command descriptor associated to the command opcode + const struct hci_cmd_desc_tag* cmd_desc = hci_look_for_cmd_desc(msg->src_id); + + // Check if the command is supported + if(cmd_desc != NULL) + { + ll_type = (cmd_desc->dest_field & HCI_CMD_DEST_LL_MASK) >> HCI_CMD_DEST_LL_POS; + } + } + break; + #if (HCI_BLE_CON_SUPPORT) + case HCI_ACL_DATA: + { + ll_type = BLE_CTRL; + } + break; + #endif // (HCI_BLE_CON_SUPPORT) + + default: + { + // Nothing to do + } + break; + } + + switch(ll_type) + { + #if BT_EMB_PRESENT + case BT_MNG: + case MNG: + { + dest = TASK_BLE_LM; + } + break; + case BT_BCST: + { + dest = TASK_BLE_LB; + } + break; + #endif //BT_EMB_PRESENT + + case BLE_MNG: + #if !BT_EMB_PRESENT + case MNG: + #endif //BT_EMB_PRESENT + { + dest = TASK_BLE_LLM; + } + break; + + #if (HCI_BLE_CON_SUPPORT) + case CTRL: + case BLE_CTRL: + { + // Check if the link identifier in the dest_id field corresponds to an active BLE link + if(msg->dest_id < BLE_ACTIVITY_MAX) + { + // Build the destination task ID + dest = KERNEL_BUILD_ID(TASK_BLE_LLC, msg->dest_id); + } + else + { + BLE_ASSERT_INFO(0, msg->id, msg->dest_id); + } + } + break; + #endif //(HCI_BLE_CON_SUPPORT) + + #if (BLE_EMB_PRESENT && BLE_ISO_PRESENT) + case BLE_ISO: + { + dest = TASK_BLE_LLI; + } + break; + #endif //(BLE_EMB_PRESENT && BLE_ISO_PRESENT) + + #if (BLE_EMB_PRESENT) + case DBG: + { + dest = TASK_BLE_DBG; + } break; + #endif // (BLE_EMB_PRESENT) + + default: + { + // Nothing to do + } + break; + } + + // Check it the destination has been found + if(dest != TASK_BLE_NONE) + { + // Send the command to the internal destination task associated to this command + msg->dest_id = dest; + kernel_msg_send(param); + } + else + { + BLE_ASSERT_INFO(0, msg->id, msg->src_id); + + // Free message to avoid memory leak + kernel_msg_free(msg); + } + } + #if(BLE_EMB_PRESENT && HCI_TL_SUPPORT) + else + { + // receiving a message from internal host is not expected at all + BLE_ASSERT_ERR(0); + // Free message to avoid memory leak + kernel_msg_free(msg); + } + #endif // (BLE_EMB_PRESENT && HCI_TL_SUPPORT) + #endif //BLE_EMB_PRESENT + #endif //(HCI_TL_SUPPORT) +} + +void hci_basic_cmd_send_2_controller(uint16_t opcode) +{ + void *no_param = kernel_msg_alloc(HCI_COMMAND, 0, opcode, 0); + hci_send_2_controller(no_param); +} + +#endif //BLE_HOST_PRESENT + +#if (BLE_EMB_PRESENT && HCI_BLE_CON_SUPPORT) +void hci_ble_conhdl_register(uint8_t link_id) +{ + BLE_ASSERT_INFO(link_id < BLE_ACTIVITY_MAX, link_id, BLE_ACTIVITY_MAX); + BLE_ASSERT_ERR(!hci_env.ble_con_state[link_id]); + + // Link ID associated with BD address AND connection handle + hci_env.ble_con_state[link_id] = true; +} + +void hci_ble_conhdl_unregister(uint8_t link_id) +{ + BLE_ASSERT_INFO(link_id < BLE_ACTIVITY_MAX, link_id, BLE_ACTIVITY_MAX); + BLE_ASSERT_ERR(hci_env.ble_con_state[link_id]); + + // Link ID associated with BD address + hci_env.ble_con_state[link_id] = false; +} +#endif //(BLE_EMB_PRESENT && !BLE_HOST_PRESENT && HCI_BLE_CON_SUPPORT) + +#if (BT_EMB_PRESENT) +void hci_bt_acl_bdaddr_register(uint8_t link_id, struct bd_addr* bd_addr) +{ + BLE_ASSERT_INFO(link_id < MAX_NB_ACTIVE_ACL, link_id, 0); + BLE_ASSERT_INFO(hci_env.bt_acl_con_tab[link_id].state == HCI_BT_ACL_STATUS_NOT_ACTIVE, hci_env.bt_acl_con_tab[link_id].state, 0); + + // Store BD address + memcpy(&hci_env.bt_acl_con_tab[link_id].bd_addr.addr[0], &bd_addr->addr[0], sizeof(struct bd_addr)); + + // Link ID associated with BD address + hci_env.bt_acl_con_tab[link_id].state = HCI_BT_ACL_STATUS_BD_ADDR; +} + +void hci_bt_acl_conhdl_register(uint8_t link_id) +{ + BLE_ASSERT_INFO(link_id < MAX_NB_ACTIVE_ACL, link_id, 0); + BLE_ASSERT_INFO(hci_env.bt_acl_con_tab[link_id].state == HCI_BT_ACL_STATUS_BD_ADDR, hci_env.bt_acl_con_tab[link_id].state, 0); + + // Link ID associated with BD address AND connection handle + hci_env.bt_acl_con_tab[link_id].state = HCI_BT_ACL_STATUS_BD_ADDR_CONHDL; +} + +void hci_bt_acl_bdaddr_unregister(uint8_t link_id) +{ + BLE_ASSERT_INFO(link_id < MAX_NB_ACTIVE_ACL, link_id, 0); + + // Link ID associated with BD address + hci_env.bt_acl_con_tab[link_id].state = HCI_BT_ACL_STATUS_NOT_ACTIVE; +} +#endif //(BT_EMB_PRESENT) + +uint8_t hci_evt_mask_set(struct evt_mask const *evt_msk, uint8_t page) +{ + switch(page) + { + case HCI_PAGE_0: + case HCI_PAGE_1: + { + BLE_ASSERT_INFO(page == HCI_PAGE_DFT,page,page); + }break; + case HCI_PAGE_2: + { + // Store event mask + memcpy(&hci_env.evt_msk_page_2.mask[0], &evt_msk->mask[0], EVT_MASK_LEN); + }break; + case HCI_PAGE_DFT: + { + // Store event mask + memcpy(&hci_env.evt_msk.mask[0], &evt_msk->mask[0], EVT_MASK_LEN); + + // ensure that reserved bit are set + for (uint8_t i = 0; i < EVT_MASK_LEN; i++) + { + hci_env.evt_msk.mask[i] |= hci_rsvd_evt_msk.mask[i]; + } + }break; + #if (BLE_EMB_PRESENT) + case HCI_PAGE_LE: + { + // Store event mask + memcpy(&hci_env.le_evt_msk.mask[0], &evt_msk->mask[0], EVT_MASK_LEN); + }break; + #endif // (BLE_EMB_PRESENT) + default: + { + BLE_ASSERT_ERR(0); + }break; + } + return COMMON_ERROR_NO_ERROR; +} + +#if (BT_EMB_PRESENT) +uint8_t hci_evt_filter_add(struct hci_set_evt_filter_cmd const *param) +{ + uint8_t status = COMMON_ERROR_INVALID_HCI_PARAM; + + // Perform the requested action according to the filter type + switch (param->filter_type) + { + case CLEAR_ALL_FILTER_TYPE: + { + // Reset all Filters + status = hci_evt_filter_reset(); + } + break; + + case INQUIRY_FILTER_TYPE: + { + // Add inquiry event filter + status = hci_evt_filter_inq_add(¶m->filter.inq_res); + } + break; + + case CONNECTION_FILTER_TYPE: + { + // Add connection event filter + status = hci_evt_filter_con_add(¶m->filter.con_set); + } + break; + + default: + { + // Nothing to do + } + break; + } + + return (status); +} + +#if (MAX_NB_SYNC > 0) +uint16_t hci_voice_settings_get(void) +{ + return(hci_env.voice_settings); +} + +uint8_t hci_voice_settings_set(uint16_t voice_settings) +{ + uint8_t status = COMMON_ERROR_UNSUPPORTED; + + // Check if the requested voice settings are supported + switch (voice_settings & AIR_COD_MSK) + { + case AIR_COD_CVSD: + case AIR_COD_MULAW: + case AIR_COD_ALAW: + case AIR_COD_TRANS: + { + hci_env.voice_settings = voice_settings; + status = COMMON_ERROR_NO_ERROR; + } + break; + default: + break; + } + + return(status); +} +#endif // (MAX_NB_SYNC > 0) +#endif //(BT_EMB_PRESENT) + +#endif //(HCI_PRESENT) +#else +/* + * Copyright (C) 2015-2017 Alibaba Group Holding Limited + */ + + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "architect.h" +#include "lowlevel.h" +#include "rtos_pub.h" +#include "mem_pub.h" + +#include "uart_pub.h" +#include "string.h" + +#include "kernel_msg.h" // kernel message declaration +#include "kernel_task.h" // kernel task definition +#include "kernel_event.h" // kernel event definition +#include "kernel_mem.h" // kernel memory definition +#include "ble_util_buf.h" +#include "em_map.h" + +#include "common_utils.h" +#include "hci.h" +#include "start_type_pub.h" + +/// Offset of the Kernel message parameters compared to the event packet position +#define HCI_CMD_PARAM_OFFSET 3 +#define HCI_EVT_CC_PARAM_OFFSET 5 +#define HCI_EVT_CS_PARAM_OFFSET 5 +#define HCI_EVT_PARAM_OFFSET 2 +#define HCI_EVT_LE_PARAM_OFFSET 2 +#define HCI_EVT_DBG_PARAM_OFFSET 2 + +#define HCI_ACL_HANDLE_MASK 0x3fff +#ifndef HCI_DBG +#define HCI_DBG(...) +#endif + +#define HCI2H_MALLOC(size) os_malloc(size) +#define HCI2H_FREE(ptr) os_free(ptr) + +static struct common_list recv_wait_list; + +/// Event mask +static struct evt_mask evt_msk; + +/// Event mask page 2 +static struct evt_mask evt_msk_page_2; + +#if (BLE_EMB_PRESENT) +/// LE Event mask +static struct evt_mask le_evt_msk; +#endif // (BLE_EMB_PRESENT) + + +struct hci_context { + beken_mutex_t lock; + int initialized; +}; + +static struct hci_context g_hci_send_context; +static hci_func_evt_cb g_hci_cmd_cb = NULL; +static hci_func_evt_cb g_hci_acl_cb = NULL; + +/* + * GLOBAL FUNCTION DECLARATIONS + **************************************************************************************** + */ +static void hci_lock(struct hci_context *context) +{ + if (context->initialized) + rtos_lock_mutex(&(context->lock)); +} + +static void hci_unlock(struct hci_context *context) +{ + if (context->initialized) + rtos_unlock_mutex(&(context->lock)); +} + +void ble_recv_handler(void *arg) +{ + bk_ble_hci_buf_t *recv_buf_info; + + while (!common_list_is_empty(&recv_wait_list)) { + ///get receive buffer + GLOBAL_INT_DIS(); + recv_buf_info = (bk_ble_hci_buf_t*)common_list_pop_front(&recv_wait_list); + GLOBAL_INT_RES(); + if (recv_buf_info->type == HCI_EVT_MSG_TYPE) { + if (g_hci_cmd_cb) { + g_hci_cmd_cb((uint8_t *)(recv_buf_info->buf), recv_buf_info->len); + } + } else if (recv_buf_info->type == HCI_ACL_MSG_TYPE) { + if (g_hci_acl_cb) { + g_hci_acl_cb((uint8_t *)(recv_buf_info->buf), recv_buf_info->len); + } + } else { + os_printf("%s:unknow msg type:%d\r\n", __FUNCTION__, recv_buf_info->type); + } + + HCI2H_FREE(recv_buf_info); + recv_buf_info = NULL; + } +} + +/// TODO:Add flowcontrl feature +uint8_t hci_fc_acl_en(bool flow_enable) +{ + return COMMON_ERROR_UNSUPPORTED; +} + +uint8_t hci_fc_acl_buf_size_set(uint16_t acl_pkt_len, uint16_t nb_acl_pkts) +{ + return COMMON_ERROR_UNSUPPORTED; +} + +void hci_ble_conhdl_unregister(uint8_t link_id) +{ + return; +} + +void hci_ble_conhdl_register(uint8_t link_id) +{ + return; +} + +void hci_fc_host_nb_acl_pkts_complete(uint16_t acl_pkt_nb) +{ + return; +} + +static uint8_t* hci_build_cc_evt(struct kernel_msg * msg) +{ + uint8_t* param = kernel_msg2param(msg); + uint8_t* buf = param - HCI_EVT_CC_PARAM_OFFSET; + uint8_t* pk = buf; + uint16_t opcode = msg->src_id; + uint16_t ret_par_len = msg->param_len; + + //pack event code + *pk++ = HCI_CMD_CMP_EVT_CODE; + + //pack event parameter length + *pk++ = HCI_CCEVT_HDR_PARLEN + ret_par_len; + + //pack the number of h2c packets + *pk++ = 1U; + + //pack opcode + common_write16p(pk, common_htobs(opcode)); + + return buf; +} + +static uint8_t* hci_build_cs_evt(struct kernel_msg * msg) +{ + uint8_t* param = kernel_msg2param(msg); + uint8_t* buf = param - HCI_EVT_CS_PARAM_OFFSET; + uint8_t* pk = buf; + uint16_t opcode = msg->src_id; + + //pack event code + *pk++ = HCI_CMD_STATUS_EVT_CODE; + + //pack event parameter length + *pk++ = HCI_CSEVT_PARLEN; + + //pack the status + *pk++ = *param; + + //pack the number of h2c packets + *pk++ = 1U; + + //pack opcode + common_write16p(pk, common_htobs(opcode)); + + return buf; +} + +static uint8_t* hci_build_evt(struct kernel_msg * msg) +{ + uint8_t* param = kernel_msg2param(msg); + uint8_t* buf = param - HCI_EVT_LE_PARAM_OFFSET; + uint8_t* pk = buf; + uint8_t evt_code = (uint8_t) msg->src_id; + uint16_t par_len = msg->param_len; + + //pack event code + *pk++ = evt_code; + + //pack event parameter length + *pk++ = par_len; + + return buf; +} + +#if ( HCI_TL_SUPPORT == 0 ) +/// Status returned by generic packer-unpacker +enum HCI_PACK_STATUS +{ + HCI_PACK_OK, + HCI_PACK_IN_BUF_OVFLW, + HCI_PACK_OUT_BUF_OVFLW, + HCI_PACK_WRONG_FORMAT, + HCI_PACK_ERROR, +}; + +static uint8_t hci_pack_bytes(uint8_t** pp_in, uint8_t** pp_out, uint8_t* p_in_end, uint8_t* p_out_end, uint8_t len) +{ + uint8_t status = HCI_PACK_OK; + + // Check if enough space in input buffer to read + if((*pp_in + len) > p_in_end) + { + status = HCI_PACK_IN_BUF_OVFLW; + } + else + { + if(p_out_end != NULL) + { + // Check if enough space in out buffer to write + if((*pp_out + len) > p_out_end) + { + status = HCI_PACK_OUT_BUF_OVFLW; + } + + // Copy BD Address + memcpy(*pp_out, *pp_in, len); + } + *pp_in = *pp_in + len; + *pp_out = *pp_out + len; + } + + return (status); +} + +/// Special packing/unpacking function for HCI LE Advertising Report Event +static uint8_t hci_le_adv_report_evt_pkupk(uint8_t *out, uint8_t *in, uint16_t* out_len, uint16_t in_len) +{ + #if BLE_EMB_PRESENT + + /* + * PACKING FUNCTION + */ + struct hci_le_adv_report_evt temp_out; + struct hci_le_adv_report_evt* s; + uint8_t* p_in = in; + uint8_t* p_out; + uint8_t* p_in_end = in + in_len; + uint8_t* p_out_start; + uint8_t status = HCI_PACK_OK; + + // Check if there is input data to parse + if(in != NULL) + { + uint8_t* p_out_end; + + // Check if there is output buffer to write to, else use temp_out buffer + if (out != NULL) + { + s = (struct hci_le_adv_report_evt*)(out); + p_out_start = out; + p_out_end = out + *out_len; + } + else + { + s = (struct hci_le_adv_report_evt*)(&temp_out); + p_out_start = (uint8_t*)&temp_out; + p_out_end = p_out_start + sizeof(temp_out); + } + + p_out = p_out_start; + + do + { + // Sub-code + p_in = &s->subcode; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Number of reports + p_in = &s->nb_reports; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + for (int i=0; i< s->nb_reports; i++) + { + uint8_t data_len; + + // Event type + p_in = &s->adv_rep[i].evt_type; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Address type + p_in = &s->adv_rep[i].adv_addr_type; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // BD Address + p_in = &s->adv_rep[i].adv_addr.addr[0]; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, BD_ADDR_LEN); + if(status != HCI_PACK_OK) + break; + + // Data Length + p_in = &s->adv_rep[i].data_len; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + data_len = s->adv_rep[i].data_len; + //bk_printf("[jerry][advlen %d]\r\n",data_len); + // ADV data + p_in = &s->adv_rep[i].data[0]; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, data_len); + if(status != HCI_PACK_OK) + break; + + // RSSI + p_in = (uint8_t*) &s->adv_rep[i].rssi; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + } + + } while(0); + + *out_len = (uint16_t)(p_out - p_out_start); + } + else + { + *out_len = 0; + } + + return (status); + + #elif BLE_HOST_PRESENT + + /* + * UNPACKING FUNCTION + */ + + // TODO unpack message as per compiler + *out_len = in_len; + if((out != NULL) && (in != NULL)) + { + // copy adv report + memcpy(out, in, in_len); + } + + return (HCI_PACK_OK); + + #endif //BLE_EMB_PRESENT +} + +static uint8_t hci_le_dir_adv_report_evt_pkupk(uint8_t *out, uint8_t *in, uint16_t* out_len, uint16_t in_len) +{ + #if BLE_EMB_PRESENT + + /* + * PACKING FUNCTION + */ + struct hci_le_dir_adv_rep_evt temp_out; + struct hci_le_dir_adv_rep_evt* s; + uint8_t* p_in = in; + uint8_t* p_out; + uint8_t* p_in_end = in + in_len; + uint8_t* p_out_start; + uint8_t status = HCI_PACK_OK; + + // Check if there is input data to parse + if(in != NULL) + { + uint8_t* p_out_end; + + // Check if there is output buffer to write to, else use temp_out buffer + if (out != NULL) + { + s = (struct hci_le_dir_adv_rep_evt*)(out); + p_out_start = out; + p_out_end = out + *out_len; + } + else + { + s = (struct hci_le_dir_adv_rep_evt*)(&temp_out); + p_out_start = (uint8_t*)&temp_out; + p_out_end = p_out_start + sizeof(temp_out); + } + + p_out = p_out_start; + + do + { + // Sub-code + p_in = &s->subcode; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Number of reports + p_in = &s->nb_reports; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + for (int i=0; i< s->nb_reports; i++) + { + // Event type + p_in = &s->adv_rep[i].evt_type; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + + // Address type + p_in = &s->adv_rep[i].addr_type; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // BD Address + p_in = &s->adv_rep[i].addr.addr[0]; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, BD_ADDR_LEN); + if(status != HCI_PACK_OK) + break; + + // Direct Address type + p_in = &s->adv_rep[i].dir_addr_type; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Direct BD Address + p_in = &s->adv_rep[i].dir_addr.addr[0]; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, BD_ADDR_LEN); + if(status != HCI_PACK_OK) + break; + + // RSSI + p_in = (uint8_t*) &s->adv_rep[i].rssi; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + } + + } while(0); + + *out_len = (uint16_t)(p_out - p_out_start); + } + else + { + *out_len = 0; + } + + return (status); + + #elif BLE_HOST_PRESENT + + /* + * UNPACKING FUNCTION + */ + + // TODO unpack message as per compiler + *out_len = in_len; + if((out != NULL) && (in != NULL)) + { + // copy adv report + memcpy(out, in, in_len); + } + + return (HCI_PACK_OK); + + #endif //BLE_EMB_PRESENT +} + +static uint8_t hci_le_ext_adv_report_evt_pkupk(uint8_t *out, uint8_t *in, uint16_t* out_len, uint16_t in_len) +{ + #if BLE_EMB_PRESENT + + /* + * PACKING FUNCTION + */ + struct hci_le_ext_adv_report_evt temp_out; + struct hci_le_ext_adv_report_evt* s; + uint8_t* p_in = in; + uint8_t* p_out; + uint8_t* p_in_end = in + in_len; + uint8_t* p_out_start; + uint8_t status = HCI_PACK_OK; + + // Check if there is input data to parse + if(in != NULL) + { + uint8_t* p_out_end; + + // Check if there is output buffer to write to, else use temp_out buffer + if (out != NULL) + { + s = (struct hci_le_ext_adv_report_evt*)(out); + p_out_start = out; + p_out_end = out + *out_len; + } + else + { + s = (struct hci_le_ext_adv_report_evt*)(&temp_out); + p_out_start = (uint8_t*)&temp_out; + p_out_end = p_out_start + sizeof(temp_out); + } + + p_out = p_out_start; + + do + { + // Sub-code + p_in = &s->subcode; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Number of reports + p_in = &s->nb_reports; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + for (int i=0; i< s->nb_reports; i++) + { + uint8_t data_len; + + // Event type + p_in = (uint8_t*) &s->adv_rep[i].evt_type; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 2); + if(status != HCI_PACK_OK) + break; + + // Adv Address type + p_in = &s->adv_rep[i].adv_addr_type; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Adv Address + p_in = &s->adv_rep[i].adv_addr.addr[0]; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, BD_ADDR_LEN); + if(status != HCI_PACK_OK) + break; + + // Primary PHY + p_in = &s->adv_rep[i].phy; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Secondary PHY + p_in = &s->adv_rep[i].phy2; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Advertising SID + p_in = &s->adv_rep[i].adv_sid; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Tx Power + p_in = &s->adv_rep[i].tx_power; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // RSSI + p_in = (uint8_t*) &s->adv_rep[i].rssi; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Periodic Advertising Interval + p_in = (uint8_t*) &s->adv_rep[i].interval; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 2); + if(status != HCI_PACK_OK) + break; + + // Direct address type + p_in = (uint8_t*) &s->adv_rep[i].dir_addr_type; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Direct BD Address + p_in = &s->adv_rep[i].dir_addr.addr[0]; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, BD_ADDR_LEN); + if(status != HCI_PACK_OK) + break; + + // Data Length + p_in = &s->adv_rep[i].data_len; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + data_len = s->adv_rep[i].data_len; + + // ADV data + p_in = &s->adv_rep[i].data[0]; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, data_len); + if(status != HCI_PACK_OK) + break; + } + + } while(0); + + *out_len = (uint16_t)(p_out - p_out_start); + } + else + { + *out_len = 0; + } + + return (status); + + #elif BLE_HOST_PRESENT + + /* + * UNPACKING FUNCTION + */ + //TODO unpack message as per compiler + *out_len = in_len; + if((out != NULL) && (in != NULL)) + { + // copy adv report + memcpy(out, in, in_len); + } + + return (HCI_PACK_OK); + + #endif //BLE_EMB_PRESENT +} + +static uint8_t hci_le_conless_iq_report_evt_pkupk(uint8_t *out, uint8_t *in, uint16_t* out_len, uint16_t in_len) +{ + #if BLE_EMB_PRESENT + + /* + * PACKING FUNCTION + */ + struct hci_le_conless_iq_report_evt temp_out; + struct hci_le_conless_iq_report_evt* s; + uint8_t* p_in = in; + uint8_t* p_out; + uint8_t* p_in_end = in + in_len; + uint8_t* p_out_start; + uint8_t status = HCI_PACK_OK; + + // Check if there is input data to parse + if(in != NULL) + { + uint8_t* p_out_end; + + // Check if there is output buffer to write to, else use temp_out buffer + if (out != NULL) + { + s = (struct hci_le_conless_iq_report_evt*)(out); + p_out_start = out; + p_out_end = out + *out_len; + } + else + { + s = (struct hci_le_conless_iq_report_evt*)(&temp_out); + p_out_start = (uint8_t*)&temp_out; + p_out_end = p_out_start + sizeof(temp_out); + } + + p_out = p_out_start; + + do + { + uint8_t sample_cnt = 0; + + // Sub-code + p_in = &s->subcode; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Sync handle + p_in = (uint8_t*) &s->sync_hdl; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 2); + if(status != HCI_PACK_OK) + break; + + // Channel index + p_in = &s->channel_idx; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // RSSI + p_in = (uint8_t*) &s->rssi; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 2); + if(status != HCI_PACK_OK) + break; + + // RSSI antenna ID + p_in = &s->rssi_antenna_id; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // CTE type + p_in = &s->cte_type; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Slot durations + p_in = &s->slot_dur; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Packet status + p_in = &s->pkt_status; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // paEventCounter + p_in = (uint8_t*) &s->pa_evt_cnt; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 2); + if(status != HCI_PACK_OK) + break; + + // Sample count + sample_cnt = s->sample_cnt; + p_in = &s->sample_cnt; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + for (int i=0; i < sample_cnt; i++) + { + // I sample + p_in = (uint8_t *) &s->iq_sample[i].i; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Q sample + p_in = (uint8_t *) &s->iq_sample[i].q; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + } + + } while(0); + + *out_len = (uint16_t)(p_out - p_out_start); + } + else + { + *out_len = 0; + } + + return (status); + + #elif BLE_HOST_PRESENT + + /* + * UNPACKING FUNCTION + */ + //TODO unpack message as per compiler + *out_len = in_len; + if((out != NULL) && (in != NULL)) + { + // copy adv report + memcpy(out, in, in_len); + } + + return (HCI_PACK_OK); + + #endif //BLE_EMB_PRESENT +} + +static uint8_t hci_le_con_iq_report_evt_pkupk(uint8_t *out, uint8_t *in, uint16_t* out_len, uint16_t in_len) +{ + #if BLE_EMB_PRESENT + + /* + * PACKING FUNCTION + */ + struct hci_le_con_iq_report_evt temp_out; + struct hci_le_con_iq_report_evt* s; + uint8_t* p_in = in; + uint8_t* p_out; + uint8_t* p_in_end = in + in_len; + uint8_t* p_out_start; + uint8_t status = HCI_PACK_OK; + + // Check if there is input data to parse + if(in != NULL) + { + uint8_t* p_out_end; + + // Check if there is output buffer to write to, else use temp_out buffer + if (out != NULL) + { + s = (struct hci_le_con_iq_report_evt*)(out); + p_out_start = out; + p_out_end = out + *out_len; + } + else + { + s = (struct hci_le_con_iq_report_evt*)(&temp_out); + p_out_start = (uint8_t*)&temp_out; + p_out_end = p_out_start + sizeof(temp_out); + } + + p_out = p_out_start; + + do + { + uint8_t sample_cnt = 0; + + // Sub-code + p_in = &s->subcode; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Connection handle + p_in = (uint8_t*) &s->conhdl; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 2); + if(status != HCI_PACK_OK) + break; + + // Rx PHY + p_in = &s->rx_phy; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Data channel index + p_in = &s->data_channel_idx; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // RSSI + p_in = (uint8_t*) &s->rssi; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 2); + if(status != HCI_PACK_OK) + break; + + // RSSI antenna ID + p_in = &s->rssi_antenna_id; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // CTE type + p_in = &s->cte_type; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Slot durations + p_in = &s->slot_dur; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Packet status + p_in = &s->pkt_status; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // connEventCounter + p_in = (uint8_t*) &s->con_evt_cnt; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 2); + if(status != HCI_PACK_OK) + break; + + // Sample count + sample_cnt = s->sample_cnt; + p_in = &s->sample_cnt; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + for (int i=0; i < sample_cnt; i++) + { + // I sample + p_in = (uint8_t *) &s->iq_sample[i].i; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Q sample + p_in = (uint8_t *) &s->iq_sample[i].q; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + } + + } while(0); + + *out_len = (uint16_t)(p_out - p_out_start); + } + else + { + *out_len = 0; + } + + return (status); + + #elif BLE_HOST_PRESENT + + /* + * UNPACKING FUNCTION + */ + //TODO unpack message as per compiler + *out_len = in_len; + if((out != NULL) && (in != NULL)) + { + // copy adv report + memcpy(out, in, in_len); + } + + return (HCI_PACK_OK); + + #endif //BLE_EMB_PRESENT +} +#endif //( HCI_TL_SUPPORT == 0 ) + +static uint8_t* hci_build_le_evt(struct kernel_msg * msg) +{ + uint8_t* param = kernel_msg2param(msg); + uint8_t* buf = param - HCI_EVT_LE_PARAM_OFFSET; + uint8_t* pk = buf; + uint16_t par_len = msg->param_len; + uint8_t subcode = *param; + uint8_t status = COMMON_UTIL_PACK_OK; + +#if ( HCI_TL_SUPPORT == 0 ) + switch(subcode) { + case HCI_LE_ADV_REPORT_EVT_SUBCODE: + status = hci_le_adv_report_evt_pkupk(param, param, &par_len, par_len); + break; + case HCI_LE_DIR_ADV_REP_EVT_SUBCODE: + status = hci_le_dir_adv_report_evt_pkupk(param, param, &par_len, par_len); + break; + case HCI_LE_EXT_ADV_REPORT_EVT_SUBCODE: + status = hci_le_ext_adv_report_evt_pkupk(param, param, &par_len, par_len); + break; + case HCI_LE_CONLESS_IQ_REPORT_EVT_SUBCODE: + status = hci_le_conless_iq_report_evt_pkupk(param, param, &par_len, par_len); + break; + case HCI_LE_CON_IQ_REPORT_EVT_SUBCODE: + status = hci_le_con_iq_report_evt_pkupk(param, param, &par_len, par_len); + break; + default: + { + bk_printf("[warning][%s][%d]subcode:0x%x\r\n",__func__,__LINE__,subcode); + } + break; + } +#endif //( HCI_TL_SUPPORT == 0 ) + if(status == COMMON_UTIL_PACK_OK) { + //pack event code + *pk++ = HCI_LE_META_EVT_CODE; + + //pack event parameter length + *pk++ = par_len; + } else { + BLE_ASSERT_INFO(0, subcode, 0); + buf = NULL; + } + + return buf; +} + +static uint8_t* hci_build_acl_data(struct kernel_msg * msg) +{ + // Point to message parameters structure + struct hci_acl_data *param = (struct hci_acl_data *) kernel_msg2param(msg); + uint16_t handle_flags = param->conhdl_pb_bc_flag; + uint8_t* buf = ((uint8_t*)param->buf_ptr) - HCI_ACL_HDR_LEN; + uint8_t* pk; + + #if (!BLE_HOST_PRESENT || BLE_EMB_PRESENT) + buf += EM_BASE_ADDR; + #endif // (!BLE_HOST_PRESENT || BLE_EMB_PRESENT) + + pk = buf; + + // Pack connection handle and data flags + common_write16p(pk, common_htobs(handle_flags)); + pk +=2; + + // Pack the data length + common_write16p(pk, common_htobs(param->length)); + pk +=2; + + return (buf); +} + +uint8_t hci_evt_mask_set(struct evt_mask const *param, uint8_t page) +{ + switch (page) { + case HCI_PAGE_0: + case HCI_PAGE_1: + BLE_ASSERT_INFO(page == HCI_PAGE_DFT,page,page); + break; + case HCI_PAGE_2: + // Store event mask + memcpy(&evt_msk_page_2.mask[0], ¶m->mask[0], EVT_MASK_LEN); + break; + case HCI_PAGE_DFT: + // Store event mask + memcpy(&evt_msk.mask[0], ¶m->mask[0], EVT_MASK_LEN); + break; +#if (BLE_EMB_PRESENT) + case HCI_PAGE_LE: + // Store event mask + memcpy(&le_evt_msk.mask[0], ¶m->mask[0], EVT_MASK_LEN); + break; +#endif // (BLE_EMB_PRESENT) + default: + BLE_ASSERT_ERR(0); + break; + } + return COMMON_ERROR_NO_ERROR; +} + +static bool hci_evt_mask_check(struct kernel_msg *msg) +{ + bool masked = false; + uint8_t evt_code; + + switch (msg->id) + { + case HCI_LE_EVENT: + // LE meta event + evt_code = HCI_LE_META_EVT_CODE; + break; + case HCI_EVENT: + // Get event code + evt_code = msg->src_id; + + if (evt_code == HCI_NB_CMP_PKTS_EVT_CODE){ + //TRACE_PRINT("err evt_code 0x13\r\n"); + return false; + } + break; + + default: + // Cannot be masked + return false; + } + + // Check if this event is maskable + if (evt_code < HCI_MAX_EVT_MSK_PAGE_1_CODE) + { + uint8_t index = evt_code - 1; + + //Checking if the event is masked or not + masked = ((evt_msk.mask[index>>3] & (1<<(index & 0x07))) == 0x00); + +#if (BLE_EMB_PRESENT) + if (!masked && (evt_code == HCI_LE_META_EVT_CODE)) { + // Get Sub-code of the mevent + uint8_t *subcode = (uint8_t*)kernel_msg2param(msg); + //Translate the subcode in index to parse the mask + uint8_t index = *subcode - 1; + //Checking if the event is masked or not + masked =((le_evt_msk.mask[index>>3] & (1<<(index & 0x07))) == 0x00); + } +#endif // (BLE_EMB_PRESENT) + } else if(evt_code < HCI_MAX_EVT_MSK_PAGE_2_CODE) + { + // In this area the evt code is in the range [EVT_MASK_CODE_MAX>3] & (1<<(index & 0x07))) == 0x00); + } + return masked; +} + +void hci_send_2_host(void *param) +{ + if (!param) { + os_printf("%s:param is null\r\n", __FUNCTION__); + return; + } + struct kernel_msg *msg = kernel_param2msg(param); + uint8_t *buf = NULL; + uint16_t len = 0; + uint8_t type = 0; + + if (hci_evt_mask_check(msg)) { + os_printf("do not support this command:%04x\r\n", msg->id); + // Free the kernel message space + kernel_msg_free(msg); + return; + } + + switch (msg->id) { + case HCI_CMD_CMP_EVENT: + buf = hci_build_cc_evt(msg); + len = HCI_EVT_HDR_LEN + *(buf + HCI_EVT_CODE_LEN); + type = HCI_EVT_MSG_TYPE; + break; + case HCI_CMD_STAT_EVENT: + buf = hci_build_cs_evt(msg); + len = HCI_EVT_HDR_LEN + *(buf + HCI_EVT_CODE_LEN); + type = HCI_EVT_MSG_TYPE; + break; + case HCI_EVENT: + buf = hci_build_evt(msg); + len = HCI_EVT_HDR_LEN + *(buf + HCI_EVT_CODE_LEN); + type = HCI_EVT_MSG_TYPE; + break; + case HCI_LE_EVENT: + buf = hci_build_le_evt(msg); + len = HCI_EVT_HDR_LEN + *(buf + HCI_EVT_CODE_LEN); + type = HCI_EVT_MSG_TYPE; + break; + case HCI_ACL_DATA: + buf = hci_build_acl_data(msg); + len = HCI_ACL_HDR_LEN + common_read16p(buf + HCI_ACL_HDR_HDL_FLAGS_LEN); + type = HCI_ACL_MSG_TYPE; + break; + default: + break; + } + + int i = 0; + if (type == HCI_EVT_MSG_TYPE && buf) { + if (g_hci_cmd_cb) { + g_hci_cmd_cb((uint8_t *)(buf), len); + } + } else if (type == HCI_ACL_MSG_TYPE ) { + if (g_hci_acl_cb) { + g_hci_acl_cb((uint8_t *)(buf), len); + } + } else { + os_printf("%s:unknow msg type:%d\r\n", __FUNCTION__, type); + } + + if (type == HCI_ACL_MSG_TYPE) { + //os_printf("acl free mem :%p \r\n",((struct hci_acl_data *)param)->buf_ptr); + ble_util_buf_rx_free(((struct hci_acl_data *)param)->buf_ptr); + } + + kernel_msg_free(msg); +} + +const struct hci_cmd_desc_tag hci_cmd_desc_tab_lk_ctrl[] = { + CMD(DISCONNECT, CTRL, HL_CTRL), + CMD(RD_REM_VER_INFO, CTRL, HL_CTRL), +}; + +/// HCI command descriptors (OGF controller and baseband) +const struct hci_cmd_desc_tag hci_cmd_desc_tab_ctrl_bb[] = { + CMD(SET_EVT_MASK, MNG, HL_MNG ), + CMD(RESET, MNG, HL_MNG ), + CMD(RD_TX_PWR_LVL, CTRL, HL_CTRL), + CMD(SET_CTRL_TO_HOST_FLOW_CTRL, MNG, HL_MNG ), + CMD(HOST_BUF_SIZE, MNG, HL_MNG ), + CMD(HOST_NB_CMP_PKTS, MNG, HL_MNG ), + CMD(RD_AUTH_PAYL_TO, CTRL, HL_CTRL), + CMD(WR_AUTH_PAYL_TO, CTRL, HL_CTRL), + CMD(SET_EVT_MASK_PAGE_2, MNG, HL_MNG ), +}; + +/// HCI command descriptors (OGF informational parameters) +const struct hci_cmd_desc_tag hci_cmd_desc_tab_info_par[] = { + CMD(RD_LOCAL_VER_INFO, MNG, HL_MNG), + CMD(RD_LOCAL_SUPP_CMDS, MNG, HL_MNG), + CMD(RD_LOCAL_SUPP_FEATS, MNG, HL_MNG), + CMD(RD_BD_ADDR, MNG, HL_MNG), +}; + +/// HCI command descriptors (OGF status parameters) +const struct hci_cmd_desc_tag hci_cmd_desc_tab_stat_par[] = { + CMD(RD_RSSI, CTRL, HL_CTRL), +}; + +/// HCI command descriptors (OGF LE controller) +const struct hci_cmd_desc_tag hci_cmd_desc_tab_le[] = { + CMD(LE_SET_EXT_ADV_EN, BLE_MNG, HL_MNG ), + CMD(LE_SET_EXT_ADV_PARAM, BLE_MNG, HL_MNG ), + CMD(LE_SET_EXT_ADV_DATA, BLE_MNG, HL_MNG ), + CMD(LE_SET_EVT_MASK, BLE_MNG, HL_MNG ), + CMD(LE_RD_BUFF_SIZE, BLE_MNG, HL_MNG ), + CMD(LE_RD_LOCAL_SUPP_FEATS, BLE_MNG, HL_MNG ), + CMD(LE_SET_RAND_ADDR, BLE_MNG, HL_MNG ), + CMD(LE_RD_ADV_CHNL_TX_PW, BLE_MNG, HL_MNG ), + CMD(LE_SET_ADV_PARAM, BLE_MNG, HL_MNG ), + CMD(LE_SET_ADV_DATA, BLE_MNG, HL_MNG ), + CMD(LE_SET_SCAN_RSP_DATA, BLE_MNG, HL_MNG ), + CMD(LE_SET_ADV_EN, BLE_MNG, HL_MNG ), + CMD(LE_SET_SCAN_PARAM, BLE_MNG, HL_MNG ), + CMD(LE_SET_SCAN_EN, BLE_MNG, HL_MNG ), + CMD(LE_CREATE_CON, BLE_MNG, HL_MNG ), + CMD(LE_CREATE_CON_CANCEL, BLE_MNG, HL_MNG ), + CMD(LE_RD_WLST_SIZE, BLE_MNG, HL_MNG ), + CMD(LE_CLEAR_WLST, BLE_MNG, HL_MNG ), + CMD(LE_ADD_DEV_TO_WLST, BLE_MNG, HL_MNG ), + CMD(LE_RMV_DEV_FROM_WLST, BLE_MNG, HL_MNG ), + CMD(LE_CON_UPDATE, BLE_CTRL, HL_CTRL), + CMD(LE_SET_HOST_CH_CLASS, BLE_MNG, HL_MNG ), + CMD(LE_RD_CHNL_MAP, BLE_CTRL, HL_CTRL), + CMD(LE_RD_REM_FEATS, BLE_CTRL, HL_CTRL), + CMD(LE_ENC, BLE_MNG, HL_MNG ), + CMD(LE_RAND, BLE_MNG, HL_MNG ), + CMD(LE_START_ENC, BLE_CTRL, HL_CTRL), + CMD(LE_LTK_REQ_REPLY, BLE_CTRL, HL_CTRL), + CMD(LE_LTK_REQ_NEG_REPLY, BLE_CTRL, HL_CTRL), + CMD(LE_RD_SUPP_STATES, BLE_MNG, HL_MNG ), + CMD(LE_RX_TEST_V1, BLE_MNG, HL_MNG ), + CMD(LE_TX_TEST_V1, BLE_MNG, HL_MNG ), + CMD(LE_TEST_END, BLE_MNG, HL_MNG ), + CMD(LE_REM_CON_PARAM_REQ_REPLY, BLE_CTRL, HL_CTRL), + CMD(LE_REM_CON_PARAM_REQ_NEG_REPLY, BLE_CTRL, HL_CTRL), + CMD(LE_SET_DATA_LEN, BLE_CTRL, HL_CTRL), + CMD(LE_RD_SUGGTED_DFT_DATA_LEN, BLE_MNG, HL_MNG ), + CMD(LE_WR_SUGGTED_DFT_DATA_LEN, BLE_MNG, HL_MNG ), + CMD(LE_RD_LOC_P256_PUB_KEY, BLE_MNG, HL_MNG ), + CMD(LE_GEN_DHKEY_V1, BLE_MNG, HL_MNG ), + CMD(LE_ADD_DEV_TO_RSLV_LIST, BLE_MNG, HL_MNG ), + CMD(LE_RMV_DEV_FROM_RSLV_LIST, BLE_MNG, HL_MNG ), + CMD(LE_CLEAR_RSLV_LIST, BLE_MNG, HL_MNG ), + CMD(LE_RD_RSLV_LIST_SIZE, BLE_MNG, HL_MNG ), + CMD(LE_RD_PEER_RSLV_ADDR, BLE_MNG, HL_MNG ), + CMD(LE_RD_LOC_RSLV_ADDR, BLE_MNG, HL_MNG ), + CMD(LE_SET_ADDR_RESOL_EN, BLE_MNG, HL_MNG ), + CMD(LE_SET_RSLV_PRIV_ADDR_TO, BLE_MNG, HL_MNG ), + CMD(LE_RD_MAX_DATA_LEN, BLE_MNG, HL_MNG ), + CMD(LE_RD_PHY, BLE_CTRL, HL_CTRL), + CMD(LE_SET_DFT_PHY, BLE_MNG, HL_MNG ), + CMD(LE_SET_PHY, BLE_CTRL, HL_CTRL), + CMD(LE_RX_TEST_V2, BLE_MNG, HL_MNG ), + CMD(LE_TX_TEST_V2, BLE_MNG, HL_MNG ), + CMD(LE_SET_ADV_SET_RAND_ADDR, BLE_MNG, HL_MNG ), + CMD(LE_SET_EXT_SCAN_RSP_DATA, BLE_MNG, HL_MNG ), + CMD(LE_RD_MAX_ADV_DATA_LEN, BLE_MNG, HL_MNG ), + CMD(LE_RD_NB_SUPP_ADV_SETS, BLE_MNG, HL_MNG ), + CMD(LE_RMV_ADV_SET, BLE_MNG, HL_MNG ), + CMD(LE_CLEAR_ADV_SETS, BLE_MNG, HL_MNG ), + CMD(LE_SET_PER_ADV_PARAM, BLE_MNG, HL_MNG ), + CMD(LE_SET_PER_ADV_DATA, BLE_MNG, HL_MNG ), + CMD(LE_SET_PER_ADV_EN, BLE_MNG, HL_MNG ), + CMD(LE_SET_EXT_SCAN_PARAM, BLE_MNG, HL_MNG ), + CMD(LE_SET_EXT_SCAN_EN, BLE_MNG, HL_MNG ), + CMD(LE_EXT_CREATE_CON, BLE_MNG, HL_MNG ), + CMD(LE_PER_ADV_CREATE_SYNC, BLE_MNG, HL_MNG ), + CMD(LE_PER_ADV_CREATE_SYNC_CANCEL, BLE_MNG, HL_MNG ), + CMD(LE_PER_ADV_TERM_SYNC, BLE_MNG, HL_MNG ), + CMD(LE_ADD_DEV_TO_PER_ADV_LIST, BLE_MNG, HL_MNG ), + CMD(LE_RMV_DEV_FROM_PER_ADV_LIST, BLE_MNG, HL_MNG ), + CMD(LE_CLEAR_PER_ADV_LIST, BLE_MNG, HL_MNG ), + CMD(LE_RD_PER_ADV_LIST_SIZE, BLE_MNG, HL_MNG ), + CMD(LE_RD_TX_PWR, BLE_MNG, HL_MNG ), + CMD(LE_RD_RF_PATH_COMP, BLE_MNG, HL_MNG ), + CMD(LE_WR_RF_PATH_COMP, BLE_MNG, HL_MNG ), + CMD(LE_SET_PRIV_MODE, BLE_MNG, HL_MNG ), + CMD(LE_RX_TEST_V3, BLE_MNG, HL_MNG ), + CMD(LE_TX_TEST_V3, BLE_MNG, HL_MNG ), + CMD(LE_SET_CONLESS_CTE_TX_PARAM, BLE_MNG, HL_MNG ), + CMD(LE_SET_CONLESS_CTE_TX_EN, BLE_MNG, HL_MNG ), + CMD(LE_SET_CONLESS_IQ_SAMPL_EN, BLE_MNG, HL_MNG ), + CMD(LE_SET_CON_CTE_RX_PARAM, BLE_CTRL, HL_CTRL), + CMD(LE_CON_CTE_REQ_EN, BLE_CTRL, HL_CTRL), + CMD(LE_SET_CON_CTE_TX_PARAM, BLE_CTRL, HL_CTRL), + CMD(LE_CON_CTE_RSP_EN, BLE_CTRL, HL_CTRL), + CMD(LE_RD_ANTENNA_INF, BLE_MNG, HL_MNG ), + CMD(LE_SET_PER_ADV_REC_EN, BLE_MNG, HL_MNG ), + CMD(LE_PER_ADV_SYNC_TRANSF, BLE_CTRL, HL_CTRL), + CMD(LE_PER_ADV_SET_INFO_TRANSF, BLE_CTRL, HL_CTRL), + CMD(LE_SET_PER_ADV_SYNC_TRANSF_PARAM, BLE_CTRL, HL_MNG ), + CMD(LE_SET_DFT_PER_ADV_SYNC_TRANSF_PARAM, BLE_MNG, HL_MNG ), + CMD(LE_GEN_DHKEY_V2, BLE_MNG, HL_MNG ), + CMD(LE_MOD_SLEEP_CLK_ACC, BLE_MNG, HL_MNG ), +}; + +/// HCI command descriptors root table (classified by OGF) +const struct hci_cmd_desc_tab_ref hci_cmd_desc_root_tab[] = { + {LK_CNTL_OGF, ARRAY_LEN(hci_cmd_desc_tab_lk_ctrl), hci_cmd_desc_tab_lk_ctrl }, + {CNTLR_BB_OGF, ARRAY_LEN(hci_cmd_desc_tab_ctrl_bb), hci_cmd_desc_tab_ctrl_bb }, + {INFO_PAR_OGF, ARRAY_LEN(hci_cmd_desc_tab_info_par), hci_cmd_desc_tab_info_par}, + {STAT_PAR_OGF, ARRAY_LEN(hci_cmd_desc_tab_stat_par), hci_cmd_desc_tab_stat_par}, + {LE_CNTLR_OGF, ARRAY_LEN(hci_cmd_desc_tab_le), hci_cmd_desc_tab_le }, +}; + +const struct hci_cmd_desc_tag* hci_look_for_cmd_desc(uint16_t opcode) +{ + const struct hci_cmd_desc_tag* tab = NULL; + const struct hci_cmd_desc_tag* desc = NULL; + uint16_t nb_cmds = 0; + uint16_t index = 0; + uint16_t ocf = HCI_OP2OCF(opcode); + uint16_t ogf = HCI_OP2OGF(opcode); + + // Find table corresponding to this OGF + for (index = 0; index < ARRAY_LEN(hci_cmd_desc_root_tab); index++) { + // Compare the command opcodes + if (hci_cmd_desc_root_tab[index].ogf == ogf) { + // Get the command descriptors table information (size and pointer) + tab = hci_cmd_desc_root_tab[index].cmd_desc_tab; + nb_cmds = hci_cmd_desc_root_tab[index].nb_cmds; + break; + } + } + + // Check if a table has been found for this OGF + if (tab != NULL) { + // Find the command descriptor associated to this OCF + for (index = 0; index < nb_cmds; index++) { + // Compare the command opcodes + if (HCI_OP2OCF(tab->opcode) == ocf) { + // Get the command descriptor pointer + desc = tab; + break; + } + + // Jump to next command descriptor + tab++; + } + } + + return (desc); +} + +void hci_send_2_controller(void *param) +{ + struct kernel_msg *msg = kernel_param2msg(param); + +#if BLE_EMB_PRESENT + kernel_task_id_t dest = TASK_BLE_NONE; + uint8_t ll_type = LL_UNDEF; + const struct hci_cmd_desc_tag* cmd_desc; + + // The internal destination first depends on the message type (command, event, data) + switch (msg->id) { + case HCI_COMMAND: + // Find a command descriptor associated to the command opcode + cmd_desc = hci_look_for_cmd_desc(msg->src_id); + + // Check if the command is supported + if(cmd_desc != NULL) + ll_type = (cmd_desc->dest_field & HCI_CMD_DEST_LL_MASK) >> HCI_CMD_DEST_LL_POS; + break; + case HCI_ACL_DATA: + ll_type = BLE_CTRL; + break; + + default: + break; + } + + switch (ll_type) { + + case BLE_MNG: + case MNG: + dest = TASK_BLE_LLM; + break; + + case CTRL: + case BLE_CTRL: + // Check if the link identifier in the dest_id field corresponds to an active BLE link + if(msg->dest_id < BLE_ACTIVITY_MAX) + // Build the destination task ID + dest = KERNEL_BUILD_ID(TASK_BLE_LLC, msg->dest_id); + else + BLE_ASSERT_INFO(0, msg->id, msg->dest_id); + break; + +#if (BLE_EMB_PRESENT && BLE_ISO_PRESENT) + case BLE_ISO: + dest = TASK_BLE_LLI; + break; +#endif //(BLE_EMB_PRESENT && BLE_ISO_PRESENT) + + default: + break; + } + + // Check it the destination has been found + if (dest != TASK_BLE_NONE) { + // Send the command to the internal destination task associated to this command + msg->dest_id = dest; + kernel_msg_send(param); + } else { + BLE_ASSERT_INFO(0, msg->id, msg->src_id); + + // Free message to avoid memory leak + kernel_msg_free(msg); + } +#endif //BLE_EMB_PRESENT +} + +int hci_driver_send(uint8_t type, uint16_t len, uint8_t *buf) +{ + uint16_t err = 0; + uint16_t conidx = 0; //No need use in controller, so use zero + + hci_lock(&g_hci_send_context); + + if (NULL == buf) { + os_printf("%s, buffer is NULL\r\n", __func__); + hci_unlock(&g_hci_send_context); + return -1; + } + + switch (type) { + case HCI_CMD_MSG_TYPE://HCI_EVT_MSG_TYPE: + if (len != (((struct hci_cmd_hdr *)buf)->parlen + 3)) { + os_printf("%s, type:%d, data length is error\r\n", __func__, type); + err = -1; + break; + } + + ///create send command message + void *cmd_data = kernel_msg_alloc(HCI_COMMAND, conidx, ((struct hci_cmd_hdr *)buf)->opcode, ((struct hci_cmd_hdr *)buf)->parlen); + if(cmd_data) { + memcpy(cmd_data, (buf + sizeof(struct hci_cmd_hdr)), ((struct hci_cmd_hdr *)buf)->parlen); + + ///send command to controller + hci_send_2_controller(cmd_data); + }else { + os_printf("create send command message error!\r\n"); + err = -1; + } + break; + + case HCI_ACL_MSG_TYPE: + //HCI_INFO("send ACL handle:0x%x\r\n", ((struct hci_acl_hdr *)buf)->hdl_flags); + if (len != (((struct hci_acl_hdr *)buf)->datalen + 4)) { + os_printf("%s, type:%d, data length is error\r\n", __func__, type); + err = -1; + break; + } + + ///get hci acl data buffer point + uint16_t acl_buf = ble_util_buf_acl_tx_alloc(); + if (acl_buf) { + struct hci_acl_data *data_tx = KERNEL_MSG_ALLOC(HCI_ACL_DATA, ((struct hci_acl_hdr *)buf)->hdl_flags & HCI_ACL_HANDLE_MASK, + TASK_BLE_NONE, hci_acl_data); + // Fill packet length + data_tx->conhdl_pb_bc_flag = ((struct hci_acl_hdr *)buf)->hdl_flags; + data_tx->length = ((struct hci_acl_hdr *)buf)->datalen; + data_tx->buf_ptr = (uint32_t)acl_buf; + uint8_t *buffer = (uint8_t *)(EM_BASE_ADDR + ((uint32_t)acl_buf)); + memcpy((uint8_t *)buffer, (buf + sizeof(struct hci_acl_hdr)), ((struct hci_acl_hdr *)buf)->datalen); + + // Send message + hci_send_2_controller(data_tx); + } else { + os_printf("create acl message error!\r\n"); + err = -1; + } + break; + + default: + os_printf("Unknown buffer type"); + err = -1; + break; + } + + hci_unlock(&g_hci_send_context); + return err; +} +//#include "tuya_hal_system.h" +int hci_driver_open(void) +{ + //bk_printf("initial BLE...%d\r\n", tuya_hal_system_getheapsize()); + + if (kNoErr == rtos_init_mutex(&g_hci_send_context.lock)) + g_hci_send_context.initialized = 1; + else { + os_printf("ble 0 failed\r\n"); + goto err_return; + } + + common_list_init(&recv_wait_list); + + //bk_printf("initial BLE END...%d\r\n", tuya_hal_system_getheapsize()); + return 0; + +err_return: + if (g_hci_send_context.lock) { + g_hci_send_context.initialized = 0; + rtos_deinit_mutex(&g_hci_send_context.lock); + g_hci_send_context.lock = NULL; + } + os_printf("ble open failed\r\n"); + return -1; +} + +void hci_set_event_callback(hci_func_evt_cb hci_cmd_cb, hci_func_evt_cb hci_acl_cb) +{ + g_hci_cmd_cb = hci_cmd_cb; + g_hci_acl_cb = hci_acl_cb; +} + +///Eof + +#endif + +/// @} HCI diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/hci/src/hci_fc.c b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/hci/src/hci_fc.c new file mode 100755 index 0000000..f6d8fc9 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/hci/src/hci_fc.c @@ -0,0 +1,307 @@ +/** + **************************************************************************************** + * + * @file hci_fc.c + * + * @brief HCI Flow Control module source file. + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @addtogroup HCI + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" // SW configuration + +#if (HCI_PRESENT) + +#include // string manipulation +#include "common_error.h" // error definition +#include "common_utils.h" // common utility definition +#include "common_list.h" // list definition + +#include "hci.h" // hci definition +#include "hci_int.h" // hci internal definition + +#include "kernel_msg.h" // kernel message declaration +#include "kernel_task.h" // kernel task definition +#include "kernel_event.h" // kernel event definition +#include "kernel_mem.h" // kernel memory definition +#include "kernel_timer.h" // kernel timer definition + + +/* + * DEFINES + **************************************************************************************** + */ + +#if (BLE_EMB_PRESENT || BT_EMB_PRESENT) + +/* + * ENUMERATIONS DEFINITIONS + **************************************************************************************** + */ + +/* + * STRUCTURES DEFINITIONS + **************************************************************************************** + */ +/// Flow control structure +struct host_set_fc +{ + /// flow control enabled + bool acl_flow_cntl_en; + /// host packet number max + uint16_t acl_pkt_nb; + /// current packet available + uint16_t curr_pkt_nb; + +#if (BT_EMB_PRESENT) +#if VOICE_OVER_HCI + /// flow control enabled + bool sync_flow_cntl_en; + /// host packet number max + uint16_t sync_pkt_nb; +#endif // VOICE_OVER_HCI +#endif // (BT_EMB_PRESENT) +}; + +struct counter_fc +{ + /// counter for number of ACL packets sent to Host + uint16_t acl_pkt_sent; +#if (BT_EMB_PRESENT) +#if VOICE_OVER_HCI + /// counter for number of SYNC packets sent to Host + uint16_t sync_pkt_sent; +#endif // VOICE_OVER_HCI +#endif // (BT_EMB_PRESENT) +}; + +struct hci_fc_tag +{ + /// Flow Control + struct host_set_fc host_set; + struct counter_fc cntr; +}; + + +/* + * CONSTANTS DEFINITIONS + **************************************************************************************** + */ + + +/* + * GLOBAL VARIABLE DEFINITIONS + **************************************************************************************** + */ + +///HCI FC environment context +static struct hci_fc_tag hci_fc_env; + + +/* + * LOCAL FUNCTION DEFINITIONS + **************************************************************************************** + */ + + + +/* + * MODULES INTERNAL FUNCTION DEFINITIONS + **************************************************************************************** + */ + + +/* + * EXPORTED FUNCTION DEFINITIONS + **************************************************************************************** + */ + +void hci_fc_init(void) +{ + memset(&hci_fc_env, 0, sizeof(hci_fc_env)); +} + +uint8_t hci_fc_acl_buf_size_set(uint16_t acl_pkt_len, uint16_t nb_acl_pkts) +{ + uint8_t status = COMMON_ERROR_UNSUPPORTED; + + /* + * Downlink fragmentation is not supported, the packet length must be greater than the maximum data size that + * the device can receive (largest air packet) + */ + #if BT_EMB_PRESENT + if (acl_pkt_len >= DH5_3_PACKET_SIZE) + #elif BLE_EMB_PRESENT + if (acl_pkt_len >= LE_MAX_OCTETS) + #endif // BT_EMB_PRESENT / BLE_EMB_PRESENT + { + status = COMMON_ERROR_NO_ERROR; + + // Store only the number of buffers (packet length is not saved as downlink fragmentation is not supported) + hci_fc_env.host_set.acl_pkt_nb = nb_acl_pkts; + } + + return(status); +} + +#if (BT_EMB_PRESENT) +#if VOICE_OVER_HCI +uint8_t hci_fc_sync_buf_size_set(uint8_t sync_pkt_len, uint16_t nb_sync_pkts) +{ + // Store only the number of buffers (packet length is not saved as downlink fragmentation is not supported) + hci_fc_env.host_set.sync_pkt_nb = nb_sync_pkts; + + return(COMMON_ERROR_NO_ERROR); +} +#endif // VOICE_OVER_HCI +#endif // (BT_EMB_PRESENT) + +uint8_t hci_fc_acl_en(bool flow_enable) +{ + uint8_t status = COMMON_ERROR_NO_ERROR; + + #if (BLE_EMB_PRESENT && (HCI_BLE_CON_SUPPORT)) + // Check that there is no BLE link + for(uint8_t conhdl = 0 ; conhdl < BLE_ACTIVITY_MAX ; conhdl++) + { + if(hci_env.ble_con_state[BLE_CONHDL_TO_LINKID(conhdl)]) + { + status = COMMON_ERROR_COMMAND_DISALLOWED; + break; + } + } + #endif //BLE_EMB_PRESENT + + #if BT_EMB_PRESENT + // Check that there is no BLE link + for(uint8_t conhdl = BT_ACL_CONHDL_MIN ; conhdl <= BT_ACL_CONHDL_MAX ; conhdl++) + { + if(hci_env.bt_acl_con_tab[(conhdl - BT_ACL_CONHDL_MIN)].state != HCI_BT_ACL_STATUS_NOT_ACTIVE) + { + status = COMMON_ERROR_COMMAND_DISALLOWED; + break; + } + } + #endif //BT_EMB_PRESENT + + if(status == COMMON_ERROR_NO_ERROR) + { + hci_fc_env.host_set.acl_flow_cntl_en = flow_enable; + } + + return status; +} + +#if (BT_EMB_PRESENT) +#if VOICE_OVER_HCI +void hci_fc_sync_en(bool flow_enable) +{ + hci_fc_env.host_set.sync_flow_cntl_en = flow_enable; +} +#endif //VOICE_OVER_HCI +#endif // (BT_EMB_PRESENT) + +void hci_fc_acl_packet_sent(void) +{ + if (hci_fc_env.host_set.acl_flow_cntl_en == true) + { + hci_fc_env.cntr.acl_pkt_sent++; + } +} + +#if BT_EMB_PRESENT +#if VOICE_OVER_HCI +void hci_fc_sync_packet_sent(void) +{ + if (hci_fc_env.host_set.sync_flow_cntl_en == true) + { + hci_fc_env.cntr.sync_pkt_sent++; + } +} +#endif //VOICE_OVER_HCI +#endif // (BT_EMB_PRESENT) + +void hci_fc_host_nb_acl_pkts_complete(uint16_t acl_pkt_nb) +{ + if (hci_fc_env.cntr.acl_pkt_sent > acl_pkt_nb) + { + hci_fc_env.cntr.acl_pkt_sent -= acl_pkt_nb; + } + else + { + hci_fc_env.cntr.acl_pkt_sent = 0; + } +} + +#if (BT_EMB_PRESENT) +#if VOICE_OVER_HCI +void hci_fc_host_nb_sync_pkts_complete(uint16_t sync_pkt_nb) +{ + if (hci_fc_env.cntr.sync_pkt_sent > sync_pkt_nb) + { + hci_fc_env.cntr.sync_pkt_sent -= sync_pkt_nb; + } + else + { + hci_fc_env.cntr.sync_pkt_sent = 0; + } +} +#endif //VOICE_OVER_HCI +#endif // (BT_EMB_PRESENT) + +uint16_t hci_fc_check_host_available_nb_acl_packets(void) +{ + uint16_t cnt = 0; + // if flow control is not enabled we can send number of packets + if (hci_fc_env.host_set.acl_flow_cntl_en != true) + { + cnt = 0xFFFF;// maximum packets + } + else + if (hci_fc_env.host_set.acl_pkt_nb > hci_fc_env.cntr.acl_pkt_sent) + { + cnt = hci_fc_env.host_set.acl_pkt_nb - hci_fc_env.cntr.acl_pkt_sent; + } + return cnt; +} + +#if (BT_EMB_PRESENT) +#if (VOICE_OVER_HCI) +uint16_t hci_fc_check_host_available_nb_sync_packets(void) +{ + uint16_t cnt = 0; + // if flow control is not enabled we can send number of packets + if (hci_fc_env.host_set.sync_flow_cntl_en != true) + { + cnt = 0xFFFF;// maximum packets + } + else + if (hci_fc_env.host_set.sync_pkt_nb > hci_fc_env.cntr.sync_pkt_sent) + { + cnt = hci_fc_env.host_set.sync_pkt_nb - hci_fc_env.cntr.sync_pkt_sent; + } + return cnt; +} +#endif //VOICE_OVER_HCI +#endif // (BT_EMB_PRESENT) + +#endif //(BLE_EMB_PRESENT || BT_EMB_PRESENT) + +#endif //(HCI_PRESENT) + +/// @} HCI diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/hci/src/hci_int.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/hci/src/hci_int.h new file mode 100755 index 0000000..9649010 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/hci/src/hci_int.h @@ -0,0 +1,481 @@ +/** + **************************************************************************************** + * + * @file hci.h + * + * @brief This file contains definitions related to the HCI module. + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef HCI_INT_H_ +#define HCI_INT_H_ + +/** + **************************************************************************************** + * @addtogroup HCI Host Controller Interface + *@{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" // SW configuration + +#if (HCI_PRESENT) + +#include // standard definition +#include // standard integer +#include "common_bt.h" // BT standard definitions + +#include "hci.h" +#include "kernel_msg.h" // Kernel message definitions + +/* + * DEFINES + **************************************************************************************** + */ + +/// Macro to get OCF of a known command +#define OCF(cmd) (HCI_OP2OCF(HCI_##cmd##_CMD_OPCODE)) + +/// Unknown opcode identifier +#define HCI_OPCODE_UNKNOWN 0xFFFF + +/** + * Destination field decoding + * + * bit | 7 6 | 5 4 | 3..0 | + * def | Rsvd (pkupk) | HL | LL | + */ +#define HCI_CMD_DEST_LL_POS 0 +#define HCI_CMD_DEST_LL_MASK 0x0F +#define HCI_CMD_DEST_HL_POS 4 +#define HCI_CMD_DEST_HL_MASK 0x30 + +/** + * Destination field decoding + * + * bit | 7..2 | 1 0 | + * def | Rsvd | HL | + */ +#define HCI_EVT_DEST_HL_POS 0 +#define HCI_EVT_DEST_HL_MASK 0x03 + +#if (HCI_TL_SUPPORT) + +/// Special Pack-Unpack settings for HCI commands (parameters and return parameters) +/** + * Special Pack-Unpack settings for HCI commands (parameters and return parameters) + * + * bit | 7 | 6 | 5..0 | + * def | RET PAR | PAR | Rsvd | + */ +#define HCI_CMD_DEST_SPEC_PAR_PK_POS 6 +#define HCI_CMD_DEST_SPEC_PAR_PK_MSK 0x40 +#define HCI_CMD_DEST_SPEC_RET_PAR_PK_POS 7 +#define HCI_CMD_DEST_SPEC_RET_PAR_PK_MSK 0x80 +#define PK_GEN_GEN (0x00) +#define PK_GEN_SPE (HCI_CMD_DEST_SPEC_RET_PAR_PK_MSK) +#define PK_SPE_GEN (HCI_CMD_DEST_SPEC_PAR_PK_MSK) +#define PK_SPE_SPE (HCI_CMD_DEST_SPEC_RET_PAR_PK_MSK | HCI_CMD_DEST_SPEC_PAR_PK_MSK) + +/// Special Pack settings for HCI events +#define PK_GEN 0x00 +#define PK_SPE 0x01 + +/// Macro for building a command descriptor in split mode (with parameters packing/unpacking) +#define CMD(opcode, dest_ll, dest_hl, pkupk, par_size_max, par_fmt, ret_fmt) {HCI_##opcode##_CMD_OPCODE, (dest_ll< 0) + /** + * Voice settings used when SCO connection is auto-accepted + */ + uint16_t voice_settings; + #endif //(MAX_NB_SYNC > 0) + + /** + * Auto-reject flag, used to filter the complete event when a request has been auto-rejected + */ + bool auto_reject; + + #elif (BLE_HOST_PRESENT && !BLE_EMB_PRESENT && (BLE_CENTRAL || BLE_PERIPHERAL)) + /// Link association table for BLE link-oriented messages routing + struct hci_ble_acl_con_tag ble_acl_con_tab[BLE_ACTIVITY_MAX]; + + #endif //(BT_EMB_PRESENT) +}; + +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ + +#if BLE_HOST_PRESENT +extern const uint8_t hl_task_type[]; +#endif //BLE_HOST_PRESENT + +#if (BLE_EMB_PRESENT && BLE_HOST_PRESENT && HCI_TL_SUPPORT) +/** + * Indicate if HCI is used by external Host, or internal Host. + * Used in Full mode only. By default HCI is used by internal Host. + * HCI switches to external host as soon as an HCI command is received. + * This variable should not be reset. + */ +extern bool hci_ext_host; +#endif // (BLE_EMB_PRESENT && BLE_HOST_PRESENT && HCI_TL_SUPPORT) + +///HCI environment context +extern struct hci_env_tag hci_env; + + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** +**************************************************************************************** +* @brief Look for a command descriptor that could match with the specified opcode +* +* @param[in] opcode Command opcode +* +* @return Pointer the command descriptor (NULL if not found) +***************************************************************************************** +*/ +const struct hci_cmd_desc_tag* hci_look_for_cmd_desc(uint16_t opcode); + +/** +**************************************************************************************** +* @brief Look for an event descriptor that could match with the specified event code +* +* @param[in] code event code +* +* @return Pointer the event descriptor (NULL if not found) +***************************************************************************************** +*/ +const struct hci_evt_desc_tag* hci_look_for_evt_desc(uint8_t code); + + +/** +**************************************************************************************** +* @brief Look for an event descriptor that could match with the specified DBG subcode +* +* @param[in] subcode DBG event subcode +* +* @return Pointer the event descriptor (NULL if not found) +***************************************************************************************** +*/ +const struct hci_evt_desc_tag* hci_look_for_dbg_evt_desc(uint8_t subcode); + +#if (BLE_EMB_PRESENT || BLE_HOST_PRESENT) +/** +**************************************************************************************** +* @brief Look for an event descriptor that could match with the specified LE subcode +* +* @param[in] subcode LE event subcode +* +* @return Pointer the event descriptor (NULL if not found) +***************************************************************************************** +*/ +const struct hci_evt_desc_tag* hci_look_for_le_evt_desc(uint8_t subcode); + +#endif //(BLE_EMB_PRESENT || BLE_HOST_PRESENT) + +#if (HCI_TL_SUPPORT) +/** + **************************************************************************************** + * @brief Initialize HIC TL part + * + * @param[in] init_type Type of initialization (@see enum rwip_init_type) + ***************************************************************************************** + */ +void hci_tl_init(uint8_t init_type); + +/** + **************************************************************************************** + * @brief Send an HCI message over TL + * + * @param[in] msg Kernel message carrying the HCI message + ***************************************************************************************** + */ +void hci_tl_send(struct kernel_msg *msg); +#endif //(HCI_TL_SUPPORT) + +/** + **************************************************************************************** + * @brief Initialize Flow Control Structure + * + ***************************************************************************************** + */ +void hci_fc_init(void); + +/** + **************************************************************************************** + * @brief count ACL packets sent to Host + * + ***************************************************************************************** + */ +void hci_fc_acl_packet_sent(void); + +/** + **************************************************************************************** + * @brief count SCO packets sent to Host + * + ***************************************************************************************** + */ +void hci_fc_sync_packet_sent(void); + +/** + **************************************************************************************** + * @brief Calculate number of ACL packets slots available on Host side + * + * @return number of packets available + ***************************************************************************************** + */ +uint16_t hci_fc_check_host_available_nb_acl_packets(void); + +/** + **************************************************************************************** + * @brief Calculate number of SCO packets slots available on Host side + * + * @return number of packets available + ***************************************************************************************** + */ +uint16_t hci_fc_check_host_available_nb_sync_packets(void); + + +#endif //HCI_PRESENT + +/// @} HCI + +#endif // HCI_INT_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/hci/src/hci_msg.c b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/hci/src/hci_msg.c new file mode 100755 index 0000000..19b2630 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/hci/src/hci_msg.c @@ -0,0 +1,2827 @@ +/** + **************************************************************************************** + * + * @file hci_msg.c + * + * @brief HCI module source file. + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @addtogroup HCI + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" // SW configuration + +#if (HCI_PRESENT) + +#include // string manipulation +#include "common_error.h" // error definition +#include "common_utils.h" // common utility definition +#include "common_list.h" // list definition +#include "common_endian.h" // 16bits in host format +#include "hci.h" // hci definition +#include "hci_int.h" // hci internal definition + +/* + * DEFINES + **************************************************************************************** + */ + + +/* + * ENUMERATIONS DEFINITIONS + **************************************************************************************** + */ + + + +/* + * STRUCTURES DEFINITIONS + **************************************************************************************** + */ + + +/* + * LOCAL FUNCTIONS DECLARATIONS + **************************************************************************************** + */ + +/* + * If Transport layer is present, some commands/events parameters with special format (variable content) needs + * specific function for packing or unpacking. The specific function may support packing only, unpacking only, or both. + * + * Function types: + * - pkupk => functions used to pack or unpack parameters (depending on the Host<->Controller direction supported) + * - upk => functions used to unpack parameters + * - pk => functions used to pack parameters + * + * The support of packing or unpacking depends on the Host<->Controller direction supported by each commands/event: + * - for commands supported in LE: + * - Split-Host configuration -> command parameters are packed / return parameters are unpacked + * - Split-Emb or full configuration -> command parameters are unpacked / return parameters are packed + * - for events supported in LE: + * - Split-Host configuration -> event parameters are unpacked + * - Split-Emb or full configuration -> event parameters are packed + * - for commands supported in BT only: + * -> command parameters are unpacked / return parameters are packed + * - for events supported in BT only: + * -> event parameters are packed + */ + +#if (HCI_TL_SUPPORT) +static uint8_t hci_host_nb_cmp_pkts_cmd_pkupk(uint8_t *out, uint8_t *in, uint16_t* out_len, uint16_t in_len); +#if (BT_EMB_PRESENT) +static uint8_t hci_set_evt_filter_cmd_upk(uint8_t *out, uint8_t *in, uint16_t* out_len, uint16_t in_len); +static uint8_t hci_wr_stored_lk_cmd_upk(uint8_t *out, uint8_t *in, uint16_t* out_len, uint16_t in_len); +static uint8_t hci_wr_curr_iac_lap_cmd_upk(uint8_t *out, uint8_t *in, uint16_t* out_len, uint16_t in_len); +#if RW_MWS_COEX +static uint8_t hci_set_external_frame_config_cmd_upk(uint8_t *out, uint8_t *in, uint16_t* out_len, uint16_t in_len); +static uint8_t hci_set_mws_scan_freq_table_upk(uint8_t *out, uint8_t *in, uint16_t* out_len, uint16_t in_len); +static uint8_t hci_set_mws_pattern_config_upk(uint8_t *out, uint8_t *in, uint16_t* out_len, uint16_t in_len); +static uint8_t hci_get_mws_transport_layer_config_cmd_cmp_evt_pk(uint8_t *out, uint8_t *in, uint16_t* out_len, uint16_t in_len); +#endif //RW_MWS_COEX +#endif //(BT_EMB_PRESENT) +#if (BLE_EMB_PRESENT || BLE_HOST_PRESENT) +static uint8_t hci_le_set_ext_scan_param_cmd_upk(uint8_t *out, uint8_t *in, uint16_t* out_len, uint16_t in_len); +static uint8_t hci_le_ext_create_con_cmd_upk(uint8_t *out, uint8_t *in, uint16_t* out_len, uint16_t in_len); +static uint8_t hci_le_set_ext_adv_en_cmd_upk(uint8_t *out, uint8_t *in, uint16_t* out_len, uint16_t in_len); +static uint8_t hci_le_adv_report_evt_pkupk(uint8_t *out, uint8_t *in, uint16_t* out_len, uint16_t in_len); +static uint8_t hci_le_dir_adv_report_evt_pkupk(uint8_t *out, uint8_t *in, uint16_t* out_len, uint16_t in_len); +static uint8_t hci_le_ext_adv_report_evt_pkupk(uint8_t *out, uint8_t *in, uint16_t* out_len, uint16_t in_len); +static uint8_t hci_le_conless_iq_report_evt_pkupk(uint8_t *out, uint8_t *in, uint16_t* out_len, uint16_t in_len); +static uint8_t hci_le_con_iq_report_evt_pkupk(uint8_t *out, uint8_t *in, uint16_t* out_len, uint16_t in_len); +#endif // (BLE_EMB_PRESENT || BLE_HOST_PRESENT) +#if (RW_DEBUG && (BLE_EMB_PRESENT || BT_EMB_PRESENT)) +static uint8_t hci_dbg_assert_evt_pkupk(uint8_t *out, uint8_t *in, uint16_t* out_len, uint16_t in_len); +#endif //(RW_DEBUG && (BLE_EMB_PRESENT || BT_EMB_PRESENT)) +#if BLE_IQ_GEN +static uint8_t hci_dbg_iqgen_cfg_cmd_upk(uint8_t *out, uint8_t *in, uint16_t* out_len, uint16_t in_len); +#endif //BLE_IQ_GEN +#endif //(HCI_TL_SUPPORT) + +/* + * GLOBAL VARIABLE DEFINITIONS + **************************************************************************************** + */ + + +/// HCI command descriptors (OGF link control) +const struct hci_cmd_desc_tag hci_cmd_desc_tab_lk_ctrl[] = +{ + #if BT_EMB_PRESENT + CMD(INQ, BT_MNG, 0, PK_GEN_GEN, 5, "3BBB", NULL ), + CMD(INQ_CANCEL, BT_MNG, 0, PK_GEN_GEN, 0, NULL, "B" ), + CMD(PER_INQ_MODE, BT_MNG, 0, PK_GEN_GEN, 9, "HH3BBB", "B" ), + CMD(EXIT_PER_INQ_MODE, BT_MNG, 0, PK_GEN_GEN, 0, NULL, "B" ), + CMD(CREATE_CON, BT_MNG, 0, PK_GEN_GEN, 13, "6BHBBHB", NULL ), + CMD(CREATE_CON_CANCEL, BT_MNG, 0, PK_GEN_GEN, 6, "6B", "B6B" ), + CMD(ACCEPT_CON_REQ, BT_CTRL_BD_ADDR, 0, PK_GEN_GEN, 7, "6BB", NULL ), + CMD(REJECT_CON_REQ, BT_CTRL_BD_ADDR, 0, PK_GEN_GEN, 7, "6BB", NULL ), + CMD(LK_REQ_REPLY, BT_CTRL_BD_ADDR, 0, PK_GEN_GEN, 22, "6B16B", "B6B" ), + CMD(LK_REQ_NEG_REPLY, BT_CTRL_BD_ADDR, 0, PK_GEN_GEN, 6, "6B", "B6B" ), + CMD(PIN_CODE_REQ_REPLY, BT_CTRL_BD_ADDR, 0, PK_GEN_GEN, 23, "6BB16B", "B6B" ), + CMD(PIN_CODE_REQ_NEG_REPLY, BT_CTRL_BD_ADDR, 0, PK_GEN_GEN, 6, "6B", "B6B" ), + CMD(CHG_CON_PKT_TYPE, BT_CTRL_CONHDL, 0, PK_GEN_GEN, 4, "HH", NULL ), + CMD(AUTH_REQ, BT_CTRL_CONHDL, 0, PK_GEN_GEN, 2, "H", NULL ), + CMD(SET_CON_ENC, BT_CTRL_CONHDL, 0, PK_GEN_GEN, 3, "HB", NULL ), + CMD(CHG_CON_LK, BT_CTRL_CONHDL, 0, PK_GEN_GEN, 2, "H", NULL ), + CMD(MASTER_LK, BT_BCST, 0, PK_GEN_GEN, 1, "B", NULL ), + CMD(REM_NAME_REQ, BT_MNG, 0, PK_GEN_GEN, 10, "6BBBH", NULL ), + CMD(REM_NAME_REQ_CANCEL, BT_MNG, 0, PK_GEN_GEN, 6, "6B", "B6B" ), + CMD(RD_REM_SUPP_FEATS, BT_CTRL_CONHDL, 0, PK_GEN_GEN, 2, "H", NULL ), + CMD(RD_REM_EXT_FEATS, BT_CTRL_CONHDL, 0, PK_GEN_GEN, 3, "HB", NULL ), + CMD(RD_CLK_OFF, BT_CTRL_CONHDL, 0, PK_GEN_GEN, 2, "H", NULL ), + CMD(RD_LMP_HDL, BT_CTRL_CONHDL, 0, PK_GEN_GEN, 2, "H", "BHBL"), + CMD(SETUP_SYNC_CON, BT_CTRL_CONHDL, 0, PK_GEN_GEN, 17, "HLLHHBH", NULL ), + CMD(ACCEPT_SYNC_CON_REQ, BT_CTRL_BD_ADDR, 0, PK_GEN_GEN, 21, "6BLLHHBH", NULL ), + CMD(REJECT_SYNC_CON_REQ, BT_CTRL_BD_ADDR, 0, PK_GEN_GEN, 7, "6BB", NULL ), + CMD(IO_CAP_REQ_REPLY, BT_CTRL_BD_ADDR, 0, PK_GEN_GEN, 9, "6BBBB", "B6B" ), + CMD(USER_CFM_REQ_REPLY, BT_CTRL_BD_ADDR, 0, PK_GEN_GEN, 6, "6B", "B6B" ), + CMD(USER_CFM_REQ_NEG_REPLY, BT_CTRL_BD_ADDR, 0, PK_GEN_GEN, 6, "6B", "B6B" ), + CMD(USER_PASSKEY_REQ_REPLY, BT_CTRL_BD_ADDR, 0, PK_GEN_GEN, 10, "6BL", "B6B" ), + CMD(USER_PASSKEY_REQ_NEG_REPLY, BT_CTRL_BD_ADDR, 0, PK_GEN_GEN, 6, "6B", "B6B" ), + CMD(REM_OOB_DATA_REQ_REPLY, BT_CTRL_BD_ADDR, 0, PK_GEN_GEN, 38, "6B16B16B", "B6B" ), + CMD(REM_OOB_DATA_REQ_NEG_REPLY, BT_CTRL_BD_ADDR, 0, PK_GEN_GEN, 6, "6B", "B6B" ), + CMD(IO_CAP_REQ_NEG_REPLY, BT_CTRL_BD_ADDR, 0, PK_GEN_GEN, 7, "6BB", "B6B" ), + CMD(ENH_SETUP_SYNC_CON, BT_CTRL_CONHDL, 0, PK_GEN_GEN, 59, "HLL5B5BHHLL5B5BHHBBBBBBBBHHB", NULL), + CMD(ENH_ACCEPT_SYNC_CON, BT_CTRL_BD_ADDR, 0, PK_GEN_GEN, 63, "6BLL5B5BHHLL5B5BHHBBBBBBBBHHB", NULL), + CMD(REM_OOB_EXT_DATA_REQ_REPLY, BT_CTRL_BD_ADDR, 0, PK_GEN_GEN, 70, "6B16B16B16B16B", "B6B" ), + #if CSB_SUPPORT + CMD(TRUNC_PAGE, BT_MNG, 0, PK_GEN_GEN, 9, "6BBH", NULL ), + CMD(TRUNC_PAGE_CAN, BT_MNG, 0, PK_GEN_GEN, 6, "6B", "B6B" ), + CMD(SET_CON_SLV_BCST, BT_BCST, 0, PK_GEN_GEN, 11, "BBBHHHH", "BBH" ), + CMD(SET_CON_SLV_BCST_REC, BT_BCST, 0, PK_GEN_GEN, 34, "B6BBHLLHBBH10B", "B6BB"), + CMD(START_SYNC_TRAIN, BT_BCST, 0, PK_GEN_GEN, 0, NULL, NULL ), + CMD(REC_SYNC_TRAIN, BT_BCST, 0, PK_GEN_GEN, 12, "6BHHH", NULL ), + #endif //CSB_SUPPORT + #endif// BT_EMB_PRESENT + CMD(DISCONNECT, CTRL, HL_CTRL, PK_GEN_GEN, 3, "HB", NULL ), + CMD(RD_REM_VER_INFO, CTRL, HL_CTRL, PK_GEN_GEN, 2, "H", NULL ), +}; + +///// HCI command descriptors (OGF link policy) +#if BT_EMB_PRESENT +const struct hci_cmd_desc_tag hci_cmd_desc_tab_lk_pol[] = +{ + CMD(SNIFF_MODE, BT_CTRL_CONHDL, 0, PK_GEN_GEN, 10, "HHHHH", NULL ), + CMD(EXIT_SNIFF_MODE, BT_CTRL_CONHDL, 0, PK_GEN_GEN, 2, "H", NULL ), + CMD(QOS_SETUP, BT_CTRL_CONHDL, 0, PK_GEN_GEN, 20, "HBBLLLL", NULL ), + CMD(ROLE_DISCOVERY, BT_CTRL_CONHDL, 0, PK_GEN_GEN, 2, "H", "BHB"), + CMD(SWITCH_ROLE, BT_CTRL_BD_ADDR, 0, PK_GEN_GEN, 7, "6BB", NULL ), + CMD(RD_LINK_POL_STG, BT_CTRL_CONHDL, 0, PK_GEN_GEN, 2, "H", "BHH"), + CMD(WR_LINK_POL_STG, BT_CTRL_CONHDL, 0, PK_GEN_GEN, 4, "HH", "BH" ), + CMD(RD_DFT_LINK_POL_STG, BT_MNG, 0, PK_GEN_GEN, 0, NULL, "BH" ), + CMD(WR_DFT_LINK_POL_STG, BT_MNG, 0, PK_GEN_GEN, 2, "H", "B" ), + CMD(FLOW_SPEC, BT_CTRL_CONHDL, 0, PK_GEN_GEN, 21, "HBBBLLLL", NULL ), + CMD(SNIFF_SUB, BT_CTRL_CONHDL, 0, PK_GEN_GEN, 8, "HHHH", "BH" ), +}; +#endif// BT_EMB_PRESENT + +/// HCI command descriptors (OGF controller and baseband) +const struct hci_cmd_desc_tag hci_cmd_desc_tab_ctrl_bb[] = +{ + CMD(SET_EVT_MASK, MNG, HL_MNG, PK_GEN_GEN, 8, "8B", "B" ), + CMD(RESET, MNG, HL_MNG, PK_GEN_GEN, 0, NULL, "B" ), + CMD(RD_TX_PWR_LVL, CTRL, HL_CTRL, PK_GEN_GEN, 3, "HB", "BHB" ), + CMD(SET_CTRL_TO_HOST_FLOW_CTRL, MNG, HL_MNG, PK_GEN_GEN, 1, "B", "B" ), + CMD(HOST_BUF_SIZE, MNG, HL_MNG, PK_GEN_GEN, 7, "HBHH", "B" ), + CMD(HOST_NB_CMP_PKTS, MNG, HL_MNG, PK_SPE_GEN, 30, &hci_host_nb_cmp_pkts_cmd_pkupk, "B" ), + CMD(RD_AUTH_PAYL_TO, CTRL, HL_CTRL, PK_GEN_GEN, 2, "H", "BHH" ), + CMD(WR_AUTH_PAYL_TO, CTRL, HL_CTRL, PK_GEN_GEN, 4, "HH", "BH" ), + CMD(SET_EVT_MASK_PAGE_2, MNG, HL_MNG, PK_GEN_GEN, 8, "8B", "B" ), + #if BT_EMB_PRESENT + CMD(SET_EVT_FILTER, BT_MNG, 0, PK_SPE_GEN, 9, &hci_set_evt_filter_cmd_upk, "B" ), + CMD(FLUSH, BT_CTRL_CONHDL, 0, PK_GEN_GEN, 2, "H", "BH" ), + CMD(RD_PIN_TYPE, BT_MNG, 0, PK_GEN_GEN, 0, NULL, "BB" ), + CMD(WR_PIN_TYPE, BT_MNG, 0, PK_GEN_GEN, 1, "B", "B" ), + CMD(RD_STORED_LK, BT_MNG, 0, PK_GEN_GEN, 7, "6BB", "BHH" ), + CMD(WR_STORED_LK, BT_MNG, 0, PK_SPE_GEN, 243, &hci_wr_stored_lk_cmd_upk, "BB" ), + CMD(DEL_STORED_LK, BT_MNG, 0, PK_GEN_GEN, 7, "6BB", "BH" ), + CMD(WR_LOCAL_NAME, BT_MNG, 0, PK_GEN_GEN, 248, "248B", "B" ), + CMD(RD_LOCAL_NAME, BT_MNG, 0, PK_GEN_GEN, 0, NULL, "B248B" ), + CMD(RD_CON_ACCEPT_TO, BT_MNG, 0, PK_GEN_GEN, 0, NULL, "BH" ), + CMD(WR_CON_ACCEPT_TO, BT_MNG, 0, PK_GEN_GEN, 2, "H", "B" ), + CMD(RD_PAGE_TO, BT_MNG, 0, PK_GEN_GEN, 0, NULL, "BH" ), + CMD(WR_PAGE_TO, BT_MNG, 0, PK_GEN_GEN, 2, "H", "B" ), + CMD(RD_SCAN_EN, BT_MNG, 0, PK_GEN_GEN, 0, NULL, "BB" ), + CMD(WR_SCAN_EN, BT_MNG, 0, PK_GEN_GEN, 1, "B", "B" ), + CMD(RD_PAGE_SCAN_ACT, BT_MNG, 0, PK_GEN_GEN, 0, NULL, "BHH" ), + CMD(WR_PAGE_SCAN_ACT, BT_MNG, 0, PK_GEN_GEN, 4, "HH", "B" ), + CMD(RD_INQ_SCAN_ACT, BT_MNG, 0, PK_GEN_GEN, 0, NULL, "BHH" ), + CMD(WR_INQ_SCAN_ACT, BT_MNG, 0, PK_GEN_GEN, 4, "HH", "B" ), + CMD(RD_AUTH_EN, BT_MNG, 0, PK_GEN_GEN, 0, NULL, "BB" ), + CMD(WR_AUTH_EN, BT_MNG, 0, PK_GEN_GEN, 1, "B", "B" ), + CMD(RD_CLASS_OF_DEV, BT_MNG, 0, PK_GEN_GEN, 0, NULL, "B3B" ), + CMD(WR_CLASS_OF_DEV, BT_MNG, 0, PK_GEN_GEN, 3, "3B", "B" ), + #if (MAX_NB_SYNC > 0) + CMD(RD_VOICE_STG, BT_MNG, 0, PK_GEN_GEN, 0, NULL, "BH" ), + CMD(WR_VOICE_STG, BT_MNG, 0, PK_GEN_GEN, 2, "H", "B" ), + #endif // (MAX_NB_SYNC > 0) + CMD(RD_AUTO_FLUSH_TO, BT_CTRL_CONHDL, 0, PK_GEN_GEN, 2, "H", "BHH" ), + CMD(WR_AUTO_FLUSH_TO, BT_CTRL_CONHDL, 0, PK_GEN_GEN, 4, "HH", "BH" ), + CMD(RD_NB_BDCST_RETX, BT_BCST, 0, PK_GEN_GEN, 0, NULL, "BB" ), + CMD(WR_NB_BDCST_RETX, BT_BCST, 0, PK_GEN_GEN, 1, "B", "B" ), + CMD(RD_SYNC_FLOW_CTRL_EN, BT_MNG, 0, PK_GEN_GEN, 0, NULL, "BB" ), + CMD(WR_SYNC_FLOW_CTRL_EN, BT_MNG, 0, PK_GEN_GEN, 1, "B", "B" ), + CMD(RD_LINK_SUPV_TO, BT_CTRL_CONHDL, 0, PK_GEN_GEN, 2, "H", "BHH" ), + CMD(WR_LINK_SUPV_TO, BT_CTRL_CONHDL, 0, PK_GEN_GEN, 4, "HH", "BH" ), + CMD(RD_NB_SUPP_IAC, BT_MNG, 0, PK_GEN_GEN, 0, NULL, "BB" ), + CMD(RD_CURR_IAC_LAP, BT_MNG, 0, PK_GEN_GEN, 0, NULL, "BB3B" ), + CMD(WR_CURR_IAC_LAP, BT_MNG, 0, PK_SPE_GEN, 253, &hci_wr_curr_iac_lap_cmd_upk, "B" ), + CMD(SET_AFH_HOST_CH_CLASS, BT_MNG, 0, PK_GEN_GEN, 10, "10B", "B" ), + CMD(RD_INQ_SCAN_TYPE, BT_MNG, 0, PK_GEN_GEN, 0, NULL, "BB" ), + CMD(WR_INQ_SCAN_TYPE, BT_MNG, 0, PK_GEN_GEN, 1, "B", "B" ), + CMD(RD_INQ_MODE, BT_MNG, 0, PK_GEN_GEN, 0, NULL, "BB" ), + CMD(WR_INQ_MODE, BT_MNG, 0, PK_GEN_GEN, 1, "B", "B" ), + CMD(RD_PAGE_SCAN_TYPE, BT_MNG, 0, PK_GEN_GEN, 0, NULL, "BB" ), + CMD(WR_PAGE_SCAN_TYPE, BT_MNG, 0, PK_GEN_GEN, 1, "B", "B" ), + CMD(RD_AFH_CH_ASSESS_MODE, BT_MNG, 0, PK_GEN_GEN, 0, NULL, "BB" ), + CMD(WR_AFH_CH_ASSESS_MODE, BT_MNG, 0, PK_GEN_GEN, 1, "B", "B" ), + CMD(RD_EXT_INQ_RSP, BT_MNG, 0, PK_GEN_GEN, 0, NULL, "BB240B" ), + CMD(WR_EXT_INQ_RSP, BT_MNG, 0, PK_GEN_GEN, 241, "B240B", "B" ), + CMD(REFRESH_ENC_KEY, BT_CTRL_CONHDL, 0, PK_GEN_GEN, 2, "H", NULL ), + CMD(RD_SP_MODE, BT_MNG, 0, PK_GEN_GEN, 0, NULL, "BB" ), + CMD(WR_SP_MODE, BT_MNG, 0, PK_GEN_GEN, 1, "B", "B" ), + CMD(RD_LOC_OOB_DATA, BT_MNG, 0, PK_GEN_GEN, 0, NULL, "B16B16B"), + CMD(RD_INQ_RSP_TX_PWR_LVL, BT_MNG, 0, PK_GEN_GEN, 0, NULL, "BB" ), + CMD(WR_INQ_TX_PWR_LVL, BT_MNG, 0, PK_GEN_GEN, 1, "B", "B" ), + CMD(RD_DFT_ERR_DATA_REP, BT_MNG, 0, PK_GEN_GEN, 0, NULL, "BB" ), + CMD(WR_DFT_ERR_DATA_REP, BT_MNG, 0, PK_GEN_GEN, 1, "B", "B" ), + CMD(ENH_FLUSH, BT_CTRL_CONHDL, 0, PK_GEN_GEN, 3, "HB", NULL ), + CMD(SEND_KEYPRESS_NOTIF, BT_CTRL_BD_ADDR, 0, PK_GEN_GEN, 7, "6BB", "B6B" ), + CMD(RD_ENH_TX_PWR_LVL, BT_CTRL_CONHDL, 0, PK_GEN_GEN, 3, "HB", "BHBBB" ), + CMD(RD_LE_HOST_SUPP, BT_MNG, 0, PK_GEN_GEN, 0, NULL, "BBB" ), + CMD(WR_LE_HOST_SUPP, BT_MNG, 0, PK_GEN_GEN, 2, "BB", "B" ), + #if RW_MWS_COEX + CMD(SET_MWS_CHANNEL_PARAMS, BT_MNG, 0, PK_GEN_GEN, 10, "BHHHHB", "B" ), + CMD(SET_EXTERNAL_FRAME_CONFIG, BT_MNG, 0, PK_SPE_GEN, 255, &hci_set_external_frame_config_cmd_upk, "B" ), + CMD(SET_MWS_SIGNALING, BT_MNG, 0, PK_GEN_GEN, 30, "HHHHHHHHHHHHHHH", "BHHHHHHHHHHHHHHHH" ), + CMD(SET_MWS_TRANSPORT_LAYER, BT_MNG, 0, PK_GEN_GEN, 9, "BLL", "B" ), + CMD(SET_MWS_SCAN_FREQ_TABLE, BT_MNG, 0, PK_SPE_GEN, 255, &hci_set_mws_scan_freq_table_upk, "B" ), + CMD(SET_MWS_PATTERN_CONFIG, BT_MNG, 0, PK_SPE_GEN, 255, &hci_set_mws_pattern_config_upk, "B" ), + #endif //RW_MWS_COEX + #if CSB_SUPPORT + CMD(SET_RES_LT_ADDR, BT_BCST, 0, PK_GEN_GEN, 1, "B", "BB" ), + CMD(DEL_RES_LT_ADDR, BT_BCST, 0, PK_GEN_GEN, 1, "B", "BB" ), + CMD(SET_CON_SLV_BCST_DATA, BT_BCST, 0, PK_GEN_GEN, 255, "BBnB", "BB" ), + CMD(RD_SYNC_TRAIN_PARAM, BT_BCST, 0, PK_GEN_GEN, 0, NULL, "BHLB" ), + CMD(WR_SYNC_TRAIN_PARAM, BT_BCST, 0, PK_GEN_GEN, 9, "HHLB", "BH" ), + #endif //CSB_SUPPORT + CMD(RD_SEC_CON_HOST_SUPP, BT_MNG, 0, PK_GEN_GEN, 0, NULL, "BB" ), + CMD(WR_SEC_CON_HOST_SUPP, BT_MNG, 0, PK_GEN_GEN, 1, "B", "B" ), + CMD(RD_LOC_OOB_EXT_DATA, BT_MNG, 0, PK_GEN_GEN, 0, NULL, "B16B16B16B16B"), + CMD(RD_EXT_PAGE_TO, BT_MNG, 0, PK_GEN_GEN, 0, NULL, "BH" ), + CMD(WR_EXT_PAGE_TO, BT_MNG, 0, PK_GEN_GEN, 2, "H", "B" ), + CMD(RD_EXT_INQ_LEN, BT_MNG, 0, PK_GEN_GEN, 0, NULL, "BH" ), + CMD(WR_EXT_INQ_LEN, BT_MNG, 0, PK_GEN_GEN, 2, "H", "B" ), + #endif// BT_EMB_PRESENT +}; + +/// HCI command descriptors (OGF informational parameters) +const struct hci_cmd_desc_tag hci_cmd_desc_tab_info_par[] = +{ + CMD(RD_LOCAL_VER_INFO, MNG, HL_MNG, PK_GEN_GEN, 0, NULL, "BBHBHH"), + CMD(RD_LOCAL_SUPP_CMDS, MNG, HL_MNG, PK_GEN_GEN, 0, NULL, "B64B" ), + CMD(RD_LOCAL_SUPP_FEATS, MNG, HL_MNG, PK_GEN_GEN, 0, NULL, "B8B" ), + CMD(RD_BD_ADDR, MNG, HL_MNG, PK_GEN_GEN, 0, NULL, "B6B" ), + #if BT_EMB_PRESENT + CMD(RD_BUFF_SIZE, BT_MNG, 0, PK_GEN_GEN, 0, NULL, "BHBHH" ), + CMD(RD_LOCAL_EXT_FEATS, BT_MNG, 0, PK_GEN_GEN, 1, "B", "BBB8B" ), + CMD(RD_LOCAL_SUPP_CODECS, BT_MNG, 0, PK_GEN_GEN, 0, NULL, "BBB" ), + CMD(RD_LOCAL_SP_OPT, BT_MNG, 0, PK_GEN_GEN, 0, NULL, "BBB" ), + #endif //BT_EMB_PRESENT +}; + +/// HCI command descriptors (OGF status parameters) +const struct hci_cmd_desc_tag hci_cmd_desc_tab_stat_par[] = +{ + CMD(RD_RSSI, CTRL, HL_CTRL, PK_GEN_GEN, 2, "H", "BHB" ), + #if BT_EMB_PRESENT + CMD(RD_FAIL_CONTACT_CNT, BT_CTRL_CONHDL, 0, PK_GEN_GEN, 2, "H", "BHH" ), + CMD(RST_FAIL_CONTACT_CNT, BT_CTRL_CONHDL, 0, PK_GEN_GEN, 2, "H", "BH" ), + CMD(RD_LINK_QUAL, BT_CTRL_CONHDL, 0, PK_GEN_GEN, 2, "H", "BHB" ), + CMD(RD_AFH_CH_MAP, BT_CTRL_CONHDL, 0, PK_GEN_GEN, 2, "H", "BHB10B"), + CMD(RD_CLK, BT_MNG , 0, PK_GEN_GEN, 3, "HB", "BHLH" ), + CMD(RD_ENC_KEY_SIZE, BT_CTRL_CONHDL, 0, PK_GEN_GEN, 2, "H", "BHB" ), + #if RW_MWS_COEX + CMD(GET_MWS_TRANSPORT_LAYER_CONFIG, BT_MNG, 0, PK_GEN_SPE, 0, NULL, &hci_get_mws_transport_layer_config_cmd_cmp_evt_pk), + #endif //RW_MWS_COEX + #endif //BT_EMB_PRESENT +}; + +///// HCI command descriptors (OGF testing) +#if BT_EMB_PRESENT +const struct hci_cmd_desc_tag hci_cmd_desc_tab_testing[] = +{ + CMD(RD_LOOPBACK_MODE, BT_MNG, 0, PK_GEN_GEN, 0, NULL, "BB"), + CMD(WR_LOOPBACK_MODE, BT_MNG, 0, PK_GEN_GEN, 1, "B", "B" ), + CMD(EN_DUT_MODE, BT_MNG, 0, PK_GEN_GEN, 0, NULL, "B" ), + CMD(WR_SP_DBG_MODE, BT_MNG, 0, PK_GEN_GEN, 1, "B", "B" ), + CMD(WR_SEC_CON_TEST_MODE, BT_CTRL_CONHDL, 0, PK_GEN_GEN, 4, "HBB", "BH" ), +}; +#endif// BT_EMB_PRESENT + +#if (BLE_EMB_PRESENT || BLE_HOST_PRESENT) +/// HCI command descriptors (OGF LE controller) +const struct hci_cmd_desc_tag hci_cmd_desc_tab_le[] = +{ + CMD(LE_SET_EXT_ADV_EN, BLE_MNG, HL_MNG, PK_SPE_GEN, 42, &hci_le_set_ext_adv_en_cmd_upk, "B" ), + CMD(LE_SET_EXT_ADV_PARAM, BLE_MNG, HL_MNG, PK_GEN_GEN, 25, "BH3B3BBBB6BBBBBBBB", "BB" ), + CMD(LE_SET_EXT_ADV_DATA, BLE_MNG, HL_MNG, PK_GEN_GEN, 255, "BBBnB", "B" ), + CMD(LE_SET_EVT_MASK, BLE_MNG, HL_MNG, PK_GEN_GEN, 8, "8B", "B" ), + CMD(LE_RD_BUFF_SIZE, BLE_MNG, HL_MNG, PK_GEN_GEN, 0, NULL, "BHB" ), + CMD(LE_RD_LOCAL_SUPP_FEATS, BLE_MNG, HL_MNG, PK_GEN_GEN, 0, NULL, "B8B" ), + CMD(LE_SET_RAND_ADDR, BLE_MNG, HL_MNG, PK_GEN_GEN, 6, "6B", "B" ), + CMD(LE_RD_ADV_CHNL_TX_PW, BLE_MNG, HL_MNG, PK_GEN_GEN, 0, NULL, "BB" ), + #if (HCI_TL_SUPPORT) + CMD(LE_SET_ADV_PARAM, BLE_MNG, HL_MNG, PK_GEN_GEN, 15, "HHBBB6BBB", "B" ), + CMD(LE_SET_ADV_DATA, BLE_MNG, HL_MNG, PK_GEN_GEN, 32, "B31B", "B" ), + CMD(LE_SET_SCAN_RSP_DATA, BLE_MNG, HL_MNG, PK_GEN_GEN, 32, "B31B", "B" ), + CMD(LE_SET_ADV_EN, BLE_MNG, HL_MNG, PK_GEN_GEN, 1, "B", "B" ), + CMD(LE_SET_SCAN_PARAM, BLE_MNG, HL_MNG, PK_GEN_GEN, 7, "BHHBB", "B" ), + CMD(LE_SET_SCAN_EN, BLE_MNG, HL_MNG, PK_GEN_GEN, 2, "BB", "B" ), + CMD(LE_CREATE_CON, BLE_MNG, HL_MNG, PK_GEN_GEN, 25, "HHBB6BBHHHHHH", NULL ), + #endif //(HCI_TL_SUPPORT) + CMD(LE_CREATE_CON_CANCEL, BLE_MNG, HL_MNG, PK_GEN_GEN, 0, NULL, "B" ), + CMD(LE_RD_WLST_SIZE, BLE_MNG, HL_MNG, PK_GEN_GEN, 0, NULL, "BB" ), + CMD(LE_CLEAR_WLST, BLE_MNG, HL_MNG, PK_GEN_GEN, 0, NULL, "B" ), + CMD(LE_ADD_DEV_TO_WLST, BLE_MNG, HL_MNG, PK_GEN_GEN, 7, "B6B", "B" ), + CMD(LE_RMV_DEV_FROM_WLST, BLE_MNG, HL_MNG, PK_GEN_GEN, 7, "B6B", "B" ), + CMD(LE_CON_UPDATE, BLE_CTRL, HL_CTRL, PK_GEN_GEN, 14, "HHHHHHH", NULL ), + CMD(LE_SET_HOST_CH_CLASS, BLE_MNG, HL_MNG, PK_GEN_GEN, 5, "5B", "B" ), + CMD(LE_RD_CHNL_MAP, BLE_CTRL, HL_CTRL, PK_GEN_GEN, 2, "H", "BH5B" ), + CMD(LE_RD_REM_FEATS, BLE_CTRL, HL_CTRL, PK_GEN_GEN, 2, "H", NULL ), + CMD(LE_ENC, BLE_MNG, HL_MNG, PK_GEN_GEN, 32, "16B16B", "B16B" ), + CMD(LE_RAND, BLE_MNG, HL_MNG, PK_GEN_GEN, 0, NULL, "B8B" ), + CMD(LE_START_ENC, BLE_CTRL, HL_CTRL, PK_GEN_GEN, 28, "H8BH16B", NULL ), + CMD(LE_LTK_REQ_REPLY, BLE_CTRL, HL_CTRL, PK_GEN_GEN, 18, "H16B", "BH" ), + CMD(LE_LTK_REQ_NEG_REPLY, BLE_CTRL, HL_CTRL, PK_GEN_GEN, 2, "H", "BH" ), + CMD(LE_RD_SUPP_STATES, BLE_MNG, HL_MNG, PK_GEN_GEN, 0, NULL, "B8B" ), + #if (HCI_TL_SUPPORT) + CMD(LE_RX_TEST_V1, BLE_MNG, HL_MNG, PK_GEN_GEN, 1, "B", "B" ), + CMD(LE_TX_TEST_V1, BLE_MNG, HL_MNG, PK_GEN_GEN, 3, "BBB", "B" ), + #endif //(HCI_TL_SUPPORT) + CMD(LE_TEST_END, BLE_MNG, HL_MNG, PK_GEN_GEN, 0, NULL, "BH" ), + CMD(LE_REM_CON_PARAM_REQ_REPLY, BLE_CTRL, HL_CTRL, PK_GEN_GEN, 14, "HHHHHHH", "BH" ), + CMD(LE_REM_CON_PARAM_REQ_NEG_REPLY, BLE_CTRL, HL_CTRL, PK_GEN_GEN, 3, "HB", "BH" ), + CMD(LE_SET_DATA_LEN, BLE_CTRL, HL_CTRL, PK_GEN_GEN, 6, "HHH", "BH" ), + CMD(LE_RD_SUGGTED_DFT_DATA_LEN, BLE_MNG, HL_MNG, PK_GEN_GEN, 0, NULL, "BHH" ), + CMD(LE_WR_SUGGTED_DFT_DATA_LEN, BLE_MNG, HL_MNG, PK_GEN_GEN, 4, "HH", "B" ), + CMD(LE_RD_LOC_P256_PUB_KEY, BLE_MNG, HL_MNG, PK_GEN_GEN, 0, NULL, NULL ), + CMD(LE_GEN_DHKEY_V1, BLE_MNG, HL_MNG, PK_GEN_GEN, 64, "64B", NULL ), + CMD(LE_ADD_DEV_TO_RSLV_LIST, BLE_MNG, HL_MNG, PK_GEN_GEN, 39, "B6B16B16B", "B" ), + CMD(LE_RMV_DEV_FROM_RSLV_LIST, BLE_MNG, HL_MNG, PK_GEN_GEN, 7, "B6B", "B" ), + CMD(LE_CLEAR_RSLV_LIST, BLE_MNG, HL_MNG, PK_GEN_GEN, 0, NULL, "B" ), + CMD(LE_RD_RSLV_LIST_SIZE, BLE_MNG, HL_MNG, PK_GEN_GEN, 0, NULL, "BB" ), + CMD(LE_RD_PEER_RSLV_ADDR, BLE_MNG, HL_MNG, PK_GEN_GEN, 7, "B6B", "B6B" ), + CMD(LE_RD_LOC_RSLV_ADDR, BLE_MNG, HL_MNG, PK_GEN_GEN, 7, "B6B", "B6B" ), + CMD(LE_SET_ADDR_RESOL_EN, BLE_MNG, HL_MNG, PK_GEN_GEN, 1, "B", "B" ), + CMD(LE_SET_RSLV_PRIV_ADDR_TO, BLE_MNG, HL_MNG, PK_GEN_GEN, 2, "H", "B" ), + CMD(LE_RD_MAX_DATA_LEN, BLE_MNG, HL_MNG, PK_GEN_GEN, 0, NULL, "BHHHH" ), + CMD(LE_RD_PHY, BLE_CTRL, HL_CTRL, PK_GEN_GEN, 2, "H", "BHBB" ), + CMD(LE_SET_DFT_PHY, BLE_MNG, HL_MNG, PK_GEN_GEN, 3, "BBB", "B" ), + CMD(LE_SET_PHY, BLE_CTRL, HL_CTRL, PK_GEN_GEN, 7, "HBBBH", NULL ), + CMD(LE_RX_TEST_V2, BLE_MNG, HL_MNG, PK_GEN_GEN, 3, "BBB", "B" ), + CMD(LE_TX_TEST_V2, BLE_MNG, HL_MNG, PK_GEN_GEN, 4, "BBBB", "B" ), + CMD(LE_SET_ADV_SET_RAND_ADDR, BLE_MNG, HL_MNG, PK_GEN_GEN, 7, "B6B", "B" ), + CMD(LE_SET_EXT_SCAN_RSP_DATA, BLE_MNG, HL_MNG, PK_GEN_GEN, 255, "BBBnB", "B" ), + CMD(LE_RD_MAX_ADV_DATA_LEN, BLE_MNG, HL_MNG, PK_GEN_GEN, 0, NULL, "BH" ), + CMD(LE_RD_NB_SUPP_ADV_SETS, BLE_MNG, HL_MNG, PK_GEN_GEN, 0, NULL, "BB" ), + CMD(LE_RMV_ADV_SET, BLE_MNG, HL_MNG, PK_GEN_GEN, 1, "B", "B" ), + CMD(LE_CLEAR_ADV_SETS, BLE_MNG, HL_MNG, PK_GEN_GEN, 0, NULL, "B" ), + CMD(LE_SET_PER_ADV_PARAM, BLE_MNG, HL_MNG, PK_GEN_GEN, 7, "BHHH", "B" ), + CMD(LE_SET_PER_ADV_DATA, BLE_MNG, HL_MNG, PK_GEN_GEN, 255, "BBnB", "B" ), + CMD(LE_SET_PER_ADV_EN, BLE_MNG, HL_MNG, PK_GEN_GEN, 2, "BB", "B" ), + CMD(LE_SET_EXT_SCAN_PARAM, BLE_MNG, HL_MNG, PK_SPE_GEN, 13, &hci_le_set_ext_scan_param_cmd_upk, "B" ), + CMD(LE_SET_EXT_SCAN_EN, BLE_MNG, HL_MNG, PK_GEN_GEN, 6, "BBHH", "B" ), + CMD(LE_EXT_CREATE_CON, BLE_MNG, HL_MNG, PK_SPE_GEN, 58, &hci_le_ext_create_con_cmd_upk, NULL ), + CMD(LE_PER_ADV_CREATE_SYNC, BLE_MNG, HL_MNG, PK_GEN_GEN, 14, "BBB6BHHB", NULL ), + CMD(LE_PER_ADV_CREATE_SYNC_CANCEL, BLE_MNG, HL_MNG, PK_GEN_GEN, 0, NULL, "B" ), + CMD(LE_PER_ADV_TERM_SYNC, BLE_MNG, HL_MNG, PK_GEN_GEN, 2, "H", "B" ), + CMD(LE_ADD_DEV_TO_PER_ADV_LIST, BLE_MNG, HL_MNG, PK_GEN_GEN, 8, "B6BB", "B" ), + CMD(LE_RMV_DEV_FROM_PER_ADV_LIST, BLE_MNG, HL_MNG, PK_GEN_GEN, 8, "B6BB", "B" ), + CMD(LE_CLEAR_PER_ADV_LIST, BLE_MNG, HL_MNG, PK_GEN_GEN, 0, NULL, "B" ), + CMD(LE_RD_PER_ADV_LIST_SIZE, BLE_MNG, HL_MNG, PK_GEN_GEN, 0, NULL, "BB" ), + CMD(LE_RD_TX_PWR, BLE_MNG, HL_MNG, PK_GEN_GEN, 0, NULL, "BBB" ), + CMD(LE_RD_RF_PATH_COMP, BLE_MNG, HL_MNG, PK_GEN_GEN, 0, NULL, "BHH" ), + CMD(LE_WR_RF_PATH_COMP, BLE_MNG, HL_MNG, PK_GEN_GEN, 4, "HH", "B" ), + CMD(LE_SET_PRIV_MODE, BLE_MNG, HL_MNG, PK_GEN_GEN, 8, "B6BB", "B" ), + CMD(LE_RX_TEST_V3, BLE_MNG, HL_MNG, PK_GEN_GEN, 82, "BBBBBBnB", "B" ), + CMD(LE_TX_TEST_V3, BLE_MNG, HL_MNG, PK_GEN_GEN, 82, "BBBBBBnB", "B" ), + #if BLE_CONLESS_CTE_TX + CMD(LE_SET_CONLESS_CTE_TX_PARAM, BLE_MNG, HL_MNG, PK_GEN_GEN, 80, "BBBBnB", "B" ), + CMD(LE_SET_CONLESS_CTE_TX_EN, BLE_MNG, HL_MNG, PK_GEN_GEN, 2, "BB", "B" ), + #endif // BLE_CONLESS_CTE_TX + #if BLE_CONLESS_CTE_RX + CMD(LE_SET_CONLESS_IQ_SAMPL_EN, BLE_MNG, HL_MNG, PK_GEN_GEN, 81, "HBBBnB", "BH" ), + #endif // BLE_CONLESS_CTE_RX + #if BLE_CON_CTE_REQ + CMD(LE_SET_CON_CTE_RX_PARAM, BLE_CTRL, HL_CTRL, PK_GEN_GEN, 80, "HBBnB", "BH" ), + CMD(LE_CON_CTE_REQ_EN, BLE_CTRL, HL_CTRL, PK_GEN_GEN, 7, "HBHBB", "BH" ), + #endif // BLE_CON_CTE_REQ + #if BLE_CON_CTE_RSP + CMD(LE_SET_CON_CTE_TX_PARAM, BLE_CTRL, HL_CTRL, PK_GEN_GEN, 79, "HBnB", "BH" ), + CMD(LE_CON_CTE_RSP_EN, BLE_CTRL, HL_CTRL, PK_GEN_GEN, 3, "HB", "BH" ), + #endif // BLE_CON_CTE_RSP + #if (BLE_AOD | BLE_AOA) + CMD(LE_RD_ANTENNA_INF, BLE_MNG, HL_MNG, PK_GEN_GEN, 0, NULL, "BBBBB" ), + #endif // (BLE_AOD | BLE_AOA) + CMD(LE_SET_PER_ADV_REC_EN, BLE_MNG, HL_MNG, PK_GEN_GEN, 3, "HB", "B" ), + CMD(LE_PER_ADV_SYNC_TRANSF, BLE_CTRL, HL_CTRL, PK_GEN_GEN, 6, "HHH", "BH" ), + CMD(LE_PER_ADV_SET_INFO_TRANSF, BLE_CTRL, HL_CTRL, PK_GEN_GEN, 5, "HHB", "BH" ), + CMD(LE_SET_PER_ADV_SYNC_TRANSF_PARAM, BLE_CTRL, HL_MNG, PK_GEN_GEN, 8, "HBHHB", "BH" ), + CMD(LE_SET_DFT_PER_ADV_SYNC_TRANSF_PARAM, BLE_MNG, HL_MNG, PK_GEN_GEN, 6, "BHHB", "B" ), + CMD(LE_GEN_DHKEY_V2, BLE_MNG, HL_MNG, PK_GEN_GEN, 65, "64BB", NULL ), + CMD(LE_MOD_SLEEP_CLK_ACC, BLE_MNG, HL_MNG, PK_GEN_GEN, 1, "B", "B" ), +}; +#endif //(BLE_EMB_PRESENT || BLE_HOST_PRESENT) + +#if (BLE_EMB_PRESENT || BT_EMB_PRESENT) +///// HCI command descriptors (OGF Vendor Specific) +const struct hci_cmd_desc_tag hci_cmd_desc_tab_vs[] = +{ + #if (RW_DEBUG && (!BLE_HOST_PRESENT || HCI_TL_SUPPORT)) + CMD(DBG_RD_MEM, DBG, 0, PK_GEN_GEN, 6, "LBB", "BnB" ), + CMD(DBG_WR_MEM, DBG, 0, PK_GEN_GEN, 136, "LBnB", "B" ), + CMD(DBG_DEL_PAR, DBG, 0, PK_GEN_GEN, 2, "H", "B" ), + CMD(DBG_ID_FLASH, DBG, 0, PK_GEN_GEN, 0, NULL, "BB" ), + CMD(DBG_ER_FLASH, DBG, 0, PK_GEN_GEN, 9, "BLL", "B" ), + CMD(DBG_WR_FLASH, DBG, 0, PK_GEN_GEN, 140, "BLnB", "B" ), + CMD(DBG_RD_FLASH, DBG, 0, PK_GEN_GEN, 6, "BLB", "BnB" ), + CMD(DBG_RD_PAR, DBG, 0, PK_GEN_GEN, 2, "H", "BnB" ), + CMD(DBG_WR_PAR, DBG, 0, PK_GEN_GEN, 132, "HnB", "B" ), + #endif //(RW_DEBUG && (!BLE_HOST_PRESENT || HCI_TL_SUPPORT)) + #if (RW_DEBUG) + CMD(DBG_RD_KERNEL_STATS, DBG, 0, PK_GEN_GEN, 0, NULL, "BBBBHH"), + #if (RW_WLAN_COEX) + CMD(DBG_WLAN_COEX, DBG, 0, PK_GEN_GEN, 1, "B", "B" ), + #if (RW_WLAN_COEX_TEST) + CMD(DBG_WLAN_COEXTST_SCEN, DBG, 0, PK_GEN_GEN, 4, "L", "B" ), + #endif //RW_BT_WLAN_COEX_TEST + #endif //RW_WLAN_COEX + #if (RW_MWS_COEX) + CMD(DBG_MWS_COEX, DBG, 0, PK_GEN_GEN, 1, "B", "B" ), + #if (RW_MWS_COEX_TEST) + CMD(DBG_MWS_COEXTST_SCEN, DBG, 0, PK_GEN_GEN, 4, "L", "B" ), + #endif //RW_BT_MWS_COEX_TEST + #endif //RW_MWS_COEX + #endif //(RW_DEBUG) + CMD(DBG_PLF_RESET, DBG, 0, PK_GEN_GEN, 1, "B", "B" ), + CMD(DBG_RD_MEM_INFO, DBG, 0, PK_GEN_GEN, 0, NULL, "BHHHL" ), + #if (BT_READ_PICONET_CLOCK) + CMD(VS_RD_PICONET_CLOCK, BT_MNG, 0, PK_GEN_GEN, 4, "HBB", "BHLHLH" ), + #endif // (BT_READ_PICONET_CLOCK) + #if BLE_EMB_PRESENT + #if (BLE_PERIPHERAL) + CMD(VS_SET_PREF_SLAVE_LATENCY, BLE_CTRL,HL_CTRL, PK_GEN_GEN, 4, "HH", "BH" ), + CMD(VS_SET_PREF_SLAVE_EVT_DUR, BLE_CTRL,HL_CTRL, PK_GEN_GEN, 5, "HHB", "BH" ), + #endif // (BLE_PERIPHERAL) + #if (RW_DEBUG) + CMD(DBG_BLE_REG_RD, BLE_MNG, 0, PK_GEN_GEN, 2, "H", "BHL" ), + CMD(DBG_BLE_REG_WR, BLE_MNG, 0, PK_GEN_GEN, 6, "HL", "BH" ), + CMD(DBG_LLCP_DISCARD, BLE_CTRL,0, PK_GEN_GEN, 3, "HB", "B" ), + CMD(DBG_RF_REG_RD, DBG, 0, PK_GEN_GEN, 2, "H", "BHL" ), + CMD(DBG_RF_REG_WR, DBG, 0, PK_GEN_GEN, 6, "HL", "BH" ), + #endif //(RW_DEBUG) + #if (BLE_ISO_MODE_0) + CMD(VS_SETUP_AM0_CHAN, BLE_ISO, HL_ISO0, PK_GEN_GEN, 16, "HHLLBBBB", "BHH" ), + CMD(VS_REMOVE_AM0_CHAN, BLE_ISO, HL_ISO0, PK_GEN_GEN, 4, "HH", "BH" ), + CMD(VS_CONTROL_AM0_CHAN, BLE_ISO, HL_ISO0, PK_GEN_GEN, 6, "HHBB", "BH" ), + #endif //(BLE_ISO_MODE_0) + #endif //BLE_EMB_PRESENT + #if (BT_EMB_PRESENT && RW_DEBUG) + CMD(DBG_BT_SEND_LMP, BT_CTRL_CONHDL, 0, PK_GEN_GEN, 131, "HnB", "BH" ), + CMD(DBG_BT_DISCARD_LMP_EN, BT_CTRL_CONHDL, 0, PK_GEN_GEN, 3, "HB", "BH" ), + CMD(DBG_SET_LOCAL_CLOCK , DBG , 0, PK_GEN_GEN, 4 , "L", "B" ), + #endif //BT_EMB_PRESENT && RW_DEBUG + #if CRYPTO_UT + CMD(DBG_TEST_CRYPTO_FUNC, BT_MNG, 0, PK_GEN_GEN, 136, "BnB", "B" ), + #endif //CRYPTO_UT + #if (RW_DEBUG && SCH_PLAN_UT) + CMD(DBG_TEST_SCH_PLAN_SET, DBG, 0, PK_GEN_GEN, 21, "LLLLLB", "BL" ), + CMD(DBG_TEST_SCH_PLAN_REM, DBG, 0, PK_GEN_GEN, 4 , "L" , "B" ), + CMD(DBG_TEST_SCH_PLAN_CHK, DBG, 0, PK_GEN_GEN, 16, "LLLL" , "B" ), + CMD(DBG_TEST_SCH_PLAN_REQ, DBG, 0, PK_GEN_GEN, 21, "LLLLLB", "BLLL" ), + #endif // (RW_DEBUG && SCH_PLAN_UT) + #if BLE_IQ_GEN + CMD(DBG_IQGEN_CFG, DBG, 0, PK_SPE_GEN, 18, &hci_dbg_iqgen_cfg_cmd_upk, "B" ), + #endif //BLE_IQ_GEN +}; +#endif //(BLE_EMB_PRESENT || BT_EMB_PRESENT) + +/// HCI command descriptors root table (classified by OGF) +const struct hci_cmd_desc_tab_ref hci_cmd_desc_root_tab[] = +{ + {LK_CNTL_OGF, ARRAY_LEN(hci_cmd_desc_tab_lk_ctrl), hci_cmd_desc_tab_lk_ctrl }, + {CNTLR_BB_OGF, ARRAY_LEN(hci_cmd_desc_tab_ctrl_bb), hci_cmd_desc_tab_ctrl_bb }, + {INFO_PAR_OGF, ARRAY_LEN(hci_cmd_desc_tab_info_par), hci_cmd_desc_tab_info_par}, + {STAT_PAR_OGF, ARRAY_LEN(hci_cmd_desc_tab_stat_par), hci_cmd_desc_tab_stat_par}, + #if BT_EMB_PRESENT + {LK_POL_OGF, ARRAY_LEN(hci_cmd_desc_tab_lk_pol), hci_cmd_desc_tab_lk_pol }, + {TEST_OGF, ARRAY_LEN(hci_cmd_desc_tab_testing), hci_cmd_desc_tab_testing }, + #endif // BT_EMB_PRESENT + #if (BLE_EMB_PRESENT || BLE_HOST_PRESENT) + {LE_CNTLR_OGF, ARRAY_LEN(hci_cmd_desc_tab_le), hci_cmd_desc_tab_le }, + #endif //(BLE_EMB_PRESENT || BLE_HOST_PRESENT) + #if (BLE_EMB_PRESENT || BT_EMB_PRESENT) + {VS_OGF, ARRAY_LEN(hci_cmd_desc_tab_vs), hci_cmd_desc_tab_vs }, + #endif //(BLE_EMB_PRESENT || BT_EMB_PRESENT) +}; + +/// HCI event descriptors +const struct hci_evt_desc_tag hci_evt_desc_tab[] = +{ + EVT(DISC_CMP, HL_CTRL, PK_GEN, "BHB" ), + EVT(ENC_CHG, HL_CTRL, PK_GEN, "BHB" ), + EVT(RD_REM_VER_INFO_CMP, HL_CTRL, PK_GEN, "BHBHH" ), + EVT(HW_ERR, HL_MNG, PK_GEN, "B" ), + EVT(FLUSH_OCCURRED, HL_CTRL, PK_GEN, "H" ), + EVT(NB_CMP_PKTS, HL_DATA, PK_GEN, "BHH" ), + EVT(DATA_BUF_OVFLW, HL_MNG, PK_GEN, "B" ), + EVT(ENC_KEY_REFRESH_CMP, HL_CTRL, PK_GEN, "BH" ), + EVT(AUTH_PAYL_TO_EXP, HL_CTRL, PK_GEN, "H" ), + #if BT_EMB_PRESENT + EVT(INQ_CMP, 0, PK_GEN, "B" ), + EVT(INQ_RES, 0, PK_GEN, "B6BBBB3BH" ), + EVT(CON_CMP, 0, PK_GEN, "BH6BBB" ), + EVT(CON_REQ, 0, PK_GEN, "6B3BB" ), + EVT(AUTH_CMP, 0, PK_GEN, "BH" ), + EVT(REM_NAME_REQ_CMP, 0, PK_GEN, "B6B248B" ), + EVT(CHG_CON_LK_CMP, 0, PK_GEN, "BH" ), + EVT(MASTER_LK_CMP, 0, PK_GEN, "BHB" ), + EVT(RD_REM_SUPP_FEATS_CMP, 0, PK_GEN, "BH8B" ), + EVT(QOS_SETUP_CMP, 0, PK_GEN, "BHBBLLLL" ), + EVT(ROLE_CHG, 0, PK_GEN, "B6BB" ), + EVT(MODE_CHG, 0, PK_GEN, "BHBH" ), + EVT(RETURN_LINK_KEYS, 0, PK_GEN, "B6B16B" ), + EVT(PIN_CODE_REQ, 0, PK_GEN, "6B" ), + EVT(LK_REQ, 0, PK_GEN, "6B" ), + EVT(LK_NOTIF, 0, PK_GEN, "6B16BB" ), + EVT(MAX_SLOT_CHG, 0, PK_GEN, "HB" ), + EVT(RD_CLK_OFF_CMP, 0, PK_GEN, "BHH" ), + EVT(CON_PKT_TYPE_CHG, 0, PK_GEN, "BHH" ), + EVT(QOS_VIOL, 0, PK_GEN, "H" ), + EVT(PAGE_SCAN_REPET_MODE_CHG, 0, PK_GEN, "6BB" ), + EVT(FLOW_SPEC_CMP, 0, PK_GEN, "BHBBBLLLL" ), + EVT(INQ_RES_WITH_RSSI, 0, PK_GEN, "B6BBB3BHB" ), + EVT(RD_REM_EXT_FEATS_CMP, 0, PK_GEN, "BHBB8B" ), + EVT(SYNC_CON_CMP, 0, PK_GEN, "BH6BBBBHHB" ), + EVT(SYNC_CON_CHG, 0, PK_GEN, "BHBBHH" ), + EVT(SNIFF_SUB, 0, PK_GEN, "BHHHHH" ), + EVT(EXT_INQ_RES, 0, PK_GEN, "B6BBB3BHB240B"), + EVT(IO_CAP_REQ, 0, PK_GEN, "6B" ), + EVT(IO_CAP_RSP, 0, PK_GEN, "6BBBB" ), + EVT(USER_CFM_REQ, 0, PK_GEN, "6BL" ), + EVT(USER_PASSKEY_REQ, 0, PK_GEN, "6B" ), + EVT(REM_OOB_DATA_REQ, 0, PK_GEN, "6B" ), + EVT(SP_CMP, 0, PK_GEN, "B6B" ), + EVT(LINK_SUPV_TO_CHG, 0, PK_GEN, "HH" ), + EVT(ENH_FLUSH_CMP, 0, PK_GEN, "H" ), + EVT(USER_PASSKEY_NOTIF, 0, PK_GEN, "6BL" ), + EVT(KEYPRESS_NOTIF, 0, PK_GEN, "6BB" ), + EVT(REM_HOST_SUPP_FEATS_NOTIF, 0, PK_GEN, "6B8B" ), + #if CSB_SUPPORT + EVT(SYNC_TRAIN_CMP, 0, PK_GEN, "B" ), + EVT(SYNC_TRAIN_REC, 0, PK_GEN, "B6BL10BBLHB" ), + EVT(CON_SLV_BCST_REC, 0, PK_GEN, "6BBLLBBnB" ), + EVT(CON_SLV_BCST_TO, 0, PK_GEN, "6BB" ), + EVT(TRUNC_PAGE_CMP, 0, PK_GEN, "B6B" ), + EVT(SLV_PAGE_RSP_TO, 0, PK_GEN, NULL ), + EVT(CON_SLV_BCST_CH_MAP_CHG, 0, PK_GEN, "10B" ), + #endif //CSB_SUPPORT + EVT(SAM_STATUS_CHANGE, 0, PK_GEN, "HBBBBBB" ), + #endif// BT_EMB_PRESENT +}; + + +// Note: remove specific BLE Flag as soon as new debug event available on BT + +#if (BLE_EMB_PRESENT || BT_EMB_PRESENT) +#if (RW_DEBUG || BLE_ISOGEN) +/// HCI DBG event descriptors +const struct hci_evt_desc_tag hci_evt_dbg_desc_tab[] = +{ + #if (RW_DEBUG) + DBG_EVT(DBG_ASSERT, 0, PK_SPE, &hci_dbg_assert_evt_pkupk ), + #endif //(RW_DEBUG) + + #if (BLE_ISOGEN) + DBG_EVT(VS_ISOGEN_STAT, HL_MNG, PK_GEN, "BHLLLLLLLLLL" ), + #endif //(BLE_ISOGEN) +}; +#endif // (RW_DEBUG || BLE_ISOGEN) +#endif // (BLE_EMB_PRESENT || BT_EMB_PRESENT) + + +#if (BLE_EMB_PRESENT || BLE_HOST_PRESENT) +/// HCI LE event descriptors +const struct hci_evt_desc_tag hci_evt_le_desc_tab[] = +{ + LE_EVT(LE_CON_CMP, HL_MNG, PK_GEN, "BBHBB6BHHHB" ), + LE_EVT(LE_ADV_REPORT, HL_MNG, PK_SPE, &hci_le_adv_report_evt_pkupk ), + LE_EVT(LE_CON_UPDATE_CMP, HL_CTRL, PK_GEN, "BBHHHH" ), + LE_EVT(LE_RD_REM_FEATS_CMP, HL_CTRL, PK_GEN, "BBH8B" ), + LE_EVT(LE_LTK_REQUEST, HL_CTRL, PK_GEN, "BH8BH" ), + LE_EVT(LE_REM_CON_PARAM_REQ, HL_CTRL, PK_GEN, "BHHHHH" ), + LE_EVT(LE_DATA_LEN_CHG, HL_CTRL, PK_GEN, "BHHHHH" ), + LE_EVT(LE_ENH_CON_CMP, HL_MNG, PK_GEN, "BBHBB6B6B6BHHHB" ), + LE_EVT(LE_RD_LOC_P256_PUB_KEY_CMP, HL_MNG, PK_GEN, "BB64B" ), + LE_EVT(LE_GEN_DHKEY_CMP, HL_MNG, PK_GEN, "BB32B" ), + LE_EVT(LE_DIR_ADV_REP, HL_MNG, PK_SPE, &hci_le_dir_adv_report_evt_pkupk ), + LE_EVT(LE_PHY_UPD_CMP, HL_CTRL, PK_GEN, "BBHBB" ), + LE_EVT(LE_EXT_ADV_REPORT, HL_MNG, PK_SPE, &hci_le_ext_adv_report_evt_pkupk ), + LE_EVT(LE_PER_ADV_SYNC_EST, HL_MNG, PK_GEN, "BBHBB6BBHB" ), + LE_EVT(LE_PER_ADV_REPORT, HL_MNG, PK_GEN, "BHBBBBnB" ), + LE_EVT(LE_PER_ADV_SYNC_LOST, HL_MNG, PK_GEN, "BH" ), + LE_EVT(LE_SCAN_TIMEOUT, HL_MNG, PK_GEN, "B" ), + LE_EVT(LE_ADV_SET_TERMINATED, HL_MNG, PK_GEN, "BBBHB" ), + LE_EVT(LE_SCAN_REQ_RCVD, HL_MNG, PK_GEN, "BBB6B" ), + LE_EVT(LE_CH_SEL_ALGO, HL_CTRL, PK_GEN, "BHB" ), + LE_EVT(LE_CONLESS_IQ_REPORT, HL_MNG, PK_SPE, &hci_le_conless_iq_report_evt_pkupk ), + LE_EVT(LE_CON_IQ_REPORT, HL_CTRL, PK_SPE, &hci_le_con_iq_report_evt_pkupk ), + LE_EVT(LE_CTE_REQ_FAILED, HL_CTRL, PK_GEN, "BBH" ), + LE_EVT(LE_PER_ADV_SYNC_TRANSF_REC, HL_MNG, PK_GEN, "BBHHHBB6BBHB" ), +}; +#endif //(BLE_EMB_PRESENT || BLE_HOST_PRESENT) + + +/* + * SPECIAL PACKER-UNPACKER DEFINITIONS + **************************************************************************************** + */ + +#if (HCI_TL_SUPPORT) +#if (BLE_EMB_PRESENT || BT_EMB_PRESENT) +/** +**************************************************************************************** +* @brief Apply a basic pack operation +* +* @param[inout] pp_in Current input buffer position +* @param[inout] pp_out Current output buffer position +* @param[in] p_in_end Input buffer end +* @param[in] p_out_end Output buffer end +* @param[in] len Number of bytes to copy +* +* @return status +***************************************************************************************** +*/ +static uint8_t hci_pack_bytes(uint8_t** pp_in, uint8_t** pp_out, uint8_t* p_in_end, uint8_t* p_out_end, uint8_t len) +{ + uint8_t status = HCI_PACK_OK; + + // Check if enough space in input buffer to read + if((*pp_in + len) > p_in_end) + { + status = HCI_PACK_IN_BUF_OVFLW; + } + else + { + if(p_out_end != NULL) + { + // Check if enough space in out buffer to write + if((*pp_out + len) > p_out_end) + { + status = HCI_PACK_OUT_BUF_OVFLW; + } + + // Copy BD Address + memcpy(*pp_out, *pp_in, len); + } + *pp_in = *pp_in + len; + *pp_out = *pp_out + len; + } + + return (status); +} +#endif //(BLE_EMB_PRESENT || BT_EMB_PRESENT) + +/// Special packing/unpacking function for HCI Host Number Of Completed Packets Command +static uint8_t hci_host_nb_cmp_pkts_cmd_pkupk(uint8_t *out, uint8_t *in, uint16_t* out_len, uint16_t in_len) +{ + #if (BLE_EMB_PRESENT || BT_EMB_PRESENT) + + /* + * PACKING FUNCTION + */ + struct hci_host_nb_cmp_pkts_cmd* cmd = (struct hci_host_nb_cmp_pkts_cmd*) out; + uint8_t* p_in = in; + uint8_t* p_out = out; + uint8_t* p_in_end = in + in_len; + uint8_t* p_out_end = out + *out_len; + uint8_t status = HCI_PACK_OK; + + // Check if there is input data to parse + if(in != NULL) + { + do + { + uint8_t i = 0; + // Number of handles + p_out = &cmd->nb_of_hdl; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + while((i < *in) && ((p_out - out) <= sizeof(struct hci_host_nb_cmp_pkts_cmd))) + { + // Connection handle + p_out = (uint8_t*) &cmd->con_hdl[i]; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 2); + if(status != HCI_PACK_OK) + break; + + // Host_Num_Of_Completed_Packets + p_out = (uint8_t*) &cmd->nb_comp_pkt[i]; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 2); + if(status != HCI_PACK_OK) + break; + + i++; + } + } while(0); + + *out_len = (uint16_t)(p_out - out); + } + else + { + // If no input data, size max is returned + *out_len = sizeof(struct hci_host_nb_cmp_pkts_cmd); + } + + return (status); + + #elif BLE_HOST_PRESENT + + /* + * UNPACKING FUNCTION + */ + return sizeof(struct hci_host_nb_cmp_pkts_cmd); + + #endif //(BLE_EMB_PRESENT || BT_EMB_PRESENT) +} + +#if (BT_EMB_PRESENT) +/// Special packing/unpacking function for HCI Set Event Filter command +static uint8_t hci_set_evt_filter_cmd_upk(uint8_t *out, uint8_t *in, uint16_t* out_len, uint16_t in_len) +{ + struct hci_set_evt_filter_cmd temp_out; + struct hci_set_evt_filter_cmd* cmd = (struct hci_set_evt_filter_cmd*) out; + uint8_t* p_in = in; + uint8_t* p_out; + uint8_t* p_in_end = in + in_len; + uint8_t* p_out_start; + uint8_t* p_out_end; + uint8_t status = HCI_PACK_OK; + + // Check if there is input data to parse + if(in != NULL) + { + // Check if there is output buffer to write to, else use temp_out buffer + if (out != NULL) + { + cmd = (struct hci_set_evt_filter_cmd*)(out); + p_out_start = out; + p_out_end = out + *out_len; + } + else + { + cmd = (struct hci_set_evt_filter_cmd*)(&temp_out); + p_out_start = (uint8_t*)&temp_out; + p_out_end = p_out_start + sizeof(temp_out); + } + + do + { + // Filter Type + p_out = &cmd->filter_type; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Check filter type + switch(cmd->filter_type) + { + case INQUIRY_FILTER_TYPE: + { + // Filter Condition Type + p_out = &cmd->filter.inq_res.cond_type; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Check Filter Condition Type + switch(cmd->filter.inq_res.cond_type) + { + case CLASS_FILTER_CONDITION_TYPE: + { + // Class_of_Device + p_out = &cmd->filter.inq_res.cond.cond_1.class_of_dev.A[0]; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, DEV_CLASS_LEN); + if(status != HCI_PACK_OK) + break; + + // Class_of_Device_Mask + p_out = &cmd->filter.inq_res.cond.cond_1.class_of_dev_msk.A[0]; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, DEV_CLASS_LEN); + if(status != HCI_PACK_OK) + break; + } + break; + case BD_ADDR_FILTER_CONDITION_TYPE: + { + // BD Address + p_out = &cmd->filter.inq_res.cond.cond_2.bd_addr.addr[0]; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, BD_ADDR_LEN); + if(status != HCI_PACK_OK) + break; + } + break; + default: + { + // Nothing + } + break; + } + } + break; + case CONNECTION_FILTER_TYPE: + { + // Filter Condition Type + p_out = &cmd->filter.con_set.cond_type; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Check Filter Condition Type + switch(cmd->filter.inq_res.cond_type) + { + case ALL_FILTER_CONDITION_TYPE: + { + // Auto_Accept_Flag + p_out = &cmd->filter.con_set.cond.cond_0.auto_accept; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + } + break; + case CLASS_FILTER_CONDITION_TYPE: + { + // Class_of_Device + p_out = &cmd->filter.con_set.cond.cond_1.class_of_dev.A[0]; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, DEV_CLASS_LEN); + if(status != HCI_PACK_OK) + break; + + // Class_of_Device_Mask + p_out = &cmd->filter.con_set.cond.cond_1.class_of_dev_msk.A[0]; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, DEV_CLASS_LEN); + if(status != HCI_PACK_OK) + break; + + // Auto_Accept_Flag + p_out = &cmd->filter.con_set.cond.cond_1.auto_accept; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + } + break; + case BD_ADDR_FILTER_CONDITION_TYPE: + { + // BD Address + p_out = &cmd->filter.con_set.cond.cond_2.bd_addr.addr[0]; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, BD_ADDR_LEN); + if(status != HCI_PACK_OK) + break; + + // Auto_Accept_Flag + p_out = &cmd->filter.con_set.cond.cond_2.auto_accept; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + } + break; + default: + { + // Nothing + } + break; + } + } + break; + default: + { + // Nothing + } + break; + } + + } while(0); + + *out_len = (uint16_t)(p_out - p_out_start); + } + else + { + // If no input data, size max is returned + *out_len = sizeof(struct hci_set_evt_filter_cmd); + } + + return (status); +} +/// Special packing/unpacking function for HCI Write Stored Link Key command +static uint8_t hci_wr_stored_lk_cmd_upk(uint8_t *out, uint8_t *in, uint16_t* out_len, uint16_t in_len) +{ + struct hci_wr_stored_lk_cmd* cmd = (struct hci_wr_stored_lk_cmd*) out; + uint8_t* p_in = in; + uint8_t* p_out = out; + uint8_t* p_in_end = in + in_len; + uint8_t* p_out_end = out + *out_len; + uint8_t status = HCI_PACK_OK; + + // Check if there is input data to parse + if(in != NULL) + { + do + { + // Number of keys + p_out = &cmd->num_key_wr; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Parse BD Address + Key table + for(uint8_t i = 0 ; i < *in ; i++) + { + // BD Address + p_out = &cmd->link_keys[i].bd_addr.addr[0]; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, BD_ADDR_LEN); + if(status != HCI_PACK_OK) + break; + + // Link Key + p_out = &cmd->link_keys[i].link_key.ltk[0]; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, KEY_LEN); + if(status != HCI_PACK_OK) + break; + } + + } while(0); + + *out_len = (uint16_t)(p_out - out); + } + else + { + // If no input data, size max is returned + *out_len = sizeof(struct hci_wr_stored_lk_cmd); + } + + return (status); +} + +/// Special packing/unpacking function for HCI Write Stored Link Key command +static uint8_t hci_wr_curr_iac_lap_cmd_upk(uint8_t *out, uint8_t *in, uint16_t* out_len, uint16_t in_len) +{ + struct hci_wr_curr_iac_lap_cmd* cmd = (struct hci_wr_curr_iac_lap_cmd*) out; + uint8_t* p_in = in; + uint8_t* p_out = out; + uint8_t* p_in_end = in + in_len; + uint8_t* p_out_end = out + *out_len; + uint8_t status = HCI_PACK_OK; + + // Check if there is input data to parse + if(in != NULL) + { + do + { + // Number of IACs + p_out = &cmd->nb_curr_iac; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Parse IAC LAP table + for(uint8_t i = 0 ; i < *in ; i++) + { + // LAP + p_out = &cmd->iac_lap[i].A[0]; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, BD_ADDR_LAP_LEN); + if(status != HCI_PACK_OK) + break; + } + + } while(0); + + *out_len = (uint16_t)(p_out - out); + } + else + { + // If no input data, size max is returned + *out_len = sizeof(struct hci_wr_curr_iac_lap_cmd); + } + + return (status); +} + +#if RW_MWS_COEX +/// Special packing/unpacking function for HCI Set External Frame Configuration command +static uint8_t hci_set_external_frame_config_cmd_upk(uint8_t *out, uint8_t *in, uint16_t* out_len, uint16_t in_len) +{ + struct hci_set_external_frame_config_cmd temp_out; + struct hci_set_external_frame_config_cmd* cmd; + uint8_t* p_in = in; + uint8_t* p_out; + uint8_t* p_in_end = in + in_len; + uint8_t* p_out_start; + uint8_t* p_out_end; + bool copy_data; + uint8_t status = HCI_PACK_OK; + + // Check if there is input data to parse + if(in != NULL) + { + // Check if there is output buffer to write to, else use temp_out buffer + if (out != NULL) + { + cmd = (struct hci_set_external_frame_config_cmd*)(out); + p_out_start = out; + p_out_end = out + *out_len; + copy_data = true; + } + else + { + cmd = (struct hci_set_external_frame_config_cmd*)(&temp_out); + p_out_start = (uint8_t*)&temp_out; + p_out_end = p_out_start + sizeof(temp_out); + copy_data = false; + } + + do + { + // Ext_Frame_Duration + p_out = (uint8_t*)&cmd->ext_fr_duration; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 2); + if(status != HCI_PACK_OK) + break; + + // Ext_Frame_Sync_Assert_Offset + p_out = (uint8_t*)&cmd->ext_fr_sync_assert_offset; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 2); + if(status != HCI_PACK_OK) + break; + + // Ext_Frame_Sync_Assert_Jitter + p_out = (uint8_t*)&cmd->ext_fr_sync_assert_jitter; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 2); + if(status != HCI_PACK_OK) + break; + + // Ext_Frame_Num_Periods + p_out = (uint8_t*)&cmd->ext_fr_num_periods; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + for (uint8_t i = 0; i < cmd->ext_fr_num_periods; i++) + { + // Period Duration + p_out = (uint8_t*)&cmd->period[i].duration; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, copy_data?p_out_end:NULL, 2); + if(status != HCI_PACK_OK) + break; + + // Period Type + p_out = (uint8_t*)&cmd->period[i].type; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, copy_data?p_out_end:NULL, 1); + if(status != HCI_PACK_OK) + break; + } + + } while(0); + + *out_len = (uint16_t)(p_out - p_out_start); + } + else + { + // If no input data, size max is returned + *out_len = HCI_MAX_CMD_PARAM_SIZE; + } + + return (status); +} + +/// Special packing/unpacking function for HCI Set MWS Scan Frequency Table command +static uint8_t hci_set_mws_scan_freq_table_upk(uint8_t *out, uint8_t *in, uint16_t* out_len, uint16_t in_len) +{ + struct hci_set_mws_scan_freq_table_cmd temp_out; + struct hci_set_mws_scan_freq_table_cmd* cmd; + uint8_t* p_in = in; + uint8_t* p_out; + uint8_t* p_in_end = in + in_len; + uint8_t* p_out_start; + uint8_t* p_out_end; + bool copy_data; + uint8_t status = HCI_PACK_OK; + + // Check if there is input data to parse + if(in != NULL) + { + // Check if there is output buffer to write to, else use temp_out buffer + if (out != NULL) + { + cmd = (struct hci_set_mws_scan_freq_table_cmd*)(out); + p_out_start = out; + p_out_end = out + *out_len; + copy_data = true; + } + else + { + cmd = (struct hci_set_mws_scan_freq_table_cmd*)(&temp_out); + p_out_start = (uint8_t*)&temp_out; + p_out_end = p_out_start + sizeof(temp_out); + copy_data = false; + } + + do + { + // Num_Scan_Frequencies + p_out = (uint8_t*)&cmd->num_scan_frequencies; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + for (uint8_t i = 0; i < cmd->num_scan_frequencies; i++) + { + // Scan_Frequency_Low + p_out = (uint8_t*)&cmd->scan_freq[i].low; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, copy_data?p_out_end:NULL, 2); + if (status != HCI_PACK_OK) + break; + + // Scan_Frequency_High + p_out = (uint8_t*)&cmd->scan_freq[i].high; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, copy_data?p_out_end:NULL, 2); + if (status != HCI_PACK_OK) + break; + } + + } while(0); + + *out_len = (uint16_t)(p_out - p_out_start); + } + else + { + // If no input data, size max is returned + *out_len = HCI_MAX_CMD_PARAM_SIZE; + } + + return (status); +} + +/// Special packing/unpacking function for HCI Set MWS Pattern Configuration command +static uint8_t hci_set_mws_pattern_config_upk(uint8_t *out, uint8_t *in, uint16_t* out_len, uint16_t in_len) +{ + struct hci_set_mws_pattern_config_cmd temp_out; + struct hci_set_mws_pattern_config_cmd* cmd; + uint8_t* p_in = in; + uint8_t* p_out; + uint8_t* p_in_end = in + in_len; + uint8_t* p_out_start; + uint8_t* p_out_end; + bool copy_data; + uint8_t status = HCI_PACK_OK; + + // Check if there is input data to parse + if(in != NULL) + { + // Check if there is output buffer to write to, else use temp_out buffer + if (out != NULL) + { + cmd = (struct hci_set_mws_pattern_config_cmd*)(out); + p_out_start = out; + p_out_end = out + *out_len; + copy_data = true; + } + else + { + cmd = (struct hci_set_mws_pattern_config_cmd*)(&temp_out); + p_out_start = (uint8_t*)&temp_out; + p_out_end = p_out_start + sizeof(temp_out); + copy_data = false; + } + + do + { + //MWS_PATTERN_Index + p_out = (uint8_t*)&cmd->mws_pattern_index; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + //MWS_PATTERN_NumIntervals + p_out = (uint8_t*)&cmd->num_intervals; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + for (uint8_t i = 0; i < cmd->num_intervals; i++) + { + // MWS_PATTERN_IntervalDuration + p_out = (uint8_t*)&cmd->intv[i].duration; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, copy_data ? p_out_end : NULL, 2); + if (status != HCI_PACK_OK) + break; + + // MWS_PATTERN_IntervalType + p_out = (uint8_t*)&cmd->intv[i].type; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, copy_data ? p_out_end : NULL, 1); + if (status != HCI_PACK_OK) + break; + } + + } while(0); + + *out_len = (uint16_t)(p_out - p_out_start); + } + else + { + // If no input data, size max is returned + *out_len = HCI_MAX_CMD_PARAM_SIZE; + } + + return (status); +} + +/// Special packing/unpacking function for HCI Set MWS Pattern Configuration command complete event +static uint8_t hci_get_mws_transport_layer_config_cmd_cmp_evt_pk(uint8_t *out, uint8_t *in, uint16_t* out_len, uint16_t in_len) +{ + struct hci_get_mws_transport_layer_config_cmd_cmp_evt* evt = (struct hci_get_mws_transport_layer_config_cmd_cmp_evt*)(in); + uint8_t* p_in = in; + uint8_t* p_out = out; + uint8_t* p_in_end = in + in_len; + uint8_t* p_out_end = out + *out_len; + uint8_t status = HCI_PACK_OK; + + // Check if there is input data to parse + if(in != NULL) + { + do + { + uint8_t num_transports, num_baud_rates; + struct mws_trans_rate *rates; + + /*The order of the return parameters in this HCI event packet is: + Status + Num_Transports + Transport_Layer[0] + Num_Baud_Rates[0] + . . . + Transport_Layer[n] + Num_Baud_Rates[n] + To_MWS_Baud_Rate[0] + From_MWS_Baud_Rate[0] + . . . + To_MWS_Baud_Rate[m] + From_MWS_Baud_Rate[m] */ + + // Status + p_in = &evt->status; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Data Length + p_in = &evt->num_transports; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + num_transports = evt->num_transports; + + for (uint8_t i = 0; i < num_transports; i++) + { + // Data + p_in = &evt->tran[i].layer_id; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if (status != HCI_PACK_OK) + break; + + // Num Baud Rates + p_in = &evt->tran[i].num_baud_rates; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if (status != HCI_PACK_OK) + break; + + num_baud_rates = evt->tran[i].num_baud_rates; + rates = evt->tran[i].rates; + + for (uint8_t j = 0; j < num_baud_rates; j++) + { + // To MWS Rate + p_in = (uint8_t*)&(rates[j].to_mws_baud_rate); + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 4); + if (status != HCI_PACK_OK) + break; + + // From MWS Rate + p_in = (uint8_t*)&(rates[j].from_mws_baud_rate); + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 4); + if (status != HCI_PACK_OK) + break; + } + } + + } while(0); + + *out_len = (uint16_t)(p_out - out); + } + else + { + *out_len = 0; + } + + return (status); +} +#endif //RW_MWS_COEX +#endif //(BT_EMB_PRESENT) + +#if (BLE_EMB_PRESENT || BLE_HOST_PRESENT) +/// Special packing/unpacking function for HCI LE Set Extended Scan Parameters command +static uint8_t hci_le_set_ext_scan_param_cmd_upk(uint8_t *out, uint8_t *in, uint16_t* out_len, uint16_t in_len) +{ + uint8_t status = HCI_PACK_OK; + + #if BLE_EMB_PRESENT + /* + * PACKING FUNCTION + */ + struct hci_le_set_ext_scan_param_cmd temp_out; + struct hci_le_set_ext_scan_param_cmd* cmd; + uint8_t* p_in = in; + uint8_t* p_out; + uint8_t* p_in_end = in + in_len; + uint8_t* p_out_start; + + // Check if there is input data to parse + if (in != NULL) + { + uint8_t* p_out_end; + bool copy_data; + + // Check if there is output buffer to write to, else use temp_out buffer + if (out != NULL) + { + cmd = (struct hci_le_set_ext_scan_param_cmd*)(out); + p_out_start = out; + p_out_end = out + *out_len; + copy_data = true; + } + else + { + cmd = (struct hci_le_set_ext_scan_param_cmd*)(&temp_out); + p_out_start = (uint8_t*)&temp_out; + p_out_end = p_out_start + sizeof(temp_out); + copy_data = false; + } + + do + { + uint8_t num_scan_phys = 0; + int i; + + // Own addr type + p_out = (uint8_t*) &cmd->own_addr_type; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Scan filter policy + p_out = (uint8_t*) &cmd->scan_filt_policy; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + //Scanning PHYs + p_out = (uint8_t*)&cmd->scan_phys; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + for (uint8_t bit_flags = cmd->scan_phys; bit_flags; bit_flags >>= 1) + { //count num scan_phys bits set + if (bit_flags & 1) + { + num_scan_phys++; + } + } + + BLE_ASSERT_ERR(num_scan_phys <= MAX_SCAN_PHYS); + + if(!copy_data) + { + p_out_end = NULL; + } + + for (i=0; i < num_scan_phys; i++) + { + // Scanning type + p_out = (uint8_t*) &cmd->phy[i].scan_type; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Scan interval + p_out = (uint8_t*) &cmd->phy[i].scan_intv; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 2); + if(status != HCI_PACK_OK) + break; + + // Scan window + p_out = (uint8_t*) &cmd->phy[i].scan_window; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 2); + if(status != HCI_PACK_OK) + break; + } + + } while(0); + + *out_len = (uint16_t)(p_out - p_out_start); + } + else + { + // If no input data, size max is returned + *out_len = sizeof(struct hci_le_set_ext_scan_param_cmd); + } + + #elif BLE_HOST_PRESENT + /* + * UNPACKING FUNCTION + */ + if((out != NULL) && (in != NULL)) + { + uint8_t i; + struct hci_le_set_ext_scan_param_cmd cmd; + uint8_t num_scan_phys; + memcpy(&cmd, in, sizeof(struct hci_le_set_ext_scan_param_cmd)); + num_scan_phys = NB_ONE_BITS(cmd.scan_phys); + + *out++ = cmd.own_addr_type; + *out++ = cmd.scan_filt_policy; + *out++ = cmd.scan_phys; + + // For each sets + for(i = 0 ; i < num_scan_phys; i++) + { + // Scaning Type: passive/active + *out++ = cmd.phy[i].scan_type; + // Scan interval + common_write16p(out, common_htobs(cmd.phy[i].scan_intv)); + out += 2; + // Scan window size + common_write16p(out, common_htobs(cmd.phy[i].scan_window)); + out += 2; + } + + *out_len = 3 + (5 * num_scan_phys); + } + else + { + status = HCI_PACK_ERROR; + } + + #endif //BLE_EMB_PRESENT + return (status); +} + +/// Special packing/unpacking function for HCI LE Extended Create Connection command +static uint8_t hci_le_ext_create_con_cmd_upk(uint8_t *out, uint8_t *in, uint16_t* out_len, uint16_t in_len) +{ + uint8_t status = HCI_PACK_OK; + + #if BLE_EMB_PRESENT + /* + * PACKING FUNCTION + */ + struct hci_le_ext_create_con_cmd temp_out; + struct hci_le_ext_create_con_cmd* cmd; + uint8_t* p_in = in; + uint8_t* p_out; + uint8_t* p_in_end = in + in_len; + uint8_t* p_out_start; + + // Check if there is input data to parse + if (in != NULL) + { + uint8_t* p_out_end; + bool copy_data; + + // Check if there is output buffer to write to, else use temp_out buffer + if (out != NULL) + { + cmd = (struct hci_le_ext_create_con_cmd*)(out); + p_out_start = out; + p_out_end = out + *out_len; + copy_data = true; + } + else + { + cmd = (struct hci_le_ext_create_con_cmd*)(&temp_out); + p_out_start = (uint8_t*)&temp_out; + p_out_end = p_out_start + sizeof(temp_out); + copy_data = false; + } + + do + { + uint8_t num_init_phys = 0; + int i; + + // Initiator filter policy + p_out = (uint8_t*) &cmd->init_filter_policy; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Own address type + p_out = (uint8_t*) &cmd->own_addr_type; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Peer address type + p_out = (uint8_t*) &cmd->peer_addr_type; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Peer address + p_out = (uint8_t*) &cmd->peer_addr.addr[0]; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, BD_ADDR_LEN); + if(status != HCI_PACK_OK) + break; + + //Initiating PHYs + p_out = (uint8_t*)&cmd->init_phys; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + for (uint8_t bit_flags = cmd->init_phys; bit_flags; bit_flags >>= 1) + { //count num init_phys bits set + if (bit_flags & 1) + { + num_init_phys++; + } + } + + BLE_ASSERT_ERR(num_init_phys <= MAX_INIT_PHYS); + + if(!copy_data) + { + p_out_end = NULL; + } + + for (i=0; i < num_init_phys; i++) + { + // Scan interval + p_out = (uint8_t*) &cmd->phy[i].scan_interval; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 2); + if(status != HCI_PACK_OK) + break; + + // Scan window + p_out = (uint8_t*) &cmd->phy[i].scan_window; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 2); + if(status != HCI_PACK_OK) + break; + + // Min connection interval + p_out = (uint8_t*)&cmd->phy[i].con_intv_min; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 2); + if (status != HCI_PACK_OK) + break; + + // Max connection interval + p_out = (uint8_t*)&cmd->phy[i].con_intv_max; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 2); + if (status != HCI_PACK_OK) + break; + + // Connection latency + p_out = (uint8_t*)&cmd->phy[i].con_latency; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 2); + if (status != HCI_PACK_OK) + break; + + // Link supervision timeout + p_out = (uint8_t*)&cmd->phy[i].superv_to; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 2); + if (status != HCI_PACK_OK) + break; + + // Min CE length + p_out = (uint8_t*)&cmd->phy[i].ce_len_min; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 2); + if (status != HCI_PACK_OK) + break; + + // Max CE length + p_out = (uint8_t*)&cmd->phy[i].ce_len_max; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 2); + if (status != HCI_PACK_OK) + break; + } + } while(0); + + *out_len = (uint16_t)(p_out - p_out_start); + } + else + { + // If no input data, size max is returned + *out_len = sizeof(struct hci_le_ext_create_con_cmd); + } + + #elif BLE_HOST_PRESENT + /* + * UNPACKING FUNCTION + */ + if((out != NULL) && (in != NULL)) + { + uint8_t i; + struct hci_le_ext_create_con_cmd cmd; + uint8_t num_init_phys; + memcpy(&cmd, in, sizeof(struct hci_le_ext_create_con_cmd)); + num_init_phys = NB_ONE_BITS(cmd.init_phys); + + *out++ = cmd.init_filter_policy; + *out++ = cmd.own_addr_type; + *out++ = cmd.peer_addr_type; + memcpy(out, cmd.peer_addr.addr, BD_ADDR_LEN); + out += BD_ADDR_LEN; + *out++ = cmd.init_phys; + + // For each sets + for(i = 0 ; i < num_init_phys; i++) + { + // Scan interval + common_write16p(out, common_htobs(cmd.phy[i].scan_interval)); + out += 2; + // Scan window size + common_write16p(out, common_htobs(cmd.phy[i].scan_window)); + out += 2; + // Minimum of connection interval + common_write16p(out, common_htobs(cmd.phy[i].con_intv_min)); + out += 2; + // Maximum of connection interval + common_write16p(out, common_htobs(cmd.phy[i].con_intv_max)); + out += 2; + // Connection latency + common_write16p(out, common_htobs(cmd.phy[i].con_latency)); + out += 2; + // Link supervision timeout + common_write16p(out, common_htobs(cmd.phy[i].superv_to)); + out += 2; + // Minimum CE length (N * 0.625 ms) + common_write16p(out, common_htobs(cmd.phy[i].ce_len_min)); + out += 2; + // Maximum CE length (N * 0.625 ms) + common_write16p(out, common_htobs(cmd.phy[i].ce_len_max)); + out += 2; + } + + *out_len = 10 + (16 * num_init_phys); + } + else + { + status = HCI_PACK_ERROR; + } + + #endif //BLE_EMB_PRESENT + return (status); +} + +/// Special packing/unpacking function for HCI LE Set Extended Advertising Enable command +static uint8_t hci_le_set_ext_adv_en_cmd_upk(uint8_t *out, uint8_t *in, uint16_t* out_len, uint16_t in_len) +{ + uint8_t status = HCI_PACK_OK; + + #if BLE_EMB_PRESENT + /* + * PACKING FUNCTION + */ + struct hci_le_set_ext_adv_en_cmd temp_out; + struct hci_le_set_ext_adv_en_cmd* cmd; + uint8_t* p_in = in; + uint8_t* p_out; + uint8_t* p_in_end = in + in_len; + uint8_t* p_out_start; + + // Check if there is input data to parse + if (in != NULL) + { + uint8_t* p_out_end; + bool copy_data; + + // Check if there is output buffer to write to, else use temp_out buffer + if (out != NULL) + { + cmd = (struct hci_le_set_ext_adv_en_cmd*)(out); + p_out_start = out; + p_out_end = out + *out_len; + copy_data = true; + } + else + { + cmd = (struct hci_le_set_ext_adv_en_cmd*)(&temp_out); + p_out_start = (uint8_t*)&temp_out; + p_out_end = p_out_start + sizeof(temp_out); + copy_data = false; + } + + do + { + // Enable + p_out = (uint8_t*) &cmd->enable; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Number of sets + p_out = (uint8_t*) &cmd->nb_sets; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + BLE_ASSERT_ERR(cmd->nb_sets <= 63); + + if(!copy_data) + { + p_out_end = NULL; + } + + + for (uint8_t i = 0; i < cmd->nb_sets; i++) + { + // Advertising handle + p_out = (uint8_t*)&cmd->adv_hdl[i]; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Duration + p_out = (uint8_t*)&cmd->duration[i]; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 2); + if(status != HCI_PACK_OK) + break; + + // Maximum number of extended advertising events + p_out = (uint8_t*)&cmd->max_ext_adv_evt[i]; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + } + + } while(0); + + *out_len = (uint16_t)(p_out - p_out_start); + } + else + { + // If no input data, size max is returned + *out_len = sizeof(struct hci_le_set_ext_adv_en_cmd); + } + + #elif BLE_HOST_PRESENT + + /* + * UNPACKING FUNCTION + */ + if((out != NULL) && (in != NULL)) + { + uint8_t i; + struct hci_le_set_ext_adv_en_cmd cmd; + memcpy(&cmd, in, sizeof(struct hci_le_set_ext_adv_en_cmd)); + *out_len = 2 + (4*cmd.nb_sets); + + // copy enable + nb sets + *out++ = cmd.enable; + *out++ = cmd.nb_sets; + + // For each sets + for(i = 0 ; i < cmd.nb_sets; i++) + { + // copy adv_handles + *out++ = cmd.adv_hdl[i]; + // copy duration + common_write16p(out, common_htobs(cmd.duration[i])); + out += 2; + // copy Maximum number of extended advertising events + *out++ = cmd.max_ext_adv_evt[i]; + } + } + else + { + status = HCI_PACK_ERROR; + } + + #endif //BLE_EMB_PRESENT + return (status); +} + +/// Special packing/unpacking function for HCI LE Advertising Report Event +static uint8_t hci_le_adv_report_evt_pkupk(uint8_t *out, uint8_t *in, uint16_t* out_len, uint16_t in_len) +{ + #if BLE_EMB_PRESENT + + /* + * PACKING FUNCTION + */ + struct hci_le_adv_report_evt temp_out; + struct hci_le_adv_report_evt* s; + uint8_t* p_in = in; + uint8_t* p_out; + uint8_t* p_in_end = in + in_len; + uint8_t* p_out_start; + uint8_t status = HCI_PACK_OK; + + // Check if there is input data to parse + if(in != NULL) + { + uint8_t* p_out_end; + + // Check if there is output buffer to write to, else use temp_out buffer + if (out != NULL) + { + s = (struct hci_le_adv_report_evt*)(out); + p_out_start = out; + p_out_end = out + *out_len; + } + else + { + s = (struct hci_le_adv_report_evt*)(&temp_out); + p_out_start = (uint8_t*)&temp_out; + p_out_end = p_out_start + sizeof(temp_out); + } + + p_out = p_out_start; + + do + { + // Sub-code + p_in = &s->subcode; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Number of reports + p_in = &s->nb_reports; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + for (int i=0; i< s->nb_reports; i++) + { + uint8_t data_len; + + // Event type + p_in = &s->adv_rep[i].evt_type; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Address type + p_in = &s->adv_rep[i].adv_addr_type; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // BD Address + p_in = &s->adv_rep[i].adv_addr.addr[0]; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, BD_ADDR_LEN); + if(status != HCI_PACK_OK) + break; + + // Data Length + p_in = &s->adv_rep[i].data_len; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + data_len = s->adv_rep[i].data_len; + + // ADV data + p_in = &s->adv_rep[i].data[0]; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, data_len); + if(status != HCI_PACK_OK) + break; + + // RSSI + p_in = (uint8_t*) &s->adv_rep[i].rssi; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + } + + } while(0); + + *out_len = (uint16_t)(p_out - p_out_start); + } + else + { + *out_len = 0; + } + + return (status); + + #elif BLE_HOST_PRESENT + + /* + * UNPACKING FUNCTION + */ + + // TODO unpack message as per compiler + *out_len = in_len; + if((out != NULL) && (in != NULL)) + { + // copy adv report + memcpy(out, in, in_len); + } + + return (HCI_PACK_OK); + + #endif //BLE_EMB_PRESENT +} + +/// Special packing/unpacking function for HCI LE Direct Advertising Report Event +static uint8_t hci_le_dir_adv_report_evt_pkupk(uint8_t *out, uint8_t *in, uint16_t* out_len, uint16_t in_len) +{ + #if BLE_EMB_PRESENT + + /* + * PACKING FUNCTION + */ + struct hci_le_dir_adv_rep_evt temp_out; + struct hci_le_dir_adv_rep_evt* s; + uint8_t* p_in = in; + uint8_t* p_out; + uint8_t* p_in_end = in + in_len; + uint8_t* p_out_start; + uint8_t status = HCI_PACK_OK; + + // Check if there is input data to parse + if(in != NULL) + { + uint8_t* p_out_end; + + // Check if there is output buffer to write to, else use temp_out buffer + if (out != NULL) + { + s = (struct hci_le_dir_adv_rep_evt*)(out); + p_out_start = out; + p_out_end = out + *out_len; + } + else + { + s = (struct hci_le_dir_adv_rep_evt*)(&temp_out); + p_out_start = (uint8_t*)&temp_out; + p_out_end = p_out_start + sizeof(temp_out); + } + + p_out = p_out_start; + + do + { + // Sub-code + p_in = &s->subcode; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Number of reports + p_in = &s->nb_reports; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + for (int i=0; i< s->nb_reports; i++) + { + // Event type + p_in = &s->adv_rep[i].evt_type; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + + // Address type + p_in = &s->adv_rep[i].addr_type; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // BD Address + p_in = &s->adv_rep[i].addr.addr[0]; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, BD_ADDR_LEN); + if(status != HCI_PACK_OK) + break; + + // Direct Address type + p_in = &s->adv_rep[i].dir_addr_type; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Direct BD Address + p_in = &s->adv_rep[i].dir_addr.addr[0]; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, BD_ADDR_LEN); + if(status != HCI_PACK_OK) + break; + + // RSSI + p_in = (uint8_t*) &s->adv_rep[i].rssi; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + } + + } while(0); + + *out_len = (uint16_t)(p_out - p_out_start); + } + else + { + *out_len = 0; + } + + return (status); + + #elif BLE_HOST_PRESENT + + /* + * UNPACKING FUNCTION + */ + + // TODO unpack message as per compiler + *out_len = in_len; + if((out != NULL) && (in != NULL)) + { + // copy adv report + memcpy(out, in, in_len); + } + + return (HCI_PACK_OK); + + #endif //BLE_EMB_PRESENT +} + +/// Special packing/unpacking function for HCI LE Extended Advertising Report Event +static uint8_t hci_le_ext_adv_report_evt_pkupk(uint8_t *out, uint8_t *in, uint16_t* out_len, uint16_t in_len) +{ + #if BLE_EMB_PRESENT + + /* + * PACKING FUNCTION + */ + struct hci_le_ext_adv_report_evt temp_out; + struct hci_le_ext_adv_report_evt* s; + uint8_t* p_in = in; + uint8_t* p_out; + uint8_t* p_in_end = in + in_len; + uint8_t* p_out_start; + uint8_t status = HCI_PACK_OK; + + // Check if there is input data to parse + if(in != NULL) + { + uint8_t* p_out_end; + + // Check if there is output buffer to write to, else use temp_out buffer + if (out != NULL) + { + s = (struct hci_le_ext_adv_report_evt*)(out); + p_out_start = out; + p_out_end = out + *out_len; + } + else + { + s = (struct hci_le_ext_adv_report_evt*)(&temp_out); + p_out_start = (uint8_t*)&temp_out; + p_out_end = p_out_start + sizeof(temp_out); + } + + p_out = p_out_start; + + do + { + // Sub-code + p_in = &s->subcode; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Number of reports + p_in = &s->nb_reports; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + for (int i=0; i< s->nb_reports; i++) + { + uint8_t data_len; + + // Event type + p_in = (uint8_t*) &s->adv_rep[i].evt_type; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 2); + if(status != HCI_PACK_OK) + break; + + // Adv Address type + p_in = &s->adv_rep[i].adv_addr_type; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Adv Address + p_in = &s->adv_rep[i].adv_addr.addr[0]; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, BD_ADDR_LEN); + if(status != HCI_PACK_OK) + break; + + // Primary PHY + p_in = &s->adv_rep[i].phy; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Secondary PHY + p_in = &s->adv_rep[i].phy2; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Advertising SID + p_in = &s->adv_rep[i].adv_sid; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Tx Power + p_in = &s->adv_rep[i].tx_power; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // RSSI + p_in = (uint8_t*) &s->adv_rep[i].rssi; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Periodic Advertising Interval + p_in = (uint8_t*) &s->adv_rep[i].interval; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 2); + if(status != HCI_PACK_OK) + break; + + // Direct address type + p_in = (uint8_t*) &s->adv_rep[i].dir_addr_type; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Direct BD Address + p_in = &s->adv_rep[i].dir_addr.addr[0]; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, BD_ADDR_LEN); + if(status != HCI_PACK_OK) + break; + + // Data Length + p_in = &s->adv_rep[i].data_len; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + data_len = s->adv_rep[i].data_len; + + // ADV data + p_in = &s->adv_rep[i].data[0]; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, data_len); + if(status != HCI_PACK_OK) + break; + } + + } while(0); + + *out_len = (uint16_t)(p_out - p_out_start); + } + else + { + *out_len = 0; + } + + return (status); + + #elif BLE_HOST_PRESENT + + /* + * UNPACKING FUNCTION + */ + //TODO unpack message as per compiler + *out_len = in_len; + if((out != NULL) && (in != NULL)) + { + // copy adv report + memcpy(out, in, in_len); + } + + return (HCI_PACK_OK); + + #endif //BLE_EMB_PRESENT +} + +/// Special packing/unpacking function for HCI LE Connectionless IQ Report Event +static uint8_t hci_le_conless_iq_report_evt_pkupk(uint8_t *out, uint8_t *in, uint16_t* out_len, uint16_t in_len) +{ + #if BLE_EMB_PRESENT + + /* + * PACKING FUNCTION + */ + struct hci_le_conless_iq_report_evt temp_out; + struct hci_le_conless_iq_report_evt* s; + uint8_t* p_in = in; + uint8_t* p_out; + uint8_t* p_in_end = in + in_len; + uint8_t* p_out_start; + uint8_t status = HCI_PACK_OK; + + // Check if there is input data to parse + if(in != NULL) + { + uint8_t* p_out_end; + + // Check if there is output buffer to write to, else use temp_out buffer + if (out != NULL) + { + s = (struct hci_le_conless_iq_report_evt*)(out); + p_out_start = out; + p_out_end = out + *out_len; + } + else + { + s = (struct hci_le_conless_iq_report_evt*)(&temp_out); + p_out_start = (uint8_t*)&temp_out; + p_out_end = p_out_start + sizeof(temp_out); + } + + p_out = p_out_start; + + do + { + uint8_t sample_cnt = 0; + + // Sub-code + p_in = &s->subcode; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Sync handle + p_in = (uint8_t*) &s->sync_hdl; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 2); + if(status != HCI_PACK_OK) + break; + + // Channel index + p_in = &s->channel_idx; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // RSSI + p_in = (uint8_t*) &s->rssi; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 2); + if(status != HCI_PACK_OK) + break; + + // RSSI antenna ID + p_in = &s->rssi_antenna_id; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // CTE type + p_in = &s->cte_type; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Slot durations + p_in = &s->slot_dur; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Packet status + p_in = &s->pkt_status; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // paEventCounter + p_in = (uint8_t*) &s->pa_evt_cnt; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 2); + if(status != HCI_PACK_OK) + break; + + // Sample count + sample_cnt = s->sample_cnt; + p_in = &s->sample_cnt; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + for (int i=0; i < sample_cnt; i++) + { + // I sample + p_in = (uint8_t *) &s->iq_sample[i].i; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Q sample + p_in = (uint8_t *) &s->iq_sample[i].q; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + } + + } while(0); + + *out_len = (uint16_t)(p_out - p_out_start); + } + else + { + *out_len = 0; + } + + return (status); + + #elif BLE_HOST_PRESENT + + /* + * UNPACKING FUNCTION + */ + //TODO unpack message as per compiler + *out_len = in_len; + if((out != NULL) && (in != NULL)) + { + // copy adv report + memcpy(out, in, in_len); + } + + return (HCI_PACK_OK); + + #endif //BLE_EMB_PRESENT +} + +/// Special packing/unpacking function for HCI LE Connection IQ Report Event +static uint8_t hci_le_con_iq_report_evt_pkupk(uint8_t *out, uint8_t *in, uint16_t* out_len, uint16_t in_len) +{ + #if BLE_EMB_PRESENT + + /* + * PACKING FUNCTION + */ + struct hci_le_con_iq_report_evt temp_out; + struct hci_le_con_iq_report_evt* s; + uint8_t* p_in = in; + uint8_t* p_out; + uint8_t* p_in_end = in + in_len; + uint8_t* p_out_start; + uint8_t status = HCI_PACK_OK; + + // Check if there is input data to parse + if(in != NULL) + { + uint8_t* p_out_end; + + // Check if there is output buffer to write to, else use temp_out buffer + if (out != NULL) + { + s = (struct hci_le_con_iq_report_evt*)(out); + p_out_start = out; + p_out_end = out + *out_len; + } + else + { + s = (struct hci_le_con_iq_report_evt*)(&temp_out); + p_out_start = (uint8_t*)&temp_out; + p_out_end = p_out_start + sizeof(temp_out); + } + + p_out = p_out_start; + + do + { + uint8_t sample_cnt = 0; + + // Sub-code + p_in = &s->subcode; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Connection handle + p_in = (uint8_t*) &s->conhdl; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 2); + if(status != HCI_PACK_OK) + break; + + // Rx PHY + p_in = &s->rx_phy; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Data channel index + p_in = &s->data_channel_idx; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // RSSI + p_in = (uint8_t*) &s->rssi; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 2); + if(status != HCI_PACK_OK) + break; + + // RSSI antenna ID + p_in = &s->rssi_antenna_id; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // CTE type + p_in = &s->cte_type; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Slot durations + p_in = &s->slot_dur; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Packet status + p_in = &s->pkt_status; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // connEventCounter + p_in = (uint8_t*) &s->con_evt_cnt; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 2); + if(status != HCI_PACK_OK) + break; + + // Sample count + sample_cnt = s->sample_cnt; + p_in = &s->sample_cnt; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + for (int i=0; i < sample_cnt; i++) + { + // I sample + p_in = (uint8_t *) &s->iq_sample[i].i; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Q sample + p_in = (uint8_t *) &s->iq_sample[i].q; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + } + + } while(0); + + *out_len = (uint16_t)(p_out - p_out_start); + } + else + { + *out_len = 0; + } + + return (status); + + #elif BLE_HOST_PRESENT + + /* + * UNPACKING FUNCTION + */ + //TODO unpack message as per compiler + *out_len = in_len; + if((out != NULL) && (in != NULL)) + { + // copy adv report + memcpy(out, in, in_len); + } + + return (HCI_PACK_OK); + + #endif //BLE_EMB_PRESENT +} + +#endif //(BLE_EMB_PRESENT || BLE_HOST_PRESENT) + +#if (RW_DEBUG && (BLE_EMB_PRESENT || BT_EMB_PRESENT)) +/// Special packing/unpacking function for HCI DBG assert error Event +static uint8_t hci_dbg_assert_evt_pkupk(uint8_t *out, uint8_t *in, uint16_t* out_len, uint16_t in_len) +{ + struct hci_dbg_assert_evt* evt = (struct hci_dbg_assert_evt*)(in); + uint8_t* p_in = in; + uint8_t* p_out = out; + uint8_t* p_in_end = in + in_len; + uint8_t* p_out_end = out + *out_len; + uint8_t status = HCI_PACK_OK; + + // Check if there is input data to parse + if(in != NULL) + { + do + { + // Subcode + p_in = &evt->subcode; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Type + p_in = &evt->type; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if(status != HCI_PACK_OK) + break; + + // Line + p_in = (uint8_t*) &evt->line; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 4); + if(status != HCI_PACK_OK) + break; + + // Param0 + p_in = (uint8_t*) &evt->param0; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 4); + if(status != HCI_PACK_OK) + break; + + // Param1 + p_in = (uint8_t*) &evt->param1; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 4); + if(status != HCI_PACK_OK) + break; + + // File + p_in = (uint8_t*) &evt->file; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, strlen((char*) evt->file)); + if(status != HCI_PACK_OK) + break; + } while(0); + + *out_len = (uint16_t)(p_out - out); + } + else + { + *out_len = 0; + } + + return (status); +} +#endif //(RW_DEBUG && (BLE_EMB_PRESENT || BT_EMB_PRESENT)) + +#if BLE_IQ_GEN +/// Special packing/unpacking function for HCI DBG iqgen config command +static uint8_t hci_dbg_iqgen_cfg_cmd_upk(uint8_t *out, uint8_t *in, uint16_t* out_len, uint16_t in_len) +{ + struct hci_dbg_iqgen_cfg_cmd temp_out; + struct hci_dbg_iqgen_cfg_cmd* cmd; + uint8_t* p_in = in; + uint8_t* p_out; + uint8_t* p_in_end = in + in_len; + uint8_t* p_out_start; + uint8_t status = HCI_PACK_OK; + + // Check if there is input data to parse + if (in != NULL) + { + uint8_t* p_out_end; + bool copy_data; + + // Check if there is output buffer to write to, else use temp_out buffer + if (out != NULL) + { + cmd = (struct hci_dbg_iqgen_cfg_cmd*)(out); + p_out_start = out; + p_out_end = out + *out_len; + copy_data = true; + } + else + { + cmd = (struct hci_dbg_iqgen_cfg_cmd*)(&temp_out); + p_out_start = (uint8_t*)&temp_out; + p_out_end = p_out_start + sizeof(temp_out); + copy_data = false; + } + + do + { + //Nb_antenna + p_out = (uint8_t*)&cmd->nb_antenna; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if (status != HCI_PACK_OK) + break; + + //Mode + p_out = (uint8_t*)&cmd->mode; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, p_out_end, 1); + if (status != HCI_PACK_OK) + break; + + for (uint8_t i = 0; i < cmd->nb_antenna; i++) + { + //I-sample control + p_out = (uint8_t*)&cmd->iq_ctrl[i].i; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, copy_data ? p_out_end : NULL, 1); + if (status != HCI_PACK_OK) + break; + + //Q-sample control + p_out = (uint8_t*)&cmd->iq_ctrl[i].q; + status = hci_pack_bytes(&p_in, &p_out, p_in_end, copy_data ? p_out_end : NULL, 1); + if (status != HCI_PACK_OK) + break; + } + + } while (0); + + *out_len = (uint16_t)(p_out - p_out_start); + } + else + { + // If no input data, size max is returned + *out_len = HCI_MAX_CMD_PARAM_SIZE; + } + + return (status); +} +#endif //BLE_IQ_GEN +#endif //(HCI_TL_SUPPORT) + +/* + * MODULES INTERNAL FUNCTION DEFINITIONS + **************************************************************************************** + */ + +const struct hci_cmd_desc_tag* hci_look_for_cmd_desc(uint16_t opcode) +{ + const struct hci_cmd_desc_tag* tab = NULL; + const struct hci_cmd_desc_tag* desc = NULL; + uint16_t nb_cmds = 0; + uint16_t index = 0; + uint16_t ocf = HCI_OP2OCF(opcode); + uint16_t ogf = HCI_OP2OGF(opcode); + + // Find table corresponding to this OGF + for(index = 0; index < ARRAY_LEN(hci_cmd_desc_root_tab); index++) + { + // Compare the command opcodes + if(hci_cmd_desc_root_tab[index].ogf == ogf) + { + // Get the command descriptors table information (size and pointer) + tab = hci_cmd_desc_root_tab[index].cmd_desc_tab; + nb_cmds = hci_cmd_desc_root_tab[index].nb_cmds; + break; + } + } + + // Check if a table has been found for this OGF + if(tab != NULL) + { + // Find the command descriptor associated to this OCF + for(index = 0; index < nb_cmds; index++) + { + // Compare the command opcodes + if(HCI_OP2OCF(tab->opcode) == ocf) + { + // Get the command descriptor pointer + desc = tab; + break; + } + + // Jump to next command descriptor + tab++; + } + } + + return (desc); +} + +/** +**************************************************************************************** +* @brief Look for an event descriptor that could match with the specified event code +* +* @param[in] code event code +* +* @return Pointer the event descriptor (NULL if not found) +***************************************************************************************** +*/ +const struct hci_evt_desc_tag* hci_look_for_evt_desc(uint8_t code) +{ + const struct hci_evt_desc_tag* desc = NULL; + uint16_t index = 0; + + while(index < (sizeof(hci_evt_desc_tab)/sizeof(hci_evt_desc_tab[0]))) + { + // Compare the command opcodes + if(hci_evt_desc_tab[index].code == code) + { + // Get the event descriptor pointer + desc = &hci_evt_desc_tab[index]; + break; + } + + // Increment index + index++; + } + + return (desc); +} + +#if (BLE_EMB_PRESENT || BT_EMB_PRESENT) +#if (RW_DEBUG || BLE_ISOGEN) +const struct hci_evt_desc_tag* hci_look_for_dbg_evt_desc(uint8_t subcode) +{ + const struct hci_evt_desc_tag* desc = NULL; + uint16_t index = 0; + + while(index < (sizeof(hci_evt_dbg_desc_tab)/sizeof(hci_evt_dbg_desc_tab[0]))) + { + // Compare the command opcodes + if(hci_evt_dbg_desc_tab[index].code == subcode) + { + // Get the event descriptor pointer + desc = &hci_evt_dbg_desc_tab[index]; + break; + } + + // Increment index + index++; + } + + return (desc); +} +#endif // (RW_DEBUG || BLE_ISOGEN) +#endif // (BLE_EMB_PRESENT || BT_EMB_PRESENT) + + +#if (BLE_EMB_PRESENT || BLE_HOST_PRESENT) +const struct hci_evt_desc_tag* hci_look_for_le_evt_desc(uint8_t subcode) +{ + const struct hci_evt_desc_tag* desc = NULL; + uint16_t index = 0; + + while(index < (sizeof(hci_evt_le_desc_tab)/sizeof(hci_evt_le_desc_tab[0]))) + { + // Compare the command opcodes + if(hci_evt_le_desc_tab[index].code == subcode) + { + // Get the event descriptor pointer + desc = &hci_evt_le_desc_tab[index]; + break; + } + + // Increment index + index++; + } + + return (desc); +} +#endif //(BLE_EMB_PRESENT || BLE_HOST_PRESENT) +#endif //(HCI_PRESENT) + + +/// @} HCI diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/hci/src/hci_tl.c b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/hci/src/hci_tl.c new file mode 100755 index 0000000..3ae369c --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/hci/src/hci_tl.c @@ -0,0 +1,2322 @@ +/** + **************************************************************************************** + * + * @file hci_tl.c + * + * @brief HCI module source file. + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @addtogroup HCI + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" // SW configuration + +#if (HCI_PRESENT) + +#if (HCI_TL_SUPPORT) + +#include // string manipulation +#include "common_error.h" // error definition +#include "common_utils.h" // common utility definition +#include "common_endian.h" // common endianess definition +#include "common_list.h" // list definition + +#include "hci.h" // hci definition +#include "hci_int.h" // hci internal definition + +#include "kernel_msg.h" // kernel message declaration +#include "kernel_task.h" // kernel task definition +#include "kernel_mem.h" // kernel memory definition +#include "kernel_timer.h" // kernel timer definition +#include "rwip.h" // rw bt core interrupt +#include "dbg.h" // debug + +#if (H4TL_SUPPORT) +#include "h4tl.h" // H4TL definitions +#endif // H4TL_SUPPORT + +#if BLE_EMB_PRESENT +#include "ble_util_buf.h" +#include "em_map.h" +#include "ble_reg_access.h" +#endif //BLE_EMB_PRESENT + +#if BT_EMB_PRESENT +#include "bt_util_buf.h" +#include "em_map.h" +#include "ble_reg_access.h" +#endif //BT_EMB_PRESENT + +#if ((BLE_HOST_PRESENT) && (!BLE_EMB_PRESENT)) +#include "gapc.h" +#include "gap.h" +#endif // ((BLE_HOST_PRESENT) && (!BLE_EMB_PRESENT)) + +/* + * DEFINES + **************************************************************************************** + */ + +/// Offset of the Kernel message parameters compared to the event packet position +#define HCI_CMD_PARAM_OFFSET 3 +#define HCI_EVT_CC_PARAM_OFFSET 5 +#define HCI_EVT_CS_PARAM_OFFSET 5 +#define HCI_EVT_PARAM_OFFSET 2 +#define HCI_EVT_LE_PARAM_OFFSET 2 +#define HCI_EVT_DBG_PARAM_OFFSET 2 + + +/* + * ENUMERATIONS DEFINITIONS + **************************************************************************************** + */ + +#if (BLE_EMB_PRESENT) +#if (BLE_OBSERVER) +/// Status of an advertising report chain +enum adv_rep_chain_stat +{ + /// No chain + HCI_ADV_REP_CHAIN_NO = 0, + /// A valid advertising report chain is ongoing + HCI_ADV_REP_CHAIN_VALID = 1, + /// A filtered advertising report chain is ongoing + HCI_ADV_REP_CHAIN_FILTERED = 2, +}; +#endif // (BLE_OBSERVER) +#endif // (BLE_EMB_PRESENT) + +///HCI TX states +enum HCI_TX_STATE +{ + ///HCI TX Start State - when packet is ready to be sent + HCI_STATE_TX_ONGOING, + ///HCI TX Done State - TX ended with no error + HCI_STATE_TX_IDLE +}; + + +/* + * STRUCTURES DEFINITIONS + **************************************************************************************** + */ + +///HCI Environment context structure +struct hci_tl_env_tag +{ + /// Queue of kernel messages corresponding to HCI TX packets + struct common_list tx_queue; + + #if (BT_EMB_PRESENT || HCI_BLE_CON_SUPPORT) + /// acl data messages + struct common_list acl_queue; + #endif //(BT_EMB_PRESENT || HCI_BLE_CON_SUPPORT) + + #if (BT_EMB_PRESENT) + #if VOICE_OVER_HCI + /// sco data messages + struct common_list sync_queue; + #endif //VOICE_OVER_HCI + #endif //BT_EMB_PRESENT + + /// keep the link to message in transmission to a Host + struct kernel_msg *curr_tx_msg; + + ///Tx state - either transmitting, done or error. + uint8_t tx_state; + + /// Allowed number of commands from Host to controller (sent from controller to host) + int8_t nb_h2c_cmd_pkts; + + /// This flag indicates that the current ACL payload is received in a trash buffer + bool acl_trash_payload; + + #if (BLE_EMB_PRESENT) + #if (BLE_OBSERVER) + /// Counter of IQ report + uint8_t iq_rep_cnt; + + /// Counter of advertising report fragments + uint8_t adv_rep_frag_cnt; + + /// Status of an advertising report chain from 1M scan + uint8_t adv_rep_chain_stat_1M; + + /// Status of an advertising report chain from coded scan + uint8_t adv_rep_chain_stat_coded; + + /// Status of an advertising report chain from periodic scans + uint8_t per_adv_rep_chain_stat[BLE_ACTIVITY_MAX]; + #endif // (BLE_OBSERVER) + #endif // (BLE_EMB_PRESENT) +}; + +/* + * GLOBAL VARIABLE DEFINITIONS + **************************************************************************************** + */ + +///HCI environment structure external global variable declaration +static struct hci_tl_env_tag hci_tl_env; + +/* + * LOCAL FUNCTION DECLARATIONS + **************************************************************************************** + */ + +static void hci_tx_done(void); + +/* + * LOCAL FUNCTION DEFINITIONS + **************************************************************************************** + */ + +#if (BLE_EMB_PRESENT) +#if (BLE_OBSERVER) +/** + **************************************************************************************** + * @brief Filter advertising reports if exceeding the maximum capacity + * + * This function controls the flow of HCI advertising reports to the Host. It monitors + * the number of accumulated reports. If the maximum number of reports has been exceeded, + * new reports are trashed. + * + * @param[in] msg Kernel message containing the event + * @return True: message is filtered | False: message can be transmitted + ***************************************************************************************** + */ +static bool hci_ble_adv_report_filter_check(struct kernel_msg * msg) +{ + bool filtered = false; + + do + { + uint8_t chain_stat = HCI_ADV_REP_CHAIN_NO; + uint8_t subcode = 0xFF; + bool adv_rep = false; + + // Check if the message is an LE event + if(msg->id != HCI_LE_EVENT) + break; + + // Retrieve event subcode + subcode = *((uint8_t *) msg->param); + + // Check event subcode HCI_LE_ADV_Report or HCI_LE_Ext_ADV_Report + switch (subcode) + { + case HCI_LE_EXT_ADV_REPORT_EVT_SUBCODE: + { + // Point to event parameters + struct hci_le_ext_adv_report_evt* evt = (struct hci_le_ext_adv_report_evt*) &msg->param; + bool more_data = (GETF(evt->adv_rep[0].evt_type, ADV_EVT_DATA_STATUS) == ADV_EVT_DATA_STATUS_INCOMPLETE); + + chain_stat = (evt->adv_rep[0].phy == PHY_1MBPS_VALUE) ? hci_tl_env.adv_rep_chain_stat_1M : hci_tl_env.adv_rep_chain_stat_coded; + + // Check if report can be queued for transmission, or must be flushed + if( (chain_stat == HCI_ADV_REP_CHAIN_FILTERED) + || ((chain_stat == HCI_ADV_REP_CHAIN_NO) && (hci_tl_env.adv_rep_frag_cnt >= BLE_MAX_NB_ADV_REP_FRAG)) ) + { + filtered = true; + } + + // Evaluate new chain status + if (!more_data) + { + chain_stat = HCI_ADV_REP_CHAIN_NO; + } + else + { + chain_stat = filtered ? HCI_ADV_REP_CHAIN_FILTERED : HCI_ADV_REP_CHAIN_VALID; + } + + // Update chain info for the scan PHY + if(evt->adv_rep[0].phy == PHY_1MBPS_VALUE) + { + hci_tl_env.adv_rep_chain_stat_1M = chain_stat; + DBG_SWDIAG(LEADVFILT, CHAIN_STAT_1M, chain_stat); + } + else + { + hci_tl_env.adv_rep_chain_stat_coded = chain_stat; + } + + adv_rep = true; + } + break; + + case HCI_LE_ADV_REPORT_EVT_SUBCODE: + { + // Filter legacy report if the max number is reached + filtered = (hci_tl_env.adv_rep_frag_cnt >= BLE_MAX_NB_ADV_REP_FRAG); + + adv_rep = true; + } + break; + + case HCI_LE_PER_ADV_REPORT_EVT_SUBCODE: + { + // Point to event parameters + struct hci_le_per_adv_report_evt* evt = (struct hci_le_per_adv_report_evt*) &msg->param; + bool more_data = (evt->status == PER_ADV_EVT_DATA_STATUS_INCOMPLETE); + + chain_stat = hci_tl_env.per_adv_rep_chain_stat[BLE_SYNCHDL_TO_ACTID(evt->sync_handle)]; + + // Check if report can be queued for transmission, or must be flushed + if( (chain_stat == HCI_ADV_REP_CHAIN_FILTERED) + || ((chain_stat == HCI_ADV_REP_CHAIN_NO) && (hci_tl_env.adv_rep_frag_cnt >= BLE_MAX_NB_ADV_REP_FRAG)) ) + { + filtered = true; + } + + // Evaluate new chain status + if (!more_data) + { + chain_stat = HCI_ADV_REP_CHAIN_NO; + } + else + { + chain_stat = filtered ? HCI_ADV_REP_CHAIN_FILTERED : HCI_ADV_REP_CHAIN_VALID; + } + + // Update chain info for the sync handle + hci_tl_env.per_adv_rep_chain_stat[BLE_SYNCHDL_TO_ACTID(evt->sync_handle)] = chain_stat; + + adv_rep = true; + } + break; + + case HCI_LE_CONLESS_IQ_REPORT_EVT_SUBCODE: + { + // Check if report can be queued for transmission, or must be flushed + filtered = (hci_tl_env.iq_rep_cnt >= BLE_MAX_NB_IQ_REP); + + // If transmitted, increment report counter + if(!filtered) + { + DBG_SWDIAG(LEADVFILT, OK, 1); + + // Increment report counter + hci_tl_env.iq_rep_cnt++; + + DBG_SWDIAG(LEADVFILT, OK, 0); + } + } + break; + + default: + { + } + break; + } + + if(filtered) + { + DBG_SWDIAG(LEADVFILT, KO, 1); + + // Trash the report + kernel_msg_free(msg); + + DBG_SWDIAG(LEADVFILT, KO, 0); + } + else if (adv_rep) + { + DBG_SWDIAG(LEADVFILT, OK, 1); + + // Increment report fragment counter + hci_tl_env.adv_rep_frag_cnt++; + DBG_SWDIAG(LEADVFILT, CNT, hci_tl_env.adv_rep_frag_cnt); + + DBG_SWDIAG(LEADVFILT, OK, 0); + } + + } while(0); + + return filtered; +} + +/** + **************************************************************************************** + * @brief Update advertising reports flow control when message is transmitted + * + * @param[in] msg Kernel message containing the event + ***************************************************************************************** + */ +static void hci_ble_adv_report_tx_check(struct kernel_msg * msg) +{ + do + { + uint8_t subcode; + + // Check if the message is an LE event + if(msg->id != HCI_LE_EVENT) + break; + + // Retrieve event subcode + subcode = *((uint8_t *) msg->param); + + // Check if the event is HCI_LE_ADV_Report or HCI_LE_Ext_ADV_Report or HCI_LE_Per_ADV_Report + if( (subcode == HCI_LE_ADV_REPORT_EVT_SUBCODE) || (subcode == HCI_LE_EXT_ADV_REPORT_EVT_SUBCODE) + || (subcode == HCI_LE_PER_ADV_REPORT_EVT_SUBCODE) ) + { + // Check that at least one advertising report is queued for transmission + if(hci_tl_env.adv_rep_frag_cnt == 0) + { + BLE_ASSERT_ERR(0); + break; + } + + // Decrement report fragment counter + hci_tl_env.adv_rep_frag_cnt--; + DBG_SWDIAG(LEADVFILT, CNT, hci_tl_env.adv_rep_frag_cnt); + + break; + } + + // Check if the event is HCI_LE_Conless_IQ_Report + if(subcode == HCI_LE_CONLESS_IQ_REPORT_EVT_SUBCODE) + { + // Check that at least one IQ report is queued for transmission + if(hci_tl_env.iq_rep_cnt == 0) + { + BLE_ASSERT_ERR(0); + break; + } + + // Decrement IQ report counter + hci_tl_env.iq_rep_cnt--; + + break; + } + + } while(0); +} +#endif // (BLE_OBSERVER) +#endif // (BLE_EMB_PRESENT) + +#if (BLE_EMB_PRESENT || BT_EMB_PRESENT) + +/** + **************************************************************************************** + * @brief Reject a HCI command + * + * This function creates a CS or CC event Kernel message to reject a command. + * + * @param[in] cmd_desc Command descriptor (NULL if command unknown) + * @return Pointer to the beginning of the event + ***************************************************************************************** + */ +static void hci_cmd_reject(const struct hci_cmd_desc_tag* cmd_desc, uint16_t opcode, uint8_t error, uint8_t * payload) +{ + if(cmd_desc != NULL) + { + // Check if this command shall be replied with a CC or CS event + if(cmd_desc->ret_par_fmt != NULL) + { + // Get size of the Command Complete Event message associated with the opcode + uint16_t ret_par_len; + uint8_t status = COMMON_UTIL_PACK_OK; + + // Check if the generic packer can be used (basic fixed-length format) + if(!(cmd_desc->dest_field & HCI_CMD_DEST_SPEC_RET_PAR_PK_MSK)) + { + // Use the generic unpacker to get unpacked parameters length + status = common_util_unpack(NULL, NULL, &ret_par_len, 0xFFFF, cmd_desc->ret_par_fmt); + } + else + { + // Use the special unpacker to get unpacked parameters length + status = ((hci_pkupk_func_t)cmd_desc->ret_par_fmt)(NULL, NULL, &ret_par_len, 0); + } + + if(status == COMMON_UTIL_PACK_OK) + { + // Send a CC event with returned parameters (eventually copy received connection handle or BD address if needed) + if(!memcmp(cmd_desc->ret_par_fmt, "BH", 2)) + { + struct hci_basic_conhdl_cmd_cmp_evt* evt = (struct hci_basic_conhdl_cmd_cmp_evt*) kernel_msg_alloc(HCI_CMD_CMP_EVENT, 0, opcode, ret_par_len); + evt->status = error; + memcpy(&evt->conhdl, payload, 2); + hci_send_2_host(evt); + } + else if(!memcmp(cmd_desc->ret_par_fmt, "B6B", 3)) + { + struct hci_basic_bd_addr_cmd_cmp_evt* evt = (struct hci_basic_bd_addr_cmd_cmp_evt*) kernel_msg_alloc(HCI_CMD_CMP_EVENT, 0, opcode, ret_par_len); + evt->status = error; + memcpy(&evt->bd_addr, payload, 6); + hci_send_2_host(evt); + } + else + { + struct hci_basic_cmd_cmp_evt* evt = (struct hci_basic_cmd_cmp_evt*) kernel_msg_alloc(HCI_CMD_CMP_EVENT, 0, opcode, ret_par_len); + evt->status = error; + hci_send_2_host(evt); + } + } + else + { + BLE_ASSERT_INFO(0, status, opcode); + } + } + else + { + // Send a CS event with error code "Unknown connection identifier" + struct hci_cmd_stat_event* evt = KERNEL_MSG_ALLOC(HCI_CMD_STAT_EVENT, 0, opcode, hci_cmd_stat_event); + evt->status = error; + hci_send_2_host(evt); + } + } + else + { + // Send a CC event with error code "Unknown HCI command" + struct hci_basic_cmd_cmp_evt * evt = KERNEL_MSG_ALLOC(HCI_CMD_CMP_EVENT, 0, opcode, hci_basic_cmd_cmp_evt); + evt->status = error; + hci_send_2_host(evt); + } +} + +/** + **************************************************************************************** + * @brief Build a HCI Command Status event + * + * This function build a HCI CS event from the CS event Kernel message. + * + * @param[in] msg Kernel message containing the CS event + * @return Pointer to the beginning of the event + ***************************************************************************************** + */ +static uint8_t* hci_build_cs_evt(struct kernel_msg * msg) +{ + uint8_t* param = kernel_msg2param(msg); + uint8_t* buf = param - HCI_EVT_CS_PARAM_OFFSET; + uint8_t* pk = buf; + uint16_t opcode = msg->src_id; + + //pack event code + *pk++ = HCI_CMD_STATUS_EVT_CODE; + + //pack event parameter length + *pk++ = HCI_CSEVT_PARLEN; + + //pack the status + *pk++ = *param; + + //pack the number of h2c packets + *pk++ = (hci_tl_env.nb_h2c_cmd_pkts > 0)? (uint8_t) hci_tl_env.nb_h2c_cmd_pkts : 0; + + //pack opcode + common_write16p(pk, common_htobs(opcode)); + + return buf; +} + +/** + **************************************************************************************** + * @brief Build a HCI Command Complete event + * + * This function build a HCI CC event from the CC event Kernel message. + * + * @param[in] msg Kernel message containing the CC event + * @return Pointer to the beginning of the event + ***************************************************************************************** + */ +static uint8_t* hci_build_cc_evt(struct kernel_msg * msg) +{ + uint8_t* param = kernel_msg2param(msg); + uint8_t* buf = param - HCI_EVT_CC_PARAM_OFFSET; + uint8_t* pk = buf; + uint16_t opcode = msg->src_id; + uint16_t ret_par_len = msg->param_len; + + // Look for the command descriptor + const struct hci_cmd_desc_tag* cmd_desc = hci_look_for_cmd_desc(opcode); + + if((cmd_desc != NULL) && (ret_par_len > 0)) + { + uint8_t status = COMMON_UTIL_PACK_ERROR; + + if(cmd_desc->ret_par_fmt != NULL) + { + // Check if the generic packer can be used (basic fixed-length format) + if(!(cmd_desc->dest_field & HCI_CMD_DEST_SPEC_RET_PAR_PK_MSK)) + { + // Pack the returned parameters using the generic packer + status = common_util_pack(param, param, &ret_par_len, ret_par_len, cmd_desc->ret_par_fmt); + } + else + { + // Pack the return parameters using the special packer + status = ((hci_pkupk_func_t)cmd_desc->ret_par_fmt)(param, param, &ret_par_len, ret_par_len); + } + } + + if(status != COMMON_UTIL_PACK_OK) + { + BLE_ASSERT_INFO((status == COMMON_UTIL_PACK_OK), status, opcode); + } + } + else if (opcode != HCI_NO_OPERATION_CMD_OPCODE) + { + // Set the status "Unknown HCI command" as unique returned parameter + *param = COMMON_ERROR_UNKNOWN_HCI_COMMAND; + } + else + { + BLE_ASSERT_INFO(0, opcode, ret_par_len); + } + + //pack event code + *pk++ = HCI_CMD_CMP_EVT_CODE; + + //pack event parameter length + *pk++ = HCI_CCEVT_HDR_PARLEN + ret_par_len; + + //pack the number of h2c packets + *pk++ = (hci_tl_env.nb_h2c_cmd_pkts > 0)? (uint8_t) hci_tl_env.nb_h2c_cmd_pkts : 0; + + //pack opcode + common_write16p(pk, common_htobs(opcode)); + + return buf; +} + +/** + **************************************************************************************** + * @brief Build a HCI event + * + * This function build a HCI event from the event Kernel message. + * + * @param[in] msg Kernel message containing the event + * @return Pointer to the beginning of the event + ***************************************************************************************** + */ +static uint8_t* hci_build_evt(struct kernel_msg * msg) +{ + uint8_t* param = kernel_msg2param(msg); + uint8_t* buf = param - HCI_EVT_LE_PARAM_OFFSET; + uint8_t* pk = buf; + uint8_t evt_code = (uint8_t) msg->src_id; + uint16_t par_len = msg->param_len; + uint8_t status = COMMON_UTIL_PACK_OK; + + BLE_ASSERT_INFO(msg->src_id <= UINT8_MAX, msg->src_id, 0); + + // Look for the event descriptor + const struct hci_evt_desc_tag* evt_desc = hci_look_for_evt_desc(evt_code); + + if(evt_desc != NULL) + { + if(evt_desc->par_fmt != NULL) + { + // Check if the generic packer can be used (basic fixed-length format) + if(evt_desc->special_pack == PK_GEN) + { + // Pack the returned parameters using the generic packer + status = common_util_pack(param, param, &par_len, par_len, evt_desc->par_fmt); + } + else + { + // Pack the parameters using the special packer + status = ((hci_pkupk_func_t)evt_desc->par_fmt)(param, param, &par_len, par_len); + } + } + else if(msg->param_len > 0) + { + status = COMMON_UTIL_PACK_ERROR; + } + + if(status != COMMON_UTIL_PACK_OK) + { + BLE_ASSERT_INFO((status == COMMON_UTIL_PACK_OK), status, evt_code); + } + + BLE_ASSERT_INFO(par_len <= msg->param_len, status, evt_code); + + //pack event code + *pk++ = evt_code; + + //pack event parameter length + *pk++ = par_len; + } + else + { + BLE_ASSERT_INFO(0, evt_code, 0); + } + + return buf; +} + +#if (RW_DEBUG) +/** + **************************************************************************************** + * @brief Build a HCI DBG event + * + * This function build a HCI LE event from the DBG event Kernel message. + * + * @param[in] msg Kernel message containing the DBG event + * @return Pointer to the beginning of the event + ***************************************************************************************** + */ +static uint8_t* hci_build_dbg_evt(struct kernel_msg * msg) +{ + uint8_t* param = kernel_msg2param(msg); + uint8_t* buf = param - HCI_EVT_DBG_PARAM_OFFSET; + uint8_t* pk = buf; + uint8_t subcode = *param; + uint16_t par_len = msg->param_len; + + // Look for the event descriptor + const struct hci_evt_desc_tag* evt_desc = hci_look_for_dbg_evt_desc(subcode); + + if(evt_desc != NULL) + { + uint8_t status = COMMON_UTIL_PACK_ERROR; + + if(evt_desc->par_fmt != NULL) + { + // Check if the generic packer can be used (basic fixed-length format) + if(evt_desc->special_pack == PK_GEN) + { + // Pack the returned parameters + status = common_util_pack(param, param, &par_len, par_len, evt_desc->par_fmt); + } + else + { + // Pack the parameters using the special packer + status = ((hci_pkupk_func_t)evt_desc->par_fmt)(param, param, &par_len, par_len); + } + } + + BLE_ASSERT_INFO((status == COMMON_UTIL_PACK_OK), status, subcode); + BLE_ASSERT_INFO(par_len <= msg->param_len, par_len, subcode); + if(status == COMMON_UTIL_PACK_OK) + { + //pack event code + *pk++ = HCI_DBG_META_EVT_CODE; + + //pack event parameter length + *pk++ = par_len; + } + } + else + { + BLE_ASSERT_INFO(0, subcode, 0); + } + + return buf; +} +#endif // (RW_DEBUG) + + +#if BLE_EMB_PRESENT +/** + **************************************************************************************** + * @brief Build a HCI LE event + * + * This function build a HCI LE event from the LE event Kernel message. + * + * @param[in] msg Kernel message containing the LE event + * @return Pointer to the beginning of the event + ***************************************************************************************** + */ +static uint8_t* hci_build_le_evt(struct kernel_msg * msg) +{ + uint8_t* param = kernel_msg2param(msg); + uint8_t* buf = param - HCI_EVT_LE_PARAM_OFFSET; + uint8_t* pk = buf; + uint8_t subcode = *param; + uint16_t par_len = msg->param_len; + + // Look for the event descriptor + const struct hci_evt_desc_tag* evt_desc = hci_look_for_le_evt_desc(subcode); + + if(evt_desc != NULL) + { + uint8_t status = COMMON_UTIL_PACK_ERROR; + + if(evt_desc->par_fmt != NULL) + { + // Check if the generic packer can be used (basic fixed-length format) + if(evt_desc->special_pack == PK_GEN) + { + // Pack the returned parameters + status = common_util_pack(param, param, &par_len, par_len, evt_desc->par_fmt); + } + else + { + // Pack the parameters using the special packer + status = ((hci_pkupk_func_t)evt_desc->par_fmt)(param, param, &par_len, par_len); + } + } + + BLE_ASSERT_INFO((status == COMMON_UTIL_PACK_OK), status, subcode); + BLE_ASSERT_INFO(par_len <= msg->param_len, par_len, subcode); + if(status == COMMON_UTIL_PACK_OK) + { + //pack event code + *pk++ = HCI_LE_META_EVT_CODE; + + //pack event parameter length + *pk++ = par_len; + } + } + else + { + BLE_ASSERT_INFO(0, subcode, 0); + } + + return buf; +} +#endif //BLE_EMB_PRESENT +#endif //(BLE_EMB_PRESENT || BT_EMB_PRESENT) + +#if BT_EMB_PRESENT +#if VOICE_OVER_HCI +/** + **************************************************************************************** + * @brief Build a HCI SYNC data packet + * + * This function build a HCI SYNC data packet from the Kernel message. + * + * @param[in] msg Kernel message associated to the HCI SYNC data + ***************************************************************************************** + */ +static uint8_t* hci_build_sync_data(struct kernel_msg * msg) +{ + struct hci_sync_data *param = (struct hci_sync_data *) kernel_msg2param(msg); + uint16_t pk_start_addr = param->buf_ptr - HCI_SYNC_HDR_LEN; + + // Pack connection handle and packet status flags + em_wr16p(pk_start_addr + HCI_SYNC_HDR_HDL_FLAGS_POS, param->conhdl_psf); + + // Pack the data length + em_wr8p(pk_start_addr + HCI_SYNC_HDR_DATA_LEN_POS, param->length); + + return (uint8_t *)(EM_BASE_ADDR + pk_start_addr); +} +#endif //VOICE_OVER_HCI +#endif //BT_EMB_PRESENT + +#if (BT_EMB_PRESENT || HCI_BLE_CON_SUPPORT) +/** + **************************************************************************************** + * @brief Build a HCI ACL data packet + * + * This function build a HCI ACL data packet from the Kernel message. + * + * @param[in] msg Kernel message associated to the HCI ACL data + ***************************************************************************************** + */ +static uint8_t* hci_build_acl_data(struct kernel_msg * msg) +{ + // Point to message parameters structure + struct hci_acl_data *param = (struct hci_acl_data *) kernel_msg2param(msg); + uint16_t handle_flags = param->conhdl_pb_bc_flag; + uint8_t* buf = ((uint8_t*)param->buf_ptr) - HCI_ACL_HDR_LEN;; + uint8_t* pk; + + #if (!BLE_HOST_PRESENT || BLE_EMB_PRESENT) + buf += EM_BASE_ADDR; + #endif // (!BLE_HOST_PRESENT || BLE_EMB_PRESENT) + + pk = buf; + + // Pack connection handle and data flags + common_write16p(pk, common_htobs(handle_flags)); + pk +=2; + + // Pack the data length + common_write16p(pk, common_htobs(param->length)); + pk +=2; + + return (buf); +} +#endif // (BT_EMB_PRESENT || HCI_BLE_CON_SUPPORT) + + +#if ((BLE_HOST_PRESENT) && (!BLE_EMB_PRESENT)) + +#if (HCI_BLE_CON_SUPPORT) +/** + **************************************************************************************** + * @brief Extract connection handle from a given format message + * + * This function returns the handle contained in a descriptor + * + * @param[in] code Kernel message containing the HCI command + * @param[in] payload Data + * @param[in] format String containning the format + * @return Connection Handle + ***************************************************************************************** + */ +static uint16_t hci_look_for_conhdl(uint8_t code, uint8_t *payload, uint8_t *format) +{ + uint8_t *params = payload; + uint8_t index = 0; + uint16_t conhdl = GAP_INVALID_CONHDL; + + // Different frame format for CC events + if ((code == HCI_CMD_CMP_EVT_CODE) || + (code == HCI_CMD_STATUS_EVT_CODE)) + { + params += HCI_CMD_OPCODE_LEN + HCI_CMDEVT_PARLEN_LEN; + } + + while(*(format + index) != '\0') + { + // Assume all parameters before connection handle are single bytes + if(*(format + index) == 'H') + { + // Read connection handle + conhdl = common_read16p(params + index); + break; + } + // Increment index + index++; + } + + return (conhdl); +} + +/** +**************************************************************************************** +* @brief Search if a CS is expected +* +* @param[in] code message code +* +* @return Connection index +***************************************************************************************** +*/ +static uint8_t hci_search_cs_index(uint8_t code) +{ + uint8_t idx = GAP_INVALID_CONIDX; + + for (uint8_t i=0; isrc_id; + uint16_t par_len = msg->param_len; + uint8_t status = COMMON_UTIL_PACK_ERROR; + + // Look for the command descriptor + const struct hci_cmd_desc_tag* cmd_desc = hci_look_for_cmd_desc(opcode); + + if((cmd_desc != NULL) && (par_len > 0)) + { + if(cmd_desc->par_fmt != NULL) + { + // Check if the generic packer can be used (basic fixed-length format) + if(!(cmd_desc->dest_field & HCI_CMD_DEST_SPEC_PAR_PK_MSK)) + { + // Pack the returned parameters using the generic packer + status = common_util_pack(param, param, &par_len, par_len, cmd_desc->par_fmt); + + #if ((HCI_BLE_CON_SUPPORT) && (BLE_HOST_PRESENT) && (!BLE_EMB_PRESENT)) + // Check if CS is expected + + uint8_t hl_type = (cmd_desc->dest_field & HCI_CMD_DEST_HL_MASK) >> HCI_CMD_DEST_HL_POS; + if ((hl_type == HL_CTRL) && (cmd_desc->ret_par_fmt == NULL)) + { + // Parse connection handle + uint16_t conhdl = hci_look_for_conhdl(opcode, param, (uint8_t *)cmd_desc->par_fmt); + // Save code in order to route CS correctly + if (conhdl != GAP_INVALID_CONHDL) + { + // dest_id actually contains the connection index + hci_env.ble_acl_con_tab[msg->dest_id].code = opcode; + } + else + { + BLE_ASSERT_INFO(0, opcode, conhdl); + } + } + #endif //((HCI_BLE_CON_SUPPORT) && (BLE_HOST_PRESENT) && (!BLE_EMB_PRESENT)) + } + else + { + // Pack the return parameters using the special packer + status = ((hci_pkupk_func_t)cmd_desc->par_fmt)(param, param, &par_len, par_len); + } + } + + BLE_ASSERT_INFO((status == COMMON_UTIL_PACK_OK), status, opcode); + } + // command with empty parameters + else if((cmd_desc != NULL) && (par_len == 0)) + { + status = COMMON_UTIL_PACK_OK; + } + else + { + // Command not found + BLE_ASSERT_INFO(0, par_len, opcode); + } + + //pack command opcode + common_write16p(pk, common_htobs(opcode)); + pk += 2; + + //pack command parameter length + *pk++ = par_len; + + return (status == COMMON_UTIL_PACK_OK) ? buf : NULL; +} +#endif // ((BLE_HOST_PRESENT) && (!BLE_EMB_PRESENT)) + +/** + **************************************************************************************** + * @brief Check if a transmission has to be done and start it. + ***************************************************************************************** + */ +static void hci_tx_start(void) +{ + struct kernel_msg *msg; + + do + { + // Check default TX queue + msg = (struct kernel_msg *)common_list_pick(&hci_tl_env.tx_queue); + if (msg != NULL) + break; + + #if (BT_EMB_PRESENT) + #if VOICE_OVER_HCI + // Check SYNC data flow control + if (hci_fc_check_host_available_nb_sync_packets()) + { + msg = (struct kernel_msg *)common_list_pick(&hci_tl_env.sync_queue); + if (msg != NULL) + break; + } + #endif //VOICE_OVER_HCI + #endif //(BT_EMB_PRESENT) + + #if (BT_EMB_PRESENT || (HCI_BLE_CON_SUPPORT && BLE_EMB_PRESENT)) + // Check ACL data flow control + if (hci_fc_check_host_available_nb_acl_packets()) + { + // Check ACL data queue + msg = (struct kernel_msg *) common_list_pick(&hci_tl_env.acl_queue); + if (msg != NULL) + break; + } + #elif (HCI_BLE_CON_SUPPORT && BLE_HOST_PRESENT) + // Check ACL TX queue + msg = (struct kernel_msg *)common_list_pick(&hci_tl_env.acl_queue); + if (msg != NULL) + break; + #endif //(BT_EMB_PRESENT || (HCI_BLE_CON_SUPPORT && BLE_EMB_PRESENT)) + + } while(0); + + + if (msg != NULL) + { + uint8_t *buf = NULL; + uint16_t len = 0; + uint8_t type = 0; + + // Store message of the packet under transmission + hci_tl_env.curr_tx_msg = msg; + + // Check what kind of TX packet + switch(msg->id) + { + #if (BLE_EMB_PRESENT || BT_EMB_PRESENT) + case HCI_CMD_CMP_EVENT: + { + // Increase the number of commands available for reception + if(hci_tl_env.nb_h2c_cmd_pkts < HCI_NB_CMD_PKTS) + { + hci_tl_env.nb_h2c_cmd_pkts++; + } + // Build the HCI event + buf = hci_build_cc_evt(msg); + + // Extract information (buffer, length, type) + len = HCI_EVT_HDR_LEN + *(buf + HCI_EVT_CODE_LEN); + type = HCI_EVT_MSG_TYPE; + } + break; + case HCI_CMD_STAT_EVENT: + { + // Increase the number of commands available for reception + if(hci_tl_env.nb_h2c_cmd_pkts < HCI_NB_CMD_PKTS) + { + hci_tl_env.nb_h2c_cmd_pkts++; + } + + // Build the HCI event + buf = hci_build_cs_evt(msg); + + // Extract information (buffer, length, type) + len = HCI_EVT_HDR_LEN + *(buf + HCI_EVT_CODE_LEN); + type = HCI_EVT_MSG_TYPE; + } + break; + case HCI_EVENT: + { + // Build the HCI event + buf = hci_build_evt(msg); + + // Extract information (buffer, length, type) + len = HCI_EVT_HDR_LEN + *(buf + HCI_EVT_CODE_LEN); + type = HCI_EVT_MSG_TYPE; + } + break; + #if BLE_EMB_PRESENT + case HCI_LE_EVENT: + { + // Build the HCI event + buf = hci_build_le_evt(msg); + + // Extract information (buffer, length, type) + len = HCI_EVT_HDR_LEN + *(buf + HCI_EVT_CODE_LEN); + type = HCI_EVT_MSG_TYPE; + } + break; + #endif //BLE_EMB_PRESENT + #if (BT_EMB_PRESENT || HCI_BLE_CON_SUPPORT) + case HCI_ACL_DATA: + { + // Build the HCI data packet from Kernel message + buf = hci_build_acl_data(msg); + + // Extract information (buffer, length, type) + len = HCI_ACL_HDR_LEN + common_read16p(buf + HCI_ACL_HDR_HDL_FLAGS_LEN); + type = HCI_ACL_MSG_TYPE; + } + break; + #endif // (BT_EMB_PRESENT || HCI_BLE_CON_SUPPORT) + #if BT_EMB_PRESENT + #if VOICE_OVER_HCI + case HCI_SYNC_DATA: + { + // Build the HCI data packet from Kernel message + buf = hci_build_sync_data(msg); + + // Extract information (buffer, length, type) + len = HCI_SYNC_HDR_LEN + *(buf + HCI_SYNC_HDR_DATA_LEN_POS); + type = HCI_SYNC_MSG_TYPE; + } + break; + #endif //VOICE_OVER_HCI + #endif //BT_EMB_PRESENT + #endif //(BLE_EMB_PRESENT || BT_EMB_PRESENT) + + #if ((BLE_HOST_PRESENT) && (!BLE_EMB_PRESENT)) + case HCI_COMMAND: + { + // Build the HCI command + buf = hci_build_cmd(msg); + + // Extract information (buffer, length, type) + len = HCI_CMD_HDR_LEN + *(buf + HCI_CMD_OPCODE_LEN); + type = HCI_CMD_MSG_TYPE; + } + break; + + #if (HCI_BLE_CON_SUPPORT) + case HCI_ACL_DATA: + { + // Build the HCI data packet from Kernel message + buf = hci_build_acl_data(msg); + + // Extract information (buffer, length, type) + len = HCI_ACL_HDR_LEN + common_read16p(buf + HCI_ACL_HDR_HDL_FLAGS_LEN); + type = HCI_ACL_MSG_TYPE; + } + break; + #endif // (HCI_BLE_CON_SUPPORT) + #endif // ((BLE_HOST_PRESENT) && (!BLE_EMB_PRESENT)) + + #if (BLE_EMB_PRESENT || BT_EMB_PRESENT) + // only one debug event supported for the moment, so flag to be + // removed as soon as more debug event are supported + #if (RW_DEBUG) + case HCI_DBG_EVT: + { + // Build the DBG event + buf = hci_build_dbg_evt(msg); + + // Extract information (buffer, length, type) + len = HCI_EVT_HDR_LEN + *(buf + HCI_EVT_CODE_LEN); + type = HCI_EVT_MSG_TYPE; + } + break; + #endif // (RW_DEBUG) + #endif // (BLE_EMB_PRESENT || BT_EMB_PRESENT) + + default: + { + BLE_ASSERT_INFO(0, msg->id, 0); + } + break; + } + + // Set TX state + hci_tl_env.tx_state = HCI_STATE_TX_ONGOING; + + #if (H4TL_SUPPORT) + // Forward the message to the H4TL for immediate transmission + h4tl_write(type, buf, len, &hci_tx_done); + #endif //(H4TL_SUPPORT) + } +} + +/** + **************************************************************************************** + * @brief Function called after sending message through UART, to free kernel_msg space and + * push the next message for transmission if any. + * + * The message is popped from the tx queue kept in hci_tl_env and freed using kernel_msg_free. + ***************************************************************************************** + */ +static void hci_tx_done(void) +{ + struct kernel_msg *msg = hci_tl_env.curr_tx_msg; + GLOBAL_INT_DIS(); + + #if (BLE_EMB_PRESENT) + #if (BLE_OBSERVER) + // Check advertising report flow control mechanism + hci_ble_adv_report_tx_check(msg); + #endif // (BLE_OBSERVER) + #endif // (BLE_EMB_PRESENT) + + // Go back to IDLE state + hci_tl_env.tx_state = HCI_STATE_TX_IDLE; + + // Free the message resources + switch(msg->id) + { + case HCI_EVENT: + #if (BLE_EMB_PRESENT) + case HCI_LE_EVENT: + #endif // (BLE_EMB_PRESENT) + #if (RW_DEBUG) + case HCI_DBG_EVT: + #endif // (RW_DEBUG) + case HCI_CMD_CMP_EVENT: + case HCI_CMD_STAT_EVENT: + case HCI_COMMAND: + { + // Nothing to do + } + break; + #if (BT_EMB_PRESENT || HCI_BLE_CON_SUPPORT) + case HCI_ACL_DATA: + { + // Pop message from HCI parameters + struct hci_acl_data *data_msg = (struct hci_acl_data *) kernel_msg2param(msg); + // Pop message from data queue + common_list_pop_front(&hci_tl_env.acl_queue); + + #if (BT_EMB_PRESENT || BLE_EMB_PRESENT) + // Get connection handle + uint16_t conhdl = GETF(data_msg->conhdl_pb_bc_flag, HCI_ACL_HDR_HDL); + #endif // (BT_EMB_PRESENT || BLE_EMB_PRESENT) + + #if (HCI_BLE_CON_SUPPORT) + #if (BLE_EMB_PRESENT) + // If connection is BLE + if(conhdl <= BLE_CONHDL_MAX) + { + // Free the RX buffer associated with the message + ble_util_buf_rx_free((uint16_t) data_msg->buf_ptr); + } + #elif (BLE_HOST_PRESENT) + // free ACL TX buffer + kernel_free((uint8_t *) data_msg->buf_ptr - (HCI_ACL_HDR_LEN + HCI_TRANSPORT_HDR_LEN)); + #endif // (BLE_EMB_PRESENT) + #endif // (HCI_BLE_CON_SUPPORT) + + #if (BT_EMB_PRESENT) + // If connection is BT + if((conhdl >= BT_ACL_CONHDL_MIN) && (conhdl <= BT_ACL_CONHDL_MAX)) + { + // Free the RX buffer associated with the message + bt_util_buf_acl_rx_free((uint16_t) data_msg->buf_ptr); + } + #endif //BT_EMB_PRESENT + + hci_tl_env.curr_tx_msg = NULL; + + #if (BLE_EMB_PRESENT || BT_EMB_PRESENT) + //count packets for flow control + hci_fc_acl_packet_sent(); + #endif // (BT_EMB_PRESENT || BLE_EMB_PRESENT) + } + break; + #endif // (BT_EMB_PRESENT || HCI_BLE_CON_SUPPORT) + #if (BT_EMB_PRESENT) + #if VOICE_OVER_HCI + case HCI_SYNC_DATA: + { + struct hci_sync_data *data_rx; + // Pop event from the event queue + msg = (struct kernel_msg *)common_list_pop_front(&hci_tl_env.sync_queue); + data_rx = (struct hci_sync_data *)(msg->param); + // Free the RX buffer associated with the message + bt_util_buf_sync_rx_free(BT_SYNC_CONHDL_LID(GETF(data_rx->conhdl_psf, HCI_SYNC_HDR_HDL)), data_rx->buf_ptr); + hci_tl_env.curr_tx_msg = NULL; + //count packets for flow control + hci_fc_sync_packet_sent(); + } + break; + #endif //VOICE_OVER_HCI + #endif // (BT_EMB_PRESENT) + default: + { + BLE_ASSERT_INFO(0, msg->id, 0); + } + break; + } + + if (hci_tl_env.curr_tx_msg != NULL) + { + // Pop event from the event queue + msg = (struct kernel_msg *)common_list_pop_front(&hci_tl_env.tx_queue); + } + + // Free the kernel message space + kernel_msg_free(msg); + + GLOBAL_INT_RES(); + + // Check if there is a new message pending for transmission + hci_tx_start(); +} + +/** + **************************************************************************************** + * @brief Trigger the transmission over HCI TL if possible + ***************************************************************************************** + */ +static void hci_tx_trigger(void) +{ + // Check if there is no transmission ongoing + if (hci_tl_env.tx_state == HCI_STATE_TX_IDLE) + { + // Start the transmission + hci_tx_start(); + } +} + + +/* + * MODULES INTERNAL FUNCTION DEFINITIONS + **************************************************************************************** + */ + +void hci_tl_send(struct kernel_msg *msg) +{ + GLOBAL_INT_DIS(); + + /// put the message into corresponding queue + switch(msg->id) + { + #if (BT_EMB_PRESENT || HCI_BLE_CON_SUPPORT) + case HCI_ACL_DATA: + { + common_list_push_back(&hci_tl_env.acl_queue, &msg->hdr); + } + break; + #endif //(BT_EMB_PRESENT || HCI_BLE_CON_SUPPORT) + + #if (BT_EMB_PRESENT) + #if VOICE_OVER_HCI + case HCI_SYNC_DATA: + { + common_list_push_back(&hci_tl_env.sync_queue, &msg->hdr); + } + break; + #endif //VOICE_OVER_HCI + #endif //(BT_EMB_PRESENT) + default: + { + #if (BLE_EMB_PRESENT) + #if (BLE_OBSERVER) + // Flow control ADV reports + if(hci_ble_adv_report_filter_check(msg)) + break; + #endif // (BLE_OBSERVER) + #endif // (BLE_EMB_PRESENT) + + // Push the message into the HCI queue + common_list_push_back(&hci_tl_env.tx_queue, &msg->hdr); + } + break; + } + + GLOBAL_INT_RES(); + + // Trigger the HCI transmission + hci_tx_trigger(); +} + + +/* + * EXPORTED FUNCTION DEFINITIONS + **************************************************************************************** + */ + +void hci_tl_init(uint8_t init_type) +{ + if(!init_type) + { + // Reset the HCI environment + memset(&hci_tl_env, 0, sizeof(hci_tl_env)); + + // Initialize the HCI event transmit queues + common_list_init(&hci_tl_env.tx_queue); + + #if (BT_EMB_PRESENT || HCI_BLE_CON_SUPPORT) + // Initialize the BT ACL transmit queues + common_list_init(&hci_tl_env.acl_queue); + #endif //(BT_EMB_PRESENT || HCI_BLE_CON_SUPPORT) + + #if (BT_EMB_PRESENT) + #if VOICE_OVER_HCI + // Initialize the BT SYNC transmit queues + common_list_init(&hci_tl_env.sync_queue); + #endif //VOICE_OVER_HCI + #endif //(BT_EMB_PRESENT) + + + // Initialize TX state machine + hci_tl_env.tx_state = HCI_STATE_TX_IDLE; + } + // Initialize the number of HCI commands the stack can handle simultaneously + hci_tl_env.nb_h2c_cmd_pkts = HCI_NB_CMD_PKTS; +} + +#if (BLE_EMB_PRESENT || BT_EMB_PRESENT) +uint8_t hci_cmd_get_max_param_size(uint16_t opcode) +{ + uint16_t max_param_size = HCI_MAX_CMD_PARAM_SIZE; + + // Find a command descriptor associated to the command opcode + const struct hci_cmd_desc_tag* cmd_desc = hci_look_for_cmd_desc(opcode); + + // Check if the command is supported + if(cmd_desc != NULL) + { + max_param_size = cmd_desc->par_size_max; + } + + return (uint8_t) max_param_size; +} + +void hci_cmd_received(uint16_t opcode, uint8_t length, uint8_t *payload) +{ + // Find a command descriptor associated to the command opcode + const struct hci_cmd_desc_tag* cmd_desc = hci_look_for_cmd_desc(opcode); + + #if (BLE_EMB_PRESENT && BLE_HOST_PRESENT && HCI_TL_SUPPORT) + // HCI used by external Host + hci_ext_host = true; + #endif // (BLE_EMB_PRESENT && BLE_HOST_PRESENT && HCI_TL_SUPPORT) + + // Decrease the number of commands available for reception + if(hci_tl_env.nb_h2c_cmd_pkts > INT8_MIN) + hci_tl_env.nb_h2c_cmd_pkts--; + + // Check if the command is supported + if(cmd_desc != NULL) + { + // Check if a new command can be received + if (hci_tl_env.nb_h2c_cmd_pkts >= 0) + { + uint16_t dest = TASK_BLE_NONE; + uint8_t ll_type = (cmd_desc->dest_field & HCI_CMD_DEST_LL_MASK) >> HCI_CMD_DEST_LL_POS; + + // Find the lower layers destination task + switch(ll_type) + { + #if BT_EMB_PRESENT + case BT_MNG: + case MNG: + { + dest = TASK_BLE_LM; + } + break; + case BT_BCST: + { + dest = TASK_BLE_LB; + } + break; + #endif //BT_EMB_PRESENT + #if BLE_EMB_PRESENT + case BLE_MNG: + #if !BT_EMB_PRESENT + case MNG: + #endif //BT_EMB_PRESENT + { + dest = TASK_BLE_LLM; + } + break; + #endif //BLE_EMB_PRESENT + case DBG: + { + dest = TASK_BLE_DBG; + } + break; + #if (BT_EMB_PRESENT || (BLE_EMB_PRESENT && (HCI_BLE_CON_SUPPORT))) + #if BT_EMB_PRESENT + case BT_CTRL_CONHDL: + case BT_CTRL_BD_ADDR: + #endif //BT_EMB_PRESENT + #if (BLE_EMB_PRESENT && (HCI_BLE_CON_SUPPORT)) + case BLE_CTRL: + #endif //(BLE_EMB_PRESENT && (HCI_BLE_CON_SUPPORT)) + case CTRL: + { + #if BT_EMB_PRESENT + if(ll_type == BT_CTRL_BD_ADDR) + { + if(length >= sizeof(struct bd_addr)) + { + // Look for a BD address matching in the table + for(int i = 0 ; i < MAX_NB_ACTIVE_ACL ; i++) + { + // Check BT connection state and BD address (assuming BD address is located at payload 1st 6 bytes) + if( (hci_env.bt_acl_con_tab[i].state != HCI_BT_ACL_STATUS_NOT_ACTIVE) + && (!memcmp(payload, &hci_env.bt_acl_con_tab[i].bd_addr.addr[0], sizeof(struct bd_addr))) ) + { + // Build the destination task ID + dest = KERNEL_BUILD_ID(TASK_BLE_LC, i); + break; + } + } + } + } + else + #endif //BT_EMB_PRESENT + { + // Check if the parameters can contain a connection handle + if(length >= 2) + { + // Retrieve connection handle from command parameters (expecting at payload 1st 2 bytes) + uint16_t conhdl = common_btohs(common_read16p(payload)); + + #if (BLE_EMB_PRESENT && (HCI_BLE_CON_SUPPORT)) + // Check if the connection handle corresponds to an active BLE link + if((conhdl <= BLE_CONHDL_MAX) && hci_env.ble_con_state[conhdl]) + { + // Build the destination task ID + dest = KERNEL_BUILD_ID(TASK_BLE_LLC, conhdl); + } + #endif //(BLE_EMB_PRESENT && (HCI_BLE_CON_SUPPORT)) + + #if BT_EMB_PRESENT + // Check if the connection handle corresponds to an active BT link (ACL or SCO) + conhdl &= ~(BT_SYNC_CONHDL_MSK); + if((conhdl >= BT_ACL_CONHDL_MIN) && (conhdl <= BT_ACL_CONHDL_MAX)) + { + if(hci_env.bt_acl_con_tab[(conhdl - BT_ACL_CONHDL_MIN)].state == HCI_BT_ACL_STATUS_BD_ADDR_CONHDL) + { + // Build the destination task ID + dest = KERNEL_BUILD_ID(TASK_BLE_LC, conhdl - BT_ACL_CONHDL_MIN); + } + } + #endif //BT_EMB_PRESENT + } + } + + // Reject command if not possible to match a valid connection + if(dest == TASK_BLE_NONE) + { + // Reject the command with error code "Unknown connection identifier" + hci_cmd_reject(cmd_desc, opcode, COMMON_ERROR_UNKNOWN_CONNECTION_ID, payload); + } + } + break; + #if (BLE_EMB_PRESENT && BLE_ISO_PRESENT) + case BLE_ISO: + { + dest = TASK_BLE_LLI; + } + break; + #endif // (BLE_EMB_PRESENT && BLE_ISO_PRESENT) + #endif // (BT_EMB_PRESENT || (BLE_EMB_PRESENT && (HCI_BLE_CON_SUPPORT))) + default: + { + BLE_ASSERT_INFO(0, ll_type, opcode); + } + break; + } + + // Check if the command can be handled by the controller + if(dest != TASK_BLE_NONE) + { + uint16_t unpk_length = 0; + uint8_t status = COMMON_UTIL_PACK_OK; + + // Check if there are parameters (to compute the unpacked parameters size for Kernel message allocation) + if (length > 0) + { + if(cmd_desc->par_fmt != NULL) + { + // Check if the generic packer can be used (basic fixed-length format) + if(!(cmd_desc->dest_field & HCI_CMD_DEST_SPEC_PAR_PK_MSK)) + { + // Compute the space needed for unpacked parameters + status = common_util_unpack(NULL, payload, &unpk_length, length, cmd_desc->par_fmt); + } + else + { + status = ((hci_pkupk_func_t)cmd_desc->par_fmt)(NULL, payload, &unpk_length, length); + } + } + else + { + status = COMMON_UTIL_PACK_ERROR; + } + } + + // Check if there is input buffer overflow (received parameter size is less than expected for this command) + if(status == COMMON_UTIL_PACK_IN_BUF_OVFLW) + { + // Reject the command with error code "Invalid HCI parameters" + hci_cmd_reject(cmd_desc, opcode, COMMON_ERROR_INVALID_HCI_PARAM, NULL); + } + else + { + // Allocate a Kernel message (with space for unpacked parameters) + void* cmd = kernel_msg_alloc(HCI_COMMAND, dest, opcode, unpk_length); + + BLE_ASSERT_INFO(status == COMMON_UTIL_PACK_OK, status, opcode); + + if(cmd == NULL) + { + // Reject the command with error code "Memory Capacity Exceeded" + hci_cmd_reject(cmd_desc, opcode, COMMON_ERROR_MEMORY_CAPA_EXCEED, NULL); + } + else + { + // Check if there are parameters to unpack + if ((unpk_length > 0) && (cmd_desc->par_fmt != NULL)) + { + // Check if the generic packer can be used (basic fixed-length format) + if(!(cmd_desc->dest_field & HCI_CMD_DEST_SPEC_PAR_PK_MSK)) + { + // Unpack parameters + status = common_util_unpack((uint8_t*) cmd, payload, &unpk_length, length, cmd_desc->par_fmt); + } + else + { + status = ((hci_pkupk_func_t)cmd_desc->par_fmt)((uint8_t*) cmd, payload, &unpk_length, length); + } + } + + BLE_ASSERT_INFO(status == COMMON_UTIL_PACK_OK, status, opcode); + + // Send the command to the internal destination task associated to this command + kernel_msg_send(cmd); + } + } + } + } + else + { + // Reject the command with error code "Memory Capacity Exceeded" + hci_cmd_reject(cmd_desc, opcode, COMMON_ERROR_MEMORY_CAPA_EXCEED, NULL); + } + } + else + { + // Reject the command with error code "Unknown HCI Command" + hci_cmd_reject(NULL, opcode, COMMON_ERROR_UNKNOWN_HCI_COMMAND, NULL); + } +} + +uint8_t* hci_acl_tx_data_alloc(uint16_t hdl_flags, uint16_t len) +{ + uint8_t* buf = NULL; + uint16_t dest = TASK_BLE_NONE; + uint16_t max_len = 0; + + #if ((BLE_EMB_PRESENT && (HCI_BLE_CON_SUPPORT)) || BT_EMB_PRESENT) + // Retrieve connection handle from command parameters (expecting at payload 1st 2 bytes) + uint16_t conhdl = GETF(hdl_flags, HCI_ACL_HDR_HDL); + uint8_t bc_flag = GETF(hdl_flags, HCI_ACL_HDR_BC_FLAG); + #endif // ((BLE_EMB_PRESENT && (HCI_BLE_CON_SUPPORT)) || BT_EMB_PRESENT) + + #if (BLE_EMB_PRESENT && (HCI_BLE_CON_SUPPORT)) + // Check if the connection handle corresponds to an active BLE link + if((conhdl <= BLE_CONHDL_MAX) && (bc_flag == BCF_P2P)) + { + // Build the destination task ID + dest = KERNEL_BUILD_ID(TASK_BLE_LLC, conhdl); + max_len = BLE_MAX_OCTETS; + } + #endif //(BLE_EMB_PRESENT && (HCI_BLE_CON_SUPPORT)) + + #if BT_EMB_PRESENT + // Check if broadcast flags are set + if (bc_flag == BCF_ACTIVE_SLV_BCST) + { + dest = TASK_BLE_LB; + max_len = ACL_DATA_BUF_SIZE; + } + // Check if the connection handle corresponds to an active BT link + else if(((bc_flag & BCF_MASK) == BCF_P2P) && (conhdl >= BT_ACL_CONHDL_MIN) && (conhdl <= BT_ACL_CONHDL_MAX)) + { + if(hci_env.bt_acl_con_tab[(conhdl - BT_ACL_CONHDL_MIN)].state == HCI_BT_ACL_STATUS_BD_ADDR_CONHDL) + { + // Build the destination task ID + dest = KERNEL_BUILD_ID(TASK_BLE_LC, conhdl - BT_ACL_CONHDL_MIN); + max_len = ACL_DATA_BUF_SIZE; + } + } + #endif //BT_EMB_PRESENT + + // Check if the requested size fits within BT/BLE data max length + if((dest != TASK_BLE_NONE) && (len <= max_len)) + { + switch(KERNEL_TYPE_GET(dest)) + { + #if (BLE_EMB_PRESENT && (HCI_BLE_CON_SUPPORT)) + case TASK_BLE_LLC: + { + // Try allocating a buffer from BLE pool + uint16_t buf_ptr = ble_util_buf_acl_tx_alloc(); + + if(buf_ptr != 0) + { + // Give the pointer to the data space + buf = (uint8_t*) (EM_BASE_ADDR + buf_ptr); + } + } + break; + #endif //(BLE_EMB_PRESENT && (HCI_BLE_CON_SUPPORT)) + + #if BT_EMB_PRESENT + case TASK_BLE_LC: + case TASK_BLE_LB: + { + // Try allocating a buffer from BT pool + uint16_t buf_ptr = bt_util_buf_acl_tx_alloc(); + + if(buf_ptr != 0) + { + // Give the pointer to the data space + buf = (uint8_t*) (EM_BASE_ADDR + buf_ptr); + } + } + break; + #endif //BT_EMB_PRESENT + + default: + { + BLE_ASSERT_ERR(0); + } + break; + } + + if(buf == NULL) + { + // Report buffer oveflow + struct hci_data_buf_ovflw_evt * evt = KERNEL_MSG_ALLOC(HCI_EVENT, 0, HCI_DATA_BUF_OVFLW_EVT_CODE, hci_data_buf_ovflw_evt); + evt->link_type = ACL_TYPE; + hci_send_2_host(evt); + + // Allocate a temporary buffer from heap + buf = kernel_malloc(len, KERNEL_MEM_KERNEL_MSG); + + // Indicate the reception of ACL payload in a trash buffer + hci_tl_env.acl_trash_payload = true; + } + } + + return buf; +} + +void hci_acl_tx_data_received(uint16_t hdl_flags, uint16_t datalen, uint8_t * payload) +{ + do + { + #if ((BLE_EMB_PRESENT && (HCI_BLE_CON_SUPPORT)) || BT_EMB_PRESENT) + uint16_t conhdl = GETF(hdl_flags, HCI_ACL_HDR_HDL); + #if BT_EMB_PRESENT + uint8_t bc_flag = GETF(hdl_flags, HCI_ACL_HDR_BC_FLAG); + #endif //BT_EMB_PRESENT + #endif // ((BLE_EMB_PRESENT && (HCI_BLE_CON_SUPPORT)) || BT_EMB_PRESENT) + + // If payload is received in trash buffer + if(hci_tl_env.acl_trash_payload) + { + // Free the temporary buffer + kernel_free(payload); + + // Clear the indication of ACL payload reception in a trash buffer + hci_tl_env.acl_trash_payload = false; + + break; + } + + #if (HCI_BLE_CON_SUPPORT) + // Check if the received packet was considered BLE one at header reception + if(conhdl <= BLE_CONHDL_MAX) + { + // Allocate a Kernel message + struct hci_acl_data* data_tx = KERNEL_MSG_ALLOC(HCI_ACL_DATA, KERNEL_BUILD_ID(TASK_BLE_LLC, conhdl), 0, hci_acl_data); + data_tx->conhdl_pb_bc_flag = hdl_flags; + data_tx->length = datalen; + data_tx->buf_ptr = (datalen > 0) ? (((uint32_t) payload) - EM_BASE_ADDR) : 0; + kernel_msg_send(data_tx); + + break; + } + #endif //(HCI_BLE_CON_SUPPORT) + + #if BT_EMB_PRESENT + // Check if the received packet was considered BT one at header reception + if( ((bc_flag == BCF_ACTIVE_SLV_BCST) || ((conhdl >= BT_ACL_CONHDL_MIN) && (conhdl <= BT_ACL_CONHDL_MAX))) ) + { + // Select the destination task, according to the broadcast flag + uint16_t dest_id = (bc_flag == BCF_ACTIVE_SLV_BCST) ? TASK_BLE_LB : KERNEL_BUILD_ID(TASK_BLE_LC, conhdl - BT_ACL_CONHDL_MIN); + + // Allocate a Kernel message + struct hci_acl_data* data_tx = KERNEL_MSG_ALLOC(HCI_ACL_DATA, dest_id, 0, hci_acl_data); + data_tx->conhdl_pb_bc_flag = hdl_flags; + data_tx->length = datalen; + data_tx->buf_ptr = (datalen > 0) ? (((uint32_t) payload) - EM_BASE_ADDR) : 0; + kernel_msg_send(data_tx); + + break; + } + #endif //BT_EMB_PRESENT + + BLE_ASSERT_INFO(0, datalen, hdl_flags); + } while(0); +} + +#if (BT_EMB_PRESENT) +#if (VOICE_OVER_HCI) +uint8_t* hci_sync_tx_data_alloc(uint16_t conhdl_flags, uint8_t len) +{ + uint8_t* buf = NULL; + + // Retrieve connection handle from command parameters (expecting at payload 1st 2 bytes) + uint16_t conhdl = GETF(conhdl_flags, HCI_SYNC_HDR_HDL); + uint8_t sync_link_id = BT_SYNC_CONHDL_LID(conhdl); + + // There are many conditions where the packet is not valid (invalid connection handle, no SCO link, not in Voice over HCI) + do + { + // Check if the connection handle corresponds to a possible synchronous link + if(sync_link_id >= MAX_NB_SYNC) + break; + + // Check if the connection handle corresponds to a possible an BT link + conhdl &= ~(BT_SYNC_CONHDL_MSK); + if((conhdl < BT_ACL_CONHDL_MIN) && (conhdl > BT_ACL_CONHDL_MAX)) + break; + + // Check if the ACL link is active + if(hci_env.bt_acl_con_tab[(conhdl - BT_ACL_CONHDL_MIN)].state != HCI_BT_ACL_STATUS_BD_ADDR_CONHDL) + break; + + // Try allocating a buffer from BT pool + buf = (uint8_t *) (uint32_t) bt_util_buf_sync_tx_alloc(sync_link_id, len); + + } while (0); + + // If a buffer element has been allocated + if(buf != 0) + { + // Give the pointer to the data space + buf += EM_BASE_ADDR; + } + else + { + // Allocate a temporary buffer from heap + buf = kernel_malloc(len, KERNEL_MEM_KERNEL_MSG); + + // Indicate the reception of ACL payload in a trash buffer + hci_tl_env.acl_trash_payload = true; + } + + return buf; +} + +void hci_sync_tx_data_received(uint16_t conhdl_flags, uint8_t len, uint8_t * payload) +{ + uint16_t conhdl = GETF(conhdl_flags, HCI_SYNC_HDR_HDL); + conhdl &= ~(BT_SYNC_CONHDL_MSK); + + // Check if the received packet is in a valid buffer + if(!hci_tl_env.acl_trash_payload) + { + // Sends the Kernel message (with space for unpacked parameters) + struct hci_sync_data* data_tx = KERNEL_MSG_ALLOC(HCI_SYNC_DATA, KERNEL_BUILD_ID(TASK_BLE_LC, conhdl - BT_ACL_CONHDL_MIN), 0, hci_sync_data); + data_tx->buf_ptr = (uint16_t) ((uint32_t)payload - EM_BASE_ADDR); + data_tx->conhdl_psf = conhdl_flags; + data_tx->length = len; + kernel_msg_send(data_tx); + } + else + { + // Free the temporary buffer + kernel_free(payload); + + // Clear the indication of ACL payload reception in a trash buffer + hci_tl_env.acl_trash_payload = false; + } +} + +#endif //(VOICE_OVER_HCI) +#endif //(BT_EMB_PRESENT) +#endif //(BLE_EMB_PRESENT || BT_EMB_PRESENT) + +#if (BLE_HOST_PRESENT && !BLE_EMB_PRESENT) +#if (HCI_BLE_CON_SUPPORT) +uint8_t* hci_acl_rx_data_alloc(uint16_t hdl_flags, uint16_t len) +{ + return kernel_malloc(len, KERNEL_MEM_NON_RETENTION); +} + +void hci_acl_rx_data_received(uint16_t hdl_flags, uint16_t datalen, uint8_t * payload) +{ + uint16_t conhdl = GETF(hdl_flags, HCI_ACL_HDR_HDL); + + // Get connection index + uint8_t idx = gapc_get_conidx(conhdl); + + if ((conhdl != GAP_INVALID_CONHDL) && + (idx != GAP_INVALID_CONIDX)) + { + // Allocate a Kernel message (with space for unpacked parameters) + struct hci_acl_data* data_rx = KERNEL_MSG_ALLOC(HCI_ACL_DATA, KERNEL_BUILD_ID(TASK_BLE_L2CC, idx), 0, hci_acl_data); + data_rx->conhdl_pb_bc_flag = hdl_flags; + + data_rx->length = datalen; + + // retrieve data buffer + data_rx->buf_ptr = (uint32_t) payload; + + // Send the kernel message + kernel_msg_send(data_rx); + } + else + { + BLE_ASSERT_INFO(0, conhdl, idx); + } +} +#endif // (HCI_BLE_CON_SUPPORT) + +uint8_t hci_evt_received(uint8_t code, uint8_t length, uint8_t *payload) +{ + uint8_t status = COMMON_UTIL_PACK_OK; + + switch(code) + { + case HCI_CMD_CMP_EVT_CODE: + { + if(length >= HCI_CCEVT_HDR_PARLEN) + { + // Retrieve opcode from parameters, expected at position 1 in payload (after nb cmp pkts) + uint16_t opcode = common_btohs(common_read16p(payload + 1)); + // Look for the command descriptor + const struct hci_cmd_desc_tag* cmd_desc = hci_look_for_cmd_desc(opcode); + + // Check if the command is supported + if(cmd_desc != NULL) + { + uint16_t dest = TASK_BLE_NONE; + uint8_t hl_type = (cmd_desc->dest_field & HCI_CMD_DEST_HL_MASK) >> HCI_CMD_DEST_HL_POS; + + // Find the higher layers destination task + switch(hl_type) + { + case HL_MNG: + { + // Build the destination task ID + dest = TASK_BLE_GAPM; + } + break; + case HL_CTRL: + case HL_DATA: + { +#if (HCI_BLE_CON_SUPPORT) + // Parse connection handle + uint16_t conhdl = hci_look_for_conhdl(code, payload, (uint8_t *)cmd_desc->ret_par_fmt); + // Get connection index + uint8_t idx = gapc_get_conidx(conhdl); + + if ((conhdl != GAP_INVALID_CONHDL) && + (idx != GAP_INVALID_CONIDX)) + { + // Build the destination task ID if found + dest = (hl_type == HL_CTRL) ? + KERNEL_BUILD_ID(TASK_BLE_GAPC, idx) : KERNEL_BUILD_ID(TASK_BLE_L2CC, idx); + } +#else + // Forward message to the first instance + dest = (hl_type == HL_CTRL) ? + TASK_BLE_GAPC : TASK_BLE_L2CC; +#endif //(HCI_BLE_CON_SUPPORT) + } + break; + #if (BLE_ISO_MODE_0) + case HL_ISO0: + { + // Parse connection handle + uint16_t conhdl = hci_look_for_conhdl(code, payload, (uint8_t *)cmd_desc->ret_par_fmt); + // Get connection index + uint8_t idx = gapc_get_conidx(conhdl); + + if ((conhdl != GAP_INVALID_CONHDL) && (idx != GAP_INVALID_CONIDX)) + { + // Build the destination task ID if found + dest = KERNEL_BUILD_ID(TASK_BLE_AM0, idx); + } + }break; + #endif // (BLE_ISO_MODE_0) + + default: + { + BLE_ASSERT_INFO(0, hl_type, opcode); + } + break; + } + + if(dest != TASK_BLE_NONE) + { + uint16_t unpk_length = length - HCI_CCEVT_HDR_PARLEN; + void* evt; + + // Check if there are parameters + if (unpk_length > 0) + { + if(cmd_desc->ret_par_fmt != NULL) + { + // Check if the generic packer can be used (basic fixed-length format) + if(!(cmd_desc->dest_field & HCI_CMD_DEST_SPEC_RET_PAR_PK_MSK)) + { + // Compute the space needed for unpacked parameters + status = common_util_unpack(NULL, NULL, &unpk_length, length - HCI_CCEVT_HDR_PARLEN, cmd_desc->ret_par_fmt); + } + else + { + status = ((hci_pkupk_func_t)cmd_desc->ret_par_fmt)(NULL, NULL, &unpk_length, length - HCI_CCEVT_HDR_PARLEN); + } + } + else + { + status = COMMON_UTIL_PACK_ERROR; + } + + BLE_ASSERT_INFO((status == COMMON_UTIL_PACK_OK), status, opcode); + } + + // Allocate a Kernel message (with space for unpacked parameters) + evt = kernel_msg_alloc(HCI_CMD_CMP_EVENT, dest, opcode, unpk_length); + + // Check if there are parameters to unpack + if (unpk_length > 0) + { + if(cmd_desc->ret_par_fmt != NULL) + { + // Check if the generic unpacker can be used (basic fixed-length format) + if(!(cmd_desc->dest_field & HCI_CMD_DEST_SPEC_RET_PAR_PK_MSK)) + { + // Unpack parameters + status = common_util_unpack((uint8_t*) evt, payload + HCI_CCEVT_HDR_PARLEN, &unpk_length, length - HCI_CCEVT_HDR_PARLEN, cmd_desc->ret_par_fmt); + } + else + { + status = ((hci_pkupk_func_t)cmd_desc->ret_par_fmt)((uint8_t*) evt, payload + HCI_CCEVT_HDR_PARLEN, &unpk_length, length - HCI_CCEVT_HDR_PARLEN); + } + } + } + + // Send the command to the internal destination task associated to this event + kernel_msg_send(evt); + } + else + { + BLE_ASSERT_INFO(0, hl_type, opcode); + } + } + else + { + BLE_ASSERT_INFO(0, opcode, 0); + } + } + else + { + BLE_ASSERT_INFO(0, length, 0); + } + } + break; + case HCI_CMD_STATUS_EVT_CODE: + { + if(length == HCI_CSEVT_PARLEN) + { + // Retrieve opcode from parameters, expected at position 2 in payload (after status and nb cmp pkts) + uint16_t opcode = common_btohs(common_read16p(payload + 2)); + // Look for the command descriptor + const struct hci_cmd_desc_tag* cmd_desc = hci_look_for_cmd_desc(opcode); + + // Check if the command is supported + if(cmd_desc != NULL) + { + uint16_t dest = TASK_BLE_NONE; + uint8_t hl_type = (cmd_desc->dest_field & HCI_CMD_DEST_HL_MASK) >> HCI_CMD_DEST_HL_POS; + + // Find the higher layers destination task + switch(hl_type) + { + case HL_MNG: + { + // Build the destination task ID + dest = TASK_BLE_GAPM; + } + break; + + case HL_CTRL: + case HL_DATA: + { +#if (HCI_BLE_CON_SUPPORT) + // Get connection index + uint8_t idx = hci_search_cs_index(opcode); + + if (idx != GAP_INVALID_CONIDX) + { + // Build the destination task ID if found + dest = (hl_type == HL_CTRL) ? + KERNEL_BUILD_ID(TASK_BLE_GAPC, idx) : KERNEL_BUILD_ID(TASK_BLE_L2CC, idx); + } +#else + // Forward message to the first instance + dest = (hl_type == HL_CTRL) ? + TASK_BLE_GAPC : TASK_BLE_L2CC; +#endif //(HCI_BLE_CON_SUPPORT) + } + break; + + default: + { + BLE_ASSERT_INFO(0, hl_type, opcode); + } + break; + } + + if(dest != TASK_BLE_NONE) + { + // Allocate a Kernel message (with space for unpacked parameters) + void* evt = kernel_msg_alloc(HCI_CMD_STAT_EVENT, dest, opcode, length); + + // Send the command to the internal destination task associated to this event + kernel_msg_send(evt); + } + else + { + BLE_ASSERT_INFO(0, hl_type, opcode); + } + } + else + { + BLE_ASSERT_INFO(0, opcode, 0); + } + } + else + { + BLE_ASSERT_INFO(0, length, 0); + } + } + break; + case HCI_LE_META_EVT_CODE: + default: + { + uint8_t code_or_subcode = code; + // Find an event descriptor associated to the event code + const struct hci_evt_desc_tag* evt_desc; + if(code_or_subcode == HCI_LE_META_EVT_CODE) + { + code_or_subcode = *payload; + evt_desc = hci_look_for_le_evt_desc(code_or_subcode); + } + else + { + evt_desc = hci_look_for_evt_desc(code_or_subcode); + } + + // Check if the evt is supported + if(evt_desc != NULL) + { + uint16_t dest = TASK_BLE_NONE; + uint8_t hl_type = (evt_desc->dest_field & HCI_EVT_DEST_HL_MASK) >> HCI_EVT_DEST_HL_POS; + + // Find the higher layers destination task + switch(hl_type) + { + case HL_MNG: + { + // Build the destination task ID + dest = TASK_BLE_GAPM; + } + break; + + case HL_CTRL: + case HL_DATA: + { + #if (HCI_BLE_CON_SUPPORT) + // Parse connection handle + uint16_t conhdl = hci_look_for_conhdl(code, payload, (uint8_t *)evt_desc->par_fmt); + // Get connection index + uint8_t idx = gapc_get_conidx(conhdl); + + if ((conhdl != GAP_INVALID_CONHDL) && (idx != GAP_INVALID_CONIDX)) + { + // Build the destination task ID if found + dest = (hl_type == HL_CTRL) ? KERNEL_BUILD_ID(TASK_BLE_GAPC, idx) : KERNEL_BUILD_ID(TASK_BLE_L2CC, idx); + } + else + { + dest = HL_MNG; // let manager to forward message later + } + + #else + // Forward message to the first instance + dest = (hl_type == HL_CTRL) ? TASK_BLE_GAPC : TASK_BLE_L2CC; + #endif //(HCI_BLE_CON_SUPPORT) + } + break; + + default: + { + BLE_ASSERT_INFO(0, hl_type, code); + } + break; + } + + if(dest != TASK_BLE_NONE) + { + uint16_t unpk_length = 0; + void* evt; + + // Check if there are parameters + if (length > 0) + { + if(evt_desc->par_fmt != NULL) + { + // Check if the generic packer can be used (basic fixed-length format) + if(evt_desc->special_pack == PK_GEN) + { + // Compute the space needed for unpacked parameters + status = common_util_unpack(NULL, NULL, &unpk_length, length, evt_desc->par_fmt); + } + else + { + status = ((hci_pkupk_func_t)evt_desc->par_fmt)(NULL, NULL, &unpk_length, length); + } + + BLE_ASSERT_INFO((status == COMMON_UTIL_PACK_OK), status, code); + } + else + { + status = COMMON_UTIL_PACK_ERROR; + } + } + + // Allocate a Kernel message (with space for unpacked parameters) + if(code == HCI_LE_META_EVT_CODE) + { + evt = kernel_msg_alloc(HCI_LE_EVENT, dest, 0, unpk_length); + } + else + { + evt = kernel_msg_alloc(HCI_EVENT, dest, code_or_subcode, unpk_length); + } + + // Check if there are parameters to unpack + if (unpk_length > 0) + { + if(evt_desc->par_fmt != NULL) + { + // Check if the generic unpacker can be used (basic fixed-length format) + if(evt_desc->special_pack == PK_GEN) + { + // Unpack parameters + status = common_util_unpack((uint8_t*) evt, payload, &unpk_length, length, evt_desc->par_fmt); + } + else + { + status = ((hci_pkupk_func_t)evt_desc->par_fmt)((uint8_t*) evt, payload, &unpk_length, length); + } + } + + BLE_ASSERT_INFO((status == COMMON_UTIL_PACK_OK), status, code); + } + + // Send the command to the internal destination task associated to this event + kernel_msg_send(evt); + } + else + { + BLE_ASSERT_INFO(0, hl_type, code_or_subcode); + } + } + else + { + BLE_ASSERT_INFO(0, code_or_subcode, 0); + } + } + break; + } + + return (status); +} +#endif //(BLE_HOST_PRESENT && !BLE_EMB_PRESENT) + + +#endif // (HCI_TL_SUPPORT) +#endif //(HCI_PRESENT) + +/// @} HCI diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/sch/api/sch_alarm.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/sch/api/sch_alarm.h new file mode 100755 index 0000000..c65de17 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/sch/api/sch_alarm.h @@ -0,0 +1,138 @@ +/** +**************************************************************************************** +* +* @file sch_alarm.h +* +* @brief sch_alarm main module +* +* Copyright (C) RivieraWaves 2009-2017 +* +* +**************************************************************************************** +*/ + +#ifndef _SCH_ALARM_H_ +#define _SCH_ALARM_H_ + +/** + **************************************************************************************** + * @addtogroup SCH + * @brief Entry points of the Scheduling alaram module + * + * @{ + **************************************************************************************** + */ + +#include "rwip_config.h" + +#include // Standard integer definitions +#include // Standard boolean definitions +#include "common_list.h" // List management functions definitions + + +/* + * MACROS + **************************************************************************************** + */ + + + +/* + * DEFINES + **************************************************************************************** + */ + + +/* + * DEFINITIONS + **************************************************************************************** + */ + +/// SCH_ALARM error codes +enum sch_alarm_error +{ + /// SCH_ALARM request succeed + SCH_ALARM_ERROR_OK = 0, + /// SCH_ALARM request rejected error + SCH_ALARM_ERROR_REJECTED, + /// SCH_ALARM element not found error + SCH_ALARM_ERROR_NOT_FOUND, + /// SCH_ALARM request rejected due to bandwidth full error + SCH_ALARM_ERROR_BW_FULL +}; + + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + +/// Alarm element structure +struct sch_alarm_tag +{ + /// List element for chaining in the Even Arbiter lists + struct common_list_hdr hdr; + + /// Timestamp of alarm expiry (in BT half-slots) + uint32_t timestamp; + + /// Call back function invoked upon alarm expiry + void (*cb_alarm)(struct sch_alarm_tag*); +}; + +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ + + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Initialize the Scheduling alarm. + * + * @param[in] init_type Type of initialization (@see enum rwip_init_type) + **************************************************************************************** + */ +void sch_alarm_init(uint8_t init_type); + +/** + **************************************************************************************** + * @brief Alarm interrupt handler + * + * This function is called under interrupt when an alarm is triggered. + * + **************************************************************************************** + */ +void sch_alarm_timer_isr(void); + +/** + **************************************************************************************** + * @brief Set an alarm + * + * If the alarm specify an instant in the past, the alarm is scheduled for earliest + * possible time. + * + * @param[in] elt Pointer to the alarm element to be programmed + **************************************************************************************** + */ +void sch_alarm_set(struct sch_alarm_tag* elt); + +/** + **************************************************************************************** + * @brief Clear an alarm + * + * @param[in] elt Pointer to the alarm element to be cleared + * + * @return 0 - no error / 1:255 - error + **************************************************************************************** + */ +uint8_t sch_alarm_clear(struct sch_alarm_tag* elt); + +///@} SCH_ALARM + +#endif // _SCH_ALARM_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/sch/api/sch_arb.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/sch/api/sch_arb.h new file mode 100755 index 0000000..4610e37 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/sch/api/sch_arb.h @@ -0,0 +1,293 @@ +/** +**************************************************************************************** +* +* @file SCH_ARB.h +* +* @brief SCH_ARB main module +* +* Copyright (C) RivieraWaves 2009-2017 +* +* +**************************************************************************************** +*/ + +#ifndef _SCH_ARB_H_ +#define _SCH_ARB_H_ + +/** + **************************************************************************************** + * @addtogroup SCH + * @brief Entry points of the Scheduling Arbiter module + * + * This module contains the primitives that allow stacks to schedule an event or frame. + * + * @{ + **************************************************************************************** + */ + +#include "rwip_config.h" + +#include // Standard integer definitions +#include // Standard boolean definitions +#include "common_list.h" // List management functions definitions +#include "rwip.h" // For rwip_time_t + + +/* + * MACROS + **************************************************************************************** + */ + + + +/* + * DEFINES + **************************************************************************************** + */ + +/// Default BW 2 slots +#define SCH_ARB_BW_USED_DFT_SLOT (2) +#define SCH_ARB_BW_USED_DFT_US (SCH_ARB_BW_USED_DFT_SLOT*SLOT_SIZE) + + +/// Set ASAP settings +#define SCH_ARB_ASAP_STG_SET(evt, type, phase, resched_att, prio_inc) evt->asap_settings = ( (((type) << 14) & 0xC000) | (((phase) << 11) & 0x3800) | (((resched_att) << 4) & 0x03F0) | (((prio_inc) << 0) & 0x000F) ); +/// Get/Set type from ASAP settings +#define SCH_ARB_ASAP_STG_TYPE_GET(evt) ((uint8_t)((evt->asap_settings & 0xC000) >> 14)) +#define SCH_ARB_ASAP_STG_TYPE_SET(evt, type) ( evt->asap_settings = ((evt->asap_settings & ~(0xC000)) | (((type) << 14) & 0xC000)) ) +/// Get phase from ASAP settings +#define SCH_ARB_ASAP_STG_PHASE_GET(evt) ((uint8_t)((evt->asap_settings & 0x3800) >> 11)) +/// Get/Set rescheduling attempts from ASAP settings +#define SCH_ARB_ASAP_STG_RESCHED_ATT_GET(evt) ((uint8_t)((evt->asap_settings & 0x03F0) >> 4)) +#define SCH_ARB_ASAP_STG_RESCHED_ATT_SET(evt, resched_att) ( evt->asap_settings = ((evt->asap_settings & ~(0x03F0)) | (((resched_att) << 4) & 0x03F0)) ) +/// Get priority increment from ASAP settings +#define SCH_ARB_ASAP_STG_PRIO_INC_GET(evt) ((uint8_t)((evt->asap_settings & 0x000F) >> 0)) + +/// Maximum SCH_ARB element duration in half-us +#define SCH_ARB_MAX_DURATION (400000) + + +/* + * DEFINITIONS + **************************************************************************************** + */ + +/// SCH_ARB error codes +enum sch_arb_error +{ + /// SCH_ARB request succeed + SCH_ARB_ERROR_OK = 0, + /// SCH_ARB request rejected error + SCH_ARB_ERROR_REJECTED, + /// SCH_ARB element not found error + SCH_ARB_ERROR_NOT_FOUND, + /// SCH_ARB request rejected due to bandwidth full error + SCH_ARB_ERROR_BW_FULL +}; + +/// ASAP type definition +/*@TRACE*/ +enum sch_arb_elt_asap_type +{ + /// 00: No ASAP + SCH_ARB_FLAG_NO_ASAP = 0, + /// 01: ASAP no limit + SCH_ARB_FLAG_ASAP_NO_LIMIT, + /// 10: ASAP with limit + SCH_ARB_FLAG_ASAP_LIMIT, + SCH_ARB_FLAG_MAX +}; + +/// ASAP slot parity definition +enum sch_arb_elt_asap_phase +{ + SCH_ARB_PHASE_0, + SCH_ARB_PHASE_1, + SCH_ARB_PHASE_2, + SCH_ARB_PHASE_3, + SCH_ARB_NO_PHASE, +}; + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + +#define RPA_TAG_TYPE (1 << 8) +#define ADV_TAG_TYPE (2 << 8) +#define ADV_AUX_TAG_TYPE (3 << 8) +#define CONN_TAG_TYPE (4 << 8) +#define INIT_TAG_TYPE (5 << 8) +#define INIT_CODED_TAG_TYPE (6 << 8) +#define PER_ADV_TAG_TYPE (7 << 8) +#define SCAN_TAG_TYPE (8 << 8) +#define SCAN_AUX_TAG_TYPE (9 << 8) +#define SCAN_CODED_TAG_TYPE (10 << 8) +#define SCAN_CODED_AUX_TAG_TYPE (11 << 8) +#define SYNC_TAG_TYPE (12 << 8) +#define TEST_TAG_TYPE (13 << 8) + +#define MASK_TAG_TYPE (0xF << 8) + +#define CONN_ROLE_MASTER (0 << 15) +#define CONN_ROLE_SLAVE (1 << 15) +#define CONN_ROLE_MASK (1 << 15) + +/// Scheduling Arbiter Element +/*@TRACE*/ +struct sch_arb_elt_tag +{ + /// List element for chaining in the Even Arbiter lists + struct common_list_hdr hdr; + + /// Programming time expressed in half-slots and half-us + rwip_time_t time; + + /// Scheduling time limit in base time (half-slots) (only for ASAP LIMIT requests) + uint32_t asap_limit; + + /// Minimum duration of the event or frame (in half-us) + uint32_t duration_min; + + /** + * ASAP settings field + * bit |15 14|13 12 11| 10 | 9..4 | 3..0 | + * def | TYPE | Phase | To protect | Resched att | Prio inc | + * + * Type: + * - 00: No ASAP + * - 01: ASAP no limit + * - 10: ASAP with limit + * - 11: ASAP with limit, no parity check + * + * Phase: (only for ASAP requests) + * - 0: phase 0 + * - 1: phase 1 + * - 2: phase 2 + * - 3: phase 3 + * - 4: don't care + * + * Number of rescheduling attempts: + * - The remaining number of rescheduling attempts. + * - Rescheduling happens when the event is overlapped by a higher priority event + * - Only used for ASAP requests + * + * Priority increment: + * - The current priority value is incremented each time the event is overlapped by a new insertion and postponed + * - Only used for ASAP requests + */ + /*@trc_desc + *bit |15..14| 13..11 | 10 | 9..4 | 3..0 | + *def | Type | Phase | Rsvd | Resched_att | Prio_inc | + * + *Phase: only if Type = 01..11 + *Resched_att: only if Type = 01..11 + *Prio_inc: only if Type = 01..11 + * + *@trc_ref Type: + * - 00: No ASAP + * - 01: ASAP no limit + * - 10: ASAP with limit + * - 11: ASAP with limit and no parity check + * + *@trc_ref Phase: + * - 000: phase 0 + * - 001: phase 1 + * - 010: phase 2 + * - 011: phase 3 + * - 100: don-t care + */ + uint16_t asap_settings; + + /// Current priority + uint8_t current_prio; + /// Latency to notify to stop the activity before next activity is notified to start (in half-slots, 0 if no stop required) + uint8_t stop_latency; + + /// BK add:For rpa renew event, we do not need rf + uint8_t rf_flag; + uint16_t tag_info; + + /************************************************************************************ + * ISR CALLBACKS + ************************************************************************************/ + + /// Start notification call back function + void (*cb_start)(struct sch_arb_elt_tag*); + /// Stop notification call back function + void (*cb_stop)(struct sch_arb_elt_tag*); + /// Cancel notification call back function + void (*cb_cancel)(struct sch_arb_elt_tag*); +}; + + +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ + + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Initialize the Scheduling Arbiter. + * + * @param[in] init_type Type of initialization (@see enum rwip_init_type) + **************************************************************************************** + */ +void sch_arb_init(uint8_t init_type); + +/** + **************************************************************************************** + * @brief Insert a new reservation in the schedule + * + * @param[in] elt Pointer to the element to be inserted + * + * @return No error if element is inserted. + **************************************************************************************** + */ +uint8_t sch_arb_insert(struct sch_arb_elt_tag *elt); + +/** + **************************************************************************************** + * @brief Remove a reservation + * + * @param[in] elt Pointer to the element to be removed from current ptr + * @param[in] not_waiting True: activity is already started | False: may be waiting or not + * + **************************************************************************************** + */ +uint8_t sch_arb_remove(struct sch_arb_elt_tag *elt, bool not_waiting); + +/** + **************************************************************************************** + * @brief Start of event/frame interrupt handler + * + * This function is called under interrupt when a start of event/frame interrupt is + * generated by the BLE/BT core. + * + **************************************************************************************** + */ +void sch_arb_event_start_isr(void); + + +/** + **************************************************************************************** + * @brief Software interrupt handler + * + * This function is called under interrupt when a SW interrupt is generated by the BLE/BT + * core. + * + **************************************************************************************** + */ +void sch_arb_sw_isr(void); + +uint8_t sch_arb_prog_check(void); + +///@} SCH_ARB + +#endif // _SCH_ARB_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/sch/api/sch_plan.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/sch/api/sch_plan.h new file mode 100755 index 0000000..d68a10a --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/sch/api/sch_plan.h @@ -0,0 +1,230 @@ +/** +**************************************************************************************** +* +* @file SCH_PLAN.h +* +* @brief SCH_PLAN main module +* +* Copyright (C) RivieraWaves 2009-2018 +* +* +**************************************************************************************** +*/ + +#ifndef _SCH_PLAN_H_ +#define _SCH_PLAN_H_ + +/** + **************************************************************************************** + * @addtogroup SCH + * @brief Entry points of the Scheduling Planner module + * + * This module contains the primitives that allow stacks to plan periodic activities + * + * @{ + **************************************************************************************** + */ + +#include // Standard integer definitions +#include // Standard boolean definitions +#include "common_list.h" // List management functions definitions + + +/* + * MACROS + **************************************************************************************** + */ + + + +/* + * DEFINES + **************************************************************************************** + */ + + + +/* + * DEFINITIONS + **************************************************************************************** + */ + +/// SCH_PLAN error codes +enum sch_plan_error +{ + /// SCH_PLAN request succeed + SCH_PLAN_ERROR_OK = 0, + /// SCH_PLAN request rejected error + SCH_PLAN_ERROR_REJECTED, + /// SCH_PLAN element not found error + SCH_PLAN_ERROR_NOT_FOUND, + /// SCH_PLAN request rejected due to bandwidth full error + SCH_PLAN_ERROR_BW_FULL +}; + +/// SCH_PLAN mobility levels +enum sch_plan_mb_lvl +{ + /// SCH_PLAN mobility level 0 (not movable) + SCH_PLAN_MB_LVL_0 = 0, + /// SCH_PLAN mobility level 1 + SCH_PLAN_MB_LVL_1, + /// SCH_PLAN mobility level 2 + SCH_PLAN_MB_LVL_2, + /// SCH_PLAN mobility level 3 + SCH_PLAN_MB_LVL_3, + /// SCH_PLAN mobility level 4 + SCH_PLAN_MB_LVL_4 +}; + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + +/// Interval element strcuture +struct sch_plan_elt_tag +{ + /// List element for chaining in the Interval list + struct common_list_hdr hdr; + /// Interval used (in slots) + uint32_t interval; + /// Offset used (in slots) + uint32_t offset; + /// Minimum duration (in slots) + uint32_t duration_min; + /// Maximum duration (in slots) + uint32_t duration_max; + /// Connection handle used + uint16_t conhdl; + /// Mobility level + uint8_t mobility; + /************************************************************************************ + * ISR CALLBACKS + ************************************************************************************/ + /// Move notification call back function + void (*cb_move)(uint16_t id); + +}; + +/// API request parameters +struct sch_plan_req_param +{ + /// Interval minimum requested (in slots) + uint32_t interval_min; + /// Interval maximum requested (in slots) + uint32_t interval_max; + /// Duration minimum requested (in slots) + uint32_t duration_min; + /// Duration maximum requested (in slots) + uint32_t duration_max; + /// Connection handle + uint16_t conhdl; + /// Preferred periodicity (in slots) + uint8_t pref_period; + /// Odd offset or even offset + bool odd_offset; + /// Interval returned (in slots) + uint32_t interval; + /// Min offset returned (in slots) + uint32_t offset_min; + /// Max offset returned (in slots) + uint32_t offset_max; +}; + +/// API check parameters +struct sch_plan_chk_param +{ + /// Interval (in slots) + uint32_t interval; + /// Duration minimum requested (in slots) + uint32_t duration_min; + /// Offset requested (in slots) + uint32_t offset; + /// Connection handle + uint16_t conhdl; +}; + +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ + + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Initialize the Scheduling Planner. + * + * @param[in] init_type Type of initialization (@see enum rwip_init_type) + **************************************************************************************** + */ +void sch_plan_init(uint8_t init_type); + +/** + **************************************************************************************** + * @brief Insert the element in the common element queue + **************************************************************************************** + */ +void sch_plan_set(struct sch_plan_elt_tag *elt_to_add); + +/** + **************************************************************************************** + * @brief Remove the element from the common element queue + **************************************************************************************** + */ +void sch_plan_rem(struct sch_plan_elt_tag *elt_to_remove); + +/** + **************************************************************************************** + * @brief Choose appropriate parameters for the activity + * + * @param[in] input_param parameters used to compute output values + * + * @param[in] output_param appropriate parameters for the activity + * + * @return See sch_plan_error error codes + **************************************************************************************** + */ +uint8_t sch_plan_req(struct sch_plan_req_param* req_param); + +/** + **************************************************************************************** + * @brief Check if the provided offset is acceptable + * + * @param[in] input_param parameters used to perform the check + * + * @param[in] output_param offset used for the interval + * + * @return See sch_plan_error error codes + **************************************************************************************** + */ +uint8_t sch_plan_chk(struct sch_plan_chk_param* chk_param); + +/** + **************************************************************************************** + * @brief Choose an appropriate offset according to the interval with a required air duration + * + * @param[in] link_id Link identifier + * @param[in] role Role of the activity + * @param[in] interval Activity interval (in slots) + * @param[in] duration Activity event duration (in slots) + * @param[in|out] min_offset Minimum Activity offset as input/computed (in slots) + * @param[in|out] max_offset Maximum Activity offset as input/computed (in slots) + * + * @return - SCH_PLAN_ERROR_OK if succeed + * - SCH_PLAN_ERROR_REJECTED if invalid parameters + * - SCH_PLAN_ERROR_BW_FULL if not able to find available bandwidth + **************************************************************************************** + */ +uint8_t sch_plan_position_range_compute(uint8_t link_id, uint8_t role, uint16_t interval, uint16_t duration, + uint16_t* min_offset, uint16_t* max_offset); + + +///@} SCH_PLAN + +#endif // _SCH_PLAN_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/sch/api/sch_prog.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/sch/api/sch_prog.h new file mode 100755 index 0000000..739388d --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/sch/api/sch_prog.h @@ -0,0 +1,268 @@ +/** +**************************************************************************************** +* +* @file sch_prog.h +* +* @brief Scheduling Programmer API +* +* Copyright (C) RivieraWaves 2009-2017 +* +**************************************************************************************** +*/ + +#ifndef SCH_PROG_H_ +#define SCH_PROG_H_ + +/** + **************************************************************************************** + * @defgroup SCH_PROG Scheduling Programmer + * @ingroup SCH + * @brief Responsible for programming BT/BLE frames. + * @{ + **************************************************************************************** + */ + + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" // stack configuration + +#include // integer +#include // boolean + +/* + * DEFINES + **************************************************************************************** + */ + +/* + * ENUMERATIONS + **************************************************************************************** + */ + +/// Mode +enum SCH_FRAME_TYPE +{ + SCH_PROG_BLE, + SCH_PROG_BT, +}; + +/// Frame type +enum SCH_FRAME_IRQ +{ + /// Normal End of Event + SCH_FRAME_IRQ_EOF = 0x00, + /// End of event due to an abort + SCH_FRAME_IRQ_EOF_ABORT = 0x01, + /// SKIP Event IRQ + SCH_FRAME_IRQ_SKIP = 0x04, + /// RX ACL IRQ + SCH_FRAME_IRQ_RX = 0x02, + /// TX ACL IRQ + SCH_FRAME_IRQ_TX = 0x03, + + #if (BLE_ISO_PRESENT) + /// RX ISO IRQ + SCH_FRAME_IRQ_RX_ISO = 0x05, + /// TX ISO IRQ + SCH_FRAME_IRQ_TX_ISO = 0x06, + #endif // (BLE_ISO_PRESENT) +}; + +#if BT_EMB_PRESENT +/// Frame type +enum SCH_BT_FRAME_TYPE +{ + SCH_BT_FRAME_TYPE_NORMAL = 0x00, + SCH_BT_FRAME_TYPE_SNIFF = 0x01, + SCH_BT_FRAME_TYPE_ESCO = 0x02, + SCH_BT_FRAME_TYPE_CSB = 0x03, + SCH_BT_FRAME_TYPE_ESCO_RETX = 0x04, +}; +#endif //BT_EMB_PRESENT + + +/* + * STRUCTURE DEFINITIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Callback for interrupt related to the frame + * + * @param[in] timestamp Timestamp of the programmed frame (in BLE slots, based on local clock) + * @param[in] dummy Dummy value (provided by the driver when programming the frame via sch_prog_push) + * @param[in] irq_type IRQ type (0: End Of Frame | 1: RX) + **************************************************************************************** + */ +typedef void (*frm_cbk_t)(uint32_t timestamp, uint32_t dummy, uint8_t irq_type); + +#if BT_EMB_PRESENT +/** + **************************************************************************************** + * @brief Callback for interrupt related to the clock IRQ + * + * @param[in] clock Clock when the IRQ happened + * @param[in] id Identification value + **************************************************************************************** + */ +typedef void (*clk_cbk_t)(uint32_t clock, uint8_t id); +#endif //BT_EMB_PRESENT + +#if BLE_EMB_PRESENT +/// Additional parameters for BLE frame +struct sch_prog_params_ble +{ + /// Advertising channel type: 0x0: AE Start on Primary channel | 0x1: AE Start on Secondary channel + uint8_t ae_nps; + /// Reserved audio event (0: reTx, 1:primary) + uint8_t rsvd; + /// Isochronous event (0: normal event | 1: iso event) + uint8_t iso; +}; +#endif //BLE_EMB_PRESENT + +#if BT_EMB_PRESENT +/// Additional parameters for BT frame +struct sch_prog_params_bt +{ + /// Frame type (0: normal | 1: sniff | 2: ESCO | 3: CSB) + uint8_t frm_type; + /// Voice channel + uint8_t vxchan; +}; +#endif //BT_EMB_PRESENT + +/// Parameters for a programmed frame +struct sch_prog_params +{ + /// Callback for handling interrupts related to the frame + frm_cbk_t frm_cbk; + /// Timestamp (in half-slots, based on local clock) and event offset (in half-us) of the programmed frame + rwip_time_t time; + /// Bandwidth duration of the event using priority 1 (in half us) + uint32_t bandwidth; + /// Dummy value reported when an event happen during the frame or the frame is completed + uint32_t dummy; + /// Priority during duration of bandwidth + uint8_t prio_1; + /// Priority after bandwidth elapsed + uint8_t prio_2; + /// Priority after trigger conditions + uint8_t prio_3; + /// Priority when specific action occurs during the event + uint8_t pti_prio; + /// Control structure index + uint8_t cs_idx; + /// Mode (0: BLE, 1:BT) + uint8_t mode; + + union + { + #if BLE_EMB_PRESENT + /// Additional parameters for BLE frame + struct sch_prog_params_ble ble; + #endif //BLE_EMB_PRESENT + + #if BT_EMB_PRESENT + /// Additional parameters for BT frame + struct sch_prog_params_bt bt; + #endif //BT_EMB_PRESENT + } add; +}; + + +/* + * FUNCTIONS DECLARATION + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Initialize the SCH_PROG module + * + * @param[in] init_type Type of initialization (@see enum rwip_init_type) + **************************************************************************************** + */ +void sch_prog_init(uint8_t init_type); + +/** + **************************************************************************************** + * @brief Handle "RX" interrupt + * + * @param[in] et_idx Entry index that trigger the ISR (@note Valid only with 5.0 + ISO HW) + **************************************************************************************** + */ +void sch_prog_rx_isr(uint8_t et_idx); + +/** + **************************************************************************************** + * @brief Handle FIFO interrupt + **************************************************************************************** + */ +void sch_prog_fifo_isr(void); + +/** +**************************************************************************************** +* @brief Push a new programmed frame +* +* @param[in] params Parameters structure +**************************************************************************************** +*/ +void sch_prog_push(struct sch_prog_params* params); + +#if BT_EMB_PRESENT +/** + **************************************************************************************** + * @brief Enable the programming of an activity + * + * @param[in] clk_cbk Callback for handling interrupts related to the clock + * @param[in] id Identification value + * @param[in] sr_size Size of the sub rating pattern (in number of bits), 0 if no sub rating + * @param[in] sr_val Sub rating pattern value, representing the clock LSBs when interrupt is raised + **************************************************************************************** + */ +void sch_prog_enable(clk_cbk_t clk_cbk, uint8_t id, uint8_t sr_size, uint8_t sr_val); + +/** + **************************************************************************************** + * @brief Disable the programming of an activity + * + * @param[in] id Identification value + **************************************************************************************** + */ +void sch_prog_disable(uint8_t id); + +/** + **************************************************************************************** + * @brief Handle "clock" interrupt + **************************************************************************************** + */ +void sch_prog_clk_isr(void); + +/** + **************************************************************************************** + * @brief Handle "Skip" interrupt + * + * @param[in] et_idx Entry index that trigger the ISR (@note Valid only with 5.0 + ISO HW) + **************************************************************************************** + */ +void sch_prog_skip_isr(uint8_t et_idx); + +/** + **************************************************************************************** + * @brief Handle "End of Event" interrupt + * + * @param[in] et_idx Entry index that trigger the ISR (@note Valid only with 5.0 + ISO HW) + **************************************************************************************** + */ +void sch_prog_end_isr(uint8_t et_idx); + +#endif //BT_EMB_PRESENT + +/// @} SCH_PROG +#endif // SCH_PROG_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/sch/api/sch_slice.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/sch/api/sch_slice.h new file mode 100755 index 0000000..303ac8d --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/sch/api/sch_slice.h @@ -0,0 +1,181 @@ +/** +**************************************************************************************** +* +* @file sch_slice.h +* +* @brief LD Scheduling Parameters API +* +* Copyright (C) RivieraWaves 2009-2015 +* +**************************************************************************************** +*/ + +#ifndef SCH_SLICE_H_ +#define SCH_SLICE_H_ + +/** + **************************************************************************************** + * @defgroup SCHSLICE Scheduling parameters + * @ingroup SCH + * @brief Responsible for selecting the optimal scheduling parameters. + * @{ + **************************************************************************************** + */ + + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" // stack configuration + +#include // integer +#include // boolean + +/* + * DEFINES + **************************************************************************************** + */ + +/// Undefined BT clock value +#define SCH_CLOCK_UNDEF 0xFFFFFFFF + + +/* + * ENUMERATIONS + **************************************************************************************** + */ + +/// Activity type +enum activity_type +{ + #if BLE_EMB_PRESENT + BLE_SCAN, + BLE_INIT, + BLE_HDC_ADV, + BLE_PER_ADV, + BLE_CON, + #endif //BLE_EMB_PRESENT + + #if BT_EMB_PRESENT + BT_INQ, + BT_PAGE, + BT_ISCAN, + BT_PSCAN, + BT_SSCAN, + BT_SNIFF, + BT_SCO, + #endif //BT_EMB_PRESENT +}; + + +/* + * STRUCTURE DEFINITIONS + **************************************************************************************** + */ + +/// SCH SLICE parameters structure +struct sch_slice_params_tag +{ + /// End of ongoing foreground activity (inq, page, HDC adv) (in BT half-slot clock, SCH_CLOCK_UNDEF if inactive) + uint32_t fg_end_ts; + + /// Scan / Inq / Page event duration (in half-us) + uint16_t scan_evt_dur; + + #if BT_EMB_PRESENT + /// ACL event duration size (in half-us) + uint16_t acl_evt_dur; + + /// SCO retx are allowed to reserve + bool sco_retx_allowed; + #endif //BT_EMB_PRESENT +}; + + +/* + * VARIABLE DECLARATION + **************************************************************************************** + */ + +/// SCH SLICE parameters variable +extern struct sch_slice_params_tag sch_slice_params; + + +/* + * FUNCTIONS DECLARATION + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Initialize the SCH_SLICE module + * + * @param[in] init_type Type of initialization (@see enum rwip_init_type) + **************************************************************************************** + */ +void sch_slice_init(uint8_t init_type); + +/** + **************************************************************************************** + * @brief Add a background activity + * + * @param[in] type Activity type (@see @enum activity_type) + **************************************************************************************** + */ +void sch_slice_bg_add(uint8_t type); + +/** + **************************************************************************************** + * @brief Remove a background activity + * + * @param[in] type Activity type (@see @enum activity_type) + **************************************************************************************** + */ +void sch_slice_bg_remove(uint8_t type); + +/** + **************************************************************************************** + * @brief Add a foreground activity + * + * @param[in] type Activity type (@see @enum activity_type) + * @param[in] end_ts Timestamp of the activity end (in half-slot clock) + **************************************************************************************** + */ +void sch_slice_fg_add(uint8_t type, uint32_t end_ts); + +/** + **************************************************************************************** + * @brief Remove a foreground activity + * + * @param[in] type Activity type (@see @enum activity_type) + **************************************************************************************** + */ +void sch_slice_fg_remove(uint8_t type); + +/** + **************************************************************************************** + * @brief Add a periodic activity + * + * @param[in] type Activity type (@see @enum activity_type) + * @param[in] id Identifier of the activity (depending on the activity type) + * @param[in] intv Interval (in half-slot) + * @param[in] duration Events duration (in half-us) + * @param[in] retx Potential retransmissions (applicable to SCO only) + **************************************************************************************** + */ +void sch_slice_per_add(uint8_t type, uint8_t id, uint32_t intv, uint16_t duration, bool retx); + +/** + **************************************************************************************** + * @brief Remove a periodic activity + * + * @param[in] type Activity type (@see @enum activity_type) + * @param[in] id Identifier of the activity (depending on the activity type) + **************************************************************************************** + */ +void sch_slice_per_remove(uint8_t type, uint8_t id); + +/// @} SCHSLICE +#endif // SCH_SLICE_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/sch/import/RW-EM-ET.xls b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/sch/import/RW-EM-ET.xls new file mode 100755 index 0000000..cb58ca4 Binary files /dev/null and b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/sch/import/RW-EM-ET.xls differ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/sch/import/_reg_em_et.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/sch/import/_reg_em_et.h new file mode 100755 index 0000000..88feef3 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/sch/import/_reg_em_et.h @@ -0,0 +1,10 @@ +#ifndef __REG_EM_ET_H_ +#define __REG_EM_ET_H_ + +#define REG_EM_ET_SIZE 16 + +#define REG_EM_ET_BASE_ADDR 0x00910000 + + +#endif // __REG_EM_ET_H_ + diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/sch/import/ble_reg_em_et.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/sch/import/ble_reg_em_et.h new file mode 100755 index 0000000..10e20d0 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/ip/sch/import/ble_reg_em_et.h @@ -0,0 +1,751 @@ +#ifndef _REG_EM_ET_H_ +#define _REG_EM_ET_H_ + +#include +#include "_reg_em_et.h" +#include "compiler.h" +#include "architect.h" +#include "em_map.h" +#include "ble_reg_access.h" + +#define REG_EM_ET_COUNT 8 + +#define REG_EM_ET_DECODING_MASK 0x0000000F + +#define REG_EM_ET_ADDR_GET(idx) (EM_ET_OFFSET + (idx) * REG_EM_ET_SIZE) + +/** + * @brief BT_EXTAB register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:11            SCH_PRIO1   0x0
+ *     10                  SPA   0
+ *     09                  CSB   0
+ *     08                SNIFF   0
+ *     07                 RSVD   0
+ *     06                 eSCO   0
+ *  05:03               STATUS   0x0
+ *  02:00                 MODE   0x0
+ * 
+ */ +#define EM_BT_EXTAB_ADDR (0x00910000 + EM_ET_OFFSET) +#define EM_BT_EXTAB_INDEX 0x00000000 +#define EM_BT_EXTAB_RESET 0x00000000 + +__INLINE uint16_t em_bt_extab_get(int elt_idx) +{ + return EM_RD(EM_BT_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE); +} + +__INLINE void em_bt_extab_set(int elt_idx, uint16_t value) +{ + EM_WR(EM_BT_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE, value); +} + +// field definitions +#define EM_SCH_PRIO1_MASK ((uint16_t)0x0000F800) +#define EM_SCH_PRIO1_LSB 11 +#define EM_SCH_PRIO1_WIDTH ((uint16_t)0x00000005) +#define EM_SPA_BIT ((uint16_t)0x00000400) +#define EM_SPA_POS 10 +#define EM_CSB_BIT ((uint16_t)0x00000200) +#define EM_CSB_POS 9 +#define EM_SNIFF_BIT ((uint16_t)0x00000100) +#define EM_SNIFF_POS 8 +#define EM_RSVD_BIT ((uint16_t)0x00000080) +#define EM_RSVD_POS 7 +#define EM_E_SCO_BIT ((uint16_t)0x00000040) +#define EM_E_SCO_POS 6 +#define EM_STATUS_MASK ((uint16_t)0x00000038) +#define EM_STATUS_LSB 3 +#define EM_STATUS_WIDTH ((uint16_t)0x00000003) +#define EM_MODE_MASK ((uint16_t)0x00000007) +#define EM_MODE_LSB 0 +#define EM_MODE_WIDTH ((uint16_t)0x00000003) + +#define EM_SCH_PRIO1_RST 0x0 +#define EM_SPA_RST 0x0 +#define EM_CSB_RST 0x0 +#define EM_SNIFF_RST 0x0 +#define EM_RSVD_RST 0x0 +#define EM_E_SCO_RST 0x0 +#define EM_STATUS_RST 0x0 +#define EM_MODE_RST 0x0 + +__INLINE void em_bt_extab_pack(int elt_idx, uint8_t schprio1, uint8_t spa, uint8_t csb, uint8_t sniff, uint8_t rsvd, uint8_t esco, uint8_t status, uint8_t mode) +{ + BLE_ASSERT_ERR((((uint16_t)schprio1 << 11) & ~((uint16_t)0x0000F800)) == 0); + BLE_ASSERT_ERR((((uint16_t)spa << 10) & ~((uint16_t)0x00000400)) == 0); + BLE_ASSERT_ERR((((uint16_t)csb << 9) & ~((uint16_t)0x00000200)) == 0); + BLE_ASSERT_ERR((((uint16_t)sniff << 8) & ~((uint16_t)0x00000100)) == 0); + BLE_ASSERT_ERR((((uint16_t)rsvd << 7) & ~((uint16_t)0x00000080)) == 0); + BLE_ASSERT_ERR((((uint16_t)esco << 6) & ~((uint16_t)0x00000040)) == 0); + BLE_ASSERT_ERR((((uint16_t)status << 3) & ~((uint16_t)0x00000038)) == 0); + BLE_ASSERT_ERR((((uint16_t)mode << 0) & ~((uint16_t)0x00000007)) == 0); + EM_WR(EM_BT_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE, ((uint16_t)schprio1 << 11) | ((uint16_t)spa << 10) | ((uint16_t)csb << 9) | ((uint16_t)sniff << 8) | ((uint16_t)rsvd << 7) | ((uint16_t)esco << 6) | ((uint16_t)status << 3) | ((uint16_t)mode << 0)); +} + +__INLINE void em_bt_extab_unpack(int elt_idx, uint8_t* schprio1, uint8_t* spa, uint8_t* csb, uint8_t* sniff, uint8_t* rsvd, uint8_t* esco, uint8_t* status, uint8_t* mode) +{ + uint16_t localVal = EM_RD(EM_BT_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE); + + *schprio1 = (localVal & ((uint16_t)0x0000F800)) >> 11; + *spa = (localVal & ((uint16_t)0x00000400)) >> 10; + *csb = (localVal & ((uint16_t)0x00000200)) >> 9; + *sniff = (localVal & ((uint16_t)0x00000100)) >> 8; + *rsvd = (localVal & ((uint16_t)0x00000080)) >> 7; + *esco = (localVal & ((uint16_t)0x00000040)) >> 6; + *status = (localVal & ((uint16_t)0x00000038)) >> 3; + *mode = (localVal & ((uint16_t)0x00000007)) >> 0; +} + +__INLINE uint8_t em_bt_extab_sch_prio1_getf(int elt_idx) +{ + uint16_t localVal = EM_RD(EM_BT_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE); + return ((localVal & ((uint16_t)0x0000F800)) >> 11); +} + +__INLINE void em_bt_extab_sch_prio1_setf(int elt_idx, uint8_t schprio1) +{ + BLE_ASSERT_ERR((((uint16_t)schprio1 << 11) & ~((uint16_t)0x0000F800)) == 0); + EM_WR(EM_BT_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE, (EM_RD(EM_BT_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE) & ~((uint16_t)0x0000F800)) | ((uint16_t)schprio1 << 11)); +} + +__INLINE uint8_t em_bt_extab_spa_getf(int elt_idx) +{ + uint16_t localVal = EM_RD(EM_BT_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE); + return ((localVal & ((uint16_t)0x00000400)) >> 10); +} + +__INLINE void em_bt_extab_spa_setf(int elt_idx, uint8_t spa) +{ + BLE_ASSERT_ERR((((uint16_t)spa << 10) & ~((uint16_t)0x00000400)) == 0); + EM_WR(EM_BT_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE, (EM_RD(EM_BT_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE) & ~((uint16_t)0x00000400)) | ((uint16_t)spa << 10)); +} + +__INLINE uint8_t em_bt_extab_csb_getf(int elt_idx) +{ + uint16_t localVal = EM_RD(EM_BT_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE); + return ((localVal & ((uint16_t)0x00000200)) >> 9); +} + +__INLINE void em_bt_extab_csb_setf(int elt_idx, uint8_t csb) +{ + BLE_ASSERT_ERR((((uint16_t)csb << 9) & ~((uint16_t)0x00000200)) == 0); + EM_WR(EM_BT_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE, (EM_RD(EM_BT_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE) & ~((uint16_t)0x00000200)) | ((uint16_t)csb << 9)); +} + +__INLINE uint8_t em_bt_extab_sniff_getf(int elt_idx) +{ + uint16_t localVal = EM_RD(EM_BT_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE); + return ((localVal & ((uint16_t)0x00000100)) >> 8); +} + +__INLINE void em_bt_extab_sniff_setf(int elt_idx, uint8_t sniff) +{ + BLE_ASSERT_ERR((((uint16_t)sniff << 8) & ~((uint16_t)0x00000100)) == 0); + EM_WR(EM_BT_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE, (EM_RD(EM_BT_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE) & ~((uint16_t)0x00000100)) | ((uint16_t)sniff << 8)); +} + +__INLINE uint8_t em_bt_extab_rsvd_getf(int elt_idx) +{ + uint16_t localVal = EM_RD(EM_BT_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE); + return ((localVal & ((uint16_t)0x00000080)) >> 7); +} + +__INLINE void em_bt_extab_rsvd_setf(int elt_idx, uint8_t rsvd) +{ + BLE_ASSERT_ERR((((uint16_t)rsvd << 7) & ~((uint16_t)0x00000080)) == 0); + EM_WR(EM_BT_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE, (EM_RD(EM_BT_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE) & ~((uint16_t)0x00000080)) | ((uint16_t)rsvd << 7)); +} + +__INLINE uint8_t em_bt_extab_e_sco_getf(int elt_idx) +{ + uint16_t localVal = EM_RD(EM_BT_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE); + return ((localVal & ((uint16_t)0x00000040)) >> 6); +} + +__INLINE void em_bt_extab_e_sco_setf(int elt_idx, uint8_t esco) +{ + BLE_ASSERT_ERR((((uint16_t)esco << 6) & ~((uint16_t)0x00000040)) == 0); + EM_WR(EM_BT_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE, (EM_RD(EM_BT_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE) & ~((uint16_t)0x00000040)) | ((uint16_t)esco << 6)); +} + +__INLINE uint8_t em_bt_extab_status_getf(int elt_idx) +{ + uint16_t localVal = EM_RD(EM_BT_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE); + return ((localVal & ((uint16_t)0x00000038)) >> 3); +} + +__INLINE void em_bt_extab_status_setf(int elt_idx, uint8_t status) +{ + BLE_ASSERT_ERR((((uint16_t)status << 3) & ~((uint16_t)0x00000038)) == 0); + EM_WR(EM_BT_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE, (EM_RD(EM_BT_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE) & ~((uint16_t)0x00000038)) | ((uint16_t)status << 3)); +} + +__INLINE uint8_t em_bt_extab_mode_getf(int elt_idx) +{ + uint16_t localVal = EM_RD(EM_BT_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE); + return ((localVal & ((uint16_t)0x00000007)) >> 0); +} + +__INLINE void em_bt_extab_mode_setf(int elt_idx, uint8_t mode) +{ + BLE_ASSERT_ERR((((uint16_t)mode << 0) & ~((uint16_t)0x00000007)) == 0); + EM_WR(EM_BT_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE, (EM_RD(EM_BT_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE) & ~((uint16_t)0x00000007)) | ((uint16_t)mode << 0)); +} + +/** + * @brief LE_EXTAB register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:11            SCH_PRIO1   0x0
+ *     10                  SPA   0
+ *     08               AE_NPS   0
+ *     07                 RSVD   0
+ *     06                  ISO   0
+ *  05:03               STATUS   0x0
+ *  02:00                 MODE   0x0
+ * 
+ */ +#define EM_LE_EXTAB_ADDR (0x00910000 + EM_ET_OFFSET) +#define EM_LE_EXTAB_INDEX 0x00000000 +#define EM_LE_EXTAB_RESET 0x00000000 + +__INLINE uint16_t em_le_extab_get(int elt_idx) +{ + return EM_RD(EM_LE_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE); +} + +__INLINE void em_le_extab_set(int elt_idx, uint16_t value) +{ + EM_WR(EM_LE_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE, value); +} + +// field definitions +#define EM_SCH_PRIO1_MASK ((uint16_t)0x0000F800) +#define EM_SCH_PRIO1_LSB 11 +#define EM_SCH_PRIO1_WIDTH ((uint16_t)0x00000005) +#define EM_SPA_BIT ((uint16_t)0x00000400) +#define EM_SPA_POS 10 +#define EM_AE_NPS_BIT ((uint16_t)0x00000100) +#define EM_AE_NPS_POS 8 +#define EM_RSVD_BIT ((uint16_t)0x00000080) +#define EM_RSVD_POS 7 +#define EM_ISO_BIT ((uint16_t)0x00000040) +#define EM_ISO_POS 6 +#define EM_STATUS_MASK ((uint16_t)0x00000038) +#define EM_STATUS_LSB 3 +#define EM_STATUS_WIDTH ((uint16_t)0x00000003) +#define EM_MODE_MASK ((uint16_t)0x00000007) +#define EM_MODE_LSB 0 +#define EM_MODE_WIDTH ((uint16_t)0x00000003) + +#define EM_SCH_PRIO1_RST 0x0 +#define EM_SPA_RST 0x0 +#define EM_AE_NPS_RST 0x0 +#define EM_RSVD_RST 0x0 +#define EM_ISO_RST 0x0 +#define EM_STATUS_RST 0x0 +#define EM_MODE_RST 0x0 + +__INLINE void em_le_extab_pack(int elt_idx, uint8_t schprio1, uint8_t spa, uint8_t aenps, uint8_t rsvd, uint8_t iso, uint8_t status, uint8_t mode) +{ + BLE_ASSERT_ERR((((uint16_t)schprio1 << 11) & ~((uint16_t)0x0000F800)) == 0); + BLE_ASSERT_ERR((((uint16_t)spa << 10) & ~((uint16_t)0x00000400)) == 0); + BLE_ASSERT_ERR((((uint16_t)aenps << 8) & ~((uint16_t)0x00000100)) == 0); + BLE_ASSERT_ERR((((uint16_t)rsvd << 7) & ~((uint16_t)0x00000080)) == 0); + BLE_ASSERT_ERR((((uint16_t)iso << 6) & ~((uint16_t)0x00000040)) == 0); + BLE_ASSERT_ERR((((uint16_t)status << 3) & ~((uint16_t)0x00000038)) == 0); + BLE_ASSERT_ERR((((uint16_t)mode << 0) & ~((uint16_t)0x00000007)) == 0); + EM_WR(EM_LE_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE, ((uint16_t)schprio1 << 11) | ((uint16_t)spa << 10) | ((uint16_t)aenps << 8) | ((uint16_t)rsvd << 7) | ((uint16_t)iso << 6) | ((uint16_t)status << 3) | ((uint16_t)mode << 0)); +} + +__INLINE void em_le_extab_unpack(int elt_idx, uint8_t* schprio1, uint8_t* spa, uint8_t* aenps, uint8_t* rsvd, uint8_t* iso, uint8_t* status, uint8_t* mode) +{ + uint16_t localVal = EM_RD(EM_LE_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE); + + *schprio1 = (localVal & ((uint16_t)0x0000F800)) >> 11; + *spa = (localVal & ((uint16_t)0x00000400)) >> 10; + *aenps = (localVal & ((uint16_t)0x00000100)) >> 8; + *rsvd = (localVal & ((uint16_t)0x00000080)) >> 7; + *iso = (localVal & ((uint16_t)0x00000040)) >> 6; + *status = (localVal & ((uint16_t)0x00000038)) >> 3; + *mode = (localVal & ((uint16_t)0x00000007)) >> 0; +} + +__INLINE uint8_t em_le_extab_sch_prio1_getf(int elt_idx) +{ + uint16_t localVal = EM_RD(EM_LE_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE); + return ((localVal & ((uint16_t)0x0000F800)) >> 11); +} + +__INLINE void em_le_extab_sch_prio1_setf(int elt_idx, uint8_t schprio1) +{ + BLE_ASSERT_ERR((((uint16_t)schprio1 << 11) & ~((uint16_t)0x0000F800)) == 0); + EM_WR(EM_LE_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE, (EM_RD(EM_LE_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE) & ~((uint16_t)0x0000F800)) | ((uint16_t)schprio1 << 11)); +} + +__INLINE uint8_t em_le_extab_spa_getf(int elt_idx) +{ + uint16_t localVal = EM_RD(EM_LE_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE); + return ((localVal & ((uint16_t)0x00000400)) >> 10); +} + +__INLINE void em_le_extab_spa_setf(int elt_idx, uint8_t spa) +{ + BLE_ASSERT_ERR((((uint16_t)spa << 10) & ~((uint16_t)0x00000400)) == 0); + EM_WR(EM_LE_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE, (EM_RD(EM_LE_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE) & ~((uint16_t)0x00000400)) | ((uint16_t)spa << 10)); +} + +__INLINE uint8_t em_le_extab_ae_nps_getf(int elt_idx) +{ + uint16_t localVal = EM_RD(EM_LE_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE); + return ((localVal & ((uint16_t)0x00000100)) >> 8); +} + +__INLINE void em_le_extab_ae_nps_setf(int elt_idx, uint8_t aenps) +{ + BLE_ASSERT_ERR((((uint16_t)aenps << 8) & ~((uint16_t)0x00000100)) == 0); + EM_WR(EM_LE_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE, (EM_RD(EM_LE_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE) & ~((uint16_t)0x00000100)) | ((uint16_t)aenps << 8)); +} + +__INLINE uint8_t em_le_extab_rsvd_getf(int elt_idx) +{ + uint16_t localVal = EM_RD(EM_LE_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE); + return ((localVal & ((uint16_t)0x00000080)) >> 7); +} + +__INLINE void em_le_extab_rsvd_setf(int elt_idx, uint8_t rsvd) +{ + BLE_ASSERT_ERR((((uint16_t)rsvd << 7) & ~((uint16_t)0x00000080)) == 0); + EM_WR(EM_LE_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE, (EM_RD(EM_LE_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE) & ~((uint16_t)0x00000080)) | ((uint16_t)rsvd << 7)); +} + +__INLINE uint8_t em_le_extab_iso_getf(int elt_idx) +{ + uint16_t localVal = EM_RD(EM_LE_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE); + return ((localVal & ((uint16_t)0x00000040)) >> 6); +} + +__INLINE void em_le_extab_iso_setf(int elt_idx, uint8_t iso) +{ + BLE_ASSERT_ERR((((uint16_t)iso << 6) & ~((uint16_t)0x00000040)) == 0); + EM_WR(EM_LE_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE, (EM_RD(EM_LE_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE) & ~((uint16_t)0x00000040)) | ((uint16_t)iso << 6)); +} + +__INLINE uint8_t em_le_extab_status_getf(int elt_idx) +{ + uint16_t localVal = EM_RD(EM_LE_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE); + return ((localVal & ((uint16_t)0x00000038)) >> 3); +} + +__INLINE void em_le_extab_status_setf(int elt_idx, uint8_t status) +{ + BLE_ASSERT_ERR((((uint16_t)status << 3) & ~((uint16_t)0x00000038)) == 0); + EM_WR(EM_LE_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE, (EM_RD(EM_LE_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE) & ~((uint16_t)0x00000038)) | ((uint16_t)status << 3)); +} + +__INLINE uint8_t em_le_extab_mode_getf(int elt_idx) +{ + uint16_t localVal = EM_RD(EM_LE_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE); + return ((localVal & ((uint16_t)0x00000007)) >> 0); +} + +__INLINE void em_le_extab_mode_setf(int elt_idx, uint8_t mode) +{ + BLE_ASSERT_ERR((((uint16_t)mode << 0) & ~((uint16_t)0x00000007)) == 0); + EM_WR(EM_LE_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE, (EM_RD(EM_LE_EXTAB_ADDR + elt_idx * REG_EM_ET_SIZE) & ~((uint16_t)0x00000007)) | ((uint16_t)mode << 0)); +} + +/** + * @brief RAWSTP0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00              RAWSTP0   0x0
+ * 
+ */ +#define EM_RAWSTP0_ADDR (0x00910002 + EM_ET_OFFSET) +#define EM_RAWSTP0_INDEX 0x00000001 +#define EM_RAWSTP0_RESET 0x00000000 + +__INLINE uint16_t em_rawstp0_get(int elt_idx) +{ + return EM_RD(EM_RAWSTP0_ADDR + elt_idx * REG_EM_ET_SIZE); +} + +__INLINE void em_rawstp0_set(int elt_idx, uint16_t value) +{ + EM_WR(EM_RAWSTP0_ADDR + elt_idx * REG_EM_ET_SIZE, value); +} + +// field definitions +#define EM_RAWSTP0_MASK ((uint16_t)0x0000FFFF) +#define EM_RAWSTP0_LSB 0 +#define EM_RAWSTP0_WIDTH ((uint16_t)0x00000010) + +#define EM_RAWSTP0_RST 0x0 + +__INLINE uint16_t em_rawstp0_getf(int elt_idx) +{ + uint16_t localVal = EM_RD(EM_RAWSTP0_ADDR + elt_idx * REG_EM_ET_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_rawstp0_setf(int elt_idx, uint16_t rawstp0) +{ + BLE_ASSERT_ERR((((uint16_t)rawstp0 << 0) & ~((uint16_t)0x0000FFFF)) == 0); + EM_WR(EM_RAWSTP0_ADDR + elt_idx * REG_EM_ET_SIZE, (uint16_t)rawstp0 << 0); +} + +/** + * @brief RAWSTP1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  11:00              RAWSTP1   0x0
+ * 
+ */ +#define EM_RAWSTP1_ADDR (0x00910004 + EM_ET_OFFSET) +#define EM_RAWSTP1_INDEX 0x00000002 +#define EM_RAWSTP1_RESET 0x00000000 + +__INLINE uint16_t em_rawstp1_get(int elt_idx) +{ + return EM_RD(EM_RAWSTP1_ADDR + elt_idx * REG_EM_ET_SIZE); +} + +__INLINE void em_rawstp1_set(int elt_idx, uint16_t value) +{ + EM_WR(EM_RAWSTP1_ADDR + elt_idx * REG_EM_ET_SIZE, value); +} + +// field definitions +#define EM_RAWSTP1_MASK ((uint16_t)0x00000FFF) +#define EM_RAWSTP1_LSB 0 +#define EM_RAWSTP1_WIDTH ((uint16_t)0x0000000C) + +#define EM_RAWSTP1_RST 0x0 + +__INLINE uint16_t em_rawstp1_getf(int elt_idx) +{ + uint16_t localVal = EM_RD(EM_RAWSTP1_ADDR + elt_idx * REG_EM_ET_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x00000FFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_rawstp1_setf(int elt_idx, uint16_t rawstp1) +{ + BLE_ASSERT_ERR((((uint16_t)rawstp1 << 0) & ~((uint16_t)0x00000FFF)) == 0); + EM_WR(EM_RAWSTP1_ADDR + elt_idx * REG_EM_ET_SIZE, (uint16_t)rawstp1 << 0); +} + +/** + * @brief FINESTP register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  09:00              FINESTP   0x0
+ * 
+ */ +#define EM_FINESTP_ADDR (0x00910006 + EM_ET_OFFSET) +#define EM_FINESTP_INDEX 0x00000003 +#define EM_FINESTP_RESET 0x00000000 + +__INLINE uint16_t em_finestp_get(int elt_idx) +{ + return EM_RD(EM_FINESTP_ADDR + elt_idx * REG_EM_ET_SIZE); +} + +__INLINE void em_finestp_set(int elt_idx, uint16_t value) +{ + EM_WR(EM_FINESTP_ADDR + elt_idx * REG_EM_ET_SIZE, value); +} + +// field definitions +#define EM_FINESTP_MASK ((uint16_t)0x000003FF) +#define EM_FINESTP_LSB 0 +#define EM_FINESTP_WIDTH ((uint16_t)0x0000000A) + +#define EM_FINESTP_RST 0x0 + +__INLINE uint16_t em_finestp_getf(int elt_idx) +{ + uint16_t localVal = EM_RD(EM_FINESTP_ADDR + elt_idx * REG_EM_ET_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x000003FF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_finestp_setf(int elt_idx, uint16_t finestp) +{ + BLE_ASSERT_ERR((((uint16_t)finestp << 0) & ~((uint16_t)0x000003FF)) == 0); + EM_WR(EM_FINESTP_ADDR + elt_idx * REG_EM_ET_SIZE, (uint16_t)finestp << 0); +} + +/** + * @brief CSPTR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  14:00                CSPTR   0x0
+ * 
+ */ +#define EM_CSPTR_ADDR (0x00910008 + EM_ET_OFFSET) +#define EM_CSPTR_INDEX 0x00000004 +#define EM_CSPTR_RESET 0x00000000 + +__INLINE uint16_t em_csptr_get(int elt_idx) +{ + return EM_RD(EM_CSPTR_ADDR + elt_idx * REG_EM_ET_SIZE); +} + +__INLINE void em_csptr_set(int elt_idx, uint16_t value) +{ + EM_WR(EM_CSPTR_ADDR + elt_idx * REG_EM_ET_SIZE, value); +} + +// field definitions +#define EM_CSPTR_MASK ((uint16_t)0x00007FFF) +#define EM_CSPTR_LSB 0 +#define EM_CSPTR_WIDTH ((uint16_t)0x0000000F) + +#define EM_CSPTR_RST 0x0 + +__INLINE uint16_t em_csptr_getf(int elt_idx) +{ + uint16_t localVal = EM_RD(EM_CSPTR_ADDR + elt_idx * REG_EM_ET_SIZE); + BLE_ASSERT_ERR((localVal & ~((uint16_t)0x00007FFF)) == 0); + return (localVal >> 0); +} + +__INLINE void em_csptr_setf(int elt_idx, uint16_t csptr) +{ + BLE_ASSERT_ERR((((uint16_t)csptr << 0) & ~((uint16_t)0x00007FFF)) == 0); + EM_WR(EM_CSPTR_ADDR + elt_idx * REG_EM_ET_SIZE, (uint16_t)csptr << 0); +} + +/** + * @brief PRIOBW register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     15          PRIOBW_UNIT   0
+ *  14:00               PRIOBW   0x0
+ * 
+ */ +#define EM_PRIOBW_ADDR (0x0091000A + EM_ET_OFFSET) +#define EM_PRIOBW_INDEX 0x00000005 +#define EM_PRIOBW_RESET 0x00000000 + +__INLINE uint16_t em_priobw_get(int elt_idx) +{ + return EM_RD(EM_PRIOBW_ADDR + elt_idx * REG_EM_ET_SIZE); +} + +__INLINE void em_priobw_set(int elt_idx, uint16_t value) +{ + EM_WR(EM_PRIOBW_ADDR + elt_idx * REG_EM_ET_SIZE, value); +} + +// field definitions +#define EM_PRIOBW_UNIT_BIT ((uint16_t)0x00008000) +#define EM_PRIOBW_UNIT_POS 15 +#define EM_PRIOBW_MASK ((uint16_t)0x00007FFF) +#define EM_PRIOBW_LSB 0 +#define EM_PRIOBW_WIDTH ((uint16_t)0x0000000F) + +#define EM_PRIOBW_UNIT_RST 0x0 +#define EM_PRIOBW_RST 0x0 + +__INLINE void em_priobw_pack(int elt_idx, uint8_t priobwunit, uint16_t priobw) +{ + BLE_ASSERT_ERR((((uint16_t)priobwunit << 15) & ~((uint16_t)0x00008000)) == 0); + BLE_ASSERT_ERR((((uint16_t)priobw << 0) & ~((uint16_t)0x00007FFF)) == 0); + EM_WR(EM_PRIOBW_ADDR + elt_idx * REG_EM_ET_SIZE, ((uint16_t)priobwunit << 15) | ((uint16_t)priobw << 0)); +} + +__INLINE void em_priobw_unpack(int elt_idx, uint8_t* priobwunit, uint16_t* priobw) +{ + uint16_t localVal = EM_RD(EM_PRIOBW_ADDR + elt_idx * REG_EM_ET_SIZE); + + *priobwunit = (localVal & ((uint16_t)0x00008000)) >> 15; + *priobw = (localVal & ((uint16_t)0x00007FFF)) >> 0; +} + +__INLINE uint8_t em_priobw_priobw_unit_getf(int elt_idx) +{ + uint16_t localVal = EM_RD(EM_PRIOBW_ADDR + elt_idx * REG_EM_ET_SIZE); + return ((localVal & ((uint16_t)0x00008000)) >> 15); +} + +__INLINE void em_priobw_priobw_unit_setf(int elt_idx, uint8_t priobwunit) +{ + BLE_ASSERT_ERR((((uint16_t)priobwunit << 15) & ~((uint16_t)0x00008000)) == 0); + EM_WR(EM_PRIOBW_ADDR + elt_idx * REG_EM_ET_SIZE, (EM_RD(EM_PRIOBW_ADDR + elt_idx * REG_EM_ET_SIZE) & ~((uint16_t)0x00008000)) | ((uint16_t)priobwunit << 15)); +} + +__INLINE uint16_t em_priobw_priobw_getf(int elt_idx) +{ + uint16_t localVal = EM_RD(EM_PRIOBW_ADDR + elt_idx * REG_EM_ET_SIZE); + return ((localVal & ((uint16_t)0x00007FFF)) >> 0); +} + +__INLINE void em_priobw_priobw_setf(int elt_idx, uint16_t priobw) +{ + BLE_ASSERT_ERR((((uint16_t)priobw << 0) & ~((uint16_t)0x00007FFF)) == 0); + EM_WR(EM_PRIOBW_ADDR + elt_idx * REG_EM_ET_SIZE, (EM_RD(EM_PRIOBW_ADDR + elt_idx * REG_EM_ET_SIZE) & ~((uint16_t)0x00007FFF)) | ((uint16_t)priobw << 0)); +} + +/** + * @brief PRIOLVL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  12:08            SCH_PRIO3   0x0
+ *  04:00            SCH_PRIO2   0x0
+ * 
+ */ +#define EM_PRIOLVL_ADDR (0x0091000C + EM_ET_OFFSET) +#define EM_PRIOLVL_INDEX 0x00000006 +#define EM_PRIOLVL_RESET 0x00000000 + +__INLINE uint16_t em_priolvl_get(int elt_idx) +{ + return EM_RD(EM_PRIOLVL_ADDR + elt_idx * REG_EM_ET_SIZE); +} + +__INLINE void em_priolvl_set(int elt_idx, uint16_t value) +{ + EM_WR(EM_PRIOLVL_ADDR + elt_idx * REG_EM_ET_SIZE, value); +} + +// field definitions +#define EM_SCH_PRIO3_MASK ((uint16_t)0x00001F00) +#define EM_SCH_PRIO3_LSB 8 +#define EM_SCH_PRIO3_WIDTH ((uint16_t)0x00000005) +#define EM_SCH_PRIO2_MASK ((uint16_t)0x0000001F) +#define EM_SCH_PRIO2_LSB 0 +#define EM_SCH_PRIO2_WIDTH ((uint16_t)0x00000005) + +#define EM_SCH_PRIO3_RST 0x0 +#define EM_SCH_PRIO2_RST 0x0 + +__INLINE void em_priolvl_pack(int elt_idx, uint8_t schprio3, uint8_t schprio2) +{ + BLE_ASSERT_ERR((((uint16_t)schprio3 << 8) & ~((uint16_t)0x00001F00)) == 0); + BLE_ASSERT_ERR((((uint16_t)schprio2 << 0) & ~((uint16_t)0x0000001F)) == 0); + EM_WR(EM_PRIOLVL_ADDR + elt_idx * REG_EM_ET_SIZE, ((uint16_t)schprio3 << 8) | ((uint16_t)schprio2 << 0)); +} + +__INLINE void em_priolvl_unpack(int elt_idx, uint8_t* schprio3, uint8_t* schprio2) +{ + uint16_t localVal = EM_RD(EM_PRIOLVL_ADDR + elt_idx * REG_EM_ET_SIZE); + + *schprio3 = (localVal & ((uint16_t)0x00001F00)) >> 8; + *schprio2 = (localVal & ((uint16_t)0x0000001F)) >> 0; +} + +__INLINE uint8_t em_priolvl_sch_prio3_getf(int elt_idx) +{ + uint16_t localVal = EM_RD(EM_PRIOLVL_ADDR + elt_idx * REG_EM_ET_SIZE); + return ((localVal & ((uint16_t)0x00001F00)) >> 8); +} + +__INLINE void em_priolvl_sch_prio3_setf(int elt_idx, uint8_t schprio3) +{ + BLE_ASSERT_ERR((((uint16_t)schprio3 << 8) & ~((uint16_t)0x00001F00)) == 0); + EM_WR(EM_PRIOLVL_ADDR + elt_idx * REG_EM_ET_SIZE, (EM_RD(EM_PRIOLVL_ADDR + elt_idx * REG_EM_ET_SIZE) & ~((uint16_t)0x00001F00)) | ((uint16_t)schprio3 << 8)); +} + +__INLINE uint8_t em_priolvl_sch_prio2_getf(int elt_idx) +{ + uint16_t localVal = EM_RD(EM_PRIOLVL_ADDR + elt_idx * REG_EM_ET_SIZE); + return ((localVal & ((uint16_t)0x0000001F)) >> 0); +} + +__INLINE void em_priolvl_sch_prio2_setf(int elt_idx, uint8_t schprio2) +{ + BLE_ASSERT_ERR((((uint16_t)schprio2 << 0) & ~((uint16_t)0x0000001F)) == 0); + EM_WR(EM_PRIOLVL_ADDR + elt_idx * REG_EM_ET_SIZE, (EM_RD(EM_PRIOLVL_ADDR + elt_idx * REG_EM_ET_SIZE) & ~((uint16_t)0x0000001F)) | ((uint16_t)schprio2 << 0)); +} + +/** + * @brief PTI_VXCHAN register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  12:08             PTI_PRIO   0x0
+ *  01:00               VXCHAN   0x0
+ * 
+ */ +#define EM_PTI_VXCHAN_ADDR (0x0091000E + EM_ET_OFFSET) +#define EM_PTI_VXCHAN_INDEX 0x00000007 +#define EM_PTI_VXCHAN_RESET 0x00000000 + +__INLINE uint16_t em_pti_vxchan_get(int elt_idx) +{ + return EM_RD(EM_PTI_VXCHAN_ADDR + elt_idx * REG_EM_ET_SIZE); +} + +__INLINE void em_pti_vxchan_set(int elt_idx, uint16_t value) +{ + EM_WR(EM_PTI_VXCHAN_ADDR + elt_idx * REG_EM_ET_SIZE, value); +} + +// field definitions +#define EM_PTI_PRIO_MASK ((uint16_t)0x00001F00) +#define EM_PTI_PRIO_LSB 8 +#define EM_PTI_PRIO_WIDTH ((uint16_t)0x00000005) +#define EM_VXCHAN_MASK ((uint16_t)0x00000003) +#define EM_VXCHAN_LSB 0 +#define EM_VXCHAN_WIDTH ((uint16_t)0x00000002) + +#define EM_PTI_PRIO_RST 0x0 +#define EM_VXCHAN_RST 0x0 + +__INLINE void em_pti_vxchan_pack(int elt_idx, uint8_t ptiprio, uint8_t vxchan) +{ + BLE_ASSERT_ERR((((uint16_t)ptiprio << 8) & ~((uint16_t)0x00001F00)) == 0); + BLE_ASSERT_ERR((((uint16_t)vxchan << 0) & ~((uint16_t)0x00000003)) == 0); + EM_WR(EM_PTI_VXCHAN_ADDR + elt_idx * REG_EM_ET_SIZE, ((uint16_t)ptiprio << 8) | ((uint16_t)vxchan << 0)); +} + +__INLINE void em_pti_vxchan_unpack(int elt_idx, uint8_t* ptiprio, uint8_t* vxchan) +{ + uint16_t localVal = EM_RD(EM_PTI_VXCHAN_ADDR + elt_idx * REG_EM_ET_SIZE); + + *ptiprio = (localVal & ((uint16_t)0x00001F00)) >> 8; + *vxchan = (localVal & ((uint16_t)0x00000003)) >> 0; +} + +__INLINE uint8_t em_pti_vxchan_pti_prio_getf(int elt_idx) +{ + uint16_t localVal = EM_RD(EM_PTI_VXCHAN_ADDR + elt_idx * REG_EM_ET_SIZE); + return ((localVal & ((uint16_t)0x00001F00)) >> 8); +} + +__INLINE void em_pti_vxchan_pti_prio_setf(int elt_idx, uint8_t ptiprio) +{ + BLE_ASSERT_ERR((((uint16_t)ptiprio << 8) & ~((uint16_t)0x00001F00)) == 0); + EM_WR(EM_PTI_VXCHAN_ADDR + elt_idx * REG_EM_ET_SIZE, (EM_RD(EM_PTI_VXCHAN_ADDR + elt_idx * REG_EM_ET_SIZE) & ~((uint16_t)0x00001F00)) | ((uint16_t)ptiprio << 8)); +} + +__INLINE uint8_t em_pti_vxchan_vxchan_getf(int elt_idx) +{ + uint16_t localVal = EM_RD(EM_PTI_VXCHAN_ADDR + elt_idx * REG_EM_ET_SIZE); + return ((localVal & ((uint16_t)0x00000003)) >> 0); +} + +__INLINE void em_pti_vxchan_vxchan_setf(int elt_idx, uint8_t vxchan) +{ + BLE_ASSERT_ERR((((uint16_t)vxchan << 0) & ~((uint16_t)0x00000003)) == 0); + EM_WR(EM_PTI_VXCHAN_ADDR + elt_idx * REG_EM_ET_SIZE, (EM_RD(EM_PTI_VXCHAN_ADDR + elt_idx * REG_EM_ET_SIZE) & ~((uint16_t)0x00000003)) | ((uint16_t)vxchan << 0)); +} + + +#endif // _REG_EM_ET_H_ + diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/lib_source.txt b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/lib_source.txt new file mode 100755 index 0000000..243014c --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/lib_source.txt @@ -0,0 +1,113 @@ +./ip/ble/hl/src/gap/gapc/gapc.c +./ip/ble/hl/src/gap/gapc/gapc_cte.c +./ip/ble/hl/src/gap/gapc/gapc_hci.c +./ip/ble/hl/src/gap/gapc/gapc_past.c +./ip/ble/hl/src/gap/gapc/gapc_sig.c +./ip/ble/hl/src/gap/gapc/gapc_smp.c +./ip/ble/hl/src/gap/gapc/gapc_task.c +./ip/ble/hl/src/gap/gapm/gapm.c +./ip/ble/hl/src/gap/gapm/gapm_actv.c +./ip/ble/hl/src/gap/gapm/gapm_addr.c +./ip/ble/hl/src/gap/gapm/gapm_adv.c +./ip/ble/hl/src/gap/gapm/gapm_cfg.c +./ip/ble/hl/src/gap/gapm/gapm_init.c +./ip/ble/hl/src/gap/gapm/gapm_list.c +./ip/ble/hl/src/gap/gapm/gapm_per_sync.c +./ip/ble/hl/src/gap/gapm/gapm_scan.c +./ip/ble/hl/src/gap/gapm/gapm_smp.c +./ip/ble/hl/src/gap/gapm/gapm_task.c +./ip/ble/hl/src/gatt/attc/attc.c +./ip/ble/hl/src/gatt/attm/attm.c +./ip/ble/hl/src/gatt/attm/attm_db.c +./ip/ble/hl/src/gatt/atts/atts.c +./ip/ble/hl/src/gatt/gattc/gattc.c +./ip/ble/hl/src/gatt/gattc/gattc_rc.c +./ip/ble/hl/src/gatt/gattc/gattc_sdp.c +./ip/ble/hl/src/gatt/gattc/gattc_svc.c +./ip/ble/hl/src/gatt/gattc/gattc_task.c +./ip/ble/hl/src/gatt/gattm/gattm.c +./ip/ble/hl/src/gatt/gattm/gattm_task.c +./ip/ble/hl/src/l2c/l2cc/l2cc.c +./ip/ble/hl/src/l2c/l2cc/l2cc_lecb.c +./ip/ble/hl/src/l2c/l2cc/l2cc_pdu.c +./ip/ble/hl/src/l2c/l2cc/l2cc_sig.c +./ip/ble/hl/src/l2c/l2cc/l2cc_task.c +./ip/ble/hl/src/l2c/l2cm/l2cm.c +./ip/ble/hl/src/rwble_hl/rwble_hl.c +./ip/ble/ll/src/co/ble_util_buf.c +./ip/ble/ll/src/co/rwble.c +./ip/ble/ll/src/llc/llc.c +./ip/ble/ll/src/llc/llc_chmap_upd.c +./ip/ble/ll/src/llc/llc_clk_acc.c +./ip/ble/ll/src/llc/llc_con_upd.c +./ip/ble/ll/src/llc/llc_cte.c +./ip/ble/ll/src/llc/llc_dbg.c +./ip/ble/ll/src/llc/llc_disconnect.c +./ip/ble/ll/src/llc/llc_dl_upd.c +./ip/ble/ll/src/llc/llc_encrypt.c +./ip/ble/ll/src/llc/llc_feat_exch.c +./ip/ble/ll/src/llc/llc_hci.c +./ip/ble/ll/src/llc/llc_le_ping.c +./ip/ble/ll/src/llc/llc_llcp.c +./ip/ble/ll/src/llc/llc_past.c +./ip/ble/ll/src/llc/llc_phy_upd.c +./ip/ble/ll/src/llc/llc_task.c +./ip/ble/ll/src/llc/llc_ver_exch.c +./ip/ble/ll/src/lld/lld.c +./ip/ble/ll/src/lld/lld_adv.c +./ip/ble/ll/src/lld/lld_con.c +./ip/ble/ll/src/lld/lld_init.c +./ip/ble/ll/src/lld/lld_per_adv.c +./ip/ble/ll/src/lld/lld_scan.c +./ip/ble/ll/src/lld/lld_sync.c +./ip/ble/ll/src/lld/lld_test.c +./ip/ble/ll/src/llm/llm.c +./ip/ble/ll/src/llm/llm_adv.c +./ip/ble/ll/src/llm/llm_hci.c +./ip/ble/ll/src/llm/llm_init.c +./ip/ble/ll/src/llm/llm_scan.c +./ip/ble/ll/src/llm/llm_task.c +./ip/ble/ll/src/llm/llm_test.c +./ip/hci/src/hci.c +./ip/hci/src/hci_fc.c +./ip/hci/src/hci_msg.c +./ip/hci/src/hci_tl.c +./ip/sch/src/sch_alarm.c +./ip/sch/src/sch_arb.c +./ip/sch/src/sch_plan.c +./ip/sch/src/sch_prog.c +./ip/sch/src/sch_slice.c +./modules/aes/src/aes.c +./modules/aes/src/aes_c1.c +./modules/aes/src/aes_ccm.c +./modules/aes/src/aes_cmac.c +./modules/aes/src/aes_f4.c +./modules/aes/src/aes_f5.c +./modules/aes/src/aes_f6.c +./modules/aes/src/aes_g2.c +./modules/aes/src/aes_k1.c +./modules/aes/src/aes_k2.c +./modules/aes/src/aes_k3.c +./modules/aes/src/aes_k4.c +./modules/aes/src/aes_rpa.c +./modules/aes/src/aes_s1.c +./modules/common/src/common_list.c +./modules/common/src/common_utils.c +./modules/dbg/src/dbg.c +./modules/dbg/src/dbg_iqgen.c +./modules/dbg/src/dbg_mwsgen.c +./modules/dbg/src/dbg_swdiag.c +./modules/dbg/src/dbg_task.c +./modules/dbg/src/dbg_trc.c +./modules/dbg/src/dbg_trc_mem.c +./modules/dbg/src/dbg_trc_tl.c +./modules/ecc_p256/src/ecc_p256.c +./modules/h4tl/src/h4tl.c +./modules/ke/src/kernel.c +./modules/ke/src/kernel_event.c +./modules/ke/src/kernel_mem.c +./modules/ke/src/kernel_msg.c +./modules/ke/src/kernel_queue.c +./modules/ke/src/kernel_task.c +./modules/ke/src/kernel_timer.c +./modules/rwip/rwip_driver.c diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/aes/api/ble_aes.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/aes/api/ble_aes.h new file mode 100755 index 0000000..04870d1 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/aes/api/ble_aes.h @@ -0,0 +1,368 @@ +/** + **************************************************************************************** + * + * @file ble_aes.h + * + * @brief Header file for AES crypto module + * + * Copyright (C) RivieraWaves 2017-2018 + * + **************************************************************************************** + */ + +#ifndef AES_H_ +#define AES_H_ + +/** + **************************************************************************************** + * @defgroup AES Crypto module + * @ingroup ROOT + * @brief AES Crypto module + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_config.h" + +#include "common_bt.h" // Common defines + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Call back definition of the function that can handle result of an AES based algorithm + * + * @param[in] status Execution status + * @param[in] ble_aes_res 16 bytes block result + * @param[in] src_info Information provided by requester + **************************************************************************************** + */ +typedef void (*ble_aes_func_result_cb) (uint8_t status, const uint8_t* ble_aes_res, uint32_t src_info); + +/** + **************************************************************************************** + * @brief Call back definition of the function that can handle result of AES-CCM Cipher/Decipher + * + * @param[in] mic_error True if a MIC error detected when Decipher, False else + * In case of MIC error output message is considered invalid + * @param[in] src_info Information provided by requester + **************************************************************************************** + */ +typedef void (*ble_aes_ccm_func_result_cb) (bool mic_error, uint32_t src_info); + +#if (BLE_EMB_PRESENT || BLE_HOST_PRESENT) +/** + **************************************************************************************** + * @brief Call back definition of the Resolvable Private Address resolution function + * + * @param[in] index Index of the IRK used to resolve the provided RPA (number of IRK if not resolved) + * @param[in] src_info Information provided by requester + **************************************************************************************** + */ +typedef void (*ble_aes_rpa_func_result_cb) (uint8_t index, uint32_t src_info); +#endif // (BLE_EMB_PRESENT || BLE_HOST_PRESENT) + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Initialize AES function management + * +* @param[in] init_type Type of initialization (@see enum rwip_init_type) + **************************************************************************************** + */ +void ble_aes_init(uint8_t init_type); + +/** + **************************************************************************************** + * @brief Handler of AES execution (HW accelerator if BLE controller present, HCI Encrypt for BLE Host Stack) + * + * @param[in] status Status of AES execution + * @param[in] result 16 bytes result of AES execution + **************************************************************************************** + */ +void ble_aes_result_handler(uint8_t status, uint8_t* result); + +/** + **************************************************************************************** + * @brief Perform an AES encryption - result within callback + * @param[in] key Key used for the encryption + * @param[in] val Value to encrypt using AES + * @param[in] copy Copy parameters because source is destroyed + * @param[in] res_cb Function that will handle the AES based result (16 bytes) + * @param[in] src_info Information used retrieve requester + **************************************************************************************** + */ +void ble_aes_encrypt(const uint8_t* key, const uint8_t *val, bool copy, ble_aes_func_result_cb res_cb, uint32_t src_info); + +/** + **************************************************************************************** + * @brief Generate a random number using AES encryption - result within callback + * + * @param[in] res_cb Function that will handle the AES based result (16 bytes) + * @param[in] src_info Information used retrieve requester + **************************************************************************************** + */ +void ble_aes_rand(ble_aes_func_result_cb res_cb, uint32_t src_info); + +#if (BLE_HOST_PRESENT) + +/** + **************************************************************************************** + * @brief Compute Confirm value + * + * @param[in] k Key used for aes functions + * @param[in] r Random number + * @param[in] p1 p1 = pres || preq || rat || iat + * @param[in] p2 p2 = padding || ia || ra + * @param[in] res_cb Function that will handle the AES based result (16 bytes) + * @param[in] src_info Information used retrieve requester + **************************************************************************************** + */ +void ble_aes_c1(const uint8_t* k, const uint8_t* r, const uint8_t* p1, const uint8_t* p2, + ble_aes_func_result_cb res_cb, uint32_t src_info); + +/** + **************************************************************************************** + * @brief Compute LE Secure Connections Confirm Value Generation Function f4 + * + * @param[in] u U is 256 bits + * @param[in] v V is 256 bits + * @param[in] x X is 128 bits + * @param[in] z Z is 8 bits + * @param[in] res_cb Function that will handle the AES based result (16 bytes) + * @param[in] src_info Information used retrieve requester + **************************************************************************************** + */ +void ble_aes_f4(const uint8_t* u, const uint8_t* v, const uint8_t* x, uint8_t z, + ble_aes_func_result_cb res_cb, uint32_t src_info); + +/** + **************************************************************************************** + * @brief Compute LE Secure Connections Key Generation Function f5 + * + * @param[in] w W is 256 bits + * @param[in] n1 N1 is 128 bits + * @param[in] n2 N2 is 128 bits + * @param[in] a1 A1 is 56 bits + * @param[in] a2 A2 is 56 bits + * @param[in] res_cb Function that will handle the AES based result (16 bytes) + * @param[in] src_info Information used retrieve requester + **************************************************************************************** + */ +void ble_aes_f5(const uint8_t* w, const uint8_t* n1, const uint8_t* n2, const uint8_t* a1, const uint8_t* a2, + ble_aes_func_result_cb res_cb, uint32_t src_info); + + +/** + **************************************************************************************** + * @brief Compute LE Secure Connections Check Value Generation Function f6 + * + * @param[in] w W is 128 bits + * @param[in] n1 N1 is 128 bits + * @param[in] n2 N2 is 128 bits + * @param[in] r R is 128 bits + * @param[in] iocap IOcap is 24 bits + * @param[in] a1 A1 is 56 bits + * @param[in] a2 A2 is 56 bits + * + * @param[in] res_cb Function that will handle the AES based result (16 bytes) + * @param[in] src_info Information used retrieve requester + **************************************************************************************** + */ +void ble_aes_f6(const uint8_t* w, const uint8_t* n1, const uint8_t* n2, const uint8_t* r, const uint8_t* iocap, + const uint8_t* a1, const uint8_t* a2, ble_aes_func_result_cb res_cb, uint32_t src_info); + +/** + **************************************************************************************** + * @brief Compute LE Secure Connections Numeric Comparison Value Generation Function g2 + * + * @param[in] u U is 256 bits + * @param[in] v V is 256 bits + * @param[in] x X is 128 bits + * @param[in] y Y is 128 bits + * + * @param[in] res_cb Function that will handle the AES based result (16 bytes) + * @param[in] src_info Information used retrieve requester + **************************************************************************************** + */ +void ble_aes_g2(const uint8_t* u, const uint8_t* v, const uint8_t* x, const uint8_t* y, + ble_aes_func_result_cb res_cb, uint32_t src_info); +#endif // (BLE_HOST_PRESENT) + + + +#if (BLE_EMB_PRESENT || BLE_HOST_PRESENT) + +/** + **************************************************************************************** + * @brief Start the AES CMAC crypto function. Allocate memory for the CMAC and + * begins the subkey generation + * + * @param[in] key Pointer to the Key to be used + * @param[in] message Pointer to the block of data the data on which the CMAC is performed + * @param[in] message_len Length (in bytes) of the block of data M + * @param[in] res_cb Function that will handle the AES based result (16 bytes) + * @param[in] src_info Information used retrieve requester + **************************************************************************************** + */ +void ble_aes_cmac(const uint8_t* key, const uint8_t* message, uint16_t message_len, + ble_aes_func_result_cb res_cb, uint32_t src_info); + +#if (BLE_MESH) + +/** + **************************************************************************************** + * @brief Start the AES S1 crypto function. + * + * @param[in] message Message used to generate Salted key + * @param[in] message_len Length (in bytes) of the block of data M + * @param[in] res_cb Function that will handle the AES based result (16 bytes) + * @param[in] src_info Information used retrieve requester + **************************************************************************************** + */ +void ble_aes_s1(const uint8_t* message, uint8_t message_len, ble_aes_func_result_cb res_cb, uint32_t src_info); + +/** + **************************************************************************************** + * @brief Start the AES K1 crypto function. + * + * @param[in] salt Salted Key to use + * @param[in] n Value of N + * @param[in] n_len Length of N + * @param[in] p Value of P + * @param[in] p_len Length of P + * @param[in] res_cb Function that will handle the AES based result (16 bytes) + * @param[in] src_info Information used retrieve requester + **************************************************************************************** + */ +void ble_aes_k1(const uint8_t* salt, const uint8_t* n, uint8_t n_len, const uint8_t* p, uint8_t p_len, + ble_aes_func_result_cb res_cb, uint32_t src_info); + +/** + **************************************************************************************** + * @brief Start the AES K2 crypto function. + * + * @param[in] n Value of N - 128 bits + * @param[in] p Value of P + * @param[in] p_len Length of P + * @param[in] res_cb Function that will handle the AES based result (33 bytes) + * @param[in] src_info Information used retrieve requester + **************************************************************************************** + */ +void ble_aes_k2(const uint8_t* n, const uint8_t* p, uint8_t p_len, ble_aes_func_result_cb res_cb, uint32_t src_info); + + +/** + **************************************************************************************** + * @brief Start the AES K3 crypto function. + * + * @param[in] n Value of N - 128 bits + * @param[in] res_cb Function that will handle the AES based result (8 bytes) + * @param[in] src_info Information used retrieve requester + **************************************************************************************** + */ +void ble_aes_k3(const uint8_t* n, ble_aes_func_result_cb res_cb, uint32_t src_info); + +/** + **************************************************************************************** + * @brief Start the AES K4 crypto function. + * + * @param[in] n Value of N - 128 bits + * @param[in] res_cb Function that will handle the AES based result (1 byte) + * @param[in] src_info Information used retrieve requester + **************************************************************************************** + */ +void ble_aes_k4(const uint8_t* n, ble_aes_func_result_cb res_cb, uint32_t src_info); + + +/** + **************************************************************************************** + * @brief Start the AES CCM crypto function. Allocate memory for the CCM and start processing it + * Execute result callback at end of function execution + * + * @param[in] key Pointer to the Key to be used + * @param[in] nonce 13 Bytes Nonce to use for cipher/decipher + * @param[in] in_message Input message for AES-CCM exectuion + * @param[out] out_message Output message that will contain cipher+mic or decipher data + * @param[in] message_len Length of Input/Output message without mic + * @param[in] mic_len Length of the mic to use (2, 4, 6, 8, 10, 12, 14, 16 valid) + * @param[in] cipher True to encrypt message, False to decrypt it. + * @param[in] add_auth_data Additional Authentication data used for computation of MIC + * @param[in] add_auth_data_len Length of Additional Authentication data + * @param[in] res_cb Function that will handle the AES CCM result + * @param[in] src_info Information used retrieve requester + **************************************************************************************** + */ +void ble_aes_ccm(const uint8_t* key, const uint8_t* nonce, const uint8_t* in_message, + uint8_t* out_message, uint16_t message_len, uint8_t mic_len, bool cipher, + const uint8_t* add_auth_data, uint8_t add_auth_data_len, ble_aes_ccm_func_result_cb res_cb, uint32_t src_info); +#endif // (BLE_MESH) + +/** + **************************************************************************************** + * @brief Group Session Key Derivation Function h8 + * + * @param[in] k K is a 128bits data + * @param[in] s S is a 128bits key + * @param[in] keyId KeyID is a 32 bits data + * @param[in] res_cb Function that will handle the AES CCM result + * @param[in] src_info Information used retrieve requester + **************************************************************************************** + */ +void ble_aes_h8(const uint8_t* k, const uint8_t* s, const uint8_t* key_id, ble_aes_func_result_cb res_cb, uint32_t src_info); + +/** + **************************************************************************************** + * @brief Group Long Term Key Generation Function h9 + * + * @param[in] w W is a 128bits data + * @param[in] keyId KeyID is a 32 bits data + * @param[in] res_cb Function that will handle the AES CCM result + * @param[in] src_info Information used retrieve requester + **************************************************************************************** + */ +void ble_aes_h9(const uint8_t* w, const uint8_t* key_id, ble_aes_func_result_cb res_cb, uint32_t src_info); + +#endif // (BLE_EMB_PRESENT || BLE_HOST_PRESENT) + +#if (BLE_EMB_PRESENT || BLE_HOST_PRESENT) +/** + **************************************************************************************** + * @brief Resolvable Private Address generation Function + * + * @param[in] irk Pointer to IRK (local IRK to generate a local RPA) + * @param[in] res_cb Function that will handle the AES RPA generation result (address generated in the 6 LSBs of the returned buffer) + * @param[in] src_info Information used retrieve requester + **************************************************************************************** + */ +void ble_aes_rpa_gen(struct irk* irk, ble_aes_func_result_cb res_cb, uint32_t src_info); + +/** + **************************************************************************************** + * @brief Resolvable Private Address resolution Function + * + * @param[in] nb_irk Number of IRKs provided + * @param[in] irk Table of IRKs (stored internally to AES RPA, caller can destroy the table) + * @param[in] addr BD address to resolve + * @param[in] res_cb Function that will handle the AES RPA resolution result + * @param[in] src_info Information used retrieve requester + **************************************************************************************** + */ +void ble_aes_rpa_resolve(uint8_t nb_irk, struct irk* irk, struct bd_addr* addr, ble_aes_rpa_func_result_cb res_cb, uint32_t src_info); + +#endif // (BLE_EMB_PRESENT || BLE_HOST_PRESENT) + +/// @} AES +/// +#endif /* AES_H_ */ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/aes/src/ble_aes_int.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/aes/src/ble_aes_int.h new file mode 100755 index 0000000..0c9bf5e --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/aes/src/ble_aes_int.h @@ -0,0 +1,197 @@ +/** + **************************************************************************************** + * + * @file ble_aes_int.h + * + * @brief Header file for AES Internal crypto module + * + * Copyright (C) RivieraWaves 2017-2018 + * + **************************************************************************************** + */ + +#ifndef AES_INT_H_ +#define AES_INT_H_ + +/** + **************************************************************************************** + * @defgroup AES_INT + * @ingroup AES + * @brief AES_INT Crypto internal definitions + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_config.h" +#include "ble_aes.h" + + +#include "common_bt.h" // Common defines +#include "common_list.h" // List usage + +/* + * Defines + **************************************************************************************** + */ + +// Size of an a AES Message block in bytes +#define AES_BLOCK_SIZE 16 + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ +struct ble_aes_func_env; + +/** + **************************************************************************************** + * Callback used to continue execution of the AES based function. + * + * @param[in] ble_aes_result Result of the AES (aes(key , val)) + * + * @return True if function execution is over + **************************************************************************************** + */ +typedef bool (*ble_aes_func_continue_cb) (struct ble_aes_func_env* ble_aes_env, uint8_t* ble_aes_result); + +/// Environment variable required for an AES based function +/// This structure must be Header of all function environment variables +struct ble_aes_func_env +{ + /// used to put AES function in the AES execution queue + struct common_list_hdr hdr; + /// AES continue callback + ble_aes_func_continue_cb ble_aes_continue_cb; + /// AES End callback + ble_aes_func_result_cb ble_aes_res_cb; + + /// Key to use for the AES execution + const uint8_t* key; + /// Value to use for AES Cypher/Decypher + const uint8_t* val; + /// Information put in source id message to retrieve requester + uint32_t src_info; +}; + +#if (BLE_EMB_PRESENT || BLE_HOST_PRESENT) +// Structure definition of the AES CMAC algorithm +struct ble_aes_cmac_env +{ + /// AES Environment structure + struct ble_aes_func_env ble_aes_env; + + /// M: Pointer to the message to be authenticated + const uint8_t* message; // pointer to memory allocated by calling function + + /// K: authentication key + const uint8_t* auth_key; + + /// T: message authentication code + uint8_t auth_code[AES_BLOCK_SIZE]; + + /// Length of the message + uint16_t message_len; + /// Number of blocks (1 block = 16 bytes) + uint8_t num_blocks; + /// Current block to process + uint8_t cur_block; +}; +#endif // (BLE_EMB_PRESENT || BLE_HOST_PRESENT) + +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ + +/// zero block +extern const uint8_t ble_aes_cmac_zero[AES_BLOCK_SIZE]; + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Allocate environment for the AES based function execution + * + * @param[in] size Size of the environment to allocate (must be >= sizeof(struct ble_aes_func_env)) + * @param[in] ble_aes_continue_cb Callback used to send the AES result + * @param[in] res_cb Function that will handle end of AES Based algorithm + * @param[in] src_info Information used to retrieve requester + * + * @return Allocated environment variable + **************************************************************************************** + */ +struct ble_aes_func_env* ble_aes_alloc(uint16_t size, ble_aes_func_continue_cb ble_aes_continue_cb, ble_aes_func_result_cb res_cb, + uint32_t src_info); + +/** + **************************************************************************************** + * @brief AES Cypher request function. + * + * This will queue AES request in the AES execution queue + * When the AES result is received, the AES continue callback is executed. + * + * If AES continue function returns that AES execution is over, a message will be send to destination task + * with latest AES result. + * + * @param[in] env AES environment + * @param[in] key Key used for cyphering + * @param[in] val Value to cypher + **************************************************************************************** + */ +void ble_aes_start(struct ble_aes_func_env* env, const uint8_t* key, const uint8_t *val); + +#if (BLE_EMB_PRESENT || BLE_HOST_PRESENT) +/** + **************************************************************************************** + * @brief Start the AES CMAC crypto function. Allocate memory for the CMAC and + * begins the subkey generation + * + * @param[in] enc AES CMAC Environment + * @param[in] key Pointer to the Key to be used + * @param[in] message Pointer to the block of data the data on which the CMAC is performed + * @param[in] message_len Length (in bytes) of the block of data M + **************************************************************************************** + */ +void ble_aes_cmac_start(struct ble_aes_cmac_env* env, const uint8_t* key, const uint8_t* message, uint16_t message_len); + +/** + **************************************************************************************** + * @brief Continue AES CMAC algorithm + * + * @param[in] env AES CMAC Environment + * @param[in] ble_aes_res AES Result + * + * @return True if algorithm is over, False else + **************************************************************************************** + */ +bool ble_aes_cmac_continue(struct ble_aes_cmac_env* env, uint8_t* ble_aes_res); + +/** + * @brief Perform a XOR of two numbers. + * + * @param[out] result Output 128 bits number: result = a ^ b + * @param[in] a first 128 bits operand + * @param[in] b second 128 bits operand + * @param[in] size number of bytes to XOR + */ +void ble_aes_xor_128(uint8_t* result, const uint8_t* a, const uint8_t* b, uint8_t size); + +/** + * @brief Perform shift left of a 128 bits numvber + * + * @param[in] input Input 128 bits number + * @param[out] output Output 128 bits number: output = input << 1 + */ +void ble_aes_shift_left_128(const uint8_t* input,uint8_t* output); +#endif // (BLE_EMB_PRESENT || BLE_HOST_PRESENT) + +/// @} AES_INT +/// +#endif /* AES_INT_H_ */ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/common/api/common_bt.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/common/api/common_bt.h new file mode 100755 index 0000000..0a38b9f --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/common/api/common_bt.h @@ -0,0 +1,62 @@ +/** + **************************************************************************************** + * + * @file common_bt.h + * + * @brief This file contains the common Bluetooth defines, enumerations and structures + * definitions for use by all modules in RW stack. + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef COMMON_BT_H_ +#define COMMON_BT_H_ + +/** + **************************************************************************************** + * @addtogroup COMMON Common SW Block + * @ingroup ROOT + * @brief The Common RW SW Block. + * + * The COMMON is the block with Bluetooth definitions and structures shared + * to all the protocol stack blocks. This also contain software wide error code + * definitions, mathematical functions, help functions, list and buffer definitions. + * + * @{ + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @addtogroup COMMON_BT Common Bluetooth defines + * @ingroup COMMON + * @brief Common Bluetooth definitions and structures. + * + * @{ + **************************************************************************************** + */ + + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include // standard boolean definitions +#include // standard definitions +#include // standard integer definitions + +/* + * DEFINES + **************************************************************************************** + */ + +#include "common_bt_defines.h" // Bluetooth defines +#include "common_lmp.h" // Bluetooth LMP definitions +#include "common_hci.h" // Bluetooth HCI definitions +#include "common_error.h" // Bluetooth error codes definitions + +/// @} COMMON_BT +#endif // COMMON_BT_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/common/api/common_bt_defines.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/common/api/common_bt_defines.h new file mode 100755 index 0000000..6c1d441 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/common/api/common_bt_defines.h @@ -0,0 +1,3213 @@ +/** + **************************************************************************************** + * + * @file common_bt_defines.h + * + * @brief This file contains the common Bluetooth defines, enumerations and structures + * definitions for use by all modules in RW stack. + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + +#ifndef COMMON_BT_DEFINES_H_ +#define COMMON_BT_DEFINES_H_ + + +/** + **************************************************************************************** + * @addtogroup COMMON_BT_DEFINES Common Bluetooth defines + * @ingroup COMMON_BT + * @brief Common Bluetooth definitions and structures. + * + * @{ + **************************************************************************************** + */ + + +/* + * DEFINES + **************************************************************************************** + */ + +/// Bluetooth technologies version +#define BT40_VERSION (6) +#define BT41_VERSION (7) +#define BT42_VERSION (8) +#define BT50_VERSION (9) +#define BT51_VERSION (10) + +/** + * BD Address format (values in bytes) + * | 3B | 1B | 2B | + * | LAP | UAP | NAP | + */ +#define BD_ADDR_LEN 6 +#define BD_ADDR_LAP_POS 0 +#define BD_ADDR_LAP_LEN 3 +#define BD_ADDR_UAP_POS BD_ADDR_LAP_LEN +#define BD_ADDR_UAP_LEN 1 +#define BD_ADDR_NAP_POS BD_ADDR_UAP_LEN +#define BD_ADDR_NAP_LEN 2 + +/** + * Resolvable private Address format (values in bytes) + * | 3B | 3B | + * | PRAND | HASH | + */ +/// Length of resolvable random address prand part +#define BD_ADDR_PRAND_LEN (3) +/// Length of resolvable random address hash part +#define BD_ADDR_HASH_LEN (3) + +/// Random Address type +enum random_addr_type +{ + /// Mask over the 2 MSBs + BD_ADDR_RND_ADDR_TYPE_MSK = 0xC0, + + /// Static random address - 11 (MSB->LSB) + BD_ADDR_STATIC = 0xC0, + /// Private non resolvable address - 00 (MSB->LSB) + BD_ADDR_NON_RSLV = 0x00, + /// Private resolvable address - 01 (MSB->LSB) + BD_ADDR_RSLV = 0x40, +}; + +///Length of fields in Bluetooth messages, in number of bytes +#define EVT_MASK_LEN 8 +#define DEV_CLASS_LEN 3 +#define ACO_LEN 12 +#define SRES_LEN 0x04 +#define ACCESS_ADDR_LEN 0x04 +#define LE_PASSKEY_LEN 0x04 +#define BD_NAME_SIZE 0xF8 // Was 0x20 for BLE HL +#define ADV_DATA_LEN 0x1F +#define EXT_ADV_DATA_MAX_LEN 229 // HCI:7.7.65.13 +#define PER_ADV_DATA_MAX_LEN 247 // 248 // HCI:7.7.65.16 +#define BLE_DATA_LEN 0x1B +#define SCAN_RSP_DATA_LEN 0x1F +#define CONNECT_REQ_DATA_LEN 0x16 +#define LE_CHNL_MAP_LEN 0x05 +#define CHNL_MAP_LEN 0x0A +#define KEY_LEN 0x10 +#define PIN_CODE_MIN_LEN 0x01 +#define PIN_CODE_MAX_LEN 0x10 +#define PRIV_KEY_192_LEN 24 +#define PUB_KEY_192_LEN 48 +#define PRIV_KEY_256_LEN 32 +#define PUB_KEY_256_LEN 64 +#define CFM_LEN 0x10 +#define ENC_DATA_LEN 0x10 +#define RAND_VAL_LEN 0x10 +#define RAND_NB_LEN 0x08 +#define LE_FEATS_LEN 0x08 +#define SUPP_CMDS_LEN 0x40 +#define FEATS_LEN 0x08 +#define NAME_VECT_SIZE 14 +#define LMP_FEATS_LEN 0x08 +#define LE_STATES_LEN 0x08 +#define WHITE_LIST_LEN 0x0A +#define LE_FREQ_LEN 0x28 +#define LE_DATA_FREQ_LEN 0x25 +#define CRC_INIT_LEN 0x03 +#define SESS_KEY_DIV_LEN 0x08 +#define INIT_VECT_LEN 0x04 +#define BLE_MIC_LEN 0x04 +#define BLE_IV_LEN 0x08 +#define SK_DIV_LEN 0x10 + +// Session Key Diversifier Master or slave +#define SKD_M_OFFSET 0x00 +#define SKD_S_OFFSET 0x08 +// Initialization Vector Master or slave +#define IV_M_OFFSET 0x00 +#define IV_S_OFFSET 0x04 + +// BT 4.2 - Secure Connections +#define PUBLIC_KEY_P256_LEN 0x20 +#define DHKEY_CHECK_LEN 0x10 + +#define DH_KEY_LEN 0x20 + +// BT 5.0 - Slot Availability Masks + +#define SAM_SUBMAPS_LEN 12 +#define SAM_TYPE0_SUBMAP_LEN 14 + +#define SAM_SLOT_NOT_AVAILABLE 0 +#define SAM_SLOT_TX_AVAILABLE 1 +#define SAM_SLOT_RX_AVAILABLE 2 +#define SAM_SLOT_TX_RX_AVAILABLE 3 + +#define SAM_INDEX_MAX 3 +#define SAM_INDEX_CONTINUE 3 +#define SAM_DISABLED 0xFF + +#define SAM_UPDATE_INVALIDATE_MAPS 0 +#define SAM_UPDATE_IMMEDIATE 1 +#define SAM_UPDATE_AT_SUBINTERVAL 2 + +#define T_SAM_SM_MIN 2 +#define T_SAM_SM_MAX 56 + +#define SAM_SLOTS_SUBMAPPED 0 +#define SAM_SLOTS_AVAILABLE 1 +#define SAM_SLOTS_UNAVAILABLE 2 + + +/// Maximum maskable event code +#define EVT_MASK_CODE_MAX EVT_MASK_LEN * 8 + +/// Default event mask +#define EVT_MASK_DEFAULT {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x9F, 0x00, 0x20} + +/// Advertising and Data Channel Indices (chapter 6.B.1.4.1) +#define DATA_CHANNEL_MIN 0 +#define DATA_CHANNEL_MAX 36 +#define DATA_CHANNEL_NB 37 +#define ADV_CHANNEL_37 37 +#define ADV_CHANNEL_38 38 +#define ADV_CHANNEL_39 39 + +/// Minimum number of used channel in the map (chapter 6.B.4.5.8.1) +#define DATA_CHANNEL_USED_NB_MIN 2 + +/// Advertising interval (in 625us slot) (chapter 2.E.7.8.5) +#define ADV_INTERVAL_MIN 0x0020 //(20 ms) +#define ADV_INTERVAL_MAX 0x4000 //(10.24 sec) +#define ADV_INTERVAL_DFT 0x0800 //(1.28 sec) + +/// Scanning interval (in 625us slot) (chapter 2.E.7.8.10) +#define SCAN_INTERVAL_MIN 0x0004 //(2.5 ms) +#define SCAN_INTERVAL_MAX 0x4000 //(10.24 sec) +#define SCAN_INTERVAL_DFT 0x0010 //(10 ms) + +/// Scanning window (in 625us slot) (chapter 2.E.7.8.10) +#define SCAN_WINDOW_MIN 0x0004 //(2.5 ms) +#define SCAN_WINDOW_MAX 0x4000 //(10.24 sec) +#define SCAN_WINDOW_DFT 0x0010 //(10 ms) + +/// Sync Timeout (in Time = N*10ms) +#define SYNC_TIMEOUT_MIN 0x000A //(100 ms) +#define SYNC_TIMEOUT_MAX 0x4000 //(163.84 s) + +/// Advertising SID valid Range +#define SYNC_SID_MIN 0x00 +#define SYNC_SID_MAX 0x0F + +/// Periodic Adv Skip valid Range +#define SYNC_SKIP_MIN 0x0000 +#define SYNC_SKIP_MAX 0x01F3 + +/// Connection interval (N*1.250ms) (chapter 2.E.7.8.12) +#if defined(CFG_ISO_MODE_0) +#define CON_INTERVAL_MIN_AUDIO 0x0002 //(2.5 msec) +#define CON_INTERVAL_MIN CON_INTERVAL_MIN_AUDIO +#else // !defined(CFG_ISO_MODE_0) +#define CON_INTERVAL_MIN 0x0006 //(7.5 msec) +#endif // defined(CFG_ISO_MODE_0) +#define CON_INTERVAL_MAX 0x0C80 //(4 sec) +/// Connection latency (N*cnx evt) (chapter 2.E.7.8.12) +#define CON_LATENCY_MIN 0x0000 +#define CON_LATENCY_MAX 0x01F3 // (499) +/// Supervision TO (N*10ms) (chapter 2.E.7.8.12) +#define CON_SUP_TO_MIN 0x000A //(100 msec) +#define CON_SUP_TO_MAX 0x0C80 //(32 sec) + +/// Format of the Advertising packets +#define ADV_ADDR_OFFSET 0 +#define ADV_ADDR_LEN BD_ADDR_LEN +#define ADV_DATA_OFFSET (ADV_ADDR_OFFSET + ADV_ADDR_LEN) + +/// List of supported BLE Features LL:4.6 +enum ble_feature +{ + //byte 0 + BLE_FEAT_ENC = (0), + BLE_FEAT_CON_PARAM_REQ_PROC = (1), + BLE_FEAT_EXT_REJ_IND = (2), + BLE_FEAT_SLAVE_INIT_FEAT_EXCHG = (3), + BLE_FEAT_PING = (4), + BLE_FEAT_DATA_PKT_LEN_EXT = (5), + BLE_FEAT_LL_PRIVACY = (6), + BLE_FEAT_EXT_SCAN_FILT_POLICY = (7), + //byte 1 + BLE_FEAT_2M_PHY = (8), + BLE_FEAT_STABLE_MOD_IDX_TX = (9), + BLE_FEAT_STABLE_MOD_IDX_RX = (10), + BLE_FEAT_CODED_PHY = (11), + BLE_FEAT_EXT_ADV = (12), + BLE_FEAT_PER_ADV = (13), + BLE_FEAT_CHAN_SEL_ALGO_2 = (14), + BLE_FEAT_PWR_CLASS_1 = (15), + //byte 2 + BLE_FEAT_MIN_NUM_USED_CHAN_PROC = (16), + BLE_FEAT_CON_CTE_REQ = (17), + BLE_FEAT_CON_CTE_RSP = (18), + BLE_FEAT_CONLESS_CTE_TX = (19), + BLE_FEAT_CONLESS_CTE_RX = (20), + BLE_FEAT_AOD = (21), + BLE_FEAT_AOA = (22), + BLE_FEAT_CTE_RX = (23), + //byte 3 + BLE_FEAT_PER_ADV_SYNC_TRANSF_TX = (24), + BLE_FEAT_PER_ADV_SYNC_TRANSF_RX = (25), + BLE_FEAT_SLEEP_CLK_ACC_UPD = (26), + BLE_FEAT_PUB_KEY_VALID = (27), +}; + +/// BLE supported states +//byte 0 +#define BLE_NON_CON_ADV_STATE 0x01 +#define BLE_DISC_ADV_STATE 0x02 +#define BLE_CON_ADV_STATE 0x04 +#define BLE_HDC_DIRECT_ADV_STATE 0x08 +#define BLE_PASS_SCAN_STATE 0x10 +#define BLE_ACTIV_SCAN_STATE 0x20 +#define BLE_INIT_MASTER_STATE 0x40 +#define BLE_CON_SLAVE_STATE 0x80 + +//byte 1 +#define BLE_NON_CON_ADV_PASS_SCAN_STATE 0x01 +#define BLE_DISC_ADV_PASS_SCAN_STATE 0x02 +#define BLE_CON_ADV_PASS_SCAN_STATE 0x04 +#define BLE_HDC_DIRECT_ADV_PASS_SCAN_STATE 0x08 +#define BLE_NON_CON_ADV_ACTIV_SCAN_STATE 0x10 +#define BLE_DISC_ADV_ACTIV_SCAN_STATE 0x20 +#define BLE_CON_ADV_ACTIV_SCAN_STATE 0x40 +#define BLE_HDC_DIRECT_ADV_ACTIV_SCAN_STATE 0x80 + +//byte 2 +#define BLE_NON_CON_ADV_INIT_STATE 0x01 +#define BLE_DISC_ADV_INIT_STATE 0x02 +#define BLE_NON_CON_ADV_MASTER_STATE 0x04 +#define BLE_DISC_ADV_MASTER_STATE 0x08 +#define BLE_NON_CON_ADV_SLAVE_STATE 0x10 +#define BLE_DISC_ADV_SLAVE_STATE 0x20 +#define BLE_PASS_SCAN_INIT_STATE 0x40 +#define BLE_ACTIV_SCAN_INIT_STATE 0x80 + +//byte 3 +#define BLE_PASS_SCAN_MASTER_STATE 0x01 +#define BLE_ACTIV_SCAN_MASTER_STATE 0x02 +#define BLE_PASS_SCAN_SLAVE_STATE 0x04 +#define BLE_ACTIV_SCAN_SLAVE_STATE 0x08 +#define BLE_INIT_MASTER_MASTER_STATE 0x10 +#define BLE_LDC_DIRECT_ADV_STATE 0x20 +#define BLE_LDC_DIRECT_ADV_PASS_SCAN_STATE 0x40 +#define BLE_LDC_DIRECT_ADV_ACTIV_SCAN_STATE 0x80 + +//byte 4 +#define BLE_CON_ADV_INIT_MASTER_SLAVE_STATE 0x01 +#define BLE_HDC_DIRECT_ADV_INIT_MASTER_SLAVE_STATE 0x02 +#define BLE_LDC_DIRECT_ADV_INIT_MASTER_SLAVE_STATE 0x04 +#define BLE_CON_ADV_MASTER_SLAVE_STATE 0x08 +#define BLE_HDC_DIRECT_ADV_MASTER_SLAVE_STATE 0x10 +#define BLE_LDC_DIRECT_ADV_MASTER_SLAVE_STATE 0x20 +#define BLE_CON_ADV_SLAVE_SLAVE_STATE 0x40 +#define BLE_HDC_DIRECT_ADV_SLAVE_SLAVE_STATE 0x80 + +//byte 5 +#define BLE_LDC_DIRECT_ADV_SLAVE_SLAVE_STATE 0x01 +#define BLE_INIT_MASTER_SLAVE_STATE 0x02 + +/// BLE supported commands +//byte0 +#define BLE_DISC_CMD 0x20 +//byte2 +#define BLE_RD_REM_VERS_CMD 0x80 +//byte5 +#define BLE_SET_EVT_MSK_CMD 0x40 +#define BLE_RESET_CMD 0x80 +//byte10 +#define BLE_RD_TX_PWR_CMD 0x04 +#define BLE_SET_CTRL_TO_HL_FCTRL_CMD 0x20 +#define BLE_HL_BUF_SIZE_CMD 0x40 +#define BLE_HL_NB_CMP_PKT_CMD 0x80 +//byte14 +#define BLE_RD_LOC_VERS_CMD 0x08 +#define BLE_RD_LOC_SUP_FEAT_CMD 0x20 +//byte15 +#define BLE_RD_BD_ADDR_CMD 0x02 +#define BLE_RD_RSSI_CMD 0x20 +//byte22 +#define BLE_SET_EVT_MSK_PG2_CMD 0x04 +//byte25 +#define BLE_LE_SET_EVT_MSK_CMD 0x01 +#define BLE_LE_RD_BUF_SIZE_CMD 0x02 +#define BLE_LE_RD_LOC_SUP_FEAT_CMD 0x04 +#define BLE_LE_SET_RAND_ADDR_CMD 0x10 +#define BLE_LE_SET_ADV_PARAM_CMD 0x20 +#define BLE_LE_RD_ADV_TX_PWR_CMD 0x40 +#define BLE_LE_SET_ADV_DATA_CMD 0x80 +//byte26 +#define BLE_LE_SET_SC_RSP_DATA_CMD 0x01 +#define BLE_LE_SET_ADV_EN_CMD 0x02 +#define BLE_LE_SET_SC_PARAM_CMD 0x04 +#define BLE_LE_SET_SC_EN_CMD 0x08 +#define BLE_LE_CREAT_CNX_CMD 0x10 +#define BLE_LE_CREAT_CNX_CNL_CMD 0x20 +#define BLE_LE_RD_WL_SIZE_CMD 0x40 +#define BLE_LE_CLEAR_WL_CMD 0x80 +//byte27 +#define BLE_LE_ADD_DEV_WL_CMD 0x01 +#define BLE_LE_REM_DEV_WL_CMD 0x02 +#define BLE_LE_CNX_UPDATE_CMD 0x04 +#define BLE_LE_SET_HL_CH_CLASS_CMD 0x08 +#define BLE_LE_RD_CH_MAP_CMD 0x10 +#define BLE_LE_RD_REM_FEAT_CMD 0x20 +#define BLE_LE_ENCRYPT_CMD 0x40 +#define BLE_LE_RAND_CMD 0x80 +//byte28 +#define BLE_LE_START_ENC_CMD 0x01 +#define BLE_LE_LTK_REQ_RPLY_CMD 0x02 +#define BLE_LE_LTK_REQ_NEG_RPLY_CMD 0x04 +#define BLE_LE_RD_SUPP_STATES_CMD 0x08 +#define BLE_LE_RX_TEST_V1_CMD 0x10 +#define BLE_LE_TX_TEST_V1_CMD 0x20 +#define BLE_LE_STOP_TEST_CMD 0x40 + +//byte32 +#define BLE_RD_AUTH_PAYL_TO_CMD 0x10 +#define BLE_WR_AUTH_PAYL_TO_CMD 0x20 + + +//byte33 +#define BLE_LE_REM_CON_PARA_REQ_RPLY_CMD 0x10 +#define BLE_LE_REM_CON_PARA_REQ_NEG_RPLY_CMD 0x20 +#define BLE_LE_SET_DATA_LEN_CMD 0x40 +#define BLE_LE_RD_SUGGTED_DFT_DATA_LEN_CMD 0x80 + +//byte34 +#define BLE_LE_WR_SUGGTED_DFT_DATA_LEN_CMD 0x01 +#define BLE_LE_RD_LOC_P256_PUB_KEY_CMD 0x02 +#define BLE_LE_GEN_DHKEY_V1_CMD 0x04 +#define BLE_LE_ADD_DEV_TO_RESOLV_LIST_CMD 0x08 +#define BLE_LE_REM_DEV_FROM_RESOLV_LIST_CMD 0x10 +#define BLE_LE_CLEAR_RESOLV_LIST_CMD 0x20 +#define BLE_LE_RD_RESOLV_LIST_SIZE_CMD 0x40 +#define BLE_LE_RD_PEER_RESOLV_ADDR_CMD 0x80 + +//byte35 +#define BLE_LE_RD_LOCAL_RESOLV_ADDR_CMD 0x01 +#define BLE_LE_SET_ADDR_RESOL_CMD 0x02 +#define BLE_LE_SET_RESOLV_PRIV_ADDR_TO_CMD 0x04 +#define BLE_LE_RD_MAX_DATA_LEN_CMD 0x08 +#define BLE_LE_RD_PHY_CMD 0x10 +#define BLE_LE_SET_DFT_PHY_CMD 0x20 +#define BLE_LE_SET_PHY_CMD 0x40 +#define BLE_LE_RX_TEST_V2_CMD 0x80 +//byte36 +#define BLE_LE_TX_TEST_V2_CMD 0x01 +#define BLE_LE_SET_ADV_SET_RAND_ADDR_CMD 0x02 +#define BLE_LE_SET_EXT_ADV_PARAM_CMD 0x04 +#define BLE_LE_SET_EXT_ADV_DATA_CMD 0x08 +#define BLE_LE_SET_EXT_SCAN_RSP_DATA_CMD 0x10 +#define BLE_LE_SET_EXT_ADV_EN_CMD 0x20 +#define BLE_LE_RD_MAX_ADV_DATA_LEN_CMD 0x40 +#define BLE_LE_RD_NB_SUPP_ADV_SETS_CMD 0x80 +//byte37 +#define BLE_LE_RMV_ADV_SET_CMD 0x01 +#define BLE_LE_CLEAR_ADV_SETS_CMD 0x02 +#define BLE_LE_SET_PER_ADV_PARAM_CMD 0x04 +#define BLE_LE_SET_PER_ADV_DATA_CMD 0x08 +#define BLE_LE_SET_PER_ADV_EN_CMD 0x10 +#define BLE_LE_SET_EXT_SCAN_PARAM_CMD 0x20 +#define BLE_LE_SET_EXT_SCAN_EN_CMD 0x40 +#define BLE_LE_EXT_CREATE_CON_CMD 0x80 +//byte38 +#define BLE_LE_PER_ADV_CREATE_SYNC_CMD 0x01 +#define BLE_LE_PER_ADV_CREATE_SYNC_CANCEL_CMD 0x02 +#define BLE_LE_PER_ADV_TERM_SYNC_CMD 0x04 +#define BLE_LE_ADD_DEV_TO_PER_ADV_LIST_CMD 0x08 +#define BLE_LE_RMV_DEV_FROM_PER_ADV_LIST_CMD 0x10 +#define BLE_LE_CLEAR_PER_ADV_LIST_CMD 0x20 +#define BLE_LE_RD_PER_ADV_LIST_SIZE_CMD 0x40 +#define BLE_LE_RD_TX_PWR_CMD 0x80 +//byte39 +#define BLE_LE_RD_RF_PATH_COMP_CMD 0x01 +#define BLE_LE_WR_RF_PATH_COMP_CMD 0x02 +#define BLE_LE_SET_PRIV_MODE_CMD 0x04 +#define BLE_LE_RX_TEST_V3_CMD 0x08 +#define BLE_LE_TX_TEST_V3_CMD 0x10 +#define BLE_LE_SET_CONLESS_CTE_TX_PARAM_CMD 0x20 +#define BLE_LE_SET_CONLESS_CTE_TX_EN_CMD 0x40 +#define BLE_LE_SET_CONLESS_IQ_SAMPL_EN_CMD 0x80 +//byte40 +#define BLE_LE_SET_CON_CTE_RX_PARAM_CMD 0x01 +#define BLE_LE_SET_CON_CTE_TX_PARAM_CMD 0x02 +#define BLE_LE_CON_CTE_REQ_EN_CMD 0x04 +#define BLE_LE_CON_CTE_RSP_EN_CMD 0x08 +#define BLE_LE_RD_ANTENNA_INF_CMD 0x10 +#define BLE_LE_SET_PER_ADV_RX_EN_CMD 0x20 +#define BLE_LE_PER_ADV_SYNC_TRANSF_CMD 0x40 +#define BLE_LE_PER_ADV_SET_INFO_TRANSF_CMD 0x80 +//byte41 +#define BLE_LE_SET_PER_ADV_SYNC_TRANSF_PARAM_CMD 0x01 +#define BLE_LE_SET_DFT_PER_ADV_SYNC_TRANSF_PARAM_CMD 0x02 +#define BLE_LE_GEN_DHKEY_V2_CMD 0x04 +#define BLE_LE_MOD_SLP_CLK_ACC_CMD 0x10 + + +// Inquiry Length HCI:7.1.1 +#define INQ_LEN_MIN 0x01 +#define INQ_LEN_MAX 0x30 + +// Inquiry Length HCI:7.1.3 +#define INQ_MIN_PER_LEN_MIN 0x0002 +#define INQ_MIN_PER_LEN_MAX 0xFFFE +#define INQ_MAX_PER_LEN_MIN 0x0003 +#define INQ_MAX_PER_LEN_MAX 0xFFFF + +// IAC support +#define NB_IAC_MIN 0x01 +#define NB_IAC_MAX 0x40 + +/// Most significant bit of the Bluetooth clock (in 312.5us half-slots) +#define BT_CLOCK_MSB (1L << 27) + +/// Logical Transport Adresses BB:4.2 +#define LT_ADDR_BCST 0x00 +#define LT_ADDR_MIN 0x01 +#define LT_ADDR_MAX 0x07 + +/// Link type HCI:7.7.3 +#define SCO_TYPE 0 +#define ACL_TYPE 1 +#define ESCO_TYPE 2 +#define UNKNOWN_TYPE 3 // Used in LM +#define LE_TYPE 4 + + +/// Allow Role Switch HCI:4.6.8 +#define MASTER_ROLE 0 +#define SLAVE_ROLE 1 +#define UNKNOWN_ROLE 0xFF //Used in LC to init the links role + +/// Link policy HCI:4.6.9 and HCI:4.6.10 +#define POLICY_SWITCH 0x0001 +#define POLICY_HOLD 0x0002 +#define POLICY_SNIFF 0x0004 +#define POLICY_PARK 0x0008 + +/// Allow Role Switch HCI:4.5.5 +#define ROLE_SWITCH_NOT_ALLOWED 0 +#define ROLE_SWITCH_ALLOWED 1 + +/// AcceptConnection Role HCI:4.5.8 +#define ACCEPT_SWITCH_TO_MASTER 0 +#define ACCEPT_REMAIN_SLAVE 1 + +/// Packet Type Flags HCI:7.1.14 +#define PACKET_TYPE_EDR_MSK 0x330E +#define PACKET_TYPE_GFSK_MSK 0xCCF8 +#define PACKET_TYPE_NO_2_DH1_FLAG 0x0002 +#define PACKET_TYPE_NO_3_DH1_FLAG 0x0004 +#define PACKET_TYPE_DM1_FLAG 0x0008 +#define PACKET_TYPE_DH1_FLAG 0x0010 +#define PACKET_TYPE_HV1_FLAG 0x0020 +#define PACKET_TYPE_HV2_FLAG 0x0040 +#define PACKET_TYPE_HV3_FLAG 0x0080 +#define PACKET_TYPE_NO_2_DH3_FLAG 0x0100 +#define PACKET_TYPE_NO_3_DH3_FLAG 0x0200 +#define PACKET_TYPE_DM3_FLAG 0x0400 +#define PACKET_TYPE_DH3_FLAG 0x0800 +#define PACKET_TYPE_NO_2_DH5_FLAG 0x1000 +#define PACKET_TYPE_NO_3_DH5_FLAG 0x2000 +#define PACKET_TYPE_DM5_FLAG 0x4000 +#define PACKET_TYPE_DH5_FLAG 0x8000 + +/// Synchronous Packet Types HCI:7.1.14 +#define SYNC_PACKET_TYPE_HV1_FLAG 0x0001 +#define SYNC_PACKET_TYPE_HV2_FLAG 0x0002 +#define SYNC_PACKET_TYPE_HV3_FLAG 0x0004 +#define SYNC_PACKET_TYPE_EV3_FLAG 0x0008 +#define SYNC_PACKET_TYPE_EV4_FLAG 0x0010 +#define SYNC_PACKET_TYPE_EV5_FLAG 0x0020 + +#define SYNC_PACKET_TYPE_NO_EV3_2_FLAG 0x0040 +#define SYNC_PACKET_TYPE_NO_EV3_3_FLAG 0x0080 +#define SYNC_PACKET_TYPE_NO_EV5_2_FLAG 0x0100 +#define SYNC_PACKET_TYPE_NO_EV5_3_FLAG 0x0200 + +#define SYNC_PACKET_TYPE_EV3_2_FLAG 0x0040 +#define SYNC_PACKET_TYPE_EV3_3_FLAG 0x0080 +#define SYNC_PACKET_TYPE_EV5_2_FLAG 0x0100 +#define SYNC_PACKET_TYPE_EV5_3_FLAG 0x0200 + +/// RWBT 1.2 +#define SYNC_EV3_PACKET_SIZE 30 +#define SYNC_EV4_PACKET_SIZE 120 +#define SYNC_EV5_PACKET_SIZE 180 + +/// Packet Boundary Flag HCI:5.4.2 +#define PBF_1ST_NF_HL_FRAG 0x00 // Non-flushable packets +#define PBF_CONT_HL_FRAG 0x01 +#define PBF_1ST_HL_FRAG 0x02 +#define PBF_CMP_PDU 0x03 +#define PBF_MASK 0x03 + +/// Broadcast Flag HCI:5.4.2 +#define BCF_P2P 0x00 +#define BCF_ACTIVE_SLV_BCST 0x01 +#define BCF_PARK_SLV_BCST 0x02 +#define BCF_MASK 0x03 + +/// Synchronous Packet Status Flag HCI:5.4.3 +#define CORRECTLY_RX_FLAG 0x00 +#define POSSIBLY_INVALID_FLAG 0x01 +#define NO_RX_DATA_FLAG 0x02 +#define PARTIALLY_LOST_FLAG 0x03 + +/// Park mode defines LMP:3.17 +#define MACCESS_MSK 0x0F +#define ACCSCHEM_MSK 0xF0 + +/// Support 3 feature pages +#define FEATURE_PAGE_MAX 3 + +#define FEATURE_PAGE_0 0 +#define FEATURE_PAGE_1 1 +#define FEATURE_PAGE_2 2 + +/// Feature mask definition LMP:3.3 +#define B0_3_SLOT_POS 0 +#define B0_3_SLOT_MSK 0x01 +#define B0_5_SLOT_POS 1 +#define B0_5_SLOT_MSK 0x02 +#define B0_ENC_POS 2 +#define B0_ENC_MSK 0x04 +#define B0_SLOT_OFF_POS 3 +#define B0_SLOT_OFF_MSK 0x08 +#define B0_TIMING_ACCU_POS 4 +#define B0_TIMING_ACCU_MSK 0x10 +#define B0_ROLE_SWITCH_POS 5 +#define B0_ROLE_SWITCH_MSK 0x20 +#define B0_HOLD_MODE_POS 6 +#define B0_HOLD_MODE_MSK 0x40 +#define B0_SNIFF_MODE_POS 7 +#define B0_SNIFF_MODE_MSK 0x80 + +#define B1_PARK_POS 0 +#define B1_PARK_MSK 0x01 +#define B1_RSSI_POS 1 +#define B1_RSSI_MSK 0x02 +#define B1_CQDDR_POS 2 +#define B1_CQDDR_MSK 0x04 +#define B1_SCO_POS 3 +#define B1_SCO_MSK 0x08 +#define B1_HV2_POS 4 +#define B1_HV2_MSK 0x10 +#define B1_HV3_POS 5 +#define B1_HV3_MSK 0x20 +#define B1_MULAW_POS 6 +#define B1_MULAW_MSK 0x40 +#define B1_ALAW_POS 7 +#define B1_ALAW_MSK 0x80 + +#define B2_CVSD_POS 0 +#define B2_CVSD_MSK 0x01 +#define B2_PAGING_PAR_NEGO_POS 1 +#define B2_PAGING_PAR_NEGO_MSK 0x02 +#define B2_PWR_CTRL_POS 2 +#define B2_PWR_CTRL_MSK 0x04 +#define B2_TRANSPARENT_SCO_POS 3 +#define B2_TRANSPARENT_SCO_MSK 0x08 +#define B2_FLOW_CTRL_LAG_POS 4 +#define B2_FLOW_CTRL_LAG_MSK 0x70 +#define B2_BCAST_ENC_POS 7 +#define B2_BCAST_ENC_MSK 0x80 + +#define B3_EDR_2MBPS_ACL_POS 1 +#define B3_EDR_2MBPS_ACL_MSK 0x02 +#define B3_EDR_3MBPS_ACL_POS 2 +#define B3_EDR_3MBPS_ACL_MSK 0x04 +#define B3_ENH_INQSCAN_POS 3 +#define B3_ENH_INQSCAN_MSK 0x08 +#define B3_INT_INQSCAN_POS 4 +#define B3_INT_INQSCAN_MSK 0x10 +#define B3_INT_PAGESCAN_POS 5 +#define B3_INT_PAGESCAN_MSK 0x20 +#define B3_RSSI_INQ_RES_POS 6 +#define B3_RSSI_INQ_RES_MSK 0x40 +#define B3_ESCO_EV3_POS 7 +#define B3_ESCO_EV3_MSK 0x80 + +#define B4_EV4_PKT_POS 0 +#define B4_EV4_PKT_MSK 0x01 +#define B4_EV5_PKT_POS 1 +#define B4_EV5_PKT_MSK 0x02 +#define B4_AFH_CAP_SLV_POS 3 +#define B4_AFH_CAP_SLV_MSK 0x08 +#define B4_AFH_CLASS_SLV_POS 4 +#define B4_AFH_CLASS_SLV_MSK 0x10 +#define B4_BR_EDR_NOT_SUPP_POS 5 +#define B4_BR_EDR_NOT_SUPP_MSK 0x20 +#define B4_LE_SUPP_POS 6 +#define B4_LE_SUPP_MSK 0x40 +#define B4_3_SLOT_EDR_ACL_POS 7 +#define B4_3_SLOT_EDR_ACL_MSK 0x80 + +#define B5_5_SLOT_EDR_ACL_POS 0 +#define B5_5_SLOT_EDR_ACL_MSK 0x01 +#define B5_SSR_POS 1 +#define B5_SSR_MSK 0x02 +#define B5_PAUSE_ENC_POS 2 +#define B5_PAUSE_ENC_MSK 0x04 +#define B5_AFH_CAP_MST_POS 3 +#define B5_AFH_CAP_MST_MSK 0x08 +#define B5_AFH_CLASS_MST_POS 4 +#define B5_AFH_CLASS_MST_MSK 0x10 +#define B5_EDR_ESCO_2MBPS_POS 5 +#define B5_EDR_ESCO_2MBPS_MSK 0x20 +#define B5_EDR_ESCO_3MBPS_POS 6 +#define B5_EDR_ESCO_3MBPS_MSK 0x40 +#define B5_3_SLOT_EDR_ESCO_POS 7 +#define B5_3_SLOT_EDR_ESCO_MSK 0x80 + +#define B6_EIR_POS 0 +#define B6_EIR_MSK 0x01 +#define B6_SIM_LE_BREDR_DEV_CAP_POS 1 +#define B6_SIM_LE_BREDR_DEV_CAP_MSK 0x02 +#define B6_SSP_POS 3 +#define B6_SSP_MSK 0x08 +#define B6_ENCAPS_PDU_POS 4 +#define B6_ENCAPS_PDU_MSK 0x10 +#define B6_ERR_DATA_REP_POS 5 +#define B6_ERR_DATA_REP_MSK 0x20 +#define B6_NONFLUSH_PBF_POS 6 +#define B6_NONFLUSH_PBF_MSK 0x40 + +#define B7_LST_CHANGE_EVT_POS 0 +#define B7_LST_CHANGE_EVT_MSK 0x01 +#define B7_INQRES_TXPOW_POS 1 +#define B7_INQRES_TXPOW_MSK 0x02 +#define B7_ENH_PWR_CTRL_POS 2 +#define B7_ENH_PWR_CTRL_MSK 0x04 +#define B7_EXT_FEATS_POS 7 +#define B7_EXT_FEATS_MSK 0x80 + +/// Extended feature mask definition page 1 LMP:3.3 +#define B0_HOST_SSP_POS 0 +#define B0_HOST_SSP_MSK 0x01 +#define B0_HOST_LE_POS 1 +#define B0_HOST_LE_MSK 0x02 +#define B0_HOST_LE_BR_EDR_POS 2 +#define B0_HOST_LE_BR_EDR_MSK 0x04 +#define B0_HOST_SECURE_CON_POS 3 +#define B0_HOST_SECURE_CON_MSK 0x08 + +/// Extended feature mask definition page 2 LMP:3.3 +#define B0_CSB_MASTER_POS 0 +#define B0_CSB_MASTER_MSK 0x01 +#define B0_CSB_SLAVE_POS 1 +#define B0_CSB_SLAVE_MSK 0x02 +#define B0_SYNC_TRAIN_POS 2 +#define B0_SYNC_TRAIN_MSK 0x04 +#define B0_SYNC_SCAN_POS 3 +#define B0_SYNC_SCAN_MSK 0x08 +#define B0_INQ_RES_NOTIF_EVT_POS 4 +#define B0_INQ_RES_NOTIF_EVT_MSK 0x10 +#define B0_GEN_INTERL_SCAN_POS 5 +#define B0_GEN_INTERL_SCAN_MSK 0x20 +#define B0_COARSE_CLK_ADJ_POS 6 +#define B0_COARSE_CLK_ADJ_MSK 0x40 + +#define B1_SEC_CON_CTRL_POS 0 +#define B1_SEC_CON_CTRL_MSK 0x01 +#define B1_PING_POS 1 +#define B1_PING_MSK 0x02 +#define B1_SAM_POS 2 +#define B1_SAM_MSK 0x04 +#define B1_TRAIN_NUDGING_POS 3 +#define B1_TRAIN_NUDGING_MSK 0x08 + +/// Features definitions +#define FEAT_3_SLOT_BIT_POS 0 +#define FEAT_5_SLOT_BIT_POS 1 +#define FEAT_ENC_BIT_POS 2 +#define FEAT_SLOT_OFFSET_BIT_POS 3 +#define FEAT_TIMING_ACC_BIT_POS 4 +#define FEAT_SWITCH_BIT_POS 5 +#define FEAT_HOLD_BIT_POS 6 +#define FEAT_SNIFF_BIT_POS 7 + +#define FEAT_PARK_BIT_POS 8 +#define FEAT_RSSI_BIT_POS 9 +#define FEAT_QUALITY_BIT_POS 10 +#define FEAT_SCO_BIT_POS 11 +#define FEAT_HV2_BIT_POS 12 +#define FEAT_HV3_BIT_POS 13 +#define FEAT_ULAW_BIT_POS 14 +#define FEAT_ALAW_BIT_POS 15 + +#define FEAT_CVSD_BIT_POS 16 +#define FEAT_PAGING_BIT_POS 17 +#define FEAT_POWER_BIT_POS 18 +#define FEAT_TRANSP_SCO_BIT_POS 19 +#define FEAT_BCAST_ENCRYPT_BIT_POS 23 + +#define FEAT_EDR_2MB_BIT_POS 25 +#define FEAT_EDR_3MB_BIT_POS 26 +#define FEAT_ENH_INQSCAN_BIT_POS 27 +#define FEAT_INT_INQSCAN_BIT_POS 28 +#define FEAT_INT_PAGESCAN_BIT_POS 29 +#define FEAT_RSSI_INQRES_BIT_POS 30 +#define FEAT_EV3_BIT_POS 31 + +#define FEAT_EV4_BIT_POS 32 +#define FEAT_EV5_BIT_POS 33 +#define FEAT_AFH_CAPABLE_S_BIT_POS 35 +#define FEAT_AFH_CLASS_S_BIT_POS 36 +#define FEAT_BR_EDR_NO_SUPP_BIT_POS 37 +#define FEAT_LE_BIT_POS 38 +#define FEAT_3_SLOT_EDR_BIT_POS 39 +#define FEAT_5_SLOT_EDR_BIT_POS 40 +#define FEAT_SNIFF_SUBRAT_BIT_POS 41 +#define FEAT_PAUSE_ENCRYPT_BIT_POS 42 +#define FEAT_AFH_CAPABLE_M_BIT_POS 43 +#define FEAT_AFH_CLASS_M_BIT_POS 44 +#define FEAT_EDR_ESCO_2MB_BIT_POS 45 +#define FEAT_EDR_ESCO_3MB_BIT_POS 46 +#define FEAT_3_SLOT_EDR_ESCO_BIT_POS 47 +#define FEAT_EIR_BIT_POS 48 +#define FEAT_LE_BR_EDR_BIT_POS 49 +#define FEAT_SSP_BIT_POS 51 +#define FEAT_ENCAP_PDU_BIT_POS 52 +#define FEAT_ERRO_DATA_REP_BIT_POS 53 +#define FEAT_NFLUSH_PBF_BIT_POS 54 +#define FEAT_LSTO_CHG_EVT_BIT_POS 56 +#define FEAT_INQ_TXPWR_BIT_POS 57 +#define FEAT_EPC_BIT_POS 58 +#define FEAT_EXT_FEATS_BIT_POS 63 +#define FEAT_SSP_HOST_BIT_POS 64 +#define FEAT_LE_HOST_BIT_POS 65 +#define FEAT_LE_BR_EDR_HOST_BIT_POS 66 +#define FEAT_SEC_CON_HOST_BIT_POS 67 + +#define FEAT_CSB_MASTER_BIT_POS 128 +#define FEAT_CSB_SLAVE_BIT_POS 129 +#define FEAT_SYNC_TRAIN_BIT_POS 130 +#define FEAT_SYNC_SCAN_BIT_POS 131 +#define FEAT_INQ_RES_NOTIF_EVT_BIT_POS 132 +#define FEAT_GEN_INTERL_SCAN_BIT_POS 133 +#define FEAT_COARSE_CLK_ADJ_BIT_POS 134 +#define FEAT_SEC_CON_CTRL_BIT_POS 136 +#define FEAT_PING_BIT_POS 137 +#define FEAT_SAM_BIT_POS 138 +#define FEAT_TRAIN_NUDGING_BIT_POS 139 + +/// Maximum number of feature bits per page (8 bytes x 8 bits) +#define MAX_FEAT_BITS_PER_PAGE 64 + +/// Poll interval defines LMP:5.2 +#define POLL_INTERVAL_MIN 0x0006 +#define POLL_INTERVAL_DFT 0x0028 +#define POLL_INTERVAL_MAX 0x1000 + +/// Power Adjustment Request LMP:5.2 +#define PWR_ADJ_REQ_DEC_1_STEP 0x00 +#define PWR_ADJ_REQ_INC_1_STEP 0x01 +#define PWR_ADJ_REQ_INC_MAX 0x02 + +/// Power Adjustment Response LMP:5.2 +#define PWR_ADJ_RES_GFSK_POS 0 +#define PWR_ADJ_RES_GFSK_MASK 0x03 +#define PWR_ADJ_RES_DQPSK_POS 2 +#define PWR_ADJ_RES_DQPSK_MASK 0x0C +#define PWR_ADJ_RES_8DPSK_POS 4 +#define PWR_ADJ_RES_8DPSK_MASK 0x30 + +#define PWR_ADJ_RES_NOT_SUPP 0x00 +#define PWR_ADJ_RES_CHG_1_STEP 0x01 +#define PWR_ADJ_RES_MAX 0x02 +#define PWR_ADJ_RES_MIN 0x03 + +/// Nb of Broadcast retransmissions defines +#define NB_BROADCAST_DFT 0x01 + +/// Nb of Broadcast CLK_ADJ PDU Baseband:4.1.14.1 +#define NB_BROADCAST_CLK_ADJ 0x06 + +/// Min PCA clk_adj_instant (in slots) LMP:4.1.14.1 +#define PCA_INSTANT_MIN 12 + +/// Piconet Clock Adjustment clk_adj_mode LMP:4.1.14.1 +#define CLK_ADJ_BEFORE_INSTANT 0 +#define CLK_ADJ_AFTER_INSTANT 1 + + +/// Different packet types BaseBand:6.7 +/* Packet and buffer sizes. These sizes do not include payload header (except for FHS + * packet where there is no payload header) since payload header is written or read by + * the RWBT in a different control structure part (TX/RXPHDR) */ +#define FHS_PACKET_SIZE 18 +#define DM1_PACKET_SIZE 17 +#define DH1_PACKET_SIZE 27 +#define DH1_2_PACKET_SIZE 54 +#define DH1_3_PACKET_SIZE 83 +#define DV_ACL_PACKET_SIZE 9 +#define DM3_PACKET_SIZE 121 +#define DH3_PACKET_SIZE 183 +#define DH3_2_PACKET_SIZE 367 +#define DH3_3_PACKET_SIZE 552 +#define DM5_PACKET_SIZE 224 +#define DH5_PACKET_SIZE 339 +#define DH5_2_PACKET_SIZE 679 +#define DH5_3_PACKET_SIZE 1021 +#define AUX1_PACKET_SIZE 29 + +#define HV1_PACKET_SIZE 10 +#define HV2_PACKET_SIZE 20 +#define HV3_PACKET_SIZE 30 +#define EV3_PACKET_SIZE 30 +#define EV3_2_PACKET_SIZE 60 +#define EV3_3_PACKET_SIZE 90 +#define EV4_PACKET_SIZE 120 +#define EV5_PACKET_SIZE 180 +#define EV5_2_PACKET_SIZE 360 +#define EV5_3_PACKET_SIZE 540 + +/// SCO Packet coding LMP:5.2 +#define SCO_PACKET_HV1 0x00 +#define SCO_PACKET_HV2 0x01 +#define SCO_PACKET_HV3 0x02 + +/// eSCO Packet coding LMP:5.2 +#define ESCO_PACKET_NULL 0x00 +#define ESCO_PACKET_EV3 0x07 +#define ESCO_PACKET_EV4 0x0C +#define ESCO_PACKET_EV5 0x0D +#define ESCO_PACKET_EV3_2 0x26 +#define ESCO_PACKET_EV3_3 0x37 +#define ESCO_PACKET_EV5_2 0x2C +#define ESCO_PACKET_EV5_3 0x3D + +/// Max number of HV packet BaseBand:4.4.2.1 +#define MAX_NB_HV1 1 +#define MAX_NB_HV2 2 +#define MAX_NB_HV3 3 + +/// Tsco (ScoInterval) BaseBand:4.4.2.1 +#define TSCO_HV1 2 +#define TSCO_HV2 4 +#define TSCO_HV3 6 + +/* Inquiry train repetition length , Baseband :Table 10.4 + * - 256 repetitions if no SCO + * - 512 repetitions if 1 SCO + * - 768 repetitions if 2 SCO */ +#define INQ_TRAIN_LENGTH_NO_SCO 256 +#define INQ_TRAIN_LENGTH_1_SCO 512 +#define INQ_TRAIN_LENGTH_2_SCO 768 + +/* Counter for train length, Npage (N*16 slots) depends on the slave page scan mode and + * the number of active SCO: + * | SR mode | no SCO | one SCO | two SCO | + * | R0 | >=1 | >=2 | >=3 | + * | R1 | >=128 | >=256 | >=384 | + * | R2 | >=256 | >=512 | >=768 | */ +#define PAGE_TRAIN_LENGTH_R0 1 +#define PAGE_TRAIN_LENGTH_R1 128 +#define PAGE_TRAIN_LENGTH_R2 256 + +/// Synchronisation defines +#define NORMAL_SYNC_POS (64 + 4) // End of Synchro word at bit 68 (64 + 4) +#define SLOT_SIZE 625 // A slot is 625 us +#define HALF_SLOT_SIZE 625 // A half slot is 312.5 us (in half us) +#define HALF_SLOT_TIME_MIN (0) // Minimum offset within a half-slot is 0 half-us +#define HALF_SLOT_TIME_MAX (HALF_SLOT_SIZE - 1) // Maximum offset within a half-slot is 624 half-us + +/// Baseband timeout default value, Baseband timers: 1.1 +#define PAGE_RESP_TO_DEF 8 +#define INQ_RESP_TO_DEF 128 +#define NEW_CONNECTION_TO 32 + +/// LMP Response Timeout (in sec) +#define LMP_RSP_TO 30 +/// LLCP Response Timeout (in units of 10 ms) +#define LLCP_RSP_TO 4000 // 40 secs + +/// Athenticated Payload Timeout (in units of 10 ms) +#define AUTH_PAYL_TO_DFT 0x0BB8 // 30 secs +#define AUTH_PAYL_TO_MIN 0x0001 + +/// Voice mute pattern defines +#define MU_LAW_MUTE 0xFF +#define ALAW_CVSD_MUTE 0x55 +#define TRANSP_MUTE 0x00 + +/// Air Mode LMP:5.2 +#define MU_LAW_MODE 0 +#define A_LAW_MODE 1 +#define CVSD_MODE 2 +#define TRANS_MODE 3 + +/// eSCO negotiation State LMP:5.2 +#define ESCO_NEGO_INIT 0 +#define ESCO_NEGO_LATEST_POSSIBLE 1 +#define ESCO_NEGO_SLOT_VIOLATION 2 +#define ESCO_NEGO_LAT_VIOLATION 3 +#define ESCO_NEGO_UNSUPPORTED 4 + +#define SCO_BANDWIDTH 8000 +#define SYNC_BANDWIDTH_DONT_CARE 0xFFFFFFFF + +#define SYNC_MIN_LATENCY 0x0004 +#define SYNC_MAX_LATENCY_ESCO_S1 0x0007 +#define SYNC_MAX_LATENCY_ESCO_S2 0x0007 +#define SYNC_MAX_LATENCY_ESCO_S3 0x000A +#define SYNC_DONT_CARE_LATENCY 0xFFFF + +#define SYNC_NO_RE_TX 0x00 +#define SYNC_RE_TX_POWER 0x01 +#define SYNC_RE_TX_QUALITY 0x02 +#define SYNC_RE_TX_DONT_CARE 0xFF + +/// Timing Control Flags LMP:5.2 +#define TIM_CHANGE_FLAG 0x01 +#define INIT2_FLAG 0x02 +#define ACCESS_WIN_FLAG 0x04 + +/// Sniff request parameters LMP:5.2 +#define SNIFF_INTERVAL_MIN 0x0006 +#define SNIFF_INTERVAL_MAX 0x0540 +#define SNIFF_TIMEOUT_MAX 0x0028 + +/// Packet Type Table defines LMP:4.1.11 +#define PACKET_TABLE_1MBPS 0x00 +#define PACKET_TABLE_2_3MBPS 0x01 + +/// Data Rate defines LMP:5.2 +#define FEC_RATE_MSK 0x01 +#define USE_FEC_RATE 0x00 +#define NO_FEC_RATE 0x01 +#define PREF_PACK_MSK 0x06 +#define NO_PREF_PACK_SIZE 0x00 +#define USE_1_SLOT_PACKET 0x02 +#define USE_3_SLOT_PACKET 0x04 +#define USE_5_SLOT_PACKET 0x06 +#define PREF_EDR_MSK 0x18 +#define USE_DM1_ONLY 0x00 +#define USE_2_MBPS_RATE 0x08 +#define USE_3_MBPS_RATE 0x10 +#define PREF_PACK_EDR_MSK 0x60 +#define USE_1_SLOT_EDR_PKT 0x20 +#define USE_3_SLOT_EDR_PKT 0x40 +#define USE_5_SLOT_EDR_PKT 0x60 + +/// EIR Data Size HCI:6.24 +#define EIR_DATA_SIZE 240 + +/// Voice setting HCI:4.7.29 & 4.7.30 +#define INPUT_COD_LIN 0x0000 +#define INPUT_COD_MULAW 0x0100 +#define INPUT_COD_ALAW 0x0200 +#define INPUT_COD_MSK 0x0300 +#define INPUT_COD_OFF 8 +#define INPUT_DATA_1COMP 0x0000 +#define INPUT_DATA_2COMP 0x0040 +#define INPUT_DATA_SMAG 0x0080 +#define INPUT_DATA_UNSIGNED 0x00C0 +#define INPUT_DATAFORM_MSK 0x00C0 +#define INPUT_DATAFORM_OFF 6 +#define INPUT_SAMP_8BIT 0x0000 +#define INPUT_SAMP_16BIT 0x0020 +#define INPUT_SAMPSIZE_MSK 0x0020 +#define INPUT_SAMPSIZE_OFF 5 +#define LIN_PCM_BIT_POS_MSK 0x001C +#define LIN_PCM_BIT_POS_OFF 2 +#define AIR_COD_CVSD 0x0000 +#define AIR_COD_MULAW 0x0001 +#define AIR_COD_ALAW 0x0002 +#define AIR_COD_TRANS 0x0003 +#define AIR_COD_MSK 0x0003 +#define AIR_COD_OFF 0 + +/// ScanEnable HCI:6.1 +#define BOTH_SCAN_DISABLE 0 +#define INQUIRY_SCAN_ENABLE 1 +#define PAGE_SCAN_ENABLE 2 +#define BOTH_SCAN_ENABLE 3 + +/// PageScanInterval HCI:6.8 +#define PAGE_SCAN_INTV_MIN 0x0012 +#define PAGE_SCAN_INTV_MAX 0x1000 +#define PAGE_SCAN_INTV_DFT 0x0800 + +/// PageScanWindow HCI:6.9 +#define PAGE_SCAN_WIN_MIN 0x0011 +#define PAGE_SCAN_WIN_MAX 0x1000 +#define PAGE_SCAN_WIN_DFT 0x0012 + +/// InquiryScanInterval HCI:6.2 +#define INQ_SCAN_INTV_MIN 0x0012 +#define INQ_SCAN_INTV_MAX 0x1000 +#define INQ_SCAN_INTV_DFT 0x1000 + +/// InquiryScanWindow HCI:6.3 +#define INQ_SCAN_WIN_MIN 0x0011 +#define INQ_SCAN_WIN_MAX 0x1000 +#define INQ_SCAN_WIN_DFT 0x0012 + +/// General/Unlimited Inquiry Access Code (GIAC) +#define GIAC_LAP_0 0x33 +#define GIAC_LAP_1 0x8B +#define GIAC_LAP_2 0x9E + +/// Limited Dedicated Inquiry Access Code (LIAC) +#define LIAC_LAP_0 0x00 +#define LIAC_LAP_1 0x8B +#define LIAC_LAP_2 0x9E + +/// Maximum Dedicated Inquiry Access Code (DIAC MAX) +#define DIAC_MAX_LAP_0 0x3F +#define DIAC_MAX_LAP_1 0x8B +#define DIAC_MAX_LAP_2 0x9E + +/// PIN Type HCI:6.13 +#define VARIABLE_PIN 0 +#define FIXED_PIN 1 + +/// ConnectionAcceptTimeout HCI:6.7 +#define CON_ACCEPT_TO_MIN 0x00A0 +#define CON_ACCEPT_TO_MAX 0xB540 +#define CON_ACCEPT_TO_DFT 0x1FA0 + +/// PageTimeout HCI:6.6 +#define PAGE_TO_MIN 0x0016 +#define PAGE_TO_MAX 0xFFFF +#define PAGE_TO_DFT 0x2000 + +/// Clock offset valid flag in clock offset field HCI:7.1.5/7.1.19 +#define CLK_OFFSET_VALID_FLAG_POS 15 +#define CLK_OFFSET_VALID_FLAG_MSK 0x8000 + +/// AuthenticationEnable HCI:4.7.24 +#define AUTH_DISABLED 0x00 // Default +#define AUTH_ENABLED 0x01 + +/// EncryptionMode HCI:4.7.26 +#define ENC_DISABLED 0x00 // Default +#define ENC_PP_ENABLED 0x01 +#define ENC_PP_BC_ENABLED 0x02 + +/// AutomaticFlushTimeout HCI:4.7.32 +#define AUTO_FLUSH_TIMEOUT_MAX 0x07FF +#define AUTO_FLUSH_TIMEOUT_OFF 0x0000 +#define AUTO_FLUSH_TIMEOUT_DFT AUTO_FLUSH_TIMEOUT_OFF // Default (no automatic flush timeout) + +/// Link Supervision Time Out (in slots) HCI:6.21 +#define LSTO_OFF 0x0000 +#define LSTO_MIN 0x0001 +#define LSTO_DFT 0x7D00 // Default is 20 s +#define LSTO_MAX 0xFFFF + +/// PageScanRepetitionMode HCI:4.5.5 +#define R0 0x00 +#define R1 0x01 +#define R2 0x02 +#define PAGESCAN_REP_DEF R1 // Default + +/// PageScanPeriodMode HCI:4.7.49 +#define P0 0x00 // Default +#define P1 0x01 +#define P2 0x02 + +/// PageScanMode HCI:4.7.51 +#define MANDATORY_PAGE_SCAN_MODE 0x00 // Default + +#define OPT_PAGE_SCAN_MODE_1 0x01 +#define OPT_PAGE_SCAN_MODE_2 0x02 +#define OPT_PAGE_SCAN_MODE_3 0x03 + +/// Encryption Enable HCI:4.5.17 +#define ENCRYPTION_OFF 0x00 +#define ENCRYPTION_ON 0x01 + +/// Country Code HCI:4.8.4 +#define NORTH_AMERICA_EUROPE 0x00 +#define FRANCE 0x01 +#define SPAIN 0x02 +#define JAPAN 0x03 + +/// Loopback mode HCI:7.6.2 +#define NO_LOOPBACK 0x00 // Default +#define LOCAL_LOOPBACK 0x01 +#define REMOTE_LOOPBACK 0x02 + +/// Erroneous Data Reporting HCI:7.3.65 +#define ERR_DATA_REP_DIS 0x00 // Default +#define ERR_DATA_REP_EN 0x01 + +/// LM modes HCI:7.7.20 +#define LM_ACTIVE_MODE 0x00 +#define LM_HOLD_MODE 0x01 +#define LM_SNIFF_MODE 0x02 +#define LM_PARK_MODE 0x03 + +/// Key Type HCI:7.7.24 +#define COMB_KEY 0 +//#define LOCAL_UNIT_KEY 1 // deprecated since BT5.1 +//#define REMOTE_UNIT_KEY 2 // deprecated since BT5.1 +#define DEBUG_COMB_KEY 3 +#define UNAUTH_COMB_KEY_192 4 +#define AUTH_COMB_KEY_192 5 +#define CHANGED_COMB_KEY 6 +#define UNAUTH_COMB_KEY_256 7 +#define AUTH_COMB_KEY_256 8 + +/// Key Flag HCI:5.4.18 +#define SEMI_PERMANENT_KEY 0x00 +#define TEMPORARY_KEY 0x01 + +/// QOS Service Type HCI:4.6.6 +#define QOS_NO_TRAFFIC 0x00 +#define QOS_BEST_EFFORT 0x01 +#define QOS_GUARANTEED 0x02 +#define QOS_NOTSPECIFIED 0xFF + +#define QOS_WILD_CARD 0xFFFFFFFF + +/// RSSI golden range +#define RSSI_GOLDEN_RG 0x00 + +/// Inquiry TX power level (in dBm) HCI:7.3.62 +#define INQ_TX_PWR_DBM_MIN -70 +#define INQ_TX_PWR_DBM_DFT 0 +#define INQ_TX_PWR_DBM_MAX +20 + +/// Bluetooth Test Mode defines Bluetooth Test Mode: Table 3.2 + +#define PAUSE_MODE 0x00 +#define TXTEST0_MODE 0x01 +#define TXTEST1_MODE 0x02 +#define TXTEST10_MODE 0x03 +#define PRAND_MODE 0x04 +#define ACLLOOP_MODE 0x05 +#define SCOLOOP_MODE 0x06 +#define ACLNOWHIT_MODE 0x07 +#define SCONOWHIT_MODE 0x08 +#define TXTEST1100_MODE 0x09 +#define EXITTEST_MODE 0xFF + +#define HOPSINGLE 0x00 +#define HOPUSA 0x01 + +#define FIXTXPOW 0x00 +#define ADAPTTXPOW 0x01 + +/// Maximum frequency value for test mode HCI:7.8.28 +#define TEST_FREQ_MAX 39 +/// Minimum PHY value for test mode HCI:7.8.50 +#define TEST_PHY_MIN 0x01 +/// Maximum PHY value for the receiver test mode HCI:7.8.50 +#define RX_TEST_PHY_MAX 0x03 +/// Maximum PHY value for the transmitter test mode HCI:7.8.51 +#define TX_TEST_PHY_MAX 0x04 + +/// Packet type parameter bit field of LMP_test_control +#define LMP_TEST_CTRL_PKT_TYPE_CODE_POS 0 +#define LMP_TEST_CTRL_PKT_TYPE_CODE_MSK 0x0F +#define LMP_TEST_CTRL_PKT_TYPE_LINK_POS 4 +#define LMP_TEST_CTRL_PKT_TYPE_LINK_MSK 0xF0 +#define TEST_ACLSCO 0 +#define TEST_ESCO 1 +#define TEST_EDRACL 2 +#define TEST_EDRESCO 3 + +/// LMP_encapsulated_header parameters LMP:5.3 +#define LMP_ENCAPS_P192_MAJ_TYPE 1 +#define LMP_ENCAPS_P192_MIN_TYPE 1 +#define LMP_ENCAPS_P192_PAYL_LEN 48 +#define LMP_ENCAPS_P192_PAYL_NB 3 +#define LMP_ENCAPS_P256_MAJ_TYPE 1 +#define LMP_ENCAPS_P256_MIN_TYPE 2 +#define LMP_ENCAPS_P256_PAYL_LEN 64 +#define LMP_ENCAPS_P256_PAYL_NB 4 + +/// Number of bits in the passkey code used during Secure Simple Pairing +#define SSP_PASSKEY_NB_BITS 20 + +// Event Filter HCI 4.7.3 + +/// Filter type +#define CLEAR_ALL_FILTER_TYPE 0x00 +#define INQUIRY_FILTER_TYPE 0x01 +#define CONNECTION_FILTER_TYPE 0x02 + +/// Filter size +#define CLEAR_ALL_FILTER_SIZE 0 + +/// Inquiry & Connection Setup Filter Condition Type +#define ALL_FILTER_CONDITION_TYPE 0x00 +#define CLASS_FILTER_CONDITION_TYPE 0x01 +#define BD_ADDR_FILTER_CONDITION_TYPE 0x02 + +/// Auto Accept Flag +#define DO_NOT_AUTO_ACCEPT_CONNECTION 0x01 +#define ACCEPT_CONNECTION_SLAVE 0x02 +#define ACCEPT_CONNECTION_MASTER 0x03 + +/// Event Mask HCI 4.7.1 +#define NO_EVENTS_SPECIFIED_FILTER 0x00000000 +#define INQUIRY_COMPLETE_EVENT_FILTER 0x00000001 +#define INQUIRY_RESULT_EVENT_FILTER 0x00000002 +#define CONNECTION_COMPLETE_EVENT_FILTER 0x00000004 +#define CONNECTION_REQUEST_EVENT_FILTER 0x00000008 +#define DISCONNECTION_COMPLETE_EVENT_FILTER 0x00000010 +#define AUTHENTICATION_COMPLETE_EVENT_FILTER 0x00000020 +#define REMOTE_NAME_REQUEST_COMPLETE_EVENT_FILTER 0x00000040 +#define ENCRYPTION_CHANGE_EVENT_FILTER 0x00000080 +#define CHANGE_CONNECTION_LINK_KEY_COMPLETE_EVENT_FILTER 0x00000100 +#define MASTER_LINK_KEY_COMPLETE_EVENT_FILTER 0x00000200 +#define READ_REMOTE_SUPPORTED_FEATURES_COMPLETE_EVENT_FILTER 0x00000400 +#define READ_REMOTE_VERSION_INFORMATION_COMPLETE_EVENT_FILTER 0x00000800 +#define QOS_SETUP_COMPLETE_EVENT_FILTER 0x00001000 +#define COMMAND_COMPLETE_EVENT_FILTER 0x00002000 // Unchecked */ +#define COMMAND_STATUS_EVENT_FILTER 0x00004000 // Unchecked */ +#define HARDWARE_ERROR_EVENT_FILTER 0x00008000 +#define FLUSH_OCCURRED_EVENT_FILTER 0x00010000 +#define ROLE_CHANGE_EVENT_FILTER 0x00020000 +#define NUMBER_OF_COMPLETED_PACKETS_EVENT_FILTER 0x00040000 // Unchecked */ +#define MODE_CHANGE_EVENT_FILTER 0x00080000 +#define RETURN_LINK_KEYS_EVENT_FILTER 0x00100000 +#define PIN_CODE_REQUEST_EVENT_FILTER 0x00200000 +#define LINK_KEY_REQUEST_EVENT_FILTER 0x00400000 +#define LINK_KEY_NOTIFICATION_EVENT_FILTER 0x00800000 +#define LOOPBACK_COMMAND_EVENT_FILTER 0x01000000 // Not implemented */ +#define DATA_BUFFER_OVERFLOW_EVENT_FILTER 0x02000000 +#define MAX_SLOTS_CHANGE_EVENT_FILTER 0x04000000 +#define READ_CLOCK_OFFSET_COMPLETE_EVENT_FILTER 0x08000000 +#define CONNECTION_PACKET_TYPE_CHANGED_EVENT_FILTER 0x10000000 +#define QOS_VIOLATION_EVENT_FILTER 0x20000000 +#define PAGE_SCAN_MODE_CHANGE_EVENT_FILTER 0x40000000 // Deprecated */ +#define PAGE_SCAN_REPETITION_MODE_CHANGE_EVENT_FILTER 0x80000000 + +#define FLOW_SPECIFICATION_COMPLETE_EVENT_FILTER 0x00000001 +#define INQUIRY_RESULT_WITH_RSSI_EVENT_FILTER 0x00000002 +#define READ_REMOTE_EXTENDED_FEATURES_COMPLETE_EVENT_FILTER 0x00000004 +#define SYNCHRONOUS_CONNECTION_COMPLETE_EVENT_FILTER 0x00000800 +#define SYNCHRONOUS_CONNECTION_CHANGE_EVENT_FILTER 0x00001000 +#define SNIFF_SUBRATING_EVENT_FILTER 0x00002000 +#define EXTENDED_INQUIRY_RESULT_EVENT_FILTER 0x00004000 +#define ENCRYPTION_KEY_REFRESH_COMPLETE_EVENT_FILTER 0x00008000 +#define IO_CAPABILITY_REQUEST_EVENT_FILTER 0x00010000 +#define IO_CAPABILITY_REQUEST_REPLY_EVENT_FILTER 0x00020000 +#define USER_CONFIRMATION_REQUEST_EVENT_FILTER 0x00040000 +#define USER_PASSKEY_REQUEST_EVENT_FILTER 0x00080000 +#define REMOTE_OOB_DATA_REQUEST_EVENT_FILTER 0x00100000 +#define SIMPLE_PAIRING_COMPLETE_EVENT_FILTER 0x00200000 +#define LINK_SUPERVISION_TIMEOUT_CHANGE_EVENT_FILTER 0x00800000 +#define ENHANCED_FLUSH_COMPLETE_EVENT_FILTER 0x01000000 +#define USER_PASSKEY_NOTIFICATION_EVENT_FILTER 0x04000000 +#define KEYPRESS_NOTIFICATION_EVENT_FILTER 0x08000000 +#define REM_HOST_SUPPORTED_FEATURES_NOTIFICATION_EVENT_FILTER 0x10000000 + +/// HostControllerToHostFlowControl (ACL) HCI 7.3.40 +#define FLOW_CONTROL_OFF 0x00 +#define FLOW_CONTROL_ACL 0x01 +#define FLOW_CONTROL_SCO 0x02 +#define FLOW_CONTROL_ACL_SCO 0x03 + +/// SynchroinousFlowControlEnable (SCO) HCI 7.3.39 +#define SYNC_FLOW_CONTROL_OFF 0x00 +#define SYNC_FLOW_CONTROL_ON 0x01 + +/// Tx Power HCI:4.7.37 +#define CURRENT_TX_POWER 0x00 +#define MAX_TX_POWER 0x01 + +/// Flow_direction HCI:7.2.13 +#define FLOW_DIR_OUT 0x00 +#define FLOW_DIR_IN 0x01 + +/// Drift and Jitter default value LMP 5.2 +#define DRIFT_BLE_DFT 500 +#define DRIFT_BT_DFT 250 +#define JITTER_DFT 10 +#define DRIFT_BT_ACTIVE_MAX 20 // BB:2.2.5 + +/// MAX LP Clock Jitter allowed by the specification (in us) (Core 4.2 - vol 6, -B - 4.2.2) +#define BLE_MAX_JITTER (16) + +/// Read Stored Link Key HCI:4.7.8 +#define LINK_KEY_BD_ADDR 0x00 +#define LINK_KEY_ALL 0x01 + +/// Read/Write Hold Mode Activity HCI:4.7.35 and 4.7.36 +#define HOLD_MODE_ACTIV_DEFAULT 0x00 +#define HOLD_MODE_ACTIV_SUSP_PAGE_SCAN 0x01 +#define HOLD_MODE_ACTIV_SUSP_INQUIRY_SCAN 0x02 +#define HOLD_MODE_ACTIV_SUSP_PERIODIC_INQ 0x04 +#define HOLD_MODE_ACTIV_NOT_MASK 0xF8 + +/// AFH Mode +#define AFH_DISABLED 0x00 +#define AFH_ENABLED 0x01 + +/// AFH Reporting Mode +#define AFH_REPORTING_DISABLED 0x00 +#define AFH_REPORTING_ENABLED 0x01 + +/// AFH channel assessment Mode +#define AFH_CH_ASS_DISABLED 0x00 +#define AFH_CH_ASS_ENABLED 0x01 + +/// AFH MIn/Max interval, in BT slots (1s - 30s) +#define AFH_REPORT_INTERVAL_MIN 0x0640 +#define AFH_REPORT_INTERVAL_MAX 0xBB80 + +/// Channel classification values for frequency pairs +#define AFH_CH_CLASS_UNKNOWN 0x0 +#define AFH_CH_CLASS_GOOD 0x1 +#define AFH_CH_CLASS_RESERVED 0x2 +#define AFH_CH_CLASS_BAD 0x3 + +/// Maximum number of frequencies used in adapted channel hopping sequence +#define AFH_NB_CHANNEL_MIN 20 +#define AFH_NB_CHANNEL_MAX 79 + +/// Number of frequencies available in standard hopping sequence +#define HOP_NB_CHANNEL 79 + +/// Base frequency in MHz of first BT hop channel [f=2402+k MHz, k=0,...,78] +#define HOP_CHANNEL_BASE_MHZ 2402 + +/// Maximum number of frequencies used in synchronization train BB:2.6.4.8 +#define SYNC_TRAIN_CHANNEL_NB 3 +/// Indices of frequencies used in synchronization train +#define SYNC_TRAIN_CHANNEL_0 0 +#define SYNC_TRAIN_CHANNEL_1 24 +#define SYNC_TRAIN_CHANNEL_2 78 + +/// Maximum delay in synchronization train (in slots) BB:2.7.2 +#define SYNC_TRAIN_DELAY_MAX_DFT 16 +/// Maximum delay in synchronization train for Coarse clock adjustment (in slots) BB:2.7.2 +#define SYNC_TRAIN_DELAY_MAX_CLK_ADJ 4 +/// Synchronization train interval for Coarse clock adjustment (in slots) BB:2.7.2 +#define SYNC_TRAIN_INTV_CLK_ADJ 32 + +/// Future CSB instant value offset for Coarse clock adjustment (in slots) BB: 8.11.2 +#define SYNC_TRAIN_CSB_INSTANT_OFFSET_CLK_ADJ 1600 + +/// Minimum value for synchronization train interval (in slots) HCI:7.3.90 +#define SYNC_TRAIN_INTV_MIN 0x20 +/// Minimum value for synchronization train timeout (in slots) HCI:7.3.90 +#define SYNC_TRAIN_TO_MIN 0x00000002 +/// Maximum value for synchronization train timeout (in slots) HCI:7.3.90 +#define SYNC_TRAIN_TO_MAX 0x07FFFFFE + +/// Default value for synchronization train interval (in slots) HCI:6.36 +#define SYNC_TRAIN_INTV_DEFAULT 0x80 +/// Default value for synchronization train timeout (in slots) HCI:6.37 +#define SYNC_TRAIN_TO_DEFAULT 0x0002EE00 +/// Default value for synchronization scan timeout for CCA recovery mode (in slots) BB: Appendix B.1.8 +#define SYNC_TRAIN_TO_CCA_RM_DEFAULT 0x8000 +/// Default value for synchronization train service data HCI:6.39 +#define SYNC_TRAIN_SVC_DATA_DEFAULT 0x00 + +/// Minimum value for synchronization scan timeout (in slots) HCI:7.1.52 +#define SYNC_SCAN_TO_MIN 0x22 +/// Minimum value for synchronization scan window (in slots) HCI:7.1.52 +#define SYNC_SCAN_WIN_MIN 0x22 +/// Minimum value for synchronization scan interval (in slots) HCI:7.1.52 +#define SYNC_SCAN_INTV_MIN 0x02 + +/// Default value for synchronization scan timeout (in slots) BB: Apppendix B +#define SYNC_SCAN_TO_DEFAULT 0x2000 +/// Default value for synchronization scan timeout for CCA recovery mode (in slots) BB: Appendix B.1.9 +#define SYNC_SCAN_TO_CCA_RM_DEFAULT 0x8000 +/// Recommended value for synchronization scan window (91.25ms) GAP: Appendix A +#define SYNC_SCAN_WIN_DEFAULT 0x0092 +/// Recommended value for synchronization scan interval (320 ms) GAP: Appendix A +#define SYNC_SCAN_INTV_DEFAULT 0x0200 + + +/// CSB receive enable HCI:7.1.50 +#define CSB_RX_MODE_DIS 0x00 +#define CSB_RX_MODE_EN 0x01 + +/// CSB fragment HCI:7.2.88 +#define CSB_CONTINUATION_FRAGMENT 0 +#define CSB_STARTING_FRAGMENT 1 +#define CSB_ENDING_FRAGMENT 2 +#define CSB_NO_FRAGMENTATION 3 + +/// CSB max fragment size HCI:7.2.88 +#define CSB_FRAGMENT_SIZE_MAX 0xFF + +/// MWS Channel_Enable +#define MWS_CHANNEL_DISABLED 0x00 +#define MWS_CHANNEL_ENABLED 0x01 + +/// MWS Channel_Type +#define MWS_TDD_CHANNEL_TYPE 0x00 +#define MWS_FDD_CHANNEL_TYPE 0x01 + +/// MWS Transport_Layer +#define MWS_SIGNALING_ONLY 0x00 +#define MWS_WCI_1 0x01 +#define MWS_WCI_2 0x02 +#define MWS_TRANSPORT_TYPE_MAX 0x02 + +/// MWS PATTERN Index +#define MWS_PATTERN_INDEX_MAX 2 + +/// MWS PATTERN IntervalType +#define MWS_PATTERN_NO_TXRX 0 +#define MWS_PATTERN_TX_ALLOWED 1 +#define MWS_PATTERN_RX_ALLOWED 2 +#define MWS_PATTERN_TXRX_ALLOWED 3 +#define MWS_PATTERN_EXT_FRAME 4 +#define MWS_PATTERN_TYPE_MAX 4 + + +/// MWS Ext_Num_Periods +#define MWS_EXT_NUM_PERIODS_MIN 0x01 +#define MWS_EXT_NUM_PERIODS_MAX 0x32 + +/// MWS Period_Type +#define MWS_PERIOD_TYPE_DOWNLINK 0x00 +#define MWS_PERIOD_TYPE_UPLINK 0x01 +#define MWS_PERIOD_TYPE_BIDIRECTIONAL 0x02 +#define MWS_PERIOD_TYPE_GUARD_PERIOD 0x03 +#define MWS_PERIOD_TYPE_RESERVED 0x04 + +/// MWS inactivity duration 7B(WCI-1):3.1.4. +#define MWS_INACT_DUR_INFINITE 0x1F + + +/// Simple pairing mode HCI:7.3.58/HCI:7.3.59 +#define SP_MODE_DIS 0x00 +#define SP_MODE_EN 0x01 + +/// Inquiry Scan Type and Page Scan Type HCI:6.4/HCI:6.11 +#define STANDARD_SCAN 0x00 +#define INTERLACED_SCAN 0x01 + +/// Default interlace offset used for frequency selection during interlaced inquiry/page scan BB:8.3.1/8.4.1 +#define INTERLACE_OFFSET_DFT 16 + +/// Inquiry Mode +#define STANDARD_INQUIRY 0x00 +#define RSSI_INQUIRY 0x01 +#define EXTENDED_INQUIRY 0x02 + +/// Maximum number of link keys Host can write via HCI Write Stored Link Key Command +#define NB_LINK_KEY 0x0B + +/// LMP Version +#define BT_LMP_V1_0 0 +#define BT_LMP_V1_1 1 +#define BT_LMP_V1_2 2 +#define BT_LMP_V2_0 3 +#define BT_LMP_V2_1 4 +#define BT_LMP_V3_0 5 +#define BT_LMP_V4_0 6 +#define BT_LMP_V4_1 7 + +/// WhichClock parameter +#define LOCAL_CLOCK 0 +#define PICONET_CLOCK 1 + +/// Clock Accuracy parameter +#define CLOCK_ACCURACY_UNKNOWN 0xFFFF + +#define SP_PASSKEY_STARTED 0x00 +#define SP_PASSKEY_DIGIT_ENTERED 0x01 +#define SP_PASSKEY_DIGIT_ERASED 0x02 +#define SP_PASSKEY_CLEARED 0x03 +#define SP_PASSKEY_COMPLETED 0x04 + +// Flags for ld_util_get_nb_acl function +/// Flag for master link +#define MASTER_FLAG 0x01 +/// Flag for slave link +#define SLAVE_FLAG 0x02 + + +/// BLE packet info in bytes +#define BLE_PKT_HDR_LEN (2) +#define BLE_PKT_CRC_LEN (3) +#define BLE_PKT_ACCESS_LEN (4) + +/// IFS duration in us +#define BLE_IFS_DUR (150) + +/// MAFS duration in us +#define BLE_MAFS_DUR (300) + +/// Offset threshold in us, below which Offset Units is set to 0 +#define OFFSET_THRESHOLD 245700 + +/// Maximum offset value (in us) that can be represented by the Sync Packet Offset +#define OFFSET_LIMIT 2457300 + +/// Offset adjust value in us +#define OFFSET_ADJUST 2457600 + +/// Maximum time difference (in us) between lastPaEventCount and EventCounter +#define OFFSET_DIFF_MAX 5000000 + +/// CTE defines + +/** + * Sync CTE type, specifies whether to only sync to periodic advertising with certain types of + * Constant Tone Extension (HCI:7.8.67) + */ +enum sync_cte_type +{ + NO_SYNC_AOA_BIT = (0x01) , + NO_SYNC_AOA_POS = (0) , + NO_SYNC_AOD_1US_BIT = (0x02) , + NO_SYNC_AOD_1US_POS = (1) , + NO_SYNC_AOD_2US_BIT = (0x04) , + NO_SYNC_AOD_2US_POS = (2) , + NO_SYNC_NO_CTE_BIT = (0x10) , + NO_SYNC_NO_CTE_POS = (4) , + +}; + +/// Modulation index +#define STANDARD_MOD_IDX (0) +#define STABLE_MOD_IDX (1) + +/// CTE length (in number of 8us periods) +#define NO_CTE (0) +#define CTE_LEN_MIN (0x02) +#define CTE_LEN_MAX (0x14) + +/// CTE type +#define CTE_TYPE_AOA (0) +#define CTE_TYPE_AOD_1US (1) +#define CTE_TYPE_AOD_2US (2) +#define CTE_TYPE_NO_CTE (0xFF) + +/// CTE types +enum cte_types +{ + CTE_TYPES_AOA_BIT = (0x01) , + CTE_TYPES_AOA_POS = (0) , + CTE_TYPES_AOD_1US_BIT = (0x02) , + CTE_TYPES_AOD_1US_POS = (1) , + CTE_TYPES_AOD_2US_BIT = (0x04) , + CTE_TYPES_AOD_2US_POS = (2) , +}; + +/// Slot durations (in us) +#define SLOT_DUR_1US (1) +#define SLOT_DUR_2US (2) + +/// Length of switching pattern +#define MIN_SWITCHING_PATTERN_LEN (0x02) +#define MAX_SWITCHING_PATTERN_LEN (0x4B) + +/// CTE count +#define MIN_CTE_CNT (0x01) +#define MAX_CTE_CNT (0x10) + +/// CTE enable +#define CTE_DIS (0) +#define CTE_EN (1) + +/// Sampling enable +#define IQ_SAMPL_DIS (0) +#define IQ_SAMPL_EN (1) + +/// CTE request interval (in number of connection events) HCI:7.8.85 +#define CTE_ASAP (0x0000) +#define MIN_CTE_INTV (0x0001) +#define MAX_CTE_INTV (0xFFFF) + +/// Supported switching sampling rates +#define AOD_TX_1_US (0x01) +#define AOD_RX_1_US (0x02) +#define AOA_RX_1_US (0x04) + +/// Number of antennae +#define MIN_ANTENNAE_NUM (0x01) +#define MAX_ANTENNAE_NUM (0x4B) + +/// Sample count +#define MIN_SAMPLE_CNT (0x09) +#define MAX_SAMPLE_CNT (0x52) + +/// No valid sample available +#define NO_VALID_SAMPLE (0x80) + +/// CTE packet status HCI:7.7.65.21 +#define CTE_PKT_STAT_CRC_OK (0x00) +#define CTE_PKT_STAT_CRC_KO_LEN_USED (0x01) +#define CTE_PKT_STAT_CRC_KO_OTHER_WAY (0x02) +#define CTE_PKT_STAT_INSUF_RES (0xFF) + +/// Periodic advertising sync transfer defines + +/** + * Periodic advertising sync information reception mode HCI:7.8.91 + * 0x00 - No attempt is made to synchronize to the periodic advertising and no HCI_LE_Periodic_Advertising_Sync_Transfer_Received event is sent to the Host. + * 0x01 - An HCI_LE_Periodic_Advertising_Sync_Transfer_Received event is sent to the Host. HCI_LE_Periodic_Advertising_Report events will be disabled. + * 0x02 - An HCI_LE_Periodic_Advertising_Sync_Transfer_Received event is sent to the Host. HCI_LE_Periodic_Advertising_Report events will be enabled. + */ +enum per_adv_sync_info_rec_mode +{ + NO_SYNC = 0x00, + SYNC_REP_DIS = 0x01, + SYNC_REP_EN = 0x02, +}; + +/** + * Private key type HCI:7.8.93 + * 0x00 - Use the generated private key + * 0x01 - Use the debug private key + */ +enum priv_key_type +{ + USE_GEN_PRIV_KEY = 0x00, + USE_DBG_PRIV_KEY = 0x01, +}; + +/** + * Action on clock accuracy HCI:7.8.94 + * 0x00 - Switch to a more accurate clock + * 0x01 - Switch to a less accurate clock + */ +enum clk_acc_action +{ + SWITCH_TO_MORE_ACC_CLK = 0x00, + SWITCH_TO_LESS_ACC_CLK = 0x01, +}; + +/// BLE event mask +enum le_evt_mask +{ + LE_EVT_MASK_CON_CMP_EVT_BIT = 0, + LE_EVT_MASK_CON_CMP_EVT_MSK = 0x00000001, + LE_EVT_MASK_ADV_REP_EVT_BIT = 1, + LE_EVT_MASK_ADV_REP_EVT_MSK = 0x00000002, + LE_EVT_MASK_CON_UPD_EVT_BIT = 2, + LE_EVT_MASK_CON_UPD_EVT_MSK = 0x00000004, + LE_EVT_MASK_CON_RD_REM_FEAT_EVT_BIT = 3, + LE_EVT_MASK_CON_RD_REM_FEAT_EVT_MSK = 0x00000008, + LE_EVT_MASK_LG_TR_KEY_REQ_EVT_BIT = 4, + LE_EVT_MASK_LG_TR_KEY_REQ_EVT_MSK = 0x00000010, + LE_EVT_MASK_REM_CON_PARA_REQ_EVT_BIT = 5, + LE_EVT_MASK_REM_CON_PARA_REQ_EVT_MSK = 0x00000020, + LE_EVT_MASK_DATA_LEN_CHG_EVT_BIT = 6, + LE_EVT_MASK_DATA_LEN_CHG_EVT_MSK = 0x00000040, + LE_EVT_MASK_RD_LOC_P256_PUB_KEY_CMP_EVT_BIT = 7, + LE_EVT_MASK_RD_LOC_P256_PUB_KEY_CMP_EVT_MSK = 0x00000080, + LE_EVT_MASK_GEN_DHKEY_CMP_EVT_BIT = 8, + LE_EVT_MASK_GEN_DHKEY_CMP_EVT_MSK = 0x00000100, + LE_EVT_MASK_ENH_CON_CMP_EVT_BIT = 9, + LE_EVT_MASK_ENH_CON_CMP_EVT_MSK = 0x00000200, + LE_EVT_MASK_DIR_ADV_REP_EVT_BIT = 10, + LE_EVT_MASK_DIR_ADV_REP_EVT_MSK = 0x00000400, + LE_EVT_MASK_PHY_UPD_CMP_EVT_BIT = 11, + LE_EVT_MASK_PHY_UPD_CMP_EVT_MSK = 0x00000800, + LE_EVT_MASK_EXT_ADV_REPORT_EVT_BIT = 12, + LE_EVT_MASK_EXT_ADV_REPORT_EVT_MSK = 0x00001000, + LE_EVT_MASK_PER_ADV_SYNC_EST_EVT_BIT = 13, + LE_EVT_MASK_PER_ADV_SYNC_EST_EVT_MSK = 0x00002000, + LE_EVT_MASK_PER_ADV_REPORT_EVT_BIT = 14, + LE_EVT_MASK_PER_ADV_REPORT_EVT_MSK = 0x00004000, + LE_EVT_MASK_PER_ADV_SYNC_LOST_EVT_BIT = 15, + LE_EVT_MASK_PER_ADV_SYNC_LOST_EVT_MSK = 0x00008000, + LE_EVT_MASK_EXT_SCAN_TIMEOUT_EVT_BIT = 16, + LE_EVT_MASK_EXT_SCAN_TIMEOUT_EVT_MSK = 0x00010000, + LE_EVT_MASK_EXT_ADV_SET_TERMINATED_EVT_BIT = 17, + LE_EVT_MASK_EVT_ADV_SET_TERMINATED_EVT_MSK = 0x00020000, + LE_EVT_MASK_SCAN_REQ_RECEIVED_EVT_BIT = 18, + LE_EVT_MASK_SCAN_REQ_RECEIVED_EVT_MSK = 0x00040000, + LE_EVT_MASK_CH_SEL_ALGO_EVT_BIT = 19, + LE_EVT_MASK_CH_SEL_ALGO_EVT_MSK = 0x00080000, + LE_EVT_MASK_CONLESS_IQ_REPORT_EVT_BIT = 20, + LE_EVT_MASK_CONLESS_IQ_REPORT_EVT_MSK = 0x00100000, + LE_EVT_MASK_CON_IQ_REPORT_EVT_BIT = 21, + LE_EVT_MASK_CON_IQ_REPORT_EVT_MSK = 0x00200000, + LE_EVT_MASK_CTE_REQ_FAILED_EVT_BIT = 22, + LE_EVT_MASK_CTE_REQ_FAILED_EVT_MSK = 0x00400000, + LE_EVT_MASK_PER_ADV_SYNC_TRANSF_REC_EVT_BIT = 23, + LE_EVT_MASK_PER_ADV_SYNC_TRANSF_REC_EVT_MSK = 0x00800000, + + LE_EVT_MASK_DFT = 0x0000001F, +}; + +/// Enhanced Synchronous Connection HCI:7.1.41 & 7.1.42 +#define CODING_FORMAT_ULAW 0x00 +#define CODING_FORMAT_ALAW 0x01 +#define CODING_FORMAT_CVSD 0x02 +#define CODING_FORMAT_TRANSP 0x03 +#define CODING_FORMAT_LINPCM 0x04 +#define CODING_FORMAT_MSBC 0x05 +#define CODING_FORMAT_VENDSPEC 0xFF + +#define PCM_FORMAT_NA 0x00 +#define PCM_FORMAT_1SCOMP 0x01 +#define PCM_FORMAT_2SCOMP 0x02 +#define PCM_FORMAT_SIGNMAG 0x03 +#define PCM_FORMAT_UNSIGNED 0x04 + +#define PCM_SAMPLE_SIZE_8BITS 8 +#define PCM_SAMPLE_SIZE_16BITS 16 + +#define AUDIO_DATA_PATH_HCI 0 +#define AUDIO_DATA_PATH_PCM 1 + +/// Default maximum number of slots per packet +#define MAX_SLOT_DFT 1 + +/// Packet type code interpretation possibilities BB:6.5 +#define ID_NUL_TYPE 0x0 +#define POLL_TYPE 0x1 +#define FHS_TYPE 0x2 +#define DM1_TYPE 0x3 +#define DH1_TYPE 0x4 +#define DH1_2_TYPE 0x4 +#define DH1_3_TYPE 0x8 +#define HV1_TYPE 0x5 +#define HV2_TYPE 0x6 +#define EV3_2_TYPE 0x6 +#define HV3_TYPE 0x7 +#define EV3_TYPE 0x7 +#define EV3_3_TYPE 0x7 +#define DV_TYPE 0x8 +#define AUX1_TYPE 0x9 +#define DM3_TYPE 0xA +#define DH3_TYPE 0xB +#define DH3_2_TYPE 0xA +#define DH3_3_TYPE 0xB +#define EV4_TYPE 0xC +#define EV5_2_TYPE 0xC +#define EV5_TYPE 0xD +#define EV5_3_TYPE 0xD +#define DM5_TYPE 0xE +#define DH5_TYPE 0xF +#define DH5_2_TYPE 0xE +#define DH5_3_TYPE 0xF + +/// Format of the FHS payload BB:6.5.1.4 +#define FHS_PAR_BITS_POS 0 +#define FHS_PAR_BITS_LEN 34 +#define FHS_PAR_BITS_END (FHS_PAR_BITS_POS + FHS_PAR_BITS_LEN) +#define FHS_LAP_POS FHS_PAR_BITS_END +#define FHS_LAP_LEN 24 +#define FHS_LAP_END (FHS_LAP_POS + FHS_LAP_LEN) +#define FHS_EIR_POS FHS_LAP_END +#define FHS_EIR_LEN 1 +#define FHS_EIR_END (FHS_EIR_POS + FHS_EIR_LEN) +#define FHS_UNDEF_POS FHS_EIR_END +#define FHS_UNDEF_LEN 1 +#define FHS_UNDEF_END (FHS_UNDEF_POS + FHS_UNDEF_LEN) +#define FHS_SR_POS FHS_UNDEF_END +#define FHS_SR_LEN 2 +#define FHS_SR_END (FHS_SR_POS + FHS_SR_LEN) +#define FHS_RSVD_POS FHS_SR_END +#define FHS_RSVD_LEN 2 +#define FHS_RSVD_END (FHS_RSVD_POS + FHS_RSVD_LEN) +#define FHS_UAP_POS FHS_RSVD_END +#define FHS_UAP_LEN 8 +#define FHS_UAP_END (FHS_UAP_POS + FHS_UAP_LEN) +#define FHS_NAP_POS FHS_UAP_END +#define FHS_NAP_LEN 16 +#define FHS_NAP_END (FHS_NAP_POS + FHS_NAP_LEN) +#define FHS_CLASS_OF_DEV_POS FHS_NAP_END +#define FHS_CLASS_OF_DEV_LEN 24 +#define FHS_CLASS_OF_DEV_END (FHS_CLASS_OF_DEV_POS + FHS_CLASS_OF_DEV_LEN) +#define FHS_LT_ADDR_POS FHS_CLASS_OF_DEV_END +#define FHS_LT_ADDR_LEN 3 +#define FHS_LT_ADDR_END (FHS_LT_ADDR_POS + FHS_LT_ADDR_LEN) +#define FHS_CLK_POS FHS_LT_ADDR_END +#define FHS_CLK_LEN 26 +#define FHS_CLK_END (FHS_CLK_POS + FHS_CLK_LEN) +#define FHS_PAGE_SCAN_MODE_POS FHS_CLK_END +#define FHS_PAGE_SCAN_MODE_LEN 3 +#define FHS_PAGE_SCAN_MODE_END (FHS_PAGE_SCAN_MODE_POS + FHS_PAGE_SCAN_MODE_LEN) + +/// Format of the STP payload BB:8.11.2 +#define STP_CLK_POS 0 +#define STP_CLK_LEN 4 +#define STP_FUT_CSB_INST_POS 4 +#define STP_FUT_CSB_INST_LEN 4 +#define STP_AFH_CH_MAP_POS 8 +#define STP_AFH_CH_MAP_LEN 10 +#define STP_MST_BD_ADDR_POS 18 +#define STP_MST_BD_ADDR_LEN 6 +#define STP_CSB_INTV_POS 24 +#define STP_CSB_INTV_LEN 2 +#define STP_CSB_LT_ADDR_POS 26 +#define STP_CSB_LT_ADDR_LEN 1 +#define STP_SVC_DATA_POS 27 +#define STP_SVC_DATA_LEN 1 +#define STP_PACKET_SIZE 28 + +/// CSB Receive status HCI:7.7.69 +#define CSB_RX_OK 0x00 +#define CSB_RX_KO 0x01 + +/// HCI 7.8.33 LE Set Data Length Command +/// Preferred minimum number of payload octets +#define LE_MIN_OCTETS (27) +/// Preferred minimum number of microseconds +#define LE_MIN_TIME (328) +/// Preferred minimum number of microseconds LL:4.5.10 +#define LE_MIN_TIME_CODED (2704) +/// Preferred maximum number of payload octets +#define LE_MAX_OCTETS (251) +/// Preferred maximum number of microseconds +#define LE_MAX_TIME (2120) +/// Preferred maximum number of microseconds LL:4.5.10 +#define LE_MAX_TIME_CODED (17040) + +/// LE LL 2.1.2 Access Address +#define LE_ADV_CH_ACC_ADDR_H 0x8E89 +#define LE_ADV_CH_ACC_ADDR_L 0xBED6 + +/// Resolvable private address timeout (in seconds) HCI:7.8.45 +#define RPA_TO_MAX 0xA1B8 // approximately 11.5 hours +#define RPA_TO_DFT 0x0384 // 900 seconds or 15 minutes +#define RPA_TO_MIN 0x0001 // 1 second + +/// Max scanning PHYs which can be set HCI:7.8.64 +#define MAX_SCAN_PHYS 2 + +/// Max initiating PHYs which can be set HCI:7.8.66 +#define MAX_INIT_PHYS 3 + +/// Ext Scanning interval (in 625us slot) (chapter 2.E.7.8.64) +#define EXT_SCAN_INTERVAL_MIN 0x0004 //(2.5 ms) +#define EXT_SCAN_INTERVAL_MAX 0xFFFF //(40.96 sec) + +/// Ext Scanning window (in 625us slot) (chapter 2.E.7.8.64) +#define EXT_SCAN_WINDOW_MIN 0x0004 //(2.5 ms) +#define EXT_SCAN_WINDOW_MAX 0xFFFF //(40.96 sec) + +/// Duration of 1MBPS PDU of specified payload length in microseconds (chapter 6.B.2.1) +#define PDU_1MBPS_LEN_US(n_bytes) ((8 + (2 + n_bytes))*8) // (1 + 4 + (2 + payload_len) + 3)*8 + +/// Duration of 2MBPS PDU of specified payload length in microseconds (chapter 6.B.2.1) +#define PDU_2MBPS_LEN_US(n_bytes) ((9 + (2 + n_bytes))*4) // (2 + 4 + (2 + payload_len) + 3)*4 + +/// Duration of 500KBPS PDU of specified payload length in microseconds (chapter 6.B.2.2) +#define PDU_500KBPS_LEN_US(n_bytes) (430 + (2 + n_bytes)*16) // 80 + 256 + 16 + 24 + (2 + payload_len)*8*2 + 24*2 + 3*2 + +/// Duration of 125KBPS PDU of specified payload length in microseconds (chapter 6.B.2.2) +#define PDU_125KBPS_LEN_US(n_bytes) (592 + (2 + n_bytes)*64) // 80 + 256 + 16 + 24 + (2 + payload_len)*8*8 + 24*8 + 3*8 + +/// Maximum length of BLE advertising channel PDU payloads ((chapter 6.B.2.3)) +#define PDU_ADV_PAYLOAD_LEN_MAX 255 + +// The total amount of Host Advertising Data before fragmentation shall not exceed 1650 octets (chapter 6.B.2.3.4.9). +#define HOST_ADV_DATA_LEN_MAX 1650 + +/// SyncInfo Sync Packet Offset unspecified (chapter 6.B.2.3) +#define PER_SYNC_OFFSET_UNSPECIFIED 0 + +/// SyncInfo Sync Interval min in 1.25ms units (chapter 6.B.2.3) +#define PER_SYNC_INTERVAL_MIN 6 // (7.5ms) + +/// Ext Adv Report - ADV SID - Define for no ADI filed in the PDU HCI:7.7.65.13 +#define REP_ADV_NO_ADI 0xFF + +/// Ext Adv Report - Tx Power & RSSI dBm - Define for information not available HCI:7.7.65.13 +#define REP_ADV_DBM_UNKNOWN 127 + +/// Periodic Advertising Report - Unused parameter - mandatory value HCI:7.7.65.15 +#define PER_ADV_REPORT_TRAIL_BYTE 0xFF + +/// Maximum advertising handle HCI:7.8.53 +#define ADV_HDL_MAX 0xEF + +/// Maximum advertising Set ID HCI:7.8.53 +#define ADV_SID_MAX 0x0F + +/// Advertising_Tx_Power, Host has no preference HCI:7.8.53 +#define ADV_TX_PWR_NO_PREF 127 + +/// Address type of devices sending anonymous advertisements, HCI 7.8.16 +#define ANONYMOUS_ADV_ADDR_TYPE 0xFF + +/// Invalid param_req offset, 2.4.2.16 LL_CONNECTION_PARAM_REQ +#define PARAM_REQ_INVALID_OFFSET 0xFFFF +/* + * *********************************************************** + * ISOCHRONOUS CHANNEL DEFINES + * *********************************************************** + */ + +/// Size of payload count +#define BLE_PLD_CNT_SIZE (5) +/// Invalid Isochronous handle +#define BLE_INVALID_ISOHDL (0xFFFF) + + +/* + * ENUMERATIONS + **************************************************************************************** + */ + +/// Specify if Host has no preference into all_phys parameter HCI:7.8.48 / HCI:7.8.49 +enum le_phys_preference +{ + /// The Host has no preference among the transmitter PHYs supported by the Controller + ALL_PHYS_TX_NO_PREF = (1 << 0), + /// The Host has no preference among the receiver PHYs supported by the Controller + ALL_PHYS_RX_NO_PREF = (1 << 1), +}; + +/// Specify what PHY the Controller has changed for TX/RX. HCI:7.7.65.12 +/*@TRACE*/ +enum le_phy_value +{ + PHY_UNDEF_VALUE = 0, + PHY_1MBPS_VALUE = 1, + PHY_2MBPS_VALUE = 2, + PHY_CODED_VALUE = 3, +}; + +/// Specify what PHY Host prefers to use for RX or TX HCI:7.8.48 / HCI:7.8.49 +enum le_phy_mask +{ + /// The Host prefers to use the LE 1M transmitter/receiver PHY (possibly among others) + PHY_1MBPS_BIT = (1<<0), + PHY_1MBPS_POS = (0), + /// The Host prefers to use the LE 2M transmitter/receiver PHY (possibly among others) + PHY_2MBPS_BIT = (1<<1), + PHY_2MBPS_POS = (1), + /// The Host prefers to use the LE Coded transmitter/receiver PHY (possibly among others) + PHY_CODED_BIT = (1<<2), + PHY_CODED_POS = (2), + /// The Host prefers to use the LE Coded transmitter/receiver PHY (possibly among others) + PHY_ALL = (PHY_1MBPS_BIT | PHY_2MBPS_BIT | PHY_CODED_BIT), +}; + +/// Specify what rate Host prefers to use in transmission on coded PHY. HCI:7.8.49 +enum le_phy_opt +{ + /// The Host has no preferred coding when transmitting on the LE Coded PHY + PHY_OPT_NO_LE_CODED_TX_PREF, + /// The Host prefers that S=2 coding be used when transmitting on the LE Coded PHY + PHY_OPT_S2_LE_CODED_TX_PREF, + /// The Host prefers that S=8 coding be used when transmitting on the LE Coded PHY + PHY_OPT_S8_LE_CODED_TX_PREF, +}; + + +enum le_phy_mode +{ + PHYS_MOD_STANDARD , + PHYS_MOD_STABLE , + PHYS_MOD_MAX, +}; + +///Transmit Power level types +enum +{ + ///Current Power Level + TX_PW_LVL_CURRENT = 0x00, + ///Maximum power level + TX_PW_LVL_MAX, +}; + +///Controller to Host flow control +enum +{ + /// C-> H flow control off + FLOW_CTRL_OFF = 0x00, + ///C->H ACL flow control on only + FLOW_CTRL_ON_ACL_OFF_SYNC, + ///C->H Sync flow control on only + FLOW_CTRL_OFF_ACL_ON_SYNC, + ///C->H ACL and Sync flow control on + FLOW_CTRL_ON_ACL_ON_SYNC, +}; + +///LE Supported Host enable +enum +{ + ///Disable LE supported Host + LE_SUPP_HOST_DIS = 0x00, + ///Enable LE Supported Host + LE_SUPP_HOST_EN, +}; + +///Simultaneous LE Host enable +enum +{ + ///Disable LE simultaneous Host disable + SIMULT_LE_HOST_DIS = 0x00, + ///Enable LE simultaneous Host disable + SIMULT_LE_HOST_EN, +}; + +///Advertising HCI Type +enum +{ + ///Connectable Undirected advertising + ADV_CONN_UNDIR = 0x00, + ///Connectable high duty cycle directed advertising + ADV_CONN_DIR, + ///Discoverable undirected advertising + ADV_DISC_UNDIR, + ///Non-connectable undirected advertising + ADV_NONCONN_UNDIR, + ///Connectable low duty cycle directed advertising + ADV_CONN_DIR_LDC, +}; + +///Advertising event properties values for legacy PDUs +enum +{ + ///Connectable and scannable undirected + ADV_IND = 0x13, + ///Connectable directed (low duty cycle) + ADV_DIRECT_LO_IND = 0x15, + ///Connectable directed (high duty cycle) + ADV_DIRECT_HI_IND = 0x1D, + ///Connectable directed (received) + ADV_DIRECT_IND = 0x15, + ///Scannable undirected + ADV_SCAN_IND = 0x12, + ///Non-connectable and non-scannable undirected + ADV_NONCONN_IND = 0x10, + ///Scan response to an ADV_IND + SCAN_RSP_TO_ADV_IND = 0x1B, + ///Scan response to an ADV_SCAN_IND + SCAN_RSP_TO_ADV_SCAN_IND = 0x1A, +}; + +///Advertising event properties masks +enum +{ + ///Connectable advertising + ADV_CON = 0x01, + ///Scannable advertising + ADV_SCAN = 0x02, + ///Directed advertising + ADV_DIRECT = 0x04, + ///High duty cycle directed connectable advertising + ADV_DIRECT_HI = 0x08, + ///Use legacy advertising PDUs + ADV_LEGACY = 0x10, + ///Omit advertiser's address from all PDUs ("anonymous advertising") + ADV_ANONYMOUS = 0x20, + ///Include TxPower in the extended header of the advertising PDU + ADV_TX_PWR = 0x40, +}; + +///Scanning HCI Type +enum +{ + ///Scan request + SCAN_REQ, + ///Scan response + SCAN_RSP, +}; + +///BD address type +enum addr_type +{ + ///Public BD address + ADDR_PUBLIC = 0x00, + ///Random BD Address + ADDR_RAND, + /// Controller generates Resolvable Private Address based on the + /// local IRK from resolving list. If resolving list contains no matching + /// entry, use public address. + ADDR_RPA_OR_PUBLIC, + /// Controller generates Resolvable Private Address based on the + /// local IRK from resolving list. If resolving list contains no matching + /// entry, use random address. + ADDR_RPA_OR_RAND, + /// mask used to determine Address type in the air + ADDR_MASK = 0x01, + /// mask used to determine if an address is an RPA + ADDR_RPA_MASK = 0x02, + /// Random device address (controller unable to resolve) + ADDR_RAND_UNRESOLVED = 0xFE, + /// No address provided (anonymous advertisement) + ADDR_NONE = 0xFF, +}; + +///Privacy mode type +enum +{ + ///Network privacy mode + PRIV_TYPE_NETWORK = 0x00, + ///Device privacy mode + PRIV_TYPE_DEVICE = 0x01, +}; + +/// Random Address type (2 MSB of the LE BD Address) +enum rnd_addr_type +{ + /// Static random address - 11 (MSB->LSB) + RND_STATIC_ADDR = 0xC0, + /// Private non resolvable address - 00 (MSB->LSB) + RND_NON_RSLV_ADDR = 0x00, + /// Private resolvable address - 01 (MSB->LSB) + RND_RSLV_ADDR = 0x40, +}; + +///Advertising channels enables +enum adv_channel_map +{ + ///Byte value for advertising channel map for channel 37 enable + ADV_CHNL_37_EN = 0x01, + ///Byte value for advertising channel map for channel 38 enable + ADV_CHNL_38_EN = 0x02, + ///Byte value for advertising channel map for channel 39 enable + ADV_CHNL_39_EN = 0x04, + ///Byte value for advertising channel map for channel 37, 38 and 39 enable + ADV_ALL_CHNLS_EN = 0x07, +}; + +///Advertising filter policy +enum adv_filter_policy +{ + ///Allow both scan and connection requests from anyone + ADV_ALLOW_SCAN_ANY_CON_ANY = 0x00, + ///Allow both scan req from White List devices only and connection req from anyone + ADV_ALLOW_SCAN_WLST_CON_ANY, + ///Allow both scan req from anyone and connection req from White List devices only + ADV_ALLOW_SCAN_ANY_CON_WLST, + ///Allow scan and connection requests from White List devices only + ADV_ALLOW_SCAN_WLST_CON_WLST, +}; + +///Advertising enables +enum +{ + ///Disable advertising + ADV_DIS = 0x00, + ///Enable advertising + ADV_EN, +}; + +///LE Scan type +enum +{ + ///Passive scan + SCAN_BLE_PASSIVE = 0x00, + ///Active scan + SCAN_BLE_ACTIVE, +}; + +///Scan filter policy +enum scan_filter_policy +{ + ///Allow advertising packets from anyone + SCAN_ALLOW_ADV_ALL = 0x00, + ///Allow advertising packets from White List devices only + SCAN_ALLOW_ADV_WLST, + ///Allow advertising packets from anyone and Direct adv using RPA in InitA + SCAN_ALLOW_ADV_ALL_AND_INIT_RPA, + ///Allow advertising packets from White List devices only and Direct adv using RPA in InitA + SCAN_ALLOW_ADV_WLST_AND_INIT_RPA, +}; + +///Le Scan enables +enum +{ + ///Disable scan + SCAN_DIS = 0x00, + ///Enable scan + SCAN_EN, +}; + +///Filter duplicates +enum scan_dup_filter_policy +{ + ///Disable filtering of duplicate packets + SCAN_FILT_DUPLIC_DIS = 0x00, + ///Enable filtering of duplicate packets + SCAN_FILT_DUPLIC_EN, + ///Enable filtering of duplicate packets per scan period + SCAN_FILT_DUPLIC_EN_PER_PERIOD, +}; + +///Initiator Filter policy +enum +{ + ///Initiator will ignore White List + INIT_FILT_IGNORE_WLST = 0x00, + ///Initiator will use White List + INIT_FILT_USE_WLST, +}; + +///Periodic Synchronization Filter policy +enum +{ + ///Use the Advertising SID, Advertising Address Type and Advertising Address parameters to determine + ///which advertiser to listen to + PER_SYNC_FILT_IGNORE_PAL = 0x00, + ///Use the Periodic Advertiser List to determine which advertiser to listen to + PER_SYNC_FILT_USE_PAL, +}; + +/// Periodic Synchronization Options +enum per_sync_opt +{ + /** + * Use the Periodic Advertiser List to determine which advertiser to listen to, otherwise use the Advertising SID, + * Advertising Address Type and Advertising Address parameters + */ + PER_SYNC_FILT_USE_PAL_POS = 0, + PER_SYNC_FILT_USE_PAL_BIT = 0x01, + /// Periodic advertising reports initially enabled or disabled (default enabled) + PER_SYNC_REP_INIT_DIS_POS = 1, + PER_SYNC_REP_INIT_DIS_BIT = 0x02, +}; + +///Transmitter test Packet Payload Type +enum +{ + ///Pseudo-random 9 TX test payload type + PAYL_PSEUDO_RAND_9 = 0x00, + ///11110000 TX test payload type + PAYL_11110000, + ///10101010 TX test payload type + PAYL_10101010, + ///Pseudo-random 15 TX test payload type + PAYL_PSEUDO_RAND_15, + ///All 1s TX test payload type + PAYL_ALL_1, + ///All 0s TX test payload type + PAYL_ALL_0, + ///00001111 TX test payload type + PAYL_00001111, + ///01010101 TX test payload type + PAYL_01010101, +}; + +/// Constant defining the role +enum +{ + ///Master role + ROLE_MASTER, + ///Slave role + ROLE_SLAVE, +}; + +/// Constant clock accuracy +enum SCA +{ + ///Clock accuracy at 500PPM + SCA_500PPM, + ///Clock accuracy at 250PPM + SCA_250PPM, + ///Clock accuracy at 150PPM + SCA_150PPM, + ///Clock accuracy at 100PPM + SCA_100PPM, + ///Clock accuracy at 75PPM + SCA_75PPM, + ///Clock accuracy at 50PPM + SCA_50PPM, + ///Clock accuracy at 30PPM + SCA_30PPM, + ///Clock accuracy at 20PPM + SCA_20PPM +}; + +///Advertising pdu Type +/*@TRACE*/ +enum ble_adv_type +{ + /// Undirected advertising + BLE_ADV_IND = 0x00, + /// Directed advertising + BLE_ADV_DIRECT_IND = 0x01, + /// Non Connectable advertising + BLE_ADV_NONCONN_IND = 0x02, + /// Scan Request on primary channel + BLE_SCAN_REQ = 0x03, + /// Scan Response on secondary channel + BLE_AUX_SCAN_REQ = 0x03, + + /// Scan Response + BLE_SCAN_RSP = 0x04, + /// Connect Request on primary channel + BLE_CONNECT_IND = 0x05, + /// Connect Request on secondary channel + BLE_AUX_CONNECT_REQ = 0x05, + + /// Discoverable advertising + BLE_ADV_SCAN_IND = 0x06, + + /// Extended Advertising indication on primary channel + BLE_ADV_EXT_IND = 0x07, + + /// ADV data indication on secondary channel + BLE_AUX_ADV_IND = 0x07, + /// Scan response data on secondary channel + BLE_AUX_SCAN_RSP = 0x07, + /// Periodic Advertising packet on secondary channel + BLE_AUX_SYNC_IND = 0x07, + /// Continuation of advertising data on secondary channel + BLE_AUX_CHAIN_IND = 0x07, + /// Response of the AUX_CONNECT_REQ on secondary channel to confirm that connection is accepted + BLE_AUX_CONNECT_RSP = 0x08, + + /// Reserved + BLE_RESERVED_PDU_TYPE, +}; + + +/// LE Advertising Report Event Type HCI:7.7.65.2 +enum +{ + /// Connectable undirected advertising + ADV_IND_EVT = 0x00, + /// Connectable directed advertising + ADV_DIRECT_IND_EVT, + /// Scannable undirected advertising + ADV_SCAN_IND_EVT, + /// Non connectable undirected advertising + ADV_NONCONN_IND_EVT, + /// Scan Response + SCAN_RSP_EVT, + /// Reserved + RESERVED_ADV_EVT_TYPES, +}; + +/// LE Extended Advertising Report Event Type Bit Mask HCI:7.7.65.13 + +/// Connectable advertising event +#define CON_ADV_EVT_MSK 0x01 +/// Scannable advertising event +#define SCAN_ADV_EVT_MSK 0x02 +/// Directed advertising event +#define DIR_ADV_EVT_MSK 0x04 +/// Scan Response +#define SCAN_RSP_EVT_MSK 0x08 +/// Legacy advertising PDUs +#define LGCY_ADV_EVT_MSK 0x10 + +/// Connectable undirected advertising +#define LGCY_ADV_IND_EVT 0x13 //LGCY_ADV_EVT_MSK|SCAN_ADV_EVT_MSK|CON_ADV_EVT_MSK +/// Connectable directed advertising +#define LGCY_ADV_DIRECT_IND_EVT 0x15 //LGCY_ADV_EVT_MSK|DIR_ADV_EVT_MSK|CON_ADV_EVT_MSK +/// Scannable undirected advertising +#define LGCY_ADV_SCAN_IND_EVT 0x12 //LGCY_ADV_EVT_MSK|SCAN_ADV_EVT_MSK +/// Non connectable undirected advertising +#define LGCY_ADV_NONCONN_IND_EVT 0x10 //LGCY_ADV_EVT_MSK +/// Scan Response to ADV_IND +#define LGCY_SCAN_RSP_TO_ADV_IND_EVT 0x1B //LGCY_ADV_EVT_MSK|SCAN_RSP_EVT_MSK|SCAN_ADV_EVT_MSK|CON_ADV_EVT_MSK +/// Scan Response to ADV_SCAN_IND +#define LGCY_SCAN_RSP_TO_ADV_SCAN_IND_EVT 0x1A //LGCY_ADV_EVT_MSK|SCAN_RSP_EVT_MSK|SCAN_ADV_EVT_MSK + +/// Offset of data status field in event type value +#define ADV_EVT_DATA_STATUS_LSB 5 +/// Mask for data status field in event type value +#define ADV_EVT_DATA_STATUS_MASK 0x0060 +/// Data status of extended advertising event - Complete +#define ADV_EVT_DATA_STATUS_COMPLETE 0 +/// Data status of extended advertising event - Incomplete, more data to come +#define ADV_EVT_DATA_STATUS_INCOMPLETE 1 +/// Data status of extended advertising event - Incomplete, data truncated, no more to come +#define ADV_EVT_DATA_STATUS_TRUNCATED 2 +/// Data status of extended advertising event - Reserved for future use +#define ADV_EVT_DATA_STATUS_RESERVED 3 + +/// Data status of periodic advertising event - Complete +#define PER_ADV_EVT_DATA_STATUS_COMPLETE 0 +/// Data status of periodic advertising event - Incomplete, more data to come +#define PER_ADV_EVT_DATA_STATUS_INCOMPLETE 1 +/// Data status of periodic advertising event - Incomplete, data truncated, no more to come +#define PER_ADV_EVT_DATA_STATUS_TRUNCATED 2 + +/// LLID packet +enum +{ + /// Reserved for future use + LLID_ISO, + /// Continue + LLID_CONTINUE, + /// Start + LLID_START, + /// Control + LLID_CNTL +}; + +/// Remote OOB Data present parameter value HCI:7.1.29 +enum +{ + REM_OOB_DATA_NO = 0x00, + REM_OOB_DATA_P192 = 0x01, + REM_OOB_DATA_P256 = 0x02, + REM_OOB_DATA_P192_P256 = 0x03, +}; + +/// Encryption enabled parameter in HCI_Enc_Chg_Evt HCI:7.7.8 +enum +{ + ENC_OFF = 0x00, + ENC_BRDER_E0_LE_AESCCM = 0x01, + ENC_BREDR_AESCC = 0x02, +}; + +/// Combined duration of Preamble and Access Address depending on the PHY used (in us) +#define BLE_PREAMBLE_ACCESS_ADDR_DUR_1MBPS (5*8) +#define BLE_PREAMBLE_ACCESS_ADDR_DUR_2MBPS (6*4) +#define BLE_PREAMBLE_ACCESS_ADDR_DUR_125KBPS (80+256) +#define BLE_PREAMBLE_ACCESS_ADDR_DUR_500KBPS (80+256) + + + +/// size of the Maximum Adv Extended header length +#define BLE_EXT_MAX_HEADER_LEN (63) + +/// size of the LEN & MODE info preceeding the extended header +#define BLE_EXT_ADV_PRE_HEADER_LEN (1) +/// size of the FLAGS info at start of the extended header +#define BLE_EXT_ADV_HEADER_FLAGS_LEN (1) +/// size of the extended header in bytes (pre-header + flags) +#define BLE_EXT_ADV_HEADER_LEN (2) +/// Size of CTE info in extended header +#define BLE_EXT_CTE_INFO_LEN (1) +/// Size of ADV Data Info in extended header +#define BLE_EXT_ADI_LEN (2) +/// Size of Aux Pointer info in extended header +#define BLE_EXT_AUX_PTR_LEN (3) +/// Size of Sync PTR info in extended header +#define BLE_EXT_SYNC_LEN (18) +/// Size of TX Power info in extended header +#define BLE_EXT_TX_PWR_LEN (1) +/// Size of ACAD Data for ICL stream info - Not Encrypted +#define BLE_EXT_ACAD_ICL_STREAM_INFO_LEN (28) +/// Size of ACAD Data for ICL stream info - Encrypted +/// AD Type reserved for Stream info ACAD data +/// TODO [FBE] put 0x29 for the moment +#define BLE_EXT_ACAD_ICL_STREAM_INFO_AD_TYPE (0x29) +#define BLE_EXT_ACAD_ICL_STREAM_INFO_ENC_LEN (57) +/// Size of the Channel Map Update Indication in extended header +#define BLE_EXT_CHM_UPD_IND_LEN (9) +/// AD Types for ACAD data +#define BLE_EXT_ACAD_CHANNEL_MAP_UPDATE_INDICATION_AD_TYPE (0x28) + +/// Extended Header Flags +enum ble_ext_header_flags +{ + // AdvA + ADVA_BIT = 0x01, + ADVA_POS = 0, + // TargetA + TARGETA_BIT = 0x02, + TARGETA_POS = 1, + // SuppInfo + SUPPINFO_BIT = 0x04, + SUPPINFO_POS = 2, + // AdvDataInfo (ADI) + ADI_BIT = 0x08, + ADI_POS = 3, + // AuxPtr + AUXPTR_BIT = 0x10, + AUXPTR_POS = 4, + // SyncInfo + SYNCINFO_BIT = 0x20, + SYNCINFO_POS = 5, + // TxPower + TXPOWER_BIT = 0x40, + TXPOWER_POS = 6, +}; + +/// AUX pointer description +enum ble_aux_ptr +{ + // Aux LL Channel + BLE_AUX_LL_CHANNEL_MASK = 0x0000003F, + BLE_AUX_LL_CHANNEL_LSB = 0, + // Aux Clock Accuracy + BLE_AUX_CA_BIT = 0x00000040, + BLE_AUX_CA_POS = 6, + // Aux Offset Unit + BLE_AUX_OFFSET_UNIT_BIT = 0x00000080, + BLE_AUX_OFFSET_UNIT_POS = 7, + // Aux ADV offset + BLE_AUX_OFFSET_MASK = 0x001FFF00, + BLE_AUX_OFFSET_LSB = 8, + // Aux PHY + BLE_AUX_PHY_MASK = 0x00E00000, + BLE_AUX_PHY_LSB = 21, +}; + +/// CTEInfo field description +enum ble_cte_info +{ + // CTETime (5 bits) + BLE_CTE_INFO_CTE_TIME_MASK = 0x0000001F, + BLE_CTE_INFO_CTE_TIME_LSB = 0, + // RFU (1 bit) + BLE_CTE_INFO_RFU_BIT = 0x00000020, + BLE_CTE_INFO_RFU_POS = 5, + // CTEType (2 bits) + BLE_CTE_INFO_CTE_TYPE_MASK = 0x000000C0, + BLE_CTE_INFO_CTE_TYPE_LSB = 6, +}; + +/// Aux PHY values LL:2.3.4.5 +enum aux_phy +{ + AUX_PHY_1MBPS = 0, + AUX_PHY_2MBPS = 1, + AUX_PHY_CODED = 2, +}; + +/// SyncInfo - various fileds description +enum syncinfo_fields +{ + /// SyncInfo - Sync Offset description (13 bits) + BLE_SYNC_OFFSET_MASK = 0x1FFF, + BLE_SYNC_OFFSET_LSB = 0, + + /// SyncInfo - Offset Units description (1 bit) + BLE_SYNC_OFFSET_UNITS_BIT = 0x2000, + BLE_SYNC_OFFSET_UNITS_POS = 13, + + /// SyncInfo - Offset Adjust description (1 bit) + BLE_SYNC_OFFSET_ADJUST_BIT = 0x4000, + BLE_SYNC_OFFSET_ADJUST_POS = 14, + + /// SyncInfo[8] - ChM description (5 bits of 37 bits) + BLE_SYNC_CHMAP_END_MASK = 0x1F, + BLE_SYNC_CHMAP_END_LSB = 0, + + /// SyncInfo[8] - SCA description (3 bits) + BLE_SYNC_SCA_MASK = 0xE0, + BLE_SYNC_SCA_LSB = 5, +}; + +/// AdvDataInfo (ADI) field description +enum ble_adi +{ + // Advertising Data ID (DID) + BLE_ADI_DID_MASK = 0x0FFF, + BLE_ADI_DID_LSB = 0, + // Advertising Set ID (SID) + BLE_ADI_SID_MASK = 0xF000, + BLE_ADI_SID_LSB = 12, +}; + +/// Advertising mode +enum ble_adv_mode +{ + /// Non connectable and non scannable mode + BLE_MODE_NON_CON_SCAN = 0, + /// Connectable Mode (accept connection request) + BLE_MODE_CONNECTABLE = 1, + /// Scannable Mode (accept scan request) + BLE_MODE_SCANNABLE = 2, + /// Reserved Advertising mode + BLE_MODE_RESERVED = 3, +}; + +/// Advertising data operation +enum adv_data_op +{ + /// Intermediate fragment of fragmented extended advertising data + ADV_DATA_OP_INTERMEDIATE_FRAG = 0, + /// First fragment of fragmented extended advertising data + ADV_DATA_OP_FIRST_FRAG = 1, + /// Last fragment of fragmented extended advertising data + ADV_DATA_OP_LAST_FRAG = 2, + /// Complete extended advertising data + ADV_DATA_OP_COMPLETE = 3, + /// Unchanged data (just update the Advertising DID) + ADV_DATA_OP_UNCHANGED_DATA = 4, +}; + +/// Advertising data fragment preference +enum adv_data_frag_pref +{ + /// The Controller may fragment all Host advertising data + ADV_DATA_MAY_FRAG = 0, + /// The Controller should not fragment nor minimize fragmentation of Host advertising data + ADV_DATA_SHOULD_NOT_FRAG = 1, +}; + +/* + * STRUCTURE DEFINITONS + **************************************************************************************** + */ + +///BD name structure +struct bd_name +{ + ///length for name + uint8_t namelen; + ///array of bytes for name + uint8_t name[BD_NAME_SIZE]; +}; + +///Structure device name +/*@TRACE*/ +struct device_name +{ + ///array of bytes for name + uint8_t name[BD_NAME_SIZE]; +}; + +///Structure name vector +/*@TRACE*/ +struct name_vect +{ + uint8_t vect[NAME_VECT_SIZE]; +}; + +/// lap structure +/*@TRACE*/ +struct lap +{ + /// LAP + uint8_t A[BD_ADDR_LAP_LEN]; +}; + +/// class structure +/*@TRACE*/ +struct devclass +{ + /// class + uint8_t A[DEV_CLASS_LEN]; +}; + +///Extended inquiry response structure +/*@TRACE*/ +struct eir +{ + /// eir data + uint8_t data[EIR_DATA_SIZE]; +}; + +///Event mask structure +/*@TRACE*/ +struct evt_mask +{ + ///8-byte array for mask value + uint8_t mask[EVT_MASK_LEN]; +}; + +///Host number of completed packets structure, for 1 connection handle +struct host_cmpl_pkts +{ + ///Connection handle + uint16_t con_hdl; + ///Number of completed packets + uint16_t nb_cmpl_pkts; +}; + +///BD Address structure +/*@TRACE*/ +struct bd_addr +{ + ///6-byte array address value + uint8_t addr[BD_ADDR_LEN]; +}; + +///Access Address structure +/*@TRACE*/ +struct access_addr +{ + ///4-byte array access address + uint8_t addr[ACCESS_ADDR_LEN]; +}; + +///Advertising data structure +/*@TRACE*/ +struct adv_data +{ + ///Maximum length data bytes array + uint8_t data[ADV_DATA_LEN]; +}; + +///Scan response data structure +/*@TRACE*/ +struct scan_rsp_data +{ + ///Maximum length data bytes array + uint8_t data[SCAN_RSP_DATA_LEN]; +}; + +///Channel map structure +/*@TRACE*/ +struct chnl_map +{ + ///10-bytes channel map array + uint8_t map[CHNL_MAP_LEN]; +}; + +///Channel map structure +/*@TRACE*/ +struct le_chnl_map +{ + ///5-byte channel map array + uint8_t map[LE_CHNL_MAP_LEN]; +}; + +/// External frame period (duration & type) structure +struct ext_fr_period +{ + /// Period_Duration + uint16_t duration; + /// Period_Type + uint8_t type; +}; + +/// MWS scan frequency (low & high) structure +struct mws_scan_freq +{ + ///Scan_Frequency_Low + uint16_t low; + ///Scan_Frequency_High + uint16_t high; +}; + +/// MWS pattern interval (duration & type) structure +struct mws_pattern_intv +{ + ///MWS_PATTERN_IntervalDuration + uint16_t duration; + ///MWS_PATTERN_IntervalType + uint8_t type; +}; + + +/// MWS transport rates structure +struct mws_trans_rate +{ + ///To_MWS_Baud_Rate + uint32_t to_mws_baud_rate; + ///From_MWS_Baud_Rate + uint32_t from_mws_baud_rate; +}; + +/// MWS transports strucutre +struct mws_transport +{ + ///Transport_Layer + uint8_t layer_id; + ///Num_Baud_Rates + uint8_t num_baud_rates; + ///To/From_MWS_Baud_Rates + struct mws_trans_rate *rates; +}; + + +/// SAM submaps structure +struct sam_submaps +{ + //12-byte SAM submaps array of 2-bit fields + //The nth (numbering from 0) such field defines the submap type of the nth submap in the map: + // - SAM_SLOTS_SUBMAPPED: Each slot is individually available or unavailable as configured. + // - SAM_SLOTS_AVAILABLE: All slots are available for transmission and reception. + // - SAM_SLOTS_UNAVAILABLE: All slots are unavailable for transmission and reception. + // - Other: Reserved for future use. + uint8_t map[SAM_SUBMAPS_LEN]; +}; + +/// SAM type0 submap structure +struct sam_type0_submap +{ + //14-byte type0 submap array of 2-bit fields + //The nth (numbering from 0) such field defines the submap type of the nth submap in the map: + // - SAM_SLOT_NOT_AVAILABLE: The slot is not available for transmision or reception. + // - SAM_SLOT_TX_AVAILABLE: The slot is available for transmission but not reception. + // - SAM_SLOT_RX_AVAILABLE: The slot is available for reception but not transmission. + // - SAM_SLOT_TX_RX_AVAILABLE: The slot is available for both transmission and reception. + uint8_t map[SAM_TYPE0_SUBMAP_LEN]; +}; + +///Long Term Key structure +/*@TRACE*/ +struct ltk +{ + ///16-byte array for LTK value + uint8_t ltk[KEY_LEN]; +}; + +///Identity Resolving Key structure +/*@TRACE*/ +struct irk +{ + ///16-byte array for IRK value + uint8_t key[KEY_LEN]; +}; + +/// Initialization vector (for AES-CCM encryption) +/*@TRACE*/ +struct initialization_vector +{ + ///8-byte array + uint8_t vect[BLE_IV_LEN]; +}; + +/// Bluetooth address with link key +struct bd_addr_plus_key +{ + /// BD Address + struct bd_addr bd_addr; + /// Link Key + struct ltk link_key; +}; + +///Random number structure +/*@TRACE*/ +struct rand_nb +{ + ///8-byte array for random number + uint8_t nb[RAND_NB_LEN]; +}; + +///Advertising report structure +/*@TRACE*/ +struct adv_report +{ + ///Event type: + /// - ADV_CONN_UNDIR: Connectable Undirected advertising + /// - ADV_CONN_DIR: Connectable directed advertising + /// - ADV_DISC_UNDIR: Discoverable undirected advertising + /// - ADV_NONCONN_UNDIR: Non-connectable undirected advertising + uint8_t evt_type; + ///Advertising address type: public/random + uint8_t adv_addr_type; + ///Advertising address value + struct bd_addr adv_addr; + ///Data length in advertising packet + uint8_t data_len; + ///Data of advertising packet + uint8_t data[ADV_DATA_LEN]; + ///RSSI value for advertising packet (in dBm, between -127 and +20 dBm) + int8_t rssi; +}; + +///Direct Advertising report structure +/*@TRACE*/ +struct dir_adv_report +{ + ///Event type: + /// - ADV_CONN_DIR: Connectable directed advertising + uint8_t evt_type; + ///Address type: public/random + uint8_t addr_type; + ///Address value + struct bd_addr addr; + ///Direct address type: public/random + uint8_t dir_addr_type; + ///Direct address value + struct bd_addr dir_addr; + ///RSSI value for advertising packet (in dBm, between -127 and +20 dBm) + int8_t rssi; +}; + +///Exteneded Advertising report structure +/*@TRACE*/ +struct ext_adv_report +{ + ///Event type + uint16_t evt_type; + ///Advertising address type: public/random + uint8_t adv_addr_type; + ///Advertising address value + struct bd_addr adv_addr; + ///Primary PHY + uint8_t phy; + ///Secondary PHY + uint8_t phy2; + ///Advertising SID + uint8_t adv_sid; + ///Tx Power + uint8_t tx_power; + ///RSSI value for advertising packet (in dBm, between -127 and +20 dBm) + int8_t rssi; + ///Periodic Advertising interval (Time=N*1.25ms) + uint16_t interval; + ///Direct address type + uint8_t dir_addr_type; + ///Direct address value + struct bd_addr dir_addr; + ///Data length in advertising packet + uint8_t data_len; + ///Data of advertising packet + uint8_t data[EXT_ADV_DATA_MAX_LEN]; +}; + +///Supported LE Features structure +/*@TRACE*/ +struct le_features +{ + ///8-byte array for LE features + uint8_t feats[LE_FEATS_LEN]; +}; + +///Simple pairing hash structure +/*@TRACE*/ +struct hash +{ + ///16-byte array for LTK value + uint8_t C[KEY_LEN]; +}; + +///Simple pairing randomizer structure +/*@TRACE*/ +struct randomizer +{ + ///16-byte array for LTK value + uint8_t R[KEY_LEN]; +}; + +///Pin code structure +/*@TRACE*/ +struct pin_code +{ + ///16-byte array for PIN value + uint8_t pin[PIN_CODE_MAX_LEN]; +}; + +///Sres structure +/*@TRACE*/ +struct sres_nb +{ + ///8-byte array for random number + uint8_t nb[SRES_LEN]; +}; + +///aco structure +/*@TRACE*/ +struct aco +{ + ///8-byte array for random number + uint8_t a[ACO_LEN]; +}; + +///struct byte 16 to stay align with the sdl version +/*@TRACE*/ +struct byte16 +{ + uint8_t A[16]; +}; + +///Controller number of completed packets structure +/*@TRACE*/ +struct nb_cmpl_pk +{ + ///Connection handle + uint16_t con_hdl; + ///Controller number of data packets that have been completed since last time + uint16_t nb_hc_cmpl_pkts; +}; + +///Supported Features structure +/*@TRACE*/ +struct features +{ + ///8-byte array for features + uint8_t feats[FEATS_LEN]; +}; + +///Supported commands structure +/*@TRACE*/ +struct supp_cmds +{ + ///64-byte array for supported commands + uint8_t cmds[SUPP_CMDS_LEN]; +}; + +///Supported LMP features structure +struct lmp_features +{ + ///8-byte array for LMp features + uint8_t feats[FEATS_LEN]; +}; + +///Simple pairing IO capabilities +struct io_capability +{ + ///IO capability + uint8_t io_cap; + /// Out Of Band Data present + bool oob_data_present; + ///Authentication Requirement + uint8_t aut_req; +}; + +///Public key +struct pub_key_192 +{ + uint8_t p_key[PUB_KEY_192_LEN/2]; +}; + +///Public key +struct pub_key_256 +{ + uint8_t p_key[PUB_KEY_256_LEN/2]; +}; + +///Simple pairing public keys 192 +struct sp_pub_key_192 +{ + ///Public key X + struct pub_key_192 X; + ///Public key Y + struct pub_key_192 Y; +}; + +///Simple pairing public keys 256 +struct sp_pub_key_256 +{ + ///Public key X + struct pub_key_256 X; + ///Public key Y + struct pub_key_256 Y; +}; + +///Supported LE states structure +/*@TRACE*/ +struct le_states +{ + ///8-byte array for LE states + uint8_t supp_states[LE_STATES_LEN]; +}; + +///White List element structure +struct white_list +{ + ///BD address of device entry + struct bd_addr wl_bdaddr; + ///BD address type of device entry + uint8_t wl_bdaddr_type; +}; + +///RAL element structure +struct ral_entry +{ + /// Peer ID address + struct bd_addr bd_addr; + /// Peer address type + uint8_t addr_type; + /// Local IRK + struct irk local_irk; + /// Peer IRK + struct irk peer_irk; +}; + +///CRC initial value structure +/*@TRACE*/ +struct crc_init +{ + ///3-byte array CRC initial value + uint8_t crc[CRC_INIT_LEN]; +}; + +///Session key diversifier master or slave structure +/*@TRACE*/ +struct sess_k_div_x +{ + ///8-byte array for diversifier value + uint8_t skdiv[SESS_KEY_DIV_LEN]; +}; + +///Session key diversifier structure +struct sess_k_div +{ + ///16-byte array for session key diversifier. + uint8_t skd[2*SESS_KEY_DIV_LEN]; +}; + +///Initiator vector +/*@TRACE*/ +struct init_vect +{ + ///4-byte array for vector + uint8_t iv[INIT_VECT_LEN]; +}; + +/*@TRACE*/ +typedef struct t_public_key +{ + uint8_t x[PUBLIC_KEY_P256_LEN]; + uint8_t y[PUBLIC_KEY_P256_LEN]; + +} t_public_key; + +/// structure connection request LLData +struct pdu_con_req_lldata +{ + /// Access address + struct access_addr aa; + + /// CRC init + struct crc_init crcinit; + + /// Window size (in units of 1,25 ms, i.e. 2 slots) + uint8_t winsize; + + /// Window offset (in units of 1,25 ms, i.e. 2 slots) + uint16_t winoffset; + + /// Interval (in units of 1,25 ms, i.e. 2 slots) + uint16_t interval; + + /// Latency + uint16_t latency; + + /// Timeout (in units of 10 ms, i.e. 16 slots) + uint16_t timeout; + + /// Channel mapping + struct le_chnl_map chm; + + /// Hopping + uint8_t hop_sca; +}; + +/// structure connection request +struct pdu_con_req +{ + /// Initiator address + struct bd_addr inita; + + /// Advertiser address + struct bd_addr adva; + + /// LLData + struct pdu_con_req_lldata lldata; +}; + +/// structure advertising syncinfo field +/*@TRACE*/ +struct sync_info +{ + /// Sync offset (in offset units) + uint16_t sync_offset; + + /// Offset units (0: 30us, 1: 300us) + uint8_t offset_units; + + /// Offset adjust (0: no action, 1: add 2.4576 seconds) + uint8_t offset_adjust; + + /// Interval (in units of 1,25 ms, i.e. 2 slots) + uint16_t interval; + + /// Channel mapping + struct le_chnl_map ch_map; + + /// Clock accuracy (@see enum SCA) + uint8_t sca; + + /// Access address + struct access_addr aa; + + /// CRC init + struct crc_init crcinit; + + /// Event counter + uint16_t evt_counter; +}; + +/// @} COMMON_BT_DEFINES +#endif // COMMON_BT_DEFINES_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/common/api/common_endian.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/common/api/common_endian.h new file mode 100755 index 0000000..59e5ee4 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/common/api/common_endian.h @@ -0,0 +1,349 @@ +/** + **************************************************************************************** + * + * @file common_endian.h + * + * @brief Common endianness conversion functions + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef _COMMON_ENDIAN_H_ +#define _COMMON_ENDIAN_H_ + +#include // standard integer definitions +#include "rwip_config.h" // stack configuration +#include "architect.h" // architectural platform definition + +/** + **************************************************************************************** + * @defgroup COMMON_ENDIAN Endianness + * @ingroup COMMON + * @brief Endianness conversion functions. + * + * This set of functions converts values between the local system + * and a external one. It is inspired from the htonl-like functions + * from the standard C library. + * + * Example: + * @code + * struct eth_header *header = get_header(); // get pointer on Eth II packet header + * uint16_t eth_id; // will contain the type of the packet + * eth_id = common_ntohs(header->eth_id); // retrieve the type with correct endianness + * @endcode + * + * @{ + * **************************************************************************************** + * */ + + +/** + **************************************************************************************** + * @brief Swap bytes of an array of bytes + * . + * The swap is done in every case. Should not be called directly. + * + * @param[in] p_val_out The output value. + * @param[in] p_val_in The input value. + * + * @param[in] len number of bytes to swap + **************************************************************************************** + */ +__INLINE void common_bswap(uint8_t* p_val_out, const uint8_t* p_val_in, uint16_t len) +{ + while (len > 0) + { + len--; + *p_val_out = p_val_in[len]; + p_val_out++; + } +} +/// @} COMMON_ENDIAN + +/** + **************************************************************************************** + * @brief Swap bytes of a 32 bits value. + * The swap is done in every case. Should not be called directly. + * @param[in] val32 The 32 bits value to swap. + * @return The 32 bit swapped value. + **************************************************************************************** + */ +__INLINE uint32_t common_bswap32(uint32_t val32) +{ + return (val32<<24) | ((val32<<8)&0xFF0000) | ((val32>>8)&0xFF00) | ((val32>>24)&0xFF); +} + +/** + **************************************************************************************** + * @brief Swap bytes of a 24 bits value. + * The swap is done in every case. Should not be called directly. + * @param[in] val24 The 24 bits value to swap. + * @return The 24 bit swapped value. + **************************************************************************************** + */ +__INLINE uint32_t common_bswap24(uint32_t val24) +{ + return ((val24<<16)&0xFF0000) | ((val24)&0xFF00) | ((val24>>16)&0xFF); +} + +/** + **************************************************************************************** + * @brief Swap bytes of a 16 bits value. + * The swap is done in every case. Should not be called directly. + * @param[in] val16 The 16 bit value to swap. + * @return The 16 bit swapped value. + **************************************************************************************** + */ +__INLINE uint16_t common_bswap16(uint16_t val16) +{ + return ((val16<<8)&0xFF00) | ((val16>>8)&0xFF); +} +/// @} COMMON_ENDIAN + + + + +/** + * **************************************************************************************** + * @defgroup COMMON_ENDIAN_NET Endianness (Network) + * @ingroup COMMON_ENDIAN + * @brief Endianness conversion functions for Network data + * + * Converts values between the local system and big-endian network data + * (e.g. IP, Ethernet, but NOT WLAN). + * + * The \b host term in the descriptions of these functions refers + * to the local system, i.e. \b application or \b embedded system. + * Therefore, these functions will behave differently depending on which + * side they are used. The reason of this terminology is to keep the + * same name than the standard C function. + * + * Behavior will depends on the endianness of the host: + * - little endian: swap bytes; + * - big endian: identity function. + * + * @{ + * **************************************************************************************** + * */ + +/** + **************************************************************************************** + * @brief Convert host to network long word. + * + * @param[in] hostlong Long word value to convert. + * + * @return The converted long word. + **************************************************************************************** + */ +__INLINE uint32_t common_htonl(uint32_t hostlong) +{ + #if (!CPU_LE) + return hostlong; + #else + return common_bswap32(hostlong); + #endif // CPU_LE +} + +/** + **************************************************************************************** + * @brief Convert host to network long 24-bit value. + * + * @param[in] val24 24-bit value to convert. + * + * @return The converted 24-but value. + **************************************************************************************** + */ +__INLINE uint32_t common_hton24(uint32_t host24) +{ + #if (!CPU_LE) + return host24; + #else + return common_bswap24(host24); + #endif // CPU_LE +} + +/** + **************************************************************************************** + * @brief Convert host to network short word. + * + * @param[in] hostshort Short word value to convert. + * + * @return The converted short word. + **************************************************************************************** + */ +__INLINE uint16_t common_htons(uint16_t hostshort) +{ + #if (!CPU_LE) + return hostshort; + #else + return common_bswap16(hostshort); + #endif // CPU_LE +} + +/** + **************************************************************************************** + * @brief Convert network to host long word. + * + * @param[in] netlong Long word value to convert. + * + * @return The converted long word. + **************************************************************************************** + */ +__INLINE uint32_t common_ntohl(uint32_t netlong) +{ + return common_htonl(netlong); +} + +/** + **************************************************************************************** + * @brief Convert network to host 24-bit value. + * + * @param[in] val24 24-bit to convert. + * + * @return The converted 24-bit value. + **************************************************************************************** + */ +__INLINE uint32_t common_ntoh24(uint32_t val24) +{ + return common_hton24(val24); +} + +/** + **************************************************************************************** + * @brief Convert network to host short word. + * + * @param[in] netshort Short word value to convert. + * + * @return The converted short word. + **************************************************************************************** + */ +__INLINE uint16_t common_ntohs(uint16_t netshort) +{ + return common_htons(netshort); +} +/// @} COMMON_ENDIAN_NET + +/** + * **************************************************************************************** + * @defgroup COMMON_ENDIAN_BT Endianness (BT) + * @ingroup COMMON_ENDIAN + * @brief Endianness conversion functions for Bluetooth data (HCI and protocol) + * + * Converts values between the local system and little-endian Bluetooth data. + * + * The \b host term in the descriptions of these functions refers + * to the local system (check \ref COMMON_ENDIAN_NET "this comment"). + * + * Behavior will depends on the endianness of the host: + * - little endian: identity function; + * - big endian: swap bytes. + * + * @addtogroup COMMON_ENDIAN_BT + * @{ + * **************************************************************************************** + * */ + + +/** + **************************************************************************************** + * @brief Convert Bluetooth to host 24-bit value. + * + * @param[in] val24 24-bit to convert. + * + * @return The converted 24-bit value. + **************************************************************************************** + */ +__INLINE uint32_t common_htob24(uint32_t val24) +{ + #if (CPU_LE) + return val24; + #else + return common_hton24(val24); + #endif // CPU_LE +} + +/** + **************************************************************************************** + * @brief Convert host to Bluetooth long word. + * + * @param[in] hostlong Long word value to convert. + * + * @return The converted long word. + **************************************************************************************** + */ +__INLINE uint32_t common_htobl(uint32_t hostlong) +{ + #if (CPU_LE) + return hostlong; + #else + return common_bswap32(hostlong); + #endif // CPU_LE +} + +/** + **************************************************************************************** + * @brief Convert host to Bluetooth short word. + * + * @param[in] hostshort Short word value to convert. + * + * @return The converted short word. + **************************************************************************************** + */ +__INLINE uint16_t common_htobs(uint16_t hostshort) +{ + #if (CPU_LE) + return hostshort; + #else + return common_bswap16(hostshort); + #endif // CPU_LE +} + + +/** + **************************************************************************************** + * @brief Convert Bluetooth to host 24-bit value. + * + * @param[in] val24 24-bit to convert. + * + * @return The converted 24-bit value. + **************************************************************************************** + */ +__INLINE uint32_t common_btoh24(uint32_t val24) +{ + return common_htob24(val24); +} + +/** + **************************************************************************************** + * @brief Convert Bluetooth to host long word. + * + * @param[in] btlong Long word value to convert. + * + * @return The converted long word. + **************************************************************************************** + */ +__INLINE uint32_t common_btohl(uint32_t btlong) +{ + return common_htobl(btlong); +} + + +/** + **************************************************************************************** + * @brief Convert Bluetooth to host short word. + * + * @param[in] btshort Short word value to convert. + * + * @return The converted short word. + **************************************************************************************** + */ +__INLINE uint16_t common_btohs(uint16_t btshort) +{ + return common_htobs(btshort); +} +/// @} COMMON_ENDIAN + +#endif // _COMMON_ENDIAN_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/common/api/common_error.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/common/api/common_error.h new file mode 100755 index 0000000..cfb5f32 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/common/api/common_error.h @@ -0,0 +1,116 @@ +/** + **************************************************************************************** + * + * @file common_error.h + * + * @brief List of codes for error in RW Software. + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef COMMON_ERROR_H_ +#define COMMON_ERROR_H_ + +/** + **************************************************************************************** + * @addtogroup COMMON_ERROR Error Codes + * @ingroup COMMON + * @brief Defines error codes in messages. + * + * @{ + **************************************************************************************** + */ + +/* + * DEFINES + **************************************************************************************** + */ +enum common_error +{ +/***************************************************** + *** ERROR CODES *** + *****************************************************/ + + COMMON_ERROR_NO_ERROR = 0x00, + COMMON_ERROR_UNKNOWN_HCI_COMMAND = 0x01, + COMMON_ERROR_UNKNOWN_CONNECTION_ID = 0x02, + COMMON_ERROR_HARDWARE_FAILURE = 0x03, + COMMON_ERROR_PAGE_TIMEOUT = 0x04, + COMMON_ERROR_AUTH_FAILURE = 0x05, + COMMON_ERROR_PIN_MISSING = 0x06, + COMMON_ERROR_MEMORY_CAPA_EXCEED = 0x07, + COMMON_ERROR_CON_TIMEOUT = 0x08, + COMMON_ERROR_CON_LIMIT_EXCEED = 0x09, + COMMON_ERROR_SYNC_CON_LIMIT_DEV_EXCEED = 0x0A, + COMMON_ERROR_CON_ALREADY_EXISTS = 0x0B, + COMMON_ERROR_COMMAND_DISALLOWED = 0x0C, + COMMON_ERROR_CONN_REJ_LIMITED_RESOURCES = 0x0D, + COMMON_ERROR_CONN_REJ_SECURITY_REASONS = 0x0E, + COMMON_ERROR_CONN_REJ_UNACCEPTABLE_BDADDR = 0x0F, + COMMON_ERROR_CONN_ACCEPT_TIMEOUT_EXCEED = 0x10, + COMMON_ERROR_UNSUPPORTED = 0x11, + COMMON_ERROR_INVALID_HCI_PARAM = 0x12, + COMMON_ERROR_REMOTE_USER_TERM_CON = 0x13, + COMMON_ERROR_REMOTE_DEV_TERM_LOW_RESOURCES = 0x14, + COMMON_ERROR_REMOTE_DEV_POWER_OFF = 0x15, + COMMON_ERROR_CON_TERM_BY_LOCAL_HOST = 0x16, + COMMON_ERROR_REPEATED_ATTEMPTS = 0x17, + COMMON_ERROR_PAIRING_NOT_ALLOWED = 0x18, + COMMON_ERROR_UNKNOWN_LMP_PDU = 0x19, + COMMON_ERROR_UNSUPPORTED_REMOTE_FEATURE = 0x1A, + COMMON_ERROR_SCO_OFFSET_REJECTED = 0x1B, + COMMON_ERROR_SCO_INTERVAL_REJECTED = 0x1C, + COMMON_ERROR_SCO_AIR_MODE_REJECTED = 0x1D, + COMMON_ERROR_INVALID_LMP_PARAM = 0x1E, + COMMON_ERROR_UNSPECIFIED_ERROR = 0x1F, + COMMON_ERROR_UNSUPPORTED_LMP_PARAM_VALUE = 0x20, + COMMON_ERROR_ROLE_CHANGE_NOT_ALLOWED = 0x21, + COMMON_ERROR_LMP_RSP_TIMEOUT = 0x22, + COMMON_ERROR_LMP_COLLISION = 0x23, + COMMON_ERROR_LMP_PDU_NOT_ALLOWED = 0x24, + COMMON_ERROR_ENC_MODE_NOT_ACCEPT = 0x25, + COMMON_ERROR_LINK_KEY_CANT_CHANGE = 0x26, + COMMON_ERROR_QOS_NOT_SUPPORTED = 0x27, + COMMON_ERROR_INSTANT_PASSED = 0x28, + COMMON_ERROR_PAIRING_WITH_UNIT_KEY_NOT_SUP = 0x29, + COMMON_ERROR_DIFF_TRANSACTION_COLLISION = 0x2A, + COMMON_ERROR_QOS_UNACCEPTABLE_PARAM = 0x2C, + COMMON_ERROR_QOS_REJECTED = 0x2D, + COMMON_ERROR_CHANNEL_CLASS_NOT_SUP = 0x2E, + COMMON_ERROR_INSUFFICIENT_SECURITY = 0x2F, + COMMON_ERROR_PARAM_OUT_OF_MAND_RANGE = 0x30, + COMMON_ERROR_ROLE_SWITCH_PEND = 0x32, /* LM_ROLE_SWITCH_PENDING */ + COMMON_ERROR_RESERVED_SLOT_VIOLATION = 0x34, /* LM_RESERVED_SLOT_VIOLATION */ + COMMON_ERROR_ROLE_SWITCH_FAIL = 0x35, /* LM_ROLE_SWITCH_FAILED */ + COMMON_ERROR_EIR_TOO_LARGE = 0x36, /* LM_EXTENDED_INQUIRY_RESPONSE_TOO_LARGE */ + COMMON_ERROR_SP_NOT_SUPPORTED_HOST = 0x37, + COMMON_ERROR_HOST_BUSY_PAIRING = 0x38, + COMMON_ERROR_CONTROLLER_BUSY = 0x3A, + COMMON_ERROR_UNACCEPTABLE_CONN_PARAM = 0x3B, + COMMON_ERROR_ADV_TO = 0x3C, + COMMON_ERROR_TERMINATED_MIC_FAILURE = 0x3D, + COMMON_ERROR_CONN_FAILED_TO_BE_EST = 0x3E, + COMMON_ERROR_CCA_REJ_USE_CLOCK_DRAG = 0x40, + COMMON_ERROR_TYPE0_SUBMAP_NOT_DEFINED = 0x41, + COMMON_ERROR_UNKNOWN_ADVERTISING_ID = 0x42, + COMMON_ERROR_LIMIT_REACHED = 0x43, + COMMON_ERROR_OPERATION_CANCELED_BY_HOST = 0x44, + COMMON_ERROR_PKT_TOO_LONG = 0x45, + + COMMON_ERROR_UNDEFINED = 0xFF, + + +/***************************************************** + *** HW ERROR CODES *** + *****************************************************/ + + COMMON_ERROR_HW_UART_OUT_OF_SYNC = 0x00, + COMMON_ERROR_HW_MEM_ALLOC_FAIL = 0x01, +}; + +/// @} COMMON_ERROR + +#endif // COMMON_ERROR_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/common/api/common_hci.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/common/api/common_hci.h new file mode 100755 index 0000000..8110d3e --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/common/api/common_hci.h @@ -0,0 +1,5962 @@ +/** + **************************************************************************************** + * + * @file common_hci.h + * + * @brief This file contains the HCI Bluetooth defines, enumerations and structures + * definitions for use by all modules in RW stack. + * + * Copyright (C) RivieraWaves 2009-2015 + * + **************************************************************************************** + */ + +#ifndef COMMON_HCI_H_ +#define COMMON_HCI_H_ + +/** + **************************************************************************************** + * @addtogroup COMMON Common SW Block + * @{ + **************************************************************************************** + */ + + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include // standard boolean definitions +#include // standard definitions +#include // standard integer definitions + +#include "rwip_config.h" // IP configuration + +#include "compiler.h" // compiler definitions + +/* + * DEFINES + **************************************************************************************** + */ + + +/******************************************************************************************/ +/* ------------------------- H4TL DEFINITIONS Part IV.A -----------------------------*/ +/******************************************************************************************/ + +///HCI Transport Header length - change if different transport +#define HCI_TRANSPORT_HDR_LEN 0x01 + +///UART header: command message type +#define HCI_CMD_MSG_TYPE 0x01 + +///UART header: ACL data message type +#define HCI_ACL_MSG_TYPE 0x02 + +///UART header: Synchronous data message type +#define HCI_SYNC_MSG_TYPE 0x03 + +///UART header: event message type +#define HCI_EVT_MSG_TYPE 0x04 + +/******************************************************************************************/ +/* ------------------------- HCI DEFINITIONS Part II.E -----------------------------*/ +/******************************************************************************************/ + +///HCI Command Opcode byte length +#define HCI_CMD_OPCODE_LEN (0x02) + +///HCI Event code byte length +#define HCI_EVT_CODE_LEN (0x01) + +///HCI Command/Event parameter length field byte length +#define HCI_CMDEVT_PARLEN_LEN (0x01) + +///HCI Command header length +#define HCI_CMD_HDR_LEN (HCI_CMD_OPCODE_LEN + HCI_CMDEVT_PARLEN_LEN) + +///HCI Event header length +#define HCI_EVT_HDR_LEN (HCI_EVT_CODE_LEN + HCI_CMDEVT_PARLEN_LEN) + +/// HCI ACL header: handle and flags decoding +enum hci_acl_hdr_fields +{ + /// bits[00:11]: Connection handle + HCI_ACL_HDR_HDL_LSB = (0), + HCI_ACL_HDR_HDL_MASK = (0x0FFF), + /// bits[12:13]: Packet boundary flag + HCI_ACL_HDR_PB_FLAG_LSB = (12), + HCI_ACL_HDR_PB_FLAG_MASK = (0x3000), + /// bits[14:15]: Broadcast flag + HCI_ACL_HDR_BC_FLAG_LSB = (14), + HCI_ACL_HDR_BC_FLAG_MASK = (0xC000), + /// Packet boundary and Broadcast flags + HCI_ACL_HDR_DATA_FLAGS_LSB = (12), + HCI_ACL_HDR_DATA_FLAGS_MASK = (0xF000), +}; + +#define HCI_ACL_HDR_HDL_FLAGS_POS (0) +#define HCI_ACL_HDR_HDL_FLAGS_LEN (2) +/// HCI ACL header: data length field length +#define HCI_ACL_HDR_DATA_LEN_POS (HCI_ACL_HDR_HDL_FLAGS_LEN) +#define HCI_ACL_HDR_DATA_LEN_LEN (2) + +///HCI ACL data packet header length +#define HCI_ACL_HDR_LEN (HCI_ACL_HDR_HDL_FLAGS_LEN + HCI_ACL_HDR_DATA_LEN_LEN) + +/// HCI Synchronous header: handle and flags decoding +enum hci_syn_hdr_fields +{ + /// bits[00:11]: Connection handle + HCI_SYNC_HDR_HDL_LSB = (0), + HCI_SYNC_HDR_HDL_MASK = (0x0FFF), + /// bits[12:13]: Packet status flag + HCI_SYNC_HDR_PSF_LSB = (12), + HCI_SYNC_HDR_PSF_MASK = (0x3000), + /// bits[14:15]: RFU + HCI_SYNC_HDR_RFU_LSB = (14), + HCI_SYNC_HDR_RFU_MASK = (0xC000), +}; + +#define HCI_SYNC_HDR_HDL_FLAGS_POS (0) +#define HCI_SYNC_HDR_HDL_FLAGS_LEN (2) + + +/// HCI Synchronous header: data length field length +#define HCI_SYNC_HDR_DATA_LEN_POS (HCI_SYNC_HDR_HDL_FLAGS_LEN) +#define HCI_SYNC_HDR_DATA_LEN_LEN (1) +#define HCI_SYNC_MAX_DATA_SIZE (255) + +///HCI sync data packet header length +#define HCI_SYNC_HDR_LEN (HCI_SYNC_HDR_HDL_FLAGS_LEN + HCI_SYNC_HDR_DATA_LEN_LEN) + +///HCI Command Complete Event minimum parameter length: 1(nb_pk)+2(opcode) +#define HCI_CCEVT_HDR_PARLEN (0x03) + +///HCI Command Complete Event header length:1(code)+1(len)+1(pk)+2(opcode) +#define HCI_CCEVT_HDR_LEN (HCI_EVT_HDR_LEN + HCI_CCEVT_HDR_PARLEN) + +///HCI Basic Command Complete Event packet length +#define HCI_CCEVT_BASIC_LEN (HCI_CCEVT_HDR_LEN + 1) + +///HCI Command Status Event parameter length - constant +#define HCI_CSEVT_PARLEN (0x04) + +///HCI Command Status Event length:1(code)+1(len)+1(st)+1(pk)+2(opcode) +#define HCI_CSEVT_LEN (HCI_EVT_HDR_LEN + HCI_CSEVT_PARLEN) + +///HCI Reset Command parameter length +#define HCI_RESET_CMD_PARLEN 0 + +/// Default return parameter length for HCI Command Complete Event +#define HCI_CCEVT_BASIC_RETPAR_LEN 1 + +/// Max HCI commands param size +#define HCI_MAX_CMD_PARAM_SIZE 255 + +/// Macro to extract OCF from OPCODE +#define HCI_OP2OCF(opcode) ((opcode) & 0x03FF) + +/// Macro to extract OGF from OPCODE +#define HCI_OP2OGF(opcode) ((opcode) >> 10 & 0x003F) + +/// Macro to create OPCODE from OGF and OCF +#define HCI_OPCODE(ocf, ogf) (((ogf) << 10) | ocf) + +/// Maximum length of HCI advertising data fragments +#define HCI_ADV_DATA_FRAG_MAX_LEN 252 + + +/************************************************************************************** + ************** HCI COMMANDS **************** + **************************************************************************************/ + +///HCI enumeration of possible Command OGF values. +enum +{ + ///HCI Link Control Commands Group OGF code + LK_CNTL_OGF = 0x01, + ///HCI Link Policy Commands Group OGF code + LK_POL_OGF, + ///HCI Controller and Baseband Commands Group OGF code + CNTLR_BB_OGF, + ///HCI Information Parameters Commands Group OGF code + INFO_PAR_OGF, + ///HCI Status Commands Group OGF code + STAT_PAR_OGF, + ///HCI Test Commands Group OGF code + TEST_OGF, + ///HCI Low Energy Commands Group OGF code + LE_CNTLR_OGF=0x08, + ///HCI Vendor Specific Group OGF code + VS_OGF = 0x3F, + MAX_OGF +}; + + +///Commands Opcodes: OGF(6b) | OCF(10b) +/* Some Abbreviation used in names: + * - LK = Link Key + * - RD = Read + * - WR = Write + * - REM = Remote + * - STG = Settings + * - CON = Connection + * - CHG = Change + * - DFT = Default + * - PER = Periodic + */ + +///HCI enumeration of possible Command OP Codes. +/*@TRACE*/ +enum hci_opcode +{ + HCI_NO_OPERATION_CMD_OPCODE = 0x0000, + + //Link Control Commands + HCI_INQ_CMD_OPCODE = 0x0401, + HCI_INQ_CANCEL_CMD_OPCODE = 0x0402, + HCI_PER_INQ_MODE_CMD_OPCODE = 0x0403, + HCI_EXIT_PER_INQ_MODE_CMD_OPCODE = 0x0404, + HCI_CREATE_CON_CMD_OPCODE = 0x0405, + HCI_DISCONNECT_CMD_OPCODE = 0x0406, + HCI_CREATE_CON_CANCEL_CMD_OPCODE = 0x0408, + HCI_ACCEPT_CON_REQ_CMD_OPCODE = 0x0409, + HCI_REJECT_CON_REQ_CMD_OPCODE = 0x040A, + HCI_LK_REQ_REPLY_CMD_OPCODE = 0x040B, + HCI_LK_REQ_NEG_REPLY_CMD_OPCODE = 0x040C, + HCI_PIN_CODE_REQ_REPLY_CMD_OPCODE = 0x040D, + HCI_PIN_CODE_REQ_NEG_REPLY_CMD_OPCODE = 0x040E, + HCI_CHG_CON_PKT_TYPE_CMD_OPCODE = 0x040F, + HCI_AUTH_REQ_CMD_OPCODE = 0x0411, + HCI_SET_CON_ENC_CMD_OPCODE = 0x0413, + HCI_CHG_CON_LK_CMD_OPCODE = 0x0415, + HCI_MASTER_LK_CMD_OPCODE = 0x0417, + HCI_REM_NAME_REQ_CMD_OPCODE = 0x0419, + HCI_REM_NAME_REQ_CANCEL_CMD_OPCODE = 0x041A, + HCI_RD_REM_SUPP_FEATS_CMD_OPCODE = 0x041B, + HCI_RD_REM_EXT_FEATS_CMD_OPCODE = 0x041C, + HCI_RD_REM_VER_INFO_CMD_OPCODE = 0x041D, + HCI_RD_CLK_OFF_CMD_OPCODE = 0x041F, + HCI_RD_LMP_HDL_CMD_OPCODE = 0x0420, + HCI_SETUP_SYNC_CON_CMD_OPCODE = 0x0428, + HCI_ACCEPT_SYNC_CON_REQ_CMD_OPCODE = 0x0429, + HCI_REJECT_SYNC_CON_REQ_CMD_OPCODE = 0x042A, + HCI_IO_CAP_REQ_REPLY_CMD_OPCODE = 0x042B, + HCI_USER_CFM_REQ_REPLY_CMD_OPCODE = 0x042C, + HCI_USER_CFM_REQ_NEG_REPLY_CMD_OPCODE = 0x042D, + HCI_USER_PASSKEY_REQ_REPLY_CMD_OPCODE = 0x042E, + HCI_USER_PASSKEY_REQ_NEG_REPLY_CMD_OPCODE = 0x042F, + HCI_REM_OOB_DATA_REQ_REPLY_CMD_OPCODE = 0x0430, + HCI_REM_OOB_DATA_REQ_NEG_REPLY_CMD_OPCODE = 0x0433, + HCI_IO_CAP_REQ_NEG_REPLY_CMD_OPCODE = 0x0434, + HCI_ENH_SETUP_SYNC_CON_CMD_OPCODE = 0x043D, + HCI_ENH_ACCEPT_SYNC_CON_CMD_OPCODE = 0x043E, + HCI_TRUNC_PAGE_CMD_OPCODE = 0x043F, + HCI_TRUNC_PAGE_CAN_CMD_OPCODE = 0x0440, + HCI_SET_CON_SLV_BCST_CMD_OPCODE = 0x0441, + HCI_SET_CON_SLV_BCST_REC_CMD_OPCODE = 0x0442, + HCI_START_SYNC_TRAIN_CMD_OPCODE = 0x0443, + HCI_REC_SYNC_TRAIN_CMD_OPCODE = 0x0444, + HCI_REM_OOB_EXT_DATA_REQ_REPLY_CMD_OPCODE = 0x0445, + + //Link Policy Commands + HCI_HOLD_MODE_CMD_OPCODE = 0x0801, + HCI_SNIFF_MODE_CMD_OPCODE = 0x0803, + HCI_EXIT_SNIFF_MODE_CMD_OPCODE = 0x0804, + HCI_PARK_STATE_CMD_OPCODE = 0x0805, + HCI_EXIT_PARK_STATE_CMD_OPCODE = 0x0806, + HCI_QOS_SETUP_CMD_OPCODE = 0x0807, + HCI_ROLE_DISCOVERY_CMD_OPCODE = 0x0809, + HCI_SWITCH_ROLE_CMD_OPCODE = 0x080B, + HCI_RD_LINK_POL_STG_CMD_OPCODE = 0x080C, + HCI_WR_LINK_POL_STG_CMD_OPCODE = 0x080D, + HCI_RD_DFT_LINK_POL_STG_CMD_OPCODE = 0x080E, + HCI_WR_DFT_LINK_POL_STG_CMD_OPCODE = 0x080F, + HCI_FLOW_SPEC_CMD_OPCODE = 0x0810, + HCI_SNIFF_SUB_CMD_OPCODE = 0x0811, + + //Controller and Baseband Commands + HCI_SET_EVT_MASK_CMD_OPCODE = 0x0C01, + HCI_RESET_CMD_OPCODE = 0x0C03, + HCI_SET_EVT_FILTER_CMD_OPCODE = 0x0C05, + HCI_FLUSH_CMD_OPCODE = 0x0C08, + HCI_RD_PIN_TYPE_CMD_OPCODE = 0x0C09, + HCI_WR_PIN_TYPE_CMD_OPCODE = 0x0C0A, + HCI_CREATE_NEW_UNIT_KEY_CMD_OPCODE = 0x0C0B, + HCI_RD_STORED_LK_CMD_OPCODE = 0x0C0D, + HCI_WR_STORED_LK_CMD_OPCODE = 0x0C11, + HCI_DEL_STORED_LK_CMD_OPCODE = 0x0C12, + HCI_WR_LOCAL_NAME_CMD_OPCODE = 0x0C13, + HCI_RD_LOCAL_NAME_CMD_OPCODE = 0x0C14, + HCI_RD_CON_ACCEPT_TO_CMD_OPCODE = 0x0C15, + HCI_WR_CON_ACCEPT_TO_CMD_OPCODE = 0x0C16, + HCI_RD_PAGE_TO_CMD_OPCODE = 0x0C17, + HCI_WR_PAGE_TO_CMD_OPCODE = 0x0C18, + HCI_RD_SCAN_EN_CMD_OPCODE = 0x0C19, + HCI_WR_SCAN_EN_CMD_OPCODE = 0x0C1A, + HCI_RD_PAGE_SCAN_ACT_CMD_OPCODE = 0x0C1B, + HCI_WR_PAGE_SCAN_ACT_CMD_OPCODE = 0x0C1C, + HCI_RD_INQ_SCAN_ACT_CMD_OPCODE = 0x0C1D, + HCI_WR_INQ_SCAN_ACT_CMD_OPCODE = 0x0C1E, + HCI_RD_AUTH_EN_CMD_OPCODE = 0x0C1F, + HCI_WR_AUTH_EN_CMD_OPCODE = 0x0C20, + HCI_RD_CLASS_OF_DEV_CMD_OPCODE = 0x0C23, + HCI_WR_CLASS_OF_DEV_CMD_OPCODE = 0x0C24, + HCI_RD_VOICE_STG_CMD_OPCODE = 0x0C25, + HCI_WR_VOICE_STG_CMD_OPCODE = 0x0C26, + HCI_RD_AUTO_FLUSH_TO_CMD_OPCODE = 0x0C27, + HCI_WR_AUTO_FLUSH_TO_CMD_OPCODE = 0x0C28, + HCI_RD_NB_BDCST_RETX_CMD_OPCODE = 0x0C29, + HCI_WR_NB_BDCST_RETX_CMD_OPCODE = 0x0C2A, + HCI_RD_HOLD_MODE_ACTIVITY_CMD_OPCODE = 0x0C2B, + HCI_WR_HOLD_MODE_ACTIVITY_CMD_OPCODE = 0x0C2C, + HCI_RD_TX_PWR_LVL_CMD_OPCODE = 0x0C2D, + HCI_RD_SYNC_FLOW_CTRL_EN_CMD_OPCODE = 0x0C2E, + HCI_WR_SYNC_FLOW_CTRL_EN_CMD_OPCODE = 0x0C2F, + HCI_SET_CTRL_TO_HOST_FLOW_CTRL_CMD_OPCODE = 0x0C31, + HCI_HOST_BUF_SIZE_CMD_OPCODE = 0x0C33, + HCI_HOST_NB_CMP_PKTS_CMD_OPCODE = 0x0C35, + HCI_RD_LINK_SUPV_TO_CMD_OPCODE = 0x0C36, + HCI_WR_LINK_SUPV_TO_CMD_OPCODE = 0x0C37, + HCI_RD_NB_SUPP_IAC_CMD_OPCODE = 0x0C38, + HCI_RD_CURR_IAC_LAP_CMD_OPCODE = 0x0C39, + HCI_WR_CURR_IAC_LAP_CMD_OPCODE = 0x0C3A, + HCI_SET_AFH_HOST_CH_CLASS_CMD_OPCODE = 0x0C3F, + HCI_RD_INQ_SCAN_TYPE_CMD_OPCODE = 0x0C42, + HCI_WR_INQ_SCAN_TYPE_CMD_OPCODE = 0x0C43, + HCI_RD_INQ_MODE_CMD_OPCODE = 0x0C44, + HCI_WR_INQ_MODE_CMD_OPCODE = 0x0C45, + HCI_RD_PAGE_SCAN_TYPE_CMD_OPCODE = 0x0C46, + HCI_WR_PAGE_SCAN_TYPE_CMD_OPCODE = 0x0C47, + HCI_RD_AFH_CH_ASSESS_MODE_CMD_OPCODE = 0x0C48, + HCI_WR_AFH_CH_ASSESS_MODE_CMD_OPCODE = 0x0C49, + HCI_RD_EXT_INQ_RSP_CMD_OPCODE = 0x0C51, + HCI_WR_EXT_INQ_RSP_CMD_OPCODE = 0x0C52, + HCI_REFRESH_ENC_KEY_CMD_OPCODE = 0x0C53, + HCI_RD_SP_MODE_CMD_OPCODE = 0x0C55, + HCI_WR_SP_MODE_CMD_OPCODE = 0x0C56, + HCI_RD_LOC_OOB_DATA_CMD_OPCODE = 0x0C57, + HCI_RD_INQ_RSP_TX_PWR_LVL_CMD_OPCODE = 0x0C58, + HCI_WR_INQ_TX_PWR_LVL_CMD_OPCODE = 0x0C59, + HCI_RD_DFT_ERR_DATA_REP_CMD_OPCODE = 0x0C5A, + HCI_WR_DFT_ERR_DATA_REP_CMD_OPCODE = 0x0C5B, + HCI_ENH_FLUSH_CMD_OPCODE = 0x0C5F, + HCI_SEND_KEYPRESS_NOTIF_CMD_OPCODE = 0x0C60, + HCI_SET_EVT_MASK_PAGE_2_CMD_OPCODE = 0x0C63, + HCI_RD_FLOW_CNTL_MODE_CMD_OPCODE = 0x0C66, + HCI_WR_FLOW_CNTL_MODE_CMD_OPCODE = 0x0C67, + HCI_RD_ENH_TX_PWR_LVL_CMD_OPCODE = 0x0C68, + HCI_RD_LE_HOST_SUPP_CMD_OPCODE = 0x0C6C, + HCI_WR_LE_HOST_SUPP_CMD_OPCODE = 0x0C6D, + HCI_SET_MWS_CHANNEL_PARAMS_CMD_OPCODE = 0x0C6E, + HCI_SET_EXTERNAL_FRAME_CONFIG_CMD_OPCODE = 0x0C6F, + HCI_SET_MWS_SIGNALING_CMD_OPCODE = 0x0C70, + HCI_SET_MWS_TRANSPORT_LAYER_CMD_OPCODE = 0x0C71, + HCI_SET_MWS_SCAN_FREQ_TABLE_CMD_OPCODE = 0x0C72, + HCI_SET_MWS_PATTERN_CONFIG_CMD_OPCODE = 0x0C73, + HCI_SET_RES_LT_ADDR_CMD_OPCODE = 0x0C74, + HCI_DEL_RES_LT_ADDR_CMD_OPCODE = 0x0C75, + HCI_SET_CON_SLV_BCST_DATA_CMD_OPCODE = 0x0C76, + HCI_RD_SYNC_TRAIN_PARAM_CMD_OPCODE = 0x0C77, + HCI_WR_SYNC_TRAIN_PARAM_CMD_OPCODE = 0x0C78, + HCI_RD_SEC_CON_HOST_SUPP_CMD_OPCODE = 0x0C79, + HCI_WR_SEC_CON_HOST_SUPP_CMD_OPCODE = 0x0C7A, + HCI_RD_AUTH_PAYL_TO_CMD_OPCODE = 0x0C7B, + HCI_WR_AUTH_PAYL_TO_CMD_OPCODE = 0x0C7C, + HCI_RD_LOC_OOB_EXT_DATA_CMD_OPCODE = 0x0C7D, + HCI_RD_EXT_PAGE_TO_CMD_OPCODE = 0x0C7E, + HCI_WR_EXT_PAGE_TO_CMD_OPCODE = 0x0C7F, + HCI_RD_EXT_INQ_LEN_CMD_OPCODE = 0x0C80, + HCI_WR_EXT_INQ_LEN_CMD_OPCODE = 0x0C81, + + //Info Params + HCI_RD_LOCAL_VER_INFO_CMD_OPCODE = 0x1001, + HCI_RD_LOCAL_SUPP_CMDS_CMD_OPCODE = 0x1002, + HCI_RD_LOCAL_SUPP_FEATS_CMD_OPCODE = 0x1003, + HCI_RD_LOCAL_EXT_FEATS_CMD_OPCODE = 0x1004, + HCI_RD_BUFF_SIZE_CMD_OPCODE = 0x1005, + HCI_RD_BD_ADDR_CMD_OPCODE = 0x1009, + HCI_RD_LOCAL_SUPP_CODECS_CMD_OPCODE = 0x100B, + HCI_RD_LOCAL_SP_OPT_CMD_OPCODE = 0x100C, + + //Status Params + HCI_RD_FAIL_CONTACT_CNT_CMD_OPCODE = 0x1401, + HCI_RST_FAIL_CONTACT_CNT_CMD_OPCODE = 0x1402, + HCI_RD_LINK_QUAL_CMD_OPCODE = 0x1403, + HCI_RD_RSSI_CMD_OPCODE = 0x1405, + HCI_RD_AFH_CH_MAP_CMD_OPCODE = 0x1406, + HCI_RD_CLK_CMD_OPCODE = 0x1407, + HCI_RD_ENC_KEY_SIZE_CMD_OPCODE = 0x1408, + HCI_GET_MWS_TRANSPORT_LAYER_CONFIG_CMD_OPCODE = 0x140C, + + //Testing Commands + HCI_RD_LOOPBACK_MODE_CMD_OPCODE = 0x1801, + HCI_WR_LOOPBACK_MODE_CMD_OPCODE = 0x1802, + HCI_EN_DUT_MODE_CMD_OPCODE = 0x1803, + HCI_WR_SP_DBG_MODE_CMD_OPCODE = 0x1804, + HCI_WR_SEC_CON_TEST_MODE_CMD_OPCODE = 0x180A, + + /// LE Commands Opcodes + HCI_LE_SET_EVT_MASK_CMD_OPCODE = 0x2001, + HCI_LE_RD_BUFF_SIZE_CMD_OPCODE = 0x2002, + HCI_LE_RD_LOCAL_SUPP_FEATS_CMD_OPCODE = 0x2003, + HCI_LE_SET_RAND_ADDR_CMD_OPCODE = 0x2005, + HCI_LE_SET_ADV_PARAM_CMD_OPCODE = 0x2006, + HCI_LE_RD_ADV_CHNL_TX_PW_CMD_OPCODE = 0x2007, + HCI_LE_SET_ADV_DATA_CMD_OPCODE = 0x2008, + HCI_LE_SET_SCAN_RSP_DATA_CMD_OPCODE = 0x2009, + HCI_LE_SET_ADV_EN_CMD_OPCODE = 0x200A, + HCI_LE_SET_SCAN_PARAM_CMD_OPCODE = 0x200B, + HCI_LE_SET_SCAN_EN_CMD_OPCODE = 0x200C, + HCI_LE_CREATE_CON_CMD_OPCODE = 0x200D, + HCI_LE_CREATE_CON_CANCEL_CMD_OPCODE = 0x200E, + HCI_LE_RD_WLST_SIZE_CMD_OPCODE = 0x200F, + HCI_LE_CLEAR_WLST_CMD_OPCODE = 0x2010, + HCI_LE_ADD_DEV_TO_WLST_CMD_OPCODE = 0x2011, + HCI_LE_RMV_DEV_FROM_WLST_CMD_OPCODE = 0x2012, + HCI_LE_CON_UPDATE_CMD_OPCODE = 0x2013, + HCI_LE_SET_HOST_CH_CLASS_CMD_OPCODE = 0x2014, + HCI_LE_RD_CHNL_MAP_CMD_OPCODE = 0x2015, + HCI_LE_RD_REM_FEATS_CMD_OPCODE = 0x2016, + HCI_LE_ENC_CMD_OPCODE = 0x2017, + HCI_LE_RAND_CMD_OPCODE = 0x2018, + HCI_LE_START_ENC_CMD_OPCODE = 0x2019, + HCI_LE_LTK_REQ_REPLY_CMD_OPCODE = 0x201A, + HCI_LE_LTK_REQ_NEG_REPLY_CMD_OPCODE = 0x201B, + HCI_LE_RD_SUPP_STATES_CMD_OPCODE = 0x201C, + HCI_LE_RX_TEST_V1_CMD_OPCODE = 0x201D, + HCI_LE_TX_TEST_V1_CMD_OPCODE = 0x201E, + HCI_LE_TEST_END_CMD_OPCODE = 0x201F, + HCI_LE_REM_CON_PARAM_REQ_REPLY_CMD_OPCODE = 0x2020, + HCI_LE_REM_CON_PARAM_REQ_NEG_REPLY_CMD_OPCODE = 0x2021, + HCI_LE_SET_DATA_LEN_CMD_OPCODE = 0x2022, + HCI_LE_RD_SUGGTED_DFT_DATA_LEN_CMD_OPCODE = 0x2023, + HCI_LE_WR_SUGGTED_DFT_DATA_LEN_CMD_OPCODE = 0x2024, + HCI_LE_RD_LOC_P256_PUB_KEY_CMD_OPCODE = 0x2025, + HCI_LE_GEN_DHKEY_V1_CMD_OPCODE = 0x2026, + HCI_LE_ADD_DEV_TO_RSLV_LIST_CMD_OPCODE = 0x2027, + HCI_LE_RMV_DEV_FROM_RSLV_LIST_CMD_OPCODE = 0x2028, + HCI_LE_CLEAR_RSLV_LIST_CMD_OPCODE = 0x2029, + HCI_LE_RD_RSLV_LIST_SIZE_CMD_OPCODE = 0x202A, + HCI_LE_RD_PEER_RSLV_ADDR_CMD_OPCODE = 0x202B, + HCI_LE_RD_LOC_RSLV_ADDR_CMD_OPCODE = 0x202C, + HCI_LE_SET_ADDR_RESOL_EN_CMD_OPCODE = 0x202D, + HCI_LE_SET_RSLV_PRIV_ADDR_TO_CMD_OPCODE = 0x202E, + HCI_LE_RD_MAX_DATA_LEN_CMD_OPCODE = 0x202F, + HCI_LE_RD_PHY_CMD_OPCODE = 0x2030, + HCI_LE_SET_DFT_PHY_CMD_OPCODE = 0x2031, + HCI_LE_SET_PHY_CMD_OPCODE = 0x2032, + HCI_LE_RX_TEST_V2_CMD_OPCODE = 0x2033, + HCI_LE_TX_TEST_V2_CMD_OPCODE = 0x2034, + HCI_LE_SET_ADV_SET_RAND_ADDR_CMD_OPCODE = 0x2035, + HCI_LE_SET_EXT_ADV_PARAM_CMD_OPCODE = 0x2036, + HCI_LE_SET_EXT_ADV_DATA_CMD_OPCODE = 0x2037, + HCI_LE_SET_EXT_SCAN_RSP_DATA_CMD_OPCODE = 0x2038, + HCI_LE_SET_EXT_ADV_EN_CMD_OPCODE = 0x2039, + HCI_LE_RD_MAX_ADV_DATA_LEN_CMD_OPCODE = 0x203A, + HCI_LE_RD_NB_SUPP_ADV_SETS_CMD_OPCODE = 0x203B, + HCI_LE_RMV_ADV_SET_CMD_OPCODE = 0x203C, + HCI_LE_CLEAR_ADV_SETS_CMD_OPCODE = 0x203D, + HCI_LE_SET_PER_ADV_PARAM_CMD_OPCODE = 0x203E, + HCI_LE_SET_PER_ADV_DATA_CMD_OPCODE = 0x203F, + HCI_LE_SET_PER_ADV_EN_CMD_OPCODE = 0x2040, + HCI_LE_SET_EXT_SCAN_PARAM_CMD_OPCODE = 0x2041, + HCI_LE_SET_EXT_SCAN_EN_CMD_OPCODE = 0x2042, + HCI_LE_EXT_CREATE_CON_CMD_OPCODE = 0x2043, + HCI_LE_PER_ADV_CREATE_SYNC_CMD_OPCODE = 0x2044, + HCI_LE_PER_ADV_CREATE_SYNC_CANCEL_CMD_OPCODE = 0x2045, + HCI_LE_PER_ADV_TERM_SYNC_CMD_OPCODE = 0x2046, + HCI_LE_ADD_DEV_TO_PER_ADV_LIST_CMD_OPCODE = 0x2047, + HCI_LE_RMV_DEV_FROM_PER_ADV_LIST_CMD_OPCODE = 0x2048, + HCI_LE_CLEAR_PER_ADV_LIST_CMD_OPCODE = 0x2049, + HCI_LE_RD_PER_ADV_LIST_SIZE_CMD_OPCODE = 0x204A, + HCI_LE_RD_TX_PWR_CMD_OPCODE = 0x204B, + HCI_LE_RD_RF_PATH_COMP_CMD_OPCODE = 0x204C, + HCI_LE_WR_RF_PATH_COMP_CMD_OPCODE = 0x204D, + HCI_LE_SET_PRIV_MODE_CMD_OPCODE = 0x204E, + HCI_LE_RX_TEST_V3_CMD_OPCODE = 0x204F, + HCI_LE_TX_TEST_V3_CMD_OPCODE = 0x2050, + HCI_LE_SET_CONLESS_CTE_TX_PARAM_CMD_OPCODE = 0x2051, + HCI_LE_SET_CONLESS_CTE_TX_EN_CMD_OPCODE = 0x2052, + HCI_LE_SET_CONLESS_IQ_SAMPL_EN_CMD_OPCODE = 0x2053, + HCI_LE_SET_CON_CTE_RX_PARAM_CMD_OPCODE = 0x2054, + HCI_LE_SET_CON_CTE_TX_PARAM_CMD_OPCODE = 0x2055, + HCI_LE_CON_CTE_REQ_EN_CMD_OPCODE = 0x2056, + HCI_LE_CON_CTE_RSP_EN_CMD_OPCODE = 0x2057, + HCI_LE_RD_ANTENNA_INF_CMD_OPCODE = 0x2058, + HCI_LE_SET_PER_ADV_REC_EN_CMD_OPCODE = 0x2059, + HCI_LE_PER_ADV_SYNC_TRANSF_CMD_OPCODE = 0x205A, + HCI_LE_PER_ADV_SET_INFO_TRANSF_CMD_OPCODE = 0x205B, + HCI_LE_SET_PER_ADV_SYNC_TRANSF_PARAM_CMD_OPCODE = 0x205C, + HCI_LE_SET_DFT_PER_ADV_SYNC_TRANSF_PARAM_CMD_OPCODE = 0x205D, + HCI_LE_GEN_DHKEY_V2_CMD_OPCODE = 0x205E, + HCI_LE_MOD_SLEEP_CLK_ACC_CMD_OPCODE = 0x205F, + + ///Debug commands - OGF = 0x3F (spec) + HCI_DBG_RD_MEM_CMD_OPCODE = 0xFC01, + HCI_DBG_WR_MEM_CMD_OPCODE = 0xFC02, + HCI_DBG_DEL_PAR_CMD_OPCODE = 0xFC03, + HCI_DBG_ID_FLASH_CMD_OPCODE = 0xFC05, + HCI_DBG_ER_FLASH_CMD_OPCODE = 0xFC06, + HCI_DBG_WR_FLASH_CMD_OPCODE = 0xFC07, + HCI_DBG_RD_FLASH_CMD_OPCODE = 0xFC08, + HCI_DBG_RD_PAR_CMD_OPCODE = 0xFC09, + HCI_DBG_WR_PAR_CMD_OPCODE = 0xFC0A, + HCI_DBG_WLAN_COEX_CMD_OPCODE = 0xFC0B, + HCI_DBG_WLAN_COEXTST_SCEN_CMD_OPCODE = 0xFC0D, + HCI_DBG_BT_SEND_LMP_CMD_OPCODE = 0xFC0E, + HCI_DBG_SET_LOCAL_CLOCK_CMD_OPCODE = 0xFC0F, + HCI_DBG_RD_KERNEL_STATS_CMD_OPCODE = 0xFC10, + HCI_DBG_PLF_RESET_CMD_OPCODE = 0xFC11, + HCI_DBG_RD_MEM_INFO_CMD_OPCODE = 0xFC12, + HCI_VS_SET_PREF_SLAVE_LATENCY_CMD_OPCODE = 0xFC13, + HCI_VS_SET_PREF_SLAVE_EVT_DUR_CMD_OPCODE = 0xFC14, + HCI_DBG_BLE_REG_RD_CMD_OPCODE = 0xFC30, + HCI_DBG_BLE_REG_WR_CMD_OPCODE = 0xFC31, + HCI_DBG_LLCP_DISCARD_CMD_OPCODE = 0xFC36, + HCI_DBG_RF_REG_RD_CMD_OPCODE = 0xFC39, + HCI_DBG_RF_REG_WR_CMD_OPCODE = 0xFC3A, + HCI_DBG_RF_SWITCH_CLK_CMD_OPCODE = 0xFC3C, + HCI_DBG_RF_WR_DATA_TX_CMD_OPCODE = 0xFC3D, + HCI_DBG_RF_RD_DATA_RX_CMD_OPCODE = 0xFC3E, + HCI_DBG_RF_CNTL_TX_CMD_OPCODE = 0xFC3F, + HCI_DBG_RF_SYNC_P_CNTL_CMD_OPCODE = 0xFC40, + + #if (RW_DEBUG && BT_EMB_PRESENT) + HCI_DBG_BT_DISCARD_LMP_EN_CMD_OPCODE = 0xFC44, + #endif //RW_DEBUG && BT_EMB_PRESENT + + HCI_DBG_MWS_COEX_CMD_OPCODE = 0xFC45, + HCI_DBG_MWS_COEXTST_SCEN_CMD_OPCODE = 0xFC46, + #if (BT_READ_PICONET_CLOCK) + HCI_VS_RD_PICONET_CLOCK_CMD_OPCODE = 0xFC50, + #endif // (BT_READ_PICONET_CLOCK) + + #if (BLE_ISO_MODE_0) + /// Vendor Specific commands for ISO Mode 0 + HCI_VS_SETUP_AM0_CHAN_CMD_OPCODE = 0xFC54, + HCI_VS_REMOVE_AM0_CHAN_CMD_OPCODE = 0xFC55, + HCI_VS_CONTROL_AM0_CHAN_CMD_OPCODE = 0xFC56, + #endif // (BLE_ISO_MODE_0) + + #if CRYPTO_UT + HCI_DBG_TEST_CRYPTO_FUNC_CMD_OPCODE = 0xFC60, + #endif //CRYPTO_UT + + #if RW_DEBUG + HCI_DBG_TEST_SCH_PLAN_SET_CMD_OPCODE = 0xFC61, + HCI_DBG_TEST_SCH_PLAN_REM_CMD_OPCODE = 0xFC62, + HCI_DBG_TEST_SCH_PLAN_CHK_CMD_OPCODE = 0xFC63, + HCI_DBG_TEST_SCH_PLAN_REQ_CMD_OPCODE = 0xFC64, + #endif //RW_DEBUG + + #if BLE_IQ_GEN + HCI_DBG_IQGEN_CFG_CMD_OPCODE = 0xFC65, + #endif //BLE_IQ_GEN +}; + +/************************************************************************************** + ************** HCI EVENTS **************** + **************************************************************************************/ + +///Event Codes +/*@TRACE*/ +enum hci_evt_code +{ + HCI_INQ_CMP_EVT_CODE = 0x01, + HCI_INQ_RES_EVT_CODE = 0x02, + HCI_CON_CMP_EVT_CODE = 0x03, + HCI_CON_REQ_EVT_CODE = 0x04, + HCI_DISC_CMP_EVT_CODE = 0x05, + HCI_AUTH_CMP_EVT_CODE = 0x06, + HCI_REM_NAME_REQ_CMP_EVT_CODE = 0x07, + HCI_ENC_CHG_EVT_CODE = 0x08, + HCI_CHG_CON_LK_CMP_EVT_CODE = 0x09, + HCI_MASTER_LK_CMP_EVT_CODE = 0x0A, + HCI_RD_REM_SUPP_FEATS_CMP_EVT_CODE = 0x0B, + HCI_RD_REM_VER_INFO_CMP_EVT_CODE = 0x0C, + HCI_QOS_SETUP_CMP_EVT_CODE = 0x0D, + HCI_CMD_CMP_EVT_CODE = 0x0E, + HCI_CMD_STATUS_EVT_CODE = 0x0F, + HCI_HW_ERR_EVT_CODE = 0x10, + HCI_FLUSH_OCCURRED_EVT_CODE = 0x11, + HCI_ROLE_CHG_EVT_CODE = 0x12, + HCI_NB_CMP_PKTS_EVT_CODE = 0x13, + HCI_MODE_CHG_EVT_CODE = 0x14, + HCI_RETURN_LINK_KEYS_EVT_CODE = 0x15, + HCI_PIN_CODE_REQ_EVT_CODE = 0x16, + HCI_LK_REQ_EVT_CODE = 0x17, + HCI_LK_NOTIF_EVT_CODE = 0x18, + HCI_DATA_BUF_OVFLW_EVT_CODE = 0x1A, + HCI_MAX_SLOT_CHG_EVT_CODE = 0x1B, + HCI_RD_CLK_OFF_CMP_EVT_CODE = 0x1C, + HCI_CON_PKT_TYPE_CHG_EVT_CODE = 0x1D, + HCI_QOS_VIOL_EVT_CODE = 0x1E, + HCI_PAGE_SCAN_REPET_MODE_CHG_EVT_CODE = 0x20, + HCI_FLOW_SPEC_CMP_EVT_CODE = 0x21, + HCI_INQ_RES_WITH_RSSI_EVT_CODE = 0x22, + HCI_RD_REM_EXT_FEATS_CMP_EVT_CODE = 0x23, + HCI_SYNC_CON_CMP_EVT_CODE = 0x2C, + HCI_SYNC_CON_CHG_EVT_CODE = 0x2D, + HCI_SNIFF_SUB_EVT_CODE = 0x2E, + HCI_EXT_INQ_RES_EVT_CODE = 0x2F, + HCI_ENC_KEY_REFRESH_CMP_EVT_CODE = 0x30, + HCI_IO_CAP_REQ_EVT_CODE = 0x31, + HCI_IO_CAP_RSP_EVT_CODE = 0x32, + HCI_USER_CFM_REQ_EVT_CODE = 0x33, + HCI_USER_PASSKEY_REQ_EVT_CODE = 0x34, + HCI_REM_OOB_DATA_REQ_EVT_CODE = 0x35, + HCI_SP_CMP_EVT_CODE = 0x36, + HCI_LINK_SUPV_TO_CHG_EVT_CODE = 0x38, + HCI_ENH_FLUSH_CMP_EVT_CODE = 0x39, + HCI_USER_PASSKEY_NOTIF_EVT_CODE = 0x3B, + HCI_KEYPRESS_NOTIF_EVT_CODE = 0x3C, + HCI_REM_HOST_SUPP_FEATS_NOTIF_EVT_CODE = 0x3D, + HCI_LE_META_EVT_CODE = 0x3E, + HCI_MAX_EVT_MSK_PAGE_1_CODE = 0x40, + HCI_SYNC_TRAIN_CMP_EVT_CODE = 0x4F, + HCI_SYNC_TRAIN_REC_EVT_CODE = 0x50, + HCI_CON_SLV_BCST_REC_EVT_CODE = 0x51, + HCI_CON_SLV_BCST_TO_EVT_CODE = 0x52, + HCI_TRUNC_PAGE_CMP_EVT_CODE = 0x53, + HCI_SLV_PAGE_RSP_TO_EVT_CODE = 0x54, + HCI_CON_SLV_BCST_CH_MAP_CHG_EVT_CODE = 0x55, + HCI_AUTH_PAYL_TO_EXP_EVT_CODE = 0x57, + HCI_SAM_STATUS_CHANGE_EVT_CODE = 0x58, + HCI_MAX_EVT_MSK_PAGE_2_CODE = 0x59, + HCI_DBG_META_EVT_CODE = 0xFF, +}; + +/*@TRACE*/ +enum hci_le_evt_subcode +{ + /// LE Events Subcodes + HCI_LE_CON_CMP_EVT_SUBCODE = 0x01, + HCI_LE_ADV_REPORT_EVT_SUBCODE = 0x02, + HCI_LE_CON_UPDATE_CMP_EVT_SUBCODE = 0x03, + HCI_LE_RD_REM_FEATS_CMP_EVT_SUBCODE = 0x04, + HCI_LE_LTK_REQUEST_EVT_SUBCODE = 0x05, + HCI_LE_REM_CON_PARAM_REQ_EVT_SUBCODE = 0x06, + HCI_LE_DATA_LEN_CHG_EVT_SUBCODE = 0x07, + HCI_LE_RD_LOC_P256_PUB_KEY_CMP_EVT_SUBCODE = 0x08, + HCI_LE_GEN_DHKEY_CMP_EVT_SUBCODE = 0x09, + HCI_LE_ENH_CON_CMP_EVT_SUBCODE = 0x0A, + HCI_LE_DIR_ADV_REP_EVT_SUBCODE = 0x0B, + HCI_LE_PHY_UPD_CMP_EVT_SUBCODE = 0x0C, + HCI_LE_EXT_ADV_REPORT_EVT_SUBCODE = 0x0D, + HCI_LE_PER_ADV_SYNC_EST_EVT_SUBCODE = 0x0E, + HCI_LE_PER_ADV_REPORT_EVT_SUBCODE = 0x0F, + HCI_LE_PER_ADV_SYNC_LOST_EVT_SUBCODE = 0x10, + HCI_LE_SCAN_TIMEOUT_EVT_SUBCODE = 0x11, + HCI_LE_ADV_SET_TERMINATED_EVT_SUBCODE = 0x12, + HCI_LE_SCAN_REQ_RCVD_EVT_SUBCODE = 0x13, + HCI_LE_CH_SEL_ALGO_EVT_SUBCODE = 0x14, + HCI_LE_CONLESS_IQ_REPORT_EVT_SUBCODE = 0x15, + HCI_LE_CON_IQ_REPORT_EVT_SUBCODE = 0x16, + HCI_LE_CTE_REQ_FAILED_EVT_SUBCODE = 0x17, + HCI_LE_PER_ADV_SYNC_TRANSF_REC_EVT_SUBCODE = 0x18, +}; + +#if (RW_DEBUG || BLE_ISOGEN) +/*@TRACE*/ +enum hci_vs_evt_subcode +{ + #if (RW_DEBUG) + /// DBG Events Subcodes + HCI_DBG_ASSERT_EVT_SUBCODE = 0x02, + #endif //(RW_DEBUG) + + #if (BLE_ISOGEN) + /// VS ISO Gen Statistics Status + HCI_VS_ISOGEN_STAT_EVT_SUBCODE = 0x03, + #endif // (BLE_ISOGEN) +}; +#endif //(RW_DEBUG || BLE_ISOGEN) + +/// Event mask page enum +enum hci_evt_mask_page +{ + /// page 0 + HCI_PAGE_0, + /// page 1 + HCI_PAGE_1, + /// page 2 + HCI_PAGE_2, + /// Default + HCI_PAGE_DFT, + /// LE event + HCI_PAGE_LE, +}; + +#if (BLE_ISO_PRESENT) +#if (BLE_ISO_MODE_0) +/// Current audio mode +enum iso_am0_ctrl +{ + // Stop Audio Mode 0 Stream + ISO_AM0_CRL_DISABLE, + // Start Audio Mode 0 Stream + ISO_AM0_CRL_ENABLE, +}; +#endif // (BLE_ISO_MODE_0) + + +/// Isochronous Channel Direction selection +enum iso_rx_tx_select +{ + /// Isochronous tx buffer selection: Host to Controller + ISO_TX_SEL, + /// Isochronous rx buffer selection: Controller to Host + ISO_RX_SEL +}; + +/// Isochronous Channel data path selection +enum iso_dp_type +{ + /// Data Path direction is disabled + ISO_DP_DISABLE = 0x00, + /// Voice over HCI Data Path + ISO_DP_VOHCI = 0x01, + + // -------- VENDOR SPECIFIC --------- // + + /// ISO over HCI Data Path + ISO_DP_ISOOHCI = 0xF0, + /// PCM Data path + ISO_DP_PCM = 0xF1, + /// ISO Payload Generator + ISO_DP_ISOGEN = 0xF2, +}; + +#endif // (BLE_ISO_PRESENT) + + + +/************************************************************************************** + ************** HCI MESSAGE STRUCTURES **************** + **************************************************************************************/ +#if (!CFG_USE_BK_HOST) +#pragma pack(push, 1) +#endif +/// HCI ACL data packet structure +/*@TRACE*/ +struct hci_acl_data +{ + /// bits[00:11]: Connection handle + /// bits[12:13]: Packet boundary flag + /// bits[14:15]: Broadcast flag + uint16_t conhdl_pb_bc_flag; + /// length of the data + uint16_t length; + /// Memory Pointer address + uint32_t buf_ptr; +}; + +/// HCI Synchronous data packet structure +/*@TRACE*/ +struct hci_sync_data +{ + /// bits[00:11]: Connection handle + /// bits[12:13]: Packet status flag + uint16_t conhdl_psf; + /// length of the data + uint8_t length; + /// EM buffer pointer + uint16_t buf_ptr; +}; + + +/* + * HCI COMMANDS PARAMETERS (to classify) + **************************************************************************************** + */ + +/// HCI basic command structure with connection handle +/*@TRACE + * hci_rd_rssi_cmd = hci_basic_conhdl_cmd + * hci_le_rd_chnl_map_cmd = hci_basic_conhdl_cmd + * hci_le_ltk_req_neg_reply_cmd = hci_basic_conhdl_cmd*/ +struct hci_basic_conhdl_cmd +{ + /// connection handle + uint16_t conhdl; +}; + +/// HCI basic command structure with BD address +struct hci_basic_bd_addr_cmd +{ + ///BdAddr + struct bd_addr bd_addr; +}; + +/// HCI Accept connection request command structure +/*@TRACE*/ +struct hci_accept_con_req_cmd +{ + ///BdAddr + struct bd_addr bd_addr; + ///Page Scan Repetition Mode + uint8_t role; +}; + +/// HCI Accept synchronous connection request command structure +/*@TRACE*/ +struct hci_accept_sync_con_req_cmd +{ + ///BdAddr + struct bd_addr bd_addr; + ///Transmit bandwidth + uint32_t tx_bw; + ///Receive bandwidth + uint32_t rx_bw; + ///Max latency + uint16_t max_lat; + ///Voice settings + uint16_t vx_set; + ///Retransmission effort + uint8_t retx_eff; + ///Packet type + uint16_t pkt_type ; +}; + +/// HCI Enhanced Accept synchronous connection request command structure +/*@TRACE*/ +struct hci_enh_accept_sync_con_cmd +{ + + struct bd_addr bd_addr; // BD address + uint32_t tx_bw; // Transmit Bandwidth (in B/sec) + uint32_t rx_bw; // Receive Bandwidth (in B/sec) + uint8_t tx_cod_fmt[5]; // Transmit Coding Format + uint8_t rx_cod_fmt[5]; // Receive Coding Format + uint16_t tx_cod_fr_sz; // Transmit Codec Frame Size (in B) + uint16_t rx_cod_fr_sz; // Receive Codec Frame Size (in B) + uint32_t in_bw; // Input Bandwidth (in B/sec) + uint32_t out_bw; // Output Bandwidth (in B/sec) + uint8_t in_cod_fmt[5]; // Input Coding Format + uint8_t out_cod_fmt[5]; // Output Coding Format + uint16_t in_cod_data_sz; // Input Coded Data Size (in bits) + uint16_t out_cod_data_sz; // Output Coded Data Size (in bits) + uint8_t in_data_fmt; // Input PCM Data Format + uint8_t out_data_fmt; // Output PCM Data Format + uint8_t in_msb_pos; // Input PCM Sample Payload MSB Position (in bits) + uint8_t out_msb_pos; // Output PCM Sample Payload MSB Position (in bits) + uint8_t in_data_path; // Input Data Path + uint8_t out_data_path; // Output Data Path + uint8_t in_tr_unit_sz; // Input Transport Unit Size (in bits) + uint8_t out_tr_unit_sz; // Output Transport Unit Size (in bits) + uint16_t max_lat; // Max Latency (in ms) + uint16_t packet_type; // Packet Type + uint8_t retx_eff; // Retransmission Effort + + +}; + +/// HCI reject connection request command structure +/*@TRACE*/ +struct hci_reject_con_req_cmd +{ + ///BdAddr + struct bd_addr bd_addr; + ///Reason + uint8_t reason; +}; + +/// HCI reject synchronous connection request command structure +/*@TRACE*/ +struct hci_reject_sync_con_req_cmd +{ + ///BdAddr + struct bd_addr bd_addr; + ///Reason + uint8_t reason; +}; + +/// HCI link key request reply command structure +/*@TRACE*/ +struct hci_lk_req_reply_cmd +{ + ///BdAddr + struct bd_addr bd_addr; + ///Key + struct ltk key; +}; + +/// HCI link key request reply command structure +/*@TRACE*/ +struct hci_pin_code_req_reply_cmd +{ + ///BdAddr + struct bd_addr bd_addr; + ///Pin code length + uint8_t pin_len; + ///Key + struct pin_code pin; +}; + +/// HCI switch role command structure +/*@TRACE*/ +struct hci_switch_role_cmd +{ + ///BdAddr + struct bd_addr bd_addr; + ///Read all flag + uint8_t role; +}; + +/// HCI flow specification command parameters structure +/*@TRACE*/ +struct hci_flow_spec_cmd +{ + ///Connection handle + uint16_t conhdl; + ///Flags + uint8_t flags; + ///Flow direction + uint8_t flow_dir; + ///Service type + uint8_t serv_type; + ///Token rate + uint32_t tk_rate; + ///Token buffer size + uint32_t tk_buf_sz; + ///Peak bandwidth + uint32_t pk_bw; + ///Access latency + uint32_t acc_lat; +}; + +/// HCI enhanced flush command parameters structure +/*@TRACE*/ +struct hci_enh_flush_cmd +{ + ///Connection handle + uint16_t conhdl; + ///Packet Type + uint8_t pkt_type; +}; + +/// HCI command complete event structure for the read auto flush TO command +struct hci_rd_auto_flush_to_cmd_cmp_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///Flush timeout + uint16_t flush_to; +}; + +/// HCI write flush timeout command parameters structure +/*@TRACE*/ +struct hci_wr_auto_flush_to_cmd +{ + ///Connection handle + uint16_t conhdl; + ///Flush timeout + uint16_t flush_to; +}; + +/// HCI change connection packet type command parameters structure +/*@TRACE*/ +struct hci_chg_con_pkt_type_cmd +{ + ///Connection handle + uint16_t conhdl; + ///Packet type + uint16_t pkt_type; +}; + +/// HCI read link policy settings command parameters structure +/*@TRACE*/ +struct hci_rd_link_pol_stg_cmd_cmp_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///Link policy + uint16_t lnk_policy; +}; + +/// HCI read link policy settings command parameters structure +/*@TRACE*/ +struct hci_wr_link_pol_stg_cmd +{ + ///Connection handle + uint16_t conhdl; + ///Link policy + uint16_t lnk_policy; +}; + +/// HCI sniff mode request command parameters structure +/*@TRACE*/ +struct hci_sniff_mode_cmd +{ + ///Connection handle + uint16_t conhdl; + /// Maximum interval (in slots) + uint16_t max_int; + /// Minimum interval (in slots) + uint16_t min_int; + /// Attempts (number of receive slots) (in slots) + uint16_t attempt; + /// Timeout (number of receive slots) (in slots) + uint16_t timeout; +}; + +/// HCI sniff subrating mode request command parameters structure +/*@TRACE*/ +struct hci_sniff_sub_cmd +{ + ///Connection handle + uint16_t conhdl; + /// Maximum latency used to calculate the maximum sniff subrate that the remote device may use (in slots) + uint16_t max_lat; + /// Minimum base sniff subrate timeout that the remote device may use (in slots) + uint16_t min_rem_to; + /// Minimum base sniff subrate timeout that the local device may use (in slots) + uint16_t min_loc_to; +}; + +/// HCI role discovery complete event parameters structure +/*@TRACE*/ +struct hci_role_discovery_cmd_cmp_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///Role + uint8_t role; + +}; + +/// HCI read failed contact counter command parameters structure +/*@TRACE*/ +struct hci_rd_fail_contact_cnt_cmd_cmp_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///Fail contact counter + uint16_t fail_cnt; +}; + +/// HCI read link quality complete event parameters structure +/*@TRACE*/ +struct hci_rd_link_qual_cmd_cmp_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///Quality type + uint8_t quality; +}; + +/// HCI read afh channel map complete event parameters structure +/*@TRACE*/ +struct hci_rd_afh_ch_map_cmd_cmp_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + /// AFH mode + uint8_t afh_mode; + /// AFH channel map + struct chnl_map afh_map; +}; + +/// HCI read lmp handle complete event parameters structure +/*@TRACE*/ +struct hci_rd_lmp_hdl_cmd_cmp_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///lmp handle + uint8_t lmp_hdl; + ///rsvd + uint32_t rsvd; +}; + +/// HCI read remote extended features command parameters structure +/*@TRACE*/ +struct hci_rd_rem_ext_feats_cmd +{ + ///Connection handle + uint16_t conhdl; + ///page number + uint8_t pg_nb; +}; + +/// HCI read encryption key size complete event parameters structure +/*@TRACE*/ +struct hci_rd_enc_key_size_cmd_cmp_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///Key size + uint8_t key_sz; +}; + +/// HCI read enhanced transmit power command parameters structure +/*@TRACE*/ +struct hci_rd_enh_tx_pwr_lvl_cmd +{ + ///Connection handle + uint16_t conhdl; + ///Type + uint8_t type; +}; + +/// HCI read enhanced transmit power complete event parameters structure +/*@TRACE*/ +struct hci_rd_enh_tx_pwr_lvl_cmd_cmp_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///Transmit power GFSK + uint8_t pw_gfsk; + ///Transmit power DQPSK + uint8_t pw_dqpsk; + ///Transmit power 8DPSK + uint8_t pw_8dpsk; +}; + + +/* + * HCI LINK CONTROL COMMANDS PARAMETERS + **************************************************************************************** + */ + +/// Format of the message of the Group: LINK_CONTROL_COMMANDS +/// HCI Inquiry command parameters structure +/*@TRACE*/ +struct hci_inq_cmd +{ + ///Lap + struct lap lap; + ///Inquiry Length in units of 1.28 s + uint8_t inq_len; + ///Number of response + uint8_t nb_rsp; +}; +/*@TRACE*/ +struct hci_per_inq_mode_cmd +{ + ///Maximum period length + uint16_t max_per_len; + ///Minimum period length + uint16_t min_per_len; + ///lap + struct lap lap; + ///Inquiry length in units of 1.28 s + uint8_t inq_len; + ///Number of response + uint8_t nb_rsp; +}; +/*@TRACE*/ +struct hci_create_con_cmd +{ + /// BdAddr + struct bd_addr bd_addr; + /// Packet Type + uint16_t pkt_type; + /// Page Scan Repetition Mode + uint8_t page_scan_rep_mode; + /// Reserved + uint8_t rsvd; + /** + * Clock Offset + * + * Bits 14-0 : Bits 16-2 of CLKNslave-CLK + * Bit 15 : Clock_Offset_Valid_Flag + * Invalid Clock Offset = 0 + * Valid Clock Offset = 1 + */ + uint16_t clk_off; + /// Allow Switch + uint8_t switch_en; +}; + +/// HCI disconnect command structure +/*@TRACE*/ +struct hci_disconnect_cmd +{ + /// connection handle + uint16_t conhdl; + /// reason + uint8_t reason; +}; + +/// HCI master link key command structure +/*@TRACE*/ +struct hci_master_lk_cmd +{ + ///Key flag + uint8_t key_flag; +}; + +/// HCI authentication request command parameters structure +/*@TRACE*/ +struct hci_set_con_enc_cmd +{ + ///Connection handle + uint16_t conhdl; + ///Encryption mode + uint8_t enc_en; +}; + +/*@TRACE*/ +struct hci_rem_name_req_cmd +{ + ///BdAddr + struct bd_addr bd_addr; + ///Page Scan Repetition Mode + uint8_t page_scan_rep_mode; + ///Reserved + uint8_t rsvd; + /** + * Clock Offset + * + * Bits 14-0 : Bits 16-2 of CLKNslave-CLK + * Bit 15 : Clock_Offset_Valid_Flag + * Invalid Clock Offset = 0 + * Valid Clock Offset = 1 + */ + uint16_t clk_off; +}; + +/// HCI remote name request complete event structure +/*@TRACE*/ +struct hci_rem_name_req_cmp_evt +{ + /// Status + uint8_t status; + /// BD Addr + struct bd_addr bd_addr; + /// Name + struct device_name name; +}; + +/// HCI setup synchronous connection command structure +/*@TRACE*/ +struct hci_setup_sync_con_cmd +{ + ///Connection handle + uint16_t conhdl; + ///Transmit bandwidth + uint32_t tx_bw; + ///Receive bandwidth + uint32_t rx_bw; + ///Max latency + uint16_t max_lat; + ///Voice setting + uint16_t vx_set; + ///Retransmission effort + uint8_t retx_eff; + ///Packet type + uint16_t pkt_type; +}; + +/// HCI setup synchronous connection command structure +/*@TRACE*/ +struct hci_enh_setup_sync_con_cmd +{ + uint16_t conhdl; // Connection Handle + uint32_t tx_bw; // Transmit Bandwidth (in B/sec) + uint32_t rx_bw; // Receive Bandwidth (in B/sec) + uint8_t tx_cod_fmt[5]; // Transmit Coding Format + uint8_t rx_cod_fmt[5]; // Receive Coding Format + uint16_t tx_cod_fr_sz; // Transmit Codec Frame Size (in B) + uint16_t rx_cod_fr_sz; // Receive Codec Frame Size (in B) + uint32_t in_bw; // Input Bandwidth (in B/sec) + uint32_t out_bw; // Output Bandwidth (in B/sec) + uint8_t in_cod_fmt[5]; // Input Coding Format + uint8_t out_cod_fmt[5]; // Output Coding Format + uint16_t in_cod_data_sz; // Input Coded Data Size (in bits) + uint16_t out_cod_data_sz; // Output Coded Data Size (in bits) + uint8_t in_data_fmt; // Input PCM Data Format + uint8_t out_data_fmt; // Output PCM Data Format + uint8_t in_msb_pos; // Input PCM Sample Payload MSB Position (in bits) + uint8_t out_msb_pos; // Output PCM Sample Payload MSB Position (in bits) + uint8_t in_data_path; // Input Data Path + uint8_t out_data_path; // Output Data Path + uint8_t in_tr_unit_sz; // Input Transport Unit Size (in bits) + uint8_t out_tr_unit_sz; // Output Transport Unit Size (in bits) + uint16_t max_lat; // Max Latency (in ms) + uint16_t packet_type; // Packet Type + uint8_t retx_eff; // Retransmission Effort +}; + +/// HCI io capability request reply command structure +/*@TRACE*/ +struct hci_io_cap_req_reply_cmd +{ + ///BdAddr + struct bd_addr bd_addr; + ///IO capability + uint8_t io_capa; + ///OOB data present + uint8_t oob_data_pres; + ///Authentication requirements + uint8_t auth_req; + +}; + +/// HCI io capability request negative reply command structure +/*@TRACE*/ +struct hci_io_cap_req_neg_reply_cmd +{ + ///BdAddr + struct bd_addr bd_addr; + ///Reason + uint8_t reason; +}; + +/// HCI user pass key request reply command structure +/*@TRACE*/ +struct hci_user_passkey_req_reply_cmd +{ + ///BdAddr + struct bd_addr bd_addr; + ///Numeric value + uint32_t num_val; +}; + +/// HCI remote oob data request reply command structure +/*@TRACE*/ +struct hci_rem_oob_data_req_reply_cmd +{ + ///BdAddr + struct bd_addr bd_addr; + ///hash part + struct hash oob_c; + ///random part + struct randomizer oob_r; +}; + +/// HCI send key press notification command structure +/*@TRACE*/ +struct hci_send_keypress_notif_cmd +{ + ///BdAddr + struct bd_addr bd_addr; + ///Notification type + uint8_t notif_type; +}; + +/// HCI truncated page command structure +/*@TRACE*/ +struct hci_trunc_page_cmd +{ + ///BdAddr + struct bd_addr bd_addr; + /// Page Scan Repetition Mode + uint8_t page_scan_rep_mode; + /** + * Clock Offset + * + * Bits 14-0 : Bits 16-2 of CLKNslave-CLK + * Bit 15 : Clock_Offset_Valid_Flag + * Invalid Clock Offset = 0 + * Valid Clock Offset = 1 + */ + uint16_t clk_off; +}; + +/// HCI truncated page cancel command structure +/*@TRACE*/ +struct hci_trunc_page_can_cmd +{ + ///BdAddr + struct bd_addr bd_addr; +}; + +/// HCI set connectionless slave broadcast command structure +/*@TRACE*/ +struct hci_set_con_slv_bcst_cmd +{ + /// Enable + uint8_t enable; + /// LT_ADDR + uint8_t lt_addr; + /// LPO_Allowed + uint8_t lpo_allowed; + /// Packet_Type + uint16_t packet_type; + /// Interval_Min (in slots) + uint16_t interval_min; + /// Interval_Max (in slots) + uint16_t interval_max; + /// CSB_supervisionTO (in slots) + uint16_t csb_supv_to; +}; + +/// HCI set connectionless slave broadcast command complete event structure +/*@TRACE*/ +struct hci_set_con_slv_bcst_cmd_cmp_evt +{ + /// Status + uint8_t status; + /// LT_ADDR + uint8_t lt_addr; + /// Interval (in slots) + uint16_t interval; +}; + +/// HCI set connectionless slave broadcast receive command structure +/*@TRACE*/ +struct hci_set_con_slv_bcst_rec_cmd +{ + /// Enable + uint8_t enable; + /// BD_ADDR + struct bd_addr bd_addr; + /// LT_ADDR + uint8_t lt_addr; + /// Interval (in slots) + uint16_t interval; + /// Clock_Offset (28 bits) - (CLKNslave - CLK) modulo 2^28 + uint32_t clock_offset; + /// Next_Connectionless_Slave_Broadcast_Clock (28 bits) + uint32_t next_csb_clock; + /// CSB_supervisionTO (in slots) + uint16_t csb_supv_to; + /// Remote_Timing_Accuracy (in ppm) + uint8_t remote_timing_accuracy; + /// Skip + uint8_t skip; + /// Packet_Type + uint16_t packet_type; + /// AFH_Channel_Map + struct chnl_map afh_ch_map; +}; + +/// HCI set connectionless slave broadcast receive command complete event structure +/*@TRACE*/ +struct hci_set_con_slv_bcst_rec_cmd_cmp_evt +{ + /// Status + uint8_t status; + /// BD_ADDR + struct bd_addr bd_addr; + /// LT_ADDR + uint8_t lt_addr; +}; + +/// HCI Receive Synchronization Train command structure +/*@TRACE*/ +struct hci_rec_sync_train_cmd +{ + /// BD_ADDR + struct bd_addr bd_addr; + /// Synchronization_scanTO (in slots) + uint16_t sync_scan_to; + /// Sync_Scan_Window (in slots) + uint16_t sync_scan_win; + /// Sync_Scan_Interval (in slots) + uint16_t sync_scan_int; +}; + +/// HCI remote oob extended data request reply command structure +/*@TRACE*/ +struct hci_rem_oob_ext_data_req_reply_cmd +{ + ///BdAddr + struct bd_addr bd_addr; + ///hash part + struct hash oob_c_192; + ///random part + struct randomizer oob_r_192; + ///hash part + struct hash oob_c_256; + ///random part + struct randomizer oob_r_256; +}; + +/*@TRACE*/ +struct hci_le_gen_dhkey_v1_cmd +{ + /// Remote P-256 public key + uint8_t public_key[64]; +}; + +/*@TRACE*/ +struct hci_le_gen_dhkey_v2_cmd +{ + /// Remote P-256 public key + uint8_t public_key[64]; + + /// Private key type (@see enum priv_key_type) + uint8_t key_type; +}; + +/*@TRACE*/ +struct hci_le_mod_sleep_clk_acc_cmd +{ + /// Switch to more or less accurate clock (@see enum clk_acc_action) + uint8_t action; +}; + + +/* + * HCI LINK POLICY COMMANDS PARAMETERS + **************************************************************************************** + */ + +/// HCI setup quality of service command structure +/*@TRACE*/ +struct hci_qos_setup_cmd +{ + ///Connection handle + uint16_t conhdl; + ///Flags + uint8_t flags; + ///Service type + uint8_t serv_type; + ///Token rate + uint32_t tok_rate; + ///Peak bandwidth + uint32_t pk_bw; + ///Latency + uint32_t lat; + ///Delay variation + uint32_t del_var; +}; + +/// HCI command complete event structure for read default link policy command structure +/*@TRACE*/ +struct hci_rd_dft_link_pol_stg_cmd_cmp_evt +{ + ///Status of the command reception + uint8_t status; + ///Link policy + uint16_t link_pol_stg; +}; + +/*@TRACE*/ +struct hci_wr_dft_link_pol_stg_cmd +{ + ///Link policy + uint16_t link_pol_stg; +}; + +/* + * HCI CONTROL & BASEBAND COMMANDS PARAMETERS + **************************************************************************************** + */ + +/// HCI set event mask command structure +/*@TRACE*/ +struct hci_set_evt_mask_cmd +{ + ///Event Mask + struct evt_mask event_mask; +}; + +/// HCI set event filter command structure +/*@TRACE*/ +struct hci_set_evt_filter_cmd +{ + /// Filter type + uint8_t filter_type; + + /// Filters + union hci_filter + { + uint8_t clear_all_filter_reserved; + + /// Inquiry Result Filter + struct inq_res_filter + { + /// Filter Condition type + uint8_t cond_type; + + /// Filter conditions + union hci_inq_filter_cond + { + /// Reserved value (Inquiry Result Filter - condition type 0x00 has no condition) + uint8_t cond_0_reserved; + + /// Inquiry Result Filter Condition - condition type 0x01 + struct inq_res_filter_cond_1 + { + /// Class_of_Device + struct devclass class_of_dev; + /// Class_of_Device_Mask + struct devclass class_of_dev_msk; + } cond_1; + + /// Inquiry Result Filter Condition - condition type 0x02 + struct inq_res_filter_cond_2 + { + /// BD Address + struct bd_addr bd_addr; + } cond_2; + } cond; + } inq_res; + + /// Connection Setup Filter + struct con_set_filter + { + /// Filter Condition type + uint8_t cond_type; + + /// Filter conditions + union hci_con_filter_cond + { + /// Connection Setup Filter Condition - condition type 0x00 + struct con_set_filter_cond_0 + { + /// Auto_Accept_Flag + uint8_t auto_accept; + } cond_0; + + /// Connection Setup Filter Condition - condition type 0x01 + struct con_set_filter_cond_1 + { + /// Class_of_Device + struct devclass class_of_dev; + /// Class_of_Device_Mask + struct devclass class_of_dev_msk; + /// Auto_Accept_Flag + uint8_t auto_accept; + } cond_1; + + /// Connection Setup Filter Condition - condition type 0x02 + struct con_set_filter_cond_2 + { + /// BD Address + struct bd_addr bd_addr; + /// Auto_Accept_Flag + uint8_t auto_accept; + } cond_2; + } cond; + + } con_set; + + } filter; +}; + +/// HCI command completed event structure for the flush command +/*@TRACE*/ +struct hci_flush_cmd_cmp_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; +}; + +/// HCI command complete event structure for the Read pin type command +/*@TRACE*/ +struct hci_rd_pin_type_cmd_cmp_evt +{ + ///Status of the command + uint8_t status; + ///PIN type + uint8_t pin_type; +}; + +/*@TRACE*/ +struct hci_wr_pin_type_cmd +{ + ///PIN type + uint8_t pin_type; +}; + +/*@TRACE*/ +struct hci_rd_stored_lk_cmd +{ + ///BdAddr + struct bd_addr bd_addr; + ///Read all flag + uint8_t rd_all_flag; +}; + +/// HCI command complete event structure for read stored link key command +/*@TRACE*/ +struct hci_rd_stored_lk_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + ///Maximum number of key + uint16_t num_key_max; + ///Read number of key + uint16_t num_key_rd; +}; + +#if BT_EMB_PRESENT +/*@TRACE*/ +struct hci_wr_stored_lk_cmd +{ + /// Number of key to write + uint8_t num_key_wr; + + /// BD Address + Key table + struct bd_addr_plus_key link_keys[HCI_MAX_CMD_PARAM_SIZE / sizeof(struct bd_addr_plus_key)]; +}; +#endif //BT_EMB_PRESENT + +/// HCI command complete event structure for write stored link key command +/*@TRACE*/ +struct hci_wr_stored_lk_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + ///number of key written + uint8_t num_key_wr; +}; + +/*@TRACE*/ +struct hci_del_stored_lk_cmd +{ + ///BdAddr + struct bd_addr bd_addr; + ///Delete all flag + uint8_t del_all_flag; +}; + +/// HCI command complete event structure for delete stored link key command +/*@TRACE*/ +struct hci_del_stored_lk_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + ///Read number of key + uint16_t num_key_del; +}; + +/*@TRACE*/ +struct hci_wr_local_name_cmd +{ + ///Name + struct device_name name; +}; + +/// HCI command complete event structure for the read local name command +/*@TRACE*/ +struct hci_rd_local_name_cmd_cmp_evt +{ + ///Status of the command + uint8_t status; + ///Name + uint8_t name[BD_NAME_SIZE]; +}; + +/// HCI command complete event structure for the Read connection accept to command +/*@TRACE*/ +struct hci_rd_con_accept_to_cmd_cmp_evt +{ + ///Status of the command + uint8_t status; + /// Connection accept timeout (in slots) + uint16_t con_acc_to; +}; + +/*@TRACE*/ +struct hci_wr_con_accept_to_cmd +{ + /// Connection accept timeout (in slots) + uint16_t con_acc_to; +}; + +/// HCI command complete event structure for the Read page to command +/*@TRACE*/ +struct hci_rd_page_to_cmd_cmp_evt +{ + ///Status of the command + uint8_t status; + /// Page timeout (in slots) + uint16_t page_to; +}; + +/*@TRACE*/ +struct hci_wr_page_to_cmd +{ + /// Page timeout (in slots) + uint16_t page_to; +}; + +/// HCI command complete event structure for the Read scan enable command +/*@TRACE*/ +struct hci_rd_scan_en_cmd_cmp_evt +{ + ///Status of the command + uint8_t status; + ///Status of the scan enable + uint8_t scan_en; +}; + +/*@TRACE*/ +struct hci_wr_scan_en_cmd +{ + ///Status of the scan enable + uint8_t scan_en; +}; + +/// HCI command complete event structure for the Read scan activity command +/*@TRACE*/ +struct hci_rd_page_scan_act_cmd_cmp_evt +{ + ///Status of the command + uint8_t status; + /// Page scan interval (in slots) + uint16_t page_scan_intv; + /// Page scan window (in slots) + uint16_t page_scan_win; +}; + +/*@TRACE*/ +struct hci_wr_page_scan_act_cmd +{ + /// Page scan interval (in slots) + uint16_t page_scan_intv; + /// Page scan window (in slots) + uint16_t page_scan_win; +}; + +/// HCI command complete event structure for the Read inquiry scan activity command +/*@TRACE*/ +struct hci_rd_inq_scan_act_cmd_cmp_evt +{ + /// Status of the command + uint8_t status; + /// Inquiry scan interval (in slots) + uint16_t inq_scan_intv; + /// Inquiry scan window (in slots) + uint16_t inq_scan_win; +}; + +/*@TRACE*/ +struct hci_wr_inq_scan_act_cmd +{ + /// Inquiry scan interval (in slots) + uint16_t inq_scan_intv; + /// Inquiry scan window (in slots) + uint16_t inq_scan_win; +}; + +/// HCI command complete event structure for the Read authentication command +/*@TRACE*/ +struct hci_rd_auth_en_cmd_cmp_evt +{ + ///Status of the command + uint8_t status; + ///Value of the authentication + uint8_t auth_en; +}; + +/*@TRACE*/ +struct hci_wr_auth_en_cmd +{ + ///Value of the authentication + uint8_t auth_en; +}; + +/// HCI command complete event structure for the read class of device command +/*@TRACE*/ +struct hci_rd_class_of_dev_cmd_cmp_evt +{ + ///Status of the command + uint8_t status; + ///Class of device + struct devclass class_of_dev; +}; + +/*@TRACE*/ +struct hci_wr_class_of_dev_cmd +{ + ///Class of device + struct devclass class_of_dev; +}; + +/// HCI read voice settings complete event +/*@TRACE*/ +struct hci_rd_voice_stg_cmd_cmp_evt +{ + ///Status of the command reception + uint8_t status; + /// Voice setting + uint16_t voice_stg; +}; + +/*@TRACE*/ +struct hci_wr_voice_stg_cmd +{ + /// voice setting + uint16_t voice_stg; +}; + +/// HCI command complete event structure for read number of broadcast retrans command +/*@TRACE*/ +struct hci_rd_nb_bdcst_retx_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + ///Read number of broadcast retransmission + uint8_t num_bcst_ret; +}; + +/*@TRACE*/ +struct hci_wr_nb_bdcst_retx_cmd +{ + ///Read number of broadcast retransmission + uint8_t num_bcst_ret; +}; + +/// HCI command complete event structure for the Read Synchronous Flow Control command +/*@TRACE*/ +struct hci_rd_sync_flow_ctrl_en_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + ///Synchronous flow control enable + uint8_t sync_flow_ctrl_en; +}; + +/*@TRACE*/ +struct hci_wr_sync_flow_ctrl_en_cmd +{ + /// Synchronous Flow Control enable + uint8_t sync_flow_ctrl_en; +}; + +///HCI set controller to host flow control command +/*@TRACE*/ +struct hci_set_ctrl_to_host_flow_ctrl_cmd +{ + ///Flow control enable for controller + uint8_t flow_cntl; +}; + +///HCI host buffer size command +/*@TRACE*/ +struct hci_host_buf_size_cmd +{ + ///Host ACL packet length + uint16_t acl_pkt_len; + ///Host synchronous packet length + uint8_t sync_pkt_len; + ///Host Total number of ACL packets allowed + uint16_t nb_acl_pkts; + ///Host total number of synchronous packets allowed + uint16_t nb_sync_pkts; +}; + +#if BT_EMB_PRESENT +///HCI host number of completed packets command +/*@TRACE*/ +struct hci_host_nb_cmp_pkts_cmd +{ + ///Number of handles for which the completed packets number is given + uint8_t nb_of_hdl; + ///Array of connection handles + uint16_t con_hdl[MAX_NB_ACTIVE_ACL]; + ///Array of number of completed packets values for connection handles. + uint16_t nb_comp_pkt[MAX_NB_ACTIVE_ACL]; +}; +#elif BLE_EMB_PRESENT || BLE_HOST_PRESENT +///HCI host number of completed packets command +/*@TRACE*/ +struct hci_host_nb_cmp_pkts_cmd +{ + ///Number of handles for which the completed packets number is given + uint8_t nb_of_hdl; + ///Array of connection handles + uint16_t con_hdl[BLE_ACTIVITY_MAX+1]; // ensure that at least 1 element is present + ///Array of number of completed packets values for connection handles. + uint16_t nb_comp_pkt[BLE_ACTIVITY_MAX+1]; // ensure that at least 1 element is present +}; +#endif //BLE_EMB_PRESENT || BLE_HOST_PRESENT + +/// HCI read link supervision timeout command parameters structure +struct hci_rd_link_supv_to_cmd_cmp_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///Link supervision timeout + uint16_t lsto_val; +}; + +/// HCI write link supervision timeout command parameters structure +/*@TRACE*/ +struct hci_wr_link_supv_to_cmd +{ + ///Connection handle + uint16_t conhdl; + ///Link supervision timeout + uint16_t lsto_val; +}; + +/// HCI command complete event structure for the nb of supported IAC command +/*@TRACE*/ +struct hci_rd_nb_supp_iac_cmd_cmp_evt +{ + ///Status of the command + uint8_t status; + ///nb_of iac + uint8_t nb_iac; +}; + +/// HCI command complete event structure for read current IAC LAP command +/*@TRACE*/ +struct hci_rd_curr_iac_lap_cmd_cmp_evt +{ + ///Status of the command + uint8_t status; + ///nb of current iac + uint8_t nb_curr_iac; + ///lap + struct lap iac_lap; +}; + +/// HCI write current IAC LAP command structure +/*@TRACE*/ +struct hci_wr_curr_iac_lap_cmd +{ + /// Number of current iac laps + uint8_t nb_curr_iac; + ///lap + struct lap iac_lap[(HCI_MAX_CMD_PARAM_SIZE / BD_ADDR_LAP_LEN) - 1]; +}; + +/*@TRACE*/ +struct hci_set_afh_host_ch_class_cmd +{ + ///AFH channel map + struct chnl_map afh_ch; +}; + +/// HCI command complete event structure for write inquiry scan type command structure +/*@TRACE*/ +struct hci_rd_inq_scan_type_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + /// Inquiry scan type + uint8_t inq_scan_type; +}; + +/*@TRACE*/ +struct hci_wr_inq_scan_type_cmd +{ + /// Inquiry scan type + uint8_t inq_scan_type; +}; + +/// HCI command complete event structure for read inquiry mode command structure +/*@TRACE*/ +struct hci_rd_inq_mode_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + /// Inquiry mode + uint8_t inq_mode; +}; + +/*@TRACE*/ +struct hci_wr_inq_mode_cmd +{ + /// Inquiry mode + uint8_t inq_mode; +}; + +/// HCI command complete event structure for write page scan type command structure +/*@TRACE*/ +struct hci_rd_page_scan_type_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + /// Page scan type + uint8_t page_scan_type; +}; + +/*@TRACE*/ +struct hci_wr_page_scan_type_cmd +{ + /// Page scan type + uint8_t page_scan_type; +}; + +/// HCI command complete event structure for read assessment mode command structure +/*@TRACE*/ +struct hci_rd_afh_ch_assess_mode_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + ///AFH channel assessment mode + uint8_t afh_ch_ass_mode; +}; + +/*@TRACE*/ +struct hci_wr_afh_ch_assess_mode_cmd +{ + ///AFH channel assessment mode + uint8_t afh_ch_ass_mode; +}; + +/// HCI command complete event structure for remote name request cancel command +/*@TRACE*/ +struct hci_rd_ext_inq_rsp_cmd_cmp_evt +{ + ///status + uint8_t status; + ///FEC required + uint8_t fec_req; + ///Extended inquiry response + struct eir eir; +}; + +/*@TRACE*/ +struct hci_wr_ext_inq_rsp_cmd +{ + ///FEC required + uint8_t fec_req; + ///Extended inquiry response + struct eir eir; +}; + +/// HCI command complete event structure for remote name request cancel command +/*@TRACE*/ +struct hci_rd_sp_mode_cmd_cmp_evt +{ + ///status + uint8_t status; + ///Simple pairing mode + uint8_t sp_mode; +}; + +/*@TRACE*/ +struct hci_wr_sp_mode_cmd +{ + ///Simple pairing mode + uint8_t sp_mode; +}; + +/// HCI command complete event structure for read oob data command +/*@TRACE*/ +struct hci_rd_loc_oob_data_cmd_cmp_evt +{ + ///status + uint8_t status; + ///hash part + struct hash oob_c; + ///random part + struct randomizer oob_r; +}; + +/// HCI command complete event structure for read inquiry response transmit power command +/*@TRACE*/ +struct hci_rd_inq_rsp_tx_pwr_lvl_cmd_cmp_evt +{ + ///status + uint8_t status; + ///TX power + uint8_t tx_pwr; +}; + +/*@TRACE*/ +struct hci_wr_inq_tx_pwr_lvl_cmd +{ + ///TX power + int8_t tx_pwr; +}; + +/// HCI command complete event structure for read erroneous data reporting command +/*@TRACE*/ +struct hci_rd_dft_err_data_rep_cmd_cmp_evt +{ + ///status + uint8_t status; + ///Erroneous data reporting + uint8_t err_data_rep; +}; + +/*@TRACE*/ +struct hci_wr_dft_err_data_rep_cmd +{ + ///Erroneous data reporting + uint8_t err_data_rep; +}; + +/// HCI read LE Host Supported complete event +/*@TRACE*/ +struct hci_rd_le_host_supp_cmd_cmp_evt +{ + ///Status + uint8_t status; + ///LE_Supported_Host + uint8_t le_supported_host; + ///Simultaneous_LE_Host + uint8_t simultaneous_le_host; +}; + +/// HCI write LE Host Supported command +/*@TRACE*/ +struct hci_wr_le_host_supp_cmd +{ + ///LE_Supported_Host + uint8_t le_supported_host; + ///Simultaneous_LE_Host + uint8_t simultaneous_le_host; +}; + +/// HCI Set MWS Channel Parameters command +/*@TRACE*/ +struct hci_set_mws_channel_params_cmd +{ + ///MWS_Channel_Enable + uint8_t mws_channel_enable; + ///MWS_RX_Center_Frequency + uint16_t mws_rx_center_frequency; + ///MWS_TX_Center_Frequency + uint16_t mws_tx_center_frequency; + ///MWS_RX_Channel_Bandwidth + uint16_t mws_rx_channel_bandwidth; + ///MWS_TX_Channel_Bandwidth + uint16_t mws_tx_channel_bandwidth; + ///MWS_Channel_Type + uint8_t mws_channel_type; +}; + +/// HCI Set External Frame Configuration command +/*@TRACE*/ +struct hci_set_external_frame_config_cmd +{ + /// Ext_Frame_Duration + uint16_t ext_fr_duration; + /// Ext_Frame_Sync_Assert_Offset + int16_t ext_fr_sync_assert_offset; + /// Ext_Frame_Sync_Assert_Jitter + uint16_t ext_fr_sync_assert_jitter; + /// Ext_Frame_Num_Periods + uint8_t ext_fr_num_periods; + /// Period Durations & Types + struct ext_fr_period period[1/*__ARRAY_EMPTY*/]; +}; + +/// HCI Set MWS Signaling command +/*@TRACE*/ +struct hci_set_mws_signaling_cmd +{ + ///MWS_RX_Assert_Offset + int16_t mws_rx_assert_offset; + ///MWS_RX_Assert_Jitter + uint16_t mws_rx_assert_jitter; + ///MWS_RX_Deassert_Offset + int16_t mws_rx_deassert_offset; + ///MWS_RX_Deassert_Jitter + uint16_t mws_rx_deassert_jitter; + ///MWS_TX_Assert_Offset + int16_t mws_tx_assert_offset; + ///MWS_TX_Assert_Jitter + uint16_t mws_tx_assert_jitter; + ///MWS_TX_Deassert_Offset + int16_t mws_tx_deassert_offset; + ///MWS_TX_Deassert_Jitter + uint16_t mws_tx_deassert_jitter; + ///MWS_Pattern_Assert_Offset + int16_t mws_pattern_assert_offset; + ///MWS_Pattern_Assert_Jitter + uint16_t mws_pattern_assert_jitter; + ///MWS_Inactivity_Duration_Assert_Offset + int16_t mws_inactivity_duration_assert_offset; + ///MWS_Inactivity_Duration_Assert_Jitter + uint16_t mws_inactivity_duration_assert_jitter; + ///MWS_Scan_Frequency_Assert_Offset + int16_t mws_scan_frequency_assert_offset; + ///MWS_Scan_Frequency_Assert_Jitter + uint16_t mws_scan_frequency_assert_jitter; + ///MWS_Priority_Assert_Offset_Request + uint16_t mws_priority_assert_offset_request; +}; + +/// HCI Set MWS Signaling command complete event +/*@TRACE*/ +struct hci_set_mws_signaling_cmd_cmp_evt +{ + ///Status + uint8_t status; + ///Bluetooth_Rx_Priority_Assert_Offset + int16_t bt_rx_prio_assert_offset; + ///Bluetooth_Rx_Priority_Assert_Jitter + uint16_t bt_rx_prio_assert_jitter; + ///Bluetooth_Rx_Priority_Deassert_Offset + int16_t bt_rx_prio_deassert_offset; + ///Bluetooth_Rx_Priority_Deassert_Jitter + uint16_t bt_rx_prio_deassert_jitter; + ///802_Rx_Priority_Assert_Offset + int16_t _802_rx_prio_assert_offset; + ///802_Rx_Priority_Assert_Jitter + uint16_t _802_rx_prio_assert_jitter; + ///802_Rx_Priority_Deassert_Offset + int16_t _802_rx_prio_deasssert_offset; + ///802_Rx_Priority_Deassert_Jitter + uint16_t _802_rx_prio_deassert_jitter; + ///Bluetooth_Tx_On_Assert_Offset + int16_t bt_tx_on_assert_offset; + ///Bluetooth_Tx_On_Assert_Jitter + uint16_t bt_tx_on_assert_jitter; + ///Bluetooth_Tx_On_Deassert_Offset + int16_t bt_tx_on_deassert_offset; + ///Bluetooth_Tx_On_Deassert_Jitter + uint16_t bt_tx_on_deassert_jitter; + ///802_Tx_On_Assert_Offset + int16_t _802_tx_on_assert_offset; + ///802_Tx_On_Assert_Jitter + uint16_t _802_tx_on_assert_jitter; + ///802_Tx_On_Deassert_Offset + int16_t _802_tx_on_deassert_offset; + ///802_Tx_On_Deassert_Jitter + uint16_t _802_tx_on_deassert_jitter; +}; + +/// HCI Set MWS Transport Layer command +/*@TRACE*/ +struct hci_set_mws_transport_layer_cmd +{ + ///Transport_Layer + uint8_t transport_layer; + ///To_MWS_Baud_Rate + uint32_t to_mws_baud_rate; + ///From_MWS_Baud_Rate + uint32_t from_mws_baud_rate; +}; + +/// HCI Set MWS Scan Frequency Table command +/*@TRACE*/ +struct hci_set_mws_scan_freq_table_cmd +{ + ///Num_Scan_Frequencies + uint8_t num_scan_frequencies; + ///Scan_Frequencys Low & High + struct mws_scan_freq scan_freq[1/*__ARRAY_EMPTY*/]; +}; + +/// HCI Set MWS Pattern Configuration command +/*@TRACE*/ +struct hci_set_mws_pattern_config_cmd +{ + ///MWS_PATTERN_Index + uint8_t mws_pattern_index; + ///MWS_PATTERN_NumIntervals + uint8_t num_intervals; + ///MWS_PATTERN_Interval Duration & Type + struct mws_pattern_intv intv[1/*__ARRAY_EMPTY*/]; +}; + +/// Hci Get MWS Transport Layer Configuration command complete event +/*@TRACE*/ +struct hci_get_mws_transport_layer_config_cmd_cmp_evt +{ + ///Status + uint8_t status; + ///Num_Transports + uint8_t num_transports; + ///Transport_Layers + struct mws_transport tran[1/*__ARRAY_EMPTY*/]; +}; + +/// HCI read Secure Connections Host Support complete event +/*@TRACE*/ +struct hci_rd_sec_con_host_supp_cmd_cmp_evt +{ + ///Status + uint8_t status; + /// Secure Connections Host Support + uint8_t sec_con_host_supp; +}; + +/// HCI write Secure Connections Host Support command +/*@TRACE*/ +struct hci_wr_sec_con_host_supp_cmd +{ + /// Secure Connections Host Support + uint8_t sec_con_host_supp; +}; + +/// HCI write Secure Connections Test Mode command +struct hci_wr_sec_con_test_mode_cmd +{ + /// Connection handle + uint16_t conhdl; + /// DM1 ACL-U mode (0: disabled | 1: enabled) + uint8_t dm1_acl_u_mode; + /// eSCO loopback mode (0: disabled | 1: enabled) + uint8_t esco_loopback_mode; +}; + +/// HCI write Secure Connections Test Mode complete event +struct hci_wr_sec_con_test_mode_cmd_cmp_evt +{ + ///Status + uint8_t status; + /// Connection handle + uint16_t conhdl; +}; + +/// HCI Set Reserved LT_ADDR command +/*@TRACE*/ +struct hci_set_res_lt_addr_cmd +{ + /// LT_ADDR + uint8_t lt_addr; +}; + +/// HCI Set Reserved LT_ADDR command complete event +/*@TRACE*/ +struct hci_set_res_lt_addr_cmd_cmp_evt +{ + /// Status + uint8_t status; + /// LT_ADDR + uint8_t lt_addr; +}; + +/// HCI Delete Reserved LT_ADDR command +/*@TRACE*/ +struct hci_del_res_lt_addr_cmd +{ + /// LT_ADDR + uint8_t lt_addr; +}; + +/// HCI Delete Reserved LT_ADDR command complete event +/*@TRACE*/ +struct hci_del_res_lt_addr_cmd_cmp_evt +{ + /// Status + uint8_t status; + /// LT_ADDR + uint8_t lt_addr; +}; + +/// HCI Set Connectionless Slave Broadcast Data command +/*@TRACE*/ +struct hci_set_con_slv_bcst_data_cmd +{ + /// LT_ADDR + uint8_t lt_addr; + /// Fragment + uint8_t fragment; + /// Data_Length (in bytes) + uint8_t data_length; + /// Data + uint8_t data[__ARRAY_EMPTY]; +}; + +/// HCI Set Connectionless Slave Broadcast Data command complete event +/*@TRACE*/ +struct hci_set_con_slv_bcst_data_cmd_cmp_evt +{ + /// Status + uint8_t status; + /// LT_ADDR + uint8_t lt_addr; +}; + +/// HCI Read Synchronization Train Parameters command complete event +/*@TRACE*/ +struct hci_rd_sync_train_param_cmd_cmp_evt +{ + /// Status + uint8_t status; + /// Sync_Train_Interval (in slots) + uint16_t sync_train_int; + /// synchronization_trainTO (in slots) + uint32_t sync_train_to; + /// Service_Data + uint8_t service_data; +}; + +/// HCI Write Synchronization Train Parameters command +/*@TRACE*/ +struct hci_wr_sync_train_param_cmd +{ + /// Interval_Min (in slots) + uint16_t int_min; + /// Interval_Max (in slots) + uint16_t int_max; + /// synchronization_trainTO (in slots) + uint32_t sync_train_to; + /// Service_Data + uint8_t service_data; +}; + +/// HCI Write Synchronization Train Parameters command complete event +/*@TRACE*/ +struct hci_wr_sync_train_param_cmd_cmp_evt +{ + /// Status + uint8_t status; + /// Sync_Train_Interval (in slots) + uint16_t sync_train_int; +}; + +// HCI Synchronization Train Complete event +struct hci_sync_train_cmp_evt +{ + /// Status + uint8_t status; +}; + +/// HCI read authenticated payload timeout command +/*@TRACE*/ +struct hci_rd_auth_payl_to_cmd +{ + ///Connection handle + uint16_t conhdl; +}; + +/// HCI command complete event structure for the Read Authenticated Payload Timeout Command +/*@TRACE*/ +struct hci_rd_auth_payl_to_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///Authenticated payload timeout + uint16_t auth_payl_to; +}; + +/// HCI command complete event structure for read oob extended data command +/*@TRACE*/ +struct hci_rd_loc_oob_ext_data_cmd_cmp_evt +{ + ///status + uint8_t status; + ///hash part + struct hash oob_c_192; + ///random part + struct randomizer oob_r_192; + ///hash part + struct hash oob_c_256; + ///random part + struct randomizer oob_r_256; +}; + +/// HCI read Extended Page Timeout CC event +/*@TRACE*/ +struct hci_rd_ext_page_to_cmd_cmp_evt +{ + /// Status + uint8_t status; + /** + * Extended Page Timeout measured in Number of Baseband slots. Interval Length = N * 0.625 msec (1 Baseband slot) + * Range for N: 0x0000 (default) - 0xFFFF + * Time Range: 0 - 40.9 Seconds + */ + uint16_t ext_page_to; +}; + +/// HCI write Extended Page Timeout +/*@TRACE*/ +struct hci_wr_ext_page_to_cmd +{ + /** + * Extended Page Timeout measured in Number of Baseband slots. Interval Length = N * 0.625 msec (1 Baseband slot) + * Range for N: 0x0000 (default) - 0xFFFF + * Time Range: 0 - 40.9 Seconds + */ + uint16_t ext_page_to; +}; + +/// HCI read Extended Inquiry Length CC event +/*@TRACE*/ +struct hci_rd_ext_inq_len_cmd_cmp_evt +{ + /// Status + uint8_t status; + /// Extended Inquiry Length + uint16_t ext_inq_len; +}; + +/// HCI write Extended Inquiry Length +/*@TRACE*/ +struct hci_wr_ext_inq_len_cmd +{ + /// Extended Inquiry Length + uint16_t ext_inq_len; +}; + +/* + * HCI INFORMATIONAL PARAMETERS COMMANDS PARAMETERS + **************************************************************************************** + */ + +///HCI command complete event structure for read local version information +/*@TRACE*/ +struct hci_rd_local_ver_info_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + ///HCI version number + uint8_t hci_ver; + ///HCI revision number + uint16_t hci_rev; + ///LMP version + uint8_t lmp_ver; + ///manufacturer name + uint16_t manuf_name; + ///LMP Subversion + uint16_t lmp_subver; +}; + +///HCI command complete event structure for read local supported commands +/*@TRACE*/ +struct hci_rd_local_supp_cmds_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + ///Supported Commands structure + struct supp_cmds local_cmds; +}; + +/// HCI command complete event structure for read local supported features command +/*@TRACE*/ +struct hci_rd_local_supp_feats_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + ///Local supported features + struct features feats; +}; + +/*@TRACE*/ +struct hci_rd_local_ext_feats_cmd +{ + ///Page number + uint8_t page_nb; +}; + +/// HCI command complete event structure for read local extended features command +/*@TRACE*/ +struct hci_rd_local_ext_feats_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + ///Page number + uint8_t page_nb; + ///Maximum page number + uint8_t page_nb_max; + ///Extended LMP features + struct features ext_feats; +}; + +///HCI command complete event structure for the Read Buffer Size Command +/*@TRACE*/ +struct hci_rd_buff_size_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + ///ACL data packet length controller can receive from host + uint16_t hc_data_pk_len; + ///Synchronous data packet length controller can receive from host + uint8_t hc_sync_pk_len; + ///Total number of ACL data packets controller can receive from host + uint16_t hc_tot_nb_data_pkts; + ///Total number of synchronous data packets controller can receive from host + uint16_t hc_tot_nb_sync_pkts; +}; + +///HCI command complete event structure for read bd address +/*@TRACE*/ +struct hci_rd_bd_addr_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + ///BD address + struct bd_addr local_addr; +}; + +/// HCI command complete event structure for read local supported codecs +/*@TRACE*/ +struct hci_rd_local_supp_codecs_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + uint8_t nb_supp_codecs; + uint8_t nb_supp_vendor_specific_codecs; + +// ///Supported Codecs structure +// struct supp_codecs local_codecs; +}; + +/// HCI command complete event structure for read local simple pairing options +struct hci_rd_local_sp_opt_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + /// Simple Pairing options (bit 0: Remote public key validation) + uint8_t sp_opt; + /// Maximum Encryption Key Size (in octets) + uint8_t max_enc_key_size; +}; + +/* + * HCI STATUS PARAMETERS COMMANDS PARAMETERS + **************************************************************************************** + */ + +/// HCI command complete event structure for read rssi +/*@TRACE*/ +struct hci_rd_rssi_cmd_cmp_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///RSSI value + uint8_t rssi; +}; + +/*@TRACE*/ +struct hci_rd_clk_cmd +{ + ///Connection handle + uint16_t conhdl; + ///Which clock + uint8_t clk_type; +}; + +/// HCI read clock command structure +/*@TRACE*/ +struct hci_rd_clk_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///clock + uint32_t clk; + ///Accuracy + uint16_t clk_acc; +}; + + +/* + * HCI TESTING COMMANDS PARAMETERS + **************************************************************************************** + */ + +/// HCI command complete event structure for read loop back mode command +/*@TRACE*/ +struct hci_rd_loopback_mode_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + ///Local supported features + uint8_t lb_mode; +}; + +/*@TRACE*/ +struct hci_wr_loopback_mode_cmd +{ + ///Local supported features + uint8_t lb_mode; +}; + +/*@TRACE*/ +struct hci_wr_sp_dbg_mode_cmd +{ + ///Simple pairing mode + uint8_t sp_mode; +}; + + +/* + * HCI LE CONTROLLER COMMANDS PARAMETERS + **************************************************************************************** + */ + +///HCI LE Set Event Mask Command parameters structure +/*@TRACE*/ +struct hci_le_set_evt_mask_cmd +{ + ///LE Event Mask + struct evt_mask le_mask; +}; + +///HCI LE Set Random Address Command parameters structure +/*@TRACE*/ +struct hci_le_set_rand_addr_cmd +{ + ///Random address to set + struct bd_addr rand_addr; +}; + +///HCI LE Set Advertising Parameters Command parameters structure +/*@TRACE*/ +struct hci_le_set_adv_param_cmd +{ + ///Minimum interval for advertising + uint16_t adv_intv_min; + ///Maximum interval for advertising + uint16_t adv_intv_max; + ///Advertising type + uint8_t adv_type; + ///Own address type: public=0 / random=1 / rpa_or_pub=2 / rpa_or_rnd=3 + uint8_t own_addr_type; + ///Peer address type: public=0 / random=1 + uint8_t peer_addr_type; + ///Peer Bluetooth device address + struct bd_addr peer_addr; + ///Advertising channel map + uint8_t adv_chnl_map; + ///Advertising filter policy + uint8_t adv_filt_policy; +}; + +///HCI LE Set Advertising Data Command parameters structure +/*@TRACE*/ +struct hci_le_set_adv_data_cmd +{ + ///Advertising data length + uint8_t adv_data_len; + ///Advertising data - maximum 31 bytes + struct adv_data data; +}; + +///HCI LE Set Scan Response Data Command parameters structure +/*@TRACE*/ +struct hci_le_set_scan_rsp_data_cmd +{ + ///Scan response data length + uint8_t scan_rsp_data_len; + ///Scan response data - maximum 31 bytes + struct scan_rsp_data data; +}; + +///HCI LE Set Advertise Enable Command parameters structure +/*@TRACE*/ +struct hci_le_set_adv_en_cmd +{ + ///Advertising enable - 0=disabled, 1=enabled + uint8_t adv_en; +}; + +///HCI LE Set Scan Parameters Command parameters structure +/*@TRACE*/ +struct hci_le_set_scan_param_cmd +{ + ///Scan type - 0=passive / 1=active + uint8_t scan_type; + ///Scan interval + uint16_t scan_intv; + ///Scan window size + uint16_t scan_window; + ///Own address type - public=0 / random=1 / rpa_or_pub=2 / rpa_or_rnd=3 + uint8_t own_addr_type; + ///Scan filter policy + uint8_t scan_filt_policy; +}; + +///HCI LE Set Scan Enable Command parameters structure +/*@TRACE*/ +struct hci_le_set_scan_en_cmd +{ + ///Scan enable - 0=disabled, 1=enabled + uint8_t scan_en; + ///Enable for duplicates filtering - 0 =disabled/ 1=enabled + uint8_t filter_duplic; +}; + +///HCI LE Create Connection Command parameters structure +/*@TRACE*/ +struct hci_le_create_con_cmd +{ + ///Scan interval (N * 0.625 ms) + uint16_t scan_intv; + ///Scan window size (N * 0.625 ms) + uint16_t scan_window; + ///Initiator filter policy + uint8_t init_filt_policy; + ///Peer address type - public=0 / random=1 / rpa_or_pub=2 / rpa_or_rnd=3 + uint8_t peer_addr_type; + ///Peer BD address + struct bd_addr peer_addr; + ///Own address type - public=0 / random=1 / rpa_or_pub=2 / rpa_or_rnd=3 + uint8_t own_addr_type; + ///Minimum of connection interval (N * 1.25 ms) + uint16_t con_intv_min; + ///Maximum of connection interval (N * 1.25 ms) + uint16_t con_intv_max; + ///Connection latency + uint16_t con_latency; + ///Link supervision timeout + uint16_t superv_to; + ///Minimum CE length (N * 0.625 ms) + uint16_t ce_len_min; + ///Maximum CE length (N * 0.625 ms) + uint16_t ce_len_max; +}; + +///HCI LE Add Device to White List Command parameters structure +/*@TRACE*/ +struct hci_le_add_dev_to_wlst_cmd +{ + ///Type of address of the device to be added to the White List - 0=public/1=random + uint8_t dev_addr_type; + ///Address of device to be added to White List + struct bd_addr dev_addr; +}; + +///HCI LE Remove Device from White List Command parameters structure +/*@TRACE*/ +struct hci_le_rmv_dev_from_wlst_cmd +{ + ///Type of address of the device to be removed from the White List - 0=public/1=random + uint8_t dev_addr_type; + ///Address of device to be removed from White List + struct bd_addr dev_addr; +}; + +///HCI LE Set Extended Scan Paramaters Command parameters structure +/*@TRACE*/ +struct hci_le_set_ext_scan_param_cmd +{ + ///Own address type public/random/rpa + uint8_t own_addr_type; + ///Scanning filter policy + uint8_t scan_filt_policy; + ///Indicates the PHY(s) on which the advertising packets should be received + uint8_t scan_phys; + ///Paramaters for PHY(s) + struct scan_phy_param + { + ///Scaning Type: passive/active + uint8_t scan_type; + ///Scan interval (slots) + uint16_t scan_intv; + ///Scan window size (slots) + uint16_t scan_window; + } phy[MAX_SCAN_PHYS]; +}; + +///HCI LE Set Extended Scan Enable Command parameters structure +/*@TRACE*/ +struct hci_le_set_ext_scan_en_cmd +{ + ///Scan enable - 0=disabled, 1=enabled + uint8_t scan_en; + ///Filter duplicates - 0=disabled, 1=enabled, 2=enabled & reset each scan period + uint8_t filter_duplic; + ///Scan duration (Time=N*10ms) | 0x0000: Scan continuously until explicitly disable + uint16_t duration; + ///Scan period (Time=N*1.28sec) | 0x0000: Periodic scanning disabled + uint16_t period; +}; + +/*@TRACE*/ +struct init_phy_param +{ + ///Scan interval (N * 0.625 ms) + uint16_t scan_interval; + ///Scan window size (N * 0.625 ms) + uint16_t scan_window; + ///Minimum of connection interval (N * 1.25 ms) + uint16_t con_intv_min; + ///Maximum of connection interval (N * 1.25 ms) + uint16_t con_intv_max; + ///Connection latency + uint16_t con_latency; + ///Link supervision timeout + uint16_t superv_to; + ///Minimum CE length (N * 0.625 ms) + uint16_t ce_len_min; + ///Maximum CE length (N * 0.625 ms) + uint16_t ce_len_max; +}; + +///HCI LE Extended Create Connection Command parameters structure +/*@TRACE*/ +struct hci_le_ext_create_con_cmd +{ + ///Initiator filter policy + uint8_t init_filter_policy; + ///Own address type public/random/rpa + uint8_t own_addr_type; + ///Peer address type public/random/rpa + uint8_t peer_addr_type; + ///Peer address + struct bd_addr peer_addr; + ///Indicates the PHY(s) on which the advertising packets should be received + uint8_t init_phys; + ///Paramaters for PHY(s) + struct init_phy_param phy[MAX_INIT_PHYS]; +}; + +///HCI LE Periodic Advertising Create Sync Command parameters structure +/*@TRACE*/ +struct hci_le_per_adv_create_sync_cmd +{ + /// Options (@see enum per_sync_opt) + uint8_t options; + ///Advertising SID + uint8_t adv_sid; + ///Advertising address type + uint8_t adv_addr_type; + ///Advertiser address + struct bd_addr adv_addr; + ///max Skip after receive + uint16_t skip; + ///Sync timeout (Time=N*10ms) + uint16_t sync_to; + /// Sync CTE type (@see enum sync_cte_type) + uint8_t sync_cte_type; +}; + +///HCI LE Periodic Advertising Terminate Sync Command parameters structure +/*@TRACE*/ +struct hci_le_per_adv_term_sync_cmd +{ + ///Sync handle + uint16_t sync_handle; +}; + +///HCI LE Add Device to Periodic Advertiser List Command parameters structure +/*@TRACE*/ +struct hci_le_add_dev_to_per_adv_list_cmd +{ + ///Advertiser address type + uint8_t adv_addr_type; + ///Advertiser address + struct bd_addr adv_addr; + ///Advertising SID + uint8_t adv_sid; +}; + +///HCI LE Remove Device from Periodic Advertiser List Command parameters structure +/*@TRACE*/ +struct hci_le_rmv_dev_from_per_adv_list_cmd +{ + ///Advertiser address type + uint8_t adv_addr_type; + ///Advertiser address + struct bd_addr adv_addr; + ///Advertising SID + uint8_t adv_sid; +}; + +///HCI LE Set Privacy Mode Command parameters structure +/*@TRACE*/ +struct hci_le_set_priv_mode_cmd +{ + ///Peer identity address type + uint8_t peer_addr_type; + ///Peer identity address + struct bd_addr peer_addr; + ///Privacy mode + uint8_t priv_mode; +}; + +///HCI LE Set Host Channel Classification Command parameters structure +/*@TRACE*/ +struct hci_le_set_host_ch_class_cmd +{ + ///Channel map + struct le_chnl_map chmap; +}; + + +///HCI LE Receiver Test v1 Command parameters structure +/*@TRACE*/ +struct hci_le_rx_test_v1_cmd +{ + ///RX frequency for Rx test + uint8_t rx_freq; +}; + +///HCI LE Transmitter Test v1 Command parameters structure +/*@TRACE*/ +struct hci_le_tx_test_v1_cmd +{ + ///TX frequency for Tx test + uint8_t tx_freq; + ///TX test data length + uint8_t test_data_len; + ///TX test payload type - see enum + uint8_t pk_payload_type; +}; + +///HCI LE Encrypt Command parameters structure +/*@TRACE*/ +struct hci_le_enc_cmd +{ + ///Long term key structure + struct ltk key; + ///Pointer to buffer with plain data to encrypt - 16 bytes + uint8_t plain_data[16]; +}; + +/// HCI LE Connection Update Command parameters structure +/*@TRACE*/ +struct hci_le_con_update_cmd +{ + ///Connection Handle + uint16_t conhdl; + ///Minimum of connection interval (units of 1.25 ms) + uint16_t con_intv_min; + ///Maximum of connection interval (units of 1.25 ms) + uint16_t con_intv_max; + ///Connection latency (units of connection event) + uint16_t con_latency; + ///Link supervision timeout (units of 10 ms) + uint16_t superv_to; + ///Minimum of CE length (units of 0.625 ms) + uint16_t ce_len_min; + ///Maximum of CE length (units of 0.625 ms) + uint16_t ce_len_max; +}; + +/// HCI LE Start Encryption Command parameters structure +/*@TRACE*/ +struct hci_le_start_enc_cmd +{ + ///Connection handle + uint16_t conhdl; + ///Random number - 8B + struct rand_nb nb; + ///Encryption Diversifier + uint16_t enc_div; + ///Long term key + struct ltk ltk; +}; + +/// HCI long term key request reply command parameters structure +/*@TRACE*/ +struct hci_le_ltk_req_reply_cmd +{ + ///Connection handle + uint16_t conhdl; + ///Long term key + struct ltk ltk; +}; + +/// HCI long term key request negative reply command parameters structure +/*@TRACE*/ +struct hci_le_ltk_req_neg_reply_cmd +{ + ///Connection handle + uint16_t conhdl; +}; + +/// HCI LE remote connection parameter request reply command parameters structure +/*@TRACE*/ +struct hci_le_rem_con_param_req_reply_cmd +{ + ///Connection handle + uint16_t conhdl; + ///Interval_Min + uint16_t interval_min; + ///Interval_Max + uint16_t interval_max; + ///Latency + uint16_t latency; + ///Timeout + uint16_t timeout; + ///Minimum_CE_Length + uint16_t min_ce_len; + ///Maximum_CE_Length + uint16_t max_ce_len; +}; + +/// HCI LE remote connection parameter request negative reply command parameters structure +/*@TRACE*/ +struct hci_le_rem_con_param_req_neg_reply_cmd +{ + ///Connection handle + uint16_t conhdl; + ///Reason + uint8_t reason; +}; + + +/// HCI LE Set Data Length Command parameters structure +/*@TRACE*/ +struct hci_le_set_data_len_cmd +{ + ///Connection Handle + uint16_t conhdl; + ///Preferred maximum number of payload octets that the local Controller should include + ///in a single Link Layer Data Channel PDU. + uint16_t tx_octets; + ///Preferred maximum number of microseconds that the local Controller should use to transmit + ///a single Link Layer Data Channel PDU + uint16_t tx_time; +}; + +/// HCI LE Read Suggested Default Data Length Command +/*@TRACE*/ +struct hci_le_wr_suggted_dft_data_len_cmd +{ + ///Suggested value for the Controller's maximum transmitted number of payload octets to be used + uint16_t suggted_max_tx_octets; + ///Suggested value for the Controller's maximum packet transmission time to be used + uint16_t suggted_max_tx_time; +}; + +/// HCI LE Add Device to Resolving List Command +/*@TRACE*/ +struct hci_le_add_dev_to_rslv_list_cmd +{ + /// Peer Identity Address Type + uint8_t peer_id_addr_type; + /// Peer Identity Address + struct bd_addr peer_id_addr; + /// Peer IRK + struct irk peer_irk; + /// Local IRK + struct irk local_irk; +}; + +/// HCI LE Remove Device From Resolving List Command +/*@TRACE*/ +struct hci_le_rmv_dev_from_rslv_list_cmd +{ + /// Peer Identity Address Type + uint8_t peer_id_addr_type; + /// Peer Identity Address + struct bd_addr peer_id_addr; +}; + +/// HCI LE Read Peer Resolvable Address Command +/*@TRACE*/ +struct hci_le_rd_peer_rslv_addr_cmd +{ + /// Peer Identity Address Type + uint8_t peer_id_addr_type; + /// Peer Identity Address + struct bd_addr peer_id_addr; +}; + +/// HCI LE Read Local Resolvable Address Command +/*@TRACE*/ +struct hci_le_rd_loc_rslv_addr_cmd +{ + /// Peer Identity Address Type + uint8_t peer_id_addr_type; + /// Peer Identity Address + struct bd_addr peer_id_addr; +}; + +/// HCI LE Set Address Resolution Enable Command +/*@TRACE*/ +struct hci_le_set_addr_resol_en_cmd +{ + /// Address Resolution Enable + uint8_t enable; +}; + +/// HCI LE Set Resolvable Private Address Timeout Command +/*@TRACE*/ +struct hci_le_set_rslv_priv_addr_to_cmd +{ + /// RPA Timeout + uint16_t rpa_timeout; +}; + +/* + * HCI EVENTS PARAMETERS + **************************************************************************************** + */ + +/// HCI inquiry complete event structure +/*@TRACE*/ +struct hci_inq_cmp_evt +{ + ///Status of the procedure + uint8_t status; +}; + + +/// HCI Inquiry result event structure (with only 1 result) +/*@TRACE*/ +struct hci_inq_res_evt +{ + + ///Number of response + uint8_t nb_rsp; + ///BdAddr + struct bd_addr bd_addr; + ///Page Scan Repetition Mode + uint8_t page_scan_rep_mode; + ///Reserved + uint8_t reserved1; + ///Reserved + uint8_t reserved2; + ///class of device + struct devclass class_of_dev; + ///Clock Offset + uint16_t clk_off; + +}; + +/// HCI Inquiry result with rssi event structure (with only 1 result) +/*@TRACE*/ +struct hci_inq_res_with_rssi_evt +{ + ///Number of response + uint8_t nb_rsp; + ///BdAddr + struct bd_addr bd_addr; + ///Page Scan Repetition Mode + uint8_t page_scan_rep_mode; + ///Reserved + uint8_t reserved1; + ///class of device + struct devclass class_of_dev; + ///Clock Offset + uint16_t clk_off; + ///Rssi + uint8_t rssi; + +}; + +/// HCI Extended inquiry result indication structure (with only 1 result) +/*@TRACE*/ +struct hci_ext_inq_res_evt +{ + ///Number of response + uint8_t nb_rsp; + ///BdAddr + struct bd_addr bd_addr; + ///Page Scan Repetition Mode + uint8_t page_scan_rep_mode; + ///Reserved + uint8_t reserved1; + ///class of device + struct devclass class_of_dev; + ///Clock Offset + uint16_t clk_off; + ///RSSi + uint8_t rssi; + ///Extended inquiry response data + struct eir eir; +}; + +/// HCI disconnect complete event structure +/*@TRACE*/ +struct hci_disc_cmp_evt +{ + ///Status of received command + uint8_t status; + ///Connection Handle + uint16_t conhdl; + ///Reason for disconnection + uint8_t reason; +}; + +/// HCI basic command complete event structure +/*@TRACE + * hci_dbg_wr_par_cmd_cmp_evt = hci_basic_cmd_cmp_evt + * hci_dbg_llcp_discard_cmd_cmp_evt = hci_basic_cmd_cmp_evt + * hci_reset_cmd_cmp_evt = hci_basic_cmd_cmp_evt + * hci_set_evt_mask_cmd_cmp_evt = hci_basic_cmd_cmp_evt + * hci_le_set_per_adv_en_cmd_cmp_evt = hci_basic_cmd_cmp_evt + * hci_le_create_con_cancel_cmd_cmp_evt = hci_basic_cmd_cmp_evt + * hci_le_set_evt_mask_cmd_cmp_evt = hci_basic_cmd_cmp_evt + * hci_le_set_host_ch_class_cmd_cmp_evt = hci_basic_cmd_cmp_evt + * hci_le_wr_suggted_dft_data_len_cmd_cmp_evt = hci_basic_cmd_cmp_evt + * hci_le_set_dft_phy_cmd_cmp_evt = hci_basic_cmd_cmp_evt + * hci_le_rmv_dev_from_wlst_cmd_cmp_evt = hci_basic_cmd_cmp_evt + * hci_le_set_adv_param_cmd_cmp_evt = hci_basic_cmd_cmp_evt + * hci_le_set_adv_data_cmd_cmp_evt = hci_basic_cmd_cmp_evt + * hci_le_set_scan_rsp_data_cmd_cmp_evt = hci_basic_cmd_cmp_evt + * hci_le_set_adv_en_cmd_cmp_evt = hci_basic_cmd_cmp_evt + * hci_le_set_scan_param_cmd_cmp_evt = hci_basic_cmd_cmp_evt + * hci_le_set_scan_en_cmd_cmp_evt = hci_basic_cmd_cmp_evt + * hci_le_set_rand_addr_cmd_cmp_evt = hci_basic_cmd_cmp_evt + * hci_le_set_addr_resol_en_cmd_cmp_evt = hci_basic_cmd_cmp_evt + * hci_le_set_rslv_priv_addr_to_cmd_cmp_evt = hci_basic_cmd_cmp_evt + * hci_le_rmv_dev_from_rslv_list_cmd_cmp_evt = hci_basic_cmd_cmp_evt + * hci_le_create_con_cmd_cmp_evt = hci_basic_cmd_cmp_evt + * hci_dbg_plf_reset_cmd_cmp_evt = hci_basic_cmd_cmp_evt + * hci_le_wr_rf_path_comp_cmd_cmp_evt = hci_basic_cmd_cmp_evt + * */ +struct hci_basic_cmd_cmp_evt +{ + ///Status of the command reception + uint8_t status; +}; + +/// HCI basic command complete event structure with connection handle +/*@TRACE*/ +struct hci_basic_conhdl_cmd_cmp_evt +{ + /// status + uint8_t status; + /// connection handle + uint16_t conhdl; +}; + +/// HCI basic command complete event structure with BD address +struct hci_basic_bd_addr_cmd_cmp_evt +{ + ///status + uint8_t status; + ///BdAddr + struct bd_addr bd_addr; +}; + +/// HCI basic event structure with status and BD address +struct hci_basic_stat_bd_addr_evt +{ + ///status + uint8_t status; + ///BdAddr + struct bd_addr bd_addr; +}; + +/// HCI basic event including a connection handle as parameter +struct hci_basic_conhdl_evt +{ + ///Connection handle + uint16_t conhdl; +}; + +/// HCI complete event with status only. +/*@TRACE*/ +struct hci_cmd_stat_event +{ + /// Status of the command reception + uint8_t status; +}; + +/// HCI number of packet complete event structure +/*@TRACE*/ +struct hci_nb_cmp_pkts_evt +{ + /// number of handles + uint8_t nb_of_hdl; + /// connection handle + uint16_t conhdl[1]; + /// number of completed packets + uint16_t nb_comp_pkt[1]; +}; + +/// HCI data buffer overflow event structure +/*@TRACE*/ +struct hci_data_buf_ovflw_evt +{ + ///Link type + uint8_t link_type; +}; + +/// HCI Hardware Error Event parameters structure +/*@TRACE*/ +struct hci_hw_err_evt +{ + /// HW error code + uint8_t hw_code; +}; + +/// HCI encryption change event structure +struct hci_enc_change_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///Encryption enabled information + uint8_t enc_stat; +}; + +/// HCI encryption key refresh complete event structure +/*@TRACE + * hci_enc_key_refresh_evt = hci_enc_key_ref_cmp_evt */ +struct hci_enc_key_ref_cmp_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; +}; + +/// HCI Authenticated Payload Timeout Expired Event structure +/*@TRACE*/ +struct hci_auth_payl_to_exp_evt +{ + ///Connection handle + uint16_t conhdl; +}; + +/// HCI command complete event structure for create connection +/*@TRACE*/ +struct hci_con_cmp_evt +{ + /// Status + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///Bluetooth Device address + struct bd_addr bd_addr; + ///Link type + uint8_t link_type; + ///Encryption state + uint8_t enc_en; +}; + +/// HCI command complete event structure for qos setup +/*@TRACE*/ +struct hci_qos_setup_cmp_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///Flags + uint8_t flags; + ///Service type + uint8_t serv_type; + ///Token rate + uint32_t tok_rate; + ///Peak bandwidth + uint32_t pk_bw; + ///Latency + uint32_t lat; + ///Delay variation + uint32_t del_var; +}; + +/// HCI flow specification complete event parameters structure +/*@TRACE*/ +struct hci_flow_spec_cmp_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///Flags + uint8_t flags; + ///Flow direction + uint8_t flow_dir; + ///Service type + uint8_t serv_type; + ///Token rate + uint32_t tk_rate; + ///Token buffer size + uint32_t tk_buf_sz; + ///Peak bandwidth + uint32_t pk_bw; + ///Access latency + uint32_t acc_lat; +}; + +/// HCI role change event parameters structure +/*@TRACE*/ +struct hci_role_chg_evt +{ + ///Status + uint8_t status; + ///BD address + struct bd_addr bd_addr; + ///New role + uint8_t new_role; +}; + +/// HCI complete event structure for the read clock offset command +/*@TRACE*/ +struct hci_rd_clk_off_cmp_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///Clock offset + uint16_t clk_off_val; +}; + +/// HCI event structure for the flush occurred event +/*@TRACE*/ +struct hci_flush_occurred_evt +{ + ///Connection handle + uint16_t conhdl; +}; + +/// HCI max slot change event structure +/*@TRACE*/ +struct hci_max_slot_chg_evt +{ + ///Connection handle + uint16_t conhdl; + ///Max slot + uint8_t max_slot; +}; + +/// HCI sniff subrating event parameters structure +/*@TRACE*/ +struct hci_sniff_sub_evt +{ + ///Status. + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///Maximum transmit latency + uint16_t max_lat_tx; + ///Maximum receive latency + uint16_t max_lat_rx; + ///Minimum remote TO + uint16_t min_rem_to; + ///Minimum local TO + uint16_t min_loc_to; +}; + +/// HCI read remote extended features complete event parameters structure +/*@TRACE*/ +struct hci_rd_rem_ext_feats_cmp_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///page number + uint8_t pg_nb; + ///page number max + uint8_t pg_nb_max; + ///ext LMP features + struct features ext_feats; +}; + +/// HCI read remote extended features complete event parameters structure +/*@TRACE*/ +struct hci_rem_host_supp_feats_notif_evt +{ + ///BD address + struct bd_addr bd_addr; + ///ext lmp features + struct features ext_feats; +}; + +/// HCI command complete event structure for the read remote supported features command +/*@TRACE*/ +struct hci_rd_rem_supp_feats_cmp_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///Remote features + struct features rem_feats; +}; + +/// HCI command complete event structure for the read remote information version command +/*@TRACE*/ +struct hci_rd_rem_ver_info_cmp_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///LMP version + uint8_t vers; + ///Manufacturer name + uint16_t compid; + ///LMP subversion + uint16_t subvers; +}; + +/// HCI encryption change event structure +/*@TRACE*/ +struct hci_enc_chg_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///Encryption enabled information + uint8_t enc_stat; +}; + +/// HCI mode change event structure +/*@TRACE*/ +struct hci_mode_chg_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///Current mode + uint8_t cur_mode; + /// Interval + uint16_t interv; +}; + +/// HCI simple pairing complete event structure +/*@TRACE*/ +struct hci_sp_cmp_evt +{ + ///Status for command reception + uint8_t status; + ///Bluetooth Device address + struct bd_addr bd_addr; +}; + +/// HCI Authentication complete event structure +/*@TRACE*/ +struct hci_auth_cmp_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; +}; + +/// HCI change connection link key complete event structure +/*@TRACE*/ +struct hci_chg_con_lk_cmp_evt +{ + ///Status + uint8_t status; + ///Connection handle + uint16_t conhdl; +}; + +/// HCI encryption key refresh complete event structure +/*@TRACE*/ +struct hci_enc_key_refresh_cmp_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; +}; + +/// HCI master link key complete event structure +/*@TRACE*/ +struct hci_master_lk_cmp_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///Key flag + uint8_t key_flag; +}; +/// HCI synchronous link connection complete event structure +/*@TRACE*/ +struct hci_sync_con_cmp_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///BD address + struct bd_addr bd_addr; + ///Link type + uint8_t lk_type; + ///Transmit interval + uint8_t tx_int; + ///Retransmission window + uint8_t ret_win; + ///rx packet length + uint16_t rx_pkt_len; + ///tx packet length + uint16_t tx_pkt_len; + ///Air mode + uint8_t air_mode; + +}; + +/// HCI synchronous connection change event structure +/*@TRACE*/ +struct hci_sync_con_chg_evt +{ + ///Status for command reception + uint8_t status; + ///Synchronous Connection handle + uint16_t sync_conhdl; + ///Transmit interval + uint8_t tx_int; + ///Retransmission window + uint8_t ret_win; + ///rx packet length + uint16_t rx_pkt_len; + ///tx packet length + uint16_t tx_pkt_len; +}; + +/// HCI connection packet type change event structure +/*@TRACE*/ +struct hci_con_pkt_type_chg_evt +{ + ///Status for command reception + uint8_t status; + ///Synchronous Connection handle + uint16_t sync_conhdl; + ///Synchronous packet type + uint16_t pkt_type; +}; + +/// HCI link supervision timeout change event structure +/*@TRACE*/ +struct hci_link_supv_to_chg_evt +{ + ///Connection handle + uint16_t conhdl; + ///Link supervision timeout + uint16_t lsto_val; +}; + +/// HCI link key request event structure +/*@TRACE*/ +struct hci_lk_req_evt +{ + ///BD address + struct bd_addr bd_addr; +}; + +/// HCI encryption key refresh event structure +/*@TRACE*/ +struct hci_enc_key_refresh_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; +}; + +/// HCI connection request event structure +/*@TRACE*/ +struct hci_con_req_evt +{ + ///BD address + struct bd_addr bd_addr; + ///Class of device + struct devclass classofdev; + ///link type + uint8_t lk_type; +}; + +/// HCI quality of service violation event structure +/*@TRACE*/ +struct hci_qos_viol_evt +{ + ///Connection handle + uint16_t conhdl; +}; + +/// HCI io capability response event structure +/*@TRACE*/ +struct hci_io_cap_rsp_evt +{ + ///BdAddr + struct bd_addr bd_addr; + ///IO capability + uint8_t io_capa; + ///OOB data present + uint8_t oob_data_pres; + ///Authentication requirements + uint8_t auth_req; + +}; + +/// HCI IO capability response event structure +/*@TRACE*/ +struct hci_io_cap_req_evt +{ + ///BdAddr + struct bd_addr bd_addr; +}; + +/// HCI Return link keys event structure +/*@TRACE*/ +struct hci_return_link_keys_evt +{ + ///Number of Keys + uint8_t num_keys; + ///BdAddr + struct bd_addr bd_addr; + ///Key + struct ltk key; +}; + +/// HCI pin code request event structure +/*@TRACE*/ +struct hci_pin_code_req_evt +{ + ///BdAddr + struct bd_addr bd_addr; +}; + +/// HCI user passkey request event structure +/*@TRACE*/ +struct hci_user_passkey_req_evt +{ + ///BdAddr + struct bd_addr bd_addr; +}; + +/// HCI user passkey notification event structure +/*@TRACE*/ +struct hci_user_passkey_notif_evt +{ + ///BdAddr + struct bd_addr bd_addr; + ///Passkey + uint32_t passkey; +}; + +/// HCI remote OOB data request event structure +/*@TRACE*/ +struct hci_rem_oob_data_req_evt +{ + ///BdAddr + struct bd_addr bd_addr; +}; + +/// HCI user confirmation request event structure +/*@TRACE*/ +struct hci_user_cfm_req_evt +{ + ///BdAddr + struct bd_addr bd_addr; + ///Passkey + uint32_t passkey; +}; + +/// HCI keypress notification event structure +/*@TRACE*/ +struct hci_keypress_notif_evt +{ + ///BdAddr + struct bd_addr bd_addr; + ///type + uint8_t type; +}; + +/// HCI link key notification event structure +/*@TRACE*/ +struct hci_lk_notif_evt +{ + ///BdAddr + struct bd_addr bd_addr; + ///Key + struct ltk key; + ///type + uint8_t key_type; +}; + +/// HCI SAM status change event strucutre +struct hci_sam_status_change_evt +{ + ///Connection handle + uint16_t conhdl; + ///Local SAM index + uint8_t loc_idx; + ///Local SAM TX availability + uint8_t loc_tx_av; + ///Local SAM RX availability + uint8_t loc_rx_av; + ///Remote SAM index + uint8_t rem_idx; + ///Remote SAM TX availability + uint8_t rem_tx_av; + ///Remote SAM RX availability + uint8_t rem_rx_av; +}; + + +/* + * HCI LE META EVENTS PARAMETERS + **************************************************************************************** + */ + + +// LE event structures + +/// HCI command complete event structure for the Read Local Supported Features +/*@TRACE*/ +struct hci_le_rd_local_supp_feats_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + ///Local LE supported features + struct le_features feats; +}; + +/// HCI command complete event structure for the Read Advertising Channel Tx Power Command +/*@TRACE + * hci_le_rd_adv_chnl_tx_pw_cmd_cmp_evt = hci_rd_adv_chnl_tx_pw_cmd_cmp_evt*/ +struct hci_rd_adv_chnl_tx_pw_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + ///Advertising channel Tx power level + int8_t adv_tx_pw_lvl; +}; + +///HCI command complete event structure for the Read White List Size Command +/*@TRACE*/ +struct hci_le_rd_wlst_size_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + ///White List size + uint8_t wlst_size; +}; + +///HCI command complete event structure for the Read Buffer Size Command +/*@TRACE*/ +struct hci_le_rd_buff_size_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + ///ACL data packet length that can be sent from host to controller + uint16_t hc_data_pk_len; + ///Total number of ACL data packets that can be sent from host to controller. + uint8_t hc_tot_nb_data_pkts; +}; + +///HCI command complete event structure for LE Rand Command +/*@TRACE*/ +struct hci_le_rand_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + ///Random number + struct rand_nb nb; +}; + +///HCI command complete event structure for Read Supported States Command +/*@TRACE*/ +struct hci_le_rd_supp_states_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + ///LE supported states response + struct le_states states; +}; + +///HCI command complete event structure for Test End +/*@TRACE + * * hci_le_test_end_cmd_cmp_evt = hci_test_end_cmd_cmp_evt*/ +struct hci_test_end_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + ///Number of RX packets - null if TX test was the ended one + uint16_t nb_packet_received; +}; + +///HCI LE Encrypt complete event structure +/*@TRACE*/ +struct hci_le_enc_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + ///Encrypted data to return to command source. + uint8_t encrypted_data[ENC_DATA_LEN]; +}; + +#if BLE_EMB_PRESENT || BLE_HOST_PRESENT +///HCI LE advertising report event structure +/*@TRACE*/ +struct hci_le_adv_report_evt +{ + ///LE Subevent code + uint8_t subcode; + ///Number of advertising reports in this event + uint8_t nb_reports; + ///Advertising reports structures array + struct adv_report adv_rep[BLE_ADV_REPORTS_MAX]; +}; + +///HCI LE extended advertising report event structure +/*@TRACE*/ +struct hci_le_ext_adv_report_evt +{ + ///LE Subevent code + uint8_t subcode; + ///Number of advertising reports in this event + uint8_t nb_reports; + ///Paramaters for each report + struct ext_adv_report adv_rep[BLE_ADV_REPORTS_MAX]; +}; + +///HCI LE periodic advertising sync established event structure +/*@TRACE + * hci_le_periodic_adv_sync_est_evt = hci_le_per_adv_sync_est_evt*/ +struct hci_le_per_adv_sync_est_evt +{ + ///LE Subevent code + uint8_t subcode; + /// Status of the advertising sync + uint8_t status; + /// Sync Handle to be used + uint16_t sync_handle; + /// Advertising SID + uint8_t adv_sid; + ///Advertising address type: public/random + uint8_t adv_addr_type; + ///Advertising address value + struct bd_addr adv_addr; + /// Advertiser PHY (@enum le_phy_value) + uint8_t phy; + /// Advertising interval (Time=N*1.25ms) + uint16_t interval; + /// Advertiser clock accuracy (@see enum SCA) + uint8_t adv_ca; +}; + +///HCI LE periodic advertising report event structure +/*@TRACE + * hci_le_periodic_adv_report_evt = hci_le_per_adv_report_evt*/ +struct hci_le_per_adv_report_evt +{ + ///LE Subevent code + uint8_t subcode; + /// Sync Handle to be used + uint16_t sync_handle; + /// Tx Power + uint8_t tx_power; + /// RSSI + uint8_t rssi; + /// CTE type + uint8_t cte_type; + /// Data Status + uint8_t status; + ///Data length in advertising packet + uint8_t data_len; + ///Data of advertising packet + uint8_t data[PER_ADV_DATA_MAX_LEN]; +}; + +///HCI LE periodic advertising sync lost event structure +/*@TRACE + * hci_le_periodic_adv_sync_lost_evt = hci_le_per_adv_sync_lost_evt*/ +struct hci_le_per_adv_sync_lost_evt +{ + ///LE Subevent code + uint8_t subcode; + /// Sync Handle to be used + uint16_t sync_handle; +}; + +///HCI LE scan timeout event structure +/*@TRACE*/ +struct hci_le_scan_timeout_evt +{ + ///LE Subevent code + uint8_t subcode; +}; + +#endif //BLE_EMB_PRESENT || BLE_HOST_PRESENT + +/// HCI command complete event structure for Read Channel Map Command +/*@TRACE*/ +struct hci_le_rd_chnl_map_cmd_cmp_evt +{ + ///Status of command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///Channel map + struct le_chnl_map ch_map; +}; + +/// HCI command complete event structure for Long Term Key Request Reply Command +/*@TRACE*/ +struct hci_le_ltk_req_reply_cmd_cmp_evt +{ + ///Status of command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; +}; + +/// HCI command complete event structure for Long Term Key Request Negative Reply Command +/*@TRACE*/ +struct hci_le_ltk_req_neg_reply_cmd_cmp_evt +{ + ///Status of command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; +}; + +/// HCI command complete event structure for LE Read Suggested Default Data Length Command +/*@TRACE*/ +struct hci_le_rd_suggted_dft_data_len_cmd_cmp_evt +{ + ///Status of command reception + uint8_t status; + ///Host's suggested value for the Controller's maximum transmitted number of payload octets + uint16_t suggted_max_tx_octets; + ///Host's suggested value for the Controller's maximum packet transmission time + uint16_t suggted_max_tx_time; +}; +/// HCI command complete event structure for LE Read Maximum Data Length Command +/*@TRACE*/ +struct hci_le_rd_max_data_len_cmd_cmp_evt +{ + ///Status of command reception + uint8_t status; + ///Maximum number of payload octets that the local Controller supports for transmission + uint16_t suppted_max_tx_octets; + ///Maximum time, in microseconds, that the local Controller supports for transmission + uint16_t suppted_max_tx_time; + ///Maximum number of payload octets that the local Controller supports for reception + uint16_t suppted_max_rx_octets; + ///Maximum time, in microseconds, that the local Controller supports for reception + uint16_t suppted_max_rx_time; +}; + +/// HCI LE Read Peer Resolvable Address Command Complete Event +/*@TRACE*/ +struct hci_le_rd_peer_rslv_addr_cmd_cmp_evt +{ + ///Status + uint8_t status; + /// Peer Resolvable Address + struct bd_addr peer_rslv_addr; +}; + +/// HCI LE Read Local Resolvable Address Command Complete Event +/*@TRACE*/ +struct hci_le_rd_loc_rslv_addr_cmd_cmp_evt +{ + ///Status + uint8_t status; + /// Local Resolvable Address + struct bd_addr loc_rslv_addr; +}; + +/// HCI LE Read Resolving List Size Command Complete Event +/*@TRACE*/ +struct hci_le_rd_rslv_list_size_cmd_cmp_evt +{ + ///Status + uint8_t status; + /// Resolving List Size + uint8_t size; +}; + + +/// HCI write authenticated payload timeout command +/*@TRACE*/ +struct hci_wr_auth_payl_to_cmd +{ + ///Connection handle + uint16_t conhdl; + ///Authenticated payload timeout (N*10ms) + uint16_t auth_payl_to; +}; + +/// HCI command complete event structure for the Write Authenticated Payload Timeout Command +/*@TRACE*/ +struct hci_wr_auth_payl_to_cmd_cmp_evt +{ + /// Status of the command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; +}; + +/// HCI command complete event structure for HCI LE Connection Update Command +/*@TRACE*/ +struct hci_le_con_update_cmp_evt +{ + ///LE Subevent code + uint8_t subcode; + ///Status of received command + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///Connection interval value + uint16_t con_interval; + ///Connection latency value + uint16_t con_latency; + ///Supervision timeout + uint16_t sup_to; +}; + +/// HCI command complete event structure for create connection +/*@TRACE*/ +struct hci_le_con_cmp_evt +{ + ///LE Subevent code + uint8_t subcode; + ///Status of received command + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///Device role - 0=Master/ 1=Slave + uint8_t role; + ///Peer address type - 0=public/1=random + uint8_t peer_addr_type; + ///Peer address + struct bd_addr peer_addr; + ///Connection interval + uint16_t con_interval; + ///Connection latency + uint16_t con_latency; + ///Link supervision timeout + uint16_t sup_to; + ///Master clock accuracy + uint8_t clk_accuracy; +}; + +/// HCI LE read remote used feature command parameters structure +/*@TRACE*/ +struct hci_le_rd_rem_feats_cmd +{ + ///Connection handle + uint16_t conhdl; +}; + +/// HCI command complete event structure for HCI LE read remote feature Command +/*@TRACE*/ +struct hci_le_rd_rem_feats_cmd_cmp_evt +{ + ///LE Subevent code + uint8_t subcode; + ///Status of received command + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///Le Features + struct le_features le_feats; +}; + +/// HCI command structure for the read transmit power level command +/*@TRACE*/ +struct hci_rd_tx_pwr_lvl_cmd +{ + ///Connection handle + uint16_t conhdl; + ///Power Level type: current or maximum + uint8_t type; +}; + +/// HCI command complete event structure for the read transmit power level command +/*@TRACE*/ +struct hci_rd_tx_pwr_lvl_cmd_cmp_evt +{ + ///Status for command reception + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///Value of TX power level + uint8_t tx_pow_lvl; +}; + +/// HCI read remote information version command parameters structure +/*@TRACE*/ +struct hci_rd_rem_ver_info_cmd +{ + ///Connection handle + uint16_t conhdl; +}; + +/// HCI LE remote connection parameter request event +/*@TRACE*/ +struct hci_le_rem_con_param_req_evt +{ + ///LE Subevent code + uint8_t subcode; + ///Connection handle + uint16_t conhdl; + ///Interval_Min + uint16_t interval_min; + ///Interval_Max + uint16_t interval_max; + ///Latency + uint16_t latency; + ///Timeout + uint16_t timeout; +}; + + +/// HCI command complete event structure for enhance create connection +/*@TRACE*/ +struct hci_le_enh_con_cmp_evt +{ + ///LE Subevent code + uint8_t subcode; + ///Status of received command + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///Device role - 0=Master/ 1=Slave + uint8_t role; + ///Peer address type - 0=public/1=random + uint8_t peer_addr_type; + ///Peer address + struct bd_addr peer_addr; + ///Local Resolvable Private Address + struct bd_addr loc_rslv_priv_addr; + ///Peer Resolvable Private Address + struct bd_addr peer_rslv_priv_addr; + ///Connection interval + uint16_t con_interval; + ///Connection latency + uint16_t con_latency; + ///Link supervision timeout + uint16_t sup_to; + ///Master clock accuracy + uint8_t clk_accuracy; +}; + +struct hci_generate_dhkey_cmp_evt +{ + ///LE Subevent code + uint8_t subcode; + ///Status of received command + uint8_t status; + /// The 32 byte Diffie Helman Key + uint8_t dh_key[32]; +}; + +struct hci_rd_local_p256_public_key_cmp_evt +{ + ///LE Subevent code + uint8_t subcode; + ///Status of received command + uint8_t status; + /// The 32 byte Diffie Helman Key + uint8_t public_key[64]; + +}; + +#if BLE_EMB_PRESENT || BLE_HOST_PRESENT +/// HCI LE Direct Advertising Report Event +/*@TRACE*/ +struct hci_le_dir_adv_rep_evt +{ + ///LE Subevent code + uint8_t subcode; + ///Number of reports + uint8_t nb_reports; + ///Direct Advertising reports structures array + struct dir_adv_report adv_rep[BLE_ADV_REPORTS_MAX]; +}; +#endif //BLE_EMB_PRESENT || BLE_HOST_PRESENT + +/// Connected LE event +struct hci_le_con_evt +{ + ///LE Subevent code + uint8_t subcode; + ///Connection handle + uint16_t conhdl; +}; + +/// HCI command complete event structure for HCI LE read remote used feature Command +/*@TRACE*/ +struct hci_le_ltk_request_evt +{ + ///LE Subevent code + uint8_t subcode; + ///Connection handle + uint16_t conhdl; + ///Random number + struct rand_nb rand; + ///Encryption diversifier + uint16_t ediv; +}; + +/// HCI LE META event LE Data Length Change Event +/*@TRACE*/ +struct hci_le_data_len_chg_evt +{ + ///LE Subevent code + uint8_t subcode; + ///Connection handle + uint16_t conhdl; + ///The maximum number of payload octets in TX + uint16_t max_tx_octets; + ///The maximum time that the local Controller will take to TX + uint16_t max_tx_time; + ///The maximum number of payload octets in RX + uint16_t max_rx_octets; + ///The maximum time that the local Controller will take to RX + uint16_t max_rx_time; +}; + + +/// HCI Synchronization Train Received Event +/*@TRACE*/ +struct hci_sync_train_rec_evt +{ + /// Status + uint8_t status; + /// BD_ADDR + struct bd_addr bd_addr; + /// Clock_Offset (28 bits) - (CLKNslave - CLK) modulo 2^28 + uint32_t clock_offset; + /// AFH_Channel_Map + struct chnl_map afh_ch_map; + /// LT_ADDR + uint8_t lt_addr; + /// Next_Broadcast_Instant (28 bits) + uint32_t next_bcst_instant; + /// Connectionless_Slave_Broadcast_Interval (in slots) + uint16_t csb_int; + /// Service_Data + uint8_t service_data; +}; + +/// HCI Connectionless Slave Broadcast Receive Event +/*@TRACE*/ +struct hci_con_slv_bcst_rec_evt +{ + /// BD_ADDR + struct bd_addr bd_addr; + /// LT_ADDR + uint8_t lt_addr; + /// CLK (28 bits) + uint32_t clk; + /// Offset (28 bits) - (CLKNslave - CLK) modulo 2^28 + uint32_t offset; + /// Receive Status + uint8_t receive_status; + /// Fragment + uint8_t fragment; + /// Data_Length (in bytes) + uint8_t data_length; + /// Data + uint8_t data[__ARRAY_EMPTY]; +}; + +/// HCI Connectionless Slave Broadcast Timeout Event +/*@TRACE*/ +struct hci_con_slv_bcst_to_evt +{ + /// BD_ADDR + struct bd_addr bd_addr; + /// LT_ADDR + uint8_t lt_addr; +}; + +/// HCI Connectionless Slave Broadcast Channel Map Change Event +/*@TRACE*/ +struct hci_con_slv_bcst_ch_map_chg_evt +{ + /// Channel_Map + struct chnl_map ch_map; +}; + +/*@TRACE*/ +struct hci_le_gen_dhkey_cmp_evt +{ + ///LE Subevent code + uint8_t subcode; + uint8_t status; + uint8_t dh_key[32]; +}; + +/*@TRACE*/ +struct hci_le_rd_loc_p256_pub_key_cmp_evt +{ + ///LE Subevent code + uint8_t subcode; + uint8_t status; + t_public_key public_key; +}; + + +/// HCI command structure for the LE receiver test v3 command +/*@TRACE*/ +struct hci_le_rx_test_v3_cmd +{ + /// RX channel + uint8_t rx_channel; + /// PHY + uint8_t phy; + /// Modulation index + uint8_t mod_idx; + /// Expected CTE length (in 8us unit) + uint8_t exp_cte_len; + /// Expected CTE type (0: AOA | 1: AOD-1us | 2: AOD-2us) + uint8_t exp_cte_type; + /// Slot durations + uint8_t slot_dur; + /// Length of switching pattern (number of antenna IDs in the pattern) + uint8_t switching_pattern_len; + /// Antenna IDs + uint8_t antenna_id[MAX_SWITCHING_PATTERN_LEN]; +}; + +/// HCI command structure for the LE transmitter test v3 command +/*@TRACE*/ +struct hci_le_tx_test_v3_cmd +{ + /// TX channel + uint8_t tx_channel; + /// Length of test data + uint8_t test_data_len; + /// Packet payload + uint8_t pkt_payl; + /// PHY (@enum le_phy_value) + uint8_t phy; + /// CTE length (in 8us unit) + uint8_t cte_len; + /// CTE type (0: AOA | 1: AOD-1us | 2: AOD-2us) + uint8_t cte_type; + /// Length of switching pattern (number of antenna IDs in the pattern) + uint8_t switching_pattern_len; + /// Antenna IDs + uint8_t antenna_id[MAX_SWITCHING_PATTERN_LEN]; +}; + +/// HCI command structure for the LE set connectionless CTE transmit parameters command +/*@TRACE*/ +struct hci_le_set_conless_cte_tx_param_cmd +{ + /// Advertising handle + uint8_t adv_hdl; + /// CTE length (in 8us unit) + uint8_t cte_len; + /// CTE type (0: AOA | 1: AOD-1us | 2: AOD-2us) + uint8_t cte_type; + /// CTE count (number of CTEs to transmit in each periodic advertising interval, range 0x01 to 0x10) + uint8_t cte_count; + /// Length of switching pattern (number of antenna IDs in the pattern) + uint8_t switching_pattern_len; + /// Antenna IDs + uint8_t antenna_id[MAX_SWITCHING_PATTERN_LEN]; +}; + +/// HCI command structure for the LE set connectionless CTE transmit enable command +/*@TRACE*/ +struct hci_le_set_conless_cte_tx_en_cmd +{ + /// Advertising handle + uint8_t adv_hdl; + /// CTE enable + uint8_t cte_en; +}; + +/// HCI command structure for LE set connectionless IQ sampling enable command +/*@TRACE*/ +struct hci_le_set_conless_iq_sampl_en_cmd +{ + /// Sync handle + uint16_t sync_hdl; + /// Sampling enable + uint8_t sampl_en; + /// Slot durations (1: 1us | 2: 2us) + uint8_t slot_dur; + /// Max sampled CTEs + uint8_t max_sampl_cte; + /// Length of switching pattern + uint8_t switching_pattern_len; + /// Antenna IDs + uint8_t antenna_id[MAX_SWITCHING_PATTERN_LEN]; +}; + +/// HCI command structure for the LE set connection CTE receive parameters command +/*@TRACE*/ +struct hci_le_set_con_cte_rx_param_cmd +{ + /// Connection handle + uint16_t conhdl; + /// Sampling enable + uint8_t sampl_en; + /// Slot durations (1: 1us | 2: 2us) + uint8_t slot_dur; + /// Length of switching pattern (number of antenna IDs in the pattern) + uint8_t switching_pattern_len; + /// Antenna IDs + uint8_t antenna_id[MAX_SWITCHING_PATTERN_LEN]; +}; + +/// HCI command structure for the LE set connection CTE transmit parameters command +/*@TRACE*/ +struct hci_le_set_con_cte_tx_param_cmd +{ + /// Connection handle + uint16_t conhdl; + /// CTE types (bit0: AOA | bit1: AOD-1us | bit2: AOD-2us) + uint8_t cte_types; + /// Length of switching pattern (number of antenna IDs in the pattern) + uint8_t switching_pattern_len; + /// Antenna IDs + uint8_t antenna_id[MAX_SWITCHING_PATTERN_LEN]; +}; + +/// HCI command structure for the LE connection CTE request enable command +/*@TRACE*/ +struct hci_le_con_cte_req_en_cmd +{ + /// Connection handle + uint16_t conhdl; + /// Enable + uint8_t en; + /// CTE request interval (in number of connection events) + uint16_t cte_req_intv; + /// Requested CTE length (in 8us unit) + uint8_t req_cte_len; + /// Requested CTE type (0: AOA | 1: AOD-1us | 2: AOD-2us) + uint8_t req_cte_type; +}; + +/// HCI command structure for the LE connection CTE response enable command +/*@TRACE*/ +struct hci_le_con_cte_rsp_en_cmd +{ + /// Connection handle + uint16_t conhdl; + /// Enable + uint8_t en; +}; + +/// HCI command structure for LE set connectionless IQ sampling enable command complete event +/*@TRACE*/ +struct hci_le_set_conless_iq_sampl_en_cmd_cmp_evt +{ + /// Status + uint8_t status; + /// Sync handle + uint16_t sync_hdl; +}; + +/// HCI command structure for LE read antenna information command complete event +/*@TRACE*/ +struct hci_le_rd_antenna_inf_cmd_cmp_evt +{ + /// Status + uint8_t status; + /// Supported switching sampling rates + uint8_t supp_switching_sampl_rates; + /// Number of antennae + uint8_t antennae_num; + /// Max length of switching pattern (number of antenna IDs in the pattern) + uint8_t max_switching_pattern_len; + /// Max CTE length + uint8_t max_cte_len; +}; + +/// HCI command structure for the LE set periodic advertising receive enable command +/*@TRACE*/ +struct hci_le_set_per_adv_rec_en_cmd +{ + /// Sync handle + uint16_t sync_hdl; + /// Enable + uint8_t en; +}; + +/// HCI command structure for the LE set periodic advertising receive enable command +/*@TRACE*/ +struct hci_le_per_adv_sync_transf_cmd +{ + /// Connection handle + uint16_t conhdl; + /// Service data (value provided by the Host) + uint16_t serv_data; + /// Sync handle + uint16_t sync_hdl; +}; + +/// HCI command structure for the LE Periodic Advertising Set Info Transfer command +/*@TRACE*/ +struct hci_le_per_adv_set_info_transf_cmd +{ + /// Connection handle + uint16_t conhdl; + /// Service data (value provided by the Host) + uint16_t serv_data; + /// Advertising handle + uint8_t adv_hdl; +}; + +/// HCI command structure for the LE Set Periodic Advertising Sync Transfer Parameters command +/*@TRACE*/ +struct hci_le_set_per_adv_sync_transf_param_cmd +{ + /// Connection handle + uint16_t conhdl; + /// Mode (@see enum per_adv_sync_info_rec_mode) + uint8_t mode; + /// The number of periodic advertising packets that can be skipped after a successful receive + uint16_t skip; + /// Sync timeout (Time=N*10ms) + uint16_t sync_to; + /// CTE type (@see enum sync_cte_type) + uint8_t cte_type; +}; + +/// HCI command structure for the LE Set Default Periodic Advertising Sync Transfer Parameters command +/*@TRACE*/ +struct hci_le_set_dft_per_adv_sync_transf_param_cmd +{ + /// Mode (@see enum per_adv_sync_info_rec_mode) + uint8_t mode; + /// The number of periodic advertising packets that can be skipped after a successful receive + uint16_t skip; + /// Sync timeout (Time=N*10ms) + uint16_t sync_to; + /// CTE type (@see enum sync_cte_type) + uint8_t cte_type; +}; + +/// HCI command structure for the LE Periodic Advertising Sync Transfer Received event +/*@TRACE*/ +struct hci_le_per_adv_sync_transf_rec_evt +{ + /// LE Subevent code + uint8_t subcode; + /// Status + uint8_t status; + /// Connection handle + uint16_t conhdl; + /// Service data (value provided by the Host) + uint16_t serv_data; + /// Sync handle + uint16_t sync_hdl; + /// Advertising SID + uint8_t adv_sid; + ///Advertising address type: public/random + uint8_t adv_addr_type; + ///Advertising address value + struct bd_addr adv_addr; + /// Advertiser PHY (@enum le_phy_value) + uint8_t phy; + /// Advertising interval (Time=N*1.25ms) + uint16_t interval; + /// Advertiser clock accuracy (@see enum SCA) + uint8_t adv_ca; +}; + + +/* + * HCI VENDOR SPECIFIC COMMANDS PARAMETERS + **************************************************************************************** + */ + +/// Buffer structure +/*@TRACE*/ +struct buffer_tag +{ + /// length of buffer + uint8_t length; + /// data of 128 bytes length + uint8_t data[128]; +}; + +/// Common structure for Command Complete Event of HCI Debug Read Memory/Flash/Param complete event parameters - vendor specific +/*@TRACE + * hci_dbg_rd_mem_cmd_cmp_evt = hci_dbg_basic_rd_data_cmd_cmp_evt + * hci_dbg_rd_flash_cmd_cmp_evt = hci_dbg_basic_rd_data_cmd_cmp_evt + * hci_dbg_rd_par_cmd_cmp_evt = hci_dbg_basic_rd_data_cmd_cmp_evt + * */ +struct hci_dbg_basic_rd_data_cmd_cmp_evt +{ + ///Status + uint8_t status; + ///buffer structure to return + struct buffer_tag buf; +}; + +///HCI Debug read memory variable command parameters - vendor specific +/*@TRACE*/ +struct hci_dbg_rd_mem_cmd +{ + ///Start address to read + uint32_t start_addr; + ///Access size + uint8_t type; + ///Length to read + uint8_t length; +}; + +///HCI Debug write memory variable command parameters - vendor specific +/*@TRACE*/ +struct hci_dbg_wr_mem_cmd +{ + ///Start address to read + uint32_t start_addr; + ///Access size + uint8_t type; + ///buffer structure to return + struct buffer_tag buf; +}; + +///HCI Debug delete parameter command parameters - vendor specific +/*@TRACE + * hci_dbg_del_par_cmd = hci_dbg_del_param_cmd*/ +struct hci_dbg_del_param_cmd +{ + ///Parameter tag + uint16_t param_tag; +}; + +///HCI Debug erase flash command parameters - vendor specific +/*@TRACE*/ +struct hci_dbg_er_flash_cmd +{ + ///Flash type + uint8_t flashtype; + ///Start offset address + uint32_t startoffset; + ///Size to erase + uint32_t size; +}; + +///HCI Debug write flash command parameters - vendor specific +/*@TRACE*/ +struct hci_dbg_wr_flash_cmd +{ + ///Flash type + uint8_t flashtype; + ///Start offset address + uint32_t startoffset; + ///buffer structure + struct buffer_tag buf; +}; + +///HCI Debug read flash command parameters - vendor specific +/*@TRACE*/ +struct hci_dbg_rd_flash_cmd +{ + ///Flash type + uint8_t flashtype; + ///Start offset address + uint32_t startoffset; + ///Size to read + uint8_t size; +}; + +///HCI Debug read parameter command parameters - vendor specific +/*@TRACE*/ +struct hci_dbg_rd_par_cmd +{ + ///Parameter tag + uint16_t param_tag; +}; + +///HCI Debug read parameters command parameters - vendor specific +/*@TRACE*/ +struct hci_dbg_wr_par_cmd +{ + ///Parameter tag + uint16_t param_tag; + ///Structure buffer + struct buffer_tag buf; +}; + +#if CRYPTO_UT +///HCI Debug Test cryptographic functions command parameters - vendor specific +/*@TRACE*/ +struct hci_dbg_test_crypto_func_cmd +{ + /// Id of Function to be tested + uint8_t function; + /// Structure buffer + struct buffer_tag buf; +}; +#endif //CRYPTO_UT + +#if (BT_READ_PICONET_CLOCK) +struct hci_vs_rd_piconet_clock_cmd +{ + ///Connection handle of the link + uint16_t conhdl; + ///Pulse trigger management + uint8_t trig_pulse; + ///Clock type (0=native clock, 1=piconet clock of conhndl) + uint8_t clk_type; +}; + +struct hci_vs_rd_piconet_clock_cmd_cmp_evt +{ + /// Status + uint8_t status; + ///Connection handle of the link + uint16_t conhdl; + /// Local timestamp(position in half slots) + uint32_t loc_clk_hslt; + /// Local timestamp fractional part (in half us) + uint16_t loc_clk_hus; + /// Piconet timestamp(position in half slots) + uint32_t pic_clk_off_hslt; + /// Piconet bit offset (in half us) + uint16_t pic_bit_off_hus; +}; +#endif //(BT_READ_PICONET_CLOCK) + + +#if RW_DEBUG +///HCI Debug Test scheduling planner set function command parameters - vendor specific +/*@TRACE*/ +struct hci_dbg_test_sch_plan_set_cmd +{ + /// Activity identifier + uint32_t id; + /// Interval (in slots) + uint32_t interval; + /// Offset (in slots) + uint32_t offset; + /// Minimum duration (in slots) + uint32_t duration_min; + /// Maximum duration (in slots) + uint32_t duration_max; + /// Indicate activity is movable + bool mobility_level; +}; + +///HCI Debug Test scheduling planner set function command complete event parameters - vendor specific +/*@TRACE*/ +struct hci_dbg_test_sch_plan_set_cmd_cmp_evt +{ + /// Status + uint8_t status; + /// Activity identifier + uint32_t moved_id; +}; + +///HCI Debug Test scheduling planner remove function command parameters - vendor specific +/*@TRACE*/ +struct hci_dbg_test_sch_plan_rem_cmd +{ + /// Activity identifier + uint32_t id; +}; + +///HCI Debug Test scheduling planner check function command parameters - vendor specific +/*@TRACE*/ +struct hci_dbg_test_sch_plan_chk_cmd +{ + /// Activity identifier + uint32_t id; + /// Interval (in slots) + uint32_t interval; + /// Offset (in slots) + uint32_t offset; + /// Minimum duration (in slots) + uint32_t duration_min; +}; + +///HCI Debug Test scheduling planner request function command parameters - vendor specific +/*@TRACE*/ +struct hci_dbg_test_sch_plan_req_cmd +{ + /// Activity identifier + uint32_t id; + /// Minimum interval (in slots) + uint32_t interval_min; + /// Maximum interval (in slots) + uint32_t interval_max; + /// Minimum duration (in slots) + uint32_t duration_min; + /// Maximum duration (in slots) + uint32_t duration_max; + /// Period (in slots) + uint8_t period; +}; + +///HCI Debug Test scheduling planner request function command complete event parameters - vendor specific +/*@TRACE*/ +struct hci_dbg_test_sch_plan_req_cmd_cmp_evt +{ + /// Status + uint8_t status; + /// Interval (in slots) + uint32_t interval; + /// Minimum offset (in slots) + uint32_t offset_min; + /// Maximum offset (in slots) + uint32_t offset_max; +}; +#endif //RW_DEBUG + +///HCI Debug Read Kernel Statistics complete event parameters - vendor specific +/*@TRACE*/ +struct hci_dbg_rd_kernel_stats_cmd_cmp_evt +{ + ///Status + uint8_t status; + ///Max message sent + uint8_t max_msg_sent; + ///Max message saved + uint8_t max_msg_saved; + ///Max timer used + uint8_t max_timer_used; + ///Max heap used + uint16_t max_heap_used; + ///Max stack used + uint16_t max_stack_used; +}; + + +/// HCI Debug Read information about memory usage. - vendor specific +/*@TRACE*/ +struct hci_dbg_rd_mem_info_cmd_cmp_evt +{ + ///Status + uint8_t status; + /// memory size currently used into each heaps. + uint16_t mem_used[KERNEL_MEM_BLOCK_MAX]; + /// peak of memory usage measured + uint32_t max_mem_used; +}; + +///HCI Debug identify Flash command complete event parameters - vendor specific +/*@TRACE*/ +struct hci_dbg_id_flash_cmd_cmp_evt +{ + ///Status + uint8_t status; + ///Flash identity + uint8_t flash_id; +}; + +///HCI Debug RF Register read command +/*@TRACE*/ +struct hci_dbg_rf_reg_rd_cmd +{ + /// register address + uint16_t addr; +}; + +///HCI Debug RF Register read command complete event +/*@TRACE*/ +struct hci_dbg_rf_reg_rd_cmd_cmp_evt +{ + /// status + uint8_t status; + /// register address + uint16_t addr; + /// register value + uint32_t value; +}; + +///HCI Debug RF Register write command +/*@TRACE*/ +struct hci_dbg_rf_reg_wr_cmd +{ + /// register address + uint16_t addr; + /// register value + uint32_t value; +}; + +///HCI Debug RF Register write command complete event +/*@TRACE*/ +struct hci_dbg_rf_reg_wr_cmd_cmp_evt +{ + /// status + uint8_t status; + /// address + uint16_t addr; +}; + +///HCI Debug platform reset command parameters - vendor specific +/*@TRACE*/ +struct hci_dbg_plf_reset_cmd +{ + /// reason + uint8_t reason; +}; + +#if (RW_DEBUG && BT_EMB_PRESENT) +/// Discard LMP Packets +/*@TRACE*/ +struct hci_dbg_bt_send_lmp_cmd +{ + /// Connection handle + uint16_t conhdl; + ///buffer structure to return + struct buffer_tag buf; +}; + +/// Discard LMP Packets +/*@TRACE*/ +struct hci_dbg_bt_discard_lmp_en_cmd +{ + /// Connection handle + uint16_t conhdl; + /// Enable/Disable LMP discard (0: disable / 1: enable) + uint8_t enable; +}; + +/// Set local clock +/*@TRACE*/ +struct hci_dbg_set_local_clock_cmd +{ + /// Clock (in half-slots) + uint32_t clock; +}; +#endif //(RW_DEBUG && BT_EMB_PRESENT) + +#if (RW_WLAN_COEX) +///HCI Debug wlan coexistence command parameters - vendor specific +/*@TRACE*/ +struct hci_dbg_wlan_coex_cmd +{ + /// State + uint8_t state; +}; +#if (RW_WLAN_COEX_TEST) +///HCI Debug wlan coexistence test scenario command parameters - vendor specific +/*@TRACE*/ +struct hci_dbg_wlan_coextst_scen_cmd +{ + /// Scenario + uint32_t scenario; +}; +#endif //RW_WLAN_COEX_TEST +#endif //RW_WLAN_COEX + +#if (RW_MWS_COEX) +///HCI Debug mws coexistence command parameters - vendor specific +/*@TRACE*/ +struct hci_dbg_mws_coex_cmd +{ + /// State + uint8_t state; +}; +#if (RW_MWS_COEX_TEST) +///HCI Debug mws coexistence test scenario command parameters - vendor specific +/*@TRACE*/ +struct hci_dbg_mws_coextst_scen_cmd +{ + /// Scenario + uint32_t scenario; +}; +#endif //RW_MWS_COEX_TEST +#endif //RW_MWS_COEX + +#if BLE_IQ_GEN +///HCI Debug I&Q samples generator command parameters - vendor specific +/// Maximum number of supported antenna patterns +#define DBG_IQGEN_MAX_ANTENNA (8) +/*@TRACE*/ +struct hci_dbg_iqgen_cfg_cmd +{ + /// Number of antenna patterns + uint8_t nb_antenna; + /// Antenna switch/sample control + // bit[0]: 0: up-sweep; 1: up-down sweep (internal switching mode) + // bit[1]: 0: 1us intervals; 1: 2us intervals (internal switching mode) + // bit[2]: 0: internal switching mode; 1: baseband switching mode + uint8_t mode; + /// I/Q sample control + struct + { + /// I-sample control + /// 0: up-count from 0x01 + /// 1: down-count from 0xFF + /// 2: Fixed value 0x00 + /// 3: PRBS pattern + /// 4..0xFF: Fixed value + uint8_t i; + /// Q-sample control + /// 0: up-count from 0x01 + /// 1: down-count from 0xFF + /// 2: Fixed value 0x00 + /// 3: PRBS pattern + /// 4..0xFF: Fixed value + uint8_t q; + } iq_ctrl[DBG_IQGEN_MAX_ANTENNA]; +}; +#endif //BLE_IQ_GEN + +#if (BLE_ISO_MODE_0) +/// HCI VS Setup Audio Mode 0 channel command parameters +/*@TRACE*/ +struct hci_vs_setup_am0_chan_cmd +{ + /// Handle that identify an ACL link between a Master and a Slave device that is requesting + /// an Audio Mode 0 Channel (range 0x0000-0x0EFF) + uint16_t conhdl; + + // *** Data path settings *** + /// Host to Controller nominal data rate in octets per second + uint32_t tx_bandwidth; + /// Controller to Host nominal data rate in octets per second + uint32_t rx_bandwidth; + /// Host to Controller Data path type + /// 0x00 Disabled + /// 0x01 HCI + /// 0x02-0xFE Logical_Channel_Number. The meaning of the logical channels will be vendor specific. + /// 0xFF Test Mode + uint8_t tx_data_path; + /// Controller to Host Data path type + /// 0x00 Disabled + /// 0x01 HCI + /// 0x02-0xFE Logical_Channel_Number. The meaning of the logical channels will be vendor specific. + /// 0xFF Test Mode + uint8_t rx_data_path; + /// The number of bits in each unit of data received from the Host over the data transport. (Range 0x01 - 0xFB) + uint8_t tx_size; + /// The number of bits in each unit of data sent to the Host over the data transport. (Range 0x01 - 0xFB) + uint8_t rx_size; +}; + +/// Used to read the maximum size of the data portion of isochronous packets +/// no parameter on command, only need to specify returned parameters +struct hci_vs_setup_am0_chan_cmd_cmp_evt +{ + /// 0x00 - Request succeed ; 0x01-0xFF Failed reason + uint8_t status; + /// Handle that identify an ACL link between a Master and a Slave device that is requesting + /// an Audio Mode 0 Channel (range 0x0000-0x0EFF) + uint16_t conhdl; + /// Channel_Handle to be used to identify an Audio Mode 0 Channel (range 0x0000-0x0EFF) + uint16_t am0_hdl; +}; + + +/// Removes existing Audio Mode 0 channel command parameters +/*@TRACE*/ +struct hci_vs_remove_am0_chan_cmd +{ + /// Channel_Handles used to identify Audio Mode 0 Channel (range 0x0000-0x0EFF) + uint16_t am0_hdl; +}; + + +/// Used to Control the channel that will b.e part of an Audio Mode 0 Connection +/*@TRACE*/ +struct hci_vs_control_am0_chan_cmd +{ + /// Channel_Handles used to identify Audio Mode 0 Channel (range 0x0000-0x0EFF) + uint16_t am0_hdl; + /// Control if the stream should be Enabled (0x01) or Disabled (0x00) + uint8_t enable; + /// Control if slave audio source is enabled or not + uint8_t slv_src_enable; +}; + +/// HCI basic command complete event structure with AM0 Channel handle +/*@TRACE*/ +struct hci_vs_basic_am0_cmd_cmp_evt +{ + /// status + uint8_t status; + /// Channel_Handles used to identify Audio Mode 0 Channel (range 0x0000-0x0EFF) + uint16_t am0_hdl; +}; +#endif // (BLE_ISO_MODE_0) + + +///HCI Debug HW Register Read command parameters - vendor specific +/*@TRACE*/ +struct hci_dbg_ble_reg_rd_cmd +{ + /// register address + uint16_t reg_addr; +}; + +///HCI Debug HW Register write command parameters - vendor specific +/*@TRACE*/ +struct hci_dbg_ble_reg_wr_cmd +{ + /// register address + uint16_t reg_addr; + /// extra parameter + uint16_t reserved; + /// register value + uint32_t reg_value; +}; + +///HCI Debug HW Register Read Complete event parameters - vendor specific +/*@TRACE*/ +struct hci_dbg_ble_reg_rd_cmd_cmp_evt +{ + /// status + uint8_t status; + /// register address + uint16_t reg_addr; + /// register value + uint32_t reg_value; +}; + +///HCI Debug HW Register Write Complete event parameters - vendor specific +/*@TRACE*/ +struct hci_dbg_ble_reg_wr_cmd_cmp_evt +{ + /// status + uint8_t status; + /// register address + uint16_t reg_addr; +}; + +#if (BLE_EMB_PRESENT) +///HCI Vendor Specific Set Preferred Slave Latency command parameters +/*@TRACE*/ +struct hci_vs_set_pref_slave_latency_cmd +{ + /// Connection handle + uint16_t conhdl; + /// Preferred latency (in number of connection events) + uint16_t latency; +}; + +///HCI Vendor Specific Set Preferred Slave event duration command parameters +/*@TRACE*/ +struct hci_vs_set_pref_slave_evt_dur_cmd +{ + /// Connection handle + uint16_t conhdl; + /// Preferred event duration (N * 0.625 ms) + uint16_t duration; + /// Slave transmits a single packet per connection event (False/True) + uint8_t single_tx; +}; + +///HCI Debug LLC discard command parameters - vendor specific +/*@TRACE*/ +struct hci_dbg_llcp_discard_cmd +{ + /// Handle pointing to the connection for which LLCP commands have to be discarded + uint16_t conhdl; + /// Flag indicating if the discarding has to be enabled or disabled + uint8_t enable; +}; +#endif //BLE_EMB_PRESENT + +#if (RW_DEBUG) +/// HCI DBG Meta Event indicating a SW assertion +//TODO[AAL] exception (associated to HCI_DBG_EVT) +/*@TRACE*/ +struct hci_dbg_assert_evt +{ + ///DBG Subevent code + uint8_t subcode; + /// Assert type (warning/error) + //@trc_ref assert_type + uint8_t type; + /// Line number + uint32_t line; + /// Param0 + uint32_t param0; + /// Param1 + uint32_t param1; + /// File name + uint8_t file[__ARRAY_EMPTY]; +}; +#endif //(RW_DEBUG) + +#if(BLE_ISOGEN) +/// Event is used to provide statistics about ISO Gen +/*@TRACE*/ +struct hci_vs_isogen_stat_evt +{ + /// VS Subevent code + uint8_t subcode; + + /// ISO Handle of the isochronous channel (Range 0x0000-0x0EFF) + uint16_t iso_hdl; + + /// Statistics - Number of transmission attempts + uint32_t nb_tx; + /// Statistics - Number of transmission attempts that succeed + uint32_t nb_tx_ok; + /// Statistics - Number of Not granted packet packets + uint32_t nb_tx_not_granted; + + /// Statistics - Number of reception attempt + uint32_t nb_rx; + /// Statistics - Number of reception attempts that succeed + uint32_t nb_rx_ok; + /// Statistics - Number of Not granted packet packets + uint32_t nb_rx_not_granted; + /// Statistics - Number of wrongly received packet (invalid data) + uint32_t nb_rx_data_err; + /// Statistics - Number of CRC Errors + uint32_t nb_rx_crc_err; + /// Statistics - Number of SYNC Errors + uint32_t nb_rx_sync_err; + /// Statistics - Number of received empty packets + uint32_t nb_rx_empty; +}; +#endif // (BLE_ISOGEN) + + +/// HCI LE Read PHY command +/*@TRACE*/ +struct hci_le_rd_phy_cmd +{ + /// Connection Handle + uint16_t conhdl; +}; + +/// HCI LE Set Default PHY Command +/*@TRACE*/ +struct hci_le_set_dft_phy_cmd +{ + /// Preferred PHYS selection + uint8_t all_phys; + /// Preferred PHYS for TX + uint8_t tx_phys; + /// Preferred PHYS for RX + uint8_t rx_phys; +}; + +/// HCI LE Set PHY Command +/*@TRACE*/ +struct hci_le_set_phy_cmd +{ + /// Connection Handle + uint16_t conhdl; + /// Preferred PHYS selection + uint8_t all_phys; + /// Preferred PHYS for TX + uint8_t tx_phys; + /// Preferred PHYS for RX + uint8_t rx_phys; + /// PHY options + uint16_t phy_opt; +}; + +/// HCI LE Set Extended Advertising Parameters Command Complete Event +/*@TRACE*/ +struct hci_le_set_ext_adv_param_cmd_cmp_evt +{ + /// Status + uint8_t status; + /// Selected Tx power + int8_t sel_tx_pwr; +}; + +/// HCI LE Receiver Test v2 Command +/*@TRACE*/ +struct hci_le_rx_test_v2_cmd +{ + /// Reception channel value + uint8_t channel; + /// Reception PHY rate + uint8_t phys; + /// Modulation index + uint8_t modulation_idx; +}; + +/// HCI LE Transmitter Test v2 Command +/*@TRACE*/ +struct hci_le_tx_test_v2_cmd +{ + /// Transmit channel value + uint8_t channel; + /// Length of the data to be transmitted in a packet + uint8_t payload_length; + /// Type of the data contained in a packet + uint8_t payload_type; + /// Transmit PHY rate + uint8_t phys; +}; + +///HCI LE Set Advertising Set Random Address Command parameters structure +/*@TRACE*/ +struct hci_le_set_adv_set_rand_addr_cmd +{ + /// Advertising handle + uint8_t adv_hdl; + /// Advertising random address + struct bd_addr rand_addr; +}; + +///HCI LE Set Extended Advertising Parameters Command parameters structure +/*@TRACE*/ +struct hci_le_set_ext_adv_param_cmd +{ + /// Advertising handle + uint8_t adv_hdl; + /// Advertising event properties + uint16_t adv_evt_properties; + /// Primary advertising minimum interval + uint8_t prim_adv_intv_min[3]; + /// Primary advertising maximum interval + uint8_t prim_adv_intv_max[3]; + /// Primary advertising channel map + uint8_t prim_adv_chnl_map; + /// Own address type: public=0 / random=1 / rpa_or_pub=2 / rpa_or_rnd=3 + uint8_t own_addr_type; + /// Peer address type: public=0 / random=1 + uint8_t peer_addr_type; + /// Peer Bluetooth device address + struct bd_addr peer_addr; + /// Advertising filter policy + uint8_t adv_filt_policy; + /// Advertising Tx power + int8_t adv_tx_pwr; + /// Primary advertising PHY + uint8_t prim_adv_phy; + /// Secondary advertising max skip + uint8_t sec_adv_max_skip; + /// Secondary advertising PHY + uint8_t sec_adv_phy; + /// Advertising SID + uint8_t adv_sid; + /// Scan request notification enable + uint8_t scan_req_notif_en; +}; + +///HCI LE Set Extended Advertising Data Command parameters structure +/*@TRACE*/ +struct hci_le_set_ext_adv_data_cmd +{ + /// Advertising handle + uint8_t adv_hdl; + /** + * Operation + * 0x00 Intermediate fragment of fragmented extended advertising data + * 0x01 First fragment of fragmented extended advertising data + * 0x02 Last fragment of fragmented extended advertising data + * 0x03 Complete extended advertising data + * 0x04 [ID7300_r06] Unchanged data (just update the Advertising DID) + * All other values Reserved for future use + */ + uint8_t operation; + /** + * Fragment preference + * 0x00 The Controller may fragment all Host advertising data + * 0x01 The Controller should not fragment nor minimize fragmentation of Host advertising data + * All other values Reserved for future use + */ + uint8_t frag_pref; + /// Advertising Data Length (0-252 bytes) + uint8_t data_len; + /// Advertising data + uint8_t data[__ARRAY_EMPTY]; +}; + +///HCI LE Set Extended Scan Response Data Command parameters structure +/*@TRACE*/ +struct hci_le_set_ext_scan_rsp_data_cmd +{ + /// Advertising handle + uint8_t adv_hdl; + /** + * Operation + * 0x00 Intermediate fragment of fragmented extended advertising data + * 0x01 First fragment of fragmented extended advertising data + * 0x02 Last fragment of fragmented extended advertising data + * 0x03 Complete extended advertising data + * 0x04 [ID7300_r06] Unchanged data (just update the Advertising DID) + * All other values Reserved for future use + */ + uint8_t operation; + /** + * Fragment preference + * 0x00 The Controller may fragment all Host advertising data + * 0x01 The Controller should not fragment nor minimize fragmentation of Host advertising data + * All other values Reserved for future use + */ + uint8_t frag_pref; + /// Scan Response Data Length (0-252 bytes) + uint8_t data_len; + /// Advertising data + uint8_t data[__ARRAY_EMPTY]; +}; + +#if BLE_EMB_PRESENT || BLE_HOST_PRESENT +///HCI LE Set Extended Advertising Enable Command parameters structure +/*@TRACE*/ +struct hci_le_set_ext_adv_en_cmd +{ + /// Enable + uint8_t enable; + /// Number of sets (1 - 0x3F) + uint8_t nb_sets; + /// Advertising handle + uint8_t adv_hdl[BLE_ACTIVITY_MAX]; + /// Duration (N * 10 ms), 0x0000 No advertising duration. Advertising to continue until the Host disables it. + uint16_t duration[BLE_ACTIVITY_MAX]; + /// Maximum number of extended advertising events + uint8_t max_ext_adv_evt[BLE_ACTIVITY_MAX]; +}; +#endif //BLE_EMB_PRESENT || BLE_HOST_PRESENT + +///HCI LE Read Maximum Advertising Data Length Command complete event +/*@TRACE*/ +struct hci_le_rd_max_adv_data_len_cmd_cmp_evt +{ + /// Status + uint8_t status; + /// Maximum advertising data length + uint16_t max_adv_data_len; +}; + +///HCI LE Remove Advertising Set Command parameters structure +/*@TRACE + * hci_le_rmv_adv_set_cmd = hci_le_rem_adv_set_cmd*/ +struct hci_le_rem_adv_set_cmd +{ + /// Advertising handle + uint8_t adv_hdl; +}; + +///HCI LE Read Number of Supported Advertising Sets Command complete event +/*@TRACE*/ +struct hci_le_rd_nb_supp_adv_sets_cmd_cmp_evt +{ + /// Status + uint8_t status; + /// Number of supported advertising sets + uint8_t nb_supp_adv_sets; +}; + +///HCI LE Read Transmit Power Command complete event +/*@TRACE*/ +struct hci_le_rd_tx_pwr_cmd_cmp_evt +{ + /// Status + uint8_t status; + /// Minimum TX Power + uint8_t min_tx_pwr; + /// Maximum TX Power + uint8_t max_tx_pwr; +}; + +///HCI LE Read RF Path Compensation Command complete event +/*@TRACE*/ +struct hci_le_rd_rf_path_comp_cmd_cmp_evt +{ + /// Status + uint8_t status; + /// RF TX Path Compensation + int16_t tx_path_comp; + /// RF RX Path Compensation + int16_t rx_path_comp; +}; + +///HCI LE Write RF Path Compensation Command complete event +/*@TRACE*/ +struct hci_le_wr_rf_path_comp_cmd +{ + /// RF TX Path Compensation + int16_t tx_path_comp; + /// RF RX Path Compensation + int16_t rx_path_comp; +}; + +///HCI LE Set Periodic Advertising Parameters Command parameters structure +/*@TRACE*/ +struct hci_le_set_per_adv_param_cmd +{ + /// Advertising handle + uint8_t adv_hdl; + /// Minimum advertising interval for periodic advertising + uint16_t adv_intv_min; + /// Maximum advertising interval for periodic advertising + uint16_t adv_intv_max; + /// Advertising properties + uint16_t adv_prop; +}; + +///HCI LE Set Periodic Advertising Data Command parameters structure +/*@TRACE*/ +struct hci_le_set_per_adv_data_cmd +{ + /// Advertising handle + uint8_t adv_hdl; + /** + * Operation + * 0x00 Intermediate fragment of fragmented periodic advertising data + * 0x01 First fragment of fragmented periodic advertising data + * 0x02 Last fragment of fragmented periodic advertising data + * 0x03 Complete periodic advertising data + * All other values Reserved for future use + */ + uint8_t operation; + /// Advertising Data Length (0-252 bytes) + uint8_t data_len; + /// Advertising data + uint8_t data[__ARRAY_EMPTY]; +}; + +///HCI LE Set Periodic Advertising Enable Command parameters structure +/*@TRACE*/ +struct hci_le_set_per_adv_en_cmd +{ + /// Enable + uint8_t enable; + /// Advertising handle + uint8_t adv_hdl; +}; + +///HCI LE Advertising Set Terminated event +/*@TRACE + * hci_le_adv_set_terminated_evt = hci_le_adv_set_term_evt*/ +struct hci_le_adv_set_term_evt +{ + /// LE Subevent code + uint8_t subcode; + /// Status + uint8_t status; + /// Advertising handle + uint8_t adv_hdl; + /// Connection handle + uint16_t conhdl; + /// Num_Completed_Extended_Advertising_Events + uint8_t nb_cmp_ext_adv_evt; +}; + +///HCI LE Scan Request Received event +/*@TRACE*/ +struct hci_le_scan_req_rcvd_evt +{ + /// LE Subevent code + uint8_t subcode; + /// Advertising handle + uint8_t adv_hdl; + /// Scanner address type: public=0 / random=1 / rpa_or_pub=2 / rpa_or_rnd=3 + uint8_t scan_addr_type; + /// Scanner address + struct bd_addr scan_addr; +}; + +///HCI LE Read Periodic Advertiser List Size Command complete event +/*@TRACE*/ +struct hci_le_rd_per_adv_list_size_cmd_cmp_evt +{ + ///Status + uint8_t status; + /// Periodic Advertiser List Size + uint8_t size; +}; + +///HCI LE Channel Selection Algorithm event +/*@TRACE*/ +struct hci_le_ch_sel_algo_evt +{ + /// LE Subevent code + uint8_t subcode; + /// Connection handle + uint16_t conhdl; + /// Channel selection algorithm + uint8_t ch_sel_algo; +}; + +/// HCI LE read PHY Command complete event +/*@TRACE*/ +struct hci_le_rd_phy_cmd_cmp_evt +{ + ///Status of received command + uint8_t status; + /// Connection Handle + uint16_t conhdl; + /// Current configured PHY for TX + //@trc_ref le_phy_value + uint8_t tx_phy; + /// Current configured PHY for RX + //@trc_ref le_phy_value + uint8_t rx_phy; +}; + +/// HCI LE PHY Update Complete event +/*@TRACE*/ +struct hci_le_phy_upd_cmp_evt +{ + ///LE Subevent code + uint8_t subcode; + ///Status of received command + uint8_t status; + ///Connection handle + uint16_t conhdl; + ///TX phy chosen + //@trc_ref le_phy_value + uint8_t tx_phy; + ///RX phy chosen + //@trc_ref le_phy_value + uint8_t rx_phy; +}; + +///HCI LE Connectionless IQ Report event +/*@TRACE*/ +struct hci_le_conless_iq_report_evt +{ + /// LE Subevent code + uint8_t subcode; + /// Sync handle + uint16_t sync_hdl; + /// Data channel index + uint8_t channel_idx; + /// RSSI (in 0.1 dBm) + int16_t rssi; + /// RSSI antenna ID + uint8_t rssi_antenna_id; + /// CTE type (0: AOA | 1: AOD-1us | 2: AOD-2us) + uint8_t cte_type; + /// Slot durations (1: 1us | 2: 2us) + uint8_t slot_dur; + /// Packet status + uint8_t pkt_status; + /// paEventCounter + uint16_t pa_evt_cnt; + /// Sample_count + uint8_t sample_cnt; + /// I/Q sample + struct + { + /// I sample + int8_t i; + /// Q sample + int8_t q; + } iq_sample[MAX_SAMPLE_CNT]; +}; + +///HCI LE Connection IQ Report event +/*@TRACE*/ +struct hci_le_con_iq_report_evt +{ + /// LE Subevent code + uint8_t subcode; + /// Connection handle + uint16_t conhdl; + /// Rx PHY (@see enum le_phy_value) + uint8_t rx_phy; + /// Data channel index + uint8_t data_channel_idx; + /// RSSI (in 0.1 dBm) + int16_t rssi; + /// RSSI antenna ID + uint8_t rssi_antenna_id; + /// CTE type (0: AOA | 1: AOD-1us | 2: AOD-2us) + uint8_t cte_type; + /// Slot durations (1: 1us | 2: 2us) + uint8_t slot_dur; + /// Packet status + uint8_t pkt_status; + /// connEventCounter + uint16_t con_evt_cnt; + /// Sample_count + uint8_t sample_cnt; + /// I/Q sample + struct + { + /// I sample + int8_t i; + /// Q sample + int8_t q; + } iq_sample[MAX_SAMPLE_CNT]; +}; + +///HCI LE CTE Request Failed event +/*@TRACE*/ +struct hci_le_cte_req_failed_evt +{ + /// LE Subevent code + uint8_t subcode; + /// Status + uint8_t status; + /// Connection handle + uint16_t conhdl; +}; + +#if (!CFG_USE_BK_HOST) +#pragma pack(pop) +#endif + +/// @} COMMON_BT +#endif // COMMON_HCI_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/common/api/common_list.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/common/api/common_list.h new file mode 100755 index 0000000..82cca3a --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/common/api/common_list.h @@ -0,0 +1,302 @@ +/** + **************************************************************************************** + * + * @file common_list.h + * + * @brief Common list structures definitions + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef _COMMON_LIST_H_ +#define _COMMON_LIST_H_ + +/** + ***************************************************************************************** + * @defgroup COMMON_LIST List management + * @ingroup COMMON + * + * @brief List management. + * + * This module contains the list structures and handling functions. + * @{ + ***************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include // standard definition +#include // boolean definition +#include // for NULL and size_t +#include "rwip_config.h" // stack configuration +#include "compiler.h" // for __INLINE + + +/* + * DEFINES + **************************************************************************************** + */ + +/// structure of a list element header +/*@TRACE*/ +struct common_list_hdr +{ + /// Pointer to next common_list_hdr + struct common_list_hdr *next; +}; + +/// simplify type name of list element header +typedef struct common_list_hdr common_list_hdr_t; + +/// structure of a list +struct common_list +{ + /// pointer to first element of the list + struct common_list_hdr *first; + /// pointer to the last element + struct common_list_hdr *last; + + #if (KERNEL_PROFILING) + /// number of element in the list + uint32_t cnt; + /// max number of element in the list + uint32_t maxcnt; + /// min number of element in the list + uint32_t mincnt; + #endif //KERNEL_PROFILING +}; + +/// simplify type name of list +typedef struct common_list common_list_t; + +/* + * MACROS + **************************************************************************************** + */ +/// pop a specific element from the list +#define COMMON_LIST_POP_ELT(list, elt) common_list_extract(&(list), &(elt->hdr)); + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ +/** + **************************************************************************************** + * @brief Initialize a list to defaults values. + * + * @param list Pointer to the list structure. + **************************************************************************************** + */ +void common_list_init(struct common_list *list); + +/** + **************************************************************************************** + * @brief Construct a list of free elements representing a pool + * + * @param list Pointer to the list structure + * @param pool Pointer to the pool to be initialized + * @param elmt_size Size of one element of the pool + * @param elmt_cnt Nb of elements available in the pool + **************************************************************************************** + */ +void common_list_pool_init(struct common_list *list, + void *pool, + size_t elmt_size, + uint32_t elmt_cnt); + +/** + **************************************************************************************** + * @brief Add an element as last on the list. + * + * @param list Pointer to the list structure + * @param list_hdr Pointer to the header to add at the end of the list + * + **************************************************************************************** + */ +void common_list_push_back(struct common_list *list, struct common_list_hdr *list_hdr); + +/** + **************************************************************************************** + * @brief Append a sequence of elements at the end of a list. + * + * Note: the elements to append shall be linked together + * + * @param list Pointer to the list structure + * @param first_hdr Pointer to the first element to append + * @param last_hdr Pointer to the last element to append + **************************************************************************************** + */ +void common_list_push_back_sublist(struct common_list *list, struct common_list_hdr *first_hdr, struct common_list_hdr *last_hdr); + +/** + **************************************************************************************** + * @brief Add an element as first on the list. + * + * @param list Pointer to the list structure + * @param list_hdr Pointer to the header to add at the beginning of the list + **************************************************************************************** + */ +void common_list_push_front(struct common_list *list, struct common_list_hdr *list_hdr); + +/** + **************************************************************************************** + * @brief Extract the first element of the list. + * @param list Pointer to the list structure + * @return The pointer to the element extracted, and NULL if the list is empty. + **************************************************************************************** + */ +struct common_list_hdr *common_list_pop_front(struct common_list *list); + +/** + **************************************************************************************** + * @brief Search for a given element in the list, and extract it if found. + * + * @param list Pointer to the list structure + * @param list_hdr Element to extract + * + * @return true if the element is found in the list, false otherwise + **************************************************************************************** + */ +bool common_list_extract(struct common_list *list, struct common_list_hdr *list_hdr); + +/** + **************************************************************************************** + * @brief Extract an element when the previous element is known + * + * Note: the element to remove shall follow immediately the reference within the list + * + * @param list Pointer to the list structure + * @param elt_ref_hdr Pointer to the referenced element (NULL if element to extract is the first in the list) + * @param elt_to_rem_hdr Pointer to the element to be extracted + **************************************************************************************** + */ +void common_list_extract_after(struct common_list *list, struct common_list_hdr *elt_ref_hdr, struct common_list_hdr *elt_to_rem_hdr); + +/** + **************************************************************************************** + * @brief Extract a sub-list when the previous element is known + * + * Note: the elements to remove shall be linked together and follow immediately the reference element + * + * @param[in] list Pointer to the list structure + * @param[in] ref_hdr Pointer to the referenced element (NULL if first element to extract is first in the list) + * @param[in] last_hdr Pointer to the last element to extract () + **************************************************************************************** + */ +void common_list_extract_sublist(struct common_list *list, struct common_list_hdr *ref_hdr, struct common_list_hdr *last_hdr); + +/** + **************************************************************************************** + * @brief Searched a given element in the list. + * + * @param list Pointer to the list structure + * @param list_hdr Pointer to the searched element + * + * @return true if the element is found in the list, false otherwise + **************************************************************************************** + */ +bool common_list_find(struct common_list *list, struct common_list_hdr *list_hdr); + +/** + **************************************************************************************** + * @brief Merge two lists in a single one. + * + * This function appends the list pointed by list2 to the list pointed by list1. Once the + * merge is done, it empties list2. + * + * @param list1 Pointer to the destination list + * @param list2 Pointer to the list to append to list1 + **************************************************************************************** + */ +void common_list_merge(struct common_list *list1, struct common_list *list2); + +/** + **************************************************************************************** + * @brief Insert a given element in the list before the referenced element. + * + * @param list Pointer to the list structure + * @param elt_ref_hdr Pointer to the referenced element + * @param elt_to_add_hdr Pointer to the element to be inserted + * + * @return true if the element is found in the list, false otherwise + **************************************************************************************** + */ +void common_list_insert_before(struct common_list *list, + struct common_list_hdr *elt_ref_hdr, struct common_list_hdr *elt_to_add_hdr); + +/** + **************************************************************************************** + * @brief Insert a given element in the list after the referenced element. + * + * @param list Pointer to the list structure + * @param elt_ref_hdr Pointer to the referenced element + * @param elt_to_add_hdr Pointer to the element to be inserted + * + * @return true if the element is found in the list, false otherwise + **************************************************************************************** + */ +void common_list_insert_after(struct common_list *list, + struct common_list_hdr *elt_ref_hdr, struct common_list_hdr *elt_to_add_hdr); + + +/** + **************************************************************************************** + * @brief Count number of elements present in the list + * + * @param list Pointer to the list structure + * + * @return Number of elements present in the list + **************************************************************************************** + */ +uint16_t common_list_size(struct common_list *list); + +/** + **************************************************************************************** + * @brief Test if the list is empty. + * @param list Pointer to the list structure. + * @return true if the list is empty, false else otherwise. + **************************************************************************************** + */ +__INLINE bool common_list_is_empty(const struct common_list *const list) +{ + bool listempty; + listempty = (list->first == NULL); + return (listempty); +} + +/** + **************************************************************************************** + * @brief Pick the first element from the list without removing it. + * + * @param list Pointer to the list structure. + * + * @return First element address. Returns NULL pointer if the list is empty. + **************************************************************************************** + */ +__INLINE struct common_list_hdr *common_list_pick(const struct common_list *const list) +{ + return(list->first); +} + + +/** + **************************************************************************************** + * @brief Return following element of a list element. + * + * @param list_hdr Pointer to the list element. + * + * @return The pointer to the next element. + **************************************************************************************** + */ +__INLINE struct common_list_hdr *common_list_next(const struct common_list_hdr *const list_hdr) +{ + return(list_hdr->next); +} + +/// @} COMMON_LIST +#endif // _COMMON_LIST_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/common/api/common_llcp.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/common/api/common_llcp.h new file mode 100755 index 0000000..7817854 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/common/api/common_llcp.h @@ -0,0 +1,734 @@ +/** + **************************************************************************************** + * + * @file common_llcp.h + * + * @brief This file contains the LLCP Bluetooth defines, enumerations and structures + * definitions for use by all modules in RW stack. + * + * Copyright (C) RivieraWaves 2009-2015 + * + **************************************************************************************** + */ + +#ifndef COMMON_LLCP_H_ +#define COMMON_LLCP_H_ + +/** + **************************************************************************************** + * @addtogroup COMMON_BT + * @{ + **************************************************************************************** + */ + + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "common_bt.h" +/* + * DEFINES + **************************************************************************************** + */ + + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + +/// Control packet op_code +/*@TRACE*/ +enum common_llcp_op_code +{ + LL_CONNECTION_UPDATE_IND_OPCODE = 0x00, + LL_CHANNEL_MAP_IND_OPCODE = 0x01, + LL_TERMINATE_IND_OPCODE = 0x02, + LL_ENC_REQ_OPCODE = 0x03, + LL_ENC_RSP_OPCODE = 0x04, + LL_START_ENC_REQ_OPCODE = 0x05, + LL_START_ENC_RSP_OPCODE = 0x06, + LL_UNKNOWN_RSP_OPCODE = 0x07, + LL_FEATURE_REQ_OPCODE = 0x08, + LL_FEATURE_RSP_OPCODE = 0x09, + LL_PAUSE_ENC_REQ_OPCODE = 0x0A, + LL_PAUSE_ENC_RSP_OPCODE = 0x0B, + LL_VERSION_IND_OPCODE = 0x0C, + LL_REJECT_IND_OPCODE = 0x0D, + LL_SLAVE_FEATURE_REQ_OPCODE = 0x0E, + LL_CONNECTION_PARAM_REQ_OPCODE = 0x0F, + LL_CONNECTION_PARAM_RSP_OPCODE = 0x10, + LL_REJECT_EXT_IND_OPCODE = 0x11, + LL_PING_REQ_OPCODE = 0x12, + LL_PING_RSP_OPCODE = 0x13, + LL_LENGTH_REQ_OPCODE = 0x14, + LL_LENGTH_RSP_OPCODE = 0x15, + LL_PHY_REQ_OPCODE = 0x16, + LL_PHY_RSP_OPCODE = 0x17, + LL_PHY_UPDATE_IND_OPCODE = 0x18, + LL_MIN_USED_CHANNELS_IND_OPCODE = 0x19, + LL_CTE_REQ_OPCODE = 0x1A, + LL_CTE_RSP_OPCODE = 0x1B, + LL_PER_SYNC_IND_OPCODE = 0x1C, + LL_CLK_ACC_REQ_OPCODE = 0x1D, + LL_CLK_ACC_RSP_OPCODE = 0x1E, + + /// Opcode length + LL_OPCODE_MAX_OPCODE, + LL_OPCODE_DEBUG = 0xFF, +}; + +/// LLCP PDU lengths (including op_code) +enum common_llcp_length +{ + LL_CONNECTION_UPDATE_IND_LEN = 12, + LL_CHANNEL_MAP_IND_LEN = 8, + LL_TERMINATE_IND_LEN = 2, + LL_ENC_REQ_LEN = 23, + LL_ENC_RSP_LEN = 13, + LL_START_ENC_REQ_LEN = 1, + LL_START_ENC_RSP_LEN = 1, + LL_UNKNOWN_RSP_LEN = 2, + LL_FEATURE_REQ_LEN = 9, + LL_FEATURE_RSP_LEN = 9, + LL_PAUSE_ENC_REQ_LEN = 1, + LL_PAUSE_ENC_RSP_LEN = 1, + LL_VERSION_IND_LEN = 6, + LL_REJECT_IND_LEN = 2, + LL_SLAVE_FEATURE_REQ_LEN = 9, + LL_REJECT_EXT_IND_LEN = 3, + LL_CONNECTION_PARAM_REQ_LEN = 24, + LL_CONNECTION_PARAM_RSP_LEN = 24, + LL_PING_REQ_LEN = 1, + LL_PING_RSP_LEN = 1, + LL_LENGTH_REQ_LEN = 9, + LL_LENGTH_RSP_LEN = 9, + LL_PHY_REQ_LEN = 3, + LL_PHY_RSP_LEN = 3, + LL_PHY_UPDATE_IND_LEN = 5, + LL_MIN_USED_CHANNELS_IND_LEN = 3, + LL_CTE_REQ_LEN = 2, + LL_CTE_RSP_LEN = 1, + LL_PER_SYNC_IND_LEN = 35, + LL_CLK_ACC_REQ_LEN = 2, + LL_CLK_ACC_RSP_LEN = 2, + + LL_PDU_LENGTH_MAX = 35 +}; + +/// PDU lengths +enum common_pdu_length +{ + PDU_SCAN_REQ_LEN = 12, + PDU_CON_REQ_LEN = 34, + PDU_CON_RSP_LEN = 14, +}; + + +/// Bit field definitions for combination of advertising Set ID, advertiser address type and sleep clock accuracy in LL_PER_SYNC_IND +/// 7 6 5 4 3 2 1 0 +/// +----+----+----+-------+----+----+----+----+ +/// | SCA | AType | SID | +/// +----+----+----+-------+----+----+----+----+ +enum common_llcp_sid_atype_sca +{ + /// Advertising SID + LLCP_PER_SYNC_IND_SID_LSB = 0, + LLCP_PER_SYNC_IND_SID_MASK = (0x0F), + + /// Advertiser address type + LLCP_PER_SYNC_IND_ATYPE_POS = 4, + LLCP_PER_SYNC_IND_ATYPE_BIT = (0x10), + + /// Sleep clock accuracy (@see enum SCA) + LLCP_PER_SYNC_IND_SCA_LSB = 5, + LLCP_PER_SYNC_IND_SCA_MASK = (0xE0), +}; + +/* + * MESSAGES + **************************************************************************************** + */ + +/// LL_DEFAULT structure (for packet with no parameter) +/*@TRACE + * @NO_PAD +*/ +struct ll_default +{ + /// op_code + uint8_t op_code; +}; + +/// LL_CONNECTION_UPDATE_IND structure. +/*@TRACE + * @NO_PAD +*/ +struct ll_connection_update_ind +{ + /// op_code + uint8_t op_code; + /// window size (units of 1.25 ms) + uint8_t win_size; + /// window offset (units of 1.25 ms) + uint16_t win_off; + /// interval (units of 1.25 ms) + uint16_t interv; + /// connection latency (unit of connection event) + uint16_t latency; + /// link supervision timeout (unit of 10 ms) + uint16_t timeout; + /// instant (unit of connection event) + uint16_t instant; +}; + +/// LL_CHANNEL_MAP_IND structure. +/*@TRACE + * @NO_PAD +*/ +struct ll_channel_map_ind +{ + /// op_code + uint8_t op_code; + /// channel mapping + struct le_chnl_map ch_map; + /// instant + uint16_t instant; +}; + +/// LL_TERMINATE_IND structure. +/*@TRACE + * @NO_PAD +*/ +struct ll_terminate_ind +{ + /// op_code + uint8_t op_code; + /// termination code + uint8_t err_code; +}; + +/// LL_ENC_REQ structure. +/*@TRACE + * @NO_PAD +*/ +struct ll_enc_req +{ + /// op_code + uint8_t op_code; + /// random value + struct rand_nb rand; + /// ediv + uint16_t ediv; + /// skdm + struct sess_k_div_x skdm; + /// ivm + struct init_vect ivm; +}; + +/// LL_ENC_RSP structure. +/*@TRACE + * @NO_PAD +*/ +struct ll_enc_rsp +{ + /// op_code + uint8_t op_code; + /// skds + struct sess_k_div_x skds; + /// ivs + struct init_vect ivs; +}; + +/// LL_START_ENC_REQ structure. +/*@TRACE + * @NO_PAD +*/ +struct ll_start_enc_req +{ + /// op_code + uint8_t op_code; +}; + +/// LL_START_ENC_RSP structure. +/*@TRACE + * @NO_PAD +*/ +struct ll_start_enc_rsp +{ + /// op_code + uint8_t op_code; +}; + +/// LL_UNKNOWN_RSP structure. +/*@TRACE + * @NO_PAD +*/ +struct ll_unknown_rsp +{ + /// op_code + uint8_t op_code; + /// unknown type + uint8_t unk_type; +}; + +/// LL_FEATURE_REQ structure. +/*@TRACE + * @NO_PAD +*/ +struct ll_feature_req +{ + /// op_code + uint8_t op_code; + /// le features + struct le_features feats; +}; + + +/// LL_FEATURE_RSP structure. +/*@TRACE + * @NO_PAD +*/ +struct ll_feature_rsp +{ + /// op_code + uint8_t op_code; + /// le features + struct le_features feats; +}; + +/// LL_PAUSE_ENC_REQ structure. +/*@TRACE + * @NO_PAD +*/ +struct ll_pause_enc_req +{ + /// op_code + uint8_t op_code; +}; + +/// LL_PAUSE_ENC_RSP structure. +/*@TRACE + * @NO_PAD +*/ +struct ll_pause_enc_rsp +{ + /// op_code + uint8_t op_code; +}; + +/// LL_VERSION_IND structure +/*@TRACE + * @NO_PAD +*/ +struct ll_version_ind +{ + /// op_code + uint8_t op_code; + /// version + uint8_t vers; + /// company id + uint16_t compid; + /// sub version + uint16_t subvers; +}; + +/// LL_REJECT_IND structure. +/*@TRACE + * @NO_PAD +*/ +struct ll_reject_ind +{ + /// op_code + uint8_t op_code; + /// reject reason + uint8_t err_code; +}; + +/// LL_SLAVE_FEATURE_REQ structure. +/*@TRACE + * @NO_PAD +*/ +struct ll_slave_feature_req +{ + /// op_code + uint8_t op_code; + /// le features + struct le_features feats; +}; + +/// LL_CONNECTION_PARAM_REQ structure. +/*@TRACE + * @NO_PAD +*/ +struct ll_connection_param_req +{ + /// op_code + uint8_t op_code; + /// minimum value of connInterval (units of 1.25 ms) + uint16_t interval_min; + /// maximum value of connInterval (units of 1.25 ms) + uint16_t interval_max; + /// connSlaveLatency value (unit of connection event) + uint16_t latency; + /// connSupervisionTimeout value (unit of 10 ms) + uint16_t timeout; + /// preferred periodicity (units of 1.25 ms) + uint8_t pref_period; + /// ReferenceConnEventCount (unit of connection event) + uint16_t ref_con_event_count; + /// Offset0 (units of 1.25 ms) + uint16_t offset0; + /// Offset1 (units of 1.25 ms) + uint16_t offset1; + /// Offset2 (units of 1.25 ms) + uint16_t offset2; + /// Offset3 (units of 1.25 ms) + uint16_t offset3; + /// Offset4 (units of 1.25 ms) + uint16_t offset4; + /// Offset5 (units of 1.25 ms) + uint16_t offset5; +}; + +/// LL_CONNECTION_PARAM_RSP structure. +/*@TRACE + * @NO_PAD +*/ +struct ll_connection_param_rsp +{ + /// op_code + uint8_t op_code; + /// minimum value of connInterval (units of 1.25 ms) + uint16_t interval_min; + /// maximum value of connInterval (units of 1.25 ms) + uint16_t interval_max; + /// connSlaveLatency value (unit of connection event) + uint16_t latency; + /// connSupervisionTimeout value (unit of 10 ms) + uint16_t timeout; + /// preferred periodicity (units of 1.25 ms) + uint8_t pref_period; + /// ReferenceConnEventCount (unit of connection event) + uint16_t ref_con_event_count; + /// Offset0 (units of 1.25 ms) + uint16_t offset0; + /// Offset1 (units of 1.25 ms) + uint16_t offset1; + /// Offset2 (units of 1.25 ms) + uint16_t offset2; + /// Offset3 (units of 1.25 ms) + uint16_t offset3; + /// Offset4 (units of 1.25 ms) + uint16_t offset4; + /// Offset5 (units of 1.25 ms) + uint16_t offset5; +}; + +/// LL_REJECT_EXT_IND structure. +/*@TRACE + * @NO_PAD +*/ +struct ll_reject_ext_ind +{ + /// op_code + uint8_t op_code; + /// rejected op_code + uint8_t rej_op_code; + /// reject reason + uint8_t err_code; +}; + +/// LL_PING_REQ structure. +/*@TRACE + * @NO_PAD +*/ +struct ll_ping_req +{ + /// op_code + uint8_t op_code; +}; + +/// LL_PING_RSP structure. +/*@TRACE + * @NO_PAD +*/ +struct ll_ping_rsp +{ + /// op_code + uint8_t op_code; +}; + +/// LL_LENGTH_REQ structure. +/*@TRACE + * @NO_PAD +*/ +struct ll_length_req +{ + /// op_code + uint8_t op_code; + /// The max size in reception (unit of byte) + uint16_t max_rx_octets; + /// The max time in reception (unit of microsecond) + uint16_t max_rx_time; + /// The max size in transmission (unit of byte) + uint16_t max_tx_octets; + /// The max time in transmission (unit of microsecond) + uint16_t max_tx_time; +}; + +/// LL_LENGTH_RSP structure. +/*@TRACE + * @NO_PAD +*/ +struct ll_length_rsp +{ + /// op_code + uint8_t op_code; + /// The max size in reception (unit of byte) + uint16_t max_rx_octets; + /// The max time in reception (unit of microsecond) + uint16_t max_rx_time; + /// The max size in transmission (unit of byte) + uint16_t max_tx_octets; + /// The max time in transmission (unit of microsecond) + uint16_t max_tx_time; +}; +/// LL_PHY_REQ structure. +/*@TRACE + * @NO_PAD +*/ +struct ll_phy_req +{ + /// op_code + uint8_t op_code; + /// Tx phy selection + uint8_t tx_phys; + /// Rx phy selection + uint8_t rx_phys; +}; + +/// LL_PHY_RSP structure. +/*@TRACE + * @NO_PAD +*/ +struct ll_phy_rsp +{ + /// op_code + uint8_t op_code; + /// Tx phy selection + uint8_t tx_phys; + /// Rx phy selection + uint8_t rx_phys; +}; + +/// LL_PHY_UPDATE_IND structure. +/*@TRACE + * @NO_PAD +*/ +struct ll_phy_update_ind +{ + /// op_code + uint8_t op_code; + /// master to slave phy selected + uint8_t m_to_s_phy; + /// slave to master phy selected + uint8_t s_to_m_phy; + /// Instant + uint16_t instant; +}; + +/// LL_MIN_USED_CHANNELS_IND structure. +/*@TRACE + * @NO_PAD +*/ +struct ll_min_used_channels_ind +{ + /// op_code + uint8_t op_code; + /// PHY(s) for which the slave has a minimum number of used channels requirement + uint8_t phys; + /// minimum number of channels to be used on the specified PHY + uint8_t min_used_ch; +}; + +/** + * CTE length and type bit field definition + * + * | 5 bits | 1b | 2 bits | + * | MinCTELenReq | RFU | CTETypeReq | + * + * - MinCTELenReq: minimum CTE length (x 8us) + * - CTETypeReq: 0-AoA, 1-AoD_1us, 2-AoD_2us, 3-RFU + */ +enum cte_len_type +{ + CTE_TYPE_REQ_MASK = 0xC0, + CTE_TYPE_REQ_LSB = 6, + + MIN_CTE_LEN_REQ_MASK = 0x1F, + MIN_CTE_LEN_REQ_LSB = 0, +}; + +/// LL_CTE_REQ structure. +/*@TRACE + * @NO_PAD +*/ +struct ll_cte_req +{ + /// op_code + uint8_t op_code; + /// CTE length and type (@see enum cte_len_type) + uint8_t cte_len_type; +}; + +/// LL_PER_SYNC_IND structure. +/*@TRACE + * @NO_PAD +*/ +struct ll_per_sync_ind +{ + /// op_code + uint8_t op_code; + /// ID (provided by the Host) + uint16_t id; + /// Sync Info (TODO ref definition or spec) + uint8_t sync_info[18]; + /// Connection event counter + uint16_t con_evt_cnt; + /// Last periodic advertising event counter + uint16_t last_pa_evt_cnt; + /// Advertising Set ID, advertiser address type and sleep clock accuracy + uint8_t sid_atype_sca; + /// Periodic advertising PHY (@see enum le_phy_mask) + uint8_t phy; + /// Periodic advertiser address + struct bd_addr adva; + /// Sync Connection event counter + uint16_t sync_con_evt_cnt; +}; + +/// LL_CLK_ACC_REQ structure. +/*@TRACE + * @NO_PAD +*/ +struct ll_clk_acc_req +{ + /// op_code + uint8_t op_code; + /// SCA (@see enum SCA) + uint8_t sca; +}; + +/// LL_CLK_ACC_RSP structure. +/*@TRACE + * @NO_PAD +*/ +struct ll_clk_acc_rsp +{ + /// op_code + uint8_t op_code; + /// SCA (@see enum SCA) + uint8_t sca; +}; + +/// LLCP pdu format +/*@TRACE + @trc_ref common_llcp_op_code + */ +union llcp_pdu +{ + /// op_code + uint8_t op_code; + + //@trc_union op_code == LL_CONNECTION_UPDATE_IND_OPCODE + struct ll_connection_update_ind con_update_ind; + + //@trc_union op_code == LL_CHANNEL_MAP_IND_OPCODE + struct ll_channel_map_ind channel_map_ind; + + //@trc_union op_code == LL_TERMINATE_IND_OPCODE + struct ll_terminate_ind terminate_ind; + + //@trc_union op_code == LL_ENC_REQ_OPCODE + struct ll_enc_req enc_req; + + //@trc_union op_code == LL_ENC_RSP_OPCODE + struct ll_enc_rsp enc_rsp; + + //@trc_union op_code == LL_START_ENC_REQ_OPCODE + struct ll_start_enc_req start_enc_req; + + //@trc_union op_code == LL_START_ENC_RSP_OPCODE + struct ll_start_enc_rsp start_enc_rsp; + + //@trc_union op_code == LL_UNKNOWN_RSP_OPCODE + struct ll_unknown_rsp unknown_rsp; + + //@trc_union op_code == LL_FEATURE_REQ_OPCODE + struct ll_feature_req feats_req; + + //@trc_union op_code == LL_FEATURE_RSP_OPCODE + struct ll_feature_rsp feats_rsp; + + //@trc_union op_code == LL_PAUSE_ENC_REQ_OPCODE + struct ll_pause_enc_req pause_enc_req; + + //@trc_union op_code == LL_PAUSE_ENC_RSP_OPCODE + struct ll_pause_enc_rsp pause_enc_rsp; + + //@trc_union op_code == LL_VERSION_IND_OPCODE + struct ll_version_ind vers_ind; + + //@trc_union op_code == LL_REJECT_IND_OPCODE + struct ll_reject_ind reject_ind; + + //@trc_union op_code == LL_SLAVE_FEATURE_REQ_OPCODE + struct ll_slave_feature_req slave_feature_req; + + //@trc_union op_code == LL_CONNECTION_PARAM_REQ_OPCODE + struct ll_connection_param_req con_param_req; + + //@trc_union op_code == LL_CONNECTION_PARAM_RSP_OPCODE + struct ll_connection_param_rsp con_param_rsp; + + //@trc_union op_code == LL_REJECT_EXT_IND_OPCODE + struct ll_reject_ext_ind reject_ind_ext; + + //@trc_union op_code == LL_PING_REQ_OPCODE + struct ll_ping_req ping_req; + + //@trc_union op_code == LL_PING_RSP_OPCODE + struct ll_ping_rsp ping_rsp; + + //@trc_union op_code == LL_LENGTH_REQ_OPCODE + struct ll_length_req length_req; + + //@trc_union op_code == LL_LENGTH_RSP_OPCODE + struct ll_length_rsp length_rsp; + + //@trc_union op_code == LL_PHY_REQ_OPCODE + struct ll_phy_req phy_req; + + //@trc_union op_code == LL_PHY_RSP_OPCODE + struct ll_phy_rsp phy_rsp; + + //@trc_union op_code == LL_PHY_UPDATE_IND_OPCODE + struct ll_phy_update_ind phy_upd_ind; + + //@trc_union op_code == LL_MIN_USED_CHANNELS_IND_OPCODE + struct ll_min_used_channels_ind min_used_channels_ind; + + //@trc_union op_code == LL_CLK_ACC_REQ_OPCODE + struct ll_clk_acc_req clk_acc_req; + + //@trc_union op_code == LL_CLK_ACC_RSP_OPCODE + struct ll_clk_acc_rsp clk_acc_rsp; + + //@trc_union op_code == LL_PER_SYNC_IND_OPCODE + struct ll_per_sync_ind per_sync_ind; +}; + +/// @} COMMON_BT +#endif // COMMON_LLCP_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/common/api/common_lmp.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/common/api/common_lmp.h new file mode 100755 index 0000000..f8346b9 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/common/api/common_lmp.h @@ -0,0 +1,1566 @@ +/** + **************************************************************************************** + * + * @file common_lmp.h + * + * @brief This file contains the HCI Bluetooth defines, enumerations and structures + * definitions for use by all modules in RW stack. + * + * Copyright (C) RivieraWaves 2009-2015 + * + **************************************************************************************** + */ + +#ifndef COMMON_LMP_H_ +#define COMMON_LMP_H_ + +/** + **************************************************************************************** + * @addtogroup COMMON_BT + * @{ + **************************************************************************************** + */ + + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "common_bt.h" +/* + * DEFINES + **************************************************************************************** + */ + +/// LMP Opcodes +/*@TRACE*/ +enum common_lmp_opcode +{ + LMP_NAME_REQ_OPCODE = 1 , + LMP_NAME_RES_OPCODE = 2 , + LMP_ACCEPTED_OPCODE = 3 , + LMP_NOT_ACCEPTED_OPCODE = 4 , + LMP_CLK_OFF_REQ_OPCODE = 5 , + LMP_CLK_OFF_RES_OPCODE = 6 , + LMP_DETACH_OPCODE = 7 , + LMP_INRAND_OPCODE = 8 , + LMP_COMBKEY_OPCODE = 9 , + LMP_UNITKEY_OPCODE = 10 , + LMP_AURAND_OPCODE = 11 , + LMP_SRES_OPCODE = 12 , + LMP_TEMPRAND_OPCODE = 13 , + LMP_TEMPKEY_OPCODE = 14 , + LMP_ENC_MODE_REQ_OPCODE = 15 , + LMP_ENC_KEY_SIZE_REQ_OPCODE = 16 , + LMP_START_ENC_REQ_OPCODE = 17 , + LMP_STOP_ENC_REQ_OPCODE = 18 , + LMP_SWITCH_REQ_OPCODE = 19 , + LMP_HOLD_OPCODE = 20 , + LMP_HOLD_REQ_OPCODE = 21 , + LMP_SNIFF_REQ_OPCODE = 23 , + LMP_UNSNIFF_REQ_OPCODE = 24 , + LMP_PARK_REQ_OPCODE = 25 , + LMP_SET_BSWIN_OPCODE = 27 , + LMP_MODIF_BEACON_OPCODE = 28 , + LMP_UNPARK_BD_REQ_OPCODE = 29 , + LMP_UNPARK_PM_REQ_OPCODE = 30 , + LMP_INCR_PWR_REQ_OPCODE = 31 , + LMP_DECR_PWR_REQ_OPCODE = 32 , + LMP_MAX_PWR_OPCODE = 33 , + LMP_MIN_PWR_OPCODE = 34 , + LMP_AUTO_RATE_OPCODE = 35 , + LMP_PREF_RATE_OPCODE = 36 , + LMP_VER_REQ_OPCODE = 37 , + LMP_VER_RES_OPCODE = 38 , + LMP_FEATS_REQ_OPCODE = 39 , + LMP_FEATS_RES_OPCODE = 40 , + LMP_QOS_OPCODE = 41 , + LMP_QOS_REQ_OPCODE = 42 , + LMP_SCO_LINK_REQ_OPCODE = 43 , + LMP_RMV_SCO_LINK_REQ_OPCODE = 44 , + LMP_MAX_SLOT_OPCODE = 45 , + LMP_MAX_SLOT_REQ_OPCODE = 46 , + LMP_TIMING_ACCU_REQ_OPCODE = 47 , + LMP_TIMING_ACCU_RES_OPCODE = 48 , + LMP_SETUP_CMP_OPCODE = 49 , + LMP_USE_SEMI_PERM_KEY_OPCODE = 50 , + LMP_HOST_CON_REQ_OPCODE = 51 , + LMP_SLOT_OFF_OPCODE = 52 , + LMP_PAGE_MODE_REQ_OPCODE = 53 , + LMP_PAGE_SCAN_MODE_REQ_OPCODE = 54 , + LMP_SUPV_TO_OPCODE = 55 , + LMP_TEST_ACTIVATE_OPCODE = 56 , + LMP_TEST_CTRL_OPCODE = 57 , + LMP_ENC_KEY_SIZE_MASK_REQ_OPCODE = 58 , + LMP_ENC_KEY_SIZE_MASK_RES_OPCODE = 59 , + LMP_SET_AFH_OPCODE = 60 , + LMP_ENCAPS_HDR_OPCODE = 61 , + LMP_ENCAPS_PAYL_OPCODE = 62 , + LMP_SP_CFM_OPCODE = 63 , + LMP_SP_NB_OPCODE = 64 , + LMP_DHKEY_CHK_OPCODE = 65 , + LMP_PAUSE_ENC_AES_REQ_OPCODE = 66 , + LMP_ESC1_OPCODE = 124, + LMP_ESC2_OPCODE = 125, + LMP_ESC3_OPCODE = 126, + LMP_ESC4_OPCODE = 127, +}; + +/// LMP Escape 4 Extended Opcodes +enum common_lmp_ext_opcode +{ + LMP_ACCEPTED_EXT_EXTOPCODE = 1, + LMP_NOT_ACCEPTED_EXT_EXTOPCODE = 2, + LMP_FEATS_REQ_EXT_EXTOPCODE = 3, + LMP_FEATS_RES_EXT_EXTOPCODE = 4, + LMP_CLK_ADJ_EXTOPCODE = 5, + LMP_CLK_ADJ_ACK_EXTOPCODE = 6, + LMP_CLK_ADJ_REQ_EXTOPCODE = 7, + LMP_PKT_TYPE_TBL_REQ_EXTOPCODE = 11, + LMP_ESCO_LINK_REQ_EXTOPCODE = 12, + LMP_RMV_ESCO_LINK_REQ_EXTOPCODE = 13, + LMP_CH_CLASS_REQ_EXTOPCODE = 16, + LMP_CH_CLASS_EXTOPCODE = 17, + LMP_SSR_REQ_EXTOPCODE = 21, + LMP_SSR_RES_EXTOPCODE = 22, + LMP_PAUSE_ENC_REQ_EXTOPCODE = 23, + LMP_RESUME_ENC_REQ_EXTOPCODE = 24, + LMP_IO_CAP_REQ_EXTOPCODE = 25, + LMP_IO_CAP_RES_EXTOPCODE = 26, + LMP_NUM_COMPARISON_FAIL_EXTOPCODE = 27, + LMP_PASSKEY_FAIL_EXTOPCODE = 28, + LMP_OOB_FAIL_EXTOPCODE = 29, + LMP_KEYPRESS_NOTIF_EXTOPCODE = 30, + LMP_PWR_CTRL_REQ_EXTOPCODE = 31, + LMP_PWR_CTRL_RES_EXTOPCODE = 32, + LMP_PING_REQ_EXTOPCODE = 33, + LMP_PING_RES_EXTOPCODE = 34, + LMP_SAM_SET_TYPE0_EXTOPCODE = 35, + LMP_SAM_DEFINE_MAP_EXTOPCODE = 36, + LMP_SAM_SWITCH_EXTOPCODE = 37, +}; + +/// PDU lengths (including opcode) +enum common_lmp_pdu_length +{ + LMP_NAME_REQ_LEN = 2 , + LMP_NAME_RES_LEN = 17, + LMP_ACCEPTED_LEN = 2 , + LMP_NOT_ACCEPTED_LEN = 3 , + LMP_CLK_OFF_REQ_LEN = 1 , + LMP_CLK_OFF_RES_LEN = 3 , + LMP_DETACH_LEN = 2 , + LMP_INRAND_LEN = 17, + LMP_COMBKEY_LEN = 17, + LMP_UNITKEY_LEN = 17, + LMP_AURAND_LEN = 17, + LMP_SRES_LEN = 5 , + LMP_TEMPRAND_LEN = 17, + LMP_TEMPKEY_LEN = 17, + LMP_ENC_MODE_REQ_LEN = 2 , + LMP_ENC_KEY_SIZE_REQ_LEN = 2 , + LMP_START_ENC_REQ_LEN = 17, + LMP_STOP_ENC_REQ_LEN = 1 , + LMP_SWITCH_REQ_LEN = 5 , + LMP_HOLD_LEN = 7 , + LMP_HOLD_REQ_LEN = 7 , + LMP_SNIFF_REQ_LEN = 10, + LMP_UNSNIFF_REQ_LEN = 1 , + LMP_PARK_REQ_LEN = 17, + LMP_INCR_PWR_REQ_LEN = 2 , + LMP_DECR_PWR_REQ_LEN = 2 , + LMP_MAX_PWR_LEN = 1 , + LMP_MIN_PWR_LEN = 1 , + LMP_AUTO_RATE_LEN = 1 , + LMP_PREF_RATE_LEN = 2 , + LMP_VER_REQ_LEN = 6 , + LMP_VER_RES_LEN = 6 , + LMP_FEATS_REQ_LEN = 9 , + LMP_FEATS_RES_LEN = 9 , + LMP_QOS_LEN = 4 , + LMP_QOS_REQ_LEN = 4 , + LMP_SCO_LINK_REQ_LEN = 7 , + LMP_RMV_SCO_LINK_REQ_LEN = 3 , + LMP_MAX_SLOT_LEN = 2 , + LMP_MAX_SLOT_REQ_LEN = 2 , + LMP_TIMING_ACCU_REQ_LEN = 1 , + LMP_TIMING_ACCU_RES_LEN = 3 , + LMP_SETUP_CMP_LEN = 1 , + LMP_USE_SEMI_PERM_KEY_LEN = 1 , + LMP_HOST_CON_REQ_LEN = 1 , + LMP_SLOT_OFF_LEN = 9 , + LMP_PAGE_MODE_REQ_LEN = 3 , + LMP_PAGE_SCAN_MODE_REQ_LEN = 3 , + LMP_SUPV_TO_LEN = 3 , + LMP_TEST_ACTIVATE_LEN = 1 , + LMP_TEST_CTRL_LEN = 10, + LMP_ENC_KEY_SIZE_MASK_REQ_LEN = 1 , + LMP_ENC_KEY_SIZE_MASK_RES_LEN = 3 , + LMP_SET_AFH_LEN = 16, + LMP_ENCAPS_HDR_LEN = 4 , + LMP_ENCAPS_PAYL_LEN = 17, + LMP_SP_CFM_LEN = 17, + LMP_SP_NB_LEN = 17, + LMP_DHKEY_CHK_LEN = 17, + LMP_PAUSE_ENC_AES_REQ_LEN = 17, +}; + +/// LMP Escape 4 Extended PDU length (including opcode and ext opcode) +enum common_lmp_ext_pdu_length +{ + LMP_ACCEPTED_EXT_LEN = 4 , + LMP_NOT_ACCEPTED_EXT_LEN = 5 , + LMP_FEATS_REQ_EXT_LEN = 12, + LMP_FEATS_RES_EXT_LEN = 12, + LMP_CLK_ADJ_LEN = 15, + LMP_CLK_ADJ_ACK_LEN = 3 , + LMP_CLK_ADJ_REQ_LEN = 6 , + LMP_PKT_TYPE_TBL_REQ_LEN = 3 , + LMP_ESCO_LINK_REQ_LEN = 16, + LMP_RMV_ESCO_LINK_REQ_LEN = 4 , + LMP_CH_CLASS_REQ_LEN = 7 , + LMP_CH_CLASS_LEN = 12, + LMP_SSR_REQ_LEN = 9 , + LMP_SSR_RES_LEN = 9 , + LMP_PAUSE_ENC_REQ_LEN = 2 , + LMP_RESUME_ENC_REQ_LEN = 2 , + LMP_IO_CAP_REQ_LEN = 5 , + LMP_IO_CAP_RES_LEN = 5 , + LMP_NUM_COMPARISON_FAIL_LEN = 2 , + LMP_PASSKEY_FAIL_LEN = 2 , + LMP_OOB_FAIL_LEN = 2 , + LMP_KEYPRESS_NOTIF_LEN = 3 , + LMP_PWR_CTRL_REQ_LEN = 3 , + LMP_PWR_CTRL_RES_LEN = 3 , + LMP_PING_REQ_LEN = 2 , + LMP_PING_RES_LEN = 2 , + LMP_SAM_SET_TYPE0_LEN = 17, + LMP_SAM_DEFINE_MAP_LEN = 17, + LMP_SAN_SWITCH_LEN = 9, +}; + +/// Maximum LMP PDU size (including opcode and ext opcode) +#define LMP_MAX_PDU_SIZE DM1_PACKET_SIZE + +/** + * Opcode and TrID in the first byte + * + * 7 6 5 4 3 2 1 0 + * +----+----+----+----+----+----+----+----+ + * | opcode | Tid| + * +----+----+----+----+----+----+----+----+ + */ +enum lmp_opcode_trid +{ + /// Position of transaction ID in 1st byte + LMP_TR_ID_POS = 0, + LMP_TR_ID_BIT = 0x01, + /// Position of opcode in 1st byte + LMP_OPCODE_LSB = 1, + LMP_OPCODE_MASK = 0xFE, +}; + +#define LMP_OPCODE(opcode, tr_id) (((opcode << LMP_OPCODE_LSB) & LMP_OPCODE_MASK) | ((tr_id << LMP_TR_ID_POS) & LMP_TR_ID_BIT)) +/* + * MESSAGES + **************************************************************************************** + */ + +///LMP_name_req PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_name_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Offset + uint8_t offset; +}; + +///LMP_name_res PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_name_res +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Offset + uint8_t offset; + ///Name Length + uint8_t length; + ///Name Fragment + struct name_vect name_frag; +}; + +///LMP_accepted PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_accepted +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Opcode of the original LMP + uint8_t orig_opcode; +}; + +///LMP_not_accepted PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_not_accepted +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Opcode of the original LMP + uint8_t orig_opcode; + ///Reason for not accepting the PDU (error code) + uint8_t reason; +}; + +///LMP_clkoffset_req PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_clk_off_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; +}; + +///LMP_clkoffset_res PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_clk_off_res +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Clock Offset value + uint16_t clk_offset ; +}; + +///LMP_detach PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_detach +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Reason to detach + uint8_t reason; +}; + +///LMP_in_rand PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_inrand +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Random number + struct ltk random; +}; + +///LMP_comb_key PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_combkey +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Random number + struct ltk random; +}; + +///LMP_unit_key PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_unitkey +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Key + struct ltk key; +}; + +///LMP_au_rand PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_aurand +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Random number + struct ltk random; +}; + +///LMP_sres PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_sres +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Authentication Response + struct sres_nb Sres; +}; + +///LMP_temp_rand PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_temprand +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Random number + struct ltk random; +}; + +///LMP_temp_key PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_tempkey +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Key + struct ltk key; +}; + +///LMP_encryption_mode_req PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_enc_mode_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Encryption Mode + uint8_t enc_mode; +}; + +///LMP_encryption_key_size_req PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_enc_key_size_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Key Size + uint8_t key_size; +}; + +///LMP_start_encryption_req PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_start_enc_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Random number + struct ltk random; +}; + +///LMP_stop_encryption_req PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_stop_enc_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; +}; + +///LMP_switch_req PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_switch_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Switch Instant + uint32_t switch_inst; +}; + +///LMP_sniff_req PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_sniff_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + /// Timing Control Flags (bit 1: initialization method 1 or 2) + uint8_t flags; + /// Offset (in slots) + uint16_t d_sniff; + /// Interval (in slots) + uint16_t t_sniff; + /// Attempts (number of receive slots) (in slots) + uint16_t sniff_attempt; + /// Timeout (number of receive slots) (in slots) + uint16_t sniff_to; +}; + +///LMP_unsniff_req PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_unsniff_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; +}; + +///LMP_incr_power_req PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_incr_pwr_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///For future use + uint8_t reserved; +}; + +///LMP_decr_power_req PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_decr_pwr_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///For future use + uint8_t reserved; +}; + +///LMP_max_power PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_max_pwr +{ + ///Opcode (including transaction ID) + uint8_t opcode; +}; + +///LMP_min_power PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_min_pwr +{ + ///Opcode (including transaction ID) + uint8_t opcode; +}; + +///LMP_auto_rate PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_auto_rate +{ + ///Opcode (including transaction ID) + uint8_t opcode; +}; + +///LMP_preferred_rate PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_pref_rate +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Data Rate + uint8_t rate; +}; + +///LMP_version_req PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_ver_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Version number + uint8_t ver; + ///Company ID + uint16_t common_id; + ///Subversion number + uint16_t subver; +}; + +///LMP_version_res PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_ver_res +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Version number + uint8_t ver; + ///Company ID + uint16_t common_id; + ///Subversion number + uint16_t subver; +}; + +///LMP_features_req PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_feats_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Features + struct features feats; +}; + +///LMP_features_res PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_feats_res +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Features + struct features feats; +}; + +///LMP_quality_of_service PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_qos +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Poll interval + uint16_t poll_intv; + ///Nbc + uint8_t nbc; +}; + + +///LMP_quality_of_service_req PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_qos_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Poll interval + uint16_t poll_intv; + ///Nbc + uint8_t nbc; +}; + +///LMP_SCO_link_req PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_sco_link_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///SCO handle + uint8_t sco_hdl; + ///timing control flags + uint8_t flags; + ///Dsco + uint8_t d_sco; + ///Tsco + uint8_t t_sco; + ///SCO packet + uint8_t sco_pkt; + ///Air mode + uint8_t air_mode; +}; + +///LMP_remove_SCO_link_req PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_rmv_sco_link_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///SCO handle + uint8_t sco_hdl; + ///Reason for its removal(error code) + uint8_t reason; +}; + +///LMP_max_slot PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_max_slot +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Max slots + uint8_t max_slots; +}; + + +///LMP_max_slot_req PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_max_slot_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Max slots + uint8_t max_slots; +}; + +///LMP_timing_accuracy_req PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_timing_accu_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; +}; + +///LMP_timing_accuracy_res PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_timing_accu_res +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Drift + uint8_t drift; + ///Jitter + uint8_t jitter; +}; + +///LMP_setup_complete PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_setup_cmp +{ + ///Opcode (including transaction ID) + uint8_t opcode; +}; + +///LMP_use_semi_permanent_key PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_use_semi_perm_key +{ + ///Opcode (including transaction ID) + uint8_t opcode; +}; + +///LMP_host_connection_req PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_host_con_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; +}; + +///LMP_slot_offset PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_slot_off +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Slot Offset + uint16_t slot_off; + ///BD Address + struct bd_addr addr; +}; + +///LMP_page_mode_req PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_page_mode_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Paging scheme + uint8_t page_scheme; + ///Paging scheme settings + uint8_t page_stg; +}; + +///LMP_page_scan_mode_req PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_page_scan_mode_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Paging scheme + uint8_t page_scheme; + ///Paging scheme settings + uint8_t page_stg; +}; + +///LMP_supervision_timeout PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_supv_to +{ + ///Opcode (including transaction ID) + uint8_t opcode; + /// Supervision Timeout (in slots, 0 means infinite timeout) + uint16_t supv_to; +}; + +///LMP_test_activate PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_test_activate +{ + ///Opcode (including transaction ID) + uint8_t opcode; +}; + +///LMP_test_control PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_test_ctrl +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Test Scenario + uint8_t scenario; + ///Hopping Mode + uint8_t hop; + ///Tx frequency + uint8_t tx_freq; + ///Rx Frequency + uint8_t rx_freq; + ///Power Control Mode + uint8_t pwr_ctrl; + ///Poll period + uint8_t poll_period; + ///Packet type + uint8_t pkt_type; + ///length of test data + uint16_t data_len; +}; + +///LMP_encryption_key_size_mask_req PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_enc_key_size_mask_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; +}; + +///LMP_encryption_key_size_mask_res PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_enc_key_size_mask_res +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Encryption Key Size Mask + uint16_t mask; +}; + +///LMP_set_AFH PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_set_afh +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///AFH Instant + uint32_t instant; + ///AFH Mode + uint8_t mode; + ///AFH channel map + struct chnl_map map; +}; + +///LMP_encapsulated_header PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_encaps_hdr +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Encapsulated major type + uint8_t maj_type; + ///Encapsulated minor type + uint8_t min_type; + ///Encapsulated Payload Length + uint8_t payl_len; +}; + +///LMP_encapsulated_payload PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_encaps_payl +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Encapsulated data + struct byte16 data; +}; + +///LMP_Simple_Pairing_Confirm PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_sp_cfm +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Commitment Value + struct byte16 commitment_val ; +}; + +///LMP_Simple_Pairing_Number PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_sp_nb +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///nonce Value + struct byte16 nonce; +}; + +///LMP_DHkey_check PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_dhkey_chk +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Confirmation Value + struct ltk cfm_val; +}; + +///LMP_pause_encryption_aes_req PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_pause_enc_aes_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + /// Random Number + struct ltk rand; +}; + +/* + * Extended PDUs parameter structures - Escape 4 + ****************************************************************************************/ + +///LMP_accepted_ext PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_accepted_ext +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; + ///Escape opcode of the original LMP + uint8_t orig_esc_opcode; + ///Extended opcode of the original LMP + uint8_t orig_ext_opcode; +}; + +///LMP_not_accepted_ext PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_not_accepted_ext +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; + ///Escape opcode of the original LMP + uint8_t orig_esc_opcode; + ///Extended opcode of the original LMP + uint8_t orig_ext_opcode; + ///Reason + uint8_t reason; +}; + +///LMP_features_req_ext PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_feats_req_ext +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; + ///Features page + uint8_t page; + ///Max supported page + uint8_t max_page; + ///Extended features + struct features ext_feats; +}; + +///LMP_features_res_ext PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_feats_res_ext +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; + ///Features page + uint8_t page; + ///Max supported page + uint8_t max_page; + ///Extended features + struct features ext_feats; +}; + +///LMP_clk_adj PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_clk_adj +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; + ///Coarse clock adjustment Event ID + uint8_t clk_adj_id; + ///Coarse clock adjustment instant + uint32_t clk_adj_instant; + ///Coarse clock adjustment intraslot alignment offset + int16_t clk_adj_us; + ///Coarse clock adjustment slot offset + uint8_t clk_adj_slots; + ///Coarse clock adjustment mode (before/after instant) + uint8_t clk_adj_mode; + ///Coarse clock adjustment PDU CLK instant + uint32_t clk_adj_clk; +}; + +///LMP_clk_adj_ack PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_clk_adj_ack +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; + ///Coarse clock adjustment Event ID + uint8_t clk_adj_id; +}; + +///LMP_clk_adj_req PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_clk_adj_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; + ///Coarse clock adjustment intraslot alignment offset + int16_t clk_adj_us; + ///Coarse clock adjustment slot offset + uint8_t clk_adj_slots; + ///Corase clock adjustment period + uint8_t clk_adj_period; +}; + +///LMP_packet_type_table_req PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_pkt_type_tbl_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; + ///Packet Type table + uint8_t pkt_type_tbl; +}; + +///LMP_SAM_define_map PDU structure +struct lmp_sam_define_map +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; + ///SAM Index + uint8_t index; + ///Tsam-sm + uint8_t t_sam_sm; + ///Nsam-sm + uint8_t n_sam_sm; + ///SAM Submaps + struct sam_submaps submaps; +}; + +///LMP_SAM_set_type0 PDU structure +struct lmp_sam_set_type0 +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; + ///Update mode + uint8_t update_mode; + ///SAM Type0 submap + struct sam_type0_submap submap; +}; + +///LMP_SAM_switch PDU structure +struct lmp_sam_switch +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; + ///SAM Index + uint8_t index; + ///timing control flags + uint8_t flags; + ///Dsam + uint8_t d_sam; + ///SAM instant + uint32_t instant; +}; + +///LMP_eSCO_link_req PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_esco_link_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; + ///eSCO handle + uint8_t esco_hdl; + ///eSCo LT Address + uint8_t esco_lt_addr; + ///timing control flags + uint8_t flags; + ///Desco + uint8_t d_esco; + ///t_esco + uint8_t t_esco; + ///Wesco + uint8_t w_esco; + ///eSCO packet type M2S + uint8_t m2s_pkt_type; + ///eSCO packet type S2M + uint8_t s2m_pkt_type; + ///Packet Length M2S + uint16_t m2s_pkt_len; + ///Packet Length S2m + uint16_t s2m_pkt_len; + ///Air Mode + uint8_t air_mode; + ///Negotiation state + uint8_t negt_st; +}; + +///LMP_remove_eSCO_link_req PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_rmv_esco_link_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; + ///eSCO handle + uint8_t esco_hdl; + ///Reason + uint8_t reason; +}; + +///LMP_channel_classification_req PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_ch_class_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; + ///AFH reporting mode + uint8_t rep_mode; + ///AFH min interval + uint16_t min_intv; + ///AFH max interval + uint16_t max_intv; +}; + +///LMP_channel_classification PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_ch_class +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; + ///AFh channel classification + struct chnl_map ch_class; +}; + +///LMP_sniff_subrating_req PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_ssr_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; + /// Maximum sniff sub-rate (in number of sniff events) + uint8_t max_subrate; + /// Minimum sniff mode timeout (in slots) + uint16_t min_to; + /// Sniff sub-rating instant (in slots, master clock value) + uint32_t instant; +}; + +///LMP_sniff_subrating_res PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_ssr_res +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; + /// Maximum sniff sub-rate (in number of sniff events) + uint8_t max_subrate; + /// Minimum sniff mode timeout (in slots) + uint16_t min_to; + /// Sniff sub-rating instant (in slots, master clock value) + uint32_t instant; +}; + +///LMP_pause_encryption_req PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_pause_enc_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; +}; + +///LMP_resume_encryption_req PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_resume_enc_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; +}; + +///LMP_IO_capability_req PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_io_cap_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; + ///IO Capabilities + uint8_t io_cap; + /// OOB Authentication data + uint8_t oob_auth_data; + ///Authentication requirements + uint8_t auth_req; +}; + + +///LMP_IO_capability_res PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_io_cap_res +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; + ///IO Capabilities + uint8_t io_cap; + /// OOB Authentication data + uint8_t oob_auth_data; + ///Authentication requirements + uint8_t auth_req; +}; + +///LMP_numeric_comparison_failed PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_num_comparison_fail +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; +}; + +///LMP_passkey_failed PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_passkey_fail +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; +}; + +///LMP_oob_failed PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_oob_fail +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; +}; + +///LMP_keypress_notification PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_keypress_notif +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; + ///Notification Type + uint8_t type; +}; + +///LMP_power_control_req PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_pwr_ctrl_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; + ///Power adjustment request + uint8_t pwr_adj; + +}; + +///LMP_power_control_res PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_pwr_ctrl_res +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; + ///Power adjustment response + uint8_t pwr_adj; +}; + +/// LMP_ping_req PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_ping_req +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; +}; + +/// LMP_ping_res PDU structure +/*@TRACE + * @NO_PAD +*/ +struct lmp_ping_res +{ + ///Opcode (including transaction ID) + uint8_t opcode; + ///Extended opcode + uint8_t ext_opcode; +}; + +/// Union of all the LMP message structures +union lmp_pdu +{ + struct lmp_name_req name_req ; + struct lmp_name_res name_res ; + struct lmp_accepted accepted ; + struct lmp_not_accepted not_accepted ; + struct lmp_clk_off_req clk_off_req ; + struct lmp_clk_off_res clk_off_res ; + struct lmp_detach detach ; + struct lmp_inrand inrand ; + struct lmp_combkey combkey ; + struct lmp_unitkey unitkey ; + struct lmp_aurand aurand ; + struct lmp_sres sres ; + struct lmp_temprand temprand ; + struct lmp_tempkey tempkey ; + struct lmp_enc_mode_req enc_mode_req ; + struct lmp_enc_key_size_req enc_key_size_req ; + struct lmp_start_enc_req start_enc_req ; + struct lmp_stop_enc_req stop_enc_req ; + struct lmp_switch_req switch_req ; + struct lmp_sniff_req sniff_req ; + struct lmp_unsniff_req unsniff_req ; + struct lmp_incr_pwr_req incr_pwr_req ; + struct lmp_decr_pwr_req decr_pwr_req ; + struct lmp_max_pwr max_pwr ; + struct lmp_min_pwr min_pwr ; + struct lmp_auto_rate auto_rate ; + struct lmp_pref_rate pref_rate ; + struct lmp_ver_req ver_req ; + struct lmp_ver_res ver_res ; + struct lmp_feats_req feats_req ; + struct lmp_feats_res feats_res ; + struct lmp_clk_adj clk_adj ; + struct lmp_clk_adj_ack clk_adj_ack ; + struct lmp_clk_adj_req clk_adj_req ; + struct lmp_qos qos ; + struct lmp_qos_req qos_req ; + struct lmp_sco_link_req sco_link_req ; + struct lmp_rmv_sco_link_req rmv_sco_link_req ; + struct lmp_max_slot max_slot ; + struct lmp_max_slot_req max_slot_req ; + struct lmp_timing_accu_req timing_accu_req ; + struct lmp_timing_accu_res timing_accu_res ; + struct lmp_setup_cmp setup_cmp ; + struct lmp_use_semi_perm_key use_semi_perm_key ; + struct lmp_host_con_req host_con_req ; + struct lmp_slot_off slot_off ; + struct lmp_page_mode_req page_mode_req ; + struct lmp_page_scan_mode_req page_scan_mode_req ; + struct lmp_supv_to supv_to ; + struct lmp_test_activate test_activate ; + struct lmp_test_ctrl test_ctrl ; + struct lmp_enc_key_size_mask_req enc_key_size_mask_req ; + struct lmp_enc_key_size_mask_res enc_key_size_mask_res ; + struct lmp_set_afh set_afh ; + struct lmp_encaps_hdr encaps_hdr ; + struct lmp_encaps_payl encaps_payl ; + struct lmp_sp_cfm sp_cfm ; + struct lmp_sp_nb sp_nb ; + struct lmp_dhkey_chk dhkey_chk ; + struct lmp_accepted_ext accepted_ext ; + struct lmp_not_accepted_ext not_accepted_ext ; + struct lmp_feats_req_ext feats_req_ext ; + struct lmp_feats_res_ext feats_res_ext ; + struct lmp_pkt_type_tbl_req pkt_type_tbl_req ; + struct lmp_sam_define_map sam_define_map ; + struct lmp_sam_set_type0 sam_set_type0 ; + struct lmp_sam_switch sam_switch ; + struct lmp_esco_link_req esco_link_req ; + struct lmp_rmv_esco_link_req rmv_esco_link_req ; + struct lmp_ch_class_req ch_class_req ; + struct lmp_ch_class ch_class ; + struct lmp_ssr_req ssr_req ; + struct lmp_ssr_res ssr_res ; + struct lmp_pause_enc_req pause_enc_req ; + struct lmp_resume_enc_req resume_enc_req ; + struct lmp_io_cap_req io_cap_req ; + struct lmp_io_cap_res io_cap_res ; + struct lmp_num_comparison_fail num_comparison_fail ; + struct lmp_passkey_fail passkey_fail ; + struct lmp_oob_fail oob_fail ; + struct lmp_keypress_notif keypress_notif ; + struct lmp_pwr_ctrl_req pwr_ctrl_req ; + struct lmp_pwr_ctrl_res pwr_ctrl_res ; + struct lmp_ping_req ping_req ; + struct lmp_ping_res ping_res ; +}; + + +/// @} COMMON_BT +#endif // COMMON_LMP_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/common/api/common_math.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/common/api/common_math.h new file mode 100755 index 0000000..20fd56a --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/common/api/common_math.h @@ -0,0 +1,284 @@ +/** + **************************************************************************************** + * + * @file common_math.h + * + * @brief Common optimized math functions + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef _COMMON_MATH_H_ +#define _COMMON_MATH_H_ + +/** + ***************************************************************************************** + * @defgroup COMMON_MATH Math functions + * @ingroup COMMON + * @brief Optimized math functions and other computations. + * + * @{ + ***************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include // standard integer definitions +#include // boolean definitions +#include // standard library +#include "compiler.h" // for __INLINE +#include "architect.h" // for BLE_ASSERT_ERR + +extern void srand (unsigned int seed); +extern int rand (void); + +/* + * MACROS + **************************************************************************************** + */ +/** + **************************************************************************************** + * @brief Return value with one bit set. + * + * @param[in] pos Position of the bit to set. + * + * @return Value with one bit set. There is no return type since this is a macro and this + * will be resolved by the compiler upon assignment to an l-value. + **************************************************************************************** + */ +#define COMMON_BIT(pos) (1UL<<(pos)) + +/** + **************************************************************************************** + * @brief Align val on the multiple of 4 equal or nearest higher. + * @param[in] val Value to align. + * @return Value aligned. + **************************************************************************************** + */ +#define COMMON_ALIGN4_HI(val) (((val)+3)&~3) + + +/** + **************************************************************************************** + * @brief Align val on the multiple of 4 equal or nearest lower. + * @param[in] val Value to align. + * @return Value aligned. + **************************************************************************************** + */ +#define COMMON_ALIGN4_LO(val) ((val)&~3) + +/** + **************************************************************************************** + * @brief Align val on the multiple of 2 equal or nearest higher. + * @param[in] val Value to align. + * @return Value aligned. + **************************************************************************************** + */ +#define COMMON_ALIGN2_HI(val) (((val)+1)&~1) + + +/** + **************************************************************************************** + * @brief Align val on the multiple of 2 equal or nearest lower. + * @param[in] val Value to align. + * @return Value aligned. + **************************************************************************************** + */ +#define COMMON_ALIGN2_LO(val) ((val)&~1) + +/** + **************************************************************************************** + * Perform a division and ceil up the result + * + * @param[in] val Value to divide + * @param[in] div Divide value + * @return ceil(val/div) + **************************************************************************************** + */ +#define COMMON_DIVIDE_CEIL(val, div) (((val) + ((div) - 1))/ (div)) + +/** + **************************************************************************************** + * Perform a division and round the result + * + * @param[in] val Value to divide + * @param[in] div Divide value + * @return round(val/div) + **************************************************************************************** + */ +#define COMMON_DIVIDE_ROUND(val, div) (((val) + ((div) >> 1))/ (div)) + +/** + **************************************************************************************** + * Perform a modulo operation + * + * @param[in] val Dividend + * @param[in] div Divisor + * @return val/div) + **************************************************************************************** + */ +//#define COMMON_MOD(val, div) ((val) % (div)) +__INLINE uint32_t common_mod(uint32_t val, uint32_t div) +{ + BLE_ASSERT_ERR(div); + return ((val) % (div)); +} +#define COMMON_MOD(val, div) common_mod(val, div) + + +/* + * FUNCTION DEFINTIONS + **************************************************************************************** + */ +/** + **************************************************************************************** + * @brief Count leading zeros. + * @param[in] val Value to count the number of leading zeros on. + * @return Number of leading zeros when value is written as 32 bits. + **************************************************************************************** + */ +__INLINE uint32_t common_clz(uint32_t val) +{ + #if defined(__arm__) + return __builtin_clz(val); + #elif defined(__GNUC__) + if (val == 0) + { + return 32; + } + return __builtin_clz(val); + #else + uint32_t i; + for (i = 0; i < 32; i++) + { + if (val & COMMON_BIT(31 - i)) + break; + } + return i; + #endif // defined(__arm__) +} + +/** + **************************************************************************************** + * @brief Count trailing zeros. + * @param[in] val Value to count the number of trailing zeros on. + * @return Number of trailing zeros when value is written as 32 bits. + **************************************************************************************** + */ +__INLINE uint32_t common_ctz(uint32_t val) +{ + #if defined(__arm__) + return __builtin_ctz(val); + #elif defined(__GNUC__) + if (val == 0) + { + return 32; + } + return __builtin_ctz(val); + #else + uint32_t i; + for (i = 0; i < 32; i++) + { + if (val & COMMON_BIT(i)) + break; + } + return i; + #endif // defined(__arm__) +} +/** + **************************************************************************************** + * @brief Function to initialize the random seed. + * @param[in] seed The seed number to use to generate the random sequence. + **************************************************************************************** + */ +__INLINE void common_random_init(uint32_t seed) +{ + srand(seed); +} + +/** + **************************************************************************************** + * @brief Function to get an 8 bit random number. + * @return Random byte value. + **************************************************************************************** + */ +__INLINE uint8_t common_rand_byte(void) +{ + return (uint8_t)(rand() & 0xFF); +} + +/** + **************************************************************************************** + * @brief Function to get an 16 bit random number. + * @return Random half word value. + **************************************************************************************** + */ +__INLINE uint16_t common_rand_hword(void) +{ + return (uint16_t)(rand() & 0xFFFF); +} + +/** + **************************************************************************************** + * @brief Function to get an 32 bit random number. + * @return Random word value. + **************************************************************************************** + */ +__INLINE uint32_t common_rand_word(void) +{ + return (uint32_t)rand(); +} + +/** + **************************************************************************************** + * @brief Function to return the smallest of 2 unsigned 32 bits words. + * @return The smallest value. + **************************************************************************************** + */ +__INLINE uint32_t common_min(uint32_t a, uint32_t b) +{ + return a < b ? a : b; +} + +/** + **************************************************************************************** + * @brief Function to return the smallest of 2 signed 32 bits words. + * @return The smallest value. + **************************************************************************************** + */ +__INLINE int32_t common_min_s(int32_t a, int32_t b) +{ + return a < b ? a : b; +} + +/** + **************************************************************************************** + * @brief Function to return the greatest of 2 unsigned 32 bits words. + * @return The greatest value. + **************************************************************************************** + */ +__INLINE uint32_t common_max(uint32_t a, uint32_t b) +{ + return a > b ? a : b; +} + +/** + **************************************************************************************** + * @brief Function to return the absolute value of a signed integer. + * @return The absolute value. + **************************************************************************************** + */ +__INLINE int common_abs(int val) +{ + return val < 0 ? val*(-1) : val; +} + +/// @} COMMON_MATH + + +#endif // _COMMON_MATH_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/common/api/common_utils.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/common/api/common_utils.h new file mode 100755 index 0000000..43961c5 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/common/api/common_utils.h @@ -0,0 +1,693 @@ +/** + **************************************************************************************** + * + * @file common_utils.h + * + * @brief Common utilities definitions + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ +#ifndef _COMMON_UTILS_H_ +#define _COMMON_UTILS_H_ + +/** + **************************************************************************************** + * @defgroup COMMON_UTILS Utilities + * @ingroup COMMON + * @brief Common utilities + * + * This module contains the common utilities functions and macros. + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include // standard definitions +#include // standard definitions +#include "common_bt.h" // common bt definitions +#include "rwip_config.h" // SW configuration +#include "rwip.h" // SW configuration +#include "compiler.h" // for inline functions + + +/* + * MACRO DEFINITIONS + **************************************************************************************** + */ + +/// Common constants - bit field definitions +#define BIT0 0x0001 +#define BIT1 0x0002 +#define BIT2 0x0004 +#define BIT3 0x0008 +#define BIT4 0x0010 +#define BIT5 0x0020 +#define BIT6 0x0040 +#define BIT7 0x0080 +#define BIT8 0x0100 +#define BIT9 0x0200 +#define BIT10 0x0400 +#define BIT11 0x0800 +#define BIT12 0x1000 +#define BIT13 0x2000 +#define BIT14 0x4000 +#define BIT15 0x8000 + +/// Number of '1' bits in a byte +#define NB_ONE_BITS(byte) (one_bits[byte & 0x0F] + one_bits[byte >> 4]) + +/// Get the number of elements within an array, give also number of rows in a 2-D array +#define ARRAY_LEN(array) (sizeof((array))/sizeof((array)[0])) + +/// Get the number of columns within a 2-D array +#define ARRAY_NB_COLUMNS(array) (sizeof((array[0]))/sizeof((array)[0][0])) + + +/// Macro for LMP message handler function declaration or definition +#define LMP_MSG_HANDLER(msg_name) __STATIC int lmp_##msg_name##_handler(struct lmp_##msg_name const *param, \ + kernel_task_id_t const dest_id) +/// Macro for LMP message handler function declaration or definition +#define LLCP_MSG_HANDLER(msg_name) __STATIC int llcp_##msg_name##_handler(struct llcp_##msg_name const *param, \ + kernel_task_id_t const dest_id) + +/// Macro for HCI message handler function declaration or definition (for multi-instantiated tasks) +#define HCI_CMD_HANDLER_C(cmd_name, param_struct) __STATIC int hci_##cmd_name##_cmd_handler(param_struct const *param, \ + kernel_task_id_t const dest_id, \ + uint16_t opcode) + +/// Macro for HCI message handler function declaration or definition (with parameters) +#define HCI_CMD_HANDLER(cmd_name, param_struct) __STATIC int hci_##cmd_name##_cmd_handler(param_struct const *param, \ + uint16_t opcode) + +/// Macro for HCI message handler function declaration or definition (with parameters) +#define HCI_CMD_HANDLER_TAB(task) __STATIC const struct task##_hci_cmd_handler task##_hci_command_handler_tab[] = + + +/// MACRO to build a subversion field from the Minor and Release fields +#define COMMON_SUBVERSION_BUILD(minor, release) (((minor) << 8) | (release)) + + +/// Macro to get a structure from one of its structure field +#define CONTAINER_OF(ptr, type, member) ((type *)( (char *)ptr - offsetof(type,member) )) + + +/// Increment value and make sure it's never greater or equals max (else wrap to 0) +#define COMMON_VAL_INC(_val, _max) \ + (_val) = (_val) + 1; \ + if((_val) >= (_max)) (_val) = 0 + +/* + * ENUMERATIONS DEFINITIONS + **************************************************************************************** + */ + +/// Status returned by generic packer-unpacker +enum COMMON_UTIL_PACK_STATUS +{ + COMMON_UTIL_PACK_OK, + COMMON_UTIL_PACK_IN_BUF_OVFLW, + COMMON_UTIL_PACK_OUT_BUF_OVFLW, + COMMON_UTIL_PACK_WRONG_FORMAT, + COMMON_UTIL_PACK_ERROR, +}; + + +/// Rate information +/*@TRACE*/ +enum phy_rate +{ + /// 1 Mbits/s Rate + COMMON_RATE_1MBPS = 0, + /// 2 Mbits/s Rate + COMMON_RATE_2MBPS = 1, + /// 125 Kbits/s Rate + COMMON_RATE_125KBPS = 2, + /// 500 Kbits/s Rate + COMMON_RATE_500KBPS = 3, + /// Undefined rate (used for reporting when no packet is received) + COMMON_RATE_UNDEF = 4, + + COMMON_RATE_MAX = 4, +}; + + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + + +/* + * CONSTANT DECLARATIONS + **************************************************************************************** + */ + +/// Number of '1' bits in values from 0 to 15, used to fasten bit counting +extern const unsigned char one_bits[16]; + +/// Conversion table Sleep Clock Accuracy to PPM +extern const uint16_t common_sca2ppm[]; + +/// NULL BD address +extern const struct bd_addr common_null_bdaddr; + +/// Default BD address +///extern const struct bd_addr common_default_bdaddr; +extern struct bd_addr common_default_bdaddr; + +/// NULL Key +extern const uint8_t common_null_key[KEY_LEN]; + +/// Table for converting rate to PHY +extern const uint8_t common_rate_to_phy[]; + +/// Table for converting PHY to rate (Warning: the coded PHY is converted to 125K by default) +extern const uint8_t common_phy_to_rate[]; + +/// Convert PHY mask (with one single bit set) to a value +extern const uint8_t common_phy_mask_to_value[]; + +/// Convert PHY a value to the corresponding mask bit +extern const uint8_t common_phy_value_to_mask[]; + +/// Convert Rate value to the corresponding PHY mask bit +extern const uint8_t common_rate_to_phy_mask[]; + +/// Convert PHY mask bit to the corresponding Rate value +extern const uint8_t common_phy_mask_to_rate[]; + +/* + * OPERATIONS ON BT CLOCK + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Clocks addition with 2 operands + * + * @param[in] clock_a 1st operand value (in BT half-slots) + * @param[in] clock_b 2nd operand value (in BT half-slots) + * @return result operation result (in BT half-slots) + **************************************************************************************** + */ +#define CLK_ADD_2(clock_a, clock_b) ((uint32_t)(((clock_a) + (clock_b)) & RWIP_MAX_CLOCK_TIME)) + +/** + **************************************************************************************** + * @brief Clocks addition with 3 operands + * + * @param[in] clock_a 1st operand value (in BT half-slots) + * @param[in] clock_b 2nd operand value (in BT half-slots) + * @param[in] clock_c 3rd operand value (in BT half-slots) + * @return result operation result (in BT half-slots) + **************************************************************************************** + */ +#define CLK_ADD_3(clock_a, clock_b, clock_c) ((uint32_t)(((clock_a) + (clock_b) + (clock_c)) & RWIP_MAX_CLOCK_TIME)) + +/** + **************************************************************************************** + * @brief Clocks subtraction + * + * @param[in] clock_a 1st operand value (in BT half-slots) + * @param[in] clock_b 2nd operand value (in BT half-slots) + * @return result operation result (in BT half-slots) + **************************************************************************************** + */ +#define CLK_SUB(clock_a, clock_b) ((uint32_t)(((clock_a) - (clock_b)) & RWIP_MAX_CLOCK_TIME)) + +/** + **************************************************************************************** + * @brief Clocks time difference + * + * @param[in] clock_a 1st operand value (in BT half-slots) + * @param[in] clock_b 2nd operand value (in BT half-slots) + * @return result return the time difference from clock A to clock B + * - result < 0 => clock_b is in the past + * - result == 0 => clock_a is equal to clock_b + * - result > 0 => clock_b is in the future + **************************************************************************************** + */ +#define CLK_DIFF(clock_a, clock_b) ( (CLK_SUB((clock_b), (clock_a)) > ((RWIP_MAX_CLOCK_TIME+1) >> 1)) ? \ + ((int32_t)((-CLK_SUB((clock_a), (clock_b))))) : ((int32_t)((CLK_SUB((clock_b), (clock_a))))) ) + + + +/// macro to extract a field from a value containing several fields +/// @param[in] __r bit field value +/// @param[in] __f field name +/// @return the value of the register masked and shifted +#define GETF(__r, __f) \ + (( (__r) & (__f##_MASK) ) >> (__f##_LSB)) + +/// macro to set a field value into a value containing several fields. +/// @param[in] __r bit field value +/// @param[in] __f field name +/// @param[in] __v value to put in field +#define SETF(__r, __f, __v) \ + do { \ + BLE_ASSERT_INFO( ( ( ( (__v) << (__f##_LSB) ) & ( ~(__f##_MASK) ) ) ) == 0 ,(__f##_MASK), (__v)); \ + __r = (((__r) & ~(__f##_MASK)) | (__v) << (__f##_LSB)); \ + } while (0) + + + +/// macro to extract a bit field from a value containing several fields +/// @param[in] __r bit field value +/// @param[in] __b bit field name +/// @return the value of the register masked and shifted +#define GETB(__r, __b) \ + (( (__r) & (__b##_BIT) ) >> (__b##_POS)) + +/// macro to set a bit field value into a value containing several fields. +/// @param[in] __r bit field value +/// @param[in] __b bit field name +/// @param[in] __v value to put in field +#define SETB(__r, __b, __v) \ + do { \ + BLE_ASSERT_ERR( ( ( ( (__v ? 1 : 0) << (__b##_POS) ) & ( ~(__b##_BIT) ) ) ) == 0 ); \ + __r = (((__r) & ~(__b##_BIT)) | (__v ? 1 : 0) << (__b##_POS)); \ + } while (0) + +/// macro to toggle a bit into a value containing several bits. +/// @param[in] __r bit field value +/// @param[in] __b bit field name +#define TOGB(__r, __b) \ + do { \ + __r = ((__r) ^ (__b##_BIT)); \ + } while (0) + +/** + **************************************************************************************** + * @brief Check if clock_a is equal to clock_b + * + * @param[in] clock_a Clock A value (in BT half-slots) + * @param[in] clock_b Clock B value (in BT half-slots) + * @return result True: clock_a lower than or equal to clock_b | False: else + **************************************************************************************** + */ +#define CLK_EQ(clock_a, clock_b) (clock_b == clock_a) + +/** + **************************************************************************************** + * @brief Check if clock_a is lower than or equal to clock_b + * + * @param[in] clock_a Clock A value (in BT half-slots) + * @param[in] clock_b Clock B value (in BT half-slots) + * @return result True: clock_a lower than or equal to clock_b | False: else + **************************************************************************************** + */ +#define CLK_LOWER_EQ(clock_a, clock_b) (CLK_SUB(clock_b, clock_a) < (RWIP_MAX_CLOCK_TIME >> 1)) + +/** + **************************************************************************************** + * @brief Check if clock A is lower than or equal to clock B (with half-us precision) + * + * @param[in] int_a Integer part of clock A (in BT half-slots) + * @param[in] fract_a Fractional part of clock A (in half-us) (range: 0 to 624) + * @param[in] int_b Integer part of clock B (in BT half-slots) + * @param[in] fract_b Fractional part of clock B (in half-us) (range: 0 to 624) + * @return result True: clock A lower than or equal to clock B | False: else + **************************************************************************************** + */ +#define CLK_LOWER_EQ_HUS(int_a, fract_a, int_b, fract_b) ( CLK_GREATER_THAN(int_b, int_a) \ + || ( CLK_EQ(int_a, int_b) \ + && (fract_a <= fract_b) ) ) \ + +/** + **************************************************************************************** + * @brief Check if clock_a is greater than clock_b + * + * @param[in] clock_a Clock A value (in BT half-slots) + * @param[in] clock_b Clock B value (in BT half-slots) + * @return result True: clock_a is greater than clock_b | False: else + **************************************************************************************** + */ +#define CLK_GREATER_THAN(clock_a, clock_b) !(CLK_LOWER_EQ(clock_a, clock_b)) + +/** + **************************************************************************************** + * @brief Check if clock A is greater than clock B (with half-us precision) + * + * @param[in] int_a Integer part of clock A (in BT half-slots) + * @param[in] fract_a Fractional part of clock A (in half-us) (range: 0 to 624) + * @param[in] int_b Integer part of clock B (in BT half-slots) + * @param[in] fract_b Fractional part of clock B (in half-us) (range: 0 to 624) + * @return result True: clock A greater than clock B | False: else + **************************************************************************************** + */ +#define CLK_GREATER_THAN_HUS(int_a, fract_a, int_b, fract_b) ( CLK_GREATER_THAN(int_a, int_b) \ + || ( CLK_EQ(int_a, int_b) \ + && (fract_a > fract_b) ) ) \ + +#if (BLE_EMB_PRESENT) +/** + ****************************************************************************** + * @brief Compare 2 BLE instants (connection event counter) + * @param[in] instant_a 1st operand value (connection event counter) + * @param[in] instant_b 2nd operand value (connection event counter) + * @return result True: B is greater or equal to A | False: B is smaller than A + ****************************************************************************** + */ +#define COMMON_BLE_INSTANT_PASSED(instant_a, instant_b) ((uint16_t)(instant_b - instant_a) < 32767) + +/** + ****************************************************************************** + * @brief Compute difference between two event counter + * @param[in] evt_cnt_a 1st operand value (connection event counter) + * @param[in] evt_cnt_b 2nd operand value (connection event counter) + * @return result return the time difference from evt_cnt_a to evt_cnt_b + * - result < 0 => evt_cnt_b is in the past + * - result == 0 => evt_cnt_a is equal to evt_cnt_b + * - result > 0 => evt_cnt_b is in the future + ****************************************************************************** + */ +#define COMMON_BLE_EVT_CNT_DIFF(evt_cnt_a, evt_cnt_b) ((((uint16_t) (evt_cnt_b)) - ((uint16_t) (evt_cnt_a)) > 32768) \ + ? ((int16_t)(-(((uint16_t) (evt_cnt_a)) - ((uint16_t) (evt_cnt_b))))) \ + : ((int16_t)(-(((uint16_t) (evt_cnt_b)) - ((uint16_t) (evt_cnt_a)))))) + +#endif //BLE_EMB_PRESENT + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Read an aligned 32 bit word. + * @param[in] ptr32 The address of the first byte of the 32 bit word. + * @return The 32 bit value. + **************************************************************************************** + */ +__INLINE uint32_t common_read32(void const *ptr32) +{ + return *((uint32_t*)ptr32); +} + +/** + **************************************************************************************** + * @brief Read an aligned 16 bits word. + * @param[in] ptr16 The address of the first byte of the 16 bits word. + * @return The 16 bits value. + **************************************************************************************** + */ +__INLINE uint16_t common_read16(void const *ptr16) +{ + return *((uint16_t*)ptr16); +} + +/** + **************************************************************************************** + * @brief Write an aligned 32 bits word. + * @param[in] ptr32 The address of the first byte of the 32 bits word. + * @param[in] value The value to write. + **************************************************************************************** + */ +__INLINE void common_write32(void const *ptr32, uint32_t value) +{ + *(uint32_t*)ptr32 = value; +} + +/** + **************************************************************************************** + * @brief Write an aligned 16 bits word. + * @param[in] ptr16 The address of the first byte of the 16 bits word. + * @param[in] value The value to write. + **************************************************************************************** + */ +__INLINE void common_write16(void const *ptr16, uint32_t value) +{ + *(uint16_t*)ptr16 = value; +} + +/** + **************************************************************************************** + * @brief Write a 8 bits word. + * @param[in] ptr8 The address of the first byte of the 8 bits word. + * @param[in] value The value to write. + **************************************************************************************** + */ +__INLINE void common_write8(void const *ptr8, uint32_t value) +{ + *(uint8_t*)ptr8 = value; +} + +/** + **************************************************************************************** + * @brief Read a packed 16 bits word. + * @param[in] ptr16 The address of the first byte of the 16 bits word. + * @return The 16 bits value. + **************************************************************************************** + */ +__INLINE uint16_t common_read16p(void const *ptr16) +{ + uint16_t value = ((uint8_t *)ptr16)[0] | ((uint8_t *)ptr16)[1] << 8; + return value; +} + +/** + **************************************************************************************** + * @brief Read a packed 24 bits word. + * @param[in] ptr24 The address of the first byte of the 24 bits word. + * @return The 24 bits value. + **************************************************************************************** + */ +__INLINE uint32_t common_read24p(void const *ptr24) +{ + uint16_t addr_l, addr_h; + addr_l = common_read16p(ptr24); + addr_h = *((uint8_t *)ptr24 + 2) & 0x00FF; + return ((uint32_t)addr_l | (uint32_t)addr_h << 16); +} + +/** + **************************************************************************************** + * @brief Write a packed 24 bits word. + * @param[in] ptr24 The address of the first byte of the 24 bits word. + * @param[in] value The value to write. + **************************************************************************************** + */ +__INLINE void common_write24p(void const *ptr24, uint32_t value) +{ + uint8_t *ptr=(uint8_t*)ptr24; + + *ptr++ = (uint8_t)(value&0xff); + *ptr++ = (uint8_t)((value&0xff00)>>8); + *ptr++ = (uint8_t)((value&0xff0000)>>16); +} + +/** + **************************************************************************************** + * @brief Read a packed 32 bits word. + * @param[in] ptr32 The address of the first byte of the 32 bits word. + * @return The 32 bits value. + **************************************************************************************** + */ +__INLINE uint32_t common_read32p(void const *ptr32) +{ + uint16_t addr_l, addr_h; + addr_l = common_read16p(ptr32); + addr_h = common_read16p((uint8_t *)ptr32 + 2); + return ((uint32_t)addr_l | (uint32_t)addr_h << 16); +} +/** + **************************************************************************************** + * @brief Write a packed 32 bits word. + * @param[in] ptr32 The address of the first byte of the 32 bits word. + * @param[in] value The value to write. + **************************************************************************************** + */ +__INLINE void common_write32p(void const *ptr32, uint32_t value) +{ + uint8_t *ptr=(uint8_t*)ptr32; + + *ptr++ = (uint8_t)(value&0xff); + *ptr++ = (uint8_t)((value&0xff00)>>8); + *ptr++ = (uint8_t)((value&0xff0000)>>16); + *ptr = (uint8_t)((value&0xff000000)>>24); +} + +/** + **************************************************************************************** + * @brief Write a packed 16 bits word. + * @param[in] ptr16 The address of the first byte of the 16 bits word. + * @param[in] value The value to write. + **************************************************************************************** + */ +__INLINE void common_write16p(void const *ptr16, uint16_t value) +{ + uint8_t *ptr=(uint8_t*)ptr16; + + *ptr++ = value&0xff; + *ptr = (value&0xff00)>>8; +} + +#if (RW_DEBUG) + +/** + **************************************************************************************** + * @brief Convert bytes to hexadecimal string + * + * @param[out] dest Pointer to the destination string (must be 2x longer than input table) + * @param[in] src Pointer to the bytes table + * @param[in] nb_bytes Number of bytes to display in the string + **************************************************************************************** + */ +void common_bytes_to_string(char* dest, uint8_t* src, uint8_t nb_bytes); +#endif //(RW_DEBUG) + +/** + **************************************************************************************** + * @brief Compares two Bluetooth device addresses + * + * This function checks if the two bd address are equal. + * + * @param[in] bd_address1 Pointer on the first bd address to be compared. + * @param[in] bd_address2 Pointer on the second bd address to be compared. + * + * @return result of the comparison (true: equal | false: different). + **************************************************************************************** + */ +bool common_bdaddr_compare(struct bd_addr const *bd_address1, struct bd_addr const *bd_address2); + +#if (BLE_EMB_PRESENT) +/** + ****************************************************************************** + * @brief Count the number of good channels in a LE map + * @param[in] map Channel Map (bit fields for the 40 BT RF channels) + * @return Number of good channels + ****************************************************************************** + */ +uint8_t common_nb_good_le_channels(const struct le_chnl_map* map); +#endif //BLE_EMB_PRESENT + +#if (BT_EMB_PRESENT) + +/** + ****************************************************************************** + * @brief Convert an duration in baseband slot to a duration in number of ticks. + * @param[in] slot_cnt Duration in number of baseband slot + * @return Duration (in number of ticks). + ****************************************************************************** + */ +uint32_t common_slot_to_duration(uint32_t slot_cnt); + +/** + ****************************************************************************** + * @brief Count the number of good channels in a map + * @param[in] map Channel Map (bit fields for the 79 BT RF channels) + * @return Number of good channels + ****************************************************************************** + */ +uint8_t common_nb_good_channels(const struct chnl_map* map); + +#endif //BT_EMB_PRESENT + +/** + **************************************************************************************** + * @brief Pack parameters from a C structure to a packed buffer + * + * This function packs parameters according to a specific format. It takes care of the + * endianess, padding, required by the compiler. + * + * By default output format is LSB but it can be changed with first character of format string + * - < : LSB output format + * - > : MSB output format + * + * Format strings are the mechanism used to specify the expected layout when packing and unpacking data. They are built + * up from Format Characters, which specify the type of data being packed/unpacked. + * - B : byte - 8bits value + * - H : word - 16bits value + * - L : long - 32-bits value + * - D : 24 bits value + * - XXB: table of several bytes, where XX is the byte number, in decimal + * - XXG: Number of several bytes, where XX is the byte number, in decimal - subject to be swapped according to endianess + * - nB : table size over 1 byte, followed by the table of bytes + * - NB : table size over 2 bytes, followed by the table of bytes + * + * Example: "BBLH12BLnB" => 1 byte | 1 byte | 1 long | 1 short | 12-bytes table | 1 long | table size over 1 byte | n-bytes table + * + * Note: the function works in the same buffer + * + * @param[out] out Output Data Buffer + * @param[in] in Input Data Buffer + * @param[out] out_len Output size of packed data (in bytes) + * @param[in] in_len Input buffer size (in bytes) + * @param[in] format Parameters format + * + * @return Status of the packing operation + ***************************************************************************************** + */ +uint8_t common_util_pack(uint8_t* out, uint8_t* in, uint16_t* out_len, uint16_t in_len, const char* format); + +/** + **************************************************************************************** + * @brief Unpack parameters from an unpacked buffer to a C structure + * + * This function unpacks parameters according to a specific format. It takes care of the + * endianess, padding, required by the compiler. + * + * By default input format is LSB but it can be changed with first character of format string + * - < : LSB input format + * - > : MSB input format + * + * Format strings are the mechanism used to specify the expected layout when packing and unpacking data. They are built + * up from Format Characters, which specify the type of data being packed/unpacked. + * - B : byte - 8bits value + * - H : word - 16bits value + * - L : long - 32-bits value + * - D : 24 bits value + * - XXB: table of several bytes, where XX is the byte number, in decimal + * - XXG: Number of several bytes, where XX is the byte number, in decimal - subject to be swapped according to endianess + * - nB : table size over 1 byte, followed by the table of bytes + * - NB : table size over 2 bytes, followed by the table of bytes + * + * Example: "BBLH12BLnB" => 1 byte | 1 byte | 1 long | 1 short | 12-bytes table | 1 long | table size over 1 byte | n-bytes table + * + * Note: the output buffer provided must be large enough to contain the unpacked data. + * Note2: if a NULL output buffer is provided, the function does not copy the unpacked parameters. It still parses the + * format string and input buffer to return the number of unpacked bytes. Can be used to compute the expected unpacked + * buffer size. + * + * @param[out] out Unpacked parameters buffer + * @param[in] in Packed parameters buffer + * @param[inout] out_len Input: buffer size / Output: size of unpacked data (in bytes) + * @param[in] in_len Size of the packed data (in bytes) + * @param[in] format Parameters format + * + * @return Status of the unpacking operation + ***************************************************************************************** + */ +uint8_t common_util_unpack(uint8_t* out, uint8_t* in, uint16_t* out_len, uint16_t in_len, const char* format); + + +#if (BLE_EMB_PRESENT) + +/** + ***************************************************************************************** + * @brief Get BLE packet duration in us according to PHY and packet size + * + * @param[in] len PDU size in octets + * @param[in] rate PHY Rate (@see enum lld_phy) + * + * @return packet duration in us. + ***************************************************************************************** + */ +uint16_t common_ble_pkt_dur_in_us(uint8_t len, uint8_t rate); +#endif // (BLE_EMB_PRESENT) +/// @} COMMON_UTILS + +#endif // _COMMON_UTILS_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/common/api/common_version.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/common/api/common_version.h new file mode 100755 index 0000000..852959e --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/common/api/common_version.h @@ -0,0 +1,46 @@ +/** + **************************************************************************************** + * + * @file common_version.h + * + * @brief Version definitions for BT5.1 + * + * Copyright (C) RivieraWaves 2009-2018 + * + * + **************************************************************************************** + */ + +#ifndef _COMMON_VERSION_H_ +#define _COMMON_VERSION_H_ +/** + **************************************************************************************** + * @defgroup COMMON_VERSION Version Defines + * @ingroup COMMON + * + * @brief Bluetooth Controller Version definitions. + * + * @{ + **************************************************************************************** + */ +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "common_bt.h" // BT standard definitions + + +/// RWBT SW Major Version +#define RWBT_SW_VERSION_MAJOR (BT51_VERSION) +/// RWBT SW Minor Version +#define RWBT_SW_VERSION_MINOR 0 +/// RWBT SW Build Version +#define RWBT_SW_VERSION_BUILD 8 +/// RWBT SW Major Version +#define RWBT_SW_VERSION_SUB_BUILD 0 + + +/// @} COMMON_VERSION + + +#endif // _COMMON_VERSION_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/dbg/api/dbg.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/dbg/api/dbg.h new file mode 100755 index 0000000..4f077ad --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/dbg/api/dbg.h @@ -0,0 +1,66 @@ +/** +**************************************************************************************** +* +* @file dbg.h +* +* @brief Debug function +* +* Copyright (C) RivieraWaves 2009-2015 +* +* +**************************************************************************************** +*/ +#ifndef DBG_H_ +#define DBG_H_ + +/** +**************************************************************************************** +* @addtogroup DBG +* @ingroup CONTROLLER +* @brief Debug +* +* @{ +**************************************************************************************** +*/ + + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" // stack configuration + +#include "dbg_swdiag.h" // sw profiling definitions + +#include "dbg_trc.h" // debug tracer definition + +/* + * FUNCTION DECLARATION + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Initialization of the BT Debug task + * + * This function initializes the the DBG task + * + * @param[in] init_type Type of initialization (@see enum rwip_init_type) + **************************************************************************************** + */ +void dbg_init(uint8_t init_type); + +/** + **************************************************************************************** + * @brief Send back to host status of platform reset request. + * + * @param status Reset error code + * + **************************************************************************************** + */ +void dbg_platform_reset_complete(uint32_t error); + +///@} DBG + +#endif // DBG_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/dbg/api/dbg_iqgen.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/dbg/api/dbg_iqgen.h new file mode 100755 index 0000000..d965a34 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/dbg/api/dbg_iqgen.h @@ -0,0 +1,153 @@ +/** +**************************************************************************************** +* +* @file dbg_iqgen.h +* +* @brief I&Q Samples Generator API. +* +* Copyright (C) RivieraWaves 2018 +* +* +**************************************************************************************** +*/ + +#ifndef DBG_IQGEN_H_ +#define DBG_IQGEN_H_ + +/** + **************************************************************************************** + * @addtogroup DBGIQGEN + * @ingroup IQ + * @brief Debug SW - I&Q samples Generator. + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" + +#if BLE_IQ_GEN + +#include "ble_reg_iqgen.h" // I&Q sample generator register functions + +/* + * CONSTANT DEFINITIONS + **************************************************************************************** + */ + +/// Maximum number of supported antenna patterns +#define DBG_IQGEN_MAX_ANTENNA (8) + +/// bit defintitions for debug configuration +#define DBG_IQGEN_PATTERN_MODE_BIT (1<<0) +#define DBG_IQGEN_TIMING_MODE_BIT (1<<1) +#define DBG_IQGEN_ANT_ID_MODE_BIT (2<<1) + + +/// I&Q samples generation control +enum dbg_iqgen_ctnl +{ + /// I&Q samples up count + DBG_IQGEN_UPCOUNT = 0, + /// I&Q samples down count + DBG_IQGEN_DOWNCOUNT = 1, + /// I&Q samples fixed value + DBG_IQGEN_FIXEDVAL = 2, + /// I&Q samples PRBS + DBG_IQGEN_PRBSPATTERN = 3, +}; + +/// I&Q samples generation antenna sweep pattern +enum dbg_iqgen_antenna_pattern +{ + /// antenna up-sweep + DBG_IQGEN_ANT_UPSWEEP = 0, + /// antenna up-down sweep + DBG_IQGEN_ANT_UPDNSWEEP = 1, +}; + +/// I&Q samples generation timing mode +enum dbg_iqgen_timing_mode +{ + /// 1us switching/sampling interval + DBG_IQGEN_1US_INTV = 0, + /// 2us switching/sampling interval + DBG_IQGEN_2US_INTV = 1, +}; + +/// antenna switch enable mode +enum dbg_iqgen_antenna_switch_mode +{ + /// Accepts antenna ID switching inputs from baseband + DBG_IQGEN_BASEBAND_SWITCHING = 0, + /// Antenna switching is internally enabled + DBG_IQGEN_INTERNAL_SWITCHING = 1, + +}; + + +/* + * VARIABLE DECLARATION + **************************************************************************************** + */ + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Enable I&Q sample generator + * + * @param[in] nb_antenna Number of antenna (valid range 1-8) + * @param[in] pattern_mode Antenna sweep pattern (@see enum dbg_iqgen_antenna_pattern) + * @param[in] timing_mode Timing interval mode (@see enum dbg_iqgen_timing_mode) + * @param[in] ant_switch_mode Antenna switching mode (@see enum dbg_iqgen_antenna_switch_mode) + * + **************************************************************************************** + */ +void dbg_iqgen_config_enable(uint8_t nb_antenna, uint8_t pattern_mode, uint8_t timing_mode, uint8_t ant_switch_mode); + +/** + **************************************************************************************** + * @brief Disable I&Q sample generator + * + **************************************************************************************** + */ +void dbg_iqgen_disable(); + +/** + **************************************************************************************** + * @brief Configure I&Q samples for a specific antenna + * + * @param[in] antenna ID antenna id (valid range 0-7) + * @param[in] i_cntl configuration mode for I-samples (@see enum dbg_iqgen_cntl) + * @param[in] q_cntl configuration mode for Q-samples (@see enum dbg_iqgen_cntl) + * @param[in] i_val I-samples initial value + * @param[in] q_val Q-samples initial value + * + **************************************************************************************** + */ +void dbg_iqgen_antenna_config(uint8_t antenna_id, uint8_t i_cntl, uint8_t q_cntl, uint8_t i_val, uint8_t q_val); + + +/** +**************************************************************************************** +* @brief I&Q Generator configure +* +* @param[in] param configuration structure (@see hci_dbg_iqgen_cfg_cmd) +**************************************************************************************** +*/ +uint8_t dbg_iqgen_config(struct hci_dbg_iqgen_cfg_cmd const *cfg); + +#endif //BLE_IQ_GEN + +/// @} DBGIQGEN + +#endif // DBG_IQGEN_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/dbg/api/dbg_mwsgen.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/dbg/api/dbg_mwsgen.h new file mode 100755 index 0000000..5e0facb --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/dbg/api/dbg_mwsgen.h @@ -0,0 +1,212 @@ +/** +**************************************************************************************** +* +* @file dbg_mwsgen.h +* +* @brief MWS/WLAN Generator API. +* +* Copyright (C) RivieraWaves 2015 +* +* +**************************************************************************************** +*/ + +#ifndef DBG_MWSGEN_H_ +#define DBG_MWSGEN_H_ + +/** + **************************************************************************************** + * @addtogroup DBGMWSGEN + * @ingroup DBG + * @brief Debug SW - MWS/WLAN Generator. + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_config.h" + +#if (RW_WLAN_COEX_TEST) || (RW_MWS_COEX_TEST) + +#include "ble_reg_mwsgen.h" // MWS Event Generator register functions + +/* + * CONSTANT DEFINITIONS + **************************************************************************************** + */ + +#if (RW_WLAN_COEX) +/// WLAN coexistence disabled +#define DBG_COEX_WLAN_DISABLED 0 +/// WLAN coexistence enabled +#define DBG_COEX_WLAN_ENABLED 1 +#endif + +#if (RW_MWS_COEX) +/// MWS coexistence disabled +#define DBG_COEX_MWS_DISABLED 0 +/// MWS coexistence enabled +#define DBG_COEX_MWS_ENABLED 1 +#endif + +/* + * VARIABLE DECLARATION + **************************************************************************************** + */ +#if (RW_WLAN_COEX_TEST) +extern uint32_t dbg_coex_scenario; +#endif // RW_WLAN_COEX_TEST + +#if (RW_MWS_COEX_TEST) +extern uint32_t dbg_coex_scenario; +#endif // RW_MWS_COEX_TEST + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +#if (RW_MWS_COEX_TEST) +/** + **************************************************************************************** + * @brief Set the scenario for the unitary testing. + * + * @param[in] scenario Scenario type + * + * @return none + * + **************************************************************************************** + */ +uint8_t dbg_mwscoex_scen_set(uint32_t scenario); + +/** + **************************************************************************************** + * @brief Initialize and configure MWS event generator registers to be in MWS mode. + **************************************************************************************** + */ +void dbg_mwsgen_init(void); + +/** + **************************************************************************************** + * @brief Configure MWS generator + * + * @param[in] period Period of the mws signal (us) + * @param[in] duty_cycle Duration of the high level (us) + * @param[in] tx_act Duration of the tx activity (us) + * @param[in] rx_act Duration of the rx activity (us) + * + **************************************************************************************** + */ +void dbg_mwsgen_config(uint32_t period, uint32_t duty_cycle, uint32_t tx_act, uint32_t rx_act); + +/** + **************************************************************************************** + * @brief Configure the WLAN COEX mode for BT. + * + * @param[in] txmode + * @param[in] rxmode + * @param[in] txmsk + * @param[in] rxmsk + * @param[in] txfmsk + * @param[in] rxfmsk + * @param[in] scanfmsk + * @param[in] knudge + * + **************************************************************************************** + */ +void dbg_mws_config(uint8_t txmode, uint8_t rxmode, uint8_t txmsk, uint8_t rxmsk, uint8_t txfms, uint8_t rxfmsk, uint8_t scanfmsk, uint8_t knudge); + +/** + **************************************************************************************** + * @brief Start the MWS signal generator. + * + **************************************************************************************** + */ +void dbg_mwsgen_start(void); + +/** + **************************************************************************************** + * @brief Stop the MWS signal generator. + * + **************************************************************************************** + */ +void dbg_mwsgen_stop(void); +#endif // RW_MWS_COEX_TEST + +#if (RW_WLAN_COEX_TEST) +/** + **************************************************************************************** + * @brief Set the scenario for the unitary testing. + * + * @param[in] scenario Scenario type + * + * @return none + * + **************************************************************************************** + */ + +uint8_t dbg_wlcoex_scen_set(uint32_t scenario); + +/** + **************************************************************************************** + * @brief Initialize and configure MWS event generator registers to be in WLAN mode. + **************************************************************************************** + */ +void dbg_wlangen_init(void); + +/** + **************************************************************************************** + * @brief Set the period and duty cycle for the wlrxbsy signal. + * + * @param[in] period Period of the wlrxbsy signal (us) + * @param[in] duty_cycle Duration of the high level (us) + * @param[in] tx_act Duration of the tx activity (us) + * @param[in] rx_act Duration of the rx activity (us) + * + **************************************************************************************** + */ +void dbg_wlangen_config(uint32_t period, uint32_t duty_cycle, uint32_t tx_act, uint32_t rx_act); + +/** + **************************************************************************************** + * @brief Configure the WLAN COEX mode for BT. + * + * @param[in] txmode + * @param[in] rxmode + * @param[in] txmsk + * @param[in] rxmsk + * @param[in] txthr + * @param[in] rxthr + * @param[in] pduration + * @param[in] pdelay + * + **************************************************************************************** + */ +void dbg_wlan_config(uint8_t txmode, uint8_t rxmode, uint8_t txmsk, uint8_t rxmsk, uint8_t txthr, uint8_t rxthr, uint8_t pduration, uint8_t pdelay); + +/** + **************************************************************************************** + * @brief Start the wlrxbs signal generator. + * + **************************************************************************************** + */ +void dbg_wlangen_start(void); + +/** + **************************************************************************************** + * @brief Stop the wlrxbs signal generator. + * + **************************************************************************************** + */ +void dbg_wlangen_stop(void); +#endif // RW_WLAN_COEX_TEST + +#endif // (RW_WLAN_COEX_TEST) || (RW_MWS_COEX_TEST) + +/// @} DBGMWSGEN + +#endif // DBG_MWSGEN_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/dbg/api/dbg_swdiag.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/dbg/api/dbg_swdiag.h new file mode 100755 index 0000000..ab19dc7 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/dbg/api/dbg_swdiag.h @@ -0,0 +1,1197 @@ +/** +**************************************************************************************** +* +* @file dbg_swdiag.h +* +* @brief SW profiling module +* +* Copyright (C) RivieraWaves 2009-2015 +* +* +**************************************************************************************** +*/ + +#ifndef DBG_SWDIAG_H_ +#define DBG_SWDIAG_H_ + +/** + **************************************************************************************** + * @addtogroup DBGSWDIAG Diag + * @ingroup DBG + * @brief Debug SW profiling module + * + * SW profiling is a debug feature that provides user a configurable way to analyze SW execution performance or + * behavior, such as timings, state machines, bit field values and so on. + * It manages the SW state representation over HW digital diagnostic signals (diagports), from the signals selection to + * the toggling of real HW signals. + * HW signals representing the SW execution could then be watched on a logic analyzer in parallel with HW internal + * signals, that could be very useful for low level debugging. + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_config.h" // stack configuration + +#if (!RW_SWDIAG) + +/// Macro used to set a SW diag to specific value +#define DBG_SWDIAG(bank , field , value) + +#else //RW_SWDIAG + +#if (BT_DUAL_MODE) +#include "ble_reg_ipcore.h" // btdm core registers +#else // !(BT_DUAL_MODE) +#if (BT_EMB_PRESENT) // TODO not fully agree with this +#include "ble_reg_btcore.h" // bt core registers +#elif (BLE_EMB_PRESENT) +#include "ble_reg_blecore.h" // ble core registers +#endif //BT_EMB_PRESENT / BLE_EMB_PRESENT +#endif // (BT_DUAL_MODE) + +/* + * DEFINES + **************************************************************************************** + */ + +/// Number of HW diagport banks +#define DBG_SWDIAG_NB_HW_BANKS 4 + +/// Undefined configuration +#define DBG_SWDIAG_UNDEFINED 0xFF + + +/* + * MACROS + **************************************************************************************** + */ +#if (BT_DUAL_MODE) +#define SW_DIAG_SET ip_swprofiling_set +#define SW_DIAG_GET ip_swprofiling_get +#else // !(BT_DUAL_MODE) +#if (BT_EMB_PRESENT) +#define SW_DIAG_SET bt_swprofiling_set +#define SW_DIAG_GET bt_swprofiling_get +#elif (BLE_EMB_PRESENT) +#define SW_DIAG_SET ble_swprofiling_set +#define SW_DIAG_GET ble_swprofiling_get +#endif //BT_EMB_PRESENT / BLE_EMB_PRESENT +#endif // (BT_DUAL_MODE) + +/// Macro used to set a SW diag to specific value +#define DBG_SWDIAG(bank , field , value) \ + if(sw_to_hw[DBG_SWDIAG_##bank] != DBG_SWDIAG_UNDEFINED) \ + { \ + SW_DIAG_SET( ((SW_DIAG_GET()) & (~(DBG_SWDIAG_##bank##_##field##_MASK << (8 * sw_to_hw[DBG_SWDIAG_##bank])))) | ((((value << DBG_SWDIAG_##bank##_##field##_OFFSET) & DBG_SWDIAG_##bank##_##field##_MASK) << (8*sw_to_hw[DBG_SWDIAG_##bank]))) ); \ + } + + +/* + * SW DIAGS MAP + **************************************************************************************** + */ + +enum dbg_swdiag +{ + /** + ****************************************************************************************** + * @brief BANK 0 : BT_ISR + ****************************************************************************************** + */ + DBG_SWDIAG_BT_ISR = 0, + + DBG_SWDIAG_BT_ISR_CLK_OFFSET = 0, + DBG_SWDIAG_BT_ISR_CLK_MASK = 0x01, + + DBG_SWDIAG_BT_ISR_RX_OFFSET = 1, + DBG_SWDIAG_BT_ISR_RX_MASK = 0x02, + + DBG_SWDIAG_BT_ISR_SLP_OFFSET = 2, + DBG_SWDIAG_BT_ISR_SLP_MASK = 0x04, + + DBG_SWDIAG_BT_ISR_GROSSTGT_OFFSET = 3, + DBG_SWDIAG_BT_ISR_GROSSTGT_MASK = 0x08, + + DBG_SWDIAG_BT_ISR_FRAME_OFFSET = 4, + DBG_SWDIAG_BT_ISR_FRAME_MASK = 0x10, + + DBG_SWDIAG_BT_ISR_FINETGT_OFFSET = 5, + DBG_SWDIAG_BT_ISR_FINETGT_MASK = 0x20, + + DBG_SWDIAG_BT_ISR_SKET_OFFSET = 6, + DBG_SWDIAG_BT_ISR_SKET_MASK = 0x40, + + DBG_SWDIAG_BT_ISR_SW_OFFSET = 7, + DBG_SWDIAG_BT_ISR_SW_MASK = 0x80, + + /** + ****************************************************************************************** + * @brief BANK 1 : SLEEP + ****************************************************************************************** + */ + DBG_SWDIAG_SLEEP = 1, + + DBG_SWDIAG_SLEEP_SLEEP_OFFSET = 0, + DBG_SWDIAG_SLEEP_SLEEP_MASK = 0x01, + + DBG_SWDIAG_SLEEP_FUNC_OFFSET = 1, + DBG_SWDIAG_SLEEP_FUNC_MASK = 0x02, + + DBG_SWDIAG_SLEEP_WAKEUP_END_OFFSET = 2, + DBG_SWDIAG_SLEEP_WAKEUP_END_MASK = 0x04, + + DBG_SWDIAG_SLEEP_ALGO_OFFSET = 4, + DBG_SWDIAG_SLEEP_ALGO_MASK = 0xF0, + + /** + ****************************************************************************************** + * @brief BANK 2 : ISR + ****************************************************************************************** + */ + DBG_SWDIAG_ISR = 2, + + DBG_SWDIAG_ISR_UART_OFFSET = 0, + DBG_SWDIAG_ISR_UART_MASK = 0x01, + + DBG_SWDIAG_ISR_BT_OFFSET = 1, + DBG_SWDIAG_ISR_BT_MASK = 0x02, + + DBG_SWDIAG_ISR_PS2_OFFSET = 1, + DBG_SWDIAG_ISR_PS2_MASK = 0x02, + + DBG_SWDIAG_ISR_BLE_OFFSET = 2, + DBG_SWDIAG_ISR_BLE_MASK = 0x04, + + DBG_SWDIAG_ISR_RWIP_OFFSET = 3, + DBG_SWDIAG_ISR_RWIP_MASK = 0x08, + + DBG_SWDIAG_ISR_GPIO_OFFSET = 4, + DBG_SWDIAG_ISR_GPIO_MASK = 0x10, + + DBG_SWDIAG_ISR_RTC0_OFFSET = 5, + DBG_SWDIAG_ISR_RTC0_MASK = 0x20, + + DBG_SWDIAG_ISR_BTDM_OFFSET = 5, + DBG_SWDIAG_ISR_BTDM_MASK = 0x20, + + DBG_SWDIAG_ISR_SPI_OFFSET = 6, + DBG_SWDIAG_ISR_SPI_MASK = 0x40, + + DBG_SWDIAG_ISR_WFI_OFFSET = 7, + DBG_SWDIAG_ISR_WFI_MASK = 0x80, + + /** + ****************************************************************************************** + * @brief BANK 3 : BLEISR + ****************************************************************************************** + */ + DBG_SWDIAG_BLE_ISR = 3, + + DBG_SWDIAG_BLE_ISR_RXINT_OFFSET = 0, + DBG_SWDIAG_BLE_ISR_RXINT_MASK = 0x01, + + DBG_SWDIAG_BLE_ISR_TXINT_OFFSET = 1, + DBG_SWDIAG_BLE_ISR_TXINT_MASK = 0x02, + + DBG_SWDIAG_BLE_ISR_EVENTINT_OFFSET = 2, + DBG_SWDIAG_BLE_ISR_EVENTINT_MASK = 0x04, + + DBG_SWDIAG_BLE_ISR_SKIPINT_OFFSET = 3, + DBG_SWDIAG_BLE_ISR_SKIPINT_MASK = 0x08, + + DBG_SWDIAG_BLE_ISR_ERRORINT_OFFSET = 4, + DBG_SWDIAG_BLE_ISR_ERRORINT_MASK = 0x10, + + DBG_SWDIAG_BLE_ISR_AUDIO0INT_OFFSET = 5, + DBG_SWDIAG_BLE_ISR_AUDIO0INT_MASK = 0x20, + + DBG_SWDIAG_BLE_ISR_AUDIO1INT_OFFSET = 6, + DBG_SWDIAG_BLE_ISR_AUDIO1INT_MASK = 0x40, + + DBG_SWDIAG_BLE_ISR_AUDIO2INT_OFFSET = 7, + DBG_SWDIAG_BLE_ISR_AUDIO2INT_MASK = 0x80, + + DBG_SWDIAG_BLE_ISR_RXISOINT_OFFSET = 5, + DBG_SWDIAG_BLE_ISR_RXISOINT_MASK = 0x20, + + DBG_SWDIAG_BLE_ISR_TXISOINT_OFFSET = 6, + DBG_SWDIAG_BLE_ISR_TXISOINT_MASK = 0x40, + + /** + ****************************************************************************************** + * @brief BANK 4 : FLASH + ****************************************************************************************** + */ + DBG_SWDIAG_FLASH = 4, + + DBG_SWDIAG_FLASH_STATE_OFFSET = 0, + DBG_SWDIAG_FLASH_STATE_MASK = 0x07, + + DBG_SWDIAG_FLASH_SUBSTATE_OFFSET = 3, + DBG_SWDIAG_FLASH_SUBSTATE_MASK = 0x38, + + DBG_SWDIAG_FLASH_MANAGE_OFFSET = 6, + DBG_SWDIAG_FLASH_MANAGE_MASK = 0x40, + + DBG_SWDIAG_FLASH_CALLBACK_OFFSET = 7, + DBG_SWDIAG_FLASH_CALLBACK_MASK = 0x80, + + /** + ****************************************************************************************** + * @brief BANK 5 : Reserved + ****************************************************************************************** + */ + + /** + ****************************************************************************************** + * @brief BANK 6 : Event execution overview. + ****************************************************************************************** + */ + DBG_SWDIAG_EVT = 6, + + DBG_SWDIAG_EVT_TIMER_OFFSET = 0, + DBG_SWDIAG_EVT_TIMER_MASK = 0x01, + + DBG_SWDIAG_EVT_MESSAGE_OFFSET = 1, + DBG_SWDIAG_EVT_MESSAGE_MASK = 0x02, + + /** + ****************************************************************************************** + * @brief BANK 8 : AFH + ****************************************************************************************** + */ + DBG_SWDIAG_AFH = 8, + + DBG_SWDIAG_AFH_TO_OFFSET = 0, + DBG_SWDIAG_AFH_TO_MASK = 0x01, + + DBG_SWDIAG_AFH_LMP_TX_OFFSET = 1, + DBG_SWDIAG_AFH_LMP_TX_MASK = 0x02, + + DBG_SWDIAG_AFH_CLASS_RX_OFFSET = 2, + DBG_SWDIAG_AFH_CLASS_RX_MASK = 0x04, + + DBG_SWDIAG_AFH_HOST_OFFSET = 3, + DBG_SWDIAG_AFH_HOST_MASK = 0x08, + + DBG_SWDIAG_AFH_REPORT_TO_OFFSET = 4, + DBG_SWDIAG_AFH_REPORT_TO_MASK = 0x10, + + DBG_SWDIAG_AFH_HSSI_OFFSET = 5, + DBG_SWDIAG_AFH_HSSI_MASK = 0x20, + + DBG_SWDIAG_AFH_CFM_OFFSET = 6, + DBG_SWDIAG_AFH_CFM_MASK = 0x40, + + DBG_SWDIAG_AFH_LMP_RX_OFFSET = 7, + DBG_SWDIAG_AFH_LMP_RX_MASK = 0x80, + + /** + ****************************************************************************************** + * @brief BANK 9 : SWITCH + ****************************************************************************************** + */ + DBG_SWDIAG_SWITCH = 9, + + DBG_SWDIAG_SWITCH_LOOP_OFFSET = 0, + DBG_SWDIAG_SWITCH_LOOP_MASK = 0x01, + + DBG_SWDIAG_SWITCH_SM_OFFSET = 1, + DBG_SWDIAG_SWITCH_SM_MASK = 0x06, + + DBG_SWDIAG_SWITCH_RSW_FAIL_OFFSET = 3, + DBG_SWDIAG_SWITCH_RSW_FAIL_MASK = 0x08, + + /** + ****************************************************************************************** + * @brief BANK 11 : VALUE8 + ****************************************************************************************** + */ + DBG_SWDIAG_VALUE8 = 11, + + DBG_SWDIAG_VALUE8_VALUE_OFFSET = 0, + DBG_SWDIAG_VALUE8_VALUE_MASK = 0xFF, + + /** + ****************************************************************************************** + * @brief BANK 12 : VALUE16 + ****************************************************************************************** + */ + DBG_SWDIAG_VALUE16 = 12, + + DBG_SWDIAG_VALUE16_VALUE_OFFSET = 0, + DBG_SWDIAG_VALUE16_VALUE_MASK = 0xFF, + + /** + ****************************************************************************************** + * @brief BANK 13 : SNIFF + ****************************************************************************************** + */ + DBG_SWDIAG_SNIFF = 13, + + DBG_SWDIAG_SNIFF_EVT_START_OFFSET = 0, + DBG_SWDIAG_SNIFF_EVT_START_MASK = 0x01, + + DBG_SWDIAG_SNIFF_EVT_CANCELED_OFFSET = 1, + DBG_SWDIAG_SNIFF_EVT_CANCELED_MASK = 0x02, + + DBG_SWDIAG_SNIFF_FRM_ISR_OFFSET = 2, + DBG_SWDIAG_SNIFF_FRM_ISR_MASK = 0x04, + + DBG_SWDIAG_SNIFF_RX_ISR_OFFSET = 3, + DBG_SWDIAG_SNIFF_RX_ISR_MASK = 0x08, + + DBG_SWDIAG_SNIFF_SCHED_OFFSET = 4, + DBG_SWDIAG_SNIFF_SCHED_MASK = 0x10, + + /** + ****************************************************************************************** + * @brief BANK 14 : SCO + ****************************************************************************************** + */ + DBG_SWDIAG_SCO = 14, + + DBG_SWDIAG_SCO_EVT_START_OFFSET = 0, + DBG_SWDIAG_SCO_EVT_START_MASK = 0x01, + + DBG_SWDIAG_SCO_EVT_STOP_OFFSET = 1, + DBG_SWDIAG_SCO_EVT_STOP_MASK = 0x02, + + DBG_SWDIAG_SCO_EVT_CANCELED_OFFSET = 2, + DBG_SWDIAG_SCO_EVT_CANCELED_MASK = 0x04, + + DBG_SWDIAG_SCO_FRM_ISR_OFFSET = 3, + DBG_SWDIAG_SCO_FRM_ISR_MASK = 0x08, + + DBG_SWDIAG_SCO_RESCHED_OFFSET = 4, + DBG_SWDIAG_SCO_RESCHED_MASK = 0x10, + + DBG_SWDIAG_SCO_UPDATE_OFFSET = 5, + DBG_SWDIAG_SCO_UPDATE_MASK = 0x60, + + DBG_SWDIAG_SCO_AUDIO_ISR_OFFSET = 7, + DBG_SWDIAG_SCO_AUDIO_ISR_MASK = 0x80, + + + /** + ****************************************************************************************** + * @brief BANK 17 : PAGE + ****************************************************************************************** + */ + DBG_SWDIAG_PAGE = 17, + + DBG_SWDIAG_PAGE_PSCAN_EVT_START_OFFSET = 0, + DBG_SWDIAG_PAGE_PSCAN_EVT_START_MASK = 0x01, + + DBG_SWDIAG_PAGE_PSCAN_EVT_CANCELED_OFFSET = 1, + DBG_SWDIAG_PAGE_PSCAN_EVT_CANCELED_MASK = 0x02, + + DBG_SWDIAG_PAGE_PSCAN_FRM_ISR_OFFSET = 2, + DBG_SWDIAG_PAGE_PSCAN_FRM_ISR_MASK = 0x04, + + DBG_SWDIAG_PAGE_PSCAN_KERNEL_EVT_OFFSET = 3, + DBG_SWDIAG_PAGE_PSCAN_KERNEL_EVT_MASK = 0x08, + + DBG_SWDIAG_PAGE_PAGE_EVT_START_OFFSET = 4, + DBG_SWDIAG_PAGE_PAGE_EVT_START_MASK = 0x10, + + DBG_SWDIAG_PAGE_PAGE_EVT_CANCELED_OFFSET = 5, + DBG_SWDIAG_PAGE_PAGE_EVT_CANCELED_MASK = 0x20, + + DBG_SWDIAG_PAGE_PAGE_FRM_ISR_OFFSET = 6, + DBG_SWDIAG_PAGE_PAGE_FRM_ISR_MASK = 0x40, + + DBG_SWDIAG_PAGE_PAGE_STEP_OFFSET = 7, + DBG_SWDIAG_PAGE_PAGE_STEP_MASK = 0x80, + + /** + ****************************************************************************************** + * @brief BANK 18 : INQ + ****************************************************************************************** + */ + DBG_SWDIAG_INQ = 18, + + DBG_SWDIAG_INQ_ISCAN_EVT_START_OFFSET = 0, + DBG_SWDIAG_INQ_ISCAN_EVT_START_MASK = 0x01, + + DBG_SWDIAG_INQ_ISCAN_EVT_CANCELED_OFFSET = 1, + DBG_SWDIAG_INQ_ISCAN_EVT_CANCELED_MASK = 0x02, + + DBG_SWDIAG_INQ_ISCAN_FRM_ISR_OFFSET = 2, + DBG_SWDIAG_INQ_ISCAN_FRM_ISR_MASK = 0x04, + + DBG_SWDIAG_INQ_INQ_EVT_START_OFFSET = 3, + DBG_SWDIAG_INQ_INQ_EVT_START_MASK = 0x08, + + DBG_SWDIAG_INQ_INQ_EVT_CANCELED_OFFSET = 4, + DBG_SWDIAG_INQ_INQ_EVT_CANCELED_MASK = 0x10, + + DBG_SWDIAG_INQ_INQ_FRM_ISR_OFFSET = 5, + DBG_SWDIAG_INQ_INQ_FRM_ISR_MASK = 0x20, + + /** + ****************************************************************************************** + * @brief BANK 19 : ACL + ****************************************************************************************** + */ + DBG_SWDIAG_ACL = 19, + + DBG_SWDIAG_ACL_EVT_START_OFFSET = 0, + DBG_SWDIAG_ACL_EVT_START_MASK = 0x01, + + DBG_SWDIAG_ACL_EVT_STOP_OFFSET = 1, + DBG_SWDIAG_ACL_EVT_STOP_MASK = 0x02, + + DBG_SWDIAG_ACL_EVT_CANCELED_OFFSET = 2, + DBG_SWDIAG_ACL_EVT_CANCELED_MASK = 0x04, + + DBG_SWDIAG_ACL_FRM_ISR_OFFSET = 3, + DBG_SWDIAG_ACL_FRM_ISR_MASK = 0x08, + + DBG_SWDIAG_ACL_CLK_ISR_OFFSET = 4, + DBG_SWDIAG_ACL_CLK_ISR_MASK = 0x10, + + DBG_SWDIAG_ACL_PROG_EN_OFFSET = 5, + DBG_SWDIAG_ACL_PROG_EN_MASK = 0x20, + + DBG_SWDIAG_ACL_SKET_ISR_OFFSET = 6, + DBG_SWDIAG_ACL_SKET_ISR_MASK = 0x40, + + DBG_SWDIAG_ACL_PARITY_OFFSET = 7, + DBG_SWDIAG_ACL_PARITY_MASK = 0x80, + + /** + ****************************************************************************************** + * @brief BANK 20 : RSW + ****************************************************************************************** + */ + DBG_SWDIAG_RSW = 20, + + DBG_SWDIAG_RSW_EVT_START_OFFSET = 0, + DBG_SWDIAG_RSW_EVT_START_MASK = 0x01, + + DBG_SWDIAG_RSW_EVT_CANCELED_OFFSET = 1, + DBG_SWDIAG_RSW_EVT_CANCELED_MASK = 0x02, + + DBG_SWDIAG_RSW_FRM_ISR_OFFSET = 2, + DBG_SWDIAG_RSW_FRM_ISR_MASK = 0x04, + + DBG_SWDIAG_RSW_STEP_OFFSET = 3, + DBG_SWDIAG_RSW_STEP_MASK = 0x08, + + DBG_SWDIAG_RSW_TX_SLOTOFF_OFFSET = 4, + DBG_SWDIAG_RSW_TX_SLOTOFF_MASK = 0x10, + + DBG_SWDIAG_RSW_TX_PARITY_OFFSET = 5, + DBG_SWDIAG_RSW_TX_PARITY_MASK = 0x20, + + DBG_SWDIAG_RSW_TDD_PARITY_OFFSET = 6, + DBG_SWDIAG_RSW_TDD_PARITY_MASK = 0x40, + + /** + ****************************************************************************************** + * @brief BANK 21 : TX + ****************************************************************************************** + */ + DBG_SWDIAG_TX = 21, + + DBG_SWDIAG_TX_LMP_TX_OFFSET = 0, + DBG_SWDIAG_TX_LMP_TX_MASK = 0x01, + + DBG_SWDIAG_TX_ACL_TX_OFFSET = 1, + DBG_SWDIAG_TX_ACL_TX_MASK = 0x02, + + DBG_SWDIAG_TX_SW_IDX_OFFSET = 2, + DBG_SWDIAG_TX_SW_IDX_MASK = 0x04, + + DBG_SWDIAG_TX_HW_IDX_OFFSET = 3, + DBG_SWDIAG_TX_HW_IDX_MASK = 0x08, + + DBG_SWDIAG_TX_TX_CNT_OFFSET = 4, + DBG_SWDIAG_TX_TX_CNT_MASK = 0x30, + + /** + ****************************************************************************************** + * @brief BANK 22 : DATA + ****************************************************************************************** + */ + DBG_SWDIAG_DATA = 22, + + DBG_SWDIAG_DATA_LMP_TX_OFFSET = 0, + DBG_SWDIAG_DATA_LMP_TX_MASK = 0x01, + + DBG_SWDIAG_DATA_ACL_TX_OFFSET = 1, + DBG_SWDIAG_DATA_ACL_TX_MASK = 0x02, + + DBG_SWDIAG_DATA_LMP_RX_OFFSET = 2, + DBG_SWDIAG_DATA_LMP_RX_MASK = 0x04, + + DBG_SWDIAG_DATA_ACL_RX_OFFSET = 3, + DBG_SWDIAG_DATA_ACL_RX_MASK = 0x08, + + DBG_SWDIAG_DATA_LMP_ACK_OFFSET = 4, + DBG_SWDIAG_DATA_LMP_ACK_MASK = 0x10, + + DBG_SWDIAG_DATA_ACL_ACK_OFFSET = 5, + DBG_SWDIAG_DATA_ACL_ACK_MASK = 0x20, + + /** + ****************************************************************************************** + * @brief BANK 23 : ECDH + ****************************************************************************************** + */ + DBG_SWDIAG_ECDH = 23, + + DBG_SWDIAG_ECDH_BUSY_OFFSET = 0, + DBG_SWDIAG_ECDH_BUSY_MASK = 0x01, + + DBG_SWDIAG_ECDH_COMPUTE_OFFSET = 1, + DBG_SWDIAG_ECDH_COMPUTE_MASK = 0x02, + + DBG_SWDIAG_ECDH_MULT_OFFSET = 2, + DBG_SWDIAG_ECDH_MULT_MASK = 0x04, + + DBG_SWDIAG_ECDH_END_OFFSET = 3, + DBG_SWDIAG_ECDH_END_MASK = 0x08, + + DBG_SWDIAG_ECDH_INV_OFFSET = 4, + DBG_SWDIAG_ECDH_INV_MASK = 0x10, + + /** + ****************************************************************************************** + * @brief BANK 24 : PCA + ****************************************************************************************** + */ + DBG_SWDIAG_PCA = 24, + + DBG_SWDIAG_PCA_FRAME_SYNC_INT_OFFSET = 0, + DBG_SWDIAG_PCA_FRAME_SYNC_INT_MASK = 0x01, + + DBG_SWDIAG_PCA_MTOFF_LT_INT_OFFSET = 1, + DBG_SWDIAG_PCA_MTOFF_LT_INT_MASK = 0x02, + + DBG_SWDIAG_PCA_SLOT_INT_OFFSET = 2, + DBG_SWDIAG_PCA_SLOT_INT_MASK = 0x04, + + DBG_SWDIAG_PCA_COARSE_CLK_ADJ_OFFSET = 3, + DBG_SWDIAG_PCA_COARSE_CLK_ADJ_MASK = 0x08, + + DBG_SWDIAG_PCA_EVT_START_OFFSET = 4, + DBG_SWDIAG_PCA_EVT_START_MASK = 0x10, + + DBG_SWDIAG_PCA_EVT_CANCELED_OFFSET = 5, + DBG_SWDIAG_PCA_EVT_CANCELED_MASK = 0x20, + + DBG_SWDIAG_PCA_ALARM_INSTANT_OFFSET = 6, + DBG_SWDIAG_PCA_ALARM_INSTANT_MASK = 0x40, + + DBG_SWDIAG_PCA_CLK_DRAG_OFFSET = 7, + DBG_SWDIAG_PCA_CLK_DRAG_MASK = 0x80, + + /** + ****************************************************************************************** + * @brief BANK 25 : BCST + ****************************************************************************************** + */ + DBG_SWDIAG_BCST = 25, + + DBG_SWDIAG_BCST_FRM_ISR_OFFSET = 0, + DBG_SWDIAG_BCST_FRM_ISR_MASK = 0x01, + + DBG_SWDIAG_BCST_EVT_START_OFFSET = 1, + DBG_SWDIAG_BCST_EVT_START_MASK = 0x02, + + DBG_SWDIAG_BCST_SKET_ISR_OFFSET = 2, + DBG_SWDIAG_BCST_SKET_ISR_MASK = 0x04, + + DBG_SWDIAG_BCST_EVT_CANCELED_OFFSET = 3, + DBG_SWDIAG_BCST_EVT_CANCELED_MASK = 0x08, + + DBG_SWDIAG_BCST_ACL_TX_OFFSET = 4, + DBG_SWDIAG_BCST_ACL_TX_MASK = 0x10, + + DBG_SWDIAG_BCST_LMP_TX_OFFSET = 5, + DBG_SWDIAG_BCST_LMP_TX_MASK = 0x20, + + DBG_SWDIAG_BCST_PDU_TX_CFM_OFFSET = 6, + DBG_SWDIAG_BCST_PDU_TX_CFM_MASK = 0x40, + + DBG_SWDIAG_BCST_PDU_RX_OFFSET = 7, + DBG_SWDIAG_BCST_PDU_RX_MASK = 0x80, + + /** + ****************************************************************************************** + * @brief IP_ISR - 26 + ****************************************************************************************** + */ + DBG_SWDIAG_IP_ISR = 26, + + DBG_SWDIAG_IP_ISR_CLKNINT_OFFSET = 0, + DBG_SWDIAG_IP_ISR_CLKNINT_MASK = 0x01, + + DBG_SWDIAG_IP_ISR_FINETGTINT_OFFSET = 1, + DBG_SWDIAG_IP_ISR_FINETGTINT_MASK = 0x02, + + DBG_SWDIAG_IP_ISR_GROSSTGTINT_OFFSET = 2, + DBG_SWDIAG_IP_ISR_GROSSTGTINT_MASK = 0x04, + + DBG_SWDIAG_IP_ISR_SLPINT_OFFSET = 3, + DBG_SWDIAG_IP_ISR_SLPINT_MASK = 0x08, + + DBG_SWDIAG_IP_ISR_CRYPTINT_OFFSET = 4, + DBG_SWDIAG_IP_ISR_CRYPTINT_MASK = 0x10, + + DBG_SWDIAG_IP_ISR_SWINT_OFFSET = 5, + DBG_SWDIAG_IP_ISR_SWINT_MASK = 0x20, + + DBG_SWDIAG_IP_ISR_TIMESTAMPINT_OFFSET = 6, + DBG_SWDIAG_IP_ISR_TIMESTAMPINT_MASK = 0x40, + + DBG_SWDIAG_IP_ISR_FIFOINT_OFFSET = 7, + DBG_SWDIAG_IP_ISR_FIFOINT_MASK = 0x80, + + /** + ****************************************************************************************** + * @brief RSA Algorithm - 27 + ****************************************************************************************** + */ + DBG_SWDIAG_RSA = 27, + + DBG_SWDIAG_RSA_BUSY_OFFSET = 0, + DBG_SWDIAG_RSA_BUSY_MASK = 0x01, + + DBG_SWDIAG_RSA_COMPUTE_OFFSET = 1, + DBG_SWDIAG_RSA_COMPUTE_MASK = 0x02, + + /** + ****************************************************************************************** + * @brief SYNC SCAN - 28 + ****************************************************************************************** + */ + DBG_SWDIAG_SSCAN = 28, + + DBG_SWDIAG_SSCAN_FRM_ISR_OFFSET = 0, + DBG_SWDIAG_SSCAN_FRM_ISR_MASK = 0x01, + + DBG_SWDIAG_SSCAN_EVT_START_OFFSET = 1, + DBG_SWDIAG_SSCAN_EVT_START_MASK = 0x02, + + DBG_SWDIAG_SSCAN_START_OFFSET = 2, + DBG_SWDIAG_SSCAN_START_MASK = 0x04, + + DBG_SWDIAG_SSCAN_EVT_CANCELED_OFFSET = 3, + DBG_SWDIAG_SSCAN_EVT_CANCELED_MASK = 0x08, + + DBG_SWDIAG_SSCAN_FRM_CBK_OFFSET = 4, + DBG_SWDIAG_SSCAN_FRM_CBK_MASK = 0x10, + + DBG_SWDIAG_SSCAN_STP_RX_OFFSET = 5, + DBG_SWDIAG_SSCAN_STP_RX_MASK = 0x20, + + DBG_SWDIAG_SSCAN_STP_RX_OK_OFFSET = 6, + DBG_SWDIAG_SSCAN_STP_RX_OK_MASK = 0x40, + + DBG_SWDIAG_SSCAN_TIMEOUT_OFFSET = 7, + DBG_SWDIAG_SSCAN_TIMEOUT_MASK = 0x80, + + /** + ****************************************************************************************** + * @brief BANK 29 : LE SCAN + ****************************************************************************************** + */ + DBG_SWDIAG_LESCAN = 29, + + DBG_SWDIAG_LESCAN_START_OFFSET = 0, + DBG_SWDIAG_LESCAN_START_MASK = 0x01, + + DBG_SWDIAG_LESCAN_STOP_OFFSET = 1, + DBG_SWDIAG_LESCAN_STOP_MASK = 0x02, + + DBG_SWDIAG_LESCAN_EVT_START_OFFSET = 2, + DBG_SWDIAG_LESCAN_EVT_START_MASK = 0x04, + + DBG_SWDIAG_LESCAN_EVT_CANCELED_OFFSET = 3, + DBG_SWDIAG_LESCAN_EVT_CANCELED_MASK = 0x08, + + DBG_SWDIAG_LESCAN_FRM_RX_ISR_OFFSET = 4, + DBG_SWDIAG_LESCAN_FRM_RX_ISR_MASK = 0x10, + + DBG_SWDIAG_LESCAN_FRM_EOF_ISR_OFFSET = 5, + DBG_SWDIAG_LESCAN_FRM_EOF_ISR_MASK = 0x20, + + DBG_SWDIAG_LESCAN_SCHED_OFFSET = 6, + DBG_SWDIAG_LESCAN_SCHED_MASK = 0x40, + + DBG_SWDIAG_LESCAN_PKT_RX_OFFSET = 7, + DBG_SWDIAG_LESCAN_PKT_RX_MASK = 0x80, + + /** + ****************************************************************************************** + * @brief BANK 30 : SCH_PROG + ****************************************************************************************** + */ + DBG_SWDIAG_SCH_PROG = 30, + + DBG_SWDIAG_SCH_PROG_RXTX_ISR_OFFSET = 0, + DBG_SWDIAG_SCH_PROG_RXTX_ISR_MASK = 0x01, + + DBG_SWDIAG_SCH_PROG_END_ISR_OFFSET = 1, + DBG_SWDIAG_SCH_PROG_END_ISR_MASK = 0x02, + + DBG_SWDIAG_SCH_PROG_PROG_PUSH_OFFSET = 2, + DBG_SWDIAG_SCH_PROG_PROG_PUSH_MASK = 0x04, + + DBG_SWDIAG_SCH_PROG_SKIP_OFFSET = 3, + DBG_SWDIAG_SCH_PROG_SKIP_MASK = 0x08, + + DBG_SWDIAG_SCH_PROG_NB_PROG_OFFSET = 4, + DBG_SWDIAG_SCH_PROG_NB_PROG_MASK = 0xF0, + + /** + ****************************************************************************************** + * @brief BANK 31 : LE INITIATING + ****************************************************************************************** + */ + DBG_SWDIAG_LEINIT = 31, + + DBG_SWDIAG_LEINIT_START_OFFSET = 0, + DBG_SWDIAG_LEINIT_START_MASK = 0x01, + + DBG_SWDIAG_LEINIT_STOP_OFFSET = 1, + DBG_SWDIAG_LEINIT_STOP_MASK = 0x02, + + DBG_SWDIAG_LEINIT_EVT_START_OFFSET = 2, + DBG_SWDIAG_LEINIT_EVT_START_MASK = 0x04, + + DBG_SWDIAG_LEINIT_EVT_CANCELED_OFFSET = 3, + DBG_SWDIAG_LEINIT_EVT_CANCELED_MASK = 0x08, + + DBG_SWDIAG_LEINIT_FRM_CBK_OFFSET = 4, + DBG_SWDIAG_LEINIT_FRM_CBK_MASK = 0x10, + + DBG_SWDIAG_LEINIT_FRM_EOF_ISR_OFFSET = 5, + DBG_SWDIAG_LEINIT_FRM_EOF_ISR_MASK = 0x20, + + DBG_SWDIAG_LEINIT_SCHED_OFFSET = 6, + DBG_SWDIAG_LEINIT_SCHED_MASK = 0x40, + + DBG_SWDIAG_LEINIT_PKT_RX_OFFSET = 7, + DBG_SWDIAG_LEINIT_PKT_RX_MASK = 0x80, + + /** + ****************************************************************************************** + * @brief BANK 32 : LE ADVERTISING + ****************************************************************************************** + */ + DBG_SWDIAG_LEADV = 32, + + DBG_SWDIAG_LEADV_START_OFFSET = 0, + DBG_SWDIAG_LEADV_START_MASK = 0x01, + + DBG_SWDIAG_LEADV_STOP_OFFSET = 1, + DBG_SWDIAG_LEADV_STOP_MASK = 0x02, + + DBG_SWDIAG_LEADV_EVT_START_OFFSET = 2, + DBG_SWDIAG_LEADV_EVT_START_MASK = 0x04, + + DBG_SWDIAG_LEADV_EVT_CANCELED_OFFSET = 3, + DBG_SWDIAG_LEADV_EVT_CANCELED_MASK = 0x08, + + DBG_SWDIAG_LEADV_RX_ISR_OFFSET = 4, + DBG_SWDIAG_LEADV_RX_ISR_MASK = 0x10, + + DBG_SWDIAG_LEADV_FRM_ISR_OFFSET = 5, + DBG_SWDIAG_LEADV_FRM_ISR_MASK = 0x20, + + DBG_SWDIAG_LEADV_SCHED_OFFSET = 6, + DBG_SWDIAG_LEADV_SCHED_MASK = 0x40, + + DBG_SWDIAG_LEADV_PKT_RX_OFFSET = 7, + DBG_SWDIAG_LEADV_PKT_RX_MASK = 0x80, + + /** + ****************************************************************************************** + * @brief BANK 33 : LE CONNECTION + ****************************************************************************************** + */ + DBG_SWDIAG_LECON = 33, + + DBG_SWDIAG_LECON_START_OFFSET = 0, + DBG_SWDIAG_LECON_START_MASK = 0x01, + + DBG_SWDIAG_LECON_STOP_OFFSET = 1, + DBG_SWDIAG_LECON_STOP_MASK = 0x02, + + DBG_SWDIAG_LECON_EVT_START_OFFSET = 2, + DBG_SWDIAG_LECON_EVT_START_MASK = 0x04, + + DBG_SWDIAG_LECON_EVT_CANCELED_OFFSET = 3, + DBG_SWDIAG_LECON_EVT_CANCELED_MASK = 0x08, + + DBG_SWDIAG_LECON_RX_ISR_OFFSET = 4, + DBG_SWDIAG_LECON_RX_ISR_MASK = 0x10, + + DBG_SWDIAG_LECON_FRM_ISR_OFFSET = 5, + DBG_SWDIAG_LECON_FRM_ISR_MASK = 0x20, + + DBG_SWDIAG_LECON_SCHED_OFFSET = 6, + DBG_SWDIAG_LECON_SCHED_MASK = 0x40, + + DBG_SWDIAG_LECON_TX_ISR_OFFSET = 7, + DBG_SWDIAG_LECON_TX_ISR_MASK = 0x80, + + /** + ****************************************************************************************** + * @brief BANK 34 : LE DATA + ****************************************************************************************** + */ + DBG_SWDIAG_LEDATA = 34, + + DBG_SWDIAG_LEDATA_LLCP_TX_OFFSET = 0, + DBG_SWDIAG_LEDATA_LLCP_TX_MASK = 0x01, + + DBG_SWDIAG_LEDATA_ACL_TX_OFFSET = 1, + DBG_SWDIAG_LEDATA_ACL_TX_MASK = 0x02, + + DBG_SWDIAG_LEDATA_LLCP_RX_OFFSET = 2, + DBG_SWDIAG_LEDATA_LLCP_RX_MASK = 0x04, + + DBG_SWDIAG_LEDATA_ACL_RX_OFFSET = 3, + DBG_SWDIAG_LEDATA_ACL_RX_MASK = 0x08, + + DBG_SWDIAG_LEDATA_LLCP_ACK_OFFSET = 4, + DBG_SWDIAG_LEDATA_LLCP_ACK_MASK = 0x10, + + DBG_SWDIAG_LEDATA_ACL_ACK_OFFSET = 5, + DBG_SWDIAG_LEDATA_ACL_ACK_MASK = 0x20, + + /** + ****************************************************************************************** + * @brief BANK 35 : LETX + ****************************************************************************************** + */ + DBG_SWDIAG_LETX = 35, + + DBG_SWDIAG_LETX_LLCP_TX_OFFSET = 0, + DBG_SWDIAG_LETX_LLCP_TX_MASK = 0x01, + + DBG_SWDIAG_LETX_ACL_TX_OFFSET = 1, + DBG_SWDIAG_LETX_ACL_TX_MASK = 0x02, + + DBG_SWDIAG_LETX_SW_IDX_OFFSET = 2, + DBG_SWDIAG_LETX_SW_IDX_MASK = 0x04, + + DBG_SWDIAG_LETX_HW_IDX_OFFSET = 3, + DBG_SWDIAG_LETX_HW_IDX_MASK = 0x08, + + DBG_SWDIAG_LETX_TX_CNT_OFFSET = 4, + DBG_SWDIAG_LETX_TX_CNT_MASK = 0x30, + + /** + ****************************************************************************************** + * @brief BANK 36 : LE PERIODIC ADVERTISING + ****************************************************************************************** + */ + DBG_SWDIAG_LEPERADV = 36, + + DBG_SWDIAG_LEPERADV_START_OFFSET = 0, + DBG_SWDIAG_LEPERADV_START_MASK = 0x01, + + DBG_SWDIAG_LEPERADV_STOP_OFFSET = 1, + DBG_SWDIAG_LEPERADV_STOP_MASK = 0x02, + + DBG_SWDIAG_LEPERADV_EVT_START_OFFSET = 2, + DBG_SWDIAG_LEPERADV_EVT_START_MASK = 0x04, + + DBG_SWDIAG_LEPERADV_EVT_CANCELED_OFFSET = 3, + DBG_SWDIAG_LEPERADV_EVT_CANCELED_MASK = 0x08, + + DBG_SWDIAG_LEPERADV_RX_ISR_OFFSET = 4, + DBG_SWDIAG_LEPERADV_RX_ISR_MASK = 0x10, + + DBG_SWDIAG_LEPERADV_FRM_ISR_OFFSET = 5, + DBG_SWDIAG_LEPERADV_FRM_ISR_MASK = 0x20, + + DBG_SWDIAG_LEPERADV_SCHED_OFFSET = 6, + DBG_SWDIAG_LEPERADV_SCHED_MASK = 0x40, + + /** + ****************************************************************************************** + * @brief BANK 37 : LE SYNC + ****************************************************************************************** + */ + DBG_SWDIAG_LESYNC = 37, + + DBG_SWDIAG_LESYNC_START_OFFSET = 0, + DBG_SWDIAG_LESYNC_START_MASK = 0x01, + + DBG_SWDIAG_LESYNC_STOP_OFFSET = 1, + DBG_SWDIAG_LESYNC_STOP_MASK = 0x02, + + DBG_SWDIAG_LESYNC_EVT_START_OFFSET = 2, + DBG_SWDIAG_LESYNC_EVT_START_MASK = 0x04, + + DBG_SWDIAG_LESYNC_EVT_CANCELED_OFFSET = 3, + DBG_SWDIAG_LESYNC_EVT_CANCELED_MASK = 0x08, + + DBG_SWDIAG_LESYNC_FRM_RX_ISR_OFFSET = 4, + DBG_SWDIAG_LESYNC_FRM_RX_ISR_MASK = 0x10, + + DBG_SWDIAG_LESYNC_FRM_EOF_ISR_OFFSET = 5, + DBG_SWDIAG_LESYNC_FRM_EOF_ISR_MASK = 0x20, + + DBG_SWDIAG_LESYNC_SCHED_OFFSET = 6, + DBG_SWDIAG_LESYNC_SCHED_MASK = 0x40, + + DBG_SWDIAG_LESYNC_PKT_RX_OFFSET = 7, + DBG_SWDIAG_LESYNC_PKT_RX_MASK = 0x80, + + /** + ****************************************************************************************** + * @brief BANK 38 : ADV REPORT FILTER + ****************************************************************************************** + */ + DBG_SWDIAG_LEADVFILT = 38, + + DBG_SWDIAG_LEADVFILT_OK_OFFSET = 0, + DBG_SWDIAG_LEADVFILT_OK_MASK = 0x01, + + DBG_SWDIAG_LEADVFILT_KO_OFFSET = 1, + DBG_SWDIAG_LEADVFILT_KO_MASK = 0x02, + + DBG_SWDIAG_LEADVFILT_CHAIN_STAT_1M_OFFSET = 2, + DBG_SWDIAG_LEADVFILT_CHAIN_STAT_1M_MASK = 0x0C, + + DBG_SWDIAG_LEADVFILT_CNT_OFFSET = 4, + DBG_SWDIAG_LEADVFILT_CNT_MASK = 0xF0, + + /** + ****************************************************************************************** + * @brief BANK 39 : ACL_TX + ****************************************************************************************** + */ + DBG_SWDIAG_ACL_TX = 39, + + DBG_SWDIAG_ACL_TX_TRAFFIC_OFFSET = 0, + DBG_SWDIAG_ACL_TX_TRAFFIC_MASK = 0xFF, + + /** + ****************************************************************************************** + * @brief BANK 40 : ACL_RX + ****************************************************************************************** + */ + DBG_SWDIAG_ACL_RX = 40, + + DBG_SWDIAG_ACL_RX_TRAFFIC_OFFSET = 0, + DBG_SWDIAG_ACL_RX_TRAFFIC_MASK = 0xFF, + + /** + ****************************************************************************************** + * @brief BANK 41 : ISOOHCI (Audio over Application-Host-interface) + ****************************************************************************************** + */ + DBG_SWDIAG_ISOOHCI = 41, + + DBG_SWDIAG_ISOOHCI_RX_ISO_OFFSET = 0, + DBG_SWDIAG_ISOOHCI_RX_ISO_MASK = 0x01, + + DBG_SWDIAG_ISOOHCI_TX_ISO_OFFSET = 1, + DBG_SWDIAG_ISOOHCI_TX_ISO_MASK = 0x02, + + DBG_SWDIAG_ISOOHCI_RX_TOG_OFFSET = 2, + DBG_SWDIAG_ISOOHCI_RX_TOG_MASK = 0x04, + + DBG_SWDIAG_ISOOHCI_TX_TOG_OFFSET = 3, + DBG_SWDIAG_ISOOHCI_TX_TOG_MASK = 0x08, + + /** + ****************************************************************************************** + * @brief BANK 44 : ISO Generator Data Path + ****************************************************************************************** + */ + DBG_SWDIAG_ISOGEN = 44, + + DBG_SWDIAG_ISOGEN_RX_OK_OFFSET = 0, + DBG_SWDIAG_ISOGEN_RX_OK_MASK = 0x01, + + DBG_SWDIAG_ISOGEN_RX_NOT_GRANT_OFFSET = 1, + DBG_SWDIAG_ISOGEN_RX_NOT_GRANT_MASK = 0x02, + + DBG_SWDIAG_ISOGEN_RX_CRC_ERR_OFFSET = 2, + DBG_SWDIAG_ISOGEN_RX_CRC_ERR_MASK = 0x04, + + DBG_SWDIAG_ISOGEN_RX_SYNC_ERR_OFFSET = 3, + DBG_SWDIAG_ISOGEN_RX_SYNC_ERR_MASK = 0x08, + + DBG_SWDIAG_ISOGEN_RX_DATA_ERR_OFFSET = 4, + DBG_SWDIAG_ISOGEN_RX_DATA_ERR_MASK = 0x10, + + DBG_SWDIAG_ISOGEN_RX_EMPTY_OFFSET = 5, + DBG_SWDIAG_ISOGEN_RX_EMPTY_MASK = 0x20, + + DBG_SWDIAG_ISOGEN_TX_OK_OFFSET = 6, + DBG_SWDIAG_ISOGEN_TX_OK_MASK = 0x40, + + DBG_SWDIAG_ISOGEN_TX_NOT_GRANT_OFFSET = 7, + DBG_SWDIAG_ISOGEN_TX_NOT_GRANT_MASK = 0x80, + + /** + ****************************************************************************************** + * @brief BANK 46 : ISOGEN TEST + ****************************************************************************************** + */ + DBG_SWDIAG_TST = 46, + + DBG_SWDIAG_TST_RX_GET_OFFSET = 0, + DBG_SWDIAG_TST_RX_GET_MASK = 0x01, + + DBG_SWDIAG_TST_RX_ISR_OFFSET = 1, + DBG_SWDIAG_TST_RX_ISR_MASK = 0x02, + + /** + ****************************************************************************************** + * @brief BANK 47 : SCH ARB + ****************************************************************************************** + */ + DBG_SWDIAG_SCH_ARB = 47, + + DBG_SWDIAG_SCH_ARB_INSERT_OFFSET = 0, + DBG_SWDIAG_SCH_ARB_INSERT_MASK = 0x01, + + DBG_SWDIAG_SCH_ARB_INSERT_ERR_OFFSET = 1, + DBG_SWDIAG_SCH_ARB_INSERT_ERR_MASK = 0x02, + + DBG_SWDIAG_SCH_ARB_REMOVE_OFFSET = 2, + DBG_SWDIAG_SCH_ARB_REMOVE_MASK = 0x04, + + DBG_SWDIAG_SCH_ARB_EVT_START_OFFSET = 3, + DBG_SWDIAG_SCH_ARB_EVT_START_MASK = 0x08, + + DBG_SWDIAG_SCH_ARB_SW_ISR_OFFSET = 4, + DBG_SWDIAG_SCH_ARB_SW_ISR_MASK = 0x10, + + DBG_SWDIAG_SCH_ARB_PROG_TIMER_OFFSET = 5, + DBG_SWDIAG_SCH_ARB_PROG_TIMER_MASK = 0x20, + + DBG_SWDIAG_SCH_ARB_ELT_CANCEL_OFFSET = 6, + DBG_SWDIAG_SCH_ARB_ELT_CANCEL_MASK = 0x40, + + DBG_SWDIAG_SCH_ARB_CONFLICT_OFFSET = 7, + DBG_SWDIAG_SCH_ARB_CONFLICT_MASK = 0x80, + + /** + ****************************************************************************************** + * @brief BANK 48 : SAM + ****************************************************************************************** + */ + DBG_SWDIAG_SAM = 48, + + DBG_SWDIAG_SAM_RMAP_OFFSET_CFG_OFFSET = 0, + DBG_SWDIAG_SAM_RMAP_OFFSET_CFG_MASK = 0x01, + + DBG_SWDIAG_SAM_CFG_OFFSET = 1, + DBG_SWDIAG_SAM_CFG_MASK = 0x02, + + DBG_SWDIAG_SAM_LMAP_SET_OFFSET = 2, + DBG_SWDIAG_SAM_LMAP_SET_MASK = 0x04, + + DBG_SWDIAG_SAM_RMAP_SET_OFFSET = 3, + DBG_SWDIAG_SAM_RMAP_SET_MASK = 0x08, + + DBG_SWDIAG_SAM_RMAP_REFRESH_OFFSET = 4, + DBG_SWDIAG_SAM_RMAP_REFRESH_MASK = 0x10, + + DBG_SWDIAG_SAM_LMAP_EN_OFFSET = 5, + DBG_SWDIAG_SAM_LMAP_EN_MASK = 0x20, + + DBG_SWDIAG_SAM_RMAP_EN_OFFSET = 6, + DBG_SWDIAG_SAM_RMAP_EN_MASK = 0x40, + + DBG_SWDIAG_SAM_LSUBMAP_CFG_OFFSET = 7, + DBG_SWDIAG_SAM_LSUBMAP_CFG_MASK = 0x80, + + /** + ****************************************************************************************** + * @brief BANK 49 : MESH_DEMO_DISPLAY_LIGHT + ****************************************************************************************** + */ + DBG_SWDIAG_LIGHT = 49, + + DBG_SWDIAG_LIGHT_LIGHTNESS0_OFFSET = 0, + DBG_SWDIAG_LIGHT_LIGHTNESS0_MASK = 0x01, + + DBG_SWDIAG_LIGHT_LIGHTNESS1_OFFSET = 1, + DBG_SWDIAG_LIGHT_LIGHTNESS1_MASK = 0x02, + + DBG_SWDIAG_LIGHT_LIGHTNESS2_OFFSET = 2, + DBG_SWDIAG_LIGHT_LIGHTNESS2_MASK = 0x04, + + DBG_SWDIAG_LIGHT_LIGHTNESS3_OFFSET = 3, + DBG_SWDIAG_LIGHT_LIGHTNESS3_MASK = 0x08, + + DBG_SWDIAG_LIGHT_LIGHTNESS4_OFFSET = 4, + DBG_SWDIAG_LIGHT_LIGHTNESS4_MASK = 0x10, + + DBG_SWDIAG_LIGHT_LIGHTNESS5_OFFSET = 5, + DBG_SWDIAG_LIGHT_LIGHTNESS5_MASK = 0x20, + + DBG_SWDIAG_LIGHT_LIGHTNESS6_OFFSET = 6, + DBG_SWDIAG_LIGHT_LIGHTNESS6_MASK = 0x40, + + DBG_SWDIAG_LIGHT_LIGHTNESS7_OFFSET = 7, + DBG_SWDIAG_LIGHT_LIGHTNESS7_MASK = 0x80, + + /// Number of SW profiles - to increase when new bank are added + DBG_SWDIAG_NB_PROFILES = 50, +}; + + +/* + * GLOBAL VARIABLE DECLARATION + **************************************************************************************** + */ + +/// Allocate HW banks to SW profiles +extern uint8_t sw_to_hw[DBG_SWDIAG_NB_PROFILES]; + + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** +****************************************************************************************** +* @brief Initialize SW profiling module +****************************************************************************************** +*/ +void dbg_swdiag_init(void); + +/** +****************************************************************************************** +* @brief Read the SW profiling configuration. +* +* @return SW profile configuration +****************************************************************************************** +*/ +uint32_t dbg_swdiag_read(void); + +/** +****************************************************************************************** +* @brief Write the SW profiling configuration. +* +* @param[in] profile SW profiling configuration to apply +****************************************************************************************** +*/ +void dbg_swdiag_write(uint32_t profile); + +#endif //RW_SWDIAG + +/// @} DBGSWDIAG + +#endif // DBG_SWDIAG_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/dbg/api/dbg_trc.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/dbg/api/dbg_trc.h new file mode 100755 index 0000000..5a8209b --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/dbg/api/dbg_trc.h @@ -0,0 +1,1609 @@ +/** + **************************************************************************************** + * + * @file dbg_trc.h + * + * @brief This file contains definitions related to the Tracer module. + * + * Copyright (C) RivieraWaves 2009-2015 + * + **************************************************************************************** + */ + +#ifndef DBG_TRC_H_ +#define DBG_TRC_H_ + +/** +**************************************************************************************** +* @addtogroup TRACER +* @ingroup TRACER +* @brief Tracer module sends traces through UART +* @{ +**************************************************************************************** +*/ + +#include "rwip_config.h" +#if (TRACER_PRESENT) + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include + +#if (TRC_KERNEL_MSG || TRC_KERNEL_TMR) +#include "kernel_msg.h" +#endif /*(TRC_KERNEL_MSG || TRC_KERNEL_TMR)*/ + +#if (TRC_ARB) +#include "sch_arb.h" +#endif /*(TRC_ARB) */ + +#if (TRC_ADV) +#include "lld.h" +#endif /*(TRC_ADV)*/ + +/* + * DEFINES + **************************************************************************************** + */ +#define TRC_GRP_B(__t) (__t##_BIT) +#define TRC_GRP_P(__t) (__t##_POS) + +#define TRC_MSG_TYPE 0x06 + +#define TRC_OPCODE_LEN (1) +#define TRC_PDULEN_LEN (2) +#define TRC_MSG_HDR_LEN (TRC_OPCODE_LEN + TRC_PDULEN_LEN) + +#define TRC_CFG_WORD_LEN (4) + +/* + * ENUMERATION DEFINITION + **************************************************************************************** + */ +/// Possible types of trace (parameter, size, conversion_to_string) +/*@TRACE*/ +enum trace_types +{ + #if TRC_KERNEL_MSG + /* @TRACE_DEF + * TRC_NAME: trc_kernel_msg_send + * TRC_VARS: msg_id_names = get_elements(TASK_BLE_API_ID, "'@%s_msg_id'%(#.lower().rsplit('_', 1)[1])") + * TRC_UNION: ("Parameters", "$Message_id", msg_id_names, "#.lower()") + * @NO_PAD + * + * ('Message_id' , uint16_t, "@['%s_msg_id'%(@TASK_BLE_API_ID.name(int($Message_id >> 8)).rsplit('_',1)[1].lower())].name(int($Message_id))", msg_id_names), + * ('Destination_task_id', uint16_t, "@KERNEL_TASK_TYPE.name(int($Destination_task_id & 0x00FF))", '@KERNEL_TASK_TYPE'), + * ('Source_task_id', uint16_t, "@KERNEL_TASK_TYPE.name(int($Source_task_id & 0x00FF))", '@KERNEL_TASK_TYPE'), + * ('Parameter_length', uint16_t), + * ('Parameters', "union", CArray(uint8_t, '$Parameter_length')) + */ + KERNEL_MSG_SEND = 0x00, + + /* @TRACE_DEF + * TRC_NAME: trc_kernel_msg_handled + * TRC_VARS: msg_id_names = get_elements(TASK_BLE_API_ID, "'@%s_msg_id'%(#.lower().rsplit('_', 1)[1])") + * @NO_PAD + * + * ('Message_id' , uint16_t, "@['%s_msg_id'%(@TASK_BLE_API_ID.name(int($Message_id >> 8)).rsplit('_',1)[1].lower())].name(int($Message_id))", msg_id_names), + * ('Destination_task_id', uint16_t, "@KERNEL_TASK_TYPE.name(int($Destination_task_id & 0x00FF))", '@KERNEL_TASK_TYPE'), + * ('Source_task_id', uint16_t, "@KERNEL_TASK_TYPE.name(int($Source_task_id & 0x00FF))", '@KERNEL_TASK_TYPE'), + * ('Message_status', uint8_t, "@kernel_msg_status_tag.name(int($Message_status))", '@kernel_msg_status_tag') + */ + KERNEL_MSG_HANDLED = 0x01, + #endif /*TRC_KERNEL_MSG*/ + + #if TRC_KERNEL_TMR + /* @TRACE_DEF + * TRC_NAME: trc_kernel_tmr_set + * TRC_VARS: msg_id_names = get_elements(TASK_BLE_API_ID, "'@%s_msg_id'%(#.lower().rsplit('_', 1)[1])") + * @NO_PAD + * + * ('Target_time' , uint32_t), + * ('Task_ID', uint16_t, "@KERNEL_TASK_TYPE.name(int($Task_ID & 0x00FF))", '@KERNEL_TASK_TYPE'), + * ('Message_id', uint16_t, "@['%s_msg_id'%(@TASK_BLE_API_ID.name(int($Message_id >> 8)).rsplit('_',1)[1].lower())].name(int($Message_id))", msg_id_names) + */ + KERNEL_TMR_SET = 0x02, + + /* @TRACE_DEF + * TRC_NAME: trc_kernel_tmr_clr + * TRC_VARS: msg_id_names = get_elements(TASK_BLE_API_ID, "'@%s_msg_id'%(#.lower().rsplit('_', 1)[1])") + * @NO_PAD + * + * + * ('Target_time' , uint32_t), + * ('Task_ID', uint16_t, "@KERNEL_TASK_TYPE.name(int($Task_ID & 0x00FF))", '@KERNEL_TASK_TYPE'), + * ('Message_id', uint16_t, "@['%s_msg_id'%(@TASK_BLE_API_ID.name(int($Message_id >> 8)).rsplit('_',1)[1].lower())].name(int($Message_id))", msg_id_names) + */ + KERNEL_TMR_CLR = 0x03, + + /* @TRACE_DEF + * TRC_NAME: trc_kernel_tmr_exp + * TRC_VARS: msg_id_names = get_elements(TASK_BLE_API_ID, "'@%s_msg_id'%(#.lower().rsplit('_', 1)[1])") + * @NO_PAD + * + * ('Target_time' , uint32_t), + * ('Task_ID', uint16_t, "@KERNEL_TASK_TYPE.name(int($Task_ID & 0x00FF))", '@KERNEL_TASK_TYPE'), + * ('Message_id', uint16_t, "@['%s_msg_id'%(@TASK_BLE_API_ID.name(int($Message_id >> 8)).rsplit('_',1)[1].lower())].name(int($Message_id))", msg_id_names) + */ + KERNEL_TMR_EXP = 0x04, + #endif /*TRC_KERNEL_TMR*/ + + #if TRC_KERNEL_EVT + /* @TRACE_DEF + * TRC_NAME: trc_kernel_evt_set + * @NO_PAD + * + * ('Event_type', uint8_t, "@KERNEL_EVENT_TYPE.name(int($Event_type))", '@KERNEL_EVENT_TYPE'), + */ + KERNEL_EVT_SET = 0x05, + + /* @TRACE_DEF + * TRC_NAME: trc_kernel_evt_handled + * @NO_PAD + * + * ('Event_type', uint8_t, "@KERNEL_EVENT_TYPE.name(int($Event_type))", '@KERNEL_EVENT_TYPE') + */ + KERNEL_EVT_HANDLED = 0x06, + + #endif /* TRC_KERNEL_EVT */ + + #if TRC_MEM + /* @TRACE_DEF + * TRC_NAME: trc_mem_alloc + * @NO_PAD + * + * ('Heap_ID', uint8_t, "@KERNEL_MEM_HEAP.name(int($Heap_ID))", '@KERNEL_MEM_HEAP'), + * ('Block_address', uint32_t), + * ('Size', uint32_t), + */ + MEM_ALLOC = 0x07, + + /* @TRACE_DEF + * TRC_NAME: trc_mem_free + * @NO_PAD + * + * ('Heap_ID', uint8_t, "@KERNEL_MEM_HEAP.name(int($Heap_ID))", '@KERNEL_MEM_HEAP'), + * ('Block_address', uint32_t), + * ('Size', uint32_t), + */ + MEM_FREE = 0x08, + + #endif /*TRC_MEM*/ + + #if TRC_SLEEP + /* @TRACE_DEF + * TRC_NAME: trc_sleep_enter + */ + SLEEP_ENTER = 0x09, + + /* @TRACE_DEF + * TRC_NAME: trc_sleep_wakeup + */ + SLEEP_WAKEUP = 0x0A, + #endif /*TRC_SLEEP*/ + + #if TRC_SW_ASS + //TODO[AAL] add support for strings in rwdt_types + BLE_ASSERT_WARNING = 0x0B, + BLE_ASSERT_ERROR = 0x0C, + #endif /*TRC_SW_ASS*/ + + #if TRC_PROG + /* @TRACE_DEF + * TRC_NAME: trc_et_prog + * @NO_PAD + * + * ('Entry_index', uint8_t), + * ('Entry_value', ET), + */ + ET_PROG = 0x0D, + + /* @TRACE_DEF + * TRC_NAME: trc_conn_evt_cnt + * @NO_PAD + * + * ('Connection_handle', uint16_t), + * ('Event_counter', uint16_t), + */ + CONN_EVT_CNT = 0x0E, + + /* @TRACE_DEF + * TRC_NAME: trc_frm_cmp_bt + * @NO_PAD + * + * ('Timestamp_programmed_frame', uint32_t), + * ('Frame_identifier', uint8_t), + * ('Callback_for_interrupt_handling', uint32_t) + */ + FRM_CMP_BT = 0x0F, + /* @TRACE_DEF + * TRC_NAME: trc_frm_cmp_ble + * @NO_PAD + * + * ('Timestamp_programmed_frame', uint32_t), + * ('Frame_identifier', uint8_t), + * ('Callback_for_interrupt_handling', uint32_t) + */ + FRM_CMP_BLE = 0x10, + #endif /*TRC_PROG*/ + + #if TRC_CS_BLE + /* @TRACE_DEF + * TRC_NAME: trc_cs_ble + * @NO_PAD + * + * ('Control_structure', CS), + */ + CS_BLE = 0x11, + #endif /*TRC_CS_BLE*/ + + #if TRC_CS_BT + CS_BT = 0x12, + #endif /*TRC_CS_BT*/ + + #if TRC_RX_DESC + /* @TRACE_DEF + * TRC_NAME: trc_rx_desc + * @NO_PAD + * + * ('Driver_type', uint8_t, "@lld_driver_types.name(int($Driver_type))", '@lld_driver_types'), + * ('Connection_index', uint8_t), + * ('Rx_descriptor', RX_DESC) + */ + RX_DESC = 0x13, + #endif /*TRC_RX_DESC*/ + + #if TRC_LLCP + /* @TRACE_DEF + * TRC_NAME: trc_llcp_tx + * @NO_PAD + * + * ('Connection_handle', uint16_t), + * ('Data_Length', uint8_t), + * ('LLCP_pdu', llcp_pdu) + */ + LLCP_TX = 0x14, + + /* @TRACE_DEF + * TRC_NAME: trc_llcp_rx + * @NO_PAD + * + * ('Connection_handle', uint16_t), + * ('Data_Length', uint8_t), + * ('LLCP_pdu', llcp_pdu) + */ + LLCP_RX = 0x15, + + /* @TRACE_DEF + * TRC_NAME: trc_llcp_ack + * @NO_PAD + * + * ('Connection_handle', uint16_t), + * ('Data_Length', uint8_t), + * ('LLCP_pdu', llcp_pdu) + */ + LLCP_ACK = 0x16, + #endif /*TRC_LLCP*/ + + #if TRC_LMP + /* @TRACE_DEF + * TRC_NAME: trc_lmp_tx + * @NO_PAD + * + * ('Connection_handle', uint16_t), + * ('Data_Length', uint8_t), + * ('TrID', uint8_t), + * ('Opcode', uint8_t), + * ('Data', CArray(uint8_t, '$Data_Length')), + */ + LMP_TX = 0x17, + + /* @TRACE_DEF + * TRC_NAME: trc_lmp_rx + * @NO_PAD + * + * ('Connection_handle', uint16_t), + * ('Data_Length', uint8_t), + * ('TrID', uint8_t), + * ('Opcode', uint8_t), + * ('Data', CArray(uint8_t, '$Data_Length')), + */ + LMP_RX = 0x18, + + /* @TRACE_DEF + * TRC_NAME: trc_lmp_ack + * @NO_PAD + * + * ('Connection_handle', uint16_t), + * ('Data_Length', uint8_t), + * ('TrID', uint8_t), + * ('Opcode', uint8_t), + * ('Data', CArray(uint8_t, '$Data_Length')), + */ + LMP_ACK = 0x19, + #endif /*TRC_LMP*/ + + #if TRC_L2CAP + /* @TRACE_DEF + * TRC_NAME: trc_l2cap_tx + * @NO_PAD + * + * ('Connection_handle', uint16_t), + * ('Data_Length', uint16_t), + * ('l2cc_pdu', l2cc_pdu) + */ + L2CAP_TX = 0x1A, + + /* @TRACE_DEF + * TRC_NAME: trc_l2cap_rx + * @NO_PAD + * + * ('Connection_handle', uint16_t), + * ('Data_Length', uint16_t), + * ('l2cc_pdu', l2cc_pdu), + */ + L2CAP_RX = 0x1B, + + /* @TRACE_DEF + * TRC_NAME: trc_l2cap_ack + * @NO_PAD + * + * ('Connection_handle', uint16_t), + * ('Number_acknowledged_packets', uint16_t), + */ + L2CAP_ACK = 0x1C, + #endif /*TRC_L2CAP*/ + + #if TRC_ARB + /* @TRACE_DEF + * TRC_NAME: trc_sch_arb_req + * @NO_PAD + * + * ('Target_time', uint32_t), + * ('elt_address', uint32_t), + * ('Status', uint8_t), + * ('sch_arb_elt', sch_arb_elt_tag) + */ + SCH_ARB_REQ = 0x1D, + + /* @TRACE_DEF + * TRC_NAME: trc_sch_arb_canc + * @NO_PAD + * + * ('elt_address', uint32_t), + */ + SCH_ARB_CANC = 0x1E, + + /* @TRACE_DEF + * TRC_NAME: trc_sch_arb_rem + * @NO_PAD + * + * ('elt_address', uint32_t), + */ + SCH_ARB_REM = 0x1F, + + /* @TRACE_DEF + * TRC_NAME: trc_sch_arb_start + * @NO_PAD + * + * ('elt_address', uint32_t), + */ + SCH_ARB_START = 0x20, + + /* @TRACE_DEF + * TRC_NAME: trc_sch_arb_shift + * @NO_PAD + * + * ('elt_address', uint32_t), + * ('Current_prio', uint8_t), + * ('Duration_min', uint32_t), + * ('Timestamp', uint32_t), + */ + SCH_ARB_SHIFT = 0x21, + #endif /*TRC_ARB*/ + + #if TRC_LC_STATE_TRANS + LC_ST = 0x22, + #endif /*TRC_LC_STATE_TRANS*/ + + #if TRC_LLC_STATE_TRANS + /* @TRACE_DEF + * TRC_NAME: trc_llc_st + * TRC_VARS: llc_proc_states = get_elements(llc_proc_id, "'@llc_%s_state'%(#.split('_', 2)[2].lower())") + * @NO_PAD + * + * ('Connection_handle', uint16_t), + * ('Procedure_ID', uint8_t, '@llc_proc_id.name(int($Procedure_ID))', '@llc_proc_id'), + * ('Previous_state', uint8_t, "@['_llc_%s_state'%(@llc_proc_id.name(int($Procedure_ID)).split('_', 2)[2].lower())].name(int($Previous_state))", llc_proc_states), + * ('Current_state', uint8_t, "@['llc_%s_state'%(@llc_proc_id.name(int($Procedure_ID)).split('_', 2)[2].lower())].name(int($Current_state))", llc_proc_states), + */ + LLC_ST = 0x23, + #endif /*TRC_LLC_STATE_TRANS*/ + + #if TRC_HCI + /* @TRACE_DEF + * TRC_NAME: trc_hci_cmd + * TRC_UNION: ("Parameters", "$Hci_opcode", hci_opcode, "#.rsplit('_OPCODE', 1)[0].lower()") + * @NO_PAD + * + * ('Hci_opcode', uint16_t, '@hci_opcode.name(int($Hci_opcode))', '@hci_opcode'), + * ('Param_length', uint16_t), + * ('Parameters', "union", CArray(uint8_t, '$Param_length')) + */ + HCI_CMD = 0x24, + + + /* @TRACE_DEF + * TRC_NAME: trc_hci_cmd_stat_evt + * TRC_UNION: ("Parameters", "$Hci_opcode", hci_opcode, "'%s_cmp_evt'%(#.rsplit('_OPCODE', 1)[0].lower())") + * @NO_PAD + * + * ('Hci_opcode', uint16_t, '@hci_opcode.name(int($Hci_opcode))', '@hci_opcode'), + * ('Param_length', uint16_t), + * ('Parameters', "union", CArray(uint8_t, '$Param_length')) + */ + HCI_CMD_STAT_EVT = 0x25, + + + /* @TRACE_DEF + * TRC_NAME: trc_hci_cmd_cmp_evt + * TRC_UNION: ("Parameters", "$Hci_opcode", hci_opcode, "'%s_cmp_evt'%(#.rsplit('_OPCODE', 1)[0].lower())") + * @NO_PAD + * + * ('Hci_opcode', uint16_t, '@hci_opcode.name(int($Hci_opcode))', '@hci_opcode'), + * ('Param_length', uint16_t), + * ('Parameters', "union", CArray(uint8_t, '$Param_length')) + */ + HCI_CMD_CMP_EVT = 0x26, + + /* @TRACE_DEF + * TRC_NAME: trc_hci_evt + * TRC_UNION: ("Parameters", "$Hci_evt_code", hci_evt_code, "#.rsplit('_CODE', 1)[0].lower()") + * @NO_PAD + * + * ('Hci_evt_code', uint16_t, '@hci_evt_code.name(int($Hci_evt_code))', '@hci_evt_code'), + * ('Param_length', uint16_t), + * ('Parameters', "union", CArray(uint8_t, '$Param_length')) + */ + HCI_EVT = 0x27, + + /* @TRACE_DEF + * TRC_NAME: trc_hci_le_evt + * TRC_UNION: ("Parameters", "$Hci_le_subcode", hci_le_evt_subcode, "#.rsplit('_SUBCODE', 1)[0].lower()") + * @NO_PAD + * + * ('Hci_le_subcode', uint16_t, '@hci_le_evt_subcode.name(int($Hci_le_subcode))', '@hci_le_evt_subcode'), + * ('Param_length', uint16_t), + * ('Parameters', "union", CArray(uint8_t, '$Param_length')) + */ + HCI_LE_EVT = 0x28, + #endif /*TRC_HCI*/ + + #if TRC_ADV + /* @TRACE_DEF + * TRC_NAME: trc_adv_init_rx + * + * ('adv_pdu', trc_init_rx_pdu) + */ + ADV_INIT_RX = 0x29, + + /* @TRACE_DEF + * TRC_NAME: trc_adv_init_tx + * + * ('adv_pdu', trc_adv_tx_pdu) + */ + ADV_INIT_TX = 0x30, + + /* @TRACE_DEF + * TRC_NAME: trc_adv_scan_rx + * + * ('adv_pdu', trc_scan_rx_pdu) + */ + ADV_SCAN_RX = 0x31, + + /* @TRACE_DEF + * TRC_NAME: trc_adv_scan_tx + * + * ('adv_pdu', trc_adv_tx_pdu) + */ + ADV_SCAN_TX = 0x32, + + /* @TRACE_DEF + * TRC_NAME: trc_adv_adv_rx + * TRC_UNION: ("payload", "$packet_type", ble_adv_type, [ + * ('BLE_CONNECT_IND', 'connect_req'), + * ('BLE_SCAN_REQ', 'scan_req'), + * ]) + * @NO_PAD + * + * ('packet_type', uint8_t, '@ble_adv_type.name(int($packet_type))', '@ble_adv_type'), + * ('used_channel', uint8_t), + * ('payload_length', uint8_t), + * ('payload', "union", CArray(uint8_t, '$payload_length')) + */ + ADV_ADV_RX = 0x33, + + /* @TRACE_DEF + * TRC_NAME: trc_adv_adv_tx + * + * ('adv_pdu', trc_adv_tx_pdu) + */ + ADV_ADV_TX = 0x34, + #endif /*TRC_ADV*/ + + #if TRC_ACL + /* @TRACE_DEF + * TRC_NAME: trc_acl_rx + * + * ('adv_pdu', trc_acl_rx_pdu) + */ + ACL_RX = 0x35, + + /* @TRACE_DEF + * TRC_NAME: trc_acl_prog_tx + * + * ('adv_pdu', trc_acl_tx_pdu) + */ + ACL_PROG_TX = 0x36, + + /* @TRACE_DEF + * TRC_NAME: trc_acl_ack_tx + * + * ('adv_pdu', trc_acl_tx_pdu) + */ + ACL_ACK_TX = 0x37, + #endif /*TRC_ACL*/ + + #if TRC_CUSTOM + /* @TRACE_DEF + * TRC_NAME: trc_custom + * TRC_UNION: ("Data", "$Trace_type", custom_trace_types, "#.lower()") + * + * ('Custom_trace_ID', uint8_t), + * ('Trace_type', uint8_t, "@custom_trace_types.name(int($Trace_type))", '@custom_trace_types'), + * ('Data', "union"), + */ + CUSTOM = 0x38, + #endif /*TRC_CUSTOM*/ +}; + +/// Configuration word bit field +/// +/// 7 6 5 4 3 2 1 0 +/// +-------+-------+-------+-------+-------+-------+-------+-------+ +/// |CS_BLE | PROG |SW_ASS | SLEEP | MEM |KERNEL_EVT |KERNEL_TMR |KERNEL_MSG | +/// +-------+-------+-------+-------+-------+-------+-------+-------+ +/// +/// 15 14 13 12 11 10 9 8 +/// +-------+-------+-------+-------+-------+-------+-------+-------+ +/// | LC_ST |LLC_ST | ARB | L2CAP | LMP | LLCP |RX_DESC| CS_BT | +/// +-------+-------+-------+-------+-------+-------+-------+-------+ +/// +/// 23 22 21 20 19 18 17 16 +/// +-------+-------+-------+-------+-------+-------+-------+-------+ +/// | | | | |CUSTOM | ACL | ADV | HCI | +/// +-------+-------+-------+-------+-------+-------+-------+-------+ +/// +/// 31 30 29 28 27 26 25 24 +/// +-------+-------+-------+-------+-------+-------+-------+-------+ +/// | | | | | | | | | +/// +-------+-------+-------+-------+-------+-------+-------+-------+ +/// +enum dbg_trc_cfg_fields +{ + /// Kernel message + TRC_KERNEL_MSG_POS = 0, + TRC_KERNEL_MSG_BIT = 0x00000001, + + /// Kernel timer + TRC_KERNEL_TMR_POS = 1, + TRC_KERNEL_TMR_BIT = 0x00000002, + + /// Kernel event + TRC_KERNEL_EVT_POS = 2, + TRC_KERNEL_EVT_BIT = 0x00000004, + + /// Memory allocation and deallocation + TRC_MEM_POS = 3, + TRC_MEM_BIT = 0x00000008, + + /// Sleep mode + TRC_SLEEP_POS = 4, + TRC_SLEEP_BIT = 0x00000010, + + /// Software Assert + TRC_SW_ASS_POS = 5, + TRC_SW_ASS_BIT = 0x00000020, + + /// Programming of the exchange table, updating of the event counter and handling of "End of Event" interrupt + TRC_PROG_POS = 6, + TRC_PROG_BIT = 0x00000040, + + /// BLE Control structure + TRC_CS_BLE_POS = 7, + TRC_CS_BLE_BIT = 0x00000080, + + /// BT Control structure + TRC_CS_BT_POS = 8, + TRC_CS_BT_BIT = 0x00000100, + + /// Processing of RX descriptors at each LLD driver + TRC_RX_DESC_POS = 9, + TRC_RX_DESC_BIT = 0x00000200, + + /// LLCP transmission, reception and acknowledgment + TRC_LLCP_POS = 10, + TRC_LLCP_BIT = 0x00000400, + + /// LMP transmission, reception and acknowledgment + TRC_LMP_POS = 11, + TRC_LMP_BIT = 0x00000800, + + /// L2CAP transmission, reception and acknowledgment + TRC_L2CAP_POS = 12, + TRC_L2CAP_BIT = 0x00001000, + + /// Scheduling request, cancellation, shift and remove + TRC_ARB_POS = 13, + TRC_ARB_BIT = 0x00002000, + + /// LLC state transition + TRC_LLC_STATE_TRANS_POS = 14, + TRC_LLC_STATE_TRANS_BIT = 0x00004000, + + /// LC state transition + TRC_LC_STATE_TRANS_POS = 15, + TRC_LC_STATE_TRANS_BIT = 0x00008000, + + /// HCI messages (in Full embedded mode) + TRC_HCI_POS = 16, + TRC_HCI_BIT = 0x00010000, + + /// Advertising pdu + TRC_ADV_POS = 17, + TRC_ADV_BIT = 0x00020000, + + /// ACL pdu + TRC_ACL_POS = 18, + TRC_ACL_BIT = 0x00040000, + + /// Custom trace + TRC_CUSTOM_POS = 19, + TRC_CUSTOM_BIT = 0x00080000, +}; + +/// Tracer packet types +enum dbg_trc_pkt_types +{ + /// Trace message + TRACE = 0x01, + /// Configuration message + TRACER_CFG = 0x02, + /// Acknowledgment message + TRACER_ACK = 0x03 +}; + +#if (TRC_RX_DESC) +/// LLD driver types +/*@TRACE*/ +enum lld_driver_types +{ + LLD_SCAN = 0x01, + LLD_INIT = 0x02, + LLD_ADV = 0x03, + LLD_CON = 0x04, +}; +#endif /*(TRC_RX_DESC)*/ + +#if (TRC_CUSTOM) +/// Custom trace types +/*@TRACE*/ +enum custom_trace_types +{ + UINT8_T = 0x01, + UINT16_T = 0x02, + UINT32_T = 0x03, + VOID = 0x04, +}; +#endif /*(TRC_CUSTOM)*/ +#endif /*(TRACER_PRESENT)*/ + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ + + +/* + * FUNCTION DECLARATION + **************************************************************************************** + */ +/** + **************************************************************************************** + * @brief Request a new trace + * + * This function checks the current configuration of the tracer + * + **************************************************************************************** + */ +#if (TRACER_PRESENT && TRC_KERNEL_MSG) +/** + **************************************************************************************** + * @brief Trace request API for kernel message pushed in the send queue + * + * This function is called when a kernel message is pushed in the send queue. + * + * It checks the current tracer configuration and writes the trace in memory if the trace + * group "kernel message" (@see enum tracer_cfg_fields) is enabled. + * + * @param[in] msg Kernel message + **************************************************************************************** + */ +void dbg_trc_req_kernel_msg_send(struct kernel_msg const *msg); + +/// Macro used to send trace request API for kernel message send +#define TRC_REQ_KERNEL_MSG_SEND(msg) \ + dbg_trc_req_kernel_msg_send(msg); + +/** + **************************************************************************************** + * @brief Trace request API for kernel message handled + * + * This function is called when a task handles a message + * + * It checks the current tracer configuration and writes the trace in memory if the trace + * group "kernel message" (@see enum tracer_cfg_fields) is enabled. + * + * @param[in] id Kernel message id + * @param[in] dest_id Destination kernel identifier + * @param[in] src_id Source kernel identifier + * @param[in] msg_status Status returned by the kernel message handler + **************************************************************************************** + */ +void dbg_trc_req_kernel_msg_handled(kernel_msg_id_t const id, kernel_task_id_t const dest_id, kernel_task_id_t const src_id, uint8_t const msg_status); + +/// Macro used to send trace request API for kernel message handled +#define TRC_REQ_KERNEL_MSG_HANDLED(id, dest_id, src_id, msg_status) \ + dbg_trc_req_kernel_msg_handled(id, dest_id, src_id, msg_status); +#else /*TRACER_PRESENT && TRC_KERNEL_MSG*/ +#define TRC_REQ_KERNEL_MSG_SEND(msg) +#define TRC_REQ_KERNEL_MSG_HANDLED(id, dest_id, src_id, msg_status) +#endif /*TRACER_PRESENT && TRC_KERNEL_MSG*/ + +#if (TRACER_PRESENT && TRC_KERNEL_TMR) +/** + **************************************************************************************** + * @brief Trace request API for kernel timer + * + * This function is called when a kernel timer is set, cleared or expired. + * + * It checks the current tracer configuration and writes the trace in memory if the trace + * group "kernel timer" (@see enum tracer_cfg_fields) is enabled. + * + * @param[in] tmr_trc_type Trace type for kernel timer (timer set, cleared and expired of @see enum trace_types) + * @param[in] target_time Timer time value + * @param[in] task_id Timer task identifier + * @param[in] msg_id Timer message identifier + **************************************************************************************** + */ +void dbg_trc_req_kernel_tmr(uint8_t const tmr_trc_type, uint32_t const target_time, kernel_task_id_t const task_id, kernel_msg_id_t const msg_id); + +/// Macro used to send trace request API for kernel timer set +#define TRC_REQ_KERNEL_TMR_SET(target_time, task_id, msg_id) \ + dbg_trc_req_kernel_tmr(KERNEL_TMR_SET, target_time, task_id, msg_id); + +/// Macro used to send trace request API for kernel timer cleared +#define TRC_REQ_KERNEL_TMR_CLR(target_time, task_id, msg_id) \ + dbg_trc_req_kernel_tmr(KERNEL_TMR_CLR,target_time, task_id, msg_id); + +/// Macro used to send trace request API for kernel timer expired +#define TRC_REQ_KERNEL_TMR_EXP(target_time, task_id, msg_id) \ + dbg_trc_req_kernel_tmr(KERNEL_TMR_EXP,target_time, task_id, msg_id); +#else /*(TRACER_PRESENT && TRC_KERNEL_TMR)*/ +#define TRC_REQ_KERNEL_TMR_SET(target_time, task_id, msg_id) +#define TRC_REQ_KERNEL_TMR_CLR(target_time, task_id, msg_id) +#define TRC_REQ_KERNEL_TMR_EXP(target_time, task_id, msg_id) +#endif /*(TRACER_PRESENT && TRC_KERNEL_TMR)*/ + +#if (TRACER_PRESENT && TRC_KERNEL_EVT) +/** + **************************************************************************************** + * @brief Trace request API for kernel event + * + * This function is called when a kernel event is set or handled. + * + * It checks the current tracer configuration and writes the trace in memory if the trace + * group "kernel event" (@see enum tracer_cfg_fields) is enabled. + * + * @param[in] evt_req_type Trace type for kernel event (event set and handled of @see enum trace_types) + * @param[in] event_type Type of event + **************************************************************************************** + */ +void dbg_trc_req_kernel_evt(uint8_t const evt_trc_type, uint8_t const event_type); + +/// Macro used to send trace request API for kernel event set +#define TRC_REQ_KERNEL_EVT_SET(evt_type) \ + dbg_trc_req_kernel_evt(KERNEL_EVT_SET, evt_type); + +/// Macro used to send trace request API for kernel event handled +#define TRC_REQ_KERNEL_EVT_HANDLED(evt_type) \ + dbg_trc_req_kernel_evt(KERNEL_EVT_HANDLED, evt_type); +#else /*(TRACER_PRESENT && TRC_KERNEL_EVT)*/ +#define TRC_REQ_KERNEL_EVT_SET(evt_type) +#define TRC_REQ_KERNEL_EVT_HANDLED(evt_type) +#endif /*(TRACER_PRESENT && TRC_KERNEL_EVT)*/ + +#if (TRACER_PRESENT && TRC_MEM) +/** + **************************************************************************************** + * @brief Trace request API for memory management + * + * This function is called when the memory is allocated or freed. + * + * It checks the current tracer configuration and writes the trace in memory if the trace + * group "memory" (@see enum tracer_cfg_fields) is enabled. + * + * @param[in] mem_trc_type Trace type for memory management (memory alloc and free of @see enum trace_types) + * @param[in] heap_id Heap identifier + * @param[in] blk_address Address of the used memory block + * @param[in] size Size of the memory area that has been allocated or freed. + **************************************************************************************** + */ +void dbg_trc_req_mem(uint8_t const mem_trc_type, uint8_t const heap_id, void const *blk_address, uint32_t const size); + +/// Macro used to send trace request API for memory allocation +#define TRC_REQ_MEM_ALLOC(heap_id, blk_address, size) \ + dbg_trc_req_mem(MEM_ALLOC, heap_id, blk_address, size); + +/// Macro used to send trace request API for memory deallocation +#define TRC_REQ_MEM_FREE(heap_id, blk_address, size) \ + dbg_trc_req_mem(MEM_FREE, heap_id, blk_address, size); + +#else /*(TRACER_PRESENT && TRC_MEM)*/ +#define TRC_REQ_MEM_ALLOC(heap_id, blk_address, size) +#define TRC_REQ_MEM_FREE(heap_id, blk_address, size) +#endif/*(TRACER_PRESENT && TRC_MEM)*/ + +#if (TRACER_PRESENT && TRC_SLEEP) +/** + **************************************************************************************** + * @brief Trace request API for sleep mode + * + * This function is called when the IP enter in deep sleep and when it wakes up. + * + * It checks the current tracer configuration and writes the trace in memory if the trace + * group "sleep" (@see enum tracer_cfg_fields) is enabled. + * + * @param[in] sleep_trc_type Trace type for sleep mode (sleep enter and wakeup of @see enum trace_types) + **************************************************************************************** + */ +void dbg_trc_req_deep_sleep(uint8_t const sleep_trc_type); + +/// Macro used to send trace request API when the IP enters in deep sleep +#define TRC_REQ_SLEEP() \ + dbg_trc_req_deep_sleep(SLEEP_ENTER); + +/// Macro used to send trace request API when the IP wakes up from deep sleep +#define TRC_REQ_WAKEUP() \ + dbg_trc_req_deep_sleep(SLEEP_WAKEUP); + +#else /*(TRACER_PRESENT && TRC_SLEEP)*/ +#define TRC_REQ_SLEEP() +#define TRC_REQ_WAKEUP() +#endif /*(TRACER_PRESENT && TRC_SLEEP)*/ + +#if (TRACER_PRESENT && TRC_SW_ASS) +/** + **************************************************************************************** + * @brief Trace request API for software asserts + * + * This function is called when an assertion statement is evaluated as true. + * + * It checks the current tracer configuration and writes the trace in memory if the trace + * group "sw assertions" (@see enum tracer_cfg_fields) is enabled. + * + * @param[in] ass_trc_type Trace type for assertions (assert warning and assert error of @see enum trace_types) + * @param[in] filename Name of the file that triggered the assertion + * @param[in] code_line Line of code where the assertion was triggered + * @param[in] param0 Parameter value 0 + * @param[in] param1 Parameter value 1 + **************************************************************************************** + */ +void dbg_trc_req_sw_ass(uint8_t const ass_trc_type, char const *filename, uint16_t const code_line, uint32_t const param0, uint32_t const param1); + +/// Macro used to send trace request API when an assert warning is evaluated as true +#define TRC_REQ_SW_ASS_WARN(filename, code_line, param0, param1) \ + dbg_trc_req_sw_ass(BLE_ASSERT_WARNING, filename, code_line, param0, param1); + +/// Macro used to send trace request API when an assert warning is evaluated as true +#define TRC_REQ_SW_ASS_ERR(filename, code_line, param0, param1) \ + dbg_trc_req_sw_ass(BLE_ASSERT_ERROR, filename, code_line, param0, param1); + +#else /*(TRACER_PRESENT && TRC_SW_ASS)*/ +#define TRC_REQ_SW_ASS_WARN(filename, code_line, param0, param1) +#define TRC_REQ_SW_ASS_ERR(filename, code_line, param0, param1) +#endif /*(TRACER_PRESENT && TRC_SW_ASS)*/ + +#if (TRACER_PRESENT && TRC_PROG) +/** + **************************************************************************************** + * @brief Trace request API for exchange table programming + * + * This function is called when the exchange table is programmed. + * + * It checks the current tracer configuration and writes the trace in memory if the trace + * group "programming" (@see enum tracer_cfg_fields) is enabled. + * + * @param[in] elt_idx Index of the programmed entry in the ET + **************************************************************************************** + */ +void dbg_trc_req_et_prog(uint8_t const elt_idx); + +#define TRC_REQ_ET_PROG(elt_idx) \ + dbg_trc_req_et_prog(elt_idx); + +/** + **************************************************************************************** + * @brief Trace request API for connection event counter programming + * + * This function is called when the connection event counter is set. + * + * It checks the current tracer configuration and writes the trace in memory if the trace + * group "programming" (@see enum tracer_cfg_fields) is enabled. + * + * @param[in] conhdl Connection handle + * @param[in] value Value of connection event counter + **************************************************************************************** + */ +void dbg_trc_req_evt_cnt(uint16_t const conhdl, uint16_t const value); +#define TRC_REQ_EVT_CNT(conhdl, value) \ + dbg_trc_req_evt_cnt(conhdl, value); +/** + **************************************************************************************** + * @brief Trace request API for frame completion + * + * This function is called when a frame is completed. + * + * It checks the current tracer configuration and writes the trace in memory if the trace + * group "programming" (@see enum tracer_cfg_fields) is enabled. + * + * @param[in] timestamp Timestamp of the programmed frame (in BLE slots, based on local clock) + * @param[in] frm_id Frame identifier + * @param[in] frm_cbk Callback for handling interrupts related to the frame + **************************************************************************************** + */ +void dbg_trc_req_frm_cmp(uint32_t const timestamp, uint8_t const frm_id, uint32_t const frm_cbk); + +#define TRC_REQ_FRM_CMP(timestamp, frm_id, frm_cbk) \ + dbg_trc_req_frm_cmp(timestamp, frm_id, frm_cbk); + +#else /*(TRACER_PRESENT && TRC_PROG)*/ +#define TRC_REQ_ET_PROG(elt_idx) +#define TRC_REQ_EVT_CNT(conhdl, value) +#define TRC_REQ_FRM_CMP(timestamp, frm_id, frm_cbk) +#endif /*(TRACER_PRESENT && TRC_PROG)*/ + +#if (TRACER_PRESENT && TRC_CS_BLE) +/** + **************************************************************************************** + * @brief Trace request API for control structure programming in BLE + * + * This function is called when a control structure is modified. + * + * It checks the current tracer configuration and writes the trace in memory if the trace + * group "BLE control structure" (@see enum tracer_cfg_fields) is enabled. + * + * @param[in] cs_addr Address of the control structure in the exchange memory + **************************************************************************************** + */ +void dbg_trc_req_cs_ble(uint16_t const cs_addr); + +#define TRC_REQ_CS_BLE(cs_addr) \ + dbg_trc_req_cs_ble(cs_addr); + +#else /*(TRACER_PRESENT && TRC_CS_BLE)*/ +#define TRC_REQ_CS_BLE(cs_addr) +#endif /*(TRACER_PRESENT && TRC_CS_BLE)*/ + +#if (TRACER_PRESENT && TRC_CS_BT) +/** + **************************************************************************************** + * @brief Trace request API for control structure programming in BT + * + * This function is called when a control structure is modified. + * + * It checks the current tracer configuration and writes the trace in memory if the trace + * group "BT control structure" (@see enum tracer_cfg_fields) is enabled. + * + * @param[in] cs_addr Address of the control structure in the exchange memory + **************************************************************************************** + */ +void dbg_trc_req_cs_bt(uint16_t const cs_addr); + +#define TRC_REQ_CS_BT(cs_addr) \ + dbg_trc_req_cs_bt(cs_addr); +#else /*(TRACER_PRESENT && TRC_CS_BT)*/ +#define TRC_REQ_CS_BT(cs_addr) +#endif /*(TRACER_PRESENT && TRC_CS_BT)*/ + +#if (TRACER_PRESENT && TRC_RX_DESC) +/** + **************************************************************************************** + * @brief Trace request API for processing of rx descriptors + * + * This function is called when a packet is received and a driver processes a rx descriptor. + * + * It checks the current tracer configuration and writes the trace in memory if the trace + * group "Rx descriptor" (@see enum tracer_cfg_fields) is enabled. + * + * @param[in] drv_type LLD driver (@see enum driver_type) + * @param[in] act_id Activity identifier + * @param[in] rx_desc_add Address of the rx descriptor in the exchange memory + **************************************************************************************** + */ +void dbg_trc_req_rx_desc(uint8_t const drv_type, uint8_t const act_id, uint16_t const rx_desc_add); + +#define TRC_REQ_RX_DESC(drv_type, act_id, rx_desc_add) \ + dbg_trc_req_rx_desc(drv_type, act_id, rx_desc_add); + +#else /*(TRACER_PRESENT && TRC_RX_DESC)*/ +#define TRC_REQ_RX_DESC(drv_type, act_id, rx_desc_add) +#endif /*(TRACER_PRESENT && TRC_RX_DESC) */ + +#if (TRACER_PRESENT && TRC_LLCP) +/** + **************************************************************************************** + * @brief Trace request API for llcp packets transmission, reception and acknowledgment + * + * This function is called when a llcp packet is transmitted, received or acknowledged. + * + * It checks the current tracer configuration and writes the trace in memory if the trace + * group "LLCP" (@see enum tracer_cfg_fields) is enabled. + * + * @param[in] llcp_trc_type Trace type for llcp (llcp tx, llcp rx and llcp ack of @see enum trace_types) + * @param[in] conhdl Connection handle + * @param[in] data_len Data length (in bytes) + * @param[in] pdu_data PDU Data + **************************************************************************************** + */ +void dbg_trc_req_llcp(uint8_t const llcp_trc_type, uint16_t const conhdl, uint8_t const data_len, uint8_t const *pdu_data); + +/// Macro used to send trace request API when an llcp packet is transmitted +#define TRC_REQ_LLCP_TX(conhdl, data_len, pdu_data) \ + dbg_trc_req_llcp(LLCP_TX, conhdl, data_len, pdu_data); + +/// Macro used to send trace request API when an llcp packet is received +#define TRC_REQ_LLCP_RX(conhdl, data_len, pdu_data) \ + dbg_trc_req_llcp(LLCP_RX, conhdl, data_len, pdu_data); + +/// Macro used to send trace request API when an llcp packet is acknowledged +#define TRC_REQ_LLCP_ACK(conhdl, data_len, pdu_data) \ + dbg_trc_req_llcp(LLCP_ACK, conhdl, data_len, pdu_data); +#else /*(TRACER_PRESENT && TRC_LLCP)*/ +#define TRC_REQ_LLCP_TX(conhdl, data_len, pdu_data) +#define TRC_REQ_LLCP_RX(conhdl, data_len, pdu_data) +#define TRC_REQ_LLCP_ACK(conhdl, data_len, pdu_data) +#endif /*(TRACER_PRESENT && TRC_LLCP) */ + +#if (TRACER_PRESENT && TRC_LMP) +/** + **************************************************************************************** + * @brief Trace request API for lmp packets transmission, reception and acknowledgment + * + * This function is called when a lmp packet is transmitted, received or acknowledged. + * + * It checks the current tracer configuration and writes the trace in memory if the trace + * group "LMP" (@see enum tracer_cfg_fields) is enabled. + * + * @param[in] lmp_trc_type Trace type for lmp (lmp tx, lmp rx and lmp ack of @see enum trace_types) + * @param[in] conhdl Connection handle + * @param[in] data_len Data length (in bytes) + * @param[in] pdu_data PDU Data + **************************************************************************************** + */ +void dbg_trc_req_lmp(uint8_t const lmp_trc_type, uint16_t const conhdl, uint8_t const data_len, uint8_t const *pdu_data); + +/// Macro used to send trace request API when an lmp packet is transmitted +#define TRC_REQ_LMP_TX(conhdl, data_len, pdu_data) \ + dbg_trc_req_lmp(LMP_TX, conhdl, data_len, pdu_data); + +/// Macro used to send trace request API when an lmp packet is received +#define TRC_REQ_LMP_RX(conhdl, data_len, pdu_data) \ + dbg_trc_req_lmp(LMP_RX, conhdl, data_len, pdu_data); + +/// Macro used to send trace request API when an lmp packet is acknowledged +#define TRC_REQ_LMP_ACK(conhdl, data_len, pdu_data) \ + dbg_trc_req_lmp(LMP_ACK, conhdl, data_len, pdu_data); + +#else /*(TRACER_PRESENT && TRC_LMP)*/ +#define TRC_REQ_LMP_TX(conhdl, data_len, pdu_data) +#define TRC_REQ_LMP_RX(conhdl, data_len, pdu_data) +#define TRC_REQ_LMP_ACK(conhdl, data_len, pdu_data) +#endif /*(TRACER_PRESENT && TRC_LMP)*/ + +#if (TRACER_PRESENT && TRC_L2CAP) +/** + **************************************************************************************** + * @brief Trace request API for l2cap packets transmission and reception + * + * This function is called when a l2cap packet is transmitted or received. + * + * It checks the current tracer configuration and writes the trace in memory if the trace + * group "L2CAP" (@see enum tracer_cfg_fields) is enabled. + * + * @param[in] l2cap_trc_type Trace type for l2cap (l2cap tx and l2cap rx of @see enum trace_types) + * @param[in] conhdl Connection handle + * @param[in] data_len Data length (in bytes) + * @param[in] buf_ptr Memory pointer address + **************************************************************************************** + */ +void dbg_trc_req_l2cap(uint8_t const l2cap_trc_type, uint16_t const conhdl, uint16_t const data_len, uint32_t const buf_ptr); + +/// Macro used to send trace request API when an l2cap packet is transmitted +#define TRC_REQ_L2CAP_TX(conhdl, tx_len, buf_ptr) \ + dbg_trc_req_l2cap(L2CAP_TX, conhdl, tx_len, buf_ptr); + +/// Macro used to send trace request API when an l2cap packet is received +#define TRC_REQ_L2CAP_RX(conhdl, tx_len, buf_ptr) \ + dbg_trc_req_l2cap(L2CAP_RX, conhdl, tx_len, buf_ptr); + +/** + **************************************************************************************** + * @brief Trace request API for l2cap packet acknowledgment + * + * This function is called when l2cap packets are acknowledged. + * + * It checks the current tracer configuration and writes the trace in memory if the trace + * group "L2CAP" (@see enum tracer_cfg_fields) is enabled. + * + * @param[in] conhdl Connection handle + * @param[in] num_ack_pkts Number of acknowledged l2cap packets + **************************************************************************************** + */ +void dbg_trc_req_l2cap_ack(uint16_t const conhdl, uint16_t const num_ack_pkts); + +#define TRC_REQ_L2CAP_ACK(conhdl, num_ack_pkts) \ + dbg_trc_req_l2cap_ack(conhdl, num_ack_pkts); + +#else /*(TRACER_PRESENT && TRC_L2CAP)*/ +#define TRC_REQ_L2CAP_TX(conhdl, tx_len, buf_ptr) +#define TRC_REQ_L2CAP_RX(conhdl, tx_len, buf_ptr) +#define TRC_REQ_L2CAP_ACK(conhdl, num_ack_pkts) +#endif/*(TRACER_PRESENT && TRC_L2CAP) */ + +#if (TRACER_PRESENT && TRC_ARB) +/** + **************************************************************************************** + * @brief Trace request API for cancellation, removal and starting of events + * + * This function is called when an event starts, is removed or is cancelled. + * + * It checks the current tracer configuration and writes the trace in memory if the trace + * group "EA" (@see enum tracer_cfg_fields) is enabled. + * + * @param[in] sch_arb_trc_type Trace type for Scheduling Arbiter (cancel, remove and start of @see enum trace_types) + * @param[in] sch_arb_elt Pointer to the Scheduling Arbiter element + **************************************************************************************** + */ +void dbg_trc_req_sch_arb(uint8_t const sch_arb_trc_type, const struct sch_arb_elt_tag *sch_arb_elt); + +/// Macro used to send trace request API when an event is cancelled +#define TRC_REQ_SCH_ARB_CANC(sch_arb_elt) \ + dbg_trc_req_sch_arb(SCH_ARB_CANC, sch_arb_elt); + +/// Macro used to send trace request API when an event is removed +#define TRC_REQ_SCH_ARB_REM(sch_arb_elt) \ + dbg_trc_req_sch_arb(SCH_ARB_REM, sch_arb_elt); + +/// Macro used to send trace request API when an event starts +#define TRC_REQ_SCH_ARB_START(sch_arb_elt) \ + dbg_trc_req_sch_arb(SCH_ARB_START, sch_arb_elt); + +/** + **************************************************************************************** + * @brief Trace request API for shifting of events + * + * This function is called when an event is shifted. + * + * It checks the current tracer configuration and writes the trace in memory if the trace + * group "EA" (@see enum tracer_cfg_fields) is enabled. + * + * @param[in] sch_arb_elt Pointer to the Scheduling Arbiter element + **************************************************************************************** + */ +void dbg_trc_req_sch_arb_shift(const struct sch_arb_elt_tag *sch_arb_elt); + +#define TRC_REQ_SCH_ARB_SHIFT(sch_arb_elt) \ + dbg_trc_req_sch_arb_shift(sch_arb_elt); +/** + **************************************************************************************** + * @brief Trace request API for pushing of event in the waiting queue + * + * This function is called when an event is pushed in the waiting queue. + * + * It checks the current tracer configuration and writes the trace in memory if the trace + * group "EA" (@see enum tracer_cfg_fields) is enabled. + * + * @param[in] sch_arb_elt Pointer to the Scheduling Arbiter element + **************************************************************************************** + */ +void dbg_trc_req_sch_arb_insert(uint32_t const target_time, uint8_t const status, const struct sch_arb_elt_tag *sch_arb_elt); + +#define TRC_REQ_SCH_ARB_INSERT(target_time, status, sch_arb_elt) \ + dbg_trc_req_sch_arb_insert(target_time, status, sch_arb_elt); + +#else /*(TRACER_PRESENT && TRC_ARB)*/ +#define TRC_REQ_SCH_ARB_CANC(sch_arb_elt) +#define TRC_REQ_SCH_ARB_REM(sch_arb_elt) +#define TRC_REQ_SCH_ARB_START(sch_arb_elt) +#define TRC_REQ_SCH_ARB_SHIFT(sch_arb_elt) +#define TRC_REQ_SCH_ARB_INSERT(target_time, status, sch_arb_elt) +#endif /*(TRACER_PRESENT && TRC_ARB)*/ + +#if (TRACER_PRESENT && TRC_LC_STATE_TRANS) +/** + **************************************************************************************** + * @brief Trace request API for lc procedure state transition + * + * This function is called when an lc procedure changes its state. + * + * It checks the current tracer configuration and writes the trace in memory if the trace + * group "LC state transition" (@see enum tracer_cfg_fields) is enabled. + * + * @param[in] conhdl Connection handle + * @param[in] proc_type LC procedure + * @param[in] prev_state Previous procedure state + * @param[in] curr_state Current procedure state + **************************************************************************************** + */ +void dbg_trc_req_lc_state_trans(uint16_t const conhdl, uint8_t const proc_type, uint8_t const prev_state, uint8_t const curr_state); + +#define TRC_REQ_LC_STATE_TRANS(conhdl, proc_type, prev_state, curr_state) \ + dbg_trc_req_lc_state_trans(conhdl, proc_type, prev_state, curr_state); + +#else /*(TRACER_PRESENT && TRC_LC_STATE_TRANS)*/ +#define TRC_REQ_LC_STATE_TRANS(conhdl, proc_type, prev_state, curr_state) +#endif /*(TRACER_PRESENT && TRC_LC_STATE_TRANS)*/ + +#if (TRACER_PRESENT && TRC_LLC_STATE_TRANS) +/** + **************************************************************************************** + * @brief Trace request API for llc procedure state transition + * + * This function is called when an llcp procedure changes its state. + * + * It checks the current tracer configuration and writes the trace in memory if the trace + * group "LLC state transition" (@see enum tracer_cfg_fields) is enabled. + * + * @param[in] conhdl Connection handle + * @param[in] proc_type LLC procedure + * @param[in] prev_state Previous procedure state + * @param[in] curr_state Current procedure state + **************************************************************************************** + */ +void dbg_trc_req_llc_state_trans(uint16_t const conhdl, uint8_t const proc_type, uint8_t const prev_state, uint8_t const curr_state); + +#define TRC_REQ_LLC_STATE_TRANS(conhdl, proc_type, prev_state, curr_state) \ + dbg_trc_req_llc_state_trans(conhdl, proc_type, prev_state, curr_state); + +#else /*(TRACER_PRESENT && TRC_LLC_STATE_TRANS)*/ +#define TRC_REQ_LLC_STATE_TRANS(conhdl, proc_type, prev_state, curr_state) +#endif /*(TRACER_PRESENT && TRC_LLC_STATE_TRANS)*/ + +#if (TRACER_PRESENT && TRC_HCI) +/** + **************************************************************************************** + * @brief Trace request API for HCI messages (in FE mode) + * + * This function is called when a HCI command is received. + * + * It checks the current tracer configuration and writes the trace in memory if the trace + * group "HCI" (@see enum tracer_cfg_fields) is enabled. + * + * @param[in] opcode HCI opcode + * @param[in] par_len HCI parameter length + * @param[in] params unpacked HCI parameters + **************************************************************************************** + */ +void dbg_trc_req_hci_cmd(uint16_t const opcode, uint16_t const par_len, uint32_t const *params); + +/** + **************************************************************************************** + * @brief Trace request API for HCI messages (in FE mode) + * + * This function is called when a HCI event is sent. + * + * It checks the current tracer configuration and writes the trace in memory if the trace + * group "HCI" (@see enum tracer_cfg_fields) is enabled. + * + * @param[in] hci_evt_type Type of hci event (@see enum trace_types) + * @param[in] opcode HCI opcode + * @param[in] par_len HCI parameter length + * @param[in] params unpacked HCI parameters + **************************************************************************************** + */ +void dbg_trc_req_hci_evt(uint8_t const hci_evt_type, uint16_t const opcode, uint16_t const par_len, uint32_t const *params); + +/// Macro used to send trace request API when a HCI command is received +#define TRC_REQ_HCI_CMD(opcode, par_len, params) \ + dbg_trc_req_hci_cmd(opcode, par_len, params); + +/// Macro used to send trace request API when a HCI command status event is sent +#define TRC_REQ_HCI_CMD_STAT_EVT(opcode, par_len, params) \ + dbg_trc_req_hci_evt(HCI_CMD_STAT_EVT, opcode, par_len, params); + +/// Macro used to send trace request API when a HCI command complete event is sent +#define TRC_REQ_HCI_CMD_CMP_EVT(opcode, par_len, params) \ + dbg_trc_req_hci_evt(HCI_CMD_CMP_EVT, opcode, par_len, params); + +/// Macro used to send trace request API when a HCI event is sent +#define TRC_REQ_HCI_EVT(opcode, par_len, params) \ + dbg_trc_req_hci_evt(HCI_EVT, opcode, par_len, params); + +/// Macro used to send trace request API when a HCI LE event is sent +#define TRC_REQ_HCI_LE_EVT(opcode, par_len, params) \ + dbg_trc_req_hci_evt(HCI_LE_EVT, (uint16_t) opcode, par_len, params); + + +#else /*(TRACER_PRESENT && TRC_HCI)*/ +#define TRC_REQ_HCI_CMD(opcode, par_len, params) +#define TRC_REQ_HCI_CMD_STAT_EVT(opcode, par_len, params) +#define TRC_REQ_HCI_CMD_CMP_EVT(opcode, par_len, params) +#define TRC_REQ_HCI_EVT(opcode, par_len, params) +#define TRC_REQ_HCI_LE_EVT(opcode, par_len, params) +#endif /*(TRACER_PRESENT && TRC_HCI)*/ + +#if (TRACER_PRESENT && TRC_ADV) + +//struct trc_scan_req +//{ +// /// Scanner address type +// //@trc_ref addr_type +// uint8_t scan_addr_type; +// +// /// Scanner address +// struct bd_addr scan_addr; +// +// /// Scan request +// struct scan_req data; +//}; +// +//struct trc_connect_req +//{ +// /// Initiator address type +// //@trc_ref addr_type +// uint8_t init_addr_type; +// +// /// Initiator address +// struct bd_addr init_addr; +// +// /// Connect request +// struct connect_req data; +//}; +// +// @trc_ref ble_adv_type +// */ +//union trc_adv_rx_payload +//{ +// //@trc_union packet_type == BLE_CONNECT_IND +// struct trc_connect_req conn_req; +// +// //@trc_union packet_type == BLE_SCAN_REQ +// struct trc_scan_req scan_req; +//}; +// +//struct trc_adv_rx_pdu_hdr +//{ +// ///Packet type +// //@trc_ref ble_adv_type +// uint8_t packet_type; +// +// ///Channel used +// uint8_t used_channel; +//}; +// +//struct trc_adv_rx_pdu +//{ +// ///Header +// struct trc_adv_rx_pdu_hdr header; +// +// ///Payload +// union trc_adv_rx_payload payload; +//}; + +/*@TRACE*/ +struct trc_scan_rx_pdu +{ + ///Packet type + //@trc_ref ble_adv_type + uint8_t packet_type; + + ///Channel used + uint8_t used_channel; + + /// Scanner device address + struct bd_addr scanner_addr; + + /// Scanner address type + //@trc_ref addr_type + uint8_t scanner_addr_type; + + /// Data length in bytes + uint8_t data_len; + + /// Data + uint8_t data[__ARRAY_EMPTY]; +}; + + +/*@TRACE*/ +struct trc_init_rx_pdu +{ + ///Packet type + //@trc_ref ble_adv_type + uint8_t packet_type; + + ///Channel used + uint8_t used_channel; + + /// Advertiser device address + struct bd_addr adv_addr; + + /// Peer device address type + //@trc_ref addr_type + uint8_t adv_addr_type; +}; + + +/*@TRACE*/ +struct trc_adv_tx_pdu +{ + ///Packet type + //@trc_ref ble_adv_type + uint8_t packet_type; + + ///Advertising channel map + uint8_t advertising_channel_map; + + /// BD Address of the advertiser + struct bd_addr adv_addr; +}; + +/*@TRACE*/ +struct trc_init_tx_pdu +{ + ///Packet type + //@trc_ref ble_adv_type + uint8_t packet_type; + + ///Advertising channel map + uint8_t advertising_channel_map; + + /// Peer device address + struct bd_addr peer_id_addr; +}; + +void dbg_trc_req_init_rx_pdu(const uint8_t index_pkt, uint16_t rxdataptr); +void dbg_trc_req_init_tx_pdu(const uint8_t index_pkt, struct bd_addr const addr); +void dbg_trc_req_adv_rx_pdu(const uint8_t index_pkt, const uint8_t data_len, void const *data); +void dbg_trc_req_adv_tx_pdu(const uint8_t adv_txdesc_idx, const uint8_t cs_idx); +void dbg_trc_req_scan_rx_pdu(const uint8_t index_pkt, struct lld_adv_rep_ind const* ind); +void dbg_trc_req_scan_tx_pdu(const uint8_t txdesc_idx, const uint8_t cs_idx); + +#define TRC_REQ_INIT_RX_PDU(index_pkt, addr) \ + dbg_trc_req_init_rx_pdu(index_pkt, addr); +#define TRC_REQ_INIT_TX_PDU(index_pkt, addr) \ + dbg_trc_req_init_tx_pdu(index_pkt, addr); + +#define TRC_REQ_ADV_RX_PDU(index_pkt, data_len, data) \ + dbg_trc_req_adv_rx_pdu(index_pkt, data_len, data); +#define TRC_REQ_ADV_TX_PDU(adv_txdesc_idx, cs_idx) \ + dbg_trc_req_adv_tx_pdu(adv_txdesc_idx, cs_idx); + +#define TRC_REQ_SCAN_RX_PDU(pkt_type, ind) \ + dbg_trc_req_scan_rx_pdu(pkt_type, ind); +#define TRC_REQ_SCAN_TX_PDU(txdesc_idx, cs_idx) \ + dbg_trc_req_scan_tx_pdu(txdesc_idx, cs_idx); + +#else +#define TRC_REQ_INIT_RX_PDU(index_pkt, addr) +#define TRC_REQ_INIT_TX_PDU(txdesc_idx, cs_idx) +#define TRC_REQ_ADV_RX_PDU(index_pkt, addr, addr_type) +#define TRC_REQ_ADV_TX_PDU(adv_txdesc_idx, cs_idx) +#define TRC_REQ_SCAN_RX_PDU(pkt_type, ind) +#define TRC_REQ_SCAN_TX_PDU(txdesc_idx, cs_idx) +#endif /*(TRACER_PRESENT && TRC_ADV)*/ + +#if (TRACER_PRESENT && TRC_ACL) +/*@TRACE*/ +struct trc_acl_tx_pdu +{ + uint16_t txdataptr; + + ///Data length + uint16_t data_len; + + ///Data + uint8_t data[__ARRAY_EMPTY]; +}; + +/*@TRACE*/ +struct trc_acl_rx_pdu +{ + ///Data length + uint16_t data_len; + + ///Data + uint8_t data[__ARRAY_EMPTY]; +}; + +void dbg_trc_req_acl_rx_pdu(struct lld_acl_rx_ind const* msg); +void dbg_trc_req_acl_tx_pdu(const uint8_t trc_acl_tx_type, const uint8_t txdesc_idx); + +#define TRC_REQ_ACL_RX_PDU(msg) \ + dbg_trc_req_acl_rx_pdu(msg); + +#define TRC_REQ_ACL_ACK_TX_PDU(txdesc_idx) \ + dbg_trc_req_acl_tx_pdu(ACL_ACK_TX, txdesc_idx); + +#define TRC_REQ_ACL_PROG_TX_PDU(txdesc_idx) \ + dbg_trc_req_acl_tx_pdu(ACL_PROG_TX, txdesc_idx); + +#else +#define TRC_REQ_ACL_RX_PDU(msg) +#define TRC_REQ_ACL_PROG_TX_PDU(txdesc_idx) +#define TRC_REQ_ACL_ACK_TX_PDU(txdesc_idx) +#endif /*(TRACER_PRESENT && TRC_ACL)*/ + +#if (TRACER_PRESENT && TRC_CUSTOM) +/** + **************************************************************************************** + * @brief Trace request API for custom traces + * + * This function is called to send a custom trace. + * + * It checks the current tracer configuration and writes the trace in memory if the trace + * group "custom" (@see enum tracer_cfg_fields) is enabled. + * + * @param[in] trc_id Trace request identifier (progressive number that identifies the caller) + * @param[in] data_type Type of data (@see enum custom_trace_types) + * @param[in] data Pointer to the data to send + **************************************************************************************** + */ +void dbg_trc_req_custom(const uint8_t trc_id, const uint8_t data_type, void const *data); +#define TRC_REQ_CUSTOM(trc_id, data_type, data) \ + dbg_trc_req_custom(trc_id, data_type, data); +#else /*(TRACER_PRESENT && TRC_CUSTOM)*/ +#define TRC_REQ_CUSTOM(trc_id, data_type, data) +#endif /*(TRACER_PRESENT && TRC_CUSTOM)*/ + +#if (TRACER_PRESENT) +/** + **************************************************************************************** + * @brief Configuration received + * + * This function checks if the received configuration can be adopted and acknowledges it + * + **************************************************************************************** + */ +void dbg_trc_cfg_received(); + +/** + **************************************************************************************** + * @brief Get the reception buffer for configuration word + * + * @return Buffer for payload reception of tracer configuration packets + **************************************************************************************** + */ +uint8_t* dbg_trc_pay_buff_get(); +#endif /*(TRACER_PRESENT)*/ +///@} TRACER +#endif // DBG_TRC_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/dbg/api/dbg_trc_config.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/dbg/api/dbg_trc_config.h new file mode 100755 index 0000000..8c0fcd0 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/dbg/api/dbg_trc_config.h @@ -0,0 +1,237 @@ +/** + **************************************************************************************** + * + * @file dbg_trc_config.h + * + * @brief Configuration of the Tracer module + * + * Copyright (C) RivieraWaves 2009-2016 + * + **************************************************************************************** + */ + +#ifndef DBG_TRC_CONFIG_H_ +#define DBG_TRC_CONFIG_H_ + +/** + **************************************************************************************** + * @addtogroup TRACER + * @{ + * @name Tracer module configuration + * @{ + **************************************************************************************** + */ + +#if defined CFG_TRC_ALL +#define TRC_KERNEL_MSG 1 +#define TRC_KERNEL_TMR 1 +#define TRC_KERNEL_EVT 1 +#define TRC_MEM 1 +#define TRC_SW_ASS 1 +#define TRC_CUSTOM 1 + +#if (BLE_EMB_PRESENT || BT_EMB_PRESENT) +#define TRC_ARB 1 +#define TRC_PROG 1 +#define TRC_SLEEP 1 +#else // (BLE_EMB_PRESENT || BT_EMB_PRESENT) +#define TRC_ARB 0 +#define TRC_PROG 0 +#define TRC_SLEEP 0 +#endif // (BLE_EMB_PRESENT || BT_EMB_PRESENT) + +#if (BLE_EMB_PRESENT) +#define TRC_CS_BLE 1 +#define TRC_LLCP 1 +#define TRC_LLC_STATE_TRANS 1 +#define TRC_RX_DESC 1 +#define TRC_ADV 1 +#define TRC_ACL 1 +#else /*(BLE_EMB_PRESENT)*/ +#define TRC_CS_BLE 0 +#define TRC_LLCP 0 +#define TRC_LLC_STATE_TRANS 0 +#define TRC_RX_DESC 0 +#define TRC_ADV 0 +#define TRC_ACL 0 +#endif /*(BLE_EMB_PRESENT)*/ + +#if (BLE_EMB_PRESENT && BLE_HOST_PRESENT) +#define TRC_HCI 1 +#else /*(BLE_EMB_PRESENT && BLE_HOST_PRESENT)*/ +#define TRC_HCI 0 +#endif /*(BLE_EMB_PRESENT && BLE_HOST_PRESENT)*/ + +#if (BLE_HOST_PRESENT) +#define TRC_L2CAP 1 +#else +#define TRC_L2CAP 0 +#endif /*(BLE_HOST_PRESENT)*/ + +#if (BT_EMB_PRESENT) +#define TRC_CS_BT 1 +#define TRC_LMP 1 +#define TRC_LC_STATE_TRANS 1 +#else +#define TRC_CS_BT 0 +#define TRC_LMP 0 +#define TRC_LC_STATE_TRANS 0 +#endif /*(BT_EMB_PRESENT)*/ + +#else /*(CFG_TRC_ALL)*/ + +#if defined CFG_TRC_KERNEL_MSG +#define TRC_KERNEL_MSG 1 +#else +#define TRC_KERNEL_MSG 0 +#endif /*(CFG_TRC_KERNEL_MSG)*/ + +#if defined CFG_TRC_KERNEL_TMR +#define TRC_KERNEL_TMR 1 +#else +#define TRC_KERNEL_TMR 0 +#endif /*CFG_TRC_KERNEL_TMR*/ + +#if defined CFG_TRC_KERNEL_EVT +#define TRC_KERNEL_EVT 1 +#else +#define TRC_KERNEL_EVT 0 +#endif /*CFG_TRC_KERNEL_EVT*/ + +#if defined CFG_TRC_MEM +#define TRC_MEM 1 +#else +#define TRC_MEM 0 +#endif /*CFG_TRC_MEM*/ + + +#if defined CFG_TRC_SW_ASS +#define TRC_SW_ASS 1 +#else +#define TRC_SW_ASS 0 +#endif /*CFG_TRC_SW_ASS*/ + +#if defined CFG_TRC_CUSTOM +#define TRC_CUSTOM 1 +#else +#define TRC_CUSTOM 0 +#endif /*CFG_TRC_CUSTOM*/ + +#if (BLE_EMB_PRESENT) +#if defined CFG_TRC_CS_BLE +#define TRC_CS_BLE 1 +#else +#define TRC_CS_BLE 0 +#endif /*(CFG_TRC_CS_BLE)*/ + +#if defined CFG_TRC_LLCP +#define TRC_LLCP 1 +#else +#define TRC_LLCP 0 +#endif /*(CFG_TRC_LLCP)*/ + +#if defined CFG_TRC_LLC_STATE_TRANS +#define TRC_LLC_STATE_TRANS 1 +#else +#define TRC_LLC_STATE_TRANS 0 +#endif /*(CFG_TRC_LLC_STATE_TRANS)*/ + +#if defined CFG_TRC_ARB +#define TRC_ARB 1 +#else +#define TRC_ARB 0 +#endif /*CFG_TRC_ARB*/ + +#if defined CFG_TRC_RX_DESC +#define TRC_RX_DESC 1 +#else +#define TRC_RX_DESC 0 +#endif /*CFG_TRC_RX_DESC*/ + +#if defined CFG_TRC_PROG +#define TRC_PROG 1 +#else +#define TRC_PROG 0 +#endif /*CFG_TRC_PROG*/ + +#if defined CFG_TRC_SLEEP +#define TRC_SLEEP 1 +#else +#define TRC_SLEEP 0 +#endif /*CFG_TRC_SLEEP*/ + +#if defined CFG_TRC_ADV +#define TRC_ADV 1 +#else +#define TRC_ADV 0 +#endif /*(CFG_TRC_ADV)*/ + +#if defined CFG_TRC_ACL +#define TRC_ACL 1 +#else +#define TRC_ACL 0 +#endif /*(CFG_TRC_ACL)*/ + +#else /*(BLE_EMB_PRESENT)*/ + +#define TRC_CS_BLE 0 +#define TRC_LLCP 0 +#define TRC_LLC_STATE_TRANS 0 +#define TRC_ARB 0 +#define TRC_RX_DESC 0 +#define TRC_PROG 0 +#define TRC_SLEEP 0 +#define TRC_ADV 0 +#define TRC_ACL 0 +#endif /*(BLE_EMB_PRESENT)*/ + +#if (BLE_EMB_PRESENT && BLE_HOST_PRESENT) +#if defined CFG_TRC_HCI +#define TRC_HCI 1 +#else +#define TRC_HCI 0 +#endif /*CFG_TRC_HCI*/ +#else /*(BLE_EMB_PRESENT && BLE_HOST_PRESENT)*/ +#define TRC_HCI 0 +#endif /*(BLE_EMB_PRESENT && BLE_HOST_PRESENT)*/ + +#if (BLE_HOST_PRESENT) +#if defined CFG_TRC_L2CAP +#define TRC_L2CAP 1 +#else +#define TRC_L2CAP 0 +#endif /*CFG_TRC_L2CAP*/ +#else /*BLE_HOST_PRESENT*/ +#define TRC_L2CAP 0 +#endif /*BLE_HOST_PRESENT*/ + +#if (BT_EMB_PRESENT) +#if defined CFG_TRC_CS_BT +#define TRC_CS_BT 1 +#else +#define TRC_CS_BT 0 +#endif /*CFG_TRC_CS_BT*/ + +#if defined CFG_TRC_LMP +#define TRC_LMP 1 +#else +#define TRC_LMP 0 +#endif /*CFG_TRC_LMP*/ + +#if defined CFG_TRC_LC_STATE_TRANS +#define TRC_LC_STATE_TRANS 1 +#else +#define TRC_LC_STATE_TRANS 0 +#endif /*CFG_TRC_LC_STATE_TRANS*/ + +#else /*BT_EMB_PRESENT*/ + +#define TRC_CS_BT 0 +#define TRC_LMP 0 +#define TRC_LC_STATE_TRANS 0 + +#endif /*BT_EMB_PRESENT*/ + +#endif /* CFG_TRC_ALL */ +/// @} TRACER +#endif /* DBG_TRC_CONFIG_H_ */ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/dbg/api/vssver.scc b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/dbg/api/vssver.scc new file mode 100755 index 0000000..2fea682 Binary files /dev/null and b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/dbg/api/vssver.scc differ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/dbg/src/dbg_trc_int.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/dbg/src/dbg_trc_int.h new file mode 100755 index 0000000..cf2f8e0 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/dbg/src/dbg_trc_int.h @@ -0,0 +1,159 @@ +/** + **************************************************************************************** + * + * @file dbg_trc_int.h + * + * @brief This file contains definitions related to the Tracer module. + * + * Copyright (C) RivieraWaves 2009-2015 + * + **************************************************************************************** + */ + +#ifndef DBG_TRC_INT_H_ +#define DBG_TRC_INT_H_ + +/** + **************************************************************************************** + * @addtogroup TRACER + * @{ + **************************************************************************************** + */ + +#include "rwip_config.h" + +#if (TRACER_PRESENT) +#include // standard definitions +#include // boolean + +/* + * DEFINES + **************************************************************************************** + */ + +///Channel index length +#define CHANNEL_ID_LEN 1 + +///lengths of trace packet fields +#define SEQ_NUM_LEN 2 +#define TIMESTAMP_LEN 4 +#define TRC_CODE_LEN 1 + +#define TRC_FIX_LEN \ + CHANNEL_ID_LEN +\ + TRC_MSG_HDR_LEN +\ + SEQ_NUM_LEN +\ + TIMESTAMP_LEN +\ + TRC_CODE_LEN + +/** + **************************************************************************************** + * @brief Convenient wrapper to trc_mem_alloc() + * + * This macro calls trc_mem_alloc() passing as parameter the length of the trace packet + * + * @param[in] trace_pay Trace payload length + * + * @return Pointer to trace code field(or NULL if the trace cannot be written) + **************************************************************************************** + */ +#define TRC_MEM_ALLOC(trace_pay) \ + dbg_trc_mem_alloc(TRC_FIX_LEN + trace_pay) + +typedef uint8_t trc_id_t; +typedef uint8_t trc_opcode_t; + +/* + * STRUCTURES DEFINITIONS + **************************************************************************************** + */ +///Tracer Environment context structure +struct dbg_trc_env_tag +{ + /// Current tracer configuration word + uint32_t curr_cw; + + /// Compiled tracer configuration word + uint32_t compiled_cw; +}; + +/* + * GLOBAL VARIABLE DEFINITIONS + **************************************************************************************** + */ +///Tracer environment context +extern struct dbg_trc_env_tag dbg_trc_env; + +/* + * TRANSPORT LAYER FUNCTION DECLARATIONS + **************************************************************************************** + */ +/** + **************************************************************************************** + * @brief initialize tracer TL + **************************************************************************************** + */ +void dbg_trc_tl_init(); + +/** + **************************************************************************************** + * @brief trigger the transmission of tracer packets + **************************************************************************************** + */ +void dbg_trc_tx_trigger(void); + +/* + * MEMORY FUNCTION DECLARATIONS + **************************************************************************************** + */ +/** + **************************************************************************************** + * @brief Initialize tracer memory + **************************************************************************************** + */ +void dbg_trc_mem_init(); + +/** + **************************************************************************************** + * @brief Try to write a trace in memory. + * @param[in] trace_len Trace packet length (expressed in bytes) + * + * @return Pointer to trace code field(or NULL if the trace cannot be written) + **************************************************************************************** + */ +uint8_t *dbg_trc_mem_alloc(uint16_t const trace_len); + +/** + **************************************************************************************** + * @brief Try to read a trace from the memory. + * + * @return Pointer to the total size of the trace (or NULL if the trace cannot be read) + **************************************************************************************** + */ +uint8_t *dbg_trc_mem_read(); + +/** + **************************************************************************************** + * @brief Deallocate a trace from the memory. + * + * This function marks the trace block pointed by the reading pointer as invalid and moves + * it to the next trace block + * + **************************************************************************************** + */ +void dbg_trc_mem_dealloc(); + +/** + **************************************************************************************** + * @brief Initialization of the tracer + * + * This function initializes the tracer + * + * @param[in] init_type Type of initialization (@see enum rwip_init_type) + **************************************************************************************** + */ +void dbg_trc_init(uint8_t init_type); + +#endif /* TRACER_PRESENT */ +/// @} TRACER +#endif /* DBG_TRC_INT_H_ */ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/ecc_p256/api/ecc_p256.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/ecc_p256/api/ecc_p256.h new file mode 100755 index 0000000..c2245b2 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/ecc_p256/api/ecc_p256.h @@ -0,0 +1,131 @@ +/** + **************************************************************************************** + * + * @file ecc_p256.h + * + * @brief ECC functions for P256 + * + * Copyright (C) RivieraWaves 2009-2015 + * + **************************************************************************************** + */ + +#ifndef ECC_P256_H_ +#define ECC_P256_H_ + + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_config.h" +#include +#include +#include "kernel_task.h" + +/* + * DEFINES + **************************************************************************************** + */ + +#define ECC_PUBLICKEY_GENERATION 0x01 +#define ECC_DHKEY_GENERATION 0x02 + + +/* + * STRUCTURE DEFINITIONS + **************************************************************************************** + */ + +/// Multiplication result message structure +/*@TRACE*/ +struct ecc_result_ind +{ + uint8_t key_res_x[32]; + uint8_t key_res_y[32]; +}; + + +/* + * VARIABLE DECLARATION + **************************************************************************************** + */ + +/// Debug Private Key +extern const uint8_t DebugE256SecretKey[32]; + + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Initialize Elliptic Curve algorithm + * + * @param[in] init_type Type of initialization (@see enum rwip_init_type) + **************************************************************************************** + */ +void ecc_init(uint8_t init_type); + +/** + **************************************************************************************** + * @brief Generate a Secret Key compliant with ECC P256 algorithm + * + * If key is forced, just check its validity + * + * @param[out] secret_key Private key - MSB First + * @param[in] forced True if provided key is forced, else generate it. + **************************************************************************************** + */ +void ecc_gen_new_secret_key(uint8_t* secret_key, bool forced); + +/** + **************************************************************************************** + * @brief Generate a new Public key pair using ECC P256 algorithm + * + * @param[in] secret_key Private key - MSB First + * @param[in] blocking Force to run full algorithm without continue mode + **************************************************************************************** + */ +void ecc_gen_new_public_key(uint8_t* secret_key256, kernel_msg_id_t msg_id, kernel_task_id_t task_id); + +/** + **************************************************************************************** + * @brief Generate a new DHKey using ECC P256 algorithm + * + * @param[in] key_type Type of key to generate (1: public key | 2: DH key) + * @param[in] secret_key Private key - MSB First + * @param[in] pub_key_x Peer public key x coordinate - LSB First + * @param[in] pub_key_y Peer public key y coordinate - LSB First + * @param[in] msg_id Message task ID for the result indication + * @param[in] task_id Client task ID (Task type + instance) + * + * @return status 0 if key generation is started, > 0 otherwise + **************************************************************************************** + */ +uint8_t ecc_generate_key256(uint8_t key_type, const uint8_t* secret_key, const uint8_t* public_key_x, const uint8_t* public_key_y, kernel_msg_id_t msg_id, kernel_task_id_t task_id); + +/** + **************************************************************************************** + * @brief Abort a current DHKey generation procedure + * + * @param[in] task_id Client task ID (Task type + instance) + **************************************************************************************** + */ +void ecc_abort_key256_generation(kernel_task_id_t task_id); + +/** + **************************************************************************************** + * @brief Retrieve debug private and public keys + * + * @param[out] secret_key Private key - MSB First + * @param[out] pub_key_x Public key x coordinate - LSB First + * @param[out] pub_key_y Public key y coordinate - LSB First + **************************************************************************************** + */ +void ecc_get_debug_Keys(uint8_t*secret_key, uint8_t* pub_key_x, uint8_t* pub_key_y); + + +#endif /* ECC_P256_H_ */ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/h4tl/api/h4tl.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/h4tl/api/h4tl.h new file mode 100755 index 0000000..c2830ef --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/h4tl/api/h4tl.h @@ -0,0 +1,136 @@ +/** + **************************************************************************************** + * + * @file h4tl.h + * + * @brief H4 UART Transport Layer header file. + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef H4TL_H_ +#define H4TL_H_ + +/** + **************************************************************************************** + * @addtogroup H4TL H4 UART Transport Layer + * @ingroup H4TL + * @brief H4 UART Transport Layer + * + * This module creates the abstraction between External UART driver and HCI generic functions + * (designed for H4 UART transport layer). + * + * @{ + **************************************************************************************** + */ + + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" // stack configuration + +#if (H4TL_SUPPORT) +#include "rwip.h" // SW interface + +#include // standard integer definition +#include // standard boolean definition + +/* + * DEFINES + **************************************************************************************** + */ + +/// Size of the logical channel identifier for H4 messages +#define H4TL_LOGICAL_CHANNEL_LEN (1) + +/** + * Number of H4TL interfaces + * + * * NB=2: AHI and HCI: for Host-only stack with external app + * - HCI has index 0 + * - AHI has index 1 + * * NB=1: AHI or HCI: for all other partitions + * + * Note: it is not possible to have no channel (H4TL must not be included in build in this case) + */ +#if (!BLE_EMB_PRESENT && HCI_TL_SUPPORT && AHI_TL_SUPPORT) +#define H4TL_NB_CHANNEL 2 +#else // (!BLE_EMB_PRESENT && HCI_TL_SUPPORT && AHI_TL_SUPPORT) +#define H4TL_NB_CHANNEL 1 +#endif // (!BLE_EMB_PRESENT && HCI_TL_SUPPORT && AHI_TL_SUPPORT) + + +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ + + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ +/** + **************************************************************************************** + * @brief H4TL transport initialization. + * + * Puts the External Interface driver in reception, waiting for simple 1 byte message type. Space for + * reception is allocated with kernel_msg_alloc and the pointer is handed to env.rx. RX + * interrupt is enabled. + * + * @param[in] tl_type Transport Layer Interface (@see enum h4tl_itf) + * @param[in] eif External interface API + * + ***************************************************************************************** + */ +void h4tl_init(uint8_t tl_type, const struct rwip_eif_api* eif); + + +/** + **************************************************************************************** + * @brief H4TL write function. + * + * @param[in] type Type of the buffer to be transmitted. It can take one of the following + * values: + * - @ref HCI_EVT_MSG_TYPE for event message + * - @ref HCI_ACL_MSG_TYPE for ACL data + * - @ref HCI_SYNC_MSG_TYPE for synchronous data + * + * @param[in] buf Pointer to the buffer to be transmitted. @note The buffer passed as + * parameter must have one free byte before the first payload byte, so that the H4TL + * module can put the type byte as first transmitted data. + * + * @param[in] len Length of the buffer to be transmitted. + * @param[in] tx_callback Callback for indicating the end of transfer + ***************************************************************************************** + */ +void h4tl_write(uint8_t type, uint8_t *buf, uint16_t len, void (*tx_callback)(void)); + +/** + **************************************************************************************** + * @brief Start External Interface input flow + * + ***************************************************************************************** + */ +void h4tl_start(void); + +/** + **************************************************************************************** + * @brief Stop External Interface input flow if possible + * + * @return true if External Interface flow was stopped, false otherwise + ***************************************************************************************** + */ +bool h4tl_stop(void); + +#endif //H4TL_SUPPORT + +/// @} H4TL + +#endif // H4TL_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/ke/api/kernel.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/ke/api/kernel.h new file mode 100755 index 0000000..4524c33 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/ke/api/kernel.h @@ -0,0 +1,103 @@ +/** + **************************************************************************************** + * + * @file kernel.h + * + * @brief This file contains the definition of the kernel environment. + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef _KERNEL_H_ +#define _KERNEL_H_ + +/** + **************************************************************************************** + * @addtogroup ENV Environment + * @ingroup KERNEL + * @brief Kernel Environment + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" // stack configuration + +#include // standard boolean definitions +#include // standard integer definitions + +/* + * ENUMERATION + **************************************************************************************** + */ + +/// Kernel Error Status +enum KERNEL_STATUS +{ + KERNEL_SUCCESS = 0, + KERNEL_FAIL +}; + + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief This function performs all the initializations of the kernel. + * + * It initializes first the heap, then the message queues and the events. Then if required + * it initializes the trace. + * + **************************************************************************************** + */ +void kernel_init(void); + +/** + **************************************************************************************** + * @brief This function flushes all messages, timers and events currently pending in the + * kernel. + * + **************************************************************************************** + */ +void kernel_flush(void); + +/** + **************************************************************************************** + * @brief This function checks if sleep is possible or kernel is processing + * + * @return True if sleep is allowed, false otherwise + **************************************************************************************** + */ +bool kernel_sleep_check(void); + +#if (KERNEL_PROFILING) +/** + **************************************************************************************** + * @brief This function gets the statistics of the kernel usage. + * + * @param[out] max_msg_sent Max message sent + * @param[out] max_msg_saved Max message saved + * @param[out] max_timer_used Max timer used + * @param[out] max_heap_used Max heap used + **************************************************************************************** + */ +enum KERNEL_STATUS kernel_stats_get(uint8_t* max_msg_sent, + uint8_t* max_msg_saved, + uint8_t* max_timer_used, + uint16_t* max_heap_used); +#endif //KERNEL_PROFILING + +/// @} KE + +#endif // _KERNEL_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/ke/api/kernel_event.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/ke/api/kernel_event.h new file mode 100755 index 0000000..4890e84 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/ke/api/kernel_event.h @@ -0,0 +1,152 @@ +/** + **************************************************************************************** + * + * @file kernel_event.h + * + * @brief This file contains the definition related to kernel events. + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef _KERNEL_EVENT_H_ +#define _KERNEL_EVENT_H_ + +/** + **************************************************************************************** + * @addtogroup EVT Events and Schedule + * @ingroup KERNEL + * @brief Event scheduling module. + * + * The KERNEL_EVT module implements event scheduling functions. It can be used to + * implement deferred actions. + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" // stack configuration + +#include // standard integer definition + + +/* + * CONSTANTS + **************************************************************************************** + */ + + +/// Status of kernel_task API functions +enum KERNEL_EVENT_STATUS +{ + KERNEL_EVENT_OK = 0, + KERNEL_EVENT_FAIL, + KERNEL_EVENT_UNKNOWN, + KERNEL_EVENT_CAPA_EXCEEDED, + KERNEL_EVENT_ALREADY_EXISTS, +}; + + +/* + * TYPE DEFINITION + **************************************************************************************** + */ + + + + +/* + * FUNCTION PROTOTYPES + **************************************************************************************** + */ + + + +/** + **************************************************************************************** + * @brief Initialize Kernel event module. + **************************************************************************************** + */ +void kernel_event_init(void); + +/** + **************************************************************************************** + * @brief Register an event callback. + * + * @param[in] event_type Event type. + * @param[in] p_callback Pointer to callback function. + * + * @return Status + **************************************************************************************** + */ +uint8_t kernel_event_callback_set(uint8_t event_type, void (*p_callback)(void)); + +/** + **************************************************************************************** + * @brief Set an event + * + * This primitive sets one event. It will trigger the call to the corresponding event + * handler in the next scheduling call. + * + * @param[in] event_type Event to be set. + **************************************************************************************** + */ +void kernel_event_set(uint8_t event_type); + +/** + **************************************************************************************** + * @brief Clear an event + * + * @param[in] event_type Event to be cleared. + **************************************************************************************** + */ +void kernel_event_clear(uint8_t event_type); + +/** + **************************************************************************************** + * @brief Get the status of an event + * + * @param[in] event_type Event to get. + * + * @return Event status (0: not set / 1: set) + **************************************************************************************** + */ +uint8_t kernel_event_get(uint8_t event_type); + +/** + **************************************************************************************** + * @brief Get all event status + * + * @return Events bit field + **************************************************************************************** + */ +uint32_t kernel_event_get_all(void); + +/** + **************************************************************************************** + * @brief Flush all pending events. + **************************************************************************************** + */ +void kernel_event_flush(void); + +/** + **************************************************************************************** + * @brief Event scheduler entry point. + * + * This primitive is the entry point of Kernel event scheduling. + **************************************************************************************** + */ +void kernel_event_schedule(void); + + + +/// @} EVT + +#endif //_KERNEL_EVENT_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/ke/api/kernel_mem.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/ke/api/kernel_mem.h new file mode 100755 index 0000000..011f26b --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/ke/api/kernel_mem.h @@ -0,0 +1,171 @@ +/** + **************************************************************************************** + * + * @file kernel_mem.h + * + * @brief API for the heap management module. + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef _KERNEL_MEM_H_ +#define _KERNEL_MEM_H_ + +#include "rwip_config.h" // IP configuration +#include // standard integer +#include // standard includes + +/** + **************************************************************************************** + * @defgroup MEM Memory + * @ingroup KERNEL + * @brief Heap management module. + * + * This module implements heap management functions that allow initializing heap, + * allocating and freeing memory. + * + * @{ + **************************************************************************************** + */ + +#define KERNEL_MEM_DEBUG 0 + +#define BK_BLE_ASSERT_MEM_CORRUPT_ERR_POS 1 +#define BK_BLE_ASSERT_MEM_NO_SPACE_POS 2 + +/* + *BIT 0--------->BK_BLE_ASSERT_MEM_CORRUPT_ERR + *BIT 1--------->BK_BLE_ASSERT_MEM_NO_SPACE + *others-------->NONE +*/ +uint8_t bk_ble_mem_assert_type_cb(uint8_t clear); + + + +// forward declarations +struct mblock_free; + +/** + **************************************************************************************** + * @brief Heap initialization. + * + * This function performs the following operations: + * - sanity checks + * - check memory allocated is at least large enough to hold two block descriptors to hold + * start and end + * - initialize the first and last descriptors + * - save heap into kernel environment variable. + * + * @param[in] type Memory type. + * @param[in|out] heap Heap pointer + * @param[in] heap_size Size of the heap + * + * + **************************************************************************************** + */ +void kernel_mem_init(uint8_t type, uint8_t* heap, uint16_t heap_size); + +/** + **************************************************************************************** + * @brief Allocation of a block of memory. + * + * Allocates a memory block whose size is size; if no memory is available return NULL + * + * @param[in] size Size of the memory area that need to be allocated. + * @param[in] type Type of memory block + * + * @return A pointer to the allocated memory area. + * + **************************************************************************************** + */ +#if KERNEL_MEM_DEBUG +void *kernel_malloc_debug(uint32_t size, uint8_t type,const char *func, uint32_t line); +#define kernel_malloc(size, type) kernel_malloc_debug(size, type, __FUNCTION__, __LINE__) +#else +void *kernel_malloc(uint32_t size, uint8_t type); +#endif + +/** + **************************************************************************************** + * @brief Check if it's possible to allocate a block of memory with a specific size. + * + * @param[in] size Size of the memory area that need to be allocated. + * @param[in] type Type of memory block + * + * @return True if memory block can be allocated, False else. + * + **************************************************************************************** + */ +bool kernel_check_malloc(uint32_t size, uint8_t type); + +/** + **************************************************************************************** + * @brief Freeing of a block of memory. + * + * Free the memory area pointed by mem_ptr : mark the block as free and insert it in + * the pool of free block. + * + * @param[in] mem_ptr Pointer to the memory area that need to be freed. + * + **************************************************************************************** + */ +void kernel_free(void *mem_ptr); + + +/** + **************************************************************************************** + * @brief Check if current heap is empty or not (not used) + * + * @param[in] type Type of memory heap block + * + * @return true if heap not used, false else. + **************************************************************************************** + */ +bool kernel_mem_is_empty(uint8_t type); + + + +/** + **************************************************************************************** + * @brief Check if current pointer is free or not + * + * @param[in] mem_ptr pointer to a memory block + * + * @return true if already free, false else. + **************************************************************************************** + */ +bool kernel_is_free(void* mem_ptr); + +#if (KERNEL_PROFILING) + +/** + **************************************************************************************** + * @brief Retrieve memory usage of selected heap. + * + * @param[in] type Type of memory heap block + * + * @return current memory usage of current heap. + **************************************************************************************** + */ +uint16_t kernel_get_mem_usage(uint8_t type); + + +/** + **************************************************************************************** + * @brief Retrieve max memory usage of all heap. + * This command also resets max measured value. + * + * @return max memory usage of all heap. + **************************************************************************************** + */ +uint32_t kernel_get_max_mem_usage(void); + +#endif // (KERNEL_PROFILING) + +///@} MEM + +#endif // _KERNEL_MEM_H_ + diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/ke/api/kernel_msg.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/ke/api/kernel_msg.h new file mode 100755 index 0000000..2e309b1 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/ke/api/kernel_msg.h @@ -0,0 +1,329 @@ +/** + **************************************************************************************** + * + * @file kernel_msg.h + * + * @brief This file contains the definition related to message scheduling. + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef _KERNEL_MSG_H_ +#define _KERNEL_MSG_H_ + +/** + **************************************************************************************** + * @defgroup MSG Message Exchange + * @ingroup KERNEL + * @brief Message scheduling module. + * + * The MSG module implements message scheduling functions. + + * A kernel message has an ID, a receiver task ID and a source task ID. + * In most cases, it also has parameters which are defined in + * a structure dynamically embedded in the message structure, + * so the whole message will be managed internally as one block. + * + * A message can also have one extra parameter which is referenced + * in the normal parameter structure. This extra block is assumed + * to be large by the kernel and will be moved by DMA if needed. + * This feature allows moving MMPDU from LMAC to UMAC. + * + * In order to send a message, a function first have to allocate + * the memory for this message. It can be done with the wrapper + * macro KERNEL_MSG_ALLOC() (which will call kernel_msg_alloc()). + + * The message can then be sent with kernel_msg_send(). The kernel + * will take care of freeing the allocated memory. + + * If the message has no parameters, the kernel_msg_send_basic() function + * can be used. + * + * @{ + **************************************************************************************** + */ + +#include // standard definition +#include // standard integer +#include // standard boolean +#include "architect.h" // architectural definition +#include "compiler.h" // compiler definition +#include "common_list.h" // list definition +#include "kernel_mem.h" + + +/// Task Identifier. Composed by the task type and the task index. +typedef uint16_t kernel_task_id_t; + +/// Builds the task identifier from the type and the index of that task. +#define KERNEL_BUILD_ID(type, index) ( (kernel_task_id_t)(((index) << 8)|(type)) ) + +/// Retrieves task type from task id. +#define KERNEL_TYPE_GET(kernel_task_id) ((kernel_task_id) & 0xFF) + +/// Retrieves task index number from task id. +#define KERNEL_IDX_GET(kernel_task_id) (((kernel_task_id) >> 8) & 0xFF) + +/// Task State +typedef uint8_t kernel_state_t; + +/// Message Identifier. The number of messages is limited to 0xFFFF. +/// The message ID is divided in two parts: +/// bits[15~8]: task index (no more than 255 tasks support) +/// bits[7~0]: message index(no more than 255 messages per task) +/*@TRACE*/ +typedef uint16_t kernel_msg_id_t; + +/// Message structure. +struct kernel_msg +{ + struct common_list_hdr hdr; ///< List header for chaining + + kernel_msg_id_t id; ///< Message id. + kernel_task_id_t dest_id; ///< Destination kernel identifier. + kernel_task_id_t src_id; ///< Source kernel identifier. + uint16_t param_len; ///< Parameter embedded struct length. + uint32_t param[__ARRAY_EMPTY]; ///< Parameter embedded struct. Must be word-aligned. +}; + + +/// Status returned by a task when handling a message +/*@TRACE*/ +enum kernel_msg_status_tag +{ + KERNEL_MSG_CONSUMED = 0, ///< consumed, msg and ext are freed by the kernel + KERNEL_MSG_NO_FREE, ///< consumed, nothing is freed by the kernel + KERNEL_MSG_SAVED, ///< not consumed, will be pushed in the saved queue +}; + +/** + **************************************************************************************** + * @brief Convert a parameter pointer to a message pointer + * + * @param[in] param_ptr Pointer to the parameter member of a kernel_msg + * Usually retrieved by a kernel_msg_alloc() + * + * @return The pointer to the kernel_msg + **************************************************************************************** + */ +__INLINE struct kernel_msg * kernel_param2msg(void const *param_ptr) +{ + return (struct kernel_msg*) (((uint8_t*)param_ptr) - offsetof(struct kernel_msg, param)); +} + +/** + **************************************************************************************** + * @brief Convert a message pointer to a parameter pointer + * + * @param[in] msg Pointer to the kernel_msg. + * + * @return The pointer to the param member + **************************************************************************************** + */ +__INLINE void * kernel_msg2param(struct kernel_msg const *msg) +{ + return (void*) (((uint8_t*) msg) + offsetof(struct kernel_msg, param)); +} + +/** + **************************************************************************************** + * @brief Convenient wrapper to kernel_msg_alloc() + * + * This macro calls kernel_msg_alloc() and cast the returned pointer to the + * appropriate structure. Can only be used if a parameter structure exists + * for this message (otherwise, use kernel_msg_send_basic()). + * + * @param[in] id Message identifier + * @param[in] dest Destination Identifier + * @param[in] src Source Identifier + * @param[in] param_str parameter structure tag + * + * @return Pointer to the parameter member of the kernel_msg. + **************************************************************************************** + */ +#define KERNEL_MSG_ALLOC(id, dest, src, param_str) \ + (struct param_str*) kernel_msg_alloc(id, dest, src, sizeof(struct param_str)) + +/** + **************************************************************************************** + * @brief Convenient wrapper to kernel_msg_free() + * + * This macro calls kernel_msg_free() with the appropriate msg pointer as parameter, according + * to the message parameter pointer passed. + * + * @param[in] param_ptr parameter structure pointer + **************************************************************************************** + */ +#define KERNEL_MSG_FREE(param_ptr) kernel_msg_free(kernel_param2msg((param_ptr))) + +/** + **************************************************************************************** + * @brief Convenient wrapper to kernel_msg_alloc() + * + * This macro calls kernel_msg_alloc() and cast the returned pointer to the + * appropriate structure with a variable length. Can only be used if a parameter structure exists + * for this message (otherwise, use kernel_msg_send_basic()).Can only be used if the data array is + * located at the end of the structure. + * + * @param[in] id Message identifier + * @param[in] dest Destination Identifier + * @param[in] src Source Identifier + * @param[in] param_str parameter structure tag + * @param[in] length length for the data + * + * @return Pointer to the parameter member of the kernel_msg. + **************************************************************************************** + */ +#define KERNEL_MSG_ALLOC_DYN(id, dest, src, param_str,length) (struct param_str*)kernel_msg_alloc(id, dest, src, \ + (sizeof(struct param_str) + (length))); + +/** + **************************************************************************************** + * @brief Allocate memory for a message + * + * This primitive allocates memory for a message that has to be sent. The memory + * is allocated dynamically on the heap and the length of the variable parameter + * structure has to be provided in order to allocate the correct size. + * + * Several additional parameters are provided which will be preset in the message + * and which may be used internally to choose the kind of memory to allocate. + * + * The memory allocated will be automatically freed by the kernel, after the + * pointer has been sent to kernel_msg_send(). If the message is not sent, it must + * be freed explicitly with kernel_msg_free(). + * + * Allocation failure is considered critical and should not happen. + * + * @param[in] id Message identifier + * @param[in] dest_id Destination Task Identifier + * @param[in] src_id Source Task Identifier + * @param[in] param_len Size of the message parameters to be allocated + * + * @return Pointer to the parameter member of the kernel_msg. If the parameter + * structure is empty, the pointer will point to the end of the message + * and should not be used (except to retrieve the message pointer or to + * send the message) + **************************************************************************************** + */ +#if KERNEL_MEM_DEBUG +void *kernel_msg_alloc_debug(kernel_msg_id_t const id, kernel_task_id_t const dest_id, + kernel_task_id_t const src_id, uint16_t const param_len,const char *func, uint32_t line); + +#define kernel_msg_alloc(id, dest_id, src_id, param_len) kernel_msg_alloc_debug(id, dest_id, src_id, param_len, __FUNCTION__, __LINE__) +#else + +void *kernel_msg_alloc(kernel_msg_id_t const id, kernel_task_id_t const dest_id, + kernel_task_id_t const src_id, uint16_t const param_len); +#endif +/** + **************************************************************************************** + * @brief Message sending. + * + * Send a message previously allocated with any kernel_msg_alloc()-like functions. + * + * The kernel will take care of freeing the message memory. + * + * Once the function have been called, it is not possible to access its data + * anymore as the kernel may have copied the message and freed the original + * memory. + * + * @param[in] param_ptr Pointer to the parameter member of the message that + * should be sent. + **************************************************************************************** + */ + +void kernel_msg_send(void const *param_ptr); + +/** + **************************************************************************************** + * @brief Basic message sending. + * + * Send a message that has a zero length parameter member. No allocation is + * required as it will be done internally. + * + * @param[in] id Message identifier + * @param[in] dest_id Destination Identifier + * @param[in] src_id Source Identifier + **************************************************************************************** + */ +void kernel_msg_send_basic(kernel_msg_id_t const id, kernel_task_id_t const dest_id, kernel_task_id_t const src_id); + +/** + **************************************************************************************** + * @brief Message forwarding. + * + * Forward a message to another task by changing its destination and source tasks IDs. + * + * @param[in] param_ptr Pointer to the parameter member of the message that + * should be sent. + * @param[in] dest_id New destination task of the message. + * @param[in] src_id New source task of the message. + **************************************************************************************** + */ +void kernel_msg_forward(void const *param_ptr, kernel_task_id_t const dest_id, kernel_task_id_t const src_id); + +/** + **************************************************************************************** + * @brief Message forwarding. + * + * Forward a message to another task by changing its message ID and its destination and source tasks IDs. + * + * @param[in] param_ptr Pointer to the parameter member of the message that + * should be sent. + * @param[in] msg_id New ID of the message. + * @param[in] dest_id New destination task of the message. + * @param[in] src_id New source task of the message. + **************************************************************************************** + */ +void kernel_msg_forward_new_id(void const *param_ptr, + kernel_msg_id_t const msg_id, kernel_task_id_t const dest_id, kernel_task_id_t const src_id); + +/** + **************************************************************************************** + * @brief Free allocated message + * + * @param[in] msg Pointer to the message to be freed (not the parameter member!) + **************************************************************************************** + */ +void kernel_msg_free(struct kernel_msg const *param); + + + +/** + **************************************************************************************** + * @brief Retrieve destination task identifier of a kernel message + * + * @param[in] param_ptr Pointer to the parameter member of the message. + * + * @return message destination task + **************************************************************************************** + */ +kernel_msg_id_t kernel_msg_dest_id_get(void const *param_ptr); + + + +/** + **************************************************************************************** + * @brief Retrieve source task identifier of a kernel message + * + * @param[in] param_ptr Pointer to the parameter member of the message. + * + * @return message source task + **************************************************************************************** + */ +kernel_msg_id_t kernel_msg_src_id_get(void const *param_ptr); + +/** + * Used to know if message is present in kernel queue or not. + * + * @param[in] param_ptr Pointer to the parameter member of the message. + * + * @return True if message is present in Kernel Queue, False else. + */ +bool kernel_msg_in_queue(void const *param_ptr); +/// @} MSG + +#endif // _KERNEL_MSG_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/ke/api/kernel_task.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/ke/api/kernel_task.h new file mode 100755 index 0000000..4b642fb --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/ke/api/kernel_task.h @@ -0,0 +1,221 @@ +/** + **************************************************************************************** + * + * @file kernel_task.h + * + * @brief This file contains the definition related to kernel task management. + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef _KERNEL_TASK_H_ +#define _KERNEL_TASK_H_ + +/** + **************************************************************************************** + * @defgroup TASK Task and Process + * @ingroup KERNEL + * @brief Task management module. + * + * This module implements the functions used for managing tasks. + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include // standard integer +#include // standard boolean + +#include "rwip_config.h" // stack configuration +#include "compiler.h" // compiler defines, INLINE +#include "kernel_msg.h" // kernel message defines + +/* Default Message handler code to handle several message type in same handler. */ +#define KERNEL_MSG_DEFAULT_HANDLER (0xFFFF) +/* Invalid task */ +#define KERNEL_TASK_INVALID (0xFFFF) +/* Used to know if a message is not present in kernel queue */ +#define KERNEL_MSG_NOT_IN_QUEUE ((struct common_list_hdr *) 0xFFFFFFFF) + +/// Status of kernel_task API functions +enum KERNEL_TASK_STATUS +{ + KERNEL_TASK_OK = 0, + KERNEL_TASK_FAIL, + KERNEL_TASK_UNKNOWN, + KERNEL_TASK_CAPA_EXCEEDED, + KERNEL_TASK_ALREADY_EXISTS, +}; + + +#define BLE_MSG_T(msg) ((kernel_task_id_t)((msg) >> 8)) +#define BLE_MSG_I(msg) ((msg) & ((1<<8)-1)) + +/// Format of a task message handler function +typedef int (*kernel_msg_func_t)(kernel_msg_id_t const msgid, void const *param, + kernel_task_id_t const dest_id, kernel_task_id_t const src_id); + +/// Macro for message handler function declaration or definition +#define KERNEL_MSG_HANDLER(msg_name, param_struct) __STATIC int msg_name##_handler(kernel_msg_id_t const msgid, \ + param_struct const *param, \ + kernel_task_id_t const dest_id, \ + kernel_task_id_t const src_id) + +#define KERNEL_MSG_HANDLER_NO_STATIC(msg_name, param_struct) int msg_name##_handler(kernel_msg_id_t const msgid, \ + param_struct const *param, \ + kernel_task_id_t const dest_id, \ + kernel_task_id_t const src_id) + +/// Macro for message handlers table declaration or definition +#define KERNEL_MSG_HANDLER_TAB(task) __STATIC const struct kernel_msg_handler task##_msg_handler_tab[] = + +/// Element of a message handler table. +struct kernel_msg_handler +{ + /// Id of the handled message. + kernel_msg_id_t id; + /// Pointer to the handler function for the msgid above. + kernel_msg_func_t func; +}; + +/// Task descriptor grouping all information required by the kernel for the scheduling. +struct kernel_task_desc +{ + /// Pointer to the message handler table + const struct kernel_msg_handler* msg_handler_tab; + /// Pointer to the state table (one element for each instance). + kernel_state_t* state; + /// Maximum index of supported instances of the task. + uint16_t idx_max; + /// Number of messages handled + uint16_t msg_cnt; +}; + +/* + * FUNCTION PROTOTYPES + **************************************************************************************** + */ + + +/** + **************************************************************************************** + * @brief Initialize Kernel task module. + **************************************************************************************** + */ +void kernel_task_init(void); + +/** + **************************************************************************************** + * @brief Create a task. + * + * @param[in] task_type Task type. + * @param[in] p_task_desc Pointer to task descriptor. + * + * @return Status + **************************************************************************************** + */ +uint8_t kernel_task_create(uint8_t task_type, struct kernel_task_desc const * p_task_desc); + +/** + **************************************************************************************** + * @brief Delete a task. + * + * @param[in] task_type Task type. + * + * @return Status + **************************************************************************************** + */ +uint8_t kernel_task_delete(uint8_t task_type); + +/** + **************************************************************************************** + * @brief Retrieve the state of a task. + * + * @param[in] id Task id. + * + * @return Current state of the task + **************************************************************************************** + */ +kernel_state_t kernel_state_get(kernel_task_id_t const id); + +/** + **************************************************************************************** + * @brief Set the state of the task identified by its Task Id. + * + * In this function we also handle the SAVE service: when a task state changes we + * try to activate all the messages currently saved in the save queue for the given + * task identifier. + * + * @param[in] id Identifier of the task instance whose state is going to be modified + * @param[in] state_id New State + * + **************************************************************************************** + */ +void kernel_state_set(kernel_task_id_t const id, kernel_state_t const state_id); + +/** + **************************************************************************************** + * @brief Generic message handler to consume message without handling it in the task. + * + * @param[in] msgid Id of the message received (probably unused) + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id TaskId of the receiving task. + * @param[in] src_id TaskId of the sending task. + * + * @return KERNEL_MSG_CONSUMED + **************************************************************************************** + */ +int kernel_msg_discard(kernel_msg_id_t const msgid, void const *param, + kernel_task_id_t const dest_id, kernel_task_id_t const src_id); + +/** + **************************************************************************************** + * @brief Generic message handler to consume message without handling it in the task. + * + * @param[in] msgid Id of the message received (probably unused) + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id TaskId of the receiving task. + * @param[in] src_id TaskId of the sending task. + * + * @return KERNEL_MSG_CONSUMED + **************************************************************************************** + */ +int kernel_msg_save(kernel_msg_id_t const msgid, void const *param, + kernel_task_id_t const dest_id, kernel_task_id_t const src_id); + + + +/** + **************************************************************************************** + * @brief This function flushes all messages, currently pending in the kernel for a + * specific task. + * + * @param[in] task The Task Identifier that shall be flushed. + **************************************************************************************** + */ +void kernel_task_msg_flush(kernel_task_id_t task); + + +/** + **************************************************************************************** + * @brief Check validity of a task. If task type or task instance does not exist, + * return invalid task + * + * @param[in] task Task Identifier to check. + * + * @return Task identifier if valid, invalid identifier else. + **************************************************************************************** + */ +kernel_task_id_t kernel_task_check(kernel_task_id_t task); + +/// @} TASK + +#endif // _KERNEL_TASK_H_ + diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/ke/api/kernel_timer.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/ke/api/kernel_timer.h new file mode 100755 index 0000000..e8b648f --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/ke/api/kernel_timer.h @@ -0,0 +1,148 @@ +/** + **************************************************************************************** + * + * @file kernel_timer.h + * + * @brief This file contains the definitions used for timer management + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef _KERNEL_TIMER_H_ +#define _KERNEL_TIMER_H_ + +/** + **************************************************************************************** + * @defgroup TIMER BT Time + * @ingroup KERNEL + * @brief Timer management module. + * + * This module implements the functions used for managing kernel timers. + * + **************************************************************************************** + */ + +#include "rwip.h" // RW definitions +#include "rwip_config.h" // stack configuration +#include "kernel_msg.h" // messaging definition + + +/* + * DEFINITIONS + **************************************************************************************** + */ + + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + +/// Timer Object +struct kernel_timer +{ + /// next ke timer + struct kernel_timer *next; + /// message identifier + kernel_msg_id_t id; + /// task identifier + kernel_task_id_t task; + /// time value + rwip_time_t time; +}; + + +/* + * FUNCTION PROTOTYPES + **************************************************************************************** + */ + + +/** + **************************************************************************************** + * @brief Initialize Kernel timer module. + **************************************************************************************** + */ +void kernel_timer_init(void); + +/** + **************************************************************************************** + * @brief Set a timer. + * + * The function first cancel the timer if it is already existing, then + * it creates a new one. The timer can be one-shot or periodic, i.e. it + * will be automatically set again after each trigger. + * + * When the timer expires, a message is sent to the task provided as + * argument, with the timer id as message id. + * + * The timer is programmed in time units (TU is 1ms). + * + * @param[in] timer_id Timer identifier (message identifier type). + * @param[in] task_id Task identifier which will be notified + * @param[in] delay Delay in time units. + **************************************************************************************** + */ +void kernel_timer_set(kernel_msg_id_t const timer_id, kernel_task_id_t const task, uint32_t delay); + +/** + **************************************************************************************** + * @brief Remove an registered timer. + * + * This function search for the timer identified by its id and its task id. + * If found it is stopped and freed, otherwise an error message is returned. + * + * @param[in] timer_id Timer identifier. + * @param[in] task Task identifier. + **************************************************************************************** + */ +void kernel_timer_clear(kernel_msg_id_t const timerid, kernel_task_id_t const task); + +/** + **************************************************************************************** + * @brief Checks if a requested timer is active. + * + * This function pops the first timer from the timer queue and notifies the appropriate + * task by sending a kernel message. If the timer is periodic, it is set again; + * if it is one-shot, the timer is freed. The function checks also the next timers + * and process them if they have expired or are about to expire. + **************************************************************************************** + */ +bool kernel_timer_active(kernel_msg_id_t const timer_id, kernel_task_id_t const task_id); + +/** + **************************************************************************************** + * @brief Adjust all kernel timers by specified adjustment delay. + * + * This function updates all timers to align to a new SCLK after a system clock adjust. + **************************************************************************************** + */ +void kernel_timer_adjust_all(uint32_t delay); + +/** + **************************************************************************************** + * @brief Compute the authorized sleep time until next kernel timer event + * + * The function takes as argument the current time to compute the sleep time. + * + * if some timer are programmed it return the sleep time between current time and + * first timer expiration. + * + * If there is no timer programmed, function return false meaning that platform should not + * consider the kernel timer to decide the sleep time duration. + * + * @param[in] current_time Current system time + * @param[out] sleep_time Computed sleep duration + * + * @return true sleep time has been computed ; false if there is no programed timer, + meaning that sleep_time is not relevant and can be ignored. + **************************************************************************************** + */ +bool kernel_sleep_time_get(uint32_t current_time, int32_t* sleep_time); + +/// @} TIMER + +#endif // _KERNEL_TIMER_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/ke/src/kernel_env.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/ke/src/kernel_env.h new file mode 100755 index 0000000..c91be0b --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/ke/src/kernel_env.h @@ -0,0 +1,66 @@ +/** + **************************************************************************************** + * + * @file kernel_env.h + * + * @brief This file contains the definition of the kernel. + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef _KERNEL_ENV_H_ +#define _KERNEL_ENV_H_ + +/** + **************************************************************************************** + * @addtogroup ENV Environment + * @ingroup KERNEL + * @brief Kernel Environment + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_config.h" // stack configuration +#include "kernel_event.h" // kernel event +#include "common_list.h" // kernel queue definition + +// forward declaration +struct mblock_free; + +/// Kernel environment definition +struct kernel_env_tag +{ + /// Queue of sent messages but not yet delivered to receiver + struct common_list queue_sent; + /// Queue of messages delivered but not consumed by receiver + struct common_list queue_saved; + /// Queue of timers + struct common_list queue_timer; + + /// Root pointer = pointer to first element of heap linked lists + struct mblock_free * heap[KERNEL_MEM_BLOCK_MAX]; + /// Size of heaps + uint16_t heap_size[KERNEL_MEM_BLOCK_MAX]; + + #if (KERNEL_PROFILING) + /// Size of heap used + uint16_t heap_used[KERNEL_MEM_BLOCK_MAX]; + /// Maximum heap memory used + uint32_t max_heap_used; + #endif //KERNEL_PROFILING +}; + +/// Kernel environment +extern struct kernel_env_tag kernel_env; + +/// @} ENV + +#endif // _KERNEL_ENV_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/ke/src/kernel_queue.h b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/ke/src/kernel_queue.h new file mode 100755 index 0000000..aa40c1d --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_lib/modules/ke/src/kernel_queue.h @@ -0,0 +1,107 @@ +/** + **************************************************************************************** + * + * @file kernel_queue.h + * + * @brief This file contains the definition of the message object, queue element + * object and queue object + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef _KERNEL_QUEUE_H_ +#define _KERNEL_QUEUE_H_ + +/** + **************************************************************************************** + * @addtogroup QUEUE Queues and Lists + * @ingroup KERNEL + * @brief Queue management module + * + * This module implements the functions used for managing message queues. + * These functions must not be called under IRQ! + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include // standard integer +#include // standard boolean +#include "compiler.h" // compiler definitions +#include "common_list.h" // list definition + +/* + * FUNCTION PROTOTYPES + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Pop entry to the queue + * + * @param[in] queue Pointer to the queue. + * @param[in] element Pointer to the element. + **************************************************************************************** + */ +__INLINE void kernel_queue_push(struct common_list *const queue, struct common_list_hdr *const element) +{ + common_list_push_back(queue, element); +} + +/** + **************************************************************************************** + * @brief Pop entry from the queue + * + * @param[in] queue Pointer to the queue. + * + * @return Pointer to the element. + **************************************************************************************** + */ +__INLINE struct common_list_hdr *kernel_queue_pop(struct common_list *const queue) +{ + return common_list_pop_front(queue); +} + +/** + **************************************************************************************** + * @brief Extracts an element matching a given algorithm. + * + * @param[in] queue Pointer to the queue. + * @param[in] func Matching function. + * @param[in] arg Match argument. + * + * @return Pointer to the element found and removed (NULL otherwise). + **************************************************************************************** + */ +struct common_list_hdr *kernel_queue_extract(struct common_list * const queue, + bool (*func)(struct common_list_hdr const * elmt, uint32_t arg), + uint32_t arg); + +/** + **************************************************************************************** + * @brief Insert an element in a sorted queue. + * + * This primitive use a comparison function from the parameter list to select where the + * element must be inserted. + * + * @param[in] queue Pointer to the queue. + * @param[in] element Pointer to the element to insert. + * @param[in] cmp Comparison function (return true if first element has to be inserted + * before the second one). + * + * @return Pointer to the element found and removed (NULL otherwise). + **************************************************************************************** + */ +void kernel_queue_insert(struct common_list * const queue, struct common_list_hdr * const element, + bool (*cmp)(struct common_list_hdr const *elementA, + struct common_list_hdr const *elementB)); + +/// @} QUEUE + +#endif // _KERNEL_QUEUE_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_pub/app/api/app_ble.h b/beken_os/beken378/driver/ble_5_x_rw/ble_pub/app/api/app_ble.h new file mode 100755 index 0000000..d99b865 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_pub/app/api/app_ble.h @@ -0,0 +1,366 @@ +/** + **************************************************************************************** + * + * @file app.h + * + * @brief Application entry point + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef _APP_BLE_H_ +#define _APP_BLE_H_ + +/** + **************************************************************************************** + * @addtogroup APP + * @ingroup RICOW + * + * @brief Application entry point. + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" // SW configuration + +#if (BLE_APP_PRESENT) + +#include // Standard Integer Definition +#include // Common BT Definitions +#include "architect.h" // Platform Definitions +#include "gapc_task.h" // GAPC Definitions +#include "ble_ui.h" + +#if (NVDS_SUPPORT) +#include "nvds.h" +#endif // (NVDS_SUPPORT) + +/* + * DEFINES + **************************************************************************************** + */ + + + +/* + * MACROS + **************************************************************************************** + */ + +#define APP_HANDLERS(subtask) {&subtask##_msg_handler_list[0], ARRAY_LEN(subtask##_msg_handler_list)} + +/* + * ENUMERATIONS + **************************************************************************************** + */ + +#if (NVDS_SUPPORT) +/// List of Application NVDS TAG identifiers +enum app_nvds_tag +{ + /// BD Address + NVDS_TAG_BD_ADDRESS = 0x01, + NVDS_LEN_BD_ADDRESS = 6, + + /// Device Name + NVDS_TAG_DEVICE_NAME = 0x02, + NVDS_LEN_DEVICE_NAME = 62, + + /// BLE Application Advertising data + NVDS_TAG_APP_BLE_ADV_DATA = 0x0B, + NVDS_LEN_APP_BLE_ADV_DATA = 32, + + /// BLE Application Scan response data + NVDS_TAG_APP_BLE_SCAN_RESP_DATA = 0x0C, + NVDS_LEN_APP_BLE_SCAN_RESP_DATA = 32, + + /// Mouse Sample Rate + NVDS_TAG_MOUSE_SAMPLE_RATE = 0x38, + NVDS_LEN_MOUSE_SAMPLE_RATE = 1, + + /// Peripheral Bonded + NVDS_TAG_PERIPH_BONDED = 0x39, + NVDS_LEN_PERIPH_BONDED = 1, + + /// Mouse NTF Cfg + NVDS_TAG_MOUSE_NTF_CFG = 0x3A, + NVDS_LEN_MOUSE_NTF_CFG = 2, + + /// Mouse Timeout value + NVDS_TAG_MOUSE_TIMEOUT = 0x3B, + NVDS_LEN_MOUSE_TIMEOUT = 2, + + /// Peer Device BD Address + NVDS_TAG_PEER_BD_ADDRESS = 0x3C, + NVDS_LEN_PEER_BD_ADDRESS = 7, + + /// Mouse Energy Safe + NVDS_TAG_MOUSE_ENERGY_SAFE = 0x3D, + NVDS_LEN_MOUSE_SAFE_ENERGY = 2, + + /// EDIV (2bytes), RAND NB (8bytes), LTK (16 bytes), Key Size (1 byte) + NVDS_TAG_LTK = 0x3E, + NVDS_LEN_LTK = 28, + + /// PAIRING + NVDS_TAG_PAIRING = 0x3F, + NVDS_LEN_PAIRING = 54, + + /// Audio mode 0 task + NVDS_TAG_AM0_FIRST = 0x90, + NVDS_TAG_AM0_LAST = 0x9F, + + /// Local device Identity resolving key + NVDS_TAG_LOC_IRK = 0xA0, + NVDS_LEN_LOC_IRK = KEY_LEN, + + /// Peer device Resolving identity key (+identity address) + NVDS_TAG_PEER_IRK = 0xA1, + NVDS_LEN_PEER_IRK = sizeof(struct gapc_irk), +}; +#endif // (NVDS_SUPPORT) + +/// Advertising state machine +enum app_adv_state +{ + /// Advertising activity does not exists + APP_ADV_STATE_IDLE = 0, + /// Creating advertising activity + APP_ADV_STATE_CREATING, + /// Setting advertising data + APP_ADV_STATE_SETTING_ADV_DATA, + /// Setting scan response data + APP_ADV_STATE_SETTING_SCAN_RSP_DATA, + /// Updata adv data + APP_ADV_STATE_UPDATA_ADV_DATA, + /// Advertising activity created + APP_ADV_STATE_CREATED, + /// Starting advertising activity + APP_ADV_STATE_STARTING, + /// Advertising activity started + APP_ADV_STATE_STARTED, + /// Stopping advertising activity + APP_ADV_STATE_STOPPING, + /// WAIT Deleteing advertising activity + APP_ADV_STATE_WAITING_DELETE, + + /// Deleteing advertising activity + APP_ADV_STATE_DELETEING, + + APP_ADV_STATE_UPDATA_SCAN_RSP_DATA, + + APP_ADV_STATE_UPDATA2_ADV_DATA, + APP_ADV_STATE_UPDATA2_SCAN_RSP_DATA, +}; + +/// Scaning state machine +enum app_scan_state +{ + /// Scaning activity does not exists + APP_SCAN_STATE_IDLE = 0, + /// Creating Scaning activity + APP_SCAN_STATE_CREATING, + /// Scaning activity created + APP_SCAN_STATE_CREATED, + /// Starting Scaning activity + APP_SCAN_STATE_STARTING, + /// Scaning activity started + APP_SCAN_STATE_STARTED, + /// Stopping Scaning activity + APP_SCAN_STATE_STOPPING, + +}; + +/// Initing state machine +enum app_init_state +{ + /// Iint activity does not exists + APP_INIT_STATE_IDLE = 0, + /// Creating Iint activity + APP_INIT_STATE_CREATING, + /// Iint activity created + APP_INIT_STATE_CREATED, + + /// WAIT Start Iint activity + APP_INIT_STATE_WAIT_CONECTTING, + /// Starting Iint activity + APP_INIT_STATE_CONECTTING, + /// Iint activity conected + APP_INIT_STATE_CONECTED, + /// Stopping Iint activity + APP_INIT_STATE_STOPPING, + +}; + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + +/// Structure containing information about the handlers for an application subtask +struct app_subtask_handlers +{ + /// Pointer to the message handler table + const struct kernel_msg_handler *p_msg_handler_tab; + /// Number of messages handled + uint16_t msg_cnt; +}; + +/// Application environment structure +struct app_env_tag +{ + /// Connection handle + uint16_t conhdl; + /// Connection Index + uint8_t conidx; + + /// Advertising activity index + uint8_t adv_actv_idx; + /// Current advertising state (@see enum app_adv_state) + uint8_t adv_state; + /// Next expected operation completed event + uint8_t adv_op; + + /// Last initialized profile + uint8_t next_svc; + + /// Bonding status + bool bonded; + + /// Device Name length + uint8_t dev_name_len; + /// Device Name + uint8_t dev_name[APP_DEVICE_NAME_MAX_LEN]; + + /// Local device IRK + uint8_t loc_irk[KEY_LEN]; + + /// Secure Connections on current link + bool sec_con_enabled; + + /// Counter used to generate IRK + uint8_t rand_cnt; +#if 1 + /// Scaning activity index + uint8_t scan_actv_idx; + /// Current scaning state (@see enum app_scan_state) + uint8_t scan_state; + /// Next expected operation completed event + uint8_t scan_op; + /// Scan interval + uint16_t scan_intv; + /// Scan window + uint16_t scan_wd; + + /// Init activity index + uint8_t init_actv_idx; + /// Current init state (@see enum app_init_state) + uint8_t init_state; + /// Next expected operation completed event + uint8_t init_op; + /// conn_intv value. Allowed range is 7.5ms to 4s. + uint16_t conn_intv; + /// Slave latency. Number of events that can be missed by a connected slave device + uint16_t conn_latency; + /// Link supervision timeout (in unit of 10ms). Allowed range is 100ms to 32s + uint16_t conn_super_to; + + uint16_t conn_dev_to; + + uint8_t role[BLE_CONNECTION_MAX]; + /// Address information about a device address + struct gap_bdaddr con_dev_addr[BLE_CONNECTION_MAX]; +#endif +}; + +/* + * GLOBAL VARIABLE DECLARATION + **************************************************************************************** + */ + +/// Application environment +extern struct app_env_tag app_ble_ctx; + +extern void set_app_ble_adv_actv_idx(unsigned char idx); +extern int get_app_ble_adv_actv_idx(void); +extern void set_app_ble_conidx(unsigned char idx); +extern int get_app_ble_conidx(void); +extern void set_app_ble_adv_state(int adv_state); +extern int get_app_ble_adv_state(void); +extern void set_app_ble_adv_op(int adv_op); +extern int get_app_ble_adv_op(void);; +extern void ble_app_set_event_cb(ble_event_cb_t func); + + +extern void set_app_ble_scan_state(int scan_state); +extern int get_app_ble_scan_state(void); +extern void set_app_ble_scan_actv_idx(unsigned char idx); +extern int get_app_ble_scan_actv_idx(void); + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Initialize the BLE demo application. + **************************************************************************************** + */ +void appm_init(void); + + +/** + **************************************************************************************** + * @brief + **************************************************************************************** + */ +void appm_adv_fsm_next(char flag); + +/** + **************************************************************************************** + * @brief Send to request to update the connection parameters + **************************************************************************************** + */ +void appm_update_param(struct gapc_conn_param *conn_param); + + + + +/** + **************************************************************************************** + * @brief delete advertising + * + * @param[in] none + **************************************************************************************** + */ + +void appm_delete_advertising(void); +/** + **************************************************************************************** + * @brief Return if the device is currently bonded + **************************************************************************************** + */ +bool app_sec_get_bond_status(void); +extern int get_app_ble_init_actv_idx(void); +extern void set_app_ble_init_state(int init_state); +extern void ble_appm_start_scaning(void); +extern void ble_appm_stop_scaning(void); +extern int ble_appm_updata_scan_rsp_data(unsigned char adv_actv_idx,unsigned char* scan_buff, unsigned char scan_len); +extern void ble_appm_disconnect(uint8_t conidx,uint8_t reason); +extern int ble_appm_set_adv_data(unsigned char adv_actv_idx,unsigned char* adv_buff, unsigned char adv_len); +extern void set_app_ble_init_actv_idx(int init_actv_idx); +/// @} APP + +#endif //(BLE_APP_PRESENT) + +#endif // APP_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_pub/app/api/app_ble_task.h b/beken_os/beken378/driver/ble_5_x_rw/ble_pub/app/api/app_ble_task.h new file mode 100755 index 0000000..dbd7c47 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_pub/app/api/app_ble_task.h @@ -0,0 +1,36 @@ +#ifndef _APP_BLE_TASK_H_ +#define _APP_BLE_TASK_H_ + +#include "rwip_config.h" // SW configuration +#if (BLE_APP_PRESENT) + +#include "app_ble.h" +#include "ble_ui.h" +#include "app_comm.h" // Application Module Definitions +#include "ble_api.h" + +/** + **************************************************************************************** + * @brief Start/stop advertising + * + * @param[in] start True if advertising has to be started, else false + **************************************************************************************** + */ +void appm_update_adv_state(char start); + +/** + **************************************************************************************** + * @brief Send a disconnection request + **************************************************************************************** + */ +void appm_disconnect(unsigned char reason); + +extern void appm_build_adv_data(uint16_t max_length, uint16_t *p_length, uint8_t *p_buf); +extern int appm_update_adv_data( uint8_t* adv_buff, uint8_t adv_len, uint8_t* scan_buff, uint8_t scan_len); +extern ble_err_t appm_stop_advertising(void); +extern ble_err_t appm_start_advertising(void); + +extern void appm_scan_fsm_next(void); + +#endif +#endif diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_pub/app/api/app_comm.h b/beken_os/beken378/driver/ble_5_x_rw/ble_pub/app/api/app_comm.h new file mode 100755 index 0000000..0a18e1e --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_pub/app/api/app_comm.h @@ -0,0 +1,17 @@ +#ifndef APP_COMM_H_ +#define APP_COMM_H_ + +#include "rwip_config.h" // SW configuration + +#if (BLE_APP_COMM) +#include // Standard Integer Definition +#include "ble.h" +#include "ble_pub.h" +#include "ble_api.h" +#include "kernel_task.h" // Kernel Task Definition + +extern const struct app_subtask_handlers app_comm_table_handler; + +#endif + +#endif diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_pub/app/api/app_task.h b/beken_os/beken378/driver/ble_5_x_rw/ble_pub/app/api/app_task.h new file mode 100755 index 0000000..f29dd3c --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_pub/app/api/app_task.h @@ -0,0 +1,120 @@ +/** + **************************************************************************************** + * + * @file app_task.h + * + * @brief Header file - APPTASK. + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef APP_TASK_H_ +#define APP_TASK_H_ + +/** + **************************************************************************************** + * @addtogroup APPTASK Task + * @ingroup APP + * @brief Routes ALL messages to/from APP block. + * + * The APPTASK is the block responsible for bridging the final application with the + * RWBLE software host stack. It communicates with the different modules of the BLE host, + * i.e. @ref SMP, @ref GAP and @ref GATT. + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" // SW configuration + +#if (BLE_APP_PRESENT) + +#include // Standard Integer +#include "rwip_task.h" // Task definitions +#include "kernel_task.h" // Kernel Task +#include "ble_ui.h" + +/* + * DEFINES + **************************************************************************************** + */ + +/// Number of APP Task Instances +#define APP_IDX_MAX (BLE_CONNECTION_MAX) + +/* + * ENUMERATIONS + **************************************************************************************** + */ +enum appc_state +{ + APPC_LINK_IDLE, + + APPC_CREATE_DB = 1, // 1 + + APPC_LINK_CONNECTED, + + APPC_SDP_DISCOVERING, + + APPC_SERVICE_CONNECTED, + /// Number of defined states. + APPC_STATE_MAX + +}; + +enum appm_state +{ + /// Initialization state + APPM_INIT, + /// Database create state + APPM_CREATE_DB, + /// Ready State + APPM_READY, + /// Connected state + APPM_CONNECTED, + + /// Number of defined states. + APPM_STATE_MAX +};; + + +/// APP Task messages +/*@TRACE*/ +enum app_msg_id +{ + APPM_DUMMY_MSG = TASK_BLE_FIRST_MSG(TASK_BLE_ID_APP), + + #if (BLE_APP_HT) + /// Timer used to refresh the temperature measurement value + APP_HT_MEAS_INTV_TIMER, + #endif //(BLE_APP_HT) + + #if (BLE_APP_HID) + /// Timer used to disconnect the moue if no activity is detecter + APP_HID_MOUSE_TIMEOUT_TIMER, + #endif //(BLE_APP_HID) + APP_DEVIATION_CLAC_TIMER, +#if (BLE_CENTRAL) + APP_INIT_CON_DEV_TIMEROUT_TIMER, +#endif +}; + + +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ + +/// @} APPTASK + +#endif //(BLE_APP_PRESENT) + +#endif // APP_TASK_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_pub/app/src/app_ble.c b/beken_os/beken378/driver/ble_5_x_rw/ble_pub/app/src/app_ble.c new file mode 100755 index 0000000..c61dee4 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_pub/app/src/app_ble.c @@ -0,0 +1,621 @@ +/** + **************************************************************************************** + * + * @file app.c + * + * @brief Application entry point + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @addtogroup APP + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "user_config.h" + +#include "rwip_config.h" // SW configuration + +#if (BLE_APP_PRESENT) +#include "rwapp_config.h" +#include + +#include "rwip.h" +#include "app_task.h" // Application task Definition +#include "app_ble.h" // Application Definition +#include "gap.h" // GAP Definition +#include "gapm_task.h" // GAP Manager Task API +#include "gapc_task.h" // GAP Controller Task API +#include "gattc_task.h" + +#include "common_bt.h" // Common BT Definition +#include "common_math.h" // Common Maths Definition + +#if (NVDS_SUPPORT) +#include "nvds.h" // NVDS Definitions +#endif //(NVDS_SUPPORT) +/* + * DEFINES + **************************************************************************************** + */ + +#define DEVICE_NAME "BK DEVICE" + +#define DEVICE_NAME_SIZE sizeof(DEVICE_NAME) + +/* + * LOCAL VARIABLES DEFINITIONS + **************************************************************************************** + */ + +/// Application Task Descriptor +extern const struct kernel_task_desc TASK_BLE_DESC_APP; + +/// Application Environment Structure +struct app_env_tag app_ble_ctx; + +#if CFG_USE_BLE_PS +static uint32_t ble_sleep_enable = 1; +#else +static uint32_t ble_sleep_enable = 0; +#endif + +/* + * LOCAL FUNCTION DEFINITIONS + **************************************************************************************** + */ +void set_app_ble_adv_actv_idx(unsigned char idx) +{ + app_ble_ctx.adv_actv_idx = idx; +} + +int get_app_ble_adv_actv_idx(void) +{ + return app_ble_ctx.adv_actv_idx; +} + +void set_app_ble_conidx(unsigned char idx) +{ + app_ble_ctx.conidx = idx; +} + +int get_app_ble_conidx(void) +{ + return app_ble_ctx.conidx; +} + +void set_app_ble_adv_state(int adv_state) +{ + app_ble_ctx.adv_state = adv_state; + bk_printf("adv_state:%d\r\n",adv_state); +} + +int get_app_ble_adv_state(void) +{ + return app_ble_ctx.adv_state; +} + +void set_app_ble_adv_op(int adv_op) +{ + app_ble_ctx.adv_op = adv_op; +} + +int get_app_ble_adv_op(void) +{ + return app_ble_ctx.adv_op; +} + +void set_app_ble_scan_actv_idx(unsigned char idx) +{ + app_ble_ctx.scan_actv_idx = idx; +} + +int get_app_ble_scan_actv_idx(void) +{ + return app_ble_ctx.scan_actv_idx; +} + +void set_app_ble_scan_state(int scan_state) +{ + app_ble_ctx.scan_state = scan_state; +} + +int get_app_ble_scan_state(void) +{ + return app_ble_ctx.scan_state; +} + +void ble_appm_create_advertising(unsigned char chnl_map,uint32_t intv_min,uint32_t intv_max) +{ + //bk_printf("[%s]\r\n",__func__); + // Prepare the GAPM_ACTIVITY_CREATE_CMD message + struct gapm_activity_create_adv_cmd *p_cmd = KERNEL_MSG_ALLOC(GAPM_ACTIVITY_CREATE_CMD, + TASK_BLE_GAPM, TASK_BLE_APP, + gapm_activity_create_adv_cmd); + + // Set operation code + p_cmd->operation = GAPM_CREATE_ADV_ACTIVITY; + + // Fill the allocated kernel message + p_cmd->own_addr_type = GAPM_STATIC_ADDR; + p_cmd->adv_param.type = GAPM_ADV_TYPE_LEGACY;//GAPM_ADV_TYPE_EXTENDED;//; + p_cmd->adv_param.prop = GAPM_ADV_PROP_UNDIR_CONN_MASK ;//| GAPM_ADV_PROP_SCAN_REQ_NTF_EN_BIT;//GAPM_ADV_PROP_BROADCAST_NON_SCAN_MASK;//GAPM_ADV_PROP_UNDIR_CONN_MASK; + p_cmd->adv_param.filter_pol = ADV_ALLOW_SCAN_ANY_CON_ANY; + p_cmd->adv_param.prim_cfg.chnl_map = chnl_map; + p_cmd->adv_param.prim_cfg.phy = GAP_PHY_LE_1MBPS; + + p_cmd->adv_param.disc_mode = GAPM_ADV_MODE_GEN_DISC; + p_cmd->adv_param.prim_cfg.adv_intv_min = intv_min; + p_cmd->adv_param.prim_cfg.adv_intv_max = intv_max; + set_app_ble_adv_op(GAPM_CREATE_ADV_ACTIVITY); + + // Send the message + kernel_msg_send(p_cmd); +} + +void ble_appm_start_advertising(unsigned char adv_actv_idx,uint16 duration) +{ + bk_printf("[%s]\r\n",__func__); + // Prepare the GAPM_ACTIVITY_START_CMD message + struct gapm_activity_start_cmd *p_cmd = KERNEL_MSG_ALLOC(GAPM_ACTIVITY_START_CMD, + TASK_BLE_GAPM, TASK_BLE_APP, + gapm_activity_start_cmd); + + p_cmd->operation = GAPM_START_ACTIVITY; + p_cmd->actv_idx = adv_actv_idx; + p_cmd->u_param.adv_add_param.duration = duration; + p_cmd->u_param.adv_add_param.max_adv_evt = 0; + + // And the next expected operation code for the command completed event + set_app_ble_adv_op(GAPM_START_ACTIVITY); + + // Send the message + kernel_msg_send(p_cmd); +} + +void ble_appm_stop_advertising(unsigned char adv_actv_idx) +{ + bk_printf("[%s]\r\n",__func__); + // Prepare the GAPM_ACTIVITY_STOP_CMD message + struct gapm_activity_stop_cmd *cmd = KERNEL_MSG_ALLOC(GAPM_ACTIVITY_STOP_CMD, + TASK_BLE_GAPM, TASK_BLE_APP, + gapm_activity_stop_cmd); + + // Fill the allocated kernel message + cmd->operation = GAPM_STOP_ACTIVITY; + cmd->actv_idx = adv_actv_idx; + + // And the next expected operation code for the command completed event + set_app_ble_adv_op(GAPM_STOP_ACTIVITY); + + // Send the message + kernel_msg_send(cmd); +} + +void ble_appm_delete_advertising(unsigned char adv_actv_idx) +{ + // Prepare the GAPM_ACTIVITY_CREATE_CMD message + struct gapm_activity_delete_cmd *p_cmd = KERNEL_MSG_ALLOC(GAPM_ACTIVITY_DELETE_CMD, + TASK_BLE_GAPM, TASK_BLE_APP, + gapm_activity_delete_cmd); + + // Set operation code + p_cmd->operation = GAPM_DELETE_ACTIVITY; + p_cmd->actv_idx = adv_actv_idx; + + // Keep the current operation + // And the next expected operation code for the command completed event + set_app_ble_adv_op(GAPM_DELETE_ACTIVITY); + + // Send the message + kernel_msg_send(p_cmd); +} + +int ble_appm_set_adv_data(unsigned char adv_actv_idx,unsigned char* adv_buff, unsigned char adv_len) +{ + // Remaining Length + uint8_t rem_len = ADV_DATA_LEN - 3;// GAP will use 3 bytes for the AD Type + + if (/*kernel_state_get(TASK_BLE_APP) == APPM_ADVERTISING + &&*/ (adv_len > ADV_DATA_LEN) && (rem_len < adv_len)) + { + return -1; + } + + // Prepare the GAPM_SET_ADV_DATA_CMD message + struct gapm_set_adv_data_cmd *p_cmd = KERNEL_MSG_ALLOC_DYN(GAPM_SET_ADV_DATA_CMD, + TASK_BLE_GAPM, TASK_BLE_APP, + gapm_set_adv_data_cmd, + ADV_DATA_LEN); + + // Fill the allocated kernel message + p_cmd->operation = GAPM_SET_ADV_DATA; + p_cmd->actv_idx = adv_actv_idx; + + p_cmd->length = 0; + ///if(rem_len >= adv_len) + { + // Copy adv data + memcpy(&p_cmd->data[0], adv_buff, adv_len); + // Update advertising data length + p_cmd->length = adv_len; + } + + bk_printf("[%s]set data",__FUNCTION__); + for(int i = 0;i < p_cmd->length;i++) + { + bk_printf(":%02x",p_cmd->data[i]); + }bk_printf("\r\n"); + + // And the next expected operation code for the command completed event + set_app_ble_adv_op(GAPM_SET_ADV_DATA); + // Send the message + kernel_msg_send(p_cmd); + + return 0; +} + +int ble_appm_set_scan_rsp_data(unsigned char adv_actv_idx,unsigned char* scan_buff, unsigned char scan_len) +{ + //bk_printf("[%s]\r\n",__func__); + + if(!(scan_len <= ADV_DATA_LEN)/* || (!(kernel_state_get(TASK_BLE_APP) == APPM_ADVERTISING + ))*/) + { + return -1; + } + + // Prepare the GAPM_SET_ADV_DATA_CMD message + struct gapm_set_adv_data_cmd *p_cmd = KERNEL_MSG_ALLOC_DYN(GAPM_SET_ADV_DATA_CMD, + TASK_BLE_GAPM, TASK_BLE_APP, + gapm_set_adv_data_cmd, + ADV_DATA_LEN); + + // Fill the allocated kernel message + p_cmd->operation = GAPM_SET_SCAN_RSP_DATA; + p_cmd->actv_idx = adv_actv_idx; + + p_cmd->length = scan_len; + memcpy(&p_cmd->data[0], scan_buff, scan_len); + + // And the next expected operation code for the command completed event + set_app_ble_adv_op(GAPM_SET_SCAN_RSP_DATA); + + // Send the message + kernel_msg_send(p_cmd); + + return 0; +} + +int ble_appm_update_adv_data(unsigned char adv_actv_idx,unsigned char* adv_buff, unsigned char adv_len) +{ + // Remaining Length + //uint8_t rem_len = ADV_DATA_LEN - 3;// GAP will use 3 bytes for the AD Type + + if (/*kernel_state_get(TASK_BLE_APP) == APPM_ADVERTISING + &&*/ (adv_len <= ADV_DATA_LEN))// && (rem_len >= adv_len)) + { + //bk_printf("!!!!!!!!!!ble_appm_update_adv_data updata adv data\r\n"); + // Prepare the GAPM_SET_ADV_DATA_CMD message + struct gapm_set_adv_data_cmd *p_cmd = KERNEL_MSG_ALLOC_DYN(GAPM_SET_ADV_DATA_CMD, + TASK_BLE_GAPM, TASK_BLE_APP, + gapm_set_adv_data_cmd, + ADV_DATA_LEN); + + // Fill the allocated kernel message + p_cmd->operation = GAPM_SET_ADV_DATA; + p_cmd->actv_idx = adv_actv_idx; + + p_cmd->length = 0; + + // Check if additional data can be added to the Advertising data - 2 bytes needed for type and length + ///if(rem_len >= adv_len) + { + // Copy adv data + memcpy(&p_cmd->data[0], adv_buff, adv_len); + // Update advertising data length + p_cmd->length = adv_len; + } + + set_app_ble_adv_op(GAPM_SET_ADV_DATA); + + // Send the message + kernel_msg_send(p_cmd); + + return 0; + } + return -1; +} + +int ble_appm_updata_scan_rsp_data(unsigned char adv_actv_idx,unsigned char* scan_buff, unsigned char scan_len) +{ + return ble_appm_set_scan_rsp_data(adv_actv_idx,scan_buff,scan_len); +} + + +static int ble_app_gapm_adv_is_advtype_unique(uint8_t type) +{ + // Advertising type check which shall be unique + switch (type) + { + case GAP_AD_TYPE_MORE_16_BIT_UUID: + case GAP_AD_TYPE_COMPLETE_LIST_16_BIT_UUID: + case GAP_AD_TYPE_MORE_32_BIT_UUID: + case GAP_AD_TYPE_COMPLETE_LIST_32_BIT_UUID: + case GAP_AD_TYPE_MORE_128_BIT_UUID: + case GAP_AD_TYPE_COMPLETE_LIST_128_BIT_UUID: + case GAP_AD_TYPE_SHORTENED_NAME: + case GAP_AD_TYPE_COMPLETE_NAME: + case GAP_AD_TYPE_APPEARANCE: + case GAP_AD_TYPE_ADV_INTV: + case GAP_AD_TYPE_PUB_TGT_ADDR: + case GAP_AD_TYPE_RAND_TGT_ADDR: + case GAP_AD_TYPE_LE_BT_ADDR: + case GAP_AD_TYPE_LE_ROLE: + case GAP_AD_TYPE_FLAGS: + { + return 1; + } + + default: + { + return 0; + } + } +} + +int ble_app_gapm_adv_check_data_sanity(uint16_t length, uint8_t *p_data) +{ + // Returned status + int status = 1; + // Cursor + uint8_t *p_cursor = p_data; + // End of data + uint8_t *p_end_cursor = p_data + length; + // Check for duplicate information in advertising or scan response data. + uint8_t dup_filter[GAP_AD_TYPE_BITFIELD_BYTES]; + + // Clear presence status of unique advertising type + memset(&dup_filter[0], 0, GAP_AD_TYPE_BITFIELD_BYTES); + + // AD type flags must not be set by application + GAP_AD_TYPE_SET_BIT(dup_filter, GAP_AD_TYPE_FLAGS); + + while (p_cursor < p_end_cursor) + { + // Extract AD type + uint8_t ad_type = *(p_cursor + 1); + + // Check if it's AD Type which shall be unique + if (ble_app_gapm_adv_is_advtype_unique(ad_type)) + { + if (!GAP_AD_TYPE_CHECK_BIT(dup_filter, ad_type)) + { + // Mark the advertising type as found + GAP_AD_TYPE_SET_BIT(dup_filter, ad_type); + } + else + { + // Advertising type has been found twice + break; + } + } + + /* Go to next advertising info */ + p_cursor += (*p_cursor + 1); + } + + // Check if total advertising length is valid with advertising data info + if (p_cursor != p_end_cursor) + { + status = 0; + } + + return (status); +} + +void ble_appm_update_param(unsigned char conidx,struct gapc_conn_param *conn_param) +{ + // Prepare the GAPC_PARAM_UPDATE_CMD message + struct gapc_param_update_cmd *cmd = KERNEL_MSG_ALLOC(GAPC_PARAM_UPDATE_CMD, + KERNEL_BUILD_ID(TASK_BLE_GAPC, conidx), TASK_BLE_APP, + gapc_param_update_cmd); + + cmd->operation = GAPC_UPDATE_PARAMS; + cmd->intv_min = conn_param->intv_min; + cmd->intv_max = conn_param->intv_max; + cmd->latency = conn_param->latency; + cmd->time_out = conn_param->time_out; + + // not used by a slave device + cmd->ce_len_min = 0x10; ///0xFFFF + cmd->ce_len_max = 0x20; ///0xFFFF + + // Send the message + kernel_msg_send(cmd); +} + +void ble_appm_disconnect(uint8_t conidx,uint8_t reason) +{ + struct gapc_disconnect_cmd *cmd = KERNEL_MSG_ALLOC(GAPC_DISCONNECT_CMD, + KERNEL_BUILD_ID(TASK_BLE_GAPC, conidx), + KERNEL_BUILD_ID(TASK_BLE_APP, conidx), + gapc_disconnect_cmd); + + cmd->operation = GAPC_DISCONNECT; + cmd->reason = reason; + + // Send the message + kernel_msg_send(cmd); +} + +///////////////////scan +void ble_appm_create_scaning(void) +{ + // Prepare the GAPM_ACTIVITY_CREATE_CMD message + struct gapm_activity_create_cmd *p_cmd = KERNEL_MSG_ALLOC(GAPM_ACTIVITY_CREATE_CMD, + TASK_BLE_GAPM, TASK_BLE_APP, + gapm_activity_create_cmd); + + // Set operation code + p_cmd->operation = GAPM_CREATE_SCAN_ACTIVITY; + + // Fill the allocated kernel message + p_cmd->own_addr_type = GAPM_STATIC_ADDR; + + // Send the message + kernel_msg_send(p_cmd); +} + +void ble_appm_start_scaning(void) +{ + if (app_ble_ctx.scan_state == APP_SCAN_STATE_CREATED) + { + // Prepare the GAPM_ACTIVITY_START_CMD message + struct gapm_activity_start_cmd *p_cmd = KERNEL_MSG_ALLOC(GAPM_ACTIVITY_START_CMD, + TASK_BLE_GAPM, TASK_BLE_APP, + gapm_activity_start_cmd); + + p_cmd->operation = GAPM_START_ACTIVITY; + p_cmd->actv_idx = app_ble_ctx.scan_actv_idx; + + p_cmd->u_param.scan_param.type = GAPM_SCAN_TYPE_OBSERVER;//GAPM_SCAN_TYPE_GEN_DISC;//GAPM_SCAN_TYPE_OBSERVER;//; + + p_cmd->u_param.scan_param.prop = GAPM_SCAN_PROP_PHY_1M_BIT ;//| GAPM_SCAN_PROP_ACTIVE_1M_BIT; + + //p_cmd->u_param.scan_param.scan_param_1m.scan_intv = app_env.scan_intv; + //p_cmd->u_param.scan_param.scan_param_1m.scan_wd = app_env.scan_wd; + + p_cmd->u_param.scan_param.scan_param_1m.scan_intv = 81; //20;//app_env.scan_intv; + p_cmd->u_param.scan_param.scan_param_1m.scan_wd = 32; //10;//app_env.scan_wd; + + p_cmd->u_param.scan_param.dup_filt_pol = 0; + + p_cmd->u_param.scan_param.duration = 0; + + p_cmd->u_param.scan_param.period = 10; + + // Keep the current operation + app_ble_ctx.scan_state = APP_SCAN_STATE_STARTING; + // And the next expected operation code for the command completed event + app_ble_ctx.scan_op = GAPM_START_ACTIVITY; + + // Send the message + kernel_msg_send(p_cmd); + } +} + +void ble_appm_stop_scaning(void) +{ + // Prepare the GAPM_ACTIVITY_STOP_CMD message + struct gapm_activity_stop_cmd *cmd = KERNEL_MSG_ALLOC(GAPM_ACTIVITY_STOP_CMD, + TASK_BLE_GAPM, TASK_BLE_APP, + gapm_activity_stop_cmd); + + // Fill the allocated kernel message + cmd->operation = GAPM_STOP_ACTIVITY; + cmd->actv_idx = app_ble_ctx.scan_actv_idx; + + // Update advertising state + app_ble_ctx.scan_state = APP_SCAN_STATE_STOPPING; + // And the next expected operation code for the command completed event + app_ble_ctx.scan_op = GAPM_STOP_ACTIVITY; + + // Send the message + kernel_msg_send(cmd); +} + +///////////////other +void ble_appm_send_gapm_reset_cmd(void) +{ + // Reset the stack + struct gapm_reset_cmd *p_cmd = KERNEL_MSG_ALLOC(GAPM_RESET_CMD, + TASK_BLE_GAPM, + TASK_BLE_APP, + gapm_reset_cmd); + + p_cmd->operation = GAPM_RESET; + + kernel_msg_send(p_cmd); + + bk_printf("[%s]\r\n",__FUNCTION__); +} + +void ble_appc_gatt_mtu_change(unsigned char conidx) +{ + // Prepare the GAPC_PARAM_UPDATE_CMD message + struct gattc_exc_mtu_cmd *cmd = KERNEL_MSG_ALLOC(GATTC_EXC_MTU_CMD, + KERNEL_BUILD_ID(TASK_BLE_GATTC, conidx), + KERNEL_BUILD_ID(TASK_BLE_APP, conidx), + gattc_exc_mtu_cmd); + + cmd->operation = GATTC_MTU_EXCH; + + // Send the message + kernel_msg_send(cmd); +} + +void __attribute__((weak)) app_ble_task_init(void) +{ + +} + +void appm_init( void ) +{ + // Reset the application manager environment + memset(&app_ble_ctx, 0, sizeof(struct app_env_tag)); + + // Create APP task + kernel_task_create(TASK_BLE_APP, &TASK_BLE_DESC_APP); + + // Initialize Task state + kernel_state_set(TASK_BLE_APP, APPM_INIT); + + /*------------------------------------------------------ + * INITIALIZE ALL MODULES + *------------------------------------------------------*/ + app_ble_task_init(); + + // Reset the stack + ble_appm_send_gapm_reset_cmd(); +} + +void ble_ps_enable_set(void) +{ + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + ble_sleep_enable = 1; + GLOBAL_INT_RESTORE(); +} + +void ble_ps_enable_clear(void) +{ + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + ble_sleep_enable = 0; + GLOBAL_INT_RESTORE(); +} + +UINT32 ble_ps_enabled(void ) +{ + uint32_t value = 0; + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + value = ble_sleep_enable; + GLOBAL_INT_RESTORE(); + return value; +} + +#endif //(BLE_APP_PRESENT) + +/// @} APP diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_pub/app/src/app_ble_task.c b/beken_os/beken378/driver/ble_5_x_rw/ble_pub/app/src/app_ble_task.c new file mode 100755 index 0000000..2774347 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_pub/app/src/app_ble_task.c @@ -0,0 +1,784 @@ +#include "app_ble_task.h" + +#if (BLE_APP_PRESENT) +#include "rw_pub.h" + +#include "ble_rf_port.h" + +#define APP_SCNRSP_DATA "\x09\xFF\x00\x60\x52\x57\x2D\x42\x4C\x45" +#define APP_SCNRSP_DATA_LEN (10) + +adv_info_t adv_info = { + .channel_map = APP_ADV_CHMAP, + .interval_min = APP_ADV_INT_MIN, + .interval_max = APP_ADV_INT_MAX, + .respData = {APP_SCNRSP_DATA}, + .respDataLen = APP_SCNRSP_DATA_LEN, + .advData = {0}, + .advDataLen = 0 +}; + +static ble_event_cb_t ble_app_event_cb = NULL; +void ble_app_set_event_cb(ble_event_cb_t func) +{ + ble_app_event_cb = func; +} + +static void ble_app_event_cb_handler(ble_event_t event, void *param) +{ + ble_event_cb_t func = ble_app_event_cb; + + if(func != NULL) + { + func(event,param); + } +} +/* + * LOCAL FUNCTION DEFINITIONS + **************************************************************************************** + */ +void appm_create_advertising(void) +{ + os_null_printf("[%s]\r\n",__func__); + + if (get_app_ble_adv_state() == APP_ADV_STATE_IDLE) + { + // And the next expected operation code for the command completed event + ble_appm_create_advertising(adv_info.channel_map,adv_info.interval_min,adv_info.interval_max); + // Keep the current operation + set_app_ble_adv_state(APP_ADV_STATE_CREATING); + } +} + +void appm_set_adv_data(void) +{ + int ret; + + // Update advertising state + set_app_ble_adv_state(APP_ADV_STATE_SETTING_ADV_DATA); + ret = ble_appm_set_adv_data(get_app_ble_adv_actv_idx(),adv_info.advData,adv_info.advDataLen); + + os_null_printf("[%s]ret:%d\r\n",__func__,ret); +} + +void appm_set_scan_rsp_data(void) +{ + os_null_printf("[%s]\r\n",__func__); + + // Update advertising state + set_app_ble_adv_state(APP_ADV_STATE_SETTING_SCAN_RSP_DATA); + ble_appm_set_scan_rsp_data(get_app_ble_adv_actv_idx(),adv_info.respData,adv_info.respDataLen); +} + +void appm_start_advertising_cmd(void) +{ + os_null_printf("[%s]\r\n",__func__); + if((get_app_ble_adv_state() == APP_ADV_STATE_CREATED) + || (get_app_ble_adv_state() == APP_ADV_STATE_SETTING_SCAN_RSP_DATA)) + { + // Keep the current operation + set_app_ble_adv_state(APP_ADV_STATE_STARTING); + + ble_appm_start_advertising(get_app_ble_adv_actv_idx(),0); + } +} + +/* 豸㲥*/ +ble_err_t appm_start_advertising(void) +{ + ble_err_t status = ERR_SUCCESS; + /* +#if !(DEEP_SLEEP) + kernel_msg_send_basic(APP_PERIOD_TIMER,TASK_APP,TASK_APP); +#endif + */ + /*if(BLE_ROLE_MASTER == ble_get_role_mode()) + { + bk_printf("current role should not be master\r\n"); + return ERR_ADV_FAIL; + } + */ + // Check if the advertising procedure is already is progress + ///if (kernel_state_get(TASK_APP) == APPM_READY) + if (APP_ADV_STATE_IDLE == get_app_ble_adv_state()) + { + appm_create_advertising(); + /* + bk_printf("appm start advertising\r\n"); + + ble_init_over = 1; + /// mcu_prevent_set(MCU_PS_BLE_FROBID); + ble_set_role_mode(BLE_ROLE_SLAVE); + + // Set the state of the task to APPM_ADVERTISING + kernel_state_set(TASK_APP, APPM_ADVERTISING); + */ + } + else + { + status = ERR_ADV_FAIL; + } + + return status; + // else ignore the request +} + +/* 豸ֹͣ㲥*/ +ble_err_t appm_stop_advertising(void) +{ + ble_err_t status = ERR_SUCCESS; + os_printf("[%s]\r\n",__func__); + + if (APP_ADV_STATE_STARTED == get_app_ble_adv_state()) + { + // Go in ready state + ///kernel_state_set(TASK_APP, APPM_READY); + // Update advertising state + set_app_ble_adv_state(APP_ADV_STATE_STOPPING); + + ble_appm_stop_advertising(get_app_ble_adv_actv_idx()); + + ///ble_set_role_mode(BLE_ROLE_NONE); + ///mcu_prevent_clear(MCU_PS_BLE_FROBID); + } + else if(get_app_ble_adv_state() != APP_ADV_STATE_IDLE ) + { + status = ERR_STOP_ADV_FAIL; + } + + return status; +} + +void appm_delete_advertising(void) +{ + os_null_printf("[%s]\r\n",__func__); + + set_app_ble_adv_state(APP_ADV_STATE_DELETEING); + ble_appm_delete_advertising(get_app_ble_adv_actv_idx()); +} + +/* 豸㲥*/ +void appm_start_direct_dvertising(void) +{ + appm_start_advertising(); + + return; +#if 0 + // Check if the advertising procedure is already is progress + if (kernel_state_get(TASK_APP) == APPM_READY) + { + struct gapm_start_advertise_cmd *cmd = KERNEL_MSG_ALLOC(GAPM_START_ADVERTISE_CMD, + TASK_GAPM, TASK_APP, + gapm_start_advertise_cmd); + + cmd->op.addr_src = GAPM_STATIC_ADDR; + cmd->channel_map = APP_ADV_CHMAP; + + cmd->intv_min = APP_ADV_FAST_INT; + cmd->intv_max = APP_ADV_FAST_INT; + + cmd->op.code = GAPM_ADV_UNDIRECT; + + cmd->info.host.mode = GAP_GEN_DISCOVERABLE; + + /* + * If the peripheral is already bonded with a central device, use the direct advertising + * procedure (BD Address of the peer device is stored in NVDS. + */ + if(app_sec_get_bond_status()) + { + #if (NVDS_SUPPORT) + uint8_t bd_len = NVDS_LEN_PEER_BD_ADDRESS; + #endif + cmd->op.code = GAPM_ADV_DIRECT_LDC; + //cmd->info.direct.addr_type = 1; + + + #if (NVDS_SUPPORT) + if (nvds_get(NVDS_TAG_PEER_BD_ADDRESS, &bd_len, + (uint8_t *)cmd->info.direct.addr.addr) != NVDS_OK) + { + // An error has occurred during access to the NVDS + ASSERT_INFO(0,NVDS_TAG_PEER_BD_ADDRESS,bd_len); + } + #endif + + kernel_msg_send(cmd); + + #if !(DEEP_SLEEP) + kernel_msg_send_basic(APP_PERIOD_TIMER,TASK_APP,TASK_APP); + #endif + + // UART_PRINTF("appm start direct advertising\r\n"); + } + else + { + kernel_msg_free(kernel_param2msg(cmd)); + appm_start_advertising(); + // UART_PRINTF("appm start general advertising\r\n"); + } + + kernel_state_set(TASK_APP, APPM_ADVERTISING); + } +#endif +} + +/*豸ϿӺ*/ +void appm_disconnect(unsigned char reason) +{ + ///if (kernel_state_get(TASK_BLE_APP) == APPM_CONNECTED) + ////if(app_ble_ctx.init_state == APP_INIT_STATE_CONECTED) + { + ble_appm_disconnect(get_app_ble_conidx(),reason);///0x13 + } +} + +///////////////////////////////////////////// +uint8_t appm_updata_adv_data(uint16_t length, uint8_t *p_data) +{ + // Returned status + uint8_t status = GAP_ERR_INVALID_PARAM; + + bk_printf("[%s]\r\n",__func__); + if(!ble_app_gapm_adv_check_data_sanity(length,p_data)) + { + status = GAP_ERR_ADV_DATA_INVALID; + return status; + } + + if((get_app_ble_adv_state() == APP_ADV_STATE_CREATED) + || (get_app_ble_adv_state() == APP_ADV_STATE_STARTED)) + { + // Update advertising state + set_app_ble_adv_state(APP_ADV_STATE_UPDATA_ADV_DATA); + ble_appm_update_adv_data(get_app_ble_adv_actv_idx(),p_data,length); + + status = GAP_ERR_NO_ERROR; + } + else + { + status = GAP_ERR_COMMAND_DISALLOWED; + } + + return status; +} + +uint8_t appm_updata_scan_rsp_data(uint16_t length, uint8_t *p_data) +{ + // Returned status + uint8_t status = GAP_ERR_INVALID_PARAM; + + bk_printf("[%s]\r\n",__func__); + + if((get_app_ble_adv_state() == APP_ADV_STATE_CREATED) + || (get_app_ble_adv_state() == APP_ADV_STATE_STARTED)) + { + // Update advertising state + set_app_ble_adv_state(APP_ADV_STATE_UPDATA_SCAN_RSP_DATA); + + ble_appm_updata_scan_rsp_data(get_app_ble_adv_actv_idx(),p_data,length); + + status = GAP_ERR_NO_ERROR; + } + else + { + status = GAP_ERR_COMMAND_DISALLOWED; + } + + return status; +} + + +int appm_update_adv_data( uint8_t* adv_buff, uint8_t adv_len, uint8_t* scan_buff, uint8_t scan_len) +{ + int advstate = get_app_ble_adv_state(); + int ret; + + if (/*(advstate == APP_ADV_STATE_CREATED) + || */(advstate == APP_ADV_STATE_STARTED)) + { + set_app_ble_adv_state(APP_ADV_STATE_UPDATA2_ADV_DATA); + ret = ble_appm_update_adv_data(get_app_ble_adv_actv_idx(),adv_buff,adv_len); + return ret; + } + + return -1; +} + +void appm_update_adv_scan_handler(void) +{ + set_app_ble_adv_state(APP_ADV_STATE_UPDATA2_SCAN_RSP_DATA); + ble_appm_set_scan_rsp_data(get_app_ble_adv_actv_idx(),adv_info.respData,adv_info.respDataLen); +} + +void appm_update_param(struct gapc_conn_param *conn_param) +{ + ble_appm_update_param(get_app_ble_conidx(),conn_param); +} + + +//////////////////Application /////////////////////////// +void appm_adv_fsm_next(char flag) +{ + bk_printf("[%s] cur adv_state:%x\r\n",__func__,get_app_ble_adv_state()); + switch (get_app_ble_adv_state()) + { + case (APP_ADV_STATE_IDLE): // 0 + { + // Create advertising + appm_create_advertising(); + } + break; + case (APP_ADV_STATE_CREATING)://1 + { + if(flag == 0) + { + // Set advertising data + appm_set_adv_data(); + } + else + { + set_app_ble_adv_state(APP_ADV_STATE_IDLE); + } + } + break; + case (APP_ADV_STATE_SETTING_ADV_DATA): //2 + { + if(flag == 0) + { + // Set scan response data + appm_set_scan_rsp_data(); + } + else + { + appm_delete_advertising(); + } + } + break; + case (APP_ADV_STATE_CREATED)://5 + case (APP_ADV_STATE_SETTING_SCAN_RSP_DATA)://3 + { + if((get_app_ble_adv_state() == APP_ADV_STATE_SETTING_SCAN_RSP_DATA) && (flag == 1)) + { + appm_delete_advertising(); + } + else + { + // Start advertising activity + appm_start_advertising_cmd(); + } + } + break; + case (APP_ADV_STATE_UPDATA_ADV_DATA)://4 + case APP_ADV_STATE_UPDATA_SCAN_RSP_DATA: + case (APP_ADV_STATE_STARTING)://6 + { + if((get_app_ble_adv_state() == APP_ADV_STATE_STARTING) && (flag == 1)) + { + appm_delete_advertising(); + } + else + { + // Go to started state + set_app_ble_adv_state(APP_ADV_STATE_STARTED); + } + } + break; + case (APP_ADV_STATE_STARTED)://7 + { + // Stop advertising activity + appm_stop_advertising(); + } + break; + case (APP_ADV_STATE_STOPPING)://8 + { + // Go delete state + appm_delete_advertising(); + } + break; + case (APP_ADV_STATE_DELETEING):// + set_app_ble_adv_state(APP_ADV_STATE_IDLE); + break; + case APP_ADV_STATE_UPDATA2_ADV_DATA: + if(!(flag & 1)){ + appm_update_adv_scan_handler(); + }else if(flag &0x01){ + set_app_ble_adv_state(APP_ADV_STATE_STARTED); + } + break; + case APP_ADV_STATE_UPDATA2_SCAN_RSP_DATA: + set_app_ble_adv_state(APP_ADV_STATE_STARTED); + break; + default: + ASSERT_ERR(0); + break; + } + + bk_printf("end adv_state:%x\r\n",get_app_ble_adv_state()); +} + +void appm_create_scaning(void) +{ + bk_printf("[%s]\r\n",__func__); + + if (get_app_ble_scan_state() == APP_SCAN_STATE_IDLE) + { + // Keep the current operation + set_app_ble_scan_state(APP_SCAN_STATE_CREATING); + // And the next expected operation code for the command completed event + ble_appm_create_scaning(); + } + else if (get_app_ble_scan_state() == APP_SCAN_STATE_CREATED) + { + appm_scan_fsm_next(); + } +} + +ble_err_t appm_start_scaning(void) +{ + bk_printf("%s\r\n", __FUNCTION__); + ble_err_t status = ERR_SUCCESS; + if ((get_app_ble_scan_state() == APP_SCAN_STATE_IDLE) || (get_app_ble_scan_state() == APP_SCAN_STATE_CREATED)) { + appm_create_scaning(); + } else { + status = ERR_SCAN_FAIL; + } + + return status; +} + +ble_err_t appm_stop_scaning(void) +{ + ble_err_t status = ERR_SUCCESS; + if (get_app_ble_scan_state() == APP_SCAN_STATE_STARTED) { + // Stop scaning activity + ble_appm_stop_scaning(); + } else { + status = ERR_SCAN_FAIL; + } + + return status; +} + +void appm_scan_fsm_next(void) +{ + // return; + switch (get_app_ble_scan_state()) + { + case (APP_SCAN_STATE_IDLE)://0 + { + // Create advertising + appm_create_scaning(); + } break; + + case (APP_SCAN_STATE_CREATING): //1 + case (APP_SCAN_STATE_CREATED): //2 + { + // Start scaning activity + ble_appm_start_scaning(); + } break; + + case (APP_SCAN_STATE_STARTING)://3 + { + // Go to started state + set_app_ble_scan_state(APP_SCAN_STATE_STARTED); + } break; + + case (APP_SCAN_STATE_STARTED)://4 + { + // Stop scaning activity + ble_appm_stop_scaning(); + } break; + + case (APP_SCAN_STATE_STOPPING)://5 + { + // Go created state + set_app_ble_scan_state(APP_SCAN_STATE_CREATED); + } break; + + default: + { + ASSERT_ERR(0); + } break; + } + bk_printf("end scan_state:%x\r\n",get_app_ble_scan_state()); +} + +void appm_update_adv_state(char start) +{ + // TODO [LT] - Check current advertising state + + // Start or stop advertising + appm_adv_fsm_next(0); +} + +static void ble_common_event_callback_handler(void *parama) +{ + struct gapm_cmp_evt *param = (struct gapm_cmp_evt *)parama; + uint8_t cur_adv_state; + + cur_adv_state = get_app_ble_adv_state(); + switch(param->operation) + { + case (GAPM_CREATE_ADV_ACTIVITY)://0xA0 + case (GAPM_SET_ADV_DATA)://0xA9 + case (GAPM_SET_SCAN_RSP_DATA)://0xAA + { + /// Sanity checks + ASSERT(get_app_ble_adv_op() == param->operation);///, get_app_ble_adv_op(), param->operation); + ///ASSERT(param->status == GAP_ERR_NO_ERROR);///, param->status, get_app_ble_adv_op()); + // Perform next operation + + if((param->status == GAP_ERR_NO_ERROR) + ///if ind status is ERROR,recover adv fsm to APP_ADV_STATE_STARTED + || (APP_ADV_STATE_UPDATA_ADV_DATA == cur_adv_state) + || (APP_ADV_STATE_UPDATA_SCAN_RSP_DATA == cur_adv_state) + || (APP_ADV_STATE_UPDATA2_ADV_DATA == cur_adv_state) + || (APP_ADV_STATE_UPDATA2_SCAN_RSP_DATA == cur_adv_state)) + { + appm_adv_fsm_next((param->status == GAP_ERR_NO_ERROR)?0:1); + } + else + { + appm_adv_fsm_next((param->status == GAP_ERR_NO_ERROR)?0:1); + } + + ////Notice APP User updata adv or scan response Data status + if((APP_ADV_STATE_UPDATA_ADV_DATA == cur_adv_state) + || (APP_ADV_STATE_UPDATA_SCAN_RSP_DATA == cur_adv_state) + || (APP_ADV_STATE_UPDATA2_ADV_DATA == cur_adv_state) + || (APP_ADV_STATE_UPDATA2_SCAN_RSP_DATA == cur_adv_state)) + { + ble_event_t event = BLE_EVENT_MAX; + + switch(param->operation) + { + case GAPM_SET_ADV_DATA: + event = BLE_UPDATA_ADV_DATA_IND; + break; + case GAPM_SET_SCAN_RSP_DATA: + event = BLE_UPDATA_SCAN_RSP_IND; + break; + default: + break; + } + + if(event != BLE_EVENT_MAX) + { + ble_app_event_cb_handler(event,¶m->status); + } + } + } + break; + case (GAPM_START_ACTIVITY)://0xA4 + { + if(param->status == GAP_ERR_NO_ERROR) + { + if(get_app_ble_adv_state() == APP_ADV_STATE_STARTING) + { + appm_adv_fsm_next(0); + } + #if (BLE_OBSERVER || BLE_CENTRAL) + if(get_app_ble_scan_state() == APP_SCAN_STATE_STARTING) + { + appm_scan_fsm_next(); + } + #endif + } + else if(get_app_ble_adv_state() == APP_ADV_STATE_STARTING) + { + if(param->status == GAP_ERR_COMMAND_DISALLOWED) + { + appm_adv_fsm_next(0); + } + else + { + appm_adv_fsm_next(1); + } + } + } + break; + case (GAPM_STOP_ACTIVITY)://0xA5 + { + if(param->status == GAP_ERR_NO_ERROR) + { + if(get_app_ble_adv_state() == APP_ADV_STATE_STOPPING) + { + appm_adv_fsm_next(0); + } + #if (BLE_OBSERVER || BLE_CENTRAL) + if(get_app_ble_scan_state() == APP_SCAN_STATE_STOPPING) + { + appm_scan_fsm_next(); + } + #endif + } + }break; + case (GAPM_DELETE_ACTIVITY)://0xA7 + { + if(param->status == GAP_ERR_NO_ERROR) + { + if(get_app_ble_adv_state() == APP_ADV_STATE_DELETEING) + { + appm_adv_fsm_next(0); + } + } + + }break; + #if (BLE_OBSERVER || BLE_CENTRAL) + case (GAPM_CREATE_SCAN_ACTIVITY)://0xA1 + { + #if (BLE_OBSERVER || BLE_CENTRAL) + if(param->status == GAP_ERR_NO_ERROR) + { + appm_scan_fsm_next(); + } + #endif + }break; + #endif + case (GAPM_PROFILE_TASK_ADD)://0x1b + { + + } + break; + case (GAPM_DELETE_ALL_ACTIVITIES) : + { + // Re-Invoke activty + set_app_ble_adv_state(APP_ADV_STATE_IDLE); + #if (BLE_OBSERVER || BLE_CENTRAL ) + set_app_ble_scan_state(APP_SCAN_STATE_IDLE); + #endif + } break; + default: + break; + } +} + +static void ble_activity_stopped_event_callback_handler(void *parama) +{ + struct gapm_activity_stopped_ind *p_param = (struct gapm_activity_stopped_ind *)parama; + + if ((get_app_ble_adv_state() == APP_ADV_STATE_STARTED) + && (p_param->actv_type == GAPM_ACTV_TYPE_ADV)) + { + // Act as if activity had been stopped by the application + set_app_ble_adv_state(APP_ADV_STATE_STOPPING); + + // Perform next operation + appm_adv_fsm_next(0); + } + else if ((get_app_ble_adv_state() == APP_ADV_STATE_WAITING_DELETE) + && (p_param->actv_type == GAPM_ACTV_TYPE_ADV)) + { + // Act as if activity had been stopped by the application + // set_app_ble_adv_state(APP_ADV_STATE_DELETEING); + + // Perform next operation + appm_adv_fsm_next(0); + } + else if((get_app_ble_scan_state() == APP_SCAN_STATE_STARTED) + && (p_param->actv_type == GAPM_ACTV_TYPE_SCAN)) + { + { + // Act as if activity had been stopped by the application + set_app_ble_scan_state(APP_SCAN_STATE_STOPPING); + // Perform next operation + appm_scan_fsm_next(); + } + } + +} + +static void ble_actiove_created_ind_handler(struct ble_activity_created_ind *p_param) +{ + switch(p_param->actv_type) + { + case BLE_ACTV_TYPE_ADV: + if(get_app_ble_adv_state() == APP_ADV_STATE_CREATING){ + // Store the advertising activity index + set_app_ble_adv_actv_idx( p_param->actv_idx ); + bk_printf("adv_actv_idx:%d,tx_pwr:%d\r\n",p_param->actv_idx,p_param->tx_pwr); + } + break; + case BLE_ACTV_TYPE_SCAN: + if((get_app_ble_scan_state() == APP_SCAN_STATE_CREATING)) + { + // Store the scaning activity index + set_app_ble_scan_actv_idx(p_param->actv_idx); + set_app_ble_scan_state(APP_SCAN_STATE_CREATED); + bk_printf("scan_actv_idx:%d,scan_state:%d\r\n",get_app_ble_scan_actv_idx(),get_app_ble_scan_state()); + } + break; + default: + break; + } +} + +static void ble_event_callback_handler(ble_event_t event, void *param) +{ + switch(event) + { + case BLE_ACTIVITY_CREATED_IND: + ble_actiove_created_ind_handler((struct ble_activity_created_ind *)param); + break; + case BLE_COMMON_EVT: + ble_common_event_callback_handler(param); + break; + case BLE_ACTIVITY_STOPPED_IND: + ble_activity_stopped_event_callback_handler(param); + break; + default: + break; + } + ble_app_event_cb_handler(event,param); +} + +void app_ble_task_init(void) +{ + ble_set_event_cb(ble_event_callback_handler); +} + +void appm_build_adv_data(uint16_t max_length, uint16_t *p_length, uint8_t *p_buf) +{ + // Remaining Length + uint8_t rem_len = max_length; + + // Sanity check + ASSERT_ERR(rem_len >= max_length); + + // Get remaining space in the Advertising Data - 2 bytes are used for name length/flag + rem_len -= *p_length; + + // Check if additional data can be added to the Advertising data - 2 bytes needed for type and length + if (rem_len > 2) + { + uint8_t dev_name_length = common_min(app_ble_ctx.dev_name_len, (rem_len - 2)); + + // Device name length + *p_buf = dev_name_length + 1; + // Device name flag (check if device name is complete or not) + *(p_buf + 1) = (dev_name_length == app_ble_ctx.dev_name_len) ? '\x09' : '\x08'; + // Copy device name + memcpy(p_buf + 2, app_ble_ctx.dev_name, dev_name_length); + + // Update advertising data length + *p_length += (dev_name_length + 2); + } +} + + +uint8_t appm_get_app_status(void) +{ + int status = 0; + ////return kernel_state_get(TASK_APP); + if(kernel_state_get(TASK_BLE_APP) == APPM_CONNECTED){ + status = 9; + }else if(get_app_ble_adv_state() == APP_ADV_STATE_STARTED){ + status = 3; + } + ///return get_app_ble_adv_state(); + return status; +} + +#endif + diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_pub/app/src/app_comm.c b/beken_os/beken378/driver/ble_5_x_rw/ble_pub/app/src/app_comm.c new file mode 100755 index 0000000..76a90e8 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_pub/app/src/app_comm.c @@ -0,0 +1,235 @@ +#include "rwip_config.h" // SW configuration + +#if (BLE_APP_COMM) +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include +#include "app_comm.h" // Application Module Definitions +#include "app_ble.h" // Application Definitions +#include "app_task.h" // application task definitions +#include "comm_task.h" // health thermometer functions +#include "common_bt.h" +#include "prf_types.h" // Profile common types definition +#include "architect.h" // Platform Definitions +#include "prf.h" +#include "comm.h" +#include "attm.h" +#include "kernel_timer.h" +#include "ble_ui.h" + +static uint8_t bk_ble_get_prf_by_id(uint16_t id, struct prf_task_env **env) +{ + uint8_t status = PRF_APP_ERROR; + uint32_t i; + for(i = 0; i < BLE_NB_PROFILES ; i++) + { + if(prf_env.prf[i].id == id) + { + *env = &(prf_env.prf[i]); + status = GAP_ERR_NO_ERROR; + break; + } + } + + return status; +} + +ble_err_t bk_ble_create_db (struct bk_ble_db_cfg* ble_db_cfg) +{ + ble_err_t ret = ERR_SUCCESS; + bk_printf("ble create new db\r\n"); + + if (kernel_state_get(TASK_BLE_APP) == APPM_READY) + { + struct bk_ble_db_cfg *db_cfg; + + struct gapm_profile_task_add_cmd *req = KERNEL_MSG_ALLOC_DYN(GAPM_PROFILE_TASK_ADD_CMD, + TASK_BLE_GAPM, TASK_BLE_APP, + gapm_profile_task_add_cmd, sizeof(struct bk_ble_db_cfg)); + // Fill message + req->operation = GAPM_PROFILE_TASK_ADD; + req->sec_lvl = ble_db_cfg->svc_perm; + req->prf_task_id = TASK_BLE_ID_COMMON + ble_db_cfg->prf_task_id; + req->app_task = TASK_BLE_APP; + req->start_hdl = ble_db_cfg->start_hdl; //req->start_hdl = 0; dynamically allocated + + //Set parameters + db_cfg = (struct bk_ble_db_cfg* ) req->param; + memcpy(db_cfg, ble_db_cfg, sizeof(struct bk_ble_db_cfg)); + + kernel_state_set(TASK_BLE_APP, APPM_CREATE_DB); + //Send the message + kernel_msg_send(req); + } + else + { + ret = ERR_CREATE_DB; + } + + return ret; +} + +static int app_comm_msg_dflt_handler(kernel_msg_id_t const msgid, + void const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + // Drop the message + return (KERNEL_MSG_CONSUMED); +} + +ble_err_t bk_ble_conn_enable_prf(uint8_t conidx, uint16_t prf_id) +{ + ble_err_t ret = ERR_SUCCESS; + uint16_t prf_task_id = prf_id + TASK_BLE_ID_COMMON; + struct prf_task_env *prf_env = NULL; + + uint8_t status = bk_ble_get_prf_by_id(prf_task_id, &prf_env); + + if(status == GAP_ERR_NO_ERROR) + { + // Allocate the message + struct bk_ble_enable_req * req = KERNEL_MSG_ALLOC(BK_BLE_ENABLE_REQ, + prf_env->task, + TASK_BLE_APP, + bk_ble_enable_req); + // Fill in the parameter structure + req->conidx = conidx; + req->ind_cfg = 0; + req->ntf_cfg = 0; + + // Send the message + kernel_msg_send(req); + } + else + { + ret = ERR_PROFILE; + } + + return ret; +} + +ble_err_t bk_ble_send_ntf_value(uint32_t len, uint8_t *buf, uint16_t prf_id, uint16_t att_idx) +{ + ble_err_t ret = ERR_SUCCESS; + uint16_t prf_task_id = prf_id + TASK_BLE_ID_COMMON; + struct prf_task_env *prf_env = NULL; + uint8_t status = bk_ble_get_prf_by_id(prf_task_id, &prf_env); + + if(status == GAP_ERR_NO_ERROR) + { + // Allocate the message + struct bk_ble_ntf_upd_req * req = KERNEL_MSG_ALLOC_DYN(BK_BLE_NTF_UPD_REQ, + prf_env->task, + TASK_BLE_APP, + bk_ble_ntf_upd_req,len); + + req->length = len; + memcpy(req->value, buf, len); + req->att_id = att_idx; + req->conidx = 0; + + kernel_msg_send(req); + } + else + { + ret = ERR_PROFILE; + } + + return ret; +} + +ble_err_t bk_ble_send_ind_value(uint32_t len, uint8_t *buf, uint16_t prf_id, uint16_t att_idx) +{ + ble_err_t ret = ERR_SUCCESS; + uint16_t prf_task_id = prf_id + TASK_BLE_ID_COMMON; + struct prf_task_env *prf_env = NULL; + + uint8_t status = bk_ble_get_prf_by_id(prf_task_id, &prf_env); + + if(status == GAP_ERR_NO_ERROR) + { + // Allocate the message + struct bk_ble_ind_upd_req * req = KERNEL_MSG_ALLOC_DYN(BK_BLE_IND_UPD_REQ, + prf_env->task, + TASK_BLE_APP, + bk_ble_ind_upd_req,len); + + req->length = len; + memcpy(req->value, buf, len); + req->att_id = att_idx; + req->conidx = 0; + + kernel_msg_send(req); + } + else + { + ret = ERR_PROFILE; + } + + return ret; +} + +static int bk_ble_write_req_ind_handler(kernel_msg_id_t const msgid, + struct bk_ble_write_ind *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + + write_req_t write_req; + + #if 0 //printf for test write req + uint32_t i; + bk_printf("prf_id:%d, att_idx:%d\r\n", param->prf_id, param->att_id); + + for(i = 0; i < param->length; i++) + { + bk_printf("%x ", (param->value)[i]); + } + bk_printf("\r\n"); + #endif + + write_req.att_idx = param->att_id; + write_req.len = param->length; + write_req.prf_id = param->prf_id; + write_req.value = &(param->value[0]); + + ble_write_cb_handler(&write_req); + + return (KERNEL_MSG_CONSUMED); +} + +static int bk_ble_enable_rsp_handler(kernel_msg_id_t const msgid, + struct bk_ble_enable_rsp const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + return (KERNEL_MSG_CONSUMED); +} + +static int bk_ble_gattc_cmp_evt_handler(kernel_msg_id_t const msgid, struct bk_ble_gattc_cmp_evt const *param, + kernel_task_id_t const dest_id, kernel_task_id_t const src_id) +{ + if(param->operation == GATTC_INDICATE || param->operation == GATTC_NOTIFY) + { + ble_event_cb_handler(BLE_TX_DONE, NULL); + } + return KERNEL_MSG_CONSUMED; +} + +const struct kernel_msg_handler app_comm_msg_handler_list[] = +{ + // Note: first message is latest message checked by kernel so default is put on top. + {KERNEL_MSG_DEFAULT_HANDLER, (kernel_msg_func_t)app_comm_msg_dflt_handler}, + {BK_BLE_WRITE_REQ_IND, (kernel_msg_func_t)bk_ble_write_req_ind_handler}, + {BK_BLE_ENABLE_RSP, (kernel_msg_func_t)bk_ble_enable_rsp_handler}, + {BK_BLE_GATTC_CMP_EVT, (kernel_msg_func_t)bk_ble_gattc_cmp_evt_handler}, +}; + +const struct app_subtask_handlers app_comm_table_handler = + {&app_comm_msg_handler_list[0], (sizeof(app_comm_msg_handler_list)/sizeof(struct kernel_msg_handler))}; + +#endif + diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_pub/app/src/app_task.c b/beken_os/beken378/driver/ble_5_x_rw/ble_pub/app/src/app_task.c new file mode 100755 index 0000000..e36da4f --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_pub/app/src/app_task.c @@ -0,0 +1,1063 @@ +/** + **************************************************************************************** + * + * @file appm_task.c + * + * @brief RW APP Task implementation + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @addtogroup APPTASK + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" // SW configuration + +#if (BLE_APP_PRESENT) + +#include "rwapp_config.h" +#include "app_task.h" // Application Manager Task API +#include "app_ble.h" // Application Manager Definition +#include "gapc_task.h" // GAP Controller Task API +#include "gapm_task.h" // GAP Manager Task API +#include "architect.h" // Platform Definitions +#include +#include "common_utils.h" +#include "kernel_timer.h" // Kernel timer +#include "ble_api.h" + +#if (BLE_APP_COMM) +#include "app_comm.h" +#endif + +#ifdef __func__ +#undef __func__ +#endif +#define __func__ __FUNCTION__ + +/* + * LOCAL FUNCTION DEFINITIONS + **************************************************************************************** + */ + +static uint8_t app_get_handler(const struct app_subtask_handlers *handler_list_desc, + kernel_msg_id_t msgid, + void *param, + kernel_task_id_t src_id) +{ + // Counter + uint8_t counter; + + // Get the message handler function by parsing the message table + for (counter = handler_list_desc->msg_cnt; 0 < counter; counter--) + { + struct kernel_msg_handler handler + = (struct kernel_msg_handler)(*(handler_list_desc->p_msg_handler_tab + counter - 1)); + + if ((handler.id == msgid) || + (handler.id == KERNEL_MSG_DEFAULT_HANDLER)) + { + // If handler is NULL, message should not have been received in this state + BLE_ASSERT_ERR(handler.func); + + return (uint8_t)(handler.func(msgid, param, TASK_BLE_APP, src_id)); + } + } + + // If we are here no handler has been found, drop the message + return (KERNEL_MSG_CONSUMED); +} + +/* + * MESSAGE HANDLERS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Handles GAPM_ACTIVITY_CREATED_IND event + * + * @param[in] msgid Id of the message received. + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance. + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int gapm_activity_created_ind_handler(kernel_msg_id_t const msgid, + struct gapm_activity_created_ind const *p_param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + struct ble_activity_created_ind ind; + + ind.actv_idx = p_param->actv_idx; + switch(p_param->actv_type){ + case GAPM_ACTV_TYPE_ADV: + ind.actv_type = BLE_ACTV_TYPE_ADV; + break; + case GAPM_ACTV_TYPE_SCAN: + ind.actv_type = BLE_ACTV_TYPE_SCAN; + break; + case GAPM_ACTV_TYPE_INIT: + ind.actv_type = BLE_ACTV_TYPE_INIT; + break; + case GAPM_ACTV_TYPE_PER_SYNC: + ind.actv_type = BLE_ACTV_TYPE_PER_SYNC; + break; + default: + ind.actv_type = p_param->actv_type; + break; + } + ind.tx_pwr = p_param->tx_pwr; + + ble_event_cb_handler(BLE_ACTIVITY_CREATED_IND,&ind); + + return (KERNEL_MSG_CONSUMED); +} + +/** + **************************************************************************************** + * @brief Handles GAPM_ACTIVITY_STOPPED_IND event. + * + * @param[in] msgid Id of the message received. + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance. + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int gapm_activity_stopped_ind_handler(kernel_msg_id_t const msgid, + struct gapm_activity_stopped_ind const *p_param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + ble_event_cb_handler(BLE_ACTIVITY_STOPPED_IND,(void*)p_param); + + return (KERNEL_MSG_CONSUMED); +} + +/** + **************************************************************************************** + * @brief Handles GAPM_PROFILE_ADDED_IND event + * + * @param[in] msgid Id of the message received. + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance. + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int gapm_profile_added_ind_handler(kernel_msg_id_t const msgid, + struct gapm_profile_added_ind *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + uint16_t id = param->prf_task_id; + +#if (BLE_SDP_CLIENT) + if((id >= TASK_BLE_ID_SDP) && (id <= TASK_BLE_ID_SDP + BLE_NB_PROFILES) ) + { + id = TASK_BLE_ID_SDP; + } +#endif + +#if (BLE_COMM_SERVER) + if((id >= TASK_BLE_ID_COMMON) && (id <= TASK_BLE_ID_COMMON + BLE_NB_PROFILES)) + { + id = TASK_BLE_ID_COMMON; + } +#endif + + switch (id) + { +#if (BLE_COMM_SERVER) + case TASK_BLE_ID_COMMON: + { + kernel_state_set(TASK_BLE_APP, APPM_READY); + + if(param->status == GAP_ERR_NO_ERROR) + { + ble_event_cb_handler(BLE_CREATE_DB_OK, NULL); + } + else + { + ble_event_cb_handler(BLE_CREATE_DB_FAIL, NULL); + } + } + break; +#endif + +#if (BLE_SDP_CLIENT) + case TASK_BLE_ID_SDP: + { + kernel_state_set(dest_id, APPM_CONNECTED); + uint8_t find; + find = sdp_enable_all_server_ntf_ind(get_app_ble_conidx(),1); + bk_printf("find = %d\r\n",find); + } + break; +#endif +#if BLE_MESH + case TASK_BLE_ID_MESH: + { + kernel_state_set(TASK_BLE_BLE_APP, APPM_READY); + + if(param->status == GAP_ERR_NO_ERROR) + { + if(ble_mesh_event_cb) + { + ble_mesh_event_cb(BLE_MESH_CREATE_DB_OK, NULL); + } + } + else + { + if(ble_mesh_event_cb) + { + ble_mesh_event_cb(BLE_MESH_CREATE_DB_FAIL, NULL); + } + } + } + break; +#endif + default: + { + + } + break; + } + + return KERNEL_MSG_CONSUMED; +} + +/** + **************************************************************************************** + * @brief Handles GAP manager command complete events. + * + * @param[in] msgid Id of the message received. + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (TASK_BLE_GAP). + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int gapm_cmp_evt_handler(kernel_msg_id_t const msgid, + struct gapm_cmp_evt const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + #if (NVDS_SUPPORT) + uint8_t key_len = KEY_LEN; + #endif //(NVDS_SUPPORT) + uint8_t conidx = KERNEL_IDX_GET(dest_id); + bk_printf("[%s] conidx:%d,operation:0x%x,status:0x%x\r\n",__func__,conidx,param->operation,param->status); + switch(param->operation) + { + // Reset completed + case (GAPM_RESET)://0 + { + + if(param->status == GAP_ERR_NO_ERROR) + { + #if (NVDS_SUPPORT) + nvds_tag_len_t len = 6; + #endif //(NVDS_SUPPORT) + + // Set Device configuration + struct gapm_set_dev_config_cmd* cmd = KERNEL_MSG_ALLOC(GAPM_SET_DEV_CONFIG_CMD, + TASK_BLE_GAPM, TASK_BLE_APP, + gapm_set_dev_config_cmd); + // Set the operation + cmd->operation = GAPM_SET_DEV_CONFIG; + // Set the device role - Peripheral / central + cmd->role = GAP_ROLE_ALL;//GAP_ROLE_PERIPHERAL; + + #if (BLE_APP_SEC_CON) + // The Max MTU is increased to support the Public Key exchange + // HOWEVER, with secure connections enabled you cannot sniff the + // LEAP and LEAS protocols + cmd->max_mtu = 160; + cmd->pairing_mode = GAPM_PAIRING_SEC_CON | GAPM_PAIRING_LEGACY; + #else // !(BLE_APP_SEC_CON) + // Do not support secure connections + cmd->pairing_mode = GAPM_PAIRING_LEGACY; + #endif //(BLE_APP_SEC_CON) + + // Set Data length parameters + cmd->sugg_max_tx_octets = LE_MAX_OCTETS;//LE_MIN_OCTETS;//LE_MAX_OCTETS; + cmd->sugg_max_tx_time = LE_MAX_TIME;//LE_MIN_TIME;//LE_MAX_TIME; + + cmd->max_mtu = 256; //527;//ATT_DEFAULT_MTU; + + #if (BLE_APP_HID) + // Enable Slave Preferred Connection Parameters present + cmd->att_cfg = GAPM_MASK_ATT_SLV_PREF_CON_PAR_EN; + #endif //(BLE_APP_HID) + + // Host privacy enabled by default + cmd->privacy_cfg = 0; + + + #if (NVDS_SUPPORT) + if (rwip_param.get(PARAM_ID_BD_ADDRESS, &len, &cmd->addr.addr[0]) == PARAM_OK) + { + // Check if address is a static random address + if (cmd->addr.addr[5] & 0xC0) + { + // Host privacy enabled by default + cmd->privacy_cfg |= GAPM_PRIV_CFG_PRIV_ADDR_BIT; + } + }else + { + memcpy(&cmd->addr.addr[0],&co_default_bdaddr.addr[0],BD_ADDR_LEN); + if (cmd->addr.addr[5] & 0xC0) + { + // Host privacy enabled by default + cmd->privacy_cfg |= GAPM_PRIV_CFG_PRIV_ADDR_BIT; + } + } + #endif //(NVDS_SUPPORT) + bk_printf("cmd->addr.addr[5] :%x\r\n",cmd->addr.addr[5]); + + #if (NVDS_SUPPORT) + if ((app_sec_get_bond_status()==true) && + (nvds_get(NVDS_TAG_LOC_IRK, &key_len, app_ble_ctx.loc_irk) == NVDS_OK)) + { + memcpy(cmd->irk.key, app_ble_ctx.loc_irk, 16); + } + else + #endif //(NVDS_SUPPORT) + { + memset((void *)&cmd->irk.key[0], 0x00, KEY_LEN); + } + // Send message + kernel_msg_send(cmd); + } + else + { + BLE_ASSERT_ERR(0); + } + } + break; + + case (GAPM_GEN_RAND_NB) ://0x1a + { + bk_printf("gapm_cmp_evt:GAPM_GEN_RAND_NB\r\n"); + if (app_ble_ctx.rand_cnt == 1) + { + // Generate a second random number + app_ble_ctx.rand_cnt++; + struct gapm_gen_rand_nb_cmd *cmd = KERNEL_MSG_ALLOC(GAPM_GEN_RAND_NB_CMD, + TASK_BLE_GAPM, TASK_BLE_APP, + gapm_gen_rand_nb_cmd); + cmd->operation = GAPM_GEN_RAND_NB; + kernel_msg_send(cmd); + } + else + { + struct gapm_set_irk_cmd *cmd = KERNEL_MSG_ALLOC(GAPM_SET_IRK_CMD, + TASK_BLE_GAPM, TASK_BLE_APP, + gapm_set_irk_cmd); + app_ble_ctx.rand_cnt=0; + /// - GAPM_SET_IRK + cmd->operation = GAPM_SET_IRK; + memcpy(&cmd->irk.key[0], &app_ble_ctx.loc_irk[0], KEY_LEN); + kernel_msg_send(cmd); + } + } + break; + + case (GAPM_SET_IRK): + { + // BLE_ASSERT_INFO(param->status == GAP_ERR_NO_ERROR, param->operation, param->status); + + #if (BLE_APP_SEC) + // If not Bonded already store the generated value in NVDS + if (app_sec_get_bond_status()==false) + { + #if (NVDS_SUPPORT) + if (nvds_put(NVDS_TAG_LOC_IRK, KEY_LEN, (uint8_t *)&app_ble_ctx.loc_irk) != NVDS_OK) + #endif //(NVDS_SUPPORT) + { + BLE_ASSERT_INFO(0, 0, 0); + } + } + #endif //(BLE_APP_SEC) + app_ble_ctx.rand_cnt = 0; + + // Go to the create db state + kernel_state_set(TASK_BLE_APP, APPM_READY); + bk_printf("gapm_cmp_evt:BLE_STACK_OK\r\n"); + ble_event_cb_handler(BLE_STACK_OK, NULL); + } + break; + + // Device Configuration updated + case (GAPM_SET_DEV_CONFIG): + { + BLE_ASSERT_INFO(param->status == GAP_ERR_NO_ERROR, param->operation, param->status); + bk_printf("gapm_cmp_evt:GAPM_SET_DEV_CONFIG\r\n"); + + #if (BLE_APP_SEC) + if (app_sec_get_bond_status()==true) + { + #if (NVDS_SUPPORT) + // If Bonded retrieve the local IRK from NVDS + if (nvds_get(NVDS_TAG_LOC_IRK, &key_len, app_ble_ctx.loc_irk) == NVDS_OK) + { + // Set the IRK in the GAP + struct gapm_set_irk_cmd *cmd = KERNEL_MSG_ALLOC(GAPM_SET_IRK_CMD, + TASK_BLE_GAPM, TASK_BLE_APP, + gapm_set_irk_cmd); + /// - GAPM_SET_IRK: + cmd->operation = GAPM_SET_IRK; + memcpy(&cmd->irk.key[0], &app_ble_ctx.loc_irk[0], KEY_LEN); + kernel_msg_send(cmd); + bk_printf("gapm_cmp_evt:wait GAPM_SET_IRK\r\n"); + } + else + #endif //(NVDS_SUPPORT) + + { + BLE_ASSERT_ERR(0); + } + } + else // Need to start the generation of new IRK + #endif //(BLE_APP_SEC) + { + struct gapm_gen_rand_nb_cmd *cmd = KERNEL_MSG_ALLOC(GAPM_GEN_RAND_NB_CMD, + TASK_BLE_GAPM, TASK_BLE_APP, + gapm_gen_rand_nb_cmd); + cmd->operation = GAPM_GEN_RAND_NB; + app_ble_ctx.rand_cnt = 1; + kernel_msg_send(cmd); + bk_printf("gapm_cmp_evt:wait GAPM_GEN_RAND_NB\r\n"); + } + + } + break; + +#if (BLE_CENTRAL ) + case (GAPM_CREATE_INIT_ACTIVITY)://0xA2 +#endif +#if (BLE_OBSERVER || BLE_CENTRAL) + case (GAPM_CREATE_SCAN_ACTIVITY)://0xA1 +#endif + case (GAPM_CREATE_ADV_ACTIVITY)://0xA0 + case (GAPM_SET_ADV_DATA)://0xA9 + case (GAPM_SET_SCAN_RSP_DATA)://0xAA + case (GAPM_START_ACTIVITY): + case (GAPM_STOP_ACTIVITY)://0xA5 + case (GAPM_DELETE_ACTIVITY)://0xA7 + case (GAPM_DELETE_ALL_ACTIVITIES) : + { + ble_event_cb_handler(BLE_COMMON_EVT,(void*)param); + } + break; + + default: + { + // Drop the message + } + break; + } + + return (KERNEL_MSG_CONSUMED); +} + +static int gapc_get_dev_info_req_ind_handler(kernel_msg_id_t const msgid, + struct gapc_get_dev_info_req_ind const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + switch(param->req) + { + case GAPC_DEV_NAME: + { + struct gapc_get_dev_info_cfm * cfm = KERNEL_MSG_ALLOC_DYN(GAPC_GET_DEV_INFO_CFM, + src_id, dest_id, + gapc_get_dev_info_cfm, APP_DEVICE_NAME_MAX_LEN); + cfm->req = param->req; + cfm->info.name.length = ble_appm_get_dev_name(cfm->info.name.value); + + // Send message + kernel_msg_send(cfm); + } break; + + case GAPC_DEV_APPEARANCE: + { + // Allocate message + struct gapc_get_dev_info_cfm *cfm = KERNEL_MSG_ALLOC(GAPC_GET_DEV_INFO_CFM, + src_id, dest_id, + gapc_get_dev_info_cfm); + cfm->req = param->req; + // Set the device appearance + #if (BLE_APP_HT) + // Generic Thermometer - TODO: Use a flag + cfm->info.appearance = 728; + #elif (BLE_APP_HID) + // HID Mouse + cfm->info.appearance = 962; + #else + // No appearance + cfm->info.appearance = 0; + #endif + + // Send message + kernel_msg_send(cfm); + } break; + + case GAPC_DEV_SLV_PREF_PARAMS: + { + // Allocate message + struct gapc_get_dev_info_cfm *cfm = KERNEL_MSG_ALLOC(GAPC_GET_DEV_INFO_CFM, + src_id, dest_id, + gapc_get_dev_info_cfm); + cfm->req = param->req; + // Slave preferred Connection interval Min + cfm->info.slv_pref_params.con_intv_min = 8; + // Slave preferred Connection interval Max + cfm->info.slv_pref_params.con_intv_max = 10; + // Slave preferred Connection latency + cfm->info.slv_pref_params.slave_latency = 0; + // Slave preferred Link supervision timeout + cfm->info.slv_pref_params.conn_timeout = 200; // 2s (500*10ms) + + // Send message + kernel_msg_send(cfm); + } break; + + default: /* Do Nothing */ break; + } + + + return (KERNEL_MSG_CONSUMED); +} +/** + **************************************************************************************** + * @brief Handles GAPC_SET_DEV_INFO_REQ_IND message. + * + * @param[in] msgid Id of the message received. + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (TASK_BLE_GAP). + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int gapc_set_dev_info_req_ind_handler(kernel_msg_id_t const msgid, + struct gapc_set_dev_info_req_ind const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + // Set Device configuration + struct gapc_set_dev_info_cfm* cfm = KERNEL_MSG_ALLOC(GAPC_SET_DEV_INFO_CFM, src_id, dest_id, + gapc_set_dev_info_cfm); + // Reject to change parameters + cfm->status = GAP_ERR_REJECTED; + cfm->req = param->req; + // Send message + kernel_msg_send(cfm); + + return (KERNEL_MSG_CONSUMED); +} + +/** + **************************************************************************************** + * @brief Handles connection complete event from the GAP. Enable all required profiles + * + * @param[in] msgid Id of the message received. + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (TASK_BLE_GAP). + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int gapc_connection_req_ind_handler(kernel_msg_id_t const msgid, + struct gapc_connection_req_ind const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + unsigned char conidx = KERNEL_IDX_GET(src_id); + app_ble_ctx.conidx = conidx; + set_app_ble_conidx(conidx); + + // Check if the received Connection Handle was valid + if (get_app_ble_conidx() != GAP_INVALID_CONIDX) + { + // Retrieve the connection info from the parameters + app_ble_ctx.conhdl = param->conhdl; + + app_ble_ctx.conn_intv = param->con_interval; + app_ble_ctx.con_dev_addr[get_app_ble_conidx()].addr_type = param->peer_addr_type; + memcpy(app_ble_ctx.con_dev_addr[get_app_ble_conidx()].addr.addr,param->peer_addr.addr,6); + app_ble_ctx.role[get_app_ble_conidx()] = param->role; + + // Send connection confirmation + struct gapc_connection_cfm *cfm = KERNEL_MSG_ALLOC(GAPC_CONNECTION_CFM, + KERNEL_BUILD_ID(TASK_BLE_GAPC, get_app_ble_conidx()), KERNEL_BUILD_ID(TASK_BLE_APP,get_app_ble_conidx()), + gapc_connection_cfm); + + #if(BLE_APP_SEC) + cfm->auth = app_sec_get_bond_status() ? GAP_AUTH_REQ_NO_MITM_BOND : GAP_AUTH_REQ_NO_MITM_NO_BOND; // TODO [FBE] restore valid data + #else // !(BLE_APP_SEC) + cfm->auth = GAP_AUTH_REQ_NO_MITM_NO_BOND; + #endif // (BLE_APP_SEC) + // Send the message + kernel_msg_send(cfm); + + ///if(param->role == 0) + { + /// sdp_discover_all_service(get_app_ble_conidx()); + } + + // We are now in connected State + ///kernel_state_set(KERNEL_BUILD_ID(TASK_BLE_APP,get_app_ble_conidx()), APPM_CONNECTED); + kernel_state_set(TASK_BLE_APP, APPM_CONNECTED); + ble_event_cb_handler(BLE_CONNECT, (void *)param); + } + else + { + // No connection has been established, restart advertising + // appm_update_adv_state(true); + } + + return (KERNEL_MSG_CONSUMED); +} + +/** + **************************************************************************************** + * @brief Handles connection complete event from the GAP. Enable all required profiles + * + * @param[in] msgid Id of the message received. + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (TASK_BLE_GAP). + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int gapc_param_update_req_ind_handler(kernel_msg_id_t const msgid, + struct gapc_param_update_req_ind const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + app_ble_ctx.conidx = KERNEL_IDX_GET(src_id); + + // Check if the received Connection Handle was valid + if (app_ble_ctx.conidx != GAP_INVALID_CONIDX) + { + + // Send connection confirmation + struct gapc_param_update_cfm *cfm = KERNEL_MSG_ALLOC(GAPC_PARAM_UPDATE_CFM, + KERNEL_BUILD_ID(TASK_BLE_GAPC, app_ble_ctx.conidx), TASK_BLE_APP, + gapc_param_update_cfm); + + cfm->accept = 1;//true; + cfm->ce_len_min = 10; + cfm->ce_len_max = 20; + + // Send message + kernel_msg_send(cfm); + + } + else + { + // No connection has been established, restart advertising + appm_update_adv_state(true); + } + + return (KERNEL_MSG_CONSUMED); +} + +/** + **************************************************************************************** + * @brief GAPC_PARAM_UPDATED_IND + * @param[in] msgid Id of the message received. + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int gapc_param_updated_ind_handler (kernel_msg_id_t const msgid, + const struct gapc_param_updated_ind *param, + kernel_task_id_t const dest_id, kernel_task_id_t const src_id) +{ + app_ble_ctx.conn_intv = param->con_interval; + + return KERNEL_MSG_CONSUMED; +} + +/** + **************************************************************************************** + * @brief Handles GAP controller command complete events. + * + * @param[in] msgid Id of the message received. + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (TASK_BLE_GAP). + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int gapc_cmp_evt_handler(kernel_msg_id_t const msgid, + struct gapc_cmp_evt const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + uint8_t conidx = KERNEL_IDX_GET(dest_id); + bk_printf("%s conidx:%d,operation:0x%x,status:%x\r\n",__func__,conidx,param->operation,param->status); + + switch(param->operation) + { + case (GAPC_UPDATE_PARAMS): + { + if (param->status != GAP_ERR_NO_ERROR) + { + } + } break; + + default: + { + } break; + } + + return (KERNEL_MSG_CONSUMED); +} + +/** + **************************************************************************************** + * @brief Handles disconnection complete event from the GAP. + * + * @param[in] msgid Id of the message received. + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance (TASK_BLE_GAP). + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int gapc_disconnect_ind_handler(kernel_msg_id_t const msgid, + struct gapc_disconnect_ind const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + + uint8_t conidx = KERNEL_IDX_GET(dest_id); + struct ble_disconnect_ind ind; + bk_printf("[%s],reason:0x%x\r\n",__func__,param->reason); + // Go to the ready state + ////kernel_state_set(KERNEL_BUILD_ID(TASK_BLE_APP, conidx), APPM_INIT); + ind.conhdl = param->conhdl; + ind.reason = param->reason; + kernel_state_set(TASK_BLE_APP, APPM_INIT); + ble_event_cb_handler(BLE_DISCONNECT, &ind); + + return (KERNEL_MSG_CONSUMED); + (void)conidx; +} + +/** + **************************************************************************************** + * @brief Handles reception of all messages sent from the lower layers to the application + * @param[in] msgid Id of the message received. + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int appm_msg_handler(kernel_msg_id_t const msgid, + void *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + // Retrieve identifier of the task from received message + kernel_task_id_t src_task_id = BLE_MSG_T(msgid); + // Message policy + uint8_t msg_pol = KERNEL_MSG_CONSUMED; + switch (src_task_id) + { + case (TASK_BLE_ID_GAPC): + { + #if (BLE_APP_SEC) + if ((msgid >= GAPC_BOND_CMD) && + (msgid <= GAPC_SECURITY_IND)) + { + // Call the Security Module + msg_pol = app_get_handler(&app_sec_handlers, msgid, param, src_id); + } + #endif //(BLE_APP_SEC) + // else drop the message + } break; + + case (TASK_BLE_ID_GATTC): + { + // Service Changed - Drop + } break; + +#if (BLE_APP_COMM) + case (TASK_BLE_ID_COMMON): + { + // Call the Health Thermometer Module + msg_pol = app_get_handler(&app_comm_table_handler, msgid, param, src_id); + } break; +#endif //(BLE_APP_COMM) + + default: + { + } break; + } + + return (msg_pol); +} + +/** + **************************************************************************************** + * @brief Handles reception of random number generated message + * + * @param[in] msgid Id of the message received. + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int gapm_gen_rand_nb_ind_handler(kernel_msg_id_t const msgid, struct gapm_gen_rand_nb_ind *param, + kernel_task_id_t const dest_id, kernel_task_id_t const src_id) +{ + if (app_ble_ctx.rand_cnt==1) // First part of IRK + { + memcpy(&app_ble_ctx.loc_irk[0], ¶m->randnb.nb[0], 8); + } + else if (app_ble_ctx.rand_cnt==2) // Second part of IRK + { + memcpy(&app_ble_ctx.loc_irk[8], ¶m->randnb.nb[0], 8); + } + + return KERNEL_MSG_CONSUMED; +} + +#if (SECURE_CONNECTIONS) +static int gapm_gen_dh_key_ind_handler(kernel_msg_id_t const msgid, + struct gapm_gen_dh_key_ind const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + int msg_status = KERNEL_MSG_CONSUMED; + struct ble_gen_dh_key_ind ind; + + ind.result = (uint8_t *)&(param->result[0]); + ind.len = GAP_P256_KEY_LEN; + + ble_event_cb_handler(BLE_GEN_DH_KEY, (void *)&ind); + + return (msg_status); +} + +static int gapm_get_key_ind_handler(kernel_msg_id_t const msgid, + struct gapm_pub_key_ind const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + int msg_status = KERNEL_MSG_CONSUMED; + struct ble_get_key_ind ind; + + ind.pub_key_x = (uint8_t *)&(param->pub_key_x[0]); + ind.pub_x_len = GAP_P256_KEY_LEN; + ind.pub_key_y = (uint8_t *)&(param->pub_key_y[0]); + ind.pub_y_len = GAP_P256_KEY_LEN; + + ble_event_cb_handler(BLE_GET_KEY, (void *)&ind); + + return (msg_status); +} +#endif + +#if (BLE_OBSERVER || BLE_CENTRAL ) + +static int gapm_ext_adv_report_ind_handler(kernel_msg_id_t const msgid, struct gapm_ext_adv_report_ind *param, + kernel_task_id_t const dest_id, kernel_task_id_t const src_id) +{ +#if CFG_DEBUG_EXT_ADV + bk_printf("%s\r\n",__func__); + bk_printf("actv_idx:%x\r\n",param->actv_idx); + bk_printf("info:%x\r\n",param->info); + bk_printf("ch:%d\r\n",param->channel_idx); + bk_printf("rssi:%d\r\n",param->rssi); + bk_printf("addr_type:%x\r\n",param->trans_addr.addr_type); + bk_printf("addr"); + for(int i = 0;i < 6;i++) + { + bk_printf(":%02x",param->trans_addr.addr.addr[i]); + }bk_printf("\r\n"); + + bk_printf("data len:%d\r\n",param->length); + bk_printf("data"); + for(int i = 0;i < param->length;i++) + { + bk_printf(":%02x",param->data[i]); + }bk_printf("\r\n"); + + //appm_adv_data_decode(param->length,param->data,NULL,0); + bk_printf("!!!![%s] recv adv\r\n",__FUNCTION__); +#endif + recv_adv_t adv_param; + + adv_param.evt_type = param->info; + adv_param.data = &(param->data[0]); + adv_param.data_len = param->length; + adv_param.rssi = param->rssi; + adv_param.adv_addr_type = param->trans_addr.addr_type; + memcpy(adv_param.adv_addr, param->trans_addr.addr.addr, GAP_BD_ADDR_LEN); + + ble_recv_adv_cb_handler(&adv_param); + //bk_printf("****************************************\r\n"); + + return KERNEL_MSG_CONSUMED; +} +#endif + +/** + **************************************************************************************** + * @brief GATTC_MTU_CHANGED_IND + * @param[in] msgid Id of the message received. + * @param[in] param Pointer to the parameters of the message. + * @param[in] dest_id ID of the receiving task instance + * @param[in] src_id ID of the sending task instance. + * + * @return If the message was consumed or not. + **************************************************************************************** + */ +static int app_gattc_mtu_changed_ind_handler(kernel_msg_id_t const msgid, + struct gattc_mtu_changed_ind const *ind, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + ble_event_cb_handler(BLE_MTU_CHANGE, (void*)&(ind->mtu)); + + return (KERNEL_MSG_CONSUMED); +} + +static int gattc_cmp_evt_handler(kernel_msg_id_t const msgid, + struct gattc_cmp_evt const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + uint8_t state = kernel_state_get(dest_id); + uint8_t conidx = KERNEL_IDX_GET(src_id); + + bk_printf("app %s dest_id = %x,conidx:%d\r\n",__func__,dest_id,conidx); + bk_printf("operation = 0x%x,status = 0x%x,seq_num = 0x%x\r\n",param->operation,param->status,param->seq_num); + + if(((param->operation == GATTC_WRITE_NO_RESPONSE) || (param->operation == GATTC_WRITE)) && (param->seq_num != 0xa5)) + { + + } + if((param->operation == GATTC_SDP_DISC_SVC_ALL)) + { + ///kernel_state_set(KERNEL_BUILD_ID(TASK_BLE_APP,conidx),APPC_SERVICE_CONNECTED); + bk_printf("\r\nAPPC_SERVICE_CONNECTED\r\n"); + + // sdp_enable_all_server_ntf_ind(conidx,1); + } + + if((param->operation == GATTC_WRITE) && (param->seq_num == 0xaa)) + { + + bk_printf("\r\nGATTC_WRITE\r\n"); + ////sdp_enable_all_server_ntf_ind(conidx,0); + } + if((param->operation == GATTC_MTU_EXCH)) + { + + bk_printf("\r\nGATTC_MTU_EXCH STATUS:0x%x\r\n",param->status); + // sdp_enable_all_server_ntf_ind(conidx,1); + } + + return (KERNEL_MSG_CONSUMED); + (void)state; +} + +int app_deviation_clac_timer_handler(kernel_msg_id_t const msgid, + void const *ind, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + + bk_printf("%s\r\n",__func__); + uint8_t conidx = KERNEL_IDX_GET(dest_id); + + return (KERNEL_MSG_CONSUMED); + (void)conidx; +} + +/* + * GLOBAL VARIABLES DEFINITION + **************************************************************************************** + */ + +/* Default State handlers definition. */ +KERNEL_MSG_HANDLER_TAB(appm) +{ + // Note: first message is latest message checked by kernel so default is put on top. + {KERNEL_MSG_DEFAULT_HANDLER, (kernel_msg_func_t)appm_msg_handler}, + + // GAPM messages + {GAPM_PROFILE_ADDED_IND, (kernel_msg_func_t)gapm_profile_added_ind_handler}, + {GAPM_ACTIVITY_CREATED_IND, (kernel_msg_func_t)gapm_activity_created_ind_handler}, + {GAPM_ACTIVITY_STOPPED_IND, (kernel_msg_func_t)gapm_activity_stopped_ind_handler}, + {GAPM_CMP_EVT, (kernel_msg_func_t)gapm_cmp_evt_handler}, + {GAPM_GEN_RAND_NB_IND, (kernel_msg_func_t)gapm_gen_rand_nb_ind_handler}, + + #if (BLE_OBSERVER || BLE_CENTRAL ) + {GAPM_EXT_ADV_REPORT_IND, (kernel_msg_func_t)gapm_ext_adv_report_ind_handler}, + #endif + + #if (SECURE_CONNECTIONS) + {GAPM_GEN_DH_KEY_IND, (kernel_msg_func_t)gapm_gen_dh_key_ind_handler}, + {GAPM_PUB_KEY_IND, (kernel_msg_func_t)gapm_get_key_ind_handler}, + #endif + + // GAPC messages + {GAPC_GET_DEV_INFO_REQ_IND, (kernel_msg_func_t)gapc_get_dev_info_req_ind_handler}, + {GAPC_SET_DEV_INFO_REQ_IND, (kernel_msg_func_t)gapc_set_dev_info_req_ind_handler}, + {GAPC_CONNECTION_REQ_IND, (kernel_msg_func_t)gapc_connection_req_ind_handler}, + {GAPC_PARAM_UPDATE_REQ_IND, (kernel_msg_func_t)gapc_param_update_req_ind_handler}, + {GAPC_PARAM_UPDATED_IND, (kernel_msg_func_t)gapc_param_updated_ind_handler}, + {GAPC_CMP_EVT, (kernel_msg_func_t)gapc_cmp_evt_handler}, + {GAPC_DISCONNECT_IND, (kernel_msg_func_t)gapc_disconnect_ind_handler}, + {GATTC_MTU_CHANGED_IND, (kernel_msg_func_t)app_gattc_mtu_changed_ind_handler}, + {GATTC_CMP_EVT, (kernel_msg_func_t)gattc_cmp_evt_handler}, +}; + +/* Defines the place holder for the states of all the task instances. */ +kernel_state_t appm_state[APP_IDX_MAX]; + +// Application task descriptor +const struct kernel_task_desc TASK_BLE_DESC_APP = {appm_msg_handler_tab, appm_state, APP_IDX_MAX, ARRAY_LEN(appm_msg_handler_tab)}; + +#endif //(BLE_APP_PRESENT) + +/// @} APPTASK diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_pub/prf/prf.c b/beken_os/beken378/driver/ble_5_x_rw/ble_pub/prf/prf.c new file mode 100755 index 0000000..df70a57 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_pub/prf/prf.c @@ -0,0 +1,447 @@ +/** + **************************************************************************************** + * + * @file prf.c + * + * @brief Entry point of profile source file. + * + * Used to manage life cycle of profiles + * + * Copyright (C) RivieraWaves 2009-2016 + * + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @addtogroup PRF + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" +#include "rwprf_config.h" +#if (BLE_PROFILES) +#include "rwip.h" +#include "prf.h" +#include "att.h" + +#if (BLE_ISO_MODE_0_PROFILE) +extern const struct prf_task_cbs* am0_has_prf_itf_get(void); +#endif // (BLE_ISO_MODE_0_PROFILE) + +#if (BLE_MESH) +extern const struct prf_task_cbs* mal_prf_itf_get(void); +#endif // (BLE_MESH) + +#if (BLE_COMM_SERVER) +extern const struct prf_task_cbs* bk_ble_prf_itf_get(void); +#endif // (BLE_COMM_SERVER) + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + + +/* + * DEFINES + **************************************************************************************** + */ + +/* + * MACROS + **************************************************************************************** + */ + + +/* + * GLOBAL VARIABLE DEFINITIONS + **************************************************************************************** + */ +struct prf_env_tag prf_env; + +/* + * LOCAL FUNCTIONS DEFINITIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Retrieve profile interface + **************************************************************************************** + */ +static const struct prf_task_cbs * prf_itf_get(uint16_t task_id) +{ + const struct prf_task_cbs* prf_cbs = NULL; + //uart_printf("~~~~~~~~~~~~~~~~~~~~~~~task id=%d",KERNEL_TYPE_GET(task_id)); + + uint16_t id = KERNEL_TYPE_GET(task_id); + +#if (BLE_SDP_CLIENT) + if((id >= TASK_BLE_ID_SDP) && (id <= TASK_BLE_ID_SDP + BLE_NB_PROFILES) ) + { + id = TASK_BLE_ID_SDP; + } +#endif + +#if (BLE_COMM_SERVER) + if((id >= TASK_BLE_ID_COMMON) && (id <= TASK_BLE_ID_COMMON + BLE_NB_PROFILES)) + { + id = TASK_BLE_ID_COMMON; + } +#endif + + switch(id) + { + #if (BLE_COMM_SERVER) + case TASK_BLE_ID_COMMON: + prf_cbs = bk_ble_prf_itf_get(); + break; + #endif + + #if (BLE_ISO_MODE_0_PROFILE) + case TASK_BLE_ID_AM0_HAS: + prf_cbs = am0_has_prf_itf_get(); + break; + #endif // (BLE_ISO_MODE_0_PROFILE) + + #if (BLE_MESH) + case TASK_BLE_ID_MESH: + prf_cbs = mal_prf_itf_get(); + break; + #endif //(BLE_MESH) + + default: /* Nothing to do */ break; + } + + return prf_cbs; +} + +/* + * EXPORTED FUNCTIONS DEFINITIONS + **************************************************************************************** + */ +void prf_init(uint8_t init_type) +{ + uint8_t i; + uart_printf("!!!!!!init_type=%x\n",init_type); + for(i = 0; i < BLE_NB_PROFILES ; i++) + { + switch (init_type) + { + case RWIP_INIT: + { + // FW boot profile initialization + prf_env.prf[i].task = TASK_BLE_GAPC + i +1; + kernel_task_create(prf_env.prf[i].task, &(prf_env.prf[i].desc)); + } + break; + + case RWIP_RST: + { + // FW boot profile destruction + // Get Profile API + const struct prf_task_cbs * cbs = prf_itf_get(prf_env.prf[i].id); + + if(cbs != NULL) + { + // request to destroy profile + cbs->destroy(&(prf_env.prf[i])); + } + // Request kernel to flush task messages + kernel_task_msg_flush(KERNEL_TYPE_GET(prf_env.prf[i].task)); + } + // No break + + case RWIP_1ST_RST: + { + // FW boot profile destruction + prf_env.prf[i].env = NULL; + // unregister profile + prf_env.prf[i].id = TASK_BLE_ID_INVALID; + prf_env.prf[i].desc.msg_handler_tab = NULL; + prf_env.prf[i].desc.state = NULL; + prf_env.prf[i].desc.idx_max = 0; + prf_env.prf[i].desc.msg_cnt = 0; + } + break; + + default: + { + // Do nothing + } + break; + } + } +} + + +uint8_t prf_add_profile(struct gapm_profile_task_add_cmd * params, kernel_task_id_t* prf_task) +{ + uint8_t i; + uint8_t status = GAP_ERR_NO_ERROR; + // retrieve profile callback + const struct prf_task_cbs * cbs = prf_itf_get(params->prf_task_id); + if(cbs == NULL) + { + // profile API not available + status = GAP_ERR_INVALID_PARAM; + } + + // check if profile not already present in task list + if(status == GAP_ERR_NO_ERROR) + { + for(i = 0; i < BLE_NB_PROFILES ; i++) + { + if(prf_env.prf[i].id == params->prf_task_id) + { + status = GAP_ERR_NOT_SUPPORTED; + break; + } + } + } + + if(status == GAP_ERR_NO_ERROR) + { + // find first available task + for(i = 0; i < BLE_NB_PROFILES ; i++) + { + // available task found + if(prf_env.prf[i].id == TASK_BLE_ID_INVALID) + { + // initialize profile + status = cbs->init(&(prf_env.prf[i]), &(params->start_hdl), params->app_task, params->sec_lvl, params->param); + + // initialization succeed + if(status == GAP_ERR_NO_ERROR) + { + // register profile + prf_env.prf[i].id = params->prf_task_id; + *prf_task = prf_env.prf[i].task; + } + break; + } + } + + if(i == BLE_NB_PROFILES) + { + status = GAP_ERR_INSUFF_RESOURCES; + } + } + + return (status); +} + + + +void prf_create(uint8_t conidx) +{ + uint8_t i; + /* simple connection creation handler, nothing to do. */ + + // execute create function of each profiles + for(i = 0; i < BLE_NB_PROFILES ; i++) + { + // Get Profile API + const struct prf_task_cbs * cbs = prf_itf_get(prf_env.prf[i].id); + if(cbs != NULL) + { + // call create callback + cbs->create(&(prf_env.prf[i]), conidx); + } + } +} + + +void prf_cleanup(uint8_t conidx, uint8_t reason) +{ + uint8_t i; + /* simple connection creation handler, nothing to do. */ + + // execute create function of each profiles + for(i = 0; i < BLE_NB_PROFILES ; i++) + { + // Get Profile API + const struct prf_task_cbs * cbs = prf_itf_get(prf_env.prf[i].id); + if(cbs != NULL) + { + // call cleanup callback + cbs->cleanup(&(prf_env.prf[i]), conidx, reason); + } + } +} + + +prf_env_t* prf_env_get(uint16_t prf_id) +{ + prf_env_t* env = NULL; + uint8_t i; + // find if profile present in profile tasks + for(i = 0; i < BLE_NB_PROFILES ; i++) + { + // check if profile identifier is known + if(prf_env.prf[i].id == prf_id) + { + env = prf_env.prf[i].env; + break; + } + } + + return env; +} + +kernel_task_id_t prf_src_task_get(prf_env_t* env, uint8_t conidx) +{ + kernel_task_id_t task = PERM_GET(env->prf_task, PRF_TASK); + + if(PERM_GET(env->prf_task, PRF_MI)) + { + task = KERNEL_BUILD_ID(task, conidx); + } + + return task; +} + +kernel_task_id_t prf_dst_task_get(prf_env_t* env, uint8_t conidx) +{ + kernel_task_id_t task = PERM_GET(env->app_task, PRF_TASK); + + if(PERM_GET(env->app_task, PRF_MI)) + { + task = KERNEL_BUILD_ID(task, conidx); + } + + return task; +} + + +kernel_task_id_t prf_get_id_from_task(kernel_msg_id_t task) +{ + kernel_task_id_t id = TASK_BLE_ID_INVALID; + uint8_t idx = KERNEL_IDX_GET(task); + uint8_t i; + task = KERNEL_TYPE_GET(task); + + // find if profile present in profile tasks + for(i = 0; i < BLE_NB_PROFILES ; i++) + { + // check if profile identifier is known + if(prf_env.prf[i].task == task) + { + id = prf_env.prf[i].id; + break; + } + } + + return KERNEL_BUILD_ID(id, idx); +} + +kernel_task_id_t prf_get_task_from_id(kernel_msg_id_t id) +{ + kernel_task_id_t task = TASK_BLE_NONE; + uint8_t idx = KERNEL_IDX_GET(id); + uint8_t i; + id = KERNEL_TYPE_GET(id); + + // find if profile present in profile tasks + for(i = 0; i < BLE_NB_PROFILES ; i++) + { + // check if profile identifier is known + if(prf_env.prf[i].id == id) + { + task = prf_env.prf[i].task; + break; + } + } + + return KERNEL_BUILD_ID(task, idx); +} + +#if 0 +struct prf_env_t * prf_env_get_from_uuid(uint8_t conidx,uint8_t uuid_len,const uint8_t *uuid) +{ + struct sdp_env_tag* sdp_env; + struct prf_env_t* env = NULL; + uint8_t i; + uint8_t j; + + // find if profile present in profile tasks + for(i = 0; i < BLE_NB_PROFILES ; i++) + { + //UART_PRINTF("prf_env.prf[%d].id = 0x%x \r\n",i,prf_env.prf[i].id); + if(prf_env.prf[i].role == PRF_CLIENT) + { + sdp_env = (struct sdp_env_tag *) prf_env.prf[i].env; + if(sdp_env->conidx == conidx) + { + // check if profile identifier is known + for(j = 0;j < sdp_env->prf_db_env->sdp_cont->chars_nb;j++) + { + if(memcmp(sdp_env->prf_db_env->sdp_cont->chars_descs_inf.chars_inf[j].uuid,uuid,uuid_len) == 0) + { + env = (struct prf_env_t*) prf_env.prf[i].env; + sdp_env->prf_db_env->sdp_cont->char_idx = j; + return env; + } + } + } + + } + } + return env; +} +struct prf_env_t * prf_env_get_from_handle(uint8_t conidx,uint16_t handle) +{ + struct sdp_env_tag* sdp_env; + struct prf_env_t* env = NULL; + uint8_t i; + uint8_t j; + + // find if profile present in profile tasks + for(i = 0; i < BLE_NB_PROFILES ; i++) + { + //UART_PRINTF("prf_env.prf[%d].id = 0x%x \r\n",i,prf_env.prf[i].id); + if(prf_env.prf[i].role == PRF_CLIENT) + { + sdp_env = (struct sdp_env_tag *) prf_env.prf[i].env; + if(sdp_env->conidx == conidx) + { + // check if profile identifier is known + for(j = 0;j < sdp_env->prf_db_env->sdp_cont->chars_nb;j++) + { + if((sdp_env->prf_db_env->sdp_cont->chars_descs_inf.chars_inf[j].char_hdl == handle) || (sdp_env->prf_db_env->sdp_cont->chars_descs_inf.chars_inf[j].val_hdl == handle)) + { + env = (struct prf_env_t*) prf_env.prf[i].env; + sdp_env->prf_db_env->sdp_cont->char_idx = j; + return env; + } + } + + // check if profile identifier is known + for(j = 0;j < sdp_env->prf_db_env->sdp_cont->descs_nb;j++) + { + if(sdp_env->prf_db_env->sdp_cont->chars_descs_inf.descs_inf[j].desc_hdl == handle) + { + env = (struct prf_env_t*) prf_env.prf[i].env; + sdp_env->prf_db_env->sdp_cont->char_idx = j; + return env; + } + } + } + + } + } + + return env; + +} +#endif +#endif // (BLE_PROFILES) + +/// @} PRF diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_pub/prf/prf.h b/beken_os/beken378/driver/ble_5_x_rw/ble_pub/prf/prf.h new file mode 100755 index 0000000..75a3540 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_pub/prf/prf.h @@ -0,0 +1,317 @@ +/** + **************************************************************************************** + * + * @file prf.h + * + * @brief Entry point of profile header file. + * + * Used to manage life cycle of profiles + * + * Copyright (C) RivieraWaves 2009-2016 + * + **************************************************************************************** + */ + + +#ifndef _PRF_H_ +#define _PRF_H_ + +/** + **************************************************************************************** + * @addtogroup PROFILE PROFILES + * @ingroup ROOT + * @brief Bluetooth Low Energy Host Profiles + * + * The PROFILE of the stack contains the profile layers (@ref PROX "PROXIMITY", + * @ref HTP "HTP",@ref FIND "FIND ME" @ref BPS "Blood Pressure"). + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @addtogroup PRF + * @ingroup PROFILE + * @brief Definitions of Profile management API + * + * @{ + **************************************************************************************** + */ + + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_config.h" + +#if (BLE_PROFILES) + +#include "kernel_task.h" +#include "gapm_task.h" + +/* + * DEFINES + **************************************************************************************** + */ +enum +{ + PRF_SERVICE = 0, + PRF_CLIENT = 1, +}; + +/** + * Profile task fields + * + * 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + * +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + * | MI | TASK Number | + * +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + * + * Bit [0-14] : Task number value + * Bit [15] : Task is multi-instantiated (Connection index is conveyed) + */ +enum prf_perm_mask +{ + /// Task number value + PERM_MASK_PRF_TASK = 0x7FFF, + PERM_POS_PRF_TASK = 0, + /// Task is multi-instantiated + PERM_MASK_PRF_MI = 0x8000, + PERM_POS_PRF_MI = 15, +}; +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + + +/// Profile Environment Data +typedef struct prf_env +{ + /// Application Task Number - if MSB bit set, Multi-Instantiated task + kernel_task_id_t app_task; + /// Profile Task Number - if MSB bit set, Multi-Instantiated task + kernel_task_id_t prf_task; +} prf_env_t; + + + +/// Profile task environment variable definition to dynamically allocate a Task. +struct prf_task_env +{ + /// Profile Task description + struct kernel_task_desc desc; + /// pointer to the allocated memory used by profile during runtime. + prf_env_t* env; + /// Profile Task Number + kernel_task_id_t task; + /// Profile Task Identifier + kernel_task_id_t id; + + uint8_t role; +}; + +/** + **************************************************************************************** + * @brief Initialization of the Profile module. + * This function performs all the initializations of the Profile module. + * - Creation of database (if it's a service) + * - Allocation of profile required memory + * - Initialization of task descriptor to register application + * - Task State array + * - Number of tasks + * - Default task handler + * + * @param[out] env Collector or Service allocated environment data. + * @param[in|out] start_hdl Service start handle (0 - dynamically allocated), only applies for services. + * @param[in] app_task Application task number. + * @param[in] sec_lvl Security level (AUTH, EKS and MI field of @see enum attm_value_perm_mask) + * @param[in] param Configuration parameters of profile collector or service (32 bits aligned) + * + * @return status code to know if profile initialization succeed or not. + **************************************************************************************** + */ +typedef uint8_t (*prf_init_fnct) (struct prf_task_env* env, uint16_t* start_hdl, uint16_t app_task, uint8_t sec_lvl, void* params); + +/** + **************************************************************************************** + * @brief Destruction of the Profile module - due to a reset for instance. + * This function clean-up allocated memory (attribute database is destroyed by another + * procedure) + * + * @param[in|out] env Collector or Service allocated environment data. + **************************************************************************************** + */ +typedef void (*prf_destroy_fnct) (struct prf_task_env* env); + +/** + **************************************************************************************** + * @brief Handles Connection creation + * + * @param[in|out] env Collector or Service allocated environment data. + * @param[in] conidx Connection index + **************************************************************************************** + */ +typedef void (*prf_create_fnct) (struct prf_task_env* env, uint8_t conidx); + +/** + **************************************************************************************** + * @brief Handles Disconnection + * + * @param[in|out] env Collector or Service allocated environment data. + * @param[in] conidx Connection index + * @param[in] reason Detach reason + **************************************************************************************** + */ +typedef void (*prf_cleanup_fnct) (struct prf_task_env* env, uint8_t conidx, uint8_t reason); + +/// Profile task callbacks. +struct prf_task_cbs +{ + /// Initialization callback + prf_init_fnct init; + /// Destroy profile callback + prf_destroy_fnct destroy; + /// Connection callback + prf_create_fnct create; + /// Disconnection callback + prf_cleanup_fnct cleanup; +}; + + +/// Profile Manager environment structure +struct prf_env_tag +{ + /// Array of profile tasks that can be managed by Profile manager. + struct prf_task_env prf[BLE_NB_PROFILES]; +}; + +/* + * MACROS + **************************************************************************************** + */ + + +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ +extern struct prf_env_tag prf_env; + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Perform Profile initialization + * + * @param[in] init_type Type of initialization (@see enum rwip_init_type) + **************************************************************************************** + */ +void prf_init(uint8_t init_type); + + +/** + **************************************************************************************** + * @brief Create Profile (collector or service) task creation and initialize it. + * + * @param[in|out] params Collector or Service parameter used for profile task creation + * @param[out] prf_task Allocated Task number + * + * @return status of adding profile task + **************************************************************************************** + */ +uint8_t prf_add_profile(struct gapm_profile_task_add_cmd * params, kernel_task_id_t *prf_task); + + +/** + **************************************************************************************** + * @brief Link creation event, update profiles states. + * + * @param[in] conidx connection index + * + **************************************************************************************** + */ +void prf_create(uint8_t conidx); + +/** + **************************************************************************************** + * @brief Link disconnection event, clean-up profiles. + * + * @param[in] conidx connection index + * @param[in] reason detach reason + * + **************************************************************************************** + */ +void prf_cleanup(uint8_t conidx, uint8_t reason); + + + +/** + **************************************************************************************** + * @brief Retrieve environment variable allocated for a profile + * + * @param[in] prf_id Profile Task Identifier + * + * @return Environment variable allocated for a profile + **************************************************************************************** + */ +prf_env_t* prf_env_get(uint16_t prf_id); + + +/** + **************************************************************************************** + * @brief Retrieve source profile task number value + * + * @param[in] env Profile Environment + * @param[in] conidx Connection index + * + * @return Source profile task number value + **************************************************************************************** + */ +kernel_task_id_t prf_src_task_get(prf_env_t* env, uint8_t conidx); + +/** + **************************************************************************************** + * @brief Retrieve destination application task number value + * + * @param[in] env Profile Environment + * @param[in] conidx Connection index + * + * @return Destination application task number value + **************************************************************************************** + */ +kernel_task_id_t prf_dst_task_get(prf_env_t* env, uint8_t conidx); + + +/** + **************************************************************************************** + * @brief Retrieve Task Identifier from Task number + * (automatically update index of task in returned task id) + * + * @param task Task number + * @return Task Identifier + **************************************************************************************** + */ +kernel_task_id_t prf_get_id_from_task(kernel_msg_id_t task); + +/** + **************************************************************************************** + * @brief Retrieve Task Number from Task Identifier + * (automatically update index of task in returned task id) + * + * @param id Task Identifier + * @return Task Number + **************************************************************************************** + */ +kernel_task_id_t prf_get_task_from_id(kernel_msg_id_t id); + +struct prf_env_t * prf_env_get_from_uuid(uint8_t conidx,uint8_t uuid_len,const uint8_t *uuid); +struct prf_env_t * prf_env_get_from_handle(uint8_t conidx,uint16_t handle); +#endif // (BLE_PROFILES) + +/// @} PRF + +#endif /* _PRF_H_ */ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_pub/prf/prf_types.h b/beken_os/beken378/driver/ble_5_x_rw/ble_pub/prf/prf_types.h new file mode 100755 index 0000000..4b5faff --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_pub/prf/prf_types.h @@ -0,0 +1,272 @@ +/** + **************************************************************************************** + * + * @file prf_types.h + * + * @brief Header file - Profile Types + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + + +#ifndef _PRF_TYPES_H_ +#define _PRF_TYPES_H_ + +/** + **************************************************************************************** + * @addtogroup PRF_TYPES + * @ingroup PROFILE + * @brief Definitions of shared profiles types + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "att.h" +#include "compiler.h" + +/* + * DEFINES + **************************************************************************************** + */ + +/// Attribute is mandatory +#define ATT_MANDATORY (0xFF) +/// Attribute is optional +#define ATT_OPTIONAL (0x00) + +/// Characteristic Presentation Format Descriptor Size +#define PRF_CHAR_PRES_FMT_SIZE (7) + + +/// Possible values for setting client configuration characteristics +enum prf_cli_conf +{ + /// Stop notification/indication + PRF_CLI_STOP_NTFIND = 0x0000, + /// Start notification + PRF_CLI_START_NTF, + /// Start indication + PRF_CLI_START_IND, +}; + +/// Possible values for setting server configuration characteristics +enum prf_srv_conf +{ + /// Stop Broadcast + PRF_SRV_STOP_BCST = 0x0000, + /// Start Broadcast + PRF_SRV_START_BCST, +}; + +/// Connection type +enum prf_con_type +{ + ///Discovery type connection + PRF_CON_DISCOVERY = 0x00, + /// Normal type connection + PRF_CON_NORMAL = 0x01, +}; + +enum prf_svc_type +{ + PRF_PRIMARY_SERVICE = 0x00, + PRF_SECONDARY_SERVICE = 0x01 +}; + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + +/** + * Characteristic Presentation Format Descriptor structure + * Packed size is PRF_CHAR_PRES_FMT_SIZE + */ +/// characteristic presentation information +struct prf_char_pres_fmt +{ + /// Unit (The Unit is a UUID) + uint16_t unit; + /// Description + uint16_t description; + /// Format + uint8_t format; + /// Exponent + uint8_t exponent; + /// Name space + uint8_t name_space; +}; + +/** + * date and time structure + * size = 7 bytes + */ +/// Time profile information +struct prf_date_time +{ + /// year time element + uint16_t year; + /// month time element + uint8_t month; + /// day time element + uint8_t day; + /// hour time element + uint8_t hour; + /// minute time element + uint8_t min; + /// second time element + uint8_t sec; +}; + +/** + * SFLOAT: Short Floating Point Type + * + * +----------+----------+---------+ + * | Exponent | Mantissa | Total | + * +------+----------+----------+---------+ + * | size | 4 bits | 12 bits | 16 bits | + * +------+----------+----------+---------+ + */ +typedef uint16_t prf_sfloat; + + + +/// Attribute information +struct prf_att_info +{ + /// Attribute Handle + uint16_t handle; + /// Attribute length + uint16_t length; + /// Status of request + uint8_t status; + /// Attribute value + uint8_t value[__ARRAY_EMPTY]; +}; + + + + +/// service handles +struct prf_svc +{ + /// UUID length + uint8_t uuid_len; + + uint8_t rfu[3]; + /// UUID + uint8_t uuid[ATT_UUID_128_LEN]; + /// start handle + uint16_t shdl; + /// end handle + uint16_t ehdl; +}; + +/// service handles +struct prf_incl_svc +{ + /// attribute handle + uint16_t handle; + /// included service start handle + uint16_t start_hdl; + /// included service end handle + uint16_t end_hdl; + /// UUID length + uint8_t uuid_len; + /// UUID + uint8_t uuid[ATT_UUID_128_LEN]; +}; + +/// characteristic info +struct prf_char_inf +{ + uint8_t uuid_len; + uint8_t uuid[ATT_UUID_128_LEN]; // add by sean 2016.11.15 refer 3431n Master + /// Characteristic handle + uint16_t char_hdl; + /// Value handle + uint16_t val_hdl; + /// Characteristic properties + uint8_t prop; + /// End of characteristic offset + uint8_t char_ehdl_off; +}; + +/// characteristic description +struct prf_char_desc_inf +{ + /// UUID length + uint8_t uuid_len; + /// UUID + uint8_t uuid[ATT_UUID_128_LEN]; // add by sean 2016.11.15 + + uint8_t char_code; + /// Descriptor handle + uint16_t desc_hdl; +}; + + +/// Characteristic definition +struct prf_char_def +{ + /// Characteristic UUID + uint16_t uuid; + /// Requirement Attribute Flag + uint8_t req_flag; + /// Mandatory Properties + uint8_t prop_mand; +}; + +struct prf_char_uuid128_def +{ + /// Service UUID Length + uint8_t uuid_len; + /// 128 bits UUID LSB First + uint8_t uuid[ATT_UUID_128_LEN]; + /// Requirement Attribute Flag + uint8_t req_flag; + /// Mandatory Properties + uint8_t prop_mand; +}; + +/// Characteristic Descriptor definition +struct prf_char_desc_def +{ + /// Characteristic Descriptor uuid + uint16_t uuid; + /// requirement attribute flag + uint8_t req_flag; + /// Corresponding characteristic code + uint8_t char_code; +}; + +/// Message structure used to inform APP that a profile client role has been disabled +struct prf_client_disable_ind +{ + /// Status + uint8_t status; +}; + + + +/// Message structure used to inform APP that an error has occured in the profile server role task +struct prf_server_error_ind +{ + /// Message ID + uint16_t msg_id; + /// Status + uint8_t status; +}; + + +/// @} PRF_TYPES + +#endif /* _PRF_TYPES_H_ */ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_pub/prf/prf_utils.c b/beken_os/beken378/driver/ble_5_x_rw/ble_pub/prf/prf_utils.c new file mode 100755 index 0000000..42404af --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_pub/prf/prf_utils.c @@ -0,0 +1,459 @@ +/** + **************************************************************************************** + * + * @file prf_utils.c + * + * @brief Implementation of Profile Utilities + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + + +/** + **************************************************************************************** + * @addtogroup PRF_UTILS + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_config.h" +#if (BLE_PROFILES) +#if (BLE_SERVER_PRF || BLE_CLIENT_PRF) + +#include +#include +#include "kernel_task.h" +#include "attm.h" +#include "gattc_task.h" +#include "prf_utils.h" +#include "gap.h" +#include "gapc.h" + +#include "kernel_mem.h" +#include "common_utils.h" +#include "common_error.h" + +#endif /* (BLE_SERVER_PRF || BLE_CLIENT_PRF) */ + +/* + * LOCAL FUNCTIONS DEFINITIONS + **************************************************************************************** + */ + +/* + * EXPORTED FUNCTIONS DEFINITIONS + **************************************************************************************** + */ + +#if (BLE_BATT_SERVER) +void prf_pack_char_pres_fmt(uint8_t *packed_val, const struct prf_char_pres_fmt* char_pres_fmt) +{ + *packed_val = char_pres_fmt->format; + *(packed_val + 1) = char_pres_fmt->exponent; + common_write16p(packed_val + 2, char_pres_fmt->unit); + *(packed_val + 4) = char_pres_fmt->name_space; + common_write16p(packed_val + 5, char_pres_fmt->description); +} +#endif // (BLE_BATT_SERVER) + +#if (BLE_BATT_CLIENT) +void prf_unpack_char_pres_fmt(const uint8_t *packed_val, struct prf_char_pres_fmt* char_pres_fmt) +{ + + char_pres_fmt->format = *packed_val; + char_pres_fmt->exponent = *(packed_val + 1); + char_pres_fmt->unit = common_read16p(packed_val + 2); + char_pres_fmt->name_space = *(packed_val + 4); + char_pres_fmt->description = common_read16p(packed_val + 5); +} +#endif // (BLE_BATT_CLIENT) + + +#if (BLE_CLIENT_PRF) +void prf_read_char_send(prf_env_t *prf_env, uint8_t conidx, + uint16_t shdl, uint16_t ehdl, uint16_t valhdl) +{ + struct gattc_read_cmd * req = KERNEL_MSG_ALLOC(GATTC_READ_CMD, KERNEL_BUILD_ID(TASK_BLE_GATTC, conidx), + prf_src_task_get(prf_env, conidx), gattc_read_cmd); + //request type + req->operation = GATTC_READ; + req->nb = 1; + req->req.simple.offset = 0; + req->req.simple.length = 0; + req->req.simple.handle = valhdl; + + //send request to GATT + kernel_msg_send(req); +} + +void prf_register_atthdl2gatt(prf_env_t *prf_env, uint8_t conidx, struct prf_svc *svc) +{ + if(svc->shdl != ATT_INVALID_HANDLE) + { + //register profile task in gatt for indication/notifications + struct gattc_reg_to_peer_evt_cmd * reg = KERNEL_MSG_ALLOC(GATTC_REG_TO_PEER_EVT_CMD, + KERNEL_BUILD_ID(TASK_BLE_GATTC, conidx), prf_src_task_get(prf_env, conidx), + gattc_reg_to_peer_evt_cmd); + + reg->operation = GATTC_REGISTER; + reg->start_hdl = svc->shdl; + reg->end_hdl = svc->ehdl; + + kernel_msg_send(reg); + } +} + +void prf_unregister_atthdl2gatt(prf_env_t *prf_env, uint8_t conidx, struct prf_svc *svc) +{ + if(svc->shdl != ATT_INVALID_HANDLE) + { + //un register profile task in gatt for indication/notifications + struct gattc_reg_to_peer_evt_cmd * reg = KERNEL_MSG_ALLOC(GATTC_REG_TO_PEER_EVT_CMD, + KERNEL_BUILD_ID(TASK_BLE_GATTC, conidx), prf_src_task_get(prf_env, conidx), + gattc_reg_to_peer_evt_cmd); + + reg->operation = GATTC_UNREGISTER; + reg->start_hdl = svc->shdl; + reg->end_hdl = svc->ehdl; + + kernel_msg_send(reg); + } +} + + +void prf_disc_svc_send(prf_env_t *prf_env, uint8_t conidx, uint16_t uuid) +{ + //send GATT discover primary services by UUID request + struct gattc_sdp_svc_disc_cmd * svc_req = KERNEL_MSG_ALLOC_DYN(GATTC_SDP_SVC_DISC_CMD, + KERNEL_BUILD_ID(TASK_BLE_GATTC, conidx), prf_src_task_get(prf_env, conidx), + gattc_sdp_svc_disc_cmd, ATT_UUID_16_LEN); + + //gatt request type: by UUID + svc_req->operation = GATTC_SDP_DISC_SVC; + //start handle; + svc_req->start_hdl = ATT_1ST_REQ_START_HDL; + //end handle + svc_req->end_hdl = ATT_1ST_REQ_END_HDL; + + // UUID search + svc_req->uuid_len = ATT_UUID_16_LEN; + + //set the first two bytes to the value array, LSB to MSB:Health Thermometer Service UUID first + common_write16p(&(svc_req->uuid[0]), uuid); + + //send the message to GATT, which will send back the response when it gets it + kernel_msg_send(svc_req); +} +void prf_disc_svc_send_uuid128(prf_env_t *prf_env, uint8_t conidx, uint8_t* uuid ) +{ + //send GATT discover primary services by UUID request + struct gattc_sdp_svc_disc_cmd * svc_req = KERNEL_MSG_ALLOC_DYN(GATTC_SDP_SVC_DISC_CMD, + KERNEL_BUILD_ID(TASK_BLE_GATTC, conidx), prf_src_task_get(prf_env, conidx), + gattc_sdp_svc_disc_cmd, ATT_UUID_128_LEN); + + //gatt request type: by UUID + svc_req->operation = GATTC_SDP_DISC_SVC; + //start handle; + svc_req->start_hdl = ATT_1ST_REQ_START_HDL; + //end handle + svc_req->end_hdl = ATT_1ST_REQ_END_HDL; + + // UUID search + svc_req->uuid_len = ATT_UUID_128_LEN; + + //set the first two bytes to the value array, LSB to MSB:Health Thermometer Service UUID first + memcpy(&(svc_req->uuid[0]), uuid,ATT_UUID_128_LEN); + + //send the message to GATT, which will send back the response when it gets it + kernel_msg_send(svc_req); +} + + + +void prf_gatt_write(prf_env_t *prf_env, uint8_t conidx, + uint16_t handle, uint8_t* value, uint16_t length, uint8_t operation)//,uint8_t seq_num) +{ + if(handle != ATT_INVALID_HANDLE) + { + struct gattc_write_cmd *wr_char = KERNEL_MSG_ALLOC_DYN(GATTC_WRITE_CMD, + KERNEL_BUILD_ID(TASK_BLE_GATTC, conidx), prf_src_task_get(prf_env, conidx), + gattc_write_cmd, length); + + // Offset + wr_char->offset = 0x0000; + // cursor always 0 + wr_char->cursor = 0x0000; + // Write Type + wr_char->operation = operation; + // Characteristic Value attribute handle + wr_char->handle = handle; + // Value Length + wr_char->length = length; + //wr_char->seq_num = seq_num; + // Auto Execute + wr_char->auto_execute = true; + // Value + memcpy(&wr_char->value[0], value, length); + + // Send the message + kernel_msg_send(wr_char); + } +} + +void prf_gatt_write_ntf_ind(prf_env_t *prf_env, uint8_t conidx, uint16_t handle, uint16_t ntf_ind_cfg)//,uint8_t seq_num) +{ + uint8_t value[2]; + + // put value in air format + common_write16p((&value[0]), ntf_ind_cfg); + // write value over GATT + prf_gatt_write(prf_env, conidx, handle, value, 2, GATTC_WRITE); +} + +uint8_t prf_check_svc_char_validity(uint8_t nb_chars, + const struct prf_char_inf* chars, + const struct prf_char_def* chars_req) +{ + uint8_t status = GAP_ERR_NO_ERROR; + uint8_t i; + + for(i = 0; ((i < nb_chars) && (status == GAP_ERR_NO_ERROR)); i++) + { + if (chars[i].char_hdl == ATT_INVALID_HANDLE) + { + //If Characteristic is not present, check requirements + if (chars_req[i].req_flag == ATT_MANDATORY) + { + status = PRF_ERR_STOP_DISC_CHAR_MISSING; + } + } + else + { + //If Characteristic is present, check properties + if((chars[i].prop & chars_req[i].prop_mand) != chars_req[i].prop_mand) + { + status = PRF_ERR_STOP_DISC_WRONG_CHAR_PROP; + } + } + } + + return (status); +} + + +uint8_t prf_check_svc_char_desc_validity(uint8_t descs_size, + const struct prf_char_desc_inf* descs, + const struct prf_char_desc_def* descs_req, + const struct prf_char_inf* chars) +{ + uint8_t status = GAP_ERR_NO_ERROR; + uint8_t i; + + for(i = 0; ((i < descs_size) && (status == GAP_ERR_NO_ERROR)) ; i++) + { + if (descs[i].desc_hdl == ATT_INVALID_HANDLE) + { + //If Descriptor is missing, check if it is mandatory + if (descs_req[i].req_flag == ATT_MANDATORY) + { + //Check if Char is present + if (chars[descs_req[i].char_code].char_hdl != ATT_INVALID_HANDLE) + { + //Char. is present and descriptor not, error + status = PRF_ERR_STOP_DISC_CHAR_MISSING; + } + } + } + } + + return (status); +} + +void prf_extract_svc_info(const struct gattc_sdp_svc_ind* param, + uint8_t nb_chars, const struct prf_char_def* chars_req, struct prf_char_inf* chars, + uint8_t nb_descs, const struct prf_char_desc_def* descs_req, struct prf_char_desc_inf* descs) +{ + //Counters + uint8_t svc_char; + uint8_t svc_desc; + uint8_t fnd_att; + + for (fnd_att=0; fnd_att< (param->end_hdl - param->start_hdl); fnd_att++) + { + if(param->info[fnd_att].att_type == GATTC_SDP_ATT_CHAR) + { + uint16_t char_hdl = param->start_hdl+ 1 + fnd_att; + uint16_t val_hdl = param->info[fnd_att].att_char.handle; + uint8_t val_prop = param->info[fnd_att].att_char.prop; + uint8_t char_idx = fnd_att; + + // check that value handle is in a valid range + if((val_hdl <= param->end_hdl) && (val_hdl > (param->start_hdl + fnd_att))) + { + // retrieve value index + uint8_t val_idx = (val_hdl - param->start_hdl - 1); + + //Look over requested characteristics + for (svc_char=0; svc_charinfo[val_idx].att.uuid, + param->info[val_idx].att.uuid_len, chars_req[svc_char].uuid)) + { + //Save properties and handles + chars[svc_char].char_hdl = char_hdl; + chars[svc_char].val_hdl = val_hdl; + chars[svc_char].prop = val_prop; + + // find end of characteristic handle and discover descriptors + do + { + fnd_att++; + + // found a descriptor + if(param->info[fnd_att].att_type == GATTC_SDP_ATT_DESC) + { + //Retrieve characteristic descriptor handle using UUID + for(svc_desc = 0; svc_descinfo[fnd_att].att.uuid, + param->info[fnd_att].att.uuid_len, descs_req[svc_desc].uuid))) + { + descs[svc_desc].desc_hdl = param->start_hdl + 1 + fnd_att; + // search for next descriptor + break; + } + } + } + } while(((param->start_hdl+ 1 + fnd_att) <= param->end_hdl) + && (param->info[fnd_att].att_type != GATTC_SDP_ATT_CHAR) + && (param->info[fnd_att].att_type != GATTC_SDP_INC_SVC)); + + // return to previous valid value + fnd_att--; + // previous handle was end of the characteristic + chars[svc_char].char_ehdl_off = fnd_att - char_idx; + + // search next characteristic + break; + } + } + } + } + } +} + + +#endif //(BLE_CLIENT_PRF) + +#if (BLE_CLIENT_PRF || BLE_TIP_SERVER || BLE_AN_SERVER || BLE_PAS_SERVER) + +void prf_client_att_info_rsp(prf_env_t *prf_env, uint8_t conidx, uint16_t msg_id, + uint8_t status, struct gattc_read_ind const* read_ind) +{ + // retrieve value length + uint16_t length = 0; + if(status == GAP_ERR_NO_ERROR) + { + length = read_ind->length; + } + + // prepare response + struct prf_att_info *rsp = KERNEL_MSG_ALLOC_DYN(msg_id, + prf_dst_task_get(prf_env, conidx), prf_src_task_get(prf_env, conidx), + prf_att_info, length); + + rsp->status = status; + rsp->handle = ATT_INVALID_HDL; + rsp->length = length; + + // set value array + if (read_ind != NULL) + { + rsp->handle = read_ind->handle; + memcpy(&(rsp->value[0]), &(read_ind->value[0]), length); + } + + kernel_msg_send(rsp); +} +#endif //(BLE_CLIENT_PRF || BLE_TIP_SERVER || BLE_AN_SERVER || BLE_PAS_SERVER) + + +#if ((BLE_SERVER_PRF || BLE_CLIENT_PRF)) + +uint8_t prf_pack_date_time(uint8_t *packed_date, const struct prf_date_time* date_time) +{ + common_write16p(packed_date, date_time->year); + *(packed_date + 2) = date_time->month; + *(packed_date + 3) = date_time->day; + *(packed_date + 4) = date_time->hour; + *(packed_date + 5) = date_time->min; + *(packed_date + 6) = date_time->sec; + + return 7; +} +uint8_t prf_unpack_date_time(uint8_t *packed_date, struct prf_date_time* date_time) +{ + date_time->year = common_read16p(&(packed_date[0])); + date_time->month = packed_date[2]; + date_time->day = packed_date[3]; + date_time->hour = packed_date[4]; + date_time->min = packed_date[5]; + date_time->sec = packed_date[6]; + + return 7; +} + +#if ((BLE_CGM_SERVER || BLE_CGM_CLIENT)) +uint16_t prf_e2e_crc(const uint8_t * buf, uint16_t length) +{ + uint16_t crc_reg = 0xffff; // initial seed + uint8_t reg; + uint16_t crc; + int i, j; + + for(i=0; i < length; i++) + { + reg = *buf++; + for(j=0; j<8; j++) + { + if ((reg & 1) != ((crc_reg>>15)& 1)) + { + crc_reg <<= 1; + crc_reg ^= (uint16_t)(1<<12) | (1<<5) | (1<<0); + } + else + { + crc_reg <<= 1; + } + reg >>= 1; + } + } + + crc = 0; + // result is in the order bits:->8 9 10 11 12 13 14 15 0 1 2 3 4 5 6 7 + for(j=0; j<8; j++) + { + crc >>= 1; + crc |= crc_reg & ((1<<15) | (1<<7)); + crc_reg <<= 1; + } + return crc; +} +#endif /* ((BLE_CGM_SERVER || BLE_CGM_CLIENT)) */ + +#endif /* ((BLE_SERVER_PRF || BLE_CLIENT_PRF)) */ +#endif // (BLE_PROFILES) +/// @} PRF_UTILS + diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_pub/prf/prf_utils.h b/beken_os/beken378/driver/ble_5_x_rw/ble_pub/prf/prf_utils.h new file mode 100755 index 0000000..facd55d --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_pub/prf/prf_utils.h @@ -0,0 +1,313 @@ +/** + **************************************************************************************** + * + * @file prf_utils.h + * + * @brief Header file - Profile Utilities + * + * Copyright (C) RivieraWaves 2009-2016 + * + * + **************************************************************************************** + */ + + +#ifndef _PRF_UTILS_H_ +#define _PRF_UTILS_H_ + +/** + **************************************************************************************** + * @addtogroup PRF_UTILS + * @ingroup PROFILE + * + * @brief Definitions of shared profiles functions that can be used by several profiles + * + * @{ + **************************************************************************************** + */ + + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" +#if (BLE_SERVER_PRF || BLE_CLIENT_PRF) +#include "kernel_msg.h" +#include "prf_types.h" +#include "gattc_task.h" +#include "gapc.h" +#include "gapc_task.h" +#include "attm.h" +#include "prf.h" +#endif /* (BLE_SERVER_PRF || BLE_CLIENT_PRF) */ + +/* + * MACROS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Macro used to called the prf_client_get_env function. + * + * @param prf_id Profile Task ID (In Upper case, ex: HTPC, DISC, ...) + * @param type Profile task type (In lower case, ex: htpc, disc, ...) + **************************************************************************************** + */ +#define PRF_ENV_GET(prf_id, type) \ + ((struct type ## _env_tag *)prf_env_get((TASK_BLE_ID_##prf_id))) + + + +// 16 bits attributes in a 128 bits array +#define ATT_16_TO_128_ARRAY(uuid) { (uuid) & 0xFF, (uuid >> 8) & 0xFF, 0,0,0,0,0,0,0,0,0,0,0,0,0,0 } +// +#define ATT_128_PRIMARY_SERVICE ATT_16_TO_128_ARRAY(ATT_DECL_PRIMARY_SERVICE) +#define ATT_128_CHARACTERISTIC ATT_16_TO_128_ARRAY(ATT_DECL_CHARACTERISTIC) +#define ATT_128_CLIENT_CHAR_CFG ATT_16_TO_128_ARRAY(ATT_DESC_CLIENT_CHAR_CFG) + + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +#if (BLE_BATT_SERVER) +/** + **************************************************************************************** + * @brief Pack Characteristic Presentation Format descriptor value + **************************************************************************************** + */ +void prf_pack_char_pres_fmt(uint8_t *packed_val, const struct prf_char_pres_fmt* char_pres_fmt); +#endif // (BLE_BATT_SERVER) + +#if (BLE_BATT_CLIENT) +/** + **************************************************************************************** + * @brief Unpack Characteristic Presentation Format descriptor value + **************************************************************************************** + */ +void prf_unpack_char_pres_fmt(const uint8_t *packed_val, struct prf_char_pres_fmt* char_pres_fmt); +#endif // (BLE_BATT_CLIENT) + +#if (BLE_CLIENT_PRF) +/** + **************************************************************************************** + * @brief Request peer device to read an attribute + * + * @param[in] prf_env Pointer to profile information + * + * @param conidx Connection index + * @param shdl Search Start Handle + * @param ehdl Search End Handle + * + * @param valhdl Value Handle + * + * @note: if attribute is invalid, nothing is registered + **************************************************************************************** + */ +void prf_read_char_send(prf_env_t *prf_env, uint8_t conidx, + uint16_t shdl, uint16_t ehdl, uint16_t valhdl); + + +/** + **************************************************************************************** + * @brief register attribute handle in GATT + * + * @param[in] prf_env Pointer to profile information + * + * @param conidx Connection index + * @param svc Service to register + * + * @note: if attribute is invalid, nothing is registered + **************************************************************************************** + */ +void prf_register_atthdl2gatt(prf_env_t *prf_env, uint8_t conidx, struct prf_svc *svc); + +/** + **************************************************************************************** + * @brief Unregister attribute handle in GATT + * + * @param[in] prf_env Pointer to profile information + * + * @param conidx Connection index + * @param svc Service to register + * + * @note: if attribute is invalid, nothing is registered + **************************************************************************************** + */ +void prf_unregister_atthdl2gatt(prf_env_t *prf_env, uint8_t conidx, struct prf_svc *svc); + +/** + **************************************************************************************** + * @brief Request service discovery on peer device. + * + * This request will be used to retrieve start and end handles of the service. + * + * @param[in] prf_env Pointer to profile information + * + * @param conidx Connection index + * @param uuid Service UUID + **************************************************************************************** + */ +void prf_disc_svc_send(prf_env_t *prf_env,uint8_t conidx, uint16_t uuid); + +void prf_disc_svc_send_uuid128(prf_env_t *prf_env, uint8_t conidx, uint8_t* uuid ); + +/** + **************************************************************************************** + * @brief Write peer characteristic using GATT. + * + * It will request write modification of peer handle + * + * @param[in] prf_env Pointer to profile information + * @param[in] conidx Connection index + * @param[in] handle Peer handle to modify + * @param[in] value New Peer handle value + * @param[in] length Value length + **************************************************************************************** + */ +void prf_gatt_write(prf_env_t *prf_env, uint8_t conidx, + uint16_t handle, uint8_t* value, uint16_t length, uint8_t operation); + +/** + **************************************************************************************** + * @brief Modify peer client configuration descriptor using GATT + * + * It will request write modification of peer client configuration descriptor handle + * + * @param[in] prf_env Pointer to profile information + * + * @param[in] conidx Connection index + * @param[in] handle Peer client configuration descriptor handle to modify + * + * @param[in] ntf_ind_cfg Indication/Notification configuration + **************************************************************************************** + */ +void prf_gatt_write_ntf_ind(prf_env_t *prf_env, uint8_t conidx, + uint16_t handle, uint16_t ntf_ind_cfg); + +/** + **************************************************************************************** + * @brief Check service characteristic validity + * + * For each characteristic in service it verifies handles. + * + * If some handles are not present, it checks if they shall be present or they are optional. + * + * @param nb_chars Number of Characteristics in the service + * @param chars Characteristics values (char handles, val handles, properties) + * @param chars_req Characteristics requirements. + * + * @return 0x1 if service is valid, 0x00 else. + **************************************************************************************** + */ +uint8_t prf_check_svc_char_validity(uint8_t nb_chars, + const struct prf_char_inf* chars, + const struct prf_char_def* chars_req); + +/** + **************************************************************************************** + * @brief Check service characteristic descriptors validity + * + * For each characteristic descriptors in service it verifies handles. + * + * If some handles are not present, according to characteristic properties it verify if + * descriptor is optional or not. + * + * @param descs_size Number of Characteristic descriptors in the service + * @param descs Characteristic descriptors values (handles) + * @param descs_req Characteristics descriptors requirements. + * + * @return 0x1 if service is valid, 0x00 else. + **************************************************************************************** + */ +uint8_t prf_check_svc_char_desc_validity(uint8_t descs_size, + const struct prf_char_desc_inf* descs, + const struct prf_char_desc_def* descs_req, + const struct prf_char_inf* chars); + +/** + **************************************************************************************** + * @brief Extract information of the service according to the service description + * + * @param param Service information + * @param nb_chars Length of provided arrays (chars and chars_req) + * @param chars_req Characteristics requirements + * @param chars Characteristics + * @param nb_descs Length of provided arrays (descs and descs_req) + * @param descs_req Descriptors requirements + * @param descs Descriptors + **************************************************************************************** + */ +void prf_extract_svc_info(const struct gattc_sdp_svc_ind* param, + uint8_t nb_chars, const struct prf_char_def* chars_req, struct prf_char_inf* chars, + uint8_t nb_descs, const struct prf_char_desc_def* descs_req, struct prf_char_desc_inf* descs); + +#endif //(BLE_CLIENT_PRF) + + +#if (BLE_CLIENT_PRF || BLE_TIP_SERVER || BLE_AN_SERVER || BLE_PAS_SERVER) + +/** + **************************************************************************************** + * @brief The function is used to send information about peer attribute value + * + * @param[in] prf_env Pointer to the profile environment variable + * @param[in] conidx Connection index + * @param[in] msg_id Profile message ID to trigger + * @param[in] status Response status code + * @param[in] read_ind GATT read message indication + **************************************************************************************** + */ +void prf_client_att_info_rsp(prf_env_t *prf_env, uint8_t conidx, uint16_t msg_id, + uint8_t status, struct gattc_read_ind const* read_ind); + +#endif //(BLE_CLIENT_PRF || BLE_TIP_SERVER || BLE_AN_SERVER || BLE_PAS_SERVER) + +#if (BLE_SERVER_PRF || BLE_CLIENT_PRF) +/** + **************************************************************************************** + * @brief Pack date time value + * + * @param[out] packed_date packed date time + * @param[in] date_time structure date time + * + * @return size of packed value + **************************************************************************************** + */ +uint8_t prf_pack_date_time(uint8_t *packed_date, const struct prf_date_time* date_time); + +/** + **************************************************************************************** + * @brief Unpack date time value + * + * @param[in] packed_date packed date time + * @param[out] date_time structure date time + * + * @return size of packed value + **************************************************************************************** + */ +uint8_t prf_unpack_date_time(uint8_t *packed_date, struct prf_date_time* date_time); + +#endif /* (BLE_SERVER_PRF || BLE_CLIENT_PRF) */ + +#if ((BLE_CGM_SERVER || BLE_CGM_CLIENT)) +/** + **************************************************************************************** + * @brief calculate E2E-CRC according to the profile specification + * @param[in] buf Pointer to the byte buffer for the crc calculation. + * @param[in] length Length of the buffer for calculation. + * @return E2E-CRC according to the specification. + **************************************************************************************** + */ +uint16_t prf_e2e_crc(const uint8_t * buf, uint16_t length); + +#endif /* ((BLE_CGM_SERVER || BLE_CGM_CLIENT)) */ + + +/// @} prf_utils + +#endif /* _PRF_UTILS_H_ */ diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_pub/profiles/comm/api/comm.h b/beken_os/beken378/driver/ble_5_x_rw/ble_pub/profiles/comm/api/comm.h new file mode 100755 index 0000000..7b4c973 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_pub/profiles/comm/api/comm.h @@ -0,0 +1,55 @@ +#ifndef _COMM_H_ +#define _COMM_H_ + +#include "rwip_config.h" +#include "rwprf_config.h" + +#if (BLE_COMM_SERVER) +#include "ble.h" +#include "ble_pub.h" +#include "ble_api.h" +#include "comm_task.h" +#include "atts.h" +#include "prf_types.h" +#include "prf.h" +#include "compiler.h" + +enum bk_ble_state +{ + /// Idle state + BLE_IDLE, + /// busy state + BLE_BUSY, + /// Number of defined states. + BLE_STATE_MAX +}; + +/// 'Profile' Server environment variable +struct bk_ble_env_tag +{ + /// profile environment + prf_env_t prf_env; + + /// On-going operation + struct kernel_msg * operation; + /// Services Start Handle + uint16_t start_hdl; + + /// Number of attribute + uint8_t att_db_nb; + + /// Profile id + uint16_t id; + + /// BASS task state + kernel_state_t state[BLE_CONN_IDX_MAX]; + + uint16_t ntf_cfg[BLE_CONNECTION_MAX]; + + uint16_t ind_cfg[BLE_CONNECTION_MAX]; +}; + +const struct prf_task_cbs* bk_ble_prf_itf_get(void); + +#endif +#endif diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_pub/profiles/comm/api/comm_pub.h b/beken_os/beken378/driver/ble_5_x_rw/ble_pub/profiles/comm/api/comm_pub.h new file mode 100755 index 0000000..e69de29 diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_pub/profiles/comm/api/comm_task.h b/beken_os/beken378/driver/ble_5_x_rw/ble_pub/profiles/comm/api/comm_task.h new file mode 100755 index 0000000..e533000 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_pub/profiles/comm/api/comm_task.h @@ -0,0 +1,92 @@ +#ifndef _COMM_TASK_H_ +#define _COMM_TASK_H_ + +#include "rwprf_config.h" +#if (BLE_COMM_SERVER) +#include +#include "rwip_task.h" // Task definitions +#include "compiler.h" + + +struct bk_ble_enable_req +{ + /// connection index + uint8_t conidx; + /// Configuration + uint16_t ind_cfg; + + uint16_t ntf_cfg; + +}; + +struct bk_ble_enable_rsp +{ + /// connection index + uint8_t conidx; + uint16_t prf_id; + ///status + uint8_t status; +}; + +struct bk_ble_ntf_upd_req +{ + /// instance + uint8_t conidx; + + uint16_t length; + + uint16_t att_id; + /// ffe1 Level + uint8_t value[__ARRAY_EMPTY]; +}; + +struct bk_ble_ind_upd_req +{ + /// instance + uint8_t conidx; + + uint16_t length; + + uint16_t att_id; + /// ffe1 Level + uint8_t value[__ARRAY_EMPTY]; +}; + + +struct bk_ble_write_ind +{ + uint8_t conidx; + uint16_t prf_id; + uint16_t att_id; + uint8_t length; + uint8_t value[__ARRAY_EMPTY]; +}; + +/// Command complete event data structure +struct bk_ble_gattc_cmp_evt +{ + /// GATT request type + uint8_t operation; + /// Status of the request + uint8_t status; + + uint16_t prf_id; + /// operation sequence number - provided when operation is started + uint16_t att_id; +}; + +enum bk_ble_msg_id +{ + BK_BLE_ENABLE_REQ = TASK_BLE_FIRST_MSG(TASK_BLE_ID_COMMON), + BK_BLE_ENABLE_RSP, + BK_BLE_NTF_UPD_REQ, + BK_BLE_IND_UPD_REQ, + BK_BLE_WRITE_REQ_IND, + BK_BLE_GATTC_CMP_EVT, +}; + +void comm_task_init(struct kernel_task_desc *task_desc, kernel_state_t *state); + +#endif + +#endif diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_pub/profiles/comm/src/comm.c b/beken_os/beken378/driver/ble_5_x_rw/ble_pub/profiles/comm/src/comm.c new file mode 100755 index 0000000..1965a74 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_pub/profiles/comm/src/comm.c @@ -0,0 +1,115 @@ +#include "rwip_config.h" + +#if (BLE_COMM_SERVER) +#include "attm.h" +#include "comm.h" +#include "comm_task.h" +#include "prf_utils.h" +#include "prf.h" +#include "kernel_mem.h" + +static uint8_t bk_ble_service_init (struct prf_task_env* env, uint16_t* start_hdl, uint16_t app_task, uint8_t sec_lvl, struct bk_ble_db_cfg* params) +{ + uint16_t shdl; + struct bk_ble_env_tag* ble_env = NULL; + // Status + uint8_t status = GAP_ERR_NO_ERROR; + + //-------------------- allocate memory required for the profile --------------------- + ble_env = (struct bk_ble_env_tag* ) kernel_malloc(sizeof(struct bk_ble_env_tag), KERNEL_MEM_ATT_DB); + memset(ble_env, 0 , sizeof(struct bk_ble_env_tag)); + + // Service content flag + uint16_t cfg_flag = 0xFFFF; + + shdl = *start_hdl; + + //Create FFF0 in the DB + //------------------ create the attribute database for the profile ------------------- + status = attm_svc_create_db_128(&(shdl), params->uuid, (uint8_t *)&cfg_flag, + params->att_db_nb, NULL, env->task, (struct attm_desc_128 *)params->att_db, + (sec_lvl & (PERM_MASK_SVC_DIS | PERM_MASK_SVC_AUTH | PERM_MASK_SVC_EKS | PERM_MASK_SVC_UUID_LEN))); + + //-------------------- Update profile task information --------------------- + if (status == ATT_ERR_NO_ERROR) + { + + // allocate BASS required environment variable + env->env = (prf_env_t*) ble_env; + *start_hdl = shdl; + ble_env->start_hdl = *start_hdl; + ble_env->prf_env.app_task = app_task + | (PERM_GET(sec_lvl, SVC_MI) ? PERM(PRF_MI, ENABLE) : PERM(PRF_MI, DISABLE)); + ble_env->prf_env.prf_task = env->task | PERM(PRF_MI, DISABLE); + + ble_env->att_db_nb = params->att_db_nb; + + // initialize environment variable + env->id = params->prf_task_id; + comm_task_init(&(env->desc), ble_env->state); + + bk_printf("ble_env->start_hdl = 0x%x\r\n",ble_env->start_hdl); + + // service is ready, go into an Idle state + kernel_state_set(env->task, BLE_IDLE); + } + else if(ble_env != NULL) + { + kernel_free(ble_env); + } + + return (status); +} + +static void bk_ble_service_destroy(struct prf_task_env* env) +{ + struct bk_ble_env_tag* ble_env = (struct bk_ble_env_tag*) env->env; + + // clear on-going operation + if(ble_env->operation != NULL) + { + kernel_free(ble_env->operation); + } + + // free profile environment variables + env->env = NULL; + kernel_free(ble_env); +} + +static void bk_ble_service_create(struct prf_task_env* env, uint8_t conidx) +{ + struct bk_ble_env_tag* ble_env = (struct bk_ble_env_tag*) env->env; + BLE_ASSERT_ERR(conidx < BLE_CONNECTION_MAX); + + // force notification config to zero when peer device is connected + ble_env->ntf_cfg[conidx] = 0; + ble_env->ind_cfg[conidx] = 0; +} + + +static void bk_ble_service_cleanup(struct prf_task_env* env, uint8_t conidx, uint8_t reason) +{ + struct bk_ble_env_tag* ble_env = (struct bk_ble_env_tag*) env->env; + + BLE_ASSERT_ERR(conidx < BLE_CONNECTION_MAX); + // force notification config to zero when peer device is disconnected + ble_env->ntf_cfg[conidx] = 0; + ble_env->ind_cfg[conidx] = 0; +} + +/// Task interface required by profile manager +const struct prf_task_cbs bk_ble_itf = +{ + (prf_init_fnct) bk_ble_service_init, + bk_ble_service_destroy, + bk_ble_service_create, + bk_ble_service_cleanup, +}; + +const struct prf_task_cbs* bk_ble_prf_itf_get(void) +{ + return &bk_ble_itf; +} + +#endif + diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_pub/profiles/comm/src/comm_task.c b/beken_os/beken378/driver/ble_5_x_rw/ble_pub/profiles/comm/src/comm_task.c new file mode 100755 index 0000000..423652d --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_pub/profiles/comm/src/comm_task.c @@ -0,0 +1,386 @@ +#include "rwip_config.h" + +#if (BLE_COMM_SERVER) + +#include "gap.h" +#include "gattc_task.h" +#include "attm.h" +#include "atts.h" +#include "common_utils.h" +#include "kernel_mem.h" +#include "comm.h" +#include "comm_task.h" + +#include "prf_utils.h" +#include "ble.h" +#include "ble_pub.h" +#include "ble_api.h" + +extern struct prf_env_tag prf_env;; + +static uint8_t bk_ble_get_prf_by_handler(uint16_t handler, struct prf_task_env **env) +{ + uint8_t status = PRF_APP_ERROR; + struct bk_ble_env_tag* ble_env = NULL; + uint32_t i; + for(i = 0; i < BLE_NB_PROFILES ; i++) + { + ble_env = (struct bk_ble_env_tag*)(prf_env.prf[i].env); + if(((ble_env->start_hdl) <= handler) && ((ble_env->start_hdl + ble_env->att_db_nb) >= handler)) + { + *env = &(prf_env.prf[i]); + status = GAP_ERR_NO_ERROR; + break; + } + } + + return status; +} + +static uint8_t bk_ble_get_prf_by_task(kernel_task_id_t task, struct prf_task_env **env) +{ + uint8_t status = PRF_APP_ERROR; + uint32_t i; + for(i = 0; i < BLE_NB_PROFILES ; i++) + { + if(prf_env.prf[i].task == task) + { + *env = &(prf_env.prf[i]); + status = GAP_ERR_NO_ERROR; + break; + } + } + + return status; +} + +static int bk_ble_enable_req_handler(kernel_msg_id_t const msgid, + struct bk_ble_enable_req const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + int msg_status = KERNEL_MSG_SAVED; + uint8_t state = kernel_state_get(dest_id); + + struct prf_task_env *prf_env = NULL; + + // retrieve handle information + uint8_t status = bk_ble_get_prf_by_task(dest_id, &prf_env); + if(status != GAP_ERR_NO_ERROR) + { + bk_printf("dest_id is invalid:%d\r\n", dest_id); + return KERNEL_MSG_CONSUMED; + } + + // check state of the task + if(state == BLE_IDLE) + { + // struct ffe0s_env_tag* ffe0s_env = PRF_ENV_GET(FFE0S, ffe0s); + + // Check provided values + if((param->conidx > BLE_CONNECTION_MAX) + || (gapc_get_conhdl(param->conidx) == GAP_INVALID_CONHDL)) + { + // an error occurs, trigg it. + struct bk_ble_enable_rsp* rsp = KERNEL_MSG_ALLOC(BK_BLE_ENABLE_RSP, src_id, + dest_id, bk_ble_enable_rsp); + rsp->prf_id = prf_env->id - TASK_BLE_ID_COMMON; + rsp->conidx = param->conidx; + rsp->status = (param->conidx > BLE_CONNECTION_MAX) ? GAP_ERR_INVALID_PARAM : PRF_ERR_REQ_DISALLOWED; + kernel_msg_send(rsp); + + msg_status = KERNEL_MSG_CONSUMED; + } + + } + + return msg_status; +} + +static void bk_ble_ntf_val(struct bk_ble_env_tag* ble_env,struct bk_ble_ntf_upd_req const *param) +{ + + // UART_PRINTF("%s\r\n",__func__); + //Allocate the GATT notification message + struct gattc_send_evt_cmd *ntf_value = KERNEL_MSG_ALLOC_DYN(GATTC_SEND_EVT_CMD, + KERNEL_BUILD_ID(TASK_BLE_GATTC, 0), prf_src_task_get(&(ble_env->prf_env),0), + gattc_send_evt_cmd, param->length); + + //Fill in the parameter structure + ntf_value->operation = GATTC_NOTIFY; + ntf_value->handle = ble_env->start_hdl + param->att_id; + // pack measured value in databaseS + ntf_value->length = param->length; + ntf_value->seq_num = param->att_id; + + //UART_PRINTF("fed6_value->handle = 0x%x\r\n",fed6_value->handle); + memcpy(&ntf_value->value[0],param->value,ntf_value->length); + + //send notification to peer device + kernel_msg_send(ntf_value); +} + +static int bk_ble_ntf_upd_req_handler(kernel_msg_id_t const msgid, + struct bk_ble_ntf_upd_req const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + int msg_status = KERNEL_MSG_CONSUMED; + uint8_t state = kernel_state_get(dest_id); + + struct prf_task_env *prf_env = NULL; + struct bk_ble_env_tag* ble_env = NULL; + + // retrieve handle information + uint8_t status = bk_ble_get_prf_by_task(dest_id, &prf_env); + // retrieve handle information + ble_env = (struct bk_ble_env_tag*)(prf_env->env); + if(GAP_ERR_NO_ERROR == status) + { + // check state of the task + if(state == BLE_IDLE) + { + // update the battery level value + kernel_state_set(dest_id, BLE_BUSY); + + bk_ble_ntf_val(ble_env, param); + // ke_state_set(dest_id, FEB3S_IDLE); + msg_status = KERNEL_MSG_CONSUMED; + } + else + { + //UART_PRINTF("KE_MSG_SAVED6\r\n"); + msg_status = KERNEL_MSG_SAVED; + } + } + + return (msg_status); + +} + +static void bk_ble_ind_val(struct bk_ble_env_tag* ble_env,struct bk_ble_ind_upd_req const *param) +{ + + // UART_PRINTF("%s\r\n",__func__); + //Allocate the GATT notification message + struct gattc_send_evt_cmd *ntf_value = KERNEL_MSG_ALLOC_DYN(GATTC_SEND_EVT_CMD, + KERNEL_BUILD_ID(TASK_BLE_GATTC, 0), prf_src_task_get(&(ble_env->prf_env),0), + gattc_send_evt_cmd, param->length); + + //Fill in the parameter structure + ntf_value->operation = GATTC_INDICATE; + ntf_value->handle = ble_env->start_hdl + param->att_id; + // pack measured value in databaseS + ntf_value->length = param->length; + ntf_value->seq_num = param->att_id; + + //UART_PRINTF("fed6_value->handle = 0x%x\r\n",fed6_value->handle); + memcpy(&ntf_value->value[0],param->value,ntf_value->length); + + //send notification to peer device + kernel_msg_send(ntf_value); +} + +static int bk_ble_ind_upd_req_handler(kernel_msg_id_t const msgid, + struct bk_ble_ind_upd_req const *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + int msg_status = KERNEL_MSG_CONSUMED; + uint8_t state = kernel_state_get(dest_id); + + struct prf_task_env *prf_env = NULL; + struct bk_ble_env_tag* ble_env = NULL; + + // retrieve handle information + uint8_t status = bk_ble_get_prf_by_task(dest_id, &prf_env); + // retrieve handle information + ble_env = (struct bk_ble_env_tag*)(prf_env->env); + if(GAP_ERR_NO_ERROR == status) + { + // check state of the task + if(state == BLE_IDLE) + { + // update the battery level value + kernel_state_set(dest_id, BLE_BUSY); + + bk_ble_ind_val(ble_env, param); + // ke_state_set(dest_id, FEB3S_IDLE); + msg_status = KERNEL_MSG_CONSUMED; + } + else + { + //UART_PRINTF("KE_MSG_SAVED6\r\n"); + msg_status = KERNEL_MSG_SAVED; + } + } + + return (msg_status); + +} + +static int gattc_att_info_req_ind_handler(kernel_msg_id_t const msgid, + struct gattc_att_info_req_ind *param, + kernel_task_id_t const dest_id, + kernel_task_id_t const src_id) +{ + struct gattc_att_info_cfm * cfm; + att_info_req_t att_info; + // retrieve handle information + struct prf_task_env *prf_env = NULL; + struct bk_ble_env_tag* ble_env = NULL; + + // retrieve handle information + uint8_t status = bk_ble_get_prf_by_handler(param->handle, &prf_env); + ble_env = (struct bk_ble_env_tag*)(prf_env->env); + att_info.att_idx = param->handle - ble_env->start_hdl; + att_info.prf_id = prf_env->id - TASK_BLE_ID_COMMON; + //Send write response + cfm = KERNEL_MSG_ALLOC(GATTC_ATT_INFO_CFM, src_id, dest_id, gattc_att_info_cfm); + cfm->handle = param->handle; + + if(status == GAP_ERR_NO_ERROR) + { + ble_event_cb_handler(BLE_ATT_INFO_REQ, (void *)&att_info); + } + + cfm->length = att_info.length; + cfm->status = att_info.status; + kernel_msg_send(cfm); + + return (KERNEL_MSG_CONSUMED); +} + +static int gattc_read_req_ind_handler(kernel_msg_id_t const msgid, struct gattc_read_req_ind const *param, + kernel_task_id_t const dest_id, kernel_task_id_t const src_id) +{ + struct gattc_read_cfm * cfm; + read_req_t read_req; + uint16_t length = 0; + + struct prf_task_env *prf_env = NULL; + struct bk_ble_env_tag* ble_env = NULL; + + // retrieve handle information + uint8_t status = bk_ble_get_prf_by_handler(param->handle, &prf_env); + + read_req.value = kernel_malloc(BLE_CHAR_DATA_LEN, KERNEL_MEM_KERNEL_MSG); + read_req.size = BLE_CHAR_DATA_LEN; + ble_env = (struct bk_ble_env_tag*)(prf_env->env); + read_req.att_idx = param->handle - ble_env->start_hdl; + read_req.prf_id = prf_env->id - TASK_BLE_ID_COMMON; + // If the attribute has been found, status is GAP_ERR_NO_ERROR + if (status == GAP_ERR_NO_ERROR) + { + length = ble_read_cb_handler(&read_req); + } + + cfm = KERNEL_MSG_ALLOC_DYN(GATTC_READ_CFM, src_id, dest_id, gattc_read_cfm, length); + + cfm->length = length; + cfm->handle = param->handle; + cfm->status = status; + memcpy(cfm->value,read_req.value,cfm->length); + + kernel_msg_send(cfm); + + kernel_free(read_req.value); + + return (KERNEL_MSG_CONSUMED); +} + +static int gattc_write_req_ind_handler(kernel_msg_id_t const msgid, struct gattc_write_req_ind const *param, + kernel_task_id_t const dest_id, kernel_task_id_t const src_id) +{ + struct gattc_write_cfm * cfm; + struct prf_task_env *prf_env = NULL; + struct bk_ble_env_tag* ble_env = NULL; + + // retrieve handle information + uint8_t status = bk_ble_get_prf_by_handler(param->handle, &prf_env); + uint8_t conidx = KERNEL_IDX_GET(src_id); + // retrieve handle information + ble_env = (struct bk_ble_env_tag*)(prf_env->env); + + + + // If the attribute has been found, status is GAP_ERR_NO_ERROR + if (status == GAP_ERR_NO_ERROR) + { + // Allocate the alert value change indication + struct bk_ble_write_ind *ind = KERNEL_MSG_ALLOC_DYN(BK_BLE_WRITE_REQ_IND, + prf_dst_task_get(&(ble_env->prf_env), conidx), + dest_id, bk_ble_write_ind, param->length); + + // Fill in the parameter structure + memcpy(ind->value,¶m->value[0],param->length); + ind->att_id = param->handle - ble_env->start_hdl;; + ind->prf_id = prf_env->id - TASK_BLE_ID_COMMON; + ind->conidx = conidx; + ind->length = param->length; + // Send the message + kernel_msg_send(ind); + } + + //Send write response + cfm = KERNEL_MSG_ALLOC(GATTC_WRITE_CFM, src_id, dest_id, gattc_write_cfm); + cfm->handle = param->handle; + cfm->status = status; + kernel_msg_send(cfm); + + return (KERNEL_MSG_CONSUMED); +} + +static int gattc_cmp_evt_handler(kernel_msg_id_t const msgid, struct gattc_cmp_evt const *param, + kernel_task_id_t const dest_id, kernel_task_id_t const src_id) +{ + //UART_PRINTF("%s\r\n",__func__); + struct prf_task_env *prf_env = NULL; + struct bk_ble_env_tag* ble_env = NULL; + + // retrieve handle information + uint8_t status = bk_ble_get_prf_by_task(dest_id, &prf_env); + // retrieve handle information + ble_env = (struct bk_ble_env_tag*)(prf_env->env); + + if (status == GAP_ERR_NO_ERROR) + { + // continue operation execution + struct bk_ble_gattc_cmp_evt *evt = KERNEL_MSG_ALLOC(BK_BLE_GATTC_CMP_EVT, + prf_dst_task_get(&(ble_env->prf_env), 0), + dest_id, bk_ble_gattc_cmp_evt); + + evt->operation = param->operation; + evt->status = param->status; + evt->prf_id = prf_env->id - TASK_BLE_ID_COMMON; + evt->att_id = param->seq_num; + + kernel_state_set(dest_id, BLE_IDLE); + kernel_msg_send(evt); + } + + return (KERNEL_MSG_CONSUMED); +} + +/// Default State handlers definition +const struct kernel_msg_handler bk_ble_default_handler[] = +{ + {BK_BLE_ENABLE_REQ, (kernel_msg_func_t) bk_ble_enable_req_handler}, + {BK_BLE_NTF_UPD_REQ, (kernel_msg_func_t) bk_ble_ntf_upd_req_handler}, + {BK_BLE_IND_UPD_REQ, (kernel_msg_func_t) bk_ble_ind_upd_req_handler}, + {GATTC_ATT_INFO_REQ_IND, (kernel_msg_func_t) gattc_att_info_req_ind_handler}, + {GATTC_READ_REQ_IND, (kernel_msg_func_t) gattc_read_req_ind_handler}, + {GATTC_WRITE_REQ_IND, (kernel_msg_func_t) gattc_write_req_ind_handler}, + {GATTC_CMP_EVT, (kernel_msg_func_t) gattc_cmp_evt_handler}, +}; + +void comm_task_init(struct kernel_task_desc *task_desc, kernel_state_t *state) +{ + // Get the address of the environment + task_desc->msg_handler_tab = bk_ble_default_handler; + task_desc->msg_cnt = ARRAY_LEN(bk_ble_default_handler); + task_desc->state = state; + task_desc->idx_max = BLE_CONN_IDX_MAX; +} + +#endif diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_pub/ui/ble_ui.c b/beken_os/beken378/driver/ble_5_x_rw/ble_pub/ui/ble_ui.c new file mode 100755 index 0000000..07125f9 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_pub/ui/ble_ui.c @@ -0,0 +1,97 @@ +#include "ble_ui.h" +#include "app_ble.h" + + +#if (BLE_APP_PRESENT) + +ble_event_cb_t ble_event_cb = NULL; +bk_ble_read_cb_t bk_ble_read_cb = NULL; +bk_ble_write_cb_t bk_ble_write_cb = NULL; +ble_recv_adv_cb_t ble_recv_adv_cb = NULL; +extern struct app_env_tag app_ble_ctx; + +void ble_set_event_cb(ble_event_cb_t func) +{ + ble_event_cb = func; +} + +void ble_event_cb_handler(ble_event_t event, void *param) +{ + ble_event_cb_t func = ble_event_cb; + + if(func != NULL) + { + func(event,param); + } +} + +void ble_set_write_cb(bk_ble_write_cb_t func) +{ + bk_ble_write_cb = func; +} + +void ble_write_cb_handler(write_req_t *write_req) +{ + bk_ble_write_cb_t func = bk_ble_write_cb; + + if(func != NULL) + { + func(write_req); + } +} + +void ble_set_read_cb(bk_ble_read_cb_t func) +{ + bk_ble_read_cb = func; +} + +int ble_read_cb_handler(read_req_t *read_req) +{ + bk_ble_read_cb_t func = bk_ble_read_cb; + + if(func != NULL) + { + return func(read_req); + } + return 0; +} + +void ble_set_recv_adv_cb(ble_recv_adv_cb_t func) +{ + ble_recv_adv_cb = func; +} + +void ble_recv_adv_cb_handler(recv_adv_t *recv_adv) +{ + ble_recv_adv_cb_t func = ble_recv_adv_cb; + + if(func != NULL) + { + func(recv_adv); + } +} + +unsigned char ble_appm_get_dev_name(unsigned char* name) +{ + // copy name to provided pointer + memcpy(name, app_ble_ctx.dev_name, app_ble_ctx.dev_name_len); + // return name length + return app_ble_ctx.dev_name_len; +} + +unsigned char ble_appm_set_dev_name(unsigned char len,unsigned char* name) +{ + // copy name to provided pointer + if(len < APP_DEVICE_NAME_MAX_LEN) + { + app_ble_ctx.dev_name_len = len; + memcpy(app_ble_ctx.dev_name, name, len); + // return name length + return app_ble_ctx.dev_name_len; + } + + return 0; +} + +#endif + diff --git a/beken_os/beken378/driver/ble_5_x_rw/ble_pub/ui/ble_ui.h b/beken_os/beken378/driver/ble_5_x_rw/ble_pub/ui/ble_ui.h new file mode 100755 index 0000000..047e921 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/ble_pub/ui/ble_ui.h @@ -0,0 +1,72 @@ +#ifndef _BLE_UI_H_ +#define _BLE_UI_H_ + +/// Maximal length of the Device Name value +#define APP_DEVICE_NAME_MAX_LEN (18) + +#include "rwip_config.h" // SW configuration +#include // Standard Integer Definition +#include "gapc_task.h" // GAPC Definitions +#include "common_bt.h" +#include +#include "kernel_task.h" // Kernel Task +#include "kernel_msg.h" +#include "gap.h" // GAP Definition +#include "gapm_task.h" // GAP Manager Task API +#include "gapc_task.h" // GAP Controller Task API +#include "common_bt.h" // Common BT Definition +#include "common_math.h" // Common Maths Definition +#include "rwip.h" // RW definitions +#include "architect.h" // Platform Definitions +#include "app_task.h" // Application task Definition +#include "gattc_int.h" +#include "ble_api.h" +#include "gapm_task.h" +#include "co_math.h" + +extern void ble_set_event_cb(ble_event_cb_t func); +extern void ble_set_write_cb(bk_ble_write_cb_t func); +extern void ble_set_read_cb(bk_ble_read_cb_t func); +extern void ble_set_recv_adv_cb(ble_recv_adv_cb_t func); + + +extern void ble_event_cb_handler(ble_event_t event, void *param); +extern void ble_write_cb_handler(write_req_t *write_req); +extern int ble_read_cb_handler(read_req_t *read_req); +extern void ble_recv_adv_cb_handler(recv_adv_t *recv_adv); + +extern void ble_appm_create_advertising(unsigned char chnl_map,uint32_t intv_min,uint32_t intv_max); +extern void ble_appm_start_advertising(unsigned char adv_actv_idx,uint16 duration); +extern void ble_appm_stop_advertising(unsigned char adv_actv_idx); +extern void ble_appm_delete_advertising(unsigned char adv_actv_idx); + + +extern int ble_appm_update_adv_data(unsigned char adv_actv_idx,unsigned char* adv_buff, unsigned char adv_len); +extern int ble_appm_set_scan_rsp_data(unsigned char adv_actv_idx,unsigned char* scan_buff, unsigned char scan_len); + + +extern int ble_app_gapm_adv_check_data_sanity(uint16_t length, uint8_t *p_data); + +extern void ble_appm_update_param(unsigned char conidx,struct gapc_conn_param *conn_param); + +///extern int ble_set_scan_param( uint16_t scan_intv, uint16_t scan_wd); + + +extern void ble_appm_send_gapm_reset_cmd(void); + +//////////////scan +extern void ble_appm_create_scaning(void); + + +////////////// +extern void ble_appc_gatt_mtu_change(unsigned char conidx); + + + +/////////////////////// +extern unsigned char ble_appm_get_dev_name(unsigned char* name); +extern unsigned char ble_appm_set_dev_name(unsigned char len,unsigned char* name); + + + +#endif diff --git a/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/config/rwapp_config.h b/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/config/rwapp_config.h new file mode 100755 index 0000000..ea81092 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/config/rwapp_config.h @@ -0,0 +1,53 @@ +/** + **************************************************************************************** + * + * @file rwapp_config.h + * + * @brief Application configuration definition + * + * Copyright (C) RivieraWaves 2009-2016 + * + **************************************************************************************** + */ + + +#ifndef _RWAPP_CONFIG_H_ +#define _RWAPP_CONFIG_H_ + +/** + **************************************************************************************** + * @addtogroup app + * @brief Application configuration definition + * + * @{ + **************************************************************************************** + */ + + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +/* + * DEFINES + **************************************************************************************** + */ +// BLE_APP_COMM +// BLE_APP_COMM enable /disable +// +#if ( 1 ) +#define CFG_APP_COMM +#endif + +/// COMM Service Application +#if defined(CFG_APP_COMM) +#define BLE_APP_COMM 1 +#else +#define BLE_APP_COMM 0 +#endif // defined(BLE_APP_COMM) +/******************************************************************************************/ +/* ------------------------- BLE APPLICATION SETTINGS -----------------------------*/ +/******************************************************************************************/ + +#endif /* _RWAPP_CONFIG_H_ */ diff --git a/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/config/rwip_config.h b/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/config/rwip_config.h new file mode 100755 index 0000000..5fe6d2f --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/config/rwip_config.h @@ -0,0 +1,1490 @@ +/** + **************************************************************************************** + * + * @file rwip_config.h + * + * @brief Configuration of the RW IP SW + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef RWIP_CONFIG_H_ +#define RWIP_CONFIG_H_ + +/** + **************************************************************************************** + * @addtogroup ROOT + * @{ + * + * Information about RW SW IP options and flags + * + * BT_DUAL_MODE BT/BLE Dual Mode + * BT_STD_MODE BT Only + * BLE_STD_MODE BLE Only + * + * BT_EMB_PRESENT BT controller exists + * BLE_EMB_PRESENT BLE controller exists + * BLE_HOST_PRESENT BLE host exists + * + * @name RW Stack Configuration + * @{ + **************************************************************************************** + */ +#include "architect.h" +#include "ble.h" +#include "user_config.h" +/* + * DEFINES + **************************************************************************************** + */ + +/******************************************************************************************/ +/* -------------------------- GENERAL SETUP --------------------------------------*/ +/* ------------------------- don't change format -------------------------------*/ +/******************************************************************************************/ + +// <<< Use Configuration Wizard in Context Menu >>> + +// CW_CFG_RW_IP_VALUE +// CFG_APP +// +#if ( CFG_USE_BK_HOST ) + #define CFG_APP +#endif + +// CFG_BLE Role +// <0=> BROADCASTER +// <1=> OBSERVER +// <2=> PERIPHERAL +// <3=> CENTRAL +// <4=> ALLROLES +// Select Role +#define CFG_ROLE 4 + +#if ( CFG_ROLE == 0) + #define CFG_BROADCASTER +#endif + +#if ( CFG_ROLE == 1) + #define CFG_OBSERVER +#endif + +#if ( CFG_ROLE == 2) + #define CFG_PERIPHERAL +#endif + +#if ( CFG_ROLE == 3) + #define CFG_CENTRAL +#endif + +#if ( CFG_ROLE == 4) + #define CFG_ALLROLES +#endif + +// CFG_EMB +// enable Exchange Memeory +// +#if ( 1 ) + #define CFG_EMB +#endif + +// CFG_BT +// BT MODE ENABLE +// +#if ( 0 ) + #define CFG_BT +#endif + +// CFG_BLE +// BLE MODE ENABLE +// +#if ( 1 ) + #define CFG_BLE +#endif + +// CFG_BLE_2MBPS +// select BLE at 2MBPS Mode +// +#if ( 1 ) + #define CFG_BLE_2MBPS +#endif + +// CFG_CHNL_ASSESS +// select BLE CHNL_ASSESS +// +#if ( 0 ) + #define CFG_CHNL_ASSESS +#endif + +// CFG_SEC_CON +// select BLE SEC CON +// +#if ( 0 ) + #define CFG_SEC_CON +#endif + +// CFG_HOST +// enable BLE HOST +// +#if ( CFG_USE_BK_HOST ) + #define CFG_HOST +#endif + +// CFG_AHITL +// enable Application Host Interface +// +#if ( 0 ) + #define CFG_AHITL +#endif + +// CFG_HCITL +// enable Host Controller Interface Support +// +#if ( CFG_USE_BK_HOST ) + #define CFG_HCITL +#endif + +// CFG_HW_AUDIO +// enable HW_AUDIO +// +#if ( 0 ) + #define CFG_HW_AUDIO +#endif + +// CFG_NVDS +// enable NVDS +// +#if ( 0 ) + #define CFG_NVDS +#endif + +// CFG_PRF +// enable PRF +// +#if ( 1 ) + #define CFG_PRF +#endif + +// CFG_NB_PRF <0-10> +// CFG_NB_PRF (0 -- 10) +#define CFG_NB_PRF 10 + +// CFG_BLE_TESTER(DUT) +// enable BLE_TESTER +// +#if ( 0 ) + #define CFG_BLE_TESTER +#endif + +// CFG_SLEEP +// enable DEEP_SLEEP +// +#if ( 1 ) + #define CFG_SLEEP +#endif + +#if ( 1 ) + #define CFG_GAIA +#endif + + +// CFG_CON <1-10> +// CFG MAX CONNECT NUM (1 -- 10) +#define CFG_CON 1 + +// CFG_RAL <1-10> +// CFG NUMBER OF DEVICE IN RAL (1 -- 10) +#define CFG_RAL 4 + +// CFG_ACT <1-10> +// CFG NUMBER OF ACTIVITIES IN BLE SIMULTANEOUS (1 -- 10) +#define CFG_ACT 3 + +// CFG_CON_SCO <0-2> +// CFG NUMBER OF SYNCHRONOUS CONNECTIONS (0 -- 2) +#define CFG_CON_SCO 0 + +// CFG_BLE_MESH +// enable CFG_BLE_MESH +// +#if ( 0 ) + #define CFG_BLE_MESH +#endif + +// + +#define CFG_ECC_P256_ACC 0 +#define CFG_BLE_PER_SYNC 0 +#define CFG_BLE_PER_ADV 0 +#define CFG_BLE_MASTER 0 +#define CFG_BLE_EXT_ADV 1 +#define CFG_BLE_EXT_SCAN 1 + + +/////POKI Test +// Config User App/Test function +// CFG_USER_APP +// enable CFG_USER_APP +// +#if ( 1 ) + #define CFG_USER_APP +#endif +// + +#ifdef CFG_BLE_TESTER + #define BLE_DUT_TEST 0 +#else + #define BLE_DUT_TEST 0 +#endif + +/******************************************************************************************/ +/* -------------------------- GENERAL SETUP --------------------------------------*/ +/* ------------------------- don't change format -------------------------------*/ +/******************************************************************************************/ + +/// Flag indicating if stack is compiled in dual or single mode +#if defined(CFG_BT) +#define BT_EMB_PRESENT 1 +#else // defined(CFG_BT) +#define BT_EMB_PRESENT 0 +#endif // defined(CFG_BT) + +#if defined(CFG_BLE) && defined(CFG_EMB) +#define BLE_EMB_PRESENT 1 +#else // defined(CFG_BLE) && defined(CFG_EMB) +#define BLE_EMB_PRESENT 0 +#endif // defined(CFG_BLE) && defined(CFG_EMB) + +#if defined(CFG_BLE) && defined(CFG_HOST) +#define BLE_HOST_PRESENT 1 +#else // defined(CFG_BLE) && defined(CFG_HOST) +#define BLE_HOST_PRESENT 0 +#endif // defined(CFG_BLE) && defined(CFG_HOST) + +#if defined(CFG_BLE) && defined(CFG_APP) +#define BLE_APP_PRESENT 1 +#else // defined(CFG_BLE) && defined(CFG_APP) +#define BLE_APP_PRESENT 0 +#endif // defined(CFG_BLE) && defined(CFG_APP) + +#define BT_DUAL_MODE (BT_EMB_PRESENT && BLE_EMB_PRESENT) +#define BT_STD_MODE (BT_EMB_PRESENT) +#define BLE_STD_MODE (BLE_EMB_PRESENT) +#define HCI_PRESENT 1 + +/// Flag indicating that Mesh is supported +#if defined(CFG_BLE_MESH) +#define BLE_MESH 1 +#else // !defined(CFG_BLE_MESH) +#define BLE_MESH 0 +#endif // defined(CFG_BLE_MESH) + +/******************************************************************************************/ +/* ------------------------- INTERFACES DEFINITIONS -------------------------------*/ +/******************************************************************************************/ + +/// Application Host Interface +#if defined(CFG_AHITL) +#define AHI_TL_SUPPORT 1 +#else // defined(CFG_AHITL) +#define AHI_TL_SUPPORT 0 +#endif // defined(CFG_AHITL) + + +/// Host Controller Interface Support (defines if HCI parser is present or not) +#if defined(CFG_HCITL) +#define HCI_TL_SUPPORT 1 +#else //defined(CFG_HCITL) +#define HCI_TL_SUPPORT 0 +#endif //defined(CFG_HCITL) + +#if BLE_HOST_PRESENT +#define H4TL_SUPPORT ((AHI_TL_SUPPORT) + (HCI_TL_SUPPORT)) +#else // !BLE_HOST_PRESENT +#define H4TL_SUPPORT (HCI_TL_SUPPORT) +#endif // BLE_HOST_PRESENT + +/// Number of HCI commands the stack can handle simultaneously +#define HCI_NB_CMD_PKTS (5 * HCI_TL_SUPPORT) + +/******************************************************************************************/ +/* -------------------------- BLE COMMON DEFINITIONS ------------------------------*/ +/******************************************************************************************/ +/// Kernel Heap memory sized reserved for allocate dynamically connection environment +#define KERNEL_HEAP_MEM_RESERVED (4) + +#if defined(CFG_BLE) + +/// Broadcaster +#if (defined(CFG_BROADCASTER) || defined(CFG_PERIPHERAL) || defined(CFG_ALLROLES)) +#define BLE_BROADCASTER 1 +#else +#define BLE_BROADCASTER 0 +#endif // (defined(CFG_BROADCASTER) || defined(CFG_PERIPHERAL) || defined(CFG_ALLROLES)) + +/// Observer +#if (defined(CFG_OBSERVER) || defined(CFG_CENTRAL) || defined(CFG_ALLROLES)) +#define BLE_OBSERVER 1 +#else +#define BLE_OBSERVER 0 +#endif // (defined(CFG_OBSERVER) || defined(CFG_CENTRAL) || defined(CFG_ALLROLES)) + +/// Central +#if (defined(CFG_CENTRAL) || defined(CFG_ALLROLES)) +#define BLE_CENTRAL 1 +#else +#define BLE_CENTRAL 0 +#endif // (defined(CFG_CENTRAL) || defined(CFG_ALLROLES)) + +/// Peripheral +#if (defined(CFG_PERIPHERAL) || defined(CFG_ALLROLES)) +#define BLE_PERIPHERAL 1 +#else +#define BLE_PERIPHERAL 0 +#endif // (defined(CFG_PERIPHERAL) || defined(CFG_ALLROLES)) + +#if ((BLE_BROADCASTER+BLE_OBSERVER+BLE_PERIPHERAL+BLE_CENTRAL) == 0) + #error "No application role defined" +#endif // ((BLE_BROADCASTER+BLE_OBSERVER+BLE_PERIPHERAL+BLE_CENTRAL) == 0) + +/// Maximum number of devices in RAL +#define BLE_RAL_MAX (CFG_RAL) + +/// Maximum number of simultaneous BLE activities (scan, connection, advertising, initiating) +#define BLE_ACTIVITY_MAX (CFG_ACT) + +#if (BLE_HOST_PRESENT) +/// Maximum number of simultaneous connections +#if (BLE_CENTRAL || BLE_PERIPHERAL) + #define BLE_CONNECTION_MAX (CFG_CON) +#else + #define BLE_CONNECTION_MAX (0) +#endif /* #if (BLE_CENTRAL || BLE_PERIPHERAL) */ + +#if (BLE_CONNECTION_MAX >= BLE_ACTIVITY_MAX) + #error "Number of connections must be strictly less than number of activities" +#endif // (BLE_CONNECTION_MAX >= BLE_ACTIVITY_MAX) +#endif // (BLE_HOST_PRESENT) + +/// Max advertising reports before sending the info to the host +#define BLE_ADV_REPORTS_MAX (1) + +#if (BLE_EMB_PRESENT) +/// Maximum number of ADV reports in the HCI queue to Host +#define BLE_MAX_NB_ADV_REP_FRAG (4 * HCI_TL_SUPPORT) +/// Maximum number of IQ reports in the HCI queue to Host +#define BLE_MAX_NB_IQ_REP (4 * HCI_TL_SUPPORT) +#endif // (BLE_EMB_PRESENT) +#endif //defined(CFG_BLE) + + +/******************************************************************************************/ +/* -------------------------- Direction finding (AoA/AoD) -------------------------*/ +/******************************************************************************************/ + +#if defined(CFG_CON_CTE_REQ) + #define BLE_CON_CTE_REQ (1) +#else // defined(CFG_CON_CTE_REQ) + #define BLE_CON_CTE_REQ (0) +#endif // defined(CFG_CON_CTE_REQ) + +#if defined(CFG_CON_CTE_RSP) + #define BLE_CON_CTE_RSP (1) +#else // defined(CFG_CON_CTE_RSP) + #define BLE_CON_CTE_RSP (0) +#endif // defined(CFG_CON_CTE_RSP) + +#if defined(CFG_CONLESS_CTE_TX) + #define BLE_CONLESS_CTE_TX (1) +#else // defined(CFG_CONLESS_CTE_TX) + #define BLE_CONLESS_CTE_TX (0) +#endif // defined(CFG_CONLESS_CTE_TX) + +#if defined(CFG_CONLESS_CTE_RX) + #define BLE_CONLESS_CTE_RX (1) +#else // defined(CFG_CONLESS_CTE_RX) + #define BLE_CONLESS_CTE_RX (0) +#endif // defined(CFG_CONLESS_CTE_RX) + +#if defined(CFG_AOD) + #define BLE_AOD (1) +#else // defined(CFG_AOD) + #define BLE_AOD (0) +#endif // defined(CFG_AOD) + +#if defined(CFG_AOA) + #define BLE_AOA (1) +#else // defined(CFG_AOA) + #define BLE_AOA (0) +#endif // defined(CFG_AOA) + +/******************************************************************************************/ +/* -------------------------- ISOCHRONOUS CONFIGURATION -------------------------*/ +/******************************************************************************************/ + +// check if isochronous is enabled or not +#if (defined(CFG_ISO_CON) && (CFG_ISO_CON > 0) && (defined(CFG_ISO_MODE_0))) + #define BLE_ISO_PRESENT (1) +#else // !(defined(CFG_ISO_CON) && (CFG_ISO_CON > 0)) + #define BLE_ISO_PRESENT (0) +#endif // (defined(CFG_ISO_CON) && (CFG_ISO_CON > 0)) + +// *** Definition of supported isochronous mode *** + +// Isochronous Mode 0 - Proprietary mode +#if (BLE_ISO_PRESENT && defined(CFG_ISO_MODE_0)) + #define BLE_ISO_MODE_0 (BLE_CENTRAL | BLE_PERIPHERAL) + #define BLE_ISO_MODE_0_PROTOCOL (BLE_ISO_MODE_0 & BLE_HOST_PRESENT) + #define BLE_ISO_MODE_0_PROFILE (BLE_ISO_MODE_0 & BLE_HOST_PRESENT) + #define BLE_RSA (BLE_ISO_MODE_0_PROFILE) +#else + #define BLE_ISO_MODE_0 (0) + #define BLE_ISO_MODE_0_PROTOCOL (0) + #define BLE_ISO_MODE_0_PROFILE (0) + #define BLE_RSA (0) +#endif // (BLE_ISO_PRESENT && defined(CFG_AUDIO)) + +#if (BLE_ISO_PRESENT) + /// Maximum number of ISO channel / streams + #define BLE_ISO_CHANNEL_MAX (CFG_ISO_CON) + #define BLE_ISO_STREAM_MAX (CFG_ISO_CON) + + /// Maximum number of octets that can be received/transmitted over Isochronous channels + #define BLE_MAX_ISO_OCTETS (251) // number of octets + + /// Define number of ISO TX/RX buffers per isochronous channel + #define BLE_NB_ISO_BUFF_PER_CHAN (4) + + /// Define number of ISO descriptors per isochronous channel + /// Must be equal to max(BLE_NB_ISODESC_PER_ICL_CHAN, BLE_NB_RX_ISODESC_PER_ICO_CHAN + BLE_NB_TX_ISODESC_PER_ICO_CHAN) + #define BLE_NB_ISODESC_PER_CHAN (4) + + /// Number of ISO Descriptors - one descriptor required for update sub-event: 1 per stream + #define BLE_ISO_DESC_NB ((BLE_ISO_CHANNEL_MAX * (BLE_NB_ISODESC_PER_CHAN)) + BLE_ISO_STREAM_MAX) + /// Number of ISO buffers + #define BLE_ISO_BUF_NB (BLE_ISO_CHANNEL_MAX * BLE_NB_ISO_BUFF_PER_CHAN) +#endif // (BLE_ISO_PRESENT) + + +/// Check status of Isochronous Data path drivers + +/// Proprietary ISO over HCI +#if defined(CFG_ISOOHCI) + #define BLE_ISOOHCI (BLE_ISO_PRESENT) +#else + #define BLE_ISOOHCI (0) +#endif + +/// Internal ISO generator for validation purpose +#if defined(CFG_ISOGEN) + #define BLE_ISOGEN (BLE_ISO_PRESENT) +#else + #define BLE_ISOGEN (0) +#endif + +/// Platform PCM +#if defined(CFG_PCM) + #define BLE_ISO_PCM (BLE_ISO_PRESENT) +#else // !defined(CFG_PCM) + #define BLE_ISO_PCM (0) +#endif // defined(CFG_PCM) + +/******************************************************************************************/ +/* -------------------------- GPIO SETUP -------------------------------------*/ +/******************************************************************************************/ + +/// Display controller enable/disable +#if defined(CFG_GPIO) +#define GPIO_SUPPORT 1 +#else +#define GPIO_SUPPORT 0 +#endif //CFG_GPIO + +/******************************************************************************************/ +/* -------------------------- RTC SETUP -------------------------------------*/ +/******************************************************************************************/ + +/// RTC enable/disable +#if defined(CFG_RTC) +#define RTC_SUPPORT 1 +#else +#define RTC_SUPPORT 0 +#endif //CFG_RTC + +/******************************************************************************************/ +/* -------------------------- PS2 SETUP -------------------------------------*/ +/******************************************************************************************/ + +/// PS2 enable/disable +#if defined(CFG_PS2) +#define PS2_SUPPORT 1 +#else +#define PS2_SUPPORT 0 +#endif //CFG_PS2 + +/******************************************************************************************/ +/* -------------------------- GAIA SETUP -------------------------------------*/ +/******************************************************************************************/ + +/// GAIA enable/disable +#if defined(CFG_GAIA) +#define GAIA_SUPPORT 1 +#else +#define GAIA_SUPPORT 0 +#endif //CFG_GAIA + +/******************************************************************************************/ +/* -------------------------- TRACER SETUP -------------------------------------*/ +/******************************************************************************************/ + +/// tracer enable/disable +#if defined(CFG_TRC_EN) + #define TRACER_PRESENT 1 + #include "dbg_trc_config.h" +#else + #define TRACER_PRESENT 0 +#endif // CFG_TRC_EN + +/******************************************************************************************/ +/* ------------------------- DEEP SLEEP SETUP -------------------------------------*/ +/******************************************************************************************/ + +/// Use 32K Hz Clock if set to 1 else 32,768k is used +#define HZ32000 (GAIA_SUPPORT) + +/// Time to wake-up Radio Module (in us) +#define SLEEP_RM_WAKEUP_DELAY 625 +/// Time for stabilization of the high frequency oscillator following a sleep-timer expiry (in us) +#define SLEEP_OSC_NORMAL_WAKEUP_DELAY 5000 +/// Time for stabilization of the high frequency oscillator following an external wake-up request (in us) +#define SLEEP_OSC_EXT_WAKEUP_DELAY 5000 + +/******************************************************************************************/ +/* -------------------------- BASEBAND SETUP -------------------------------------*/ +/******************************************************************************************/ + +/// Default programming delay, margin for programming the baseband in advance of each activity (in half-slots) +#define IP_PROG_DELAY_DFT (6) + +/** + * Prefetch time (in us) + * - Radio power up: 110us (worst case) + * - EM fetch: 30us (worst case at 26Mhz) + * - HW logic: 10us (worst case at 26Mhz) + */ +#define IP_PREFETCH_TIME_US (150) + +/** + * Prefetch Abort time (in us) + * + * - EM fetch: + * - HW CS Update is 18 access + * - HW Tx Desc Update is 1 access + * - HW Rx Desc Update is 5 access + * => EM update at 26MHz Tx, Rx and CS is (18+1+5)*0.04*4 = 4us + * - HW logic: 10us (worst case) + * - Radio power down: 26 us for Ripple + * + * Prefetch abort time = prefetch time + 4 + 10 + 26 + */ +#define IP_PREFETCHABORT_TIME_US (190) + +/******************************************************************************************/ +/* -------------------------- RADIO SETUP ----------------------------------------*/ +/******************************************************************************************/ + +/// Power control features +#define RF_TXPWR 1 +/// Class of device +#define RF_CLASS1 0 + + +/******************************************************************************************/ +/* -------------------------- BEKEN TEST SETUP -------------------------------------*/ +/******************************************************************************************/ +#if defined(CFG_USER_APP) + #define BEKEN_TASK_ENABLE 1 +#else + #define BEKEN_TASK_ENABLE 0 +#endif // CFG_USER_APP + + + +/******************************************************************************************/ +/* ------------------------- SUPPORTED RADIO PHY ------------------------------------*/ +/******************************************************************************************/ + +#if defined(CFG_RF_ATLAS) +#define BLE_PHY_1MBPS_SUPPORT 1 +#define BLE_PHY_2MBPS_SUPPORT 1 +#define BLE_PHY_CODED_SUPPORT 1 +#define BLE_STABLE_MOD_IDX_TX_SUPPORT 0 +#define BLE_STABLE_MOD_IDX_RX_SUPPORT 0 +#elif defined(CFG_RF_BTIPT) +#define BLE_PHY_1MBPS_SUPPORT 1 +#define BLE_PHY_2MBPS_SUPPORT 1 +#define BLE_PHY_CODED_SUPPORT 1 +#define BLE_STABLE_MOD_IDX_TX_SUPPORT 0 +#define BLE_STABLE_MOD_IDX_RX_SUPPORT 0 +#elif defined(CFG_RF_EXTRC) +#define BLE_PHY_1MBPS_SUPPORT 1 +#define BLE_PHY_2MBPS_SUPPORT 1 +#define BLE_PHY_CODED_SUPPORT 1 +#define BLE_STABLE_MOD_IDX_TX_SUPPORT 0 +#define BLE_STABLE_MOD_IDX_RX_SUPPORT 0 +#else // RIPPLE +#define BLE_PHY_1MBPS_SUPPORT 1 +#define BLE_PHY_2MBPS_SUPPORT 0 +#define BLE_PHY_CODED_SUPPORT 1 +#define BLE_STABLE_MOD_IDX_TX_SUPPORT 0 +#define BLE_STABLE_MOD_IDX_RX_SUPPORT 0 +#endif + +/******************************************************************************************/ +/* ------------------------- COEXISTENCE SETUP ------------------------------------*/ +/******************************************************************************************/ + +/// WLAN Coexistence +#if defined(CFG_WLAN_COEX) + #define RW_WLAN_COEX 1 + #define RW_WLAN_COEX_TEST (defined(CFG_WLAN_COEX_TEST)) +#else + #define RW_WLAN_COEX 0 + #define RW_WLAN_COEX_TEST 0 +#endif // defined(CFG_WLAN_COEX) + +/// MWS Coexistence +#if defined(CFG_MWS_COEX) + #define RW_MWS_COEX 1 + #define RW_MWS_COEX_TEST (defined(CFG_MWS_COEX_TEST)) +#else + #define RW_MWS_COEX 0 + #define RW_MWS_COEX_TEST 0 +#endif // defined(CFG_MWS_COEX) + +/******************************************************************************************/ +/* ----------------------- SLOT AVAILABILITY MASKS -----------------------------------*/ +/******************************************************************************************/ + +/// Maximum support peer SAM map size +#define RW_MAX_PEER_SAM_MAP_SLOTS (256) +#define RW_PEER_SAM_MAP_MAX_LEN (RW_MAX_PEER_SAM_MAP_SLOTS/4) // 2-bit field per slot + +/******************************************************************************************/ +/* -------------------- SECURE CONNECTIONS SETUP --------------------------------------*/ +/******************************************************************************************/ +#if defined(CFG_ECC_16_BITS_ALGO) +#define ECC_MULT_ALGO_TYPE (16) +#else // !defined(CFG_ECC_16_BITS_ALGO) +#define ECC_MULT_ALGO_TYPE (32) +#endif // defined(CFG_ECC_16_BITS_ALGO) +#if defined(CFG_CRYPTO_UT) +#define CRYPTO_UT (1) +#else //defined(CFG_CRYPTO_UT) +#define CRYPTO_UT (0) +#endif //defined(CFG_CRYPTO_UT) + +/******************************************************************************************/ +/* -------------------------- DEBUG SETUP ----------------------------------------*/ +/******************************************************************************************/ + +/// Flag indicating if debug mode is activated or not +#if defined(CFG_BLE_DBG) + #define RW_DEBUG ((BLE_EMB_PRESENT) || (BT_EMB_PRESENT) || (BLE_HOST_PRESENT)) +#if (BLE_EMB_PRESENT || BT_EMB_PRESENT) + #define RW_SWDIAG 1 +#else + #define RW_SWDIAG 0 +#endif + #define KERNEL_PROFILING 1 +#else + #define RW_DEBUG 0 + #define RW_SWDIAG 0 + #define KERNEL_PROFILING 0 +#endif /* CFG_DBG */ + +/// Flag indicating if Read/Write memory commands are supported or not +#if defined(CFG_DBG_MEM) + #define RW_DEBUG_MEM 1 +#else //CFG_DBG_MEM + #define RW_DEBUG_MEM 0 +#endif //CFG_DBG_MEM + +/// Flag indicating if Flash debug commands are supported or not +#if defined(CFG_DBG_FLASH) + #define RW_DEBUG_FLASH 1 +#else //CFG_DBG_FLASH + #define RW_DEBUG_FLASH 0 +#endif //CFG_DBG_FLASH + +/// Flag indicating if CPU stack profiling commands are supported or not +#if defined(CFG_DBG_STACK_PROF) + #define RW_DEBUG_STACK_PROF 1 +#else + #define RW_DEBUG_STACK_PROF 0 +#endif // defined (CFG_DBG_STACK_PROF) + +/// Scheduling Planner unit test (HCI debug commands to test scheduling planner functions) +#define SCH_PLAN_UT (1) + +/// BLE I&Q sample Generator control interface +#define BLE_IQ_GEN (RW_DEBUG && (BLE_CON_CTE_REQ | BLE_CONLESS_CTE_RX)) + + +/******************************************************************************************/ +/* -------------------------- VS SETUP --------------------------------------*/ +/******************************************************************************************/ + +/// Read piconnect clock +#if defined (CFG_BT_READ_PICONET_CLOCK) +#define BT_READ_PICONET_CLOCK 1 +#else +#define BT_READ_PICONET_CLOCK 0 +#endif //defined (CFG_BT_READ_PICONET_CLOCK) + +/******************************************************************************************/ +/* -------------------------- NVDS SETUP --------------------------------------*/ +/******************************************************************************************/ + +/// Flag indicating if NVDS feature is supported or not +#if defined(CFG_NVDS) + #define NVDS_SUPPORT 1 +#else //CFG_DBG_NVDS + #define NVDS_SUPPORT 0 +#endif //CFG_DBG_NVDS + +/******************************************************************************************/ +/* -------------------------- MISC SETUP --------------------------------------*/ +/******************************************************************************************/ +/// Manufacturer: RivieraWaves SAS +#define RW_COMP_ID 0x0060 + +/// Bluetooth technologies version +#define RW_BT40_VERSION (6) +#define RW_BT41_VERSION (7) +#define RW_BT42_VERSION (8) +#define RW_BT50_VERSION (9) +#define RW_BT51_VERSION (10) + +/******************************************************************************************/ +/* ------------------------- BT / BLE / BLE HL CONFIG -------------------------------*/ +/******************************************************************************************/ + +#if (BT_EMB_PRESENT) +#include "rwbt_config.h" // bt stack configuration +#endif //BT_EMB_PRESENT + +#if (BLE_EMB_PRESENT) +#include "rwble_config.h" // ble stack configuration +#endif //BLE_EMB_PRESENT + +#if (BLE_HOST_PRESENT) +#include "rwble_hl_config.h" // ble Host stack configuration +#endif //BLE_HOST_PRESENT + +#if defined(CFG_APP) +#include "rwapp_config.h" // Application configuration +#endif // defined(CFG_APP) + + + +/******************************************************************************************/ +/* ------------------------- KERNEL SETUP -------------------------------------*/ +/******************************************************************************************/ + +/// Event types definition +/*@TRACE*/ +enum KERNEL_EVENT_TYPE +{ + #if RTC_SUPPORT + KERNEL_EVENT_RTC_1S_TICK, + #endif //RTC_SUPPORT + + #if BLE_RSA + KERNEL_EVENT_RSA_SIGN, + #endif //BLE_RSA + + KERNEL_EVENT_ECC_MULTIPLICATION, + + #if BT_EMB_PRESENT + KERNEL_EVENT_P192_PUB_KEY_GEN, + #endif // BT_EMB_PRESENT + + #if (BLE_MESH) + KERNEL_EVENT_BLE_MESH_DJOB , + #endif // (BLE_MESH) + + #if (BLE_EMB_PRESENT || BT_EMB_PRESENT) + KERNEL_EVENT_AES_END, + #endif // (BLE_EMB_PRESENT || BT_EMB_PRESENT) + + KERNEL_EVENT_KERNEL_MESSAGE, + KERNEL_EVENT_KERNEL_TIMER, + + #if (TRACER_PRESENT) + KERNEL_EVENT_TRC, + #endif /*(TRACER_PRESENT)*/ + + #if H4TL_SUPPORT + KERNEL_EVENT_H4TL_TX, + #if (BLE_EMB_PRESENT || BT_EMB_PRESENT) + KERNEL_EVENT_H4TL_CMD_HDR_RX, + KERNEL_EVENT_H4TL_CMD_PLD_RX, + #endif //(BLE_EMB_PRESENT || BT_EMB_PRESENT) + #if (((BLE_EMB_PRESENT || BLE_HOST_PRESENT) && (BLE_CENTRAL || BLE_PERIPHERAL)) || BT_EMB_PRESENT) + KERNEL_EVENT_H4TL_ACL_HDR_RX, + #endif //(((BLE_EMB_PRESENT || BLE_HOST_PRESENT) && (BLE_CENTRAL || BLE_PERIPHERAL)) || BT_EMB_PRESENT) + #endif //H4TL_SUPPORT + + #if (BLE_HOST_PRESENT) + #if (BLE_L2CC) + KERNEL_EVENT_L2CAP_TX, + #endif //(BLE_L2CC) + #endif// (BLE_HOST_PRESENT) + + #if BT_EMB_PRESENT + KERNEL_EVENT_BT_PSCAN_PROC, + #endif //BT_EMB_PRESENT + + #if (BLE_ISOOHCI) + KERNEL_EVENT_ISOOHCI_IN_DEFER, + KERNEL_EVENT_ISOOHCI_OUT_DEFER, + #endif //(BLE_ISOOHCI) + + #if(BEKEN_TASK_ENABLE) + KERNEL_EVENT_BEKEN_TEST, + #endif + + KERNEL_EVENT_MAX, +}; + +/// Tasks types definition +/*@TRACE*/ +enum KERNEL_TASK_TYPE +{ + #if (BT_EMB_PRESENT) + // BT Controller Tasks + TASK_BLE_LM, + TASK_BLE_LC, + TASK_BLE_LB, + #endif // (BT_EMB_PRESENT) + + #if (BLE_EMB_PRESENT) + // Link Layer Tasks + TASK_BLE_LLM, + TASK_BLE_LLC, + #if (BLE_ISO_PRESENT) + TASK_BLE_LLI, + #endif // (BLE_ISO_PRESENT) + #endif // (BLE_EMB_PRESENT) + +#if ((BLE_EMB_PRESENT) || (BT_EMB_PRESENT)) + TASK_BLE_DBG, +#endif // ((BLE_EMB_PRESENT) || (BT_EMB_PRESENT)) + +#if (BLE_APP_PRESENT) + TASK_BLE_APP, +#endif // (BLE_APP_PRESENT) + +#if (BLE_HOST_PRESENT) + TASK_BLE_L2CC, // L2CAP Controller Task + TASK_BLE_GATTM, // Generic Attribute Profile Manager Task + TASK_BLE_GATTC, // Generic Attribute Profile Controller Task + TASK_BLE_GAPM, // Generic Access Profile Manager + TASK_BLE_GAPC, // Generic Access Profile Controller + + // allocate a certain number of profiles task + TASK_BLE_PRF_MAX = (TASK_BLE_GAPC + BLE_NB_PROFILES), + + #if (BLE_ISO_MODE_0_PROTOCOL) + TASK_BLE_AM0, // BLE Audio Mode 0 Task + #endif // (BLE_ISO_MODE_0_PROTOCOL) +#endif // (BLE_HOST_PRESENT) + +#if (AHI_TL_SUPPORT) + TASK_BLE_AHI, +#endif // (AHI_TL_SUPPORT) + + #if(BEKEN_TASK_ENABLE) + TASK_BLE_BEKEN, + #endif + + /// Maximum number of tasks + TASK_BLE_MAX, + + TASK_BLE_NONE = 0xFF, +}; + +/// Kernel memory heaps types. +/*@TRACE*/ +enum KERNEL_MEM_HEAP +{ + /// Memory allocated for environment variables + KERNEL_MEM_ENV, + #if (BLE_HOST_PRESENT) + /// Memory allocated for Attribute database + KERNEL_MEM_ATT_DB, + #endif // (BLE_HOST_PRESENT) + /// Memory allocated for kernel messages + KERNEL_MEM_KERNEL_MSG, + /// Non Retention memory block + KERNEL_MEM_NON_RETENTION, + KERNEL_MEM_BLOCK_MAX, +}; + + + +#if (BT_EMB_PRESENT) +#define BT_HEAP_MSG_SIZE_ BT_HEAP_MSG_SIZE +#define BT_HEAP_ENV_SIZE_ BT_HEAP_ENV_SIZE +#else +#define BT_HEAP_MSG_SIZE_ 0 +#define BT_HEAP_ENV_SIZE_ 0 +#endif //BT_EMB_PRESENT + +#if (BLE_EMB_PRESENT) +#define BLE_HEAP_MSG_SIZE_ BLE_HEAP_MSG_SIZE +#define BLE_HEAP_ENV_SIZE_ BLE_HEAP_ENV_SIZE +#else +#define BLE_HEAP_MSG_SIZE_ 0 +#define BLE_HEAP_ENV_SIZE_ 0 +#endif //BLE_EMB_PRESENT + +#if (BLE_HOST_PRESENT) + +#define BLEHL_HEAP_MSG_SIZE_ BLEHL_HEAP_MSG_SIZE +#define BLEHL_HEAP_ENV_SIZE_ BLEHL_HEAP_ENV_SIZE +#define BLEHL_HEAP_DB_SIZE_ BLEHL_HEAP_DB_SIZE +#else +#define BLEHL_HEAP_MSG_SIZE_ 0 +#define BLEHL_HEAP_ENV_SIZE_ 0 +#define BLEHL_HEAP_DB_SIZE_ 0 +#endif //BLE_HOST_PRESENT + +#if (BT_EMB_PRESENT || BLE_EMB_PRESENT) +#define ECC_HEAP_NON_RET_SIZE_ (328*2) // Could only have 2 ECC computations simultaneously +#else // (BT_EMB_PRESENT || BLE_EMB_PRESENT) +#define ECC_HEAP_NON_RET_SIZE_ 0 +#endif // (BT_EMB_PRESENT || BLE_EMB_PRESENT) + +/// Kernel Message Heap +#define RWIP_HEAP_MSG_SIZE ( BT_HEAP_MSG_SIZE_ + \ + BLE_HEAP_MSG_SIZE_ + \ + BLEHL_HEAP_MSG_SIZE_ ) + +/// Size of Environment heap +#define RWIP_HEAP_ENV_SIZE ( BT_HEAP_ENV_SIZE_ + \ + BLE_HEAP_ENV_SIZE_ + \ + BLEHL_HEAP_ENV_SIZE_ ) + + +/// Size of Attribute database heap +#define RWIP_HEAP_DB_SIZE ( BLEHL_HEAP_DB_SIZE_ ) + +/** + * Size of non-retention heap + * + * This heap can be used to split the RAM into 2 parts: + * - an always-on part that can handle a certain number of links + * - a secondary memory that could be powered-off when not used, and retained only when used + * + * With such mechanism, the previous heaps need to be reduced so that they can contain all required data + * in a light scenario (few connections, few profiles). Then the non-retention heap is sized in order to + * cover the worst case scenario (max connections, max profiles, etc ...) + * + * The current size show what is already known as not needing to be retained during deep sleep. + */ +#define RWIP_HEAP_NON_RET_SIZE ( ECC_HEAP_NON_RET_SIZE_ ) + +/// Minimum sleep time to enter in deep sleep (in half slot). +#define RWIP_MINIMUM_SLEEP_TIME (6) + +/******************************************************************************************/ +/* ------------------------- CONFIGURABLE PARAMETERS -----------------------------*/ +/******************************************************************************************/ + +/// Bit field definitions for channel assessment enable parameter +enum param_ch_ass_en +{ + /// Indicate channel assessment enabled for BLE + CH_ASS_EN_BLE_POS = 0, + CH_ASS_EN_BLE_BIT = (0x1), + /// Indicate channel assessment enabled for BT + CH_ASS_EN_BT_POS = 1, + CH_ASS_EN_BT_BIT = (0x2), +}; + +/// List of parameters identifiers +enum PARAM_ID +{ + /// Definition of the tag associated to each parameters + /// Local Bd Address + PARAM_ID_BD_ADDRESS = 0x01, + /// Device Name + PARAM_ID_DEVICE_NAME = 0x02, + /// Radio Drift + PARAM_ID_LPCLK_DRIFT = 0x07, + /// Radio Jitter + PARAM_ID_LPCLK_JITTER = 0x08, + /// External wake-up time + PARAM_ID_EXT_WAKEUP_TIME = 0x0D, + /// Oscillator wake-up time + PARAM_ID_OSC_WAKEUP_TIME = 0x0E, + /// Radio wake-up time + PARAM_ID_RM_WAKEUP_TIME = 0x0F, + /// UART baudrate + PARAM_ID_UART_BAUDRATE = 0x10, + /// Enable sleep mode + PARAM_ID_SLEEP_ENABLE = 0x11, + /// Enable External Wakeup + PARAM_ID_EXT_WAKEUP_ENABLE = 0x12, + /// SP Private Key 192 + PARAM_ID_SP_PRIVATE_KEY_P192 = 0x13, + /// SP Public Key 192 + PARAM_ID_SP_PUBLIC_KEY_P192 = 0x14, + + /// Activity Move Configuration (enables/disables activity move for BLE connections and BT (e)SCO links) + PARAM_ID_ACTIVITY_MOVE_CONFIG = 0x15, + + /// Enable/disable scanning for extended advertising PDUs + PARAM_ID_SCAN_EXT_ADV = 0x16, + + /// Duration of the schedule reservation for long activities such as scan, inquiry, page, HDC advertising + PARAM_ID_SCHED_SCAN_DUR = 0x17, + + /// Programming delay, margin for programming the baseband in advance of each activity (in half-slots) + PARAM_ID_PROG_DELAY = 0x18, + + /// Enable/disable channel assessment for BT and/or BLE + PARAM_ID_CH_ASS_EN = 0x19, + + /// Synchronous links configuration + PARAM_ID_SYNC_CONFIG = 0x2C, + /// PCM Settings + PARAM_ID_PCM_SETTINGS = 0x2D, + /// Sleep algorithm duration + PARAM_ID_SLEEP_ALGO_DUR = 0x2E, + /// Tracer configuration + PARAM_ID_TRACER_CONFIG = 0x2F, + + /// Diagport configuration + PARAM_ID_DIAG_BT_HW = 0x30, + PARAM_ID_DIAG_BLE_HW = 0x31, + PARAM_ID_DIAG_SW = 0x32, + PARAM_ID_DIAG_DM_HW = 0x33, + PARAM_ID_DIAG_PLF = 0x34, + + /// IDC selection (for audio demo) + PARAM_ID_IDCSEL_PLF = 0x37, + + /// RSSI threshold tags + PARAM_ID_RSSI_HIGH_THR = 0x3A, + PARAM_ID_RSSI_LOW_THR = 0x3B, + PARAM_ID_RSSI_INTERF_THR = 0x3C, + + /// RF BTIPT + PARAM_ID_RF_BTIPT_VERSION = 0x3E, + PARAM_ID_RF_BTIPT_XO_SETTING = 0x3F, + PARAM_ID_RF_BTIPT_GAIN_SETTING = 0x40, + + PARAM_ID_BT_LINK_KEY_FIRST = 0x60, + PARAM_ID_BT_LINK_KEY_LAST = 0x67, + + PARAM_ID_BLE_LINK_KEY_FIRST = 0x70, + PARAM_ID_BLE_LINK_KEY_LAST = 0x7F, + /// SC Private Key (Low Energy) + PARAM_ID_LE_PRIVATE_KEY_P256 = 0x80, + /// SC Public Key (Low Energy) + PARAM_ID_LE_PUBLIC_KEY_P256 = 0x81, + /// SC Debug: Used Fixed Private Key from NVDS (Low Energy) + PARAM_ID_LE_DBG_FIXED_P256_KEY = 0x82, + /// SP Private Key (classic BT) + PARAM_ID_SP_PRIVATE_KEY_P256 = 0x83, + /// SP Public Key (classic BT) + PARAM_ID_SP_PUBLIC_KEY_P256 = 0x84, + + /// LE Coded PHY 500 Kbps selection + PARAM_ID_LE_CODED_PHY_500 = 0x85, + + /// Application specific + PARAM_ID_APP_SPECIFIC_FIRST = 0x90, + PARAM_ID_APP_SPECIFIC_LAST = 0xAF, + + /// Mesh NVDS values + PARAM_ID_MESH_SPECIFIC_FIRST = 0xB0, + PARAM_ID_MESH_SPECIFIC_LAST = 0xF0, +}; + +/// List of parameters lengths +enum PARAM_LEN +{ + // Definition of length associated to each parameters + /// Local Bd Address + PARAM_LEN_BD_ADDRESS = 6, + /// Device Name + PARAM_LEN_DEVICE_NAME = 248, + /// Low power clock drift + PARAM_LEN_LPCLK_DRIFT = 2, + /// Low power clock jitter + PARAM_LEN_LPCLK_JITTER = 1, + /// External wake-up time + PARAM_LEN_EXT_WAKEUP_TIME = 2, + /// Oscillator wake-up time + PARAM_LEN_OSC_WAKEUP_TIME = 2, + /// Radio wake-up time + PARAM_LEN_RM_WAKEUP_TIME = 2, + /// UART baudrate + PARAM_LEN_UART_BAUDRATE = 4, + /// Enable sleep mode + PARAM_LEN_SLEEP_ENABLE = 1, + /// Enable External Wakeup + PARAM_LEN_EXT_WAKEUP_ENABLE = 1, + /// SP Private Key 192 + PARAM_LEN_SP_PRIVATE_KEY_P192 = 24, + /// SP Public Key 192 + PARAM_LEN_SP_PUBLIC_KEY_P192 = 48, + + /// Activity Move Configuration + PARAM_LEN_ACTIVITY_MOVE_CONFIG = 1, + + /// Enable/disable scanning for extended advertising PDUs + PARAM_LEN_SCAN_EXT_ADV = 1, + + /// Duration of the schedule reservation for long activities such as scan, inquiry, page, HDC advertising + PARAM_LEN_SCHED_SCAN_DUR = 2, + + /// Programming delay, margin for programming the baseband in advance of each activity (in half-slots) + PARAM_LEN_PROG_DELAY = 1, + + /// Enable/disable channel assessment for BT and/or BLE + PARAM_LEN_CH_ASS_EN = 1, + + /// Synchronous links configuration + PARAM_LEN_SYNC_CONFIG = 2, + /// PCM Settings + PARAM_LEN_PCM_SETTINGS = 8, + /// Tracer configuration + PARAM_LEN_TRACER_CONFIG = 4, + + /// Diagport configuration + PARAM_LEN_DIAG_BT_HW = 4, + PARAM_LEN_DIAG_BLE_HW = 4, + PARAM_LEN_DIAG_SW = 4, + PARAM_LEN_DIAG_DM_HW = 4, + PARAM_LEN_DIAG_PLF = 4, + + /// IDC selection (for audio demo) + PARAM_LEN_IDCSEL_PLF = 4, + + /// RSSI thresholds + PARAM_LEN_RSSI_THR = 1, + + /// RF BTIPT + PARAM_LEN_RF_BTIPT_VERSION = 1, + PARAM_LEN_RF_BTIPT_XO_SETTING = 1, + PARAM_LEN_RF_BTIPT_GAIN_SETTING = 2, + + /// Link keys + PARAM_LEN_BT_LINK_KEY = 22, + PARAM_LEN_BLE_LINK_KEY = 48, + + /// P256 + PARAM_LEN_PRIVATE_KEY_P256 = 32, + PARAM_LEN_PUBLIC_KEY_P256 = 64, + PARAM_LEN_DBG_FIXED_P256_KEY = 1, + + /// LE Coded PHY 500 Kbps selection + PARAM_LEN_LE_CODED_PHY_500 = 1, +}; + +/******************************************************************************************/ +/* ------------------------- BT-BLE COEX -----------------------------------*/ +/******************************************************************************************/ + +///To let the HW using the default values set in the registers +#define RW_BLE_PTI_PRIO_AUTO 15 + +#if (BLE_EMB_PRESENT || BT_EMB_PRESENT) +/// Enable and diable definition for the PTI +///Enable TX busy signal +#define RWIP_PTI_TXEN 1 +///Disable TX busy signal +#define RWIP_PTI_TXDIS 0 +/// Tx busy position +#define RWIP_TXBSY_POS 0 + +///Enable RX busy signal +#define RWIP_PTI_RXEN 1 +///Disable RX busy signal +#define RWIP_PTI_RXDIS 0 +/// Rx busy position +#define RWIP_RXBSY_POS 1 + +///Enable do not abort TX +#define RWIP_PTI_DNABORTEN 1 +///Disable do not abort TX +#define RWIP_PTI_DNABORTDIS 0 +/// Do not abort busy position +#define RWIP_DNABORT_POS 2 + +/// SAM disabled +#define RWIP_SAM_DIS 0 +/// SAM enabled +#define RWIP_SAM_EN 1 +/// SAM enable position +#define RWIP_SAMEN_POS 3 + +/// Bit masking +#define RWIP_COEX_BIT_MASK 1 + +/// Coex configuration index +enum rwip_coex_config_idx +{ + #if (BT_EMB_PRESENT) + RWIP_COEX_MSSWITCH_IDX, + RWIP_COEX_SNIFFATT_IDX, + RWIP_COEX_PAGE_IDX, + RWIP_COEX_PSCAN_IDX, + RWIP_COEX_INQ_IDX, + RWIP_COEX_INQRES_IDX, + RWIP_COEX_SCORSVD_IDX, + RWIP_COEX_BCAST_IDX, + RWIP_COEX_CONNECT_IDX, + #endif //#if (BT_EMB_PRESENT) + #if (BLE_EMB_PRESENT) + RWIP_COEX_CON_IDX, + RWIP_COEX_CON_DATA_IDX, + RWIP_COEX_ADV_IDX, + RWIP_COEX_SCAN_IDX, + RWIP_COEX_INIT_IDX, + #endif // #if (BLE_EMB_PRESENT) + /// Max configuration index + RWIP_COEX_CFG_MAX, +}; +#endif //(BLE_EMB_PRESENT || BT_EMB_PRESENT) + +/******************************************************************************************/ +/* ------------------------- BT-BLE PRIORITIES -----------------------------------*/ +/******************************************************************************************/ +#if (BLE_EMB_PRESENT || BT_EMB_PRESENT) +/// Priority index definition +enum rwip_prio_idx +{ + #if (BT_EMB_PRESENT) + /// ACL event default priority + RWIP_PRIO_ACL_DFT_IDX, + /// ACL event priority with activity + RWIP_PRIO_ACL_ACT_IDX, + /// ACL Role Switch event default priority + RWIP_PRIO_ACL_RSW_IDX, + /// ACL sniff event default priority + RWIP_PRIO_ACL_SNIFF_DFT_IDX, + /// ACL sniff transition event default priority + RWIP_PRIO_ACL_SNIFF_TRANS_IDX, + #if MAX_NB_SYNC + /// SCO event default priority + RWIP_PRIO_SCO_DFT_IDX, + #endif //MAX_NB_SYNC + /// Broadcast ACL event default priority + RWIP_PRIO_BCST_DFT_IDX, + /// Broadcast ACL event with LMP activity priority + RWIP_PRIO_BCST_ACT_IDX, + /// CSB RX event default priority + RWIP_PRIO_CSB_RX_DFT_IDX, + /// CSB TX event default priority + RWIP_PRIO_CSB_TX_DFT_IDX, + /// Inquiry event default priority + RWIP_PRIO_INQ_DFT_IDX, + /// Inquiry Scan event default priority + RWIP_PRIO_ISCAN_DFT_IDX, + /// Page event default priority + RWIP_PRIO_PAGE_DFT_IDX, + /// Page event default priority + RWIP_PRIO_PAGE_1ST_PKT_IDX, + /// Page first packet event default priority + RWIP_PRIO_PCA_DFT_IDX, + /// Page scan event default priority + RWIP_PRIO_PSCAN_DFT_IDX, + /// Page scan event priority increment when canceled + RWIP_PRIO_PSCAN_1ST_PKT_IDX, + /// Synchronization Scan event default priority + RWIP_PRIO_SSCAN_DFT_IDX, + /// Synchronization Train event default priority + RWIP_PRIO_STRAIN_DFT_IDX, + #endif //#if (BT_EMB_PRESENT) + #if (BLE_EMB_PRESENT) + /// Default priority for scanning events + RWIP_PRIO_SCAN_IDX, + /// Default priority for auxillary scan/init (no_asap) rx events + RWIP_PRIO_AUX_RX_IDX, + /// Default priority for periodic adv rx events + RWIP_PRIO_PER_ADV_RX_DFT_IDX, + /// Default priority for initiating events + RWIP_PRIO_INIT_IDX, + /// LE connection events default priority + RWIP_PRIO_CONNECT_DFT_IDX, + /// LE connection events priority with activity + RWIP_PRIO_CONNECT_ACT_IDX, + /// Default priority for advertising events + RWIP_PRIO_ADV_IDX, + /// Default priority for advertising high duty cycle events + RWIP_PRIO_ADV_HDC_IDX, + /// Default priority for aux advertising events + RWIP_PRIO_ADV_AUX_IDX, + /// Default priority for periodic advertising events + RWIP_PRIO_PER_ADV_IDX, + /// Default priority for resolvable private addresses renewal event + RWIP_PRIO_RPA_RENEW_IDX, + #endif // #if (BLE_EMB_PRESENT) + RWIP_PRIO_IDX_MAX +}; +/// Default priority value definition +enum rwip_prio_dft +{ + #if (BT_EMB_PRESENT) + /// ACL event default priority + RWIP_PRIO_ACL_DFT = 5, + /// ACL event priority with activity + RWIP_PRIO_ACL_ACT = 10, + /// ACL Role Switch event default priority + RWIP_PRIO_ACL_RSW = 20, + /// ACL sniff event default priority + RWIP_PRIO_ACL_SNIFF_DFT = 15, + /// ACL sniff transition event default priority + RWIP_PRIO_ACL_SNIFF_TRANS = 10, + #if MAX_NB_SYNC + /// SCO event default priority + RWIP_PRIO_SCO_DFT = 18, + #endif //MAX_NB_SYNC + /// Broadcast ACL event default priority + RWIP_PRIO_BCST_DFT = 5, + /// Broadcast ACL event with LMP activity priority + RWIP_PRIO_BCST_ACT = 10, + /// CSB RX event default priority + RWIP_PRIO_CSB_RX_DFT = 10, + /// CSB TX event default priority + RWIP_PRIO_CSB_TX_DFT = 10, + /// Inquiry event default priority + RWIP_PRIO_INQ_DFT = 5, + /// Inquiry Scan event default priority + RWIP_PRIO_ISCAN_DFT = 5, + /// Page event default priority + RWIP_PRIO_PAGE_DFT = 8, + /// Page first packet event default priority + RWIP_PRIO_PAGE_1ST_PKT = 20, + /// PCA event default priority + RWIP_PRIO_PCA_DFT = 20, + /// Page scan event default priority + RWIP_PRIO_PSCAN_DFT = 8, + /// Page scan event priority increment when canceled + RWIP_PRIO_PSCAN_1ST_PKT = 20, + /// Synchronization Scan event default priority + RWIP_PRIO_SSCAN_DFT = 10, + /// Synchronization Train event default priority + RWIP_PRIO_STRAIN_DFT = 10, + #endif //#if (BT_EMB_PRESENT) + #if (BLE_EMB_PRESENT) + /// Default priority for scanning events + RWIP_PRIO_SCAN_DFT = 5, + /// Default priority for auxillary scan/init (no_asap) rx events + RWIP_PRIO_AUX_RX_DFT = 12, + /// Default priority for periodic adv rx events + RWIP_PRIO_PER_ADV_RX_DFT = 16, + /// Active priority for periodic adv rx events + RWIP_PRIO_INIT_DFT = 10, + /// LE connection events default priority + RWIP_PRIO_CONNECT_DFT = 14, + /// LE connection events priority with activity + RWIP_PRIO_CONNECT_ACT = 16, + /// Default priority for advertising events + RWIP_PRIO_ADV_DFT = 5, + /// Default priority for advertising high duty cycle events + RWIP_PRIO_ADV_HDC_DFT = 10, + /// Default priority for aux advertising events + RWIP_PRIO_ADV_AUX_DFT = 12, + /// Default priority for periodic advertising events + RWIP_PRIO_PER_ADV_DFT = 10, + /// Default priority for resolvable private addresses renewal event + RWIP_PRIO_RPA_RENEW_DFT = 10, + #endif // #if (BLE_EMB_PRESENT) + /// Max priority + RWIP_PRIO_MAX = 31, +}; +/// Default increment value definition +enum rwip_incr_dft +{ + #if (BT_EMB_PRESENT) + /// ACL event default increment + RWIP_INCR_ACL_DFT = 1, + /// ACL event increment with activity + RWIP_INCR_ACL_ACT = 1, + /// ACL Role Switch event default increment + RWIP_INCR_ACL_RSW = 1, + /// ACL sniff event default increment + RWIP_INCR_ACL_SNIFF_DFT = 1, + /// ACL sniff transition event default increment + RWIP_INCR_ACL_SNIFF_TRANS = 1, + #if MAX_NB_SYNC + /// SCO event default increment + RWIP_INCR_SCO_DFT = 1, + #endif //MAX_NB_SYNC + /// Broadcast ACL event default increment + RWIP_INCR_BCST_DFT = 1, + /// Broadcast ACL event with LMP activity increment + RWIP_INCR_BCST_ACT = 1, + /// CSB RX event default increment + RWIP_INCR_CSB_RX_DFT = 1, + /// CSB TX event default increment + RWIP_INCR_CSB_TX_DFT = 1, + /// Inquiry event default increment + RWIP_INCR_INQ_DFT = 1, + /// Inquiry Scan event default increment + RWIP_INCR_ISCAN_DFT = 1, + /// Page event default increment + RWIP_INCR_PAGE_DFT = 1, + /// Page event default increment + RWIP_INCR_PAGE_1ST_PKT = 2, + /// Page first packet event default increment + RWIP_INCR_PCA_DFT = 1, + /// Page scan event default increment + RWIP_INCR_PSCAN_DFT = 1, + /// Page scan event increment increment when canceled + RWIP_INCR_PSCAN_1ST_PKT = 1, + /// Synchronization Scan event default increment + RWIP_INCR_SSCAN_DFT = 1, + /// Synchronization Train event default increment + RWIP_INCR_STRAIN_DFT = 1, + #endif //#if (BT_EMB_PRESENT) + #if (BLE_EMB_PRESENT) + /// Default increment for scanning events + RWIP_INCR_SCAN_DFT = 1, + /// Default increment for auxillary scan/init (no_asap) rx events + RWIP_INCR_AUX_RX_DFT = 1, + /// Default increment for periodic adv rx events + RWIP_INCR_PER_ADV_RX_DFT = 1, + /// Default increment for initiating events + RWIP_INCR_INIT_DFT = 1, + /// LE connection events default increment + RWIP_INCR_CONNECT_DFT = 1, + /// LE connection events increment with activity + RWIP_INCR_CONNECT_ACT = 1, + /// Default increment for advertising events + RWIP_INCR_ADV_DFT = 1, + /// Default increment for advertising high duty cycle events + RWIP_INCR_ADV_HDC_PRIO_DFT = 1, + /// Default increment for aux advertising events + RWIP_INCR_ADV_AUX_DFT = 1, + /// Default increment for periodic advertising events + RWIP_INCR_PER_ADV_DFT = 1, + /// Default increment for resolvable private addresses renewal event + RWIP_INCR_RPA_RENEW_DFT = 1, + #endif // #if (BLE_EMB_PRESENT) +}; +#endif //#if (BLE_EMB_PRESENT || BT_EMB_PRESENT) +/// @} BT Stack Configuration +/// @} ROOT + +#endif //RWIP_CONFIG_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/config/rwprf_config.h b/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/config/rwprf_config.h new file mode 100755 index 0000000..aeee460 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/config/rwprf_config.h @@ -0,0 +1,87 @@ +/** + **************************************************************************************** + * + * @file rwprf_config.h + * + * @brief Header file - Profile Configuration + * + * Copyright (C) RivieraWaves 2009-2016 + * + **************************************************************************************** + */ + + +#ifndef _RWPRF_CONFIG_H_ +#define _RWPRF_CONFIG_H_ + + +/** + **************************************************************************************** + * @addtogroup PRF_CONFIG + * @ingroup PROFILE + * @brief Profile configuration + * + * @{ + **************************************************************************************** + */ +#include "rwip_config.h" + +//ATT DB,Testing and Qualification related flags +#if (BLE_CENTRAL || BLE_PERIPHERAL) + +#if (1) +#define CFG_PRF_COMM +#endif + +#if defined(CFG_PRF_COMM) +#define BLE_COMM_SERVER 1 +#else +#define BLE_COMM_SERVER 0 +#endif + +/// BLE_CLIENT_PRF indicates if at least one client profile is present +#if (BLE_PROX_MONITOR || BLE_FINDME_LOCATOR || BLE_HT_COLLECTOR || BLE_BP_COLLECTOR \ + || BLE_HR_COLLECTOR || BLE_DIS_CLIENT || BLE_TIP_CLIENT || BLE_SP_CLIENT \ + || BLE_BATT_CLIENT || BLE_GL_COLLECTOR || BLE_HID_BOOT_HOST || BLE_HID_REPORT_HOST \ + || BLE_RSC_COLLECTOR || BLE_CSC_COLLECTOR || BLE_CP_COLLECTOR || BLE_LN_COLLECTOR || BLE_AN_CLIENT \ + || BLE_PAS_CLIENT || BLE_IPS_CLIENT || BLE_ENV_CLIENT || BLE_WSC_CLIENT \ + || BLE_UDS_CLIENT || BLE_BCS_CLIENT || BLE_WPT_CLIENT || BLE_PLX_CLIENT \ + || BLE_CGM_CLIENT || BLE_DBG_THPP||BLE_ANCS_CLIENT) +#define BLE_CLIENT_PRF 1 +#else +#define BLE_CLIENT_PRF 0 +#endif // + +/// BLE_SERVER_PRF indicates if at least one server profile is present +#if (BLE_COMM_SERVER) +#define BLE_SERVER_PRF 1 +#else +#define BLE_SERVER_PRF 0 +#endif //BLE_COMM_SERVER + +//Force ATT parts depending on profile roles or compile options +/// Attribute Client +#if (BLE_CLIENT_PRF) +#define BLE_ATTC 1 +#endif //(BLE_CLIENT_PRF) + +/// Attribute Server +#if (BLE_SERVER_PRF) +#define BLE_ATTS 1 +#endif //(BLE_SERVER_PRF) + + +#elif (BLE_OBSERVER || BLE_BROADCASTER) +//Force ATT parts to 0 +/// External database management +#define BLE_EXT_ATTS_DB 0 +/// Profile Server +#define BLE_SERVER_PRF 0 +/// Profile Client +#define BLE_CLIENT_PRF 0 +#endif //(BLE_OBSERVER || BLE_BROADCASTER) + + +/// @} PRF_CONFIG + +#endif /* _RWPRF_CONFIG_H_ */ diff --git a/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/config/user_config.h b/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/config/user_config.h new file mode 100755 index 0000000..449f1db --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/config/user_config.h @@ -0,0 +1,63 @@ +/** + **************************************************************************************** + * + * @file user_config.h + * + * @brief Configuration of the BT function + * + * Copyright (C) Beken 2019 + * + **************************************************************************************** + */ +#ifndef USER_CONFIG_H_ +#define USER_CONFIG_H_ + +#include "uart_pub.h" + +#define VIRTUAL_UART_H4TL 1 +#define UART_PRINTF_ENABLE 1 +#define DEBUG_HW 0 +#define GPIO_DBG_MSG 0 +#define DEBUG_RF_REG 0 +#define LDO_MODE 0 + +//DRIVER CONFIG +#define UART0_DRIVER 1 +#define UART2_DRIVER 1 + +#define GPIO_DRIVER 0 +#define ADC_DRIVER 0 +#define I2C_DRIVER 0 +#define PWM_DRIVER 0 +#define USB_DRIVER 0 +#define SPI_DRIVER 0 +#define AON_RTC_DRIVER 1 + +#define uart_printf bk_printf +#define UART_PRINTF bk_printf + +/// Default Device Name +#define APP_DFLT_DEVICE_NAME ("BK7231N-BLE") +#define APP_DFLT_DEVICE_NAME_LEN (sizeof(APP_DFLT_DEVICE_NAME)) + +/// Advertising channel map - 37, 38, 39 +#define APP_ADV_CHMAP (0x07) +/// Advertising minimum interval - 40ms (64*0.625ms) +#define APP_ADV_INT_MIN (160 ) +/// Advertising maximum interval - 40ms (64*0.625ms) +#define APP_ADV_INT_MAX (160) +/// Fast advertising interval +#define APP_ADV_FAST_INT (32) + + +#define BLE_UAPDATA_MIN_INTVALUE 20 + +#define BLE_UAPDATA_MAX_INTVALUE 40 + +#define BLE_UAPDATA_LATENCY 0 + +#define BLE_UAPDATA_TIMEOUT 600 + +#endif // USER_CONFIG_H_ + + diff --git a/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/driver/reg/ble_reg_access.h b/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/driver/reg/ble_reg_access.h new file mode 100755 index 0000000..c131062 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/driver/reg/ble_reg_access.h @@ -0,0 +1,172 @@ +/** + **************************************************************************************** + * + * @file ble_reg_access.h + * + * @brief File implementing the basic primitives for register accesses + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef REG_ACCESS_H_ +#define REG_ACCESS_H_ + +/** + **************************************************************************************** + * @addtogroup REG REG_ACCESS + * @ingroup DRIVERS + * + * @brief Basic primitives for register access + * + * @{ + **************************************************************************************** + */ + + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include // string functions + +#include "common_utils.h" +#include "em_map.h" // EM Map + +#if defined(CFG_EMB) +/* + * DEFINES + **************************************************************************************** + */ + +/* + * MACROS + **************************************************************************************** + */ +/// Macro to read a platform register +#define REG_PL_RD(addr) (*(volatile uint32_t *)(addr)) + +/// Macro to write a platform register +#define REG_PL_WR(addr, value) (*(volatile uint32_t *)(addr)) = (value) + +/// Macro to read a common ip register +#define REG_IP_RD(addr) (*(volatile uint32_t *)(addr)) + +/// Macro to write a common ip register +#define REG_IP_WR(addr, value) (*(volatile uint32_t *)(addr)) = (value) + +/// Macro to read a BLE register +#define REG_BLE_RD(addr) (*(volatile uint32_t *)(addr)) + +/// Macro to write a BLE register +#define REG_BLE_WR(addr, value) (*(volatile uint32_t *)(addr)) = (value) + +/// Macro to read a BLE control structure field (16-bit wide) +#define EM_BLE_RD(addr) (*(volatile uint16_t *)(addr)) + +/// Macro to write a BLE control structure field (16-bit wide) +#define EM_BLE_WR(addr, value) (*(volatile uint16_t *)(addr)) = (value) + +/// Macro to read a BT register +#define REG_BT_RD(addr) (*(volatile uint32_t *)(addr)) + +/// Macro to write a BT register +#define REG_BT_WR(addr, value) (*(volatile uint32_t *)(addr)) = (value) + +/// Macro to read a INT register ////???? +#define REG_INT_RD(addr) (*(volatile uint32_t *)(addr)) + +/// Macro to write a INT register ////???? +#define REG_INT_WR(addr, value) (*(volatile uint32_t *)(addr)) = (value) + +/// Macro to read a BT control structure field (16-bit wide) +#define EM_BT_RD(addr) (*(volatile uint16_t *)(addr)) + +/// Macro to write a BT control structure field (16-bit wide) +#define EM_BT_WR(addr, value) (*(volatile uint16_t *)(addr)) = (value) + +/// Macro to read a EM field (16-bit wide) +#define EM_RD(addr) (*(volatile uint16_t *)(addr)) + +/// Macro to write a EM field (16-bit wide) +#define EM_WR(addr, value) (*(volatile uint16_t *)(addr)) = (value) + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +#if (defined(CFG_BT) || (defined(CFG_BLE) && defined(CFG_EMB))) +/// Read bytes from EM +__INLINE void em_rd(void *sys_addr, uint16_t em_addr, uint16_t len) +{ + memcpy(sys_addr, (void *)(em_addr + EM_BASE_ADDR), len); +} +/// Write bytes to EM +__INLINE void em_wr(void const *sys_addr, uint16_t em_addr, uint16_t len) +{ + memcpy((void *)(em_addr + EM_BASE_ADDR), sys_addr, len); +} + +// copy two exchange memory area +__INLINE void em_cpy(uint16_t dst_em_addr, uint16_t src_em_addr, uint16_t len) +{ + memcpy((void *)(dst_em_addr + EM_BASE_ADDR), (void *)(src_em_addr + EM_BASE_ADDR), len); +} + +/// Fill an EM space with the same value +__INLINE void em_set(int value, uint16_t em_addr, uint16_t len) +{ + memset((void *)(em_addr + EM_BASE_ADDR), value, len); +} + +/// Read 32-bits value from EM +__INLINE uint32_t em_rd32p(uint16_t em_addr) +{ + return common_read32p((void *)(em_addr + EM_BASE_ADDR)); +} +/// Write 32-bits value to EM +__INLINE void em_wr32p(uint16_t em_addr, uint32_t value) +{ + common_write32p((void *)(em_addr + EM_BASE_ADDR), value); +} + +/// Read 24-bits value from EM +__INLINE uint32_t em_rd24p(uint16_t em_addr) +{ + return common_read24p((void *)(em_addr + EM_BASE_ADDR)); +} +/// Write 24-bits value to EM +__INLINE void em_wr24p(uint16_t em_addr, uint32_t value) +{ + common_write24p((void *)(em_addr + EM_BASE_ADDR), value); +} + +/// Read 16-bits value from EM +__INLINE uint16_t em_rd16p(uint16_t em_addr) +{ + return common_read16p((void *)(em_addr + EM_BASE_ADDR)); +} +/// Write 16-bits value to EM +__INLINE void em_wr16p(uint16_t em_addr, uint16_t value) +{ + common_write16p((void *)(em_addr + EM_BASE_ADDR), value); +} + +/// Read 8-bits value from EM +__INLINE uint8_t em_rd8p(uint16_t em_addr) +{ + return *((uint8_t *)(em_addr + EM_BASE_ADDR)); +} +/// Write 8-bits value to EM +__INLINE void em_wr8p(uint16_t em_addr, uint8_t value) +{ + *(uint8_t *)(em_addr + EM_BASE_ADDR) = value; +} +#endif // (defined(CFG_BT) || (defined(CFG_BLE) && defined(CFG_EMB))) + +/// @} REG +#endif // defined(CFG_EMB) +#endif // REG_ACCESS_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/driver/rf/BK3633_RegList.h b/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/driver/rf/BK3633_RegList.h new file mode 100755 index 0000000..3cd7f16 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/driver/rf/BK3633_RegList.h @@ -0,0 +1,98 @@ +#ifndef _BK3633_REGLIST_H_ +#define _BK3633_REGLIST_H_ + +//************************************************************// +//XVR +//************************************************************// +#define BASEADDR_XVR (0x0080B400) + +#define BLE_XVR_REG00 (BASEADDR_XVR + 0x00 * 4) +#define BLE_XVR_REG01 (BASEADDR_XVR + 0x01 * 4) +#define BLE_XVR_REG02 (BASEADDR_XVR + 0x02 * 4) +#define BLE_XVR_REG03 (BASEADDR_XVR + 0x03 * 4) +#define BLE_XVR_REG04 (BASEADDR_XVR + 0x04 * 4) +#define BLE_XVR_REG05 (BASEADDR_XVR + 0x05 * 4) +#define BLE_XVR_REG06 (BASEADDR_XVR + 0x06 * 4) +#define BLE_XVR_REG07 (BASEADDR_XVR + 0x07 * 4) +#define BLE_XVR_REG08 (BASEADDR_XVR + 0x08 * 4) +#define BLE_XVR_REG09 (BASEADDR_XVR + 0x09 * 4) +#define BLE_XVR_REG0A (BASEADDR_XVR + 0x0A * 4) +#define BLE_XVR_REG0B (BASEADDR_XVR + 0x0B * 4) +#define BLE_XVR_REG0C (BASEADDR_XVR + 0x0C * 4) +#define BLE_XVR_REG0D (BASEADDR_XVR + 0x0D * 4) +#define BLE_XVR_REG0E (BASEADDR_XVR + 0x0E * 4) +#define BLE_XVR_REG0F (BASEADDR_XVR + 0x0F * 4) +#define BLE_XVR_REG10 (BASEADDR_XVR + 0x10 * 4) +#define BLE_XVR_REG11 (BASEADDR_XVR + 0x11 * 4) +#define BLE_XVR_REG12 (BASEADDR_XVR + 0x12 * 4) +#define BLE_XVR_REG13 (BASEADDR_XVR + 0x13 * 4) +#define BLE_XVR_REG14 (BASEADDR_XVR + 0x14 * 4) +#define BLE_XVR_REG15 (BASEADDR_XVR + 0x15 * 4) +#define BLE_XVR_REG16 (BASEADDR_XVR + 0x16 * 4) +#define BLE_XVR_REG17 (BASEADDR_XVR + 0x17 * 4) +#define BLE_XVR_REG18 (BASEADDR_XVR + 0x18 * 4) +#define BLE_XVR_REG19 (BASEADDR_XVR + 0x19 * 4) +#define BLE_XVR_REG1A (BASEADDR_XVR + 0x1A * 4) +#define BLE_XVR_REG1B (BASEADDR_XVR + 0x1B * 4) +#define BLE_XVR_REG1C (BASEADDR_XVR + 0x1C * 4) +#define BLE_XVR_REG1D (BASEADDR_XVR + 0x1D * 4) +#define BLE_XVR_REG1E (BASEADDR_XVR + 0x1E * 4) +#define BLE_XVR_REG1F (BASEADDR_XVR + 0x1F * 4) +#define BLE_XVR_REG20 (BASEADDR_XVR + 0x20 * 4) +#define BLE_XVR_REG21 (BASEADDR_XVR + 0x21 * 4) +#define BLE_XVR_REG22 (BASEADDR_XVR + 0x22 * 4) +#define BLE_XVR_REG23 (BASEADDR_XVR + 0x23 * 4) +#define BLE_XVR_REG24 (BASEADDR_XVR + 0x24 * 4) +#define BLE_XVR_REG25 (BASEADDR_XVR + 0x25 * 4) +#define BLE_XVR_REG26 (BASEADDR_XVR + 0x26 * 4) +#define BLE_XVR_REG27 (BASEADDR_XVR + 0x27 * 4) +#define BLE_XVR_REG28 (BASEADDR_XVR + 0x28 * 4) +#define BLE_XVR_REG29 (BASEADDR_XVR + 0x29 * 4) +#define BLE_XVR_REG2A (BASEADDR_XVR + 0x2A * 4) +#define BLE_XVR_REG2B (BASEADDR_XVR + 0x2B * 4) +#define BLE_XVR_REG2C (BASEADDR_XVR + 0x2C * 4) +#define BLE_XVR_REG2D (BASEADDR_XVR + 0x2D * 4) +#define BLE_XVR_REG2E (BASEADDR_XVR + 0x2E * 4) +#define BLE_XVR_REG2F (BASEADDR_XVR + 0x2F * 4) +#define BLE_XVR_REG30 (BASEADDR_XVR + 0x30 * 4) +#define BLE_XVR_REG31 (BASEADDR_XVR + 0x31 * 4) +#define BLE_XVR_REG32 (BASEADDR_XVR + 0x32 * 4) +#define BLE_XVR_REG33 (BASEADDR_XVR + 0x33 * 4) +#define BLE_XVR_REG34 (BASEADDR_XVR + 0x34 * 4) +#define BLE_XVR_REG35 (BASEADDR_XVR + 0x35 * 4) +#define BLE_XVR_REG36 (BASEADDR_XVR + 0x36 * 4) +#define BLE_XVR_REG37 (BASEADDR_XVR + 0x37 * 4) +#define BLE_XVR_REG38 (BASEADDR_XVR + 0x38 * 4) +#define BLE_XVR_REG39 (BASEADDR_XVR + 0x39 * 4) +#define BLE_XVR_REG3A (BASEADDR_XVR + 0x3A * 4) +#define BLE_XVR_REG3B (BASEADDR_XVR + 0x3B * 4) +#define BLE_XVR_REG3C (BASEADDR_XVR + 0x3C * 4) +#define BLE_XVR_REG3D (BASEADDR_XVR + 0x3D * 4) +#define BLE_XVR_REG3E (BASEADDR_XVR + 0x3E * 4) +#define BLE_XVR_REG3F (BASEADDR_XVR + 0x3F * 4) +#define BLE_XVR_REG40 (BASEADDR_XVR + 0x40 * 4) +#define BLE_XVR_REG41 (BASEADDR_XVR + 0x41 * 4) +#define BLE_XVR_REG42 (BASEADDR_XVR + 0x42 * 4) +#define BLE_XVR_REG43 (BASEADDR_XVR + 0x43 * 4) +#define BLE_XVR_REG44 (BASEADDR_XVR + 0x44 * 4) +#define BLE_XVR_REG45 (BASEADDR_XVR + 0x45 * 4) +#define BLE_XVR_REG46 (BASEADDR_XVR + 0x46 * 4) +#define BLE_XVR_REG47 (BASEADDR_XVR + 0x47 * 4) +#define BLE_XVR_REG48 (BASEADDR_XVR + 0x48 * 4) +#define BLE_XVR_REG49 (BASEADDR_XVR + 0x49 * 4) +#define BLE_XVR_REG4A (BASEADDR_XVR + 0x4A * 4) +#define BLE_XVR_REG4B (BASEADDR_XVR + 0x4B * 4) +#define BLE_XVR_REG4C (BASEADDR_XVR + 0x4C * 4) +#define BLE_XVR_REG4D (BASEADDR_XVR + 0x4D * 4) +#define BLE_XVR_REG4E (BASEADDR_XVR + 0x4E * 4) +#define BLE_XVR_REG4F (BASEADDR_XVR + 0x4F * 4) + +#define BLE_XVR_CHAN_MASK (0x7F) +#define BLE_XVR_CHAN_POST (0) +#define BLE_XVR_AUTO_CHAN_MASK (0xF) +#define BLE_XVR_AUTO_CHAN_POST (17) + +#define REG_READ(addr) *((volatile uint32_t *)(addr)) +#define REG_WRITE(addr, _data) (*((volatile uint32_t *)(addr)) = (_data)) + +#endif diff --git a/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/driver/rf/ble_rf_port.c b/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/driver/rf/ble_rf_port.c new file mode 100755 index 0000000..7a158bc --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/driver/rf/ble_rf_port.c @@ -0,0 +1,403 @@ +#include "ble_rf_port.h" +#include "rwip_config.h" // RW SW configuration +#include "rwip.h" +#include "rwip_int.h" +#include "architect.h" // architectural platform definitions +#include // standard lib functions +#include // standard definitions +#include // standard integer definition +#include // boolean definition +#include // boolean definition +#include "rwip.h" // RW SW initialization +#include "prf.h" // RW SW initialization +#include "rwble.h" +#include "uart_pub.h" +#include "rtos_pub.h" +#include "ble.h" +#include "ble_pub.h" +#include "ble_api.h" +#include "sys_ctrl_pub.h" +#include "icu_pub.h" +#include "intc_pub.h" + +#include "drv_model_pub.h" +#include "include.h" +#include "drv_model_pub.h" +#include "intc_pub.h" +#include "uart_pub.h" +#include "app_task.h" +#include "udebug.h" +//#include "bkDriverUart.h" +#include "typedef.h" +#include "common_bt.h" +#include "arm_arch.h" +#include "rw_pub.h" +#include "power_save_pub.h" +#include "gapc_task.h" +#include "bk7011_cal_pub.h" + +#ifdef BLE_CHOOSE_WIFI_IDLE +uint8_t ble_switch_old_state = HW_IDLE; +#endif +extern void sctrl_set_rf_sleep(void); +extern uint8_t ble_switch_mac_sleeped; +UINT32 rf_wifi_used = 0; + +uint8 is_rf_switch_to_ble(void) +{ + UINT32 param; + + sddev_control(SCTRL_DEV_NAME, CMD_BLE_RF_BIT_GET, ¶m); + + return (param > 0 ) ? 1 : 0; +} + +void rf_wifi_used_set(void) +{ + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + if(0 == rf_wifi_used) + { + rf_wifi_used = 1; + } + GLOBAL_INT_RESTORE(); +} + +void rf_wifi_used_clr(void) +{ + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + if(1 == rf_wifi_used) + { + rf_wifi_used = 0; + } + GLOBAL_INT_RESTORE(); +} + +UINT32 if_rf_wifi_used(void ) +{ + uint32_t value = 0; + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + value = rf_wifi_used; + GLOBAL_INT_RESTORE(); + return value; +} +extern UINT32 ble_ps_enabled(void ); +uint8_t if_ble_sleep(void) +{ + uint8_t ret; + extern struct rwip_env_tag rwip_env; + GLOBAL_INT_DIS(); + if(ble_ps_enabled()) + { + ret = (rwip_env.prevent_sleep & RW_DEEP_SLEEP); + } + else + { + ret = 0; + } + GLOBAL_INT_RES(); + + return ret; +} + +#define MAX_SKIP_CNT 5 +#define MAX_SKIP_CON_CNT 4 +uint32_t ble_switch_skip_cnt = 0; +extern void ble_cal_recover_txpwr(void); +extern uint32_t ps_get_sleep_prevent(void); +extern void rwnxl_reset_handle(int dummy); +extern void sctrl_modem_core_reset(void); +extern void ble_cal_set_txpwr(uint8_t idx); +extern void ble_cal_recover_txpwr(void); +void ble_switch_clear_mac_interrupts(void) +{ + uint32_t fiq_status; + + hal_machw_disable_int(); + nxmac_tx_rx_int_ack_clear(0xffffffff); + nxmac_gen_int_ack_clear(0xffffffff); + fiq_status = sddev_control(ICU_DEV_NAME, CMD_GET_INTR_STATUS, 0); + fiq_status = fiq_status & 0xFFFF0000; + sddev_control(ICU_DEV_NAME, CMD_CLR_INTR_STATUS, &fiq_status); +} + +#define BLE_RF_FORBIT_LOG_EN 0 +#if BLE_RF_FORBIT_LOG_EN < 1 +#define BLE_RF_FORBIT_LOG(...) +#else +#define BLE_RF_FORBIT_LOG bk_printf +#endif + +extern UINT32 txl_cntrl_pck_get(void ); +extern uint32_t sch_arb_prog_check_role_and_index(void); +void ble_switch_rf_to_ble(void) +{ + uint32_t skip_max,cur_skip_cnt = (ble_switch_skip_cnt > 0xFF) ? 0xFFU: ble_switch_skip_cnt; + + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + + uint32_t ble_info = sch_arb_prog_check_role_and_index(); + if (ble_info & (0x02 << 24)) { + skip_max = MAX_SKIP_CON_CNT; + cur_skip_cnt = (cur_skip_cnt > (ble_info&0xFFU)) ? ble_info : (ble_info & 0xFFU); + } + else { + skip_max = MAX_SKIP_CNT; + } + + if(if_rf_wifi_used() && cur_skip_cnt <= (MAX_SKIP_CON_CNT * 2)){ + ble_switch_skip_cnt++; + GLOBAL_INT_RESTORE(); + BLE_RF_FORBIT_LOG("%d RF Forbit:%x\r\n",__LINE__,ble_info); + return; + } + if (txl_cntrl_pck_get() && (cur_skip_cnt < skip_max)) + { + ble_switch_skip_cnt++; + GLOBAL_INT_RESTORE(); + BLE_RF_FORBIT_LOG("%d RF Forbit:%x\r\n",__LINE__,ble_info); + return; + } + + // for ble can get rf when wifi is scanning + if ((ps_get_sleep_prevent() & 0x35) && (cur_skip_cnt < skip_max)) + { + GLOBAL_INT_RESTORE(); + BLE_RF_FORBIT_LOG("%d RF Forbit:%x\r\n",__LINE__,ble_info); + return; + } + + if((REG_READ((ICU_BASE + 19 * 4)) + & (CO_BIT(FIQ_MAC_TX_RX_MISC) + | CO_BIT(FIQ_MAC_TX_RX_TIMER) + | CO_BIT(FIQ_MAC_RX_TRIGGER) + | CO_BIT(FIQ_MAC_TX_TRIGGER) + | CO_BIT(FIQ_MAC_GENERAL) + | CO_BIT(FIQ_MAC_PROT_TRIGGER) + | CO_BIT(FIQ_DPLL_UNLOCK) + ))&&(cur_skip_cnt < skip_max)) + { + GLOBAL_INT_RESTORE(); + BLE_RF_FORBIT_LOG("%d RF Forbit:%x\r\n",__LINE__,ble_info); + return; + } + + ble_switch_skip_cnt = 0; + +#ifdef BLE_CHOOSE_WIFI_IDLE + ble_switch_old_state = nxmac_current_state_getf(); + + // Ask HW to go to IDLE + if (ble_switch_old_state == HW_ACTIVE) + { + uint32_t i_tmp = 0, y_tmp = 0; + uint32_t v_tmp; + + // Ask HW to go to IDLE + if (nxmac_current_state_getf() != HW_IDLE) + { + nxmac_next_state_setf(HW_IDLE); + + while(1) + { + if(nxmac_status_idle_interrupt_getf() == 1) + break; + else + { + i_tmp++; + if(i_tmp > 1000) + { + i_tmp = 0; + v_tmp =nxmac_state_cntrl_get(); + PS_WPRT("s s:0x%x c:0x%x\r\n",v_tmp,power_save_get_sleep_count()); + y_tmp ++; + if(y_tmp > 500) + { + y_tmp = 0; + PS_WPRT("idle rec\r\n"); + bk_printf("idle rec\r\n"); + //long time wait idle interrupt,recover! + hal_machw_disable_int(); + rwnxl_reset_handle(0); + PS_WPRT("idle rec over\r\n"); + nxmac_next_state_setf(HW_IDLE); + } + } + } + } + //while (nxmac_status_idle_interrupt_getf() != 1); + nxmac_gen_int_ack_clear(NXMAC_IDLE_INTERRUPT_BIT); + + // reset modem. + sctrl_modem_core_reset(); + + // Disable MAC interrupts and clear all existing ones + ble_switch_clear_mac_interrupts(); + } + } + else + ble_switch_old_state = HW_IDLE; +#endif + + sctrl_rf_wakeup();//after swtich ble check if need start rf + + extern uint8_t tx_pwr_idx; + ble_cal_set_txpwr(tx_pwr_idx); + + sddev_control(SCTRL_DEV_NAME, CMD_BLE_RF_BIT_SET, NULL); + + ble_switch_mac_sleeped = 1; + + GLOBAL_INT_RESTORE(); + //PS_DEBUG_RF_UP_TRIGER; +} + + +void ble_switch_rf_to_wifi(void) +{ + // if in ble dut mode, no need change back to wifi any more. + // ble dut mode can not exit until power off + // if (!is_rf_switch_to_ble() || power_save_if_rf_sleep()) + if (!is_rf_switch_to_ble()) + return; + + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + + sddev_control(SCTRL_DEV_NAME, CMD_BLE_RF_BIT_CLR, NULL); + ble_switch_mac_sleeped = 0; + + ble_cal_recover_txpwr(); + + sctrl_set_rf_sleep();//after swtich wifi check if can stop rf + + if(power_save_if_rf_sleep()) + { + GLOBAL_INT_RESTORE(); + return; + } +#ifdef BLE_CHOOSE_WIFI_IDLE + if (ble_switch_old_state != HW_IDLE && nxmac_current_state_getf() == HW_IDLE) + { + if(ke_state_get(TASK_MM) == MM_ACTIVE) + { + nxmac_next_state_setf(ble_switch_old_state); + while (nxmac_current_state_getf() != ble_switch_old_state); + } + } +#endif + + if (!power_save_if_rf_sleep()) + { + power_save_rf_ps_wkup_semlist_set(); + } + GLOBAL_INT_RESTORE(); + +#ifdef BLE_CHOOSE_WIFI_IDLE + //Re-enable MAC interrupts + nxmac_enable_master_gen_int_en_setf(1); + nxmac_enable_master_tx_rx_int_en_setf(1); + //PS_DEBUG_RF_UP_TRIGER; +#endif +} + +#if defined(CFG_PTA_SWITCH_RF_EN) && (CFG_PTA_SWITCH_RF_EN == 0) +void ble_request_rf_by_isr(void) +{ + if (ble_get_sys_mode() == NORMAL_MODE) { +#if (CFG_DEFAULT_RF_USER == CFG_RF_USER_WIFI) + ble_switch_rf_to_ble(); +#else + if (kernel_state_get(TASK_APP) == APPM_CONNECTED) + { + ble_switch_rf_to_ble(); + } +#endif + } +} + +void ble_release_rf_by_isr(void) +{ + if (ble_get_sys_mode() == NORMAL_MODE) { +#if (CFG_DEFAULT_RF_USER == CFG_RF_USER_WIFI) + ble_switch_rf_to_wifi(); +#else + if (kernel_state_get(TASK_APP) == APPM_CONNECTED) + { + ble_switch_rf_to_wifi(); + } +#endif + } +} + +#else ////#if defined(CFG_PTA_SWITCH_RF_EN) && (CFG_PTA_SWITCH_RF_EN == 0) + +void ble_request_rf_by_isr(void) +{ + +} + +void ble_release_rf_by_isr(void) +{ + +} + +#endif ////#if defined(CFG_PTA_SWITCH_RF_EN) && (CFG_PTA_SWITCH_RF_EN == 0) + + +/* +#include "ble_reg_blecore.h" +///#include "reg_blecore.h" +#include "common_bt.h" + + + +/// If the Fine counter is close to the greater slot boundary add 1 slot +#if (BT_EMB_PRESENT) +#define EA_CHECK_HALFSLOT_BOUNDARY(void) ((bt_finetimecnt_get() < (624 >> 1)) ? 1 : 0) +#define EA_CHECK_SLOT_BOUNDARY(void) ((bt_finetimecnt_get() < 106) ? 1 : 0) +#else //BT_EMB_PRESENT +#define EA_CHECK_HALFSLOT_BOUNDARY(void) ((ble_finetimecnt_get() < (624 >> 1)) ? 1 : 0) +#define EA_CHECK_SLOT_BOUNDARY(void) ((ble_finetimecnt_get() < 106) ? 1 : 0) +#endif //BT_EMB_PRESENT + +/// Maximum value of a Bluetooth clock (in 625us slots) +#define MAX_SLOT_CLOCK ((1L<<27) - 1) + +uint32_t ea_time_get_halfslot_rounded(void) +{ +#if (BT_EMB_PRESENT) + //Sample the base time count + bt_slotclk_samp_setf(1); + while (bt_slotclk_samp_getf()); + + // Read current time in HW + return ((bt_slotclk_sclk_getf() + 1) >> 1) & MAX_SLOT_CLOCK; +#else + //Sample the base time count + ble_samp_setf(1); + while (ble_samp_getf()); + + // Read current time in HW + return ((ble_basetimecnt_get() + EA_CHECK_HALFSLOT_BOUNDARY()) & MAX_SLOT_CLOCK); +#endif +} +*/ + + +uint32_t rwip_get_current_time(void) +{ + ///return (ea_time_get_halfslot_rounded()); + return 0xFFFFFFFFU; +} + +uint32_t rwip_get_next_target_time(void) +{ + ////return (ea_timer_next_target_get()); + return 0xFFFFFFFFU; +} + + diff --git a/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/driver/rf/ble_rf_port.h b/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/driver/rf/ble_rf_port.h new file mode 100755 index 0000000..4677b4a --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/driver/rf/ble_rf_port.h @@ -0,0 +1,12 @@ + +#ifndef _BLE_RF_PORT_H_ +#define _BLE_RF_PORT_H_ + +#include "include.h" + +extern void ble_switch_rf_to_wifi(void); +extern void ble_switch_rf_to_ble(void); +extern uint8 is_rf_switch_to_ble(void); + +#endif // _BLE_RF_PORT_H_ + diff --git a/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/driver/rf/rf.h b/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/driver/rf/rf.h new file mode 100755 index 0000000..9f693ca --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/driver/rf/rf.h @@ -0,0 +1,59 @@ +/** + **************************************************************************************** + * + * @file rf.h + * + * @brief Common header file for all radios. + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +#ifndef RF_H_ +#define RF_H_ + +/** + **************************************************************************************** + * @addtogroup RF + * @ingroup DRIVERS + * @brief Common definitions for radio modules. + * + * This module declares the functions and constants that have to be defined for all RF. + * + * @{ + **************************************************************************************** + */ + + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +struct rwip_rf_api; // forward declaration to avoid including rw.h + +/** + ***************************************************************************************** + * @brief Initialization of RF. + * + * This function initializes the RF and fills the structure containing the function + * pointers and parameters required by the RW BT stack. + * + * @param[out] api Pointer to the BT RF API structure + * + ***************************************************************************************** + */ +void rf_init(struct rwip_rf_api *api); + +void xvr_reg_initial(void) ; +void kmod_calibration(void) ; +void rf_debug_gpio_init(uint8_t GPIO_C_D); +void CLK32K_AutoCali_init(void); +void Delay(int num); +void Delay_us(int num); +void Delay_ms(int num); +/// @} RF + +#endif // RF_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/driver/rf/rf_xvr.c b/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/driver/rf/rf_xvr.c new file mode 100755 index 0000000..37c8781 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/driver/rf/rf_xvr.c @@ -0,0 +1,687 @@ +/** +**************************************************************************************** +* +* @file rf_xvras.c +* +* @brief Atlas radio initialization and specific functions +* +* Copyright (C) Beken 2009-2015 +* +* $Rev: $ +* +**************************************************************************************** +*/ + +/** +**************************************************************************************** +* @addtogroup RF_XVR +* @ingroup RF +* @brief Radio Driver +* +* This is the driver block for radio +* @{ +**************************************************************************************** +*/ + +/** + ***************************************************************************************** + * INCLUDE FILES + ***************************************************************************************** + */ +#include "ble_reg_ipcore.h" // DM core registers +#include "rwip_config.h" // RW SW configuration +#include // for memcpy +#include "common_utils.h" // common utility definition +#include "common_math.h" // common math functions +#include "rf.h" // RF interface +#include "rwip.h" // for RF API structure definition +#include "em_map.h" +#if (BLE_EMB_PRESENT) +#include "ble_reg_blecore.h" // ble core registers +#include "ble_reg_em_ble_cs.h" // control structure definitions +#endif //BLE_EMB_PRESENT +#if (BT_EMB_PRESENT) +#include "ble_reg_btcore.h" // bt core registers +#include "ble_reg_em_bt_cs.h" // control structure definitions +#endif //BT_EMB_PRESENT +#include "ble_reg_access.h" //// added +#include "BK3633_RegList.h" // Platform register +#include "user_config.h" +#include "sys_ctrl.h" +/** + **************************************************************************************** + * DEFINES + **************************************************************************************** + **/ + #define RPL_GAIN_TBL_SIZE 0x0F +//#define bk_printf uart2_printf + +// EM RF SPI address +#define RF_EM_SPI_ADRESS (EM_BASE_ADDR + EM_RF_SW_SPI_OFFSET) + +#define RPL_SPIRD 0x00 +#define RPL_SPIWR 0x80 +#define RPL_RFPLL_TBL_SIZE 0x50 +#define RPL_PWR_TBL_SIZE 0x0F + +/* The offset value given below is the offset to add to the frequency table index to + get the value to be programmed in the radio for each channel */ +#define RPL_FREQTAB_OFFSET 0 // Offset for Ripple radio + +/// Radio skew compensation (round trip delay) +#define RPL_RADIO_SKEW 12L + +#define RFLOIF 0x00 + +#define RPL_RSSI_20dB_THRHLD -20 +#define RPL_RSSI_45dB_THRHLD -45 +#define RPL_RSSI_48dB_THRHLD -48 +#define RPL_RSSI_55dB_THRHLD -55 +#define RPL_RSSI_60dB_THRHLD -60 +#define RPL_RSSI_70dB_THRHLD -70 + +// EDR Control value +#define RPL_EDRCNTL 18 // Default value is set to 18us + + +#define RPL_POWER_MAX 0x0c //// ???? +////#define RPL_POWER_MAX 0x06 +#define RPL_POWER_MIN 0x01 //// ???? +#define RPL_POWER_MSK 0x07 //// ???? + +// Generic RSSI Threshold +#define RF_RPL_RSSI_THR 0x29 + + +/** +**************************************************************************************** +* MACROS +***************************************************************************************** +*/ + + + + +/** + **************************************************************************************** + * GLOBAL VARIABLE DEFINITIONS + ***************************************************************************************** + **/ +//// IP ???? +// PLL Lock Table +///static uint8_t RFPLL_LOCK_TABLE[RPL_RFPLL_TBL_SIZE] = {0}; + +// PLL VCOFC table +//static uint8_t RFPLL_VCOFC_TABLE[RPL_RFPLL_TBL_SIZE] = {0}; + +// PLL ICP table +//static uint8_t RFPLL_ICP_TABLE[RPL_RFPLL_TBL_SIZE] = {0}; + +// Power table +static const int8_t RF_RPL_TX_PW_CONV_TBL[RPL_PWR_TBL_SIZE] = { + [0] = -23, + [1] = -20, + [2] = -17, + [3] = -14, + [4] = -11, + [5] = -8, + [6] = -5, + [7] = -2}; +// Gain table +static const uint8_t RF_RPL_RX_GAIN_TBL[RPL_GAIN_TBL_SIZE] = { + [0] = 43, + [1] = 37, + [2] = 31, + [3] = 25, + [4] = 19, + [5] = 13, + [6] = 7, + [7] = 1}; +////IP ???? + + +extern uint8_t system_mode; + +/** + **************************************************************************************** + * FUNCTION DEFINITIONS + **************************************************************************************** + */ + +void CLK32K_AutoCali_init(void); + + +/** + ***************************************************************************************** + * @brief Init RF sequence after reset. + ***************************************************************************************** + */ + +static void rf_reset(void) +{ +} + +/** + **************************************************************************************** + * @brief ISR to be called in BLE ISR routine when RF Interrupt occurs. + ***************************************************************************************** + */ + + +//// IP +/** + ***************************************************************************************** + * @brief Get the TX power as control structure TX power field from a value in dBm. + * + * @param[in] txpwr_dbm TX power in dBm + * @param[in] high If true, return index equal to or higher than requested + * If false, return index equal to or lower than requested + * + * @return The index of the TX power + * + ***************************************************************************************** + */ +static uint8_t rf_txpwr_cs_get (int8_t txpwr_dbm, bool high) +{ + uint8_t i; + + for (i = RPL_POWER_MIN; i <= RPL_POWER_MAX; i++) + { + // Loop until we find a power just higher or equal to the requested one + if (RF_RPL_TX_PW_CONV_TBL[i] >= txpwr_dbm) + break; + } + + // If equal to value requested, do nothing + // Else if 'high' is false and index higher than the minimum one, decrement by one + if ((RF_RPL_TX_PW_CONV_TBL[i] != txpwr_dbm) && (!high) && (i > RPL_POWER_MIN)) + { + i--; + } + + return(i); +} + + + + + +/** + ***************************************************************************************** + * @brief Get TX power in dBm from the index in the control structure + * + * @param[in] txpwr_idx Index of the TX power in the control structure + * @param[in] modulation Modulation: 1 or 2 or 3 MBPS + * + * @return The TX power in dBm + * + ***************************************************************************************** + */ + +static uint8_t rf_txpwr_dbm_get(uint8_t txpwr_idx, uint8_t modulation) +{ + // Power table should be provided + return(0); +} + +/** + ***************************************************************************************** + * @brief Sleep function for RF. + ***************************************************************************************** + */ + +static void rf_sleep(void) +{ + ip_deepslcntl_set(ip_deepslcntl_get() | 0x04);//// IP_DEEP_SLEEP_ON_BIT | IP_RADIO_SLEEP_EN_BIT | IP_OSC_SLEEP_EN_BIT +} + + +/** + ***************************************************************************************** + * @brief Convert RSSI to dBm + * + * @param[in] rssi_reg RSSI read from the HW registers + * + * @return The converted RSSI + * + ***************************************************************************************** + */ + +static int8_t rf_rssi_convert (uint8_t rssi_reg) +{ + uint8_t RssidBm = 0; + + RssidBm = ((rssi_reg) >> 1) - 118; + + return(RssidBm); +} + + +static uint32_t rf_rpl_reg_rd (uint32_t addr) +{ + uint32_t ret; + + ret = REG_PL_RD(addr); + + return ret; +} + +static void rf_rpl_reg_wr (uint32_t addr, uint32_t value) +{ + REG_PL_WR(addr, value); +} + +static void rf_em_init(void) +{ + uint8_t idx = 0; + uint8_t temp_freq_tbl[EM_RF_FREQ_TABLE_LEN]; + + #if BT_EMB_PRESENT + // First half part of frequency table is for the even frequencies + while(idx < EM_RF_FREQ_TABLE_LEN/2) + { + temp_freq_tbl[idx] = 2*idx + RPL_FREQTAB_OFFSET; + idx++; + } + while(idx < EM_RF_FREQ_TABLE_LEN) + { + temp_freq_tbl[idx] = 2*(idx-(EM_RF_FREQ_TABLE_LEN/2)) + 1 + RPL_FREQTAB_OFFSET; + idx++; + } + // em_wr(&temp_freq_tbl[0], EM_FT_OFFSET, EM_RF_FREQ_TABLE_LEN); + #elif BLE_EMB_PRESENT + while(idx < EM_RF_FREQ_TABLE_LEN) + { + temp_freq_tbl[idx] = 2*idx + RPL_FREQTAB_OFFSET; + idx++; + } + em_wr(&temp_freq_tbl[0], EM_FT_OFFSET, EM_RF_FREQ_TABLE_LEN); + #endif // BT_EMB_PRESENT/BLE_EMB_PRESENT +} + +void xvr_reg_init(void) +{ + // TODO:Use hardware powertable +#if 0 + *((volatile unsigned long *)(0x01050200)) = 0x200; + unsigned long temp = *((volatile unsigned long *)(0x01050200)); + bk_printf("temp:%08x\r\n", temp); +#endif + +#if 1 + REG_WRITE(BLE_XVR_REG00, 0x0426684E); + REG_WRITE(BLE_XVR_REG01, 0x925B28A1); + REG_WRITE(BLE_XVR_REG02, 0x2F00EFF2); + REG_WRITE(BLE_XVR_REG03, 0x0AA00000); + REG_WRITE(BLE_XVR_REG04, 0x9C697067); + REG_WRITE(BLE_XVR_REG05, 0xB13B1133); + REG_WRITE(BLE_XVR_REG06, 0x078A0C5A); + REG_WRITE(BLE_XVR_REG07, 0x3DA87860); + REG_WRITE(BLE_XVR_REG08, 0x23BC6000); + REG_WRITE(BLE_XVR_REG09, 0x03D7F000); + REG_WRITE(BLE_XVR_REG0A, 0x0003007C); + REG_WRITE(BLE_XVR_REG0B, 0x00000E5B); + REG_WRITE(BLE_XVR_REG0C, 0x000101E0); + REG_WRITE(BLE_XVR_REG0D, 0x08006300); + REG_WRITE(BLE_XVR_REG0E, 0x00000000); + REG_WRITE(BLE_XVR_REG0F, 0x00000000); + REG_WRITE(BLE_XVR_REG10, 0x00003011); + REG_WRITE(BLE_XVR_REG11, 0x3EED021C); + REG_WRITE(BLE_XVR_REG12, 0x00000097); + REG_WRITE(BLE_XVR_REG13, 0x00180000); + REG_WRITE(BLE_XVR_REG14, 0x02690F8A); + REG_WRITE(BLE_XVR_REG15, 0x07233AE7); + REG_WRITE(BLE_XVR_REG16, 0x000103A5); + REG_WRITE(BLE_XVR_REG17, 0x00000016); + REG_WRITE(BLE_XVR_REG18, 0x00000000); + REG_WRITE(BLE_XVR_REG20, 0x3BA7A940); + REG_WRITE(BLE_XVR_REG21, 0x96000000); + REG_WRITE(BLE_XVR_REG22, 0x78000000); + REG_WRITE(BLE_XVR_REG23, 0xA0000000); + REG_WRITE(BLE_XVR_REG24, 0x001E0782); + REG_WRITE(BLE_XVR_REG25, 0x00000000); + REG_WRITE(BLE_XVR_REG26, 0x10200400); + REG_WRITE(BLE_XVR_REG27, 0x0008C900); + REG_WRITE(BLE_XVR_REG28, 0x01011010); + REG_WRITE(BLE_XVR_REG29, 0x7C104E00); + REG_WRITE(BLE_XVR_REG2A, 0x12084044); + REG_WRITE(BLE_XVR_REG2B, 0x00000408); + REG_WRITE(BLE_XVR_REG2C, 0x00000000); + REG_WRITE(BLE_XVR_REG2D, 0x082AC444); + //REG_WRITE(BLE_XVR_REG2E, 0x00000000); + //REG_WRITE(BLE_XVR_REG2F, 0x00000000); + REG_WRITE(BLE_XVR_REG30, 0xA0419980);//<11:10>=2 by qunshan20201228 for rx + REG_WRITE(BLE_XVR_REG31, 0x00000000); + REG_WRITE(BLE_XVR_REG32, 0x00000000); + REG_WRITE(BLE_XVR_REG33, 0x00000000); + //REG_WRITE(BLE_XVR_REG34, 0x00000000); + //REG_WRITE(BLE_XVR_REG35, 0x00000000); + //REG_WRITE(BLE_XVR_REG36, 0x00000000); + //REG_WRITE(BLE_XVR_REG37, 0x00000000); + REG_WRITE(BLE_XVR_REG38, 0x00000000); + REG_WRITE(BLE_XVR_REG39, 0x00000000); + REG_WRITE(BLE_XVR_REG3A, 0x01028000); + REG_WRITE(BLE_XVR_REG3B, 0x3F341448); //<11:9>=2 by qunshan20201224 for rx + REG_WRITE(BLE_XVR_REG3C, 0x26771C01); + REG_WRITE(BLE_XVR_REG3D, 0x00000000); + REG_WRITE(BLE_XVR_REG3E, 0x8908B950);//0908B942 + //REG_WRITE(BLE_XVR_REG3F, 0x00000000); +#if 0 + REG_WRITE(BLE_XVR_REG40, 0x02000100); + REG_WRITE(BLE_XVR_REG41, 0x04000300); + REG_WRITE(BLE_XVR_REG42, 0x06000500); + REG_WRITE(BLE_XVR_REG43, 0x08000700); + REG_WRITE(BLE_XVR_REG44, 0x0A000900); + REG_WRITE(BLE_XVR_REG45, 0x0C000B00); + REG_WRITE(BLE_XVR_REG46, 0x0E000D00); + REG_WRITE(BLE_XVR_REG47, 0x10000F00); + REG_WRITE(BLE_XVR_REG48, 0x12001100); + REG_WRITE(BLE_XVR_REG49, 0x14001300); + REG_WRITE(BLE_XVR_REG4A, 0x16001500); + REG_WRITE(BLE_XVR_REG4B, 0x18001700); + REG_WRITE(BLE_XVR_REG4C, 0x1A001900); + REG_WRITE(BLE_XVR_REG4D, 0x1C001B00); + REG_WRITE(BLE_XVR_REG4E, 0x1E001D00); + REG_WRITE(BLE_XVR_REG4F, 0x20001F00); +#endif + +#if 0 + REG_WRITE(BLE_XVR_REG40, 0x03000180); + REG_WRITE(BLE_XVR_REG41, 0x06000480); + REG_WRITE(BLE_XVR_REG42, 0x09000780); + REG_WRITE(BLE_XVR_REG43, 0x0C000A80); + REG_WRITE(BLE_XVR_REG44, 0x0F000D80); + REG_WRITE(BLE_XVR_REG45, 0x12001080); + REG_WRITE(BLE_XVR_REG46, 0x15001380); + REG_WRITE(BLE_XVR_REG47, 0x18001680); + REG_WRITE(BLE_XVR_REG48, 0x1B001980); + REG_WRITE(BLE_XVR_REG49, 0x1E001C80); + REG_WRITE(BLE_XVR_REG4A, 0x21001F80); + REG_WRITE(BLE_XVR_REG4B, 0x24002280); + REG_WRITE(BLE_XVR_REG4C, 0x27002580); + REG_WRITE(BLE_XVR_REG4D, 0x2A002880); + REG_WRITE(BLE_XVR_REG4E, 0x2D002B80); + REG_WRITE(BLE_XVR_REG4F, 0x30002E80); +#endif + +#if 0 + REG_WRITE(BLE_XVR_REG40, 0x01200090); + REG_WRITE(BLE_XVR_REG41, 0x024001B0); + REG_WRITE(BLE_XVR_REG42, 0x036002D0); + REG_WRITE(BLE_XVR_REG43, 0x048003F0); + REG_WRITE(BLE_XVR_REG44, 0x05A00510); + REG_WRITE(BLE_XVR_REG45, 0x06C00630); + REG_WRITE(BLE_XVR_REG46, 0x07E00750); + REG_WRITE(BLE_XVR_REG47, 0x09000870); + REG_WRITE(BLE_XVR_REG48, 0x0A200990); + REG_WRITE(BLE_XVR_REG49, 0x0B400AB0); + REG_WRITE(BLE_XVR_REG4A, 0x0C600BD0); + REG_WRITE(BLE_XVR_REG4B, 0x0D800CF0); + REG_WRITE(BLE_XVR_REG4C, 0x0EA00E10); + REG_WRITE(BLE_XVR_REG4D, 0x0FC00F30); + REG_WRITE(BLE_XVR_REG4E, 0x10E01050); + REG_WRITE(BLE_XVR_REG4F, 0x12001170); +#endif +#endif +} + +#if defined(CFG_BLE) + +static void rf_force_agc_enable(bool en) +{ + #if defined(CFG_BT) + ip_radiocntl1_forceagc_en_setf(en); + #else + ip_radiocntl1_forceagc_en_setf(en); + #endif //CFG_BLE + + ble_radiocntl1_forceagc_en_setf(en); + +} +#endif //CFG_BLE + +void rf_init(struct rwip_rf_api *api) +{ + // Initialize the RF driver API structure + api->reg_rd = rf_rpl_reg_rd; + api->reg_wr = rf_rpl_reg_wr; + api->txpwr_dbm_get = rf_txpwr_dbm_get; + api->txpwr_min = RPL_POWER_MIN; + api->txpwr_max = RPL_POWER_MAX; + api->sleep = rf_sleep; + api->reset = rf_reset; + +#if defined(CFG_BLE) + api->force_agc_enable = rf_force_agc_enable; +#endif //CFG_BLE + + api->rssi_convert = rf_rssi_convert; + api->txpwr_cs_get = rf_txpwr_cs_get; + +#if defined(CFG_BT) + api->txpwr_dec = rf_txpwr_dec; + api->txpwr_inc = rf_txpwr_inc; + api->txpwr_max_set = txpwr_max_set; + // Initialize the RSSI thresholds (high, low, interference) + // These are 'real' signed values in dBm + if ( (rwip_param.get(PARAM_ID_RSSI_HIGH_THR, &length, (uint8_t*)&api->rssi_high_thr) != PARAM_OK) + || (rwip_param.get(PARAM_ID_RSSI_LOW_THR, &length, (uint8_t*)&api->rssi_low_thr) != PARAM_OK) + || (rwip_param.get(PARAM_ID_RSSI_INTERF_THR, &length, (uint8_t*)&api->rssi_interf_thr) != PARAM_OK) ) + { + api->rssi_high_thr = (int8_t)RPL_RSSI_20dB_THRHLD; + api->rssi_low_thr = (int8_t)RPL_RSSI_60dB_THRHLD; + api->rssi_interf_thr = (int8_t)RPL_RSSI_70dB_THRHLD; + } +#endif //CFG_BT + + os_null_printf("xvr_reg_init\r\n"); + rf_em_init(); + xvr_reg_init(); + + ip_radiocntl1_pack(/*uint8_t forceagcen*/ 0, + /*uint8_t forceiq*/ 0, + /*uint8_t rxdnsl*/ 0, + /*uint8_t txdnsl*/ 0, + /*uint16_t forceagclength*/ 0, + /*uint8_t syncpulsemode*/ 0, + /*uint8_t syncpulsesrc*/ 0, + /*uint8_t dpcorren*/ 0, + /*uint8_t jefselect*/ 0, + /*uint8_t xrfsel*/ 0x02, + /*uint8_t subversion*/ 0x0); + + + ip_radiocntl1_set(0x00000020); + //uart_printf("ip RADIOCNTL1 addr:0x%08x,val:0x%08x\r\n",ip_RADIOCNTL1_ADDR,ip_radiocntl1_get()); + ip_timgencntl_set(0x01df0120); ////Beken, + //uart_printf("ip_TIMGENCNTL addr:0x%08x,val:0x%08x\r\n",ip_TIMGENCNTL_ADDR,ip_timgencntl_get()); +#if defined(CFG_BLE) + //uart_printf("RW BLE reg init\r\n"); + /* BLE RADIOCNTL2 */ + ble_radiocntl2_pack(/*uint8_t lrsynccompmode*/ 0x0, + /*uint8_t rxcitermbypass*/ 0x0, + /*uint8_t lrvtbflush*/ 0x8, + /*uint8_t phymsk*/ 0x2, // mark that Coded phy are supported + /*uint8_t lrsyncerr*/ 0, + /*uint8_t syncerr*/ 0, + /*uint16_t freqtableptr*/ (EM_FT_OFFSET >> 2)); + ble_radiocntl2_set(0x00C000C0); + //uart_printf("BLE_RADIOCNTL2 addr:0x%08x,val:0x%08x\r\n",BLE_RADIOCNTL2_ADDR,ble_radiocntl2_get()); + + /* BLE RADIOPWRUPDN0 */ + ble_radiopwrupdn0_pack(/*uint8_t syncposition0*/ 0, + /*uint8_t rxpwrup0*/ 0x50, + /*uint8_t txpwrdn0*/ 0x07, + /*uint8_t txpwrup0*/ 0x55); + ble_radiopwrupdn0_set(0x00650065); + //uart_printf("BLE_RADIOPWRUPDN0 addr:0x%08x,val:0x%08x\r\n",BLE_RADIOPWRUPDN0_ADDR,ble_radiopwrupdn0_get()); + + /* BLE RADIOPWRUPDN1 */ + ble_radiopwrupdn1_pack(/*uint8_t syncposition1*/ 0, + /*uint8_t rxpwrup1*/ 0x70, + /*uint8_t txpwrdn0*/ 0x00, + /*uint8_t txpwrup1*/ 0x65); + ble_radiopwrupdn1_set(0x00650065); + // uart_printf("BLE_RADIOPWRUPDN1 addr:0x%08x,val:0x%08x\r\n",BLE_RADIOPWRUPDN1_ADDR,ble_radiopwrupdn1_get()); + + /* BLE RADIOPWRUPDN2 */ + ble_radiopwrupdn2_pack(/*uint8_t syncposition2*/ 0, + /*uint8_t rxpwrup2*/ 0x50, // 50 + /*uint8_t txpwrdn2*/ 0x07, + /*uint8_t txpwrup2*/ 0x55); + ble_radiopwrupdn2_set(0x00650065); + //uart_printf("BLE_RADIOPWRUPDN2 addr:0x%08x,val:0x%08x\r\n",BLE_RADIOPWRUPDN2_ADDR,ble_radiopwrupdn2_get()); + + + /* BLE RADIOPWRUPDN3 */ + ble_radiopwrupdn3_pack(/*uint8_t txpwrdn3*/ 0x07, + /*uint8_t txpwrup3*/ 0x55); + ble_radiopwrupdn3_set(0x00000065); + //uart_printf("BLE_RADIOPWRUPDN3 addr:0x%08x,val:0x%08x\r\n",BLE_RADIOPWRUPDN3_ADDR,ble_radiopwrupdn3_get()); + + /* BLE RADIOTXRXTIM0 */ + ble_radiotxrxtim0_pack(/*uint8_t rfrxtmda0*/ 0, + /*uint8_t rxpathdly0*/ 0x6, + /*uint8_t txpathdly0*/ 0x6); + ble_radiotxrxtim0_set(0x00000606); //0x00001007 + //uart_printf("BLE_RADIOTXRXTIM0 addr:0x%08x,val:0x%08x\r\n",BLE_RADIOTXRXTIM0_ADDR,ble_radiotxrxtim0_get()); + + /* BLE RADIOTXRXTIM1 */ + ble_radiotxrxtim1_pack(/*uint8_t rfrxtmda1*/ 0x00, + /*uint8_t rxpathdly1*/ 0x04, + /*uint8_t txpathdly1*/ 0x04); + ble_radiotxrxtim1_set(0x00050C04); + //uart_printf("BLE_RADIOTXRXTIM1 addr:0x%08x,val:0x%08x\r\n",BLE_RADIOTXRXTIM1_ADDR,ble_radiotxrxtim1_get()); + + + /* BLE RADIOTXRXTIM2 */ + // uart_printf("# 09\r\n"); + ble_radiotxrxtim2_pack(/*uint8_t rxflushpathdly2*/ 0x10, + /*uint8_t rfrxtmda2*/ 0x00, + /*uint8_t rxpathdly2*/ 0x49, + /*uint8_t txpathdly2*/ 0x03); + ble_radiotxrxtim2_set(0x00002020); + //uart_printf("BLE_RADIOTXRXTIM2 addr:0x%08x,val:0x%08x\r\n",BLE_RADIOTXRXTIM2_ADDR,ble_radiotxrxtim2_get()); + + /* BLE RADIOTXRXTIM3 */ + ble_radiotxrxtim3_pack(/*uint8_t rxflushpathdly3*/ 0x10, + /*uint8_t rfrxtmda3*/ 0x00, + /*uint8_t txpathdly3*/ 0x03); + ble_radiotxrxtim3_set(0x00000020); + //uart_printf("BLE_RADIOTXRXTIM3 addr:0x%08x,val:0x%08x\r\n",BLE_RADIOTXRXTIM3_ADDR,ble_radiotxrxtim3_get()); + + bk_ble_addtion_reg0_set(0x00000007); + +#if (BLE_CON_CTE_REQ | BLE_CONLESS_CTE_RX) + // Init the DF CNTL + ble_dfcntl0_1us_pack(/*uint8_t rxsampstinst01us*/ 0x08, /*uint8_t rxswstinst01us*/ 0x18, /*uint8_t txswstinst01us*/ 0x19); + ble_dfcntl0_2us_pack(/*uint8_t rxsampstinst02us*/ 0x08, /*uint8_t rxswstinst02us*/ 0x18, /*uint8_t txswstinst02us*/ 0x19); + ble_dfcntl1_1us_pack(/*uint8_t rxsampstinst11us*/ 0x08, /*uint8_t rxswstinst11us*/ 0x18, /*uint8_t txswstinst11us*/ 0x19); + ble_dfcntl1_2us_pack(/*uint8_t rxsampstinst12us*/ 0x08, /*uint8_t rxswstinst12us*/ 0x18, /*uint8_t txswstinst12us*/ 0x19); + ble_dfantcntl_pack(/*uint8_t rxprimidcntlen*/ 1, /*uint8_t rxprimantid*/ 0, /*uint8_t txprimidcntlen*/ 1, /*uint8_t txprimantid*/ 0); +#endif // (BLE_CON_CTE_REQ | BLE_CONLESS_CTE_RX) +#endif // defined CFG_BLE + +#if defined(CFG_BT) + + /* EDRCNTL */ +#if 1 ////BEKEN + bt_rwbtcntl_set(0x0000010A); +#else + bt_rwbtcntl_nwinsize_setf(0); +#endif + bt_edrcntl_rxgrd_timeout_setf(RPL_EDRCNTL); + + /* BT RADIOPWRUPDN */ +#if 1 //// BEKEN + bt_radiopwrupdn_set(0x00710271); +#else + bt_radiopwrupdn_rxpwrupct_setf(0x42); + bt_radiopwrupdn_txpwrdnct_setf(0x07); + bt_radiopwrupdn_txpwrupct_setf(0x56); +#endif + /* BT RADIOCNTL 2 */ +#if 1 ////BEKEN + //uart_printf("# 14\r\n"); + bt_radiocntl2_set(0x04070100); +#else + bt_radiocntl2_freqtable_ptr_setf((EM_FT_OFFSET >> 2)); + bt_radiocntl2_syncerr_setf(0x7); +#endif + /* BT RADIOTXRXTIM */ +#define PRL_TX_PATH_DLY 4 +#define PRL_RX_PATH_DLY (RPL_RADIO_SKEW - PRL_TX_PATH_DLY) +#if 1 ////BEKEN + //uart_printf("# 15\r\n"); + bt_radiotxrxtim_set(0x00000403); +#else + bt_radiotxrxtim_rxpathdly_setf(PRL_RX_PATH_DLY); + bt_radiotxrxtim_txpathdly_setf(PRL_TX_PATH_DLY); + bt_radiotxrxtim_sync_position_setf(0x38); // Default is 0x10 +#endif + /* BT RADIOCNTL 3*/ +#if 1 ////BEKEN + //uart_printf("# 16\r\n"); + bt_radiocntl3_set(0x39003900); +#else + bt_radiocntl3_pack( /*uint8_t rxrate2cfg*/ 3, + /*uint8_t rxrate1cfg*/ 2, + /*uint8_t rxrate0cfg*/ 1, + /*uint8_t rxserparif*/ 0, + /*uint8_t rxsyncrouting*/ 0, + /*uint8_t rxvalidbeh*/ 0, + /*uint8_t txrate2cfg*/ 3, + /*uint8_t txrate1cfg*/ 2, + /*uint8_t txrate0cfg*/ 1, + /*uint8_t txserparif*/ 0, + /*uint8_t txvalidbeh*/ 0); +#endif +#endif //CFG_BT + + // Settings for proper reception +#if defined(CFG_BLE) + ip_radiocntl1_forceiq_setf(1); + ip_radiocntl1_dpcorr_en_setf(0x0); + BLE_ASSERT_ERR(ip_radiocntl1_dpcorr_en_getf() == 0x0); +#endif // CFG_BLE + +#if defined(CFG_BT) + ip_radiocntl1_dpcorr_en_setf(0x1); + BLE_ASSERT_ERR(ip_radiocntl1_dpcorr_en_getf() == 0x1); +#endif // CFG_BT + +#if defined(CFG_BLE) + // Force IQ mode for BLE only + ip_radiocntl1_forceiq_setf(1); +#endif //CFG_BLE + +} + +void Delay_us(int num) +{ + int x, y; + for(y = 0; y < num; y ++ ) + { + for(x = 0; x < 10; x++); + } +} + +void Delay(int num) +{ + int x, y; + for(y = 0; y < num; y ++ ) + { + for(x = 0; x < 50; x++); + } +} + +void Delay_ms(int num) //sync from svn revision 18 +{ + int x, y; + for(y = 0; y < num; y ++ ) + { + for(x = 0; x < 3260; x++); + } + +} + diff --git a/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/driver/uart/uart_ble.c b/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/driver/uart/uart_ble.c new file mode 100755 index 0000000..b5a7b85 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/driver/uart/uart_ble.c @@ -0,0 +1,348 @@ +#include "includes.h" +#include "arm_arch.h" +#include // standard definition +#include +#include // standard integer definition +#include // string manipulation +#include +#include "rwip.h" +#include "uart.h" +#include "uart_ble.h" +#include "cmd_evm.h" +#include "ble_pub.h" + +volatile static struct uart_env_tag uart_env; +volatile static uint8_t uart_rx_done = 0; +volatile static uint32_t uart_rx_index = 0; +uint8_t uart_rx_buf[UART_FIFO_MAX_COUNT]; +extern uint8_t tx_pwr_idx; +uint8_t ble_test_mode = IDLE_MODE; +uint8_t tx_mode; + +void ble_uart_init(void) +{ + uart_rx_done = 0; + uart_rx_index = 0; + + //// Initialize RX and TX transfer callbacks + uart_env.rx.callback = NULL; + uart_env.tx.callback = NULL; + uart_env.uart_tx_buf = NULL; + uart_env.uart_rx_buf = NULL; + uart_env.uart_tx_length = 0; + uart_env.uart_rx_length = 0; + uart_env.uart_tx_enable = 0; + uart_env.uart_rx_enable = 0; + + if (ble_get_sys_mode() == DUT_FCC_MODE) { + hci_data_init((HCI_DATA_TYPE_CMD | HCI_DATA_TYPE_EVENT)); + host_get_event_cbReg(ble_uart_send); + } +} + +void ble_uart_read(uint8_t *bufptr, uint32_t size, void (*callback) (void*, uint8_t), void* dummy) +{ + BLE_ASSERT_ERR(bufptr != NULL); + BLE_ASSERT_ERR(size != 0); + BLE_ASSERT_ERR(callback != NULL); + uart_env.rx.callback = callback; + uart_env.rx.dummy = dummy; + + uart_env.uart_rx_buf = bufptr; //// uart_rx_ptr_setf((uint32_t) bufptr); + uart_env.uart_rx_length = size; //// uart_rx_size_setf(size); + uart_env.uart_rx_enable = 1; //// uart_rx_start_setf(1); +} + +void ble_uart_write(uint8_t *bufptr, uint32_t size, void (*callback) (void*, uint8_t), void* dummy) +{ + // Sanity check + BLE_ASSERT_ERR(bufptr != NULL); + BLE_ASSERT_ERR(size != 0); + BLE_ASSERT_ERR(callback != NULL); + uart_env.tx.callback = callback; + uart_env.tx.dummy = dummy; + + uart_env.uart_tx_buf = bufptr; + uart_env.uart_tx_length = size; + uart_env.uart_tx_enable = 1; + + ble_send_msg(BLE_MSG_DUT); +} + +void ble_uart_flow_on(void) +{ + +} +bool ble_uart_flow_off(void) +{ + return true; +} + +static void ble_uart_send_byte(uint8_t data) +{ + data = (data & UART_TX_FIFO_DIN_MASK) << UART_TX_FIFO_DIN_POSI; + REG_WRITE(REG_UART1_FIFO_PORT, data); +} + +void ble_uart_send(void *buff, uint16_t len) +{ + uint8_t *tmpbuf = (uint8_t *)buff; + while (len--) + ble_uart_send_byte(*tmpbuf++); +} + +void uart_rx_cmd_handler(uint8_t *buff, uint8_t len) +{ + uint8_t length; + length = len; + switch (buff[0]) { + case EXIT_DUT_CMD: + if ((length == 2) && (buff[1] == EXIT_DUT_ACT)) { + ble_send_msg(BLE_DUT_EXIT); + } else { + bk_printf("unknow dut cmd\r\n"); + } + break; + case TX_PWR_SET_CMD: + if (length == 2) { + if (buff[1] > 79) { + tx_pwr_idx = 79; + } else { + tx_pwr_idx = buff[1]; + } + extern void ble_cal_set_txpwr(uint8_t idx); + ble_cal_set_txpwr(tx_pwr_idx); + bk_printf("idx:%d\r\n", tx_pwr_idx); + + if (ble_test_mode == USER_TX_MODE) + { + ble_ctrl(CMD_BLE_STOP_TX, NULL); + ble_ctrl(CMD_BLE_START_TX, &tx_mode); + } + } else { + bk_printf("unknow dut cmd\r\n"); + } + break; + case TX_PWR_SAVE_CMD: + if (length == 3) { + uint8_t channel = buff[1]; + uint8_t pwr_idx = buff[2]; + + if (channel > 39) + channel = 39; + if (pwr_idx > 79) + pwr_idx = 79; + extern void manual_cal_save_txpwr(UINT32 rate, UINT32 channel, UINT32 pwr_gain); + manual_cal_save_txpwr(EVM_DEFUALT_BLE_RATE, channel, pwr_idx); + + } else { + bk_printf("unknow dut cmd\r\n"); + } + break; + case USER_SEND_CMD: + if (length == 3) { + uint8_t channel = buff[1]; + tx_mode = buff[2]; + if (channel > 39) + channel = 39; + + uint32_t freq = (uint32_t)((channel + 1) * 2); + + ble_ctrl(CMD_BLE_SET_CHANNEL, &freq); + ble_ctrl(CMD_BLE_START_TX, &tx_mode); + + ble_test_mode = USER_TX_MODE; + } else { + bk_printf("unknow dut cmd\r\n"); + } + break; + case USER_STOP_CMD: + if (length == 2) { + if (buff[1] == USER_SEND_CMD) { + ble_ctrl(CMD_BLE_STOP_TX, NULL); + ble_test_mode = IDLE_MODE; + } else { + bk_printf("unknow dut cmd"); + } + } else { + bk_printf("unknow dut cmd"); + } + break; + default: + break; + } +} + +extern int bkreg_run_command(const char *content, int cnt); +void ble_uart_isr(void) +{ + UINT32 status; + UINT32 intr_en; + UINT32 intr_status; + + intr_en = REG_READ(REG_UART1_INTR_ENABLE); + intr_status = REG_READ(REG_UART1_INTR_STATUS); + REG_WRITE(REG_UART1_INTR_STATUS, intr_status); + status = intr_status & intr_en; + + if (status & (RX_FIFO_NEED_READ_STA | UART_RX_STOP_END_STA)) { + while(REG_READ(REG_UART1_FIFO_STATUS) & FIFO_RD_READY) + { + uart_rx_buf[uart_rx_index] = ((REG_READ(REG_UART1_FIFO_PORT) >> UART_RX_FIFO_DOUT_POSI) & UART_RX_FIFO_DOUT_MASK); + uart_rx_index++; + if (uart_rx_index == UART_FIFO_MAX_COUNT) { + uart_rx_index = 0; + } + } + + if ((uart_rx_buf[0] == 0x01) && (uart_rx_buf[1] == 0xe0) && (uart_rx_buf[2] == 0xfc)) { + if (uart_rx_buf[3] == (uart_rx_index - 4)) { + uart_rx_cmd_handler((uint8_t *)&uart_rx_buf[4], uart_rx_buf[3]); + bkreg_run_command((char*)&uart_rx_buf[0], uart_rx_index); + } + } + + if ((uart_rx_buf[0] == 0x01) && ((uart_rx_buf[3] + 4) == uart_rx_index) + && (uart_rx_buf[1] != 0xe0) && (uart_rx_buf[2] != 0xfc)) { + if (ble_test_mode == USER_TX_MODE) { + bk_printf("user test is running\r\n"); + } else { + host_send_cmd(uart_rx_buf, uart_rx_index); + } + } + + // work around:ble dut have own print show command success, wo should not add print + if ((uart_rx_buf[0] == 0x01) && (uart_rx_buf[1] == 0x1e) && (uart_rx_buf[2] == 0x20)) { +#if (CFG_SUPPORT_MANUAL_CALI) + extern uint8_t manual_cal_get_ble_pwr_idx(uint8_t channel); + tx_pwr_idx = manual_cal_get_ble_pwr_idx(uart_rx_buf[4]); +#endif + extern void ble_cal_set_txpwr(uint8_t idx); + ble_cal_set_txpwr(tx_pwr_idx); + bk_printf("c:%d\r\n", uart_rx_buf[4]); + } + + uart_rx_index=0; + uart_rx_done = 1; + } +} + +volatile struct hci_cmd_event_data host_cmd_data; +volatile struct hci_cmd_event_data host_event_data; + +void hci_data_init(uint8_t type) +{ ////type: 0x01-Clear host cmd data; 0x02-Clear host event data + + if(type & HCI_DATA_TYPE_CMD) + { + host_cmd_data.callback = NULL; + memset((void *)&host_cmd_data.data_buf[0], 0, HCI_DATA_BUF_SIZE); + host_cmd_data.data_len = 0; + } + if(type & HCI_DATA_TYPE_EVENT) + { + //// host_event_data.callback = NULL; ////Will clear callback func + memset((void *)&host_event_data.data_buf[0], 0, HCI_DATA_BUF_SIZE); + host_event_data.data_len = 0; + } +} + +void host_send_cmd(uint8_t *bufptr, uint16_t length) +{ + //uint16_t tmpCnt = 0; + BLE_ASSERT_ERR(length <= HCI_DATA_BUF_SIZE); + host_cmd_data.callback = NULL; ////Test Only + memcpy((void *)&host_cmd_data.data_buf[0], bufptr, length); + host_cmd_data.data_len = length; + ble_send_msg(BLE_MSG_DUT); +} + +////void host_get_event(uint8 *bufptr, uint8 length) +void host_get_event(void) +{ + + if(host_event_data.callback != NULL) + { + host_event_data.callback((void *)host_event_data.data_buf, host_event_data.data_len); + } + hci_data_init(HCI_DATA_TYPE_EVENT); +} + +void host_get_event_cbReg(void (*callback) (void*, uint16_t)) +{ + host_event_data.callback = callback; +} + +void uart_h4tl_data_switch(void) +{ + void (*callback) (void*, uint8_t) = NULL; + void* data =NULL; + uint16_t data_len = 0; + + while(uart_env.uart_tx_enable == 1) + { + //uart_printf("uart_h4tl_data_switch tx_enable\r\n"); + // Retrieve callback pointer + callback = uart_env.tx.callback; + data = uart_env.tx.dummy; + + uart_env.uart_tx_enable = 0; + memcpy((void *)&host_event_data.data_buf[data_len], uart_env.uart_tx_buf, uart_env.uart_tx_length); + data_len += uart_env.uart_tx_length; + host_event_data.data_len += uart_env.uart_tx_length; + if(callback != NULL) + { + // Clear callback pointer + uart_env.tx.callback = NULL; + uart_env.tx.dummy = NULL; + + // Call handler + callback(data, RWIP_EIF_STATUS_OK); + } + else + { + BLE_ASSERT_ERR(0); + } + } + + if(host_event_data.data_len != 0) + { ////New Event + host_get_event(); + } + + data_len = 0; + + if(host_cmd_data.data_len > 0) + { + while(uart_env.uart_rx_enable == 1) + { + // Retrieve callback pointer + callback = uart_env.rx.callback; + data = uart_env.rx.dummy; + uart_env.uart_rx_enable = 0; + + memcpy((void *)uart_env.uart_rx_buf, (void *)&host_cmd_data.data_buf[data_len], uart_env.uart_rx_length); + + data_len += uart_env.uart_rx_length; + if(callback != NULL) + { + // Clear callback pointer + uart_env.rx.callback = NULL; + uart_env.rx.dummy = NULL; + + // Call handler + callback(data, RWIP_EIF_STATUS_OK); + } + else + { + BLE_ASSERT_ERR(0); + } + if(data_len >= host_cmd_data.data_len) + break; + }////while(uart_env.uart_rx_enable == 1) + + ////Clear HCI Cmd data + hci_data_init(HCI_DATA_TYPE_CMD); + } +} + diff --git a/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/driver/uart/uart_ble.h b/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/driver/uart/uart_ble.h new file mode 100755 index 0000000..c7b8d4e --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/driver/uart/uart_ble.h @@ -0,0 +1,89 @@ + +#ifndef __UART_BLE_H__ +#define __UART_BLE_H__ + +#define HCI_DATA_BUF_SIZE 512 +#define UART_FIFO_MAX_COUNT 128 +#define HCI_DATA_TYPE_CMD 0x01 +#define HCI_DATA_TYPE_EVENT 0x02 + +enum +{ + UART_CMD_STATE_HEAD, + UART_CMD_STATE_OPCODE_ONE, + UART_CMD_STATE_OPCODE_TWO, + UART_CMD_STATE_LENGTH, + UART_CMD_STATE_CMD, +}; + +enum +{ + EXIT_DUT_CMD = 0x0E, + EXIT_DUT_ACT = 0xA0, + TX_PWR_SET_CMD = 0x10, + TX_PWR_SAVE_CMD = 0x11, + XTAL_SET_CMD = 0x12, + USER_SEND_CMD = 0x21, + USER_STOP_CMD = 0x2F, +}; + +enum +{ + IDLE_MODE = 0, + USER_TX_MODE = 1, + DUT_MODE = 2, +}; + +/// UART TX RX Channel +struct uart_txrxchannel +{ + /// call back function pointer + void (*callback) (void*, uint8_t); + /// Dummy data pointer returned to callback when operation is over. + void* dummy; +}; + +/// UART environment structure +struct uart_env_tag +{ + /// tx channel + struct uart_txrxchannel tx; + /// rx channel + struct uart_txrxchannel rx; + /// error detect + uint8_t errordetect; + /// external wakeup + bool ext_wakeup; + //// Modified + uint8_t *uart_tx_buf; + uint8_t *uart_rx_buf; + uint32_t uart_tx_length; + uint32_t uart_rx_length; + uint8_t uart_tx_enable; ////Maybe no need + uint8_t uart_rx_enable; ////Maybe no need + uint8_t uart_download_state; +}; + +struct hci_cmd_event_data +{ + /// call back function pointer + void (*callback) (void*, uint16_t); + /// Dummy data pointer returned to callback when operation is over. + uint8_t data_buf[HCI_DATA_BUF_SIZE]; + uint32_t data_len; +}; + +void ble_uart_init(void); +void ble_uart_read(uint8_t *bufptr, uint32_t size, void (*callback) (void*, uint8_t), void* dummy); +void ble_uart_write(uint8_t *bufptr, uint32_t size, void (*callback) (void*, uint8_t), void* dummy); +void host_get_event_cbReg(void (*callback) (void*, uint16_t)); +void uart_h4tl_data_switch(void); +void host_get_event(void); +void host_send_cmd(uint8_t *bufptr, uint16_t length); +void hci_data_init(uint8_t type); +void ble_uart_send(void *buff, uint16_t len); +void ble_uart_flow_on(void); +bool ble_uart_flow_off(void); +void ble_uart_isr(void); + +#endif \ No newline at end of file diff --git a/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/entry/ble.h b/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/entry/ble.h new file mode 100755 index 0000000..ac6b83d --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/entry/ble.h @@ -0,0 +1,50 @@ + +#ifndef __BLE_H_ +#define __BLE_H_ + +#define BLE_CONN_IDX_MAX (0x01) +#define BLE_CHAR_DATA_LEN (128) + +#define BLE_MSG_QUEUE_COUNT (20) +#define BLE_STACK_SIZE (3072) + +// ble dut uart port +#define PORT_UART1 (1) +#define PORT_UART2 (2) +#define BLE_DUT_UART_PORT PORT_UART1 // PORT_UART2 + +enum +{ + BLE_MSG_POLL = 0, + BLE_MSG_DUT, + BLE_DUT_START, + BLE_DUT_EXIT, + BLE_MSG_SLEEP, + BLE_MSG_NULL, +}; + +enum { + BLE_SCAN_CLOSED = 0, + BLE_SCAN_OPENED, +}; + +enum { + RF_USER_BLE, + RF_USER_WIFI, +}; + +enum system_run_mode { + NORMAL_MODE = 0, + DUT_FCC_MODE = (0x01 << 0), +}; + +typedef struct ble_message { + uint32_t data; +} BLE_MSG_T; + +uint8_t ble_get_sys_mode(void); +void ble_send_msg(UINT32 data); +UINT32 ble_ctrl( UINT32 cmd, void *param ); + +#endif + diff --git a/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/entry/ble_main.c b/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/entry/ble_main.c new file mode 100755 index 0000000..0b3b626 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/entry/ble_main.c @@ -0,0 +1,549 @@ +/** + **************************************************************************************** + * + * @file arch_main.c + * + * @brief Main loop of the application. + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ +#include "rwip_config.h" // RW SW configuration +#include "architect.h" // architectural platform definitions +#include // standard lib functions +#include // standard definitions +#include // standard integer definition +#include // boolean definition +#include // boolean definition +#include "rwip.h" // RW SW initialization +#include "prf.h" // RW SW initialization +#include "rwble.h" +#include "uart_pub.h" +#include "rtos_pub.h" +#include "ble.h" +#include "ble_pub.h" +#include "ble_api.h" +#include "sys_ctrl_pub.h" +#include "icu_pub.h" +#include "intc_pub.h" +#include "drv_model_pub.h" +#include "uart_ble.h" +#include "ble_reg_blecore.h" +#include "BK3633_RegList.h" +#include "param_config.h" +#include "common_utils.h" + +beken_queue_t ble_msg_que = NULL; +beken_thread_t ble_thread_handle = NULL; +uint8_t ble_system_mode; +uint8_t tx_pwr_idx; + +enum { + DUT_IDLE, + DUT_RUNNING, +}; + +uint8_t ble_dut_status = DUT_IDLE; + +#if CFG_USE_BK_HOST == 0 +#if CFG_USE_BLE_PS +static uint32_t ble_sleep_enable = 1; +#else +static uint32_t ble_sleep_enable = 0; +#endif +#endif + +const struct rwip_eif_api uart_api = +{ + ble_uart_read, + ble_uart_write, + ble_uart_flow_on, + ble_uart_flow_off, +}; + +struct ble_session_env ble_session_ctx = +{ + .ble_active = 0, + .system_sleep_flag = 0, + .ble_first_sleep = 1, + .ble_deep_sleep = 0, + .ble_init_over = 0, +}; + +void set_ble_active_status(char active) +{ + ble_session_ctx.ble_active = (active > 0)?1:0; +} + +int get_ble_active_status(void) +{ + return (ble_session_ctx.ble_active != 0)?1:0; +} + +static SDD_OPERATIONS ble_op = +{ + ble_ctrl +}; + +void assert_err(const char *condition, const char * file, int line) +{ + bk_printf("%s %s at %s:%d\r\n",__func__,condition,file,line); +} + +void assert_param(int param0, int param1, const char * file, int line) +{ + bk_printf("%s param0=%d,param1=%d at %s:%d\r\n",__func__,param0,param1,file,line); +} + +void assert_warn(int param0, int param1, const char * file, int line) +{ + bk_printf("%s param0=%d,param1=%d at %s:%d\r\n",__func__,param0,param1,file,line); +} + +void dump_data(uint8_t* data, uint16_t length) +{ + bk_printf("%s data=%d,length=%d at %s:%d\r\n",__func__,data,length); +} + +void platform_reset(uint32_t error) +{ + os_printf("reset error(%x)\r\n", error); + + //watch dog reset + extern void bk_reboot(void); + bk_reboot(); +} + +void ble_set_power_up(uint32 up) +{ + if (up) { + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_BLE_POWERUP, NULL); + } else { + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_BLE_POWERDOWN, NULL); + } +} +#include "common_bt_defines.h" +extern void wifi_get_mac_address(char *mac, u8 type); +void bdaddr_env_init(void) +{ + uint8_t sta_mac[BD_ADDR_LEN]; + uint8_t *ble_mac = &common_default_bdaddr.addr[0]; + + wifi_get_mac_address((char *)sta_mac, CONFIG_ROLE_STA); + sta_mac[5] += 1; // add 1, diff from wifi's mac + + for (int i = 0; i < BD_ADDR_LEN; i++) { + ble_mac[i] = sta_mac[BD_ADDR_LEN - 1 - i]; + } + os_printf("ble mac:%02x-%02x-%02x-%02x-%02x-%02x\r\n", + ble_mac[5], ble_mac[4], ble_mac[3], ble_mac[2], ble_mac[1], ble_mac[0]); +} + +void ble_sys_mode_init(uint8_t mode) +{ + ble_system_mode = mode; +} + +uint8_t ble_get_sys_mode(void) +{ + return ble_system_mode; +} + +void ble_clk_power_up(uint32 up) +{ + UINT32 param; + param = PWD_BLE_CLK_BIT; + + if (up) { + sddev_control(ICU_DEV_NAME, CMD_TL410_CLK_PWR_UP, ¶m); + } else { + sddev_control(ICU_DEV_NAME, CMD_TL410_CLK_PWR_DOWN, ¶m); + } +} + +void ble_intc_enable(uint32_t enable) +{ + if (enable) { + ble_rwblecntl_master_soft_rst_setf(1); + while(ble_rwblecntl_master_soft_rst_getf()); + ble_rwblecntl_reg_soft_rst_setf(1); + while(ble_rwblecntl_reg_soft_rst_getf()); + intc_enable(FIQ_BTDM); + intc_enable(FIQ_BLE); + } else { + intc_disable(FIQ_BTDM); + intc_disable(FIQ_BLE); + } +} + +void ble_btdm_isr(void) +{ + rwip_isr(); + ble_send_msg(BLE_MSG_POLL); + return; +} + +void ble_ble_isr(void) +{ + rwble_isr(); + ble_send_msg(BLE_MSG_POLL); + return; +} + +void ble_init(void) +{ + intc_service_register( FIQ_BLE, PRI_FIQ_BLE, ble_ble_isr ); + intc_service_register( FIQ_BTDM, PRI_FIQ_BTDM, ble_btdm_isr ); + + sddev_register_dev( BLE_DEV_NAME, &ble_op ); + + return; +} + +void ble_exit(void) +{ + sddev_unregister_dev( BLE_DEV_NAME ); + + return; +} + +void ble_send_msg(UINT32 data) +{ + OSStatus ret; + BLE_MSG_T msg; + + if (ble_msg_que) { + msg.data = data; + ret = rtos_push_to_queue(&ble_msg_que, &msg, BEKEN_NO_WAIT); + } + + (void)ret; +} + +extern int bk7011_reduce_vdddig_for_rx(int reduce); +extern void intc_service_change_handler(UINT8 int_num, FUNCPTR isr); +#define BLE_DUT_DIVISION (8) + +void enter_dut_fcc_mode(void) +{ + bk_printf("enter dut mode\r\n"); + uint32_t reg; + static uint32_t default_mclk_mux = MCLK_SELECT_DPLL; + static uint32_t default_mclk_div = BLE_DUT_DIVISION; + +#ifdef FOR_TEST +#if (BLE_DUT_UART_PORT == PORT_UART2) + intc_service_change_handler(IRQ_UART2, ble_uart_isr); +#else + intc_service_change_handler(IRQ_UART1, ble_uart_isr); +#endif +#endif + while (1) { + OSStatus err; + BLE_MSG_T msg; + + err = rtos_pop_from_queue(&ble_msg_que, &msg, BEKEN_WAIT_FOREVER); + if (kNoErr == err) { + switch (msg.data) { + case BLE_MSG_POLL: + //schedule all pending events + rwip_schedule(); + break; + case BLE_MSG_DUT: + //ble test code for debug pin + //ble_diagcntl_set(0x00008383); + uart_h4tl_data_switch(); + break; + case BLE_DUT_EXIT: + bk_printf("exit ble dut\r\n"); + bk7011_reduce_vdddig_for_rx(0); + ble_dut_status = DUT_IDLE; + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_MCLK_SELECT, &default_mclk_mux); + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_MCLK_DIVISION, &default_mclk_div); + + sddev_control(SCTRL_DEV_NAME, CMD_BLE_RF_BIT_CLR, NULL); + extern void ble_cal_recover_txpwr(void); + ble_cal_recover_txpwr(); +#if (BLE_DUT_UART_PORT == PORT_UART2) + intc_service_change_handler(IRQ_UART2, uart2_isr); +#else + intc_service_change_handler(IRQ_UART1, uart1_isr); +#endif + break; + case BLE_DUT_START: + bk_printf("enter ble dut\r\n"); + bk7011_reduce_vdddig_for_rx(1); + ble_dut_status = DUT_RUNNING; + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_MCLK_MUX_GET, &default_mclk_mux); + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_MCLK_DIV_GET, &default_mclk_div); + reg = MCLK_SELECT_DPLL; + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_MCLK_SELECT, ®); + reg = BLE_DUT_DIVISION; + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_MCLK_DIVISION, ®); + + sddev_control(SCTRL_DEV_NAME, CMD_BLE_RF_BIT_SET, NULL); + extern void ble_cal_set_txpwr(uint8_t idx); + ble_cal_set_txpwr(tx_pwr_idx); +#if (BLE_DUT_UART_PORT == PORT_UART2) + intc_service_change_handler(IRQ_UART2, ble_uart_isr); +#else + intc_service_change_handler(IRQ_UART1, ble_uart_isr); +#endif + break; + default: + break; + } + } + } +} + +extern UINT32 ble_ps_enabled(void ); +void enter_normal_app_mode(void) +{ + //bk_printf("enter normal mode\r\n"); + + while (1) { + OSStatus err; + BLE_MSG_T msg; + + err = rtos_pop_from_queue(&ble_msg_que, &msg, BEKEN_WAIT_FOREVER); + if (kNoErr == err) { + switch (msg.data) { + case BLE_MSG_POLL: + //schedule all pending events + //ble test code for debug pin + //ble_diagcntl_set(0x00008383); + rwip_schedule(); + break; + default: + break; + } + } + + if (ble_ps_enabled()) + { + GLOBAL_INT_DIS(); + rwip_sleep(); + GLOBAL_INT_RES(); + } + } +} + +extern void ble_thread_exit_cb(void); +extern uint32_t get_ate_mode_state(void); +void ble_thread_main(void *arg) +{ + ble_set_power_up(1); + + ble_clk_power_up(1); + + ble_intc_enable(1); + + if (get_ate_mode_state()) { + ble_sys_mode_init(DUT_FCC_MODE); + } else { + ble_sys_mode_init(NORMAL_MODE); + } + + bdaddr_env_init(); + + ble_uart_init(); + +#if defined(CFG_PTA_SWITCH_RF_EN) && (CFG_PTA_SWITCH_RF_EN == 0) + *(volatile unsigned int *)(0x800008) &= 0xFEFFFFFF; ////PTA disable +#else + *(volatile unsigned int *)(0x800008) |= (~0xFEFFFFFFU); ////PTA disable +#endif + +#if (NVDS_SUPPORT) + nvds_init(); +#endif + + rwip_init(0); + +#if (CFG_SUPPORT_MANUAL_CALI) + extern uint8_t manual_cal_get_ble_pwr_idx(uint8_t channel); + tx_pwr_idx = manual_cal_get_ble_pwr_idx(19); +#else + tx_pwr_idx = 16; +#endif + + os_null_printf("tx_pwr_idx:%d\r\n", tx_pwr_idx); + + if (ble_get_sys_mode() == DUT_FCC_MODE) { + enter_dut_fcc_mode(); + } else { + enter_normal_app_mode(); + } + + ble_thread_exit_cb(); + rtos_deinit_queue(&ble_msg_que); + ble_msg_que = NULL; + ble_thread_handle = NULL; + rtos_delete_thread(NULL); +} + +void ble_entry(void) +{ + OSStatus ret; + + if (!ble_thread_handle && !ble_msg_que) { + ret = rtos_init_queue(&ble_msg_que, + "ble_msg_queue", + sizeof(BLE_MSG_T), + BLE_MSG_QUEUE_COUNT); + ASSERT(0 == ret); + + ret = rtos_create_thread(&ble_thread_handle, + 4, + "ble", + (beken_thread_function_t)ble_thread_main, + BLE_STACK_SIZE, + (beken_thread_arg_t)0); + + ASSERT(0 == ret); + } +} + +UINT32 ble_ctrl( UINT32 cmd, void *param ) +{ + UINT32 reg; + UINT32 ret = ERR_SUCCESS; + + switch (cmd) { + case CMD_BLE_REG_INIT: + break; + + case CMD_BLE_REG_DEINIT: + break; + + case CMD_BLE_SET_CHANNEL: + reg = REG_READ(BLE_XVR_REG24); + reg &= ~(BLE_XVR_CHAN_MASK << BLE_XVR_CHAN_POST); + reg |= (*(UINT32 *)param) << BLE_XVR_CHAN_POST; + REG_WRITE(BLE_XVR_REG24, reg); + break; + + case CMD_BLE_START_TX: + reg = REG_READ(BLE_XVR_REG24); + reg &= ~(BLE_XVR_AUTO_CHAN_MASK << BLE_XVR_AUTO_CHAN_POST); + REG_WRITE(BLE_XVR_REG24, reg); + if ((*(UINT8 *)param) == 0x00) { + reg = 0x3800; + } else if ((*(UINT8 *)param) == 0x01) { + reg = 0x3100; + } else { + os_null_printf("unknow ble test mode\r\n"); + } + REG_WRITE(BLE_XVR_REG25, reg); + break; + + case CMD_BLE_STOP_TX: + reg = REG_READ(BLE_XVR_REG24); + reg |= (BLE_XVR_AUTO_CHAN_MASK << BLE_XVR_AUTO_CHAN_POST); + REG_WRITE(BLE_XVR_REG24, reg); + reg = 0; + REG_WRITE(BLE_XVR_REG25, reg); + break; + + default: + ret = ERR_CMD_NOT_SUPPORT; + break; + } + + return ret; +} + +UINT8 ble_is_start(void) +{ + return (ble_thread_handle == NULL)? 0:1; +} + +extern void ble_switch_rf_to_wifi(void); +void ble_thread_exit_cb(void) +{ + + if(ble_ps_enabled()) + { + GLOBAL_INT_DIS(); + #if CFG_USE_BLE_PS + sctrl_rf_wakeup(); + ble_switch_rf_to_wifi(); + #endif + ble_session_ctx.ble_deep_sleep = 0; + ble_session_ctx.ble_first_sleep = 1; + ble_session_ctx.ble_sleep_enable = 0; + ble_session_ctx.ble_init_over = 0; + GLOBAL_INT_RES(); + } + set_ble_active_status(0); + + ble_switch_rf_to_wifi(); +} + +void ble_dut_start(void) +{ + ble_send_msg(BLE_DUT_START); +} + +UINT32 ble_in_dut_mode(void) +{ + return (ble_dut_status == DUT_IDLE) ? 0 : 1; +} + +const struct rwip_eif_api* rwip_eif_get(uint8_t idx) +{ + return &uart_api; +} + +void ble_update_tx_pwr(void) +{ +#if (CFG_SUPPORT_MANUAL_CALI) + extern uint8_t manual_cal_get_ble_pwr_idx(uint8_t channel); + tx_pwr_idx = manual_cal_get_ble_pwr_idx(19); +#else + tx_pwr_idx = 16; +#endif +} + +#if CFG_USE_BK_HOST == 0 +void ble_ps_enable_set(void) +{ + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + ble_sleep_enable = 1; + GLOBAL_INT_RESTORE(); +} + +void ble_ps_enable_clear(void) +{ + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + ble_sleep_enable = 0; + GLOBAL_INT_RESTORE(); +} + +UINT32 ble_ps_enabled(void ) +{ + uint32_t value = 0; + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + value = ble_sleep_enable; + GLOBAL_INT_RESTORE(); + return value; +} + +#define SYS_CTRL_BASE_ADDRESS 0x800000 + +void ble_set_ext_wkup(uint8_t enable) +{ + if (enable) { + *(volatile unsigned int *)(SYS_CTRL_BASE_ADDRESS + 0xD * 4) |= 0x1 << 27; + } else { + *(volatile unsigned int *)(SYS_CTRL_BASE_ADDRESS + 0xD * 4) &= ~(0x1 << 27); + } +} +#endif + diff --git a/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/nvds/api/nvds.h b/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/nvds/api/nvds.h new file mode 100755 index 0000000..5899871 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/nvds/api/nvds.h @@ -0,0 +1,216 @@ +/** + **************************************************************************************** + * + * @file nvds.h + * + * @brief Non Volatile Data Storage (NVDS) driver + * + * Copyright (C) RivieraWaves 2009-2015 + * + **************************************************************************************** + */ +#ifndef _NVDS_H_ +#define _NVDS_H_ + +/** + **************************************************************************************** + * @addtogroup NVDS + * @ingroup COMMON + * @brief Non Volatile Data Storage (NVDS) + * + * Parameters management + * there are two compilation options: + * + NVDS_8BIT_TAGLENGTH : + * if set, each TAG has a maximum length of 256 bytes + * if not set, each TAG has a maximum length of 65536 bytes + * + NVDS_PACKED : + * if not set, all the TAG header structures and TAG data contents are stored with an + * alignment on 32 bit boundary + * if set, all the TAG header structures and TAG data contents are stored + * consecutively without gaps (as would be a structure with pragma packed) + * + NVDS_READ_WRITE : + * if not set, only GET action on TAGs is provided. + * if set, PUT/DEL/LOCK actions are provided in addition of GET action. + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include // boolean definition +#include // integer definition + + +/* + * DEFINES + **************************************************************************************** + */ + +/// NVDS is defined as read-write +#define NVDS_READ_WRITE 1 + +/// NVDS is defined as packed +#define NVDS_PACKED 1 + +/// NVDS has 8-bit length tags +#define NVDS_8BIT_TAGLENGTH 1 + +/// Type of the tag length (8 or 16 bits) +#if (NVDS_8BIT_TAGLENGTH) +typedef uint8_t nvds_tag_len_t; +#else +typedef uint16_t nvds_tag_len_t; +#endif // NVDS_8BIT_TAGLENGTH + +/// Environment structure of the NVDS module +struct nvds_env_tag +{ + /// Function to read the device Address being in the NVDS memory space + void (*read)(uint32_t const address, + uint32_t const length, + uint8_t* const buf); + /// Function to write the device Address being in the NVDS memory space + void (*write)(uint32_t const address, + uint32_t const length, + uint8_t* const buf); + /// Function to erase the entire NVDS memory space + void (*erase)(uint32_t const address, + uint32_t const length); + + /// NVDS base pointer + uint8_t *nvds_space; + + /// Total size of the NVDS area + uint32_t total_size; + + /// Flash ID + uint8_t flash_id; +}; + + +/* + * ENUMERATION DEFINITIONS + **************************************************************************************** + */ + +/// Possible Returned Status +enum NVDS_STATUS +{ + /// NVDS status OK + NVDS_OK, + /// generic NVDS status KO + NVDS_FAIL, + /// NVDS TAG unrecognized + NVDS_TAG_NOT_DEFINED, + /// No space for NVDS + NVDS_NO_SPACE_AVAILABLE, + /// Length violation + NVDS_LENGTH_OUT_OF_RANGE, + /// NVDS parameter locked + NVDS_PARAM_LOCKED, + /// NVDS corrupted + NVDS_CORRUPT +}; + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Initialize NVDS. + * @return NVDS_OK + **************************************************************************************** + */ +uint8_t nvds_init(void); + +/** + **************************************************************************************** + * @brief Look for a specific tag and return, if found and matching (in length), the + * DATA part of the TAG. + * + * If the length does not match, the TAG header structure is still filled, in order for + * the caller to be able to check the actual length of the TAG. + * + * @param[in] tag TAG to look for whose DATA is to be retrieved + * @param[in] length Expected length of the TAG + * @param[out] buf A pointer to the buffer allocated by the caller to be filled with + * the DATA part of the TAG + * + * @return NVDS_OK The read operation was performed + * NVDS_LENGTH_OUT_OF_RANGE The length passed in parameter is different than the TAG's + **************************************************************************************** + */ +uint8_t nvds_get(uint8_t tag, nvds_tag_len_t * lengthPtr, uint8_t *buf); + +#if (NVDS_READ_WRITE == 1) + +/** + **************************************************************************************** + * @brief Look for a specific tag and delete it (Status set to invalid) + * + * Implementation notes + * 1. The write function call return status is not handled + * + * @param[in] tag TAG to mark as deleted + * + * @return NVDS_OK TAG found and deleted + * NVDS_PARAM_LOCKED TAG found but can not be deleted because it is locked + * (others) return values from function call @ref nvds_browse_tag + **************************************************************************************** + */ +uint8_t nvds_del(uint8_t tag); + +/** + **************************************************************************************** + * @brief Look for a specific tag and lock it (Status lock bit set to LOCK). + * + * The write function call return status is not handled + * + * @param[in] tag TAG to mark as locked + * + * @return NVDS_OK TAG found and locked + * (others) return values from function call @ref nvds_browse_tag + **************************************************************************************** + */ +uint8_t nvds_lock(uint8_t tag); + +/** + **************************************************************************************** + * @brief This function adds a specific TAG to the NVDS. + * + * Steps: + * 1) parse all the TAGs to: + * 1.1) calculate the total size of all the valid TAGs + * 1.2) erase the existing TAGs that have the same ID + * 1.3) check if we can use the same TAG area in case of an EEPROM + * 1.4) check that the TAG is not locked + * 2) if we have to add the new TAG at the end fo the NVDS (cant use same area): + * 2.1) allocate the appropriate amount of memory + * 2.2) purge the NVDS + * 2.3) free the memory allocated + * 2.4) check that there is now enough room for the new TAG or return + * NO_SPACE_AVAILABLE + * 3) add the new TAG + * + * @param[in] tag TAG to look for whose DATA is to be retrieved + * @param[in] length Expected length of the TAG + * @param[in] buf Pointer to the buffer containing the DATA part of the TAG to add to + * the NVDS + * + * @return NVDS_OK New TAG correctly written to the NVDS + * NVDS_PARAM_LOCKED New TAG is trying to overwrite a TAG that is locked + * NO_SPACE_AVAILABLE New TAG can not fit in the available space in the NVDS + **************************************************************************************** + */ +uint8_t nvds_put(uint8_t tag, nvds_tag_len_t length, uint8_t *buf); + +#endif //(NVDS_READ_WRITE == 1) + +/// @} NVDS + +#endif // _NVDS_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/nvds/src/nvds.c b/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/nvds/src/nvds.c new file mode 100755 index 0000000..f5105db --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/nvds/src/nvds.c @@ -0,0 +1,770 @@ +/** + **************************************************************************************** + * + * @file nvds.c + * + * @brief Non Volatile Data Storage (NVDS) driver + * + * Copyright (C) RivieraWaves 2009-2015 + * + * + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @addtogroup NVDS + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include // string definitions +#include // standard definitions +#include // limits definitions +#include "nvds.h" // nvds definitions +#include "architect.h" // main +#include "common_math.h" // math operations +#include "flash.h" // flash definition +/* + * DEFINES + **************************************************************************************** + */ + +/// NVDS parameter data maximum length +#if NVDS_8BIT_TAGLENGTH +#define NVDS_PARAMETER_MAX_LENGTH UCHAR_MAX +#else // NVDS_8BIT_TAGLENGTH +#define NVDS_PARAMETER_MAX_LENGTH USHRT_MAX +#endif // NVDS_8BIT_TAGLENGTH + +/// TAG STATUS bit assignment +#define NVDS_STATUS_VALID_MASK 0x01 +#define NVDS_STATUS_VALID 0x00 +#define NVDS_STATUS_NOT_VALID 0x01 +#define NVDS_STATUS_LOCKED_MASK 0x02 +#define NVDS_STATUS_LOCKED 0x00 +#define NVDS_STATUS_NOT_LOCKED 0x02 +#define NVDS_STATUS_ERASED_MASK 0x04 +#define NVDS_STATUS_ERASED 0x00 +#define NVDS_STATUS_NOT_ERASED 0x04 + +#if (NVDS_READ_WRITE == 1) +/// Max storage for the NVDS device which can be used for tags +#define NVDS_MAX_STORAGE_SIZE 0x0200 // 512B +#endif //(NVDS_READ_WRITE == 1) + +// NVDS Mapping + +/// Magic number offset +#define NVDS_MAGIC_NUMBER_ADDRESS 0x7F000 +/// Size of magic number +#define NVDS_MAGIC_NUMBER_LENGTH 4 + +/// Start of NVDS data +#if (NVDS_PACKED == 1) +#define NVDS_START_STORAGE_AREA_ADDRESS \ + NVDS_MAGIC_NUMBER_ADDRESS + NVDS_MAGIC_NUMBER_LENGTH +#else //(NVDS_PACKED == 0) +#define NVDS_START_STORAGE_AREA_ADDRESS \ + COMMON_ALIGN4_HI(NVDS_MAGIC_NUMBER_ADDRESS) + \ + COMMON_ALIGN4_HI(NVDS_MAGIC_NUMBER_LENGTH) +#endif //(NVDS_PACKED == 1) + +/// Value found in flash when nothing has been written +#define NVDS_NO_TAG 0xFF + + +/* + * MACROS + **************************************************************************************** + */ + +/// Check is tag is the last one +#define NVDS_IS_TAG_LAST(h) \ + ((h).tag == NVDS_NO_TAG) +/// Check is tag is valid +#define NVDS_IS_TAG_OK(h) \ + ((((h).status) & (NVDS_STATUS_VALID_MASK|NVDS_STATUS_ERASED_MASK)) == \ + (NVDS_STATUS_VALID|NVDS_STATUS_NOT_ERASED)) +/// Check is tag is locked +#define NVDS_IS_TAG_LOCKED(h) \ + ((((h).status) & NVDS_STATUS_LOCKED_MASK) == NVDS_STATUS_LOCKED) +/// Set tag as erased +#define NVDS_SET_TAG_ERASED(h) \ + ((((h).status) & (~NVDS_STATUS_ERASED_MASK)) | NVDS_STATUS_ERASED) +/// Set tag as locked +#define NVDS_SET_TAG_LOCKED(h) \ + ((((h).status) & (~NVDS_STATUS_LOCKED_MASK)) | NVDS_STATUS_LOCKED) +/// Set tag as valid +#define NVDS_SET_TAG_OK(h) \ + (NVDS_STATUS_VALID | NVDS_STATUS_NOT_LOCKED | NVDS_STATUS_NOT_ERASED) + + +/// Macro for alignment +#if (NVDS_PACKED == 1) +#define NVDS_ALIGNMENT(p) (p) +#else //(NVDS_PACKED == 0) +#define NVDS_ALIGNMENT(p) COMMON_ALIGN4_HI(p) +#endif //(NVDS_PACKED == 1) + +/// Length of tag header +#define NVDS_TAG_HEADER_LENGTH \ + NVDS_ALIGNMENT(sizeof(struct nvds_tag_header)) +/// Length of tag data +#define NVDS_TAG_CONTENT_LENGTH(h) \ + NVDS_ALIGNMENT((h).length) +/// Full length of tag (header+data) +#define NVDS_TAG_FULL_LENGTH(h) \ + NVDS_TAG_HEADER_LENGTH + NVDS_TAG_CONTENT_LENGTH(h) + +/* + * STRUCT DEFINITIONS + **************************************************************************************** + */ + +/// Structure defining the header of a TAG. It is very important that the TAG remains +/// the first element of the structure because it defines the LAST TAG of the NVDS when +/// set the oxFF. +struct nvds_tag_header +{ + /// current TAG identifier + uint8_t tag; + /// status of the TAG (erased, locked ...) + uint8_t status; + /// length of the TAG + nvds_tag_len_t length; +}; + + + + +/* + * GLOBAL VARIABLE DECLARATIONS + **************************************************************************************** + */ +/// NVDS magic number keyword +static const uint8_t nvds_magic_number[NVDS_MAGIC_NUMBER_LENGTH] = {'N', 'V', 'D', 'S'}; + +/// NVDS environment +static struct nvds_env_tag nvds_env; + +/* + * LOCAL FUNCTION DECLARATION + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Check if the current NVDS has the correct magic number set. + * + * Implementation notes:we do not put an assert on the read access because we could be in + * the situation of a dummy read (returns always NVDS_FAIL) and we want to return + * correctly the FALSE. + * + * @return True if the NVDS has the Magic Number set, false otherwise. + **************************************************************************************** + */ +static bool nvds_is_magic_number_ok(void); + +/** + **************************************************************************************** + * @brief Look for a specific TAG. + * + * If found, it returns the address and the header, otherwise the TAG address returned + * points to a location where it is possible to store a new TAG. + * The TAG is returned only if it is valid (not erased). This function is useful to find + * a single valid TAG element or find the next available space for a new TAG. + * + * @param[in] tag TAG to look for + * @param[out] nvds_tag_header_ptr Pointer to the TAG header structure allocated by the + * caller to contain the searched TAG header + * @param[out] tag_address_ptr Pointer to the NVDS address at which TAG was found + * (returned) or if the TAG was not found, first address + * free for storing new TAG in NVDS + * + * @return Return codes from the @ref nvds_walk_tag function call + **************************************************************************************** + */ +static uint8_t nvds_browse_tag(uint8_t tag, + struct nvds_tag_header *nvds_tag_header_ptr, + uint32_t *tag_address_ptr); + +/** + **************************************************************************************** + * @brief Read the TAG header that MUST be present at NVDS address cur_tag_addr and fill + * the TAG header structure that is allocated by the caller and referenced by + * nvds_tag_header_ptr. + * + * Upon completion of the read, the next TAG address is computed and returned to the + * caller through nxt_tag_addr_ptr (except if the current TAG is the LAST one). + * If the caller wishes to read the first TAG of the NVDS, the value + * NVDS_START_STORAGE_AREA_ADDRESS can be used as the cur_tag_addr. + * If the current Address specified is pointing at the position of the last element of + * the NVDS the function returns NVDS_TAG_NOT_DEFINED. In this case, there is NO VALUE + * returned through nxt_tag_addr_ptr. The cur_tag_addr is already pointing to an empty + * TAG. + * The TAG read is not check for validity, this information should be handled by the + * caller if he wishes to use the TAG information correctly. + * + * @param[in] cur_tag_addr Address of the current TAG in NVDS memory space + * @param[out] nvds_tag_header_ptr A pointer to an allocated space for the parameter header + * @param[out] nxt_tag_addr_ptr A pointer to the next TAG address in the NVDS memory space + * + * @return NVDS_OK TAG read, header filled and next TAG address filled + * NVDS_TAG_NOT_DEFINED Last TAG reached, header filled with garbage + * NVDS_CORRUPT Current TAG is overcoming the NVDS size limit + **************************************************************************************** + */ +static uint8_t nvds_walk_tag (uint32_t cur_tag_addr, + struct nvds_tag_header *nvds_tag_header_ptr, + uint32_t *nxt_tag_addr_ptr); + +/** + **************************************************************************************** + * @brief Hook a dummy driver to the NVDS. + * If no valid NVDS media was found, to avoid incorrect behavior a dummy driver should + * be hooked to the NVDS. + * + * @return NVDS_OK + **************************************************************************************** + */ +static uint8_t nvds_null_init(void); + +/** + **************************************************************************************** + * @brief Dummy function to safely replace Read function + * + * @param[in] address Start address of the data to read from NVDS + * @param[in] length Length of the data to read from NVDS + * @param[in] buf Pointer to the buffer containing the DATA to read from the NVDS + **************************************************************************************** + */ +static void nvds_null_read(uint32_t address, uint32_t length, uint8_t *buf); + +/** + **************************************************************************************** + * @brief Dummy function to safely replace Write function + * + * @param[in] address NVDS address at which the write operation must be performed + * @param[in] length Length of the write operation to perform + * @param[in] buf Pointer to a buffer containing the data to write + **************************************************************************************** + */ +static void nvds_null_write(uint32_t address, uint32_t length, uint8_t *buf); + +/** + **************************************************************************************** + * @brief Dummy function to safely replace Erase function + * @param[in] address NVDS address at which the erase operation must be performed + * @param[in] length Length of the erase operation to perform + **************************************************************************************** + */ +static void nvds_null_erase(uint32_t address, uint32_t length); + +/** + **************************************************************************************** + * @brief Read data from NVDS. + * + * @param[in] address Start address of the data to read from NVDS + * @param[in] length Length of the data to read from NVDS + * @param[in] buf Pointer to the buffer containing the DATA to read from the NVDS + **************************************************************************************** + */ +static void nvds_read(uint32_t address, uint32_t length, uint8_t *buf); + +#if (NVDS_READ_WRITE == 1) +/** + **************************************************************************************** + * @brief Write data into NVDS + * + * @param[in] address Start address of the data to write to NVDS + * @param[in] length Length of the data to write to NVDS + * @param[in] buf Pointer to the buffer containing the DATA to write to the NVDS + **************************************************************************************** + */ +static void nvds_write(uint32_t address, uint32_t length, uint8_t *buf); + +/** + **************************************************************************************** + * @brief Erase data in NVDS + * + * @param[in] address Start address of the data to read from NVDS + * @param[in] length Length of the data to read from NVDS + **************************************************************************************** + */ +static void nvds_erase(uint32_t address, uint32_t length); + +/** + **************************************************************************************** + * @brief Initialize the NVDS memory. + * + * This function clears the entire memory content and writes the MagicNumber + **************************************************************************************** + */ +static void nvds_init_memory(void); + +/** + **************************************************************************************** + * @brief Purge NVDS memory + * + * This function performs a read of all the valid TAGs of the NVDS, stores them in + * the temporary buffer allocated by the caller, flushes the NVDS and then rewrites all + * the valid TAGs. + * + * It is used to purge the NVDS when there is no more space to store a new TAG for + * example or regularly to save TAG browse time. + * + * @param[in] length Length of the buffer allocated to perform the temporary storage of + * the NVDS while purging (erase and compress) + * @param[in] buf A pointer to the buffer allocated by the caller for the temporary + * storage of the NVDS while purging + **************************************************************************************** + */ +static void nvds_purge(uint32_t length, uint8_t* buf); +#endif //(NVDS_READ_WRITE == 1) + +/* + * LOCAL FUNCTION DEFINITIONS + **************************************************************************************** + */ + +static bool nvds_is_magic_number_ok(void) +{ + bool is_magic_number_ok = false; + uint8_t read_magic_number[NVDS_MAGIC_NUMBER_LENGTH]; + + // Look for the magic number + nvds_env.read(NVDS_MAGIC_NUMBER_ADDRESS, sizeof(read_magic_number), read_magic_number); + + // Compare the read magic number with the correct value + if (memcmp(read_magic_number, nvds_magic_number, NVDS_MAGIC_NUMBER_LENGTH)==0) + { + is_magic_number_ok = true; + } + return is_magic_number_ok; +} + +static uint8_t nvds_walk_tag (uint32_t cur_tag_addr, + struct nvds_tag_header *nvds_tag_header_ptr, + uint32_t *nxt_tag_addr_ptr) +{ + uint8_t status = NVDS_OK; + + // Read the current parameter header + nvds_env.read((uint32_t)cur_tag_addr, + (uint32_t)sizeof(struct nvds_tag_header), + (uint8_t*)nvds_tag_header_ptr); + + // Check if the read operation completed successfully + if (!NVDS_IS_TAG_LAST(*nvds_tag_header_ptr)) + { + // Calculate the address of the next tag + *nxt_tag_addr_ptr = cur_tag_addr + NVDS_TAG_FULL_LENGTH(*nvds_tag_header_ptr); + + // Check if there is enough space to read next header + // the limit is set minus 1 because we need to leave at least an end marker + if ((*nxt_tag_addr_ptr - NVDS_MAGIC_NUMBER_ADDRESS) > (nvds_env.total_size - 1)) + { + // Going above NVDS limit, probably an error occurred + BLE_ASSERT_ERR(0); + status = NVDS_CORRUPT; + } + } + else + { + // this is beyond the last TAG + status = NVDS_TAG_NOT_DEFINED; + } + return(status); +} + +static uint8_t nvds_browse_tag (uint8_t tag, + struct nvds_tag_header *nvds_tag_header_ptr, + uint32_t *tag_address_ptr) +{ + uint8_t status; + uint32_t cur_tag_addr, nxt_tag_addr; + + // set the address to the first data byte of the NVDS + nxt_tag_addr = NVDS_START_STORAGE_AREA_ADDRESS; + + do + { + // go to the next tag + cur_tag_addr = nxt_tag_addr; + + // retrieve the parameter header + status = nvds_walk_tag(cur_tag_addr, nvds_tag_header_ptr, &nxt_tag_addr); + + } while ((status == NVDS_OK) && + !((nvds_tag_header_ptr->tag == tag) && NVDS_IS_TAG_OK(*nvds_tag_header_ptr))); + + // the returned address is the last address found + *tag_address_ptr = cur_tag_addr; + + return(status); +} + +static void nvds_null_read(uint32_t address, uint32_t length, uint8_t *buf){} + +static void nvds_null_write(uint32_t address, uint32_t length, uint8_t *buf){} + +static void nvds_null_erase(uint32_t address, uint32_t length){} + +static uint8_t nvds_null_init(void) +{ + // init all the structure + memset( &nvds_env, 0, sizeof(nvds_env)); + nvds_env.read = nvds_null_read; + nvds_env.write = nvds_null_write; + nvds_env.erase = nvds_null_erase; + + return NVDS_OK; +} + +static void nvds_read(uint32_t address, uint32_t length, uint8_t *buf) +{ + // Test the validity of address + length + BLE_ASSERT_ERR((( length) <= nvds_env.total_size)); + + // Read the memory + flash_read(nvds_env.flash_id, address, length, buf, NULL); +} + +#if (NVDS_READ_WRITE == 1) +static void nvds_write(uint32_t address, uint32_t length, uint8_t *buf) +{ + // Test the validity of address + length + BLE_ASSERT_ERR(((length) <= nvds_env.total_size)); + + // Read the memory + flash_write(nvds_env.flash_id, address, length, buf, NULL); +} + +static void nvds_erase(uint32_t address, uint32_t length) +{ + // Erase NVDS + flash_erase(nvds_env.flash_id, address, length, NULL); +} + +static void nvds_init_memory(void) +{ + // clear the device + nvds_env.erase((uint32_t)NVDS_MAGIC_NUMBER_ADDRESS, nvds_env.total_size); + + // Write the magic number at address 0 + nvds_env.write((uint32_t)NVDS_MAGIC_NUMBER_ADDRESS, + (uint32_t)NVDS_MAGIC_NUMBER_LENGTH, + (uint8_t*)nvds_magic_number); + +} + +static void nvds_purge(uint32_t length, uint8_t* buf) +{ + uint8_t status; + struct nvds_tag_header tag_hdr; + uint32_t cur_tag_addr, nxt_tag_addr; + uint32_t total_length; + uint8_t *walk_ptr; + + // store all the valid TAG elements in the locally allocated buffer + total_length = 0; + nxt_tag_addr = NVDS_START_STORAGE_AREA_ADDRESS; + walk_ptr = buf; + do + { + // go to the next tag + cur_tag_addr = nxt_tag_addr; + + status = nvds_walk_tag(cur_tag_addr, (struct nvds_tag_header*)&tag_hdr, &nxt_tag_addr); + + if ((status == NVDS_OK) && NVDS_IS_TAG_OK(tag_hdr)) + { + // check that the current size is not overcoming the buffer + total_length += NVDS_TAG_FULL_LENGTH(tag_hdr); + BLE_ASSERT_ERR(total_length <= length); + + // copy the header content + *((struct nvds_tag_header*)walk_ptr) = tag_hdr; + + // increment the pointer to the data part + walk_ptr += NVDS_TAG_HEADER_LENGTH; + cur_tag_addr += NVDS_TAG_HEADER_LENGTH; + + // retrieve all the data part + nvds_env.read((uint32_t)cur_tag_addr, (uint32_t)tag_hdr.length, walk_ptr); + + // increment the walking pointer + walk_ptr += NVDS_TAG_CONTENT_LENGTH(tag_hdr); + } + + } while (status == NVDS_OK); + + // reinitialize the flash + nvds_init_memory(); + + // rewrite the NVDS once cleaned + nvds_env.write((uint32_t)NVDS_START_STORAGE_AREA_ADDRESS, + (uint32_t)total_length, + buf); +} + +#endif //(NVDS_READ_WRITE == 1) + + +/* + * EXPORTED FUNCTION DEFINITIONS + **************************************************************************************** + */ + +uint8_t nvds_init(void) +{ + uint8_t status = NVDS_OK; + + if(1) + { + // Initialize the pointer to the NVDS + nvds_env.nvds_space = 0; + + // initialize the access functions + nvds_env.read = &nvds_read; + + #if (NVDS_READ_WRITE == 1) + nvds_env.write = &nvds_write; + nvds_env.erase = &nvds_erase; + #else //(NVDS_READ_WRITE == 0) + nvds_env.write = &nvds_null_write; + nvds_env.erase = &nvds_null_erase; + #endif //(NVDS_READ_WRITE == 1) + + nvds_env.total_size = NVDS_MAX_STORAGE_SIZE; + + // Check if NVDS is correctly initialized + if (!nvds_is_magic_number_ok()) + { + #if (NVDS_READ_WRITE == 1) + // Initialize the memory + nvds_init_memory(); + #else //(NVDS_READ_WRITE == 0) + // No NVDS, so select the NULL NVDS + nvds_null_init(); + // Return bad status + status = NVDS_FAIL; + #endif //(NVDS_READ_WRITE == 1) + } + } + else + { + // No NVDS, so select the NULL NVDS + nvds_null_init(); + // Return bad status + status = NVDS_FAIL; + } + return (status); +} + + +uint8_t nvds_get(uint8_t tag, nvds_tag_len_t * lengthPtr, uint8_t *buf) +{ + uint8_t status; + uint32_t tag_addr; + struct nvds_tag_header tag_hdr; + + // try to find the TAG in the NVDS + status = nvds_browse_tag(tag, &tag_hdr, &tag_addr); + + // if the TAG was found + if (status == NVDS_OK) + { + // The parameter is valid, verify that buffer is large enough to store it + if (*lengthPtr < tag_hdr.length) + { + status = NVDS_LENGTH_OUT_OF_RANGE; + } + else // All is OK, proceed to the read operation + { + // Copy data to output buffer + nvds_env.read((uint32_t)(tag_addr + NVDS_TAG_HEADER_LENGTH), + (uint32_t)tag_hdr.length, + buf); + + // Return tag address + *lengthPtr = tag_hdr.length; + } + } + else + { + // Nothing to return, set length to 0 + *lengthPtr = 0; + } + return(status); +} + +#if (NVDS_READ_WRITE == 1) + +uint8_t nvds_del(uint8_t tag) +{ + uint8_t status; + struct nvds_tag_header tag_hdr; + uint32_t tag_addr; + uint8_t status_to_write; + + // look for the TAG + status = nvds_browse_tag(tag, &tag_hdr, &tag_addr); + + // Verify whether the parameter is locked or not + if ((status == NVDS_OK) && NVDS_IS_TAG_LOCKED(tag_hdr)) + { + status = NVDS_PARAM_LOCKED; + } + + // Proceed to the delete operation + if (status == NVDS_OK) + { + // then we set parameter to erased + status_to_write = NVDS_SET_TAG_ERASED(tag_hdr); + nvds_env.write((uint32_t)(tag_addr+offsetof(struct nvds_tag_header, status)), + (uint32_t) sizeof(status_to_write), + (uint8_t*) &status_to_write); + } + return(status); +} + +uint8_t nvds_lock(uint8_t tag) +{ + uint8_t status; + struct nvds_tag_header tag_hdr; + uint32_t tag_addr; + uint8_t status_to_write; + + // look for the TAG + status = nvds_browse_tag(tag, &tag_hdr, &tag_addr); + + // Proceed to the lock operation + if (status == NVDS_OK) + { + // The tag has been found, set the parameter to locked + status_to_write = NVDS_SET_TAG_LOCKED(tag_hdr); + nvds_env.write((uint32_t)(tag_addr+offsetof(struct nvds_tag_header, status)), + (uint32_t)sizeof(status_to_write), + &status_to_write); + } + return(status); +} + +uint8_t nvds_put(uint8_t tag, nvds_tag_len_t length, uint8_t *buf) +{ + uint8_t status; + uint8_t nvds_temp_buf[NVDS_MAX_STORAGE_SIZE]; + struct nvds_tag_header tag_hdr; + uint8_t tag_buffer[NVDS_PARAMETER_MAX_LENGTH]; + uint32_t cur_tag_addr, nxt_tag_addr; + uint8_t status_to_write; + uint32_t total_length; + + /* parse once all the TAG elements of the NVDS to: + * 1) find same tag + * 2) erase and invalidate the former tag + * 3) compute the total length needed by the all valid tags + * 4) retrieve the first address where new data can be stored */ + total_length = 0; + nxt_tag_addr = NVDS_START_STORAGE_AREA_ADDRESS; + + do + { + // Go to the next tag + cur_tag_addr = nxt_tag_addr; + + // Read the next TAG header structure + status = nvds_walk_tag(cur_tag_addr, &tag_hdr, &nxt_tag_addr); + + // check TAG is valid + if ((status == NVDS_OK) && NVDS_IS_TAG_OK(tag_hdr)) + { + // check TAG is identical to the new one + if (tag_hdr.tag == tag) + { + // check TAG is not locked + if (NVDS_IS_TAG_LOCKED(tag_hdr)) + { + return NVDS_PARAM_LOCKED; + } + + // Read parameter data + nvds_env.read((uint32_t)(cur_tag_addr + NVDS_TAG_HEADER_LENGTH), + (uint32_t)tag_hdr.length, + tag_buffer); + + // Compare data with new parameter + if((tag_hdr.length == length) && !memcmp(buf, tag_buffer, tag_hdr.length)) + { + return NVDS_OK; + } + + // then we set parameter to erased + status_to_write = NVDS_SET_TAG_ERASED(tag_hdr); + nvds_env.write((uint32_t)(cur_tag_addr+offsetof(struct nvds_tag_header, status)), + (uint32_t) sizeof(status_to_write), + (uint8_t*) &status_to_write); + } + else + { + // add the current tag length to the total length (used for purge) + total_length += NVDS_TAG_FULL_LENGTH(tag_hdr); + } + } + } while (status == NVDS_OK); + + // check that we've reached the last TAG of the NVDS + if (status != NVDS_OK) + { + /* check if there is enough space to write next tag + the limit is calculated including 2 TAG headers (the current and the next + that is used to leave at least an end marker) */ + if ((cur_tag_addr + (NVDS_TAG_HEADER_LENGTH*2) + NVDS_ALIGNMENT(length) - NVDS_MAGIC_NUMBER_ADDRESS) + > (nvds_env.total_size - 1)) + { + BLE_ASSERT_ERR(nvds_temp_buf != NULL); + + // purge the NVDS using the current buffer + nvds_purge(total_length, nvds_temp_buf); + + // compute the next tag address in the NVDS memory space + cur_tag_addr = NVDS_START_STORAGE_AREA_ADDRESS + NVDS_ALIGNMENT(total_length); + + // if there is still not enough space, return an error + if ((cur_tag_addr + NVDS_TAG_HEADER_LENGTH + NVDS_ALIGNMENT(length) - NVDS_MAGIC_NUMBER_ADDRESS) + > (nvds_env.total_size - 1)) + { + return NVDS_NO_SPACE_AVAILABLE; + } + } + } + + // First of all, write the data of the parameter + nvds_env.write((uint32_t)(cur_tag_addr+NVDS_TAG_HEADER_LENGTH), + (uint32_t)length, + buf); + + // Second of all, configure the new value of the TAG HEADER + tag_hdr.tag = tag; + tag_hdr.status = NVDS_SET_TAG_OK(tag_hdr); + tag_hdr.length = length; + + // Third of all, write the new TAG HEADER + nvds_env.write((uint32_t)(cur_tag_addr), + (uint32_t)sizeof(tag_hdr), + (uint8_t*)&tag_hdr); + + return(NVDS_OK); +} +#endif //(NVDS_READ_WRITE == 1) + + + +/// @} NVDS + diff --git a/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/rwip/api/rwip.h b/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/rwip/api/rwip.h new file mode 100755 index 0000000..ff6cbf3 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/rwip/api/rwip.h @@ -0,0 +1,592 @@ +/** +**************************************************************************************** +* +* @file rwip.h +* +* @brief RW IP SW main module +* +* Copyright (C) RivieraWaves 2009-2015 +* +* +**************************************************************************************** +*/ +#ifndef _RWIP_H_ +#define _RWIP_H_ + +/** + **************************************************************************************** + * @addtogroup ROOT + * @brief Entry points of the RW IP stacks/modules + * + * This module contains the primitives that allow an application accessing and running the + * RW IP protocol stacks / modules. + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_config.h" // stack configuration + +#include // standard integer definitions +#include // standard boolean definitions + + +/* + * DEFINES + **************************************************************************************** + */ +/// Maximum value of a Bluetooth clock (in 312.5us half slots) +#define RWIP_MAX_CLOCK_TIME ((1L<<28) - 1) +/// Maximum value of a 10ms Bluetooth clock +#define RWIP_MAX_10MS_TIME ((1L<<23) - 1) +/// retrieve 10ms time according to clock time +#define RWIP_CLOCK_TO_10MS_TIME(clock) ((clock) >> 5) +/// retrieve clock time according to 10ms time +#define RWIP_10MS_TIME_TO_CLOCK(time) ((time) << 5) +/// Invalid target time +#define RWIP_INVALID_TARGET_TIME (0xFFFFFFFFL) + + +/// result of sleep state. +enum rwip_sleep_state +{ + /// Some activity pending, can not enter in sleep state + RWIP_ACTIVE = 0, + /// CPU can be put in sleep state + RWIP_CPU_SLEEP, + /// IP could enter in deep sleep + RWIP_DEEP_SLEEP, +}; + + +/// Definition of the bits preventing the system from sleeping +enum prevent_sleep +{ + /// Flag indicating that the wake up process is ongoing + RW_WAKE_UP_ONGOING = 0x0001, + /// Flag indicating that an TX transfer is ongoing on Transport Layer + RW_TL_TX_ONGOING = 0x0002, + /// Flag indicating that an RX transfer is ongoing on Transport Layer + RW_TL_RX_ONGOING = 0x0004, + /// Flag indicating the IP is in sleep, to avoid running sleep algorithm while already entering sleep + RW_DEEP_SLEEP = 0x0008, + /// Flag indicating that an encryption is ongoing + RW_CRYPT_ONGOING = 0x0010, + /// Flag indicating that controller shall not sleep due to not CSB LPO_Allowed + RW_CSB_NOT_LPO_ALLOWED = 0x0040, + /// Flag indicating the MWS/WLAN Event Generator is in operation + RW_MWS_WLAN_EVENT_GENERATOR_ACTIVE = 0x0080, + /// Flag to indicate that platform does not support deep sleep + RW_PLF_DEEP_SLEEP_DISABLED = 0x0100, + /// Flag to indicate that a baseband frame is ongoing + RW_BB_FRAME_ONGOING = 0x0200, + /// Flag to indicate that BLE Hopping computation on-going + RW_HOP_CALC_ONGOING = 0x0400, + /// Flag to indicate that BT is in active mode (ACL, SCO) + RW_BT_ACTIVE_MODE = 0x0800, + /// Flag to indicate that BLE requires active mode + RW_BLE_ACTIVE_MODE = 0x1000, +}; + +/// Parameters - Possible Returned Status +enum PARAM_STATUS +{ + /// PARAM status OK + PARAM_OK, + /// generic PARAM status KO + PARAM_FAIL, + /// PARAM ID unrecognized + PARAM_ID_NOT_DEFINED, + /// No space for PARAM + PARAM_NO_SPACE_AVAILABLE, + /// Length violation + PARAM_LENGTH_OUT_OF_RANGE, + /// PARAM parameter locked + PARAM_PARAM_LOCKED, + /// PARAM corrupted + PARAM_CORRUPT +}; + +/** + * External interface type types. + */ +enum rwip_eif_types +{ + /// Host Controller Interface - Controller part + RWIP_EIF_HCIC, + + /// Host Controller Interface - Host part + RWIP_EIF_HCIH, + + /// Application Host interface + RWIP_EIF_AHI, +}; + + +/// Enumeration of External Interface status codes +enum rwip_eif_status +{ + /// EIF status OK + RWIP_EIF_STATUS_OK, + /// EIF status KO + RWIP_EIF_STATUS_ERROR, + +#if (BLE_EMB_PRESENT == 0) + /// External interface detached + RWIP_EIF_STATUS_DETACHED, + /// External interface attached + RWIP_EIF_STATUS_ATTACHED, +#endif // (BLE_EMB_PRESENT == 0) +}; + +/// Enumeration of RF modulations +enum rwip_rf_mod +{ + MOD_GFSK = 0x01, + MOD_DQPSK = 0x02, + MOD_8DPSK = 0x03, +}; + +#if RW_DEBUG +/// Assert type +/*@TRACE*/ +enum assert_type +{ + BLE_ASSERT_TYPE_WARNING = 0, + BLE_ASSERT_TYPE_ERROR = 1, +}; +#endif //RW_DEBUG + +/// Types of initialization of the IP +enum rwip_init_type +{ + /// IP initialization + RWIP_INIT = 0, + /// IP first reset (done once after initialization, before protocol stack is used) + RWIP_1ST_RST, + /// Normal IP reset (can be done at any time when protocol stack is in use) + RWIP_RST, +}; + +/* + * TYPE DEFINITIONS + **************************************************************************************** + */ + +/// Time information +/*@TRACE*/ +typedef struct +{ + /// Integer part of the time (in half-slot) + uint32_t hs; + /// Fractional part of the time (in half-us) (range: 0-624) + uint32_t hus; +} rwip_time_t; + +/// API functions of the RF driver that are used by the BLE or BT software +struct rwip_rf_api +{ + /// Function called upon HCI reset command reception + void (*reset)(void); + /// Function called to enable/disable force AGC mechanism (true: en / false : dis) + void (*force_agc_enable)(bool); + /// Function called when TX power has to be decreased for a specific link id + bool (*txpwr_dec)(uint8_t); + /// Function called when TX power has to be increased for a specific link id + bool (*txpwr_inc)(uint8_t); + /// Function called when TX power has to be set to max for a specific link id + void (*txpwr_max_set)(uint8_t); + /// Function called to convert a TX power CS power field into the corresponding value in dBm + uint8_t (*txpwr_dbm_get)(uint8_t, uint8_t); + /// Function called to convert a power in dBm into a control structure tx power field + uint8_t (*txpwr_cs_get)(int8_t, bool); + /// Function called to convert the RSSI read from the control structure into a real RSSI + int8_t (*rssi_convert)(uint8_t); + /// Function used to read a RF register + uint32_t (*reg_rd)(uint32_t); + /// Function used to write a RF register + void (*reg_wr)(uint32_t, uint32_t); + /// Function called to put the RF in deep sleep mode + void (*sleep)(void); + /// Index of minimum TX power + uint8_t txpwr_min; + /// Index of maximum TX power + uint8_t txpwr_max; + /// RSSI high threshold ('real' signed value in dBm) + int8_t rssi_high_thr; + /// RSSI low threshold ('real' signed value in dBm) + int8_t rssi_low_thr; + /// interferer threshold ('real' signed value in dBm) + int8_t rssi_interf_thr; + /// RF wakeup delay (in slots) + uint8_t wakeup_delay; +}; + +/// API functions of the parameters that are used by the BLE or BT software +struct rwip_param_api +{ + /** + * Get a parameter value + * @param[in] param_id Parameter identifier + * @param[in/out] lengthPtr Pointer to the length of the parameter (input: contain max length, output contain the effective param length, in bytes) + * @param[out] buf Pointer to the buffer be filled with the parameter value + * @return status 0: success | >0 : error + */ + uint8_t (*get) (uint8_t param_id, uint8_t * lengthPtr, uint8_t *buf); + + /** + * Set a parameter value + * @param[in] param_id Parameter identifier + * @param[in/out] length Length of the parameter (in bytes) + * @param[out] buf Pointer to the buffer containing the parameter value + * @return status 0: success | >0 : error + */ + uint8_t (*set) (uint8_t param_id, uint8_t length, uint8_t *buf); + + /** + * Delete a parameter + * @param[in] param_id Parameter identifier + * @return status 0: success | >0 : error + */ + uint8_t (*del) (uint8_t param_id); +}; + +/// Internal API for priority +struct rwip_prio +{ + ///value + uint8_t value; + ///Increment + uint8_t increment; +}; +/** + **************************************************************************************** + * @brief Function called when packet transmission/reception is finished. + + * @param[in] dummy Dummy data pointer returned to callback when operation is over. + * @param[in] status Ok if action correctly performed, else reason status code. + ***************************************************************************************** + */ +typedef void (*rwip_eif_callback) (void*, uint8_t); + +/** + * Transport layer communication interface. + */ +struct rwip_eif_api +{ + /** + ************************************************************************************* + * @brief Starts a data reception. + * + * @param[out] bufptr Pointer to the RX buffer + * @param[in] size Size of the expected reception + * @param[in] callback Pointer to the function called back when transfer finished + * @param[in] dummy Dummy data pointer returned to callback when reception is finished + ************************************************************************************* + */ + void (*read) (uint8_t *bufptr, uint32_t size, rwip_eif_callback callback, void* dummy); + + /** + ************************************************************************************* + * @brief Starts a data transmission. + * + * @param[in] bufptr Pointer to the TX buffer + * @param[in] size Size of the transmission + * @param[in] callback Pointer to the function called back when transfer finished + * @param[in] dummy Dummy data pointer returned to callback when transmission is finished + ************************************************************************************* + */ + void (*write)(uint8_t *bufptr, uint32_t size, rwip_eif_callback callback, void* dummy); + + /** + ************************************************************************************* + * @brief Enable Interface flow. + ************************************************************************************* + */ + void (*flow_on)(void); + + /** + ************************************************************************************* + * @brief Disable Interface flow. + * + * @return True if flow has been disabled, False else. + ************************************************************************************* + */ + bool (*flow_off)(void); +}; + +/* + * VARIABLE DECLARATION +***************************************************************************************** + */ + +/// API for RF driver +extern struct rwip_rf_api rwip_rf; +/// API for parameters +extern struct rwip_param_api rwip_param; +#if (BLE_EMB_PRESENT || BT_EMB_PRESENT) +/// API for dual mode priority +extern const struct rwip_prio rwip_priority[RWIP_PRIO_IDX_MAX]; +#if (RW_WLAN_COEX || RW_MWS_COEX) +/// API for COEX configuration +extern const uint8_t rwip_coex_cfg[RWIP_COEX_CFG_MAX]; +#endif //(RW_WLAN_COEX || RW_MWS_COEX) +/// Programming delay, margin for programming the baseband in advance of each activity (in half-slots) +extern uint8_t rwip_prog_delay; +#endif //(BT_EMB_PRESENT || BLE_EMB_PRESENT) + +/* + * MACROS + **************************************************************************************** + */ + +/// Get Event status flag +#if (BT_EMB_PRESENT || BLE_EMB_PRESENT) +#if (RW_WLAN_COEX || RW_MWS_COEX) +#define RWIP_COEX_GET(coex_cfg_idx, bit_field) \ + (uint8_t)(((rwip_coex_cfg[RWIP_COEX_ ## coex_cfg_idx ##_IDX]) >> RWIP_ ## bit_field ## _POS ) & RWIP_COEX_BIT_MASK) +#else //!(RW_WLAN_COEX || RW_MWS_COEX) +#define RWIP_COEX_GET(coex_cfg_idx, bit_field) 0 +#endif //(RW_WLAN_COEX || RW_MWS_COEX) +#endif //(BT_EMB_PRESENT || BLE_EMB_PRESENT) + +/* + * FUNCTION DECLARATION +***************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Initializes the RW BT SW. + * + **************************************************************************************** + */ +void rwip_init(uint32_t error); + +/** + **************************************************************************************** + * @brief Reset the RW BT SW. + * + **************************************************************************************** + */ +void rwip_reset(void); + + + +#if (BT_EMB_PRESENT) + +#if PCA_SUPPORT +/** + **************************************************************************************** + * @brief Check if clock dragging limitation + * + * @return true if clock dragging must be used + **************************************************************************************** + */ +bool rwip_pca_clock_dragging_only(void); +#endif //PCA_SUPPORT +#endif // (BT_EMB_PRESENT) + +#if (BT_EMB_PRESENT || BLE_EMB_PRESENT) +#if (RW_MWS_COEX) +/** + **************************************************************************************** + * @brief Enable/Disable the MWS coexistence interface. + * + * @param[in] CoexSetting Coexistence value + * + **************************************************************************************** + */ +void rwip_mwscoex_set(bool state); +#endif //RW_MWS_COEX + +#if (RW_WLAN_COEX) +/** + **************************************************************************************** + * @brief Enable/Disable the Wireless LAN coexistence interface. + * + * @param[in] CoexSetting Coexistence value + * + **************************************************************************************** + */ +void rwip_wlcoex_set(bool state); +#endif //RW_WLAN_COEX +#endif //(BT_EMB_PRESENT || BLE_EMB_PRESENT) + +/** + **************************************************************************************** + * @brief Function to implement in platform in order to retrieve each external interface API + * + * @param[in] idx External interface index + * + * @return External interface api structure + **************************************************************************************** + */ +extern const struct rwip_eif_api* rwip_eif_get(uint8_t idx); + +#if RW_DEBUG +/** + **************************************************************************************** + * @brief Raises an assertion message to the control interface (if present) + * + * @param[in] file File name + * @param[in] line Line number + * @param[in] param0 Parameter 0 (custom value given by the assert instruction) + * @param[in] param1 Parameter 1 (custom value given by the assert instruction) + * @param[in] type 0: warning / 1: error + **************************************************************************************** + */ +void rwip_assert(const char * file, int line, int param0, int param1, uint8_t type); +#endif //RW_DEBUG + + +/* ************************************************************************************** + * Driver functions + * ************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Retrieved sampled time + * + * @note Shall be called within a critical section + * + * @return current time sampled (@see rwip_time_t) + **************************************************************************************** + */ +rwip_time_t rwip_time_get(void); + + +#if (BT_EMB_PRESENT) +/** + **************************************************************************************** + * @brief Set current time + * + * @param clock value in half-slots + **************************************************************************************** + */ +void rwip_time_set(uint32_t clock); +#endif // (BT_EMB_PRESENT) + +/** + **************************************************************************************** + * @brief Set the 1 ms target timer + * + * @note if target is RWIP_INVALID_TARGET_TIME, not timer are programmed + * + * @param[in] target 1ms Timer target value + **************************************************************************************** + */ +void rwip_timer_1ms_set(rwip_time_t target); + +#if (BLE_EMB_PRESENT || BT_EMB_PRESENT) +/** + **************************************************************************************** + * @brief Set the a half slot target timer + * + * @note if target is RWIP_INVALID_TARGET_TIME, not timer are programmed + * + * @param[in] target Half Slot Timer target value + **************************************************************************************** + */ +void rwip_timer_hs_set(uint32_t target); + +/** + **************************************************************************************** + * @brief Set the a half slot target timer + * + * @note if target is RWIP_INVALID_TARGET_TIME, not timer are programmed + * + * @param[in] target Half Slot Timer target value + * @param[in] half_us_delay Half us timer delay in corresponding half slot (range [0:624]) + **************************************************************************************** + */ +void rwip_timer_hus_set(uint32_t target, uint32_t half_us_delay); +#endif // (BLE_EMB_PRESENT || BT_EMB_PRESENT) + +/** + **************************************************************************************** + * @brief Start AES encryption + * + * The exchange memory must be filled before calling this function. + * This function expect to be called from a BLE Module + * + * @param[in] key AES Encryption key must be 16 bytes + * @param[in] val 16 bytes value array to encrypt using AES + **************************************************************************************** + */ +void rwip_aes_encrypt(const uint8_t *key, const uint8_t* val); + +#if (BLE_EMB_PRESENT || BT_EMB_PRESENT) +/** + **************************************************************************************** + * @brief Request a Software interrupt to be triggered + **************************************************************************************** + */ +void rwip_sw_int_req(void); +#endif // (BLE_EMB_PRESENT || BT_EMB_PRESENT) + +/** + **************************************************************************************** + * @brief Invoke the sleep function. + * + * @return sleep status (@see enum rwip_sleep_state) + **************************************************************************************** + */ +uint8_t rwip_sleep(void); + +#if (BLE_EMB_PRESENT || BT_EMB_PRESENT) +/** + **************************************************************************************** + * @brief Handle the common core interrupts. + **************************************************************************************** + */ +void rwip_isr(void); +#endif // (BLE_EMB_PRESENT || BT_EMB_PRESENT) + +/** + **************************************************************************************** + * @brief Set a bit in the prevent sleep bit field, in order to prevent the system from + * going to sleep + * + * @param[in] prv_slp_bit Bit to be set in the prevent sleep bit field + **************************************************************************************** + */ +void rwip_prevent_sleep_set(uint16_t prv_slp_bit); + +/** + **************************************************************************************** + * @brief Clears a bit in the prevent sleep bit field, in order to allow the system + * going to sleep + * + * @param[in] prv_slp_bit Bit to be cleared in the prevent sleep bit field + **************************************************************************************** + */ +void rwip_prevent_sleep_clear(uint16_t prv_slp_bit); + +#if (BLE_EMB_PRESENT || BT_EMB_PRESENT) +/** + **************************************************************************************** + * @brief Check if the system is permanently active (e.g. for BT ACL connection) + * + * @return false: system might sleep | true: system stays active + **************************************************************************************** + */ +bool rwip_active_check(void); +#endif // (BLE_EMB_PRESENT || BT_EMB_PRESENT) + +/** + **************************************************************************************** + * @brief Schedule all pending events. + * + **************************************************************************************** + */ +void rwip_schedule(void); + +///@} ROOT + +#endif // _RWIP_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/rwip/api/rwip_int.h b/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/rwip/api/rwip_int.h new file mode 100755 index 0000000..10228c7 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/rwip/api/rwip_int.h @@ -0,0 +1,103 @@ +/** +**************************************************************************************** +* +* @file rwip_int.h +* +* @brief RW IP internal SW main module +* +* Copyright (C) RivieraWaves 2009-2015 +* +* +**************************************************************************************** +*/ +#ifndef _RWIP_INT_H_ +#define _RWIP_INT_H_ + +/** + **************************************************************************************** + * @addtogroup ROOT + * @brief Entry points of the RW IP stacks/modules + * + * This module contains the primitives that allow an application accessing and running the + * RW IP protocol stacks / modules. + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_config.h" // stack configuration + +#include // standard integer definitions +#include // standard boolean definitions + + +/* + * DEFINES + **************************************************************************************** + */ + + +/* + * STRUCTURE DEFINITIONS + **************************************************************************************** + */ + +/// RWIP Environment structure +struct rwip_env_tag +{ + #if (BLE_EMB_PRESENT || BT_EMB_PRESENT) + /// Half slot target timer (in half slots) + uint32_t timer_hs_target; + /// Half us target timer (integer part, in half slots) + rwip_time_t timer_hus_target; + #endif // (BLE_EMB_PRESENT || BT_EMB_PRESENT) + /// 1 ms target timer (in rwip_time_t) + rwip_time_t timer_1ms_target; + #if (BLE_EMB_PRESENT || BT_EMB_PRESENT) + /// Contains sleep duration accumulated timing error (32kHz: 1/2 half us | 32.768kHz: 1/256 half-us) + uint32_t sleep_acc_error; + /// Power_up delay (in LP clock cycle unit, depends on Low power clock frequency) + uint32_t lp_cycle_wakeup_delay; + /// Duration of sleep and wake-up algorithm (depends on CPU speed) expressed in half us. + uint16_t sleep_algo_dur; + #endif // (BLE_EMB_PRESENT || BT_EMB_PRESENT) + /// Prevent sleep bit field + uint16_t prevent_sleep; + #if (BLE_EMB_PRESENT || BT_EMB_PRESENT) + /// External wake-up support + bool ext_wakeup_enable; + #endif // (BLE_EMB_PRESENT || BT_EMB_PRESENT) + + uint32_t irq_mask; +}; + + +/* + * GLOBAL DEFINITIONS + **************************************************************************************** + */ + +/// RW SW environment +extern struct rwip_env_tag rwip_env; + + +/* + * FUNCTION DEFINITIONS + **************************************************************************************** + */ + +/** + * Initialization of the RW IP Common core driver + * + * @param[in] init_type Type of initialization (@see enum rwip_init_type) + */ +void rwip_driver_init(uint8_t init_type); + + +///@} ROOT + +#endif // _RWIP_INT_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/rwip/api/rwip_task.h b/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/rwip/api/rwip_task.h new file mode 100755 index 0000000..cb88a3a --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/rwip/api/rwip_task.h @@ -0,0 +1,121 @@ +/** + **************************************************************************************** + * + * @file rwip_task.h + * + * @brief Task Identifier description for the RW IP + * + * Copyright (C) RivieraWaves 2009-2016 + * + **************************************************************************************** + */ + +#ifndef RWIP_TASK_H_ +#define RWIP_TASK_H_ + +/** + **************************************************************************************** + * @addtogroup ROOT + * @{ + * + * Information about RW SW TASK + * + * @name RW TASK Configuration + * @{ + **************************************************************************************** + */ + +#include + +/* + * DEFINES + **************************************************************************************** + */ + + +/// Build the first message ID of a task. (in fact a kernel_msg_id_t) +#define TASK_BLE_FIRST_MSG(task) ((uint16_t)((task) << 8)) + +/// Builds the task identifier from the type and the index of that task. +#define TASK_BLE_BUILD(type, index) ((uint16_t)(((index) << 8)|(type)) ) + +/// Retrieves task type from task id. +#define TASK_BLE_TYPE_GET(kernel_task_id) (((uint16_t)kernel_task_id) & 0xFF) + +/// Retrieves task index number from task id. +#define TASK_BLE_IDX_GET(kernel_task_id) ((((uint16_t)kernel_task_id) >> 8) & 0xFF) + +/// Message identifier index +#define MSG_ID(task, idx) (TASK_BLE_FIRST_MSG((TASK_BLE_ID_ ## task)) + idx) + +/// Tasks types definition, this value shall be in [0-254] range +/*@TRACE*/ +enum TASK_BLE_API_ID +{ + // ----------------------------------------------------------------------------------- + // ---------------------- Controller Task identifer ---------------------------------- + // ----------------------------------------------------------------------------------- + // Link Layer Tasks + TASK_BLE_ID_LLM = 0,//!< TASK_BLE_ID_LLM + TASK_BLE_ID_LLC = 1,//!< TASK_BLE_ID_LLC + TASK_BLE_ID_LLD = 2,//!< TASK_BLE_ID_LLD + TASK_BLE_ID_LLI = 3,//!< TASK_BLE_ID_LLI + + TASK_BLE_ID_DBG = 4,//!< TASK_BLE_ID_DBG + + // BT Controller Tasks + TASK_BLE_ID_LM = 5,//!< TASK_BLE_ID_LM + TASK_BLE_ID_LC = 6,//!< TASK_BLE_ID_LC + TASK_BLE_ID_LB = 7,//!< TASK_BLE_ID_LB + TASK_BLE_ID_LD = 8,//!< TASK_BLE_ID_LD + + // ----------------------------------------------------------------------------------- + // --------------------- BLE HL TASK API Identifiers --------------------------------- + // --------------------- SHALL NOT BE CHANGED --------------------------------- + // ----------------------------------------------------------------------------------- + + TASK_BLE_ID_L2CC = 10, // L2CAP Controller Task + TASK_BLE_ID_GATTM = 11, // Generic Attribute Profile Manager Task + TASK_BLE_ID_GATTC = 12, // Generic Attribute Profile Controller Task + TASK_BLE_ID_GAPM = 13, // Generic Access Profile Manager + TASK_BLE_ID_GAPC = 14, // Generic Access Profile Controller + TASK_BLE_ID_APP = 15, // Application API + + // ----------------------------------------------------------------------------------- + // --------------------- TRANSPORT AND PLATFORM TASKS -------------------------------- + // ----------------------------------------------------------------------------------- + TASK_BLE_ID_AHI = 16, // Application Host Interface + TASK_BLE_ID_HCI = 17, //!< TASK_BLE_ID_HCI + TASK_BLE_ID_DISPLAY = 19, //!< TASK_BLE_ID_DISPLAY + + // ----------------------------------------------------------------------------------- + // --------------------- BLE Profile TASK API Identifiers ---------------------------- + // --------------------- SHALL NOT BE CHANGED --------------------------------- + // ----------------------------------------------------------------------------------- + +#if (BEKEN_TASK_ENABLE) + TASK_BLE_ID_BEKEN = 100, //// BEKEN Test +#endif + +#if (BLE_COMM_SERVER) + TASK_BLE_ID_COMMON = 120, +#endif + +#if (BLE_MESH) + TASK_BLE_ID_MESH = 200, // Mesh Task +#endif + + /* 240 -> 241 reserved for Audio Mode 0 */ + TASK_BLE_ID_AM0 = 240, // BLE Audio Mode 0 Task + TASK_BLE_ID_AM0_HAS = 241, // BLE Audio Mode 0 Hearing Aid Service Task + + + TASK_BLE_ID_THPP = 242, // Throughput profile tester used for debugging + + TASK_BLE_ID_INVALID = 0xFF, // Invalid Task Identifier +}; + +/// @} BT Stack Configuration +/// @} ROOT + +#endif //RWIP_CONFIG_H_ diff --git a/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/rwip/import/reg/_reg_ipcore.h b/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/rwip/import/reg/_reg_ipcore.h new file mode 100755 index 0000000..19fafff --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/rwip/import/reg/_reg_ipcore.h @@ -0,0 +1,10 @@ +#ifndef __REG_IPCORE_H_ +#define __REG_IPCORE_H_ + +#define REG_IPCORE_SIZE 392 + +#define REG_IPCORE_BASE_ADDR 0x00900000 + + +#endif // __REG_IPCORE_H_ + diff --git a/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/rwip/import/reg/ble_reg_ipcore.h b/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/rwip/import/reg/ble_reg_ipcore.h new file mode 100755 index 0000000..e24eb64 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/rwip/import/reg/ble_reg_ipcore.h @@ -0,0 +1,3911 @@ +#ifndef _REG_IPCORE_H_ +#define _REG_IPCORE_H_ + +#include +#include "_reg_ipcore.h" +#include "compiler.h" +#include "architect.h" +#include "ble_reg_access.h" + +#define REG_IPCORE_COUNT 98 + +#define REG_IPCORE_DECODING_MASK 0x000001FF + +/** + * @brief RWDMCNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31      MASTER_SOFT_RST   0
+ *     30    MASTER_TGSOFT_RST   0
+ *     29         REG_SOFT_RST   0
+ *     28   RADIOCNTL_SOFT_RST   0
+ *     27            SWINT_REQ   0
+ * 
+ */ +#define IP_RWDMCNTL_ADDR 0x00900000 +#define IP_RWDMCNTL_OFFSET 0x00000000 +#define IP_RWDMCNTL_INDEX 0x00000000 +#define IP_RWDMCNTL_RESET 0x00000000 + +__INLINE uint32_t ip_rwdmcntl_get(void) +{ + return REG_IP_RD(IP_RWDMCNTL_ADDR); +} + +__INLINE void ip_rwdmcntl_set(uint32_t value) +{ + REG_IP_WR(IP_RWDMCNTL_ADDR, value); +} + +// field definitions +#define IP_MASTER_SOFT_RST_BIT ((uint32_t)0x80000000) +#define IP_MASTER_SOFT_RST_POS 31 +#define IP_MASTER_TGSOFT_RST_BIT ((uint32_t)0x40000000) +#define IP_MASTER_TGSOFT_RST_POS 30 +#define IP_REG_SOFT_RST_BIT ((uint32_t)0x20000000) +#define IP_REG_SOFT_RST_POS 29 +#define IP_RADIOCNTL_SOFT_RST_BIT ((uint32_t)0x10000000) +#define IP_RADIOCNTL_SOFT_RST_POS 28 +#define IP_SWINT_REQ_BIT ((uint32_t)0x08000000) +#define IP_SWINT_REQ_POS 27 + +#define IP_MASTER_SOFT_RST_RST 0x0 +#define IP_MASTER_TGSOFT_RST_RST 0x0 +#define IP_REG_SOFT_RST_RST 0x0 +#define IP_RADIOCNTL_SOFT_RST_RST 0x0 +#define IP_SWINT_REQ_RST 0x0 + +__INLINE void ip_rwdmcntl_pack(uint8_t mastersoftrst, uint8_t mastertgsoftrst, uint8_t regsoftrst, uint8_t radiocntlsoftrst, uint8_t swintreq) +{ + BLE_ASSERT_ERR((((uint32_t)mastersoftrst << 31) & ~((uint32_t)0x80000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)mastertgsoftrst << 30) & ~((uint32_t)0x40000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)regsoftrst << 29) & ~((uint32_t)0x20000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)radiocntlsoftrst << 28) & ~((uint32_t)0x10000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)swintreq << 27) & ~((uint32_t)0x08000000)) == 0); + REG_IP_WR(IP_RWDMCNTL_ADDR, ((uint32_t)mastersoftrst << 31) | ((uint32_t)mastertgsoftrst << 30) | ((uint32_t)regsoftrst << 29) | ((uint32_t)radiocntlsoftrst << 28) | ((uint32_t)swintreq << 27)); +} + +__INLINE void ip_rwdmcntl_unpack(uint8_t* mastersoftrst, uint8_t* mastertgsoftrst, uint8_t* regsoftrst, uint8_t* radiocntlsoftrst, uint8_t* swintreq) +{ + uint32_t localVal = REG_IP_RD(IP_RWDMCNTL_ADDR); + + *mastersoftrst = (localVal & ((uint32_t)0x80000000)) >> 31; + *mastertgsoftrst = (localVal & ((uint32_t)0x40000000)) >> 30; + *regsoftrst = (localVal & ((uint32_t)0x20000000)) >> 29; + *radiocntlsoftrst = (localVal & ((uint32_t)0x10000000)) >> 28; + *swintreq = (localVal & ((uint32_t)0x08000000)) >> 27; +} + +__INLINE uint8_t ip_rwdmcntl_master_soft_rst_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_RWDMCNTL_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +__INLINE void ip_rwdmcntl_master_soft_rst_setf(uint8_t mastersoftrst) +{ + BLE_ASSERT_ERR((((uint32_t)mastersoftrst << 31) & ~((uint32_t)0x80000000)) == 0); + REG_IP_WR(IP_RWDMCNTL_ADDR, (REG_IP_RD(IP_RWDMCNTL_ADDR) & ~((uint32_t)0x80000000)) | ((uint32_t)mastersoftrst << 31)); +} + +__INLINE uint8_t ip_rwdmcntl_master_tgsoft_rst_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_RWDMCNTL_ADDR); + return ((localVal & ((uint32_t)0x40000000)) >> 30); +} + +__INLINE void ip_rwdmcntl_master_tgsoft_rst_setf(uint8_t mastertgsoftrst) +{ + BLE_ASSERT_ERR((((uint32_t)mastertgsoftrst << 30) & ~((uint32_t)0x40000000)) == 0); + REG_IP_WR(IP_RWDMCNTL_ADDR, (REG_IP_RD(IP_RWDMCNTL_ADDR) & ~((uint32_t)0x40000000)) | ((uint32_t)mastertgsoftrst << 30)); +} + +__INLINE uint8_t ip_rwdmcntl_reg_soft_rst_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_RWDMCNTL_ADDR); + return ((localVal & ((uint32_t)0x20000000)) >> 29); +} + +__INLINE void ip_rwdmcntl_reg_soft_rst_setf(uint8_t regsoftrst) +{ + BLE_ASSERT_ERR((((uint32_t)regsoftrst << 29) & ~((uint32_t)0x20000000)) == 0); + REG_IP_WR(IP_RWDMCNTL_ADDR, (REG_IP_RD(IP_RWDMCNTL_ADDR) & ~((uint32_t)0x20000000)) | ((uint32_t)regsoftrst << 29)); +} + +__INLINE uint8_t ip_rwdmcntl_radiocntl_soft_rst_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_RWDMCNTL_ADDR); + return ((localVal & ((uint32_t)0x10000000)) >> 28); +} + +__INLINE void ip_rwdmcntl_radiocntl_soft_rst_setf(uint8_t radiocntlsoftrst) +{ + BLE_ASSERT_ERR((((uint32_t)radiocntlsoftrst << 28) & ~((uint32_t)0x10000000)) == 0); + REG_IP_WR(IP_RWDMCNTL_ADDR, (REG_IP_RD(IP_RWDMCNTL_ADDR) & ~((uint32_t)0x10000000)) | ((uint32_t)radiocntlsoftrst << 28)); +} + +__INLINE uint8_t ip_rwdmcntl_swint_req_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_RWDMCNTL_ADDR); + return ((localVal & ((uint32_t)0x08000000)) >> 27); +} + +__INLINE void ip_rwdmcntl_swint_req_setf(uint8_t swintreq) +{ + BLE_ASSERT_ERR((((uint32_t)swintreq << 27) & ~((uint32_t)0x08000000)) == 0); + REG_IP_WR(IP_RWDMCNTL_ADDR, (REG_IP_RD(IP_RWDMCNTL_ADDR) & ~((uint32_t)0x08000000)) | ((uint32_t)swintreq << 27)); +} + +/** + * @brief VERSION register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:24                  TYP   0xA
+ *  23:16                  REL   0x0
+ *  15:08                  UPG   0x7
+ *  07:00                BUILD   0x0
+ * 
+ */ +#define IP_VERSION_ADDR 0x00900004 +#define IP_VERSION_OFFSET 0x00000004 +#define IP_VERSION_INDEX 0x00000001 +#define IP_VERSION_RESET 0x0A000700 + +__INLINE uint32_t ip_version_get(void) +{ + return REG_IP_RD(IP_VERSION_ADDR); +} + +// field definitions +#define IP_TYP_MASK ((uint32_t)0xFF000000) +#define IP_TYP_LSB 24 +#define IP_TYP_WIDTH ((uint32_t)0x00000008) +#define IP_REL_MASK ((uint32_t)0x00FF0000) +#define IP_REL_LSB 16 +#define IP_REL_WIDTH ((uint32_t)0x00000008) +#define IP_UPG_MASK ((uint32_t)0x0000FF00) +#define IP_UPG_LSB 8 +#define IP_UPG_WIDTH ((uint32_t)0x00000008) +#define IP_BUILD_MASK ((uint32_t)0x000000FF) +#define IP_BUILD_LSB 0 +#define IP_BUILD_WIDTH ((uint32_t)0x00000008) + +#define IP_TYP_RST 0xA +#define IP_REL_RST 0x0 +#define IP_UPG_RST 0x7 +#define IP_BUILD_RST 0x0 + +__INLINE void ip_version_unpack(uint8_t* typ, uint8_t* rel, uint8_t* upg, uint8_t* build) +{ + uint32_t localVal = REG_IP_RD(IP_VERSION_ADDR); + + *typ = (localVal & ((uint32_t)0xFF000000)) >> 24; + *rel = (localVal & ((uint32_t)0x00FF0000)) >> 16; + *upg = (localVal & ((uint32_t)0x0000FF00)) >> 8; + *build = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +__INLINE uint8_t ip_version_typ_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_VERSION_ADDR); + return ((localVal & ((uint32_t)0xFF000000)) >> 24); +} + +__INLINE uint8_t ip_version_rel_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_VERSION_ADDR); + return ((localVal & ((uint32_t)0x00FF0000)) >> 16); +} + +__INLINE uint8_t ip_version_upg_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_VERSION_ADDR); + return ((localVal & ((uint32_t)0x0000FF00)) >> 8); +} + +__INLINE uint8_t ip_version_build_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_VERSION_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +/** + * @brief INTCNTL0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     16          ERRORINTMSK   0
+ * 
+ */ +#define IP_INTCNTL0_ADDR 0x0090000C +#define IP_INTCNTL0_OFFSET 0x0000000C +#define IP_INTCNTL0_INDEX 0x00000003 +#define IP_INTCNTL0_RESET 0x00000000 + +__INLINE uint32_t ip_intcntl0_get(void) +{ + return REG_IP_RD(IP_INTCNTL0_ADDR); +} + +__INLINE void ip_intcntl0_set(uint32_t value) +{ + REG_IP_WR(IP_INTCNTL0_ADDR, value); +} + +// field definitions +#define IP_ERRORINTMSK_BIT ((uint32_t)0x00010000) +#define IP_ERRORINTMSK_POS 16 + +#define IP_ERRORINTMSK_RST 0x0 + +__INLINE uint8_t ip_intcntl0_errorintmsk_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_INTCNTL0_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0x00010000)) == 0); + return (localVal >> 16); +} + +__INLINE void ip_intcntl0_errorintmsk_setf(uint8_t errorintmsk) +{ + BLE_ASSERT_ERR((((uint32_t)errorintmsk << 16) & ~((uint32_t)0x00010000)) == 0); + REG_IP_WR(IP_INTCNTL0_ADDR, (uint32_t)errorintmsk << 16); +} + +/** + * @brief INTSTAT0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     16         ERRORINTSTAT   0
+ * 
+ */ +#define IP_INTSTAT0_ADDR 0x00900010 +#define IP_INTSTAT0_OFFSET 0x00000010 +#define IP_INTSTAT0_INDEX 0x00000004 +#define IP_INTSTAT0_RESET 0x00000000 + +__INLINE uint32_t ip_intstat0_get(void) +{ + return REG_IP_RD(IP_INTSTAT0_ADDR); +} + +// field definitions +#define IP_ERRORINTSTAT_BIT ((uint32_t)0x00010000) +#define IP_ERRORINTSTAT_POS 16 + +#define IP_ERRORINTSTAT_RST 0x0 + +__INLINE uint8_t ip_intstat0_errorintstat_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_INTSTAT0_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0x00010000)) == 0); + return (localVal >> 16); +} + +/** + * @brief INTACK0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     16          ERRORINTACK   0
+ * 
+ */ +#define IP_INTACK0_ADDR 0x00900014 +#define IP_INTACK0_OFFSET 0x00000014 +#define IP_INTACK0_INDEX 0x00000005 +#define IP_INTACK0_RESET 0x00000000 + +__INLINE uint32_t ip_intack0_get(void) +{ + return REG_IP_RD(IP_INTACK0_ADDR); +} + +__INLINE void ip_intack0_clear(uint32_t value) +{ + REG_IP_WR(IP_INTACK0_ADDR, value); +} + +// field definitions +#define IP_ERRORINTACK_BIT ((uint32_t)0x00010000) +#define IP_ERRORINTACK_POS 16 + +#define IP_ERRORINTACK_RST 0x0 + +__INLINE uint8_t ip_intack0_errorintack_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_INTACK0_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0x00010000)) == 0); + return (localVal >> 16); +} + +__INLINE void ip_intack0_errorintack_clearf(uint8_t errorintack) +{ + BLE_ASSERT_ERR((((uint32_t)errorintack << 16) & ~((uint32_t)0x00010000)) == 0); + REG_IP_WR(IP_INTACK0_ADDR, (uint32_t)errorintack << 16); +} + +/** + * @brief INTCNTL1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  30:28         CLKNINTSRMSK   0x0
+ *  27:24         CLKNINTSRVAL   0x0
+ *     15           FIFOINTMSK   1
+ *     06   TIMESTAMPTGT2INTMSK   0
+ *     05   TIMESTAMPTGT1INTMSK   0
+ *     04        FINETGTINTMSK   0
+ *     03             SWINTMSK   0
+ *     02          CRYPTINTMSK   0
+ *     01            SLPINTMSK   1
+ *     00           CLKNINTMSK   1
+ * 
+ */ +#define IP_INTCNTL1_ADDR 0x00900018 +#define IP_INTCNTL1_OFFSET 0x00000018 +#define IP_INTCNTL1_INDEX 0x00000006 +#define IP_INTCNTL1_RESET 0x00008003 + +__INLINE uint32_t ip_intcntl1_get(void) +{ + return REG_IP_RD(IP_INTCNTL1_ADDR); +} + +__INLINE void ip_intcntl1_set(uint32_t value) +{ + REG_IP_WR(IP_INTCNTL1_ADDR, value); +} + +// field definitions +#define IP_CLKNINTSRMSK_MASK ((uint32_t)0x70000000) +#define IP_CLKNINTSRMSK_LSB 28 +#define IP_CLKNINTSRMSK_WIDTH ((uint32_t)0x00000003) +#define IP_CLKNINTSRVAL_MASK ((uint32_t)0x0F000000) +#define IP_CLKNINTSRVAL_LSB 24 +#define IP_CLKNINTSRVAL_WIDTH ((uint32_t)0x00000004) +#define IP_FIFOINTMSK_BIT ((uint32_t)0x00008000) +#define IP_FIFOINTMSK_POS 15 +#define IP_TIMESTAMPTGT2INTMSK_BIT ((uint32_t)0x00000040) +#define IP_TIMESTAMPTGT2INTMSK_POS 6 +#define IP_TIMESTAMPTGT1INTMSK_BIT ((uint32_t)0x00000020) +#define IP_TIMESTAMPTGT1INTMSK_POS 5 +#define IP_FINETGTINTMSK_BIT ((uint32_t)0x00000010) +#define IP_FINETGTINTMSK_POS 4 +#define IP_SWINTMSK_BIT ((uint32_t)0x00000008) +#define IP_SWINTMSK_POS 3 +#define IP_CRYPTINTMSK_BIT ((uint32_t)0x00000004) +#define IP_CRYPTINTMSK_POS 2 +#define IP_SLPINTMSK_BIT ((uint32_t)0x00000002) +#define IP_SLPINTMSK_POS 1 +#define IP_CLKNINTMSK_BIT ((uint32_t)0x00000001) +#define IP_CLKNINTMSK_POS 0 + +#define IP_CLKNINTSRMSK_RST 0x0 +#define IP_CLKNINTSRVAL_RST 0x0 +#define IP_FIFOINTMSK_RST 0x1 +#define IP_TIMESTAMPTGT2INTMSK_RST 0x0 +#define IP_TIMESTAMPTGT1INTMSK_RST 0x0 +#define IP_FINETGTINTMSK_RST 0x0 +#define IP_SWINTMSK_RST 0x0 +#define IP_CRYPTINTMSK_RST 0x0 +#define IP_SLPINTMSK_RST 0x1 +#define IP_CLKNINTMSK_RST 0x1 + +__INLINE void ip_intcntl1_pack(uint8_t clknintsrmsk, uint8_t clknintsrval, uint8_t fifointmsk, uint8_t timestamptgt2intmsk, uint8_t timestamptgt1intmsk, uint8_t finetgtintmsk, uint8_t swintmsk, uint8_t cryptintmsk, uint8_t slpintmsk, uint8_t clknintmsk) +{ + BLE_ASSERT_ERR((((uint32_t)clknintsrmsk << 28) & ~((uint32_t)0x70000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)clknintsrval << 24) & ~((uint32_t)0x0F000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)fifointmsk << 15) & ~((uint32_t)0x00008000)) == 0); + BLE_ASSERT_ERR((((uint32_t)timestamptgt2intmsk << 6) & ~((uint32_t)0x00000040)) == 0); + BLE_ASSERT_ERR((((uint32_t)timestamptgt1intmsk << 5) & ~((uint32_t)0x00000020)) == 0); + BLE_ASSERT_ERR((((uint32_t)finetgtintmsk << 4) & ~((uint32_t)0x00000010)) == 0); + BLE_ASSERT_ERR((((uint32_t)swintmsk << 3) & ~((uint32_t)0x00000008)) == 0); + BLE_ASSERT_ERR((((uint32_t)cryptintmsk << 2) & ~((uint32_t)0x00000004)) == 0); + BLE_ASSERT_ERR((((uint32_t)slpintmsk << 1) & ~((uint32_t)0x00000002)) == 0); + BLE_ASSERT_ERR((((uint32_t)clknintmsk << 0) & ~((uint32_t)0x00000001)) == 0); + REG_IP_WR(IP_INTCNTL1_ADDR, ((uint32_t)clknintsrmsk << 28) | ((uint32_t)clknintsrval << 24) | ((uint32_t)fifointmsk << 15) | ((uint32_t)timestamptgt2intmsk << 6) | ((uint32_t)timestamptgt1intmsk << 5) | ((uint32_t)finetgtintmsk << 4) | ((uint32_t)swintmsk << 3) | ((uint32_t)cryptintmsk << 2) | ((uint32_t)slpintmsk << 1) | ((uint32_t)clknintmsk << 0)); +} + +__INLINE void ip_intcntl1_unpack(uint8_t* clknintsrmsk, uint8_t* clknintsrval, uint8_t* fifointmsk, uint8_t* timestamptgt2intmsk, uint8_t* timestamptgt1intmsk, uint8_t* finetgtintmsk, uint8_t* swintmsk, uint8_t* cryptintmsk, uint8_t* slpintmsk, uint8_t* clknintmsk) +{ + uint32_t localVal = REG_IP_RD(IP_INTCNTL1_ADDR); + + *clknintsrmsk = (localVal & ((uint32_t)0x70000000)) >> 28; + *clknintsrval = (localVal & ((uint32_t)0x0F000000)) >> 24; + *fifointmsk = (localVal & ((uint32_t)0x00008000)) >> 15; + *timestamptgt2intmsk = (localVal & ((uint32_t)0x00000040)) >> 6; + *timestamptgt1intmsk = (localVal & ((uint32_t)0x00000020)) >> 5; + *finetgtintmsk = (localVal & ((uint32_t)0x00000010)) >> 4; + *swintmsk = (localVal & ((uint32_t)0x00000008)) >> 3; + *cryptintmsk = (localVal & ((uint32_t)0x00000004)) >> 2; + *slpintmsk = (localVal & ((uint32_t)0x00000002)) >> 1; + *clknintmsk = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +__INLINE uint8_t ip_intcntl1_clknintsrmsk_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_INTCNTL1_ADDR); + return ((localVal & ((uint32_t)0x70000000)) >> 28); +} + +__INLINE void ip_intcntl1_clknintsrmsk_setf(uint8_t clknintsrmsk) +{ + BLE_ASSERT_ERR((((uint32_t)clknintsrmsk << 28) & ~((uint32_t)0x70000000)) == 0); + REG_IP_WR(IP_INTCNTL1_ADDR, (REG_IP_RD(IP_INTCNTL1_ADDR) & ~((uint32_t)0x70000000)) | ((uint32_t)clknintsrmsk << 28)); +} + +__INLINE uint8_t ip_intcntl1_clknintsrval_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_INTCNTL1_ADDR); + return ((localVal & ((uint32_t)0x0F000000)) >> 24); +} + +__INLINE void ip_intcntl1_clknintsrval_setf(uint8_t clknintsrval) +{ + BLE_ASSERT_ERR((((uint32_t)clknintsrval << 24) & ~((uint32_t)0x0F000000)) == 0); + REG_IP_WR(IP_INTCNTL1_ADDR, (REG_IP_RD(IP_INTCNTL1_ADDR) & ~((uint32_t)0x0F000000)) | ((uint32_t)clknintsrval << 24)); +} + +__INLINE uint8_t ip_intcntl1_fifointmsk_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_INTCNTL1_ADDR); + return ((localVal & ((uint32_t)0x00008000)) >> 15); +} + +__INLINE void ip_intcntl1_fifointmsk_setf(uint8_t fifointmsk) +{ + BLE_ASSERT_ERR((((uint32_t)fifointmsk << 15) & ~((uint32_t)0x00008000)) == 0); + REG_IP_WR(IP_INTCNTL1_ADDR, (REG_IP_RD(IP_INTCNTL1_ADDR) & ~((uint32_t)0x00008000)) | ((uint32_t)fifointmsk << 15)); +} + +__INLINE uint8_t ip_intcntl1_timestamptgt2intmsk_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_INTCNTL1_ADDR); + return ((localVal & ((uint32_t)0x00000040)) >> 6); +} + +__INLINE void ip_intcntl1_timestamptgt2intmsk_setf(uint8_t timestamptgt2intmsk) +{ + BLE_ASSERT_ERR((((uint32_t)timestamptgt2intmsk << 6) & ~((uint32_t)0x00000040)) == 0); + REG_IP_WR(IP_INTCNTL1_ADDR, (REG_IP_RD(IP_INTCNTL1_ADDR) & ~((uint32_t)0x00000040)) | ((uint32_t)timestamptgt2intmsk << 6)); +} + +__INLINE uint8_t ip_intcntl1_timestamptgt1intmsk_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_INTCNTL1_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +__INLINE void ip_intcntl1_timestamptgt1intmsk_setf(uint8_t timestamptgt1intmsk) +{ + BLE_ASSERT_ERR((((uint32_t)timestamptgt1intmsk << 5) & ~((uint32_t)0x00000020)) == 0); + REG_IP_WR(IP_INTCNTL1_ADDR, (REG_IP_RD(IP_INTCNTL1_ADDR) & ~((uint32_t)0x00000020)) | ((uint32_t)timestamptgt1intmsk << 5)); +} + +__INLINE uint8_t ip_intcntl1_finetgtintmsk_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_INTCNTL1_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +__INLINE void ip_intcntl1_finetgtintmsk_setf(uint8_t finetgtintmsk) +{ + BLE_ASSERT_ERR((((uint32_t)finetgtintmsk << 4) & ~((uint32_t)0x00000010)) == 0); + REG_IP_WR(IP_INTCNTL1_ADDR, (REG_IP_RD(IP_INTCNTL1_ADDR) & ~((uint32_t)0x00000010)) | ((uint32_t)finetgtintmsk << 4)); +} + +__INLINE uint8_t ip_intcntl1_swintmsk_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_INTCNTL1_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +__INLINE void ip_intcntl1_swintmsk_setf(uint8_t swintmsk) +{ + BLE_ASSERT_ERR((((uint32_t)swintmsk << 3) & ~((uint32_t)0x00000008)) == 0); + REG_IP_WR(IP_INTCNTL1_ADDR, (REG_IP_RD(IP_INTCNTL1_ADDR) & ~((uint32_t)0x00000008)) | ((uint32_t)swintmsk << 3)); +} + +__INLINE uint8_t ip_intcntl1_cryptintmsk_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_INTCNTL1_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +__INLINE void ip_intcntl1_cryptintmsk_setf(uint8_t cryptintmsk) +{ + BLE_ASSERT_ERR((((uint32_t)cryptintmsk << 2) & ~((uint32_t)0x00000004)) == 0); + REG_IP_WR(IP_INTCNTL1_ADDR, (REG_IP_RD(IP_INTCNTL1_ADDR) & ~((uint32_t)0x00000004)) | ((uint32_t)cryptintmsk << 2)); +} + +__INLINE uint8_t ip_intcntl1_slpintmsk_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_INTCNTL1_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +__INLINE void ip_intcntl1_slpintmsk_setf(uint8_t slpintmsk) +{ + BLE_ASSERT_ERR((((uint32_t)slpintmsk << 1) & ~((uint32_t)0x00000002)) == 0); + REG_IP_WR(IP_INTCNTL1_ADDR, (REG_IP_RD(IP_INTCNTL1_ADDR) & ~((uint32_t)0x00000002)) | ((uint32_t)slpintmsk << 1)); +} + +__INLINE uint8_t ip_intcntl1_clknintmsk_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_INTCNTL1_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +__INLINE void ip_intcntl1_clknintmsk_setf(uint8_t clknintmsk) +{ + BLE_ASSERT_ERR((((uint32_t)clknintmsk << 0) & ~((uint32_t)0x00000001)) == 0); + REG_IP_WR(IP_INTCNTL1_ADDR, (REG_IP_RD(IP_INTCNTL1_ADDR) & ~((uint32_t)0x00000001)) | ((uint32_t)clknintmsk << 0)); +} + +/** + * @brief INTSTAT1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     15          FIFOINTSTAT   0
+ *     06   TIMESTAMPTGT2INTSTAT   0
+ *     05   TIMESTAMPTGT1INTSTAT   0
+ *     04       FINETGTINTSTAT   0
+ *     03            SWINTSTAT   0
+ *     02         CRYPTINTSTAT   0
+ *     01           SLPINTSTAT   0
+ *     00          CLKNINTSTAT   0
+ * 
+ */ +#define IP_INTSTAT1_ADDR 0x0090001C +#define IP_INTSTAT1_OFFSET 0x0000001C +#define IP_INTSTAT1_INDEX 0x00000007 +#define IP_INTSTAT1_RESET 0x00000000 + +__INLINE uint32_t ip_intstat1_get(void) +{ + return REG_IP_RD(IP_INTSTAT1_ADDR); +} + +// field definitions +#define IP_FIFOINTSTAT_BIT ((uint32_t)0x00008000) +#define IP_FIFOINTSTAT_POS 15 +#define IP_TIMESTAMPTGT2INTSTAT_BIT ((uint32_t)0x00000040) +#define IP_TIMESTAMPTGT2INTSTAT_POS 6 +#define IP_TIMESTAMPTGT1INTSTAT_BIT ((uint32_t)0x00000020) +#define IP_TIMESTAMPTGT1INTSTAT_POS 5 +#define IP_FINETGTINTSTAT_BIT ((uint32_t)0x00000010) +#define IP_FINETGTINTSTAT_POS 4 +#define IP_SWINTSTAT_BIT ((uint32_t)0x00000008) +#define IP_SWINTSTAT_POS 3 +#define IP_CRYPTINTSTAT_BIT ((uint32_t)0x00000004) +#define IP_CRYPTINTSTAT_POS 2 +#define IP_SLPINTSTAT_BIT ((uint32_t)0x00000002) +#define IP_SLPINTSTAT_POS 1 +#define IP_CLKNINTSTAT_BIT ((uint32_t)0x00000001) +#define IP_CLKNINTSTAT_POS 0 + +#define IP_FIFOINTSTAT_RST 0x0 +#define IP_TIMESTAMPTGT2INTSTAT_RST 0x0 +#define IP_TIMESTAMPTGT1INTSTAT_RST 0x0 +#define IP_FINETGTINTSTAT_RST 0x0 +#define IP_SWINTSTAT_RST 0x0 +#define IP_CRYPTINTSTAT_RST 0x0 +#define IP_SLPINTSTAT_RST 0x0 +#define IP_CLKNINTSTAT_RST 0x0 + +__INLINE void ip_intstat1_unpack(uint8_t* fifointstat, uint8_t* timestamptgt2intstat, uint8_t* timestamptgt1intstat, uint8_t* finetgtintstat, uint8_t* swintstat, uint8_t* cryptintstat, uint8_t* slpintstat, uint8_t* clknintstat) +{ + uint32_t localVal = REG_IP_RD(IP_INTSTAT1_ADDR); + + *fifointstat = (localVal & ((uint32_t)0x00008000)) >> 15; + *timestamptgt2intstat = (localVal & ((uint32_t)0x00000040)) >> 6; + *timestamptgt1intstat = (localVal & ((uint32_t)0x00000020)) >> 5; + *finetgtintstat = (localVal & ((uint32_t)0x00000010)) >> 4; + *swintstat = (localVal & ((uint32_t)0x00000008)) >> 3; + *cryptintstat = (localVal & ((uint32_t)0x00000004)) >> 2; + *slpintstat = (localVal & ((uint32_t)0x00000002)) >> 1; + *clknintstat = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +__INLINE uint8_t ip_intstat1_fifointstat_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_INTSTAT1_ADDR); + return ((localVal & ((uint32_t)0x00008000)) >> 15); +} + +__INLINE uint8_t ip_intstat1_timestamptgt2intstat_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_INTSTAT1_ADDR); + return ((localVal & ((uint32_t)0x00000040)) >> 6); +} + +__INLINE uint8_t ip_intstat1_timestamptgt1intstat_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_INTSTAT1_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +__INLINE uint8_t ip_intstat1_finetgtintstat_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_INTSTAT1_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +__INLINE uint8_t ip_intstat1_swintstat_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_INTSTAT1_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +__INLINE uint8_t ip_intstat1_cryptintstat_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_INTSTAT1_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +__INLINE uint8_t ip_intstat1_slpintstat_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_INTSTAT1_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +__INLINE uint8_t ip_intstat1_clknintstat_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_INTSTAT1_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/** + * @brief INTACK1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     15           FIFOINTACK   0
+ *     06   TIMESTAMPTGT2INTACK   0
+ *     05   TIMESTAMPTGT1INTACK   0
+ *     04        FINETGTINTACK   0
+ *     03             SWINTACK   0
+ *     02          CRYPTINTACK   0
+ *     01            SLPINTACK   0
+ *     00           CLKNINTACK   0
+ * 
+ */ +#define IP_INTACK1_ADDR 0x00900020 +#define IP_INTACK1_OFFSET 0x00000020 +#define IP_INTACK1_INDEX 0x00000008 +#define IP_INTACK1_RESET 0x00000000 + +__INLINE uint32_t ip_intack1_get(void) +{ + return REG_IP_RD(IP_INTACK1_ADDR); +} + +__INLINE void ip_intack1_clear(uint32_t value) +{ + REG_IP_WR(IP_INTACK1_ADDR, value); +} + +// field definitions +#define IP_FIFOINTACK_BIT ((uint32_t)0x00008000) +#define IP_FIFOINTACK_POS 15 +#define IP_TIMESTAMPTGT2INTACK_BIT ((uint32_t)0x00000040) +#define IP_TIMESTAMPTGT2INTACK_POS 6 +#define IP_TIMESTAMPTGT1INTACK_BIT ((uint32_t)0x00000020) +#define IP_TIMESTAMPTGT1INTACK_POS 5 +#define IP_FINETGTINTACK_BIT ((uint32_t)0x00000010) +#define IP_FINETGTINTACK_POS 4 +#define IP_SWINTACK_BIT ((uint32_t)0x00000008) +#define IP_SWINTACK_POS 3 +#define IP_CRYPTINTACK_BIT ((uint32_t)0x00000004) +#define IP_CRYPTINTACK_POS 2 +#define IP_SLPINTACK_BIT ((uint32_t)0x00000002) +#define IP_SLPINTACK_POS 1 +#define IP_CLKNINTACK_BIT ((uint32_t)0x00000001) +#define IP_CLKNINTACK_POS 0 + +#define IP_FIFOINTACK_RST 0x0 +#define IP_TIMESTAMPTGT2INTACK_RST 0x0 +#define IP_TIMESTAMPTGT1INTACK_RST 0x0 +#define IP_FINETGTINTACK_RST 0x0 +#define IP_SWINTACK_RST 0x0 +#define IP_CRYPTINTACK_RST 0x0 +#define IP_SLPINTACK_RST 0x0 +#define IP_CLKNINTACK_RST 0x0 + +__INLINE void ip_intack1_pack(uint8_t fifointack, uint8_t timestamptgt2intack, uint8_t timestamptgt1intack, uint8_t finetgtintack, uint8_t swintack, uint8_t cryptintack, uint8_t slpintack, uint8_t clknintack) +{ + BLE_ASSERT_ERR((((uint32_t)fifointack << 15) & ~((uint32_t)0x00008000)) == 0); + BLE_ASSERT_ERR((((uint32_t)timestamptgt2intack << 6) & ~((uint32_t)0x00000040)) == 0); + BLE_ASSERT_ERR((((uint32_t)timestamptgt1intack << 5) & ~((uint32_t)0x00000020)) == 0); + BLE_ASSERT_ERR((((uint32_t)finetgtintack << 4) & ~((uint32_t)0x00000010)) == 0); + BLE_ASSERT_ERR((((uint32_t)swintack << 3) & ~((uint32_t)0x00000008)) == 0); + BLE_ASSERT_ERR((((uint32_t)cryptintack << 2) & ~((uint32_t)0x00000004)) == 0); + BLE_ASSERT_ERR((((uint32_t)slpintack << 1) & ~((uint32_t)0x00000002)) == 0); + BLE_ASSERT_ERR((((uint32_t)clknintack << 0) & ~((uint32_t)0x00000001)) == 0); + REG_IP_WR(IP_INTACK1_ADDR, ((uint32_t)fifointack << 15) | ((uint32_t)timestamptgt2intack << 6) | ((uint32_t)timestamptgt1intack << 5) | ((uint32_t)finetgtintack << 4) | ((uint32_t)swintack << 3) | ((uint32_t)cryptintack << 2) | ((uint32_t)slpintack << 1) | ((uint32_t)clknintack << 0)); +} + +__INLINE void ip_intack1_unpack(uint8_t* fifointack, uint8_t* timestamptgt2intack, uint8_t* timestamptgt1intack, uint8_t* finetgtintack, uint8_t* swintack, uint8_t* cryptintack, uint8_t* slpintack, uint8_t* clknintack) +{ + uint32_t localVal = REG_IP_RD(IP_INTACK1_ADDR); + + *fifointack = (localVal & ((uint32_t)0x00008000)) >> 15; + *timestamptgt2intack = (localVal & ((uint32_t)0x00000040)) >> 6; + *timestamptgt1intack = (localVal & ((uint32_t)0x00000020)) >> 5; + *finetgtintack = (localVal & ((uint32_t)0x00000010)) >> 4; + *swintack = (localVal & ((uint32_t)0x00000008)) >> 3; + *cryptintack = (localVal & ((uint32_t)0x00000004)) >> 2; + *slpintack = (localVal & ((uint32_t)0x00000002)) >> 1; + *clknintack = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +__INLINE uint8_t ip_intack1_fifointack_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_INTACK1_ADDR); + return ((localVal & ((uint32_t)0x00008000)) >> 15); +} + +__INLINE void ip_intack1_fifointack_clearf(uint8_t fifointack) +{ + BLE_ASSERT_ERR((((uint32_t)fifointack << 15) & ~((uint32_t)0x00008000)) == 0); + REG_IP_WR(IP_INTACK1_ADDR, (uint32_t)fifointack << 15); +} + +__INLINE uint8_t ip_intack1_timestamptgt2intack_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_INTACK1_ADDR); + return ((localVal & ((uint32_t)0x00000040)) >> 6); +} + +__INLINE void ip_intack1_timestamptgt2intack_clearf(uint8_t timestamptgt2intack) +{ + BLE_ASSERT_ERR((((uint32_t)timestamptgt2intack << 6) & ~((uint32_t)0x00000040)) == 0); + REG_IP_WR(IP_INTACK1_ADDR, (uint32_t)timestamptgt2intack << 6); +} + +__INLINE uint8_t ip_intack1_timestamptgt1intack_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_INTACK1_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +__INLINE void ip_intack1_timestamptgt1intack_clearf(uint8_t timestamptgt1intack) +{ + BLE_ASSERT_ERR((((uint32_t)timestamptgt1intack << 5) & ~((uint32_t)0x00000020)) == 0); + REG_IP_WR(IP_INTACK1_ADDR, (uint32_t)timestamptgt1intack << 5); +} + +__INLINE uint8_t ip_intack1_finetgtintack_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_INTACK1_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +__INLINE void ip_intack1_finetgtintack_clearf(uint8_t finetgtintack) +{ + BLE_ASSERT_ERR((((uint32_t)finetgtintack << 4) & ~((uint32_t)0x00000010)) == 0); + REG_IP_WR(IP_INTACK1_ADDR, (uint32_t)finetgtintack << 4); +} + +__INLINE uint8_t ip_intack1_swintack_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_INTACK1_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +__INLINE void ip_intack1_swintack_clearf(uint8_t swintack) +{ + BLE_ASSERT_ERR((((uint32_t)swintack << 3) & ~((uint32_t)0x00000008)) == 0); + REG_IP_WR(IP_INTACK1_ADDR, (uint32_t)swintack << 3); +} + +__INLINE uint8_t ip_intack1_cryptintack_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_INTACK1_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +__INLINE void ip_intack1_cryptintack_clearf(uint8_t cryptintack) +{ + BLE_ASSERT_ERR((((uint32_t)cryptintack << 2) & ~((uint32_t)0x00000004)) == 0); + REG_IP_WR(IP_INTACK1_ADDR, (uint32_t)cryptintack << 2); +} + +__INLINE uint8_t ip_intack1_slpintack_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_INTACK1_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +__INLINE void ip_intack1_slpintack_clearf(uint8_t slpintack) +{ + BLE_ASSERT_ERR((((uint32_t)slpintack << 1) & ~((uint32_t)0x00000002)) == 0); + REG_IP_WR(IP_INTACK1_ADDR, (uint32_t)slpintack << 1); +} + +__INLINE uint8_t ip_intack1_clknintack_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_INTACK1_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +__INLINE void ip_intack1_clknintack_clearf(uint8_t clknintack) +{ + BLE_ASSERT_ERR((((uint32_t)clknintack << 0) & ~((uint32_t)0x00000001)) == 0); + REG_IP_WR(IP_INTACK1_ADDR, (uint32_t)clknintack << 0); +} + +/** + * @brief ACTFIFOSTAT register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:28          SKIP_ET_IDX   0x0
+ *  27:24       CURRENT_ET_IDX   0x0
+ *     15              ACTFLAG   0
+ *     06         ISORXINTSTAT   0
+ *     05         ISOTXINTSTAT   0
+ *     04            RXINTSTAT   0
+ *     03            TXINTSTAT   0
+ *     02       SKIPACTINTSTAT   0
+ *     01        ENDACTINTSTAT   0
+ *     00      STARTACTINTSTAT   0
+ * 
+ */ +#define IP_ACTFIFOSTAT_ADDR 0x00900024 +#define IP_ACTFIFOSTAT_OFFSET 0x00000024 +#define IP_ACTFIFOSTAT_INDEX 0x00000009 +#define IP_ACTFIFOSTAT_RESET 0x00000000 + +__INLINE uint32_t ip_actfifostat_get(void) +{ + return REG_IP_RD(IP_ACTFIFOSTAT_ADDR); +} + +// field definitions +#define IP_SKIP_ET_IDX_MASK ((uint32_t)0xF0000000) +#define IP_SKIP_ET_IDX_LSB 28 +#define IP_SKIP_ET_IDX_WIDTH ((uint32_t)0x00000004) +#define IP_CURRENT_ET_IDX_MASK ((uint32_t)0x0F000000) +#define IP_CURRENT_ET_IDX_LSB 24 +#define IP_CURRENT_ET_IDX_WIDTH ((uint32_t)0x00000004) +#define IP_ACTFLAG_BIT ((uint32_t)0x00008000) +#define IP_ACTFLAG_POS 15 +#define IP_ISORXINTSTAT_BIT ((uint32_t)0x00000040) +#define IP_ISORXINTSTAT_POS 6 +#define IP_ISOTXINTSTAT_BIT ((uint32_t)0x00000020) +#define IP_ISOTXINTSTAT_POS 5 +#define IP_RXINTSTAT_BIT ((uint32_t)0x00000010) +#define IP_RXINTSTAT_POS 4 +#define IP_TXINTSTAT_BIT ((uint32_t)0x00000008) +#define IP_TXINTSTAT_POS 3 +#define IP_SKIPACTINTSTAT_BIT ((uint32_t)0x00000004) +#define IP_SKIPACTINTSTAT_POS 2 +#define IP_ENDACTINTSTAT_BIT ((uint32_t)0x00000002) +#define IP_ENDACTINTSTAT_POS 1 +#define IP_STARTACTINTSTAT_BIT ((uint32_t)0x00000001) +#define IP_STARTACTINTSTAT_POS 0 + +#define IP_SKIP_ET_IDX_RST 0x0 +#define IP_CURRENT_ET_IDX_RST 0x0 +#define IP_ACTFLAG_RST 0x0 +#define IP_ISORXINTSTAT_RST 0x0 +#define IP_ISOTXINTSTAT_RST 0x0 +#define IP_RXINTSTAT_RST 0x0 +#define IP_TXINTSTAT_RST 0x0 +#define IP_SKIPACTINTSTAT_RST 0x0 +#define IP_ENDACTINTSTAT_RST 0x0 +#define IP_STARTACTINTSTAT_RST 0x0 + +__INLINE void ip_actfifostat_unpack(uint8_t* skipetidx, uint8_t* currentetidx, uint8_t* actflag, uint8_t* isorxintstat, uint8_t* isotxintstat, uint8_t* rxintstat, uint8_t* txintstat, uint8_t* skipactintstat, uint8_t* endactintstat, uint8_t* startactintstat) +{ + uint32_t localVal = REG_IP_RD(IP_ACTFIFOSTAT_ADDR); + + *skipetidx = (localVal & ((uint32_t)0xF0000000)) >> 28; + *currentetidx = (localVal & ((uint32_t)0x0F000000)) >> 24; + *actflag = (localVal & ((uint32_t)0x00008000)) >> 15; + *isorxintstat = (localVal & ((uint32_t)0x00000040)) >> 6; + *isotxintstat = (localVal & ((uint32_t)0x00000020)) >> 5; + *rxintstat = (localVal & ((uint32_t)0x00000010)) >> 4; + *txintstat = (localVal & ((uint32_t)0x00000008)) >> 3; + *skipactintstat = (localVal & ((uint32_t)0x00000004)) >> 2; + *endactintstat = (localVal & ((uint32_t)0x00000002)) >> 1; + *startactintstat = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +__INLINE uint8_t ip_actfifostat_skip_et_idx_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_ACTFIFOSTAT_ADDR); + return ((localVal & ((uint32_t)0xF0000000)) >> 28); +} + +__INLINE uint8_t ip_actfifostat_current_et_idx_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_ACTFIFOSTAT_ADDR); + return ((localVal & ((uint32_t)0x0F000000)) >> 24); +} + +__INLINE uint8_t ip_actfifostat_actflag_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_ACTFIFOSTAT_ADDR); + return ((localVal & ((uint32_t)0x00008000)) >> 15); +} + +__INLINE uint8_t ip_actfifostat_isorxintstat_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_ACTFIFOSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000040)) >> 6); +} + +__INLINE uint8_t ip_actfifostat_isotxintstat_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_ACTFIFOSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +__INLINE uint8_t ip_actfifostat_rxintstat_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_ACTFIFOSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +__INLINE uint8_t ip_actfifostat_txintstat_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_ACTFIFOSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +__INLINE uint8_t ip_actfifostat_skipactintstat_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_ACTFIFOSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +__INLINE uint8_t ip_actfifostat_endactintstat_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_ACTFIFOSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +__INLINE uint8_t ip_actfifostat_startactintstat_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_ACTFIFOSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/** + * @brief ETPTR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  13:00                ETPTR   0x0
+ * 
+ */ +#define IP_ETPTR_ADDR 0x0090002C +#define IP_ETPTR_OFFSET 0x0000002C +#define IP_ETPTR_INDEX 0x0000000B +#define IP_ETPTR_RESET 0x00000000 + +__INLINE uint32_t ip_etptr_get(void) +{ + return REG_IP_RD(IP_ETPTR_ADDR); +} + +__INLINE void ip_etptr_set(uint32_t value) +{ + REG_IP_WR(IP_ETPTR_ADDR, value); +} + +// field definitions +#define IP_ETPTR_MASK ((uint32_t)0x00003FFF) +#define IP_ETPTR_LSB 0 +#define IP_ETPTR_WIDTH ((uint32_t)0x0000000E) + +#define IP_ETPTR_RST 0x0 + +__INLINE uint16_t ip_etptr_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_ETPTR_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0x00003FFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ip_etptr_setf(uint16_t etptr) +{ + BLE_ASSERT_ERR((((uint32_t)etptr << 0) & ~((uint32_t)0x00003FFF)) == 0); + REG_IP_WR(IP_ETPTR_ADDR, (uint32_t)etptr << 0); +} + +/** + * @brief DEEPSLCNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31           EXTWKUPDSB   0
+ *     15      DEEP_SLEEP_STAT   0
+ *     03   DEEP_SLEEP_CORR_EN   0
+ *     02        DEEP_SLEEP_ON   0
+ *     01       RADIO_SLEEP_EN   0
+ *     00         OSC_SLEEP_EN   0
+ * 
+ */ +#define IP_DEEPSLCNTL_ADDR 0x00900030 +#define IP_DEEPSLCNTL_OFFSET 0x00000030 +#define IP_DEEPSLCNTL_INDEX 0x0000000C +#define IP_DEEPSLCNTL_RESET 0x00000000 + +__INLINE uint32_t ip_deepslcntl_get(void) +{ + return REG_IP_RD(IP_DEEPSLCNTL_ADDR); +} + +__INLINE void ip_deepslcntl_set(uint32_t value) +{ + REG_IP_WR(IP_DEEPSLCNTL_ADDR, value); +} + +// field definitions +#define IP_EXTWKUPDSB_BIT ((uint32_t)0x80000000) +#define IP_EXTWKUPDSB_POS 31 +#define IP_DEEP_SLEEP_STAT_BIT ((uint32_t)0x00008000) +#define IP_DEEP_SLEEP_STAT_POS 15 +#define IP_DEEP_SLEEP_CORR_EN_BIT ((uint32_t)0x00000008) +#define IP_DEEP_SLEEP_CORR_EN_POS 3 +#define IP_DEEP_SLEEP_ON_BIT ((uint32_t)0x00000004) +#define IP_DEEP_SLEEP_ON_POS 2 +#define IP_RADIO_SLEEP_EN_BIT ((uint32_t)0x00000002) +#define IP_RADIO_SLEEP_EN_POS 1 +#define IP_OSC_SLEEP_EN_BIT ((uint32_t)0x00000001) +#define IP_OSC_SLEEP_EN_POS 0 + +#define IP_EXTWKUPDSB_RST 0x0 +#define IP_DEEP_SLEEP_STAT_RST 0x0 +#define IP_DEEP_SLEEP_CORR_EN_RST 0x0 +#define IP_DEEP_SLEEP_ON_RST 0x0 +#define IP_RADIO_SLEEP_EN_RST 0x0 +#define IP_OSC_SLEEP_EN_RST 0x0 + +__INLINE void ip_deepslcntl_pack(uint8_t extwkupdsb, uint8_t deepsleepcorren, uint8_t deepsleepon, uint8_t radiosleepen, uint8_t oscsleepen) +{ + BLE_ASSERT_ERR((((uint32_t)extwkupdsb << 31) & ~((uint32_t)0x80000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)deepsleepcorren << 3) & ~((uint32_t)0x00000008)) == 0); + BLE_ASSERT_ERR((((uint32_t)deepsleepon << 2) & ~((uint32_t)0x00000004)) == 0); + BLE_ASSERT_ERR((((uint32_t)radiosleepen << 1) & ~((uint32_t)0x00000002)) == 0); + BLE_ASSERT_ERR((((uint32_t)oscsleepen << 0) & ~((uint32_t)0x00000001)) == 0); + REG_IP_WR(IP_DEEPSLCNTL_ADDR, ((uint32_t)extwkupdsb << 31) | ((uint32_t)deepsleepcorren << 3) | ((uint32_t)deepsleepon << 2) | ((uint32_t)radiosleepen << 1) | ((uint32_t)oscsleepen << 0)); +} + +__INLINE void ip_deepslcntl_unpack(uint8_t* extwkupdsb, uint8_t* deepsleepstat, uint8_t* deepsleepcorren, uint8_t* deepsleepon, uint8_t* radiosleepen, uint8_t* oscsleepen) +{ + uint32_t localVal = REG_IP_RD(IP_DEEPSLCNTL_ADDR); + + *extwkupdsb = (localVal & ((uint32_t)0x80000000)) >> 31; + *deepsleepstat = (localVal & ((uint32_t)0x00008000)) >> 15; + *deepsleepcorren = (localVal & ((uint32_t)0x00000008)) >> 3; + *deepsleepon = (localVal & ((uint32_t)0x00000004)) >> 2; + *radiosleepen = (localVal & ((uint32_t)0x00000002)) >> 1; + *oscsleepen = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +__INLINE uint8_t ip_deepslcntl_extwkupdsb_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_DEEPSLCNTL_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +__INLINE void ip_deepslcntl_extwkupdsb_setf(uint8_t extwkupdsb) +{ + BLE_ASSERT_ERR((((uint32_t)extwkupdsb << 31) & ~((uint32_t)0x80000000)) == 0); + REG_IP_WR(IP_DEEPSLCNTL_ADDR, (REG_IP_RD(IP_DEEPSLCNTL_ADDR) & ~((uint32_t)0x80000000)) | ((uint32_t)extwkupdsb << 31)); +} + +__INLINE uint8_t ip_deepslcntl_deep_sleep_stat_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_DEEPSLCNTL_ADDR); + return ((localVal & ((uint32_t)0x00008000)) >> 15); +} + +__INLINE uint8_t ip_deepslcntl_deep_sleep_corr_en_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_DEEPSLCNTL_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +__INLINE void ip_deepslcntl_deep_sleep_corr_en_setf(uint8_t deepsleepcorren) +{ + BLE_ASSERT_ERR((((uint32_t)deepsleepcorren << 3) & ~((uint32_t)0x00000008)) == 0); + REG_IP_WR(IP_DEEPSLCNTL_ADDR, (REG_IP_RD(IP_DEEPSLCNTL_ADDR) & ~((uint32_t)0x00000008)) | ((uint32_t)deepsleepcorren << 3)); +} + +__INLINE uint8_t ip_deepslcntl_deep_sleep_on_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_DEEPSLCNTL_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +__INLINE void ip_deepslcntl_deep_sleep_on_setf(uint8_t deepsleepon) +{ + BLE_ASSERT_ERR((((uint32_t)deepsleepon << 2) & ~((uint32_t)0x00000004)) == 0); + REG_IP_WR(IP_DEEPSLCNTL_ADDR, (REG_IP_RD(IP_DEEPSLCNTL_ADDR) & ~((uint32_t)0x00000004)) | ((uint32_t)deepsleepon << 2)); +} + +__INLINE uint8_t ip_deepslcntl_radio_sleep_en_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_DEEPSLCNTL_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +__INLINE void ip_deepslcntl_radio_sleep_en_setf(uint8_t radiosleepen) +{ + BLE_ASSERT_ERR((((uint32_t)radiosleepen << 1) & ~((uint32_t)0x00000002)) == 0); + REG_IP_WR(IP_DEEPSLCNTL_ADDR, (REG_IP_RD(IP_DEEPSLCNTL_ADDR) & ~((uint32_t)0x00000002)) | ((uint32_t)radiosleepen << 1)); +} + +__INLINE uint8_t ip_deepslcntl_osc_sleep_en_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_DEEPSLCNTL_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +__INLINE void ip_deepslcntl_osc_sleep_en_setf(uint8_t oscsleepen) +{ + BLE_ASSERT_ERR((((uint32_t)oscsleepen << 0) & ~((uint32_t)0x00000001)) == 0); + REG_IP_WR(IP_DEEPSLCNTL_ADDR, (REG_IP_RD(IP_DEEPSLCNTL_ADDR) & ~((uint32_t)0x00000001)) | ((uint32_t)oscsleepen << 0)); +} + +/** + * @brief DEEPSLWKUP register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00           DEEPSLTIME   0x0
+ * 
+ */ +#define IP_DEEPSLWKUP_ADDR 0x00900034 +#define IP_DEEPSLWKUP_OFFSET 0x00000034 +#define IP_DEEPSLWKUP_INDEX 0x0000000D +#define IP_DEEPSLWKUP_RESET 0x00000000 + +__INLINE uint32_t ip_deepslwkup_get(void) +{ + return REG_IP_RD(IP_DEEPSLWKUP_ADDR); +} + +__INLINE void ip_deepslwkup_set(uint32_t value) +{ + REG_IP_WR(IP_DEEPSLWKUP_ADDR, value); +} + +// field definitions +#define IP_DEEPSLTIME_MASK ((uint32_t)0xFFFFFFFF) +#define IP_DEEPSLTIME_LSB 0 +#define IP_DEEPSLTIME_WIDTH ((uint32_t)0x00000020) + +#define IP_DEEPSLTIME_RST 0x0 + +__INLINE uint32_t ip_deepslwkup_deepsltime_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_DEEPSLWKUP_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ip_deepslwkup_deepsltime_setf(uint32_t deepsltime) +{ + BLE_ASSERT_ERR((((uint32_t)deepsltime << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_IP_WR(IP_DEEPSLWKUP_ADDR, (uint32_t)deepsltime << 0); +} + +/** + * @brief DEEPSLSTAT register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00            DEEPSLDUR   0x0
+ * 
+ */ +#define IP_DEEPSLSTAT_ADDR 0x00900038 +#define IP_DEEPSLSTAT_OFFSET 0x00000038 +#define IP_DEEPSLSTAT_INDEX 0x0000000E +#define IP_DEEPSLSTAT_RESET 0x00000000 + +__INLINE uint32_t ip_deepslstat_get(void) +{ + return REG_IP_RD(IP_DEEPSLSTAT_ADDR); +} + +// field definitions +#define IP_DEEPSLDUR_MASK ((uint32_t)0xFFFFFFFF) +#define IP_DEEPSLDUR_LSB 0 +#define IP_DEEPSLDUR_WIDTH ((uint32_t)0x00000020) + +#define IP_DEEPSLDUR_RST 0x0 + +__INLINE uint32_t ip_deepslstat_deepsldur_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_DEEPSLSTAT_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief ENBPRESET register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:21                TWEXT   0xA0
+ *  20:10                TWOSC   0xA0
+ *  09:00                 TWRM   0x20
+ * 
+ */ +#define IP_ENBPRESET_ADDR 0x0090003C +#define IP_ENBPRESET_OFFSET 0x0000003C +#define IP_ENBPRESET_INDEX 0x0000000F +#define IP_ENBPRESET_RESET 0x14028020 + +__INLINE uint32_t ip_enbpreset_get(void) +{ + return REG_IP_RD(IP_ENBPRESET_ADDR); +} + +__INLINE void ip_enbpreset_set(uint32_t value) +{ + REG_IP_WR(IP_ENBPRESET_ADDR, value); +} + +// field definitions +#define IP_TWEXT_MASK ((uint32_t)0xFFE00000) +#define IP_TWEXT_LSB 21 +#define IP_TWEXT_WIDTH ((uint32_t)0x0000000B) +#define IP_TWOSC_MASK ((uint32_t)0x001FFC00) +#define IP_TWOSC_LSB 10 +#define IP_TWOSC_WIDTH ((uint32_t)0x0000000B) +#define IP_TWRM_MASK ((uint32_t)0x000003FF) +#define IP_TWRM_LSB 0 +#define IP_TWRM_WIDTH ((uint32_t)0x0000000A) + +#define IP_TWEXT_RST 0xA0 +#define IP_TWOSC_RST 0xA0 +#define IP_TWRM_RST 0x20 + +__INLINE void ip_enbpreset_pack(uint16_t twext, uint16_t twosc, uint16_t twrm) +{ + BLE_ASSERT_ERR((((uint32_t)twext << 21) & ~((uint32_t)0xFFE00000)) == 0); + BLE_ASSERT_ERR((((uint32_t)twosc << 10) & ~((uint32_t)0x001FFC00)) == 0); + BLE_ASSERT_ERR((((uint32_t)twrm << 0) & ~((uint32_t)0x000003FF)) == 0); + REG_IP_WR(IP_ENBPRESET_ADDR, ((uint32_t)twext << 21) | ((uint32_t)twosc << 10) | ((uint32_t)twrm << 0)); +} + +__INLINE void ip_enbpreset_unpack(uint16_t* twext, uint16_t* twosc, uint16_t* twrm) +{ + uint32_t localVal = REG_IP_RD(IP_ENBPRESET_ADDR); + + *twext = (localVal & ((uint32_t)0xFFE00000)) >> 21; + *twosc = (localVal & ((uint32_t)0x001FFC00)) >> 10; + *twrm = (localVal & ((uint32_t)0x000003FF)) >> 0; +} + +__INLINE uint16_t ip_enbpreset_twext_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_ENBPRESET_ADDR); + return ((localVal & ((uint32_t)0xFFE00000)) >> 21); +} + +__INLINE void ip_enbpreset_twext_setf(uint16_t twext) +{ + BLE_ASSERT_ERR((((uint32_t)twext << 21) & ~((uint32_t)0xFFE00000)) == 0); + REG_IP_WR(IP_ENBPRESET_ADDR, (REG_IP_RD(IP_ENBPRESET_ADDR) & ~((uint32_t)0xFFE00000)) | ((uint32_t)twext << 21)); +} + +__INLINE uint16_t ip_enbpreset_twosc_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_ENBPRESET_ADDR); + return ((localVal & ((uint32_t)0x001FFC00)) >> 10); +} + +__INLINE void ip_enbpreset_twosc_setf(uint16_t twosc) +{ + BLE_ASSERT_ERR((((uint32_t)twosc << 10) & ~((uint32_t)0x001FFC00)) == 0); + REG_IP_WR(IP_ENBPRESET_ADDR, (REG_IP_RD(IP_ENBPRESET_ADDR) & ~((uint32_t)0x001FFC00)) | ((uint32_t)twosc << 10)); +} + +__INLINE uint16_t ip_enbpreset_twrm_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_ENBPRESET_ADDR); + return ((localVal & ((uint32_t)0x000003FF)) >> 0); +} + +__INLINE void ip_enbpreset_twrm_setf(uint16_t twrm) +{ + BLE_ASSERT_ERR((((uint32_t)twrm << 0) & ~((uint32_t)0x000003FF)) == 0); + REG_IP_WR(IP_ENBPRESET_ADDR, (REG_IP_RD(IP_ENBPRESET_ADDR) & ~((uint32_t)0x000003FF)) | ((uint32_t)twrm << 0)); +} + +/** + * @brief FINECNTCORR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  09:00          FINECNTCORR   0x0
+ * 
+ */ +#define IP_FINECNTCORR_ADDR 0x00900040 +#define IP_FINECNTCORR_OFFSET 0x00000040 +#define IP_FINECNTCORR_INDEX 0x00000010 +#define IP_FINECNTCORR_RESET 0x00000000 + +__INLINE uint32_t ip_finecntcorr_get(void) +{ + return REG_IP_RD(IP_FINECNTCORR_ADDR); +} + +__INLINE void ip_finecntcorr_set(uint32_t value) +{ + REG_IP_WR(IP_FINECNTCORR_ADDR, value); +} + +// field definitions +#define IP_FINECNTCORR_MASK ((uint32_t)0x000003FF) +#define IP_FINECNTCORR_LSB 0 +#define IP_FINECNTCORR_WIDTH ((uint32_t)0x0000000A) + +#define IP_FINECNTCORR_RST 0x0 + +__INLINE uint16_t ip_finecntcorr_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_FINECNTCORR_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0x000003FF)) == 0); + return (localVal >> 0); +} + +__INLINE void ip_finecntcorr_setf(uint16_t finecntcorr) +{ + BLE_ASSERT_ERR((((uint32_t)finecntcorr << 0) & ~((uint32_t)0x000003FF)) == 0); + REG_IP_WR(IP_FINECNTCORR_ADDR, (uint32_t)finecntcorr << 0); +} + +/** + * @brief CLKNCNTCORR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31            ABS_DELTA   0
+ *  27:00          CLKNCNTCORR   0x0
+ * 
+ */ +#define IP_CLKNCNTCORR_ADDR 0x00900044 +#define IP_CLKNCNTCORR_OFFSET 0x00000044 +#define IP_CLKNCNTCORR_INDEX 0x00000011 +#define IP_CLKNCNTCORR_RESET 0x00000000 + +__INLINE uint32_t ip_clkncntcorr_get(void) +{ + return REG_IP_RD(IP_CLKNCNTCORR_ADDR); +} + +__INLINE void ip_clkncntcorr_set(uint32_t value) +{ + REG_IP_WR(IP_CLKNCNTCORR_ADDR, value); +} + +// field definitions +#define IP_ABS_DELTA_BIT ((uint32_t)0x80000000) +#define IP_ABS_DELTA_POS 31 +#define IP_CLKNCNTCORR_MASK ((uint32_t)0x0FFFFFFF) +#define IP_CLKNCNTCORR_LSB 0 +#define IP_CLKNCNTCORR_WIDTH ((uint32_t)0x0000001C) + +#define IP_ABS_DELTA_RST 0x0 +#define IP_CLKNCNTCORR_RST 0x0 + +__INLINE void ip_clkncntcorr_pack(uint8_t absdelta, uint32_t clkncntcorr) +{ + BLE_ASSERT_ERR((((uint32_t)absdelta << 31) & ~((uint32_t)0x80000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)clkncntcorr << 0) & ~((uint32_t)0x0FFFFFFF)) == 0); + REG_IP_WR(IP_CLKNCNTCORR_ADDR, ((uint32_t)absdelta << 31) | ((uint32_t)clkncntcorr << 0)); +} + +__INLINE void ip_clkncntcorr_unpack(uint8_t* absdelta, uint32_t* clkncntcorr) +{ + uint32_t localVal = REG_IP_RD(IP_CLKNCNTCORR_ADDR); + + *absdelta = (localVal & ((uint32_t)0x80000000)) >> 31; + *clkncntcorr = (localVal & ((uint32_t)0x0FFFFFFF)) >> 0; +} + +__INLINE uint8_t ip_clkncntcorr_abs_delta_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_CLKNCNTCORR_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +__INLINE void ip_clkncntcorr_abs_delta_setf(uint8_t absdelta) +{ + BLE_ASSERT_ERR((((uint32_t)absdelta << 31) & ~((uint32_t)0x80000000)) == 0); + REG_IP_WR(IP_CLKNCNTCORR_ADDR, (REG_IP_RD(IP_CLKNCNTCORR_ADDR) & ~((uint32_t)0x80000000)) | ((uint32_t)absdelta << 31)); +} + +__INLINE uint32_t ip_clkncntcorr_clkncntcorr_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_CLKNCNTCORR_ADDR); + return ((localVal & ((uint32_t)0x0FFFFFFF)) >> 0); +} + +__INLINE void ip_clkncntcorr_clkncntcorr_setf(uint32_t clkncntcorr) +{ + BLE_ASSERT_ERR((((uint32_t)clkncntcorr << 0) & ~((uint32_t)0x0FFFFFFF)) == 0); + REG_IP_WR(IP_CLKNCNTCORR_ADDR, (REG_IP_RD(IP_CLKNCNTCORR_ADDR) & ~((uint32_t)0x0FFFFFFF)) | ((uint32_t)clkncntcorr << 0)); +} + +/** + * @brief DIAGCNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31             DIAG3_EN   0
+ *  29:24                DIAG3   0x0
+ *     23             DIAG2_EN   0
+ *  21:16                DIAG2   0x0
+ *     15             DIAG1_EN   0
+ *  13:08                DIAG1   0x0
+ *     07             DIAG0_EN   0
+ *  05:00                DIAG0   0x0
+ * 
+ */ +#define IP_DIAGCNTL_ADDR 0x00900050 +#define IP_DIAGCNTL_OFFSET 0x00000050 +#define IP_DIAGCNTL_INDEX 0x00000014 +#define IP_DIAGCNTL_RESET 0x00000000 + +__INLINE uint32_t ip_diagcntl_get(void) +{ + return REG_IP_RD(IP_DIAGCNTL_ADDR); +} + +__INLINE void ip_diagcntl_set(uint32_t value) +{ + REG_IP_WR(IP_DIAGCNTL_ADDR, value); +} + +// field definitions +#define IP_DIAG3_EN_BIT ((uint32_t)0x80000000) +#define IP_DIAG3_EN_POS 31 +#define IP_DIAG3_MASK ((uint32_t)0x3F000000) +#define IP_DIAG3_LSB 24 +#define IP_DIAG3_WIDTH ((uint32_t)0x00000006) +#define IP_DIAG2_EN_BIT ((uint32_t)0x00800000) +#define IP_DIAG2_EN_POS 23 +#define IP_DIAG2_MASK ((uint32_t)0x003F0000) +#define IP_DIAG2_LSB 16 +#define IP_DIAG2_WIDTH ((uint32_t)0x00000006) +#define IP_DIAG1_EN_BIT ((uint32_t)0x00008000) +#define IP_DIAG1_EN_POS 15 +#define IP_DIAG1_MASK ((uint32_t)0x00003F00) +#define IP_DIAG1_LSB 8 +#define IP_DIAG1_WIDTH ((uint32_t)0x00000006) +#define IP_DIAG0_EN_BIT ((uint32_t)0x00000080) +#define IP_DIAG0_EN_POS 7 +#define IP_DIAG0_MASK ((uint32_t)0x0000003F) +#define IP_DIAG0_LSB 0 +#define IP_DIAG0_WIDTH ((uint32_t)0x00000006) + +#define IP_DIAG3_EN_RST 0x0 +#define IP_DIAG3_RST 0x0 +#define IP_DIAG2_EN_RST 0x0 +#define IP_DIAG2_RST 0x0 +#define IP_DIAG1_EN_RST 0x0 +#define IP_DIAG1_RST 0x0 +#define IP_DIAG0_EN_RST 0x0 +#define IP_DIAG0_RST 0x0 + +__INLINE void ip_diagcntl_pack(uint8_t diag3en, uint8_t diag3, uint8_t diag2en, uint8_t diag2, uint8_t diag1en, uint8_t diag1, uint8_t diag0en, uint8_t diag0) +{ + BLE_ASSERT_ERR((((uint32_t)diag3en << 31) & ~((uint32_t)0x80000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)diag3 << 24) & ~((uint32_t)0x3F000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)diag2en << 23) & ~((uint32_t)0x00800000)) == 0); + BLE_ASSERT_ERR((((uint32_t)diag2 << 16) & ~((uint32_t)0x003F0000)) == 0); + BLE_ASSERT_ERR((((uint32_t)diag1en << 15) & ~((uint32_t)0x00008000)) == 0); + BLE_ASSERT_ERR((((uint32_t)diag1 << 8) & ~((uint32_t)0x00003F00)) == 0); + BLE_ASSERT_ERR((((uint32_t)diag0en << 7) & ~((uint32_t)0x00000080)) == 0); + BLE_ASSERT_ERR((((uint32_t)diag0 << 0) & ~((uint32_t)0x0000003F)) == 0); + REG_IP_WR(IP_DIAGCNTL_ADDR, ((uint32_t)diag3en << 31) | ((uint32_t)diag3 << 24) | ((uint32_t)diag2en << 23) | ((uint32_t)diag2 << 16) | ((uint32_t)diag1en << 15) | ((uint32_t)diag1 << 8) | ((uint32_t)diag0en << 7) | ((uint32_t)diag0 << 0)); +} + +__INLINE void ip_diagcntl_unpack(uint8_t* diag3en, uint8_t* diag3, uint8_t* diag2en, uint8_t* diag2, uint8_t* diag1en, uint8_t* diag1, uint8_t* diag0en, uint8_t* diag0) +{ + uint32_t localVal = REG_IP_RD(IP_DIAGCNTL_ADDR); + + *diag3en = (localVal & ((uint32_t)0x80000000)) >> 31; + *diag3 = (localVal & ((uint32_t)0x3F000000)) >> 24; + *diag2en = (localVal & ((uint32_t)0x00800000)) >> 23; + *diag2 = (localVal & ((uint32_t)0x003F0000)) >> 16; + *diag1en = (localVal & ((uint32_t)0x00008000)) >> 15; + *diag1 = (localVal & ((uint32_t)0x00003F00)) >> 8; + *diag0en = (localVal & ((uint32_t)0x00000080)) >> 7; + *diag0 = (localVal & ((uint32_t)0x0000003F)) >> 0; +} + +__INLINE uint8_t ip_diagcntl_diag3_en_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_DIAGCNTL_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +__INLINE void ip_diagcntl_diag3_en_setf(uint8_t diag3en) +{ + BLE_ASSERT_ERR((((uint32_t)diag3en << 31) & ~((uint32_t)0x80000000)) == 0); + REG_IP_WR(IP_DIAGCNTL_ADDR, (REG_IP_RD(IP_DIAGCNTL_ADDR) & ~((uint32_t)0x80000000)) | ((uint32_t)diag3en << 31)); +} + +__INLINE uint8_t ip_diagcntl_diag3_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_DIAGCNTL_ADDR); + return ((localVal & ((uint32_t)0x3F000000)) >> 24); +} + +__INLINE void ip_diagcntl_diag3_setf(uint8_t diag3) +{ + BLE_ASSERT_ERR((((uint32_t)diag3 << 24) & ~((uint32_t)0x3F000000)) == 0); + REG_IP_WR(IP_DIAGCNTL_ADDR, (REG_IP_RD(IP_DIAGCNTL_ADDR) & ~((uint32_t)0x3F000000)) | ((uint32_t)diag3 << 24)); +} + +__INLINE uint8_t ip_diagcntl_diag2_en_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_DIAGCNTL_ADDR); + return ((localVal & ((uint32_t)0x00800000)) >> 23); +} + +__INLINE void ip_diagcntl_diag2_en_setf(uint8_t diag2en) +{ + BLE_ASSERT_ERR((((uint32_t)diag2en << 23) & ~((uint32_t)0x00800000)) == 0); + REG_IP_WR(IP_DIAGCNTL_ADDR, (REG_IP_RD(IP_DIAGCNTL_ADDR) & ~((uint32_t)0x00800000)) | ((uint32_t)diag2en << 23)); +} + +__INLINE uint8_t ip_diagcntl_diag2_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_DIAGCNTL_ADDR); + return ((localVal & ((uint32_t)0x003F0000)) >> 16); +} + +__INLINE void ip_diagcntl_diag2_setf(uint8_t diag2) +{ + BLE_ASSERT_ERR((((uint32_t)diag2 << 16) & ~((uint32_t)0x003F0000)) == 0); + REG_IP_WR(IP_DIAGCNTL_ADDR, (REG_IP_RD(IP_DIAGCNTL_ADDR) & ~((uint32_t)0x003F0000)) | ((uint32_t)diag2 << 16)); +} + +__INLINE uint8_t ip_diagcntl_diag1_en_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_DIAGCNTL_ADDR); + return ((localVal & ((uint32_t)0x00008000)) >> 15); +} + +__INLINE void ip_diagcntl_diag1_en_setf(uint8_t diag1en) +{ + BLE_ASSERT_ERR((((uint32_t)diag1en << 15) & ~((uint32_t)0x00008000)) == 0); + REG_IP_WR(IP_DIAGCNTL_ADDR, (REG_IP_RD(IP_DIAGCNTL_ADDR) & ~((uint32_t)0x00008000)) | ((uint32_t)diag1en << 15)); +} + +__INLINE uint8_t ip_diagcntl_diag1_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_DIAGCNTL_ADDR); + return ((localVal & ((uint32_t)0x00003F00)) >> 8); +} + +__INLINE void ip_diagcntl_diag1_setf(uint8_t diag1) +{ + BLE_ASSERT_ERR((((uint32_t)diag1 << 8) & ~((uint32_t)0x00003F00)) == 0); + REG_IP_WR(IP_DIAGCNTL_ADDR, (REG_IP_RD(IP_DIAGCNTL_ADDR) & ~((uint32_t)0x00003F00)) | ((uint32_t)diag1 << 8)); +} + +__INLINE uint8_t ip_diagcntl_diag0_en_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_DIAGCNTL_ADDR); + return ((localVal & ((uint32_t)0x00000080)) >> 7); +} + +__INLINE void ip_diagcntl_diag0_en_setf(uint8_t diag0en) +{ + BLE_ASSERT_ERR((((uint32_t)diag0en << 7) & ~((uint32_t)0x00000080)) == 0); + REG_IP_WR(IP_DIAGCNTL_ADDR, (REG_IP_RD(IP_DIAGCNTL_ADDR) & ~((uint32_t)0x00000080)) | ((uint32_t)diag0en << 7)); +} + +__INLINE uint8_t ip_diagcntl_diag0_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_DIAGCNTL_ADDR); + return ((localVal & ((uint32_t)0x0000003F)) >> 0); +} + +__INLINE void ip_diagcntl_diag0_setf(uint8_t diag0) +{ + BLE_ASSERT_ERR((((uint32_t)diag0 << 0) & ~((uint32_t)0x0000003F)) == 0); + REG_IP_WR(IP_DIAGCNTL_ADDR, (REG_IP_RD(IP_DIAGCNTL_ADDR) & ~((uint32_t)0x0000003F)) | ((uint32_t)diag0 << 0)); +} + +/** + * @brief DIAGSTAT register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:24            DIAG3STAT   0x0
+ *  23:16            DIAG2STAT   0x0
+ *  15:08            DIAG1STAT   0x0
+ *  07:00            DIAG0STAT   0x0
+ * 
+ */ +#define IP_DIAGSTAT_ADDR 0x00900054 +#define IP_DIAGSTAT_OFFSET 0x00000054 +#define IP_DIAGSTAT_INDEX 0x00000015 +#define IP_DIAGSTAT_RESET 0x00000000 + +__INLINE uint32_t ip_diagstat_get(void) +{ + return REG_IP_RD(IP_DIAGSTAT_ADDR); +} + +// field definitions +#define IP_DIAG3STAT_MASK ((uint32_t)0xFF000000) +#define IP_DIAG3STAT_LSB 24 +#define IP_DIAG3STAT_WIDTH ((uint32_t)0x00000008) +#define IP_DIAG2STAT_MASK ((uint32_t)0x00FF0000) +#define IP_DIAG2STAT_LSB 16 +#define IP_DIAG2STAT_WIDTH ((uint32_t)0x00000008) +#define IP_DIAG1STAT_MASK ((uint32_t)0x0000FF00) +#define IP_DIAG1STAT_LSB 8 +#define IP_DIAG1STAT_WIDTH ((uint32_t)0x00000008) +#define IP_DIAG0STAT_MASK ((uint32_t)0x000000FF) +#define IP_DIAG0STAT_LSB 0 +#define IP_DIAG0STAT_WIDTH ((uint32_t)0x00000008) + +#define IP_DIAG3STAT_RST 0x0 +#define IP_DIAG2STAT_RST 0x0 +#define IP_DIAG1STAT_RST 0x0 +#define IP_DIAG0STAT_RST 0x0 + +__INLINE void ip_diagstat_unpack(uint8_t* diag3stat, uint8_t* diag2stat, uint8_t* diag1stat, uint8_t* diag0stat) +{ + uint32_t localVal = REG_IP_RD(IP_DIAGSTAT_ADDR); + + *diag3stat = (localVal & ((uint32_t)0xFF000000)) >> 24; + *diag2stat = (localVal & ((uint32_t)0x00FF0000)) >> 16; + *diag1stat = (localVal & ((uint32_t)0x0000FF00)) >> 8; + *diag0stat = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +__INLINE uint8_t ip_diagstat_diag3stat_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_DIAGSTAT_ADDR); + return ((localVal & ((uint32_t)0xFF000000)) >> 24); +} + +__INLINE uint8_t ip_diagstat_diag2stat_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_DIAGSTAT_ADDR); + return ((localVal & ((uint32_t)0x00FF0000)) >> 16); +} + +__INLINE uint8_t ip_diagstat_diag1stat_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_DIAGSTAT_ADDR); + return ((localVal & ((uint32_t)0x0000FF00)) >> 8); +} + +__INLINE uint8_t ip_diagstat_diag0stat_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_DIAGSTAT_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +/** + * @brief DEBUGADDMAX register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:16           REG_ADDMAX   0x0
+ *  15:00            EM_ADDMAX   0x0
+ * 
+ */ +#define IP_DEBUGADDMAX_ADDR 0x00900058 +#define IP_DEBUGADDMAX_OFFSET 0x00000058 +#define IP_DEBUGADDMAX_INDEX 0x00000016 +#define IP_DEBUGADDMAX_RESET 0x00000000 + +__INLINE uint32_t ip_debugaddmax_get(void) +{ + return REG_IP_RD(IP_DEBUGADDMAX_ADDR); +} + +__INLINE void ip_debugaddmax_set(uint32_t value) +{ + REG_IP_WR(IP_DEBUGADDMAX_ADDR, value); +} + +// field definitions +#define IP_REG_ADDMAX_MASK ((uint32_t)0xFFFF0000) +#define IP_REG_ADDMAX_LSB 16 +#define IP_REG_ADDMAX_WIDTH ((uint32_t)0x00000010) +#define IP_EM_ADDMAX_MASK ((uint32_t)0x0000FFFF) +#define IP_EM_ADDMAX_LSB 0 +#define IP_EM_ADDMAX_WIDTH ((uint32_t)0x00000010) + +#define IP_REG_ADDMAX_RST 0x0 +#define IP_EM_ADDMAX_RST 0x0 + +__INLINE void ip_debugaddmax_pack(uint16_t regaddmax, uint16_t emaddmax) +{ + BLE_ASSERT_ERR((((uint32_t)regaddmax << 16) & ~((uint32_t)0xFFFF0000)) == 0); + BLE_ASSERT_ERR((((uint32_t)emaddmax << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_IP_WR(IP_DEBUGADDMAX_ADDR, ((uint32_t)regaddmax << 16) | ((uint32_t)emaddmax << 0)); +} + +__INLINE void ip_debugaddmax_unpack(uint16_t* regaddmax, uint16_t* emaddmax) +{ + uint32_t localVal = REG_IP_RD(IP_DEBUGADDMAX_ADDR); + + *regaddmax = (localVal & ((uint32_t)0xFFFF0000)) >> 16; + *emaddmax = (localVal & ((uint32_t)0x0000FFFF)) >> 0; +} + +__INLINE uint16_t ip_debugaddmax_reg_addmax_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_DEBUGADDMAX_ADDR); + return ((localVal & ((uint32_t)0xFFFF0000)) >> 16); +} + +__INLINE void ip_debugaddmax_reg_addmax_setf(uint16_t regaddmax) +{ + BLE_ASSERT_ERR((((uint32_t)regaddmax << 16) & ~((uint32_t)0xFFFF0000)) == 0); + REG_IP_WR(IP_DEBUGADDMAX_ADDR, (REG_IP_RD(IP_DEBUGADDMAX_ADDR) & ~((uint32_t)0xFFFF0000)) | ((uint32_t)regaddmax << 16)); +} + +__INLINE uint16_t ip_debugaddmax_em_addmax_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_DEBUGADDMAX_ADDR); + return ((localVal & ((uint32_t)0x0000FFFF)) >> 0); +} + +__INLINE void ip_debugaddmax_em_addmax_setf(uint16_t emaddmax) +{ + BLE_ASSERT_ERR((((uint32_t)emaddmax << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_IP_WR(IP_DEBUGADDMAX_ADDR, (REG_IP_RD(IP_DEBUGADDMAX_ADDR) & ~((uint32_t)0x0000FFFF)) | ((uint32_t)emaddmax << 0)); +} + +/** + * @brief DEBUGADDMIN register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:16           REG_ADDMIN   0x0
+ *  15:00            EM_ADDMIN   0x0
+ * 
+ */ +#define IP_DEBUGADDMIN_ADDR 0x0090005C +#define IP_DEBUGADDMIN_OFFSET 0x0000005C +#define IP_DEBUGADDMIN_INDEX 0x00000017 +#define IP_DEBUGADDMIN_RESET 0x00000000 + +__INLINE uint32_t ip_debugaddmin_get(void) +{ + return REG_IP_RD(IP_DEBUGADDMIN_ADDR); +} + +__INLINE void ip_debugaddmin_set(uint32_t value) +{ + REG_IP_WR(IP_DEBUGADDMIN_ADDR, value); +} + +// field definitions +#define IP_REG_ADDMIN_MASK ((uint32_t)0xFFFF0000) +#define IP_REG_ADDMIN_LSB 16 +#define IP_REG_ADDMIN_WIDTH ((uint32_t)0x00000010) +#define IP_EM_ADDMIN_MASK ((uint32_t)0x0000FFFF) +#define IP_EM_ADDMIN_LSB 0 +#define IP_EM_ADDMIN_WIDTH ((uint32_t)0x00000010) + +#define IP_REG_ADDMIN_RST 0x0 +#define IP_EM_ADDMIN_RST 0x0 + +__INLINE void ip_debugaddmin_pack(uint16_t regaddmin, uint16_t emaddmin) +{ + BLE_ASSERT_ERR((((uint32_t)regaddmin << 16) & ~((uint32_t)0xFFFF0000)) == 0); + BLE_ASSERT_ERR((((uint32_t)emaddmin << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_IP_WR(IP_DEBUGADDMIN_ADDR, ((uint32_t)regaddmin << 16) | ((uint32_t)emaddmin << 0)); +} + +__INLINE void ip_debugaddmin_unpack(uint16_t* regaddmin, uint16_t* emaddmin) +{ + uint32_t localVal = REG_IP_RD(IP_DEBUGADDMIN_ADDR); + + *regaddmin = (localVal & ((uint32_t)0xFFFF0000)) >> 16; + *emaddmin = (localVal & ((uint32_t)0x0000FFFF)) >> 0; +} + +__INLINE uint16_t ip_debugaddmin_reg_addmin_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_DEBUGADDMIN_ADDR); + return ((localVal & ((uint32_t)0xFFFF0000)) >> 16); +} + +__INLINE void ip_debugaddmin_reg_addmin_setf(uint16_t regaddmin) +{ + BLE_ASSERT_ERR((((uint32_t)regaddmin << 16) & ~((uint32_t)0xFFFF0000)) == 0); + REG_IP_WR(IP_DEBUGADDMIN_ADDR, (REG_IP_RD(IP_DEBUGADDMIN_ADDR) & ~((uint32_t)0xFFFF0000)) | ((uint32_t)regaddmin << 16)); +} + +__INLINE uint16_t ip_debugaddmin_em_addmin_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_DEBUGADDMIN_ADDR); + return ((localVal & ((uint32_t)0x0000FFFF)) >> 0); +} + +__INLINE void ip_debugaddmin_em_addmin_setf(uint16_t emaddmin) +{ + BLE_ASSERT_ERR((((uint32_t)emaddmin << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_IP_WR(IP_DEBUGADDMIN_ADDR, (REG_IP_RD(IP_DEBUGADDMIN_ADDR) & ~((uint32_t)0x0000FFFF)) | ((uint32_t)emaddmin << 0)); +} + +/** + * @brief ERRORTYPESTAT register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     03   ACT_SCHDL_APFM_ERROR   0
+ *     02   ACT_SCHDL_ENTRY_ERROR   0
+ *     01         FIFOWRITEERR   0
+ *     00    RADIO_EMACC_ERROR   0
+ * 
+ */ +#define IP_ERRORTYPESTAT_ADDR 0x00900060 +#define IP_ERRORTYPESTAT_OFFSET 0x00000060 +#define IP_ERRORTYPESTAT_INDEX 0x00000018 +#define IP_ERRORTYPESTAT_RESET 0x00000000 + +__INLINE uint32_t ip_errortypestat_get(void) +{ + return REG_IP_RD(IP_ERRORTYPESTAT_ADDR); +} + +// field definitions +#define IP_ACT_SCHDL_APFM_ERROR_BIT ((uint32_t)0x00000008) +#define IP_ACT_SCHDL_APFM_ERROR_POS 3 +#define IP_ACT_SCHDL_ENTRY_ERROR_BIT ((uint32_t)0x00000004) +#define IP_ACT_SCHDL_ENTRY_ERROR_POS 2 +#define IP_FIFOWRITEERR_BIT ((uint32_t)0x00000002) +#define IP_FIFOWRITEERR_POS 1 +#define IP_RADIO_EMACC_ERROR_BIT ((uint32_t)0x00000001) +#define IP_RADIO_EMACC_ERROR_POS 0 + +#define IP_ACT_SCHDL_APFM_ERROR_RST 0x0 +#define IP_ACT_SCHDL_ENTRY_ERROR_RST 0x0 +#define IP_FIFOWRITEERR_RST 0x0 +#define IP_RADIO_EMACC_ERROR_RST 0x0 + +__INLINE void ip_errortypestat_unpack(uint8_t* actschdlapfmerror, uint8_t* actschdlentryerror, uint8_t* fifowriteerr, uint8_t* radioemaccerror) +{ + uint32_t localVal = REG_IP_RD(IP_ERRORTYPESTAT_ADDR); + + *actschdlapfmerror = (localVal & ((uint32_t)0x00000008)) >> 3; + *actschdlentryerror = (localVal & ((uint32_t)0x00000004)) >> 2; + *fifowriteerr = (localVal & ((uint32_t)0x00000002)) >> 1; + *radioemaccerror = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +__INLINE uint8_t ip_errortypestat_act_schdl_apfm_error_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_ERRORTYPESTAT_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +__INLINE uint8_t ip_errortypestat_act_schdl_entry_error_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_ERRORTYPESTAT_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +__INLINE uint8_t ip_errortypestat_fifowriteerr_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_ERRORTYPESTAT_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +__INLINE uint8_t ip_errortypestat_radio_emacc_error_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_ERRORTYPESTAT_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/** + * @brief SWPROFILING register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31             SWPROF31   0
+ *     30             SWPROF30   0
+ *     29             SWPROF29   0
+ *     28             SWPROF28   0
+ *     27             SWPROF27   0
+ *     26             SWPROF26   0
+ *     25             SWPROF25   0
+ *     24             SWPROF24   0
+ *     23             SWPROF23   0
+ *     22             SWPROF22   0
+ *     21             SWPROF21   0
+ *     20             SWPROF20   0
+ *     19             SWPROF19   0
+ *     18             SWPROF18   0
+ *     17             SWPROF17   0
+ *     16             SWPROF16   0
+ *     15             SWPROF15   0
+ *     14             SWPROF14   0
+ *     13             SWPROF13   0
+ *     12             SWPROF12   0
+ *     11             SWPROF11   0
+ *     10             SWPROF10   0
+ *     09              SWPROF9   0
+ *     08              SWPROF8   0
+ *     07              SWPROF7   0
+ *     06              SWPROF6   0
+ *     05              SWPROF5   0
+ *     04              SWPROF4   0
+ *     03              SWPROF3   0
+ *     02              SWPROF2   0
+ *     01              SWPROF1   0
+ *     00              SWPROF0   0
+ * 
+ */ +#define IP_SWPROFILING_ADDR 0x00900064 +#define IP_SWPROFILING_OFFSET 0x00000064 +#define IP_SWPROFILING_INDEX 0x00000019 +#define IP_SWPROFILING_RESET 0x00000000 + +__INLINE uint32_t ip_swprofiling_get(void) +{ + return REG_IP_RD(IP_SWPROFILING_ADDR); +} + +__INLINE void ip_swprofiling_set(uint32_t value) +{ + REG_IP_WR(IP_SWPROFILING_ADDR, value); +} + +// field definitions +#define IP_SWPROF31_BIT ((uint32_t)0x80000000) +#define IP_SWPROF31_POS 31 +#define IP_SWPROF30_BIT ((uint32_t)0x40000000) +#define IP_SWPROF30_POS 30 +#define IP_SWPROF29_BIT ((uint32_t)0x20000000) +#define IP_SWPROF29_POS 29 +#define IP_SWPROF28_BIT ((uint32_t)0x10000000) +#define IP_SWPROF28_POS 28 +#define IP_SWPROF27_BIT ((uint32_t)0x08000000) +#define IP_SWPROF27_POS 27 +#define IP_SWPROF26_BIT ((uint32_t)0x04000000) +#define IP_SWPROF26_POS 26 +#define IP_SWPROF25_BIT ((uint32_t)0x02000000) +#define IP_SWPROF25_POS 25 +#define IP_SWPROF24_BIT ((uint32_t)0x01000000) +#define IP_SWPROF24_POS 24 +#define IP_SWPROF23_BIT ((uint32_t)0x00800000) +#define IP_SWPROF23_POS 23 +#define IP_SWPROF22_BIT ((uint32_t)0x00400000) +#define IP_SWPROF22_POS 22 +#define IP_SWPROF21_BIT ((uint32_t)0x00200000) +#define IP_SWPROF21_POS 21 +#define IP_SWPROF20_BIT ((uint32_t)0x00100000) +#define IP_SWPROF20_POS 20 +#define IP_SWPROF19_BIT ((uint32_t)0x00080000) +#define IP_SWPROF19_POS 19 +#define IP_SWPROF18_BIT ((uint32_t)0x00040000) +#define IP_SWPROF18_POS 18 +#define IP_SWPROF17_BIT ((uint32_t)0x00020000) +#define IP_SWPROF17_POS 17 +#define IP_SWPROF16_BIT ((uint32_t)0x00010000) +#define IP_SWPROF16_POS 16 +#define IP_SWPROF15_BIT ((uint32_t)0x00008000) +#define IP_SWPROF15_POS 15 +#define IP_SWPROF14_BIT ((uint32_t)0x00004000) +#define IP_SWPROF14_POS 14 +#define IP_SWPROF13_BIT ((uint32_t)0x00002000) +#define IP_SWPROF13_POS 13 +#define IP_SWPROF12_BIT ((uint32_t)0x00001000) +#define IP_SWPROF12_POS 12 +#define IP_SWPROF11_BIT ((uint32_t)0x00000800) +#define IP_SWPROF11_POS 11 +#define IP_SWPROF10_BIT ((uint32_t)0x00000400) +#define IP_SWPROF10_POS 10 +#define IP_SWPROF9_BIT ((uint32_t)0x00000200) +#define IP_SWPROF9_POS 9 +#define IP_SWPROF8_BIT ((uint32_t)0x00000100) +#define IP_SWPROF8_POS 8 +#define IP_SWPROF7_BIT ((uint32_t)0x00000080) +#define IP_SWPROF7_POS 7 +#define IP_SWPROF6_BIT ((uint32_t)0x00000040) +#define IP_SWPROF6_POS 6 +#define IP_SWPROF5_BIT ((uint32_t)0x00000020) +#define IP_SWPROF5_POS 5 +#define IP_SWPROF4_BIT ((uint32_t)0x00000010) +#define IP_SWPROF4_POS 4 +#define IP_SWPROF3_BIT ((uint32_t)0x00000008) +#define IP_SWPROF3_POS 3 +#define IP_SWPROF2_BIT ((uint32_t)0x00000004) +#define IP_SWPROF2_POS 2 +#define IP_SWPROF1_BIT ((uint32_t)0x00000002) +#define IP_SWPROF1_POS 1 +#define IP_SWPROF0_BIT ((uint32_t)0x00000001) +#define IP_SWPROF0_POS 0 + +#define IP_SWPROF31_RST 0x0 +#define IP_SWPROF30_RST 0x0 +#define IP_SWPROF29_RST 0x0 +#define IP_SWPROF28_RST 0x0 +#define IP_SWPROF27_RST 0x0 +#define IP_SWPROF26_RST 0x0 +#define IP_SWPROF25_RST 0x0 +#define IP_SWPROF24_RST 0x0 +#define IP_SWPROF23_RST 0x0 +#define IP_SWPROF22_RST 0x0 +#define IP_SWPROF21_RST 0x0 +#define IP_SWPROF20_RST 0x0 +#define IP_SWPROF19_RST 0x0 +#define IP_SWPROF18_RST 0x0 +#define IP_SWPROF17_RST 0x0 +#define IP_SWPROF16_RST 0x0 +#define IP_SWPROF15_RST 0x0 +#define IP_SWPROF14_RST 0x0 +#define IP_SWPROF13_RST 0x0 +#define IP_SWPROF12_RST 0x0 +#define IP_SWPROF11_RST 0x0 +#define IP_SWPROF10_RST 0x0 +#define IP_SWPROF9_RST 0x0 +#define IP_SWPROF8_RST 0x0 +#define IP_SWPROF7_RST 0x0 +#define IP_SWPROF6_RST 0x0 +#define IP_SWPROF5_RST 0x0 +#define IP_SWPROF4_RST 0x0 +#define IP_SWPROF3_RST 0x0 +#define IP_SWPROF2_RST 0x0 +#define IP_SWPROF1_RST 0x0 +#define IP_SWPROF0_RST 0x0 + +__INLINE void ip_swprofiling_pack(uint8_t swprof31, uint8_t swprof30, uint8_t swprof29, uint8_t swprof28, uint8_t swprof27, uint8_t swprof26, uint8_t swprof25, uint8_t swprof24, uint8_t swprof23, uint8_t swprof22, uint8_t swprof21, uint8_t swprof20, uint8_t swprof19, uint8_t swprof18, uint8_t swprof17, uint8_t swprof16, uint8_t swprof15, uint8_t swprof14, uint8_t swprof13, uint8_t swprof12, uint8_t swprof11, uint8_t swprof10, uint8_t swprof9, uint8_t swprof8, uint8_t swprof7, uint8_t swprof6, uint8_t swprof5, uint8_t swprof4, uint8_t swprof3, uint8_t swprof2, uint8_t swprof1, uint8_t swprof0) +{ + BLE_ASSERT_ERR((((uint32_t)swprof31 << 31) & ~((uint32_t)0x80000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof30 << 30) & ~((uint32_t)0x40000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof29 << 29) & ~((uint32_t)0x20000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof28 << 28) & ~((uint32_t)0x10000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof27 << 27) & ~((uint32_t)0x08000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof26 << 26) & ~((uint32_t)0x04000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof25 << 25) & ~((uint32_t)0x02000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof24 << 24) & ~((uint32_t)0x01000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof23 << 23) & ~((uint32_t)0x00800000)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof22 << 22) & ~((uint32_t)0x00400000)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof21 << 21) & ~((uint32_t)0x00200000)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof20 << 20) & ~((uint32_t)0x00100000)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof19 << 19) & ~((uint32_t)0x00080000)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof18 << 18) & ~((uint32_t)0x00040000)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof17 << 17) & ~((uint32_t)0x00020000)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof16 << 16) & ~((uint32_t)0x00010000)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof15 << 15) & ~((uint32_t)0x00008000)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof14 << 14) & ~((uint32_t)0x00004000)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof13 << 13) & ~((uint32_t)0x00002000)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof12 << 12) & ~((uint32_t)0x00001000)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof11 << 11) & ~((uint32_t)0x00000800)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof10 << 10) & ~((uint32_t)0x00000400)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof9 << 9) & ~((uint32_t)0x00000200)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof8 << 8) & ~((uint32_t)0x00000100)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof7 << 7) & ~((uint32_t)0x00000080)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof6 << 6) & ~((uint32_t)0x00000040)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof5 << 5) & ~((uint32_t)0x00000020)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof4 << 4) & ~((uint32_t)0x00000010)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof3 << 3) & ~((uint32_t)0x00000008)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof2 << 2) & ~((uint32_t)0x00000004)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof1 << 1) & ~((uint32_t)0x00000002)) == 0); + BLE_ASSERT_ERR((((uint32_t)swprof0 << 0) & ~((uint32_t)0x00000001)) == 0); + REG_IP_WR(IP_SWPROFILING_ADDR, ((uint32_t)swprof31 << 31) | ((uint32_t)swprof30 << 30) | ((uint32_t)swprof29 << 29) | ((uint32_t)swprof28 << 28) | ((uint32_t)swprof27 << 27) | ((uint32_t)swprof26 << 26) | ((uint32_t)swprof25 << 25) | ((uint32_t)swprof24 << 24) | ((uint32_t)swprof23 << 23) | ((uint32_t)swprof22 << 22) | ((uint32_t)swprof21 << 21) | ((uint32_t)swprof20 << 20) | ((uint32_t)swprof19 << 19) | ((uint32_t)swprof18 << 18) | ((uint32_t)swprof17 << 17) | ((uint32_t)swprof16 << 16) | ((uint32_t)swprof15 << 15) | ((uint32_t)swprof14 << 14) | ((uint32_t)swprof13 << 13) | ((uint32_t)swprof12 << 12) | ((uint32_t)swprof11 << 11) | ((uint32_t)swprof10 << 10) | ((uint32_t)swprof9 << 9) | ((uint32_t)swprof8 << 8) | ((uint32_t)swprof7 << 7) | ((uint32_t)swprof6 << 6) | ((uint32_t)swprof5 << 5) | ((uint32_t)swprof4 << 4) | ((uint32_t)swprof3 << 3) | ((uint32_t)swprof2 << 2) | ((uint32_t)swprof1 << 1) | ((uint32_t)swprof0 << 0)); +} + +__INLINE void ip_swprofiling_unpack(uint8_t* swprof31, uint8_t* swprof30, uint8_t* swprof29, uint8_t* swprof28, uint8_t* swprof27, uint8_t* swprof26, uint8_t* swprof25, uint8_t* swprof24, uint8_t* swprof23, uint8_t* swprof22, uint8_t* swprof21, uint8_t* swprof20, uint8_t* swprof19, uint8_t* swprof18, uint8_t* swprof17, uint8_t* swprof16, uint8_t* swprof15, uint8_t* swprof14, uint8_t* swprof13, uint8_t* swprof12, uint8_t* swprof11, uint8_t* swprof10, uint8_t* swprof9, uint8_t* swprof8, uint8_t* swprof7, uint8_t* swprof6, uint8_t* swprof5, uint8_t* swprof4, uint8_t* swprof3, uint8_t* swprof2, uint8_t* swprof1, uint8_t* swprof0) +{ + uint32_t localVal = REG_IP_RD(IP_SWPROFILING_ADDR); + + *swprof31 = (localVal & ((uint32_t)0x80000000)) >> 31; + *swprof30 = (localVal & ((uint32_t)0x40000000)) >> 30; + *swprof29 = (localVal & ((uint32_t)0x20000000)) >> 29; + *swprof28 = (localVal & ((uint32_t)0x10000000)) >> 28; + *swprof27 = (localVal & ((uint32_t)0x08000000)) >> 27; + *swprof26 = (localVal & ((uint32_t)0x04000000)) >> 26; + *swprof25 = (localVal & ((uint32_t)0x02000000)) >> 25; + *swprof24 = (localVal & ((uint32_t)0x01000000)) >> 24; + *swprof23 = (localVal & ((uint32_t)0x00800000)) >> 23; + *swprof22 = (localVal & ((uint32_t)0x00400000)) >> 22; + *swprof21 = (localVal & ((uint32_t)0x00200000)) >> 21; + *swprof20 = (localVal & ((uint32_t)0x00100000)) >> 20; + *swprof19 = (localVal & ((uint32_t)0x00080000)) >> 19; + *swprof18 = (localVal & ((uint32_t)0x00040000)) >> 18; + *swprof17 = (localVal & ((uint32_t)0x00020000)) >> 17; + *swprof16 = (localVal & ((uint32_t)0x00010000)) >> 16; + *swprof15 = (localVal & ((uint32_t)0x00008000)) >> 15; + *swprof14 = (localVal & ((uint32_t)0x00004000)) >> 14; + *swprof13 = (localVal & ((uint32_t)0x00002000)) >> 13; + *swprof12 = (localVal & ((uint32_t)0x00001000)) >> 12; + *swprof11 = (localVal & ((uint32_t)0x00000800)) >> 11; + *swprof10 = (localVal & ((uint32_t)0x00000400)) >> 10; + *swprof9 = (localVal & ((uint32_t)0x00000200)) >> 9; + *swprof8 = (localVal & ((uint32_t)0x00000100)) >> 8; + *swprof7 = (localVal & ((uint32_t)0x00000080)) >> 7; + *swprof6 = (localVal & ((uint32_t)0x00000040)) >> 6; + *swprof5 = (localVal & ((uint32_t)0x00000020)) >> 5; + *swprof4 = (localVal & ((uint32_t)0x00000010)) >> 4; + *swprof3 = (localVal & ((uint32_t)0x00000008)) >> 3; + *swprof2 = (localVal & ((uint32_t)0x00000004)) >> 2; + *swprof1 = (localVal & ((uint32_t)0x00000002)) >> 1; + *swprof0 = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +__INLINE uint8_t ip_swprofiling_swprof31_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +__INLINE void ip_swprofiling_swprof31_setf(uint8_t swprof31) +{ + BLE_ASSERT_ERR((((uint32_t)swprof31 << 31) & ~((uint32_t)0x80000000)) == 0); + REG_IP_WR(IP_SWPROFILING_ADDR, (REG_IP_RD(IP_SWPROFILING_ADDR) & ~((uint32_t)0x80000000)) | ((uint32_t)swprof31 << 31)); +} + +__INLINE uint8_t ip_swprofiling_swprof30_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x40000000)) >> 30); +} + +__INLINE void ip_swprofiling_swprof30_setf(uint8_t swprof30) +{ + BLE_ASSERT_ERR((((uint32_t)swprof30 << 30) & ~((uint32_t)0x40000000)) == 0); + REG_IP_WR(IP_SWPROFILING_ADDR, (REG_IP_RD(IP_SWPROFILING_ADDR) & ~((uint32_t)0x40000000)) | ((uint32_t)swprof30 << 30)); +} + +__INLINE uint8_t ip_swprofiling_swprof29_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x20000000)) >> 29); +} + +__INLINE void ip_swprofiling_swprof29_setf(uint8_t swprof29) +{ + BLE_ASSERT_ERR((((uint32_t)swprof29 << 29) & ~((uint32_t)0x20000000)) == 0); + REG_IP_WR(IP_SWPROFILING_ADDR, (REG_IP_RD(IP_SWPROFILING_ADDR) & ~((uint32_t)0x20000000)) | ((uint32_t)swprof29 << 29)); +} + +__INLINE uint8_t ip_swprofiling_swprof28_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x10000000)) >> 28); +} + +__INLINE void ip_swprofiling_swprof28_setf(uint8_t swprof28) +{ + BLE_ASSERT_ERR((((uint32_t)swprof28 << 28) & ~((uint32_t)0x10000000)) == 0); + REG_IP_WR(IP_SWPROFILING_ADDR, (REG_IP_RD(IP_SWPROFILING_ADDR) & ~((uint32_t)0x10000000)) | ((uint32_t)swprof28 << 28)); +} + +__INLINE uint8_t ip_swprofiling_swprof27_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x08000000)) >> 27); +} + +__INLINE void ip_swprofiling_swprof27_setf(uint8_t swprof27) +{ + BLE_ASSERT_ERR((((uint32_t)swprof27 << 27) & ~((uint32_t)0x08000000)) == 0); + REG_IP_WR(IP_SWPROFILING_ADDR, (REG_IP_RD(IP_SWPROFILING_ADDR) & ~((uint32_t)0x08000000)) | ((uint32_t)swprof27 << 27)); +} + +__INLINE uint8_t ip_swprofiling_swprof26_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x04000000)) >> 26); +} + +__INLINE void ip_swprofiling_swprof26_setf(uint8_t swprof26) +{ + BLE_ASSERT_ERR((((uint32_t)swprof26 << 26) & ~((uint32_t)0x04000000)) == 0); + REG_IP_WR(IP_SWPROFILING_ADDR, (REG_IP_RD(IP_SWPROFILING_ADDR) & ~((uint32_t)0x04000000)) | ((uint32_t)swprof26 << 26)); +} + +__INLINE uint8_t ip_swprofiling_swprof25_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x02000000)) >> 25); +} + +__INLINE void ip_swprofiling_swprof25_setf(uint8_t swprof25) +{ + BLE_ASSERT_ERR((((uint32_t)swprof25 << 25) & ~((uint32_t)0x02000000)) == 0); + REG_IP_WR(IP_SWPROFILING_ADDR, (REG_IP_RD(IP_SWPROFILING_ADDR) & ~((uint32_t)0x02000000)) | ((uint32_t)swprof25 << 25)); +} + +__INLINE uint8_t ip_swprofiling_swprof24_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x01000000)) >> 24); +} + +__INLINE void ip_swprofiling_swprof24_setf(uint8_t swprof24) +{ + BLE_ASSERT_ERR((((uint32_t)swprof24 << 24) & ~((uint32_t)0x01000000)) == 0); + REG_IP_WR(IP_SWPROFILING_ADDR, (REG_IP_RD(IP_SWPROFILING_ADDR) & ~((uint32_t)0x01000000)) | ((uint32_t)swprof24 << 24)); +} + +__INLINE uint8_t ip_swprofiling_swprof23_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00800000)) >> 23); +} + +__INLINE void ip_swprofiling_swprof23_setf(uint8_t swprof23) +{ + BLE_ASSERT_ERR((((uint32_t)swprof23 << 23) & ~((uint32_t)0x00800000)) == 0); + REG_IP_WR(IP_SWPROFILING_ADDR, (REG_IP_RD(IP_SWPROFILING_ADDR) & ~((uint32_t)0x00800000)) | ((uint32_t)swprof23 << 23)); +} + +__INLINE uint8_t ip_swprofiling_swprof22_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00400000)) >> 22); +} + +__INLINE void ip_swprofiling_swprof22_setf(uint8_t swprof22) +{ + BLE_ASSERT_ERR((((uint32_t)swprof22 << 22) & ~((uint32_t)0x00400000)) == 0); + REG_IP_WR(IP_SWPROFILING_ADDR, (REG_IP_RD(IP_SWPROFILING_ADDR) & ~((uint32_t)0x00400000)) | ((uint32_t)swprof22 << 22)); +} + +__INLINE uint8_t ip_swprofiling_swprof21_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00200000)) >> 21); +} + +__INLINE void ip_swprofiling_swprof21_setf(uint8_t swprof21) +{ + BLE_ASSERT_ERR((((uint32_t)swprof21 << 21) & ~((uint32_t)0x00200000)) == 0); + REG_IP_WR(IP_SWPROFILING_ADDR, (REG_IP_RD(IP_SWPROFILING_ADDR) & ~((uint32_t)0x00200000)) | ((uint32_t)swprof21 << 21)); +} + +__INLINE uint8_t ip_swprofiling_swprof20_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00100000)) >> 20); +} + +__INLINE void ip_swprofiling_swprof20_setf(uint8_t swprof20) +{ + BLE_ASSERT_ERR((((uint32_t)swprof20 << 20) & ~((uint32_t)0x00100000)) == 0); + REG_IP_WR(IP_SWPROFILING_ADDR, (REG_IP_RD(IP_SWPROFILING_ADDR) & ~((uint32_t)0x00100000)) | ((uint32_t)swprof20 << 20)); +} + +__INLINE uint8_t ip_swprofiling_swprof19_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00080000)) >> 19); +} + +__INLINE void ip_swprofiling_swprof19_setf(uint8_t swprof19) +{ + BLE_ASSERT_ERR((((uint32_t)swprof19 << 19) & ~((uint32_t)0x00080000)) == 0); + REG_IP_WR(IP_SWPROFILING_ADDR, (REG_IP_RD(IP_SWPROFILING_ADDR) & ~((uint32_t)0x00080000)) | ((uint32_t)swprof19 << 19)); +} + +__INLINE uint8_t ip_swprofiling_swprof18_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00040000)) >> 18); +} + +__INLINE void ip_swprofiling_swprof18_setf(uint8_t swprof18) +{ + BLE_ASSERT_ERR((((uint32_t)swprof18 << 18) & ~((uint32_t)0x00040000)) == 0); + REG_IP_WR(IP_SWPROFILING_ADDR, (REG_IP_RD(IP_SWPROFILING_ADDR) & ~((uint32_t)0x00040000)) | ((uint32_t)swprof18 << 18)); +} + +__INLINE uint8_t ip_swprofiling_swprof17_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00020000)) >> 17); +} + +__INLINE void ip_swprofiling_swprof17_setf(uint8_t swprof17) +{ + BLE_ASSERT_ERR((((uint32_t)swprof17 << 17) & ~((uint32_t)0x00020000)) == 0); + REG_IP_WR(IP_SWPROFILING_ADDR, (REG_IP_RD(IP_SWPROFILING_ADDR) & ~((uint32_t)0x00020000)) | ((uint32_t)swprof17 << 17)); +} + +__INLINE uint8_t ip_swprofiling_swprof16_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00010000)) >> 16); +} + +__INLINE void ip_swprofiling_swprof16_setf(uint8_t swprof16) +{ + BLE_ASSERT_ERR((((uint32_t)swprof16 << 16) & ~((uint32_t)0x00010000)) == 0); + REG_IP_WR(IP_SWPROFILING_ADDR, (REG_IP_RD(IP_SWPROFILING_ADDR) & ~((uint32_t)0x00010000)) | ((uint32_t)swprof16 << 16)); +} + +__INLINE uint8_t ip_swprofiling_swprof15_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00008000)) >> 15); +} + +__INLINE void ip_swprofiling_swprof15_setf(uint8_t swprof15) +{ + BLE_ASSERT_ERR((((uint32_t)swprof15 << 15) & ~((uint32_t)0x00008000)) == 0); + REG_IP_WR(IP_SWPROFILING_ADDR, (REG_IP_RD(IP_SWPROFILING_ADDR) & ~((uint32_t)0x00008000)) | ((uint32_t)swprof15 << 15)); +} + +__INLINE uint8_t ip_swprofiling_swprof14_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00004000)) >> 14); +} + +__INLINE void ip_swprofiling_swprof14_setf(uint8_t swprof14) +{ + BLE_ASSERT_ERR((((uint32_t)swprof14 << 14) & ~((uint32_t)0x00004000)) == 0); + REG_IP_WR(IP_SWPROFILING_ADDR, (REG_IP_RD(IP_SWPROFILING_ADDR) & ~((uint32_t)0x00004000)) | ((uint32_t)swprof14 << 14)); +} + +__INLINE uint8_t ip_swprofiling_swprof13_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00002000)) >> 13); +} + +__INLINE void ip_swprofiling_swprof13_setf(uint8_t swprof13) +{ + BLE_ASSERT_ERR((((uint32_t)swprof13 << 13) & ~((uint32_t)0x00002000)) == 0); + REG_IP_WR(IP_SWPROFILING_ADDR, (REG_IP_RD(IP_SWPROFILING_ADDR) & ~((uint32_t)0x00002000)) | ((uint32_t)swprof13 << 13)); +} + +__INLINE uint8_t ip_swprofiling_swprof12_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00001000)) >> 12); +} + +__INLINE void ip_swprofiling_swprof12_setf(uint8_t swprof12) +{ + BLE_ASSERT_ERR((((uint32_t)swprof12 << 12) & ~((uint32_t)0x00001000)) == 0); + REG_IP_WR(IP_SWPROFILING_ADDR, (REG_IP_RD(IP_SWPROFILING_ADDR) & ~((uint32_t)0x00001000)) | ((uint32_t)swprof12 << 12)); +} + +__INLINE uint8_t ip_swprofiling_swprof11_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000800)) >> 11); +} + +__INLINE void ip_swprofiling_swprof11_setf(uint8_t swprof11) +{ + BLE_ASSERT_ERR((((uint32_t)swprof11 << 11) & ~((uint32_t)0x00000800)) == 0); + REG_IP_WR(IP_SWPROFILING_ADDR, (REG_IP_RD(IP_SWPROFILING_ADDR) & ~((uint32_t)0x00000800)) | ((uint32_t)swprof11 << 11)); +} + +__INLINE uint8_t ip_swprofiling_swprof10_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000400)) >> 10); +} + +__INLINE void ip_swprofiling_swprof10_setf(uint8_t swprof10) +{ + BLE_ASSERT_ERR((((uint32_t)swprof10 << 10) & ~((uint32_t)0x00000400)) == 0); + REG_IP_WR(IP_SWPROFILING_ADDR, (REG_IP_RD(IP_SWPROFILING_ADDR) & ~((uint32_t)0x00000400)) | ((uint32_t)swprof10 << 10)); +} + +__INLINE uint8_t ip_swprofiling_swprof9_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000200)) >> 9); +} + +__INLINE void ip_swprofiling_swprof9_setf(uint8_t swprof9) +{ + BLE_ASSERT_ERR((((uint32_t)swprof9 << 9) & ~((uint32_t)0x00000200)) == 0); + REG_IP_WR(IP_SWPROFILING_ADDR, (REG_IP_RD(IP_SWPROFILING_ADDR) & ~((uint32_t)0x00000200)) | ((uint32_t)swprof9 << 9)); +} + +__INLINE uint8_t ip_swprofiling_swprof8_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000100)) >> 8); +} + +__INLINE void ip_swprofiling_swprof8_setf(uint8_t swprof8) +{ + BLE_ASSERT_ERR((((uint32_t)swprof8 << 8) & ~((uint32_t)0x00000100)) == 0); + REG_IP_WR(IP_SWPROFILING_ADDR, (REG_IP_RD(IP_SWPROFILING_ADDR) & ~((uint32_t)0x00000100)) | ((uint32_t)swprof8 << 8)); +} + +__INLINE uint8_t ip_swprofiling_swprof7_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000080)) >> 7); +} + +__INLINE void ip_swprofiling_swprof7_setf(uint8_t swprof7) +{ + BLE_ASSERT_ERR((((uint32_t)swprof7 << 7) & ~((uint32_t)0x00000080)) == 0); + REG_IP_WR(IP_SWPROFILING_ADDR, (REG_IP_RD(IP_SWPROFILING_ADDR) & ~((uint32_t)0x00000080)) | ((uint32_t)swprof7 << 7)); +} + +__INLINE uint8_t ip_swprofiling_swprof6_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000040)) >> 6); +} + +__INLINE void ip_swprofiling_swprof6_setf(uint8_t swprof6) +{ + BLE_ASSERT_ERR((((uint32_t)swprof6 << 6) & ~((uint32_t)0x00000040)) == 0); + REG_IP_WR(IP_SWPROFILING_ADDR, (REG_IP_RD(IP_SWPROFILING_ADDR) & ~((uint32_t)0x00000040)) | ((uint32_t)swprof6 << 6)); +} + +__INLINE uint8_t ip_swprofiling_swprof5_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +__INLINE void ip_swprofiling_swprof5_setf(uint8_t swprof5) +{ + BLE_ASSERT_ERR((((uint32_t)swprof5 << 5) & ~((uint32_t)0x00000020)) == 0); + REG_IP_WR(IP_SWPROFILING_ADDR, (REG_IP_RD(IP_SWPROFILING_ADDR) & ~((uint32_t)0x00000020)) | ((uint32_t)swprof5 << 5)); +} + +__INLINE uint8_t ip_swprofiling_swprof4_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +__INLINE void ip_swprofiling_swprof4_setf(uint8_t swprof4) +{ + BLE_ASSERT_ERR((((uint32_t)swprof4 << 4) & ~((uint32_t)0x00000010)) == 0); + REG_IP_WR(IP_SWPROFILING_ADDR, (REG_IP_RD(IP_SWPROFILING_ADDR) & ~((uint32_t)0x00000010)) | ((uint32_t)swprof4 << 4)); +} + +__INLINE uint8_t ip_swprofiling_swprof3_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +__INLINE void ip_swprofiling_swprof3_setf(uint8_t swprof3) +{ + BLE_ASSERT_ERR((((uint32_t)swprof3 << 3) & ~((uint32_t)0x00000008)) == 0); + REG_IP_WR(IP_SWPROFILING_ADDR, (REG_IP_RD(IP_SWPROFILING_ADDR) & ~((uint32_t)0x00000008)) | ((uint32_t)swprof3 << 3)); +} + +__INLINE uint8_t ip_swprofiling_swprof2_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +__INLINE void ip_swprofiling_swprof2_setf(uint8_t swprof2) +{ + BLE_ASSERT_ERR((((uint32_t)swprof2 << 2) & ~((uint32_t)0x00000004)) == 0); + REG_IP_WR(IP_SWPROFILING_ADDR, (REG_IP_RD(IP_SWPROFILING_ADDR) & ~((uint32_t)0x00000004)) | ((uint32_t)swprof2 << 2)); +} + +__INLINE uint8_t ip_swprofiling_swprof1_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +__INLINE void ip_swprofiling_swprof1_setf(uint8_t swprof1) +{ + BLE_ASSERT_ERR((((uint32_t)swprof1 << 1) & ~((uint32_t)0x00000002)) == 0); + REG_IP_WR(IP_SWPROFILING_ADDR, (REG_IP_RD(IP_SWPROFILING_ADDR) & ~((uint32_t)0x00000002)) | ((uint32_t)swprof1 << 1)); +} + +__INLINE uint8_t ip_swprofiling_swprof0_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_SWPROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +__INLINE void ip_swprofiling_swprof0_setf(uint8_t swprof0) +{ + BLE_ASSERT_ERR((((uint32_t)swprof0 << 0) & ~((uint32_t)0x00000001)) == 0); + REG_IP_WR(IP_SWPROFILING_ADDR, (REG_IP_RD(IP_SWPROFILING_ADDR) & ~((uint32_t)0x00000001)) | ((uint32_t)swprof0 << 0)); +} + +/** + * @brief RADIOCNTL0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  29:16               SPIPTR   0x0
+ *     07               SPICFG   0
+ *  05:04              SPIFREQ   0x0
+ *     01              SPICOMP   1
+ *     00                SPIGO   0
+ * 
+ */ +#define IP_RADIOCNTL0_ADDR 0x00900070 +#define IP_RADIOCNTL0_OFFSET 0x00000070 +#define IP_RADIOCNTL0_INDEX 0x0000001C +#define IP_RADIOCNTL0_RESET 0x00000002 + +__INLINE uint32_t ip_radiocntl0_get(void) +{ + return REG_IP_RD(IP_RADIOCNTL0_ADDR); +} + +__INLINE void ip_radiocntl0_set(uint32_t value) +{ + REG_IP_WR(IP_RADIOCNTL0_ADDR, value); +} + +// field definitions +#define IP_SPIPTR_MASK ((uint32_t)0x3FFF0000) +#define IP_SPIPTR_LSB 16 +#define IP_SPIPTR_WIDTH ((uint32_t)0x0000000E) +#define IP_SPICFG_BIT ((uint32_t)0x00000080) +#define IP_SPICFG_POS 7 +#define IP_SPIFREQ_MASK ((uint32_t)0x00000030) +#define IP_SPIFREQ_LSB 4 +#define IP_SPIFREQ_WIDTH ((uint32_t)0x00000002) +#define IP_SPICOMP_BIT ((uint32_t)0x00000002) +#define IP_SPICOMP_POS 1 +#define IP_SPIGO_BIT ((uint32_t)0x00000001) +#define IP_SPIGO_POS 0 + +#define IP_SPIPTR_RST 0x0 +#define IP_SPICFG_RST 0x0 +#define IP_SPIFREQ_RST 0x0 +#define IP_SPICOMP_RST 0x1 +#define IP_SPIGO_RST 0x0 + +__INLINE void ip_radiocntl0_pack(uint16_t spiptr, uint8_t spicfg, uint8_t spifreq, uint8_t spigo) +{ + BLE_ASSERT_ERR((((uint32_t)spiptr << 16) & ~((uint32_t)0x3FFF0000)) == 0); + BLE_ASSERT_ERR((((uint32_t)spicfg << 7) & ~((uint32_t)0x00000080)) == 0); + BLE_ASSERT_ERR((((uint32_t)spifreq << 4) & ~((uint32_t)0x00000030)) == 0); + BLE_ASSERT_ERR((((uint32_t)spigo << 0) & ~((uint32_t)0x00000001)) == 0); + REG_IP_WR(IP_RADIOCNTL0_ADDR, ((uint32_t)spiptr << 16) | ((uint32_t)spicfg << 7) | ((uint32_t)spifreq << 4) | ((uint32_t)spigo << 0)); +} + +__INLINE void ip_radiocntl0_unpack(uint16_t* spiptr, uint8_t* spicfg, uint8_t* spifreq, uint8_t* spicomp, uint8_t* spigo) +{ + uint32_t localVal = REG_IP_RD(IP_RADIOCNTL0_ADDR); + + *spiptr = (localVal & ((uint32_t)0x3FFF0000)) >> 16; + *spicfg = (localVal & ((uint32_t)0x00000080)) >> 7; + *spifreq = (localVal & ((uint32_t)0x00000030)) >> 4; + *spicomp = (localVal & ((uint32_t)0x00000002)) >> 1; + *spigo = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +__INLINE uint16_t ip_radiocntl0_spiptr_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_RADIOCNTL0_ADDR); + return ((localVal & ((uint32_t)0x3FFF0000)) >> 16); +} + +__INLINE void ip_radiocntl0_spiptr_setf(uint16_t spiptr) +{ + BLE_ASSERT_ERR((((uint32_t)spiptr << 16) & ~((uint32_t)0x3FFF0000)) == 0); + REG_IP_WR(IP_RADIOCNTL0_ADDR, (REG_IP_RD(IP_RADIOCNTL0_ADDR) & ~((uint32_t)0x3FFF0000)) | ((uint32_t)spiptr << 16)); +} + +__INLINE uint8_t ip_radiocntl0_spicfg_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_RADIOCNTL0_ADDR); + return ((localVal & ((uint32_t)0x00000080)) >> 7); +} + +__INLINE void ip_radiocntl0_spicfg_setf(uint8_t spicfg) +{ + BLE_ASSERT_ERR((((uint32_t)spicfg << 7) & ~((uint32_t)0x00000080)) == 0); + REG_IP_WR(IP_RADIOCNTL0_ADDR, (REG_IP_RD(IP_RADIOCNTL0_ADDR) & ~((uint32_t)0x00000080)) | ((uint32_t)spicfg << 7)); +} + +__INLINE uint8_t ip_radiocntl0_spifreq_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_RADIOCNTL0_ADDR); + return ((localVal & ((uint32_t)0x00000030)) >> 4); +} + +__INLINE void ip_radiocntl0_spifreq_setf(uint8_t spifreq) +{ + BLE_ASSERT_ERR((((uint32_t)spifreq << 4) & ~((uint32_t)0x00000030)) == 0); + REG_IP_WR(IP_RADIOCNTL0_ADDR, (REG_IP_RD(IP_RADIOCNTL0_ADDR) & ~((uint32_t)0x00000030)) | ((uint32_t)spifreq << 4)); +} + +__INLINE uint8_t ip_radiocntl0_spicomp_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_RADIOCNTL0_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +__INLINE uint8_t ip_radiocntl0_spigo_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_RADIOCNTL0_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +__INLINE void ip_radiocntl0_spigo_setf(uint8_t spigo) +{ + BLE_ASSERT_ERR((((uint32_t)spigo << 0) & ~((uint32_t)0x00000001)) == 0); + REG_IP_WR(IP_RADIOCNTL0_ADDR, (REG_IP_RD(IP_RADIOCNTL0_ADDR) & ~((uint32_t)0x00000001)) | ((uint32_t)spigo << 0)); +} + +/** + * @brief RADIOCNTL1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31          FORCEAGC_EN   0
+ *     30              FORCEIQ   0
+ *     29               RXDNSL   0
+ *     28               TXDNSL   0
+ *  27:16      FORCEAGC_LENGTH   0x0
+ *     15      SYNC_PULSE_MODE   0
+ *     14       SYNC_PULSE_SRC   0
+ *     13            DPCORR_EN   0
+ *     12           JEF_SELECT   0
+ *  09:04               XRFSEL   0x0
+ *  03:00           SUBVERSION   0x0
+ * 
+ */ +#define IP_RADIOCNTL1_ADDR 0x00900074 +#define IP_RADIOCNTL1_OFFSET 0x00000074 +#define IP_RADIOCNTL1_INDEX 0x0000001D +#define IP_RADIOCNTL1_RESET 0x00000000 + +__INLINE uint32_t ip_radiocntl1_get(void) +{ + return REG_IP_RD(IP_RADIOCNTL1_ADDR); +} + +__INLINE void ip_radiocntl1_set(uint32_t value) +{ + REG_IP_WR(IP_RADIOCNTL1_ADDR, value); +} + +// field definitions +#define IP_FORCEAGC_EN_BIT ((uint32_t)0x80000000) +#define IP_FORCEAGC_EN_POS 31 +#define IP_FORCEIQ_BIT ((uint32_t)0x40000000) +#define IP_FORCEIQ_POS 30 +#define IP_RXDNSL_BIT ((uint32_t)0x20000000) +#define IP_RXDNSL_POS 29 +#define IP_TXDNSL_BIT ((uint32_t)0x10000000) +#define IP_TXDNSL_POS 28 +#define IP_FORCEAGC_LENGTH_MASK ((uint32_t)0x0FFF0000) +#define IP_FORCEAGC_LENGTH_LSB 16 +#define IP_FORCEAGC_LENGTH_WIDTH ((uint32_t)0x0000000C) +#define IP_SYNC_PULSE_MODE_BIT ((uint32_t)0x00008000) +#define IP_SYNC_PULSE_MODE_POS 15 +#define IP_SYNC_PULSE_SRC_BIT ((uint32_t)0x00004000) +#define IP_SYNC_PULSE_SRC_POS 14 +#define IP_DPCORR_EN_BIT ((uint32_t)0x00002000) +#define IP_DPCORR_EN_POS 13 +#define IP_JEF_SELECT_BIT ((uint32_t)0x00001000) +#define IP_JEF_SELECT_POS 12 +#define IP_XRFSEL_MASK ((uint32_t)0x000003F0) +#define IP_XRFSEL_LSB 4 +#define IP_XRFSEL_WIDTH ((uint32_t)0x00000006) +#define IP_SUBVERSION_MASK ((uint32_t)0x0000000F) +#define IP_SUBVERSION_LSB 0 +#define IP_SUBVERSION_WIDTH ((uint32_t)0x00000004) + +#define IP_FORCEAGC_EN_RST 0x0 +#define IP_FORCEIQ_RST 0x0 +#define IP_RXDNSL_RST 0x0 +#define IP_TXDNSL_RST 0x0 +#define IP_FORCEAGC_LENGTH_RST 0x0 +#define IP_SYNC_PULSE_MODE_RST 0x0 +#define IP_SYNC_PULSE_SRC_RST 0x0 +#define IP_DPCORR_EN_RST 0x0 +#define IP_JEF_SELECT_RST 0x0 +#define IP_XRFSEL_RST 0x0 +#define IP_SUBVERSION_RST 0x0 + +__INLINE void ip_radiocntl1_pack(uint8_t forceagcen, uint8_t forceiq, uint8_t rxdnsl, uint8_t txdnsl, uint16_t forceagclength, uint8_t syncpulsemode, uint8_t syncpulsesrc, uint8_t dpcorren, uint8_t jefselect, uint8_t xrfsel, uint8_t subversion) +{ + BLE_ASSERT_ERR((((uint32_t)forceagcen << 31) & ~((uint32_t)0x80000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)forceiq << 30) & ~((uint32_t)0x40000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)rxdnsl << 29) & ~((uint32_t)0x20000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)txdnsl << 28) & ~((uint32_t)0x10000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)forceagclength << 16) & ~((uint32_t)0x0FFF0000)) == 0); + BLE_ASSERT_ERR((((uint32_t)syncpulsemode << 15) & ~((uint32_t)0x00008000)) == 0); + BLE_ASSERT_ERR((((uint32_t)syncpulsesrc << 14) & ~((uint32_t)0x00004000)) == 0); + BLE_ASSERT_ERR((((uint32_t)dpcorren << 13) & ~((uint32_t)0x00002000)) == 0); + BLE_ASSERT_ERR((((uint32_t)jefselect << 12) & ~((uint32_t)0x00001000)) == 0); + BLE_ASSERT_ERR((((uint32_t)xrfsel << 4) & ~((uint32_t)0x000003F0)) == 0); + BLE_ASSERT_ERR((((uint32_t)subversion << 0) & ~((uint32_t)0x0000000F)) == 0); + REG_IP_WR(IP_RADIOCNTL1_ADDR, ((uint32_t)forceagcen << 31) | ((uint32_t)forceiq << 30) | ((uint32_t)rxdnsl << 29) | ((uint32_t)txdnsl << 28) | ((uint32_t)forceagclength << 16) | ((uint32_t)syncpulsemode << 15) | ((uint32_t)syncpulsesrc << 14) | ((uint32_t)dpcorren << 13) | ((uint32_t)jefselect << 12) | ((uint32_t)xrfsel << 4) | ((uint32_t)subversion << 0)); +} + +__INLINE void ip_radiocntl1_unpack(uint8_t* forceagcen, uint8_t* forceiq, uint8_t* rxdnsl, uint8_t* txdnsl, uint16_t* forceagclength, uint8_t* syncpulsemode, uint8_t* syncpulsesrc, uint8_t* dpcorren, uint8_t* jefselect, uint8_t* xrfsel, uint8_t* subversion) +{ + uint32_t localVal = REG_IP_RD(IP_RADIOCNTL1_ADDR); + + *forceagcen = (localVal & ((uint32_t)0x80000000)) >> 31; + *forceiq = (localVal & ((uint32_t)0x40000000)) >> 30; + *rxdnsl = (localVal & ((uint32_t)0x20000000)) >> 29; + *txdnsl = (localVal & ((uint32_t)0x10000000)) >> 28; + *forceagclength = (localVal & ((uint32_t)0x0FFF0000)) >> 16; + *syncpulsemode = (localVal & ((uint32_t)0x00008000)) >> 15; + *syncpulsesrc = (localVal & ((uint32_t)0x00004000)) >> 14; + *dpcorren = (localVal & ((uint32_t)0x00002000)) >> 13; + *jefselect = (localVal & ((uint32_t)0x00001000)) >> 12; + *xrfsel = (localVal & ((uint32_t)0x000003F0)) >> 4; + *subversion = (localVal & ((uint32_t)0x0000000F)) >> 0; +} + +__INLINE uint8_t ip_radiocntl1_forceagc_en_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_RADIOCNTL1_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +__INLINE void ip_radiocntl1_forceagc_en_setf(uint8_t forceagcen) +{ + BLE_ASSERT_ERR((((uint32_t)forceagcen << 31) & ~((uint32_t)0x80000000)) == 0); + REG_IP_WR(IP_RADIOCNTL1_ADDR, (REG_IP_RD(IP_RADIOCNTL1_ADDR) & ~((uint32_t)0x80000000)) | ((uint32_t)forceagcen << 31)); +} + +__INLINE uint8_t ip_radiocntl1_forceiq_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_RADIOCNTL1_ADDR); + return ((localVal & ((uint32_t)0x40000000)) >> 30); +} + +__INLINE void ip_radiocntl1_forceiq_setf(uint8_t forceiq) +{ + BLE_ASSERT_ERR((((uint32_t)forceiq << 30) & ~((uint32_t)0x40000000)) == 0); + REG_IP_WR(IP_RADIOCNTL1_ADDR, (REG_IP_RD(IP_RADIOCNTL1_ADDR) & ~((uint32_t)0x40000000)) | ((uint32_t)forceiq << 30)); +} + +__INLINE uint8_t ip_radiocntl1_rxdnsl_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_RADIOCNTL1_ADDR); + return ((localVal & ((uint32_t)0x20000000)) >> 29); +} + +__INLINE void ip_radiocntl1_rxdnsl_setf(uint8_t rxdnsl) +{ + BLE_ASSERT_ERR((((uint32_t)rxdnsl << 29) & ~((uint32_t)0x20000000)) == 0); + REG_IP_WR(IP_RADIOCNTL1_ADDR, (REG_IP_RD(IP_RADIOCNTL1_ADDR) & ~((uint32_t)0x20000000)) | ((uint32_t)rxdnsl << 29)); +} + +__INLINE uint8_t ip_radiocntl1_txdnsl_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_RADIOCNTL1_ADDR); + return ((localVal & ((uint32_t)0x10000000)) >> 28); +} + +__INLINE void ip_radiocntl1_txdnsl_setf(uint8_t txdnsl) +{ + BLE_ASSERT_ERR((((uint32_t)txdnsl << 28) & ~((uint32_t)0x10000000)) == 0); + REG_IP_WR(IP_RADIOCNTL1_ADDR, (REG_IP_RD(IP_RADIOCNTL1_ADDR) & ~((uint32_t)0x10000000)) | ((uint32_t)txdnsl << 28)); +} + +__INLINE uint16_t ip_radiocntl1_forceagc_length_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_RADIOCNTL1_ADDR); + return ((localVal & ((uint32_t)0x0FFF0000)) >> 16); +} + +__INLINE void ip_radiocntl1_forceagc_length_setf(uint16_t forceagclength) +{ + BLE_ASSERT_ERR((((uint32_t)forceagclength << 16) & ~((uint32_t)0x0FFF0000)) == 0); + REG_IP_WR(IP_RADIOCNTL1_ADDR, (REG_IP_RD(IP_RADIOCNTL1_ADDR) & ~((uint32_t)0x0FFF0000)) | ((uint32_t)forceagclength << 16)); +} + +__INLINE uint8_t ip_radiocntl1_sync_pulse_mode_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_RADIOCNTL1_ADDR); + return ((localVal & ((uint32_t)0x00008000)) >> 15); +} + +__INLINE void ip_radiocntl1_sync_pulse_mode_setf(uint8_t syncpulsemode) +{ + BLE_ASSERT_ERR((((uint32_t)syncpulsemode << 15) & ~((uint32_t)0x00008000)) == 0); + REG_IP_WR(IP_RADIOCNTL1_ADDR, (REG_IP_RD(IP_RADIOCNTL1_ADDR) & ~((uint32_t)0x00008000)) | ((uint32_t)syncpulsemode << 15)); +} + +__INLINE uint8_t ip_radiocntl1_sync_pulse_src_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_RADIOCNTL1_ADDR); + return ((localVal & ((uint32_t)0x00004000)) >> 14); +} + +__INLINE void ip_radiocntl1_sync_pulse_src_setf(uint8_t syncpulsesrc) +{ + BLE_ASSERT_ERR((((uint32_t)syncpulsesrc << 14) & ~((uint32_t)0x00004000)) == 0); + REG_IP_WR(IP_RADIOCNTL1_ADDR, (REG_IP_RD(IP_RADIOCNTL1_ADDR) & ~((uint32_t)0x00004000)) | ((uint32_t)syncpulsesrc << 14)); +} + +__INLINE uint8_t ip_radiocntl1_dpcorr_en_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_RADIOCNTL1_ADDR); + return ((localVal & ((uint32_t)0x00002000)) >> 13); +} + +__INLINE void ip_radiocntl1_dpcorr_en_setf(uint8_t dpcorren) +{ + BLE_ASSERT_ERR((((uint32_t)dpcorren << 13) & ~((uint32_t)0x00002000)) == 0); + REG_IP_WR(IP_RADIOCNTL1_ADDR, (REG_IP_RD(IP_RADIOCNTL1_ADDR) & ~((uint32_t)0x00002000)) | ((uint32_t)dpcorren << 13)); +} + +__INLINE uint8_t ip_radiocntl1_jef_select_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_RADIOCNTL1_ADDR); + return ((localVal & ((uint32_t)0x00001000)) >> 12); +} + +__INLINE void ip_radiocntl1_jef_select_setf(uint8_t jefselect) +{ + BLE_ASSERT_ERR((((uint32_t)jefselect << 12) & ~((uint32_t)0x00001000)) == 0); + REG_IP_WR(IP_RADIOCNTL1_ADDR, (REG_IP_RD(IP_RADIOCNTL1_ADDR) & ~((uint32_t)0x00001000)) | ((uint32_t)jefselect << 12)); +} + +__INLINE uint8_t ip_radiocntl1_xrfsel_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_RADIOCNTL1_ADDR); + return ((localVal & ((uint32_t)0x000003F0)) >> 4); +} + +__INLINE void ip_radiocntl1_xrfsel_setf(uint8_t xrfsel) +{ + BLE_ASSERT_ERR((((uint32_t)xrfsel << 4) & ~((uint32_t)0x000003F0)) == 0); + REG_IP_WR(IP_RADIOCNTL1_ADDR, (REG_IP_RD(IP_RADIOCNTL1_ADDR) & ~((uint32_t)0x000003F0)) | ((uint32_t)xrfsel << 4)); +} + +__INLINE uint8_t ip_radiocntl1_subversion_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_RADIOCNTL1_ADDR); + return ((localVal & ((uint32_t)0x0000000F)) >> 0); +} + +__INLINE void ip_radiocntl1_subversion_setf(uint8_t subversion) +{ + BLE_ASSERT_ERR((((uint32_t)subversion << 0) & ~((uint32_t)0x0000000F)) == 0); + REG_IP_WR(IP_RADIOCNTL1_ADDR, (REG_IP_RD(IP_RADIOCNTL1_ADDR) & ~((uint32_t)0x0000000F)) | ((uint32_t)subversion << 0)); +} + +/** + * @brief AESCNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     01             AES_MODE   0
+ *     00            AES_START   0
+ * 
+ */ +#define IP_AESCNTL_ADDR 0x009000B0 +#define IP_AESCNTL_OFFSET 0x000000B0 +#define IP_AESCNTL_INDEX 0x0000002C +#define IP_AESCNTL_RESET 0x00000000 + +__INLINE uint32_t ip_aescntl_get(void) +{ + return REG_IP_RD(IP_AESCNTL_ADDR); +} + +__INLINE void ip_aescntl_set(uint32_t value) +{ + REG_IP_WR(IP_AESCNTL_ADDR, value); +} + +// field definitions +#define IP_AES_MODE_BIT ((uint32_t)0x00000002) +#define IP_AES_MODE_POS 1 +#define IP_AES_START_BIT ((uint32_t)0x00000001) +#define IP_AES_START_POS 0 + +#define IP_AES_MODE_RST 0x0 +#define IP_AES_START_RST 0x0 + +__INLINE void ip_aescntl_pack(uint8_t aesmode, uint8_t aesstart) +{ + BLE_ASSERT_ERR((((uint32_t)aesmode << 1) & ~((uint32_t)0x00000002)) == 0); + BLE_ASSERT_ERR((((uint32_t)aesstart << 0) & ~((uint32_t)0x00000001)) == 0); + REG_IP_WR(IP_AESCNTL_ADDR, ((uint32_t)aesmode << 1) | ((uint32_t)aesstart << 0)); +} + +__INLINE void ip_aescntl_unpack(uint8_t* aesmode, uint8_t* aesstart) +{ + uint32_t localVal = REG_IP_RD(IP_AESCNTL_ADDR); + + *aesmode = (localVal & ((uint32_t)0x00000002)) >> 1; + *aesstart = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +__INLINE uint8_t ip_aescntl_aes_mode_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_AESCNTL_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +__INLINE void ip_aescntl_aes_mode_setf(uint8_t aesmode) +{ + BLE_ASSERT_ERR((((uint32_t)aesmode << 1) & ~((uint32_t)0x00000002)) == 0); + REG_IP_WR(IP_AESCNTL_ADDR, (REG_IP_RD(IP_AESCNTL_ADDR) & ~((uint32_t)0x00000002)) | ((uint32_t)aesmode << 1)); +} + +__INLINE uint8_t ip_aescntl_aes_start_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_AESCNTL_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +__INLINE void ip_aescntl_aes_start_setf(uint8_t aesstart) +{ + BLE_ASSERT_ERR((((uint32_t)aesstart << 0) & ~((uint32_t)0x00000001)) == 0); + REG_IP_WR(IP_AESCNTL_ADDR, (REG_IP_RD(IP_AESCNTL_ADDR) & ~((uint32_t)0x00000001)) | ((uint32_t)aesstart << 0)); +} + +/** + * @brief AESKEY31_0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00           AESKEY31_0   0x0
+ * 
+ */ +#define IP_AESKEY31_0_ADDR 0x009000B4 +#define IP_AESKEY31_0_OFFSET 0x000000B4 +#define IP_AESKEY31_0_INDEX 0x0000002D +#define IP_AESKEY31_0_RESET 0x00000000 + +__INLINE uint32_t ip_aeskey31_0_get(void) +{ + return REG_IP_RD(IP_AESKEY31_0_ADDR); +} + +__INLINE void ip_aeskey31_0_set(uint32_t value) +{ + REG_IP_WR(IP_AESKEY31_0_ADDR, value); +} + +// field definitions +#define IP_AESKEY31_0_MASK ((uint32_t)0xFFFFFFFF) +#define IP_AESKEY31_0_LSB 0 +#define IP_AESKEY31_0_WIDTH ((uint32_t)0x00000020) + +#define IP_AESKEY31_0_RST 0x0 + +__INLINE uint32_t ip_aeskey31_0_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_AESKEY31_0_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ip_aeskey31_0_setf(uint32_t aeskey310) +{ + BLE_ASSERT_ERR((((uint32_t)aeskey310 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_IP_WR(IP_AESKEY31_0_ADDR, (uint32_t)aeskey310 << 0); +} + +/** + * @brief AESKEY63_32 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00          AESKEY63_32   0x0
+ * 
+ */ +#define IP_AESKEY63_32_ADDR 0x009000B8 +#define IP_AESKEY63_32_OFFSET 0x000000B8 +#define IP_AESKEY63_32_INDEX 0x0000002E +#define IP_AESKEY63_32_RESET 0x00000000 + +__INLINE uint32_t ip_aeskey63_32_get(void) +{ + return REG_IP_RD(IP_AESKEY63_32_ADDR); +} + +__INLINE void ip_aeskey63_32_set(uint32_t value) +{ + REG_IP_WR(IP_AESKEY63_32_ADDR, value); +} + +// field definitions +#define IP_AESKEY63_32_MASK ((uint32_t)0xFFFFFFFF) +#define IP_AESKEY63_32_LSB 0 +#define IP_AESKEY63_32_WIDTH ((uint32_t)0x00000020) + +#define IP_AESKEY63_32_RST 0x0 + +__INLINE uint32_t ip_aeskey63_32_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_AESKEY63_32_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ip_aeskey63_32_setf(uint32_t aeskey6332) +{ + BLE_ASSERT_ERR((((uint32_t)aeskey6332 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_IP_WR(IP_AESKEY63_32_ADDR, (uint32_t)aeskey6332 << 0); +} + +/** + * @brief AESKEY95_64 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00          AESKEY95_64   0x0
+ * 
+ */ +#define IP_AESKEY95_64_ADDR 0x009000BC +#define IP_AESKEY95_64_OFFSET 0x000000BC +#define IP_AESKEY95_64_INDEX 0x0000002F +#define IP_AESKEY95_64_RESET 0x00000000 + +__INLINE uint32_t ip_aeskey95_64_get(void) +{ + return REG_IP_RD(IP_AESKEY95_64_ADDR); +} + +__INLINE void ip_aeskey95_64_set(uint32_t value) +{ + REG_IP_WR(IP_AESKEY95_64_ADDR, value); +} + +// field definitions +#define IP_AESKEY95_64_MASK ((uint32_t)0xFFFFFFFF) +#define IP_AESKEY95_64_LSB 0 +#define IP_AESKEY95_64_WIDTH ((uint32_t)0x00000020) + +#define IP_AESKEY95_64_RST 0x0 + +__INLINE uint32_t ip_aeskey95_64_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_AESKEY95_64_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ip_aeskey95_64_setf(uint32_t aeskey9564) +{ + BLE_ASSERT_ERR((((uint32_t)aeskey9564 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_IP_WR(IP_AESKEY95_64_ADDR, (uint32_t)aeskey9564 << 0); +} + +/** + * @brief AESKEY127_96 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00         AESKEY127_96   0x0
+ * 
+ */ +#define IP_AESKEY127_96_ADDR 0x009000C0 +#define IP_AESKEY127_96_OFFSET 0x000000C0 +#define IP_AESKEY127_96_INDEX 0x00000030 +#define IP_AESKEY127_96_RESET 0x00000000 + +__INLINE uint32_t ip_aeskey127_96_get(void) +{ + return REG_IP_RD(IP_AESKEY127_96_ADDR); +} + +__INLINE void ip_aeskey127_96_set(uint32_t value) +{ + REG_IP_WR(IP_AESKEY127_96_ADDR, value); +} + +// field definitions +#define IP_AESKEY127_96_MASK ((uint32_t)0xFFFFFFFF) +#define IP_AESKEY127_96_LSB 0 +#define IP_AESKEY127_96_WIDTH ((uint32_t)0x00000020) + +#define IP_AESKEY127_96_RST 0x0 + +__INLINE uint32_t ip_aeskey127_96_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_AESKEY127_96_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ip_aeskey127_96_setf(uint32_t aeskey12796) +{ + BLE_ASSERT_ERR((((uint32_t)aeskey12796 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_IP_WR(IP_AESKEY127_96_ADDR, (uint32_t)aeskey12796 << 0); +} + +/** + * @brief AESPTR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  13:00               AESPTR   0x0
+ * 
+ */ +#define IP_AESPTR_ADDR 0x009000C4 +#define IP_AESPTR_OFFSET 0x000000C4 +#define IP_AESPTR_INDEX 0x00000031 +#define IP_AESPTR_RESET 0x00000000 + +__INLINE uint32_t ip_aesptr_get(void) +{ + return REG_IP_RD(IP_AESPTR_ADDR); +} + +__INLINE void ip_aesptr_set(uint32_t value) +{ + REG_IP_WR(IP_AESPTR_ADDR, value); +} + +// field definitions +#define IP_AESPTR_MASK ((uint32_t)0x00003FFF) +#define IP_AESPTR_LSB 0 +#define IP_AESPTR_WIDTH ((uint32_t)0x0000000E) + +#define IP_AESPTR_RST 0x0 + +__INLINE uint16_t ip_aesptr_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_AESPTR_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0x00003FFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ip_aesptr_setf(uint16_t aesptr) +{ + BLE_ASSERT_ERR((((uint32_t)aesptr << 0) & ~((uint32_t)0x00003FFF)) == 0); + REG_IP_WR(IP_AESPTR_ADDR, (uint32_t)aesptr << 0); +} + +/** + * @brief TXMICVAL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00             TXMICVAL   0x0
+ * 
+ */ +#define IP_TXMICVAL_ADDR 0x009000C8 +#define IP_TXMICVAL_OFFSET 0x000000C8 +#define IP_TXMICVAL_INDEX 0x00000032 +#define IP_TXMICVAL_RESET 0x00000000 + +__INLINE uint32_t ip_txmicval_get(void) +{ + return REG_IP_RD(IP_TXMICVAL_ADDR); +} + +// field definitions +#define IP_TXMICVAL_MASK ((uint32_t)0xFFFFFFFF) +#define IP_TXMICVAL_LSB 0 +#define IP_TXMICVAL_WIDTH ((uint32_t)0x00000020) + +#define IP_TXMICVAL_RST 0x0 + +__INLINE uint32_t ip_txmicval_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_TXMICVAL_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief RXMICVAL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00             RXMICVAL   0x0
+ * 
+ */ +#define IP_RXMICVAL_ADDR 0x009000CC +#define IP_RXMICVAL_OFFSET 0x000000CC +#define IP_RXMICVAL_INDEX 0x00000033 +#define IP_RXMICVAL_RESET 0x00000000 + +__INLINE uint32_t ip_rxmicval_get(void) +{ + return REG_IP_RD(IP_RXMICVAL_ADDR); +} + +// field definitions +#define IP_RXMICVAL_MASK ((uint32_t)0xFFFFFFFF) +#define IP_RXMICVAL_LSB 0 +#define IP_RXMICVAL_WIDTH ((uint32_t)0x00000020) + +#define IP_RXMICVAL_RST 0x0 + +__INLINE uint32_t ip_rxmicval_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_RXMICVAL_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief TIMGENCNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  25:16   PREFETCHABORT_TIME   0x1DF
+ *  08:00        PREFETCH_TIME   0xBD
+ * 
+ */ +#define IP_TIMGENCNTL_ADDR 0x009000E0 +#define IP_TIMGENCNTL_OFFSET 0x000000E0 +#define IP_TIMGENCNTL_INDEX 0x00000038 +#define IP_TIMGENCNTL_RESET 0x01DF00BD + +__INLINE uint32_t ip_timgencntl_get(void) +{ + return REG_IP_RD(IP_TIMGENCNTL_ADDR); +} + +__INLINE void ip_timgencntl_set(uint32_t value) +{ + REG_IP_WR(IP_TIMGENCNTL_ADDR, value); +} + +// field definitions +#define IP_PREFETCHABORT_TIME_MASK ((uint32_t)0x03FF0000) +#define IP_PREFETCHABORT_TIME_LSB 16 +#define IP_PREFETCHABORT_TIME_WIDTH ((uint32_t)0x0000000A) +#define IP_PREFETCH_TIME_MASK ((uint32_t)0x000001FF) +#define IP_PREFETCH_TIME_LSB 0 +#define IP_PREFETCH_TIME_WIDTH ((uint32_t)0x00000009) + +#define IP_PREFETCHABORT_TIME_RST 0x1DF +#define IP_PREFETCH_TIME_RST 0xBD + +__INLINE void ip_timgencntl_pack(uint16_t prefetchaborttime, uint16_t prefetchtime) +{ + BLE_ASSERT_ERR((((uint32_t)prefetchaborttime << 16) & ~((uint32_t)0x03FF0000)) == 0); + BLE_ASSERT_ERR((((uint32_t)prefetchtime << 0) & ~((uint32_t)0x000001FF)) == 0); + REG_IP_WR(IP_TIMGENCNTL_ADDR, ((uint32_t)prefetchaborttime << 16) | ((uint32_t)prefetchtime << 0)); +} + +__INLINE void ip_timgencntl_unpack(uint16_t* prefetchaborttime, uint16_t* prefetchtime) +{ + uint32_t localVal = REG_IP_RD(IP_TIMGENCNTL_ADDR); + + *prefetchaborttime = (localVal & ((uint32_t)0x03FF0000)) >> 16; + *prefetchtime = (localVal & ((uint32_t)0x000001FF)) >> 0; +} + +__INLINE uint16_t ip_timgencntl_prefetchabort_time_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_TIMGENCNTL_ADDR); + return ((localVal & ((uint32_t)0x03FF0000)) >> 16); +} + +__INLINE void ip_timgencntl_prefetchabort_time_setf(uint16_t prefetchaborttime) +{ + BLE_ASSERT_ERR((((uint32_t)prefetchaborttime << 16) & ~((uint32_t)0x03FF0000)) == 0); + REG_IP_WR(IP_TIMGENCNTL_ADDR, (REG_IP_RD(IP_TIMGENCNTL_ADDR) & ~((uint32_t)0x03FF0000)) | ((uint32_t)prefetchaborttime << 16)); +} + +__INLINE uint16_t ip_timgencntl_prefetch_time_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_TIMGENCNTL_ADDR); + return ((localVal & ((uint32_t)0x000001FF)) >> 0); +} + +__INLINE void ip_timgencntl_prefetch_time_setf(uint16_t prefetchtime) +{ + BLE_ASSERT_ERR((((uint32_t)prefetchtime << 0) & ~((uint32_t)0x000001FF)) == 0); + REG_IP_WR(IP_TIMGENCNTL_ADDR, (REG_IP_RD(IP_TIMGENCNTL_ADDR) & ~((uint32_t)0x000001FF)) | ((uint32_t)prefetchtime << 0)); +} + +/** + * @brief FINETIMTGT register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  27:00           FINETARGET   0x0
+ * 
+ */ +#define IP_FINETIMTGT_ADDR 0x009000E4 +#define IP_FINETIMTGT_OFFSET 0x000000E4 +#define IP_FINETIMTGT_INDEX 0x00000039 +#define IP_FINETIMTGT_RESET 0x00000000 + +__INLINE uint32_t ip_finetimtgt_get(void) +{ + return REG_IP_RD(IP_FINETIMTGT_ADDR); +} + +__INLINE void ip_finetimtgt_set(uint32_t value) +{ + REG_IP_WR(IP_FINETIMTGT_ADDR, value); +} + +// field definitions +#define IP_FINETARGET_MASK ((uint32_t)0x0FFFFFFF) +#define IP_FINETARGET_LSB 0 +#define IP_FINETARGET_WIDTH ((uint32_t)0x0000001C) + +#define IP_FINETARGET_RST 0x0 + +__INLINE uint32_t ip_finetimtgt_finetarget_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_FINETIMTGT_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0x0FFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ip_finetimtgt_finetarget_setf(uint32_t finetarget) +{ + BLE_ASSERT_ERR((((uint32_t)finetarget << 0) & ~((uint32_t)0x0FFFFFFF)) == 0); + REG_IP_WR(IP_FINETIMTGT_ADDR, (uint32_t)finetarget << 0); +} + +/** + * @brief CLKNTGT1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  27:00             CLKNTGT1   0x0
+ * 
+ */ +#define IP_CLKNTGT1_ADDR 0x009000E8 +#define IP_CLKNTGT1_OFFSET 0x000000E8 +#define IP_CLKNTGT1_INDEX 0x0000003A +#define IP_CLKNTGT1_RESET 0x00000000 + +__INLINE uint32_t ip_clkntgt1_get(void) +{ + return REG_IP_RD(IP_CLKNTGT1_ADDR); +} + +__INLINE void ip_clkntgt1_set(uint32_t value) +{ + REG_IP_WR(IP_CLKNTGT1_ADDR, value); +} + +// field definitions +#define IP_CLKNTGT1_MASK ((uint32_t)0x0FFFFFFF) +#define IP_CLKNTGT1_LSB 0 +#define IP_CLKNTGT1_WIDTH ((uint32_t)0x0000001C) + +#define IP_CLKNTGT1_RST 0x0 + +__INLINE uint32_t ip_clkntgt1_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_CLKNTGT1_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0x0FFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ip_clkntgt1_setf(uint32_t clkntgt1) +{ + BLE_ASSERT_ERR((((uint32_t)clkntgt1 << 0) & ~((uint32_t)0x0FFFFFFF)) == 0); + REG_IP_WR(IP_CLKNTGT1_ADDR, (uint32_t)clkntgt1 << 0); +} + +/** + * @brief HMICROSECTGT1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  09:00        HMICROSECTGT1   0x0
+ * 
+ */ +#define IP_HMICROSECTGT1_ADDR 0x009000EC +#define IP_HMICROSECTGT1_OFFSET 0x000000EC +#define IP_HMICROSECTGT1_INDEX 0x0000003B +#define IP_HMICROSECTGT1_RESET 0x00000000 + +__INLINE uint32_t ip_hmicrosectgt1_get(void) +{ + return REG_IP_RD(IP_HMICROSECTGT1_ADDR); +} + +__INLINE void ip_hmicrosectgt1_set(uint32_t value) +{ + REG_IP_WR(IP_HMICROSECTGT1_ADDR, value); +} + +// field definitions +#define IP_HMICROSECTGT1_MASK ((uint32_t)0x000003FF) +#define IP_HMICROSECTGT1_LSB 0 +#define IP_HMICROSECTGT1_WIDTH ((uint32_t)0x0000000A) + +#define IP_HMICROSECTGT1_RST 0x0 + +__INLINE uint16_t ip_hmicrosectgt1_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_HMICROSECTGT1_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0x000003FF)) == 0); + return (localVal >> 0); +} + +__INLINE void ip_hmicrosectgt1_setf(uint16_t hmicrosectgt1) +{ + BLE_ASSERT_ERR((((uint32_t)hmicrosectgt1 << 0) & ~((uint32_t)0x000003FF)) == 0); + REG_IP_WR(IP_HMICROSECTGT1_ADDR, (uint32_t)hmicrosectgt1 << 0); +} + +/** + * @brief CLKNTGT2 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  27:00             CLKNTGT2   0x0
+ * 
+ */ +#define IP_CLKNTGT2_ADDR 0x009000F0 +#define IP_CLKNTGT2_OFFSET 0x000000F0 +#define IP_CLKNTGT2_INDEX 0x0000003C +#define IP_CLKNTGT2_RESET 0x00000000 + +__INLINE uint32_t ip_clkntgt2_get(void) +{ + return REG_IP_RD(IP_CLKNTGT2_ADDR); +} + +__INLINE void ip_clkntgt2_set(uint32_t value) +{ + REG_IP_WR(IP_CLKNTGT2_ADDR, value); +} + +// field definitions +#define IP_CLKNTGT2_MASK ((uint32_t)0x0FFFFFFF) +#define IP_CLKNTGT2_LSB 0 +#define IP_CLKNTGT2_WIDTH ((uint32_t)0x0000001C) + +#define IP_CLKNTGT2_RST 0x0 + +__INLINE uint32_t ip_clkntgt2_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_CLKNTGT2_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0x0FFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void ip_clkntgt2_setf(uint32_t clkntgt2) +{ + BLE_ASSERT_ERR((((uint32_t)clkntgt2 << 0) & ~((uint32_t)0x0FFFFFFF)) == 0); + REG_IP_WR(IP_CLKNTGT2_ADDR, (uint32_t)clkntgt2 << 0); +} + +/** + * @brief HMICROSECTGT2 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  09:00        HMICROSECTGT2   0x0
+ * 
+ */ +#define IP_HMICROSECTGT2_ADDR 0x009000F4 +#define IP_HMICROSECTGT2_OFFSET 0x000000F4 +#define IP_HMICROSECTGT2_INDEX 0x0000003D +#define IP_HMICROSECTGT2_RESET 0x00000000 + +__INLINE uint32_t ip_hmicrosectgt2_get(void) +{ + return REG_IP_RD(IP_HMICROSECTGT2_ADDR); +} + +__INLINE void ip_hmicrosectgt2_set(uint32_t value) +{ + REG_IP_WR(IP_HMICROSECTGT2_ADDR, value); +} + +// field definitions +#define IP_HMICROSECTGT2_MASK ((uint32_t)0x000003FF) +#define IP_HMICROSECTGT2_LSB 0 +#define IP_HMICROSECTGT2_WIDTH ((uint32_t)0x0000000A) + +#define IP_HMICROSECTGT2_RST 0x0 + +__INLINE uint16_t ip_hmicrosectgt2_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_HMICROSECTGT2_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0x000003FF)) == 0); + return (localVal >> 0); +} + +__INLINE void ip_hmicrosectgt2_setf(uint16_t hmicrosectgt2) +{ + BLE_ASSERT_ERR((((uint32_t)hmicrosectgt2 << 0) & ~((uint32_t)0x000003FF)) == 0); + REG_IP_WR(IP_HMICROSECTGT2_ADDR, (uint32_t)hmicrosectgt2 << 0); +} + +/** + * @brief SLOTCLK register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31                 SAMP   0
+ *     30             CLKN_UPD   0
+ *  27:00                 SCLK   0x0
+ * 
+ */ +#define IP_SLOTCLK_ADDR 0x009000F8 +#define IP_SLOTCLK_OFFSET 0x000000F8 +#define IP_SLOTCLK_INDEX 0x0000003E +#define IP_SLOTCLK_RESET 0x00000000 + +__INLINE uint32_t ip_slotclk_get(void) +{ + return REG_IP_RD(IP_SLOTCLK_ADDR); +} + +__INLINE void ip_slotclk_set(uint32_t value) +{ + REG_IP_WR(IP_SLOTCLK_ADDR, value); +} + +// field definitions +#define IP_SAMP_BIT ((uint32_t)0x80000000) +#define IP_SAMP_POS 31 +#define IP_CLKN_UPD_BIT ((uint32_t)0x40000000) +#define IP_CLKN_UPD_POS 30 +#define IP_SCLK_MASK ((uint32_t)0x0FFFFFFF) +#define IP_SCLK_LSB 0 +#define IP_SCLK_WIDTH ((uint32_t)0x0000001C) + +#define IP_SAMP_RST 0x0 +#define IP_CLKN_UPD_RST 0x0 +#define IP_SCLK_RST 0x0 + +__INLINE void ip_slotclk_pack(uint8_t samp, uint8_t clknupd, uint32_t sclk) +{ + BLE_ASSERT_ERR((((uint32_t)samp << 31) & ~((uint32_t)0x80000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)clknupd << 30) & ~((uint32_t)0x40000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)sclk << 0) & ~((uint32_t)0x0FFFFFFF)) == 0); + REG_IP_WR(IP_SLOTCLK_ADDR, ((uint32_t)samp << 31) | ((uint32_t)clknupd << 30) | ((uint32_t)sclk << 0)); +} + +__INLINE void ip_slotclk_unpack(uint8_t* samp, uint8_t* clknupd, uint32_t* sclk) +{ + uint32_t localVal = REG_IP_RD(IP_SLOTCLK_ADDR); + + *samp = (localVal & ((uint32_t)0x80000000)) >> 31; + *clknupd = (localVal & ((uint32_t)0x40000000)) >> 30; + *sclk = (localVal & ((uint32_t)0x0FFFFFFF)) >> 0; +} + +__INLINE uint8_t ip_slotclk_samp_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_SLOTCLK_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +__INLINE void ip_slotclk_samp_setf(uint8_t samp) +{ + BLE_ASSERT_ERR((((uint32_t)samp << 31) & ~((uint32_t)0x80000000)) == 0); + REG_IP_WR(IP_SLOTCLK_ADDR, (REG_IP_RD(IP_SLOTCLK_ADDR) & ~((uint32_t)0x80000000)) | ((uint32_t)samp << 31)); +} + +__INLINE uint8_t ip_slotclk_clkn_upd_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_SLOTCLK_ADDR); + return ((localVal & ((uint32_t)0x40000000)) >> 30); +} + +__INLINE void ip_slotclk_clkn_upd_setf(uint8_t clknupd) +{ + BLE_ASSERT_ERR((((uint32_t)clknupd << 30) & ~((uint32_t)0x40000000)) == 0); + REG_IP_WR(IP_SLOTCLK_ADDR, (REG_IP_RD(IP_SLOTCLK_ADDR) & ~((uint32_t)0x40000000)) | ((uint32_t)clknupd << 30)); +} + +__INLINE uint32_t ip_slotclk_sclk_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_SLOTCLK_ADDR); + return ((localVal & ((uint32_t)0x0FFFFFFF)) >> 0); +} + +__INLINE void ip_slotclk_sclk_setf(uint32_t sclk) +{ + BLE_ASSERT_ERR((((uint32_t)sclk << 0) & ~((uint32_t)0x0FFFFFFF)) == 0); + REG_IP_WR(IP_SLOTCLK_ADDR, (REG_IP_RD(IP_SLOTCLK_ADDR) & ~((uint32_t)0x0FFFFFFF)) | ((uint32_t)sclk << 0)); +} + +/** + * @brief FINETIMECNT register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  09:00              FINECNT   0x0
+ * 
+ */ +#define IP_FINETIMECNT_ADDR 0x009000FC +#define IP_FINETIMECNT_OFFSET 0x000000FC +#define IP_FINETIMECNT_INDEX 0x0000003F +#define IP_FINETIMECNT_RESET 0x00000000 + +__INLINE uint32_t ip_finetimecnt_get(void) +{ + return REG_IP_RD(IP_FINETIMECNT_ADDR); +} + +// field definitions +#define IP_FINECNT_MASK ((uint32_t)0x000003FF) +#define IP_FINECNT_LSB 0 +#define IP_FINECNT_WIDTH ((uint32_t)0x0000000A) + +#define IP_FINECNT_RST 0x0 + +__INLINE uint16_t ip_finetimecnt_finecnt_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_FINETIMECNT_ADDR); + BLE_ASSERT_ERR((localVal & ~((uint32_t)0x000003FF)) == 0); + return (localVal >> 0); +} + +/** + * @brief ACTSCHCNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31            START_ACT   0
+ *  03:00            ENTRY_IDX   0x0
+ * 
+ */ +#define IP_ACTSCHCNTL_ADDR 0x00900100 +#define IP_ACTSCHCNTL_OFFSET 0x00000100 +#define IP_ACTSCHCNTL_INDEX 0x00000040 +#define IP_ACTSCHCNTL_RESET 0x00000000 + +__INLINE uint32_t ip_actschcntl_get(void) +{ + return REG_IP_RD(IP_ACTSCHCNTL_ADDR); +} + +__INLINE void ip_actschcntl_set(uint32_t value) +{ + REG_IP_WR(IP_ACTSCHCNTL_ADDR, value); +} + +// field definitions +#define IP_START_ACT_BIT ((uint32_t)0x80000000) +#define IP_START_ACT_POS 31 +#define IP_ENTRY_IDX_MASK ((uint32_t)0x0000000F) +#define IP_ENTRY_IDX_LSB 0 +#define IP_ENTRY_IDX_WIDTH ((uint32_t)0x00000004) + +#define IP_START_ACT_RST 0x0 +#define IP_ENTRY_IDX_RST 0x0 + +__INLINE void ip_actschcntl_pack(uint8_t startact, uint8_t entryidx) +{ + BLE_ASSERT_ERR((((uint32_t)startact << 31) & ~((uint32_t)0x80000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)entryidx << 0) & ~((uint32_t)0x0000000F)) == 0); + REG_IP_WR(IP_ACTSCHCNTL_ADDR, ((uint32_t)startact << 31) | ((uint32_t)entryidx << 0)); +} + +__INLINE void ip_actschcntl_unpack(uint8_t* startact, uint8_t* entryidx) +{ + uint32_t localVal = REG_IP_RD(IP_ACTSCHCNTL_ADDR); + + *startact = (localVal & ((uint32_t)0x80000000)) >> 31; + *entryidx = (localVal & ((uint32_t)0x0000000F)) >> 0; +} + +__INLINE uint8_t ip_actschcntl_start_act_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_ACTSCHCNTL_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +__INLINE void ip_actschcntl_start_act_setf(uint8_t startact) +{ + BLE_ASSERT_ERR((((uint32_t)startact << 31) & ~((uint32_t)0x80000000)) == 0); + REG_IP_WR(IP_ACTSCHCNTL_ADDR, (REG_IP_RD(IP_ACTSCHCNTL_ADDR) & ~((uint32_t)0x80000000)) | ((uint32_t)startact << 31)); +} + +__INLINE uint8_t ip_actschcntl_entry_idx_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_ACTSCHCNTL_ADDR); + return ((localVal & ((uint32_t)0x0000000F)) >> 0); +} + +__INLINE void ip_actschcntl_entry_idx_setf(uint8_t entryidx) +{ + BLE_ASSERT_ERR((((uint32_t)entryidx << 0) & ~((uint32_t)0x0000000F)) == 0); + REG_IP_WR(IP_ACTSCHCNTL_ADDR, (REG_IP_RD(IP_ACTSCHCNTL_ADDR) & ~((uint32_t)0x0000000F)) | ((uint32_t)entryidx << 0)); +} + +/** + * @brief DFANCNTL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31     BTRXPRIMIDCNTLEN   0
+ *  30:24        BTRXPRIMANTID   0x0
+ *     23     BTTXPRIMIDCNTLEN   0
+ *  22:16        BTTXPRIMANTID   0x0
+ *     15     LERXPRIMIDCNTLEN   0
+ *  14:08        LERXPRIMANTID   0x0
+ *     07     LETXPRIMIDCNTLEN   0
+ *  06:00        LETXPRIMANTID   0x0
+ * 
+ */ +#define IP_DFANCNTL_ADDR 0x00900184 +#define IP_DFANCNTL_OFFSET 0x00000184 +#define IP_DFANCNTL_INDEX 0x00000061 +#define IP_DFANCNTL_RESET 0x00000000 + +__INLINE uint32_t ip_dfancntl_get(void) +{ + return REG_IP_RD(IP_DFANCNTL_ADDR); +} + +__INLINE void ip_dfancntl_set(uint32_t value) +{ + REG_IP_WR(IP_DFANCNTL_ADDR, value); +} + +// field definitions +#define IP_BTRXPRIMIDCNTLEN_BIT ((uint32_t)0x80000000) +#define IP_BTRXPRIMIDCNTLEN_POS 31 +#define IP_BTRXPRIMANTID_MASK ((uint32_t)0x7F000000) +#define IP_BTRXPRIMANTID_LSB 24 +#define IP_BTRXPRIMANTID_WIDTH ((uint32_t)0x00000007) +#define IP_BTTXPRIMIDCNTLEN_BIT ((uint32_t)0x00800000) +#define IP_BTTXPRIMIDCNTLEN_POS 23 +#define IP_BTTXPRIMANTID_MASK ((uint32_t)0x007F0000) +#define IP_BTTXPRIMANTID_LSB 16 +#define IP_BTTXPRIMANTID_WIDTH ((uint32_t)0x00000007) +#define IP_LERXPRIMIDCNTLEN_BIT ((uint32_t)0x00008000) +#define IP_LERXPRIMIDCNTLEN_POS 15 +#define IP_LERXPRIMANTID_MASK ((uint32_t)0x00007F00) +#define IP_LERXPRIMANTID_LSB 8 +#define IP_LERXPRIMANTID_WIDTH ((uint32_t)0x00000007) +#define IP_LETXPRIMIDCNTLEN_BIT ((uint32_t)0x00000080) +#define IP_LETXPRIMIDCNTLEN_POS 7 +#define IP_LETXPRIMANTID_MASK ((uint32_t)0x0000007F) +#define IP_LETXPRIMANTID_LSB 0 +#define IP_LETXPRIMANTID_WIDTH ((uint32_t)0x00000007) + +#define IP_BTRXPRIMIDCNTLEN_RST 0x0 +#define IP_BTRXPRIMANTID_RST 0x0 +#define IP_BTTXPRIMIDCNTLEN_RST 0x0 +#define IP_BTTXPRIMANTID_RST 0x0 +#define IP_LERXPRIMIDCNTLEN_RST 0x0 +#define IP_LERXPRIMANTID_RST 0x0 +#define IP_LETXPRIMIDCNTLEN_RST 0x0 +#define IP_LETXPRIMANTID_RST 0x0 + +__INLINE void ip_dfancntl_pack(uint8_t btrxprimidcntlen, uint8_t btrxprimantid, uint8_t bttxprimidcntlen, uint8_t bttxprimantid, uint8_t lerxprimidcntlen, uint8_t lerxprimantid, uint8_t letxprimidcntlen, uint8_t letxprimantid) +{ + BLE_ASSERT_ERR((((uint32_t)btrxprimidcntlen << 31) & ~((uint32_t)0x80000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)btrxprimantid << 24) & ~((uint32_t)0x7F000000)) == 0); + BLE_ASSERT_ERR((((uint32_t)bttxprimidcntlen << 23) & ~((uint32_t)0x00800000)) == 0); + BLE_ASSERT_ERR((((uint32_t)bttxprimantid << 16) & ~((uint32_t)0x007F0000)) == 0); + BLE_ASSERT_ERR((((uint32_t)lerxprimidcntlen << 15) & ~((uint32_t)0x00008000)) == 0); + BLE_ASSERT_ERR((((uint32_t)lerxprimantid << 8) & ~((uint32_t)0x00007F00)) == 0); + BLE_ASSERT_ERR((((uint32_t)letxprimidcntlen << 7) & ~((uint32_t)0x00000080)) == 0); + BLE_ASSERT_ERR((((uint32_t)letxprimantid << 0) & ~((uint32_t)0x0000007F)) == 0); + REG_IP_WR(IP_DFANCNTL_ADDR, ((uint32_t)btrxprimidcntlen << 31) | ((uint32_t)btrxprimantid << 24) | ((uint32_t)bttxprimidcntlen << 23) | ((uint32_t)bttxprimantid << 16) | ((uint32_t)lerxprimidcntlen << 15) | ((uint32_t)lerxprimantid << 8) | ((uint32_t)letxprimidcntlen << 7) | ((uint32_t)letxprimantid << 0)); +} + +__INLINE void ip_dfancntl_unpack(uint8_t* btrxprimidcntlen, uint8_t* btrxprimantid, uint8_t* bttxprimidcntlen, uint8_t* bttxprimantid, uint8_t* lerxprimidcntlen, uint8_t* lerxprimantid, uint8_t* letxprimidcntlen, uint8_t* letxprimantid) +{ + uint32_t localVal = REG_IP_RD(IP_DFANCNTL_ADDR); + + *btrxprimidcntlen = (localVal & ((uint32_t)0x80000000)) >> 31; + *btrxprimantid = (localVal & ((uint32_t)0x7F000000)) >> 24; + *bttxprimidcntlen = (localVal & ((uint32_t)0x00800000)) >> 23; + *bttxprimantid = (localVal & ((uint32_t)0x007F0000)) >> 16; + *lerxprimidcntlen = (localVal & ((uint32_t)0x00008000)) >> 15; + *lerxprimantid = (localVal & ((uint32_t)0x00007F00)) >> 8; + *letxprimidcntlen = (localVal & ((uint32_t)0x00000080)) >> 7; + *letxprimantid = (localVal & ((uint32_t)0x0000007F)) >> 0; +} + +__INLINE uint8_t ip_dfancntl_btrxprimidcntlen_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_DFANCNTL_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +__INLINE void ip_dfancntl_btrxprimidcntlen_setf(uint8_t btrxprimidcntlen) +{ + BLE_ASSERT_ERR((((uint32_t)btrxprimidcntlen << 31) & ~((uint32_t)0x80000000)) == 0); + REG_IP_WR(IP_DFANCNTL_ADDR, (REG_IP_RD(IP_DFANCNTL_ADDR) & ~((uint32_t)0x80000000)) | ((uint32_t)btrxprimidcntlen << 31)); +} + +__INLINE uint8_t ip_dfancntl_btrxprimantid_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_DFANCNTL_ADDR); + return ((localVal & ((uint32_t)0x7F000000)) >> 24); +} + +__INLINE void ip_dfancntl_btrxprimantid_setf(uint8_t btrxprimantid) +{ + BLE_ASSERT_ERR((((uint32_t)btrxprimantid << 24) & ~((uint32_t)0x7F000000)) == 0); + REG_IP_WR(IP_DFANCNTL_ADDR, (REG_IP_RD(IP_DFANCNTL_ADDR) & ~((uint32_t)0x7F000000)) | ((uint32_t)btrxprimantid << 24)); +} + +__INLINE uint8_t ip_dfancntl_bttxprimidcntlen_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_DFANCNTL_ADDR); + return ((localVal & ((uint32_t)0x00800000)) >> 23); +} + +__INLINE void ip_dfancntl_bttxprimidcntlen_setf(uint8_t bttxprimidcntlen) +{ + BLE_ASSERT_ERR((((uint32_t)bttxprimidcntlen << 23) & ~((uint32_t)0x00800000)) == 0); + REG_IP_WR(IP_DFANCNTL_ADDR, (REG_IP_RD(IP_DFANCNTL_ADDR) & ~((uint32_t)0x00800000)) | ((uint32_t)bttxprimidcntlen << 23)); +} + +__INLINE uint8_t ip_dfancntl_bttxprimantid_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_DFANCNTL_ADDR); + return ((localVal & ((uint32_t)0x007F0000)) >> 16); +} + +__INLINE void ip_dfancntl_bttxprimantid_setf(uint8_t bttxprimantid) +{ + BLE_ASSERT_ERR((((uint32_t)bttxprimantid << 16) & ~((uint32_t)0x007F0000)) == 0); + REG_IP_WR(IP_DFANCNTL_ADDR, (REG_IP_RD(IP_DFANCNTL_ADDR) & ~((uint32_t)0x007F0000)) | ((uint32_t)bttxprimantid << 16)); +} + +__INLINE uint8_t ip_dfancntl_lerxprimidcntlen_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_DFANCNTL_ADDR); + return ((localVal & ((uint32_t)0x00008000)) >> 15); +} + +__INLINE void ip_dfancntl_lerxprimidcntlen_setf(uint8_t lerxprimidcntlen) +{ + BLE_ASSERT_ERR((((uint32_t)lerxprimidcntlen << 15) & ~((uint32_t)0x00008000)) == 0); + REG_IP_WR(IP_DFANCNTL_ADDR, (REG_IP_RD(IP_DFANCNTL_ADDR) & ~((uint32_t)0x00008000)) | ((uint32_t)lerxprimidcntlen << 15)); +} + +__INLINE uint8_t ip_dfancntl_lerxprimantid_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_DFANCNTL_ADDR); + return ((localVal & ((uint32_t)0x00007F00)) >> 8); +} + +__INLINE void ip_dfancntl_lerxprimantid_setf(uint8_t lerxprimantid) +{ + BLE_ASSERT_ERR((((uint32_t)lerxprimantid << 8) & ~((uint32_t)0x00007F00)) == 0); + REG_IP_WR(IP_DFANCNTL_ADDR, (REG_IP_RD(IP_DFANCNTL_ADDR) & ~((uint32_t)0x00007F00)) | ((uint32_t)lerxprimantid << 8)); +} + +__INLINE uint8_t ip_dfancntl_letxprimidcntlen_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_DFANCNTL_ADDR); + return ((localVal & ((uint32_t)0x00000080)) >> 7); +} + +__INLINE void ip_dfancntl_letxprimidcntlen_setf(uint8_t letxprimidcntlen) +{ + BLE_ASSERT_ERR((((uint32_t)letxprimidcntlen << 7) & ~((uint32_t)0x00000080)) == 0); + REG_IP_WR(IP_DFANCNTL_ADDR, (REG_IP_RD(IP_DFANCNTL_ADDR) & ~((uint32_t)0x00000080)) | ((uint32_t)letxprimidcntlen << 7)); +} + +__INLINE uint8_t ip_dfancntl_letxprimantid_getf(void) +{ + uint32_t localVal = REG_IP_RD(IP_DFANCNTL_ADDR); + return ((localVal & ((uint32_t)0x0000007F)) >> 0); +} + +__INLINE void ip_dfancntl_letxprimantid_setf(uint8_t letxprimantid) +{ + BLE_ASSERT_ERR((((uint32_t)letxprimantid << 0) & ~((uint32_t)0x0000007F)) == 0); + REG_IP_WR(IP_DFANCNTL_ADDR, (REG_IP_RD(IP_DFANCNTL_ADDR) & ~((uint32_t)0x0000007F)) | ((uint32_t)letxprimantid << 0)); +} + + +#endif // _REG_IPCORE_H_ + diff --git a/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/rwip/src/rwble.c b/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/rwip/src/rwble.c new file mode 100755 index 0000000..68ac6c2 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/rwip/src/rwble.c @@ -0,0 +1,161 @@ +/** +**************************************************************************************** +* +* @file rwble.c +* +* @brief RWBLE core interrupt handler +* +* Copyright (C) RivieraWaves 2009-2016 +* +**************************************************************************************** +*/ + +/** + **************************************************************************************** + * @addtogroup ROOT + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwip_config.h" // stack configuration + +#include // for mem* functions +#include "common_version.h" +#include "common_math.h" +#include "rwble.h" // BLE API definition +#include "rwip.h" // stack main module + +#include "ble_util_buf.h" // BLE EM buffer management +#include "lld.h" // link layer driver definition +#include "llctrl.h" // link layer controller definition +#include "llm.h" // link layer manager definition + +#if (BLE_ISO_PRESENT) +#include "lli.h" // Link Layer ISO definition +#endif // (BLE_ISO_PRESENT) + +#include "kernel_event.h" // kernel event definition + +#include "sch_arb.h" // Scheduling Arbiter +#include "sch_prog.h" // Scheduling Programmer + +#include "dbg.h" // debug definitions + +#include "ble_reg_blecore.h" // BLE Core registers + + +/* + * DEFINES + **************************************************************************************** + */ + +/* + * STRUCTURE DEFINITIONS + **************************************************************************************** + */ + + +/* + * LOCAL VARIABLE DEFINITIONS + **************************************************************************************** + */ + + +/* + * GLOBAL VARIABLES + **************************************************************************************** + */ + + +/* + * LOCAL FUNCTION DEFINITIONS + **************************************************************************************** + */ + +/* + * EXPORTED FUNCTION DEFINITIONS + **************************************************************************************** + */ + +void rwble_init(uint8_t init_type) +{ + if(!init_type) + { + uint32_t seed; + rwip_time_t current_time = rwip_time_get(); + + seed = current_time.hs; + seed += current_time.hus; + + //Init the random seed + common_random_init(seed); + } + + // Initialize buffer management system + ble_util_buf_init(init_type); + + #if (BLE_ISO_PRESENT) + // Initialize ISO descriptor management system + ble_util_isodesc_init(init_type); + #endif // (BLE_ISO_PRESENT) + + // LLD block does nothing at IP INIT state + if (init_type) + { + // Initialize the Link Layer Driver + lld_init(init_type); + } + + #if(BLE_CENTRAL || BLE_PERIPHERAL) + // Initialize the Link Layer Controller + llc_init(init_type); + #endif // (BLE_CENTRAL || BLE_PERIPHERAL) + + // Initialize the Link Layer Manager + llm_init(init_type); + + #if (BLE_ISO_PRESENT) + // Initialize the Link Layer ISO + lli_init(init_type); + #endif // (BLE_ISO_PRESENT) +} + +#if BT_DUAL_MODE +bool rwble_activity_ongoing_check(void) +{ + // check that a BLE activity is ongoing (advertising, scan, initiating, connection) + return llm_activity_ongoing_check(); +} +#endif //BT_DUAL_MODE + +__BLEIRQ void rwble_isr(void) +{ + DBG_SWDIAG(ISR, BLE, 1); + + // Loop until no more interrupts have to be handled + while (1) + { + // Check BLE interrupt status and call the appropriate handlers + uint32_t irq_stat = ble_intstat0_get(); + + if (irq_stat == 0) + break; + + // Error interrupt + if (irq_stat & BLE_ERRORINTSTAT_BIT) + { + // Clear the interrupt + ble_intack0_errorintack_clearf(1); + + BLE_ASSERT_INFO(0, ble_errortypestat_get(), (ble_errortypestat_get()>>16)); + } + } + + DBG_SWDIAG(ISR, BLE, 0); +} + +///@} RWBTINT diff --git a/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/rwip/src/rwip.c b/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/rwip/src/rwip.c new file mode 100755 index 0000000..5d0ded0 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/platform/7231n/rwip/src/rwip.c @@ -0,0 +1,616 @@ +/** +**************************************************************************************** +* +* @file rwip.c +* +* @brief RW IP SW main module +* +* Copyright (C) RivieraWaves 2009-2015 +* +* +**************************************************************************************** +*/ + +/** + **************************************************************************************** + * @addtogroup RW IP SW main module + * @ingroup ROOT + * @brief The RW IP SW main module. + * + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ + +#include "rwip_config.h" // RW SW configuration + +#include // for mem* functions +#include +#include "architect.h" // Platform architecture definition +#include "compiler.h" +#include "common_version.h" // version information +#include "common_utils.h" + +#include "rwip.h" // RW definitions +#include "rwip_int.h" // RW internal definitions + +#if (NVDS_SUPPORT) +#include "nvds.h" // NVDS definitions +#endif // NVDS_SUPPORT + +#if (BT_EMB_PRESENT) +#include "rwbt.h" // rwbt definitions +#endif //BT_EMB_PRESENT + +#if (BLE_EMB_PRESENT) +#include "rwble.h" // rwble definitions +#endif //BLE_EMB_PRESENT + +#if (BLE_HOST_PRESENT) +#include "rwble_hl.h" // BLE HL definitions +#include "gapc.h" +#include "gapm.h" +#include "gattc.h" +#include "l2cc.h" +#endif //BLE_HOST_PRESENT + +#if (BLE_APP_PRESENT) +#include "app_ble.h" // Application definitions +#endif //BLE_APP_PRESENT + +#if (BT_EMB_PRESENT) +#include "ld.h" +#endif //BT_EMB_PRESENT + +#if (BT_EMB_PRESENT || BLE_EMB_PRESENT) +#include "sch_arb.h" // Scheduling Arbiter +#include "sch_prog.h" // Scheduling Programmer +#include "sch_plan.h" // Scheduling Planner +#include "sch_slice.h" // Scheduling Slicer +#include "sch_alarm.h" // Scheduling Alarm +#endif //(BT_EMB_PRESENT || BLE_EMB_PRESENT) + +#if (BT_EMB_PRESENT || BLE_EMB_PRESENT) +#include "rf.h" // RF definitions +#endif //BT_EMB_PRESENT || BLE_EMB_PRESENT + +#if (H4TL_SUPPORT) +#include "h4tl.h" +#endif //H4TL_SUPPORT + +#if (AHI_TL_SUPPORT) +#include "ahi.h" +#endif //AHI_TL_SUPPORT + +#if (HCI_PRESENT) +#include "hci.h" // HCI definition +#endif //HCI_PRESENT + +#include "kernel.h" // kernel definition +#include "kernel_event.h" // kernel event +#include "kernel_timer.h" // definitions for timer +#include "kernel_mem.h" // kernel memory manager + +#if (BT_EMB_PRESENT || BLE_EMB_PRESENT) +#include "ecc_p256.h" // ECC P256 library +#endif // (BT_EMB_PRESENT || BLE_EMB_PRESENT) + +#include "ble_aes.h" // For AES functions + +#if (BLE_EMB_PRESENT) +#include "ble_reg_blecore.h" // ble core registers +#endif //BLE_EMB_PRESENT + +#if (BT_EMB_PRESENT) +#include "ble_reg_btcore.h" // bt core registers +#endif //BT_EMB_PRESENT + +#include "dbg.h" // debug definition + + +/* + * DEFINES + **************************************************************************************** + */ + +/// Sleep Duration Value in periodic wake-up mode +#define MAX_SLEEP_DURATION_PERIODIC_WAKEUP 0x0320 // 0.5s +/// Sleep Duration Value in external wake-up mode +#define MAX_SLEEP_DURATION_EXTERNAL_WAKEUP 0x3E80 //10s + +#if (DISPLAY_SUPPORT) +///Table of HW image names for display +static const char* plf_type[4] = +{ + "BK", + "LE", + "BT", + "DM" +}; +static const char* rf_type[6] = +{ + "NONE", + "RPLE", + "EXRC", + "ICY1", + "ICY2", + "BTPT" + }; + +/// FW type display line +#if (BT_EMB_PRESENT && BLE_EMB_PRESENT) +#define FW_TYPE_DISPLAY "FW: BTDM split emb" +#elif (BT_EMB_PRESENT) +#define FW_TYPE_DISPLAY "FW: BT split emb" +#elif (BLE_EMB_PRESENT && BLE_HOST_PRESENT) +#define FW_TYPE_DISPLAY "FW: BLE full" +#elif (BLE_EMB_PRESENT) +#define FW_TYPE_DISPLAY "FW: BLE split emb" +#else +#define FW_TYPE_DISPLAY "FW: ROM" +#endif // BT_EMB_PRESENT / BLE_EMB_PRESENT / BLE_HOST_PRESENT +#endif //DISPLAY_SUPPORT + + // Heap header size is 12 bytes + #define RWIP_HEAP_HEADER (12 / sizeof(uint32_t)) + // ceil(len/sizeof(uint32_t)) + RWIP_HEAP_HEADER + #define RWIP_CALC_HEAP_LEN(len) ((((len) + (sizeof(uint32_t) - 1)) / sizeof(uint32_t)) + RWIP_HEAP_HEADER) + // compute size of the heap block in bytes + #define RWIP_CALC_HEAP_LEN_IN_BYTES(len) (RWIP_CALC_HEAP_LEN(len) * sizeof(uint32_t)) + + +/* + * STRUCT DEFINITIONS + **************************************************************************************** + */ +#if (BLE_EMB_PRESENT || BT_EMB_PRESENT) +/// Local supported commands +const struct rwip_prio rwip_priority[RWIP_PRIO_IDX_MAX]={ + #if (BT_EMB_PRESENT) + {RWIP_PRIO_ACL_DFT, RWIP_INCR_ACL_DFT}, + {RWIP_PRIO_ACL_ACT, RWIP_INCR_ACL_ACT}, + {RWIP_PRIO_ACL_RSW, RWIP_INCR_ACL_RSW}, + {RWIP_PRIO_ACL_SNIFF_DFT, RWIP_INCR_ACL_SNIFF_DFT}, + {RWIP_PRIO_ACL_SNIFF_TRANS,RWIP_INCR_ACL_SNIFF_TRANS}, + #if MAX_NB_SYNC + {RWIP_PRIO_SCO_DFT, RWIP_INCR_SCO_DFT}, + #endif //MAX_NB_SYNC + {RWIP_PRIO_BCST_DFT, RWIP_INCR_BCST_DFT}, + {RWIP_PRIO_BCST_ACT, RWIP_INCR_BCST_ACT}, + {RWIP_PRIO_CSB_RX_DFT, RWIP_INCR_CSB_RX_DFT}, + {RWIP_PRIO_CSB_TX_DFT, RWIP_INCR_CSB_TX_DFT}, + {RWIP_PRIO_INQ_DFT, RWIP_INCR_INQ_DFT}, + {RWIP_PRIO_ISCAN_DFT, RWIP_INCR_ISCAN_DFT}, + {RWIP_PRIO_PAGE_DFT, RWIP_INCR_PAGE_DFT}, + {RWIP_PRIO_PAGE_1ST_PKT, RWIP_INCR_PAGE_1ST_PKT}, + {RWIP_PRIO_PCA_DFT, RWIP_INCR_PCA_DFT}, + {RWIP_PRIO_PSCAN_DFT, RWIP_INCR_PSCAN_DFT}, + {RWIP_PRIO_PSCAN_1ST_PKT, RWIP_INCR_PSCAN_1ST_PKT}, + {RWIP_PRIO_SSCAN_DFT, RWIP_INCR_SSCAN_DFT}, + {RWIP_PRIO_STRAIN_DFT, RWIP_INCR_STRAIN_DFT}, + #endif // #if (BT_EMB_PRESENT) + #if (BLE_EMB_PRESENT) + {RWIP_PRIO_SCAN_DFT, RWIP_INCR_SCAN_DFT}, + {RWIP_PRIO_AUX_RX_DFT, RWIP_INCR_AUX_RX_DFT}, + {RWIP_PRIO_PER_ADV_RX_DFT, RWIP_INCR_PER_ADV_RX_DFT}, + {RWIP_PRIO_INIT_DFT, RWIP_INCR_INIT_DFT}, + {RWIP_PRIO_CONNECT_DFT, RWIP_INCR_CONNECT_DFT}, + {RWIP_PRIO_CONNECT_ACT, RWIP_INCR_CONNECT_ACT}, + {RWIP_PRIO_ADV_DFT, RWIP_INCR_ADV_DFT}, + {RWIP_PRIO_ADV_HDC_DFT, RWIP_INCR_ADV_HDC_PRIO_DFT}, + {RWIP_PRIO_ADV_AUX_DFT, RWIP_INCR_ADV_AUX_DFT}, + {RWIP_PRIO_PER_ADV_DFT, RWIP_INCR_PER_ADV_DFT}, + {RWIP_PRIO_RPA_RENEW_DFT, RWIP_INCR_RPA_RENEW_DFT}, + #endif // #if (BLE_EMB_PRESENT) +}; +#endif//#if (BLE_EMB_PRESENT || BT_EMB_PRESENT) + +#if (BLE_EMB_PRESENT || BT_EMB_PRESENT) +#if (RW_WLAN_COEX || RW_MWS_COEX) +const uint8_t rwip_coex_cfg[RWIP_COEX_CFG_MAX]={ + #if (BT_EMB_PRESENT) + [RWIP_COEX_MSSWITCH_IDX] = (uint8_t)((RWIP_PTI_TXEN << RWIP_TXBSY_POS) | (RWIP_PTI_RXEN << RWIP_RXBSY_POS) | (RWIP_PTI_DNABORTDIS << RWIP_DNABORT_POS) | (RWIP_SAM_DIS << RWIP_SAMEN_POS)), + [RWIP_COEX_SNIFFATT_IDX] = (uint8_t)((RWIP_PTI_TXEN << RWIP_TXBSY_POS) | (RWIP_PTI_RXEN << RWIP_RXBSY_POS) | (RWIP_PTI_DNABORTDIS << RWIP_DNABORT_POS) | (RWIP_SAM_DIS << RWIP_SAMEN_POS)), + [RWIP_COEX_PAGE_IDX] = (uint8_t)((RWIP_PTI_TXEN << RWIP_TXBSY_POS) | (RWIP_PTI_RXEN << RWIP_RXBSY_POS) | (RWIP_PTI_DNABORTEN << RWIP_DNABORT_POS) | (RWIP_SAM_DIS << RWIP_SAMEN_POS)), + [RWIP_COEX_PSCAN_IDX] = (uint8_t)((RWIP_PTI_TXEN << RWIP_TXBSY_POS) | (RWIP_PTI_RXEN << RWIP_RXBSY_POS) | (RWIP_PTI_DNABORTDIS << RWIP_DNABORT_POS) | (RWIP_SAM_DIS << RWIP_SAMEN_POS)), + [RWIP_COEX_INQ_IDX] = (uint8_t)((RWIP_PTI_TXEN << RWIP_TXBSY_POS) | (RWIP_PTI_RXEN << RWIP_RXBSY_POS) | (RWIP_PTI_DNABORTDIS << RWIP_DNABORT_POS) | (RWIP_SAM_DIS << RWIP_SAMEN_POS)), + [RWIP_COEX_INQRES_IDX] = (uint8_t)((RWIP_PTI_TXEN << RWIP_TXBSY_POS) | (RWIP_PTI_RXEN << RWIP_RXBSY_POS) | (RWIP_PTI_DNABORTDIS << RWIP_DNABORT_POS) | (RWIP_SAM_DIS << RWIP_SAMEN_POS)), + [RWIP_COEX_SCORSVD_IDX] = (uint8_t)((RWIP_PTI_TXEN << RWIP_TXBSY_POS) | (RWIP_PTI_RXEN << RWIP_RXBSY_POS) | (RWIP_PTI_DNABORTDIS << RWIP_DNABORT_POS) | (RWIP_SAM_DIS << RWIP_SAMEN_POS)), + [RWIP_COEX_BCAST_IDX] = (uint8_t)((RWIP_PTI_TXEN << RWIP_TXBSY_POS) | (RWIP_PTI_RXEN << RWIP_RXBSY_POS) | (RWIP_PTI_DNABORTDIS << RWIP_DNABORT_POS) | (RWIP_SAM_DIS << RWIP_SAMEN_POS)), + [RWIP_COEX_CONNECT_IDX] = (uint8_t)((RWIP_PTI_TXEN << RWIP_TXBSY_POS) | (RWIP_PTI_RXEN << RWIP_RXBSY_POS) | (RWIP_PTI_DNABORTDIS << RWIP_DNABORT_POS) | (RWIP_SAM_EN << RWIP_SAMEN_POS)), + #endif // #if (BT_EMB_PRESENT) + #if (BLE_EMB_PRESENT) + [RWIP_COEX_CON_IDX] = (uint8_t)((RWIP_PTI_TXDIS << RWIP_TXBSY_POS) | (RWIP_PTI_RXDIS << RWIP_RXBSY_POS) | (RWIP_PTI_DNABORTDIS << RWIP_DNABORT_POS)), + [RWIP_COEX_CON_DATA_IDX]= (uint8_t)((RWIP_PTI_TXEN << RWIP_TXBSY_POS) | (RWIP_PTI_RXEN << RWIP_RXBSY_POS) | (RWIP_PTI_DNABORTDIS << RWIP_DNABORT_POS)), + [RWIP_COEX_ADV_IDX] = (uint8_t)((RWIP_PTI_TXEN << RWIP_TXBSY_POS) | (RWIP_PTI_RXDIS << RWIP_RXBSY_POS) | (RWIP_PTI_DNABORTDIS << RWIP_DNABORT_POS)), + [RWIP_COEX_SCAN_IDX] = (uint8_t)((RWIP_PTI_TXDIS << RWIP_TXBSY_POS) | (RWIP_PTI_RXEN << RWIP_RXBSY_POS) | (RWIP_PTI_DNABORTDIS << RWIP_DNABORT_POS)), + [RWIP_COEX_INIT_IDX] = (uint8_t)((RWIP_PTI_TXEN << RWIP_TXBSY_POS) | (RWIP_PTI_RXEN << RWIP_RXBSY_POS) | (RWIP_PTI_DNABORTDIS << RWIP_DNABORT_POS)), + #endif // #if (BLE_EMB_PRESENT) +}; +#endif //(RW_WLAN_COEX || RW_MWS_COEX) +#endif //(BLE_EMB_PRESENT || BT_EMB_PRESENT) + + +/* + * GLOBAL VARIABLES + **************************************************************************************** + */ + +/// RF API +struct rwip_rf_api rwip_rf; +/// Parameters API +struct rwip_param_api rwip_param; + +#if (BLE_EMB_PRESENT || BT_EMB_PRESENT) +/// Programming delay, margin for programming the baseband in advance of each activity (in half-slots) +uint8_t rwip_prog_delay; +#endif //(BLE_EMB_PRESENT || BT_EMB_PRESENT) + +/// Heap definitions - use uint32 to ensure that memory blocks are 32bits aligned. +/// Memory allocated for environment variables +uint32_t rwip_heap_env[RWIP_CALC_HEAP_LEN(RWIP_HEAP_ENV_SIZE)]; +#if (BLE_HOST_PRESENT) +/// Memory allocated for Attribute database +uint32_t rwip_heap_db[RWIP_CALC_HEAP_LEN(RWIP_HEAP_DB_SIZE)]; +#endif // (BLE_HOST_PRESENT) +/// Memory allocated for kernel messages +uint32_t rwip_heap_msg[RWIP_CALC_HEAP_LEN(RWIP_HEAP_MSG_SIZE)]; +/// Non Retention memory block +uint32_t rwip_heap_non_ret[RWIP_CALC_HEAP_LEN(RWIP_HEAP_NON_RET_SIZE)]; +/// IP reset state variable (@see enum rwip_init_type) +static uint8_t rwip_rst_state; + +/* + * LOCAL FUNCTION DEFINITIONS + **************************************************************************************** + */ + +#if (!NVDS_SUPPORT) +__STATIC uint8_t rwip_param_dummy_get(uint8_t param_id, uint8_t * lengthPtr, uint8_t *buf) +{ + return (PARAM_FAIL); +} +__STATIC uint8_t rwip_param_dummy_set(uint8_t param_id, uint8_t length, uint8_t *buf) +{ + return (PARAM_FAIL); +} +__STATIC uint8_t rwip_param_dummy_del(uint8_t param_id) +{ + return (PARAM_FAIL); +} +#endif // (!NVDS_SUPPORT) + + + +/* + * EXPORTED FUNCTION DEFINITIONS + **************************************************************************************** + */ + +void rwip_init(uint32_t error) +{ + // IP initialization + rwip_rst_state = RWIP_INIT; + #if (NVDS_SUPPORT) + // Point to NVDS for parameters get/set + rwip_param.get = nvds_get; + rwip_param.set = nvds_put; + rwip_param.del = nvds_del; + #else // (NVDS_SUPPORT) + // !! Need to point to some parameter configuration system + BLE_ASSERT_WARN(GAIA_SUPPORT, 0, 0); + rwip_param.get = rwip_param_dummy_get; + rwip_param.set = rwip_param_dummy_set; + rwip_param.del = rwip_param_dummy_del; + #endif // (NVDS_SUPPORT) + + // Initialize kernel + kernel_init(); + + // Initialize memory heap used by kernel. + // Memory allocated for environment variables + kernel_mem_init(KERNEL_MEM_ENV, (uint8_t*)rwip_heap_env, RWIP_CALC_HEAP_LEN_IN_BYTES(RWIP_HEAP_ENV_SIZE)); + #if (BLE_HOST_PRESENT) + // Memory allocated for Attribute database + kernel_mem_init(KERNEL_MEM_ATT_DB, (uint8_t*)rwip_heap_db, RWIP_CALC_HEAP_LEN_IN_BYTES(RWIP_HEAP_DB_SIZE)); + #endif // (BLE_HOST_PRESENT) + // Memory allocated for kernel messages + kernel_mem_init(KERNEL_MEM_KERNEL_MSG, (uint8_t*)rwip_heap_msg, RWIP_CALC_HEAP_LEN_IN_BYTES(RWIP_HEAP_MSG_SIZE)); + // Non Retention memory block + kernel_mem_init(KERNEL_MEM_NON_RETENTION, (uint8_t*)rwip_heap_non_ret, RWIP_CALC_HEAP_LEN_IN_BYTES(RWIP_HEAP_NON_RET_SIZE)); + + #if (BT_EMB_PRESENT || BLE_EMB_PRESENT) + #if (RW_DEBUG) + // Initialize the debug process + dbg_init(rwip_rst_state); + #endif //(RW_DEBUG) + #endif //(BT_EMB_PRESENT || BLE_EMB_PRESENT) + + // Initialize RF + #if (BT_EMB_PRESENT || BLE_EMB_PRESENT) + rf_init(&rwip_rf); + #endif //BT_EMB_PRESENT || BLE_EMB_PRESENT + + #if (CFG_ECC_P256_ACC) + #if (BT_EMB_PRESENT || BLE_EMB_PRESENT) + // Initialize Diffie Hellman Elliptic Curve Algorithm + ecc_init(rwip_rst_state); + #endif // (BT_EMB_PRESENT || BLE_EMB_PRESENT) + #endif // (CFG_ECC_P256_ACC) + + // Initialize H4TL + #if (H4TL_SUPPORT) + #if (H4TL_NB_CHANNEL > 1) + h4tl_init(1, rwip_eif_get(1)); + //uart_printf("h4tl_init ok\r\n"); + #endif // (H4TL_NB_CHANNEL > 1) + h4tl_init(0, rwip_eif_get(0)); + //uart_printf("h4tl_init-1 ok\r\n"); + #endif //(H4TL_SUPPORT) + + #if (CFG_USE_BK_HOST) + #if (HCI_PRESENT) + // Initialize the HCI + hci_init(rwip_rst_state); + //uart_printf("hci_init ok\r\n"); + #endif //HCI_PRESENT + #endif + + #if (AHI_TL_SUPPORT) + // Initialize the Application Host Interface + ahi_init(); + //uart_printf("ahi_init ok\r\n"); + #endif //AHI_TL_SUPPORT + + #if (BLE_HOST_PRESENT) + // Initialize BLE Host stack + rwble_hl_init(rwip_rst_state); + //uart_printf("rwble_hl_init ok\r\n"); + #endif //BLE_HOST_PRESENT + + #if (BT_EMB_PRESENT) + // Initialize BT + rwbt_init(); + //uart_printf("rwbt_init ok\r\n"); + #endif //BT_EMB_PRESENT + + #if (BLE_EMB_PRESENT) + // Initialize BLE + rwble_init(rwip_rst_state); + //uart_printf("rwble_init ok\r\n"); + #endif //BLE_EMB_PRESENT + + // Initialize IP core driver + rwip_driver_init(rwip_rst_state); + //uart_printf("rwip_driver_init ok\r\n"); + + #if (BT_EMB_PRESENT || BLE_EMB_PRESENT) + #if (RW_WLAN_COEX) + rwip_wlcoex_set(1); + //uart_printf("rwip_wlcoex_set ok\r\n"); + #endif //(RW_WLAN_COEX) + #endif //(BT_EMB_PRESENT || BLE_EMB_PRESENT) + + #if (BT_EMB_PRESENT || (BLE_EMB_PRESENT && !BLE_HOST_PRESENT)) + // If FW initializes due to FW reset, send the message to Host + if(error != RESET_NO_ERROR) + { + uart_printf("@@error(%x)\r\n",error); + if(error == RESET_TO_ROM || error == RESET_AND_LOAD_FW) + { + // Send platform reset command complete if requested by user + + } + else + { + // Allocate a message structure for hardware error event + struct hci_hw_err_evt *evt = KERNEL_MSG_ALLOC(HCI_EVENT, 0, HCI_HW_ERR_EVT_CODE, hci_hw_err_evt); + + // Fill the HW error code + switch(error) + { + case RESET_MEM_ALLOC_FAIL: evt->hw_code = COMMON_ERROR_HW_MEM_ALLOC_FAIL; break; + default: BLE_ASSERT_INFO(0, error, 0); break; + } + + // Send the message + hci_send_2_host(evt); + } + } + #endif //(BT_EMB_PRESENT || (BLE_EMB_PRESENT && !BLE_HOST_PRESENT)) + + /* + ************************************************************************************ + * Application initialization + ************************************************************************************ + */ + #if (BLE_APP_PRESENT) + // Initialize APP + // TODO + appm_init(); + #endif //BLE_APP_PRESENT + + // Move to IP first reset state + rwip_rst_state = RWIP_1ST_RST; + + #if ((!BLE_HOST_PRESENT && BLE_EMB_PRESENT) || BT_EMB_PRESENT) + // Make a full initialization in split-emb mode + rwip_reset(); + #endif // ((!BLE_HOST_PRESENT && BLE_EMB_PRESENT) || BT_EMB_PRESENT) +} + +void rwip_reset(void) +{ + // Disable interrupts until reset procedure is completed + GLOBAL_INT_DIS(); + + #if (BT_EMB_PRESENT || BLE_EMB_PRESENT) + #if (RW_DEBUG) + // Reset dbg + dbg_init(rwip_rst_state); + #endif //(RW_DEBUG) + #endif //(BT_EMB_PRESENT || BLE_EMB_PRESENT) + + //Clear all message and timer pending + kernel_flush(); + + #if (CFG_ECC_P256_ACC) + #if (BT_EMB_PRESENT || BLE_EMB_PRESENT) + // Reset Diffie Hellman Elliptic Curve Algorithm + ecc_init(rwip_rst_state); + #endif // (BT_EMB_PRESENT || BLE_EMB_PRESENT) + #endif // (CFG_ECC_P256_ACC) + + #if (CFG_USE_BK_HOST) + #if (HCI_PRESENT) + // Reset the HCI + hci_init(rwip_rst_state); + #endif //HCI_PRESENT + #endif + + #if (BLE_HOST_PRESENT) + // Initialize BLE Host stack + rwble_hl_init(rwip_rst_state); + #endif //BLE_HOST_PRESENT + + #if (BT_EMB_PRESENT) + if (rwip_rst_state == RWIP_RST) + { + // Reset BT + rwbt_reset(); + } + #endif //BT_EMB_PRESENT + + #if (BLE_EMB_PRESENT) + // Reset BLE + rwble_init(rwip_rst_state); + #endif //BLE_EMB_PRESENT + + // Reset AES + ble_aes_init(rwip_rst_state); + + #if (BT_EMB_PRESENT || BLE_EMB_PRESENT) + // Reset Scheduling blocks + sch_arb_init(rwip_rst_state); + sch_prog_init(rwip_rst_state); + sch_plan_init(rwip_rst_state); + sch_alarm_init(rwip_rst_state); + sch_slice_init(rwip_rst_state); + #endif //(BT_EMB_PRESENT || BLE_EMB_PRESENT) + + #if (BLE_EMB_PRESENT || BT_EMB_PRESENT) + // Initialize IP core driver + rwip_driver_init(rwip_rst_state); + #endif // (BLE_EMB_PRESENT || BT_EMB_PRESENT) + + #if (BT_EMB_PRESENT || BLE_EMB_PRESENT) + #if (RW_WLAN_COEX) + rwip_wlcoex_set(1); + #endif //(RW_WLAN_COEX) + + + if (rwip_rst_state == RWIP_RST) + { + // Reset the RF + rwip_rf.reset(); + } + #endif //(BT_EMB_PRESENT || BLE_EMB_PRESENT) + // Move to normal IP reset state + rwip_rst_state = RWIP_RST; + + // Restore interrupts once reset procedure is completed + GLOBAL_INT_RES(); +} + +extern void ble_set_ext_wkup(uint8_t enable); + +void rwip_schedule(void) +{ + #if (BLE_EMB_PRESENT || BT_EMB_PRESENT) + // If system is waking up, delay the handling up to the Bluetooth clock is available and corrected + if ((rwip_env.prevent_sleep & (RW_WAKE_UP_ONGOING | RW_DEEP_SLEEP)) == 0) + #endif // (BLE_EMB_PRESENT || BT_EMB_PRESENT) + { + // schedule all pending events + kernel_event_schedule(); + } + #if CFG_USE_BK_HOST == 0 + else if (((rwip_env.prevent_sleep & RW_DEEP_SLEEP) == RW_DEEP_SLEEP) + && (!kernel_sleep_check())) { + ble_set_ext_wkup(1); + } + #endif +} + +#if (BT_EMB_PRESENT) +#if PCA_SUPPORT +bool rwip_pca_clock_dragging_only(void) +{ +#if (BLE_EMB_PRESENT) + return rwble_activity_ongoing_check(); +#else + return false; +#endif // BLE_EMB_PRESENT +} +#endif // PCA_SUPPORT +#endif // BT_EMB_PRESENT + +#if (BT_EMB_PRESENT || BLE_EMB_PRESENT) +#if (RW_MWS_COEX) +void rwip_mwscoex_set(bool state) +{ +#if (BT_EMB_PRESENT) + if (state) + { + bt_coexifcntl0_mwswci_en_setf(0); + bt_coexifcntl0_mwscoex_en_setf(1); + } + else + { + bt_coexifcntl0_mwswci_en_setf(0); + bt_coexifcntl0_mwscoex_en_setf(0); + } +#endif // BT_EMB_PRESENT +} +#endif // RW_MWS_COEX +#if (RW_WLAN_COEX) +void rwip_wlcoex_set(bool state) +{ +#if (BLE_EMB_PRESENT) + if (state) + { + ble_coexifcntl0_syncgen_en_setf(1); + ble_coexifcntl0_wlancoex_en_setf(1); + } + else + { + ble_coexifcntl0_syncgen_en_setf(0); + ble_coexifcntl0_wlancoex_en_setf(0); + } +#endif // BLE_EMB_PRESENT +} +#endif // RW_WLAN_COEX +#endif // (BT_EMB_PRESENT || BLE_EMB_PRESENT) + +#if RW_DEBUG +void rwip_assert(const char * file, int line, int param0, int param1, uint8_t type) +{ + #if (BT_EMB_PRESENT || (BLE_EMB_PRESENT && !BLE_HOST_PRESENT)) + struct hci_dbg_assert_evt *evt = KERNEL_MSG_ALLOC_DYN(HCI_DBG_EVT, 0, 0, hci_dbg_assert_evt, sizeof(struct hci_dbg_assert_evt) + strlen(file)); + evt->subcode = HCI_DBG_ASSERT_EVT_SUBCODE; + evt->type = type; + evt->line = line; + evt->param0 = param0; + evt->param1 = param1; + strcpy((char *) evt->file, file); + hci_send_2_host(evt); + #endif //(BT_EMB_PRESENT || (BLE_EMB_PRESENT && !BLE_HOST_PRESENT)) +} +#endif //RW_DEBUG + +///@} RW + diff --git a/beken_os/beken378/driver/ble_5_x_rw/replace.sh b/beken_os/beken378/driver/ble_5_x_rw/replace.sh new file mode 100755 index 0000000..335c443 --- /dev/null +++ b/beken_os/beken378/driver/ble_5_x_rw/replace.sh @@ -0,0 +1,62 @@ +#!/bin/sh +set -v +find . -name *.h | xargs sed -i 's/\\)/ble_\1/g' +find . -name *.c | xargs sed -i 's/\(\\)/ble_\1/g' +find . -name *.h | xargs sed -i 's/ke\.h/kernel\.h/g' +find . -name *.c | xargs sed -i 's/ke\.h/kernel\.h/g' +find . -name *.h | xargs sed -i 's/\GPIONUM) + return; + gpio_cfg_addr = (volatile UINT32 *)(REG_GPIO_CFG_BASE_ADDR + index * 4); + tmp =mode; + mode &= 0xff; + + if(mode == 1) + val =0x0c; + else + { + val = 0x30; + if(tmp>>8) + val |= 1<<1; + } + REG_WRITE(gpio_cfg_addr, val); +} + + + +static void gpio_output_c(UINT32 index, UINT32 val) +{ + UINT32 reg_val; + volatile UINT32 *gpio_cfg_addr; + + gpio_cfg_addr = (volatile UINT32 *)(REG_GPIO_CFG_BASE_ADDR + index * 4); + reg_val = REG_READ(gpio_cfg_addr); + + reg_val &= ~GCFG_OUTPUT_BIT; + reg_val |= (val & 0x01) << GCFG_OUTPUT_POS; + REG_WRITE(gpio_cfg_addr, reg_val); +} + +static UINT32 DATA_INPUT(void) +{ + UINT32 val = 0; + volatile UINT32 *gpio_cfg_addr; + + gpio_cfg_addr = (volatile UINT32 *)(REG_GPIO_CFG_BASE_ADDR + I2C_DAT * 4); + val = REG_READ(gpio_cfg_addr); + + return (val & 1); +} + + +static void CLK_OUTPUT_HIGH(void) +{ + gpio_output_c(I2C_CLK,1); +} +static void CLK_OUTPUT_LOW(void) +{ + gpio_output_c(I2C_CLK,0); +} + +static void DATA_OUTPUT_HIGH(void) +{ + gpio_output_c(I2C_DAT,1); +} + +static void DATA_OUTPUT_LOW(void) +{ + gpio_output_c(I2C_DAT,0); +} + +static void SET_DATA_INPUT(void) +{ + gpio_config_c(I2C_DAT,1); +} + +static void set_data_output(void) +{ + UINT32 mode; + UINT32 val = DATA_INPUT(); + mode = (val<<8) ; + gpio_config_c(I2C_DAT,mode); +} + +/*1 equals about 5 us*/ +static void es8374_codec_i2c_delay(int us) +{ + volatile int i, j; + for(i = 0; i < us; i++) + { + j = 50; + while(j--); + } +} + +static void es8374_codec_i2c_start(void) +{ + // start bit + CLK_OUTPUT_HIGH(); + DATA_OUTPUT_HIGH(); + es8374_codec_i2c_delay(1); + DATA_OUTPUT_LOW(); + es8374_codec_i2c_delay(1); +} + +static void es8374_codec_i2c_stop(void) +{ + //stop bit + CLK_OUTPUT_LOW(); + es8374_codec_i2c_delay(1); + CLK_OUTPUT_HIGH(); + es8374_codec_i2c_delay(1); + DATA_OUTPUT_HIGH(); + es8374_codec_i2c_delay(1); +} + + +static void es8374_codec_i2c_write_byte(unsigned char data) +{ + int i; + + //data 0-7bit + for(i = 7; i >= 0; i--) + { + CLK_OUTPUT_LOW(); + if(data & (0x1 << i)) // msb first, rising change and falling lock in codec + DATA_OUTPUT_HIGH(); + else + DATA_OUTPUT_LOW(); + es8374_codec_i2c_delay(1); + CLK_OUTPUT_HIGH(); + es8374_codec_i2c_delay(1); + } + //receive ack, bit9 + CLK_OUTPUT_LOW(); + SET_DATA_INPUT(); + + es8374_codec_i2c_delay(1); + + CLK_OUTPUT_HIGH(); + es8374_codec_i2c_delay(1); + set_data_output(); +} + +static void I2CWRNBYTE_CODEC(unsigned char reg, unsigned char val) +{ + UINT8 i2c_address = 0x20; + + es8374_codec_i2c_start(); + es8374_codec_i2c_write_byte(i2c_address); + es8374_codec_i2c_write_byte(reg); + es8374_codec_i2c_write_byte(val); + es8374_codec_i2c_stop(); +} + + +static void es8374_dac_mute(BOOL mute) +{ + if(mute)//mute dac + I2CWRNBYTE_CODEC(0x36, 0x20); + else //unmute + I2CWRNBYTE_CODEC(0x36, 0x00); +} + +static void es8374_dac_volume(unsigned char vol) +{ + unsigned int vol_tmp; + if(vol < 100) + { // 99 is the maximum volume, 0 is the minimum volume + vol_tmp = (99 - vol)*2; + I2CWRNBYTE_CODEC(0x38, vol_tmp); + } +} + +static void es8374_set_sample_rate(unsigned int sr) +{ + switch(sr) + { + case 8000: + /* + * set pll, 26MHZ->12.288MHZ + */ + es8374_dac_mute(1); + I2CWRNBYTE_CODEC(0x09,0x01); //pll set:reset on ,set start + + I2CWRNBYTE_CODEC(0x0C,0x17); //pll set:k + I2CWRNBYTE_CODEC(0x0D,0xA3); //pll set:k + I2CWRNBYTE_CODEC(0x0E,0x2F); //pll set:k + I2CWRNBYTE_CODEC(0x0A,0x8A); //pll set: + I2CWRNBYTE_CODEC(0x0B,0x07); //pll set:n + + I2CWRNBYTE_CODEC(0x09,0x41); //pll set:reset off ,set stop + + I2CWRNBYTE_CODEC(0x05, 0x66);//adc&dac clkdiv + I2CWRNBYTE_CODEC(0x02, 0x08);//pll enable + I2CWRNBYTE_CODEC(0x06, 0x06); //LRCK div =0600H = 1536D, lrck = 12.288M/1536 = 8K + I2CWRNBYTE_CODEC(0x07, 0x00); + I2CWRNBYTE_CODEC(0x0f, 0x95); //bclk = mclk/ 24 = 512K +// es8374_dac_mute(0); + break; + + case 16000: + /* + * set pll, 26MHZ->12.288MHZ + */ + es8374_dac_mute(1); + I2CWRNBYTE_CODEC(0x09,0x01); //pll set:reset on ,set start + + I2CWRNBYTE_CODEC(0x0C,0x17); //pll set:k + I2CWRNBYTE_CODEC(0x0D,0xA3); //pll set:k + I2CWRNBYTE_CODEC(0x0E,0x2F); //pll set:k + I2CWRNBYTE_CODEC(0x0A,0x8A); //pll set: + I2CWRNBYTE_CODEC(0x0B,0x07); //pll set:n + + I2CWRNBYTE_CODEC(0x09,0x41); //pll set:reset off ,set stop + + I2CWRNBYTE_CODEC(0x05, 0x33);//adc&dac clkdiv + I2CWRNBYTE_CODEC(0x02, 0x08);//pll enable + I2CWRNBYTE_CODEC(0x06, 0x03); //LRCK div =0300H = 768D, lrck = 12.288M/768 = 16K + I2CWRNBYTE_CODEC(0x07, 0x00); + I2CWRNBYTE_CODEC(0x0f, 0x8C); //bclk = mclk/ 12 = 1.024M + // es8374_dac_mute(0); + break; + + + case 24000: + /* + * set pll, 26MHZ->12.288MHZ + */ + es8374_dac_mute(1); + I2CWRNBYTE_CODEC(0x09,0x01); //pll set:reset on ,set start + + I2CWRNBYTE_CODEC(0x0C,0x17); //pll set:k + I2CWRNBYTE_CODEC(0x0D,0xA3); //pll set:k + I2CWRNBYTE_CODEC(0x0E,0x2F); //pll set:k + I2CWRNBYTE_CODEC(0x0A,0x8A); //pll set: + I2CWRNBYTE_CODEC(0x0B,0x07); //pll set:n + + I2CWRNBYTE_CODEC(0x09,0x41); //pll set:reset off ,set stop + + I2CWRNBYTE_CODEC(0x05, 0x22);//adc&dac clkdiv + I2CWRNBYTE_CODEC(0x02, 0x08);//pll enable + I2CWRNBYTE_CODEC(0x06, 0x02); //LRCK div =0200H = 412D, lrck = 12.288M/412 = 24K + I2CWRNBYTE_CODEC(0x07, 0x00); + I2CWRNBYTE_CODEC(0x0f, 0x88); //bclk = mclk/ 8 = 1.536M +// es8374_dac_mute(0); + break; + + + case 32000: + /* + * set pll, 26MHZ->8.192MHZ + */ + es8374_dac_mute(1); + I2CWRNBYTE_CODEC(0x09,0x01); //pll set:reset on ,set start + + I2CWRNBYTE_CODEC(0x0C,0x01); //pll set:k + I2CWRNBYTE_CODEC(0x0D,0xBC); //pll set:k + I2CWRNBYTE_CODEC(0x0E,0x11); //pll set:k + I2CWRNBYTE_CODEC(0x0A,0x8A); //pll set: + I2CWRNBYTE_CODEC(0x0B,0x05); //pll set:n + + I2CWRNBYTE_CODEC(0x09,0x41); //pll set:reset off ,set stop + + I2CWRNBYTE_CODEC(0x05, 0x11);//adc&dac clkdiv + I2CWRNBYTE_CODEC(0x02, 0x08);//pll enable + I2CWRNBYTE_CODEC(0x06, 0x01); //LRCK div =0100H = 256D, lrck =8.192M/256 = 32K + I2CWRNBYTE_CODEC(0x07, 0x00); + I2CWRNBYTE_CODEC(0x0f, 0x84); //bclk = mclk/ 4 = 3..072M +// es8374_dac_mute(0); + break; + + + case 48000: + /* + * set pll, 26MHZ->12.288MHZ + */ + es8374_dac_mute(1); + I2CWRNBYTE_CODEC(0x09,0x01); //pll set:reset on ,set start + + I2CWRNBYTE_CODEC(0x0C,0x17); //pll set:k + I2CWRNBYTE_CODEC(0x0D,0xA3); //pll set:k + I2CWRNBYTE_CODEC(0x0E,0x2F); //pll set:k + I2CWRNBYTE_CODEC(0x0A,0x8A); //pll set: + I2CWRNBYTE_CODEC(0x0B,0x07); //pll set:n + + I2CWRNBYTE_CODEC(0x09,0x41); //pll set:reset off ,set stop + + I2CWRNBYTE_CODEC(0x05, 0x11);//adc&dac clkdiv + I2CWRNBYTE_CODEC(0x02, 0x08);//pll enable + I2CWRNBYTE_CODEC(0x06, 0x01); //LRCK div =0100H = 256D, lrck =12.288M/256 = 48K + I2CWRNBYTE_CODEC(0x07, 0x00); + I2CWRNBYTE_CODEC(0x0f, 0x84); //bclk = mclk/ 8 = 3.072M + // es8374_dac_mute(0); + break; + + case 44100: + /* + * set pll, 26MHZ->11.2896MHZ + */ + es8374_dac_mute(1); + I2CWRNBYTE_CODEC(0x6F,0xA0); //pll set:mode enable + I2CWRNBYTE_CODEC(0x72,0x41); //pll set:mode set + + I2CWRNBYTE_CODEC(0x09,0x01); //pll set:reset on ,set start + + I2CWRNBYTE_CODEC(0x0C,0x27); //pll set:k + I2CWRNBYTE_CODEC(0x0D,0xDC); //pll set:k + I2CWRNBYTE_CODEC(0x0E,0x2B); //pll set:k + I2CWRNBYTE_CODEC(0x0A,0x8A); //pll set: + I2CWRNBYTE_CODEC(0x0B,0x06);//pll set:n + + I2CWRNBYTE_CODEC(0x09,0x41); //pll set:reset off ,set stop + + I2CWRNBYTE_CODEC(0x05, 0x11);//adc&dac clkdiv + I2CWRNBYTE_CODEC(0x02, 0x08);//pll enable + I2CWRNBYTE_CODEC(0x06, 0x01); //LRCK div =0100H = 256D, lrck =11.2896M/256 = 44.1K + I2CWRNBYTE_CODEC(0x07, 0x00); + I2CWRNBYTE_CODEC(0x0f, 0x84); //bclk = mclk/ 4 = 2.828M +// es8374_dac_mute(0); + break; + + case 22050: + /* + * set pll, 26MHZ->11.2896MHZ + */ + es8374_dac_mute(1); + I2CWRNBYTE_CODEC(0x09,0x01); //pll set:reset on ,set start + + I2CWRNBYTE_CODEC(0x0C,0x27); //pll set:k + I2CWRNBYTE_CODEC(0x0D,0xDC); //pll set:k + I2CWRNBYTE_CODEC(0x0E,0x2B); //pll set:k + I2CWRNBYTE_CODEC(0x0A,0x8A); //pll set: + I2CWRNBYTE_CODEC(0x0B,0x06);//pll set:n + + I2CWRNBYTE_CODEC(0x09,0x41); //pll set:reset off ,set stop + + I2CWRNBYTE_CODEC(0x05, 0x22);//adc&dac clkdiv + I2CWRNBYTE_CODEC(0x02, 0x08);//pll enable + I2CWRNBYTE_CODEC(0x06, 0x02); //LRCK div =0200H = 512D, lrck =11.2896M/512 = 22.05K + I2CWRNBYTE_CODEC(0x07, 0x00); + I2CWRNBYTE_CODEC(0x0f, 0x88); //bclk = mclk/ 8 = 1.414m +// es8374_dac_mute(0); + break; + + case 11025: + /* + * set pll, 26MHZ->11.2896MHZ + */ + es8374_dac_mute(1); + I2CWRNBYTE_CODEC(0x09,0x01); //pll set:reset on ,set start + + I2CWRNBYTE_CODEC(0x0C,0x27); //pll set:k + I2CWRNBYTE_CODEC(0x0D,0xDC); //pll set:k + I2CWRNBYTE_CODEC(0x0E,0x2B); //pll set:k + I2CWRNBYTE_CODEC(0x0A,0x8A); //pll set: + I2CWRNBYTE_CODEC(0x0B,0x06);//pll set:n + + I2CWRNBYTE_CODEC(0x09,0x41); //pll set:reset off ,set stop + + I2CWRNBYTE_CODEC(0x05, 0x44);//adc&dac clkdiv + I2CWRNBYTE_CODEC(0x02, 0x08);//pll enable + I2CWRNBYTE_CODEC(0x06, 0x04); //LRCK div =0400H = 1024D, lrck =11.2896M/1024 = 11.025K + I2CWRNBYTE_CODEC(0x07, 0x00); + I2CWRNBYTE_CODEC(0x0f, 0x8C); //bclk = mclk/ 12 = 705K +// es8374_dac_mute(0); + break; + + default: + break; + } +} + + +static void es8374_standby(void) +{ + I2CWRNBYTE_CODEC(0x38,0xC0); + I2CWRNBYTE_CODEC(0x25,0xC0); + I2CWRNBYTE_CODEC(0x28,0x1C); + I2CWRNBYTE_CODEC(0x36,0x20); + I2CWRNBYTE_CODEC(0x37,0x01); + I2CWRNBYTE_CODEC(0x1A,0x08); + I2CWRNBYTE_CODEC(0x1D,0x10); + I2CWRNBYTE_CODEC(0x1E,0x40); + I2CWRNBYTE_CODEC(0x1C,0x10); + I2CWRNBYTE_CODEC(0x24,0x20); + I2CWRNBYTE_CODEC(0x22,0x00); + I2CWRNBYTE_CODEC(0x21,0xD4); + I2CWRNBYTE_CODEC(0x14,0x94); + I2CWRNBYTE_CODEC(0x15,0xBF); + I2CWRNBYTE_CODEC(0x09,0x80); + I2CWRNBYTE_CODEC(0x01,0xFF); + I2CWRNBYTE_CODEC(0x01,0x03); +} + + +static void ES8374_CODEC_Startup(void) +{ + I2CWRNBYTE_CODEC(0x00,0x3F); //IC Rst start + I2CWRNBYTE_CODEC(0x00,0x03); //IC Rst stop + I2CWRNBYTE_CODEC(0x01,0xFF); //IC clk on + I2CWRNBYTE_CODEC(0x05,0x11); //clk div =1 + I2CWRNBYTE_CODEC(0x6F,0xA0); //pll set:mode enable + I2CWRNBYTE_CODEC(0x72,0x41); //pll set:mode set + I2CWRNBYTE_CODEC(0x09,0x01); //pll set:reset on ,set start + /* PLL FOR 26MHZ/44.1KHZ */ + I2CWRNBYTE_CODEC(0x0C,0x27); //pll set:k + I2CWRNBYTE_CODEC(0x0D,0xDC); //pll set:k + I2CWRNBYTE_CODEC(0x0E,0x2B); //pll set:k + I2CWRNBYTE_CODEC(0x0A,0x88); //pll set: + I2CWRNBYTE_CODEC(0x0B,0x06); //pll set:n + + I2CWRNBYTE_CODEC(0x09,0x41); //pll set:reset off ,set stop + I2CWRNBYTE_CODEC(0x0F,0x84); //MASTER MODE, BCLK = MCLK/4 + I2CWRNBYTE_CODEC(0x10,0x0C); //I2S-16BIT, ADC + I2CWRNBYTE_CODEC(0x11,0x0C); //I2S-16BIT, DAC + I2CWRNBYTE_CODEC(0x02,0x08); //select PLL + + + I2CWRNBYTE_CODEC(0x24,0x08); //adc set + I2CWRNBYTE_CODEC(0x36,0x40); //dac set + I2CWRNBYTE_CODEC(0x12,0x30); //timming set + I2CWRNBYTE_CODEC(0x13,0x20); //timming set + I2CWRNBYTE_CODEC(0x21,0x50); //adc set: SEL LIN1 CH+PGAGAIN=0DB + I2CWRNBYTE_CODEC(0x22,0xFF); //adc set: PGA GAIN=0DB + I2CWRNBYTE_CODEC(0x21,0x14); //adc set: SEL LIN1 CH+PGAGAIN=18DB + I2CWRNBYTE_CODEC(0x22,0x55); //pga = +15db + I2CWRNBYTE_CODEC(0x00,0x80); // IC START + vTaskDelay(25); //DELAY_MS + I2CWRNBYTE_CODEC(0x14,0x8A); // IC START + I2CWRNBYTE_CODEC(0x15,0x40); // IC START + I2CWRNBYTE_CODEC(0x1A,0xA0); // monoout set + I2CWRNBYTE_CODEC(0x1B,0x19); // monoout set + I2CWRNBYTE_CODEC(0x1C,0x90); // spk set + I2CWRNBYTE_CODEC(0x1D,0x02); // spk set + I2CWRNBYTE_CODEC(0x1F,0x00); // spk set + I2CWRNBYTE_CODEC(0x1E,0xA0); // spk on + I2CWRNBYTE_CODEC(0x28,0x00); // alc set + I2CWRNBYTE_CODEC(0x25,0x00); // ADCVOLUME on + I2CWRNBYTE_CODEC(0x38,0x0c); // DACVOLUMEL on + I2CWRNBYTE_CODEC(0x37,0x30); // dac set + I2CWRNBYTE_CODEC(0x6D,0x60); //SEL:GPIO1=DMIC CLK OUT+SEL:GPIO2=PLL CLK OUT + + I2CWRNBYTE_CODEC(0x36,0x20); //dac set + I2CWRNBYTE_CODEC(0x37,0x00); // dac set +} + +void es8374_codec_init(void) +{ + gpio_config_c(I2C_CLK,0); + gpio_config_c(I2C_DAT,0); + CLK_OUTPUT_HIGH(); + DATA_OUTPUT_HIGH(); + es8374_codec_i2c_delay(1); + ES8374_CODEC_Startup(); +} + +void es8374_codec_configure(unsigned int fs, unsigned char datawidth) +{ + es8374_set_sample_rate(fs); +} + +void es8374_codec_close(void) +{ + es8374_standby(); +} + +void es8374_codec_volume_control(unsigned char volume) +{ + es8374_dac_volume(volume); +} + +void es8374_codec_mute_control(BOOL enable) +{ + es8374_dac_mute(enable); +} +#endif diff --git a/beken_os/beken378/driver/codec/driver_codec_es8374.h b/beken_os/beken378/driver/codec/driver_codec_es8374.h new file mode 100755 index 0000000..ac1d2cd --- /dev/null +++ b/beken_os/beken378/driver/codec/driver_codec_es8374.h @@ -0,0 +1,8 @@ +#ifndef _DRIVER_CODEC_ES8328_H_ +#define _DRIVER_CODEC_ES8328_H_ + + + + + +#endif diff --git a/beken_os/beken378/driver/common/compiler.h b/beken_os/beken378/driver/common/compiler.h new file mode 100755 index 0000000..d6222c0 --- /dev/null +++ b/beken_os/beken378/driver/common/compiler.h @@ -0,0 +1,53 @@ +/** + **************************************************************************************** + * + * @file gnuarm/compiler.h + * + * @brief Definitions of compiler specific directives. + * + * Copyright (C) RivieraWaves 2011-2016 + * + **************************************************************************************** + */ + +#ifndef _COMPILER_H_ +#define _COMPILER_H_ + +/// define the force inlining attribute for this compiler gcc: __attribute__((always_inline)) +#define __INLINE static inline + +/// function returns struct in registers (4 words max, var with gnuarm) +#define __VIR __value_in_regs + +/// function has no side effect and return depends only on arguments +#define __PURE __pure + +/// Align instantiated lvalue or struct member on 4 bytes +#define __ALIGN4 __attribute__((aligned(4))) + +#define __MODULE__ __BASE_FILE__ + +/// define the BLE IRQ handler attribute for this compiler +#define __BLEIRQ + +/// define size of an empty array (used to declare structure with an array size not defined) +#define __ARRAY_EMPTY + +/// define the static keyword for this compiler +#define __STATIC static + +/// Pack a structure field +#define __PACKED16 __attribute__( ( packed ) ) +#define __PACKED __attribute__( ( packed ) ) + +#if !defined(__SECTION) +#define __SECTION(x) __attribute__((section(x))) +#endif + +#ifndef likely +#define likely(x) __builtin_expect(!!(x), 1) +#define unlikely(x) __builtin_expect(!!(x), 0) +#endif + +#endif // _COMPILER_H_ + diff --git a/beken_os/beken378/driver/common/dd.c b/beken_os/beken378/driver/common/dd.c new file mode 100755 index 0000000..18b4077 --- /dev/null +++ b/beken_os/beken378/driver/common/dd.c @@ -0,0 +1,170 @@ +#include "include.h" +#include "arm_arch.h" + +#include "dd_pub.h" + +#include "sdio_pub.h" +#include "sys_ctrl_pub.h" +#include "uart_pub.h" +#include "gpio_pub.h" +#include "icu_pub.h" +#include "wdt_pub.h" +#include "usb_pub.h" +#include "pwm_pub.h" +#include "flash_pub.h" +#include "spi_pub.h" +#include "fft_pub.h" +#include "i2s_pub.h" +#include "saradc_pub.h" +#include "irda_pub.h" +#include "mac_phy_bypass_pub.h" +#include "bk_timer_pub.h" + +#if CFG_USE_CAMERA_INTF +#include "jpeg_encoder_pub.h" +#include "i2c_pub.h" +#endif + +#if CFG_USE_AUDIO +#include "audio_pub.h" +#endif + +#if CFG_USE_SPIDMA +#include "spidma_pub.h" +#endif + +#if CFG_GENERAL_DMA +#include "general_dma_pub.h" +#endif + +#if CFG_USE_SDCARD_HOST +#include "sdcard_pub.h" +#endif + +#if CFG_USE_STA_PS +#include "power_save_pub.h" +#endif + +#ifdef CFG_SUPPORT_BLE +#include "ble_pub.h" +#endif + +static DD_INIT_S dd_init_tbl[] = +{ + /* name*/ /* init function*/ /* exit function*/ + {SCTRL_DEV_NAME, sctrl_init, sctrl_exit}, + {ICU_DEV_NAME, icu_init, icu_exit}, + {WDT_DEV_NAME, wdt_init, wdt_exit}, + {GPIO_DEV_NAME, gpio_init, gpio_exit}, + +#ifndef KEIL_SIMULATOR + {UART2_DEV_NAME, uart2_init, uart2_exit}, +#endif + +#if CFG_USE_UART1 + {UART1_DEV_NAME, uart1_init, uart1_exit}, +#endif + + {FLASH_DEV_NAME, flash_init, flash_exit}, + +#if CFG_GENERAL_DMA + {GDMA_DEV_NAME, gdma_init, gdma_exit}, +#endif + +#if CFG_USE_SPIDMA + {SPIDMA_DEV_NAME, spidma_init, spidma_uninit}, +#endif + +#if CFG_USE_CAMERA_INTF + {EJPEG_DEV_NAME, ejpeg_init, ejpeg_exit}, + {I2C1_DEV_NAME, i2c1_init, i2c1_exit}, + {I2C2_DEV_NAME, i2c2_init, i2c2_exit}, +#endif + +#if CFG_USE_AUDIO + {AUD_DAC_DEV_NAME, audio_init, audio_exit}, +#endif + +#if CFG_SDIO || CFG_SDIO_TRANS + {SDIO_DEV_NAME, sdio_init, sdio_exit}, +#endif + +#if CFG_USB + {USB_DEV_NAME, usb_init, usb_exit}, +#endif + + {PWM_DEV_NAME, pwm_init, pwm_exit}, +#if (CFG_SOC_NAME != SOC_BK7231) + {TIMER_DEV_NAME, bk_timer_init, bk_timer_exit}, +#endif + {SPI_DEV_NAME, spi_init, spi_exit}, + +#if (CFG_SOC_NAME != SOC_BK7231N) + {FFT_DEV_NAME, fft_init, fft_exit}, + {I2S_DEV_NAME, i2s_init, i2s_exit}, +#endif + {SARADC_DEV_NAME, saradc_init, saradc_exit}, + {IRDA_DEV_NAME, irda_init, irda_exit}, + +#if CFG_MAC_PHY_BAPASS + {MPB_DEV_NAME, mpb_init, mpb_exit}, +#endif + +#if CFG_USE_SDCARD_HOST + {SDCARD_DEV_NAME, sdcard_init, sdcard_exit}, +#endif + +#if CFG_USE_STA_PS + {"power_save", sctrl_sta_ps_init, NULLPTR}, +#endif + +#if defined(CFG_SUPPORT_BLE) && CFG_SUPPORT_BLE + {BLE_DEV_NAME, ble_init, ble_exit}, //sean +#endif + + {NULL, NULLPTR, NULLPTR} +}; + +void g_dd_init(void) +{ + UINT32 i; + UINT32 tbl_count; + DD_INIT_S *dd_element; + + tbl_count = sizeof(dd_init_tbl) / sizeof(DD_INIT_S); + for(i = 0; i < tbl_count; i ++) + { + dd_element = &dd_init_tbl[i]; + if(dd_element->dev_name && dd_element->init) + { + (dd_element->init)(); + } + else + { + return; + } + } +} + +void g_dd_exit(void) +{ + UINT32 i; + UINT32 tbl_count; + DD_INIT_S *dd_element; + + tbl_count = sizeof(dd_init_tbl) / sizeof(DD_INIT_S); + for(i = 0; i < tbl_count; i ++) + { + dd_element = &dd_init_tbl[i]; + if(dd_element->dev_name && dd_element->exit) + { + (dd_element->exit)(); + } + else + { + return; + } + } +} + +// EOF diff --git a/beken_os/beken378/driver/common/dd_pub.h b/beken_os/beken378/driver/common/dd_pub.h new file mode 100755 index 0000000..89555bf --- /dev/null +++ b/beken_os/beken378/driver/common/dd_pub.h @@ -0,0 +1,19 @@ +#ifndef __DD_H_ +#define __DD_H_ + +typedef struct _dd_init_s_ +{ + char *dev_name; + + void (*init)(void); + void (*exit)(void); +} DD_INIT_S; + + +/******************************************************************************* +* Function Declarations +*******************************************************************************/ +extern void g_dd_init(void); +extern void g_dd_exit(void); + +#endif // __DD_H_ diff --git a/beken_os/beken378/driver/common/drv_model.c b/beken_os/beken378/driver/common/drv_model.c new file mode 100755 index 0000000..61ca1de --- /dev/null +++ b/beken_os/beken378/driver/common/drv_model.c @@ -0,0 +1,429 @@ +#include "include.h" +#include "arm_arch.h" + +#include "drv_model_pub.h" +#include "drv_model.h" +#include "mem_pub.h" +#include "str_pub.h" +#if CFG_SUPPORT_ALIOS +#include "ll.h" +#endif + +static DRV_SDEV_S drv_sdev_tbl[DD_MAX_SDEV] = +{ + {0}, +}; + +static DRV_DEV_S drv_dev_tbl[DD_MAX_DEV] = +{ + {0}, +}; + +UINT32 drv_model_init(void) +{ + os_memset(drv_dev_tbl, 0, sizeof(drv_dev_tbl)); + os_memset(drv_sdev_tbl, 0, sizeof(drv_sdev_tbl)); + + return DRV_SUCCESS; +} + +UINT32 drv_model_uninit(void) +{ + os_memset(drv_dev_tbl, 0, sizeof(drv_dev_tbl)); + os_memset(drv_sdev_tbl, 0, sizeof(drv_sdev_tbl)); + + return DRV_SUCCESS; +} + +UINT32 ddev_check_handle(DD_HANDLE handle) +{ + UINT32 magic; + UINT32 id; + + magic = handle & DD_HANDLE_MAGIC_MASK; + id = handle & DD_HANDLE_ID_MASK; + if((DD_HANDLE_MAGIC_WORD == magic) + && (id < DD_MAX_DEV)) + { + return DRV_SUCCESS; + } + else + { + return DRV_FAILURE; + } +} + +DD_HANDLE ddev_make_handle(UINT32 id) +{ + UINT32 handle = DD_HANDLE_UNVALID; + + if(id >= DD_MAX_DEV) + { + goto make_exit; + } + + handle = id + DD_HANDLE_MAGIC_WORD; + +make_exit: + return handle; +} + +UINT32 ddev_get_id_from_handle(DD_HANDLE handle) +{ + UINT32 magic; + UINT32 id; + + magic = handle & DD_HANDLE_MAGIC_MASK; + id = handle & DD_HANDLE_ID_MASK; + + if(magic != DD_HANDLE_MAGIC_WORD) + { + return DD_ID_UNVALID; + } + + return id; +} + +DD_HANDLE ddev_open(char *dev_name, UINT32 *status, UINT32 op_flag) +{ + UINT32 i; + UINT32 handle; + UINT32 name_len; + DRV_DEV_PTR dev_ptr; + DD_OPERATIONS *operation; + GLOBAL_INT_DECLARATION(); + + handle = DD_HANDLE_UNVALID; + name_len = os_strlen(dev_name); + if((!(dev_name && status)) || (name_len > DD_MAX_NAME_LEN)) + { + goto open_exit; + } + + *status = DRV_FAILURE; + + for(i = 0; i < DD_MAX_DEV; i ++) + { + dev_ptr = &drv_dev_tbl[i]; + if((dev_ptr) + && (0 == os_strncmp(dev_ptr->name, dev_name, name_len))) + { + if(DD_STATE_OPENED == dev_ptr->state) + { + handle = ddev_make_handle(i); + } + else if(DD_STATE_CLOSED == dev_ptr->state) + { + handle = ddev_make_handle(i); + + operation = dev_ptr->op; + if(operation && (operation->open)) + { + *status = (operation->open)(op_flag); + } + + GLOBAL_INT_DISABLE(); + dev_ptr->state = DD_STATE_OPENED; + dev_ptr->use_cnt = 0; + GLOBAL_INT_RESTORE(); + } + else + { + } + + GLOBAL_INT_DISABLE(); + dev_ptr->use_cnt ++; + GLOBAL_INT_RESTORE(); + break; + } + } + + ASSERT(DD_HANDLE_UNVALID != handle); + +open_exit: + return handle; +} + +UINT32 ddev_close(DD_HANDLE handle) +{ + UINT32 id; + DRV_DEV_PTR dev_ptr; + DD_OPERATIONS *operation; + GLOBAL_INT_DECLARATION(); + + id = ddev_get_id_from_handle(handle); + if(DD_ID_UNVALID == id) + { + return DRV_FAILURE; + } + + dev_ptr = &drv_dev_tbl[id]; + + GLOBAL_INT_DISABLE(); + dev_ptr->use_cnt --; + GLOBAL_INT_RESTORE(); + + if(0 == dev_ptr->use_cnt) + { + operation = dev_ptr->op; + if(operation && (operation->close)) + { + (operation->close)(); + } + + ASSERT(dev_ptr); + + GLOBAL_INT_DISABLE(); + dev_ptr->state = DD_STATE_CLOSED; + GLOBAL_INT_RESTORE(); + } + + return DRV_SUCCESS; +} + +UINT32 ddev_read(DD_HANDLE handle, char *user_buf, UINT32 count, UINT32 op_flag) +{ + UINT32 id; + UINT32 status; + DRV_DEV_PTR dev_ptr; + DD_OPERATIONS *operation; + + id = ddev_get_id_from_handle(handle); + if(DD_ID_UNVALID == id) + { + return DRV_FAILURE; + } + + status = DRV_FAILURE; + dev_ptr = &drv_dev_tbl[id]; + ASSERT(dev_ptr); + operation = dev_ptr->op; + if(operation && (operation->read)) + { + status = (operation->read)(user_buf, count, op_flag); + } + + return status; +} + +UINT32 ddev_write(DD_HANDLE handle, char *user_buf, UINT32 count, UINT32 op_flag) +{ + UINT32 id; + UINT32 status; + DRV_DEV_PTR dev_ptr; + DD_OPERATIONS *operation; + + id = ddev_get_id_from_handle(handle); + if(DD_ID_UNVALID == id) + { + return DRV_FAILURE; + } + + status = DRV_FAILURE; + dev_ptr = &drv_dev_tbl[id]; + ASSERT(dev_ptr); + operation = dev_ptr->op; + if(operation && (operation->write)) + { + status = (operation->write)(user_buf, count, op_flag); + } + + return status; +} + +UINT32 ddev_control(DD_HANDLE handle, UINT32 cmd, VOID *param) +{ + UINT32 id; + UINT32 status; + DRV_DEV_PTR dev_ptr; + DD_OPERATIONS *operation; + + id = ddev_get_id_from_handle(handle); + if(DD_ID_UNVALID == id) + { + return DRV_FAILURE; + } + + status = DRV_FAILURE; + dev_ptr = &drv_dev_tbl[id]; + ASSERT(dev_ptr); + operation = dev_ptr->op; + if(operation && (operation->control)) + { + status = (operation->control)(cmd, param); + } + + return status; +} + +UINT32 sddev_control(char *dev_name, UINT32 cmd, VOID *param) +{ + UINT32 i; + UINT32 status; + UINT32 name_len; + DRV_SDEV_PTR dev_ptr; + SDD_OPERATIONS *operation = NULLPTR; + + ASSERT(dev_name); + status = DRV_FAILURE; + name_len = os_strlen(dev_name); + for(i = 0; i < DD_MAX_SDEV; i ++) + { + dev_ptr = &drv_sdev_tbl[i]; + if((dev_ptr) + && (0 == os_strncmp(dev_ptr->name, dev_name, name_len))) + { + operation = dev_ptr->op; + if(operation && (operation->control)) + { + status = (operation->control)(cmd, param); + } + + break; + } + } + + ASSERT(operation); + + return status; +} + +UINT32 ddev_register_dev(char *dev_name, DD_OPERATIONS *optr) +{ + UINT32 i; + DRV_DEV_PTR dev_ptr; + + if(!(dev_name && optr)) + { + return DRV_FAILURE; + } + + dev_ptr = NULLPTR; + for(i = 0; i < DD_MAX_DEV; i ++) + { + dev_ptr = &drv_dev_tbl[i]; + if( (NULLPTR == dev_ptr->name) + && (DD_STATE_NODEVICE == dev_ptr->state)) + { + dev_ptr->name = dev_name; + dev_ptr->op = optr; + dev_ptr->state = DD_STATE_CLOSED; + + break; + } + } + + ASSERT(DD_MAX_DEV != i); + ASSERT(NULLPTR != dev_ptr->op); + + return DRV_SUCCESS; +} + +UINT32 sddev_register_dev(char *dev_name, SDD_OPERATIONS *optr) +{ + UINT32 i; + DRV_SDEV_PTR dev_ptr; + + if(!(dev_name && optr)) + { + return DRV_FAILURE; + } + + dev_ptr = NULLPTR; + for(i = 0; i < DD_MAX_SDEV; i ++) + { + dev_ptr = &drv_sdev_tbl[i]; + if( (NULLPTR == dev_ptr->name) + && (DD_STATE_NODEVICE == dev_ptr->state)) + { + dev_ptr->name = dev_name; + dev_ptr->op = optr; + dev_ptr->state = DD_STATE_CLOSED; + + break; + } + } + + ASSERT(DD_MAX_SDEV != i); + ASSERT(NULLPTR != dev_ptr->op); + + return DRV_SUCCESS; +} + +UINT32 ddev_unregister_dev(char *dev_name) +{ + UINT32 i; + UINT32 name_len; + DRV_DEV_PTR dev_ptr; + + if(!dev_name) + { + return DRV_FAILURE; + } + + dev_ptr = NULLPTR; + name_len = os_strlen(dev_name); + if((!dev_name) || (name_len > DD_MAX_NAME_LEN)) + { + return DRV_FAILURE; + } + + for(i = 0; i < DD_MAX_SDEV; i ++) + { + dev_ptr = &drv_dev_tbl[i]; + if(0 == os_strncmp(dev_ptr->name, dev_name, name_len)) + { + dev_ptr->name = 0; + dev_ptr->op = 0; + dev_ptr->state = DD_STATE_NODEVICE; + + dev_ptr = NULLPTR; + + break; + } + } + + ASSERT(NULLPTR == dev_ptr); + + return DRV_SUCCESS; +} + +UINT32 sddev_unregister_dev(char *dev_name) +{ + UINT32 i; + UINT32 name_len; + DRV_SDEV_PTR dev_ptr; + + if(!dev_name) + { + return DRV_FAILURE; + } + + dev_ptr = NULLPTR; + name_len = os_strlen(dev_name); + if((!dev_name) || (name_len > DD_MAX_NAME_LEN)) + { + return DRV_FAILURE; + } + + for(i = 0; i < DD_MAX_DEV; i ++) + { + dev_ptr = &drv_sdev_tbl[i]; + if(0 == os_strncmp(dev_ptr->name, dev_name, name_len)) + { + dev_ptr->name = 0; + dev_ptr->op = 0; + dev_ptr->state = DD_STATE_NODEVICE; + + dev_ptr = NULLPTR; + + break; + } + } + + ASSERT(NULLPTR == dev_ptr); + + return DRV_SUCCESS; +} + +// EOF diff --git a/beken_os/beken378/driver/common/drv_model.h b/beken_os/beken378/driver/common/drv_model.h new file mode 100755 index 0000000..cf026a3 --- /dev/null +++ b/beken_os/beken378/driver/common/drv_model.h @@ -0,0 +1,45 @@ +#ifndef _DRV_MODEL_H_ +#define _DRV_MODEL_H_ + +#define DD_MAX_DEV (8) +#define DD_MAX_SDEV (16) + +#define DD_MAX_DEV_MASK (DD_MAX_DEV - 1) + +#define DD_MAX_NAME_LEN (16) + +typedef enum _dd_state_ +{ + DD_STATE_NODEVICE = 0, // find no such device when you open + DD_STATE_CLOSED, // + DD_STATE_OPENED, // + DD_STATE_BREAK, // + DD_STATE_SUCCESS // +} DD_STATE; + +typedef struct _drv_dev_ +{ + char *name; + UINT32 use_cnt; + + DD_STATE state; + DD_OPERATIONS *op; + DD_OPEN_METHOD method; + + void *private; +} DRV_DEV_S, *DRV_DEV_PTR; + +typedef struct _drv_sdev_ +{ + char *name; + UINT32 use_cnt; + + DD_STATE state; + SDD_OPERATIONS *op; + DD_OPEN_METHOD method; + + void *private; +} DRV_SDEV_S, *DRV_SDEV_PTR; + +#endif // _DRV_MODEL_H_ + diff --git a/beken_os/beken378/driver/common/reg/_reg_agc.h b/beken_os/beken378/driver/common/reg/_reg_agc.h new file mode 100755 index 0000000..76c48af --- /dev/null +++ b/beken_os/beken378/driver/common/reg/_reg_agc.h @@ -0,0 +1,10 @@ +#ifndef __REG_AGC_H_ +#define __REG_AGC_H_ + +#define REG_AGC_SIZE 172 + +#define REG_AGC_BASE_ADDR 0x01000000 + + +#endif // __REG_AGC_H_ + diff --git a/beken_os/beken378/driver/common/reg/_reg_dma.h b/beken_os/beken378/driver/common/reg/_reg_dma.h new file mode 100755 index 0000000..13ae201 --- /dev/null +++ b/beken_os/beken378/driver/common/reg/_reg_dma.h @@ -0,0 +1,10 @@ +#ifndef __REG_DMA_H_ +#define __REG_DMA_H_ + +#define REG_DMA_SIZE 196 + +#define REG_DMA_BASE_ADDR 0x10A00000 + + +#endif // __REG_DMA_H_ + diff --git a/beken_os/beken378/driver/common/reg/_reg_intc.h b/beken_os/beken378/driver/common/reg/_reg_intc.h new file mode 100755 index 0000000..71cd885 --- /dev/null +++ b/beken_os/beken378/driver/common/reg/_reg_intc.h @@ -0,0 +1,10 @@ +#ifndef __REG_INTC_H_ +#define __REG_INTC_H_ + +#define REG_INTC_SIZE 68 + +#define REG_INTC_BASE_ADDR 0x10910000 + + +#endif // __REG_INTC_H_ + diff --git a/beken_os/beken378/driver/common/reg/_reg_la.h b/beken_os/beken378/driver/common/reg/_reg_la.h new file mode 100755 index 0000000..8c44553 --- /dev/null +++ b/beken_os/beken378/driver/common/reg/_reg_la.h @@ -0,0 +1,18 @@ +#ifndef __REG_LA_H_ +#define __REG_LA_H_ + +#include "sys_config.h" + +#if (CFG_SOC_NAME == SOC_BK7231N) +#define REG_LA_OFFSET 0x00000000 + +#define REG_LA_BASE_ADDR 0x00808000 +#else +#define REG_LA_SIZE 64 +#define REG_LA_OFFSET 0x00800000 + +#define REG_LA_BASE_ADDR 0x10E00000 +#endif + +#endif // __REG_LA_H_ + diff --git a/beken_os/beken378/driver/common/reg/_reg_mac_core.h b/beken_os/beken378/driver/common/reg/_reg_mac_core.h new file mode 100755 index 0000000..88e480e --- /dev/null +++ b/beken_os/beken378/driver/common/reg/_reg_mac_core.h @@ -0,0 +1,10 @@ +#ifndef __REG_MAC_CORE_H_ +#define __REG_MAC_CORE_H_ + +#define REG_MAC_CORE_SIZE 1376 + +#define REG_MAC_CORE_BASE_ADDR 0xC0000000 + + +#endif // __REG_MAC_CORE_H_ + diff --git a/beken_os/beken378/driver/common/reg/_reg_mac_pl.h b/beken_os/beken378/driver/common/reg/_reg_mac_pl.h new file mode 100755 index 0000000..9f694ea --- /dev/null +++ b/beken_os/beken378/driver/common/reg/_reg_mac_pl.h @@ -0,0 +1,8 @@ +#ifndef __REG_MAC_PL_H_ +#define __REG_MAC_PL_H_ + +#define REG_MAC_PL_SIZE 1404 +#define REG_MAC_PL_BASE_ADDR 0xC0008000 + +#endif // __REG_MAC_PL_H_ + diff --git a/beken_os/beken378/driver/common/reg/_reg_mdm_cfg.h b/beken_os/beken378/driver/common/reg/_reg_mdm_cfg.h new file mode 100755 index 0000000..3483bc9 --- /dev/null +++ b/beken_os/beken378/driver/common/reg/_reg_mdm_cfg.h @@ -0,0 +1,10 @@ +#ifndef __REG_MDM_CFG_H_ +#define __REG_MDM_CFG_H_ + +#define REG_MDM_CFG_SIZE 152 + +#define REG_MDM_CFG_BASE_ADDR 0x01000000 + + +#endif // __REG_MDM_CFG_H_ + diff --git a/beken_os/beken378/driver/common/reg/_reg_mdm_stat.h b/beken_os/beken378/driver/common/reg/_reg_mdm_stat.h new file mode 100755 index 0000000..2b77bbb --- /dev/null +++ b/beken_os/beken378/driver/common/reg/_reg_mdm_stat.h @@ -0,0 +1,10 @@ +#ifndef __REG_MDM_STAT_H_ +#define __REG_MDM_STAT_H_ + +#define REG_MDM_STAT_SIZE 108 + +#define REG_MDM_STAT_BASE_ADDR 0x01000000 + + +#endif // __REG_MDM_STAT_H_ + diff --git a/beken_os/beken378/driver/common/reg/_reg_rc.h b/beken_os/beken378/driver/common/reg/_reg_rc.h new file mode 100755 index 0000000..7baa855 --- /dev/null +++ b/beken_os/beken378/driver/common/reg/_reg_rc.h @@ -0,0 +1,10 @@ +#ifndef __REG_RC_H_ +#define __REG_RC_H_ + +#define REG_RC_SIZE 428 + +#define REG_RC_BASE_ADDR 0x01050000 + + +#endif // __REG_RC_H_ + diff --git a/beken_os/beken378/driver/common/reg/reg_access.h b/beken_os/beken378/driver/common/reg/reg_access.h new file mode 100755 index 0000000..6f69978 --- /dev/null +++ b/beken_os/beken378/driver/common/reg/reg_access.h @@ -0,0 +1,42 @@ +/** + **************************************************************************************** + * + * @file reg_access.h + * + * @brief File implementing the basic primitives for register accesses + * + * Copyright (C) RivieraWaves 2011-2016 + * + **************************************************************************************** + */ + +#ifndef REG_ACCESS_H_ +#define REG_ACCESS_H_ + +/** + **************************************************************************************** + * @defgroup REG REG + * @ingroup PLATFORM_DRIVERS + * + * @brief Basic primitives for register access. + * + * @{ + **************************************************************************************** + */ + + +/* + * MACROS + **************************************************************************************** + */ +/// Macro to read a platform register +#define REG_PL_RD(addr) (*(volatile uint32_t *)(addr)) + +/// Macro to write a platform register +#define REG_PL_WR(addr, value) (*(volatile uint32_t *)(addr)) = (value) + + + +/// @} REG + +#endif // REG_ACCESS_H_ diff --git a/beken_os/beken378/driver/common/reg/reg_agc.h b/beken_os/beken378/driver/common/reg/reg_agc.h new file mode 100755 index 0000000..6b7c2ba --- /dev/null +++ b/beken_os/beken378/driver/common/reg/reg_agc.h @@ -0,0 +1,9630 @@ +/** + * @file reg_agc.h + * @brief Definitions of the AGC HW block registers and register access functions. + * + * @defgroup REG_AGC REG_AGC + * @ingroup REG + * @{ + * + * @brief Definitions of the AGC HW block registers and register access functions. + */ +#ifndef _REG_AGC_H_ +#define _REG_AGC_H_ + +#include "co_int.h" +#include "_reg_agc.h" +#include "compiler.h" +#include "arch.h" +#include "reg_access.h" + +/** @brief Number of registers in the REG_AGC peripheral. + */ +#define REG_AGC_COUNT 2091 + +/** @brief Decoding mask of the REG_AGC peripheral registers from the CPU point of view. + */ +#define REG_AGC_DECODING_MASK 0x00003FFF + +/** + * @name RWNXAGCGAINRG register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:28         RFLOSSANT3DB   0x0
+ *  27:24         RFLOSSANT2DB   0x0
+ *  23:20         RFLOSSANT1DB   0x0
+ *  19:16         RFLOSSANT0DB   0x0
+ *  14:08          RFGAINMAXDB   0x64
+ *  06:00          RFGAINMINDB   0x0
+ * 
+ * + * @{ + */ + +/// Address of the RWNXAGCGAINRG register +#define AGC_RWNXAGCGAINRG_ADDR 0x01002000 +/// Offset of the RWNXAGCGAINRG register from the base address +#define AGC_RWNXAGCGAINRG_OFFSET 0x00002000 +/// Index of the RWNXAGCGAINRG register +#define AGC_RWNXAGCGAINRG_INDEX 0x00000800 +/// Reset value of the RWNXAGCGAINRG register +#define AGC_RWNXAGCGAINRG_RESET 0x00006400 + +/** + * @brief Returns the current value of the RWNXAGCGAINRG register. + * The RWNXAGCGAINRG register will be read and its value returned. + * @return The current value of the RWNXAGCGAINRG register. + */ +__INLINE uint32_t agc_rwnxagcgainrg_get(void) +{ + return REG_PL_RD(AGC_RWNXAGCGAINRG_ADDR); +} + +/** + * @brief Sets the RWNXAGCGAINRG register to a value. + * The RWNXAGCGAINRG register will be written. + * @param value - The value to write. + */ +__INLINE void agc_rwnxagcgainrg_set(uint32_t value) +{ + REG_PL_WR(AGC_RWNXAGCGAINRG_ADDR, value); +} + +// field definitions +/// RFLOSSANT3DB field mask +#define AGC_RFLOSSANT3DB_MASK ((uint32_t)0xF0000000) +/// RFLOSSANT3DB field LSB position +#define AGC_RFLOSSANT3DB_LSB 28 +/// RFLOSSANT3DB field width +#define AGC_RFLOSSANT3DB_WIDTH ((uint32_t)0x00000004) +/// RFLOSSANT2DB field mask +#define AGC_RFLOSSANT2DB_MASK ((uint32_t)0x0F000000) +/// RFLOSSANT2DB field LSB position +#define AGC_RFLOSSANT2DB_LSB 24 +/// RFLOSSANT2DB field width +#define AGC_RFLOSSANT2DB_WIDTH ((uint32_t)0x00000004) +/// RFLOSSANT1DB field mask +#define AGC_RFLOSSANT1DB_MASK ((uint32_t)0x00F00000) +/// RFLOSSANT1DB field LSB position +#define AGC_RFLOSSANT1DB_LSB 20 +/// RFLOSSANT1DB field width +#define AGC_RFLOSSANT1DB_WIDTH ((uint32_t)0x00000004) +/// RFLOSSANT0DB field mask +#define AGC_RFLOSSANT0DB_MASK ((uint32_t)0x000F0000) +/// RFLOSSANT0DB field LSB position +#define AGC_RFLOSSANT0DB_LSB 16 +/// RFLOSSANT0DB field width +#define AGC_RFLOSSANT0DB_WIDTH ((uint32_t)0x00000004) +/// RFGAINMAXDB field mask +#define AGC_RFGAINMAXDB_MASK ((uint32_t)0x00007F00) +/// RFGAINMAXDB field LSB position +#define AGC_RFGAINMAXDB_LSB 8 +/// RFGAINMAXDB field width +#define AGC_RFGAINMAXDB_WIDTH ((uint32_t)0x00000007) +/// RFGAINMINDB field mask +#define AGC_RFGAINMINDB_MASK ((uint32_t)0x0000007F) +/// RFGAINMINDB field LSB position +#define AGC_RFGAINMINDB_LSB 0 +/// RFGAINMINDB field width +#define AGC_RFGAINMINDB_WIDTH ((uint32_t)0x00000007) + +/// RFLOSSANT3DB field reset value +#define AGC_RFLOSSANT3DB_RST 0x0 +/// RFLOSSANT2DB field reset value +#define AGC_RFLOSSANT2DB_RST 0x0 +/// RFLOSSANT1DB field reset value +#define AGC_RFLOSSANT1DB_RST 0x0 +/// RFLOSSANT0DB field reset value +#define AGC_RFLOSSANT0DB_RST 0x0 +/// RFGAINMAXDB field reset value +#define AGC_RFGAINMAXDB_RST 0x64 +/// RFGAINMINDB field reset value +#define AGC_RFGAINMINDB_RST 0x0 + +/** + * @brief Constructs a value for the RWNXAGCGAINRG register given values for its fields + * and writes the value to the register. + * + * @param[in] rflossant3db - The value to use for the RFLOSSANT3DB field. + * @param[in] rflossant2db - The value to use for the RFLOSSANT2DB field. + * @param[in] rflossant1db - The value to use for the RFLOSSANT1DB field. + * @param[in] rflossant0db - The value to use for the RFLOSSANT0DB field. + * @param[in] rfgainmaxdb - The value to use for the RFGAINMAXDB field. + * @param[in] rfgainmindb - The value to use for the RFGAINMINDB field. + */ +__INLINE void agc_rwnxagcgainrg_pack(uint8_t rflossant3db, uint8_t rflossant2db, uint8_t rflossant1db, uint8_t rflossant0db, uint8_t rfgainmaxdb, uint8_t rfgainmindb) +{ + ASSERT_ERR((((uint32_t)rflossant3db << 28) & ~((uint32_t)0xF0000000)) == 0); + ASSERT_ERR((((uint32_t)rflossant2db << 24) & ~((uint32_t)0x0F000000)) == 0); + ASSERT_ERR((((uint32_t)rflossant1db << 20) & ~((uint32_t)0x00F00000)) == 0); + ASSERT_ERR((((uint32_t)rflossant0db << 16) & ~((uint32_t)0x000F0000)) == 0); + ASSERT_ERR((((uint32_t)rfgainmaxdb << 8) & ~((uint32_t)0x00007F00)) == 0); + ASSERT_ERR((((uint32_t)rfgainmindb << 0) & ~((uint32_t)0x0000007F)) == 0); + REG_PL_WR(AGC_RWNXAGCGAINRG_ADDR, ((uint32_t)rflossant3db << 28) | ((uint32_t)rflossant2db << 24) | ((uint32_t)rflossant1db << 20) | ((uint32_t)rflossant0db << 16) | ((uint32_t)rfgainmaxdb << 8) | ((uint32_t)rfgainmindb << 0)); +} + +/** + * @brief Unpacks RWNXAGCGAINRG's fields from current value of the RWNXAGCGAINRG register. + * + * Reads the RWNXAGCGAINRG register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] rflossant3db - Will be populated with the current value of this field from the register. + * @param[out] rflossant2db - Will be populated with the current value of this field from the register. + * @param[out] rflossant1db - Will be populated with the current value of this field from the register. + * @param[out] rflossant0db - Will be populated with the current value of this field from the register. + * @param[out] rfgainmaxdb - Will be populated with the current value of this field from the register. + * @param[out] rfgainmindb - Will be populated with the current value of this field from the register. + */ +__INLINE void agc_rwnxagcgainrg_unpack(uint8_t *rflossant3db, uint8_t *rflossant2db, uint8_t *rflossant1db, uint8_t *rflossant0db, uint8_t *rfgainmaxdb, uint8_t *rfgainmindb) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCGAINRG_ADDR); + + *rflossant3db = (localVal & ((uint32_t)0xF0000000)) >> 28; + *rflossant2db = (localVal & ((uint32_t)0x0F000000)) >> 24; + *rflossant1db = (localVal & ((uint32_t)0x00F00000)) >> 20; + *rflossant0db = (localVal & ((uint32_t)0x000F0000)) >> 16; + *rfgainmaxdb = (localVal & ((uint32_t)0x00007F00)) >> 8; + *rfgainmindb = (localVal & ((uint32_t)0x0000007F)) >> 0; +} + +/** + * @brief Returns the current value of the RFLOSSANT3DB field in the RWNXAGCGAINRG register. + * + * The RWNXAGCGAINRG register will be read and the RFLOSSANT3DB field's value will be returned. + * + * @return The current value of the RFLOSSANT3DB field in the RWNXAGCGAINRG register. + */ +__INLINE uint8_t agc_rflossant3db_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCGAINRG_ADDR); + return ((localVal & ((uint32_t)0xF0000000)) >> 28); +} + +/** + * @brief Sets the RFLOSSANT3DB field of the RWNXAGCGAINRG register. + * + * The RWNXAGCGAINRG register will be read, modified to contain the new field value, and written. + * + * @param[in] rflossant3db - The value to set the field to. + */ +__INLINE void agc_rflossant3db_setf(uint8_t rflossant3db) +{ + ASSERT_ERR((((uint32_t)rflossant3db << 28) & ~((uint32_t)0xF0000000)) == 0); + REG_PL_WR(AGC_RWNXAGCGAINRG_ADDR, (REG_PL_RD(AGC_RWNXAGCGAINRG_ADDR) & ~((uint32_t)0xF0000000)) | ((uint32_t)rflossant3db << 28)); +} + +/** + * @brief Returns the current value of the RFLOSSANT2DB field in the RWNXAGCGAINRG register. + * + * The RWNXAGCGAINRG register will be read and the RFLOSSANT2DB field's value will be returned. + * + * @return The current value of the RFLOSSANT2DB field in the RWNXAGCGAINRG register. + */ +__INLINE uint8_t agc_rflossant2db_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCGAINRG_ADDR); + return ((localVal & ((uint32_t)0x0F000000)) >> 24); +} + +/** + * @brief Sets the RFLOSSANT2DB field of the RWNXAGCGAINRG register. + * + * The RWNXAGCGAINRG register will be read, modified to contain the new field value, and written. + * + * @param[in] rflossant2db - The value to set the field to. + */ +__INLINE void agc_rflossant2db_setf(uint8_t rflossant2db) +{ + ASSERT_ERR((((uint32_t)rflossant2db << 24) & ~((uint32_t)0x0F000000)) == 0); + REG_PL_WR(AGC_RWNXAGCGAINRG_ADDR, (REG_PL_RD(AGC_RWNXAGCGAINRG_ADDR) & ~((uint32_t)0x0F000000)) | ((uint32_t)rflossant2db << 24)); +} + +/** + * @brief Returns the current value of the RFLOSSANT1DB field in the RWNXAGCGAINRG register. + * + * The RWNXAGCGAINRG register will be read and the RFLOSSANT1DB field's value will be returned. + * + * @return The current value of the RFLOSSANT1DB field in the RWNXAGCGAINRG register. + */ +__INLINE uint8_t agc_rflossant1db_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCGAINRG_ADDR); + return ((localVal & ((uint32_t)0x00F00000)) >> 20); +} + +/** + * @brief Sets the RFLOSSANT1DB field of the RWNXAGCGAINRG register. + * + * The RWNXAGCGAINRG register will be read, modified to contain the new field value, and written. + * + * @param[in] rflossant1db - The value to set the field to. + */ +__INLINE void agc_rflossant1db_setf(uint8_t rflossant1db) +{ + ASSERT_ERR((((uint32_t)rflossant1db << 20) & ~((uint32_t)0x00F00000)) == 0); + REG_PL_WR(AGC_RWNXAGCGAINRG_ADDR, (REG_PL_RD(AGC_RWNXAGCGAINRG_ADDR) & ~((uint32_t)0x00F00000)) | ((uint32_t)rflossant1db << 20)); +} + +/** + * @brief Returns the current value of the RFLOSSANT0DB field in the RWNXAGCGAINRG register. + * + * The RWNXAGCGAINRG register will be read and the RFLOSSANT0DB field's value will be returned. + * + * @return The current value of the RFLOSSANT0DB field in the RWNXAGCGAINRG register. + */ +__INLINE uint8_t agc_rflossant0db_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCGAINRG_ADDR); + return ((localVal & ((uint32_t)0x000F0000)) >> 16); +} + +/** + * @brief Sets the RFLOSSANT0DB field of the RWNXAGCGAINRG register. + * + * The RWNXAGCGAINRG register will be read, modified to contain the new field value, and written. + * + * @param[in] rflossant0db - The value to set the field to. + */ +__INLINE void agc_rflossant0db_setf(uint8_t rflossant0db) +{ + ASSERT_ERR((((uint32_t)rflossant0db << 16) & ~((uint32_t)0x000F0000)) == 0); + REG_PL_WR(AGC_RWNXAGCGAINRG_ADDR, (REG_PL_RD(AGC_RWNXAGCGAINRG_ADDR) & ~((uint32_t)0x000F0000)) | ((uint32_t)rflossant0db << 16)); +} + +/** + * @brief Returns the current value of the RFGAINMAXDB field in the RWNXAGCGAINRG register. + * + * The RWNXAGCGAINRG register will be read and the RFGAINMAXDB field's value will be returned. + * + * @return The current value of the RFGAINMAXDB field in the RWNXAGCGAINRG register. + */ +__INLINE uint8_t agc_rfgainmaxdb_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCGAINRG_ADDR); + return ((localVal & ((uint32_t)0x00007F00)) >> 8); +} + +/** + * @brief Sets the RFGAINMAXDB field of the RWNXAGCGAINRG register. + * + * The RWNXAGCGAINRG register will be read, modified to contain the new field value, and written. + * + * @param[in] rfgainmaxdb - The value to set the field to. + */ +__INLINE void agc_rfgainmaxdb_setf(uint8_t rfgainmaxdb) +{ + ASSERT_ERR((((uint32_t)rfgainmaxdb << 8) & ~((uint32_t)0x00007F00)) == 0); + REG_PL_WR(AGC_RWNXAGCGAINRG_ADDR, (REG_PL_RD(AGC_RWNXAGCGAINRG_ADDR) & ~((uint32_t)0x00007F00)) | ((uint32_t)rfgainmaxdb << 8)); +} + +/** + * @brief Returns the current value of the RFGAINMINDB field in the RWNXAGCGAINRG register. + * + * The RWNXAGCGAINRG register will be read and the RFGAINMINDB field's value will be returned. + * + * @return The current value of the RFGAINMINDB field in the RWNXAGCGAINRG register. + */ +__INLINE uint8_t agc_rfgainmindb_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCGAINRG_ADDR); + return ((localVal & ((uint32_t)0x0000007F)) >> 0); +} + +/** + * @brief Sets the RFGAINMINDB field of the RWNXAGCGAINRG register. + * + * The RWNXAGCGAINRG register will be read, modified to contain the new field value, and written. + * + * @param[in] rfgainmindb - The value to set the field to. + */ +__INLINE void agc_rfgainmindb_setf(uint8_t rfgainmindb) +{ + ASSERT_ERR((((uint32_t)rfgainmindb << 0) & ~((uint32_t)0x0000007F)) == 0); + REG_PL_WR(AGC_RWNXAGCGAINRG_ADDR, (REG_PL_RD(AGC_RWNXAGCGAINRG_ADDR) & ~((uint32_t)0x0000007F)) | ((uint32_t)rfgainmindb << 0)); +} + +/// @} + +/** + * @name RWNXAGCLNAVGAREF0 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  30:28            VGASTEPDB   0x2
+ *  27:24             VGAMINDB   0x0
+ *  21:16               LNAHDB   0x1E
+ *  13:08               LMAMDB   0xF
+ *  06:00               LNALDB   0x0
+ * 
+ * + * @{ + */ + +/// Address of the RWNXAGCLNAVGAREF0 register +#define AGC_RWNXAGCLNAVGAREF0_ADDR 0x01002004 +/// Offset of the RWNXAGCLNAVGAREF0 register from the base address +#define AGC_RWNXAGCLNAVGAREF0_OFFSET 0x00002004 +/// Index of the RWNXAGCLNAVGAREF0 register +#define AGC_RWNXAGCLNAVGAREF0_INDEX 0x00000801 +/// Reset value of the RWNXAGCLNAVGAREF0 register +#define AGC_RWNXAGCLNAVGAREF0_RESET 0x201E0F00 + +/** + * @brief Returns the current value of the RWNXAGCLNAVGAREF0 register. + * The RWNXAGCLNAVGAREF0 register will be read and its value returned. + * @return The current value of the RWNXAGCLNAVGAREF0 register. + */ +__INLINE uint32_t agc_rwnxagclnavgaref0_get(void) +{ + return REG_PL_RD(AGC_RWNXAGCLNAVGAREF0_ADDR); +} + +/** + * @brief Sets the RWNXAGCLNAVGAREF0 register to a value. + * The RWNXAGCLNAVGAREF0 register will be written. + * @param value - The value to write. + */ +__INLINE void agc_rwnxagclnavgaref0_set(uint32_t value) +{ + REG_PL_WR(AGC_RWNXAGCLNAVGAREF0_ADDR, value); +} + +// field definitions +/// VGASTEPDB field mask +#define AGC_VGASTEPDB_MASK ((uint32_t)0x70000000) +/// VGASTEPDB field LSB position +#define AGC_VGASTEPDB_LSB 28 +/// VGASTEPDB field width +#define AGC_VGASTEPDB_WIDTH ((uint32_t)0x00000003) +/// VGAMINDB field mask +#define AGC_VGAMINDB_MASK ((uint32_t)0x0F000000) +/// VGAMINDB field LSB position +#define AGC_VGAMINDB_LSB 24 +/// VGAMINDB field width +#define AGC_VGAMINDB_WIDTH ((uint32_t)0x00000004) +/// LNAHDB field mask +#define AGC_LNAHDB_MASK ((uint32_t)0x003F0000) +/// LNAHDB field LSB position +#define AGC_LNAHDB_LSB 16 +/// LNAHDB field width +#define AGC_LNAHDB_WIDTH ((uint32_t)0x00000006) +/// LMAMDB field mask +#define AGC_LMAMDB_MASK ((uint32_t)0x00003F00) +/// LMAMDB field LSB position +#define AGC_LMAMDB_LSB 8 +/// LMAMDB field width +#define AGC_LMAMDB_WIDTH ((uint32_t)0x00000006) +/// LNALDB field mask +#define AGC_LNALDB_MASK ((uint32_t)0x0000007F) +/// LNALDB field LSB position +#define AGC_LNALDB_LSB 0 +/// LNALDB field width +#define AGC_LNALDB_WIDTH ((uint32_t)0x00000007) + +/// VGASTEPDB field reset value +#define AGC_VGASTEPDB_RST 0x2 +/// VGAMINDB field reset value +#define AGC_VGAMINDB_RST 0x0 +/// LNAHDB field reset value +#define AGC_LNAHDB_RST 0x1E +/// LMAMDB field reset value +#define AGC_LMAMDB_RST 0xF +/// LNALDB field reset value +#define AGC_LNALDB_RST 0x0 + +/** + * @brief Constructs a value for the RWNXAGCLNAVGAREF0 register given values for its fields + * and writes the value to the register. + * + * @param[in] vgastepdb - The value to use for the VGASTEPDB field. + * @param[in] vgamindb - The value to use for the VGAMINDB field. + * @param[in] lnahdb - The value to use for the LNAHDB field. + * @param[in] lmamdb - The value to use for the LMAMDB field. + * @param[in] lnaldb - The value to use for the LNALDB field. + */ +__INLINE void agc_rwnxagclnavgaref0_pack(uint8_t vgastepdb, uint8_t vgamindb, uint8_t lnahdb, uint8_t lmamdb, uint8_t lnaldb) +{ + ASSERT_ERR((((uint32_t)vgastepdb << 28) & ~((uint32_t)0x70000000)) == 0); + ASSERT_ERR((((uint32_t)vgamindb << 24) & ~((uint32_t)0x0F000000)) == 0); + ASSERT_ERR((((uint32_t)lnahdb << 16) & ~((uint32_t)0x003F0000)) == 0); + ASSERT_ERR((((uint32_t)lmamdb << 8) & ~((uint32_t)0x00003F00)) == 0); + ASSERT_ERR((((uint32_t)lnaldb << 0) & ~((uint32_t)0x0000007F)) == 0); + REG_PL_WR(AGC_RWNXAGCLNAVGAREF0_ADDR, ((uint32_t)vgastepdb << 28) | ((uint32_t)vgamindb << 24) | ((uint32_t)lnahdb << 16) | ((uint32_t)lmamdb << 8) | ((uint32_t)lnaldb << 0)); +} + +/** + * @brief Unpacks RWNXAGCLNAVGAREF0's fields from current value of the RWNXAGCLNAVGAREF0 register. + * + * Reads the RWNXAGCLNAVGAREF0 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] vgastepdb - Will be populated with the current value of this field from the register. + * @param[out] vgamindb - Will be populated with the current value of this field from the register. + * @param[out] lnahdb - Will be populated with the current value of this field from the register. + * @param[out] lmamdb - Will be populated with the current value of this field from the register. + * @param[out] lnaldb - Will be populated with the current value of this field from the register. + */ +__INLINE void agc_rwnxagclnavgaref0_unpack(uint8_t *vgastepdb, uint8_t *vgamindb, uint8_t *lnahdb, uint8_t *lmamdb, uint8_t *lnaldb) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCLNAVGAREF0_ADDR); + + *vgastepdb = (localVal & ((uint32_t)0x70000000)) >> 28; + *vgamindb = (localVal & ((uint32_t)0x0F000000)) >> 24; + *lnahdb = (localVal & ((uint32_t)0x003F0000)) >> 16; + *lmamdb = (localVal & ((uint32_t)0x00003F00)) >> 8; + *lnaldb = (localVal & ((uint32_t)0x0000007F)) >> 0; +} + +/** + * @brief Returns the current value of the VGASTEPDB field in the RWNXAGCLNAVGAREF0 register. + * + * The RWNXAGCLNAVGAREF0 register will be read and the VGASTEPDB field's value will be returned. + * + * @return The current value of the VGASTEPDB field in the RWNXAGCLNAVGAREF0 register. + */ +__INLINE uint8_t agc_vgastepdb_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCLNAVGAREF0_ADDR); + return ((localVal & ((uint32_t)0x70000000)) >> 28); +} + +/** + * @brief Sets the VGASTEPDB field of the RWNXAGCLNAVGAREF0 register. + * + * The RWNXAGCLNAVGAREF0 register will be read, modified to contain the new field value, and written. + * + * @param[in] vgastepdb - The value to set the field to. + */ +__INLINE void agc_vgastepdb_setf(uint8_t vgastepdb) +{ + ASSERT_ERR((((uint32_t)vgastepdb << 28) & ~((uint32_t)0x70000000)) == 0); + REG_PL_WR(AGC_RWNXAGCLNAVGAREF0_ADDR, (REG_PL_RD(AGC_RWNXAGCLNAVGAREF0_ADDR) & ~((uint32_t)0x70000000)) | ((uint32_t)vgastepdb << 28)); +} + +/** + * @brief Returns the current value of the VGAMINDB field in the RWNXAGCLNAVGAREF0 register. + * + * The RWNXAGCLNAVGAREF0 register will be read and the VGAMINDB field's value will be returned. + * + * @return The current value of the VGAMINDB field in the RWNXAGCLNAVGAREF0 register. + */ +__INLINE uint8_t agc_vgamindb_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCLNAVGAREF0_ADDR); + return ((localVal & ((uint32_t)0x0F000000)) >> 24); +} + +/** + * @brief Sets the VGAMINDB field of the RWNXAGCLNAVGAREF0 register. + * + * The RWNXAGCLNAVGAREF0 register will be read, modified to contain the new field value, and written. + * + * @param[in] vgamindb - The value to set the field to. + */ +__INLINE void agc_vgamindb_setf(uint8_t vgamindb) +{ + ASSERT_ERR((((uint32_t)vgamindb << 24) & ~((uint32_t)0x0F000000)) == 0); + REG_PL_WR(AGC_RWNXAGCLNAVGAREF0_ADDR, (REG_PL_RD(AGC_RWNXAGCLNAVGAREF0_ADDR) & ~((uint32_t)0x0F000000)) | ((uint32_t)vgamindb << 24)); +} + +/** + * @brief Returns the current value of the LNAHDB field in the RWNXAGCLNAVGAREF0 register. + * + * The RWNXAGCLNAVGAREF0 register will be read and the LNAHDB field's value will be returned. + * + * @return The current value of the LNAHDB field in the RWNXAGCLNAVGAREF0 register. + */ +__INLINE uint8_t agc_lnahdb_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCLNAVGAREF0_ADDR); + return ((localVal & ((uint32_t)0x003F0000)) >> 16); +} + +/** + * @brief Sets the LNAHDB field of the RWNXAGCLNAVGAREF0 register. + * + * The RWNXAGCLNAVGAREF0 register will be read, modified to contain the new field value, and written. + * + * @param[in] lnahdb - The value to set the field to. + */ +__INLINE void agc_lnahdb_setf(uint8_t lnahdb) +{ + ASSERT_ERR((((uint32_t)lnahdb << 16) & ~((uint32_t)0x003F0000)) == 0); + REG_PL_WR(AGC_RWNXAGCLNAVGAREF0_ADDR, (REG_PL_RD(AGC_RWNXAGCLNAVGAREF0_ADDR) & ~((uint32_t)0x003F0000)) | ((uint32_t)lnahdb << 16)); +} + +/** + * @brief Returns the current value of the LMAMDB field in the RWNXAGCLNAVGAREF0 register. + * + * The RWNXAGCLNAVGAREF0 register will be read and the LMAMDB field's value will be returned. + * + * @return The current value of the LMAMDB field in the RWNXAGCLNAVGAREF0 register. + */ +__INLINE uint8_t agc_lmamdb_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCLNAVGAREF0_ADDR); + return ((localVal & ((uint32_t)0x00003F00)) >> 8); +} + +/** + * @brief Sets the LMAMDB field of the RWNXAGCLNAVGAREF0 register. + * + * The RWNXAGCLNAVGAREF0 register will be read, modified to contain the new field value, and written. + * + * @param[in] lmamdb - The value to set the field to. + */ +__INLINE void agc_lmamdb_setf(uint8_t lmamdb) +{ + ASSERT_ERR((((uint32_t)lmamdb << 8) & ~((uint32_t)0x00003F00)) == 0); + REG_PL_WR(AGC_RWNXAGCLNAVGAREF0_ADDR, (REG_PL_RD(AGC_RWNXAGCLNAVGAREF0_ADDR) & ~((uint32_t)0x00003F00)) | ((uint32_t)lmamdb << 8)); +} + +/** + * @brief Returns the current value of the LNALDB field in the RWNXAGCLNAVGAREF0 register. + * + * The RWNXAGCLNAVGAREF0 register will be read and the LNALDB field's value will be returned. + * + * @return The current value of the LNALDB field in the RWNXAGCLNAVGAREF0 register. + */ +__INLINE uint8_t agc_lnaldb_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCLNAVGAREF0_ADDR); + return ((localVal & ((uint32_t)0x0000007F)) >> 0); +} + +/** + * @brief Sets the LNALDB field of the RWNXAGCLNAVGAREF0 register. + * + * The RWNXAGCLNAVGAREF0 register will be read, modified to contain the new field value, and written. + * + * @param[in] lnaldb - The value to set the field to. + */ +__INLINE void agc_lnaldb_setf(uint8_t lnaldb) +{ + ASSERT_ERR((((uint32_t)lnaldb << 0) & ~((uint32_t)0x0000007F)) == 0); + REG_PL_WR(AGC_RWNXAGCLNAVGAREF0_ADDR, (REG_PL_RD(AGC_RWNXAGCLNAVGAREF0_ADDR) & ~((uint32_t)0x0000007F)) | ((uint32_t)lnaldb << 0)); +} + +/// @} + +/** + * @name RWNXAGCLNAVGAREF1 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:28        DIGGAIN80VS20   0x0
+ *  27:24        DIGGAIN40VS20   0x0
+ *  20:16            VGAINDMAX   0x1F
+ *  13:08           LNAHMTHRDB   0x1E
+ *  05:00           LNAMLTHRDB   0xF
+ * 
+ * + * @{ + */ + +/// Address of the RWNXAGCLNAVGAREF1 register +#define AGC_RWNXAGCLNAVGAREF1_ADDR 0x01002008 +/// Offset of the RWNXAGCLNAVGAREF1 register from the base address +#define AGC_RWNXAGCLNAVGAREF1_OFFSET 0x00002008 +/// Index of the RWNXAGCLNAVGAREF1 register +#define AGC_RWNXAGCLNAVGAREF1_INDEX 0x00000802 +/// Reset value of the RWNXAGCLNAVGAREF1 register +#define AGC_RWNXAGCLNAVGAREF1_RESET 0x001F1E0F + +/** + * @brief Returns the current value of the RWNXAGCLNAVGAREF1 register. + * The RWNXAGCLNAVGAREF1 register will be read and its value returned. + * @return The current value of the RWNXAGCLNAVGAREF1 register. + */ +__INLINE uint32_t agc_rwnxagclnavgaref1_get(void) +{ + return REG_PL_RD(AGC_RWNXAGCLNAVGAREF1_ADDR); +} + +/** + * @brief Sets the RWNXAGCLNAVGAREF1 register to a value. + * The RWNXAGCLNAVGAREF1 register will be written. + * @param value - The value to write. + */ +__INLINE void agc_rwnxagclnavgaref1_set(uint32_t value) +{ + REG_PL_WR(AGC_RWNXAGCLNAVGAREF1_ADDR, value); +} + +// field definitions +/// DIGGAIN80VS20 field mask +#define AGC_DIGGAIN80VS20_MASK ((uint32_t)0xF0000000) +/// DIGGAIN80VS20 field LSB position +#define AGC_DIGGAIN80VS20_LSB 28 +/// DIGGAIN80VS20 field width +#define AGC_DIGGAIN80VS20_WIDTH ((uint32_t)0x00000004) +/// DIGGAIN40VS20 field mask +#define AGC_DIGGAIN40VS20_MASK ((uint32_t)0x0F000000) +/// DIGGAIN40VS20 field LSB position +#define AGC_DIGGAIN40VS20_LSB 24 +/// DIGGAIN40VS20 field width +#define AGC_DIGGAIN40VS20_WIDTH ((uint32_t)0x00000004) +/// VGAINDMAX field mask +#define AGC_VGAINDMAX_MASK ((uint32_t)0x001F0000) +/// VGAINDMAX field LSB position +#define AGC_VGAINDMAX_LSB 16 +/// VGAINDMAX field width +#define AGC_VGAINDMAX_WIDTH ((uint32_t)0x00000005) +/// LNAHMTHRDB field mask +#define AGC_LNAHMTHRDB_MASK ((uint32_t)0x00003F00) +/// LNAHMTHRDB field LSB position +#define AGC_LNAHMTHRDB_LSB 8 +/// LNAHMTHRDB field width +#define AGC_LNAHMTHRDB_WIDTH ((uint32_t)0x00000006) +/// LNAMLTHRDB field mask +#define AGC_LNAMLTHRDB_MASK ((uint32_t)0x0000003F) +/// LNAMLTHRDB field LSB position +#define AGC_LNAMLTHRDB_LSB 0 +/// LNAMLTHRDB field width +#define AGC_LNAMLTHRDB_WIDTH ((uint32_t)0x00000006) + +/// DIGGAIN80VS20 field reset value +#define AGC_DIGGAIN80VS20_RST 0x0 +/// DIGGAIN40VS20 field reset value +#define AGC_DIGGAIN40VS20_RST 0x0 +/// VGAINDMAX field reset value +#define AGC_VGAINDMAX_RST 0x1F +/// LNAHMTHRDB field reset value +#define AGC_LNAHMTHRDB_RST 0x1E +/// LNAMLTHRDB field reset value +#define AGC_LNAMLTHRDB_RST 0xF + +/** + * @brief Constructs a value for the RWNXAGCLNAVGAREF1 register given values for its fields + * and writes the value to the register. + * + * @param[in] diggain80vs20 - The value to use for the DIGGAIN80VS20 field. + * @param[in] diggain40vs20 - The value to use for the DIGGAIN40VS20 field. + * @param[in] vgaindmax - The value to use for the VGAINDMAX field. + * @param[in] lnahmthrdb - The value to use for the LNAHMTHRDB field. + * @param[in] lnamlthrdb - The value to use for the LNAMLTHRDB field. + */ +__INLINE void agc_rwnxagclnavgaref1_pack(uint8_t diggain80vs20, uint8_t diggain40vs20, uint8_t vgaindmax, uint8_t lnahmthrdb, uint8_t lnamlthrdb) +{ + ASSERT_ERR((((uint32_t)diggain80vs20 << 28) & ~((uint32_t)0xF0000000)) == 0); + ASSERT_ERR((((uint32_t)diggain40vs20 << 24) & ~((uint32_t)0x0F000000)) == 0); + ASSERT_ERR((((uint32_t)vgaindmax << 16) & ~((uint32_t)0x001F0000)) == 0); + ASSERT_ERR((((uint32_t)lnahmthrdb << 8) & ~((uint32_t)0x00003F00)) == 0); + ASSERT_ERR((((uint32_t)lnamlthrdb << 0) & ~((uint32_t)0x0000003F)) == 0); + REG_PL_WR(AGC_RWNXAGCLNAVGAREF1_ADDR, ((uint32_t)diggain80vs20 << 28) | ((uint32_t)diggain40vs20 << 24) | ((uint32_t)vgaindmax << 16) | ((uint32_t)lnahmthrdb << 8) | ((uint32_t)lnamlthrdb << 0)); +} + +/** + * @brief Unpacks RWNXAGCLNAVGAREF1's fields from current value of the RWNXAGCLNAVGAREF1 register. + * + * Reads the RWNXAGCLNAVGAREF1 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] diggain80vs20 - Will be populated with the current value of this field from the register. + * @param[out] diggain40vs20 - Will be populated with the current value of this field from the register. + * @param[out] vgaindmax - Will be populated with the current value of this field from the register. + * @param[out] lnahmthrdb - Will be populated with the current value of this field from the register. + * @param[out] lnamlthrdb - Will be populated with the current value of this field from the register. + */ +__INLINE void agc_rwnxagclnavgaref1_unpack(uint8_t *diggain80vs20, uint8_t *diggain40vs20, uint8_t *vgaindmax, uint8_t *lnahmthrdb, uint8_t *lnamlthrdb) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCLNAVGAREF1_ADDR); + + *diggain80vs20 = (localVal & ((uint32_t)0xF0000000)) >> 28; + *diggain40vs20 = (localVal & ((uint32_t)0x0F000000)) >> 24; + *vgaindmax = (localVal & ((uint32_t)0x001F0000)) >> 16; + *lnahmthrdb = (localVal & ((uint32_t)0x00003F00)) >> 8; + *lnamlthrdb = (localVal & ((uint32_t)0x0000003F)) >> 0; +} + +/** + * @brief Returns the current value of the DIGGAIN80VS20 field in the RWNXAGCLNAVGAREF1 register. + * + * The RWNXAGCLNAVGAREF1 register will be read and the DIGGAIN80VS20 field's value will be returned. + * + * @return The current value of the DIGGAIN80VS20 field in the RWNXAGCLNAVGAREF1 register. + */ +__INLINE uint8_t agc_diggain80vs20_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCLNAVGAREF1_ADDR); + return ((localVal & ((uint32_t)0xF0000000)) >> 28); +} + +/** + * @brief Sets the DIGGAIN80VS20 field of the RWNXAGCLNAVGAREF1 register. + * + * The RWNXAGCLNAVGAREF1 register will be read, modified to contain the new field value, and written. + * + * @param[in] diggain80vs20 - The value to set the field to. + */ +__INLINE void agc_diggain80vs20_setf(uint8_t diggain80vs20) +{ + ASSERT_ERR((((uint32_t)diggain80vs20 << 28) & ~((uint32_t)0xF0000000)) == 0); + REG_PL_WR(AGC_RWNXAGCLNAVGAREF1_ADDR, (REG_PL_RD(AGC_RWNXAGCLNAVGAREF1_ADDR) & ~((uint32_t)0xF0000000)) | ((uint32_t)diggain80vs20 << 28)); +} + +/** + * @brief Returns the current value of the DIGGAIN40VS20 field in the RWNXAGCLNAVGAREF1 register. + * + * The RWNXAGCLNAVGAREF1 register will be read and the DIGGAIN40VS20 field's value will be returned. + * + * @return The current value of the DIGGAIN40VS20 field in the RWNXAGCLNAVGAREF1 register. + */ +__INLINE uint8_t agc_diggain40vs20_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCLNAVGAREF1_ADDR); + return ((localVal & ((uint32_t)0x0F000000)) >> 24); +} + +/** + * @brief Sets the DIGGAIN40VS20 field of the RWNXAGCLNAVGAREF1 register. + * + * The RWNXAGCLNAVGAREF1 register will be read, modified to contain the new field value, and written. + * + * @param[in] diggain40vs20 - The value to set the field to. + */ +__INLINE void agc_diggain40vs20_setf(uint8_t diggain40vs20) +{ + ASSERT_ERR((((uint32_t)diggain40vs20 << 24) & ~((uint32_t)0x0F000000)) == 0); + REG_PL_WR(AGC_RWNXAGCLNAVGAREF1_ADDR, (REG_PL_RD(AGC_RWNXAGCLNAVGAREF1_ADDR) & ~((uint32_t)0x0F000000)) | ((uint32_t)diggain40vs20 << 24)); +} + +/** + * @brief Returns the current value of the VGAINDMAX field in the RWNXAGCLNAVGAREF1 register. + * + * The RWNXAGCLNAVGAREF1 register will be read and the VGAINDMAX field's value will be returned. + * + * @return The current value of the VGAINDMAX field in the RWNXAGCLNAVGAREF1 register. + */ +__INLINE uint8_t agc_vgaindmax_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCLNAVGAREF1_ADDR); + return ((localVal & ((uint32_t)0x001F0000)) >> 16); +} + +/** + * @brief Sets the VGAINDMAX field of the RWNXAGCLNAVGAREF1 register. + * + * The RWNXAGCLNAVGAREF1 register will be read, modified to contain the new field value, and written. + * + * @param[in] vgaindmax - The value to set the field to. + */ +__INLINE void agc_vgaindmax_setf(uint8_t vgaindmax) +{ + ASSERT_ERR((((uint32_t)vgaindmax << 16) & ~((uint32_t)0x001F0000)) == 0); + REG_PL_WR(AGC_RWNXAGCLNAVGAREF1_ADDR, (REG_PL_RD(AGC_RWNXAGCLNAVGAREF1_ADDR) & ~((uint32_t)0x001F0000)) | ((uint32_t)vgaindmax << 16)); +} + +/** + * @brief Returns the current value of the LNAHMTHRDB field in the RWNXAGCLNAVGAREF1 register. + * + * The RWNXAGCLNAVGAREF1 register will be read and the LNAHMTHRDB field's value will be returned. + * + * @return The current value of the LNAHMTHRDB field in the RWNXAGCLNAVGAREF1 register. + */ +__INLINE uint8_t agc_lnahmthrdb_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCLNAVGAREF1_ADDR); + return ((localVal & ((uint32_t)0x00003F00)) >> 8); +} + +/** + * @brief Sets the LNAHMTHRDB field of the RWNXAGCLNAVGAREF1 register. + * + * The RWNXAGCLNAVGAREF1 register will be read, modified to contain the new field value, and written. + * + * @param[in] lnahmthrdb - The value to set the field to. + */ +__INLINE void agc_lnahmthrdb_setf(uint8_t lnahmthrdb) +{ + ASSERT_ERR((((uint32_t)lnahmthrdb << 8) & ~((uint32_t)0x00003F00)) == 0); + REG_PL_WR(AGC_RWNXAGCLNAVGAREF1_ADDR, (REG_PL_RD(AGC_RWNXAGCLNAVGAREF1_ADDR) & ~((uint32_t)0x00003F00)) | ((uint32_t)lnahmthrdb << 8)); +} + +/** + * @brief Returns the current value of the LNAMLTHRDB field in the RWNXAGCLNAVGAREF1 register. + * + * The RWNXAGCLNAVGAREF1 register will be read and the LNAMLTHRDB field's value will be returned. + * + * @return The current value of the LNAMLTHRDB field in the RWNXAGCLNAVGAREF1 register. + */ +__INLINE uint8_t agc_lnamlthrdb_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCLNAVGAREF1_ADDR); + return ((localVal & ((uint32_t)0x0000003F)) >> 0); +} + +/** + * @brief Sets the LNAMLTHRDB field of the RWNXAGCLNAVGAREF1 register. + * + * The RWNXAGCLNAVGAREF1 register will be read, modified to contain the new field value, and written. + * + * @param[in] lnamlthrdb - The value to set the field to. + */ +__INLINE void agc_lnamlthrdb_setf(uint8_t lnamlthrdb) +{ + ASSERT_ERR((((uint32_t)lnamlthrdb << 0) & ~((uint32_t)0x0000003F)) == 0); + REG_PL_WR(AGC_RWNXAGCLNAVGAREF1_ADDR, (REG_PL_RD(AGC_RWNXAGCLNAVGAREF1_ADDR) & ~((uint32_t)0x0000003F)) | ((uint32_t)lnamlthrdb << 0)); +} + +/// @} + +/** + * @name RWNXAGCACI20MARG0 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  29:24        ACI20MARGMCS3   0x2
+ *  21:16        ACI20MARGMCS2   0x4
+ *  13:08        ACI20MARGMCS1   0x5
+ *  05:00        ACI20MARGMCS0   0x7
+ * 
+ * + * @{ + */ + +/// Address of the RWNXAGCACI20MARG0 register +#define AGC_RWNXAGCACI20MARG0_ADDR 0x0100200C +/// Offset of the RWNXAGCACI20MARG0 register from the base address +#define AGC_RWNXAGCACI20MARG0_OFFSET 0x0000200C +/// Index of the RWNXAGCACI20MARG0 register +#define AGC_RWNXAGCACI20MARG0_INDEX 0x00000803 +/// Reset value of the RWNXAGCACI20MARG0 register +#define AGC_RWNXAGCACI20MARG0_RESET 0x02040507 + +/** + * @brief Returns the current value of the RWNXAGCACI20MARG0 register. + * The RWNXAGCACI20MARG0 register will be read and its value returned. + * @return The current value of the RWNXAGCACI20MARG0 register. + */ +__INLINE uint32_t agc_rwnxagcaci20marg0_get(void) +{ + return REG_PL_RD(AGC_RWNXAGCACI20MARG0_ADDR); +} + +/** + * @brief Sets the RWNXAGCACI20MARG0 register to a value. + * The RWNXAGCACI20MARG0 register will be written. + * @param value - The value to write. + */ +__INLINE void agc_rwnxagcaci20marg0_set(uint32_t value) +{ + REG_PL_WR(AGC_RWNXAGCACI20MARG0_ADDR, value); +} + +// field definitions +/// ACI20MARGMCS3 field mask +#define AGC_ACI20MARGMCS3_MASK ((uint32_t)0x3F000000) +/// ACI20MARGMCS3 field LSB position +#define AGC_ACI20MARGMCS3_LSB 24 +/// ACI20MARGMCS3 field width +#define AGC_ACI20MARGMCS3_WIDTH ((uint32_t)0x00000006) +/// ACI20MARGMCS2 field mask +#define AGC_ACI20MARGMCS2_MASK ((uint32_t)0x003F0000) +/// ACI20MARGMCS2 field LSB position +#define AGC_ACI20MARGMCS2_LSB 16 +/// ACI20MARGMCS2 field width +#define AGC_ACI20MARGMCS2_WIDTH ((uint32_t)0x00000006) +/// ACI20MARGMCS1 field mask +#define AGC_ACI20MARGMCS1_MASK ((uint32_t)0x00003F00) +/// ACI20MARGMCS1 field LSB position +#define AGC_ACI20MARGMCS1_LSB 8 +/// ACI20MARGMCS1 field width +#define AGC_ACI20MARGMCS1_WIDTH ((uint32_t)0x00000006) +/// ACI20MARGMCS0 field mask +#define AGC_ACI20MARGMCS0_MASK ((uint32_t)0x0000003F) +/// ACI20MARGMCS0 field LSB position +#define AGC_ACI20MARGMCS0_LSB 0 +/// ACI20MARGMCS0 field width +#define AGC_ACI20MARGMCS0_WIDTH ((uint32_t)0x00000006) + +/// ACI20MARGMCS3 field reset value +#define AGC_ACI20MARGMCS3_RST 0x2 +/// ACI20MARGMCS2 field reset value +#define AGC_ACI20MARGMCS2_RST 0x4 +/// ACI20MARGMCS1 field reset value +#define AGC_ACI20MARGMCS1_RST 0x5 +/// ACI20MARGMCS0 field reset value +#define AGC_ACI20MARGMCS0_RST 0x7 + +/** + * @brief Constructs a value for the RWNXAGCACI20MARG0 register given values for its fields + * and writes the value to the register. + * + * @param[in] aci20margmcs3 - The value to use for the ACI20MARGMCS3 field. + * @param[in] aci20margmcs2 - The value to use for the ACI20MARGMCS2 field. + * @param[in] aci20margmcs1 - The value to use for the ACI20MARGMCS1 field. + * @param[in] aci20margmcs0 - The value to use for the ACI20MARGMCS0 field. + */ +__INLINE void agc_rwnxagcaci20marg0_pack(uint8_t aci20margmcs3, uint8_t aci20margmcs2, uint8_t aci20margmcs1, uint8_t aci20margmcs0) +{ + ASSERT_ERR((((uint32_t)aci20margmcs3 << 24) & ~((uint32_t)0x3F000000)) == 0); + ASSERT_ERR((((uint32_t)aci20margmcs2 << 16) & ~((uint32_t)0x003F0000)) == 0); + ASSERT_ERR((((uint32_t)aci20margmcs1 << 8) & ~((uint32_t)0x00003F00)) == 0); + ASSERT_ERR((((uint32_t)aci20margmcs0 << 0) & ~((uint32_t)0x0000003F)) == 0); + REG_PL_WR(AGC_RWNXAGCACI20MARG0_ADDR, ((uint32_t)aci20margmcs3 << 24) | ((uint32_t)aci20margmcs2 << 16) | ((uint32_t)aci20margmcs1 << 8) | ((uint32_t)aci20margmcs0 << 0)); +} + +/** + * @brief Unpacks RWNXAGCACI20MARG0's fields from current value of the RWNXAGCACI20MARG0 register. + * + * Reads the RWNXAGCACI20MARG0 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] aci20margmcs3 - Will be populated with the current value of this field from the register. + * @param[out] aci20margmcs2 - Will be populated with the current value of this field from the register. + * @param[out] aci20margmcs1 - Will be populated with the current value of this field from the register. + * @param[out] aci20margmcs0 - Will be populated with the current value of this field from the register. + */ +__INLINE void agc_rwnxagcaci20marg0_unpack(uint8_t *aci20margmcs3, uint8_t *aci20margmcs2, uint8_t *aci20margmcs1, uint8_t *aci20margmcs0) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCACI20MARG0_ADDR); + + *aci20margmcs3 = (localVal & ((uint32_t)0x3F000000)) >> 24; + *aci20margmcs2 = (localVal & ((uint32_t)0x003F0000)) >> 16; + *aci20margmcs1 = (localVal & ((uint32_t)0x00003F00)) >> 8; + *aci20margmcs0 = (localVal & ((uint32_t)0x0000003F)) >> 0; +} + +/** + * @brief Returns the current value of the ACI20MARGMCS3 field in the RWNXAGCACI20MARG0 register. + * + * The RWNXAGCACI20MARG0 register will be read and the ACI20MARGMCS3 field's value will be returned. + * + * @return The current value of the ACI20MARGMCS3 field in the RWNXAGCACI20MARG0 register. + */ +__INLINE uint8_t agc_aci20margmcs3_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCACI20MARG0_ADDR); + return ((localVal & ((uint32_t)0x3F000000)) >> 24); +} + +/** + * @brief Sets the ACI20MARGMCS3 field of the RWNXAGCACI20MARG0 register. + * + * The RWNXAGCACI20MARG0 register will be read, modified to contain the new field value, and written. + * + * @param[in] aci20margmcs3 - The value to set the field to. + */ +__INLINE void agc_aci20margmcs3_setf(uint8_t aci20margmcs3) +{ + ASSERT_ERR((((uint32_t)aci20margmcs3 << 24) & ~((uint32_t)0x3F000000)) == 0); + REG_PL_WR(AGC_RWNXAGCACI20MARG0_ADDR, (REG_PL_RD(AGC_RWNXAGCACI20MARG0_ADDR) & ~((uint32_t)0x3F000000)) | ((uint32_t)aci20margmcs3 << 24)); +} + +/** + * @brief Returns the current value of the ACI20MARGMCS2 field in the RWNXAGCACI20MARG0 register. + * + * The RWNXAGCACI20MARG0 register will be read and the ACI20MARGMCS2 field's value will be returned. + * + * @return The current value of the ACI20MARGMCS2 field in the RWNXAGCACI20MARG0 register. + */ +__INLINE uint8_t agc_aci20margmcs2_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCACI20MARG0_ADDR); + return ((localVal & ((uint32_t)0x003F0000)) >> 16); +} + +/** + * @brief Sets the ACI20MARGMCS2 field of the RWNXAGCACI20MARG0 register. + * + * The RWNXAGCACI20MARG0 register will be read, modified to contain the new field value, and written. + * + * @param[in] aci20margmcs2 - The value to set the field to. + */ +__INLINE void agc_aci20margmcs2_setf(uint8_t aci20margmcs2) +{ + ASSERT_ERR((((uint32_t)aci20margmcs2 << 16) & ~((uint32_t)0x003F0000)) == 0); + REG_PL_WR(AGC_RWNXAGCACI20MARG0_ADDR, (REG_PL_RD(AGC_RWNXAGCACI20MARG0_ADDR) & ~((uint32_t)0x003F0000)) | ((uint32_t)aci20margmcs2 << 16)); +} + +/** + * @brief Returns the current value of the ACI20MARGMCS1 field in the RWNXAGCACI20MARG0 register. + * + * The RWNXAGCACI20MARG0 register will be read and the ACI20MARGMCS1 field's value will be returned. + * + * @return The current value of the ACI20MARGMCS1 field in the RWNXAGCACI20MARG0 register. + */ +__INLINE uint8_t agc_aci20margmcs1_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCACI20MARG0_ADDR); + return ((localVal & ((uint32_t)0x00003F00)) >> 8); +} + +/** + * @brief Sets the ACI20MARGMCS1 field of the RWNXAGCACI20MARG0 register. + * + * The RWNXAGCACI20MARG0 register will be read, modified to contain the new field value, and written. + * + * @param[in] aci20margmcs1 - The value to set the field to. + */ +__INLINE void agc_aci20margmcs1_setf(uint8_t aci20margmcs1) +{ + ASSERT_ERR((((uint32_t)aci20margmcs1 << 8) & ~((uint32_t)0x00003F00)) == 0); + REG_PL_WR(AGC_RWNXAGCACI20MARG0_ADDR, (REG_PL_RD(AGC_RWNXAGCACI20MARG0_ADDR) & ~((uint32_t)0x00003F00)) | ((uint32_t)aci20margmcs1 << 8)); +} + +/** + * @brief Returns the current value of the ACI20MARGMCS0 field in the RWNXAGCACI20MARG0 register. + * + * The RWNXAGCACI20MARG0 register will be read and the ACI20MARGMCS0 field's value will be returned. + * + * @return The current value of the ACI20MARGMCS0 field in the RWNXAGCACI20MARG0 register. + */ +__INLINE uint8_t agc_aci20margmcs0_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCACI20MARG0_ADDR); + return ((localVal & ((uint32_t)0x0000003F)) >> 0); +} + +/** + * @brief Sets the ACI20MARGMCS0 field of the RWNXAGCACI20MARG0 register. + * + * The RWNXAGCACI20MARG0 register will be read, modified to contain the new field value, and written. + * + * @param[in] aci20margmcs0 - The value to set the field to. + */ +__INLINE void agc_aci20margmcs0_setf(uint8_t aci20margmcs0) +{ + ASSERT_ERR((((uint32_t)aci20margmcs0 << 0) & ~((uint32_t)0x0000003F)) == 0); + REG_PL_WR(AGC_RWNXAGCACI20MARG0_ADDR, (REG_PL_RD(AGC_RWNXAGCACI20MARG0_ADDR) & ~((uint32_t)0x0000003F)) | ((uint32_t)aci20margmcs0 << 0)); +} + +/// @} + +/** + * @name RWNXAGCACI20MARG1 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  29:24        ACI20MARGMCS7   0x0
+ *  21:16        ACI20MARGMCS6   0x0
+ *  13:08        ACI20MARGMCS5   0x0
+ *  05:00        ACI20MARGMCS4   0x1
+ * 
+ * + * @{ + */ + +/// Address of the RWNXAGCACI20MARG1 register +#define AGC_RWNXAGCACI20MARG1_ADDR 0x01002010 +/// Offset of the RWNXAGCACI20MARG1 register from the base address +#define AGC_RWNXAGCACI20MARG1_OFFSET 0x00002010 +/// Index of the RWNXAGCACI20MARG1 register +#define AGC_RWNXAGCACI20MARG1_INDEX 0x00000804 +/// Reset value of the RWNXAGCACI20MARG1 register +#define AGC_RWNXAGCACI20MARG1_RESET 0x00000001 + +/** + * @brief Returns the current value of the RWNXAGCACI20MARG1 register. + * The RWNXAGCACI20MARG1 register will be read and its value returned. + * @return The current value of the RWNXAGCACI20MARG1 register. + */ +__INLINE uint32_t agc_rwnxagcaci20marg1_get(void) +{ + return REG_PL_RD(AGC_RWNXAGCACI20MARG1_ADDR); +} + +/** + * @brief Sets the RWNXAGCACI20MARG1 register to a value. + * The RWNXAGCACI20MARG1 register will be written. + * @param value - The value to write. + */ +__INLINE void agc_rwnxagcaci20marg1_set(uint32_t value) +{ + REG_PL_WR(AGC_RWNXAGCACI20MARG1_ADDR, value); +} + +// field definitions +/// ACI20MARGMCS7 field mask +#define AGC_ACI20MARGMCS7_MASK ((uint32_t)0x3F000000) +/// ACI20MARGMCS7 field LSB position +#define AGC_ACI20MARGMCS7_LSB 24 +/// ACI20MARGMCS7 field width +#define AGC_ACI20MARGMCS7_WIDTH ((uint32_t)0x00000006) +/// ACI20MARGMCS6 field mask +#define AGC_ACI20MARGMCS6_MASK ((uint32_t)0x003F0000) +/// ACI20MARGMCS6 field LSB position +#define AGC_ACI20MARGMCS6_LSB 16 +/// ACI20MARGMCS6 field width +#define AGC_ACI20MARGMCS6_WIDTH ((uint32_t)0x00000006) +/// ACI20MARGMCS5 field mask +#define AGC_ACI20MARGMCS5_MASK ((uint32_t)0x00003F00) +/// ACI20MARGMCS5 field LSB position +#define AGC_ACI20MARGMCS5_LSB 8 +/// ACI20MARGMCS5 field width +#define AGC_ACI20MARGMCS5_WIDTH ((uint32_t)0x00000006) +/// ACI20MARGMCS4 field mask +#define AGC_ACI20MARGMCS4_MASK ((uint32_t)0x0000003F) +/// ACI20MARGMCS4 field LSB position +#define AGC_ACI20MARGMCS4_LSB 0 +/// ACI20MARGMCS4 field width +#define AGC_ACI20MARGMCS4_WIDTH ((uint32_t)0x00000006) + +/// ACI20MARGMCS7 field reset value +#define AGC_ACI20MARGMCS7_RST 0x0 +/// ACI20MARGMCS6 field reset value +#define AGC_ACI20MARGMCS6_RST 0x0 +/// ACI20MARGMCS5 field reset value +#define AGC_ACI20MARGMCS5_RST 0x0 +/// ACI20MARGMCS4 field reset value +#define AGC_ACI20MARGMCS4_RST 0x1 + +/** + * @brief Constructs a value for the RWNXAGCACI20MARG1 register given values for its fields + * and writes the value to the register. + * + * @param[in] aci20margmcs7 - The value to use for the ACI20MARGMCS7 field. + * @param[in] aci20margmcs6 - The value to use for the ACI20MARGMCS6 field. + * @param[in] aci20margmcs5 - The value to use for the ACI20MARGMCS5 field. + * @param[in] aci20margmcs4 - The value to use for the ACI20MARGMCS4 field. + */ +__INLINE void agc_rwnxagcaci20marg1_pack(uint8_t aci20margmcs7, uint8_t aci20margmcs6, uint8_t aci20margmcs5, uint8_t aci20margmcs4) +{ + ASSERT_ERR((((uint32_t)aci20margmcs7 << 24) & ~((uint32_t)0x3F000000)) == 0); + ASSERT_ERR((((uint32_t)aci20margmcs6 << 16) & ~((uint32_t)0x003F0000)) == 0); + ASSERT_ERR((((uint32_t)aci20margmcs5 << 8) & ~((uint32_t)0x00003F00)) == 0); + ASSERT_ERR((((uint32_t)aci20margmcs4 << 0) & ~((uint32_t)0x0000003F)) == 0); + REG_PL_WR(AGC_RWNXAGCACI20MARG1_ADDR, ((uint32_t)aci20margmcs7 << 24) | ((uint32_t)aci20margmcs6 << 16) | ((uint32_t)aci20margmcs5 << 8) | ((uint32_t)aci20margmcs4 << 0)); +} + +/** + * @brief Unpacks RWNXAGCACI20MARG1's fields from current value of the RWNXAGCACI20MARG1 register. + * + * Reads the RWNXAGCACI20MARG1 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] aci20margmcs7 - Will be populated with the current value of this field from the register. + * @param[out] aci20margmcs6 - Will be populated with the current value of this field from the register. + * @param[out] aci20margmcs5 - Will be populated with the current value of this field from the register. + * @param[out] aci20margmcs4 - Will be populated with the current value of this field from the register. + */ +__INLINE void agc_rwnxagcaci20marg1_unpack(uint8_t *aci20margmcs7, uint8_t *aci20margmcs6, uint8_t *aci20margmcs5, uint8_t *aci20margmcs4) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCACI20MARG1_ADDR); + + *aci20margmcs7 = (localVal & ((uint32_t)0x3F000000)) >> 24; + *aci20margmcs6 = (localVal & ((uint32_t)0x003F0000)) >> 16; + *aci20margmcs5 = (localVal & ((uint32_t)0x00003F00)) >> 8; + *aci20margmcs4 = (localVal & ((uint32_t)0x0000003F)) >> 0; +} + +/** + * @brief Returns the current value of the ACI20MARGMCS7 field in the RWNXAGCACI20MARG1 register. + * + * The RWNXAGCACI20MARG1 register will be read and the ACI20MARGMCS7 field's value will be returned. + * + * @return The current value of the ACI20MARGMCS7 field in the RWNXAGCACI20MARG1 register. + */ +__INLINE uint8_t agc_aci20margmcs7_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCACI20MARG1_ADDR); + return ((localVal & ((uint32_t)0x3F000000)) >> 24); +} + +/** + * @brief Sets the ACI20MARGMCS7 field of the RWNXAGCACI20MARG1 register. + * + * The RWNXAGCACI20MARG1 register will be read, modified to contain the new field value, and written. + * + * @param[in] aci20margmcs7 - The value to set the field to. + */ +__INLINE void agc_aci20margmcs7_setf(uint8_t aci20margmcs7) +{ + ASSERT_ERR((((uint32_t)aci20margmcs7 << 24) & ~((uint32_t)0x3F000000)) == 0); + REG_PL_WR(AGC_RWNXAGCACI20MARG1_ADDR, (REG_PL_RD(AGC_RWNXAGCACI20MARG1_ADDR) & ~((uint32_t)0x3F000000)) | ((uint32_t)aci20margmcs7 << 24)); +} + +/** + * @brief Returns the current value of the ACI20MARGMCS6 field in the RWNXAGCACI20MARG1 register. + * + * The RWNXAGCACI20MARG1 register will be read and the ACI20MARGMCS6 field's value will be returned. + * + * @return The current value of the ACI20MARGMCS6 field in the RWNXAGCACI20MARG1 register. + */ +__INLINE uint8_t agc_aci20margmcs6_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCACI20MARG1_ADDR); + return ((localVal & ((uint32_t)0x003F0000)) >> 16); +} + +/** + * @brief Sets the ACI20MARGMCS6 field of the RWNXAGCACI20MARG1 register. + * + * The RWNXAGCACI20MARG1 register will be read, modified to contain the new field value, and written. + * + * @param[in] aci20margmcs6 - The value to set the field to. + */ +__INLINE void agc_aci20margmcs6_setf(uint8_t aci20margmcs6) +{ + ASSERT_ERR((((uint32_t)aci20margmcs6 << 16) & ~((uint32_t)0x003F0000)) == 0); + REG_PL_WR(AGC_RWNXAGCACI20MARG1_ADDR, (REG_PL_RD(AGC_RWNXAGCACI20MARG1_ADDR) & ~((uint32_t)0x003F0000)) | ((uint32_t)aci20margmcs6 << 16)); +} + +/** + * @brief Returns the current value of the ACI20MARGMCS5 field in the RWNXAGCACI20MARG1 register. + * + * The RWNXAGCACI20MARG1 register will be read and the ACI20MARGMCS5 field's value will be returned. + * + * @return The current value of the ACI20MARGMCS5 field in the RWNXAGCACI20MARG1 register. + */ +__INLINE uint8_t agc_aci20margmcs5_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCACI20MARG1_ADDR); + return ((localVal & ((uint32_t)0x00003F00)) >> 8); +} + +/** + * @brief Sets the ACI20MARGMCS5 field of the RWNXAGCACI20MARG1 register. + * + * The RWNXAGCACI20MARG1 register will be read, modified to contain the new field value, and written. + * + * @param[in] aci20margmcs5 - The value to set the field to. + */ +__INLINE void agc_aci20margmcs5_setf(uint8_t aci20margmcs5) +{ + ASSERT_ERR((((uint32_t)aci20margmcs5 << 8) & ~((uint32_t)0x00003F00)) == 0); + REG_PL_WR(AGC_RWNXAGCACI20MARG1_ADDR, (REG_PL_RD(AGC_RWNXAGCACI20MARG1_ADDR) & ~((uint32_t)0x00003F00)) | ((uint32_t)aci20margmcs5 << 8)); +} + +/** + * @brief Returns the current value of the ACI20MARGMCS4 field in the RWNXAGCACI20MARG1 register. + * + * The RWNXAGCACI20MARG1 register will be read and the ACI20MARGMCS4 field's value will be returned. + * + * @return The current value of the ACI20MARGMCS4 field in the RWNXAGCACI20MARG1 register. + */ +__INLINE uint8_t agc_aci20margmcs4_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCACI20MARG1_ADDR); + return ((localVal & ((uint32_t)0x0000003F)) >> 0); +} + +/** + * @brief Sets the ACI20MARGMCS4 field of the RWNXAGCACI20MARG1 register. + * + * The RWNXAGCACI20MARG1 register will be read, modified to contain the new field value, and written. + * + * @param[in] aci20margmcs4 - The value to set the field to. + */ +__INLINE void agc_aci20margmcs4_setf(uint8_t aci20margmcs4) +{ + ASSERT_ERR((((uint32_t)aci20margmcs4 << 0) & ~((uint32_t)0x0000003F)) == 0); + REG_PL_WR(AGC_RWNXAGCACI20MARG1_ADDR, (REG_PL_RD(AGC_RWNXAGCACI20MARG1_ADDR) & ~((uint32_t)0x0000003F)) | ((uint32_t)aci20margmcs4 << 0)); +} + +/// @} + +/** + * @name RWNXAGCACI20MARG2 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  13:08        ACI20MARGMCS9   0x0
+ *  05:00        ACI20MARGMCS8   0x0
+ * 
+ * + * @{ + */ + +/// Address of the RWNXAGCACI20MARG2 register +#define AGC_RWNXAGCACI20MARG2_ADDR 0x01002014 +/// Offset of the RWNXAGCACI20MARG2 register from the base address +#define AGC_RWNXAGCACI20MARG2_OFFSET 0x00002014 +/// Index of the RWNXAGCACI20MARG2 register +#define AGC_RWNXAGCACI20MARG2_INDEX 0x00000805 +/// Reset value of the RWNXAGCACI20MARG2 register +#define AGC_RWNXAGCACI20MARG2_RESET 0x00000000 + +/** + * @brief Returns the current value of the RWNXAGCACI20MARG2 register. + * The RWNXAGCACI20MARG2 register will be read and its value returned. + * @return The current value of the RWNXAGCACI20MARG2 register. + */ +__INLINE uint32_t agc_rwnxagcaci20marg2_get(void) +{ + return REG_PL_RD(AGC_RWNXAGCACI20MARG2_ADDR); +} + +/** + * @brief Sets the RWNXAGCACI20MARG2 register to a value. + * The RWNXAGCACI20MARG2 register will be written. + * @param value - The value to write. + */ +__INLINE void agc_rwnxagcaci20marg2_set(uint32_t value) +{ + REG_PL_WR(AGC_RWNXAGCACI20MARG2_ADDR, value); +} + +// field definitions +/// ACI20MARGMCS9 field mask +#define AGC_ACI20MARGMCS9_MASK ((uint32_t)0x00003F00) +/// ACI20MARGMCS9 field LSB position +#define AGC_ACI20MARGMCS9_LSB 8 +/// ACI20MARGMCS9 field width +#define AGC_ACI20MARGMCS9_WIDTH ((uint32_t)0x00000006) +/// ACI20MARGMCS8 field mask +#define AGC_ACI20MARGMCS8_MASK ((uint32_t)0x0000003F) +/// ACI20MARGMCS8 field LSB position +#define AGC_ACI20MARGMCS8_LSB 0 +/// ACI20MARGMCS8 field width +#define AGC_ACI20MARGMCS8_WIDTH ((uint32_t)0x00000006) + +/// ACI20MARGMCS9 field reset value +#define AGC_ACI20MARGMCS9_RST 0x0 +/// ACI20MARGMCS8 field reset value +#define AGC_ACI20MARGMCS8_RST 0x0 + +/** + * @brief Constructs a value for the RWNXAGCACI20MARG2 register given values for its fields + * and writes the value to the register. + * + * @param[in] aci20margmcs9 - The value to use for the ACI20MARGMCS9 field. + * @param[in] aci20margmcs8 - The value to use for the ACI20MARGMCS8 field. + */ +__INLINE void agc_rwnxagcaci20marg2_pack(uint8_t aci20margmcs9, uint8_t aci20margmcs8) +{ + ASSERT_ERR((((uint32_t)aci20margmcs9 << 8) & ~((uint32_t)0x00003F00)) == 0); + ASSERT_ERR((((uint32_t)aci20margmcs8 << 0) & ~((uint32_t)0x0000003F)) == 0); + REG_PL_WR(AGC_RWNXAGCACI20MARG2_ADDR, ((uint32_t)aci20margmcs9 << 8) | ((uint32_t)aci20margmcs8 << 0)); +} + +/** + * @brief Unpacks RWNXAGCACI20MARG2's fields from current value of the RWNXAGCACI20MARG2 register. + * + * Reads the RWNXAGCACI20MARG2 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] aci20margmcs9 - Will be populated with the current value of this field from the register. + * @param[out] aci20margmcs8 - Will be populated with the current value of this field from the register. + */ +__INLINE void agc_rwnxagcaci20marg2_unpack(uint8_t *aci20margmcs9, uint8_t *aci20margmcs8) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCACI20MARG2_ADDR); + + *aci20margmcs9 = (localVal & ((uint32_t)0x00003F00)) >> 8; + *aci20margmcs8 = (localVal & ((uint32_t)0x0000003F)) >> 0; +} + +/** + * @brief Returns the current value of the ACI20MARGMCS9 field in the RWNXAGCACI20MARG2 register. + * + * The RWNXAGCACI20MARG2 register will be read and the ACI20MARGMCS9 field's value will be returned. + * + * @return The current value of the ACI20MARGMCS9 field in the RWNXAGCACI20MARG2 register. + */ +__INLINE uint8_t agc_aci20margmcs9_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCACI20MARG2_ADDR); + return ((localVal & ((uint32_t)0x00003F00)) >> 8); +} + +/** + * @brief Sets the ACI20MARGMCS9 field of the RWNXAGCACI20MARG2 register. + * + * The RWNXAGCACI20MARG2 register will be read, modified to contain the new field value, and written. + * + * @param[in] aci20margmcs9 - The value to set the field to. + */ +__INLINE void agc_aci20margmcs9_setf(uint8_t aci20margmcs9) +{ + ASSERT_ERR((((uint32_t)aci20margmcs9 << 8) & ~((uint32_t)0x00003F00)) == 0); + REG_PL_WR(AGC_RWNXAGCACI20MARG2_ADDR, (REG_PL_RD(AGC_RWNXAGCACI20MARG2_ADDR) & ~((uint32_t)0x00003F00)) | ((uint32_t)aci20margmcs9 << 8)); +} + +/** + * @brief Returns the current value of the ACI20MARGMCS8 field in the RWNXAGCACI20MARG2 register. + * + * The RWNXAGCACI20MARG2 register will be read and the ACI20MARGMCS8 field's value will be returned. + * + * @return The current value of the ACI20MARGMCS8 field in the RWNXAGCACI20MARG2 register. + */ +__INLINE uint8_t agc_aci20margmcs8_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCACI20MARG2_ADDR); + return ((localVal & ((uint32_t)0x0000003F)) >> 0); +} + +/** + * @brief Sets the ACI20MARGMCS8 field of the RWNXAGCACI20MARG2 register. + * + * The RWNXAGCACI20MARG2 register will be read, modified to contain the new field value, and written. + * + * @param[in] aci20margmcs8 - The value to set the field to. + */ +__INLINE void agc_aci20margmcs8_setf(uint8_t aci20margmcs8) +{ + ASSERT_ERR((((uint32_t)aci20margmcs8 << 0) & ~((uint32_t)0x0000003F)) == 0); + REG_PL_WR(AGC_RWNXAGCACI20MARG2_ADDR, (REG_PL_RD(AGC_RWNXAGCACI20MARG2_ADDR) & ~((uint32_t)0x0000003F)) | ((uint32_t)aci20margmcs8 << 0)); +} + +/// @} + +/** + * @name RWNXAGCACI40MARG0 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  29:24        ACI40MARGMCS3   0x9
+ *  21:16        ACI40MARGMCS2   0xB
+ *  13:08        ACI40MARGMCS1   0xD
+ *  05:00        ACI40MARGMCS0   0x10
+ * 
+ * + * @{ + */ + +/// Address of the RWNXAGCACI40MARG0 register +#define AGC_RWNXAGCACI40MARG0_ADDR 0x01002018 +/// Offset of the RWNXAGCACI40MARG0 register from the base address +#define AGC_RWNXAGCACI40MARG0_OFFSET 0x00002018 +/// Index of the RWNXAGCACI40MARG0 register +#define AGC_RWNXAGCACI40MARG0_INDEX 0x00000806 +/// Reset value of the RWNXAGCACI40MARG0 register +#define AGC_RWNXAGCACI40MARG0_RESET 0x090B0D10 + +/** + * @brief Returns the current value of the RWNXAGCACI40MARG0 register. + * The RWNXAGCACI40MARG0 register will be read and its value returned. + * @return The current value of the RWNXAGCACI40MARG0 register. + */ +__INLINE uint32_t agc_rwnxagcaci40marg0_get(void) +{ + return REG_PL_RD(AGC_RWNXAGCACI40MARG0_ADDR); +} + +/** + * @brief Sets the RWNXAGCACI40MARG0 register to a value. + * The RWNXAGCACI40MARG0 register will be written. + * @param value - The value to write. + */ +__INLINE void agc_rwnxagcaci40marg0_set(uint32_t value) +{ + REG_PL_WR(AGC_RWNXAGCACI40MARG0_ADDR, value); +} + +// field definitions +/// ACI40MARGMCS3 field mask +#define AGC_ACI40MARGMCS3_MASK ((uint32_t)0x3F000000) +/// ACI40MARGMCS3 field LSB position +#define AGC_ACI40MARGMCS3_LSB 24 +/// ACI40MARGMCS3 field width +#define AGC_ACI40MARGMCS3_WIDTH ((uint32_t)0x00000006) +/// ACI40MARGMCS2 field mask +#define AGC_ACI40MARGMCS2_MASK ((uint32_t)0x003F0000) +/// ACI40MARGMCS2 field LSB position +#define AGC_ACI40MARGMCS2_LSB 16 +/// ACI40MARGMCS2 field width +#define AGC_ACI40MARGMCS2_WIDTH ((uint32_t)0x00000006) +/// ACI40MARGMCS1 field mask +#define AGC_ACI40MARGMCS1_MASK ((uint32_t)0x00003F00) +/// ACI40MARGMCS1 field LSB position +#define AGC_ACI40MARGMCS1_LSB 8 +/// ACI40MARGMCS1 field width +#define AGC_ACI40MARGMCS1_WIDTH ((uint32_t)0x00000006) +/// ACI40MARGMCS0 field mask +#define AGC_ACI40MARGMCS0_MASK ((uint32_t)0x0000003F) +/// ACI40MARGMCS0 field LSB position +#define AGC_ACI40MARGMCS0_LSB 0 +/// ACI40MARGMCS0 field width +#define AGC_ACI40MARGMCS0_WIDTH ((uint32_t)0x00000006) + +/// ACI40MARGMCS3 field reset value +#define AGC_ACI40MARGMCS3_RST 0x9 +/// ACI40MARGMCS2 field reset value +#define AGC_ACI40MARGMCS2_RST 0xB +/// ACI40MARGMCS1 field reset value +#define AGC_ACI40MARGMCS1_RST 0xD +/// ACI40MARGMCS0 field reset value +#define AGC_ACI40MARGMCS0_RST 0x10 + +/** + * @brief Constructs a value for the RWNXAGCACI40MARG0 register given values for its fields + * and writes the value to the register. + * + * @param[in] aci40margmcs3 - The value to use for the ACI40MARGMCS3 field. + * @param[in] aci40margmcs2 - The value to use for the ACI40MARGMCS2 field. + * @param[in] aci40margmcs1 - The value to use for the ACI40MARGMCS1 field. + * @param[in] aci40margmcs0 - The value to use for the ACI40MARGMCS0 field. + */ +__INLINE void agc_rwnxagcaci40marg0_pack(uint8_t aci40margmcs3, uint8_t aci40margmcs2, uint8_t aci40margmcs1, uint8_t aci40margmcs0) +{ + ASSERT_ERR((((uint32_t)aci40margmcs3 << 24) & ~((uint32_t)0x3F000000)) == 0); + ASSERT_ERR((((uint32_t)aci40margmcs2 << 16) & ~((uint32_t)0x003F0000)) == 0); + ASSERT_ERR((((uint32_t)aci40margmcs1 << 8) & ~((uint32_t)0x00003F00)) == 0); + ASSERT_ERR((((uint32_t)aci40margmcs0 << 0) & ~((uint32_t)0x0000003F)) == 0); + REG_PL_WR(AGC_RWNXAGCACI40MARG0_ADDR, ((uint32_t)aci40margmcs3 << 24) | ((uint32_t)aci40margmcs2 << 16) | ((uint32_t)aci40margmcs1 << 8) | ((uint32_t)aci40margmcs0 << 0)); +} + +/** + * @brief Unpacks RWNXAGCACI40MARG0's fields from current value of the RWNXAGCACI40MARG0 register. + * + * Reads the RWNXAGCACI40MARG0 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] aci40margmcs3 - Will be populated with the current value of this field from the register. + * @param[out] aci40margmcs2 - Will be populated with the current value of this field from the register. + * @param[out] aci40margmcs1 - Will be populated with the current value of this field from the register. + * @param[out] aci40margmcs0 - Will be populated with the current value of this field from the register. + */ +__INLINE void agc_rwnxagcaci40marg0_unpack(uint8_t *aci40margmcs3, uint8_t *aci40margmcs2, uint8_t *aci40margmcs1, uint8_t *aci40margmcs0) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCACI40MARG0_ADDR); + + *aci40margmcs3 = (localVal & ((uint32_t)0x3F000000)) >> 24; + *aci40margmcs2 = (localVal & ((uint32_t)0x003F0000)) >> 16; + *aci40margmcs1 = (localVal & ((uint32_t)0x00003F00)) >> 8; + *aci40margmcs0 = (localVal & ((uint32_t)0x0000003F)) >> 0; +} + +/** + * @brief Returns the current value of the ACI40MARGMCS3 field in the RWNXAGCACI40MARG0 register. + * + * The RWNXAGCACI40MARG0 register will be read and the ACI40MARGMCS3 field's value will be returned. + * + * @return The current value of the ACI40MARGMCS3 field in the RWNXAGCACI40MARG0 register. + */ +__INLINE uint8_t agc_aci40margmcs3_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCACI40MARG0_ADDR); + return ((localVal & ((uint32_t)0x3F000000)) >> 24); +} + +/** + * @brief Sets the ACI40MARGMCS3 field of the RWNXAGCACI40MARG0 register. + * + * The RWNXAGCACI40MARG0 register will be read, modified to contain the new field value, and written. + * + * @param[in] aci40margmcs3 - The value to set the field to. + */ +__INLINE void agc_aci40margmcs3_setf(uint8_t aci40margmcs3) +{ + ASSERT_ERR((((uint32_t)aci40margmcs3 << 24) & ~((uint32_t)0x3F000000)) == 0); + REG_PL_WR(AGC_RWNXAGCACI40MARG0_ADDR, (REG_PL_RD(AGC_RWNXAGCACI40MARG0_ADDR) & ~((uint32_t)0x3F000000)) | ((uint32_t)aci40margmcs3 << 24)); +} + +/** + * @brief Returns the current value of the ACI40MARGMCS2 field in the RWNXAGCACI40MARG0 register. + * + * The RWNXAGCACI40MARG0 register will be read and the ACI40MARGMCS2 field's value will be returned. + * + * @return The current value of the ACI40MARGMCS2 field in the RWNXAGCACI40MARG0 register. + */ +__INLINE uint8_t agc_aci40margmcs2_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCACI40MARG0_ADDR); + return ((localVal & ((uint32_t)0x003F0000)) >> 16); +} + +/** + * @brief Sets the ACI40MARGMCS2 field of the RWNXAGCACI40MARG0 register. + * + * The RWNXAGCACI40MARG0 register will be read, modified to contain the new field value, and written. + * + * @param[in] aci40margmcs2 - The value to set the field to. + */ +__INLINE void agc_aci40margmcs2_setf(uint8_t aci40margmcs2) +{ + ASSERT_ERR((((uint32_t)aci40margmcs2 << 16) & ~((uint32_t)0x003F0000)) == 0); + REG_PL_WR(AGC_RWNXAGCACI40MARG0_ADDR, (REG_PL_RD(AGC_RWNXAGCACI40MARG0_ADDR) & ~((uint32_t)0x003F0000)) | ((uint32_t)aci40margmcs2 << 16)); +} + +/** + * @brief Returns the current value of the ACI40MARGMCS1 field in the RWNXAGCACI40MARG0 register. + * + * The RWNXAGCACI40MARG0 register will be read and the ACI40MARGMCS1 field's value will be returned. + * + * @return The current value of the ACI40MARGMCS1 field in the RWNXAGCACI40MARG0 register. + */ +__INLINE uint8_t agc_aci40margmcs1_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCACI40MARG0_ADDR); + return ((localVal & ((uint32_t)0x00003F00)) >> 8); +} + +/** + * @brief Sets the ACI40MARGMCS1 field of the RWNXAGCACI40MARG0 register. + * + * The RWNXAGCACI40MARG0 register will be read, modified to contain the new field value, and written. + * + * @param[in] aci40margmcs1 - The value to set the field to. + */ +__INLINE void agc_aci40margmcs1_setf(uint8_t aci40margmcs1) +{ + ASSERT_ERR((((uint32_t)aci40margmcs1 << 8) & ~((uint32_t)0x00003F00)) == 0); + REG_PL_WR(AGC_RWNXAGCACI40MARG0_ADDR, (REG_PL_RD(AGC_RWNXAGCACI40MARG0_ADDR) & ~((uint32_t)0x00003F00)) | ((uint32_t)aci40margmcs1 << 8)); +} + +/** + * @brief Returns the current value of the ACI40MARGMCS0 field in the RWNXAGCACI40MARG0 register. + * + * The RWNXAGCACI40MARG0 register will be read and the ACI40MARGMCS0 field's value will be returned. + * + * @return The current value of the ACI40MARGMCS0 field in the RWNXAGCACI40MARG0 register. + */ +__INLINE uint8_t agc_aci40margmcs0_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCACI40MARG0_ADDR); + return ((localVal & ((uint32_t)0x0000003F)) >> 0); +} + +/** + * @brief Sets the ACI40MARGMCS0 field of the RWNXAGCACI40MARG0 register. + * + * The RWNXAGCACI40MARG0 register will be read, modified to contain the new field value, and written. + * + * @param[in] aci40margmcs0 - The value to set the field to. + */ +__INLINE void agc_aci40margmcs0_setf(uint8_t aci40margmcs0) +{ + ASSERT_ERR((((uint32_t)aci40margmcs0 << 0) & ~((uint32_t)0x0000003F)) == 0); + REG_PL_WR(AGC_RWNXAGCACI40MARG0_ADDR, (REG_PL_RD(AGC_RWNXAGCACI40MARG0_ADDR) & ~((uint32_t)0x0000003F)) | ((uint32_t)aci40margmcs0 << 0)); +} + +/// @} + +/** + * @name RWNXAGCACI40MARG1 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  29:24        ACI40MARGMCS7   0x2
+ *  21:16        ACI40MARGMCS6   0x3
+ *  13:08        ACI40MARGMCS5   0x3
+ *  05:00        ACI40MARGMCS4   0x5
+ * 
+ * + * @{ + */ + +/// Address of the RWNXAGCACI40MARG1 register +#define AGC_RWNXAGCACI40MARG1_ADDR 0x0100201C +/// Offset of the RWNXAGCACI40MARG1 register from the base address +#define AGC_RWNXAGCACI40MARG1_OFFSET 0x0000201C +/// Index of the RWNXAGCACI40MARG1 register +#define AGC_RWNXAGCACI40MARG1_INDEX 0x00000807 +/// Reset value of the RWNXAGCACI40MARG1 register +#define AGC_RWNXAGCACI40MARG1_RESET 0x02030305 + +/** + * @brief Returns the current value of the RWNXAGCACI40MARG1 register. + * The RWNXAGCACI40MARG1 register will be read and its value returned. + * @return The current value of the RWNXAGCACI40MARG1 register. + */ +__INLINE uint32_t agc_rwnxagcaci40marg1_get(void) +{ + return REG_PL_RD(AGC_RWNXAGCACI40MARG1_ADDR); +} + +/** + * @brief Sets the RWNXAGCACI40MARG1 register to a value. + * The RWNXAGCACI40MARG1 register will be written. + * @param value - The value to write. + */ +__INLINE void agc_rwnxagcaci40marg1_set(uint32_t value) +{ + REG_PL_WR(AGC_RWNXAGCACI40MARG1_ADDR, value); +} + +// field definitions +/// ACI40MARGMCS7 field mask +#define AGC_ACI40MARGMCS7_MASK ((uint32_t)0x3F000000) +/// ACI40MARGMCS7 field LSB position +#define AGC_ACI40MARGMCS7_LSB 24 +/// ACI40MARGMCS7 field width +#define AGC_ACI40MARGMCS7_WIDTH ((uint32_t)0x00000006) +/// ACI40MARGMCS6 field mask +#define AGC_ACI40MARGMCS6_MASK ((uint32_t)0x003F0000) +/// ACI40MARGMCS6 field LSB position +#define AGC_ACI40MARGMCS6_LSB 16 +/// ACI40MARGMCS6 field width +#define AGC_ACI40MARGMCS6_WIDTH ((uint32_t)0x00000006) +/// ACI40MARGMCS5 field mask +#define AGC_ACI40MARGMCS5_MASK ((uint32_t)0x00003F00) +/// ACI40MARGMCS5 field LSB position +#define AGC_ACI40MARGMCS5_LSB 8 +/// ACI40MARGMCS5 field width +#define AGC_ACI40MARGMCS5_WIDTH ((uint32_t)0x00000006) +/// ACI40MARGMCS4 field mask +#define AGC_ACI40MARGMCS4_MASK ((uint32_t)0x0000003F) +/// ACI40MARGMCS4 field LSB position +#define AGC_ACI40MARGMCS4_LSB 0 +/// ACI40MARGMCS4 field width +#define AGC_ACI40MARGMCS4_WIDTH ((uint32_t)0x00000006) + +/// ACI40MARGMCS7 field reset value +#define AGC_ACI40MARGMCS7_RST 0x2 +/// ACI40MARGMCS6 field reset value +#define AGC_ACI40MARGMCS6_RST 0x3 +/// ACI40MARGMCS5 field reset value +#define AGC_ACI40MARGMCS5_RST 0x3 +/// ACI40MARGMCS4 field reset value +#define AGC_ACI40MARGMCS4_RST 0x5 + +/** + * @brief Constructs a value for the RWNXAGCACI40MARG1 register given values for its fields + * and writes the value to the register. + * + * @param[in] aci40margmcs7 - The value to use for the ACI40MARGMCS7 field. + * @param[in] aci40margmcs6 - The value to use for the ACI40MARGMCS6 field. + * @param[in] aci40margmcs5 - The value to use for the ACI40MARGMCS5 field. + * @param[in] aci40margmcs4 - The value to use for the ACI40MARGMCS4 field. + */ +__INLINE void agc_rwnxagcaci40marg1_pack(uint8_t aci40margmcs7, uint8_t aci40margmcs6, uint8_t aci40margmcs5, uint8_t aci40margmcs4) +{ + ASSERT_ERR((((uint32_t)aci40margmcs7 << 24) & ~((uint32_t)0x3F000000)) == 0); + ASSERT_ERR((((uint32_t)aci40margmcs6 << 16) & ~((uint32_t)0x003F0000)) == 0); + ASSERT_ERR((((uint32_t)aci40margmcs5 << 8) & ~((uint32_t)0x00003F00)) == 0); + ASSERT_ERR((((uint32_t)aci40margmcs4 << 0) & ~((uint32_t)0x0000003F)) == 0); + REG_PL_WR(AGC_RWNXAGCACI40MARG1_ADDR, ((uint32_t)aci40margmcs7 << 24) | ((uint32_t)aci40margmcs6 << 16) | ((uint32_t)aci40margmcs5 << 8) | ((uint32_t)aci40margmcs4 << 0)); +} + +/** + * @brief Unpacks RWNXAGCACI40MARG1's fields from current value of the RWNXAGCACI40MARG1 register. + * + * Reads the RWNXAGCACI40MARG1 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] aci40margmcs7 - Will be populated with the current value of this field from the register. + * @param[out] aci40margmcs6 - Will be populated with the current value of this field from the register. + * @param[out] aci40margmcs5 - Will be populated with the current value of this field from the register. + * @param[out] aci40margmcs4 - Will be populated with the current value of this field from the register. + */ +__INLINE void agc_rwnxagcaci40marg1_unpack(uint8_t *aci40margmcs7, uint8_t *aci40margmcs6, uint8_t *aci40margmcs5, uint8_t *aci40margmcs4) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCACI40MARG1_ADDR); + + *aci40margmcs7 = (localVal & ((uint32_t)0x3F000000)) >> 24; + *aci40margmcs6 = (localVal & ((uint32_t)0x003F0000)) >> 16; + *aci40margmcs5 = (localVal & ((uint32_t)0x00003F00)) >> 8; + *aci40margmcs4 = (localVal & ((uint32_t)0x0000003F)) >> 0; +} + +/** + * @brief Returns the current value of the ACI40MARGMCS7 field in the RWNXAGCACI40MARG1 register. + * + * The RWNXAGCACI40MARG1 register will be read and the ACI40MARGMCS7 field's value will be returned. + * + * @return The current value of the ACI40MARGMCS7 field in the RWNXAGCACI40MARG1 register. + */ +__INLINE uint8_t agc_aci40margmcs7_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCACI40MARG1_ADDR); + return ((localVal & ((uint32_t)0x3F000000)) >> 24); +} + +/** + * @brief Sets the ACI40MARGMCS7 field of the RWNXAGCACI40MARG1 register. + * + * The RWNXAGCACI40MARG1 register will be read, modified to contain the new field value, and written. + * + * @param[in] aci40margmcs7 - The value to set the field to. + */ +__INLINE void agc_aci40margmcs7_setf(uint8_t aci40margmcs7) +{ + ASSERT_ERR((((uint32_t)aci40margmcs7 << 24) & ~((uint32_t)0x3F000000)) == 0); + REG_PL_WR(AGC_RWNXAGCACI40MARG1_ADDR, (REG_PL_RD(AGC_RWNXAGCACI40MARG1_ADDR) & ~((uint32_t)0x3F000000)) | ((uint32_t)aci40margmcs7 << 24)); +} + +/** + * @brief Returns the current value of the ACI40MARGMCS6 field in the RWNXAGCACI40MARG1 register. + * + * The RWNXAGCACI40MARG1 register will be read and the ACI40MARGMCS6 field's value will be returned. + * + * @return The current value of the ACI40MARGMCS6 field in the RWNXAGCACI40MARG1 register. + */ +__INLINE uint8_t agc_aci40margmcs6_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCACI40MARG1_ADDR); + return ((localVal & ((uint32_t)0x003F0000)) >> 16); +} + +/** + * @brief Sets the ACI40MARGMCS6 field of the RWNXAGCACI40MARG1 register. + * + * The RWNXAGCACI40MARG1 register will be read, modified to contain the new field value, and written. + * + * @param[in] aci40margmcs6 - The value to set the field to. + */ +__INLINE void agc_aci40margmcs6_setf(uint8_t aci40margmcs6) +{ + ASSERT_ERR((((uint32_t)aci40margmcs6 << 16) & ~((uint32_t)0x003F0000)) == 0); + REG_PL_WR(AGC_RWNXAGCACI40MARG1_ADDR, (REG_PL_RD(AGC_RWNXAGCACI40MARG1_ADDR) & ~((uint32_t)0x003F0000)) | ((uint32_t)aci40margmcs6 << 16)); +} + +/** + * @brief Returns the current value of the ACI40MARGMCS5 field in the RWNXAGCACI40MARG1 register. + * + * The RWNXAGCACI40MARG1 register will be read and the ACI40MARGMCS5 field's value will be returned. + * + * @return The current value of the ACI40MARGMCS5 field in the RWNXAGCACI40MARG1 register. + */ +__INLINE uint8_t agc_aci40margmcs5_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCACI40MARG1_ADDR); + return ((localVal & ((uint32_t)0x00003F00)) >> 8); +} + +/** + * @brief Sets the ACI40MARGMCS5 field of the RWNXAGCACI40MARG1 register. + * + * The RWNXAGCACI40MARG1 register will be read, modified to contain the new field value, and written. + * + * @param[in] aci40margmcs5 - The value to set the field to. + */ +__INLINE void agc_aci40margmcs5_setf(uint8_t aci40margmcs5) +{ + ASSERT_ERR((((uint32_t)aci40margmcs5 << 8) & ~((uint32_t)0x00003F00)) == 0); + REG_PL_WR(AGC_RWNXAGCACI40MARG1_ADDR, (REG_PL_RD(AGC_RWNXAGCACI40MARG1_ADDR) & ~((uint32_t)0x00003F00)) | ((uint32_t)aci40margmcs5 << 8)); +} + +/** + * @brief Returns the current value of the ACI40MARGMCS4 field in the RWNXAGCACI40MARG1 register. + * + * The RWNXAGCACI40MARG1 register will be read and the ACI40MARGMCS4 field's value will be returned. + * + * @return The current value of the ACI40MARGMCS4 field in the RWNXAGCACI40MARG1 register. + */ +__INLINE uint8_t agc_aci40margmcs4_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCACI40MARG1_ADDR); + return ((localVal & ((uint32_t)0x0000003F)) >> 0); +} + +/** + * @brief Sets the ACI40MARGMCS4 field of the RWNXAGCACI40MARG1 register. + * + * The RWNXAGCACI40MARG1 register will be read, modified to contain the new field value, and written. + * + * @param[in] aci40margmcs4 - The value to set the field to. + */ +__INLINE void agc_aci40margmcs4_setf(uint8_t aci40margmcs4) +{ + ASSERT_ERR((((uint32_t)aci40margmcs4 << 0) & ~((uint32_t)0x0000003F)) == 0); + REG_PL_WR(AGC_RWNXAGCACI40MARG1_ADDR, (REG_PL_RD(AGC_RWNXAGCACI40MARG1_ADDR) & ~((uint32_t)0x0000003F)) | ((uint32_t)aci40margmcs4 << 0)); +} + +/// @} + +/** + * @name RWNXAGCACI40MARG2 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  13:08        ACI40MARGMCS9   0x1
+ *  05:00        ACI40MARGMCS8   0x1
+ * 
+ * + * @{ + */ + +/// Address of the RWNXAGCACI40MARG2 register +#define AGC_RWNXAGCACI40MARG2_ADDR 0x01002020 +/// Offset of the RWNXAGCACI40MARG2 register from the base address +#define AGC_RWNXAGCACI40MARG2_OFFSET 0x00002020 +/// Index of the RWNXAGCACI40MARG2 register +#define AGC_RWNXAGCACI40MARG2_INDEX 0x00000808 +/// Reset value of the RWNXAGCACI40MARG2 register +#define AGC_RWNXAGCACI40MARG2_RESET 0x00000101 + +/** + * @brief Returns the current value of the RWNXAGCACI40MARG2 register. + * The RWNXAGCACI40MARG2 register will be read and its value returned. + * @return The current value of the RWNXAGCACI40MARG2 register. + */ +__INLINE uint32_t agc_rwnxagcaci40marg2_get(void) +{ + return REG_PL_RD(AGC_RWNXAGCACI40MARG2_ADDR); +} + +/** + * @brief Sets the RWNXAGCACI40MARG2 register to a value. + * The RWNXAGCACI40MARG2 register will be written. + * @param value - The value to write. + */ +__INLINE void agc_rwnxagcaci40marg2_set(uint32_t value) +{ + REG_PL_WR(AGC_RWNXAGCACI40MARG2_ADDR, value); +} + +// field definitions +/// ACI40MARGMCS9 field mask +#define AGC_ACI40MARGMCS9_MASK ((uint32_t)0x00003F00) +/// ACI40MARGMCS9 field LSB position +#define AGC_ACI40MARGMCS9_LSB 8 +/// ACI40MARGMCS9 field width +#define AGC_ACI40MARGMCS9_WIDTH ((uint32_t)0x00000006) +/// ACI40MARGMCS8 field mask +#define AGC_ACI40MARGMCS8_MASK ((uint32_t)0x0000003F) +/// ACI40MARGMCS8 field LSB position +#define AGC_ACI40MARGMCS8_LSB 0 +/// ACI40MARGMCS8 field width +#define AGC_ACI40MARGMCS8_WIDTH ((uint32_t)0x00000006) + +/// ACI40MARGMCS9 field reset value +#define AGC_ACI40MARGMCS9_RST 0x1 +/// ACI40MARGMCS8 field reset value +#define AGC_ACI40MARGMCS8_RST 0x1 + +/** + * @brief Constructs a value for the RWNXAGCACI40MARG2 register given values for its fields + * and writes the value to the register. + * + * @param[in] aci40margmcs9 - The value to use for the ACI40MARGMCS9 field. + * @param[in] aci40margmcs8 - The value to use for the ACI40MARGMCS8 field. + */ +__INLINE void agc_rwnxagcaci40marg2_pack(uint8_t aci40margmcs9, uint8_t aci40margmcs8) +{ + ASSERT_ERR((((uint32_t)aci40margmcs9 << 8) & ~((uint32_t)0x00003F00)) == 0); + ASSERT_ERR((((uint32_t)aci40margmcs8 << 0) & ~((uint32_t)0x0000003F)) == 0); + REG_PL_WR(AGC_RWNXAGCACI40MARG2_ADDR, ((uint32_t)aci40margmcs9 << 8) | ((uint32_t)aci40margmcs8 << 0)); +} + +/** + * @brief Unpacks RWNXAGCACI40MARG2's fields from current value of the RWNXAGCACI40MARG2 register. + * + * Reads the RWNXAGCACI40MARG2 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] aci40margmcs9 - Will be populated with the current value of this field from the register. + * @param[out] aci40margmcs8 - Will be populated with the current value of this field from the register. + */ +__INLINE void agc_rwnxagcaci40marg2_unpack(uint8_t *aci40margmcs9, uint8_t *aci40margmcs8) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCACI40MARG2_ADDR); + + *aci40margmcs9 = (localVal & ((uint32_t)0x00003F00)) >> 8; + *aci40margmcs8 = (localVal & ((uint32_t)0x0000003F)) >> 0; +} + +/** + * @brief Returns the current value of the ACI40MARGMCS9 field in the RWNXAGCACI40MARG2 register. + * + * The RWNXAGCACI40MARG2 register will be read and the ACI40MARGMCS9 field's value will be returned. + * + * @return The current value of the ACI40MARGMCS9 field in the RWNXAGCACI40MARG2 register. + */ +__INLINE uint8_t agc_aci40margmcs9_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCACI40MARG2_ADDR); + return ((localVal & ((uint32_t)0x00003F00)) >> 8); +} + +/** + * @brief Sets the ACI40MARGMCS9 field of the RWNXAGCACI40MARG2 register. + * + * The RWNXAGCACI40MARG2 register will be read, modified to contain the new field value, and written. + * + * @param[in] aci40margmcs9 - The value to set the field to. + */ +__INLINE void agc_aci40margmcs9_setf(uint8_t aci40margmcs9) +{ + ASSERT_ERR((((uint32_t)aci40margmcs9 << 8) & ~((uint32_t)0x00003F00)) == 0); + REG_PL_WR(AGC_RWNXAGCACI40MARG2_ADDR, (REG_PL_RD(AGC_RWNXAGCACI40MARG2_ADDR) & ~((uint32_t)0x00003F00)) | ((uint32_t)aci40margmcs9 << 8)); +} + +/** + * @brief Returns the current value of the ACI40MARGMCS8 field in the RWNXAGCACI40MARG2 register. + * + * The RWNXAGCACI40MARG2 register will be read and the ACI40MARGMCS8 field's value will be returned. + * + * @return The current value of the ACI40MARGMCS8 field in the RWNXAGCACI40MARG2 register. + */ +__INLINE uint8_t agc_aci40margmcs8_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCACI40MARG2_ADDR); + return ((localVal & ((uint32_t)0x0000003F)) >> 0); +} + +/** + * @brief Sets the ACI40MARGMCS8 field of the RWNXAGCACI40MARG2 register. + * + * The RWNXAGCACI40MARG2 register will be read, modified to contain the new field value, and written. + * + * @param[in] aci40margmcs8 - The value to set the field to. + */ +__INLINE void agc_aci40margmcs8_setf(uint8_t aci40margmcs8) +{ + ASSERT_ERR((((uint32_t)aci40margmcs8 << 0) & ~((uint32_t)0x0000003F)) == 0); + REG_PL_WR(AGC_RWNXAGCACI40MARG2_ADDR, (REG_PL_RD(AGC_RWNXAGCACI40MARG2_ADDR) & ~((uint32_t)0x0000003F)) | ((uint32_t)aci40margmcs8 << 0)); +} + +/// @} + +/** + * @name RWNXAGCACI80MARG0 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  29:24        ACI80MARGMCS3   0x18
+ *  21:16        ACI80MARGMCS2   0x1B
+ *  13:08        ACI80MARGMCS1   0x1D
+ *  05:00        ACI80MARGMCS0   0x20
+ * 
+ * + * @{ + */ + +/// Address of the RWNXAGCACI80MARG0 register +#define AGC_RWNXAGCACI80MARG0_ADDR 0x01002024 +/// Offset of the RWNXAGCACI80MARG0 register from the base address +#define AGC_RWNXAGCACI80MARG0_OFFSET 0x00002024 +/// Index of the RWNXAGCACI80MARG0 register +#define AGC_RWNXAGCACI80MARG0_INDEX 0x00000809 +/// Reset value of the RWNXAGCACI80MARG0 register +#define AGC_RWNXAGCACI80MARG0_RESET 0x181B1D20 + +/** + * @brief Returns the current value of the RWNXAGCACI80MARG0 register. + * The RWNXAGCACI80MARG0 register will be read and its value returned. + * @return The current value of the RWNXAGCACI80MARG0 register. + */ +__INLINE uint32_t agc_rwnxagcaci80marg0_get(void) +{ + return REG_PL_RD(AGC_RWNXAGCACI80MARG0_ADDR); +} + +/** + * @brief Sets the RWNXAGCACI80MARG0 register to a value. + * The RWNXAGCACI80MARG0 register will be written. + * @param value - The value to write. + */ +__INLINE void agc_rwnxagcaci80marg0_set(uint32_t value) +{ + REG_PL_WR(AGC_RWNXAGCACI80MARG0_ADDR, value); +} + +// field definitions +/// ACI80MARGMCS3 field mask +#define AGC_ACI80MARGMCS3_MASK ((uint32_t)0x3F000000) +/// ACI80MARGMCS3 field LSB position +#define AGC_ACI80MARGMCS3_LSB 24 +/// ACI80MARGMCS3 field width +#define AGC_ACI80MARGMCS3_WIDTH ((uint32_t)0x00000006) +/// ACI80MARGMCS2 field mask +#define AGC_ACI80MARGMCS2_MASK ((uint32_t)0x003F0000) +/// ACI80MARGMCS2 field LSB position +#define AGC_ACI80MARGMCS2_LSB 16 +/// ACI80MARGMCS2 field width +#define AGC_ACI80MARGMCS2_WIDTH ((uint32_t)0x00000006) +/// ACI80MARGMCS1 field mask +#define AGC_ACI80MARGMCS1_MASK ((uint32_t)0x00003F00) +/// ACI80MARGMCS1 field LSB position +#define AGC_ACI80MARGMCS1_LSB 8 +/// ACI80MARGMCS1 field width +#define AGC_ACI80MARGMCS1_WIDTH ((uint32_t)0x00000006) +/// ACI80MARGMCS0 field mask +#define AGC_ACI80MARGMCS0_MASK ((uint32_t)0x0000003F) +/// ACI80MARGMCS0 field LSB position +#define AGC_ACI80MARGMCS0_LSB 0 +/// ACI80MARGMCS0 field width +#define AGC_ACI80MARGMCS0_WIDTH ((uint32_t)0x00000006) + +/// ACI80MARGMCS3 field reset value +#define AGC_ACI80MARGMCS3_RST 0x18 +/// ACI80MARGMCS2 field reset value +#define AGC_ACI80MARGMCS2_RST 0x1B +/// ACI80MARGMCS1 field reset value +#define AGC_ACI80MARGMCS1_RST 0x1D +/// ACI80MARGMCS0 field reset value +#define AGC_ACI80MARGMCS0_RST 0x20 + +/** + * @brief Constructs a value for the RWNXAGCACI80MARG0 register given values for its fields + * and writes the value to the register. + * + * @param[in] aci80margmcs3 - The value to use for the ACI80MARGMCS3 field. + * @param[in] aci80margmcs2 - The value to use for the ACI80MARGMCS2 field. + * @param[in] aci80margmcs1 - The value to use for the ACI80MARGMCS1 field. + * @param[in] aci80margmcs0 - The value to use for the ACI80MARGMCS0 field. + */ +__INLINE void agc_rwnxagcaci80marg0_pack(uint8_t aci80margmcs3, uint8_t aci80margmcs2, uint8_t aci80margmcs1, uint8_t aci80margmcs0) +{ + ASSERT_ERR((((uint32_t)aci80margmcs3 << 24) & ~((uint32_t)0x3F000000)) == 0); + ASSERT_ERR((((uint32_t)aci80margmcs2 << 16) & ~((uint32_t)0x003F0000)) == 0); + ASSERT_ERR((((uint32_t)aci80margmcs1 << 8) & ~((uint32_t)0x00003F00)) == 0); + ASSERT_ERR((((uint32_t)aci80margmcs0 << 0) & ~((uint32_t)0x0000003F)) == 0); + REG_PL_WR(AGC_RWNXAGCACI80MARG0_ADDR, ((uint32_t)aci80margmcs3 << 24) | ((uint32_t)aci80margmcs2 << 16) | ((uint32_t)aci80margmcs1 << 8) | ((uint32_t)aci80margmcs0 << 0)); +} + +/** + * @brief Unpacks RWNXAGCACI80MARG0's fields from current value of the RWNXAGCACI80MARG0 register. + * + * Reads the RWNXAGCACI80MARG0 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] aci80margmcs3 - Will be populated with the current value of this field from the register. + * @param[out] aci80margmcs2 - Will be populated with the current value of this field from the register. + * @param[out] aci80margmcs1 - Will be populated with the current value of this field from the register. + * @param[out] aci80margmcs0 - Will be populated with the current value of this field from the register. + */ +__INLINE void agc_rwnxagcaci80marg0_unpack(uint8_t *aci80margmcs3, uint8_t *aci80margmcs2, uint8_t *aci80margmcs1, uint8_t *aci80margmcs0) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCACI80MARG0_ADDR); + + *aci80margmcs3 = (localVal & ((uint32_t)0x3F000000)) >> 24; + *aci80margmcs2 = (localVal & ((uint32_t)0x003F0000)) >> 16; + *aci80margmcs1 = (localVal & ((uint32_t)0x00003F00)) >> 8; + *aci80margmcs0 = (localVal & ((uint32_t)0x0000003F)) >> 0; +} + +/** + * @brief Returns the current value of the ACI80MARGMCS3 field in the RWNXAGCACI80MARG0 register. + * + * The RWNXAGCACI80MARG0 register will be read and the ACI80MARGMCS3 field's value will be returned. + * + * @return The current value of the ACI80MARGMCS3 field in the RWNXAGCACI80MARG0 register. + */ +__INLINE uint8_t agc_aci80margmcs3_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCACI80MARG0_ADDR); + return ((localVal & ((uint32_t)0x3F000000)) >> 24); +} + +/** + * @brief Sets the ACI80MARGMCS3 field of the RWNXAGCACI80MARG0 register. + * + * The RWNXAGCACI80MARG0 register will be read, modified to contain the new field value, and written. + * + * @param[in] aci80margmcs3 - The value to set the field to. + */ +__INLINE void agc_aci80margmcs3_setf(uint8_t aci80margmcs3) +{ + ASSERT_ERR((((uint32_t)aci80margmcs3 << 24) & ~((uint32_t)0x3F000000)) == 0); + REG_PL_WR(AGC_RWNXAGCACI80MARG0_ADDR, (REG_PL_RD(AGC_RWNXAGCACI80MARG0_ADDR) & ~((uint32_t)0x3F000000)) | ((uint32_t)aci80margmcs3 << 24)); +} + +/** + * @brief Returns the current value of the ACI80MARGMCS2 field in the RWNXAGCACI80MARG0 register. + * + * The RWNXAGCACI80MARG0 register will be read and the ACI80MARGMCS2 field's value will be returned. + * + * @return The current value of the ACI80MARGMCS2 field in the RWNXAGCACI80MARG0 register. + */ +__INLINE uint8_t agc_aci80margmcs2_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCACI80MARG0_ADDR); + return ((localVal & ((uint32_t)0x003F0000)) >> 16); +} + +/** + * @brief Sets the ACI80MARGMCS2 field of the RWNXAGCACI80MARG0 register. + * + * The RWNXAGCACI80MARG0 register will be read, modified to contain the new field value, and written. + * + * @param[in] aci80margmcs2 - The value to set the field to. + */ +__INLINE void agc_aci80margmcs2_setf(uint8_t aci80margmcs2) +{ + ASSERT_ERR((((uint32_t)aci80margmcs2 << 16) & ~((uint32_t)0x003F0000)) == 0); + REG_PL_WR(AGC_RWNXAGCACI80MARG0_ADDR, (REG_PL_RD(AGC_RWNXAGCACI80MARG0_ADDR) & ~((uint32_t)0x003F0000)) | ((uint32_t)aci80margmcs2 << 16)); +} + +/** + * @brief Returns the current value of the ACI80MARGMCS1 field in the RWNXAGCACI80MARG0 register. + * + * The RWNXAGCACI80MARG0 register will be read and the ACI80MARGMCS1 field's value will be returned. + * + * @return The current value of the ACI80MARGMCS1 field in the RWNXAGCACI80MARG0 register. + */ +__INLINE uint8_t agc_aci80margmcs1_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCACI80MARG0_ADDR); + return ((localVal & ((uint32_t)0x00003F00)) >> 8); +} + +/** + * @brief Sets the ACI80MARGMCS1 field of the RWNXAGCACI80MARG0 register. + * + * The RWNXAGCACI80MARG0 register will be read, modified to contain the new field value, and written. + * + * @param[in] aci80margmcs1 - The value to set the field to. + */ +__INLINE void agc_aci80margmcs1_setf(uint8_t aci80margmcs1) +{ + ASSERT_ERR((((uint32_t)aci80margmcs1 << 8) & ~((uint32_t)0x00003F00)) == 0); + REG_PL_WR(AGC_RWNXAGCACI80MARG0_ADDR, (REG_PL_RD(AGC_RWNXAGCACI80MARG0_ADDR) & ~((uint32_t)0x00003F00)) | ((uint32_t)aci80margmcs1 << 8)); +} + +/** + * @brief Returns the current value of the ACI80MARGMCS0 field in the RWNXAGCACI80MARG0 register. + * + * The RWNXAGCACI80MARG0 register will be read and the ACI80MARGMCS0 field's value will be returned. + * + * @return The current value of the ACI80MARGMCS0 field in the RWNXAGCACI80MARG0 register. + */ +__INLINE uint8_t agc_aci80margmcs0_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCACI80MARG0_ADDR); + return ((localVal & ((uint32_t)0x0000003F)) >> 0); +} + +/** + * @brief Sets the ACI80MARGMCS0 field of the RWNXAGCACI80MARG0 register. + * + * The RWNXAGCACI80MARG0 register will be read, modified to contain the new field value, and written. + * + * @param[in] aci80margmcs0 - The value to set the field to. + */ +__INLINE void agc_aci80margmcs0_setf(uint8_t aci80margmcs0) +{ + ASSERT_ERR((((uint32_t)aci80margmcs0 << 0) & ~((uint32_t)0x0000003F)) == 0); + REG_PL_WR(AGC_RWNXAGCACI80MARG0_ADDR, (REG_PL_RD(AGC_RWNXAGCACI80MARG0_ADDR) & ~((uint32_t)0x0000003F)) | ((uint32_t)aci80margmcs0 << 0)); +} + +/// @} + +/** + * @name RWNXAGCACI80MARG1 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  29:24        ACI80MARGMCS7   0xE
+ *  21:16        ACI80MARGMCS6   0xF
+ *  13:08        ACI80MARGMCS5   0x10
+ *  05:00        ACI80MARGMCS4   0x14
+ * 
+ * + * @{ + */ + +/// Address of the RWNXAGCACI80MARG1 register +#define AGC_RWNXAGCACI80MARG1_ADDR 0x01002028 +/// Offset of the RWNXAGCACI80MARG1 register from the base address +#define AGC_RWNXAGCACI80MARG1_OFFSET 0x00002028 +/// Index of the RWNXAGCACI80MARG1 register +#define AGC_RWNXAGCACI80MARG1_INDEX 0x0000080A +/// Reset value of the RWNXAGCACI80MARG1 register +#define AGC_RWNXAGCACI80MARG1_RESET 0x0E0F1014 + +/** + * @brief Returns the current value of the RWNXAGCACI80MARG1 register. + * The RWNXAGCACI80MARG1 register will be read and its value returned. + * @return The current value of the RWNXAGCACI80MARG1 register. + */ +__INLINE uint32_t agc_rwnxagcaci80marg1_get(void) +{ + return REG_PL_RD(AGC_RWNXAGCACI80MARG1_ADDR); +} + +/** + * @brief Sets the RWNXAGCACI80MARG1 register to a value. + * The RWNXAGCACI80MARG1 register will be written. + * @param value - The value to write. + */ +__INLINE void agc_rwnxagcaci80marg1_set(uint32_t value) +{ + REG_PL_WR(AGC_RWNXAGCACI80MARG1_ADDR, value); +} + +// field definitions +/// ACI80MARGMCS7 field mask +#define AGC_ACI80MARGMCS7_MASK ((uint32_t)0x3F000000) +/// ACI80MARGMCS7 field LSB position +#define AGC_ACI80MARGMCS7_LSB 24 +/// ACI80MARGMCS7 field width +#define AGC_ACI80MARGMCS7_WIDTH ((uint32_t)0x00000006) +/// ACI80MARGMCS6 field mask +#define AGC_ACI80MARGMCS6_MASK ((uint32_t)0x003F0000) +/// ACI80MARGMCS6 field LSB position +#define AGC_ACI80MARGMCS6_LSB 16 +/// ACI80MARGMCS6 field width +#define AGC_ACI80MARGMCS6_WIDTH ((uint32_t)0x00000006) +/// ACI80MARGMCS5 field mask +#define AGC_ACI80MARGMCS5_MASK ((uint32_t)0x00003F00) +/// ACI80MARGMCS5 field LSB position +#define AGC_ACI80MARGMCS5_LSB 8 +/// ACI80MARGMCS5 field width +#define AGC_ACI80MARGMCS5_WIDTH ((uint32_t)0x00000006) +/// ACI80MARGMCS4 field mask +#define AGC_ACI80MARGMCS4_MASK ((uint32_t)0x0000003F) +/// ACI80MARGMCS4 field LSB position +#define AGC_ACI80MARGMCS4_LSB 0 +/// ACI80MARGMCS4 field width +#define AGC_ACI80MARGMCS4_WIDTH ((uint32_t)0x00000006) + +/// ACI80MARGMCS7 field reset value +#define AGC_ACI80MARGMCS7_RST 0xE +/// ACI80MARGMCS6 field reset value +#define AGC_ACI80MARGMCS6_RST 0xF +/// ACI80MARGMCS5 field reset value +#define AGC_ACI80MARGMCS5_RST 0x10 +/// ACI80MARGMCS4 field reset value +#define AGC_ACI80MARGMCS4_RST 0x14 + +/** + * @brief Constructs a value for the RWNXAGCACI80MARG1 register given values for its fields + * and writes the value to the register. + * + * @param[in] aci80margmcs7 - The value to use for the ACI80MARGMCS7 field. + * @param[in] aci80margmcs6 - The value to use for the ACI80MARGMCS6 field. + * @param[in] aci80margmcs5 - The value to use for the ACI80MARGMCS5 field. + * @param[in] aci80margmcs4 - The value to use for the ACI80MARGMCS4 field. + */ +__INLINE void agc_rwnxagcaci80marg1_pack(uint8_t aci80margmcs7, uint8_t aci80margmcs6, uint8_t aci80margmcs5, uint8_t aci80margmcs4) +{ + ASSERT_ERR((((uint32_t)aci80margmcs7 << 24) & ~((uint32_t)0x3F000000)) == 0); + ASSERT_ERR((((uint32_t)aci80margmcs6 << 16) & ~((uint32_t)0x003F0000)) == 0); + ASSERT_ERR((((uint32_t)aci80margmcs5 << 8) & ~((uint32_t)0x00003F00)) == 0); + ASSERT_ERR((((uint32_t)aci80margmcs4 << 0) & ~((uint32_t)0x0000003F)) == 0); + REG_PL_WR(AGC_RWNXAGCACI80MARG1_ADDR, ((uint32_t)aci80margmcs7 << 24) | ((uint32_t)aci80margmcs6 << 16) | ((uint32_t)aci80margmcs5 << 8) | ((uint32_t)aci80margmcs4 << 0)); +} + +/** + * @brief Unpacks RWNXAGCACI80MARG1's fields from current value of the RWNXAGCACI80MARG1 register. + * + * Reads the RWNXAGCACI80MARG1 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] aci80margmcs7 - Will be populated with the current value of this field from the register. + * @param[out] aci80margmcs6 - Will be populated with the current value of this field from the register. + * @param[out] aci80margmcs5 - Will be populated with the current value of this field from the register. + * @param[out] aci80margmcs4 - Will be populated with the current value of this field from the register. + */ +__INLINE void agc_rwnxagcaci80marg1_unpack(uint8_t *aci80margmcs7, uint8_t *aci80margmcs6, uint8_t *aci80margmcs5, uint8_t *aci80margmcs4) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCACI80MARG1_ADDR); + + *aci80margmcs7 = (localVal & ((uint32_t)0x3F000000)) >> 24; + *aci80margmcs6 = (localVal & ((uint32_t)0x003F0000)) >> 16; + *aci80margmcs5 = (localVal & ((uint32_t)0x00003F00)) >> 8; + *aci80margmcs4 = (localVal & ((uint32_t)0x0000003F)) >> 0; +} + +/** + * @brief Returns the current value of the ACI80MARGMCS7 field in the RWNXAGCACI80MARG1 register. + * + * The RWNXAGCACI80MARG1 register will be read and the ACI80MARGMCS7 field's value will be returned. + * + * @return The current value of the ACI80MARGMCS7 field in the RWNXAGCACI80MARG1 register. + */ +__INLINE uint8_t agc_aci80margmcs7_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCACI80MARG1_ADDR); + return ((localVal & ((uint32_t)0x3F000000)) >> 24); +} + +/** + * @brief Sets the ACI80MARGMCS7 field of the RWNXAGCACI80MARG1 register. + * + * The RWNXAGCACI80MARG1 register will be read, modified to contain the new field value, and written. + * + * @param[in] aci80margmcs7 - The value to set the field to. + */ +__INLINE void agc_aci80margmcs7_setf(uint8_t aci80margmcs7) +{ + ASSERT_ERR((((uint32_t)aci80margmcs7 << 24) & ~((uint32_t)0x3F000000)) == 0); + REG_PL_WR(AGC_RWNXAGCACI80MARG1_ADDR, (REG_PL_RD(AGC_RWNXAGCACI80MARG1_ADDR) & ~((uint32_t)0x3F000000)) | ((uint32_t)aci80margmcs7 << 24)); +} + +/** + * @brief Returns the current value of the ACI80MARGMCS6 field in the RWNXAGCACI80MARG1 register. + * + * The RWNXAGCACI80MARG1 register will be read and the ACI80MARGMCS6 field's value will be returned. + * + * @return The current value of the ACI80MARGMCS6 field in the RWNXAGCACI80MARG1 register. + */ +__INLINE uint8_t agc_aci80margmcs6_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCACI80MARG1_ADDR); + return ((localVal & ((uint32_t)0x003F0000)) >> 16); +} + +/** + * @brief Sets the ACI80MARGMCS6 field of the RWNXAGCACI80MARG1 register. + * + * The RWNXAGCACI80MARG1 register will be read, modified to contain the new field value, and written. + * + * @param[in] aci80margmcs6 - The value to set the field to. + */ +__INLINE void agc_aci80margmcs6_setf(uint8_t aci80margmcs6) +{ + ASSERT_ERR((((uint32_t)aci80margmcs6 << 16) & ~((uint32_t)0x003F0000)) == 0); + REG_PL_WR(AGC_RWNXAGCACI80MARG1_ADDR, (REG_PL_RD(AGC_RWNXAGCACI80MARG1_ADDR) & ~((uint32_t)0x003F0000)) | ((uint32_t)aci80margmcs6 << 16)); +} + +/** + * @brief Returns the current value of the ACI80MARGMCS5 field in the RWNXAGCACI80MARG1 register. + * + * The RWNXAGCACI80MARG1 register will be read and the ACI80MARGMCS5 field's value will be returned. + * + * @return The current value of the ACI80MARGMCS5 field in the RWNXAGCACI80MARG1 register. + */ +__INLINE uint8_t agc_aci80margmcs5_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCACI80MARG1_ADDR); + return ((localVal & ((uint32_t)0x00003F00)) >> 8); +} + +/** + * @brief Sets the ACI80MARGMCS5 field of the RWNXAGCACI80MARG1 register. + * + * The RWNXAGCACI80MARG1 register will be read, modified to contain the new field value, and written. + * + * @param[in] aci80margmcs5 - The value to set the field to. + */ +__INLINE void agc_aci80margmcs5_setf(uint8_t aci80margmcs5) +{ + ASSERT_ERR((((uint32_t)aci80margmcs5 << 8) & ~((uint32_t)0x00003F00)) == 0); + REG_PL_WR(AGC_RWNXAGCACI80MARG1_ADDR, (REG_PL_RD(AGC_RWNXAGCACI80MARG1_ADDR) & ~((uint32_t)0x00003F00)) | ((uint32_t)aci80margmcs5 << 8)); +} + +/** + * @brief Returns the current value of the ACI80MARGMCS4 field in the RWNXAGCACI80MARG1 register. + * + * The RWNXAGCACI80MARG1 register will be read and the ACI80MARGMCS4 field's value will be returned. + * + * @return The current value of the ACI80MARGMCS4 field in the RWNXAGCACI80MARG1 register. + */ +__INLINE uint8_t agc_aci80margmcs4_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCACI80MARG1_ADDR); + return ((localVal & ((uint32_t)0x0000003F)) >> 0); +} + +/** + * @brief Sets the ACI80MARGMCS4 field of the RWNXAGCACI80MARG1 register. + * + * The RWNXAGCACI80MARG1 register will be read, modified to contain the new field value, and written. + * + * @param[in] aci80margmcs4 - The value to set the field to. + */ +__INLINE void agc_aci80margmcs4_setf(uint8_t aci80margmcs4) +{ + ASSERT_ERR((((uint32_t)aci80margmcs4 << 0) & ~((uint32_t)0x0000003F)) == 0); + REG_PL_WR(AGC_RWNXAGCACI80MARG1_ADDR, (REG_PL_RD(AGC_RWNXAGCACI80MARG1_ADDR) & ~((uint32_t)0x0000003F)) | ((uint32_t)aci80margmcs4 << 0)); +} + +/// @} + +/** + * @name RWNXAGCACI80MARG2 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  13:08        ACI80MARGMCS9   0x8
+ *  05:00        ACI80MARGMCS8   0xA
+ * 
+ * + * @{ + */ + +/// Address of the RWNXAGCACI80MARG2 register +#define AGC_RWNXAGCACI80MARG2_ADDR 0x0100202C +/// Offset of the RWNXAGCACI80MARG2 register from the base address +#define AGC_RWNXAGCACI80MARG2_OFFSET 0x0000202C +/// Index of the RWNXAGCACI80MARG2 register +#define AGC_RWNXAGCACI80MARG2_INDEX 0x0000080B +/// Reset value of the RWNXAGCACI80MARG2 register +#define AGC_RWNXAGCACI80MARG2_RESET 0x0000080A + +/** + * @brief Returns the current value of the RWNXAGCACI80MARG2 register. + * The RWNXAGCACI80MARG2 register will be read and its value returned. + * @return The current value of the RWNXAGCACI80MARG2 register. + */ +__INLINE uint32_t agc_rwnxagcaci80marg2_get(void) +{ + return REG_PL_RD(AGC_RWNXAGCACI80MARG2_ADDR); +} + +/** + * @brief Sets the RWNXAGCACI80MARG2 register to a value. + * The RWNXAGCACI80MARG2 register will be written. + * @param value - The value to write. + */ +__INLINE void agc_rwnxagcaci80marg2_set(uint32_t value) +{ + REG_PL_WR(AGC_RWNXAGCACI80MARG2_ADDR, value); +} + +// field definitions +/// ACI80MARGMCS9 field mask +#define AGC_ACI80MARGMCS9_MASK ((uint32_t)0x00003F00) +/// ACI80MARGMCS9 field LSB position +#define AGC_ACI80MARGMCS9_LSB 8 +/// ACI80MARGMCS9 field width +#define AGC_ACI80MARGMCS9_WIDTH ((uint32_t)0x00000006) +/// ACI80MARGMCS8 field mask +#define AGC_ACI80MARGMCS8_MASK ((uint32_t)0x0000003F) +/// ACI80MARGMCS8 field LSB position +#define AGC_ACI80MARGMCS8_LSB 0 +/// ACI80MARGMCS8 field width +#define AGC_ACI80MARGMCS8_WIDTH ((uint32_t)0x00000006) + +/// ACI80MARGMCS9 field reset value +#define AGC_ACI80MARGMCS9_RST 0x8 +/// ACI80MARGMCS8 field reset value +#define AGC_ACI80MARGMCS8_RST 0xA + +/** + * @brief Constructs a value for the RWNXAGCACI80MARG2 register given values for its fields + * and writes the value to the register. + * + * @param[in] aci80margmcs9 - The value to use for the ACI80MARGMCS9 field. + * @param[in] aci80margmcs8 - The value to use for the ACI80MARGMCS8 field. + */ +__INLINE void agc_rwnxagcaci80marg2_pack(uint8_t aci80margmcs9, uint8_t aci80margmcs8) +{ + ASSERT_ERR((((uint32_t)aci80margmcs9 << 8) & ~((uint32_t)0x00003F00)) == 0); + ASSERT_ERR((((uint32_t)aci80margmcs8 << 0) & ~((uint32_t)0x0000003F)) == 0); + REG_PL_WR(AGC_RWNXAGCACI80MARG2_ADDR, ((uint32_t)aci80margmcs9 << 8) | ((uint32_t)aci80margmcs8 << 0)); +} + +/** + * @brief Unpacks RWNXAGCACI80MARG2's fields from current value of the RWNXAGCACI80MARG2 register. + * + * Reads the RWNXAGCACI80MARG2 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] aci80margmcs9 - Will be populated with the current value of this field from the register. + * @param[out] aci80margmcs8 - Will be populated with the current value of this field from the register. + */ +__INLINE void agc_rwnxagcaci80marg2_unpack(uint8_t *aci80margmcs9, uint8_t *aci80margmcs8) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCACI80MARG2_ADDR); + + *aci80margmcs9 = (localVal & ((uint32_t)0x00003F00)) >> 8; + *aci80margmcs8 = (localVal & ((uint32_t)0x0000003F)) >> 0; +} + +/** + * @brief Returns the current value of the ACI80MARGMCS9 field in the RWNXAGCACI80MARG2 register. + * + * The RWNXAGCACI80MARG2 register will be read and the ACI80MARGMCS9 field's value will be returned. + * + * @return The current value of the ACI80MARGMCS9 field in the RWNXAGCACI80MARG2 register. + */ +__INLINE uint8_t agc_aci80margmcs9_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCACI80MARG2_ADDR); + return ((localVal & ((uint32_t)0x00003F00)) >> 8); +} + +/** + * @brief Sets the ACI80MARGMCS9 field of the RWNXAGCACI80MARG2 register. + * + * The RWNXAGCACI80MARG2 register will be read, modified to contain the new field value, and written. + * + * @param[in] aci80margmcs9 - The value to set the field to. + */ +__INLINE void agc_aci80margmcs9_setf(uint8_t aci80margmcs9) +{ + ASSERT_ERR((((uint32_t)aci80margmcs9 << 8) & ~((uint32_t)0x00003F00)) == 0); + REG_PL_WR(AGC_RWNXAGCACI80MARG2_ADDR, (REG_PL_RD(AGC_RWNXAGCACI80MARG2_ADDR) & ~((uint32_t)0x00003F00)) | ((uint32_t)aci80margmcs9 << 8)); +} + +/** + * @brief Returns the current value of the ACI80MARGMCS8 field in the RWNXAGCACI80MARG2 register. + * + * The RWNXAGCACI80MARG2 register will be read and the ACI80MARGMCS8 field's value will be returned. + * + * @return The current value of the ACI80MARGMCS8 field in the RWNXAGCACI80MARG2 register. + */ +__INLINE uint8_t agc_aci80margmcs8_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCACI80MARG2_ADDR); + return ((localVal & ((uint32_t)0x0000003F)) >> 0); +} + +/** + * @brief Sets the ACI80MARGMCS8 field of the RWNXAGCACI80MARG2 register. + * + * The RWNXAGCACI80MARG2 register will be read, modified to contain the new field value, and written. + * + * @param[in] aci80margmcs8 - The value to set the field to. + */ +__INLINE void agc_aci80margmcs8_setf(uint8_t aci80margmcs8) +{ + ASSERT_ERR((((uint32_t)aci80margmcs8 << 0) & ~((uint32_t)0x0000003F)) == 0); + REG_PL_WR(AGC_RWNXAGCACI80MARG2_ADDR, (REG_PL_RD(AGC_RWNXAGCACI80MARG2_ADDR) & ~((uint32_t)0x0000003F)) | ((uint32_t)aci80margmcs8 << 0)); +} + +/// @} + +/** + * @name RWNXAGCCGH register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  28:24          CHGVGAPSTHR   0x1
+ *  20:16          CHGVGAPLTHR   0x5
+ *  12:08          CHGVGANSTHR   0x1
+ *  04:00          CHGVGANLTHR   0x5
+ * 
+ * + * @{ + */ + +/// Address of the RWNXAGCCGH register +#define AGC_RWNXAGCCGH_ADDR 0x01002030 +/// Offset of the RWNXAGCCGH register from the base address +#define AGC_RWNXAGCCGH_OFFSET 0x00002030 +/// Index of the RWNXAGCCGH register +#define AGC_RWNXAGCCGH_INDEX 0x0000080C +/// Reset value of the RWNXAGCCGH register +#define AGC_RWNXAGCCGH_RESET 0x01050105 + +/** + * @brief Returns the current value of the RWNXAGCCGH register. + * The RWNXAGCCGH register will be read and its value returned. + * @return The current value of the RWNXAGCCGH register. + */ +__INLINE uint32_t agc_rwnxagccgh_get(void) +{ + return REG_PL_RD(AGC_RWNXAGCCGH_ADDR); +} + +/** + * @brief Sets the RWNXAGCCGH register to a value. + * The RWNXAGCCGH register will be written. + * @param value - The value to write. + */ +__INLINE void agc_rwnxagccgh_set(uint32_t value) +{ + REG_PL_WR(AGC_RWNXAGCCGH_ADDR, value); +} + +// field definitions +/// CHGVGAPSTHR field mask +#define AGC_CHGVGAPSTHR_MASK ((uint32_t)0x1F000000) +/// CHGVGAPSTHR field LSB position +#define AGC_CHGVGAPSTHR_LSB 24 +/// CHGVGAPSTHR field width +#define AGC_CHGVGAPSTHR_WIDTH ((uint32_t)0x00000005) +/// CHGVGAPLTHR field mask +#define AGC_CHGVGAPLTHR_MASK ((uint32_t)0x001F0000) +/// CHGVGAPLTHR field LSB position +#define AGC_CHGVGAPLTHR_LSB 16 +/// CHGVGAPLTHR field width +#define AGC_CHGVGAPLTHR_WIDTH ((uint32_t)0x00000005) +/// CHGVGANSTHR field mask +#define AGC_CHGVGANSTHR_MASK ((uint32_t)0x00001F00) +/// CHGVGANSTHR field LSB position +#define AGC_CHGVGANSTHR_LSB 8 +/// CHGVGANSTHR field width +#define AGC_CHGVGANSTHR_WIDTH ((uint32_t)0x00000005) +/// CHGVGANLTHR field mask +#define AGC_CHGVGANLTHR_MASK ((uint32_t)0x0000001F) +/// CHGVGANLTHR field LSB position +#define AGC_CHGVGANLTHR_LSB 0 +/// CHGVGANLTHR field width +#define AGC_CHGVGANLTHR_WIDTH ((uint32_t)0x00000005) + +/// CHGVGAPSTHR field reset value +#define AGC_CHGVGAPSTHR_RST 0x1 +/// CHGVGAPLTHR field reset value +#define AGC_CHGVGAPLTHR_RST 0x5 +/// CHGVGANSTHR field reset value +#define AGC_CHGVGANSTHR_RST 0x1 +/// CHGVGANLTHR field reset value +#define AGC_CHGVGANLTHR_RST 0x5 + +/** + * @brief Constructs a value for the RWNXAGCCGH register given values for its fields + * and writes the value to the register. + * + * @param[in] chgvgapsthr - The value to use for the CHGVGAPSTHR field. + * @param[in] chgvgaplthr - The value to use for the CHGVGAPLTHR field. + * @param[in] chgvgansthr - The value to use for the CHGVGANSTHR field. + * @param[in] chgvganlthr - The value to use for the CHGVGANLTHR field. + */ +__INLINE void agc_rwnxagccgh_pack(uint8_t chgvgapsthr, uint8_t chgvgaplthr, uint8_t chgvgansthr, uint8_t chgvganlthr) +{ + ASSERT_ERR((((uint32_t)chgvgapsthr << 24) & ~((uint32_t)0x1F000000)) == 0); + ASSERT_ERR((((uint32_t)chgvgaplthr << 16) & ~((uint32_t)0x001F0000)) == 0); + ASSERT_ERR((((uint32_t)chgvgansthr << 8) & ~((uint32_t)0x00001F00)) == 0); + ASSERT_ERR((((uint32_t)chgvganlthr << 0) & ~((uint32_t)0x0000001F)) == 0); + REG_PL_WR(AGC_RWNXAGCCGH_ADDR, ((uint32_t)chgvgapsthr << 24) | ((uint32_t)chgvgaplthr << 16) | ((uint32_t)chgvgansthr << 8) | ((uint32_t)chgvganlthr << 0)); +} + +/** + * @brief Unpacks RWNXAGCCGH's fields from current value of the RWNXAGCCGH register. + * + * Reads the RWNXAGCCGH register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] chgvgapsthr - Will be populated with the current value of this field from the register. + * @param[out] chgvgaplthr - Will be populated with the current value of this field from the register. + * @param[out] chgvgansthr - Will be populated with the current value of this field from the register. + * @param[out] chgvganlthr - Will be populated with the current value of this field from the register. + */ +__INLINE void agc_rwnxagccgh_unpack(uint8_t *chgvgapsthr, uint8_t *chgvgaplthr, uint8_t *chgvgansthr, uint8_t *chgvganlthr) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCCGH_ADDR); + + *chgvgapsthr = (localVal & ((uint32_t)0x1F000000)) >> 24; + *chgvgaplthr = (localVal & ((uint32_t)0x001F0000)) >> 16; + *chgvgansthr = (localVal & ((uint32_t)0x00001F00)) >> 8; + *chgvganlthr = (localVal & ((uint32_t)0x0000001F)) >> 0; +} + +/** + * @brief Returns the current value of the CHGVGAPSTHR field in the RWNXAGCCGH register. + * + * The RWNXAGCCGH register will be read and the CHGVGAPSTHR field's value will be returned. + * + * @return The current value of the CHGVGAPSTHR field in the RWNXAGCCGH register. + */ +__INLINE uint8_t agc_chgvgapsthr_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCCGH_ADDR); + return ((localVal & ((uint32_t)0x1F000000)) >> 24); +} + +/** + * @brief Sets the CHGVGAPSTHR field of the RWNXAGCCGH register. + * + * The RWNXAGCCGH register will be read, modified to contain the new field value, and written. + * + * @param[in] chgvgapsthr - The value to set the field to. + */ +__INLINE void agc_chgvgapsthr_setf(uint8_t chgvgapsthr) +{ + ASSERT_ERR((((uint32_t)chgvgapsthr << 24) & ~((uint32_t)0x1F000000)) == 0); + REG_PL_WR(AGC_RWNXAGCCGH_ADDR, (REG_PL_RD(AGC_RWNXAGCCGH_ADDR) & ~((uint32_t)0x1F000000)) | ((uint32_t)chgvgapsthr << 24)); +} + +/** + * @brief Returns the current value of the CHGVGAPLTHR field in the RWNXAGCCGH register. + * + * The RWNXAGCCGH register will be read and the CHGVGAPLTHR field's value will be returned. + * + * @return The current value of the CHGVGAPLTHR field in the RWNXAGCCGH register. + */ +__INLINE uint8_t agc_chgvgaplthr_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCCGH_ADDR); + return ((localVal & ((uint32_t)0x001F0000)) >> 16); +} + +/** + * @brief Sets the CHGVGAPLTHR field of the RWNXAGCCGH register. + * + * The RWNXAGCCGH register will be read, modified to contain the new field value, and written. + * + * @param[in] chgvgaplthr - The value to set the field to. + */ +__INLINE void agc_chgvgaplthr_setf(uint8_t chgvgaplthr) +{ + ASSERT_ERR((((uint32_t)chgvgaplthr << 16) & ~((uint32_t)0x001F0000)) == 0); + REG_PL_WR(AGC_RWNXAGCCGH_ADDR, (REG_PL_RD(AGC_RWNXAGCCGH_ADDR) & ~((uint32_t)0x001F0000)) | ((uint32_t)chgvgaplthr << 16)); +} + +/** + * @brief Returns the current value of the CHGVGANSTHR field in the RWNXAGCCGH register. + * + * The RWNXAGCCGH register will be read and the CHGVGANSTHR field's value will be returned. + * + * @return The current value of the CHGVGANSTHR field in the RWNXAGCCGH register. + */ +__INLINE uint8_t agc_chgvgansthr_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCCGH_ADDR); + return ((localVal & ((uint32_t)0x00001F00)) >> 8); +} + +/** + * @brief Sets the CHGVGANSTHR field of the RWNXAGCCGH register. + * + * The RWNXAGCCGH register will be read, modified to contain the new field value, and written. + * + * @param[in] chgvgansthr - The value to set the field to. + */ +__INLINE void agc_chgvgansthr_setf(uint8_t chgvgansthr) +{ + ASSERT_ERR((((uint32_t)chgvgansthr << 8) & ~((uint32_t)0x00001F00)) == 0); + REG_PL_WR(AGC_RWNXAGCCGH_ADDR, (REG_PL_RD(AGC_RWNXAGCCGH_ADDR) & ~((uint32_t)0x00001F00)) | ((uint32_t)chgvgansthr << 8)); +} + +/** + * @brief Returns the current value of the CHGVGANLTHR field in the RWNXAGCCGH register. + * + * The RWNXAGCCGH register will be read and the CHGVGANLTHR field's value will be returned. + * + * @return The current value of the CHGVGANLTHR field in the RWNXAGCCGH register. + */ +__INLINE uint8_t agc_chgvganlthr_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCCGH_ADDR); + return ((localVal & ((uint32_t)0x0000001F)) >> 0); +} + +/** + * @brief Sets the CHGVGANLTHR field of the RWNXAGCCGH register. + * + * The RWNXAGCCGH register will be read, modified to contain the new field value, and written. + * + * @param[in] chgvganlthr - The value to set the field to. + */ +__INLINE void agc_chgvganlthr_setf(uint8_t chgvganlthr) +{ + ASSERT_ERR((((uint32_t)chgvganlthr << 0) & ~((uint32_t)0x0000001F)) == 0); + REG_PL_WR(AGC_RWNXAGCCGH_ADDR, (REG_PL_RD(AGC_RWNXAGCCGH_ADDR) & ~((uint32_t)0x0000001F)) | ((uint32_t)chgvganlthr << 0)); +} + +/// @} + +/** + * @name RWNXAGCSAT register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  28:24         SATDELAY50NS   0x8
+ *  21:16        SATHIGHTHRDBV   0x39
+ *  13:08         SATLOWTHRDBV   0x35
+ *  05:00            SATTHRDBV   0x36
+ * 
+ * + * @{ + */ + +/// Address of the RWNXAGCSAT register +#define AGC_RWNXAGCSAT_ADDR 0x01002034 +/// Offset of the RWNXAGCSAT register from the base address +#define AGC_RWNXAGCSAT_OFFSET 0x00002034 +/// Index of the RWNXAGCSAT register +#define AGC_RWNXAGCSAT_INDEX 0x0000080D +/// Reset value of the RWNXAGCSAT register +#define AGC_RWNXAGCSAT_RESET 0x08393536 + +/** + * @brief Returns the current value of the RWNXAGCSAT register. + * The RWNXAGCSAT register will be read and its value returned. + * @return The current value of the RWNXAGCSAT register. + */ +__INLINE uint32_t agc_rwnxagcsat_get(void) +{ + return REG_PL_RD(AGC_RWNXAGCSAT_ADDR); +} + +/** + * @brief Sets the RWNXAGCSAT register to a value. + * The RWNXAGCSAT register will be written. + * @param value - The value to write. + */ +__INLINE void agc_rwnxagcsat_set(uint32_t value) +{ + REG_PL_WR(AGC_RWNXAGCSAT_ADDR, value); +} + +// field definitions +/// SATDELAY50NS field mask +#define AGC_SATDELAY50NS_MASK ((uint32_t)0x1F000000) +/// SATDELAY50NS field LSB position +#define AGC_SATDELAY50NS_LSB 24 +/// SATDELAY50NS field width +#define AGC_SATDELAY50NS_WIDTH ((uint32_t)0x00000005) +/// SATHIGHTHRDBV field mask +#define AGC_SATHIGHTHRDBV_MASK ((uint32_t)0x003F0000) +/// SATHIGHTHRDBV field LSB position +#define AGC_SATHIGHTHRDBV_LSB 16 +/// SATHIGHTHRDBV field width +#define AGC_SATHIGHTHRDBV_WIDTH ((uint32_t)0x00000006) +/// SATLOWTHRDBV field mask +#define AGC_SATLOWTHRDBV_MASK ((uint32_t)0x00003F00) +/// SATLOWTHRDBV field LSB position +#define AGC_SATLOWTHRDBV_LSB 8 +/// SATLOWTHRDBV field width +#define AGC_SATLOWTHRDBV_WIDTH ((uint32_t)0x00000006) +/// SATTHRDBV field mask +#define AGC_SATTHRDBV_MASK ((uint32_t)0x0000003F) +/// SATTHRDBV field LSB position +#define AGC_SATTHRDBV_LSB 0 +/// SATTHRDBV field width +#define AGC_SATTHRDBV_WIDTH ((uint32_t)0x00000006) + +/// SATDELAY50NS field reset value +#define AGC_SATDELAY50NS_RST 0x8 +/// SATHIGHTHRDBV field reset value +#define AGC_SATHIGHTHRDBV_RST 0x39 +/// SATLOWTHRDBV field reset value +#define AGC_SATLOWTHRDBV_RST 0x35 +/// SATTHRDBV field reset value +#define AGC_SATTHRDBV_RST 0x36 + +/** + * @brief Constructs a value for the RWNXAGCSAT register given values for its fields + * and writes the value to the register. + * + * @param[in] satdelay50ns - The value to use for the SATDELAY50NS field. + * @param[in] sathighthrdbv - The value to use for the SATHIGHTHRDBV field. + * @param[in] satlowthrdbv - The value to use for the SATLOWTHRDBV field. + * @param[in] satthrdbv - The value to use for the SATTHRDBV field. + */ +__INLINE void agc_rwnxagcsat_pack(uint8_t satdelay50ns, uint8_t sathighthrdbv, uint8_t satlowthrdbv, uint8_t satthrdbv) +{ + ASSERT_ERR((((uint32_t)satdelay50ns << 24) & ~((uint32_t)0x1F000000)) == 0); + ASSERT_ERR((((uint32_t)sathighthrdbv << 16) & ~((uint32_t)0x003F0000)) == 0); + ASSERT_ERR((((uint32_t)satlowthrdbv << 8) & ~((uint32_t)0x00003F00)) == 0); + ASSERT_ERR((((uint32_t)satthrdbv << 0) & ~((uint32_t)0x0000003F)) == 0); + REG_PL_WR(AGC_RWNXAGCSAT_ADDR, ((uint32_t)satdelay50ns << 24) | ((uint32_t)sathighthrdbv << 16) | ((uint32_t)satlowthrdbv << 8) | ((uint32_t)satthrdbv << 0)); +} + +/** + * @brief Unpacks RWNXAGCSAT's fields from current value of the RWNXAGCSAT register. + * + * Reads the RWNXAGCSAT register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] satdelay50ns - Will be populated with the current value of this field from the register. + * @param[out] sathighthrdbv - Will be populated with the current value of this field from the register. + * @param[out] satlowthrdbv - Will be populated with the current value of this field from the register. + * @param[out] satthrdbv - Will be populated with the current value of this field from the register. + */ +__INLINE void agc_rwnxagcsat_unpack(uint8_t *satdelay50ns, uint8_t *sathighthrdbv, uint8_t *satlowthrdbv, uint8_t *satthrdbv) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCSAT_ADDR); + + *satdelay50ns = (localVal & ((uint32_t)0x1F000000)) >> 24; + *sathighthrdbv = (localVal & ((uint32_t)0x003F0000)) >> 16; + *satlowthrdbv = (localVal & ((uint32_t)0x00003F00)) >> 8; + *satthrdbv = (localVal & ((uint32_t)0x0000003F)) >> 0; +} + +/** + * @brief Returns the current value of the SATDELAY50NS field in the RWNXAGCSAT register. + * + * The RWNXAGCSAT register will be read and the SATDELAY50NS field's value will be returned. + * + * @return The current value of the SATDELAY50NS field in the RWNXAGCSAT register. + */ +__INLINE uint8_t agc_satdelay50ns_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCSAT_ADDR); + return ((localVal & ((uint32_t)0x1F000000)) >> 24); +} + +/** + * @brief Sets the SATDELAY50NS field of the RWNXAGCSAT register. + * + * The RWNXAGCSAT register will be read, modified to contain the new field value, and written. + * + * @param[in] satdelay50ns - The value to set the field to. + */ +__INLINE void agc_satdelay50ns_setf(uint8_t satdelay50ns) +{ + ASSERT_ERR((((uint32_t)satdelay50ns << 24) & ~((uint32_t)0x1F000000)) == 0); + REG_PL_WR(AGC_RWNXAGCSAT_ADDR, (REG_PL_RD(AGC_RWNXAGCSAT_ADDR) & ~((uint32_t)0x1F000000)) | ((uint32_t)satdelay50ns << 24)); +} + +/** + * @brief Returns the current value of the SATHIGHTHRDBV field in the RWNXAGCSAT register. + * + * The RWNXAGCSAT register will be read and the SATHIGHTHRDBV field's value will be returned. + * + * @return The current value of the SATHIGHTHRDBV field in the RWNXAGCSAT register. + */ +__INLINE uint8_t agc_sathighthrdbv_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCSAT_ADDR); + return ((localVal & ((uint32_t)0x003F0000)) >> 16); +} + +/** + * @brief Sets the SATHIGHTHRDBV field of the RWNXAGCSAT register. + * + * The RWNXAGCSAT register will be read, modified to contain the new field value, and written. + * + * @param[in] sathighthrdbv - The value to set the field to. + */ +__INLINE void agc_sathighthrdbv_setf(uint8_t sathighthrdbv) +{ + ASSERT_ERR((((uint32_t)sathighthrdbv << 16) & ~((uint32_t)0x003F0000)) == 0); + REG_PL_WR(AGC_RWNXAGCSAT_ADDR, (REG_PL_RD(AGC_RWNXAGCSAT_ADDR) & ~((uint32_t)0x003F0000)) | ((uint32_t)sathighthrdbv << 16)); +} + +/** + * @brief Returns the current value of the SATLOWTHRDBV field in the RWNXAGCSAT register. + * + * The RWNXAGCSAT register will be read and the SATLOWTHRDBV field's value will be returned. + * + * @return The current value of the SATLOWTHRDBV field in the RWNXAGCSAT register. + */ +__INLINE uint8_t agc_satlowthrdbv_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCSAT_ADDR); + return ((localVal & ((uint32_t)0x00003F00)) >> 8); +} + +/** + * @brief Sets the SATLOWTHRDBV field of the RWNXAGCSAT register. + * + * The RWNXAGCSAT register will be read, modified to contain the new field value, and written. + * + * @param[in] satlowthrdbv - The value to set the field to. + */ +__INLINE void agc_satlowthrdbv_setf(uint8_t satlowthrdbv) +{ + ASSERT_ERR((((uint32_t)satlowthrdbv << 8) & ~((uint32_t)0x00003F00)) == 0); + REG_PL_WR(AGC_RWNXAGCSAT_ADDR, (REG_PL_RD(AGC_RWNXAGCSAT_ADDR) & ~((uint32_t)0x00003F00)) | ((uint32_t)satlowthrdbv << 8)); +} + +/** + * @brief Returns the current value of the SATTHRDBV field in the RWNXAGCSAT register. + * + * The RWNXAGCSAT register will be read and the SATTHRDBV field's value will be returned. + * + * @return The current value of the SATTHRDBV field in the RWNXAGCSAT register. + */ +__INLINE uint8_t agc_satthrdbv_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCSAT_ADDR); + return ((localVal & ((uint32_t)0x0000003F)) >> 0); +} + +/** + * @brief Sets the SATTHRDBV field of the RWNXAGCSAT register. + * + * The RWNXAGCSAT register will be read, modified to contain the new field value, and written. + * + * @param[in] satthrdbv - The value to set the field to. + */ +__INLINE void agc_satthrdbv_setf(uint8_t satthrdbv) +{ + ASSERT_ERR((((uint32_t)satthrdbv << 0) & ~((uint32_t)0x0000003F)) == 0); + REG_PL_WR(AGC_RWNXAGCSAT_ADDR, (REG_PL_RD(AGC_RWNXAGCSAT_ADDR) & ~((uint32_t)0x0000003F)) | ((uint32_t)satthrdbv << 0)); +} + +/// @} + +/** + * @name RWNXAGCCROSS register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  21:12       CROSSDNTHRQDBM   0x280
+ *  09:00       CROSSUPTHRQDBM   0x288
+ * 
+ * + * @{ + */ + +/// Address of the RWNXAGCCROSS register +#define AGC_RWNXAGCCROSS_ADDR 0x01002038 +/// Offset of the RWNXAGCCROSS register from the base address +#define AGC_RWNXAGCCROSS_OFFSET 0x00002038 +/// Index of the RWNXAGCCROSS register +#define AGC_RWNXAGCCROSS_INDEX 0x0000080E +/// Reset value of the RWNXAGCCROSS register +#define AGC_RWNXAGCCROSS_RESET 0x00280288 + +/** + * @brief Returns the current value of the RWNXAGCCROSS register. + * The RWNXAGCCROSS register will be read and its value returned. + * @return The current value of the RWNXAGCCROSS register. + */ +__INLINE uint32_t agc_rwnxagccross_get(void) +{ + return REG_PL_RD(AGC_RWNXAGCCROSS_ADDR); +} + +/** + * @brief Sets the RWNXAGCCROSS register to a value. + * The RWNXAGCCROSS register will be written. + * @param value - The value to write. + */ +__INLINE void agc_rwnxagccross_set(uint32_t value) +{ + REG_PL_WR(AGC_RWNXAGCCROSS_ADDR, value); +} + +// field definitions +/// CROSSDNTHRQDBM field mask +#define AGC_CROSSDNTHRQDBM_MASK ((uint32_t)0x003FF000) +/// CROSSDNTHRQDBM field LSB position +#define AGC_CROSSDNTHRQDBM_LSB 12 +/// CROSSDNTHRQDBM field width +#define AGC_CROSSDNTHRQDBM_WIDTH ((uint32_t)0x0000000A) +/// CROSSUPTHRQDBM field mask +#define AGC_CROSSUPTHRQDBM_MASK ((uint32_t)0x000003FF) +/// CROSSUPTHRQDBM field LSB position +#define AGC_CROSSUPTHRQDBM_LSB 0 +/// CROSSUPTHRQDBM field width +#define AGC_CROSSUPTHRQDBM_WIDTH ((uint32_t)0x0000000A) + +/// CROSSDNTHRQDBM field reset value +#define AGC_CROSSDNTHRQDBM_RST 0x280 +/// CROSSUPTHRQDBM field reset value +#define AGC_CROSSUPTHRQDBM_RST 0x288 + +/** + * @brief Constructs a value for the RWNXAGCCROSS register given values for its fields + * and writes the value to the register. + * + * @param[in] crossdnthrqdbm - The value to use for the CROSSDNTHRQDBM field. + * @param[in] crossupthrqdbm - The value to use for the CROSSUPTHRQDBM field. + */ +__INLINE void agc_rwnxagccross_pack(uint16_t crossdnthrqdbm, uint16_t crossupthrqdbm) +{ + ASSERT_ERR((((uint32_t)crossdnthrqdbm << 12) & ~((uint32_t)0x003FF000)) == 0); + ASSERT_ERR((((uint32_t)crossupthrqdbm << 0) & ~((uint32_t)0x000003FF)) == 0); + REG_PL_WR(AGC_RWNXAGCCROSS_ADDR, ((uint32_t)crossdnthrqdbm << 12) | ((uint32_t)crossupthrqdbm << 0)); +} + +/** + * @brief Unpacks RWNXAGCCROSS's fields from current value of the RWNXAGCCROSS register. + * + * Reads the RWNXAGCCROSS register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] crossdnthrqdbm - Will be populated with the current value of this field from the register. + * @param[out] crossupthrqdbm - Will be populated with the current value of this field from the register. + */ +__INLINE void agc_rwnxagccross_unpack(uint16_t *crossdnthrqdbm, uint16_t *crossupthrqdbm) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCCROSS_ADDR); + + *crossdnthrqdbm = (localVal & ((uint32_t)0x003FF000)) >> 12; + *crossupthrqdbm = (localVal & ((uint32_t)0x000003FF)) >> 0; +} + +/** + * @brief Returns the current value of the CROSSDNTHRQDBM field in the RWNXAGCCROSS register. + * + * The RWNXAGCCROSS register will be read and the CROSSDNTHRQDBM field's value will be returned. + * + * @return The current value of the CROSSDNTHRQDBM field in the RWNXAGCCROSS register. + */ +__INLINE uint16_t agc_crossdnthrqdbm_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCCROSS_ADDR); + return ((localVal & ((uint32_t)0x003FF000)) >> 12); +} + +/** + * @brief Sets the CROSSDNTHRQDBM field of the RWNXAGCCROSS register. + * + * The RWNXAGCCROSS register will be read, modified to contain the new field value, and written. + * + * @param[in] crossdnthrqdbm - The value to set the field to. + */ +__INLINE void agc_crossdnthrqdbm_setf(uint16_t crossdnthrqdbm) +{ + ASSERT_ERR((((uint32_t)crossdnthrqdbm << 12) & ~((uint32_t)0x003FF000)) == 0); + REG_PL_WR(AGC_RWNXAGCCROSS_ADDR, (REG_PL_RD(AGC_RWNXAGCCROSS_ADDR) & ~((uint32_t)0x003FF000)) | ((uint32_t)crossdnthrqdbm << 12)); +} + +/** + * @brief Returns the current value of the CROSSUPTHRQDBM field in the RWNXAGCCROSS register. + * + * The RWNXAGCCROSS register will be read and the CROSSUPTHRQDBM field's value will be returned. + * + * @return The current value of the CROSSUPTHRQDBM field in the RWNXAGCCROSS register. + */ +__INLINE uint16_t agc_crossupthrqdbm_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCCROSS_ADDR); + return ((localVal & ((uint32_t)0x000003FF)) >> 0); +} + +/** + * @brief Sets the CROSSUPTHRQDBM field of the RWNXAGCCROSS register. + * + * The RWNXAGCCROSS register will be read, modified to contain the new field value, and written. + * + * @param[in] crossupthrqdbm - The value to set the field to. + */ +__INLINE void agc_crossupthrqdbm_setf(uint16_t crossupthrqdbm) +{ + ASSERT_ERR((((uint32_t)crossupthrqdbm << 0) & ~((uint32_t)0x000003FF)) == 0); + REG_PL_WR(AGC_RWNXAGCCROSS_ADDR, (REG_PL_RD(AGC_RWNXAGCCROSS_ADDR) & ~((uint32_t)0x000003FF)) | ((uint32_t)crossupthrqdbm << 0)); +} + +/// @} + +/** + * @name RWNXAGCRAMP register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  26:24       RAMPDNNDLINDEX   0x7
+ *  23:16         RAMPDNGAPQDB   0x20
+ *  10:08       RAMPUPNDLINDEX   0x7
+ *  07:00         RAMPUPGAPQDB   0x10
+ * 
+ * + * @{ + */ + +/// Address of the RWNXAGCRAMP register +#define AGC_RWNXAGCRAMP_ADDR 0x0100203C +/// Offset of the RWNXAGCRAMP register from the base address +#define AGC_RWNXAGCRAMP_OFFSET 0x0000203C +/// Index of the RWNXAGCRAMP register +#define AGC_RWNXAGCRAMP_INDEX 0x0000080F +/// Reset value of the RWNXAGCRAMP register +#define AGC_RWNXAGCRAMP_RESET 0x07200710 + +/** + * @brief Returns the current value of the RWNXAGCRAMP register. + * The RWNXAGCRAMP register will be read and its value returned. + * @return The current value of the RWNXAGCRAMP register. + */ +__INLINE uint32_t agc_rwnxagcramp_get(void) +{ + return REG_PL_RD(AGC_RWNXAGCRAMP_ADDR); +} + +/** + * @brief Sets the RWNXAGCRAMP register to a value. + * The RWNXAGCRAMP register will be written. + * @param value - The value to write. + */ +__INLINE void agc_rwnxagcramp_set(uint32_t value) +{ + REG_PL_WR(AGC_RWNXAGCRAMP_ADDR, value); +} + +// field definitions +/// RAMPDNNDLINDEX field mask +#define AGC_RAMPDNNDLINDEX_MASK ((uint32_t)0x07000000) +/// RAMPDNNDLINDEX field LSB position +#define AGC_RAMPDNNDLINDEX_LSB 24 +/// RAMPDNNDLINDEX field width +#define AGC_RAMPDNNDLINDEX_WIDTH ((uint32_t)0x00000003) +/// RAMPDNGAPQDB field mask +#define AGC_RAMPDNGAPQDB_MASK ((uint32_t)0x00FF0000) +/// RAMPDNGAPQDB field LSB position +#define AGC_RAMPDNGAPQDB_LSB 16 +/// RAMPDNGAPQDB field width +#define AGC_RAMPDNGAPQDB_WIDTH ((uint32_t)0x00000008) +/// RAMPUPNDLINDEX field mask +#define AGC_RAMPUPNDLINDEX_MASK ((uint32_t)0x00000700) +/// RAMPUPNDLINDEX field LSB position +#define AGC_RAMPUPNDLINDEX_LSB 8 +/// RAMPUPNDLINDEX field width +#define AGC_RAMPUPNDLINDEX_WIDTH ((uint32_t)0x00000003) +/// RAMPUPGAPQDB field mask +#define AGC_RAMPUPGAPQDB_MASK ((uint32_t)0x000000FF) +/// RAMPUPGAPQDB field LSB position +#define AGC_RAMPUPGAPQDB_LSB 0 +/// RAMPUPGAPQDB field width +#define AGC_RAMPUPGAPQDB_WIDTH ((uint32_t)0x00000008) + +/// RAMPDNNDLINDEX field reset value +#define AGC_RAMPDNNDLINDEX_RST 0x7 +/// RAMPDNGAPQDB field reset value +#define AGC_RAMPDNGAPQDB_RST 0x20 +/// RAMPUPNDLINDEX field reset value +#define AGC_RAMPUPNDLINDEX_RST 0x7 +/// RAMPUPGAPQDB field reset value +#define AGC_RAMPUPGAPQDB_RST 0x10 + +/** + * @brief Constructs a value for the RWNXAGCRAMP register given values for its fields + * and writes the value to the register. + * + * @param[in] rampdnndlindex - The value to use for the RAMPDNNDLINDEX field. + * @param[in] rampdngapqdb - The value to use for the RAMPDNGAPQDB field. + * @param[in] rampupndlindex - The value to use for the RAMPUPNDLINDEX field. + * @param[in] rampupgapqdb - The value to use for the RAMPUPGAPQDB field. + */ +__INLINE void agc_rwnxagcramp_pack(uint8_t rampdnndlindex, uint8_t rampdngapqdb, uint8_t rampupndlindex, uint8_t rampupgapqdb) +{ + ASSERT_ERR((((uint32_t)rampdnndlindex << 24) & ~((uint32_t)0x07000000)) == 0); + ASSERT_ERR((((uint32_t)rampdngapqdb << 16) & ~((uint32_t)0x00FF0000)) == 0); + ASSERT_ERR((((uint32_t)rampupndlindex << 8) & ~((uint32_t)0x00000700)) == 0); + ASSERT_ERR((((uint32_t)rampupgapqdb << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(AGC_RWNXAGCRAMP_ADDR, ((uint32_t)rampdnndlindex << 24) | ((uint32_t)rampdngapqdb << 16) | ((uint32_t)rampupndlindex << 8) | ((uint32_t)rampupgapqdb << 0)); +} + +/** + * @brief Unpacks RWNXAGCRAMP's fields from current value of the RWNXAGCRAMP register. + * + * Reads the RWNXAGCRAMP register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] rampdnndlindex - Will be populated with the current value of this field from the register. + * @param[out] rampdngapqdb - Will be populated with the current value of this field from the register. + * @param[out] rampupndlindex - Will be populated with the current value of this field from the register. + * @param[out] rampupgapqdb - Will be populated with the current value of this field from the register. + */ +__INLINE void agc_rwnxagcramp_unpack(uint8_t *rampdnndlindex, uint8_t *rampdngapqdb, uint8_t *rampupndlindex, uint8_t *rampupgapqdb) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCRAMP_ADDR); + + *rampdnndlindex = (localVal & ((uint32_t)0x07000000)) >> 24; + *rampdngapqdb = (localVal & ((uint32_t)0x00FF0000)) >> 16; + *rampupndlindex = (localVal & ((uint32_t)0x00000700)) >> 8; + *rampupgapqdb = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +/** + * @brief Returns the current value of the RAMPDNNDLINDEX field in the RWNXAGCRAMP register. + * + * The RWNXAGCRAMP register will be read and the RAMPDNNDLINDEX field's value will be returned. + * + * @return The current value of the RAMPDNNDLINDEX field in the RWNXAGCRAMP register. + */ +__INLINE uint8_t agc_rampdnndlindex_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCRAMP_ADDR); + return ((localVal & ((uint32_t)0x07000000)) >> 24); +} + +/** + * @brief Sets the RAMPDNNDLINDEX field of the RWNXAGCRAMP register. + * + * The RWNXAGCRAMP register will be read, modified to contain the new field value, and written. + * + * @param[in] rampdnndlindex - The value to set the field to. + */ +__INLINE void agc_rampdnndlindex_setf(uint8_t rampdnndlindex) +{ + ASSERT_ERR((((uint32_t)rampdnndlindex << 24) & ~((uint32_t)0x07000000)) == 0); + REG_PL_WR(AGC_RWNXAGCRAMP_ADDR, (REG_PL_RD(AGC_RWNXAGCRAMP_ADDR) & ~((uint32_t)0x07000000)) | ((uint32_t)rampdnndlindex << 24)); +} + +/** + * @brief Returns the current value of the RAMPDNGAPQDB field in the RWNXAGCRAMP register. + * + * The RWNXAGCRAMP register will be read and the RAMPDNGAPQDB field's value will be returned. + * + * @return The current value of the RAMPDNGAPQDB field in the RWNXAGCRAMP register. + */ +__INLINE uint8_t agc_rampdngapqdb_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCRAMP_ADDR); + return ((localVal & ((uint32_t)0x00FF0000)) >> 16); +} + +/** + * @brief Sets the RAMPDNGAPQDB field of the RWNXAGCRAMP register. + * + * The RWNXAGCRAMP register will be read, modified to contain the new field value, and written. + * + * @param[in] rampdngapqdb - The value to set the field to. + */ +__INLINE void agc_rampdngapqdb_setf(uint8_t rampdngapqdb) +{ + ASSERT_ERR((((uint32_t)rampdngapqdb << 16) & ~((uint32_t)0x00FF0000)) == 0); + REG_PL_WR(AGC_RWNXAGCRAMP_ADDR, (REG_PL_RD(AGC_RWNXAGCRAMP_ADDR) & ~((uint32_t)0x00FF0000)) | ((uint32_t)rampdngapqdb << 16)); +} + +/** + * @brief Returns the current value of the RAMPUPNDLINDEX field in the RWNXAGCRAMP register. + * + * The RWNXAGCRAMP register will be read and the RAMPUPNDLINDEX field's value will be returned. + * + * @return The current value of the RAMPUPNDLINDEX field in the RWNXAGCRAMP register. + */ +__INLINE uint8_t agc_rampupndlindex_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCRAMP_ADDR); + return ((localVal & ((uint32_t)0x00000700)) >> 8); +} + +/** + * @brief Sets the RAMPUPNDLINDEX field of the RWNXAGCRAMP register. + * + * The RWNXAGCRAMP register will be read, modified to contain the new field value, and written. + * + * @param[in] rampupndlindex - The value to set the field to. + */ +__INLINE void agc_rampupndlindex_setf(uint8_t rampupndlindex) +{ + ASSERT_ERR((((uint32_t)rampupndlindex << 8) & ~((uint32_t)0x00000700)) == 0); + REG_PL_WR(AGC_RWNXAGCRAMP_ADDR, (REG_PL_RD(AGC_RWNXAGCRAMP_ADDR) & ~((uint32_t)0x00000700)) | ((uint32_t)rampupndlindex << 8)); +} + +/** + * @brief Returns the current value of the RAMPUPGAPQDB field in the RWNXAGCRAMP register. + * + * The RWNXAGCRAMP register will be read and the RAMPUPGAPQDB field's value will be returned. + * + * @return The current value of the RAMPUPGAPQDB field in the RWNXAGCRAMP register. + */ +__INLINE uint8_t agc_rampupgapqdb_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCRAMP_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +/** + * @brief Sets the RAMPUPGAPQDB field of the RWNXAGCRAMP register. + * + * The RWNXAGCRAMP register will be read, modified to contain the new field value, and written. + * + * @param[in] rampupgapqdb - The value to set the field to. + */ +__INLINE void agc_rampupgapqdb_setf(uint8_t rampupgapqdb) +{ + ASSERT_ERR((((uint32_t)rampupgapqdb << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(AGC_RWNXAGCRAMP_ADDR, (REG_PL_RD(AGC_RWNXAGCRAMP_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)rampupgapqdb << 0)); +} + +/// @} + +/** + * @name RWNXAGCSTABDIS register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  27:24         ADCPOWDISNDL   0x8
+ *  22:16      ADCPOWDISTHRDBV   0x5D
+ *  10:08         PLATNDLINDEX   0x3
+ *  04:00            PLATDPQDB   0x8
+ * 
+ * + * @{ + */ + +/// Address of the RWNXAGCSTABDIS register +#define AGC_RWNXAGCSTABDIS_ADDR 0x01002040 +/// Offset of the RWNXAGCSTABDIS register from the base address +#define AGC_RWNXAGCSTABDIS_OFFSET 0x00002040 +/// Index of the RWNXAGCSTABDIS register +#define AGC_RWNXAGCSTABDIS_INDEX 0x00000810 +/// Reset value of the RWNXAGCSTABDIS register +#define AGC_RWNXAGCSTABDIS_RESET 0x085D0308 + +/** + * @brief Returns the current value of the RWNXAGCSTABDIS register. + * The RWNXAGCSTABDIS register will be read and its value returned. + * @return The current value of the RWNXAGCSTABDIS register. + */ +__INLINE uint32_t agc_rwnxagcstabdis_get(void) +{ + return REG_PL_RD(AGC_RWNXAGCSTABDIS_ADDR); +} + +/** + * @brief Sets the RWNXAGCSTABDIS register to a value. + * The RWNXAGCSTABDIS register will be written. + * @param value - The value to write. + */ +__INLINE void agc_rwnxagcstabdis_set(uint32_t value) +{ + REG_PL_WR(AGC_RWNXAGCSTABDIS_ADDR, value); +} + +// field definitions +/// ADCPOWDISNDL field mask +#define AGC_ADCPOWDISNDL_MASK ((uint32_t)0x0F000000) +/// ADCPOWDISNDL field LSB position +#define AGC_ADCPOWDISNDL_LSB 24 +/// ADCPOWDISNDL field width +#define AGC_ADCPOWDISNDL_WIDTH ((uint32_t)0x00000004) +/// ADCPOWDISTHRDBV field mask +#define AGC_ADCPOWDISTHRDBV_MASK ((uint32_t)0x007F0000) +/// ADCPOWDISTHRDBV field LSB position +#define AGC_ADCPOWDISTHRDBV_LSB 16 +/// ADCPOWDISTHRDBV field width +#define AGC_ADCPOWDISTHRDBV_WIDTH ((uint32_t)0x00000007) +/// PLATNDLINDEX field mask +#define AGC_PLATNDLINDEX_MASK ((uint32_t)0x00000700) +/// PLATNDLINDEX field LSB position +#define AGC_PLATNDLINDEX_LSB 8 +/// PLATNDLINDEX field width +#define AGC_PLATNDLINDEX_WIDTH ((uint32_t)0x00000003) +/// PLATDPQDB field mask +#define AGC_PLATDPQDB_MASK ((uint32_t)0x0000001F) +/// PLATDPQDB field LSB position +#define AGC_PLATDPQDB_LSB 0 +/// PLATDPQDB field width +#define AGC_PLATDPQDB_WIDTH ((uint32_t)0x00000005) + +/// ADCPOWDISNDL field reset value +#define AGC_ADCPOWDISNDL_RST 0x8 +/// ADCPOWDISTHRDBV field reset value +#define AGC_ADCPOWDISTHRDBV_RST 0x5D +/// PLATNDLINDEX field reset value +#define AGC_PLATNDLINDEX_RST 0x3 +/// PLATDPQDB field reset value +#define AGC_PLATDPQDB_RST 0x8 + +/** + * @brief Constructs a value for the RWNXAGCSTABDIS register given values for its fields + * and writes the value to the register. + * + * @param[in] adcpowdisndl - The value to use for the ADCPOWDISNDL field. + * @param[in] adcpowdisthrdbv - The value to use for the ADCPOWDISTHRDBV field. + * @param[in] platndlindex - The value to use for the PLATNDLINDEX field. + * @param[in] platdpqdb - The value to use for the PLATDPQDB field. + */ +__INLINE void agc_rwnxagcstabdis_pack(uint8_t adcpowdisndl, uint8_t adcpowdisthrdbv, uint8_t platndlindex, uint8_t platdpqdb) +{ + ASSERT_ERR((((uint32_t)adcpowdisndl << 24) & ~((uint32_t)0x0F000000)) == 0); + ASSERT_ERR((((uint32_t)adcpowdisthrdbv << 16) & ~((uint32_t)0x007F0000)) == 0); + ASSERT_ERR((((uint32_t)platndlindex << 8) & ~((uint32_t)0x00000700)) == 0); + ASSERT_ERR((((uint32_t)platdpqdb << 0) & ~((uint32_t)0x0000001F)) == 0); + REG_PL_WR(AGC_RWNXAGCSTABDIS_ADDR, ((uint32_t)adcpowdisndl << 24) | ((uint32_t)adcpowdisthrdbv << 16) | ((uint32_t)platndlindex << 8) | ((uint32_t)platdpqdb << 0)); +} + +/** + * @brief Unpacks RWNXAGCSTABDIS's fields from current value of the RWNXAGCSTABDIS register. + * + * Reads the RWNXAGCSTABDIS register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] adcpowdisndl - Will be populated with the current value of this field from the register. + * @param[out] adcpowdisthrdbv - Will be populated with the current value of this field from the register. + * @param[out] platndlindex - Will be populated with the current value of this field from the register. + * @param[out] platdpqdb - Will be populated with the current value of this field from the register. + */ +__INLINE void agc_rwnxagcstabdis_unpack(uint8_t *adcpowdisndl, uint8_t *adcpowdisthrdbv, uint8_t *platndlindex, uint8_t *platdpqdb) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCSTABDIS_ADDR); + + *adcpowdisndl = (localVal & ((uint32_t)0x0F000000)) >> 24; + *adcpowdisthrdbv = (localVal & ((uint32_t)0x007F0000)) >> 16; + *platndlindex = (localVal & ((uint32_t)0x00000700)) >> 8; + *platdpqdb = (localVal & ((uint32_t)0x0000001F)) >> 0; +} + +/** + * @brief Returns the current value of the ADCPOWDISNDL field in the RWNXAGCSTABDIS register. + * + * The RWNXAGCSTABDIS register will be read and the ADCPOWDISNDL field's value will be returned. + * + * @return The current value of the ADCPOWDISNDL field in the RWNXAGCSTABDIS register. + */ +__INLINE uint8_t agc_adcpowdisndl_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCSTABDIS_ADDR); + return ((localVal & ((uint32_t)0x0F000000)) >> 24); +} + +/** + * @brief Sets the ADCPOWDISNDL field of the RWNXAGCSTABDIS register. + * + * The RWNXAGCSTABDIS register will be read, modified to contain the new field value, and written. + * + * @param[in] adcpowdisndl - The value to set the field to. + */ +__INLINE void agc_adcpowdisndl_setf(uint8_t adcpowdisndl) +{ + ASSERT_ERR((((uint32_t)adcpowdisndl << 24) & ~((uint32_t)0x0F000000)) == 0); + REG_PL_WR(AGC_RWNXAGCSTABDIS_ADDR, (REG_PL_RD(AGC_RWNXAGCSTABDIS_ADDR) & ~((uint32_t)0x0F000000)) | ((uint32_t)adcpowdisndl << 24)); +} + +/** + * @brief Returns the current value of the ADCPOWDISTHRDBV field in the RWNXAGCSTABDIS register. + * + * The RWNXAGCSTABDIS register will be read and the ADCPOWDISTHRDBV field's value will be returned. + * + * @return The current value of the ADCPOWDISTHRDBV field in the RWNXAGCSTABDIS register. + */ +__INLINE uint8_t agc_adcpowdisthrdbv_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCSTABDIS_ADDR); + return ((localVal & ((uint32_t)0x007F0000)) >> 16); +} + +/** + * @brief Sets the ADCPOWDISTHRDBV field of the RWNXAGCSTABDIS register. + * + * The RWNXAGCSTABDIS register will be read, modified to contain the new field value, and written. + * + * @param[in] adcpowdisthrdbv - The value to set the field to. + */ +__INLINE void agc_adcpowdisthrdbv_setf(uint8_t adcpowdisthrdbv) +{ + ASSERT_ERR((((uint32_t)adcpowdisthrdbv << 16) & ~((uint32_t)0x007F0000)) == 0); + REG_PL_WR(AGC_RWNXAGCSTABDIS_ADDR, (REG_PL_RD(AGC_RWNXAGCSTABDIS_ADDR) & ~((uint32_t)0x007F0000)) | ((uint32_t)adcpowdisthrdbv << 16)); +} + +/** + * @brief Returns the current value of the PLATNDLINDEX field in the RWNXAGCSTABDIS register. + * + * The RWNXAGCSTABDIS register will be read and the PLATNDLINDEX field's value will be returned. + * + * @return The current value of the PLATNDLINDEX field in the RWNXAGCSTABDIS register. + */ +__INLINE uint8_t agc_platndlindex_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCSTABDIS_ADDR); + return ((localVal & ((uint32_t)0x00000700)) >> 8); +} + +/** + * @brief Sets the PLATNDLINDEX field of the RWNXAGCSTABDIS register. + * + * The RWNXAGCSTABDIS register will be read, modified to contain the new field value, and written. + * + * @param[in] platndlindex - The value to set the field to. + */ +__INLINE void agc_platndlindex_setf(uint8_t platndlindex) +{ + ASSERT_ERR((((uint32_t)platndlindex << 8) & ~((uint32_t)0x00000700)) == 0); + REG_PL_WR(AGC_RWNXAGCSTABDIS_ADDR, (REG_PL_RD(AGC_RWNXAGCSTABDIS_ADDR) & ~((uint32_t)0x00000700)) | ((uint32_t)platndlindex << 8)); +} + +/** + * @brief Returns the current value of the PLATDPQDB field in the RWNXAGCSTABDIS register. + * + * The RWNXAGCSTABDIS register will be read and the PLATDPQDB field's value will be returned. + * + * @return The current value of the PLATDPQDB field in the RWNXAGCSTABDIS register. + */ +__INLINE uint8_t agc_platdpqdb_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCSTABDIS_ADDR); + return ((localVal & ((uint32_t)0x0000001F)) >> 0); +} + +/** + * @brief Sets the PLATDPQDB field of the RWNXAGCSTABDIS register. + * + * The RWNXAGCSTABDIS register will be read, modified to contain the new field value, and written. + * + * @param[in] platdpqdb - The value to set the field to. + */ +__INLINE void agc_platdpqdb_setf(uint8_t platdpqdb) +{ + ASSERT_ERR((((uint32_t)platdpqdb << 0) & ~((uint32_t)0x0000001F)) == 0); + REG_PL_WR(AGC_RWNXAGCSTABDIS_ADDR, (REG_PL_RD(AGC_RWNXAGCSTABDIS_ADDR) & ~((uint32_t)0x0000001F)) | ((uint32_t)platdpqdb << 0)); +} + +/// @} + +/** + * @name RWNXAGCDCCOMP0 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  29:28          DCRADARTYPE   0x3
+ *  25:24          DCMDM20TYPE   0x3
+ *  21:20          DCAGC20TYPE   0x1
+ *  17:16            DCADCTYPE   0x1
+ *  14:08    DCADCHOLDTIME50NS   0x0
+ *  06:00    DCADCZEROTIME50NS   0x0
+ * 
+ * + * @{ + */ + +/// Address of the RWNXAGCDCCOMP0 register +#define AGC_RWNXAGCDCCOMP0_ADDR 0x01002044 +/// Offset of the RWNXAGCDCCOMP0 register from the base address +#define AGC_RWNXAGCDCCOMP0_OFFSET 0x00002044 +/// Index of the RWNXAGCDCCOMP0 register +#define AGC_RWNXAGCDCCOMP0_INDEX 0x00000811 +/// Reset value of the RWNXAGCDCCOMP0 register +#define AGC_RWNXAGCDCCOMP0_RESET 0x33110000 + +/** + * @brief Returns the current value of the RWNXAGCDCCOMP0 register. + * The RWNXAGCDCCOMP0 register will be read and its value returned. + * @return The current value of the RWNXAGCDCCOMP0 register. + */ +__INLINE uint32_t agc_rwnxagcdccomp0_get(void) +{ + return REG_PL_RD(AGC_RWNXAGCDCCOMP0_ADDR); +} + +/** + * @brief Sets the RWNXAGCDCCOMP0 register to a value. + * The RWNXAGCDCCOMP0 register will be written. + * @param value - The value to write. + */ +__INLINE void agc_rwnxagcdccomp0_set(uint32_t value) +{ + REG_PL_WR(AGC_RWNXAGCDCCOMP0_ADDR, value); +} + +// field definitions +/// DCRADARTYPE field mask +#define AGC_DCRADARTYPE_MASK ((uint32_t)0x30000000) +/// DCRADARTYPE field LSB position +#define AGC_DCRADARTYPE_LSB 28 +/// DCRADARTYPE field width +#define AGC_DCRADARTYPE_WIDTH ((uint32_t)0x00000002) +/// DCMDM20TYPE field mask +#define AGC_DCMDM20TYPE_MASK ((uint32_t)0x03000000) +/// DCMDM20TYPE field LSB position +#define AGC_DCMDM20TYPE_LSB 24 +/// DCMDM20TYPE field width +#define AGC_DCMDM20TYPE_WIDTH ((uint32_t)0x00000002) +/// DCAGC20TYPE field mask +#define AGC_DCAGC20TYPE_MASK ((uint32_t)0x00300000) +/// DCAGC20TYPE field LSB position +#define AGC_DCAGC20TYPE_LSB 20 +/// DCAGC20TYPE field width +#define AGC_DCAGC20TYPE_WIDTH ((uint32_t)0x00000002) +/// DCADCTYPE field mask +#define AGC_DCADCTYPE_MASK ((uint32_t)0x00030000) +/// DCADCTYPE field LSB position +#define AGC_DCADCTYPE_LSB 16 +/// DCADCTYPE field width +#define AGC_DCADCTYPE_WIDTH ((uint32_t)0x00000002) +/// DCADCHOLDTIME50NS field mask +#define AGC_DCADCHOLDTIME50NS_MASK ((uint32_t)0x00007F00) +/// DCADCHOLDTIME50NS field LSB position +#define AGC_DCADCHOLDTIME50NS_LSB 8 +/// DCADCHOLDTIME50NS field width +#define AGC_DCADCHOLDTIME50NS_WIDTH ((uint32_t)0x00000007) +/// DCADCZEROTIME50NS field mask +#define AGC_DCADCZEROTIME50NS_MASK ((uint32_t)0x0000007F) +/// DCADCZEROTIME50NS field LSB position +#define AGC_DCADCZEROTIME50NS_LSB 0 +/// DCADCZEROTIME50NS field width +#define AGC_DCADCZEROTIME50NS_WIDTH ((uint32_t)0x00000007) + +/// DCRADARTYPE field reset value +#define AGC_DCRADARTYPE_RST 0x3 +/// DCMDM20TYPE field reset value +#define AGC_DCMDM20TYPE_RST 0x3 +/// DCAGC20TYPE field reset value +#define AGC_DCAGC20TYPE_RST 0x1 +/// DCADCTYPE field reset value +#define AGC_DCADCTYPE_RST 0x1 +/// DCADCHOLDTIME50NS field reset value +#define AGC_DCADCHOLDTIME50NS_RST 0x0 +/// DCADCZEROTIME50NS field reset value +#define AGC_DCADCZEROTIME50NS_RST 0x0 + +/** + * @brief Constructs a value for the RWNXAGCDCCOMP0 register given values for its fields + * and writes the value to the register. + * + * @param[in] dcradartype - The value to use for the DCRADARTYPE field. + * @param[in] dcmdm20type - The value to use for the DCMDM20TYPE field. + * @param[in] dcagc20type - The value to use for the DCAGC20TYPE field. + * @param[in] dcadctype - The value to use for the DCADCTYPE field. + * @param[in] dcadcholdtime50ns - The value to use for the DCADCHOLDTIME50NS field. + * @param[in] dcadczerotime50ns - The value to use for the DCADCZEROTIME50NS field. + */ +__INLINE void agc_rwnxagcdccomp0_pack(uint8_t dcradartype, uint8_t dcmdm20type, uint8_t dcagc20type, uint8_t dcadctype, uint8_t dcadcholdtime50ns, uint8_t dcadczerotime50ns) +{ + ASSERT_ERR((((uint32_t)dcradartype << 28) & ~((uint32_t)0x30000000)) == 0); + ASSERT_ERR((((uint32_t)dcmdm20type << 24) & ~((uint32_t)0x03000000)) == 0); + ASSERT_ERR((((uint32_t)dcagc20type << 20) & ~((uint32_t)0x00300000)) == 0); + ASSERT_ERR((((uint32_t)dcadctype << 16) & ~((uint32_t)0x00030000)) == 0); + ASSERT_ERR((((uint32_t)dcadcholdtime50ns << 8) & ~((uint32_t)0x00007F00)) == 0); + ASSERT_ERR((((uint32_t)dcadczerotime50ns << 0) & ~((uint32_t)0x0000007F)) == 0); + REG_PL_WR(AGC_RWNXAGCDCCOMP0_ADDR, ((uint32_t)dcradartype << 28) | ((uint32_t)dcmdm20type << 24) | ((uint32_t)dcagc20type << 20) | ((uint32_t)dcadctype << 16) | ((uint32_t)dcadcholdtime50ns << 8) | ((uint32_t)dcadczerotime50ns << 0)); +} + +/** + * @brief Unpacks RWNXAGCDCCOMP0's fields from current value of the RWNXAGCDCCOMP0 register. + * + * Reads the RWNXAGCDCCOMP0 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] dcradartype - Will be populated with the current value of this field from the register. + * @param[out] dcmdm20type - Will be populated with the current value of this field from the register. + * @param[out] dcagc20type - Will be populated with the current value of this field from the register. + * @param[out] dcadctype - Will be populated with the current value of this field from the register. + * @param[out] dcadcholdtime50ns - Will be populated with the current value of this field from the register. + * @param[out] dcadczerotime50ns - Will be populated with the current value of this field from the register. + */ +__INLINE void agc_rwnxagcdccomp0_unpack(uint8_t *dcradartype, uint8_t *dcmdm20type, uint8_t *dcagc20type, uint8_t *dcadctype, uint8_t *dcadcholdtime50ns, uint8_t *dcadczerotime50ns) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCDCCOMP0_ADDR); + + *dcradartype = (localVal & ((uint32_t)0x30000000)) >> 28; + *dcmdm20type = (localVal & ((uint32_t)0x03000000)) >> 24; + *dcagc20type = (localVal & ((uint32_t)0x00300000)) >> 20; + *dcadctype = (localVal & ((uint32_t)0x00030000)) >> 16; + *dcadcholdtime50ns = (localVal & ((uint32_t)0x00007F00)) >> 8; + *dcadczerotime50ns = (localVal & ((uint32_t)0x0000007F)) >> 0; +} + +/** + * @brief Returns the current value of the DCRADARTYPE field in the RWNXAGCDCCOMP0 register. + * + * The RWNXAGCDCCOMP0 register will be read and the DCRADARTYPE field's value will be returned. + * + * @return The current value of the DCRADARTYPE field in the RWNXAGCDCCOMP0 register. + */ +__INLINE uint8_t agc_dcradartype_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCDCCOMP0_ADDR); + return ((localVal & ((uint32_t)0x30000000)) >> 28); +} + +/** + * @brief Sets the DCRADARTYPE field of the RWNXAGCDCCOMP0 register. + * + * The RWNXAGCDCCOMP0 register will be read, modified to contain the new field value, and written. + * + * @param[in] dcradartype - The value to set the field to. + */ +__INLINE void agc_dcradartype_setf(uint8_t dcradartype) +{ + ASSERT_ERR((((uint32_t)dcradartype << 28) & ~((uint32_t)0x30000000)) == 0); + REG_PL_WR(AGC_RWNXAGCDCCOMP0_ADDR, (REG_PL_RD(AGC_RWNXAGCDCCOMP0_ADDR) & ~((uint32_t)0x30000000)) | ((uint32_t)dcradartype << 28)); +} + +/** + * @brief Returns the current value of the DCMDM20TYPE field in the RWNXAGCDCCOMP0 register. + * + * The RWNXAGCDCCOMP0 register will be read and the DCMDM20TYPE field's value will be returned. + * + * @return The current value of the DCMDM20TYPE field in the RWNXAGCDCCOMP0 register. + */ +__INLINE uint8_t agc_dcmdm20type_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCDCCOMP0_ADDR); + return ((localVal & ((uint32_t)0x03000000)) >> 24); +} + +/** + * @brief Sets the DCMDM20TYPE field of the RWNXAGCDCCOMP0 register. + * + * The RWNXAGCDCCOMP0 register will be read, modified to contain the new field value, and written. + * + * @param[in] dcmdm20type - The value to set the field to. + */ +__INLINE void agc_dcmdm20type_setf(uint8_t dcmdm20type) +{ + ASSERT_ERR((((uint32_t)dcmdm20type << 24) & ~((uint32_t)0x03000000)) == 0); + REG_PL_WR(AGC_RWNXAGCDCCOMP0_ADDR, (REG_PL_RD(AGC_RWNXAGCDCCOMP0_ADDR) & ~((uint32_t)0x03000000)) | ((uint32_t)dcmdm20type << 24)); +} + +/** + * @brief Returns the current value of the DCAGC20TYPE field in the RWNXAGCDCCOMP0 register. + * + * The RWNXAGCDCCOMP0 register will be read and the DCAGC20TYPE field's value will be returned. + * + * @return The current value of the DCAGC20TYPE field in the RWNXAGCDCCOMP0 register. + */ +__INLINE uint8_t agc_dcagc20type_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCDCCOMP0_ADDR); + return ((localVal & ((uint32_t)0x00300000)) >> 20); +} + +/** + * @brief Sets the DCAGC20TYPE field of the RWNXAGCDCCOMP0 register. + * + * The RWNXAGCDCCOMP0 register will be read, modified to contain the new field value, and written. + * + * @param[in] dcagc20type - The value to set the field to. + */ +__INLINE void agc_dcagc20type_setf(uint8_t dcagc20type) +{ + ASSERT_ERR((((uint32_t)dcagc20type << 20) & ~((uint32_t)0x00300000)) == 0); + REG_PL_WR(AGC_RWNXAGCDCCOMP0_ADDR, (REG_PL_RD(AGC_RWNXAGCDCCOMP0_ADDR) & ~((uint32_t)0x00300000)) | ((uint32_t)dcagc20type << 20)); +} + +/** + * @brief Returns the current value of the DCADCTYPE field in the RWNXAGCDCCOMP0 register. + * + * The RWNXAGCDCCOMP0 register will be read and the DCADCTYPE field's value will be returned. + * + * @return The current value of the DCADCTYPE field in the RWNXAGCDCCOMP0 register. + */ +__INLINE uint8_t agc_dcadctype_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCDCCOMP0_ADDR); + return ((localVal & ((uint32_t)0x00030000)) >> 16); +} + +/** + * @brief Sets the DCADCTYPE field of the RWNXAGCDCCOMP0 register. + * + * The RWNXAGCDCCOMP0 register will be read, modified to contain the new field value, and written. + * + * @param[in] dcadctype - The value to set the field to. + */ +__INLINE void agc_dcadctype_setf(uint8_t dcadctype) +{ + ASSERT_ERR((((uint32_t)dcadctype << 16) & ~((uint32_t)0x00030000)) == 0); + REG_PL_WR(AGC_RWNXAGCDCCOMP0_ADDR, (REG_PL_RD(AGC_RWNXAGCDCCOMP0_ADDR) & ~((uint32_t)0x00030000)) | ((uint32_t)dcadctype << 16)); +} + +/** + * @brief Returns the current value of the DCADCHOLDTIME50NS field in the RWNXAGCDCCOMP0 register. + * + * The RWNXAGCDCCOMP0 register will be read and the DCADCHOLDTIME50NS field's value will be returned. + * + * @return The current value of the DCADCHOLDTIME50NS field in the RWNXAGCDCCOMP0 register. + */ +__INLINE uint8_t agc_dcadcholdtime50ns_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCDCCOMP0_ADDR); + return ((localVal & ((uint32_t)0x00007F00)) >> 8); +} + +/** + * @brief Sets the DCADCHOLDTIME50NS field of the RWNXAGCDCCOMP0 register. + * + * The RWNXAGCDCCOMP0 register will be read, modified to contain the new field value, and written. + * + * @param[in] dcadcholdtime50ns - The value to set the field to. + */ +__INLINE void agc_dcadcholdtime50ns_setf(uint8_t dcadcholdtime50ns) +{ + ASSERT_ERR((((uint32_t)dcadcholdtime50ns << 8) & ~((uint32_t)0x00007F00)) == 0); + REG_PL_WR(AGC_RWNXAGCDCCOMP0_ADDR, (REG_PL_RD(AGC_RWNXAGCDCCOMP0_ADDR) & ~((uint32_t)0x00007F00)) | ((uint32_t)dcadcholdtime50ns << 8)); +} + +/** + * @brief Returns the current value of the DCADCZEROTIME50NS field in the RWNXAGCDCCOMP0 register. + * + * The RWNXAGCDCCOMP0 register will be read and the DCADCZEROTIME50NS field's value will be returned. + * + * @return The current value of the DCADCZEROTIME50NS field in the RWNXAGCDCCOMP0 register. + */ +__INLINE uint8_t agc_dcadczerotime50ns_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCDCCOMP0_ADDR); + return ((localVal & ((uint32_t)0x0000007F)) >> 0); +} + +/** + * @brief Sets the DCADCZEROTIME50NS field of the RWNXAGCDCCOMP0 register. + * + * The RWNXAGCDCCOMP0 register will be read, modified to contain the new field value, and written. + * + * @param[in] dcadczerotime50ns - The value to set the field to. + */ +__INLINE void agc_dcadczerotime50ns_setf(uint8_t dcadczerotime50ns) +{ + ASSERT_ERR((((uint32_t)dcadczerotime50ns << 0) & ~((uint32_t)0x0000007F)) == 0); + REG_PL_WR(AGC_RWNXAGCDCCOMP0_ADDR, (REG_PL_RD(AGC_RWNXAGCDCCOMP0_ADDR) & ~((uint32_t)0x0000007F)) | ((uint32_t)dcadczerotime50ns << 0)); +} + +/// @} + +/** + * @name RWNXAGCDCCOMP1 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  30:24   DCMDM20HOLDTIME50NS   0x14
+ *  22:16   DCMDM20ZEROTIME50NS   0x0
+ *  14:08   DCAGC20HOLDTIME50NS   0x0
+ *  06:00   DCAGC20ZEROTIME50NS   0x0
+ * 
+ * + * @{ + */ + +/// Address of the RWNXAGCDCCOMP1 register +#define AGC_RWNXAGCDCCOMP1_ADDR 0x01002048 +/// Offset of the RWNXAGCDCCOMP1 register from the base address +#define AGC_RWNXAGCDCCOMP1_OFFSET 0x00002048 +/// Index of the RWNXAGCDCCOMP1 register +#define AGC_RWNXAGCDCCOMP1_INDEX 0x00000812 +/// Reset value of the RWNXAGCDCCOMP1 register +#define AGC_RWNXAGCDCCOMP1_RESET 0x14000000 + +/** + * @brief Returns the current value of the RWNXAGCDCCOMP1 register. + * The RWNXAGCDCCOMP1 register will be read and its value returned. + * @return The current value of the RWNXAGCDCCOMP1 register. + */ +__INLINE uint32_t agc_rwnxagcdccomp1_get(void) +{ + return REG_PL_RD(AGC_RWNXAGCDCCOMP1_ADDR); +} + +/** + * @brief Sets the RWNXAGCDCCOMP1 register to a value. + * The RWNXAGCDCCOMP1 register will be written. + * @param value - The value to write. + */ +__INLINE void agc_rwnxagcdccomp1_set(uint32_t value) +{ + REG_PL_WR(AGC_RWNXAGCDCCOMP1_ADDR, value); +} + +// field definitions +/// DCMDM20HOLDTIME50NS field mask +#define AGC_DCMDM20HOLDTIME50NS_MASK ((uint32_t)0x7F000000) +/// DCMDM20HOLDTIME50NS field LSB position +#define AGC_DCMDM20HOLDTIME50NS_LSB 24 +/// DCMDM20HOLDTIME50NS field width +#define AGC_DCMDM20HOLDTIME50NS_WIDTH ((uint32_t)0x00000007) +/// DCMDM20ZEROTIME50NS field mask +#define AGC_DCMDM20ZEROTIME50NS_MASK ((uint32_t)0x007F0000) +/// DCMDM20ZEROTIME50NS field LSB position +#define AGC_DCMDM20ZEROTIME50NS_LSB 16 +/// DCMDM20ZEROTIME50NS field width +#define AGC_DCMDM20ZEROTIME50NS_WIDTH ((uint32_t)0x00000007) +/// DCAGC20HOLDTIME50NS field mask +#define AGC_DCAGC20HOLDTIME50NS_MASK ((uint32_t)0x00007F00) +/// DCAGC20HOLDTIME50NS field LSB position +#define AGC_DCAGC20HOLDTIME50NS_LSB 8 +/// DCAGC20HOLDTIME50NS field width +#define AGC_DCAGC20HOLDTIME50NS_WIDTH ((uint32_t)0x00000007) +/// DCAGC20ZEROTIME50NS field mask +#define AGC_DCAGC20ZEROTIME50NS_MASK ((uint32_t)0x0000007F) +/// DCAGC20ZEROTIME50NS field LSB position +#define AGC_DCAGC20ZEROTIME50NS_LSB 0 +/// DCAGC20ZEROTIME50NS field width +#define AGC_DCAGC20ZEROTIME50NS_WIDTH ((uint32_t)0x00000007) + +/// DCMDM20HOLDTIME50NS field reset value +#define AGC_DCMDM20HOLDTIME50NS_RST 0x14 +/// DCMDM20ZEROTIME50NS field reset value +#define AGC_DCMDM20ZEROTIME50NS_RST 0x0 +/// DCAGC20HOLDTIME50NS field reset value +#define AGC_DCAGC20HOLDTIME50NS_RST 0x0 +/// DCAGC20ZEROTIME50NS field reset value +#define AGC_DCAGC20ZEROTIME50NS_RST 0x0 + +/** + * @brief Constructs a value for the RWNXAGCDCCOMP1 register given values for its fields + * and writes the value to the register. + * + * @param[in] dcmdm20holdtime50ns - The value to use for the DCMDM20HOLDTIME50NS field. + * @param[in] dcmdm20zerotime50ns - The value to use for the DCMDM20ZEROTIME50NS field. + * @param[in] dcagc20holdtime50ns - The value to use for the DCAGC20HOLDTIME50NS field. + * @param[in] dcagc20zerotime50ns - The value to use for the DCAGC20ZEROTIME50NS field. + */ +__INLINE void agc_rwnxagcdccomp1_pack(uint8_t dcmdm20holdtime50ns, uint8_t dcmdm20zerotime50ns, uint8_t dcagc20holdtime50ns, uint8_t dcagc20zerotime50ns) +{ + ASSERT_ERR((((uint32_t)dcmdm20holdtime50ns << 24) & ~((uint32_t)0x7F000000)) == 0); + ASSERT_ERR((((uint32_t)dcmdm20zerotime50ns << 16) & ~((uint32_t)0x007F0000)) == 0); + ASSERT_ERR((((uint32_t)dcagc20holdtime50ns << 8) & ~((uint32_t)0x00007F00)) == 0); + ASSERT_ERR((((uint32_t)dcagc20zerotime50ns << 0) & ~((uint32_t)0x0000007F)) == 0); + REG_PL_WR(AGC_RWNXAGCDCCOMP1_ADDR, ((uint32_t)dcmdm20holdtime50ns << 24) | ((uint32_t)dcmdm20zerotime50ns << 16) | ((uint32_t)dcagc20holdtime50ns << 8) | ((uint32_t)dcagc20zerotime50ns << 0)); +} + +/** + * @brief Unpacks RWNXAGCDCCOMP1's fields from current value of the RWNXAGCDCCOMP1 register. + * + * Reads the RWNXAGCDCCOMP1 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] dcmdm20holdtime50ns - Will be populated with the current value of this field from the register. + * @param[out] dcmdm20zerotime50ns - Will be populated with the current value of this field from the register. + * @param[out] dcagc20holdtime50ns - Will be populated with the current value of this field from the register. + * @param[out] dcagc20zerotime50ns - Will be populated with the current value of this field from the register. + */ +__INLINE void agc_rwnxagcdccomp1_unpack(uint8_t *dcmdm20holdtime50ns, uint8_t *dcmdm20zerotime50ns, uint8_t *dcagc20holdtime50ns, uint8_t *dcagc20zerotime50ns) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCDCCOMP1_ADDR); + + *dcmdm20holdtime50ns = (localVal & ((uint32_t)0x7F000000)) >> 24; + *dcmdm20zerotime50ns = (localVal & ((uint32_t)0x007F0000)) >> 16; + *dcagc20holdtime50ns = (localVal & ((uint32_t)0x00007F00)) >> 8; + *dcagc20zerotime50ns = (localVal & ((uint32_t)0x0000007F)) >> 0; +} + +/** + * @brief Returns the current value of the DCMDM20HOLDTIME50NS field in the RWNXAGCDCCOMP1 register. + * + * The RWNXAGCDCCOMP1 register will be read and the DCMDM20HOLDTIME50NS field's value will be returned. + * + * @return The current value of the DCMDM20HOLDTIME50NS field in the RWNXAGCDCCOMP1 register. + */ +__INLINE uint8_t agc_dcmdm20holdtime50ns_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCDCCOMP1_ADDR); + return ((localVal & ((uint32_t)0x7F000000)) >> 24); +} + +/** + * @brief Sets the DCMDM20HOLDTIME50NS field of the RWNXAGCDCCOMP1 register. + * + * The RWNXAGCDCCOMP1 register will be read, modified to contain the new field value, and written. + * + * @param[in] dcmdm20holdtime50ns - The value to set the field to. + */ +__INLINE void agc_dcmdm20holdtime50ns_setf(uint8_t dcmdm20holdtime50ns) +{ + ASSERT_ERR((((uint32_t)dcmdm20holdtime50ns << 24) & ~((uint32_t)0x7F000000)) == 0); + REG_PL_WR(AGC_RWNXAGCDCCOMP1_ADDR, (REG_PL_RD(AGC_RWNXAGCDCCOMP1_ADDR) & ~((uint32_t)0x7F000000)) | ((uint32_t)dcmdm20holdtime50ns << 24)); +} + +/** + * @brief Returns the current value of the DCMDM20ZEROTIME50NS field in the RWNXAGCDCCOMP1 register. + * + * The RWNXAGCDCCOMP1 register will be read and the DCMDM20ZEROTIME50NS field's value will be returned. + * + * @return The current value of the DCMDM20ZEROTIME50NS field in the RWNXAGCDCCOMP1 register. + */ +__INLINE uint8_t agc_dcmdm20zerotime50ns_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCDCCOMP1_ADDR); + return ((localVal & ((uint32_t)0x007F0000)) >> 16); +} + +/** + * @brief Sets the DCMDM20ZEROTIME50NS field of the RWNXAGCDCCOMP1 register. + * + * The RWNXAGCDCCOMP1 register will be read, modified to contain the new field value, and written. + * + * @param[in] dcmdm20zerotime50ns - The value to set the field to. + */ +__INLINE void agc_dcmdm20zerotime50ns_setf(uint8_t dcmdm20zerotime50ns) +{ + ASSERT_ERR((((uint32_t)dcmdm20zerotime50ns << 16) & ~((uint32_t)0x007F0000)) == 0); + REG_PL_WR(AGC_RWNXAGCDCCOMP1_ADDR, (REG_PL_RD(AGC_RWNXAGCDCCOMP1_ADDR) & ~((uint32_t)0x007F0000)) | ((uint32_t)dcmdm20zerotime50ns << 16)); +} + +/** + * @brief Returns the current value of the DCAGC20HOLDTIME50NS field in the RWNXAGCDCCOMP1 register. + * + * The RWNXAGCDCCOMP1 register will be read and the DCAGC20HOLDTIME50NS field's value will be returned. + * + * @return The current value of the DCAGC20HOLDTIME50NS field in the RWNXAGCDCCOMP1 register. + */ +__INLINE uint8_t agc_dcagc20holdtime50ns_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCDCCOMP1_ADDR); + return ((localVal & ((uint32_t)0x00007F00)) >> 8); +} + +/** + * @brief Sets the DCAGC20HOLDTIME50NS field of the RWNXAGCDCCOMP1 register. + * + * The RWNXAGCDCCOMP1 register will be read, modified to contain the new field value, and written. + * + * @param[in] dcagc20holdtime50ns - The value to set the field to. + */ +__INLINE void agc_dcagc20holdtime50ns_setf(uint8_t dcagc20holdtime50ns) +{ + ASSERT_ERR((((uint32_t)dcagc20holdtime50ns << 8) & ~((uint32_t)0x00007F00)) == 0); + REG_PL_WR(AGC_RWNXAGCDCCOMP1_ADDR, (REG_PL_RD(AGC_RWNXAGCDCCOMP1_ADDR) & ~((uint32_t)0x00007F00)) | ((uint32_t)dcagc20holdtime50ns << 8)); +} + +/** + * @brief Returns the current value of the DCAGC20ZEROTIME50NS field in the RWNXAGCDCCOMP1 register. + * + * The RWNXAGCDCCOMP1 register will be read and the DCAGC20ZEROTIME50NS field's value will be returned. + * + * @return The current value of the DCAGC20ZEROTIME50NS field in the RWNXAGCDCCOMP1 register. + */ +__INLINE uint8_t agc_dcagc20zerotime50ns_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCDCCOMP1_ADDR); + return ((localVal & ((uint32_t)0x0000007F)) >> 0); +} + +/** + * @brief Sets the DCAGC20ZEROTIME50NS field of the RWNXAGCDCCOMP1 register. + * + * The RWNXAGCDCCOMP1 register will be read, modified to contain the new field value, and written. + * + * @param[in] dcagc20zerotime50ns - The value to set the field to. + */ +__INLINE void agc_dcagc20zerotime50ns_setf(uint8_t dcagc20zerotime50ns) +{ + ASSERT_ERR((((uint32_t)dcagc20zerotime50ns << 0) & ~((uint32_t)0x0000007F)) == 0); + REG_PL_WR(AGC_RWNXAGCDCCOMP1_ADDR, (REG_PL_RD(AGC_RWNXAGCDCCOMP1_ADDR) & ~((uint32_t)0x0000007F)) | ((uint32_t)dcagc20zerotime50ns << 0)); +} + +/// @} + +/** + * @name RWNXAGCDCCOMP2 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  22:16   DCRADARHOLDTIME50NS   0x0
+ *  14:08   DCRADARZEROTIME50NS   0x0
+ *  06:00        DELDCSTABLECC   0x0
+ * 
+ * + * @{ + */ + +/// Address of the RWNXAGCDCCOMP2 register +#define AGC_RWNXAGCDCCOMP2_ADDR 0x0100204C +/// Offset of the RWNXAGCDCCOMP2 register from the base address +#define AGC_RWNXAGCDCCOMP2_OFFSET 0x0000204C +/// Index of the RWNXAGCDCCOMP2 register +#define AGC_RWNXAGCDCCOMP2_INDEX 0x00000813 +/// Reset value of the RWNXAGCDCCOMP2 register +#define AGC_RWNXAGCDCCOMP2_RESET 0x00000000 + +/** + * @brief Returns the current value of the RWNXAGCDCCOMP2 register. + * The RWNXAGCDCCOMP2 register will be read and its value returned. + * @return The current value of the RWNXAGCDCCOMP2 register. + */ +__INLINE uint32_t agc_rwnxagcdccomp2_get(void) +{ + return REG_PL_RD(AGC_RWNXAGCDCCOMP2_ADDR); +} + +/** + * @brief Sets the RWNXAGCDCCOMP2 register to a value. + * The RWNXAGCDCCOMP2 register will be written. + * @param value - The value to write. + */ +__INLINE void agc_rwnxagcdccomp2_set(uint32_t value) +{ + REG_PL_WR(AGC_RWNXAGCDCCOMP2_ADDR, value); +} + +// field definitions +/// DCRADARHOLDTIME50NS field mask +#define AGC_DCRADARHOLDTIME50NS_MASK ((uint32_t)0x007F0000) +/// DCRADARHOLDTIME50NS field LSB position +#define AGC_DCRADARHOLDTIME50NS_LSB 16 +/// DCRADARHOLDTIME50NS field width +#define AGC_DCRADARHOLDTIME50NS_WIDTH ((uint32_t)0x00000007) +/// DCRADARZEROTIME50NS field mask +#define AGC_DCRADARZEROTIME50NS_MASK ((uint32_t)0x00007F00) +/// DCRADARZEROTIME50NS field LSB position +#define AGC_DCRADARZEROTIME50NS_LSB 8 +/// DCRADARZEROTIME50NS field width +#define AGC_DCRADARZEROTIME50NS_WIDTH ((uint32_t)0x00000007) +/// DELDCSTABLECC field mask +#define AGC_DELDCSTABLECC_MASK ((uint32_t)0x0000007F) +/// DELDCSTABLECC field LSB position +#define AGC_DELDCSTABLECC_LSB 0 +/// DELDCSTABLECC field width +#define AGC_DELDCSTABLECC_WIDTH ((uint32_t)0x00000007) + +/// DCRADARHOLDTIME50NS field reset value +#define AGC_DCRADARHOLDTIME50NS_RST 0x0 +/// DCRADARZEROTIME50NS field reset value +#define AGC_DCRADARZEROTIME50NS_RST 0x0 +/// DELDCSTABLECC field reset value +#define AGC_DELDCSTABLECC_RST 0x0 + +/** + * @brief Constructs a value for the RWNXAGCDCCOMP2 register given values for its fields + * and writes the value to the register. + * + * @param[in] dcradarholdtime50ns - The value to use for the DCRADARHOLDTIME50NS field. + * @param[in] dcradarzerotime50ns - The value to use for the DCRADARZEROTIME50NS field. + * @param[in] deldcstablecc - The value to use for the DELDCSTABLECC field. + */ +__INLINE void agc_rwnxagcdccomp2_pack(uint8_t dcradarholdtime50ns, uint8_t dcradarzerotime50ns, uint8_t deldcstablecc) +{ + ASSERT_ERR((((uint32_t)dcradarholdtime50ns << 16) & ~((uint32_t)0x007F0000)) == 0); + ASSERT_ERR((((uint32_t)dcradarzerotime50ns << 8) & ~((uint32_t)0x00007F00)) == 0); + ASSERT_ERR((((uint32_t)deldcstablecc << 0) & ~((uint32_t)0x0000007F)) == 0); + REG_PL_WR(AGC_RWNXAGCDCCOMP2_ADDR, ((uint32_t)dcradarholdtime50ns << 16) | ((uint32_t)dcradarzerotime50ns << 8) | ((uint32_t)deldcstablecc << 0)); +} + +/** + * @brief Unpacks RWNXAGCDCCOMP2's fields from current value of the RWNXAGCDCCOMP2 register. + * + * Reads the RWNXAGCDCCOMP2 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] dcradarholdtime50ns - Will be populated with the current value of this field from the register. + * @param[out] dcradarzerotime50ns - Will be populated with the current value of this field from the register. + * @param[out] deldcstablecc - Will be populated with the current value of this field from the register. + */ +__INLINE void agc_rwnxagcdccomp2_unpack(uint8_t *dcradarholdtime50ns, uint8_t *dcradarzerotime50ns, uint8_t *deldcstablecc) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCDCCOMP2_ADDR); + + *dcradarholdtime50ns = (localVal & ((uint32_t)0x007F0000)) >> 16; + *dcradarzerotime50ns = (localVal & ((uint32_t)0x00007F00)) >> 8; + *deldcstablecc = (localVal & ((uint32_t)0x0000007F)) >> 0; +} + +/** + * @brief Returns the current value of the DCRADARHOLDTIME50NS field in the RWNXAGCDCCOMP2 register. + * + * The RWNXAGCDCCOMP2 register will be read and the DCRADARHOLDTIME50NS field's value will be returned. + * + * @return The current value of the DCRADARHOLDTIME50NS field in the RWNXAGCDCCOMP2 register. + */ +__INLINE uint8_t agc_dcradarholdtime50ns_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCDCCOMP2_ADDR); + return ((localVal & ((uint32_t)0x007F0000)) >> 16); +} + +/** + * @brief Sets the DCRADARHOLDTIME50NS field of the RWNXAGCDCCOMP2 register. + * + * The RWNXAGCDCCOMP2 register will be read, modified to contain the new field value, and written. + * + * @param[in] dcradarholdtime50ns - The value to set the field to. + */ +__INLINE void agc_dcradarholdtime50ns_setf(uint8_t dcradarholdtime50ns) +{ + ASSERT_ERR((((uint32_t)dcradarholdtime50ns << 16) & ~((uint32_t)0x007F0000)) == 0); + REG_PL_WR(AGC_RWNXAGCDCCOMP2_ADDR, (REG_PL_RD(AGC_RWNXAGCDCCOMP2_ADDR) & ~((uint32_t)0x007F0000)) | ((uint32_t)dcradarholdtime50ns << 16)); +} + +/** + * @brief Returns the current value of the DCRADARZEROTIME50NS field in the RWNXAGCDCCOMP2 register. + * + * The RWNXAGCDCCOMP2 register will be read and the DCRADARZEROTIME50NS field's value will be returned. + * + * @return The current value of the DCRADARZEROTIME50NS field in the RWNXAGCDCCOMP2 register. + */ +__INLINE uint8_t agc_dcradarzerotime50ns_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCDCCOMP2_ADDR); + return ((localVal & ((uint32_t)0x00007F00)) >> 8); +} + +/** + * @brief Sets the DCRADARZEROTIME50NS field of the RWNXAGCDCCOMP2 register. + * + * The RWNXAGCDCCOMP2 register will be read, modified to contain the new field value, and written. + * + * @param[in] dcradarzerotime50ns - The value to set the field to. + */ +__INLINE void agc_dcradarzerotime50ns_setf(uint8_t dcradarzerotime50ns) +{ + ASSERT_ERR((((uint32_t)dcradarzerotime50ns << 8) & ~((uint32_t)0x00007F00)) == 0); + REG_PL_WR(AGC_RWNXAGCDCCOMP2_ADDR, (REG_PL_RD(AGC_RWNXAGCDCCOMP2_ADDR) & ~((uint32_t)0x00007F00)) | ((uint32_t)dcradarzerotime50ns << 8)); +} + +/** + * @brief Returns the current value of the DELDCSTABLECC field in the RWNXAGCDCCOMP2 register. + * + * The RWNXAGCDCCOMP2 register will be read and the DELDCSTABLECC field's value will be returned. + * + * @return The current value of the DELDCSTABLECC field in the RWNXAGCDCCOMP2 register. + */ +__INLINE uint8_t agc_deldcstablecc_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCDCCOMP2_ADDR); + return ((localVal & ((uint32_t)0x0000007F)) >> 0); +} + +/** + * @brief Sets the DELDCSTABLECC field of the RWNXAGCDCCOMP2 register. + * + * The RWNXAGCDCCOMP2 register will be read, modified to contain the new field value, and written. + * + * @param[in] deldcstablecc - The value to set the field to. + */ +__INLINE void agc_deldcstablecc_setf(uint8_t deldcstablecc) +{ + ASSERT_ERR((((uint32_t)deldcstablecc << 0) & ~((uint32_t)0x0000007F)) == 0); + REG_PL_WR(AGC_RWNXAGCDCCOMP2_ADDR, (REG_PL_RD(AGC_RWNXAGCDCCOMP2_ADDR) & ~((uint32_t)0x0000007F)) | ((uint32_t)deldcstablecc << 0)); +} + +/// @} + +/** + * @name RWNXAGCEVTSAT register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:26              EVT0OP3   0x1
+ *  25:20              EVT0OP2   0x10
+ *  19:14              EVT0OP1   0x11
+ *     13         EVT0PATHCOMB   0
+ *  12:11           EVT0OPCOMB   0x1
+ *  10:00           EVT0TGTADD   0x4
+ * 
+ * + * @{ + */ + +/// Address of the RWNXAGCEVTSAT register +#define AGC_RWNXAGCEVTSAT_ADDR 0x01002050 +/// Offset of the RWNXAGCEVTSAT register from the base address +#define AGC_RWNXAGCEVTSAT_OFFSET 0x00002050 +/// Index of the RWNXAGCEVTSAT register +#define AGC_RWNXAGCEVTSAT_INDEX 0x00000814 +/// Reset value of the RWNXAGCEVTSAT register +#define AGC_RWNXAGCEVTSAT_RESET 0x05044804 + +/** + * @brief Returns the current value of the RWNXAGCEVTSAT register. + * The RWNXAGCEVTSAT register will be read and its value returned. + * @return The current value of the RWNXAGCEVTSAT register. + */ +__INLINE uint32_t agc_rwnxagcevtsat_get(void) +{ + return REG_PL_RD(AGC_RWNXAGCEVTSAT_ADDR); +} + +/** + * @brief Sets the RWNXAGCEVTSAT register to a value. + * The RWNXAGCEVTSAT register will be written. + * @param value - The value to write. + */ +__INLINE void agc_rwnxagcevtsat_set(uint32_t value) +{ + REG_PL_WR(AGC_RWNXAGCEVTSAT_ADDR, value); +} + +// field definitions +/// EVT0OP3 field mask +#define AGC_EVT0OP3_MASK ((uint32_t)0xFC000000) +/// EVT0OP3 field LSB position +#define AGC_EVT0OP3_LSB 26 +/// EVT0OP3 field width +#define AGC_EVT0OP3_WIDTH ((uint32_t)0x00000006) +/// EVT0OP2 field mask +#define AGC_EVT0OP2_MASK ((uint32_t)0x03F00000) +/// EVT0OP2 field LSB position +#define AGC_EVT0OP2_LSB 20 +/// EVT0OP2 field width +#define AGC_EVT0OP2_WIDTH ((uint32_t)0x00000006) +/// EVT0OP1 field mask +#define AGC_EVT0OP1_MASK ((uint32_t)0x000FC000) +/// EVT0OP1 field LSB position +#define AGC_EVT0OP1_LSB 14 +/// EVT0OP1 field width +#define AGC_EVT0OP1_WIDTH ((uint32_t)0x00000006) +/// EVT0PATHCOMB field bit +#define AGC_EVT0PATHCOMB_BIT ((uint32_t)0x00002000) +/// EVT0PATHCOMB field position +#define AGC_EVT0PATHCOMB_POS 13 +/// EVT0OPCOMB field mask +#define AGC_EVT0OPCOMB_MASK ((uint32_t)0x00001800) +/// EVT0OPCOMB field LSB position +#define AGC_EVT0OPCOMB_LSB 11 +/// EVT0OPCOMB field width +#define AGC_EVT0OPCOMB_WIDTH ((uint32_t)0x00000002) +/// EVT0TGTADD field mask +#define AGC_EVT0TGTADD_MASK ((uint32_t)0x000007FF) +/// EVT0TGTADD field LSB position +#define AGC_EVT0TGTADD_LSB 0 +/// EVT0TGTADD field width +#define AGC_EVT0TGTADD_WIDTH ((uint32_t)0x0000000B) + +/// EVT0OP3 field reset value +#define AGC_EVT0OP3_RST 0x1 +/// EVT0OP2 field reset value +#define AGC_EVT0OP2_RST 0x10 +/// EVT0OP1 field reset value +#define AGC_EVT0OP1_RST 0x11 +/// EVT0PATHCOMB field reset value +#define AGC_EVT0PATHCOMB_RST 0x0 +/// EVT0OPCOMB field reset value +#define AGC_EVT0OPCOMB_RST 0x1 +/// EVT0TGTADD field reset value +#define AGC_EVT0TGTADD_RST 0x4 + +/** + * @brief Constructs a value for the RWNXAGCEVTSAT register given values for its fields + * and writes the value to the register. + * + * @param[in] evt0op3 - The value to use for the EVT0OP3 field. + * @param[in] evt0op2 - The value to use for the EVT0OP2 field. + * @param[in] evt0op1 - The value to use for the EVT0OP1 field. + * @param[in] evt0pathcomb - The value to use for the EVT0PATHCOMB field. + * @param[in] evt0opcomb - The value to use for the EVT0OPCOMB field. + * @param[in] evt0tgtadd - The value to use for the EVT0TGTADD field. + */ +__INLINE void agc_rwnxagcevtsat_pack(uint8_t evt0op3, uint8_t evt0op2, uint8_t evt0op1, uint8_t evt0pathcomb, uint8_t evt0opcomb, uint16_t evt0tgtadd) +{ + ASSERT_ERR((((uint32_t)evt0op3 << 26) & ~((uint32_t)0xFC000000)) == 0); + ASSERT_ERR((((uint32_t)evt0op2 << 20) & ~((uint32_t)0x03F00000)) == 0); + ASSERT_ERR((((uint32_t)evt0op1 << 14) & ~((uint32_t)0x000FC000)) == 0); + ASSERT_ERR((((uint32_t)evt0pathcomb << 13) & ~((uint32_t)0x00002000)) == 0); + ASSERT_ERR((((uint32_t)evt0opcomb << 11) & ~((uint32_t)0x00001800)) == 0); + ASSERT_ERR((((uint32_t)evt0tgtadd << 0) & ~((uint32_t)0x000007FF)) == 0); + REG_PL_WR(AGC_RWNXAGCEVTSAT_ADDR, ((uint32_t)evt0op3 << 26) | ((uint32_t)evt0op2 << 20) | ((uint32_t)evt0op1 << 14) | ((uint32_t)evt0pathcomb << 13) | ((uint32_t)evt0opcomb << 11) | ((uint32_t)evt0tgtadd << 0)); +} + +/** + * @brief Unpacks RWNXAGCEVTSAT's fields from current value of the RWNXAGCEVTSAT register. + * + * Reads the RWNXAGCEVTSAT register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] evt0op3 - Will be populated with the current value of this field from the register. + * @param[out] evt0op2 - Will be populated with the current value of this field from the register. + * @param[out] evt0op1 - Will be populated with the current value of this field from the register. + * @param[out] evt0pathcomb - Will be populated with the current value of this field from the register. + * @param[out] evt0opcomb - Will be populated with the current value of this field from the register. + * @param[out] evt0tgtadd - Will be populated with the current value of this field from the register. + */ +__INLINE void agc_rwnxagcevtsat_unpack(uint8_t *evt0op3, uint8_t *evt0op2, uint8_t *evt0op1, uint8_t *evt0pathcomb, uint8_t *evt0opcomb, uint16_t *evt0tgtadd) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCEVTSAT_ADDR); + + *evt0op3 = (localVal & ((uint32_t)0xFC000000)) >> 26; + *evt0op2 = (localVal & ((uint32_t)0x03F00000)) >> 20; + *evt0op1 = (localVal & ((uint32_t)0x000FC000)) >> 14; + *evt0pathcomb = (localVal & ((uint32_t)0x00002000)) >> 13; + *evt0opcomb = (localVal & ((uint32_t)0x00001800)) >> 11; + *evt0tgtadd = (localVal & ((uint32_t)0x000007FF)) >> 0; +} + +/** + * @brief Returns the current value of the EVT0OP3 field in the RWNXAGCEVTSAT register. + * + * The RWNXAGCEVTSAT register will be read and the EVT0OP3 field's value will be returned. + * + * @return The current value of the EVT0OP3 field in the RWNXAGCEVTSAT register. + */ +__INLINE uint8_t agc_evt0op3_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCEVTSAT_ADDR); + return ((localVal & ((uint32_t)0xFC000000)) >> 26); +} + +/** + * @brief Sets the EVT0OP3 field of the RWNXAGCEVTSAT register. + * + * The RWNXAGCEVTSAT register will be read, modified to contain the new field value, and written. + * + * @param[in] evt0op3 - The value to set the field to. + */ +__INLINE void agc_evt0op3_setf(uint8_t evt0op3) +{ + ASSERT_ERR((((uint32_t)evt0op3 << 26) & ~((uint32_t)0xFC000000)) == 0); + REG_PL_WR(AGC_RWNXAGCEVTSAT_ADDR, (REG_PL_RD(AGC_RWNXAGCEVTSAT_ADDR) & ~((uint32_t)0xFC000000)) | ((uint32_t)evt0op3 << 26)); +} + +/** + * @brief Returns the current value of the EVT0OP2 field in the RWNXAGCEVTSAT register. + * + * The RWNXAGCEVTSAT register will be read and the EVT0OP2 field's value will be returned. + * + * @return The current value of the EVT0OP2 field in the RWNXAGCEVTSAT register. + */ +__INLINE uint8_t agc_evt0op2_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCEVTSAT_ADDR); + return ((localVal & ((uint32_t)0x03F00000)) >> 20); +} + +/** + * @brief Sets the EVT0OP2 field of the RWNXAGCEVTSAT register. + * + * The RWNXAGCEVTSAT register will be read, modified to contain the new field value, and written. + * + * @param[in] evt0op2 - The value to set the field to. + */ +__INLINE void agc_evt0op2_setf(uint8_t evt0op2) +{ + ASSERT_ERR((((uint32_t)evt0op2 << 20) & ~((uint32_t)0x03F00000)) == 0); + REG_PL_WR(AGC_RWNXAGCEVTSAT_ADDR, (REG_PL_RD(AGC_RWNXAGCEVTSAT_ADDR) & ~((uint32_t)0x03F00000)) | ((uint32_t)evt0op2 << 20)); +} + +/** + * @brief Returns the current value of the EVT0OP1 field in the RWNXAGCEVTSAT register. + * + * The RWNXAGCEVTSAT register will be read and the EVT0OP1 field's value will be returned. + * + * @return The current value of the EVT0OP1 field in the RWNXAGCEVTSAT register. + */ +__INLINE uint8_t agc_evt0op1_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCEVTSAT_ADDR); + return ((localVal & ((uint32_t)0x000FC000)) >> 14); +} + +/** + * @brief Sets the EVT0OP1 field of the RWNXAGCEVTSAT register. + * + * The RWNXAGCEVTSAT register will be read, modified to contain the new field value, and written. + * + * @param[in] evt0op1 - The value to set the field to. + */ +__INLINE void agc_evt0op1_setf(uint8_t evt0op1) +{ + ASSERT_ERR((((uint32_t)evt0op1 << 14) & ~((uint32_t)0x000FC000)) == 0); + REG_PL_WR(AGC_RWNXAGCEVTSAT_ADDR, (REG_PL_RD(AGC_RWNXAGCEVTSAT_ADDR) & ~((uint32_t)0x000FC000)) | ((uint32_t)evt0op1 << 14)); +} + +/** + * @brief Returns the current value of the EVT0PATHCOMB field in the RWNXAGCEVTSAT register. + * + * The RWNXAGCEVTSAT register will be read and the EVT0PATHCOMB field's value will be returned. + * + * @return The current value of the EVT0PATHCOMB field in the RWNXAGCEVTSAT register. + */ +__INLINE uint8_t agc_evt0pathcomb_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCEVTSAT_ADDR); + return ((localVal & ((uint32_t)0x00002000)) >> 13); +} + +/** + * @brief Sets the EVT0PATHCOMB field of the RWNXAGCEVTSAT register. + * + * The RWNXAGCEVTSAT register will be read, modified to contain the new field value, and written. + * + * @param[in] evt0pathcomb - The value to set the field to. + */ +__INLINE void agc_evt0pathcomb_setf(uint8_t evt0pathcomb) +{ + ASSERT_ERR((((uint32_t)evt0pathcomb << 13) & ~((uint32_t)0x00002000)) == 0); + REG_PL_WR(AGC_RWNXAGCEVTSAT_ADDR, (REG_PL_RD(AGC_RWNXAGCEVTSAT_ADDR) & ~((uint32_t)0x00002000)) | ((uint32_t)evt0pathcomb << 13)); +} + +/** + * @brief Returns the current value of the EVT0OPCOMB field in the RWNXAGCEVTSAT register. + * + * The RWNXAGCEVTSAT register will be read and the EVT0OPCOMB field's value will be returned. + * + * @return The current value of the EVT0OPCOMB field in the RWNXAGCEVTSAT register. + */ +__INLINE uint8_t agc_evt0opcomb_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCEVTSAT_ADDR); + return ((localVal & ((uint32_t)0x00001800)) >> 11); +} + +/** + * @brief Sets the EVT0OPCOMB field of the RWNXAGCEVTSAT register. + * + * The RWNXAGCEVTSAT register will be read, modified to contain the new field value, and written. + * + * @param[in] evt0opcomb - The value to set the field to. + */ +__INLINE void agc_evt0opcomb_setf(uint8_t evt0opcomb) +{ + ASSERT_ERR((((uint32_t)evt0opcomb << 11) & ~((uint32_t)0x00001800)) == 0); + REG_PL_WR(AGC_RWNXAGCEVTSAT_ADDR, (REG_PL_RD(AGC_RWNXAGCEVTSAT_ADDR) & ~((uint32_t)0x00001800)) | ((uint32_t)evt0opcomb << 11)); +} + +/** + * @brief Returns the current value of the EVT0TGTADD field in the RWNXAGCEVTSAT register. + * + * The RWNXAGCEVTSAT register will be read and the EVT0TGTADD field's value will be returned. + * + * @return The current value of the EVT0TGTADD field in the RWNXAGCEVTSAT register. + */ +__INLINE uint16_t agc_evt0tgtadd_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCEVTSAT_ADDR); + return ((localVal & ((uint32_t)0x000007FF)) >> 0); +} + +/** + * @brief Sets the EVT0TGTADD field of the RWNXAGCEVTSAT register. + * + * The RWNXAGCEVTSAT register will be read, modified to contain the new field value, and written. + * + * @param[in] evt0tgtadd - The value to set the field to. + */ +__INLINE void agc_evt0tgtadd_setf(uint16_t evt0tgtadd) +{ + ASSERT_ERR((((uint32_t)evt0tgtadd << 0) & ~((uint32_t)0x000007FF)) == 0); + REG_PL_WR(AGC_RWNXAGCEVTSAT_ADDR, (REG_PL_RD(AGC_RWNXAGCEVTSAT_ADDR) & ~((uint32_t)0x000007FF)) | ((uint32_t)evt0tgtadd << 0)); +} + +/// @} + +/** + * @name RWNXAGCEVTDET register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:26              EVT1OP3   0xF
+ *  25:20              EVT1OP2   0x14
+ *  19:14              EVT1OP1   0x12
+ *     13         EVT1PATHCOMB   0
+ *  12:11           EVT1OPCOMB   0x2
+ *  10:00           EVT1TGTADD   0x8
+ * 
+ * + * @{ + */ + +/// Address of the RWNXAGCEVTDET register +#define AGC_RWNXAGCEVTDET_ADDR 0x01002054 +/// Offset of the RWNXAGCEVTDET register from the base address +#define AGC_RWNXAGCEVTDET_OFFSET 0x00002054 +/// Index of the RWNXAGCEVTDET register +#define AGC_RWNXAGCEVTDET_INDEX 0x00000815 +/// Reset value of the RWNXAGCEVTDET register +#define AGC_RWNXAGCEVTDET_RESET 0x3D449008 + +/** + * @brief Returns the current value of the RWNXAGCEVTDET register. + * The RWNXAGCEVTDET register will be read and its value returned. + * @return The current value of the RWNXAGCEVTDET register. + */ +__INLINE uint32_t agc_rwnxagcevtdet_get(void) +{ + return REG_PL_RD(AGC_RWNXAGCEVTDET_ADDR); +} + +/** + * @brief Sets the RWNXAGCEVTDET register to a value. + * The RWNXAGCEVTDET register will be written. + * @param value - The value to write. + */ +__INLINE void agc_rwnxagcevtdet_set(uint32_t value) +{ + REG_PL_WR(AGC_RWNXAGCEVTDET_ADDR, value); +} + +// field definitions +/// EVT1OP3 field mask +#define AGC_EVT1OP3_MASK ((uint32_t)0xFC000000) +/// EVT1OP3 field LSB position +#define AGC_EVT1OP3_LSB 26 +/// EVT1OP3 field width +#define AGC_EVT1OP3_WIDTH ((uint32_t)0x00000006) +/// EVT1OP2 field mask +#define AGC_EVT1OP2_MASK ((uint32_t)0x03F00000) +/// EVT1OP2 field LSB position +#define AGC_EVT1OP2_LSB 20 +/// EVT1OP2 field width +#define AGC_EVT1OP2_WIDTH ((uint32_t)0x00000006) +/// EVT1OP1 field mask +#define AGC_EVT1OP1_MASK ((uint32_t)0x000FC000) +/// EVT1OP1 field LSB position +#define AGC_EVT1OP1_LSB 14 +/// EVT1OP1 field width +#define AGC_EVT1OP1_WIDTH ((uint32_t)0x00000006) +/// EVT1PATHCOMB field bit +#define AGC_EVT1PATHCOMB_BIT ((uint32_t)0x00002000) +/// EVT1PATHCOMB field position +#define AGC_EVT1PATHCOMB_POS 13 +/// EVT1OPCOMB field mask +#define AGC_EVT1OPCOMB_MASK ((uint32_t)0x00001800) +/// EVT1OPCOMB field LSB position +#define AGC_EVT1OPCOMB_LSB 11 +/// EVT1OPCOMB field width +#define AGC_EVT1OPCOMB_WIDTH ((uint32_t)0x00000002) +/// EVT1TGTADD field mask +#define AGC_EVT1TGTADD_MASK ((uint32_t)0x000007FF) +/// EVT1TGTADD field LSB position +#define AGC_EVT1TGTADD_LSB 0 +/// EVT1TGTADD field width +#define AGC_EVT1TGTADD_WIDTH ((uint32_t)0x0000000B) + +/// EVT1OP3 field reset value +#define AGC_EVT1OP3_RST 0xF +/// EVT1OP2 field reset value +#define AGC_EVT1OP2_RST 0x14 +/// EVT1OP1 field reset value +#define AGC_EVT1OP1_RST 0x12 +/// EVT1PATHCOMB field reset value +#define AGC_EVT1PATHCOMB_RST 0x0 +/// EVT1OPCOMB field reset value +#define AGC_EVT1OPCOMB_RST 0x2 +/// EVT1TGTADD field reset value +#define AGC_EVT1TGTADD_RST 0x8 + +/** + * @brief Constructs a value for the RWNXAGCEVTDET register given values for its fields + * and writes the value to the register. + * + * @param[in] evt1op3 - The value to use for the EVT1OP3 field. + * @param[in] evt1op2 - The value to use for the EVT1OP2 field. + * @param[in] evt1op1 - The value to use for the EVT1OP1 field. + * @param[in] evt1pathcomb - The value to use for the EVT1PATHCOMB field. + * @param[in] evt1opcomb - The value to use for the EVT1OPCOMB field. + * @param[in] evt1tgtadd - The value to use for the EVT1TGTADD field. + */ +__INLINE void agc_rwnxagcevtdet_pack(uint8_t evt1op3, uint8_t evt1op2, uint8_t evt1op1, uint8_t evt1pathcomb, uint8_t evt1opcomb, uint16_t evt1tgtadd) +{ + ASSERT_ERR((((uint32_t)evt1op3 << 26) & ~((uint32_t)0xFC000000)) == 0); + ASSERT_ERR((((uint32_t)evt1op2 << 20) & ~((uint32_t)0x03F00000)) == 0); + ASSERT_ERR((((uint32_t)evt1op1 << 14) & ~((uint32_t)0x000FC000)) == 0); + ASSERT_ERR((((uint32_t)evt1pathcomb << 13) & ~((uint32_t)0x00002000)) == 0); + ASSERT_ERR((((uint32_t)evt1opcomb << 11) & ~((uint32_t)0x00001800)) == 0); + ASSERT_ERR((((uint32_t)evt1tgtadd << 0) & ~((uint32_t)0x000007FF)) == 0); + REG_PL_WR(AGC_RWNXAGCEVTDET_ADDR, ((uint32_t)evt1op3 << 26) | ((uint32_t)evt1op2 << 20) | ((uint32_t)evt1op1 << 14) | ((uint32_t)evt1pathcomb << 13) | ((uint32_t)evt1opcomb << 11) | ((uint32_t)evt1tgtadd << 0)); +} + +/** + * @brief Unpacks RWNXAGCEVTDET's fields from current value of the RWNXAGCEVTDET register. + * + * Reads the RWNXAGCEVTDET register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] evt1op3 - Will be populated with the current value of this field from the register. + * @param[out] evt1op2 - Will be populated with the current value of this field from the register. + * @param[out] evt1op1 - Will be populated with the current value of this field from the register. + * @param[out] evt1pathcomb - Will be populated with the current value of this field from the register. + * @param[out] evt1opcomb - Will be populated with the current value of this field from the register. + * @param[out] evt1tgtadd - Will be populated with the current value of this field from the register. + */ +__INLINE void agc_rwnxagcevtdet_unpack(uint8_t *evt1op3, uint8_t *evt1op2, uint8_t *evt1op1, uint8_t *evt1pathcomb, uint8_t *evt1opcomb, uint16_t *evt1tgtadd) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCEVTDET_ADDR); + + *evt1op3 = (localVal & ((uint32_t)0xFC000000)) >> 26; + *evt1op2 = (localVal & ((uint32_t)0x03F00000)) >> 20; + *evt1op1 = (localVal & ((uint32_t)0x000FC000)) >> 14; + *evt1pathcomb = (localVal & ((uint32_t)0x00002000)) >> 13; + *evt1opcomb = (localVal & ((uint32_t)0x00001800)) >> 11; + *evt1tgtadd = (localVal & ((uint32_t)0x000007FF)) >> 0; +} + +/** + * @brief Returns the current value of the EVT1OP3 field in the RWNXAGCEVTDET register. + * + * The RWNXAGCEVTDET register will be read and the EVT1OP3 field's value will be returned. + * + * @return The current value of the EVT1OP3 field in the RWNXAGCEVTDET register. + */ +__INLINE uint8_t agc_evt1op3_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCEVTDET_ADDR); + return ((localVal & ((uint32_t)0xFC000000)) >> 26); +} + +/** + * @brief Sets the EVT1OP3 field of the RWNXAGCEVTDET register. + * + * The RWNXAGCEVTDET register will be read, modified to contain the new field value, and written. + * + * @param[in] evt1op3 - The value to set the field to. + */ +__INLINE void agc_evt1op3_setf(uint8_t evt1op3) +{ + ASSERT_ERR((((uint32_t)evt1op3 << 26) & ~((uint32_t)0xFC000000)) == 0); + REG_PL_WR(AGC_RWNXAGCEVTDET_ADDR, (REG_PL_RD(AGC_RWNXAGCEVTDET_ADDR) & ~((uint32_t)0xFC000000)) | ((uint32_t)evt1op3 << 26)); +} + +/** + * @brief Returns the current value of the EVT1OP2 field in the RWNXAGCEVTDET register. + * + * The RWNXAGCEVTDET register will be read and the EVT1OP2 field's value will be returned. + * + * @return The current value of the EVT1OP2 field in the RWNXAGCEVTDET register. + */ +__INLINE uint8_t agc_evt1op2_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCEVTDET_ADDR); + return ((localVal & ((uint32_t)0x03F00000)) >> 20); +} + +/** + * @brief Sets the EVT1OP2 field of the RWNXAGCEVTDET register. + * + * The RWNXAGCEVTDET register will be read, modified to contain the new field value, and written. + * + * @param[in] evt1op2 - The value to set the field to. + */ +__INLINE void agc_evt1op2_setf(uint8_t evt1op2) +{ + ASSERT_ERR((((uint32_t)evt1op2 << 20) & ~((uint32_t)0x03F00000)) == 0); + REG_PL_WR(AGC_RWNXAGCEVTDET_ADDR, (REG_PL_RD(AGC_RWNXAGCEVTDET_ADDR) & ~((uint32_t)0x03F00000)) | ((uint32_t)evt1op2 << 20)); +} + +/** + * @brief Returns the current value of the EVT1OP1 field in the RWNXAGCEVTDET register. + * + * The RWNXAGCEVTDET register will be read and the EVT1OP1 field's value will be returned. + * + * @return The current value of the EVT1OP1 field in the RWNXAGCEVTDET register. + */ +__INLINE uint8_t agc_evt1op1_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCEVTDET_ADDR); + return ((localVal & ((uint32_t)0x000FC000)) >> 14); +} + +/** + * @brief Sets the EVT1OP1 field of the RWNXAGCEVTDET register. + * + * The RWNXAGCEVTDET register will be read, modified to contain the new field value, and written. + * + * @param[in] evt1op1 - The value to set the field to. + */ +__INLINE void agc_evt1op1_setf(uint8_t evt1op1) +{ + ASSERT_ERR((((uint32_t)evt1op1 << 14) & ~((uint32_t)0x000FC000)) == 0); + REG_PL_WR(AGC_RWNXAGCEVTDET_ADDR, (REG_PL_RD(AGC_RWNXAGCEVTDET_ADDR) & ~((uint32_t)0x000FC000)) | ((uint32_t)evt1op1 << 14)); +} + +/** + * @brief Returns the current value of the EVT1PATHCOMB field in the RWNXAGCEVTDET register. + * + * The RWNXAGCEVTDET register will be read and the EVT1PATHCOMB field's value will be returned. + * + * @return The current value of the EVT1PATHCOMB field in the RWNXAGCEVTDET register. + */ +__INLINE uint8_t agc_evt1pathcomb_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCEVTDET_ADDR); + return ((localVal & ((uint32_t)0x00002000)) >> 13); +} + +/** + * @brief Sets the EVT1PATHCOMB field of the RWNXAGCEVTDET register. + * + * The RWNXAGCEVTDET register will be read, modified to contain the new field value, and written. + * + * @param[in] evt1pathcomb - The value to set the field to. + */ +__INLINE void agc_evt1pathcomb_setf(uint8_t evt1pathcomb) +{ + ASSERT_ERR((((uint32_t)evt1pathcomb << 13) & ~((uint32_t)0x00002000)) == 0); + REG_PL_WR(AGC_RWNXAGCEVTDET_ADDR, (REG_PL_RD(AGC_RWNXAGCEVTDET_ADDR) & ~((uint32_t)0x00002000)) | ((uint32_t)evt1pathcomb << 13)); +} + +/** + * @brief Returns the current value of the EVT1OPCOMB field in the RWNXAGCEVTDET register. + * + * The RWNXAGCEVTDET register will be read and the EVT1OPCOMB field's value will be returned. + * + * @return The current value of the EVT1OPCOMB field in the RWNXAGCEVTDET register. + */ +__INLINE uint8_t agc_evt1opcomb_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCEVTDET_ADDR); + return ((localVal & ((uint32_t)0x00001800)) >> 11); +} + +/** + * @brief Sets the EVT1OPCOMB field of the RWNXAGCEVTDET register. + * + * The RWNXAGCEVTDET register will be read, modified to contain the new field value, and written. + * + * @param[in] evt1opcomb - The value to set the field to. + */ +__INLINE void agc_evt1opcomb_setf(uint8_t evt1opcomb) +{ + ASSERT_ERR((((uint32_t)evt1opcomb << 11) & ~((uint32_t)0x00001800)) == 0); + REG_PL_WR(AGC_RWNXAGCEVTDET_ADDR, (REG_PL_RD(AGC_RWNXAGCEVTDET_ADDR) & ~((uint32_t)0x00001800)) | ((uint32_t)evt1opcomb << 11)); +} + +/** + * @brief Returns the current value of the EVT1TGTADD field in the RWNXAGCEVTDET register. + * + * The RWNXAGCEVTDET register will be read and the EVT1TGTADD field's value will be returned. + * + * @return The current value of the EVT1TGTADD field in the RWNXAGCEVTDET register. + */ +__INLINE uint16_t agc_evt1tgtadd_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCEVTDET_ADDR); + return ((localVal & ((uint32_t)0x000007FF)) >> 0); +} + +/** + * @brief Sets the EVT1TGTADD field of the RWNXAGCEVTDET register. + * + * The RWNXAGCEVTDET register will be read, modified to contain the new field value, and written. + * + * @param[in] evt1tgtadd - The value to set the field to. + */ +__INLINE void agc_evt1tgtadd_setf(uint16_t evt1tgtadd) +{ + ASSERT_ERR((((uint32_t)evt1tgtadd << 0) & ~((uint32_t)0x000007FF)) == 0); + REG_PL_WR(AGC_RWNXAGCEVTDET_ADDR, (REG_PL_RD(AGC_RWNXAGCEVTDET_ADDR) & ~((uint32_t)0x000007FF)) | ((uint32_t)evt1tgtadd << 0)); +} + +/// @} + +/** + * @name RWNXAGCEVTDIS register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:26              EVT2OP3   0xE
+ *  25:20              EVT2OP2   0x15
+ *  19:14              EVT2OP1   0x16
+ *     13         EVT2PATHCOMB   0
+ *  12:11           EVT2OPCOMB   0x2
+ *  10:00           EVT2TGTADD   0xB
+ * 
+ * + * @{ + */ + +/// Address of the RWNXAGCEVTDIS register +#define AGC_RWNXAGCEVTDIS_ADDR 0x01002058 +/// Offset of the RWNXAGCEVTDIS register from the base address +#define AGC_RWNXAGCEVTDIS_OFFSET 0x00002058 +/// Index of the RWNXAGCEVTDIS register +#define AGC_RWNXAGCEVTDIS_INDEX 0x00000816 +/// Reset value of the RWNXAGCEVTDIS register +#define AGC_RWNXAGCEVTDIS_RESET 0x3955900B + +/** + * @brief Returns the current value of the RWNXAGCEVTDIS register. + * The RWNXAGCEVTDIS register will be read and its value returned. + * @return The current value of the RWNXAGCEVTDIS register. + */ +__INLINE uint32_t agc_rwnxagcevtdis_get(void) +{ + return REG_PL_RD(AGC_RWNXAGCEVTDIS_ADDR); +} + +/** + * @brief Sets the RWNXAGCEVTDIS register to a value. + * The RWNXAGCEVTDIS register will be written. + * @param value - The value to write. + */ +__INLINE void agc_rwnxagcevtdis_set(uint32_t value) +{ + REG_PL_WR(AGC_RWNXAGCEVTDIS_ADDR, value); +} + +// field definitions +/// EVT2OP3 field mask +#define AGC_EVT2OP3_MASK ((uint32_t)0xFC000000) +/// EVT2OP3 field LSB position +#define AGC_EVT2OP3_LSB 26 +/// EVT2OP3 field width +#define AGC_EVT2OP3_WIDTH ((uint32_t)0x00000006) +/// EVT2OP2 field mask +#define AGC_EVT2OP2_MASK ((uint32_t)0x03F00000) +/// EVT2OP2 field LSB position +#define AGC_EVT2OP2_LSB 20 +/// EVT2OP2 field width +#define AGC_EVT2OP2_WIDTH ((uint32_t)0x00000006) +/// EVT2OP1 field mask +#define AGC_EVT2OP1_MASK ((uint32_t)0x000FC000) +/// EVT2OP1 field LSB position +#define AGC_EVT2OP1_LSB 14 +/// EVT2OP1 field width +#define AGC_EVT2OP1_WIDTH ((uint32_t)0x00000006) +/// EVT2PATHCOMB field bit +#define AGC_EVT2PATHCOMB_BIT ((uint32_t)0x00002000) +/// EVT2PATHCOMB field position +#define AGC_EVT2PATHCOMB_POS 13 +/// EVT2OPCOMB field mask +#define AGC_EVT2OPCOMB_MASK ((uint32_t)0x00001800) +/// EVT2OPCOMB field LSB position +#define AGC_EVT2OPCOMB_LSB 11 +/// EVT2OPCOMB field width +#define AGC_EVT2OPCOMB_WIDTH ((uint32_t)0x00000002) +/// EVT2TGTADD field mask +#define AGC_EVT2TGTADD_MASK ((uint32_t)0x000007FF) +/// EVT2TGTADD field LSB position +#define AGC_EVT2TGTADD_LSB 0 +/// EVT2TGTADD field width +#define AGC_EVT2TGTADD_WIDTH ((uint32_t)0x0000000B) + +/// EVT2OP3 field reset value +#define AGC_EVT2OP3_RST 0xE +/// EVT2OP2 field reset value +#define AGC_EVT2OP2_RST 0x15 +/// EVT2OP1 field reset value +#define AGC_EVT2OP1_RST 0x16 +/// EVT2PATHCOMB field reset value +#define AGC_EVT2PATHCOMB_RST 0x0 +/// EVT2OPCOMB field reset value +#define AGC_EVT2OPCOMB_RST 0x2 +/// EVT2TGTADD field reset value +#define AGC_EVT2TGTADD_RST 0xB + +/** + * @brief Constructs a value for the RWNXAGCEVTDIS register given values for its fields + * and writes the value to the register. + * + * @param[in] evt2op3 - The value to use for the EVT2OP3 field. + * @param[in] evt2op2 - The value to use for the EVT2OP2 field. + * @param[in] evt2op1 - The value to use for the EVT2OP1 field. + * @param[in] evt2pathcomb - The value to use for the EVT2PATHCOMB field. + * @param[in] evt2opcomb - The value to use for the EVT2OPCOMB field. + * @param[in] evt2tgtadd - The value to use for the EVT2TGTADD field. + */ +__INLINE void agc_rwnxagcevtdis_pack(uint8_t evt2op3, uint8_t evt2op2, uint8_t evt2op1, uint8_t evt2pathcomb, uint8_t evt2opcomb, uint16_t evt2tgtadd) +{ + ASSERT_ERR((((uint32_t)evt2op3 << 26) & ~((uint32_t)0xFC000000)) == 0); + ASSERT_ERR((((uint32_t)evt2op2 << 20) & ~((uint32_t)0x03F00000)) == 0); + ASSERT_ERR((((uint32_t)evt2op1 << 14) & ~((uint32_t)0x000FC000)) == 0); + ASSERT_ERR((((uint32_t)evt2pathcomb << 13) & ~((uint32_t)0x00002000)) == 0); + ASSERT_ERR((((uint32_t)evt2opcomb << 11) & ~((uint32_t)0x00001800)) == 0); + ASSERT_ERR((((uint32_t)evt2tgtadd << 0) & ~((uint32_t)0x000007FF)) == 0); + REG_PL_WR(AGC_RWNXAGCEVTDIS_ADDR, ((uint32_t)evt2op3 << 26) | ((uint32_t)evt2op2 << 20) | ((uint32_t)evt2op1 << 14) | ((uint32_t)evt2pathcomb << 13) | ((uint32_t)evt2opcomb << 11) | ((uint32_t)evt2tgtadd << 0)); +} + +/** + * @brief Unpacks RWNXAGCEVTDIS's fields from current value of the RWNXAGCEVTDIS register. + * + * Reads the RWNXAGCEVTDIS register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] evt2op3 - Will be populated with the current value of this field from the register. + * @param[out] evt2op2 - Will be populated with the current value of this field from the register. + * @param[out] evt2op1 - Will be populated with the current value of this field from the register. + * @param[out] evt2pathcomb - Will be populated with the current value of this field from the register. + * @param[out] evt2opcomb - Will be populated with the current value of this field from the register. + * @param[out] evt2tgtadd - Will be populated with the current value of this field from the register. + */ +__INLINE void agc_rwnxagcevtdis_unpack(uint8_t *evt2op3, uint8_t *evt2op2, uint8_t *evt2op1, uint8_t *evt2pathcomb, uint8_t *evt2opcomb, uint16_t *evt2tgtadd) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCEVTDIS_ADDR); + + *evt2op3 = (localVal & ((uint32_t)0xFC000000)) >> 26; + *evt2op2 = (localVal & ((uint32_t)0x03F00000)) >> 20; + *evt2op1 = (localVal & ((uint32_t)0x000FC000)) >> 14; + *evt2pathcomb = (localVal & ((uint32_t)0x00002000)) >> 13; + *evt2opcomb = (localVal & ((uint32_t)0x00001800)) >> 11; + *evt2tgtadd = (localVal & ((uint32_t)0x000007FF)) >> 0; +} + +/** + * @brief Returns the current value of the EVT2OP3 field in the RWNXAGCEVTDIS register. + * + * The RWNXAGCEVTDIS register will be read and the EVT2OP3 field's value will be returned. + * + * @return The current value of the EVT2OP3 field in the RWNXAGCEVTDIS register. + */ +__INLINE uint8_t agc_evt2op3_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCEVTDIS_ADDR); + return ((localVal & ((uint32_t)0xFC000000)) >> 26); +} + +/** + * @brief Sets the EVT2OP3 field of the RWNXAGCEVTDIS register. + * + * The RWNXAGCEVTDIS register will be read, modified to contain the new field value, and written. + * + * @param[in] evt2op3 - The value to set the field to. + */ +__INLINE void agc_evt2op3_setf(uint8_t evt2op3) +{ + ASSERT_ERR((((uint32_t)evt2op3 << 26) & ~((uint32_t)0xFC000000)) == 0); + REG_PL_WR(AGC_RWNXAGCEVTDIS_ADDR, (REG_PL_RD(AGC_RWNXAGCEVTDIS_ADDR) & ~((uint32_t)0xFC000000)) | ((uint32_t)evt2op3 << 26)); +} + +/** + * @brief Returns the current value of the EVT2OP2 field in the RWNXAGCEVTDIS register. + * + * The RWNXAGCEVTDIS register will be read and the EVT2OP2 field's value will be returned. + * + * @return The current value of the EVT2OP2 field in the RWNXAGCEVTDIS register. + */ +__INLINE uint8_t agc_evt2op2_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCEVTDIS_ADDR); + return ((localVal & ((uint32_t)0x03F00000)) >> 20); +} + +/** + * @brief Sets the EVT2OP2 field of the RWNXAGCEVTDIS register. + * + * The RWNXAGCEVTDIS register will be read, modified to contain the new field value, and written. + * + * @param[in] evt2op2 - The value to set the field to. + */ +__INLINE void agc_evt2op2_setf(uint8_t evt2op2) +{ + ASSERT_ERR((((uint32_t)evt2op2 << 20) & ~((uint32_t)0x03F00000)) == 0); + REG_PL_WR(AGC_RWNXAGCEVTDIS_ADDR, (REG_PL_RD(AGC_RWNXAGCEVTDIS_ADDR) & ~((uint32_t)0x03F00000)) | ((uint32_t)evt2op2 << 20)); +} + +/** + * @brief Returns the current value of the EVT2OP1 field in the RWNXAGCEVTDIS register. + * + * The RWNXAGCEVTDIS register will be read and the EVT2OP1 field's value will be returned. + * + * @return The current value of the EVT2OP1 field in the RWNXAGCEVTDIS register. + */ +__INLINE uint8_t agc_evt2op1_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCEVTDIS_ADDR); + return ((localVal & ((uint32_t)0x000FC000)) >> 14); +} + +/** + * @brief Sets the EVT2OP1 field of the RWNXAGCEVTDIS register. + * + * The RWNXAGCEVTDIS register will be read, modified to contain the new field value, and written. + * + * @param[in] evt2op1 - The value to set the field to. + */ +__INLINE void agc_evt2op1_setf(uint8_t evt2op1) +{ + ASSERT_ERR((((uint32_t)evt2op1 << 14) & ~((uint32_t)0x000FC000)) == 0); + REG_PL_WR(AGC_RWNXAGCEVTDIS_ADDR, (REG_PL_RD(AGC_RWNXAGCEVTDIS_ADDR) & ~((uint32_t)0x000FC000)) | ((uint32_t)evt2op1 << 14)); +} + +/** + * @brief Returns the current value of the EVT2PATHCOMB field in the RWNXAGCEVTDIS register. + * + * The RWNXAGCEVTDIS register will be read and the EVT2PATHCOMB field's value will be returned. + * + * @return The current value of the EVT2PATHCOMB field in the RWNXAGCEVTDIS register. + */ +__INLINE uint8_t agc_evt2pathcomb_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCEVTDIS_ADDR); + return ((localVal & ((uint32_t)0x00002000)) >> 13); +} + +/** + * @brief Sets the EVT2PATHCOMB field of the RWNXAGCEVTDIS register. + * + * The RWNXAGCEVTDIS register will be read, modified to contain the new field value, and written. + * + * @param[in] evt2pathcomb - The value to set the field to. + */ +__INLINE void agc_evt2pathcomb_setf(uint8_t evt2pathcomb) +{ + ASSERT_ERR((((uint32_t)evt2pathcomb << 13) & ~((uint32_t)0x00002000)) == 0); + REG_PL_WR(AGC_RWNXAGCEVTDIS_ADDR, (REG_PL_RD(AGC_RWNXAGCEVTDIS_ADDR) & ~((uint32_t)0x00002000)) | ((uint32_t)evt2pathcomb << 13)); +} + +/** + * @brief Returns the current value of the EVT2OPCOMB field in the RWNXAGCEVTDIS register. + * + * The RWNXAGCEVTDIS register will be read and the EVT2OPCOMB field's value will be returned. + * + * @return The current value of the EVT2OPCOMB field in the RWNXAGCEVTDIS register. + */ +__INLINE uint8_t agc_evt2opcomb_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCEVTDIS_ADDR); + return ((localVal & ((uint32_t)0x00001800)) >> 11); +} + +/** + * @brief Sets the EVT2OPCOMB field of the RWNXAGCEVTDIS register. + * + * The RWNXAGCEVTDIS register will be read, modified to contain the new field value, and written. + * + * @param[in] evt2opcomb - The value to set the field to. + */ +__INLINE void agc_evt2opcomb_setf(uint8_t evt2opcomb) +{ + ASSERT_ERR((((uint32_t)evt2opcomb << 11) & ~((uint32_t)0x00001800)) == 0); + REG_PL_WR(AGC_RWNXAGCEVTDIS_ADDR, (REG_PL_RD(AGC_RWNXAGCEVTDIS_ADDR) & ~((uint32_t)0x00001800)) | ((uint32_t)evt2opcomb << 11)); +} + +/** + * @brief Returns the current value of the EVT2TGTADD field in the RWNXAGCEVTDIS register. + * + * The RWNXAGCEVTDIS register will be read and the EVT2TGTADD field's value will be returned. + * + * @return The current value of the EVT2TGTADD field in the RWNXAGCEVTDIS register. + */ +__INLINE uint16_t agc_evt2tgtadd_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCEVTDIS_ADDR); + return ((localVal & ((uint32_t)0x000007FF)) >> 0); +} + +/** + * @brief Sets the EVT2TGTADD field of the RWNXAGCEVTDIS register. + * + * The RWNXAGCEVTDIS register will be read, modified to contain the new field value, and written. + * + * @param[in] evt2tgtadd - The value to set the field to. + */ +__INLINE void agc_evt2tgtadd_setf(uint16_t evt2tgtadd) +{ + ASSERT_ERR((((uint32_t)evt2tgtadd << 0) & ~((uint32_t)0x000007FF)) == 0); + REG_PL_WR(AGC_RWNXAGCEVTDIS_ADDR, (REG_PL_RD(AGC_RWNXAGCEVTDIS_ADDR) & ~((uint32_t)0x000007FF)) | ((uint32_t)evt2tgtadd << 0)); +} + +/// @} + +/** + * @name RWNXAGCEVTDSSSDET register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:26              EVT3OP3   0x1
+ *  25:20              EVT3OP2   0xF
+ *  19:14              EVT3OP1   0x1D
+ *     13         EVT3PATHCOMB   0
+ *  12:11           EVT3OPCOMB   0x1
+ *  10:00           EVT3TGTADD   0xF
+ * 
+ * + * @{ + */ + +/// Address of the RWNXAGCEVTDSSSDET register +#define AGC_RWNXAGCEVTDSSSDET_ADDR 0x0100205C +/// Offset of the RWNXAGCEVTDSSSDET register from the base address +#define AGC_RWNXAGCEVTDSSSDET_OFFSET 0x0000205C +/// Index of the RWNXAGCEVTDSSSDET register +#define AGC_RWNXAGCEVTDSSSDET_INDEX 0x00000817 +/// Reset value of the RWNXAGCEVTDSSSDET register +#define AGC_RWNXAGCEVTDSSSDET_RESET 0x04F7480F + +/** + * @brief Returns the current value of the RWNXAGCEVTDSSSDET register. + * The RWNXAGCEVTDSSSDET register will be read and its value returned. + * @return The current value of the RWNXAGCEVTDSSSDET register. + */ +__INLINE uint32_t agc_rwnxagcevtdsssdet_get(void) +{ + return REG_PL_RD(AGC_RWNXAGCEVTDSSSDET_ADDR); +} + +/** + * @brief Sets the RWNXAGCEVTDSSSDET register to a value. + * The RWNXAGCEVTDSSSDET register will be written. + * @param value - The value to write. + */ +__INLINE void agc_rwnxagcevtdsssdet_set(uint32_t value) +{ + REG_PL_WR(AGC_RWNXAGCEVTDSSSDET_ADDR, value); +} + +// field definitions +/// EVT3OP3 field mask +#define AGC_EVT3OP3_MASK ((uint32_t)0xFC000000) +/// EVT3OP3 field LSB position +#define AGC_EVT3OP3_LSB 26 +/// EVT3OP3 field width +#define AGC_EVT3OP3_WIDTH ((uint32_t)0x00000006) +/// EVT3OP2 field mask +#define AGC_EVT3OP2_MASK ((uint32_t)0x03F00000) +/// EVT3OP2 field LSB position +#define AGC_EVT3OP2_LSB 20 +/// EVT3OP2 field width +#define AGC_EVT3OP2_WIDTH ((uint32_t)0x00000006) +/// EVT3OP1 field mask +#define AGC_EVT3OP1_MASK ((uint32_t)0x000FC000) +/// EVT3OP1 field LSB position +#define AGC_EVT3OP1_LSB 14 +/// EVT3OP1 field width +#define AGC_EVT3OP1_WIDTH ((uint32_t)0x00000006) +/// EVT3PATHCOMB field bit +#define AGC_EVT3PATHCOMB_BIT ((uint32_t)0x00002000) +/// EVT3PATHCOMB field position +#define AGC_EVT3PATHCOMB_POS 13 +/// EVT3OPCOMB field mask +#define AGC_EVT3OPCOMB_MASK ((uint32_t)0x00001800) +/// EVT3OPCOMB field LSB position +#define AGC_EVT3OPCOMB_LSB 11 +/// EVT3OPCOMB field width +#define AGC_EVT3OPCOMB_WIDTH ((uint32_t)0x00000002) +/// EVT3TGTADD field mask +#define AGC_EVT3TGTADD_MASK ((uint32_t)0x000007FF) +/// EVT3TGTADD field LSB position +#define AGC_EVT3TGTADD_LSB 0 +/// EVT3TGTADD field width +#define AGC_EVT3TGTADD_WIDTH ((uint32_t)0x0000000B) + +/// EVT3OP3 field reset value +#define AGC_EVT3OP3_RST 0x1 +/// EVT3OP2 field reset value +#define AGC_EVT3OP2_RST 0xF +/// EVT3OP1 field reset value +#define AGC_EVT3OP1_RST 0x1D +/// EVT3PATHCOMB field reset value +#define AGC_EVT3PATHCOMB_RST 0x0 +/// EVT3OPCOMB field reset value +#define AGC_EVT3OPCOMB_RST 0x1 +/// EVT3TGTADD field reset value +#define AGC_EVT3TGTADD_RST 0xF + +/** + * @brief Constructs a value for the RWNXAGCEVTDSSSDET register given values for its fields + * and writes the value to the register. + * + * @param[in] evt3op3 - The value to use for the EVT3OP3 field. + * @param[in] evt3op2 - The value to use for the EVT3OP2 field. + * @param[in] evt3op1 - The value to use for the EVT3OP1 field. + * @param[in] evt3pathcomb - The value to use for the EVT3PATHCOMB field. + * @param[in] evt3opcomb - The value to use for the EVT3OPCOMB field. + * @param[in] evt3tgtadd - The value to use for the EVT3TGTADD field. + */ +__INLINE void agc_rwnxagcevtdsssdet_pack(uint8_t evt3op3, uint8_t evt3op2, uint8_t evt3op1, uint8_t evt3pathcomb, uint8_t evt3opcomb, uint16_t evt3tgtadd) +{ + ASSERT_ERR((((uint32_t)evt3op3 << 26) & ~((uint32_t)0xFC000000)) == 0); + ASSERT_ERR((((uint32_t)evt3op2 << 20) & ~((uint32_t)0x03F00000)) == 0); + ASSERT_ERR((((uint32_t)evt3op1 << 14) & ~((uint32_t)0x000FC000)) == 0); + ASSERT_ERR((((uint32_t)evt3pathcomb << 13) & ~((uint32_t)0x00002000)) == 0); + ASSERT_ERR((((uint32_t)evt3opcomb << 11) & ~((uint32_t)0x00001800)) == 0); + ASSERT_ERR((((uint32_t)evt3tgtadd << 0) & ~((uint32_t)0x000007FF)) == 0); + REG_PL_WR(AGC_RWNXAGCEVTDSSSDET_ADDR, ((uint32_t)evt3op3 << 26) | ((uint32_t)evt3op2 << 20) | ((uint32_t)evt3op1 << 14) | ((uint32_t)evt3pathcomb << 13) | ((uint32_t)evt3opcomb << 11) | ((uint32_t)evt3tgtadd << 0)); +} + +/** + * @brief Unpacks RWNXAGCEVTDSSSDET's fields from current value of the RWNXAGCEVTDSSSDET register. + * + * Reads the RWNXAGCEVTDSSSDET register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] evt3op3 - Will be populated with the current value of this field from the register. + * @param[out] evt3op2 - Will be populated with the current value of this field from the register. + * @param[out] evt3op1 - Will be populated with the current value of this field from the register. + * @param[out] evt3pathcomb - Will be populated with the current value of this field from the register. + * @param[out] evt3opcomb - Will be populated with the current value of this field from the register. + * @param[out] evt3tgtadd - Will be populated with the current value of this field from the register. + */ +__INLINE void agc_rwnxagcevtdsssdet_unpack(uint8_t *evt3op3, uint8_t *evt3op2, uint8_t *evt3op1, uint8_t *evt3pathcomb, uint8_t *evt3opcomb, uint16_t *evt3tgtadd) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCEVTDSSSDET_ADDR); + + *evt3op3 = (localVal & ((uint32_t)0xFC000000)) >> 26; + *evt3op2 = (localVal & ((uint32_t)0x03F00000)) >> 20; + *evt3op1 = (localVal & ((uint32_t)0x000FC000)) >> 14; + *evt3pathcomb = (localVal & ((uint32_t)0x00002000)) >> 13; + *evt3opcomb = (localVal & ((uint32_t)0x00001800)) >> 11; + *evt3tgtadd = (localVal & ((uint32_t)0x000007FF)) >> 0; +} + +/** + * @brief Returns the current value of the EVT3OP3 field in the RWNXAGCEVTDSSSDET register. + * + * The RWNXAGCEVTDSSSDET register will be read and the EVT3OP3 field's value will be returned. + * + * @return The current value of the EVT3OP3 field in the RWNXAGCEVTDSSSDET register. + */ +__INLINE uint8_t agc_evt3op3_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCEVTDSSSDET_ADDR); + return ((localVal & ((uint32_t)0xFC000000)) >> 26); +} + +/** + * @brief Sets the EVT3OP3 field of the RWNXAGCEVTDSSSDET register. + * + * The RWNXAGCEVTDSSSDET register will be read, modified to contain the new field value, and written. + * + * @param[in] evt3op3 - The value to set the field to. + */ +__INLINE void agc_evt3op3_setf(uint8_t evt3op3) +{ + ASSERT_ERR((((uint32_t)evt3op3 << 26) & ~((uint32_t)0xFC000000)) == 0); + REG_PL_WR(AGC_RWNXAGCEVTDSSSDET_ADDR, (REG_PL_RD(AGC_RWNXAGCEVTDSSSDET_ADDR) & ~((uint32_t)0xFC000000)) | ((uint32_t)evt3op3 << 26)); +} + +/** + * @brief Returns the current value of the EVT3OP2 field in the RWNXAGCEVTDSSSDET register. + * + * The RWNXAGCEVTDSSSDET register will be read and the EVT3OP2 field's value will be returned. + * + * @return The current value of the EVT3OP2 field in the RWNXAGCEVTDSSSDET register. + */ +__INLINE uint8_t agc_evt3op2_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCEVTDSSSDET_ADDR); + return ((localVal & ((uint32_t)0x03F00000)) >> 20); +} + +/** + * @brief Sets the EVT3OP2 field of the RWNXAGCEVTDSSSDET register. + * + * The RWNXAGCEVTDSSSDET register will be read, modified to contain the new field value, and written. + * + * @param[in] evt3op2 - The value to set the field to. + */ +__INLINE void agc_evt3op2_setf(uint8_t evt3op2) +{ + ASSERT_ERR((((uint32_t)evt3op2 << 20) & ~((uint32_t)0x03F00000)) == 0); + REG_PL_WR(AGC_RWNXAGCEVTDSSSDET_ADDR, (REG_PL_RD(AGC_RWNXAGCEVTDSSSDET_ADDR) & ~((uint32_t)0x03F00000)) | ((uint32_t)evt3op2 << 20)); +} + +/** + * @brief Returns the current value of the EVT3OP1 field in the RWNXAGCEVTDSSSDET register. + * + * The RWNXAGCEVTDSSSDET register will be read and the EVT3OP1 field's value will be returned. + * + * @return The current value of the EVT3OP1 field in the RWNXAGCEVTDSSSDET register. + */ +__INLINE uint8_t agc_evt3op1_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCEVTDSSSDET_ADDR); + return ((localVal & ((uint32_t)0x000FC000)) >> 14); +} + +/** + * @brief Sets the EVT3OP1 field of the RWNXAGCEVTDSSSDET register. + * + * The RWNXAGCEVTDSSSDET register will be read, modified to contain the new field value, and written. + * + * @param[in] evt3op1 - The value to set the field to. + */ +__INLINE void agc_evt3op1_setf(uint8_t evt3op1) +{ + ASSERT_ERR((((uint32_t)evt3op1 << 14) & ~((uint32_t)0x000FC000)) == 0); + REG_PL_WR(AGC_RWNXAGCEVTDSSSDET_ADDR, (REG_PL_RD(AGC_RWNXAGCEVTDSSSDET_ADDR) & ~((uint32_t)0x000FC000)) | ((uint32_t)evt3op1 << 14)); +} + +/** + * @brief Returns the current value of the EVT3PATHCOMB field in the RWNXAGCEVTDSSSDET register. + * + * The RWNXAGCEVTDSSSDET register will be read and the EVT3PATHCOMB field's value will be returned. + * + * @return The current value of the EVT3PATHCOMB field in the RWNXAGCEVTDSSSDET register. + */ +__INLINE uint8_t agc_evt3pathcomb_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCEVTDSSSDET_ADDR); + return ((localVal & ((uint32_t)0x00002000)) >> 13); +} + +/** + * @brief Sets the EVT3PATHCOMB field of the RWNXAGCEVTDSSSDET register. + * + * The RWNXAGCEVTDSSSDET register will be read, modified to contain the new field value, and written. + * + * @param[in] evt3pathcomb - The value to set the field to. + */ +__INLINE void agc_evt3pathcomb_setf(uint8_t evt3pathcomb) +{ + ASSERT_ERR((((uint32_t)evt3pathcomb << 13) & ~((uint32_t)0x00002000)) == 0); + REG_PL_WR(AGC_RWNXAGCEVTDSSSDET_ADDR, (REG_PL_RD(AGC_RWNXAGCEVTDSSSDET_ADDR) & ~((uint32_t)0x00002000)) | ((uint32_t)evt3pathcomb << 13)); +} + +/** + * @brief Returns the current value of the EVT3OPCOMB field in the RWNXAGCEVTDSSSDET register. + * + * The RWNXAGCEVTDSSSDET register will be read and the EVT3OPCOMB field's value will be returned. + * + * @return The current value of the EVT3OPCOMB field in the RWNXAGCEVTDSSSDET register. + */ +__INLINE uint8_t agc_evt3opcomb_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCEVTDSSSDET_ADDR); + return ((localVal & ((uint32_t)0x00001800)) >> 11); +} + +/** + * @brief Sets the EVT3OPCOMB field of the RWNXAGCEVTDSSSDET register. + * + * The RWNXAGCEVTDSSSDET register will be read, modified to contain the new field value, and written. + * + * @param[in] evt3opcomb - The value to set the field to. + */ +__INLINE void agc_evt3opcomb_setf(uint8_t evt3opcomb) +{ + ASSERT_ERR((((uint32_t)evt3opcomb << 11) & ~((uint32_t)0x00001800)) == 0); + REG_PL_WR(AGC_RWNXAGCEVTDSSSDET_ADDR, (REG_PL_RD(AGC_RWNXAGCEVTDSSSDET_ADDR) & ~((uint32_t)0x00001800)) | ((uint32_t)evt3opcomb << 11)); +} + +/** + * @brief Returns the current value of the EVT3TGTADD field in the RWNXAGCEVTDSSSDET register. + * + * The RWNXAGCEVTDSSSDET register will be read and the EVT3TGTADD field's value will be returned. + * + * @return The current value of the EVT3TGTADD field in the RWNXAGCEVTDSSSDET register. + */ +__INLINE uint16_t agc_evt3tgtadd_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCEVTDSSSDET_ADDR); + return ((localVal & ((uint32_t)0x000007FF)) >> 0); +} + +/** + * @brief Sets the EVT3TGTADD field of the RWNXAGCEVTDSSSDET register. + * + * The RWNXAGCEVTDSSSDET register will be read, modified to contain the new field value, and written. + * + * @param[in] evt3tgtadd - The value to set the field to. + */ +__INLINE void agc_evt3tgtadd_setf(uint16_t evt3tgtadd) +{ + ASSERT_ERR((((uint32_t)evt3tgtadd << 0) & ~((uint32_t)0x000007FF)) == 0); + REG_PL_WR(AGC_RWNXAGCEVTDSSSDET_ADDR, (REG_PL_RD(AGC_RWNXAGCEVTDSSSDET_ADDR) & ~((uint32_t)0x000007FF)) | ((uint32_t)evt3tgtadd << 0)); +} + +/// @} + +/** + * @name RWNXAGCCNTL register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     16          HTSTFGAINEN   1
+ *     12          AGCFSMRESET   0
+ *     11           RADARDETEN   0
+ *     10            RIFSDETEN   1
+ *     09             DSSSONLY   0
+ *     08             OFDMONLY   0
+ *  07:04             GPSTATUS   0x0
+ *  03:00          COMBPATHSEL   0xF
+ * 
+ * + * @{ + */ + +/// Address of the RWNXAGCCNTL register +#define AGC_RWNXAGCCNTL_ADDR 0x01002060 +/// Offset of the RWNXAGCCNTL register from the base address +#define AGC_RWNXAGCCNTL_OFFSET 0x00002060 +/// Index of the RWNXAGCCNTL register +#define AGC_RWNXAGCCNTL_INDEX 0x00000818 +/// Reset value of the RWNXAGCCNTL register +#define AGC_RWNXAGCCNTL_RESET 0x0001040F + +/** + * @brief Returns the current value of the RWNXAGCCNTL register. + * The RWNXAGCCNTL register will be read and its value returned. + * @return The current value of the RWNXAGCCNTL register. + */ +__INLINE uint32_t agc_rwnxagccntl_get(void) +{ + return REG_PL_RD(AGC_RWNXAGCCNTL_ADDR); +} + +/** + * @brief Sets the RWNXAGCCNTL register to a value. + * The RWNXAGCCNTL register will be written. + * @param value - The value to write. + */ +__INLINE void agc_rwnxagccntl_set(uint32_t value) +{ + REG_PL_WR(AGC_RWNXAGCCNTL_ADDR, value); +} + +// field definitions +/// HTSTFGAINEN field bit +#define AGC_HTSTFGAINEN_BIT ((uint32_t)0x00010000) +/// HTSTFGAINEN field position +#define AGC_HTSTFGAINEN_POS 16 +/// AGCFSMRESET field bit +#define AGC_AGCFSMRESET_BIT ((uint32_t)0x00001000) +/// AGCFSMRESET field position +#define AGC_AGCFSMRESET_POS 12 +/// RADARDETEN field bit +#define AGC_RADARDETEN_BIT ((uint32_t)0x00000800) +/// RADARDETEN field position +#define AGC_RADARDETEN_POS 11 +/// RIFSDETEN field bit +#define AGC_RIFSDETEN_BIT ((uint32_t)0x00000400) +/// RIFSDETEN field position +#define AGC_RIFSDETEN_POS 10 +/// DSSSONLY field bit +#define AGC_DSSSONLY_BIT ((uint32_t)0x00000200) +/// DSSSONLY field position +#define AGC_DSSSONLY_POS 9 +/// OFDMONLY field bit +#define AGC_OFDMONLY_BIT ((uint32_t)0x00000100) +/// OFDMONLY field position +#define AGC_OFDMONLY_POS 8 +/// GPSTATUS field mask +#define AGC_GPSTATUS_MASK ((uint32_t)0x000000F0) +/// GPSTATUS field LSB position +#define AGC_GPSTATUS_LSB 4 +/// GPSTATUS field width +#define AGC_GPSTATUS_WIDTH ((uint32_t)0x00000004) +/// COMBPATHSEL field mask +#define AGC_COMBPATHSEL_MASK ((uint32_t)0x0000000F) +/// COMBPATHSEL field LSB position +#define AGC_COMBPATHSEL_LSB 0 +/// COMBPATHSEL field width +#define AGC_COMBPATHSEL_WIDTH ((uint32_t)0x00000004) + +/// HTSTFGAINEN field reset value +#define AGC_HTSTFGAINEN_RST 0x1 +/// AGCFSMRESET field reset value +#define AGC_AGCFSMRESET_RST 0x0 +/// RADARDETEN field reset value +#define AGC_RADARDETEN_RST 0x0 +/// RIFSDETEN field reset value +#define AGC_RIFSDETEN_RST 0x1 +/// DSSSONLY field reset value +#define AGC_DSSSONLY_RST 0x0 +/// OFDMONLY field reset value +#define AGC_OFDMONLY_RST 0x0 +/// GPSTATUS field reset value +#define AGC_GPSTATUS_RST 0x0 +/// COMBPATHSEL field reset value +#define AGC_COMBPATHSEL_RST 0xF + +/** + * @brief Constructs a value for the RWNXAGCCNTL register given values for its fields + * and writes the value to the register. + * + * @param[in] htstfgainen - The value to use for the HTSTFGAINEN field. + * @param[in] agcfsmreset - The value to use for the AGCFSMRESET field. + * @param[in] radardeten - The value to use for the RADARDETEN field. + * @param[in] rifsdeten - The value to use for the RIFSDETEN field. + * @param[in] dsssonly - The value to use for the DSSSONLY field. + * @param[in] ofdmonly - The value to use for the OFDMONLY field. + * @param[in] gpstatus - The value to use for the GPSTATUS field. + * @param[in] combpathsel - The value to use for the COMBPATHSEL field. + */ +__INLINE void agc_rwnxagccntl_pack(uint8_t htstfgainen, uint8_t agcfsmreset, uint8_t radardeten, uint8_t rifsdeten, uint8_t dsssonly, uint8_t ofdmonly, uint8_t gpstatus, uint8_t combpathsel) +{ + ASSERT_ERR((((uint32_t)htstfgainen << 16) & ~((uint32_t)0x00010000)) == 0); + ASSERT_ERR((((uint32_t)agcfsmreset << 12) & ~((uint32_t)0x00001000)) == 0); + ASSERT_ERR((((uint32_t)radardeten << 11) & ~((uint32_t)0x00000800)) == 0); + ASSERT_ERR((((uint32_t)rifsdeten << 10) & ~((uint32_t)0x00000400)) == 0); + ASSERT_ERR((((uint32_t)dsssonly << 9) & ~((uint32_t)0x00000200)) == 0); + ASSERT_ERR((((uint32_t)ofdmonly << 8) & ~((uint32_t)0x00000100)) == 0); + ASSERT_ERR((((uint32_t)gpstatus << 4) & ~((uint32_t)0x000000F0)) == 0); + ASSERT_ERR((((uint32_t)combpathsel << 0) & ~((uint32_t)0x0000000F)) == 0); + REG_PL_WR(AGC_RWNXAGCCNTL_ADDR, ((uint32_t)htstfgainen << 16) | ((uint32_t)agcfsmreset << 12) | ((uint32_t)radardeten << 11) | ((uint32_t)rifsdeten << 10) | ((uint32_t)dsssonly << 9) | ((uint32_t)ofdmonly << 8) | ((uint32_t)gpstatus << 4) | ((uint32_t)combpathsel << 0)); +} + +/** + * @brief Unpacks RWNXAGCCNTL's fields from current value of the RWNXAGCCNTL register. + * + * Reads the RWNXAGCCNTL register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] htstfgainen - Will be populated with the current value of this field from the register. + * @param[out] agcfsmreset - Will be populated with the current value of this field from the register. + * @param[out] radardeten - Will be populated with the current value of this field from the register. + * @param[out] rifsdeten - Will be populated with the current value of this field from the register. + * @param[out] dsssonly - Will be populated with the current value of this field from the register. + * @param[out] ofdmonly - Will be populated with the current value of this field from the register. + * @param[out] gpstatus - Will be populated with the current value of this field from the register. + * @param[out] combpathsel - Will be populated with the current value of this field from the register. + */ +__INLINE void agc_rwnxagccntl_unpack(uint8_t *htstfgainen, uint8_t *agcfsmreset, uint8_t *radardeten, uint8_t *rifsdeten, uint8_t *dsssonly, uint8_t *ofdmonly, uint8_t *gpstatus, uint8_t *combpathsel) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCCNTL_ADDR); + + *htstfgainen = (localVal & ((uint32_t)0x00010000)) >> 16; + *agcfsmreset = (localVal & ((uint32_t)0x00001000)) >> 12; + *radardeten = (localVal & ((uint32_t)0x00000800)) >> 11; + *rifsdeten = (localVal & ((uint32_t)0x00000400)) >> 10; + *dsssonly = (localVal & ((uint32_t)0x00000200)) >> 9; + *ofdmonly = (localVal & ((uint32_t)0x00000100)) >> 8; + *gpstatus = (localVal & ((uint32_t)0x000000F0)) >> 4; + *combpathsel = (localVal & ((uint32_t)0x0000000F)) >> 0; +} + +/** + * @brief Returns the current value of the HTSTFGAINEN field in the RWNXAGCCNTL register. + * + * The RWNXAGCCNTL register will be read and the HTSTFGAINEN field's value will be returned. + * + * @return The current value of the HTSTFGAINEN field in the RWNXAGCCNTL register. + */ +__INLINE uint8_t agc_htstfgainen_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCCNTL_ADDR); + return ((localVal & ((uint32_t)0x00010000)) >> 16); +} + +/** + * @brief Sets the HTSTFGAINEN field of the RWNXAGCCNTL register. + * + * The RWNXAGCCNTL register will be read, modified to contain the new field value, and written. + * + * @param[in] htstfgainen - The value to set the field to. + */ +__INLINE void agc_htstfgainen_setf(uint8_t htstfgainen) +{ + ASSERT_ERR((((uint32_t)htstfgainen << 16) & ~((uint32_t)0x00010000)) == 0); + REG_PL_WR(AGC_RWNXAGCCNTL_ADDR, (REG_PL_RD(AGC_RWNXAGCCNTL_ADDR) & ~((uint32_t)0x00010000)) | ((uint32_t)htstfgainen << 16)); +} + +/** + * @brief Returns the current value of the AGCFSMRESET field in the RWNXAGCCNTL register. + * + * The RWNXAGCCNTL register will be read and the AGCFSMRESET field's value will be returned. + * + * @return The current value of the AGCFSMRESET field in the RWNXAGCCNTL register. + */ +__INLINE uint8_t agc_agcfsmreset_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCCNTL_ADDR); + return ((localVal & ((uint32_t)0x00001000)) >> 12); +} + +/** + * @brief Sets the AGCFSMRESET field of the RWNXAGCCNTL register. + * + * The RWNXAGCCNTL register will be read, modified to contain the new field value, and written. + * + * @param[in] agcfsmreset - The value to set the field to. + */ +__INLINE void agc_agcfsmreset_setf(uint8_t agcfsmreset) +{ + ASSERT_ERR((((uint32_t)agcfsmreset << 12) & ~((uint32_t)0x00001000)) == 0); + REG_PL_WR(AGC_RWNXAGCCNTL_ADDR, (REG_PL_RD(AGC_RWNXAGCCNTL_ADDR) & ~((uint32_t)0x00001000)) | ((uint32_t)agcfsmreset << 12)); +} + +/** + * @brief Returns the current value of the RADARDETEN field in the RWNXAGCCNTL register. + * + * The RWNXAGCCNTL register will be read and the RADARDETEN field's value will be returned. + * + * @return The current value of the RADARDETEN field in the RWNXAGCCNTL register. + */ +__INLINE uint8_t agc_radardeten_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCCNTL_ADDR); + return ((localVal & ((uint32_t)0x00000800)) >> 11); +} + +/** + * @brief Sets the RADARDETEN field of the RWNXAGCCNTL register. + * + * The RWNXAGCCNTL register will be read, modified to contain the new field value, and written. + * + * @param[in] radardeten - The value to set the field to. + */ +__INLINE void agc_radardeten_setf(uint8_t radardeten) +{ + ASSERT_ERR((((uint32_t)radardeten << 11) & ~((uint32_t)0x00000800)) == 0); + REG_PL_WR(AGC_RWNXAGCCNTL_ADDR, (REG_PL_RD(AGC_RWNXAGCCNTL_ADDR) & ~((uint32_t)0x00000800)) | ((uint32_t)radardeten << 11)); +} + +/** + * @brief Returns the current value of the RIFSDETEN field in the RWNXAGCCNTL register. + * + * The RWNXAGCCNTL register will be read and the RIFSDETEN field's value will be returned. + * + * @return The current value of the RIFSDETEN field in the RWNXAGCCNTL register. + */ +__INLINE uint8_t agc_rifsdeten_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCCNTL_ADDR); + return ((localVal & ((uint32_t)0x00000400)) >> 10); +} + +/** + * @brief Sets the RIFSDETEN field of the RWNXAGCCNTL register. + * + * The RWNXAGCCNTL register will be read, modified to contain the new field value, and written. + * + * @param[in] rifsdeten - The value to set the field to. + */ +__INLINE void agc_rifsdeten_setf(uint8_t rifsdeten) +{ + ASSERT_ERR((((uint32_t)rifsdeten << 10) & ~((uint32_t)0x00000400)) == 0); + REG_PL_WR(AGC_RWNXAGCCNTL_ADDR, (REG_PL_RD(AGC_RWNXAGCCNTL_ADDR) & ~((uint32_t)0x00000400)) | ((uint32_t)rifsdeten << 10)); +} + +/** + * @brief Returns the current value of the DSSSONLY field in the RWNXAGCCNTL register. + * + * The RWNXAGCCNTL register will be read and the DSSSONLY field's value will be returned. + * + * @return The current value of the DSSSONLY field in the RWNXAGCCNTL register. + */ +__INLINE uint8_t agc_dsssonly_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCCNTL_ADDR); + return ((localVal & ((uint32_t)0x00000200)) >> 9); +} + +/** + * @brief Sets the DSSSONLY field of the RWNXAGCCNTL register. + * + * The RWNXAGCCNTL register will be read, modified to contain the new field value, and written. + * + * @param[in] dsssonly - The value to set the field to. + */ +__INLINE void agc_dsssonly_setf(uint8_t dsssonly) +{ + ASSERT_ERR((((uint32_t)dsssonly << 9) & ~((uint32_t)0x00000200)) == 0); + REG_PL_WR(AGC_RWNXAGCCNTL_ADDR, (REG_PL_RD(AGC_RWNXAGCCNTL_ADDR) & ~((uint32_t)0x00000200)) | ((uint32_t)dsssonly << 9)); +} + +/** + * @brief Returns the current value of the OFDMONLY field in the RWNXAGCCNTL register. + * + * The RWNXAGCCNTL register will be read and the OFDMONLY field's value will be returned. + * + * @return The current value of the OFDMONLY field in the RWNXAGCCNTL register. + */ +__INLINE uint8_t agc_ofdmonly_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCCNTL_ADDR); + return ((localVal & ((uint32_t)0x00000100)) >> 8); +} + +/** + * @brief Sets the OFDMONLY field of the RWNXAGCCNTL register. + * + * The RWNXAGCCNTL register will be read, modified to contain the new field value, and written. + * + * @param[in] ofdmonly - The value to set the field to. + */ +__INLINE void agc_ofdmonly_setf(uint8_t ofdmonly) +{ + ASSERT_ERR((((uint32_t)ofdmonly << 8) & ~((uint32_t)0x00000100)) == 0); + REG_PL_WR(AGC_RWNXAGCCNTL_ADDR, (REG_PL_RD(AGC_RWNXAGCCNTL_ADDR) & ~((uint32_t)0x00000100)) | ((uint32_t)ofdmonly << 8)); +} + +/** + * @brief Returns the current value of the GPSTATUS field in the RWNXAGCCNTL register. + * + * The RWNXAGCCNTL register will be read and the GPSTATUS field's value will be returned. + * + * @return The current value of the GPSTATUS field in the RWNXAGCCNTL register. + */ +__INLINE uint8_t agc_gpstatus_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCCNTL_ADDR); + return ((localVal & ((uint32_t)0x000000F0)) >> 4); +} + +/** + * @brief Sets the GPSTATUS field of the RWNXAGCCNTL register. + * + * The RWNXAGCCNTL register will be read, modified to contain the new field value, and written. + * + * @param[in] gpstatus - The value to set the field to. + */ +__INLINE void agc_gpstatus_setf(uint8_t gpstatus) +{ + ASSERT_ERR((((uint32_t)gpstatus << 4) & ~((uint32_t)0x000000F0)) == 0); + REG_PL_WR(AGC_RWNXAGCCNTL_ADDR, (REG_PL_RD(AGC_RWNXAGCCNTL_ADDR) & ~((uint32_t)0x000000F0)) | ((uint32_t)gpstatus << 4)); +} + +/** + * @brief Returns the current value of the COMBPATHSEL field in the RWNXAGCCNTL register. + * + * The RWNXAGCCNTL register will be read and the COMBPATHSEL field's value will be returned. + * + * @return The current value of the COMBPATHSEL field in the RWNXAGCCNTL register. + */ +__INLINE uint8_t agc_combpathsel_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCCNTL_ADDR); + return ((localVal & ((uint32_t)0x0000000F)) >> 0); +} + +/** + * @brief Sets the COMBPATHSEL field of the RWNXAGCCNTL register. + * + * The RWNXAGCCNTL register will be read, modified to contain the new field value, and written. + * + * @param[in] combpathsel - The value to set the field to. + */ +__INLINE void agc_combpathsel_setf(uint8_t combpathsel) +{ + ASSERT_ERR((((uint32_t)combpathsel << 0) & ~((uint32_t)0x0000000F)) == 0); + REG_PL_WR(AGC_RWNXAGCCNTL_ADDR, (REG_PL_RD(AGC_RWNXAGCCNTL_ADDR) & ~((uint32_t)0x0000000F)) | ((uint32_t)combpathsel << 0)); +} + +/// @} + +/** + * @name RWNXAGCDSP0 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  27:24              NBITADC   0xC
+ *  23:16         VPEAKADCQDBV   0xE8
+ *  15:08         ADCPOWMINDBV   0xCE
+ *  07:00        ADCPOWBIASQDB   0x0
+ * 
+ * + * @{ + */ + +/// Address of the RWNXAGCDSP0 register +#define AGC_RWNXAGCDSP0_ADDR 0x01002064 +/// Offset of the RWNXAGCDSP0 register from the base address +#define AGC_RWNXAGCDSP0_OFFSET 0x00002064 +/// Index of the RWNXAGCDSP0 register +#define AGC_RWNXAGCDSP0_INDEX 0x00000819 +/// Reset value of the RWNXAGCDSP0 register +#define AGC_RWNXAGCDSP0_RESET 0x0CE8CE00 + +/** + * @brief Returns the current value of the RWNXAGCDSP0 register. + * The RWNXAGCDSP0 register will be read and its value returned. + * @return The current value of the RWNXAGCDSP0 register. + */ +__INLINE uint32_t agc_rwnxagcdsp0_get(void) +{ + return REG_PL_RD(AGC_RWNXAGCDSP0_ADDR); +} + +/** + * @brief Sets the RWNXAGCDSP0 register to a value. + * The RWNXAGCDSP0 register will be written. + * @param value - The value to write. + */ +__INLINE void agc_rwnxagcdsp0_set(uint32_t value) +{ + REG_PL_WR(AGC_RWNXAGCDSP0_ADDR, value); +} + +// field definitions +/// NBITADC field mask +#define AGC_NBITADC_MASK ((uint32_t)0x0F000000) +/// NBITADC field LSB position +#define AGC_NBITADC_LSB 24 +/// NBITADC field width +#define AGC_NBITADC_WIDTH ((uint32_t)0x00000004) +/// VPEAKADCQDBV field mask +#define AGC_VPEAKADCQDBV_MASK ((uint32_t)0x00FF0000) +/// VPEAKADCQDBV field LSB position +#define AGC_VPEAKADCQDBV_LSB 16 +/// VPEAKADCQDBV field width +#define AGC_VPEAKADCQDBV_WIDTH ((uint32_t)0x00000008) +/// ADCPOWMINDBV field mask +#define AGC_ADCPOWMINDBV_MASK ((uint32_t)0x0000FF00) +/// ADCPOWMINDBV field LSB position +#define AGC_ADCPOWMINDBV_LSB 8 +/// ADCPOWMINDBV field width +#define AGC_ADCPOWMINDBV_WIDTH ((uint32_t)0x00000008) +/// ADCPOWBIASQDB field mask +#define AGC_ADCPOWBIASQDB_MASK ((uint32_t)0x000000FF) +/// ADCPOWBIASQDB field LSB position +#define AGC_ADCPOWBIASQDB_LSB 0 +/// ADCPOWBIASQDB field width +#define AGC_ADCPOWBIASQDB_WIDTH ((uint32_t)0x00000008) + +/// NBITADC field reset value +#define AGC_NBITADC_RST 0xC +/// VPEAKADCQDBV field reset value +#define AGC_VPEAKADCQDBV_RST 0xE8 +/// ADCPOWMINDBV field reset value +#define AGC_ADCPOWMINDBV_RST 0xCE +/// ADCPOWBIASQDB field reset value +#define AGC_ADCPOWBIASQDB_RST 0x0 + +/** + * @brief Constructs a value for the RWNXAGCDSP0 register given values for its fields + * and writes the value to the register. + * + * @param[in] nbitadc - The value to use for the NBITADC field. + * @param[in] vpeakadcqdbv - The value to use for the VPEAKADCQDBV field. + * @param[in] adcpowmindbv - The value to use for the ADCPOWMINDBV field. + * @param[in] adcpowbiasqdb - The value to use for the ADCPOWBIASQDB field. + */ +__INLINE void agc_rwnxagcdsp0_pack(uint8_t nbitadc, uint8_t vpeakadcqdbv, uint8_t adcpowmindbv, uint8_t adcpowbiasqdb) +{ + ASSERT_ERR((((uint32_t)nbitadc << 24) & ~((uint32_t)0x0F000000)) == 0); + ASSERT_ERR((((uint32_t)vpeakadcqdbv << 16) & ~((uint32_t)0x00FF0000)) == 0); + ASSERT_ERR((((uint32_t)adcpowmindbv << 8) & ~((uint32_t)0x0000FF00)) == 0); + ASSERT_ERR((((uint32_t)adcpowbiasqdb << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(AGC_RWNXAGCDSP0_ADDR, ((uint32_t)nbitadc << 24) | ((uint32_t)vpeakadcqdbv << 16) | ((uint32_t)adcpowmindbv << 8) | ((uint32_t)adcpowbiasqdb << 0)); +} + +/** + * @brief Unpacks RWNXAGCDSP0's fields from current value of the RWNXAGCDSP0 register. + * + * Reads the RWNXAGCDSP0 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] nbitadc - Will be populated with the current value of this field from the register. + * @param[out] vpeakadcqdbv - Will be populated with the current value of this field from the register. + * @param[out] adcpowmindbv - Will be populated with the current value of this field from the register. + * @param[out] adcpowbiasqdb - Will be populated with the current value of this field from the register. + */ +__INLINE void agc_rwnxagcdsp0_unpack(uint8_t *nbitadc, uint8_t *vpeakadcqdbv, uint8_t *adcpowmindbv, uint8_t *adcpowbiasqdb) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCDSP0_ADDR); + + *nbitadc = (localVal & ((uint32_t)0x0F000000)) >> 24; + *vpeakadcqdbv = (localVal & ((uint32_t)0x00FF0000)) >> 16; + *adcpowmindbv = (localVal & ((uint32_t)0x0000FF00)) >> 8; + *adcpowbiasqdb = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +/** + * @brief Returns the current value of the NBITADC field in the RWNXAGCDSP0 register. + * + * The RWNXAGCDSP0 register will be read and the NBITADC field's value will be returned. + * + * @return The current value of the NBITADC field in the RWNXAGCDSP0 register. + */ +__INLINE uint8_t agc_nbitadc_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCDSP0_ADDR); + return ((localVal & ((uint32_t)0x0F000000)) >> 24); +} + +/** + * @brief Sets the NBITADC field of the RWNXAGCDSP0 register. + * + * The RWNXAGCDSP0 register will be read, modified to contain the new field value, and written. + * + * @param[in] nbitadc - The value to set the field to. + */ +__INLINE void agc_nbitadc_setf(uint8_t nbitadc) +{ + ASSERT_ERR((((uint32_t)nbitadc << 24) & ~((uint32_t)0x0F000000)) == 0); + REG_PL_WR(AGC_RWNXAGCDSP0_ADDR, (REG_PL_RD(AGC_RWNXAGCDSP0_ADDR) & ~((uint32_t)0x0F000000)) | ((uint32_t)nbitadc << 24)); +} + +/** + * @brief Returns the current value of the VPEAKADCQDBV field in the RWNXAGCDSP0 register. + * + * The RWNXAGCDSP0 register will be read and the VPEAKADCQDBV field's value will be returned. + * + * @return The current value of the VPEAKADCQDBV field in the RWNXAGCDSP0 register. + */ +__INLINE uint8_t agc_vpeakadcqdbv_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCDSP0_ADDR); + return ((localVal & ((uint32_t)0x00FF0000)) >> 16); +} + +/** + * @brief Sets the VPEAKADCQDBV field of the RWNXAGCDSP0 register. + * + * The RWNXAGCDSP0 register will be read, modified to contain the new field value, and written. + * + * @param[in] vpeakadcqdbv - The value to set the field to. + */ +__INLINE void agc_vpeakadcqdbv_setf(uint8_t vpeakadcqdbv) +{ + ASSERT_ERR((((uint32_t)vpeakadcqdbv << 16) & ~((uint32_t)0x00FF0000)) == 0); + REG_PL_WR(AGC_RWNXAGCDSP0_ADDR, (REG_PL_RD(AGC_RWNXAGCDSP0_ADDR) & ~((uint32_t)0x00FF0000)) | ((uint32_t)vpeakadcqdbv << 16)); +} + +/** + * @brief Returns the current value of the ADCPOWMINDBV field in the RWNXAGCDSP0 register. + * + * The RWNXAGCDSP0 register will be read and the ADCPOWMINDBV field's value will be returned. + * + * @return The current value of the ADCPOWMINDBV field in the RWNXAGCDSP0 register. + */ +__INLINE uint8_t agc_adcpowmindbv_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCDSP0_ADDR); + return ((localVal & ((uint32_t)0x0000FF00)) >> 8); +} + +/** + * @brief Sets the ADCPOWMINDBV field of the RWNXAGCDSP0 register. + * + * The RWNXAGCDSP0 register will be read, modified to contain the new field value, and written. + * + * @param[in] adcpowmindbv - The value to set the field to. + */ +__INLINE void agc_adcpowmindbv_setf(uint8_t adcpowmindbv) +{ + ASSERT_ERR((((uint32_t)adcpowmindbv << 8) & ~((uint32_t)0x0000FF00)) == 0); + REG_PL_WR(AGC_RWNXAGCDSP0_ADDR, (REG_PL_RD(AGC_RWNXAGCDSP0_ADDR) & ~((uint32_t)0x0000FF00)) | ((uint32_t)adcpowmindbv << 8)); +} + +/** + * @brief Returns the current value of the ADCPOWBIASQDB field in the RWNXAGCDSP0 register. + * + * The RWNXAGCDSP0 register will be read and the ADCPOWBIASQDB field's value will be returned. + * + * @return The current value of the ADCPOWBIASQDB field in the RWNXAGCDSP0 register. + */ +__INLINE uint8_t agc_adcpowbiasqdb_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCDSP0_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +/** + * @brief Sets the ADCPOWBIASQDB field of the RWNXAGCDSP0 register. + * + * The RWNXAGCDSP0 register will be read, modified to contain the new field value, and written. + * + * @param[in] adcpowbiasqdb - The value to set the field to. + */ +__INLINE void agc_adcpowbiasqdb_setf(uint8_t adcpowbiasqdb) +{ + ASSERT_ERR((((uint32_t)adcpowbiasqdb << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(AGC_RWNXAGCDSP0_ADDR, (REG_PL_RD(AGC_RWNXAGCDSP0_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)adcpowbiasqdb << 0)); +} + +/// @} + +/** + * @name RWNXAGCDSP1 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  29:28              INBDRND   0x3
+ *  23:16    INBDPOW40SBIASQDB   0x0
+ *  15:08    INBDPOW20SBIASQDB   0x0
+ *  07:00    INBDPOW20PBIASQDB   0x0
+ * 
+ * + * @{ + */ + +/// Address of the RWNXAGCDSP1 register +#define AGC_RWNXAGCDSP1_ADDR 0x01002068 +/// Offset of the RWNXAGCDSP1 register from the base address +#define AGC_RWNXAGCDSP1_OFFSET 0x00002068 +/// Index of the RWNXAGCDSP1 register +#define AGC_RWNXAGCDSP1_INDEX 0x0000081A +/// Reset value of the RWNXAGCDSP1 register +#define AGC_RWNXAGCDSP1_RESET 0x30000000 + +/** + * @brief Returns the current value of the RWNXAGCDSP1 register. + * The RWNXAGCDSP1 register will be read and its value returned. + * @return The current value of the RWNXAGCDSP1 register. + */ +__INLINE uint32_t agc_rwnxagcdsp1_get(void) +{ + return REG_PL_RD(AGC_RWNXAGCDSP1_ADDR); +} + +/** + * @brief Sets the RWNXAGCDSP1 register to a value. + * The RWNXAGCDSP1 register will be written. + * @param value - The value to write. + */ +__INLINE void agc_rwnxagcdsp1_set(uint32_t value) +{ + REG_PL_WR(AGC_RWNXAGCDSP1_ADDR, value); +} + +// field definitions +/// INBDRND field mask +#define AGC_INBDRND_MASK ((uint32_t)0x30000000) +/// INBDRND field LSB position +#define AGC_INBDRND_LSB 28 +/// INBDRND field width +#define AGC_INBDRND_WIDTH ((uint32_t)0x00000002) +/// INBDPOW40SBIASQDB field mask +#define AGC_INBDPOW40SBIASQDB_MASK ((uint32_t)0x00FF0000) +/// INBDPOW40SBIASQDB field LSB position +#define AGC_INBDPOW40SBIASQDB_LSB 16 +/// INBDPOW40SBIASQDB field width +#define AGC_INBDPOW40SBIASQDB_WIDTH ((uint32_t)0x00000008) +/// INBDPOW20SBIASQDB field mask +#define AGC_INBDPOW20SBIASQDB_MASK ((uint32_t)0x0000FF00) +/// INBDPOW20SBIASQDB field LSB position +#define AGC_INBDPOW20SBIASQDB_LSB 8 +/// INBDPOW20SBIASQDB field width +#define AGC_INBDPOW20SBIASQDB_WIDTH ((uint32_t)0x00000008) +/// INBDPOW20PBIASQDB field mask +#define AGC_INBDPOW20PBIASQDB_MASK ((uint32_t)0x000000FF) +/// INBDPOW20PBIASQDB field LSB position +#define AGC_INBDPOW20PBIASQDB_LSB 0 +/// INBDPOW20PBIASQDB field width +#define AGC_INBDPOW20PBIASQDB_WIDTH ((uint32_t)0x00000008) + +/// INBDRND field reset value +#define AGC_INBDRND_RST 0x3 +/// INBDPOW40SBIASQDB field reset value +#define AGC_INBDPOW40SBIASQDB_RST 0x0 +/// INBDPOW20SBIASQDB field reset value +#define AGC_INBDPOW20SBIASQDB_RST 0x0 +/// INBDPOW20PBIASQDB field reset value +#define AGC_INBDPOW20PBIASQDB_RST 0x0 + +/** + * @brief Constructs a value for the RWNXAGCDSP1 register given values for its fields + * and writes the value to the register. + * + * @param[in] inbdrnd - The value to use for the INBDRND field. + * @param[in] inbdpow40sbiasqdb - The value to use for the INBDPOW40SBIASQDB field. + * @param[in] inbdpow20sbiasqdb - The value to use for the INBDPOW20SBIASQDB field. + * @param[in] inbdpow20pbiasqdb - The value to use for the INBDPOW20PBIASQDB field. + */ +__INLINE void agc_rwnxagcdsp1_pack(uint8_t inbdrnd, uint8_t inbdpow40sbiasqdb, uint8_t inbdpow20sbiasqdb, uint8_t inbdpow20pbiasqdb) +{ + ASSERT_ERR((((uint32_t)inbdrnd << 28) & ~((uint32_t)0x30000000)) == 0); + ASSERT_ERR((((uint32_t)inbdpow40sbiasqdb << 16) & ~((uint32_t)0x00FF0000)) == 0); + ASSERT_ERR((((uint32_t)inbdpow20sbiasqdb << 8) & ~((uint32_t)0x0000FF00)) == 0); + ASSERT_ERR((((uint32_t)inbdpow20pbiasqdb << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(AGC_RWNXAGCDSP1_ADDR, ((uint32_t)inbdrnd << 28) | ((uint32_t)inbdpow40sbiasqdb << 16) | ((uint32_t)inbdpow20sbiasqdb << 8) | ((uint32_t)inbdpow20pbiasqdb << 0)); +} + +/** + * @brief Unpacks RWNXAGCDSP1's fields from current value of the RWNXAGCDSP1 register. + * + * Reads the RWNXAGCDSP1 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] inbdrnd - Will be populated with the current value of this field from the register. + * @param[out] inbdpow40sbiasqdb - Will be populated with the current value of this field from the register. + * @param[out] inbdpow20sbiasqdb - Will be populated with the current value of this field from the register. + * @param[out] inbdpow20pbiasqdb - Will be populated with the current value of this field from the register. + */ +__INLINE void agc_rwnxagcdsp1_unpack(uint8_t *inbdrnd, uint8_t *inbdpow40sbiasqdb, uint8_t *inbdpow20sbiasqdb, uint8_t *inbdpow20pbiasqdb) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCDSP1_ADDR); + + *inbdrnd = (localVal & ((uint32_t)0x30000000)) >> 28; + *inbdpow40sbiasqdb = (localVal & ((uint32_t)0x00FF0000)) >> 16; + *inbdpow20sbiasqdb = (localVal & ((uint32_t)0x0000FF00)) >> 8; + *inbdpow20pbiasqdb = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +/** + * @brief Returns the current value of the INBDRND field in the RWNXAGCDSP1 register. + * + * The RWNXAGCDSP1 register will be read and the INBDRND field's value will be returned. + * + * @return The current value of the INBDRND field in the RWNXAGCDSP1 register. + */ +__INLINE uint8_t agc_inbdrnd_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCDSP1_ADDR); + return ((localVal & ((uint32_t)0x30000000)) >> 28); +} + +/** + * @brief Sets the INBDRND field of the RWNXAGCDSP1 register. + * + * The RWNXAGCDSP1 register will be read, modified to contain the new field value, and written. + * + * @param[in] inbdrnd - The value to set the field to. + */ +__INLINE void agc_inbdrnd_setf(uint8_t inbdrnd) +{ + ASSERT_ERR((((uint32_t)inbdrnd << 28) & ~((uint32_t)0x30000000)) == 0); + REG_PL_WR(AGC_RWNXAGCDSP1_ADDR, (REG_PL_RD(AGC_RWNXAGCDSP1_ADDR) & ~((uint32_t)0x30000000)) | ((uint32_t)inbdrnd << 28)); +} + +/** + * @brief Returns the current value of the INBDPOW40SBIASQDB field in the RWNXAGCDSP1 register. + * + * The RWNXAGCDSP1 register will be read and the INBDPOW40SBIASQDB field's value will be returned. + * + * @return The current value of the INBDPOW40SBIASQDB field in the RWNXAGCDSP1 register. + */ +__INLINE uint8_t agc_inbdpow40sbiasqdb_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCDSP1_ADDR); + return ((localVal & ((uint32_t)0x00FF0000)) >> 16); +} + +/** + * @brief Sets the INBDPOW40SBIASQDB field of the RWNXAGCDSP1 register. + * + * The RWNXAGCDSP1 register will be read, modified to contain the new field value, and written. + * + * @param[in] inbdpow40sbiasqdb - The value to set the field to. + */ +__INLINE void agc_inbdpow40sbiasqdb_setf(uint8_t inbdpow40sbiasqdb) +{ + ASSERT_ERR((((uint32_t)inbdpow40sbiasqdb << 16) & ~((uint32_t)0x00FF0000)) == 0); + REG_PL_WR(AGC_RWNXAGCDSP1_ADDR, (REG_PL_RD(AGC_RWNXAGCDSP1_ADDR) & ~((uint32_t)0x00FF0000)) | ((uint32_t)inbdpow40sbiasqdb << 16)); +} + +/** + * @brief Returns the current value of the INBDPOW20SBIASQDB field in the RWNXAGCDSP1 register. + * + * The RWNXAGCDSP1 register will be read and the INBDPOW20SBIASQDB field's value will be returned. + * + * @return The current value of the INBDPOW20SBIASQDB field in the RWNXAGCDSP1 register. + */ +__INLINE uint8_t agc_inbdpow20sbiasqdb_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCDSP1_ADDR); + return ((localVal & ((uint32_t)0x0000FF00)) >> 8); +} + +/** + * @brief Sets the INBDPOW20SBIASQDB field of the RWNXAGCDSP1 register. + * + * The RWNXAGCDSP1 register will be read, modified to contain the new field value, and written. + * + * @param[in] inbdpow20sbiasqdb - The value to set the field to. + */ +__INLINE void agc_inbdpow20sbiasqdb_setf(uint8_t inbdpow20sbiasqdb) +{ + ASSERT_ERR((((uint32_t)inbdpow20sbiasqdb << 8) & ~((uint32_t)0x0000FF00)) == 0); + REG_PL_WR(AGC_RWNXAGCDSP1_ADDR, (REG_PL_RD(AGC_RWNXAGCDSP1_ADDR) & ~((uint32_t)0x0000FF00)) | ((uint32_t)inbdpow20sbiasqdb << 8)); +} + +/** + * @brief Returns the current value of the INBDPOW20PBIASQDB field in the RWNXAGCDSP1 register. + * + * The RWNXAGCDSP1 register will be read and the INBDPOW20PBIASQDB field's value will be returned. + * + * @return The current value of the INBDPOW20PBIASQDB field in the RWNXAGCDSP1 register. + */ +__INLINE uint8_t agc_inbdpow20pbiasqdb_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCDSP1_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +/** + * @brief Sets the INBDPOW20PBIASQDB field of the RWNXAGCDSP1 register. + * + * The RWNXAGCDSP1 register will be read, modified to contain the new field value, and written. + * + * @param[in] inbdpow20pbiasqdb - The value to set the field to. + */ +__INLINE void agc_inbdpow20pbiasqdb_setf(uint8_t inbdpow20pbiasqdb) +{ + ASSERT_ERR((((uint32_t)inbdpow20pbiasqdb << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(AGC_RWNXAGCDSP1_ADDR, (REG_PL_RD(AGC_RWNXAGCDSP1_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)inbdpow20pbiasqdb << 0)); +} + +/// @} + +/** + * @name RWNXAGCDSP2 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  24:16        INBDPOWMINDBM   0x19C
+ *  15:08             FE40GAIN   0x2
+ *  07:00             FE20GAIN   0x2
+ * 
+ * + * @{ + */ + +/// Address of the RWNXAGCDSP2 register +#define AGC_RWNXAGCDSP2_ADDR 0x0100206C +/// Offset of the RWNXAGCDSP2 register from the base address +#define AGC_RWNXAGCDSP2_OFFSET 0x0000206C +/// Index of the RWNXAGCDSP2 register +#define AGC_RWNXAGCDSP2_INDEX 0x0000081B +/// Reset value of the RWNXAGCDSP2 register +#define AGC_RWNXAGCDSP2_RESET 0x019C0202 + +/** + * @brief Returns the current value of the RWNXAGCDSP2 register. + * The RWNXAGCDSP2 register will be read and its value returned. + * @return The current value of the RWNXAGCDSP2 register. + */ +__INLINE uint32_t agc_rwnxagcdsp2_get(void) +{ + return REG_PL_RD(AGC_RWNXAGCDSP2_ADDR); +} + +/** + * @brief Sets the RWNXAGCDSP2 register to a value. + * The RWNXAGCDSP2 register will be written. + * @param value - The value to write. + */ +__INLINE void agc_rwnxagcdsp2_set(uint32_t value) +{ + REG_PL_WR(AGC_RWNXAGCDSP2_ADDR, value); +} + +// field definitions +/// INBDPOWMINDBM field mask +#define AGC_INBDPOWMINDBM_MASK ((uint32_t)0x01FF0000) +/// INBDPOWMINDBM field LSB position +#define AGC_INBDPOWMINDBM_LSB 16 +/// INBDPOWMINDBM field width +#define AGC_INBDPOWMINDBM_WIDTH ((uint32_t)0x00000009) +/// FE40GAIN field mask +#define AGC_FE40GAIN_MASK ((uint32_t)0x0000FF00) +/// FE40GAIN field LSB position +#define AGC_FE40GAIN_LSB 8 +/// FE40GAIN field width +#define AGC_FE40GAIN_WIDTH ((uint32_t)0x00000008) +/// FE20GAIN field mask +#define AGC_FE20GAIN_MASK ((uint32_t)0x000000FF) +/// FE20GAIN field LSB position +#define AGC_FE20GAIN_LSB 0 +/// FE20GAIN field width +#define AGC_FE20GAIN_WIDTH ((uint32_t)0x00000008) + +/// INBDPOWMINDBM field reset value +#define AGC_INBDPOWMINDBM_RST 0x19C +/// FE40GAIN field reset value +#define AGC_FE40GAIN_RST 0x2 +/// FE20GAIN field reset value +#define AGC_FE20GAIN_RST 0x2 + +/** + * @brief Constructs a value for the RWNXAGCDSP2 register given values for its fields + * and writes the value to the register. + * + * @param[in] inbdpowmindbm - The value to use for the INBDPOWMINDBM field. + * @param[in] fe40gain - The value to use for the FE40GAIN field. + * @param[in] fe20gain - The value to use for the FE20GAIN field. + */ +__INLINE void agc_rwnxagcdsp2_pack(uint16_t inbdpowmindbm, uint8_t fe40gain, uint8_t fe20gain) +{ + ASSERT_ERR((((uint32_t)inbdpowmindbm << 16) & ~((uint32_t)0x01FF0000)) == 0); + ASSERT_ERR((((uint32_t)fe40gain << 8) & ~((uint32_t)0x0000FF00)) == 0); + ASSERT_ERR((((uint32_t)fe20gain << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(AGC_RWNXAGCDSP2_ADDR, ((uint32_t)inbdpowmindbm << 16) | ((uint32_t)fe40gain << 8) | ((uint32_t)fe20gain << 0)); +} + +/** + * @brief Unpacks RWNXAGCDSP2's fields from current value of the RWNXAGCDSP2 register. + * + * Reads the RWNXAGCDSP2 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] inbdpowmindbm - Will be populated with the current value of this field from the register. + * @param[out] fe40gain - Will be populated with the current value of this field from the register. + * @param[out] fe20gain - Will be populated with the current value of this field from the register. + */ +__INLINE void agc_rwnxagcdsp2_unpack(uint16_t *inbdpowmindbm, uint8_t *fe40gain, uint8_t *fe20gain) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCDSP2_ADDR); + + *inbdpowmindbm = (localVal & ((uint32_t)0x01FF0000)) >> 16; + *fe40gain = (localVal & ((uint32_t)0x0000FF00)) >> 8; + *fe20gain = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +/** + * @brief Returns the current value of the INBDPOWMINDBM field in the RWNXAGCDSP2 register. + * + * The RWNXAGCDSP2 register will be read and the INBDPOWMINDBM field's value will be returned. + * + * @return The current value of the INBDPOWMINDBM field in the RWNXAGCDSP2 register. + */ +__INLINE uint16_t agc_inbdpowmindbm_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCDSP2_ADDR); + return ((localVal & ((uint32_t)0x01FF0000)) >> 16); +} + +/** + * @brief Sets the INBDPOWMINDBM field of the RWNXAGCDSP2 register. + * + * The RWNXAGCDSP2 register will be read, modified to contain the new field value, and written. + * + * @param[in] inbdpowmindbm - The value to set the field to. + */ +__INLINE void agc_inbdpowmindbm_setf(uint16_t inbdpowmindbm) +{ + ASSERT_ERR((((uint32_t)inbdpowmindbm << 16) & ~((uint32_t)0x01FF0000)) == 0); + REG_PL_WR(AGC_RWNXAGCDSP2_ADDR, (REG_PL_RD(AGC_RWNXAGCDSP2_ADDR) & ~((uint32_t)0x01FF0000)) | ((uint32_t)inbdpowmindbm << 16)); +} + +/** + * @brief Returns the current value of the FE40GAIN field in the RWNXAGCDSP2 register. + * + * The RWNXAGCDSP2 register will be read and the FE40GAIN field's value will be returned. + * + * @return The current value of the FE40GAIN field in the RWNXAGCDSP2 register. + */ +__INLINE uint8_t agc_fe40gain_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCDSP2_ADDR); + return ((localVal & ((uint32_t)0x0000FF00)) >> 8); +} + +/** + * @brief Sets the FE40GAIN field of the RWNXAGCDSP2 register. + * + * The RWNXAGCDSP2 register will be read, modified to contain the new field value, and written. + * + * @param[in] fe40gain - The value to set the field to. + */ +__INLINE void agc_fe40gain_setf(uint8_t fe40gain) +{ + ASSERT_ERR((((uint32_t)fe40gain << 8) & ~((uint32_t)0x0000FF00)) == 0); + REG_PL_WR(AGC_RWNXAGCDSP2_ADDR, (REG_PL_RD(AGC_RWNXAGCDSP2_ADDR) & ~((uint32_t)0x0000FF00)) | ((uint32_t)fe40gain << 8)); +} + +/** + * @brief Returns the current value of the FE20GAIN field in the RWNXAGCDSP2 register. + * + * The RWNXAGCDSP2 register will be read and the FE20GAIN field's value will be returned. + * + * @return The current value of the FE20GAIN field in the RWNXAGCDSP2 register. + */ +__INLINE uint8_t agc_fe20gain_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCDSP2_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +/** + * @brief Sets the FE20GAIN field of the RWNXAGCDSP2 register. + * + * The RWNXAGCDSP2 register will be read, modified to contain the new field value, and written. + * + * @param[in] fe20gain - The value to set the field to. + */ +__INLINE void agc_fe20gain_setf(uint8_t fe20gain) +{ + ASSERT_ERR((((uint32_t)fe20gain << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(AGC_RWNXAGCDSP2_ADDR, (REG_PL_RD(AGC_RWNXAGCDSP2_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)fe20gain << 0)); +} + +/// @} + +/** + * @name RWNXAGCCCA0 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  22:20      DELCCARAMPDNTAP   0x5
+ *  18:16      DELCCARAMPUPTAP   0x5
+ *  13:08         CCADETRAMPDN   0x9
+ *  05:00         CCADETRAMPUP   0x9
+ * 
+ * + * @{ + */ + +/// Address of the RWNXAGCCCA0 register +#define AGC_RWNXAGCCCA0_ADDR 0x01002070 +/// Offset of the RWNXAGCCCA0 register from the base address +#define AGC_RWNXAGCCCA0_OFFSET 0x00002070 +/// Index of the RWNXAGCCCA0 register +#define AGC_RWNXAGCCCA0_INDEX 0x0000081C +/// Reset value of the RWNXAGCCCA0 register +#define AGC_RWNXAGCCCA0_RESET 0x00550909 + +/** + * @brief Returns the current value of the RWNXAGCCCA0 register. + * The RWNXAGCCCA0 register will be read and its value returned. + * @return The current value of the RWNXAGCCCA0 register. + */ +__INLINE uint32_t agc_rwnxagccca0_get(void) +{ + return REG_PL_RD(AGC_RWNXAGCCCA0_ADDR); +} + +/** + * @brief Sets the RWNXAGCCCA0 register to a value. + * The RWNXAGCCCA0 register will be written. + * @param value - The value to write. + */ +__INLINE void agc_rwnxagccca0_set(uint32_t value) +{ + REG_PL_WR(AGC_RWNXAGCCCA0_ADDR, value); +} + +// field definitions +/// DELCCARAMPDNTAP field mask +#define AGC_DELCCARAMPDNTAP_MASK ((uint32_t)0x00700000) +/// DELCCARAMPDNTAP field LSB position +#define AGC_DELCCARAMPDNTAP_LSB 20 +/// DELCCARAMPDNTAP field width +#define AGC_DELCCARAMPDNTAP_WIDTH ((uint32_t)0x00000003) +/// DELCCARAMPUPTAP field mask +#define AGC_DELCCARAMPUPTAP_MASK ((uint32_t)0x00070000) +/// DELCCARAMPUPTAP field LSB position +#define AGC_DELCCARAMPUPTAP_LSB 16 +/// DELCCARAMPUPTAP field width +#define AGC_DELCCARAMPUPTAP_WIDTH ((uint32_t)0x00000003) +/// CCADETRAMPDN field mask +#define AGC_CCADETRAMPDN_MASK ((uint32_t)0x00003F00) +/// CCADETRAMPDN field LSB position +#define AGC_CCADETRAMPDN_LSB 8 +/// CCADETRAMPDN field width +#define AGC_CCADETRAMPDN_WIDTH ((uint32_t)0x00000006) +/// CCADETRAMPUP field mask +#define AGC_CCADETRAMPUP_MASK ((uint32_t)0x0000003F) +/// CCADETRAMPUP field LSB position +#define AGC_CCADETRAMPUP_LSB 0 +/// CCADETRAMPUP field width +#define AGC_CCADETRAMPUP_WIDTH ((uint32_t)0x00000006) + +/// DELCCARAMPDNTAP field reset value +#define AGC_DELCCARAMPDNTAP_RST 0x5 +/// DELCCARAMPUPTAP field reset value +#define AGC_DELCCARAMPUPTAP_RST 0x5 +/// CCADETRAMPDN field reset value +#define AGC_CCADETRAMPDN_RST 0x9 +/// CCADETRAMPUP field reset value +#define AGC_CCADETRAMPUP_RST 0x9 + +/** + * @brief Constructs a value for the RWNXAGCCCA0 register given values for its fields + * and writes the value to the register. + * + * @param[in] delccarampdntap - The value to use for the DELCCARAMPDNTAP field. + * @param[in] delccarampuptap - The value to use for the DELCCARAMPUPTAP field. + * @param[in] ccadetrampdn - The value to use for the CCADETRAMPDN field. + * @param[in] ccadetrampup - The value to use for the CCADETRAMPUP field. + */ +__INLINE void agc_rwnxagccca0_pack(uint8_t delccarampdntap, uint8_t delccarampuptap, uint8_t ccadetrampdn, uint8_t ccadetrampup) +{ + ASSERT_ERR((((uint32_t)delccarampdntap << 20) & ~((uint32_t)0x00700000)) == 0); + ASSERT_ERR((((uint32_t)delccarampuptap << 16) & ~((uint32_t)0x00070000)) == 0); + ASSERT_ERR((((uint32_t)ccadetrampdn << 8) & ~((uint32_t)0x00003F00)) == 0); + ASSERT_ERR((((uint32_t)ccadetrampup << 0) & ~((uint32_t)0x0000003F)) == 0); + REG_PL_WR(AGC_RWNXAGCCCA0_ADDR, ((uint32_t)delccarampdntap << 20) | ((uint32_t)delccarampuptap << 16) | ((uint32_t)ccadetrampdn << 8) | ((uint32_t)ccadetrampup << 0)); +} + +/** + * @brief Unpacks RWNXAGCCCA0's fields from current value of the RWNXAGCCCA0 register. + * + * Reads the RWNXAGCCCA0 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] delccarampdntap - Will be populated with the current value of this field from the register. + * @param[out] delccarampuptap - Will be populated with the current value of this field from the register. + * @param[out] ccadetrampdn - Will be populated with the current value of this field from the register. + * @param[out] ccadetrampup - Will be populated with the current value of this field from the register. + */ +__INLINE void agc_rwnxagccca0_unpack(uint8_t *delccarampdntap, uint8_t *delccarampuptap, uint8_t *ccadetrampdn, uint8_t *ccadetrampup) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCCCA0_ADDR); + + *delccarampdntap = (localVal & ((uint32_t)0x00700000)) >> 20; + *delccarampuptap = (localVal & ((uint32_t)0x00070000)) >> 16; + *ccadetrampdn = (localVal & ((uint32_t)0x00003F00)) >> 8; + *ccadetrampup = (localVal & ((uint32_t)0x0000003F)) >> 0; +} + +/** + * @brief Returns the current value of the DELCCARAMPDNTAP field in the RWNXAGCCCA0 register. + * + * The RWNXAGCCCA0 register will be read and the DELCCARAMPDNTAP field's value will be returned. + * + * @return The current value of the DELCCARAMPDNTAP field in the RWNXAGCCCA0 register. + */ +__INLINE uint8_t agc_delccarampdntap_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCCCA0_ADDR); + return ((localVal & ((uint32_t)0x00700000)) >> 20); +} + +/** + * @brief Sets the DELCCARAMPDNTAP field of the RWNXAGCCCA0 register. + * + * The RWNXAGCCCA0 register will be read, modified to contain the new field value, and written. + * + * @param[in] delccarampdntap - The value to set the field to. + */ +__INLINE void agc_delccarampdntap_setf(uint8_t delccarampdntap) +{ + ASSERT_ERR((((uint32_t)delccarampdntap << 20) & ~((uint32_t)0x00700000)) == 0); + REG_PL_WR(AGC_RWNXAGCCCA0_ADDR, (REG_PL_RD(AGC_RWNXAGCCCA0_ADDR) & ~((uint32_t)0x00700000)) | ((uint32_t)delccarampdntap << 20)); +} + +/** + * @brief Returns the current value of the DELCCARAMPUPTAP field in the RWNXAGCCCA0 register. + * + * The RWNXAGCCCA0 register will be read and the DELCCARAMPUPTAP field's value will be returned. + * + * @return The current value of the DELCCARAMPUPTAP field in the RWNXAGCCCA0 register. + */ +__INLINE uint8_t agc_delccarampuptap_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCCCA0_ADDR); + return ((localVal & ((uint32_t)0x00070000)) >> 16); +} + +/** + * @brief Sets the DELCCARAMPUPTAP field of the RWNXAGCCCA0 register. + * + * The RWNXAGCCCA0 register will be read, modified to contain the new field value, and written. + * + * @param[in] delccarampuptap - The value to set the field to. + */ +__INLINE void agc_delccarampuptap_setf(uint8_t delccarampuptap) +{ + ASSERT_ERR((((uint32_t)delccarampuptap << 16) & ~((uint32_t)0x00070000)) == 0); + REG_PL_WR(AGC_RWNXAGCCCA0_ADDR, (REG_PL_RD(AGC_RWNXAGCCCA0_ADDR) & ~((uint32_t)0x00070000)) | ((uint32_t)delccarampuptap << 16)); +} + +/** + * @brief Returns the current value of the CCADETRAMPDN field in the RWNXAGCCCA0 register. + * + * The RWNXAGCCCA0 register will be read and the CCADETRAMPDN field's value will be returned. + * + * @return The current value of the CCADETRAMPDN field in the RWNXAGCCCA0 register. + */ +__INLINE uint8_t agc_ccadetrampdn_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCCCA0_ADDR); + return ((localVal & ((uint32_t)0x00003F00)) >> 8); +} + +/** + * @brief Sets the CCADETRAMPDN field of the RWNXAGCCCA0 register. + * + * The RWNXAGCCCA0 register will be read, modified to contain the new field value, and written. + * + * @param[in] ccadetrampdn - The value to set the field to. + */ +__INLINE void agc_ccadetrampdn_setf(uint8_t ccadetrampdn) +{ + ASSERT_ERR((((uint32_t)ccadetrampdn << 8) & ~((uint32_t)0x00003F00)) == 0); + REG_PL_WR(AGC_RWNXAGCCCA0_ADDR, (REG_PL_RD(AGC_RWNXAGCCCA0_ADDR) & ~((uint32_t)0x00003F00)) | ((uint32_t)ccadetrampdn << 8)); +} + +/** + * @brief Returns the current value of the CCADETRAMPUP field in the RWNXAGCCCA0 register. + * + * The RWNXAGCCCA0 register will be read and the CCADETRAMPUP field's value will be returned. + * + * @return The current value of the CCADETRAMPUP field in the RWNXAGCCCA0 register. + */ +__INLINE uint8_t agc_ccadetrampup_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCCCA0_ADDR); + return ((localVal & ((uint32_t)0x0000003F)) >> 0); +} + +/** + * @brief Sets the CCADETRAMPUP field of the RWNXAGCCCA0 register. + * + * The RWNXAGCCCA0 register will be read, modified to contain the new field value, and written. + * + * @param[in] ccadetrampup - The value to set the field to. + */ +__INLINE void agc_ccadetrampup_setf(uint8_t ccadetrampup) +{ + ASSERT_ERR((((uint32_t)ccadetrampup << 0) & ~((uint32_t)0x0000003F)) == 0); + REG_PL_WR(AGC_RWNXAGCCCA0_ADDR, (REG_PL_RD(AGC_RWNXAGCCCA0_ADDR) & ~((uint32_t)0x0000003F)) | ((uint32_t)ccadetrampup << 0)); +} + +/// @} + +/** + * @name RWNXAGCCCA1 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  28:20     INBDCCAPOWMINDBM   0x1B5
+ *  19:12        CCAFALLTHRDBM   0xBF
+ *     09             DISCCAEN   1
+ *     08             SATCCAEN   1
+ *  07:00        CCARISETHRDBM   0xC2
+ * 
+ * + * @{ + */ + +/// Address of the RWNXAGCCCA1 register +#define AGC_RWNXAGCCCA1_ADDR 0x01002074 +/// Offset of the RWNXAGCCCA1 register from the base address +#define AGC_RWNXAGCCCA1_OFFSET 0x00002074 +/// Index of the RWNXAGCCCA1 register +#define AGC_RWNXAGCCCA1_INDEX 0x0000081D +/// Reset value of the RWNXAGCCCA1 register +#define AGC_RWNXAGCCCA1_RESET 0x1B5BF3C2 + +/** + * @brief Returns the current value of the RWNXAGCCCA1 register. + * The RWNXAGCCCA1 register will be read and its value returned. + * @return The current value of the RWNXAGCCCA1 register. + */ +__INLINE uint32_t agc_rwnxagccca1_get(void) +{ + return REG_PL_RD(AGC_RWNXAGCCCA1_ADDR); +} + +/** + * @brief Sets the RWNXAGCCCA1 register to a value. + * The RWNXAGCCCA1 register will be written. + * @param value - The value to write. + */ +__INLINE void agc_rwnxagccca1_set(uint32_t value) +{ + REG_PL_WR(AGC_RWNXAGCCCA1_ADDR, value); +} + +// field definitions +/// INBDCCAPOWMINDBM field mask +#define AGC_INBDCCAPOWMINDBM_MASK ((uint32_t)0x1FF00000) +/// INBDCCAPOWMINDBM field LSB position +#define AGC_INBDCCAPOWMINDBM_LSB 20 +/// INBDCCAPOWMINDBM field width +#define AGC_INBDCCAPOWMINDBM_WIDTH ((uint32_t)0x00000009) +/// CCAFALLTHRDBM field mask +#define AGC_CCAFALLTHRDBM_MASK ((uint32_t)0x000FF000) +/// CCAFALLTHRDBM field LSB position +#define AGC_CCAFALLTHRDBM_LSB 12 +/// CCAFALLTHRDBM field width +#define AGC_CCAFALLTHRDBM_WIDTH ((uint32_t)0x00000008) +/// DISCCAEN field bit +#define AGC_DISCCAEN_BIT ((uint32_t)0x00000200) +/// DISCCAEN field position +#define AGC_DISCCAEN_POS 9 +/// SATCCAEN field bit +#define AGC_SATCCAEN_BIT ((uint32_t)0x00000100) +/// SATCCAEN field position +#define AGC_SATCCAEN_POS 8 +/// CCARISETHRDBM field mask +#define AGC_CCARISETHRDBM_MASK ((uint32_t)0x000000FF) +/// CCARISETHRDBM field LSB position +#define AGC_CCARISETHRDBM_LSB 0 +/// CCARISETHRDBM field width +#define AGC_CCARISETHRDBM_WIDTH ((uint32_t)0x00000008) + +/// INBDCCAPOWMINDBM field reset value +#define AGC_INBDCCAPOWMINDBM_RST 0x1B5 +/// CCAFALLTHRDBM field reset value +#define AGC_CCAFALLTHRDBM_RST 0xBF +/// DISCCAEN field reset value +#define AGC_DISCCAEN_RST 0x1 +/// SATCCAEN field reset value +#define AGC_SATCCAEN_RST 0x1 +/// CCARISETHRDBM field reset value +#define AGC_CCARISETHRDBM_RST 0xC2 + +/** + * @brief Constructs a value for the RWNXAGCCCA1 register given values for its fields + * and writes the value to the register. + * + * @param[in] inbdccapowmindbm - The value to use for the INBDCCAPOWMINDBM field. + * @param[in] ccafallthrdbm - The value to use for the CCAFALLTHRDBM field. + * @param[in] disccaen - The value to use for the DISCCAEN field. + * @param[in] satccaen - The value to use for the SATCCAEN field. + * @param[in] ccarisethrdbm - The value to use for the CCARISETHRDBM field. + */ +__INLINE void agc_rwnxagccca1_pack(uint16_t inbdccapowmindbm, uint8_t ccafallthrdbm, uint8_t disccaen, uint8_t satccaen, uint8_t ccarisethrdbm) +{ + ASSERT_ERR((((uint32_t)inbdccapowmindbm << 20) & ~((uint32_t)0x1FF00000)) == 0); + ASSERT_ERR((((uint32_t)ccafallthrdbm << 12) & ~((uint32_t)0x000FF000)) == 0); + ASSERT_ERR((((uint32_t)disccaen << 9) & ~((uint32_t)0x00000200)) == 0); + ASSERT_ERR((((uint32_t)satccaen << 8) & ~((uint32_t)0x00000100)) == 0); + ASSERT_ERR((((uint32_t)ccarisethrdbm << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(AGC_RWNXAGCCCA1_ADDR, ((uint32_t)inbdccapowmindbm << 20) | ((uint32_t)ccafallthrdbm << 12) | ((uint32_t)disccaen << 9) | ((uint32_t)satccaen << 8) | ((uint32_t)ccarisethrdbm << 0)); +} + +/** + * @brief Unpacks RWNXAGCCCA1's fields from current value of the RWNXAGCCCA1 register. + * + * Reads the RWNXAGCCCA1 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] inbdccapowmindbm - Will be populated with the current value of this field from the register. + * @param[out] ccafallthrdbm - Will be populated with the current value of this field from the register. + * @param[out] disccaen - Will be populated with the current value of this field from the register. + * @param[out] satccaen - Will be populated with the current value of this field from the register. + * @param[out] ccarisethrdbm - Will be populated with the current value of this field from the register. + */ +__INLINE void agc_rwnxagccca1_unpack(uint16_t *inbdccapowmindbm, uint8_t *ccafallthrdbm, uint8_t *disccaen, uint8_t *satccaen, uint8_t *ccarisethrdbm) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCCCA1_ADDR); + + *inbdccapowmindbm = (localVal & ((uint32_t)0x1FF00000)) >> 20; + *ccafallthrdbm = (localVal & ((uint32_t)0x000FF000)) >> 12; + *disccaen = (localVal & ((uint32_t)0x00000200)) >> 9; + *satccaen = (localVal & ((uint32_t)0x00000100)) >> 8; + *ccarisethrdbm = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +/** + * @brief Returns the current value of the INBDCCAPOWMINDBM field in the RWNXAGCCCA1 register. + * + * The RWNXAGCCCA1 register will be read and the INBDCCAPOWMINDBM field's value will be returned. + * + * @return The current value of the INBDCCAPOWMINDBM field in the RWNXAGCCCA1 register. + */ +__INLINE uint16_t agc_inbdccapowmindbm_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCCCA1_ADDR); + return ((localVal & ((uint32_t)0x1FF00000)) >> 20); +} + +/** + * @brief Sets the INBDCCAPOWMINDBM field of the RWNXAGCCCA1 register. + * + * The RWNXAGCCCA1 register will be read, modified to contain the new field value, and written. + * + * @param[in] inbdccapowmindbm - The value to set the field to. + */ +__INLINE void agc_inbdccapowmindbm_setf(uint16_t inbdccapowmindbm) +{ + ASSERT_ERR((((uint32_t)inbdccapowmindbm << 20) & ~((uint32_t)0x1FF00000)) == 0); + REG_PL_WR(AGC_RWNXAGCCCA1_ADDR, (REG_PL_RD(AGC_RWNXAGCCCA1_ADDR) & ~((uint32_t)0x1FF00000)) | ((uint32_t)inbdccapowmindbm << 20)); +} + +/** + * @brief Returns the current value of the CCAFALLTHRDBM field in the RWNXAGCCCA1 register. + * + * The RWNXAGCCCA1 register will be read and the CCAFALLTHRDBM field's value will be returned. + * + * @return The current value of the CCAFALLTHRDBM field in the RWNXAGCCCA1 register. + */ +__INLINE uint8_t agc_ccafallthrdbm_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCCCA1_ADDR); + return ((localVal & ((uint32_t)0x000FF000)) >> 12); +} + +/** + * @brief Sets the CCAFALLTHRDBM field of the RWNXAGCCCA1 register. + * + * The RWNXAGCCCA1 register will be read, modified to contain the new field value, and written. + * + * @param[in] ccafallthrdbm - The value to set the field to. + */ +__INLINE void agc_ccafallthrdbm_setf(uint8_t ccafallthrdbm) +{ + ASSERT_ERR((((uint32_t)ccafallthrdbm << 12) & ~((uint32_t)0x000FF000)) == 0); + REG_PL_WR(AGC_RWNXAGCCCA1_ADDR, (REG_PL_RD(AGC_RWNXAGCCCA1_ADDR) & ~((uint32_t)0x000FF000)) | ((uint32_t)ccafallthrdbm << 12)); +} + +/** + * @brief Returns the current value of the DISCCAEN field in the RWNXAGCCCA1 register. + * + * The RWNXAGCCCA1 register will be read and the DISCCAEN field's value will be returned. + * + * @return The current value of the DISCCAEN field in the RWNXAGCCCA1 register. + */ +__INLINE uint8_t agc_disccaen_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCCCA1_ADDR); + return ((localVal & ((uint32_t)0x00000200)) >> 9); +} + +/** + * @brief Sets the DISCCAEN field of the RWNXAGCCCA1 register. + * + * The RWNXAGCCCA1 register will be read, modified to contain the new field value, and written. + * + * @param[in] disccaen - The value to set the field to. + */ +__INLINE void agc_disccaen_setf(uint8_t disccaen) +{ + ASSERT_ERR((((uint32_t)disccaen << 9) & ~((uint32_t)0x00000200)) == 0); + REG_PL_WR(AGC_RWNXAGCCCA1_ADDR, (REG_PL_RD(AGC_RWNXAGCCCA1_ADDR) & ~((uint32_t)0x00000200)) | ((uint32_t)disccaen << 9)); +} + +/** + * @brief Returns the current value of the SATCCAEN field in the RWNXAGCCCA1 register. + * + * The RWNXAGCCCA1 register will be read and the SATCCAEN field's value will be returned. + * + * @return The current value of the SATCCAEN field in the RWNXAGCCCA1 register. + */ +__INLINE uint8_t agc_satccaen_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCCCA1_ADDR); + return ((localVal & ((uint32_t)0x00000100)) >> 8); +} + +/** + * @brief Sets the SATCCAEN field of the RWNXAGCCCA1 register. + * + * The RWNXAGCCCA1 register will be read, modified to contain the new field value, and written. + * + * @param[in] satccaen - The value to set the field to. + */ +__INLINE void agc_satccaen_setf(uint8_t satccaen) +{ + ASSERT_ERR((((uint32_t)satccaen << 8) & ~((uint32_t)0x00000100)) == 0); + REG_PL_WR(AGC_RWNXAGCCCA1_ADDR, (REG_PL_RD(AGC_RWNXAGCCCA1_ADDR) & ~((uint32_t)0x00000100)) | ((uint32_t)satccaen << 8)); +} + +/** + * @brief Returns the current value of the CCARISETHRDBM field in the RWNXAGCCCA1 register. + * + * The RWNXAGCCCA1 register will be read and the CCARISETHRDBM field's value will be returned. + * + * @return The current value of the CCARISETHRDBM field in the RWNXAGCCCA1 register. + */ +__INLINE uint8_t agc_ccarisethrdbm_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCCCA1_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +/** + * @brief Sets the CCARISETHRDBM field of the RWNXAGCCCA1 register. + * + * The RWNXAGCCCA1 register will be read, modified to contain the new field value, and written. + * + * @param[in] ccarisethrdbm - The value to set the field to. + */ +__INLINE void agc_ccarisethrdbm_setf(uint8_t ccarisethrdbm) +{ + ASSERT_ERR((((uint32_t)ccarisethrdbm << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(AGC_RWNXAGCCCA1_ADDR, (REG_PL_RD(AGC_RWNXAGCCCA1_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)ccarisethrdbm << 0)); +} + +/// @} + +/** + * @name RWNXAGCCCACTRL register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:28         CCAFLAG3CTRL   0xA
+ *  27:24         CCAFLAG2CTRL   0xA
+ *  23:20         CCAFLAG1CTRL   0xA
+ *  19:16         CCAFLAG0CTRL   0xA
+ *     09             CCADEMOD   1
+ *     08              CCACSEN   1
+ *  06:04          CCARAMPUDEN   0x7
+ *  02:00          CCAENERGYEN   0x7
+ * 
+ * + * @{ + */ + +/// Address of the RWNXAGCCCACTRL register +#define AGC_RWNXAGCCCACTRL_ADDR 0x01002078 +/// Offset of the RWNXAGCCCACTRL register from the base address +#define AGC_RWNXAGCCCACTRL_OFFSET 0x00002078 +/// Index of the RWNXAGCCCACTRL register +#define AGC_RWNXAGCCCACTRL_INDEX 0x0000081E +/// Reset value of the RWNXAGCCCACTRL register +#define AGC_RWNXAGCCCACTRL_RESET 0xAAAA0377 + +/** + * @brief Returns the current value of the RWNXAGCCCACTRL register. + * The RWNXAGCCCACTRL register will be read and its value returned. + * @return The current value of the RWNXAGCCCACTRL register. + */ +__INLINE uint32_t agc_rwnxagcccactrl_get(void) +{ + return REG_PL_RD(AGC_RWNXAGCCCACTRL_ADDR); +} + +/** + * @brief Sets the RWNXAGCCCACTRL register to a value. + * The RWNXAGCCCACTRL register will be written. + * @param value - The value to write. + */ +__INLINE void agc_rwnxagcccactrl_set(uint32_t value) +{ + REG_PL_WR(AGC_RWNXAGCCCACTRL_ADDR, value); +} + +// field definitions +/// CCAFLAG3CTRL field mask +#define AGC_CCAFLAG3CTRL_MASK ((uint32_t)0xF0000000) +/// CCAFLAG3CTRL field LSB position +#define AGC_CCAFLAG3CTRL_LSB 28 +/// CCAFLAG3CTRL field width +#define AGC_CCAFLAG3CTRL_WIDTH ((uint32_t)0x00000004) +/// CCAFLAG2CTRL field mask +#define AGC_CCAFLAG2CTRL_MASK ((uint32_t)0x0F000000) +/// CCAFLAG2CTRL field LSB position +#define AGC_CCAFLAG2CTRL_LSB 24 +/// CCAFLAG2CTRL field width +#define AGC_CCAFLAG2CTRL_WIDTH ((uint32_t)0x00000004) +/// CCAFLAG1CTRL field mask +#define AGC_CCAFLAG1CTRL_MASK ((uint32_t)0x00F00000) +/// CCAFLAG1CTRL field LSB position +#define AGC_CCAFLAG1CTRL_LSB 20 +/// CCAFLAG1CTRL field width +#define AGC_CCAFLAG1CTRL_WIDTH ((uint32_t)0x00000004) +/// CCAFLAG0CTRL field mask +#define AGC_CCAFLAG0CTRL_MASK ((uint32_t)0x000F0000) +/// CCAFLAG0CTRL field LSB position +#define AGC_CCAFLAG0CTRL_LSB 16 +/// CCAFLAG0CTRL field width +#define AGC_CCAFLAG0CTRL_WIDTH ((uint32_t)0x00000004) +/// CCADEMOD field bit +#define AGC_CCADEMOD_BIT ((uint32_t)0x00000200) +/// CCADEMOD field position +#define AGC_CCADEMOD_POS 9 +/// CCACSEN field bit +#define AGC_CCACSEN_BIT ((uint32_t)0x00000100) +/// CCACSEN field position +#define AGC_CCACSEN_POS 8 +/// CCARAMPUDEN field mask +#define AGC_CCARAMPUDEN_MASK ((uint32_t)0x00000070) +/// CCARAMPUDEN field LSB position +#define AGC_CCARAMPUDEN_LSB 4 +/// CCARAMPUDEN field width +#define AGC_CCARAMPUDEN_WIDTH ((uint32_t)0x00000003) +/// CCAENERGYEN field mask +#define AGC_CCAENERGYEN_MASK ((uint32_t)0x00000007) +/// CCAENERGYEN field LSB position +#define AGC_CCAENERGYEN_LSB 0 +/// CCAENERGYEN field width +#define AGC_CCAENERGYEN_WIDTH ((uint32_t)0x00000003) + +/// CCAFLAG3CTRL field reset value +#define AGC_CCAFLAG3CTRL_RST 0xA +/// CCAFLAG2CTRL field reset value +#define AGC_CCAFLAG2CTRL_RST 0xA +/// CCAFLAG1CTRL field reset value +#define AGC_CCAFLAG1CTRL_RST 0xA +/// CCAFLAG0CTRL field reset value +#define AGC_CCAFLAG0CTRL_RST 0xA +/// CCADEMOD field reset value +#define AGC_CCADEMOD_RST 0x1 +/// CCACSEN field reset value +#define AGC_CCACSEN_RST 0x1 +/// CCARAMPUDEN field reset value +#define AGC_CCARAMPUDEN_RST 0x7 +/// CCAENERGYEN field reset value +#define AGC_CCAENERGYEN_RST 0x7 + +/** + * @brief Constructs a value for the RWNXAGCCCACTRL register given values for its fields + * and writes the value to the register. + * + * @param[in] ccaflag3ctrl - The value to use for the CCAFLAG3CTRL field. + * @param[in] ccaflag2ctrl - The value to use for the CCAFLAG2CTRL field. + * @param[in] ccaflag1ctrl - The value to use for the CCAFLAG1CTRL field. + * @param[in] ccaflag0ctrl - The value to use for the CCAFLAG0CTRL field. + * @param[in] ccademod - The value to use for the CCADEMOD field. + * @param[in] ccacsen - The value to use for the CCACSEN field. + * @param[in] ccarampuden - The value to use for the CCARAMPUDEN field. + * @param[in] ccaenergyen - The value to use for the CCAENERGYEN field. + */ +__INLINE void agc_rwnxagcccactrl_pack(uint8_t ccaflag3ctrl, uint8_t ccaflag2ctrl, uint8_t ccaflag1ctrl, uint8_t ccaflag0ctrl, uint8_t ccademod, uint8_t ccacsen, uint8_t ccarampuden, uint8_t ccaenergyen) +{ + ASSERT_ERR((((uint32_t)ccaflag3ctrl << 28) & ~((uint32_t)0xF0000000)) == 0); + ASSERT_ERR((((uint32_t)ccaflag2ctrl << 24) & ~((uint32_t)0x0F000000)) == 0); + ASSERT_ERR((((uint32_t)ccaflag1ctrl << 20) & ~((uint32_t)0x00F00000)) == 0); + ASSERT_ERR((((uint32_t)ccaflag0ctrl << 16) & ~((uint32_t)0x000F0000)) == 0); + ASSERT_ERR((((uint32_t)ccademod << 9) & ~((uint32_t)0x00000200)) == 0); + ASSERT_ERR((((uint32_t)ccacsen << 8) & ~((uint32_t)0x00000100)) == 0); + ASSERT_ERR((((uint32_t)ccarampuden << 4) & ~((uint32_t)0x00000070)) == 0); + ASSERT_ERR((((uint32_t)ccaenergyen << 0) & ~((uint32_t)0x00000007)) == 0); + REG_PL_WR(AGC_RWNXAGCCCACTRL_ADDR, ((uint32_t)ccaflag3ctrl << 28) | ((uint32_t)ccaflag2ctrl << 24) | ((uint32_t)ccaflag1ctrl << 20) | ((uint32_t)ccaflag0ctrl << 16) | ((uint32_t)ccademod << 9) | ((uint32_t)ccacsen << 8) | ((uint32_t)ccarampuden << 4) | ((uint32_t)ccaenergyen << 0)); +} + +/** + * @brief Unpacks RWNXAGCCCACTRL's fields from current value of the RWNXAGCCCACTRL register. + * + * Reads the RWNXAGCCCACTRL register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] ccaflag3ctrl - Will be populated with the current value of this field from the register. + * @param[out] ccaflag2ctrl - Will be populated with the current value of this field from the register. + * @param[out] ccaflag1ctrl - Will be populated with the current value of this field from the register. + * @param[out] ccaflag0ctrl - Will be populated with the current value of this field from the register. + * @param[out] ccademod - Will be populated with the current value of this field from the register. + * @param[out] ccacsen - Will be populated with the current value of this field from the register. + * @param[out] ccarampuden - Will be populated with the current value of this field from the register. + * @param[out] ccaenergyen - Will be populated with the current value of this field from the register. + */ +__INLINE void agc_rwnxagcccactrl_unpack(uint8_t *ccaflag3ctrl, uint8_t *ccaflag2ctrl, uint8_t *ccaflag1ctrl, uint8_t *ccaflag0ctrl, uint8_t *ccademod, uint8_t *ccacsen, uint8_t *ccarampuden, uint8_t *ccaenergyen) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCCCACTRL_ADDR); + + *ccaflag3ctrl = (localVal & ((uint32_t)0xF0000000)) >> 28; + *ccaflag2ctrl = (localVal & ((uint32_t)0x0F000000)) >> 24; + *ccaflag1ctrl = (localVal & ((uint32_t)0x00F00000)) >> 20; + *ccaflag0ctrl = (localVal & ((uint32_t)0x000F0000)) >> 16; + *ccademod = (localVal & ((uint32_t)0x00000200)) >> 9; + *ccacsen = (localVal & ((uint32_t)0x00000100)) >> 8; + *ccarampuden = (localVal & ((uint32_t)0x00000070)) >> 4; + *ccaenergyen = (localVal & ((uint32_t)0x00000007)) >> 0; +} + +/** + * @brief Returns the current value of the CCAFLAG3CTRL field in the RWNXAGCCCACTRL register. + * + * The RWNXAGCCCACTRL register will be read and the CCAFLAG3CTRL field's value will be returned. + * + * @return The current value of the CCAFLAG3CTRL field in the RWNXAGCCCACTRL register. + */ +__INLINE uint8_t agc_ccaflag3ctrl_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCCCACTRL_ADDR); + return ((localVal & ((uint32_t)0xF0000000)) >> 28); +} + +/** + * @brief Sets the CCAFLAG3CTRL field of the RWNXAGCCCACTRL register. + * + * The RWNXAGCCCACTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] ccaflag3ctrl - The value to set the field to. + */ +__INLINE void agc_ccaflag3ctrl_setf(uint8_t ccaflag3ctrl) +{ + ASSERT_ERR((((uint32_t)ccaflag3ctrl << 28) & ~((uint32_t)0xF0000000)) == 0); + REG_PL_WR(AGC_RWNXAGCCCACTRL_ADDR, (REG_PL_RD(AGC_RWNXAGCCCACTRL_ADDR) & ~((uint32_t)0xF0000000)) | ((uint32_t)ccaflag3ctrl << 28)); +} + +/** + * @brief Returns the current value of the CCAFLAG2CTRL field in the RWNXAGCCCACTRL register. + * + * The RWNXAGCCCACTRL register will be read and the CCAFLAG2CTRL field's value will be returned. + * + * @return The current value of the CCAFLAG2CTRL field in the RWNXAGCCCACTRL register. + */ +__INLINE uint8_t agc_ccaflag2ctrl_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCCCACTRL_ADDR); + return ((localVal & ((uint32_t)0x0F000000)) >> 24); +} + +/** + * @brief Sets the CCAFLAG2CTRL field of the RWNXAGCCCACTRL register. + * + * The RWNXAGCCCACTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] ccaflag2ctrl - The value to set the field to. + */ +__INLINE void agc_ccaflag2ctrl_setf(uint8_t ccaflag2ctrl) +{ + ASSERT_ERR((((uint32_t)ccaflag2ctrl << 24) & ~((uint32_t)0x0F000000)) == 0); + REG_PL_WR(AGC_RWNXAGCCCACTRL_ADDR, (REG_PL_RD(AGC_RWNXAGCCCACTRL_ADDR) & ~((uint32_t)0x0F000000)) | ((uint32_t)ccaflag2ctrl << 24)); +} + +/** + * @brief Returns the current value of the CCAFLAG1CTRL field in the RWNXAGCCCACTRL register. + * + * The RWNXAGCCCACTRL register will be read and the CCAFLAG1CTRL field's value will be returned. + * + * @return The current value of the CCAFLAG1CTRL field in the RWNXAGCCCACTRL register. + */ +__INLINE uint8_t agc_ccaflag1ctrl_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCCCACTRL_ADDR); + return ((localVal & ((uint32_t)0x00F00000)) >> 20); +} + +/** + * @brief Sets the CCAFLAG1CTRL field of the RWNXAGCCCACTRL register. + * + * The RWNXAGCCCACTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] ccaflag1ctrl - The value to set the field to. + */ +__INLINE void agc_ccaflag1ctrl_setf(uint8_t ccaflag1ctrl) +{ + ASSERT_ERR((((uint32_t)ccaflag1ctrl << 20) & ~((uint32_t)0x00F00000)) == 0); + REG_PL_WR(AGC_RWNXAGCCCACTRL_ADDR, (REG_PL_RD(AGC_RWNXAGCCCACTRL_ADDR) & ~((uint32_t)0x00F00000)) | ((uint32_t)ccaflag1ctrl << 20)); +} + +/** + * @brief Returns the current value of the CCAFLAG0CTRL field in the RWNXAGCCCACTRL register. + * + * The RWNXAGCCCACTRL register will be read and the CCAFLAG0CTRL field's value will be returned. + * + * @return The current value of the CCAFLAG0CTRL field in the RWNXAGCCCACTRL register. + */ +__INLINE uint8_t agc_ccaflag0ctrl_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCCCACTRL_ADDR); + return ((localVal & ((uint32_t)0x000F0000)) >> 16); +} + +/** + * @brief Sets the CCAFLAG0CTRL field of the RWNXAGCCCACTRL register. + * + * The RWNXAGCCCACTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] ccaflag0ctrl - The value to set the field to. + */ +__INLINE void agc_ccaflag0ctrl_setf(uint8_t ccaflag0ctrl) +{ + ASSERT_ERR((((uint32_t)ccaflag0ctrl << 16) & ~((uint32_t)0x000F0000)) == 0); + REG_PL_WR(AGC_RWNXAGCCCACTRL_ADDR, (REG_PL_RD(AGC_RWNXAGCCCACTRL_ADDR) & ~((uint32_t)0x000F0000)) | ((uint32_t)ccaflag0ctrl << 16)); +} + +/** + * @brief Returns the current value of the CCADEMOD field in the RWNXAGCCCACTRL register. + * + * The RWNXAGCCCACTRL register will be read and the CCADEMOD field's value will be returned. + * + * @return The current value of the CCADEMOD field in the RWNXAGCCCACTRL register. + */ +__INLINE uint8_t agc_ccademod_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCCCACTRL_ADDR); + return ((localVal & ((uint32_t)0x00000200)) >> 9); +} + +/** + * @brief Sets the CCADEMOD field of the RWNXAGCCCACTRL register. + * + * The RWNXAGCCCACTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] ccademod - The value to set the field to. + */ +__INLINE void agc_ccademod_setf(uint8_t ccademod) +{ + ASSERT_ERR((((uint32_t)ccademod << 9) & ~((uint32_t)0x00000200)) == 0); + REG_PL_WR(AGC_RWNXAGCCCACTRL_ADDR, (REG_PL_RD(AGC_RWNXAGCCCACTRL_ADDR) & ~((uint32_t)0x00000200)) | ((uint32_t)ccademod << 9)); +} + +/** + * @brief Returns the current value of the CCACSEN field in the RWNXAGCCCACTRL register. + * + * The RWNXAGCCCACTRL register will be read and the CCACSEN field's value will be returned. + * + * @return The current value of the CCACSEN field in the RWNXAGCCCACTRL register. + */ +__INLINE uint8_t agc_ccacsen_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCCCACTRL_ADDR); + return ((localVal & ((uint32_t)0x00000100)) >> 8); +} + +/** + * @brief Sets the CCACSEN field of the RWNXAGCCCACTRL register. + * + * The RWNXAGCCCACTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] ccacsen - The value to set the field to. + */ +__INLINE void agc_ccacsen_setf(uint8_t ccacsen) +{ + ASSERT_ERR((((uint32_t)ccacsen << 8) & ~((uint32_t)0x00000100)) == 0); + REG_PL_WR(AGC_RWNXAGCCCACTRL_ADDR, (REG_PL_RD(AGC_RWNXAGCCCACTRL_ADDR) & ~((uint32_t)0x00000100)) | ((uint32_t)ccacsen << 8)); +} + +/** + * @brief Returns the current value of the CCARAMPUDEN field in the RWNXAGCCCACTRL register. + * + * The RWNXAGCCCACTRL register will be read and the CCARAMPUDEN field's value will be returned. + * + * @return The current value of the CCARAMPUDEN field in the RWNXAGCCCACTRL register. + */ +__INLINE uint8_t agc_ccarampuden_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCCCACTRL_ADDR); + return ((localVal & ((uint32_t)0x00000070)) >> 4); +} + +/** + * @brief Sets the CCARAMPUDEN field of the RWNXAGCCCACTRL register. + * + * The RWNXAGCCCACTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] ccarampuden - The value to set the field to. + */ +__INLINE void agc_ccarampuden_setf(uint8_t ccarampuden) +{ + ASSERT_ERR((((uint32_t)ccarampuden << 4) & ~((uint32_t)0x00000070)) == 0); + REG_PL_WR(AGC_RWNXAGCCCACTRL_ADDR, (REG_PL_RD(AGC_RWNXAGCCCACTRL_ADDR) & ~((uint32_t)0x00000070)) | ((uint32_t)ccarampuden << 4)); +} + +/** + * @brief Returns the current value of the CCAENERGYEN field in the RWNXAGCCCACTRL register. + * + * The RWNXAGCCCACTRL register will be read and the CCAENERGYEN field's value will be returned. + * + * @return The current value of the CCAENERGYEN field in the RWNXAGCCCACTRL register. + */ +__INLINE uint8_t agc_ccaenergyen_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCCCACTRL_ADDR); + return ((localVal & ((uint32_t)0x00000007)) >> 0); +} + +/** + * @brief Sets the CCAENERGYEN field of the RWNXAGCCCACTRL register. + * + * The RWNXAGCCCACTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] ccaenergyen - The value to set the field to. + */ +__INLINE void agc_ccaenergyen_setf(uint8_t ccaenergyen) +{ + ASSERT_ERR((((uint32_t)ccaenergyen << 0) & ~((uint32_t)0x00000007)) == 0); + REG_PL_WR(AGC_RWNXAGCCCACTRL_ADDR, (REG_PL_RD(AGC_RWNXAGCCCACTRL_ADDR) & ~((uint32_t)0x00000007)) | ((uint32_t)ccaenergyen << 0)); +} + +/// @} + +/** + * @name RWNXAGCCCASTATE0 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  26:16     RXSTATECCA20SSEL   0xD4
+ *  10:00     RXSTATECCA20PSEL   0x6FE
+ * 
+ * + * @{ + */ + +/// Address of the RWNXAGCCCASTATE0 register +#define AGC_RWNXAGCCCASTATE0_ADDR 0x0100207C +/// Offset of the RWNXAGCCCASTATE0 register from the base address +#define AGC_RWNXAGCCCASTATE0_OFFSET 0x0000207C +/// Index of the RWNXAGCCCASTATE0 register +#define AGC_RWNXAGCCCASTATE0_INDEX 0x0000081F +/// Reset value of the RWNXAGCCCASTATE0 register +#define AGC_RWNXAGCCCASTATE0_RESET 0x00D406FE + +/** + * @brief Returns the current value of the RWNXAGCCCASTATE0 register. + * The RWNXAGCCCASTATE0 register will be read and its value returned. + * @return The current value of the RWNXAGCCCASTATE0 register. + */ +__INLINE uint32_t agc_rwnxagcccastate0_get(void) +{ + return REG_PL_RD(AGC_RWNXAGCCCASTATE0_ADDR); +} + +/** + * @brief Sets the RWNXAGCCCASTATE0 register to a value. + * The RWNXAGCCCASTATE0 register will be written. + * @param value - The value to write. + */ +__INLINE void agc_rwnxagcccastate0_set(uint32_t value) +{ + REG_PL_WR(AGC_RWNXAGCCCASTATE0_ADDR, value); +} + +// field definitions +/// RXSTATECCA20SSEL field mask +#define AGC_RXSTATECCA20SSEL_MASK ((uint32_t)0x07FF0000) +/// RXSTATECCA20SSEL field LSB position +#define AGC_RXSTATECCA20SSEL_LSB 16 +/// RXSTATECCA20SSEL field width +#define AGC_RXSTATECCA20SSEL_WIDTH ((uint32_t)0x0000000B) +/// RXSTATECCA20PSEL field mask +#define AGC_RXSTATECCA20PSEL_MASK ((uint32_t)0x000007FF) +/// RXSTATECCA20PSEL field LSB position +#define AGC_RXSTATECCA20PSEL_LSB 0 +/// RXSTATECCA20PSEL field width +#define AGC_RXSTATECCA20PSEL_WIDTH ((uint32_t)0x0000000B) + +/// RXSTATECCA20SSEL field reset value +#define AGC_RXSTATECCA20SSEL_RST 0xD4 +/// RXSTATECCA20PSEL field reset value +#define AGC_RXSTATECCA20PSEL_RST 0x6FE + +/** + * @brief Constructs a value for the RWNXAGCCCASTATE0 register given values for its fields + * and writes the value to the register. + * + * @param[in] rxstatecca20ssel - The value to use for the RXSTATECCA20SSEL field. + * @param[in] rxstatecca20psel - The value to use for the RXSTATECCA20PSEL field. + */ +__INLINE void agc_rwnxagcccastate0_pack(uint16_t rxstatecca20ssel, uint16_t rxstatecca20psel) +{ + ASSERT_ERR((((uint32_t)rxstatecca20ssel << 16) & ~((uint32_t)0x07FF0000)) == 0); + ASSERT_ERR((((uint32_t)rxstatecca20psel << 0) & ~((uint32_t)0x000007FF)) == 0); + REG_PL_WR(AGC_RWNXAGCCCASTATE0_ADDR, ((uint32_t)rxstatecca20ssel << 16) | ((uint32_t)rxstatecca20psel << 0)); +} + +/** + * @brief Unpacks RWNXAGCCCASTATE0's fields from current value of the RWNXAGCCCASTATE0 register. + * + * Reads the RWNXAGCCCASTATE0 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] rxstatecca20ssel - Will be populated with the current value of this field from the register. + * @param[out] rxstatecca20psel - Will be populated with the current value of this field from the register. + */ +__INLINE void agc_rwnxagcccastate0_unpack(uint16_t *rxstatecca20ssel, uint16_t *rxstatecca20psel) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCCCASTATE0_ADDR); + + *rxstatecca20ssel = (localVal & ((uint32_t)0x07FF0000)) >> 16; + *rxstatecca20psel = (localVal & ((uint32_t)0x000007FF)) >> 0; +} + +/** + * @brief Returns the current value of the RXSTATECCA20SSEL field in the RWNXAGCCCASTATE0 register. + * + * The RWNXAGCCCASTATE0 register will be read and the RXSTATECCA20SSEL field's value will be returned. + * + * @return The current value of the RXSTATECCA20SSEL field in the RWNXAGCCCASTATE0 register. + */ +__INLINE uint16_t agc_rxstatecca20ssel_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCCCASTATE0_ADDR); + return ((localVal & ((uint32_t)0x07FF0000)) >> 16); +} + +/** + * @brief Sets the RXSTATECCA20SSEL field of the RWNXAGCCCASTATE0 register. + * + * The RWNXAGCCCASTATE0 register will be read, modified to contain the new field value, and written. + * + * @param[in] rxstatecca20ssel - The value to set the field to. + */ +__INLINE void agc_rxstatecca20ssel_setf(uint16_t rxstatecca20ssel) +{ + ASSERT_ERR((((uint32_t)rxstatecca20ssel << 16) & ~((uint32_t)0x07FF0000)) == 0); + REG_PL_WR(AGC_RWNXAGCCCASTATE0_ADDR, (REG_PL_RD(AGC_RWNXAGCCCASTATE0_ADDR) & ~((uint32_t)0x07FF0000)) | ((uint32_t)rxstatecca20ssel << 16)); +} + +/** + * @brief Returns the current value of the RXSTATECCA20PSEL field in the RWNXAGCCCASTATE0 register. + * + * The RWNXAGCCCASTATE0 register will be read and the RXSTATECCA20PSEL field's value will be returned. + * + * @return The current value of the RXSTATECCA20PSEL field in the RWNXAGCCCASTATE0 register. + */ +__INLINE uint16_t agc_rxstatecca20psel_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCCCASTATE0_ADDR); + return ((localVal & ((uint32_t)0x000007FF)) >> 0); +} + +/** + * @brief Sets the RXSTATECCA20PSEL field of the RWNXAGCCCASTATE0 register. + * + * The RWNXAGCCCASTATE0 register will be read, modified to contain the new field value, and written. + * + * @param[in] rxstatecca20psel - The value to set the field to. + */ +__INLINE void agc_rxstatecca20psel_setf(uint16_t rxstatecca20psel) +{ + ASSERT_ERR((((uint32_t)rxstatecca20psel << 0) & ~((uint32_t)0x000007FF)) == 0); + REG_PL_WR(AGC_RWNXAGCCCASTATE0_ADDR, (REG_PL_RD(AGC_RWNXAGCCCASTATE0_ADDR) & ~((uint32_t)0x000007FF)) | ((uint32_t)rxstatecca20psel << 0)); +} + +/// @} + +/** + * @name RWNXAGCCCASTATE1 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  10:00     RXSTATECCA40SSEL   0x80
+ * 
+ * + * @{ + */ + +/// Address of the RWNXAGCCCASTATE1 register +#define AGC_RWNXAGCCCASTATE1_ADDR 0x01002080 +/// Offset of the RWNXAGCCCASTATE1 register from the base address +#define AGC_RWNXAGCCCASTATE1_OFFSET 0x00002080 +/// Index of the RWNXAGCCCASTATE1 register +#define AGC_RWNXAGCCCASTATE1_INDEX 0x00000820 +/// Reset value of the RWNXAGCCCASTATE1 register +#define AGC_RWNXAGCCCASTATE1_RESET 0x00000080 + +/** + * @brief Returns the current value of the RWNXAGCCCASTATE1 register. + * The RWNXAGCCCASTATE1 register will be read and its value returned. + * @return The current value of the RWNXAGCCCASTATE1 register. + */ +__INLINE uint32_t agc_rwnxagcccastate1_get(void) +{ + return REG_PL_RD(AGC_RWNXAGCCCASTATE1_ADDR); +} + +/** + * @brief Sets the RWNXAGCCCASTATE1 register to a value. + * The RWNXAGCCCASTATE1 register will be written. + * @param value - The value to write. + */ +__INLINE void agc_rwnxagcccastate1_set(uint32_t value) +{ + REG_PL_WR(AGC_RWNXAGCCCASTATE1_ADDR, value); +} + +// field definitions +/// RXSTATECCA40SSEL field mask +#define AGC_RXSTATECCA40SSEL_MASK ((uint32_t)0x000007FF) +/// RXSTATECCA40SSEL field LSB position +#define AGC_RXSTATECCA40SSEL_LSB 0 +/// RXSTATECCA40SSEL field width +#define AGC_RXSTATECCA40SSEL_WIDTH ((uint32_t)0x0000000B) + +/// RXSTATECCA40SSEL field reset value +#define AGC_RXSTATECCA40SSEL_RST 0x80 + +/** + * @brief Returns the current value of the RXSTATECCA40SSEL field in the RWNXAGCCCASTATE1 register. + * + * The RWNXAGCCCASTATE1 register will be read and the RXSTATECCA40SSEL field's value will be returned. + * + * @return The current value of the RXSTATECCA40SSEL field in the RWNXAGCCCASTATE1 register. + */ +__INLINE uint16_t agc_rxstatecca40ssel_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCCCASTATE1_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x000007FF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the RXSTATECCA40SSEL field of the RWNXAGCCCASTATE1 register. + * + * The RWNXAGCCCASTATE1 register will be read, modified to contain the new field value, and written. + * + * @param[in] rxstatecca40ssel - The value to set the field to. + */ +__INLINE void agc_rxstatecca40ssel_setf(uint16_t rxstatecca40ssel) +{ + ASSERT_ERR((((uint32_t)rxstatecca40ssel << 0) & ~((uint32_t)0x000007FF)) == 0); + REG_PL_WR(AGC_RWNXAGCCCASTATE1_ADDR, (uint32_t)rxstatecca40ssel << 0); +} + +/// @} + +/** + * @name RWNXAGCCCATIMEOUT register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00           CCATIMEOUT   0x9312A
+ * 
+ * + * @{ + */ + +/// Address of the RWNXAGCCCATIMEOUT register +#define AGC_RWNXAGCCCATIMEOUT_ADDR 0x01002084 +/// Offset of the RWNXAGCCCATIMEOUT register from the base address +#define AGC_RWNXAGCCCATIMEOUT_OFFSET 0x00002084 +/// Index of the RWNXAGCCCATIMEOUT register +#define AGC_RWNXAGCCCATIMEOUT_INDEX 0x00000821 +/// Reset value of the RWNXAGCCCATIMEOUT register +#define AGC_RWNXAGCCCATIMEOUT_RESET 0x0009312A + +/** + * @brief Returns the current value of the RWNXAGCCCATIMEOUT register. + * The RWNXAGCCCATIMEOUT register will be read and its value returned. + * @return The current value of the RWNXAGCCCATIMEOUT register. + */ +__INLINE uint32_t agc_rwnxagcccatimeout_get(void) +{ + return REG_PL_RD(AGC_RWNXAGCCCATIMEOUT_ADDR); +} + +/** + * @brief Sets the RWNXAGCCCATIMEOUT register to a value. + * The RWNXAGCCCATIMEOUT register will be written. + * @param value - The value to write. + */ +__INLINE void agc_rwnxagcccatimeout_set(uint32_t value) +{ + REG_PL_WR(AGC_RWNXAGCCCATIMEOUT_ADDR, value); +} + +// field definitions +/// CCATIMEOUT field mask +#define AGC_CCATIMEOUT_MASK ((uint32_t)0xFFFFFFFF) +/// CCATIMEOUT field LSB position +#define AGC_CCATIMEOUT_LSB 0 +/// CCATIMEOUT field width +#define AGC_CCATIMEOUT_WIDTH ((uint32_t)0x00000020) + +/// CCATIMEOUT field reset value +#define AGC_CCATIMEOUT_RST 0x9312A + +/** + * @brief Returns the current value of the CCATIMEOUT field in the RWNXAGCCCATIMEOUT register. + * + * The RWNXAGCCCATIMEOUT register will be read and the CCATIMEOUT field's value will be returned. + * + * @return The current value of the CCATIMEOUT field in the RWNXAGCCCATIMEOUT register. + */ +__INLINE uint32_t agc_ccatimeout_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCCCATIMEOUT_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the CCATIMEOUT field of the RWNXAGCCCATIMEOUT register. + * + * The RWNXAGCCCATIMEOUT register will be read, modified to contain the new field value, and written. + * + * @param[in] ccatimeout - The value to set the field to. + */ +__INLINE void agc_ccatimeout_setf(uint32_t ccatimeout) +{ + ASSERT_ERR((((uint32_t)ccatimeout << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(AGC_RWNXAGCCCATIMEOUT_ADDR, (uint32_t)ccatimeout << 0); +} + +/// @} + +/** + * @name RWNXAGCSNR0 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  23:20           NFVGATHRM2   0xA
+ *  19:16           NFVGATHRM1   0x8
+ *  15:12           NFVGATHRM0   0x6
+ *  11:08           NFVGATHRL2   0xA
+ *  07:04           NFVGATHRL1   0x8
+ *  03:00           NFVGATHRL0   0x6
+ * 
+ * + * @{ + */ + +/// Address of the RWNXAGCSNR0 register +#define AGC_RWNXAGCSNR0_ADDR 0x01002088 +/// Offset of the RWNXAGCSNR0 register from the base address +#define AGC_RWNXAGCSNR0_OFFSET 0x00002088 +/// Index of the RWNXAGCSNR0 register +#define AGC_RWNXAGCSNR0_INDEX 0x00000822 +/// Reset value of the RWNXAGCSNR0 register +#define AGC_RWNXAGCSNR0_RESET 0x00A86A86 + +/** + * @brief Returns the current value of the RWNXAGCSNR0 register. + * The RWNXAGCSNR0 register will be read and its value returned. + * @return The current value of the RWNXAGCSNR0 register. + */ +__INLINE uint32_t agc_rwnxagcsnr0_get(void) +{ + return REG_PL_RD(AGC_RWNXAGCSNR0_ADDR); +} + +/** + * @brief Sets the RWNXAGCSNR0 register to a value. + * The RWNXAGCSNR0 register will be written. + * @param value - The value to write. + */ +__INLINE void agc_rwnxagcsnr0_set(uint32_t value) +{ + REG_PL_WR(AGC_RWNXAGCSNR0_ADDR, value); +} + +// field definitions +/// NFVGATHRM2 field mask +#define AGC_NFVGATHRM2_MASK ((uint32_t)0x00F00000) +/// NFVGATHRM2 field LSB position +#define AGC_NFVGATHRM2_LSB 20 +/// NFVGATHRM2 field width +#define AGC_NFVGATHRM2_WIDTH ((uint32_t)0x00000004) +/// NFVGATHRM1 field mask +#define AGC_NFVGATHRM1_MASK ((uint32_t)0x000F0000) +/// NFVGATHRM1 field LSB position +#define AGC_NFVGATHRM1_LSB 16 +/// NFVGATHRM1 field width +#define AGC_NFVGATHRM1_WIDTH ((uint32_t)0x00000004) +/// NFVGATHRM0 field mask +#define AGC_NFVGATHRM0_MASK ((uint32_t)0x0000F000) +/// NFVGATHRM0 field LSB position +#define AGC_NFVGATHRM0_LSB 12 +/// NFVGATHRM0 field width +#define AGC_NFVGATHRM0_WIDTH ((uint32_t)0x00000004) +/// NFVGATHRL2 field mask +#define AGC_NFVGATHRL2_MASK ((uint32_t)0x00000F00) +/// NFVGATHRL2 field LSB position +#define AGC_NFVGATHRL2_LSB 8 +/// NFVGATHRL2 field width +#define AGC_NFVGATHRL2_WIDTH ((uint32_t)0x00000004) +/// NFVGATHRL1 field mask +#define AGC_NFVGATHRL1_MASK ((uint32_t)0x000000F0) +/// NFVGATHRL1 field LSB position +#define AGC_NFVGATHRL1_LSB 4 +/// NFVGATHRL1 field width +#define AGC_NFVGATHRL1_WIDTH ((uint32_t)0x00000004) +/// NFVGATHRL0 field mask +#define AGC_NFVGATHRL0_MASK ((uint32_t)0x0000000F) +/// NFVGATHRL0 field LSB position +#define AGC_NFVGATHRL0_LSB 0 +/// NFVGATHRL0 field width +#define AGC_NFVGATHRL0_WIDTH ((uint32_t)0x00000004) + +/// NFVGATHRM2 field reset value +#define AGC_NFVGATHRM2_RST 0xA +/// NFVGATHRM1 field reset value +#define AGC_NFVGATHRM1_RST 0x8 +/// NFVGATHRM0 field reset value +#define AGC_NFVGATHRM0_RST 0x6 +/// NFVGATHRL2 field reset value +#define AGC_NFVGATHRL2_RST 0xA +/// NFVGATHRL1 field reset value +#define AGC_NFVGATHRL1_RST 0x8 +/// NFVGATHRL0 field reset value +#define AGC_NFVGATHRL0_RST 0x6 + +/** + * @brief Constructs a value for the RWNXAGCSNR0 register given values for its fields + * and writes the value to the register. + * + * @param[in] nfvgathrm2 - The value to use for the NFVGATHRM2 field. + * @param[in] nfvgathrm1 - The value to use for the NFVGATHRM1 field. + * @param[in] nfvgathrm0 - The value to use for the NFVGATHRM0 field. + * @param[in] nfvgathrl2 - The value to use for the NFVGATHRL2 field. + * @param[in] nfvgathrl1 - The value to use for the NFVGATHRL1 field. + * @param[in] nfvgathrl0 - The value to use for the NFVGATHRL0 field. + */ +__INLINE void agc_rwnxagcsnr0_pack(uint8_t nfvgathrm2, uint8_t nfvgathrm1, uint8_t nfvgathrm0, uint8_t nfvgathrl2, uint8_t nfvgathrl1, uint8_t nfvgathrl0) +{ + ASSERT_ERR((((uint32_t)nfvgathrm2 << 20) & ~((uint32_t)0x00F00000)) == 0); + ASSERT_ERR((((uint32_t)nfvgathrm1 << 16) & ~((uint32_t)0x000F0000)) == 0); + ASSERT_ERR((((uint32_t)nfvgathrm0 << 12) & ~((uint32_t)0x0000F000)) == 0); + ASSERT_ERR((((uint32_t)nfvgathrl2 << 8) & ~((uint32_t)0x00000F00)) == 0); + ASSERT_ERR((((uint32_t)nfvgathrl1 << 4) & ~((uint32_t)0x000000F0)) == 0); + ASSERT_ERR((((uint32_t)nfvgathrl0 << 0) & ~((uint32_t)0x0000000F)) == 0); + REG_PL_WR(AGC_RWNXAGCSNR0_ADDR, ((uint32_t)nfvgathrm2 << 20) | ((uint32_t)nfvgathrm1 << 16) | ((uint32_t)nfvgathrm0 << 12) | ((uint32_t)nfvgathrl2 << 8) | ((uint32_t)nfvgathrl1 << 4) | ((uint32_t)nfvgathrl0 << 0)); +} + +/** + * @brief Unpacks RWNXAGCSNR0's fields from current value of the RWNXAGCSNR0 register. + * + * Reads the RWNXAGCSNR0 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] nfvgathrm2 - Will be populated with the current value of this field from the register. + * @param[out] nfvgathrm1 - Will be populated with the current value of this field from the register. + * @param[out] nfvgathrm0 - Will be populated with the current value of this field from the register. + * @param[out] nfvgathrl2 - Will be populated with the current value of this field from the register. + * @param[out] nfvgathrl1 - Will be populated with the current value of this field from the register. + * @param[out] nfvgathrl0 - Will be populated with the current value of this field from the register. + */ +__INLINE void agc_rwnxagcsnr0_unpack(uint8_t *nfvgathrm2, uint8_t *nfvgathrm1, uint8_t *nfvgathrm0, uint8_t *nfvgathrl2, uint8_t *nfvgathrl1, uint8_t *nfvgathrl0) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCSNR0_ADDR); + + *nfvgathrm2 = (localVal & ((uint32_t)0x00F00000)) >> 20; + *nfvgathrm1 = (localVal & ((uint32_t)0x000F0000)) >> 16; + *nfvgathrm0 = (localVal & ((uint32_t)0x0000F000)) >> 12; + *nfvgathrl2 = (localVal & ((uint32_t)0x00000F00)) >> 8; + *nfvgathrl1 = (localVal & ((uint32_t)0x000000F0)) >> 4; + *nfvgathrl0 = (localVal & ((uint32_t)0x0000000F)) >> 0; +} + +/** + * @brief Returns the current value of the NFVGATHRM2 field in the RWNXAGCSNR0 register. + * + * The RWNXAGCSNR0 register will be read and the NFVGATHRM2 field's value will be returned. + * + * @return The current value of the NFVGATHRM2 field in the RWNXAGCSNR0 register. + */ +__INLINE uint8_t agc_nfvgathrm2_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCSNR0_ADDR); + return ((localVal & ((uint32_t)0x00F00000)) >> 20); +} + +/** + * @brief Sets the NFVGATHRM2 field of the RWNXAGCSNR0 register. + * + * The RWNXAGCSNR0 register will be read, modified to contain the new field value, and written. + * + * @param[in] nfvgathrm2 - The value to set the field to. + */ +__INLINE void agc_nfvgathrm2_setf(uint8_t nfvgathrm2) +{ + ASSERT_ERR((((uint32_t)nfvgathrm2 << 20) & ~((uint32_t)0x00F00000)) == 0); + REG_PL_WR(AGC_RWNXAGCSNR0_ADDR, (REG_PL_RD(AGC_RWNXAGCSNR0_ADDR) & ~((uint32_t)0x00F00000)) | ((uint32_t)nfvgathrm2 << 20)); +} + +/** + * @brief Returns the current value of the NFVGATHRM1 field in the RWNXAGCSNR0 register. + * + * The RWNXAGCSNR0 register will be read and the NFVGATHRM1 field's value will be returned. + * + * @return The current value of the NFVGATHRM1 field in the RWNXAGCSNR0 register. + */ +__INLINE uint8_t agc_nfvgathrm1_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCSNR0_ADDR); + return ((localVal & ((uint32_t)0x000F0000)) >> 16); +} + +/** + * @brief Sets the NFVGATHRM1 field of the RWNXAGCSNR0 register. + * + * The RWNXAGCSNR0 register will be read, modified to contain the new field value, and written. + * + * @param[in] nfvgathrm1 - The value to set the field to. + */ +__INLINE void agc_nfvgathrm1_setf(uint8_t nfvgathrm1) +{ + ASSERT_ERR((((uint32_t)nfvgathrm1 << 16) & ~((uint32_t)0x000F0000)) == 0); + REG_PL_WR(AGC_RWNXAGCSNR0_ADDR, (REG_PL_RD(AGC_RWNXAGCSNR0_ADDR) & ~((uint32_t)0x000F0000)) | ((uint32_t)nfvgathrm1 << 16)); +} + +/** + * @brief Returns the current value of the NFVGATHRM0 field in the RWNXAGCSNR0 register. + * + * The RWNXAGCSNR0 register will be read and the NFVGATHRM0 field's value will be returned. + * + * @return The current value of the NFVGATHRM0 field in the RWNXAGCSNR0 register. + */ +__INLINE uint8_t agc_nfvgathrm0_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCSNR0_ADDR); + return ((localVal & ((uint32_t)0x0000F000)) >> 12); +} + +/** + * @brief Sets the NFVGATHRM0 field of the RWNXAGCSNR0 register. + * + * The RWNXAGCSNR0 register will be read, modified to contain the new field value, and written. + * + * @param[in] nfvgathrm0 - The value to set the field to. + */ +__INLINE void agc_nfvgathrm0_setf(uint8_t nfvgathrm0) +{ + ASSERT_ERR((((uint32_t)nfvgathrm0 << 12) & ~((uint32_t)0x0000F000)) == 0); + REG_PL_WR(AGC_RWNXAGCSNR0_ADDR, (REG_PL_RD(AGC_RWNXAGCSNR0_ADDR) & ~((uint32_t)0x0000F000)) | ((uint32_t)nfvgathrm0 << 12)); +} + +/** + * @brief Returns the current value of the NFVGATHRL2 field in the RWNXAGCSNR0 register. + * + * The RWNXAGCSNR0 register will be read and the NFVGATHRL2 field's value will be returned. + * + * @return The current value of the NFVGATHRL2 field in the RWNXAGCSNR0 register. + */ +__INLINE uint8_t agc_nfvgathrl2_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCSNR0_ADDR); + return ((localVal & ((uint32_t)0x00000F00)) >> 8); +} + +/** + * @brief Sets the NFVGATHRL2 field of the RWNXAGCSNR0 register. + * + * The RWNXAGCSNR0 register will be read, modified to contain the new field value, and written. + * + * @param[in] nfvgathrl2 - The value to set the field to. + */ +__INLINE void agc_nfvgathrl2_setf(uint8_t nfvgathrl2) +{ + ASSERT_ERR((((uint32_t)nfvgathrl2 << 8) & ~((uint32_t)0x00000F00)) == 0); + REG_PL_WR(AGC_RWNXAGCSNR0_ADDR, (REG_PL_RD(AGC_RWNXAGCSNR0_ADDR) & ~((uint32_t)0x00000F00)) | ((uint32_t)nfvgathrl2 << 8)); +} + +/** + * @brief Returns the current value of the NFVGATHRL1 field in the RWNXAGCSNR0 register. + * + * The RWNXAGCSNR0 register will be read and the NFVGATHRL1 field's value will be returned. + * + * @return The current value of the NFVGATHRL1 field in the RWNXAGCSNR0 register. + */ +__INLINE uint8_t agc_nfvgathrl1_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCSNR0_ADDR); + return ((localVal & ((uint32_t)0x000000F0)) >> 4); +} + +/** + * @brief Sets the NFVGATHRL1 field of the RWNXAGCSNR0 register. + * + * The RWNXAGCSNR0 register will be read, modified to contain the new field value, and written. + * + * @param[in] nfvgathrl1 - The value to set the field to. + */ +__INLINE void agc_nfvgathrl1_setf(uint8_t nfvgathrl1) +{ + ASSERT_ERR((((uint32_t)nfvgathrl1 << 4) & ~((uint32_t)0x000000F0)) == 0); + REG_PL_WR(AGC_RWNXAGCSNR0_ADDR, (REG_PL_RD(AGC_RWNXAGCSNR0_ADDR) & ~((uint32_t)0x000000F0)) | ((uint32_t)nfvgathrl1 << 4)); +} + +/** + * @brief Returns the current value of the NFVGATHRL0 field in the RWNXAGCSNR0 register. + * + * The RWNXAGCSNR0 register will be read and the NFVGATHRL0 field's value will be returned. + * + * @return The current value of the NFVGATHRL0 field in the RWNXAGCSNR0 register. + */ +__INLINE uint8_t agc_nfvgathrl0_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCSNR0_ADDR); + return ((localVal & ((uint32_t)0x0000000F)) >> 0); +} + +/** + * @brief Sets the NFVGATHRL0 field of the RWNXAGCSNR0 register. + * + * The RWNXAGCSNR0 register will be read, modified to contain the new field value, and written. + * + * @param[in] nfvgathrl0 - The value to set the field to. + */ +__INLINE void agc_nfvgathrl0_setf(uint8_t nfvgathrl0) +{ + ASSERT_ERR((((uint32_t)nfvgathrl0 << 0) & ~((uint32_t)0x0000000F)) == 0); + REG_PL_WR(AGC_RWNXAGCSNR0_ADDR, (REG_PL_RD(AGC_RWNXAGCSNR0_ADDR) & ~((uint32_t)0x0000000F)) | ((uint32_t)nfvgathrl0 << 0)); +} + +/// @} + +/** + * @name RWNXAGCSNR1 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     24           SNRMEASSEL   0
+ *  11:08           NFVGATHRH2   0xA
+ *  07:04           NFVGATHRH1   0x8
+ *  03:00           NFVGATHRH0   0x6
+ * 
+ * + * @{ + */ + +/// Address of the RWNXAGCSNR1 register +#define AGC_RWNXAGCSNR1_ADDR 0x0100208C +/// Offset of the RWNXAGCSNR1 register from the base address +#define AGC_RWNXAGCSNR1_OFFSET 0x0000208C +/// Index of the RWNXAGCSNR1 register +#define AGC_RWNXAGCSNR1_INDEX 0x00000823 +/// Reset value of the RWNXAGCSNR1 register +#define AGC_RWNXAGCSNR1_RESET 0x00000A86 + +/** + * @brief Returns the current value of the RWNXAGCSNR1 register. + * The RWNXAGCSNR1 register will be read and its value returned. + * @return The current value of the RWNXAGCSNR1 register. + */ +__INLINE uint32_t agc_rwnxagcsnr1_get(void) +{ + return REG_PL_RD(AGC_RWNXAGCSNR1_ADDR); +} + +/** + * @brief Sets the RWNXAGCSNR1 register to a value. + * The RWNXAGCSNR1 register will be written. + * @param value - The value to write. + */ +__INLINE void agc_rwnxagcsnr1_set(uint32_t value) +{ + REG_PL_WR(AGC_RWNXAGCSNR1_ADDR, value); +} + +// field definitions +/// SNRMEASSEL field bit +#define AGC_SNRMEASSEL_BIT ((uint32_t)0x01000000) +/// SNRMEASSEL field position +#define AGC_SNRMEASSEL_POS 24 +/// NFVGATHRH2 field mask +#define AGC_NFVGATHRH2_MASK ((uint32_t)0x00000F00) +/// NFVGATHRH2 field LSB position +#define AGC_NFVGATHRH2_LSB 8 +/// NFVGATHRH2 field width +#define AGC_NFVGATHRH2_WIDTH ((uint32_t)0x00000004) +/// NFVGATHRH1 field mask +#define AGC_NFVGATHRH1_MASK ((uint32_t)0x000000F0) +/// NFVGATHRH1 field LSB position +#define AGC_NFVGATHRH1_LSB 4 +/// NFVGATHRH1 field width +#define AGC_NFVGATHRH1_WIDTH ((uint32_t)0x00000004) +/// NFVGATHRH0 field mask +#define AGC_NFVGATHRH0_MASK ((uint32_t)0x0000000F) +/// NFVGATHRH0 field LSB position +#define AGC_NFVGATHRH0_LSB 0 +/// NFVGATHRH0 field width +#define AGC_NFVGATHRH0_WIDTH ((uint32_t)0x00000004) + +/// SNRMEASSEL field reset value +#define AGC_SNRMEASSEL_RST 0x0 +/// NFVGATHRH2 field reset value +#define AGC_NFVGATHRH2_RST 0xA +/// NFVGATHRH1 field reset value +#define AGC_NFVGATHRH1_RST 0x8 +/// NFVGATHRH0 field reset value +#define AGC_NFVGATHRH0_RST 0x6 + +/** + * @brief Constructs a value for the RWNXAGCSNR1 register given values for its fields + * and writes the value to the register. + * + * @param[in] snrmeassel - The value to use for the SNRMEASSEL field. + * @param[in] nfvgathrh2 - The value to use for the NFVGATHRH2 field. + * @param[in] nfvgathrh1 - The value to use for the NFVGATHRH1 field. + * @param[in] nfvgathrh0 - The value to use for the NFVGATHRH0 field. + */ +__INLINE void agc_rwnxagcsnr1_pack(uint8_t snrmeassel, uint8_t nfvgathrh2, uint8_t nfvgathrh1, uint8_t nfvgathrh0) +{ + ASSERT_ERR((((uint32_t)snrmeassel << 24) & ~((uint32_t)0x01000000)) == 0); + ASSERT_ERR((((uint32_t)nfvgathrh2 << 8) & ~((uint32_t)0x00000F00)) == 0); + ASSERT_ERR((((uint32_t)nfvgathrh1 << 4) & ~((uint32_t)0x000000F0)) == 0); + ASSERT_ERR((((uint32_t)nfvgathrh0 << 0) & ~((uint32_t)0x0000000F)) == 0); + REG_PL_WR(AGC_RWNXAGCSNR1_ADDR, ((uint32_t)snrmeassel << 24) | ((uint32_t)nfvgathrh2 << 8) | ((uint32_t)nfvgathrh1 << 4) | ((uint32_t)nfvgathrh0 << 0)); +} + +/** + * @brief Unpacks RWNXAGCSNR1's fields from current value of the RWNXAGCSNR1 register. + * + * Reads the RWNXAGCSNR1 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] snrmeassel - Will be populated with the current value of this field from the register. + * @param[out] nfvgathrh2 - Will be populated with the current value of this field from the register. + * @param[out] nfvgathrh1 - Will be populated with the current value of this field from the register. + * @param[out] nfvgathrh0 - Will be populated with the current value of this field from the register. + */ +__INLINE void agc_rwnxagcsnr1_unpack(uint8_t *snrmeassel, uint8_t *nfvgathrh2, uint8_t *nfvgathrh1, uint8_t *nfvgathrh0) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCSNR1_ADDR); + + *snrmeassel = (localVal & ((uint32_t)0x01000000)) >> 24; + *nfvgathrh2 = (localVal & ((uint32_t)0x00000F00)) >> 8; + *nfvgathrh1 = (localVal & ((uint32_t)0x000000F0)) >> 4; + *nfvgathrh0 = (localVal & ((uint32_t)0x0000000F)) >> 0; +} + +/** + * @brief Returns the current value of the SNRMEASSEL field in the RWNXAGCSNR1 register. + * + * The RWNXAGCSNR1 register will be read and the SNRMEASSEL field's value will be returned. + * + * @return The current value of the SNRMEASSEL field in the RWNXAGCSNR1 register. + */ +__INLINE uint8_t agc_snrmeassel_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCSNR1_ADDR); + return ((localVal & ((uint32_t)0x01000000)) >> 24); +} + +/** + * @brief Sets the SNRMEASSEL field of the RWNXAGCSNR1 register. + * + * The RWNXAGCSNR1 register will be read, modified to contain the new field value, and written. + * + * @param[in] snrmeassel - The value to set the field to. + */ +__INLINE void agc_snrmeassel_setf(uint8_t snrmeassel) +{ + ASSERT_ERR((((uint32_t)snrmeassel << 24) & ~((uint32_t)0x01000000)) == 0); + REG_PL_WR(AGC_RWNXAGCSNR1_ADDR, (REG_PL_RD(AGC_RWNXAGCSNR1_ADDR) & ~((uint32_t)0x01000000)) | ((uint32_t)snrmeassel << 24)); +} + +/** + * @brief Returns the current value of the NFVGATHRH2 field in the RWNXAGCSNR1 register. + * + * The RWNXAGCSNR1 register will be read and the NFVGATHRH2 field's value will be returned. + * + * @return The current value of the NFVGATHRH2 field in the RWNXAGCSNR1 register. + */ +__INLINE uint8_t agc_nfvgathrh2_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCSNR1_ADDR); + return ((localVal & ((uint32_t)0x00000F00)) >> 8); +} + +/** + * @brief Sets the NFVGATHRH2 field of the RWNXAGCSNR1 register. + * + * The RWNXAGCSNR1 register will be read, modified to contain the new field value, and written. + * + * @param[in] nfvgathrh2 - The value to set the field to. + */ +__INLINE void agc_nfvgathrh2_setf(uint8_t nfvgathrh2) +{ + ASSERT_ERR((((uint32_t)nfvgathrh2 << 8) & ~((uint32_t)0x00000F00)) == 0); + REG_PL_WR(AGC_RWNXAGCSNR1_ADDR, (REG_PL_RD(AGC_RWNXAGCSNR1_ADDR) & ~((uint32_t)0x00000F00)) | ((uint32_t)nfvgathrh2 << 8)); +} + +/** + * @brief Returns the current value of the NFVGATHRH1 field in the RWNXAGCSNR1 register. + * + * The RWNXAGCSNR1 register will be read and the NFVGATHRH1 field's value will be returned. + * + * @return The current value of the NFVGATHRH1 field in the RWNXAGCSNR1 register. + */ +__INLINE uint8_t agc_nfvgathrh1_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCSNR1_ADDR); + return ((localVal & ((uint32_t)0x000000F0)) >> 4); +} + +/** + * @brief Sets the NFVGATHRH1 field of the RWNXAGCSNR1 register. + * + * The RWNXAGCSNR1 register will be read, modified to contain the new field value, and written. + * + * @param[in] nfvgathrh1 - The value to set the field to. + */ +__INLINE void agc_nfvgathrh1_setf(uint8_t nfvgathrh1) +{ + ASSERT_ERR((((uint32_t)nfvgathrh1 << 4) & ~((uint32_t)0x000000F0)) == 0); + REG_PL_WR(AGC_RWNXAGCSNR1_ADDR, (REG_PL_RD(AGC_RWNXAGCSNR1_ADDR) & ~((uint32_t)0x000000F0)) | ((uint32_t)nfvgathrh1 << 4)); +} + +/** + * @brief Returns the current value of the NFVGATHRH0 field in the RWNXAGCSNR1 register. + * + * The RWNXAGCSNR1 register will be read and the NFVGATHRH0 field's value will be returned. + * + * @return The current value of the NFVGATHRH0 field in the RWNXAGCSNR1 register. + */ +__INLINE uint8_t agc_nfvgathrh0_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCSNR1_ADDR); + return ((localVal & ((uint32_t)0x0000000F)) >> 0); +} + +/** + * @brief Sets the NFVGATHRH0 field of the RWNXAGCSNR1 register. + * + * The RWNXAGCSNR1 register will be read, modified to contain the new field value, and written. + * + * @param[in] nfvgathrh0 - The value to set the field to. + */ +__INLINE void agc_nfvgathrh0_setf(uint8_t nfvgathrh0) +{ + ASSERT_ERR((((uint32_t)nfvgathrh0 << 0) & ~((uint32_t)0x0000000F)) == 0); + REG_PL_WR(AGC_RWNXAGCSNR1_ADDR, (REG_PL_RD(AGC_RWNXAGCSNR1_ADDR) & ~((uint32_t)0x0000000F)) | ((uint32_t)nfvgathrh0 << 0)); +} + +/// @} + +/** + * @name RWNXAGCSNR2 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  29:24            NFVALL3DB   0x20
+ *  21:16            NFVALL2DB   0x21
+ *  13:08            NFVALL1DB   0x28
+ *  05:00            NFVALL0DB   0x28
+ * 
+ * + * @{ + */ + +/// Address of the RWNXAGCSNR2 register +#define AGC_RWNXAGCSNR2_ADDR 0x01002090 +/// Offset of the RWNXAGCSNR2 register from the base address +#define AGC_RWNXAGCSNR2_OFFSET 0x00002090 +/// Index of the RWNXAGCSNR2 register +#define AGC_RWNXAGCSNR2_INDEX 0x00000824 +/// Reset value of the RWNXAGCSNR2 register +#define AGC_RWNXAGCSNR2_RESET 0x20212828 + +/** + * @brief Returns the current value of the RWNXAGCSNR2 register. + * The RWNXAGCSNR2 register will be read and its value returned. + * @return The current value of the RWNXAGCSNR2 register. + */ +__INLINE uint32_t agc_rwnxagcsnr2_get(void) +{ + return REG_PL_RD(AGC_RWNXAGCSNR2_ADDR); +} + +/** + * @brief Sets the RWNXAGCSNR2 register to a value. + * The RWNXAGCSNR2 register will be written. + * @param value - The value to write. + */ +__INLINE void agc_rwnxagcsnr2_set(uint32_t value) +{ + REG_PL_WR(AGC_RWNXAGCSNR2_ADDR, value); +} + +// field definitions +/// NFVALL3DB field mask +#define AGC_NFVALL3DB_MASK ((uint32_t)0x3F000000) +/// NFVALL3DB field LSB position +#define AGC_NFVALL3DB_LSB 24 +/// NFVALL3DB field width +#define AGC_NFVALL3DB_WIDTH ((uint32_t)0x00000006) +/// NFVALL2DB field mask +#define AGC_NFVALL2DB_MASK ((uint32_t)0x003F0000) +/// NFVALL2DB field LSB position +#define AGC_NFVALL2DB_LSB 16 +/// NFVALL2DB field width +#define AGC_NFVALL2DB_WIDTH ((uint32_t)0x00000006) +/// NFVALL1DB field mask +#define AGC_NFVALL1DB_MASK ((uint32_t)0x00003F00) +/// NFVALL1DB field LSB position +#define AGC_NFVALL1DB_LSB 8 +/// NFVALL1DB field width +#define AGC_NFVALL1DB_WIDTH ((uint32_t)0x00000006) +/// NFVALL0DB field mask +#define AGC_NFVALL0DB_MASK ((uint32_t)0x0000003F) +/// NFVALL0DB field LSB position +#define AGC_NFVALL0DB_LSB 0 +/// NFVALL0DB field width +#define AGC_NFVALL0DB_WIDTH ((uint32_t)0x00000006) + +/// NFVALL3DB field reset value +#define AGC_NFVALL3DB_RST 0x20 +/// NFVALL2DB field reset value +#define AGC_NFVALL2DB_RST 0x21 +/// NFVALL1DB field reset value +#define AGC_NFVALL1DB_RST 0x28 +/// NFVALL0DB field reset value +#define AGC_NFVALL0DB_RST 0x28 + +/** + * @brief Constructs a value for the RWNXAGCSNR2 register given values for its fields + * and writes the value to the register. + * + * @param[in] nfvall3db - The value to use for the NFVALL3DB field. + * @param[in] nfvall2db - The value to use for the NFVALL2DB field. + * @param[in] nfvall1db - The value to use for the NFVALL1DB field. + * @param[in] nfvall0db - The value to use for the NFVALL0DB field. + */ +__INLINE void agc_rwnxagcsnr2_pack(uint8_t nfvall3db, uint8_t nfvall2db, uint8_t nfvall1db, uint8_t nfvall0db) +{ + ASSERT_ERR((((uint32_t)nfvall3db << 24) & ~((uint32_t)0x3F000000)) == 0); + ASSERT_ERR((((uint32_t)nfvall2db << 16) & ~((uint32_t)0x003F0000)) == 0); + ASSERT_ERR((((uint32_t)nfvall1db << 8) & ~((uint32_t)0x00003F00)) == 0); + ASSERT_ERR((((uint32_t)nfvall0db << 0) & ~((uint32_t)0x0000003F)) == 0); + REG_PL_WR(AGC_RWNXAGCSNR2_ADDR, ((uint32_t)nfvall3db << 24) | ((uint32_t)nfvall2db << 16) | ((uint32_t)nfvall1db << 8) | ((uint32_t)nfvall0db << 0)); +} + +/** + * @brief Unpacks RWNXAGCSNR2's fields from current value of the RWNXAGCSNR2 register. + * + * Reads the RWNXAGCSNR2 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] nfvall3db - Will be populated with the current value of this field from the register. + * @param[out] nfvall2db - Will be populated with the current value of this field from the register. + * @param[out] nfvall1db - Will be populated with the current value of this field from the register. + * @param[out] nfvall0db - Will be populated with the current value of this field from the register. + */ +__INLINE void agc_rwnxagcsnr2_unpack(uint8_t *nfvall3db, uint8_t *nfvall2db, uint8_t *nfvall1db, uint8_t *nfvall0db) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCSNR2_ADDR); + + *nfvall3db = (localVal & ((uint32_t)0x3F000000)) >> 24; + *nfvall2db = (localVal & ((uint32_t)0x003F0000)) >> 16; + *nfvall1db = (localVal & ((uint32_t)0x00003F00)) >> 8; + *nfvall0db = (localVal & ((uint32_t)0x0000003F)) >> 0; +} + +/** + * @brief Returns the current value of the NFVALL3DB field in the RWNXAGCSNR2 register. + * + * The RWNXAGCSNR2 register will be read and the NFVALL3DB field's value will be returned. + * + * @return The current value of the NFVALL3DB field in the RWNXAGCSNR2 register. + */ +__INLINE uint8_t agc_nfvall3db_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCSNR2_ADDR); + return ((localVal & ((uint32_t)0x3F000000)) >> 24); +} + +/** + * @brief Sets the NFVALL3DB field of the RWNXAGCSNR2 register. + * + * The RWNXAGCSNR2 register will be read, modified to contain the new field value, and written. + * + * @param[in] nfvall3db - The value to set the field to. + */ +__INLINE void agc_nfvall3db_setf(uint8_t nfvall3db) +{ + ASSERT_ERR((((uint32_t)nfvall3db << 24) & ~((uint32_t)0x3F000000)) == 0); + REG_PL_WR(AGC_RWNXAGCSNR2_ADDR, (REG_PL_RD(AGC_RWNXAGCSNR2_ADDR) & ~((uint32_t)0x3F000000)) | ((uint32_t)nfvall3db << 24)); +} + +/** + * @brief Returns the current value of the NFVALL2DB field in the RWNXAGCSNR2 register. + * + * The RWNXAGCSNR2 register will be read and the NFVALL2DB field's value will be returned. + * + * @return The current value of the NFVALL2DB field in the RWNXAGCSNR2 register. + */ +__INLINE uint8_t agc_nfvall2db_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCSNR2_ADDR); + return ((localVal & ((uint32_t)0x003F0000)) >> 16); +} + +/** + * @brief Sets the NFVALL2DB field of the RWNXAGCSNR2 register. + * + * The RWNXAGCSNR2 register will be read, modified to contain the new field value, and written. + * + * @param[in] nfvall2db - The value to set the field to. + */ +__INLINE void agc_nfvall2db_setf(uint8_t nfvall2db) +{ + ASSERT_ERR((((uint32_t)nfvall2db << 16) & ~((uint32_t)0x003F0000)) == 0); + REG_PL_WR(AGC_RWNXAGCSNR2_ADDR, (REG_PL_RD(AGC_RWNXAGCSNR2_ADDR) & ~((uint32_t)0x003F0000)) | ((uint32_t)nfvall2db << 16)); +} + +/** + * @brief Returns the current value of the NFVALL1DB field in the RWNXAGCSNR2 register. + * + * The RWNXAGCSNR2 register will be read and the NFVALL1DB field's value will be returned. + * + * @return The current value of the NFVALL1DB field in the RWNXAGCSNR2 register. + */ +__INLINE uint8_t agc_nfvall1db_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCSNR2_ADDR); + return ((localVal & ((uint32_t)0x00003F00)) >> 8); +} + +/** + * @brief Sets the NFVALL1DB field of the RWNXAGCSNR2 register. + * + * The RWNXAGCSNR2 register will be read, modified to contain the new field value, and written. + * + * @param[in] nfvall1db - The value to set the field to. + */ +__INLINE void agc_nfvall1db_setf(uint8_t nfvall1db) +{ + ASSERT_ERR((((uint32_t)nfvall1db << 8) & ~((uint32_t)0x00003F00)) == 0); + REG_PL_WR(AGC_RWNXAGCSNR2_ADDR, (REG_PL_RD(AGC_RWNXAGCSNR2_ADDR) & ~((uint32_t)0x00003F00)) | ((uint32_t)nfvall1db << 8)); +} + +/** + * @brief Returns the current value of the NFVALL0DB field in the RWNXAGCSNR2 register. + * + * The RWNXAGCSNR2 register will be read and the NFVALL0DB field's value will be returned. + * + * @return The current value of the NFVALL0DB field in the RWNXAGCSNR2 register. + */ +__INLINE uint8_t agc_nfvall0db_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCSNR2_ADDR); + return ((localVal & ((uint32_t)0x0000003F)) >> 0); +} + +/** + * @brief Sets the NFVALL0DB field of the RWNXAGCSNR2 register. + * + * The RWNXAGCSNR2 register will be read, modified to contain the new field value, and written. + * + * @param[in] nfvall0db - The value to set the field to. + */ +__INLINE void agc_nfvall0db_setf(uint8_t nfvall0db) +{ + ASSERT_ERR((((uint32_t)nfvall0db << 0) & ~((uint32_t)0x0000003F)) == 0); + REG_PL_WR(AGC_RWNXAGCSNR2_ADDR, (REG_PL_RD(AGC_RWNXAGCSNR2_ADDR) & ~((uint32_t)0x0000003F)) | ((uint32_t)nfvall0db << 0)); +} + +/// @} + +/** + * @name RWNXAGCSNR3 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  29:24            NFVALM3DB   0x11
+ *  21:16            NFVALM2DB   0x12
+ *  13:08            NFVALM1DB   0x16
+ *  05:00            NFVALM0DB   0x17
+ * 
+ * + * @{ + */ + +/// Address of the RWNXAGCSNR3 register +#define AGC_RWNXAGCSNR3_ADDR 0x01002094 +/// Offset of the RWNXAGCSNR3 register from the base address +#define AGC_RWNXAGCSNR3_OFFSET 0x00002094 +/// Index of the RWNXAGCSNR3 register +#define AGC_RWNXAGCSNR3_INDEX 0x00000825 +/// Reset value of the RWNXAGCSNR3 register +#define AGC_RWNXAGCSNR3_RESET 0x11121617 + +/** + * @brief Returns the current value of the RWNXAGCSNR3 register. + * The RWNXAGCSNR3 register will be read and its value returned. + * @return The current value of the RWNXAGCSNR3 register. + */ +__INLINE uint32_t agc_rwnxagcsnr3_get(void) +{ + return REG_PL_RD(AGC_RWNXAGCSNR3_ADDR); +} + +/** + * @brief Sets the RWNXAGCSNR3 register to a value. + * The RWNXAGCSNR3 register will be written. + * @param value - The value to write. + */ +__INLINE void agc_rwnxagcsnr3_set(uint32_t value) +{ + REG_PL_WR(AGC_RWNXAGCSNR3_ADDR, value); +} + +// field definitions +/// NFVALM3DB field mask +#define AGC_NFVALM3DB_MASK ((uint32_t)0x3F000000) +/// NFVALM3DB field LSB position +#define AGC_NFVALM3DB_LSB 24 +/// NFVALM3DB field width +#define AGC_NFVALM3DB_WIDTH ((uint32_t)0x00000006) +/// NFVALM2DB field mask +#define AGC_NFVALM2DB_MASK ((uint32_t)0x003F0000) +/// NFVALM2DB field LSB position +#define AGC_NFVALM2DB_LSB 16 +/// NFVALM2DB field width +#define AGC_NFVALM2DB_WIDTH ((uint32_t)0x00000006) +/// NFVALM1DB field mask +#define AGC_NFVALM1DB_MASK ((uint32_t)0x00003F00) +/// NFVALM1DB field LSB position +#define AGC_NFVALM1DB_LSB 8 +/// NFVALM1DB field width +#define AGC_NFVALM1DB_WIDTH ((uint32_t)0x00000006) +/// NFVALM0DB field mask +#define AGC_NFVALM0DB_MASK ((uint32_t)0x0000003F) +/// NFVALM0DB field LSB position +#define AGC_NFVALM0DB_LSB 0 +/// NFVALM0DB field width +#define AGC_NFVALM0DB_WIDTH ((uint32_t)0x00000006) + +/// NFVALM3DB field reset value +#define AGC_NFVALM3DB_RST 0x11 +/// NFVALM2DB field reset value +#define AGC_NFVALM2DB_RST 0x12 +/// NFVALM1DB field reset value +#define AGC_NFVALM1DB_RST 0x16 +/// NFVALM0DB field reset value +#define AGC_NFVALM0DB_RST 0x17 + +/** + * @brief Constructs a value for the RWNXAGCSNR3 register given values for its fields + * and writes the value to the register. + * + * @param[in] nfvalm3db - The value to use for the NFVALM3DB field. + * @param[in] nfvalm2db - The value to use for the NFVALM2DB field. + * @param[in] nfvalm1db - The value to use for the NFVALM1DB field. + * @param[in] nfvalm0db - The value to use for the NFVALM0DB field. + */ +__INLINE void agc_rwnxagcsnr3_pack(uint8_t nfvalm3db, uint8_t nfvalm2db, uint8_t nfvalm1db, uint8_t nfvalm0db) +{ + ASSERT_ERR((((uint32_t)nfvalm3db << 24) & ~((uint32_t)0x3F000000)) == 0); + ASSERT_ERR((((uint32_t)nfvalm2db << 16) & ~((uint32_t)0x003F0000)) == 0); + ASSERT_ERR((((uint32_t)nfvalm1db << 8) & ~((uint32_t)0x00003F00)) == 0); + ASSERT_ERR((((uint32_t)nfvalm0db << 0) & ~((uint32_t)0x0000003F)) == 0); + REG_PL_WR(AGC_RWNXAGCSNR3_ADDR, ((uint32_t)nfvalm3db << 24) | ((uint32_t)nfvalm2db << 16) | ((uint32_t)nfvalm1db << 8) | ((uint32_t)nfvalm0db << 0)); +} + +/** + * @brief Unpacks RWNXAGCSNR3's fields from current value of the RWNXAGCSNR3 register. + * + * Reads the RWNXAGCSNR3 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] nfvalm3db - Will be populated with the current value of this field from the register. + * @param[out] nfvalm2db - Will be populated with the current value of this field from the register. + * @param[out] nfvalm1db - Will be populated with the current value of this field from the register. + * @param[out] nfvalm0db - Will be populated with the current value of this field from the register. + */ +__INLINE void agc_rwnxagcsnr3_unpack(uint8_t *nfvalm3db, uint8_t *nfvalm2db, uint8_t *nfvalm1db, uint8_t *nfvalm0db) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCSNR3_ADDR); + + *nfvalm3db = (localVal & ((uint32_t)0x3F000000)) >> 24; + *nfvalm2db = (localVal & ((uint32_t)0x003F0000)) >> 16; + *nfvalm1db = (localVal & ((uint32_t)0x00003F00)) >> 8; + *nfvalm0db = (localVal & ((uint32_t)0x0000003F)) >> 0; +} + +/** + * @brief Returns the current value of the NFVALM3DB field in the RWNXAGCSNR3 register. + * + * The RWNXAGCSNR3 register will be read and the NFVALM3DB field's value will be returned. + * + * @return The current value of the NFVALM3DB field in the RWNXAGCSNR3 register. + */ +__INLINE uint8_t agc_nfvalm3db_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCSNR3_ADDR); + return ((localVal & ((uint32_t)0x3F000000)) >> 24); +} + +/** + * @brief Sets the NFVALM3DB field of the RWNXAGCSNR3 register. + * + * The RWNXAGCSNR3 register will be read, modified to contain the new field value, and written. + * + * @param[in] nfvalm3db - The value to set the field to. + */ +__INLINE void agc_nfvalm3db_setf(uint8_t nfvalm3db) +{ + ASSERT_ERR((((uint32_t)nfvalm3db << 24) & ~((uint32_t)0x3F000000)) == 0); + REG_PL_WR(AGC_RWNXAGCSNR3_ADDR, (REG_PL_RD(AGC_RWNXAGCSNR3_ADDR) & ~((uint32_t)0x3F000000)) | ((uint32_t)nfvalm3db << 24)); +} + +/** + * @brief Returns the current value of the NFVALM2DB field in the RWNXAGCSNR3 register. + * + * The RWNXAGCSNR3 register will be read and the NFVALM2DB field's value will be returned. + * + * @return The current value of the NFVALM2DB field in the RWNXAGCSNR3 register. + */ +__INLINE uint8_t agc_nfvalm2db_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCSNR3_ADDR); + return ((localVal & ((uint32_t)0x003F0000)) >> 16); +} + +/** + * @brief Sets the NFVALM2DB field of the RWNXAGCSNR3 register. + * + * The RWNXAGCSNR3 register will be read, modified to contain the new field value, and written. + * + * @param[in] nfvalm2db - The value to set the field to. + */ +__INLINE void agc_nfvalm2db_setf(uint8_t nfvalm2db) +{ + ASSERT_ERR((((uint32_t)nfvalm2db << 16) & ~((uint32_t)0x003F0000)) == 0); + REG_PL_WR(AGC_RWNXAGCSNR3_ADDR, (REG_PL_RD(AGC_RWNXAGCSNR3_ADDR) & ~((uint32_t)0x003F0000)) | ((uint32_t)nfvalm2db << 16)); +} + +/** + * @brief Returns the current value of the NFVALM1DB field in the RWNXAGCSNR3 register. + * + * The RWNXAGCSNR3 register will be read and the NFVALM1DB field's value will be returned. + * + * @return The current value of the NFVALM1DB field in the RWNXAGCSNR3 register. + */ +__INLINE uint8_t agc_nfvalm1db_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCSNR3_ADDR); + return ((localVal & ((uint32_t)0x00003F00)) >> 8); +} + +/** + * @brief Sets the NFVALM1DB field of the RWNXAGCSNR3 register. + * + * The RWNXAGCSNR3 register will be read, modified to contain the new field value, and written. + * + * @param[in] nfvalm1db - The value to set the field to. + */ +__INLINE void agc_nfvalm1db_setf(uint8_t nfvalm1db) +{ + ASSERT_ERR((((uint32_t)nfvalm1db << 8) & ~((uint32_t)0x00003F00)) == 0); + REG_PL_WR(AGC_RWNXAGCSNR3_ADDR, (REG_PL_RD(AGC_RWNXAGCSNR3_ADDR) & ~((uint32_t)0x00003F00)) | ((uint32_t)nfvalm1db << 8)); +} + +/** + * @brief Returns the current value of the NFVALM0DB field in the RWNXAGCSNR3 register. + * + * The RWNXAGCSNR3 register will be read and the NFVALM0DB field's value will be returned. + * + * @return The current value of the NFVALM0DB field in the RWNXAGCSNR3 register. + */ +__INLINE uint8_t agc_nfvalm0db_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCSNR3_ADDR); + return ((localVal & ((uint32_t)0x0000003F)) >> 0); +} + +/** + * @brief Sets the NFVALM0DB field of the RWNXAGCSNR3 register. + * + * The RWNXAGCSNR3 register will be read, modified to contain the new field value, and written. + * + * @param[in] nfvalm0db - The value to set the field to. + */ +__INLINE void agc_nfvalm0db_setf(uint8_t nfvalm0db) +{ + ASSERT_ERR((((uint32_t)nfvalm0db << 0) & ~((uint32_t)0x0000003F)) == 0); + REG_PL_WR(AGC_RWNXAGCSNR3_ADDR, (REG_PL_RD(AGC_RWNXAGCSNR3_ADDR) & ~((uint32_t)0x0000003F)) | ((uint32_t)nfvalm0db << 0)); +} + +/// @} + +/** + * @name RWNXAGCSNR4 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  29:24            NFVALH3DB   0x4
+ *  21:16            NFVALH2DB   0x6
+ *  13:08            NFVALH1DB   0x7
+ *  05:00            NFVALH0DB   0x8
+ * 
+ * + * @{ + */ + +/// Address of the RWNXAGCSNR4 register +#define AGC_RWNXAGCSNR4_ADDR 0x01002098 +/// Offset of the RWNXAGCSNR4 register from the base address +#define AGC_RWNXAGCSNR4_OFFSET 0x00002098 +/// Index of the RWNXAGCSNR4 register +#define AGC_RWNXAGCSNR4_INDEX 0x00000826 +/// Reset value of the RWNXAGCSNR4 register +#define AGC_RWNXAGCSNR4_RESET 0x04060708 + +/** + * @brief Returns the current value of the RWNXAGCSNR4 register. + * The RWNXAGCSNR4 register will be read and its value returned. + * @return The current value of the RWNXAGCSNR4 register. + */ +__INLINE uint32_t agc_rwnxagcsnr4_get(void) +{ + return REG_PL_RD(AGC_RWNXAGCSNR4_ADDR); +} + +/** + * @brief Sets the RWNXAGCSNR4 register to a value. + * The RWNXAGCSNR4 register will be written. + * @param value - The value to write. + */ +__INLINE void agc_rwnxagcsnr4_set(uint32_t value) +{ + REG_PL_WR(AGC_RWNXAGCSNR4_ADDR, value); +} + +// field definitions +/// NFVALH3DB field mask +#define AGC_NFVALH3DB_MASK ((uint32_t)0x3F000000) +/// NFVALH3DB field LSB position +#define AGC_NFVALH3DB_LSB 24 +/// NFVALH3DB field width +#define AGC_NFVALH3DB_WIDTH ((uint32_t)0x00000006) +/// NFVALH2DB field mask +#define AGC_NFVALH2DB_MASK ((uint32_t)0x003F0000) +/// NFVALH2DB field LSB position +#define AGC_NFVALH2DB_LSB 16 +/// NFVALH2DB field width +#define AGC_NFVALH2DB_WIDTH ((uint32_t)0x00000006) +/// NFVALH1DB field mask +#define AGC_NFVALH1DB_MASK ((uint32_t)0x00003F00) +/// NFVALH1DB field LSB position +#define AGC_NFVALH1DB_LSB 8 +/// NFVALH1DB field width +#define AGC_NFVALH1DB_WIDTH ((uint32_t)0x00000006) +/// NFVALH0DB field mask +#define AGC_NFVALH0DB_MASK ((uint32_t)0x0000003F) +/// NFVALH0DB field LSB position +#define AGC_NFVALH0DB_LSB 0 +/// NFVALH0DB field width +#define AGC_NFVALH0DB_WIDTH ((uint32_t)0x00000006) + +/// NFVALH3DB field reset value +#define AGC_NFVALH3DB_RST 0x4 +/// NFVALH2DB field reset value +#define AGC_NFVALH2DB_RST 0x6 +/// NFVALH1DB field reset value +#define AGC_NFVALH1DB_RST 0x7 +/// NFVALH0DB field reset value +#define AGC_NFVALH0DB_RST 0x8 + +/** + * @brief Constructs a value for the RWNXAGCSNR4 register given values for its fields + * and writes the value to the register. + * + * @param[in] nfvalh3db - The value to use for the NFVALH3DB field. + * @param[in] nfvalh2db - The value to use for the NFVALH2DB field. + * @param[in] nfvalh1db - The value to use for the NFVALH1DB field. + * @param[in] nfvalh0db - The value to use for the NFVALH0DB field. + */ +__INLINE void agc_rwnxagcsnr4_pack(uint8_t nfvalh3db, uint8_t nfvalh2db, uint8_t nfvalh1db, uint8_t nfvalh0db) +{ + ASSERT_ERR((((uint32_t)nfvalh3db << 24) & ~((uint32_t)0x3F000000)) == 0); + ASSERT_ERR((((uint32_t)nfvalh2db << 16) & ~((uint32_t)0x003F0000)) == 0); + ASSERT_ERR((((uint32_t)nfvalh1db << 8) & ~((uint32_t)0x00003F00)) == 0); + ASSERT_ERR((((uint32_t)nfvalh0db << 0) & ~((uint32_t)0x0000003F)) == 0); + REG_PL_WR(AGC_RWNXAGCSNR4_ADDR, ((uint32_t)nfvalh3db << 24) | ((uint32_t)nfvalh2db << 16) | ((uint32_t)nfvalh1db << 8) | ((uint32_t)nfvalh0db << 0)); +} + +/** + * @brief Unpacks RWNXAGCSNR4's fields from current value of the RWNXAGCSNR4 register. + * + * Reads the RWNXAGCSNR4 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] nfvalh3db - Will be populated with the current value of this field from the register. + * @param[out] nfvalh2db - Will be populated with the current value of this field from the register. + * @param[out] nfvalh1db - Will be populated with the current value of this field from the register. + * @param[out] nfvalh0db - Will be populated with the current value of this field from the register. + */ +__INLINE void agc_rwnxagcsnr4_unpack(uint8_t *nfvalh3db, uint8_t *nfvalh2db, uint8_t *nfvalh1db, uint8_t *nfvalh0db) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCSNR4_ADDR); + + *nfvalh3db = (localVal & ((uint32_t)0x3F000000)) >> 24; + *nfvalh2db = (localVal & ((uint32_t)0x003F0000)) >> 16; + *nfvalh1db = (localVal & ((uint32_t)0x00003F00)) >> 8; + *nfvalh0db = (localVal & ((uint32_t)0x0000003F)) >> 0; +} + +/** + * @brief Returns the current value of the NFVALH3DB field in the RWNXAGCSNR4 register. + * + * The RWNXAGCSNR4 register will be read and the NFVALH3DB field's value will be returned. + * + * @return The current value of the NFVALH3DB field in the RWNXAGCSNR4 register. + */ +__INLINE uint8_t agc_nfvalh3db_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCSNR4_ADDR); + return ((localVal & ((uint32_t)0x3F000000)) >> 24); +} + +/** + * @brief Sets the NFVALH3DB field of the RWNXAGCSNR4 register. + * + * The RWNXAGCSNR4 register will be read, modified to contain the new field value, and written. + * + * @param[in] nfvalh3db - The value to set the field to. + */ +__INLINE void agc_nfvalh3db_setf(uint8_t nfvalh3db) +{ + ASSERT_ERR((((uint32_t)nfvalh3db << 24) & ~((uint32_t)0x3F000000)) == 0); + REG_PL_WR(AGC_RWNXAGCSNR4_ADDR, (REG_PL_RD(AGC_RWNXAGCSNR4_ADDR) & ~((uint32_t)0x3F000000)) | ((uint32_t)nfvalh3db << 24)); +} + +/** + * @brief Returns the current value of the NFVALH2DB field in the RWNXAGCSNR4 register. + * + * The RWNXAGCSNR4 register will be read and the NFVALH2DB field's value will be returned. + * + * @return The current value of the NFVALH2DB field in the RWNXAGCSNR4 register. + */ +__INLINE uint8_t agc_nfvalh2db_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCSNR4_ADDR); + return ((localVal & ((uint32_t)0x003F0000)) >> 16); +} + +/** + * @brief Sets the NFVALH2DB field of the RWNXAGCSNR4 register. + * + * The RWNXAGCSNR4 register will be read, modified to contain the new field value, and written. + * + * @param[in] nfvalh2db - The value to set the field to. + */ +__INLINE void agc_nfvalh2db_setf(uint8_t nfvalh2db) +{ + ASSERT_ERR((((uint32_t)nfvalh2db << 16) & ~((uint32_t)0x003F0000)) == 0); + REG_PL_WR(AGC_RWNXAGCSNR4_ADDR, (REG_PL_RD(AGC_RWNXAGCSNR4_ADDR) & ~((uint32_t)0x003F0000)) | ((uint32_t)nfvalh2db << 16)); +} + +/** + * @brief Returns the current value of the NFVALH1DB field in the RWNXAGCSNR4 register. + * + * The RWNXAGCSNR4 register will be read and the NFVALH1DB field's value will be returned. + * + * @return The current value of the NFVALH1DB field in the RWNXAGCSNR4 register. + */ +__INLINE uint8_t agc_nfvalh1db_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCSNR4_ADDR); + return ((localVal & ((uint32_t)0x00003F00)) >> 8); +} + +/** + * @brief Sets the NFVALH1DB field of the RWNXAGCSNR4 register. + * + * The RWNXAGCSNR4 register will be read, modified to contain the new field value, and written. + * + * @param[in] nfvalh1db - The value to set the field to. + */ +__INLINE void agc_nfvalh1db_setf(uint8_t nfvalh1db) +{ + ASSERT_ERR((((uint32_t)nfvalh1db << 8) & ~((uint32_t)0x00003F00)) == 0); + REG_PL_WR(AGC_RWNXAGCSNR4_ADDR, (REG_PL_RD(AGC_RWNXAGCSNR4_ADDR) & ~((uint32_t)0x00003F00)) | ((uint32_t)nfvalh1db << 8)); +} + +/** + * @brief Returns the current value of the NFVALH0DB field in the RWNXAGCSNR4 register. + * + * The RWNXAGCSNR4 register will be read and the NFVALH0DB field's value will be returned. + * + * @return The current value of the NFVALH0DB field in the RWNXAGCSNR4 register. + */ +__INLINE uint8_t agc_nfvalh0db_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCSNR4_ADDR); + return ((localVal & ((uint32_t)0x0000003F)) >> 0); +} + +/** + * @brief Sets the NFVALH0DB field of the RWNXAGCSNR4 register. + * + * The RWNXAGCSNR4 register will be read, modified to contain the new field value, and written. + * + * @param[in] nfvalh0db - The value to set the field to. + */ +__INLINE void agc_nfvalh0db_setf(uint8_t nfvalh0db) +{ + ASSERT_ERR((((uint32_t)nfvalh0db << 0) & ~((uint32_t)0x0000003F)) == 0); + REG_PL_WR(AGC_RWNXAGCSNR4_ADDR, (REG_PL_RD(AGC_RWNXAGCSNR4_ADDR) & ~((uint32_t)0x0000003F)) | ((uint32_t)nfvalh0db << 0)); +} + +/// @} + +/** + * @name RWNXAGCCOMP register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:24       IDPOWGAPDNQDBM   0x28
+ *  23:16       IDPOWGAPUPQDBM   0x28
+ *  15:08         POWINFTHRDBM   0xBA
+ *  07:00         POWSUPTHRDBM   0xBA
+ * 
+ * + * @{ + */ + +/// Address of the RWNXAGCCOMP register +#define AGC_RWNXAGCCOMP_ADDR 0x0100209C +/// Offset of the RWNXAGCCOMP register from the base address +#define AGC_RWNXAGCCOMP_OFFSET 0x0000209C +/// Index of the RWNXAGCCOMP register +#define AGC_RWNXAGCCOMP_INDEX 0x00000827 +/// Reset value of the RWNXAGCCOMP register +#define AGC_RWNXAGCCOMP_RESET 0x2828BABA + +/** + * @brief Returns the current value of the RWNXAGCCOMP register. + * The RWNXAGCCOMP register will be read and its value returned. + * @return The current value of the RWNXAGCCOMP register. + */ +__INLINE uint32_t agc_rwnxagccomp_get(void) +{ + return REG_PL_RD(AGC_RWNXAGCCOMP_ADDR); +} + +/** + * @brief Sets the RWNXAGCCOMP register to a value. + * The RWNXAGCCOMP register will be written. + * @param value - The value to write. + */ +__INLINE void agc_rwnxagccomp_set(uint32_t value) +{ + REG_PL_WR(AGC_RWNXAGCCOMP_ADDR, value); +} + +// field definitions +/// IDPOWGAPDNQDBM field mask +#define AGC_IDPOWGAPDNQDBM_MASK ((uint32_t)0xFF000000) +/// IDPOWGAPDNQDBM field LSB position +#define AGC_IDPOWGAPDNQDBM_LSB 24 +/// IDPOWGAPDNQDBM field width +#define AGC_IDPOWGAPDNQDBM_WIDTH ((uint32_t)0x00000008) +/// IDPOWGAPUPQDBM field mask +#define AGC_IDPOWGAPUPQDBM_MASK ((uint32_t)0x00FF0000) +/// IDPOWGAPUPQDBM field LSB position +#define AGC_IDPOWGAPUPQDBM_LSB 16 +/// IDPOWGAPUPQDBM field width +#define AGC_IDPOWGAPUPQDBM_WIDTH ((uint32_t)0x00000008) +/// POWINFTHRDBM field mask +#define AGC_POWINFTHRDBM_MASK ((uint32_t)0x0000FF00) +/// POWINFTHRDBM field LSB position +#define AGC_POWINFTHRDBM_LSB 8 +/// POWINFTHRDBM field width +#define AGC_POWINFTHRDBM_WIDTH ((uint32_t)0x00000008) +/// POWSUPTHRDBM field mask +#define AGC_POWSUPTHRDBM_MASK ((uint32_t)0x000000FF) +/// POWSUPTHRDBM field LSB position +#define AGC_POWSUPTHRDBM_LSB 0 +/// POWSUPTHRDBM field width +#define AGC_POWSUPTHRDBM_WIDTH ((uint32_t)0x00000008) + +/// IDPOWGAPDNQDBM field reset value +#define AGC_IDPOWGAPDNQDBM_RST 0x28 +/// IDPOWGAPUPQDBM field reset value +#define AGC_IDPOWGAPUPQDBM_RST 0x28 +/// POWINFTHRDBM field reset value +#define AGC_POWINFTHRDBM_RST 0xBA +/// POWSUPTHRDBM field reset value +#define AGC_POWSUPTHRDBM_RST 0xBA + +/** + * @brief Constructs a value for the RWNXAGCCOMP register given values for its fields + * and writes the value to the register. + * + * @param[in] idpowgapdnqdbm - The value to use for the IDPOWGAPDNQDBM field. + * @param[in] idpowgapupqdbm - The value to use for the IDPOWGAPUPQDBM field. + * @param[in] powinfthrdbm - The value to use for the POWINFTHRDBM field. + * @param[in] powsupthrdbm - The value to use for the POWSUPTHRDBM field. + */ +__INLINE void agc_rwnxagccomp_pack(uint8_t idpowgapdnqdbm, uint8_t idpowgapupqdbm, uint8_t powinfthrdbm, uint8_t powsupthrdbm) +{ + ASSERT_ERR((((uint32_t)idpowgapdnqdbm << 24) & ~((uint32_t)0xFF000000)) == 0); + ASSERT_ERR((((uint32_t)idpowgapupqdbm << 16) & ~((uint32_t)0x00FF0000)) == 0); + ASSERT_ERR((((uint32_t)powinfthrdbm << 8) & ~((uint32_t)0x0000FF00)) == 0); + ASSERT_ERR((((uint32_t)powsupthrdbm << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(AGC_RWNXAGCCOMP_ADDR, ((uint32_t)idpowgapdnqdbm << 24) | ((uint32_t)idpowgapupqdbm << 16) | ((uint32_t)powinfthrdbm << 8) | ((uint32_t)powsupthrdbm << 0)); +} + +/** + * @brief Unpacks RWNXAGCCOMP's fields from current value of the RWNXAGCCOMP register. + * + * Reads the RWNXAGCCOMP register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] idpowgapdnqdbm - Will be populated with the current value of this field from the register. + * @param[out] idpowgapupqdbm - Will be populated with the current value of this field from the register. + * @param[out] powinfthrdbm - Will be populated with the current value of this field from the register. + * @param[out] powsupthrdbm - Will be populated with the current value of this field from the register. + */ +__INLINE void agc_rwnxagccomp_unpack(uint8_t *idpowgapdnqdbm, uint8_t *idpowgapupqdbm, uint8_t *powinfthrdbm, uint8_t *powsupthrdbm) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCCOMP_ADDR); + + *idpowgapdnqdbm = (localVal & ((uint32_t)0xFF000000)) >> 24; + *idpowgapupqdbm = (localVal & ((uint32_t)0x00FF0000)) >> 16; + *powinfthrdbm = (localVal & ((uint32_t)0x0000FF00)) >> 8; + *powsupthrdbm = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +/** + * @brief Returns the current value of the IDPOWGAPDNQDBM field in the RWNXAGCCOMP register. + * + * The RWNXAGCCOMP register will be read and the IDPOWGAPDNQDBM field's value will be returned. + * + * @return The current value of the IDPOWGAPDNQDBM field in the RWNXAGCCOMP register. + */ +__INLINE uint8_t agc_idpowgapdnqdbm_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCCOMP_ADDR); + return ((localVal & ((uint32_t)0xFF000000)) >> 24); +} + +/** + * @brief Sets the IDPOWGAPDNQDBM field of the RWNXAGCCOMP register. + * + * The RWNXAGCCOMP register will be read, modified to contain the new field value, and written. + * + * @param[in] idpowgapdnqdbm - The value to set the field to. + */ +__INLINE void agc_idpowgapdnqdbm_setf(uint8_t idpowgapdnqdbm) +{ + ASSERT_ERR((((uint32_t)idpowgapdnqdbm << 24) & ~((uint32_t)0xFF000000)) == 0); + REG_PL_WR(AGC_RWNXAGCCOMP_ADDR, (REG_PL_RD(AGC_RWNXAGCCOMP_ADDR) & ~((uint32_t)0xFF000000)) | ((uint32_t)idpowgapdnqdbm << 24)); +} + +/** + * @brief Returns the current value of the IDPOWGAPUPQDBM field in the RWNXAGCCOMP register. + * + * The RWNXAGCCOMP register will be read and the IDPOWGAPUPQDBM field's value will be returned. + * + * @return The current value of the IDPOWGAPUPQDBM field in the RWNXAGCCOMP register. + */ +__INLINE uint8_t agc_idpowgapupqdbm_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCCOMP_ADDR); + return ((localVal & ((uint32_t)0x00FF0000)) >> 16); +} + +/** + * @brief Sets the IDPOWGAPUPQDBM field of the RWNXAGCCOMP register. + * + * The RWNXAGCCOMP register will be read, modified to contain the new field value, and written. + * + * @param[in] idpowgapupqdbm - The value to set the field to. + */ +__INLINE void agc_idpowgapupqdbm_setf(uint8_t idpowgapupqdbm) +{ + ASSERT_ERR((((uint32_t)idpowgapupqdbm << 16) & ~((uint32_t)0x00FF0000)) == 0); + REG_PL_WR(AGC_RWNXAGCCOMP_ADDR, (REG_PL_RD(AGC_RWNXAGCCOMP_ADDR) & ~((uint32_t)0x00FF0000)) | ((uint32_t)idpowgapupqdbm << 16)); +} + +/** + * @brief Returns the current value of the POWINFTHRDBM field in the RWNXAGCCOMP register. + * + * The RWNXAGCCOMP register will be read and the POWINFTHRDBM field's value will be returned. + * + * @return The current value of the POWINFTHRDBM field in the RWNXAGCCOMP register. + */ +__INLINE uint8_t agc_powinfthrdbm_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCCOMP_ADDR); + return ((localVal & ((uint32_t)0x0000FF00)) >> 8); +} + +/** + * @brief Sets the POWINFTHRDBM field of the RWNXAGCCOMP register. + * + * The RWNXAGCCOMP register will be read, modified to contain the new field value, and written. + * + * @param[in] powinfthrdbm - The value to set the field to. + */ +__INLINE void agc_powinfthrdbm_setf(uint8_t powinfthrdbm) +{ + ASSERT_ERR((((uint32_t)powinfthrdbm << 8) & ~((uint32_t)0x0000FF00)) == 0); + REG_PL_WR(AGC_RWNXAGCCOMP_ADDR, (REG_PL_RD(AGC_RWNXAGCCOMP_ADDR) & ~((uint32_t)0x0000FF00)) | ((uint32_t)powinfthrdbm << 8)); +} + +/** + * @brief Returns the current value of the POWSUPTHRDBM field in the RWNXAGCCOMP register. + * + * The RWNXAGCCOMP register will be read and the POWSUPTHRDBM field's value will be returned. + * + * @return The current value of the POWSUPTHRDBM field in the RWNXAGCCOMP register. + */ +__INLINE uint8_t agc_powsupthrdbm_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCCOMP_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +/** + * @brief Sets the POWSUPTHRDBM field of the RWNXAGCCOMP register. + * + * The RWNXAGCCOMP register will be read, modified to contain the new field value, and written. + * + * @param[in] powsupthrdbm - The value to set the field to. + */ +__INLINE void agc_powsupthrdbm_setf(uint8_t powsupthrdbm) +{ + ASSERT_ERR((((uint32_t)powsupthrdbm << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(AGC_RWNXAGCCOMP_ADDR, (REG_PL_RD(AGC_RWNXAGCCOMP_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)powsupthrdbm << 0)); +} + +/// @} + +/** + * @name RWNXAGCRADAR register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  27:24          FREQSINGGAP   0x0
+ *  23:16             FREQSING   0x0
+ *  11:08           FOMSINGGAP   0x0
+ *  07:00              FOMSING   0x0
+ * 
+ * + * @{ + */ + +/// Address of the RWNXAGCRADAR register +#define AGC_RWNXAGCRADAR_ADDR 0x010020A0 +/// Offset of the RWNXAGCRADAR register from the base address +#define AGC_RWNXAGCRADAR_OFFSET 0x000020A0 +/// Index of the RWNXAGCRADAR register +#define AGC_RWNXAGCRADAR_INDEX 0x00000828 +/// Reset value of the RWNXAGCRADAR register +#define AGC_RWNXAGCRADAR_RESET 0x00000000 + +/** + * @brief Returns the current value of the RWNXAGCRADAR register. + * The RWNXAGCRADAR register will be read and its value returned. + * @return The current value of the RWNXAGCRADAR register. + */ +__INLINE uint32_t agc_rwnxagcradar_get(void) +{ + return REG_PL_RD(AGC_RWNXAGCRADAR_ADDR); +} + +/** + * @brief Sets the RWNXAGCRADAR register to a value. + * The RWNXAGCRADAR register will be written. + * @param value - The value to write. + */ +__INLINE void agc_rwnxagcradar_set(uint32_t value) +{ + REG_PL_WR(AGC_RWNXAGCRADAR_ADDR, value); +} + +// field definitions +/// FREQSINGGAP field mask +#define AGC_FREQSINGGAP_MASK ((uint32_t)0x0F000000) +/// FREQSINGGAP field LSB position +#define AGC_FREQSINGGAP_LSB 24 +/// FREQSINGGAP field width +#define AGC_FREQSINGGAP_WIDTH ((uint32_t)0x00000004) +/// FREQSING field mask +#define AGC_FREQSING_MASK ((uint32_t)0x00FF0000) +/// FREQSING field LSB position +#define AGC_FREQSING_LSB 16 +/// FREQSING field width +#define AGC_FREQSING_WIDTH ((uint32_t)0x00000008) +/// FOMSINGGAP field mask +#define AGC_FOMSINGGAP_MASK ((uint32_t)0x00000F00) +/// FOMSINGGAP field LSB position +#define AGC_FOMSINGGAP_LSB 8 +/// FOMSINGGAP field width +#define AGC_FOMSINGGAP_WIDTH ((uint32_t)0x00000004) +/// FOMSING field mask +#define AGC_FOMSING_MASK ((uint32_t)0x000000FF) +/// FOMSING field LSB position +#define AGC_FOMSING_LSB 0 +/// FOMSING field width +#define AGC_FOMSING_WIDTH ((uint32_t)0x00000008) + +/// FREQSINGGAP field reset value +#define AGC_FREQSINGGAP_RST 0x0 +/// FREQSING field reset value +#define AGC_FREQSING_RST 0x0 +/// FOMSINGGAP field reset value +#define AGC_FOMSINGGAP_RST 0x0 +/// FOMSING field reset value +#define AGC_FOMSING_RST 0x0 + +/** + * @brief Constructs a value for the RWNXAGCRADAR register given values for its fields + * and writes the value to the register. + * + * @param[in] freqsinggap - The value to use for the FREQSINGGAP field. + * @param[in] freqsing - The value to use for the FREQSING field. + * @param[in] fomsinggap - The value to use for the FOMSINGGAP field. + * @param[in] fomsing - The value to use for the FOMSING field. + */ +__INLINE void agc_rwnxagcradar_pack(uint8_t freqsinggap, uint8_t freqsing, uint8_t fomsinggap, uint8_t fomsing) +{ + ASSERT_ERR((((uint32_t)freqsinggap << 24) & ~((uint32_t)0x0F000000)) == 0); + ASSERT_ERR((((uint32_t)freqsing << 16) & ~((uint32_t)0x00FF0000)) == 0); + ASSERT_ERR((((uint32_t)fomsinggap << 8) & ~((uint32_t)0x00000F00)) == 0); + ASSERT_ERR((((uint32_t)fomsing << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(AGC_RWNXAGCRADAR_ADDR, ((uint32_t)freqsinggap << 24) | ((uint32_t)freqsing << 16) | ((uint32_t)fomsinggap << 8) | ((uint32_t)fomsing << 0)); +} + +/** + * @brief Unpacks RWNXAGCRADAR's fields from current value of the RWNXAGCRADAR register. + * + * Reads the RWNXAGCRADAR register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] freqsinggap - Will be populated with the current value of this field from the register. + * @param[out] freqsing - Will be populated with the current value of this field from the register. + * @param[out] fomsinggap - Will be populated with the current value of this field from the register. + * @param[out] fomsing - Will be populated with the current value of this field from the register. + */ +__INLINE void agc_rwnxagcradar_unpack(uint8_t *freqsinggap, uint8_t *freqsing, uint8_t *fomsinggap, uint8_t *fomsing) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCRADAR_ADDR); + + *freqsinggap = (localVal & ((uint32_t)0x0F000000)) >> 24; + *freqsing = (localVal & ((uint32_t)0x00FF0000)) >> 16; + *fomsinggap = (localVal & ((uint32_t)0x00000F00)) >> 8; + *fomsing = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +/** + * @brief Returns the current value of the FREQSINGGAP field in the RWNXAGCRADAR register. + * + * The RWNXAGCRADAR register will be read and the FREQSINGGAP field's value will be returned. + * + * @return The current value of the FREQSINGGAP field in the RWNXAGCRADAR register. + */ +__INLINE uint8_t agc_freqsinggap_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCRADAR_ADDR); + return ((localVal & ((uint32_t)0x0F000000)) >> 24); +} + +/** + * @brief Sets the FREQSINGGAP field of the RWNXAGCRADAR register. + * + * The RWNXAGCRADAR register will be read, modified to contain the new field value, and written. + * + * @param[in] freqsinggap - The value to set the field to. + */ +__INLINE void agc_freqsinggap_setf(uint8_t freqsinggap) +{ + ASSERT_ERR((((uint32_t)freqsinggap << 24) & ~((uint32_t)0x0F000000)) == 0); + REG_PL_WR(AGC_RWNXAGCRADAR_ADDR, (REG_PL_RD(AGC_RWNXAGCRADAR_ADDR) & ~((uint32_t)0x0F000000)) | ((uint32_t)freqsinggap << 24)); +} + +/** + * @brief Returns the current value of the FREQSING field in the RWNXAGCRADAR register. + * + * The RWNXAGCRADAR register will be read and the FREQSING field's value will be returned. + * + * @return The current value of the FREQSING field in the RWNXAGCRADAR register. + */ +__INLINE uint8_t agc_freqsing_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCRADAR_ADDR); + return ((localVal & ((uint32_t)0x00FF0000)) >> 16); +} + +/** + * @brief Sets the FREQSING field of the RWNXAGCRADAR register. + * + * The RWNXAGCRADAR register will be read, modified to contain the new field value, and written. + * + * @param[in] freqsing - The value to set the field to. + */ +__INLINE void agc_freqsing_setf(uint8_t freqsing) +{ + ASSERT_ERR((((uint32_t)freqsing << 16) & ~((uint32_t)0x00FF0000)) == 0); + REG_PL_WR(AGC_RWNXAGCRADAR_ADDR, (REG_PL_RD(AGC_RWNXAGCRADAR_ADDR) & ~((uint32_t)0x00FF0000)) | ((uint32_t)freqsing << 16)); +} + +/** + * @brief Returns the current value of the FOMSINGGAP field in the RWNXAGCRADAR register. + * + * The RWNXAGCRADAR register will be read and the FOMSINGGAP field's value will be returned. + * + * @return The current value of the FOMSINGGAP field in the RWNXAGCRADAR register. + */ +__INLINE uint8_t agc_fomsinggap_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCRADAR_ADDR); + return ((localVal & ((uint32_t)0x00000F00)) >> 8); +} + +/** + * @brief Sets the FOMSINGGAP field of the RWNXAGCRADAR register. + * + * The RWNXAGCRADAR register will be read, modified to contain the new field value, and written. + * + * @param[in] fomsinggap - The value to set the field to. + */ +__INLINE void agc_fomsinggap_setf(uint8_t fomsinggap) +{ + ASSERT_ERR((((uint32_t)fomsinggap << 8) & ~((uint32_t)0x00000F00)) == 0); + REG_PL_WR(AGC_RWNXAGCRADAR_ADDR, (REG_PL_RD(AGC_RWNXAGCRADAR_ADDR) & ~((uint32_t)0x00000F00)) | ((uint32_t)fomsinggap << 8)); +} + +/** + * @brief Returns the current value of the FOMSING field in the RWNXAGCRADAR register. + * + * The RWNXAGCRADAR register will be read and the FOMSING field's value will be returned. + * + * @return The current value of the FOMSING field in the RWNXAGCRADAR register. + */ +__INLINE uint8_t agc_fomsing_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCRADAR_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +/** + * @brief Sets the FOMSING field of the RWNXAGCRADAR register. + * + * The RWNXAGCRADAR register will be read, modified to contain the new field value, and written. + * + * @param[in] fomsing - The value to set the field to. + */ +__INLINE void agc_fomsing_setf(uint8_t fomsing) +{ + ASSERT_ERR((((uint32_t)fomsing << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(AGC_RWNXAGCRADAR_ADDR, (REG_PL_RD(AGC_RWNXAGCRADAR_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)fomsing << 0)); +} + +/// @} + +/** + * @name RWNXAGCRADARTIM register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31      PULSETIMERCLEAR   0
+ *  18:16      PULSEIRQFIFOTHR   0x3
+ *  07:00      PULSEIRQTIMEOUT   0x8
+ * 
+ * + * @{ + */ + +/// Address of the RWNXAGCRADARTIM register +#define AGC_RWNXAGCRADARTIM_ADDR 0x010020A4 +/// Offset of the RWNXAGCRADARTIM register from the base address +#define AGC_RWNXAGCRADARTIM_OFFSET 0x000020A4 +/// Index of the RWNXAGCRADARTIM register +#define AGC_RWNXAGCRADARTIM_INDEX 0x00000829 +/// Reset value of the RWNXAGCRADARTIM register +#define AGC_RWNXAGCRADARTIM_RESET 0x00030008 + +/** + * @brief Returns the current value of the RWNXAGCRADARTIM register. + * The RWNXAGCRADARTIM register will be read and its value returned. + * @return The current value of the RWNXAGCRADARTIM register. + */ +__INLINE uint32_t agc_rwnxagcradartim_get(void) +{ + return REG_PL_RD(AGC_RWNXAGCRADARTIM_ADDR); +} + +/** + * @brief Sets the RWNXAGCRADARTIM register to a value. + * The RWNXAGCRADARTIM register will be written. + * @param value - The value to write. + */ +__INLINE void agc_rwnxagcradartim_set(uint32_t value) +{ + REG_PL_WR(AGC_RWNXAGCRADARTIM_ADDR, value); +} + +// field definitions +/// PULSETIMERCLEAR field bit +#define AGC_PULSETIMERCLEAR_BIT ((uint32_t)0x80000000) +/// PULSETIMERCLEAR field position +#define AGC_PULSETIMERCLEAR_POS 31 +/// PULSEIRQFIFOTHR field mask +#define AGC_PULSEIRQFIFOTHR_MASK ((uint32_t)0x00070000) +/// PULSEIRQFIFOTHR field LSB position +#define AGC_PULSEIRQFIFOTHR_LSB 16 +/// PULSEIRQFIFOTHR field width +#define AGC_PULSEIRQFIFOTHR_WIDTH ((uint32_t)0x00000003) +/// PULSEIRQTIMEOUT field mask +#define AGC_PULSEIRQTIMEOUT_MASK ((uint32_t)0x000000FF) +/// PULSEIRQTIMEOUT field LSB position +#define AGC_PULSEIRQTIMEOUT_LSB 0 +/// PULSEIRQTIMEOUT field width +#define AGC_PULSEIRQTIMEOUT_WIDTH ((uint32_t)0x00000008) + +/// PULSETIMERCLEAR field reset value +#define AGC_PULSETIMERCLEAR_RST 0x0 +/// PULSEIRQFIFOTHR field reset value +#define AGC_PULSEIRQFIFOTHR_RST 0x3 +/// PULSEIRQTIMEOUT field reset value +#define AGC_PULSEIRQTIMEOUT_RST 0x8 + +/** + * @brief Constructs a value for the RWNXAGCRADARTIM register given values for its fields + * and writes the value to the register. + * + * @param[in] pulsetimerclear - The value to use for the PULSETIMERCLEAR field. + * @param[in] pulseirqfifothr - The value to use for the PULSEIRQFIFOTHR field. + * @param[in] pulseirqtimeout - The value to use for the PULSEIRQTIMEOUT field. + */ +__INLINE void agc_rwnxagcradartim_pack(uint8_t pulsetimerclear, uint8_t pulseirqfifothr, uint8_t pulseirqtimeout) +{ + ASSERT_ERR((((uint32_t)pulsetimerclear << 31) & ~((uint32_t)0x80000000)) == 0); + ASSERT_ERR((((uint32_t)pulseirqfifothr << 16) & ~((uint32_t)0x00070000)) == 0); + ASSERT_ERR((((uint32_t)pulseirqtimeout << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(AGC_RWNXAGCRADARTIM_ADDR, ((uint32_t)pulsetimerclear << 31) | ((uint32_t)pulseirqfifothr << 16) | ((uint32_t)pulseirqtimeout << 0)); +} + +/** + * @brief Unpacks RWNXAGCRADARTIM's fields from current value of the RWNXAGCRADARTIM register. + * + * Reads the RWNXAGCRADARTIM register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] pulsetimerclear - Will be populated with the current value of this field from the register. + * @param[out] pulseirqfifothr - Will be populated with the current value of this field from the register. + * @param[out] pulseirqtimeout - Will be populated with the current value of this field from the register. + */ +__INLINE void agc_rwnxagcradartim_unpack(uint8_t *pulsetimerclear, uint8_t *pulseirqfifothr, uint8_t *pulseirqtimeout) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCRADARTIM_ADDR); + + *pulsetimerclear = (localVal & ((uint32_t)0x80000000)) >> 31; + *pulseirqfifothr = (localVal & ((uint32_t)0x00070000)) >> 16; + *pulseirqtimeout = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +/** + * @brief Returns the current value of the PULSETIMERCLEAR field in the RWNXAGCRADARTIM register. + * + * The RWNXAGCRADARTIM register will be read and the PULSETIMERCLEAR field's value will be returned. + * + * @return The current value of the PULSETIMERCLEAR field in the RWNXAGCRADARTIM register. + */ +__INLINE uint8_t agc_pulsetimerclear_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCRADARTIM_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +/** + * @brief Sets the PULSETIMERCLEAR field of the RWNXAGCRADARTIM register. + * + * The RWNXAGCRADARTIM register will be read, modified to contain the new field value, and written. + * + * @param[in] pulsetimerclear - The value to set the field to. + */ +__INLINE void agc_pulsetimerclear_setf(uint8_t pulsetimerclear) +{ + ASSERT_ERR((((uint32_t)pulsetimerclear << 31) & ~((uint32_t)0x80000000)) == 0); + REG_PL_WR(AGC_RWNXAGCRADARTIM_ADDR, (REG_PL_RD(AGC_RWNXAGCRADARTIM_ADDR) & ~((uint32_t)0x80000000)) | ((uint32_t)pulsetimerclear << 31)); +} + +/** + * @brief Returns the current value of the PULSEIRQFIFOTHR field in the RWNXAGCRADARTIM register. + * + * The RWNXAGCRADARTIM register will be read and the PULSEIRQFIFOTHR field's value will be returned. + * + * @return The current value of the PULSEIRQFIFOTHR field in the RWNXAGCRADARTIM register. + */ +__INLINE uint8_t agc_pulseirqfifothr_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCRADARTIM_ADDR); + return ((localVal & ((uint32_t)0x00070000)) >> 16); +} + +/** + * @brief Sets the PULSEIRQFIFOTHR field of the RWNXAGCRADARTIM register. + * + * The RWNXAGCRADARTIM register will be read, modified to contain the new field value, and written. + * + * @param[in] pulseirqfifothr - The value to set the field to. + */ +__INLINE void agc_pulseirqfifothr_setf(uint8_t pulseirqfifothr) +{ + ASSERT_ERR((((uint32_t)pulseirqfifothr << 16) & ~((uint32_t)0x00070000)) == 0); + REG_PL_WR(AGC_RWNXAGCRADARTIM_ADDR, (REG_PL_RD(AGC_RWNXAGCRADARTIM_ADDR) & ~((uint32_t)0x00070000)) | ((uint32_t)pulseirqfifothr << 16)); +} + +/** + * @brief Returns the current value of the PULSEIRQTIMEOUT field in the RWNXAGCRADARTIM register. + * + * The RWNXAGCRADARTIM register will be read and the PULSEIRQTIMEOUT field's value will be returned. + * + * @return The current value of the PULSEIRQTIMEOUT field in the RWNXAGCRADARTIM register. + */ +__INLINE uint8_t agc_pulseirqtimeout_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCRADARTIM_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +/** + * @brief Sets the PULSEIRQTIMEOUT field of the RWNXAGCRADARTIM register. + * + * The RWNXAGCRADARTIM register will be read, modified to contain the new field value, and written. + * + * @param[in] pulseirqtimeout - The value to set the field to. + */ +__INLINE void agc_pulseirqtimeout_setf(uint8_t pulseirqtimeout) +{ + ASSERT_ERR((((uint32_t)pulseirqtimeout << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(AGC_RWNXAGCRADARTIM_ADDR, (REG_PL_RD(AGC_RWNXAGCRADARTIM_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)pulseirqtimeout << 0)); +} + +/// @} + +/** + * @name RWNXAGCDSP3 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  07:00        INBDPOWDBVTHR   0xBF
+ * 
+ * + * @{ + */ + +/// Address of the RWNXAGCDSP3 register +#define AGC_RWNXAGCDSP3_ADDR 0x010020A8 +/// Offset of the RWNXAGCDSP3 register from the base address +#define AGC_RWNXAGCDSP3_OFFSET 0x000020A8 +/// Index of the RWNXAGCDSP3 register +#define AGC_RWNXAGCDSP3_INDEX 0x0000082A +/// Reset value of the RWNXAGCDSP3 register +#define AGC_RWNXAGCDSP3_RESET 0x000000BF + +/** + * @brief Returns the current value of the RWNXAGCDSP3 register. + * The RWNXAGCDSP3 register will be read and its value returned. + * @return The current value of the RWNXAGCDSP3 register. + */ +__INLINE uint32_t agc_rwnxagcdsp3_get(void) +{ + return REG_PL_RD(AGC_RWNXAGCDSP3_ADDR); +} + +/** + * @brief Sets the RWNXAGCDSP3 register to a value. + * The RWNXAGCDSP3 register will be written. + * @param value - The value to write. + */ +__INLINE void agc_rwnxagcdsp3_set(uint32_t value) +{ + REG_PL_WR(AGC_RWNXAGCDSP3_ADDR, value); +} + +// field definitions +/// INBDPOWDBVTHR field mask +#define AGC_INBDPOWDBVTHR_MASK ((uint32_t)0x000000FF) +/// INBDPOWDBVTHR field LSB position +#define AGC_INBDPOWDBVTHR_LSB 0 +/// INBDPOWDBVTHR field width +#define AGC_INBDPOWDBVTHR_WIDTH ((uint32_t)0x00000008) + +/// INBDPOWDBVTHR field reset value +#define AGC_INBDPOWDBVTHR_RST 0xBF + +/** + * @brief Returns the current value of the INBDPOWDBVTHR field in the RWNXAGCDSP3 register. + * + * The RWNXAGCDSP3 register will be read and the INBDPOWDBVTHR field's value will be returned. + * + * @return The current value of the INBDPOWDBVTHR field in the RWNXAGCDSP3 register. + */ +__INLINE uint8_t agc_inbdpowdbvthr_getf(void) +{ + uint32_t localVal = REG_PL_RD(AGC_RWNXAGCDSP3_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x000000FF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the INBDPOWDBVTHR field of the RWNXAGCDSP3 register. + * + * The RWNXAGCDSP3 register will be read, modified to contain the new field value, and written. + * + * @param[in] inbdpowdbvthr - The value to set the field to. + */ +__INLINE void agc_inbdpowdbvthr_setf(uint8_t inbdpowdbvthr) +{ + ASSERT_ERR((((uint32_t)inbdpowdbvthr << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(AGC_RWNXAGCDSP3_ADDR, (uint32_t)inbdpowdbvthr << 0); +} + +/// @} + +/* On SOC platform, write agc value to (0x01C0A000) may not right */ +#define PHY_AGC_UCODE_ADDR (0x0100A000) + +#endif // _REG_AGC_H_ + +/// @} + diff --git a/beken_os/beken378/driver/common/reg/reg_dma.h b/beken_os/beken378/driver/common/reg/reg_dma.h new file mode 100755 index 0000000..7e2561d --- /dev/null +++ b/beken_os/beken378/driver/common/reg/reg_dma.h @@ -0,0 +1,860 @@ +#ifndef _REG_DMA_H_ +#define _REG_DMA_H_ + +#include "co_int.h" +#include "_reg_dma.h" +#include "compiler.h" +#include "arch.h" +#include "reg_access.h" + +#define REG_DMA_COUNT 49 + +#define REG_DMA_DECODING_MASK 0x000000FF + +/** + * @brief CH_LLI_ROOT register definition + */ + +__INLINE uint32_t dma_ch_lli_root_get(int reg_idx) +{ + return 0; +} + +__INLINE void dma_ch_lli_root_set(int reg_idx, uint32_t value) +{ +} + +/** + * @brief DMA_STATUS register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     29      DOWN_STREAM_BSY   0
+ *     28        UP_STREAM_BSY   0
+ *     27         ARB_Q3_VALID   0
+ *     26         ARB_Q2_VALID   0
+ *     25         ARB_Q1_VALID   0
+ *     24         ARB_Q0_VALID   0
+ *  23:20        REQUEST_STATE   0x0
+ *     19          CH3_STOPPED   0
+ *     18          CH2_STOPPED   0
+ *     17          CH1_STOPPED   0
+ *     16          CH0_STOPPED   0
+ *  15:00             OFT_FREE   0x0
+ * 
+ */ +#define DMA_DMA_STATUS_ADDR 0x10A00010 +#define DMA_DMA_STATUS_OFFSET 0x00000010 +#define DMA_DMA_STATUS_INDEX 0x00000004 +#define DMA_DMA_STATUS_RESET 0x00000000 + +__INLINE uint32_t dma_dma_status_get(void) +{ + return 0; +} + +// field definitions +#define DMA_DOWN_STREAM_BSY_BIT ((uint32_t)0x20000000) +#define DMA_DOWN_STREAM_BSY_POS 29 +#define DMA_UP_STREAM_BSY_BIT ((uint32_t)0x10000000) +#define DMA_UP_STREAM_BSY_POS 28 +#define DMA_ARB_Q3_VALID_BIT ((uint32_t)0x08000000) +#define DMA_ARB_Q3_VALID_POS 27 +#define DMA_ARB_Q2_VALID_BIT ((uint32_t)0x04000000) +#define DMA_ARB_Q2_VALID_POS 26 +#define DMA_ARB_Q1_VALID_BIT ((uint32_t)0x02000000) +#define DMA_ARB_Q1_VALID_POS 25 +#define DMA_ARB_Q0_VALID_BIT ((uint32_t)0x01000000) +#define DMA_ARB_Q0_VALID_POS 24 +#define DMA_REQUEST_STATE_MASK ((uint32_t)0x00F00000) +#define DMA_REQUEST_STATE_LSB 20 +#define DMA_REQUEST_STATE_WIDTH ((uint32_t)0x00000004) +#define DMA_CH3_STOPPED_BIT ((uint32_t)0x00080000) +#define DMA_CH3_STOPPED_POS 19 +#define DMA_CH2_STOPPED_BIT ((uint32_t)0x00040000) +#define DMA_CH2_STOPPED_POS 18 +#define DMA_CH1_STOPPED_BIT ((uint32_t)0x00020000) +#define DMA_CH1_STOPPED_POS 17 +#define DMA_CH0_STOPPED_BIT ((uint32_t)0x00010000) +#define DMA_CH0_STOPPED_POS 16 +#define DMA_OFT_FREE_MASK ((uint32_t)0x0000FFFF) +#define DMA_OFT_FREE_LSB 0 +#define DMA_OFT_FREE_WIDTH ((uint32_t)0x00000010) + +#define DMA_DOWN_STREAM_BSY_RST 0x0 +#define DMA_UP_STREAM_BSY_RST 0x0 +#define DMA_ARB_Q3_VALID_RST 0x0 +#define DMA_ARB_Q2_VALID_RST 0x0 +#define DMA_ARB_Q1_VALID_RST 0x0 +#define DMA_ARB_Q0_VALID_RST 0x0 +#define DMA_REQUEST_STATE_RST 0x0 +#define DMA_CH3_STOPPED_RST 0x0 +#define DMA_CH2_STOPPED_RST 0x0 +#define DMA_CH1_STOPPED_RST 0x0 +#define DMA_CH0_STOPPED_RST 0x0 +#define DMA_OFT_FREE_RST 0x0 + +__INLINE void dma_dma_status_unpack(uint8_t *downstreambsy, uint8_t *upstreambsy, uint8_t *arbq3valid, uint8_t *arbq2valid, uint8_t *arbq1valid, uint8_t *arbq0valid, uint8_t *requeststate, uint8_t *ch3stopped, uint8_t *ch2stopped, uint8_t *ch1stopped, uint8_t *ch0stopped, uint16_t *oftfree) +{ +} + +__INLINE uint8_t dma_dma_status_down_stream_bsy_getf(void) +{ + return 0; +} + +__INLINE uint8_t dma_dma_status_up_stream_bsy_getf(void) +{ + return 0; +} + +__INLINE uint8_t dma_dma_status_arb_q3_valid_getf(void) +{ + return 0; +} + +__INLINE uint8_t dma_dma_status_arb_q2_valid_getf(void) +{ + return 0; +} + +__INLINE uint8_t dma_dma_status_arb_q1_valid_getf(void) +{ + return 0; +} + +__INLINE uint8_t dma_dma_status_arb_q0_valid_getf(void) +{ + return 0; +} + +__INLINE uint8_t dma_dma_status_request_state_getf(void) +{ + return 0; +} + +__INLINE uint8_t dma_dma_status_ch3_stopped_getf(void) +{ + return 0; +} + +__INLINE uint8_t dma_dma_status_ch2_stopped_getf(void) +{ + return 0; +} + +__INLINE uint8_t dma_dma_status_ch1_stopped_getf(void) +{ + return 0; +} + +__INLINE uint8_t dma_dma_status_ch0_stopped_getf(void) +{ + return 0; +} + +/** + * @brief INT_RAWSTATUS register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     23              CH3_EOT   0
+ *     22              CH2_EOT   0
+ *     21              CH1_EOT   0
+ *     20              CH0_EOT   0
+ *     16                ERROR   0
+ *  15:00              LLI_IRQ   0x0
+ * 
+ */ +#define DMA_INT_RAWSTATUS_ADDR 0x10A00014 +#define DMA_INT_RAWSTATUS_OFFSET 0x00000014 +#define DMA_INT_RAWSTATUS_INDEX 0x00000005 +#define DMA_INT_RAWSTATUS_RESET 0x00000000 + +__INLINE uint32_t dma_int_rawstatus_get(void) +{ + return 0; +} + +// field definitions +#define DMA_CH3_EOT_BIT ((uint32_t)0x00800000) +#define DMA_CH3_EOT_POS 23 +#define DMA_CH2_EOT_BIT ((uint32_t)0x00400000) +#define DMA_CH2_EOT_POS 22 +#define DMA_CH1_EOT_BIT ((uint32_t)0x00200000) +#define DMA_CH1_EOT_POS 21 +#define DMA_CH0_EOT_BIT ((uint32_t)0x00100000) +#define DMA_CH0_EOT_POS 20 +#define DMA_ERROR_BIT ((uint32_t)0x00010000) +#define DMA_ERROR_POS 16 +#define DMA_LLI_IRQ_MASK ((uint32_t)0x0000FFFF) +#define DMA_LLI_IRQ_LSB 0 +#define DMA_LLI_IRQ_WIDTH ((uint32_t)0x00000010) + +#define DMA_CH3_EOT_RST 0x0 +#define DMA_CH2_EOT_RST 0x0 +#define DMA_CH1_EOT_RST 0x0 +#define DMA_CH0_EOT_RST 0x0 +#define DMA_ERROR_RST 0x0 +#define DMA_LLI_IRQ_RST 0x0 + +__INLINE void dma_int_rawstatus_unpack(uint8_t *ch3eot, uint8_t *ch2eot, uint8_t *ch1eot, uint8_t *ch0eot, uint8_t *error, uint16_t *lliirq) +{ +} + +__INLINE uint8_t dma_int_rawstatus_ch3_eot_getf(void) +{ + return 0; +} + +__INLINE uint8_t dma_int_rawstatus_ch2_eot_getf(void) +{ + return 0; +} + +__INLINE uint8_t dma_int_rawstatus_ch1_eot_getf(void) +{ + return 0; +} + +__INLINE uint8_t dma_int_rawstatus_ch0_eot_getf(void) +{ + return 0; +} + +__INLINE uint8_t dma_int_rawstatus_error_getf(void) +{ + return 0; +} + +__INLINE uint16_t dma_int_rawstatus_lli_irq_getf(void) +{ + return 0; +} + +/** + * @brief INT_UNMASK_SET register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     23              CH3_EOT   0
+ *     22              CH2_EOT   0
+ *     21              CH1_EOT   0
+ *     20              CH0_EOT   0
+ *     16                ERROR   0
+ *  15:00              LLI_IRQ   0x0
+ * 
+ */ +#define DMA_INT_UNMASK_SET_ADDR 0x10A00018 +#define DMA_INT_UNMASK_SET_OFFSET 0x00000018 +#define DMA_INT_UNMASK_SET_INDEX 0x00000006 +#define DMA_INT_UNMASK_SET_RESET 0x00000000 + +__INLINE uint32_t dma_int_unmask_get(void) +{ + return 0; +} + +__INLINE void dma_int_unmask_set(uint32_t value) +{ +} + +// field definitions +#define DMA_CH3_EOT_BIT ((uint32_t)0x00800000) +#define DMA_CH3_EOT_POS 23 +#define DMA_CH2_EOT_BIT ((uint32_t)0x00400000) +#define DMA_CH2_EOT_POS 22 +#define DMA_CH1_EOT_BIT ((uint32_t)0x00200000) +#define DMA_CH1_EOT_POS 21 +#define DMA_CH0_EOT_BIT ((uint32_t)0x00100000) +#define DMA_CH0_EOT_POS 20 +#define DMA_ERROR_BIT ((uint32_t)0x00010000) +#define DMA_ERROR_POS 16 +#define DMA_LLI_IRQ_MASK ((uint32_t)0x0000FFFF) +#define DMA_LLI_IRQ_LSB 0 +#define DMA_LLI_IRQ_WIDTH ((uint32_t)0x00000010) + +#define DMA_CH3_EOT_RST 0x0 +#define DMA_CH2_EOT_RST 0x0 +#define DMA_CH1_EOT_RST 0x0 +#define DMA_CH0_EOT_RST 0x0 +#define DMA_ERROR_RST 0x0 +#define DMA_LLI_IRQ_RST 0x0 + +__INLINE void dma_int_unmask_set_pack(uint8_t ch3eot, uint8_t ch2eot, uint8_t ch1eot, uint8_t ch0eot, uint8_t error, uint16_t lliirq) +{ +} + +__INLINE void dma_int_unmask_unpack(uint8_t *ch3eot, uint8_t *ch2eot, uint8_t *ch1eot, uint8_t *ch0eot, uint8_t *error, uint16_t *lliirq) +{ +} + +__INLINE uint8_t dma_int_unmask_ch3_eot_getf(void) +{ + return 0; +} + +__INLINE void dma_int_unmask_ch3_eot_setf(uint8_t ch3eot) +{ +} + +__INLINE uint8_t dma_int_unmask_ch2_eot_getf(void) +{ + return 0; +} + +__INLINE void dma_int_unmask_ch2_eot_setf(uint8_t ch2eot) +{ +} + +__INLINE uint8_t dma_int_unmask_ch1_eot_getf(void) +{ + return 0; +} + +__INLINE void dma_int_unmask_ch1_eot_setf(uint8_t ch1eot) +{ +} + +__INLINE uint8_t dma_int_unmask_ch0_eot_getf(void) +{ + return 0; +} + +__INLINE void dma_int_unmask_ch0_eot_setf(uint8_t ch0eot) +{ +} + +__INLINE uint8_t dma_int_unmask_error_getf(void) +{ + return 0; +} + +__INLINE void dma_int_unmask_error_setf(uint8_t error) +{ +} + +__INLINE uint16_t dma_int_unmask_lli_irq_getf(void) +{ + return 0; +} + +__INLINE void dma_int_unmask_lli_irq_setf(uint16_t lliirq) +{ +} + +/** + * @brief INT_UNMASK_CLEAR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     23              CH3_EOT   0
+ *     22              CH2_EOT   0
+ *     21              CH1_EOT   0
+ *     20              CH0_EOT   0
+ *     16                ERROR   0
+ *  15:00              LLI_IRQ   0x0
+ * 
+ */ +#define DMA_INT_UNMASK_CLEAR_ADDR 0x10A0001C +#define DMA_INT_UNMASK_CLEAR_OFFSET 0x0000001C +#define DMA_INT_UNMASK_CLEAR_INDEX 0x00000007 +#define DMA_INT_UNMASK_CLEAR_RESET 0x00000000 + +__INLINE void dma_int_unmask_clear(uint32_t value) +{ +} + +// fields defined in symmetrical set/clear register +__INLINE void dma_int_unmask_clear_pack(uint8_t ch3eot, uint8_t ch2eot, uint8_t ch1eot, uint8_t ch0eot, uint8_t error, uint16_t lliirq) +{ +} + +__INLINE void dma_int_unmask_ch3_eot_clearf(uint8_t ch3eot) +{ +} + +__INLINE void dma_int_unmask_ch2_eot_clearf(uint8_t ch2eot) +{ +} + +__INLINE void dma_int_unmask_ch1_eot_clearf(uint8_t ch1eot) +{ +} + +__INLINE void dma_int_unmask_ch0_eot_clearf(uint8_t ch0eot) +{ +} + +__INLINE void dma_int_unmask_error_clearf(uint8_t error) +{ +} + +__INLINE void dma_int_unmask_lli_irq_clearf(uint16_t lliirq) +{ +} + +/** + * @brief INT_ACK register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     23              CH3_EOT   0
+ *     22              CH2_EOT   0
+ *     21              CH1_EOT   0
+ *     20              CH0_EOT   0
+ *     16                ERROR   0
+ *  15:00              LLI_IRQ   0x0
+ * 
+ */ +#define DMA_INT_ACK_ADDR 0x10A00020 +#define DMA_INT_ACK_OFFSET 0x00000020 +#define DMA_INT_ACK_INDEX 0x00000008 +#define DMA_INT_ACK_RESET 0x00000000 + +__INLINE uint32_t dma_int_ack_get(void) +{ + return 0; +} + +__INLINE void dma_int_ack_clear(uint32_t value) +{ +} + +// field definitions +#define DMA_CH3_EOT_BIT ((uint32_t)0x00800000) +#define DMA_CH3_EOT_POS 23 +#define DMA_CH2_EOT_BIT ((uint32_t)0x00400000) +#define DMA_CH2_EOT_POS 22 +#define DMA_CH1_EOT_BIT ((uint32_t)0x00200000) +#define DMA_CH1_EOT_POS 21 +#define DMA_CH0_EOT_BIT ((uint32_t)0x00100000) +#define DMA_CH0_EOT_POS 20 +#define DMA_ERROR_BIT ((uint32_t)0x00010000) +#define DMA_ERROR_POS 16 +#define DMA_LLI_IRQ_MASK ((uint32_t)0x0000FFFF) +#define DMA_LLI_IRQ_LSB 0 +#define DMA_LLI_IRQ_WIDTH ((uint32_t)0x00000010) + +#define DMA_CH3_EOT_RST 0x0 +#define DMA_CH2_EOT_RST 0x0 +#define DMA_CH1_EOT_RST 0x0 +#define DMA_CH0_EOT_RST 0x0 +#define DMA_ERROR_RST 0x0 +#define DMA_LLI_IRQ_RST 0x0 + +__INLINE void dma_int_ack_pack(uint8_t ch3eot, uint8_t ch2eot, uint8_t ch1eot, uint8_t ch0eot, uint8_t error, uint16_t lliirq) +{ +} + +__INLINE void dma_int_ack_unpack(uint8_t *ch3eot, uint8_t *ch2eot, uint8_t *ch1eot, uint8_t *ch0eot, uint8_t *error, uint16_t *lliirq) +{ +} + +__INLINE uint8_t dma_int_ack_ch3_eot_getf(void) +{ + return 0; +} + +__INLINE void dma_int_ack_ch3_eot_clearf(uint8_t ch3eot) +{ +} + +__INLINE uint8_t dma_int_ack_ch2_eot_getf(void) +{ + return 0; +} + +__INLINE void dma_int_ack_ch2_eot_clearf(uint8_t ch2eot) +{ +} + +__INLINE uint8_t dma_int_ack_ch1_eot_getf(void) +{ + return 0; +} + +__INLINE void dma_int_ack_ch1_eot_clearf(uint8_t ch1eot) +{ +} + +__INLINE uint8_t dma_int_ack_ch0_eot_getf(void) +{ + return 0; +} + +__INLINE void dma_int_ack_ch0_eot_clearf(uint8_t ch0eot) +{ +} + +__INLINE uint8_t dma_int_ack_error_getf(void) +{ + return 0; +} + +__INLINE void dma_int_ack_error_clearf(uint8_t error) +{ +} + +__INLINE uint16_t dma_int_ack_lli_irq_getf(void) +{ + return 0; +} + +__INLINE void dma_int_ack_lli_irq_clearf(uint16_t lliirq) +{ +} + +/** + * @brief INT_STATUS register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     23              CH3_EOT   0
+ *     22              CH2_EOT   0
+ *     21              CH1_EOT   0
+ *     20              CH0_EOT   0
+ *     16                ERROR   0
+ *  15:00              LLI_IRQ   0x0
+ * 
+ */ +#define DMA_INT_STATUS_ADDR 0x10A00024 +#define DMA_INT_STATUS_OFFSET 0x00000024 +#define DMA_INT_STATUS_INDEX 0x00000009 +#define DMA_INT_STATUS_RESET 0x00000000 + +__INLINE uint32_t dma_int_status_get(void) +{ + return REG_PL_RD(DMA_INT_STATUS_ADDR); +} + +// field definitions +#define DMA_CH3_EOT_BIT ((uint32_t)0x00800000) +#define DMA_CH3_EOT_POS 23 +#define DMA_CH2_EOT_BIT ((uint32_t)0x00400000) +#define DMA_CH2_EOT_POS 22 +#define DMA_CH1_EOT_BIT ((uint32_t)0x00200000) +#define DMA_CH1_EOT_POS 21 +#define DMA_CH0_EOT_BIT ((uint32_t)0x00100000) +#define DMA_CH0_EOT_POS 20 +#define DMA_ERROR_BIT ((uint32_t)0x00010000) +#define DMA_ERROR_POS 16 +#define DMA_LLI_IRQ_MASK ((uint32_t)0x0000FFFF) +#define DMA_LLI_IRQ_LSB 0 +#define DMA_LLI_IRQ_WIDTH ((uint32_t)0x00000010) + +#define DMA_CH3_EOT_RST 0x0 +#define DMA_CH2_EOT_RST 0x0 +#define DMA_CH1_EOT_RST 0x0 +#define DMA_CH0_EOT_RST 0x0 +#define DMA_ERROR_RST 0x0 +#define DMA_LLI_IRQ_RST 0x0 + +__INLINE void dma_int_status_unpack(uint8_t *ch3eot, uint8_t *ch2eot, uint8_t *ch1eot, uint8_t *ch0eot, uint8_t *error, uint16_t *lliirq) +{ +} + +__INLINE uint8_t dma_int_status_ch3_eot_getf(void) +{ + return 0; +} + +__INLINE uint8_t dma_int_status_ch2_eot_getf(void) +{ + return 0; +} + +__INLINE uint8_t dma_int_status_ch1_eot_getf(void) +{ + return 0; +} + +__INLINE uint8_t dma_int_status_ch0_eot_getf(void) +{ + return 0; +} + +__INLINE uint8_t dma_int_status_error_getf(void) +{ + return 0; +} + +__INLINE uint16_t dma_int_status_lli_irq_getf(void) +{ + return 0; +} + +/** + * @brief CHANNEL_PRIORITY register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     16   INTERLEAVE_ENABLED   0
+ *  13:12         CH3_PRIORITY   0x0
+ *  09:08         CH2_PRIORITY   0x0
+ *  05:04         CH1_PRIORITY   0x0
+ *  01:00         CH0_PRIORITY   0x0
+ * 
+ */ +#define DMA_CHANNEL_PRIORITY_ADDR 0x10A00034 +#define DMA_CHANNEL_PRIORITY_OFFSET 0x00000034 +#define DMA_CHANNEL_PRIORITY_INDEX 0x0000000D +#define DMA_CHANNEL_PRIORITY_RESET 0x00000000 + +__INLINE uint32_t dma_channel_priority_get(void) +{ + return 0; +} + +__INLINE void dma_channel_priority_set(uint32_t value) +{ + REG_PL_WR(DMA_CHANNEL_PRIORITY_ADDR, value); +} + +// field definitions +#define DMA_INTERLEAVE_ENABLED_BIT ((uint32_t)0x00010000) +#define DMA_INTERLEAVE_ENABLED_POS 16 +#define DMA_CH3_PRIORITY_MASK ((uint32_t)0x00003000) +#define DMA_CH3_PRIORITY_LSB 12 +#define DMA_CH3_PRIORITY_WIDTH ((uint32_t)0x00000002) +#define DMA_CH2_PRIORITY_MASK ((uint32_t)0x00000300) +#define DMA_CH2_PRIORITY_LSB 8 +#define DMA_CH2_PRIORITY_WIDTH ((uint32_t)0x00000002) +#define DMA_CH1_PRIORITY_MASK ((uint32_t)0x00000030) +#define DMA_CH1_PRIORITY_LSB 4 +#define DMA_CH1_PRIORITY_WIDTH ((uint32_t)0x00000002) +#define DMA_CH0_PRIORITY_MASK ((uint32_t)0x00000003) +#define DMA_CH0_PRIORITY_LSB 0 +#define DMA_CH0_PRIORITY_WIDTH ((uint32_t)0x00000002) + +#define DMA_INTERLEAVE_ENABLED_RST 0x0 +#define DMA_CH3_PRIORITY_RST 0x0 +#define DMA_CH2_PRIORITY_RST 0x0 +#define DMA_CH1_PRIORITY_RST 0x0 +#define DMA_CH0_PRIORITY_RST 0x0 + +__INLINE void dma_channel_priority_pack(uint8_t interleaveenabled, uint8_t ch3priority, uint8_t ch2priority, uint8_t ch1priority, uint8_t ch0priority) +{ +} + +__INLINE void dma_channel_priority_unpack(uint8_t *interleaveenabled, uint8_t *ch3priority, uint8_t *ch2priority, uint8_t *ch1priority, uint8_t *ch0priority) +{ +} + +__INLINE uint8_t dma_channel_priority_interleave_enabled_getf(void) +{ + return 0; +} + +__INLINE void dma_channel_priority_interleave_enabled_setf(uint8_t interleaveenabled) +{ +} + +__INLINE uint8_t dma_channel_priority_ch3_priority_getf(void) +{ + return 0; +} + +__INLINE void dma_channel_priority_ch3_priority_setf(uint8_t ch3priority) +{ +} + +__INLINE uint8_t dma_channel_priority_ch2_priority_getf(void) +{ + return 0; +} + +__INLINE void dma_channel_priority_ch2_priority_setf(uint8_t ch2priority) +{ +} + +__INLINE uint8_t dma_channel_priority_ch1_priority_getf(void) +{ + return 0; +} + +__INLINE void dma_channel_priority_ch1_priority_setf(uint8_t ch1priority) +{ +} + +__INLINE uint8_t dma_channel_priority_ch0_priority_getf(void) +{ + return 0; +} + +__INLINE void dma_channel_priority_ch0_priority_setf(uint8_t ch0priority) +{ +} + +/** + * @brief CHANNEL_MUTEX_SET register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     03            CH3_MUTEX   0
+ *     02            CH2_MUTEX   0
+ *     01            CH1_MUTEX   0
+ *     00            CH0_MUTEX   0
+ * 
+ */ +#define DMA_CHANNEL_MUTEX_SET_ADDR 0x10A00038 +#define DMA_CHANNEL_MUTEX_SET_OFFSET 0x00000038 +#define DMA_CHANNEL_MUTEX_SET_INDEX 0x0000000E +#define DMA_CHANNEL_MUTEX_SET_RESET 0x00000000 + +__INLINE uint32_t dma_channel_mutex_get(void) +{ + return 0; +} + +__INLINE void dma_channel_mutex_set(uint32_t value) +{ +} + +// field definitions +#define DMA_CH3_MUTEX_BIT ((uint32_t)0x00000008) +#define DMA_CH3_MUTEX_POS 3 +#define DMA_CH2_MUTEX_BIT ((uint32_t)0x00000004) +#define DMA_CH2_MUTEX_POS 2 +#define DMA_CH1_MUTEX_BIT ((uint32_t)0x00000002) +#define DMA_CH1_MUTEX_POS 1 +#define DMA_CH0_MUTEX_BIT ((uint32_t)0x00000001) +#define DMA_CH0_MUTEX_POS 0 + +#define DMA_CH3_MUTEX_RST 0x0 +#define DMA_CH2_MUTEX_RST 0x0 +#define DMA_CH1_MUTEX_RST 0x0 +#define DMA_CH0_MUTEX_RST 0x0 + +__INLINE void dma_channel_mutex_set_pack(uint8_t ch3mutex, uint8_t ch2mutex, uint8_t ch1mutex, uint8_t ch0mutex) +{ +} + +__INLINE void dma_channel_mutex_unpack(uint8_t *ch3mutex, uint8_t *ch2mutex, uint8_t *ch1mutex, uint8_t *ch0mutex) +{ +} + +__INLINE uint8_t dma_channel_mutex_ch3_mutex_getf(void) +{ + return 0; +} + +__INLINE void dma_channel_mutex_ch3_mutex_setf(uint8_t ch3mutex) +{ +} + +__INLINE uint8_t dma_channel_mutex_ch2_mutex_getf(void) +{ + return 0; +} + +__INLINE void dma_channel_mutex_ch2_mutex_setf(uint8_t ch2mutex) +{ +} + +__INLINE uint8_t dma_channel_mutex_ch1_mutex_getf(void) +{ + return 0; +} + +__INLINE void dma_channel_mutex_ch1_mutex_setf(uint8_t ch1mutex) +{ +} + +__INLINE uint8_t dma_channel_mutex_ch0_mutex_getf(void) +{ + return 0; +} + +__INLINE void dma_channel_mutex_ch0_mutex_setf(uint8_t ch0mutex) +{ +} + +/** + * @brief CHANNEL_MUTEX_CLEAR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     03            CH3_MUTEX   0
+ *     02            CH2_MUTEX   0
+ *     01            CH1_MUTEX   0
+ *     00            CH0_MUTEX   0
+ * 
+ */ +#define DMA_CHANNEL_MUTEX_CLEAR_ADDR 0x10A0003C +#define DMA_CHANNEL_MUTEX_CLEAR_OFFSET 0x0000003C +#define DMA_CHANNEL_MUTEX_CLEAR_INDEX 0x0000000F +#define DMA_CHANNEL_MUTEX_CLEAR_RESET 0x00000000 + +__INLINE void dma_channel_mutex_clear(uint32_t value) +{ +} + +// fields defined in symmetrical set/clear register +__INLINE void dma_channel_mutex_clear_pack(uint8_t ch3mutex, uint8_t ch2mutex, uint8_t ch1mutex, uint8_t ch0mutex) +{ +} + +__INLINE void dma_channel_mutex_ch3_mutex_clearf(uint8_t ch3mutex) +{ +} + +__INLINE void dma_channel_mutex_ch2_mutex_clearf(uint8_t ch2mutex) +{ +} + +__INLINE void dma_channel_mutex_ch1_mutex_clearf(uint8_t ch1mutex) +{ +} + +__INLINE void dma_channel_mutex_ch0_mutex_clearf(uint8_t ch0mutex) +{ +} + +// field definitions +#define DMA_COUNTER_MASK ((uint32_t)0x0000FFFF) +#define DMA_COUNTER_LSB 0 +#define DMA_COUNTER_WIDTH ((uint32_t)0x00000010) + +#define DMA_COUNTER_RST 0x0 + +/** + * @brief DUMMY register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     00                DUMMY   0
+ * 
+ */ +#define DMA_DUMMY_ADDR 0x10A000C0 +#define DMA_DUMMY_OFFSET 0x000000C0 +#define DMA_DUMMY_INDEX 0x00000030 +#define DMA_DUMMY_RESET 0x00000000 + +__INLINE uint32_t dma_dummy_get(void) +{ + return 0; +} + +__INLINE void dma_dummy_set(uint32_t value) +{ +} + +// field definitions +#define DMA_DUMMY_BIT ((uint32_t)0x00000001) +#define DMA_DUMMY_POS 0 + +#define DMA_DUMMY_RST 0x0 + +__INLINE uint8_t dma_dummy_getf(void) +{ + return 0; +} + +__INLINE void dma_dummy_setf(uint8_t dummy) +{ +} + + +#endif // _REG_DMA_H_ + diff --git a/beken_os/beken378/driver/common/reg/reg_intc.h b/beken_os/beken378/driver/common/reg/reg_intc.h new file mode 100755 index 0000000..09cd43c --- /dev/null +++ b/beken_os/beken378/driver/common/reg/reg_intc.h @@ -0,0 +1,238 @@ +/** + * @file reg_intc.h + * @brief Definitions of the INTC HW block registers and register access functions. + * + * @defgroup REG_INTC REG_INTC + * @ingroup REG + * @{ + * + * @brief Definitions of the INTC HW block registers and register access functions. + */ +#ifndef _REG_INTC_H_ +#define _REG_INTC_H_ + +#include "co_int.h" +#include "_reg_intc.h" +#include "compiler.h" +#include "arch.h" +#include "reg_access.h" + +/** @brief Number of registers in the REG_INTC peripheral. + */ +#define REG_INTC_COUNT 17 + +/** @brief Decoding mask of the REG_INTC peripheral registers from the CPU point of view. + */ +#define REG_INTC_DECODING_MASK 0x0000007F + +/** + * @name IRQ_STATUS register definitions + * + * @{ + */ + +/// Address of the IRQ_STATUS register +#define INTC_IRQ_STATUS_ADDR 0x10910000 +/// Offset of the IRQ_STATUS register from the base address +#define INTC_IRQ_STATUS_OFFSET 0x00000000 +/// Index of the IRQ_STATUS register +#define INTC_IRQ_STATUS_INDEX 0x00000000 +/// Reset value of the IRQ_STATUS register +#define INTC_IRQ_STATUS_RESET 0x00000000 +/// Number of elements of the IRQ_STATUS register array +#define INTC_IRQ_STATUS_COUNT 2 + +/** + * @brief Returns the current value of the IRQ_STATUS register. + * The IRQ_STATUS register will be read and its value returned. + * @param[in] reg_idx Index of the register + * @return The current value of the IRQ_STATUS register. + */ +__INLINE uint32_t intc_irq_status_get(int reg_idx) +{ + ASSERT_ERR(reg_idx <= 1); + return REG_PL_RD(INTC_IRQ_STATUS_ADDR + reg_idx * 4); +} + +/// @} + +/** + * @name IRQ_RAW_STATUS register definitions + * + * @{ + */ + +/// Address of the IRQ_RAW_STATUS register +#define INTC_IRQ_RAW_STATUS_ADDR 0x10910008 +/// Offset of the IRQ_RAW_STATUS register from the base address +#define INTC_IRQ_RAW_STATUS_OFFSET 0x00000008 +/// Index of the IRQ_RAW_STATUS register +#define INTC_IRQ_RAW_STATUS_INDEX 0x00000002 +/// Reset value of the IRQ_RAW_STATUS register +#define INTC_IRQ_RAW_STATUS_RESET 0x00000000 +/// Number of elements of the IRQ_RAW_STATUS register array +#define INTC_IRQ_RAW_STATUS_COUNT 2 + +/** + * @brief Returns the current value of the IRQ_RAW_STATUS register. + * The IRQ_RAW_STATUS register will be read and its value returned. + * @param[in] reg_idx Index of the register + * @return The current value of the IRQ_RAW_STATUS register. + */ +__INLINE uint32_t intc_irq_raw_status_get(int reg_idx) +{ + ASSERT_ERR(reg_idx <= 1); + return REG_PL_RD(INTC_IRQ_RAW_STATUS_ADDR + reg_idx * 4); +} + +/// @} + +/** + * @name IRQ_UNMASK_SET register definitions + * + * @{ + */ + +/// Address of the IRQ_UNMASK_SET register +#define INTC_IRQ_UNMASK_SET_ADDR 0x10910010 +/// Offset of the IRQ_UNMASK_SET register from the base address +#define INTC_IRQ_UNMASK_SET_OFFSET 0x00000010 +/// Index of the IRQ_UNMASK_SET register +#define INTC_IRQ_UNMASK_SET_INDEX 0x00000004 +/// Reset value of the IRQ_UNMASK_SET register +#define INTC_IRQ_UNMASK_SET_RESET 0x00000000 +/// Number of elements of the IRQ_UNMASK_SET register array +#define INTC_IRQ_UNMASK_SET_COUNT 2 + +/** + * @brief Returns the current value of the IRQ_UNMASK_SET register. + * The IRQ_UNMASK_SET register will be read and its value returned. + * @param[in] reg_idx Index of the register + * @return The current value of the IRQ_UNMASK_SET register. + */ +__INLINE uint32_t intc_irq_unmask_get(int reg_idx) +{ + ASSERT_ERR(reg_idx <= 1); + return REG_PL_RD(INTC_IRQ_UNMASK_SET_ADDR + reg_idx * 4); +} + +/** + * @brief Sets the IRQ_UNMASK_SET register to a value. + * The IRQ_UNMASK_SET register will be written. + * @param[in] reg_idx Index of the register + * @param value - The value to write. + */ +__INLINE void intc_irq_unmask_set(int reg_idx, uint32_t value) +{ + ASSERT_ERR(reg_idx <= 1); + REG_PL_WR(INTC_IRQ_UNMASK_SET_ADDR + reg_idx * 4, value); +} + +/// @} + +/** + * @name IRQ_UNMASK_CLEAR register definitions + * + * @{ + */ + +/// Address of the IRQ_UNMASK_CLEAR register +#define INTC_IRQ_UNMASK_CLEAR_ADDR 0x10910018 +/// Offset of the IRQ_UNMASK_CLEAR register from the base address +#define INTC_IRQ_UNMASK_CLEAR_OFFSET 0x00000018 +/// Index of the IRQ_UNMASK_CLEAR register +#define INTC_IRQ_UNMASK_CLEAR_INDEX 0x00000006 +/// Reset value of the IRQ_UNMASK_CLEAR register +#define INTC_IRQ_UNMASK_CLEAR_RESET 0x00000000 +/// Number of elements of the IRQ_UNMASK_CLEAR register array +#define INTC_IRQ_UNMASK_CLEAR_COUNT 2 + +/** + * @brief Sets the IRQ_UNMASK_CLEAR register to a value. + * The IRQ_UNMASK_CLEAR register will be written. + * @param[in] reg_idx Index of the register + * @param value - The value to write. + */ +__INLINE void intc_irq_unmask_clear(int reg_idx, uint32_t value) +{ + ASSERT_ERR(reg_idx <= 1); + REG_PL_WR(INTC_IRQ_UNMASK_CLEAR_ADDR + reg_idx * 4, value); +} + +/// @} + +/** + * @name IRQ_POLARITY register definitions + * + * @{ + */ + +/// Address of the IRQ_POLARITY register +#define INTC_IRQ_POLARITY_ADDR 0x10910020 +/// Offset of the IRQ_POLARITY register from the base address +#define INTC_IRQ_POLARITY_OFFSET 0x00000020 +/// Index of the IRQ_POLARITY register +#define INTC_IRQ_POLARITY_INDEX 0x00000008 +/// Reset value of the IRQ_POLARITY register +#define INTC_IRQ_POLARITY_RESET 0x00000000 +/// Number of elements of the IRQ_POLARITY register array +#define INTC_IRQ_POLARITY_COUNT 2 + +/** + * @brief Returns the current value of the IRQ_POLARITY register. + * The IRQ_POLARITY register will be read and its value returned. + * @param[in] reg_idx Index of the register + * @return The current value of the IRQ_POLARITY register. + */ +__INLINE uint32_t intc_irq_polarity_get(int reg_idx) +{ + ASSERT_ERR(reg_idx <= 1); + return REG_PL_RD(INTC_IRQ_POLARITY_ADDR + reg_idx * 4); +} + +/** + * @brief Sets the IRQ_POLARITY register to a value. + * The IRQ_POLARITY register will be written. + * @param[in] reg_idx Index of the register + * @param value - The value to write. + */ +__INLINE void intc_irq_polarity_set(int reg_idx, uint32_t value) +{ + ASSERT_ERR(reg_idx <= 1); + REG_PL_WR(INTC_IRQ_POLARITY_ADDR + reg_idx * 4, value); +} + +/// @} + +/** + * @name IRQ_INDEX register definitions + * + * @{ + */ + +/// Address of the IRQ_INDEX register +#define INTC_IRQ_INDEX_ADDR 0x10910040 +/// Offset of the IRQ_INDEX register from the base address +#define INTC_IRQ_INDEX_OFFSET 0x00000040 +/// Index of the IRQ_INDEX register +#define INTC_IRQ_INDEX_INDEX 0x00000010 +/// Reset value of the IRQ_INDEX register +#define INTC_IRQ_INDEX_RESET 0x00000000 + +/** + * @brief Returns the current value of the IRQ_INDEX register. + * The IRQ_INDEX register will be read and its value returned. + * @return The current value of the IRQ_INDEX register. + */ +__INLINE uint32_t intc_irq_index_get(void) +{ + return REG_PL_RD(INTC_IRQ_INDEX_ADDR); +} + +/// @} + + +#endif // _REG_INTC_H_ + +/// @} + diff --git a/beken_os/beken378/driver/common/reg/reg_la.h b/beken_os/beken378/driver/common/reg/reg_la.h new file mode 100755 index 0000000..2c6562d --- /dev/null +++ b/beken_os/beken378/driver/common/reg/reg_la.h @@ -0,0 +1,1389 @@ +/** + * @file reg_la.h + * @brief Definitions of the LA HW block registers and register access functions. + * + * @defgroup REG_LA REG_LA + * @ingroup REG + * @{ + * + * @brief Definitions of the LA HW block registers and register access functions. + */ +#ifndef _REG_LA_H_ +#define _REG_LA_H_ + +#include "co_int.h" +#include "_reg_la.h" +#include "compiler.h" +#include "arch.h" +#include "reg_access.h" + +#if (CFG_SOC_NAME != SOC_BK7231N) +/** @brief Number of registers in the REG_LA peripheral. + */ +#define REG_LA_COUNT 16 + +/** @brief Decoding mask of the REG_LA peripheral registers from the CPU point of view. + */ +#define REG_LA_DECODING_MASK 0x0000003F + +/** + * @name ID_LOW register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00               id_low   0x0
+ * 
+ * + * @{ + */ + +/// Address of the ID_LOW register +#define LA_ID_LOW_ADDR 0x10E00000 +/// Offset of the ID_LOW register from the base address +#define LA_ID_LOW_OFFSET 0x00000000 +/// Index of the ID_LOW register +#define LA_ID_LOW_INDEX 0x00000000 +/// Reset value of the ID_LOW register +#define LA_ID_LOW_RESET 0x00000000 + +/** + * @brief Returns the current value of the ID_LOW register. + * The ID_LOW register will be read and its value returned. + * @param[in] elt_idx Index of the HW block + * @return The current value of the ID_LOW register. + */ +__INLINE uint32_t la_id_low_get(int elt_idx) +{ + return REG_PL_RD(LA_ID_LOW_ADDR + elt_idx * REG_LA_OFFSET); +} + +// field definitions +/// ID_LOW field mask +#define LA_ID_LOW_MASK ((uint32_t)0xFFFFFFFF) +/// ID_LOW field LSB position +#define LA_ID_LOW_LSB 0 +/// ID_LOW field width +#define LA_ID_LOW_WIDTH ((uint32_t)0x00000020) + +/// ID_LOW field reset value +#define LA_ID_LOW_RST 0x0 + +/** + * @brief Returns the current value of the id_low field in the ID_LOW register. + * + * The ID_LOW register will be read and the id_low field's value will be returned. + * + * @param[in] elt_idx Index of the HW block + * @return The current value of the id_low field in the ID_LOW register. + */ +__INLINE uint32_t la_id_low_getf(int elt_idx) +{ + uint32_t localVal = REG_PL_RD(LA_ID_LOW_ADDR + elt_idx * REG_LA_OFFSET); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/// @} + +/** + * @name ID_HIGH register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00              id_high   0x0
+ * 
+ * + * @{ + */ + +/// Address of the ID_HIGH register +#define LA_ID_HIGH_ADDR 0x10E00004 +/// Offset of the ID_HIGH register from the base address +#define LA_ID_HIGH_OFFSET 0x00000004 +/// Index of the ID_HIGH register +#define LA_ID_HIGH_INDEX 0x00000001 +/// Reset value of the ID_HIGH register +#define LA_ID_HIGH_RESET 0x00000000 + +/** + * @brief Returns the current value of the ID_HIGH register. + * The ID_HIGH register will be read and its value returned. + * @param[in] elt_idx Index of the HW block + * @return The current value of the ID_HIGH register. + */ +__INLINE uint32_t la_id_high_get(int elt_idx) +{ + return REG_PL_RD(LA_ID_HIGH_ADDR + elt_idx * REG_LA_OFFSET); +} + +// field definitions +/// ID_HIGH field mask +#define LA_ID_HIGH_MASK ((uint32_t)0xFFFFFFFF) +/// ID_HIGH field LSB position +#define LA_ID_HIGH_LSB 0 +/// ID_HIGH field width +#define LA_ID_HIGH_WIDTH ((uint32_t)0x00000020) + +/// ID_HIGH field reset value +#define LA_ID_HIGH_RST 0x0 + +/** + * @brief Returns the current value of the id_high field in the ID_HIGH register. + * + * The ID_HIGH register will be read and the id_high field's value will be returned. + * + * @param[in] elt_idx Index of the HW block + * @return The current value of the id_high field in the ID_HIGH register. + */ +__INLINE uint32_t la_id_high_getf(int elt_idx) +{ + uint32_t localVal = REG_PL_RD(LA_ID_HIGH_ADDR + elt_idx * REG_LA_OFFSET); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/// @} + +/** + * @name VERSION register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00              version   0x0
+ * 
+ * + * @{ + */ + +/// Address of the VERSION register +#define LA_VERSION_ADDR 0x10E00008 +/// Offset of the VERSION register from the base address +#define LA_VERSION_OFFSET 0x00000008 +/// Index of the VERSION register +#define LA_VERSION_INDEX 0x00000002 +/// Reset value of the VERSION register +#define LA_VERSION_RESET 0x00000000 + +/** + * @brief Returns the current value of the VERSION register. + * The VERSION register will be read and its value returned. + * @param[in] elt_idx Index of the HW block + * @return The current value of the VERSION register. + */ +__INLINE uint32_t la_version_get(int elt_idx) +{ + return REG_PL_RD(LA_VERSION_ADDR + elt_idx * REG_LA_OFFSET); +} + +// field definitions +/// VERSION field mask +#define LA_VERSION_MASK ((uint32_t)0xFFFFFFFF) +/// VERSION field LSB position +#define LA_VERSION_LSB 0 +/// VERSION field width +#define LA_VERSION_WIDTH ((uint32_t)0x00000020) + +/// VERSION field reset value +#define LA_VERSION_RST 0x0 + +/** + * @brief Returns the current value of the version field in the VERSION register. + * + * The VERSION register will be read and the version field's value will be returned. + * + * @param[in] elt_idx Index of the HW block + * @return The current value of the version field in the VERSION register. + */ +__INLINE uint32_t la_version_getf(int elt_idx) +{ + uint32_t localVal = REG_PL_RD(LA_VERSION_ADDR + elt_idx * REG_LA_OFFSET); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/// @} + +/** + * @name CNTRL register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     02                reset   0
+ *     01                 stop   0
+ *     00                start   0
+ * 
+ * + * @{ + */ + +/// Address of the CNTRL register +#define LA_CNTRL_ADDR 0x10E0000C +/// Offset of the CNTRL register from the base address +#define LA_CNTRL_OFFSET 0x0000000C +/// Index of the CNTRL register +#define LA_CNTRL_INDEX 0x00000003 +/// Reset value of the CNTRL register +#define LA_CNTRL_RESET 0x00000000 + +/** + * @brief Sets the CNTRL register to a value. + * The CNTRL register will be written. + * @param[in] elt_idx Index of the HW block + * @param value - The value to write. + */ +__INLINE void la_cntrl_set(int elt_idx, uint32_t value) +{ + REG_PL_WR(LA_CNTRL_ADDR + elt_idx * REG_LA_OFFSET, value); +} + +// field definitions +/// RESET field bit +#define LA_RESET_BIT ((uint32_t)0x00000004) +/// RESET field position +#define LA_RESET_POS 2 +/// STOP field bit +#define LA_STOP_BIT ((uint32_t)0x00000002) +/// STOP field position +#define LA_STOP_POS 1 +/// START field bit +#define LA_START_BIT ((uint32_t)0x00000001) +/// START field position +#define LA_START_POS 0 + +/// RESET field reset value +#define LA_RESET_RST 0x0 +/// STOP field reset value +#define LA_STOP_RST 0x0 +/// START field reset value +#define LA_START_RST 0x0 + +/** + * @brief Constructs a value for the CNTRL register given values for its fields + * and writes the value to the register. + * + * @param[in] elt_idx Index of the HW block + * @param[in] reset - The value to use for the reset field. + * @param[in] stop - The value to use for the stop field. + * @param[in] start - The value to use for the start field. + */ +__INLINE void la_cntrl_pack(int elt_idx, uint8_t reset, uint8_t stop, uint8_t start) +{ + ASSERT_ERR((((uint32_t)reset << 2) & ~((uint32_t)0x00000004)) == 0); + ASSERT_ERR((((uint32_t)stop << 1) & ~((uint32_t)0x00000002)) == 0); + ASSERT_ERR((((uint32_t)start << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(LA_CNTRL_ADDR + elt_idx * REG_LA_OFFSET, ((uint32_t)reset << 2) | ((uint32_t)stop << 1) | ((uint32_t)start << 0)); +} + +/** + * @brief Sets the reset field of the CNTRL register. + * + * The CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] elt_idx Index of the HW block + * @param[in] reset - The value to set the field to. + */ +__INLINE void la_reset_setf(int elt_idx, uint8_t reset) +{ + ASSERT_ERR((((uint32_t)reset << 2) & ~((uint32_t)0x00000004)) == 0); + REG_PL_WR(LA_CNTRL_ADDR + elt_idx * REG_LA_OFFSET, (REG_PL_RD(LA_CNTRL_ADDR + elt_idx * REG_LA_OFFSET) & ~((uint32_t)0x00000004)) | ((uint32_t)reset << 2)); +} + +/** + * @brief Sets the stop field of the CNTRL register. + * + * The CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] elt_idx Index of the HW block + * @param[in] stop - The value to set the field to. + */ +__INLINE void la_stop_setf(int elt_idx, uint8_t stop) +{ + ASSERT_ERR((((uint32_t)stop << 1) & ~((uint32_t)0x00000002)) == 0); + REG_PL_WR(LA_CNTRL_ADDR + elt_idx * REG_LA_OFFSET, (REG_PL_RD(LA_CNTRL_ADDR + elt_idx * REG_LA_OFFSET) & ~((uint32_t)0x00000002)) | ((uint32_t)stop << 1)); +} + +/** + * @brief Sets the start field of the CNTRL register. + * + * The CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] elt_idx Index of the HW block + * @param[in] start - The value to set the field to. + */ +__INLINE void la_start_setf(int elt_idx, uint8_t start) +{ + ASSERT_ERR((((uint32_t)start << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(LA_CNTRL_ADDR + elt_idx * REG_LA_OFFSET, (REG_PL_RD(LA_CNTRL_ADDR + elt_idx * REG_LA_OFFSET) & ~((uint32_t)0x00000001)) | ((uint32_t)start << 0)); +} + +/// @} + +/** + * @name STATUS register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  23:08            writeaddr   0x0
+ *     07                error   0
+ *     01            triggered   0
+ *     00              started   0
+ * 
+ * + * @{ + */ + +/// Address of the STATUS register +#define LA_STATUS_ADDR 0x10E00010 +/// Offset of the STATUS register from the base address +#define LA_STATUS_OFFSET 0x00000010 +/// Index of the STATUS register +#define LA_STATUS_INDEX 0x00000004 +/// Reset value of the STATUS register +#define LA_STATUS_RESET 0x00000000 + +/** + * @brief Returns the current value of the STATUS register. + * The STATUS register will be read and its value returned. + * @param[in] elt_idx Index of the HW block + * @return The current value of the STATUS register. + */ +__INLINE uint32_t la_status_get(int elt_idx) +{ + return REG_PL_RD(LA_STATUS_ADDR + elt_idx * REG_LA_OFFSET); +} + +/** + * @brief Sets the STATUS register to a value. + * The STATUS register will be written. + * @param[in] elt_idx Index of the HW block + * @param value - The value to write. + */ +__INLINE void la_status_set(int elt_idx, uint32_t value) +{ + REG_PL_WR(LA_STATUS_ADDR + elt_idx * REG_LA_OFFSET, value); +} + +// field definitions +/// WRITEADDR field mask +#define LA_WRITEADDR_MASK ((uint32_t)0x00FFFF00) +/// WRITEADDR field LSB position +#define LA_WRITEADDR_LSB 8 +/// WRITEADDR field width +#define LA_WRITEADDR_WIDTH ((uint32_t)0x00000010) +/// ERROR field bit +#define LA_ERROR_BIT ((uint32_t)0x00000080) +/// ERROR field position +#define LA_ERROR_POS 7 +/// TRIGGERED field bit +#define LA_TRIGGERED_BIT ((uint32_t)0x00000002) +/// TRIGGERED field position +#define LA_TRIGGERED_POS 1 +/// STARTED field bit +#define LA_STARTED_BIT ((uint32_t)0x00000001) +/// STARTED field position +#define LA_STARTED_POS 0 + +/// WRITEADDR field reset value +#define LA_WRITEADDR_RST 0x0 +/// ERROR field reset value +#define LA_ERROR_RST 0x0 +/// TRIGGERED field reset value +#define LA_TRIGGERED_RST 0x0 +/// STARTED field reset value +#define LA_STARTED_RST 0x0 + +/** + * @brief Unpacks STATUS's fields from current value of the STATUS register. + * + * Reads the STATUS register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[in] elt_idx Index of the HW block + * @param[out] writeaddr - Will be populated with the current value of this field from the register. + * @param[out] error - Will be populated with the current value of this field from the register. + * @param[out] triggered - Will be populated with the current value of this field from the register. + * @param[out] started - Will be populated with the current value of this field from the register. + */ +__INLINE void la_status_unpack(int elt_idx, uint16_t *writeaddr, uint8_t *error, uint8_t *triggered, uint8_t *started) +{ + uint32_t localVal = REG_PL_RD(LA_STATUS_ADDR + elt_idx * REG_LA_OFFSET); + + *writeaddr = (localVal & ((uint32_t)0x00FFFF00)) >> 8; + *error = (localVal & ((uint32_t)0x00000080)) >> 7; + *triggered = (localVal & ((uint32_t)0x00000002)) >> 1; + *started = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +/** + * @brief Returns the current value of the writeaddr field in the STATUS register. + * + * The STATUS register will be read and the writeaddr field's value will be returned. + * + * @param[in] elt_idx Index of the HW block + * @return The current value of the writeaddr field in the STATUS register. + */ +__INLINE uint16_t la_writeaddr_getf(int elt_idx) +{ + uint32_t localVal = REG_PL_RD(LA_STATUS_ADDR + elt_idx * REG_LA_OFFSET); + return ((localVal & ((uint32_t)0x00FFFF00)) >> 8); +} + +/** + * @brief Returns the current value of the error field in the STATUS register. + * + * The STATUS register will be read and the error field's value will be returned. + * + * @param[in] elt_idx Index of the HW block + * @return The current value of the error field in the STATUS register. + */ +__INLINE uint8_t la_error_getf(int elt_idx) +{ + uint32_t localVal = REG_PL_RD(LA_STATUS_ADDR + elt_idx * REG_LA_OFFSET); + return ((localVal & ((uint32_t)0x00000080)) >> 7); +} + +/** + * @brief Returns the current value of the triggered field in the STATUS register. + * + * The STATUS register will be read and the triggered field's value will be returned. + * + * @param[in] elt_idx Index of the HW block + * @return The current value of the triggered field in the STATUS register. + */ +__INLINE uint8_t la_triggered_getf(int elt_idx) +{ + uint32_t localVal = REG_PL_RD(LA_STATUS_ADDR + elt_idx * REG_LA_OFFSET); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +/** + * @brief Returns the current value of the started field in the STATUS register. + * + * The STATUS register will be read and the started field's value will be returned. + * + * @param[in] elt_idx Index of the HW block + * @return The current value of the started field in the STATUS register. + */ +__INLINE uint8_t la_started_getf(int elt_idx) +{ + uint32_t localVal = REG_PL_RD(LA_STATUS_ADDR + elt_idx * REG_LA_OFFSET); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/// @} + +/** + * @name SAMPLING_MASK_LOW register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00    sampling_mask_low   0x0
+ * 
+ * + * @{ + */ + +/// Address of the SAMPLING_MASK_LOW register +#define LA_SAMPLING_MASK_LOW_ADDR 0x10E00014 +/// Offset of the SAMPLING_MASK_LOW register from the base address +#define LA_SAMPLING_MASK_LOW_OFFSET 0x00000014 +/// Index of the SAMPLING_MASK_LOW register +#define LA_SAMPLING_MASK_LOW_INDEX 0x00000005 +/// Reset value of the SAMPLING_MASK_LOW register +#define LA_SAMPLING_MASK_LOW_RESET 0x00000000 + +/** + * @brief Returns the current value of the SAMPLING_MASK_LOW register. + * The SAMPLING_MASK_LOW register will be read and its value returned. + * @param[in] elt_idx Index of the HW block + * @return The current value of the SAMPLING_MASK_LOW register. + */ +__INLINE uint32_t la_sampling_mask_low_get(int elt_idx) +{ + return REG_PL_RD(LA_SAMPLING_MASK_LOW_ADDR + elt_idx * REG_LA_OFFSET); +} + +/** + * @brief Sets the SAMPLING_MASK_LOW register to a value. + * The SAMPLING_MASK_LOW register will be written. + * @param[in] elt_idx Index of the HW block + * @param value - The value to write. + */ +__INLINE void la_sampling_mask_low_set(int elt_idx, uint32_t value) +{ + REG_PL_WR(LA_SAMPLING_MASK_LOW_ADDR + elt_idx * REG_LA_OFFSET, value); +} + +// field definitions +/// SAMPLING_MASK_LOW field mask +#define LA_SAMPLING_MASK_LOW_MASK ((uint32_t)0xFFFFFFFF) +/// SAMPLING_MASK_LOW field LSB position +#define LA_SAMPLING_MASK_LOW_LSB 0 +/// SAMPLING_MASK_LOW field width +#define LA_SAMPLING_MASK_LOW_WIDTH ((uint32_t)0x00000020) + +/// SAMPLING_MASK_LOW field reset value +#define LA_SAMPLING_MASK_LOW_RST 0x0 + +/** + * @brief Returns the current value of the sampling_mask_low field in the SAMPLING_MASK_LOW register. + * + * The SAMPLING_MASK_LOW register will be read and the sampling_mask_low field's value will be returned. + * + * @param[in] elt_idx Index of the HW block + * @return The current value of the sampling_mask_low field in the SAMPLING_MASK_LOW register. + */ +__INLINE uint32_t la_sampling_mask_low_getf(int elt_idx) +{ + uint32_t localVal = REG_PL_RD(LA_SAMPLING_MASK_LOW_ADDR + elt_idx * REG_LA_OFFSET); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the sampling_mask_low field of the SAMPLING_MASK_LOW register. + * + * The SAMPLING_MASK_LOW register will be read, modified to contain the new field value, and written. + * + * @param[in] elt_idx Index of the HW block + * @param[in] samplingmasklow - The value to set the field to. + */ +__INLINE void la_sampling_mask_low_setf(int elt_idx, uint32_t samplingmasklow) +{ + ASSERT_ERR((((uint32_t)samplingmasklow << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(LA_SAMPLING_MASK_LOW_ADDR + elt_idx * REG_LA_OFFSET, (uint32_t)samplingmasklow << 0); +} + +/// @} + +/** + * @name SAMPLING_MASK_MED register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00    sampling_mask_med   0x0
+ * 
+ * + * @{ + */ + +/// Address of the SAMPLING_MASK_MED register +#define LA_SAMPLING_MASK_MED_ADDR 0x10E00018 +/// Offset of the SAMPLING_MASK_MED register from the base address +#define LA_SAMPLING_MASK_MED_OFFSET 0x00000018 +/// Index of the SAMPLING_MASK_MED register +#define LA_SAMPLING_MASK_MED_INDEX 0x00000006 +/// Reset value of the SAMPLING_MASK_MED register +#define LA_SAMPLING_MASK_MED_RESET 0x00000000 + +/** + * @brief Returns the current value of the SAMPLING_MASK_MED register. + * The SAMPLING_MASK_MED register will be read and its value returned. + * @param[in] elt_idx Index of the HW block + * @return The current value of the SAMPLING_MASK_MED register. + */ +__INLINE uint32_t la_sampling_mask_med_get(int elt_idx) +{ + return REG_PL_RD(LA_SAMPLING_MASK_MED_ADDR + elt_idx * REG_LA_OFFSET); +} + +/** + * @brief Sets the SAMPLING_MASK_MED register to a value. + * The SAMPLING_MASK_MED register will be written. + * @param[in] elt_idx Index of the HW block + * @param value - The value to write. + */ +__INLINE void la_sampling_mask_med_set(int elt_idx, uint32_t value) +{ + REG_PL_WR(LA_SAMPLING_MASK_MED_ADDR + elt_idx * REG_LA_OFFSET, value); +} + +// field definitions +/// SAMPLING_MASK_MED field mask +#define LA_SAMPLING_MASK_MED_MASK ((uint32_t)0xFFFFFFFF) +/// SAMPLING_MASK_MED field LSB position +#define LA_SAMPLING_MASK_MED_LSB 0 +/// SAMPLING_MASK_MED field width +#define LA_SAMPLING_MASK_MED_WIDTH ((uint32_t)0x00000020) + +/// SAMPLING_MASK_MED field reset value +#define LA_SAMPLING_MASK_MED_RST 0x0 + +/** + * @brief Returns the current value of the sampling_mask_med field in the SAMPLING_MASK_MED register. + * + * The SAMPLING_MASK_MED register will be read and the sampling_mask_med field's value will be returned. + * + * @param[in] elt_idx Index of the HW block + * @return The current value of the sampling_mask_med field in the SAMPLING_MASK_MED register. + */ +__INLINE uint32_t la_sampling_mask_med_getf(int elt_idx) +{ + uint32_t localVal = REG_PL_RD(LA_SAMPLING_MASK_MED_ADDR + elt_idx * REG_LA_OFFSET); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the sampling_mask_med field of the SAMPLING_MASK_MED register. + * + * The SAMPLING_MASK_MED register will be read, modified to contain the new field value, and written. + * + * @param[in] elt_idx Index of the HW block + * @param[in] samplingmaskmed - The value to set the field to. + */ +__INLINE void la_sampling_mask_med_setf(int elt_idx, uint32_t samplingmaskmed) +{ + ASSERT_ERR((((uint32_t)samplingmaskmed << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(LA_SAMPLING_MASK_MED_ADDR + elt_idx * REG_LA_OFFSET, (uint32_t)samplingmaskmed << 0); +} + +/// @} + +/** + * @name SAMPLING_MASK_HIGH register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00   sampling_mask_high   0x0
+ * 
+ * + * @{ + */ + +/// Address of the SAMPLING_MASK_HIGH register +#define LA_SAMPLING_MASK_HIGH_ADDR 0x10E0001C +/// Offset of the SAMPLING_MASK_HIGH register from the base address +#define LA_SAMPLING_MASK_HIGH_OFFSET 0x0000001C +/// Index of the SAMPLING_MASK_HIGH register +#define LA_SAMPLING_MASK_HIGH_INDEX 0x00000007 +/// Reset value of the SAMPLING_MASK_HIGH register +#define LA_SAMPLING_MASK_HIGH_RESET 0x00000000 + +/** + * @brief Returns the current value of the SAMPLING_MASK_HIGH register. + * The SAMPLING_MASK_HIGH register will be read and its value returned. + * @param[in] elt_idx Index of the HW block + * @return The current value of the SAMPLING_MASK_HIGH register. + */ +__INLINE uint32_t la_sampling_mask_high_get(int elt_idx) +{ + return REG_PL_RD(LA_SAMPLING_MASK_HIGH_ADDR + elt_idx * REG_LA_OFFSET); +} + +/** + * @brief Sets the SAMPLING_MASK_HIGH register to a value. + * The SAMPLING_MASK_HIGH register will be written. + * @param[in] elt_idx Index of the HW block + * @param value - The value to write. + */ +__INLINE void la_sampling_mask_high_set(int elt_idx, uint32_t value) +{ + REG_PL_WR(LA_SAMPLING_MASK_HIGH_ADDR + elt_idx * REG_LA_OFFSET, value); +} + +// field definitions +/// SAMPLING_MASK_HIGH field mask +#define LA_SAMPLING_MASK_HIGH_MASK ((uint32_t)0xFFFFFFFF) +/// SAMPLING_MASK_HIGH field LSB position +#define LA_SAMPLING_MASK_HIGH_LSB 0 +/// SAMPLING_MASK_HIGH field width +#define LA_SAMPLING_MASK_HIGH_WIDTH ((uint32_t)0x00000020) + +/// SAMPLING_MASK_HIGH field reset value +#define LA_SAMPLING_MASK_HIGH_RST 0x0 + +/** + * @brief Returns the current value of the sampling_mask_high field in the SAMPLING_MASK_HIGH register. + * + * The SAMPLING_MASK_HIGH register will be read and the sampling_mask_high field's value will be returned. + * + * @param[in] elt_idx Index of the HW block + * @return The current value of the sampling_mask_high field in the SAMPLING_MASK_HIGH register. + */ +__INLINE uint32_t la_sampling_mask_high_getf(int elt_idx) +{ + uint32_t localVal = REG_PL_RD(LA_SAMPLING_MASK_HIGH_ADDR + elt_idx * REG_LA_OFFSET); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the sampling_mask_high field of the SAMPLING_MASK_HIGH register. + * + * The SAMPLING_MASK_HIGH register will be read, modified to contain the new field value, and written. + * + * @param[in] elt_idx Index of the HW block + * @param[in] samplingmaskhigh - The value to set the field to. + */ +__INLINE void la_sampling_mask_high_setf(int elt_idx, uint32_t samplingmaskhigh) +{ + ASSERT_ERR((((uint32_t)samplingmaskhigh << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(LA_SAMPLING_MASK_HIGH_ADDR + elt_idx * REG_LA_OFFSET, (uint32_t)samplingmaskhigh << 0); +} + +/// @} + +/** + * @name TRIGGER_MASK_LOW register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00     trigger_mask_med   0x0
+ * 
+ * + * @{ + */ + +/// Address of the TRIGGER_MASK_LOW register +#define LA_TRIGGER_MASK_LOW_ADDR 0x10E00020 +/// Offset of the TRIGGER_MASK_LOW register from the base address +#define LA_TRIGGER_MASK_LOW_OFFSET 0x00000020 +/// Index of the TRIGGER_MASK_LOW register +#define LA_TRIGGER_MASK_LOW_INDEX 0x00000008 +/// Reset value of the TRIGGER_MASK_LOW register +#define LA_TRIGGER_MASK_LOW_RESET 0x00000000 + +/** + * @brief Returns the current value of the TRIGGER_MASK_LOW register. + * The TRIGGER_MASK_LOW register will be read and its value returned. + * @param[in] elt_idx Index of the HW block + * @return The current value of the TRIGGER_MASK_LOW register. + */ +__INLINE uint32_t la_trigger_mask_low_get(int elt_idx) +{ + return REG_PL_RD(LA_TRIGGER_MASK_LOW_ADDR + elt_idx * REG_LA_OFFSET); +} + +/** + * @brief Sets the TRIGGER_MASK_LOW register to a value. + * The TRIGGER_MASK_LOW register will be written. + * @param[in] elt_idx Index of the HW block + * @param value - The value to write. + */ +__INLINE void la_trigger_mask_low_set(int elt_idx, uint32_t value) +{ + REG_PL_WR(LA_TRIGGER_MASK_LOW_ADDR + elt_idx * REG_LA_OFFSET, value); +} + +// field definitions +/// TRIGGER_MASK_MED field mask +#define LA_TRIGGER_MASK_MED_MASK ((uint32_t)0xFFFFFFFF) +/// TRIGGER_MASK_MED field LSB position +#define LA_TRIGGER_MASK_MED_LSB 0 +/// TRIGGER_MASK_MED field width +#define LA_TRIGGER_MASK_MED_WIDTH ((uint32_t)0x00000020) + +/// TRIGGER_MASK_MED field reset value +#define LA_TRIGGER_MASK_MED_RST 0x0 + +/** + * @brief Returns the current value of the trigger_mask_med field in the TRIGGER_MASK_LOW register. + * + * The TRIGGER_MASK_LOW register will be read and the trigger_mask_med field's value will be returned. + * + * @param[in] elt_idx Index of the HW block + * @return The current value of the trigger_mask_med field in the TRIGGER_MASK_LOW register. + */ +__INLINE uint32_t la_trigger_mask_med_getf(int elt_idx) +{ + uint32_t localVal = REG_PL_RD(LA_TRIGGER_MASK_LOW_ADDR + elt_idx * REG_LA_OFFSET); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the trigger_mask_med field of the TRIGGER_MASK_LOW register. + * + * The TRIGGER_MASK_LOW register will be read, modified to contain the new field value, and written. + * + * @param[in] elt_idx Index of the HW block + * @param[in] triggermaskmed - The value to set the field to. + */ +__INLINE void la_trigger_mask_med_setf(int elt_idx, uint32_t triggermaskmed) +{ + ASSERT_ERR((((uint32_t)triggermaskmed << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(LA_TRIGGER_MASK_LOW_ADDR + elt_idx * REG_LA_OFFSET, (uint32_t)triggermaskmed << 0); +} + +/// @} + +/** + * @name TRIGGER_MASK_MED register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00     trigger_mask_low   0x0
+ * 
+ * + * @{ + */ + +/// Address of the TRIGGER_MASK_MED register +#define LA_TRIGGER_MASK_MED_ADDR 0x10E00024 +/// Offset of the TRIGGER_MASK_MED register from the base address +#define LA_TRIGGER_MASK_MED_OFFSET 0x00000024 +/// Index of the TRIGGER_MASK_MED register +#define LA_TRIGGER_MASK_MED_INDEX 0x00000009 +/// Reset value of the TRIGGER_MASK_MED register +#define LA_TRIGGER_MASK_MED_RESET 0x00000000 + +/** + * @brief Returns the current value of the TRIGGER_MASK_MED register. + * The TRIGGER_MASK_MED register will be read and its value returned. + * @param[in] elt_idx Index of the HW block + * @return The current value of the TRIGGER_MASK_MED register. + */ +__INLINE uint32_t la_trigger_mask_med_get(int elt_idx) +{ + return REG_PL_RD(LA_TRIGGER_MASK_MED_ADDR + elt_idx * REG_LA_OFFSET); +} + +/** + * @brief Sets the TRIGGER_MASK_MED register to a value. + * The TRIGGER_MASK_MED register will be written. + * @param[in] elt_idx Index of the HW block + * @param value - The value to write. + */ +__INLINE void la_trigger_mask_med_set(int elt_idx, uint32_t value) +{ + REG_PL_WR(LA_TRIGGER_MASK_MED_ADDR + elt_idx * REG_LA_OFFSET, value); +} + +// field definitions +/// TRIGGER_MASK_LOW field mask +#define LA_TRIGGER_MASK_LOW_MASK ((uint32_t)0xFFFFFFFF) +/// TRIGGER_MASK_LOW field LSB position +#define LA_TRIGGER_MASK_LOW_LSB 0 +/// TRIGGER_MASK_LOW field width +#define LA_TRIGGER_MASK_LOW_WIDTH ((uint32_t)0x00000020) + +/// TRIGGER_MASK_LOW field reset value +#define LA_TRIGGER_MASK_LOW_RST 0x0 + +/** + * @brief Returns the current value of the trigger_mask_low field in the TRIGGER_MASK_MED register. + * + * The TRIGGER_MASK_MED register will be read and the trigger_mask_low field's value will be returned. + * + * @param[in] elt_idx Index of the HW block + * @return The current value of the trigger_mask_low field in the TRIGGER_MASK_MED register. + */ +__INLINE uint32_t la_trigger_mask_low_getf(int elt_idx) +{ + uint32_t localVal = REG_PL_RD(LA_TRIGGER_MASK_MED_ADDR + elt_idx * REG_LA_OFFSET); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the trigger_mask_low field of the TRIGGER_MASK_MED register. + * + * The TRIGGER_MASK_MED register will be read, modified to contain the new field value, and written. + * + * @param[in] elt_idx Index of the HW block + * @param[in] triggermasklow - The value to set the field to. + */ +__INLINE void la_trigger_mask_low_setf(int elt_idx, uint32_t triggermasklow) +{ + ASSERT_ERR((((uint32_t)triggermasklow << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(LA_TRIGGER_MASK_MED_ADDR + elt_idx * REG_LA_OFFSET, (uint32_t)triggermasklow << 0); +} + +/// @} + +/** + * @name TRIGGER_MASK_HIGH register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00    trigger_mask_high   0x0
+ * 
+ * + * @{ + */ + +/// Address of the TRIGGER_MASK_HIGH register +#define LA_TRIGGER_MASK_HIGH_ADDR 0x10E00028 +/// Offset of the TRIGGER_MASK_HIGH register from the base address +#define LA_TRIGGER_MASK_HIGH_OFFSET 0x00000028 +/// Index of the TRIGGER_MASK_HIGH register +#define LA_TRIGGER_MASK_HIGH_INDEX 0x0000000A +/// Reset value of the TRIGGER_MASK_HIGH register +#define LA_TRIGGER_MASK_HIGH_RESET 0x00000000 + +/** + * @brief Returns the current value of the TRIGGER_MASK_HIGH register. + * The TRIGGER_MASK_HIGH register will be read and its value returned. + * @param[in] elt_idx Index of the HW block + * @return The current value of the TRIGGER_MASK_HIGH register. + */ +__INLINE uint32_t la_trigger_mask_high_get(int elt_idx) +{ + return REG_PL_RD(LA_TRIGGER_MASK_HIGH_ADDR + elt_idx * REG_LA_OFFSET); +} + +/** + * @brief Sets the TRIGGER_MASK_HIGH register to a value. + * The TRIGGER_MASK_HIGH register will be written. + * @param[in] elt_idx Index of the HW block + * @param value - The value to write. + */ +__INLINE void la_trigger_mask_high_set(int elt_idx, uint32_t value) +{ + REG_PL_WR(LA_TRIGGER_MASK_HIGH_ADDR + elt_idx * REG_LA_OFFSET, value); +} + +// field definitions +/// TRIGGER_MASK_HIGH field mask +#define LA_TRIGGER_MASK_HIGH_MASK ((uint32_t)0xFFFFFFFF) +/// TRIGGER_MASK_HIGH field LSB position +#define LA_TRIGGER_MASK_HIGH_LSB 0 +/// TRIGGER_MASK_HIGH field width +#define LA_TRIGGER_MASK_HIGH_WIDTH ((uint32_t)0x00000020) + +/// TRIGGER_MASK_HIGH field reset value +#define LA_TRIGGER_MASK_HIGH_RST 0x0 + +/** + * @brief Returns the current value of the trigger_mask_high field in the TRIGGER_MASK_HIGH register. + * + * The TRIGGER_MASK_HIGH register will be read and the trigger_mask_high field's value will be returned. + * + * @param[in] elt_idx Index of the HW block + * @return The current value of the trigger_mask_high field in the TRIGGER_MASK_HIGH register. + */ +__INLINE uint32_t la_trigger_mask_high_getf(int elt_idx) +{ + uint32_t localVal = REG_PL_RD(LA_TRIGGER_MASK_HIGH_ADDR + elt_idx * REG_LA_OFFSET); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the trigger_mask_high field of the TRIGGER_MASK_HIGH register. + * + * The TRIGGER_MASK_HIGH register will be read, modified to contain the new field value, and written. + * + * @param[in] elt_idx Index of the HW block + * @param[in] triggermaskhigh - The value to set the field to. + */ +__INLINE void la_trigger_mask_high_setf(int elt_idx, uint32_t triggermaskhigh) +{ + ASSERT_ERR((((uint32_t)triggermaskhigh << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(LA_TRIGGER_MASK_HIGH_ADDR + elt_idx * REG_LA_OFFSET, (uint32_t)triggermaskhigh << 0); +} + +/// @} + +/** + * @name TRIGGER_VALUE_LOW register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00    trigger_value_low   0x0
+ * 
+ * + * @{ + */ + +/// Address of the TRIGGER_VALUE_LOW register +#define LA_TRIGGER_VALUE_LOW_ADDR 0x10E0002C +/// Offset of the TRIGGER_VALUE_LOW register from the base address +#define LA_TRIGGER_VALUE_LOW_OFFSET 0x0000002C +/// Index of the TRIGGER_VALUE_LOW register +#define LA_TRIGGER_VALUE_LOW_INDEX 0x0000000B +/// Reset value of the TRIGGER_VALUE_LOW register +#define LA_TRIGGER_VALUE_LOW_RESET 0x00000000 + +/** + * @brief Returns the current value of the TRIGGER_VALUE_LOW register. + * The TRIGGER_VALUE_LOW register will be read and its value returned. + * @param[in] elt_idx Index of the HW block + * @return The current value of the TRIGGER_VALUE_LOW register. + */ +__INLINE uint32_t la_trigger_value_low_get(int elt_idx) +{ + return REG_PL_RD(LA_TRIGGER_VALUE_LOW_ADDR + elt_idx * REG_LA_OFFSET); +} + +/** + * @brief Sets the TRIGGER_VALUE_LOW register to a value. + * The TRIGGER_VALUE_LOW register will be written. + * @param[in] elt_idx Index of the HW block + * @param value - The value to write. + */ +__INLINE void la_trigger_value_low_set(int elt_idx, uint32_t value) +{ + REG_PL_WR(LA_TRIGGER_VALUE_LOW_ADDR + elt_idx * REG_LA_OFFSET, value); +} + +// field definitions +/// TRIGGER_VALUE_LOW field mask +#define LA_TRIGGER_VALUE_LOW_MASK ((uint32_t)0xFFFFFFFF) +/// TRIGGER_VALUE_LOW field LSB position +#define LA_TRIGGER_VALUE_LOW_LSB 0 +/// TRIGGER_VALUE_LOW field width +#define LA_TRIGGER_VALUE_LOW_WIDTH ((uint32_t)0x00000020) + +/// TRIGGER_VALUE_LOW field reset value +#define LA_TRIGGER_VALUE_LOW_RST 0x0 + +/** + * @brief Returns the current value of the trigger_value_low field in the TRIGGER_VALUE_LOW register. + * + * The TRIGGER_VALUE_LOW register will be read and the trigger_value_low field's value will be returned. + * + * @param[in] elt_idx Index of the HW block + * @return The current value of the trigger_value_low field in the TRIGGER_VALUE_LOW register. + */ +__INLINE uint32_t la_trigger_value_low_getf(int elt_idx) +{ + uint32_t localVal = REG_PL_RD(LA_TRIGGER_VALUE_LOW_ADDR + elt_idx * REG_LA_OFFSET); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the trigger_value_low field of the TRIGGER_VALUE_LOW register. + * + * The TRIGGER_VALUE_LOW register will be read, modified to contain the new field value, and written. + * + * @param[in] elt_idx Index of the HW block + * @param[in] triggervaluelow - The value to set the field to. + */ +__INLINE void la_trigger_value_low_setf(int elt_idx, uint32_t triggervaluelow) +{ + ASSERT_ERR((((uint32_t)triggervaluelow << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(LA_TRIGGER_VALUE_LOW_ADDR + elt_idx * REG_LA_OFFSET, (uint32_t)triggervaluelow << 0); +} + +/// @} + +/** + * @name TRIGGER_VALUE_MED register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00    trigger_value_med   0x0
+ * 
+ * + * @{ + */ + +/// Address of the TRIGGER_VALUE_MED register +#define LA_TRIGGER_VALUE_MED_ADDR 0x10E00030 +/// Offset of the TRIGGER_VALUE_MED register from the base address +#define LA_TRIGGER_VALUE_MED_OFFSET 0x00000030 +/// Index of the TRIGGER_VALUE_MED register +#define LA_TRIGGER_VALUE_MED_INDEX 0x0000000C +/// Reset value of the TRIGGER_VALUE_MED register +#define LA_TRIGGER_VALUE_MED_RESET 0x00000000 + +/** + * @brief Returns the current value of the TRIGGER_VALUE_MED register. + * The TRIGGER_VALUE_MED register will be read and its value returned. + * @param[in] elt_idx Index of the HW block + * @return The current value of the TRIGGER_VALUE_MED register. + */ +__INLINE uint32_t la_trigger_value_med_get(int elt_idx) +{ + return REG_PL_RD(LA_TRIGGER_VALUE_MED_ADDR + elt_idx * REG_LA_OFFSET); +} + +/** + * @brief Sets the TRIGGER_VALUE_MED register to a value. + * The TRIGGER_VALUE_MED register will be written. + * @param[in] elt_idx Index of the HW block + * @param value - The value to write. + */ +__INLINE void la_trigger_value_med_set(int elt_idx, uint32_t value) +{ + REG_PL_WR(LA_TRIGGER_VALUE_MED_ADDR + elt_idx * REG_LA_OFFSET, value); +} + +// field definitions +/// TRIGGER_VALUE_MED field mask +#define LA_TRIGGER_VALUE_MED_MASK ((uint32_t)0xFFFFFFFF) +/// TRIGGER_VALUE_MED field LSB position +#define LA_TRIGGER_VALUE_MED_LSB 0 +/// TRIGGER_VALUE_MED field width +#define LA_TRIGGER_VALUE_MED_WIDTH ((uint32_t)0x00000020) + +/// TRIGGER_VALUE_MED field reset value +#define LA_TRIGGER_VALUE_MED_RST 0x0 + +/** + * @brief Returns the current value of the trigger_value_med field in the TRIGGER_VALUE_MED register. + * + * The TRIGGER_VALUE_MED register will be read and the trigger_value_med field's value will be returned. + * + * @param[in] elt_idx Index of the HW block + * @return The current value of the trigger_value_med field in the TRIGGER_VALUE_MED register. + */ +__INLINE uint32_t la_trigger_value_med_getf(int elt_idx) +{ + uint32_t localVal = REG_PL_RD(LA_TRIGGER_VALUE_MED_ADDR + elt_idx * REG_LA_OFFSET); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the trigger_value_med field of the TRIGGER_VALUE_MED register. + * + * The TRIGGER_VALUE_MED register will be read, modified to contain the new field value, and written. + * + * @param[in] elt_idx Index of the HW block + * @param[in] triggervaluemed - The value to set the field to. + */ +__INLINE void la_trigger_value_med_setf(int elt_idx, uint32_t triggervaluemed) +{ + ASSERT_ERR((((uint32_t)triggervaluemed << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(LA_TRIGGER_VALUE_MED_ADDR + elt_idx * REG_LA_OFFSET, (uint32_t)triggervaluemed << 0); +} + +/// @} + +/** + * @name TRIGGER_VALUE_HIGH register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00   trigger_value_high   0x0
+ * 
+ * + * @{ + */ + +/// Address of the TRIGGER_VALUE_HIGH register +#define LA_TRIGGER_VALUE_HIGH_ADDR 0x10E00034 +/// Offset of the TRIGGER_VALUE_HIGH register from the base address +#define LA_TRIGGER_VALUE_HIGH_OFFSET 0x00000034 +/// Index of the TRIGGER_VALUE_HIGH register +#define LA_TRIGGER_VALUE_HIGH_INDEX 0x0000000D +/// Reset value of the TRIGGER_VALUE_HIGH register +#define LA_TRIGGER_VALUE_HIGH_RESET 0x00000000 + +/** + * @brief Returns the current value of the TRIGGER_VALUE_HIGH register. + * The TRIGGER_VALUE_HIGH register will be read and its value returned. + * @param[in] elt_idx Index of the HW block + * @return The current value of the TRIGGER_VALUE_HIGH register. + */ +__INLINE uint32_t la_trigger_value_high_get(int elt_idx) +{ + return REG_PL_RD(LA_TRIGGER_VALUE_HIGH_ADDR + elt_idx * REG_LA_OFFSET); +} + +/** + * @brief Sets the TRIGGER_VALUE_HIGH register to a value. + * The TRIGGER_VALUE_HIGH register will be written. + * @param[in] elt_idx Index of the HW block + * @param value - The value to write. + */ +__INLINE void la_trigger_value_high_set(int elt_idx, uint32_t value) +{ + REG_PL_WR(LA_TRIGGER_VALUE_HIGH_ADDR + elt_idx * REG_LA_OFFSET, value); +} + +// field definitions +/// TRIGGER_VALUE_HIGH field mask +#define LA_TRIGGER_VALUE_HIGH_MASK ((uint32_t)0xFFFFFFFF) +/// TRIGGER_VALUE_HIGH field LSB position +#define LA_TRIGGER_VALUE_HIGH_LSB 0 +/// TRIGGER_VALUE_HIGH field width +#define LA_TRIGGER_VALUE_HIGH_WIDTH ((uint32_t)0x00000020) + +/// TRIGGER_VALUE_HIGH field reset value +#define LA_TRIGGER_VALUE_HIGH_RST 0x0 + +/** + * @brief Returns the current value of the trigger_value_high field in the TRIGGER_VALUE_HIGH register. + * + * The TRIGGER_VALUE_HIGH register will be read and the trigger_value_high field's value will be returned. + * + * @param[in] elt_idx Index of the HW block + * @return The current value of the trigger_value_high field in the TRIGGER_VALUE_HIGH register. + */ +__INLINE uint32_t la_trigger_value_high_getf(int elt_idx) +{ + uint32_t localVal = REG_PL_RD(LA_TRIGGER_VALUE_HIGH_ADDR + elt_idx * REG_LA_OFFSET); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the trigger_value_high field of the TRIGGER_VALUE_HIGH register. + * + * The TRIGGER_VALUE_HIGH register will be read, modified to contain the new field value, and written. + * + * @param[in] elt_idx Index of the HW block + * @param[in] triggervaluehigh - The value to set the field to. + */ +__INLINE void la_trigger_value_high_setf(int elt_idx, uint32_t triggervaluehigh) +{ + ASSERT_ERR((((uint32_t)triggervaluehigh << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(LA_TRIGGER_VALUE_HIGH_ADDR + elt_idx * REG_LA_OFFSET, (uint32_t)triggervaluehigh << 0); +} + +/// @} + +/** + * @name TRIGGER_POINT register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00        trigger_point   0x0
+ * 
+ * + * @{ + */ + +/// Address of the TRIGGER_POINT register +#define LA_TRIGGER_POINT_ADDR 0x10E00038 +/// Offset of the TRIGGER_POINT register from the base address +#define LA_TRIGGER_POINT_OFFSET 0x00000038 +/// Index of the TRIGGER_POINT register +#define LA_TRIGGER_POINT_INDEX 0x0000000E +/// Reset value of the TRIGGER_POINT register +#define LA_TRIGGER_POINT_RESET 0x00000000 + +/** + * @brief Returns the current value of the TRIGGER_POINT register. + * The TRIGGER_POINT register will be read and its value returned. + * @param[in] elt_idx Index of the HW block + * @return The current value of the TRIGGER_POINT register. + */ +__INLINE uint32_t la_trigger_point_get(int elt_idx) +{ + return REG_PL_RD(LA_TRIGGER_POINT_ADDR + elt_idx * REG_LA_OFFSET); +} + +/** + * @brief Sets the TRIGGER_POINT register to a value. + * The TRIGGER_POINT register will be written. + * @param[in] elt_idx Index of the HW block + * @param value - The value to write. + */ +__INLINE void la_trigger_point_set(int elt_idx, uint32_t value) +{ + REG_PL_WR(LA_TRIGGER_POINT_ADDR + elt_idx * REG_LA_OFFSET, value); +} + +// field definitions +/// TRIGGER_POINT field mask +#define LA_TRIGGER_POINT_MASK ((uint32_t)0x0000FFFF) +/// TRIGGER_POINT field LSB position +#define LA_TRIGGER_POINT_LSB 0 +/// TRIGGER_POINT field width +#define LA_TRIGGER_POINT_WIDTH ((uint32_t)0x00000010) + +/// TRIGGER_POINT field reset value +#define LA_TRIGGER_POINT_RST 0x0 + +/** + * @brief Returns the current value of the trigger_point field in the TRIGGER_POINT register. + * + * The TRIGGER_POINT register will be read and the trigger_point field's value will be returned. + * + * @param[in] elt_idx Index of the HW block + * @return The current value of the trigger_point field in the TRIGGER_POINT register. + */ +__INLINE uint16_t la_trigger_point_getf(int elt_idx) +{ + uint32_t localVal = REG_PL_RD(LA_TRIGGER_POINT_ADDR + elt_idx * REG_LA_OFFSET); + ASSERT_ERR((localVal & ~((uint32_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the trigger_point field of the TRIGGER_POINT register. + * + * The TRIGGER_POINT register will be read, modified to contain the new field value, and written. + * + * @param[in] elt_idx Index of the HW block + * @param[in] triggerpoint - The value to set the field to. + */ +__INLINE void la_trigger_point_setf(int elt_idx, uint16_t triggerpoint) +{ + ASSERT_ERR((((uint32_t)triggerpoint << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_PL_WR(LA_TRIGGER_POINT_ADDR + elt_idx * REG_LA_OFFSET, (uint32_t)triggerpoint << 0); +} + +/// @} + +/** + * @name FIRSTSAMPLE register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00          firstsample   0x0
+ * 
+ * + * @{ + */ + +/// Address of the FIRSTSAMPLE register +#define LA_FIRSTSAMPLE_ADDR 0x10E0003C +/// Offset of the FIRSTSAMPLE register from the base address +#define LA_FIRSTSAMPLE_OFFSET 0x0000003C +/// Index of the FIRSTSAMPLE register +#define LA_FIRSTSAMPLE_INDEX 0x0000000F +/// Reset value of the FIRSTSAMPLE register +#define LA_FIRSTSAMPLE_RESET 0x00000000 + +/** + * @brief Returns the current value of the FIRSTSAMPLE register. + * The FIRSTSAMPLE register will be read and its value returned. + * @param[in] elt_idx Index of the HW block + * @return The current value of the FIRSTSAMPLE register. + */ +__INLINE uint32_t la_firstsample_get(int elt_idx) +{ + return REG_PL_RD(LA_FIRSTSAMPLE_ADDR + elt_idx * REG_LA_OFFSET); +} + +/** + * @brief Sets the FIRSTSAMPLE register to a value. + * The FIRSTSAMPLE register will be written. + * @param[in] elt_idx Index of the HW block + * @param value - The value to write. + */ +__INLINE void la_firstsample_set(int elt_idx, uint32_t value) +{ + REG_PL_WR(LA_FIRSTSAMPLE_ADDR + elt_idx * REG_LA_OFFSET, value); +} + +// field definitions +/// FIRSTSAMPLE field mask +#define LA_FIRSTSAMPLE_MASK ((uint32_t)0x0000FFFF) +/// FIRSTSAMPLE field LSB position +#define LA_FIRSTSAMPLE_LSB 0 +/// FIRSTSAMPLE field width +#define LA_FIRSTSAMPLE_WIDTH ((uint32_t)0x00000010) + +/// FIRSTSAMPLE field reset value +#define LA_FIRSTSAMPLE_RST 0x0 + +/** + * @brief Returns the current value of the firstsample field in the FIRSTSAMPLE register. + * + * The FIRSTSAMPLE register will be read and the firstsample field's value will be returned. + * + * @param[in] elt_idx Index of the HW block + * @return The current value of the firstsample field in the FIRSTSAMPLE register. + */ +__INLINE uint16_t la_firstsample_getf(int elt_idx) +{ + uint32_t localVal = REG_PL_RD(LA_FIRSTSAMPLE_ADDR + elt_idx * REG_LA_OFFSET); + ASSERT_ERR((localVal & ~((uint32_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +/// @} +#endif + +#endif // _REG_LA_H_ + +/// @} + diff --git a/beken_os/beken378/driver/common/reg/reg_mac_core.h b/beken_os/beken378/driver/common/reg/reg_mac_core.h new file mode 100755 index 0000000..4b244d4 --- /dev/null +++ b/beken_os/beken378/driver/common/reg/reg_mac_core.h @@ -0,0 +1,16687 @@ +/** + * @file reg_mac_core.h + * @brief Definitions of the NXMAC HW block registers and register access functions. + * + * @defgroup REG_MAC_CORE REG_MAC_CORE + * @ingroup REG + * @{ + * + * @brief Definitions of the NXMAC HW block registers and register access functions. + */ +#ifndef _REG_MAC_CORE_H_ +#define _REG_MAC_CORE_H_ + +#include "co_int.h" +#include "_reg_mac_core.h" +#include "compiler.h" +#include "arch.h" +#include "reg_access.h" + +/*lint -e91 */ +/** @brief Number of registers in the REG_MAC_CORE peripheral. + */ +#define REG_MAC_CORE_COUNT 344 + +/** @brief Decoding mask of the REG_MAC_CORE peripheral registers from the CPU point of view. + */ +#define REG_MAC_CORE_DECODING_MASK 0x000007FF + +/** + * @name SIGNATURE register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00            signature   0x0
+ * 
+ * + * @{ + */ + +/// Address of the SIGNATURE register +#define NXMAC_SIGNATURE_ADDR 0xC0000000 +/// Offset of the SIGNATURE register from the base address +#define NXMAC_SIGNATURE_OFFSET 0x00000000 +/// Index of the SIGNATURE register +#define NXMAC_SIGNATURE_INDEX 0x00000000 +/// Reset value of the SIGNATURE register +#define NXMAC_SIGNATURE_RESET 0x00000000 + +/** + * @brief Returns the current value of the SIGNATURE register. + * The SIGNATURE register will be read and its value returned. + * @return The current value of the SIGNATURE register. + */ +__INLINE uint32_t nxmac_signature_get(void) +{ + return REG_PL_RD(NXMAC_SIGNATURE_ADDR); +} + +// field definitions +/// SIGNATURE field mask +#define NXMAC_SIGNATURE_MASK ((uint32_t)0xFFFFFFFF) +/// SIGNATURE field LSB position +#define NXMAC_SIGNATURE_LSB 0 +/// SIGNATURE field width +#define NXMAC_SIGNATURE_WIDTH ((uint32_t)0x00000020) + +/// SIGNATURE field reset value +#define NXMAC_SIGNATURE_RST 0x0 + +/** + * @brief Returns the current value of the signature field in the SIGNATURE register. + * + * The SIGNATURE register will be read and the signature field's value will be returned. + * + * @return The current value of the signature field in the SIGNATURE register. + */ +__INLINE uint32_t nxmac_signature_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SIGNATURE_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/// @} + +/** + * @name VERSION_1 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     19             muMIMOTx   0
+ *     18                bfmer   0
+ *     17                bfmee   0
+ *     16     mac80211MHFormat   0
+ *     14                 coex   0
+ *     13                 wapi   0
+ *     12                  tpc   1
+ *     11                  vht   1
+ *     10                   ht   1
+ *     08                  rce   0
+ *     07                 ccmp   0
+ *     06                 tkip   0
+ *     05                  wep   0
+ *     04             security   0
+ *     03                  sme   0
+ *     02                 hcca   0
+ *     01                 edca   1
+ *     00                  qos   1
+ * 
+ * + * @{ + */ + +/// Address of the VERSION_1 register +#define NXMAC_VERSION_1_ADDR 0xC0000004 +/// Offset of the VERSION_1 register from the base address +#define NXMAC_VERSION_1_OFFSET 0x00000004 +/// Index of the VERSION_1 register +#define NXMAC_VERSION_1_INDEX 0x00000001 +/// Reset value of the VERSION_1 register +#define NXMAC_VERSION_1_RESET 0x00001C03 + +/** + * @brief Returns the current value of the VERSION_1 register. + * The VERSION_1 register will be read and its value returned. + * @return The current value of the VERSION_1 register. + */ +__INLINE uint32_t nxmac_version_1_get(void) +{ + return REG_PL_RD(NXMAC_VERSION_1_ADDR); +} + +// field definitions +/// MU_MIMO_TX field bit +#define NXMAC_MU_MIMO_TX_BIT ((uint32_t)0x00080000) +/// MU_MIMO_TX field position +#define NXMAC_MU_MIMO_TX_POS 19 +/// BFMER field bit +#define NXMAC_BFMER_BIT ((uint32_t)0x00040000) +/// BFMER field position +#define NXMAC_BFMER_POS 18 +/// BFMEE field bit +#define NXMAC_BFMEE_BIT ((uint32_t)0x00020000) +/// BFMEE field position +#define NXMAC_BFMEE_POS 17 +/// MAC_80211MH_FORMAT field bit +#define NXMAC_MAC_80211MH_FORMAT_BIT ((uint32_t)0x00010000) +/// MAC_80211MH_FORMAT field position +#define NXMAC_MAC_80211MH_FORMAT_POS 16 +/// COEX field bit +#define NXMAC_COEX_BIT ((uint32_t)0x00004000) +/// COEX field position +#define NXMAC_COEX_POS 14 +/// WAPI field bit +#define NXMAC_WAPI_BIT ((uint32_t)0x00002000) +/// WAPI field position +#define NXMAC_WAPI_POS 13 +/// TPC field bit +#define NXMAC_TPC_BIT ((uint32_t)0x00001000) +/// TPC field position +#define NXMAC_TPC_POS 12 +/// VHT field bit +#define NXMAC_VHT_BIT ((uint32_t)0x00000800) +/// VHT field position +#define NXMAC_VHT_POS 11 +/// HT field bit +#define NXMAC_HT_BIT ((uint32_t)0x00000400) +/// HT field position +#define NXMAC_HT_POS 10 +/// RCE field bit +#define NXMAC_RCE_BIT ((uint32_t)0x00000100) +/// RCE field position +#define NXMAC_RCE_POS 8 +/// CCMP field bit +#define NXMAC_CCMP_BIT ((uint32_t)0x00000080) +/// CCMP field position +#define NXMAC_CCMP_POS 7 +/// TKIP field bit +#define NXMAC_TKIP_BIT ((uint32_t)0x00000040) +/// TKIP field position +#define NXMAC_TKIP_POS 6 +/// WEP field bit +#define NXMAC_WEP_BIT ((uint32_t)0x00000020) +/// WEP field position +#define NXMAC_WEP_POS 5 +/// SECURITY field bit +#define NXMAC_SECURITY_BIT ((uint32_t)0x00000010) +/// SECURITY field position +#define NXMAC_SECURITY_POS 4 +/// SME field bit +#define NXMAC_SME_BIT ((uint32_t)0x00000008) +/// SME field position +#define NXMAC_SME_POS 3 +/// HCCA field bit +#define NXMAC_HCCA_BIT ((uint32_t)0x00000004) +/// HCCA field position +#define NXMAC_HCCA_POS 2 +/// EDCA field bit +#define NXMAC_EDCA_BIT ((uint32_t)0x00000002) +/// EDCA field position +#define NXMAC_EDCA_POS 1 +/// QOS field bit +#define NXMAC_QOS_BIT ((uint32_t)0x00000001) +/// QOS field position +#define NXMAC_QOS_POS 0 + +/// MU_MIMO_TX field reset value +#define NXMAC_MU_MIMO_TX_RST 0x0 +/// BFMER field reset value +#define NXMAC_BFMER_RST 0x0 +/// BFMEE field reset value +#define NXMAC_BFMEE_RST 0x0 +/// MAC_80211MH_FORMAT field reset value +#define NXMAC_MAC_80211MH_FORMAT_RST 0x0 +/// COEX field reset value +#define NXMAC_COEX_RST 0x0 +/// WAPI field reset value +#define NXMAC_WAPI_RST 0x0 +/// TPC field reset value +#define NXMAC_TPC_RST 0x1 +/// VHT field reset value +#define NXMAC_VHT_RST 0x1 +/// HT field reset value +#define NXMAC_HT_RST 0x1 +/// RCE field reset value +#define NXMAC_RCE_RST 0x0 +/// CCMP field reset value +#define NXMAC_CCMP_RST 0x0 +/// TKIP field reset value +#define NXMAC_TKIP_RST 0x0 +/// WEP field reset value +#define NXMAC_WEP_RST 0x0 +/// SECURITY field reset value +#define NXMAC_SECURITY_RST 0x0 +/// SME field reset value +#define NXMAC_SME_RST 0x0 +/// HCCA field reset value +#define NXMAC_HCCA_RST 0x0 +/// EDCA field reset value +#define NXMAC_EDCA_RST 0x1 +/// QOS field reset value +#define NXMAC_QOS_RST 0x1 + +/** + * @brief Unpacks VERSION_1's fields from current value of the VERSION_1 register. + * + * Reads the VERSION_1 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] mumimotx - Will be populated with the current value of this field from the register. + * @param[out] bfmer - Will be populated with the current value of this field from the register. + * @param[out] bfmee - Will be populated with the current value of this field from the register. + * @param[out] mac80211mhformat - Will be populated with the current value of this field from the register. + * @param[out] coex - Will be populated with the current value of this field from the register. + * @param[out] wapi - Will be populated with the current value of this field from the register. + * @param[out] tpc - Will be populated with the current value of this field from the register. + * @param[out] vht - Will be populated with the current value of this field from the register. + * @param[out] ht - Will be populated with the current value of this field from the register. + * @param[out] rce - Will be populated with the current value of this field from the register. + * @param[out] ccmp - Will be populated with the current value of this field from the register. + * @param[out] tkip - Will be populated with the current value of this field from the register. + * @param[out] wep - Will be populated with the current value of this field from the register. + * @param[out] security - Will be populated with the current value of this field from the register. + * @param[out] sme - Will be populated with the current value of this field from the register. + * @param[out] hcca - Will be populated with the current value of this field from the register. + * @param[out] edca - Will be populated with the current value of this field from the register. + * @param[out] qos - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_version_1_unpack(uint8_t *mumimotx, uint8_t *bfmer, uint8_t *bfmee, uint8_t *mac80211mhformat, uint8_t *coex, uint8_t *wapi, uint8_t *tpc, uint8_t *vht, uint8_t *ht, uint8_t *rce, uint8_t *ccmp, uint8_t *tkip, uint8_t *wep, uint8_t *security, uint8_t *sme, uint8_t *hcca, uint8_t *edca, uint8_t *qos) +{ + uint32_t localVal = REG_PL_RD(NXMAC_VERSION_1_ADDR); + + *mumimotx = (localVal & ((uint32_t)0x00080000)) >> 19; + *bfmer = (localVal & ((uint32_t)0x00040000)) >> 18; + *bfmee = (localVal & ((uint32_t)0x00020000)) >> 17; + *mac80211mhformat = (localVal & ((uint32_t)0x00010000)) >> 16; + *coex = (localVal & ((uint32_t)0x00004000)) >> 14; + *wapi = (localVal & ((uint32_t)0x00002000)) >> 13; + *tpc = (localVal & ((uint32_t)0x00001000)) >> 12; + *vht = (localVal & ((uint32_t)0x00000800)) >> 11; + *ht = (localVal & ((uint32_t)0x00000400)) >> 10; + *rce = (localVal & ((uint32_t)0x00000100)) >> 8; + *ccmp = (localVal & ((uint32_t)0x00000080)) >> 7; + *tkip = (localVal & ((uint32_t)0x00000040)) >> 6; + *wep = (localVal & ((uint32_t)0x00000020)) >> 5; + *security = (localVal & ((uint32_t)0x00000010)) >> 4; + *sme = (localVal & ((uint32_t)0x00000008)) >> 3; + *hcca = (localVal & ((uint32_t)0x00000004)) >> 2; + *edca = (localVal & ((uint32_t)0x00000002)) >> 1; + *qos = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +/** + * @brief Returns the current value of the muMIMOTx field in the VERSION_1 register. + * + * The VERSION_1 register will be read and the muMIMOTx field's value will be returned. + * + * @return The current value of the muMIMOTx field in the VERSION_1 register. + */ +__INLINE uint8_t nxmac_mu_mimo_tx_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_VERSION_1_ADDR); + return ((localVal & ((uint32_t)0x00080000)) >> 19); +} + +/** + * @brief Returns the current value of the bfmer field in the VERSION_1 register. + * + * The VERSION_1 register will be read and the bfmer field's value will be returned. + * + * @return The current value of the bfmer field in the VERSION_1 register. + */ +__INLINE uint8_t nxmac_bfmer_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_VERSION_1_ADDR); + return ((localVal & ((uint32_t)0x00040000)) >> 18); +} + +/** + * @brief Returns the current value of the bfmee field in the VERSION_1 register. + * + * The VERSION_1 register will be read and the bfmee field's value will be returned. + * + * @return The current value of the bfmee field in the VERSION_1 register. + */ +__INLINE uint8_t nxmac_bfmee_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_VERSION_1_ADDR); + return ((localVal & ((uint32_t)0x00020000)) >> 17); +} + +/** + * @brief Returns the current value of the mac80211MHFormat field in the VERSION_1 register. + * + * The VERSION_1 register will be read and the mac80211MHFormat field's value will be returned. + * + * @return The current value of the mac80211MHFormat field in the VERSION_1 register. + */ +__INLINE uint8_t nxmac_mac_80211mh_format_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_VERSION_1_ADDR); + return ((localVal & ((uint32_t)0x00010000)) >> 16); +} + +/** + * @brief Returns the current value of the coex field in the VERSION_1 register. + * + * The VERSION_1 register will be read and the coex field's value will be returned. + * + * @return The current value of the coex field in the VERSION_1 register. + */ +__INLINE uint8_t nxmac_coex_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_VERSION_1_ADDR); + return ((localVal & ((uint32_t)0x00004000)) >> 14); +} + +/** + * @brief Returns the current value of the wapi field in the VERSION_1 register. + * + * The VERSION_1 register will be read and the wapi field's value will be returned. + * + * @return The current value of the wapi field in the VERSION_1 register. + */ +__INLINE uint8_t nxmac_wapi_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_VERSION_1_ADDR); + return ((localVal & ((uint32_t)0x00002000)) >> 13); +} + +/** + * @brief Returns the current value of the tpc field in the VERSION_1 register. + * + * The VERSION_1 register will be read and the tpc field's value will be returned. + * + * @return The current value of the tpc field in the VERSION_1 register. + */ +__INLINE uint8_t nxmac_tpc_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_VERSION_1_ADDR); + return ((localVal & ((uint32_t)0x00001000)) >> 12); +} + +/** + * @brief Returns the current value of the vht field in the VERSION_1 register. + * + * The VERSION_1 register will be read and the vht field's value will be returned. + * + * @return The current value of the vht field in the VERSION_1 register. + */ +__INLINE uint8_t nxmac_vht_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_VERSION_1_ADDR); + return ((localVal & ((uint32_t)0x00000800)) >> 11); +} + +/** + * @brief Returns the current value of the ht field in the VERSION_1 register. + * + * The VERSION_1 register will be read and the ht field's value will be returned. + * + * @return The current value of the ht field in the VERSION_1 register. + */ +__INLINE uint8_t nxmac_ht_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_VERSION_1_ADDR); + return ((localVal & ((uint32_t)0x00000400)) >> 10); +} + +/** + * @brief Returns the current value of the rce field in the VERSION_1 register. + * + * The VERSION_1 register will be read and the rce field's value will be returned. + * + * @return The current value of the rce field in the VERSION_1 register. + */ +__INLINE uint8_t nxmac_rce_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_VERSION_1_ADDR); + return ((localVal & ((uint32_t)0x00000100)) >> 8); +} + +/** + * @brief Returns the current value of the ccmp field in the VERSION_1 register. + * + * The VERSION_1 register will be read and the ccmp field's value will be returned. + * + * @return The current value of the ccmp field in the VERSION_1 register. + */ +__INLINE uint8_t nxmac_ccmp_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_VERSION_1_ADDR); + return ((localVal & ((uint32_t)0x00000080)) >> 7); +} + +/** + * @brief Returns the current value of the tkip field in the VERSION_1 register. + * + * The VERSION_1 register will be read and the tkip field's value will be returned. + * + * @return The current value of the tkip field in the VERSION_1 register. + */ +__INLINE uint8_t nxmac_tkip_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_VERSION_1_ADDR); + return ((localVal & ((uint32_t)0x00000040)) >> 6); +} + +/** + * @brief Returns the current value of the wep field in the VERSION_1 register. + * + * The VERSION_1 register will be read and the wep field's value will be returned. + * + * @return The current value of the wep field in the VERSION_1 register. + */ +__INLINE uint8_t nxmac_wep_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_VERSION_1_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +/** + * @brief Returns the current value of the security field in the VERSION_1 register. + * + * The VERSION_1 register will be read and the security field's value will be returned. + * + * @return The current value of the security field in the VERSION_1 register. + */ +__INLINE uint8_t nxmac_security_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_VERSION_1_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +/** + * @brief Returns the current value of the sme field in the VERSION_1 register. + * + * The VERSION_1 register will be read and the sme field's value will be returned. + * + * @return The current value of the sme field in the VERSION_1 register. + */ +__INLINE uint8_t nxmac_sme_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_VERSION_1_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +/** + * @brief Returns the current value of the hcca field in the VERSION_1 register. + * + * The VERSION_1 register will be read and the hcca field's value will be returned. + * + * @return The current value of the hcca field in the VERSION_1 register. + */ +__INLINE uint8_t nxmac_hcca_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_VERSION_1_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +/** + * @brief Returns the current value of the edca field in the VERSION_1 register. + * + * The VERSION_1 register will be read and the edca field's value will be returned. + * + * @return The current value of the edca field in the VERSION_1 register. + */ +__INLINE uint8_t nxmac_edca_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_VERSION_1_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +/** + * @brief Returns the current value of the qos field in the VERSION_1 register. + * + * The VERSION_1 register will be read and the qos field's value will be returned. + * + * @return The current value of the qos field in the VERSION_1 register. + */ +__INLINE uint8_t nxmac_qos_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_VERSION_1_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/// @} + +/** + * @name VERSION_2 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  16:14          phaseNumber   0x0
+ *  13:08        releaseNumber   0x0
+ *     07            ieRelease   0
+ *  06:00            umVersion   0x0
+ * 
+ * + * @{ + */ + +/// Address of the VERSION_2 register +#define NXMAC_VERSION_2_ADDR 0xC0000008 +/// Offset of the VERSION_2 register from the base address +#define NXMAC_VERSION_2_OFFSET 0x00000008 +/// Index of the VERSION_2 register +#define NXMAC_VERSION_2_INDEX 0x00000002 +/// Reset value of the VERSION_2 register +#define NXMAC_VERSION_2_RESET 0x00000000 + +/** + * @brief Returns the current value of the VERSION_2 register. + * The VERSION_2 register will be read and its value returned. + * @return The current value of the VERSION_2 register. + */ +__INLINE uint32_t nxmac_version_2_get(void) +{ + return REG_PL_RD(NXMAC_VERSION_2_ADDR); +} + +// field definitions +/// PHASE_NUMBER field mask +#define NXMAC_PHASE_NUMBER_MASK ((uint32_t)0x0001C000) +/// PHASE_NUMBER field LSB position +#define NXMAC_PHASE_NUMBER_LSB 14 +/// PHASE_NUMBER field width +#define NXMAC_PHASE_NUMBER_WIDTH ((uint32_t)0x00000003) +/// RELEASE_NUMBER field mask +#define NXMAC_RELEASE_NUMBER_MASK ((uint32_t)0x00003F00) +/// RELEASE_NUMBER field LSB position +#define NXMAC_RELEASE_NUMBER_LSB 8 +/// RELEASE_NUMBER field width +#define NXMAC_RELEASE_NUMBER_WIDTH ((uint32_t)0x00000006) +/// IE_RELEASE field bit +#define NXMAC_IE_RELEASE_BIT ((uint32_t)0x00000080) +/// IE_RELEASE field position +#define NXMAC_IE_RELEASE_POS 7 +/// UM_VERSION field mask +#define NXMAC_UM_VERSION_MASK ((uint32_t)0x0000007F) +/// UM_VERSION field LSB position +#define NXMAC_UM_VERSION_LSB 0 +/// UM_VERSION field width +#define NXMAC_UM_VERSION_WIDTH ((uint32_t)0x00000007) + +/// PHASE_NUMBER field reset value +#define NXMAC_PHASE_NUMBER_RST 0x0 +/// RELEASE_NUMBER field reset value +#define NXMAC_RELEASE_NUMBER_RST 0x0 +/// IE_RELEASE field reset value +#define NXMAC_IE_RELEASE_RST 0x0 +/// UM_VERSION field reset value +#define NXMAC_UM_VERSION_RST 0x0 + +/** + * @brief Unpacks VERSION_2's fields from current value of the VERSION_2 register. + * + * Reads the VERSION_2 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] phasenumber - Will be populated with the current value of this field from the register. + * @param[out] releasenumber - Will be populated with the current value of this field from the register. + * @param[out] ierelease - Will be populated with the current value of this field from the register. + * @param[out] umversion - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_version_2_unpack(uint8_t *phasenumber, uint8_t *releasenumber, uint8_t *ierelease, uint8_t *umversion) +{ + uint32_t localVal = REG_PL_RD(NXMAC_VERSION_2_ADDR); + + *phasenumber = (localVal & ((uint32_t)0x0001C000)) >> 14; + *releasenumber = (localVal & ((uint32_t)0x00003F00)) >> 8; + *ierelease = (localVal & ((uint32_t)0x00000080)) >> 7; + *umversion = (localVal & ((uint32_t)0x0000007F)) >> 0; +} + +/** + * @brief Returns the current value of the phaseNumber field in the VERSION_2 register. + * + * The VERSION_2 register will be read and the phaseNumber field's value will be returned. + * + * @return The current value of the phaseNumber field in the VERSION_2 register. + */ +__INLINE uint8_t nxmac_phase_number_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_VERSION_2_ADDR); + return ((localVal & ((uint32_t)0x0001C000)) >> 14); +} + +/** + * @brief Returns the current value of the releaseNumber field in the VERSION_2 register. + * + * The VERSION_2 register will be read and the releaseNumber field's value will be returned. + * + * @return The current value of the releaseNumber field in the VERSION_2 register. + */ +__INLINE uint8_t nxmac_release_number_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_VERSION_2_ADDR); + return ((localVal & ((uint32_t)0x00003F00)) >> 8); +} + +/** + * @brief Returns the current value of the ieRelease field in the VERSION_2 register. + * + * The VERSION_2 register will be read and the ieRelease field's value will be returned. + * + * @return The current value of the ieRelease field in the VERSION_2 register. + */ +__INLINE uint8_t nxmac_ie_release_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_VERSION_2_ADDR); + return ((localVal & ((uint32_t)0x00000080)) >> 7); +} + +/** + * @brief Returns the current value of the umVersion field in the VERSION_2 register. + * + * The VERSION_2 register will be read and the umVersion field's value will be returned. + * + * @return The current value of the umVersion field in the VERSION_2 register. + */ +__INLINE uint8_t nxmac_um_version_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_VERSION_2_ADDR); + return ((localVal & ((uint32_t)0x0000007F)) >> 0); +} + +/// @} + +/** + * @name BITMAP_CNT register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00            bitmapCnt   0x0
+ * 
+ * + * @{ + */ + +/// Address of the BITMAP_CNT register +#define NXMAC_BITMAP_CNT_ADDR 0xC000000C +/// Offset of the BITMAP_CNT register from the base address +#define NXMAC_BITMAP_CNT_OFFSET 0x0000000C +/// Index of the BITMAP_CNT register +#define NXMAC_BITMAP_CNT_INDEX 0x00000003 +/// Reset value of the BITMAP_CNT register +#define NXMAC_BITMAP_CNT_RESET 0x00000000 + +/** + * @brief Returns the current value of the BITMAP_CNT register. + * The BITMAP_CNT register will be read and its value returned. + * @return The current value of the BITMAP_CNT register. + */ +__INLINE uint32_t nxmac_bitmap_cnt_get(void) +{ + return REG_PL_RD(NXMAC_BITMAP_CNT_ADDR); +} + +// field definitions +/// BITMAP_CNT field mask +#define NXMAC_BITMAP_CNT_MASK ((uint32_t)0x0000FFFF) +/// BITMAP_CNT field LSB position +#define NXMAC_BITMAP_CNT_LSB 0 +/// BITMAP_CNT field width +#define NXMAC_BITMAP_CNT_WIDTH ((uint32_t)0x00000010) + +/// BITMAP_CNT field reset value +#define NXMAC_BITMAP_CNT_RST 0x0 + +/** + * @brief Returns the current value of the bitmapCnt field in the BITMAP_CNT register. + * + * The BITMAP_CNT register will be read and the bitmapCnt field's value will be returned. + * + * @return The current value of the bitmapCnt field in the BITMAP_CNT register. + */ +__INLINE uint16_t nxmac_bitmap_cnt_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_BITMAP_CNT_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +/// @} + +/** + * @name MAC_ADDR_LOW register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00           macAddrLow   0x0
+ * 
+ * + * @{ + */ + +/// Address of the MAC_ADDR_LOW register +#define NXMAC_MAC_ADDR_LOW_ADDR 0xC0000010 +/// Offset of the MAC_ADDR_LOW register from the base address +#define NXMAC_MAC_ADDR_LOW_OFFSET 0x00000010 +/// Index of the MAC_ADDR_LOW register +#define NXMAC_MAC_ADDR_LOW_INDEX 0x00000004 +/// Reset value of the MAC_ADDR_LOW register +#define NXMAC_MAC_ADDR_LOW_RESET 0x00000000 + +/** + * @brief Returns the current value of the MAC_ADDR_LOW register. + * The MAC_ADDR_LOW register will be read and its value returned. + * @return The current value of the MAC_ADDR_LOW register. + */ +__INLINE uint32_t nxmac_mac_addr_low_get(void) +{ + return REG_PL_RD(NXMAC_MAC_ADDR_LOW_ADDR); +} + +/** + * @brief Sets the MAC_ADDR_LOW register to a value. + * The MAC_ADDR_LOW register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_mac_addr_low_set(uint32_t value) +{ + REG_PL_WR(NXMAC_MAC_ADDR_LOW_ADDR, value); +} + +// field definitions +/// MAC_ADDR_LOW field mask +#define NXMAC_MAC_ADDR_LOW_MASK ((uint32_t)0xFFFFFFFF) +/// MAC_ADDR_LOW field LSB position +#define NXMAC_MAC_ADDR_LOW_LSB 0 +/// MAC_ADDR_LOW field width +#define NXMAC_MAC_ADDR_LOW_WIDTH ((uint32_t)0x00000020) + +/// MAC_ADDR_LOW field reset value +#define NXMAC_MAC_ADDR_LOW_RST 0x0 + +/** + * @brief Returns the current value of the macAddrLow field in the MAC_ADDR_LOW register. + * + * The MAC_ADDR_LOW register will be read and the macAddrLow field's value will be returned. + * + * @return The current value of the macAddrLow field in the MAC_ADDR_LOW register. + */ +__INLINE uint32_t nxmac_mac_addr_low_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MAC_ADDR_LOW_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the macAddrLow field of the MAC_ADDR_LOW register. + * + * The MAC_ADDR_LOW register will be read, modified to contain the new field value, and written. + * + * @param[in] macaddrlow - The value to set the field to. + */ +__INLINE void nxmac_mac_addr_low_setf(uint32_t macaddrlow) +{ + ASSERT_ERR((((uint32_t)macaddrlow << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(NXMAC_MAC_ADDR_LOW_ADDR, (uint32_t)macaddrlow << 0); +} + +/// @} + +/** + * @name MAC_ADDR_HI register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00          macAddrHigh   0x0
+ * 
+ * + * @{ + */ + +/// Address of the MAC_ADDR_HI register +#define NXMAC_MAC_ADDR_HI_ADDR 0xC0000014 +/// Offset of the MAC_ADDR_HI register from the base address +#define NXMAC_MAC_ADDR_HI_OFFSET 0x00000014 +/// Index of the MAC_ADDR_HI register +#define NXMAC_MAC_ADDR_HI_INDEX 0x00000005 +/// Reset value of the MAC_ADDR_HI register +#define NXMAC_MAC_ADDR_HI_RESET 0x00000000 + +/** + * @brief Returns the current value of the MAC_ADDR_HI register. + * The MAC_ADDR_HI register will be read and its value returned. + * @return The current value of the MAC_ADDR_HI register. + */ +__INLINE uint32_t nxmac_mac_addr_hi_get(void) +{ + return REG_PL_RD(NXMAC_MAC_ADDR_HI_ADDR); +} + +/** + * @brief Sets the MAC_ADDR_HI register to a value. + * The MAC_ADDR_HI register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_mac_addr_hi_set(uint32_t value) +{ + REG_PL_WR(NXMAC_MAC_ADDR_HI_ADDR, value); +} + +// field definitions +/// MAC_ADDR_HIGH field mask +#define NXMAC_MAC_ADDR_HIGH_MASK ((uint32_t)0x0000FFFF) +/// MAC_ADDR_HIGH field LSB position +#define NXMAC_MAC_ADDR_HIGH_LSB 0 +/// MAC_ADDR_HIGH field width +#define NXMAC_MAC_ADDR_HIGH_WIDTH ((uint32_t)0x00000010) + +/// MAC_ADDR_HIGH field reset value +#define NXMAC_MAC_ADDR_HIGH_RST 0x0 + +/** + * @brief Returns the current value of the macAddrHigh field in the MAC_ADDR_HI register. + * + * The MAC_ADDR_HI register will be read and the macAddrHigh field's value will be returned. + * + * @return The current value of the macAddrHigh field in the MAC_ADDR_HI register. + */ +__INLINE uint16_t nxmac_mac_addr_high_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MAC_ADDR_HI_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the macAddrHigh field of the MAC_ADDR_HI register. + * + * The MAC_ADDR_HI register will be read, modified to contain the new field value, and written. + * + * @param[in] macaddrhigh - The value to set the field to. + */ +__INLINE void nxmac_mac_addr_high_setf(uint16_t macaddrhigh) +{ + ASSERT_ERR((((uint32_t)macaddrhigh << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_PL_WR(NXMAC_MAC_ADDR_HI_ADDR, (uint32_t)macaddrhigh << 0); +} + +/// @} + +/** + * @name MAC_ADDR_LOW_MASK register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00       macAddrLowMask   0x0
+ * 
+ * + * @{ + */ + +/// Address of the MAC_ADDR_LOW_MASK register +#define NXMAC_MAC_ADDR_LOW_MASK_ADDR 0xC0000018 +/// Offset of the MAC_ADDR_LOW_MASK register from the base address +#define NXMAC_MAC_ADDR_LOW_MASK_OFFSET 0x00000018 +/// Index of the MAC_ADDR_LOW_MASK register +#define NXMAC_MAC_ADDR_LOW_MASK_INDEX 0x00000006 +/// Reset value of the MAC_ADDR_LOW_MASK register +#define NXMAC_MAC_ADDR_LOW_MASK_RESET 0x00000000 + +/** + * @brief Returns the current value of the MAC_ADDR_LOW_MASK register. + * The MAC_ADDR_LOW_MASK register will be read and its value returned. + * @return The current value of the MAC_ADDR_LOW_MASK register. + */ +__INLINE uint32_t nxmac_mac_addr_low_mask_get(void) +{ + return REG_PL_RD(NXMAC_MAC_ADDR_LOW_MASK_ADDR); +} + +/** + * @brief Sets the MAC_ADDR_LOW_MASK register to a value. + * The MAC_ADDR_LOW_MASK register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_mac_addr_low_mask_set(uint32_t value) +{ + REG_PL_WR(NXMAC_MAC_ADDR_LOW_MASK_ADDR, value); +} + +// field definitions +/// MAC_ADDR_LOW_MASK field mask +#define NXMAC_MAC_ADDR_LOW_MASK_MASK ((uint32_t)0xFFFFFFFF) +/// MAC_ADDR_LOW_MASK field LSB position +#define NXMAC_MAC_ADDR_LOW_MASK_LSB 0 +/// MAC_ADDR_LOW_MASK field width +#define NXMAC_MAC_ADDR_LOW_MASK_WIDTH ((uint32_t)0x00000020) + +/// MAC_ADDR_LOW_MASK field reset value +#define NXMAC_MAC_ADDR_LOW_MASK_RST 0x0 + +/** + * @brief Returns the current value of the macAddrLowMask field in the MAC_ADDR_LOW_MASK register. + * + * The MAC_ADDR_LOW_MASK register will be read and the macAddrLowMask field's value will be returned. + * + * @return The current value of the macAddrLowMask field in the MAC_ADDR_LOW_MASK register. + */ +__INLINE uint32_t nxmac_mac_addr_low_mask_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MAC_ADDR_LOW_MASK_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the macAddrLowMask field of the MAC_ADDR_LOW_MASK register. + * + * The MAC_ADDR_LOW_MASK register will be read, modified to contain the new field value, and written. + * + * @param[in] macaddrlowmask - The value to set the field to. + */ +__INLINE void nxmac_mac_addr_low_mask_setf(uint32_t macaddrlowmask) +{ + ASSERT_ERR((((uint32_t)macaddrlowmask << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(NXMAC_MAC_ADDR_LOW_MASK_ADDR, (uint32_t)macaddrlowmask << 0); +} + +/// @} + +/** + * @name MAC_ADDR_HI_MASK register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00      macAddrHighMask   0x0
+ * 
+ * + * @{ + */ + +/// Address of the MAC_ADDR_HI_MASK register +#define NXMAC_MAC_ADDR_HI_MASK_ADDR 0xC000001C +/// Offset of the MAC_ADDR_HI_MASK register from the base address +#define NXMAC_MAC_ADDR_HI_MASK_OFFSET 0x0000001C +/// Index of the MAC_ADDR_HI_MASK register +#define NXMAC_MAC_ADDR_HI_MASK_INDEX 0x00000007 +/// Reset value of the MAC_ADDR_HI_MASK register +#define NXMAC_MAC_ADDR_HI_MASK_RESET 0x00000000 + +/** + * @brief Returns the current value of the MAC_ADDR_HI_MASK register. + * The MAC_ADDR_HI_MASK register will be read and its value returned. + * @return The current value of the MAC_ADDR_HI_MASK register. + */ +__INLINE uint32_t nxmac_mac_addr_hi_mask_get(void) +{ + return REG_PL_RD(NXMAC_MAC_ADDR_HI_MASK_ADDR); +} + +/** + * @brief Sets the MAC_ADDR_HI_MASK register to a value. + * The MAC_ADDR_HI_MASK register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_mac_addr_hi_mask_set(uint32_t value) +{ + REG_PL_WR(NXMAC_MAC_ADDR_HI_MASK_ADDR, value); +} + +// field definitions +/// MAC_ADDR_HIGH_MASK field mask +#define NXMAC_MAC_ADDR_HIGH_MASK_MASK ((uint32_t)0x0000FFFF) +/// MAC_ADDR_HIGH_MASK field LSB position +#define NXMAC_MAC_ADDR_HIGH_MASK_LSB 0 +/// MAC_ADDR_HIGH_MASK field width +#define NXMAC_MAC_ADDR_HIGH_MASK_WIDTH ((uint32_t)0x00000010) + +/// MAC_ADDR_HIGH_MASK field reset value +#define NXMAC_MAC_ADDR_HIGH_MASK_RST 0x0 + +/** + * @brief Returns the current value of the macAddrHighMask field in the MAC_ADDR_HI_MASK register. + * + * The MAC_ADDR_HI_MASK register will be read and the macAddrHighMask field's value will be returned. + * + * @return The current value of the macAddrHighMask field in the MAC_ADDR_HI_MASK register. + */ +__INLINE uint16_t nxmac_mac_addr_high_mask_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MAC_ADDR_HI_MASK_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the macAddrHighMask field of the MAC_ADDR_HI_MASK register. + * + * The MAC_ADDR_HI_MASK register will be read, modified to contain the new field value, and written. + * + * @param[in] macaddrhighmask - The value to set the field to. + */ +__INLINE void nxmac_mac_addr_high_mask_setf(uint16_t macaddrhighmask) +{ + ASSERT_ERR((((uint32_t)macaddrhighmask << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_PL_WR(NXMAC_MAC_ADDR_HI_MASK_ADDR, (uint32_t)macaddrhighmask << 0); +} + +/// @} + +/** + * @name BSS_ID_LOW register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00             bssIDLow   0x0
+ * 
+ * + * @{ + */ + +/// Address of the BSS_ID_LOW register +#define NXMAC_BSS_ID_LOW_ADDR 0xC0000020 +/// Offset of the BSS_ID_LOW register from the base address +#define NXMAC_BSS_ID_LOW_OFFSET 0x00000020 +/// Index of the BSS_ID_LOW register +#define NXMAC_BSS_ID_LOW_INDEX 0x00000008 +/// Reset value of the BSS_ID_LOW register +#define NXMAC_BSS_ID_LOW_RESET 0x00000000 + +/** + * @brief Returns the current value of the BSS_ID_LOW register. + * The BSS_ID_LOW register will be read and its value returned. + * @return The current value of the BSS_ID_LOW register. + */ +__INLINE uint32_t nxmac_bss_id_low_get(void) +{ + return REG_PL_RD(NXMAC_BSS_ID_LOW_ADDR); +} + +/** + * @brief Sets the BSS_ID_LOW register to a value. + * The BSS_ID_LOW register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_bss_id_low_set(uint32_t value) +{ + REG_PL_WR(NXMAC_BSS_ID_LOW_ADDR, value); +} + +// field definitions +/// BSS_ID_LOW field mask +#define NXMAC_BSS_ID_LOW_MASK ((uint32_t)0xFFFFFFFF) +/// BSS_ID_LOW field LSB position +#define NXMAC_BSS_ID_LOW_LSB 0 +/// BSS_ID_LOW field width +#define NXMAC_BSS_ID_LOW_WIDTH ((uint32_t)0x00000020) + +/// BSS_ID_LOW field reset value +#define NXMAC_BSS_ID_LOW_RST 0x0 + +/** + * @brief Returns the current value of the bssIDLow field in the BSS_ID_LOW register. + * + * The BSS_ID_LOW register will be read and the bssIDLow field's value will be returned. + * + * @return The current value of the bssIDLow field in the BSS_ID_LOW register. + */ +__INLINE uint32_t nxmac_bss_id_low_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_BSS_ID_LOW_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the bssIDLow field of the BSS_ID_LOW register. + * + * The BSS_ID_LOW register will be read, modified to contain the new field value, and written. + * + * @param[in] bssidlow - The value to set the field to. + */ +__INLINE void nxmac_bss_id_low_setf(uint32_t bssidlow) +{ + ASSERT_ERR((((uint32_t)bssidlow << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(NXMAC_BSS_ID_LOW_ADDR, (uint32_t)bssidlow << 0); +} + +/// @} + +/** + * @name BSS_ID_HI register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00            bssIDHigh   0x0
+ * 
+ * + * @{ + */ + +/// Address of the BSS_ID_HI register +#define NXMAC_BSS_ID_HI_ADDR 0xC0000024 +/// Offset of the BSS_ID_HI register from the base address +#define NXMAC_BSS_ID_HI_OFFSET 0x00000024 +/// Index of the BSS_ID_HI register +#define NXMAC_BSS_ID_HI_INDEX 0x00000009 +/// Reset value of the BSS_ID_HI register +#define NXMAC_BSS_ID_HI_RESET 0x00000000 + +/** + * @brief Returns the current value of the BSS_ID_HI register. + * The BSS_ID_HI register will be read and its value returned. + * @return The current value of the BSS_ID_HI register. + */ +__INLINE uint32_t nxmac_bss_id_hi_get(void) +{ + return REG_PL_RD(NXMAC_BSS_ID_HI_ADDR); +} + +/** + * @brief Sets the BSS_ID_HI register to a value. + * The BSS_ID_HI register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_bss_id_hi_set(uint32_t value) +{ + REG_PL_WR(NXMAC_BSS_ID_HI_ADDR, value); +} + +// field definitions +/// BSS_ID_HIGH field mask +#define NXMAC_BSS_ID_HIGH_MASK ((uint32_t)0x0000FFFF) +/// BSS_ID_HIGH field LSB position +#define NXMAC_BSS_ID_HIGH_LSB 0 +/// BSS_ID_HIGH field width +#define NXMAC_BSS_ID_HIGH_WIDTH ((uint32_t)0x00000010) + +/// BSS_ID_HIGH field reset value +#define NXMAC_BSS_ID_HIGH_RST 0x0 + +/** + * @brief Returns the current value of the bssIDHigh field in the BSS_ID_HI register. + * + * The BSS_ID_HI register will be read and the bssIDHigh field's value will be returned. + * + * @return The current value of the bssIDHigh field in the BSS_ID_HI register. + */ +__INLINE uint16_t nxmac_bss_id_high_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_BSS_ID_HI_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the bssIDHigh field of the BSS_ID_HI register. + * + * The BSS_ID_HI register will be read, modified to contain the new field value, and written. + * + * @param[in] bssidhigh - The value to set the field to. + */ +__INLINE void nxmac_bss_id_high_setf(uint16_t bssidhigh) +{ + ASSERT_ERR((((uint32_t)bssidhigh << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_PL_WR(NXMAC_BSS_ID_HI_ADDR, (uint32_t)bssidhigh << 0); +} + +/// @} + +/** + * @name BSS_ID_LOW_MASK register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00         bssIDLowMask   0x0
+ * 
+ * + * @{ + */ + +/// Address of the BSS_ID_LOW_MASK register +#define NXMAC_BSS_ID_LOW_MASK_ADDR 0xC0000028 +/// Offset of the BSS_ID_LOW_MASK register from the base address +#define NXMAC_BSS_ID_LOW_MASK_OFFSET 0x00000028 +/// Index of the BSS_ID_LOW_MASK register +#define NXMAC_BSS_ID_LOW_MASK_INDEX 0x0000000A +/// Reset value of the BSS_ID_LOW_MASK register +#define NXMAC_BSS_ID_LOW_MASK_RESET 0x00000000 + +/** + * @brief Returns the current value of the BSS_ID_LOW_MASK register. + * The BSS_ID_LOW_MASK register will be read and its value returned. + * @return The current value of the BSS_ID_LOW_MASK register. + */ +__INLINE uint32_t nxmac_bss_id_low_mask_get(void) +{ + return REG_PL_RD(NXMAC_BSS_ID_LOW_MASK_ADDR); +} + +/** + * @brief Sets the BSS_ID_LOW_MASK register to a value. + * The BSS_ID_LOW_MASK register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_bss_id_low_mask_set(uint32_t value) +{ + REG_PL_WR(NXMAC_BSS_ID_LOW_MASK_ADDR, value); +} + +// field definitions +/// BSS_ID_LOW_MASK field mask +#define NXMAC_BSS_ID_LOW_MASK_MASK ((uint32_t)0xFFFFFFFF) +/// BSS_ID_LOW_MASK field LSB position +#define NXMAC_BSS_ID_LOW_MASK_LSB 0 +/// BSS_ID_LOW_MASK field width +#define NXMAC_BSS_ID_LOW_MASK_WIDTH ((uint32_t)0x00000020) + +/// BSS_ID_LOW_MASK field reset value +#define NXMAC_BSS_ID_LOW_MASK_RST 0x0 + +/** + * @brief Returns the current value of the bssIDLowMask field in the BSS_ID_LOW_MASK register. + * + * The BSS_ID_LOW_MASK register will be read and the bssIDLowMask field's value will be returned. + * + * @return The current value of the bssIDLowMask field in the BSS_ID_LOW_MASK register. + */ +__INLINE uint32_t nxmac_bss_id_low_mask_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_BSS_ID_LOW_MASK_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the bssIDLowMask field of the BSS_ID_LOW_MASK register. + * + * The BSS_ID_LOW_MASK register will be read, modified to contain the new field value, and written. + * + * @param[in] bssidlowmask - The value to set the field to. + */ +__INLINE void nxmac_bss_id_low_mask_setf(uint32_t bssidlowmask) +{ + ASSERT_ERR((((uint32_t)bssidlowmask << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(NXMAC_BSS_ID_LOW_MASK_ADDR, (uint32_t)bssidlowmask << 0); +} + +/// @} + +/** + * @name BSS_ID_HI_MASK register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00        bssIDHighMask   0x0
+ * 
+ * + * @{ + */ + +/// Address of the BSS_ID_HI_MASK register +#define NXMAC_BSS_ID_HI_MASK_ADDR 0xC000002C +/// Offset of the BSS_ID_HI_MASK register from the base address +#define NXMAC_BSS_ID_HI_MASK_OFFSET 0x0000002C +/// Index of the BSS_ID_HI_MASK register +#define NXMAC_BSS_ID_HI_MASK_INDEX 0x0000000B +/// Reset value of the BSS_ID_HI_MASK register +#define NXMAC_BSS_ID_HI_MASK_RESET 0x00000000 + +/** + * @brief Returns the current value of the BSS_ID_HI_MASK register. + * The BSS_ID_HI_MASK register will be read and its value returned. + * @return The current value of the BSS_ID_HI_MASK register. + */ +__INLINE uint32_t nxmac_bss_id_hi_mask_get(void) +{ + return REG_PL_RD(NXMAC_BSS_ID_HI_MASK_ADDR); +} + +/** + * @brief Sets the BSS_ID_HI_MASK register to a value. + * The BSS_ID_HI_MASK register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_bss_id_hi_mask_set(uint32_t value) +{ + REG_PL_WR(NXMAC_BSS_ID_HI_MASK_ADDR, value); +} + +// field definitions +/// BSS_ID_HIGH_MASK field mask +#define NXMAC_BSS_ID_HIGH_MASK_MASK ((uint32_t)0x0000FFFF) +/// BSS_ID_HIGH_MASK field LSB position +#define NXMAC_BSS_ID_HIGH_MASK_LSB 0 +/// BSS_ID_HIGH_MASK field width +#define NXMAC_BSS_ID_HIGH_MASK_WIDTH ((uint32_t)0x00000010) + +/// BSS_ID_HIGH_MASK field reset value +#define NXMAC_BSS_ID_HIGH_MASK_RST 0x0 + +/** + * @brief Returns the current value of the bssIDHighMask field in the BSS_ID_HI_MASK register. + * + * The BSS_ID_HI_MASK register will be read and the bssIDHighMask field's value will be returned. + * + * @return The current value of the bssIDHighMask field in the BSS_ID_HI_MASK register. + */ +__INLINE uint16_t nxmac_bss_id_high_mask_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_BSS_ID_HI_MASK_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the bssIDHighMask field of the BSS_ID_HI_MASK register. + * + * The BSS_ID_HI_MASK register will be read, modified to contain the new field value, and written. + * + * @param[in] bssidhighmask - The value to set the field to. + */ +__INLINE void nxmac_bss_id_high_mask_setf(uint16_t bssidhighmask) +{ + ASSERT_ERR((((uint32_t)bssidhighmask << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_PL_WR(NXMAC_BSS_ID_HI_MASK_ADDR, (uint32_t)bssidhighmask << 0); +} + +/// @} + +/** + * @name STATE_CNTRL register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  07:04            nextState   0x0
+ *  03:00         currentState   0x0
+ * 
+ * + * @{ + */ + +/// Address of the STATE_CNTRL register +#define NXMAC_STATE_CNTRL_ADDR 0xC0000038 +/// Offset of the STATE_CNTRL register from the base address +#define NXMAC_STATE_CNTRL_OFFSET 0x00000038 +/// Index of the STATE_CNTRL register +#define NXMAC_STATE_CNTRL_INDEX 0x0000000E +/// Reset value of the STATE_CNTRL register +#define NXMAC_STATE_CNTRL_RESET 0x00000000 + +/** + * @brief Returns the current value of the STATE_CNTRL register. + * The STATE_CNTRL register will be read and its value returned. + * @return The current value of the STATE_CNTRL register. + */ +__INLINE uint32_t nxmac_state_cntrl_get(void) +{ + return REG_PL_RD(NXMAC_STATE_CNTRL_ADDR); +} + +/** + * @brief Sets the STATE_CNTRL register to a value. + * The STATE_CNTRL register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_state_cntrl_set(uint32_t value) +{ + REG_PL_WR(NXMAC_STATE_CNTRL_ADDR, value); +} + +// field definitions +/// NEXT_STATE field mask +#define NXMAC_NEXT_STATE_MASK ((uint32_t)0x000000F0) +/// NEXT_STATE field LSB position +#define NXMAC_NEXT_STATE_LSB 4 +/// NEXT_STATE field width +#define NXMAC_NEXT_STATE_WIDTH ((uint32_t)0x00000004) +/// CURRENT_STATE field mask +#define NXMAC_CURRENT_STATE_MASK ((uint32_t)0x0000000F) +/// CURRENT_STATE field LSB position +#define NXMAC_CURRENT_STATE_LSB 0 +/// CURRENT_STATE field width +#define NXMAC_CURRENT_STATE_WIDTH ((uint32_t)0x00000004) + +/// NEXT_STATE field reset value +#define NXMAC_NEXT_STATE_RST 0x0 +/// CURRENT_STATE field reset value +#define NXMAC_CURRENT_STATE_RST 0x0 + +/** + * @brief Unpacks STATE_CNTRL's fields from current value of the STATE_CNTRL register. + * + * Reads the STATE_CNTRL register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] nextstate - Will be populated with the current value of this field from the register. + * @param[out] currentstate - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_state_cntrl_unpack(uint8_t *nextstate, uint8_t *currentstate) +{ + uint32_t localVal = REG_PL_RD(NXMAC_STATE_CNTRL_ADDR); + + *nextstate = (localVal & ((uint32_t)0x000000F0)) >> 4; + *currentstate = (localVal & ((uint32_t)0x0000000F)) >> 0; +} + +/** + * @brief Returns the current value of the nextState field in the STATE_CNTRL register. + * + * The STATE_CNTRL register will be read and the nextState field's value will be returned. + * + * @return The current value of the nextState field in the STATE_CNTRL register. + */ +__INLINE uint8_t nxmac_next_state_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_STATE_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x000000F0)) >> 4); +} + +/** + * @brief Sets the nextState field of the STATE_CNTRL register. + * + * The STATE_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] nextstate - The value to set the field to. + */ +__INLINE void nxmac_next_state_setf(uint8_t nextstate) +{ + ASSERT_ERR((((uint32_t)nextstate << 4) & ~((uint32_t)0x000000F0)) == 0); + REG_PL_WR(NXMAC_STATE_CNTRL_ADDR, (uint32_t)nextstate << 4); +} + +/** + * @brief Returns the current value of the currentState field in the STATE_CNTRL register. + * + * The STATE_CNTRL register will be read and the currentState field's value will be returned. + * + * @return The current value of the currentState field in the STATE_CNTRL register. + */ +__INLINE uint8_t nxmac_current_state_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_STATE_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x0000000F)) >> 0); +} + +/// @} + +/** + * @name SCAN_CNTRL register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00           probeDelay   0x0
+ * 
+ * + * @{ + */ + +/// Address of the SCAN_CNTRL register +#define NXMAC_SCAN_CNTRL_ADDR 0xC000003C +/// Offset of the SCAN_CNTRL register from the base address +#define NXMAC_SCAN_CNTRL_OFFSET 0x0000003C +/// Index of the SCAN_CNTRL register +#define NXMAC_SCAN_CNTRL_INDEX 0x0000000F +/// Reset value of the SCAN_CNTRL register +#define NXMAC_SCAN_CNTRL_RESET 0x00000000 + +/** + * @brief Returns the current value of the SCAN_CNTRL register. + * The SCAN_CNTRL register will be read and its value returned. + * @return The current value of the SCAN_CNTRL register. + */ +__INLINE uint32_t nxmac_scan_cntrl_get(void) +{ + return REG_PL_RD(NXMAC_SCAN_CNTRL_ADDR); +} + +/** + * @brief Sets the SCAN_CNTRL register to a value. + * The SCAN_CNTRL register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_scan_cntrl_set(uint32_t value) +{ + REG_PL_WR(NXMAC_SCAN_CNTRL_ADDR, value); +} + +// field definitions +/// PROBE_DELAY field mask +#define NXMAC_PROBE_DELAY_MASK ((uint32_t)0x0000FFFF) +/// PROBE_DELAY field LSB position +#define NXMAC_PROBE_DELAY_LSB 0 +/// PROBE_DELAY field width +#define NXMAC_PROBE_DELAY_WIDTH ((uint32_t)0x00000010) + +/// PROBE_DELAY field reset value +#define NXMAC_PROBE_DELAY_RST 0x0 + +/** + * @brief Returns the current value of the probeDelay field in the SCAN_CNTRL register. + * + * The SCAN_CNTRL register will be read and the probeDelay field's value will be returned. + * + * @return The current value of the probeDelay field in the SCAN_CNTRL register. + */ +__INLINE uint16_t nxmac_probe_delay_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SCAN_CNTRL_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the probeDelay field of the SCAN_CNTRL register. + * + * The SCAN_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] probedelay - The value to set the field to. + */ +__INLINE void nxmac_probe_delay_setf(uint16_t probedelay) +{ + ASSERT_ERR((((uint32_t)probedelay << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_PL_WR(NXMAC_SCAN_CNTRL_ADDR, (uint32_t)probedelay << 0); +} + +/// @} + +/** + * @name DOZE_CNTRL_1 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:17                atimW   0x0
+ *     16           wakeupDTIM   0
+ *  15:00       listenInterval   0x0
+ * 
+ * + * @{ + */ + +/// Address of the DOZE_CNTRL_1 register +#define NXMAC_DOZE_CNTRL_1_ADDR 0xC0000044 +/// Offset of the DOZE_CNTRL_1 register from the base address +#define NXMAC_DOZE_CNTRL_1_OFFSET 0x00000044 +/// Index of the DOZE_CNTRL_1 register +#define NXMAC_DOZE_CNTRL_1_INDEX 0x00000011 +/// Reset value of the DOZE_CNTRL_1 register +#define NXMAC_DOZE_CNTRL_1_RESET 0x00000000 + +/** + * @brief Returns the current value of the DOZE_CNTRL_1 register. + * The DOZE_CNTRL_1 register will be read and its value returned. + * @return The current value of the DOZE_CNTRL_1 register. + */ +__INLINE uint32_t nxmac_doze_cntrl_1_get(void) +{ + return REG_PL_RD(NXMAC_DOZE_CNTRL_1_ADDR); +} + +/** + * @brief Sets the DOZE_CNTRL_1 register to a value. + * The DOZE_CNTRL_1 register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_doze_cntrl_1_set(uint32_t value) +{ + REG_PL_WR(NXMAC_DOZE_CNTRL_1_ADDR, value); +} + +// field definitions +/// ATIM_W field mask +#define NXMAC_ATIM_W_MASK ((uint32_t)0xFFFE0000) +/// ATIM_W field LSB position +#define NXMAC_ATIM_W_LSB 17 +/// ATIM_W field width +#define NXMAC_ATIM_W_WIDTH ((uint32_t)0x0000000F) +/// WAKEUP_DTIM field bit +#define NXMAC_WAKEUP_DTIM_BIT ((uint32_t)0x00010000) +/// WAKEUP_DTIM field position +#define NXMAC_WAKEUP_DTIM_POS 16 +/// LISTEN_INTERVAL field mask +#define NXMAC_LISTEN_INTERVAL_MASK ((uint32_t)0x0000FFFF) +/// LISTEN_INTERVAL field LSB position +#define NXMAC_LISTEN_INTERVAL_LSB 0 +/// LISTEN_INTERVAL field width +#define NXMAC_LISTEN_INTERVAL_WIDTH ((uint32_t)0x00000010) + +/// ATIM_W field reset value +#define NXMAC_ATIM_W_RST 0x0 +/// WAKEUP_DTIM field reset value +#define NXMAC_WAKEUP_DTIM_RST 0x0 +/// LISTEN_INTERVAL field reset value +#define NXMAC_LISTEN_INTERVAL_RST 0x0 + +/** + * @brief Constructs a value for the DOZE_CNTRL_1 register given values for its fields + * and writes the value to the register. + * + * @param[in] atimw - The value to use for the atimW field. + * @param[in] wakeupdtim - The value to use for the wakeupDTIM field. + * @param[in] listeninterval - The value to use for the listenInterval field. + */ +__INLINE void nxmac_doze_cntrl_1_pack(uint16_t atimw, uint8_t wakeupdtim, uint16_t listeninterval) +{ + ASSERT_ERR((((uint32_t)atimw << 17) & ~((uint32_t)0xFFFE0000)) == 0); + ASSERT_ERR((((uint32_t)wakeupdtim << 16) & ~((uint32_t)0x00010000)) == 0); + ASSERT_ERR((((uint32_t)listeninterval << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_PL_WR(NXMAC_DOZE_CNTRL_1_ADDR, ((uint32_t)atimw << 17) | ((uint32_t)wakeupdtim << 16) | ((uint32_t)listeninterval << 0)); +} + +/** + * @brief Unpacks DOZE_CNTRL_1's fields from current value of the DOZE_CNTRL_1 register. + * + * Reads the DOZE_CNTRL_1 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] atimw - Will be populated with the current value of this field from the register. + * @param[out] wakeupdtim - Will be populated with the current value of this field from the register. + * @param[out] listeninterval - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_doze_cntrl_1_unpack(uint16_t *atimw, uint8_t *wakeupdtim, uint16_t *listeninterval) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DOZE_CNTRL_1_ADDR); + + *atimw = (localVal & ((uint32_t)0xFFFE0000)) >> 17; + *wakeupdtim = (localVal & ((uint32_t)0x00010000)) >> 16; + *listeninterval = (localVal & ((uint32_t)0x0000FFFF)) >> 0; +} + +/** + * @brief Returns the current value of the atimW field in the DOZE_CNTRL_1 register. + * + * The DOZE_CNTRL_1 register will be read and the atimW field's value will be returned. + * + * @return The current value of the atimW field in the DOZE_CNTRL_1 register. + */ +__INLINE uint16_t nxmac_atim_w_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DOZE_CNTRL_1_ADDR); + return ((localVal & ((uint32_t)0xFFFE0000)) >> 17); +} + +/** + * @brief Sets the atimW field of the DOZE_CNTRL_1 register. + * + * The DOZE_CNTRL_1 register will be read, modified to contain the new field value, and written. + * + * @param[in] atimw - The value to set the field to. + */ +__INLINE void nxmac_atim_w_setf(uint16_t atimw) +{ + ASSERT_ERR((((uint32_t)atimw << 17) & ~((uint32_t)0xFFFE0000)) == 0); + REG_PL_WR(NXMAC_DOZE_CNTRL_1_ADDR, (REG_PL_RD(NXMAC_DOZE_CNTRL_1_ADDR) & ~((uint32_t)0xFFFE0000)) | ((uint32_t)atimw << 17)); +} + +/** + * @brief Returns the current value of the wakeupDTIM field in the DOZE_CNTRL_1 register. + * + * The DOZE_CNTRL_1 register will be read and the wakeupDTIM field's value will be returned. + * + * @return The current value of the wakeupDTIM field in the DOZE_CNTRL_1 register. + */ +__INLINE uint8_t nxmac_wakeup_dtim_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DOZE_CNTRL_1_ADDR); + return ((localVal & ((uint32_t)0x00010000)) >> 16); +} + +/** + * @brief Sets the wakeupDTIM field of the DOZE_CNTRL_1 register. + * + * The DOZE_CNTRL_1 register will be read, modified to contain the new field value, and written. + * + * @param[in] wakeupdtim - The value to set the field to. + */ +__INLINE void nxmac_wakeup_dtim_setf(uint8_t wakeupdtim) +{ + ASSERT_ERR((((uint32_t)wakeupdtim << 16) & ~((uint32_t)0x00010000)) == 0); + REG_PL_WR(NXMAC_DOZE_CNTRL_1_ADDR, (REG_PL_RD(NXMAC_DOZE_CNTRL_1_ADDR) & ~((uint32_t)0x00010000)) | ((uint32_t)wakeupdtim << 16)); +} + +/** + * @brief Returns the current value of the listenInterval field in the DOZE_CNTRL_1 register. + * + * The DOZE_CNTRL_1 register will be read and the listenInterval field's value will be returned. + * + * @return The current value of the listenInterval field in the DOZE_CNTRL_1 register. + */ +__INLINE uint16_t nxmac_listen_interval_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DOZE_CNTRL_1_ADDR); + return ((localVal & ((uint32_t)0x0000FFFF)) >> 0); +} + +/** + * @brief Sets the listenInterval field of the DOZE_CNTRL_1 register. + * + * The DOZE_CNTRL_1 register will be read, modified to contain the new field value, and written. + * + * @param[in] listeninterval - The value to set the field to. + */ +__INLINE void nxmac_listen_interval_setf(uint16_t listeninterval) +{ + ASSERT_ERR((((uint32_t)listeninterval << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_PL_WR(NXMAC_DOZE_CNTRL_1_ADDR, (REG_PL_RD(NXMAC_DOZE_CNTRL_1_ADDR) & ~((uint32_t)0x0000FFFF)) | ((uint32_t)listeninterval << 0)); +} + +/// @} + +/** + * @name MAC_CNTRL_1 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     26             rxRIFSEn   0
+ *     25        tsfMgtDisable   0
+ *     24       tsfUpdatedBySW   0
+ *  16:14             abgnMode   0x3
+ *     13       keyStoRAMReset   0
+ *     12        mibTableReset   0
+ *     11   rateControllerMPIF   1
+ *     10        disableBAResp   0
+ *     09       disableCTSResp   0
+ *     08       disableACKResp   0
+ *     07      activeClkGating   1
+ *     06    enableLPClkSwitch   0
+ *     05         lpClk32786Hz   0
+ *     03             cfpAware   0
+ *     02               pwrMgt   0
+ *     01                   ap   0
+ *     00              bssType   1
+ * 
+ * + * @{ + */ + +/// Address of the MAC_CNTRL_1 register +#define NXMAC_MAC_CNTRL_1_ADDR 0xC000004C +/// Offset of the MAC_CNTRL_1 register from the base address +#define NXMAC_MAC_CNTRL_1_OFFSET 0x0000004C +/// Index of the MAC_CNTRL_1 register +#define NXMAC_MAC_CNTRL_1_INDEX 0x00000013 +/// Reset value of the MAC_CNTRL_1 register +#define NXMAC_MAC_CNTRL_1_RESET 0x0000C881 + +/** + * @brief Returns the current value of the MAC_CNTRL_1 register. + * The MAC_CNTRL_1 register will be read and its value returned. + * @return The current value of the MAC_CNTRL_1 register. + */ +__INLINE uint32_t nxmac_mac_cntrl_1_get(void) +{ + return REG_PL_RD(NXMAC_MAC_CNTRL_1_ADDR); +} + +/** + * @brief Sets the MAC_CNTRL_1 register to a value. + * The MAC_CNTRL_1 register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_mac_cntrl_1_set(uint32_t value) +{ + REG_PL_WR(NXMAC_MAC_CNTRL_1_ADDR, value); +} + +// field definitions +/// RX_RIFS_EN field bit +#define NXMAC_RX_RIFS_EN_BIT ((uint32_t)0x04000000) +/// RX_RIFS_EN field position +#define NXMAC_RX_RIFS_EN_POS 26 +/// TSF_MGT_DISABLE field bit +#define NXMAC_TSF_MGT_DISABLE_BIT ((uint32_t)0x02000000) +/// TSF_MGT_DISABLE field position +#define NXMAC_TSF_MGT_DISABLE_POS 25 +/// TSF_UPDATED_BY_SW field bit +#define NXMAC_TSF_UPDATED_BY_SW_BIT ((uint32_t)0x01000000) +/// TSF_UPDATED_BY_SW field position +#define NXMAC_TSF_UPDATED_BY_SW_POS 24 +/// ABGN_MODE field mask +#define NXMAC_ABGN_MODE_MASK ((uint32_t)0x0001C000) +/// ABGN_MODE field LSB position +#define NXMAC_ABGN_MODE_LSB 14 +/// ABGN_MODE field width +#define NXMAC_ABGN_MODE_WIDTH ((uint32_t)0x00000003) +/// KEY_STO_RAM_RESET field bit +#define NXMAC_KEY_STO_RAM_RESET_BIT ((uint32_t)0x00002000) +/// KEY_STO_RAM_RESET field position +#define NXMAC_KEY_STO_RAM_RESET_POS 13 +/// MIB_TABLE_RESET field bit +#define NXMAC_MIB_TABLE_RESET_BIT ((uint32_t)0x00001000) +/// MIB_TABLE_RESET field position +#define NXMAC_MIB_TABLE_RESET_POS 12 +/// RATE_CONTROLLER_MPIF field bit +#define NXMAC_RATE_CONTROLLER_MPIF_BIT ((uint32_t)0x00000800) +/// RATE_CONTROLLER_MPIF field position +#define NXMAC_RATE_CONTROLLER_MPIF_POS 11 +/// DISABLE_BA_RESP field bit +#define NXMAC_DISABLE_BA_RESP_BIT ((uint32_t)0x00000400) +/// DISABLE_BA_RESP field position +#define NXMAC_DISABLE_BA_RESP_POS 10 +/// DISABLE_CTS_RESP field bit +#define NXMAC_DISABLE_CTS_RESP_BIT ((uint32_t)0x00000200) +/// DISABLE_CTS_RESP field position +#define NXMAC_DISABLE_CTS_RESP_POS 9 +/// DISABLE_ACK_RESP field bit +#define NXMAC_DISABLE_ACK_RESP_BIT ((uint32_t)0x00000100) +/// DISABLE_ACK_RESP field position +#define NXMAC_DISABLE_ACK_RESP_POS 8 +/// ACTIVE_CLK_GATING field bit +#define NXMAC_ACTIVE_CLK_GATING_BIT ((uint32_t)0x00000080) +/// ACTIVE_CLK_GATING field position +#define NXMAC_ACTIVE_CLK_GATING_POS 7 +/// ENABLE_LP_CLK_SWITCH field bit +#define NXMAC_ENABLE_LP_CLK_SWITCH_BIT ((uint32_t)0x00000040) +/// ENABLE_LP_CLK_SWITCH field position +#define NXMAC_ENABLE_LP_CLK_SWITCH_POS 6 +/// LP_CLK_32786_HZ field bit +#define NXMAC_LP_CLK_32786_HZ_BIT ((uint32_t)0x00000020) +/// LP_CLK_32786_HZ field position +#define NXMAC_LP_CLK_32786_HZ_POS 5 +/// CFP_AWARE field bit +#define NXMAC_CFP_AWARE_BIT ((uint32_t)0x00000008) +/// CFP_AWARE field position +#define NXMAC_CFP_AWARE_POS 3 +/// PWR_MGT field bit +#define NXMAC_PWR_MGT_BIT ((uint32_t)0x00000004) +/// PWR_MGT field position +#define NXMAC_PWR_MGT_POS 2 +/// AP field bit +#define NXMAC_AP_BIT ((uint32_t)0x00000002) +/// AP field position +#define NXMAC_AP_POS 1 +/// BSS_TYPE field bit +#define NXMAC_BSS_TYPE_BIT ((uint32_t)0x00000001) +/// BSS_TYPE field position +#define NXMAC_BSS_TYPE_POS 0 + +/// RX_RIFS_EN field reset value +#define NXMAC_RX_RIFS_EN_RST 0x0 +/// TSF_MGT_DISABLE field reset value +#define NXMAC_TSF_MGT_DISABLE_RST 0x0 +/// TSF_UPDATED_BY_SW field reset value +#define NXMAC_TSF_UPDATED_BY_SW_RST 0x0 +/// ABGN_MODE field reset value +#define NXMAC_ABGN_MODE_RST 0x3 +/// KEY_STO_RAM_RESET field reset value +#define NXMAC_KEY_STO_RAM_RESET_RST 0x0 +/// MIB_TABLE_RESET field reset value +#define NXMAC_MIB_TABLE_RESET_RST 0x0 +/// RATE_CONTROLLER_MPIF field reset value +#define NXMAC_RATE_CONTROLLER_MPIF_RST 0x1 +/// DISABLE_BA_RESP field reset value +#define NXMAC_DISABLE_BA_RESP_RST 0x0 +/// DISABLE_CTS_RESP field reset value +#define NXMAC_DISABLE_CTS_RESP_RST 0x0 +/// DISABLE_ACK_RESP field reset value +#define NXMAC_DISABLE_ACK_RESP_RST 0x0 +/// ACTIVE_CLK_GATING field reset value +#define NXMAC_ACTIVE_CLK_GATING_RST 0x1 +/// ENABLE_LP_CLK_SWITCH field reset value +#define NXMAC_ENABLE_LP_CLK_SWITCH_RST 0x0 +/// LP_CLK_32786_HZ field reset value +#define NXMAC_LP_CLK_32786_HZ_RST 0x0 +/// CFP_AWARE field reset value +#define NXMAC_CFP_AWARE_RST 0x0 +/// PWR_MGT field reset value +#define NXMAC_PWR_MGT_RST 0x0 +/// AP field reset value +#define NXMAC_AP_RST 0x0 +/// BSS_TYPE field reset value +#define NXMAC_BSS_TYPE_RST 0x1 + +/** + * @brief Constructs a value for the MAC_CNTRL_1 register given values for its fields + * and writes the value to the register. + * + * @param[in] rxrifsen - The value to use for the rxRIFSEn field. + * @param[in] tsfmgtdisable - The value to use for the tsfMgtDisable field. + * @param[in] tsfupdatedbysw - The value to use for the tsfUpdatedBySW field. + * @param[in] abgnmode - The value to use for the abgnMode field. + * @param[in] keystoramreset - The value to use for the keyStoRAMReset field. + * @param[in] mibtablereset - The value to use for the mibTableReset field. + * @param[in] ratecontrollermpif - The value to use for the rateControllerMPIF field. + * @param[in] disablebaresp - The value to use for the disableBAResp field. + * @param[in] disablectsresp - The value to use for the disableCTSResp field. + * @param[in] disableackresp - The value to use for the disableACKResp field. + * @param[in] activeclkgating - The value to use for the activeClkGating field. + * @param[in] enablelpclkswitch - The value to use for the enableLPClkSwitch field. + * @param[in] lpclk32786hz - The value to use for the lpClk32786Hz field. + * @param[in] cfpaware - The value to use for the cfpAware field. + * @param[in] pwrmgt - The value to use for the pwrMgt field. + * @param[in] ap - The value to use for the ap field. + * @param[in] bsstype - The value to use for the bssType field. + */ +__INLINE void nxmac_mac_cntrl_1_pack(uint8_t rxrifsen, uint8_t tsfmgtdisable, uint8_t tsfupdatedbysw, uint8_t abgnmode, uint8_t keystoramreset, uint8_t mibtablereset, uint8_t ratecontrollermpif, uint8_t disablebaresp, uint8_t disablectsresp, uint8_t disableackresp, uint8_t activeclkgating, uint8_t enablelpclkswitch, uint8_t lpclk32786hz, uint8_t cfpaware, uint8_t pwrmgt, uint8_t ap, uint8_t bsstype) +{ + ASSERT_ERR((((uint32_t)rxrifsen << 26) & ~((uint32_t)0x04000000)) == 0); + ASSERT_ERR((((uint32_t)tsfmgtdisable << 25) & ~((uint32_t)0x02000000)) == 0); + ASSERT_ERR((((uint32_t)tsfupdatedbysw << 24) & ~((uint32_t)0x01000000)) == 0); + ASSERT_ERR((((uint32_t)abgnmode << 14) & ~((uint32_t)0x0001C000)) == 0); + ASSERT_ERR((((uint32_t)keystoramreset << 13) & ~((uint32_t)0x00002000)) == 0); + ASSERT_ERR((((uint32_t)mibtablereset << 12) & ~((uint32_t)0x00001000)) == 0); + ASSERT_ERR((((uint32_t)ratecontrollermpif << 11) & ~((uint32_t)0x00000800)) == 0); + ASSERT_ERR((((uint32_t)disablebaresp << 10) & ~((uint32_t)0x00000400)) == 0); + ASSERT_ERR((((uint32_t)disablectsresp << 9) & ~((uint32_t)0x00000200)) == 0); + ASSERT_ERR((((uint32_t)disableackresp << 8) & ~((uint32_t)0x00000100)) == 0); + ASSERT_ERR((((uint32_t)activeclkgating << 7) & ~((uint32_t)0x00000080)) == 0); + ASSERT_ERR((((uint32_t)enablelpclkswitch << 6) & ~((uint32_t)0x00000040)) == 0); + ASSERT_ERR((((uint32_t)lpclk32786hz << 5) & ~((uint32_t)0x00000020)) == 0); + ASSERT_ERR((((uint32_t)cfpaware << 3) & ~((uint32_t)0x00000008)) == 0); + ASSERT_ERR((((uint32_t)pwrmgt << 2) & ~((uint32_t)0x00000004)) == 0); + ASSERT_ERR((((uint32_t)ap << 1) & ~((uint32_t)0x00000002)) == 0); + ASSERT_ERR((((uint32_t)bsstype << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_MAC_CNTRL_1_ADDR, ((uint32_t)rxrifsen << 26) | ((uint32_t)tsfmgtdisable << 25) | ((uint32_t)tsfupdatedbysw << 24) | ((uint32_t)abgnmode << 14) | ((uint32_t)keystoramreset << 13) | ((uint32_t)mibtablereset << 12) | ((uint32_t)ratecontrollermpif << 11) | ((uint32_t)disablebaresp << 10) | ((uint32_t)disablectsresp << 9) | ((uint32_t)disableackresp << 8) | ((uint32_t)activeclkgating << 7) | ((uint32_t)enablelpclkswitch << 6) | ((uint32_t)lpclk32786hz << 5) | ((uint32_t)cfpaware << 3) | ((uint32_t)pwrmgt << 2) | ((uint32_t)ap << 1) | ((uint32_t)bsstype << 0)); +} + +/** + * @brief Unpacks MAC_CNTRL_1's fields from current value of the MAC_CNTRL_1 register. + * + * Reads the MAC_CNTRL_1 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] rxrifsen - Will be populated with the current value of this field from the register. + * @param[out] tsfmgtdisable - Will be populated with the current value of this field from the register. + * @param[out] tsfupdatedbysw - Will be populated with the current value of this field from the register. + * @param[out] abgnmode - Will be populated with the current value of this field from the register. + * @param[out] keystoramreset - Will be populated with the current value of this field from the register. + * @param[out] mibtablereset - Will be populated with the current value of this field from the register. + * @param[out] ratecontrollermpif - Will be populated with the current value of this field from the register. + * @param[out] disablebaresp - Will be populated with the current value of this field from the register. + * @param[out] disablectsresp - Will be populated with the current value of this field from the register. + * @param[out] disableackresp - Will be populated with the current value of this field from the register. + * @param[out] activeclkgating - Will be populated with the current value of this field from the register. + * @param[out] enablelpclkswitch - Will be populated with the current value of this field from the register. + * @param[out] lpclk32786hz - Will be populated with the current value of this field from the register. + * @param[out] cfpaware - Will be populated with the current value of this field from the register. + * @param[out] pwrmgt - Will be populated with the current value of this field from the register. + * @param[out] ap - Will be populated with the current value of this field from the register. + * @param[out] bsstype - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_mac_cntrl_1_unpack(uint8_t *rxrifsen, uint8_t *tsfmgtdisable, uint8_t *tsfupdatedbysw, uint8_t *abgnmode, uint8_t *keystoramreset, uint8_t *mibtablereset, uint8_t *ratecontrollermpif, uint8_t *disablebaresp, uint8_t *disablectsresp, uint8_t *disableackresp, uint8_t *activeclkgating, uint8_t *enablelpclkswitch, uint8_t *lpclk32786hz, uint8_t *cfpaware, uint8_t *pwrmgt, uint8_t *ap, uint8_t *bsstype) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MAC_CNTRL_1_ADDR); + + *rxrifsen = (localVal & ((uint32_t)0x04000000)) >> 26; + *tsfmgtdisable = (localVal & ((uint32_t)0x02000000)) >> 25; + *tsfupdatedbysw = (localVal & ((uint32_t)0x01000000)) >> 24; + *abgnmode = (localVal & ((uint32_t)0x0001C000)) >> 14; + *keystoramreset = (localVal & ((uint32_t)0x00002000)) >> 13; + *mibtablereset = (localVal & ((uint32_t)0x00001000)) >> 12; + *ratecontrollermpif = (localVal & ((uint32_t)0x00000800)) >> 11; + *disablebaresp = (localVal & ((uint32_t)0x00000400)) >> 10; + *disablectsresp = (localVal & ((uint32_t)0x00000200)) >> 9; + *disableackresp = (localVal & ((uint32_t)0x00000100)) >> 8; + *activeclkgating = (localVal & ((uint32_t)0x00000080)) >> 7; + *enablelpclkswitch = (localVal & ((uint32_t)0x00000040)) >> 6; + *lpclk32786hz = (localVal & ((uint32_t)0x00000020)) >> 5; + *cfpaware = (localVal & ((uint32_t)0x00000008)) >> 3; + *pwrmgt = (localVal & ((uint32_t)0x00000004)) >> 2; + *ap = (localVal & ((uint32_t)0x00000002)) >> 1; + *bsstype = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +/** + * @brief Returns the current value of the rxRIFSEn field in the MAC_CNTRL_1 register. + * + * The MAC_CNTRL_1 register will be read and the rxRIFSEn field's value will be returned. + * + * @return The current value of the rxRIFSEn field in the MAC_CNTRL_1 register. + */ +__INLINE uint8_t nxmac_rx_rifs_en_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MAC_CNTRL_1_ADDR); + return ((localVal & ((uint32_t)0x04000000)) >> 26); +} + +/** + * @brief Sets the rxRIFSEn field of the MAC_CNTRL_1 register. + * + * The MAC_CNTRL_1 register will be read, modified to contain the new field value, and written. + * + * @param[in] rxrifsen - The value to set the field to. + */ +__INLINE void nxmac_rx_rifs_en_setf(uint8_t rxrifsen) +{ + ASSERT_ERR((((uint32_t)rxrifsen << 26) & ~((uint32_t)0x04000000)) == 0); + REG_PL_WR(NXMAC_MAC_CNTRL_1_ADDR, (REG_PL_RD(NXMAC_MAC_CNTRL_1_ADDR) & ~((uint32_t)0x04000000)) | ((uint32_t)rxrifsen << 26)); +} + +/** + * @brief Returns the current value of the tsfMgtDisable field in the MAC_CNTRL_1 register. + * + * The MAC_CNTRL_1 register will be read and the tsfMgtDisable field's value will be returned. + * + * @return The current value of the tsfMgtDisable field in the MAC_CNTRL_1 register. + */ +__INLINE uint8_t nxmac_tsf_mgt_disable_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MAC_CNTRL_1_ADDR); + return ((localVal & ((uint32_t)0x02000000)) >> 25); +} + +/** + * @brief Sets the tsfMgtDisable field of the MAC_CNTRL_1 register. + * + * The MAC_CNTRL_1 register will be read, modified to contain the new field value, and written. + * + * @param[in] tsfmgtdisable - The value to set the field to. + */ +__INLINE void nxmac_tsf_mgt_disable_setf(uint8_t tsfmgtdisable) +{ + ASSERT_ERR((((uint32_t)tsfmgtdisable << 25) & ~((uint32_t)0x02000000)) == 0); + REG_PL_WR(NXMAC_MAC_CNTRL_1_ADDR, (REG_PL_RD(NXMAC_MAC_CNTRL_1_ADDR) & ~((uint32_t)0x02000000)) | ((uint32_t)tsfmgtdisable << 25)); +} + +/** + * @brief Returns the current value of the tsfUpdatedBySW field in the MAC_CNTRL_1 register. + * + * The MAC_CNTRL_1 register will be read and the tsfUpdatedBySW field's value will be returned. + * + * @return The current value of the tsfUpdatedBySW field in the MAC_CNTRL_1 register. + */ +__INLINE uint8_t nxmac_tsf_updated_by_sw_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MAC_CNTRL_1_ADDR); + return ((localVal & ((uint32_t)0x01000000)) >> 24); +} + +/** + * @brief Sets the tsfUpdatedBySW field of the MAC_CNTRL_1 register. + * + * The MAC_CNTRL_1 register will be read, modified to contain the new field value, and written. + * + * @param[in] tsfupdatedbysw - The value to set the field to. + */ +__INLINE void nxmac_tsf_updated_by_sw_setf(uint8_t tsfupdatedbysw) +{ + ASSERT_ERR((((uint32_t)tsfupdatedbysw << 24) & ~((uint32_t)0x01000000)) == 0); + REG_PL_WR(NXMAC_MAC_CNTRL_1_ADDR, (REG_PL_RD(NXMAC_MAC_CNTRL_1_ADDR) & ~((uint32_t)0x01000000)) | ((uint32_t)tsfupdatedbysw << 24)); +} + +/** + * @brief Returns the current value of the abgnMode field in the MAC_CNTRL_1 register. + * + * The MAC_CNTRL_1 register will be read and the abgnMode field's value will be returned. + * + * @return The current value of the abgnMode field in the MAC_CNTRL_1 register. + */ +__INLINE uint8_t nxmac_abgn_mode_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MAC_CNTRL_1_ADDR); + return ((localVal & ((uint32_t)0x0001C000)) >> 14); +} + +/** + * @brief Sets the abgnMode field of the MAC_CNTRL_1 register. + * + * The MAC_CNTRL_1 register will be read, modified to contain the new field value, and written. + * + * @param[in] abgnmode - The value to set the field to. + */ +__INLINE void nxmac_abgn_mode_setf(uint8_t abgnmode) +{ + ASSERT_ERR((((uint32_t)abgnmode << 14) & ~((uint32_t)0x0001C000)) == 0); + REG_PL_WR(NXMAC_MAC_CNTRL_1_ADDR, (REG_PL_RD(NXMAC_MAC_CNTRL_1_ADDR) & ~((uint32_t)0x0001C000)) | ((uint32_t)abgnmode << 14)); +} + +/** + * @brief Returns the current value of the keyStoRAMReset field in the MAC_CNTRL_1 register. + * + * The MAC_CNTRL_1 register will be read and the keyStoRAMReset field's value will be returned. + * + * @return The current value of the keyStoRAMReset field in the MAC_CNTRL_1 register. + */ +__INLINE uint8_t nxmac_key_sto_ram_reset_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MAC_CNTRL_1_ADDR); + return ((localVal & ((uint32_t)0x00002000)) >> 13); +} + +/** + * @brief Sets the keyStoRAMReset field of the MAC_CNTRL_1 register. + * + * The MAC_CNTRL_1 register will be read, modified to contain the new field value, and written. + * + * @param[in] keystoramreset - The value to set the field to. + */ +__INLINE void nxmac_key_sto_ram_reset_setf(uint8_t keystoramreset) +{ + ASSERT_ERR((((uint32_t)keystoramreset << 13) & ~((uint32_t)0x00002000)) == 0); + REG_PL_WR(NXMAC_MAC_CNTRL_1_ADDR, (REG_PL_RD(NXMAC_MAC_CNTRL_1_ADDR) & ~((uint32_t)0x00002000)) | ((uint32_t)keystoramreset << 13)); +} + +/** + * @brief Returns the current value of the mibTableReset field in the MAC_CNTRL_1 register. + * + * The MAC_CNTRL_1 register will be read and the mibTableReset field's value will be returned. + * + * @return The current value of the mibTableReset field in the MAC_CNTRL_1 register. + */ +__INLINE uint8_t nxmac_mib_table_reset_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MAC_CNTRL_1_ADDR); + return ((localVal & ((uint32_t)0x00001000)) >> 12); +} + +/** + * @brief Sets the mibTableReset field of the MAC_CNTRL_1 register. + * + * The MAC_CNTRL_1 register will be read, modified to contain the new field value, and written. + * + * @param[in] mibtablereset - The value to set the field to. + */ +__INLINE void nxmac_mib_table_reset_setf(uint8_t mibtablereset) +{ + ASSERT_ERR((((uint32_t)mibtablereset << 12) & ~((uint32_t)0x00001000)) == 0); + REG_PL_WR(NXMAC_MAC_CNTRL_1_ADDR, (REG_PL_RD(NXMAC_MAC_CNTRL_1_ADDR) & ~((uint32_t)0x00001000)) | ((uint32_t)mibtablereset << 12)); +} + +/** + * @brief Returns the current value of the rateControllerMPIF field in the MAC_CNTRL_1 register. + * + * The MAC_CNTRL_1 register will be read and the rateControllerMPIF field's value will be returned. + * + * @return The current value of the rateControllerMPIF field in the MAC_CNTRL_1 register. + */ +__INLINE uint8_t nxmac_rate_controller_mpif_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MAC_CNTRL_1_ADDR); + return ((localVal & ((uint32_t)0x00000800)) >> 11); +} + +/** + * @brief Sets the rateControllerMPIF field of the MAC_CNTRL_1 register. + * + * The MAC_CNTRL_1 register will be read, modified to contain the new field value, and written. + * + * @param[in] ratecontrollermpif - The value to set the field to. + */ +__INLINE void nxmac_rate_controller_mpif_setf(uint8_t ratecontrollermpif) +{ + ASSERT_ERR((((uint32_t)ratecontrollermpif << 11) & ~((uint32_t)0x00000800)) == 0); + REG_PL_WR(NXMAC_MAC_CNTRL_1_ADDR, (REG_PL_RD(NXMAC_MAC_CNTRL_1_ADDR) & ~((uint32_t)0x00000800)) | ((uint32_t)ratecontrollermpif << 11)); +} + +/** + * @brief Returns the current value of the disableBAResp field in the MAC_CNTRL_1 register. + * + * The MAC_CNTRL_1 register will be read and the disableBAResp field's value will be returned. + * + * @return The current value of the disableBAResp field in the MAC_CNTRL_1 register. + */ +__INLINE uint8_t nxmac_disable_ba_resp_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MAC_CNTRL_1_ADDR); + return ((localVal & ((uint32_t)0x00000400)) >> 10); +} + +/** + * @brief Sets the disableBAResp field of the MAC_CNTRL_1 register. + * + * The MAC_CNTRL_1 register will be read, modified to contain the new field value, and written. + * + * @param[in] disablebaresp - The value to set the field to. + */ +__INLINE void nxmac_disable_ba_resp_setf(uint8_t disablebaresp) +{ + ASSERT_ERR((((uint32_t)disablebaresp << 10) & ~((uint32_t)0x00000400)) == 0); + REG_PL_WR(NXMAC_MAC_CNTRL_1_ADDR, (REG_PL_RD(NXMAC_MAC_CNTRL_1_ADDR) & ~((uint32_t)0x00000400)) | ((uint32_t)disablebaresp << 10)); +} + +/** + * @brief Returns the current value of the disableCTSResp field in the MAC_CNTRL_1 register. + * + * The MAC_CNTRL_1 register will be read and the disableCTSResp field's value will be returned. + * + * @return The current value of the disableCTSResp field in the MAC_CNTRL_1 register. + */ +__INLINE uint8_t nxmac_disable_cts_resp_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MAC_CNTRL_1_ADDR); + return ((localVal & ((uint32_t)0x00000200)) >> 9); +} + +/** + * @brief Sets the disableCTSResp field of the MAC_CNTRL_1 register. + * + * The MAC_CNTRL_1 register will be read, modified to contain the new field value, and written. + * + * @param[in] disablectsresp - The value to set the field to. + */ +__INLINE void nxmac_disable_cts_resp_setf(uint8_t disablectsresp) +{ + ASSERT_ERR((((uint32_t)disablectsresp << 9) & ~((uint32_t)0x00000200)) == 0); + REG_PL_WR(NXMAC_MAC_CNTRL_1_ADDR, (REG_PL_RD(NXMAC_MAC_CNTRL_1_ADDR) & ~((uint32_t)0x00000200)) | ((uint32_t)disablectsresp << 9)); +} + +/** + * @brief Returns the current value of the disableACKResp field in the MAC_CNTRL_1 register. + * + * The MAC_CNTRL_1 register will be read and the disableACKResp field's value will be returned. + * + * @return The current value of the disableACKResp field in the MAC_CNTRL_1 register. + */ +__INLINE uint8_t nxmac_disable_ack_resp_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MAC_CNTRL_1_ADDR); + return ((localVal & ((uint32_t)0x00000100)) >> 8); +} + +/** + * @brief Sets the disableACKResp field of the MAC_CNTRL_1 register. + * + * The MAC_CNTRL_1 register will be read, modified to contain the new field value, and written. + * + * @param[in] disableackresp - The value to set the field to. + */ +__INLINE void nxmac_disable_ack_resp_setf(uint8_t disableackresp) +{ + ASSERT_ERR((((uint32_t)disableackresp << 8) & ~((uint32_t)0x00000100)) == 0); + REG_PL_WR(NXMAC_MAC_CNTRL_1_ADDR, (REG_PL_RD(NXMAC_MAC_CNTRL_1_ADDR) & ~((uint32_t)0x00000100)) | ((uint32_t)disableackresp << 8)); +} + +/** + * @brief Returns the current value of the activeClkGating field in the MAC_CNTRL_1 register. + * + * The MAC_CNTRL_1 register will be read and the activeClkGating field's value will be returned. + * + * @return The current value of the activeClkGating field in the MAC_CNTRL_1 register. + */ +__INLINE uint8_t nxmac_active_clk_gating_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MAC_CNTRL_1_ADDR); + return ((localVal & ((uint32_t)0x00000080)) >> 7); +} + +/** + * @brief Sets the activeClkGating field of the MAC_CNTRL_1 register. + * + * The MAC_CNTRL_1 register will be read, modified to contain the new field value, and written. + * + * @param[in] activeclkgating - The value to set the field to. + */ +__INLINE void nxmac_active_clk_gating_setf(uint8_t activeclkgating) +{ + ASSERT_ERR((((uint32_t)activeclkgating << 7) & ~((uint32_t)0x00000080)) == 0); + REG_PL_WR(NXMAC_MAC_CNTRL_1_ADDR, (REG_PL_RD(NXMAC_MAC_CNTRL_1_ADDR) & ~((uint32_t)0x00000080)) | ((uint32_t)activeclkgating << 7)); +} + +/** + * @brief Returns the current value of the enableLPClkSwitch field in the MAC_CNTRL_1 register. + * + * The MAC_CNTRL_1 register will be read and the enableLPClkSwitch field's value will be returned. + * + * @return The current value of the enableLPClkSwitch field in the MAC_CNTRL_1 register. + */ +__INLINE uint8_t nxmac_enable_lp_clk_switch_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MAC_CNTRL_1_ADDR); + return ((localVal & ((uint32_t)0x00000040)) >> 6); +} + +/** + * @brief Sets the enableLPClkSwitch field of the MAC_CNTRL_1 register. + * + * The MAC_CNTRL_1 register will be read, modified to contain the new field value, and written. + * + * @param[in] enablelpclkswitch - The value to set the field to. + */ +__INLINE void nxmac_enable_lp_clk_switch_setf(uint8_t enablelpclkswitch) +{ + ASSERT_ERR((((uint32_t)enablelpclkswitch << 6) & ~((uint32_t)0x00000040)) == 0); + REG_PL_WR(NXMAC_MAC_CNTRL_1_ADDR, (REG_PL_RD(NXMAC_MAC_CNTRL_1_ADDR) & ~((uint32_t)0x00000040)) | ((uint32_t)enablelpclkswitch << 6)); +} + +/** + * @brief Returns the current value of the lpClk32786Hz field in the MAC_CNTRL_1 register. + * + * The MAC_CNTRL_1 register will be read and the lpClk32786Hz field's value will be returned. + * + * @return The current value of the lpClk32786Hz field in the MAC_CNTRL_1 register. + */ +__INLINE uint8_t nxmac_lp_clk_32786_hz_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MAC_CNTRL_1_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +/** + * @brief Sets the lpClk32786Hz field of the MAC_CNTRL_1 register. + * + * The MAC_CNTRL_1 register will be read, modified to contain the new field value, and written. + * + * @param[in] lpclk32786hz - The value to set the field to. + */ +__INLINE void nxmac_lp_clk_32786_hz_setf(uint8_t lpclk32786hz) +{ + ASSERT_ERR((((uint32_t)lpclk32786hz << 5) & ~((uint32_t)0x00000020)) == 0); + REG_PL_WR(NXMAC_MAC_CNTRL_1_ADDR, (REG_PL_RD(NXMAC_MAC_CNTRL_1_ADDR) & ~((uint32_t)0x00000020)) | ((uint32_t)lpclk32786hz << 5)); +} + +/** + * @brief Returns the current value of the cfpAware field in the MAC_CNTRL_1 register. + * + * The MAC_CNTRL_1 register will be read and the cfpAware field's value will be returned. + * + * @return The current value of the cfpAware field in the MAC_CNTRL_1 register. + */ +__INLINE uint8_t nxmac_cfp_aware_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MAC_CNTRL_1_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +/** + * @brief Sets the cfpAware field of the MAC_CNTRL_1 register. + * + * The MAC_CNTRL_1 register will be read, modified to contain the new field value, and written. + * + * @param[in] cfpaware - The value to set the field to. + */ +__INLINE void nxmac_cfp_aware_setf(uint8_t cfpaware) +{ + ASSERT_ERR((((uint32_t)cfpaware << 3) & ~((uint32_t)0x00000008)) == 0); + REG_PL_WR(NXMAC_MAC_CNTRL_1_ADDR, (REG_PL_RD(NXMAC_MAC_CNTRL_1_ADDR) & ~((uint32_t)0x00000008)) | ((uint32_t)cfpaware << 3)); +} + +/** + * @brief Returns the current value of the pwrMgt field in the MAC_CNTRL_1 register. + * + * The MAC_CNTRL_1 register will be read and the pwrMgt field's value will be returned. + * + * @return The current value of the pwrMgt field in the MAC_CNTRL_1 register. + */ +__INLINE uint8_t nxmac_pwr_mgt_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MAC_CNTRL_1_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +/** + * @brief Sets the pwrMgt field of the MAC_CNTRL_1 register. + * + * The MAC_CNTRL_1 register will be read, modified to contain the new field value, and written. + * + * @param[in] pwrmgt - The value to set the field to. + */ +__INLINE void nxmac_pwr_mgt_setf(uint8_t pwrmgt) +{ + ASSERT_ERR((((uint32_t)pwrmgt << 2) & ~((uint32_t)0x00000004)) == 0); + REG_PL_WR(NXMAC_MAC_CNTRL_1_ADDR, (REG_PL_RD(NXMAC_MAC_CNTRL_1_ADDR) & ~((uint32_t)0x00000004)) | ((uint32_t)pwrmgt << 2)); +} + +/** + * @brief Returns the current value of the ap field in the MAC_CNTRL_1 register. + * + * The MAC_CNTRL_1 register will be read and the ap field's value will be returned. + * + * @return The current value of the ap field in the MAC_CNTRL_1 register. + */ +__INLINE uint8_t nxmac_ap_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MAC_CNTRL_1_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +/** + * @brief Sets the ap field of the MAC_CNTRL_1 register. + * + * The MAC_CNTRL_1 register will be read, modified to contain the new field value, and written. + * + * @param[in] ap - The value to set the field to. + */ +__INLINE void nxmac_ap_setf(uint8_t ap) +{ + ASSERT_ERR((((uint32_t)ap << 1) & ~((uint32_t)0x00000002)) == 0); + REG_PL_WR(NXMAC_MAC_CNTRL_1_ADDR, (REG_PL_RD(NXMAC_MAC_CNTRL_1_ADDR) & ~((uint32_t)0x00000002)) | ((uint32_t)ap << 1)); +} + +/** + * @brief Returns the current value of the bssType field in the MAC_CNTRL_1 register. + * + * The MAC_CNTRL_1 register will be read and the bssType field's value will be returned. + * + * @return The current value of the bssType field in the MAC_CNTRL_1 register. + */ +__INLINE uint8_t nxmac_bss_type_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MAC_CNTRL_1_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/** + * @brief Sets the bssType field of the MAC_CNTRL_1 register. + * + * The MAC_CNTRL_1 register will be read, modified to contain the new field value, and written. + * + * @param[in] bsstype - The value to set the field to. + */ +__INLINE void nxmac_bss_type_setf(uint8_t bsstype) +{ + ASSERT_ERR((((uint32_t)bsstype << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_MAC_CNTRL_1_ADDR, (REG_PL_RD(NXMAC_MAC_CNTRL_1_ADDR) & ~((uint32_t)0x00000001)) | ((uint32_t)bsstype << 0)); +} + +/// @} + +/** + * @name MAC_ERR_REC_CNTRL register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     16        rxFlowCntrlEn   0
+ *     07      baPSBitmapReset   0
+ *     06      encrRxFIFOReset   0
+ *     05    macPHYIFFIFOReset   0
+ *     04          txFIFOReset   0
+ *     03          rxFIFOReset   0
+ *     02           hwFSMReset   0
+ *     01            useErrDet   0
+ *     00            useErrRec   0
+ * 
+ * + * @{ + */ + +/// Address of the MAC_ERR_REC_CNTRL register +#define NXMAC_MAC_ERR_REC_CNTRL_ADDR 0xC0000054 +/// Offset of the MAC_ERR_REC_CNTRL register from the base address +#define NXMAC_MAC_ERR_REC_CNTRL_OFFSET 0x00000054 +/// Index of the MAC_ERR_REC_CNTRL register +#define NXMAC_MAC_ERR_REC_CNTRL_INDEX 0x00000015 +/// Reset value of the MAC_ERR_REC_CNTRL register +#define NXMAC_MAC_ERR_REC_CNTRL_RESET 0x00000000 + +/** + * @brief Returns the current value of the MAC_ERR_REC_CNTRL register. + * The MAC_ERR_REC_CNTRL register will be read and its value returned. + * @return The current value of the MAC_ERR_REC_CNTRL register. + */ +__INLINE uint32_t nxmac_mac_err_rec_cntrl_get(void) +{ + return REG_PL_RD(NXMAC_MAC_ERR_REC_CNTRL_ADDR); +} + +/** + * @brief Sets the MAC_ERR_REC_CNTRL register to a value. + * The MAC_ERR_REC_CNTRL register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_mac_err_rec_cntrl_set(uint32_t value) +{ + REG_PL_WR(NXMAC_MAC_ERR_REC_CNTRL_ADDR, value); +} + +// field definitions +/// RX_FLOW_CNTRL_EN field bit +#define NXMAC_RX_FLOW_CNTRL_EN_BIT ((uint32_t)0x00010000) +/// RX_FLOW_CNTRL_EN field position +#define NXMAC_RX_FLOW_CNTRL_EN_POS 16 +/// BA_PS_BITMAP_RESET field bit +#define NXMAC_BA_PS_BITMAP_RESET_BIT ((uint32_t)0x00000080) +/// BA_PS_BITMAP_RESET field position +#define NXMAC_BA_PS_BITMAP_RESET_POS 7 +/// ENCR_RX_FIFO_RESET field bit +#define NXMAC_ENCR_RX_FIFO_RESET_BIT ((uint32_t)0x00000040) +/// ENCR_RX_FIFO_RESET field position +#define NXMAC_ENCR_RX_FIFO_RESET_POS 6 +/// MAC_PHYIFFIFO_RESET field bit +#define NXMAC_MAC_PHYIFFIFO_RESET_BIT ((uint32_t)0x00000020) +/// MAC_PHYIFFIFO_RESET field position +#define NXMAC_MAC_PHYIFFIFO_RESET_POS 5 +/// TX_FIFO_RESET field bit +#define NXMAC_TX_FIFO_RESET_BIT ((uint32_t)0x00000010) +/// TX_FIFO_RESET field position +#define NXMAC_TX_FIFO_RESET_POS 4 +/// RX_FIFO_RESET field bit +#define NXMAC_RX_FIFO_RESET_BIT ((uint32_t)0x00000008) +/// RX_FIFO_RESET field position +#define NXMAC_RX_FIFO_RESET_POS 3 +/// HW_FSM_RESET field bit +#define NXMAC_HW_FSM_RESET_BIT ((uint32_t)0x00000004) +/// HW_FSM_RESET field position +#define NXMAC_HW_FSM_RESET_POS 2 +/// USE_ERR_DET field bit +#define NXMAC_USE_ERR_DET_BIT ((uint32_t)0x00000002) +/// USE_ERR_DET field position +#define NXMAC_USE_ERR_DET_POS 1 +/// USE_ERR_REC field bit +#define NXMAC_USE_ERR_REC_BIT ((uint32_t)0x00000001) +/// USE_ERR_REC field position +#define NXMAC_USE_ERR_REC_POS 0 + +/// RX_FLOW_CNTRL_EN field reset value +#define NXMAC_RX_FLOW_CNTRL_EN_RST 0x0 +/// BA_PS_BITMAP_RESET field reset value +#define NXMAC_BA_PS_BITMAP_RESET_RST 0x0 +/// ENCR_RX_FIFO_RESET field reset value +#define NXMAC_ENCR_RX_FIFO_RESET_RST 0x0 +/// MAC_PHYIFFIFO_RESET field reset value +#define NXMAC_MAC_PHYIFFIFO_RESET_RST 0x0 +/// TX_FIFO_RESET field reset value +#define NXMAC_TX_FIFO_RESET_RST 0x0 +/// RX_FIFO_RESET field reset value +#define NXMAC_RX_FIFO_RESET_RST 0x0 +/// HW_FSM_RESET field reset value +#define NXMAC_HW_FSM_RESET_RST 0x0 +/// USE_ERR_DET field reset value +#define NXMAC_USE_ERR_DET_RST 0x0 +/// USE_ERR_REC field reset value +#define NXMAC_USE_ERR_REC_RST 0x0 + +/** + * @brief Constructs a value for the MAC_ERR_REC_CNTRL register given values for its fields + * and writes the value to the register. + * + * @param[in] rxflowcntrlen - The value to use for the rxFlowCntrlEn field. + * @param[in] bapsbitmapreset - The value to use for the baPSBitmapReset field. + * @param[in] encrrxfiforeset - The value to use for the encrRxFIFOReset field. + * @param[in] macphyiffiforeset - The value to use for the macPHYIFFIFOReset field. + * @param[in] txfiforeset - The value to use for the txFIFOReset field. + * @param[in] rxfiforeset - The value to use for the rxFIFOReset field. + * @param[in] hwfsmreset - The value to use for the hwFSMReset field. + * @param[in] useerrdet - The value to use for the useErrDet field. + */ +__INLINE void nxmac_mac_err_rec_cntrl_pack(uint8_t rxflowcntrlen, uint8_t bapsbitmapreset, uint8_t encrrxfiforeset, uint8_t macphyiffiforeset, uint8_t txfiforeset, uint8_t rxfiforeset, uint8_t hwfsmreset, uint8_t useerrdet) +{ + ASSERT_ERR((((uint32_t)rxflowcntrlen << 16) & ~((uint32_t)0x00010000)) == 0); + ASSERT_ERR((((uint32_t)bapsbitmapreset << 7) & ~((uint32_t)0x00000080)) == 0); + ASSERT_ERR((((uint32_t)encrrxfiforeset << 6) & ~((uint32_t)0x00000040)) == 0); + ASSERT_ERR((((uint32_t)macphyiffiforeset << 5) & ~((uint32_t)0x00000020)) == 0); + ASSERT_ERR((((uint32_t)txfiforeset << 4) & ~((uint32_t)0x00000010)) == 0); + ASSERT_ERR((((uint32_t)rxfiforeset << 3) & ~((uint32_t)0x00000008)) == 0); + ASSERT_ERR((((uint32_t)hwfsmreset << 2) & ~((uint32_t)0x00000004)) == 0); + ASSERT_ERR((((uint32_t)useerrdet << 1) & ~((uint32_t)0x00000002)) == 0); + REG_PL_WR(NXMAC_MAC_ERR_REC_CNTRL_ADDR, ((uint32_t)rxflowcntrlen << 16) | ((uint32_t)bapsbitmapreset << 7) | ((uint32_t)encrrxfiforeset << 6) | ((uint32_t)macphyiffiforeset << 5) | ((uint32_t)txfiforeset << 4) | ((uint32_t)rxfiforeset << 3) | ((uint32_t)hwfsmreset << 2) | ((uint32_t)useerrdet << 1)); +} + +/** + * @brief Unpacks MAC_ERR_REC_CNTRL's fields from current value of the MAC_ERR_REC_CNTRL register. + * + * Reads the MAC_ERR_REC_CNTRL register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] rxflowcntrlen - Will be populated with the current value of this field from the register. + * @param[out] bapsbitmapreset - Will be populated with the current value of this field from the register. + * @param[out] encrrxfiforeset - Will be populated with the current value of this field from the register. + * @param[out] macphyiffiforeset - Will be populated with the current value of this field from the register. + * @param[out] txfiforeset - Will be populated with the current value of this field from the register. + * @param[out] rxfiforeset - Will be populated with the current value of this field from the register. + * @param[out] hwfsmreset - Will be populated with the current value of this field from the register. + * @param[out] useerrdet - Will be populated with the current value of this field from the register. + * @param[out] useerrrec - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_mac_err_rec_cntrl_unpack(uint8_t *rxflowcntrlen, uint8_t *bapsbitmapreset, uint8_t *encrrxfiforeset, uint8_t *macphyiffiforeset, uint8_t *txfiforeset, uint8_t *rxfiforeset, uint8_t *hwfsmreset, uint8_t *useerrdet, uint8_t *useerrrec) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MAC_ERR_REC_CNTRL_ADDR); + + *rxflowcntrlen = (localVal & ((uint32_t)0x00010000)) >> 16; + *bapsbitmapreset = (localVal & ((uint32_t)0x00000080)) >> 7; + *encrrxfiforeset = (localVal & ((uint32_t)0x00000040)) >> 6; + *macphyiffiforeset = (localVal & ((uint32_t)0x00000020)) >> 5; + *txfiforeset = (localVal & ((uint32_t)0x00000010)) >> 4; + *rxfiforeset = (localVal & ((uint32_t)0x00000008)) >> 3; + *hwfsmreset = (localVal & ((uint32_t)0x00000004)) >> 2; + *useerrdet = (localVal & ((uint32_t)0x00000002)) >> 1; + *useerrrec = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +/** + * @brief Returns the current value of the rxFlowCntrlEn field in the MAC_ERR_REC_CNTRL register. + * + * The MAC_ERR_REC_CNTRL register will be read and the rxFlowCntrlEn field's value will be returned. + * + * @return The current value of the rxFlowCntrlEn field in the MAC_ERR_REC_CNTRL register. + */ +__INLINE uint8_t nxmac_rx_flow_cntrl_en_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MAC_ERR_REC_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x00010000)) >> 16); +} + +/** + * @brief Sets the rxFlowCntrlEn field of the MAC_ERR_REC_CNTRL register. + * + * The MAC_ERR_REC_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] rxflowcntrlen - The value to set the field to. + */ +__INLINE void nxmac_rx_flow_cntrl_en_setf(uint8_t rxflowcntrlen) +{ + ASSERT_ERR((((uint32_t)rxflowcntrlen << 16) & ~((uint32_t)0x00010000)) == 0); + REG_PL_WR(NXMAC_MAC_ERR_REC_CNTRL_ADDR, (REG_PL_RD(NXMAC_MAC_ERR_REC_CNTRL_ADDR) & ~((uint32_t)0x00010000)) | ((uint32_t)rxflowcntrlen << 16)); +} + +/** + * @brief Returns the current value of the baPSBitmapReset field in the MAC_ERR_REC_CNTRL register. + * + * The MAC_ERR_REC_CNTRL register will be read and the baPSBitmapReset field's value will be returned. + * + * @return The current value of the baPSBitmapReset field in the MAC_ERR_REC_CNTRL register. + */ +__INLINE uint8_t nxmac_ba_ps_bitmap_reset_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MAC_ERR_REC_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x00000080)) >> 7); +} + +/** + * @brief Sets the baPSBitmapReset field of the MAC_ERR_REC_CNTRL register. + * + * The MAC_ERR_REC_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] bapsbitmapreset - The value to set the field to. + */ +__INLINE void nxmac_ba_ps_bitmap_reset_setf(uint8_t bapsbitmapreset) +{ + ASSERT_ERR((((uint32_t)bapsbitmapreset << 7) & ~((uint32_t)0x00000080)) == 0); + REG_PL_WR(NXMAC_MAC_ERR_REC_CNTRL_ADDR, (REG_PL_RD(NXMAC_MAC_ERR_REC_CNTRL_ADDR) & ~((uint32_t)0x00000080)) | ((uint32_t)bapsbitmapreset << 7)); +} + +/** + * @brief Returns the current value of the encrRxFIFOReset field in the MAC_ERR_REC_CNTRL register. + * + * The MAC_ERR_REC_CNTRL register will be read and the encrRxFIFOReset field's value will be returned. + * + * @return The current value of the encrRxFIFOReset field in the MAC_ERR_REC_CNTRL register. + */ +__INLINE uint8_t nxmac_encr_rx_fifo_reset_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MAC_ERR_REC_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x00000040)) >> 6); +} + +/** + * @brief Sets the encrRxFIFOReset field of the MAC_ERR_REC_CNTRL register. + * + * The MAC_ERR_REC_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] encrrxfiforeset - The value to set the field to. + */ +__INLINE void nxmac_encr_rx_fifo_reset_setf(uint8_t encrrxfiforeset) +{ + ASSERT_ERR((((uint32_t)encrrxfiforeset << 6) & ~((uint32_t)0x00000040)) == 0); + REG_PL_WR(NXMAC_MAC_ERR_REC_CNTRL_ADDR, (REG_PL_RD(NXMAC_MAC_ERR_REC_CNTRL_ADDR) & ~((uint32_t)0x00000040)) | ((uint32_t)encrrxfiforeset << 6)); +} + +/** + * @brief Returns the current value of the macPHYIFFIFOReset field in the MAC_ERR_REC_CNTRL register. + * + * The MAC_ERR_REC_CNTRL register will be read and the macPHYIFFIFOReset field's value will be returned. + * + * @return The current value of the macPHYIFFIFOReset field in the MAC_ERR_REC_CNTRL register. + */ +__INLINE uint8_t nxmac_mac_phyiffifo_reset_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MAC_ERR_REC_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +/** + * @brief Sets the macPHYIFFIFOReset field of the MAC_ERR_REC_CNTRL register. + * + * The MAC_ERR_REC_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] macphyiffiforeset - The value to set the field to. + */ +__INLINE void nxmac_mac_phyiffifo_reset_setf(uint8_t macphyiffiforeset) +{ + ASSERT_ERR((((uint32_t)macphyiffiforeset << 5) & ~((uint32_t)0x00000020)) == 0); + REG_PL_WR(NXMAC_MAC_ERR_REC_CNTRL_ADDR, (REG_PL_RD(NXMAC_MAC_ERR_REC_CNTRL_ADDR) & ~((uint32_t)0x00000020)) | ((uint32_t)macphyiffiforeset << 5)); +} + +/** + * @brief Returns the current value of the txFIFOReset field in the MAC_ERR_REC_CNTRL register. + * + * The MAC_ERR_REC_CNTRL register will be read and the txFIFOReset field's value will be returned. + * + * @return The current value of the txFIFOReset field in the MAC_ERR_REC_CNTRL register. + */ +__INLINE uint8_t nxmac_tx_fifo_reset_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MAC_ERR_REC_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +/** + * @brief Sets the txFIFOReset field of the MAC_ERR_REC_CNTRL register. + * + * The MAC_ERR_REC_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] txfiforeset - The value to set the field to. + */ +__INLINE void nxmac_tx_fifo_reset_setf(uint8_t txfiforeset) +{ + ASSERT_ERR((((uint32_t)txfiforeset << 4) & ~((uint32_t)0x00000010)) == 0); + REG_PL_WR(NXMAC_MAC_ERR_REC_CNTRL_ADDR, (REG_PL_RD(NXMAC_MAC_ERR_REC_CNTRL_ADDR) & ~((uint32_t)0x00000010)) | ((uint32_t)txfiforeset << 4)); +} + +/** + * @brief Returns the current value of the rxFIFOReset field in the MAC_ERR_REC_CNTRL register. + * + * The MAC_ERR_REC_CNTRL register will be read and the rxFIFOReset field's value will be returned. + * + * @return The current value of the rxFIFOReset field in the MAC_ERR_REC_CNTRL register. + */ +__INLINE uint8_t nxmac_rx_fifo_reset_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MAC_ERR_REC_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +/** + * @brief Sets the rxFIFOReset field of the MAC_ERR_REC_CNTRL register. + * + * The MAC_ERR_REC_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] rxfiforeset - The value to set the field to. + */ +__INLINE void nxmac_rx_fifo_reset_setf(uint8_t rxfiforeset) +{ + ASSERT_ERR((((uint32_t)rxfiforeset << 3) & ~((uint32_t)0x00000008)) == 0); + REG_PL_WR(NXMAC_MAC_ERR_REC_CNTRL_ADDR, (REG_PL_RD(NXMAC_MAC_ERR_REC_CNTRL_ADDR) & ~((uint32_t)0x00000008)) | ((uint32_t)rxfiforeset << 3)); +} + +/** + * @brief Returns the current value of the hwFSMReset field in the MAC_ERR_REC_CNTRL register. + * + * The MAC_ERR_REC_CNTRL register will be read and the hwFSMReset field's value will be returned. + * + * @return The current value of the hwFSMReset field in the MAC_ERR_REC_CNTRL register. + */ +__INLINE uint8_t nxmac_hw_fsm_reset_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MAC_ERR_REC_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +/** + * @brief Sets the hwFSMReset field of the MAC_ERR_REC_CNTRL register. + * + * The MAC_ERR_REC_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] hwfsmreset - The value to set the field to. + */ +__INLINE void nxmac_hw_fsm_reset_setf(uint8_t hwfsmreset) +{ + ASSERT_ERR((((uint32_t)hwfsmreset << 2) & ~((uint32_t)0x00000004)) == 0); + REG_PL_WR(NXMAC_MAC_ERR_REC_CNTRL_ADDR, (REG_PL_RD(NXMAC_MAC_ERR_REC_CNTRL_ADDR) & ~((uint32_t)0x00000004)) | ((uint32_t)hwfsmreset << 2)); +} + +/** + * @brief Returns the current value of the useErrDet field in the MAC_ERR_REC_CNTRL register. + * + * The MAC_ERR_REC_CNTRL register will be read and the useErrDet field's value will be returned. + * + * @return The current value of the useErrDet field in the MAC_ERR_REC_CNTRL register. + */ +__INLINE uint8_t nxmac_use_err_det_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MAC_ERR_REC_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +/** + * @brief Sets the useErrDet field of the MAC_ERR_REC_CNTRL register. + * + * The MAC_ERR_REC_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] useerrdet - The value to set the field to. + */ +__INLINE void nxmac_use_err_det_setf(uint8_t useerrdet) +{ + ASSERT_ERR((((uint32_t)useerrdet << 1) & ~((uint32_t)0x00000002)) == 0); + REG_PL_WR(NXMAC_MAC_ERR_REC_CNTRL_ADDR, (REG_PL_RD(NXMAC_MAC_ERR_REC_CNTRL_ADDR) & ~((uint32_t)0x00000002)) | ((uint32_t)useerrdet << 1)); +} + +/** + * @brief Returns the current value of the useErrRec field in the MAC_ERR_REC_CNTRL register. + * + * The MAC_ERR_REC_CNTRL register will be read and the useErrRec field's value will be returned. + * + * @return The current value of the useErrRec field in the MAC_ERR_REC_CNTRL register. + */ +__INLINE uint8_t nxmac_use_err_rec_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MAC_ERR_REC_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/// @} + +/** + * @name MAC_ERR_SET_STATUS register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     03        errInHWLevel3   0
+ *     02      errInTxRxLevel2   0
+ *     01        errInRxLevel1   0
+ *     00        errInTxLevel1   0
+ * 
+ * + * @{ + */ + +/// Address of the MAC_ERR_SET_STATUS register +#define NXMAC_MAC_ERR_SET_STATUS_ADDR 0xC0000058 +/// Offset of the MAC_ERR_SET_STATUS register from the base address +#define NXMAC_MAC_ERR_SET_STATUS_OFFSET 0x00000058 +/// Index of the MAC_ERR_SET_STATUS register +#define NXMAC_MAC_ERR_SET_STATUS_INDEX 0x00000016 +/// Reset value of the MAC_ERR_SET_STATUS register +#define NXMAC_MAC_ERR_SET_STATUS_RESET 0x00000000 + +/** + * @brief Returns the current value of the MAC_ERR_SET_STATUS register. + * The MAC_ERR_SET_STATUS register will be read and its value returned. + * @return The current value of the MAC_ERR_SET_STATUS register. + */ +__INLINE uint32_t nxmac_mac_err_set_status_get(void) +{ + return REG_PL_RD(NXMAC_MAC_ERR_SET_STATUS_ADDR); +} + +/** + * @brief Sets the MAC_ERR_SET_STATUS register to a value. + * The MAC_ERR_SET_STATUS register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_mac_err_set_status_set(uint32_t value) +{ + REG_PL_WR(NXMAC_MAC_ERR_SET_STATUS_ADDR, value); +} + +// field definitions +/// ERR_IN_HW_LEVEL_3 field bit +#define NXMAC_ERR_IN_HW_LEVEL_3_BIT ((uint32_t)0x00000008) +/// ERR_IN_HW_LEVEL_3 field position +#define NXMAC_ERR_IN_HW_LEVEL_3_POS 3 +/// ERR_IN_TX_RX_LEVEL_2 field bit +#define NXMAC_ERR_IN_TX_RX_LEVEL_2_BIT ((uint32_t)0x00000004) +/// ERR_IN_TX_RX_LEVEL_2 field position +#define NXMAC_ERR_IN_TX_RX_LEVEL_2_POS 2 +/// ERR_IN_RX_LEVEL_1 field bit +#define NXMAC_ERR_IN_RX_LEVEL_1_BIT ((uint32_t)0x00000002) +/// ERR_IN_RX_LEVEL_1 field position +#define NXMAC_ERR_IN_RX_LEVEL_1_POS 1 +/// ERR_IN_TX_LEVEL_1 field bit +#define NXMAC_ERR_IN_TX_LEVEL_1_BIT ((uint32_t)0x00000001) +/// ERR_IN_TX_LEVEL_1 field position +#define NXMAC_ERR_IN_TX_LEVEL_1_POS 0 + +/// ERR_IN_HW_LEVEL_3 field reset value +#define NXMAC_ERR_IN_HW_LEVEL_3_RST 0x0 +/// ERR_IN_TX_RX_LEVEL_2 field reset value +#define NXMAC_ERR_IN_TX_RX_LEVEL_2_RST 0x0 +/// ERR_IN_RX_LEVEL_1 field reset value +#define NXMAC_ERR_IN_RX_LEVEL_1_RST 0x0 +/// ERR_IN_TX_LEVEL_1 field reset value +#define NXMAC_ERR_IN_TX_LEVEL_1_RST 0x0 + +/** + * @brief Constructs a value for the MAC_ERR_SET_STATUS register given values for its fields + * and writes the value to the register. + * + * @param[in] errinhwlevel3 - The value to use for the errInHWLevel3 field. + * @param[in] errintxrxlevel2 - The value to use for the errInTxRxLevel2 field. + * @param[in] errinrxlevel1 - The value to use for the errInRxLevel1 field. + * @param[in] errintxlevel1 - The value to use for the errInTxLevel1 field. + */ +__INLINE void nxmac_mac_err_set_status_pack(uint8_t errinhwlevel3, uint8_t errintxrxlevel2, uint8_t errinrxlevel1, uint8_t errintxlevel1) +{ + ASSERT_ERR((((uint32_t)errinhwlevel3 << 3) & ~((uint32_t)0x00000008)) == 0); + ASSERT_ERR((((uint32_t)errintxrxlevel2 << 2) & ~((uint32_t)0x00000004)) == 0); + ASSERT_ERR((((uint32_t)errinrxlevel1 << 1) & ~((uint32_t)0x00000002)) == 0); + ASSERT_ERR((((uint32_t)errintxlevel1 << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_MAC_ERR_SET_STATUS_ADDR, ((uint32_t)errinhwlevel3 << 3) | ((uint32_t)errintxrxlevel2 << 2) | ((uint32_t)errinrxlevel1 << 1) | ((uint32_t)errintxlevel1 << 0)); +} + +/** + * @brief Unpacks MAC_ERR_SET_STATUS's fields from current value of the MAC_ERR_SET_STATUS register. + * + * Reads the MAC_ERR_SET_STATUS register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] errinhwlevel3 - Will be populated with the current value of this field from the register. + * @param[out] errintxrxlevel2 - Will be populated with the current value of this field from the register. + * @param[out] errinrxlevel1 - Will be populated with the current value of this field from the register. + * @param[out] errintxlevel1 - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_mac_err_set_status_unpack(uint8_t *errinhwlevel3, uint8_t *errintxrxlevel2, uint8_t *errinrxlevel1, uint8_t *errintxlevel1) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MAC_ERR_SET_STATUS_ADDR); + + *errinhwlevel3 = (localVal & ((uint32_t)0x00000008)) >> 3; + *errintxrxlevel2 = (localVal & ((uint32_t)0x00000004)) >> 2; + *errinrxlevel1 = (localVal & ((uint32_t)0x00000002)) >> 1; + *errintxlevel1 = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +/** + * @brief Returns the current value of the errInHWLevel3 field in the MAC_ERR_SET_STATUS register. + * + * The MAC_ERR_SET_STATUS register will be read and the errInHWLevel3 field's value will be returned. + * + * @return The current value of the errInHWLevel3 field in the MAC_ERR_SET_STATUS register. + */ +__INLINE uint8_t nxmac_err_in_hw_level_3_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MAC_ERR_SET_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +/** + * @brief Sets the errInHWLevel3 field of the MAC_ERR_SET_STATUS register. + * + * The MAC_ERR_SET_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] errinhwlevel3 - The value to set the field to. + */ +__INLINE void nxmac_err_in_hw_level_3_setf(uint8_t errinhwlevel3) +{ + ASSERT_ERR((((uint32_t)errinhwlevel3 << 3) & ~((uint32_t)0x00000008)) == 0); + REG_PL_WR(NXMAC_MAC_ERR_SET_STATUS_ADDR, (uint32_t)errinhwlevel3 << 3); +} + +/** + * @brief Returns the current value of the errInTxRxLevel2 field in the MAC_ERR_SET_STATUS register. + * + * The MAC_ERR_SET_STATUS register will be read and the errInTxRxLevel2 field's value will be returned. + * + * @return The current value of the errInTxRxLevel2 field in the MAC_ERR_SET_STATUS register. + */ +__INLINE uint8_t nxmac_err_in_tx_rx_level_2_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MAC_ERR_SET_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +/** + * @brief Sets the errInTxRxLevel2 field of the MAC_ERR_SET_STATUS register. + * + * The MAC_ERR_SET_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] errintxrxlevel2 - The value to set the field to. + */ +__INLINE void nxmac_err_in_tx_rx_level_2_setf(uint8_t errintxrxlevel2) +{ + ASSERT_ERR((((uint32_t)errintxrxlevel2 << 2) & ~((uint32_t)0x00000004)) == 0); + REG_PL_WR(NXMAC_MAC_ERR_SET_STATUS_ADDR, (uint32_t)errintxrxlevel2 << 2); +} + +/** + * @brief Returns the current value of the errInRxLevel1 field in the MAC_ERR_SET_STATUS register. + * + * The MAC_ERR_SET_STATUS register will be read and the errInRxLevel1 field's value will be returned. + * + * @return The current value of the errInRxLevel1 field in the MAC_ERR_SET_STATUS register. + */ +__INLINE uint8_t nxmac_err_in_rx_level_1_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MAC_ERR_SET_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +/** + * @brief Sets the errInRxLevel1 field of the MAC_ERR_SET_STATUS register. + * + * The MAC_ERR_SET_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] errinrxlevel1 - The value to set the field to. + */ +__INLINE void nxmac_err_in_rx_level_1_setf(uint8_t errinrxlevel1) +{ + ASSERT_ERR((((uint32_t)errinrxlevel1 << 1) & ~((uint32_t)0x00000002)) == 0); + REG_PL_WR(NXMAC_MAC_ERR_SET_STATUS_ADDR, (uint32_t)errinrxlevel1 << 1); +} + +/** + * @brief Returns the current value of the errInTxLevel1 field in the MAC_ERR_SET_STATUS register. + * + * The MAC_ERR_SET_STATUS register will be read and the errInTxLevel1 field's value will be returned. + * + * @return The current value of the errInTxLevel1 field in the MAC_ERR_SET_STATUS register. + */ +__INLINE uint8_t nxmac_err_in_tx_level_1_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MAC_ERR_SET_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/** + * @brief Sets the errInTxLevel1 field of the MAC_ERR_SET_STATUS register. + * + * The MAC_ERR_SET_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] errintxlevel1 - The value to set the field to. + */ +__INLINE void nxmac_err_in_tx_level_1_setf(uint8_t errintxlevel1) +{ + ASSERT_ERR((((uint32_t)errintxlevel1 << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_MAC_ERR_SET_STATUS_ADDR, (uint32_t)errintxlevel1 << 0); +} + +/// @} + +/** + * @name MAC_ERR_CLEAR_STATUS register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     03   clearErrInHWLevel3   0
+ *     02   clearErrInTxRxLevel2   0
+ *     01   clearErrInRxLevel1   0
+ *     00   clearErrInTxLevel1   0
+ * 
+ * + * @{ + */ + +/// Address of the MAC_ERR_CLEAR_STATUS register +#define NXMAC_MAC_ERR_CLEAR_STATUS_ADDR 0xC000005C +/// Offset of the MAC_ERR_CLEAR_STATUS register from the base address +#define NXMAC_MAC_ERR_CLEAR_STATUS_OFFSET 0x0000005C +/// Index of the MAC_ERR_CLEAR_STATUS register +#define NXMAC_MAC_ERR_CLEAR_STATUS_INDEX 0x00000017 +/// Reset value of the MAC_ERR_CLEAR_STATUS register +#define NXMAC_MAC_ERR_CLEAR_STATUS_RESET 0x00000000 + +/** + * @brief Returns the current value of the MAC_ERR_CLEAR_STATUS register. + * The MAC_ERR_CLEAR_STATUS register will be read and its value returned. + * @return The current value of the MAC_ERR_CLEAR_STATUS register. + */ +__INLINE uint32_t nxmac_mac_err_clear_status_get(void) +{ + return REG_PL_RD(NXMAC_MAC_ERR_CLEAR_STATUS_ADDR); +} + +/** + * @brief Sets the MAC_ERR_CLEAR_STATUS register to a value. + * The MAC_ERR_CLEAR_STATUS register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_mac_err_clear_status_clear(uint32_t value) +{ + REG_PL_WR(NXMAC_MAC_ERR_CLEAR_STATUS_ADDR, value); +} + +// field definitions +/// CLEAR_ERR_IN_HW_LEVEL_3 field bit +#define NXMAC_CLEAR_ERR_IN_HW_LEVEL_3_BIT ((uint32_t)0x00000008) +/// CLEAR_ERR_IN_HW_LEVEL_3 field position +#define NXMAC_CLEAR_ERR_IN_HW_LEVEL_3_POS 3 +/// CLEAR_ERR_IN_TX_RX_LEVEL_2 field bit +#define NXMAC_CLEAR_ERR_IN_TX_RX_LEVEL_2_BIT ((uint32_t)0x00000004) +/// CLEAR_ERR_IN_TX_RX_LEVEL_2 field position +#define NXMAC_CLEAR_ERR_IN_TX_RX_LEVEL_2_POS 2 +/// CLEAR_ERR_IN_RX_LEVEL_1 field bit +#define NXMAC_CLEAR_ERR_IN_RX_LEVEL_1_BIT ((uint32_t)0x00000002) +/// CLEAR_ERR_IN_RX_LEVEL_1 field position +#define NXMAC_CLEAR_ERR_IN_RX_LEVEL_1_POS 1 +/// CLEAR_ERR_IN_TX_LEVEL_1 field bit +#define NXMAC_CLEAR_ERR_IN_TX_LEVEL_1_BIT ((uint32_t)0x00000001) +/// CLEAR_ERR_IN_TX_LEVEL_1 field position +#define NXMAC_CLEAR_ERR_IN_TX_LEVEL_1_POS 0 + +/// CLEAR_ERR_IN_HW_LEVEL_3 field reset value +#define NXMAC_CLEAR_ERR_IN_HW_LEVEL_3_RST 0x0 +/// CLEAR_ERR_IN_TX_RX_LEVEL_2 field reset value +#define NXMAC_CLEAR_ERR_IN_TX_RX_LEVEL_2_RST 0x0 +/// CLEAR_ERR_IN_RX_LEVEL_1 field reset value +#define NXMAC_CLEAR_ERR_IN_RX_LEVEL_1_RST 0x0 +/// CLEAR_ERR_IN_TX_LEVEL_1 field reset value +#define NXMAC_CLEAR_ERR_IN_TX_LEVEL_1_RST 0x0 + +/** + * @brief Constructs a value for the MAC_ERR_CLEAR_STATUS register given values for its fields + * and writes the value to the register. + * + * @param[in] clearerrinhwlevel3 - The value to use for the clearErrInHWLevel3 field. + * @param[in] clearerrintxrxlevel2 - The value to use for the clearErrInTxRxLevel2 field. + * @param[in] clearerrinrxlevel1 - The value to use for the clearErrInRxLevel1 field. + * @param[in] clearerrintxlevel1 - The value to use for the clearErrInTxLevel1 field. + */ +__INLINE void nxmac_mac_err_clear_status_pack(uint8_t clearerrinhwlevel3, uint8_t clearerrintxrxlevel2, uint8_t clearerrinrxlevel1, uint8_t clearerrintxlevel1) +{ + ASSERT_ERR((((uint32_t)clearerrinhwlevel3 << 3) & ~((uint32_t)0x00000008)) == 0); + ASSERT_ERR((((uint32_t)clearerrintxrxlevel2 << 2) & ~((uint32_t)0x00000004)) == 0); + ASSERT_ERR((((uint32_t)clearerrinrxlevel1 << 1) & ~((uint32_t)0x00000002)) == 0); + ASSERT_ERR((((uint32_t)clearerrintxlevel1 << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_MAC_ERR_CLEAR_STATUS_ADDR, ((uint32_t)clearerrinhwlevel3 << 3) | ((uint32_t)clearerrintxrxlevel2 << 2) | ((uint32_t)clearerrinrxlevel1 << 1) | ((uint32_t)clearerrintxlevel1 << 0)); +} + +/** + * @brief Unpacks MAC_ERR_CLEAR_STATUS's fields from current value of the MAC_ERR_CLEAR_STATUS register. + * + * Reads the MAC_ERR_CLEAR_STATUS register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] clearerrinhwlevel3 - Will be populated with the current value of this field from the register. + * @param[out] clearerrintxrxlevel2 - Will be populated with the current value of this field from the register. + * @param[out] clearerrinrxlevel1 - Will be populated with the current value of this field from the register. + * @param[out] clearerrintxlevel1 - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_mac_err_clear_status_unpack(uint8_t *clearerrinhwlevel3, uint8_t *clearerrintxrxlevel2, uint8_t *clearerrinrxlevel1, uint8_t *clearerrintxlevel1) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MAC_ERR_CLEAR_STATUS_ADDR); + + *clearerrinhwlevel3 = (localVal & ((uint32_t)0x00000008)) >> 3; + *clearerrintxrxlevel2 = (localVal & ((uint32_t)0x00000004)) >> 2; + *clearerrinrxlevel1 = (localVal & ((uint32_t)0x00000002)) >> 1; + *clearerrintxlevel1 = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +/** + * @brief Returns the current value of the clearErrInHWLevel3 field in the MAC_ERR_CLEAR_STATUS register. + * + * The MAC_ERR_CLEAR_STATUS register will be read and the clearErrInHWLevel3 field's value will be returned. + * + * @return The current value of the clearErrInHWLevel3 field in the MAC_ERR_CLEAR_STATUS register. + */ +__INLINE uint8_t nxmac_clear_err_in_hw_level_3_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MAC_ERR_CLEAR_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +/** + * @brief Sets the clearErrInHWLevel3 field of the MAC_ERR_CLEAR_STATUS register. + * + * The MAC_ERR_CLEAR_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] clearerrinhwlevel3 - The value to set the field to. + */ +__INLINE void nxmac_clear_err_in_hw_level_3_clearf(uint8_t clearerrinhwlevel3) +{ + ASSERT_ERR((((uint32_t)clearerrinhwlevel3 << 3) & ~((uint32_t)0x00000008)) == 0); + REG_PL_WR(NXMAC_MAC_ERR_CLEAR_STATUS_ADDR, (uint32_t)clearerrinhwlevel3 << 3); +} + +/** + * @brief Returns the current value of the clearErrInTxRxLevel2 field in the MAC_ERR_CLEAR_STATUS register. + * + * The MAC_ERR_CLEAR_STATUS register will be read and the clearErrInTxRxLevel2 field's value will be returned. + * + * @return The current value of the clearErrInTxRxLevel2 field in the MAC_ERR_CLEAR_STATUS register. + */ +__INLINE uint8_t nxmac_clear_err_in_tx_rx_level_2_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MAC_ERR_CLEAR_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +/** + * @brief Sets the clearErrInTxRxLevel2 field of the MAC_ERR_CLEAR_STATUS register. + * + * The MAC_ERR_CLEAR_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] clearerrintxrxlevel2 - The value to set the field to. + */ +__INLINE void nxmac_clear_err_in_tx_rx_level_2_clearf(uint8_t clearerrintxrxlevel2) +{ + ASSERT_ERR((((uint32_t)clearerrintxrxlevel2 << 2) & ~((uint32_t)0x00000004)) == 0); + REG_PL_WR(NXMAC_MAC_ERR_CLEAR_STATUS_ADDR, (uint32_t)clearerrintxrxlevel2 << 2); +} + +/** + * @brief Returns the current value of the clearErrInRxLevel1 field in the MAC_ERR_CLEAR_STATUS register. + * + * The MAC_ERR_CLEAR_STATUS register will be read and the clearErrInRxLevel1 field's value will be returned. + * + * @return The current value of the clearErrInRxLevel1 field in the MAC_ERR_CLEAR_STATUS register. + */ +__INLINE uint8_t nxmac_clear_err_in_rx_level_1_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MAC_ERR_CLEAR_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +/** + * @brief Sets the clearErrInRxLevel1 field of the MAC_ERR_CLEAR_STATUS register. + * + * The MAC_ERR_CLEAR_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] clearerrinrxlevel1 - The value to set the field to. + */ +__INLINE void nxmac_clear_err_in_rx_level_1_clearf(uint8_t clearerrinrxlevel1) +{ + ASSERT_ERR((((uint32_t)clearerrinrxlevel1 << 1) & ~((uint32_t)0x00000002)) == 0); + REG_PL_WR(NXMAC_MAC_ERR_CLEAR_STATUS_ADDR, (uint32_t)clearerrinrxlevel1 << 1); +} + +/** + * @brief Returns the current value of the clearErrInTxLevel1 field in the MAC_ERR_CLEAR_STATUS register. + * + * The MAC_ERR_CLEAR_STATUS register will be read and the clearErrInTxLevel1 field's value will be returned. + * + * @return The current value of the clearErrInTxLevel1 field in the MAC_ERR_CLEAR_STATUS register. + */ +__INLINE uint8_t nxmac_clear_err_in_tx_level_1_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MAC_ERR_CLEAR_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/** + * @brief Sets the clearErrInTxLevel1 field of the MAC_ERR_CLEAR_STATUS register. + * + * The MAC_ERR_CLEAR_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] clearerrintxlevel1 - The value to set the field to. + */ +__INLINE void nxmac_clear_err_in_tx_level_1_clearf(uint8_t clearerrintxlevel1) +{ + ASSERT_ERR((((uint32_t)clearerrintxlevel1 << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_MAC_ERR_CLEAR_STATUS_ADDR, (uint32_t)clearerrintxlevel1 << 0); +} + +/// @} + +/** + * @name RX_CNTRL register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31   enDuplicateDetection   0
+ *     30        acceptUnknown   0
+ *     29   acceptOtherDataFrames   0
+ *     28        acceptQoSNull   1
+ *     27      acceptQCFWOData   0
+ *     26          acceptQData   1
+ *     25       acceptCFWOData   0
+ *     24           acceptData   1
+ *     23   acceptOtherCntrlFrames   0
+ *     22          acceptCFEnd   0
+ *     21            acceptACK   0
+ *     20            acceptCTS   0
+ *     19            acceptRTS   0
+ *     18         acceptPSPoll   1
+ *     17             acceptBA   1
+ *     16            acceptBAR   1
+ *     15   acceptOtherMgmtFrames   1
+ *     14    acceptBfmeeFrames   0
+ *     13      acceptAllBeacon   0
+ *     12   acceptNotExpectedBA   0
+ *     11   acceptDecryptErrorFrames   0
+ *     10         acceptBeacon   1
+ *     09      acceptProbeResp   1
+ *     08       acceptProbeReq   1
+ *     07      acceptMyUnicast   1
+ *     06        acceptUnicast   0
+ *     05    acceptErrorFrames   0
+ *     04     acceptOtherBSSID   0
+ *     03      acceptBroadcast   1
+ *     02      acceptMulticast   0
+ *     01          dontDecrypt   0
+ *     00       excUnencrypted   0
+ * 
+ * + * @{ + */ + +/// Address of the RX_CNTRL register +#define NXMAC_RX_CNTRL_ADDR 0xC0000060 +/// Offset of the RX_CNTRL register from the base address +#define NXMAC_RX_CNTRL_OFFSET 0x00000060 +/// Index of the RX_CNTRL register +#define NXMAC_RX_CNTRL_INDEX 0x00000018 +/// Reset value of the RX_CNTRL register +#define NXMAC_RX_CNTRL_RESET 0x15078788 + +/** + * @brief Returns the current value of the RX_CNTRL register. + * The RX_CNTRL register will be read and its value returned. + * @return The current value of the RX_CNTRL register. + */ +__INLINE uint32_t nxmac_rx_cntrl_get(void) +{ + return REG_PL_RD(NXMAC_RX_CNTRL_ADDR); +} + +/** + * @brief Sets the RX_CNTRL register to a value. + * The RX_CNTRL register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_rx_cntrl_set(uint32_t value) +{ + REG_PL_WR(NXMAC_RX_CNTRL_ADDR, value); +} + +// field definitions +/// EN_DUPLICATE_DETECTION field bit +#define NXMAC_EN_DUPLICATE_DETECTION_BIT ((uint32_t)0x80000000) +/// EN_DUPLICATE_DETECTION field position +#define NXMAC_EN_DUPLICATE_DETECTION_POS 31 +/// ACCEPT_UNKNOWN field bit +#define NXMAC_ACCEPT_UNKNOWN_BIT ((uint32_t)0x40000000) +/// ACCEPT_UNKNOWN field position +#define NXMAC_ACCEPT_UNKNOWN_POS 30 +/// ACCEPT_OTHER_DATA_FRAMES field bit +#define NXMAC_ACCEPT_OTHER_DATA_FRAMES_BIT ((uint32_t)0x20000000) +/// ACCEPT_OTHER_DATA_FRAMES field position +#define NXMAC_ACCEPT_OTHER_DATA_FRAMES_POS 29 +/// ACCEPT_QO_S_NULL field bit +#define NXMAC_ACCEPT_QO_S_NULL_BIT ((uint32_t)0x10000000) +/// ACCEPT_QO_S_NULL field position +#define NXMAC_ACCEPT_QO_S_NULL_POS 28 +/// ACCEPT_QCFWO_DATA field bit +#define NXMAC_ACCEPT_QCFWO_DATA_BIT ((uint32_t)0x08000000) +/// ACCEPT_QCFWO_DATA field position +#define NXMAC_ACCEPT_QCFWO_DATA_POS 27 +/// ACCEPT_Q_DATA field bit +#define NXMAC_ACCEPT_Q_DATA_BIT ((uint32_t)0x04000000) +/// ACCEPT_Q_DATA field position +#define NXMAC_ACCEPT_Q_DATA_POS 26 +/// ACCEPT_CFWO_DATA field bit +#define NXMAC_ACCEPT_CFWO_DATA_BIT ((uint32_t)0x02000000) +/// ACCEPT_CFWO_DATA field position +#define NXMAC_ACCEPT_CFWO_DATA_POS 25 +/// ACCEPT_DATA field bit +#define NXMAC_ACCEPT_DATA_BIT ((uint32_t)0x01000000) +/// ACCEPT_DATA field position +#define NXMAC_ACCEPT_DATA_POS 24 +/// ACCEPT_OTHER_CNTRL_FRAMES field bit +#define NXMAC_ACCEPT_OTHER_CNTRL_FRAMES_BIT ((uint32_t)0x00800000) +/// ACCEPT_OTHER_CNTRL_FRAMES field position +#define NXMAC_ACCEPT_OTHER_CNTRL_FRAMES_POS 23 +/// ACCEPT_CF_END field bit +#define NXMAC_ACCEPT_CF_END_BIT ((uint32_t)0x00400000) +/// ACCEPT_CF_END field position +#define NXMAC_ACCEPT_CF_END_POS 22 +/// ACCEPT_ACK field bit +#define NXMAC_ACCEPT_ACK_BIT ((uint32_t)0x00200000) +/// ACCEPT_ACK field position +#define NXMAC_ACCEPT_ACK_POS 21 +/// ACCEPT_CTS field bit +#define NXMAC_ACCEPT_CTS_BIT ((uint32_t)0x00100000) +/// ACCEPT_CTS field position +#define NXMAC_ACCEPT_CTS_POS 20 +/// ACCEPT_RTS field bit +#define NXMAC_ACCEPT_RTS_BIT ((uint32_t)0x00080000) +/// ACCEPT_RTS field position +#define NXMAC_ACCEPT_RTS_POS 19 +/// ACCEPT_PS_POLL field bit +#define NXMAC_ACCEPT_PS_POLL_BIT ((uint32_t)0x00040000) +/// ACCEPT_PS_POLL field position +#define NXMAC_ACCEPT_PS_POLL_POS 18 +/// ACCEPT_BA field bit +#define NXMAC_ACCEPT_BA_BIT ((uint32_t)0x00020000) +/// ACCEPT_BA field position +#define NXMAC_ACCEPT_BA_POS 17 +/// ACCEPT_BAR field bit +#define NXMAC_ACCEPT_BAR_BIT ((uint32_t)0x00010000) +/// ACCEPT_BAR field position +#define NXMAC_ACCEPT_BAR_POS 16 +/// ACCEPT_OTHER_MGMT_FRAMES field bit +#define NXMAC_ACCEPT_OTHER_MGMT_FRAMES_BIT ((uint32_t)0x00008000) +/// ACCEPT_OTHER_MGMT_FRAMES field position +#define NXMAC_ACCEPT_OTHER_MGMT_FRAMES_POS 15 +/// ACCEPT_BFMEE_FRAMES field bit +#define NXMAC_ACCEPT_BFMEE_FRAMES_BIT ((uint32_t)0x00004000) +/// ACCEPT_BFMEE_FRAMES field position +#define NXMAC_ACCEPT_BFMEE_FRAMES_POS 14 +/// ACCEPT_ALL_BEACON field bit +#define NXMAC_ACCEPT_ALL_BEACON_BIT ((uint32_t)0x00002000) +/// ACCEPT_ALL_BEACON field position +#define NXMAC_ACCEPT_ALL_BEACON_POS 13 +/// ACCEPT_NOT_EXPECTED_BA field bit +#define NXMAC_ACCEPT_NOT_EXPECTED_BA_BIT ((uint32_t)0x00001000) +/// ACCEPT_NOT_EXPECTED_BA field position +#define NXMAC_ACCEPT_NOT_EXPECTED_BA_POS 12 +/// ACCEPT_DECRYPT_ERROR_FRAMES field bit +#define NXMAC_ACCEPT_DECRYPT_ERROR_FRAMES_BIT ((uint32_t)0x00000800) +/// ACCEPT_DECRYPT_ERROR_FRAMES field position +#define NXMAC_ACCEPT_DECRYPT_ERROR_FRAMES_POS 11 +/// ACCEPT_BEACON field bit +#define NXMAC_ACCEPT_BEACON_BIT ((uint32_t)0x00000400) +/// ACCEPT_BEACON field position +#define NXMAC_ACCEPT_BEACON_POS 10 +/// ACCEPT_PROBE_RESP field bit +#define NXMAC_ACCEPT_PROBE_RESP_BIT ((uint32_t)0x00000200) +/// ACCEPT_PROBE_RESP field position +#define NXMAC_ACCEPT_PROBE_RESP_POS 9 +/// ACCEPT_PROBE_REQ field bit +#define NXMAC_ACCEPT_PROBE_REQ_BIT ((uint32_t)0x00000100) +/// ACCEPT_PROBE_REQ field position +#define NXMAC_ACCEPT_PROBE_REQ_POS 8 +/// ACCEPT_MY_UNICAST field bit +#define NXMAC_ACCEPT_MY_UNICAST_BIT ((uint32_t)0x00000080) +/// ACCEPT_MY_UNICAST field position +#define NXMAC_ACCEPT_MY_UNICAST_POS 7 +/// ACCEPT_UNICAST field bit +#define NXMAC_ACCEPT_UNICAST_BIT ((uint32_t)0x00000040) +/// ACCEPT_UNICAST field position +#define NXMAC_ACCEPT_UNICAST_POS 6 +/// ACCEPT_ERROR_FRAMES field bit +#define NXMAC_ACCEPT_ERROR_FRAMES_BIT ((uint32_t)0x00000020) +/// ACCEPT_ERROR_FRAMES field position +#define NXMAC_ACCEPT_ERROR_FRAMES_POS 5 +/// ACCEPT_OTHER_BSSID field bit +#define NXMAC_ACCEPT_OTHER_BSSID_BIT ((uint32_t)0x00000010) +/// ACCEPT_OTHER_BSSID field position +#define NXMAC_ACCEPT_OTHER_BSSID_POS 4 +/// ACCEPT_BROADCAST field bit +#define NXMAC_ACCEPT_BROADCAST_BIT ((uint32_t)0x00000008) +/// ACCEPT_BROADCAST field position +#define NXMAC_ACCEPT_BROADCAST_POS 3 +/// ACCEPT_MULTICAST field bit +#define NXMAC_ACCEPT_MULTICAST_BIT ((uint32_t)0x00000004) +/// ACCEPT_MULTICAST field position +#define NXMAC_ACCEPT_MULTICAST_POS 2 +/// DONT_DECRYPT field bit +#define NXMAC_DONT_DECRYPT_BIT ((uint32_t)0x00000002) +/// DONT_DECRYPT field position +#define NXMAC_DONT_DECRYPT_POS 1 +/// EXC_UNENCRYPTED field bit +#define NXMAC_EXC_UNENCRYPTED_BIT ((uint32_t)0x00000001) +/// EXC_UNENCRYPTED field position +#define NXMAC_EXC_UNENCRYPTED_POS 0 + +/// EN_DUPLICATE_DETECTION field reset value +#define NXMAC_EN_DUPLICATE_DETECTION_RST 0x0 +/// ACCEPT_UNKNOWN field reset value +#define NXMAC_ACCEPT_UNKNOWN_RST 0x0 +/// ACCEPT_OTHER_DATA_FRAMES field reset value +#define NXMAC_ACCEPT_OTHER_DATA_FRAMES_RST 0x0 +/// ACCEPT_QO_S_NULL field reset value +#define NXMAC_ACCEPT_QO_S_NULL_RST 0x1 +/// ACCEPT_QCFWO_DATA field reset value +#define NXMAC_ACCEPT_QCFWO_DATA_RST 0x0 +/// ACCEPT_Q_DATA field reset value +#define NXMAC_ACCEPT_Q_DATA_RST 0x1 +/// ACCEPT_CFWO_DATA field reset value +#define NXMAC_ACCEPT_CFWO_DATA_RST 0x0 +/// ACCEPT_DATA field reset value +#define NXMAC_ACCEPT_DATA_RST 0x1 +/// ACCEPT_OTHER_CNTRL_FRAMES field reset value +#define NXMAC_ACCEPT_OTHER_CNTRL_FRAMES_RST 0x0 +/// ACCEPT_CF_END field reset value +#define NXMAC_ACCEPT_CF_END_RST 0x0 +/// ACCEPT_ACK field reset value +#define NXMAC_ACCEPT_ACK_RST 0x0 +/// ACCEPT_CTS field reset value +#define NXMAC_ACCEPT_CTS_RST 0x0 +/// ACCEPT_RTS field reset value +#define NXMAC_ACCEPT_RTS_RST 0x0 +/// ACCEPT_PS_POLL field reset value +#define NXMAC_ACCEPT_PS_POLL_RST 0x1 +/// ACCEPT_BA field reset value +#define NXMAC_ACCEPT_BA_RST 0x1 +/// ACCEPT_BAR field reset value +#define NXMAC_ACCEPT_BAR_RST 0x1 +/// ACCEPT_OTHER_MGMT_FRAMES field reset value +#define NXMAC_ACCEPT_OTHER_MGMT_FRAMES_RST 0x1 +/// ACCEPT_BFMEE_FRAMES field reset value +#define NXMAC_ACCEPT_BFMEE_FRAMES_RST 0x0 +/// ACCEPT_ALL_BEACON field reset value +#define NXMAC_ACCEPT_ALL_BEACON_RST 0x0 +/// ACCEPT_NOT_EXPECTED_BA field reset value +#define NXMAC_ACCEPT_NOT_EXPECTED_BA_RST 0x0 +/// ACCEPT_DECRYPT_ERROR_FRAMES field reset value +#define NXMAC_ACCEPT_DECRYPT_ERROR_FRAMES_RST 0x0 +/// ACCEPT_BEACON field reset value +#define NXMAC_ACCEPT_BEACON_RST 0x1 +/// ACCEPT_PROBE_RESP field reset value +#define NXMAC_ACCEPT_PROBE_RESP_RST 0x1 +/// ACCEPT_PROBE_REQ field reset value +#define NXMAC_ACCEPT_PROBE_REQ_RST 0x1 +/// ACCEPT_MY_UNICAST field reset value +#define NXMAC_ACCEPT_MY_UNICAST_RST 0x1 +/// ACCEPT_UNICAST field reset value +#define NXMAC_ACCEPT_UNICAST_RST 0x0 +/// ACCEPT_ERROR_FRAMES field reset value +#define NXMAC_ACCEPT_ERROR_FRAMES_RST 0x0 +/// ACCEPT_OTHER_BSSID field reset value +#define NXMAC_ACCEPT_OTHER_BSSID_RST 0x0 +/// ACCEPT_BROADCAST field reset value +#define NXMAC_ACCEPT_BROADCAST_RST 0x1 +/// ACCEPT_MULTICAST field reset value +#define NXMAC_ACCEPT_MULTICAST_RST 0x0 +/// DONT_DECRYPT field reset value +#define NXMAC_DONT_DECRYPT_RST 0x0 +/// EXC_UNENCRYPTED field reset value +#define NXMAC_EXC_UNENCRYPTED_RST 0x0 + +/** + * @brief Constructs a value for the RX_CNTRL register given values for its fields + * and writes the value to the register. + * + * @param[in] acceptunknown - The value to use for the acceptUnknown field. + * @param[in] acceptotherdataframes - The value to use for the acceptOtherDataFrames field. + * @param[in] acceptqosnull - The value to use for the acceptQoSNull field. + * @param[in] acceptqcfwodata - The value to use for the acceptQCFWOData field. + * @param[in] acceptqdata - The value to use for the acceptQData field. + * @param[in] acceptcfwodata - The value to use for the acceptCFWOData field. + * @param[in] acceptdata - The value to use for the acceptData field. + * @param[in] acceptothercntrlframes - The value to use for the acceptOtherCntrlFrames field. + * @param[in] acceptcfend - The value to use for the acceptCFEnd field. + * @param[in] acceptack - The value to use for the acceptACK field. + * @param[in] acceptcts - The value to use for the acceptCTS field. + * @param[in] acceptrts - The value to use for the acceptRTS field. + * @param[in] acceptpspoll - The value to use for the acceptPSPoll field. + * @param[in] acceptba - The value to use for the acceptBA field. + * @param[in] acceptbar - The value to use for the acceptBAR field. + * @param[in] acceptothermgmtframes - The value to use for the acceptOtherMgmtFrames field. + * @param[in] acceptbfmeeframes - The value to use for the acceptBfmeeFrames field. + * @param[in] acceptallbeacon - The value to use for the acceptAllBeacon field. + * @param[in] acceptnotexpectedba - The value to use for the acceptNotExpectedBA field. + * @param[in] acceptdecrypterrorframes - The value to use for the acceptDecryptErrorFrames field. + * @param[in] acceptbeacon - The value to use for the acceptBeacon field. + * @param[in] acceptproberesp - The value to use for the acceptProbeResp field. + * @param[in] acceptprobereq - The value to use for the acceptProbeReq field. + * @param[in] acceptmyunicast - The value to use for the acceptMyUnicast field. + * @param[in] acceptunicast - The value to use for the acceptUnicast field. + * @param[in] accepterrorframes - The value to use for the acceptErrorFrames field. + * @param[in] acceptotherbssid - The value to use for the acceptOtherBSSID field. + * @param[in] acceptbroadcast - The value to use for the acceptBroadcast field. + * @param[in] acceptmulticast - The value to use for the acceptMulticast field. + * @param[in] dontdecrypt - The value to use for the dontDecrypt field. + * @param[in] excunencrypted - The value to use for the excUnencrypted field. + */ +__INLINE void nxmac_rx_cntrl_pack(uint8_t acceptunknown, uint8_t acceptotherdataframes, uint8_t acceptqosnull, uint8_t acceptqcfwodata, uint8_t acceptqdata, uint8_t acceptcfwodata, uint8_t acceptdata, uint8_t acceptothercntrlframes, uint8_t acceptcfend, uint8_t acceptack, uint8_t acceptcts, uint8_t acceptrts, uint8_t acceptpspoll, uint8_t acceptba, uint8_t acceptbar, uint8_t acceptothermgmtframes, uint8_t acceptbfmeeframes, uint8_t acceptallbeacon, uint8_t acceptnotexpectedba, uint8_t acceptdecrypterrorframes, uint8_t acceptbeacon, uint8_t acceptproberesp, uint8_t acceptprobereq, uint8_t acceptmyunicast, uint8_t acceptunicast, uint8_t accepterrorframes, uint8_t acceptotherbssid, uint8_t acceptbroadcast, uint8_t acceptmulticast, uint8_t dontdecrypt, uint8_t excunencrypted) +{ + ASSERT_ERR((((uint32_t)acceptunknown << 30) & ~((uint32_t)0x40000000)) == 0); + ASSERT_ERR((((uint32_t)acceptotherdataframes << 29) & ~((uint32_t)0x20000000)) == 0); + ASSERT_ERR((((uint32_t)acceptqosnull << 28) & ~((uint32_t)0x10000000)) == 0); + ASSERT_ERR((((uint32_t)acceptqcfwodata << 27) & ~((uint32_t)0x08000000)) == 0); + ASSERT_ERR((((uint32_t)acceptqdata << 26) & ~((uint32_t)0x04000000)) == 0); + ASSERT_ERR((((uint32_t)acceptcfwodata << 25) & ~((uint32_t)0x02000000)) == 0); + ASSERT_ERR((((uint32_t)acceptdata << 24) & ~((uint32_t)0x01000000)) == 0); + ASSERT_ERR((((uint32_t)acceptothercntrlframes << 23) & ~((uint32_t)0x00800000)) == 0); + ASSERT_ERR((((uint32_t)acceptcfend << 22) & ~((uint32_t)0x00400000)) == 0); + ASSERT_ERR((((uint32_t)acceptack << 21) & ~((uint32_t)0x00200000)) == 0); + ASSERT_ERR((((uint32_t)acceptcts << 20) & ~((uint32_t)0x00100000)) == 0); + ASSERT_ERR((((uint32_t)acceptrts << 19) & ~((uint32_t)0x00080000)) == 0); + ASSERT_ERR((((uint32_t)acceptpspoll << 18) & ~((uint32_t)0x00040000)) == 0); + ASSERT_ERR((((uint32_t)acceptba << 17) & ~((uint32_t)0x00020000)) == 0); + ASSERT_ERR((((uint32_t)acceptbar << 16) & ~((uint32_t)0x00010000)) == 0); + ASSERT_ERR((((uint32_t)acceptothermgmtframes << 15) & ~((uint32_t)0x00008000)) == 0); + ASSERT_ERR((((uint32_t)acceptbfmeeframes << 14) & ~((uint32_t)0x00004000)) == 0); + ASSERT_ERR((((uint32_t)acceptallbeacon << 13) & ~((uint32_t)0x00002000)) == 0); + ASSERT_ERR((((uint32_t)acceptnotexpectedba << 12) & ~((uint32_t)0x00001000)) == 0); + ASSERT_ERR((((uint32_t)acceptdecrypterrorframes << 11) & ~((uint32_t)0x00000800)) == 0); + ASSERT_ERR((((uint32_t)acceptbeacon << 10) & ~((uint32_t)0x00000400)) == 0); + ASSERT_ERR((((uint32_t)acceptproberesp << 9) & ~((uint32_t)0x00000200)) == 0); + ASSERT_ERR((((uint32_t)acceptprobereq << 8) & ~((uint32_t)0x00000100)) == 0); + ASSERT_ERR((((uint32_t)acceptmyunicast << 7) & ~((uint32_t)0x00000080)) == 0); + ASSERT_ERR((((uint32_t)acceptunicast << 6) & ~((uint32_t)0x00000040)) == 0); + ASSERT_ERR((((uint32_t)accepterrorframes << 5) & ~((uint32_t)0x00000020)) == 0); + ASSERT_ERR((((uint32_t)acceptotherbssid << 4) & ~((uint32_t)0x00000010)) == 0); + ASSERT_ERR((((uint32_t)acceptbroadcast << 3) & ~((uint32_t)0x00000008)) == 0); + ASSERT_ERR((((uint32_t)acceptmulticast << 2) & ~((uint32_t)0x00000004)) == 0); + ASSERT_ERR((((uint32_t)dontdecrypt << 1) & ~((uint32_t)0x00000002)) == 0); + ASSERT_ERR((((uint32_t)excunencrypted << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_RX_CNTRL_ADDR, ((uint32_t)acceptunknown << 30) | ((uint32_t)acceptotherdataframes << 29) | ((uint32_t)acceptqosnull << 28) | ((uint32_t)acceptqcfwodata << 27) | ((uint32_t)acceptqdata << 26) | ((uint32_t)acceptcfwodata << 25) | ((uint32_t)acceptdata << 24) | ((uint32_t)acceptothercntrlframes << 23) | ((uint32_t)acceptcfend << 22) | ((uint32_t)acceptack << 21) | ((uint32_t)acceptcts << 20) | ((uint32_t)acceptrts << 19) | ((uint32_t)acceptpspoll << 18) | ((uint32_t)acceptba << 17) | ((uint32_t)acceptbar << 16) | ((uint32_t)acceptothermgmtframes << 15) | ((uint32_t)acceptbfmeeframes << 14) | ((uint32_t)acceptallbeacon << 13) | ((uint32_t)acceptnotexpectedba << 12) | ((uint32_t)acceptdecrypterrorframes << 11) | ((uint32_t)acceptbeacon << 10) | ((uint32_t)acceptproberesp << 9) | ((uint32_t)acceptprobereq << 8) | ((uint32_t)acceptmyunicast << 7) | ((uint32_t)acceptunicast << 6) | ((uint32_t)accepterrorframes << 5) | ((uint32_t)acceptotherbssid << 4) | ((uint32_t)acceptbroadcast << 3) | ((uint32_t)acceptmulticast << 2) | ((uint32_t)dontdecrypt << 1) | ((uint32_t)excunencrypted << 0)); +} + +/** + * @brief Unpacks RX_CNTRL's fields from current value of the RX_CNTRL register. + * + * Reads the RX_CNTRL register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] enduplicatedetection - Will be populated with the current value of this field from the register. + * @param[out] acceptunknown - Will be populated with the current value of this field from the register. + * @param[out] acceptotherdataframes - Will be populated with the current value of this field from the register. + * @param[out] acceptqosnull - Will be populated with the current value of this field from the register. + * @param[out] acceptqcfwodata - Will be populated with the current value of this field from the register. + * @param[out] acceptqdata - Will be populated with the current value of this field from the register. + * @param[out] acceptcfwodata - Will be populated with the current value of this field from the register. + * @param[out] acceptdata - Will be populated with the current value of this field from the register. + * @param[out] acceptothercntrlframes - Will be populated with the current value of this field from the register. + * @param[out] acceptcfend - Will be populated with the current value of this field from the register. + * @param[out] acceptack - Will be populated with the current value of this field from the register. + * @param[out] acceptcts - Will be populated with the current value of this field from the register. + * @param[out] acceptrts - Will be populated with the current value of this field from the register. + * @param[out] acceptpspoll - Will be populated with the current value of this field from the register. + * @param[out] acceptba - Will be populated with the current value of this field from the register. + * @param[out] acceptbar - Will be populated with the current value of this field from the register. + * @param[out] acceptothermgmtframes - Will be populated with the current value of this field from the register. + * @param[out] acceptbfmeeframes - Will be populated with the current value of this field from the register. + * @param[out] acceptallbeacon - Will be populated with the current value of this field from the register. + * @param[out] acceptnotexpectedba - Will be populated with the current value of this field from the register. + * @param[out] acceptdecrypterrorframes - Will be populated with the current value of this field from the register. + * @param[out] acceptbeacon - Will be populated with the current value of this field from the register. + * @param[out] acceptproberesp - Will be populated with the current value of this field from the register. + * @param[out] acceptprobereq - Will be populated with the current value of this field from the register. + * @param[out] acceptmyunicast - Will be populated with the current value of this field from the register. + * @param[out] acceptunicast - Will be populated with the current value of this field from the register. + * @param[out] accepterrorframes - Will be populated with the current value of this field from the register. + * @param[out] acceptotherbssid - Will be populated with the current value of this field from the register. + * @param[out] acceptbroadcast - Will be populated with the current value of this field from the register. + * @param[out] acceptmulticast - Will be populated with the current value of this field from the register. + * @param[out] dontdecrypt - Will be populated with the current value of this field from the register. + * @param[out] excunencrypted - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_rx_cntrl_unpack(uint8_t *enduplicatedetection, uint8_t *acceptunknown, uint8_t *acceptotherdataframes, uint8_t *acceptqosnull, uint8_t *acceptqcfwodata, uint8_t *acceptqdata, uint8_t *acceptcfwodata, uint8_t *acceptdata, uint8_t *acceptothercntrlframes, uint8_t *acceptcfend, uint8_t *acceptack, uint8_t *acceptcts, uint8_t *acceptrts, uint8_t *acceptpspoll, uint8_t *acceptba, uint8_t *acceptbar, uint8_t *acceptothermgmtframes, uint8_t *acceptbfmeeframes, uint8_t *acceptallbeacon, uint8_t *acceptnotexpectedba, uint8_t *acceptdecrypterrorframes, uint8_t *acceptbeacon, uint8_t *acceptproberesp, uint8_t *acceptprobereq, uint8_t *acceptmyunicast, uint8_t *acceptunicast, uint8_t *accepterrorframes, uint8_t *acceptotherbssid, uint8_t *acceptbroadcast, uint8_t *acceptmulticast, uint8_t *dontdecrypt, uint8_t *excunencrypted) +{ + uint32_t localVal = REG_PL_RD(NXMAC_RX_CNTRL_ADDR); + + *enduplicatedetection = (localVal & ((uint32_t)0x80000000)) >> 31; + *acceptunknown = (localVal & ((uint32_t)0x40000000)) >> 30; + *acceptotherdataframes = (localVal & ((uint32_t)0x20000000)) >> 29; + *acceptqosnull = (localVal & ((uint32_t)0x10000000)) >> 28; + *acceptqcfwodata = (localVal & ((uint32_t)0x08000000)) >> 27; + *acceptqdata = (localVal & ((uint32_t)0x04000000)) >> 26; + *acceptcfwodata = (localVal & ((uint32_t)0x02000000)) >> 25; + *acceptdata = (localVal & ((uint32_t)0x01000000)) >> 24; + *acceptothercntrlframes = (localVal & ((uint32_t)0x00800000)) >> 23; + *acceptcfend = (localVal & ((uint32_t)0x00400000)) >> 22; + *acceptack = (localVal & ((uint32_t)0x00200000)) >> 21; + *acceptcts = (localVal & ((uint32_t)0x00100000)) >> 20; + *acceptrts = (localVal & ((uint32_t)0x00080000)) >> 19; + *acceptpspoll = (localVal & ((uint32_t)0x00040000)) >> 18; + *acceptba = (localVal & ((uint32_t)0x00020000)) >> 17; + *acceptbar = (localVal & ((uint32_t)0x00010000)) >> 16; + *acceptothermgmtframes = (localVal & ((uint32_t)0x00008000)) >> 15; + *acceptbfmeeframes = (localVal & ((uint32_t)0x00004000)) >> 14; + *acceptallbeacon = (localVal & ((uint32_t)0x00002000)) >> 13; + *acceptnotexpectedba = (localVal & ((uint32_t)0x00001000)) >> 12; + *acceptdecrypterrorframes = (localVal & ((uint32_t)0x00000800)) >> 11; + *acceptbeacon = (localVal & ((uint32_t)0x00000400)) >> 10; + *acceptproberesp = (localVal & ((uint32_t)0x00000200)) >> 9; + *acceptprobereq = (localVal & ((uint32_t)0x00000100)) >> 8; + *acceptmyunicast = (localVal & ((uint32_t)0x00000080)) >> 7; + *acceptunicast = (localVal & ((uint32_t)0x00000040)) >> 6; + *accepterrorframes = (localVal & ((uint32_t)0x00000020)) >> 5; + *acceptotherbssid = (localVal & ((uint32_t)0x00000010)) >> 4; + *acceptbroadcast = (localVal & ((uint32_t)0x00000008)) >> 3; + *acceptmulticast = (localVal & ((uint32_t)0x00000004)) >> 2; + *dontdecrypt = (localVal & ((uint32_t)0x00000002)) >> 1; + *excunencrypted = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +/** + * @brief Returns the current value of the enDuplicateDetection field in the RX_CNTRL register. + * + * The RX_CNTRL register will be read and the enDuplicateDetection field's value will be returned. + * + * @return The current value of the enDuplicateDetection field in the RX_CNTRL register. + */ +__INLINE uint8_t nxmac_en_duplicate_detection_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_RX_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +/** + * @brief Returns the current value of the acceptUnknown field in the RX_CNTRL register. + * + * The RX_CNTRL register will be read and the acceptUnknown field's value will be returned. + * + * @return The current value of the acceptUnknown field in the RX_CNTRL register. + */ +__INLINE uint8_t nxmac_accept_unknown_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_RX_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x40000000)) >> 30); +} + +/** + * @brief Sets the acceptUnknown field of the RX_CNTRL register. + * + * The RX_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] acceptunknown - The value to set the field to. + */ +__INLINE void nxmac_accept_unknown_setf(uint8_t acceptunknown) +{ + ASSERT_ERR((((uint32_t)acceptunknown << 30) & ~((uint32_t)0x40000000)) == 0); + REG_PL_WR(NXMAC_RX_CNTRL_ADDR, (REG_PL_RD(NXMAC_RX_CNTRL_ADDR) & ~((uint32_t)0x40000000)) | ((uint32_t)acceptunknown << 30)); +} + +/** + * @brief Returns the current value of the acceptOtherDataFrames field in the RX_CNTRL register. + * + * The RX_CNTRL register will be read and the acceptOtherDataFrames field's value will be returned. + * + * @return The current value of the acceptOtherDataFrames field in the RX_CNTRL register. + */ +__INLINE uint8_t nxmac_accept_other_data_frames_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_RX_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x20000000)) >> 29); +} + +/** + * @brief Sets the acceptOtherDataFrames field of the RX_CNTRL register. + * + * The RX_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] acceptotherdataframes - The value to set the field to. + */ +__INLINE void nxmac_accept_other_data_frames_setf(uint8_t acceptotherdataframes) +{ + ASSERT_ERR((((uint32_t)acceptotherdataframes << 29) & ~((uint32_t)0x20000000)) == 0); + REG_PL_WR(NXMAC_RX_CNTRL_ADDR, (REG_PL_RD(NXMAC_RX_CNTRL_ADDR) & ~((uint32_t)0x20000000)) | ((uint32_t)acceptotherdataframes << 29)); +} + +/** + * @brief Returns the current value of the acceptQoSNull field in the RX_CNTRL register. + * + * The RX_CNTRL register will be read and the acceptQoSNull field's value will be returned. + * + * @return The current value of the acceptQoSNull field in the RX_CNTRL register. + */ +__INLINE uint8_t nxmac_accept_qo_s_null_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_RX_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x10000000)) >> 28); +} + +/** + * @brief Sets the acceptQoSNull field of the RX_CNTRL register. + * + * The RX_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] acceptqosnull - The value to set the field to. + */ +__INLINE void nxmac_accept_qo_s_null_setf(uint8_t acceptqosnull) +{ + ASSERT_ERR((((uint32_t)acceptqosnull << 28) & ~((uint32_t)0x10000000)) == 0); + REG_PL_WR(NXMAC_RX_CNTRL_ADDR, (REG_PL_RD(NXMAC_RX_CNTRL_ADDR) & ~((uint32_t)0x10000000)) | ((uint32_t)acceptqosnull << 28)); +} + +/** + * @brief Returns the current value of the acceptQCFWOData field in the RX_CNTRL register. + * + * The RX_CNTRL register will be read and the acceptQCFWOData field's value will be returned. + * + * @return The current value of the acceptQCFWOData field in the RX_CNTRL register. + */ +__INLINE uint8_t nxmac_accept_qcfwo_data_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_RX_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x08000000)) >> 27); +} + +/** + * @brief Sets the acceptQCFWOData field of the RX_CNTRL register. + * + * The RX_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] acceptqcfwodata - The value to set the field to. + */ +__INLINE void nxmac_accept_qcfwo_data_setf(uint8_t acceptqcfwodata) +{ + ASSERT_ERR((((uint32_t)acceptqcfwodata << 27) & ~((uint32_t)0x08000000)) == 0); + REG_PL_WR(NXMAC_RX_CNTRL_ADDR, (REG_PL_RD(NXMAC_RX_CNTRL_ADDR) & ~((uint32_t)0x08000000)) | ((uint32_t)acceptqcfwodata << 27)); +} + +/** + * @brief Returns the current value of the acceptQData field in the RX_CNTRL register. + * + * The RX_CNTRL register will be read and the acceptQData field's value will be returned. + * + * @return The current value of the acceptQData field in the RX_CNTRL register. + */ +__INLINE uint8_t nxmac_accept_q_data_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_RX_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x04000000)) >> 26); +} + +/** + * @brief Sets the acceptQData field of the RX_CNTRL register. + * + * The RX_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] acceptqdata - The value to set the field to. + */ +__INLINE void nxmac_accept_q_data_setf(uint8_t acceptqdata) +{ + ASSERT_ERR((((uint32_t)acceptqdata << 26) & ~((uint32_t)0x04000000)) == 0); + REG_PL_WR(NXMAC_RX_CNTRL_ADDR, (REG_PL_RD(NXMAC_RX_CNTRL_ADDR) & ~((uint32_t)0x04000000)) | ((uint32_t)acceptqdata << 26)); +} + +/** + * @brief Returns the current value of the acceptCFWOData field in the RX_CNTRL register. + * + * The RX_CNTRL register will be read and the acceptCFWOData field's value will be returned. + * + * @return The current value of the acceptCFWOData field in the RX_CNTRL register. + */ +__INLINE uint8_t nxmac_accept_cfwo_data_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_RX_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x02000000)) >> 25); +} + +/** + * @brief Sets the acceptCFWOData field of the RX_CNTRL register. + * + * The RX_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] acceptcfwodata - The value to set the field to. + */ +__INLINE void nxmac_accept_cfwo_data_setf(uint8_t acceptcfwodata) +{ + ASSERT_ERR((((uint32_t)acceptcfwodata << 25) & ~((uint32_t)0x02000000)) == 0); + REG_PL_WR(NXMAC_RX_CNTRL_ADDR, (REG_PL_RD(NXMAC_RX_CNTRL_ADDR) & ~((uint32_t)0x02000000)) | ((uint32_t)acceptcfwodata << 25)); +} + +/** + * @brief Returns the current value of the acceptData field in the RX_CNTRL register. + * + * The RX_CNTRL register will be read and the acceptData field's value will be returned. + * + * @return The current value of the acceptData field in the RX_CNTRL register. + */ +__INLINE uint8_t nxmac_accept_data_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_RX_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x01000000)) >> 24); +} + +/** + * @brief Sets the acceptData field of the RX_CNTRL register. + * + * The RX_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] acceptdata - The value to set the field to. + */ +__INLINE void nxmac_accept_data_setf(uint8_t acceptdata) +{ + ASSERT_ERR((((uint32_t)acceptdata << 24) & ~((uint32_t)0x01000000)) == 0); + REG_PL_WR(NXMAC_RX_CNTRL_ADDR, (REG_PL_RD(NXMAC_RX_CNTRL_ADDR) & ~((uint32_t)0x01000000)) | ((uint32_t)acceptdata << 24)); +} + +/** + * @brief Returns the current value of the acceptOtherCntrlFrames field in the RX_CNTRL register. + * + * The RX_CNTRL register will be read and the acceptOtherCntrlFrames field's value will be returned. + * + * @return The current value of the acceptOtherCntrlFrames field in the RX_CNTRL register. + */ +__INLINE uint8_t nxmac_accept_other_cntrl_frames_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_RX_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x00800000)) >> 23); +} + +/** + * @brief Sets the acceptOtherCntrlFrames field of the RX_CNTRL register. + * + * The RX_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] acceptothercntrlframes - The value to set the field to. + */ +__INLINE void nxmac_accept_other_cntrl_frames_setf(uint8_t acceptothercntrlframes) +{ + ASSERT_ERR((((uint32_t)acceptothercntrlframes << 23) & ~((uint32_t)0x00800000)) == 0); + REG_PL_WR(NXMAC_RX_CNTRL_ADDR, (REG_PL_RD(NXMAC_RX_CNTRL_ADDR) & ~((uint32_t)0x00800000)) | ((uint32_t)acceptothercntrlframes << 23)); +} + +/** + * @brief Returns the current value of the acceptCFEnd field in the RX_CNTRL register. + * + * The RX_CNTRL register will be read and the acceptCFEnd field's value will be returned. + * + * @return The current value of the acceptCFEnd field in the RX_CNTRL register. + */ +__INLINE uint8_t nxmac_accept_cf_end_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_RX_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x00400000)) >> 22); +} + +/** + * @brief Sets the acceptCFEnd field of the RX_CNTRL register. + * + * The RX_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] acceptcfend - The value to set the field to. + */ +__INLINE void nxmac_accept_cf_end_setf(uint8_t acceptcfend) +{ + ASSERT_ERR((((uint32_t)acceptcfend << 22) & ~((uint32_t)0x00400000)) == 0); + REG_PL_WR(NXMAC_RX_CNTRL_ADDR, (REG_PL_RD(NXMAC_RX_CNTRL_ADDR) & ~((uint32_t)0x00400000)) | ((uint32_t)acceptcfend << 22)); +} + +/** + * @brief Returns the current value of the acceptACK field in the RX_CNTRL register. + * + * The RX_CNTRL register will be read and the acceptACK field's value will be returned. + * + * @return The current value of the acceptACK field in the RX_CNTRL register. + */ +__INLINE uint8_t nxmac_accept_ack_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_RX_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x00200000)) >> 21); +} + +/** + * @brief Sets the acceptACK field of the RX_CNTRL register. + * + * The RX_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] acceptack - The value to set the field to. + */ +__INLINE void nxmac_accept_ack_setf(uint8_t acceptack) +{ + ASSERT_ERR((((uint32_t)acceptack << 21) & ~((uint32_t)0x00200000)) == 0); + REG_PL_WR(NXMAC_RX_CNTRL_ADDR, (REG_PL_RD(NXMAC_RX_CNTRL_ADDR) & ~((uint32_t)0x00200000)) | ((uint32_t)acceptack << 21)); +} + +/** + * @brief Returns the current value of the acceptCTS field in the RX_CNTRL register. + * + * The RX_CNTRL register will be read and the acceptCTS field's value will be returned. + * + * @return The current value of the acceptCTS field in the RX_CNTRL register. + */ +__INLINE uint8_t nxmac_accept_cts_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_RX_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x00100000)) >> 20); +} + +/** + * @brief Sets the acceptCTS field of the RX_CNTRL register. + * + * The RX_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] acceptcts - The value to set the field to. + */ +__INLINE void nxmac_accept_cts_setf(uint8_t acceptcts) +{ + ASSERT_ERR((((uint32_t)acceptcts << 20) & ~((uint32_t)0x00100000)) == 0); + REG_PL_WR(NXMAC_RX_CNTRL_ADDR, (REG_PL_RD(NXMAC_RX_CNTRL_ADDR) & ~((uint32_t)0x00100000)) | ((uint32_t)acceptcts << 20)); +} + +/** + * @brief Returns the current value of the acceptRTS field in the RX_CNTRL register. + * + * The RX_CNTRL register will be read and the acceptRTS field's value will be returned. + * + * @return The current value of the acceptRTS field in the RX_CNTRL register. + */ +__INLINE uint8_t nxmac_accept_rts_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_RX_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x00080000)) >> 19); +} + +/** + * @brief Sets the acceptRTS field of the RX_CNTRL register. + * + * The RX_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] acceptrts - The value to set the field to. + */ +__INLINE void nxmac_accept_rts_setf(uint8_t acceptrts) +{ + ASSERT_ERR((((uint32_t)acceptrts << 19) & ~((uint32_t)0x00080000)) == 0); + REG_PL_WR(NXMAC_RX_CNTRL_ADDR, (REG_PL_RD(NXMAC_RX_CNTRL_ADDR) & ~((uint32_t)0x00080000)) | ((uint32_t)acceptrts << 19)); +} + +/** + * @brief Returns the current value of the acceptPSPoll field in the RX_CNTRL register. + * + * The RX_CNTRL register will be read and the acceptPSPoll field's value will be returned. + * + * @return The current value of the acceptPSPoll field in the RX_CNTRL register. + */ +__INLINE uint8_t nxmac_accept_ps_poll_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_RX_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x00040000)) >> 18); +} + +/** + * @brief Sets the acceptPSPoll field of the RX_CNTRL register. + * + * The RX_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] acceptpspoll - The value to set the field to. + */ +__INLINE void nxmac_accept_ps_poll_setf(uint8_t acceptpspoll) +{ + ASSERT_ERR((((uint32_t)acceptpspoll << 18) & ~((uint32_t)0x00040000)) == 0); + REG_PL_WR(NXMAC_RX_CNTRL_ADDR, (REG_PL_RD(NXMAC_RX_CNTRL_ADDR) & ~((uint32_t)0x00040000)) | ((uint32_t)acceptpspoll << 18)); +} + +/** + * @brief Returns the current value of the acceptBA field in the RX_CNTRL register. + * + * The RX_CNTRL register will be read and the acceptBA field's value will be returned. + * + * @return The current value of the acceptBA field in the RX_CNTRL register. + */ +__INLINE uint8_t nxmac_accept_ba_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_RX_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x00020000)) >> 17); +} + +/** + * @brief Sets the acceptBA field of the RX_CNTRL register. + * + * The RX_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] acceptba - The value to set the field to. + */ +__INLINE void nxmac_accept_ba_setf(uint8_t acceptba) +{ + ASSERT_ERR((((uint32_t)acceptba << 17) & ~((uint32_t)0x00020000)) == 0); + REG_PL_WR(NXMAC_RX_CNTRL_ADDR, (REG_PL_RD(NXMAC_RX_CNTRL_ADDR) & ~((uint32_t)0x00020000)) | ((uint32_t)acceptba << 17)); +} + +/** + * @brief Returns the current value of the acceptBAR field in the RX_CNTRL register. + * + * The RX_CNTRL register will be read and the acceptBAR field's value will be returned. + * + * @return The current value of the acceptBAR field in the RX_CNTRL register. + */ +__INLINE uint8_t nxmac_accept_bar_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_RX_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x00010000)) >> 16); +} + +/** + * @brief Sets the acceptBAR field of the RX_CNTRL register. + * + * The RX_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] acceptbar - The value to set the field to. + */ +__INLINE void nxmac_accept_bar_setf(uint8_t acceptbar) +{ + ASSERT_ERR((((uint32_t)acceptbar << 16) & ~((uint32_t)0x00010000)) == 0); + REG_PL_WR(NXMAC_RX_CNTRL_ADDR, (REG_PL_RD(NXMAC_RX_CNTRL_ADDR) & ~((uint32_t)0x00010000)) | ((uint32_t)acceptbar << 16)); +} + +/** + * @brief Returns the current value of the acceptOtherMgmtFrames field in the RX_CNTRL register. + * + * The RX_CNTRL register will be read and the acceptOtherMgmtFrames field's value will be returned. + * + * @return The current value of the acceptOtherMgmtFrames field in the RX_CNTRL register. + */ +__INLINE uint8_t nxmac_accept_other_mgmt_frames_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_RX_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x00008000)) >> 15); +} + +/** + * @brief Sets the acceptOtherMgmtFrames field of the RX_CNTRL register. + * + * The RX_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] acceptothermgmtframes - The value to set the field to. + */ +__INLINE void nxmac_accept_other_mgmt_frames_setf(uint8_t acceptothermgmtframes) +{ + ASSERT_ERR((((uint32_t)acceptothermgmtframes << 15) & ~((uint32_t)0x00008000)) == 0); + REG_PL_WR(NXMAC_RX_CNTRL_ADDR, (REG_PL_RD(NXMAC_RX_CNTRL_ADDR) & ~((uint32_t)0x00008000)) | ((uint32_t)acceptothermgmtframes << 15)); +} + +/** + * @brief Returns the current value of the acceptBfmeeFrames field in the RX_CNTRL register. + * + * The RX_CNTRL register will be read and the acceptBfmeeFrames field's value will be returned. + * + * @return The current value of the acceptBfmeeFrames field in the RX_CNTRL register. + */ +__INLINE uint8_t nxmac_accept_bfmee_frames_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_RX_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x00004000)) >> 14); +} + +/** + * @brief Sets the acceptBfmeeFrames field of the RX_CNTRL register. + * + * The RX_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] acceptbfmeeframes - The value to set the field to. + */ +__INLINE void nxmac_accept_bfmee_frames_setf(uint8_t acceptbfmeeframes) +{ + ASSERT_ERR((((uint32_t)acceptbfmeeframes << 14) & ~((uint32_t)0x00004000)) == 0); + REG_PL_WR(NXMAC_RX_CNTRL_ADDR, (REG_PL_RD(NXMAC_RX_CNTRL_ADDR) & ~((uint32_t)0x00004000)) | ((uint32_t)acceptbfmeeframes << 14)); +} + +/** + * @brief Returns the current value of the acceptAllBeacon field in the RX_CNTRL register. + * + * The RX_CNTRL register will be read and the acceptAllBeacon field's value will be returned. + * + * @return The current value of the acceptAllBeacon field in the RX_CNTRL register. + */ +__INLINE uint8_t nxmac_accept_all_beacon_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_RX_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x00002000)) >> 13); +} + +/** + * @brief Sets the acceptAllBeacon field of the RX_CNTRL register. + * + * The RX_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] acceptallbeacon - The value to set the field to. + */ +__INLINE void nxmac_accept_all_beacon_setf(uint8_t acceptallbeacon) +{ + ASSERT_ERR((((uint32_t)acceptallbeacon << 13) & ~((uint32_t)0x00002000)) == 0); + REG_PL_WR(NXMAC_RX_CNTRL_ADDR, (REG_PL_RD(NXMAC_RX_CNTRL_ADDR) & ~((uint32_t)0x00002000)) | ((uint32_t)acceptallbeacon << 13)); +} + +/** + * @brief Returns the current value of the acceptNotExpectedBA field in the RX_CNTRL register. + * + * The RX_CNTRL register will be read and the acceptNotExpectedBA field's value will be returned. + * + * @return The current value of the acceptNotExpectedBA field in the RX_CNTRL register. + */ +__INLINE uint8_t nxmac_accept_not_expected_ba_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_RX_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x00001000)) >> 12); +} + +/** + * @brief Sets the acceptNotExpectedBA field of the RX_CNTRL register. + * + * The RX_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] acceptnotexpectedba - The value to set the field to. + */ +__INLINE void nxmac_accept_not_expected_ba_setf(uint8_t acceptnotexpectedba) +{ + ASSERT_ERR((((uint32_t)acceptnotexpectedba << 12) & ~((uint32_t)0x00001000)) == 0); + REG_PL_WR(NXMAC_RX_CNTRL_ADDR, (REG_PL_RD(NXMAC_RX_CNTRL_ADDR) & ~((uint32_t)0x00001000)) | ((uint32_t)acceptnotexpectedba << 12)); +} + +/** + * @brief Returns the current value of the acceptDecryptErrorFrames field in the RX_CNTRL register. + * + * The RX_CNTRL register will be read and the acceptDecryptErrorFrames field's value will be returned. + * + * @return The current value of the acceptDecryptErrorFrames field in the RX_CNTRL register. + */ +__INLINE uint8_t nxmac_accept_decrypt_error_frames_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_RX_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x00000800)) >> 11); +} + +/** + * @brief Sets the acceptDecryptErrorFrames field of the RX_CNTRL register. + * + * The RX_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] acceptdecrypterrorframes - The value to set the field to. + */ +__INLINE void nxmac_accept_decrypt_error_frames_setf(uint8_t acceptdecrypterrorframes) +{ + ASSERT_ERR((((uint32_t)acceptdecrypterrorframes << 11) & ~((uint32_t)0x00000800)) == 0); + REG_PL_WR(NXMAC_RX_CNTRL_ADDR, (REG_PL_RD(NXMAC_RX_CNTRL_ADDR) & ~((uint32_t)0x00000800)) | ((uint32_t)acceptdecrypterrorframes << 11)); +} + +/** + * @brief Returns the current value of the acceptBeacon field in the RX_CNTRL register. + * + * The RX_CNTRL register will be read and the acceptBeacon field's value will be returned. + * + * @return The current value of the acceptBeacon field in the RX_CNTRL register. + */ +__INLINE uint8_t nxmac_accept_beacon_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_RX_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x00000400)) >> 10); +} + +/** + * @brief Sets the acceptBeacon field of the RX_CNTRL register. + * + * The RX_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] acceptbeacon - The value to set the field to. + */ +__INLINE void nxmac_accept_beacon_setf(uint8_t acceptbeacon) +{ + ASSERT_ERR((((uint32_t)acceptbeacon << 10) & ~((uint32_t)0x00000400)) == 0); + REG_PL_WR(NXMAC_RX_CNTRL_ADDR, (REG_PL_RD(NXMAC_RX_CNTRL_ADDR) & ~((uint32_t)0x00000400)) | ((uint32_t)acceptbeacon << 10)); +} + +/** + * @brief Returns the current value of the acceptProbeResp field in the RX_CNTRL register. + * + * The RX_CNTRL register will be read and the acceptProbeResp field's value will be returned. + * + * @return The current value of the acceptProbeResp field in the RX_CNTRL register. + */ +__INLINE uint8_t nxmac_accept_probe_resp_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_RX_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x00000200)) >> 9); +} + +/** + * @brief Sets the acceptProbeResp field of the RX_CNTRL register. + * + * The RX_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] acceptproberesp - The value to set the field to. + */ +__INLINE void nxmac_accept_probe_resp_setf(uint8_t acceptproberesp) +{ + ASSERT_ERR((((uint32_t)acceptproberesp << 9) & ~((uint32_t)0x00000200)) == 0); + REG_PL_WR(NXMAC_RX_CNTRL_ADDR, (REG_PL_RD(NXMAC_RX_CNTRL_ADDR) & ~((uint32_t)0x00000200)) | ((uint32_t)acceptproberesp << 9)); +} + +/** + * @brief Returns the current value of the acceptProbeReq field in the RX_CNTRL register. + * + * The RX_CNTRL register will be read and the acceptProbeReq field's value will be returned. + * + * @return The current value of the acceptProbeReq field in the RX_CNTRL register. + */ +__INLINE uint8_t nxmac_accept_probe_req_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_RX_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x00000100)) >> 8); +} + +/** + * @brief Sets the acceptProbeReq field of the RX_CNTRL register. + * + * The RX_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] acceptprobereq - The value to set the field to. + */ +__INLINE void nxmac_accept_probe_req_setf(uint8_t acceptprobereq) +{ + ASSERT_ERR((((uint32_t)acceptprobereq << 8) & ~((uint32_t)0x00000100)) == 0); + REG_PL_WR(NXMAC_RX_CNTRL_ADDR, (REG_PL_RD(NXMAC_RX_CNTRL_ADDR) & ~((uint32_t)0x00000100)) | ((uint32_t)acceptprobereq << 8)); +} + +/** + * @brief Returns the current value of the acceptMyUnicast field in the RX_CNTRL register. + * + * The RX_CNTRL register will be read and the acceptMyUnicast field's value will be returned. + * + * @return The current value of the acceptMyUnicast field in the RX_CNTRL register. + */ +__INLINE uint8_t nxmac_accept_my_unicast_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_RX_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x00000080)) >> 7); +} + +/** + * @brief Sets the acceptMyUnicast field of the RX_CNTRL register. + * + * The RX_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] acceptmyunicast - The value to set the field to. + */ +__INLINE void nxmac_accept_my_unicast_setf(uint8_t acceptmyunicast) +{ + ASSERT_ERR((((uint32_t)acceptmyunicast << 7) & ~((uint32_t)0x00000080)) == 0); + REG_PL_WR(NXMAC_RX_CNTRL_ADDR, (REG_PL_RD(NXMAC_RX_CNTRL_ADDR) & ~((uint32_t)0x00000080)) | ((uint32_t)acceptmyunicast << 7)); +} + +/** + * @brief Returns the current value of the acceptUnicast field in the RX_CNTRL register. + * + * The RX_CNTRL register will be read and the acceptUnicast field's value will be returned. + * + * @return The current value of the acceptUnicast field in the RX_CNTRL register. + */ +__INLINE uint8_t nxmac_accept_unicast_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_RX_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x00000040)) >> 6); +} + +/** + * @brief Sets the acceptUnicast field of the RX_CNTRL register. + * + * The RX_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] acceptunicast - The value to set the field to. + */ +__INLINE void nxmac_accept_unicast_setf(uint8_t acceptunicast) +{ + ASSERT_ERR((((uint32_t)acceptunicast << 6) & ~((uint32_t)0x00000040)) == 0); + REG_PL_WR(NXMAC_RX_CNTRL_ADDR, (REG_PL_RD(NXMAC_RX_CNTRL_ADDR) & ~((uint32_t)0x00000040)) | ((uint32_t)acceptunicast << 6)); +} + +/** + * @brief Returns the current value of the acceptErrorFrames field in the RX_CNTRL register. + * + * The RX_CNTRL register will be read and the acceptErrorFrames field's value will be returned. + * + * @return The current value of the acceptErrorFrames field in the RX_CNTRL register. + */ +__INLINE uint8_t nxmac_accept_error_frames_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_RX_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +/** + * @brief Sets the acceptErrorFrames field of the RX_CNTRL register. + * + * The RX_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] accepterrorframes - The value to set the field to. + */ +__INLINE void nxmac_accept_error_frames_setf(uint8_t accepterrorframes) +{ + ASSERT_ERR((((uint32_t)accepterrorframes << 5) & ~((uint32_t)0x00000020)) == 0); + REG_PL_WR(NXMAC_RX_CNTRL_ADDR, (REG_PL_RD(NXMAC_RX_CNTRL_ADDR) & ~((uint32_t)0x00000020)) | ((uint32_t)accepterrorframes << 5)); +} + +/** + * @brief Returns the current value of the acceptOtherBSSID field in the RX_CNTRL register. + * + * The RX_CNTRL register will be read and the acceptOtherBSSID field's value will be returned. + * + * @return The current value of the acceptOtherBSSID field in the RX_CNTRL register. + */ +__INLINE uint8_t nxmac_accept_other_bssid_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_RX_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +/** + * @brief Sets the acceptOtherBSSID field of the RX_CNTRL register. + * + * The RX_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] acceptotherbssid - The value to set the field to. + */ +__INLINE void nxmac_accept_other_bssid_setf(uint8_t acceptotherbssid) +{ + ASSERT_ERR((((uint32_t)acceptotherbssid << 4) & ~((uint32_t)0x00000010)) == 0); + REG_PL_WR(NXMAC_RX_CNTRL_ADDR, (REG_PL_RD(NXMAC_RX_CNTRL_ADDR) & ~((uint32_t)0x00000010)) | ((uint32_t)acceptotherbssid << 4)); +} + +/** + * @brief Returns the current value of the acceptBroadcast field in the RX_CNTRL register. + * + * The RX_CNTRL register will be read and the acceptBroadcast field's value will be returned. + * + * @return The current value of the acceptBroadcast field in the RX_CNTRL register. + */ +__INLINE uint8_t nxmac_accept_broadcast_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_RX_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +/** + * @brief Sets the acceptBroadcast field of the RX_CNTRL register. + * + * The RX_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] acceptbroadcast - The value to set the field to. + */ +__INLINE void nxmac_accept_broadcast_setf(uint8_t acceptbroadcast) +{ + ASSERT_ERR((((uint32_t)acceptbroadcast << 3) & ~((uint32_t)0x00000008)) == 0); + REG_PL_WR(NXMAC_RX_CNTRL_ADDR, (REG_PL_RD(NXMAC_RX_CNTRL_ADDR) & ~((uint32_t)0x00000008)) | ((uint32_t)acceptbroadcast << 3)); +} + +/** + * @brief Returns the current value of the acceptMulticast field in the RX_CNTRL register. + * + * The RX_CNTRL register will be read and the acceptMulticast field's value will be returned. + * + * @return The current value of the acceptMulticast field in the RX_CNTRL register. + */ +__INLINE uint8_t nxmac_accept_multicast_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_RX_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +/** + * @brief Sets the acceptMulticast field of the RX_CNTRL register. + * + * The RX_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] acceptmulticast - The value to set the field to. + */ +__INLINE void nxmac_accept_multicast_setf(uint8_t acceptmulticast) +{ + ASSERT_ERR((((uint32_t)acceptmulticast << 2) & ~((uint32_t)0x00000004)) == 0); + REG_PL_WR(NXMAC_RX_CNTRL_ADDR, (REG_PL_RD(NXMAC_RX_CNTRL_ADDR) & ~((uint32_t)0x00000004)) | ((uint32_t)acceptmulticast << 2)); +} + +/** + * @brief Returns the current value of the dontDecrypt field in the RX_CNTRL register. + * + * The RX_CNTRL register will be read and the dontDecrypt field's value will be returned. + * + * @return The current value of the dontDecrypt field in the RX_CNTRL register. + */ +__INLINE uint8_t nxmac_dont_decrypt_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_RX_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +/** + * @brief Sets the dontDecrypt field of the RX_CNTRL register. + * + * The RX_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] dontdecrypt - The value to set the field to. + */ +__INLINE void nxmac_dont_decrypt_setf(uint8_t dontdecrypt) +{ + ASSERT_ERR((((uint32_t)dontdecrypt << 1) & ~((uint32_t)0x00000002)) == 0); + REG_PL_WR(NXMAC_RX_CNTRL_ADDR, (REG_PL_RD(NXMAC_RX_CNTRL_ADDR) & ~((uint32_t)0x00000002)) | ((uint32_t)dontdecrypt << 1)); +} + +/** + * @brief Returns the current value of the excUnencrypted field in the RX_CNTRL register. + * + * The RX_CNTRL register will be read and the excUnencrypted field's value will be returned. + * + * @return The current value of the excUnencrypted field in the RX_CNTRL register. + */ +__INLINE uint8_t nxmac_exc_unencrypted_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_RX_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/** + * @brief Sets the excUnencrypted field of the RX_CNTRL register. + * + * The RX_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] excunencrypted - The value to set the field to. + */ +__INLINE void nxmac_exc_unencrypted_setf(uint8_t excunencrypted) +{ + ASSERT_ERR((((uint32_t)excunencrypted << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_RX_CNTRL_ADDR, (REG_PL_RD(NXMAC_RX_CNTRL_ADDR) & ~((uint32_t)0x00000001)) | ((uint32_t)excunencrypted << 0)); +} + +/// @} + +/** + * @name BCN_CNTRL_1 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:24          noBcnTxTime   0x0
+ *     23       impTBTTIn128Us   0
+ *  22:16        impTBTTPeriod   0x0
+ *  15:00            beaconInt   0x0
+ * 
+ * + * @{ + */ + +/// Address of the BCN_CNTRL_1 register +#define NXMAC_BCN_CNTRL_1_ADDR 0xC0000064 +/// Offset of the BCN_CNTRL_1 register from the base address +#define NXMAC_BCN_CNTRL_1_OFFSET 0x00000064 +/// Index of the BCN_CNTRL_1 register +#define NXMAC_BCN_CNTRL_1_INDEX 0x00000019 +/// Reset value of the BCN_CNTRL_1 register +#define NXMAC_BCN_CNTRL_1_RESET 0x00000000 + +/** + * @brief Returns the current value of the BCN_CNTRL_1 register. + * The BCN_CNTRL_1 register will be read and its value returned. + * @return The current value of the BCN_CNTRL_1 register. + */ +__INLINE uint32_t nxmac_bcn_cntrl_1_get(void) +{ + return REG_PL_RD(NXMAC_BCN_CNTRL_1_ADDR); +} + +/** + * @brief Sets the BCN_CNTRL_1 register to a value. + * The BCN_CNTRL_1 register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_bcn_cntrl_1_set(uint32_t value) +{ + REG_PL_WR(NXMAC_BCN_CNTRL_1_ADDR, value); +} + +// field definitions +/// NO_BCN_TX_TIME field mask +#define NXMAC_NO_BCN_TX_TIME_MASK ((uint32_t)0xFF000000) +/// NO_BCN_TX_TIME field LSB position +#define NXMAC_NO_BCN_TX_TIME_LSB 24 +/// NO_BCN_TX_TIME field width +#define NXMAC_NO_BCN_TX_TIME_WIDTH ((uint32_t)0x00000008) +/// IMP_TBTT_IN_128_US field bit +#define NXMAC_IMP_TBTT_IN_128_US_BIT ((uint32_t)0x00800000) +/// IMP_TBTT_IN_128_US field position +#define NXMAC_IMP_TBTT_IN_128_US_POS 23 +/// IMP_TBTT_PERIOD field mask +#define NXMAC_IMP_TBTT_PERIOD_MASK ((uint32_t)0x007F0000) +/// IMP_TBTT_PERIOD field LSB position +#define NXMAC_IMP_TBTT_PERIOD_LSB 16 +/// IMP_TBTT_PERIOD field width +#define NXMAC_IMP_TBTT_PERIOD_WIDTH ((uint32_t)0x00000007) +/// BEACON_INT field mask +#define NXMAC_BEACON_INT_MASK ((uint32_t)0x0000FFFF) +/// BEACON_INT field LSB position +#define NXMAC_BEACON_INT_LSB 0 +/// BEACON_INT field width +#define NXMAC_BEACON_INT_WIDTH ((uint32_t)0x00000010) + +/// NO_BCN_TX_TIME field reset value +#define NXMAC_NO_BCN_TX_TIME_RST 0x0 +/// IMP_TBTT_IN_128_US field reset value +#define NXMAC_IMP_TBTT_IN_128_US_RST 0x0 +/// IMP_TBTT_PERIOD field reset value +#define NXMAC_IMP_TBTT_PERIOD_RST 0x0 +/// BEACON_INT field reset value +#define NXMAC_BEACON_INT_RST 0x0 + +/** + * @brief Constructs a value for the BCN_CNTRL_1 register given values for its fields + * and writes the value to the register. + * + * @param[in] nobcntxtime - The value to use for the noBcnTxTime field. + * @param[in] imptbttin128us - The value to use for the impTBTTIn128Us field. + * @param[in] imptbttperiod - The value to use for the impTBTTPeriod field. + * @param[in] beaconint - The value to use for the beaconInt field. + */ +__INLINE void nxmac_bcn_cntrl_1_pack(uint8_t nobcntxtime, uint8_t imptbttin128us, uint8_t imptbttperiod, uint16_t beaconint) +{ + ASSERT_ERR((((uint32_t)nobcntxtime << 24) & ~((uint32_t)0xFF000000)) == 0); + ASSERT_ERR((((uint32_t)imptbttin128us << 23) & ~((uint32_t)0x00800000)) == 0); + ASSERT_ERR((((uint32_t)imptbttperiod << 16) & ~((uint32_t)0x007F0000)) == 0); + ASSERT_ERR((((uint32_t)beaconint << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_PL_WR(NXMAC_BCN_CNTRL_1_ADDR, ((uint32_t)nobcntxtime << 24) | ((uint32_t)imptbttin128us << 23) | ((uint32_t)imptbttperiod << 16) | ((uint32_t)beaconint << 0)); +} + +/** + * @brief Unpacks BCN_CNTRL_1's fields from current value of the BCN_CNTRL_1 register. + * + * Reads the BCN_CNTRL_1 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] nobcntxtime - Will be populated with the current value of this field from the register. + * @param[out] imptbttin128us - Will be populated with the current value of this field from the register. + * @param[out] imptbttperiod - Will be populated with the current value of this field from the register. + * @param[out] beaconint - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_bcn_cntrl_1_unpack(uint8_t *nobcntxtime, uint8_t *imptbttin128us, uint8_t *imptbttperiod, uint16_t *beaconint) +{ + uint32_t localVal = REG_PL_RD(NXMAC_BCN_CNTRL_1_ADDR); + + *nobcntxtime = (localVal & ((uint32_t)0xFF000000)) >> 24; + *imptbttin128us = (localVal & ((uint32_t)0x00800000)) >> 23; + *imptbttperiod = (localVal & ((uint32_t)0x007F0000)) >> 16; + *beaconint = (localVal & ((uint32_t)0x0000FFFF)) >> 0; +} + +/** + * @brief Returns the current value of the noBcnTxTime field in the BCN_CNTRL_1 register. + * + * The BCN_CNTRL_1 register will be read and the noBcnTxTime field's value will be returned. + * + * @return The current value of the noBcnTxTime field in the BCN_CNTRL_1 register. + */ +__INLINE uint8_t nxmac_no_bcn_tx_time_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_BCN_CNTRL_1_ADDR); + return ((localVal & ((uint32_t)0xFF000000)) >> 24); +} + +/** + * @brief Sets the noBcnTxTime field of the BCN_CNTRL_1 register. + * + * The BCN_CNTRL_1 register will be read, modified to contain the new field value, and written. + * + * @param[in] nobcntxtime - The value to set the field to. + */ +__INLINE void nxmac_no_bcn_tx_time_setf(uint8_t nobcntxtime) +{ + ASSERT_ERR((((uint32_t)nobcntxtime << 24) & ~((uint32_t)0xFF000000)) == 0); + REG_PL_WR(NXMAC_BCN_CNTRL_1_ADDR, (REG_PL_RD(NXMAC_BCN_CNTRL_1_ADDR) & ~((uint32_t)0xFF000000)) | ((uint32_t)nobcntxtime << 24)); +} + +/** + * @brief Returns the current value of the impTBTTIn128Us field in the BCN_CNTRL_1 register. + * + * The BCN_CNTRL_1 register will be read and the impTBTTIn128Us field's value will be returned. + * + * @return The current value of the impTBTTIn128Us field in the BCN_CNTRL_1 register. + */ +__INLINE uint8_t nxmac_imp_tbtt_in_128_us_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_BCN_CNTRL_1_ADDR); + return ((localVal & ((uint32_t)0x00800000)) >> 23); +} + +/** + * @brief Sets the impTBTTIn128Us field of the BCN_CNTRL_1 register. + * + * The BCN_CNTRL_1 register will be read, modified to contain the new field value, and written. + * + * @param[in] imptbttin128us - The value to set the field to. + */ +__INLINE void nxmac_imp_tbtt_in_128_us_setf(uint8_t imptbttin128us) +{ + ASSERT_ERR((((uint32_t)imptbttin128us << 23) & ~((uint32_t)0x00800000)) == 0); + REG_PL_WR(NXMAC_BCN_CNTRL_1_ADDR, (REG_PL_RD(NXMAC_BCN_CNTRL_1_ADDR) & ~((uint32_t)0x00800000)) | ((uint32_t)imptbttin128us << 23)); +} + +/** + * @brief Returns the current value of the impTBTTPeriod field in the BCN_CNTRL_1 register. + * + * The BCN_CNTRL_1 register will be read and the impTBTTPeriod field's value will be returned. + * + * @return The current value of the impTBTTPeriod field in the BCN_CNTRL_1 register. + */ +__INLINE uint8_t nxmac_imp_tbtt_period_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_BCN_CNTRL_1_ADDR); + return ((localVal & ((uint32_t)0x007F0000)) >> 16); +} + +/** + * @brief Sets the impTBTTPeriod field of the BCN_CNTRL_1 register. + * + * The BCN_CNTRL_1 register will be read, modified to contain the new field value, and written. + * + * @param[in] imptbttperiod - The value to set the field to. + */ +__INLINE void nxmac_imp_tbtt_period_setf(uint8_t imptbttperiod) +{ + ASSERT_ERR((((uint32_t)imptbttperiod << 16) & ~((uint32_t)0x007F0000)) == 0); + REG_PL_WR(NXMAC_BCN_CNTRL_1_ADDR, (REG_PL_RD(NXMAC_BCN_CNTRL_1_ADDR) & ~((uint32_t)0x007F0000)) | ((uint32_t)imptbttperiod << 16)); +} + +/** + * @brief Returns the current value of the beaconInt field in the BCN_CNTRL_1 register. + * + * The BCN_CNTRL_1 register will be read and the beaconInt field's value will be returned. + * + * @return The current value of the beaconInt field in the BCN_CNTRL_1 register. + */ +__INLINE uint16_t nxmac_beacon_int_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_BCN_CNTRL_1_ADDR); + return ((localVal & ((uint32_t)0x0000FFFF)) >> 0); +} + +/** + * @brief Sets the beaconInt field of the BCN_CNTRL_1 register. + * + * The BCN_CNTRL_1 register will be read, modified to contain the new field value, and written. + * + * @param[in] beaconint - The value to set the field to. + */ +__INLINE void nxmac_beacon_int_setf(uint16_t beaconint) +{ + ASSERT_ERR((((uint32_t)beaconint << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_PL_WR(NXMAC_BCN_CNTRL_1_ADDR, (REG_PL_RD(NXMAC_BCN_CNTRL_1_ADDR) & ~((uint32_t)0x0000FFFF)) | ((uint32_t)beaconint << 0)); +} + +/// @} + +/** + * @name BCN_CNTRL_2 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:16                  aid   0x0
+ *  15:08            timOffset   0x0
+ *  07:00      bcnUpdateOffset   0x0
+ * 
+ * + * @{ + */ + +/// Address of the BCN_CNTRL_2 register +#define NXMAC_BCN_CNTRL_2_ADDR 0xC0000068 +/// Offset of the BCN_CNTRL_2 register from the base address +#define NXMAC_BCN_CNTRL_2_OFFSET 0x00000068 +/// Index of the BCN_CNTRL_2 register +#define NXMAC_BCN_CNTRL_2_INDEX 0x0000001A +/// Reset value of the BCN_CNTRL_2 register +#define NXMAC_BCN_CNTRL_2_RESET 0x00000000 + +/** + * @brief Returns the current value of the BCN_CNTRL_2 register. + * The BCN_CNTRL_2 register will be read and its value returned. + * @return The current value of the BCN_CNTRL_2 register. + */ +__INLINE uint32_t nxmac_bcn_cntrl_2_get(void) +{ + return REG_PL_RD(NXMAC_BCN_CNTRL_2_ADDR); +} + +/** + * @brief Sets the BCN_CNTRL_2 register to a value. + * The BCN_CNTRL_2 register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_bcn_cntrl_2_set(uint32_t value) +{ + REG_PL_WR(NXMAC_BCN_CNTRL_2_ADDR, value); +} + +// field definitions +/// AID field mask +#define NXMAC_AID_MASK ((uint32_t)0xFFFF0000) +/// AID field LSB position +#define NXMAC_AID_LSB 16 +/// AID field width +#define NXMAC_AID_WIDTH ((uint32_t)0x00000010) +/// TIM_OFFSET field mask +#define NXMAC_TIM_OFFSET_MASK ((uint32_t)0x0000FF00) +/// TIM_OFFSET field LSB position +#define NXMAC_TIM_OFFSET_LSB 8 +/// TIM_OFFSET field width +#define NXMAC_TIM_OFFSET_WIDTH ((uint32_t)0x00000008) +/// BCN_UPDATE_OFFSET field mask +#define NXMAC_BCN_UPDATE_OFFSET_MASK ((uint32_t)0x000000FF) +/// BCN_UPDATE_OFFSET field LSB position +#define NXMAC_BCN_UPDATE_OFFSET_LSB 0 +/// BCN_UPDATE_OFFSET field width +#define NXMAC_BCN_UPDATE_OFFSET_WIDTH ((uint32_t)0x00000008) + +/// AID field reset value +#define NXMAC_AID_RST 0x0 +/// TIM_OFFSET field reset value +#define NXMAC_TIM_OFFSET_RST 0x0 +/// BCN_UPDATE_OFFSET field reset value +#define NXMAC_BCN_UPDATE_OFFSET_RST 0x0 + +/** + * @brief Constructs a value for the BCN_CNTRL_2 register given values for its fields + * and writes the value to the register. + * + * @param[in] aid - The value to use for the aid field. + * @param[in] timoffset - The value to use for the timOffset field. + * @param[in] bcnupdateoffset - The value to use for the bcnUpdateOffset field. + */ +__INLINE void nxmac_bcn_cntrl_2_pack(uint16_t aid, uint8_t timoffset, uint8_t bcnupdateoffset) +{ + ASSERT_ERR((((uint32_t)aid << 16) & ~((uint32_t)0xFFFF0000)) == 0); + ASSERT_ERR((((uint32_t)timoffset << 8) & ~((uint32_t)0x0000FF00)) == 0); + ASSERT_ERR((((uint32_t)bcnupdateoffset << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(NXMAC_BCN_CNTRL_2_ADDR, ((uint32_t)aid << 16) | ((uint32_t)timoffset << 8) | ((uint32_t)bcnupdateoffset << 0)); +} + +/** + * @brief Unpacks BCN_CNTRL_2's fields from current value of the BCN_CNTRL_2 register. + * + * Reads the BCN_CNTRL_2 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] aid - Will be populated with the current value of this field from the register. + * @param[out] timoffset - Will be populated with the current value of this field from the register. + * @param[out] bcnupdateoffset - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_bcn_cntrl_2_unpack(uint16_t *aid, uint8_t *timoffset, uint8_t *bcnupdateoffset) +{ + uint32_t localVal = REG_PL_RD(NXMAC_BCN_CNTRL_2_ADDR); + + *aid = (localVal & ((uint32_t)0xFFFF0000)) >> 16; + *timoffset = (localVal & ((uint32_t)0x0000FF00)) >> 8; + *bcnupdateoffset = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +/** + * @brief Returns the current value of the aid field in the BCN_CNTRL_2 register. + * + * The BCN_CNTRL_2 register will be read and the aid field's value will be returned. + * + * @return The current value of the aid field in the BCN_CNTRL_2 register. + */ +__INLINE uint16_t nxmac_aid_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_BCN_CNTRL_2_ADDR); + return ((localVal & ((uint32_t)0xFFFF0000)) >> 16); +} + +/** + * @brief Sets the aid field of the BCN_CNTRL_2 register. + * + * The BCN_CNTRL_2 register will be read, modified to contain the new field value, and written. + * + * @param[in] aid - The value to set the field to. + */ +__INLINE void nxmac_aid_setf(uint16_t aid) +{ + ASSERT_ERR((((uint32_t)aid << 16) & ~((uint32_t)0xFFFF0000)) == 0); + REG_PL_WR(NXMAC_BCN_CNTRL_2_ADDR, (REG_PL_RD(NXMAC_BCN_CNTRL_2_ADDR) & ~((uint32_t)0xFFFF0000)) | ((uint32_t)aid << 16)); +} + +/** + * @brief Returns the current value of the timOffset field in the BCN_CNTRL_2 register. + * + * The BCN_CNTRL_2 register will be read and the timOffset field's value will be returned. + * + * @return The current value of the timOffset field in the BCN_CNTRL_2 register. + */ +__INLINE uint8_t nxmac_tim_offset_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_BCN_CNTRL_2_ADDR); + return ((localVal & ((uint32_t)0x0000FF00)) >> 8); +} + +/** + * @brief Sets the timOffset field of the BCN_CNTRL_2 register. + * + * The BCN_CNTRL_2 register will be read, modified to contain the new field value, and written. + * + * @param[in] timoffset - The value to set the field to. + */ +__INLINE void nxmac_tim_offset_setf(uint8_t timoffset) +{ + ASSERT_ERR((((uint32_t)timoffset << 8) & ~((uint32_t)0x0000FF00)) == 0); + REG_PL_WR(NXMAC_BCN_CNTRL_2_ADDR, (REG_PL_RD(NXMAC_BCN_CNTRL_2_ADDR) & ~((uint32_t)0x0000FF00)) | ((uint32_t)timoffset << 8)); +} + +/** + * @brief Returns the current value of the bcnUpdateOffset field in the BCN_CNTRL_2 register. + * + * The BCN_CNTRL_2 register will be read and the bcnUpdateOffset field's value will be returned. + * + * @return The current value of the bcnUpdateOffset field in the BCN_CNTRL_2 register. + */ +__INLINE uint8_t nxmac_bcn_update_offset_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_BCN_CNTRL_2_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +/** + * @brief Sets the bcnUpdateOffset field of the BCN_CNTRL_2 register. + * + * The BCN_CNTRL_2 register will be read, modified to contain the new field value, and written. + * + * @param[in] bcnupdateoffset - The value to set the field to. + */ +__INLINE void nxmac_bcn_update_offset_setf(uint8_t bcnupdateoffset) +{ + ASSERT_ERR((((uint32_t)bcnupdateoffset << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(NXMAC_BCN_CNTRL_2_ADDR, (REG_PL_RD(NXMAC_BCN_CNTRL_2_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)bcnupdateoffset << 0)); +} + +/// @} + +/** + * @name DTIM_CFP_1 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31      dtimUpdatedBySW   0
+ *  15:08            cfpPeriod   0x0
+ *  07:00           dtimPeriod   0x0
+ * 
+ * + * @{ + */ + +/// Address of the DTIM_CFP_1 register +#define NXMAC_DTIM_CFP_1_ADDR 0xC0000090 +/// Offset of the DTIM_CFP_1 register from the base address +#define NXMAC_DTIM_CFP_1_OFFSET 0x00000090 +/// Index of the DTIM_CFP_1 register +#define NXMAC_DTIM_CFP_1_INDEX 0x00000024 +/// Reset value of the DTIM_CFP_1 register +#define NXMAC_DTIM_CFP_1_RESET 0x00000000 + +/** + * @brief Returns the current value of the DTIM_CFP_1 register. + * The DTIM_CFP_1 register will be read and its value returned. + * @return The current value of the DTIM_CFP_1 register. + */ +__INLINE uint32_t nxmac_dtim_cfp_1_get(void) +{ + return REG_PL_RD(NXMAC_DTIM_CFP_1_ADDR); +} + +/** + * @brief Sets the DTIM_CFP_1 register to a value. + * The DTIM_CFP_1 register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_dtim_cfp_1_set(uint32_t value) +{ + REG_PL_WR(NXMAC_DTIM_CFP_1_ADDR, value); +} + +// field definitions +/// DTIM_UPDATED_BY_SW field bit +#define NXMAC_DTIM_UPDATED_BY_SW_BIT ((uint32_t)0x80000000) +/// DTIM_UPDATED_BY_SW field position +#define NXMAC_DTIM_UPDATED_BY_SW_POS 31 +/// CFP_PERIOD field mask +#define NXMAC_CFP_PERIOD_MASK ((uint32_t)0x0000FF00) +/// CFP_PERIOD field LSB position +#define NXMAC_CFP_PERIOD_LSB 8 +/// CFP_PERIOD field width +#define NXMAC_CFP_PERIOD_WIDTH ((uint32_t)0x00000008) +/// DTIM_PERIOD field mask +#define NXMAC_DTIM_PERIOD_MASK ((uint32_t)0x000000FF) +/// DTIM_PERIOD field LSB position +#define NXMAC_DTIM_PERIOD_LSB 0 +/// DTIM_PERIOD field width +#define NXMAC_DTIM_PERIOD_WIDTH ((uint32_t)0x00000008) + +/// DTIM_UPDATED_BY_SW field reset value +#define NXMAC_DTIM_UPDATED_BY_SW_RST 0x0 +/// CFP_PERIOD field reset value +#define NXMAC_CFP_PERIOD_RST 0x0 +/// DTIM_PERIOD field reset value +#define NXMAC_DTIM_PERIOD_RST 0x0 + +/** + * @brief Constructs a value for the DTIM_CFP_1 register given values for its fields + * and writes the value to the register. + * + * @param[in] dtimupdatedbysw - The value to use for the dtimUpdatedBySW field. + * @param[in] cfpperiod - The value to use for the cfpPeriod field. + * @param[in] dtimperiod - The value to use for the dtimPeriod field. + */ +__INLINE void nxmac_dtim_cfp_1_pack(uint8_t dtimupdatedbysw, uint8_t cfpperiod, uint8_t dtimperiod) +{ + ASSERT_ERR((((uint32_t)dtimupdatedbysw << 31) & ~((uint32_t)0x80000000)) == 0); + ASSERT_ERR((((uint32_t)cfpperiod << 8) & ~((uint32_t)0x0000FF00)) == 0); + ASSERT_ERR((((uint32_t)dtimperiod << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(NXMAC_DTIM_CFP_1_ADDR, ((uint32_t)dtimupdatedbysw << 31) | ((uint32_t)cfpperiod << 8) | ((uint32_t)dtimperiod << 0)); +} + +/** + * @brief Unpacks DTIM_CFP_1's fields from current value of the DTIM_CFP_1 register. + * + * Reads the DTIM_CFP_1 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] dtimupdatedbysw - Will be populated with the current value of this field from the register. + * @param[out] cfpperiod - Will be populated with the current value of this field from the register. + * @param[out] dtimperiod - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_dtim_cfp_1_unpack(uint8_t *dtimupdatedbysw, uint8_t *cfpperiod, uint8_t *dtimperiod) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DTIM_CFP_1_ADDR); + + *dtimupdatedbysw = (localVal & ((uint32_t)0x80000000)) >> 31; + *cfpperiod = (localVal & ((uint32_t)0x0000FF00)) >> 8; + *dtimperiod = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +/** + * @brief Returns the current value of the dtimUpdatedBySW field in the DTIM_CFP_1 register. + * + * The DTIM_CFP_1 register will be read and the dtimUpdatedBySW field's value will be returned. + * + * @return The current value of the dtimUpdatedBySW field in the DTIM_CFP_1 register. + */ +__INLINE uint8_t nxmac_dtim_updated_by_sw_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DTIM_CFP_1_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +/** + * @brief Sets the dtimUpdatedBySW field of the DTIM_CFP_1 register. + * + * The DTIM_CFP_1 register will be read, modified to contain the new field value, and written. + * + * @param[in] dtimupdatedbysw - The value to set the field to. + */ +__INLINE void nxmac_dtim_updated_by_sw_setf(uint8_t dtimupdatedbysw) +{ + ASSERT_ERR((((uint32_t)dtimupdatedbysw << 31) & ~((uint32_t)0x80000000)) == 0); + REG_PL_WR(NXMAC_DTIM_CFP_1_ADDR, (REG_PL_RD(NXMAC_DTIM_CFP_1_ADDR) & ~((uint32_t)0x80000000)) | ((uint32_t)dtimupdatedbysw << 31)); +} + +/** + * @brief Returns the current value of the cfpPeriod field in the DTIM_CFP_1 register. + * + * The DTIM_CFP_1 register will be read and the cfpPeriod field's value will be returned. + * + * @return The current value of the cfpPeriod field in the DTIM_CFP_1 register. + */ +__INLINE uint8_t nxmac_cfp_period_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DTIM_CFP_1_ADDR); + return ((localVal & ((uint32_t)0x0000FF00)) >> 8); +} + +/** + * @brief Sets the cfpPeriod field of the DTIM_CFP_1 register. + * + * The DTIM_CFP_1 register will be read, modified to contain the new field value, and written. + * + * @param[in] cfpperiod - The value to set the field to. + */ +__INLINE void nxmac_cfp_period_setf(uint8_t cfpperiod) +{ + ASSERT_ERR((((uint32_t)cfpperiod << 8) & ~((uint32_t)0x0000FF00)) == 0); + REG_PL_WR(NXMAC_DTIM_CFP_1_ADDR, (REG_PL_RD(NXMAC_DTIM_CFP_1_ADDR) & ~((uint32_t)0x0000FF00)) | ((uint32_t)cfpperiod << 8)); +} + +/** + * @brief Returns the current value of the dtimPeriod field in the DTIM_CFP_1 register. + * + * The DTIM_CFP_1 register will be read and the dtimPeriod field's value will be returned. + * + * @return The current value of the dtimPeriod field in the DTIM_CFP_1 register. + */ +__INLINE uint8_t nxmac_dtim_period_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DTIM_CFP_1_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +/** + * @brief Sets the dtimPeriod field of the DTIM_CFP_1 register. + * + * The DTIM_CFP_1 register will be read, modified to contain the new field value, and written. + * + * @param[in] dtimperiod - The value to set the field to. + */ +__INLINE void nxmac_dtim_period_setf(uint8_t dtimperiod) +{ + ASSERT_ERR((((uint32_t)dtimperiod << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(NXMAC_DTIM_CFP_1_ADDR, (REG_PL_RD(NXMAC_DTIM_CFP_1_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)dtimperiod << 0)); +} + +/// @} + +/** + * @name DTIM_CFP_2 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00       cfpMaxDuration   0x0
+ * 
+ * + * @{ + */ + +/// Address of the DTIM_CFP_2 register +#define NXMAC_DTIM_CFP_2_ADDR 0xC0000094 +/// Offset of the DTIM_CFP_2 register from the base address +#define NXMAC_DTIM_CFP_2_OFFSET 0x00000094 +/// Index of the DTIM_CFP_2 register +#define NXMAC_DTIM_CFP_2_INDEX 0x00000025 +/// Reset value of the DTIM_CFP_2 register +#define NXMAC_DTIM_CFP_2_RESET 0x00000000 + +/** + * @brief Returns the current value of the DTIM_CFP_2 register. + * The DTIM_CFP_2 register will be read and its value returned. + * @return The current value of the DTIM_CFP_2 register. + */ +__INLINE uint32_t nxmac_dtim_cfp_2_get(void) +{ + return REG_PL_RD(NXMAC_DTIM_CFP_2_ADDR); +} + +/** + * @brief Sets the DTIM_CFP_2 register to a value. + * The DTIM_CFP_2 register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_dtim_cfp_2_set(uint32_t value) +{ + REG_PL_WR(NXMAC_DTIM_CFP_2_ADDR, value); +} + +// field definitions +/// CFP_MAX_DURATION field mask +#define NXMAC_CFP_MAX_DURATION_MASK ((uint32_t)0x0000FFFF) +/// CFP_MAX_DURATION field LSB position +#define NXMAC_CFP_MAX_DURATION_LSB 0 +/// CFP_MAX_DURATION field width +#define NXMAC_CFP_MAX_DURATION_WIDTH ((uint32_t)0x00000010) + +/// CFP_MAX_DURATION field reset value +#define NXMAC_CFP_MAX_DURATION_RST 0x0 + +/** + * @brief Returns the current value of the cfpMaxDuration field in the DTIM_CFP_2 register. + * + * The DTIM_CFP_2 register will be read and the cfpMaxDuration field's value will be returned. + * + * @return The current value of the cfpMaxDuration field in the DTIM_CFP_2 register. + */ +__INLINE uint16_t nxmac_cfp_max_duration_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DTIM_CFP_2_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the cfpMaxDuration field of the DTIM_CFP_2 register. + * + * The DTIM_CFP_2 register will be read, modified to contain the new field value, and written. + * + * @param[in] cfpmaxduration - The value to set the field to. + */ +__INLINE void nxmac_cfp_max_duration_setf(uint16_t cfpmaxduration) +{ + ASSERT_ERR((((uint32_t)cfpmaxduration << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_PL_WR(NXMAC_DTIM_CFP_2_ADDR, (uint32_t)cfpmaxduration << 0); +} + +/// @} + +/** + * @name RETRY_LIMITS register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:08   dot11LongRetryLimit   0x4
+ *  07:00   dot11ShortRetryLimit   0x7
+ * 
+ * + * @{ + */ + +/// Address of the RETRY_LIMITS register +#define NXMAC_RETRY_LIMITS_ADDR 0xC0000098 +/// Offset of the RETRY_LIMITS register from the base address +#define NXMAC_RETRY_LIMITS_OFFSET 0x00000098 +/// Index of the RETRY_LIMITS register +#define NXMAC_RETRY_LIMITS_INDEX 0x00000026 +/// Reset value of the RETRY_LIMITS register +#define NXMAC_RETRY_LIMITS_RESET 0x00000407 + +/** + * @brief Returns the current value of the RETRY_LIMITS register. + * The RETRY_LIMITS register will be read and its value returned. + * @return The current value of the RETRY_LIMITS register. + */ +__INLINE uint32_t nxmac_retry_limits_get(void) +{ + return REG_PL_RD(NXMAC_RETRY_LIMITS_ADDR); +} + +/** + * @brief Sets the RETRY_LIMITS register to a value. + * The RETRY_LIMITS register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_retry_limits_set(uint32_t value) +{ + REG_PL_WR(NXMAC_RETRY_LIMITS_ADDR, value); +} + +// field definitions +/// DOT_11_LONG_RETRY_LIMIT field mask +#define NXMAC_DOT_11_LONG_RETRY_LIMIT_MASK ((uint32_t)0x0000FF00) +/// DOT_11_LONG_RETRY_LIMIT field LSB position +#define NXMAC_DOT_11_LONG_RETRY_LIMIT_LSB 8 +/// DOT_11_LONG_RETRY_LIMIT field width +#define NXMAC_DOT_11_LONG_RETRY_LIMIT_WIDTH ((uint32_t)0x00000008) +/// DOT_11_SHORT_RETRY_LIMIT field mask +#define NXMAC_DOT_11_SHORT_RETRY_LIMIT_MASK ((uint32_t)0x000000FF) +/// DOT_11_SHORT_RETRY_LIMIT field LSB position +#define NXMAC_DOT_11_SHORT_RETRY_LIMIT_LSB 0 +/// DOT_11_SHORT_RETRY_LIMIT field width +#define NXMAC_DOT_11_SHORT_RETRY_LIMIT_WIDTH ((uint32_t)0x00000008) + +/// DOT_11_LONG_RETRY_LIMIT field reset value +#define NXMAC_DOT_11_LONG_RETRY_LIMIT_RST 0x4 +/// DOT_11_SHORT_RETRY_LIMIT field reset value +#define NXMAC_DOT_11_SHORT_RETRY_LIMIT_RST 0x7 + +/** + * @brief Constructs a value for the RETRY_LIMITS register given values for its fields + * and writes the value to the register. + * + * @param[in] dot11longretrylimit - The value to use for the dot11LongRetryLimit field. + * @param[in] dot11shortretrylimit - The value to use for the dot11ShortRetryLimit field. + */ +__INLINE void nxmac_retry_limits_pack(uint8_t dot11longretrylimit, uint8_t dot11shortretrylimit) +{ + ASSERT_ERR((((uint32_t)dot11longretrylimit << 8) & ~((uint32_t)0x0000FF00)) == 0); + ASSERT_ERR((((uint32_t)dot11shortretrylimit << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(NXMAC_RETRY_LIMITS_ADDR, ((uint32_t)dot11longretrylimit << 8) | ((uint32_t)dot11shortretrylimit << 0)); +} + +/** + * @brief Unpacks RETRY_LIMITS's fields from current value of the RETRY_LIMITS register. + * + * Reads the RETRY_LIMITS register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] dot11longretrylimit - Will be populated with the current value of this field from the register. + * @param[out] dot11shortretrylimit - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_retry_limits_unpack(uint8_t *dot11longretrylimit, uint8_t *dot11shortretrylimit) +{ + uint32_t localVal = REG_PL_RD(NXMAC_RETRY_LIMITS_ADDR); + + *dot11longretrylimit = (localVal & ((uint32_t)0x0000FF00)) >> 8; + *dot11shortretrylimit = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +/** + * @brief Returns the current value of the dot11LongRetryLimit field in the RETRY_LIMITS register. + * + * The RETRY_LIMITS register will be read and the dot11LongRetryLimit field's value will be returned. + * + * @return The current value of the dot11LongRetryLimit field in the RETRY_LIMITS register. + */ +__INLINE uint8_t nxmac_dot_11_long_retry_limit_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_RETRY_LIMITS_ADDR); + return ((localVal & ((uint32_t)0x0000FF00)) >> 8); +} + +/** + * @brief Sets the dot11LongRetryLimit field of the RETRY_LIMITS register. + * + * The RETRY_LIMITS register will be read, modified to contain the new field value, and written. + * + * @param[in] dot11longretrylimit - The value to set the field to. + */ +__INLINE void nxmac_dot_11_long_retry_limit_setf(uint8_t dot11longretrylimit) +{ + ASSERT_ERR((((uint32_t)dot11longretrylimit << 8) & ~((uint32_t)0x0000FF00)) == 0); + REG_PL_WR(NXMAC_RETRY_LIMITS_ADDR, (REG_PL_RD(NXMAC_RETRY_LIMITS_ADDR) & ~((uint32_t)0x0000FF00)) | ((uint32_t)dot11longretrylimit << 8)); +} + +/** + * @brief Returns the current value of the dot11ShortRetryLimit field in the RETRY_LIMITS register. + * + * The RETRY_LIMITS register will be read and the dot11ShortRetryLimit field's value will be returned. + * + * @return The current value of the dot11ShortRetryLimit field in the RETRY_LIMITS register. + */ +__INLINE uint8_t nxmac_dot_11_short_retry_limit_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_RETRY_LIMITS_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +/** + * @brief Sets the dot11ShortRetryLimit field of the RETRY_LIMITS register. + * + * The RETRY_LIMITS register will be read, modified to contain the new field value, and written. + * + * @param[in] dot11shortretrylimit - The value to set the field to. + */ +__INLINE void nxmac_dot_11_short_retry_limit_setf(uint8_t dot11shortretrylimit) +{ + ASSERT_ERR((((uint32_t)dot11shortretrylimit << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(NXMAC_RETRY_LIMITS_ADDR, (REG_PL_RD(NXMAC_RETRY_LIMITS_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)dot11shortretrylimit << 0)); +} + +/// @} + +/** + * @name BB_SERVICE register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  28:26            maxPHYNtx   0x2
+ *  23:16           bbServiceB   0x0
+ *  15:00           bbServiceA   0x0
+ * 
+ * + * @{ + */ + +/// Address of the BB_SERVICE register +#define NXMAC_BB_SERVICE_ADDR 0xC000009C +/// Offset of the BB_SERVICE register from the base address +#define NXMAC_BB_SERVICE_OFFSET 0x0000009C +/// Index of the BB_SERVICE register +#define NXMAC_BB_SERVICE_INDEX 0x00000027 +/// Reset value of the BB_SERVICE register +#define NXMAC_BB_SERVICE_RESET 0x08000000 + +/** + * @brief Returns the current value of the BB_SERVICE register. + * The BB_SERVICE register will be read and its value returned. + * @return The current value of the BB_SERVICE register. + */ +__INLINE uint32_t nxmac_bb_service_get(void) +{ + return REG_PL_RD(NXMAC_BB_SERVICE_ADDR); +} + +/** + * @brief Sets the BB_SERVICE register to a value. + * The BB_SERVICE register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_bb_service_set(uint32_t value) +{ + REG_PL_WR(NXMAC_BB_SERVICE_ADDR, value); +} + +// field definitions +/// MAX_PHY_NTX field mask +#define NXMAC_MAX_PHY_NTX_MASK ((uint32_t)0x1C000000) +/// MAX_PHY_NTX field LSB position +#define NXMAC_MAX_PHY_NTX_LSB 26 +/// MAX_PHY_NTX field width +#define NXMAC_MAX_PHY_NTX_WIDTH ((uint32_t)0x00000003) +/// BB_SERVICE_B field mask +#define NXMAC_BB_SERVICE_B_MASK ((uint32_t)0x00FF0000) +/// BB_SERVICE_B field LSB position +#define NXMAC_BB_SERVICE_B_LSB 16 +/// BB_SERVICE_B field width +#define NXMAC_BB_SERVICE_B_WIDTH ((uint32_t)0x00000008) +/// BB_SERVICE_A field mask +#define NXMAC_BB_SERVICE_A_MASK ((uint32_t)0x0000FFFF) +/// BB_SERVICE_A field LSB position +#define NXMAC_BB_SERVICE_A_LSB 0 +/// BB_SERVICE_A field width +#define NXMAC_BB_SERVICE_A_WIDTH ((uint32_t)0x00000010) + +/// MAX_PHY_NTX field reset value +#define NXMAC_MAX_PHY_NTX_RST 0x2 +/// BB_SERVICE_B field reset value +#define NXMAC_BB_SERVICE_B_RST 0x0 +/// BB_SERVICE_A field reset value +#define NXMAC_BB_SERVICE_A_RST 0x0 + +/** + * @brief Constructs a value for the BB_SERVICE register given values for its fields + * and writes the value to the register. + * + * @param[in] maxphyntx - The value to use for the maxPHYNtx field. + * @param[in] bbserviceb - The value to use for the bbServiceB field. + * @param[in] bbservicea - The value to use for the bbServiceA field. + */ +__INLINE void nxmac_bb_service_pack(uint8_t maxphyntx, uint8_t bbserviceb, uint16_t bbservicea) +{ + ASSERT_ERR((((uint32_t)maxphyntx << 26) & ~((uint32_t)0x1C000000)) == 0); + ASSERT_ERR((((uint32_t)bbserviceb << 16) & ~((uint32_t)0x00FF0000)) == 0); + ASSERT_ERR((((uint32_t)bbservicea << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_PL_WR(NXMAC_BB_SERVICE_ADDR, ((uint32_t)maxphyntx << 26) | ((uint32_t)bbserviceb << 16) | ((uint32_t)bbservicea << 0)); +} + +/** + * @brief Unpacks BB_SERVICE's fields from current value of the BB_SERVICE register. + * + * Reads the BB_SERVICE register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] maxphyntx - Will be populated with the current value of this field from the register. + * @param[out] bbserviceb - Will be populated with the current value of this field from the register. + * @param[out] bbservicea - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_bb_service_unpack(uint8_t *maxphyntx, uint8_t *bbserviceb, uint16_t *bbservicea) +{ + uint32_t localVal = REG_PL_RD(NXMAC_BB_SERVICE_ADDR); + + *maxphyntx = (localVal & ((uint32_t)0x1C000000)) >> 26; + *bbserviceb = (localVal & ((uint32_t)0x00FF0000)) >> 16; + *bbservicea = (localVal & ((uint32_t)0x0000FFFF)) >> 0; +} + +/** + * @brief Returns the current value of the maxPHYNtx field in the BB_SERVICE register. + * + * The BB_SERVICE register will be read and the maxPHYNtx field's value will be returned. + * + * @return The current value of the maxPHYNtx field in the BB_SERVICE register. + */ +__INLINE uint8_t nxmac_max_phy_ntx_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_BB_SERVICE_ADDR); + return ((localVal & ((uint32_t)0x1C000000)) >> 26); +} + +/** + * @brief Sets the maxPHYNtx field of the BB_SERVICE register. + * + * The BB_SERVICE register will be read, modified to contain the new field value, and written. + * + * @param[in] maxphyntx - The value to set the field to. + */ +__INLINE void nxmac_max_phy_ntx_setf(uint8_t maxphyntx) +{ + ASSERT_ERR((((uint32_t)maxphyntx << 26) & ~((uint32_t)0x1C000000)) == 0); + REG_PL_WR(NXMAC_BB_SERVICE_ADDR, (REG_PL_RD(NXMAC_BB_SERVICE_ADDR) & ~((uint32_t)0x1C000000)) | ((uint32_t)maxphyntx << 26)); +} + +/** + * @brief Returns the current value of the bbServiceB field in the BB_SERVICE register. + * + * The BB_SERVICE register will be read and the bbServiceB field's value will be returned. + * + * @return The current value of the bbServiceB field in the BB_SERVICE register. + */ +__INLINE uint8_t nxmac_bb_service_b_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_BB_SERVICE_ADDR); + return ((localVal & ((uint32_t)0x00FF0000)) >> 16); +} + +/** + * @brief Sets the bbServiceB field of the BB_SERVICE register. + * + * The BB_SERVICE register will be read, modified to contain the new field value, and written. + * + * @param[in] bbserviceb - The value to set the field to. + */ +__INLINE void nxmac_bb_service_b_setf(uint8_t bbserviceb) +{ + ASSERT_ERR((((uint32_t)bbserviceb << 16) & ~((uint32_t)0x00FF0000)) == 0); + REG_PL_WR(NXMAC_BB_SERVICE_ADDR, (REG_PL_RD(NXMAC_BB_SERVICE_ADDR) & ~((uint32_t)0x00FF0000)) | ((uint32_t)bbserviceb << 16)); +} + +/** + * @brief Returns the current value of the bbServiceA field in the BB_SERVICE register. + * + * The BB_SERVICE register will be read and the bbServiceA field's value will be returned. + * + * @return The current value of the bbServiceA field in the BB_SERVICE register. + */ +__INLINE uint16_t nxmac_bb_service_a_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_BB_SERVICE_ADDR); + return ((localVal & ((uint32_t)0x0000FFFF)) >> 0); +} + +/** + * @brief Sets the bbServiceA field of the BB_SERVICE register. + * + * The BB_SERVICE register will be read, modified to contain the new field value, and written. + * + * @param[in] bbservicea - The value to set the field to. + */ +__INLINE void nxmac_bb_service_a_setf(uint16_t bbservicea) +{ + ASSERT_ERR((((uint32_t)bbservicea << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_PL_WR(NXMAC_BB_SERVICE_ADDR, (REG_PL_RD(NXMAC_BB_SERVICE_ADDR) & ~((uint32_t)0x0000FFFF)) | ((uint32_t)bbservicea << 0)); +} + +/// @} + +/** + * @name MAX_POWER_LEVEL register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:08      dsssMaxPwrLevel   0x4
+ *  07:00      ofdmMaxPwrLevel   0x4
+ * 
+ * + * @{ + */ + +/// Address of the MAX_POWER_LEVEL register +#define NXMAC_MAX_POWER_LEVEL_ADDR 0xC00000A0 +/// Offset of the MAX_POWER_LEVEL register from the base address +#define NXMAC_MAX_POWER_LEVEL_OFFSET 0x000000A0 +/// Index of the MAX_POWER_LEVEL register +#define NXMAC_MAX_POWER_LEVEL_INDEX 0x00000028 +/// Reset value of the MAX_POWER_LEVEL register +#define NXMAC_MAX_POWER_LEVEL_RESET 0x00000404 + +/** + * @brief Returns the current value of the MAX_POWER_LEVEL register. + * The MAX_POWER_LEVEL register will be read and its value returned. + * @return The current value of the MAX_POWER_LEVEL register. + */ +__INLINE uint32_t nxmac_max_power_level_get(void) +{ + return REG_PL_RD(NXMAC_MAX_POWER_LEVEL_ADDR); +} + +/** + * @brief Sets the MAX_POWER_LEVEL register to a value. + * The MAX_POWER_LEVEL register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_max_power_level_set(uint32_t value) +{ + REG_PL_WR(NXMAC_MAX_POWER_LEVEL_ADDR, value); +} + +// field definitions +/// DSSS_MAX_PWR_LEVEL field mask +#define NXMAC_DSSS_MAX_PWR_LEVEL_MASK ((uint32_t)0x0000FF00) +/// DSSS_MAX_PWR_LEVEL field LSB position +#define NXMAC_DSSS_MAX_PWR_LEVEL_LSB 8 +/// DSSS_MAX_PWR_LEVEL field width +#define NXMAC_DSSS_MAX_PWR_LEVEL_WIDTH ((uint32_t)0x00000008) +/// OFDM_MAX_PWR_LEVEL field mask +#define NXMAC_OFDM_MAX_PWR_LEVEL_MASK ((uint32_t)0x000000FF) +/// OFDM_MAX_PWR_LEVEL field LSB position +#define NXMAC_OFDM_MAX_PWR_LEVEL_LSB 0 +/// OFDM_MAX_PWR_LEVEL field width +#define NXMAC_OFDM_MAX_PWR_LEVEL_WIDTH ((uint32_t)0x00000008) + +/// DSSS_MAX_PWR_LEVEL field reset value +#define NXMAC_DSSS_MAX_PWR_LEVEL_RST 0x4 +/// OFDM_MAX_PWR_LEVEL field reset value +#define NXMAC_OFDM_MAX_PWR_LEVEL_RST 0x4 + +/** + * @brief Constructs a value for the MAX_POWER_LEVEL register given values for its fields + * and writes the value to the register. + * + * @param[in] dsssmaxpwrlevel - The value to use for the dsssMaxPwrLevel field. + * @param[in] ofdmmaxpwrlevel - The value to use for the ofdmMaxPwrLevel field. + */ +__INLINE void nxmac_max_power_level_pack(uint8_t dsssmaxpwrlevel, uint8_t ofdmmaxpwrlevel) +{ + ASSERT_ERR((((uint32_t)dsssmaxpwrlevel << 8) & ~((uint32_t)0x0000FF00)) == 0); + ASSERT_ERR((((uint32_t)ofdmmaxpwrlevel << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(NXMAC_MAX_POWER_LEVEL_ADDR, ((uint32_t)dsssmaxpwrlevel << 8) | ((uint32_t)ofdmmaxpwrlevel << 0)); +} + +/** + * @brief Unpacks MAX_POWER_LEVEL's fields from current value of the MAX_POWER_LEVEL register. + * + * Reads the MAX_POWER_LEVEL register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] dsssmaxpwrlevel - Will be populated with the current value of this field from the register. + * @param[out] ofdmmaxpwrlevel - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_max_power_level_unpack(uint8_t *dsssmaxpwrlevel, uint8_t *ofdmmaxpwrlevel) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MAX_POWER_LEVEL_ADDR); + + *dsssmaxpwrlevel = (localVal & ((uint32_t)0x0000FF00)) >> 8; + *ofdmmaxpwrlevel = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +/** + * @brief Returns the current value of the dsssMaxPwrLevel field in the MAX_POWER_LEVEL register. + * + * The MAX_POWER_LEVEL register will be read and the dsssMaxPwrLevel field's value will be returned. + * + * @return The current value of the dsssMaxPwrLevel field in the MAX_POWER_LEVEL register. + */ +__INLINE uint8_t nxmac_dsss_max_pwr_level_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MAX_POWER_LEVEL_ADDR); + return ((localVal & ((uint32_t)0x0000FF00)) >> 8); +} + +/** + * @brief Sets the dsssMaxPwrLevel field of the MAX_POWER_LEVEL register. + * + * The MAX_POWER_LEVEL register will be read, modified to contain the new field value, and written. + * + * @param[in] dsssmaxpwrlevel - The value to set the field to. + */ +__INLINE void nxmac_dsss_max_pwr_level_setf(uint8_t dsssmaxpwrlevel) +{ + ASSERT_ERR((((uint32_t)dsssmaxpwrlevel << 8) & ~((uint32_t)0x0000FF00)) == 0); + REG_PL_WR(NXMAC_MAX_POWER_LEVEL_ADDR, (REG_PL_RD(NXMAC_MAX_POWER_LEVEL_ADDR) & ~((uint32_t)0x0000FF00)) | ((uint32_t)dsssmaxpwrlevel << 8)); +} + +/** + * @brief Returns the current value of the ofdmMaxPwrLevel field in the MAX_POWER_LEVEL register. + * + * The MAX_POWER_LEVEL register will be read and the ofdmMaxPwrLevel field's value will be returned. + * + * @return The current value of the ofdmMaxPwrLevel field in the MAX_POWER_LEVEL register. + */ +__INLINE uint8_t nxmac_ofdm_max_pwr_level_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MAX_POWER_LEVEL_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +/** + * @brief Sets the ofdmMaxPwrLevel field of the MAX_POWER_LEVEL register. + * + * The MAX_POWER_LEVEL register will be read, modified to contain the new field value, and written. + * + * @param[in] ofdmmaxpwrlevel - The value to set the field to. + */ +__INLINE void nxmac_ofdm_max_pwr_level_setf(uint8_t ofdmmaxpwrlevel) +{ + ASSERT_ERR((((uint32_t)ofdmmaxpwrlevel << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(NXMAC_MAX_POWER_LEVEL_ADDR, (REG_PL_RD(NXMAC_MAX_POWER_LEVEL_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)ofdmmaxpwrlevel << 0)); +} + +/// @} + +/** + * @name ENCR_KEY_0 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00      encrKeyRAMWord0   0x0
+ * 
+ * + * @{ + */ + +/// Address of the ENCR_KEY_0 register +#define NXMAC_ENCR_KEY_0_ADDR 0xC00000AC +/// Offset of the ENCR_KEY_0 register from the base address +#define NXMAC_ENCR_KEY_0_OFFSET 0x000000AC +/// Index of the ENCR_KEY_0 register +#define NXMAC_ENCR_KEY_0_INDEX 0x0000002B +/// Reset value of the ENCR_KEY_0 register +#define NXMAC_ENCR_KEY_0_RESET 0x00000000 + +/** + * @brief Returns the current value of the ENCR_KEY_0 register. + * The ENCR_KEY_0 register will be read and its value returned. + * @return The current value of the ENCR_KEY_0 register. + */ +__INLINE uint32_t nxmac_encr_key_0_get(void) +{ + return REG_PL_RD(NXMAC_ENCR_KEY_0_ADDR); +} + +/** + * @brief Sets the ENCR_KEY_0 register to a value. + * The ENCR_KEY_0 register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_encr_key_0_set(uint32_t value) +{ + REG_PL_WR(NXMAC_ENCR_KEY_0_ADDR, value); +} + +// field definitions +/// ENCR_KEY_RAM_WORD_0 field mask +#define NXMAC_ENCR_KEY_RAM_WORD_0_MASK ((uint32_t)0xFFFFFFFF) +/// ENCR_KEY_RAM_WORD_0 field LSB position +#define NXMAC_ENCR_KEY_RAM_WORD_0_LSB 0 +/// ENCR_KEY_RAM_WORD_0 field width +#define NXMAC_ENCR_KEY_RAM_WORD_0_WIDTH ((uint32_t)0x00000020) + +/// ENCR_KEY_RAM_WORD_0 field reset value +#define NXMAC_ENCR_KEY_RAM_WORD_0_RST 0x0 + +/** + * @brief Returns the current value of the encrKeyRAMWord0 field in the ENCR_KEY_0 register. + * + * The ENCR_KEY_0 register will be read and the encrKeyRAMWord0 field's value will be returned. + * + * @return The current value of the encrKeyRAMWord0 field in the ENCR_KEY_0 register. + */ +__INLINE uint32_t nxmac_encr_key_ram_word_0_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_ENCR_KEY_0_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the encrKeyRAMWord0 field of the ENCR_KEY_0 register. + * + * The ENCR_KEY_0 register will be read, modified to contain the new field value, and written. + * + * @param[in] encrkeyramword0 - The value to set the field to. + */ +__INLINE void nxmac_encr_key_ram_word_0_setf(uint32_t encrkeyramword0) +{ + ASSERT_ERR((((uint32_t)encrkeyramword0 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(NXMAC_ENCR_KEY_0_ADDR, (uint32_t)encrkeyramword0 << 0); +} + +/// @} + +/** + * @name ENCR_KEY_1 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00      encrKeyRAMWord1   0x0
+ * 
+ * + * @{ + */ + +/// Address of the ENCR_KEY_1 register +#define NXMAC_ENCR_KEY_1_ADDR 0xC00000B0 +/// Offset of the ENCR_KEY_1 register from the base address +#define NXMAC_ENCR_KEY_1_OFFSET 0x000000B0 +/// Index of the ENCR_KEY_1 register +#define NXMAC_ENCR_KEY_1_INDEX 0x0000002C +/// Reset value of the ENCR_KEY_1 register +#define NXMAC_ENCR_KEY_1_RESET 0x00000000 + +/** + * @brief Returns the current value of the ENCR_KEY_1 register. + * The ENCR_KEY_1 register will be read and its value returned. + * @return The current value of the ENCR_KEY_1 register. + */ +__INLINE uint32_t nxmac_encr_key_1_get(void) +{ + return REG_PL_RD(NXMAC_ENCR_KEY_1_ADDR); +} + +/** + * @brief Sets the ENCR_KEY_1 register to a value. + * The ENCR_KEY_1 register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_encr_key_1_set(uint32_t value) +{ + REG_PL_WR(NXMAC_ENCR_KEY_1_ADDR, value); +} + +// field definitions +/// ENCR_KEY_RAM_WORD_1 field mask +#define NXMAC_ENCR_KEY_RAM_WORD_1_MASK ((uint32_t)0xFFFFFFFF) +/// ENCR_KEY_RAM_WORD_1 field LSB position +#define NXMAC_ENCR_KEY_RAM_WORD_1_LSB 0 +/// ENCR_KEY_RAM_WORD_1 field width +#define NXMAC_ENCR_KEY_RAM_WORD_1_WIDTH ((uint32_t)0x00000020) + +/// ENCR_KEY_RAM_WORD_1 field reset value +#define NXMAC_ENCR_KEY_RAM_WORD_1_RST 0x0 + +/** + * @brief Returns the current value of the encrKeyRAMWord1 field in the ENCR_KEY_1 register. + * + * The ENCR_KEY_1 register will be read and the encrKeyRAMWord1 field's value will be returned. + * + * @return The current value of the encrKeyRAMWord1 field in the ENCR_KEY_1 register. + */ +__INLINE uint32_t nxmac_encr_key_ram_word_1_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_ENCR_KEY_1_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the encrKeyRAMWord1 field of the ENCR_KEY_1 register. + * + * The ENCR_KEY_1 register will be read, modified to contain the new field value, and written. + * + * @param[in] encrkeyramword1 - The value to set the field to. + */ +__INLINE void nxmac_encr_key_ram_word_1_setf(uint32_t encrkeyramword1) +{ + ASSERT_ERR((((uint32_t)encrkeyramword1 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(NXMAC_ENCR_KEY_1_ADDR, (uint32_t)encrkeyramword1 << 0); +} + +/// @} + +/** + * @name ENCR_KEY_2 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00      encrKeyRAMWord2   0x0
+ * 
+ * + * @{ + */ + +/// Address of the ENCR_KEY_2 register +#define NXMAC_ENCR_KEY_2_ADDR 0xC00000B4 +/// Offset of the ENCR_KEY_2 register from the base address +#define NXMAC_ENCR_KEY_2_OFFSET 0x000000B4 +/// Index of the ENCR_KEY_2 register +#define NXMAC_ENCR_KEY_2_INDEX 0x0000002D +/// Reset value of the ENCR_KEY_2 register +#define NXMAC_ENCR_KEY_2_RESET 0x00000000 + +/** + * @brief Returns the current value of the ENCR_KEY_2 register. + * The ENCR_KEY_2 register will be read and its value returned. + * @return The current value of the ENCR_KEY_2 register. + */ +__INLINE uint32_t nxmac_encr_key_2_get(void) +{ + return REG_PL_RD(NXMAC_ENCR_KEY_2_ADDR); +} + +/** + * @brief Sets the ENCR_KEY_2 register to a value. + * The ENCR_KEY_2 register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_encr_key_2_set(uint32_t value) +{ + REG_PL_WR(NXMAC_ENCR_KEY_2_ADDR, value); +} + +// field definitions +/// ENCR_KEY_RAM_WORD_2 field mask +#define NXMAC_ENCR_KEY_RAM_WORD_2_MASK ((uint32_t)0xFFFFFFFF) +/// ENCR_KEY_RAM_WORD_2 field LSB position +#define NXMAC_ENCR_KEY_RAM_WORD_2_LSB 0 +/// ENCR_KEY_RAM_WORD_2 field width +#define NXMAC_ENCR_KEY_RAM_WORD_2_WIDTH ((uint32_t)0x00000020) + +/// ENCR_KEY_RAM_WORD_2 field reset value +#define NXMAC_ENCR_KEY_RAM_WORD_2_RST 0x0 + +/** + * @brief Returns the current value of the encrKeyRAMWord2 field in the ENCR_KEY_2 register. + * + * The ENCR_KEY_2 register will be read and the encrKeyRAMWord2 field's value will be returned. + * + * @return The current value of the encrKeyRAMWord2 field in the ENCR_KEY_2 register. + */ +__INLINE uint32_t nxmac_encr_key_ram_word_2_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_ENCR_KEY_2_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the encrKeyRAMWord2 field of the ENCR_KEY_2 register. + * + * The ENCR_KEY_2 register will be read, modified to contain the new field value, and written. + * + * @param[in] encrkeyramword2 - The value to set the field to. + */ +__INLINE void nxmac_encr_key_ram_word_2_setf(uint32_t encrkeyramword2) +{ + ASSERT_ERR((((uint32_t)encrkeyramword2 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(NXMAC_ENCR_KEY_2_ADDR, (uint32_t)encrkeyramword2 << 0); +} + +/// @} + +/** + * @name ENCR_KEY_3 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00      encrKeyRAMWord3   0x0
+ * 
+ * + * @{ + */ + +/// Address of the ENCR_KEY_3 register +#define NXMAC_ENCR_KEY_3_ADDR 0xC00000B8 +/// Offset of the ENCR_KEY_3 register from the base address +#define NXMAC_ENCR_KEY_3_OFFSET 0x000000B8 +/// Index of the ENCR_KEY_3 register +#define NXMAC_ENCR_KEY_3_INDEX 0x0000002E +/// Reset value of the ENCR_KEY_3 register +#define NXMAC_ENCR_KEY_3_RESET 0x00000000 + +/** + * @brief Returns the current value of the ENCR_KEY_3 register. + * The ENCR_KEY_3 register will be read and its value returned. + * @return The current value of the ENCR_KEY_3 register. + */ +__INLINE uint32_t nxmac_encr_key_3_get(void) +{ + return REG_PL_RD(NXMAC_ENCR_KEY_3_ADDR); +} + +/** + * @brief Sets the ENCR_KEY_3 register to a value. + * The ENCR_KEY_3 register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_encr_key_3_set(uint32_t value) +{ + REG_PL_WR(NXMAC_ENCR_KEY_3_ADDR, value); +} + +// field definitions +/// ENCR_KEY_RAM_WORD_3 field mask +#define NXMAC_ENCR_KEY_RAM_WORD_3_MASK ((uint32_t)0xFFFFFFFF) +/// ENCR_KEY_RAM_WORD_3 field LSB position +#define NXMAC_ENCR_KEY_RAM_WORD_3_LSB 0 +/// ENCR_KEY_RAM_WORD_3 field width +#define NXMAC_ENCR_KEY_RAM_WORD_3_WIDTH ((uint32_t)0x00000020) + +/// ENCR_KEY_RAM_WORD_3 field reset value +#define NXMAC_ENCR_KEY_RAM_WORD_3_RST 0x0 + +/** + * @brief Returns the current value of the encrKeyRAMWord3 field in the ENCR_KEY_3 register. + * + * The ENCR_KEY_3 register will be read and the encrKeyRAMWord3 field's value will be returned. + * + * @return The current value of the encrKeyRAMWord3 field in the ENCR_KEY_3 register. + */ +__INLINE uint32_t nxmac_encr_key_ram_word_3_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_ENCR_KEY_3_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the encrKeyRAMWord3 field of the ENCR_KEY_3 register. + * + * The ENCR_KEY_3 register will be read, modified to contain the new field value, and written. + * + * @param[in] encrkeyramword3 - The value to set the field to. + */ +__INLINE void nxmac_encr_key_ram_word_3_setf(uint32_t encrkeyramword3) +{ + ASSERT_ERR((((uint32_t)encrkeyramword3 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(NXMAC_ENCR_KEY_3_ADDR, (uint32_t)encrkeyramword3 << 0); +} + +/// @} + +/** + * @name ENCR_MAC_ADDR_LOW register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00        macAddrRAMLow   0xFFFFFFFF
+ * 
+ * + * @{ + */ + +/// Address of the ENCR_MAC_ADDR_LOW register +#define NXMAC_ENCR_MAC_ADDR_LOW_ADDR 0xC00000BC +/// Offset of the ENCR_MAC_ADDR_LOW register from the base address +#define NXMAC_ENCR_MAC_ADDR_LOW_OFFSET 0x000000BC +/// Index of the ENCR_MAC_ADDR_LOW register +#define NXMAC_ENCR_MAC_ADDR_LOW_INDEX 0x0000002F +/// Reset value of the ENCR_MAC_ADDR_LOW register +#define NXMAC_ENCR_MAC_ADDR_LOW_RESET 0xFFFFFFFF + +/** + * @brief Returns the current value of the ENCR_MAC_ADDR_LOW register. + * The ENCR_MAC_ADDR_LOW register will be read and its value returned. + * @return The current value of the ENCR_MAC_ADDR_LOW register. + */ +__INLINE uint32_t nxmac_encr_mac_addr_low_get(void) +{ + return REG_PL_RD(NXMAC_ENCR_MAC_ADDR_LOW_ADDR); +} + +/** + * @brief Sets the ENCR_MAC_ADDR_LOW register to a value. + * The ENCR_MAC_ADDR_LOW register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_encr_mac_addr_low_set(uint32_t value) +{ + REG_PL_WR(NXMAC_ENCR_MAC_ADDR_LOW_ADDR, value); +} + +// field definitions +/// MAC_ADDR_RAM_LOW field mask +#define NXMAC_MAC_ADDR_RAM_LOW_MASK ((uint32_t)0xFFFFFFFF) +/// MAC_ADDR_RAM_LOW field LSB position +#define NXMAC_MAC_ADDR_RAM_LOW_LSB 0 +/// MAC_ADDR_RAM_LOW field width +#define NXMAC_MAC_ADDR_RAM_LOW_WIDTH ((uint32_t)0x00000020) + +/// MAC_ADDR_RAM_LOW field reset value +#define NXMAC_MAC_ADDR_RAM_LOW_RST 0xFFFFFFFF + +/** + * @brief Returns the current value of the macAddrRAMLow field in the ENCR_MAC_ADDR_LOW register. + * + * The ENCR_MAC_ADDR_LOW register will be read and the macAddrRAMLow field's value will be returned. + * + * @return The current value of the macAddrRAMLow field in the ENCR_MAC_ADDR_LOW register. + */ +__INLINE uint32_t nxmac_mac_addr_ram_low_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_ENCR_MAC_ADDR_LOW_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the macAddrRAMLow field of the ENCR_MAC_ADDR_LOW register. + * + * The ENCR_MAC_ADDR_LOW register will be read, modified to contain the new field value, and written. + * + * @param[in] macaddrramlow - The value to set the field to. + */ +__INLINE void nxmac_mac_addr_ram_low_setf(uint32_t macaddrramlow) +{ + ASSERT_ERR((((uint32_t)macaddrramlow << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(NXMAC_ENCR_MAC_ADDR_LOW_ADDR, (uint32_t)macaddrramlow << 0); +} + +/// @} + +/** + * @name ENCR_MAC_ADDR_HIGH register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00       macAddrRAMHigh   0xFFFF
+ * 
+ * + * @{ + */ + +/// Address of the ENCR_MAC_ADDR_HIGH register +#define NXMAC_ENCR_MAC_ADDR_HIGH_ADDR 0xC00000C0 +/// Offset of the ENCR_MAC_ADDR_HIGH register from the base address +#define NXMAC_ENCR_MAC_ADDR_HIGH_OFFSET 0x000000C0 +/// Index of the ENCR_MAC_ADDR_HIGH register +#define NXMAC_ENCR_MAC_ADDR_HIGH_INDEX 0x00000030 +/// Reset value of the ENCR_MAC_ADDR_HIGH register +#define NXMAC_ENCR_MAC_ADDR_HIGH_RESET 0x0000FFFF + +/** + * @brief Returns the current value of the ENCR_MAC_ADDR_HIGH register. + * The ENCR_MAC_ADDR_HIGH register will be read and its value returned. + * @return The current value of the ENCR_MAC_ADDR_HIGH register. + */ +__INLINE uint32_t nxmac_encr_mac_addr_high_get(void) +{ + return REG_PL_RD(NXMAC_ENCR_MAC_ADDR_HIGH_ADDR); +} + +/** + * @brief Sets the ENCR_MAC_ADDR_HIGH register to a value. + * The ENCR_MAC_ADDR_HIGH register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_encr_mac_addr_high_set(uint32_t value) +{ + REG_PL_WR(NXMAC_ENCR_MAC_ADDR_HIGH_ADDR, value); +} + +// field definitions +/// MAC_ADDR_RAM_HIGH field mask +#define NXMAC_MAC_ADDR_RAM_HIGH_MASK ((uint32_t)0x0000FFFF) +/// MAC_ADDR_RAM_HIGH field LSB position +#define NXMAC_MAC_ADDR_RAM_HIGH_LSB 0 +/// MAC_ADDR_RAM_HIGH field width +#define NXMAC_MAC_ADDR_RAM_HIGH_WIDTH ((uint32_t)0x00000010) + +/// MAC_ADDR_RAM_HIGH field reset value +#define NXMAC_MAC_ADDR_RAM_HIGH_RST 0xFFFF + +/** + * @brief Returns the current value of the macAddrRAMHigh field in the ENCR_MAC_ADDR_HIGH register. + * + * The ENCR_MAC_ADDR_HIGH register will be read and the macAddrRAMHigh field's value will be returned. + * + * @return The current value of the macAddrRAMHigh field in the ENCR_MAC_ADDR_HIGH register. + */ +__INLINE uint16_t nxmac_mac_addr_ram_high_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_ENCR_MAC_ADDR_HIGH_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the macAddrRAMHigh field of the ENCR_MAC_ADDR_HIGH register. + * + * The ENCR_MAC_ADDR_HIGH register will be read, modified to contain the new field value, and written. + * + * @param[in] macaddrramhigh - The value to set the field to. + */ +__INLINE void nxmac_mac_addr_ram_high_setf(uint16_t macaddrramhigh) +{ + ASSERT_ERR((((uint32_t)macaddrramhigh << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_PL_WR(NXMAC_ENCR_MAC_ADDR_HIGH_ADDR, (uint32_t)macaddrramhigh << 0); +} + +/// @} + +/** + * @name ENCR_CNTRL register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31              newRead   0
+ *     30             newWrite   0
+ *     29            newSearch   0
+ *     28          searchError   0
+ *  25:16          keyIndexRAM   0x0
+ *  10:08             cTypeRAM   0x0
+ *  07:04            vlanIDRAM   0x0
+ *  03:02               sppRAM   0x0
+ *     01         useDefKeyRAM   0
+ *     00              cLenRAM   0
+ * 
+ * + * @{ + */ +enum +{ + CTYPERAM_NULL_KEY = 0, + CTYPERAM_WEP, + CTYPERAM_TKIP, + CTYPERAM_CCMP, +}; + +/// Address of the ENCR_CNTRL register +#define NXMAC_ENCR_CNTRL_ADDR 0xC00000C4 +/// Offset of the ENCR_CNTRL register from the base address +#define NXMAC_ENCR_CNTRL_OFFSET 0x000000C4 +/// Index of the ENCR_CNTRL register +#define NXMAC_ENCR_CNTRL_INDEX 0x00000031 +/// Reset value of the ENCR_CNTRL register +#define NXMAC_ENCR_CNTRL_RESET 0x00000000 + +/** + * @brief Returns the current value of the ENCR_CNTRL register. + * The ENCR_CNTRL register will be read and its value returned. + * @return The current value of the ENCR_CNTRL register. + */ +__INLINE uint32_t nxmac_encr_cntrl_get(void) +{ + return REG_PL_RD(NXMAC_ENCR_CNTRL_ADDR); +} + +/** + * @brief Sets the ENCR_CNTRL register to a value. + * The ENCR_CNTRL register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_encr_cntrl_set(uint32_t value) +{ + REG_PL_WR(NXMAC_ENCR_CNTRL_ADDR, value); +} + +// field definitions +/// NEW_READ field bit +#define NXMAC_NEW_READ_BIT ((uint32_t)0x80000000) +/// NEW_READ field position +#define NXMAC_NEW_READ_POS 31 +/// NEW_WRITE field bit +#define NXMAC_NEW_WRITE_BIT ((uint32_t)0x40000000) +/// NEW_WRITE field position +#define NXMAC_NEW_WRITE_POS 30 +/// NEW_SEARCH field bit +#define NXMAC_NEW_SEARCH_BIT ((uint32_t)0x20000000) +/// NEW_SEARCH field position +#define NXMAC_NEW_SEARCH_POS 29 +/// SEARCH_ERROR field bit +#define NXMAC_SEARCH_ERROR_BIT ((uint32_t)0x10000000) +/// SEARCH_ERROR field position +#define NXMAC_SEARCH_ERROR_POS 28 +/// KEY_INDEX_RAM field mask +#define NXMAC_KEY_INDEX_RAM_MASK ((uint32_t)0x03FF0000) +/// KEY_INDEX_RAM field LSB position +#define NXMAC_KEY_INDEX_RAM_LSB 16 +/// KEY_INDEX_RAM field width +#define NXMAC_KEY_INDEX_RAM_WIDTH ((uint32_t)0x0000000A) +/// C_TYPE_RAM field mask +#define NXMAC_C_TYPE_RAM_MASK ((uint32_t)0x00000700) +/// C_TYPE_RAM field LSB position +#define NXMAC_C_TYPE_RAM_LSB 8 +/// C_TYPE_RAM field width +#define NXMAC_C_TYPE_RAM_WIDTH ((uint32_t)0x00000003) +/// VLAN_IDRAM field mask +#define NXMAC_VLAN_IDRAM_MASK ((uint32_t)0x000000F0) +/// VLAN_IDRAM field LSB position +#define NXMAC_VLAN_IDRAM_LSB 4 +/// VLAN_IDRAM field width +#define NXMAC_VLAN_IDRAM_WIDTH ((uint32_t)0x00000004) +/// SPP_RAM field mask +#define NXMAC_SPP_RAM_MASK ((uint32_t)0x0000000C) +/// SPP_RAM field LSB position +#define NXMAC_SPP_RAM_LSB 2 +/// SPP_RAM field width +#define NXMAC_SPP_RAM_WIDTH ((uint32_t)0x00000002) +/// USE_DEF_KEY_RAM field bit +#define NXMAC_USE_DEF_KEY_RAM_BIT ((uint32_t)0x00000002) +/// USE_DEF_KEY_RAM field position +#define NXMAC_USE_DEF_KEY_RAM_POS 1 +/// C_LEN_RAM field bit +#define NXMAC_C_LEN_RAM_BIT ((uint32_t)0x00000001) +/// C_LEN_RAM field position +#define NXMAC_C_LEN_RAM_POS 0 + +/// NEW_READ field reset value +#define NXMAC_NEW_READ_RST 0x0 +/// NEW_WRITE field reset value +#define NXMAC_NEW_WRITE_RST 0x0 +/// NEW_SEARCH field reset value +#define NXMAC_NEW_SEARCH_RST 0x0 +/// SEARCH_ERROR field reset value +#define NXMAC_SEARCH_ERROR_RST 0x0 +/// KEY_INDEX_RAM field reset value +#define NXMAC_KEY_INDEX_RAM_RST 0x0 +/// C_TYPE_RAM field reset value +#define NXMAC_C_TYPE_RAM_RST 0x0 +/// VLAN_IDRAM field reset value +#define NXMAC_VLAN_IDRAM_RST 0x0 +/// SPP_RAM field reset value +#define NXMAC_SPP_RAM_RST 0x0 +/// USE_DEF_KEY_RAM field reset value +#define NXMAC_USE_DEF_KEY_RAM_RST 0x0 +/// C_LEN_RAM field reset value +#define NXMAC_C_LEN_RAM_RST 0x0 + +/** + * @brief Constructs a value for the ENCR_CNTRL register given values for its fields + * and writes the value to the register. + * + * @param[in] newread - The value to use for the newRead field. + * @param[in] newwrite - The value to use for the newWrite field. + * @param[in] newsearch - The value to use for the newSearch field. + * @param[in] searcherror - The value to use for the searchError field. + * @param[in] keyindexram - The value to use for the keyIndexRAM field. + * @param[in] ctyperam - The value to use for the cTypeRAM field. + * @param[in] vlanidram - The value to use for the vlanIDRAM field. + * @param[in] sppram - The value to use for the sppRAM field. + * @param[in] usedefkeyram - The value to use for the useDefKeyRAM field. + * @param[in] clenram - The value to use for the cLenRAM field. + */ +__INLINE void nxmac_encr_cntrl_pack(uint8_t newread, uint8_t newwrite, uint8_t newsearch, uint8_t searcherror, uint16_t keyindexram, uint8_t ctyperam, uint8_t vlanidram, uint8_t sppram, uint8_t usedefkeyram, uint8_t clenram) +{ + ASSERT_ERR((((uint32_t)newread << 31) & ~((uint32_t)0x80000000)) == 0); + ASSERT_ERR((((uint32_t)newwrite << 30) & ~((uint32_t)0x40000000)) == 0); + ASSERT_ERR((((uint32_t)newsearch << 29) & ~((uint32_t)0x20000000)) == 0); + ASSERT_ERR((((uint32_t)searcherror << 28) & ~((uint32_t)0x10000000)) == 0); + ASSERT_ERR((((uint32_t)keyindexram << 16) & ~((uint32_t)0x03FF0000)) == 0); + ASSERT_ERR((((uint32_t)ctyperam << 8) & ~((uint32_t)0x00000700)) == 0); + ASSERT_ERR((((uint32_t)vlanidram << 4) & ~((uint32_t)0x000000F0)) == 0); + ASSERT_ERR((((uint32_t)sppram << 2) & ~((uint32_t)0x0000000C)) == 0); + ASSERT_ERR((((uint32_t)usedefkeyram << 1) & ~((uint32_t)0x00000002)) == 0); + ASSERT_ERR((((uint32_t)clenram << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_ENCR_CNTRL_ADDR, ((uint32_t)newread << 31) | ((uint32_t)newwrite << 30) | ((uint32_t)newsearch << 29) | ((uint32_t)searcherror << 28) | ((uint32_t)keyindexram << 16) | ((uint32_t)ctyperam << 8) | ((uint32_t)vlanidram << 4) | ((uint32_t)sppram << 2) | ((uint32_t)usedefkeyram << 1) | ((uint32_t)clenram << 0)); +} + +/** + * @brief Unpacks ENCR_CNTRL's fields from current value of the ENCR_CNTRL register. + * + * Reads the ENCR_CNTRL register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] newread - Will be populated with the current value of this field from the register. + * @param[out] newwrite - Will be populated with the current value of this field from the register. + * @param[out] newsearch - Will be populated with the current value of this field from the register. + * @param[out] searcherror - Will be populated with the current value of this field from the register. + * @param[out] keyindexram - Will be populated with the current value of this field from the register. + * @param[out] ctyperam - Will be populated with the current value of this field from the register. + * @param[out] vlanidram - Will be populated with the current value of this field from the register. + * @param[out] sppram - Will be populated with the current value of this field from the register. + * @param[out] usedefkeyram - Will be populated with the current value of this field from the register. + * @param[out] clenram - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_encr_cntrl_unpack(uint8_t *newread, uint8_t *newwrite, uint8_t *newsearch, uint8_t *searcherror, uint16_t *keyindexram, uint8_t *ctyperam, uint8_t *vlanidram, uint8_t *sppram, uint8_t *usedefkeyram, uint8_t *clenram) +{ + uint32_t localVal = REG_PL_RD(NXMAC_ENCR_CNTRL_ADDR); + + *newread = (localVal & ((uint32_t)0x80000000)) >> 31; + *newwrite = (localVal & ((uint32_t)0x40000000)) >> 30; + *newsearch = (localVal & ((uint32_t)0x20000000)) >> 29; + *searcherror = (localVal & ((uint32_t)0x10000000)) >> 28; + *keyindexram = (localVal & ((uint32_t)0x03FF0000)) >> 16; + *ctyperam = (localVal & ((uint32_t)0x00000700)) >> 8; + *vlanidram = (localVal & ((uint32_t)0x000000F0)) >> 4; + *sppram = (localVal & ((uint32_t)0x0000000C)) >> 2; + *usedefkeyram = (localVal & ((uint32_t)0x00000002)) >> 1; + *clenram = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +/** + * @brief Returns the current value of the newRead field in the ENCR_CNTRL register. + * + * The ENCR_CNTRL register will be read and the newRead field's value will be returned. + * + * @return The current value of the newRead field in the ENCR_CNTRL register. + */ +__INLINE uint8_t nxmac_new_read_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_ENCR_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +/** + * @brief Sets the newRead field of the ENCR_CNTRL register. + * + * The ENCR_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] newread - The value to set the field to. + */ +__INLINE void nxmac_new_read_setf(uint8_t newread) +{ + ASSERT_ERR((((uint32_t)newread << 31) & ~((uint32_t)0x80000000)) == 0); + REG_PL_WR(NXMAC_ENCR_CNTRL_ADDR, (REG_PL_RD(NXMAC_ENCR_CNTRL_ADDR) & ~((uint32_t)0x80000000)) | ((uint32_t)newread << 31)); +} + +/** + * @brief Returns the current value of the newWrite field in the ENCR_CNTRL register. + * + * The ENCR_CNTRL register will be read and the newWrite field's value will be returned. + * + * @return The current value of the newWrite field in the ENCR_CNTRL register. + */ +__INLINE uint8_t nxmac_new_write_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_ENCR_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x40000000)) >> 30); +} + +/** + * @brief Sets the newWrite field of the ENCR_CNTRL register. + * + * The ENCR_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] newwrite - The value to set the field to. + */ +__INLINE void nxmac_new_write_setf(uint8_t newwrite) +{ + ASSERT_ERR((((uint32_t)newwrite << 30) & ~((uint32_t)0x40000000)) == 0); + REG_PL_WR(NXMAC_ENCR_CNTRL_ADDR, (REG_PL_RD(NXMAC_ENCR_CNTRL_ADDR) & ~((uint32_t)0x40000000)) | ((uint32_t)newwrite << 30)); +} + +/** + * @brief Returns the current value of the newSearch field in the ENCR_CNTRL register. + * + * The ENCR_CNTRL register will be read and the newSearch field's value will be returned. + * + * @return The current value of the newSearch field in the ENCR_CNTRL register. + */ +__INLINE uint8_t nxmac_new_search_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_ENCR_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x20000000)) >> 29); +} + +/** + * @brief Sets the newSearch field of the ENCR_CNTRL register. + * + * The ENCR_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] newsearch - The value to set the field to. + */ +__INLINE void nxmac_new_search_setf(uint8_t newsearch) +{ + ASSERT_ERR((((uint32_t)newsearch << 29) & ~((uint32_t)0x20000000)) == 0); + REG_PL_WR(NXMAC_ENCR_CNTRL_ADDR, (REG_PL_RD(NXMAC_ENCR_CNTRL_ADDR) & ~((uint32_t)0x20000000)) | ((uint32_t)newsearch << 29)); +} + +/** + * @brief Returns the current value of the searchError field in the ENCR_CNTRL register. + * + * The ENCR_CNTRL register will be read and the searchError field's value will be returned. + * + * @return The current value of the searchError field in the ENCR_CNTRL register. + */ +__INLINE uint8_t nxmac_search_error_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_ENCR_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x10000000)) >> 28); +} + +/** + * @brief Sets the searchError field of the ENCR_CNTRL register. + * + * The ENCR_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] searcherror - The value to set the field to. + */ +__INLINE void nxmac_search_error_setf(uint8_t searcherror) +{ + ASSERT_ERR((((uint32_t)searcherror << 28) & ~((uint32_t)0x10000000)) == 0); + REG_PL_WR(NXMAC_ENCR_CNTRL_ADDR, (REG_PL_RD(NXMAC_ENCR_CNTRL_ADDR) & ~((uint32_t)0x10000000)) | ((uint32_t)searcherror << 28)); +} + +/** + * @brief Returns the current value of the keyIndexRAM field in the ENCR_CNTRL register. + * + * The ENCR_CNTRL register will be read and the keyIndexRAM field's value will be returned. + * + * @return The current value of the keyIndexRAM field in the ENCR_CNTRL register. + */ +__INLINE uint16_t nxmac_key_index_ram_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_ENCR_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x03FF0000)) >> 16); +} + +/** + * @brief Sets the keyIndexRAM field of the ENCR_CNTRL register. + * + * The ENCR_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] keyindexram - The value to set the field to. + */ +__INLINE void nxmac_key_index_ram_setf(uint16_t keyindexram) +{ + ASSERT_ERR((((uint32_t)keyindexram << 16) & ~((uint32_t)0x03FF0000)) == 0); + REG_PL_WR(NXMAC_ENCR_CNTRL_ADDR, (REG_PL_RD(NXMAC_ENCR_CNTRL_ADDR) & ~((uint32_t)0x03FF0000)) | ((uint32_t)keyindexram << 16)); +} + +/** + * @brief Returns the current value of the cTypeRAM field in the ENCR_CNTRL register. + * + * The ENCR_CNTRL register will be read and the cTypeRAM field's value will be returned. + * + * @return The current value of the cTypeRAM field in the ENCR_CNTRL register. + */ +__INLINE uint8_t nxmac_c_type_ram_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_ENCR_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x00000700)) >> 8); +} + +/** + * @brief Sets the cTypeRAM field of the ENCR_CNTRL register. + * + * The ENCR_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] ctyperam - The value to set the field to. + */ +__INLINE void nxmac_c_type_ram_setf(uint8_t ctyperam) +{ + ASSERT_ERR((((uint32_t)ctyperam << 8) & ~((uint32_t)0x00000700)) == 0); + REG_PL_WR(NXMAC_ENCR_CNTRL_ADDR, (REG_PL_RD(NXMAC_ENCR_CNTRL_ADDR) & ~((uint32_t)0x00000700)) | ((uint32_t)ctyperam << 8)); +} + +/** + * @brief Returns the current value of the vlanIDRAM field in the ENCR_CNTRL register. + * + * The ENCR_CNTRL register will be read and the vlanIDRAM field's value will be returned. + * + * @return The current value of the vlanIDRAM field in the ENCR_CNTRL register. + */ +__INLINE uint8_t nxmac_vlan_idram_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_ENCR_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x000000F0)) >> 4); +} + +/** + * @brief Sets the vlanIDRAM field of the ENCR_CNTRL register. + * + * The ENCR_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] vlanidram - The value to set the field to. + */ +__INLINE void nxmac_vlan_idram_setf(uint8_t vlanidram) +{ + ASSERT_ERR((((uint32_t)vlanidram << 4) & ~((uint32_t)0x000000F0)) == 0); + REG_PL_WR(NXMAC_ENCR_CNTRL_ADDR, (REG_PL_RD(NXMAC_ENCR_CNTRL_ADDR) & ~((uint32_t)0x000000F0)) | ((uint32_t)vlanidram << 4)); +} + +/** + * @brief Returns the current value of the sppRAM field in the ENCR_CNTRL register. + * + * The ENCR_CNTRL register will be read and the sppRAM field's value will be returned. + * + * @return The current value of the sppRAM field in the ENCR_CNTRL register. + */ +__INLINE uint8_t nxmac_spp_ram_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_ENCR_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x0000000C)) >> 2); +} + +/** + * @brief Sets the sppRAM field of the ENCR_CNTRL register. + * + * The ENCR_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] sppram - The value to set the field to. + */ +__INLINE void nxmac_spp_ram_setf(uint8_t sppram) +{ + ASSERT_ERR((((uint32_t)sppram << 2) & ~((uint32_t)0x0000000C)) == 0); + REG_PL_WR(NXMAC_ENCR_CNTRL_ADDR, (REG_PL_RD(NXMAC_ENCR_CNTRL_ADDR) & ~((uint32_t)0x0000000C)) | ((uint32_t)sppram << 2)); +} + +/** + * @brief Returns the current value of the useDefKeyRAM field in the ENCR_CNTRL register. + * + * The ENCR_CNTRL register will be read and the useDefKeyRAM field's value will be returned. + * + * @return The current value of the useDefKeyRAM field in the ENCR_CNTRL register. + */ +__INLINE uint8_t nxmac_use_def_key_ram_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_ENCR_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +/** + * @brief Sets the useDefKeyRAM field of the ENCR_CNTRL register. + * + * The ENCR_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] usedefkeyram - The value to set the field to. + */ +__INLINE void nxmac_use_def_key_ram_setf(uint8_t usedefkeyram) +{ + ASSERT_ERR((((uint32_t)usedefkeyram << 1) & ~((uint32_t)0x00000002)) == 0); + REG_PL_WR(NXMAC_ENCR_CNTRL_ADDR, (REG_PL_RD(NXMAC_ENCR_CNTRL_ADDR) & ~((uint32_t)0x00000002)) | ((uint32_t)usedefkeyram << 1)); +} + +/** + * @brief Returns the current value of the cLenRAM field in the ENCR_CNTRL register. + * + * The ENCR_CNTRL register will be read and the cLenRAM field's value will be returned. + * + * @return The current value of the cLenRAM field in the ENCR_CNTRL register. + */ +__INLINE uint8_t nxmac_c_len_ram_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_ENCR_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/** + * @brief Sets the cLenRAM field of the ENCR_CNTRL register. + * + * The ENCR_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] clenram - The value to set the field to. + */ +__INLINE void nxmac_c_len_ram_setf(uint8_t clenram) +{ + ASSERT_ERR((((uint32_t)clenram << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_ENCR_CNTRL_ADDR, (REG_PL_RD(NXMAC_ENCR_CNTRL_ADDR) & ~((uint32_t)0x00000001)) | ((uint32_t)clenram << 0)); +} + +/// @} + +#if RW_WAPI_EN +/** + * @name ENCR_WPI_INT_KEY_0 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00   encrIntKeyRAMWord0   0x0
+ * 
+ * + * @{ + */ + +/// Address of the ENCR_WPI_INT_KEY_0 register +#define NXMAC_ENCR_WPI_INT_KEY_0_ADDR 0xC00000C8 +/// Offset of the ENCR_WPI_INT_KEY_0 register from the base address +#define NXMAC_ENCR_WPI_INT_KEY_0_OFFSET 0x000000C8 +/// Index of the ENCR_WPI_INT_KEY_0 register +#define NXMAC_ENCR_WPI_INT_KEY_0_INDEX 0x00000032 +/// Reset value of the ENCR_WPI_INT_KEY_0 register +#define NXMAC_ENCR_WPI_INT_KEY_0_RESET 0x00000000 + +/** + * @brief Returns the current value of the ENCR_WPI_INT_KEY_0 register. + * The ENCR_WPI_INT_KEY_0 register will be read and its value returned. + * @return The current value of the ENCR_WPI_INT_KEY_0 register. + */ +__INLINE uint32_t nxmac_encr_wpi_int_key_0_get(void) +{ + return REG_PL_RD(NXMAC_ENCR_WPI_INT_KEY_0_ADDR); +} + +/** + * @brief Sets the ENCR_WPI_INT_KEY_0 register to a value. + * The ENCR_WPI_INT_KEY_0 register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_encr_wpi_int_key_0_set(uint32_t value) +{ + REG_PL_WR(NXMAC_ENCR_WPI_INT_KEY_0_ADDR, value); +} + +// field definitions +/// ENCR_INT_KEY_RAM_WORD_0 field mask +#define NXMAC_ENCR_INT_KEY_RAM_WORD_0_MASK ((uint32_t)0xFFFFFFFF) +/// ENCR_INT_KEY_RAM_WORD_0 field LSB position +#define NXMAC_ENCR_INT_KEY_RAM_WORD_0_LSB 0 +/// ENCR_INT_KEY_RAM_WORD_0 field width +#define NXMAC_ENCR_INT_KEY_RAM_WORD_0_WIDTH ((uint32_t)0x00000020) + +/// ENCR_INT_KEY_RAM_WORD_0 field reset value +#define NXMAC_ENCR_INT_KEY_RAM_WORD_0_RST 0x0 + +/** + * @brief Returns the current value of the encrIntKeyRAMWord0 field in the ENCR_WPI_INT_KEY_0 register. + * + * The ENCR_WPI_INT_KEY_0 register will be read and the encrIntKeyRAMWord0 field's value will be returned. + * + * @return The current value of the encrIntKeyRAMWord0 field in the ENCR_WPI_INT_KEY_0 register. + */ +__INLINE uint32_t nxmac_encr_int_key_ram_word_0_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_ENCR_WPI_INT_KEY_0_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the encrIntKeyRAMWord0 field of the ENCR_WPI_INT_KEY_0 register. + * + * The ENCR_WPI_INT_KEY_0 register will be read, modified to contain the new field value, and written. + * + * @param[in] encrintkeyramword0 - The value to set the field to. + */ +__INLINE void nxmac_encr_int_key_ram_word_0_setf(uint32_t encrintkeyramword0) +{ + ASSERT_ERR((((uint32_t)encrintkeyramword0 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(NXMAC_ENCR_WPI_INT_KEY_0_ADDR, (uint32_t)encrintkeyramword0 << 0); +} + +#endif // RW_WAPI_EN +/// @} + +#if RW_WAPI_EN +/** + * @name ENCR_WPI_INT_KEY_1 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00   encrIntKeyRAMWord1   0x0
+ * 
+ * + * @{ + */ + +/// Address of the ENCR_WPI_INT_KEY_1 register +#define NXMAC_ENCR_WPI_INT_KEY_1_ADDR 0xC00000CC +/// Offset of the ENCR_WPI_INT_KEY_1 register from the base address +#define NXMAC_ENCR_WPI_INT_KEY_1_OFFSET 0x000000CC +/// Index of the ENCR_WPI_INT_KEY_1 register +#define NXMAC_ENCR_WPI_INT_KEY_1_INDEX 0x00000033 +/// Reset value of the ENCR_WPI_INT_KEY_1 register +#define NXMAC_ENCR_WPI_INT_KEY_1_RESET 0x00000000 + +/** + * @brief Returns the current value of the ENCR_WPI_INT_KEY_1 register. + * The ENCR_WPI_INT_KEY_1 register will be read and its value returned. + * @return The current value of the ENCR_WPI_INT_KEY_1 register. + */ +__INLINE uint32_t nxmac_encr_wpi_int_key_1_get(void) +{ + return REG_PL_RD(NXMAC_ENCR_WPI_INT_KEY_1_ADDR); +} + +/** + * @brief Sets the ENCR_WPI_INT_KEY_1 register to a value. + * The ENCR_WPI_INT_KEY_1 register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_encr_wpi_int_key_1_set(uint32_t value) +{ + REG_PL_WR(NXMAC_ENCR_WPI_INT_KEY_1_ADDR, value); +} + +// field definitions +/// ENCR_INT_KEY_RAM_WORD_1 field mask +#define NXMAC_ENCR_INT_KEY_RAM_WORD_1_MASK ((uint32_t)0xFFFFFFFF) +/// ENCR_INT_KEY_RAM_WORD_1 field LSB position +#define NXMAC_ENCR_INT_KEY_RAM_WORD_1_LSB 0 +/// ENCR_INT_KEY_RAM_WORD_1 field width +#define NXMAC_ENCR_INT_KEY_RAM_WORD_1_WIDTH ((uint32_t)0x00000020) + +/// ENCR_INT_KEY_RAM_WORD_1 field reset value +#define NXMAC_ENCR_INT_KEY_RAM_WORD_1_RST 0x0 + +/** + * @brief Returns the current value of the encrIntKeyRAMWord1 field in the ENCR_WPI_INT_KEY_1 register. + * + * The ENCR_WPI_INT_KEY_1 register will be read and the encrIntKeyRAMWord1 field's value will be returned. + * + * @return The current value of the encrIntKeyRAMWord1 field in the ENCR_WPI_INT_KEY_1 register. + */ +__INLINE uint32_t nxmac_encr_int_key_ram_word_1_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_ENCR_WPI_INT_KEY_1_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the encrIntKeyRAMWord1 field of the ENCR_WPI_INT_KEY_1 register. + * + * The ENCR_WPI_INT_KEY_1 register will be read, modified to contain the new field value, and written. + * + * @param[in] encrintkeyramword1 - The value to set the field to. + */ +__INLINE void nxmac_encr_int_key_ram_word_1_setf(uint32_t encrintkeyramword1) +{ + ASSERT_ERR((((uint32_t)encrintkeyramword1 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(NXMAC_ENCR_WPI_INT_KEY_1_ADDR, (uint32_t)encrintkeyramword1 << 0); +} + +#endif // RW_WAPI_EN +/// @} + +#if RW_WAPI_EN +/** + * @name ENCR_WPI_INT_KEY_2 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00   encrIntKeyRAMWord2   0x0
+ * 
+ * + * @{ + */ + +/// Address of the ENCR_WPI_INT_KEY_2 register +#define NXMAC_ENCR_WPI_INT_KEY_2_ADDR 0xC00000D0 +/// Offset of the ENCR_WPI_INT_KEY_2 register from the base address +#define NXMAC_ENCR_WPI_INT_KEY_2_OFFSET 0x000000D0 +/// Index of the ENCR_WPI_INT_KEY_2 register +#define NXMAC_ENCR_WPI_INT_KEY_2_INDEX 0x00000034 +/// Reset value of the ENCR_WPI_INT_KEY_2 register +#define NXMAC_ENCR_WPI_INT_KEY_2_RESET 0x00000000 + +/** + * @brief Returns the current value of the ENCR_WPI_INT_KEY_2 register. + * The ENCR_WPI_INT_KEY_2 register will be read and its value returned. + * @return The current value of the ENCR_WPI_INT_KEY_2 register. + */ +__INLINE uint32_t nxmac_encr_wpi_int_key_2_get(void) +{ + return REG_PL_RD(NXMAC_ENCR_WPI_INT_KEY_2_ADDR); +} + +/** + * @brief Sets the ENCR_WPI_INT_KEY_2 register to a value. + * The ENCR_WPI_INT_KEY_2 register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_encr_wpi_int_key_2_set(uint32_t value) +{ + REG_PL_WR(NXMAC_ENCR_WPI_INT_KEY_2_ADDR, value); +} + +// field definitions +/// ENCR_INT_KEY_RAM_WORD_2 field mask +#define NXMAC_ENCR_INT_KEY_RAM_WORD_2_MASK ((uint32_t)0xFFFFFFFF) +/// ENCR_INT_KEY_RAM_WORD_2 field LSB position +#define NXMAC_ENCR_INT_KEY_RAM_WORD_2_LSB 0 +/// ENCR_INT_KEY_RAM_WORD_2 field width +#define NXMAC_ENCR_INT_KEY_RAM_WORD_2_WIDTH ((uint32_t)0x00000020) + +/// ENCR_INT_KEY_RAM_WORD_2 field reset value +#define NXMAC_ENCR_INT_KEY_RAM_WORD_2_RST 0x0 + +/** + * @brief Returns the current value of the encrIntKeyRAMWord2 field in the ENCR_WPI_INT_KEY_2 register. + * + * The ENCR_WPI_INT_KEY_2 register will be read and the encrIntKeyRAMWord2 field's value will be returned. + * + * @return The current value of the encrIntKeyRAMWord2 field in the ENCR_WPI_INT_KEY_2 register. + */ +__INLINE uint32_t nxmac_encr_int_key_ram_word_2_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_ENCR_WPI_INT_KEY_2_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the encrIntKeyRAMWord2 field of the ENCR_WPI_INT_KEY_2 register. + * + * The ENCR_WPI_INT_KEY_2 register will be read, modified to contain the new field value, and written. + * + * @param[in] encrintkeyramword2 - The value to set the field to. + */ +__INLINE void nxmac_encr_int_key_ram_word_2_setf(uint32_t encrintkeyramword2) +{ + ASSERT_ERR((((uint32_t)encrintkeyramword2 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(NXMAC_ENCR_WPI_INT_KEY_2_ADDR, (uint32_t)encrintkeyramword2 << 0); +} + +#endif // RW_WAPI_EN +/// @} + +#if RW_WAPI_EN +/** + * @name ENCR_WPI_INT_KEY_3 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00   encrIntKeyRAMWord3   0x0
+ * 
+ * + * @{ + */ + +/// Address of the ENCR_WPI_INT_KEY_3 register +#define NXMAC_ENCR_WPI_INT_KEY_3_ADDR 0xC00000D4 +/// Offset of the ENCR_WPI_INT_KEY_3 register from the base address +#define NXMAC_ENCR_WPI_INT_KEY_3_OFFSET 0x000000D4 +/// Index of the ENCR_WPI_INT_KEY_3 register +#define NXMAC_ENCR_WPI_INT_KEY_3_INDEX 0x00000035 +/// Reset value of the ENCR_WPI_INT_KEY_3 register +#define NXMAC_ENCR_WPI_INT_KEY_3_RESET 0x00000000 + +/** + * @brief Returns the current value of the ENCR_WPI_INT_KEY_3 register. + * The ENCR_WPI_INT_KEY_3 register will be read and its value returned. + * @return The current value of the ENCR_WPI_INT_KEY_3 register. + */ +__INLINE uint32_t nxmac_encr_wpi_int_key_3_get(void) +{ + return REG_PL_RD(NXMAC_ENCR_WPI_INT_KEY_3_ADDR); +} + +/** + * @brief Sets the ENCR_WPI_INT_KEY_3 register to a value. + * The ENCR_WPI_INT_KEY_3 register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_encr_wpi_int_key_3_set(uint32_t value) +{ + REG_PL_WR(NXMAC_ENCR_WPI_INT_KEY_3_ADDR, value); +} + +// field definitions +/// ENCR_INT_KEY_RAM_WORD_3 field mask +#define NXMAC_ENCR_INT_KEY_RAM_WORD_3_MASK ((uint32_t)0xFFFFFFFF) +/// ENCR_INT_KEY_RAM_WORD_3 field LSB position +#define NXMAC_ENCR_INT_KEY_RAM_WORD_3_LSB 0 +/// ENCR_INT_KEY_RAM_WORD_3 field width +#define NXMAC_ENCR_INT_KEY_RAM_WORD_3_WIDTH ((uint32_t)0x00000020) + +/// ENCR_INT_KEY_RAM_WORD_3 field reset value +#define NXMAC_ENCR_INT_KEY_RAM_WORD_3_RST 0x0 + +/** + * @brief Returns the current value of the encrIntKeyRAMWord3 field in the ENCR_WPI_INT_KEY_3 register. + * + * The ENCR_WPI_INT_KEY_3 register will be read and the encrIntKeyRAMWord3 field's value will be returned. + * + * @return The current value of the encrIntKeyRAMWord3 field in the ENCR_WPI_INT_KEY_3 register. + */ +__INLINE uint32_t nxmac_encr_int_key_ram_word_3_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_ENCR_WPI_INT_KEY_3_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the encrIntKeyRAMWord3 field of the ENCR_WPI_INT_KEY_3 register. + * + * The ENCR_WPI_INT_KEY_3 register will be read, modified to contain the new field value, and written. + * + * @param[in] encrintkeyramword3 - The value to set the field to. + */ +__INLINE void nxmac_encr_int_key_ram_word_3_setf(uint32_t encrintkeyramword3) +{ + ASSERT_ERR((((uint32_t)encrintkeyramword3 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(NXMAC_ENCR_WPI_INT_KEY_3_ADDR, (uint32_t)encrintkeyramword3 << 0); +} + +#endif // RW_WAPI_EN +/// @} + +/** + * @name ENCR_RAM_CONFIG register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:24       staKeyMaxIndex   0x0
+ *  19:16                 nVAP   0x0
+ *  15:08       staKeyEndIndex   0x0
+ *  07:00     staKeyStartIndex   0x0
+ * 
+ * + * @{ + */ + +/// Address of the ENCR_RAM_CONFIG register +#define NXMAC_ENCR_RAM_CONFIG_ADDR 0xC00000D8 +/// Offset of the ENCR_RAM_CONFIG register from the base address +#define NXMAC_ENCR_RAM_CONFIG_OFFSET 0x000000D8 +/// Index of the ENCR_RAM_CONFIG register +#define NXMAC_ENCR_RAM_CONFIG_INDEX 0x00000036 +/// Reset value of the ENCR_RAM_CONFIG register +#define NXMAC_ENCR_RAM_CONFIG_RESET 0x00000000 + +/** + * @brief Returns the current value of the ENCR_RAM_CONFIG register. + * The ENCR_RAM_CONFIG register will be read and its value returned. + * @return The current value of the ENCR_RAM_CONFIG register. + */ +__INLINE uint32_t nxmac_encr_ram_config_get(void) +{ + return REG_PL_RD(NXMAC_ENCR_RAM_CONFIG_ADDR); +} + +/** + * @brief Sets the ENCR_RAM_CONFIG register to a value. + * The ENCR_RAM_CONFIG register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_encr_ram_config_set(uint32_t value) +{ + REG_PL_WR(NXMAC_ENCR_RAM_CONFIG_ADDR, value); +} + +// field definitions +/// STA_KEY_MAX_INDEX field mask +#define NXMAC_STA_KEY_MAX_INDEX_MASK ((uint32_t)0xFF000000) +/// STA_KEY_MAX_INDEX field LSB position +#define NXMAC_STA_KEY_MAX_INDEX_LSB 24 +/// STA_KEY_MAX_INDEX field width +#define NXMAC_STA_KEY_MAX_INDEX_WIDTH ((uint32_t)0x00000008) +/// N_VAP field mask +#define NXMAC_N_VAP_MASK ((uint32_t)0x000F0000) +/// N_VAP field LSB position +#define NXMAC_N_VAP_LSB 16 +/// N_VAP field width +#define NXMAC_N_VAP_WIDTH ((uint32_t)0x00000004) +/// STA_KEY_END_INDEX field mask +#define NXMAC_STA_KEY_END_INDEX_MASK ((uint32_t)0x0000FF00) +/// STA_KEY_END_INDEX field LSB position +#define NXMAC_STA_KEY_END_INDEX_LSB 8 +/// STA_KEY_END_INDEX field width +#define NXMAC_STA_KEY_END_INDEX_WIDTH ((uint32_t)0x00000008) +/// STA_KEY_START_INDEX field mask +#define NXMAC_STA_KEY_START_INDEX_MASK ((uint32_t)0x000000FF) +/// STA_KEY_START_INDEX field LSB position +#define NXMAC_STA_KEY_START_INDEX_LSB 0 +/// STA_KEY_START_INDEX field width +#define NXMAC_STA_KEY_START_INDEX_WIDTH ((uint32_t)0x00000008) + +/// STA_KEY_MAX_INDEX field reset value +#define NXMAC_STA_KEY_MAX_INDEX_RST 0x0 +/// N_VAP field reset value +#define NXMAC_N_VAP_RST 0x0 +/// STA_KEY_END_INDEX field reset value +#define NXMAC_STA_KEY_END_INDEX_RST 0x0 +/// STA_KEY_START_INDEX field reset value +#define NXMAC_STA_KEY_START_INDEX_RST 0x0 + +/** + * @brief Constructs a value for the ENCR_RAM_CONFIG register given values for its fields + * and writes the value to the register. + * + * @param[in] nvap - The value to use for the nVAP field. + * @param[in] stakeyendindex - The value to use for the staKeyEndIndex field. + * @param[in] stakeystartindex - The value to use for the staKeyStartIndex field. + */ +__INLINE void nxmac_encr_ram_config_pack(uint8_t nvap, uint8_t stakeyendindex, uint8_t stakeystartindex) +{ + ASSERT_ERR((((uint32_t)nvap << 16) & ~((uint32_t)0x000F0000)) == 0); + ASSERT_ERR((((uint32_t)stakeyendindex << 8) & ~((uint32_t)0x0000FF00)) == 0); + ASSERT_ERR((((uint32_t)stakeystartindex << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(NXMAC_ENCR_RAM_CONFIG_ADDR, ((uint32_t)nvap << 16) | ((uint32_t)stakeyendindex << 8) | ((uint32_t)stakeystartindex << 0)); +} + +/** + * @brief Unpacks ENCR_RAM_CONFIG's fields from current value of the ENCR_RAM_CONFIG register. + * + * Reads the ENCR_RAM_CONFIG register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] stakeymaxindex - Will be populated with the current value of this field from the register. + * @param[out] nvap - Will be populated with the current value of this field from the register. + * @param[out] stakeyendindex - Will be populated with the current value of this field from the register. + * @param[out] stakeystartindex - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_encr_ram_config_unpack(uint8_t *stakeymaxindex, uint8_t *nvap, uint8_t *stakeyendindex, uint8_t *stakeystartindex) +{ + uint32_t localVal = REG_PL_RD(NXMAC_ENCR_RAM_CONFIG_ADDR); + + *stakeymaxindex = (localVal & ((uint32_t)0xFF000000)) >> 24; + *nvap = (localVal & ((uint32_t)0x000F0000)) >> 16; + *stakeyendindex = (localVal & ((uint32_t)0x0000FF00)) >> 8; + *stakeystartindex = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +/** + * @brief Returns the current value of the staKeyMaxIndex field in the ENCR_RAM_CONFIG register. + * + * The ENCR_RAM_CONFIG register will be read and the staKeyMaxIndex field's value will be returned. + * + * @return The current value of the staKeyMaxIndex field in the ENCR_RAM_CONFIG register. + */ +__INLINE uint8_t nxmac_sta_key_max_index_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_ENCR_RAM_CONFIG_ADDR); + return ((localVal & ((uint32_t)0xFF000000)) >> 24); +} + +/** + * @brief Returns the current value of the nVAP field in the ENCR_RAM_CONFIG register. + * + * The ENCR_RAM_CONFIG register will be read and the nVAP field's value will be returned. + * + * @return The current value of the nVAP field in the ENCR_RAM_CONFIG register. + */ +__INLINE uint8_t nxmac_n_vap_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_ENCR_RAM_CONFIG_ADDR); + return ((localVal & ((uint32_t)0x000F0000)) >> 16); +} + +/** + * @brief Sets the nVAP field of the ENCR_RAM_CONFIG register. + * + * The ENCR_RAM_CONFIG register will be read, modified to contain the new field value, and written. + * + * @param[in] nvap - The value to set the field to. + */ +__INLINE void nxmac_n_vap_setf(uint8_t nvap) +{ + ASSERT_ERR((((uint32_t)nvap << 16) & ~((uint32_t)0x000F0000)) == 0); + REG_PL_WR(NXMAC_ENCR_RAM_CONFIG_ADDR, (REG_PL_RD(NXMAC_ENCR_RAM_CONFIG_ADDR) & ~((uint32_t)0x000F0000)) | ((uint32_t)nvap << 16)); +} + +/** + * @brief Returns the current value of the staKeyEndIndex field in the ENCR_RAM_CONFIG register. + * + * The ENCR_RAM_CONFIG register will be read and the staKeyEndIndex field's value will be returned. + * + * @return The current value of the staKeyEndIndex field in the ENCR_RAM_CONFIG register. + */ +__INLINE uint8_t nxmac_sta_key_end_index_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_ENCR_RAM_CONFIG_ADDR); + return ((localVal & ((uint32_t)0x0000FF00)) >> 8); +} + +/** + * @brief Sets the staKeyEndIndex field of the ENCR_RAM_CONFIG register. + * + * The ENCR_RAM_CONFIG register will be read, modified to contain the new field value, and written. + * + * @param[in] stakeyendindex - The value to set the field to. + */ +__INLINE void nxmac_sta_key_end_index_setf(uint8_t stakeyendindex) +{ + ASSERT_ERR((((uint32_t)stakeyendindex << 8) & ~((uint32_t)0x0000FF00)) == 0); + REG_PL_WR(NXMAC_ENCR_RAM_CONFIG_ADDR, (REG_PL_RD(NXMAC_ENCR_RAM_CONFIG_ADDR) & ~((uint32_t)0x0000FF00)) | ((uint32_t)stakeyendindex << 8)); +} + +/** + * @brief Returns the current value of the staKeyStartIndex field in the ENCR_RAM_CONFIG register. + * + * The ENCR_RAM_CONFIG register will be read and the staKeyStartIndex field's value will be returned. + * + * @return The current value of the staKeyStartIndex field in the ENCR_RAM_CONFIG register. + */ +__INLINE uint8_t nxmac_sta_key_start_index_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_ENCR_RAM_CONFIG_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +/** + * @brief Sets the staKeyStartIndex field of the ENCR_RAM_CONFIG register. + * + * The ENCR_RAM_CONFIG register will be read, modified to contain the new field value, and written. + * + * @param[in] stakeystartindex - The value to set the field to. + */ +__INLINE void nxmac_sta_key_start_index_setf(uint8_t stakeystartindex) +{ + ASSERT_ERR((((uint32_t)stakeystartindex << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(NXMAC_ENCR_RAM_CONFIG_ADDR, (REG_PL_RD(NXMAC_ENCR_RAM_CONFIG_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)stakeystartindex << 0)); +} + +/// @} + +/** + * @name RATES register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  11:00      bssBasicRateSet   0x150
+ * 
+ * + * @{ + */ + +/// Address of the RATES register +#define NXMAC_RATES_ADDR 0xC00000DC +/// Offset of the RATES register from the base address +#define NXMAC_RATES_OFFSET 0x000000DC +/// Index of the RATES register +#define NXMAC_RATES_INDEX 0x00000037 +/// Reset value of the RATES register +#define NXMAC_RATES_RESET 0x00000150 + +/** + * @brief Returns the current value of the RATES register. + * The RATES register will be read and its value returned. + * @return The current value of the RATES register. + */ +__INLINE uint32_t nxmac_rates_get(void) +{ + return REG_PL_RD(NXMAC_RATES_ADDR); +} + +/** + * @brief Sets the RATES register to a value. + * The RATES register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_rates_set(uint32_t value) +{ + REG_PL_WR(NXMAC_RATES_ADDR, value); +} + +// field definitions +/// BSS_BASIC_RATE_SET field mask +#define NXMAC_BSS_BASIC_RATE_SET_MASK ((uint32_t)0x00000FFF) +/// BSS_BASIC_RATE_SET field LSB position +#define NXMAC_BSS_BASIC_RATE_SET_LSB 0 +/// BSS_BASIC_RATE_SET field width +#define NXMAC_BSS_BASIC_RATE_SET_WIDTH ((uint32_t)0x0000000C) + +/// BSS_BASIC_RATE_SET field reset value +#define NXMAC_BSS_BASIC_RATE_SET_RST 0x150 + +/** + * @brief Returns the current value of the bssBasicRateSet field in the RATES register. + * + * The RATES register will be read and the bssBasicRateSet field's value will be returned. + * + * @return The current value of the bssBasicRateSet field in the RATES register. + */ +__INLINE uint16_t nxmac_bss_basic_rate_set_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_RATES_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x00000FFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the bssBasicRateSet field of the RATES register. + * + * The RATES register will be read, modified to contain the new field value, and written. + * + * @param[in] bssbasicrateset - The value to set the field to. + */ +__INLINE void nxmac_bss_basic_rate_set_setf(uint16_t bssbasicrateset) +{ + ASSERT_ERR((((uint32_t)bssbasicrateset << 0) & ~((uint32_t)0x00000FFF)) == 0); + REG_PL_WR(NXMAC_RATES_ADDR, (uint32_t)bssbasicrateset << 0); +} + +/// @} + +/** + * @name OLBC register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:24            dsssCount   0x0
+ *  23:16            ofdmCount   0x0
+ *  15:00            olbcTimer   0x0
+ * 
+ * + * @{ + */ + +/// Address of the OLBC register +#define NXMAC_OLBC_ADDR 0xC00000E0 +/// Offset of the OLBC register from the base address +#define NXMAC_OLBC_OFFSET 0x000000E0 +/// Index of the OLBC register +#define NXMAC_OLBC_INDEX 0x00000038 +/// Reset value of the OLBC register +#define NXMAC_OLBC_RESET 0x00000000 + +/** + * @brief Returns the current value of the OLBC register. + * The OLBC register will be read and its value returned. + * @return The current value of the OLBC register. + */ +__INLINE uint32_t nxmac_olbc_get(void) +{ + return REG_PL_RD(NXMAC_OLBC_ADDR); +} + +/** + * @brief Sets the OLBC register to a value. + * The OLBC register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_olbc_set(uint32_t value) +{ + REG_PL_WR(NXMAC_OLBC_ADDR, value); +} + +// field definitions +/// DSSS_COUNT field mask +#define NXMAC_DSSS_COUNT_MASK ((uint32_t)0xFF000000) +/// DSSS_COUNT field LSB position +#define NXMAC_DSSS_COUNT_LSB 24 +/// DSSS_COUNT field width +#define NXMAC_DSSS_COUNT_WIDTH ((uint32_t)0x00000008) +/// OFDM_COUNT field mask +#define NXMAC_OFDM_COUNT_MASK ((uint32_t)0x00FF0000) +/// OFDM_COUNT field LSB position +#define NXMAC_OFDM_COUNT_LSB 16 +/// OFDM_COUNT field width +#define NXMAC_OFDM_COUNT_WIDTH ((uint32_t)0x00000008) +/// OLBC_TIMER field mask +#define NXMAC_OLBC_TIMER_MASK ((uint32_t)0x0000FFFF) +/// OLBC_TIMER field LSB position +#define NXMAC_OLBC_TIMER_LSB 0 +/// OLBC_TIMER field width +#define NXMAC_OLBC_TIMER_WIDTH ((uint32_t)0x00000010) + +/// DSSS_COUNT field reset value +#define NXMAC_DSSS_COUNT_RST 0x0 +/// OFDM_COUNT field reset value +#define NXMAC_OFDM_COUNT_RST 0x0 +/// OLBC_TIMER field reset value +#define NXMAC_OLBC_TIMER_RST 0x0 + +/** + * @brief Constructs a value for the OLBC register given values for its fields + * and writes the value to the register. + * + * @param[in] dssscount - The value to use for the dsssCount field. + * @param[in] ofdmcount - The value to use for the ofdmCount field. + * @param[in] olbctimer - The value to use for the olbcTimer field. + */ +__INLINE void nxmac_olbc_pack(uint8_t dssscount, uint8_t ofdmcount, uint16_t olbctimer) +{ + ASSERT_ERR((((uint32_t)dssscount << 24) & ~((uint32_t)0xFF000000)) == 0); + ASSERT_ERR((((uint32_t)ofdmcount << 16) & ~((uint32_t)0x00FF0000)) == 0); + ASSERT_ERR((((uint32_t)olbctimer << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_PL_WR(NXMAC_OLBC_ADDR, ((uint32_t)dssscount << 24) | ((uint32_t)ofdmcount << 16) | ((uint32_t)olbctimer << 0)); +} + +/** + * @brief Unpacks OLBC's fields from current value of the OLBC register. + * + * Reads the OLBC register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] dssscount - Will be populated with the current value of this field from the register. + * @param[out] ofdmcount - Will be populated with the current value of this field from the register. + * @param[out] olbctimer - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_olbc_unpack(uint8_t *dssscount, uint8_t *ofdmcount, uint16_t *olbctimer) +{ + uint32_t localVal = REG_PL_RD(NXMAC_OLBC_ADDR); + + *dssscount = (localVal & ((uint32_t)0xFF000000)) >> 24; + *ofdmcount = (localVal & ((uint32_t)0x00FF0000)) >> 16; + *olbctimer = (localVal & ((uint32_t)0x0000FFFF)) >> 0; +} + +/** + * @brief Returns the current value of the dsssCount field in the OLBC register. + * + * The OLBC register will be read and the dsssCount field's value will be returned. + * + * @return The current value of the dsssCount field in the OLBC register. + */ +__INLINE uint8_t nxmac_dsss_count_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_OLBC_ADDR); + return ((localVal & ((uint32_t)0xFF000000)) >> 24); +} + +/** + * @brief Sets the dsssCount field of the OLBC register. + * + * The OLBC register will be read, modified to contain the new field value, and written. + * + * @param[in] dssscount - The value to set the field to. + */ +__INLINE void nxmac_dsss_count_setf(uint8_t dssscount) +{ + ASSERT_ERR((((uint32_t)dssscount << 24) & ~((uint32_t)0xFF000000)) == 0); + REG_PL_WR(NXMAC_OLBC_ADDR, (REG_PL_RD(NXMAC_OLBC_ADDR) & ~((uint32_t)0xFF000000)) | ((uint32_t)dssscount << 24)); +} + +/** + * @brief Returns the current value of the ofdmCount field in the OLBC register. + * + * The OLBC register will be read and the ofdmCount field's value will be returned. + * + * @return The current value of the ofdmCount field in the OLBC register. + */ +__INLINE uint8_t nxmac_ofdm_count_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_OLBC_ADDR); + return ((localVal & ((uint32_t)0x00FF0000)) >> 16); +} + +/** + * @brief Sets the ofdmCount field of the OLBC register. + * + * The OLBC register will be read, modified to contain the new field value, and written. + * + * @param[in] ofdmcount - The value to set the field to. + */ +__INLINE void nxmac_ofdm_count_setf(uint8_t ofdmcount) +{ + ASSERT_ERR((((uint32_t)ofdmcount << 16) & ~((uint32_t)0x00FF0000)) == 0); + REG_PL_WR(NXMAC_OLBC_ADDR, (REG_PL_RD(NXMAC_OLBC_ADDR) & ~((uint32_t)0x00FF0000)) | ((uint32_t)ofdmcount << 16)); +} + +/** + * @brief Returns the current value of the olbcTimer field in the OLBC register. + * + * The OLBC register will be read and the olbcTimer field's value will be returned. + * + * @return The current value of the olbcTimer field in the OLBC register. + */ +__INLINE uint16_t nxmac_olbc_timer_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_OLBC_ADDR); + return ((localVal & ((uint32_t)0x0000FFFF)) >> 0); +} + +/** + * @brief Sets the olbcTimer field of the OLBC register. + * + * The OLBC register will be read, modified to contain the new field value, and written. + * + * @param[in] olbctimer - The value to set the field to. + */ +__INLINE void nxmac_olbc_timer_setf(uint16_t olbctimer) +{ + ASSERT_ERR((((uint32_t)olbctimer << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_PL_WR(NXMAC_OLBC_ADDR, (REG_PL_RD(NXMAC_OLBC_ADDR) & ~((uint32_t)0x0000FFFF)) | ((uint32_t)olbctimer << 0)); +} + +/// @} + +/** + * @name TIMINGS_1 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  27:18   txChainDelayInMACClk   0x0
+ *  17:08    txRFDelayInMACClk   0x0
+ *  07:00       macCoreClkFreq   0x0
+ * 
+ * + * @{ + */ + +/// Address of the TIMINGS_1 register +#define NXMAC_TIMINGS_1_ADDR 0xC00000E4 +/// Offset of the TIMINGS_1 register from the base address +#define NXMAC_TIMINGS_1_OFFSET 0x000000E4 +/// Index of the TIMINGS_1 register +#define NXMAC_TIMINGS_1_INDEX 0x00000039 +/// Reset value of the TIMINGS_1 register +#define NXMAC_TIMINGS_1_RESET 0x00000000 + +/** + * @brief Returns the current value of the TIMINGS_1 register. + * The TIMINGS_1 register will be read and its value returned. + * @return The current value of the TIMINGS_1 register. + */ +__INLINE uint32_t nxmac_timings_1_get(void) +{ + return REG_PL_RD(NXMAC_TIMINGS_1_ADDR); +} + +/** + * @brief Sets the TIMINGS_1 register to a value. + * The TIMINGS_1 register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_timings_1_set(uint32_t value) +{ + REG_PL_WR(NXMAC_TIMINGS_1_ADDR, value); +} + +// field definitions +/// TX_CHAIN_DELAY_IN_MAC_CLK field mask +#define NXMAC_TX_CHAIN_DELAY_IN_MAC_CLK_MASK ((uint32_t)0x0FFC0000) +/// TX_CHAIN_DELAY_IN_MAC_CLK field LSB position +#define NXMAC_TX_CHAIN_DELAY_IN_MAC_CLK_LSB 18 +/// TX_CHAIN_DELAY_IN_MAC_CLK field width +#define NXMAC_TX_CHAIN_DELAY_IN_MAC_CLK_WIDTH ((uint32_t)0x0000000A) +/// TX_RF_DELAY_IN_MAC_CLK field mask +#define NXMAC_TX_RF_DELAY_IN_MAC_CLK_MASK ((uint32_t)0x0003FF00) +/// TX_RF_DELAY_IN_MAC_CLK field LSB position +#define NXMAC_TX_RF_DELAY_IN_MAC_CLK_LSB 8 +/// TX_RF_DELAY_IN_MAC_CLK field width +#define NXMAC_TX_RF_DELAY_IN_MAC_CLK_WIDTH ((uint32_t)0x0000000A) +/// MAC_CORE_CLK_FREQ field mask +#define NXMAC_MAC_CORE_CLK_FREQ_MASK ((uint32_t)0x000000FF) +/// MAC_CORE_CLK_FREQ field LSB position +#define NXMAC_MAC_CORE_CLK_FREQ_LSB 0 +/// MAC_CORE_CLK_FREQ field width +#define NXMAC_MAC_CORE_CLK_FREQ_WIDTH ((uint32_t)0x00000008) + +/// TX_CHAIN_DELAY_IN_MAC_CLK field reset value +#define NXMAC_TX_CHAIN_DELAY_IN_MAC_CLK_RST 0x0 +/// TX_RF_DELAY_IN_MAC_CLK field reset value +#define NXMAC_TX_RF_DELAY_IN_MAC_CLK_RST 0x0 +/// MAC_CORE_CLK_FREQ field reset value +#define NXMAC_MAC_CORE_CLK_FREQ_RST 0x0 + +/** + * @brief Constructs a value for the TIMINGS_1 register given values for its fields + * and writes the value to the register. + * + * @param[in] txchaindelayinmacclk - The value to use for the txChainDelayInMACClk field. + * @param[in] txrfdelayinmacclk - The value to use for the txRFDelayInMACClk field. + * @param[in] maccoreclkfreq - The value to use for the macCoreClkFreq field. + */ +__INLINE void nxmac_timings_1_pack(uint16_t txchaindelayinmacclk, uint16_t txrfdelayinmacclk, uint8_t maccoreclkfreq) +{ + ASSERT_ERR((((uint32_t)txchaindelayinmacclk << 18) & ~((uint32_t)0x0FFC0000)) == 0); + ASSERT_ERR((((uint32_t)txrfdelayinmacclk << 8) & ~((uint32_t)0x0003FF00)) == 0); + ASSERT_ERR((((uint32_t)maccoreclkfreq << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(NXMAC_TIMINGS_1_ADDR, ((uint32_t)txchaindelayinmacclk << 18) | ((uint32_t)txrfdelayinmacclk << 8) | ((uint32_t)maccoreclkfreq << 0)); +} + +/** + * @brief Unpacks TIMINGS_1's fields from current value of the TIMINGS_1 register. + * + * Reads the TIMINGS_1 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] txchaindelayinmacclk - Will be populated with the current value of this field from the register. + * @param[out] txrfdelayinmacclk - Will be populated with the current value of this field from the register. + * @param[out] maccoreclkfreq - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_timings_1_unpack(uint16_t *txchaindelayinmacclk, uint16_t *txrfdelayinmacclk, uint8_t *maccoreclkfreq) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMINGS_1_ADDR); + + *txchaindelayinmacclk = (localVal & ((uint32_t)0x0FFC0000)) >> 18; + *txrfdelayinmacclk = (localVal & ((uint32_t)0x0003FF00)) >> 8; + *maccoreclkfreq = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +/** + * @brief Returns the current value of the txChainDelayInMACClk field in the TIMINGS_1 register. + * + * The TIMINGS_1 register will be read and the txChainDelayInMACClk field's value will be returned. + * + * @return The current value of the txChainDelayInMACClk field in the TIMINGS_1 register. + */ +__INLINE uint16_t nxmac_tx_chain_delay_in_mac_clk_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMINGS_1_ADDR); + return ((localVal & ((uint32_t)0x0FFC0000)) >> 18); +} + +/** + * @brief Sets the txChainDelayInMACClk field of the TIMINGS_1 register. + * + * The TIMINGS_1 register will be read, modified to contain the new field value, and written. + * + * @param[in] txchaindelayinmacclk - The value to set the field to. + */ +__INLINE void nxmac_tx_chain_delay_in_mac_clk_setf(uint16_t txchaindelayinmacclk) +{ + ASSERT_ERR((((uint32_t)txchaindelayinmacclk << 18) & ~((uint32_t)0x0FFC0000)) == 0); + REG_PL_WR(NXMAC_TIMINGS_1_ADDR, (REG_PL_RD(NXMAC_TIMINGS_1_ADDR) & ~((uint32_t)0x0FFC0000)) | ((uint32_t)txchaindelayinmacclk << 18)); +} + +/** + * @brief Returns the current value of the txRFDelayInMACClk field in the TIMINGS_1 register. + * + * The TIMINGS_1 register will be read and the txRFDelayInMACClk field's value will be returned. + * + * @return The current value of the txRFDelayInMACClk field in the TIMINGS_1 register. + */ +__INLINE uint16_t nxmac_tx_rf_delay_in_mac_clk_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMINGS_1_ADDR); + return ((localVal & ((uint32_t)0x0003FF00)) >> 8); +} + +/** + * @brief Sets the txRFDelayInMACClk field of the TIMINGS_1 register. + * + * The TIMINGS_1 register will be read, modified to contain the new field value, and written. + * + * @param[in] txrfdelayinmacclk - The value to set the field to. + */ +__INLINE void nxmac_tx_rf_delay_in_mac_clk_setf(uint16_t txrfdelayinmacclk) +{ + ASSERT_ERR((((uint32_t)txrfdelayinmacclk << 8) & ~((uint32_t)0x0003FF00)) == 0); + REG_PL_WR(NXMAC_TIMINGS_1_ADDR, (REG_PL_RD(NXMAC_TIMINGS_1_ADDR) & ~((uint32_t)0x0003FF00)) | ((uint32_t)txrfdelayinmacclk << 8)); +} + +/** + * @brief Returns the current value of the macCoreClkFreq field in the TIMINGS_1 register. + * + * The TIMINGS_1 register will be read and the macCoreClkFreq field's value will be returned. + * + * @return The current value of the macCoreClkFreq field in the TIMINGS_1 register. + */ +__INLINE uint8_t nxmac_mac_core_clk_freq_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMINGS_1_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +/** + * @brief Sets the macCoreClkFreq field of the TIMINGS_1 register. + * + * The TIMINGS_1 register will be read, modified to contain the new field value, and written. + * + * @param[in] maccoreclkfreq - The value to set the field to. + */ +__INLINE void nxmac_mac_core_clk_freq_setf(uint8_t maccoreclkfreq) +{ + ASSERT_ERR((((uint32_t)maccoreclkfreq << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(NXMAC_TIMINGS_1_ADDR, (REG_PL_RD(NXMAC_TIMINGS_1_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)maccoreclkfreq << 0)); +} + +/// @} + +/** + * @name TIMINGS_2 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  23:08     slotTimeInMACClk   0x0
+ *  07:00             slotTime   0x0
+ * 
+ * + * @{ + */ + +/// Address of the TIMINGS_2 register +#define NXMAC_TIMINGS_2_ADDR 0xC00000E8 +/// Offset of the TIMINGS_2 register from the base address +#define NXMAC_TIMINGS_2_OFFSET 0x000000E8 +/// Index of the TIMINGS_2 register +#define NXMAC_TIMINGS_2_INDEX 0x0000003A +/// Reset value of the TIMINGS_2 register +#define NXMAC_TIMINGS_2_RESET 0x00000000 + +/** + * @brief Returns the current value of the TIMINGS_2 register. + * The TIMINGS_2 register will be read and its value returned. + * @return The current value of the TIMINGS_2 register. + */ +__INLINE uint32_t nxmac_timings_2_get(void) +{ + return REG_PL_RD(NXMAC_TIMINGS_2_ADDR); +} + +/** + * @brief Sets the TIMINGS_2 register to a value. + * The TIMINGS_2 register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_timings_2_set(uint32_t value) +{ + REG_PL_WR(NXMAC_TIMINGS_2_ADDR, value); +} + +// field definitions +/// SLOT_TIME_IN_MAC_CLK field mask +#define NXMAC_SLOT_TIME_IN_MAC_CLK_MASK ((uint32_t)0x00FFFF00) +/// SLOT_TIME_IN_MAC_CLK field LSB position +#define NXMAC_SLOT_TIME_IN_MAC_CLK_LSB 8 +/// SLOT_TIME_IN_MAC_CLK field width +#define NXMAC_SLOT_TIME_IN_MAC_CLK_WIDTH ((uint32_t)0x00000010) +/// SLOT_TIME field mask +#define NXMAC_SLOT_TIME_MASK ((uint32_t)0x000000FF) +/// SLOT_TIME field LSB position +#define NXMAC_SLOT_TIME_LSB 0 +/// SLOT_TIME field width +#define NXMAC_SLOT_TIME_WIDTH ((uint32_t)0x00000008) + +/// SLOT_TIME_IN_MAC_CLK field reset value +#define NXMAC_SLOT_TIME_IN_MAC_CLK_RST 0x0 +/// SLOT_TIME field reset value +#define NXMAC_SLOT_TIME_RST 0x0 + +/** + * @brief Constructs a value for the TIMINGS_2 register given values for its fields + * and writes the value to the register. + * + * @param[in] slottimeinmacclk - The value to use for the slotTimeInMACClk field. + * @param[in] slottime - The value to use for the slotTime field. + */ +__INLINE void nxmac_timings_2_pack(uint16_t slottimeinmacclk, uint8_t slottime) +{ + ASSERT_ERR((((uint32_t)slottimeinmacclk << 8) & ~((uint32_t)0x00FFFF00)) == 0); + ASSERT_ERR((((uint32_t)slottime << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(NXMAC_TIMINGS_2_ADDR, ((uint32_t)slottimeinmacclk << 8) | ((uint32_t)slottime << 0)); +} + +/** + * @brief Unpacks TIMINGS_2's fields from current value of the TIMINGS_2 register. + * + * Reads the TIMINGS_2 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] slottimeinmacclk - Will be populated with the current value of this field from the register. + * @param[out] slottime - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_timings_2_unpack(uint16_t *slottimeinmacclk, uint8_t *slottime) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMINGS_2_ADDR); + + *slottimeinmacclk = (localVal & ((uint32_t)0x00FFFF00)) >> 8; + *slottime = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +/** + * @brief Returns the current value of the slotTimeInMACClk field in the TIMINGS_2 register. + * + * The TIMINGS_2 register will be read and the slotTimeInMACClk field's value will be returned. + * + * @return The current value of the slotTimeInMACClk field in the TIMINGS_2 register. + */ +__INLINE uint16_t nxmac_slot_time_in_mac_clk_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMINGS_2_ADDR); + return ((localVal & ((uint32_t)0x00FFFF00)) >> 8); +} + +/** + * @brief Sets the slotTimeInMACClk field of the TIMINGS_2 register. + * + * The TIMINGS_2 register will be read, modified to contain the new field value, and written. + * + * @param[in] slottimeinmacclk - The value to set the field to. + */ +__INLINE void nxmac_slot_time_in_mac_clk_setf(uint16_t slottimeinmacclk) +{ + ASSERT_ERR((((uint32_t)slottimeinmacclk << 8) & ~((uint32_t)0x00FFFF00)) == 0); + REG_PL_WR(NXMAC_TIMINGS_2_ADDR, (REG_PL_RD(NXMAC_TIMINGS_2_ADDR) & ~((uint32_t)0x00FFFF00)) | ((uint32_t)slottimeinmacclk << 8)); +} + +/** + * @brief Returns the current value of the slotTime field in the TIMINGS_2 register. + * + * The TIMINGS_2 register will be read and the slotTime field's value will be returned. + * + * @return The current value of the slotTime field in the TIMINGS_2 register. + */ +__INLINE uint8_t nxmac_slot_time_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMINGS_2_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +/** + * @brief Sets the slotTime field of the TIMINGS_2 register. + * + * The TIMINGS_2 register will be read, modified to contain the new field value, and written. + * + * @param[in] slottime - The value to set the field to. + */ +__INLINE void nxmac_slot_time_setf(uint8_t slottime) +{ + ASSERT_ERR((((uint32_t)slottime << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(NXMAC_TIMINGS_2_ADDR, (REG_PL_RD(NXMAC_TIMINGS_2_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)slottime << 0)); +} + +/// @} + +/** + * @name TIMINGS_3 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  29:20    rxRFDelayInMACClk   0x0
+ *  19:10   txDelayRFOnInMACClk   0x0
+ *  09:00   macProcDelayInMACClk   0x0
+ * 
+ * + * @{ + */ + +/// Address of the TIMINGS_3 register +#define NXMAC_TIMINGS_3_ADDR 0xC00000EC +/// Offset of the TIMINGS_3 register from the base address +#define NXMAC_TIMINGS_3_OFFSET 0x000000EC +/// Index of the TIMINGS_3 register +#define NXMAC_TIMINGS_3_INDEX 0x0000003B +/// Reset value of the TIMINGS_3 register +#define NXMAC_TIMINGS_3_RESET 0x00000000 + +/** + * @brief Returns the current value of the TIMINGS_3 register. + * The TIMINGS_3 register will be read and its value returned. + * @return The current value of the TIMINGS_3 register. + */ +__INLINE uint32_t nxmac_timings_3_get(void) +{ + return REG_PL_RD(NXMAC_TIMINGS_3_ADDR); +} + +/** + * @brief Sets the TIMINGS_3 register to a value. + * The TIMINGS_3 register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_timings_3_set(uint32_t value) +{ + REG_PL_WR(NXMAC_TIMINGS_3_ADDR, value); +} + +// field definitions +/// RX_RF_DELAY_IN_MAC_CLK field mask +#define NXMAC_RX_RF_DELAY_IN_MAC_CLK_MASK ((uint32_t)0x3FF00000) +/// RX_RF_DELAY_IN_MAC_CLK field LSB position +#define NXMAC_RX_RF_DELAY_IN_MAC_CLK_LSB 20 +/// RX_RF_DELAY_IN_MAC_CLK field width +#define NXMAC_RX_RF_DELAY_IN_MAC_CLK_WIDTH ((uint32_t)0x0000000A) +/// TX_DELAY_RF_ON_IN_MAC_CLK field mask +#define NXMAC_TX_DELAY_RF_ON_IN_MAC_CLK_MASK ((uint32_t)0x000FFC00) +/// TX_DELAY_RF_ON_IN_MAC_CLK field LSB position +#define NXMAC_TX_DELAY_RF_ON_IN_MAC_CLK_LSB 10 +/// TX_DELAY_RF_ON_IN_MAC_CLK field width +#define NXMAC_TX_DELAY_RF_ON_IN_MAC_CLK_WIDTH ((uint32_t)0x0000000A) +/// MAC_PROC_DELAY_IN_MAC_CLK field mask +#define NXMAC_MAC_PROC_DELAY_IN_MAC_CLK_MASK ((uint32_t)0x000003FF) +/// MAC_PROC_DELAY_IN_MAC_CLK field LSB position +#define NXMAC_MAC_PROC_DELAY_IN_MAC_CLK_LSB 0 +/// MAC_PROC_DELAY_IN_MAC_CLK field width +#define NXMAC_MAC_PROC_DELAY_IN_MAC_CLK_WIDTH ((uint32_t)0x0000000A) + +/// RX_RF_DELAY_IN_MAC_CLK field reset value +#define NXMAC_RX_RF_DELAY_IN_MAC_CLK_RST 0x0 +/// TX_DELAY_RF_ON_IN_MAC_CLK field reset value +#define NXMAC_TX_DELAY_RF_ON_IN_MAC_CLK_RST 0x0 +/// MAC_PROC_DELAY_IN_MAC_CLK field reset value +#define NXMAC_MAC_PROC_DELAY_IN_MAC_CLK_RST 0x0 + +/** + * @brief Constructs a value for the TIMINGS_3 register given values for its fields + * and writes the value to the register. + * + * @param[in] rxrfdelayinmacclk - The value to use for the rxRFDelayInMACClk field. + * @param[in] txdelayrfoninmacclk - The value to use for the txDelayRFOnInMACClk field. + * @param[in] macprocdelayinmacclk - The value to use for the macProcDelayInMACClk field. + */ +__INLINE void nxmac_timings_3_pack(uint16_t rxrfdelayinmacclk, uint16_t txdelayrfoninmacclk, uint16_t macprocdelayinmacclk) +{ + ASSERT_ERR((((uint32_t)rxrfdelayinmacclk << 20) & ~((uint32_t)0x3FF00000)) == 0); + ASSERT_ERR((((uint32_t)txdelayrfoninmacclk << 10) & ~((uint32_t)0x000FFC00)) == 0); + ASSERT_ERR((((uint32_t)macprocdelayinmacclk << 0) & ~((uint32_t)0x000003FF)) == 0); + REG_PL_WR(NXMAC_TIMINGS_3_ADDR, ((uint32_t)rxrfdelayinmacclk << 20) | ((uint32_t)txdelayrfoninmacclk << 10) | ((uint32_t)macprocdelayinmacclk << 0)); +} + +/** + * @brief Unpacks TIMINGS_3's fields from current value of the TIMINGS_3 register. + * + * Reads the TIMINGS_3 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] rxrfdelayinmacclk - Will be populated with the current value of this field from the register. + * @param[out] txdelayrfoninmacclk - Will be populated with the current value of this field from the register. + * @param[out] macprocdelayinmacclk - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_timings_3_unpack(uint16_t *rxrfdelayinmacclk, uint16_t *txdelayrfoninmacclk, uint16_t *macprocdelayinmacclk) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMINGS_3_ADDR); + + *rxrfdelayinmacclk = (localVal & ((uint32_t)0x3FF00000)) >> 20; + *txdelayrfoninmacclk = (localVal & ((uint32_t)0x000FFC00)) >> 10; + *macprocdelayinmacclk = (localVal & ((uint32_t)0x000003FF)) >> 0; +} + +/** + * @brief Returns the current value of the rxRFDelayInMACClk field in the TIMINGS_3 register. + * + * The TIMINGS_3 register will be read and the rxRFDelayInMACClk field's value will be returned. + * + * @return The current value of the rxRFDelayInMACClk field in the TIMINGS_3 register. + */ +__INLINE uint16_t nxmac_rx_rf_delay_in_mac_clk_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMINGS_3_ADDR); + return ((localVal & ((uint32_t)0x3FF00000)) >> 20); +} + +/** + * @brief Sets the rxRFDelayInMACClk field of the TIMINGS_3 register. + * + * The TIMINGS_3 register will be read, modified to contain the new field value, and written. + * + * @param[in] rxrfdelayinmacclk - The value to set the field to. + */ +__INLINE void nxmac_rx_rf_delay_in_mac_clk_setf(uint16_t rxrfdelayinmacclk) +{ + ASSERT_ERR((((uint32_t)rxrfdelayinmacclk << 20) & ~((uint32_t)0x3FF00000)) == 0); + REG_PL_WR(NXMAC_TIMINGS_3_ADDR, (REG_PL_RD(NXMAC_TIMINGS_3_ADDR) & ~((uint32_t)0x3FF00000)) | ((uint32_t)rxrfdelayinmacclk << 20)); +} + +/** + * @brief Returns the current value of the txDelayRFOnInMACClk field in the TIMINGS_3 register. + * + * The TIMINGS_3 register will be read and the txDelayRFOnInMACClk field's value will be returned. + * + * @return The current value of the txDelayRFOnInMACClk field in the TIMINGS_3 register. + */ +__INLINE uint16_t nxmac_tx_delay_rf_on_in_mac_clk_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMINGS_3_ADDR); + return ((localVal & ((uint32_t)0x000FFC00)) >> 10); +} + +/** + * @brief Sets the txDelayRFOnInMACClk field of the TIMINGS_3 register. + * + * The TIMINGS_3 register will be read, modified to contain the new field value, and written. + * + * @param[in] txdelayrfoninmacclk - The value to set the field to. + */ +__INLINE void nxmac_tx_delay_rf_on_in_mac_clk_setf(uint16_t txdelayrfoninmacclk) +{ + ASSERT_ERR((((uint32_t)txdelayrfoninmacclk << 10) & ~((uint32_t)0x000FFC00)) == 0); + REG_PL_WR(NXMAC_TIMINGS_3_ADDR, (REG_PL_RD(NXMAC_TIMINGS_3_ADDR) & ~((uint32_t)0x000FFC00)) | ((uint32_t)txdelayrfoninmacclk << 10)); +} + +/** + * @brief Returns the current value of the macProcDelayInMACClk field in the TIMINGS_3 register. + * + * The TIMINGS_3 register will be read and the macProcDelayInMACClk field's value will be returned. + * + * @return The current value of the macProcDelayInMACClk field in the TIMINGS_3 register. + */ +__INLINE uint16_t nxmac_mac_proc_delay_in_mac_clk_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMINGS_3_ADDR); + return ((localVal & ((uint32_t)0x000003FF)) >> 0); +} + +/** + * @brief Sets the macProcDelayInMACClk field of the TIMINGS_3 register. + * + * The TIMINGS_3 register will be read, modified to contain the new field value, and written. + * + * @param[in] macprocdelayinmacclk - The value to set the field to. + */ +__INLINE void nxmac_mac_proc_delay_in_mac_clk_setf(uint16_t macprocdelayinmacclk) +{ + ASSERT_ERR((((uint32_t)macprocdelayinmacclk << 0) & ~((uint32_t)0x000003FF)) == 0); + REG_PL_WR(NXMAC_TIMINGS_3_ADDR, (REG_PL_RD(NXMAC_TIMINGS_3_ADDR) & ~((uint32_t)0x000003FF)) | ((uint32_t)macprocdelayinmacclk << 0)); +} + +/// @} + +/** + * @name TIMINGS_4 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:22      radioWakeUpTime   0x0
+ *  21:12       radioChirpTime   0x0
+ *  01:00     wt2CryptClkRatio   0x0
+ * 
+ * + * @{ + */ + +/// Address of the TIMINGS_4 register +#define NXMAC_TIMINGS_4_ADDR 0xC00000F0 +/// Offset of the TIMINGS_4 register from the base address +#define NXMAC_TIMINGS_4_OFFSET 0x000000F0 +/// Index of the TIMINGS_4 register +#define NXMAC_TIMINGS_4_INDEX 0x0000003C +/// Reset value of the TIMINGS_4 register +#define NXMAC_TIMINGS_4_RESET 0x00000000 + +/** + * @brief Returns the current value of the TIMINGS_4 register. + * The TIMINGS_4 register will be read and its value returned. + * @return The current value of the TIMINGS_4 register. + */ +__INLINE uint32_t nxmac_timings_4_get(void) +{ + return REG_PL_RD(NXMAC_TIMINGS_4_ADDR); +} + +/** + * @brief Sets the TIMINGS_4 register to a value. + * The TIMINGS_4 register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_timings_4_set(uint32_t value) +{ + REG_PL_WR(NXMAC_TIMINGS_4_ADDR, value); +} + +// field definitions +/// RADIO_WAKE_UP_TIME field mask +#define NXMAC_RADIO_WAKE_UP_TIME_MASK ((uint32_t)0xFFC00000) +/// RADIO_WAKE_UP_TIME field LSB position +#define NXMAC_RADIO_WAKE_UP_TIME_LSB 22 +/// RADIO_WAKE_UP_TIME field width +#define NXMAC_RADIO_WAKE_UP_TIME_WIDTH ((uint32_t)0x0000000A) +/// RADIO_CHIRP_TIME field mask +#define NXMAC_RADIO_CHIRP_TIME_MASK ((uint32_t)0x003FF000) +/// RADIO_CHIRP_TIME field LSB position +#define NXMAC_RADIO_CHIRP_TIME_LSB 12 +/// RADIO_CHIRP_TIME field width +#define NXMAC_RADIO_CHIRP_TIME_WIDTH ((uint32_t)0x0000000A) +/// WT_2_CRYPT_CLK_RATIO field mask +#define NXMAC_WT_2_CRYPT_CLK_RATIO_MASK ((uint32_t)0x00000003) +/// WT_2_CRYPT_CLK_RATIO field LSB position +#define NXMAC_WT_2_CRYPT_CLK_RATIO_LSB 0 +/// WT_2_CRYPT_CLK_RATIO field width +#define NXMAC_WT_2_CRYPT_CLK_RATIO_WIDTH ((uint32_t)0x00000002) + +/// RADIO_WAKE_UP_TIME field reset value +#define NXMAC_RADIO_WAKE_UP_TIME_RST 0x0 +/// RADIO_CHIRP_TIME field reset value +#define NXMAC_RADIO_CHIRP_TIME_RST 0x0 +/// WT_2_CRYPT_CLK_RATIO field reset value +#define NXMAC_WT_2_CRYPT_CLK_RATIO_RST 0x0 + +/** + * @brief Constructs a value for the TIMINGS_4 register given values for its fields + * and writes the value to the register. + * + * @param[in] radiowakeuptime - The value to use for the radioWakeUpTime field. + * @param[in] radiochirptime - The value to use for the radioChirpTime field. + * @param[in] wt2cryptclkratio - The value to use for the wt2CryptClkRatio field. + */ +__INLINE void nxmac_timings_4_pack(uint16_t radiowakeuptime, uint16_t radiochirptime, uint8_t wt2cryptclkratio) +{ + ASSERT_ERR((((uint32_t)radiowakeuptime << 22) & ~((uint32_t)0xFFC00000)) == 0); + ASSERT_ERR((((uint32_t)radiochirptime << 12) & ~((uint32_t)0x003FF000)) == 0); + ASSERT_ERR((((uint32_t)wt2cryptclkratio << 0) & ~((uint32_t)0x00000003)) == 0); + REG_PL_WR(NXMAC_TIMINGS_4_ADDR, ((uint32_t)radiowakeuptime << 22) | ((uint32_t)radiochirptime << 12) | ((uint32_t)wt2cryptclkratio << 0)); +} + +/** + * @brief Unpacks TIMINGS_4's fields from current value of the TIMINGS_4 register. + * + * Reads the TIMINGS_4 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] radiowakeuptime - Will be populated with the current value of this field from the register. + * @param[out] radiochirptime - Will be populated with the current value of this field from the register. + * @param[out] wt2cryptclkratio - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_timings_4_unpack(uint16_t *radiowakeuptime, uint16_t *radiochirptime, uint8_t *wt2cryptclkratio) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMINGS_4_ADDR); + + *radiowakeuptime = (localVal & ((uint32_t)0xFFC00000)) >> 22; + *radiochirptime = (localVal & ((uint32_t)0x003FF000)) >> 12; + *wt2cryptclkratio = (localVal & ((uint32_t)0x00000003)) >> 0; +} + +/** + * @brief Returns the current value of the radioWakeUpTime field in the TIMINGS_4 register. + * + * The TIMINGS_4 register will be read and the radioWakeUpTime field's value will be returned. + * + * @return The current value of the radioWakeUpTime field in the TIMINGS_4 register. + */ +__INLINE uint16_t nxmac_radio_wake_up_time_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMINGS_4_ADDR); + return ((localVal & ((uint32_t)0xFFC00000)) >> 22); +} + +/** + * @brief Sets the radioWakeUpTime field of the TIMINGS_4 register. + * + * The TIMINGS_4 register will be read, modified to contain the new field value, and written. + * + * @param[in] radiowakeuptime - The value to set the field to. + */ +__INLINE void nxmac_radio_wake_up_time_setf(uint16_t radiowakeuptime) +{ + ASSERT_ERR((((uint32_t)radiowakeuptime << 22) & ~((uint32_t)0xFFC00000)) == 0); + REG_PL_WR(NXMAC_TIMINGS_4_ADDR, (REG_PL_RD(NXMAC_TIMINGS_4_ADDR) & ~((uint32_t)0xFFC00000)) | ((uint32_t)radiowakeuptime << 22)); +} + +/** + * @brief Returns the current value of the radioChirpTime field in the TIMINGS_4 register. + * + * The TIMINGS_4 register will be read and the radioChirpTime field's value will be returned. + * + * @return The current value of the radioChirpTime field in the TIMINGS_4 register. + */ +__INLINE uint16_t nxmac_radio_chirp_time_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMINGS_4_ADDR); + return ((localVal & ((uint32_t)0x003FF000)) >> 12); +} + +/** + * @brief Sets the radioChirpTime field of the TIMINGS_4 register. + * + * The TIMINGS_4 register will be read, modified to contain the new field value, and written. + * + * @param[in] radiochirptime - The value to set the field to. + */ +__INLINE void nxmac_radio_chirp_time_setf(uint16_t radiochirptime) +{ + ASSERT_ERR((((uint32_t)radiochirptime << 12) & ~((uint32_t)0x003FF000)) == 0); + REG_PL_WR(NXMAC_TIMINGS_4_ADDR, (REG_PL_RD(NXMAC_TIMINGS_4_ADDR) & ~((uint32_t)0x003FF000)) | ((uint32_t)radiochirptime << 12)); +} + +/** + * @brief Returns the current value of the wt2CryptClkRatio field in the TIMINGS_4 register. + * + * The TIMINGS_4 register will be read and the wt2CryptClkRatio field's value will be returned. + * + * @return The current value of the wt2CryptClkRatio field in the TIMINGS_4 register. + */ +__INLINE uint8_t nxmac_wt_2_crypt_clk_ratio_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMINGS_4_ADDR); + return ((localVal & ((uint32_t)0x00000003)) >> 0); +} + +/** + * @brief Sets the wt2CryptClkRatio field of the TIMINGS_4 register. + * + * The TIMINGS_4 register will be read, modified to contain the new field value, and written. + * + * @param[in] wt2cryptclkratio - The value to set the field to. + */ +__INLINE void nxmac_wt_2_crypt_clk_ratio_setf(uint8_t wt2cryptclkratio) +{ + ASSERT_ERR((((uint32_t)wt2cryptclkratio << 0) & ~((uint32_t)0x00000003)) == 0); + REG_PL_WR(NXMAC_TIMINGS_4_ADDR, (REG_PL_RD(NXMAC_TIMINGS_4_ADDR) & ~((uint32_t)0x00000003)) | ((uint32_t)wt2cryptclkratio << 0)); +} + +/// @} + +/** + * @name TIMINGS_5 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  23:08        sifsBInMACClk   0x0
+ *  07:00                sifsB   0x0
+ * 
+ * + * @{ + */ + +/// Address of the TIMINGS_5 register +#define NXMAC_TIMINGS_5_ADDR 0xC00000F4 +/// Offset of the TIMINGS_5 register from the base address +#define NXMAC_TIMINGS_5_OFFSET 0x000000F4 +/// Index of the TIMINGS_5 register +#define NXMAC_TIMINGS_5_INDEX 0x0000003D +/// Reset value of the TIMINGS_5 register +#define NXMAC_TIMINGS_5_RESET 0x00000000 + +/** + * @brief Returns the current value of the TIMINGS_5 register. + * The TIMINGS_5 register will be read and its value returned. + * @return The current value of the TIMINGS_5 register. + */ +__INLINE uint32_t nxmac_timings_5_get(void) +{ + return REG_PL_RD(NXMAC_TIMINGS_5_ADDR); +} + +/** + * @brief Sets the TIMINGS_5 register to a value. + * The TIMINGS_5 register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_timings_5_set(uint32_t value) +{ + REG_PL_WR(NXMAC_TIMINGS_5_ADDR, value); +} + +// field definitions +/// SIFS_B_IN_MAC_CLK field mask +#define NXMAC_SIFS_B_IN_MAC_CLK_MASK ((uint32_t)0x00FFFF00) +/// SIFS_B_IN_MAC_CLK field LSB position +#define NXMAC_SIFS_B_IN_MAC_CLK_LSB 8 +/// SIFS_B_IN_MAC_CLK field width +#define NXMAC_SIFS_B_IN_MAC_CLK_WIDTH ((uint32_t)0x00000010) +/// SIFS_B field mask +#define NXMAC_SIFS_B_MASK ((uint32_t)0x000000FF) +/// SIFS_B field LSB position +#define NXMAC_SIFS_B_LSB 0 +/// SIFS_B field width +#define NXMAC_SIFS_B_WIDTH ((uint32_t)0x00000008) + +/// SIFS_B_IN_MAC_CLK field reset value +#define NXMAC_SIFS_B_IN_MAC_CLK_RST 0x0 +/// SIFS_B field reset value +#define NXMAC_SIFS_B_RST 0x0 + +/** + * @brief Constructs a value for the TIMINGS_5 register given values for its fields + * and writes the value to the register. + * + * @param[in] sifsbinmacclk - The value to use for the sifsBInMACClk field. + * @param[in] sifsb - The value to use for the sifsB field. + */ +__INLINE void nxmac_timings_5_pack(uint16_t sifsbinmacclk, uint8_t sifsb) +{ + ASSERT_ERR((((uint32_t)sifsbinmacclk << 8) & ~((uint32_t)0x00FFFF00)) == 0); + ASSERT_ERR((((uint32_t)sifsb << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(NXMAC_TIMINGS_5_ADDR, ((uint32_t)sifsbinmacclk << 8) | ((uint32_t)sifsb << 0)); +} + +/** + * @brief Unpacks TIMINGS_5's fields from current value of the TIMINGS_5 register. + * + * Reads the TIMINGS_5 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] sifsbinmacclk - Will be populated with the current value of this field from the register. + * @param[out] sifsb - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_timings_5_unpack(uint16_t *sifsbinmacclk, uint8_t *sifsb) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMINGS_5_ADDR); + + *sifsbinmacclk = (localVal & ((uint32_t)0x00FFFF00)) >> 8; + *sifsb = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +/** + * @brief Returns the current value of the sifsBInMACClk field in the TIMINGS_5 register. + * + * The TIMINGS_5 register will be read and the sifsBInMACClk field's value will be returned. + * + * @return The current value of the sifsBInMACClk field in the TIMINGS_5 register. + */ +__INLINE uint16_t nxmac_sifs_b_in_mac_clk_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMINGS_5_ADDR); + return ((localVal & ((uint32_t)0x00FFFF00)) >> 8); +} + +/** + * @brief Sets the sifsBInMACClk field of the TIMINGS_5 register. + * + * The TIMINGS_5 register will be read, modified to contain the new field value, and written. + * + * @param[in] sifsbinmacclk - The value to set the field to. + */ +__INLINE void nxmac_sifs_b_in_mac_clk_setf(uint16_t sifsbinmacclk) +{ + ASSERT_ERR((((uint32_t)sifsbinmacclk << 8) & ~((uint32_t)0x00FFFF00)) == 0); + REG_PL_WR(NXMAC_TIMINGS_5_ADDR, (REG_PL_RD(NXMAC_TIMINGS_5_ADDR) & ~((uint32_t)0x00FFFF00)) | ((uint32_t)sifsbinmacclk << 8)); +} + +/** + * @brief Returns the current value of the sifsB field in the TIMINGS_5 register. + * + * The TIMINGS_5 register will be read and the sifsB field's value will be returned. + * + * @return The current value of the sifsB field in the TIMINGS_5 register. + */ +__INLINE uint8_t nxmac_sifs_b_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMINGS_5_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +/** + * @brief Sets the sifsB field of the TIMINGS_5 register. + * + * The TIMINGS_5 register will be read, modified to contain the new field value, and written. + * + * @param[in] sifsb - The value to set the field to. + */ +__INLINE void nxmac_sifs_b_setf(uint8_t sifsb) +{ + ASSERT_ERR((((uint32_t)sifsb << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(NXMAC_TIMINGS_5_ADDR, (REG_PL_RD(NXMAC_TIMINGS_5_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)sifsb << 0)); +} + +/// @} + +/** + * @name TIMINGS_6 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  23:08        sifsAInMACClk   0x0
+ *  07:00                sifsA   0x0
+ * 
+ * + * @{ + */ + +/// Address of the TIMINGS_6 register +#define NXMAC_TIMINGS_6_ADDR 0xC00000F8 +/// Offset of the TIMINGS_6 register from the base address +#define NXMAC_TIMINGS_6_OFFSET 0x000000F8 +/// Index of the TIMINGS_6 register +#define NXMAC_TIMINGS_6_INDEX 0x0000003E +/// Reset value of the TIMINGS_6 register +#define NXMAC_TIMINGS_6_RESET 0x00000000 + +/** + * @brief Returns the current value of the TIMINGS_6 register. + * The TIMINGS_6 register will be read and its value returned. + * @return The current value of the TIMINGS_6 register. + */ +__INLINE uint32_t nxmac_timings_6_get(void) +{ + return REG_PL_RD(NXMAC_TIMINGS_6_ADDR); +} + +/** + * @brief Sets the TIMINGS_6 register to a value. + * The TIMINGS_6 register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_timings_6_set(uint32_t value) +{ + REG_PL_WR(NXMAC_TIMINGS_6_ADDR, value); +} + +// field definitions +/// SIFS_A_IN_MAC_CLK field mask +#define NXMAC_SIFS_A_IN_MAC_CLK_MASK ((uint32_t)0x00FFFF00) +/// SIFS_A_IN_MAC_CLK field LSB position +#define NXMAC_SIFS_A_IN_MAC_CLK_LSB 8 +/// SIFS_A_IN_MAC_CLK field width +#define NXMAC_SIFS_A_IN_MAC_CLK_WIDTH ((uint32_t)0x00000010) +/// SIFS_A field mask +#define NXMAC_SIFS_A_MASK ((uint32_t)0x000000FF) +/// SIFS_A field LSB position +#define NXMAC_SIFS_A_LSB 0 +/// SIFS_A field width +#define NXMAC_SIFS_A_WIDTH ((uint32_t)0x00000008) + +/// SIFS_A_IN_MAC_CLK field reset value +#define NXMAC_SIFS_A_IN_MAC_CLK_RST 0x0 +/// SIFS_A field reset value +#define NXMAC_SIFS_A_RST 0x0 + +/** + * @brief Constructs a value for the TIMINGS_6 register given values for its fields + * and writes the value to the register. + * + * @param[in] sifsainmacclk - The value to use for the sifsAInMACClk field. + * @param[in] sifsa - The value to use for the sifsA field. + */ +__INLINE void nxmac_timings_6_pack(uint16_t sifsainmacclk, uint8_t sifsa) +{ + ASSERT_ERR((((uint32_t)sifsainmacclk << 8) & ~((uint32_t)0x00FFFF00)) == 0); + ASSERT_ERR((((uint32_t)sifsa << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(NXMAC_TIMINGS_6_ADDR, ((uint32_t)sifsainmacclk << 8) | ((uint32_t)sifsa << 0)); +} + +/** + * @brief Unpacks TIMINGS_6's fields from current value of the TIMINGS_6 register. + * + * Reads the TIMINGS_6 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] sifsainmacclk - Will be populated with the current value of this field from the register. + * @param[out] sifsa - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_timings_6_unpack(uint16_t *sifsainmacclk, uint8_t *sifsa) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMINGS_6_ADDR); + + *sifsainmacclk = (localVal & ((uint32_t)0x00FFFF00)) >> 8; + *sifsa = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +/** + * @brief Returns the current value of the sifsAInMACClk field in the TIMINGS_6 register. + * + * The TIMINGS_6 register will be read and the sifsAInMACClk field's value will be returned. + * + * @return The current value of the sifsAInMACClk field in the TIMINGS_6 register. + */ +__INLINE uint16_t nxmac_sifs_a_in_mac_clk_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMINGS_6_ADDR); + return ((localVal & ((uint32_t)0x00FFFF00)) >> 8); +} + +/** + * @brief Sets the sifsAInMACClk field of the TIMINGS_6 register. + * + * The TIMINGS_6 register will be read, modified to contain the new field value, and written. + * + * @param[in] sifsainmacclk - The value to set the field to. + */ +__INLINE void nxmac_sifs_a_in_mac_clk_setf(uint16_t sifsainmacclk) +{ + ASSERT_ERR((((uint32_t)sifsainmacclk << 8) & ~((uint32_t)0x00FFFF00)) == 0); + REG_PL_WR(NXMAC_TIMINGS_6_ADDR, (REG_PL_RD(NXMAC_TIMINGS_6_ADDR) & ~((uint32_t)0x00FFFF00)) | ((uint32_t)sifsainmacclk << 8)); +} + +/** + * @brief Returns the current value of the sifsA field in the TIMINGS_6 register. + * + * The TIMINGS_6 register will be read and the sifsA field's value will be returned. + * + * @return The current value of the sifsA field in the TIMINGS_6 register. + */ +__INLINE uint8_t nxmac_sifs_a_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMINGS_6_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +/** + * @brief Sets the sifsA field of the TIMINGS_6 register. + * + * The TIMINGS_6 register will be read, modified to contain the new field value, and written. + * + * @param[in] sifsa - The value to set the field to. + */ +__INLINE void nxmac_sifs_a_setf(uint8_t sifsa) +{ + ASSERT_ERR((((uint32_t)sifsa << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(NXMAC_TIMINGS_6_ADDR, (REG_PL_RD(NXMAC_TIMINGS_6_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)sifsa << 0)); +} + +/// @} + +/** + * @name TIMINGS_7 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  11:08           rxCCADelay   0x0
+ *  07:00                 rifs   0x0
+ * 
+ * + * @{ + */ + +/// Address of the TIMINGS_7 register +#define NXMAC_TIMINGS_7_ADDR 0xC00000FC +/// Offset of the TIMINGS_7 register from the base address +#define NXMAC_TIMINGS_7_OFFSET 0x000000FC +/// Index of the TIMINGS_7 register +#define NXMAC_TIMINGS_7_INDEX 0x0000003F +/// Reset value of the TIMINGS_7 register +#define NXMAC_TIMINGS_7_RESET 0x00000000 + +/** + * @brief Returns the current value of the TIMINGS_7 register. + * The TIMINGS_7 register will be read and its value returned. + * @return The current value of the TIMINGS_7 register. + */ +__INLINE uint32_t nxmac_timings_7_get(void) +{ + return REG_PL_RD(NXMAC_TIMINGS_7_ADDR); +} + +/** + * @brief Sets the TIMINGS_7 register to a value. + * The TIMINGS_7 register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_timings_7_set(uint32_t value) +{ + REG_PL_WR(NXMAC_TIMINGS_7_ADDR, value); +} + +// field definitions +/// RX_CCA_DELAY field mask +#define NXMAC_RX_CCA_DELAY_MASK ((uint32_t)0x00000F00) +/// RX_CCA_DELAY field LSB position +#define NXMAC_RX_CCA_DELAY_LSB 8 +/// RX_CCA_DELAY field width +#define NXMAC_RX_CCA_DELAY_WIDTH ((uint32_t)0x00000004) +/// RIFS field mask +#define NXMAC_RIFS_MASK ((uint32_t)0x000000FF) +/// RIFS field LSB position +#define NXMAC_RIFS_LSB 0 +/// RIFS field width +#define NXMAC_RIFS_WIDTH ((uint32_t)0x00000008) + +/// RX_CCA_DELAY field reset value +#define NXMAC_RX_CCA_DELAY_RST 0x0 +/// RIFS field reset value +#define NXMAC_RIFS_RST 0x0 + +/** + * @brief Constructs a value for the TIMINGS_7 register given values for its fields + * and writes the value to the register. + * + * @param[in] rxccadelay - The value to use for the rxCCADelay field. + * @param[in] rifs - The value to use for the rifs field. + */ +__INLINE void nxmac_timings_7_pack(uint8_t rxccadelay, uint8_t rifs) +{ + ASSERT_ERR((((uint32_t)rxccadelay << 8) & ~((uint32_t)0x00000F00)) == 0); + ASSERT_ERR((((uint32_t)rifs << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(NXMAC_TIMINGS_7_ADDR, ((uint32_t)rxccadelay << 8) | ((uint32_t)rifs << 0)); +} + +/** + * @brief Unpacks TIMINGS_7's fields from current value of the TIMINGS_7 register. + * + * Reads the TIMINGS_7 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] rxccadelay - Will be populated with the current value of this field from the register. + * @param[out] rifs - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_timings_7_unpack(uint8_t *rxccadelay, uint8_t *rifs) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMINGS_7_ADDR); + + *rxccadelay = (localVal & ((uint32_t)0x00000F00)) >> 8; + *rifs = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +/** + * @brief Returns the current value of the rxCCADelay field in the TIMINGS_7 register. + * + * The TIMINGS_7 register will be read and the rxCCADelay field's value will be returned. + * + * @return The current value of the rxCCADelay field in the TIMINGS_7 register. + */ +__INLINE uint8_t nxmac_rx_cca_delay_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMINGS_7_ADDR); + return ((localVal & ((uint32_t)0x00000F00)) >> 8); +} + +/** + * @brief Sets the rxCCADelay field of the TIMINGS_7 register. + * + * The TIMINGS_7 register will be read, modified to contain the new field value, and written. + * + * @param[in] rxccadelay - The value to set the field to. + */ +__INLINE void nxmac_rx_cca_delay_setf(uint8_t rxccadelay) +{ + ASSERT_ERR((((uint32_t)rxccadelay << 8) & ~((uint32_t)0x00000F00)) == 0); + REG_PL_WR(NXMAC_TIMINGS_7_ADDR, (REG_PL_RD(NXMAC_TIMINGS_7_ADDR) & ~((uint32_t)0x00000F00)) | ((uint32_t)rxccadelay << 8)); +} + +/** + * @brief Returns the current value of the rifs field in the TIMINGS_7 register. + * + * The TIMINGS_7 register will be read and the rifs field's value will be returned. + * + * @return The current value of the rifs field in the TIMINGS_7 register. + */ +__INLINE uint8_t nxmac_rifs_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMINGS_7_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +/** + * @brief Sets the rifs field of the TIMINGS_7 register. + * + * The TIMINGS_7 register will be read, modified to contain the new field value, and written. + * + * @param[in] rifs - The value to set the field to. + */ +__INLINE void nxmac_rifs_setf(uint8_t rifs) +{ + ASSERT_ERR((((uint32_t)rifs << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(NXMAC_TIMINGS_7_ADDR, (REG_PL_RD(NXMAC_TIMINGS_7_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)rifs << 0)); +} + +/// @} + +/** + * @name TIMINGS_8 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:24     rxStartDelayMIMO   0x21
+ *  23:16    rxStartDelayShort   0x66
+ *  15:08     rxStartDelayLong   0xC6
+ *  07:00     rxStartDelayOFDM   0x21
+ * 
+ * + * @{ + */ + +/// Address of the TIMINGS_8 register +#define NXMAC_TIMINGS_8_ADDR 0xC0000100 +/// Offset of the TIMINGS_8 register from the base address +#define NXMAC_TIMINGS_8_OFFSET 0x00000100 +/// Index of the TIMINGS_8 register +#define NXMAC_TIMINGS_8_INDEX 0x00000040 +/// Reset value of the TIMINGS_8 register +#define NXMAC_TIMINGS_8_RESET 0x2166C621 + +/** + * @brief Returns the current value of the TIMINGS_8 register. + * The TIMINGS_8 register will be read and its value returned. + * @return The current value of the TIMINGS_8 register. + */ +__INLINE uint32_t nxmac_timings_8_get(void) +{ + return REG_PL_RD(NXMAC_TIMINGS_8_ADDR); +} + +/** + * @brief Sets the TIMINGS_8 register to a value. + * The TIMINGS_8 register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_timings_8_set(uint32_t value) +{ + REG_PL_WR(NXMAC_TIMINGS_8_ADDR, value); +} + +// field definitions +/// RX_START_DELAY_MIMO field mask +#define NXMAC_RX_START_DELAY_MIMO_MASK ((uint32_t)0xFF000000) +/// RX_START_DELAY_MIMO field LSB position +#define NXMAC_RX_START_DELAY_MIMO_LSB 24 +/// RX_START_DELAY_MIMO field width +#define NXMAC_RX_START_DELAY_MIMO_WIDTH ((uint32_t)0x00000008) +/// RX_START_DELAY_SHORT field mask +#define NXMAC_RX_START_DELAY_SHORT_MASK ((uint32_t)0x00FF0000) +/// RX_START_DELAY_SHORT field LSB position +#define NXMAC_RX_START_DELAY_SHORT_LSB 16 +/// RX_START_DELAY_SHORT field width +#define NXMAC_RX_START_DELAY_SHORT_WIDTH ((uint32_t)0x00000008) +/// RX_START_DELAY_LONG field mask +#define NXMAC_RX_START_DELAY_LONG_MASK ((uint32_t)0x0000FF00) +/// RX_START_DELAY_LONG field LSB position +#define NXMAC_RX_START_DELAY_LONG_LSB 8 +/// RX_START_DELAY_LONG field width +#define NXMAC_RX_START_DELAY_LONG_WIDTH ((uint32_t)0x00000008) +/// RX_START_DELAY_OFDM field mask +#define NXMAC_RX_START_DELAY_OFDM_MASK ((uint32_t)0x000000FF) +/// RX_START_DELAY_OFDM field LSB position +#define NXMAC_RX_START_DELAY_OFDM_LSB 0 +/// RX_START_DELAY_OFDM field width +#define NXMAC_RX_START_DELAY_OFDM_WIDTH ((uint32_t)0x00000008) + +/// RX_START_DELAY_MIMO field reset value +#define NXMAC_RX_START_DELAY_MIMO_RST 0x21 +/// RX_START_DELAY_SHORT field reset value +#define NXMAC_RX_START_DELAY_SHORT_RST 0x66 +/// RX_START_DELAY_LONG field reset value +#define NXMAC_RX_START_DELAY_LONG_RST 0xC6 +/// RX_START_DELAY_OFDM field reset value +#define NXMAC_RX_START_DELAY_OFDM_RST 0x21 + +/** + * @brief Constructs a value for the TIMINGS_8 register given values for its fields + * and writes the value to the register. + * + * @param[in] rxstartdelaymimo - The value to use for the rxStartDelayMIMO field. + * @param[in] rxstartdelayshort - The value to use for the rxStartDelayShort field. + * @param[in] rxstartdelaylong - The value to use for the rxStartDelayLong field. + * @param[in] rxstartdelayofdm - The value to use for the rxStartDelayOFDM field. + */ +__INLINE void nxmac_timings_8_pack(uint8_t rxstartdelaymimo, uint8_t rxstartdelayshort, uint8_t rxstartdelaylong, uint8_t rxstartdelayofdm) +{ + ASSERT_ERR((((uint32_t)rxstartdelaymimo << 24) & ~((uint32_t)0xFF000000)) == 0); + ASSERT_ERR((((uint32_t)rxstartdelayshort << 16) & ~((uint32_t)0x00FF0000)) == 0); + ASSERT_ERR((((uint32_t)rxstartdelaylong << 8) & ~((uint32_t)0x0000FF00)) == 0); + ASSERT_ERR((((uint32_t)rxstartdelayofdm << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(NXMAC_TIMINGS_8_ADDR, ((uint32_t)rxstartdelaymimo << 24) | ((uint32_t)rxstartdelayshort << 16) | ((uint32_t)rxstartdelaylong << 8) | ((uint32_t)rxstartdelayofdm << 0)); +} + +/** + * @brief Unpacks TIMINGS_8's fields from current value of the TIMINGS_8 register. + * + * Reads the TIMINGS_8 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] rxstartdelaymimo - Will be populated with the current value of this field from the register. + * @param[out] rxstartdelayshort - Will be populated with the current value of this field from the register. + * @param[out] rxstartdelaylong - Will be populated with the current value of this field from the register. + * @param[out] rxstartdelayofdm - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_timings_8_unpack(uint8_t *rxstartdelaymimo, uint8_t *rxstartdelayshort, uint8_t *rxstartdelaylong, uint8_t *rxstartdelayofdm) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMINGS_8_ADDR); + + *rxstartdelaymimo = (localVal & ((uint32_t)0xFF000000)) >> 24; + *rxstartdelayshort = (localVal & ((uint32_t)0x00FF0000)) >> 16; + *rxstartdelaylong = (localVal & ((uint32_t)0x0000FF00)) >> 8; + *rxstartdelayofdm = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +/** + * @brief Returns the current value of the rxStartDelayMIMO field in the TIMINGS_8 register. + * + * The TIMINGS_8 register will be read and the rxStartDelayMIMO field's value will be returned. + * + * @return The current value of the rxStartDelayMIMO field in the TIMINGS_8 register. + */ +__INLINE uint8_t nxmac_rx_start_delay_mimo_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMINGS_8_ADDR); + return ((localVal & ((uint32_t)0xFF000000)) >> 24); +} + +/** + * @brief Sets the rxStartDelayMIMO field of the TIMINGS_8 register. + * + * The TIMINGS_8 register will be read, modified to contain the new field value, and written. + * + * @param[in] rxstartdelaymimo - The value to set the field to. + */ +__INLINE void nxmac_rx_start_delay_mimo_setf(uint8_t rxstartdelaymimo) +{ + ASSERT_ERR((((uint32_t)rxstartdelaymimo << 24) & ~((uint32_t)0xFF000000)) == 0); + REG_PL_WR(NXMAC_TIMINGS_8_ADDR, (REG_PL_RD(NXMAC_TIMINGS_8_ADDR) & ~((uint32_t)0xFF000000)) | ((uint32_t)rxstartdelaymimo << 24)); +} + +/** + * @brief Returns the current value of the rxStartDelayShort field in the TIMINGS_8 register. + * + * The TIMINGS_8 register will be read and the rxStartDelayShort field's value will be returned. + * + * @return The current value of the rxStartDelayShort field in the TIMINGS_8 register. + */ +__INLINE uint8_t nxmac_rx_start_delay_short_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMINGS_8_ADDR); + return ((localVal & ((uint32_t)0x00FF0000)) >> 16); +} + +/** + * @brief Sets the rxStartDelayShort field of the TIMINGS_8 register. + * + * The TIMINGS_8 register will be read, modified to contain the new field value, and written. + * + * @param[in] rxstartdelayshort - The value to set the field to. + */ +__INLINE void nxmac_rx_start_delay_short_setf(uint8_t rxstartdelayshort) +{ + ASSERT_ERR((((uint32_t)rxstartdelayshort << 16) & ~((uint32_t)0x00FF0000)) == 0); + REG_PL_WR(NXMAC_TIMINGS_8_ADDR, (REG_PL_RD(NXMAC_TIMINGS_8_ADDR) & ~((uint32_t)0x00FF0000)) | ((uint32_t)rxstartdelayshort << 16)); +} + +/** + * @brief Returns the current value of the rxStartDelayLong field in the TIMINGS_8 register. + * + * The TIMINGS_8 register will be read and the rxStartDelayLong field's value will be returned. + * + * @return The current value of the rxStartDelayLong field in the TIMINGS_8 register. + */ +__INLINE uint8_t nxmac_rx_start_delay_long_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMINGS_8_ADDR); + return ((localVal & ((uint32_t)0x0000FF00)) >> 8); +} + +/** + * @brief Sets the rxStartDelayLong field of the TIMINGS_8 register. + * + * The TIMINGS_8 register will be read, modified to contain the new field value, and written. + * + * @param[in] rxstartdelaylong - The value to set the field to. + */ +__INLINE void nxmac_rx_start_delay_long_setf(uint8_t rxstartdelaylong) +{ + ASSERT_ERR((((uint32_t)rxstartdelaylong << 8) & ~((uint32_t)0x0000FF00)) == 0); + REG_PL_WR(NXMAC_TIMINGS_8_ADDR, (REG_PL_RD(NXMAC_TIMINGS_8_ADDR) & ~((uint32_t)0x0000FF00)) | ((uint32_t)rxstartdelaylong << 8)); +} + +/** + * @brief Returns the current value of the rxStartDelayOFDM field in the TIMINGS_8 register. + * + * The TIMINGS_8 register will be read and the rxStartDelayOFDM field's value will be returned. + * + * @return The current value of the rxStartDelayOFDM field in the TIMINGS_8 register. + */ +__INLINE uint8_t nxmac_rx_start_delay_ofdm_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMINGS_8_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +/** + * @brief Sets the rxStartDelayOFDM field of the TIMINGS_8 register. + * + * The TIMINGS_8 register will be read, modified to contain the new field value, and written. + * + * @param[in] rxstartdelayofdm - The value to set the field to. + */ +__INLINE void nxmac_rx_start_delay_ofdm_setf(uint8_t rxstartdelayofdm) +{ + ASSERT_ERR((((uint32_t)rxstartdelayofdm << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(NXMAC_TIMINGS_8_ADDR, (REG_PL_RD(NXMAC_TIMINGS_8_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)rxstartdelayofdm << 0)); +} + +/// @} + +/** + * @name TIMINGS_9 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  29:20       rifsTOInMACClk   0x0
+ *  19:10         rifsInMACClk   0x0
+ *  09:00   txDMAProcDlyInMACClk   0x0
+ * 
+ * + * @{ + */ + +/// Address of the TIMINGS_9 register +#define NXMAC_TIMINGS_9_ADDR 0xC0000104 +/// Offset of the TIMINGS_9 register from the base address +#define NXMAC_TIMINGS_9_OFFSET 0x00000104 +/// Index of the TIMINGS_9 register +#define NXMAC_TIMINGS_9_INDEX 0x00000041 +/// Reset value of the TIMINGS_9 register +#define NXMAC_TIMINGS_9_RESET 0x00000000 + +/** + * @brief Returns the current value of the TIMINGS_9 register. + * The TIMINGS_9 register will be read and its value returned. + * @return The current value of the TIMINGS_9 register. + */ +__INLINE uint32_t nxmac_timings_9_get(void) +{ + return REG_PL_RD(NXMAC_TIMINGS_9_ADDR); +} + +/** + * @brief Sets the TIMINGS_9 register to a value. + * The TIMINGS_9 register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_timings_9_set(uint32_t value) +{ + REG_PL_WR(NXMAC_TIMINGS_9_ADDR, value); +} + +// field definitions +/// RIFS_TO_IN_MAC_CLK field mask +#define NXMAC_RIFS_TO_IN_MAC_CLK_MASK ((uint32_t)0x3FF00000) +/// RIFS_TO_IN_MAC_CLK field LSB position +#define NXMAC_RIFS_TO_IN_MAC_CLK_LSB 20 +/// RIFS_TO_IN_MAC_CLK field width +#define NXMAC_RIFS_TO_IN_MAC_CLK_WIDTH ((uint32_t)0x0000000A) +/// RIFS_IN_MAC_CLK field mask +#define NXMAC_RIFS_IN_MAC_CLK_MASK ((uint32_t)0x000FFC00) +/// RIFS_IN_MAC_CLK field LSB position +#define NXMAC_RIFS_IN_MAC_CLK_LSB 10 +/// RIFS_IN_MAC_CLK field width +#define NXMAC_RIFS_IN_MAC_CLK_WIDTH ((uint32_t)0x0000000A) +/// TX_DMA_PROC_DLY_IN_MAC_CLK field mask +#define NXMAC_TX_DMA_PROC_DLY_IN_MAC_CLK_MASK ((uint32_t)0x000003FF) +/// TX_DMA_PROC_DLY_IN_MAC_CLK field LSB position +#define NXMAC_TX_DMA_PROC_DLY_IN_MAC_CLK_LSB 0 +/// TX_DMA_PROC_DLY_IN_MAC_CLK field width +#define NXMAC_TX_DMA_PROC_DLY_IN_MAC_CLK_WIDTH ((uint32_t)0x0000000A) + +/// RIFS_TO_IN_MAC_CLK field reset value +#define NXMAC_RIFS_TO_IN_MAC_CLK_RST 0x0 +/// RIFS_IN_MAC_CLK field reset value +#define NXMAC_RIFS_IN_MAC_CLK_RST 0x0 +/// TX_DMA_PROC_DLY_IN_MAC_CLK field reset value +#define NXMAC_TX_DMA_PROC_DLY_IN_MAC_CLK_RST 0x0 + +/** + * @brief Constructs a value for the TIMINGS_9 register given values for its fields + * and writes the value to the register. + * + * @param[in] rifstoinmacclk - The value to use for the rifsTOInMACClk field. + * @param[in] rifsinmacclk - The value to use for the rifsInMACClk field. + * @param[in] txdmaprocdlyinmacclk - The value to use for the txDMAProcDlyInMACClk field. + */ +__INLINE void nxmac_timings_9_pack(uint16_t rifstoinmacclk, uint16_t rifsinmacclk, uint16_t txdmaprocdlyinmacclk) +{ + ASSERT_ERR((((uint32_t)rifstoinmacclk << 20) & ~((uint32_t)0x3FF00000)) == 0); + ASSERT_ERR((((uint32_t)rifsinmacclk << 10) & ~((uint32_t)0x000FFC00)) == 0); + ASSERT_ERR((((uint32_t)txdmaprocdlyinmacclk << 0) & ~((uint32_t)0x000003FF)) == 0); + REG_PL_WR(NXMAC_TIMINGS_9_ADDR, ((uint32_t)rifstoinmacclk << 20) | ((uint32_t)rifsinmacclk << 10) | ((uint32_t)txdmaprocdlyinmacclk << 0)); +} + +/** + * @brief Unpacks TIMINGS_9's fields from current value of the TIMINGS_9 register. + * + * Reads the TIMINGS_9 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] rifstoinmacclk - Will be populated with the current value of this field from the register. + * @param[out] rifsinmacclk - Will be populated with the current value of this field from the register. + * @param[out] txdmaprocdlyinmacclk - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_timings_9_unpack(uint16_t *rifstoinmacclk, uint16_t *rifsinmacclk, uint16_t *txdmaprocdlyinmacclk) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMINGS_9_ADDR); + + *rifstoinmacclk = (localVal & ((uint32_t)0x3FF00000)) >> 20; + *rifsinmacclk = (localVal & ((uint32_t)0x000FFC00)) >> 10; + *txdmaprocdlyinmacclk = (localVal & ((uint32_t)0x000003FF)) >> 0; +} + +/** + * @brief Returns the current value of the rifsTOInMACClk field in the TIMINGS_9 register. + * + * The TIMINGS_9 register will be read and the rifsTOInMACClk field's value will be returned. + * + * @return The current value of the rifsTOInMACClk field in the TIMINGS_9 register. + */ +__INLINE uint16_t nxmac_rifs_to_in_mac_clk_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMINGS_9_ADDR); + return ((localVal & ((uint32_t)0x3FF00000)) >> 20); +} + +/** + * @brief Sets the rifsTOInMACClk field of the TIMINGS_9 register. + * + * The TIMINGS_9 register will be read, modified to contain the new field value, and written. + * + * @param[in] rifstoinmacclk - The value to set the field to. + */ +__INLINE void nxmac_rifs_to_in_mac_clk_setf(uint16_t rifstoinmacclk) +{ + ASSERT_ERR((((uint32_t)rifstoinmacclk << 20) & ~((uint32_t)0x3FF00000)) == 0); + REG_PL_WR(NXMAC_TIMINGS_9_ADDR, (REG_PL_RD(NXMAC_TIMINGS_9_ADDR) & ~((uint32_t)0x3FF00000)) | ((uint32_t)rifstoinmacclk << 20)); +} + +/** + * @brief Returns the current value of the rifsInMACClk field in the TIMINGS_9 register. + * + * The TIMINGS_9 register will be read and the rifsInMACClk field's value will be returned. + * + * @return The current value of the rifsInMACClk field in the TIMINGS_9 register. + */ +__INLINE uint16_t nxmac_rifs_in_mac_clk_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMINGS_9_ADDR); + return ((localVal & ((uint32_t)0x000FFC00)) >> 10); +} + +/** + * @brief Sets the rifsInMACClk field of the TIMINGS_9 register. + * + * The TIMINGS_9 register will be read, modified to contain the new field value, and written. + * + * @param[in] rifsinmacclk - The value to set the field to. + */ +__INLINE void nxmac_rifs_in_mac_clk_setf(uint16_t rifsinmacclk) +{ + ASSERT_ERR((((uint32_t)rifsinmacclk << 10) & ~((uint32_t)0x000FFC00)) == 0); + REG_PL_WR(NXMAC_TIMINGS_9_ADDR, (REG_PL_RD(NXMAC_TIMINGS_9_ADDR) & ~((uint32_t)0x000FFC00)) | ((uint32_t)rifsinmacclk << 10)); +} + +/** + * @brief Returns the current value of the txDMAProcDlyInMACClk field in the TIMINGS_9 register. + * + * The TIMINGS_9 register will be read and the txDMAProcDlyInMACClk field's value will be returned. + * + * @return The current value of the txDMAProcDlyInMACClk field in the TIMINGS_9 register. + */ +__INLINE uint16_t nxmac_tx_dma_proc_dly_in_mac_clk_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMINGS_9_ADDR); + return ((localVal & ((uint32_t)0x000003FF)) >> 0); +} + +/** + * @brief Sets the txDMAProcDlyInMACClk field of the TIMINGS_9 register. + * + * The TIMINGS_9 register will be read, modified to contain the new field value, and written. + * + * @param[in] txdmaprocdlyinmacclk - The value to set the field to. + */ +__INLINE void nxmac_tx_dma_proc_dly_in_mac_clk_setf(uint16_t txdmaprocdlyinmacclk) +{ + ASSERT_ERR((((uint32_t)txdmaprocdlyinmacclk << 0) & ~((uint32_t)0x000003FF)) == 0); + REG_PL_WR(NXMAC_TIMINGS_9_ADDR, (REG_PL_RD(NXMAC_TIMINGS_9_ADDR) & ~((uint32_t)0x000003FF)) | ((uint32_t)txdmaprocdlyinmacclk << 0)); +} + +/// @} + +/** + * @name PROT_TRIG_TIMER register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:08     hccaTriggerTimer   0x0
+ *  07:00     edcaTriggerTimer   0x9
+ * 
+ * + * @{ + */ + +/// Address of the PROT_TRIG_TIMER register +#define NXMAC_PROT_TRIG_TIMER_ADDR 0xC000010C +/// Offset of the PROT_TRIG_TIMER register from the base address +#define NXMAC_PROT_TRIG_TIMER_OFFSET 0x0000010C +/// Index of the PROT_TRIG_TIMER register +#define NXMAC_PROT_TRIG_TIMER_INDEX 0x00000043 +/// Reset value of the PROT_TRIG_TIMER register +#define NXMAC_PROT_TRIG_TIMER_RESET 0x00000009 + +/** + * @brief Returns the current value of the PROT_TRIG_TIMER register. + * The PROT_TRIG_TIMER register will be read and its value returned. + * @return The current value of the PROT_TRIG_TIMER register. + */ +__INLINE uint32_t nxmac_prot_trig_timer_get(void) +{ + return REG_PL_RD(NXMAC_PROT_TRIG_TIMER_ADDR); +} + +/** + * @brief Sets the PROT_TRIG_TIMER register to a value. + * The PROT_TRIG_TIMER register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_prot_trig_timer_set(uint32_t value) +{ + REG_PL_WR(NXMAC_PROT_TRIG_TIMER_ADDR, value); +} + +// field definitions +/// HCCA_TRIGGER_TIMER field mask +#define NXMAC_HCCA_TRIGGER_TIMER_MASK ((uint32_t)0x0000FF00) +/// HCCA_TRIGGER_TIMER field LSB position +#define NXMAC_HCCA_TRIGGER_TIMER_LSB 8 +/// HCCA_TRIGGER_TIMER field width +#define NXMAC_HCCA_TRIGGER_TIMER_WIDTH ((uint32_t)0x00000008) +/// EDCA_TRIGGER_TIMER field mask +#define NXMAC_EDCA_TRIGGER_TIMER_MASK ((uint32_t)0x000000FF) +/// EDCA_TRIGGER_TIMER field LSB position +#define NXMAC_EDCA_TRIGGER_TIMER_LSB 0 +/// EDCA_TRIGGER_TIMER field width +#define NXMAC_EDCA_TRIGGER_TIMER_WIDTH ((uint32_t)0x00000008) + +/// HCCA_TRIGGER_TIMER field reset value +#define NXMAC_HCCA_TRIGGER_TIMER_RST 0x0 +/// EDCA_TRIGGER_TIMER field reset value +#define NXMAC_EDCA_TRIGGER_TIMER_RST 0x9 + +/** + * @brief Unpacks PROT_TRIG_TIMER's fields from current value of the PROT_TRIG_TIMER register. + * + * Reads the PROT_TRIG_TIMER register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] hccatriggertimer - Will be populated with the current value of this field from the register. + * @param[out] edcatriggertimer - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_prot_trig_timer_unpack(uint8_t *hccatriggertimer, uint8_t *edcatriggertimer) +{ + uint32_t localVal = REG_PL_RD(NXMAC_PROT_TRIG_TIMER_ADDR); + + *hccatriggertimer = (localVal & ((uint32_t)0x0000FF00)) >> 8; + *edcatriggertimer = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +/** + * @brief Returns the current value of the hccaTriggerTimer field in the PROT_TRIG_TIMER register. + * + * The PROT_TRIG_TIMER register will be read and the hccaTriggerTimer field's value will be returned. + * + * @return The current value of the hccaTriggerTimer field in the PROT_TRIG_TIMER register. + */ +__INLINE uint8_t nxmac_hcca_trigger_timer_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_PROT_TRIG_TIMER_ADDR); + return ((localVal & ((uint32_t)0x0000FF00)) >> 8); +} + +/** + * @brief Returns the current value of the edcaTriggerTimer field in the PROT_TRIG_TIMER register. + * + * The PROT_TRIG_TIMER register will be read and the edcaTriggerTimer field's value will be returned. + * + * @return The current value of the edcaTriggerTimer field in the PROT_TRIG_TIMER register. + */ +__INLINE uint8_t nxmac_edca_trigger_timer_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_PROT_TRIG_TIMER_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +/** + * @brief Sets the edcaTriggerTimer field of the PROT_TRIG_TIMER register. + * + * The PROT_TRIG_TIMER register will be read, modified to contain the new field value, and written. + * + * @param[in] edcatriggertimer - The value to set the field to. + */ +__INLINE void nxmac_edca_trigger_timer_setf(uint8_t edcatriggertimer) +{ + ASSERT_ERR((((uint32_t)edcatriggertimer << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(NXMAC_PROT_TRIG_TIMER_ADDR, (uint32_t)edcatriggertimer << 0); +} + +/// @} + +/** + * @name TX_TRIGGER_TIMER register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:08      txPacketTimeout   0xF
+ *  07:00    txAbsoluteTimeout   0x9C
+ * 
+ * + * @{ + */ + +/// Address of the TX_TRIGGER_TIMER register +#define NXMAC_TX_TRIGGER_TIMER_ADDR 0xC0000110 +/// Offset of the TX_TRIGGER_TIMER register from the base address +#define NXMAC_TX_TRIGGER_TIMER_OFFSET 0x00000110 +/// Index of the TX_TRIGGER_TIMER register +#define NXMAC_TX_TRIGGER_TIMER_INDEX 0x00000044 +/// Reset value of the TX_TRIGGER_TIMER register +#define NXMAC_TX_TRIGGER_TIMER_RESET 0x00000F9C + +/** + * @brief Returns the current value of the TX_TRIGGER_TIMER register. + * The TX_TRIGGER_TIMER register will be read and its value returned. + * @return The current value of the TX_TRIGGER_TIMER register. + */ +__INLINE uint32_t nxmac_tx_trigger_timer_get(void) +{ + return REG_PL_RD(NXMAC_TX_TRIGGER_TIMER_ADDR); +} + +/** + * @brief Sets the TX_TRIGGER_TIMER register to a value. + * The TX_TRIGGER_TIMER register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_tx_trigger_timer_set(uint32_t value) +{ + REG_PL_WR(NXMAC_TX_TRIGGER_TIMER_ADDR, value); +} + +// field definitions +/// TX_PACKET_TIMEOUT field mask +#define NXMAC_TX_PACKET_TIMEOUT_MASK ((uint32_t)0x0000FF00) +/// TX_PACKET_TIMEOUT field LSB position +#define NXMAC_TX_PACKET_TIMEOUT_LSB 8 +/// TX_PACKET_TIMEOUT field width +#define NXMAC_TX_PACKET_TIMEOUT_WIDTH ((uint32_t)0x00000008) +/// TX_ABSOLUTE_TIMEOUT field mask +#define NXMAC_TX_ABSOLUTE_TIMEOUT_MASK ((uint32_t)0x000000FF) +/// TX_ABSOLUTE_TIMEOUT field LSB position +#define NXMAC_TX_ABSOLUTE_TIMEOUT_LSB 0 +/// TX_ABSOLUTE_TIMEOUT field width +#define NXMAC_TX_ABSOLUTE_TIMEOUT_WIDTH ((uint32_t)0x00000008) + +/// TX_PACKET_TIMEOUT field reset value +#define NXMAC_TX_PACKET_TIMEOUT_RST 0xF +/// TX_ABSOLUTE_TIMEOUT field reset value +#define NXMAC_TX_ABSOLUTE_TIMEOUT_RST 0x9C + +/** + * @brief Constructs a value for the TX_TRIGGER_TIMER register given values for its fields + * and writes the value to the register. + * + * @param[in] txpackettimeout - The value to use for the txPacketTimeout field. + * @param[in] txabsolutetimeout - The value to use for the txAbsoluteTimeout field. + */ +__INLINE void nxmac_tx_trigger_timer_pack(uint8_t txpackettimeout, uint8_t txabsolutetimeout) +{ + ASSERT_ERR((((uint32_t)txpackettimeout << 8) & ~((uint32_t)0x0000FF00)) == 0); + ASSERT_ERR((((uint32_t)txabsolutetimeout << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(NXMAC_TX_TRIGGER_TIMER_ADDR, ((uint32_t)txpackettimeout << 8) | ((uint32_t)txabsolutetimeout << 0)); +} + +/** + * @brief Unpacks TX_TRIGGER_TIMER's fields from current value of the TX_TRIGGER_TIMER register. + * + * Reads the TX_TRIGGER_TIMER register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] txpackettimeout - Will be populated with the current value of this field from the register. + * @param[out] txabsolutetimeout - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_tx_trigger_timer_unpack(uint8_t *txpackettimeout, uint8_t *txabsolutetimeout) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_TRIGGER_TIMER_ADDR); + + *txpackettimeout = (localVal & ((uint32_t)0x0000FF00)) >> 8; + *txabsolutetimeout = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +/** + * @brief Returns the current value of the txPacketTimeout field in the TX_TRIGGER_TIMER register. + * + * The TX_TRIGGER_TIMER register will be read and the txPacketTimeout field's value will be returned. + * + * @return The current value of the txPacketTimeout field in the TX_TRIGGER_TIMER register. + */ +__INLINE uint8_t nxmac_tx_packet_timeout_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_TRIGGER_TIMER_ADDR); + return ((localVal & ((uint32_t)0x0000FF00)) >> 8); +} + +/** + * @brief Sets the txPacketTimeout field of the TX_TRIGGER_TIMER register. + * + * The TX_TRIGGER_TIMER register will be read, modified to contain the new field value, and written. + * + * @param[in] txpackettimeout - The value to set the field to. + */ +__INLINE void nxmac_tx_packet_timeout_setf(uint8_t txpackettimeout) +{ + ASSERT_ERR((((uint32_t)txpackettimeout << 8) & ~((uint32_t)0x0000FF00)) == 0); + REG_PL_WR(NXMAC_TX_TRIGGER_TIMER_ADDR, (REG_PL_RD(NXMAC_TX_TRIGGER_TIMER_ADDR) & ~((uint32_t)0x0000FF00)) | ((uint32_t)txpackettimeout << 8)); +} + +/** + * @brief Returns the current value of the txAbsoluteTimeout field in the TX_TRIGGER_TIMER register. + * + * The TX_TRIGGER_TIMER register will be read and the txAbsoluteTimeout field's value will be returned. + * + * @return The current value of the txAbsoluteTimeout field in the TX_TRIGGER_TIMER register. + */ +__INLINE uint8_t nxmac_tx_absolute_timeout_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_TRIGGER_TIMER_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +/** + * @brief Sets the txAbsoluteTimeout field of the TX_TRIGGER_TIMER register. + * + * The TX_TRIGGER_TIMER register will be read, modified to contain the new field value, and written. + * + * @param[in] txabsolutetimeout - The value to set the field to. + */ +__INLINE void nxmac_tx_absolute_timeout_setf(uint8_t txabsolutetimeout) +{ + ASSERT_ERR((((uint32_t)txabsolutetimeout << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(NXMAC_TX_TRIGGER_TIMER_ADDR, (REG_PL_RD(NXMAC_TX_TRIGGER_TIMER_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)txabsolutetimeout << 0)); +} + +/// @} + +/** + * @name RX_TRIGGER_TIMER register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  23:16   rxPayloadUsedCount   0xF
+ *  15:08      rxPacketTimeout   0xF
+ *  07:00    rxAbsoluteTimeout   0x9C
+ * 
+ * + * @{ + */ + +/// Address of the RX_TRIGGER_TIMER register +#define NXMAC_RX_TRIGGER_TIMER_ADDR 0xC0000114 +/// Offset of the RX_TRIGGER_TIMER register from the base address +#define NXMAC_RX_TRIGGER_TIMER_OFFSET 0x00000114 +/// Index of the RX_TRIGGER_TIMER register +#define NXMAC_RX_TRIGGER_TIMER_INDEX 0x00000045 +/// Reset value of the RX_TRIGGER_TIMER register +#define NXMAC_RX_TRIGGER_TIMER_RESET 0x000F0F9C + +/** + * @brief Returns the current value of the RX_TRIGGER_TIMER register. + * The RX_TRIGGER_TIMER register will be read and its value returned. + * @return The current value of the RX_TRIGGER_TIMER register. + */ +__INLINE uint32_t nxmac_rx_trigger_timer_get(void) +{ + return REG_PL_RD(NXMAC_RX_TRIGGER_TIMER_ADDR); +} + +/** + * @brief Sets the RX_TRIGGER_TIMER register to a value. + * The RX_TRIGGER_TIMER register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_rx_trigger_timer_set(uint32_t value) +{ + REG_PL_WR(NXMAC_RX_TRIGGER_TIMER_ADDR, value); +} + +// field definitions +/// RX_PAYLOAD_USED_COUNT field mask +#define NXMAC_RX_PAYLOAD_USED_COUNT_MASK ((uint32_t)0x00FF0000) +/// RX_PAYLOAD_USED_COUNT field LSB position +#define NXMAC_RX_PAYLOAD_USED_COUNT_LSB 16 +/// RX_PAYLOAD_USED_COUNT field width +#define NXMAC_RX_PAYLOAD_USED_COUNT_WIDTH ((uint32_t)0x00000008) +/// RX_PACKET_TIMEOUT field mask +#define NXMAC_RX_PACKET_TIMEOUT_MASK ((uint32_t)0x0000FF00) +/// RX_PACKET_TIMEOUT field LSB position +#define NXMAC_RX_PACKET_TIMEOUT_LSB 8 +/// RX_PACKET_TIMEOUT field width +#define NXMAC_RX_PACKET_TIMEOUT_WIDTH ((uint32_t)0x00000008) +/// RX_ABSOLUTE_TIMEOUT field mask +#define NXMAC_RX_ABSOLUTE_TIMEOUT_MASK ((uint32_t)0x000000FF) +/// RX_ABSOLUTE_TIMEOUT field LSB position +#define NXMAC_RX_ABSOLUTE_TIMEOUT_LSB 0 +/// RX_ABSOLUTE_TIMEOUT field width +#define NXMAC_RX_ABSOLUTE_TIMEOUT_WIDTH ((uint32_t)0x00000008) + +/// RX_PAYLOAD_USED_COUNT field reset value +#define NXMAC_RX_PAYLOAD_USED_COUNT_RST 0xF +/// RX_PACKET_TIMEOUT field reset value +#define NXMAC_RX_PACKET_TIMEOUT_RST 0xF +/// RX_ABSOLUTE_TIMEOUT field reset value +#define NXMAC_RX_ABSOLUTE_TIMEOUT_RST 0x9C + +/** + * @brief Constructs a value for the RX_TRIGGER_TIMER register given values for its fields + * and writes the value to the register. + * + * @param[in] rxpayloadusedcount - The value to use for the rxPayloadUsedCount field. + * @param[in] rxpackettimeout - The value to use for the rxPacketTimeout field. + * @param[in] rxabsolutetimeout - The value to use for the rxAbsoluteTimeout field. + */ +__INLINE void nxmac_rx_trigger_timer_pack(uint8_t rxpayloadusedcount, uint8_t rxpackettimeout, uint8_t rxabsolutetimeout) +{ + ASSERT_ERR((((uint32_t)rxpayloadusedcount << 16) & ~((uint32_t)0x00FF0000)) == 0); + ASSERT_ERR((((uint32_t)rxpackettimeout << 8) & ~((uint32_t)0x0000FF00)) == 0); + ASSERT_ERR((((uint32_t)rxabsolutetimeout << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(NXMAC_RX_TRIGGER_TIMER_ADDR, ((uint32_t)rxpayloadusedcount << 16) | ((uint32_t)rxpackettimeout << 8) | ((uint32_t)rxabsolutetimeout << 0)); +} + +/** + * @brief Unpacks RX_TRIGGER_TIMER's fields from current value of the RX_TRIGGER_TIMER register. + * + * Reads the RX_TRIGGER_TIMER register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] rxpayloadusedcount - Will be populated with the current value of this field from the register. + * @param[out] rxpackettimeout - Will be populated with the current value of this field from the register. + * @param[out] rxabsolutetimeout - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_rx_trigger_timer_unpack(uint8_t *rxpayloadusedcount, uint8_t *rxpackettimeout, uint8_t *rxabsolutetimeout) +{ + uint32_t localVal = REG_PL_RD(NXMAC_RX_TRIGGER_TIMER_ADDR); + + *rxpayloadusedcount = (localVal & ((uint32_t)0x00FF0000)) >> 16; + *rxpackettimeout = (localVal & ((uint32_t)0x0000FF00)) >> 8; + *rxabsolutetimeout = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +/** + * @brief Returns the current value of the rxPayloadUsedCount field in the RX_TRIGGER_TIMER register. + * + * The RX_TRIGGER_TIMER register will be read and the rxPayloadUsedCount field's value will be returned. + * + * @return The current value of the rxPayloadUsedCount field in the RX_TRIGGER_TIMER register. + */ +__INLINE uint8_t nxmac_rx_payload_used_count_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_RX_TRIGGER_TIMER_ADDR); + return ((localVal & ((uint32_t)0x00FF0000)) >> 16); +} + +/** + * @brief Sets the rxPayloadUsedCount field of the RX_TRIGGER_TIMER register. + * + * The RX_TRIGGER_TIMER register will be read, modified to contain the new field value, and written. + * + * @param[in] rxpayloadusedcount - The value to set the field to. + */ +__INLINE void nxmac_rx_payload_used_count_setf(uint8_t rxpayloadusedcount) +{ + ASSERT_ERR((((uint32_t)rxpayloadusedcount << 16) & ~((uint32_t)0x00FF0000)) == 0); + REG_PL_WR(NXMAC_RX_TRIGGER_TIMER_ADDR, (REG_PL_RD(NXMAC_RX_TRIGGER_TIMER_ADDR) & ~((uint32_t)0x00FF0000)) | ((uint32_t)rxpayloadusedcount << 16)); +} + +/** + * @brief Returns the current value of the rxPacketTimeout field in the RX_TRIGGER_TIMER register. + * + * The RX_TRIGGER_TIMER register will be read and the rxPacketTimeout field's value will be returned. + * + * @return The current value of the rxPacketTimeout field in the RX_TRIGGER_TIMER register. + */ +__INLINE uint8_t nxmac_rx_packet_timeout_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_RX_TRIGGER_TIMER_ADDR); + return ((localVal & ((uint32_t)0x0000FF00)) >> 8); +} + +/** + * @brief Sets the rxPacketTimeout field of the RX_TRIGGER_TIMER register. + * + * The RX_TRIGGER_TIMER register will be read, modified to contain the new field value, and written. + * + * @param[in] rxpackettimeout - The value to set the field to. + */ +__INLINE void nxmac_rx_packet_timeout_setf(uint8_t rxpackettimeout) +{ + ASSERT_ERR((((uint32_t)rxpackettimeout << 8) & ~((uint32_t)0x0000FF00)) == 0); + REG_PL_WR(NXMAC_RX_TRIGGER_TIMER_ADDR, (REG_PL_RD(NXMAC_RX_TRIGGER_TIMER_ADDR) & ~((uint32_t)0x0000FF00)) | ((uint32_t)rxpackettimeout << 8)); +} + +/** + * @brief Returns the current value of the rxAbsoluteTimeout field in the RX_TRIGGER_TIMER register. + * + * The RX_TRIGGER_TIMER register will be read and the rxAbsoluteTimeout field's value will be returned. + * + * @return The current value of the rxAbsoluteTimeout field in the RX_TRIGGER_TIMER register. + */ +__INLINE uint8_t nxmac_rx_absolute_timeout_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_RX_TRIGGER_TIMER_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +/** + * @brief Sets the rxAbsoluteTimeout field of the RX_TRIGGER_TIMER register. + * + * The RX_TRIGGER_TIMER register will be read, modified to contain the new field value, and written. + * + * @param[in] rxabsolutetimeout - The value to set the field to. + */ +__INLINE void nxmac_rx_absolute_timeout_setf(uint8_t rxabsolutetimeout) +{ + ASSERT_ERR((((uint32_t)rxabsolutetimeout << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(NXMAC_RX_TRIGGER_TIMER_ADDR, (REG_PL_RD(NXMAC_RX_TRIGGER_TIMER_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)rxabsolutetimeout << 0)); +} + +/// @} + +/** + * @name MIB_TABLE_WRITE register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:16             mibValue   0x0
+ *     15             mibWrite   0
+ *     14     mibIncrementMode   1
+ *  09:00        mibTableIndex   0x0
+ * 
+ * + * @{ + */ + +/// Address of the MIB_TABLE_WRITE register +#define NXMAC_MIB_TABLE_WRITE_ADDR 0xC0000118 +/// Offset of the MIB_TABLE_WRITE register from the base address +#define NXMAC_MIB_TABLE_WRITE_OFFSET 0x00000118 +/// Index of the MIB_TABLE_WRITE register +#define NXMAC_MIB_TABLE_WRITE_INDEX 0x00000046 +/// Reset value of the MIB_TABLE_WRITE register +#define NXMAC_MIB_TABLE_WRITE_RESET 0x00004000 + +/** + * @brief Returns the current value of the MIB_TABLE_WRITE register. + * The MIB_TABLE_WRITE register will be read and its value returned. + * @return The current value of the MIB_TABLE_WRITE register. + */ +__INLINE uint32_t nxmac_mib_table_write_get(void) +{ + return REG_PL_RD(NXMAC_MIB_TABLE_WRITE_ADDR); +} + +/** + * @brief Sets the MIB_TABLE_WRITE register to a value. + * The MIB_TABLE_WRITE register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_mib_table_write_set(uint32_t value) +{ + REG_PL_WR(NXMAC_MIB_TABLE_WRITE_ADDR, value); +} + +// field definitions +/// MIB_VALUE field mask +#define NXMAC_MIB_VALUE_MASK ((uint32_t)0xFFFF0000) +/// MIB_VALUE field LSB position +#define NXMAC_MIB_VALUE_LSB 16 +/// MIB_VALUE field width +#define NXMAC_MIB_VALUE_WIDTH ((uint32_t)0x00000010) +/// MIB_WRITE field bit +#define NXMAC_MIB_WRITE_BIT ((uint32_t)0x00008000) +/// MIB_WRITE field position +#define NXMAC_MIB_WRITE_POS 15 +/// MIB_INCREMENT_MODE field bit +#define NXMAC_MIB_INCREMENT_MODE_BIT ((uint32_t)0x00004000) +/// MIB_INCREMENT_MODE field position +#define NXMAC_MIB_INCREMENT_MODE_POS 14 +/// MIB_TABLE_INDEX field mask +#define NXMAC_MIB_TABLE_INDEX_MASK ((uint32_t)0x000003FF) +/// MIB_TABLE_INDEX field LSB position +#define NXMAC_MIB_TABLE_INDEX_LSB 0 +/// MIB_TABLE_INDEX field width +#define NXMAC_MIB_TABLE_INDEX_WIDTH ((uint32_t)0x0000000A) + +/// MIB_VALUE field reset value +#define NXMAC_MIB_VALUE_RST 0x0 +/// MIB_WRITE field reset value +#define NXMAC_MIB_WRITE_RST 0x0 +/// MIB_INCREMENT_MODE field reset value +#define NXMAC_MIB_INCREMENT_MODE_RST 0x1 +/// MIB_TABLE_INDEX field reset value +#define NXMAC_MIB_TABLE_INDEX_RST 0x0 + +/** + * @brief Constructs a value for the MIB_TABLE_WRITE register given values for its fields + * and writes the value to the register. + * + * @param[in] mibvalue - The value to use for the mibValue field. + * @param[in] mibwrite - The value to use for the mibWrite field. + * @param[in] mibincrementmode - The value to use for the mibIncrementMode field. + * @param[in] mibtableindex - The value to use for the mibTableIndex field. + */ +__INLINE void nxmac_mib_table_write_pack(uint16_t mibvalue, uint8_t mibwrite, uint8_t mibincrementmode, uint16_t mibtableindex) +{ + ASSERT_ERR((((uint32_t)mibvalue << 16) & ~((uint32_t)0xFFFF0000)) == 0); + ASSERT_ERR((((uint32_t)mibwrite << 15) & ~((uint32_t)0x00008000)) == 0); + ASSERT_ERR((((uint32_t)mibincrementmode << 14) & ~((uint32_t)0x00004000)) == 0); + ASSERT_ERR((((uint32_t)mibtableindex << 0) & ~((uint32_t)0x000003FF)) == 0); + REG_PL_WR(NXMAC_MIB_TABLE_WRITE_ADDR, ((uint32_t)mibvalue << 16) | ((uint32_t)mibwrite << 15) | ((uint32_t)mibincrementmode << 14) | ((uint32_t)mibtableindex << 0)); +} + +/** + * @brief Unpacks MIB_TABLE_WRITE's fields from current value of the MIB_TABLE_WRITE register. + * + * Reads the MIB_TABLE_WRITE register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] mibvalue - Will be populated with the current value of this field from the register. + * @param[out] mibwrite - Will be populated with the current value of this field from the register. + * @param[out] mibincrementmode - Will be populated with the current value of this field from the register. + * @param[out] mibtableindex - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_mib_table_write_unpack(uint16_t *mibvalue, uint8_t *mibwrite, uint8_t *mibincrementmode, uint16_t *mibtableindex) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MIB_TABLE_WRITE_ADDR); + + *mibvalue = (localVal & ((uint32_t)0xFFFF0000)) >> 16; + *mibwrite = (localVal & ((uint32_t)0x00008000)) >> 15; + *mibincrementmode = (localVal & ((uint32_t)0x00004000)) >> 14; + *mibtableindex = (localVal & ((uint32_t)0x000003FF)) >> 0; +} + +/** + * @brief Returns the current value of the mibValue field in the MIB_TABLE_WRITE register. + * + * The MIB_TABLE_WRITE register will be read and the mibValue field's value will be returned. + * + * @return The current value of the mibValue field in the MIB_TABLE_WRITE register. + */ +__INLINE uint16_t nxmac_mib_value_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MIB_TABLE_WRITE_ADDR); + return ((localVal & ((uint32_t)0xFFFF0000)) >> 16); +} + +/** + * @brief Sets the mibValue field of the MIB_TABLE_WRITE register. + * + * The MIB_TABLE_WRITE register will be read, modified to contain the new field value, and written. + * + * @param[in] mibvalue - The value to set the field to. + */ +__INLINE void nxmac_mib_value_setf(uint16_t mibvalue) +{ + ASSERT_ERR((((uint32_t)mibvalue << 16) & ~((uint32_t)0xFFFF0000)) == 0); + REG_PL_WR(NXMAC_MIB_TABLE_WRITE_ADDR, (REG_PL_RD(NXMAC_MIB_TABLE_WRITE_ADDR) & ~((uint32_t)0xFFFF0000)) | ((uint32_t)mibvalue << 16)); +} + +/** + * @brief Returns the current value of the mibWrite field in the MIB_TABLE_WRITE register. + * + * The MIB_TABLE_WRITE register will be read and the mibWrite field's value will be returned. + * + * @return The current value of the mibWrite field in the MIB_TABLE_WRITE register. + */ +__INLINE uint8_t nxmac_mib_write_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MIB_TABLE_WRITE_ADDR); + return ((localVal & ((uint32_t)0x00008000)) >> 15); +} + +/** + * @brief Sets the mibWrite field of the MIB_TABLE_WRITE register. + * + * The MIB_TABLE_WRITE register will be read, modified to contain the new field value, and written. + * + * @param[in] mibwrite - The value to set the field to. + */ +__INLINE void nxmac_mib_write_setf(uint8_t mibwrite) +{ + ASSERT_ERR((((uint32_t)mibwrite << 15) & ~((uint32_t)0x00008000)) == 0); + REG_PL_WR(NXMAC_MIB_TABLE_WRITE_ADDR, (REG_PL_RD(NXMAC_MIB_TABLE_WRITE_ADDR) & ~((uint32_t)0x00008000)) | ((uint32_t)mibwrite << 15)); +} + +/** + * @brief Returns the current value of the mibIncrementMode field in the MIB_TABLE_WRITE register. + * + * The MIB_TABLE_WRITE register will be read and the mibIncrementMode field's value will be returned. + * + * @return The current value of the mibIncrementMode field in the MIB_TABLE_WRITE register. + */ +__INLINE uint8_t nxmac_mib_increment_mode_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MIB_TABLE_WRITE_ADDR); + return ((localVal & ((uint32_t)0x00004000)) >> 14); +} + +/** + * @brief Sets the mibIncrementMode field of the MIB_TABLE_WRITE register. + * + * The MIB_TABLE_WRITE register will be read, modified to contain the new field value, and written. + * + * @param[in] mibincrementmode - The value to set the field to. + */ +__INLINE void nxmac_mib_increment_mode_setf(uint8_t mibincrementmode) +{ + ASSERT_ERR((((uint32_t)mibincrementmode << 14) & ~((uint32_t)0x00004000)) == 0); + REG_PL_WR(NXMAC_MIB_TABLE_WRITE_ADDR, (REG_PL_RD(NXMAC_MIB_TABLE_WRITE_ADDR) & ~((uint32_t)0x00004000)) | ((uint32_t)mibincrementmode << 14)); +} + +/** + * @brief Returns the current value of the mibTableIndex field in the MIB_TABLE_WRITE register. + * + * The MIB_TABLE_WRITE register will be read and the mibTableIndex field's value will be returned. + * + * @return The current value of the mibTableIndex field in the MIB_TABLE_WRITE register. + */ +__INLINE uint16_t nxmac_mib_table_index_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MIB_TABLE_WRITE_ADDR); + return ((localVal & ((uint32_t)0x000003FF)) >> 0); +} + +/** + * @brief Sets the mibTableIndex field of the MIB_TABLE_WRITE register. + * + * The MIB_TABLE_WRITE register will be read, modified to contain the new field value, and written. + * + * @param[in] mibtableindex - The value to set the field to. + */ +__INLINE void nxmac_mib_table_index_setf(uint16_t mibtableindex) +{ + ASSERT_ERR((((uint32_t)mibtableindex << 0) & ~((uint32_t)0x000003FF)) == 0); + REG_PL_WR(NXMAC_MIB_TABLE_WRITE_ADDR, (REG_PL_RD(NXMAC_MIB_TABLE_WRITE_ADDR) & ~((uint32_t)0x000003FF)) | ((uint32_t)mibtableindex << 0)); +} + +/// @} + +/** + * @name MONOTONIC_COUNTER_1 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00    monotonicCounter1   0x0
+ * 
+ * + * @{ + */ + +/// Address of the MONOTONIC_COUNTER_1 register +#define NXMAC_MONOTONIC_COUNTER_1_ADDR 0xC000011C +/// Offset of the MONOTONIC_COUNTER_1 register from the base address +#define NXMAC_MONOTONIC_COUNTER_1_OFFSET 0x0000011C +/// Index of the MONOTONIC_COUNTER_1 register +#define NXMAC_MONOTONIC_COUNTER_1_INDEX 0x00000047 +/// Reset value of the MONOTONIC_COUNTER_1 register +#define NXMAC_MONOTONIC_COUNTER_1_RESET 0x00000000 + +/** + * @brief Returns the current value of the MONOTONIC_COUNTER_1 register. + * The MONOTONIC_COUNTER_1 register will be read and its value returned. + * @return The current value of the MONOTONIC_COUNTER_1 register. + */ +__INLINE uint32_t nxmac_monotonic_counter_1_get(void) +{ + return REG_PL_RD(NXMAC_MONOTONIC_COUNTER_1_ADDR); +} + +// field definitions +/// MONOTONIC_COUNTER_1 field mask +#define NXMAC_MONOTONIC_COUNTER_1_MASK ((uint32_t)0xFFFFFFFF) +/// MONOTONIC_COUNTER_1 field LSB position +#define NXMAC_MONOTONIC_COUNTER_1_LSB 0 +/// MONOTONIC_COUNTER_1 field width +#define NXMAC_MONOTONIC_COUNTER_1_WIDTH ((uint32_t)0x00000020) + +/// MONOTONIC_COUNTER_1 field reset value +#define NXMAC_MONOTONIC_COUNTER_1_RST 0x0 + +/** + * @brief Returns the current value of the monotonicCounter1 field in the MONOTONIC_COUNTER_1 register. + * + * The MONOTONIC_COUNTER_1 register will be read and the monotonicCounter1 field's value will be returned. + * + * @return The current value of the monotonicCounter1 field in the MONOTONIC_COUNTER_1 register. + */ +__INLINE uint32_t nxmac_monotonic_counter_1_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MONOTONIC_COUNTER_1_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/// @} + +/** + * @name MONOTONIC_COUNTER_2_LO register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00   monotonicCounterLow2   0x0
+ * 
+ * + * @{ + */ + +/// Address of the MONOTONIC_COUNTER_2_LO register +#define NXMAC_MONOTONIC_COUNTER_2_LO_ADDR 0xC0000120 +/// Offset of the MONOTONIC_COUNTER_2_LO register from the base address +#define NXMAC_MONOTONIC_COUNTER_2_LO_OFFSET 0x00000120 +/// Index of the MONOTONIC_COUNTER_2_LO register +#define NXMAC_MONOTONIC_COUNTER_2_LO_INDEX 0x00000048 +/// Reset value of the MONOTONIC_COUNTER_2_LO register +#define NXMAC_MONOTONIC_COUNTER_2_LO_RESET 0x00000000 + +/** + * @brief Returns the current value of the MONOTONIC_COUNTER_2_LO register. + * The MONOTONIC_COUNTER_2_LO register will be read and its value returned. + * @return The current value of the MONOTONIC_COUNTER_2_LO register. + */ +__INLINE uint32_t nxmac_monotonic_counter_2_lo_get(void) +{ + return REG_PL_RD(NXMAC_MONOTONIC_COUNTER_2_LO_ADDR); +} + +/** + * @brief Sets the MONOTONIC_COUNTER_2_LO register to a value. + * The MONOTONIC_COUNTER_2_LO register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_monotonic_counter_2_lo_set(uint32_t value) +{ + REG_PL_WR(NXMAC_MONOTONIC_COUNTER_2_LO_ADDR, value); +} + +// field definitions +/// MONOTONIC_COUNTER_LOW_2 field mask +#define NXMAC_MONOTONIC_COUNTER_LOW_2_MASK ((uint32_t)0xFFFFFFFF) +/// MONOTONIC_COUNTER_LOW_2 field LSB position +#define NXMAC_MONOTONIC_COUNTER_LOW_2_LSB 0 +/// MONOTONIC_COUNTER_LOW_2 field width +#define NXMAC_MONOTONIC_COUNTER_LOW_2_WIDTH ((uint32_t)0x00000020) + +/// MONOTONIC_COUNTER_LOW_2 field reset value +#define NXMAC_MONOTONIC_COUNTER_LOW_2_RST 0x0 + +/** + * @brief Returns the current value of the monotonicCounterLow2 field in the MONOTONIC_COUNTER_2_LO register. + * + * The MONOTONIC_COUNTER_2_LO register will be read and the monotonicCounterLow2 field's value will be returned. + * + * @return The current value of the monotonicCounterLow2 field in the MONOTONIC_COUNTER_2_LO register. + */ +__INLINE uint32_t nxmac_monotonic_counter_low_2_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MONOTONIC_COUNTER_2_LO_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the monotonicCounterLow2 field of the MONOTONIC_COUNTER_2_LO register. + * + * The MONOTONIC_COUNTER_2_LO register will be read, modified to contain the new field value, and written. + * + * @param[in] monotoniccounterlow2 - The value to set the field to. + */ +__INLINE void nxmac_monotonic_counter_low_2_setf(uint32_t monotoniccounterlow2) +{ + ASSERT_ERR((((uint32_t)monotoniccounterlow2 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(NXMAC_MONOTONIC_COUNTER_2_LO_ADDR, (uint32_t)monotoniccounterlow2 << 0); +} + +/// @} + +/** + * @name MONOTONIC_COUNTER_2_HI register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31   monotonicCounter2SWUpdate   0
+ *  15:00   monotonicCounterHigh2   0x0
+ * 
+ * + * @{ + */ + +/// Address of the MONOTONIC_COUNTER_2_HI register +#define NXMAC_MONOTONIC_COUNTER_2_HI_ADDR 0xC0000124 +/// Offset of the MONOTONIC_COUNTER_2_HI register from the base address +#define NXMAC_MONOTONIC_COUNTER_2_HI_OFFSET 0x00000124 +/// Index of the MONOTONIC_COUNTER_2_HI register +#define NXMAC_MONOTONIC_COUNTER_2_HI_INDEX 0x00000049 +/// Reset value of the MONOTONIC_COUNTER_2_HI register +#define NXMAC_MONOTONIC_COUNTER_2_HI_RESET 0x00000000 + +/** + * @brief Returns the current value of the MONOTONIC_COUNTER_2_HI register. + * The MONOTONIC_COUNTER_2_HI register will be read and its value returned. + * @return The current value of the MONOTONIC_COUNTER_2_HI register. + */ +__INLINE uint32_t nxmac_monotonic_counter_2_hi_get(void) +{ + return REG_PL_RD(NXMAC_MONOTONIC_COUNTER_2_HI_ADDR); +} + +/** + * @brief Sets the MONOTONIC_COUNTER_2_HI register to a value. + * The MONOTONIC_COUNTER_2_HI register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_monotonic_counter_2_hi_set(uint32_t value) +{ + REG_PL_WR(NXMAC_MONOTONIC_COUNTER_2_HI_ADDR, value); +} + +// field definitions +/// MONOTONIC_COUNTER_2SW_UPDATE field bit +#define NXMAC_MONOTONIC_COUNTER_2SW_UPDATE_BIT ((uint32_t)0x80000000) +/// MONOTONIC_COUNTER_2SW_UPDATE field position +#define NXMAC_MONOTONIC_COUNTER_2SW_UPDATE_POS 31 +/// MONOTONIC_COUNTER_HIGH_2 field mask +#define NXMAC_MONOTONIC_COUNTER_HIGH_2_MASK ((uint32_t)0x0000FFFF) +/// MONOTONIC_COUNTER_HIGH_2 field LSB position +#define NXMAC_MONOTONIC_COUNTER_HIGH_2_LSB 0 +/// MONOTONIC_COUNTER_HIGH_2 field width +#define NXMAC_MONOTONIC_COUNTER_HIGH_2_WIDTH ((uint32_t)0x00000010) + +/// MONOTONIC_COUNTER_2SW_UPDATE field reset value +#define NXMAC_MONOTONIC_COUNTER_2SW_UPDATE_RST 0x0 +/// MONOTONIC_COUNTER_HIGH_2 field reset value +#define NXMAC_MONOTONIC_COUNTER_HIGH_2_RST 0x0 + +/** + * @brief Constructs a value for the MONOTONIC_COUNTER_2_HI register given values for its fields + * and writes the value to the register. + * + * @param[in] monotoniccounter2swupdate - The value to use for the monotonicCounter2SWUpdate field. + * @param[in] monotoniccounterhigh2 - The value to use for the monotonicCounterHigh2 field. + */ +__INLINE void nxmac_monotonic_counter_2_hi_pack(uint8_t monotoniccounter2swupdate, uint16_t monotoniccounterhigh2) +{ + ASSERT_ERR((((uint32_t)monotoniccounter2swupdate << 31) & ~((uint32_t)0x80000000)) == 0); + ASSERT_ERR((((uint32_t)monotoniccounterhigh2 << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_PL_WR(NXMAC_MONOTONIC_COUNTER_2_HI_ADDR, ((uint32_t)monotoniccounter2swupdate << 31) | ((uint32_t)monotoniccounterhigh2 << 0)); +} + +/** + * @brief Unpacks MONOTONIC_COUNTER_2_HI's fields from current value of the MONOTONIC_COUNTER_2_HI register. + * + * Reads the MONOTONIC_COUNTER_2_HI register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] monotoniccounter2swupdate - Will be populated with the current value of this field from the register. + * @param[out] monotoniccounterhigh2 - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_monotonic_counter_2_hi_unpack(uint8_t *monotoniccounter2swupdate, uint16_t *monotoniccounterhigh2) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MONOTONIC_COUNTER_2_HI_ADDR); + + *monotoniccounter2swupdate = (localVal & ((uint32_t)0x80000000)) >> 31; + *monotoniccounterhigh2 = (localVal & ((uint32_t)0x0000FFFF)) >> 0; +} + +/** + * @brief Returns the current value of the monotonicCounter2SWUpdate field in the MONOTONIC_COUNTER_2_HI register. + * + * The MONOTONIC_COUNTER_2_HI register will be read and the monotonicCounter2SWUpdate field's value will be returned. + * + * @return The current value of the monotonicCounter2SWUpdate field in the MONOTONIC_COUNTER_2_HI register. + */ +__INLINE uint8_t nxmac_monotonic_counter_2sw_update_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MONOTONIC_COUNTER_2_HI_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +/** + * @brief Sets the monotonicCounter2SWUpdate field of the MONOTONIC_COUNTER_2_HI register. + * + * The MONOTONIC_COUNTER_2_HI register will be read, modified to contain the new field value, and written. + * + * @param[in] monotoniccounter2swupdate - The value to set the field to. + */ +__INLINE void nxmac_monotonic_counter_2sw_update_setf(uint8_t monotoniccounter2swupdate) +{ + ASSERT_ERR((((uint32_t)monotoniccounter2swupdate << 31) & ~((uint32_t)0x80000000)) == 0); + REG_PL_WR(NXMAC_MONOTONIC_COUNTER_2_HI_ADDR, (REG_PL_RD(NXMAC_MONOTONIC_COUNTER_2_HI_ADDR) & ~((uint32_t)0x80000000)) | ((uint32_t)monotoniccounter2swupdate << 31)); +} + +/** + * @brief Returns the current value of the monotonicCounterHigh2 field in the MONOTONIC_COUNTER_2_HI register. + * + * The MONOTONIC_COUNTER_2_HI register will be read and the monotonicCounterHigh2 field's value will be returned. + * + * @return The current value of the monotonicCounterHigh2 field in the MONOTONIC_COUNTER_2_HI register. + */ +__INLINE uint16_t nxmac_monotonic_counter_high_2_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MONOTONIC_COUNTER_2_HI_ADDR); + return ((localVal & ((uint32_t)0x0000FFFF)) >> 0); +} + +/** + * @brief Sets the monotonicCounterHigh2 field of the MONOTONIC_COUNTER_2_HI register. + * + * The MONOTONIC_COUNTER_2_HI register will be read, modified to contain the new field value, and written. + * + * @param[in] monotoniccounterhigh2 - The value to set the field to. + */ +__INLINE void nxmac_monotonic_counter_high_2_setf(uint16_t monotoniccounterhigh2) +{ + ASSERT_ERR((((uint32_t)monotoniccounterhigh2 << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_PL_WR(NXMAC_MONOTONIC_COUNTER_2_HI_ADDR, (REG_PL_RD(NXMAC_MONOTONIC_COUNTER_2_HI_ADDR) & ~((uint32_t)0x0000FFFF)) | ((uint32_t)monotoniccounterhigh2 << 0)); +} + +/// @} + +/** + * @name ABS_TIMER register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00        absTimerValue   0x0
+ * 
+ * + * @{ + */ + +/// Address of the ABS_TIMER register +#define NXMAC_ABS_TIMER_ADDR 0xC0000128 +/// Offset of the ABS_TIMER register from the base address +#define NXMAC_ABS_TIMER_OFFSET 0x00000128 +/// Index of the ABS_TIMER register +#define NXMAC_ABS_TIMER_INDEX 0x0000004A +/// Reset value of the ABS_TIMER register +#define NXMAC_ABS_TIMER_RESET 0x00000000 +/// Number of elements of the ABS_TIMER register array +#define NXMAC_ABS_TIMER_COUNT 10 + +/** + * @brief Returns the current value of the ABS_TIMER register. + * The ABS_TIMER register will be read and its value returned. + * @param[in] reg_idx Index of the register + * @return The current value of the ABS_TIMER register. + */ +__INLINE uint32_t nxmac_abs_timer_get(int reg_idx) +{ + ASSERT_ERR(reg_idx <= 9); + return REG_PL_RD(NXMAC_ABS_TIMER_ADDR + reg_idx * 4); +} + +/** + * @brief Sets the ABS_TIMER register to a value. + * The ABS_TIMER register will be written. + * @param[in] reg_idx Index of the register + * @param value - The value to write. + */ +__INLINE void nxmac_abs_timer_set(int reg_idx, uint32_t value) +{ + ASSERT_ERR(reg_idx <= 9); + REG_PL_WR(NXMAC_ABS_TIMER_ADDR + reg_idx * 4, value); +} + +// field definitions +/// ABS_TIMER_VALUE field mask +#define NXMAC_ABS_TIMER_VALUE_MASK ((uint32_t)0xFFFFFFFF) +/// ABS_TIMER_VALUE field LSB position +#define NXMAC_ABS_TIMER_VALUE_LSB 0 +/// ABS_TIMER_VALUE field width +#define NXMAC_ABS_TIMER_VALUE_WIDTH ((uint32_t)0x00000020) + +/// ABS_TIMER_VALUE field reset value +#define NXMAC_ABS_TIMER_VALUE_RST 0x0 + +/** + * @brief Returns the current value of the absTimerValue field in the ABS_TIMER register. + * + * The ABS_TIMER register will be read and the absTimerValue field's value will be returned. + * + * @param[in] reg_idx Index of the register + * @return The current value of the absTimerValue field in the ABS_TIMER register. + */ +__INLINE uint32_t nxmac_abs_timer_value_getf(int reg_idx) +{ + ASSERT_ERR(reg_idx <= 9); + + uint32_t localVal = REG_PL_RD(NXMAC_ABS_TIMER_ADDR + reg_idx * 4); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + + return (localVal >> 0); +} + +/** + * @brief Sets the absTimerValue field of the ABS_TIMER register. + * + * The ABS_TIMER register will be read, modified to contain the new field value, and written. + * + * @param[in] reg_idx Index of the register + * @param[in] abstimervalue - The value to set the field to. + */ +__INLINE void nxmac_abs_timer_value_setf(int reg_idx, uint32_t abstimervalue) +{ + ASSERT_ERR(reg_idx <= 9); + ASSERT_ERR((((uint32_t)abstimervalue << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(NXMAC_ABS_TIMER_ADDR + reg_idx * 4, (uint32_t)abstimervalue << 0); +} + +/// @} + +/** + * @name MAX_RX_LENGTH register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  19:00     maxAllowedLength   0xFFFF
+ * 
+ * + * @{ + */ + +/// Address of the MAX_RX_LENGTH register +#define NXMAC_MAX_RX_LENGTH_ADDR 0xC0000150 +/// Offset of the MAX_RX_LENGTH register from the base address +#define NXMAC_MAX_RX_LENGTH_OFFSET 0x00000150 +/// Index of the MAX_RX_LENGTH register +#define NXMAC_MAX_RX_LENGTH_INDEX 0x00000054 +/// Reset value of the MAX_RX_LENGTH register +#define NXMAC_MAX_RX_LENGTH_RESET 0x0000FFFF + +/** + * @brief Returns the current value of the MAX_RX_LENGTH register. + * The MAX_RX_LENGTH register will be read and its value returned. + * @return The current value of the MAX_RX_LENGTH register. + */ +__INLINE uint32_t nxmac_max_rx_length_get(void) +{ + return REG_PL_RD(NXMAC_MAX_RX_LENGTH_ADDR); +} + +/** + * @brief Sets the MAX_RX_LENGTH register to a value. + * The MAX_RX_LENGTH register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_max_rx_length_set(uint32_t value) +{ + REG_PL_WR(NXMAC_MAX_RX_LENGTH_ADDR, value); +} + +// field definitions +/// MAX_ALLOWED_LENGTH field mask +#define NXMAC_MAX_ALLOWED_LENGTH_MASK ((uint32_t)0x000FFFFF) +/// MAX_ALLOWED_LENGTH field LSB position +#define NXMAC_MAX_ALLOWED_LENGTH_LSB 0 +/// MAX_ALLOWED_LENGTH field width +#define NXMAC_MAX_ALLOWED_LENGTH_WIDTH ((uint32_t)0x00000014) + +/// MAX_ALLOWED_LENGTH field reset value +#define NXMAC_MAX_ALLOWED_LENGTH_RST 0xFFFF + +/** + * @brief Returns the current value of the maxAllowedLength field in the MAX_RX_LENGTH register. + * + * The MAX_RX_LENGTH register will be read and the maxAllowedLength field's value will be returned. + * + * @return The current value of the maxAllowedLength field in the MAX_RX_LENGTH register. + */ +__INLINE uint32_t nxmac_max_allowed_length_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MAX_RX_LENGTH_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x000FFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the maxAllowedLength field of the MAX_RX_LENGTH register. + * + * The MAX_RX_LENGTH register will be read, modified to contain the new field value, and written. + * + * @param[in] maxallowedlength - The value to set the field to. + */ +__INLINE void nxmac_max_allowed_length_setf(uint32_t maxallowedlength) +{ + ASSERT_ERR((((uint32_t)maxallowedlength << 0) & ~((uint32_t)0x000FFFFF)) == 0); + REG_PL_WR(NXMAC_MAX_RX_LENGTH_ADDR, (uint32_t)maxallowedlength << 0); +} + +/// @} + +/** + * @name EDCA_AC_0 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  27:12           txOpLimit0   0x0
+ *  11:08               cwMax0   0xA
+ *  07:04               cwMin0   0x4
+ *  03:00               aifsn0   0x7
+ * 
+ * + * @{ + */ + +/// Address of the EDCA_AC_0 register +#define NXMAC_EDCA_AC_0_ADDR 0xC0000200 +/// Offset of the EDCA_AC_0 register from the base address +#define NXMAC_EDCA_AC_0_OFFSET 0x00000200 +/// Index of the EDCA_AC_0 register +#define NXMAC_EDCA_AC_0_INDEX 0x00000080 +/// Reset value of the EDCA_AC_0 register +#define NXMAC_EDCA_AC_0_RESET 0x00000A47 + +/** + * @brief Returns the current value of the EDCA_AC_0 register. + * The EDCA_AC_0 register will be read and its value returned. + * @return The current value of the EDCA_AC_0 register. + */ +__INLINE uint32_t nxmac_edca_ac_0_get(void) +{ + return REG_PL_RD(NXMAC_EDCA_AC_0_ADDR); +} + +/** + * @brief Sets the EDCA_AC_0 register to a value. + * The EDCA_AC_0 register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_edca_ac_0_set(uint32_t value) +{ + REG_PL_WR(NXMAC_EDCA_AC_0_ADDR, value); +} + +// field definitions +/// TX_OP_LIMIT_0 field mask +#define NXMAC_TX_OP_LIMIT_0_MASK ((uint32_t)0x0FFFF000) +/// TX_OP_LIMIT_0 field LSB position +#define NXMAC_TX_OP_LIMIT_0_LSB 12 +/// TX_OP_LIMIT_0 field width +#define NXMAC_TX_OP_LIMIT_0_WIDTH ((uint32_t)0x00000010) +/// CW_MAX_0 field mask +#define NXMAC_CW_MAX_0_MASK ((uint32_t)0x00000F00) +/// CW_MAX_0 field LSB position +#define NXMAC_CW_MAX_0_LSB 8 +/// CW_MAX_0 field width +#define NXMAC_CW_MAX_0_WIDTH ((uint32_t)0x00000004) +/// CW_MIN_0 field mask +#define NXMAC_CW_MIN_0_MASK ((uint32_t)0x000000F0) +/// CW_MIN_0 field LSB position +#define NXMAC_CW_MIN_0_LSB 4 +/// CW_MIN_0 field width +#define NXMAC_CW_MIN_0_WIDTH ((uint32_t)0x00000004) +/// AIFSN_0 field mask +#define NXMAC_AIFSN_0_MASK ((uint32_t)0x0000000F) +/// AIFSN_0 field LSB position +#define NXMAC_AIFSN_0_LSB 0 +/// AIFSN_0 field width +#define NXMAC_AIFSN_0_WIDTH ((uint32_t)0x00000004) + +/// TX_OP_LIMIT_0 field reset value +#define NXMAC_TX_OP_LIMIT_0_RST 0x0 +/// CW_MAX_0 field reset value +#define NXMAC_CW_MAX_0_RST 0xA +/// CW_MIN_0 field reset value +#define NXMAC_CW_MIN_0_RST 0x4 +/// AIFSN_0 field reset value +#define NXMAC_AIFSN_0_RST 0x7 + +/** + * @brief Constructs a value for the EDCA_AC_0 register given values for its fields + * and writes the value to the register. + * + * @param[in] txoplimit0 - The value to use for the txOpLimit0 field. + * @param[in] cwmax0 - The value to use for the cwMax0 field. + * @param[in] cwmin0 - The value to use for the cwMin0 field. + * @param[in] aifsn0 - The value to use for the aifsn0 field. + */ +__INLINE void nxmac_edca_ac_0_pack(uint16_t txoplimit0, uint8_t cwmax0, uint8_t cwmin0, uint8_t aifsn0) +{ + ASSERT_ERR((((uint32_t)txoplimit0 << 12) & ~((uint32_t)0x0FFFF000)) == 0); + ASSERT_ERR((((uint32_t)cwmax0 << 8) & ~((uint32_t)0x00000F00)) == 0); + ASSERT_ERR((((uint32_t)cwmin0 << 4) & ~((uint32_t)0x000000F0)) == 0); + ASSERT_ERR((((uint32_t)aifsn0 << 0) & ~((uint32_t)0x0000000F)) == 0); + REG_PL_WR(NXMAC_EDCA_AC_0_ADDR, ((uint32_t)txoplimit0 << 12) | ((uint32_t)cwmax0 << 8) | ((uint32_t)cwmin0 << 4) | ((uint32_t)aifsn0 << 0)); +} + +/** + * @brief Unpacks EDCA_AC_0's fields from current value of the EDCA_AC_0 register. + * + * Reads the EDCA_AC_0 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] txoplimit0 - Will be populated with the current value of this field from the register. + * @param[out] cwmax0 - Will be populated with the current value of this field from the register. + * @param[out] cwmin0 - Will be populated with the current value of this field from the register. + * @param[out] aifsn0 - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_edca_ac_0_unpack(uint16_t *txoplimit0, uint8_t *cwmax0, uint8_t *cwmin0, uint8_t *aifsn0) +{ + uint32_t localVal = REG_PL_RD(NXMAC_EDCA_AC_0_ADDR); + + *txoplimit0 = (localVal & ((uint32_t)0x0FFFF000)) >> 12; + *cwmax0 = (localVal & ((uint32_t)0x00000F00)) >> 8; + *cwmin0 = (localVal & ((uint32_t)0x000000F0)) >> 4; + *aifsn0 = (localVal & ((uint32_t)0x0000000F)) >> 0; +} + +/** + * @brief Returns the current value of the txOpLimit0 field in the EDCA_AC_0 register. + * + * The EDCA_AC_0 register will be read and the txOpLimit0 field's value will be returned. + * + * @return The current value of the txOpLimit0 field in the EDCA_AC_0 register. + */ +__INLINE uint16_t nxmac_tx_op_limit_0_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_EDCA_AC_0_ADDR); + return ((localVal & ((uint32_t)0x0FFFF000)) >> 12); +} + +/** + * @brief Sets the txOpLimit0 field of the EDCA_AC_0 register. + * + * The EDCA_AC_0 register will be read, modified to contain the new field value, and written. + * + * @param[in] txoplimit0 - The value to set the field to. + */ +__INLINE void nxmac_tx_op_limit_0_setf(uint16_t txoplimit0) +{ + ASSERT_ERR((((uint32_t)txoplimit0 << 12) & ~((uint32_t)0x0FFFF000)) == 0); + REG_PL_WR(NXMAC_EDCA_AC_0_ADDR, (REG_PL_RD(NXMAC_EDCA_AC_0_ADDR) & ~((uint32_t)0x0FFFF000)) | ((uint32_t)txoplimit0 << 12)); +} + +/** + * @brief Returns the current value of the cwMax0 field in the EDCA_AC_0 register. + * + * The EDCA_AC_0 register will be read and the cwMax0 field's value will be returned. + * + * @return The current value of the cwMax0 field in the EDCA_AC_0 register. + */ +__INLINE uint8_t nxmac_cw_max_0_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_EDCA_AC_0_ADDR); + return ((localVal & ((uint32_t)0x00000F00)) >> 8); +} + +/** + * @brief Sets the cwMax0 field of the EDCA_AC_0 register. + * + * The EDCA_AC_0 register will be read, modified to contain the new field value, and written. + * + * @param[in] cwmax0 - The value to set the field to. + */ +__INLINE void nxmac_cw_max_0_setf(uint8_t cwmax0) +{ + ASSERT_ERR((((uint32_t)cwmax0 << 8) & ~((uint32_t)0x00000F00)) == 0); + REG_PL_WR(NXMAC_EDCA_AC_0_ADDR, (REG_PL_RD(NXMAC_EDCA_AC_0_ADDR) & ~((uint32_t)0x00000F00)) | ((uint32_t)cwmax0 << 8)); +} + +/** + * @brief Returns the current value of the cwMin0 field in the EDCA_AC_0 register. + * + * The EDCA_AC_0 register will be read and the cwMin0 field's value will be returned. + * + * @return The current value of the cwMin0 field in the EDCA_AC_0 register. + */ +__INLINE uint8_t nxmac_cw_min_0_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_EDCA_AC_0_ADDR); + return ((localVal & ((uint32_t)0x000000F0)) >> 4); +} + +/** + * @brief Sets the cwMin0 field of the EDCA_AC_0 register. + * + * The EDCA_AC_0 register will be read, modified to contain the new field value, and written. + * + * @param[in] cwmin0 - The value to set the field to. + */ +__INLINE void nxmac_cw_min_0_setf(uint8_t cwmin0) +{ + ASSERT_ERR((((uint32_t)cwmin0 << 4) & ~((uint32_t)0x000000F0)) == 0); + REG_PL_WR(NXMAC_EDCA_AC_0_ADDR, (REG_PL_RD(NXMAC_EDCA_AC_0_ADDR) & ~((uint32_t)0x000000F0)) | ((uint32_t)cwmin0 << 4)); +} + +/** + * @brief Returns the current value of the aifsn0 field in the EDCA_AC_0 register. + * + * The EDCA_AC_0 register will be read and the aifsn0 field's value will be returned. + * + * @return The current value of the aifsn0 field in the EDCA_AC_0 register. + */ +__INLINE uint8_t nxmac_aifsn_0_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_EDCA_AC_0_ADDR); + return ((localVal & ((uint32_t)0x0000000F)) >> 0); +} + +/** + * @brief Sets the aifsn0 field of the EDCA_AC_0 register. + * + * The EDCA_AC_0 register will be read, modified to contain the new field value, and written. + * + * @param[in] aifsn0 - The value to set the field to. + */ +__INLINE void nxmac_aifsn_0_setf(uint8_t aifsn0) +{ + ASSERT_ERR((((uint32_t)aifsn0 << 0) & ~((uint32_t)0x0000000F)) == 0); + REG_PL_WR(NXMAC_EDCA_AC_0_ADDR, (REG_PL_RD(NXMAC_EDCA_AC_0_ADDR) & ~((uint32_t)0x0000000F)) | ((uint32_t)aifsn0 << 0)); +} + +/// @} + +/** + * @name EDCA_AC_1 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  27:12           txOpLimit1   0x0
+ *  11:08               cwMax1   0xA
+ *  07:04               cwMin1   0x4
+ *  03:00               aifsn1   0x3
+ * 
+ * + * @{ + */ + +/// Address of the EDCA_AC_1 register +#define NXMAC_EDCA_AC_1_ADDR 0xC0000204 +/// Offset of the EDCA_AC_1 register from the base address +#define NXMAC_EDCA_AC_1_OFFSET 0x00000204 +/// Index of the EDCA_AC_1 register +#define NXMAC_EDCA_AC_1_INDEX 0x00000081 +/// Reset value of the EDCA_AC_1 register +#define NXMAC_EDCA_AC_1_RESET 0x00000A43 + +/** + * @brief Returns the current value of the EDCA_AC_1 register. + * The EDCA_AC_1 register will be read and its value returned. + * @return The current value of the EDCA_AC_1 register. + */ +__INLINE uint32_t nxmac_edca_ac_1_get(void) +{ + return REG_PL_RD(NXMAC_EDCA_AC_1_ADDR); +} + +/** + * @brief Sets the EDCA_AC_1 register to a value. + * The EDCA_AC_1 register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_edca_ac_1_set(uint32_t value) +{ + REG_PL_WR(NXMAC_EDCA_AC_1_ADDR, value); +} + +// field definitions +/// TX_OP_LIMIT_1 field mask +#define NXMAC_TX_OP_LIMIT_1_MASK ((uint32_t)0x0FFFF000) +/// TX_OP_LIMIT_1 field LSB position +#define NXMAC_TX_OP_LIMIT_1_LSB 12 +/// TX_OP_LIMIT_1 field width +#define NXMAC_TX_OP_LIMIT_1_WIDTH ((uint32_t)0x00000010) +/// CW_MAX_1 field mask +#define NXMAC_CW_MAX_1_MASK ((uint32_t)0x00000F00) +/// CW_MAX_1 field LSB position +#define NXMAC_CW_MAX_1_LSB 8 +/// CW_MAX_1 field width +#define NXMAC_CW_MAX_1_WIDTH ((uint32_t)0x00000004) +/// CW_MIN_1 field mask +#define NXMAC_CW_MIN_1_MASK ((uint32_t)0x000000F0) +/// CW_MIN_1 field LSB position +#define NXMAC_CW_MIN_1_LSB 4 +/// CW_MIN_1 field width +#define NXMAC_CW_MIN_1_WIDTH ((uint32_t)0x00000004) +/// AIFSN_1 field mask +#define NXMAC_AIFSN_1_MASK ((uint32_t)0x0000000F) +/// AIFSN_1 field LSB position +#define NXMAC_AIFSN_1_LSB 0 +/// AIFSN_1 field width +#define NXMAC_AIFSN_1_WIDTH ((uint32_t)0x00000004) + +/// TX_OP_LIMIT_1 field reset value +#define NXMAC_TX_OP_LIMIT_1_RST 0x0 +/// CW_MAX_1 field reset value +#define NXMAC_CW_MAX_1_RST 0xA +/// CW_MIN_1 field reset value +#define NXMAC_CW_MIN_1_RST 0x4 +/// AIFSN_1 field reset value +#define NXMAC_AIFSN_1_RST 0x3 + +/** + * @brief Constructs a value for the EDCA_AC_1 register given values for its fields + * and writes the value to the register. + * + * @param[in] txoplimit1 - The value to use for the txOpLimit1 field. + * @param[in] cwmax1 - The value to use for the cwMax1 field. + * @param[in] cwmin1 - The value to use for the cwMin1 field. + * @param[in] aifsn1 - The value to use for the aifsn1 field. + */ +__INLINE void nxmac_edca_ac_1_pack(uint16_t txoplimit1, uint8_t cwmax1, uint8_t cwmin1, uint8_t aifsn1) +{ + ASSERT_ERR((((uint32_t)txoplimit1 << 12) & ~((uint32_t)0x0FFFF000)) == 0); + ASSERT_ERR((((uint32_t)cwmax1 << 8) & ~((uint32_t)0x00000F00)) == 0); + ASSERT_ERR((((uint32_t)cwmin1 << 4) & ~((uint32_t)0x000000F0)) == 0); + ASSERT_ERR((((uint32_t)aifsn1 << 0) & ~((uint32_t)0x0000000F)) == 0); + REG_PL_WR(NXMAC_EDCA_AC_1_ADDR, ((uint32_t)txoplimit1 << 12) | ((uint32_t)cwmax1 << 8) | ((uint32_t)cwmin1 << 4) | ((uint32_t)aifsn1 << 0)); +} + +/** + * @brief Unpacks EDCA_AC_1's fields from current value of the EDCA_AC_1 register. + * + * Reads the EDCA_AC_1 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] txoplimit1 - Will be populated with the current value of this field from the register. + * @param[out] cwmax1 - Will be populated with the current value of this field from the register. + * @param[out] cwmin1 - Will be populated with the current value of this field from the register. + * @param[out] aifsn1 - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_edca_ac_1_unpack(uint16_t *txoplimit1, uint8_t *cwmax1, uint8_t *cwmin1, uint8_t *aifsn1) +{ + uint32_t localVal = REG_PL_RD(NXMAC_EDCA_AC_1_ADDR); + + *txoplimit1 = (localVal & ((uint32_t)0x0FFFF000)) >> 12; + *cwmax1 = (localVal & ((uint32_t)0x00000F00)) >> 8; + *cwmin1 = (localVal & ((uint32_t)0x000000F0)) >> 4; + *aifsn1 = (localVal & ((uint32_t)0x0000000F)) >> 0; +} + +/** + * @brief Returns the current value of the txOpLimit1 field in the EDCA_AC_1 register. + * + * The EDCA_AC_1 register will be read and the txOpLimit1 field's value will be returned. + * + * @return The current value of the txOpLimit1 field in the EDCA_AC_1 register. + */ +__INLINE uint16_t nxmac_tx_op_limit_1_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_EDCA_AC_1_ADDR); + return ((localVal & ((uint32_t)0x0FFFF000)) >> 12); +} + +/** + * @brief Sets the txOpLimit1 field of the EDCA_AC_1 register. + * + * The EDCA_AC_1 register will be read, modified to contain the new field value, and written. + * + * @param[in] txoplimit1 - The value to set the field to. + */ +__INLINE void nxmac_tx_op_limit_1_setf(uint16_t txoplimit1) +{ + ASSERT_ERR((((uint32_t)txoplimit1 << 12) & ~((uint32_t)0x0FFFF000)) == 0); + REG_PL_WR(NXMAC_EDCA_AC_1_ADDR, (REG_PL_RD(NXMAC_EDCA_AC_1_ADDR) & ~((uint32_t)0x0FFFF000)) | ((uint32_t)txoplimit1 << 12)); +} + +/** + * @brief Returns the current value of the cwMax1 field in the EDCA_AC_1 register. + * + * The EDCA_AC_1 register will be read and the cwMax1 field's value will be returned. + * + * @return The current value of the cwMax1 field in the EDCA_AC_1 register. + */ +__INLINE uint8_t nxmac_cw_max_1_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_EDCA_AC_1_ADDR); + return ((localVal & ((uint32_t)0x00000F00)) >> 8); +} + +/** + * @brief Sets the cwMax1 field of the EDCA_AC_1 register. + * + * The EDCA_AC_1 register will be read, modified to contain the new field value, and written. + * + * @param[in] cwmax1 - The value to set the field to. + */ +__INLINE void nxmac_cw_max_1_setf(uint8_t cwmax1) +{ + ASSERT_ERR((((uint32_t)cwmax1 << 8) & ~((uint32_t)0x00000F00)) == 0); + REG_PL_WR(NXMAC_EDCA_AC_1_ADDR, (REG_PL_RD(NXMAC_EDCA_AC_1_ADDR) & ~((uint32_t)0x00000F00)) | ((uint32_t)cwmax1 << 8)); +} + +/** + * @brief Returns the current value of the cwMin1 field in the EDCA_AC_1 register. + * + * The EDCA_AC_1 register will be read and the cwMin1 field's value will be returned. + * + * @return The current value of the cwMin1 field in the EDCA_AC_1 register. + */ +__INLINE uint8_t nxmac_cw_min_1_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_EDCA_AC_1_ADDR); + return ((localVal & ((uint32_t)0x000000F0)) >> 4); +} + +/** + * @brief Sets the cwMin1 field of the EDCA_AC_1 register. + * + * The EDCA_AC_1 register will be read, modified to contain the new field value, and written. + * + * @param[in] cwmin1 - The value to set the field to. + */ +__INLINE void nxmac_cw_min_1_setf(uint8_t cwmin1) +{ + ASSERT_ERR((((uint32_t)cwmin1 << 4) & ~((uint32_t)0x000000F0)) == 0); + REG_PL_WR(NXMAC_EDCA_AC_1_ADDR, (REG_PL_RD(NXMAC_EDCA_AC_1_ADDR) & ~((uint32_t)0x000000F0)) | ((uint32_t)cwmin1 << 4)); +} + +/** + * @brief Returns the current value of the aifsn1 field in the EDCA_AC_1 register. + * + * The EDCA_AC_1 register will be read and the aifsn1 field's value will be returned. + * + * @return The current value of the aifsn1 field in the EDCA_AC_1 register. + */ +__INLINE uint8_t nxmac_aifsn_1_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_EDCA_AC_1_ADDR); + return ((localVal & ((uint32_t)0x0000000F)) >> 0); +} + +/** + * @brief Sets the aifsn1 field of the EDCA_AC_1 register. + * + * The EDCA_AC_1 register will be read, modified to contain the new field value, and written. + * + * @param[in] aifsn1 - The value to set the field to. + */ +__INLINE void nxmac_aifsn_1_setf(uint8_t aifsn1) +{ + ASSERT_ERR((((uint32_t)aifsn1 << 0) & ~((uint32_t)0x0000000F)) == 0); + REG_PL_WR(NXMAC_EDCA_AC_1_ADDR, (REG_PL_RD(NXMAC_EDCA_AC_1_ADDR) & ~((uint32_t)0x0000000F)) | ((uint32_t)aifsn1 << 0)); +} + +/// @} + +/** + * @name EDCA_AC_2 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  27:12           txOpLimit2   0x5E
+ *  11:08               cwMax2   0x4
+ *  07:04               cwMin2   0x3
+ *  03:00               aifsn2   0x2
+ * 
+ * + * @{ + */ + +/// Address of the EDCA_AC_2 register +#define NXMAC_EDCA_AC_2_ADDR 0xC0000208 +/// Offset of the EDCA_AC_2 register from the base address +#define NXMAC_EDCA_AC_2_OFFSET 0x00000208 +/// Index of the EDCA_AC_2 register +#define NXMAC_EDCA_AC_2_INDEX 0x00000082 +/// Reset value of the EDCA_AC_2 register +#define NXMAC_EDCA_AC_2_RESET 0x0005E432 + +/** + * @brief Returns the current value of the EDCA_AC_2 register. + * The EDCA_AC_2 register will be read and its value returned. + * @return The current value of the EDCA_AC_2 register. + */ +__INLINE uint32_t nxmac_edca_ac_2_get(void) +{ + return REG_PL_RD(NXMAC_EDCA_AC_2_ADDR); +} + +/** + * @brief Sets the EDCA_AC_2 register to a value. + * The EDCA_AC_2 register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_edca_ac_2_set(uint32_t value) +{ + REG_PL_WR(NXMAC_EDCA_AC_2_ADDR, value); +} + +// field definitions +/// TX_OP_LIMIT_2 field mask +#define NXMAC_TX_OP_LIMIT_2_MASK ((uint32_t)0x0FFFF000) +/// TX_OP_LIMIT_2 field LSB position +#define NXMAC_TX_OP_LIMIT_2_LSB 12 +/// TX_OP_LIMIT_2 field width +#define NXMAC_TX_OP_LIMIT_2_WIDTH ((uint32_t)0x00000010) +/// CW_MAX_2 field mask +#define NXMAC_CW_MAX_2_MASK ((uint32_t)0x00000F00) +/// CW_MAX_2 field LSB position +#define NXMAC_CW_MAX_2_LSB 8 +/// CW_MAX_2 field width +#define NXMAC_CW_MAX_2_WIDTH ((uint32_t)0x00000004) +/// CW_MIN_2 field mask +#define NXMAC_CW_MIN_2_MASK ((uint32_t)0x000000F0) +/// CW_MIN_2 field LSB position +#define NXMAC_CW_MIN_2_LSB 4 +/// CW_MIN_2 field width +#define NXMAC_CW_MIN_2_WIDTH ((uint32_t)0x00000004) +/// AIFSN_2 field mask +#define NXMAC_AIFSN_2_MASK ((uint32_t)0x0000000F) +/// AIFSN_2 field LSB position +#define NXMAC_AIFSN_2_LSB 0 +/// AIFSN_2 field width +#define NXMAC_AIFSN_2_WIDTH ((uint32_t)0x00000004) + +/// TX_OP_LIMIT_2 field reset value +#define NXMAC_TX_OP_LIMIT_2_RST 0x5E +/// CW_MAX_2 field reset value +#define NXMAC_CW_MAX_2_RST 0x4 +/// CW_MIN_2 field reset value +#define NXMAC_CW_MIN_2_RST 0x3 +/// AIFSN_2 field reset value +#define NXMAC_AIFSN_2_RST 0x2 + +/** + * @brief Constructs a value for the EDCA_AC_2 register given values for its fields + * and writes the value to the register. + * + * @param[in] txoplimit2 - The value to use for the txOpLimit2 field. + * @param[in] cwmax2 - The value to use for the cwMax2 field. + * @param[in] cwmin2 - The value to use for the cwMin2 field. + * @param[in] aifsn2 - The value to use for the aifsn2 field. + */ +__INLINE void nxmac_edca_ac_2_pack(uint16_t txoplimit2, uint8_t cwmax2, uint8_t cwmin2, uint8_t aifsn2) +{ + ASSERT_ERR((((uint32_t)txoplimit2 << 12) & ~((uint32_t)0x0FFFF000)) == 0); + ASSERT_ERR((((uint32_t)cwmax2 << 8) & ~((uint32_t)0x00000F00)) == 0); + ASSERT_ERR((((uint32_t)cwmin2 << 4) & ~((uint32_t)0x000000F0)) == 0); + ASSERT_ERR((((uint32_t)aifsn2 << 0) & ~((uint32_t)0x0000000F)) == 0); + REG_PL_WR(NXMAC_EDCA_AC_2_ADDR, ((uint32_t)txoplimit2 << 12) | ((uint32_t)cwmax2 << 8) | ((uint32_t)cwmin2 << 4) | ((uint32_t)aifsn2 << 0)); +} + +/** + * @brief Unpacks EDCA_AC_2's fields from current value of the EDCA_AC_2 register. + * + * Reads the EDCA_AC_2 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] txoplimit2 - Will be populated with the current value of this field from the register. + * @param[out] cwmax2 - Will be populated with the current value of this field from the register. + * @param[out] cwmin2 - Will be populated with the current value of this field from the register. + * @param[out] aifsn2 - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_edca_ac_2_unpack(uint16_t *txoplimit2, uint8_t *cwmax2, uint8_t *cwmin2, uint8_t *aifsn2) +{ + uint32_t localVal = REG_PL_RD(NXMAC_EDCA_AC_2_ADDR); + + *txoplimit2 = (localVal & ((uint32_t)0x0FFFF000)) >> 12; + *cwmax2 = (localVal & ((uint32_t)0x00000F00)) >> 8; + *cwmin2 = (localVal & ((uint32_t)0x000000F0)) >> 4; + *aifsn2 = (localVal & ((uint32_t)0x0000000F)) >> 0; +} + +/** + * @brief Returns the current value of the txOpLimit2 field in the EDCA_AC_2 register. + * + * The EDCA_AC_2 register will be read and the txOpLimit2 field's value will be returned. + * + * @return The current value of the txOpLimit2 field in the EDCA_AC_2 register. + */ +__INLINE uint16_t nxmac_tx_op_limit_2_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_EDCA_AC_2_ADDR); + return ((localVal & ((uint32_t)0x0FFFF000)) >> 12); +} + +/** + * @brief Sets the txOpLimit2 field of the EDCA_AC_2 register. + * + * The EDCA_AC_2 register will be read, modified to contain the new field value, and written. + * + * @param[in] txoplimit2 - The value to set the field to. + */ +__INLINE void nxmac_tx_op_limit_2_setf(uint16_t txoplimit2) +{ + ASSERT_ERR((((uint32_t)txoplimit2 << 12) & ~((uint32_t)0x0FFFF000)) == 0); + REG_PL_WR(NXMAC_EDCA_AC_2_ADDR, (REG_PL_RD(NXMAC_EDCA_AC_2_ADDR) & ~((uint32_t)0x0FFFF000)) | ((uint32_t)txoplimit2 << 12)); +} + +/** + * @brief Returns the current value of the cwMax2 field in the EDCA_AC_2 register. + * + * The EDCA_AC_2 register will be read and the cwMax2 field's value will be returned. + * + * @return The current value of the cwMax2 field in the EDCA_AC_2 register. + */ +__INLINE uint8_t nxmac_cw_max_2_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_EDCA_AC_2_ADDR); + return ((localVal & ((uint32_t)0x00000F00)) >> 8); +} + +/** + * @brief Sets the cwMax2 field of the EDCA_AC_2 register. + * + * The EDCA_AC_2 register will be read, modified to contain the new field value, and written. + * + * @param[in] cwmax2 - The value to set the field to. + */ +__INLINE void nxmac_cw_max_2_setf(uint8_t cwmax2) +{ + ASSERT_ERR((((uint32_t)cwmax2 << 8) & ~((uint32_t)0x00000F00)) == 0); + REG_PL_WR(NXMAC_EDCA_AC_2_ADDR, (REG_PL_RD(NXMAC_EDCA_AC_2_ADDR) & ~((uint32_t)0x00000F00)) | ((uint32_t)cwmax2 << 8)); +} + +/** + * @brief Returns the current value of the cwMin2 field in the EDCA_AC_2 register. + * + * The EDCA_AC_2 register will be read and the cwMin2 field's value will be returned. + * + * @return The current value of the cwMin2 field in the EDCA_AC_2 register. + */ +__INLINE uint8_t nxmac_cw_min_2_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_EDCA_AC_2_ADDR); + return ((localVal & ((uint32_t)0x000000F0)) >> 4); +} + +/** + * @brief Sets the cwMin2 field of the EDCA_AC_2 register. + * + * The EDCA_AC_2 register will be read, modified to contain the new field value, and written. + * + * @param[in] cwmin2 - The value to set the field to. + */ +__INLINE void nxmac_cw_min_2_setf(uint8_t cwmin2) +{ + ASSERT_ERR((((uint32_t)cwmin2 << 4) & ~((uint32_t)0x000000F0)) == 0); + REG_PL_WR(NXMAC_EDCA_AC_2_ADDR, (REG_PL_RD(NXMAC_EDCA_AC_2_ADDR) & ~((uint32_t)0x000000F0)) | ((uint32_t)cwmin2 << 4)); +} + +/** + * @brief Returns the current value of the aifsn2 field in the EDCA_AC_2 register. + * + * The EDCA_AC_2 register will be read and the aifsn2 field's value will be returned. + * + * @return The current value of the aifsn2 field in the EDCA_AC_2 register. + */ +__INLINE uint8_t nxmac_aifsn_2_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_EDCA_AC_2_ADDR); + return ((localVal & ((uint32_t)0x0000000F)) >> 0); +} + +/** + * @brief Sets the aifsn2 field of the EDCA_AC_2 register. + * + * The EDCA_AC_2 register will be read, modified to contain the new field value, and written. + * + * @param[in] aifsn2 - The value to set the field to. + */ +__INLINE void nxmac_aifsn_2_setf(uint8_t aifsn2) +{ + ASSERT_ERR((((uint32_t)aifsn2 << 0) & ~((uint32_t)0x0000000F)) == 0); + REG_PL_WR(NXMAC_EDCA_AC_2_ADDR, (REG_PL_RD(NXMAC_EDCA_AC_2_ADDR) & ~((uint32_t)0x0000000F)) | ((uint32_t)aifsn2 << 0)); +} + +/// @} + +/** + * @name EDCA_AC_3 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  27:12           txOpLimit3   0x2F
+ *  11:08               cwMax3   0x3
+ *  07:04               cwMin3   0x2
+ *  03:00               aifsn3   0x2
+ * 
+ * + * @{ + */ + +/// Address of the EDCA_AC_3 register +#define NXMAC_EDCA_AC_3_ADDR 0xC000020C +/// Offset of the EDCA_AC_3 register from the base address +#define NXMAC_EDCA_AC_3_OFFSET 0x0000020C +/// Index of the EDCA_AC_3 register +#define NXMAC_EDCA_AC_3_INDEX 0x00000083 +/// Reset value of the EDCA_AC_3 register +#define NXMAC_EDCA_AC_3_RESET 0x0002F322 + +/** + * @brief Returns the current value of the EDCA_AC_3 register. + * The EDCA_AC_3 register will be read and its value returned. + * @return The current value of the EDCA_AC_3 register. + */ +__INLINE uint32_t nxmac_edca_ac_3_get(void) +{ + return REG_PL_RD(NXMAC_EDCA_AC_3_ADDR); +} + +/** + * @brief Sets the EDCA_AC_3 register to a value. + * The EDCA_AC_3 register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_edca_ac_3_set(uint32_t value) +{ + REG_PL_WR(NXMAC_EDCA_AC_3_ADDR, value); +} + +// field definitions +/// TX_OP_LIMIT_3 field mask +#define NXMAC_TX_OP_LIMIT_3_MASK ((uint32_t)0x0FFFF000) +/// TX_OP_LIMIT_3 field LSB position +#define NXMAC_TX_OP_LIMIT_3_LSB 12 +/// TX_OP_LIMIT_3 field width +#define NXMAC_TX_OP_LIMIT_3_WIDTH ((uint32_t)0x00000010) +/// CW_MAX_3 field mask +#define NXMAC_CW_MAX_3_MASK ((uint32_t)0x00000F00) +/// CW_MAX_3 field LSB position +#define NXMAC_CW_MAX_3_LSB 8 +/// CW_MAX_3 field width +#define NXMAC_CW_MAX_3_WIDTH ((uint32_t)0x00000004) +/// CW_MIN_3 field mask +#define NXMAC_CW_MIN_3_MASK ((uint32_t)0x000000F0) +/// CW_MIN_3 field LSB position +#define NXMAC_CW_MIN_3_LSB 4 +/// CW_MIN_3 field width +#define NXMAC_CW_MIN_3_WIDTH ((uint32_t)0x00000004) +/// AIFSN_3 field mask +#define NXMAC_AIFSN_3_MASK ((uint32_t)0x0000000F) +/// AIFSN_3 field LSB position +#define NXMAC_AIFSN_3_LSB 0 +/// AIFSN_3 field width +#define NXMAC_AIFSN_3_WIDTH ((uint32_t)0x00000004) + +/// TX_OP_LIMIT_3 field reset value +#define NXMAC_TX_OP_LIMIT_3_RST 0x2F +/// CW_MAX_3 field reset value +#define NXMAC_CW_MAX_3_RST 0x3 +/// CW_MIN_3 field reset value +#define NXMAC_CW_MIN_3_RST 0x2 +/// AIFSN_3 field reset value +#define NXMAC_AIFSN_3_RST 0x2 + +/** + * @brief Constructs a value for the EDCA_AC_3 register given values for its fields + * and writes the value to the register. + * + * @param[in] txoplimit3 - The value to use for the txOpLimit3 field. + * @param[in] cwmax3 - The value to use for the cwMax3 field. + * @param[in] cwmin3 - The value to use for the cwMin3 field. + * @param[in] aifsn3 - The value to use for the aifsn3 field. + */ +__INLINE void nxmac_edca_ac_3_pack(uint16_t txoplimit3, uint8_t cwmax3, uint8_t cwmin3, uint8_t aifsn3) +{ + ASSERT_ERR((((uint32_t)txoplimit3 << 12) & ~((uint32_t)0x0FFFF000)) == 0); + ASSERT_ERR((((uint32_t)cwmax3 << 8) & ~((uint32_t)0x00000F00)) == 0); + ASSERT_ERR((((uint32_t)cwmin3 << 4) & ~((uint32_t)0x000000F0)) == 0); + ASSERT_ERR((((uint32_t)aifsn3 << 0) & ~((uint32_t)0x0000000F)) == 0); + REG_PL_WR(NXMAC_EDCA_AC_3_ADDR, ((uint32_t)txoplimit3 << 12) | ((uint32_t)cwmax3 << 8) | ((uint32_t)cwmin3 << 4) | ((uint32_t)aifsn3 << 0)); +} + +/** + * @brief Unpacks EDCA_AC_3's fields from current value of the EDCA_AC_3 register. + * + * Reads the EDCA_AC_3 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] txoplimit3 - Will be populated with the current value of this field from the register. + * @param[out] cwmax3 - Will be populated with the current value of this field from the register. + * @param[out] cwmin3 - Will be populated with the current value of this field from the register. + * @param[out] aifsn3 - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_edca_ac_3_unpack(uint16_t *txoplimit3, uint8_t *cwmax3, uint8_t *cwmin3, uint8_t *aifsn3) +{ + uint32_t localVal = REG_PL_RD(NXMAC_EDCA_AC_3_ADDR); + + *txoplimit3 = (localVal & ((uint32_t)0x0FFFF000)) >> 12; + *cwmax3 = (localVal & ((uint32_t)0x00000F00)) >> 8; + *cwmin3 = (localVal & ((uint32_t)0x000000F0)) >> 4; + *aifsn3 = (localVal & ((uint32_t)0x0000000F)) >> 0; +} + +/** + * @brief Returns the current value of the txOpLimit3 field in the EDCA_AC_3 register. + * + * The EDCA_AC_3 register will be read and the txOpLimit3 field's value will be returned. + * + * @return The current value of the txOpLimit3 field in the EDCA_AC_3 register. + */ +__INLINE uint16_t nxmac_tx_op_limit_3_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_EDCA_AC_3_ADDR); + return ((localVal & ((uint32_t)0x0FFFF000)) >> 12); +} + +/** + * @brief Sets the txOpLimit3 field of the EDCA_AC_3 register. + * + * The EDCA_AC_3 register will be read, modified to contain the new field value, and written. + * + * @param[in] txoplimit3 - The value to set the field to. + */ +__INLINE void nxmac_tx_op_limit_3_setf(uint16_t txoplimit3) +{ + ASSERT_ERR((((uint32_t)txoplimit3 << 12) & ~((uint32_t)0x0FFFF000)) == 0); + REG_PL_WR(NXMAC_EDCA_AC_3_ADDR, (REG_PL_RD(NXMAC_EDCA_AC_3_ADDR) & ~((uint32_t)0x0FFFF000)) | ((uint32_t)txoplimit3 << 12)); +} + +/** + * @brief Returns the current value of the cwMax3 field in the EDCA_AC_3 register. + * + * The EDCA_AC_3 register will be read and the cwMax3 field's value will be returned. + * + * @return The current value of the cwMax3 field in the EDCA_AC_3 register. + */ +__INLINE uint8_t nxmac_cw_max_3_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_EDCA_AC_3_ADDR); + return ((localVal & ((uint32_t)0x00000F00)) >> 8); +} + +/** + * @brief Sets the cwMax3 field of the EDCA_AC_3 register. + * + * The EDCA_AC_3 register will be read, modified to contain the new field value, and written. + * + * @param[in] cwmax3 - The value to set the field to. + */ +__INLINE void nxmac_cw_max_3_setf(uint8_t cwmax3) +{ + ASSERT_ERR((((uint32_t)cwmax3 << 8) & ~((uint32_t)0x00000F00)) == 0); + REG_PL_WR(NXMAC_EDCA_AC_3_ADDR, (REG_PL_RD(NXMAC_EDCA_AC_3_ADDR) & ~((uint32_t)0x00000F00)) | ((uint32_t)cwmax3 << 8)); +} + +/** + * @brief Returns the current value of the cwMin3 field in the EDCA_AC_3 register. + * + * The EDCA_AC_3 register will be read and the cwMin3 field's value will be returned. + * + * @return The current value of the cwMin3 field in the EDCA_AC_3 register. + */ +__INLINE uint8_t nxmac_cw_min_3_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_EDCA_AC_3_ADDR); + return ((localVal & ((uint32_t)0x000000F0)) >> 4); +} + +/** + * @brief Sets the cwMin3 field of the EDCA_AC_3 register. + * + * The EDCA_AC_3 register will be read, modified to contain the new field value, and written. + * + * @param[in] cwmin3 - The value to set the field to. + */ +__INLINE void nxmac_cw_min_3_setf(uint8_t cwmin3) +{ + ASSERT_ERR((((uint32_t)cwmin3 << 4) & ~((uint32_t)0x000000F0)) == 0); + REG_PL_WR(NXMAC_EDCA_AC_3_ADDR, (REG_PL_RD(NXMAC_EDCA_AC_3_ADDR) & ~((uint32_t)0x000000F0)) | ((uint32_t)cwmin3 << 4)); +} + +/** + * @brief Returns the current value of the aifsn3 field in the EDCA_AC_3 register. + * + * The EDCA_AC_3 register will be read and the aifsn3 field's value will be returned. + * + * @return The current value of the aifsn3 field in the EDCA_AC_3 register. + */ +__INLINE uint8_t nxmac_aifsn_3_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_EDCA_AC_3_ADDR); + return ((localVal & ((uint32_t)0x0000000F)) >> 0); +} + +/** + * @brief Sets the aifsn3 field of the EDCA_AC_3 register. + * + * The EDCA_AC_3 register will be read, modified to contain the new field value, and written. + * + * @param[in] aifsn3 - The value to set the field to. + */ +__INLINE void nxmac_aifsn_3_setf(uint8_t aifsn3) +{ + ASSERT_ERR((((uint32_t)aifsn3 << 0) & ~((uint32_t)0x0000000F)) == 0); + REG_PL_WR(NXMAC_EDCA_AC_3_ADDR, (REG_PL_RD(NXMAC_EDCA_AC_3_ADDR) & ~((uint32_t)0x0000000F)) | ((uint32_t)aifsn3 << 0)); +} + +/// @} + +/** + * @name EDCA_CCA_BUSY register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00           ccaBusyDur   0x0
+ * 
+ * + * @{ + */ + +/// Address of the EDCA_CCA_BUSY register +#define NXMAC_EDCA_CCA_BUSY_ADDR 0xC0000220 +/// Offset of the EDCA_CCA_BUSY register from the base address +#define NXMAC_EDCA_CCA_BUSY_OFFSET 0x00000220 +/// Index of the EDCA_CCA_BUSY register +#define NXMAC_EDCA_CCA_BUSY_INDEX 0x00000088 +/// Reset value of the EDCA_CCA_BUSY register +#define NXMAC_EDCA_CCA_BUSY_RESET 0x00000000 + +/** + * @brief Returns the current value of the EDCA_CCA_BUSY register. + * The EDCA_CCA_BUSY register will be read and its value returned. + * @return The current value of the EDCA_CCA_BUSY register. + */ +__INLINE uint32_t nxmac_edca_cca_busy_get(void) +{ + return REG_PL_RD(NXMAC_EDCA_CCA_BUSY_ADDR); +} + +/** + * @brief Sets the EDCA_CCA_BUSY register to a value. + * The EDCA_CCA_BUSY register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_edca_cca_busy_set(uint32_t value) +{ + REG_PL_WR(NXMAC_EDCA_CCA_BUSY_ADDR, value); +} + +// field definitions +/// CCA_BUSY_DUR field mask +#define NXMAC_CCA_BUSY_DUR_MASK ((uint32_t)0xFFFFFFFF) +/// CCA_BUSY_DUR field LSB position +#define NXMAC_CCA_BUSY_DUR_LSB 0 +/// CCA_BUSY_DUR field width +#define NXMAC_CCA_BUSY_DUR_WIDTH ((uint32_t)0x00000020) + +/// CCA_BUSY_DUR field reset value +#define NXMAC_CCA_BUSY_DUR_RST 0x0 + +/** + * @brief Returns the current value of the ccaBusyDur field in the EDCA_CCA_BUSY register. + * + * The EDCA_CCA_BUSY register will be read and the ccaBusyDur field's value will be returned. + * + * @return The current value of the ccaBusyDur field in the EDCA_CCA_BUSY register. + */ +__INLINE uint32_t nxmac_cca_busy_dur_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_EDCA_CCA_BUSY_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the ccaBusyDur field of the EDCA_CCA_BUSY register. + * + * The EDCA_CCA_BUSY register will be read, modified to contain the new field value, and written. + * + * @param[in] ccabusydur - The value to set the field to. + */ +__INLINE void nxmac_cca_busy_dur_setf(uint32_t ccabusydur) +{ + ASSERT_ERR((((uint32_t)ccabusydur << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(NXMAC_EDCA_CCA_BUSY_ADDR, (uint32_t)ccabusydur << 0); +} + +/// @} + +/** + * @name EDCA_CNTRL register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     05         keepTXOPOpen   0
+ *     04    remTXOPInDurField   0
+ *     01            sendCFEnd   0
+ *     00         sendCFEndNow   0
+ * 
+ * + * @{ + */ + +/// Address of the EDCA_CNTRL register +#define NXMAC_EDCA_CNTRL_ADDR 0xC0000224 +/// Offset of the EDCA_CNTRL register from the base address +#define NXMAC_EDCA_CNTRL_OFFSET 0x00000224 +/// Index of the EDCA_CNTRL register +#define NXMAC_EDCA_CNTRL_INDEX 0x00000089 +/// Reset value of the EDCA_CNTRL register +#define NXMAC_EDCA_CNTRL_RESET 0x00000000 + +/** + * @brief Returns the current value of the EDCA_CNTRL register. + * The EDCA_CNTRL register will be read and its value returned. + * @return The current value of the EDCA_CNTRL register. + */ +__INLINE uint32_t nxmac_edca_cntrl_get(void) +{ + return REG_PL_RD(NXMAC_EDCA_CNTRL_ADDR); +} + +/** + * @brief Sets the EDCA_CNTRL register to a value. + * The EDCA_CNTRL register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_edca_cntrl_set(uint32_t value) +{ + REG_PL_WR(NXMAC_EDCA_CNTRL_ADDR, value); +} + +// field definitions +/// KEEP_TXOP_OPEN field bit +#define NXMAC_KEEP_TXOP_OPEN_BIT ((uint32_t)0x00000020) +/// KEEP_TXOP_OPEN field position +#define NXMAC_KEEP_TXOP_OPEN_POS 5 +/// REM_TXOP_IN_DUR_FIELD field bit +#define NXMAC_REM_TXOP_IN_DUR_FIELD_BIT ((uint32_t)0x00000010) +/// REM_TXOP_IN_DUR_FIELD field position +#define NXMAC_REM_TXOP_IN_DUR_FIELD_POS 4 +/// SEND_CF_END field bit +#define NXMAC_SEND_CF_END_BIT ((uint32_t)0x00000002) +/// SEND_CF_END field position +#define NXMAC_SEND_CF_END_POS 1 +/// SEND_CF_END_NOW field bit +#define NXMAC_SEND_CF_END_NOW_BIT ((uint32_t)0x00000001) +/// SEND_CF_END_NOW field position +#define NXMAC_SEND_CF_END_NOW_POS 0 + +/// KEEP_TXOP_OPEN field reset value +#define NXMAC_KEEP_TXOP_OPEN_RST 0x0 +/// REM_TXOP_IN_DUR_FIELD field reset value +#define NXMAC_REM_TXOP_IN_DUR_FIELD_RST 0x0 +/// SEND_CF_END field reset value +#define NXMAC_SEND_CF_END_RST 0x0 +/// SEND_CF_END_NOW field reset value +#define NXMAC_SEND_CF_END_NOW_RST 0x0 + +/** + * @brief Constructs a value for the EDCA_CNTRL register given values for its fields + * and writes the value to the register. + * + * @param[in] keeptxopopen - The value to use for the keepTXOPOpen field. + * @param[in] remtxopindurfield - The value to use for the remTXOPInDurField field. + * @param[in] sendcfend - The value to use for the sendCFEnd field. + * @param[in] sendcfendnow - The value to use for the sendCFEndNow field. + */ +__INLINE void nxmac_edca_cntrl_pack(uint8_t keeptxopopen, uint8_t remtxopindurfield, uint8_t sendcfend, uint8_t sendcfendnow) +{ + ASSERT_ERR((((uint32_t)keeptxopopen << 5) & ~((uint32_t)0x00000020)) == 0); + ASSERT_ERR((((uint32_t)remtxopindurfield << 4) & ~((uint32_t)0x00000010)) == 0); + ASSERT_ERR((((uint32_t)sendcfend << 1) & ~((uint32_t)0x00000002)) == 0); + ASSERT_ERR((((uint32_t)sendcfendnow << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_EDCA_CNTRL_ADDR, ((uint32_t)keeptxopopen << 5) | ((uint32_t)remtxopindurfield << 4) | ((uint32_t)sendcfend << 1) | ((uint32_t)sendcfendnow << 0)); +} + +/** + * @brief Unpacks EDCA_CNTRL's fields from current value of the EDCA_CNTRL register. + * + * Reads the EDCA_CNTRL register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] keeptxopopen - Will be populated with the current value of this field from the register. + * @param[out] remtxopindurfield - Will be populated with the current value of this field from the register. + * @param[out] sendcfend - Will be populated with the current value of this field from the register. + * @param[out] sendcfendnow - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_edca_cntrl_unpack(uint8_t *keeptxopopen, uint8_t *remtxopindurfield, uint8_t *sendcfend, uint8_t *sendcfendnow) +{ + uint32_t localVal = REG_PL_RD(NXMAC_EDCA_CNTRL_ADDR); + + *keeptxopopen = (localVal & ((uint32_t)0x00000020)) >> 5; + *remtxopindurfield = (localVal & ((uint32_t)0x00000010)) >> 4; + *sendcfend = (localVal & ((uint32_t)0x00000002)) >> 1; + *sendcfendnow = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +/** + * @brief Returns the current value of the keepTXOPOpen field in the EDCA_CNTRL register. + * + * The EDCA_CNTRL register will be read and the keepTXOPOpen field's value will be returned. + * + * @return The current value of the keepTXOPOpen field in the EDCA_CNTRL register. + */ +__INLINE uint8_t nxmac_keep_txop_open_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_EDCA_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +/** + * @brief Sets the keepTXOPOpen field of the EDCA_CNTRL register. + * + * The EDCA_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] keeptxopopen - The value to set the field to. + */ +__INLINE void nxmac_keep_txop_open_setf(uint8_t keeptxopopen) +{ + ASSERT_ERR((((uint32_t)keeptxopopen << 5) & ~((uint32_t)0x00000020)) == 0); + REG_PL_WR(NXMAC_EDCA_CNTRL_ADDR, (REG_PL_RD(NXMAC_EDCA_CNTRL_ADDR) & ~((uint32_t)0x00000020)) | ((uint32_t)keeptxopopen << 5)); +} + +/** + * @brief Returns the current value of the remTXOPInDurField field in the EDCA_CNTRL register. + * + * The EDCA_CNTRL register will be read and the remTXOPInDurField field's value will be returned. + * + * @return The current value of the remTXOPInDurField field in the EDCA_CNTRL register. + */ +__INLINE uint8_t nxmac_rem_txop_in_dur_field_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_EDCA_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +/** + * @brief Sets the remTXOPInDurField field of the EDCA_CNTRL register. + * + * The EDCA_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] remtxopindurfield - The value to set the field to. + */ +__INLINE void nxmac_rem_txop_in_dur_field_setf(uint8_t remtxopindurfield) +{ + ASSERT_ERR((((uint32_t)remtxopindurfield << 4) & ~((uint32_t)0x00000010)) == 0); + REG_PL_WR(NXMAC_EDCA_CNTRL_ADDR, (REG_PL_RD(NXMAC_EDCA_CNTRL_ADDR) & ~((uint32_t)0x00000010)) | ((uint32_t)remtxopindurfield << 4)); +} + +/** + * @brief Returns the current value of the sendCFEnd field in the EDCA_CNTRL register. + * + * The EDCA_CNTRL register will be read and the sendCFEnd field's value will be returned. + * + * @return The current value of the sendCFEnd field in the EDCA_CNTRL register. + */ +__INLINE uint8_t nxmac_send_cf_end_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_EDCA_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +/** + * @brief Sets the sendCFEnd field of the EDCA_CNTRL register. + * + * The EDCA_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] sendcfend - The value to set the field to. + */ +__INLINE void nxmac_send_cf_end_setf(uint8_t sendcfend) +{ + ASSERT_ERR((((uint32_t)sendcfend << 1) & ~((uint32_t)0x00000002)) == 0); + REG_PL_WR(NXMAC_EDCA_CNTRL_ADDR, (REG_PL_RD(NXMAC_EDCA_CNTRL_ADDR) & ~((uint32_t)0x00000002)) | ((uint32_t)sendcfend << 1)); +} + +/** + * @brief Returns the current value of the sendCFEndNow field in the EDCA_CNTRL register. + * + * The EDCA_CNTRL register will be read and the sendCFEndNow field's value will be returned. + * + * @return The current value of the sendCFEndNow field in the EDCA_CNTRL register. + */ +__INLINE uint8_t nxmac_send_cf_end_now_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_EDCA_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/** + * @brief Sets the sendCFEndNow field of the EDCA_CNTRL register. + * + * The EDCA_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] sendcfendnow - The value to set the field to. + */ +__INLINE void nxmac_send_cf_end_now_setf(uint8_t sendcfendnow) +{ + ASSERT_ERR((((uint32_t)sendcfendnow << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_EDCA_CNTRL_ADDR, (REG_PL_RD(NXMAC_EDCA_CNTRL_ADDR) & ~((uint32_t)0x00000001)) | ((uint32_t)sendcfendnow << 0)); +} + +/// @} + +/** + * @name QUIET_ELEMENT_1A register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:16       quietDuration1   0x0
+ *  15:08         quietPeriod1   0x0
+ *  07:00          quietCount1   0x0
+ * 
+ * + * @{ + */ + +/// Address of the QUIET_ELEMENT_1A register +#define NXMAC_QUIET_ELEMENT_1A_ADDR 0xC0000280 +/// Offset of the QUIET_ELEMENT_1A register from the base address +#define NXMAC_QUIET_ELEMENT_1A_OFFSET 0x00000280 +/// Index of the QUIET_ELEMENT_1A register +#define NXMAC_QUIET_ELEMENT_1A_INDEX 0x000000A0 +/// Reset value of the QUIET_ELEMENT_1A register +#define NXMAC_QUIET_ELEMENT_1A_RESET 0x00000000 + +/** + * @brief Returns the current value of the QUIET_ELEMENT_1A register. + * The QUIET_ELEMENT_1A register will be read and its value returned. + * @return The current value of the QUIET_ELEMENT_1A register. + */ +__INLINE uint32_t nxmac_quiet_element_1a_get(void) +{ + return REG_PL_RD(NXMAC_QUIET_ELEMENT_1A_ADDR); +} + +/** + * @brief Sets the QUIET_ELEMENT_1A register to a value. + * The QUIET_ELEMENT_1A register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_quiet_element_1a_set(uint32_t value) +{ + REG_PL_WR(NXMAC_QUIET_ELEMENT_1A_ADDR, value); +} + +// field definitions +/// QUIET_DURATION_1 field mask +#define NXMAC_QUIET_DURATION_1_MASK ((uint32_t)0xFFFF0000) +/// QUIET_DURATION_1 field LSB position +#define NXMAC_QUIET_DURATION_1_LSB 16 +/// QUIET_DURATION_1 field width +#define NXMAC_QUIET_DURATION_1_WIDTH ((uint32_t)0x00000010) +/// QUIET_PERIOD_1 field mask +#define NXMAC_QUIET_PERIOD_1_MASK ((uint32_t)0x0000FF00) +/// QUIET_PERIOD_1 field LSB position +#define NXMAC_QUIET_PERIOD_1_LSB 8 +/// QUIET_PERIOD_1 field width +#define NXMAC_QUIET_PERIOD_1_WIDTH ((uint32_t)0x00000008) +/// QUIET_COUNT_1 field mask +#define NXMAC_QUIET_COUNT_1_MASK ((uint32_t)0x000000FF) +/// QUIET_COUNT_1 field LSB position +#define NXMAC_QUIET_COUNT_1_LSB 0 +/// QUIET_COUNT_1 field width +#define NXMAC_QUIET_COUNT_1_WIDTH ((uint32_t)0x00000008) + +/// QUIET_DURATION_1 field reset value +#define NXMAC_QUIET_DURATION_1_RST 0x0 +/// QUIET_PERIOD_1 field reset value +#define NXMAC_QUIET_PERIOD_1_RST 0x0 +/// QUIET_COUNT_1 field reset value +#define NXMAC_QUIET_COUNT_1_RST 0x0 + +/** + * @brief Constructs a value for the QUIET_ELEMENT_1A register given values for its fields + * and writes the value to the register. + * + * @param[in] quietduration1 - The value to use for the quietDuration1 field. + * @param[in] quietperiod1 - The value to use for the quietPeriod1 field. + * @param[in] quietcount1 - The value to use for the quietCount1 field. + */ +__INLINE void nxmac_quiet_element_1a_pack(uint16_t quietduration1, uint8_t quietperiod1, uint8_t quietcount1) +{ + ASSERT_ERR((((uint32_t)quietduration1 << 16) & ~((uint32_t)0xFFFF0000)) == 0); + ASSERT_ERR((((uint32_t)quietperiod1 << 8) & ~((uint32_t)0x0000FF00)) == 0); + ASSERT_ERR((((uint32_t)quietcount1 << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(NXMAC_QUIET_ELEMENT_1A_ADDR, ((uint32_t)quietduration1 << 16) | ((uint32_t)quietperiod1 << 8) | ((uint32_t)quietcount1 << 0)); +} + +/** + * @brief Unpacks QUIET_ELEMENT_1A's fields from current value of the QUIET_ELEMENT_1A register. + * + * Reads the QUIET_ELEMENT_1A register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] quietduration1 - Will be populated with the current value of this field from the register. + * @param[out] quietperiod1 - Will be populated with the current value of this field from the register. + * @param[out] quietcount1 - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_quiet_element_1a_unpack(uint16_t *quietduration1, uint8_t *quietperiod1, uint8_t *quietcount1) +{ + uint32_t localVal = REG_PL_RD(NXMAC_QUIET_ELEMENT_1A_ADDR); + + *quietduration1 = (localVal & ((uint32_t)0xFFFF0000)) >> 16; + *quietperiod1 = (localVal & ((uint32_t)0x0000FF00)) >> 8; + *quietcount1 = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +/** + * @brief Returns the current value of the quietDuration1 field in the QUIET_ELEMENT_1A register. + * + * The QUIET_ELEMENT_1A register will be read and the quietDuration1 field's value will be returned. + * + * @return The current value of the quietDuration1 field in the QUIET_ELEMENT_1A register. + */ +__INLINE uint16_t nxmac_quiet_duration_1_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_QUIET_ELEMENT_1A_ADDR); + return ((localVal & ((uint32_t)0xFFFF0000)) >> 16); +} + +/** + * @brief Sets the quietDuration1 field of the QUIET_ELEMENT_1A register. + * + * The QUIET_ELEMENT_1A register will be read, modified to contain the new field value, and written. + * + * @param[in] quietduration1 - The value to set the field to. + */ +__INLINE void nxmac_quiet_duration_1_setf(uint16_t quietduration1) +{ + ASSERT_ERR((((uint32_t)quietduration1 << 16) & ~((uint32_t)0xFFFF0000)) == 0); + REG_PL_WR(NXMAC_QUIET_ELEMENT_1A_ADDR, (REG_PL_RD(NXMAC_QUIET_ELEMENT_1A_ADDR) & ~((uint32_t)0xFFFF0000)) | ((uint32_t)quietduration1 << 16)); +} + +/** + * @brief Returns the current value of the quietPeriod1 field in the QUIET_ELEMENT_1A register. + * + * The QUIET_ELEMENT_1A register will be read and the quietPeriod1 field's value will be returned. + * + * @return The current value of the quietPeriod1 field in the QUIET_ELEMENT_1A register. + */ +__INLINE uint8_t nxmac_quiet_period_1_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_QUIET_ELEMENT_1A_ADDR); + return ((localVal & ((uint32_t)0x0000FF00)) >> 8); +} + +/** + * @brief Sets the quietPeriod1 field of the QUIET_ELEMENT_1A register. + * + * The QUIET_ELEMENT_1A register will be read, modified to contain the new field value, and written. + * + * @param[in] quietperiod1 - The value to set the field to. + */ +__INLINE void nxmac_quiet_period_1_setf(uint8_t quietperiod1) +{ + ASSERT_ERR((((uint32_t)quietperiod1 << 8) & ~((uint32_t)0x0000FF00)) == 0); + REG_PL_WR(NXMAC_QUIET_ELEMENT_1A_ADDR, (REG_PL_RD(NXMAC_QUIET_ELEMENT_1A_ADDR) & ~((uint32_t)0x0000FF00)) | ((uint32_t)quietperiod1 << 8)); +} + +/** + * @brief Returns the current value of the quietCount1 field in the QUIET_ELEMENT_1A register. + * + * The QUIET_ELEMENT_1A register will be read and the quietCount1 field's value will be returned. + * + * @return The current value of the quietCount1 field in the QUIET_ELEMENT_1A register. + */ +__INLINE uint8_t nxmac_quiet_count_1_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_QUIET_ELEMENT_1A_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +/** + * @brief Sets the quietCount1 field of the QUIET_ELEMENT_1A register. + * + * The QUIET_ELEMENT_1A register will be read, modified to contain the new field value, and written. + * + * @param[in] quietcount1 - The value to set the field to. + */ +__INLINE void nxmac_quiet_count_1_setf(uint8_t quietcount1) +{ + ASSERT_ERR((((uint32_t)quietcount1 << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(NXMAC_QUIET_ELEMENT_1A_ADDR, (REG_PL_RD(NXMAC_QUIET_ELEMENT_1A_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)quietcount1 << 0)); +} + +/// @} + +/** + * @name QUIET_ELEMENT_1B register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00         quietOffset1   0x0
+ * 
+ * + * @{ + */ + +/// Address of the QUIET_ELEMENT_1B register +#define NXMAC_QUIET_ELEMENT_1B_ADDR 0xC0000284 +/// Offset of the QUIET_ELEMENT_1B register from the base address +#define NXMAC_QUIET_ELEMENT_1B_OFFSET 0x00000284 +/// Index of the QUIET_ELEMENT_1B register +#define NXMAC_QUIET_ELEMENT_1B_INDEX 0x000000A1 +/// Reset value of the QUIET_ELEMENT_1B register +#define NXMAC_QUIET_ELEMENT_1B_RESET 0x00000000 + +/** + * @brief Returns the current value of the QUIET_ELEMENT_1B register. + * The QUIET_ELEMENT_1B register will be read and its value returned. + * @return The current value of the QUIET_ELEMENT_1B register. + */ +__INLINE uint32_t nxmac_quiet_element_1b_get(void) +{ + return REG_PL_RD(NXMAC_QUIET_ELEMENT_1B_ADDR); +} + +/** + * @brief Sets the QUIET_ELEMENT_1B register to a value. + * The QUIET_ELEMENT_1B register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_quiet_element_1b_set(uint32_t value) +{ + REG_PL_WR(NXMAC_QUIET_ELEMENT_1B_ADDR, value); +} + +// field definitions +/// QUIET_OFFSET_1 field mask +#define NXMAC_QUIET_OFFSET_1_MASK ((uint32_t)0x0000FFFF) +/// QUIET_OFFSET_1 field LSB position +#define NXMAC_QUIET_OFFSET_1_LSB 0 +/// QUIET_OFFSET_1 field width +#define NXMAC_QUIET_OFFSET_1_WIDTH ((uint32_t)0x00000010) + +/// QUIET_OFFSET_1 field reset value +#define NXMAC_QUIET_OFFSET_1_RST 0x0 + +/** + * @brief Returns the current value of the quietOffset1 field in the QUIET_ELEMENT_1B register. + * + * The QUIET_ELEMENT_1B register will be read and the quietOffset1 field's value will be returned. + * + * @return The current value of the quietOffset1 field in the QUIET_ELEMENT_1B register. + */ +__INLINE uint16_t nxmac_quiet_offset_1_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_QUIET_ELEMENT_1B_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the quietOffset1 field of the QUIET_ELEMENT_1B register. + * + * The QUIET_ELEMENT_1B register will be read, modified to contain the new field value, and written. + * + * @param[in] quietoffset1 - The value to set the field to. + */ +__INLINE void nxmac_quiet_offset_1_setf(uint16_t quietoffset1) +{ + ASSERT_ERR((((uint32_t)quietoffset1 << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_PL_WR(NXMAC_QUIET_ELEMENT_1B_ADDR, (uint32_t)quietoffset1 << 0); +} + +/// @} + +/** + * @name QUIET_ELEMENT_2A register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:16       quietDuration2   0x0
+ *  15:08         quietPeriod2   0x0
+ *  07:00          quietCount2   0x0
+ * 
+ * + * @{ + */ + +/// Address of the QUIET_ELEMENT_2A register +#define NXMAC_QUIET_ELEMENT_2A_ADDR 0xC0000288 +/// Offset of the QUIET_ELEMENT_2A register from the base address +#define NXMAC_QUIET_ELEMENT_2A_OFFSET 0x00000288 +/// Index of the QUIET_ELEMENT_2A register +#define NXMAC_QUIET_ELEMENT_2A_INDEX 0x000000A2 +/// Reset value of the QUIET_ELEMENT_2A register +#define NXMAC_QUIET_ELEMENT_2A_RESET 0x00000000 + +/** + * @brief Returns the current value of the QUIET_ELEMENT_2A register. + * The QUIET_ELEMENT_2A register will be read and its value returned. + * @return The current value of the QUIET_ELEMENT_2A register. + */ +__INLINE uint32_t nxmac_quiet_element_2a_get(void) +{ + return REG_PL_RD(NXMAC_QUIET_ELEMENT_2A_ADDR); +} + +/** + * @brief Sets the QUIET_ELEMENT_2A register to a value. + * The QUIET_ELEMENT_2A register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_quiet_element_2a_set(uint32_t value) +{ + REG_PL_WR(NXMAC_QUIET_ELEMENT_2A_ADDR, value); +} + +// field definitions +/// QUIET_DURATION_2 field mask +#define NXMAC_QUIET_DURATION_2_MASK ((uint32_t)0xFFFF0000) +/// QUIET_DURATION_2 field LSB position +#define NXMAC_QUIET_DURATION_2_LSB 16 +/// QUIET_DURATION_2 field width +#define NXMAC_QUIET_DURATION_2_WIDTH ((uint32_t)0x00000010) +/// QUIET_PERIOD_2 field mask +#define NXMAC_QUIET_PERIOD_2_MASK ((uint32_t)0x0000FF00) +/// QUIET_PERIOD_2 field LSB position +#define NXMAC_QUIET_PERIOD_2_LSB 8 +/// QUIET_PERIOD_2 field width +#define NXMAC_QUIET_PERIOD_2_WIDTH ((uint32_t)0x00000008) +/// QUIET_COUNT_2 field mask +#define NXMAC_QUIET_COUNT_2_MASK ((uint32_t)0x000000FF) +/// QUIET_COUNT_2 field LSB position +#define NXMAC_QUIET_COUNT_2_LSB 0 +/// QUIET_COUNT_2 field width +#define NXMAC_QUIET_COUNT_2_WIDTH ((uint32_t)0x00000008) + +/// QUIET_DURATION_2 field reset value +#define NXMAC_QUIET_DURATION_2_RST 0x0 +/// QUIET_PERIOD_2 field reset value +#define NXMAC_QUIET_PERIOD_2_RST 0x0 +/// QUIET_COUNT_2 field reset value +#define NXMAC_QUIET_COUNT_2_RST 0x0 + +/** + * @brief Constructs a value for the QUIET_ELEMENT_2A register given values for its fields + * and writes the value to the register. + * + * @param[in] quietduration2 - The value to use for the quietDuration2 field. + * @param[in] quietperiod2 - The value to use for the quietPeriod2 field. + * @param[in] quietcount2 - The value to use for the quietCount2 field. + */ +__INLINE void nxmac_quiet_element_2a_pack(uint16_t quietduration2, uint8_t quietperiod2, uint8_t quietcount2) +{ + ASSERT_ERR((((uint32_t)quietduration2 << 16) & ~((uint32_t)0xFFFF0000)) == 0); + ASSERT_ERR((((uint32_t)quietperiod2 << 8) & ~((uint32_t)0x0000FF00)) == 0); + ASSERT_ERR((((uint32_t)quietcount2 << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(NXMAC_QUIET_ELEMENT_2A_ADDR, ((uint32_t)quietduration2 << 16) | ((uint32_t)quietperiod2 << 8) | ((uint32_t)quietcount2 << 0)); +} + +/** + * @brief Unpacks QUIET_ELEMENT_2A's fields from current value of the QUIET_ELEMENT_2A register. + * + * Reads the QUIET_ELEMENT_2A register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] quietduration2 - Will be populated with the current value of this field from the register. + * @param[out] quietperiod2 - Will be populated with the current value of this field from the register. + * @param[out] quietcount2 - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_quiet_element_2a_unpack(uint16_t *quietduration2, uint8_t *quietperiod2, uint8_t *quietcount2) +{ + uint32_t localVal = REG_PL_RD(NXMAC_QUIET_ELEMENT_2A_ADDR); + + *quietduration2 = (localVal & ((uint32_t)0xFFFF0000)) >> 16; + *quietperiod2 = (localVal & ((uint32_t)0x0000FF00)) >> 8; + *quietcount2 = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +/** + * @brief Returns the current value of the quietDuration2 field in the QUIET_ELEMENT_2A register. + * + * The QUIET_ELEMENT_2A register will be read and the quietDuration2 field's value will be returned. + * + * @return The current value of the quietDuration2 field in the QUIET_ELEMENT_2A register. + */ +__INLINE uint16_t nxmac_quiet_duration_2_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_QUIET_ELEMENT_2A_ADDR); + return ((localVal & ((uint32_t)0xFFFF0000)) >> 16); +} + +/** + * @brief Sets the quietDuration2 field of the QUIET_ELEMENT_2A register. + * + * The QUIET_ELEMENT_2A register will be read, modified to contain the new field value, and written. + * + * @param[in] quietduration2 - The value to set the field to. + */ +__INLINE void nxmac_quiet_duration_2_setf(uint16_t quietduration2) +{ + ASSERT_ERR((((uint32_t)quietduration2 << 16) & ~((uint32_t)0xFFFF0000)) == 0); + REG_PL_WR(NXMAC_QUIET_ELEMENT_2A_ADDR, (REG_PL_RD(NXMAC_QUIET_ELEMENT_2A_ADDR) & ~((uint32_t)0xFFFF0000)) | ((uint32_t)quietduration2 << 16)); +} + +/** + * @brief Returns the current value of the quietPeriod2 field in the QUIET_ELEMENT_2A register. + * + * The QUIET_ELEMENT_2A register will be read and the quietPeriod2 field's value will be returned. + * + * @return The current value of the quietPeriod2 field in the QUIET_ELEMENT_2A register. + */ +__INLINE uint8_t nxmac_quiet_period_2_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_QUIET_ELEMENT_2A_ADDR); + return ((localVal & ((uint32_t)0x0000FF00)) >> 8); +} + +/** + * @brief Sets the quietPeriod2 field of the QUIET_ELEMENT_2A register. + * + * The QUIET_ELEMENT_2A register will be read, modified to contain the new field value, and written. + * + * @param[in] quietperiod2 - The value to set the field to. + */ +__INLINE void nxmac_quiet_period_2_setf(uint8_t quietperiod2) +{ + ASSERT_ERR((((uint32_t)quietperiod2 << 8) & ~((uint32_t)0x0000FF00)) == 0); + REG_PL_WR(NXMAC_QUIET_ELEMENT_2A_ADDR, (REG_PL_RD(NXMAC_QUIET_ELEMENT_2A_ADDR) & ~((uint32_t)0x0000FF00)) | ((uint32_t)quietperiod2 << 8)); +} + +/** + * @brief Returns the current value of the quietCount2 field in the QUIET_ELEMENT_2A register. + * + * The QUIET_ELEMENT_2A register will be read and the quietCount2 field's value will be returned. + * + * @return The current value of the quietCount2 field in the QUIET_ELEMENT_2A register. + */ +__INLINE uint8_t nxmac_quiet_count_2_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_QUIET_ELEMENT_2A_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +/** + * @brief Sets the quietCount2 field of the QUIET_ELEMENT_2A register. + * + * The QUIET_ELEMENT_2A register will be read, modified to contain the new field value, and written. + * + * @param[in] quietcount2 - The value to set the field to. + */ +__INLINE void nxmac_quiet_count_2_setf(uint8_t quietcount2) +{ + ASSERT_ERR((((uint32_t)quietcount2 << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(NXMAC_QUIET_ELEMENT_2A_ADDR, (REG_PL_RD(NXMAC_QUIET_ELEMENT_2A_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)quietcount2 << 0)); +} + +/// @} + +/** + * @name QUIET_ELEMENT_2B register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00         quietOffset2   0x0
+ * 
+ * + * @{ + */ + +/// Address of the QUIET_ELEMENT_2B register +#define NXMAC_QUIET_ELEMENT_2B_ADDR 0xC000028C +/// Offset of the QUIET_ELEMENT_2B register from the base address +#define NXMAC_QUIET_ELEMENT_2B_OFFSET 0x0000028C +/// Index of the QUIET_ELEMENT_2B register +#define NXMAC_QUIET_ELEMENT_2B_INDEX 0x000000A3 +/// Reset value of the QUIET_ELEMENT_2B register +#define NXMAC_QUIET_ELEMENT_2B_RESET 0x00000000 + +/** + * @brief Returns the current value of the QUIET_ELEMENT_2B register. + * The QUIET_ELEMENT_2B register will be read and its value returned. + * @return The current value of the QUIET_ELEMENT_2B register. + */ +__INLINE uint32_t nxmac_quiet_element_2b_get(void) +{ + return REG_PL_RD(NXMAC_QUIET_ELEMENT_2B_ADDR); +} + +/** + * @brief Sets the QUIET_ELEMENT_2B register to a value. + * The QUIET_ELEMENT_2B register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_quiet_element_2b_set(uint32_t value) +{ + REG_PL_WR(NXMAC_QUIET_ELEMENT_2B_ADDR, value); +} + +// field definitions +/// QUIET_OFFSET_2 field mask +#define NXMAC_QUIET_OFFSET_2_MASK ((uint32_t)0x0000FFFF) +/// QUIET_OFFSET_2 field LSB position +#define NXMAC_QUIET_OFFSET_2_LSB 0 +/// QUIET_OFFSET_2 field width +#define NXMAC_QUIET_OFFSET_2_WIDTH ((uint32_t)0x00000010) + +/// QUIET_OFFSET_2 field reset value +#define NXMAC_QUIET_OFFSET_2_RST 0x0 + +/** + * @brief Returns the current value of the quietOffset2 field in the QUIET_ELEMENT_2B register. + * + * The QUIET_ELEMENT_2B register will be read and the quietOffset2 field's value will be returned. + * + * @return The current value of the quietOffset2 field in the QUIET_ELEMENT_2B register. + */ +__INLINE uint16_t nxmac_quiet_offset_2_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_QUIET_ELEMENT_2B_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the quietOffset2 field of the QUIET_ELEMENT_2B register. + * + * The QUIET_ELEMENT_2B register will be read, modified to contain the new field value, and written. + * + * @param[in] quietoffset2 - The value to set the field to. + */ +__INLINE void nxmac_quiet_offset_2_setf(uint16_t quietoffset2) +{ + ASSERT_ERR((((uint32_t)quietoffset2 << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_PL_WR(NXMAC_QUIET_ELEMENT_2B_ADDR, (uint32_t)quietoffset2 << 0); +} + +/// @} + +/** + * @name ADD_CCA_BUSY_SEC_20 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00      ccaBusyDurSec20   0x0
+ * 
+ * + * @{ + */ + +/// Address of the ADD_CCA_BUSY_SEC_20 register +#define NXMAC_ADD_CCA_BUSY_SEC_20_ADDR 0xC0000290 +/// Offset of the ADD_CCA_BUSY_SEC_20 register from the base address +#define NXMAC_ADD_CCA_BUSY_SEC_20_OFFSET 0x00000290 +/// Index of the ADD_CCA_BUSY_SEC_20 register +#define NXMAC_ADD_CCA_BUSY_SEC_20_INDEX 0x000000A4 +/// Reset value of the ADD_CCA_BUSY_SEC_20 register +#define NXMAC_ADD_CCA_BUSY_SEC_20_RESET 0x00000000 + +/** + * @brief Returns the current value of the ADD_CCA_BUSY_SEC_20 register. + * The ADD_CCA_BUSY_SEC_20 register will be read and its value returned. + * @return The current value of the ADD_CCA_BUSY_SEC_20 register. + */ +__INLINE uint32_t nxmac_add_cca_busy_sec_20_get(void) +{ + return REG_PL_RD(NXMAC_ADD_CCA_BUSY_SEC_20_ADDR); +} + +/** + * @brief Sets the ADD_CCA_BUSY_SEC_20 register to a value. + * The ADD_CCA_BUSY_SEC_20 register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_add_cca_busy_sec_20_set(uint32_t value) +{ + REG_PL_WR(NXMAC_ADD_CCA_BUSY_SEC_20_ADDR, value); +} + +// field definitions +/// CCA_BUSY_DUR_SEC_20 field mask +#define NXMAC_CCA_BUSY_DUR_SEC_20_MASK ((uint32_t)0xFFFFFFFF) +/// CCA_BUSY_DUR_SEC_20 field LSB position +#define NXMAC_CCA_BUSY_DUR_SEC_20_LSB 0 +/// CCA_BUSY_DUR_SEC_20 field width +#define NXMAC_CCA_BUSY_DUR_SEC_20_WIDTH ((uint32_t)0x00000020) + +/// CCA_BUSY_DUR_SEC_20 field reset value +#define NXMAC_CCA_BUSY_DUR_SEC_20_RST 0x0 + +/** + * @brief Returns the current value of the ccaBusyDurSec20 field in the ADD_CCA_BUSY_SEC_20 register. + * + * The ADD_CCA_BUSY_SEC_20 register will be read and the ccaBusyDurSec20 field's value will be returned. + * + * @return The current value of the ccaBusyDurSec20 field in the ADD_CCA_BUSY_SEC_20 register. + */ +__INLINE uint32_t nxmac_cca_busy_dur_sec_20_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_ADD_CCA_BUSY_SEC_20_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the ccaBusyDurSec20 field of the ADD_CCA_BUSY_SEC_20 register. + * + * The ADD_CCA_BUSY_SEC_20 register will be read, modified to contain the new field value, and written. + * + * @param[in] ccabusydursec20 - The value to set the field to. + */ +__INLINE void nxmac_cca_busy_dur_sec_20_setf(uint32_t ccabusydursec20) +{ + ASSERT_ERR((((uint32_t)ccabusydursec20 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(NXMAC_ADD_CCA_BUSY_SEC_20_ADDR, (uint32_t)ccabusydursec20 << 0); +} + +/// @} + +/** + * @name ADD_CCA_BUSY_SEC_40 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00      ccaBusyDurSec40   0x0
+ * 
+ * + * @{ + */ + +/// Address of the ADD_CCA_BUSY_SEC_40 register +#define NXMAC_ADD_CCA_BUSY_SEC_40_ADDR 0xC0000294 +/// Offset of the ADD_CCA_BUSY_SEC_40 register from the base address +#define NXMAC_ADD_CCA_BUSY_SEC_40_OFFSET 0x00000294 +/// Index of the ADD_CCA_BUSY_SEC_40 register +#define NXMAC_ADD_CCA_BUSY_SEC_40_INDEX 0x000000A5 +/// Reset value of the ADD_CCA_BUSY_SEC_40 register +#define NXMAC_ADD_CCA_BUSY_SEC_40_RESET 0x00000000 + +/** + * @brief Returns the current value of the ADD_CCA_BUSY_SEC_40 register. + * The ADD_CCA_BUSY_SEC_40 register will be read and its value returned. + * @return The current value of the ADD_CCA_BUSY_SEC_40 register. + */ +__INLINE uint32_t nxmac_add_cca_busy_sec_40_get(void) +{ + return REG_PL_RD(NXMAC_ADD_CCA_BUSY_SEC_40_ADDR); +} + +/** + * @brief Sets the ADD_CCA_BUSY_SEC_40 register to a value. + * The ADD_CCA_BUSY_SEC_40 register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_add_cca_busy_sec_40_set(uint32_t value) +{ + REG_PL_WR(NXMAC_ADD_CCA_BUSY_SEC_40_ADDR, value); +} + +// field definitions +/// CCA_BUSY_DUR_SEC_40 field mask +#define NXMAC_CCA_BUSY_DUR_SEC_40_MASK ((uint32_t)0xFFFFFFFF) +/// CCA_BUSY_DUR_SEC_40 field LSB position +#define NXMAC_CCA_BUSY_DUR_SEC_40_LSB 0 +/// CCA_BUSY_DUR_SEC_40 field width +#define NXMAC_CCA_BUSY_DUR_SEC_40_WIDTH ((uint32_t)0x00000020) + +/// CCA_BUSY_DUR_SEC_40 field reset value +#define NXMAC_CCA_BUSY_DUR_SEC_40_RST 0x0 + +/** + * @brief Returns the current value of the ccaBusyDurSec40 field in the ADD_CCA_BUSY_SEC_40 register. + * + * The ADD_CCA_BUSY_SEC_40 register will be read and the ccaBusyDurSec40 field's value will be returned. + * + * @return The current value of the ccaBusyDurSec40 field in the ADD_CCA_BUSY_SEC_40 register. + */ +__INLINE uint32_t nxmac_cca_busy_dur_sec_40_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_ADD_CCA_BUSY_SEC_40_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the ccaBusyDurSec40 field of the ADD_CCA_BUSY_SEC_40 register. + * + * The ADD_CCA_BUSY_SEC_40 register will be read, modified to contain the new field value, and written. + * + * @param[in] ccabusydursec40 - The value to set the field to. + */ +__INLINE void nxmac_cca_busy_dur_sec_40_setf(uint32_t ccabusydursec40) +{ + ASSERT_ERR((((uint32_t)ccabusydursec40 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(NXMAC_ADD_CCA_BUSY_SEC_40_ADDR, (uint32_t)ccabusydursec40 << 0); +} + +/// @} + +/** + * @name ADD_CCA_BUSY_SEC_80 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00      ccaBusyDurSec80   0x0
+ * 
+ * + * @{ + */ + +/// Address of the ADD_CCA_BUSY_SEC_80 register +#define NXMAC_ADD_CCA_BUSY_SEC_80_ADDR 0xC0000298 +/// Offset of the ADD_CCA_BUSY_SEC_80 register from the base address +#define NXMAC_ADD_CCA_BUSY_SEC_80_OFFSET 0x00000298 +/// Index of the ADD_CCA_BUSY_SEC_80 register +#define NXMAC_ADD_CCA_BUSY_SEC_80_INDEX 0x000000A6 +/// Reset value of the ADD_CCA_BUSY_SEC_80 register +#define NXMAC_ADD_CCA_BUSY_SEC_80_RESET 0x00000000 + +/** + * @brief Returns the current value of the ADD_CCA_BUSY_SEC_80 register. + * The ADD_CCA_BUSY_SEC_80 register will be read and its value returned. + * @return The current value of the ADD_CCA_BUSY_SEC_80 register. + */ +__INLINE uint32_t nxmac_add_cca_busy_sec_80_get(void) +{ + return REG_PL_RD(NXMAC_ADD_CCA_BUSY_SEC_80_ADDR); +} + +/** + * @brief Sets the ADD_CCA_BUSY_SEC_80 register to a value. + * The ADD_CCA_BUSY_SEC_80 register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_add_cca_busy_sec_80_set(uint32_t value) +{ + REG_PL_WR(NXMAC_ADD_CCA_BUSY_SEC_80_ADDR, value); +} + +// field definitions +/// CCA_BUSY_DUR_SEC_80 field mask +#define NXMAC_CCA_BUSY_DUR_SEC_80_MASK ((uint32_t)0xFFFFFFFF) +/// CCA_BUSY_DUR_SEC_80 field LSB position +#define NXMAC_CCA_BUSY_DUR_SEC_80_LSB 0 +/// CCA_BUSY_DUR_SEC_80 field width +#define NXMAC_CCA_BUSY_DUR_SEC_80_WIDTH ((uint32_t)0x00000020) + +/// CCA_BUSY_DUR_SEC_80 field reset value +#define NXMAC_CCA_BUSY_DUR_SEC_80_RST 0x0 + +/** + * @brief Returns the current value of the ccaBusyDurSec80 field in the ADD_CCA_BUSY_SEC_80 register. + * + * The ADD_CCA_BUSY_SEC_80 register will be read and the ccaBusyDurSec80 field's value will be returned. + * + * @return The current value of the ccaBusyDurSec80 field in the ADD_CCA_BUSY_SEC_80 register. + */ +__INLINE uint32_t nxmac_cca_busy_dur_sec_80_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_ADD_CCA_BUSY_SEC_80_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the ccaBusyDurSec80 field of the ADD_CCA_BUSY_SEC_80 register. + * + * The ADD_CCA_BUSY_SEC_80 register will be read, modified to contain the new field value, and written. + * + * @param[in] ccabusydursec80 - The value to set the field to. + */ +__INLINE void nxmac_cca_busy_dur_sec_80_setf(uint32_t ccabusydursec80) +{ + ASSERT_ERR((((uint32_t)ccabusydursec80 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(NXMAC_ADD_CCA_BUSY_SEC_80_ADDR, (uint32_t)ccabusydursec80 << 0); +} + +/// @} + +/** + * @name STBC_CNTRL register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:25         basicSTBCMCS   0x0
+ *     24          dualCTSProt   0
+ *  23:16           ctsSTBCDur   0x0
+ *  15:00         cfEndSTBCDur   0x0
+ * 
+ * + * @{ + */ + +/// Address of the STBC_CNTRL register +#define NXMAC_STBC_CNTRL_ADDR 0xC0000300 +/// Offset of the STBC_CNTRL register from the base address +#define NXMAC_STBC_CNTRL_OFFSET 0x00000300 +/// Index of the STBC_CNTRL register +#define NXMAC_STBC_CNTRL_INDEX 0x000000C0 +/// Reset value of the STBC_CNTRL register +#define NXMAC_STBC_CNTRL_RESET 0x00000000 + +/** + * @brief Returns the current value of the STBC_CNTRL register. + * The STBC_CNTRL register will be read and its value returned. + * @return The current value of the STBC_CNTRL register. + */ +__INLINE uint32_t nxmac_stbc_cntrl_get(void) +{ + return REG_PL_RD(NXMAC_STBC_CNTRL_ADDR); +} + +/** + * @brief Sets the STBC_CNTRL register to a value. + * The STBC_CNTRL register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_stbc_cntrl_set(uint32_t value) +{ + REG_PL_WR(NXMAC_STBC_CNTRL_ADDR, value); +} + +// field definitions +/// BASIC_STBCMCS field mask +#define NXMAC_BASIC_STBCMCS_MASK ((uint32_t)0xFE000000) +/// BASIC_STBCMCS field LSB position +#define NXMAC_BASIC_STBCMCS_LSB 25 +/// BASIC_STBCMCS field width +#define NXMAC_BASIC_STBCMCS_WIDTH ((uint32_t)0x00000007) +/// DUAL_CTS_PROT field bit +#define NXMAC_DUAL_CTS_PROT_BIT ((uint32_t)0x01000000) +/// DUAL_CTS_PROT field position +#define NXMAC_DUAL_CTS_PROT_POS 24 +/// CTS_STBC_DUR field mask +#define NXMAC_CTS_STBC_DUR_MASK ((uint32_t)0x00FF0000) +/// CTS_STBC_DUR field LSB position +#define NXMAC_CTS_STBC_DUR_LSB 16 +/// CTS_STBC_DUR field width +#define NXMAC_CTS_STBC_DUR_WIDTH ((uint32_t)0x00000008) +/// CF_END_STBC_DUR field mask +#define NXMAC_CF_END_STBC_DUR_MASK ((uint32_t)0x0000FFFF) +/// CF_END_STBC_DUR field LSB position +#define NXMAC_CF_END_STBC_DUR_LSB 0 +/// CF_END_STBC_DUR field width +#define NXMAC_CF_END_STBC_DUR_WIDTH ((uint32_t)0x00000010) + +/// BASIC_STBCMCS field reset value +#define NXMAC_BASIC_STBCMCS_RST 0x0 +/// DUAL_CTS_PROT field reset value +#define NXMAC_DUAL_CTS_PROT_RST 0x0 +/// CTS_STBC_DUR field reset value +#define NXMAC_CTS_STBC_DUR_RST 0x0 +/// CF_END_STBC_DUR field reset value +#define NXMAC_CF_END_STBC_DUR_RST 0x0 + +/** + * @brief Constructs a value for the STBC_CNTRL register given values for its fields + * and writes the value to the register. + * + * @param[in] basicstbcmcs - The value to use for the basicSTBCMCS field. + * @param[in] dualctsprot - The value to use for the dualCTSProt field. + * @param[in] ctsstbcdur - The value to use for the ctsSTBCDur field. + * @param[in] cfendstbcdur - The value to use for the cfEndSTBCDur field. + */ +__INLINE void nxmac_stbc_cntrl_pack(uint8_t basicstbcmcs, uint8_t dualctsprot, uint8_t ctsstbcdur, uint16_t cfendstbcdur) +{ + ASSERT_ERR((((uint32_t)basicstbcmcs << 25) & ~((uint32_t)0xFE000000)) == 0); + ASSERT_ERR((((uint32_t)dualctsprot << 24) & ~((uint32_t)0x01000000)) == 0); + ASSERT_ERR((((uint32_t)ctsstbcdur << 16) & ~((uint32_t)0x00FF0000)) == 0); + ASSERT_ERR((((uint32_t)cfendstbcdur << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_PL_WR(NXMAC_STBC_CNTRL_ADDR, ((uint32_t)basicstbcmcs << 25) | ((uint32_t)dualctsprot << 24) | ((uint32_t)ctsstbcdur << 16) | ((uint32_t)cfendstbcdur << 0)); +} + +/** + * @brief Unpacks STBC_CNTRL's fields from current value of the STBC_CNTRL register. + * + * Reads the STBC_CNTRL register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] basicstbcmcs - Will be populated with the current value of this field from the register. + * @param[out] dualctsprot - Will be populated with the current value of this field from the register. + * @param[out] ctsstbcdur - Will be populated with the current value of this field from the register. + * @param[out] cfendstbcdur - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_stbc_cntrl_unpack(uint8_t *basicstbcmcs, uint8_t *dualctsprot, uint8_t *ctsstbcdur, uint16_t *cfendstbcdur) +{ + uint32_t localVal = REG_PL_RD(NXMAC_STBC_CNTRL_ADDR); + + *basicstbcmcs = (localVal & ((uint32_t)0xFE000000)) >> 25; + *dualctsprot = (localVal & ((uint32_t)0x01000000)) >> 24; + *ctsstbcdur = (localVal & ((uint32_t)0x00FF0000)) >> 16; + *cfendstbcdur = (localVal & ((uint32_t)0x0000FFFF)) >> 0; +} + +/** + * @brief Returns the current value of the basicSTBCMCS field in the STBC_CNTRL register. + * + * The STBC_CNTRL register will be read and the basicSTBCMCS field's value will be returned. + * + * @return The current value of the basicSTBCMCS field in the STBC_CNTRL register. + */ +__INLINE uint8_t nxmac_basic_stbcmcs_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_STBC_CNTRL_ADDR); + return ((localVal & ((uint32_t)0xFE000000)) >> 25); +} + +/** + * @brief Sets the basicSTBCMCS field of the STBC_CNTRL register. + * + * The STBC_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] basicstbcmcs - The value to set the field to. + */ +__INLINE void nxmac_basic_stbcmcs_setf(uint8_t basicstbcmcs) +{ + ASSERT_ERR((((uint32_t)basicstbcmcs << 25) & ~((uint32_t)0xFE000000)) == 0); + REG_PL_WR(NXMAC_STBC_CNTRL_ADDR, (REG_PL_RD(NXMAC_STBC_CNTRL_ADDR) & ~((uint32_t)0xFE000000)) | ((uint32_t)basicstbcmcs << 25)); +} + +/** + * @brief Returns the current value of the dualCTSProt field in the STBC_CNTRL register. + * + * The STBC_CNTRL register will be read and the dualCTSProt field's value will be returned. + * + * @return The current value of the dualCTSProt field in the STBC_CNTRL register. + */ +__INLINE uint8_t nxmac_dual_cts_prot_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_STBC_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x01000000)) >> 24); +} + +/** + * @brief Sets the dualCTSProt field of the STBC_CNTRL register. + * + * The STBC_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] dualctsprot - The value to set the field to. + */ +__INLINE void nxmac_dual_cts_prot_setf(uint8_t dualctsprot) +{ + ASSERT_ERR((((uint32_t)dualctsprot << 24) & ~((uint32_t)0x01000000)) == 0); + REG_PL_WR(NXMAC_STBC_CNTRL_ADDR, (REG_PL_RD(NXMAC_STBC_CNTRL_ADDR) & ~((uint32_t)0x01000000)) | ((uint32_t)dualctsprot << 24)); +} + +/** + * @brief Returns the current value of the ctsSTBCDur field in the STBC_CNTRL register. + * + * The STBC_CNTRL register will be read and the ctsSTBCDur field's value will be returned. + * + * @return The current value of the ctsSTBCDur field in the STBC_CNTRL register. + */ +__INLINE uint8_t nxmac_cts_stbc_dur_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_STBC_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x00FF0000)) >> 16); +} + +/** + * @brief Sets the ctsSTBCDur field of the STBC_CNTRL register. + * + * The STBC_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] ctsstbcdur - The value to set the field to. + */ +__INLINE void nxmac_cts_stbc_dur_setf(uint8_t ctsstbcdur) +{ + ASSERT_ERR((((uint32_t)ctsstbcdur << 16) & ~((uint32_t)0x00FF0000)) == 0); + REG_PL_WR(NXMAC_STBC_CNTRL_ADDR, (REG_PL_RD(NXMAC_STBC_CNTRL_ADDR) & ~((uint32_t)0x00FF0000)) | ((uint32_t)ctsstbcdur << 16)); +} + +/** + * @brief Returns the current value of the cfEndSTBCDur field in the STBC_CNTRL register. + * + * The STBC_CNTRL register will be read and the cfEndSTBCDur field's value will be returned. + * + * @return The current value of the cfEndSTBCDur field in the STBC_CNTRL register. + */ +__INLINE uint16_t nxmac_cf_end_stbc_dur_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_STBC_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x0000FFFF)) >> 0); +} + +/** + * @brief Sets the cfEndSTBCDur field of the STBC_CNTRL register. + * + * The STBC_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] cfendstbcdur - The value to set the field to. + */ +__INLINE void nxmac_cf_end_stbc_dur_setf(uint16_t cfendstbcdur) +{ + ASSERT_ERR((((uint32_t)cfendstbcdur << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_PL_WR(NXMAC_STBC_CNTRL_ADDR, (REG_PL_RD(NXMAC_STBC_CNTRL_ADDR) & ~((uint32_t)0x0000FFFF)) | ((uint32_t)cfendstbcdur << 0)); +} + +/// @} + +/** + * @name START_TX_1 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  29:28            startTxBW   0x0
+ *     27       startTxPreType   0
+ *  26:24     startTxFormatMod   0x0
+ *  23:16     startTxMCSIndex0   0x0
+ *  15:06      startTxKSRIndex   0x0
+ *  04:03            startTxAC   0x0
+ *  02:01     startTxFrmExType   0x0
+ *     00       startTxFrameEx   0
+ * 
+ * + * @{ + */ + +/// Address of the START_TX_1 register +#define NXMAC_START_TX_1_ADDR 0xC0000304 +/// Offset of the START_TX_1 register from the base address +#define NXMAC_START_TX_1_OFFSET 0x00000304 +/// Index of the START_TX_1 register +#define NXMAC_START_TX_1_INDEX 0x000000C1 +/// Reset value of the START_TX_1 register +#define NXMAC_START_TX_1_RESET 0x00000000 + +/** + * @brief Returns the current value of the START_TX_1 register. + * The START_TX_1 register will be read and its value returned. + * @return The current value of the START_TX_1 register. + */ +__INLINE uint32_t nxmac_start_tx_1_get(void) +{ + return REG_PL_RD(NXMAC_START_TX_1_ADDR); +} + +/** + * @brief Sets the START_TX_1 register to a value. + * The START_TX_1 register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_start_tx_1_set(uint32_t value) +{ + REG_PL_WR(NXMAC_START_TX_1_ADDR, value); +} + +// field definitions +/// START_TX_BW field mask +#define NXMAC_START_TX_BW_MASK ((uint32_t)0x30000000) +/// START_TX_BW field LSB position +#define NXMAC_START_TX_BW_LSB 28 +/// START_TX_BW field width +#define NXMAC_START_TX_BW_WIDTH ((uint32_t)0x00000002) +/// START_TX_PRE_TYPE field bit +#define NXMAC_START_TX_PRE_TYPE_BIT ((uint32_t)0x08000000) +/// START_TX_PRE_TYPE field position +#define NXMAC_START_TX_PRE_TYPE_POS 27 +/// START_TX_FORMAT_MOD field mask +#define NXMAC_START_TX_FORMAT_MOD_MASK ((uint32_t)0x07000000) +/// START_TX_FORMAT_MOD field LSB position +#define NXMAC_START_TX_FORMAT_MOD_LSB 24 +/// START_TX_FORMAT_MOD field width +#define NXMAC_START_TX_FORMAT_MOD_WIDTH ((uint32_t)0x00000003) +/// START_TX_MCS_INDEX_0 field mask +#define NXMAC_START_TX_MCS_INDEX_0_MASK ((uint32_t)0x00FF0000) +/// START_TX_MCS_INDEX_0 field LSB position +#define NXMAC_START_TX_MCS_INDEX_0_LSB 16 +/// START_TX_MCS_INDEX_0 field width +#define NXMAC_START_TX_MCS_INDEX_0_WIDTH ((uint32_t)0x00000008) +/// START_TX_KSR_INDEX field mask +#define NXMAC_START_TX_KSR_INDEX_MASK ((uint32_t)0x0000FFC0) +/// START_TX_KSR_INDEX field LSB position +#define NXMAC_START_TX_KSR_INDEX_LSB 6 +/// START_TX_KSR_INDEX field width +#define NXMAC_START_TX_KSR_INDEX_WIDTH ((uint32_t)0x0000000A) +/// START_TX_AC field mask +#define NXMAC_START_TX_AC_MASK ((uint32_t)0x00000018) +/// START_TX_AC field LSB position +#define NXMAC_START_TX_AC_LSB 3 +/// START_TX_AC field width +#define NXMAC_START_TX_AC_WIDTH ((uint32_t)0x00000002) +/// START_TX_FRM_EX_TYPE field mask +#define NXMAC_START_TX_FRM_EX_TYPE_MASK ((uint32_t)0x00000006) +/// START_TX_FRM_EX_TYPE field LSB position +#define NXMAC_START_TX_FRM_EX_TYPE_LSB 1 +/// START_TX_FRM_EX_TYPE field width +#define NXMAC_START_TX_FRM_EX_TYPE_WIDTH ((uint32_t)0x00000002) +/// START_TX_FRAME_EX field bit +#define NXMAC_START_TX_FRAME_EX_BIT ((uint32_t)0x00000001) +/// START_TX_FRAME_EX field position +#define NXMAC_START_TX_FRAME_EX_POS 0 + +/// START_TX_BW field reset value +#define NXMAC_START_TX_BW_RST 0x0 +/// START_TX_PRE_TYPE field reset value +#define NXMAC_START_TX_PRE_TYPE_RST 0x0 +/// START_TX_FORMAT_MOD field reset value +#define NXMAC_START_TX_FORMAT_MOD_RST 0x0 +/// START_TX_MCS_INDEX_0 field reset value +#define NXMAC_START_TX_MCS_INDEX_0_RST 0x0 +/// START_TX_KSR_INDEX field reset value +#define NXMAC_START_TX_KSR_INDEX_RST 0x0 +/// START_TX_AC field reset value +#define NXMAC_START_TX_AC_RST 0x0 +/// START_TX_FRM_EX_TYPE field reset value +#define NXMAC_START_TX_FRM_EX_TYPE_RST 0x0 +/// START_TX_FRAME_EX field reset value +#define NXMAC_START_TX_FRAME_EX_RST 0x0 + +/** + * @brief Constructs a value for the START_TX_1 register given values for its fields + * and writes the value to the register. + * + * @param[in] starttxbw - The value to use for the startTxBW field. + * @param[in] starttxpretype - The value to use for the startTxPreType field. + * @param[in] starttxformatmod - The value to use for the startTxFormatMod field. + * @param[in] starttxmcsindex0 - The value to use for the startTxMCSIndex0 field. + * @param[in] starttxksrindex - The value to use for the startTxKSRIndex field. + * @param[in] starttxac - The value to use for the startTxAC field. + * @param[in] starttxfrmextype - The value to use for the startTxFrmExType field. + * @param[in] starttxframeex - The value to use for the startTxFrameEx field. + */ +__INLINE void nxmac_start_tx_1_pack(uint8_t starttxbw, uint8_t starttxpretype, uint8_t starttxformatmod, uint8_t starttxmcsindex0, uint16_t starttxksrindex, uint8_t starttxac, uint8_t starttxfrmextype, uint8_t starttxframeex) +{ + ASSERT_ERR((((uint32_t)starttxbw << 28) & ~((uint32_t)0x30000000)) == 0); + ASSERT_ERR((((uint32_t)starttxpretype << 27) & ~((uint32_t)0x08000000)) == 0); + ASSERT_ERR((((uint32_t)starttxformatmod << 24) & ~((uint32_t)0x07000000)) == 0); + ASSERT_ERR((((uint32_t)starttxmcsindex0 << 16) & ~((uint32_t)0x00FF0000)) == 0); + ASSERT_ERR((((uint32_t)starttxksrindex << 6) & ~((uint32_t)0x0000FFC0)) == 0); + ASSERT_ERR((((uint32_t)starttxac << 3) & ~((uint32_t)0x00000018)) == 0); + ASSERT_ERR((((uint32_t)starttxfrmextype << 1) & ~((uint32_t)0x00000006)) == 0); + ASSERT_ERR((((uint32_t)starttxframeex << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_START_TX_1_ADDR, ((uint32_t)starttxbw << 28) | ((uint32_t)starttxpretype << 27) | ((uint32_t)starttxformatmod << 24) | ((uint32_t)starttxmcsindex0 << 16) | ((uint32_t)starttxksrindex << 6) | ((uint32_t)starttxac << 3) | ((uint32_t)starttxfrmextype << 1) | ((uint32_t)starttxframeex << 0)); +} + +/** + * @brief Unpacks START_TX_1's fields from current value of the START_TX_1 register. + * + * Reads the START_TX_1 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] starttxbw - Will be populated with the current value of this field from the register. + * @param[out] starttxpretype - Will be populated with the current value of this field from the register. + * @param[out] starttxformatmod - Will be populated with the current value of this field from the register. + * @param[out] starttxmcsindex0 - Will be populated with the current value of this field from the register. + * @param[out] starttxksrindex - Will be populated with the current value of this field from the register. + * @param[out] starttxac - Will be populated with the current value of this field from the register. + * @param[out] starttxfrmextype - Will be populated with the current value of this field from the register. + * @param[out] starttxframeex - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_start_tx_1_unpack(uint8_t *starttxbw, uint8_t *starttxpretype, uint8_t *starttxformatmod, uint8_t *starttxmcsindex0, uint16_t *starttxksrindex, uint8_t *starttxac, uint8_t *starttxfrmextype, uint8_t *starttxframeex) +{ + uint32_t localVal = REG_PL_RD(NXMAC_START_TX_1_ADDR); + + *starttxbw = (localVal & ((uint32_t)0x30000000)) >> 28; + *starttxpretype = (localVal & ((uint32_t)0x08000000)) >> 27; + *starttxformatmod = (localVal & ((uint32_t)0x07000000)) >> 24; + *starttxmcsindex0 = (localVal & ((uint32_t)0x00FF0000)) >> 16; + *starttxksrindex = (localVal & ((uint32_t)0x0000FFC0)) >> 6; + *starttxac = (localVal & ((uint32_t)0x00000018)) >> 3; + *starttxfrmextype = (localVal & ((uint32_t)0x00000006)) >> 1; + *starttxframeex = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +/** + * @brief Returns the current value of the startTxBW field in the START_TX_1 register. + * + * The START_TX_1 register will be read and the startTxBW field's value will be returned. + * + * @return The current value of the startTxBW field in the START_TX_1 register. + */ +__INLINE uint8_t nxmac_start_tx_bw_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_START_TX_1_ADDR); + return ((localVal & ((uint32_t)0x30000000)) >> 28); +} + +/** + * @brief Sets the startTxBW field of the START_TX_1 register. + * + * The START_TX_1 register will be read, modified to contain the new field value, and written. + * + * @param[in] starttxbw - The value to set the field to. + */ +__INLINE void nxmac_start_tx_bw_setf(uint8_t starttxbw) +{ + ASSERT_ERR((((uint32_t)starttxbw << 28) & ~((uint32_t)0x30000000)) == 0); + REG_PL_WR(NXMAC_START_TX_1_ADDR, (REG_PL_RD(NXMAC_START_TX_1_ADDR) & ~((uint32_t)0x30000000)) | ((uint32_t)starttxbw << 28)); +} + +/** + * @brief Returns the current value of the startTxPreType field in the START_TX_1 register. + * + * The START_TX_1 register will be read and the startTxPreType field's value will be returned. + * + * @return The current value of the startTxPreType field in the START_TX_1 register. + */ +__INLINE uint8_t nxmac_start_tx_pre_type_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_START_TX_1_ADDR); + return ((localVal & ((uint32_t)0x08000000)) >> 27); +} + +/** + * @brief Sets the startTxPreType field of the START_TX_1 register. + * + * The START_TX_1 register will be read, modified to contain the new field value, and written. + * + * @param[in] starttxpretype - The value to set the field to. + */ +__INLINE void nxmac_start_tx_pre_type_setf(uint8_t starttxpretype) +{ + ASSERT_ERR((((uint32_t)starttxpretype << 27) & ~((uint32_t)0x08000000)) == 0); + REG_PL_WR(NXMAC_START_TX_1_ADDR, (REG_PL_RD(NXMAC_START_TX_1_ADDR) & ~((uint32_t)0x08000000)) | ((uint32_t)starttxpretype << 27)); +} + +/** + * @brief Returns the current value of the startTxFormatMod field in the START_TX_1 register. + * + * The START_TX_1 register will be read and the startTxFormatMod field's value will be returned. + * + * @return The current value of the startTxFormatMod field in the START_TX_1 register. + */ +__INLINE uint8_t nxmac_start_tx_format_mod_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_START_TX_1_ADDR); + return ((localVal & ((uint32_t)0x07000000)) >> 24); +} + +/** + * @brief Sets the startTxFormatMod field of the START_TX_1 register. + * + * The START_TX_1 register will be read, modified to contain the new field value, and written. + * + * @param[in] starttxformatmod - The value to set the field to. + */ +__INLINE void nxmac_start_tx_format_mod_setf(uint8_t starttxformatmod) +{ + ASSERT_ERR((((uint32_t)starttxformatmod << 24) & ~((uint32_t)0x07000000)) == 0); + REG_PL_WR(NXMAC_START_TX_1_ADDR, (REG_PL_RD(NXMAC_START_TX_1_ADDR) & ~((uint32_t)0x07000000)) | ((uint32_t)starttxformatmod << 24)); +} + +/** + * @brief Returns the current value of the startTxMCSIndex0 field in the START_TX_1 register. + * + * The START_TX_1 register will be read and the startTxMCSIndex0 field's value will be returned. + * + * @return The current value of the startTxMCSIndex0 field in the START_TX_1 register. + */ +__INLINE uint8_t nxmac_start_tx_mcs_index_0_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_START_TX_1_ADDR); + return ((localVal & ((uint32_t)0x00FF0000)) >> 16); +} + +/** + * @brief Sets the startTxMCSIndex0 field of the START_TX_1 register. + * + * The START_TX_1 register will be read, modified to contain the new field value, and written. + * + * @param[in] starttxmcsindex0 - The value to set the field to. + */ +__INLINE void nxmac_start_tx_mcs_index_0_setf(uint8_t starttxmcsindex0) +{ + ASSERT_ERR((((uint32_t)starttxmcsindex0 << 16) & ~((uint32_t)0x00FF0000)) == 0); + REG_PL_WR(NXMAC_START_TX_1_ADDR, (REG_PL_RD(NXMAC_START_TX_1_ADDR) & ~((uint32_t)0x00FF0000)) | ((uint32_t)starttxmcsindex0 << 16)); +} + +/** + * @brief Returns the current value of the startTxKSRIndex field in the START_TX_1 register. + * + * The START_TX_1 register will be read and the startTxKSRIndex field's value will be returned. + * + * @return The current value of the startTxKSRIndex field in the START_TX_1 register. + */ +__INLINE uint16_t nxmac_start_tx_ksr_index_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_START_TX_1_ADDR); + return ((localVal & ((uint32_t)0x0000FFC0)) >> 6); +} + +/** + * @brief Sets the startTxKSRIndex field of the START_TX_1 register. + * + * The START_TX_1 register will be read, modified to contain the new field value, and written. + * + * @param[in] starttxksrindex - The value to set the field to. + */ +__INLINE void nxmac_start_tx_ksr_index_setf(uint16_t starttxksrindex) +{ + ASSERT_ERR((((uint32_t)starttxksrindex << 6) & ~((uint32_t)0x0000FFC0)) == 0); + REG_PL_WR(NXMAC_START_TX_1_ADDR, (REG_PL_RD(NXMAC_START_TX_1_ADDR) & ~((uint32_t)0x0000FFC0)) | ((uint32_t)starttxksrindex << 6)); +} + +/** + * @brief Returns the current value of the startTxAC field in the START_TX_1 register. + * + * The START_TX_1 register will be read and the startTxAC field's value will be returned. + * + * @return The current value of the startTxAC field in the START_TX_1 register. + */ +__INLINE uint8_t nxmac_start_tx_ac_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_START_TX_1_ADDR); + return ((localVal & ((uint32_t)0x00000018)) >> 3); +} + +/** + * @brief Sets the startTxAC field of the START_TX_1 register. + * + * The START_TX_1 register will be read, modified to contain the new field value, and written. + * + * @param[in] starttxac - The value to set the field to. + */ +__INLINE void nxmac_start_tx_ac_setf(uint8_t starttxac) +{ + ASSERT_ERR((((uint32_t)starttxac << 3) & ~((uint32_t)0x00000018)) == 0); + REG_PL_WR(NXMAC_START_TX_1_ADDR, (REG_PL_RD(NXMAC_START_TX_1_ADDR) & ~((uint32_t)0x00000018)) | ((uint32_t)starttxac << 3)); +} + +/** + * @brief Returns the current value of the startTxFrmExType field in the START_TX_1 register. + * + * The START_TX_1 register will be read and the startTxFrmExType field's value will be returned. + * + * @return The current value of the startTxFrmExType field in the START_TX_1 register. + */ +__INLINE uint8_t nxmac_start_tx_frm_ex_type_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_START_TX_1_ADDR); + return ((localVal & ((uint32_t)0x00000006)) >> 1); +} + +/** + * @brief Sets the startTxFrmExType field of the START_TX_1 register. + * + * The START_TX_1 register will be read, modified to contain the new field value, and written. + * + * @param[in] starttxfrmextype - The value to set the field to. + */ +__INLINE void nxmac_start_tx_frm_ex_type_setf(uint8_t starttxfrmextype) +{ + ASSERT_ERR((((uint32_t)starttxfrmextype << 1) & ~((uint32_t)0x00000006)) == 0); + REG_PL_WR(NXMAC_START_TX_1_ADDR, (REG_PL_RD(NXMAC_START_TX_1_ADDR) & ~((uint32_t)0x00000006)) | ((uint32_t)starttxfrmextype << 1)); +} + +/** + * @brief Returns the current value of the startTxFrameEx field in the START_TX_1 register. + * + * The START_TX_1 register will be read and the startTxFrameEx field's value will be returned. + * + * @return The current value of the startTxFrameEx field in the START_TX_1 register. + */ +__INLINE uint8_t nxmac_start_tx_frame_ex_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_START_TX_1_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/** + * @brief Sets the startTxFrameEx field of the START_TX_1 register. + * + * The START_TX_1 register will be read, modified to contain the new field value, and written. + * + * @param[in] starttxframeex - The value to set the field to. + */ +__INLINE void nxmac_start_tx_frame_ex_setf(uint8_t starttxframeex) +{ + ASSERT_ERR((((uint32_t)starttxframeex << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_START_TX_1_ADDR, (REG_PL_RD(NXMAC_START_TX_1_ADDR) & ~((uint32_t)0x00000001)) | ((uint32_t)starttxframeex << 0)); +} + +/// @} + +/** + * @name START_TX_2 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00        durControlFrm   0x0
+ * 
+ * + * @{ + */ + +/// Address of the START_TX_2 register +#define NXMAC_START_TX_2_ADDR 0xC0000308 +/// Offset of the START_TX_2 register from the base address +#define NXMAC_START_TX_2_OFFSET 0x00000308 +/// Index of the START_TX_2 register +#define NXMAC_START_TX_2_INDEX 0x000000C2 +/// Reset value of the START_TX_2 register +#define NXMAC_START_TX_2_RESET 0x00000000 + +/** + * @brief Returns the current value of the START_TX_2 register. + * The START_TX_2 register will be read and its value returned. + * @return The current value of the START_TX_2 register. + */ +__INLINE uint32_t nxmac_start_tx_2_get(void) +{ + return REG_PL_RD(NXMAC_START_TX_2_ADDR); +} + +/** + * @brief Sets the START_TX_2 register to a value. + * The START_TX_2 register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_start_tx_2_set(uint32_t value) +{ + REG_PL_WR(NXMAC_START_TX_2_ADDR, value); +} + +// field definitions +/// DUR_CONTROL_FRM field mask +#define NXMAC_DUR_CONTROL_FRM_MASK ((uint32_t)0x0000FFFF) +/// DUR_CONTROL_FRM field LSB position +#define NXMAC_DUR_CONTROL_FRM_LSB 0 +/// DUR_CONTROL_FRM field width +#define NXMAC_DUR_CONTROL_FRM_WIDTH ((uint32_t)0x00000010) + +/// DUR_CONTROL_FRM field reset value +#define NXMAC_DUR_CONTROL_FRM_RST 0x0 + +/** + * @brief Returns the current value of the durControlFrm field in the START_TX_2 register. + * + * The START_TX_2 register will be read and the durControlFrm field's value will be returned. + * + * @return The current value of the durControlFrm field in the START_TX_2 register. + */ +__INLINE uint16_t nxmac_dur_control_frm_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_START_TX_2_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the durControlFrm field of the START_TX_2 register. + * + * The START_TX_2 register will be read, modified to contain the new field value, and written. + * + * @param[in] durcontrolfrm - The value to set the field to. + */ +__INLINE void nxmac_dur_control_frm_setf(uint16_t durcontrolfrm) +{ + ASSERT_ERR((((uint32_t)durcontrolfrm << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_PL_WR(NXMAC_START_TX_2_ADDR, (uint32_t)durcontrolfrm << 0); +} + +/// @} + +/** + * @name START_TX_3 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:24      startTxSMMIndex   0x0
+ *  23:16    startTxAntennaSet   0x0
+ *     13          startTxLSTP   0
+ *     12     startTxSmoothing   0
+ *     08       startTxShortGI   0
+ *  07:05           startTxNTx   0x0
+ *     04     startTxFecCoding   0
+ *  03:02          startTxSTBC   0x0
+ *  01:00     startTxNumExtnSS   0x0
+ * 
+ * + * @{ + */ + +/// Address of the START_TX_3 register +#define NXMAC_START_TX_3_ADDR 0xC000030C +/// Offset of the START_TX_3 register from the base address +#define NXMAC_START_TX_3_OFFSET 0x0000030C +/// Index of the START_TX_3 register +#define NXMAC_START_TX_3_INDEX 0x000000C3 +/// Reset value of the START_TX_3 register +#define NXMAC_START_TX_3_RESET 0x00000000 + +/** + * @brief Returns the current value of the START_TX_3 register. + * The START_TX_3 register will be read and its value returned. + * @return The current value of the START_TX_3 register. + */ +__INLINE uint32_t nxmac_start_tx_3_get(void) +{ + return REG_PL_RD(NXMAC_START_TX_3_ADDR); +} + +/** + * @brief Sets the START_TX_3 register to a value. + * The START_TX_3 register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_start_tx_3_set(uint32_t value) +{ + REG_PL_WR(NXMAC_START_TX_3_ADDR, value); +} + +// field definitions +/// START_TX_SMM_INDEX field mask +#define NXMAC_START_TX_SMM_INDEX_MASK ((uint32_t)0xFF000000) +/// START_TX_SMM_INDEX field LSB position +#define NXMAC_START_TX_SMM_INDEX_LSB 24 +/// START_TX_SMM_INDEX field width +#define NXMAC_START_TX_SMM_INDEX_WIDTH ((uint32_t)0x00000008) +/// START_TX_ANTENNA_SET field mask +#define NXMAC_START_TX_ANTENNA_SET_MASK ((uint32_t)0x00FF0000) +/// START_TX_ANTENNA_SET field LSB position +#define NXMAC_START_TX_ANTENNA_SET_LSB 16 +/// START_TX_ANTENNA_SET field width +#define NXMAC_START_TX_ANTENNA_SET_WIDTH ((uint32_t)0x00000008) +/// START_TX_LSTP field bit +#define NXMAC_START_TX_LSTP_BIT ((uint32_t)0x00002000) +/// START_TX_LSTP field position +#define NXMAC_START_TX_LSTP_POS 13 +/// START_TX_SMOOTHING field bit +#define NXMAC_START_TX_SMOOTHING_BIT ((uint32_t)0x00001000) +/// START_TX_SMOOTHING field position +#define NXMAC_START_TX_SMOOTHING_POS 12 +/// START_TX_SHORT_GI field bit +#define NXMAC_START_TX_SHORT_GI_BIT ((uint32_t)0x00000100) +/// START_TX_SHORT_GI field position +#define NXMAC_START_TX_SHORT_GI_POS 8 +/// START_TX_N_TX field mask +#define NXMAC_START_TX_N_TX_MASK ((uint32_t)0x000000E0) +/// START_TX_N_TX field LSB position +#define NXMAC_START_TX_N_TX_LSB 5 +/// START_TX_N_TX field width +#define NXMAC_START_TX_N_TX_WIDTH ((uint32_t)0x00000003) +/// START_TX_FEC_CODING field bit +#define NXMAC_START_TX_FEC_CODING_BIT ((uint32_t)0x00000010) +/// START_TX_FEC_CODING field position +#define NXMAC_START_TX_FEC_CODING_POS 4 +/// START_TX_STBC field mask +#define NXMAC_START_TX_STBC_MASK ((uint32_t)0x0000000C) +/// START_TX_STBC field LSB position +#define NXMAC_START_TX_STBC_LSB 2 +/// START_TX_STBC field width +#define NXMAC_START_TX_STBC_WIDTH ((uint32_t)0x00000002) +/// START_TX_NUM_EXTN_SS field mask +#define NXMAC_START_TX_NUM_EXTN_SS_MASK ((uint32_t)0x00000003) +/// START_TX_NUM_EXTN_SS field LSB position +#define NXMAC_START_TX_NUM_EXTN_SS_LSB 0 +/// START_TX_NUM_EXTN_SS field width +#define NXMAC_START_TX_NUM_EXTN_SS_WIDTH ((uint32_t)0x00000002) + +/// START_TX_SMM_INDEX field reset value +#define NXMAC_START_TX_SMM_INDEX_RST 0x0 +/// START_TX_ANTENNA_SET field reset value +#define NXMAC_START_TX_ANTENNA_SET_RST 0x0 +/// START_TX_LSTP field reset value +#define NXMAC_START_TX_LSTP_RST 0x0 +/// START_TX_SMOOTHING field reset value +#define NXMAC_START_TX_SMOOTHING_RST 0x0 +/// START_TX_SHORT_GI field reset value +#define NXMAC_START_TX_SHORT_GI_RST 0x0 +/// START_TX_N_TX field reset value +#define NXMAC_START_TX_N_TX_RST 0x0 +/// START_TX_FEC_CODING field reset value +#define NXMAC_START_TX_FEC_CODING_RST 0x0 +/// START_TX_STBC field reset value +#define NXMAC_START_TX_STBC_RST 0x0 +/// START_TX_NUM_EXTN_SS field reset value +#define NXMAC_START_TX_NUM_EXTN_SS_RST 0x0 + +/** + * @brief Constructs a value for the START_TX_3 register given values for its fields + * and writes the value to the register. + * + * @param[in] starttxsmmindex - The value to use for the startTxSMMIndex field. + * @param[in] starttxantennaset - The value to use for the startTxAntennaSet field. + * @param[in] starttxlstp - The value to use for the startTxLSTP field. + * @param[in] starttxsmoothing - The value to use for the startTxSmoothing field. + * @param[in] starttxshortgi - The value to use for the startTxShortGI field. + * @param[in] starttxntx - The value to use for the startTxNTx field. + * @param[in] starttxfeccoding - The value to use for the startTxFecCoding field. + * @param[in] starttxstbc - The value to use for the startTxSTBC field. + * @param[in] starttxnumextnss - The value to use for the startTxNumExtnSS field. + */ +__INLINE void nxmac_start_tx_3_pack(uint8_t starttxsmmindex, uint8_t starttxantennaset, uint8_t starttxlstp, uint8_t starttxsmoothing, uint8_t starttxshortgi, uint8_t starttxntx, uint8_t starttxfeccoding, uint8_t starttxstbc, uint8_t starttxnumextnss) +{ + ASSERT_ERR((((uint32_t)starttxsmmindex << 24) & ~((uint32_t)0xFF000000)) == 0); + ASSERT_ERR((((uint32_t)starttxantennaset << 16) & ~((uint32_t)0x00FF0000)) == 0); + ASSERT_ERR((((uint32_t)starttxlstp << 13) & ~((uint32_t)0x00002000)) == 0); + ASSERT_ERR((((uint32_t)starttxsmoothing << 12) & ~((uint32_t)0x00001000)) == 0); + ASSERT_ERR((((uint32_t)starttxshortgi << 8) & ~((uint32_t)0x00000100)) == 0); + ASSERT_ERR((((uint32_t)starttxntx << 5) & ~((uint32_t)0x000000E0)) == 0); + ASSERT_ERR((((uint32_t)starttxfeccoding << 4) & ~((uint32_t)0x00000010)) == 0); + ASSERT_ERR((((uint32_t)starttxstbc << 2) & ~((uint32_t)0x0000000C)) == 0); + ASSERT_ERR((((uint32_t)starttxnumextnss << 0) & ~((uint32_t)0x00000003)) == 0); + REG_PL_WR(NXMAC_START_TX_3_ADDR, ((uint32_t)starttxsmmindex << 24) | ((uint32_t)starttxantennaset << 16) | ((uint32_t)starttxlstp << 13) | ((uint32_t)starttxsmoothing << 12) | ((uint32_t)starttxshortgi << 8) | ((uint32_t)starttxntx << 5) | ((uint32_t)starttxfeccoding << 4) | ((uint32_t)starttxstbc << 2) | ((uint32_t)starttxnumextnss << 0)); +} + +/** + * @brief Unpacks START_TX_3's fields from current value of the START_TX_3 register. + * + * Reads the START_TX_3 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] starttxsmmindex - Will be populated with the current value of this field from the register. + * @param[out] starttxantennaset - Will be populated with the current value of this field from the register. + * @param[out] starttxlstp - Will be populated with the current value of this field from the register. + * @param[out] starttxsmoothing - Will be populated with the current value of this field from the register. + * @param[out] starttxshortgi - Will be populated with the current value of this field from the register. + * @param[out] starttxntx - Will be populated with the current value of this field from the register. + * @param[out] starttxfeccoding - Will be populated with the current value of this field from the register. + * @param[out] starttxstbc - Will be populated with the current value of this field from the register. + * @param[out] starttxnumextnss - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_start_tx_3_unpack(uint8_t *starttxsmmindex, uint8_t *starttxantennaset, uint8_t *starttxlstp, uint8_t *starttxsmoothing, uint8_t *starttxshortgi, uint8_t *starttxntx, uint8_t *starttxfeccoding, uint8_t *starttxstbc, uint8_t *starttxnumextnss) +{ + uint32_t localVal = REG_PL_RD(NXMAC_START_TX_3_ADDR); + + *starttxsmmindex = (localVal & ((uint32_t)0xFF000000)) >> 24; + *starttxantennaset = (localVal & ((uint32_t)0x00FF0000)) >> 16; + *starttxlstp = (localVal & ((uint32_t)0x00002000)) >> 13; + *starttxsmoothing = (localVal & ((uint32_t)0x00001000)) >> 12; + *starttxshortgi = (localVal & ((uint32_t)0x00000100)) >> 8; + *starttxntx = (localVal & ((uint32_t)0x000000E0)) >> 5; + *starttxfeccoding = (localVal & ((uint32_t)0x00000010)) >> 4; + *starttxstbc = (localVal & ((uint32_t)0x0000000C)) >> 2; + *starttxnumextnss = (localVal & ((uint32_t)0x00000003)) >> 0; +} + +/** + * @brief Returns the current value of the startTxSMMIndex field in the START_TX_3 register. + * + * The START_TX_3 register will be read and the startTxSMMIndex field's value will be returned. + * + * @return The current value of the startTxSMMIndex field in the START_TX_3 register. + */ +__INLINE uint8_t nxmac_start_tx_smm_index_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_START_TX_3_ADDR); + return ((localVal & ((uint32_t)0xFF000000)) >> 24); +} + +/** + * @brief Sets the startTxSMMIndex field of the START_TX_3 register. + * + * The START_TX_3 register will be read, modified to contain the new field value, and written. + * + * @param[in] starttxsmmindex - The value to set the field to. + */ +__INLINE void nxmac_start_tx_smm_index_setf(uint8_t starttxsmmindex) +{ + ASSERT_ERR((((uint32_t)starttxsmmindex << 24) & ~((uint32_t)0xFF000000)) == 0); + REG_PL_WR(NXMAC_START_TX_3_ADDR, (REG_PL_RD(NXMAC_START_TX_3_ADDR) & ~((uint32_t)0xFF000000)) | ((uint32_t)starttxsmmindex << 24)); +} + +/** + * @brief Returns the current value of the startTxAntennaSet field in the START_TX_3 register. + * + * The START_TX_3 register will be read and the startTxAntennaSet field's value will be returned. + * + * @return The current value of the startTxAntennaSet field in the START_TX_3 register. + */ +__INLINE uint8_t nxmac_start_tx_antenna_set_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_START_TX_3_ADDR); + return ((localVal & ((uint32_t)0x00FF0000)) >> 16); +} + +/** + * @brief Sets the startTxAntennaSet field of the START_TX_3 register. + * + * The START_TX_3 register will be read, modified to contain the new field value, and written. + * + * @param[in] starttxantennaset - The value to set the field to. + */ +__INLINE void nxmac_start_tx_antenna_set_setf(uint8_t starttxantennaset) +{ + ASSERT_ERR((((uint32_t)starttxantennaset << 16) & ~((uint32_t)0x00FF0000)) == 0); + REG_PL_WR(NXMAC_START_TX_3_ADDR, (REG_PL_RD(NXMAC_START_TX_3_ADDR) & ~((uint32_t)0x00FF0000)) | ((uint32_t)starttxantennaset << 16)); +} + +/** + * @brief Returns the current value of the startTxLSTP field in the START_TX_3 register. + * + * The START_TX_3 register will be read and the startTxLSTP field's value will be returned. + * + * @return The current value of the startTxLSTP field in the START_TX_3 register. + */ +__INLINE uint8_t nxmac_start_tx_lstp_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_START_TX_3_ADDR); + return ((localVal & ((uint32_t)0x00002000)) >> 13); +} + +/** + * @brief Sets the startTxLSTP field of the START_TX_3 register. + * + * The START_TX_3 register will be read, modified to contain the new field value, and written. + * + * @param[in] starttxlstp - The value to set the field to. + */ +__INLINE void nxmac_start_tx_lstp_setf(uint8_t starttxlstp) +{ + ASSERT_ERR((((uint32_t)starttxlstp << 13) & ~((uint32_t)0x00002000)) == 0); + REG_PL_WR(NXMAC_START_TX_3_ADDR, (REG_PL_RD(NXMAC_START_TX_3_ADDR) & ~((uint32_t)0x00002000)) | ((uint32_t)starttxlstp << 13)); +} + +/** + * @brief Returns the current value of the startTxSmoothing field in the START_TX_3 register. + * + * The START_TX_3 register will be read and the startTxSmoothing field's value will be returned. + * + * @return The current value of the startTxSmoothing field in the START_TX_3 register. + */ +__INLINE uint8_t nxmac_start_tx_smoothing_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_START_TX_3_ADDR); + return ((localVal & ((uint32_t)0x00001000)) >> 12); +} + +/** + * @brief Sets the startTxSmoothing field of the START_TX_3 register. + * + * The START_TX_3 register will be read, modified to contain the new field value, and written. + * + * @param[in] starttxsmoothing - The value to set the field to. + */ +__INLINE void nxmac_start_tx_smoothing_setf(uint8_t starttxsmoothing) +{ + ASSERT_ERR((((uint32_t)starttxsmoothing << 12) & ~((uint32_t)0x00001000)) == 0); + REG_PL_WR(NXMAC_START_TX_3_ADDR, (REG_PL_RD(NXMAC_START_TX_3_ADDR) & ~((uint32_t)0x00001000)) | ((uint32_t)starttxsmoothing << 12)); +} + +/** + * @brief Returns the current value of the startTxShortGI field in the START_TX_3 register. + * + * The START_TX_3 register will be read and the startTxShortGI field's value will be returned. + * + * @return The current value of the startTxShortGI field in the START_TX_3 register. + */ +__INLINE uint8_t nxmac_start_tx_short_gi_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_START_TX_3_ADDR); + return ((localVal & ((uint32_t)0x00000100)) >> 8); +} + +/** + * @brief Sets the startTxShortGI field of the START_TX_3 register. + * + * The START_TX_3 register will be read, modified to contain the new field value, and written. + * + * @param[in] starttxshortgi - The value to set the field to. + */ +__INLINE void nxmac_start_tx_short_gi_setf(uint8_t starttxshortgi) +{ + ASSERT_ERR((((uint32_t)starttxshortgi << 8) & ~((uint32_t)0x00000100)) == 0); + REG_PL_WR(NXMAC_START_TX_3_ADDR, (REG_PL_RD(NXMAC_START_TX_3_ADDR) & ~((uint32_t)0x00000100)) | ((uint32_t)starttxshortgi << 8)); +} + +/** + * @brief Returns the current value of the startTxNTx field in the START_TX_3 register. + * + * The START_TX_3 register will be read and the startTxNTx field's value will be returned. + * + * @return The current value of the startTxNTx field in the START_TX_3 register. + */ +__INLINE uint8_t nxmac_start_tx_n_tx_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_START_TX_3_ADDR); + return ((localVal & ((uint32_t)0x000000E0)) >> 5); +} + +/** + * @brief Sets the startTxNTx field of the START_TX_3 register. + * + * The START_TX_3 register will be read, modified to contain the new field value, and written. + * + * @param[in] starttxntx - The value to set the field to. + */ +__INLINE void nxmac_start_tx_n_tx_setf(uint8_t starttxntx) +{ + ASSERT_ERR((((uint32_t)starttxntx << 5) & ~((uint32_t)0x000000E0)) == 0); + REG_PL_WR(NXMAC_START_TX_3_ADDR, (REG_PL_RD(NXMAC_START_TX_3_ADDR) & ~((uint32_t)0x000000E0)) | ((uint32_t)starttxntx << 5)); +} + +/** + * @brief Returns the current value of the startTxFecCoding field in the START_TX_3 register. + * + * The START_TX_3 register will be read and the startTxFecCoding field's value will be returned. + * + * @return The current value of the startTxFecCoding field in the START_TX_3 register. + */ +__INLINE uint8_t nxmac_start_tx_fec_coding_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_START_TX_3_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +/** + * @brief Sets the startTxFecCoding field of the START_TX_3 register. + * + * The START_TX_3 register will be read, modified to contain the new field value, and written. + * + * @param[in] starttxfeccoding - The value to set the field to. + */ +__INLINE void nxmac_start_tx_fec_coding_setf(uint8_t starttxfeccoding) +{ + ASSERT_ERR((((uint32_t)starttxfeccoding << 4) & ~((uint32_t)0x00000010)) == 0); + REG_PL_WR(NXMAC_START_TX_3_ADDR, (REG_PL_RD(NXMAC_START_TX_3_ADDR) & ~((uint32_t)0x00000010)) | ((uint32_t)starttxfeccoding << 4)); +} + +/** + * @brief Returns the current value of the startTxSTBC field in the START_TX_3 register. + * + * The START_TX_3 register will be read and the startTxSTBC field's value will be returned. + * + * @return The current value of the startTxSTBC field in the START_TX_3 register. + */ +__INLINE uint8_t nxmac_start_tx_stbc_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_START_TX_3_ADDR); + return ((localVal & ((uint32_t)0x0000000C)) >> 2); +} + +/** + * @brief Sets the startTxSTBC field of the START_TX_3 register. + * + * The START_TX_3 register will be read, modified to contain the new field value, and written. + * + * @param[in] starttxstbc - The value to set the field to. + */ +__INLINE void nxmac_start_tx_stbc_setf(uint8_t starttxstbc) +{ + ASSERT_ERR((((uint32_t)starttxstbc << 2) & ~((uint32_t)0x0000000C)) == 0); + REG_PL_WR(NXMAC_START_TX_3_ADDR, (REG_PL_RD(NXMAC_START_TX_3_ADDR) & ~((uint32_t)0x0000000C)) | ((uint32_t)starttxstbc << 2)); +} + +/** + * @brief Returns the current value of the startTxNumExtnSS field in the START_TX_3 register. + * + * The START_TX_3 register will be read and the startTxNumExtnSS field's value will be returned. + * + * @return The current value of the startTxNumExtnSS field in the START_TX_3 register. + */ +__INLINE uint8_t nxmac_start_tx_num_extn_ss_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_START_TX_3_ADDR); + return ((localVal & ((uint32_t)0x00000003)) >> 0); +} + +/** + * @brief Sets the startTxNumExtnSS field of the START_TX_3 register. + * + * The START_TX_3 register will be read, modified to contain the new field value, and written. + * + * @param[in] starttxnumextnss - The value to set the field to. + */ +__INLINE void nxmac_start_tx_num_extn_ss_setf(uint8_t starttxnumextnss) +{ + ASSERT_ERR((((uint32_t)starttxnumextnss << 0) & ~((uint32_t)0x00000003)) == 0); + REG_PL_WR(NXMAC_START_TX_3_ADDR, (REG_PL_RD(NXMAC_START_TX_3_ADDR) & ~((uint32_t)0x00000003)) | ((uint32_t)starttxnumextnss << 0)); +} + +/// @} + +/** + * @name TX_BW_CNTRL register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  17:16       maxSupportedBW   0x2
+ *  15:08         aPPDUMaxTime   0xA
+ *     07              dynBWEn   0
+ *  06:04   numTryBWAcquisition   0x1
+ *     03        dropToLowerBW   1
+ *  02:01        defaultBWTXOP   0x0
+ *     00       defaultBWTXOPV   0
+ * 
+ * + * @{ + */ + +/// Address of the TX_BW_CNTRL register +#define NXMAC_TX_BW_CNTRL_ADDR 0xC0000310 +/// Offset of the TX_BW_CNTRL register from the base address +#define NXMAC_TX_BW_CNTRL_OFFSET 0x00000310 +/// Index of the TX_BW_CNTRL register +#define NXMAC_TX_BW_CNTRL_INDEX 0x000000C4 +/// Reset value of the TX_BW_CNTRL register +#define NXMAC_TX_BW_CNTRL_RESET 0x00020A18 + +/** + * @brief Returns the current value of the TX_BW_CNTRL register. + * The TX_BW_CNTRL register will be read and its value returned. + * @return The current value of the TX_BW_CNTRL register. + */ +__INLINE uint32_t nxmac_tx_bw_cntrl_get(void) +{ + return REG_PL_RD(NXMAC_TX_BW_CNTRL_ADDR); +} + +/** + * @brief Sets the TX_BW_CNTRL register to a value. + * The TX_BW_CNTRL register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_tx_bw_cntrl_set(uint32_t value) +{ + REG_PL_WR(NXMAC_TX_BW_CNTRL_ADDR, value); +} + +// field definitions +/// MAX_SUPPORTED_BW field mask +#define NXMAC_MAX_SUPPORTED_BW_MASK ((uint32_t)0x00030000) +/// MAX_SUPPORTED_BW field LSB position +#define NXMAC_MAX_SUPPORTED_BW_LSB 16 +/// MAX_SUPPORTED_BW field width +#define NXMAC_MAX_SUPPORTED_BW_WIDTH ((uint32_t)0x00000002) +/// A_PPDU_MAX_TIME field mask +#define NXMAC_A_PPDU_MAX_TIME_MASK ((uint32_t)0x0000FF00) +/// A_PPDU_MAX_TIME field LSB position +#define NXMAC_A_PPDU_MAX_TIME_LSB 8 +/// A_PPDU_MAX_TIME field width +#define NXMAC_A_PPDU_MAX_TIME_WIDTH ((uint32_t)0x00000008) +/// DYN_BW_EN field bit +#define NXMAC_DYN_BW_EN_BIT ((uint32_t)0x00000080) +/// DYN_BW_EN field position +#define NXMAC_DYN_BW_EN_POS 7 +/// NUM_TRY_BW_ACQUISITION field mask +#define NXMAC_NUM_TRY_BW_ACQUISITION_MASK ((uint32_t)0x00000070) +/// NUM_TRY_BW_ACQUISITION field LSB position +#define NXMAC_NUM_TRY_BW_ACQUISITION_LSB 4 +/// NUM_TRY_BW_ACQUISITION field width +#define NXMAC_NUM_TRY_BW_ACQUISITION_WIDTH ((uint32_t)0x00000003) +/// DROP_TO_LOWER_BW field bit +#define NXMAC_DROP_TO_LOWER_BW_BIT ((uint32_t)0x00000008) +/// DROP_TO_LOWER_BW field position +#define NXMAC_DROP_TO_LOWER_BW_POS 3 +/// DEFAULT_BWTXOP field mask +#define NXMAC_DEFAULT_BWTXOP_MASK ((uint32_t)0x00000006) +/// DEFAULT_BWTXOP field LSB position +#define NXMAC_DEFAULT_BWTXOP_LSB 1 +/// DEFAULT_BWTXOP field width +#define NXMAC_DEFAULT_BWTXOP_WIDTH ((uint32_t)0x00000002) +/// DEFAULT_BWTXOPV field bit +#define NXMAC_DEFAULT_BWTXOPV_BIT ((uint32_t)0x00000001) +/// DEFAULT_BWTXOPV field position +#define NXMAC_DEFAULT_BWTXOPV_POS 0 + +/// MAX_SUPPORTED_BW field reset value +#define NXMAC_MAX_SUPPORTED_BW_RST 0x2 +/// A_PPDU_MAX_TIME field reset value +#define NXMAC_A_PPDU_MAX_TIME_RST 0xA +/// DYN_BW_EN field reset value +#define NXMAC_DYN_BW_EN_RST 0x0 +/// NUM_TRY_BW_ACQUISITION field reset value +#define NXMAC_NUM_TRY_BW_ACQUISITION_RST 0x1 +/// DROP_TO_LOWER_BW field reset value +#define NXMAC_DROP_TO_LOWER_BW_RST 0x1 +/// DEFAULT_BWTXOP field reset value +#define NXMAC_DEFAULT_BWTXOP_RST 0x0 +/// DEFAULT_BWTXOPV field reset value +#define NXMAC_DEFAULT_BWTXOPV_RST 0x0 + +/** + * @brief Constructs a value for the TX_BW_CNTRL register given values for its fields + * and writes the value to the register. + * + * @param[in] maxsupportedbw - The value to use for the maxSupportedBW field. + * @param[in] appdumaxtime - The value to use for the aPPDUMaxTime field. + * @param[in] dynbwen - The value to use for the dynBWEn field. + * @param[in] numtrybwacquisition - The value to use for the numTryBWAcquisition field. + * @param[in] droptolowerbw - The value to use for the dropToLowerBW field. + * @param[in] defaultbwtxop - The value to use for the defaultBWTXOP field. + * @param[in] defaultbwtxopv - The value to use for the defaultBWTXOPV field. + */ +__INLINE void nxmac_tx_bw_cntrl_pack(uint8_t maxsupportedbw, uint8_t appdumaxtime, uint8_t dynbwen, uint8_t numtrybwacquisition, uint8_t droptolowerbw, uint8_t defaultbwtxop, uint8_t defaultbwtxopv) +{ + ASSERT_ERR((((uint32_t)maxsupportedbw << 16) & ~((uint32_t)0x00030000)) == 0); + ASSERT_ERR((((uint32_t)appdumaxtime << 8) & ~((uint32_t)0x0000FF00)) == 0); + ASSERT_ERR((((uint32_t)dynbwen << 7) & ~((uint32_t)0x00000080)) == 0); + ASSERT_ERR((((uint32_t)numtrybwacquisition << 4) & ~((uint32_t)0x00000070)) == 0); + ASSERT_ERR((((uint32_t)droptolowerbw << 3) & ~((uint32_t)0x00000008)) == 0); + ASSERT_ERR((((uint32_t)defaultbwtxop << 1) & ~((uint32_t)0x00000006)) == 0); + ASSERT_ERR((((uint32_t)defaultbwtxopv << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_TX_BW_CNTRL_ADDR, ((uint32_t)maxsupportedbw << 16) | ((uint32_t)appdumaxtime << 8) | ((uint32_t)dynbwen << 7) | ((uint32_t)numtrybwacquisition << 4) | ((uint32_t)droptolowerbw << 3) | ((uint32_t)defaultbwtxop << 1) | ((uint32_t)defaultbwtxopv << 0)); +} + +/** + * @brief Unpacks TX_BW_CNTRL's fields from current value of the TX_BW_CNTRL register. + * + * Reads the TX_BW_CNTRL register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] maxsupportedbw - Will be populated with the current value of this field from the register. + * @param[out] appdumaxtime - Will be populated with the current value of this field from the register. + * @param[out] dynbwen - Will be populated with the current value of this field from the register. + * @param[out] numtrybwacquisition - Will be populated with the current value of this field from the register. + * @param[out] droptolowerbw - Will be populated with the current value of this field from the register. + * @param[out] defaultbwtxop - Will be populated with the current value of this field from the register. + * @param[out] defaultbwtxopv - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_tx_bw_cntrl_unpack(uint8_t *maxsupportedbw, uint8_t *appdumaxtime, uint8_t *dynbwen, uint8_t *numtrybwacquisition, uint8_t *droptolowerbw, uint8_t *defaultbwtxop, uint8_t *defaultbwtxopv) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_BW_CNTRL_ADDR); + + *maxsupportedbw = (localVal & ((uint32_t)0x00030000)) >> 16; + *appdumaxtime = (localVal & ((uint32_t)0x0000FF00)) >> 8; + *dynbwen = (localVal & ((uint32_t)0x00000080)) >> 7; + *numtrybwacquisition = (localVal & ((uint32_t)0x00000070)) >> 4; + *droptolowerbw = (localVal & ((uint32_t)0x00000008)) >> 3; + *defaultbwtxop = (localVal & ((uint32_t)0x00000006)) >> 1; + *defaultbwtxopv = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +/** + * @brief Returns the current value of the maxSupportedBW field in the TX_BW_CNTRL register. + * + * The TX_BW_CNTRL register will be read and the maxSupportedBW field's value will be returned. + * + * @return The current value of the maxSupportedBW field in the TX_BW_CNTRL register. + */ +__INLINE uint8_t nxmac_max_supported_bw_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_BW_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x00030000)) >> 16); +} + +/** + * @brief Sets the maxSupportedBW field of the TX_BW_CNTRL register. + * + * The TX_BW_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] maxsupportedbw - The value to set the field to. + */ +__INLINE void nxmac_max_supported_bw_setf(uint8_t maxsupportedbw) +{ + ASSERT_ERR((((uint32_t)maxsupportedbw << 16) & ~((uint32_t)0x00030000)) == 0); + REG_PL_WR(NXMAC_TX_BW_CNTRL_ADDR, (REG_PL_RD(NXMAC_TX_BW_CNTRL_ADDR) & ~((uint32_t)0x00030000)) | ((uint32_t)maxsupportedbw << 16)); +} + +/** + * @brief Returns the current value of the aPPDUMaxTime field in the TX_BW_CNTRL register. + * + * The TX_BW_CNTRL register will be read and the aPPDUMaxTime field's value will be returned. + * + * @return The current value of the aPPDUMaxTime field in the TX_BW_CNTRL register. + */ +__INLINE uint8_t nxmac_a_ppdu_max_time_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_BW_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x0000FF00)) >> 8); +} + +/** + * @brief Sets the aPPDUMaxTime field of the TX_BW_CNTRL register. + * + * The TX_BW_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] appdumaxtime - The value to set the field to. + */ +__INLINE void nxmac_a_ppdu_max_time_setf(uint8_t appdumaxtime) +{ + ASSERT_ERR((((uint32_t)appdumaxtime << 8) & ~((uint32_t)0x0000FF00)) == 0); + REG_PL_WR(NXMAC_TX_BW_CNTRL_ADDR, (REG_PL_RD(NXMAC_TX_BW_CNTRL_ADDR) & ~((uint32_t)0x0000FF00)) | ((uint32_t)appdumaxtime << 8)); +} + +/** + * @brief Returns the current value of the dynBWEn field in the TX_BW_CNTRL register. + * + * The TX_BW_CNTRL register will be read and the dynBWEn field's value will be returned. + * + * @return The current value of the dynBWEn field in the TX_BW_CNTRL register. + */ +__INLINE uint8_t nxmac_dyn_bw_en_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_BW_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x00000080)) >> 7); +} + +/** + * @brief Sets the dynBWEn field of the TX_BW_CNTRL register. + * + * The TX_BW_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] dynbwen - The value to set the field to. + */ +__INLINE void nxmac_dyn_bw_en_setf(uint8_t dynbwen) +{ + ASSERT_ERR((((uint32_t)dynbwen << 7) & ~((uint32_t)0x00000080)) == 0); + REG_PL_WR(NXMAC_TX_BW_CNTRL_ADDR, (REG_PL_RD(NXMAC_TX_BW_CNTRL_ADDR) & ~((uint32_t)0x00000080)) | ((uint32_t)dynbwen << 7)); +} + +/** + * @brief Returns the current value of the numTryBWAcquisition field in the TX_BW_CNTRL register. + * + * The TX_BW_CNTRL register will be read and the numTryBWAcquisition field's value will be returned. + * + * @return The current value of the numTryBWAcquisition field in the TX_BW_CNTRL register. + */ +__INLINE uint8_t nxmac_num_try_bw_acquisition_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_BW_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x00000070)) >> 4); +} + +/** + * @brief Sets the numTryBWAcquisition field of the TX_BW_CNTRL register. + * + * The TX_BW_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] numtrybwacquisition - The value to set the field to. + */ +__INLINE void nxmac_num_try_bw_acquisition_setf(uint8_t numtrybwacquisition) +{ + ASSERT_ERR((((uint32_t)numtrybwacquisition << 4) & ~((uint32_t)0x00000070)) == 0); + REG_PL_WR(NXMAC_TX_BW_CNTRL_ADDR, (REG_PL_RD(NXMAC_TX_BW_CNTRL_ADDR) & ~((uint32_t)0x00000070)) | ((uint32_t)numtrybwacquisition << 4)); +} + +/** + * @brief Returns the current value of the dropToLowerBW field in the TX_BW_CNTRL register. + * + * The TX_BW_CNTRL register will be read and the dropToLowerBW field's value will be returned. + * + * @return The current value of the dropToLowerBW field in the TX_BW_CNTRL register. + */ +__INLINE uint8_t nxmac_drop_to_lower_bw_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_BW_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +/** + * @brief Sets the dropToLowerBW field of the TX_BW_CNTRL register. + * + * The TX_BW_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] droptolowerbw - The value to set the field to. + */ +__INLINE void nxmac_drop_to_lower_bw_setf(uint8_t droptolowerbw) +{ + ASSERT_ERR((((uint32_t)droptolowerbw << 3) & ~((uint32_t)0x00000008)) == 0); + REG_PL_WR(NXMAC_TX_BW_CNTRL_ADDR, (REG_PL_RD(NXMAC_TX_BW_CNTRL_ADDR) & ~((uint32_t)0x00000008)) | ((uint32_t)droptolowerbw << 3)); +} + +/** + * @brief Returns the current value of the defaultBWTXOP field in the TX_BW_CNTRL register. + * + * The TX_BW_CNTRL register will be read and the defaultBWTXOP field's value will be returned. + * + * @return The current value of the defaultBWTXOP field in the TX_BW_CNTRL register. + */ +__INLINE uint8_t nxmac_default_bwtxop_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_BW_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x00000006)) >> 1); +} + +/** + * @brief Sets the defaultBWTXOP field of the TX_BW_CNTRL register. + * + * The TX_BW_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] defaultbwtxop - The value to set the field to. + */ +__INLINE void nxmac_default_bwtxop_setf(uint8_t defaultbwtxop) +{ + ASSERT_ERR((((uint32_t)defaultbwtxop << 1) & ~((uint32_t)0x00000006)) == 0); + REG_PL_WR(NXMAC_TX_BW_CNTRL_ADDR, (REG_PL_RD(NXMAC_TX_BW_CNTRL_ADDR) & ~((uint32_t)0x00000006)) | ((uint32_t)defaultbwtxop << 1)); +} + +/** + * @brief Returns the current value of the defaultBWTXOPV field in the TX_BW_CNTRL register. + * + * The TX_BW_CNTRL register will be read and the defaultBWTXOPV field's value will be returned. + * + * @return The current value of the defaultBWTXOPV field in the TX_BW_CNTRL register. + */ +__INLINE uint8_t nxmac_default_bwtxopv_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_BW_CNTRL_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/** + * @brief Sets the defaultBWTXOPV field of the TX_BW_CNTRL register. + * + * The TX_BW_CNTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] defaultbwtxopv - The value to set the field to. + */ +__INLINE void nxmac_default_bwtxopv_setf(uint8_t defaultbwtxopv) +{ + ASSERT_ERR((((uint32_t)defaultbwtxopv << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_TX_BW_CNTRL_ADDR, (REG_PL_RD(NXMAC_TX_BW_CNTRL_ADDR) & ~((uint32_t)0x00000001)) | ((uint32_t)defaultbwtxopv << 0)); +} + +/// @} + +/** + * @name HTMCS register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  21:16   bssBasicHTMCSSetUM   0x0
+ *  15:00   bssBasicHTMCSSetEM   0xFFFF
+ * 
+ * + * @{ + */ + +/// Address of the HTMCS register +#define NXMAC_HTMCS_ADDR 0xC0000314 +/// Offset of the HTMCS register from the base address +#define NXMAC_HTMCS_OFFSET 0x00000314 +/// Index of the HTMCS register +#define NXMAC_HTMCS_INDEX 0x000000C5 +/// Reset value of the HTMCS register +#define NXMAC_HTMCS_RESET 0x0000FFFF + +/** + * @brief Returns the current value of the HTMCS register. + * The HTMCS register will be read and its value returned. + * @return The current value of the HTMCS register. + */ +__INLINE uint32_t nxmac_htmcs_get(void) +{ + return REG_PL_RD(NXMAC_HTMCS_ADDR); +} + +/** + * @brief Sets the HTMCS register to a value. + * The HTMCS register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_htmcs_set(uint32_t value) +{ + REG_PL_WR(NXMAC_HTMCS_ADDR, value); +} + +// field definitions +/// BSS_BASIC_HTMCS_SET_UM field mask +#define NXMAC_BSS_BASIC_HTMCS_SET_UM_MASK ((uint32_t)0x003F0000) +/// BSS_BASIC_HTMCS_SET_UM field LSB position +#define NXMAC_BSS_BASIC_HTMCS_SET_UM_LSB 16 +/// BSS_BASIC_HTMCS_SET_UM field width +#define NXMAC_BSS_BASIC_HTMCS_SET_UM_WIDTH ((uint32_t)0x00000006) +/// BSS_BASIC_HTMCS_SET_EM field mask +#define NXMAC_BSS_BASIC_HTMCS_SET_EM_MASK ((uint32_t)0x0000FFFF) +/// BSS_BASIC_HTMCS_SET_EM field LSB position +#define NXMAC_BSS_BASIC_HTMCS_SET_EM_LSB 0 +/// BSS_BASIC_HTMCS_SET_EM field width +#define NXMAC_BSS_BASIC_HTMCS_SET_EM_WIDTH ((uint32_t)0x00000010) + +/// BSS_BASIC_HTMCS_SET_UM field reset value +#define NXMAC_BSS_BASIC_HTMCS_SET_UM_RST 0x0 +/// BSS_BASIC_HTMCS_SET_EM field reset value +#define NXMAC_BSS_BASIC_HTMCS_SET_EM_RST 0xFFFF + +/** + * @brief Constructs a value for the HTMCS register given values for its fields + * and writes the value to the register. + * + * @param[in] bssbasichtmcssetum - The value to use for the bssBasicHTMCSSetUM field. + * @param[in] bssbasichtmcssetem - The value to use for the bssBasicHTMCSSetEM field. + */ +__INLINE void nxmac_htmcs_pack(uint8_t bssbasichtmcssetum, uint16_t bssbasichtmcssetem) +{ + ASSERT_ERR((((uint32_t)bssbasichtmcssetum << 16) & ~((uint32_t)0x003F0000)) == 0); + ASSERT_ERR((((uint32_t)bssbasichtmcssetem << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_PL_WR(NXMAC_HTMCS_ADDR, ((uint32_t)bssbasichtmcssetum << 16) | ((uint32_t)bssbasichtmcssetem << 0)); +} + +/** + * @brief Unpacks HTMCS's fields from current value of the HTMCS register. + * + * Reads the HTMCS register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] bssbasichtmcssetum - Will be populated with the current value of this field from the register. + * @param[out] bssbasichtmcssetem - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_htmcs_unpack(uint8_t *bssbasichtmcssetum, uint16_t *bssbasichtmcssetem) +{ + uint32_t localVal = REG_PL_RD(NXMAC_HTMCS_ADDR); + + *bssbasichtmcssetum = (localVal & ((uint32_t)0x003F0000)) >> 16; + *bssbasichtmcssetem = (localVal & ((uint32_t)0x0000FFFF)) >> 0; +} + +/** + * @brief Returns the current value of the bssBasicHTMCSSetUM field in the HTMCS register. + * + * The HTMCS register will be read and the bssBasicHTMCSSetUM field's value will be returned. + * + * @return The current value of the bssBasicHTMCSSetUM field in the HTMCS register. + */ +__INLINE uint8_t nxmac_bss_basic_htmcs_set_um_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_HTMCS_ADDR); + return ((localVal & ((uint32_t)0x003F0000)) >> 16); +} + +/** + * @brief Sets the bssBasicHTMCSSetUM field of the HTMCS register. + * + * The HTMCS register will be read, modified to contain the new field value, and written. + * + * @param[in] bssbasichtmcssetum - The value to set the field to. + */ +__INLINE void nxmac_bss_basic_htmcs_set_um_setf(uint8_t bssbasichtmcssetum) +{ + ASSERT_ERR((((uint32_t)bssbasichtmcssetum << 16) & ~((uint32_t)0x003F0000)) == 0); + REG_PL_WR(NXMAC_HTMCS_ADDR, (REG_PL_RD(NXMAC_HTMCS_ADDR) & ~((uint32_t)0x003F0000)) | ((uint32_t)bssbasichtmcssetum << 16)); +} + +/** + * @brief Returns the current value of the bssBasicHTMCSSetEM field in the HTMCS register. + * + * The HTMCS register will be read and the bssBasicHTMCSSetEM field's value will be returned. + * + * @return The current value of the bssBasicHTMCSSetEM field in the HTMCS register. + */ +__INLINE uint16_t nxmac_bss_basic_htmcs_set_em_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_HTMCS_ADDR); + return ((localVal & ((uint32_t)0x0000FFFF)) >> 0); +} + +/** + * @brief Sets the bssBasicHTMCSSetEM field of the HTMCS register. + * + * The HTMCS register will be read, modified to contain the new field value, and written. + * + * @param[in] bssbasichtmcssetem - The value to set the field to. + */ +__INLINE void nxmac_bss_basic_htmcs_set_em_setf(uint16_t bssbasichtmcssetem) +{ + ASSERT_ERR((((uint32_t)bssbasichtmcssetem << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_PL_WR(NXMAC_HTMCS_ADDR, (REG_PL_RD(NXMAC_HTMCS_ADDR) & ~((uint32_t)0x0000FFFF)) | ((uint32_t)bssbasichtmcssetem << 0)); +} + +/// @} + +/** + * @name VHTMCS register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00    bssBasicVHTMCSSet   0xFFFF
+ * 
+ * + * @{ + */ + +/// Address of the VHTMCS register +#define NXMAC_VHTMCS_ADDR 0xC000031C +/// Offset of the VHTMCS register from the base address +#define NXMAC_VHTMCS_OFFSET 0x0000031C +/// Index of the VHTMCS register +#define NXMAC_VHTMCS_INDEX 0x000000C7 +/// Reset value of the VHTMCS register +#define NXMAC_VHTMCS_RESET 0x0000FFFF + +/** + * @brief Returns the current value of the VHTMCS register. + * The VHTMCS register will be read and its value returned. + * @return The current value of the VHTMCS register. + */ +__INLINE uint32_t nxmac_vhtmcs_get(void) +{ + return REG_PL_RD(NXMAC_VHTMCS_ADDR); +} + +/** + * @brief Sets the VHTMCS register to a value. + * The VHTMCS register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_vhtmcs_set(uint32_t value) +{ + REG_PL_WR(NXMAC_VHTMCS_ADDR, value); +} + +// field definitions +/// BSS_BASIC_VHTMCS_SET field mask +#define NXMAC_BSS_BASIC_VHTMCS_SET_MASK ((uint32_t)0x0000FFFF) +/// BSS_BASIC_VHTMCS_SET field LSB position +#define NXMAC_BSS_BASIC_VHTMCS_SET_LSB 0 +/// BSS_BASIC_VHTMCS_SET field width +#define NXMAC_BSS_BASIC_VHTMCS_SET_WIDTH ((uint32_t)0x00000010) + +/// BSS_BASIC_VHTMCS_SET field reset value +#define NXMAC_BSS_BASIC_VHTMCS_SET_RST 0xFFFF + +/** + * @brief Returns the current value of the bssBasicVHTMCSSet field in the VHTMCS register. + * + * The VHTMCS register will be read and the bssBasicVHTMCSSet field's value will be returned. + * + * @return The current value of the bssBasicVHTMCSSet field in the VHTMCS register. + */ +__INLINE uint16_t nxmac_bss_basic_vhtmcs_set_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_VHTMCS_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the bssBasicVHTMCSSet field of the VHTMCS register. + * + * The VHTMCS register will be read, modified to contain the new field value, and written. + * + * @param[in] bssbasicvhtmcsset - The value to set the field to. + */ +__INLINE void nxmac_bss_basic_vhtmcs_set_setf(uint16_t bssbasicvhtmcsset) +{ + ASSERT_ERR((((uint32_t)bssbasicvhtmcsset << 0) & ~((uint32_t)0x0000FFFF)) == 0); + REG_PL_WR(NXMAC_VHTMCS_ADDR, (uint32_t)bssbasicvhtmcsset << 0); +} + +/// @} + +/** + * @name LSTP register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     00          supportLSTP   0
+ * 
+ * + * @{ + */ + +/// Address of the LSTP register +#define NXMAC_LSTP_ADDR 0xC0000320 +/// Offset of the LSTP register from the base address +#define NXMAC_LSTP_OFFSET 0x00000320 +/// Index of the LSTP register +#define NXMAC_LSTP_INDEX 0x000000C8 +/// Reset value of the LSTP register +#define NXMAC_LSTP_RESET 0x00000000 + +/** + * @brief Returns the current value of the LSTP register. + * The LSTP register will be read and its value returned. + * @return The current value of the LSTP register. + */ +__INLINE uint32_t nxmac_lstp_get(void) +{ + return REG_PL_RD(NXMAC_LSTP_ADDR); +} + +/** + * @brief Sets the LSTP register to a value. + * The LSTP register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_lstp_set(uint32_t value) +{ + REG_PL_WR(NXMAC_LSTP_ADDR, value); +} + +// field definitions +/// SUPPORT_LSTP field bit +#define NXMAC_SUPPORT_LSTP_BIT ((uint32_t)0x00000001) +/// SUPPORT_LSTP field position +#define NXMAC_SUPPORT_LSTP_POS 0 + +/// SUPPORT_LSTP field reset value +#define NXMAC_SUPPORT_LSTP_RST 0x0 + +/** + * @brief Returns the current value of the supportLSTP field in the LSTP register. + * + * The LSTP register will be read and the supportLSTP field's value will be returned. + * + * @return The current value of the supportLSTP field in the LSTP register. + */ +__INLINE uint8_t nxmac_support_lstp_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_LSTP_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x00000001)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the supportLSTP field of the LSTP register. + * + * The LSTP register will be read, modified to contain the new field value, and written. + * + * @param[in] supportlstp - The value to set the field to. + */ +__INLINE void nxmac_support_lstp_setf(uint8_t supportlstp) +{ + ASSERT_ERR((((uint32_t)supportlstp << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_LSTP_ADDR, (uint32_t)supportlstp << 0); +} + +/// @} + +#if RW_BFMEE_EN +/** + * @name BFMEE_CONTROL register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  27:25         bfrFormatMod   0x4
+ *     24           bfrShortGI   0
+ *  23:16               bfrMCS   0x84
+ *  10:08              bfmeeNc   0x1
+ *  07:05              bfmeeNr   0x1
+ *  04:03        bfmeeGrouping   0x0
+ *     02        bfmeeCodebook   1
+ *     01       bfmeeMUSupport   0
+ *     00          bfmeeEnable   0
+ * 
+ * + * @{ + */ + +/// Address of the BFMEE_CONTROL register +#define NXMAC_BFMEE_CONTROL_ADDR 0xC0000350 +/// Offset of the BFMEE_CONTROL register from the base address +#define NXMAC_BFMEE_CONTROL_OFFSET 0x00000350 +/// Index of the BFMEE_CONTROL register +#define NXMAC_BFMEE_CONTROL_INDEX 0x000000D4 +/// Reset value of the BFMEE_CONTROL register +#define NXMAC_BFMEE_CONTROL_RESET 0x08840124 + +/** + * @brief Returns the current value of the BFMEE_CONTROL register. + * The BFMEE_CONTROL register will be read and its value returned. + * @return The current value of the BFMEE_CONTROL register. + */ +__INLINE uint32_t nxmac_bfmee_control_get(void) +{ + return REG_PL_RD(NXMAC_BFMEE_CONTROL_ADDR); +} + +/** + * @brief Sets the BFMEE_CONTROL register to a value. + * The BFMEE_CONTROL register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_bfmee_control_set(uint32_t value) +{ + REG_PL_WR(NXMAC_BFMEE_CONTROL_ADDR, value); +} + +// field definitions +/// BFR_FORMAT_MOD field mask +#define NXMAC_BFR_FORMAT_MOD_MASK ((uint32_t)0x0E000000) +/// BFR_FORMAT_MOD field LSB position +#define NXMAC_BFR_FORMAT_MOD_LSB 25 +/// BFR_FORMAT_MOD field width +#define NXMAC_BFR_FORMAT_MOD_WIDTH ((uint32_t)0x00000003) +/// BFR_SHORT_GI field bit +#define NXMAC_BFR_SHORT_GI_BIT ((uint32_t)0x01000000) +/// BFR_SHORT_GI field position +#define NXMAC_BFR_SHORT_GI_POS 24 +/// BFR_MCS field mask +#define NXMAC_BFR_MCS_MASK ((uint32_t)0x00FF0000) +/// BFR_MCS field LSB position +#define NXMAC_BFR_MCS_LSB 16 +/// BFR_MCS field width +#define NXMAC_BFR_MCS_WIDTH ((uint32_t)0x00000008) +/// BFMEE_NC field mask +#define NXMAC_BFMEE_NC_MASK ((uint32_t)0x00000700) +/// BFMEE_NC field LSB position +#define NXMAC_BFMEE_NC_LSB 8 +/// BFMEE_NC field width +#define NXMAC_BFMEE_NC_WIDTH ((uint32_t)0x00000003) +/// BFMEE_NR field mask +#define NXMAC_BFMEE_NR_MASK ((uint32_t)0x000000E0) +/// BFMEE_NR field LSB position +#define NXMAC_BFMEE_NR_LSB 5 +/// BFMEE_NR field width +#define NXMAC_BFMEE_NR_WIDTH ((uint32_t)0x00000003) +/// BFMEE_GROUPING field mask +#define NXMAC_BFMEE_GROUPING_MASK ((uint32_t)0x00000018) +/// BFMEE_GROUPING field LSB position +#define NXMAC_BFMEE_GROUPING_LSB 3 +/// BFMEE_GROUPING field width +#define NXMAC_BFMEE_GROUPING_WIDTH ((uint32_t)0x00000002) +/// BFMEE_CODEBOOK field bit +#define NXMAC_BFMEE_CODEBOOK_BIT ((uint32_t)0x00000004) +/// BFMEE_CODEBOOK field position +#define NXMAC_BFMEE_CODEBOOK_POS 2 +/// BFMEE_MU_SUPPORT field bit +#define NXMAC_BFMEE_MU_SUPPORT_BIT ((uint32_t)0x00000002) +/// BFMEE_MU_SUPPORT field position +#define NXMAC_BFMEE_MU_SUPPORT_POS 1 +/// BFMEE_ENABLE field bit +#define NXMAC_BFMEE_ENABLE_BIT ((uint32_t)0x00000001) +/// BFMEE_ENABLE field position +#define NXMAC_BFMEE_ENABLE_POS 0 + +/// BFR_FORMAT_MOD field reset value +#define NXMAC_BFR_FORMAT_MOD_RST 0x4 +/// BFR_SHORT_GI field reset value +#define NXMAC_BFR_SHORT_GI_RST 0x0 +/// BFR_MCS field reset value +#define NXMAC_BFR_MCS_RST 0x84 +/// BFMEE_NC field reset value +#define NXMAC_BFMEE_NC_RST 0x1 +/// BFMEE_NR field reset value +#define NXMAC_BFMEE_NR_RST 0x1 +/// BFMEE_GROUPING field reset value +#define NXMAC_BFMEE_GROUPING_RST 0x0 +/// BFMEE_CODEBOOK field reset value +#define NXMAC_BFMEE_CODEBOOK_RST 0x1 +/// BFMEE_MU_SUPPORT field reset value +#define NXMAC_BFMEE_MU_SUPPORT_RST 0x0 +/// BFMEE_ENABLE field reset value +#define NXMAC_BFMEE_ENABLE_RST 0x0 + +/** + * @brief Constructs a value for the BFMEE_CONTROL register given values for its fields + * and writes the value to the register. + * + * @param[in] bfrformatmod - The value to use for the bfrFormatMod field. + * @param[in] bfrshortgi - The value to use for the bfrShortGI field. + * @param[in] bfrmcs - The value to use for the bfrMCS field. + * @param[in] bfmeenc - The value to use for the bfmeeNc field. + * @param[in] bfmeenr - The value to use for the bfmeeNr field. + * @param[in] bfmeegrouping - The value to use for the bfmeeGrouping field. + * @param[in] bfmeecodebook - The value to use for the bfmeeCodebook field. + * @param[in] bfmeemusupport - The value to use for the bfmeeMUSupport field. + * @param[in] bfmeeenable - The value to use for the bfmeeEnable field. + */ +__INLINE void nxmac_bfmee_control_pack(uint8_t bfrformatmod, uint8_t bfrshortgi, uint8_t bfrmcs, uint8_t bfmeenc, uint8_t bfmeenr, uint8_t bfmeegrouping, uint8_t bfmeecodebook, uint8_t bfmeemusupport, uint8_t bfmeeenable) +{ + ASSERT_ERR((((uint32_t)bfrformatmod << 25) & ~((uint32_t)0x0E000000)) == 0); + ASSERT_ERR((((uint32_t)bfrshortgi << 24) & ~((uint32_t)0x01000000)) == 0); + ASSERT_ERR((((uint32_t)bfrmcs << 16) & ~((uint32_t)0x00FF0000)) == 0); + ASSERT_ERR((((uint32_t)bfmeenc << 8) & ~((uint32_t)0x00000700)) == 0); + ASSERT_ERR((((uint32_t)bfmeenr << 5) & ~((uint32_t)0x000000E0)) == 0); + ASSERT_ERR((((uint32_t)bfmeegrouping << 3) & ~((uint32_t)0x00000018)) == 0); + ASSERT_ERR((((uint32_t)bfmeecodebook << 2) & ~((uint32_t)0x00000004)) == 0); + ASSERT_ERR((((uint32_t)bfmeemusupport << 1) & ~((uint32_t)0x00000002)) == 0); + ASSERT_ERR((((uint32_t)bfmeeenable << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_BFMEE_CONTROL_ADDR, ((uint32_t)bfrformatmod << 25) | ((uint32_t)bfrshortgi << 24) | ((uint32_t)bfrmcs << 16) | ((uint32_t)bfmeenc << 8) | ((uint32_t)bfmeenr << 5) | ((uint32_t)bfmeegrouping << 3) | ((uint32_t)bfmeecodebook << 2) | ((uint32_t)bfmeemusupport << 1) | ((uint32_t)bfmeeenable << 0)); +} + +/** + * @brief Unpacks BFMEE_CONTROL's fields from current value of the BFMEE_CONTROL register. + * + * Reads the BFMEE_CONTROL register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] bfrformatmod - Will be populated with the current value of this field from the register. + * @param[out] bfrshortgi - Will be populated with the current value of this field from the register. + * @param[out] bfrmcs - Will be populated with the current value of this field from the register. + * @param[out] bfmeenc - Will be populated with the current value of this field from the register. + * @param[out] bfmeenr - Will be populated with the current value of this field from the register. + * @param[out] bfmeegrouping - Will be populated with the current value of this field from the register. + * @param[out] bfmeecodebook - Will be populated with the current value of this field from the register. + * @param[out] bfmeemusupport - Will be populated with the current value of this field from the register. + * @param[out] bfmeeenable - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_bfmee_control_unpack(uint8_t *bfrformatmod, uint8_t *bfrshortgi, uint8_t *bfrmcs, uint8_t *bfmeenc, uint8_t *bfmeenr, uint8_t *bfmeegrouping, uint8_t *bfmeecodebook, uint8_t *bfmeemusupport, uint8_t *bfmeeenable) +{ + uint32_t localVal = REG_PL_RD(NXMAC_BFMEE_CONTROL_ADDR); + + *bfrformatmod = (localVal & ((uint32_t)0x0E000000)) >> 25; + *bfrshortgi = (localVal & ((uint32_t)0x01000000)) >> 24; + *bfrmcs = (localVal & ((uint32_t)0x00FF0000)) >> 16; + *bfmeenc = (localVal & ((uint32_t)0x00000700)) >> 8; + *bfmeenr = (localVal & ((uint32_t)0x000000E0)) >> 5; + *bfmeegrouping = (localVal & ((uint32_t)0x00000018)) >> 3; + *bfmeecodebook = (localVal & ((uint32_t)0x00000004)) >> 2; + *bfmeemusupport = (localVal & ((uint32_t)0x00000002)) >> 1; + *bfmeeenable = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +/** + * @brief Returns the current value of the bfrFormatMod field in the BFMEE_CONTROL register. + * + * The BFMEE_CONTROL register will be read and the bfrFormatMod field's value will be returned. + * + * @return The current value of the bfrFormatMod field in the BFMEE_CONTROL register. + */ +__INLINE uint8_t nxmac_bfr_format_mod_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_BFMEE_CONTROL_ADDR); + return ((localVal & ((uint32_t)0x0E000000)) >> 25); +} + +/** + * @brief Sets the bfrFormatMod field of the BFMEE_CONTROL register. + * + * The BFMEE_CONTROL register will be read, modified to contain the new field value, and written. + * + * @param[in] bfrformatmod - The value to set the field to. + */ +__INLINE void nxmac_bfr_format_mod_setf(uint8_t bfrformatmod) +{ + ASSERT_ERR((((uint32_t)bfrformatmod << 25) & ~((uint32_t)0x0E000000)) == 0); + REG_PL_WR(NXMAC_BFMEE_CONTROL_ADDR, (REG_PL_RD(NXMAC_BFMEE_CONTROL_ADDR) & ~((uint32_t)0x0E000000)) | ((uint32_t)bfrformatmod << 25)); +} + +/** + * @brief Returns the current value of the bfrShortGI field in the BFMEE_CONTROL register. + * + * The BFMEE_CONTROL register will be read and the bfrShortGI field's value will be returned. + * + * @return The current value of the bfrShortGI field in the BFMEE_CONTROL register. + */ +__INLINE uint8_t nxmac_bfr_short_gi_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_BFMEE_CONTROL_ADDR); + return ((localVal & ((uint32_t)0x01000000)) >> 24); +} + +/** + * @brief Sets the bfrShortGI field of the BFMEE_CONTROL register. + * + * The BFMEE_CONTROL register will be read, modified to contain the new field value, and written. + * + * @param[in] bfrshortgi - The value to set the field to. + */ +__INLINE void nxmac_bfr_short_gi_setf(uint8_t bfrshortgi) +{ + ASSERT_ERR((((uint32_t)bfrshortgi << 24) & ~((uint32_t)0x01000000)) == 0); + REG_PL_WR(NXMAC_BFMEE_CONTROL_ADDR, (REG_PL_RD(NXMAC_BFMEE_CONTROL_ADDR) & ~((uint32_t)0x01000000)) | ((uint32_t)bfrshortgi << 24)); +} + +/** + * @brief Returns the current value of the bfrMCS field in the BFMEE_CONTROL register. + * + * The BFMEE_CONTROL register will be read and the bfrMCS field's value will be returned. + * + * @return The current value of the bfrMCS field in the BFMEE_CONTROL register. + */ +__INLINE uint8_t nxmac_bfr_mcs_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_BFMEE_CONTROL_ADDR); + return ((localVal & ((uint32_t)0x00FF0000)) >> 16); +} + +/** + * @brief Sets the bfrMCS field of the BFMEE_CONTROL register. + * + * The BFMEE_CONTROL register will be read, modified to contain the new field value, and written. + * + * @param[in] bfrmcs - The value to set the field to. + */ +__INLINE void nxmac_bfr_mcs_setf(uint8_t bfrmcs) +{ + ASSERT_ERR((((uint32_t)bfrmcs << 16) & ~((uint32_t)0x00FF0000)) == 0); + REG_PL_WR(NXMAC_BFMEE_CONTROL_ADDR, (REG_PL_RD(NXMAC_BFMEE_CONTROL_ADDR) & ~((uint32_t)0x00FF0000)) | ((uint32_t)bfrmcs << 16)); +} + +/** + * @brief Returns the current value of the bfmeeNc field in the BFMEE_CONTROL register. + * + * The BFMEE_CONTROL register will be read and the bfmeeNc field's value will be returned. + * + * @return The current value of the bfmeeNc field in the BFMEE_CONTROL register. + */ +__INLINE uint8_t nxmac_bfmee_nc_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_BFMEE_CONTROL_ADDR); + return ((localVal & ((uint32_t)0x00000700)) >> 8); +} + +/** + * @brief Sets the bfmeeNc field of the BFMEE_CONTROL register. + * + * The BFMEE_CONTROL register will be read, modified to contain the new field value, and written. + * + * @param[in] bfmeenc - The value to set the field to. + */ +__INLINE void nxmac_bfmee_nc_setf(uint8_t bfmeenc) +{ + ASSERT_ERR((((uint32_t)bfmeenc << 8) & ~((uint32_t)0x00000700)) == 0); + REG_PL_WR(NXMAC_BFMEE_CONTROL_ADDR, (REG_PL_RD(NXMAC_BFMEE_CONTROL_ADDR) & ~((uint32_t)0x00000700)) | ((uint32_t)bfmeenc << 8)); +} + +/** + * @brief Returns the current value of the bfmeeNr field in the BFMEE_CONTROL register. + * + * The BFMEE_CONTROL register will be read and the bfmeeNr field's value will be returned. + * + * @return The current value of the bfmeeNr field in the BFMEE_CONTROL register. + */ +__INLINE uint8_t nxmac_bfmee_nr_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_BFMEE_CONTROL_ADDR); + return ((localVal & ((uint32_t)0x000000E0)) >> 5); +} + +/** + * @brief Sets the bfmeeNr field of the BFMEE_CONTROL register. + * + * The BFMEE_CONTROL register will be read, modified to contain the new field value, and written. + * + * @param[in] bfmeenr - The value to set the field to. + */ +__INLINE void nxmac_bfmee_nr_setf(uint8_t bfmeenr) +{ + ASSERT_ERR((((uint32_t)bfmeenr << 5) & ~((uint32_t)0x000000E0)) == 0); + REG_PL_WR(NXMAC_BFMEE_CONTROL_ADDR, (REG_PL_RD(NXMAC_BFMEE_CONTROL_ADDR) & ~((uint32_t)0x000000E0)) | ((uint32_t)bfmeenr << 5)); +} + +/** + * @brief Returns the current value of the bfmeeGrouping field in the BFMEE_CONTROL register. + * + * The BFMEE_CONTROL register will be read and the bfmeeGrouping field's value will be returned. + * + * @return The current value of the bfmeeGrouping field in the BFMEE_CONTROL register. + */ +__INLINE uint8_t nxmac_bfmee_grouping_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_BFMEE_CONTROL_ADDR); + return ((localVal & ((uint32_t)0x00000018)) >> 3); +} + +/** + * @brief Sets the bfmeeGrouping field of the BFMEE_CONTROL register. + * + * The BFMEE_CONTROL register will be read, modified to contain the new field value, and written. + * + * @param[in] bfmeegrouping - The value to set the field to. + */ +__INLINE void nxmac_bfmee_grouping_setf(uint8_t bfmeegrouping) +{ + ASSERT_ERR((((uint32_t)bfmeegrouping << 3) & ~((uint32_t)0x00000018)) == 0); + REG_PL_WR(NXMAC_BFMEE_CONTROL_ADDR, (REG_PL_RD(NXMAC_BFMEE_CONTROL_ADDR) & ~((uint32_t)0x00000018)) | ((uint32_t)bfmeegrouping << 3)); +} + +/** + * @brief Returns the current value of the bfmeeCodebook field in the BFMEE_CONTROL register. + * + * The BFMEE_CONTROL register will be read and the bfmeeCodebook field's value will be returned. + * + * @return The current value of the bfmeeCodebook field in the BFMEE_CONTROL register. + */ +__INLINE uint8_t nxmac_bfmee_codebook_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_BFMEE_CONTROL_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +/** + * @brief Sets the bfmeeCodebook field of the BFMEE_CONTROL register. + * + * The BFMEE_CONTROL register will be read, modified to contain the new field value, and written. + * + * @param[in] bfmeecodebook - The value to set the field to. + */ +__INLINE void nxmac_bfmee_codebook_setf(uint8_t bfmeecodebook) +{ + ASSERT_ERR((((uint32_t)bfmeecodebook << 2) & ~((uint32_t)0x00000004)) == 0); + REG_PL_WR(NXMAC_BFMEE_CONTROL_ADDR, (REG_PL_RD(NXMAC_BFMEE_CONTROL_ADDR) & ~((uint32_t)0x00000004)) | ((uint32_t)bfmeecodebook << 2)); +} + +/** + * @brief Returns the current value of the bfmeeMUSupport field in the BFMEE_CONTROL register. + * + * The BFMEE_CONTROL register will be read and the bfmeeMUSupport field's value will be returned. + * + * @return The current value of the bfmeeMUSupport field in the BFMEE_CONTROL register. + */ +__INLINE uint8_t nxmac_bfmee_mu_support_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_BFMEE_CONTROL_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +/** + * @brief Sets the bfmeeMUSupport field of the BFMEE_CONTROL register. + * + * The BFMEE_CONTROL register will be read, modified to contain the new field value, and written. + * + * @param[in] bfmeemusupport - The value to set the field to. + */ +__INLINE void nxmac_bfmee_mu_support_setf(uint8_t bfmeemusupport) +{ + ASSERT_ERR((((uint32_t)bfmeemusupport << 1) & ~((uint32_t)0x00000002)) == 0); + REG_PL_WR(NXMAC_BFMEE_CONTROL_ADDR, (REG_PL_RD(NXMAC_BFMEE_CONTROL_ADDR) & ~((uint32_t)0x00000002)) | ((uint32_t)bfmeemusupport << 1)); +} + +/** + * @brief Returns the current value of the bfmeeEnable field in the BFMEE_CONTROL register. + * + * The BFMEE_CONTROL register will be read and the bfmeeEnable field's value will be returned. + * + * @return The current value of the bfmeeEnable field in the BFMEE_CONTROL register. + */ +__INLINE uint8_t nxmac_bfmee_enable_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_BFMEE_CONTROL_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/** + * @brief Sets the bfmeeEnable field of the BFMEE_CONTROL register. + * + * The BFMEE_CONTROL register will be read, modified to contain the new field value, and written. + * + * @param[in] bfmeeenable - The value to set the field to. + */ +__INLINE void nxmac_bfmee_enable_setf(uint8_t bfmeeenable) +{ + ASSERT_ERR((((uint32_t)bfmeeenable << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_BFMEE_CONTROL_ADDR, (REG_PL_RD(NXMAC_BFMEE_CONTROL_ADDR) & ~((uint32_t)0x00000001)) | ((uint32_t)bfmeeenable << 0)); +} + +#endif // RW_BFMEE_EN +/// @} + +#if RW_WLAN_COEX_EN +/** + * @name COEX_CONTROL register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:28     coexForceWlanPTI   0x0
+ *     27   coexForceWlanPTIToggle   0
+ *     26   coexForceWlanChanBw   0
+ *     25      coexForceWlanRx   0
+ *     24      coexForceWlanTx   0
+ *  22:16     coexWlanChanFreq   0x0
+ *     12   coexWlanChanOffset   0
+ *  07:06   coexAutoPTIAdjIncr   0x1
+ *     05   coexAutoPTIAdjEnable   1
+ *     04      coexForceEnable   0
+ *     03   coexPostponeTxEnable   1
+ *     02   coexPHYRxAbortEnable   0
+ *     01   coexPHYTxAbortEnable   0
+ *     00           coexEnable   0
+ * 
+ * + * @{ + */ + +/// Address of the COEX_CONTROL register +#define NXMAC_COEX_CONTROL_ADDR 0xC0000400 +/// Offset of the COEX_CONTROL register from the base address +#define NXMAC_COEX_CONTROL_OFFSET 0x00000400 +/// Index of the COEX_CONTROL register +#define NXMAC_COEX_CONTROL_INDEX 0x00000100 +/// Reset value of the COEX_CONTROL register +#define NXMAC_COEX_CONTROL_RESET 0x00000068 + +/** + * @brief Returns the current value of the COEX_CONTROL register. + * The COEX_CONTROL register will be read and its value returned. + * @return The current value of the COEX_CONTROL register. + */ +__INLINE uint32_t nxmac_coex_control_get(void) +{ + return REG_PL_RD(NXMAC_COEX_CONTROL_ADDR); +} + +/** + * @brief Sets the COEX_CONTROL register to a value. + * The COEX_CONTROL register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_coex_control_set(uint32_t value) +{ + REG_PL_WR(NXMAC_COEX_CONTROL_ADDR, value); +} + +// field definitions +/// COEX_FORCE_WLAN_PTI field mask +#define NXMAC_COEX_FORCE_WLAN_PTI_MASK ((uint32_t)0xF0000000) +/// COEX_FORCE_WLAN_PTI field LSB position +#define NXMAC_COEX_FORCE_WLAN_PTI_LSB 28 +/// COEX_FORCE_WLAN_PTI field width +#define NXMAC_COEX_FORCE_WLAN_PTI_WIDTH ((uint32_t)0x00000004) +/// COEX_FORCE_WLAN_PTI_TOGGLE field bit +#define NXMAC_COEX_FORCE_WLAN_PTI_TOGGLE_BIT ((uint32_t)0x08000000) +/// COEX_FORCE_WLAN_PTI_TOGGLE field position +#define NXMAC_COEX_FORCE_WLAN_PTI_TOGGLE_POS 27 +/// COEX_FORCE_WLAN_CHAN_BW field bit +#define NXMAC_COEX_FORCE_WLAN_CHAN_BW_BIT ((uint32_t)0x04000000) +/// COEX_FORCE_WLAN_CHAN_BW field position +#define NXMAC_COEX_FORCE_WLAN_CHAN_BW_POS 26 +/// COEX_FORCE_WLAN_RX field bit +#define NXMAC_COEX_FORCE_WLAN_RX_BIT ((uint32_t)0x02000000) +/// COEX_FORCE_WLAN_RX field position +#define NXMAC_COEX_FORCE_WLAN_RX_POS 25 +/// COEX_FORCE_WLAN_TX field bit +#define NXMAC_COEX_FORCE_WLAN_TX_BIT ((uint32_t)0x01000000) +/// COEX_FORCE_WLAN_TX field position +#define NXMAC_COEX_FORCE_WLAN_TX_POS 24 +/// COEX_WLAN_CHAN_FREQ field mask +#define NXMAC_COEX_WLAN_CHAN_FREQ_MASK ((uint32_t)0x007F0000) +/// COEX_WLAN_CHAN_FREQ field LSB position +#define NXMAC_COEX_WLAN_CHAN_FREQ_LSB 16 +/// COEX_WLAN_CHAN_FREQ field width +#define NXMAC_COEX_WLAN_CHAN_FREQ_WIDTH ((uint32_t)0x00000007) +/// COEX_WLAN_CHAN_OFFSET field bit +#define NXMAC_COEX_WLAN_CHAN_OFFSET_BIT ((uint32_t)0x00001000) +/// COEX_WLAN_CHAN_OFFSET field position +#define NXMAC_COEX_WLAN_CHAN_OFFSET_POS 12 +/// COEX_AUTO_PTI_ADJ_INCR field mask +#define NXMAC_COEX_AUTO_PTI_ADJ_INCR_MASK ((uint32_t)0x000000C0) +/// COEX_AUTO_PTI_ADJ_INCR field LSB position +#define NXMAC_COEX_AUTO_PTI_ADJ_INCR_LSB 6 +/// COEX_AUTO_PTI_ADJ_INCR field width +#define NXMAC_COEX_AUTO_PTI_ADJ_INCR_WIDTH ((uint32_t)0x00000002) +/// COEX_AUTO_PTI_ADJ_ENABLE field bit +#define NXMAC_COEX_AUTO_PTI_ADJ_ENABLE_BIT ((uint32_t)0x00000020) +/// COEX_AUTO_PTI_ADJ_ENABLE field position +#define NXMAC_COEX_AUTO_PTI_ADJ_ENABLE_POS 5 +/// COEX_FORCE_ENABLE field bit +#define NXMAC_COEX_FORCE_ENABLE_BIT ((uint32_t)0x00000010) +/// COEX_FORCE_ENABLE field position +#define NXMAC_COEX_FORCE_ENABLE_POS 4 +/// COEX_POSTPONE_TX_ENABLE field bit +#define NXMAC_COEX_POSTPONE_TX_ENABLE_BIT ((uint32_t)0x00000008) +/// COEX_POSTPONE_TX_ENABLE field position +#define NXMAC_COEX_POSTPONE_TX_ENABLE_POS 3 +/// COEX_PHY_RX_ABORT_ENABLE field bit +#define NXMAC_COEX_PHY_RX_ABORT_ENABLE_BIT ((uint32_t)0x00000004) +/// COEX_PHY_RX_ABORT_ENABLE field position +#define NXMAC_COEX_PHY_RX_ABORT_ENABLE_POS 2 +/// COEX_PHY_TX_ABORT_ENABLE field bit +#define NXMAC_COEX_PHY_TX_ABORT_ENABLE_BIT ((uint32_t)0x00000002) +/// COEX_PHY_TX_ABORT_ENABLE field position +#define NXMAC_COEX_PHY_TX_ABORT_ENABLE_POS 1 +/// COEX_ENABLE field bit +#define NXMAC_COEX_ENABLE_BIT ((uint32_t)0x00000001) +/// COEX_ENABLE field position +#define NXMAC_COEX_ENABLE_POS 0 + +/// COEX_FORCE_WLAN_PTI field reset value +#define NXMAC_COEX_FORCE_WLAN_PTI_RST 0x0 +/// COEX_FORCE_WLAN_PTI_TOGGLE field reset value +#define NXMAC_COEX_FORCE_WLAN_PTI_TOGGLE_RST 0x0 +/// COEX_FORCE_WLAN_CHAN_BW field reset value +#define NXMAC_COEX_FORCE_WLAN_CHAN_BW_RST 0x0 +/// COEX_FORCE_WLAN_RX field reset value +#define NXMAC_COEX_FORCE_WLAN_RX_RST 0x0 +/// COEX_FORCE_WLAN_TX field reset value +#define NXMAC_COEX_FORCE_WLAN_TX_RST 0x0 +/// COEX_WLAN_CHAN_FREQ field reset value +#define NXMAC_COEX_WLAN_CHAN_FREQ_RST 0x0 +/// COEX_WLAN_CHAN_OFFSET field reset value +#define NXMAC_COEX_WLAN_CHAN_OFFSET_RST 0x0 +/// COEX_AUTO_PTI_ADJ_INCR field reset value +#define NXMAC_COEX_AUTO_PTI_ADJ_INCR_RST 0x1 +/// COEX_AUTO_PTI_ADJ_ENABLE field reset value +#define NXMAC_COEX_AUTO_PTI_ADJ_ENABLE_RST 0x1 +/// COEX_FORCE_ENABLE field reset value +#define NXMAC_COEX_FORCE_ENABLE_RST 0x0 +/// COEX_POSTPONE_TX_ENABLE field reset value +#define NXMAC_COEX_POSTPONE_TX_ENABLE_RST 0x1 +/// COEX_PHY_RX_ABORT_ENABLE field reset value +#define NXMAC_COEX_PHY_RX_ABORT_ENABLE_RST 0x0 +/// COEX_PHY_TX_ABORT_ENABLE field reset value +#define NXMAC_COEX_PHY_TX_ABORT_ENABLE_RST 0x0 +/// COEX_ENABLE field reset value +#define NXMAC_COEX_ENABLE_RST 0x0 + +/** + * @brief Constructs a value for the COEX_CONTROL register given values for its fields + * and writes the value to the register. + * + * @param[in] coexforcewlanpti - The value to use for the coexForceWlanPTI field. + * @param[in] coexforcewlanptitoggle - The value to use for the coexForceWlanPTIToggle field. + * @param[in] coexforcewlanchanbw - The value to use for the coexForceWlanChanBw field. + * @param[in] coexforcewlanrx - The value to use for the coexForceWlanRx field. + * @param[in] coexforcewlantx - The value to use for the coexForceWlanTx field. + * @param[in] coexwlanchanfreq - The value to use for the coexWlanChanFreq field. + * @param[in] coexwlanchanoffset - The value to use for the coexWlanChanOffset field. + * @param[in] coexautoptiadjincr - The value to use for the coexAutoPTIAdjIncr field. + * @param[in] coexautoptiadjenable - The value to use for the coexAutoPTIAdjEnable field. + * @param[in] coexforceenable - The value to use for the coexForceEnable field. + * @param[in] coexpostponetxenable - The value to use for the coexPostponeTxEnable field. + * @param[in] coexphyrxabortenable - The value to use for the coexPHYRxAbortEnable field. + * @param[in] coexphytxabortenable - The value to use for the coexPHYTxAbortEnable field. + * @param[in] coexenable - The value to use for the coexEnable field. + */ +__INLINE void nxmac_coex_control_pack(uint8_t coexforcewlanpti, uint8_t coexforcewlanptitoggle, uint8_t coexforcewlanchanbw, uint8_t coexforcewlanrx, uint8_t coexforcewlantx, uint8_t coexwlanchanfreq, uint8_t coexwlanchanoffset, uint8_t coexautoptiadjincr, uint8_t coexautoptiadjenable, uint8_t coexforceenable, uint8_t coexpostponetxenable, uint8_t coexphyrxabortenable, uint8_t coexphytxabortenable, uint8_t coexenable) +{ + ASSERT_ERR((((uint32_t)coexforcewlanpti << 28) & ~((uint32_t)0xF0000000)) == 0); + ASSERT_ERR((((uint32_t)coexforcewlanptitoggle << 27) & ~((uint32_t)0x08000000)) == 0); + ASSERT_ERR((((uint32_t)coexforcewlanchanbw << 26) & ~((uint32_t)0x04000000)) == 0); + ASSERT_ERR((((uint32_t)coexforcewlanrx << 25) & ~((uint32_t)0x02000000)) == 0); + ASSERT_ERR((((uint32_t)coexforcewlantx << 24) & ~((uint32_t)0x01000000)) == 0); + ASSERT_ERR((((uint32_t)coexwlanchanfreq << 16) & ~((uint32_t)0x007F0000)) == 0); + ASSERT_ERR((((uint32_t)coexwlanchanoffset << 12) & ~((uint32_t)0x00001000)) == 0); + ASSERT_ERR((((uint32_t)coexautoptiadjincr << 6) & ~((uint32_t)0x000000C0)) == 0); + ASSERT_ERR((((uint32_t)coexautoptiadjenable << 5) & ~((uint32_t)0x00000020)) == 0); + ASSERT_ERR((((uint32_t)coexforceenable << 4) & ~((uint32_t)0x00000010)) == 0); + ASSERT_ERR((((uint32_t)coexpostponetxenable << 3) & ~((uint32_t)0x00000008)) == 0); + ASSERT_ERR((((uint32_t)coexphyrxabortenable << 2) & ~((uint32_t)0x00000004)) == 0); + ASSERT_ERR((((uint32_t)coexphytxabortenable << 1) & ~((uint32_t)0x00000002)) == 0); + ASSERT_ERR((((uint32_t)coexenable << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_COEX_CONTROL_ADDR, ((uint32_t)coexforcewlanpti << 28) | ((uint32_t)coexforcewlanptitoggle << 27) | ((uint32_t)coexforcewlanchanbw << 26) | ((uint32_t)coexforcewlanrx << 25) | ((uint32_t)coexforcewlantx << 24) | ((uint32_t)coexwlanchanfreq << 16) | ((uint32_t)coexwlanchanoffset << 12) | ((uint32_t)coexautoptiadjincr << 6) | ((uint32_t)coexautoptiadjenable << 5) | ((uint32_t)coexforceenable << 4) | ((uint32_t)coexpostponetxenable << 3) | ((uint32_t)coexphyrxabortenable << 2) | ((uint32_t)coexphytxabortenable << 1) | ((uint32_t)coexenable << 0)); +} + +/** + * @brief Unpacks COEX_CONTROL's fields from current value of the COEX_CONTROL register. + * + * Reads the COEX_CONTROL register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] coexforcewlanpti - Will be populated with the current value of this field from the register. + * @param[out] coexforcewlanptitoggle - Will be populated with the current value of this field from the register. + * @param[out] coexforcewlanchanbw - Will be populated with the current value of this field from the register. + * @param[out] coexforcewlanrx - Will be populated with the current value of this field from the register. + * @param[out] coexforcewlantx - Will be populated with the current value of this field from the register. + * @param[out] coexwlanchanfreq - Will be populated with the current value of this field from the register. + * @param[out] coexwlanchanoffset - Will be populated with the current value of this field from the register. + * @param[out] coexautoptiadjincr - Will be populated with the current value of this field from the register. + * @param[out] coexautoptiadjenable - Will be populated with the current value of this field from the register. + * @param[out] coexforceenable - Will be populated with the current value of this field from the register. + * @param[out] coexpostponetxenable - Will be populated with the current value of this field from the register. + * @param[out] coexphyrxabortenable - Will be populated with the current value of this field from the register. + * @param[out] coexphytxabortenable - Will be populated with the current value of this field from the register. + * @param[out] coexenable - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_coex_control_unpack(uint8_t *coexforcewlanpti, uint8_t *coexforcewlanptitoggle, uint8_t *coexforcewlanchanbw, uint8_t *coexforcewlanrx, uint8_t *coexforcewlantx, uint8_t *coexwlanchanfreq, uint8_t *coexwlanchanoffset, uint8_t *coexautoptiadjincr, uint8_t *coexautoptiadjenable, uint8_t *coexforceenable, uint8_t *coexpostponetxenable, uint8_t *coexphyrxabortenable, uint8_t *coexphytxabortenable, uint8_t *coexenable) +{ + uint32_t localVal = REG_PL_RD(NXMAC_COEX_CONTROL_ADDR); + + *coexforcewlanpti = (localVal & ((uint32_t)0xF0000000)) >> 28; + *coexforcewlanptitoggle = (localVal & ((uint32_t)0x08000000)) >> 27; + *coexforcewlanchanbw = (localVal & ((uint32_t)0x04000000)) >> 26; + *coexforcewlanrx = (localVal & ((uint32_t)0x02000000)) >> 25; + *coexforcewlantx = (localVal & ((uint32_t)0x01000000)) >> 24; + *coexwlanchanfreq = (localVal & ((uint32_t)0x007F0000)) >> 16; + *coexwlanchanoffset = (localVal & ((uint32_t)0x00001000)) >> 12; + *coexautoptiadjincr = (localVal & ((uint32_t)0x000000C0)) >> 6; + *coexautoptiadjenable = (localVal & ((uint32_t)0x00000020)) >> 5; + *coexforceenable = (localVal & ((uint32_t)0x00000010)) >> 4; + *coexpostponetxenable = (localVal & ((uint32_t)0x00000008)) >> 3; + *coexphyrxabortenable = (localVal & ((uint32_t)0x00000004)) >> 2; + *coexphytxabortenable = (localVal & ((uint32_t)0x00000002)) >> 1; + *coexenable = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +/** + * @brief Returns the current value of the coexForceWlanPTI field in the COEX_CONTROL register. + * + * The COEX_CONTROL register will be read and the coexForceWlanPTI field's value will be returned. + * + * @return The current value of the coexForceWlanPTI field in the COEX_CONTROL register. + */ +__INLINE uint8_t nxmac_coex_force_wlan_pti_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_COEX_CONTROL_ADDR); + return ((localVal & ((uint32_t)0xF0000000)) >> 28); +} + +/** + * @brief Sets the coexForceWlanPTI field of the COEX_CONTROL register. + * + * The COEX_CONTROL register will be read, modified to contain the new field value, and written. + * + * @param[in] coexforcewlanpti - The value to set the field to. + */ +__INLINE void nxmac_coex_force_wlan_pti_setf(uint8_t coexforcewlanpti) +{ + ASSERT_ERR((((uint32_t)coexforcewlanpti << 28) & ~((uint32_t)0xF0000000)) == 0); + REG_PL_WR(NXMAC_COEX_CONTROL_ADDR, (REG_PL_RD(NXMAC_COEX_CONTROL_ADDR) & ~((uint32_t)0xF0000000)) | ((uint32_t)coexforcewlanpti << 28)); +} + +/** + * @brief Returns the current value of the coexForceWlanPTIToggle field in the COEX_CONTROL register. + * + * The COEX_CONTROL register will be read and the coexForceWlanPTIToggle field's value will be returned. + * + * @return The current value of the coexForceWlanPTIToggle field in the COEX_CONTROL register. + */ +__INLINE uint8_t nxmac_coex_force_wlan_pti_toggle_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_COEX_CONTROL_ADDR); + return ((localVal & ((uint32_t)0x08000000)) >> 27); +} + +/** + * @brief Sets the coexForceWlanPTIToggle field of the COEX_CONTROL register. + * + * The COEX_CONTROL register will be read, modified to contain the new field value, and written. + * + * @param[in] coexforcewlanptitoggle - The value to set the field to. + */ +__INLINE void nxmac_coex_force_wlan_pti_toggle_setf(uint8_t coexforcewlanptitoggle) +{ + ASSERT_ERR((((uint32_t)coexforcewlanptitoggle << 27) & ~((uint32_t)0x08000000)) == 0); + REG_PL_WR(NXMAC_COEX_CONTROL_ADDR, (REG_PL_RD(NXMAC_COEX_CONTROL_ADDR) & ~((uint32_t)0x08000000)) | ((uint32_t)coexforcewlanptitoggle << 27)); +} + +/** + * @brief Returns the current value of the coexForceWlanChanBw field in the COEX_CONTROL register. + * + * The COEX_CONTROL register will be read and the coexForceWlanChanBw field's value will be returned. + * + * @return The current value of the coexForceWlanChanBw field in the COEX_CONTROL register. + */ +__INLINE uint8_t nxmac_coex_force_wlan_chan_bw_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_COEX_CONTROL_ADDR); + return ((localVal & ((uint32_t)0x04000000)) >> 26); +} + +/** + * @brief Sets the coexForceWlanChanBw field of the COEX_CONTROL register. + * + * The COEX_CONTROL register will be read, modified to contain the new field value, and written. + * + * @param[in] coexforcewlanchanbw - The value to set the field to. + */ +__INLINE void nxmac_coex_force_wlan_chan_bw_setf(uint8_t coexforcewlanchanbw) +{ + ASSERT_ERR((((uint32_t)coexforcewlanchanbw << 26) & ~((uint32_t)0x04000000)) == 0); + REG_PL_WR(NXMAC_COEX_CONTROL_ADDR, (REG_PL_RD(NXMAC_COEX_CONTROL_ADDR) & ~((uint32_t)0x04000000)) | ((uint32_t)coexforcewlanchanbw << 26)); +} + +/** + * @brief Returns the current value of the coexForceWlanRx field in the COEX_CONTROL register. + * + * The COEX_CONTROL register will be read and the coexForceWlanRx field's value will be returned. + * + * @return The current value of the coexForceWlanRx field in the COEX_CONTROL register. + */ +__INLINE uint8_t nxmac_coex_force_wlan_rx_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_COEX_CONTROL_ADDR); + return ((localVal & ((uint32_t)0x02000000)) >> 25); +} + +/** + * @brief Sets the coexForceWlanRx field of the COEX_CONTROL register. + * + * The COEX_CONTROL register will be read, modified to contain the new field value, and written. + * + * @param[in] coexforcewlanrx - The value to set the field to. + */ +__INLINE void nxmac_coex_force_wlan_rx_setf(uint8_t coexforcewlanrx) +{ + ASSERT_ERR((((uint32_t)coexforcewlanrx << 25) & ~((uint32_t)0x02000000)) == 0); + REG_PL_WR(NXMAC_COEX_CONTROL_ADDR, (REG_PL_RD(NXMAC_COEX_CONTROL_ADDR) & ~((uint32_t)0x02000000)) | ((uint32_t)coexforcewlanrx << 25)); +} + +/** + * @brief Returns the current value of the coexForceWlanTx field in the COEX_CONTROL register. + * + * The COEX_CONTROL register will be read and the coexForceWlanTx field's value will be returned. + * + * @return The current value of the coexForceWlanTx field in the COEX_CONTROL register. + */ +__INLINE uint8_t nxmac_coex_force_wlan_tx_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_COEX_CONTROL_ADDR); + return ((localVal & ((uint32_t)0x01000000)) >> 24); +} + +/** + * @brief Sets the coexForceWlanTx field of the COEX_CONTROL register. + * + * The COEX_CONTROL register will be read, modified to contain the new field value, and written. + * + * @param[in] coexforcewlantx - The value to set the field to. + */ +__INLINE void nxmac_coex_force_wlan_tx_setf(uint8_t coexforcewlantx) +{ + ASSERT_ERR((((uint32_t)coexforcewlantx << 24) & ~((uint32_t)0x01000000)) == 0); + REG_PL_WR(NXMAC_COEX_CONTROL_ADDR, (REG_PL_RD(NXMAC_COEX_CONTROL_ADDR) & ~((uint32_t)0x01000000)) | ((uint32_t)coexforcewlantx << 24)); +} + +/** + * @brief Returns the current value of the coexWlanChanFreq field in the COEX_CONTROL register. + * + * The COEX_CONTROL register will be read and the coexWlanChanFreq field's value will be returned. + * + * @return The current value of the coexWlanChanFreq field in the COEX_CONTROL register. + */ +__INLINE uint8_t nxmac_coex_wlan_chan_freq_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_COEX_CONTROL_ADDR); + return ((localVal & ((uint32_t)0x007F0000)) >> 16); +} + +/** + * @brief Sets the coexWlanChanFreq field of the COEX_CONTROL register. + * + * The COEX_CONTROL register will be read, modified to contain the new field value, and written. + * + * @param[in] coexwlanchanfreq - The value to set the field to. + */ +__INLINE void nxmac_coex_wlan_chan_freq_setf(uint8_t coexwlanchanfreq) +{ + ASSERT_ERR((((uint32_t)coexwlanchanfreq << 16) & ~((uint32_t)0x007F0000)) == 0); + REG_PL_WR(NXMAC_COEX_CONTROL_ADDR, (REG_PL_RD(NXMAC_COEX_CONTROL_ADDR) & ~((uint32_t)0x007F0000)) | ((uint32_t)coexwlanchanfreq << 16)); +} + +/** + * @brief Returns the current value of the coexWlanChanOffset field in the COEX_CONTROL register. + * + * The COEX_CONTROL register will be read and the coexWlanChanOffset field's value will be returned. + * + * @return The current value of the coexWlanChanOffset field in the COEX_CONTROL register. + */ +__INLINE uint8_t nxmac_coex_wlan_chan_offset_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_COEX_CONTROL_ADDR); + return ((localVal & ((uint32_t)0x00001000)) >> 12); +} + +/** + * @brief Sets the coexWlanChanOffset field of the COEX_CONTROL register. + * + * The COEX_CONTROL register will be read, modified to contain the new field value, and written. + * + * @param[in] coexwlanchanoffset - The value to set the field to. + */ +__INLINE void nxmac_coex_wlan_chan_offset_setf(uint8_t coexwlanchanoffset) +{ + ASSERT_ERR((((uint32_t)coexwlanchanoffset << 12) & ~((uint32_t)0x00001000)) == 0); + REG_PL_WR(NXMAC_COEX_CONTROL_ADDR, (REG_PL_RD(NXMAC_COEX_CONTROL_ADDR) & ~((uint32_t)0x00001000)) | ((uint32_t)coexwlanchanoffset << 12)); +} + +/** + * @brief Returns the current value of the coexAutoPTIAdjIncr field in the COEX_CONTROL register. + * + * The COEX_CONTROL register will be read and the coexAutoPTIAdjIncr field's value will be returned. + * + * @return The current value of the coexAutoPTIAdjIncr field in the COEX_CONTROL register. + */ +__INLINE uint8_t nxmac_coex_auto_pti_adj_incr_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_COEX_CONTROL_ADDR); + return ((localVal & ((uint32_t)0x000000C0)) >> 6); +} + +/** + * @brief Sets the coexAutoPTIAdjIncr field of the COEX_CONTROL register. + * + * The COEX_CONTROL register will be read, modified to contain the new field value, and written. + * + * @param[in] coexautoptiadjincr - The value to set the field to. + */ +__INLINE void nxmac_coex_auto_pti_adj_incr_setf(uint8_t coexautoptiadjincr) +{ + ASSERT_ERR((((uint32_t)coexautoptiadjincr << 6) & ~((uint32_t)0x000000C0)) == 0); + REG_PL_WR(NXMAC_COEX_CONTROL_ADDR, (REG_PL_RD(NXMAC_COEX_CONTROL_ADDR) & ~((uint32_t)0x000000C0)) | ((uint32_t)coexautoptiadjincr << 6)); +} + +/** + * @brief Returns the current value of the coexAutoPTIAdjEnable field in the COEX_CONTROL register. + * + * The COEX_CONTROL register will be read and the coexAutoPTIAdjEnable field's value will be returned. + * + * @return The current value of the coexAutoPTIAdjEnable field in the COEX_CONTROL register. + */ +__INLINE uint8_t nxmac_coex_auto_pti_adj_enable_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_COEX_CONTROL_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +/** + * @brief Sets the coexAutoPTIAdjEnable field of the COEX_CONTROL register. + * + * The COEX_CONTROL register will be read, modified to contain the new field value, and written. + * + * @param[in] coexautoptiadjenable - The value to set the field to. + */ +__INLINE void nxmac_coex_auto_pti_adj_enable_setf(uint8_t coexautoptiadjenable) +{ + ASSERT_ERR((((uint32_t)coexautoptiadjenable << 5) & ~((uint32_t)0x00000020)) == 0); + REG_PL_WR(NXMAC_COEX_CONTROL_ADDR, (REG_PL_RD(NXMAC_COEX_CONTROL_ADDR) & ~((uint32_t)0x00000020)) | ((uint32_t)coexautoptiadjenable << 5)); +} + +/** + * @brief Returns the current value of the coexForceEnable field in the COEX_CONTROL register. + * + * The COEX_CONTROL register will be read and the coexForceEnable field's value will be returned. + * + * @return The current value of the coexForceEnable field in the COEX_CONTROL register. + */ +__INLINE uint8_t nxmac_coex_force_enable_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_COEX_CONTROL_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +/** + * @brief Sets the coexForceEnable field of the COEX_CONTROL register. + * + * The COEX_CONTROL register will be read, modified to contain the new field value, and written. + * + * @param[in] coexforceenable - The value to set the field to. + */ +__INLINE void nxmac_coex_force_enable_setf(uint8_t coexforceenable) +{ + ASSERT_ERR((((uint32_t)coexforceenable << 4) & ~((uint32_t)0x00000010)) == 0); + REG_PL_WR(NXMAC_COEX_CONTROL_ADDR, (REG_PL_RD(NXMAC_COEX_CONTROL_ADDR) & ~((uint32_t)0x00000010)) | ((uint32_t)coexforceenable << 4)); +} + +/** + * @brief Returns the current value of the coexPostponeTxEnable field in the COEX_CONTROL register. + * + * The COEX_CONTROL register will be read and the coexPostponeTxEnable field's value will be returned. + * + * @return The current value of the coexPostponeTxEnable field in the COEX_CONTROL register. + */ +__INLINE uint8_t nxmac_coex_postpone_tx_enable_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_COEX_CONTROL_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +/** + * @brief Sets the coexPostponeTxEnable field of the COEX_CONTROL register. + * + * The COEX_CONTROL register will be read, modified to contain the new field value, and written. + * + * @param[in] coexpostponetxenable - The value to set the field to. + */ +__INLINE void nxmac_coex_postpone_tx_enable_setf(uint8_t coexpostponetxenable) +{ + ASSERT_ERR((((uint32_t)coexpostponetxenable << 3) & ~((uint32_t)0x00000008)) == 0); + REG_PL_WR(NXMAC_COEX_CONTROL_ADDR, (REG_PL_RD(NXMAC_COEX_CONTROL_ADDR) & ~((uint32_t)0x00000008)) | ((uint32_t)coexpostponetxenable << 3)); +} + +/** + * @brief Returns the current value of the coexPHYRxAbortEnable field in the COEX_CONTROL register. + * + * The COEX_CONTROL register will be read and the coexPHYRxAbortEnable field's value will be returned. + * + * @return The current value of the coexPHYRxAbortEnable field in the COEX_CONTROL register. + */ +__INLINE uint8_t nxmac_coex_phy_rx_abort_enable_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_COEX_CONTROL_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +/** + * @brief Sets the coexPHYRxAbortEnable field of the COEX_CONTROL register. + * + * The COEX_CONTROL register will be read, modified to contain the new field value, and written. + * + * @param[in] coexphyrxabortenable - The value to set the field to. + */ +__INLINE void nxmac_coex_phy_rx_abort_enable_setf(uint8_t coexphyrxabortenable) +{ + ASSERT_ERR((((uint32_t)coexphyrxabortenable << 2) & ~((uint32_t)0x00000004)) == 0); + REG_PL_WR(NXMAC_COEX_CONTROL_ADDR, (REG_PL_RD(NXMAC_COEX_CONTROL_ADDR) & ~((uint32_t)0x00000004)) | ((uint32_t)coexphyrxabortenable << 2)); +} + +/** + * @brief Returns the current value of the coexPHYTxAbortEnable field in the COEX_CONTROL register. + * + * The COEX_CONTROL register will be read and the coexPHYTxAbortEnable field's value will be returned. + * + * @return The current value of the coexPHYTxAbortEnable field in the COEX_CONTROL register. + */ +__INLINE uint8_t nxmac_coex_phy_tx_abort_enable_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_COEX_CONTROL_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +/** + * @brief Sets the coexPHYTxAbortEnable field of the COEX_CONTROL register. + * + * The COEX_CONTROL register will be read, modified to contain the new field value, and written. + * + * @param[in] coexphytxabortenable - The value to set the field to. + */ +__INLINE void nxmac_coex_phy_tx_abort_enable_setf(uint8_t coexphytxabortenable) +{ + ASSERT_ERR((((uint32_t)coexphytxabortenable << 1) & ~((uint32_t)0x00000002)) == 0); + REG_PL_WR(NXMAC_COEX_CONTROL_ADDR, (REG_PL_RD(NXMAC_COEX_CONTROL_ADDR) & ~((uint32_t)0x00000002)) | ((uint32_t)coexphytxabortenable << 1)); +} + +/** + * @brief Returns the current value of the coexEnable field in the COEX_CONTROL register. + * + * The COEX_CONTROL register will be read and the coexEnable field's value will be returned. + * + * @return The current value of the coexEnable field in the COEX_CONTROL register. + */ +__INLINE uint8_t nxmac_coex_enable_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_COEX_CONTROL_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/** + * @brief Sets the coexEnable field of the COEX_CONTROL register. + * + * The COEX_CONTROL register will be read, modified to contain the new field value, and written. + * + * @param[in] coexenable - The value to set the field to. + */ +__INLINE void nxmac_coex_enable_setf(uint8_t coexenable) +{ + ASSERT_ERR((((uint32_t)coexenable << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_COEX_CONTROL_ADDR, (REG_PL_RD(NXMAC_COEX_CONTROL_ADDR) & ~((uint32_t)0x00000001)) | ((uint32_t)coexenable << 0)); +} + +#endif // RW_WLAN_COEX_EN +/// @} + +#if RW_WLAN_COEX_EN +/** + * @name COEX_PTI register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:28       coexPTIBcnData   0x0
+ *  27:24        coexPTIBKData   0x0
+ *  23:20        coexPTIBEData   0x2
+ *  19:16        coexPTIVIData   0x4
+ *  15:12        coexPTIVOData   0x6
+ *  11:08           coexPTIMgt   0x6
+ *  07:04          coexPTICntl   0x3
+ *  03:00           coexPTIAck   0x7
+ * 
+ * + * @{ + */ + +/// Address of the COEX_PTI register +#define NXMAC_COEX_PTI_ADDR 0xC0000404 +/// Offset of the COEX_PTI register from the base address +#define NXMAC_COEX_PTI_OFFSET 0x00000404 +/// Index of the COEX_PTI register +#define NXMAC_COEX_PTI_INDEX 0x00000101 +/// Reset value of the COEX_PTI register +#define NXMAC_COEX_PTI_RESET 0x00246637 + +/** + * @brief Returns the current value of the COEX_PTI register. + * The COEX_PTI register will be read and its value returned. + * @return The current value of the COEX_PTI register. + */ +__INLINE uint32_t nxmac_coex_pti_get(void) +{ + return REG_PL_RD(NXMAC_COEX_PTI_ADDR); +} + +/** + * @brief Sets the COEX_PTI register to a value. + * The COEX_PTI register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_coex_pti_set(uint32_t value) +{ + REG_PL_WR(NXMAC_COEX_PTI_ADDR, value); +} + +// field definitions +/// COEX_PTI_BCN_DATA field mask +#define NXMAC_COEX_PTI_BCN_DATA_MASK ((uint32_t)0xF0000000) +/// COEX_PTI_BCN_DATA field LSB position +#define NXMAC_COEX_PTI_BCN_DATA_LSB 28 +/// COEX_PTI_BCN_DATA field width +#define NXMAC_COEX_PTI_BCN_DATA_WIDTH ((uint32_t)0x00000004) +/// COEX_PTIBK_DATA field mask +#define NXMAC_COEX_PTIBK_DATA_MASK ((uint32_t)0x0F000000) +/// COEX_PTIBK_DATA field LSB position +#define NXMAC_COEX_PTIBK_DATA_LSB 24 +/// COEX_PTIBK_DATA field width +#define NXMAC_COEX_PTIBK_DATA_WIDTH ((uint32_t)0x00000004) +/// COEX_PTIBE_DATA field mask +#define NXMAC_COEX_PTIBE_DATA_MASK ((uint32_t)0x00F00000) +/// COEX_PTIBE_DATA field LSB position +#define NXMAC_COEX_PTIBE_DATA_LSB 20 +/// COEX_PTIBE_DATA field width +#define NXMAC_COEX_PTIBE_DATA_WIDTH ((uint32_t)0x00000004) +/// COEX_PTIVI_DATA field mask +#define NXMAC_COEX_PTIVI_DATA_MASK ((uint32_t)0x000F0000) +/// COEX_PTIVI_DATA field LSB position +#define NXMAC_COEX_PTIVI_DATA_LSB 16 +/// COEX_PTIVI_DATA field width +#define NXMAC_COEX_PTIVI_DATA_WIDTH ((uint32_t)0x00000004) +/// COEX_PTIVO_DATA field mask +#define NXMAC_COEX_PTIVO_DATA_MASK ((uint32_t)0x0000F000) +/// COEX_PTIVO_DATA field LSB position +#define NXMAC_COEX_PTIVO_DATA_LSB 12 +/// COEX_PTIVO_DATA field width +#define NXMAC_COEX_PTIVO_DATA_WIDTH ((uint32_t)0x00000004) +/// COEX_PTI_MGT field mask +#define NXMAC_COEX_PTI_MGT_MASK ((uint32_t)0x00000F00) +/// COEX_PTI_MGT field LSB position +#define NXMAC_COEX_PTI_MGT_LSB 8 +/// COEX_PTI_MGT field width +#define NXMAC_COEX_PTI_MGT_WIDTH ((uint32_t)0x00000004) +/// COEX_PTI_CNTL field mask +#define NXMAC_COEX_PTI_CNTL_MASK ((uint32_t)0x000000F0) +/// COEX_PTI_CNTL field LSB position +#define NXMAC_COEX_PTI_CNTL_LSB 4 +/// COEX_PTI_CNTL field width +#define NXMAC_COEX_PTI_CNTL_WIDTH ((uint32_t)0x00000004) +/// COEX_PTI_ACK field mask +#define NXMAC_COEX_PTI_ACK_MASK ((uint32_t)0x0000000F) +/// COEX_PTI_ACK field LSB position +#define NXMAC_COEX_PTI_ACK_LSB 0 +/// COEX_PTI_ACK field width +#define NXMAC_COEX_PTI_ACK_WIDTH ((uint32_t)0x00000004) + +/// COEX_PTI_BCN_DATA field reset value +#define NXMAC_COEX_PTI_BCN_DATA_RST 0x0 +/// COEX_PTIBK_DATA field reset value +#define NXMAC_COEX_PTIBK_DATA_RST 0x0 +/// COEX_PTIBE_DATA field reset value +#define NXMAC_COEX_PTIBE_DATA_RST 0x2 +/// COEX_PTIVI_DATA field reset value +#define NXMAC_COEX_PTIVI_DATA_RST 0x4 +/// COEX_PTIVO_DATA field reset value +#define NXMAC_COEX_PTIVO_DATA_RST 0x6 +/// COEX_PTI_MGT field reset value +#define NXMAC_COEX_PTI_MGT_RST 0x6 +/// COEX_PTI_CNTL field reset value +#define NXMAC_COEX_PTI_CNTL_RST 0x3 +/// COEX_PTI_ACK field reset value +#define NXMAC_COEX_PTI_ACK_RST 0x7 + +/** + * @brief Constructs a value for the COEX_PTI register given values for its fields + * and writes the value to the register. + * + * @param[in] coexptibcndata - The value to use for the coexPTIBcnData field. + * @param[in] coexptibkdata - The value to use for the coexPTIBKData field. + * @param[in] coexptibedata - The value to use for the coexPTIBEData field. + * @param[in] coexptividata - The value to use for the coexPTIVIData field. + * @param[in] coexptivodata - The value to use for the coexPTIVOData field. + * @param[in] coexptimgt - The value to use for the coexPTIMgt field. + * @param[in] coexpticntl - The value to use for the coexPTICntl field. + * @param[in] coexptiack - The value to use for the coexPTIAck field. + */ +__INLINE void nxmac_coex_pti_pack(uint8_t coexptibcndata, uint8_t coexptibkdata, uint8_t coexptibedata, uint8_t coexptividata, uint8_t coexptivodata, uint8_t coexptimgt, uint8_t coexpticntl, uint8_t coexptiack) +{ + ASSERT_ERR((((uint32_t)coexptibcndata << 28) & ~((uint32_t)0xF0000000)) == 0); + ASSERT_ERR((((uint32_t)coexptibkdata << 24) & ~((uint32_t)0x0F000000)) == 0); + ASSERT_ERR((((uint32_t)coexptibedata << 20) & ~((uint32_t)0x00F00000)) == 0); + ASSERT_ERR((((uint32_t)coexptividata << 16) & ~((uint32_t)0x000F0000)) == 0); + ASSERT_ERR((((uint32_t)coexptivodata << 12) & ~((uint32_t)0x0000F000)) == 0); + ASSERT_ERR((((uint32_t)coexptimgt << 8) & ~((uint32_t)0x00000F00)) == 0); + ASSERT_ERR((((uint32_t)coexpticntl << 4) & ~((uint32_t)0x000000F0)) == 0); + ASSERT_ERR((((uint32_t)coexptiack << 0) & ~((uint32_t)0x0000000F)) == 0); + REG_PL_WR(NXMAC_COEX_PTI_ADDR, ((uint32_t)coexptibcndata << 28) | ((uint32_t)coexptibkdata << 24) | ((uint32_t)coexptibedata << 20) | ((uint32_t)coexptividata << 16) | ((uint32_t)coexptivodata << 12) | ((uint32_t)coexptimgt << 8) | ((uint32_t)coexpticntl << 4) | ((uint32_t)coexptiack << 0)); +} + +/** + * @brief Unpacks COEX_PTI's fields from current value of the COEX_PTI register. + * + * Reads the COEX_PTI register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] coexptibcndata - Will be populated with the current value of this field from the register. + * @param[out] coexptibkdata - Will be populated with the current value of this field from the register. + * @param[out] coexptibedata - Will be populated with the current value of this field from the register. + * @param[out] coexptividata - Will be populated with the current value of this field from the register. + * @param[out] coexptivodata - Will be populated with the current value of this field from the register. + * @param[out] coexptimgt - Will be populated with the current value of this field from the register. + * @param[out] coexpticntl - Will be populated with the current value of this field from the register. + * @param[out] coexptiack - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_coex_pti_unpack(uint8_t *coexptibcndata, uint8_t *coexptibkdata, uint8_t *coexptibedata, uint8_t *coexptividata, uint8_t *coexptivodata, uint8_t *coexptimgt, uint8_t *coexpticntl, uint8_t *coexptiack) +{ + uint32_t localVal = REG_PL_RD(NXMAC_COEX_PTI_ADDR); + + *coexptibcndata = (localVal & ((uint32_t)0xF0000000)) >> 28; + *coexptibkdata = (localVal & ((uint32_t)0x0F000000)) >> 24; + *coexptibedata = (localVal & ((uint32_t)0x00F00000)) >> 20; + *coexptividata = (localVal & ((uint32_t)0x000F0000)) >> 16; + *coexptivodata = (localVal & ((uint32_t)0x0000F000)) >> 12; + *coexptimgt = (localVal & ((uint32_t)0x00000F00)) >> 8; + *coexpticntl = (localVal & ((uint32_t)0x000000F0)) >> 4; + *coexptiack = (localVal & ((uint32_t)0x0000000F)) >> 0; +} + +/** + * @brief Returns the current value of the coexPTIBcnData field in the COEX_PTI register. + * + * The COEX_PTI register will be read and the coexPTIBcnData field's value will be returned. + * + * @return The current value of the coexPTIBcnData field in the COEX_PTI register. + */ +__INLINE uint8_t nxmac_coex_pti_bcn_data_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_COEX_PTI_ADDR); + return ((localVal & ((uint32_t)0xF0000000)) >> 28); +} + +/** + * @brief Sets the coexPTIBcnData field of the COEX_PTI register. + * + * The COEX_PTI register will be read, modified to contain the new field value, and written. + * + * @param[in] coexptibcndata - The value to set the field to. + */ +__INLINE void nxmac_coex_pti_bcn_data_setf(uint8_t coexptibcndata) +{ + ASSERT_ERR((((uint32_t)coexptibcndata << 28) & ~((uint32_t)0xF0000000)) == 0); + REG_PL_WR(NXMAC_COEX_PTI_ADDR, (REG_PL_RD(NXMAC_COEX_PTI_ADDR) & ~((uint32_t)0xF0000000)) | ((uint32_t)coexptibcndata << 28)); +} + +/** + * @brief Returns the current value of the coexPTIBKData field in the COEX_PTI register. + * + * The COEX_PTI register will be read and the coexPTIBKData field's value will be returned. + * + * @return The current value of the coexPTIBKData field in the COEX_PTI register. + */ +__INLINE uint8_t nxmac_coex_ptibk_data_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_COEX_PTI_ADDR); + return ((localVal & ((uint32_t)0x0F000000)) >> 24); +} + +/** + * @brief Sets the coexPTIBKData field of the COEX_PTI register. + * + * The COEX_PTI register will be read, modified to contain the new field value, and written. + * + * @param[in] coexptibkdata - The value to set the field to. + */ +__INLINE void nxmac_coex_ptibk_data_setf(uint8_t coexptibkdata) +{ + ASSERT_ERR((((uint32_t)coexptibkdata << 24) & ~((uint32_t)0x0F000000)) == 0); + REG_PL_WR(NXMAC_COEX_PTI_ADDR, (REG_PL_RD(NXMAC_COEX_PTI_ADDR) & ~((uint32_t)0x0F000000)) | ((uint32_t)coexptibkdata << 24)); +} + +/** + * @brief Returns the current value of the coexPTIBEData field in the COEX_PTI register. + * + * The COEX_PTI register will be read and the coexPTIBEData field's value will be returned. + * + * @return The current value of the coexPTIBEData field in the COEX_PTI register. + */ +__INLINE uint8_t nxmac_coex_ptibe_data_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_COEX_PTI_ADDR); + return ((localVal & ((uint32_t)0x00F00000)) >> 20); +} + +/** + * @brief Sets the coexPTIBEData field of the COEX_PTI register. + * + * The COEX_PTI register will be read, modified to contain the new field value, and written. + * + * @param[in] coexptibedata - The value to set the field to. + */ +__INLINE void nxmac_coex_ptibe_data_setf(uint8_t coexptibedata) +{ + ASSERT_ERR((((uint32_t)coexptibedata << 20) & ~((uint32_t)0x00F00000)) == 0); + REG_PL_WR(NXMAC_COEX_PTI_ADDR, (REG_PL_RD(NXMAC_COEX_PTI_ADDR) & ~((uint32_t)0x00F00000)) | ((uint32_t)coexptibedata << 20)); +} + +/** + * @brief Returns the current value of the coexPTIVIData field in the COEX_PTI register. + * + * The COEX_PTI register will be read and the coexPTIVIData field's value will be returned. + * + * @return The current value of the coexPTIVIData field in the COEX_PTI register. + */ +__INLINE uint8_t nxmac_coex_ptivi_data_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_COEX_PTI_ADDR); + return ((localVal & ((uint32_t)0x000F0000)) >> 16); +} + +/** + * @brief Sets the coexPTIVIData field of the COEX_PTI register. + * + * The COEX_PTI register will be read, modified to contain the new field value, and written. + * + * @param[in] coexptividata - The value to set the field to. + */ +__INLINE void nxmac_coex_ptivi_data_setf(uint8_t coexptividata) +{ + ASSERT_ERR((((uint32_t)coexptividata << 16) & ~((uint32_t)0x000F0000)) == 0); + REG_PL_WR(NXMAC_COEX_PTI_ADDR, (REG_PL_RD(NXMAC_COEX_PTI_ADDR) & ~((uint32_t)0x000F0000)) | ((uint32_t)coexptividata << 16)); +} + +/** + * @brief Returns the current value of the coexPTIVOData field in the COEX_PTI register. + * + * The COEX_PTI register will be read and the coexPTIVOData field's value will be returned. + * + * @return The current value of the coexPTIVOData field in the COEX_PTI register. + */ +__INLINE uint8_t nxmac_coex_ptivo_data_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_COEX_PTI_ADDR); + return ((localVal & ((uint32_t)0x0000F000)) >> 12); +} + +/** + * @brief Sets the coexPTIVOData field of the COEX_PTI register. + * + * The COEX_PTI register will be read, modified to contain the new field value, and written. + * + * @param[in] coexptivodata - The value to set the field to. + */ +__INLINE void nxmac_coex_ptivo_data_setf(uint8_t coexptivodata) +{ + ASSERT_ERR((((uint32_t)coexptivodata << 12) & ~((uint32_t)0x0000F000)) == 0); + REG_PL_WR(NXMAC_COEX_PTI_ADDR, (REG_PL_RD(NXMAC_COEX_PTI_ADDR) & ~((uint32_t)0x0000F000)) | ((uint32_t)coexptivodata << 12)); +} + +/** + * @brief Returns the current value of the coexPTIMgt field in the COEX_PTI register. + * + * The COEX_PTI register will be read and the coexPTIMgt field's value will be returned. + * + * @return The current value of the coexPTIMgt field in the COEX_PTI register. + */ +__INLINE uint8_t nxmac_coex_pti_mgt_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_COEX_PTI_ADDR); + return ((localVal & ((uint32_t)0x00000F00)) >> 8); +} + +/** + * @brief Sets the coexPTIMgt field of the COEX_PTI register. + * + * The COEX_PTI register will be read, modified to contain the new field value, and written. + * + * @param[in] coexptimgt - The value to set the field to. + */ +__INLINE void nxmac_coex_pti_mgt_setf(uint8_t coexptimgt) +{ + ASSERT_ERR((((uint32_t)coexptimgt << 8) & ~((uint32_t)0x00000F00)) == 0); + REG_PL_WR(NXMAC_COEX_PTI_ADDR, (REG_PL_RD(NXMAC_COEX_PTI_ADDR) & ~((uint32_t)0x00000F00)) | ((uint32_t)coexptimgt << 8)); +} + +/** + * @brief Returns the current value of the coexPTICntl field in the COEX_PTI register. + * + * The COEX_PTI register will be read and the coexPTICntl field's value will be returned. + * + * @return The current value of the coexPTICntl field in the COEX_PTI register. + */ +__INLINE uint8_t nxmac_coex_pti_cntl_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_COEX_PTI_ADDR); + return ((localVal & ((uint32_t)0x000000F0)) >> 4); +} + +/** + * @brief Sets the coexPTICntl field of the COEX_PTI register. + * + * The COEX_PTI register will be read, modified to contain the new field value, and written. + * + * @param[in] coexpticntl - The value to set the field to. + */ +__INLINE void nxmac_coex_pti_cntl_setf(uint8_t coexpticntl) +{ + ASSERT_ERR((((uint32_t)coexpticntl << 4) & ~((uint32_t)0x000000F0)) == 0); + REG_PL_WR(NXMAC_COEX_PTI_ADDR, (REG_PL_RD(NXMAC_COEX_PTI_ADDR) & ~((uint32_t)0x000000F0)) | ((uint32_t)coexpticntl << 4)); +} + +/** + * @brief Returns the current value of the coexPTIAck field in the COEX_PTI register. + * + * The COEX_PTI register will be read and the coexPTIAck field's value will be returned. + * + * @return The current value of the coexPTIAck field in the COEX_PTI register. + */ +__INLINE uint8_t nxmac_coex_pti_ack_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_COEX_PTI_ADDR); + return ((localVal & ((uint32_t)0x0000000F)) >> 0); +} + +/** + * @brief Sets the coexPTIAck field of the COEX_PTI register. + * + * The COEX_PTI register will be read, modified to contain the new field value, and written. + * + * @param[in] coexptiack - The value to set the field to. + */ +__INLINE void nxmac_coex_pti_ack_setf(uint8_t coexptiack) +{ + ASSERT_ERR((((uint32_t)coexptiack << 0) & ~((uint32_t)0x0000000F)) == 0); + REG_PL_WR(NXMAC_COEX_PTI_ADDR, (REG_PL_RD(NXMAC_COEX_PTI_ADDR) & ~((uint32_t)0x0000000F)) | ((uint32_t)coexptiack << 0)); +} + +#endif // RW_WLAN_COEX_EN +/// @} + +#if RW_WLAN_COEX_EN +/** + * @name COEX_STAT register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  11:08     coexWlanPTIState   0x0
+ *     05   coexWlanPTIToggleState   0
+ *     04   coexWlanChanBwState   0
+ *     03      coexWlanRxState   0
+ *     02      coexWlanTxState   0
+ *     01   coexWlanRxAbortState   0
+ *     00   coexWlanTxAbortState   0
+ * 
+ * + * @{ + */ + +/// Address of the COEX_STAT register +#define NXMAC_COEX_STAT_ADDR 0xC0000408 +/// Offset of the COEX_STAT register from the base address +#define NXMAC_COEX_STAT_OFFSET 0x00000408 +/// Index of the COEX_STAT register +#define NXMAC_COEX_STAT_INDEX 0x00000102 +/// Reset value of the COEX_STAT register +#define NXMAC_COEX_STAT_RESET 0x00000000 + +/** + * @brief Returns the current value of the COEX_STAT register. + * The COEX_STAT register will be read and its value returned. + * @return The current value of the COEX_STAT register. + */ +__INLINE uint32_t nxmac_coex_stat_get(void) +{ + return REG_PL_RD(NXMAC_COEX_STAT_ADDR); +} + +/** + * @brief Sets the COEX_STAT register to a value. + * The COEX_STAT register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_coex_stat_set(uint32_t value) +{ + REG_PL_WR(NXMAC_COEX_STAT_ADDR, value); +} + +// field definitions +/// COEX_WLAN_PTI_STATE field mask +#define NXMAC_COEX_WLAN_PTI_STATE_MASK ((uint32_t)0x00000F00) +/// COEX_WLAN_PTI_STATE field LSB position +#define NXMAC_COEX_WLAN_PTI_STATE_LSB 8 +/// COEX_WLAN_PTI_STATE field width +#define NXMAC_COEX_WLAN_PTI_STATE_WIDTH ((uint32_t)0x00000004) +/// COEX_WLAN_PTI_TOGGLE_STATE field bit +#define NXMAC_COEX_WLAN_PTI_TOGGLE_STATE_BIT ((uint32_t)0x00000020) +/// COEX_WLAN_PTI_TOGGLE_STATE field position +#define NXMAC_COEX_WLAN_PTI_TOGGLE_STATE_POS 5 +/// COEX_WLAN_CHAN_BW_STATE field bit +#define NXMAC_COEX_WLAN_CHAN_BW_STATE_BIT ((uint32_t)0x00000010) +/// COEX_WLAN_CHAN_BW_STATE field position +#define NXMAC_COEX_WLAN_CHAN_BW_STATE_POS 4 +/// COEX_WLAN_RX_STATE field bit +#define NXMAC_COEX_WLAN_RX_STATE_BIT ((uint32_t)0x00000008) +/// COEX_WLAN_RX_STATE field position +#define NXMAC_COEX_WLAN_RX_STATE_POS 3 +/// COEX_WLAN_TX_STATE field bit +#define NXMAC_COEX_WLAN_TX_STATE_BIT ((uint32_t)0x00000004) +/// COEX_WLAN_TX_STATE field position +#define NXMAC_COEX_WLAN_TX_STATE_POS 2 +/// COEX_WLAN_RX_ABORT_STATE field bit +#define NXMAC_COEX_WLAN_RX_ABORT_STATE_BIT ((uint32_t)0x00000002) +/// COEX_WLAN_RX_ABORT_STATE field position +#define NXMAC_COEX_WLAN_RX_ABORT_STATE_POS 1 +/// COEX_WLAN_TX_ABORT_STATE field bit +#define NXMAC_COEX_WLAN_TX_ABORT_STATE_BIT ((uint32_t)0x00000001) +/// COEX_WLAN_TX_ABORT_STATE field position +#define NXMAC_COEX_WLAN_TX_ABORT_STATE_POS 0 + +/// COEX_WLAN_PTI_STATE field reset value +#define NXMAC_COEX_WLAN_PTI_STATE_RST 0x0 +/// COEX_WLAN_PTI_TOGGLE_STATE field reset value +#define NXMAC_COEX_WLAN_PTI_TOGGLE_STATE_RST 0x0 +/// COEX_WLAN_CHAN_BW_STATE field reset value +#define NXMAC_COEX_WLAN_CHAN_BW_STATE_RST 0x0 +/// COEX_WLAN_RX_STATE field reset value +#define NXMAC_COEX_WLAN_RX_STATE_RST 0x0 +/// COEX_WLAN_TX_STATE field reset value +#define NXMAC_COEX_WLAN_TX_STATE_RST 0x0 +/// COEX_WLAN_RX_ABORT_STATE field reset value +#define NXMAC_COEX_WLAN_RX_ABORT_STATE_RST 0x0 +/// COEX_WLAN_TX_ABORT_STATE field reset value +#define NXMAC_COEX_WLAN_TX_ABORT_STATE_RST 0x0 + +/** + * @brief Unpacks COEX_STAT's fields from current value of the COEX_STAT register. + * + * Reads the COEX_STAT register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] coexwlanptistate - Will be populated with the current value of this field from the register. + * @param[out] coexwlanptitogglestate - Will be populated with the current value of this field from the register. + * @param[out] coexwlanchanbwstate - Will be populated with the current value of this field from the register. + * @param[out] coexwlanrxstate - Will be populated with the current value of this field from the register. + * @param[out] coexwlantxstate - Will be populated with the current value of this field from the register. + * @param[out] coexwlanrxabortstate - Will be populated with the current value of this field from the register. + * @param[out] coexwlantxabortstate - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_coex_stat_unpack(uint8_t *coexwlanptistate, uint8_t *coexwlanptitogglestate, uint8_t *coexwlanchanbwstate, uint8_t *coexwlanrxstate, uint8_t *coexwlantxstate, uint8_t *coexwlanrxabortstate, uint8_t *coexwlantxabortstate) +{ + uint32_t localVal = REG_PL_RD(NXMAC_COEX_STAT_ADDR); + + *coexwlanptistate = (localVal & ((uint32_t)0x00000F00)) >> 8; + *coexwlanptitogglestate = (localVal & ((uint32_t)0x00000020)) >> 5; + *coexwlanchanbwstate = (localVal & ((uint32_t)0x00000010)) >> 4; + *coexwlanrxstate = (localVal & ((uint32_t)0x00000008)) >> 3; + *coexwlantxstate = (localVal & ((uint32_t)0x00000004)) >> 2; + *coexwlanrxabortstate = (localVal & ((uint32_t)0x00000002)) >> 1; + *coexwlantxabortstate = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +/** + * @brief Returns the current value of the coexWlanPTIState field in the COEX_STAT register. + * + * The COEX_STAT register will be read and the coexWlanPTIState field's value will be returned. + * + * @return The current value of the coexWlanPTIState field in the COEX_STAT register. + */ +__INLINE uint8_t nxmac_coex_wlan_pti_state_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_COEX_STAT_ADDR); + return ((localVal & ((uint32_t)0x00000F00)) >> 8); +} + +/** + * @brief Returns the current value of the coexWlanPTIToggleState field in the COEX_STAT register. + * + * The COEX_STAT register will be read and the coexWlanPTIToggleState field's value will be returned. + * + * @return The current value of the coexWlanPTIToggleState field in the COEX_STAT register. + */ +__INLINE uint8_t nxmac_coex_wlan_pti_toggle_state_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_COEX_STAT_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +/** + * @brief Returns the current value of the coexWlanChanBwState field in the COEX_STAT register. + * + * The COEX_STAT register will be read and the coexWlanChanBwState field's value will be returned. + * + * @return The current value of the coexWlanChanBwState field in the COEX_STAT register. + */ +__INLINE uint8_t nxmac_coex_wlan_chan_bw_state_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_COEX_STAT_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +/** + * @brief Returns the current value of the coexWlanRxState field in the COEX_STAT register. + * + * The COEX_STAT register will be read and the coexWlanRxState field's value will be returned. + * + * @return The current value of the coexWlanRxState field in the COEX_STAT register. + */ +__INLINE uint8_t nxmac_coex_wlan_rx_state_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_COEX_STAT_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +/** + * @brief Returns the current value of the coexWlanTxState field in the COEX_STAT register. + * + * The COEX_STAT register will be read and the coexWlanTxState field's value will be returned. + * + * @return The current value of the coexWlanTxState field in the COEX_STAT register. + */ +__INLINE uint8_t nxmac_coex_wlan_tx_state_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_COEX_STAT_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +/** + * @brief Returns the current value of the coexWlanRxAbortState field in the COEX_STAT register. + * + * The COEX_STAT register will be read and the coexWlanRxAbortState field's value will be returned. + * + * @return The current value of the coexWlanRxAbortState field in the COEX_STAT register. + */ +__INLINE uint8_t nxmac_coex_wlan_rx_abort_state_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_COEX_STAT_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +/** + * @brief Returns the current value of the coexWlanTxAbortState field in the COEX_STAT register. + * + * The COEX_STAT register will be read and the coexWlanTxAbortState field's value will be returned. + * + * @return The current value of the coexWlanTxAbortState field in the COEX_STAT register. + */ +__INLINE uint8_t nxmac_coex_wlan_tx_abort_state_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_COEX_STAT_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +#endif // RW_WLAN_COEX_EN +/// @} + +#if RW_WLAN_COEX_EN +/** + * @name COEX_INT register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     03   coexWlanRxAbortFallEn   0
+ *     02   coexWlanRxAbortRiseEn   0
+ *     01   coexWlanTxAbortFallEn   0
+ *     00   coexWlanTxAbortRiseEn   0
+ * 
+ * + * @{ + */ + +/// Address of the COEX_INT register +#define NXMAC_COEX_INT_ADDR 0xC000040C +/// Offset of the COEX_INT register from the base address +#define NXMAC_COEX_INT_OFFSET 0x0000040C +/// Index of the COEX_INT register +#define NXMAC_COEX_INT_INDEX 0x00000103 +/// Reset value of the COEX_INT register +#define NXMAC_COEX_INT_RESET 0x00000000 + +/** + * @brief Returns the current value of the COEX_INT register. + * The COEX_INT register will be read and its value returned. + * @return The current value of the COEX_INT register. + */ +__INLINE uint32_t nxmac_coex_int_get(void) +{ + return REG_PL_RD(NXMAC_COEX_INT_ADDR); +} + +/** + * @brief Sets the COEX_INT register to a value. + * The COEX_INT register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_coex_int_set(uint32_t value) +{ + REG_PL_WR(NXMAC_COEX_INT_ADDR, value); +} + +// field definitions +/// COEX_WLAN_RX_ABORT_FALL_EN field bit +#define NXMAC_COEX_WLAN_RX_ABORT_FALL_EN_BIT ((uint32_t)0x00000008) +/// COEX_WLAN_RX_ABORT_FALL_EN field position +#define NXMAC_COEX_WLAN_RX_ABORT_FALL_EN_POS 3 +/// COEX_WLAN_RX_ABORT_RISE_EN field bit +#define NXMAC_COEX_WLAN_RX_ABORT_RISE_EN_BIT ((uint32_t)0x00000004) +/// COEX_WLAN_RX_ABORT_RISE_EN field position +#define NXMAC_COEX_WLAN_RX_ABORT_RISE_EN_POS 2 +/// COEX_WLAN_TX_ABORT_FALL_EN field bit +#define NXMAC_COEX_WLAN_TX_ABORT_FALL_EN_BIT ((uint32_t)0x00000002) +/// COEX_WLAN_TX_ABORT_FALL_EN field position +#define NXMAC_COEX_WLAN_TX_ABORT_FALL_EN_POS 1 +/// COEX_WLAN_TX_ABORT_RISE_EN field bit +#define NXMAC_COEX_WLAN_TX_ABORT_RISE_EN_BIT ((uint32_t)0x00000001) +/// COEX_WLAN_TX_ABORT_RISE_EN field position +#define NXMAC_COEX_WLAN_TX_ABORT_RISE_EN_POS 0 + +/// COEX_WLAN_RX_ABORT_FALL_EN field reset value +#define NXMAC_COEX_WLAN_RX_ABORT_FALL_EN_RST 0x0 +/// COEX_WLAN_RX_ABORT_RISE_EN field reset value +#define NXMAC_COEX_WLAN_RX_ABORT_RISE_EN_RST 0x0 +/// COEX_WLAN_TX_ABORT_FALL_EN field reset value +#define NXMAC_COEX_WLAN_TX_ABORT_FALL_EN_RST 0x0 +/// COEX_WLAN_TX_ABORT_RISE_EN field reset value +#define NXMAC_COEX_WLAN_TX_ABORT_RISE_EN_RST 0x0 + +/** + * @brief Constructs a value for the COEX_INT register given values for its fields + * and writes the value to the register. + * + * @param[in] coexwlanrxabortfallen - The value to use for the coexWlanRxAbortFallEn field. + * @param[in] coexwlanrxabortriseen - The value to use for the coexWlanRxAbortRiseEn field. + * @param[in] coexwlantxabortfallen - The value to use for the coexWlanTxAbortFallEn field. + * @param[in] coexwlantxabortriseen - The value to use for the coexWlanTxAbortRiseEn field. + */ +__INLINE void nxmac_coex_int_pack(uint8_t coexwlanrxabortfallen, uint8_t coexwlanrxabortriseen, uint8_t coexwlantxabortfallen, uint8_t coexwlantxabortriseen) +{ + ASSERT_ERR((((uint32_t)coexwlanrxabortfallen << 3) & ~((uint32_t)0x00000008)) == 0); + ASSERT_ERR((((uint32_t)coexwlanrxabortriseen << 2) & ~((uint32_t)0x00000004)) == 0); + ASSERT_ERR((((uint32_t)coexwlantxabortfallen << 1) & ~((uint32_t)0x00000002)) == 0); + ASSERT_ERR((((uint32_t)coexwlantxabortriseen << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_COEX_INT_ADDR, ((uint32_t)coexwlanrxabortfallen << 3) | ((uint32_t)coexwlanrxabortriseen << 2) | ((uint32_t)coexwlantxabortfallen << 1) | ((uint32_t)coexwlantxabortriseen << 0)); +} + +/** + * @brief Unpacks COEX_INT's fields from current value of the COEX_INT register. + * + * Reads the COEX_INT register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] coexwlanrxabortfallen - Will be populated with the current value of this field from the register. + * @param[out] coexwlanrxabortriseen - Will be populated with the current value of this field from the register. + * @param[out] coexwlantxabortfallen - Will be populated with the current value of this field from the register. + * @param[out] coexwlantxabortriseen - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_coex_int_unpack(uint8_t *coexwlanrxabortfallen, uint8_t *coexwlanrxabortriseen, uint8_t *coexwlantxabortfallen, uint8_t *coexwlantxabortriseen) +{ + uint32_t localVal = REG_PL_RD(NXMAC_COEX_INT_ADDR); + + *coexwlanrxabortfallen = (localVal & ((uint32_t)0x00000008)) >> 3; + *coexwlanrxabortriseen = (localVal & ((uint32_t)0x00000004)) >> 2; + *coexwlantxabortfallen = (localVal & ((uint32_t)0x00000002)) >> 1; + *coexwlantxabortriseen = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +/** + * @brief Returns the current value of the coexWlanRxAbortFallEn field in the COEX_INT register. + * + * The COEX_INT register will be read and the coexWlanRxAbortFallEn field's value will be returned. + * + * @return The current value of the coexWlanRxAbortFallEn field in the COEX_INT register. + */ +__INLINE uint8_t nxmac_coex_wlan_rx_abort_fall_en_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_COEX_INT_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +/** + * @brief Sets the coexWlanRxAbortFallEn field of the COEX_INT register. + * + * The COEX_INT register will be read, modified to contain the new field value, and written. + * + * @param[in] coexwlanrxabortfallen - The value to set the field to. + */ +__INLINE void nxmac_coex_wlan_rx_abort_fall_en_setf(uint8_t coexwlanrxabortfallen) +{ + ASSERT_ERR((((uint32_t)coexwlanrxabortfallen << 3) & ~((uint32_t)0x00000008)) == 0); + REG_PL_WR(NXMAC_COEX_INT_ADDR, (REG_PL_RD(NXMAC_COEX_INT_ADDR) & ~((uint32_t)0x00000008)) | ((uint32_t)coexwlanrxabortfallen << 3)); +} + +/** + * @brief Returns the current value of the coexWlanRxAbortRiseEn field in the COEX_INT register. + * + * The COEX_INT register will be read and the coexWlanRxAbortRiseEn field's value will be returned. + * + * @return The current value of the coexWlanRxAbortRiseEn field in the COEX_INT register. + */ +__INLINE uint8_t nxmac_coex_wlan_rx_abort_rise_en_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_COEX_INT_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +/** + * @brief Sets the coexWlanRxAbortRiseEn field of the COEX_INT register. + * + * The COEX_INT register will be read, modified to contain the new field value, and written. + * + * @param[in] coexwlanrxabortriseen - The value to set the field to. + */ +__INLINE void nxmac_coex_wlan_rx_abort_rise_en_setf(uint8_t coexwlanrxabortriseen) +{ + ASSERT_ERR((((uint32_t)coexwlanrxabortriseen << 2) & ~((uint32_t)0x00000004)) == 0); + REG_PL_WR(NXMAC_COEX_INT_ADDR, (REG_PL_RD(NXMAC_COEX_INT_ADDR) & ~((uint32_t)0x00000004)) | ((uint32_t)coexwlanrxabortriseen << 2)); +} + +/** + * @brief Returns the current value of the coexWlanTxAbortFallEn field in the COEX_INT register. + * + * The COEX_INT register will be read and the coexWlanTxAbortFallEn field's value will be returned. + * + * @return The current value of the coexWlanTxAbortFallEn field in the COEX_INT register. + */ +__INLINE uint8_t nxmac_coex_wlan_tx_abort_fall_en_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_COEX_INT_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +/** + * @brief Sets the coexWlanTxAbortFallEn field of the COEX_INT register. + * + * The COEX_INT register will be read, modified to contain the new field value, and written. + * + * @param[in] coexwlantxabortfallen - The value to set the field to. + */ +__INLINE void nxmac_coex_wlan_tx_abort_fall_en_setf(uint8_t coexwlantxabortfallen) +{ + ASSERT_ERR((((uint32_t)coexwlantxabortfallen << 1) & ~((uint32_t)0x00000002)) == 0); + REG_PL_WR(NXMAC_COEX_INT_ADDR, (REG_PL_RD(NXMAC_COEX_INT_ADDR) & ~((uint32_t)0x00000002)) | ((uint32_t)coexwlantxabortfallen << 1)); +} + +/** + * @brief Returns the current value of the coexWlanTxAbortRiseEn field in the COEX_INT register. + * + * The COEX_INT register will be read and the coexWlanTxAbortRiseEn field's value will be returned. + * + * @return The current value of the coexWlanTxAbortRiseEn field in the COEX_INT register. + */ +__INLINE uint8_t nxmac_coex_wlan_tx_abort_rise_en_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_COEX_INT_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/** + * @brief Sets the coexWlanTxAbortRiseEn field of the COEX_INT register. + * + * The COEX_INT register will be read, modified to contain the new field value, and written. + * + * @param[in] coexwlantxabortriseen - The value to set the field to. + */ +__INLINE void nxmac_coex_wlan_tx_abort_rise_en_setf(uint8_t coexwlantxabortriseen) +{ + ASSERT_ERR((((uint32_t)coexwlantxabortriseen << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_COEX_INT_ADDR, (REG_PL_RD(NXMAC_COEX_INT_ADDR) & ~((uint32_t)0x00000001)) | ((uint32_t)coexwlantxabortriseen << 0)); +} + +#endif // RW_WLAN_COEX_EN +/// @} + +/** + * @name DEBUG_HWSM_1 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:24         macControlLs   0x0
+ *  16:08          txControlLs   0x0
+ *  05:00          rxControlLs   0x0
+ * 
+ * + * @{ + */ + +/// Address of the DEBUG_HWSM_1 register +#define NXMAC_DEBUG_HWSM_1_ADDR 0xC0000500 +/// Offset of the DEBUG_HWSM_1 register from the base address +#define NXMAC_DEBUG_HWSM_1_OFFSET 0x00000500 +/// Index of the DEBUG_HWSM_1 register +#define NXMAC_DEBUG_HWSM_1_INDEX 0x00000140 +/// Reset value of the DEBUG_HWSM_1 register +#define NXMAC_DEBUG_HWSM_1_RESET 0x00000000 + +/** + * @brief Returns the current value of the DEBUG_HWSM_1 register. + * The DEBUG_HWSM_1 register will be read and its value returned. + * @return The current value of the DEBUG_HWSM_1 register. + */ +__INLINE uint32_t nxmac_debug_hwsm_1_get(void) +{ + return REG_PL_RD(NXMAC_DEBUG_HWSM_1_ADDR); +} + +// field definitions +/// MAC_CONTROL_LS field mask +#define NXMAC_MAC_CONTROL_LS_MASK ((uint32_t)0xFF000000) +/// MAC_CONTROL_LS field LSB position +#define NXMAC_MAC_CONTROL_LS_LSB 24 +/// MAC_CONTROL_LS field width +#define NXMAC_MAC_CONTROL_LS_WIDTH ((uint32_t)0x00000008) +/// TX_CONTROL_LS field mask +#define NXMAC_TX_CONTROL_LS_MASK ((uint32_t)0x0001FF00) +/// TX_CONTROL_LS field LSB position +#define NXMAC_TX_CONTROL_LS_LSB 8 +/// TX_CONTROL_LS field width +#define NXMAC_TX_CONTROL_LS_WIDTH ((uint32_t)0x00000009) +/// RX_CONTROL_LS field mask +#define NXMAC_RX_CONTROL_LS_MASK ((uint32_t)0x0000003F) +/// RX_CONTROL_LS field LSB position +#define NXMAC_RX_CONTROL_LS_LSB 0 +/// RX_CONTROL_LS field width +#define NXMAC_RX_CONTROL_LS_WIDTH ((uint32_t)0x00000006) + +/// MAC_CONTROL_LS field reset value +#define NXMAC_MAC_CONTROL_LS_RST 0x0 +/// TX_CONTROL_LS field reset value +#define NXMAC_TX_CONTROL_LS_RST 0x0 +/// RX_CONTROL_LS field reset value +#define NXMAC_RX_CONTROL_LS_RST 0x0 + +/** + * @brief Unpacks DEBUG_HWSM_1's fields from current value of the DEBUG_HWSM_1 register. + * + * Reads the DEBUG_HWSM_1 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] maccontrolls - Will be populated with the current value of this field from the register. + * @param[out] txcontrolls - Will be populated with the current value of this field from the register. + * @param[out] rxcontrolls - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_debug_hwsm_1_unpack(uint8_t *maccontrolls, uint16_t *txcontrolls, uint8_t *rxcontrolls) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DEBUG_HWSM_1_ADDR); + + *maccontrolls = (localVal & ((uint32_t)0xFF000000)) >> 24; + *txcontrolls = (localVal & ((uint32_t)0x0001FF00)) >> 8; + *rxcontrolls = (localVal & ((uint32_t)0x0000003F)) >> 0; +} + +/** + * @brief Returns the current value of the macControlLs field in the DEBUG_HWSM_1 register. + * + * The DEBUG_HWSM_1 register will be read and the macControlLs field's value will be returned. + * + * @return The current value of the macControlLs field in the DEBUG_HWSM_1 register. + */ +__INLINE uint8_t nxmac_mac_control_ls_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DEBUG_HWSM_1_ADDR); + return ((localVal & ((uint32_t)0xFF000000)) >> 24); +} + +/** + * @brief Returns the current value of the txControlLs field in the DEBUG_HWSM_1 register. + * + * The DEBUG_HWSM_1 register will be read and the txControlLs field's value will be returned. + * + * @return The current value of the txControlLs field in the DEBUG_HWSM_1 register. + */ +__INLINE uint16_t nxmac_tx_control_ls_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DEBUG_HWSM_1_ADDR); + return ((localVal & ((uint32_t)0x0001FF00)) >> 8); +} + +/** + * @brief Returns the current value of the rxControlLs field in the DEBUG_HWSM_1 register. + * + * The DEBUG_HWSM_1 register will be read and the rxControlLs field's value will be returned. + * + * @return The current value of the rxControlLs field in the DEBUG_HWSM_1 register. + */ +__INLINE uint8_t nxmac_rx_control_ls_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DEBUG_HWSM_1_ADDR); + return ((localVal & ((uint32_t)0x0000003F)) >> 0); +} + +/// @} + +/** + * @name DEBUG_HWSM_2 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:24         macControlCs   0x0
+ *  16:08          txControlCs   0x0
+ *  05:00          rxControlCs   0x0
+ * 
+ * + * @{ + */ + +/// Address of the DEBUG_HWSM_2 register +#define NXMAC_DEBUG_HWSM_2_ADDR 0xC0000504 +/// Offset of the DEBUG_HWSM_2 register from the base address +#define NXMAC_DEBUG_HWSM_2_OFFSET 0x00000504 +/// Index of the DEBUG_HWSM_2 register +#define NXMAC_DEBUG_HWSM_2_INDEX 0x00000141 +/// Reset value of the DEBUG_HWSM_2 register +#define NXMAC_DEBUG_HWSM_2_RESET 0x00000000 + +/** + * @brief Returns the current value of the DEBUG_HWSM_2 register. + * The DEBUG_HWSM_2 register will be read and its value returned. + * @return The current value of the DEBUG_HWSM_2 register. + */ +__INLINE uint32_t nxmac_debug_hwsm_2_get(void) +{ + return REG_PL_RD(NXMAC_DEBUG_HWSM_2_ADDR); +} + +// field definitions +/// MAC_CONTROL_CS field mask +#define NXMAC_MAC_CONTROL_CS_MASK ((uint32_t)0xFF000000) +/// MAC_CONTROL_CS field LSB position +#define NXMAC_MAC_CONTROL_CS_LSB 24 +/// MAC_CONTROL_CS field width +#define NXMAC_MAC_CONTROL_CS_WIDTH ((uint32_t)0x00000008) +/// TX_CONTROL_CS field mask +#define NXMAC_TX_CONTROL_CS_MASK ((uint32_t)0x0001FF00) +/// TX_CONTROL_CS field LSB position +#define NXMAC_TX_CONTROL_CS_LSB 8 +/// TX_CONTROL_CS field width +#define NXMAC_TX_CONTROL_CS_WIDTH ((uint32_t)0x00000009) +/// RX_CONTROL_CS field mask +#define NXMAC_RX_CONTROL_CS_MASK ((uint32_t)0x0000003F) +/// RX_CONTROL_CS field LSB position +#define NXMAC_RX_CONTROL_CS_LSB 0 +/// RX_CONTROL_CS field width +#define NXMAC_RX_CONTROL_CS_WIDTH ((uint32_t)0x00000006) + +/// MAC_CONTROL_CS field reset value +#define NXMAC_MAC_CONTROL_CS_RST 0x0 +/// TX_CONTROL_CS field reset value +#define NXMAC_TX_CONTROL_CS_RST 0x0 +/// RX_CONTROL_CS field reset value +#define NXMAC_RX_CONTROL_CS_RST 0x0 + +/** + * @brief Unpacks DEBUG_HWSM_2's fields from current value of the DEBUG_HWSM_2 register. + * + * Reads the DEBUG_HWSM_2 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] maccontrolcs - Will be populated with the current value of this field from the register. + * @param[out] txcontrolcs - Will be populated with the current value of this field from the register. + * @param[out] rxcontrolcs - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_debug_hwsm_2_unpack(uint8_t *maccontrolcs, uint16_t *txcontrolcs, uint8_t *rxcontrolcs) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DEBUG_HWSM_2_ADDR); + + *maccontrolcs = (localVal & ((uint32_t)0xFF000000)) >> 24; + *txcontrolcs = (localVal & ((uint32_t)0x0001FF00)) >> 8; + *rxcontrolcs = (localVal & ((uint32_t)0x0000003F)) >> 0; +} + +/** + * @brief Returns the current value of the macControlCs field in the DEBUG_HWSM_2 register. + * + * The DEBUG_HWSM_2 register will be read and the macControlCs field's value will be returned. + * + * @return The current value of the macControlCs field in the DEBUG_HWSM_2 register. + */ +__INLINE uint8_t nxmac_mac_control_cs_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DEBUG_HWSM_2_ADDR); + return ((localVal & ((uint32_t)0xFF000000)) >> 24); +} + +/** + * @brief Returns the current value of the txControlCs field in the DEBUG_HWSM_2 register. + * + * The DEBUG_HWSM_2 register will be read and the txControlCs field's value will be returned. + * + * @return The current value of the txControlCs field in the DEBUG_HWSM_2 register. + */ +__INLINE uint16_t nxmac_tx_control_cs_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DEBUG_HWSM_2_ADDR); + return ((localVal & ((uint32_t)0x0001FF00)) >> 8); +} + +/** + * @brief Returns the current value of the rxControlCs field in the DEBUG_HWSM_2 register. + * + * The DEBUG_HWSM_2 register will be read and the rxControlCs field's value will be returned. + * + * @return The current value of the rxControlCs field in the DEBUG_HWSM_2 register. + */ +__INLINE uint8_t nxmac_rx_control_cs_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DEBUG_HWSM_2_ADDR); + return ((localVal & ((uint32_t)0x0000003F)) >> 0); +} + +/// @} + +/** + * @name DEBUG_PORT_VALUE register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00        debugPortRead   0x0
+ * 
+ * + * @{ + */ + +/// Address of the DEBUG_PORT_VALUE register +#define NXMAC_DEBUG_PORT_VALUE_ADDR 0xC000050C +/// Offset of the DEBUG_PORT_VALUE register from the base address +#define NXMAC_DEBUG_PORT_VALUE_OFFSET 0x0000050C +/// Index of the DEBUG_PORT_VALUE register +#define NXMAC_DEBUG_PORT_VALUE_INDEX 0x00000143 +/// Reset value of the DEBUG_PORT_VALUE register +#define NXMAC_DEBUG_PORT_VALUE_RESET 0x00000000 + +/** + * @brief Returns the current value of the DEBUG_PORT_VALUE register. + * The DEBUG_PORT_VALUE register will be read and its value returned. + * @return The current value of the DEBUG_PORT_VALUE register. + */ +__INLINE uint32_t nxmac_debug_port_value_get(void) +{ + return REG_PL_RD(NXMAC_DEBUG_PORT_VALUE_ADDR); +} + +// field definitions +/// DEBUG_PORT_READ field mask +#define NXMAC_DEBUG_PORT_READ_MASK ((uint32_t)0xFFFFFFFF) +/// DEBUG_PORT_READ field LSB position +#define NXMAC_DEBUG_PORT_READ_LSB 0 +/// DEBUG_PORT_READ field width +#define NXMAC_DEBUG_PORT_READ_WIDTH ((uint32_t)0x00000020) + +/// DEBUG_PORT_READ field reset value +#define NXMAC_DEBUG_PORT_READ_RST 0x0 + +/** + * @brief Returns the current value of the debugPortRead field in the DEBUG_PORT_VALUE register. + * + * The DEBUG_PORT_VALUE register will be read and the debugPortRead field's value will be returned. + * + * @return The current value of the debugPortRead field in the DEBUG_PORT_VALUE register. + */ +__INLINE uint32_t nxmac_debug_port_read_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DEBUG_PORT_VALUE_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/// @} + +/** + * @name DEBUG_PORT_SEL register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:08        debugPortSel2   0x0
+ *  07:00        debugPortSel1   0x0
+ * 
+ * + * @{ + */ + +/// Address of the DEBUG_PORT_SEL register +#define NXMAC_DEBUG_PORT_SEL_ADDR 0xC0000510 +/// Offset of the DEBUG_PORT_SEL register from the base address +#define NXMAC_DEBUG_PORT_SEL_OFFSET 0x00000510 +/// Index of the DEBUG_PORT_SEL register +#define NXMAC_DEBUG_PORT_SEL_INDEX 0x00000144 +/// Reset value of the DEBUG_PORT_SEL register +#define NXMAC_DEBUG_PORT_SEL_RESET 0x00000000 + +/** + * @brief Returns the current value of the DEBUG_PORT_SEL register. + * The DEBUG_PORT_SEL register will be read and its value returned. + * @return The current value of the DEBUG_PORT_SEL register. + */ +__INLINE uint32_t nxmac_debug_port_sel_get(void) +{ + return REG_PL_RD(NXMAC_DEBUG_PORT_SEL_ADDR); +} + +/** + * @brief Sets the DEBUG_PORT_SEL register to a value. + * The DEBUG_PORT_SEL register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_debug_port_sel_set(uint32_t value) +{ + REG_PL_WR(NXMAC_DEBUG_PORT_SEL_ADDR, value); +} + +// field definitions +/// DEBUG_PORT_SEL_2 field mask +#define NXMAC_DEBUG_PORT_SEL_2_MASK ((uint32_t)0x0000FF00) +/// DEBUG_PORT_SEL_2 field LSB position +#define NXMAC_DEBUG_PORT_SEL_2_LSB 8 +/// DEBUG_PORT_SEL_2 field width +#define NXMAC_DEBUG_PORT_SEL_2_WIDTH ((uint32_t)0x00000008) +/// DEBUG_PORT_SEL_1 field mask +#define NXMAC_DEBUG_PORT_SEL_1_MASK ((uint32_t)0x000000FF) +/// DEBUG_PORT_SEL_1 field LSB position +#define NXMAC_DEBUG_PORT_SEL_1_LSB 0 +/// DEBUG_PORT_SEL_1 field width +#define NXMAC_DEBUG_PORT_SEL_1_WIDTH ((uint32_t)0x00000008) + +/// DEBUG_PORT_SEL_2 field reset value +#define NXMAC_DEBUG_PORT_SEL_2_RST 0x0 +/// DEBUG_PORT_SEL_1 field reset value +#define NXMAC_DEBUG_PORT_SEL_1_RST 0x0 + +/** + * @brief Constructs a value for the DEBUG_PORT_SEL register given values for its fields + * and writes the value to the register. + * + * @param[in] debugportsel2 - The value to use for the debugPortSel2 field. + * @param[in] debugportsel1 - The value to use for the debugPortSel1 field. + */ +__INLINE void nxmac_debug_port_sel_pack(uint8_t debugportsel2, uint8_t debugportsel1) +{ + ASSERT_ERR((((uint32_t)debugportsel2 << 8) & ~((uint32_t)0x0000FF00)) == 0); + ASSERT_ERR((((uint32_t)debugportsel1 << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(NXMAC_DEBUG_PORT_SEL_ADDR, ((uint32_t)debugportsel2 << 8) | ((uint32_t)debugportsel1 << 0)); +} + +/** + * @brief Unpacks DEBUG_PORT_SEL's fields from current value of the DEBUG_PORT_SEL register. + * + * Reads the DEBUG_PORT_SEL register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] debugportsel2 - Will be populated with the current value of this field from the register. + * @param[out] debugportsel1 - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_debug_port_sel_unpack(uint8_t *debugportsel2, uint8_t *debugportsel1) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DEBUG_PORT_SEL_ADDR); + + *debugportsel2 = (localVal & ((uint32_t)0x0000FF00)) >> 8; + *debugportsel1 = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +/** + * @brief Returns the current value of the debugPortSel2 field in the DEBUG_PORT_SEL register. + * + * The DEBUG_PORT_SEL register will be read and the debugPortSel2 field's value will be returned. + * + * @return The current value of the debugPortSel2 field in the DEBUG_PORT_SEL register. + */ +__INLINE uint8_t nxmac_debug_port_sel_2_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DEBUG_PORT_SEL_ADDR); + return ((localVal & ((uint32_t)0x0000FF00)) >> 8); +} + +/** + * @brief Sets the debugPortSel2 field of the DEBUG_PORT_SEL register. + * + * The DEBUG_PORT_SEL register will be read, modified to contain the new field value, and written. + * + * @param[in] debugportsel2 - The value to set the field to. + */ +__INLINE void nxmac_debug_port_sel_2_setf(uint8_t debugportsel2) +{ + ASSERT_ERR((((uint32_t)debugportsel2 << 8) & ~((uint32_t)0x0000FF00)) == 0); + REG_PL_WR(NXMAC_DEBUG_PORT_SEL_ADDR, (REG_PL_RD(NXMAC_DEBUG_PORT_SEL_ADDR) & ~((uint32_t)0x0000FF00)) | ((uint32_t)debugportsel2 << 8)); +} + +/** + * @brief Returns the current value of the debugPortSel1 field in the DEBUG_PORT_SEL register. + * + * The DEBUG_PORT_SEL register will be read and the debugPortSel1 field's value will be returned. + * + * @return The current value of the debugPortSel1 field in the DEBUG_PORT_SEL register. + */ +__INLINE uint8_t nxmac_debug_port_sel_1_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DEBUG_PORT_SEL_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +/** + * @brief Sets the debugPortSel1 field of the DEBUG_PORT_SEL register. + * + * The DEBUG_PORT_SEL register will be read, modified to contain the new field value, and written. + * + * @param[in] debugportsel1 - The value to set the field to. + */ +__INLINE void nxmac_debug_port_sel_1_setf(uint8_t debugportsel1) +{ + ASSERT_ERR((((uint32_t)debugportsel1 << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(NXMAC_DEBUG_PORT_SEL_ADDR, (REG_PL_RD(NXMAC_DEBUG_PORT_SEL_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)debugportsel1 << 0)); +} + +/// @} + +/** + * @name DEBUG_NAV register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  25:00           navCounter   0x0
+ * 
+ * + * @{ + */ + +/// Address of the DEBUG_NAV register +#define NXMAC_DEBUG_NAV_ADDR 0xC0000514 +/// Offset of the DEBUG_NAV register from the base address +#define NXMAC_DEBUG_NAV_OFFSET 0x00000514 +/// Index of the DEBUG_NAV register +#define NXMAC_DEBUG_NAV_INDEX 0x00000145 +/// Reset value of the DEBUG_NAV register +#define NXMAC_DEBUG_NAV_RESET 0x00000000 + +/** + * @brief Returns the current value of the DEBUG_NAV register. + * The DEBUG_NAV register will be read and its value returned. + * @return The current value of the DEBUG_NAV register. + */ +__INLINE uint32_t nxmac_debug_nav_get(void) +{ + return REG_PL_RD(NXMAC_DEBUG_NAV_ADDR); +} + +/** + * @brief Sets the DEBUG_NAV register to a value. + * The DEBUG_NAV register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_debug_nav_set(uint32_t value) +{ + REG_PL_WR(NXMAC_DEBUG_NAV_ADDR, value); +} + +// field definitions +/// NAV_COUNTER field mask +#define NXMAC_NAV_COUNTER_MASK ((uint32_t)0x03FFFFFF) +/// NAV_COUNTER field LSB position +#define NXMAC_NAV_COUNTER_LSB 0 +/// NAV_COUNTER field width +#define NXMAC_NAV_COUNTER_WIDTH ((uint32_t)0x0000001A) + +/// NAV_COUNTER field reset value +#define NXMAC_NAV_COUNTER_RST 0x0 + +/** + * @brief Returns the current value of the navCounter field in the DEBUG_NAV register. + * + * The DEBUG_NAV register will be read and the navCounter field's value will be returned. + * + * @return The current value of the navCounter field in the DEBUG_NAV register. + */ +__INLINE uint32_t nxmac_nav_counter_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DEBUG_NAV_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x03FFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the navCounter field of the DEBUG_NAV register. + * + * The DEBUG_NAV register will be read, modified to contain the new field value, and written. + * + * @param[in] navcounter - The value to set the field to. + */ +__INLINE void nxmac_nav_counter_setf(uint32_t navcounter) +{ + ASSERT_ERR((((uint32_t)navcounter << 0) & ~((uint32_t)0x03FFFFFF)) == 0); + REG_PL_WR(NXMAC_DEBUG_NAV_ADDR, (uint32_t)navcounter << 0); +} + +/// @} + +/** + * @name DEBUG_CW register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  25:24        backoffOffset   0x0
+ *  17:16             activeAC   0x0
+ *  15:12           currentCW3   0x2
+ *  11:08           currentCW2   0x3
+ *  07:04           currentCW1   0x4
+ *  03:00           currentCW0   0x4
+ * 
+ * + * @{ + */ + +/// Address of the DEBUG_CW register +#define NXMAC_DEBUG_CW_ADDR 0xC0000518 +/// Offset of the DEBUG_CW register from the base address +#define NXMAC_DEBUG_CW_OFFSET 0x00000518 +/// Index of the DEBUG_CW register +#define NXMAC_DEBUG_CW_INDEX 0x00000146 +/// Reset value of the DEBUG_CW register +#define NXMAC_DEBUG_CW_RESET 0x00002344 + +/** + * @brief Returns the current value of the DEBUG_CW register. + * The DEBUG_CW register will be read and its value returned. + * @return The current value of the DEBUG_CW register. + */ +__INLINE uint32_t nxmac_debug_cw_get(void) +{ + return REG_PL_RD(NXMAC_DEBUG_CW_ADDR); +} + +/** + * @brief Sets the DEBUG_CW register to a value. + * The DEBUG_CW register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_debug_cw_set(uint32_t value) +{ + REG_PL_WR(NXMAC_DEBUG_CW_ADDR, value); +} + +// field definitions +/// BACKOFF_OFFSET field mask +#define NXMAC_BACKOFF_OFFSET_MASK ((uint32_t)0x03000000) +/// BACKOFF_OFFSET field LSB position +#define NXMAC_BACKOFF_OFFSET_LSB 24 +/// BACKOFF_OFFSET field width +#define NXMAC_BACKOFF_OFFSET_WIDTH ((uint32_t)0x00000002) +/// ACTIVE_AC field mask +#define NXMAC_ACTIVE_AC_MASK ((uint32_t)0x00030000) +/// ACTIVE_AC field LSB position +#define NXMAC_ACTIVE_AC_LSB 16 +/// ACTIVE_AC field width +#define NXMAC_ACTIVE_AC_WIDTH ((uint32_t)0x00000002) +/// CURRENT_CW_3 field mask +#define NXMAC_CURRENT_CW_3_MASK ((uint32_t)0x0000F000) +/// CURRENT_CW_3 field LSB position +#define NXMAC_CURRENT_CW_3_LSB 12 +/// CURRENT_CW_3 field width +#define NXMAC_CURRENT_CW_3_WIDTH ((uint32_t)0x00000004) +/// CURRENT_CW_2 field mask +#define NXMAC_CURRENT_CW_2_MASK ((uint32_t)0x00000F00) +/// CURRENT_CW_2 field LSB position +#define NXMAC_CURRENT_CW_2_LSB 8 +/// CURRENT_CW_2 field width +#define NXMAC_CURRENT_CW_2_WIDTH ((uint32_t)0x00000004) +/// CURRENT_CW_1 field mask +#define NXMAC_CURRENT_CW_1_MASK ((uint32_t)0x000000F0) +/// CURRENT_CW_1 field LSB position +#define NXMAC_CURRENT_CW_1_LSB 4 +/// CURRENT_CW_1 field width +#define NXMAC_CURRENT_CW_1_WIDTH ((uint32_t)0x00000004) +/// CURRENT_CW_0 field mask +#define NXMAC_CURRENT_CW_0_MASK ((uint32_t)0x0000000F) +/// CURRENT_CW_0 field LSB position +#define NXMAC_CURRENT_CW_0_LSB 0 +/// CURRENT_CW_0 field width +#define NXMAC_CURRENT_CW_0_WIDTH ((uint32_t)0x00000004) + +/// BACKOFF_OFFSET field reset value +#define NXMAC_BACKOFF_OFFSET_RST 0x0 +/// ACTIVE_AC field reset value +#define NXMAC_ACTIVE_AC_RST 0x0 +/// CURRENT_CW_3 field reset value +#define NXMAC_CURRENT_CW_3_RST 0x2 +/// CURRENT_CW_2 field reset value +#define NXMAC_CURRENT_CW_2_RST 0x3 +/// CURRENT_CW_1 field reset value +#define NXMAC_CURRENT_CW_1_RST 0x4 +/// CURRENT_CW_0 field reset value +#define NXMAC_CURRENT_CW_0_RST 0x4 + +/** + * @brief Unpacks DEBUG_CW's fields from current value of the DEBUG_CW register. + * + * Reads the DEBUG_CW register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] backoffoffset - Will be populated with the current value of this field from the register. + * @param[out] activeac - Will be populated with the current value of this field from the register. + * @param[out] currentcw3 - Will be populated with the current value of this field from the register. + * @param[out] currentcw2 - Will be populated with the current value of this field from the register. + * @param[out] currentcw1 - Will be populated with the current value of this field from the register. + * @param[out] currentcw0 - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_debug_cw_unpack(uint8_t *backoffoffset, uint8_t *activeac, uint8_t *currentcw3, uint8_t *currentcw2, uint8_t *currentcw1, uint8_t *currentcw0) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DEBUG_CW_ADDR); + + *backoffoffset = (localVal & ((uint32_t)0x03000000)) >> 24; + *activeac = (localVal & ((uint32_t)0x00030000)) >> 16; + *currentcw3 = (localVal & ((uint32_t)0x0000F000)) >> 12; + *currentcw2 = (localVal & ((uint32_t)0x00000F00)) >> 8; + *currentcw1 = (localVal & ((uint32_t)0x000000F0)) >> 4; + *currentcw0 = (localVal & ((uint32_t)0x0000000F)) >> 0; +} + +/** + * @brief Returns the current value of the backoffOffset field in the DEBUG_CW register. + * + * The DEBUG_CW register will be read and the backoffOffset field's value will be returned. + * + * @return The current value of the backoffOffset field in the DEBUG_CW register. + */ +__INLINE uint8_t nxmac_backoff_offset_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DEBUG_CW_ADDR); + return ((localVal & ((uint32_t)0x03000000)) >> 24); +} + +/** + * @brief Sets the backoffOffset field of the DEBUG_CW register. + * + * The DEBUG_CW register will be read, modified to contain the new field value, and written. + * + * @param[in] backoffoffset - The value to set the field to. + */ +__INLINE void nxmac_backoff_offset_setf(uint8_t backoffoffset) +{ + ASSERT_ERR((((uint32_t)backoffoffset << 24) & ~((uint32_t)0x03000000)) == 0); + REG_PL_WR(NXMAC_DEBUG_CW_ADDR, (uint32_t)backoffoffset << 24); +} + +/** + * @brief Returns the current value of the activeAC field in the DEBUG_CW register. + * + * The DEBUG_CW register will be read and the activeAC field's value will be returned. + * + * @return The current value of the activeAC field in the DEBUG_CW register. + */ +__INLINE uint8_t nxmac_active_ac_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DEBUG_CW_ADDR); + return ((localVal & ((uint32_t)0x00030000)) >> 16); +} + +/** + * @brief Returns the current value of the currentCW3 field in the DEBUG_CW register. + * + * The DEBUG_CW register will be read and the currentCW3 field's value will be returned. + * + * @return The current value of the currentCW3 field in the DEBUG_CW register. + */ +__INLINE uint8_t nxmac_current_cw_3_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DEBUG_CW_ADDR); + return ((localVal & ((uint32_t)0x0000F000)) >> 12); +} + +/** + * @brief Returns the current value of the currentCW2 field in the DEBUG_CW register. + * + * The DEBUG_CW register will be read and the currentCW2 field's value will be returned. + * + * @return The current value of the currentCW2 field in the DEBUG_CW register. + */ +__INLINE uint8_t nxmac_current_cw_2_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DEBUG_CW_ADDR); + return ((localVal & ((uint32_t)0x00000F00)) >> 8); +} + +/** + * @brief Returns the current value of the currentCW1 field in the DEBUG_CW register. + * + * The DEBUG_CW register will be read and the currentCW1 field's value will be returned. + * + * @return The current value of the currentCW1 field in the DEBUG_CW register. + */ +__INLINE uint8_t nxmac_current_cw_1_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DEBUG_CW_ADDR); + return ((localVal & ((uint32_t)0x000000F0)) >> 4); +} + +/** + * @brief Returns the current value of the currentCW0 field in the DEBUG_CW register. + * + * The DEBUG_CW register will be read and the currentCW0 field's value will be returned. + * + * @return The current value of the currentCW0 field in the DEBUG_CW register. + */ +__INLINE uint8_t nxmac_current_cw_0_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DEBUG_CW_ADDR); + return ((localVal & ((uint32_t)0x0000000F)) >> 0); +} + +/// @} + +/** + * @name DEBUG_QSRC register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:24              ac3QSRC   0x0
+ *  23:16              ac2QSRC   0x0
+ *  15:08              ac1QSRC   0x0
+ *  07:00              ac0QSRC   0x0
+ * 
+ * + * @{ + */ + +/// Address of the DEBUG_QSRC register +#define NXMAC_DEBUG_QSRC_ADDR 0xC000051C +/// Offset of the DEBUG_QSRC register from the base address +#define NXMAC_DEBUG_QSRC_OFFSET 0x0000051C +/// Index of the DEBUG_QSRC register +#define NXMAC_DEBUG_QSRC_INDEX 0x00000147 +/// Reset value of the DEBUG_QSRC register +#define NXMAC_DEBUG_QSRC_RESET 0x00000000 + +/** + * @brief Returns the current value of the DEBUG_QSRC register. + * The DEBUG_QSRC register will be read and its value returned. + * @return The current value of the DEBUG_QSRC register. + */ +__INLINE uint32_t nxmac_debug_qsrc_get(void) +{ + return REG_PL_RD(NXMAC_DEBUG_QSRC_ADDR); +} + +// field definitions +/// AC_3QSRC field mask +#define NXMAC_AC_3QSRC_MASK ((uint32_t)0xFF000000) +/// AC_3QSRC field LSB position +#define NXMAC_AC_3QSRC_LSB 24 +/// AC_3QSRC field width +#define NXMAC_AC_3QSRC_WIDTH ((uint32_t)0x00000008) +/// AC_2QSRC field mask +#define NXMAC_AC_2QSRC_MASK ((uint32_t)0x00FF0000) +/// AC_2QSRC field LSB position +#define NXMAC_AC_2QSRC_LSB 16 +/// AC_2QSRC field width +#define NXMAC_AC_2QSRC_WIDTH ((uint32_t)0x00000008) +/// AC_1QSRC field mask +#define NXMAC_AC_1QSRC_MASK ((uint32_t)0x0000FF00) +/// AC_1QSRC field LSB position +#define NXMAC_AC_1QSRC_LSB 8 +/// AC_1QSRC field width +#define NXMAC_AC_1QSRC_WIDTH ((uint32_t)0x00000008) +/// AC_0QSRC field mask +#define NXMAC_AC_0QSRC_MASK ((uint32_t)0x000000FF) +/// AC_0QSRC field LSB position +#define NXMAC_AC_0QSRC_LSB 0 +/// AC_0QSRC field width +#define NXMAC_AC_0QSRC_WIDTH ((uint32_t)0x00000008) + +/// AC_3QSRC field reset value +#define NXMAC_AC_3QSRC_RST 0x0 +/// AC_2QSRC field reset value +#define NXMAC_AC_2QSRC_RST 0x0 +/// AC_1QSRC field reset value +#define NXMAC_AC_1QSRC_RST 0x0 +/// AC_0QSRC field reset value +#define NXMAC_AC_0QSRC_RST 0x0 + +/** + * @brief Unpacks DEBUG_QSRC's fields from current value of the DEBUG_QSRC register. + * + * Reads the DEBUG_QSRC register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] ac3qsrc - Will be populated with the current value of this field from the register. + * @param[out] ac2qsrc - Will be populated with the current value of this field from the register. + * @param[out] ac1qsrc - Will be populated with the current value of this field from the register. + * @param[out] ac0qsrc - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_debug_qsrc_unpack(uint8_t *ac3qsrc, uint8_t *ac2qsrc, uint8_t *ac1qsrc, uint8_t *ac0qsrc) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DEBUG_QSRC_ADDR); + + *ac3qsrc = (localVal & ((uint32_t)0xFF000000)) >> 24; + *ac2qsrc = (localVal & ((uint32_t)0x00FF0000)) >> 16; + *ac1qsrc = (localVal & ((uint32_t)0x0000FF00)) >> 8; + *ac0qsrc = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +/** + * @brief Returns the current value of the ac3QSRC field in the DEBUG_QSRC register. + * + * The DEBUG_QSRC register will be read and the ac3QSRC field's value will be returned. + * + * @return The current value of the ac3QSRC field in the DEBUG_QSRC register. + */ +__INLINE uint8_t nxmac_ac_3qsrc_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DEBUG_QSRC_ADDR); + return ((localVal & ((uint32_t)0xFF000000)) >> 24); +} + +/** + * @brief Returns the current value of the ac2QSRC field in the DEBUG_QSRC register. + * + * The DEBUG_QSRC register will be read and the ac2QSRC field's value will be returned. + * + * @return The current value of the ac2QSRC field in the DEBUG_QSRC register. + */ +__INLINE uint8_t nxmac_ac_2qsrc_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DEBUG_QSRC_ADDR); + return ((localVal & ((uint32_t)0x00FF0000)) >> 16); +} + +/** + * @brief Returns the current value of the ac1QSRC field in the DEBUG_QSRC register. + * + * The DEBUG_QSRC register will be read and the ac1QSRC field's value will be returned. + * + * @return The current value of the ac1QSRC field in the DEBUG_QSRC register. + */ +__INLINE uint8_t nxmac_ac_1qsrc_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DEBUG_QSRC_ADDR); + return ((localVal & ((uint32_t)0x0000FF00)) >> 8); +} + +/** + * @brief Returns the current value of the ac0QSRC field in the DEBUG_QSRC register. + * + * The DEBUG_QSRC register will be read and the ac0QSRC field's value will be returned. + * + * @return The current value of the ac0QSRC field in the DEBUG_QSRC register. + */ +__INLINE uint8_t nxmac_ac_0qsrc_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DEBUG_QSRC_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +/// @} + +/** + * @name DEBUG_QLRC register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:24              ac3QLRC   0x0
+ *  23:16              ac2QLRC   0x0
+ *  15:08              ac1QLRC   0x0
+ *  07:00              ac0QLRC   0x0
+ * 
+ * + * @{ + */ + +/// Address of the DEBUG_QLRC register +#define NXMAC_DEBUG_QLRC_ADDR 0xC0000520 +/// Offset of the DEBUG_QLRC register from the base address +#define NXMAC_DEBUG_QLRC_OFFSET 0x00000520 +/// Index of the DEBUG_QLRC register +#define NXMAC_DEBUG_QLRC_INDEX 0x00000148 +/// Reset value of the DEBUG_QLRC register +#define NXMAC_DEBUG_QLRC_RESET 0x00000000 + +/** + * @brief Returns the current value of the DEBUG_QLRC register. + * The DEBUG_QLRC register will be read and its value returned. + * @return The current value of the DEBUG_QLRC register. + */ +__INLINE uint32_t nxmac_debug_qlrc_get(void) +{ + return REG_PL_RD(NXMAC_DEBUG_QLRC_ADDR); +} + +// field definitions +/// AC_3QLRC field mask +#define NXMAC_AC_3QLRC_MASK ((uint32_t)0xFF000000) +/// AC_3QLRC field LSB position +#define NXMAC_AC_3QLRC_LSB 24 +/// AC_3QLRC field width +#define NXMAC_AC_3QLRC_WIDTH ((uint32_t)0x00000008) +/// AC_2QLRC field mask +#define NXMAC_AC_2QLRC_MASK ((uint32_t)0x00FF0000) +/// AC_2QLRC field LSB position +#define NXMAC_AC_2QLRC_LSB 16 +/// AC_2QLRC field width +#define NXMAC_AC_2QLRC_WIDTH ((uint32_t)0x00000008) +/// AC_1QLRC field mask +#define NXMAC_AC_1QLRC_MASK ((uint32_t)0x0000FF00) +/// AC_1QLRC field LSB position +#define NXMAC_AC_1QLRC_LSB 8 +/// AC_1QLRC field width +#define NXMAC_AC_1QLRC_WIDTH ((uint32_t)0x00000008) +/// AC_0QLRC field mask +#define NXMAC_AC_0QLRC_MASK ((uint32_t)0x000000FF) +/// AC_0QLRC field LSB position +#define NXMAC_AC_0QLRC_LSB 0 +/// AC_0QLRC field width +#define NXMAC_AC_0QLRC_WIDTH ((uint32_t)0x00000008) + +/// AC_3QLRC field reset value +#define NXMAC_AC_3QLRC_RST 0x0 +/// AC_2QLRC field reset value +#define NXMAC_AC_2QLRC_RST 0x0 +/// AC_1QLRC field reset value +#define NXMAC_AC_1QLRC_RST 0x0 +/// AC_0QLRC field reset value +#define NXMAC_AC_0QLRC_RST 0x0 + +/** + * @brief Unpacks DEBUG_QLRC's fields from current value of the DEBUG_QLRC register. + * + * Reads the DEBUG_QLRC register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] ac3qlrc - Will be populated with the current value of this field from the register. + * @param[out] ac2qlrc - Will be populated with the current value of this field from the register. + * @param[out] ac1qlrc - Will be populated with the current value of this field from the register. + * @param[out] ac0qlrc - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_debug_qlrc_unpack(uint8_t *ac3qlrc, uint8_t *ac2qlrc, uint8_t *ac1qlrc, uint8_t *ac0qlrc) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DEBUG_QLRC_ADDR); + + *ac3qlrc = (localVal & ((uint32_t)0xFF000000)) >> 24; + *ac2qlrc = (localVal & ((uint32_t)0x00FF0000)) >> 16; + *ac1qlrc = (localVal & ((uint32_t)0x0000FF00)) >> 8; + *ac0qlrc = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +/** + * @brief Returns the current value of the ac3QLRC field in the DEBUG_QLRC register. + * + * The DEBUG_QLRC register will be read and the ac3QLRC field's value will be returned. + * + * @return The current value of the ac3QLRC field in the DEBUG_QLRC register. + */ +__INLINE uint8_t nxmac_ac_3qlrc_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DEBUG_QLRC_ADDR); + return ((localVal & ((uint32_t)0xFF000000)) >> 24); +} + +/** + * @brief Returns the current value of the ac2QLRC field in the DEBUG_QLRC register. + * + * The DEBUG_QLRC register will be read and the ac2QLRC field's value will be returned. + * + * @return The current value of the ac2QLRC field in the DEBUG_QLRC register. + */ +__INLINE uint8_t nxmac_ac_2qlrc_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DEBUG_QLRC_ADDR); + return ((localVal & ((uint32_t)0x00FF0000)) >> 16); +} + +/** + * @brief Returns the current value of the ac1QLRC field in the DEBUG_QLRC register. + * + * The DEBUG_QLRC register will be read and the ac1QLRC field's value will be returned. + * + * @return The current value of the ac1QLRC field in the DEBUG_QLRC register. + */ +__INLINE uint8_t nxmac_ac_1qlrc_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DEBUG_QLRC_ADDR); + return ((localVal & ((uint32_t)0x0000FF00)) >> 8); +} + +/** + * @brief Returns the current value of the ac0QLRC field in the DEBUG_QLRC register. + * + * The DEBUG_QLRC register will be read and the ac0QLRC field's value will be returned. + * + * @return The current value of the ac0QLRC field in the DEBUG_QLRC register. + */ +__INLINE uint8_t nxmac_ac_0qlrc_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DEBUG_QLRC_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +/// @} + +/** + * @name DEBUG_PHY register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     01   rxEndForTimingErrRec   0
+ *     00   rxReqForceDeassertion   0
+ * 
+ * + * @{ + */ + +/// Address of the DEBUG_PHY register +#define NXMAC_DEBUG_PHY_ADDR 0xC000055C +/// Offset of the DEBUG_PHY register from the base address +#define NXMAC_DEBUG_PHY_OFFSET 0x0000055C +/// Index of the DEBUG_PHY register +#define NXMAC_DEBUG_PHY_INDEX 0x00000157 +/// Reset value of the DEBUG_PHY register +#define NXMAC_DEBUG_PHY_RESET 0x00000000 + +/** + * @brief Returns the current value of the DEBUG_PHY register. + * The DEBUG_PHY register will be read and its value returned. + * @return The current value of the DEBUG_PHY register. + */ +__INLINE uint32_t nxmac_debug_phy_get(void) +{ + return REG_PL_RD(NXMAC_DEBUG_PHY_ADDR); +} + +/** + * @brief Sets the DEBUG_PHY register to a value. + * The DEBUG_PHY register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_debug_phy_set(uint32_t value) +{ + REG_PL_WR(NXMAC_DEBUG_PHY_ADDR, value); +} + +// field definitions +/// RX_END_FOR_TIMING_ERR_REC field bit +#define NXMAC_RX_END_FOR_TIMING_ERR_REC_BIT ((uint32_t)0x00000002) +/// RX_END_FOR_TIMING_ERR_REC field position +#define NXMAC_RX_END_FOR_TIMING_ERR_REC_POS 1 +/// RX_REQ_FORCE_DEASSERTION field bit +#define NXMAC_RX_REQ_FORCE_DEASSERTION_BIT ((uint32_t)0x00000001) +/// RX_REQ_FORCE_DEASSERTION field position +#define NXMAC_RX_REQ_FORCE_DEASSERTION_POS 0 + +/// RX_END_FOR_TIMING_ERR_REC field reset value +#define NXMAC_RX_END_FOR_TIMING_ERR_REC_RST 0x0 +/// RX_REQ_FORCE_DEASSERTION field reset value +#define NXMAC_RX_REQ_FORCE_DEASSERTION_RST 0x0 + +/** + * @brief Constructs a value for the DEBUG_PHY register given values for its fields + * and writes the value to the register. + * + * @param[in] rxendfortimingerrrec - The value to use for the rxEndForTimingErrRec field. + * @param[in] rxreqforcedeassertion - The value to use for the rxReqForceDeassertion field. + */ +__INLINE void nxmac_debug_phy_pack(uint8_t rxendfortimingerrrec, uint8_t rxreqforcedeassertion) +{ + ASSERT_ERR((((uint32_t)rxendfortimingerrrec << 1) & ~((uint32_t)0x00000002)) == 0); + ASSERT_ERR((((uint32_t)rxreqforcedeassertion << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_DEBUG_PHY_ADDR, ((uint32_t)rxendfortimingerrrec << 1) | ((uint32_t)rxreqforcedeassertion << 0)); +} + +/** + * @brief Unpacks DEBUG_PHY's fields from current value of the DEBUG_PHY register. + * + * Reads the DEBUG_PHY register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] rxendfortimingerrrec - Will be populated with the current value of this field from the register. + * @param[out] rxreqforcedeassertion - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_debug_phy_unpack(uint8_t *rxendfortimingerrrec, uint8_t *rxreqforcedeassertion) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DEBUG_PHY_ADDR); + + *rxendfortimingerrrec = (localVal & ((uint32_t)0x00000002)) >> 1; + *rxreqforcedeassertion = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +/** + * @brief Returns the current value of the rxEndForTimingErrRec field in the DEBUG_PHY register. + * + * The DEBUG_PHY register will be read and the rxEndForTimingErrRec field's value will be returned. + * + * @return The current value of the rxEndForTimingErrRec field in the DEBUG_PHY register. + */ +__INLINE uint8_t nxmac_rx_end_for_timing_err_rec_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DEBUG_PHY_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +/** + * @brief Sets the rxEndForTimingErrRec field of the DEBUG_PHY register. + * + * The DEBUG_PHY register will be read, modified to contain the new field value, and written. + * + * @param[in] rxendfortimingerrrec - The value to set the field to. + */ +__INLINE void nxmac_rx_end_for_timing_err_rec_setf(uint8_t rxendfortimingerrrec) +{ + ASSERT_ERR((((uint32_t)rxendfortimingerrrec << 1) & ~((uint32_t)0x00000002)) == 0); + REG_PL_WR(NXMAC_DEBUG_PHY_ADDR, (REG_PL_RD(NXMAC_DEBUG_PHY_ADDR) & ~((uint32_t)0x00000002)) | ((uint32_t)rxendfortimingerrrec << 1)); +} + +/** + * @brief Returns the current value of the rxReqForceDeassertion field in the DEBUG_PHY register. + * + * The DEBUG_PHY register will be read and the rxReqForceDeassertion field's value will be returned. + * + * @return The current value of the rxReqForceDeassertion field in the DEBUG_PHY register. + */ +__INLINE uint8_t nxmac_rx_req_force_deassertion_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DEBUG_PHY_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/** + * @brief Sets the rxReqForceDeassertion field of the DEBUG_PHY register. + * + * The DEBUG_PHY register will be read, modified to contain the new field value, and written. + * + * @param[in] rxreqforcedeassertion - The value to set the field to. + */ +__INLINE void nxmac_rx_req_force_deassertion_setf(uint8_t rxreqforcedeassertion) +{ + ASSERT_ERR((((uint32_t)rxreqforcedeassertion << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_DEBUG_PHY_ADDR, (REG_PL_RD(NXMAC_DEBUG_PHY_ADDR) & ~((uint32_t)0x00000001)) | ((uint32_t)rxreqforcedeassertion << 0)); +} +/*lint +e91*/ + +/// @} + +#endif // _REG_MAC_CORE_H_ + +/// @} + diff --git a/beken_os/beken378/driver/common/reg/reg_mac_pl.h b/beken_os/beken378/driver/common/reg/reg_mac_pl.h new file mode 100755 index 0000000..a6355c1 --- /dev/null +++ b/beken_os/beken378/driver/common/reg/reg_mac_pl.h @@ -0,0 +1,18197 @@ +/** + * @file reg_mac_pl.h + * @brief Definitions of the NXMAC HW block registers and register access functions. + * + * @defgroup REG_MAC_PL REG_MAC_PL + * @ingroup REG + * @{ + * + * @brief Definitions of the NXMAC HW block registers and register access functions. + */ +#ifndef _REG_MAC_PL_H_ +#define _REG_MAC_PL_H_ + +#include "co_int.h" +#include "_reg_mac_pl.h" +#include "compiler.h" +#include "arch.h" +#include "reg_access.h" + +/*lint -e(91)*/ +/** @brief Number of registers in the REG_MAC_PL peripheral. + */ +#define REG_MAC_PL_COUNT 351 + +/** @brief Decoding mask of the REG_MAC_PL peripheral registers from the CPU point of view. + */ +#define REG_MAC_PL_DECODING_MASK 0x000007FF + +/** + * @name NEXT_TBTT register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:00             nextTBTT   0x0
+ * 
+ * + * @{ + */ + +/// Address of the NEXT_TBTT register +#define NXMAC_NEXT_TBTT_ADDR 0xC0008040 +/// Offset of the NEXT_TBTT register from the base address +#define NXMAC_NEXT_TBTT_OFFSET 0x00000040 +/// Index of the NEXT_TBTT register +#define NXMAC_NEXT_TBTT_INDEX 0x00000010 +/// Reset value of the NEXT_TBTT register +#define NXMAC_NEXT_TBTT_RESET 0x00000000 + +/** + * @brief Returns the current value of the NEXT_TBTT register. + * The NEXT_TBTT register will be read and its value returned. + * @return The current value of the NEXT_TBTT register. + */ +__INLINE uint32_t nxmac_next_tbtt_get(void) +{ + return REG_PL_RD(NXMAC_NEXT_TBTT_ADDR); +} + +// field definitions +/// NEXT_TBTT field mask +#define NXMAC_NEXT_TBTT_MASK ((uint32_t)0x0000FFFF) +/// NEXT_TBTT field LSB position +#define NXMAC_NEXT_TBTT_LSB 0 +/// NEXT_TBTT field width +#define NXMAC_NEXT_TBTT_WIDTH ((uint32_t)0x00000010) + +/// NEXT_TBTT field reset value +#define NXMAC_NEXT_TBTT_RST 0x0 + +/** + * @brief Returns the current value of the nextTBTT field in the NEXT_TBTT register. + * + * The NEXT_TBTT register will be read and the nextTBTT field's value will be returned. + * + * @return The current value of the nextTBTT field in the NEXT_TBTT register. + */ +__INLINE uint16_t nxmac_next_tbtt_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_NEXT_TBTT_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x0000FFFF)) == 0); + return (localVal >> 0); +} + +/// @} + +/** + * @name DOZE_CNTRL_2 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31       wakeUpFromDoze   0
+ *     00             wakeUpSW   1
+ * 
+ * + * @{ + */ + +/// Address of the DOZE_CNTRL_2 register +#define NXMAC_DOZE_CNTRL_2_ADDR 0xC0008048 +/// Offset of the DOZE_CNTRL_2 register from the base address +#define NXMAC_DOZE_CNTRL_2_OFFSET 0x00000048 +/// Index of the DOZE_CNTRL_2 register +#define NXMAC_DOZE_CNTRL_2_INDEX 0x00000012 +/// Reset value of the DOZE_CNTRL_2 register +#define NXMAC_DOZE_CNTRL_2_RESET 0x00000001 + +/** + * @brief Returns the current value of the DOZE_CNTRL_2 register. + * The DOZE_CNTRL_2 register will be read and its value returned. + * @return The current value of the DOZE_CNTRL_2 register. + */ +__INLINE uint32_t nxmac_doze_cntrl_2_get(void) +{ + return REG_PL_RD(NXMAC_DOZE_CNTRL_2_ADDR); +} + +/** + * @brief Sets the DOZE_CNTRL_2 register to a value. + * The DOZE_CNTRL_2 register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_doze_cntrl_2_set(uint32_t value) +{ + REG_PL_WR(NXMAC_DOZE_CNTRL_2_ADDR, value); +} + +// field definitions +/// WAKE_UP_FROM_DOZE field bit +#define NXMAC_WAKE_UP_FROM_DOZE_BIT ((uint32_t)0x80000000) +/// WAKE_UP_FROM_DOZE field position +#define NXMAC_WAKE_UP_FROM_DOZE_POS 31 +/// WAKE_UP_SW field bit +#define NXMAC_WAKE_UP_SW_BIT ((uint32_t)0x00000001) +/// WAKE_UP_SW field position +#define NXMAC_WAKE_UP_SW_POS 0 + +/// WAKE_UP_FROM_DOZE field reset value +#define NXMAC_WAKE_UP_FROM_DOZE_RST 0x0 +/// WAKE_UP_SW field reset value +#define NXMAC_WAKE_UP_SW_RST 0x1 + +/** + * @brief Constructs a value for the DOZE_CNTRL_2 register given values for its fields + * and writes the value to the register. + * + * @param[in] wakeupfromdoze - The value to use for the wakeUpFromDoze field. + * @param[in] wakeupsw - The value to use for the wakeUpSW field. + */ +__INLINE void nxmac_doze_cntrl_2_pack(uint8_t wakeupfromdoze, uint8_t wakeupsw) +{ + ASSERT_ERR((((uint32_t)wakeupfromdoze << 31) & ~((uint32_t)0x80000000)) == 0); + ASSERT_ERR((((uint32_t)wakeupsw << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_DOZE_CNTRL_2_ADDR, ((uint32_t)wakeupfromdoze << 31) | ((uint32_t)wakeupsw << 0)); +} + +/** + * @brief Unpacks DOZE_CNTRL_2's fields from current value of the DOZE_CNTRL_2 register. + * + * Reads the DOZE_CNTRL_2 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] wakeupfromdoze - Will be populated with the current value of this field from the register. + * @param[out] wakeupsw - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_doze_cntrl_2_unpack(uint8_t *wakeupfromdoze, uint8_t *wakeupsw) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DOZE_CNTRL_2_ADDR); + + *wakeupfromdoze = (localVal & ((uint32_t)0x80000000)) >> 31; + *wakeupsw = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +/** + * @brief Returns the current value of the wakeUpFromDoze field in the DOZE_CNTRL_2 register. + * + * The DOZE_CNTRL_2 register will be read and the wakeUpFromDoze field's value will be returned. + * + * @return The current value of the wakeUpFromDoze field in the DOZE_CNTRL_2 register. + */ +__INLINE uint8_t nxmac_wake_up_from_doze_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DOZE_CNTRL_2_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +/** + * @brief Sets the wakeUpFromDoze field of the DOZE_CNTRL_2 register. + * + * The DOZE_CNTRL_2 register will be read, modified to contain the new field value, and written. + * + * @param[in] wakeupfromdoze - The value to set the field to. + */ +__INLINE void nxmac_wake_up_from_doze_setf(uint8_t wakeupfromdoze) +{ + ASSERT_ERR((((uint32_t)wakeupfromdoze << 31) & ~((uint32_t)0x80000000)) == 0); + REG_PL_WR(NXMAC_DOZE_CNTRL_2_ADDR, (REG_PL_RD(NXMAC_DOZE_CNTRL_2_ADDR) & ~((uint32_t)0x80000000)) | ((uint32_t)wakeupfromdoze << 31)); +} + +/** + * @brief Returns the current value of the wakeUpSW field in the DOZE_CNTRL_2 register. + * + * The DOZE_CNTRL_2 register will be read and the wakeUpSW field's value will be returned. + * + * @return The current value of the wakeUpSW field in the DOZE_CNTRL_2 register. + */ +__INLINE uint8_t nxmac_wake_up_sw_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DOZE_CNTRL_2_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/** + * @brief Sets the wakeUpSW field of the DOZE_CNTRL_2 register. + * + * The DOZE_CNTRL_2 register will be read, modified to contain the new field value, and written. + * + * @param[in] wakeupsw - The value to set the field to. + */ +__INLINE void nxmac_wake_up_sw_setf(uint8_t wakeupsw) +{ + ASSERT_ERR((((uint32_t)wakeupsw << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_DOZE_CNTRL_2_ADDR, (REG_PL_RD(NXMAC_DOZE_CNTRL_2_ADDR) & ~((uint32_t)0x00000001)) | ((uint32_t)wakeupsw << 0)); +} + +/// @} + +/** + * @name MAC_CNTRL_2 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     00            softReset   0
+ * 
+ * + * @{ + */ + +/// Address of the MAC_CNTRL_2 register +#define NXMAC_MAC_CNTRL_2_ADDR 0xC0008050 +/// Offset of the MAC_CNTRL_2 register from the base address +#define NXMAC_MAC_CNTRL_2_OFFSET 0x00000050 +/// Index of the MAC_CNTRL_2 register +#define NXMAC_MAC_CNTRL_2_INDEX 0x00000014 +/// Reset value of the MAC_CNTRL_2 register +#define NXMAC_MAC_CNTRL_2_RESET 0x00000000 + +/** + * @brief Returns the current value of the MAC_CNTRL_2 register. + * The MAC_CNTRL_2 register will be read and its value returned. + * @return The current value of the MAC_CNTRL_2 register. + */ +__INLINE uint32_t nxmac_mac_cntrl_2_get(void) +{ + return REG_PL_RD(NXMAC_MAC_CNTRL_2_ADDR); +} + +/** + * @brief Sets the MAC_CNTRL_2 register to a value. + * The MAC_CNTRL_2 register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_mac_cntrl_2_set(uint32_t value) +{ + REG_PL_WR(NXMAC_MAC_CNTRL_2_ADDR, value); +} + +// field definitions +/// SOFT_RESET field bit +#define NXMAC_SOFT_RESET_BIT ((uint32_t)0x00000001) +/// SOFT_RESET field position +#define NXMAC_SOFT_RESET_POS 0 + +/// SOFT_RESET field reset value +#define NXMAC_SOFT_RESET_RST 0x0 + +/** + * @brief Returns the current value of the softReset field in the MAC_CNTRL_2 register. + * + * The MAC_CNTRL_2 register will be read and the softReset field's value will be returned. + * + * @return The current value of the softReset field in the MAC_CNTRL_2 register. + */ +__INLINE uint8_t nxmac_soft_reset_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MAC_CNTRL_2_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x00000001)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the softReset field of the MAC_CNTRL_2 register. + * + * The MAC_CNTRL_2 register will be read, modified to contain the new field value, and written. + * + * @param[in] softreset - The value to set the field to. + */ +__INLINE void nxmac_soft_reset_setf(uint8_t softreset) +{ + ASSERT_ERR((((uint32_t)softreset << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_MAC_CNTRL_2_ADDR, (uint32_t)softreset << 0); +} + +/// @} + +/** + * @name GEN_INT_STATUS register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     25     rxPayloadDMADead   0
+ *     24      rxHeaderDMADead   0
+ *     23           phyRxStart   0
+ *     22               phyErr   0
+ *     21     macPHYIFUnderRun   0
+ *     20                hwErr   0
+ *     19           impSecDTIM   0
+ *     18           impPriDTIM   0
+ *     17         bcnTxDMADead   0
+ *     16         ac3TxDMADead   0
+ *     15         ac2TxDMADead   0
+ *     14         ac1TxDMADead   0
+ *     13         ac0TxDMADead   0
+ *     12              ptError   0
+ *     11               timSet   0
+ *     10             olbcDSSS   0
+ *     09             olbcOFDM   0
+ *     08       rxFIFOOverFlow   0
+ *     07           rxDMAEmpty   0
+ *     06     macPHYIFOverflow   0
+ *     05            coexEvent   0
+ *     03         absGenTimers   0
+ *     02        idleInterrupt   0
+ *     01           impSecTBTT   0
+ *     00           impPriTBTT   0
+ * 
+ * + * @{ + */ + +/// Address of the GEN_INT_STATUS register +#define NXMAC_GEN_INT_STATUS_ADDR 0xC000806C +/// Offset of the GEN_INT_STATUS register from the base address +#define NXMAC_GEN_INT_STATUS_OFFSET 0x0000006C +/// Index of the GEN_INT_STATUS register +#define NXMAC_GEN_INT_STATUS_INDEX 0x0000001B +/// Reset value of the GEN_INT_STATUS register +#define NXMAC_GEN_INT_STATUS_RESET 0x00000000 + +/** + * @brief Returns the current value of the GEN_INT_STATUS register. + * The GEN_INT_STATUS register will be read and its value returned. + * @return The current value of the GEN_INT_STATUS register. + */ +__INLINE uint32_t nxmac_gen_int_status_get(void) +{ + return REG_PL_RD(NXMAC_GEN_INT_STATUS_ADDR); +} + +/** + * @brief Sets the GEN_INT_STATUS register to a value. + * The GEN_INT_STATUS register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_gen_int_status_set(uint32_t value) +{ + REG_PL_WR(NXMAC_GEN_INT_STATUS_ADDR, value); +} + +// fields defined in symmetrical set/clear register +/** + * @brief Constructs a value for the GEN_INT_STATUS register given values for its fields + * and writes the value to the register. + * + * @param[in] rxpayloaddmadead - The value to use for the rxPayloadDMADead field. + * @param[in] rxheaderdmadead - The value to use for the rxHeaderDMADead field. + * @param[in] phyrxstart - The value to use for the phyRxStart field. + * @param[in] phyerr - The value to use for the phyErr field. + * @param[in] macphyifunderrun - The value to use for the macPHYIFUnderRun field. + * @param[in] hwerr - The value to use for the hwErr field. + * @param[in] impsecdtim - The value to use for the impSecDTIM field. + * @param[in] imppridtim - The value to use for the impPriDTIM field. + * @param[in] bcntxdmadead - The value to use for the bcnTxDMADead field. + * @param[in] ac3txdmadead - The value to use for the ac3TxDMADead field. + * @param[in] ac2txdmadead - The value to use for the ac2TxDMADead field. + * @param[in] ac1txdmadead - The value to use for the ac1TxDMADead field. + * @param[in] ac0txdmadead - The value to use for the ac0TxDMADead field. + * @param[in] pterror - The value to use for the ptError field. + * @param[in] timset - The value to use for the timSet field. + * @param[in] olbcdsss - The value to use for the olbcDSSS field. + * @param[in] olbcofdm - The value to use for the olbcOFDM field. + * @param[in] rxfifooverflow - The value to use for the rxFIFOOverFlow field. + * @param[in] rxdmaempty - The value to use for the rxDMAEmpty field. + * @param[in] macphyifoverflow - The value to use for the macPHYIFOverflow field. + * @param[in] coexevent - The value to use for the coexEvent field. + * @param[in] idleinterrupt - The value to use for the idleInterrupt field. + * @param[in] impsectbtt - The value to use for the impSecTBTT field. + * @param[in] imppritbtt - The value to use for the impPriTBTT field. + */ +__INLINE void nxmac_gen_int_status_pack(uint8_t rxpayloaddmadead, uint8_t rxheaderdmadead, uint8_t phyrxstart, uint8_t phyerr, uint8_t macphyifunderrun, uint8_t hwerr, uint8_t impsecdtim, uint8_t imppridtim, uint8_t bcntxdmadead, uint8_t ac3txdmadead, uint8_t ac2txdmadead, uint8_t ac1txdmadead, uint8_t ac0txdmadead, uint8_t pterror, uint8_t timset, uint8_t olbcdsss, uint8_t olbcofdm, uint8_t rxfifooverflow, uint8_t rxdmaempty, uint8_t macphyifoverflow, uint8_t coexevent, uint8_t idleinterrupt, uint8_t impsectbtt, uint8_t imppritbtt) +{ + ASSERT_ERR((((uint32_t)rxpayloaddmadead << 25) & ~((uint32_t)0x02000000)) == 0); + ASSERT_ERR((((uint32_t)rxheaderdmadead << 24) & ~((uint32_t)0x01000000)) == 0); + ASSERT_ERR((((uint32_t)phyrxstart << 23) & ~((uint32_t)0x00800000)) == 0); + ASSERT_ERR((((uint32_t)phyerr << 22) & ~((uint32_t)0x00400000)) == 0); + ASSERT_ERR((((uint32_t)macphyifunderrun << 21) & ~((uint32_t)0x00200000)) == 0); + ASSERT_ERR((((uint32_t)hwerr << 20) & ~((uint32_t)0x00100000)) == 0); + ASSERT_ERR((((uint32_t)impsecdtim << 19) & ~((uint32_t)0x00080000)) == 0); + ASSERT_ERR((((uint32_t)imppridtim << 18) & ~((uint32_t)0x00040000)) == 0); + ASSERT_ERR((((uint32_t)bcntxdmadead << 17) & ~((uint32_t)0x00020000)) == 0); + ASSERT_ERR((((uint32_t)ac3txdmadead << 16) & ~((uint32_t)0x00010000)) == 0); + ASSERT_ERR((((uint32_t)ac2txdmadead << 15) & ~((uint32_t)0x00008000)) == 0); + ASSERT_ERR((((uint32_t)ac1txdmadead << 14) & ~((uint32_t)0x00004000)) == 0); + ASSERT_ERR((((uint32_t)ac0txdmadead << 13) & ~((uint32_t)0x00002000)) == 0); + ASSERT_ERR((((uint32_t)pterror << 12) & ~((uint32_t)0x00001000)) == 0); + ASSERT_ERR((((uint32_t)timset << 11) & ~((uint32_t)0x00000800)) == 0); + ASSERT_ERR((((uint32_t)olbcdsss << 10) & ~((uint32_t)0x00000400)) == 0); + ASSERT_ERR((((uint32_t)olbcofdm << 9) & ~((uint32_t)0x00000200)) == 0); + ASSERT_ERR((((uint32_t)rxfifooverflow << 8) & ~((uint32_t)0x00000100)) == 0); + ASSERT_ERR((((uint32_t)rxdmaempty << 7) & ~((uint32_t)0x00000080)) == 0); + ASSERT_ERR((((uint32_t)macphyifoverflow << 6) & ~((uint32_t)0x00000040)) == 0); + ASSERT_ERR((((uint32_t)coexevent << 5) & ~((uint32_t)0x00000020)) == 0); + ASSERT_ERR((((uint32_t)idleinterrupt << 2) & ~((uint32_t)0x00000004)) == 0); + ASSERT_ERR((((uint32_t)impsectbtt << 1) & ~((uint32_t)0x00000002)) == 0); + ASSERT_ERR((((uint32_t)imppritbtt << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_GEN_INT_STATUS_ADDR, ((uint32_t)rxpayloaddmadead << 25) | ((uint32_t)rxheaderdmadead << 24) | ((uint32_t)phyrxstart << 23) | ((uint32_t)phyerr << 22) | ((uint32_t)macphyifunderrun << 21) | ((uint32_t)hwerr << 20) | ((uint32_t)impsecdtim << 19) | ((uint32_t)imppridtim << 18) | ((uint32_t)bcntxdmadead << 17) | ((uint32_t)ac3txdmadead << 16) | ((uint32_t)ac2txdmadead << 15) | ((uint32_t)ac1txdmadead << 14) | ((uint32_t)ac0txdmadead << 13) | ((uint32_t)pterror << 12) | ((uint32_t)timset << 11) | ((uint32_t)olbcdsss << 10) | ((uint32_t)olbcofdm << 9) | ((uint32_t)rxfifooverflow << 8) | ((uint32_t)rxdmaempty << 7) | ((uint32_t)macphyifoverflow << 6) | ((uint32_t)coexevent << 5) | ((uint32_t)idleinterrupt << 2) | ((uint32_t)impsectbtt << 1) | ((uint32_t)imppritbtt << 0)); +} + +/** + * @brief Unpacks GEN_INT_STATUS's fields from current value of the GEN_INT_STATUS register. + * + * Reads the GEN_INT_STATUS register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] rxpayloaddmadead - Will be populated with the current value of this field from the register. + * @param[out] rxheaderdmadead - Will be populated with the current value of this field from the register. + * @param[out] phyrxstart - Will be populated with the current value of this field from the register. + * @param[out] phyerr - Will be populated with the current value of this field from the register. + * @param[out] macphyifunderrun - Will be populated with the current value of this field from the register. + * @param[out] hwerr - Will be populated with the current value of this field from the register. + * @param[out] impsecdtim - Will be populated with the current value of this field from the register. + * @param[out] imppridtim - Will be populated with the current value of this field from the register. + * @param[out] bcntxdmadead - Will be populated with the current value of this field from the register. + * @param[out] ac3txdmadead - Will be populated with the current value of this field from the register. + * @param[out] ac2txdmadead - Will be populated with the current value of this field from the register. + * @param[out] ac1txdmadead - Will be populated with the current value of this field from the register. + * @param[out] ac0txdmadead - Will be populated with the current value of this field from the register. + * @param[out] pterror - Will be populated with the current value of this field from the register. + * @param[out] timset - Will be populated with the current value of this field from the register. + * @param[out] olbcdsss - Will be populated with the current value of this field from the register. + * @param[out] olbcofdm - Will be populated with the current value of this field from the register. + * @param[out] rxfifooverflow - Will be populated with the current value of this field from the register. + * @param[out] rxdmaempty - Will be populated with the current value of this field from the register. + * @param[out] macphyifoverflow - Will be populated with the current value of this field from the register. + * @param[out] coexevent - Will be populated with the current value of this field from the register. + * @param[out] absgentimers - Will be populated with the current value of this field from the register. + * @param[out] idleinterrupt - Will be populated with the current value of this field from the register. + * @param[out] impsectbtt - Will be populated with the current value of this field from the register. + * @param[out] imppritbtt - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_gen_int_status_unpack(uint8_t *rxpayloaddmadead, uint8_t *rxheaderdmadead, uint8_t *phyrxstart, uint8_t *phyerr, uint8_t *macphyifunderrun, uint8_t *hwerr, uint8_t *impsecdtim, uint8_t *imppridtim, uint8_t *bcntxdmadead, uint8_t *ac3txdmadead, uint8_t *ac2txdmadead, uint8_t *ac1txdmadead, uint8_t *ac0txdmadead, uint8_t *pterror, uint8_t *timset, uint8_t *olbcdsss, uint8_t *olbcofdm, uint8_t *rxfifooverflow, uint8_t *rxdmaempty, uint8_t *macphyifoverflow, uint8_t *coexevent, uint8_t *absgentimers, uint8_t *idleinterrupt, uint8_t *impsectbtt, uint8_t *imppritbtt) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_STATUS_ADDR); + + *rxpayloaddmadead = (localVal & ((uint32_t)0x02000000)) >> 25; + *rxheaderdmadead = (localVal & ((uint32_t)0x01000000)) >> 24; + *phyrxstart = (localVal & ((uint32_t)0x00800000)) >> 23; + *phyerr = (localVal & ((uint32_t)0x00400000)) >> 22; + *macphyifunderrun = (localVal & ((uint32_t)0x00200000)) >> 21; + *hwerr = (localVal & ((uint32_t)0x00100000)) >> 20; + *impsecdtim = (localVal & ((uint32_t)0x00080000)) >> 19; + *imppridtim = (localVal & ((uint32_t)0x00040000)) >> 18; + *bcntxdmadead = (localVal & ((uint32_t)0x00020000)) >> 17; + *ac3txdmadead = (localVal & ((uint32_t)0x00010000)) >> 16; + *ac2txdmadead = (localVal & ((uint32_t)0x00008000)) >> 15; + *ac1txdmadead = (localVal & ((uint32_t)0x00004000)) >> 14; + *ac0txdmadead = (localVal & ((uint32_t)0x00002000)) >> 13; + *pterror = (localVal & ((uint32_t)0x00001000)) >> 12; + *timset = (localVal & ((uint32_t)0x00000800)) >> 11; + *olbcdsss = (localVal & ((uint32_t)0x00000400)) >> 10; + *olbcofdm = (localVal & ((uint32_t)0x00000200)) >> 9; + *rxfifooverflow = (localVal & ((uint32_t)0x00000100)) >> 8; + *rxdmaempty = (localVal & ((uint32_t)0x00000080)) >> 7; + *macphyifoverflow = (localVal & ((uint32_t)0x00000040)) >> 6; + *coexevent = (localVal & ((uint32_t)0x00000020)) >> 5; + *absgentimers = (localVal & ((uint32_t)0x00000008)) >> 3; + *idleinterrupt = (localVal & ((uint32_t)0x00000004)) >> 2; + *impsectbtt = (localVal & ((uint32_t)0x00000002)) >> 1; + *imppritbtt = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +/** + * @brief Returns the current value of the rxPayloadDMADead field in the GEN_INT_STATUS register. + * + * The GEN_INT_STATUS register will be read and the rxPayloadDMADead field's value will be returned. + * + * @return The current value of the rxPayloadDMADead field in the GEN_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_rx_payload_dma_dead_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x02000000)) >> 25); +} + +/** + * @brief Sets the rxPayloadDMADead field of the GEN_INT_STATUS register. + * + * The GEN_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] rxpayloaddmadead - The value to set the field to. + */ +__INLINE void nxmac_status_rx_payload_dma_dead_setf(uint8_t rxpayloaddmadead) +{ + ASSERT_ERR((((uint32_t)rxpayloaddmadead << 25) & ~((uint32_t)0x02000000)) == 0); + REG_PL_WR(NXMAC_GEN_INT_STATUS_ADDR, (uint32_t)rxpayloaddmadead << 25); +} + +/** + * @brief Returns the current value of the rxHeaderDMADead field in the GEN_INT_STATUS register. + * + * The GEN_INT_STATUS register will be read and the rxHeaderDMADead field's value will be returned. + * + * @return The current value of the rxHeaderDMADead field in the GEN_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_rx_header_dma_dead_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x01000000)) >> 24); +} + +/** + * @brief Sets the rxHeaderDMADead field of the GEN_INT_STATUS register. + * + * The GEN_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] rxheaderdmadead - The value to set the field to. + */ +__INLINE void nxmac_status_rx_header_dma_dead_setf(uint8_t rxheaderdmadead) +{ + ASSERT_ERR((((uint32_t)rxheaderdmadead << 24) & ~((uint32_t)0x01000000)) == 0); + REG_PL_WR(NXMAC_GEN_INT_STATUS_ADDR, (uint32_t)rxheaderdmadead << 24); +} + +/** + * @brief Returns the current value of the phyRxStart field in the GEN_INT_STATUS register. + * + * The GEN_INT_STATUS register will be read and the phyRxStart field's value will be returned. + * + * @return The current value of the phyRxStart field in the GEN_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_phy_rx_start_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00800000)) >> 23); +} + +/** + * @brief Sets the phyRxStart field of the GEN_INT_STATUS register. + * + * The GEN_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] phyrxstart - The value to set the field to. + */ +__INLINE void nxmac_status_phy_rx_start_setf(uint8_t phyrxstart) +{ + ASSERT_ERR((((uint32_t)phyrxstart << 23) & ~((uint32_t)0x00800000)) == 0); + REG_PL_WR(NXMAC_GEN_INT_STATUS_ADDR, (uint32_t)phyrxstart << 23); +} + +/** + * @brief Returns the current value of the phyErr field in the GEN_INT_STATUS register. + * + * The GEN_INT_STATUS register will be read and the phyErr field's value will be returned. + * + * @return The current value of the phyErr field in the GEN_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_phy_err_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00400000)) >> 22); +} + +/** + * @brief Sets the phyErr field of the GEN_INT_STATUS register. + * + * The GEN_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] phyerr - The value to set the field to. + */ +__INLINE void nxmac_status_phy_err_setf(uint8_t phyerr) +{ + ASSERT_ERR((((uint32_t)phyerr << 22) & ~((uint32_t)0x00400000)) == 0); + REG_PL_WR(NXMAC_GEN_INT_STATUS_ADDR, (uint32_t)phyerr << 22); +} + +/** + * @brief Returns the current value of the macPHYIFUnderRun field in the GEN_INT_STATUS register. + * + * The GEN_INT_STATUS register will be read and the macPHYIFUnderRun field's value will be returned. + * + * @return The current value of the macPHYIFUnderRun field in the GEN_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_mac_phyif_under_run_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00200000)) >> 21); +} + +/** + * @brief Sets the macPHYIFUnderRun field of the GEN_INT_STATUS register. + * + * The GEN_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] macphyifunderrun - The value to set the field to. + */ +__INLINE void nxmac_status_mac_phyif_under_run_setf(uint8_t macphyifunderrun) +{ + ASSERT_ERR((((uint32_t)macphyifunderrun << 21) & ~((uint32_t)0x00200000)) == 0); + REG_PL_WR(NXMAC_GEN_INT_STATUS_ADDR, (uint32_t)macphyifunderrun << 21); +} + +/** + * @brief Returns the current value of the hwErr field in the GEN_INT_STATUS register. + * + * The GEN_INT_STATUS register will be read and the hwErr field's value will be returned. + * + * @return The current value of the hwErr field in the GEN_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_hw_err_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00100000)) >> 20); +} + +/** + * @brief Sets the hwErr field of the GEN_INT_STATUS register. + * + * The GEN_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] hwerr - The value to set the field to. + */ +__INLINE void nxmac_status_hw_err_setf(uint8_t hwerr) +{ + ASSERT_ERR((((uint32_t)hwerr << 20) & ~((uint32_t)0x00100000)) == 0); + REG_PL_WR(NXMAC_GEN_INT_STATUS_ADDR, (uint32_t)hwerr << 20); +} + +/** + * @brief Returns the current value of the impSecDTIM field in the GEN_INT_STATUS register. + * + * The GEN_INT_STATUS register will be read and the impSecDTIM field's value will be returned. + * + * @return The current value of the impSecDTIM field in the GEN_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_imp_sec_dtim_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00080000)) >> 19); +} + +/** + * @brief Sets the impSecDTIM field of the GEN_INT_STATUS register. + * + * The GEN_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] impsecdtim - The value to set the field to. + */ +__INLINE void nxmac_status_imp_sec_dtim_setf(uint8_t impsecdtim) +{ + ASSERT_ERR((((uint32_t)impsecdtim << 19) & ~((uint32_t)0x00080000)) == 0); + REG_PL_WR(NXMAC_GEN_INT_STATUS_ADDR, (uint32_t)impsecdtim << 19); +} + +/** + * @brief Returns the current value of the impPriDTIM field in the GEN_INT_STATUS register. + * + * The GEN_INT_STATUS register will be read and the impPriDTIM field's value will be returned. + * + * @return The current value of the impPriDTIM field in the GEN_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_imp_pri_dtim_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00040000)) >> 18); +} + +/** + * @brief Sets the impPriDTIM field of the GEN_INT_STATUS register. + * + * The GEN_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] imppridtim - The value to set the field to. + */ +__INLINE void nxmac_status_imp_pri_dtim_setf(uint8_t imppridtim) +{ + ASSERT_ERR((((uint32_t)imppridtim << 18) & ~((uint32_t)0x00040000)) == 0); + REG_PL_WR(NXMAC_GEN_INT_STATUS_ADDR, (uint32_t)imppridtim << 18); +} + +/** + * @brief Returns the current value of the bcnTxDMADead field in the GEN_INT_STATUS register. + * + * The GEN_INT_STATUS register will be read and the bcnTxDMADead field's value will be returned. + * + * @return The current value of the bcnTxDMADead field in the GEN_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_bcn_tx_dma_dead_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00020000)) >> 17); +} + +/** + * @brief Sets the bcnTxDMADead field of the GEN_INT_STATUS register. + * + * The GEN_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] bcntxdmadead - The value to set the field to. + */ +__INLINE void nxmac_status_bcn_tx_dma_dead_setf(uint8_t bcntxdmadead) +{ + ASSERT_ERR((((uint32_t)bcntxdmadead << 17) & ~((uint32_t)0x00020000)) == 0); + REG_PL_WR(NXMAC_GEN_INT_STATUS_ADDR, (uint32_t)bcntxdmadead << 17); +} + +/** + * @brief Returns the current value of the ac3TxDMADead field in the GEN_INT_STATUS register. + * + * The GEN_INT_STATUS register will be read and the ac3TxDMADead field's value will be returned. + * + * @return The current value of the ac3TxDMADead field in the GEN_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_ac_3_tx_dma_dead_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00010000)) >> 16); +} + +/** + * @brief Sets the ac3TxDMADead field of the GEN_INT_STATUS register. + * + * The GEN_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] ac3txdmadead - The value to set the field to. + */ +__INLINE void nxmac_status_ac_3_tx_dma_dead_setf(uint8_t ac3txdmadead) +{ + ASSERT_ERR((((uint32_t)ac3txdmadead << 16) & ~((uint32_t)0x00010000)) == 0); + REG_PL_WR(NXMAC_GEN_INT_STATUS_ADDR, (uint32_t)ac3txdmadead << 16); +} + +/** + * @brief Returns the current value of the ac2TxDMADead field in the GEN_INT_STATUS register. + * + * The GEN_INT_STATUS register will be read and the ac2TxDMADead field's value will be returned. + * + * @return The current value of the ac2TxDMADead field in the GEN_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_ac_2_tx_dma_dead_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00008000)) >> 15); +} + +/** + * @brief Sets the ac2TxDMADead field of the GEN_INT_STATUS register. + * + * The GEN_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] ac2txdmadead - The value to set the field to. + */ +__INLINE void nxmac_status_ac_2_tx_dma_dead_setf(uint8_t ac2txdmadead) +{ + ASSERT_ERR((((uint32_t)ac2txdmadead << 15) & ~((uint32_t)0x00008000)) == 0); + REG_PL_WR(NXMAC_GEN_INT_STATUS_ADDR, (uint32_t)ac2txdmadead << 15); +} + +/** + * @brief Returns the current value of the ac1TxDMADead field in the GEN_INT_STATUS register. + * + * The GEN_INT_STATUS register will be read and the ac1TxDMADead field's value will be returned. + * + * @return The current value of the ac1TxDMADead field in the GEN_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_ac_1_tx_dma_dead_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00004000)) >> 14); +} + +/** + * @brief Sets the ac1TxDMADead field of the GEN_INT_STATUS register. + * + * The GEN_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] ac1txdmadead - The value to set the field to. + */ +__INLINE void nxmac_status_ac_1_tx_dma_dead_setf(uint8_t ac1txdmadead) +{ + ASSERT_ERR((((uint32_t)ac1txdmadead << 14) & ~((uint32_t)0x00004000)) == 0); + REG_PL_WR(NXMAC_GEN_INT_STATUS_ADDR, (uint32_t)ac1txdmadead << 14); +} + +/** + * @brief Returns the current value of the ac0TxDMADead field in the GEN_INT_STATUS register. + * + * The GEN_INT_STATUS register will be read and the ac0TxDMADead field's value will be returned. + * + * @return The current value of the ac0TxDMADead field in the GEN_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_ac_0_tx_dma_dead_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00002000)) >> 13); +} + +/** + * @brief Sets the ac0TxDMADead field of the GEN_INT_STATUS register. + * + * The GEN_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] ac0txdmadead - The value to set the field to. + */ +__INLINE void nxmac_status_ac_0_tx_dma_dead_setf(uint8_t ac0txdmadead) +{ + ASSERT_ERR((((uint32_t)ac0txdmadead << 13) & ~((uint32_t)0x00002000)) == 0); + REG_PL_WR(NXMAC_GEN_INT_STATUS_ADDR, (uint32_t)ac0txdmadead << 13); +} + +/** + * @brief Returns the current value of the ptError field in the GEN_INT_STATUS register. + * + * The GEN_INT_STATUS register will be read and the ptError field's value will be returned. + * + * @return The current value of the ptError field in the GEN_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_pt_error_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00001000)) >> 12); +} + +/** + * @brief Sets the ptError field of the GEN_INT_STATUS register. + * + * The GEN_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] pterror - The value to set the field to. + */ +__INLINE void nxmac_status_pt_error_setf(uint8_t pterror) +{ + ASSERT_ERR((((uint32_t)pterror << 12) & ~((uint32_t)0x00001000)) == 0); + REG_PL_WR(NXMAC_GEN_INT_STATUS_ADDR, (uint32_t)pterror << 12); +} + +/** + * @brief Returns the current value of the timSet field in the GEN_INT_STATUS register. + * + * The GEN_INT_STATUS register will be read and the timSet field's value will be returned. + * + * @return The current value of the timSet field in the GEN_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_tim_set_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00000800)) >> 11); +} + +/** + * @brief Sets the timSet field of the GEN_INT_STATUS register. + * + * The GEN_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] timset - The value to set the field to. + */ +__INLINE void nxmac_status_tim_set_setf(uint8_t timset) +{ + ASSERT_ERR((((uint32_t)timset << 11) & ~((uint32_t)0x00000800)) == 0); + REG_PL_WR(NXMAC_GEN_INT_STATUS_ADDR, (uint32_t)timset << 11); +} + +/** + * @brief Returns the current value of the olbcDSSS field in the GEN_INT_STATUS register. + * + * The GEN_INT_STATUS register will be read and the olbcDSSS field's value will be returned. + * + * @return The current value of the olbcDSSS field in the GEN_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_olbc_dsss_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00000400)) >> 10); +} + +/** + * @brief Sets the olbcDSSS field of the GEN_INT_STATUS register. + * + * The GEN_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] olbcdsss - The value to set the field to. + */ +__INLINE void nxmac_status_olbc_dsss_setf(uint8_t olbcdsss) +{ + ASSERT_ERR((((uint32_t)olbcdsss << 10) & ~((uint32_t)0x00000400)) == 0); + REG_PL_WR(NXMAC_GEN_INT_STATUS_ADDR, (uint32_t)olbcdsss << 10); +} + +/** + * @brief Returns the current value of the olbcOFDM field in the GEN_INT_STATUS register. + * + * The GEN_INT_STATUS register will be read and the olbcOFDM field's value will be returned. + * + * @return The current value of the olbcOFDM field in the GEN_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_olbc_ofdm_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00000200)) >> 9); +} + +/** + * @brief Sets the olbcOFDM field of the GEN_INT_STATUS register. + * + * The GEN_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] olbcofdm - The value to set the field to. + */ +__INLINE void nxmac_status_olbc_ofdm_setf(uint8_t olbcofdm) +{ + ASSERT_ERR((((uint32_t)olbcofdm << 9) & ~((uint32_t)0x00000200)) == 0); + REG_PL_WR(NXMAC_GEN_INT_STATUS_ADDR, (uint32_t)olbcofdm << 9); +} + +/** + * @brief Returns the current value of the rxFIFOOverFlow field in the GEN_INT_STATUS register. + * + * The GEN_INT_STATUS register will be read and the rxFIFOOverFlow field's value will be returned. + * + * @return The current value of the rxFIFOOverFlow field in the GEN_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_rx_fifo_over_flow_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00000100)) >> 8); +} + +/** + * @brief Sets the rxFIFOOverFlow field of the GEN_INT_STATUS register. + * + * The GEN_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] rxfifooverflow - The value to set the field to. + */ +__INLINE void nxmac_status_rx_fifo_over_flow_setf(uint8_t rxfifooverflow) +{ + ASSERT_ERR((((uint32_t)rxfifooverflow << 8) & ~((uint32_t)0x00000100)) == 0); + REG_PL_WR(NXMAC_GEN_INT_STATUS_ADDR, (uint32_t)rxfifooverflow << 8); +} + +/** + * @brief Returns the current value of the rxDMAEmpty field in the GEN_INT_STATUS register. + * + * The GEN_INT_STATUS register will be read and the rxDMAEmpty field's value will be returned. + * + * @return The current value of the rxDMAEmpty field in the GEN_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_rx_dma_empty_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00000080)) >> 7); +} + +/** + * @brief Sets the rxDMAEmpty field of the GEN_INT_STATUS register. + * + * The GEN_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] rxdmaempty - The value to set the field to. + */ +__INLINE void nxmac_status_rx_dma_empty_setf(uint8_t rxdmaempty) +{ + ASSERT_ERR((((uint32_t)rxdmaempty << 7) & ~((uint32_t)0x00000080)) == 0); + REG_PL_WR(NXMAC_GEN_INT_STATUS_ADDR, (uint32_t)rxdmaempty << 7); +} + +/** + * @brief Returns the current value of the macPHYIFOverflow field in the GEN_INT_STATUS register. + * + * The GEN_INT_STATUS register will be read and the macPHYIFOverflow field's value will be returned. + * + * @return The current value of the macPHYIFOverflow field in the GEN_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_mac_phyif_overflow_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00000040)) >> 6); +} + +/** + * @brief Sets the macPHYIFOverflow field of the GEN_INT_STATUS register. + * + * The GEN_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] macphyifoverflow - The value to set the field to. + */ +__INLINE void nxmac_status_mac_phyif_overflow_setf(uint8_t macphyifoverflow) +{ + ASSERT_ERR((((uint32_t)macphyifoverflow << 6) & ~((uint32_t)0x00000040)) == 0); + REG_PL_WR(NXMAC_GEN_INT_STATUS_ADDR, (uint32_t)macphyifoverflow << 6); +} + +/** + * @brief Returns the current value of the coexEvent field in the GEN_INT_STATUS register. + * + * The GEN_INT_STATUS register will be read and the coexEvent field's value will be returned. + * + * @return The current value of the coexEvent field in the GEN_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_coex_event_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +/** + * @brief Sets the coexEvent field of the GEN_INT_STATUS register. + * + * The GEN_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] coexevent - The value to set the field to. + */ +__INLINE void nxmac_status_coex_event_setf(uint8_t coexevent) +{ + ASSERT_ERR((((uint32_t)coexevent << 5) & ~((uint32_t)0x00000020)) == 0); + REG_PL_WR(NXMAC_GEN_INT_STATUS_ADDR, (uint32_t)coexevent << 5); +} + +/** + * @brief Returns the current value of the absGenTimers field in the GEN_INT_STATUS register. + * + * The GEN_INT_STATUS register will be read and the absGenTimers field's value will be returned. + * + * @return The current value of the absGenTimers field in the GEN_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_abs_gen_timers_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +/** + * @brief Returns the current value of the idleInterrupt field in the GEN_INT_STATUS register. + * + * The GEN_INT_STATUS register will be read and the idleInterrupt field's value will be returned. + * + * @return The current value of the idleInterrupt field in the GEN_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_idle_interrupt_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +/** + * @brief Sets the idleInterrupt field of the GEN_INT_STATUS register. + * + * The GEN_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] idleinterrupt - The value to set the field to. + */ +__INLINE void nxmac_status_idle_interrupt_setf(uint8_t idleinterrupt) +{ + ASSERT_ERR((((uint32_t)idleinterrupt << 2) & ~((uint32_t)0x00000004)) == 0); + REG_PL_WR(NXMAC_GEN_INT_STATUS_ADDR, (uint32_t)idleinterrupt << 2); +} + +/** + * @brief Returns the current value of the impSecTBTT field in the GEN_INT_STATUS register. + * + * The GEN_INT_STATUS register will be read and the impSecTBTT field's value will be returned. + * + * @return The current value of the impSecTBTT field in the GEN_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_imp_sec_tbtt_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +/** + * @brief Sets the impSecTBTT field of the GEN_INT_STATUS register. + * + * The GEN_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] impsectbtt - The value to set the field to. + */ +__INLINE void nxmac_status_imp_sec_tbtt_setf(uint8_t impsectbtt) +{ + ASSERT_ERR((((uint32_t)impsectbtt << 1) & ~((uint32_t)0x00000002)) == 0); + REG_PL_WR(NXMAC_GEN_INT_STATUS_ADDR, (uint32_t)impsectbtt << 1); +} + +/** + * @brief Returns the current value of the impPriTBTT field in the GEN_INT_STATUS register. + * + * The GEN_INT_STATUS register will be read and the impPriTBTT field's value will be returned. + * + * @return The current value of the impPriTBTT field in the GEN_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_imp_pri_tbtt_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/** + * @brief Sets the impPriTBTT field of the GEN_INT_STATUS register. + * + * The GEN_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] imppritbtt - The value to set the field to. + */ +__INLINE void nxmac_status_imp_pri_tbtt_setf(uint8_t imppritbtt) +{ + ASSERT_ERR((((uint32_t)imppritbtt << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_GEN_INT_STATUS_ADDR, (uint32_t)imppritbtt << 0); +} + +/// @} + +/** + * @name GEN_INT_ACK register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     25     rxPayloadDMADead   0
+ *     24      rxHeaderDMADead   0
+ *     23           phyRxStart   0
+ *     22               phyErr   0
+ *     21     macPHYIFUnderRun   0
+ *     20                hwErr   0
+ *     19           impSecDTIM   0
+ *     18           impPriDTIM   0
+ *     17         bcnTxDMADead   0
+ *     16         ac3TxDMADead   0
+ *     15         ac2TxDMADead   0
+ *     14         ac1TxDMADead   0
+ *     13         ac0TxDMADead   0
+ *     12              ptError   0
+ *     11               timSet   0
+ *     10             olbcDSSS   0
+ *     09             olbcOFDM   0
+ *     08       rxFIFOOverFlow   0
+ *     07           rxDMAEmpty   0
+ *     06     macPHYIFOverflow   0
+ *     05            coexEvent   0
+ *     02        idleInterrupt   0
+ *     01           impSecTBTT   0
+ *     00           impPriTBTT   0
+ * 
+ * + * @{ + */ + +/// Address of the GEN_INT_ACK register +#define NXMAC_GEN_INT_ACK_ADDR 0xC0008070 +/// Offset of the GEN_INT_ACK register from the base address +#define NXMAC_GEN_INT_ACK_OFFSET 0x00000070 +/// Index of the GEN_INT_ACK register +#define NXMAC_GEN_INT_ACK_INDEX 0x0000001C +/// Reset value of the GEN_INT_ACK register +#define NXMAC_GEN_INT_ACK_RESET 0x00000000 + +/** + * @brief Sets the GEN_INT_ACK register to a value. + * The GEN_INT_ACK register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_gen_int_ack_clear(uint32_t value) +{ + REG_PL_WR(NXMAC_GEN_INT_ACK_ADDR, value); +} + +// fields defined in symmetrical set/clear register +/** + * @brief Constructs a value for the GEN_INT_ACK register given values for its fields + * and writes the value to the register. + * + * @param[in] rxpayloaddmadead - The value to use for the rxPayloadDMADead field. + * @param[in] rxheaderdmadead - The value to use for the rxHeaderDMADead field. + * @param[in] phyrxstart - The value to use for the phyRxStart field. + * @param[in] phyerr - The value to use for the phyErr field. + * @param[in] macphyifunderrun - The value to use for the macPHYIFUnderRun field. + * @param[in] hwerr - The value to use for the hwErr field. + * @param[in] impsecdtim - The value to use for the impSecDTIM field. + * @param[in] imppridtim - The value to use for the impPriDTIM field. + * @param[in] bcntxdmadead - The value to use for the bcnTxDMADead field. + * @param[in] ac3txdmadead - The value to use for the ac3TxDMADead field. + * @param[in] ac2txdmadead - The value to use for the ac2TxDMADead field. + * @param[in] ac1txdmadead - The value to use for the ac1TxDMADead field. + * @param[in] ac0txdmadead - The value to use for the ac0TxDMADead field. + * @param[in] pterror - The value to use for the ptError field. + * @param[in] timset - The value to use for the timSet field. + * @param[in] olbcdsss - The value to use for the olbcDSSS field. + * @param[in] olbcofdm - The value to use for the olbcOFDM field. + * @param[in] rxfifooverflow - The value to use for the rxFIFOOverFlow field. + * @param[in] rxdmaempty - The value to use for the rxDMAEmpty field. + * @param[in] macphyifoverflow - The value to use for the macPHYIFOverflow field. + * @param[in] coexevent - The value to use for the coexEvent field. + * @param[in] idleinterrupt - The value to use for the idleInterrupt field. + * @param[in] impsectbtt - The value to use for the impSecTBTT field. + * @param[in] imppritbtt - The value to use for the impPriTBTT field. + */ +__INLINE void nxmac_gen_int_ack_pack(uint8_t rxpayloaddmadead, uint8_t rxheaderdmadead, uint8_t phyrxstart, uint8_t phyerr, uint8_t macphyifunderrun, uint8_t hwerr, uint8_t impsecdtim, uint8_t imppridtim, uint8_t bcntxdmadead, uint8_t ac3txdmadead, uint8_t ac2txdmadead, uint8_t ac1txdmadead, uint8_t ac0txdmadead, uint8_t pterror, uint8_t timset, uint8_t olbcdsss, uint8_t olbcofdm, uint8_t rxfifooverflow, uint8_t rxdmaempty, uint8_t macphyifoverflow, uint8_t coexevent, uint8_t idleinterrupt, uint8_t impsectbtt, uint8_t imppritbtt) +{ + ASSERT_ERR((((uint32_t)rxpayloaddmadead << 25) & ~((uint32_t)0x02000000)) == 0); + ASSERT_ERR((((uint32_t)rxheaderdmadead << 24) & ~((uint32_t)0x01000000)) == 0); + ASSERT_ERR((((uint32_t)phyrxstart << 23) & ~((uint32_t)0x00800000)) == 0); + ASSERT_ERR((((uint32_t)phyerr << 22) & ~((uint32_t)0x00400000)) == 0); + ASSERT_ERR((((uint32_t)macphyifunderrun << 21) & ~((uint32_t)0x00200000)) == 0); + ASSERT_ERR((((uint32_t)hwerr << 20) & ~((uint32_t)0x00100000)) == 0); + ASSERT_ERR((((uint32_t)impsecdtim << 19) & ~((uint32_t)0x00080000)) == 0); + ASSERT_ERR((((uint32_t)imppridtim << 18) & ~((uint32_t)0x00040000)) == 0); + ASSERT_ERR((((uint32_t)bcntxdmadead << 17) & ~((uint32_t)0x00020000)) == 0); + ASSERT_ERR((((uint32_t)ac3txdmadead << 16) & ~((uint32_t)0x00010000)) == 0); + ASSERT_ERR((((uint32_t)ac2txdmadead << 15) & ~((uint32_t)0x00008000)) == 0); + ASSERT_ERR((((uint32_t)ac1txdmadead << 14) & ~((uint32_t)0x00004000)) == 0); + ASSERT_ERR((((uint32_t)ac0txdmadead << 13) & ~((uint32_t)0x00002000)) == 0); + ASSERT_ERR((((uint32_t)pterror << 12) & ~((uint32_t)0x00001000)) == 0); + ASSERT_ERR((((uint32_t)timset << 11) & ~((uint32_t)0x00000800)) == 0); + ASSERT_ERR((((uint32_t)olbcdsss << 10) & ~((uint32_t)0x00000400)) == 0); + ASSERT_ERR((((uint32_t)olbcofdm << 9) & ~((uint32_t)0x00000200)) == 0); + ASSERT_ERR((((uint32_t)rxfifooverflow << 8) & ~((uint32_t)0x00000100)) == 0); + ASSERT_ERR((((uint32_t)rxdmaempty << 7) & ~((uint32_t)0x00000080)) == 0); + ASSERT_ERR((((uint32_t)macphyifoverflow << 6) & ~((uint32_t)0x00000040)) == 0); + ASSERT_ERR((((uint32_t)coexevent << 5) & ~((uint32_t)0x00000020)) == 0); + ASSERT_ERR((((uint32_t)idleinterrupt << 2) & ~((uint32_t)0x00000004)) == 0); + ASSERT_ERR((((uint32_t)impsectbtt << 1) & ~((uint32_t)0x00000002)) == 0); + ASSERT_ERR((((uint32_t)imppritbtt << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ACK_ADDR, ((uint32_t)rxpayloaddmadead << 25) | ((uint32_t)rxheaderdmadead << 24) | ((uint32_t)phyrxstart << 23) | ((uint32_t)phyerr << 22) | ((uint32_t)macphyifunderrun << 21) | ((uint32_t)hwerr << 20) | ((uint32_t)impsecdtim << 19) | ((uint32_t)imppridtim << 18) | ((uint32_t)bcntxdmadead << 17) | ((uint32_t)ac3txdmadead << 16) | ((uint32_t)ac2txdmadead << 15) | ((uint32_t)ac1txdmadead << 14) | ((uint32_t)ac0txdmadead << 13) | ((uint32_t)pterror << 12) | ((uint32_t)timset << 11) | ((uint32_t)olbcdsss << 10) | ((uint32_t)olbcofdm << 9) | ((uint32_t)rxfifooverflow << 8) | ((uint32_t)rxdmaempty << 7) | ((uint32_t)macphyifoverflow << 6) | ((uint32_t)coexevent << 5) | ((uint32_t)idleinterrupt << 2) | ((uint32_t)impsectbtt << 1) | ((uint32_t)imppritbtt << 0)); +} + +/** + * @brief Sets the rxPayloadDMADead field of the GEN_INT_ACK register. + * + * The GEN_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] rxpayloaddmadead - The value to set the field to. + */ +__INLINE void nxmac_ack_rx_payload_dma_dead_clearf(uint8_t rxpayloaddmadead) +{ + ASSERT_ERR((((uint32_t)rxpayloaddmadead << 25) & ~((uint32_t)0x02000000)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ACK_ADDR, (uint32_t)rxpayloaddmadead << 25); +} + +/** + * @brief Sets the rxHeaderDMADead field of the GEN_INT_ACK register. + * + * The GEN_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] rxheaderdmadead - The value to set the field to. + */ +__INLINE void nxmac_ack_rx_header_dma_dead_clearf(uint8_t rxheaderdmadead) +{ + ASSERT_ERR((((uint32_t)rxheaderdmadead << 24) & ~((uint32_t)0x01000000)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ACK_ADDR, (uint32_t)rxheaderdmadead << 24); +} + +/** + * @brief Sets the phyRxStart field of the GEN_INT_ACK register. + * + * The GEN_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] phyrxstart - The value to set the field to. + */ +__INLINE void nxmac_ack_phy_rx_start_clearf(uint8_t phyrxstart) +{ + ASSERT_ERR((((uint32_t)phyrxstart << 23) & ~((uint32_t)0x00800000)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ACK_ADDR, (uint32_t)phyrxstart << 23); +} + +/** + * @brief Sets the phyErr field of the GEN_INT_ACK register. + * + * The GEN_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] phyerr - The value to set the field to. + */ +__INLINE void nxmac_ack_phy_err_clearf(uint8_t phyerr) +{ + ASSERT_ERR((((uint32_t)phyerr << 22) & ~((uint32_t)0x00400000)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ACK_ADDR, (uint32_t)phyerr << 22); +} + +/** + * @brief Sets the macPHYIFUnderRun field of the GEN_INT_ACK register. + * + * The GEN_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] macphyifunderrun - The value to set the field to. + */ +__INLINE void nxmac_ack_mac_phyif_under_run_clearf(uint8_t macphyifunderrun) +{ + ASSERT_ERR((((uint32_t)macphyifunderrun << 21) & ~((uint32_t)0x00200000)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ACK_ADDR, (uint32_t)macphyifunderrun << 21); +} + +/** + * @brief Sets the hwErr field of the GEN_INT_ACK register. + * + * The GEN_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] hwerr - The value to set the field to. + */ +__INLINE void nxmac_ack_hw_err_clearf(uint8_t hwerr) +{ + ASSERT_ERR((((uint32_t)hwerr << 20) & ~((uint32_t)0x00100000)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ACK_ADDR, (uint32_t)hwerr << 20); +} + +/** + * @brief Sets the impSecDTIM field of the GEN_INT_ACK register. + * + * The GEN_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] impsecdtim - The value to set the field to. + */ +__INLINE void nxmac_ack_imp_sec_dtim_clearf(uint8_t impsecdtim) +{ + ASSERT_ERR((((uint32_t)impsecdtim << 19) & ~((uint32_t)0x00080000)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ACK_ADDR, (uint32_t)impsecdtim << 19); +} + +/** + * @brief Sets the impPriDTIM field of the GEN_INT_ACK register. + * + * The GEN_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] imppridtim - The value to set the field to. + */ +__INLINE void nxmac_ack_imp_pri_dtim_clearf(uint8_t imppridtim) +{ + ASSERT_ERR((((uint32_t)imppridtim << 18) & ~((uint32_t)0x00040000)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ACK_ADDR, (uint32_t)imppridtim << 18); +} + +/** + * @brief Sets the bcnTxDMADead field of the GEN_INT_ACK register. + * + * The GEN_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] bcntxdmadead - The value to set the field to. + */ +__INLINE void nxmac_ack_bcn_tx_dma_dead_clearf(uint8_t bcntxdmadead) +{ + ASSERT_ERR((((uint32_t)bcntxdmadead << 17) & ~((uint32_t)0x00020000)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ACK_ADDR, (uint32_t)bcntxdmadead << 17); +} + +/** + * @brief Sets the ac3TxDMADead field of the GEN_INT_ACK register. + * + * The GEN_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] ac3txdmadead - The value to set the field to. + */ +__INLINE void nxmac_ack_ac_3_tx_dma_dead_clearf(uint8_t ac3txdmadead) +{ + ASSERT_ERR((((uint32_t)ac3txdmadead << 16) & ~((uint32_t)0x00010000)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ACK_ADDR, (uint32_t)ac3txdmadead << 16); +} + +/** + * @brief Sets the ac2TxDMADead field of the GEN_INT_ACK register. + * + * The GEN_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] ac2txdmadead - The value to set the field to. + */ +__INLINE void nxmac_ack_ac_2_tx_dma_dead_clearf(uint8_t ac2txdmadead) +{ + ASSERT_ERR((((uint32_t)ac2txdmadead << 15) & ~((uint32_t)0x00008000)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ACK_ADDR, (uint32_t)ac2txdmadead << 15); +} + +/** + * @brief Sets the ac1TxDMADead field of the GEN_INT_ACK register. + * + * The GEN_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] ac1txdmadead - The value to set the field to. + */ +__INLINE void nxmac_ack_ac_1_tx_dma_dead_clearf(uint8_t ac1txdmadead) +{ + ASSERT_ERR((((uint32_t)ac1txdmadead << 14) & ~((uint32_t)0x00004000)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ACK_ADDR, (uint32_t)ac1txdmadead << 14); +} + +/** + * @brief Sets the ac0TxDMADead field of the GEN_INT_ACK register. + * + * The GEN_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] ac0txdmadead - The value to set the field to. + */ +__INLINE void nxmac_ack_ac_0_tx_dma_dead_clearf(uint8_t ac0txdmadead) +{ + ASSERT_ERR((((uint32_t)ac0txdmadead << 13) & ~((uint32_t)0x00002000)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ACK_ADDR, (uint32_t)ac0txdmadead << 13); +} + +/** + * @brief Sets the ptError field of the GEN_INT_ACK register. + * + * The GEN_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] pterror - The value to set the field to. + */ +__INLINE void nxmac_ack_pt_error_clearf(uint8_t pterror) +{ + ASSERT_ERR((((uint32_t)pterror << 12) & ~((uint32_t)0x00001000)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ACK_ADDR, (uint32_t)pterror << 12); +} + +/** + * @brief Sets the timSet field of the GEN_INT_ACK register. + * + * The GEN_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] timset - The value to set the field to. + */ +__INLINE void nxmac_ack_tim_set_clearf(uint8_t timset) +{ + ASSERT_ERR((((uint32_t)timset << 11) & ~((uint32_t)0x00000800)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ACK_ADDR, (uint32_t)timset << 11); +} + +/** + * @brief Sets the olbcDSSS field of the GEN_INT_ACK register. + * + * The GEN_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] olbcdsss - The value to set the field to. + */ +__INLINE void nxmac_ack_olbc_dsss_clearf(uint8_t olbcdsss) +{ + ASSERT_ERR((((uint32_t)olbcdsss << 10) & ~((uint32_t)0x00000400)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ACK_ADDR, (uint32_t)olbcdsss << 10); +} + +/** + * @brief Sets the olbcOFDM field of the GEN_INT_ACK register. + * + * The GEN_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] olbcofdm - The value to set the field to. + */ +__INLINE void nxmac_ack_olbc_ofdm_clearf(uint8_t olbcofdm) +{ + ASSERT_ERR((((uint32_t)olbcofdm << 9) & ~((uint32_t)0x00000200)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ACK_ADDR, (uint32_t)olbcofdm << 9); +} + +/** + * @brief Sets the rxFIFOOverFlow field of the GEN_INT_ACK register. + * + * The GEN_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] rxfifooverflow - The value to set the field to. + */ +__INLINE void nxmac_ack_rx_fifo_over_flow_clearf(uint8_t rxfifooverflow) +{ + ASSERT_ERR((((uint32_t)rxfifooverflow << 8) & ~((uint32_t)0x00000100)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ACK_ADDR, (uint32_t)rxfifooverflow << 8); +} + +/** + * @brief Sets the rxDMAEmpty field of the GEN_INT_ACK register. + * + * The GEN_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] rxdmaempty - The value to set the field to. + */ +__INLINE void nxmac_ack_rx_dma_empty_clearf(uint8_t rxdmaempty) +{ + ASSERT_ERR((((uint32_t)rxdmaempty << 7) & ~((uint32_t)0x00000080)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ACK_ADDR, (uint32_t)rxdmaempty << 7); +} + +/** + * @brief Sets the macPHYIFOverflow field of the GEN_INT_ACK register. + * + * The GEN_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] macphyifoverflow - The value to set the field to. + */ +__INLINE void nxmac_ack_mac_phyif_overflow_clearf(uint8_t macphyifoverflow) +{ + ASSERT_ERR((((uint32_t)macphyifoverflow << 6) & ~((uint32_t)0x00000040)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ACK_ADDR, (uint32_t)macphyifoverflow << 6); +} + +/** + * @brief Sets the coexEvent field of the GEN_INT_ACK register. + * + * The GEN_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] coexevent - The value to set the field to. + */ +__INLINE void nxmac_ack_coex_event_clearf(uint8_t coexevent) +{ + ASSERT_ERR((((uint32_t)coexevent << 5) & ~((uint32_t)0x00000020)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ACK_ADDR, (uint32_t)coexevent << 5); +} + +/** + * @brief Sets the idleInterrupt field of the GEN_INT_ACK register. + * + * The GEN_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] idleinterrupt - The value to set the field to. + */ +__INLINE void nxmac_ack_idle_interrupt_clearf(uint8_t idleinterrupt) +{ + ASSERT_ERR((((uint32_t)idleinterrupt << 2) & ~((uint32_t)0x00000004)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ACK_ADDR, (uint32_t)idleinterrupt << 2); +} + +/** + * @brief Sets the impSecTBTT field of the GEN_INT_ACK register. + * + * The GEN_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] impsectbtt - The value to set the field to. + */ +__INLINE void nxmac_ack_imp_sec_tbtt_clearf(uint8_t impsectbtt) +{ + ASSERT_ERR((((uint32_t)impsectbtt << 1) & ~((uint32_t)0x00000002)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ACK_ADDR, (uint32_t)impsectbtt << 1); +} + +/** + * @brief Sets the impPriTBTT field of the GEN_INT_ACK register. + * + * The GEN_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] imppritbtt - The value to set the field to. + */ +__INLINE void nxmac_ack_imp_pri_tbtt_clearf(uint8_t imppritbtt) +{ + ASSERT_ERR((((uint32_t)imppritbtt << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ACK_ADDR, (uint32_t)imppritbtt << 0); +} + +/// @} + +/** + * @name GEN_INT_ENABLE register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31       masterGenIntEn   0
+ *     25     rxPayloadDMADead   0
+ *     24      rxHeaderDMADead   0
+ *     23           phyRxStart   0
+ *     22               phyErr   0
+ *     21     macPHYIFUnderRun   0
+ *     20                hwErr   0
+ *     19           impSecDTIM   0
+ *     18           impPriDTIM   0
+ *     17         bcnTxDMADead   0
+ *     16         ac3TxDMADead   0
+ *     15         ac2TxDMADead   0
+ *     14         ac1TxDMADead   0
+ *     13         ac0TxDMADead   0
+ *     12              ptError   0
+ *     11               timSet   0
+ *     10             olbcDSSS   0
+ *     09             olbcOFDM   0
+ *     08       rxFIFOOverFlow   0
+ *     07           rxDMAEmpty   0
+ *     06     macPHYIFOverflow   0
+ *     05            coexEvent   0
+ *     03         absGenTimers   0
+ *     02        idleInterrupt   0
+ *     01           impSecTBTT   0
+ *     00           impPriTBTT   0
+ * 
+ * + * @{ + */ + +/// Address of the GEN_INT_ENABLE register +#define NXMAC_GEN_INT_ENABLE_ADDR 0xC0008074 +/// Offset of the GEN_INT_ENABLE register from the base address +#define NXMAC_GEN_INT_ENABLE_OFFSET 0x00000074 +/// Index of the GEN_INT_ENABLE register +#define NXMAC_GEN_INT_ENABLE_INDEX 0x0000001D +/// Reset value of the GEN_INT_ENABLE register +#define NXMAC_GEN_INT_ENABLE_RESET 0x00000000 + +/** + * @brief Returns the current value of the GEN_INT_ENABLE register. + * The GEN_INT_ENABLE register will be read and its value returned. + * @return The current value of the GEN_INT_ENABLE register. + */ +__INLINE uint32_t nxmac_gen_int_enable_get(void) +{ + return REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR); +} + +/** + * @brief Sets the GEN_INT_ENABLE register to a value. + * The GEN_INT_ENABLE register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_gen_int_enable_set(uint32_t value) +{ + REG_PL_WR(NXMAC_GEN_INT_ENABLE_ADDR, value); +} + +// field definitions +/// MASTER_GEN_INT_EN field bit +#define NXMAC_MASTER_GEN_INT_EN_BIT ((uint32_t)0x80000000) +/// MASTER_GEN_INT_EN field position +#define NXMAC_MASTER_GEN_INT_EN_POS 31 +/// RX_PAYLOAD_DMA_DEAD field bit +#define NXMAC_RX_PAYLOAD_DMA_DEAD_BIT ((uint32_t)0x02000000) +/// RX_PAYLOAD_DMA_DEAD field position +#define NXMAC_RX_PAYLOAD_DMA_DEAD_POS 25 +/// RX_HEADER_DMA_DEAD field bit +#define NXMAC_RX_HEADER_DMA_DEAD_BIT ((uint32_t)0x01000000) +/// RX_HEADER_DMA_DEAD field position +#define NXMAC_RX_HEADER_DMA_DEAD_POS 24 +/// PHY_RX_START field bit +#define NXMAC_PHY_RX_START_BIT ((uint32_t)0x00800000) +/// PHY_RX_START field position +#define NXMAC_PHY_RX_START_POS 23 +/// PHY_ERR field bit +#define NXMAC_PHY_ERR_BIT ((uint32_t)0x00400000) +/// PHY_ERR field position +#define NXMAC_PHY_ERR_POS 22 +/// MAC_PHYIF_UNDER_RUN field bit +#define NXMAC_MAC_PHYIF_UNDER_RUN_BIT ((uint32_t)0x00200000) +/// MAC_PHYIF_UNDER_RUN field position +#define NXMAC_MAC_PHYIF_UNDER_RUN_POS 21 +/// HW_ERR field bit +#define NXMAC_HW_ERR_BIT ((uint32_t)0x00100000) +/// HW_ERR field position +#define NXMAC_HW_ERR_POS 20 +/// IMP_SEC_DTIM field bit +#define NXMAC_IMP_SEC_DTIM_BIT ((uint32_t)0x00080000) +/// IMP_SEC_DTIM field position +#define NXMAC_IMP_SEC_DTIM_POS 19 +/// IMP_PRI_DTIM field bit +#define NXMAC_IMP_PRI_DTIM_BIT ((uint32_t)0x00040000) +/// IMP_PRI_DTIM field position +#define NXMAC_IMP_PRI_DTIM_POS 18 +/// BCN_TX_DMA_DEAD field bit +#define NXMAC_BCN_TX_DMA_DEAD_BIT ((uint32_t)0x00020000) +/// BCN_TX_DMA_DEAD field position +#define NXMAC_BCN_TX_DMA_DEAD_POS 17 +/// AC_3_TX_DMA_DEAD field bit +#define NXMAC_AC_3_TX_DMA_DEAD_BIT ((uint32_t)0x00010000) +/// AC_3_TX_DMA_DEAD field position +#define NXMAC_AC_3_TX_DMA_DEAD_POS 16 +/// AC_2_TX_DMA_DEAD field bit +#define NXMAC_AC_2_TX_DMA_DEAD_BIT ((uint32_t)0x00008000) +/// AC_2_TX_DMA_DEAD field position +#define NXMAC_AC_2_TX_DMA_DEAD_POS 15 +/// AC_1_TX_DMA_DEAD field bit +#define NXMAC_AC_1_TX_DMA_DEAD_BIT ((uint32_t)0x00004000) +/// AC_1_TX_DMA_DEAD field position +#define NXMAC_AC_1_TX_DMA_DEAD_POS 14 +/// AC_0_TX_DMA_DEAD field bit +#define NXMAC_AC_0_TX_DMA_DEAD_BIT ((uint32_t)0x00002000) +/// AC_0_TX_DMA_DEAD field position +#define NXMAC_AC_0_TX_DMA_DEAD_POS 13 +/// PT_ERROR field bit +#define NXMAC_PT_ERROR_BIT ((uint32_t)0x00001000) +/// PT_ERROR field position +#define NXMAC_PT_ERROR_POS 12 +/// TIM_SET field bit +#define NXMAC_TIM_SET_BIT ((uint32_t)0x00000800) +/// TIM_SET field position +#define NXMAC_TIM_SET_POS 11 +/// OLBC_DSSS field bit +#define NXMAC_OLBC_DSSS_BIT ((uint32_t)0x00000400) +/// OLBC_DSSS field position +#define NXMAC_OLBC_DSSS_POS 10 +/// OLBC_OFDM field bit +#define NXMAC_OLBC_OFDM_BIT ((uint32_t)0x00000200) +/// OLBC_OFDM field position +#define NXMAC_OLBC_OFDM_POS 9 +/// RX_FIFO_OVER_FLOW field bit +#define NXMAC_RX_FIFO_OVER_FLOW_BIT ((uint32_t)0x00000100) +/// RX_FIFO_OVER_FLOW field position +#define NXMAC_RX_FIFO_OVER_FLOW_POS 8 +/// RX_DMA_EMPTY field bit +#define NXMAC_RX_DMA_EMPTY_BIT ((uint32_t)0x00000080) +/// RX_DMA_EMPTY field position +#define NXMAC_RX_DMA_EMPTY_POS 7 +/// MAC_PHYIF_OVERFLOW field bit +#define NXMAC_MAC_PHYIF_OVERFLOW_BIT ((uint32_t)0x00000040) +/// MAC_PHYIF_OVERFLOW field position +#define NXMAC_MAC_PHYIF_OVERFLOW_POS 6 +/// COEX_EVENT field bit +#define NXMAC_COEX_EVENT_BIT ((uint32_t)0x00000020) +/// COEX_EVENT field position +#define NXMAC_COEX_EVENT_POS 5 +/// ABS_GEN_TIMERS field bit +#define NXMAC_ABS_GEN_TIMERS_BIT ((uint32_t)0x00000008) +/// ABS_GEN_TIMERS field position +#define NXMAC_ABS_GEN_TIMERS_POS 3 +/// IDLE_INTERRUPT field bit +#define NXMAC_IDLE_INTERRUPT_BIT ((uint32_t)0x00000004) +/// IDLE_INTERRUPT field position +#define NXMAC_IDLE_INTERRUPT_POS 2 +/// IMP_SEC_TBTT field bit +#define NXMAC_IMP_SEC_TBTT_BIT ((uint32_t)0x00000002) +/// IMP_SEC_TBTT field position +#define NXMAC_IMP_SEC_TBTT_POS 1 +/// IMP_PRI_TBTT field bit +#define NXMAC_IMP_PRI_TBTT_BIT ((uint32_t)0x00000001) +/// IMP_PRI_TBTT field position +#define NXMAC_IMP_PRI_TBTT_POS 0 + +/// MASTER_GEN_INT_EN field reset value +#define NXMAC_MASTER_GEN_INT_EN_RST 0x0 +/// RX_PAYLOAD_DMA_DEAD field reset value +#define NXMAC_RX_PAYLOAD_DMA_DEAD_RST 0x0 +/// RX_HEADER_DMA_DEAD field reset value +#define NXMAC_RX_HEADER_DMA_DEAD_RST 0x0 +/// PHY_RX_START field reset value +#define NXMAC_PHY_RX_START_RST 0x0 +/// PHY_ERR field reset value +#define NXMAC_PHY_ERR_RST 0x0 +/// MAC_PHYIF_UNDER_RUN field reset value +#define NXMAC_MAC_PHYIF_UNDER_RUN_RST 0x0 +/// HW_ERR field reset value +#define NXMAC_HW_ERR_RST 0x0 +/// IMP_SEC_DTIM field reset value +#define NXMAC_IMP_SEC_DTIM_RST 0x0 +/// IMP_PRI_DTIM field reset value +#define NXMAC_IMP_PRI_DTIM_RST 0x0 +/// BCN_TX_DMA_DEAD field reset value +#define NXMAC_BCN_TX_DMA_DEAD_RST 0x0 +/// AC_3_TX_DMA_DEAD field reset value +#define NXMAC_AC_3_TX_DMA_DEAD_RST 0x0 +/// AC_2_TX_DMA_DEAD field reset value +#define NXMAC_AC_2_TX_DMA_DEAD_RST 0x0 +/// AC_1_TX_DMA_DEAD field reset value +#define NXMAC_AC_1_TX_DMA_DEAD_RST 0x0 +/// AC_0_TX_DMA_DEAD field reset value +#define NXMAC_AC_0_TX_DMA_DEAD_RST 0x0 +/// PT_ERROR field reset value +#define NXMAC_PT_ERROR_RST 0x0 +/// TIM_SET field reset value +#define NXMAC_TIM_SET_RST 0x0 +/// OLBC_DSSS field reset value +#define NXMAC_OLBC_DSSS_RST 0x0 +/// OLBC_OFDM field reset value +#define NXMAC_OLBC_OFDM_RST 0x0 +/// RX_FIFO_OVER_FLOW field reset value +#define NXMAC_RX_FIFO_OVER_FLOW_RST 0x0 +/// RX_DMA_EMPTY field reset value +#define NXMAC_RX_DMA_EMPTY_RST 0x0 +/// MAC_PHYIF_OVERFLOW field reset value +#define NXMAC_MAC_PHYIF_OVERFLOW_RST 0x0 +/// COEX_EVENT field reset value +#define NXMAC_COEX_EVENT_RST 0x0 +/// ABS_GEN_TIMERS field reset value +#define NXMAC_ABS_GEN_TIMERS_RST 0x0 +/// IDLE_INTERRUPT field reset value +#define NXMAC_IDLE_INTERRUPT_RST 0x0 +/// IMP_SEC_TBTT field reset value +#define NXMAC_IMP_SEC_TBTT_RST 0x0 +/// IMP_PRI_TBTT field reset value +#define NXMAC_IMP_PRI_TBTT_RST 0x0 + +/** + * @brief Constructs a value for the GEN_INT_ENABLE register given values for its fields + * and writes the value to the register. + * + * @param[in] mastergeninten - The value to use for the masterGenIntEn field. + * @param[in] rxpayloaddmadead - The value to use for the rxPayloadDMADead field. + * @param[in] rxheaderdmadead - The value to use for the rxHeaderDMADead field. + * @param[in] phyrxstart - The value to use for the phyRxStart field. + * @param[in] phyerr - The value to use for the phyErr field. + * @param[in] macphyifunderrun - The value to use for the macPHYIFUnderRun field. + * @param[in] hwerr - The value to use for the hwErr field. + * @param[in] impsecdtim - The value to use for the impSecDTIM field. + * @param[in] imppridtim - The value to use for the impPriDTIM field. + * @param[in] bcntxdmadead - The value to use for the bcnTxDMADead field. + * @param[in] ac3txdmadead - The value to use for the ac3TxDMADead field. + * @param[in] ac2txdmadead - The value to use for the ac2TxDMADead field. + * @param[in] ac1txdmadead - The value to use for the ac1TxDMADead field. + * @param[in] ac0txdmadead - The value to use for the ac0TxDMADead field. + * @param[in] pterror - The value to use for the ptError field. + * @param[in] timset - The value to use for the timSet field. + * @param[in] olbcdsss - The value to use for the olbcDSSS field. + * @param[in] olbcofdm - The value to use for the olbcOFDM field. + * @param[in] rxfifooverflow - The value to use for the rxFIFOOverFlow field. + * @param[in] rxdmaempty - The value to use for the rxDMAEmpty field. + * @param[in] macphyifoverflow - The value to use for the macPHYIFOverflow field. + * @param[in] coexevent - The value to use for the coexEvent field. + * @param[in] absgentimers - The value to use for the absGenTimers field. + * @param[in] idleinterrupt - The value to use for the idleInterrupt field. + * @param[in] impsectbtt - The value to use for the impSecTBTT field. + * @param[in] imppritbtt - The value to use for the impPriTBTT field. + */ +__INLINE void nxmac_gen_int_enable_pack(uint8_t mastergeninten, uint8_t rxpayloaddmadead, uint8_t rxheaderdmadead, uint8_t phyrxstart, uint8_t phyerr, uint8_t macphyifunderrun, uint8_t hwerr, uint8_t impsecdtim, uint8_t imppridtim, uint8_t bcntxdmadead, uint8_t ac3txdmadead, uint8_t ac2txdmadead, uint8_t ac1txdmadead, uint8_t ac0txdmadead, uint8_t pterror, uint8_t timset, uint8_t olbcdsss, uint8_t olbcofdm, uint8_t rxfifooverflow, uint8_t rxdmaempty, uint8_t macphyifoverflow, uint8_t coexevent, uint8_t absgentimers, uint8_t idleinterrupt, uint8_t impsectbtt, uint8_t imppritbtt) +{ + ASSERT_ERR((((uint32_t)mastergeninten << 31) & ~((uint32_t)0x80000000)) == 0); + ASSERT_ERR((((uint32_t)rxpayloaddmadead << 25) & ~((uint32_t)0x02000000)) == 0); + ASSERT_ERR((((uint32_t)rxheaderdmadead << 24) & ~((uint32_t)0x01000000)) == 0); + ASSERT_ERR((((uint32_t)phyrxstart << 23) & ~((uint32_t)0x00800000)) == 0); + ASSERT_ERR((((uint32_t)phyerr << 22) & ~((uint32_t)0x00400000)) == 0); + ASSERT_ERR((((uint32_t)macphyifunderrun << 21) & ~((uint32_t)0x00200000)) == 0); + ASSERT_ERR((((uint32_t)hwerr << 20) & ~((uint32_t)0x00100000)) == 0); + ASSERT_ERR((((uint32_t)impsecdtim << 19) & ~((uint32_t)0x00080000)) == 0); + ASSERT_ERR((((uint32_t)imppridtim << 18) & ~((uint32_t)0x00040000)) == 0); + ASSERT_ERR((((uint32_t)bcntxdmadead << 17) & ~((uint32_t)0x00020000)) == 0); + ASSERT_ERR((((uint32_t)ac3txdmadead << 16) & ~((uint32_t)0x00010000)) == 0); + ASSERT_ERR((((uint32_t)ac2txdmadead << 15) & ~((uint32_t)0x00008000)) == 0); + ASSERT_ERR((((uint32_t)ac1txdmadead << 14) & ~((uint32_t)0x00004000)) == 0); + ASSERT_ERR((((uint32_t)ac0txdmadead << 13) & ~((uint32_t)0x00002000)) == 0); + ASSERT_ERR((((uint32_t)pterror << 12) & ~((uint32_t)0x00001000)) == 0); + ASSERT_ERR((((uint32_t)timset << 11) & ~((uint32_t)0x00000800)) == 0); + ASSERT_ERR((((uint32_t)olbcdsss << 10) & ~((uint32_t)0x00000400)) == 0); + ASSERT_ERR((((uint32_t)olbcofdm << 9) & ~((uint32_t)0x00000200)) == 0); + ASSERT_ERR((((uint32_t)rxfifooverflow << 8) & ~((uint32_t)0x00000100)) == 0); + ASSERT_ERR((((uint32_t)rxdmaempty << 7) & ~((uint32_t)0x00000080)) == 0); + ASSERT_ERR((((uint32_t)macphyifoverflow << 6) & ~((uint32_t)0x00000040)) == 0); + ASSERT_ERR((((uint32_t)coexevent << 5) & ~((uint32_t)0x00000020)) == 0); + ASSERT_ERR((((uint32_t)absgentimers << 3) & ~((uint32_t)0x00000008)) == 0); + ASSERT_ERR((((uint32_t)idleinterrupt << 2) & ~((uint32_t)0x00000004)) == 0); + ASSERT_ERR((((uint32_t)impsectbtt << 1) & ~((uint32_t)0x00000002)) == 0); + ASSERT_ERR((((uint32_t)imppritbtt << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ENABLE_ADDR, ((uint32_t)mastergeninten << 31) | ((uint32_t)rxpayloaddmadead << 25) | ((uint32_t)rxheaderdmadead << 24) | ((uint32_t)phyrxstart << 23) | ((uint32_t)phyerr << 22) | ((uint32_t)macphyifunderrun << 21) | ((uint32_t)hwerr << 20) | ((uint32_t)impsecdtim << 19) | ((uint32_t)imppridtim << 18) | ((uint32_t)bcntxdmadead << 17) | ((uint32_t)ac3txdmadead << 16) | ((uint32_t)ac2txdmadead << 15) | ((uint32_t)ac1txdmadead << 14) | ((uint32_t)ac0txdmadead << 13) | ((uint32_t)pterror << 12) | ((uint32_t)timset << 11) | ((uint32_t)olbcdsss << 10) | ((uint32_t)olbcofdm << 9) | ((uint32_t)rxfifooverflow << 8) | ((uint32_t)rxdmaempty << 7) | ((uint32_t)macphyifoverflow << 6) | ((uint32_t)coexevent << 5) | ((uint32_t)absgentimers << 3) | ((uint32_t)idleinterrupt << 2) | ((uint32_t)impsectbtt << 1) | ((uint32_t)imppritbtt << 0)); +} + +/** + * @brief Unpacks GEN_INT_ENABLE's fields from current value of the GEN_INT_ENABLE register. + * + * Reads the GEN_INT_ENABLE register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] mastergeninten - Will be populated with the current value of this field from the register. + * @param[out] rxpayloaddmadead - Will be populated with the current value of this field from the register. + * @param[out] rxheaderdmadead - Will be populated with the current value of this field from the register. + * @param[out] phyrxstart - Will be populated with the current value of this field from the register. + * @param[out] phyerr - Will be populated with the current value of this field from the register. + * @param[out] macphyifunderrun - Will be populated with the current value of this field from the register. + * @param[out] hwerr - Will be populated with the current value of this field from the register. + * @param[out] impsecdtim - Will be populated with the current value of this field from the register. + * @param[out] imppridtim - Will be populated with the current value of this field from the register. + * @param[out] bcntxdmadead - Will be populated with the current value of this field from the register. + * @param[out] ac3txdmadead - Will be populated with the current value of this field from the register. + * @param[out] ac2txdmadead - Will be populated with the current value of this field from the register. + * @param[out] ac1txdmadead - Will be populated with the current value of this field from the register. + * @param[out] ac0txdmadead - Will be populated with the current value of this field from the register. + * @param[out] pterror - Will be populated with the current value of this field from the register. + * @param[out] timset - Will be populated with the current value of this field from the register. + * @param[out] olbcdsss - Will be populated with the current value of this field from the register. + * @param[out] olbcofdm - Will be populated with the current value of this field from the register. + * @param[out] rxfifooverflow - Will be populated with the current value of this field from the register. + * @param[out] rxdmaempty - Will be populated with the current value of this field from the register. + * @param[out] macphyifoverflow - Will be populated with the current value of this field from the register. + * @param[out] coexevent - Will be populated with the current value of this field from the register. + * @param[out] absgentimers - Will be populated with the current value of this field from the register. + * @param[out] idleinterrupt - Will be populated with the current value of this field from the register. + * @param[out] impsectbtt - Will be populated with the current value of this field from the register. + * @param[out] imppritbtt - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_gen_int_enable_unpack(uint8_t *mastergeninten, uint8_t *rxpayloaddmadead, uint8_t *rxheaderdmadead, uint8_t *phyrxstart, uint8_t *phyerr, uint8_t *macphyifunderrun, uint8_t *hwerr, uint8_t *impsecdtim, uint8_t *imppridtim, uint8_t *bcntxdmadead, uint8_t *ac3txdmadead, uint8_t *ac2txdmadead, uint8_t *ac1txdmadead, uint8_t *ac0txdmadead, uint8_t *pterror, uint8_t *timset, uint8_t *olbcdsss, uint8_t *olbcofdm, uint8_t *rxfifooverflow, uint8_t *rxdmaempty, uint8_t *macphyifoverflow, uint8_t *coexevent, uint8_t *absgentimers, uint8_t *idleinterrupt, uint8_t *impsectbtt, uint8_t *imppritbtt) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR); + + *mastergeninten = (localVal & ((uint32_t)0x80000000)) >> 31; + *rxpayloaddmadead = (localVal & ((uint32_t)0x02000000)) >> 25; + *rxheaderdmadead = (localVal & ((uint32_t)0x01000000)) >> 24; + *phyrxstart = (localVal & ((uint32_t)0x00800000)) >> 23; + *phyerr = (localVal & ((uint32_t)0x00400000)) >> 22; + *macphyifunderrun = (localVal & ((uint32_t)0x00200000)) >> 21; + *hwerr = (localVal & ((uint32_t)0x00100000)) >> 20; + *impsecdtim = (localVal & ((uint32_t)0x00080000)) >> 19; + *imppridtim = (localVal & ((uint32_t)0x00040000)) >> 18; + *bcntxdmadead = (localVal & ((uint32_t)0x00020000)) >> 17; + *ac3txdmadead = (localVal & ((uint32_t)0x00010000)) >> 16; + *ac2txdmadead = (localVal & ((uint32_t)0x00008000)) >> 15; + *ac1txdmadead = (localVal & ((uint32_t)0x00004000)) >> 14; + *ac0txdmadead = (localVal & ((uint32_t)0x00002000)) >> 13; + *pterror = (localVal & ((uint32_t)0x00001000)) >> 12; + *timset = (localVal & ((uint32_t)0x00000800)) >> 11; + *olbcdsss = (localVal & ((uint32_t)0x00000400)) >> 10; + *olbcofdm = (localVal & ((uint32_t)0x00000200)) >> 9; + *rxfifooverflow = (localVal & ((uint32_t)0x00000100)) >> 8; + *rxdmaempty = (localVal & ((uint32_t)0x00000080)) >> 7; + *macphyifoverflow = (localVal & ((uint32_t)0x00000040)) >> 6; + *coexevent = (localVal & ((uint32_t)0x00000020)) >> 5; + *absgentimers = (localVal & ((uint32_t)0x00000008)) >> 3; + *idleinterrupt = (localVal & ((uint32_t)0x00000004)) >> 2; + *impsectbtt = (localVal & ((uint32_t)0x00000002)) >> 1; + *imppritbtt = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +/** + * @brief Returns the current value of the masterGenIntEn field in the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read and the masterGenIntEn field's value will be returned. + * + * @return The current value of the masterGenIntEn field in the GEN_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_master_gen_int_en_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +/** + * @brief Sets the masterGenIntEn field of the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] mastergeninten - The value to set the field to. + */ +__INLINE void nxmac_enable_master_gen_int_en_setf(uint8_t mastergeninten) +{ + ASSERT_ERR((((uint32_t)mastergeninten << 31) & ~((uint32_t)0x80000000)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR) & ~((uint32_t)0x80000000)) | ((uint32_t)mastergeninten << 31)); +} + +/** + * @brief Returns the current value of the rxPayloadDMADead field in the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read and the rxPayloadDMADead field's value will be returned. + * + * @return The current value of the rxPayloadDMADead field in the GEN_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_rx_payload_dma_dead_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x02000000)) >> 25); +} + +/** + * @brief Sets the rxPayloadDMADead field of the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] rxpayloaddmadead - The value to set the field to. + */ +__INLINE void nxmac_enable_rx_payload_dma_dead_setf(uint8_t rxpayloaddmadead) +{ + ASSERT_ERR((((uint32_t)rxpayloaddmadead << 25) & ~((uint32_t)0x02000000)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR) & ~((uint32_t)0x02000000)) | ((uint32_t)rxpayloaddmadead << 25)); +} + +/** + * @brief Returns the current value of the rxHeaderDMADead field in the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read and the rxHeaderDMADead field's value will be returned. + * + * @return The current value of the rxHeaderDMADead field in the GEN_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_rx_header_dma_dead_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x01000000)) >> 24); +} + +/** + * @brief Sets the rxHeaderDMADead field of the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] rxheaderdmadead - The value to set the field to. + */ +__INLINE void nxmac_enable_rx_header_dma_dead_setf(uint8_t rxheaderdmadead) +{ + ASSERT_ERR((((uint32_t)rxheaderdmadead << 24) & ~((uint32_t)0x01000000)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR) & ~((uint32_t)0x01000000)) | ((uint32_t)rxheaderdmadead << 24)); +} + +/** + * @brief Returns the current value of the phyRxStart field in the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read and the phyRxStart field's value will be returned. + * + * @return The current value of the phyRxStart field in the GEN_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_phy_rx_start_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x00800000)) >> 23); +} + +/** + * @brief Sets the phyRxStart field of the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] phyrxstart - The value to set the field to. + */ +__INLINE void nxmac_enable_phy_rx_start_setf(uint8_t phyrxstart) +{ + ASSERT_ERR((((uint32_t)phyrxstart << 23) & ~((uint32_t)0x00800000)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR) & ~((uint32_t)0x00800000)) | ((uint32_t)phyrxstart << 23)); +} + +/** + * @brief Returns the current value of the phyErr field in the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read and the phyErr field's value will be returned. + * + * @return The current value of the phyErr field in the GEN_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_phy_err_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x00400000)) >> 22); +} + +/** + * @brief Sets the phyErr field of the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] phyerr - The value to set the field to. + */ +__INLINE void nxmac_enable_phy_err_setf(uint8_t phyerr) +{ + ASSERT_ERR((((uint32_t)phyerr << 22) & ~((uint32_t)0x00400000)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR) & ~((uint32_t)0x00400000)) | ((uint32_t)phyerr << 22)); +} + +/** + * @brief Returns the current value of the macPHYIFUnderRun field in the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read and the macPHYIFUnderRun field's value will be returned. + * + * @return The current value of the macPHYIFUnderRun field in the GEN_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_mac_phyif_under_run_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x00200000)) >> 21); +} + +/** + * @brief Sets the macPHYIFUnderRun field of the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] macphyifunderrun - The value to set the field to. + */ +__INLINE void nxmac_enable_mac_phyif_under_run_setf(uint8_t macphyifunderrun) +{ + ASSERT_ERR((((uint32_t)macphyifunderrun << 21) & ~((uint32_t)0x00200000)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR) & ~((uint32_t)0x00200000)) | ((uint32_t)macphyifunderrun << 21)); +} + +/** + * @brief Returns the current value of the hwErr field in the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read and the hwErr field's value will be returned. + * + * @return The current value of the hwErr field in the GEN_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_hw_err_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x00100000)) >> 20); +} + +/** + * @brief Sets the hwErr field of the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] hwerr - The value to set the field to. + */ +__INLINE void nxmac_enable_hw_err_setf(uint8_t hwerr) +{ + ASSERT_ERR((((uint32_t)hwerr << 20) & ~((uint32_t)0x00100000)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR) & ~((uint32_t)0x00100000)) | ((uint32_t)hwerr << 20)); +} + +/** + * @brief Returns the current value of the impSecDTIM field in the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read and the impSecDTIM field's value will be returned. + * + * @return The current value of the impSecDTIM field in the GEN_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_imp_sec_dtim_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x00080000)) >> 19); +} + +/** + * @brief Sets the impSecDTIM field of the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] impsecdtim - The value to set the field to. + */ +__INLINE void nxmac_enable_imp_sec_dtim_setf(uint8_t impsecdtim) +{ + ASSERT_ERR((((uint32_t)impsecdtim << 19) & ~((uint32_t)0x00080000)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR) & ~((uint32_t)0x00080000)) | ((uint32_t)impsecdtim << 19)); +} + +/** + * @brief Returns the current value of the impPriDTIM field in the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read and the impPriDTIM field's value will be returned. + * + * @return The current value of the impPriDTIM field in the GEN_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_imp_pri_dtim_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x00040000)) >> 18); +} + +/** + * @brief Sets the impPriDTIM field of the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] imppridtim - The value to set the field to. + */ +__INLINE void nxmac_enable_imp_pri_dtim_setf(uint8_t imppridtim) +{ + ASSERT_ERR((((uint32_t)imppridtim << 18) & ~((uint32_t)0x00040000)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR) & ~((uint32_t)0x00040000)) | ((uint32_t)imppridtim << 18)); +} + +/** + * @brief Returns the current value of the bcnTxDMADead field in the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read and the bcnTxDMADead field's value will be returned. + * + * @return The current value of the bcnTxDMADead field in the GEN_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_bcn_tx_dma_dead_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x00020000)) >> 17); +} + +/** + * @brief Sets the bcnTxDMADead field of the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] bcntxdmadead - The value to set the field to. + */ +__INLINE void nxmac_enable_bcn_tx_dma_dead_setf(uint8_t bcntxdmadead) +{ + ASSERT_ERR((((uint32_t)bcntxdmadead << 17) & ~((uint32_t)0x00020000)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR) & ~((uint32_t)0x00020000)) | ((uint32_t)bcntxdmadead << 17)); +} + +/** + * @brief Returns the current value of the ac3TxDMADead field in the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read and the ac3TxDMADead field's value will be returned. + * + * @return The current value of the ac3TxDMADead field in the GEN_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_ac_3_tx_dma_dead_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x00010000)) >> 16); +} + +/** + * @brief Sets the ac3TxDMADead field of the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] ac3txdmadead - The value to set the field to. + */ +__INLINE void nxmac_enable_ac_3_tx_dma_dead_setf(uint8_t ac3txdmadead) +{ + ASSERT_ERR((((uint32_t)ac3txdmadead << 16) & ~((uint32_t)0x00010000)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR) & ~((uint32_t)0x00010000)) | ((uint32_t)ac3txdmadead << 16)); +} + +/** + * @brief Returns the current value of the ac2TxDMADead field in the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read and the ac2TxDMADead field's value will be returned. + * + * @return The current value of the ac2TxDMADead field in the GEN_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_ac_2_tx_dma_dead_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x00008000)) >> 15); +} + +/** + * @brief Sets the ac2TxDMADead field of the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] ac2txdmadead - The value to set the field to. + */ +__INLINE void nxmac_enable_ac_2_tx_dma_dead_setf(uint8_t ac2txdmadead) +{ + ASSERT_ERR((((uint32_t)ac2txdmadead << 15) & ~((uint32_t)0x00008000)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR) & ~((uint32_t)0x00008000)) | ((uint32_t)ac2txdmadead << 15)); +} + +/** + * @brief Returns the current value of the ac1TxDMADead field in the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read and the ac1TxDMADead field's value will be returned. + * + * @return The current value of the ac1TxDMADead field in the GEN_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_ac_1_tx_dma_dead_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x00004000)) >> 14); +} + +/** + * @brief Sets the ac1TxDMADead field of the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] ac1txdmadead - The value to set the field to. + */ +__INLINE void nxmac_enable_ac_1_tx_dma_dead_setf(uint8_t ac1txdmadead) +{ + ASSERT_ERR((((uint32_t)ac1txdmadead << 14) & ~((uint32_t)0x00004000)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR) & ~((uint32_t)0x00004000)) | ((uint32_t)ac1txdmadead << 14)); +} + +/** + * @brief Returns the current value of the ac0TxDMADead field in the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read and the ac0TxDMADead field's value will be returned. + * + * @return The current value of the ac0TxDMADead field in the GEN_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_ac_0_tx_dma_dead_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x00002000)) >> 13); +} + +/** + * @brief Sets the ac0TxDMADead field of the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] ac0txdmadead - The value to set the field to. + */ +__INLINE void nxmac_enable_ac_0_tx_dma_dead_setf(uint8_t ac0txdmadead) +{ + ASSERT_ERR((((uint32_t)ac0txdmadead << 13) & ~((uint32_t)0x00002000)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR) & ~((uint32_t)0x00002000)) | ((uint32_t)ac0txdmadead << 13)); +} + +/** + * @brief Returns the current value of the ptError field in the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read and the ptError field's value will be returned. + * + * @return The current value of the ptError field in the GEN_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_pt_error_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x00001000)) >> 12); +} + +/** + * @brief Sets the ptError field of the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] pterror - The value to set the field to. + */ +__INLINE void nxmac_enable_pt_error_setf(uint8_t pterror) +{ + ASSERT_ERR((((uint32_t)pterror << 12) & ~((uint32_t)0x00001000)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR) & ~((uint32_t)0x00001000)) | ((uint32_t)pterror << 12)); +} + +/** + * @brief Returns the current value of the timSet field in the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read and the timSet field's value will be returned. + * + * @return The current value of the timSet field in the GEN_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_tim_set_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x00000800)) >> 11); +} + +/** + * @brief Sets the timSet field of the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] timset - The value to set the field to. + */ +__INLINE void nxmac_enable_tim_set_setf(uint8_t timset) +{ + ASSERT_ERR((((uint32_t)timset << 11) & ~((uint32_t)0x00000800)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR) & ~((uint32_t)0x00000800)) | ((uint32_t)timset << 11)); +} + +/** + * @brief Returns the current value of the olbcDSSS field in the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read and the olbcDSSS field's value will be returned. + * + * @return The current value of the olbcDSSS field in the GEN_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_olbc_dsss_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x00000400)) >> 10); +} + +/** + * @brief Sets the olbcDSSS field of the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] olbcdsss - The value to set the field to. + */ +__INLINE void nxmac_enable_olbc_dsss_setf(uint8_t olbcdsss) +{ + ASSERT_ERR((((uint32_t)olbcdsss << 10) & ~((uint32_t)0x00000400)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR) & ~((uint32_t)0x00000400)) | ((uint32_t)olbcdsss << 10)); +} + +/** + * @brief Returns the current value of the olbcOFDM field in the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read and the olbcOFDM field's value will be returned. + * + * @return The current value of the olbcOFDM field in the GEN_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_olbc_ofdm_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x00000200)) >> 9); +} + +/** + * @brief Sets the olbcOFDM field of the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] olbcofdm - The value to set the field to. + */ +__INLINE void nxmac_enable_olbc_ofdm_setf(uint8_t olbcofdm) +{ + ASSERT_ERR((((uint32_t)olbcofdm << 9) & ~((uint32_t)0x00000200)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR) & ~((uint32_t)0x00000200)) | ((uint32_t)olbcofdm << 9)); +} + +/** + * @brief Returns the current value of the rxFIFOOverFlow field in the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read and the rxFIFOOverFlow field's value will be returned. + * + * @return The current value of the rxFIFOOverFlow field in the GEN_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_rx_fifo_over_flow_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x00000100)) >> 8); +} + +/** + * @brief Sets the rxFIFOOverFlow field of the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] rxfifooverflow - The value to set the field to. + */ +__INLINE void nxmac_enable_rx_fifo_over_flow_setf(uint8_t rxfifooverflow) +{ + ASSERT_ERR((((uint32_t)rxfifooverflow << 8) & ~((uint32_t)0x00000100)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR) & ~((uint32_t)0x00000100)) | ((uint32_t)rxfifooverflow << 8)); +} + +/** + * @brief Returns the current value of the rxDMAEmpty field in the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read and the rxDMAEmpty field's value will be returned. + * + * @return The current value of the rxDMAEmpty field in the GEN_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_rx_dma_empty_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x00000080)) >> 7); +} + +/** + * @brief Sets the rxDMAEmpty field of the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] rxdmaempty - The value to set the field to. + */ +__INLINE void nxmac_enable_rx_dma_empty_setf(uint8_t rxdmaempty) +{ + ASSERT_ERR((((uint32_t)rxdmaempty << 7) & ~((uint32_t)0x00000080)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR) & ~((uint32_t)0x00000080)) | ((uint32_t)rxdmaempty << 7)); +} + +/** + * @brief Returns the current value of the macPHYIFOverflow field in the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read and the macPHYIFOverflow field's value will be returned. + * + * @return The current value of the macPHYIFOverflow field in the GEN_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_mac_phyif_overflow_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x00000040)) >> 6); +} + +/** + * @brief Sets the macPHYIFOverflow field of the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] macphyifoverflow - The value to set the field to. + */ +__INLINE void nxmac_enable_mac_phyif_overflow_setf(uint8_t macphyifoverflow) +{ + ASSERT_ERR((((uint32_t)macphyifoverflow << 6) & ~((uint32_t)0x00000040)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR) & ~((uint32_t)0x00000040)) | ((uint32_t)macphyifoverflow << 6)); +} + +/** + * @brief Returns the current value of the coexEvent field in the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read and the coexEvent field's value will be returned. + * + * @return The current value of the coexEvent field in the GEN_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_coex_event_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +/** + * @brief Sets the coexEvent field of the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] coexevent - The value to set the field to. + */ +__INLINE void nxmac_enable_coex_event_setf(uint8_t coexevent) +{ + ASSERT_ERR((((uint32_t)coexevent << 5) & ~((uint32_t)0x00000020)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR) & ~((uint32_t)0x00000020)) | ((uint32_t)coexevent << 5)); +} + +/** + * @brief Returns the current value of the absGenTimers field in the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read and the absGenTimers field's value will be returned. + * + * @return The current value of the absGenTimers field in the GEN_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_abs_gen_timers_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +/** + * @brief Sets the absGenTimers field of the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] absgentimers - The value to set the field to. + */ +__INLINE void nxmac_enable_abs_gen_timers_setf(uint8_t absgentimers) +{ + ASSERT_ERR((((uint32_t)absgentimers << 3) & ~((uint32_t)0x00000008)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR) & ~((uint32_t)0x00000008)) | ((uint32_t)absgentimers << 3)); +} + +/** + * @brief Returns the current value of the idleInterrupt field in the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read and the idleInterrupt field's value will be returned. + * + * @return The current value of the idleInterrupt field in the GEN_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_idle_interrupt_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +/** + * @brief Sets the idleInterrupt field of the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] idleinterrupt - The value to set the field to. + */ +__INLINE void nxmac_enable_idle_interrupt_setf(uint8_t idleinterrupt) +{ + ASSERT_ERR((((uint32_t)idleinterrupt << 2) & ~((uint32_t)0x00000004)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR) & ~((uint32_t)0x00000004)) | ((uint32_t)idleinterrupt << 2)); +} + +/** + * @brief Returns the current value of the impSecTBTT field in the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read and the impSecTBTT field's value will be returned. + * + * @return The current value of the impSecTBTT field in the GEN_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_imp_sec_tbtt_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +/** + * @brief Sets the impSecTBTT field of the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] impsectbtt - The value to set the field to. + */ +__INLINE void nxmac_enable_imp_sec_tbtt_setf(uint8_t impsectbtt) +{ + ASSERT_ERR((((uint32_t)impsectbtt << 1) & ~((uint32_t)0x00000002)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR) & ~((uint32_t)0x00000002)) | ((uint32_t)impsectbtt << 1)); +} + +/** + * @brief Returns the current value of the impPriTBTT field in the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read and the impPriTBTT field's value will be returned. + * + * @return The current value of the impPriTBTT field in the GEN_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_imp_pri_tbtt_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/** + * @brief Sets the impPriTBTT field of the GEN_INT_ENABLE register. + * + * The GEN_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] imppritbtt - The value to set the field to. + */ +__INLINE void nxmac_enable_imp_pri_tbtt_setf(uint8_t imppritbtt) +{ + ASSERT_ERR((((uint32_t)imppritbtt << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_GEN_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_GEN_INT_ENABLE_ADDR) & ~((uint32_t)0x00000001)) | ((uint32_t)imppritbtt << 0)); +} + +/// @} + +/** + * @name TX_RX_INT_STATUS register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     28      bcnTxBufTrigger   0
+ *     27      ac3TxBufTrigger   0
+ *     26      ac2TxBufTrigger   0
+ *     25      ac1TxBufTrigger   0
+ *     24      ac0TxBufTrigger   0
+ *     23     ac3BWDropTrigger   0
+ *     22     ac2BWDropTrigger   0
+ *     21     ac1BWDropTrigger   0
+ *     20     ac0BWDropTrigger   0
+ *     19     counterRxTrigger   0
+ *     18          baRxTrigger   0
+ *     17       timerRxTrigger   0
+ *     16            rxTrigger   0
+ *     15     secUserTxTrigger   0
+ *     14       timerTxTrigger   0
+ *     13         txopComplete   0
+ *     12          rdTxTrigger   0
+ *     11        hccaTxTrigger   0
+ *     10         bcnTxTrigger   0
+ *     09         ac3TxTrigger   0
+ *     08         ac2TxTrigger   0
+ *     07         ac1TxTrigger   0
+ *     06         ac0TxTrigger   0
+ *     05        rdProtTrigger   0
+ *     04      hccaProtTrigger   0
+ *     03       ac3ProtTrigger   0
+ *     02       ac2ProtTrigger   0
+ *     01       ac1ProtTrigger   0
+ *     00       ac0ProtTrigger   0
+ * 
+ * + * @{ + */ + +/// Address of the TX_RX_INT_STATUS register +#define NXMAC_TX_RX_INT_STATUS_ADDR 0xC0008078 +/// Offset of the TX_RX_INT_STATUS register from the base address +#define NXMAC_TX_RX_INT_STATUS_OFFSET 0x00000078 +/// Index of the TX_RX_INT_STATUS register +#define NXMAC_TX_RX_INT_STATUS_INDEX 0x0000001E +/// Reset value of the TX_RX_INT_STATUS register +#define NXMAC_TX_RX_INT_STATUS_RESET 0x00000000 + +/** + * @brief Returns the current value of the TX_RX_INT_STATUS register. + * The TX_RX_INT_STATUS register will be read and its value returned. + * @return The current value of the TX_RX_INT_STATUS register. + */ +__INLINE uint32_t nxmac_tx_rx_int_status_get(void) +{ + return REG_PL_RD(NXMAC_TX_RX_INT_STATUS_ADDR); +} + +/** + * @brief Sets the TX_RX_INT_STATUS register to a value. + * The TX_RX_INT_STATUS register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_tx_rx_int_status_set(uint32_t value) +{ + REG_PL_WR(NXMAC_TX_RX_INT_STATUS_ADDR, value); +} + +// fields defined in symmetrical set/clear register +/** + * @brief Constructs a value for the TX_RX_INT_STATUS register given values for its fields + * and writes the value to the register. + * + * @param[in] bcntxbuftrigger - The value to use for the bcnTxBufTrigger field. + * @param[in] ac3txbuftrigger - The value to use for the ac3TxBufTrigger field. + * @param[in] ac2txbuftrigger - The value to use for the ac2TxBufTrigger field. + * @param[in] ac1txbuftrigger - The value to use for the ac1TxBufTrigger field. + * @param[in] ac0txbuftrigger - The value to use for the ac0TxBufTrigger field. + * @param[in] ac3bwdroptrigger - The value to use for the ac3BWDropTrigger field. + * @param[in] ac2bwdroptrigger - The value to use for the ac2BWDropTrigger field. + * @param[in] ac1bwdroptrigger - The value to use for the ac1BWDropTrigger field. + * @param[in] ac0bwdroptrigger - The value to use for the ac0BWDropTrigger field. + * @param[in] counterrxtrigger - The value to use for the counterRxTrigger field. + * @param[in] barxtrigger - The value to use for the baRxTrigger field. + * @param[in] timerrxtrigger - The value to use for the timerRxTrigger field. + * @param[in] rxtrigger - The value to use for the rxTrigger field. + * @param[in] timertxtrigger - The value to use for the timerTxTrigger field. + * @param[in] txopcomplete - The value to use for the txopComplete field. + * @param[in] rdtxtrigger - The value to use for the rdTxTrigger field. + * @param[in] hccatxtrigger - The value to use for the hccaTxTrigger field. + * @param[in] bcntxtrigger - The value to use for the bcnTxTrigger field. + * @param[in] ac3txtrigger - The value to use for the ac3TxTrigger field. + * @param[in] ac2txtrigger - The value to use for the ac2TxTrigger field. + * @param[in] ac1txtrigger - The value to use for the ac1TxTrigger field. + * @param[in] ac0txtrigger - The value to use for the ac0TxTrigger field. + * @param[in] rdprottrigger - The value to use for the rdProtTrigger field. + * @param[in] hccaprottrigger - The value to use for the hccaProtTrigger field. + * @param[in] ac3prottrigger - The value to use for the ac3ProtTrigger field. + * @param[in] ac2prottrigger - The value to use for the ac2ProtTrigger field. + * @param[in] ac1prottrigger - The value to use for the ac1ProtTrigger field. + * @param[in] ac0prottrigger - The value to use for the ac0ProtTrigger field. + */ +__INLINE void nxmac_tx_rx_int_status_pack(uint8_t bcntxbuftrigger, uint8_t ac3txbuftrigger, uint8_t ac2txbuftrigger, uint8_t ac1txbuftrigger, uint8_t ac0txbuftrigger, uint8_t ac3bwdroptrigger, uint8_t ac2bwdroptrigger, uint8_t ac1bwdroptrigger, uint8_t ac0bwdroptrigger, uint8_t counterrxtrigger, uint8_t barxtrigger, uint8_t timerrxtrigger, uint8_t rxtrigger, uint8_t timertxtrigger, uint8_t txopcomplete, uint8_t rdtxtrigger, uint8_t hccatxtrigger, uint8_t bcntxtrigger, uint8_t ac3txtrigger, uint8_t ac2txtrigger, uint8_t ac1txtrigger, uint8_t ac0txtrigger, uint8_t rdprottrigger, uint8_t hccaprottrigger, uint8_t ac3prottrigger, uint8_t ac2prottrigger, uint8_t ac1prottrigger, uint8_t ac0prottrigger) +{ + ASSERT_ERR((((uint32_t)bcntxbuftrigger << 28) & ~((uint32_t)0x10000000)) == 0); + ASSERT_ERR((((uint32_t)ac3txbuftrigger << 27) & ~((uint32_t)0x08000000)) == 0); + ASSERT_ERR((((uint32_t)ac2txbuftrigger << 26) & ~((uint32_t)0x04000000)) == 0); + ASSERT_ERR((((uint32_t)ac1txbuftrigger << 25) & ~((uint32_t)0x02000000)) == 0); + ASSERT_ERR((((uint32_t)ac0txbuftrigger << 24) & ~((uint32_t)0x01000000)) == 0); + ASSERT_ERR((((uint32_t)ac3bwdroptrigger << 23) & ~((uint32_t)0x00800000)) == 0); + ASSERT_ERR((((uint32_t)ac2bwdroptrigger << 22) & ~((uint32_t)0x00400000)) == 0); + ASSERT_ERR((((uint32_t)ac1bwdroptrigger << 21) & ~((uint32_t)0x00200000)) == 0); + ASSERT_ERR((((uint32_t)ac0bwdroptrigger << 20) & ~((uint32_t)0x00100000)) == 0); + ASSERT_ERR((((uint32_t)counterrxtrigger << 19) & ~((uint32_t)0x00080000)) == 0); + ASSERT_ERR((((uint32_t)barxtrigger << 18) & ~((uint32_t)0x00040000)) == 0); + ASSERT_ERR((((uint32_t)timerrxtrigger << 17) & ~((uint32_t)0x00020000)) == 0); + ASSERT_ERR((((uint32_t)rxtrigger << 16) & ~((uint32_t)0x00010000)) == 0); + ASSERT_ERR((((uint32_t)timertxtrigger << 14) & ~((uint32_t)0x00004000)) == 0); + ASSERT_ERR((((uint32_t)txopcomplete << 13) & ~((uint32_t)0x00002000)) == 0); + ASSERT_ERR((((uint32_t)rdtxtrigger << 12) & ~((uint32_t)0x00001000)) == 0); + ASSERT_ERR((((uint32_t)hccatxtrigger << 11) & ~((uint32_t)0x00000800)) == 0); + ASSERT_ERR((((uint32_t)bcntxtrigger << 10) & ~((uint32_t)0x00000400)) == 0); + ASSERT_ERR((((uint32_t)ac3txtrigger << 9) & ~((uint32_t)0x00000200)) == 0); + ASSERT_ERR((((uint32_t)ac2txtrigger << 8) & ~((uint32_t)0x00000100)) == 0); + ASSERT_ERR((((uint32_t)ac1txtrigger << 7) & ~((uint32_t)0x00000080)) == 0); + ASSERT_ERR((((uint32_t)ac0txtrigger << 6) & ~((uint32_t)0x00000040)) == 0); + ASSERT_ERR((((uint32_t)rdprottrigger << 5) & ~((uint32_t)0x00000020)) == 0); + ASSERT_ERR((((uint32_t)hccaprottrigger << 4) & ~((uint32_t)0x00000010)) == 0); + ASSERT_ERR((((uint32_t)ac3prottrigger << 3) & ~((uint32_t)0x00000008)) == 0); + ASSERT_ERR((((uint32_t)ac2prottrigger << 2) & ~((uint32_t)0x00000004)) == 0); + ASSERT_ERR((((uint32_t)ac1prottrigger << 1) & ~((uint32_t)0x00000002)) == 0); + ASSERT_ERR((((uint32_t)ac0prottrigger << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_STATUS_ADDR, ((uint32_t)bcntxbuftrigger << 28) | ((uint32_t)ac3txbuftrigger << 27) | ((uint32_t)ac2txbuftrigger << 26) | ((uint32_t)ac1txbuftrigger << 25) | ((uint32_t)ac0txbuftrigger << 24) | ((uint32_t)ac3bwdroptrigger << 23) | ((uint32_t)ac2bwdroptrigger << 22) | ((uint32_t)ac1bwdroptrigger << 21) | ((uint32_t)ac0bwdroptrigger << 20) | ((uint32_t)counterrxtrigger << 19) | ((uint32_t)barxtrigger << 18) | ((uint32_t)timerrxtrigger << 17) | ((uint32_t)rxtrigger << 16) | ((uint32_t)timertxtrigger << 14) | ((uint32_t)txopcomplete << 13) | ((uint32_t)rdtxtrigger << 12) | ((uint32_t)hccatxtrigger << 11) | ((uint32_t)bcntxtrigger << 10) | ((uint32_t)ac3txtrigger << 9) | ((uint32_t)ac2txtrigger << 8) | ((uint32_t)ac1txtrigger << 7) | ((uint32_t)ac0txtrigger << 6) | ((uint32_t)rdprottrigger << 5) | ((uint32_t)hccaprottrigger << 4) | ((uint32_t)ac3prottrigger << 3) | ((uint32_t)ac2prottrigger << 2) | ((uint32_t)ac1prottrigger << 1) | ((uint32_t)ac0prottrigger << 0)); +} + +/** + * @brief Unpacks TX_RX_INT_STATUS's fields from current value of the TX_RX_INT_STATUS register. + * + * Reads the TX_RX_INT_STATUS register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] bcntxbuftrigger - Will be populated with the current value of this field from the register. + * @param[out] ac3txbuftrigger - Will be populated with the current value of this field from the register. + * @param[out] ac2txbuftrigger - Will be populated with the current value of this field from the register. + * @param[out] ac1txbuftrigger - Will be populated with the current value of this field from the register. + * @param[out] ac0txbuftrigger - Will be populated with the current value of this field from the register. + * @param[out] ac3bwdroptrigger - Will be populated with the current value of this field from the register. + * @param[out] ac2bwdroptrigger - Will be populated with the current value of this field from the register. + * @param[out] ac1bwdroptrigger - Will be populated with the current value of this field from the register. + * @param[out] ac0bwdroptrigger - Will be populated with the current value of this field from the register. + * @param[out] counterrxtrigger - Will be populated with the current value of this field from the register. + * @param[out] barxtrigger - Will be populated with the current value of this field from the register. + * @param[out] timerrxtrigger - Will be populated with the current value of this field from the register. + * @param[out] rxtrigger - Will be populated with the current value of this field from the register. + * @param[out] secusertxtrigger - Will be populated with the current value of this field from the register. + * @param[out] timertxtrigger - Will be populated with the current value of this field from the register. + * @param[out] txopcomplete - Will be populated with the current value of this field from the register. + * @param[out] rdtxtrigger - Will be populated with the current value of this field from the register. + * @param[out] hccatxtrigger - Will be populated with the current value of this field from the register. + * @param[out] bcntxtrigger - Will be populated with the current value of this field from the register. + * @param[out] ac3txtrigger - Will be populated with the current value of this field from the register. + * @param[out] ac2txtrigger - Will be populated with the current value of this field from the register. + * @param[out] ac1txtrigger - Will be populated with the current value of this field from the register. + * @param[out] ac0txtrigger - Will be populated with the current value of this field from the register. + * @param[out] rdprottrigger - Will be populated with the current value of this field from the register. + * @param[out] hccaprottrigger - Will be populated with the current value of this field from the register. + * @param[out] ac3prottrigger - Will be populated with the current value of this field from the register. + * @param[out] ac2prottrigger - Will be populated with the current value of this field from the register. + * @param[out] ac1prottrigger - Will be populated with the current value of this field from the register. + * @param[out] ac0prottrigger - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_tx_rx_int_status_unpack(uint8_t *bcntxbuftrigger, uint8_t *ac3txbuftrigger, uint8_t *ac2txbuftrigger, uint8_t *ac1txbuftrigger, uint8_t *ac0txbuftrigger, uint8_t *ac3bwdroptrigger, uint8_t *ac2bwdroptrigger, uint8_t *ac1bwdroptrigger, uint8_t *ac0bwdroptrigger, uint8_t *counterrxtrigger, uint8_t *barxtrigger, uint8_t *timerrxtrigger, uint8_t *rxtrigger, uint8_t *secusertxtrigger, uint8_t *timertxtrigger, uint8_t *txopcomplete, uint8_t *rdtxtrigger, uint8_t *hccatxtrigger, uint8_t *bcntxtrigger, uint8_t *ac3txtrigger, uint8_t *ac2txtrigger, uint8_t *ac1txtrigger, uint8_t *ac0txtrigger, uint8_t *rdprottrigger, uint8_t *hccaprottrigger, uint8_t *ac3prottrigger, uint8_t *ac2prottrigger, uint8_t *ac1prottrigger, uint8_t *ac0prottrigger) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_STATUS_ADDR); + + *bcntxbuftrigger = (localVal & ((uint32_t)0x10000000)) >> 28; + *ac3txbuftrigger = (localVal & ((uint32_t)0x08000000)) >> 27; + *ac2txbuftrigger = (localVal & ((uint32_t)0x04000000)) >> 26; + *ac1txbuftrigger = (localVal & ((uint32_t)0x02000000)) >> 25; + *ac0txbuftrigger = (localVal & ((uint32_t)0x01000000)) >> 24; + *ac3bwdroptrigger = (localVal & ((uint32_t)0x00800000)) >> 23; + *ac2bwdroptrigger = (localVal & ((uint32_t)0x00400000)) >> 22; + *ac1bwdroptrigger = (localVal & ((uint32_t)0x00200000)) >> 21; + *ac0bwdroptrigger = (localVal & ((uint32_t)0x00100000)) >> 20; + *counterrxtrigger = (localVal & ((uint32_t)0x00080000)) >> 19; + *barxtrigger = (localVal & ((uint32_t)0x00040000)) >> 18; + *timerrxtrigger = (localVal & ((uint32_t)0x00020000)) >> 17; + *rxtrigger = (localVal & ((uint32_t)0x00010000)) >> 16; + *secusertxtrigger = (localVal & ((uint32_t)0x00008000)) >> 15; + *timertxtrigger = (localVal & ((uint32_t)0x00004000)) >> 14; + *txopcomplete = (localVal & ((uint32_t)0x00002000)) >> 13; + *rdtxtrigger = (localVal & ((uint32_t)0x00001000)) >> 12; + *hccatxtrigger = (localVal & ((uint32_t)0x00000800)) >> 11; + *bcntxtrigger = (localVal & ((uint32_t)0x00000400)) >> 10; + *ac3txtrigger = (localVal & ((uint32_t)0x00000200)) >> 9; + *ac2txtrigger = (localVal & ((uint32_t)0x00000100)) >> 8; + *ac1txtrigger = (localVal & ((uint32_t)0x00000080)) >> 7; + *ac0txtrigger = (localVal & ((uint32_t)0x00000040)) >> 6; + *rdprottrigger = (localVal & ((uint32_t)0x00000020)) >> 5; + *hccaprottrigger = (localVal & ((uint32_t)0x00000010)) >> 4; + *ac3prottrigger = (localVal & ((uint32_t)0x00000008)) >> 3; + *ac2prottrigger = (localVal & ((uint32_t)0x00000004)) >> 2; + *ac1prottrigger = (localVal & ((uint32_t)0x00000002)) >> 1; + *ac0prottrigger = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +/** + * @brief Returns the current value of the bcnTxBufTrigger field in the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read and the bcnTxBufTrigger field's value will be returned. + * + * @return The current value of the bcnTxBufTrigger field in the TX_RX_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_bcn_tx_buf_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x10000000)) >> 28); +} + +/** + * @brief Sets the bcnTxBufTrigger field of the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] bcntxbuftrigger - The value to set the field to. + */ +__INLINE void nxmac_status_bcn_tx_buf_trigger_setf(uint8_t bcntxbuftrigger) +{ + ASSERT_ERR((((uint32_t)bcntxbuftrigger << 28) & ~((uint32_t)0x10000000)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_STATUS_ADDR, (uint32_t)bcntxbuftrigger << 28); +} + +/** + * @brief Returns the current value of the ac3TxBufTrigger field in the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read and the ac3TxBufTrigger field's value will be returned. + * + * @return The current value of the ac3TxBufTrigger field in the TX_RX_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_ac_3_tx_buf_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x08000000)) >> 27); +} + +/** + * @brief Sets the ac3TxBufTrigger field of the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] ac3txbuftrigger - The value to set the field to. + */ +__INLINE void nxmac_status_ac_3_tx_buf_trigger_setf(uint8_t ac3txbuftrigger) +{ + ASSERT_ERR((((uint32_t)ac3txbuftrigger << 27) & ~((uint32_t)0x08000000)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_STATUS_ADDR, (uint32_t)ac3txbuftrigger << 27); +} + +/** + * @brief Returns the current value of the ac2TxBufTrigger field in the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read and the ac2TxBufTrigger field's value will be returned. + * + * @return The current value of the ac2TxBufTrigger field in the TX_RX_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_ac_2_tx_buf_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x04000000)) >> 26); +} + +/** + * @brief Sets the ac2TxBufTrigger field of the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] ac2txbuftrigger - The value to set the field to. + */ +__INLINE void nxmac_status_ac_2_tx_buf_trigger_setf(uint8_t ac2txbuftrigger) +{ + ASSERT_ERR((((uint32_t)ac2txbuftrigger << 26) & ~((uint32_t)0x04000000)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_STATUS_ADDR, (uint32_t)ac2txbuftrigger << 26); +} + +/** + * @brief Returns the current value of the ac1TxBufTrigger field in the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read and the ac1TxBufTrigger field's value will be returned. + * + * @return The current value of the ac1TxBufTrigger field in the TX_RX_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_ac_1_tx_buf_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x02000000)) >> 25); +} + +/** + * @brief Sets the ac1TxBufTrigger field of the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] ac1txbuftrigger - The value to set the field to. + */ +__INLINE void nxmac_status_ac_1_tx_buf_trigger_setf(uint8_t ac1txbuftrigger) +{ + ASSERT_ERR((((uint32_t)ac1txbuftrigger << 25) & ~((uint32_t)0x02000000)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_STATUS_ADDR, (uint32_t)ac1txbuftrigger << 25); +} + +/** + * @brief Returns the current value of the ac0TxBufTrigger field in the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read and the ac0TxBufTrigger field's value will be returned. + * + * @return The current value of the ac0TxBufTrigger field in the TX_RX_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_ac_0_tx_buf_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x01000000)) >> 24); +} + +/** + * @brief Sets the ac0TxBufTrigger field of the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] ac0txbuftrigger - The value to set the field to. + */ +__INLINE void nxmac_status_ac_0_tx_buf_trigger_setf(uint8_t ac0txbuftrigger) +{ + ASSERT_ERR((((uint32_t)ac0txbuftrigger << 24) & ~((uint32_t)0x01000000)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_STATUS_ADDR, (uint32_t)ac0txbuftrigger << 24); +} + +/** + * @brief Returns the current value of the ac3BWDropTrigger field in the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read and the ac3BWDropTrigger field's value will be returned. + * + * @return The current value of the ac3BWDropTrigger field in the TX_RX_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_ac_3bw_drop_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00800000)) >> 23); +} + +/** + * @brief Sets the ac3BWDropTrigger field of the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] ac3bwdroptrigger - The value to set the field to. + */ +__INLINE void nxmac_status_ac_3bw_drop_trigger_setf(uint8_t ac3bwdroptrigger) +{ + ASSERT_ERR((((uint32_t)ac3bwdroptrigger << 23) & ~((uint32_t)0x00800000)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_STATUS_ADDR, (uint32_t)ac3bwdroptrigger << 23); +} + +/** + * @brief Returns the current value of the ac2BWDropTrigger field in the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read and the ac2BWDropTrigger field's value will be returned. + * + * @return The current value of the ac2BWDropTrigger field in the TX_RX_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_ac_2bw_drop_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00400000)) >> 22); +} + +/** + * @brief Sets the ac2BWDropTrigger field of the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] ac2bwdroptrigger - The value to set the field to. + */ +__INLINE void nxmac_status_ac_2bw_drop_trigger_setf(uint8_t ac2bwdroptrigger) +{ + ASSERT_ERR((((uint32_t)ac2bwdroptrigger << 22) & ~((uint32_t)0x00400000)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_STATUS_ADDR, (uint32_t)ac2bwdroptrigger << 22); +} + +/** + * @brief Returns the current value of the ac1BWDropTrigger field in the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read and the ac1BWDropTrigger field's value will be returned. + * + * @return The current value of the ac1BWDropTrigger field in the TX_RX_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_ac_1bw_drop_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00200000)) >> 21); +} + +/** + * @brief Sets the ac1BWDropTrigger field of the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] ac1bwdroptrigger - The value to set the field to. + */ +__INLINE void nxmac_status_ac_1bw_drop_trigger_setf(uint8_t ac1bwdroptrigger) +{ + ASSERT_ERR((((uint32_t)ac1bwdroptrigger << 21) & ~((uint32_t)0x00200000)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_STATUS_ADDR, (uint32_t)ac1bwdroptrigger << 21); +} + +/** + * @brief Returns the current value of the ac0BWDropTrigger field in the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read and the ac0BWDropTrigger field's value will be returned. + * + * @return The current value of the ac0BWDropTrigger field in the TX_RX_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_ac_0bw_drop_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00100000)) >> 20); +} + +/** + * @brief Sets the ac0BWDropTrigger field of the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] ac0bwdroptrigger - The value to set the field to. + */ +__INLINE void nxmac_status_ac_0bw_drop_trigger_setf(uint8_t ac0bwdroptrigger) +{ + ASSERT_ERR((((uint32_t)ac0bwdroptrigger << 20) & ~((uint32_t)0x00100000)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_STATUS_ADDR, (uint32_t)ac0bwdroptrigger << 20); +} + +/** + * @brief Returns the current value of the counterRxTrigger field in the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read and the counterRxTrigger field's value will be returned. + * + * @return The current value of the counterRxTrigger field in the TX_RX_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_counter_rx_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00080000)) >> 19); +} + +/** + * @brief Sets the counterRxTrigger field of the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] counterrxtrigger - The value to set the field to. + */ +__INLINE void nxmac_status_counter_rx_trigger_setf(uint8_t counterrxtrigger) +{ + ASSERT_ERR((((uint32_t)counterrxtrigger << 19) & ~((uint32_t)0x00080000)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_STATUS_ADDR, (uint32_t)counterrxtrigger << 19); +} + +/** + * @brief Returns the current value of the baRxTrigger field in the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read and the baRxTrigger field's value will be returned. + * + * @return The current value of the baRxTrigger field in the TX_RX_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_ba_rx_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00040000)) >> 18); +} + +/** + * @brief Sets the baRxTrigger field of the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] barxtrigger - The value to set the field to. + */ +__INLINE void nxmac_status_ba_rx_trigger_setf(uint8_t barxtrigger) +{ + ASSERT_ERR((((uint32_t)barxtrigger << 18) & ~((uint32_t)0x00040000)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_STATUS_ADDR, (uint32_t)barxtrigger << 18); +} + +/** + * @brief Returns the current value of the timerRxTrigger field in the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read and the timerRxTrigger field's value will be returned. + * + * @return The current value of the timerRxTrigger field in the TX_RX_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_timer_rx_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00020000)) >> 17); +} + +/** + * @brief Sets the timerRxTrigger field of the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] timerrxtrigger - The value to set the field to. + */ +__INLINE void nxmac_status_timer_rx_trigger_setf(uint8_t timerrxtrigger) +{ + ASSERT_ERR((((uint32_t)timerrxtrigger << 17) & ~((uint32_t)0x00020000)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_STATUS_ADDR, (uint32_t)timerrxtrigger << 17); +} + +/** + * @brief Returns the current value of the rxTrigger field in the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read and the rxTrigger field's value will be returned. + * + * @return The current value of the rxTrigger field in the TX_RX_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_rx_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00010000)) >> 16); +} + +/** + * @brief Sets the rxTrigger field of the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] rxtrigger - The value to set the field to. + */ +__INLINE void nxmac_status_rx_trigger_setf(uint8_t rxtrigger) +{ + ASSERT_ERR((((uint32_t)rxtrigger << 16) & ~((uint32_t)0x00010000)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_STATUS_ADDR, (uint32_t)rxtrigger << 16); +} + +/** + * @brief Returns the current value of the secUserTxTrigger field in the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read and the secUserTxTrigger field's value will be returned. + * + * @return The current value of the secUserTxTrigger field in the TX_RX_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_sec_user_tx_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00008000)) >> 15); +} + +/** + * @brief Returns the current value of the timerTxTrigger field in the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read and the timerTxTrigger field's value will be returned. + * + * @return The current value of the timerTxTrigger field in the TX_RX_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_timer_tx_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00004000)) >> 14); +} + +/** + * @brief Sets the timerTxTrigger field of the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] timertxtrigger - The value to set the field to. + */ +__INLINE void nxmac_status_timer_tx_trigger_setf(uint8_t timertxtrigger) +{ + ASSERT_ERR((((uint32_t)timertxtrigger << 14) & ~((uint32_t)0x00004000)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_STATUS_ADDR, (uint32_t)timertxtrigger << 14); +} + +/** + * @brief Returns the current value of the txopComplete field in the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read and the txopComplete field's value will be returned. + * + * @return The current value of the txopComplete field in the TX_RX_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_txop_complete_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00002000)) >> 13); +} + +/** + * @brief Sets the txopComplete field of the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] txopcomplete - The value to set the field to. + */ +__INLINE void nxmac_status_txop_complete_setf(uint8_t txopcomplete) +{ + ASSERT_ERR((((uint32_t)txopcomplete << 13) & ~((uint32_t)0x00002000)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_STATUS_ADDR, (uint32_t)txopcomplete << 13); +} + +/** + * @brief Returns the current value of the rdTxTrigger field in the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read and the rdTxTrigger field's value will be returned. + * + * @return The current value of the rdTxTrigger field in the TX_RX_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_rd_tx_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00001000)) >> 12); +} + +/** + * @brief Sets the rdTxTrigger field of the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] rdtxtrigger - The value to set the field to. + */ +__INLINE void nxmac_status_rd_tx_trigger_setf(uint8_t rdtxtrigger) +{ + ASSERT_ERR((((uint32_t)rdtxtrigger << 12) & ~((uint32_t)0x00001000)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_STATUS_ADDR, (uint32_t)rdtxtrigger << 12); +} + +/** + * @brief Returns the current value of the hccaTxTrigger field in the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read and the hccaTxTrigger field's value will be returned. + * + * @return The current value of the hccaTxTrigger field in the TX_RX_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_hcca_tx_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00000800)) >> 11); +} + +/** + * @brief Sets the hccaTxTrigger field of the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] hccatxtrigger - The value to set the field to. + */ +__INLINE void nxmac_status_hcca_tx_trigger_setf(uint8_t hccatxtrigger) +{ + ASSERT_ERR((((uint32_t)hccatxtrigger << 11) & ~((uint32_t)0x00000800)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_STATUS_ADDR, (uint32_t)hccatxtrigger << 11); +} + +/** + * @brief Returns the current value of the bcnTxTrigger field in the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read and the bcnTxTrigger field's value will be returned. + * + * @return The current value of the bcnTxTrigger field in the TX_RX_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_bcn_tx_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00000400)) >> 10); +} + +/** + * @brief Sets the bcnTxTrigger field of the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] bcntxtrigger - The value to set the field to. + */ +__INLINE void nxmac_status_bcn_tx_trigger_setf(uint8_t bcntxtrigger) +{ + ASSERT_ERR((((uint32_t)bcntxtrigger << 10) & ~((uint32_t)0x00000400)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_STATUS_ADDR, (uint32_t)bcntxtrigger << 10); +} + +/** + * @brief Returns the current value of the ac3TxTrigger field in the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read and the ac3TxTrigger field's value will be returned. + * + * @return The current value of the ac3TxTrigger field in the TX_RX_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_ac_3_tx_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00000200)) >> 9); +} + +/** + * @brief Sets the ac3TxTrigger field of the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] ac3txtrigger - The value to set the field to. + */ +__INLINE void nxmac_status_ac_3_tx_trigger_setf(uint8_t ac3txtrigger) +{ + ASSERT_ERR((((uint32_t)ac3txtrigger << 9) & ~((uint32_t)0x00000200)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_STATUS_ADDR, (uint32_t)ac3txtrigger << 9); +} + +/** + * @brief Returns the current value of the ac2TxTrigger field in the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read and the ac2TxTrigger field's value will be returned. + * + * @return The current value of the ac2TxTrigger field in the TX_RX_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_ac_2_tx_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00000100)) >> 8); +} + +/** + * @brief Sets the ac2TxTrigger field of the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] ac2txtrigger - The value to set the field to. + */ +__INLINE void nxmac_status_ac_2_tx_trigger_setf(uint8_t ac2txtrigger) +{ + ASSERT_ERR((((uint32_t)ac2txtrigger << 8) & ~((uint32_t)0x00000100)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_STATUS_ADDR, (uint32_t)ac2txtrigger << 8); +} + +/** + * @brief Returns the current value of the ac1TxTrigger field in the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read and the ac1TxTrigger field's value will be returned. + * + * @return The current value of the ac1TxTrigger field in the TX_RX_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_ac_1_tx_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00000080)) >> 7); +} + +/** + * @brief Sets the ac1TxTrigger field of the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] ac1txtrigger - The value to set the field to. + */ +__INLINE void nxmac_status_ac_1_tx_trigger_setf(uint8_t ac1txtrigger) +{ + ASSERT_ERR((((uint32_t)ac1txtrigger << 7) & ~((uint32_t)0x00000080)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_STATUS_ADDR, (uint32_t)ac1txtrigger << 7); +} + +/** + * @brief Returns the current value of the ac0TxTrigger field in the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read and the ac0TxTrigger field's value will be returned. + * + * @return The current value of the ac0TxTrigger field in the TX_RX_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_ac_0_tx_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00000040)) >> 6); +} + +/** + * @brief Sets the ac0TxTrigger field of the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] ac0txtrigger - The value to set the field to. + */ +__INLINE void nxmac_status_ac_0_tx_trigger_setf(uint8_t ac0txtrigger) +{ + ASSERT_ERR((((uint32_t)ac0txtrigger << 6) & ~((uint32_t)0x00000040)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_STATUS_ADDR, (uint32_t)ac0txtrigger << 6); +} + +/** + * @brief Returns the current value of the rdProtTrigger field in the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read and the rdProtTrigger field's value will be returned. + * + * @return The current value of the rdProtTrigger field in the TX_RX_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_rd_prot_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +/** + * @brief Sets the rdProtTrigger field of the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] rdprottrigger - The value to set the field to. + */ +__INLINE void nxmac_status_rd_prot_trigger_setf(uint8_t rdprottrigger) +{ + ASSERT_ERR((((uint32_t)rdprottrigger << 5) & ~((uint32_t)0x00000020)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_STATUS_ADDR, (uint32_t)rdprottrigger << 5); +} + +/** + * @brief Returns the current value of the hccaProtTrigger field in the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read and the hccaProtTrigger field's value will be returned. + * + * @return The current value of the hccaProtTrigger field in the TX_RX_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_hcca_prot_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +/** + * @brief Sets the hccaProtTrigger field of the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] hccaprottrigger - The value to set the field to. + */ +__INLINE void nxmac_status_hcca_prot_trigger_setf(uint8_t hccaprottrigger) +{ + ASSERT_ERR((((uint32_t)hccaprottrigger << 4) & ~((uint32_t)0x00000010)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_STATUS_ADDR, (uint32_t)hccaprottrigger << 4); +} + +/** + * @brief Returns the current value of the ac3ProtTrigger field in the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read and the ac3ProtTrigger field's value will be returned. + * + * @return The current value of the ac3ProtTrigger field in the TX_RX_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_ac_3_prot_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +/** + * @brief Sets the ac3ProtTrigger field of the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] ac3prottrigger - The value to set the field to. + */ +__INLINE void nxmac_status_ac_3_prot_trigger_setf(uint8_t ac3prottrigger) +{ + ASSERT_ERR((((uint32_t)ac3prottrigger << 3) & ~((uint32_t)0x00000008)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_STATUS_ADDR, (uint32_t)ac3prottrigger << 3); +} + +/** + * @brief Returns the current value of the ac2ProtTrigger field in the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read and the ac2ProtTrigger field's value will be returned. + * + * @return The current value of the ac2ProtTrigger field in the TX_RX_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_ac_2_prot_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +/** + * @brief Sets the ac2ProtTrigger field of the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] ac2prottrigger - The value to set the field to. + */ +__INLINE void nxmac_status_ac_2_prot_trigger_setf(uint8_t ac2prottrigger) +{ + ASSERT_ERR((((uint32_t)ac2prottrigger << 2) & ~((uint32_t)0x00000004)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_STATUS_ADDR, (uint32_t)ac2prottrigger << 2); +} + +/** + * @brief Returns the current value of the ac1ProtTrigger field in the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read and the ac1ProtTrigger field's value will be returned. + * + * @return The current value of the ac1ProtTrigger field in the TX_RX_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_ac_1_prot_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +/** + * @brief Sets the ac1ProtTrigger field of the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] ac1prottrigger - The value to set the field to. + */ +__INLINE void nxmac_status_ac_1_prot_trigger_setf(uint8_t ac1prottrigger) +{ + ASSERT_ERR((((uint32_t)ac1prottrigger << 1) & ~((uint32_t)0x00000002)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_STATUS_ADDR, (uint32_t)ac1prottrigger << 1); +} + +/** + * @brief Returns the current value of the ac0ProtTrigger field in the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read and the ac0ProtTrigger field's value will be returned. + * + * @return The current value of the ac0ProtTrigger field in the TX_RX_INT_STATUS register. + */ +__INLINE uint8_t nxmac_status_ac_0_prot_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_STATUS_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/** + * @brief Sets the ac0ProtTrigger field of the TX_RX_INT_STATUS register. + * + * The TX_RX_INT_STATUS register will be read, modified to contain the new field value, and written. + * + * @param[in] ac0prottrigger - The value to set the field to. + */ +__INLINE void nxmac_status_ac_0_prot_trigger_setf(uint8_t ac0prottrigger) +{ + ASSERT_ERR((((uint32_t)ac0prottrigger << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_STATUS_ADDR, (uint32_t)ac0prottrigger << 0); +} + +/// @} + +/** + * @name TX_RX_INT_ACK register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     28      bcnTxBufTrigger   0
+ *     27      ac3TxBufTrigger   0
+ *     26      ac2TxBufTrigger   0
+ *     25      ac1TxBufTrigger   0
+ *     24      ac0TxBufTrigger   0
+ *     23     ac3BWDropTrigger   0
+ *     22     ac2BWDropTrigger   0
+ *     21     ac1BWDropTrigger   0
+ *     20     ac0BWDropTrigger   0
+ *     19     counterRxTrigger   0
+ *     18          baRxTrigger   0
+ *     17       timerRxTrigger   0
+ *     16            rxTrigger   0
+ *     14       timerTxTrigger   0
+ *     13         txopComplete   0
+ *     12          rdTxTrigger   0
+ *     11        hccaTxTrigger   0
+ *     10         bcnTxTrigger   0
+ *     09         ac3TxTrigger   0
+ *     08         ac2TxTrigger   0
+ *     07         ac1TxTrigger   0
+ *     06         ac0TxTrigger   0
+ *     05        rdProtTrigger   0
+ *     04      hccaProtTrigger   0
+ *     03       ac3ProtTrigger   0
+ *     02       ac2ProtTrigger   0
+ *     01       ac1ProtTrigger   0
+ *     00       ac0ProtTrigger   0
+ * 
+ * + * @{ + */ + +/// Address of the TX_RX_INT_ACK register +#define NXMAC_TX_RX_INT_ACK_ADDR 0xC000807C +/// Offset of the TX_RX_INT_ACK register from the base address +#define NXMAC_TX_RX_INT_ACK_OFFSET 0x0000007C +/// Index of the TX_RX_INT_ACK register +#define NXMAC_TX_RX_INT_ACK_INDEX 0x0000001F +/// Reset value of the TX_RX_INT_ACK register +#define NXMAC_TX_RX_INT_ACK_RESET 0x00000000 + +/** + * @brief Sets the TX_RX_INT_ACK register to a value. + * The TX_RX_INT_ACK register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_tx_rx_int_ack_clear(uint32_t value) +{ + REG_PL_WR(NXMAC_TX_RX_INT_ACK_ADDR, value); +} + +// fields defined in symmetrical set/clear register +/** + * @brief Constructs a value for the TX_RX_INT_ACK register given values for its fields + * and writes the value to the register. + * + * @param[in] bcntxbuftrigger - The value to use for the bcnTxBufTrigger field. + * @param[in] ac3txbuftrigger - The value to use for the ac3TxBufTrigger field. + * @param[in] ac2txbuftrigger - The value to use for the ac2TxBufTrigger field. + * @param[in] ac1txbuftrigger - The value to use for the ac1TxBufTrigger field. + * @param[in] ac0txbuftrigger - The value to use for the ac0TxBufTrigger field. + * @param[in] ac3bwdroptrigger - The value to use for the ac3BWDropTrigger field. + * @param[in] ac2bwdroptrigger - The value to use for the ac2BWDropTrigger field. + * @param[in] ac1bwdroptrigger - The value to use for the ac1BWDropTrigger field. + * @param[in] ac0bwdroptrigger - The value to use for the ac0BWDropTrigger field. + * @param[in] counterrxtrigger - The value to use for the counterRxTrigger field. + * @param[in] barxtrigger - The value to use for the baRxTrigger field. + * @param[in] timerrxtrigger - The value to use for the timerRxTrigger field. + * @param[in] rxtrigger - The value to use for the rxTrigger field. + * @param[in] timertxtrigger - The value to use for the timerTxTrigger field. + * @param[in] txopcomplete - The value to use for the txopComplete field. + * @param[in] rdtxtrigger - The value to use for the rdTxTrigger field. + * @param[in] hccatxtrigger - The value to use for the hccaTxTrigger field. + * @param[in] bcntxtrigger - The value to use for the bcnTxTrigger field. + * @param[in] ac3txtrigger - The value to use for the ac3TxTrigger field. + * @param[in] ac2txtrigger - The value to use for the ac2TxTrigger field. + * @param[in] ac1txtrigger - The value to use for the ac1TxTrigger field. + * @param[in] ac0txtrigger - The value to use for the ac0TxTrigger field. + * @param[in] rdprottrigger - The value to use for the rdProtTrigger field. + * @param[in] hccaprottrigger - The value to use for the hccaProtTrigger field. + * @param[in] ac3prottrigger - The value to use for the ac3ProtTrigger field. + * @param[in] ac2prottrigger - The value to use for the ac2ProtTrigger field. + * @param[in] ac1prottrigger - The value to use for the ac1ProtTrigger field. + * @param[in] ac0prottrigger - The value to use for the ac0ProtTrigger field. + */ +__INLINE void nxmac_tx_rx_int_ack_pack(uint8_t bcntxbuftrigger, uint8_t ac3txbuftrigger, uint8_t ac2txbuftrigger, uint8_t ac1txbuftrigger, uint8_t ac0txbuftrigger, uint8_t ac3bwdroptrigger, uint8_t ac2bwdroptrigger, uint8_t ac1bwdroptrigger, uint8_t ac0bwdroptrigger, uint8_t counterrxtrigger, uint8_t barxtrigger, uint8_t timerrxtrigger, uint8_t rxtrigger, uint8_t timertxtrigger, uint8_t txopcomplete, uint8_t rdtxtrigger, uint8_t hccatxtrigger, uint8_t bcntxtrigger, uint8_t ac3txtrigger, uint8_t ac2txtrigger, uint8_t ac1txtrigger, uint8_t ac0txtrigger, uint8_t rdprottrigger, uint8_t hccaprottrigger, uint8_t ac3prottrigger, uint8_t ac2prottrigger, uint8_t ac1prottrigger, uint8_t ac0prottrigger) +{ + ASSERT_ERR((((uint32_t)bcntxbuftrigger << 28) & ~((uint32_t)0x10000000)) == 0); + ASSERT_ERR((((uint32_t)ac3txbuftrigger << 27) & ~((uint32_t)0x08000000)) == 0); + ASSERT_ERR((((uint32_t)ac2txbuftrigger << 26) & ~((uint32_t)0x04000000)) == 0); + ASSERT_ERR((((uint32_t)ac1txbuftrigger << 25) & ~((uint32_t)0x02000000)) == 0); + ASSERT_ERR((((uint32_t)ac0txbuftrigger << 24) & ~((uint32_t)0x01000000)) == 0); + ASSERT_ERR((((uint32_t)ac3bwdroptrigger << 23) & ~((uint32_t)0x00800000)) == 0); + ASSERT_ERR((((uint32_t)ac2bwdroptrigger << 22) & ~((uint32_t)0x00400000)) == 0); + ASSERT_ERR((((uint32_t)ac1bwdroptrigger << 21) & ~((uint32_t)0x00200000)) == 0); + ASSERT_ERR((((uint32_t)ac0bwdroptrigger << 20) & ~((uint32_t)0x00100000)) == 0); + ASSERT_ERR((((uint32_t)counterrxtrigger << 19) & ~((uint32_t)0x00080000)) == 0); + ASSERT_ERR((((uint32_t)barxtrigger << 18) & ~((uint32_t)0x00040000)) == 0); + ASSERT_ERR((((uint32_t)timerrxtrigger << 17) & ~((uint32_t)0x00020000)) == 0); + ASSERT_ERR((((uint32_t)rxtrigger << 16) & ~((uint32_t)0x00010000)) == 0); + ASSERT_ERR((((uint32_t)timertxtrigger << 14) & ~((uint32_t)0x00004000)) == 0); + ASSERT_ERR((((uint32_t)txopcomplete << 13) & ~((uint32_t)0x00002000)) == 0); + ASSERT_ERR((((uint32_t)rdtxtrigger << 12) & ~((uint32_t)0x00001000)) == 0); + ASSERT_ERR((((uint32_t)hccatxtrigger << 11) & ~((uint32_t)0x00000800)) == 0); + ASSERT_ERR((((uint32_t)bcntxtrigger << 10) & ~((uint32_t)0x00000400)) == 0); + ASSERT_ERR((((uint32_t)ac3txtrigger << 9) & ~((uint32_t)0x00000200)) == 0); + ASSERT_ERR((((uint32_t)ac2txtrigger << 8) & ~((uint32_t)0x00000100)) == 0); + ASSERT_ERR((((uint32_t)ac1txtrigger << 7) & ~((uint32_t)0x00000080)) == 0); + ASSERT_ERR((((uint32_t)ac0txtrigger << 6) & ~((uint32_t)0x00000040)) == 0); + ASSERT_ERR((((uint32_t)rdprottrigger << 5) & ~((uint32_t)0x00000020)) == 0); + ASSERT_ERR((((uint32_t)hccaprottrigger << 4) & ~((uint32_t)0x00000010)) == 0); + ASSERT_ERR((((uint32_t)ac3prottrigger << 3) & ~((uint32_t)0x00000008)) == 0); + ASSERT_ERR((((uint32_t)ac2prottrigger << 2) & ~((uint32_t)0x00000004)) == 0); + ASSERT_ERR((((uint32_t)ac1prottrigger << 1) & ~((uint32_t)0x00000002)) == 0); + ASSERT_ERR((((uint32_t)ac0prottrigger << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ACK_ADDR, ((uint32_t)bcntxbuftrigger << 28) | ((uint32_t)ac3txbuftrigger << 27) | ((uint32_t)ac2txbuftrigger << 26) | ((uint32_t)ac1txbuftrigger << 25) | ((uint32_t)ac0txbuftrigger << 24) | ((uint32_t)ac3bwdroptrigger << 23) | ((uint32_t)ac2bwdroptrigger << 22) | ((uint32_t)ac1bwdroptrigger << 21) | ((uint32_t)ac0bwdroptrigger << 20) | ((uint32_t)counterrxtrigger << 19) | ((uint32_t)barxtrigger << 18) | ((uint32_t)timerrxtrigger << 17) | ((uint32_t)rxtrigger << 16) | ((uint32_t)timertxtrigger << 14) | ((uint32_t)txopcomplete << 13) | ((uint32_t)rdtxtrigger << 12) | ((uint32_t)hccatxtrigger << 11) | ((uint32_t)bcntxtrigger << 10) | ((uint32_t)ac3txtrigger << 9) | ((uint32_t)ac2txtrigger << 8) | ((uint32_t)ac1txtrigger << 7) | ((uint32_t)ac0txtrigger << 6) | ((uint32_t)rdprottrigger << 5) | ((uint32_t)hccaprottrigger << 4) | ((uint32_t)ac3prottrigger << 3) | ((uint32_t)ac2prottrigger << 2) | ((uint32_t)ac1prottrigger << 1) | ((uint32_t)ac0prottrigger << 0)); +} + +/** + * @brief Sets the bcnTxBufTrigger field of the TX_RX_INT_ACK register. + * + * The TX_RX_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] bcntxbuftrigger - The value to set the field to. + */ +__INLINE void nxmac_ack_bcn_tx_buf_trigger_clearf(uint8_t bcntxbuftrigger) +{ + ASSERT_ERR((((uint32_t)bcntxbuftrigger << 28) & ~((uint32_t)0x10000000)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ACK_ADDR, (uint32_t)bcntxbuftrigger << 28); +} + +/** + * @brief Sets the ac3TxBufTrigger field of the TX_RX_INT_ACK register. + * + * The TX_RX_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] ac3txbuftrigger - The value to set the field to. + */ +__INLINE void nxmac_ack_ac_3_tx_buf_trigger_clearf(uint8_t ac3txbuftrigger) +{ + ASSERT_ERR((((uint32_t)ac3txbuftrigger << 27) & ~((uint32_t)0x08000000)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ACK_ADDR, (uint32_t)ac3txbuftrigger << 27); +} + +/** + * @brief Sets the ac2TxBufTrigger field of the TX_RX_INT_ACK register. + * + * The TX_RX_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] ac2txbuftrigger - The value to set the field to. + */ +__INLINE void nxmac_ack_ac_2_tx_buf_trigger_clearf(uint8_t ac2txbuftrigger) +{ + ASSERT_ERR((((uint32_t)ac2txbuftrigger << 26) & ~((uint32_t)0x04000000)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ACK_ADDR, (uint32_t)ac2txbuftrigger << 26); +} + +/** + * @brief Sets the ac1TxBufTrigger field of the TX_RX_INT_ACK register. + * + * The TX_RX_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] ac1txbuftrigger - The value to set the field to. + */ +__INLINE void nxmac_ack_ac_1_tx_buf_trigger_clearf(uint8_t ac1txbuftrigger) +{ + ASSERT_ERR((((uint32_t)ac1txbuftrigger << 25) & ~((uint32_t)0x02000000)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ACK_ADDR, (uint32_t)ac1txbuftrigger << 25); +} + +/** + * @brief Sets the ac0TxBufTrigger field of the TX_RX_INT_ACK register. + * + * The TX_RX_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] ac0txbuftrigger - The value to set the field to. + */ +__INLINE void nxmac_ack_ac_0_tx_buf_trigger_clearf(uint8_t ac0txbuftrigger) +{ + ASSERT_ERR((((uint32_t)ac0txbuftrigger << 24) & ~((uint32_t)0x01000000)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ACK_ADDR, (uint32_t)ac0txbuftrigger << 24); +} + +/** + * @brief Sets the ac3BWDropTrigger field of the TX_RX_INT_ACK register. + * + * The TX_RX_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] ac3bwdroptrigger - The value to set the field to. + */ +__INLINE void nxmac_ack_ac_3bw_drop_trigger_clearf(uint8_t ac3bwdroptrigger) +{ + ASSERT_ERR((((uint32_t)ac3bwdroptrigger << 23) & ~((uint32_t)0x00800000)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ACK_ADDR, (uint32_t)ac3bwdroptrigger << 23); +} + +/** + * @brief Sets the ac2BWDropTrigger field of the TX_RX_INT_ACK register. + * + * The TX_RX_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] ac2bwdroptrigger - The value to set the field to. + */ +__INLINE void nxmac_ack_ac_2bw_drop_trigger_clearf(uint8_t ac2bwdroptrigger) +{ + ASSERT_ERR((((uint32_t)ac2bwdroptrigger << 22) & ~((uint32_t)0x00400000)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ACK_ADDR, (uint32_t)ac2bwdroptrigger << 22); +} + +/** + * @brief Sets the ac1BWDropTrigger field of the TX_RX_INT_ACK register. + * + * The TX_RX_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] ac1bwdroptrigger - The value to set the field to. + */ +__INLINE void nxmac_ack_ac_1bw_drop_trigger_clearf(uint8_t ac1bwdroptrigger) +{ + ASSERT_ERR((((uint32_t)ac1bwdroptrigger << 21) & ~((uint32_t)0x00200000)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ACK_ADDR, (uint32_t)ac1bwdroptrigger << 21); +} + +/** + * @brief Sets the ac0BWDropTrigger field of the TX_RX_INT_ACK register. + * + * The TX_RX_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] ac0bwdroptrigger - The value to set the field to. + */ +__INLINE void nxmac_ack_ac_0bw_drop_trigger_clearf(uint8_t ac0bwdroptrigger) +{ + ASSERT_ERR((((uint32_t)ac0bwdroptrigger << 20) & ~((uint32_t)0x00100000)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ACK_ADDR, (uint32_t)ac0bwdroptrigger << 20); +} + +/** + * @brief Sets the counterRxTrigger field of the TX_RX_INT_ACK register. + * + * The TX_RX_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] counterrxtrigger - The value to set the field to. + */ +__INLINE void nxmac_ack_counter_rx_trigger_clearf(uint8_t counterrxtrigger) +{ + ASSERT_ERR((((uint32_t)counterrxtrigger << 19) & ~((uint32_t)0x00080000)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ACK_ADDR, (uint32_t)counterrxtrigger << 19); +} + +/** + * @brief Sets the baRxTrigger field of the TX_RX_INT_ACK register. + * + * The TX_RX_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] barxtrigger - The value to set the field to. + */ +__INLINE void nxmac_ack_ba_rx_trigger_clearf(uint8_t barxtrigger) +{ + ASSERT_ERR((((uint32_t)barxtrigger << 18) & ~((uint32_t)0x00040000)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ACK_ADDR, (uint32_t)barxtrigger << 18); +} + +/** + * @brief Sets the timerRxTrigger field of the TX_RX_INT_ACK register. + * + * The TX_RX_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] timerrxtrigger - The value to set the field to. + */ +__INLINE void nxmac_ack_timer_rx_trigger_clearf(uint8_t timerrxtrigger) +{ + ASSERT_ERR((((uint32_t)timerrxtrigger << 17) & ~((uint32_t)0x00020000)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ACK_ADDR, (uint32_t)timerrxtrigger << 17); +} + +/** + * @brief Sets the rxTrigger field of the TX_RX_INT_ACK register. + * + * The TX_RX_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] rxtrigger - The value to set the field to. + */ +__INLINE void nxmac_ack_rx_trigger_clearf(uint8_t rxtrigger) +{ + ASSERT_ERR((((uint32_t)rxtrigger << 16) & ~((uint32_t)0x00010000)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ACK_ADDR, (uint32_t)rxtrigger << 16); +} + +/** + * @brief Sets the timerTxTrigger field of the TX_RX_INT_ACK register. + * + * The TX_RX_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] timertxtrigger - The value to set the field to. + */ +__INLINE void nxmac_ack_timer_tx_trigger_clearf(uint8_t timertxtrigger) +{ + ASSERT_ERR((((uint32_t)timertxtrigger << 14) & ~((uint32_t)0x00004000)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ACK_ADDR, (uint32_t)timertxtrigger << 14); +} + +/** + * @brief Sets the txopComplete field of the TX_RX_INT_ACK register. + * + * The TX_RX_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] txopcomplete - The value to set the field to. + */ +__INLINE void nxmac_ack_txop_complete_clearf(uint8_t txopcomplete) +{ + ASSERT_ERR((((uint32_t)txopcomplete << 13) & ~((uint32_t)0x00002000)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ACK_ADDR, (uint32_t)txopcomplete << 13); +} + +/** + * @brief Sets the rdTxTrigger field of the TX_RX_INT_ACK register. + * + * The TX_RX_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] rdtxtrigger - The value to set the field to. + */ +__INLINE void nxmac_ack_rd_tx_trigger_clearf(uint8_t rdtxtrigger) +{ + ASSERT_ERR((((uint32_t)rdtxtrigger << 12) & ~((uint32_t)0x00001000)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ACK_ADDR, (uint32_t)rdtxtrigger << 12); +} + +/** + * @brief Sets the hccaTxTrigger field of the TX_RX_INT_ACK register. + * + * The TX_RX_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] hccatxtrigger - The value to set the field to. + */ +__INLINE void nxmac_ack_hcca_tx_trigger_clearf(uint8_t hccatxtrigger) +{ + ASSERT_ERR((((uint32_t)hccatxtrigger << 11) & ~((uint32_t)0x00000800)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ACK_ADDR, (uint32_t)hccatxtrigger << 11); +} + +/** + * @brief Sets the bcnTxTrigger field of the TX_RX_INT_ACK register. + * + * The TX_RX_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] bcntxtrigger - The value to set the field to. + */ +__INLINE void nxmac_ack_bcn_tx_trigger_clearf(uint8_t bcntxtrigger) +{ + ASSERT_ERR((((uint32_t)bcntxtrigger << 10) & ~((uint32_t)0x00000400)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ACK_ADDR, (uint32_t)bcntxtrigger << 10); +} + +/** + * @brief Sets the ac3TxTrigger field of the TX_RX_INT_ACK register. + * + * The TX_RX_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] ac3txtrigger - The value to set the field to. + */ +__INLINE void nxmac_ack_ac_3_tx_trigger_clearf(uint8_t ac3txtrigger) +{ + ASSERT_ERR((((uint32_t)ac3txtrigger << 9) & ~((uint32_t)0x00000200)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ACK_ADDR, (uint32_t)ac3txtrigger << 9); +} + +/** + * @brief Sets the ac2TxTrigger field of the TX_RX_INT_ACK register. + * + * The TX_RX_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] ac2txtrigger - The value to set the field to. + */ +__INLINE void nxmac_ack_ac_2_tx_trigger_clearf(uint8_t ac2txtrigger) +{ + ASSERT_ERR((((uint32_t)ac2txtrigger << 8) & ~((uint32_t)0x00000100)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ACK_ADDR, (uint32_t)ac2txtrigger << 8); +} + +/** + * @brief Sets the ac1TxTrigger field of the TX_RX_INT_ACK register. + * + * The TX_RX_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] ac1txtrigger - The value to set the field to. + */ +__INLINE void nxmac_ack_ac_1_tx_trigger_clearf(uint8_t ac1txtrigger) +{ + ASSERT_ERR((((uint32_t)ac1txtrigger << 7) & ~((uint32_t)0x00000080)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ACK_ADDR, (uint32_t)ac1txtrigger << 7); +} + +/** + * @brief Sets the ac0TxTrigger field of the TX_RX_INT_ACK register. + * + * The TX_RX_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] ac0txtrigger - The value to set the field to. + */ +__INLINE void nxmac_ack_ac_0_tx_trigger_clearf(uint8_t ac0txtrigger) +{ + ASSERT_ERR((((uint32_t)ac0txtrigger << 6) & ~((uint32_t)0x00000040)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ACK_ADDR, (uint32_t)ac0txtrigger << 6); +} + +/** + * @brief Sets the rdProtTrigger field of the TX_RX_INT_ACK register. + * + * The TX_RX_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] rdprottrigger - The value to set the field to. + */ +__INLINE void nxmac_ack_rd_prot_trigger_clearf(uint8_t rdprottrigger) +{ + ASSERT_ERR((((uint32_t)rdprottrigger << 5) & ~((uint32_t)0x00000020)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ACK_ADDR, (uint32_t)rdprottrigger << 5); +} + +/** + * @brief Sets the hccaProtTrigger field of the TX_RX_INT_ACK register. + * + * The TX_RX_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] hccaprottrigger - The value to set the field to. + */ +__INLINE void nxmac_ack_hcca_prot_trigger_clearf(uint8_t hccaprottrigger) +{ + ASSERT_ERR((((uint32_t)hccaprottrigger << 4) & ~((uint32_t)0x00000010)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ACK_ADDR, (uint32_t)hccaprottrigger << 4); +} + +/** + * @brief Sets the ac3ProtTrigger field of the TX_RX_INT_ACK register. + * + * The TX_RX_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] ac3prottrigger - The value to set the field to. + */ +__INLINE void nxmac_ack_ac_3_prot_trigger_clearf(uint8_t ac3prottrigger) +{ + ASSERT_ERR((((uint32_t)ac3prottrigger << 3) & ~((uint32_t)0x00000008)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ACK_ADDR, (uint32_t)ac3prottrigger << 3); +} + +/** + * @brief Sets the ac2ProtTrigger field of the TX_RX_INT_ACK register. + * + * The TX_RX_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] ac2prottrigger - The value to set the field to. + */ +__INLINE void nxmac_ack_ac_2_prot_trigger_clearf(uint8_t ac2prottrigger) +{ + ASSERT_ERR((((uint32_t)ac2prottrigger << 2) & ~((uint32_t)0x00000004)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ACK_ADDR, (uint32_t)ac2prottrigger << 2); +} + +/** + * @brief Sets the ac1ProtTrigger field of the TX_RX_INT_ACK register. + * + * The TX_RX_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] ac1prottrigger - The value to set the field to. + */ +__INLINE void nxmac_ack_ac_1_prot_trigger_clearf(uint8_t ac1prottrigger) +{ + ASSERT_ERR((((uint32_t)ac1prottrigger << 1) & ~((uint32_t)0x00000002)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ACK_ADDR, (uint32_t)ac1prottrigger << 1); +} + +/** + * @brief Sets the ac0ProtTrigger field of the TX_RX_INT_ACK register. + * + * The TX_RX_INT_ACK register will be read, modified to contain the new field value, and written. + * + * @param[in] ac0prottrigger - The value to set the field to. + */ +__INLINE void nxmac_ack_ac_0_prot_trigger_clearf(uint8_t ac0prottrigger) +{ + ASSERT_ERR((((uint32_t)ac0prottrigger << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ACK_ADDR, (uint32_t)ac0prottrigger << 0); +} + +/// @} + +/** + * @name TX_RX_INT_ENABLE register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31      masterTxRxIntEn   0
+ *     28      bcnTxBufTrigger   0
+ *     27      ac3TxBufTrigger   0
+ *     26      ac2TxBufTrigger   0
+ *     25      ac1TxBufTrigger   0
+ *     24      ac0TxBufTrigger   0
+ *     23     ac3BWDropTrigger   0
+ *     22     ac2BWDropTrigger   0
+ *     21     ac1BWDropTrigger   0
+ *     20     ac0BWDropTrigger   0
+ *     19     counterRxTrigger   0
+ *     18          baRxTrigger   0
+ *     17       timerRxTrigger   0
+ *     16            rxTrigger   0
+ *     15     secUserTxTrigger   0
+ *     14       timerTxTrigger   0
+ *     13         txopComplete   0
+ *     12          rdTxTrigger   0
+ *     11        hccaTxTrigger   0
+ *     10         bcnTxTrigger   0
+ *     09         ac3TxTrigger   0
+ *     08         ac2TxTrigger   0
+ *     07         ac1TxTrigger   0
+ *     06         ac0TxTrigger   0
+ *     05        rdProtTrigger   0
+ *     04      hccaProtTrigger   0
+ *     03       ac3ProtTrigger   0
+ *     02       ac2ProtTrigger   0
+ *     01       ac1ProtTrigger   0
+ *     00       ac0ProtTrigger   0
+ * 
+ * + * @{ + */ + +/// Address of the TX_RX_INT_ENABLE register +#define NXMAC_TX_RX_INT_ENABLE_ADDR 0xC0008080 +/// Offset of the TX_RX_INT_ENABLE register from the base address +#define NXMAC_TX_RX_INT_ENABLE_OFFSET 0x00000080 +/// Index of the TX_RX_INT_ENABLE register +#define NXMAC_TX_RX_INT_ENABLE_INDEX 0x00000020 +/// Reset value of the TX_RX_INT_ENABLE register +#define NXMAC_TX_RX_INT_ENABLE_RESET 0x00000000 + +/** + * @brief Returns the current value of the TX_RX_INT_ENABLE register. + * The TX_RX_INT_ENABLE register will be read and its value returned. + * @return The current value of the TX_RX_INT_ENABLE register. + */ +__INLINE uint32_t nxmac_tx_rx_int_enable_get(void) +{ + return REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR); +} + +/** + * @brief Sets the TX_RX_INT_ENABLE register to a value. + * The TX_RX_INT_ENABLE register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_tx_rx_int_enable_set(uint32_t value) +{ + REG_PL_WR(NXMAC_TX_RX_INT_ENABLE_ADDR, value); +} + +// field definitions +/// MASTER_TX_RX_INT_EN field bit +#define NXMAC_MASTER_TX_RX_INT_EN_BIT ((uint32_t)0x80000000) +/// MASTER_TX_RX_INT_EN field position +#define NXMAC_MASTER_TX_RX_INT_EN_POS 31 +/// BCN_TX_BUF_TRIGGER field bit +#define NXMAC_BCN_TX_BUF_TRIGGER_BIT ((uint32_t)0x10000000) +/// BCN_TX_BUF_TRIGGER field position +#define NXMAC_BCN_TX_BUF_TRIGGER_POS 28 +/// AC_3_TX_BUF_TRIGGER field bit +#define NXMAC_AC_3_TX_BUF_TRIGGER_BIT ((uint32_t)0x08000000) +/// AC_3_TX_BUF_TRIGGER field position +#define NXMAC_AC_3_TX_BUF_TRIGGER_POS 27 +/// AC_2_TX_BUF_TRIGGER field bit +#define NXMAC_AC_2_TX_BUF_TRIGGER_BIT ((uint32_t)0x04000000) +/// AC_2_TX_BUF_TRIGGER field position +#define NXMAC_AC_2_TX_BUF_TRIGGER_POS 26 +/// AC_1_TX_BUF_TRIGGER field bit +#define NXMAC_AC_1_TX_BUF_TRIGGER_BIT ((uint32_t)0x02000000) +/// AC_1_TX_BUF_TRIGGER field position +#define NXMAC_AC_1_TX_BUF_TRIGGER_POS 25 +/// AC_0_TX_BUF_TRIGGER field bit +#define NXMAC_AC_0_TX_BUF_TRIGGER_BIT ((uint32_t)0x01000000) +/// AC_0_TX_BUF_TRIGGER field position +#define NXMAC_AC_0_TX_BUF_TRIGGER_POS 24 +/// AC_3BW_DROP_TRIGGER field bit +#define NXMAC_AC_3BW_DROP_TRIGGER_BIT ((uint32_t)0x00800000) +/// AC_3BW_DROP_TRIGGER field position +#define NXMAC_AC_3BW_DROP_TRIGGER_POS 23 +/// AC_2BW_DROP_TRIGGER field bit +#define NXMAC_AC_2BW_DROP_TRIGGER_BIT ((uint32_t)0x00400000) +/// AC_2BW_DROP_TRIGGER field position +#define NXMAC_AC_2BW_DROP_TRIGGER_POS 22 +/// AC_1BW_DROP_TRIGGER field bit +#define NXMAC_AC_1BW_DROP_TRIGGER_BIT ((uint32_t)0x00200000) +/// AC_1BW_DROP_TRIGGER field position +#define NXMAC_AC_1BW_DROP_TRIGGER_POS 21 +/// AC_0BW_DROP_TRIGGER field bit +#define NXMAC_AC_0BW_DROP_TRIGGER_BIT ((uint32_t)0x00100000) +/// AC_0BW_DROP_TRIGGER field position +#define NXMAC_AC_0BW_DROP_TRIGGER_POS 20 +/// COUNTER_RX_TRIGGER field bit +#define NXMAC_COUNTER_RX_TRIGGER_BIT ((uint32_t)0x00080000) +/// COUNTER_RX_TRIGGER field position +#define NXMAC_COUNTER_RX_TRIGGER_POS 19 +/// BA_RX_TRIGGER field bit +#define NXMAC_BA_RX_TRIGGER_BIT ((uint32_t)0x00040000) +/// BA_RX_TRIGGER field position +#define NXMAC_BA_RX_TRIGGER_POS 18 +/// TIMER_RX_TRIGGER field bit +#define NXMAC_TIMER_RX_TRIGGER_BIT ((uint32_t)0x00020000) +/// TIMER_RX_TRIGGER field position +#define NXMAC_TIMER_RX_TRIGGER_POS 17 +/// RX_TRIGGER field bit +#define NXMAC_RX_TRIGGER_BIT ((uint32_t)0x00010000) +/// RX_TRIGGER field position +#define NXMAC_RX_TRIGGER_POS 16 +/// SEC_USER_TX_TRIGGER field bit +#define NXMAC_SEC_USER_TX_TRIGGER_BIT ((uint32_t)0x00008000) +/// SEC_USER_TX_TRIGGER field position +#define NXMAC_SEC_USER_TX_TRIGGER_POS 15 +/// TIMER_TX_TRIGGER field bit +#define NXMAC_TIMER_TX_TRIGGER_BIT ((uint32_t)0x00004000) +/// TIMER_TX_TRIGGER field position +#define NXMAC_TIMER_TX_TRIGGER_POS 14 +/// TXOP_COMPLETE field bit +#define NXMAC_TXOP_COMPLETE_BIT ((uint32_t)0x00002000) +/// TXOP_COMPLETE field position +#define NXMAC_TXOP_COMPLETE_POS 13 +/// RD_TX_TRIGGER field bit +#define NXMAC_RD_TX_TRIGGER_BIT ((uint32_t)0x00001000) +/// RD_TX_TRIGGER field position +#define NXMAC_RD_TX_TRIGGER_POS 12 +/// HCCA_TX_TRIGGER field bit +#define NXMAC_HCCA_TX_TRIGGER_BIT ((uint32_t)0x00000800) +/// HCCA_TX_TRIGGER field position +#define NXMAC_HCCA_TX_TRIGGER_POS 11 +/// BCN_TX_TRIGGER field bit +#define NXMAC_BCN_TX_TRIGGER_BIT ((uint32_t)0x00000400) +/// BCN_TX_TRIGGER field position +#define NXMAC_BCN_TX_TRIGGER_POS 10 +/// AC_3_TX_TRIGGER field bit +#define NXMAC_AC_3_TX_TRIGGER_BIT ((uint32_t)0x00000200) +/// AC_3_TX_TRIGGER field position +#define NXMAC_AC_3_TX_TRIGGER_POS 9 +/// AC_2_TX_TRIGGER field bit +#define NXMAC_AC_2_TX_TRIGGER_BIT ((uint32_t)0x00000100) +/// AC_2_TX_TRIGGER field position +#define NXMAC_AC_2_TX_TRIGGER_POS 8 +/// AC_1_TX_TRIGGER field bit +#define NXMAC_AC_1_TX_TRIGGER_BIT ((uint32_t)0x00000080) +/// AC_1_TX_TRIGGER field position +#define NXMAC_AC_1_TX_TRIGGER_POS 7 +/// AC_0_TX_TRIGGER field bit +#define NXMAC_AC_0_TX_TRIGGER_BIT ((uint32_t)0x00000040) +/// AC_0_TX_TRIGGER field position +#define NXMAC_AC_0_TX_TRIGGER_POS 6 +/// RD_PROT_TRIGGER field bit +#define NXMAC_RD_PROT_TRIGGER_BIT ((uint32_t)0x00000020) +/// RD_PROT_TRIGGER field position +#define NXMAC_RD_PROT_TRIGGER_POS 5 +/// HCCA_PROT_TRIGGER field bit +#define NXMAC_HCCA_PROT_TRIGGER_BIT ((uint32_t)0x00000010) +/// HCCA_PROT_TRIGGER field position +#define NXMAC_HCCA_PROT_TRIGGER_POS 4 +/// AC_3_PROT_TRIGGER field bit +#define NXMAC_AC_3_PROT_TRIGGER_BIT ((uint32_t)0x00000008) +/// AC_3_PROT_TRIGGER field position +#define NXMAC_AC_3_PROT_TRIGGER_POS 3 +/// AC_2_PROT_TRIGGER field bit +#define NXMAC_AC_2_PROT_TRIGGER_BIT ((uint32_t)0x00000004) +/// AC_2_PROT_TRIGGER field position +#define NXMAC_AC_2_PROT_TRIGGER_POS 2 +/// AC_1_PROT_TRIGGER field bit +#define NXMAC_AC_1_PROT_TRIGGER_BIT ((uint32_t)0x00000002) +/// AC_1_PROT_TRIGGER field position +#define NXMAC_AC_1_PROT_TRIGGER_POS 1 +/// AC_0_PROT_TRIGGER field bit +#define NXMAC_AC_0_PROT_TRIGGER_BIT ((uint32_t)0x00000001) +/// AC_0_PROT_TRIGGER field position +#define NXMAC_AC_0_PROT_TRIGGER_POS 0 + +/// MASTER_TX_RX_INT_EN field reset value +#define NXMAC_MASTER_TX_RX_INT_EN_RST 0x0 +/// BCN_TX_BUF_TRIGGER field reset value +#define NXMAC_BCN_TX_BUF_TRIGGER_RST 0x0 +/// AC_3_TX_BUF_TRIGGER field reset value +#define NXMAC_AC_3_TX_BUF_TRIGGER_RST 0x0 +/// AC_2_TX_BUF_TRIGGER field reset value +#define NXMAC_AC_2_TX_BUF_TRIGGER_RST 0x0 +/// AC_1_TX_BUF_TRIGGER field reset value +#define NXMAC_AC_1_TX_BUF_TRIGGER_RST 0x0 +/// AC_0_TX_BUF_TRIGGER field reset value +#define NXMAC_AC_0_TX_BUF_TRIGGER_RST 0x0 +/// AC_3BW_DROP_TRIGGER field reset value +#define NXMAC_AC_3BW_DROP_TRIGGER_RST 0x0 +/// AC_2BW_DROP_TRIGGER field reset value +#define NXMAC_AC_2BW_DROP_TRIGGER_RST 0x0 +/// AC_1BW_DROP_TRIGGER field reset value +#define NXMAC_AC_1BW_DROP_TRIGGER_RST 0x0 +/// AC_0BW_DROP_TRIGGER field reset value +#define NXMAC_AC_0BW_DROP_TRIGGER_RST 0x0 +/// COUNTER_RX_TRIGGER field reset value +#define NXMAC_COUNTER_RX_TRIGGER_RST 0x0 +/// BA_RX_TRIGGER field reset value +#define NXMAC_BA_RX_TRIGGER_RST 0x0 +/// TIMER_RX_TRIGGER field reset value +#define NXMAC_TIMER_RX_TRIGGER_RST 0x0 +/// RX_TRIGGER field reset value +#define NXMAC_RX_TRIGGER_RST 0x0 +/// SEC_USER_TX_TRIGGER field reset value +#define NXMAC_SEC_USER_TX_TRIGGER_RST 0x0 +/// TIMER_TX_TRIGGER field reset value +#define NXMAC_TIMER_TX_TRIGGER_RST 0x0 +/// TXOP_COMPLETE field reset value +#define NXMAC_TXOP_COMPLETE_RST 0x0 +/// RD_TX_TRIGGER field reset value +#define NXMAC_RD_TX_TRIGGER_RST 0x0 +/// HCCA_TX_TRIGGER field reset value +#define NXMAC_HCCA_TX_TRIGGER_RST 0x0 +/// BCN_TX_TRIGGER field reset value +#define NXMAC_BCN_TX_TRIGGER_RST 0x0 +/// AC_3_TX_TRIGGER field reset value +#define NXMAC_AC_3_TX_TRIGGER_RST 0x0 +/// AC_2_TX_TRIGGER field reset value +#define NXMAC_AC_2_TX_TRIGGER_RST 0x0 +/// AC_1_TX_TRIGGER field reset value +#define NXMAC_AC_1_TX_TRIGGER_RST 0x0 +/// AC_0_TX_TRIGGER field reset value +#define NXMAC_AC_0_TX_TRIGGER_RST 0x0 +/// RD_PROT_TRIGGER field reset value +#define NXMAC_RD_PROT_TRIGGER_RST 0x0 +/// HCCA_PROT_TRIGGER field reset value +#define NXMAC_HCCA_PROT_TRIGGER_RST 0x0 +/// AC_3_PROT_TRIGGER field reset value +#define NXMAC_AC_3_PROT_TRIGGER_RST 0x0 +/// AC_2_PROT_TRIGGER field reset value +#define NXMAC_AC_2_PROT_TRIGGER_RST 0x0 +/// AC_1_PROT_TRIGGER field reset value +#define NXMAC_AC_1_PROT_TRIGGER_RST 0x0 +/// AC_0_PROT_TRIGGER field reset value +#define NXMAC_AC_0_PROT_TRIGGER_RST 0x0 + +/** + * @brief Constructs a value for the TX_RX_INT_ENABLE register given values for its fields + * and writes the value to the register. + * + * @param[in] mastertxrxinten - The value to use for the masterTxRxIntEn field. + * @param[in] bcntxbuftrigger - The value to use for the bcnTxBufTrigger field. + * @param[in] ac3txbuftrigger - The value to use for the ac3TxBufTrigger field. + * @param[in] ac2txbuftrigger - The value to use for the ac2TxBufTrigger field. + * @param[in] ac1txbuftrigger - The value to use for the ac1TxBufTrigger field. + * @param[in] ac0txbuftrigger - The value to use for the ac0TxBufTrigger field. + * @param[in] ac3bwdroptrigger - The value to use for the ac3BWDropTrigger field. + * @param[in] ac2bwdroptrigger - The value to use for the ac2BWDropTrigger field. + * @param[in] ac1bwdroptrigger - The value to use for the ac1BWDropTrigger field. + * @param[in] ac0bwdroptrigger - The value to use for the ac0BWDropTrigger field. + * @param[in] counterrxtrigger - The value to use for the counterRxTrigger field. + * @param[in] barxtrigger - The value to use for the baRxTrigger field. + * @param[in] timerrxtrigger - The value to use for the timerRxTrigger field. + * @param[in] rxtrigger - The value to use for the rxTrigger field. + * @param[in] secusertxtrigger - The value to use for the secUserTxTrigger field. + * @param[in] timertxtrigger - The value to use for the timerTxTrigger field. + * @param[in] txopcomplete - The value to use for the txopComplete field. + * @param[in] rdtxtrigger - The value to use for the rdTxTrigger field. + * @param[in] hccatxtrigger - The value to use for the hccaTxTrigger field. + * @param[in] bcntxtrigger - The value to use for the bcnTxTrigger field. + * @param[in] ac3txtrigger - The value to use for the ac3TxTrigger field. + * @param[in] ac2txtrigger - The value to use for the ac2TxTrigger field. + * @param[in] ac1txtrigger - The value to use for the ac1TxTrigger field. + * @param[in] ac0txtrigger - The value to use for the ac0TxTrigger field. + * @param[in] rdprottrigger - The value to use for the rdProtTrigger field. + * @param[in] hccaprottrigger - The value to use for the hccaProtTrigger field. + * @param[in] ac3prottrigger - The value to use for the ac3ProtTrigger field. + * @param[in] ac2prottrigger - The value to use for the ac2ProtTrigger field. + * @param[in] ac1prottrigger - The value to use for the ac1ProtTrigger field. + * @param[in] ac0prottrigger - The value to use for the ac0ProtTrigger field. + */ +__INLINE void nxmac_tx_rx_int_enable_pack(uint8_t mastertxrxinten, uint8_t bcntxbuftrigger, uint8_t ac3txbuftrigger, uint8_t ac2txbuftrigger, uint8_t ac1txbuftrigger, uint8_t ac0txbuftrigger, uint8_t ac3bwdroptrigger, uint8_t ac2bwdroptrigger, uint8_t ac1bwdroptrigger, uint8_t ac0bwdroptrigger, uint8_t counterrxtrigger, uint8_t barxtrigger, uint8_t timerrxtrigger, uint8_t rxtrigger, uint8_t secusertxtrigger, uint8_t timertxtrigger, uint8_t txopcomplete, uint8_t rdtxtrigger, uint8_t hccatxtrigger, uint8_t bcntxtrigger, uint8_t ac3txtrigger, uint8_t ac2txtrigger, uint8_t ac1txtrigger, uint8_t ac0txtrigger, uint8_t rdprottrigger, uint8_t hccaprottrigger, uint8_t ac3prottrigger, uint8_t ac2prottrigger, uint8_t ac1prottrigger, uint8_t ac0prottrigger) +{ + ASSERT_ERR((((uint32_t)mastertxrxinten << 31) & ~((uint32_t)0x80000000)) == 0); + ASSERT_ERR((((uint32_t)bcntxbuftrigger << 28) & ~((uint32_t)0x10000000)) == 0); + ASSERT_ERR((((uint32_t)ac3txbuftrigger << 27) & ~((uint32_t)0x08000000)) == 0); + ASSERT_ERR((((uint32_t)ac2txbuftrigger << 26) & ~((uint32_t)0x04000000)) == 0); + ASSERT_ERR((((uint32_t)ac1txbuftrigger << 25) & ~((uint32_t)0x02000000)) == 0); + ASSERT_ERR((((uint32_t)ac0txbuftrigger << 24) & ~((uint32_t)0x01000000)) == 0); + ASSERT_ERR((((uint32_t)ac3bwdroptrigger << 23) & ~((uint32_t)0x00800000)) == 0); + ASSERT_ERR((((uint32_t)ac2bwdroptrigger << 22) & ~((uint32_t)0x00400000)) == 0); + ASSERT_ERR((((uint32_t)ac1bwdroptrigger << 21) & ~((uint32_t)0x00200000)) == 0); + ASSERT_ERR((((uint32_t)ac0bwdroptrigger << 20) & ~((uint32_t)0x00100000)) == 0); + ASSERT_ERR((((uint32_t)counterrxtrigger << 19) & ~((uint32_t)0x00080000)) == 0); + ASSERT_ERR((((uint32_t)barxtrigger << 18) & ~((uint32_t)0x00040000)) == 0); + ASSERT_ERR((((uint32_t)timerrxtrigger << 17) & ~((uint32_t)0x00020000)) == 0); + ASSERT_ERR((((uint32_t)rxtrigger << 16) & ~((uint32_t)0x00010000)) == 0); + ASSERT_ERR((((uint32_t)secusertxtrigger << 15) & ~((uint32_t)0x00008000)) == 0); + ASSERT_ERR((((uint32_t)timertxtrigger << 14) & ~((uint32_t)0x00004000)) == 0); + ASSERT_ERR((((uint32_t)txopcomplete << 13) & ~((uint32_t)0x00002000)) == 0); + ASSERT_ERR((((uint32_t)rdtxtrigger << 12) & ~((uint32_t)0x00001000)) == 0); + ASSERT_ERR((((uint32_t)hccatxtrigger << 11) & ~((uint32_t)0x00000800)) == 0); + ASSERT_ERR((((uint32_t)bcntxtrigger << 10) & ~((uint32_t)0x00000400)) == 0); + ASSERT_ERR((((uint32_t)ac3txtrigger << 9) & ~((uint32_t)0x00000200)) == 0); + ASSERT_ERR((((uint32_t)ac2txtrigger << 8) & ~((uint32_t)0x00000100)) == 0); + ASSERT_ERR((((uint32_t)ac1txtrigger << 7) & ~((uint32_t)0x00000080)) == 0); + ASSERT_ERR((((uint32_t)ac0txtrigger << 6) & ~((uint32_t)0x00000040)) == 0); + ASSERT_ERR((((uint32_t)rdprottrigger << 5) & ~((uint32_t)0x00000020)) == 0); + ASSERT_ERR((((uint32_t)hccaprottrigger << 4) & ~((uint32_t)0x00000010)) == 0); + ASSERT_ERR((((uint32_t)ac3prottrigger << 3) & ~((uint32_t)0x00000008)) == 0); + ASSERT_ERR((((uint32_t)ac2prottrigger << 2) & ~((uint32_t)0x00000004)) == 0); + ASSERT_ERR((((uint32_t)ac1prottrigger << 1) & ~((uint32_t)0x00000002)) == 0); + ASSERT_ERR((((uint32_t)ac0prottrigger << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ENABLE_ADDR, ((uint32_t)mastertxrxinten << 31) | ((uint32_t)bcntxbuftrigger << 28) | ((uint32_t)ac3txbuftrigger << 27) | ((uint32_t)ac2txbuftrigger << 26) | ((uint32_t)ac1txbuftrigger << 25) | ((uint32_t)ac0txbuftrigger << 24) | ((uint32_t)ac3bwdroptrigger << 23) | ((uint32_t)ac2bwdroptrigger << 22) | ((uint32_t)ac1bwdroptrigger << 21) | ((uint32_t)ac0bwdroptrigger << 20) | ((uint32_t)counterrxtrigger << 19) | ((uint32_t)barxtrigger << 18) | ((uint32_t)timerrxtrigger << 17) | ((uint32_t)rxtrigger << 16) | ((uint32_t)secusertxtrigger << 15) | ((uint32_t)timertxtrigger << 14) | ((uint32_t)txopcomplete << 13) | ((uint32_t)rdtxtrigger << 12) | ((uint32_t)hccatxtrigger << 11) | ((uint32_t)bcntxtrigger << 10) | ((uint32_t)ac3txtrigger << 9) | ((uint32_t)ac2txtrigger << 8) | ((uint32_t)ac1txtrigger << 7) | ((uint32_t)ac0txtrigger << 6) | ((uint32_t)rdprottrigger << 5) | ((uint32_t)hccaprottrigger << 4) | ((uint32_t)ac3prottrigger << 3) | ((uint32_t)ac2prottrigger << 2) | ((uint32_t)ac1prottrigger << 1) | ((uint32_t)ac0prottrigger << 0)); +} + +/** + * @brief Unpacks TX_RX_INT_ENABLE's fields from current value of the TX_RX_INT_ENABLE register. + * + * Reads the TX_RX_INT_ENABLE register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] mastertxrxinten - Will be populated with the current value of this field from the register. + * @param[out] bcntxbuftrigger - Will be populated with the current value of this field from the register. + * @param[out] ac3txbuftrigger - Will be populated with the current value of this field from the register. + * @param[out] ac2txbuftrigger - Will be populated with the current value of this field from the register. + * @param[out] ac1txbuftrigger - Will be populated with the current value of this field from the register. + * @param[out] ac0txbuftrigger - Will be populated with the current value of this field from the register. + * @param[out] ac3bwdroptrigger - Will be populated with the current value of this field from the register. + * @param[out] ac2bwdroptrigger - Will be populated with the current value of this field from the register. + * @param[out] ac1bwdroptrigger - Will be populated with the current value of this field from the register. + * @param[out] ac0bwdroptrigger - Will be populated with the current value of this field from the register. + * @param[out] counterrxtrigger - Will be populated with the current value of this field from the register. + * @param[out] barxtrigger - Will be populated with the current value of this field from the register. + * @param[out] timerrxtrigger - Will be populated with the current value of this field from the register. + * @param[out] rxtrigger - Will be populated with the current value of this field from the register. + * @param[out] secusertxtrigger - Will be populated with the current value of this field from the register. + * @param[out] timertxtrigger - Will be populated with the current value of this field from the register. + * @param[out] txopcomplete - Will be populated with the current value of this field from the register. + * @param[out] rdtxtrigger - Will be populated with the current value of this field from the register. + * @param[out] hccatxtrigger - Will be populated with the current value of this field from the register. + * @param[out] bcntxtrigger - Will be populated with the current value of this field from the register. + * @param[out] ac3txtrigger - Will be populated with the current value of this field from the register. + * @param[out] ac2txtrigger - Will be populated with the current value of this field from the register. + * @param[out] ac1txtrigger - Will be populated with the current value of this field from the register. + * @param[out] ac0txtrigger - Will be populated with the current value of this field from the register. + * @param[out] rdprottrigger - Will be populated with the current value of this field from the register. + * @param[out] hccaprottrigger - Will be populated with the current value of this field from the register. + * @param[out] ac3prottrigger - Will be populated with the current value of this field from the register. + * @param[out] ac2prottrigger - Will be populated with the current value of this field from the register. + * @param[out] ac1prottrigger - Will be populated with the current value of this field from the register. + * @param[out] ac0prottrigger - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_tx_rx_int_enable_unpack(uint8_t *mastertxrxinten, uint8_t *bcntxbuftrigger, uint8_t *ac3txbuftrigger, uint8_t *ac2txbuftrigger, uint8_t *ac1txbuftrigger, uint8_t *ac0txbuftrigger, uint8_t *ac3bwdroptrigger, uint8_t *ac2bwdroptrigger, uint8_t *ac1bwdroptrigger, uint8_t *ac0bwdroptrigger, uint8_t *counterrxtrigger, uint8_t *barxtrigger, uint8_t *timerrxtrigger, uint8_t *rxtrigger, uint8_t *secusertxtrigger, uint8_t *timertxtrigger, uint8_t *txopcomplete, uint8_t *rdtxtrigger, uint8_t *hccatxtrigger, uint8_t *bcntxtrigger, uint8_t *ac3txtrigger, uint8_t *ac2txtrigger, uint8_t *ac1txtrigger, uint8_t *ac0txtrigger, uint8_t *rdprottrigger, uint8_t *hccaprottrigger, uint8_t *ac3prottrigger, uint8_t *ac2prottrigger, uint8_t *ac1prottrigger, uint8_t *ac0prottrigger) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR); + + *mastertxrxinten = (localVal & ((uint32_t)0x80000000)) >> 31; + *bcntxbuftrigger = (localVal & ((uint32_t)0x10000000)) >> 28; + *ac3txbuftrigger = (localVal & ((uint32_t)0x08000000)) >> 27; + *ac2txbuftrigger = (localVal & ((uint32_t)0x04000000)) >> 26; + *ac1txbuftrigger = (localVal & ((uint32_t)0x02000000)) >> 25; + *ac0txbuftrigger = (localVal & ((uint32_t)0x01000000)) >> 24; + *ac3bwdroptrigger = (localVal & ((uint32_t)0x00800000)) >> 23; + *ac2bwdroptrigger = (localVal & ((uint32_t)0x00400000)) >> 22; + *ac1bwdroptrigger = (localVal & ((uint32_t)0x00200000)) >> 21; + *ac0bwdroptrigger = (localVal & ((uint32_t)0x00100000)) >> 20; + *counterrxtrigger = (localVal & ((uint32_t)0x00080000)) >> 19; + *barxtrigger = (localVal & ((uint32_t)0x00040000)) >> 18; + *timerrxtrigger = (localVal & ((uint32_t)0x00020000)) >> 17; + *rxtrigger = (localVal & ((uint32_t)0x00010000)) >> 16; + *secusertxtrigger = (localVal & ((uint32_t)0x00008000)) >> 15; + *timertxtrigger = (localVal & ((uint32_t)0x00004000)) >> 14; + *txopcomplete = (localVal & ((uint32_t)0x00002000)) >> 13; + *rdtxtrigger = (localVal & ((uint32_t)0x00001000)) >> 12; + *hccatxtrigger = (localVal & ((uint32_t)0x00000800)) >> 11; + *bcntxtrigger = (localVal & ((uint32_t)0x00000400)) >> 10; + *ac3txtrigger = (localVal & ((uint32_t)0x00000200)) >> 9; + *ac2txtrigger = (localVal & ((uint32_t)0x00000100)) >> 8; + *ac1txtrigger = (localVal & ((uint32_t)0x00000080)) >> 7; + *ac0txtrigger = (localVal & ((uint32_t)0x00000040)) >> 6; + *rdprottrigger = (localVal & ((uint32_t)0x00000020)) >> 5; + *hccaprottrigger = (localVal & ((uint32_t)0x00000010)) >> 4; + *ac3prottrigger = (localVal & ((uint32_t)0x00000008)) >> 3; + *ac2prottrigger = (localVal & ((uint32_t)0x00000004)) >> 2; + *ac1prottrigger = (localVal & ((uint32_t)0x00000002)) >> 1; + *ac0prottrigger = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +/** + * @brief Returns the current value of the masterTxRxIntEn field in the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read and the masterTxRxIntEn field's value will be returned. + * + * @return The current value of the masterTxRxIntEn field in the TX_RX_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_master_tx_rx_int_en_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +/** + * @brief Sets the masterTxRxIntEn field of the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] mastertxrxinten - The value to set the field to. + */ +__INLINE void nxmac_enable_master_tx_rx_int_en_setf(uint8_t mastertxrxinten) +{ + ASSERT_ERR((((uint32_t)mastertxrxinten << 31) & ~((uint32_t)0x80000000)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR) & ~((uint32_t)0x80000000)) | ((uint32_t)mastertxrxinten << 31)); +} + +/** + * @brief Returns the current value of the bcnTxBufTrigger field in the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read and the bcnTxBufTrigger field's value will be returned. + * + * @return The current value of the bcnTxBufTrigger field in the TX_RX_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_bcn_tx_buf_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x10000000)) >> 28); +} + +/** + * @brief Sets the bcnTxBufTrigger field of the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] bcntxbuftrigger - The value to set the field to. + */ +__INLINE void nxmac_enable_bcn_tx_buf_trigger_setf(uint8_t bcntxbuftrigger) +{ + ASSERT_ERR((((uint32_t)bcntxbuftrigger << 28) & ~((uint32_t)0x10000000)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR) & ~((uint32_t)0x10000000)) | ((uint32_t)bcntxbuftrigger << 28)); +} + +/** + * @brief Returns the current value of the ac3TxBufTrigger field in the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read and the ac3TxBufTrigger field's value will be returned. + * + * @return The current value of the ac3TxBufTrigger field in the TX_RX_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_ac_3_tx_buf_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x08000000)) >> 27); +} + +/** + * @brief Sets the ac3TxBufTrigger field of the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] ac3txbuftrigger - The value to set the field to. + */ +__INLINE void nxmac_enable_ac_3_tx_buf_trigger_setf(uint8_t ac3txbuftrigger) +{ + ASSERT_ERR((((uint32_t)ac3txbuftrigger << 27) & ~((uint32_t)0x08000000)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR) & ~((uint32_t)0x08000000)) | ((uint32_t)ac3txbuftrigger << 27)); +} + +/** + * @brief Returns the current value of the ac2TxBufTrigger field in the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read and the ac2TxBufTrigger field's value will be returned. + * + * @return The current value of the ac2TxBufTrigger field in the TX_RX_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_ac_2_tx_buf_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x04000000)) >> 26); +} + +/** + * @brief Sets the ac2TxBufTrigger field of the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] ac2txbuftrigger - The value to set the field to. + */ +__INLINE void nxmac_enable_ac_2_tx_buf_trigger_setf(uint8_t ac2txbuftrigger) +{ + ASSERT_ERR((((uint32_t)ac2txbuftrigger << 26) & ~((uint32_t)0x04000000)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR) & ~((uint32_t)0x04000000)) | ((uint32_t)ac2txbuftrigger << 26)); +} + +/** + * @brief Returns the current value of the ac1TxBufTrigger field in the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read and the ac1TxBufTrigger field's value will be returned. + * + * @return The current value of the ac1TxBufTrigger field in the TX_RX_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_ac_1_tx_buf_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x02000000)) >> 25); +} + +/** + * @brief Sets the ac1TxBufTrigger field of the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] ac1txbuftrigger - The value to set the field to. + */ +__INLINE void nxmac_enable_ac_1_tx_buf_trigger_setf(uint8_t ac1txbuftrigger) +{ + ASSERT_ERR((((uint32_t)ac1txbuftrigger << 25) & ~((uint32_t)0x02000000)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR) & ~((uint32_t)0x02000000)) | ((uint32_t)ac1txbuftrigger << 25)); +} + +/** + * @brief Returns the current value of the ac0TxBufTrigger field in the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read and the ac0TxBufTrigger field's value will be returned. + * + * @return The current value of the ac0TxBufTrigger field in the TX_RX_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_ac_0_tx_buf_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x01000000)) >> 24); +} + +/** + * @brief Sets the ac0TxBufTrigger field of the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] ac0txbuftrigger - The value to set the field to. + */ +__INLINE void nxmac_enable_ac_0_tx_buf_trigger_setf(uint8_t ac0txbuftrigger) +{ + ASSERT_ERR((((uint32_t)ac0txbuftrigger << 24) & ~((uint32_t)0x01000000)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR) & ~((uint32_t)0x01000000)) | ((uint32_t)ac0txbuftrigger << 24)); +} + +/** + * @brief Returns the current value of the ac3BWDropTrigger field in the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read and the ac3BWDropTrigger field's value will be returned. + * + * @return The current value of the ac3BWDropTrigger field in the TX_RX_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_ac_3bw_drop_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x00800000)) >> 23); +} + +/** + * @brief Sets the ac3BWDropTrigger field of the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] ac3bwdroptrigger - The value to set the field to. + */ +__INLINE void nxmac_enable_ac_3bw_drop_trigger_setf(uint8_t ac3bwdroptrigger) +{ + ASSERT_ERR((((uint32_t)ac3bwdroptrigger << 23) & ~((uint32_t)0x00800000)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR) & ~((uint32_t)0x00800000)) | ((uint32_t)ac3bwdroptrigger << 23)); +} + +/** + * @brief Returns the current value of the ac2BWDropTrigger field in the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read and the ac2BWDropTrigger field's value will be returned. + * + * @return The current value of the ac2BWDropTrigger field in the TX_RX_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_ac_2bw_drop_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x00400000)) >> 22); +} + +/** + * @brief Sets the ac2BWDropTrigger field of the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] ac2bwdroptrigger - The value to set the field to. + */ +__INLINE void nxmac_enable_ac_2bw_drop_trigger_setf(uint8_t ac2bwdroptrigger) +{ + ASSERT_ERR((((uint32_t)ac2bwdroptrigger << 22) & ~((uint32_t)0x00400000)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR) & ~((uint32_t)0x00400000)) | ((uint32_t)ac2bwdroptrigger << 22)); +} + +/** + * @brief Returns the current value of the ac1BWDropTrigger field in the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read and the ac1BWDropTrigger field's value will be returned. + * + * @return The current value of the ac1BWDropTrigger field in the TX_RX_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_ac_1bw_drop_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x00200000)) >> 21); +} + +/** + * @brief Sets the ac1BWDropTrigger field of the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] ac1bwdroptrigger - The value to set the field to. + */ +__INLINE void nxmac_enable_ac_1bw_drop_trigger_setf(uint8_t ac1bwdroptrigger) +{ + ASSERT_ERR((((uint32_t)ac1bwdroptrigger << 21) & ~((uint32_t)0x00200000)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR) & ~((uint32_t)0x00200000)) | ((uint32_t)ac1bwdroptrigger << 21)); +} + +/** + * @brief Returns the current value of the ac0BWDropTrigger field in the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read and the ac0BWDropTrigger field's value will be returned. + * + * @return The current value of the ac0BWDropTrigger field in the TX_RX_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_ac_0bw_drop_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x00100000)) >> 20); +} + +/** + * @brief Sets the ac0BWDropTrigger field of the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] ac0bwdroptrigger - The value to set the field to. + */ +__INLINE void nxmac_enable_ac_0bw_drop_trigger_setf(uint8_t ac0bwdroptrigger) +{ + ASSERT_ERR((((uint32_t)ac0bwdroptrigger << 20) & ~((uint32_t)0x00100000)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR) & ~((uint32_t)0x00100000)) | ((uint32_t)ac0bwdroptrigger << 20)); +} + +/** + * @brief Returns the current value of the counterRxTrigger field in the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read and the counterRxTrigger field's value will be returned. + * + * @return The current value of the counterRxTrigger field in the TX_RX_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_counter_rx_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x00080000)) >> 19); +} + +/** + * @brief Sets the counterRxTrigger field of the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] counterrxtrigger - The value to set the field to. + */ +__INLINE void nxmac_enable_counter_rx_trigger_setf(uint8_t counterrxtrigger) +{ + ASSERT_ERR((((uint32_t)counterrxtrigger << 19) & ~((uint32_t)0x00080000)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR) & ~((uint32_t)0x00080000)) | ((uint32_t)counterrxtrigger << 19)); +} + +/** + * @brief Returns the current value of the baRxTrigger field in the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read and the baRxTrigger field's value will be returned. + * + * @return The current value of the baRxTrigger field in the TX_RX_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_ba_rx_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x00040000)) >> 18); +} + +/** + * @brief Sets the baRxTrigger field of the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] barxtrigger - The value to set the field to. + */ +__INLINE void nxmac_enable_ba_rx_trigger_setf(uint8_t barxtrigger) +{ + ASSERT_ERR((((uint32_t)barxtrigger << 18) & ~((uint32_t)0x00040000)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR) & ~((uint32_t)0x00040000)) | ((uint32_t)barxtrigger << 18)); +} + +/** + * @brief Returns the current value of the timerRxTrigger field in the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read and the timerRxTrigger field's value will be returned. + * + * @return The current value of the timerRxTrigger field in the TX_RX_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_timer_rx_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x00020000)) >> 17); +} + +/** + * @brief Sets the timerRxTrigger field of the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] timerrxtrigger - The value to set the field to. + */ +__INLINE void nxmac_enable_timer_rx_trigger_setf(uint8_t timerrxtrigger) +{ + ASSERT_ERR((((uint32_t)timerrxtrigger << 17) & ~((uint32_t)0x00020000)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR) & ~((uint32_t)0x00020000)) | ((uint32_t)timerrxtrigger << 17)); +} + +/** + * @brief Returns the current value of the rxTrigger field in the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read and the rxTrigger field's value will be returned. + * + * @return The current value of the rxTrigger field in the TX_RX_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_rx_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x00010000)) >> 16); +} + +/** + * @brief Sets the rxTrigger field of the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] rxtrigger - The value to set the field to. + */ +__INLINE void nxmac_enable_rx_trigger_setf(uint8_t rxtrigger) +{ + ASSERT_ERR((((uint32_t)rxtrigger << 16) & ~((uint32_t)0x00010000)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR) & ~((uint32_t)0x00010000)) | ((uint32_t)rxtrigger << 16)); +} + +/** + * @brief Returns the current value of the secUserTxTrigger field in the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read and the secUserTxTrigger field's value will be returned. + * + * @return The current value of the secUserTxTrigger field in the TX_RX_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_sec_user_tx_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x00008000)) >> 15); +} + +/** + * @brief Sets the secUserTxTrigger field of the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] secusertxtrigger - The value to set the field to. + */ +__INLINE void nxmac_enable_sec_user_tx_trigger_setf(uint8_t secusertxtrigger) +{ + ASSERT_ERR((((uint32_t)secusertxtrigger << 15) & ~((uint32_t)0x00008000)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR) & ~((uint32_t)0x00008000)) | ((uint32_t)secusertxtrigger << 15)); +} + +/** + * @brief Returns the current value of the timerTxTrigger field in the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read and the timerTxTrigger field's value will be returned. + * + * @return The current value of the timerTxTrigger field in the TX_RX_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_timer_tx_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x00004000)) >> 14); +} + +/** + * @brief Sets the timerTxTrigger field of the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] timertxtrigger - The value to set the field to. + */ +__INLINE void nxmac_enable_timer_tx_trigger_setf(uint8_t timertxtrigger) +{ + ASSERT_ERR((((uint32_t)timertxtrigger << 14) & ~((uint32_t)0x00004000)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR) & ~((uint32_t)0x00004000)) | ((uint32_t)timertxtrigger << 14)); +} + +/** + * @brief Returns the current value of the txopComplete field in the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read and the txopComplete field's value will be returned. + * + * @return The current value of the txopComplete field in the TX_RX_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_txop_complete_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x00002000)) >> 13); +} + +/** + * @brief Sets the txopComplete field of the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] txopcomplete - The value to set the field to. + */ +__INLINE void nxmac_enable_txop_complete_setf(uint8_t txopcomplete) +{ + ASSERT_ERR((((uint32_t)txopcomplete << 13) & ~((uint32_t)0x00002000)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR) & ~((uint32_t)0x00002000)) | ((uint32_t)txopcomplete << 13)); +} + +/** + * @brief Returns the current value of the rdTxTrigger field in the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read and the rdTxTrigger field's value will be returned. + * + * @return The current value of the rdTxTrigger field in the TX_RX_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_rd_tx_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x00001000)) >> 12); +} + +/** + * @brief Sets the rdTxTrigger field of the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] rdtxtrigger - The value to set the field to. + */ +__INLINE void nxmac_enable_rd_tx_trigger_setf(uint8_t rdtxtrigger) +{ + ASSERT_ERR((((uint32_t)rdtxtrigger << 12) & ~((uint32_t)0x00001000)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR) & ~((uint32_t)0x00001000)) | ((uint32_t)rdtxtrigger << 12)); +} + +/** + * @brief Returns the current value of the hccaTxTrigger field in the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read and the hccaTxTrigger field's value will be returned. + * + * @return The current value of the hccaTxTrigger field in the TX_RX_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_hcca_tx_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x00000800)) >> 11); +} + +/** + * @brief Sets the hccaTxTrigger field of the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] hccatxtrigger - The value to set the field to. + */ +__INLINE void nxmac_enable_hcca_tx_trigger_setf(uint8_t hccatxtrigger) +{ + ASSERT_ERR((((uint32_t)hccatxtrigger << 11) & ~((uint32_t)0x00000800)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR) & ~((uint32_t)0x00000800)) | ((uint32_t)hccatxtrigger << 11)); +} + +/** + * @brief Returns the current value of the bcnTxTrigger field in the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read and the bcnTxTrigger field's value will be returned. + * + * @return The current value of the bcnTxTrigger field in the TX_RX_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_bcn_tx_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x00000400)) >> 10); +} + +/** + * @brief Sets the bcnTxTrigger field of the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] bcntxtrigger - The value to set the field to. + */ +__INLINE void nxmac_enable_bcn_tx_trigger_setf(uint8_t bcntxtrigger) +{ + ASSERT_ERR((((uint32_t)bcntxtrigger << 10) & ~((uint32_t)0x00000400)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR) & ~((uint32_t)0x00000400)) | ((uint32_t)bcntxtrigger << 10)); +} + +/** + * @brief Returns the current value of the ac3TxTrigger field in the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read and the ac3TxTrigger field's value will be returned. + * + * @return The current value of the ac3TxTrigger field in the TX_RX_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_ac_3_tx_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x00000200)) >> 9); +} + +/** + * @brief Sets the ac3TxTrigger field of the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] ac3txtrigger - The value to set the field to. + */ +__INLINE void nxmac_enable_ac_3_tx_trigger_setf(uint8_t ac3txtrigger) +{ + ASSERT_ERR((((uint32_t)ac3txtrigger << 9) & ~((uint32_t)0x00000200)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR) & ~((uint32_t)0x00000200)) | ((uint32_t)ac3txtrigger << 9)); +} + +/** + * @brief Returns the current value of the ac2TxTrigger field in the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read and the ac2TxTrigger field's value will be returned. + * + * @return The current value of the ac2TxTrigger field in the TX_RX_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_ac_2_tx_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x00000100)) >> 8); +} + +/** + * @brief Sets the ac2TxTrigger field of the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] ac2txtrigger - The value to set the field to. + */ +__INLINE void nxmac_enable_ac_2_tx_trigger_setf(uint8_t ac2txtrigger) +{ + ASSERT_ERR((((uint32_t)ac2txtrigger << 8) & ~((uint32_t)0x00000100)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR) & ~((uint32_t)0x00000100)) | ((uint32_t)ac2txtrigger << 8)); +} + +/** + * @brief Returns the current value of the ac1TxTrigger field in the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read and the ac1TxTrigger field's value will be returned. + * + * @return The current value of the ac1TxTrigger field in the TX_RX_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_ac_1_tx_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x00000080)) >> 7); +} + +/** + * @brief Sets the ac1TxTrigger field of the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] ac1txtrigger - The value to set the field to. + */ +__INLINE void nxmac_enable_ac_1_tx_trigger_setf(uint8_t ac1txtrigger) +{ + ASSERT_ERR((((uint32_t)ac1txtrigger << 7) & ~((uint32_t)0x00000080)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR) & ~((uint32_t)0x00000080)) | ((uint32_t)ac1txtrigger << 7)); +} + +/** + * @brief Returns the current value of the ac0TxTrigger field in the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read and the ac0TxTrigger field's value will be returned. + * + * @return The current value of the ac0TxTrigger field in the TX_RX_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_ac_0_tx_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x00000040)) >> 6); +} + +/** + * @brief Sets the ac0TxTrigger field of the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] ac0txtrigger - The value to set the field to. + */ +__INLINE void nxmac_enable_ac_0_tx_trigger_setf(uint8_t ac0txtrigger) +{ + ASSERT_ERR((((uint32_t)ac0txtrigger << 6) & ~((uint32_t)0x00000040)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR) & ~((uint32_t)0x00000040)) | ((uint32_t)ac0txtrigger << 6)); +} + +/** + * @brief Returns the current value of the rdProtTrigger field in the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read and the rdProtTrigger field's value will be returned. + * + * @return The current value of the rdProtTrigger field in the TX_RX_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_rd_prot_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +/** + * @brief Sets the rdProtTrigger field of the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] rdprottrigger - The value to set the field to. + */ +__INLINE void nxmac_enable_rd_prot_trigger_setf(uint8_t rdprottrigger) +{ + ASSERT_ERR((((uint32_t)rdprottrigger << 5) & ~((uint32_t)0x00000020)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR) & ~((uint32_t)0x00000020)) | ((uint32_t)rdprottrigger << 5)); +} + +/** + * @brief Returns the current value of the hccaProtTrigger field in the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read and the hccaProtTrigger field's value will be returned. + * + * @return The current value of the hccaProtTrigger field in the TX_RX_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_hcca_prot_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +/** + * @brief Sets the hccaProtTrigger field of the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] hccaprottrigger - The value to set the field to. + */ +__INLINE void nxmac_enable_hcca_prot_trigger_setf(uint8_t hccaprottrigger) +{ + ASSERT_ERR((((uint32_t)hccaprottrigger << 4) & ~((uint32_t)0x00000010)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR) & ~((uint32_t)0x00000010)) | ((uint32_t)hccaprottrigger << 4)); +} + +/** + * @brief Returns the current value of the ac3ProtTrigger field in the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read and the ac3ProtTrigger field's value will be returned. + * + * @return The current value of the ac3ProtTrigger field in the TX_RX_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_ac_3_prot_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +/** + * @brief Sets the ac3ProtTrigger field of the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] ac3prottrigger - The value to set the field to. + */ +__INLINE void nxmac_enable_ac_3_prot_trigger_setf(uint8_t ac3prottrigger) +{ + ASSERT_ERR((((uint32_t)ac3prottrigger << 3) & ~((uint32_t)0x00000008)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR) & ~((uint32_t)0x00000008)) | ((uint32_t)ac3prottrigger << 3)); +} + +/** + * @brief Returns the current value of the ac2ProtTrigger field in the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read and the ac2ProtTrigger field's value will be returned. + * + * @return The current value of the ac2ProtTrigger field in the TX_RX_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_ac_2_prot_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +/** + * @brief Sets the ac2ProtTrigger field of the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] ac2prottrigger - The value to set the field to. + */ +__INLINE void nxmac_enable_ac_2_prot_trigger_setf(uint8_t ac2prottrigger) +{ + ASSERT_ERR((((uint32_t)ac2prottrigger << 2) & ~((uint32_t)0x00000004)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR) & ~((uint32_t)0x00000004)) | ((uint32_t)ac2prottrigger << 2)); +} + +/** + * @brief Returns the current value of the ac1ProtTrigger field in the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read and the ac1ProtTrigger field's value will be returned. + * + * @return The current value of the ac1ProtTrigger field in the TX_RX_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_ac_1_prot_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +/** + * @brief Sets the ac1ProtTrigger field of the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] ac1prottrigger - The value to set the field to. + */ +__INLINE void nxmac_enable_ac_1_prot_trigger_setf(uint8_t ac1prottrigger) +{ + ASSERT_ERR((((uint32_t)ac1prottrigger << 1) & ~((uint32_t)0x00000002)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR) & ~((uint32_t)0x00000002)) | ((uint32_t)ac1prottrigger << 1)); +} + +/** + * @brief Returns the current value of the ac0ProtTrigger field in the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read and the ac0ProtTrigger field's value will be returned. + * + * @return The current value of the ac0ProtTrigger field in the TX_RX_INT_ENABLE register. + */ +__INLINE uint8_t nxmac_enable_ac_0_prot_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/** + * @brief Sets the ac0ProtTrigger field of the TX_RX_INT_ENABLE register. + * + * The TX_RX_INT_ENABLE register will be read, modified to contain the new field value, and written. + * + * @param[in] ac0prottrigger - The value to set the field to. + */ +__INLINE void nxmac_enable_ac_0_prot_trigger_setf(uint8_t ac0prottrigger) +{ + ASSERT_ERR((((uint32_t)ac0prottrigger << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_TX_RX_INT_ENABLE_ADDR, (REG_PL_RD(NXMAC_TX_RX_INT_ENABLE_ADDR) & ~((uint32_t)0x00000001)) | ((uint32_t)ac0prottrigger << 0)); +} + +/// @} + +/** + * @name TIMERS_INT_EVENT_SET register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     09           absTimers9   0
+ *     08           absTimers8   0
+ *     07           absTimers7   0
+ *     06           absTimers6   0
+ *     05           absTimers5   0
+ *     04           absTimers4   0
+ *     03           absTimers3   0
+ *     02           absTimers2   0
+ *     01           absTimers1   0
+ *     00           absTimers0   0
+ * 
+ * + * @{ + */ + +/// Address of the TIMERS_INT_EVENT_SET register +#define NXMAC_TIMERS_INT_EVENT_SET_ADDR 0xC0008084 +/// Offset of the TIMERS_INT_EVENT_SET register from the base address +#define NXMAC_TIMERS_INT_EVENT_SET_OFFSET 0x00000084 +/// Index of the TIMERS_INT_EVENT_SET register +#define NXMAC_TIMERS_INT_EVENT_SET_INDEX 0x00000021 +/// Reset value of the TIMERS_INT_EVENT_SET register +#define NXMAC_TIMERS_INT_EVENT_SET_RESET 0x00000000 + +/** + * @brief Returns the current value of the TIMERS_INT_EVENT_SET register. + * The TIMERS_INT_EVENT_SET register will be read and its value returned. + * @return The current value of the TIMERS_INT_EVENT_SET register. + */ +__INLINE uint32_t nxmac_timers_int_event_get(void) +{ + return REG_PL_RD(NXMAC_TIMERS_INT_EVENT_SET_ADDR); +} + +/** + * @brief Sets the TIMERS_INT_EVENT_SET register to a value. + * The TIMERS_INT_EVENT_SET register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_timers_int_event_set(uint32_t value) +{ + REG_PL_WR(NXMAC_TIMERS_INT_EVENT_SET_ADDR, value); +} + +// field definitions +/// ABS_TIMERS_9 field bit +#define NXMAC_ABS_TIMERS_9_BIT ((uint32_t)0x00000200) +/// ABS_TIMERS_9 field position +#define NXMAC_ABS_TIMERS_9_POS 9 +/// ABS_TIMERS_8 field bit +#define NXMAC_ABS_TIMERS_8_BIT ((uint32_t)0x00000100) +/// ABS_TIMERS_8 field position +#define NXMAC_ABS_TIMERS_8_POS 8 +/// ABS_TIMERS_7 field bit +#define NXMAC_ABS_TIMERS_7_BIT ((uint32_t)0x00000080) +/// ABS_TIMERS_7 field position +#define NXMAC_ABS_TIMERS_7_POS 7 +/// ABS_TIMERS_6 field bit +#define NXMAC_ABS_TIMERS_6_BIT ((uint32_t)0x00000040) +/// ABS_TIMERS_6 field position +#define NXMAC_ABS_TIMERS_6_POS 6 +/// ABS_TIMERS_5 field bit +#define NXMAC_ABS_TIMERS_5_BIT ((uint32_t)0x00000020) +/// ABS_TIMERS_5 field position +#define NXMAC_ABS_TIMERS_5_POS 5 +/// ABS_TIMERS_4 field bit +#define NXMAC_ABS_TIMERS_4_BIT ((uint32_t)0x00000010) +/// ABS_TIMERS_4 field position +#define NXMAC_ABS_TIMERS_4_POS 4 +/// ABS_TIMERS_3 field bit +#define NXMAC_ABS_TIMERS_3_BIT ((uint32_t)0x00000008) +/// ABS_TIMERS_3 field position +#define NXMAC_ABS_TIMERS_3_POS 3 +/// ABS_TIMERS_2 field bit +#define NXMAC_ABS_TIMERS_2_BIT ((uint32_t)0x00000004) +/// ABS_TIMERS_2 field position +#define NXMAC_ABS_TIMERS_2_POS 2 +/// ABS_TIMERS_1 field bit +#define NXMAC_ABS_TIMERS_1_BIT ((uint32_t)0x00000002) +/// ABS_TIMERS_1 field position +#define NXMAC_ABS_TIMERS_1_POS 1 +/// ABS_TIMERS_0 field bit +#define NXMAC_ABS_TIMERS_0_BIT ((uint32_t)0x00000001) +/// ABS_TIMERS_0 field position +#define NXMAC_ABS_TIMERS_0_POS 0 + +/// ABS_TIMERS_9 field reset value +#define NXMAC_ABS_TIMERS_9_RST 0x0 +/// ABS_TIMERS_8 field reset value +#define NXMAC_ABS_TIMERS_8_RST 0x0 +/// ABS_TIMERS_7 field reset value +#define NXMAC_ABS_TIMERS_7_RST 0x0 +/// ABS_TIMERS_6 field reset value +#define NXMAC_ABS_TIMERS_6_RST 0x0 +/// ABS_TIMERS_5 field reset value +#define NXMAC_ABS_TIMERS_5_RST 0x0 +/// ABS_TIMERS_4 field reset value +#define NXMAC_ABS_TIMERS_4_RST 0x0 +/// ABS_TIMERS_3 field reset value +#define NXMAC_ABS_TIMERS_3_RST 0x0 +/// ABS_TIMERS_2 field reset value +#define NXMAC_ABS_TIMERS_2_RST 0x0 +/// ABS_TIMERS_1 field reset value +#define NXMAC_ABS_TIMERS_1_RST 0x0 +/// ABS_TIMERS_0 field reset value +#define NXMAC_ABS_TIMERS_0_RST 0x0 + +/** + * @brief Constructs a value for the TIMERS_INT_EVENT_SET register given values for its fields + * and writes the value to the register. + * + * @param[in] abstimers9 - The value to use for the absTimers9 field. + * @param[in] abstimers8 - The value to use for the absTimers8 field. + * @param[in] abstimers7 - The value to use for the absTimers7 field. + * @param[in] abstimers6 - The value to use for the absTimers6 field. + * @param[in] abstimers5 - The value to use for the absTimers5 field. + * @param[in] abstimers4 - The value to use for the absTimers4 field. + * @param[in] abstimers3 - The value to use for the absTimers3 field. + * @param[in] abstimers2 - The value to use for the absTimers2 field. + * @param[in] abstimers1 - The value to use for the absTimers1 field. + * @param[in] abstimers0 - The value to use for the absTimers0 field. + */ +__INLINE void nxmac_timers_int_event_set_pack(uint8_t abstimers9, uint8_t abstimers8, uint8_t abstimers7, uint8_t abstimers6, uint8_t abstimers5, uint8_t abstimers4, uint8_t abstimers3, uint8_t abstimers2, uint8_t abstimers1, uint8_t abstimers0) +{ + ASSERT_ERR((((uint32_t)abstimers9 << 9) & ~((uint32_t)0x00000200)) == 0); + ASSERT_ERR((((uint32_t)abstimers8 << 8) & ~((uint32_t)0x00000100)) == 0); + ASSERT_ERR((((uint32_t)abstimers7 << 7) & ~((uint32_t)0x00000080)) == 0); + ASSERT_ERR((((uint32_t)abstimers6 << 6) & ~((uint32_t)0x00000040)) == 0); + ASSERT_ERR((((uint32_t)abstimers5 << 5) & ~((uint32_t)0x00000020)) == 0); + ASSERT_ERR((((uint32_t)abstimers4 << 4) & ~((uint32_t)0x00000010)) == 0); + ASSERT_ERR((((uint32_t)abstimers3 << 3) & ~((uint32_t)0x00000008)) == 0); + ASSERT_ERR((((uint32_t)abstimers2 << 2) & ~((uint32_t)0x00000004)) == 0); + ASSERT_ERR((((uint32_t)abstimers1 << 1) & ~((uint32_t)0x00000002)) == 0); + ASSERT_ERR((((uint32_t)abstimers0 << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_TIMERS_INT_EVENT_SET_ADDR, ((uint32_t)abstimers9 << 9) | ((uint32_t)abstimers8 << 8) | ((uint32_t)abstimers7 << 7) | ((uint32_t)abstimers6 << 6) | ((uint32_t)abstimers5 << 5) | ((uint32_t)abstimers4 << 4) | ((uint32_t)abstimers3 << 3) | ((uint32_t)abstimers2 << 2) | ((uint32_t)abstimers1 << 1) | ((uint32_t)abstimers0 << 0)); +} + +/** + * @brief Unpacks TIMERS_INT_EVENT_SET's fields from current value of the TIMERS_INT_EVENT_SET register. + * + * Reads the TIMERS_INT_EVENT_SET register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] abstimers9 - Will be populated with the current value of this field from the register. + * @param[out] abstimers8 - Will be populated with the current value of this field from the register. + * @param[out] abstimers7 - Will be populated with the current value of this field from the register. + * @param[out] abstimers6 - Will be populated with the current value of this field from the register. + * @param[out] abstimers5 - Will be populated with the current value of this field from the register. + * @param[out] abstimers4 - Will be populated with the current value of this field from the register. + * @param[out] abstimers3 - Will be populated with the current value of this field from the register. + * @param[out] abstimers2 - Will be populated with the current value of this field from the register. + * @param[out] abstimers1 - Will be populated with the current value of this field from the register. + * @param[out] abstimers0 - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_timers_int_event_unpack(uint8_t *abstimers9, uint8_t *abstimers8, uint8_t *abstimers7, uint8_t *abstimers6, uint8_t *abstimers5, uint8_t *abstimers4, uint8_t *abstimers3, uint8_t *abstimers2, uint8_t *abstimers1, uint8_t *abstimers0) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMERS_INT_EVENT_SET_ADDR); + + *abstimers9 = (localVal & ((uint32_t)0x00000200)) >> 9; + *abstimers8 = (localVal & ((uint32_t)0x00000100)) >> 8; + *abstimers7 = (localVal & ((uint32_t)0x00000080)) >> 7; + *abstimers6 = (localVal & ((uint32_t)0x00000040)) >> 6; + *abstimers5 = (localVal & ((uint32_t)0x00000020)) >> 5; + *abstimers4 = (localVal & ((uint32_t)0x00000010)) >> 4; + *abstimers3 = (localVal & ((uint32_t)0x00000008)) >> 3; + *abstimers2 = (localVal & ((uint32_t)0x00000004)) >> 2; + *abstimers1 = (localVal & ((uint32_t)0x00000002)) >> 1; + *abstimers0 = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +/** + * @brief Returns the current value of the absTimers9 field in the TIMERS_INT_EVENT_SET register. + * + * The TIMERS_INT_EVENT_SET register will be read and the absTimers9 field's value will be returned. + * + * @return The current value of the absTimers9 field in the TIMERS_INT_EVENT_SET register. + */ +__INLINE uint8_t nxmac_abs_timers_9_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMERS_INT_EVENT_SET_ADDR); + return ((localVal & ((uint32_t)0x00000200)) >> 9); +} + +/** + * @brief Sets the absTimers9 field of the TIMERS_INT_EVENT_SET register. + * + * The TIMERS_INT_EVENT_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] abstimers9 - The value to set the field to. + */ +__INLINE void nxmac_abs_timers_9_setf(uint8_t abstimers9) +{ + ASSERT_ERR((((uint32_t)abstimers9 << 9) & ~((uint32_t)0x00000200)) == 0); + REG_PL_WR(NXMAC_TIMERS_INT_EVENT_SET_ADDR, (uint32_t)abstimers9 << 9); +} + +/** + * @brief Returns the current value of the absTimers8 field in the TIMERS_INT_EVENT_SET register. + * + * The TIMERS_INT_EVENT_SET register will be read and the absTimers8 field's value will be returned. + * + * @return The current value of the absTimers8 field in the TIMERS_INT_EVENT_SET register. + */ +__INLINE uint8_t nxmac_abs_timers_8_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMERS_INT_EVENT_SET_ADDR); + return ((localVal & ((uint32_t)0x00000100)) >> 8); +} + +/** + * @brief Sets the absTimers8 field of the TIMERS_INT_EVENT_SET register. + * + * The TIMERS_INT_EVENT_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] abstimers8 - The value to set the field to. + */ +__INLINE void nxmac_abs_timers_8_setf(uint8_t abstimers8) +{ + ASSERT_ERR((((uint32_t)abstimers8 << 8) & ~((uint32_t)0x00000100)) == 0); + REG_PL_WR(NXMAC_TIMERS_INT_EVENT_SET_ADDR, (uint32_t)abstimers8 << 8); +} + +/** + * @brief Returns the current value of the absTimers7 field in the TIMERS_INT_EVENT_SET register. + * + * The TIMERS_INT_EVENT_SET register will be read and the absTimers7 field's value will be returned. + * + * @return The current value of the absTimers7 field in the TIMERS_INT_EVENT_SET register. + */ +__INLINE uint8_t nxmac_abs_timers_7_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMERS_INT_EVENT_SET_ADDR); + return ((localVal & ((uint32_t)0x00000080)) >> 7); +} + +/** + * @brief Sets the absTimers7 field of the TIMERS_INT_EVENT_SET register. + * + * The TIMERS_INT_EVENT_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] abstimers7 - The value to set the field to. + */ +__INLINE void nxmac_abs_timers_7_setf(uint8_t abstimers7) +{ + ASSERT_ERR((((uint32_t)abstimers7 << 7) & ~((uint32_t)0x00000080)) == 0); + REG_PL_WR(NXMAC_TIMERS_INT_EVENT_SET_ADDR, (uint32_t)abstimers7 << 7); +} + +/** + * @brief Returns the current value of the absTimers6 field in the TIMERS_INT_EVENT_SET register. + * + * The TIMERS_INT_EVENT_SET register will be read and the absTimers6 field's value will be returned. + * + * @return The current value of the absTimers6 field in the TIMERS_INT_EVENT_SET register. + */ +__INLINE uint8_t nxmac_abs_timers_6_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMERS_INT_EVENT_SET_ADDR); + return ((localVal & ((uint32_t)0x00000040)) >> 6); +} + +/** + * @brief Sets the absTimers6 field of the TIMERS_INT_EVENT_SET register. + * + * The TIMERS_INT_EVENT_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] abstimers6 - The value to set the field to. + */ +__INLINE void nxmac_abs_timers_6_setf(uint8_t abstimers6) +{ + ASSERT_ERR((((uint32_t)abstimers6 << 6) & ~((uint32_t)0x00000040)) == 0); + REG_PL_WR(NXMAC_TIMERS_INT_EVENT_SET_ADDR, (uint32_t)abstimers6 << 6); +} + +/** + * @brief Returns the current value of the absTimers5 field in the TIMERS_INT_EVENT_SET register. + * + * The TIMERS_INT_EVENT_SET register will be read and the absTimers5 field's value will be returned. + * + * @return The current value of the absTimers5 field in the TIMERS_INT_EVENT_SET register. + */ +__INLINE uint8_t nxmac_abs_timers_5_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMERS_INT_EVENT_SET_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +/** + * @brief Sets the absTimers5 field of the TIMERS_INT_EVENT_SET register. + * + * The TIMERS_INT_EVENT_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] abstimers5 - The value to set the field to. + */ +__INLINE void nxmac_abs_timers_5_setf(uint8_t abstimers5) +{ + ASSERT_ERR((((uint32_t)abstimers5 << 5) & ~((uint32_t)0x00000020)) == 0); + REG_PL_WR(NXMAC_TIMERS_INT_EVENT_SET_ADDR, (uint32_t)abstimers5 << 5); +} + +/** + * @brief Returns the current value of the absTimers4 field in the TIMERS_INT_EVENT_SET register. + * + * The TIMERS_INT_EVENT_SET register will be read and the absTimers4 field's value will be returned. + * + * @return The current value of the absTimers4 field in the TIMERS_INT_EVENT_SET register. + */ +__INLINE uint8_t nxmac_abs_timers_4_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMERS_INT_EVENT_SET_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +/** + * @brief Sets the absTimers4 field of the TIMERS_INT_EVENT_SET register. + * + * The TIMERS_INT_EVENT_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] abstimers4 - The value to set the field to. + */ +__INLINE void nxmac_abs_timers_4_setf(uint8_t abstimers4) +{ + ASSERT_ERR((((uint32_t)abstimers4 << 4) & ~((uint32_t)0x00000010)) == 0); + REG_PL_WR(NXMAC_TIMERS_INT_EVENT_SET_ADDR, (uint32_t)abstimers4 << 4); +} + +/** + * @brief Returns the current value of the absTimers3 field in the TIMERS_INT_EVENT_SET register. + * + * The TIMERS_INT_EVENT_SET register will be read and the absTimers3 field's value will be returned. + * + * @return The current value of the absTimers3 field in the TIMERS_INT_EVENT_SET register. + */ +__INLINE uint8_t nxmac_abs_timers_3_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMERS_INT_EVENT_SET_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +/** + * @brief Sets the absTimers3 field of the TIMERS_INT_EVENT_SET register. + * + * The TIMERS_INT_EVENT_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] abstimers3 - The value to set the field to. + */ +__INLINE void nxmac_abs_timers_3_setf(uint8_t abstimers3) +{ + ASSERT_ERR((((uint32_t)abstimers3 << 3) & ~((uint32_t)0x00000008)) == 0); + REG_PL_WR(NXMAC_TIMERS_INT_EVENT_SET_ADDR, (uint32_t)abstimers3 << 3); +} + +/** + * @brief Returns the current value of the absTimers2 field in the TIMERS_INT_EVENT_SET register. + * + * The TIMERS_INT_EVENT_SET register will be read and the absTimers2 field's value will be returned. + * + * @return The current value of the absTimers2 field in the TIMERS_INT_EVENT_SET register. + */ +__INLINE uint8_t nxmac_abs_timers_2_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMERS_INT_EVENT_SET_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +/** + * @brief Sets the absTimers2 field of the TIMERS_INT_EVENT_SET register. + * + * The TIMERS_INT_EVENT_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] abstimers2 - The value to set the field to. + */ +__INLINE void nxmac_abs_timers_2_setf(uint8_t abstimers2) +{ + ASSERT_ERR((((uint32_t)abstimers2 << 2) & ~((uint32_t)0x00000004)) == 0); + REG_PL_WR(NXMAC_TIMERS_INT_EVENT_SET_ADDR, (uint32_t)abstimers2 << 2); +} + +/** + * @brief Returns the current value of the absTimers1 field in the TIMERS_INT_EVENT_SET register. + * + * The TIMERS_INT_EVENT_SET register will be read and the absTimers1 field's value will be returned. + * + * @return The current value of the absTimers1 field in the TIMERS_INT_EVENT_SET register. + */ +__INLINE uint8_t nxmac_abs_timers_1_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMERS_INT_EVENT_SET_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +/** + * @brief Sets the absTimers1 field of the TIMERS_INT_EVENT_SET register. + * + * The TIMERS_INT_EVENT_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] abstimers1 - The value to set the field to. + */ +__INLINE void nxmac_abs_timers_1_setf(uint8_t abstimers1) +{ + ASSERT_ERR((((uint32_t)abstimers1 << 1) & ~((uint32_t)0x00000002)) == 0); + REG_PL_WR(NXMAC_TIMERS_INT_EVENT_SET_ADDR, (uint32_t)abstimers1 << 1); +} + +/** + * @brief Returns the current value of the absTimers0 field in the TIMERS_INT_EVENT_SET register. + * + * The TIMERS_INT_EVENT_SET register will be read and the absTimers0 field's value will be returned. + * + * @return The current value of the absTimers0 field in the TIMERS_INT_EVENT_SET register. + */ +__INLINE uint8_t nxmac_abs_timers_0_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMERS_INT_EVENT_SET_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/** + * @brief Sets the absTimers0 field of the TIMERS_INT_EVENT_SET register. + * + * The TIMERS_INT_EVENT_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] abstimers0 - The value to set the field to. + */ +__INLINE void nxmac_abs_timers_0_setf(uint8_t abstimers0) +{ + ASSERT_ERR((((uint32_t)abstimers0 << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_TIMERS_INT_EVENT_SET_ADDR, (uint32_t)abstimers0 << 0); +} + +/// @} + +/** + * @name TIMERS_INT_EVENT_CLEAR register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     09           absTimers9   0
+ *     08           absTimers8   0
+ *     07           absTimers7   0
+ *     06           absTimers6   0
+ *     05           absTimers5   0
+ *     04           absTimers4   0
+ *     03           absTimers3   0
+ *     02           absTimers2   0
+ *     01           absTimers1   0
+ *     00           absTimers0   0
+ * 
+ * + * @{ + */ + +/// Address of the TIMERS_INT_EVENT_CLEAR register +#define NXMAC_TIMERS_INT_EVENT_CLEAR_ADDR 0xC0008088 +/// Offset of the TIMERS_INT_EVENT_CLEAR register from the base address +#define NXMAC_TIMERS_INT_EVENT_CLEAR_OFFSET 0x00000088 +/// Index of the TIMERS_INT_EVENT_CLEAR register +#define NXMAC_TIMERS_INT_EVENT_CLEAR_INDEX 0x00000022 +/// Reset value of the TIMERS_INT_EVENT_CLEAR register +#define NXMAC_TIMERS_INT_EVENT_CLEAR_RESET 0x00000000 + +/** + * @brief Sets the TIMERS_INT_EVENT_CLEAR register to a value. + * The TIMERS_INT_EVENT_CLEAR register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_timers_int_event_clear(uint32_t value) +{ + REG_PL_WR(NXMAC_TIMERS_INT_EVENT_CLEAR_ADDR, value); +} + +// fields defined in symmetrical set/clear register +/** + * @brief Constructs a value for the TIMERS_INT_EVENT_CLEAR register given values for its fields + * and writes the value to the register. + * + * @param[in] abstimers9 - The value to use for the absTimers9 field. + * @param[in] abstimers8 - The value to use for the absTimers8 field. + * @param[in] abstimers7 - The value to use for the absTimers7 field. + * @param[in] abstimers6 - The value to use for the absTimers6 field. + * @param[in] abstimers5 - The value to use for the absTimers5 field. + * @param[in] abstimers4 - The value to use for the absTimers4 field. + * @param[in] abstimers3 - The value to use for the absTimers3 field. + * @param[in] abstimers2 - The value to use for the absTimers2 field. + * @param[in] abstimers1 - The value to use for the absTimers1 field. + * @param[in] abstimers0 - The value to use for the absTimers0 field. + */ +__INLINE void nxmac_timers_int_event_clear_pack(uint8_t abstimers9, uint8_t abstimers8, uint8_t abstimers7, uint8_t abstimers6, uint8_t abstimers5, uint8_t abstimers4, uint8_t abstimers3, uint8_t abstimers2, uint8_t abstimers1, uint8_t abstimers0) +{ + ASSERT_ERR((((uint32_t)abstimers9 << 9) & ~((uint32_t)0x00000200)) == 0); + ASSERT_ERR((((uint32_t)abstimers8 << 8) & ~((uint32_t)0x00000100)) == 0); + ASSERT_ERR((((uint32_t)abstimers7 << 7) & ~((uint32_t)0x00000080)) == 0); + ASSERT_ERR((((uint32_t)abstimers6 << 6) & ~((uint32_t)0x00000040)) == 0); + ASSERT_ERR((((uint32_t)abstimers5 << 5) & ~((uint32_t)0x00000020)) == 0); + ASSERT_ERR((((uint32_t)abstimers4 << 4) & ~((uint32_t)0x00000010)) == 0); + ASSERT_ERR((((uint32_t)abstimers3 << 3) & ~((uint32_t)0x00000008)) == 0); + ASSERT_ERR((((uint32_t)abstimers2 << 2) & ~((uint32_t)0x00000004)) == 0); + ASSERT_ERR((((uint32_t)abstimers1 << 1) & ~((uint32_t)0x00000002)) == 0); + ASSERT_ERR((((uint32_t)abstimers0 << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_TIMERS_INT_EVENT_CLEAR_ADDR, ((uint32_t)abstimers9 << 9) | ((uint32_t)abstimers8 << 8) | ((uint32_t)abstimers7 << 7) | ((uint32_t)abstimers6 << 6) | ((uint32_t)abstimers5 << 5) | ((uint32_t)abstimers4 << 4) | ((uint32_t)abstimers3 << 3) | ((uint32_t)abstimers2 << 2) | ((uint32_t)abstimers1 << 1) | ((uint32_t)abstimers0 << 0)); +} + +/** + * @brief Sets the absTimers9 field of the TIMERS_INT_EVENT_CLEAR register. + * + * The TIMERS_INT_EVENT_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] abstimers9 - The value to set the field to. + */ +__INLINE void nxmac_abs_timers_9_clearf(uint8_t abstimers9) +{ + ASSERT_ERR((((uint32_t)abstimers9 << 9) & ~((uint32_t)0x00000200)) == 0); + REG_PL_WR(NXMAC_TIMERS_INT_EVENT_CLEAR_ADDR, (uint32_t)abstimers9 << 9); +} + +/** + * @brief Sets the absTimers8 field of the TIMERS_INT_EVENT_CLEAR register. + * + * The TIMERS_INT_EVENT_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] abstimers8 - The value to set the field to. + */ +__INLINE void nxmac_abs_timers_8_clearf(uint8_t abstimers8) +{ + ASSERT_ERR((((uint32_t)abstimers8 << 8) & ~((uint32_t)0x00000100)) == 0); + REG_PL_WR(NXMAC_TIMERS_INT_EVENT_CLEAR_ADDR, (uint32_t)abstimers8 << 8); +} + +/** + * @brief Sets the absTimers7 field of the TIMERS_INT_EVENT_CLEAR register. + * + * The TIMERS_INT_EVENT_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] abstimers7 - The value to set the field to. + */ +__INLINE void nxmac_abs_timers_7_clearf(uint8_t abstimers7) +{ + ASSERT_ERR((((uint32_t)abstimers7 << 7) & ~((uint32_t)0x00000080)) == 0); + REG_PL_WR(NXMAC_TIMERS_INT_EVENT_CLEAR_ADDR, (uint32_t)abstimers7 << 7); +} + +/** + * @brief Sets the absTimers6 field of the TIMERS_INT_EVENT_CLEAR register. + * + * The TIMERS_INT_EVENT_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] abstimers6 - The value to set the field to. + */ +__INLINE void nxmac_abs_timers_6_clearf(uint8_t abstimers6) +{ + ASSERT_ERR((((uint32_t)abstimers6 << 6) & ~((uint32_t)0x00000040)) == 0); + REG_PL_WR(NXMAC_TIMERS_INT_EVENT_CLEAR_ADDR, (uint32_t)abstimers6 << 6); +} + +/** + * @brief Sets the absTimers5 field of the TIMERS_INT_EVENT_CLEAR register. + * + * The TIMERS_INT_EVENT_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] abstimers5 - The value to set the field to. + */ +__INLINE void nxmac_abs_timers_5_clearf(uint8_t abstimers5) +{ + ASSERT_ERR((((uint32_t)abstimers5 << 5) & ~((uint32_t)0x00000020)) == 0); + REG_PL_WR(NXMAC_TIMERS_INT_EVENT_CLEAR_ADDR, (uint32_t)abstimers5 << 5); +} + +/** + * @brief Sets the absTimers4 field of the TIMERS_INT_EVENT_CLEAR register. + * + * The TIMERS_INT_EVENT_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] abstimers4 - The value to set the field to. + */ +__INLINE void nxmac_abs_timers_4_clearf(uint8_t abstimers4) +{ + ASSERT_ERR((((uint32_t)abstimers4 << 4) & ~((uint32_t)0x00000010)) == 0); + REG_PL_WR(NXMAC_TIMERS_INT_EVENT_CLEAR_ADDR, (uint32_t)abstimers4 << 4); +} + +/** + * @brief Sets the absTimers3 field of the TIMERS_INT_EVENT_CLEAR register. + * + * The TIMERS_INT_EVENT_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] abstimers3 - The value to set the field to. + */ +__INLINE void nxmac_abs_timers_3_clearf(uint8_t abstimers3) +{ + ASSERT_ERR((((uint32_t)abstimers3 << 3) & ~((uint32_t)0x00000008)) == 0); + REG_PL_WR(NXMAC_TIMERS_INT_EVENT_CLEAR_ADDR, (uint32_t)abstimers3 << 3); +} + +/** + * @brief Sets the absTimers2 field of the TIMERS_INT_EVENT_CLEAR register. + * + * The TIMERS_INT_EVENT_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] abstimers2 - The value to set the field to. + */ +__INLINE void nxmac_abs_timers_2_clearf(uint8_t abstimers2) +{ + ASSERT_ERR((((uint32_t)abstimers2 << 2) & ~((uint32_t)0x00000004)) == 0); + REG_PL_WR(NXMAC_TIMERS_INT_EVENT_CLEAR_ADDR, (uint32_t)abstimers2 << 2); +} + +/** + * @brief Sets the absTimers1 field of the TIMERS_INT_EVENT_CLEAR register. + * + * The TIMERS_INT_EVENT_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] abstimers1 - The value to set the field to. + */ +__INLINE void nxmac_abs_timers_1_clearf(uint8_t abstimers1) +{ + ASSERT_ERR((((uint32_t)abstimers1 << 1) & ~((uint32_t)0x00000002)) == 0); + REG_PL_WR(NXMAC_TIMERS_INT_EVENT_CLEAR_ADDR, (uint32_t)abstimers1 << 1); +} + +/** + * @brief Sets the absTimers0 field of the TIMERS_INT_EVENT_CLEAR register. + * + * The TIMERS_INT_EVENT_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] abstimers0 - The value to set the field to. + */ +__INLINE void nxmac_abs_timers_0_clearf(uint8_t abstimers0) +{ + ASSERT_ERR((((uint32_t)abstimers0 << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_TIMERS_INT_EVENT_CLEAR_ADDR, (uint32_t)abstimers0 << 0); +} + +/// @} + +/** + * @name TIMERS_INT_UN_MASK register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     09       maskabsTimers9   0
+ *     08       maskabsTimers8   0
+ *     07       maskabsTimers7   0
+ *     06       maskabsTimers6   0
+ *     05       maskabsTimers5   0
+ *     04       maskabsTimers4   0
+ *     03       maskabsTimers3   0
+ *     02       maskabsTimers2   0
+ *     01       maskabsTimers1   0
+ *     00       maskabsTimers0   0
+ * 
+ * + * @{ + */ + +/// Address of the TIMERS_INT_UN_MASK register +#define NXMAC_TIMERS_INT_UN_MASK_ADDR 0xC000808C +/// Offset of the TIMERS_INT_UN_MASK register from the base address +#define NXMAC_TIMERS_INT_UN_MASK_OFFSET 0x0000008C +/// Index of the TIMERS_INT_UN_MASK register +#define NXMAC_TIMERS_INT_UN_MASK_INDEX 0x00000023 +/// Reset value of the TIMERS_INT_UN_MASK register +#define NXMAC_TIMERS_INT_UN_MASK_RESET 0x00000000 + +/** + * @brief Returns the current value of the TIMERS_INT_UN_MASK register. + * The TIMERS_INT_UN_MASK register will be read and its value returned. + * @return The current value of the TIMERS_INT_UN_MASK register. + */ +__INLINE uint32_t nxmac_timers_int_un_mask_get(void) +{ + return REG_PL_RD(NXMAC_TIMERS_INT_UN_MASK_ADDR); +} + +/** + * @brief Sets the TIMERS_INT_UN_MASK register to a value. + * The TIMERS_INT_UN_MASK register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_timers_int_un_mask_set(uint32_t value) +{ + REG_PL_WR(NXMAC_TIMERS_INT_UN_MASK_ADDR, value); +} + +extern void rwnxl_set_nxmac_timer_value_set_bit(uint32_t bit); +extern void rwnxl_set_nxmac_timer_value_clear_bit(uint32_t bit); +extern UINT32 nxmac_timer_saved; +__INLINE void nxmac_timers_int_un_mask_set_bit(uint32_t bit) +{ + uint32_t timer_msk; + + ///bk_printf("[%d]:%d %d\r\n",bit,nxmac_timer_saved,__LINE__); + timer_msk = nxmac_timers_int_un_mask_get(); + nxmac_timers_int_un_mask_set(timer_msk | bit); + rwnxl_set_nxmac_timer_value_set_bit(bit); +} +__INLINE void nxmac_timers_int_un_mask_clear_bit(uint32_t bit) +{ + uint32_t timer_msk; + + ///bk_printf("[%d]:%d %d\r\n",bit,nxmac_timer_saved,__LINE__); + timer_msk = nxmac_timers_int_un_mask_get(); + nxmac_timers_int_un_mask_set(timer_msk & (~ bit)); + rwnxl_set_nxmac_timer_value_clear_bit(bit); +} + + +// field definitions +/// MASKABS_TIMERS_9 field bit +#define NXMAC_MASKABS_TIMERS_9_BIT ((uint32_t)0x00000200) +/// MASKABS_TIMERS_9 field position +#define NXMAC_MASKABS_TIMERS_9_POS 9 +/// MASKABS_TIMERS_8 field bit +#define NXMAC_MASKABS_TIMERS_8_BIT ((uint32_t)0x00000100) +/// MASKABS_TIMERS_8 field position +#define NXMAC_MASKABS_TIMERS_8_POS 8 +/// MASKABS_TIMERS_7 field bit +#define NXMAC_MASKABS_TIMERS_7_BIT ((uint32_t)0x00000080) +/// MASKABS_TIMERS_7 field position +#define NXMAC_MASKABS_TIMERS_7_POS 7 +/// MASKABS_TIMERS_6 field bit +#define NXMAC_MASKABS_TIMERS_6_BIT ((uint32_t)0x00000040) +/// MASKABS_TIMERS_6 field position +#define NXMAC_MASKABS_TIMERS_6_POS 6 +/// MASKABS_TIMERS_5 field bit +#define NXMAC_MASKABS_TIMERS_5_BIT ((uint32_t)0x00000020) +/// MASKABS_TIMERS_5 field position +#define NXMAC_MASKABS_TIMERS_5_POS 5 +/// MASKABS_TIMERS_4 field bit +#define NXMAC_MASKABS_TIMERS_4_BIT ((uint32_t)0x00000010) +/// MASKABS_TIMERS_4 field position +#define NXMAC_MASKABS_TIMERS_4_POS 4 +/// MASKABS_TIMERS_3 field bit +#define NXMAC_MASKABS_TIMERS_3_BIT ((uint32_t)0x00000008) +/// MASKABS_TIMERS_3 field position +#define NXMAC_MASKABS_TIMERS_3_POS 3 +/// MASKABS_TIMERS_2 field bit +#define NXMAC_MASKABS_TIMERS_2_BIT ((uint32_t)0x00000004) +/// MASKABS_TIMERS_2 field position +#define NXMAC_MASKABS_TIMERS_2_POS 2 +/// MASKABS_TIMERS_1 field bit +#define NXMAC_MASKABS_TIMERS_1_BIT ((uint32_t)0x00000002) +/// MASKABS_TIMERS_1 field position +#define NXMAC_MASKABS_TIMERS_1_POS 1 +/// MASKABS_TIMERS_0 field bit +#define NXMAC_MASKABS_TIMERS_0_BIT ((uint32_t)0x00000001) +/// MASKABS_TIMERS_0 field position +#define NXMAC_MASKABS_TIMERS_0_POS 0 + +/// MASKABS_TIMERS_9 field reset value +#define NXMAC_MASKABS_TIMERS_9_RST 0x0 +/// MASKABS_TIMERS_8 field reset value +#define NXMAC_MASKABS_TIMERS_8_RST 0x0 +/// MASKABS_TIMERS_7 field reset value +#define NXMAC_MASKABS_TIMERS_7_RST 0x0 +/// MASKABS_TIMERS_6 field reset value +#define NXMAC_MASKABS_TIMERS_6_RST 0x0 +/// MASKABS_TIMERS_5 field reset value +#define NXMAC_MASKABS_TIMERS_5_RST 0x0 +/// MASKABS_TIMERS_4 field reset value +#define NXMAC_MASKABS_TIMERS_4_RST 0x0 +/// MASKABS_TIMERS_3 field reset value +#define NXMAC_MASKABS_TIMERS_3_RST 0x0 +/// MASKABS_TIMERS_2 field reset value +#define NXMAC_MASKABS_TIMERS_2_RST 0x0 +/// MASKABS_TIMERS_1 field reset value +#define NXMAC_MASKABS_TIMERS_1_RST 0x0 +/// MASKABS_TIMERS_0 field reset value +#define NXMAC_MASKABS_TIMERS_0_RST 0x0 + +/** + * @brief Constructs a value for the TIMERS_INT_UN_MASK register given values for its fields + * and writes the value to the register. + * + * @param[in] maskabstimers9 - The value to use for the maskabsTimers9 field. + * @param[in] maskabstimers8 - The value to use for the maskabsTimers8 field. + * @param[in] maskabstimers7 - The value to use for the maskabsTimers7 field. + * @param[in] maskabstimers6 - The value to use for the maskabsTimers6 field. + * @param[in] maskabstimers5 - The value to use for the maskabsTimers5 field. + * @param[in] maskabstimers4 - The value to use for the maskabsTimers4 field. + * @param[in] maskabstimers3 - The value to use for the maskabsTimers3 field. + * @param[in] maskabstimers2 - The value to use for the maskabsTimers2 field. + * @param[in] maskabstimers1 - The value to use for the maskabsTimers1 field. + * @param[in] maskabstimers0 - The value to use for the maskabsTimers0 field. + */ +__INLINE void nxmac_timers_int_un_mask_pack(uint8_t maskabstimers9, uint8_t maskabstimers8, uint8_t maskabstimers7, uint8_t maskabstimers6, uint8_t maskabstimers5, uint8_t maskabstimers4, uint8_t maskabstimers3, uint8_t maskabstimers2, uint8_t maskabstimers1, uint8_t maskabstimers0) +{ + ASSERT_ERR((((uint32_t)maskabstimers9 << 9) & ~((uint32_t)0x00000200)) == 0); + ASSERT_ERR((((uint32_t)maskabstimers8 << 8) & ~((uint32_t)0x00000100)) == 0); + ASSERT_ERR((((uint32_t)maskabstimers7 << 7) & ~((uint32_t)0x00000080)) == 0); + ASSERT_ERR((((uint32_t)maskabstimers6 << 6) & ~((uint32_t)0x00000040)) == 0); + ASSERT_ERR((((uint32_t)maskabstimers5 << 5) & ~((uint32_t)0x00000020)) == 0); + ASSERT_ERR((((uint32_t)maskabstimers4 << 4) & ~((uint32_t)0x00000010)) == 0); + ASSERT_ERR((((uint32_t)maskabstimers3 << 3) & ~((uint32_t)0x00000008)) == 0); + ASSERT_ERR((((uint32_t)maskabstimers2 << 2) & ~((uint32_t)0x00000004)) == 0); + ASSERT_ERR((((uint32_t)maskabstimers1 << 1) & ~((uint32_t)0x00000002)) == 0); + ASSERT_ERR((((uint32_t)maskabstimers0 << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_TIMERS_INT_UN_MASK_ADDR, ((uint32_t)maskabstimers9 << 9) | ((uint32_t)maskabstimers8 << 8) | ((uint32_t)maskabstimers7 << 7) | ((uint32_t)maskabstimers6 << 6) | ((uint32_t)maskabstimers5 << 5) | ((uint32_t)maskabstimers4 << 4) | ((uint32_t)maskabstimers3 << 3) | ((uint32_t)maskabstimers2 << 2) | ((uint32_t)maskabstimers1 << 1) | ((uint32_t)maskabstimers0 << 0)); +} + +/** + * @brief Unpacks TIMERS_INT_UN_MASK's fields from current value of the TIMERS_INT_UN_MASK register. + * + * Reads the TIMERS_INT_UN_MASK register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] maskabstimers9 - Will be populated with the current value of this field from the register. + * @param[out] maskabstimers8 - Will be populated with the current value of this field from the register. + * @param[out] maskabstimers7 - Will be populated with the current value of this field from the register. + * @param[out] maskabstimers6 - Will be populated with the current value of this field from the register. + * @param[out] maskabstimers5 - Will be populated with the current value of this field from the register. + * @param[out] maskabstimers4 - Will be populated with the current value of this field from the register. + * @param[out] maskabstimers3 - Will be populated with the current value of this field from the register. + * @param[out] maskabstimers2 - Will be populated with the current value of this field from the register. + * @param[out] maskabstimers1 - Will be populated with the current value of this field from the register. + * @param[out] maskabstimers0 - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_timers_int_un_mask_unpack(uint8_t *maskabstimers9, uint8_t *maskabstimers8, uint8_t *maskabstimers7, uint8_t *maskabstimers6, uint8_t *maskabstimers5, uint8_t *maskabstimers4, uint8_t *maskabstimers3, uint8_t *maskabstimers2, uint8_t *maskabstimers1, uint8_t *maskabstimers0) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMERS_INT_UN_MASK_ADDR); + + *maskabstimers9 = (localVal & ((uint32_t)0x00000200)) >> 9; + *maskabstimers8 = (localVal & ((uint32_t)0x00000100)) >> 8; + *maskabstimers7 = (localVal & ((uint32_t)0x00000080)) >> 7; + *maskabstimers6 = (localVal & ((uint32_t)0x00000040)) >> 6; + *maskabstimers5 = (localVal & ((uint32_t)0x00000020)) >> 5; + *maskabstimers4 = (localVal & ((uint32_t)0x00000010)) >> 4; + *maskabstimers3 = (localVal & ((uint32_t)0x00000008)) >> 3; + *maskabstimers2 = (localVal & ((uint32_t)0x00000004)) >> 2; + *maskabstimers1 = (localVal & ((uint32_t)0x00000002)) >> 1; + *maskabstimers0 = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +/** + * @brief Returns the current value of the maskabsTimers9 field in the TIMERS_INT_UN_MASK register. + * + * The TIMERS_INT_UN_MASK register will be read and the maskabsTimers9 field's value will be returned. + * + * @return The current value of the maskabsTimers9 field in the TIMERS_INT_UN_MASK register. + */ +__INLINE uint8_t nxmac_maskabs_timers_9_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMERS_INT_UN_MASK_ADDR); + return ((localVal & ((uint32_t)0x00000200)) >> 9); +} + +/** + * @brief Sets the maskabsTimers9 field of the TIMERS_INT_UN_MASK register. + * + * The TIMERS_INT_UN_MASK register will be read, modified to contain the new field value, and written. + * + * @param[in] maskabstimers9 - The value to set the field to. + */ +__INLINE void nxmac_maskabs_timers_9_setf(uint8_t maskabstimers9) +{ + ASSERT_ERR((((uint32_t)maskabstimers9 << 9) & ~((uint32_t)0x00000200)) == 0); + REG_PL_WR(NXMAC_TIMERS_INT_UN_MASK_ADDR, (REG_PL_RD(NXMAC_TIMERS_INT_UN_MASK_ADDR) & ~((uint32_t)0x00000200)) | ((uint32_t)maskabstimers9 << 9)); +} + +/** + * @brief Returns the current value of the maskabsTimers8 field in the TIMERS_INT_UN_MASK register. + * + * The TIMERS_INT_UN_MASK register will be read and the maskabsTimers8 field's value will be returned. + * + * @return The current value of the maskabsTimers8 field in the TIMERS_INT_UN_MASK register. + */ +__INLINE uint8_t nxmac_maskabs_timers_8_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMERS_INT_UN_MASK_ADDR); + return ((localVal & ((uint32_t)0x00000100)) >> 8); +} + +/** + * @brief Sets the maskabsTimers8 field of the TIMERS_INT_UN_MASK register. + * + * The TIMERS_INT_UN_MASK register will be read, modified to contain the new field value, and written. + * + * @param[in] maskabstimers8 - The value to set the field to. + */ +__INLINE void nxmac_maskabs_timers_8_setf(uint8_t maskabstimers8) +{ + ASSERT_ERR((((uint32_t)maskabstimers8 << 8) & ~((uint32_t)0x00000100)) == 0); + REG_PL_WR(NXMAC_TIMERS_INT_UN_MASK_ADDR, (REG_PL_RD(NXMAC_TIMERS_INT_UN_MASK_ADDR) & ~((uint32_t)0x00000100)) | ((uint32_t)maskabstimers8 << 8)); +} + +/** + * @brief Returns the current value of the maskabsTimers7 field in the TIMERS_INT_UN_MASK register. + * + * The TIMERS_INT_UN_MASK register will be read and the maskabsTimers7 field's value will be returned. + * + * @return The current value of the maskabsTimers7 field in the TIMERS_INT_UN_MASK register. + */ +__INLINE uint8_t nxmac_maskabs_timers_7_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMERS_INT_UN_MASK_ADDR); + return ((localVal & ((uint32_t)0x00000080)) >> 7); +} + +/** + * @brief Sets the maskabsTimers7 field of the TIMERS_INT_UN_MASK register. + * + * The TIMERS_INT_UN_MASK register will be read, modified to contain the new field value, and written. + * + * @param[in] maskabstimers7 - The value to set the field to. + */ +__INLINE void nxmac_maskabs_timers_7_setf(uint8_t maskabstimers7) +{ + ASSERT_ERR((((uint32_t)maskabstimers7 << 7) & ~((uint32_t)0x00000080)) == 0); + REG_PL_WR(NXMAC_TIMERS_INT_UN_MASK_ADDR, (REG_PL_RD(NXMAC_TIMERS_INT_UN_MASK_ADDR) & ~((uint32_t)0x00000080)) | ((uint32_t)maskabstimers7 << 7)); +} + +/** + * @brief Returns the current value of the maskabsTimers6 field in the TIMERS_INT_UN_MASK register. + * + * The TIMERS_INT_UN_MASK register will be read and the maskabsTimers6 field's value will be returned. + * + * @return The current value of the maskabsTimers6 field in the TIMERS_INT_UN_MASK register. + */ +__INLINE uint8_t nxmac_maskabs_timers_6_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMERS_INT_UN_MASK_ADDR); + return ((localVal & ((uint32_t)0x00000040)) >> 6); +} + +/** + * @brief Sets the maskabsTimers6 field of the TIMERS_INT_UN_MASK register. + * + * The TIMERS_INT_UN_MASK register will be read, modified to contain the new field value, and written. + * + * @param[in] maskabstimers6 - The value to set the field to. + */ +__INLINE void nxmac_maskabs_timers_6_setf(uint8_t maskabstimers6) +{ + ASSERT_ERR((((uint32_t)maskabstimers6 << 6) & ~((uint32_t)0x00000040)) == 0); + REG_PL_WR(NXMAC_TIMERS_INT_UN_MASK_ADDR, (REG_PL_RD(NXMAC_TIMERS_INT_UN_MASK_ADDR) & ~((uint32_t)0x00000040)) | ((uint32_t)maskabstimers6 << 6)); +} + +/** + * @brief Returns the current value of the maskabsTimers5 field in the TIMERS_INT_UN_MASK register. + * + * The TIMERS_INT_UN_MASK register will be read and the maskabsTimers5 field's value will be returned. + * + * @return The current value of the maskabsTimers5 field in the TIMERS_INT_UN_MASK register. + */ +__INLINE uint8_t nxmac_maskabs_timers_5_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMERS_INT_UN_MASK_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +/** + * @brief Sets the maskabsTimers5 field of the TIMERS_INT_UN_MASK register. + * + * The TIMERS_INT_UN_MASK register will be read, modified to contain the new field value, and written. + * + * @param[in] maskabstimers5 - The value to set the field to. + */ +__INLINE void nxmac_maskabs_timers_5_setf(uint8_t maskabstimers5) +{ + ASSERT_ERR((((uint32_t)maskabstimers5 << 5) & ~((uint32_t)0x00000020)) == 0); + REG_PL_WR(NXMAC_TIMERS_INT_UN_MASK_ADDR, (REG_PL_RD(NXMAC_TIMERS_INT_UN_MASK_ADDR) & ~((uint32_t)0x00000020)) | ((uint32_t)maskabstimers5 << 5)); +} + +/** + * @brief Returns the current value of the maskabsTimers4 field in the TIMERS_INT_UN_MASK register. + * + * The TIMERS_INT_UN_MASK register will be read and the maskabsTimers4 field's value will be returned. + * + * @return The current value of the maskabsTimers4 field in the TIMERS_INT_UN_MASK register. + */ +__INLINE uint8_t nxmac_maskabs_timers_4_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMERS_INT_UN_MASK_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +/** + * @brief Sets the maskabsTimers4 field of the TIMERS_INT_UN_MASK register. + * + * The TIMERS_INT_UN_MASK register will be read, modified to contain the new field value, and written. + * + * @param[in] maskabstimers4 - The value to set the field to. + */ +__INLINE void nxmac_maskabs_timers_4_setf(uint8_t maskabstimers4) +{ + ASSERT_ERR((((uint32_t)maskabstimers4 << 4) & ~((uint32_t)0x00000010)) == 0); + REG_PL_WR(NXMAC_TIMERS_INT_UN_MASK_ADDR, (REG_PL_RD(NXMAC_TIMERS_INT_UN_MASK_ADDR) & ~((uint32_t)0x00000010)) | ((uint32_t)maskabstimers4 << 4)); +} + +/** + * @brief Returns the current value of the maskabsTimers3 field in the TIMERS_INT_UN_MASK register. + * + * The TIMERS_INT_UN_MASK register will be read and the maskabsTimers3 field's value will be returned. + * + * @return The current value of the maskabsTimers3 field in the TIMERS_INT_UN_MASK register. + */ +__INLINE uint8_t nxmac_maskabs_timers_3_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMERS_INT_UN_MASK_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +/** + * @brief Sets the maskabsTimers3 field of the TIMERS_INT_UN_MASK register. + * + * The TIMERS_INT_UN_MASK register will be read, modified to contain the new field value, and written. + * + * @param[in] maskabstimers3 - The value to set the field to. + */ +__INLINE void nxmac_maskabs_timers_3_setf(uint8_t maskabstimers3) +{ + ASSERT_ERR((((uint32_t)maskabstimers3 << 3) & ~((uint32_t)0x00000008)) == 0); + REG_PL_WR(NXMAC_TIMERS_INT_UN_MASK_ADDR, (REG_PL_RD(NXMAC_TIMERS_INT_UN_MASK_ADDR) & ~((uint32_t)0x00000008)) | ((uint32_t)maskabstimers3 << 3)); +} + +/** + * @brief Returns the current value of the maskabsTimers2 field in the TIMERS_INT_UN_MASK register. + * + * The TIMERS_INT_UN_MASK register will be read and the maskabsTimers2 field's value will be returned. + * + * @return The current value of the maskabsTimers2 field in the TIMERS_INT_UN_MASK register. + */ +__INLINE uint8_t nxmac_maskabs_timers_2_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMERS_INT_UN_MASK_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +/** + * @brief Sets the maskabsTimers2 field of the TIMERS_INT_UN_MASK register. + * + * The TIMERS_INT_UN_MASK register will be read, modified to contain the new field value, and written. + * + * @param[in] maskabstimers2 - The value to set the field to. + */ +__INLINE void nxmac_maskabs_timers_2_setf(uint8_t maskabstimers2) +{ + ASSERT_ERR((((uint32_t)maskabstimers2 << 2) & ~((uint32_t)0x00000004)) == 0); + REG_PL_WR(NXMAC_TIMERS_INT_UN_MASK_ADDR, (REG_PL_RD(NXMAC_TIMERS_INT_UN_MASK_ADDR) & ~((uint32_t)0x00000004)) | ((uint32_t)maskabstimers2 << 2)); +} + +/** + * @brief Returns the current value of the maskabsTimers1 field in the TIMERS_INT_UN_MASK register. + * + * The TIMERS_INT_UN_MASK register will be read and the maskabsTimers1 field's value will be returned. + * + * @return The current value of the maskabsTimers1 field in the TIMERS_INT_UN_MASK register. + */ +__INLINE uint8_t nxmac_maskabs_timers_1_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMERS_INT_UN_MASK_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +/** + * @brief Sets the maskabsTimers1 field of the TIMERS_INT_UN_MASK register. + * + * The TIMERS_INT_UN_MASK register will be read, modified to contain the new field value, and written. + * + * @param[in] maskabstimers1 - The value to set the field to. + */ +__INLINE void nxmac_maskabs_timers_1_setf(uint8_t maskabstimers1) +{ + ASSERT_ERR((((uint32_t)maskabstimers1 << 1) & ~((uint32_t)0x00000002)) == 0); + REG_PL_WR(NXMAC_TIMERS_INT_UN_MASK_ADDR, (REG_PL_RD(NXMAC_TIMERS_INT_UN_MASK_ADDR) & ~((uint32_t)0x00000002)) | ((uint32_t)maskabstimers1 << 1)); +} + +/** + * @brief Returns the current value of the maskabsTimers0 field in the TIMERS_INT_UN_MASK register. + * + * The TIMERS_INT_UN_MASK register will be read and the maskabsTimers0 field's value will be returned. + * + * @return The current value of the maskabsTimers0 field in the TIMERS_INT_UN_MASK register. + */ +__INLINE uint8_t nxmac_maskabs_timers_0_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIMERS_INT_UN_MASK_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/** + * @brief Sets the maskabsTimers0 field of the TIMERS_INT_UN_MASK register. + * + * The TIMERS_INT_UN_MASK register will be read, modified to contain the new field value, and written. + * + * @param[in] maskabstimers0 - The value to set the field to. + */ +__INLINE void nxmac_maskabs_timers_0_setf(uint8_t maskabstimers0) +{ + ASSERT_ERR((((uint32_t)maskabstimers0 << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_TIMERS_INT_UN_MASK_ADDR, (REG_PL_RD(NXMAC_TIMERS_INT_UN_MASK_ADDR) & ~((uint32_t)0x00000001)) | ((uint32_t)maskabstimers0 << 0)); +} + +/// @} + +/** + * @name TSF_LO register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00          tsfTimerLow   0x0
+ * 
+ * + * @{ + */ + +/// Address of the TSF_LO register +#define NXMAC_TSF_LO_ADDR 0xC00080A4 +/// Offset of the TSF_LO register from the base address +#define NXMAC_TSF_LO_OFFSET 0x000000A4 +/// Index of the TSF_LO register +#define NXMAC_TSF_LO_INDEX 0x00000029 +/// Reset value of the TSF_LO register +#define NXMAC_TSF_LO_RESET 0x00000000 + +/** + * @brief Returns the current value of the TSF_LO register. + * The TSF_LO register will be read and its value returned. + * @return The current value of the TSF_LO register. + */ +__INLINE uint32_t nxmac_tsf_lo_get(void) +{ + return REG_PL_RD(NXMAC_TSF_LO_ADDR); +} + +/** + * @brief Sets the TSF_LO register to a value. + * The TSF_LO register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_tsf_lo_set(uint32_t value) +{ + REG_PL_WR(NXMAC_TSF_LO_ADDR, value); +} + +// field definitions +/// TSF_TIMER_LOW field mask +#define NXMAC_TSF_TIMER_LOW_MASK ((uint32_t)0xFFFFFFFF) +/// TSF_TIMER_LOW field LSB position +#define NXMAC_TSF_TIMER_LOW_LSB 0 +/// TSF_TIMER_LOW field width +#define NXMAC_TSF_TIMER_LOW_WIDTH ((uint32_t)0x00000020) + +/// TSF_TIMER_LOW field reset value +#define NXMAC_TSF_TIMER_LOW_RST 0x0 + +/** + * @brief Returns the current value of the tsfTimerLow field in the TSF_LO register. + * + * The TSF_LO register will be read and the tsfTimerLow field's value will be returned. + * + * @return The current value of the tsfTimerLow field in the TSF_LO register. + */ +__INLINE uint32_t nxmac_tsf_timer_low_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TSF_LO_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the tsfTimerLow field of the TSF_LO register. + * + * The TSF_LO register will be read, modified to contain the new field value, and written. + * + * @param[in] tsftimerlow - The value to set the field to. + */ +__INLINE void nxmac_tsf_timer_low_setf(uint32_t tsftimerlow) +{ + ASSERT_ERR((((uint32_t)tsftimerlow << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(NXMAC_TSF_LO_ADDR, (uint32_t)tsftimerlow << 0); +} + +/// @} + +/** + * @name TSF_HI register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00         tsfTimerHigh   0x0
+ * 
+ * + * @{ + */ + +/// Address of the TSF_HI register +#define NXMAC_TSF_HI_ADDR 0xC00080A8 +/// Offset of the TSF_HI register from the base address +#define NXMAC_TSF_HI_OFFSET 0x000000A8 +/// Index of the TSF_HI register +#define NXMAC_TSF_HI_INDEX 0x0000002A +/// Reset value of the TSF_HI register +#define NXMAC_TSF_HI_RESET 0x00000000 + +/** + * @brief Returns the current value of the TSF_HI register. + * The TSF_HI register will be read and its value returned. + * @return The current value of the TSF_HI register. + */ +__INLINE uint32_t nxmac_tsf_hi_get(void) +{ + return REG_PL_RD(NXMAC_TSF_HI_ADDR); +} + +/** + * @brief Sets the TSF_HI register to a value. + * The TSF_HI register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_tsf_hi_set(uint32_t value) +{ + REG_PL_WR(NXMAC_TSF_HI_ADDR, value); +} + +// field definitions +/// TSF_TIMER_HIGH field mask +#define NXMAC_TSF_TIMER_HIGH_MASK ((uint32_t)0xFFFFFFFF) +/// TSF_TIMER_HIGH field LSB position +#define NXMAC_TSF_TIMER_HIGH_LSB 0 +/// TSF_TIMER_HIGH field width +#define NXMAC_TSF_TIMER_HIGH_WIDTH ((uint32_t)0x00000020) + +/// TSF_TIMER_HIGH field reset value +#define NXMAC_TSF_TIMER_HIGH_RST 0x0 + +/** + * @brief Returns the current value of the tsfTimerHigh field in the TSF_HI register. + * + * The TSF_HI register will be read and the tsfTimerHigh field's value will be returned. + * + * @return The current value of the tsfTimerHigh field in the TSF_HI register. + */ +__INLINE uint32_t nxmac_tsf_timer_high_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TSF_HI_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the tsfTimerHigh field of the TSF_HI register. + * + * The TSF_HI register will be read, modified to contain the new field value, and written. + * + * @param[in] tsftimerhigh - The value to set the field to. + */ +__INLINE void nxmac_tsf_timer_high_setf(uint32_t tsftimerhigh) +{ + ASSERT_ERR((((uint32_t)tsftimerhigh << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(NXMAC_TSF_HI_ADDR, (uint32_t)tsftimerhigh << 0); +} + +/// @} + +/** + * @name TIME_ON_AIR_PARAM_1 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:30             ppduSTBC   0x0
+ *  29:28        ppduNumExtnSS   0x0
+ *     27          ppduShortGI   0
+ *  26:24          ppduPreType   0x0
+ *  23:22               ppduBW   0x0
+ *  19:00           ppduLength   0x0
+ * 
+ * + * @{ + */ + +/// Address of the TIME_ON_AIR_PARAM_1 register +#define NXMAC_TIME_ON_AIR_PARAM_1_ADDR 0xC0008160 +/// Offset of the TIME_ON_AIR_PARAM_1 register from the base address +#define NXMAC_TIME_ON_AIR_PARAM_1_OFFSET 0x00000160 +/// Index of the TIME_ON_AIR_PARAM_1 register +#define NXMAC_TIME_ON_AIR_PARAM_1_INDEX 0x00000058 +/// Reset value of the TIME_ON_AIR_PARAM_1 register +#define NXMAC_TIME_ON_AIR_PARAM_1_RESET 0x00000000 + +/** + * @brief Returns the current value of the TIME_ON_AIR_PARAM_1 register. + * The TIME_ON_AIR_PARAM_1 register will be read and its value returned. + * @return The current value of the TIME_ON_AIR_PARAM_1 register. + */ +__INLINE uint32_t nxmac_time_on_air_param_1_get(void) +{ + return REG_PL_RD(NXMAC_TIME_ON_AIR_PARAM_1_ADDR); +} + +/** + * @brief Sets the TIME_ON_AIR_PARAM_1 register to a value. + * The TIME_ON_AIR_PARAM_1 register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_time_on_air_param_1_set(uint32_t value) +{ + REG_PL_WR(NXMAC_TIME_ON_AIR_PARAM_1_ADDR, value); +} + +// field definitions +/// PPDU_STBC field mask +#define NXMAC_PPDU_STBC_MASK ((uint32_t)0xC0000000) +/// PPDU_STBC field LSB position +#define NXMAC_PPDU_STBC_LSB 30 +/// PPDU_STBC field width +#define NXMAC_PPDU_STBC_WIDTH ((uint32_t)0x00000002) +/// PPDU_NUM_EXTN_SS field mask +#define NXMAC_PPDU_NUM_EXTN_SS_MASK ((uint32_t)0x30000000) +/// PPDU_NUM_EXTN_SS field LSB position +#define NXMAC_PPDU_NUM_EXTN_SS_LSB 28 +/// PPDU_NUM_EXTN_SS field width +#define NXMAC_PPDU_NUM_EXTN_SS_WIDTH ((uint32_t)0x00000002) +/// PPDU_SHORT_GI field bit +#define NXMAC_PPDU_SHORT_GI_BIT ((uint32_t)0x08000000) +/// PPDU_SHORT_GI field position +#define NXMAC_PPDU_SHORT_GI_POS 27 +/// PPDU_PRE_TYPE field mask +#define NXMAC_PPDU_PRE_TYPE_MASK ((uint32_t)0x07000000) +/// PPDU_PRE_TYPE field LSB position +#define NXMAC_PPDU_PRE_TYPE_LSB 24 +/// PPDU_PRE_TYPE field width +#define NXMAC_PPDU_PRE_TYPE_WIDTH ((uint32_t)0x00000003) +/// PPDU_BW field mask +#define NXMAC_PPDU_BW_MASK ((uint32_t)0x00C00000) +/// PPDU_BW field LSB position +#define NXMAC_PPDU_BW_LSB 22 +/// PPDU_BW field width +#define NXMAC_PPDU_BW_WIDTH ((uint32_t)0x00000002) +/// PPDU_LENGTH field mask +#define NXMAC_PPDU_LENGTH_MASK ((uint32_t)0x000FFFFF) +/// PPDU_LENGTH field LSB position +#define NXMAC_PPDU_LENGTH_LSB 0 +/// PPDU_LENGTH field width +#define NXMAC_PPDU_LENGTH_WIDTH ((uint32_t)0x00000014) + +/// PPDU_STBC field reset value +#define NXMAC_PPDU_STBC_RST 0x0 +/// PPDU_NUM_EXTN_SS field reset value +#define NXMAC_PPDU_NUM_EXTN_SS_RST 0x0 +/// PPDU_SHORT_GI field reset value +#define NXMAC_PPDU_SHORT_GI_RST 0x0 +/// PPDU_PRE_TYPE field reset value +#define NXMAC_PPDU_PRE_TYPE_RST 0x0 +/// PPDU_BW field reset value +#define NXMAC_PPDU_BW_RST 0x0 +/// PPDU_LENGTH field reset value +#define NXMAC_PPDU_LENGTH_RST 0x0 + +/** + * @brief Constructs a value for the TIME_ON_AIR_PARAM_1 register given values for its fields + * and writes the value to the register. + * + * @param[in] ppdustbc - The value to use for the ppduSTBC field. + * @param[in] ppdunumextnss - The value to use for the ppduNumExtnSS field. + * @param[in] ppdushortgi - The value to use for the ppduShortGI field. + * @param[in] ppdupretype - The value to use for the ppduPreType field. + * @param[in] ppdubw - The value to use for the ppduBW field. + * @param[in] ppdulength - The value to use for the ppduLength field. + */ +__INLINE void nxmac_time_on_air_param_1_pack(uint8_t ppdustbc, uint8_t ppdunumextnss, uint8_t ppdushortgi, uint8_t ppdupretype, uint8_t ppdubw, uint32_t ppdulength) +{ + ASSERT_ERR((((uint32_t)ppdustbc << 30) & ~((uint32_t)0xC0000000)) == 0); + ASSERT_ERR((((uint32_t)ppdunumextnss << 28) & ~((uint32_t)0x30000000)) == 0); + ASSERT_ERR((((uint32_t)ppdushortgi << 27) & ~((uint32_t)0x08000000)) == 0); + ASSERT_ERR((((uint32_t)ppdupretype << 24) & ~((uint32_t)0x07000000)) == 0); + ASSERT_ERR((((uint32_t)ppdubw << 22) & ~((uint32_t)0x00C00000)) == 0); + ASSERT_ERR((((uint32_t)ppdulength << 0) & ~((uint32_t)0x000FFFFF)) == 0); + REG_PL_WR(NXMAC_TIME_ON_AIR_PARAM_1_ADDR, ((uint32_t)ppdustbc << 30) | ((uint32_t)ppdunumextnss << 28) | ((uint32_t)ppdushortgi << 27) | ((uint32_t)ppdupretype << 24) | ((uint32_t)ppdubw << 22) | ((uint32_t)ppdulength << 0)); +} + +/** + * @brief Unpacks TIME_ON_AIR_PARAM_1's fields from current value of the TIME_ON_AIR_PARAM_1 register. + * + * Reads the TIME_ON_AIR_PARAM_1 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] ppdustbc - Will be populated with the current value of this field from the register. + * @param[out] ppdunumextnss - Will be populated with the current value of this field from the register. + * @param[out] ppdushortgi - Will be populated with the current value of this field from the register. + * @param[out] ppdupretype - Will be populated with the current value of this field from the register. + * @param[out] ppdubw - Will be populated with the current value of this field from the register. + * @param[out] ppdulength - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_time_on_air_param_1_unpack(uint8_t *ppdustbc, uint8_t *ppdunumextnss, uint8_t *ppdushortgi, uint8_t *ppdupretype, uint8_t *ppdubw, uint32_t *ppdulength) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIME_ON_AIR_PARAM_1_ADDR); + + *ppdustbc = (localVal & ((uint32_t)0xC0000000)) >> 30; + *ppdunumextnss = (localVal & ((uint32_t)0x30000000)) >> 28; + *ppdushortgi = (localVal & ((uint32_t)0x08000000)) >> 27; + *ppdupretype = (localVal & ((uint32_t)0x07000000)) >> 24; + *ppdubw = (localVal & ((uint32_t)0x00C00000)) >> 22; + *ppdulength = (localVal & ((uint32_t)0x000FFFFF)) >> 0; +} + +/** + * @brief Returns the current value of the ppduSTBC field in the TIME_ON_AIR_PARAM_1 register. + * + * The TIME_ON_AIR_PARAM_1 register will be read and the ppduSTBC field's value will be returned. + * + * @return The current value of the ppduSTBC field in the TIME_ON_AIR_PARAM_1 register. + */ +__INLINE uint8_t nxmac_ppdu_stbc_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIME_ON_AIR_PARAM_1_ADDR); + return ((localVal & ((uint32_t)0xC0000000)) >> 30); +} + +/** + * @brief Sets the ppduSTBC field of the TIME_ON_AIR_PARAM_1 register. + * + * The TIME_ON_AIR_PARAM_1 register will be read, modified to contain the new field value, and written. + * + * @param[in] ppdustbc - The value to set the field to. + */ +__INLINE void nxmac_ppdu_stbc_setf(uint8_t ppdustbc) +{ + ASSERT_ERR((((uint32_t)ppdustbc << 30) & ~((uint32_t)0xC0000000)) == 0); + REG_PL_WR(NXMAC_TIME_ON_AIR_PARAM_1_ADDR, (REG_PL_RD(NXMAC_TIME_ON_AIR_PARAM_1_ADDR) & ~((uint32_t)0xC0000000)) | ((uint32_t)ppdustbc << 30)); +} + +/** + * @brief Returns the current value of the ppduNumExtnSS field in the TIME_ON_AIR_PARAM_1 register. + * + * The TIME_ON_AIR_PARAM_1 register will be read and the ppduNumExtnSS field's value will be returned. + * + * @return The current value of the ppduNumExtnSS field in the TIME_ON_AIR_PARAM_1 register. + */ +__INLINE uint8_t nxmac_ppdu_num_extn_ss_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIME_ON_AIR_PARAM_1_ADDR); + return ((localVal & ((uint32_t)0x30000000)) >> 28); +} + +/** + * @brief Sets the ppduNumExtnSS field of the TIME_ON_AIR_PARAM_1 register. + * + * The TIME_ON_AIR_PARAM_1 register will be read, modified to contain the new field value, and written. + * + * @param[in] ppdunumextnss - The value to set the field to. + */ +__INLINE void nxmac_ppdu_num_extn_ss_setf(uint8_t ppdunumextnss) +{ + ASSERT_ERR((((uint32_t)ppdunumextnss << 28) & ~((uint32_t)0x30000000)) == 0); + REG_PL_WR(NXMAC_TIME_ON_AIR_PARAM_1_ADDR, (REG_PL_RD(NXMAC_TIME_ON_AIR_PARAM_1_ADDR) & ~((uint32_t)0x30000000)) | ((uint32_t)ppdunumextnss << 28)); +} + +/** + * @brief Returns the current value of the ppduShortGI field in the TIME_ON_AIR_PARAM_1 register. + * + * The TIME_ON_AIR_PARAM_1 register will be read and the ppduShortGI field's value will be returned. + * + * @return The current value of the ppduShortGI field in the TIME_ON_AIR_PARAM_1 register. + */ +__INLINE uint8_t nxmac_ppdu_short_gi_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIME_ON_AIR_PARAM_1_ADDR); + return ((localVal & ((uint32_t)0x08000000)) >> 27); +} + +/** + * @brief Sets the ppduShortGI field of the TIME_ON_AIR_PARAM_1 register. + * + * The TIME_ON_AIR_PARAM_1 register will be read, modified to contain the new field value, and written. + * + * @param[in] ppdushortgi - The value to set the field to. + */ +__INLINE void nxmac_ppdu_short_gi_setf(uint8_t ppdushortgi) +{ + ASSERT_ERR((((uint32_t)ppdushortgi << 27) & ~((uint32_t)0x08000000)) == 0); + REG_PL_WR(NXMAC_TIME_ON_AIR_PARAM_1_ADDR, (REG_PL_RD(NXMAC_TIME_ON_AIR_PARAM_1_ADDR) & ~((uint32_t)0x08000000)) | ((uint32_t)ppdushortgi << 27)); +} + +/** + * @brief Returns the current value of the ppduPreType field in the TIME_ON_AIR_PARAM_1 register. + * + * The TIME_ON_AIR_PARAM_1 register will be read and the ppduPreType field's value will be returned. + * + * @return The current value of the ppduPreType field in the TIME_ON_AIR_PARAM_1 register. + */ +__INLINE uint8_t nxmac_ppdu_pre_type_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIME_ON_AIR_PARAM_1_ADDR); + return ((localVal & ((uint32_t)0x07000000)) >> 24); +} + +/** + * @brief Sets the ppduPreType field of the TIME_ON_AIR_PARAM_1 register. + * + * The TIME_ON_AIR_PARAM_1 register will be read, modified to contain the new field value, and written. + * + * @param[in] ppdupretype - The value to set the field to. + */ +__INLINE void nxmac_ppdu_pre_type_setf(uint8_t ppdupretype) +{ + ASSERT_ERR((((uint32_t)ppdupretype << 24) & ~((uint32_t)0x07000000)) == 0); + REG_PL_WR(NXMAC_TIME_ON_AIR_PARAM_1_ADDR, (REG_PL_RD(NXMAC_TIME_ON_AIR_PARAM_1_ADDR) & ~((uint32_t)0x07000000)) | ((uint32_t)ppdupretype << 24)); +} + +/** + * @brief Returns the current value of the ppduBW field in the TIME_ON_AIR_PARAM_1 register. + * + * The TIME_ON_AIR_PARAM_1 register will be read and the ppduBW field's value will be returned. + * + * @return The current value of the ppduBW field in the TIME_ON_AIR_PARAM_1 register. + */ +__INLINE uint8_t nxmac_ppdu_bw_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIME_ON_AIR_PARAM_1_ADDR); + return ((localVal & ((uint32_t)0x00C00000)) >> 22); +} + +/** + * @brief Sets the ppduBW field of the TIME_ON_AIR_PARAM_1 register. + * + * The TIME_ON_AIR_PARAM_1 register will be read, modified to contain the new field value, and written. + * + * @param[in] ppdubw - The value to set the field to. + */ +__INLINE void nxmac_ppdu_bw_setf(uint8_t ppdubw) +{ + ASSERT_ERR((((uint32_t)ppdubw << 22) & ~((uint32_t)0x00C00000)) == 0); + REG_PL_WR(NXMAC_TIME_ON_AIR_PARAM_1_ADDR, (REG_PL_RD(NXMAC_TIME_ON_AIR_PARAM_1_ADDR) & ~((uint32_t)0x00C00000)) | ((uint32_t)ppdubw << 22)); +} + +/** + * @brief Returns the current value of the ppduLength field in the TIME_ON_AIR_PARAM_1 register. + * + * The TIME_ON_AIR_PARAM_1 register will be read and the ppduLength field's value will be returned. + * + * @return The current value of the ppduLength field in the TIME_ON_AIR_PARAM_1 register. + */ +__INLINE uint32_t nxmac_ppdu_length_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIME_ON_AIR_PARAM_1_ADDR); + return ((localVal & ((uint32_t)0x000FFFFF)) >> 0); +} + +/** + * @brief Sets the ppduLength field of the TIME_ON_AIR_PARAM_1 register. + * + * The TIME_ON_AIR_PARAM_1 register will be read, modified to contain the new field value, and written. + * + * @param[in] ppdulength - The value to set the field to. + */ +__INLINE void nxmac_ppdu_length_setf(uint32_t ppdulength) +{ + ASSERT_ERR((((uint32_t)ppdulength << 0) & ~((uint32_t)0x000FFFFF)) == 0); + REG_PL_WR(NXMAC_TIME_ON_AIR_PARAM_1_ADDR, (REG_PL_RD(NXMAC_TIME_ON_AIR_PARAM_1_ADDR) & ~((uint32_t)0x000FFFFF)) | ((uint32_t)ppdulength << 0)); +} + +/// @} + +/** + * @name TIME_ON_AIR_PARAM_2 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  06:00         ppduMCSIndex   0x0
+ * 
+ * + * @{ + */ + +/// Address of the TIME_ON_AIR_PARAM_2 register +#define NXMAC_TIME_ON_AIR_PARAM_2_ADDR 0xC0008164 +/// Offset of the TIME_ON_AIR_PARAM_2 register from the base address +#define NXMAC_TIME_ON_AIR_PARAM_2_OFFSET 0x00000164 +/// Index of the TIME_ON_AIR_PARAM_2 register +#define NXMAC_TIME_ON_AIR_PARAM_2_INDEX 0x00000059 +/// Reset value of the TIME_ON_AIR_PARAM_2 register +#define NXMAC_TIME_ON_AIR_PARAM_2_RESET 0x00000000 + +/** + * @brief Returns the current value of the TIME_ON_AIR_PARAM_2 register. + * The TIME_ON_AIR_PARAM_2 register will be read and its value returned. + * @return The current value of the TIME_ON_AIR_PARAM_2 register. + */ +__INLINE uint32_t nxmac_time_on_air_param_2_get(void) +{ + return REG_PL_RD(NXMAC_TIME_ON_AIR_PARAM_2_ADDR); +} + +/** + * @brief Sets the TIME_ON_AIR_PARAM_2 register to a value. + * The TIME_ON_AIR_PARAM_2 register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_time_on_air_param_2_set(uint32_t value) +{ + REG_PL_WR(NXMAC_TIME_ON_AIR_PARAM_2_ADDR, value); +} + +// field definitions +/// PPDU_MCS_INDEX field mask +#define NXMAC_PPDU_MCS_INDEX_MASK ((uint32_t)0x0000007F) +/// PPDU_MCS_INDEX field LSB position +#define NXMAC_PPDU_MCS_INDEX_LSB 0 +/// PPDU_MCS_INDEX field width +#define NXMAC_PPDU_MCS_INDEX_WIDTH ((uint32_t)0x00000007) + +/// PPDU_MCS_INDEX field reset value +#define NXMAC_PPDU_MCS_INDEX_RST 0x0 + +/** + * @brief Returns the current value of the ppduMCSIndex field in the TIME_ON_AIR_PARAM_2 register. + * + * The TIME_ON_AIR_PARAM_2 register will be read and the ppduMCSIndex field's value will be returned. + * + * @return The current value of the ppduMCSIndex field in the TIME_ON_AIR_PARAM_2 register. + */ +__INLINE uint8_t nxmac_ppdu_mcs_index_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIME_ON_AIR_PARAM_2_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x0000007F)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the ppduMCSIndex field of the TIME_ON_AIR_PARAM_2 register. + * + * The TIME_ON_AIR_PARAM_2 register will be read, modified to contain the new field value, and written. + * + * @param[in] ppdumcsindex - The value to set the field to. + */ +__INLINE void nxmac_ppdu_mcs_index_setf(uint8_t ppdumcsindex) +{ + ASSERT_ERR((((uint32_t)ppdumcsindex << 0) & ~((uint32_t)0x0000007F)) == 0); + REG_PL_WR(NXMAC_TIME_ON_AIR_PARAM_2_ADDR, (uint32_t)ppdumcsindex << 0); +} + +/// @} + +/** + * @name TIME_ON_AIR_VALUE register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31      computeDuration   0
+ *     30       timeOnAirValid   0
+ *  15:00            timeOnAir   0x0
+ * 
+ * + * @{ + */ + +/// Address of the TIME_ON_AIR_VALUE register +#define NXMAC_TIME_ON_AIR_VALUE_ADDR 0xC0008168 +/// Offset of the TIME_ON_AIR_VALUE register from the base address +#define NXMAC_TIME_ON_AIR_VALUE_OFFSET 0x00000168 +/// Index of the TIME_ON_AIR_VALUE register +#define NXMAC_TIME_ON_AIR_VALUE_INDEX 0x0000005A +/// Reset value of the TIME_ON_AIR_VALUE register +#define NXMAC_TIME_ON_AIR_VALUE_RESET 0x00000000 + +/** + * @brief Returns the current value of the TIME_ON_AIR_VALUE register. + * The TIME_ON_AIR_VALUE register will be read and its value returned. + * @return The current value of the TIME_ON_AIR_VALUE register. + */ +__INLINE uint32_t nxmac_time_on_air_value_get(void) +{ + return REG_PL_RD(NXMAC_TIME_ON_AIR_VALUE_ADDR); +} + +/** + * @brief Sets the TIME_ON_AIR_VALUE register to a value. + * The TIME_ON_AIR_VALUE register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_time_on_air_value_set(uint32_t value) +{ + REG_PL_WR(NXMAC_TIME_ON_AIR_VALUE_ADDR, value); +} + +// field definitions +/// COMPUTE_DURATION field bit +#define NXMAC_COMPUTE_DURATION_BIT ((uint32_t)0x80000000) +/// COMPUTE_DURATION field position +#define NXMAC_COMPUTE_DURATION_POS 31 +/// TIME_ON_AIR_VALID field bit +#define NXMAC_TIME_ON_AIR_VALID_BIT ((uint32_t)0x40000000) +/// TIME_ON_AIR_VALID field position +#define NXMAC_TIME_ON_AIR_VALID_POS 30 +/// TIME_ON_AIR field mask +#define NXMAC_TIME_ON_AIR_MASK ((uint32_t)0x0000FFFF) +/// TIME_ON_AIR field LSB position +#define NXMAC_TIME_ON_AIR_LSB 0 +/// TIME_ON_AIR field width +#define NXMAC_TIME_ON_AIR_WIDTH ((uint32_t)0x00000010) + +/// COMPUTE_DURATION field reset value +#define NXMAC_COMPUTE_DURATION_RST 0x0 +/// TIME_ON_AIR_VALID field reset value +#define NXMAC_TIME_ON_AIR_VALID_RST 0x0 +/// TIME_ON_AIR field reset value +#define NXMAC_TIME_ON_AIR_RST 0x0 + +/** + * @brief Unpacks TIME_ON_AIR_VALUE's fields from current value of the TIME_ON_AIR_VALUE register. + * + * Reads the TIME_ON_AIR_VALUE register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] computeduration - Will be populated with the current value of this field from the register. + * @param[out] timeonairvalid - Will be populated with the current value of this field from the register. + * @param[out] timeonair - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_time_on_air_value_unpack(uint8_t *computeduration, uint8_t *timeonairvalid, uint16_t *timeonair) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIME_ON_AIR_VALUE_ADDR); + + *computeduration = (localVal & ((uint32_t)0x80000000)) >> 31; + *timeonairvalid = (localVal & ((uint32_t)0x40000000)) >> 30; + *timeonair = (localVal & ((uint32_t)0x0000FFFF)) >> 0; +} + +/** + * @brief Returns the current value of the computeDuration field in the TIME_ON_AIR_VALUE register. + * + * The TIME_ON_AIR_VALUE register will be read and the computeDuration field's value will be returned. + * + * @return The current value of the computeDuration field in the TIME_ON_AIR_VALUE register. + */ +__INLINE uint8_t nxmac_compute_duration_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIME_ON_AIR_VALUE_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +/** + * @brief Sets the computeDuration field of the TIME_ON_AIR_VALUE register. + * + * The TIME_ON_AIR_VALUE register will be read, modified to contain the new field value, and written. + * + * @param[in] computeduration - The value to set the field to. + */ +__INLINE void nxmac_compute_duration_setf(uint8_t computeduration) +{ + ASSERT_ERR((((uint32_t)computeduration << 31) & ~((uint32_t)0x80000000)) == 0); + REG_PL_WR(NXMAC_TIME_ON_AIR_VALUE_ADDR, (uint32_t)computeduration << 31); +} + +/** + * @brief Returns the current value of the timeOnAirValid field in the TIME_ON_AIR_VALUE register. + * + * The TIME_ON_AIR_VALUE register will be read and the timeOnAirValid field's value will be returned. + * + * @return The current value of the timeOnAirValid field in the TIME_ON_AIR_VALUE register. + */ +__INLINE uint8_t nxmac_time_on_air_valid_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIME_ON_AIR_VALUE_ADDR); + return ((localVal & ((uint32_t)0x40000000)) >> 30); +} + +/** + * @brief Returns the current value of the timeOnAir field in the TIME_ON_AIR_VALUE register. + * + * The TIME_ON_AIR_VALUE register will be read and the timeOnAir field's value will be returned. + * + * @return The current value of the timeOnAir field in the TIME_ON_AIR_VALUE register. + */ +__INLINE uint16_t nxmac_time_on_air_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TIME_ON_AIR_VALUE_ADDR); + return ((localVal & ((uint32_t)0x0000FFFF)) >> 0); +} + +/// @} + +/** + * @name DMA_CNTRL_SET register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     27     rxPayloadNewHead   0
+ *     26      rxHeaderNewHead   0
+ *     25     rxPayloadNewTail   0
+ *     24      rxHeaderNewTail   0
+ *     19     haltAC3AfterTXOP   0
+ *     18     haltAC2AfterTXOP   0
+ *     17     haltAC1AfterTXOP   0
+ *     16     haltAC0AfterTXOP   0
+ *     15     haltBcnAfterTXOP   0
+ *     12         txAC3NewHead   0
+ *     11         txAC2NewHead   0
+ *     10         txAC1NewHead   0
+ *     09         txAC0NewHead   0
+ *     08         txBcnNewHead   0
+ *     04         txAC3NewTail   0
+ *     03         txAC2NewTail   0
+ *     02         txAC1NewTail   0
+ *     01         txAC0NewTail   0
+ *     00         txBcnNewTail   0
+ * 
+ * + * @{ + */ + +/// Address of the DMA_CNTRL_SET register +#define NXMAC_DMA_CNTRL_SET_ADDR 0xC0008180 +/// Offset of the DMA_CNTRL_SET register from the base address +#define NXMAC_DMA_CNTRL_SET_OFFSET 0x00000180 +/// Index of the DMA_CNTRL_SET register +#define NXMAC_DMA_CNTRL_SET_INDEX 0x00000060 +/// Reset value of the DMA_CNTRL_SET register +#define NXMAC_DMA_CNTRL_SET_RESET 0x00000000 + +/** + * @brief Returns the current value of the DMA_CNTRL_SET register. + * The DMA_CNTRL_SET register will be read and its value returned. + * @return The current value of the DMA_CNTRL_SET register. + */ +__INLINE uint32_t nxmac_dma_cntrl_get(void) +{ + return REG_PL_RD(NXMAC_DMA_CNTRL_SET_ADDR); +} + +/** + * @brief Sets the DMA_CNTRL_SET register to a value. + * The DMA_CNTRL_SET register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_dma_cntrl_set(uint32_t value) +{ + REG_PL_WR(NXMAC_DMA_CNTRL_SET_ADDR, value); +} + +// field definitions +/// RX_PAYLOAD_NEW_HEAD field bit +#define NXMAC_RX_PAYLOAD_NEW_HEAD_BIT ((uint32_t)0x08000000) +/// RX_PAYLOAD_NEW_HEAD field position +#define NXMAC_RX_PAYLOAD_NEW_HEAD_POS 27 +/// RX_HEADER_NEW_HEAD field bit +#define NXMAC_RX_HEADER_NEW_HEAD_BIT ((uint32_t)0x04000000) +/// RX_HEADER_NEW_HEAD field position +#define NXMAC_RX_HEADER_NEW_HEAD_POS 26 +/// RX_PAYLOAD_NEW_TAIL field bit +#define NXMAC_RX_PAYLOAD_NEW_TAIL_BIT ((uint32_t)0x02000000) +/// RX_PAYLOAD_NEW_TAIL field position +#define NXMAC_RX_PAYLOAD_NEW_TAIL_POS 25 +/// RX_HEADER_NEW_TAIL field bit +#define NXMAC_RX_HEADER_NEW_TAIL_BIT ((uint32_t)0x01000000) +/// RX_HEADER_NEW_TAIL field position +#define NXMAC_RX_HEADER_NEW_TAIL_POS 24 +/// HALT_AC_3_AFTER_TXOP field bit +#define NXMAC_HALT_AC_3_AFTER_TXOP_BIT ((uint32_t)0x00080000) +/// HALT_AC_3_AFTER_TXOP field position +#define NXMAC_HALT_AC_3_AFTER_TXOP_POS 19 +/// HALT_AC_2_AFTER_TXOP field bit +#define NXMAC_HALT_AC_2_AFTER_TXOP_BIT ((uint32_t)0x00040000) +/// HALT_AC_2_AFTER_TXOP field position +#define NXMAC_HALT_AC_2_AFTER_TXOP_POS 18 +/// HALT_AC_1_AFTER_TXOP field bit +#define NXMAC_HALT_AC_1_AFTER_TXOP_BIT ((uint32_t)0x00020000) +/// HALT_AC_1_AFTER_TXOP field position +#define NXMAC_HALT_AC_1_AFTER_TXOP_POS 17 +/// HALT_AC_0_AFTER_TXOP field bit +#define NXMAC_HALT_AC_0_AFTER_TXOP_BIT ((uint32_t)0x00010000) +/// HALT_AC_0_AFTER_TXOP field position +#define NXMAC_HALT_AC_0_AFTER_TXOP_POS 16 +/// HALT_BCN_AFTER_TXOP field bit +#define NXMAC_HALT_BCN_AFTER_TXOP_BIT ((uint32_t)0x00008000) +/// HALT_BCN_AFTER_TXOP field position +#define NXMAC_HALT_BCN_AFTER_TXOP_POS 15 +/// TX_AC_3_NEW_HEAD field bit +#define NXMAC_TX_AC_3_NEW_HEAD_BIT ((uint32_t)0x00001000) +/// TX_AC_3_NEW_HEAD field position +#define NXMAC_TX_AC_3_NEW_HEAD_POS 12 +/// TX_AC_2_NEW_HEAD field bit +#define NXMAC_TX_AC_2_NEW_HEAD_BIT ((uint32_t)0x00000800) +/// TX_AC_2_NEW_HEAD field position +#define NXMAC_TX_AC_2_NEW_HEAD_POS 11 +/// TX_AC_1_NEW_HEAD field bit +#define NXMAC_TX_AC_1_NEW_HEAD_BIT ((uint32_t)0x00000400) +/// TX_AC_1_NEW_HEAD field position +#define NXMAC_TX_AC_1_NEW_HEAD_POS 10 +/// TX_AC_0_NEW_HEAD field bit +#define NXMAC_TX_AC_0_NEW_HEAD_BIT ((uint32_t)0x00000200) +/// TX_AC_0_NEW_HEAD field position +#define NXMAC_TX_AC_0_NEW_HEAD_POS 9 +/// TX_BCN_NEW_HEAD field bit +#define NXMAC_TX_BCN_NEW_HEAD_BIT ((uint32_t)0x00000100) +/// TX_BCN_NEW_HEAD field position +#define NXMAC_TX_BCN_NEW_HEAD_POS 8 +/// TX_AC_3_NEW_TAIL field bit +#define NXMAC_TX_AC_3_NEW_TAIL_BIT ((uint32_t)0x00000010) +/// TX_AC_3_NEW_TAIL field position +#define NXMAC_TX_AC_3_NEW_TAIL_POS 4 +/// TX_AC_2_NEW_TAIL field bit +#define NXMAC_TX_AC_2_NEW_TAIL_BIT ((uint32_t)0x00000008) +/// TX_AC_2_NEW_TAIL field position +#define NXMAC_TX_AC_2_NEW_TAIL_POS 3 +/// TX_AC_1_NEW_TAIL field bit +#define NXMAC_TX_AC_1_NEW_TAIL_BIT ((uint32_t)0x00000004) +/// TX_AC_1_NEW_TAIL field position +#define NXMAC_TX_AC_1_NEW_TAIL_POS 2 +/// TX_AC_0_NEW_TAIL field bit +#define NXMAC_TX_AC_0_NEW_TAIL_BIT ((uint32_t)0x00000002) +/// TX_AC_0_NEW_TAIL field position +#define NXMAC_TX_AC_0_NEW_TAIL_POS 1 +/// TX_BCN_NEW_TAIL field bit +#define NXMAC_TX_BCN_NEW_TAIL_BIT ((uint32_t)0x00000001) +/// TX_BCN_NEW_TAIL field position +#define NXMAC_TX_BCN_NEW_TAIL_POS 0 + +/// RX_PAYLOAD_NEW_HEAD field reset value +#define NXMAC_RX_PAYLOAD_NEW_HEAD_RST 0x0 +/// RX_HEADER_NEW_HEAD field reset value +#define NXMAC_RX_HEADER_NEW_HEAD_RST 0x0 +/// RX_PAYLOAD_NEW_TAIL field reset value +#define NXMAC_RX_PAYLOAD_NEW_TAIL_RST 0x0 +/// RX_HEADER_NEW_TAIL field reset value +#define NXMAC_RX_HEADER_NEW_TAIL_RST 0x0 +/// HALT_AC_3_AFTER_TXOP field reset value +#define NXMAC_HALT_AC_3_AFTER_TXOP_RST 0x0 +/// HALT_AC_2_AFTER_TXOP field reset value +#define NXMAC_HALT_AC_2_AFTER_TXOP_RST 0x0 +/// HALT_AC_1_AFTER_TXOP field reset value +#define NXMAC_HALT_AC_1_AFTER_TXOP_RST 0x0 +/// HALT_AC_0_AFTER_TXOP field reset value +#define NXMAC_HALT_AC_0_AFTER_TXOP_RST 0x0 +/// HALT_BCN_AFTER_TXOP field reset value +#define NXMAC_HALT_BCN_AFTER_TXOP_RST 0x0 +/// TX_AC_3_NEW_HEAD field reset value +#define NXMAC_TX_AC_3_NEW_HEAD_RST 0x0 +/// TX_AC_2_NEW_HEAD field reset value +#define NXMAC_TX_AC_2_NEW_HEAD_RST 0x0 +/// TX_AC_1_NEW_HEAD field reset value +#define NXMAC_TX_AC_1_NEW_HEAD_RST 0x0 +/// TX_AC_0_NEW_HEAD field reset value +#define NXMAC_TX_AC_0_NEW_HEAD_RST 0x0 +/// TX_BCN_NEW_HEAD field reset value +#define NXMAC_TX_BCN_NEW_HEAD_RST 0x0 +/// TX_AC_3_NEW_TAIL field reset value +#define NXMAC_TX_AC_3_NEW_TAIL_RST 0x0 +/// TX_AC_2_NEW_TAIL field reset value +#define NXMAC_TX_AC_2_NEW_TAIL_RST 0x0 +/// TX_AC_1_NEW_TAIL field reset value +#define NXMAC_TX_AC_1_NEW_TAIL_RST 0x0 +/// TX_AC_0_NEW_TAIL field reset value +#define NXMAC_TX_AC_0_NEW_TAIL_RST 0x0 +/// TX_BCN_NEW_TAIL field reset value +#define NXMAC_TX_BCN_NEW_TAIL_RST 0x0 + +/** + * @brief Constructs a value for the DMA_CNTRL_SET register given values for its fields + * and writes the value to the register. + * + * @param[in] rxpayloadnewhead - The value to use for the rxPayloadNewHead field. + * @param[in] rxheadernewhead - The value to use for the rxHeaderNewHead field. + * @param[in] rxpayloadnewtail - The value to use for the rxPayloadNewTail field. + * @param[in] rxheadernewtail - The value to use for the rxHeaderNewTail field. + * @param[in] haltac3aftertxop - The value to use for the haltAC3AfterTXOP field. + * @param[in] haltac2aftertxop - The value to use for the haltAC2AfterTXOP field. + * @param[in] haltac1aftertxop - The value to use for the haltAC1AfterTXOP field. + * @param[in] haltac0aftertxop - The value to use for the haltAC0AfterTXOP field. + * @param[in] haltbcnaftertxop - The value to use for the haltBcnAfterTXOP field. + * @param[in] txac3newhead - The value to use for the txAC3NewHead field. + * @param[in] txac2newhead - The value to use for the txAC2NewHead field. + * @param[in] txac1newhead - The value to use for the txAC1NewHead field. + * @param[in] txac0newhead - The value to use for the txAC0NewHead field. + * @param[in] txbcnnewhead - The value to use for the txBcnNewHead field. + * @param[in] txac3newtail - The value to use for the txAC3NewTail field. + * @param[in] txac2newtail - The value to use for the txAC2NewTail field. + * @param[in] txac1newtail - The value to use for the txAC1NewTail field. + * @param[in] txac0newtail - The value to use for the txAC0NewTail field. + * @param[in] txbcnnewtail - The value to use for the txBcnNewTail field. + */ +__INLINE void nxmac_dma_cntrl_set_pack(uint8_t rxpayloadnewhead, uint8_t rxheadernewhead, uint8_t rxpayloadnewtail, uint8_t rxheadernewtail, uint8_t haltac3aftertxop, uint8_t haltac2aftertxop, uint8_t haltac1aftertxop, uint8_t haltac0aftertxop, uint8_t haltbcnaftertxop, uint8_t txac3newhead, uint8_t txac2newhead, uint8_t txac1newhead, uint8_t txac0newhead, uint8_t txbcnnewhead, uint8_t txac3newtail, uint8_t txac2newtail, uint8_t txac1newtail, uint8_t txac0newtail, uint8_t txbcnnewtail) +{ + ASSERT_ERR((((uint32_t)rxpayloadnewhead << 27) & ~((uint32_t)0x08000000)) == 0); + ASSERT_ERR((((uint32_t)rxheadernewhead << 26) & ~((uint32_t)0x04000000)) == 0); + ASSERT_ERR((((uint32_t)rxpayloadnewtail << 25) & ~((uint32_t)0x02000000)) == 0); + ASSERT_ERR((((uint32_t)rxheadernewtail << 24) & ~((uint32_t)0x01000000)) == 0); + ASSERT_ERR((((uint32_t)haltac3aftertxop << 19) & ~((uint32_t)0x00080000)) == 0); + ASSERT_ERR((((uint32_t)haltac2aftertxop << 18) & ~((uint32_t)0x00040000)) == 0); + ASSERT_ERR((((uint32_t)haltac1aftertxop << 17) & ~((uint32_t)0x00020000)) == 0); + ASSERT_ERR((((uint32_t)haltac0aftertxop << 16) & ~((uint32_t)0x00010000)) == 0); + ASSERT_ERR((((uint32_t)haltbcnaftertxop << 15) & ~((uint32_t)0x00008000)) == 0); + ASSERT_ERR((((uint32_t)txac3newhead << 12) & ~((uint32_t)0x00001000)) == 0); + ASSERT_ERR((((uint32_t)txac2newhead << 11) & ~((uint32_t)0x00000800)) == 0); + ASSERT_ERR((((uint32_t)txac1newhead << 10) & ~((uint32_t)0x00000400)) == 0); + ASSERT_ERR((((uint32_t)txac0newhead << 9) & ~((uint32_t)0x00000200)) == 0); + ASSERT_ERR((((uint32_t)txbcnnewhead << 8) & ~((uint32_t)0x00000100)) == 0); + ASSERT_ERR((((uint32_t)txac3newtail << 4) & ~((uint32_t)0x00000010)) == 0); + ASSERT_ERR((((uint32_t)txac2newtail << 3) & ~((uint32_t)0x00000008)) == 0); + ASSERT_ERR((((uint32_t)txac1newtail << 2) & ~((uint32_t)0x00000004)) == 0); + ASSERT_ERR((((uint32_t)txac0newtail << 1) & ~((uint32_t)0x00000002)) == 0); + ASSERT_ERR((((uint32_t)txbcnnewtail << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_DMA_CNTRL_SET_ADDR, ((uint32_t)rxpayloadnewhead << 27) | ((uint32_t)rxheadernewhead << 26) | ((uint32_t)rxpayloadnewtail << 25) | ((uint32_t)rxheadernewtail << 24) | ((uint32_t)haltac3aftertxop << 19) | ((uint32_t)haltac2aftertxop << 18) | ((uint32_t)haltac1aftertxop << 17) | ((uint32_t)haltac0aftertxop << 16) | ((uint32_t)haltbcnaftertxop << 15) | ((uint32_t)txac3newhead << 12) | ((uint32_t)txac2newhead << 11) | ((uint32_t)txac1newhead << 10) | ((uint32_t)txac0newhead << 9) | ((uint32_t)txbcnnewhead << 8) | ((uint32_t)txac3newtail << 4) | ((uint32_t)txac2newtail << 3) | ((uint32_t)txac1newtail << 2) | ((uint32_t)txac0newtail << 1) | ((uint32_t)txbcnnewtail << 0)); +} + +/** + * @brief Unpacks DMA_CNTRL_SET's fields from current value of the DMA_CNTRL_SET register. + * + * Reads the DMA_CNTRL_SET register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] rxpayloadnewhead - Will be populated with the current value of this field from the register. + * @param[out] rxheadernewhead - Will be populated with the current value of this field from the register. + * @param[out] rxpayloadnewtail - Will be populated with the current value of this field from the register. + * @param[out] rxheadernewtail - Will be populated with the current value of this field from the register. + * @param[out] haltac3aftertxop - Will be populated with the current value of this field from the register. + * @param[out] haltac2aftertxop - Will be populated with the current value of this field from the register. + * @param[out] haltac1aftertxop - Will be populated with the current value of this field from the register. + * @param[out] haltac0aftertxop - Will be populated with the current value of this field from the register. + * @param[out] haltbcnaftertxop - Will be populated with the current value of this field from the register. + * @param[out] txac3newhead - Will be populated with the current value of this field from the register. + * @param[out] txac2newhead - Will be populated with the current value of this field from the register. + * @param[out] txac1newhead - Will be populated with the current value of this field from the register. + * @param[out] txac0newhead - Will be populated with the current value of this field from the register. + * @param[out] txbcnnewhead - Will be populated with the current value of this field from the register. + * @param[out] txac3newtail - Will be populated with the current value of this field from the register. + * @param[out] txac2newtail - Will be populated with the current value of this field from the register. + * @param[out] txac1newtail - Will be populated with the current value of this field from the register. + * @param[out] txac0newtail - Will be populated with the current value of this field from the register. + * @param[out] txbcnnewtail - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_dma_cntrl_unpack(uint8_t *rxpayloadnewhead, uint8_t *rxheadernewhead, uint8_t *rxpayloadnewtail, uint8_t *rxheadernewtail, uint8_t *haltac3aftertxop, uint8_t *haltac2aftertxop, uint8_t *haltac1aftertxop, uint8_t *haltac0aftertxop, uint8_t *haltbcnaftertxop, uint8_t *txac3newhead, uint8_t *txac2newhead, uint8_t *txac1newhead, uint8_t *txac0newhead, uint8_t *txbcnnewhead, uint8_t *txac3newtail, uint8_t *txac2newtail, uint8_t *txac1newtail, uint8_t *txac0newtail, uint8_t *txbcnnewtail) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_CNTRL_SET_ADDR); + + *rxpayloadnewhead = (localVal & ((uint32_t)0x08000000)) >> 27; + *rxheadernewhead = (localVal & ((uint32_t)0x04000000)) >> 26; + *rxpayloadnewtail = (localVal & ((uint32_t)0x02000000)) >> 25; + *rxheadernewtail = (localVal & ((uint32_t)0x01000000)) >> 24; + *haltac3aftertxop = (localVal & ((uint32_t)0x00080000)) >> 19; + *haltac2aftertxop = (localVal & ((uint32_t)0x00040000)) >> 18; + *haltac1aftertxop = (localVal & ((uint32_t)0x00020000)) >> 17; + *haltac0aftertxop = (localVal & ((uint32_t)0x00010000)) >> 16; + *haltbcnaftertxop = (localVal & ((uint32_t)0x00008000)) >> 15; + *txac3newhead = (localVal & ((uint32_t)0x00001000)) >> 12; + *txac2newhead = (localVal & ((uint32_t)0x00000800)) >> 11; + *txac1newhead = (localVal & ((uint32_t)0x00000400)) >> 10; + *txac0newhead = (localVal & ((uint32_t)0x00000200)) >> 9; + *txbcnnewhead = (localVal & ((uint32_t)0x00000100)) >> 8; + *txac3newtail = (localVal & ((uint32_t)0x00000010)) >> 4; + *txac2newtail = (localVal & ((uint32_t)0x00000008)) >> 3; + *txac1newtail = (localVal & ((uint32_t)0x00000004)) >> 2; + *txac0newtail = (localVal & ((uint32_t)0x00000002)) >> 1; + *txbcnnewtail = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +/** + * @brief Returns the current value of the rxPayloadNewHead field in the DMA_CNTRL_SET register. + * + * The DMA_CNTRL_SET register will be read and the rxPayloadNewHead field's value will be returned. + * + * @return The current value of the rxPayloadNewHead field in the DMA_CNTRL_SET register. + */ +__INLINE uint8_t nxmac_rx_payload_new_head_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_CNTRL_SET_ADDR); + return ((localVal & ((uint32_t)0x08000000)) >> 27); +} + +/** + * @brief Sets the rxPayloadNewHead field of the DMA_CNTRL_SET register. + * + * The DMA_CNTRL_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] rxpayloadnewhead - The value to set the field to. + */ +__INLINE void nxmac_rx_payload_new_head_setf(uint8_t rxpayloadnewhead) +{ + ASSERT_ERR((((uint32_t)rxpayloadnewhead << 27) & ~((uint32_t)0x08000000)) == 0); + REG_PL_WR(NXMAC_DMA_CNTRL_SET_ADDR, (uint32_t)rxpayloadnewhead << 27); +} + +/** + * @brief Returns the current value of the rxHeaderNewHead field in the DMA_CNTRL_SET register. + * + * The DMA_CNTRL_SET register will be read and the rxHeaderNewHead field's value will be returned. + * + * @return The current value of the rxHeaderNewHead field in the DMA_CNTRL_SET register. + */ +__INLINE uint8_t nxmac_rx_header_new_head_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_CNTRL_SET_ADDR); + return ((localVal & ((uint32_t)0x04000000)) >> 26); +} + +/** + * @brief Sets the rxHeaderNewHead field of the DMA_CNTRL_SET register. + * + * The DMA_CNTRL_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] rxheadernewhead - The value to set the field to. + */ +__INLINE void nxmac_rx_header_new_head_setf(uint8_t rxheadernewhead) +{ + ASSERT_ERR((((uint32_t)rxheadernewhead << 26) & ~((uint32_t)0x04000000)) == 0); + REG_PL_WR(NXMAC_DMA_CNTRL_SET_ADDR, (uint32_t)rxheadernewhead << 26); +} + +/** + * @brief Returns the current value of the rxPayloadNewTail field in the DMA_CNTRL_SET register. + * + * The DMA_CNTRL_SET register will be read and the rxPayloadNewTail field's value will be returned. + * + * @return The current value of the rxPayloadNewTail field in the DMA_CNTRL_SET register. + */ +__INLINE uint8_t nxmac_rx_payload_new_tail_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_CNTRL_SET_ADDR); + return ((localVal & ((uint32_t)0x02000000)) >> 25); +} + +/** + * @brief Sets the rxPayloadNewTail field of the DMA_CNTRL_SET register. + * + * The DMA_CNTRL_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] rxpayloadnewtail - The value to set the field to. + */ +__INLINE void nxmac_rx_payload_new_tail_setf(uint8_t rxpayloadnewtail) +{ + ASSERT_ERR((((uint32_t)rxpayloadnewtail << 25) & ~((uint32_t)0x02000000)) == 0); + REG_PL_WR(NXMAC_DMA_CNTRL_SET_ADDR, (uint32_t)rxpayloadnewtail << 25); +} + +/** + * @brief Returns the current value of the rxHeaderNewTail field in the DMA_CNTRL_SET register. + * + * The DMA_CNTRL_SET register will be read and the rxHeaderNewTail field's value will be returned. + * + * @return The current value of the rxHeaderNewTail field in the DMA_CNTRL_SET register. + */ +__INLINE uint8_t nxmac_rx_header_new_tail_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_CNTRL_SET_ADDR); + return ((localVal & ((uint32_t)0x01000000)) >> 24); +} + +/** + * @brief Sets the rxHeaderNewTail field of the DMA_CNTRL_SET register. + * + * The DMA_CNTRL_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] rxheadernewtail - The value to set the field to. + */ +__INLINE void nxmac_rx_header_new_tail_setf(uint8_t rxheadernewtail) +{ + ASSERT_ERR((((uint32_t)rxheadernewtail << 24) & ~((uint32_t)0x01000000)) == 0); + REG_PL_WR(NXMAC_DMA_CNTRL_SET_ADDR, (uint32_t)rxheadernewtail << 24); +} + +/** + * @brief Returns the current value of the haltAC3AfterTXOP field in the DMA_CNTRL_SET register. + * + * The DMA_CNTRL_SET register will be read and the haltAC3AfterTXOP field's value will be returned. + * + * @return The current value of the haltAC3AfterTXOP field in the DMA_CNTRL_SET register. + */ +__INLINE uint8_t nxmac_halt_ac_3_after_txop_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_CNTRL_SET_ADDR); + return ((localVal & ((uint32_t)0x00080000)) >> 19); +} + +/** + * @brief Sets the haltAC3AfterTXOP field of the DMA_CNTRL_SET register. + * + * The DMA_CNTRL_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] haltac3aftertxop - The value to set the field to. + */ +__INLINE void nxmac_halt_ac_3_after_txop_setf(uint8_t haltac3aftertxop) +{ + ASSERT_ERR((((uint32_t)haltac3aftertxop << 19) & ~((uint32_t)0x00080000)) == 0); + REG_PL_WR(NXMAC_DMA_CNTRL_SET_ADDR, (uint32_t)haltac3aftertxop << 19); +} + +/** + * @brief Returns the current value of the haltAC2AfterTXOP field in the DMA_CNTRL_SET register. + * + * The DMA_CNTRL_SET register will be read and the haltAC2AfterTXOP field's value will be returned. + * + * @return The current value of the haltAC2AfterTXOP field in the DMA_CNTRL_SET register. + */ +__INLINE uint8_t nxmac_halt_ac_2_after_txop_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_CNTRL_SET_ADDR); + return ((localVal & ((uint32_t)0x00040000)) >> 18); +} + +/** + * @brief Sets the haltAC2AfterTXOP field of the DMA_CNTRL_SET register. + * + * The DMA_CNTRL_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] haltac2aftertxop - The value to set the field to. + */ +__INLINE void nxmac_halt_ac_2_after_txop_setf(uint8_t haltac2aftertxop) +{ + ASSERT_ERR((((uint32_t)haltac2aftertxop << 18) & ~((uint32_t)0x00040000)) == 0); + REG_PL_WR(NXMAC_DMA_CNTRL_SET_ADDR, (uint32_t)haltac2aftertxop << 18); +} + +/** + * @brief Returns the current value of the haltAC1AfterTXOP field in the DMA_CNTRL_SET register. + * + * The DMA_CNTRL_SET register will be read and the haltAC1AfterTXOP field's value will be returned. + * + * @return The current value of the haltAC1AfterTXOP field in the DMA_CNTRL_SET register. + */ +__INLINE uint8_t nxmac_halt_ac_1_after_txop_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_CNTRL_SET_ADDR); + return ((localVal & ((uint32_t)0x00020000)) >> 17); +} + +/** + * @brief Sets the haltAC1AfterTXOP field of the DMA_CNTRL_SET register. + * + * The DMA_CNTRL_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] haltac1aftertxop - The value to set the field to. + */ +__INLINE void nxmac_halt_ac_1_after_txop_setf(uint8_t haltac1aftertxop) +{ + ASSERT_ERR((((uint32_t)haltac1aftertxop << 17) & ~((uint32_t)0x00020000)) == 0); + REG_PL_WR(NXMAC_DMA_CNTRL_SET_ADDR, (uint32_t)haltac1aftertxop << 17); +} + +/** + * @brief Returns the current value of the haltAC0AfterTXOP field in the DMA_CNTRL_SET register. + * + * The DMA_CNTRL_SET register will be read and the haltAC0AfterTXOP field's value will be returned. + * + * @return The current value of the haltAC0AfterTXOP field in the DMA_CNTRL_SET register. + */ +__INLINE uint8_t nxmac_halt_ac_0_after_txop_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_CNTRL_SET_ADDR); + return ((localVal & ((uint32_t)0x00010000)) >> 16); +} + +/** + * @brief Sets the haltAC0AfterTXOP field of the DMA_CNTRL_SET register. + * + * The DMA_CNTRL_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] haltac0aftertxop - The value to set the field to. + */ +__INLINE void nxmac_halt_ac_0_after_txop_setf(uint8_t haltac0aftertxop) +{ + ASSERT_ERR((((uint32_t)haltac0aftertxop << 16) & ~((uint32_t)0x00010000)) == 0); + REG_PL_WR(NXMAC_DMA_CNTRL_SET_ADDR, (uint32_t)haltac0aftertxop << 16); +} + +/** + * @brief Returns the current value of the haltBcnAfterTXOP field in the DMA_CNTRL_SET register. + * + * The DMA_CNTRL_SET register will be read and the haltBcnAfterTXOP field's value will be returned. + * + * @return The current value of the haltBcnAfterTXOP field in the DMA_CNTRL_SET register. + */ +__INLINE uint8_t nxmac_halt_bcn_after_txop_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_CNTRL_SET_ADDR); + return ((localVal & ((uint32_t)0x00008000)) >> 15); +} + +/** + * @brief Sets the haltBcnAfterTXOP field of the DMA_CNTRL_SET register. + * + * The DMA_CNTRL_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] haltbcnaftertxop - The value to set the field to. + */ +__INLINE void nxmac_halt_bcn_after_txop_setf(uint8_t haltbcnaftertxop) +{ + ASSERT_ERR((((uint32_t)haltbcnaftertxop << 15) & ~((uint32_t)0x00008000)) == 0); + REG_PL_WR(NXMAC_DMA_CNTRL_SET_ADDR, (uint32_t)haltbcnaftertxop << 15); +} + +/** + * @brief Returns the current value of the txAC3NewHead field in the DMA_CNTRL_SET register. + * + * The DMA_CNTRL_SET register will be read and the txAC3NewHead field's value will be returned. + * + * @return The current value of the txAC3NewHead field in the DMA_CNTRL_SET register. + */ +__INLINE uint8_t nxmac_tx_ac_3_new_head_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_CNTRL_SET_ADDR); + return ((localVal & ((uint32_t)0x00001000)) >> 12); +} + +/** + * @brief Sets the txAC3NewHead field of the DMA_CNTRL_SET register. + * + * The DMA_CNTRL_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] txac3newhead - The value to set the field to. + */ +__INLINE void nxmac_tx_ac_3_new_head_setf(uint8_t txac3newhead) +{ + ASSERT_ERR((((uint32_t)txac3newhead << 12) & ~((uint32_t)0x00001000)) == 0); + REG_PL_WR(NXMAC_DMA_CNTRL_SET_ADDR, (uint32_t)txac3newhead << 12); +} + +/** + * @brief Returns the current value of the txAC2NewHead field in the DMA_CNTRL_SET register. + * + * The DMA_CNTRL_SET register will be read and the txAC2NewHead field's value will be returned. + * + * @return The current value of the txAC2NewHead field in the DMA_CNTRL_SET register. + */ +__INLINE uint8_t nxmac_tx_ac_2_new_head_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_CNTRL_SET_ADDR); + return ((localVal & ((uint32_t)0x00000800)) >> 11); +} + +/** + * @brief Sets the txAC2NewHead field of the DMA_CNTRL_SET register. + * + * The DMA_CNTRL_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] txac2newhead - The value to set the field to. + */ +__INLINE void nxmac_tx_ac_2_new_head_setf(uint8_t txac2newhead) +{ + ASSERT_ERR((((uint32_t)txac2newhead << 11) & ~((uint32_t)0x00000800)) == 0); + REG_PL_WR(NXMAC_DMA_CNTRL_SET_ADDR, (uint32_t)txac2newhead << 11); +} + +/** + * @brief Returns the current value of the txAC1NewHead field in the DMA_CNTRL_SET register. + * + * The DMA_CNTRL_SET register will be read and the txAC1NewHead field's value will be returned. + * + * @return The current value of the txAC1NewHead field in the DMA_CNTRL_SET register. + */ +__INLINE uint8_t nxmac_tx_ac_1_new_head_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_CNTRL_SET_ADDR); + return ((localVal & ((uint32_t)0x00000400)) >> 10); +} + +/** + * @brief Sets the txAC1NewHead field of the DMA_CNTRL_SET register. + * + * The DMA_CNTRL_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] txac1newhead - The value to set the field to. + */ +__INLINE void nxmac_tx_ac_1_new_head_setf(uint8_t txac1newhead) +{ + ASSERT_ERR((((uint32_t)txac1newhead << 10) & ~((uint32_t)0x00000400)) == 0); + REG_PL_WR(NXMAC_DMA_CNTRL_SET_ADDR, (uint32_t)txac1newhead << 10); +} + +/** + * @brief Returns the current value of the txAC0NewHead field in the DMA_CNTRL_SET register. + * + * The DMA_CNTRL_SET register will be read and the txAC0NewHead field's value will be returned. + * + * @return The current value of the txAC0NewHead field in the DMA_CNTRL_SET register. + */ +__INLINE uint8_t nxmac_tx_ac_0_new_head_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_CNTRL_SET_ADDR); + return ((localVal & ((uint32_t)0x00000200)) >> 9); +} + +/** + * @brief Sets the txAC0NewHead field of the DMA_CNTRL_SET register. + * + * The DMA_CNTRL_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] txac0newhead - The value to set the field to. + */ +__INLINE void nxmac_tx_ac_0_new_head_setf(uint8_t txac0newhead) +{ + ASSERT_ERR((((uint32_t)txac0newhead << 9) & ~((uint32_t)0x00000200)) == 0); + REG_PL_WR(NXMAC_DMA_CNTRL_SET_ADDR, (uint32_t)txac0newhead << 9); +} + +/** + * @brief Returns the current value of the txBcnNewHead field in the DMA_CNTRL_SET register. + * + * The DMA_CNTRL_SET register will be read and the txBcnNewHead field's value will be returned. + * + * @return The current value of the txBcnNewHead field in the DMA_CNTRL_SET register. + */ +__INLINE uint8_t nxmac_tx_bcn_new_head_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_CNTRL_SET_ADDR); + return ((localVal & ((uint32_t)0x00000100)) >> 8); +} + +/** + * @brief Sets the txBcnNewHead field of the DMA_CNTRL_SET register. + * + * The DMA_CNTRL_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] txbcnnewhead - The value to set the field to. + */ +__INLINE void nxmac_tx_bcn_new_head_setf(uint8_t txbcnnewhead) +{ + ASSERT_ERR((((uint32_t)txbcnnewhead << 8) & ~((uint32_t)0x00000100)) == 0); + REG_PL_WR(NXMAC_DMA_CNTRL_SET_ADDR, (uint32_t)txbcnnewhead << 8); +} + +/** + * @brief Returns the current value of the txAC3NewTail field in the DMA_CNTRL_SET register. + * + * The DMA_CNTRL_SET register will be read and the txAC3NewTail field's value will be returned. + * + * @return The current value of the txAC3NewTail field in the DMA_CNTRL_SET register. + */ +__INLINE uint8_t nxmac_tx_ac_3_new_tail_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_CNTRL_SET_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +/** + * @brief Sets the txAC3NewTail field of the DMA_CNTRL_SET register. + * + * The DMA_CNTRL_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] txac3newtail - The value to set the field to. + */ +__INLINE void nxmac_tx_ac_3_new_tail_setf(uint8_t txac3newtail) +{ + ASSERT_ERR((((uint32_t)txac3newtail << 4) & ~((uint32_t)0x00000010)) == 0); + REG_PL_WR(NXMAC_DMA_CNTRL_SET_ADDR, (uint32_t)txac3newtail << 4); +} + +/** + * @brief Returns the current value of the txAC2NewTail field in the DMA_CNTRL_SET register. + * + * The DMA_CNTRL_SET register will be read and the txAC2NewTail field's value will be returned. + * + * @return The current value of the txAC2NewTail field in the DMA_CNTRL_SET register. + */ +__INLINE uint8_t nxmac_tx_ac_2_new_tail_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_CNTRL_SET_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +/** + * @brief Sets the txAC2NewTail field of the DMA_CNTRL_SET register. + * + * The DMA_CNTRL_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] txac2newtail - The value to set the field to. + */ +__INLINE void nxmac_tx_ac_2_new_tail_setf(uint8_t txac2newtail) +{ + ASSERT_ERR((((uint32_t)txac2newtail << 3) & ~((uint32_t)0x00000008)) == 0); + REG_PL_WR(NXMAC_DMA_CNTRL_SET_ADDR, (uint32_t)txac2newtail << 3); +} + +/** + * @brief Returns the current value of the txAC1NewTail field in the DMA_CNTRL_SET register. + * + * The DMA_CNTRL_SET register will be read and the txAC1NewTail field's value will be returned. + * + * @return The current value of the txAC1NewTail field in the DMA_CNTRL_SET register. + */ +__INLINE uint8_t nxmac_tx_ac_1_new_tail_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_CNTRL_SET_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +/** + * @brief Sets the txAC1NewTail field of the DMA_CNTRL_SET register. + * + * The DMA_CNTRL_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] txac1newtail - The value to set the field to. + */ +__INLINE void nxmac_tx_ac_1_new_tail_setf(uint8_t txac1newtail) +{ + ASSERT_ERR((((uint32_t)txac1newtail << 2) & ~((uint32_t)0x00000004)) == 0); + REG_PL_WR(NXMAC_DMA_CNTRL_SET_ADDR, (uint32_t)txac1newtail << 2); +} + +/** + * @brief Returns the current value of the txAC0NewTail field in the DMA_CNTRL_SET register. + * + * The DMA_CNTRL_SET register will be read and the txAC0NewTail field's value will be returned. + * + * @return The current value of the txAC0NewTail field in the DMA_CNTRL_SET register. + */ +__INLINE uint8_t nxmac_tx_ac_0_new_tail_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_CNTRL_SET_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +/** + * @brief Sets the txAC0NewTail field of the DMA_CNTRL_SET register. + * + * The DMA_CNTRL_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] txac0newtail - The value to set the field to. + */ +__INLINE void nxmac_tx_ac_0_new_tail_setf(uint8_t txac0newtail) +{ + ASSERT_ERR((((uint32_t)txac0newtail << 1) & ~((uint32_t)0x00000002)) == 0); + REG_PL_WR(NXMAC_DMA_CNTRL_SET_ADDR, (uint32_t)txac0newtail << 1); +} + +/** + * @brief Returns the current value of the txBcnNewTail field in the DMA_CNTRL_SET register. + * + * The DMA_CNTRL_SET register will be read and the txBcnNewTail field's value will be returned. + * + * @return The current value of the txBcnNewTail field in the DMA_CNTRL_SET register. + */ +__INLINE uint8_t nxmac_tx_bcn_new_tail_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_CNTRL_SET_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/** + * @brief Sets the txBcnNewTail field of the DMA_CNTRL_SET register. + * + * The DMA_CNTRL_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] txbcnnewtail - The value to set the field to. + */ +__INLINE void nxmac_tx_bcn_new_tail_setf(uint8_t txbcnnewtail) +{ + ASSERT_ERR((((uint32_t)txbcnnewtail << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_DMA_CNTRL_SET_ADDR, (uint32_t)txbcnnewtail << 0); +} + +/// @} + +/** + * @name DMA_CNTRL_CLEAR register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     27     rxPayloadNewHead   0
+ *     26      rxHeaderNewHead   0
+ *     25     rxPayloadNewTail   0
+ *     24      rxHeaderNewTail   0
+ *     19     haltAC3AfterTXOP   0
+ *     18     haltAC2AfterTXOP   0
+ *     17     haltAC1AfterTXOP   0
+ *     16     haltAC0AfterTXOP   0
+ *     15     haltBcnAfterTXOP   0
+ *     12         txAC3NewHead   0
+ *     11         txAC2NewHead   0
+ *     10         txAC1NewHead   0
+ *     09         txAC0NewHead   0
+ *     08         txBcnNewHead   0
+ *     04         txAC3NewTail   0
+ *     03         txAC2NewTail   0
+ *     02         txAC1NewTail   0
+ *     01         txAC0NewTail   0
+ *     00         txBcnNewTail   0
+ * 
+ * + * @{ + */ + +/// Address of the DMA_CNTRL_CLEAR register +#define NXMAC_DMA_CNTRL_CLEAR_ADDR 0xC0008184 +/// Offset of the DMA_CNTRL_CLEAR register from the base address +#define NXMAC_DMA_CNTRL_CLEAR_OFFSET 0x00000184 +/// Index of the DMA_CNTRL_CLEAR register +#define NXMAC_DMA_CNTRL_CLEAR_INDEX 0x00000061 +/// Reset value of the DMA_CNTRL_CLEAR register +#define NXMAC_DMA_CNTRL_CLEAR_RESET 0x00000000 + +/** + * @brief Sets the DMA_CNTRL_CLEAR register to a value. + * The DMA_CNTRL_CLEAR register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_dma_cntrl_clear(uint32_t value) +{ + REG_PL_WR(NXMAC_DMA_CNTRL_CLEAR_ADDR, value); +} + +// fields defined in symmetrical set/clear register +/** + * @brief Constructs a value for the DMA_CNTRL_CLEAR register given values for its fields + * and writes the value to the register. + * + * @param[in] rxpayloadnewhead - The value to use for the rxPayloadNewHead field. + * @param[in] rxheadernewhead - The value to use for the rxHeaderNewHead field. + * @param[in] rxpayloadnewtail - The value to use for the rxPayloadNewTail field. + * @param[in] rxheadernewtail - The value to use for the rxHeaderNewTail field. + * @param[in] haltac3aftertxop - The value to use for the haltAC3AfterTXOP field. + * @param[in] haltac2aftertxop - The value to use for the haltAC2AfterTXOP field. + * @param[in] haltac1aftertxop - The value to use for the haltAC1AfterTXOP field. + * @param[in] haltac0aftertxop - The value to use for the haltAC0AfterTXOP field. + * @param[in] haltbcnaftertxop - The value to use for the haltBcnAfterTXOP field. + * @param[in] txac3newhead - The value to use for the txAC3NewHead field. + * @param[in] txac2newhead - The value to use for the txAC2NewHead field. + * @param[in] txac1newhead - The value to use for the txAC1NewHead field. + * @param[in] txac0newhead - The value to use for the txAC0NewHead field. + * @param[in] txbcnnewhead - The value to use for the txBcnNewHead field. + * @param[in] txac3newtail - The value to use for the txAC3NewTail field. + * @param[in] txac2newtail - The value to use for the txAC2NewTail field. + * @param[in] txac1newtail - The value to use for the txAC1NewTail field. + * @param[in] txac0newtail - The value to use for the txAC0NewTail field. + * @param[in] txbcnnewtail - The value to use for the txBcnNewTail field. + */ +__INLINE void nxmac_dma_cntrl_clear_pack(uint8_t rxpayloadnewhead, uint8_t rxheadernewhead, uint8_t rxpayloadnewtail, uint8_t rxheadernewtail, uint8_t haltac3aftertxop, uint8_t haltac2aftertxop, uint8_t haltac1aftertxop, uint8_t haltac0aftertxop, uint8_t haltbcnaftertxop, uint8_t txac3newhead, uint8_t txac2newhead, uint8_t txac1newhead, uint8_t txac0newhead, uint8_t txbcnnewhead, uint8_t txac3newtail, uint8_t txac2newtail, uint8_t txac1newtail, uint8_t txac0newtail, uint8_t txbcnnewtail) +{ + ASSERT_ERR((((uint32_t)rxpayloadnewhead << 27) & ~((uint32_t)0x08000000)) == 0); + ASSERT_ERR((((uint32_t)rxheadernewhead << 26) & ~((uint32_t)0x04000000)) == 0); + ASSERT_ERR((((uint32_t)rxpayloadnewtail << 25) & ~((uint32_t)0x02000000)) == 0); + ASSERT_ERR((((uint32_t)rxheadernewtail << 24) & ~((uint32_t)0x01000000)) == 0); + ASSERT_ERR((((uint32_t)haltac3aftertxop << 19) & ~((uint32_t)0x00080000)) == 0); + ASSERT_ERR((((uint32_t)haltac2aftertxop << 18) & ~((uint32_t)0x00040000)) == 0); + ASSERT_ERR((((uint32_t)haltac1aftertxop << 17) & ~((uint32_t)0x00020000)) == 0); + ASSERT_ERR((((uint32_t)haltac0aftertxop << 16) & ~((uint32_t)0x00010000)) == 0); + ASSERT_ERR((((uint32_t)haltbcnaftertxop << 15) & ~((uint32_t)0x00008000)) == 0); + ASSERT_ERR((((uint32_t)txac3newhead << 12) & ~((uint32_t)0x00001000)) == 0); + ASSERT_ERR((((uint32_t)txac2newhead << 11) & ~((uint32_t)0x00000800)) == 0); + ASSERT_ERR((((uint32_t)txac1newhead << 10) & ~((uint32_t)0x00000400)) == 0); + ASSERT_ERR((((uint32_t)txac0newhead << 9) & ~((uint32_t)0x00000200)) == 0); + ASSERT_ERR((((uint32_t)txbcnnewhead << 8) & ~((uint32_t)0x00000100)) == 0); + ASSERT_ERR((((uint32_t)txac3newtail << 4) & ~((uint32_t)0x00000010)) == 0); + ASSERT_ERR((((uint32_t)txac2newtail << 3) & ~((uint32_t)0x00000008)) == 0); + ASSERT_ERR((((uint32_t)txac1newtail << 2) & ~((uint32_t)0x00000004)) == 0); + ASSERT_ERR((((uint32_t)txac0newtail << 1) & ~((uint32_t)0x00000002)) == 0); + ASSERT_ERR((((uint32_t)txbcnnewtail << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_DMA_CNTRL_CLEAR_ADDR, ((uint32_t)rxpayloadnewhead << 27) | ((uint32_t)rxheadernewhead << 26) | ((uint32_t)rxpayloadnewtail << 25) | ((uint32_t)rxheadernewtail << 24) | ((uint32_t)haltac3aftertxop << 19) | ((uint32_t)haltac2aftertxop << 18) | ((uint32_t)haltac1aftertxop << 17) | ((uint32_t)haltac0aftertxop << 16) | ((uint32_t)haltbcnaftertxop << 15) | ((uint32_t)txac3newhead << 12) | ((uint32_t)txac2newhead << 11) | ((uint32_t)txac1newhead << 10) | ((uint32_t)txac0newhead << 9) | ((uint32_t)txbcnnewhead << 8) | ((uint32_t)txac3newtail << 4) | ((uint32_t)txac2newtail << 3) | ((uint32_t)txac1newtail << 2) | ((uint32_t)txac0newtail << 1) | ((uint32_t)txbcnnewtail << 0)); +} + +/** + * @brief Sets the rxPayloadNewHead field of the DMA_CNTRL_CLEAR register. + * + * The DMA_CNTRL_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] rxpayloadnewhead - The value to set the field to. + */ +__INLINE void nxmac_rx_payload_new_head_clearf(uint8_t rxpayloadnewhead) +{ + ASSERT_ERR((((uint32_t)rxpayloadnewhead << 27) & ~((uint32_t)0x08000000)) == 0); + REG_PL_WR(NXMAC_DMA_CNTRL_CLEAR_ADDR, (uint32_t)rxpayloadnewhead << 27); +} + +/** + * @brief Sets the rxHeaderNewHead field of the DMA_CNTRL_CLEAR register. + * + * The DMA_CNTRL_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] rxheadernewhead - The value to set the field to. + */ +__INLINE void nxmac_rx_header_new_head_clearf(uint8_t rxheadernewhead) +{ + ASSERT_ERR((((uint32_t)rxheadernewhead << 26) & ~((uint32_t)0x04000000)) == 0); + REG_PL_WR(NXMAC_DMA_CNTRL_CLEAR_ADDR, (uint32_t)rxheadernewhead << 26); +} + +/** + * @brief Sets the rxPayloadNewTail field of the DMA_CNTRL_CLEAR register. + * + * The DMA_CNTRL_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] rxpayloadnewtail - The value to set the field to. + */ +__INLINE void nxmac_rx_payload_new_tail_clearf(uint8_t rxpayloadnewtail) +{ + ASSERT_ERR((((uint32_t)rxpayloadnewtail << 25) & ~((uint32_t)0x02000000)) == 0); + REG_PL_WR(NXMAC_DMA_CNTRL_CLEAR_ADDR, (uint32_t)rxpayloadnewtail << 25); +} + +/** + * @brief Sets the rxHeaderNewTail field of the DMA_CNTRL_CLEAR register. + * + * The DMA_CNTRL_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] rxheadernewtail - The value to set the field to. + */ +__INLINE void nxmac_rx_header_new_tail_clearf(uint8_t rxheadernewtail) +{ + ASSERT_ERR((((uint32_t)rxheadernewtail << 24) & ~((uint32_t)0x01000000)) == 0); + REG_PL_WR(NXMAC_DMA_CNTRL_CLEAR_ADDR, (uint32_t)rxheadernewtail << 24); +} + +/** + * @brief Sets the haltAC3AfterTXOP field of the DMA_CNTRL_CLEAR register. + * + * The DMA_CNTRL_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] haltac3aftertxop - The value to set the field to. + */ +__INLINE void nxmac_halt_ac_3_after_txop_clearf(uint8_t haltac3aftertxop) +{ + ASSERT_ERR((((uint32_t)haltac3aftertxop << 19) & ~((uint32_t)0x00080000)) == 0); + REG_PL_WR(NXMAC_DMA_CNTRL_CLEAR_ADDR, (uint32_t)haltac3aftertxop << 19); +} + +/** + * @brief Sets the haltAC2AfterTXOP field of the DMA_CNTRL_CLEAR register. + * + * The DMA_CNTRL_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] haltac2aftertxop - The value to set the field to. + */ +__INLINE void nxmac_halt_ac_2_after_txop_clearf(uint8_t haltac2aftertxop) +{ + ASSERT_ERR((((uint32_t)haltac2aftertxop << 18) & ~((uint32_t)0x00040000)) == 0); + REG_PL_WR(NXMAC_DMA_CNTRL_CLEAR_ADDR, (uint32_t)haltac2aftertxop << 18); +} + +/** + * @brief Sets the haltAC1AfterTXOP field of the DMA_CNTRL_CLEAR register. + * + * The DMA_CNTRL_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] haltac1aftertxop - The value to set the field to. + */ +__INLINE void nxmac_halt_ac_1_after_txop_clearf(uint8_t haltac1aftertxop) +{ + ASSERT_ERR((((uint32_t)haltac1aftertxop << 17) & ~((uint32_t)0x00020000)) == 0); + REG_PL_WR(NXMAC_DMA_CNTRL_CLEAR_ADDR, (uint32_t)haltac1aftertxop << 17); +} + +/** + * @brief Sets the haltAC0AfterTXOP field of the DMA_CNTRL_CLEAR register. + * + * The DMA_CNTRL_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] haltac0aftertxop - The value to set the field to. + */ +__INLINE void nxmac_halt_ac_0_after_txop_clearf(uint8_t haltac0aftertxop) +{ + ASSERT_ERR((((uint32_t)haltac0aftertxop << 16) & ~((uint32_t)0x00010000)) == 0); + REG_PL_WR(NXMAC_DMA_CNTRL_CLEAR_ADDR, (uint32_t)haltac0aftertxop << 16); +} + +/** + * @brief Sets the haltBcnAfterTXOP field of the DMA_CNTRL_CLEAR register. + * + * The DMA_CNTRL_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] haltbcnaftertxop - The value to set the field to. + */ +__INLINE void nxmac_halt_bcn_after_txop_clearf(uint8_t haltbcnaftertxop) +{ + ASSERT_ERR((((uint32_t)haltbcnaftertxop << 15) & ~((uint32_t)0x00008000)) == 0); + REG_PL_WR(NXMAC_DMA_CNTRL_CLEAR_ADDR, (uint32_t)haltbcnaftertxop << 15); +} + +/** + * @brief Sets the txAC3NewHead field of the DMA_CNTRL_CLEAR register. + * + * The DMA_CNTRL_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] txac3newhead - The value to set the field to. + */ +__INLINE void nxmac_tx_ac_3_new_head_clearf(uint8_t txac3newhead) +{ + ASSERT_ERR((((uint32_t)txac3newhead << 12) & ~((uint32_t)0x00001000)) == 0); + REG_PL_WR(NXMAC_DMA_CNTRL_CLEAR_ADDR, (uint32_t)txac3newhead << 12); +} + +/** + * @brief Sets the txAC2NewHead field of the DMA_CNTRL_CLEAR register. + * + * The DMA_CNTRL_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] txac2newhead - The value to set the field to. + */ +__INLINE void nxmac_tx_ac_2_new_head_clearf(uint8_t txac2newhead) +{ + ASSERT_ERR((((uint32_t)txac2newhead << 11) & ~((uint32_t)0x00000800)) == 0); + REG_PL_WR(NXMAC_DMA_CNTRL_CLEAR_ADDR, (uint32_t)txac2newhead << 11); +} + +/** + * @brief Sets the txAC1NewHead field of the DMA_CNTRL_CLEAR register. + * + * The DMA_CNTRL_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] txac1newhead - The value to set the field to. + */ +__INLINE void nxmac_tx_ac_1_new_head_clearf(uint8_t txac1newhead) +{ + ASSERT_ERR((((uint32_t)txac1newhead << 10) & ~((uint32_t)0x00000400)) == 0); + REG_PL_WR(NXMAC_DMA_CNTRL_CLEAR_ADDR, (uint32_t)txac1newhead << 10); +} + +/** + * @brief Sets the txAC0NewHead field of the DMA_CNTRL_CLEAR register. + * + * The DMA_CNTRL_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] txac0newhead - The value to set the field to. + */ +__INLINE void nxmac_tx_ac_0_new_head_clearf(uint8_t txac0newhead) +{ + ASSERT_ERR((((uint32_t)txac0newhead << 9) & ~((uint32_t)0x00000200)) == 0); + REG_PL_WR(NXMAC_DMA_CNTRL_CLEAR_ADDR, (uint32_t)txac0newhead << 9); +} + +/** + * @brief Sets the txBcnNewHead field of the DMA_CNTRL_CLEAR register. + * + * The DMA_CNTRL_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] txbcnnewhead - The value to set the field to. + */ +__INLINE void nxmac_tx_bcn_new_head_clearf(uint8_t txbcnnewhead) +{ + ASSERT_ERR((((uint32_t)txbcnnewhead << 8) & ~((uint32_t)0x00000100)) == 0); + REG_PL_WR(NXMAC_DMA_CNTRL_CLEAR_ADDR, (uint32_t)txbcnnewhead << 8); +} + +/** + * @brief Sets the txAC3NewTail field of the DMA_CNTRL_CLEAR register. + * + * The DMA_CNTRL_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] txac3newtail - The value to set the field to. + */ +__INLINE void nxmac_tx_ac_3_new_tail_clearf(uint8_t txac3newtail) +{ + ASSERT_ERR((((uint32_t)txac3newtail << 4) & ~((uint32_t)0x00000010)) == 0); + REG_PL_WR(NXMAC_DMA_CNTRL_CLEAR_ADDR, (uint32_t)txac3newtail << 4); +} + +/** + * @brief Sets the txAC2NewTail field of the DMA_CNTRL_CLEAR register. + * + * The DMA_CNTRL_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] txac2newtail - The value to set the field to. + */ +__INLINE void nxmac_tx_ac_2_new_tail_clearf(uint8_t txac2newtail) +{ + ASSERT_ERR((((uint32_t)txac2newtail << 3) & ~((uint32_t)0x00000008)) == 0); + REG_PL_WR(NXMAC_DMA_CNTRL_CLEAR_ADDR, (uint32_t)txac2newtail << 3); +} + +/** + * @brief Sets the txAC1NewTail field of the DMA_CNTRL_CLEAR register. + * + * The DMA_CNTRL_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] txac1newtail - The value to set the field to. + */ +__INLINE void nxmac_tx_ac_1_new_tail_clearf(uint8_t txac1newtail) +{ + ASSERT_ERR((((uint32_t)txac1newtail << 2) & ~((uint32_t)0x00000004)) == 0); + REG_PL_WR(NXMAC_DMA_CNTRL_CLEAR_ADDR, (uint32_t)txac1newtail << 2); +} + +/** + * @brief Sets the txAC0NewTail field of the DMA_CNTRL_CLEAR register. + * + * The DMA_CNTRL_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] txac0newtail - The value to set the field to. + */ +__INLINE void nxmac_tx_ac_0_new_tail_clearf(uint8_t txac0newtail) +{ + ASSERT_ERR((((uint32_t)txac0newtail << 1) & ~((uint32_t)0x00000002)) == 0); + REG_PL_WR(NXMAC_DMA_CNTRL_CLEAR_ADDR, (uint32_t)txac0newtail << 1); +} + +/** + * @brief Sets the txBcnNewTail field of the DMA_CNTRL_CLEAR register. + * + * The DMA_CNTRL_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] txbcnnewtail - The value to set the field to. + */ +__INLINE void nxmac_tx_bcn_new_tail_clearf(uint8_t txbcnnewtail) +{ + ASSERT_ERR((((uint32_t)txbcnnewtail << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_DMA_CNTRL_CLEAR_ADDR, (uint32_t)txbcnnewtail << 0); +} + +/// @} + +/** + * @name DMA_STATUS_1 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  29:28       rxPayloadState   0x0
+ *  25:24        rxHeaderState   0x0
+ *  17:16           txAC3State   0x0
+ *  13:12           txAC2State   0x0
+ *  09:08           txAC1State   0x0
+ *  05:04           txAC0State   0x0
+ *  01:00           txBcnState   0x0
+ * 
+ * + * @{ + */ + +/// Address of the DMA_STATUS_1 register +#define NXMAC_DMA_STATUS_1_ADDR 0xC0008188 +/// Offset of the DMA_STATUS_1 register from the base address +#define NXMAC_DMA_STATUS_1_OFFSET 0x00000188 +/// Index of the DMA_STATUS_1 register +#define NXMAC_DMA_STATUS_1_INDEX 0x00000062 +/// Reset value of the DMA_STATUS_1 register +#define NXMAC_DMA_STATUS_1_RESET 0x00000000 + +/** + * @brief Returns the current value of the DMA_STATUS_1 register. + * The DMA_STATUS_1 register will be read and its value returned. + * @return The current value of the DMA_STATUS_1 register. + */ +__INLINE uint32_t nxmac_dma_status_1_get(void) +{ + return REG_PL_RD(NXMAC_DMA_STATUS_1_ADDR); +} + +// field definitions +/// RX_PAYLOAD_STATE field mask +#define NXMAC_RX_PAYLOAD_STATE_MASK ((uint32_t)0x30000000) +/// RX_PAYLOAD_STATE field LSB position +#define NXMAC_RX_PAYLOAD_STATE_LSB 28 +/// RX_PAYLOAD_STATE field width +#define NXMAC_RX_PAYLOAD_STATE_WIDTH ((uint32_t)0x00000002) +/// RX_HEADER_STATE field mask +#define NXMAC_RX_HEADER_STATE_MASK ((uint32_t)0x03000000) +/// RX_HEADER_STATE field LSB position +#define NXMAC_RX_HEADER_STATE_LSB 24 +/// RX_HEADER_STATE field width +#define NXMAC_RX_HEADER_STATE_WIDTH ((uint32_t)0x00000002) +/// TX_AC_3_STATE field mask +#define NXMAC_TX_AC_3_STATE_MASK ((uint32_t)0x00030000) +/// TX_AC_3_STATE field LSB position +#define NXMAC_TX_AC_3_STATE_LSB 16 +/// TX_AC_3_STATE field width +#define NXMAC_TX_AC_3_STATE_WIDTH ((uint32_t)0x00000002) +/// TX_AC_2_STATE field mask +#define NXMAC_TX_AC_2_STATE_MASK ((uint32_t)0x00003000) +/// TX_AC_2_STATE field LSB position +#define NXMAC_TX_AC_2_STATE_LSB 12 +/// TX_AC_2_STATE field width +#define NXMAC_TX_AC_2_STATE_WIDTH ((uint32_t)0x00000002) +/// TX_AC_1_STATE field mask +#define NXMAC_TX_AC_1_STATE_MASK ((uint32_t)0x00000300) +/// TX_AC_1_STATE field LSB position +#define NXMAC_TX_AC_1_STATE_LSB 8 +/// TX_AC_1_STATE field width +#define NXMAC_TX_AC_1_STATE_WIDTH ((uint32_t)0x00000002) +/// TX_AC_0_STATE field mask +#define NXMAC_TX_AC_0_STATE_MASK ((uint32_t)0x00000030) +/// TX_AC_0_STATE field LSB position +#define NXMAC_TX_AC_0_STATE_LSB 4 +/// TX_AC_0_STATE field width +#define NXMAC_TX_AC_0_STATE_WIDTH ((uint32_t)0x00000002) +/// TX_BCN_STATE field mask +#define NXMAC_TX_BCN_STATE_MASK ((uint32_t)0x00000003) +/// TX_BCN_STATE field LSB position +#define NXMAC_TX_BCN_STATE_LSB 0 +/// TX_BCN_STATE field width +#define NXMAC_TX_BCN_STATE_WIDTH ((uint32_t)0x00000002) + +/// RX_PAYLOAD_STATE field reset value +#define NXMAC_RX_PAYLOAD_STATE_RST 0x0 +/// RX_HEADER_STATE field reset value +#define NXMAC_RX_HEADER_STATE_RST 0x0 +/// TX_AC_3_STATE field reset value +#define NXMAC_TX_AC_3_STATE_RST 0x0 +/// TX_AC_2_STATE field reset value +#define NXMAC_TX_AC_2_STATE_RST 0x0 +/// TX_AC_1_STATE field reset value +#define NXMAC_TX_AC_1_STATE_RST 0x0 +/// TX_AC_0_STATE field reset value +#define NXMAC_TX_AC_0_STATE_RST 0x0 +/// TX_BCN_STATE field reset value +#define NXMAC_TX_BCN_STATE_RST 0x0 + +/** + * @brief Unpacks DMA_STATUS_1's fields from current value of the DMA_STATUS_1 register. + * + * Reads the DMA_STATUS_1 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] rxpayloadstate - Will be populated with the current value of this field from the register. + * @param[out] rxheaderstate - Will be populated with the current value of this field from the register. + * @param[out] txac3state - Will be populated with the current value of this field from the register. + * @param[out] txac2state - Will be populated with the current value of this field from the register. + * @param[out] txac1state - Will be populated with the current value of this field from the register. + * @param[out] txac0state - Will be populated with the current value of this field from the register. + * @param[out] txbcnstate - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_dma_status_1_unpack(uint8_t *rxpayloadstate, uint8_t *rxheaderstate, uint8_t *txac3state, uint8_t *txac2state, uint8_t *txac1state, uint8_t *txac0state, uint8_t *txbcnstate) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_1_ADDR); + + *rxpayloadstate = (localVal & ((uint32_t)0x30000000)) >> 28; + *rxheaderstate = (localVal & ((uint32_t)0x03000000)) >> 24; + *txac3state = (localVal & ((uint32_t)0x00030000)) >> 16; + *txac2state = (localVal & ((uint32_t)0x00003000)) >> 12; + *txac1state = (localVal & ((uint32_t)0x00000300)) >> 8; + *txac0state = (localVal & ((uint32_t)0x00000030)) >> 4; + *txbcnstate = (localVal & ((uint32_t)0x00000003)) >> 0; +} + +/** + * @brief Returns the current value of the rxPayloadState field in the DMA_STATUS_1 register. + * + * The DMA_STATUS_1 register will be read and the rxPayloadState field's value will be returned. + * + * @return The current value of the rxPayloadState field in the DMA_STATUS_1 register. + */ +__INLINE uint8_t nxmac_rx_payload_state_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_1_ADDR); + return ((localVal & ((uint32_t)0x30000000)) >> 28); +} + +/** + * @brief Returns the current value of the rxHeaderState field in the DMA_STATUS_1 register. + * + * The DMA_STATUS_1 register will be read and the rxHeaderState field's value will be returned. + * + * @return The current value of the rxHeaderState field in the DMA_STATUS_1 register. + */ +__INLINE uint8_t nxmac_rx_header_state_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_1_ADDR); + return ((localVal & ((uint32_t)0x03000000)) >> 24); +} + +/** + * @brief Returns the current value of the txAC3State field in the DMA_STATUS_1 register. + * + * The DMA_STATUS_1 register will be read and the txAC3State field's value will be returned. + * + * @return The current value of the txAC3State field in the DMA_STATUS_1 register. + */ +__INLINE uint8_t nxmac_tx_ac_3_state_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_1_ADDR); + return ((localVal & ((uint32_t)0x00030000)) >> 16); +} + +/** + * @brief Returns the current value of the txAC2State field in the DMA_STATUS_1 register. + * + * The DMA_STATUS_1 register will be read and the txAC2State field's value will be returned. + * + * @return The current value of the txAC2State field in the DMA_STATUS_1 register. + */ +__INLINE uint8_t nxmac_tx_ac_2_state_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_1_ADDR); + return ((localVal & ((uint32_t)0x00003000)) >> 12); +} + +/** + * @brief Returns the current value of the txAC1State field in the DMA_STATUS_1 register. + * + * The DMA_STATUS_1 register will be read and the txAC1State field's value will be returned. + * + * @return The current value of the txAC1State field in the DMA_STATUS_1 register. + */ +__INLINE uint8_t nxmac_tx_ac_1_state_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_1_ADDR); + return ((localVal & ((uint32_t)0x00000300)) >> 8); +} + +/** + * @brief Returns the current value of the txAC0State field in the DMA_STATUS_1 register. + * + * The DMA_STATUS_1 register will be read and the txAC0State field's value will be returned. + * + * @return The current value of the txAC0State field in the DMA_STATUS_1 register. + */ +__INLINE uint8_t nxmac_tx_ac_0_state_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_1_ADDR); + return ((localVal & ((uint32_t)0x00000030)) >> 4); +} + +/** + * @brief Returns the current value of the txBcnState field in the DMA_STATUS_1 register. + * + * The DMA_STATUS_1 register will be read and the txBcnState field's value will be returned. + * + * @return The current value of the txBcnState field in the DMA_STATUS_1 register. + */ +__INLINE uint8_t nxmac_tx_bcn_state_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_1_ADDR); + return ((localVal & ((uint32_t)0x00000003)) >> 0); +} + +/// @} + +/** + * @name DMA_STATUS_2 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     29      txAC3NewHeadErr   0
+ *     28      txAC2NewHeadErr   0
+ *     27      txAC1NewHeadErr   0
+ *     26      txAC0NewHeadErr   0
+ *     25      txBcnNewHeadErr   0
+ *     24          txAC3BusErr   0
+ *     23          txAC2BusErr   0
+ *     22          txAC1BusErr   0
+ *     21          txAC0BusErr   0
+ *     20          txBcnBusErr   0
+ *     19    txAC3PTAddressErr   0
+ *     18    txAC2PTAddressErr   0
+ *     17    txAC1PTAddressErr   0
+ *     16    txAC0PTAddressErr   0
+ *     15    txBcnPTAddressErr   0
+ *     14   txAC3NextPointerErr   0
+ *     13   txAC2NextPointerErr   0
+ *     12   txAC1NextPointerErr   0
+ *     11   txAC0NextPointerErr   0
+ *     10   txBcnNextPointerErr   0
+ *     09     txAC3UPatternErr   0
+ *     08     txAC2UPatternErr   0
+ *     07     txAC1UPatternErr   0
+ *     06     txAC0UPatternErr   0
+ *     05     txBcnUPatternErr   0
+ *     04     txAC3LenMismatch   0
+ *     03     txAC2LenMismatch   0
+ *     02     txAC1LenMismatch   0
+ *     01     txAC0LenMismatch   0
+ *     00     txBcnLenMismatch   0
+ * 
+ * + * @{ + */ + +/// Address of the DMA_STATUS_2 register +#define NXMAC_DMA_STATUS_2_ADDR 0xC000818C +/// Offset of the DMA_STATUS_2 register from the base address +#define NXMAC_DMA_STATUS_2_OFFSET 0x0000018C +/// Index of the DMA_STATUS_2 register +#define NXMAC_DMA_STATUS_2_INDEX 0x00000063 +/// Reset value of the DMA_STATUS_2 register +#define NXMAC_DMA_STATUS_2_RESET 0x00000000 + +/** + * @brief Returns the current value of the DMA_STATUS_2 register. + * The DMA_STATUS_2 register will be read and its value returned. + * @return The current value of the DMA_STATUS_2 register. + */ +__INLINE uint32_t nxmac_dma_status_2_get(void) +{ + return REG_PL_RD(NXMAC_DMA_STATUS_2_ADDR); +} + +// field definitions +/// TX_AC_3_NEW_HEAD_ERR field bit +#define NXMAC_TX_AC_3_NEW_HEAD_ERR_BIT ((uint32_t)0x20000000) +/// TX_AC_3_NEW_HEAD_ERR field position +#define NXMAC_TX_AC_3_NEW_HEAD_ERR_POS 29 +/// TX_AC_2_NEW_HEAD_ERR field bit +#define NXMAC_TX_AC_2_NEW_HEAD_ERR_BIT ((uint32_t)0x10000000) +/// TX_AC_2_NEW_HEAD_ERR field position +#define NXMAC_TX_AC_2_NEW_HEAD_ERR_POS 28 +/// TX_AC_1_NEW_HEAD_ERR field bit +#define NXMAC_TX_AC_1_NEW_HEAD_ERR_BIT ((uint32_t)0x08000000) +/// TX_AC_1_NEW_HEAD_ERR field position +#define NXMAC_TX_AC_1_NEW_HEAD_ERR_POS 27 +/// TX_AC_0_NEW_HEAD_ERR field bit +#define NXMAC_TX_AC_0_NEW_HEAD_ERR_BIT ((uint32_t)0x04000000) +/// TX_AC_0_NEW_HEAD_ERR field position +#define NXMAC_TX_AC_0_NEW_HEAD_ERR_POS 26 +/// TX_BCN_NEW_HEAD_ERR field bit +#define NXMAC_TX_BCN_NEW_HEAD_ERR_BIT ((uint32_t)0x02000000) +/// TX_BCN_NEW_HEAD_ERR field position +#define NXMAC_TX_BCN_NEW_HEAD_ERR_POS 25 +/// TX_AC_3_BUS_ERR field bit +#define NXMAC_TX_AC_3_BUS_ERR_BIT ((uint32_t)0x01000000) +/// TX_AC_3_BUS_ERR field position +#define NXMAC_TX_AC_3_BUS_ERR_POS 24 +/// TX_AC_2_BUS_ERR field bit +#define NXMAC_TX_AC_2_BUS_ERR_BIT ((uint32_t)0x00800000) +/// TX_AC_2_BUS_ERR field position +#define NXMAC_TX_AC_2_BUS_ERR_POS 23 +/// TX_AC_1_BUS_ERR field bit +#define NXMAC_TX_AC_1_BUS_ERR_BIT ((uint32_t)0x00400000) +/// TX_AC_1_BUS_ERR field position +#define NXMAC_TX_AC_1_BUS_ERR_POS 22 +/// TX_AC_0_BUS_ERR field bit +#define NXMAC_TX_AC_0_BUS_ERR_BIT ((uint32_t)0x00200000) +/// TX_AC_0_BUS_ERR field position +#define NXMAC_TX_AC_0_BUS_ERR_POS 21 +/// TX_BCN_BUS_ERR field bit +#define NXMAC_TX_BCN_BUS_ERR_BIT ((uint32_t)0x00100000) +/// TX_BCN_BUS_ERR field position +#define NXMAC_TX_BCN_BUS_ERR_POS 20 +/// TX_AC_3PT_ADDRESS_ERR field bit +#define NXMAC_TX_AC_3PT_ADDRESS_ERR_BIT ((uint32_t)0x00080000) +/// TX_AC_3PT_ADDRESS_ERR field position +#define NXMAC_TX_AC_3PT_ADDRESS_ERR_POS 19 +/// TX_AC_2PT_ADDRESS_ERR field bit +#define NXMAC_TX_AC_2PT_ADDRESS_ERR_BIT ((uint32_t)0x00040000) +/// TX_AC_2PT_ADDRESS_ERR field position +#define NXMAC_TX_AC_2PT_ADDRESS_ERR_POS 18 +/// TX_AC_1PT_ADDRESS_ERR field bit +#define NXMAC_TX_AC_1PT_ADDRESS_ERR_BIT ((uint32_t)0x00020000) +/// TX_AC_1PT_ADDRESS_ERR field position +#define NXMAC_TX_AC_1PT_ADDRESS_ERR_POS 17 +/// TX_AC_0PT_ADDRESS_ERR field bit +#define NXMAC_TX_AC_0PT_ADDRESS_ERR_BIT ((uint32_t)0x00010000) +/// TX_AC_0PT_ADDRESS_ERR field position +#define NXMAC_TX_AC_0PT_ADDRESS_ERR_POS 16 +/// TX_BCN_PT_ADDRESS_ERR field bit +#define NXMAC_TX_BCN_PT_ADDRESS_ERR_BIT ((uint32_t)0x00008000) +/// TX_BCN_PT_ADDRESS_ERR field position +#define NXMAC_TX_BCN_PT_ADDRESS_ERR_POS 15 +/// TX_AC_3_NEXT_POINTER_ERR field bit +#define NXMAC_TX_AC_3_NEXT_POINTER_ERR_BIT ((uint32_t)0x00004000) +/// TX_AC_3_NEXT_POINTER_ERR field position +#define NXMAC_TX_AC_3_NEXT_POINTER_ERR_POS 14 +/// TX_AC_2_NEXT_POINTER_ERR field bit +#define NXMAC_TX_AC_2_NEXT_POINTER_ERR_BIT ((uint32_t)0x00002000) +/// TX_AC_2_NEXT_POINTER_ERR field position +#define NXMAC_TX_AC_2_NEXT_POINTER_ERR_POS 13 +/// TX_AC_1_NEXT_POINTER_ERR field bit +#define NXMAC_TX_AC_1_NEXT_POINTER_ERR_BIT ((uint32_t)0x00001000) +/// TX_AC_1_NEXT_POINTER_ERR field position +#define NXMAC_TX_AC_1_NEXT_POINTER_ERR_POS 12 +/// TX_AC_0_NEXT_POINTER_ERR field bit +#define NXMAC_TX_AC_0_NEXT_POINTER_ERR_BIT ((uint32_t)0x00000800) +/// TX_AC_0_NEXT_POINTER_ERR field position +#define NXMAC_TX_AC_0_NEXT_POINTER_ERR_POS 11 +/// TX_BCN_NEXT_POINTER_ERR field bit +#define NXMAC_TX_BCN_NEXT_POINTER_ERR_BIT ((uint32_t)0x00000400) +/// TX_BCN_NEXT_POINTER_ERR field position +#define NXMAC_TX_BCN_NEXT_POINTER_ERR_POS 10 +/// TX_AC_3U_PATTERN_ERR field bit +#define NXMAC_TX_AC_3U_PATTERN_ERR_BIT ((uint32_t)0x00000200) +/// TX_AC_3U_PATTERN_ERR field position +#define NXMAC_TX_AC_3U_PATTERN_ERR_POS 9 +/// TX_AC_2U_PATTERN_ERR field bit +#define NXMAC_TX_AC_2U_PATTERN_ERR_BIT ((uint32_t)0x00000100) +/// TX_AC_2U_PATTERN_ERR field position +#define NXMAC_TX_AC_2U_PATTERN_ERR_POS 8 +/// TX_AC_1U_PATTERN_ERR field bit +#define NXMAC_TX_AC_1U_PATTERN_ERR_BIT ((uint32_t)0x00000080) +/// TX_AC_1U_PATTERN_ERR field position +#define NXMAC_TX_AC_1U_PATTERN_ERR_POS 7 +/// TX_AC_0U_PATTERN_ERR field bit +#define NXMAC_TX_AC_0U_PATTERN_ERR_BIT ((uint32_t)0x00000040) +/// TX_AC_0U_PATTERN_ERR field position +#define NXMAC_TX_AC_0U_PATTERN_ERR_POS 6 +/// TX_BCN_U_PATTERN_ERR field bit +#define NXMAC_TX_BCN_U_PATTERN_ERR_BIT ((uint32_t)0x00000020) +/// TX_BCN_U_PATTERN_ERR field position +#define NXMAC_TX_BCN_U_PATTERN_ERR_POS 5 +/// TX_AC_3_LEN_MISMATCH field bit +#define NXMAC_TX_AC_3_LEN_MISMATCH_BIT ((uint32_t)0x00000010) +/// TX_AC_3_LEN_MISMATCH field position +#define NXMAC_TX_AC_3_LEN_MISMATCH_POS 4 +/// TX_AC_2_LEN_MISMATCH field bit +#define NXMAC_TX_AC_2_LEN_MISMATCH_BIT ((uint32_t)0x00000008) +/// TX_AC_2_LEN_MISMATCH field position +#define NXMAC_TX_AC_2_LEN_MISMATCH_POS 3 +/// TX_AC_1_LEN_MISMATCH field bit +#define NXMAC_TX_AC_1_LEN_MISMATCH_BIT ((uint32_t)0x00000004) +/// TX_AC_1_LEN_MISMATCH field position +#define NXMAC_TX_AC_1_LEN_MISMATCH_POS 2 +/// TX_AC_0_LEN_MISMATCH field bit +#define NXMAC_TX_AC_0_LEN_MISMATCH_BIT ((uint32_t)0x00000002) +/// TX_AC_0_LEN_MISMATCH field position +#define NXMAC_TX_AC_0_LEN_MISMATCH_POS 1 +/// TX_BCN_LEN_MISMATCH field bit +#define NXMAC_TX_BCN_LEN_MISMATCH_BIT ((uint32_t)0x00000001) +/// TX_BCN_LEN_MISMATCH field position +#define NXMAC_TX_BCN_LEN_MISMATCH_POS 0 + +/// TX_AC_3_NEW_HEAD_ERR field reset value +#define NXMAC_TX_AC_3_NEW_HEAD_ERR_RST 0x0 +/// TX_AC_2_NEW_HEAD_ERR field reset value +#define NXMAC_TX_AC_2_NEW_HEAD_ERR_RST 0x0 +/// TX_AC_1_NEW_HEAD_ERR field reset value +#define NXMAC_TX_AC_1_NEW_HEAD_ERR_RST 0x0 +/// TX_AC_0_NEW_HEAD_ERR field reset value +#define NXMAC_TX_AC_0_NEW_HEAD_ERR_RST 0x0 +/// TX_BCN_NEW_HEAD_ERR field reset value +#define NXMAC_TX_BCN_NEW_HEAD_ERR_RST 0x0 +/// TX_AC_3_BUS_ERR field reset value +#define NXMAC_TX_AC_3_BUS_ERR_RST 0x0 +/// TX_AC_2_BUS_ERR field reset value +#define NXMAC_TX_AC_2_BUS_ERR_RST 0x0 +/// TX_AC_1_BUS_ERR field reset value +#define NXMAC_TX_AC_1_BUS_ERR_RST 0x0 +/// TX_AC_0_BUS_ERR field reset value +#define NXMAC_TX_AC_0_BUS_ERR_RST 0x0 +/// TX_BCN_BUS_ERR field reset value +#define NXMAC_TX_BCN_BUS_ERR_RST 0x0 +/// TX_AC_3PT_ADDRESS_ERR field reset value +#define NXMAC_TX_AC_3PT_ADDRESS_ERR_RST 0x0 +/// TX_AC_2PT_ADDRESS_ERR field reset value +#define NXMAC_TX_AC_2PT_ADDRESS_ERR_RST 0x0 +/// TX_AC_1PT_ADDRESS_ERR field reset value +#define NXMAC_TX_AC_1PT_ADDRESS_ERR_RST 0x0 +/// TX_AC_0PT_ADDRESS_ERR field reset value +#define NXMAC_TX_AC_0PT_ADDRESS_ERR_RST 0x0 +/// TX_BCN_PT_ADDRESS_ERR field reset value +#define NXMAC_TX_BCN_PT_ADDRESS_ERR_RST 0x0 +/// TX_AC_3_NEXT_POINTER_ERR field reset value +#define NXMAC_TX_AC_3_NEXT_POINTER_ERR_RST 0x0 +/// TX_AC_2_NEXT_POINTER_ERR field reset value +#define NXMAC_TX_AC_2_NEXT_POINTER_ERR_RST 0x0 +/// TX_AC_1_NEXT_POINTER_ERR field reset value +#define NXMAC_TX_AC_1_NEXT_POINTER_ERR_RST 0x0 +/// TX_AC_0_NEXT_POINTER_ERR field reset value +#define NXMAC_TX_AC_0_NEXT_POINTER_ERR_RST 0x0 +/// TX_BCN_NEXT_POINTER_ERR field reset value +#define NXMAC_TX_BCN_NEXT_POINTER_ERR_RST 0x0 +/// TX_AC_3U_PATTERN_ERR field reset value +#define NXMAC_TX_AC_3U_PATTERN_ERR_RST 0x0 +/// TX_AC_2U_PATTERN_ERR field reset value +#define NXMAC_TX_AC_2U_PATTERN_ERR_RST 0x0 +/// TX_AC_1U_PATTERN_ERR field reset value +#define NXMAC_TX_AC_1U_PATTERN_ERR_RST 0x0 +/// TX_AC_0U_PATTERN_ERR field reset value +#define NXMAC_TX_AC_0U_PATTERN_ERR_RST 0x0 +/// TX_BCN_U_PATTERN_ERR field reset value +#define NXMAC_TX_BCN_U_PATTERN_ERR_RST 0x0 +/// TX_AC_3_LEN_MISMATCH field reset value +#define NXMAC_TX_AC_3_LEN_MISMATCH_RST 0x0 +/// TX_AC_2_LEN_MISMATCH field reset value +#define NXMAC_TX_AC_2_LEN_MISMATCH_RST 0x0 +/// TX_AC_1_LEN_MISMATCH field reset value +#define NXMAC_TX_AC_1_LEN_MISMATCH_RST 0x0 +/// TX_AC_0_LEN_MISMATCH field reset value +#define NXMAC_TX_AC_0_LEN_MISMATCH_RST 0x0 +/// TX_BCN_LEN_MISMATCH field reset value +#define NXMAC_TX_BCN_LEN_MISMATCH_RST 0x0 + +/** + * @brief Unpacks DMA_STATUS_2's fields from current value of the DMA_STATUS_2 register. + * + * Reads the DMA_STATUS_2 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] txac3newheaderr - Will be populated with the current value of this field from the register. + * @param[out] txac2newheaderr - Will be populated with the current value of this field from the register. + * @param[out] txac1newheaderr - Will be populated with the current value of this field from the register. + * @param[out] txac0newheaderr - Will be populated with the current value of this field from the register. + * @param[out] txbcnnewheaderr - Will be populated with the current value of this field from the register. + * @param[out] txac3buserr - Will be populated with the current value of this field from the register. + * @param[out] txac2buserr - Will be populated with the current value of this field from the register. + * @param[out] txac1buserr - Will be populated with the current value of this field from the register. + * @param[out] txac0buserr - Will be populated with the current value of this field from the register. + * @param[out] txbcnbuserr - Will be populated with the current value of this field from the register. + * @param[out] txac3ptaddresserr - Will be populated with the current value of this field from the register. + * @param[out] txac2ptaddresserr - Will be populated with the current value of this field from the register. + * @param[out] txac1ptaddresserr - Will be populated with the current value of this field from the register. + * @param[out] txac0ptaddresserr - Will be populated with the current value of this field from the register. + * @param[out] txbcnptaddresserr - Will be populated with the current value of this field from the register. + * @param[out] txac3nextpointererr - Will be populated with the current value of this field from the register. + * @param[out] txac2nextpointererr - Will be populated with the current value of this field from the register. + * @param[out] txac1nextpointererr - Will be populated with the current value of this field from the register. + * @param[out] txac0nextpointererr - Will be populated with the current value of this field from the register. + * @param[out] txbcnnextpointererr - Will be populated with the current value of this field from the register. + * @param[out] txac3upatternerr - Will be populated with the current value of this field from the register. + * @param[out] txac2upatternerr - Will be populated with the current value of this field from the register. + * @param[out] txac1upatternerr - Will be populated with the current value of this field from the register. + * @param[out] txac0upatternerr - Will be populated with the current value of this field from the register. + * @param[out] txbcnupatternerr - Will be populated with the current value of this field from the register. + * @param[out] txac3lenmismatch - Will be populated with the current value of this field from the register. + * @param[out] txac2lenmismatch - Will be populated with the current value of this field from the register. + * @param[out] txac1lenmismatch - Will be populated with the current value of this field from the register. + * @param[out] txac0lenmismatch - Will be populated with the current value of this field from the register. + * @param[out] txbcnlenmismatch - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_dma_status_2_unpack(uint8_t *txac3newheaderr, uint8_t *txac2newheaderr, uint8_t *txac1newheaderr, uint8_t *txac0newheaderr, uint8_t *txbcnnewheaderr, uint8_t *txac3buserr, uint8_t *txac2buserr, uint8_t *txac1buserr, uint8_t *txac0buserr, uint8_t *txbcnbuserr, uint8_t *txac3ptaddresserr, uint8_t *txac2ptaddresserr, uint8_t *txac1ptaddresserr, uint8_t *txac0ptaddresserr, uint8_t *txbcnptaddresserr, uint8_t *txac3nextpointererr, uint8_t *txac2nextpointererr, uint8_t *txac1nextpointererr, uint8_t *txac0nextpointererr, uint8_t *txbcnnextpointererr, uint8_t *txac3upatternerr, uint8_t *txac2upatternerr, uint8_t *txac1upatternerr, uint8_t *txac0upatternerr, uint8_t *txbcnupatternerr, uint8_t *txac3lenmismatch, uint8_t *txac2lenmismatch, uint8_t *txac1lenmismatch, uint8_t *txac0lenmismatch, uint8_t *txbcnlenmismatch) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_2_ADDR); + + *txac3newheaderr = (localVal & ((uint32_t)0x20000000)) >> 29; + *txac2newheaderr = (localVal & ((uint32_t)0x10000000)) >> 28; + *txac1newheaderr = (localVal & ((uint32_t)0x08000000)) >> 27; + *txac0newheaderr = (localVal & ((uint32_t)0x04000000)) >> 26; + *txbcnnewheaderr = (localVal & ((uint32_t)0x02000000)) >> 25; + *txac3buserr = (localVal & ((uint32_t)0x01000000)) >> 24; + *txac2buserr = (localVal & ((uint32_t)0x00800000)) >> 23; + *txac1buserr = (localVal & ((uint32_t)0x00400000)) >> 22; + *txac0buserr = (localVal & ((uint32_t)0x00200000)) >> 21; + *txbcnbuserr = (localVal & ((uint32_t)0x00100000)) >> 20; + *txac3ptaddresserr = (localVal & ((uint32_t)0x00080000)) >> 19; + *txac2ptaddresserr = (localVal & ((uint32_t)0x00040000)) >> 18; + *txac1ptaddresserr = (localVal & ((uint32_t)0x00020000)) >> 17; + *txac0ptaddresserr = (localVal & ((uint32_t)0x00010000)) >> 16; + *txbcnptaddresserr = (localVal & ((uint32_t)0x00008000)) >> 15; + *txac3nextpointererr = (localVal & ((uint32_t)0x00004000)) >> 14; + *txac2nextpointererr = (localVal & ((uint32_t)0x00002000)) >> 13; + *txac1nextpointererr = (localVal & ((uint32_t)0x00001000)) >> 12; + *txac0nextpointererr = (localVal & ((uint32_t)0x00000800)) >> 11; + *txbcnnextpointererr = (localVal & ((uint32_t)0x00000400)) >> 10; + *txac3upatternerr = (localVal & ((uint32_t)0x00000200)) >> 9; + *txac2upatternerr = (localVal & ((uint32_t)0x00000100)) >> 8; + *txac1upatternerr = (localVal & ((uint32_t)0x00000080)) >> 7; + *txac0upatternerr = (localVal & ((uint32_t)0x00000040)) >> 6; + *txbcnupatternerr = (localVal & ((uint32_t)0x00000020)) >> 5; + *txac3lenmismatch = (localVal & ((uint32_t)0x00000010)) >> 4; + *txac2lenmismatch = (localVal & ((uint32_t)0x00000008)) >> 3; + *txac1lenmismatch = (localVal & ((uint32_t)0x00000004)) >> 2; + *txac0lenmismatch = (localVal & ((uint32_t)0x00000002)) >> 1; + *txbcnlenmismatch = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +/** + * @brief Returns the current value of the txAC3NewHeadErr field in the DMA_STATUS_2 register. + * + * The DMA_STATUS_2 register will be read and the txAC3NewHeadErr field's value will be returned. + * + * @return The current value of the txAC3NewHeadErr field in the DMA_STATUS_2 register. + */ +__INLINE uint8_t nxmac_tx_ac_3_new_head_err_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_2_ADDR); + return ((localVal & ((uint32_t)0x20000000)) >> 29); +} + +/** + * @brief Returns the current value of the txAC2NewHeadErr field in the DMA_STATUS_2 register. + * + * The DMA_STATUS_2 register will be read and the txAC2NewHeadErr field's value will be returned. + * + * @return The current value of the txAC2NewHeadErr field in the DMA_STATUS_2 register. + */ +__INLINE uint8_t nxmac_tx_ac_2_new_head_err_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_2_ADDR); + return ((localVal & ((uint32_t)0x10000000)) >> 28); +} + +/** + * @brief Returns the current value of the txAC1NewHeadErr field in the DMA_STATUS_2 register. + * + * The DMA_STATUS_2 register will be read and the txAC1NewHeadErr field's value will be returned. + * + * @return The current value of the txAC1NewHeadErr field in the DMA_STATUS_2 register. + */ +__INLINE uint8_t nxmac_tx_ac_1_new_head_err_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_2_ADDR); + return ((localVal & ((uint32_t)0x08000000)) >> 27); +} + +/** + * @brief Returns the current value of the txAC0NewHeadErr field in the DMA_STATUS_2 register. + * + * The DMA_STATUS_2 register will be read and the txAC0NewHeadErr field's value will be returned. + * + * @return The current value of the txAC0NewHeadErr field in the DMA_STATUS_2 register. + */ +__INLINE uint8_t nxmac_tx_ac_0_new_head_err_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_2_ADDR); + return ((localVal & ((uint32_t)0x04000000)) >> 26); +} + +/** + * @brief Returns the current value of the txBcnNewHeadErr field in the DMA_STATUS_2 register. + * + * The DMA_STATUS_2 register will be read and the txBcnNewHeadErr field's value will be returned. + * + * @return The current value of the txBcnNewHeadErr field in the DMA_STATUS_2 register. + */ +__INLINE uint8_t nxmac_tx_bcn_new_head_err_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_2_ADDR); + return ((localVal & ((uint32_t)0x02000000)) >> 25); +} + +/** + * @brief Returns the current value of the txAC3BusErr field in the DMA_STATUS_2 register. + * + * The DMA_STATUS_2 register will be read and the txAC3BusErr field's value will be returned. + * + * @return The current value of the txAC3BusErr field in the DMA_STATUS_2 register. + */ +__INLINE uint8_t nxmac_tx_ac_3_bus_err_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_2_ADDR); + return ((localVal & ((uint32_t)0x01000000)) >> 24); +} + +/** + * @brief Returns the current value of the txAC2BusErr field in the DMA_STATUS_2 register. + * + * The DMA_STATUS_2 register will be read and the txAC2BusErr field's value will be returned. + * + * @return The current value of the txAC2BusErr field in the DMA_STATUS_2 register. + */ +__INLINE uint8_t nxmac_tx_ac_2_bus_err_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_2_ADDR); + return ((localVal & ((uint32_t)0x00800000)) >> 23); +} + +/** + * @brief Returns the current value of the txAC1BusErr field in the DMA_STATUS_2 register. + * + * The DMA_STATUS_2 register will be read and the txAC1BusErr field's value will be returned. + * + * @return The current value of the txAC1BusErr field in the DMA_STATUS_2 register. + */ +__INLINE uint8_t nxmac_tx_ac_1_bus_err_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_2_ADDR); + return ((localVal & ((uint32_t)0x00400000)) >> 22); +} + +/** + * @brief Returns the current value of the txAC0BusErr field in the DMA_STATUS_2 register. + * + * The DMA_STATUS_2 register will be read and the txAC0BusErr field's value will be returned. + * + * @return The current value of the txAC0BusErr field in the DMA_STATUS_2 register. + */ +__INLINE uint8_t nxmac_tx_ac_0_bus_err_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_2_ADDR); + return ((localVal & ((uint32_t)0x00200000)) >> 21); +} + +/** + * @brief Returns the current value of the txBcnBusErr field in the DMA_STATUS_2 register. + * + * The DMA_STATUS_2 register will be read and the txBcnBusErr field's value will be returned. + * + * @return The current value of the txBcnBusErr field in the DMA_STATUS_2 register. + */ +__INLINE uint8_t nxmac_tx_bcn_bus_err_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_2_ADDR); + return ((localVal & ((uint32_t)0x00100000)) >> 20); +} + +/** + * @brief Returns the current value of the txAC3PTAddressErr field in the DMA_STATUS_2 register. + * + * The DMA_STATUS_2 register will be read and the txAC3PTAddressErr field's value will be returned. + * + * @return The current value of the txAC3PTAddressErr field in the DMA_STATUS_2 register. + */ +__INLINE uint8_t nxmac_tx_ac_3pt_address_err_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_2_ADDR); + return ((localVal & ((uint32_t)0x00080000)) >> 19); +} + +/** + * @brief Returns the current value of the txAC2PTAddressErr field in the DMA_STATUS_2 register. + * + * The DMA_STATUS_2 register will be read and the txAC2PTAddressErr field's value will be returned. + * + * @return The current value of the txAC2PTAddressErr field in the DMA_STATUS_2 register. + */ +__INLINE uint8_t nxmac_tx_ac_2pt_address_err_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_2_ADDR); + return ((localVal & ((uint32_t)0x00040000)) >> 18); +} + +/** + * @brief Returns the current value of the txAC1PTAddressErr field in the DMA_STATUS_2 register. + * + * The DMA_STATUS_2 register will be read and the txAC1PTAddressErr field's value will be returned. + * + * @return The current value of the txAC1PTAddressErr field in the DMA_STATUS_2 register. + */ +__INLINE uint8_t nxmac_tx_ac_1pt_address_err_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_2_ADDR); + return ((localVal & ((uint32_t)0x00020000)) >> 17); +} + +/** + * @brief Returns the current value of the txAC0PTAddressErr field in the DMA_STATUS_2 register. + * + * The DMA_STATUS_2 register will be read and the txAC0PTAddressErr field's value will be returned. + * + * @return The current value of the txAC0PTAddressErr field in the DMA_STATUS_2 register. + */ +__INLINE uint8_t nxmac_tx_ac_0pt_address_err_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_2_ADDR); + return ((localVal & ((uint32_t)0x00010000)) >> 16); +} + +/** + * @brief Returns the current value of the txBcnPTAddressErr field in the DMA_STATUS_2 register. + * + * The DMA_STATUS_2 register will be read and the txBcnPTAddressErr field's value will be returned. + * + * @return The current value of the txBcnPTAddressErr field in the DMA_STATUS_2 register. + */ +__INLINE uint8_t nxmac_tx_bcn_pt_address_err_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_2_ADDR); + return ((localVal & ((uint32_t)0x00008000)) >> 15); +} + +/** + * @brief Returns the current value of the txAC3NextPointerErr field in the DMA_STATUS_2 register. + * + * The DMA_STATUS_2 register will be read and the txAC3NextPointerErr field's value will be returned. + * + * @return The current value of the txAC3NextPointerErr field in the DMA_STATUS_2 register. + */ +__INLINE uint8_t nxmac_tx_ac_3_next_pointer_err_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_2_ADDR); + return ((localVal & ((uint32_t)0x00004000)) >> 14); +} + +/** + * @brief Returns the current value of the txAC2NextPointerErr field in the DMA_STATUS_2 register. + * + * The DMA_STATUS_2 register will be read and the txAC2NextPointerErr field's value will be returned. + * + * @return The current value of the txAC2NextPointerErr field in the DMA_STATUS_2 register. + */ +__INLINE uint8_t nxmac_tx_ac_2_next_pointer_err_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_2_ADDR); + return ((localVal & ((uint32_t)0x00002000)) >> 13); +} + +/** + * @brief Returns the current value of the txAC1NextPointerErr field in the DMA_STATUS_2 register. + * + * The DMA_STATUS_2 register will be read and the txAC1NextPointerErr field's value will be returned. + * + * @return The current value of the txAC1NextPointerErr field in the DMA_STATUS_2 register. + */ +__INLINE uint8_t nxmac_tx_ac_1_next_pointer_err_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_2_ADDR); + return ((localVal & ((uint32_t)0x00001000)) >> 12); +} + +/** + * @brief Returns the current value of the txAC0NextPointerErr field in the DMA_STATUS_2 register. + * + * The DMA_STATUS_2 register will be read and the txAC0NextPointerErr field's value will be returned. + * + * @return The current value of the txAC0NextPointerErr field in the DMA_STATUS_2 register. + */ +__INLINE uint8_t nxmac_tx_ac_0_next_pointer_err_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_2_ADDR); + return ((localVal & ((uint32_t)0x00000800)) >> 11); +} + +/** + * @brief Returns the current value of the txBcnNextPointerErr field in the DMA_STATUS_2 register. + * + * The DMA_STATUS_2 register will be read and the txBcnNextPointerErr field's value will be returned. + * + * @return The current value of the txBcnNextPointerErr field in the DMA_STATUS_2 register. + */ +__INLINE uint8_t nxmac_tx_bcn_next_pointer_err_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_2_ADDR); + return ((localVal & ((uint32_t)0x00000400)) >> 10); +} + +/** + * @brief Returns the current value of the txAC3UPatternErr field in the DMA_STATUS_2 register. + * + * The DMA_STATUS_2 register will be read and the txAC3UPatternErr field's value will be returned. + * + * @return The current value of the txAC3UPatternErr field in the DMA_STATUS_2 register. + */ +__INLINE uint8_t nxmac_tx_ac_3u_pattern_err_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_2_ADDR); + return ((localVal & ((uint32_t)0x00000200)) >> 9); +} + +/** + * @brief Returns the current value of the txAC2UPatternErr field in the DMA_STATUS_2 register. + * + * The DMA_STATUS_2 register will be read and the txAC2UPatternErr field's value will be returned. + * + * @return The current value of the txAC2UPatternErr field in the DMA_STATUS_2 register. + */ +__INLINE uint8_t nxmac_tx_ac_2u_pattern_err_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_2_ADDR); + return ((localVal & ((uint32_t)0x00000100)) >> 8); +} + +/** + * @brief Returns the current value of the txAC1UPatternErr field in the DMA_STATUS_2 register. + * + * The DMA_STATUS_2 register will be read and the txAC1UPatternErr field's value will be returned. + * + * @return The current value of the txAC1UPatternErr field in the DMA_STATUS_2 register. + */ +__INLINE uint8_t nxmac_tx_ac_1u_pattern_err_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_2_ADDR); + return ((localVal & ((uint32_t)0x00000080)) >> 7); +} + +/** + * @brief Returns the current value of the txAC0UPatternErr field in the DMA_STATUS_2 register. + * + * The DMA_STATUS_2 register will be read and the txAC0UPatternErr field's value will be returned. + * + * @return The current value of the txAC0UPatternErr field in the DMA_STATUS_2 register. + */ +__INLINE uint8_t nxmac_tx_ac_0u_pattern_err_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_2_ADDR); + return ((localVal & ((uint32_t)0x00000040)) >> 6); +} + +/** + * @brief Returns the current value of the txBcnUPatternErr field in the DMA_STATUS_2 register. + * + * The DMA_STATUS_2 register will be read and the txBcnUPatternErr field's value will be returned. + * + * @return The current value of the txBcnUPatternErr field in the DMA_STATUS_2 register. + */ +__INLINE uint8_t nxmac_tx_bcn_u_pattern_err_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_2_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +/** + * @brief Returns the current value of the txAC3LenMismatch field in the DMA_STATUS_2 register. + * + * The DMA_STATUS_2 register will be read and the txAC3LenMismatch field's value will be returned. + * + * @return The current value of the txAC3LenMismatch field in the DMA_STATUS_2 register. + */ +__INLINE uint8_t nxmac_tx_ac_3_len_mismatch_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_2_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +/** + * @brief Returns the current value of the txAC2LenMismatch field in the DMA_STATUS_2 register. + * + * The DMA_STATUS_2 register will be read and the txAC2LenMismatch field's value will be returned. + * + * @return The current value of the txAC2LenMismatch field in the DMA_STATUS_2 register. + */ +__INLINE uint8_t nxmac_tx_ac_2_len_mismatch_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_2_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +/** + * @brief Returns the current value of the txAC1LenMismatch field in the DMA_STATUS_2 register. + * + * The DMA_STATUS_2 register will be read and the txAC1LenMismatch field's value will be returned. + * + * @return The current value of the txAC1LenMismatch field in the DMA_STATUS_2 register. + */ +__INLINE uint8_t nxmac_tx_ac_1_len_mismatch_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_2_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +/** + * @brief Returns the current value of the txAC0LenMismatch field in the DMA_STATUS_2 register. + * + * The DMA_STATUS_2 register will be read and the txAC0LenMismatch field's value will be returned. + * + * @return The current value of the txAC0LenMismatch field in the DMA_STATUS_2 register. + */ +__INLINE uint8_t nxmac_tx_ac_0_len_mismatch_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_2_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +/** + * @brief Returns the current value of the txBcnLenMismatch field in the DMA_STATUS_2 register. + * + * The DMA_STATUS_2 register will be read and the txBcnLenMismatch field's value will be returned. + * + * @return The current value of the txBcnLenMismatch field in the DMA_STATUS_2 register. + */ +__INLINE uint8_t nxmac_tx_bcn_len_mismatch_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_2_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/// @} + +/** + * @name DMA_STATUS_3 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     07      rxPayNewHeadErr   0
+ *     06      rxHdrNewHeadErr   0
+ *     05          rxPayBusErr   0
+ *     04          rxHdrBusErr   0
+ *     03   rxPayNextPointerErr   0
+ *     02   rxHdrNextPointerErr   0
+ *     01     rxPayUPatternErr   0
+ *     00     rxHdrUPatternErr   0
+ * 
+ * + * @{ + */ + +/// Address of the DMA_STATUS_3 register +#define NXMAC_DMA_STATUS_3_ADDR 0xC0008190 +/// Offset of the DMA_STATUS_3 register from the base address +#define NXMAC_DMA_STATUS_3_OFFSET 0x00000190 +/// Index of the DMA_STATUS_3 register +#define NXMAC_DMA_STATUS_3_INDEX 0x00000064 +/// Reset value of the DMA_STATUS_3 register +#define NXMAC_DMA_STATUS_3_RESET 0x00000000 + +/** + * @brief Returns the current value of the DMA_STATUS_3 register. + * The DMA_STATUS_3 register will be read and its value returned. + * @return The current value of the DMA_STATUS_3 register. + */ +__INLINE uint32_t nxmac_dma_status_3_get(void) +{ + return REG_PL_RD(NXMAC_DMA_STATUS_3_ADDR); +} + +// field definitions +/// RX_PAY_NEW_HEAD_ERR field bit +#define NXMAC_RX_PAY_NEW_HEAD_ERR_BIT ((uint32_t)0x00000080) +/// RX_PAY_NEW_HEAD_ERR field position +#define NXMAC_RX_PAY_NEW_HEAD_ERR_POS 7 +/// RX_HDR_NEW_HEAD_ERR field bit +#define NXMAC_RX_HDR_NEW_HEAD_ERR_BIT ((uint32_t)0x00000040) +/// RX_HDR_NEW_HEAD_ERR field position +#define NXMAC_RX_HDR_NEW_HEAD_ERR_POS 6 +/// RX_PAY_BUS_ERR field bit +#define NXMAC_RX_PAY_BUS_ERR_BIT ((uint32_t)0x00000020) +/// RX_PAY_BUS_ERR field position +#define NXMAC_RX_PAY_BUS_ERR_POS 5 +/// RX_HDR_BUS_ERR field bit +#define NXMAC_RX_HDR_BUS_ERR_BIT ((uint32_t)0x00000010) +/// RX_HDR_BUS_ERR field position +#define NXMAC_RX_HDR_BUS_ERR_POS 4 +/// RX_PAY_NEXT_POINTER_ERR field bit +#define NXMAC_RX_PAY_NEXT_POINTER_ERR_BIT ((uint32_t)0x00000008) +/// RX_PAY_NEXT_POINTER_ERR field position +#define NXMAC_RX_PAY_NEXT_POINTER_ERR_POS 3 +/// RX_HDR_NEXT_POINTER_ERR field bit +#define NXMAC_RX_HDR_NEXT_POINTER_ERR_BIT ((uint32_t)0x00000004) +/// RX_HDR_NEXT_POINTER_ERR field position +#define NXMAC_RX_HDR_NEXT_POINTER_ERR_POS 2 +/// RX_PAY_U_PATTERN_ERR field bit +#define NXMAC_RX_PAY_U_PATTERN_ERR_BIT ((uint32_t)0x00000002) +/// RX_PAY_U_PATTERN_ERR field position +#define NXMAC_RX_PAY_U_PATTERN_ERR_POS 1 +/// RX_HDR_U_PATTERN_ERR field bit +#define NXMAC_RX_HDR_U_PATTERN_ERR_BIT ((uint32_t)0x00000001) +/// RX_HDR_U_PATTERN_ERR field position +#define NXMAC_RX_HDR_U_PATTERN_ERR_POS 0 + +/// RX_PAY_NEW_HEAD_ERR field reset value +#define NXMAC_RX_PAY_NEW_HEAD_ERR_RST 0x0 +/// RX_HDR_NEW_HEAD_ERR field reset value +#define NXMAC_RX_HDR_NEW_HEAD_ERR_RST 0x0 +/// RX_PAY_BUS_ERR field reset value +#define NXMAC_RX_PAY_BUS_ERR_RST 0x0 +/// RX_HDR_BUS_ERR field reset value +#define NXMAC_RX_HDR_BUS_ERR_RST 0x0 +/// RX_PAY_NEXT_POINTER_ERR field reset value +#define NXMAC_RX_PAY_NEXT_POINTER_ERR_RST 0x0 +/// RX_HDR_NEXT_POINTER_ERR field reset value +#define NXMAC_RX_HDR_NEXT_POINTER_ERR_RST 0x0 +/// RX_PAY_U_PATTERN_ERR field reset value +#define NXMAC_RX_PAY_U_PATTERN_ERR_RST 0x0 +/// RX_HDR_U_PATTERN_ERR field reset value +#define NXMAC_RX_HDR_U_PATTERN_ERR_RST 0x0 + +/** + * @brief Unpacks DMA_STATUS_3's fields from current value of the DMA_STATUS_3 register. + * + * Reads the DMA_STATUS_3 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] rxpaynewheaderr - Will be populated with the current value of this field from the register. + * @param[out] rxhdrnewheaderr - Will be populated with the current value of this field from the register. + * @param[out] rxpaybuserr - Will be populated with the current value of this field from the register. + * @param[out] rxhdrbuserr - Will be populated with the current value of this field from the register. + * @param[out] rxpaynextpointererr - Will be populated with the current value of this field from the register. + * @param[out] rxhdrnextpointererr - Will be populated with the current value of this field from the register. + * @param[out] rxpayupatternerr - Will be populated with the current value of this field from the register. + * @param[out] rxhdrupatternerr - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_dma_status_3_unpack(uint8_t *rxpaynewheaderr, uint8_t *rxhdrnewheaderr, uint8_t *rxpaybuserr, uint8_t *rxhdrbuserr, uint8_t *rxpaynextpointererr, uint8_t *rxhdrnextpointererr, uint8_t *rxpayupatternerr, uint8_t *rxhdrupatternerr) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_3_ADDR); + + *rxpaynewheaderr = (localVal & ((uint32_t)0x00000080)) >> 7; + *rxhdrnewheaderr = (localVal & ((uint32_t)0x00000040)) >> 6; + *rxpaybuserr = (localVal & ((uint32_t)0x00000020)) >> 5; + *rxhdrbuserr = (localVal & ((uint32_t)0x00000010)) >> 4; + *rxpaynextpointererr = (localVal & ((uint32_t)0x00000008)) >> 3; + *rxhdrnextpointererr = (localVal & ((uint32_t)0x00000004)) >> 2; + *rxpayupatternerr = (localVal & ((uint32_t)0x00000002)) >> 1; + *rxhdrupatternerr = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +/** + * @brief Returns the current value of the rxPayNewHeadErr field in the DMA_STATUS_3 register. + * + * The DMA_STATUS_3 register will be read and the rxPayNewHeadErr field's value will be returned. + * + * @return The current value of the rxPayNewHeadErr field in the DMA_STATUS_3 register. + */ +__INLINE uint8_t nxmac_rx_pay_new_head_err_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_3_ADDR); + return ((localVal & ((uint32_t)0x00000080)) >> 7); +} + +/** + * @brief Returns the current value of the rxHdrNewHeadErr field in the DMA_STATUS_3 register. + * + * The DMA_STATUS_3 register will be read and the rxHdrNewHeadErr field's value will be returned. + * + * @return The current value of the rxHdrNewHeadErr field in the DMA_STATUS_3 register. + */ +__INLINE uint8_t nxmac_rx_hdr_new_head_err_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_3_ADDR); + return ((localVal & ((uint32_t)0x00000040)) >> 6); +} + +/** + * @brief Returns the current value of the rxPayBusErr field in the DMA_STATUS_3 register. + * + * The DMA_STATUS_3 register will be read and the rxPayBusErr field's value will be returned. + * + * @return The current value of the rxPayBusErr field in the DMA_STATUS_3 register. + */ +__INLINE uint8_t nxmac_rx_pay_bus_err_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_3_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +/** + * @brief Returns the current value of the rxHdrBusErr field in the DMA_STATUS_3 register. + * + * The DMA_STATUS_3 register will be read and the rxHdrBusErr field's value will be returned. + * + * @return The current value of the rxHdrBusErr field in the DMA_STATUS_3 register. + */ +__INLINE uint8_t nxmac_rx_hdr_bus_err_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_3_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +/** + * @brief Returns the current value of the rxPayNextPointerErr field in the DMA_STATUS_3 register. + * + * The DMA_STATUS_3 register will be read and the rxPayNextPointerErr field's value will be returned. + * + * @return The current value of the rxPayNextPointerErr field in the DMA_STATUS_3 register. + */ +__INLINE uint8_t nxmac_rx_pay_next_pointer_err_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_3_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +/** + * @brief Returns the current value of the rxHdrNextPointerErr field in the DMA_STATUS_3 register. + * + * The DMA_STATUS_3 register will be read and the rxHdrNextPointerErr field's value will be returned. + * + * @return The current value of the rxHdrNextPointerErr field in the DMA_STATUS_3 register. + */ +__INLINE uint8_t nxmac_rx_hdr_next_pointer_err_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_3_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +/** + * @brief Returns the current value of the rxPayUPatternErr field in the DMA_STATUS_3 register. + * + * The DMA_STATUS_3 register will be read and the rxPayUPatternErr field's value will be returned. + * + * @return The current value of the rxPayUPatternErr field in the DMA_STATUS_3 register. + */ +__INLINE uint8_t nxmac_rx_pay_u_pattern_err_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_3_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +/** + * @brief Returns the current value of the rxHdrUPatternErr field in the DMA_STATUS_3 register. + * + * The DMA_STATUS_3 register will be read and the rxHdrUPatternErr field's value will be returned. + * + * @return The current value of the rxHdrUPatternErr field in the DMA_STATUS_3 register. + */ +__INLINE uint8_t nxmac_rx_hdr_u_pattern_err_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_3_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/// @} + +/** + * @name DMA_STATUS_4 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     14   txAC3HaltAfterTXOP   0
+ *     13   txAC2HaltAfterTXOP   0
+ *     12   txAC1HaltAfterTXOP   0
+ *     11   txAC0HaltAfterTXOP   0
+ *     10   txBcnHaltAfterTXOP   0
+ *     09            txAC3EndQ   0
+ *     08            txAC2EndQ   0
+ *     07            txAC1EndQ   0
+ *     06            txAC0EndQ   0
+ *     05            txBcnEndQ   0
+ *     04         txAC3Startup   1
+ *     03         txAC2Startup   1
+ *     02         txAC1Startup   1
+ *     01         txAC0Startup   1
+ *     00         txBcnStartup   1
+ * 
+ * + * @{ + */ + +/// Address of the DMA_STATUS_4 register +#define NXMAC_DMA_STATUS_4_ADDR 0xC0008194 +/// Offset of the DMA_STATUS_4 register from the base address +#define NXMAC_DMA_STATUS_4_OFFSET 0x00000194 +/// Index of the DMA_STATUS_4 register +#define NXMAC_DMA_STATUS_4_INDEX 0x00000065 +/// Reset value of the DMA_STATUS_4 register +#define NXMAC_DMA_STATUS_4_RESET 0x0000001F + +/** + * @brief Returns the current value of the DMA_STATUS_4 register. + * The DMA_STATUS_4 register will be read and its value returned. + * @return The current value of the DMA_STATUS_4 register. + */ +__INLINE uint32_t nxmac_dma_status_4_get(void) +{ + return REG_PL_RD(NXMAC_DMA_STATUS_4_ADDR); +} + +// field definitions +/// TX_AC_3_HALT_AFTER_TXOP field bit +#define NXMAC_TX_AC_3_HALT_AFTER_TXOP_BIT ((uint32_t)0x00004000) +/// TX_AC_3_HALT_AFTER_TXOP field position +#define NXMAC_TX_AC_3_HALT_AFTER_TXOP_POS 14 +/// TX_AC_2_HALT_AFTER_TXOP field bit +#define NXMAC_TX_AC_2_HALT_AFTER_TXOP_BIT ((uint32_t)0x00002000) +/// TX_AC_2_HALT_AFTER_TXOP field position +#define NXMAC_TX_AC_2_HALT_AFTER_TXOP_POS 13 +/// TX_AC_1_HALT_AFTER_TXOP field bit +#define NXMAC_TX_AC_1_HALT_AFTER_TXOP_BIT ((uint32_t)0x00001000) +/// TX_AC_1_HALT_AFTER_TXOP field position +#define NXMAC_TX_AC_1_HALT_AFTER_TXOP_POS 12 +/// TX_AC_0_HALT_AFTER_TXOP field bit +#define NXMAC_TX_AC_0_HALT_AFTER_TXOP_BIT ((uint32_t)0x00000800) +/// TX_AC_0_HALT_AFTER_TXOP field position +#define NXMAC_TX_AC_0_HALT_AFTER_TXOP_POS 11 +/// TX_BCN_HALT_AFTER_TXOP field bit +#define NXMAC_TX_BCN_HALT_AFTER_TXOP_BIT ((uint32_t)0x00000400) +/// TX_BCN_HALT_AFTER_TXOP field position +#define NXMAC_TX_BCN_HALT_AFTER_TXOP_POS 10 +/// TX_AC_3_END_Q field bit +#define NXMAC_TX_AC_3_END_Q_BIT ((uint32_t)0x00000200) +/// TX_AC_3_END_Q field position +#define NXMAC_TX_AC_3_END_Q_POS 9 +/// TX_AC_2_END_Q field bit +#define NXMAC_TX_AC_2_END_Q_BIT ((uint32_t)0x00000100) +/// TX_AC_2_END_Q field position +#define NXMAC_TX_AC_2_END_Q_POS 8 +/// TX_AC_1_END_Q field bit +#define NXMAC_TX_AC_1_END_Q_BIT ((uint32_t)0x00000080) +/// TX_AC_1_END_Q field position +#define NXMAC_TX_AC_1_END_Q_POS 7 +/// TX_AC_0_END_Q field bit +#define NXMAC_TX_AC_0_END_Q_BIT ((uint32_t)0x00000040) +/// TX_AC_0_END_Q field position +#define NXMAC_TX_AC_0_END_Q_POS 6 +/// TX_BCN_END_Q field bit +#define NXMAC_TX_BCN_END_Q_BIT ((uint32_t)0x00000020) +/// TX_BCN_END_Q field position +#define NXMAC_TX_BCN_END_Q_POS 5 +/// TX_AC_3_STARTUP field bit +#define NXMAC_TX_AC_3_STARTUP_BIT ((uint32_t)0x00000010) +/// TX_AC_3_STARTUP field position +#define NXMAC_TX_AC_3_STARTUP_POS 4 +/// TX_AC_2_STARTUP field bit +#define NXMAC_TX_AC_2_STARTUP_BIT ((uint32_t)0x00000008) +/// TX_AC_2_STARTUP field position +#define NXMAC_TX_AC_2_STARTUP_POS 3 +/// TX_AC_1_STARTUP field bit +#define NXMAC_TX_AC_1_STARTUP_BIT ((uint32_t)0x00000004) +/// TX_AC_1_STARTUP field position +#define NXMAC_TX_AC_1_STARTUP_POS 2 +/// TX_AC_0_STARTUP field bit +#define NXMAC_TX_AC_0_STARTUP_BIT ((uint32_t)0x00000002) +/// TX_AC_0_STARTUP field position +#define NXMAC_TX_AC_0_STARTUP_POS 1 +/// TX_BCN_STARTUP field bit +#define NXMAC_TX_BCN_STARTUP_BIT ((uint32_t)0x00000001) +/// TX_BCN_STARTUP field position +#define NXMAC_TX_BCN_STARTUP_POS 0 + +/// TX_AC_3_HALT_AFTER_TXOP field reset value +#define NXMAC_TX_AC_3_HALT_AFTER_TXOP_RST 0x0 +/// TX_AC_2_HALT_AFTER_TXOP field reset value +#define NXMAC_TX_AC_2_HALT_AFTER_TXOP_RST 0x0 +/// TX_AC_1_HALT_AFTER_TXOP field reset value +#define NXMAC_TX_AC_1_HALT_AFTER_TXOP_RST 0x0 +/// TX_AC_0_HALT_AFTER_TXOP field reset value +#define NXMAC_TX_AC_0_HALT_AFTER_TXOP_RST 0x0 +/// TX_BCN_HALT_AFTER_TXOP field reset value +#define NXMAC_TX_BCN_HALT_AFTER_TXOP_RST 0x0 +/// TX_AC_3_END_Q field reset value +#define NXMAC_TX_AC_3_END_Q_RST 0x0 +/// TX_AC_2_END_Q field reset value +#define NXMAC_TX_AC_2_END_Q_RST 0x0 +/// TX_AC_1_END_Q field reset value +#define NXMAC_TX_AC_1_END_Q_RST 0x0 +/// TX_AC_0_END_Q field reset value +#define NXMAC_TX_AC_0_END_Q_RST 0x0 +/// TX_BCN_END_Q field reset value +#define NXMAC_TX_BCN_END_Q_RST 0x0 +/// TX_AC_3_STARTUP field reset value +#define NXMAC_TX_AC_3_STARTUP_RST 0x1 +/// TX_AC_2_STARTUP field reset value +#define NXMAC_TX_AC_2_STARTUP_RST 0x1 +/// TX_AC_1_STARTUP field reset value +#define NXMAC_TX_AC_1_STARTUP_RST 0x1 +/// TX_AC_0_STARTUP field reset value +#define NXMAC_TX_AC_0_STARTUP_RST 0x1 +/// TX_BCN_STARTUP field reset value +#define NXMAC_TX_BCN_STARTUP_RST 0x1 + +/** + * @brief Unpacks DMA_STATUS_4's fields from current value of the DMA_STATUS_4 register. + * + * Reads the DMA_STATUS_4 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] txac3haltaftertxop - Will be populated with the current value of this field from the register. + * @param[out] txac2haltaftertxop - Will be populated with the current value of this field from the register. + * @param[out] txac1haltaftertxop - Will be populated with the current value of this field from the register. + * @param[out] txac0haltaftertxop - Will be populated with the current value of this field from the register. + * @param[out] txbcnhaltaftertxop - Will be populated with the current value of this field from the register. + * @param[out] txac3endq - Will be populated with the current value of this field from the register. + * @param[out] txac2endq - Will be populated with the current value of this field from the register. + * @param[out] txac1endq - Will be populated with the current value of this field from the register. + * @param[out] txac0endq - Will be populated with the current value of this field from the register. + * @param[out] txbcnendq - Will be populated with the current value of this field from the register. + * @param[out] txac3startup - Will be populated with the current value of this field from the register. + * @param[out] txac2startup - Will be populated with the current value of this field from the register. + * @param[out] txac1startup - Will be populated with the current value of this field from the register. + * @param[out] txac0startup - Will be populated with the current value of this field from the register. + * @param[out] txbcnstartup - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_dma_status_4_unpack(uint8_t *txac3haltaftertxop, uint8_t *txac2haltaftertxop, uint8_t *txac1haltaftertxop, uint8_t *txac0haltaftertxop, uint8_t *txbcnhaltaftertxop, uint8_t *txac3endq, uint8_t *txac2endq, uint8_t *txac1endq, uint8_t *txac0endq, uint8_t *txbcnendq, uint8_t *txac3startup, uint8_t *txac2startup, uint8_t *txac1startup, uint8_t *txac0startup, uint8_t *txbcnstartup) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_4_ADDR); + + *txac3haltaftertxop = (localVal & ((uint32_t)0x00004000)) >> 14; + *txac2haltaftertxop = (localVal & ((uint32_t)0x00002000)) >> 13; + *txac1haltaftertxop = (localVal & ((uint32_t)0x00001000)) >> 12; + *txac0haltaftertxop = (localVal & ((uint32_t)0x00000800)) >> 11; + *txbcnhaltaftertxop = (localVal & ((uint32_t)0x00000400)) >> 10; + *txac3endq = (localVal & ((uint32_t)0x00000200)) >> 9; + *txac2endq = (localVal & ((uint32_t)0x00000100)) >> 8; + *txac1endq = (localVal & ((uint32_t)0x00000080)) >> 7; + *txac0endq = (localVal & ((uint32_t)0x00000040)) >> 6; + *txbcnendq = (localVal & ((uint32_t)0x00000020)) >> 5; + *txac3startup = (localVal & ((uint32_t)0x00000010)) >> 4; + *txac2startup = (localVal & ((uint32_t)0x00000008)) >> 3; + *txac1startup = (localVal & ((uint32_t)0x00000004)) >> 2; + *txac0startup = (localVal & ((uint32_t)0x00000002)) >> 1; + *txbcnstartup = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +/** + * @brief Returns the current value of the txAC3HaltAfterTXOP field in the DMA_STATUS_4 register. + * + * The DMA_STATUS_4 register will be read and the txAC3HaltAfterTXOP field's value will be returned. + * + * @return The current value of the txAC3HaltAfterTXOP field in the DMA_STATUS_4 register. + */ +__INLINE uint8_t nxmac_tx_ac_3_halt_after_txop_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_4_ADDR); + return ((localVal & ((uint32_t)0x00004000)) >> 14); +} + +/** + * @brief Returns the current value of the txAC2HaltAfterTXOP field in the DMA_STATUS_4 register. + * + * The DMA_STATUS_4 register will be read and the txAC2HaltAfterTXOP field's value will be returned. + * + * @return The current value of the txAC2HaltAfterTXOP field in the DMA_STATUS_4 register. + */ +__INLINE uint8_t nxmac_tx_ac_2_halt_after_txop_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_4_ADDR); + return ((localVal & ((uint32_t)0x00002000)) >> 13); +} + +/** + * @brief Returns the current value of the txAC1HaltAfterTXOP field in the DMA_STATUS_4 register. + * + * The DMA_STATUS_4 register will be read and the txAC1HaltAfterTXOP field's value will be returned. + * + * @return The current value of the txAC1HaltAfterTXOP field in the DMA_STATUS_4 register. + */ +__INLINE uint8_t nxmac_tx_ac_1_halt_after_txop_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_4_ADDR); + return ((localVal & ((uint32_t)0x00001000)) >> 12); +} + +/** + * @brief Returns the current value of the txAC0HaltAfterTXOP field in the DMA_STATUS_4 register. + * + * The DMA_STATUS_4 register will be read and the txAC0HaltAfterTXOP field's value will be returned. + * + * @return The current value of the txAC0HaltAfterTXOP field in the DMA_STATUS_4 register. + */ +__INLINE uint8_t nxmac_tx_ac_0_halt_after_txop_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_4_ADDR); + return ((localVal & ((uint32_t)0x00000800)) >> 11); +} + +/** + * @brief Returns the current value of the txBcnHaltAfterTXOP field in the DMA_STATUS_4 register. + * + * The DMA_STATUS_4 register will be read and the txBcnHaltAfterTXOP field's value will be returned. + * + * @return The current value of the txBcnHaltAfterTXOP field in the DMA_STATUS_4 register. + */ +__INLINE uint8_t nxmac_tx_bcn_halt_after_txop_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_4_ADDR); + return ((localVal & ((uint32_t)0x00000400)) >> 10); +} + +/** + * @brief Returns the current value of the txAC3EndQ field in the DMA_STATUS_4 register. + * + * The DMA_STATUS_4 register will be read and the txAC3EndQ field's value will be returned. + * + * @return The current value of the txAC3EndQ field in the DMA_STATUS_4 register. + */ +__INLINE uint8_t nxmac_tx_ac_3_end_q_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_4_ADDR); + return ((localVal & ((uint32_t)0x00000200)) >> 9); +} + +/** + * @brief Returns the current value of the txAC2EndQ field in the DMA_STATUS_4 register. + * + * The DMA_STATUS_4 register will be read and the txAC2EndQ field's value will be returned. + * + * @return The current value of the txAC2EndQ field in the DMA_STATUS_4 register. + */ +__INLINE uint8_t nxmac_tx_ac_2_end_q_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_4_ADDR); + return ((localVal & ((uint32_t)0x00000100)) >> 8); +} + +/** + * @brief Returns the current value of the txAC1EndQ field in the DMA_STATUS_4 register. + * + * The DMA_STATUS_4 register will be read and the txAC1EndQ field's value will be returned. + * + * @return The current value of the txAC1EndQ field in the DMA_STATUS_4 register. + */ +__INLINE uint8_t nxmac_tx_ac_1_end_q_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_4_ADDR); + return ((localVal & ((uint32_t)0x00000080)) >> 7); +} + +/** + * @brief Returns the current value of the txAC0EndQ field in the DMA_STATUS_4 register. + * + * The DMA_STATUS_4 register will be read and the txAC0EndQ field's value will be returned. + * + * @return The current value of the txAC0EndQ field in the DMA_STATUS_4 register. + */ +__INLINE uint8_t nxmac_tx_ac_0_end_q_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_4_ADDR); + return ((localVal & ((uint32_t)0x00000040)) >> 6); +} + +/** + * @brief Returns the current value of the txBcnEndQ field in the DMA_STATUS_4 register. + * + * The DMA_STATUS_4 register will be read and the txBcnEndQ field's value will be returned. + * + * @return The current value of the txBcnEndQ field in the DMA_STATUS_4 register. + */ +__INLINE uint8_t nxmac_tx_bcn_end_q_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_4_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +/** + * @brief Returns the current value of the txAC3Startup field in the DMA_STATUS_4 register. + * + * The DMA_STATUS_4 register will be read and the txAC3Startup field's value will be returned. + * + * @return The current value of the txAC3Startup field in the DMA_STATUS_4 register. + */ +__INLINE uint8_t nxmac_tx_ac_3_startup_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_4_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +/** + * @brief Returns the current value of the txAC2Startup field in the DMA_STATUS_4 register. + * + * The DMA_STATUS_4 register will be read and the txAC2Startup field's value will be returned. + * + * @return The current value of the txAC2Startup field in the DMA_STATUS_4 register. + */ +__INLINE uint8_t nxmac_tx_ac_2_startup_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_4_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +/** + * @brief Returns the current value of the txAC1Startup field in the DMA_STATUS_4 register. + * + * The DMA_STATUS_4 register will be read and the txAC1Startup field's value will be returned. + * + * @return The current value of the txAC1Startup field in the DMA_STATUS_4 register. + */ +__INLINE uint8_t nxmac_tx_ac_1_startup_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_4_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +/** + * @brief Returns the current value of the txAC0Startup field in the DMA_STATUS_4 register. + * + * The DMA_STATUS_4 register will be read and the txAC0Startup field's value will be returned. + * + * @return The current value of the txAC0Startup field in the DMA_STATUS_4 register. + */ +__INLINE uint8_t nxmac_tx_ac_0_startup_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_4_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +/** + * @brief Returns the current value of the txBcnStartup field in the DMA_STATUS_4 register. + * + * The DMA_STATUS_4 register will be read and the txBcnStartup field's value will be returned. + * + * @return The current value of the txBcnStartup field in the DMA_STATUS_4 register. + */ +__INLINE uint8_t nxmac_tx_bcn_startup_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_STATUS_4_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/// @} + +/** + * @name TX_BCN_HEAD_PTR register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00         txBcnHeadPtr   0x0
+ * 
+ * + * @{ + */ + +/// Address of the TX_BCN_HEAD_PTR register +#define NXMAC_TX_BCN_HEAD_PTR_ADDR 0xC0008198 +/// Offset of the TX_BCN_HEAD_PTR register from the base address +#define NXMAC_TX_BCN_HEAD_PTR_OFFSET 0x00000198 +/// Index of the TX_BCN_HEAD_PTR register +#define NXMAC_TX_BCN_HEAD_PTR_INDEX 0x00000066 +/// Reset value of the TX_BCN_HEAD_PTR register +#define NXMAC_TX_BCN_HEAD_PTR_RESET 0x00000000 + +/** + * @brief Returns the current value of the TX_BCN_HEAD_PTR register. + * The TX_BCN_HEAD_PTR register will be read and its value returned. + * @return The current value of the TX_BCN_HEAD_PTR register. + */ +__INLINE uint32_t nxmac_tx_bcn_head_ptr_get(void) +{ + return REG_PL_RD(NXMAC_TX_BCN_HEAD_PTR_ADDR); +} + +/** + * @brief Sets the TX_BCN_HEAD_PTR register to a value. + * The TX_BCN_HEAD_PTR register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_tx_bcn_head_ptr_set(uint32_t value) +{ + REG_PL_WR(NXMAC_TX_BCN_HEAD_PTR_ADDR, value); +} + +// field definitions +/// TX_BCN_HEAD_PTR field mask +#define NXMAC_TX_BCN_HEAD_PTR_MASK ((uint32_t)0xFFFFFFFF) +/// TX_BCN_HEAD_PTR field LSB position +#define NXMAC_TX_BCN_HEAD_PTR_LSB 0 +/// TX_BCN_HEAD_PTR field width +#define NXMAC_TX_BCN_HEAD_PTR_WIDTH ((uint32_t)0x00000020) + +/// TX_BCN_HEAD_PTR field reset value +#define NXMAC_TX_BCN_HEAD_PTR_RST 0x0 + +/** + * @brief Returns the current value of the txBcnHeadPtr field in the TX_BCN_HEAD_PTR register. + * + * The TX_BCN_HEAD_PTR register will be read and the txBcnHeadPtr field's value will be returned. + * + * @return The current value of the txBcnHeadPtr field in the TX_BCN_HEAD_PTR register. + */ +__INLINE uint32_t nxmac_tx_bcn_head_ptr_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_BCN_HEAD_PTR_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the txBcnHeadPtr field of the TX_BCN_HEAD_PTR register. + * + * The TX_BCN_HEAD_PTR register will be read, modified to contain the new field value, and written. + * + * @param[in] txbcnheadptr - The value to set the field to. + */ +__INLINE void nxmac_tx_bcn_head_ptr_setf(uint32_t txbcnheadptr) +{ + ASSERT_ERR((((uint32_t)txbcnheadptr << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(NXMAC_TX_BCN_HEAD_PTR_ADDR, (uint32_t)txbcnheadptr << 0); +} + +/// @} + +/** + * @name TX_AC_0_HEAD_PTR register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00         txAC0HeadPtr   0x0
+ * 
+ * + * @{ + */ + +/// Address of the TX_AC_0_HEAD_PTR register +#define NXMAC_TX_AC_0_HEAD_PTR_ADDR 0xC000819C +/// Offset of the TX_AC_0_HEAD_PTR register from the base address +#define NXMAC_TX_AC_0_HEAD_PTR_OFFSET 0x0000019C +/// Index of the TX_AC_0_HEAD_PTR register +#define NXMAC_TX_AC_0_HEAD_PTR_INDEX 0x00000067 +/// Reset value of the TX_AC_0_HEAD_PTR register +#define NXMAC_TX_AC_0_HEAD_PTR_RESET 0x00000000 + +/** + * @brief Returns the current value of the TX_AC_0_HEAD_PTR register. + * The TX_AC_0_HEAD_PTR register will be read and its value returned. + * @return The current value of the TX_AC_0_HEAD_PTR register. + */ +__INLINE uint32_t nxmac_tx_ac_0_head_ptr_get(void) +{ + return REG_PL_RD(NXMAC_TX_AC_0_HEAD_PTR_ADDR); +} + +/** + * @brief Sets the TX_AC_0_HEAD_PTR register to a value. + * The TX_AC_0_HEAD_PTR register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_tx_ac_0_head_ptr_set(uint32_t value) +{ + REG_PL_WR(NXMAC_TX_AC_0_HEAD_PTR_ADDR, value); +} + +// field definitions +/// TX_AC_0_HEAD_PTR field mask +#define NXMAC_TX_AC_0_HEAD_PTR_MASK ((uint32_t)0xFFFFFFFF) +/// TX_AC_0_HEAD_PTR field LSB position +#define NXMAC_TX_AC_0_HEAD_PTR_LSB 0 +/// TX_AC_0_HEAD_PTR field width +#define NXMAC_TX_AC_0_HEAD_PTR_WIDTH ((uint32_t)0x00000020) + +/// TX_AC_0_HEAD_PTR field reset value +#define NXMAC_TX_AC_0_HEAD_PTR_RST 0x0 + +/** + * @brief Returns the current value of the txAC0HeadPtr field in the TX_AC_0_HEAD_PTR register. + * + * The TX_AC_0_HEAD_PTR register will be read and the txAC0HeadPtr field's value will be returned. + * + * @return The current value of the txAC0HeadPtr field in the TX_AC_0_HEAD_PTR register. + */ +__INLINE uint32_t nxmac_tx_ac_0_head_ptr_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_AC_0_HEAD_PTR_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the txAC0HeadPtr field of the TX_AC_0_HEAD_PTR register. + * + * The TX_AC_0_HEAD_PTR register will be read, modified to contain the new field value, and written. + * + * @param[in] txac0headptr - The value to set the field to. + */ +__INLINE void nxmac_tx_ac_0_head_ptr_setf(uint32_t txac0headptr) +{ + ASSERT_ERR((((uint32_t)txac0headptr << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(NXMAC_TX_AC_0_HEAD_PTR_ADDR, (uint32_t)txac0headptr << 0); +} + +/// @} + +/** + * @name TX_AC_1_HEAD_PTR register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00         txAC1HeadPtr   0x0
+ * 
+ * + * @{ + */ + +/// Address of the TX_AC_1_HEAD_PTR register +#define NXMAC_TX_AC_1_HEAD_PTR_ADDR 0xC00081A0 +/// Offset of the TX_AC_1_HEAD_PTR register from the base address +#define NXMAC_TX_AC_1_HEAD_PTR_OFFSET 0x000001A0 +/// Index of the TX_AC_1_HEAD_PTR register +#define NXMAC_TX_AC_1_HEAD_PTR_INDEX 0x00000068 +/// Reset value of the TX_AC_1_HEAD_PTR register +#define NXMAC_TX_AC_1_HEAD_PTR_RESET 0x00000000 + +/** + * @brief Returns the current value of the TX_AC_1_HEAD_PTR register. + * The TX_AC_1_HEAD_PTR register will be read and its value returned. + * @return The current value of the TX_AC_1_HEAD_PTR register. + */ +__INLINE uint32_t nxmac_tx_ac_1_head_ptr_get(void) +{ + return REG_PL_RD(NXMAC_TX_AC_1_HEAD_PTR_ADDR); +} + +/** + * @brief Sets the TX_AC_1_HEAD_PTR register to a value. + * The TX_AC_1_HEAD_PTR register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_tx_ac_1_head_ptr_set(uint32_t value) +{ + REG_PL_WR(NXMAC_TX_AC_1_HEAD_PTR_ADDR, value); +} + +// field definitions +/// TX_AC_1_HEAD_PTR field mask +#define NXMAC_TX_AC_1_HEAD_PTR_MASK ((uint32_t)0xFFFFFFFF) +/// TX_AC_1_HEAD_PTR field LSB position +#define NXMAC_TX_AC_1_HEAD_PTR_LSB 0 +/// TX_AC_1_HEAD_PTR field width +#define NXMAC_TX_AC_1_HEAD_PTR_WIDTH ((uint32_t)0x00000020) + +/// TX_AC_1_HEAD_PTR field reset value +#define NXMAC_TX_AC_1_HEAD_PTR_RST 0x0 + +/** + * @brief Returns the current value of the txAC1HeadPtr field in the TX_AC_1_HEAD_PTR register. + * + * The TX_AC_1_HEAD_PTR register will be read and the txAC1HeadPtr field's value will be returned. + * + * @return The current value of the txAC1HeadPtr field in the TX_AC_1_HEAD_PTR register. + */ +__INLINE uint32_t nxmac_tx_ac_1_head_ptr_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_AC_1_HEAD_PTR_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the txAC1HeadPtr field of the TX_AC_1_HEAD_PTR register. + * + * The TX_AC_1_HEAD_PTR register will be read, modified to contain the new field value, and written. + * + * @param[in] txac1headptr - The value to set the field to. + */ +__INLINE void nxmac_tx_ac_1_head_ptr_setf(uint32_t txac1headptr) +{ + ASSERT_ERR((((uint32_t)txac1headptr << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(NXMAC_TX_AC_1_HEAD_PTR_ADDR, (uint32_t)txac1headptr << 0); +} + +/// @} + +/** + * @name TX_AC_2_HEAD_PTR register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00         txAC2HeadPtr   0x0
+ * 
+ * + * @{ + */ + +/// Address of the TX_AC_2_HEAD_PTR register +#define NXMAC_TX_AC_2_HEAD_PTR_ADDR 0xC00081A4 +/// Offset of the TX_AC_2_HEAD_PTR register from the base address +#define NXMAC_TX_AC_2_HEAD_PTR_OFFSET 0x000001A4 +/// Index of the TX_AC_2_HEAD_PTR register +#define NXMAC_TX_AC_2_HEAD_PTR_INDEX 0x00000069 +/// Reset value of the TX_AC_2_HEAD_PTR register +#define NXMAC_TX_AC_2_HEAD_PTR_RESET 0x00000000 + +/** + * @brief Returns the current value of the TX_AC_2_HEAD_PTR register. + * The TX_AC_2_HEAD_PTR register will be read and its value returned. + * @return The current value of the TX_AC_2_HEAD_PTR register. + */ +__INLINE uint32_t nxmac_tx_ac_2_head_ptr_get(void) +{ + return REG_PL_RD(NXMAC_TX_AC_2_HEAD_PTR_ADDR); +} + +/** + * @brief Sets the TX_AC_2_HEAD_PTR register to a value. + * The TX_AC_2_HEAD_PTR register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_tx_ac_2_head_ptr_set(uint32_t value) +{ + REG_PL_WR(NXMAC_TX_AC_2_HEAD_PTR_ADDR, value); +} + +// field definitions +/// TX_AC_2_HEAD_PTR field mask +#define NXMAC_TX_AC_2_HEAD_PTR_MASK ((uint32_t)0xFFFFFFFF) +/// TX_AC_2_HEAD_PTR field LSB position +#define NXMAC_TX_AC_2_HEAD_PTR_LSB 0 +/// TX_AC_2_HEAD_PTR field width +#define NXMAC_TX_AC_2_HEAD_PTR_WIDTH ((uint32_t)0x00000020) + +/// TX_AC_2_HEAD_PTR field reset value +#define NXMAC_TX_AC_2_HEAD_PTR_RST 0x0 + +/** + * @brief Returns the current value of the txAC2HeadPtr field in the TX_AC_2_HEAD_PTR register. + * + * The TX_AC_2_HEAD_PTR register will be read and the txAC2HeadPtr field's value will be returned. + * + * @return The current value of the txAC2HeadPtr field in the TX_AC_2_HEAD_PTR register. + */ +__INLINE uint32_t nxmac_tx_ac_2_head_ptr_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_AC_2_HEAD_PTR_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the txAC2HeadPtr field of the TX_AC_2_HEAD_PTR register. + * + * The TX_AC_2_HEAD_PTR register will be read, modified to contain the new field value, and written. + * + * @param[in] txac2headptr - The value to set the field to. + */ +__INLINE void nxmac_tx_ac_2_head_ptr_setf(uint32_t txac2headptr) +{ + ASSERT_ERR((((uint32_t)txac2headptr << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(NXMAC_TX_AC_2_HEAD_PTR_ADDR, (uint32_t)txac2headptr << 0); +} + +/// @} + +/** + * @name TX_AC_3_HEAD_PTR register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00         txAC3HeadPtr   0x0
+ * 
+ * + * @{ + */ + +/// Address of the TX_AC_3_HEAD_PTR register +#define NXMAC_TX_AC_3_HEAD_PTR_ADDR 0xC00081A8 +/// Offset of the TX_AC_3_HEAD_PTR register from the base address +#define NXMAC_TX_AC_3_HEAD_PTR_OFFSET 0x000001A8 +/// Index of the TX_AC_3_HEAD_PTR register +#define NXMAC_TX_AC_3_HEAD_PTR_INDEX 0x0000006A +/// Reset value of the TX_AC_3_HEAD_PTR register +#define NXMAC_TX_AC_3_HEAD_PTR_RESET 0x00000000 + +/** + * @brief Returns the current value of the TX_AC_3_HEAD_PTR register. + * The TX_AC_3_HEAD_PTR register will be read and its value returned. + * @return The current value of the TX_AC_3_HEAD_PTR register. + */ +__INLINE uint32_t nxmac_tx_ac_3_head_ptr_get(void) +{ + return REG_PL_RD(NXMAC_TX_AC_3_HEAD_PTR_ADDR); +} + +/** + * @brief Sets the TX_AC_3_HEAD_PTR register to a value. + * The TX_AC_3_HEAD_PTR register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_tx_ac_3_head_ptr_set(uint32_t value) +{ + REG_PL_WR(NXMAC_TX_AC_3_HEAD_PTR_ADDR, value); +} + +// field definitions +/// TX_AC_3_HEAD_PTR field mask +#define NXMAC_TX_AC_3_HEAD_PTR_MASK ((uint32_t)0xFFFFFFFF) +/// TX_AC_3_HEAD_PTR field LSB position +#define NXMAC_TX_AC_3_HEAD_PTR_LSB 0 +/// TX_AC_3_HEAD_PTR field width +#define NXMAC_TX_AC_3_HEAD_PTR_WIDTH ((uint32_t)0x00000020) + +/// TX_AC_3_HEAD_PTR field reset value +#define NXMAC_TX_AC_3_HEAD_PTR_RST 0x0 + +/** + * @brief Returns the current value of the txAC3HeadPtr field in the TX_AC_3_HEAD_PTR register. + * + * The TX_AC_3_HEAD_PTR register will be read and the txAC3HeadPtr field's value will be returned. + * + * @return The current value of the txAC3HeadPtr field in the TX_AC_3_HEAD_PTR register. + */ +__INLINE uint32_t nxmac_tx_ac_3_head_ptr_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_AC_3_HEAD_PTR_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the txAC3HeadPtr field of the TX_AC_3_HEAD_PTR register. + * + * The TX_AC_3_HEAD_PTR register will be read, modified to contain the new field value, and written. + * + * @param[in] txac3headptr - The value to set the field to. + */ +__INLINE void nxmac_tx_ac_3_head_ptr_setf(uint32_t txac3headptr) +{ + ASSERT_ERR((((uint32_t)txac3headptr << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(NXMAC_TX_AC_3_HEAD_PTR_ADDR, (uint32_t)txac3headptr << 0); +} + +/// @} + +/** + * @name TX_STRUCT_SIZES register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  29:24           dmaRBDSize   0x0
+ *  23:18           dmaRHDSize   0x0
+ *  17:12           dmaTBDSize   0x0
+ *  11:06           dmaTHDSize   0x0
+ *  05:00          ptEntrySize   0x0
+ * 
+ * + * @{ + */ + +/// Address of the TX_STRUCT_SIZES register +#define NXMAC_TX_STRUCT_SIZES_ADDR 0xC00081AC +/// Offset of the TX_STRUCT_SIZES register from the base address +#define NXMAC_TX_STRUCT_SIZES_OFFSET 0x000001AC +/// Index of the TX_STRUCT_SIZES register +#define NXMAC_TX_STRUCT_SIZES_INDEX 0x0000006B +/// Reset value of the TX_STRUCT_SIZES register +#define NXMAC_TX_STRUCT_SIZES_RESET 0x00000000 + +/** + * @brief Returns the current value of the TX_STRUCT_SIZES register. + * The TX_STRUCT_SIZES register will be read and its value returned. + * @return The current value of the TX_STRUCT_SIZES register. + */ +__INLINE uint32_t nxmac_tx_struct_sizes_get(void) +{ + return REG_PL_RD(NXMAC_TX_STRUCT_SIZES_ADDR); +} + +/** + * @brief Sets the TX_STRUCT_SIZES register to a value. + * The TX_STRUCT_SIZES register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_tx_struct_sizes_set(uint32_t value) +{ + REG_PL_WR(NXMAC_TX_STRUCT_SIZES_ADDR, value); +} + +// field definitions +/// DMA_RBD_SIZE field mask +#define NXMAC_DMA_RBD_SIZE_MASK ((uint32_t)0x3F000000) +/// DMA_RBD_SIZE field LSB position +#define NXMAC_DMA_RBD_SIZE_LSB 24 +/// DMA_RBD_SIZE field width +#define NXMAC_DMA_RBD_SIZE_WIDTH ((uint32_t)0x00000006) +/// DMA_RHD_SIZE field mask +#define NXMAC_DMA_RHD_SIZE_MASK ((uint32_t)0x00FC0000) +/// DMA_RHD_SIZE field LSB position +#define NXMAC_DMA_RHD_SIZE_LSB 18 +/// DMA_RHD_SIZE field width +#define NXMAC_DMA_RHD_SIZE_WIDTH ((uint32_t)0x00000006) +/// DMA_TBD_SIZE field mask +#define NXMAC_DMA_TBD_SIZE_MASK ((uint32_t)0x0003F000) +/// DMA_TBD_SIZE field LSB position +#define NXMAC_DMA_TBD_SIZE_LSB 12 +/// DMA_TBD_SIZE field width +#define NXMAC_DMA_TBD_SIZE_WIDTH ((uint32_t)0x00000006) +/// DMA_THD_SIZE field mask +#define NXMAC_DMA_THD_SIZE_MASK ((uint32_t)0x00000FC0) +/// DMA_THD_SIZE field LSB position +#define NXMAC_DMA_THD_SIZE_LSB 6 +/// DMA_THD_SIZE field width +#define NXMAC_DMA_THD_SIZE_WIDTH ((uint32_t)0x00000006) +/// PT_ENTRY_SIZE field mask +#define NXMAC_PT_ENTRY_SIZE_MASK ((uint32_t)0x0000003F) +/// PT_ENTRY_SIZE field LSB position +#define NXMAC_PT_ENTRY_SIZE_LSB 0 +/// PT_ENTRY_SIZE field width +#define NXMAC_PT_ENTRY_SIZE_WIDTH ((uint32_t)0x00000006) + +/// DMA_RBD_SIZE field reset value +#define NXMAC_DMA_RBD_SIZE_RST 0x0 +/// DMA_RHD_SIZE field reset value +#define NXMAC_DMA_RHD_SIZE_RST 0x0 +/// DMA_TBD_SIZE field reset value +#define NXMAC_DMA_TBD_SIZE_RST 0x0 +/// DMA_THD_SIZE field reset value +#define NXMAC_DMA_THD_SIZE_RST 0x0 +/// PT_ENTRY_SIZE field reset value +#define NXMAC_PT_ENTRY_SIZE_RST 0x0 + +/** + * @brief Constructs a value for the TX_STRUCT_SIZES register given values for its fields + * and writes the value to the register. + * + * @param[in] dmarbdsize - The value to use for the dmaRBDSize field. + * @param[in] dmarhdsize - The value to use for the dmaRHDSize field. + * @param[in] dmatbdsize - The value to use for the dmaTBDSize field. + * @param[in] dmathdsize - The value to use for the dmaTHDSize field. + * @param[in] ptentrysize - The value to use for the ptEntrySize field. + */ +__INLINE void nxmac_tx_struct_sizes_pack(uint8_t dmarbdsize, uint8_t dmarhdsize, uint8_t dmatbdsize, uint8_t dmathdsize, uint8_t ptentrysize) +{ + ASSERT_ERR((((uint32_t)dmarbdsize << 24) & ~((uint32_t)0x3F000000)) == 0); + ASSERT_ERR((((uint32_t)dmarhdsize << 18) & ~((uint32_t)0x00FC0000)) == 0); + ASSERT_ERR((((uint32_t)dmatbdsize << 12) & ~((uint32_t)0x0003F000)) == 0); + ASSERT_ERR((((uint32_t)dmathdsize << 6) & ~((uint32_t)0x00000FC0)) == 0); + ASSERT_ERR((((uint32_t)ptentrysize << 0) & ~((uint32_t)0x0000003F)) == 0); + REG_PL_WR(NXMAC_TX_STRUCT_SIZES_ADDR, ((uint32_t)dmarbdsize << 24) | ((uint32_t)dmarhdsize << 18) | ((uint32_t)dmatbdsize << 12) | ((uint32_t)dmathdsize << 6) | ((uint32_t)ptentrysize << 0)); +} + +/** + * @brief Unpacks TX_STRUCT_SIZES's fields from current value of the TX_STRUCT_SIZES register. + * + * Reads the TX_STRUCT_SIZES register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] dmarbdsize - Will be populated with the current value of this field from the register. + * @param[out] dmarhdsize - Will be populated with the current value of this field from the register. + * @param[out] dmatbdsize - Will be populated with the current value of this field from the register. + * @param[out] dmathdsize - Will be populated with the current value of this field from the register. + * @param[out] ptentrysize - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_tx_struct_sizes_unpack(uint8_t *dmarbdsize, uint8_t *dmarhdsize, uint8_t *dmatbdsize, uint8_t *dmathdsize, uint8_t *ptentrysize) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_STRUCT_SIZES_ADDR); + + *dmarbdsize = (localVal & ((uint32_t)0x3F000000)) >> 24; + *dmarhdsize = (localVal & ((uint32_t)0x00FC0000)) >> 18; + *dmatbdsize = (localVal & ((uint32_t)0x0003F000)) >> 12; + *dmathdsize = (localVal & ((uint32_t)0x00000FC0)) >> 6; + *ptentrysize = (localVal & ((uint32_t)0x0000003F)) >> 0; +} + +/** + * @brief Returns the current value of the dmaRBDSize field in the TX_STRUCT_SIZES register. + * + * The TX_STRUCT_SIZES register will be read and the dmaRBDSize field's value will be returned. + * + * @return The current value of the dmaRBDSize field in the TX_STRUCT_SIZES register. + */ +__INLINE uint8_t nxmac_dma_rbd_size_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_STRUCT_SIZES_ADDR); + return ((localVal & ((uint32_t)0x3F000000)) >> 24); +} + +/** + * @brief Sets the dmaRBDSize field of the TX_STRUCT_SIZES register. + * + * The TX_STRUCT_SIZES register will be read, modified to contain the new field value, and written. + * + * @param[in] dmarbdsize - The value to set the field to. + */ +__INLINE void nxmac_dma_rbd_size_setf(uint8_t dmarbdsize) +{ + ASSERT_ERR((((uint32_t)dmarbdsize << 24) & ~((uint32_t)0x3F000000)) == 0); + REG_PL_WR(NXMAC_TX_STRUCT_SIZES_ADDR, (REG_PL_RD(NXMAC_TX_STRUCT_SIZES_ADDR) & ~((uint32_t)0x3F000000)) | ((uint32_t)dmarbdsize << 24)); +} + +/** + * @brief Returns the current value of the dmaRHDSize field in the TX_STRUCT_SIZES register. + * + * The TX_STRUCT_SIZES register will be read and the dmaRHDSize field's value will be returned. + * + * @return The current value of the dmaRHDSize field in the TX_STRUCT_SIZES register. + */ +__INLINE uint8_t nxmac_dma_rhd_size_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_STRUCT_SIZES_ADDR); + return ((localVal & ((uint32_t)0x00FC0000)) >> 18); +} + +/** + * @brief Sets the dmaRHDSize field of the TX_STRUCT_SIZES register. + * + * The TX_STRUCT_SIZES register will be read, modified to contain the new field value, and written. + * + * @param[in] dmarhdsize - The value to set the field to. + */ +__INLINE void nxmac_dma_rhd_size_setf(uint8_t dmarhdsize) +{ + ASSERT_ERR((((uint32_t)dmarhdsize << 18) & ~((uint32_t)0x00FC0000)) == 0); + REG_PL_WR(NXMAC_TX_STRUCT_SIZES_ADDR, (REG_PL_RD(NXMAC_TX_STRUCT_SIZES_ADDR) & ~((uint32_t)0x00FC0000)) | ((uint32_t)dmarhdsize << 18)); +} + +/** + * @brief Returns the current value of the dmaTBDSize field in the TX_STRUCT_SIZES register. + * + * The TX_STRUCT_SIZES register will be read and the dmaTBDSize field's value will be returned. + * + * @return The current value of the dmaTBDSize field in the TX_STRUCT_SIZES register. + */ +__INLINE uint8_t nxmac_dma_tbd_size_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_STRUCT_SIZES_ADDR); + return ((localVal & ((uint32_t)0x0003F000)) >> 12); +} + +/** + * @brief Sets the dmaTBDSize field of the TX_STRUCT_SIZES register. + * + * The TX_STRUCT_SIZES register will be read, modified to contain the new field value, and written. + * + * @param[in] dmatbdsize - The value to set the field to. + */ +__INLINE void nxmac_dma_tbd_size_setf(uint8_t dmatbdsize) +{ + ASSERT_ERR((((uint32_t)dmatbdsize << 12) & ~((uint32_t)0x0003F000)) == 0); + REG_PL_WR(NXMAC_TX_STRUCT_SIZES_ADDR, (REG_PL_RD(NXMAC_TX_STRUCT_SIZES_ADDR) & ~((uint32_t)0x0003F000)) | ((uint32_t)dmatbdsize << 12)); +} + +/** + * @brief Returns the current value of the dmaTHDSize field in the TX_STRUCT_SIZES register. + * + * The TX_STRUCT_SIZES register will be read and the dmaTHDSize field's value will be returned. + * + * @return The current value of the dmaTHDSize field in the TX_STRUCT_SIZES register. + */ +__INLINE uint8_t nxmac_dma_thd_size_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_STRUCT_SIZES_ADDR); + return ((localVal & ((uint32_t)0x00000FC0)) >> 6); +} + +/** + * @brief Sets the dmaTHDSize field of the TX_STRUCT_SIZES register. + * + * The TX_STRUCT_SIZES register will be read, modified to contain the new field value, and written. + * + * @param[in] dmathdsize - The value to set the field to. + */ +__INLINE void nxmac_dma_thd_size_setf(uint8_t dmathdsize) +{ + ASSERT_ERR((((uint32_t)dmathdsize << 6) & ~((uint32_t)0x00000FC0)) == 0); + REG_PL_WR(NXMAC_TX_STRUCT_SIZES_ADDR, (REG_PL_RD(NXMAC_TX_STRUCT_SIZES_ADDR) & ~((uint32_t)0x00000FC0)) | ((uint32_t)dmathdsize << 6)); +} + +/** + * @brief Returns the current value of the ptEntrySize field in the TX_STRUCT_SIZES register. + * + * The TX_STRUCT_SIZES register will be read and the ptEntrySize field's value will be returned. + * + * @return The current value of the ptEntrySize field in the TX_STRUCT_SIZES register. + */ +__INLINE uint8_t nxmac_pt_entry_size_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_STRUCT_SIZES_ADDR); + return ((localVal & ((uint32_t)0x0000003F)) >> 0); +} + +/** + * @brief Sets the ptEntrySize field of the TX_STRUCT_SIZES register. + * + * The TX_STRUCT_SIZES register will be read, modified to contain the new field value, and written. + * + * @param[in] ptentrysize - The value to set the field to. + */ +__INLINE void nxmac_pt_entry_size_setf(uint8_t ptentrysize) +{ + ASSERT_ERR((((uint32_t)ptentrysize << 0) & ~((uint32_t)0x0000003F)) == 0); + REG_PL_WR(NXMAC_TX_STRUCT_SIZES_ADDR, (REG_PL_RD(NXMAC_TX_STRUCT_SIZES_ADDR) & ~((uint32_t)0x0000003F)) | ((uint32_t)ptentrysize << 0)); +} + +/// @} + +/** + * @name RX_HEADER_HEAD_PTR register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:02      rxHeaderHeadPtr   0x0
+ *     00   rxHeaderHeadPtrValid   0
+ * 
+ * + * @{ + */ + +/// Address of the RX_HEADER_HEAD_PTR register +#define NXMAC_RX_HEADER_HEAD_PTR_ADDR 0xC00081B8 +/// Offset of the RX_HEADER_HEAD_PTR register from the base address +#define NXMAC_RX_HEADER_HEAD_PTR_OFFSET 0x000001B8 +/// Index of the RX_HEADER_HEAD_PTR register +#define NXMAC_RX_HEADER_HEAD_PTR_INDEX 0x0000006E +/// Reset value of the RX_HEADER_HEAD_PTR register +#define NXMAC_RX_HEADER_HEAD_PTR_RESET 0x00000000 + +/** + * @brief Returns the current value of the RX_HEADER_HEAD_PTR register. + * The RX_HEADER_HEAD_PTR register will be read and its value returned. + * @return The current value of the RX_HEADER_HEAD_PTR register. + */ +__INLINE uint32_t nxmac_rx_header_head_ptr_get(void) +{ + return REG_PL_RD(NXMAC_RX_HEADER_HEAD_PTR_ADDR); +} + +/** + * @brief Sets the RX_HEADER_HEAD_PTR register to a value. + * The RX_HEADER_HEAD_PTR register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_rx_header_head_ptr_set(uint32_t value) +{ + REG_PL_WR(NXMAC_RX_HEADER_HEAD_PTR_ADDR, value); +} + +// field definitions +/// RX_HEADER_HEAD_PTR field mask +#define NXMAC_RX_HEADER_HEAD_PTR_MASK ((uint32_t)0xFFFFFFFC) +/// RX_HEADER_HEAD_PTR field LSB position +#define NXMAC_RX_HEADER_HEAD_PTR_LSB 2 +/// RX_HEADER_HEAD_PTR field width +#define NXMAC_RX_HEADER_HEAD_PTR_WIDTH ((uint32_t)0x0000001E) +/// RX_HEADER_HEAD_PTR_VALID field bit +#define NXMAC_RX_HEADER_HEAD_PTR_VALID_BIT ((uint32_t)0x00000001) +/// RX_HEADER_HEAD_PTR_VALID field position +#define NXMAC_RX_HEADER_HEAD_PTR_VALID_POS 0 + +/// RX_HEADER_HEAD_PTR field reset value +#define NXMAC_RX_HEADER_HEAD_PTR_RST 0x0 +/// RX_HEADER_HEAD_PTR_VALID field reset value +#define NXMAC_RX_HEADER_HEAD_PTR_VALID_RST 0x0 + +/** + * @brief Constructs a value for the RX_HEADER_HEAD_PTR register given values for its fields + * and writes the value to the register. + * + * @param[in] rxheaderheadptr - The value to use for the rxHeaderHeadPtr field. + * @param[in] rxheaderheadptrvalid - The value to use for the rxHeaderHeadPtrValid field. + */ +__INLINE void nxmac_rx_header_head_ptr_pack(uint32_t rxheaderheadptr, uint8_t rxheaderheadptrvalid) +{ + ASSERT_ERR((((uint32_t)rxheaderheadptr << 2) & ~((uint32_t)0xFFFFFFFC)) == 0); + ASSERT_ERR((((uint32_t)rxheaderheadptrvalid << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_RX_HEADER_HEAD_PTR_ADDR, ((uint32_t)rxheaderheadptr << 2) | ((uint32_t)rxheaderheadptrvalid << 0)); +} + +/** + * @brief Unpacks RX_HEADER_HEAD_PTR's fields from current value of the RX_HEADER_HEAD_PTR register. + * + * Reads the RX_HEADER_HEAD_PTR register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] rxheaderheadptr - Will be populated with the current value of this field from the register. + * @param[out] rxheaderheadptrvalid - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_rx_header_head_ptr_unpack(uint32_t *rxheaderheadptr, uint8_t *rxheaderheadptrvalid) +{ + uint32_t localVal = REG_PL_RD(NXMAC_RX_HEADER_HEAD_PTR_ADDR); + + *rxheaderheadptr = (localVal & ((uint32_t)0xFFFFFFFC)) >> 2; + *rxheaderheadptrvalid = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +/** + * @brief Returns the current value of the rxHeaderHeadPtr field in the RX_HEADER_HEAD_PTR register. + * + * The RX_HEADER_HEAD_PTR register will be read and the rxHeaderHeadPtr field's value will be returned. + * + * @return The current value of the rxHeaderHeadPtr field in the RX_HEADER_HEAD_PTR register. + */ +__INLINE uint32_t nxmac_rx_header_head_ptr_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_RX_HEADER_HEAD_PTR_ADDR); + return ((localVal & ((uint32_t)0xFFFFFFFC)) >> 2); +} + +/** + * @brief Sets the rxHeaderHeadPtr field of the RX_HEADER_HEAD_PTR register. + * + * The RX_HEADER_HEAD_PTR register will be read, modified to contain the new field value, and written. + * + * @param[in] rxheaderheadptr - The value to set the field to. + */ +__INLINE void nxmac_rx_header_head_ptr_setf(uint32_t rxheaderheadptr) +{ + ASSERT_ERR((((uint32_t)rxheaderheadptr << 2) & ~((uint32_t)0xFFFFFFFC)) == 0); + REG_PL_WR(NXMAC_RX_HEADER_HEAD_PTR_ADDR, (REG_PL_RD(NXMAC_RX_HEADER_HEAD_PTR_ADDR) & ~((uint32_t)0xFFFFFFFC)) | ((uint32_t)rxheaderheadptr << 2)); +} + +/** + * @brief Returns the current value of the rxHeaderHeadPtrValid field in the RX_HEADER_HEAD_PTR register. + * + * The RX_HEADER_HEAD_PTR register will be read and the rxHeaderHeadPtrValid field's value will be returned. + * + * @return The current value of the rxHeaderHeadPtrValid field in the RX_HEADER_HEAD_PTR register. + */ +__INLINE uint8_t nxmac_rx_header_head_ptr_valid_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_RX_HEADER_HEAD_PTR_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/** + * @brief Sets the rxHeaderHeadPtrValid field of the RX_HEADER_HEAD_PTR register. + * + * The RX_HEADER_HEAD_PTR register will be read, modified to contain the new field value, and written. + * + * @param[in] rxheaderheadptrvalid - The value to set the field to. + */ +__INLINE void nxmac_rx_header_head_ptr_valid_setf(uint8_t rxheaderheadptrvalid) +{ + ASSERT_ERR((((uint32_t)rxheaderheadptrvalid << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_RX_HEADER_HEAD_PTR_ADDR, (REG_PL_RD(NXMAC_RX_HEADER_HEAD_PTR_ADDR) & ~((uint32_t)0x00000001)) | ((uint32_t)rxheaderheadptrvalid << 0)); +} + +/// @} + +/** + * @name RX_PAYLOAD_HEAD_PTR register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:02     rxPayloadHeadPtr   0x0
+ *     00   rxPayloadHeadPtrValid   0
+ * 
+ * + * @{ + */ + +/// Address of the RX_PAYLOAD_HEAD_PTR register +#define NXMAC_RX_PAYLOAD_HEAD_PTR_ADDR 0xC00081BC +/// Offset of the RX_PAYLOAD_HEAD_PTR register from the base address +#define NXMAC_RX_PAYLOAD_HEAD_PTR_OFFSET 0x000001BC +/// Index of the RX_PAYLOAD_HEAD_PTR register +#define NXMAC_RX_PAYLOAD_HEAD_PTR_INDEX 0x0000006F +/// Reset value of the RX_PAYLOAD_HEAD_PTR register +#define NXMAC_RX_PAYLOAD_HEAD_PTR_RESET 0x00000000 + +/** + * @brief Returns the current value of the RX_PAYLOAD_HEAD_PTR register. + * The RX_PAYLOAD_HEAD_PTR register will be read and its value returned. + * @return The current value of the RX_PAYLOAD_HEAD_PTR register. + */ +__INLINE uint32_t nxmac_rx_payload_head_ptr_get(void) +{ + return REG_PL_RD(NXMAC_RX_PAYLOAD_HEAD_PTR_ADDR); +} + +/** + * @brief Sets the RX_PAYLOAD_HEAD_PTR register to a value. + * The RX_PAYLOAD_HEAD_PTR register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_rx_payload_head_ptr_set(uint32_t value) +{ + REG_PL_WR(NXMAC_RX_PAYLOAD_HEAD_PTR_ADDR, value); +} + +// field definitions +/// RX_PAYLOAD_HEAD_PTR field mask +#define NXMAC_RX_PAYLOAD_HEAD_PTR_MASK ((uint32_t)0xFFFFFFFC) +/// RX_PAYLOAD_HEAD_PTR field LSB position +#define NXMAC_RX_PAYLOAD_HEAD_PTR_LSB 2 +/// RX_PAYLOAD_HEAD_PTR field width +#define NXMAC_RX_PAYLOAD_HEAD_PTR_WIDTH ((uint32_t)0x0000001E) +/// RX_PAYLOAD_HEAD_PTR_VALID field bit +#define NXMAC_RX_PAYLOAD_HEAD_PTR_VALID_BIT ((uint32_t)0x00000001) +/// RX_PAYLOAD_HEAD_PTR_VALID field position +#define NXMAC_RX_PAYLOAD_HEAD_PTR_VALID_POS 0 + +/// RX_PAYLOAD_HEAD_PTR field reset value +#define NXMAC_RX_PAYLOAD_HEAD_PTR_RST 0x0 +/// RX_PAYLOAD_HEAD_PTR_VALID field reset value +#define NXMAC_RX_PAYLOAD_HEAD_PTR_VALID_RST 0x0 + +/** + * @brief Constructs a value for the RX_PAYLOAD_HEAD_PTR register given values for its fields + * and writes the value to the register. + * + * @param[in] rxpayloadheadptr - The value to use for the rxPayloadHeadPtr field. + * @param[in] rxpayloadheadptrvalid - The value to use for the rxPayloadHeadPtrValid field. + */ +__INLINE void nxmac_rx_payload_head_ptr_pack(uint32_t rxpayloadheadptr, uint8_t rxpayloadheadptrvalid) +{ + ASSERT_ERR((((uint32_t)rxpayloadheadptr << 2) & ~((uint32_t)0xFFFFFFFC)) == 0); + ASSERT_ERR((((uint32_t)rxpayloadheadptrvalid << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_RX_PAYLOAD_HEAD_PTR_ADDR, ((uint32_t)rxpayloadheadptr << 2) | ((uint32_t)rxpayloadheadptrvalid << 0)); +} + +/** + * @brief Unpacks RX_PAYLOAD_HEAD_PTR's fields from current value of the RX_PAYLOAD_HEAD_PTR register. + * + * Reads the RX_PAYLOAD_HEAD_PTR register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] rxpayloadheadptr - Will be populated with the current value of this field from the register. + * @param[out] rxpayloadheadptrvalid - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_rx_payload_head_ptr_unpack(uint32_t *rxpayloadheadptr, uint8_t *rxpayloadheadptrvalid) +{ + uint32_t localVal = REG_PL_RD(NXMAC_RX_PAYLOAD_HEAD_PTR_ADDR); + + *rxpayloadheadptr = (localVal & ((uint32_t)0xFFFFFFFC)) >> 2; + *rxpayloadheadptrvalid = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +/** + * @brief Returns the current value of the rxPayloadHeadPtr field in the RX_PAYLOAD_HEAD_PTR register. + * + * The RX_PAYLOAD_HEAD_PTR register will be read and the rxPayloadHeadPtr field's value will be returned. + * + * @return The current value of the rxPayloadHeadPtr field in the RX_PAYLOAD_HEAD_PTR register. + */ +__INLINE uint32_t nxmac_rx_payload_head_ptr_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_RX_PAYLOAD_HEAD_PTR_ADDR); + return ((localVal & ((uint32_t)0xFFFFFFFC)) >> 2); +} + +/** + * @brief Sets the rxPayloadHeadPtr field of the RX_PAYLOAD_HEAD_PTR register. + * + * The RX_PAYLOAD_HEAD_PTR register will be read, modified to contain the new field value, and written. + * + * @param[in] rxpayloadheadptr - The value to set the field to. + */ +__INLINE void nxmac_rx_payload_head_ptr_setf(uint32_t rxpayloadheadptr) +{ + ASSERT_ERR((((uint32_t)rxpayloadheadptr << 2) & ~((uint32_t)0xFFFFFFFC)) == 0); + REG_PL_WR(NXMAC_RX_PAYLOAD_HEAD_PTR_ADDR, (REG_PL_RD(NXMAC_RX_PAYLOAD_HEAD_PTR_ADDR) & ~((uint32_t)0xFFFFFFFC)) | ((uint32_t)rxpayloadheadptr << 2)); +} + +/** + * @brief Returns the current value of the rxPayloadHeadPtrValid field in the RX_PAYLOAD_HEAD_PTR register. + * + * The RX_PAYLOAD_HEAD_PTR register will be read and the rxPayloadHeadPtrValid field's value will be returned. + * + * @return The current value of the rxPayloadHeadPtrValid field in the RX_PAYLOAD_HEAD_PTR register. + */ +__INLINE uint8_t nxmac_rx_payload_head_ptr_valid_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_RX_PAYLOAD_HEAD_PTR_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/** + * @brief Sets the rxPayloadHeadPtrValid field of the RX_PAYLOAD_HEAD_PTR register. + * + * The RX_PAYLOAD_HEAD_PTR register will be read, modified to contain the new field value, and written. + * + * @param[in] rxpayloadheadptrvalid - The value to set the field to. + */ +__INLINE void nxmac_rx_payload_head_ptr_valid_setf(uint8_t rxpayloadheadptrvalid) +{ + ASSERT_ERR((((uint32_t)rxpayloadheadptrvalid << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_RX_PAYLOAD_HEAD_PTR_ADDR, (REG_PL_RD(NXMAC_RX_PAYLOAD_HEAD_PTR_ADDR) & ~((uint32_t)0x00000001)) | ((uint32_t)rxpayloadheadptrvalid << 0)); +} + +/// @} + +/** + * @name DMA_THRESHOLD register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  23:16      rxFIFOThreshold   0x10
+ *  07:00      txFIFOThreshold   0x10
+ * 
+ * + * @{ + */ + +/// Address of the DMA_THRESHOLD register +#define NXMAC_DMA_THRESHOLD_ADDR 0xC00081C0 +/// Offset of the DMA_THRESHOLD register from the base address +#define NXMAC_DMA_THRESHOLD_OFFSET 0x000001C0 +/// Index of the DMA_THRESHOLD register +#define NXMAC_DMA_THRESHOLD_INDEX 0x00000070 +/// Reset value of the DMA_THRESHOLD register +#define NXMAC_DMA_THRESHOLD_RESET 0x00100010 + +/** + * @brief Returns the current value of the DMA_THRESHOLD register. + * The DMA_THRESHOLD register will be read and its value returned. + * @return The current value of the DMA_THRESHOLD register. + */ +__INLINE uint32_t nxmac_dma_threshold_get(void) +{ + return REG_PL_RD(NXMAC_DMA_THRESHOLD_ADDR); +} + +/** + * @brief Sets the DMA_THRESHOLD register to a value. + * The DMA_THRESHOLD register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_dma_threshold_set(uint32_t value) +{ + REG_PL_WR(NXMAC_DMA_THRESHOLD_ADDR, value); +} + +// field definitions +/// RX_FIFO_THRESHOLD field mask +#define NXMAC_RX_FIFO_THRESHOLD_MASK ((uint32_t)0x00FF0000) +/// RX_FIFO_THRESHOLD field LSB position +#define NXMAC_RX_FIFO_THRESHOLD_LSB 16 +/// RX_FIFO_THRESHOLD field width +#define NXMAC_RX_FIFO_THRESHOLD_WIDTH ((uint32_t)0x00000008) +/// TX_FIFO_THRESHOLD field mask +#define NXMAC_TX_FIFO_THRESHOLD_MASK ((uint32_t)0x000000FF) +/// TX_FIFO_THRESHOLD field LSB position +#define NXMAC_TX_FIFO_THRESHOLD_LSB 0 +/// TX_FIFO_THRESHOLD field width +#define NXMAC_TX_FIFO_THRESHOLD_WIDTH ((uint32_t)0x00000008) + +/// RX_FIFO_THRESHOLD field reset value +#define NXMAC_RX_FIFO_THRESHOLD_RST 0x10 +/// TX_FIFO_THRESHOLD field reset value +#define NXMAC_TX_FIFO_THRESHOLD_RST 0x10 + +/** + * @brief Constructs a value for the DMA_THRESHOLD register given values for its fields + * and writes the value to the register. + * + * @param[in] rxfifothreshold - The value to use for the rxFIFOThreshold field. + * @param[in] txfifothreshold - The value to use for the txFIFOThreshold field. + */ +__INLINE void nxmac_dma_threshold_pack(uint8_t rxfifothreshold, uint8_t txfifothreshold) +{ + ASSERT_ERR((((uint32_t)rxfifothreshold << 16) & ~((uint32_t)0x00FF0000)) == 0); + ASSERT_ERR((((uint32_t)txfifothreshold << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(NXMAC_DMA_THRESHOLD_ADDR, ((uint32_t)rxfifothreshold << 16) | ((uint32_t)txfifothreshold << 0)); +} + +/** + * @brief Unpacks DMA_THRESHOLD's fields from current value of the DMA_THRESHOLD register. + * + * Reads the DMA_THRESHOLD register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] rxfifothreshold - Will be populated with the current value of this field from the register. + * @param[out] txfifothreshold - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_dma_threshold_unpack(uint8_t *rxfifothreshold, uint8_t *txfifothreshold) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_THRESHOLD_ADDR); + + *rxfifothreshold = (localVal & ((uint32_t)0x00FF0000)) >> 16; + *txfifothreshold = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +/** + * @brief Returns the current value of the rxFIFOThreshold field in the DMA_THRESHOLD register. + * + * The DMA_THRESHOLD register will be read and the rxFIFOThreshold field's value will be returned. + * + * @return The current value of the rxFIFOThreshold field in the DMA_THRESHOLD register. + */ +__INLINE uint8_t nxmac_rx_fifo_threshold_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_THRESHOLD_ADDR); + return ((localVal & ((uint32_t)0x00FF0000)) >> 16); +} + +/** + * @brief Sets the rxFIFOThreshold field of the DMA_THRESHOLD register. + * + * The DMA_THRESHOLD register will be read, modified to contain the new field value, and written. + * + * @param[in] rxfifothreshold - The value to set the field to. + */ +__INLINE void nxmac_rx_fifo_threshold_setf(uint8_t rxfifothreshold) +{ + ASSERT_ERR((((uint32_t)rxfifothreshold << 16) & ~((uint32_t)0x00FF0000)) == 0); + REG_PL_WR(NXMAC_DMA_THRESHOLD_ADDR, (REG_PL_RD(NXMAC_DMA_THRESHOLD_ADDR) & ~((uint32_t)0x00FF0000)) | ((uint32_t)rxfifothreshold << 16)); +} + +/** + * @brief Returns the current value of the txFIFOThreshold field in the DMA_THRESHOLD register. + * + * The DMA_THRESHOLD register will be read and the txFIFOThreshold field's value will be returned. + * + * @return The current value of the txFIFOThreshold field in the DMA_THRESHOLD register. + */ +__INLINE uint8_t nxmac_tx_fifo_threshold_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DMA_THRESHOLD_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +/** + * @brief Sets the txFIFOThreshold field of the DMA_THRESHOLD register. + * + * The DMA_THRESHOLD register will be read, modified to contain the new field value, and written. + * + * @param[in] txfifothreshold - The value to set the field to. + */ +__INLINE void nxmac_tx_fifo_threshold_setf(uint8_t txfifothreshold) +{ + ASSERT_ERR((((uint32_t)txfifothreshold << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(NXMAC_DMA_THRESHOLD_ADDR, (REG_PL_RD(NXMAC_DMA_THRESHOLD_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)txfifothreshold << 0)); +} + +/// @} + +/** + * @name EDCA_AC_HAS_DATA_SET register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     03           ac3HasData   0
+ *     02           ac2HasData   0
+ *     01           ac1HasData   0
+ *     00           ac0HasData   0
+ * 
+ * + * @{ + */ + +/// Address of the EDCA_AC_HAS_DATA_SET register +#define NXMAC_EDCA_AC_HAS_DATA_SET_ADDR 0xC0008210 +/// Offset of the EDCA_AC_HAS_DATA_SET register from the base address +#define NXMAC_EDCA_AC_HAS_DATA_SET_OFFSET 0x00000210 +/// Index of the EDCA_AC_HAS_DATA_SET register +#define NXMAC_EDCA_AC_HAS_DATA_SET_INDEX 0x00000084 +/// Reset value of the EDCA_AC_HAS_DATA_SET register +#define NXMAC_EDCA_AC_HAS_DATA_SET_RESET 0x00000000 + +/** + * @brief Returns the current value of the EDCA_AC_HAS_DATA_SET register. + * The EDCA_AC_HAS_DATA_SET register will be read and its value returned. + * @return The current value of the EDCA_AC_HAS_DATA_SET register. + */ +__INLINE uint32_t nxmac_edca_ac_has_data_get(void) +{ + return REG_PL_RD(NXMAC_EDCA_AC_HAS_DATA_SET_ADDR); +} + +/** + * @brief Sets the EDCA_AC_HAS_DATA_SET register to a value. + * The EDCA_AC_HAS_DATA_SET register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_edca_ac_has_data_set(uint32_t value) +{ + REG_PL_WR(NXMAC_EDCA_AC_HAS_DATA_SET_ADDR, value); +} + +// field definitions +/// AC_3_HAS_DATA field bit +#define NXMAC_AC_3_HAS_DATA_BIT ((uint32_t)0x00000008) +/// AC_3_HAS_DATA field position +#define NXMAC_AC_3_HAS_DATA_POS 3 +/// AC_2_HAS_DATA field bit +#define NXMAC_AC_2_HAS_DATA_BIT ((uint32_t)0x00000004) +/// AC_2_HAS_DATA field position +#define NXMAC_AC_2_HAS_DATA_POS 2 +/// AC_1_HAS_DATA field bit +#define NXMAC_AC_1_HAS_DATA_BIT ((uint32_t)0x00000002) +/// AC_1_HAS_DATA field position +#define NXMAC_AC_1_HAS_DATA_POS 1 +/// AC_0_HAS_DATA field bit +#define NXMAC_AC_0_HAS_DATA_BIT ((uint32_t)0x00000001) +/// AC_0_HAS_DATA field position +#define NXMAC_AC_0_HAS_DATA_POS 0 + +/// AC_3_HAS_DATA field reset value +#define NXMAC_AC_3_HAS_DATA_RST 0x0 +/// AC_2_HAS_DATA field reset value +#define NXMAC_AC_2_HAS_DATA_RST 0x0 +/// AC_1_HAS_DATA field reset value +#define NXMAC_AC_1_HAS_DATA_RST 0x0 +/// AC_0_HAS_DATA field reset value +#define NXMAC_AC_0_HAS_DATA_RST 0x0 + +/** + * @brief Constructs a value for the EDCA_AC_HAS_DATA_SET register given values for its fields + * and writes the value to the register. + * + * @param[in] ac3hasdata - The value to use for the ac3HasData field. + * @param[in] ac2hasdata - The value to use for the ac2HasData field. + * @param[in] ac1hasdata - The value to use for the ac1HasData field. + * @param[in] ac0hasdata - The value to use for the ac0HasData field. + */ +__INLINE void nxmac_edca_ac_has_data_set_pack(uint8_t ac3hasdata, uint8_t ac2hasdata, uint8_t ac1hasdata, uint8_t ac0hasdata) +{ + ASSERT_ERR((((uint32_t)ac3hasdata << 3) & ~((uint32_t)0x00000008)) == 0); + ASSERT_ERR((((uint32_t)ac2hasdata << 2) & ~((uint32_t)0x00000004)) == 0); + ASSERT_ERR((((uint32_t)ac1hasdata << 1) & ~((uint32_t)0x00000002)) == 0); + ASSERT_ERR((((uint32_t)ac0hasdata << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_EDCA_AC_HAS_DATA_SET_ADDR, ((uint32_t)ac3hasdata << 3) | ((uint32_t)ac2hasdata << 2) | ((uint32_t)ac1hasdata << 1) | ((uint32_t)ac0hasdata << 0)); +} + +/** + * @brief Unpacks EDCA_AC_HAS_DATA_SET's fields from current value of the EDCA_AC_HAS_DATA_SET register. + * + * Reads the EDCA_AC_HAS_DATA_SET register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] ac3hasdata - Will be populated with the current value of this field from the register. + * @param[out] ac2hasdata - Will be populated with the current value of this field from the register. + * @param[out] ac1hasdata - Will be populated with the current value of this field from the register. + * @param[out] ac0hasdata - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_edca_ac_has_data_unpack(uint8_t *ac3hasdata, uint8_t *ac2hasdata, uint8_t *ac1hasdata, uint8_t *ac0hasdata) +{ + uint32_t localVal = REG_PL_RD(NXMAC_EDCA_AC_HAS_DATA_SET_ADDR); + + *ac3hasdata = (localVal & ((uint32_t)0x00000008)) >> 3; + *ac2hasdata = (localVal & ((uint32_t)0x00000004)) >> 2; + *ac1hasdata = (localVal & ((uint32_t)0x00000002)) >> 1; + *ac0hasdata = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +/** + * @brief Returns the current value of the ac3HasData field in the EDCA_AC_HAS_DATA_SET register. + * + * The EDCA_AC_HAS_DATA_SET register will be read and the ac3HasData field's value will be returned. + * + * @return The current value of the ac3HasData field in the EDCA_AC_HAS_DATA_SET register. + */ +__INLINE uint8_t nxmac_ac_3_has_data_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_EDCA_AC_HAS_DATA_SET_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +/** + * @brief Sets the ac3HasData field of the EDCA_AC_HAS_DATA_SET register. + * + * The EDCA_AC_HAS_DATA_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] ac3hasdata - The value to set the field to. + */ +__INLINE void nxmac_ac_3_has_data_setf(uint8_t ac3hasdata) +{ + ASSERT_ERR((((uint32_t)ac3hasdata << 3) & ~((uint32_t)0x00000008)) == 0); + REG_PL_WR(NXMAC_EDCA_AC_HAS_DATA_SET_ADDR, (uint32_t)ac3hasdata << 3); +} + +/** + * @brief Returns the current value of the ac2HasData field in the EDCA_AC_HAS_DATA_SET register. + * + * The EDCA_AC_HAS_DATA_SET register will be read and the ac2HasData field's value will be returned. + * + * @return The current value of the ac2HasData field in the EDCA_AC_HAS_DATA_SET register. + */ +__INLINE uint8_t nxmac_ac_2_has_data_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_EDCA_AC_HAS_DATA_SET_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +/** + * @brief Sets the ac2HasData field of the EDCA_AC_HAS_DATA_SET register. + * + * The EDCA_AC_HAS_DATA_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] ac2hasdata - The value to set the field to. + */ +__INLINE void nxmac_ac_2_has_data_setf(uint8_t ac2hasdata) +{ + ASSERT_ERR((((uint32_t)ac2hasdata << 2) & ~((uint32_t)0x00000004)) == 0); + REG_PL_WR(NXMAC_EDCA_AC_HAS_DATA_SET_ADDR, (uint32_t)ac2hasdata << 2); +} + +/** + * @brief Returns the current value of the ac1HasData field in the EDCA_AC_HAS_DATA_SET register. + * + * The EDCA_AC_HAS_DATA_SET register will be read and the ac1HasData field's value will be returned. + * + * @return The current value of the ac1HasData field in the EDCA_AC_HAS_DATA_SET register. + */ +__INLINE uint8_t nxmac_ac_1_has_data_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_EDCA_AC_HAS_DATA_SET_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +/** + * @brief Sets the ac1HasData field of the EDCA_AC_HAS_DATA_SET register. + * + * The EDCA_AC_HAS_DATA_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] ac1hasdata - The value to set the field to. + */ +__INLINE void nxmac_ac_1_has_data_setf(uint8_t ac1hasdata) +{ + ASSERT_ERR((((uint32_t)ac1hasdata << 1) & ~((uint32_t)0x00000002)) == 0); + REG_PL_WR(NXMAC_EDCA_AC_HAS_DATA_SET_ADDR, (uint32_t)ac1hasdata << 1); +} + +/** + * @brief Returns the current value of the ac0HasData field in the EDCA_AC_HAS_DATA_SET register. + * + * The EDCA_AC_HAS_DATA_SET register will be read and the ac0HasData field's value will be returned. + * + * @return The current value of the ac0HasData field in the EDCA_AC_HAS_DATA_SET register. + */ +__INLINE uint8_t nxmac_ac_0_has_data_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_EDCA_AC_HAS_DATA_SET_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/** + * @brief Sets the ac0HasData field of the EDCA_AC_HAS_DATA_SET register. + * + * The EDCA_AC_HAS_DATA_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] ac0hasdata - The value to set the field to. + */ +__INLINE void nxmac_ac_0_has_data_setf(uint8_t ac0hasdata) +{ + ASSERT_ERR((((uint32_t)ac0hasdata << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_EDCA_AC_HAS_DATA_SET_ADDR, (uint32_t)ac0hasdata << 0); +} + +/// @} + +/** + * @name EDCA_AC_HAS_DATA_CLEAR register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     03           ac3HasData   0
+ *     02           ac2HasData   0
+ *     01           ac1HasData   0
+ *     00           ac0HasData   0
+ * 
+ * + * @{ + */ + +/// Address of the EDCA_AC_HAS_DATA_CLEAR register +#define NXMAC_EDCA_AC_HAS_DATA_CLEAR_ADDR 0xC0008214 +/// Offset of the EDCA_AC_HAS_DATA_CLEAR register from the base address +#define NXMAC_EDCA_AC_HAS_DATA_CLEAR_OFFSET 0x00000214 +/// Index of the EDCA_AC_HAS_DATA_CLEAR register +#define NXMAC_EDCA_AC_HAS_DATA_CLEAR_INDEX 0x00000085 +/// Reset value of the EDCA_AC_HAS_DATA_CLEAR register +#define NXMAC_EDCA_AC_HAS_DATA_CLEAR_RESET 0x00000000 + +/** + * @brief Sets the EDCA_AC_HAS_DATA_CLEAR register to a value. + * The EDCA_AC_HAS_DATA_CLEAR register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_edca_ac_has_data_clear(uint32_t value) +{ + REG_PL_WR(NXMAC_EDCA_AC_HAS_DATA_CLEAR_ADDR, value); +} + +// fields defined in symmetrical set/clear register +/** + * @brief Constructs a value for the EDCA_AC_HAS_DATA_CLEAR register given values for its fields + * and writes the value to the register. + * + * @param[in] ac3hasdata - The value to use for the ac3HasData field. + * @param[in] ac2hasdata - The value to use for the ac2HasData field. + * @param[in] ac1hasdata - The value to use for the ac1HasData field. + * @param[in] ac0hasdata - The value to use for the ac0HasData field. + */ +__INLINE void nxmac_edca_ac_has_data_clear_pack(uint8_t ac3hasdata, uint8_t ac2hasdata, uint8_t ac1hasdata, uint8_t ac0hasdata) +{ + ASSERT_ERR((((uint32_t)ac3hasdata << 3) & ~((uint32_t)0x00000008)) == 0); + ASSERT_ERR((((uint32_t)ac2hasdata << 2) & ~((uint32_t)0x00000004)) == 0); + ASSERT_ERR((((uint32_t)ac1hasdata << 1) & ~((uint32_t)0x00000002)) == 0); + ASSERT_ERR((((uint32_t)ac0hasdata << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_EDCA_AC_HAS_DATA_CLEAR_ADDR, ((uint32_t)ac3hasdata << 3) | ((uint32_t)ac2hasdata << 2) | ((uint32_t)ac1hasdata << 1) | ((uint32_t)ac0hasdata << 0)); +} + +/** + * @brief Sets the ac3HasData field of the EDCA_AC_HAS_DATA_CLEAR register. + * + * The EDCA_AC_HAS_DATA_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] ac3hasdata - The value to set the field to. + */ +__INLINE void nxmac_ac_3_has_data_clearf(uint8_t ac3hasdata) +{ + ASSERT_ERR((((uint32_t)ac3hasdata << 3) & ~((uint32_t)0x00000008)) == 0); + REG_PL_WR(NXMAC_EDCA_AC_HAS_DATA_CLEAR_ADDR, (uint32_t)ac3hasdata << 3); +} + +/** + * @brief Sets the ac2HasData field of the EDCA_AC_HAS_DATA_CLEAR register. + * + * The EDCA_AC_HAS_DATA_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] ac2hasdata - The value to set the field to. + */ +__INLINE void nxmac_ac_2_has_data_clearf(uint8_t ac2hasdata) +{ + ASSERT_ERR((((uint32_t)ac2hasdata << 2) & ~((uint32_t)0x00000004)) == 0); + REG_PL_WR(NXMAC_EDCA_AC_HAS_DATA_CLEAR_ADDR, (uint32_t)ac2hasdata << 2); +} + +/** + * @brief Sets the ac1HasData field of the EDCA_AC_HAS_DATA_CLEAR register. + * + * The EDCA_AC_HAS_DATA_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] ac1hasdata - The value to set the field to. + */ +__INLINE void nxmac_ac_1_has_data_clearf(uint8_t ac1hasdata) +{ + ASSERT_ERR((((uint32_t)ac1hasdata << 1) & ~((uint32_t)0x00000002)) == 0); + REG_PL_WR(NXMAC_EDCA_AC_HAS_DATA_CLEAR_ADDR, (uint32_t)ac1hasdata << 1); +} + +/** + * @brief Sets the ac0HasData field of the EDCA_AC_HAS_DATA_CLEAR register. + * + * The EDCA_AC_HAS_DATA_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] ac0hasdata - The value to set the field to. + */ +__INLINE void nxmac_ac_0_has_data_clearf(uint8_t ac0hasdata) +{ + ASSERT_ERR((((uint32_t)ac0hasdata << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_EDCA_AC_HAS_DATA_CLEAR_ADDR, (uint32_t)ac0hasdata << 0); +} + +/// @} + +/** + * @name MOT_1 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:16               ac1MOT   0x0
+ *  15:00               ac0MOT   0x0
+ * 
+ * + * @{ + */ + +/// Address of the MOT_1 register +#define NXMAC_MOT_1_ADDR 0xC0008228 +/// Offset of the MOT_1 register from the base address +#define NXMAC_MOT_1_OFFSET 0x00000228 +/// Index of the MOT_1 register +#define NXMAC_MOT_1_INDEX 0x0000008A +/// Reset value of the MOT_1 register +#define NXMAC_MOT_1_RESET 0x00000000 + +/** + * @brief Returns the current value of the MOT_1 register. + * The MOT_1 register will be read and its value returned. + * @return The current value of the MOT_1 register. + */ +__INLINE uint32_t nxmac_mot_1_get(void) +{ + return REG_PL_RD(NXMAC_MOT_1_ADDR); +} + +// field definitions +/// AC_1MOT field mask +#define NXMAC_AC_1MOT_MASK ((uint32_t)0xFFFF0000) +/// AC_1MOT field LSB position +#define NXMAC_AC_1MOT_LSB 16 +/// AC_1MOT field width +#define NXMAC_AC_1MOT_WIDTH ((uint32_t)0x00000010) +/// AC_0MOT field mask +#define NXMAC_AC_0MOT_MASK ((uint32_t)0x0000FFFF) +/// AC_0MOT field LSB position +#define NXMAC_AC_0MOT_LSB 0 +/// AC_0MOT field width +#define NXMAC_AC_0MOT_WIDTH ((uint32_t)0x00000010) + +/// AC_1MOT field reset value +#define NXMAC_AC_1MOT_RST 0x0 +/// AC_0MOT field reset value +#define NXMAC_AC_0MOT_RST 0x0 + +/** + * @brief Unpacks MOT_1's fields from current value of the MOT_1 register. + * + * Reads the MOT_1 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] ac1mot - Will be populated with the current value of this field from the register. + * @param[out] ac0mot - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_mot_1_unpack(uint16_t *ac1mot, uint16_t *ac0mot) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MOT_1_ADDR); + + *ac1mot = (localVal & ((uint32_t)0xFFFF0000)) >> 16; + *ac0mot = (localVal & ((uint32_t)0x0000FFFF)) >> 0; +} + +/** + * @brief Returns the current value of the ac1MOT field in the MOT_1 register. + * + * The MOT_1 register will be read and the ac1MOT field's value will be returned. + * + * @return The current value of the ac1MOT field in the MOT_1 register. + */ +__INLINE uint16_t nxmac_ac_1mot_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MOT_1_ADDR); + return ((localVal & ((uint32_t)0xFFFF0000)) >> 16); +} + +/** + * @brief Returns the current value of the ac0MOT field in the MOT_1 register. + * + * The MOT_1 register will be read and the ac0MOT field's value will be returned. + * + * @return The current value of the ac0MOT field in the MOT_1 register. + */ +__INLINE uint16_t nxmac_ac_0mot_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MOT_1_ADDR); + return ((localVal & ((uint32_t)0x0000FFFF)) >> 0); +} + +/// @} + +/** + * @name MOT_2 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:16               ac3MOT   0x2F
+ *  15:00               ac2MOT   0x5E
+ * 
+ * + * @{ + */ + +/// Address of the MOT_2 register +#define NXMAC_MOT_2_ADDR 0xC000822C +/// Offset of the MOT_2 register from the base address +#define NXMAC_MOT_2_OFFSET 0x0000022C +/// Index of the MOT_2 register +#define NXMAC_MOT_2_INDEX 0x0000008B +/// Reset value of the MOT_2 register +#define NXMAC_MOT_2_RESET 0x002F005E + +/** + * @brief Returns the current value of the MOT_2 register. + * The MOT_2 register will be read and its value returned. + * @return The current value of the MOT_2 register. + */ +__INLINE uint32_t nxmac_mot_2_get(void) +{ + return REG_PL_RD(NXMAC_MOT_2_ADDR); +} + +// field definitions +/// AC_3MOT field mask +#define NXMAC_AC_3MOT_MASK ((uint32_t)0xFFFF0000) +/// AC_3MOT field LSB position +#define NXMAC_AC_3MOT_LSB 16 +/// AC_3MOT field width +#define NXMAC_AC_3MOT_WIDTH ((uint32_t)0x00000010) +/// AC_2MOT field mask +#define NXMAC_AC_2MOT_MASK ((uint32_t)0x0000FFFF) +/// AC_2MOT field LSB position +#define NXMAC_AC_2MOT_LSB 0 +/// AC_2MOT field width +#define NXMAC_AC_2MOT_WIDTH ((uint32_t)0x00000010) + +/// AC_3MOT field reset value +#define NXMAC_AC_3MOT_RST 0x2F +/// AC_2MOT field reset value +#define NXMAC_AC_2MOT_RST 0x5E + +/** + * @brief Unpacks MOT_2's fields from current value of the MOT_2 register. + * + * Reads the MOT_2 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] ac3mot - Will be populated with the current value of this field from the register. + * @param[out] ac2mot - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_mot_2_unpack(uint16_t *ac3mot, uint16_t *ac2mot) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MOT_2_ADDR); + + *ac3mot = (localVal & ((uint32_t)0xFFFF0000)) >> 16; + *ac2mot = (localVal & ((uint32_t)0x0000FFFF)) >> 0; +} + +/** + * @brief Returns the current value of the ac3MOT field in the MOT_2 register. + * + * The MOT_2 register will be read and the ac3MOT field's value will be returned. + * + * @return The current value of the ac3MOT field in the MOT_2 register. + */ +__INLINE uint16_t nxmac_ac_3mot_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MOT_2_ADDR); + return ((localVal & ((uint32_t)0xFFFF0000)) >> 16); +} + +/** + * @brief Returns the current value of the ac2MOT field in the MOT_2 register. + * + * The MOT_2 register will be read and the ac2MOT field's value will be returned. + * + * @return The current value of the ac2MOT field in the MOT_2 register. + */ +__INLINE uint16_t nxmac_ac_2mot_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MOT_2_ADDR); + return ((localVal & ((uint32_t)0x0000FFFF)) >> 0); +} + +/// @} + +/** + * @name MOT_3 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:16              miscMOT   0x0
+ *  15:00           hccaQAPMOT   0x0
+ * 
+ * + * @{ + */ + +/// Address of the MOT_3 register +#define NXMAC_MOT_3_ADDR 0xC0008230 +/// Offset of the MOT_3 register from the base address +#define NXMAC_MOT_3_OFFSET 0x00000230 +/// Index of the MOT_3 register +#define NXMAC_MOT_3_INDEX 0x0000008C +/// Reset value of the MOT_3 register +#define NXMAC_MOT_3_RESET 0x00000000 + +/** + * @brief Returns the current value of the MOT_3 register. + * The MOT_3 register will be read and its value returned. + * @return The current value of the MOT_3 register. + */ +__INLINE uint32_t nxmac_mot_3_get(void) +{ + return REG_PL_RD(NXMAC_MOT_3_ADDR); +} + +// field definitions +/// MISC_MOT field mask +#define NXMAC_MISC_MOT_MASK ((uint32_t)0xFFFF0000) +/// MISC_MOT field LSB position +#define NXMAC_MISC_MOT_LSB 16 +/// MISC_MOT field width +#define NXMAC_MISC_MOT_WIDTH ((uint32_t)0x00000010) +/// HCCA_QAPMOT field mask +#define NXMAC_HCCA_QAPMOT_MASK ((uint32_t)0x0000FFFF) +/// HCCA_QAPMOT field LSB position +#define NXMAC_HCCA_QAPMOT_LSB 0 +/// HCCA_QAPMOT field width +#define NXMAC_HCCA_QAPMOT_WIDTH ((uint32_t)0x00000010) + +/// MISC_MOT field reset value +#define NXMAC_MISC_MOT_RST 0x0 +/// HCCA_QAPMOT field reset value +#define NXMAC_HCCA_QAPMOT_RST 0x0 + +/** + * @brief Unpacks MOT_3's fields from current value of the MOT_3 register. + * + * Reads the MOT_3 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] miscmot - Will be populated with the current value of this field from the register. + * @param[out] hccaqapmot - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_mot_3_unpack(uint16_t *miscmot, uint16_t *hccaqapmot) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MOT_3_ADDR); + + *miscmot = (localVal & ((uint32_t)0xFFFF0000)) >> 16; + *hccaqapmot = (localVal & ((uint32_t)0x0000FFFF)) >> 0; +} + +/** + * @brief Returns the current value of the miscMOT field in the MOT_3 register. + * + * The MOT_3 register will be read and the miscMOT field's value will be returned. + * + * @return The current value of the miscMOT field in the MOT_3 register. + */ +__INLINE uint16_t nxmac_misc_mot_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MOT_3_ADDR); + return ((localVal & ((uint32_t)0xFFFF0000)) >> 16); +} + +/** + * @brief Returns the current value of the hccaQAPMOT field in the MOT_3 register. + * + * The MOT_3 register will be read and the hccaQAPMOT field's value will be returned. + * + * @return The current value of the hccaQAPMOT field in the MOT_3 register. + */ +__INLINE uint16_t nxmac_hcca_qapmot_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_MOT_3_ADDR); + return ((localVal & ((uint32_t)0x0000FFFF)) >> 0); +} + +/// @} + +/** + * @name TX_BW_DROP_INFO register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  01:00        txBWAfterDrop   0x0
+ * 
+ * + * @{ + */ + +/// Address of the TX_BW_DROP_INFO register +#define NXMAC_TX_BW_DROP_INFO_ADDR 0xC0008330 +/// Offset of the TX_BW_DROP_INFO register from the base address +#define NXMAC_TX_BW_DROP_INFO_OFFSET 0x00000330 +/// Index of the TX_BW_DROP_INFO register +#define NXMAC_TX_BW_DROP_INFO_INDEX 0x000000CC +/// Reset value of the TX_BW_DROP_INFO register +#define NXMAC_TX_BW_DROP_INFO_RESET 0x00000000 + +/** + * @brief Returns the current value of the TX_BW_DROP_INFO register. + * The TX_BW_DROP_INFO register will be read and its value returned. + * @return The current value of the TX_BW_DROP_INFO register. + */ +__INLINE uint32_t nxmac_tx_bw_drop_info_get(void) +{ + return REG_PL_RD(NXMAC_TX_BW_DROP_INFO_ADDR); +} + +// field definitions +/// TX_BW_AFTER_DROP field mask +#define NXMAC_TX_BW_AFTER_DROP_MASK ((uint32_t)0x00000003) +/// TX_BW_AFTER_DROP field LSB position +#define NXMAC_TX_BW_AFTER_DROP_LSB 0 +/// TX_BW_AFTER_DROP field width +#define NXMAC_TX_BW_AFTER_DROP_WIDTH ((uint32_t)0x00000002) + +/// TX_BW_AFTER_DROP field reset value +#define NXMAC_TX_BW_AFTER_DROP_RST 0x0 + +/** + * @brief Returns the current value of the txBWAfterDrop field in the TX_BW_DROP_INFO register. + * + * The TX_BW_DROP_INFO register will be read and the txBWAfterDrop field's value will be returned. + * + * @return The current value of the txBWAfterDrop field in the TX_BW_DROP_INFO register. + */ +__INLINE uint8_t nxmac_tx_bw_after_drop_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_TX_BW_DROP_INFO_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x00000003)) == 0); + return (localVal >> 0); +} + +/// @} + +#if RW_MUMIMO_TX_EN +/** + * @name SEC_USERS_TX_INT_EVENT_SET register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     23   secU3ac3TxBufTrigger   0
+ *     22   secU3ac2TxBufTrigger   0
+ *     21   secU3ac1TxBufTrigger   0
+ *     20   secU3ac0TxBufTrigger   0
+ *     19    secU3ac3TxTrigger   0
+ *     18    secU3ac2TxTrigger   0
+ *     17    secU3ac1TxTrigger   0
+ *     16    secU3ac0TxTrigger   0
+ *     15   secU2ac3TxBufTrigger   0
+ *     14   secU2ac2TxBufTrigger   0
+ *     13   secU2ac1TxBufTrigger   0
+ *     12   secU2ac0TxBufTrigger   0
+ *     11    secU2ac3TxTrigger   0
+ *     10    secU2ac2TxTrigger   0
+ *     09    secU2ac1TxTrigger   0
+ *     08    secU2ac0TxTrigger   0
+ *     07   secU1ac3TxBufTrigger   0
+ *     06   secU1ac2TxBufTrigger   0
+ *     05   secU1ac1TxBufTrigger   0
+ *     04   secU1ac0TxBufTrigger   0
+ *     03    secU1ac3TxTrigger   0
+ *     02    secU1ac2TxTrigger   0
+ *     01    secU1ac1TxTrigger   0
+ *     00    secU1ac0TxTrigger   0
+ * 
+ * + * @{ + */ + +/// Address of the SEC_USERS_TX_INT_EVENT_SET register +#define NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR 0xC0008364 +/// Offset of the SEC_USERS_TX_INT_EVENT_SET register from the base address +#define NXMAC_SEC_USERS_TX_INT_EVENT_SET_OFFSET 0x00000364 +/// Index of the SEC_USERS_TX_INT_EVENT_SET register +#define NXMAC_SEC_USERS_TX_INT_EVENT_SET_INDEX 0x000000D9 +/// Reset value of the SEC_USERS_TX_INT_EVENT_SET register +#define NXMAC_SEC_USERS_TX_INT_EVENT_SET_RESET 0x00000000 + +/** + * @brief Returns the current value of the SEC_USERS_TX_INT_EVENT_SET register. + * The SEC_USERS_TX_INT_EVENT_SET register will be read and its value returned. + * @return The current value of the SEC_USERS_TX_INT_EVENT_SET register. + */ +__INLINE uint32_t nxmac_sec_users_tx_int_event_get(void) +{ + return REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR); +} + +/** + * @brief Sets the SEC_USERS_TX_INT_EVENT_SET register to a value. + * The SEC_USERS_TX_INT_EVENT_SET register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_sec_users_tx_int_event_set(uint32_t value) +{ + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR, value); +} + +// field definitions +/// SEC_U_3AC_3_TX_BUF_TRIGGER field bit +#define NXMAC_SEC_U_3AC_3_TX_BUF_TRIGGER_BIT ((uint32_t)0x00800000) +/// SEC_U_3AC_3_TX_BUF_TRIGGER field position +#define NXMAC_SEC_U_3AC_3_TX_BUF_TRIGGER_POS 23 +/// SEC_U_3AC_2_TX_BUF_TRIGGER field bit +#define NXMAC_SEC_U_3AC_2_TX_BUF_TRIGGER_BIT ((uint32_t)0x00400000) +/// SEC_U_3AC_2_TX_BUF_TRIGGER field position +#define NXMAC_SEC_U_3AC_2_TX_BUF_TRIGGER_POS 22 +/// SEC_U_3AC_1_TX_BUF_TRIGGER field bit +#define NXMAC_SEC_U_3AC_1_TX_BUF_TRIGGER_BIT ((uint32_t)0x00200000) +/// SEC_U_3AC_1_TX_BUF_TRIGGER field position +#define NXMAC_SEC_U_3AC_1_TX_BUF_TRIGGER_POS 21 +/// SEC_U_3AC_0_TX_BUF_TRIGGER field bit +#define NXMAC_SEC_U_3AC_0_TX_BUF_TRIGGER_BIT ((uint32_t)0x00100000) +/// SEC_U_3AC_0_TX_BUF_TRIGGER field position +#define NXMAC_SEC_U_3AC_0_TX_BUF_TRIGGER_POS 20 +/// SEC_U_3AC_3_TX_TRIGGER field bit +#define NXMAC_SEC_U_3AC_3_TX_TRIGGER_BIT ((uint32_t)0x00080000) +/// SEC_U_3AC_3_TX_TRIGGER field position +#define NXMAC_SEC_U_3AC_3_TX_TRIGGER_POS 19 +/// SEC_U_3AC_2_TX_TRIGGER field bit +#define NXMAC_SEC_U_3AC_2_TX_TRIGGER_BIT ((uint32_t)0x00040000) +/// SEC_U_3AC_2_TX_TRIGGER field position +#define NXMAC_SEC_U_3AC_2_TX_TRIGGER_POS 18 +/// SEC_U_3AC_1_TX_TRIGGER field bit +#define NXMAC_SEC_U_3AC_1_TX_TRIGGER_BIT ((uint32_t)0x00020000) +/// SEC_U_3AC_1_TX_TRIGGER field position +#define NXMAC_SEC_U_3AC_1_TX_TRIGGER_POS 17 +/// SEC_U_3AC_0_TX_TRIGGER field bit +#define NXMAC_SEC_U_3AC_0_TX_TRIGGER_BIT ((uint32_t)0x00010000) +/// SEC_U_3AC_0_TX_TRIGGER field position +#define NXMAC_SEC_U_3AC_0_TX_TRIGGER_POS 16 +/// SEC_U_2AC_3_TX_BUF_TRIGGER field bit +#define NXMAC_SEC_U_2AC_3_TX_BUF_TRIGGER_BIT ((uint32_t)0x00008000) +/// SEC_U_2AC_3_TX_BUF_TRIGGER field position +#define NXMAC_SEC_U_2AC_3_TX_BUF_TRIGGER_POS 15 +/// SEC_U_2AC_2_TX_BUF_TRIGGER field bit +#define NXMAC_SEC_U_2AC_2_TX_BUF_TRIGGER_BIT ((uint32_t)0x00004000) +/// SEC_U_2AC_2_TX_BUF_TRIGGER field position +#define NXMAC_SEC_U_2AC_2_TX_BUF_TRIGGER_POS 14 +/// SEC_U_2AC_1_TX_BUF_TRIGGER field bit +#define NXMAC_SEC_U_2AC_1_TX_BUF_TRIGGER_BIT ((uint32_t)0x00002000) +/// SEC_U_2AC_1_TX_BUF_TRIGGER field position +#define NXMAC_SEC_U_2AC_1_TX_BUF_TRIGGER_POS 13 +/// SEC_U_2AC_0_TX_BUF_TRIGGER field bit +#define NXMAC_SEC_U_2AC_0_TX_BUF_TRIGGER_BIT ((uint32_t)0x00001000) +/// SEC_U_2AC_0_TX_BUF_TRIGGER field position +#define NXMAC_SEC_U_2AC_0_TX_BUF_TRIGGER_POS 12 +/// SEC_U_2AC_3_TX_TRIGGER field bit +#define NXMAC_SEC_U_2AC_3_TX_TRIGGER_BIT ((uint32_t)0x00000800) +/// SEC_U_2AC_3_TX_TRIGGER field position +#define NXMAC_SEC_U_2AC_3_TX_TRIGGER_POS 11 +/// SEC_U_2AC_2_TX_TRIGGER field bit +#define NXMAC_SEC_U_2AC_2_TX_TRIGGER_BIT ((uint32_t)0x00000400) +/// SEC_U_2AC_2_TX_TRIGGER field position +#define NXMAC_SEC_U_2AC_2_TX_TRIGGER_POS 10 +/// SEC_U_2AC_1_TX_TRIGGER field bit +#define NXMAC_SEC_U_2AC_1_TX_TRIGGER_BIT ((uint32_t)0x00000200) +/// SEC_U_2AC_1_TX_TRIGGER field position +#define NXMAC_SEC_U_2AC_1_TX_TRIGGER_POS 9 +/// SEC_U_2AC_0_TX_TRIGGER field bit +#define NXMAC_SEC_U_2AC_0_TX_TRIGGER_BIT ((uint32_t)0x00000100) +/// SEC_U_2AC_0_TX_TRIGGER field position +#define NXMAC_SEC_U_2AC_0_TX_TRIGGER_POS 8 +/// SEC_U_1AC_3_TX_BUF_TRIGGER field bit +#define NXMAC_SEC_U_1AC_3_TX_BUF_TRIGGER_BIT ((uint32_t)0x00000080) +/// SEC_U_1AC_3_TX_BUF_TRIGGER field position +#define NXMAC_SEC_U_1AC_3_TX_BUF_TRIGGER_POS 7 +/// SEC_U_1AC_2_TX_BUF_TRIGGER field bit +#define NXMAC_SEC_U_1AC_2_TX_BUF_TRIGGER_BIT ((uint32_t)0x00000040) +/// SEC_U_1AC_2_TX_BUF_TRIGGER field position +#define NXMAC_SEC_U_1AC_2_TX_BUF_TRIGGER_POS 6 +/// SEC_U_1AC_1_TX_BUF_TRIGGER field bit +#define NXMAC_SEC_U_1AC_1_TX_BUF_TRIGGER_BIT ((uint32_t)0x00000020) +/// SEC_U_1AC_1_TX_BUF_TRIGGER field position +#define NXMAC_SEC_U_1AC_1_TX_BUF_TRIGGER_POS 5 +/// SEC_U_1AC_0_TX_BUF_TRIGGER field bit +#define NXMAC_SEC_U_1AC_0_TX_BUF_TRIGGER_BIT ((uint32_t)0x00000010) +/// SEC_U_1AC_0_TX_BUF_TRIGGER field position +#define NXMAC_SEC_U_1AC_0_TX_BUF_TRIGGER_POS 4 +/// SEC_U_1AC_3_TX_TRIGGER field bit +#define NXMAC_SEC_U_1AC_3_TX_TRIGGER_BIT ((uint32_t)0x00000008) +/// SEC_U_1AC_3_TX_TRIGGER field position +#define NXMAC_SEC_U_1AC_3_TX_TRIGGER_POS 3 +/// SEC_U_1AC_2_TX_TRIGGER field bit +#define NXMAC_SEC_U_1AC_2_TX_TRIGGER_BIT ((uint32_t)0x00000004) +/// SEC_U_1AC_2_TX_TRIGGER field position +#define NXMAC_SEC_U_1AC_2_TX_TRIGGER_POS 2 +/// SEC_U_1AC_1_TX_TRIGGER field bit +#define NXMAC_SEC_U_1AC_1_TX_TRIGGER_BIT ((uint32_t)0x00000002) +/// SEC_U_1AC_1_TX_TRIGGER field position +#define NXMAC_SEC_U_1AC_1_TX_TRIGGER_POS 1 +/// SEC_U_1AC_0_TX_TRIGGER field bit +#define NXMAC_SEC_U_1AC_0_TX_TRIGGER_BIT ((uint32_t)0x00000001) +/// SEC_U_1AC_0_TX_TRIGGER field position +#define NXMAC_SEC_U_1AC_0_TX_TRIGGER_POS 0 + +/// SEC_U_3AC_3_TX_BUF_TRIGGER field reset value +#define NXMAC_SEC_U_3AC_3_TX_BUF_TRIGGER_RST 0x0 +/// SEC_U_3AC_2_TX_BUF_TRIGGER field reset value +#define NXMAC_SEC_U_3AC_2_TX_BUF_TRIGGER_RST 0x0 +/// SEC_U_3AC_1_TX_BUF_TRIGGER field reset value +#define NXMAC_SEC_U_3AC_1_TX_BUF_TRIGGER_RST 0x0 +/// SEC_U_3AC_0_TX_BUF_TRIGGER field reset value +#define NXMAC_SEC_U_3AC_0_TX_BUF_TRIGGER_RST 0x0 +/// SEC_U_3AC_3_TX_TRIGGER field reset value +#define NXMAC_SEC_U_3AC_3_TX_TRIGGER_RST 0x0 +/// SEC_U_3AC_2_TX_TRIGGER field reset value +#define NXMAC_SEC_U_3AC_2_TX_TRIGGER_RST 0x0 +/// SEC_U_3AC_1_TX_TRIGGER field reset value +#define NXMAC_SEC_U_3AC_1_TX_TRIGGER_RST 0x0 +/// SEC_U_3AC_0_TX_TRIGGER field reset value +#define NXMAC_SEC_U_3AC_0_TX_TRIGGER_RST 0x0 +/// SEC_U_2AC_3_TX_BUF_TRIGGER field reset value +#define NXMAC_SEC_U_2AC_3_TX_BUF_TRIGGER_RST 0x0 +/// SEC_U_2AC_2_TX_BUF_TRIGGER field reset value +#define NXMAC_SEC_U_2AC_2_TX_BUF_TRIGGER_RST 0x0 +/// SEC_U_2AC_1_TX_BUF_TRIGGER field reset value +#define NXMAC_SEC_U_2AC_1_TX_BUF_TRIGGER_RST 0x0 +/// SEC_U_2AC_0_TX_BUF_TRIGGER field reset value +#define NXMAC_SEC_U_2AC_0_TX_BUF_TRIGGER_RST 0x0 +/// SEC_U_2AC_3_TX_TRIGGER field reset value +#define NXMAC_SEC_U_2AC_3_TX_TRIGGER_RST 0x0 +/// SEC_U_2AC_2_TX_TRIGGER field reset value +#define NXMAC_SEC_U_2AC_2_TX_TRIGGER_RST 0x0 +/// SEC_U_2AC_1_TX_TRIGGER field reset value +#define NXMAC_SEC_U_2AC_1_TX_TRIGGER_RST 0x0 +/// SEC_U_2AC_0_TX_TRIGGER field reset value +#define NXMAC_SEC_U_2AC_0_TX_TRIGGER_RST 0x0 +/// SEC_U_1AC_3_TX_BUF_TRIGGER field reset value +#define NXMAC_SEC_U_1AC_3_TX_BUF_TRIGGER_RST 0x0 +/// SEC_U_1AC_2_TX_BUF_TRIGGER field reset value +#define NXMAC_SEC_U_1AC_2_TX_BUF_TRIGGER_RST 0x0 +/// SEC_U_1AC_1_TX_BUF_TRIGGER field reset value +#define NXMAC_SEC_U_1AC_1_TX_BUF_TRIGGER_RST 0x0 +/// SEC_U_1AC_0_TX_BUF_TRIGGER field reset value +#define NXMAC_SEC_U_1AC_0_TX_BUF_TRIGGER_RST 0x0 +/// SEC_U_1AC_3_TX_TRIGGER field reset value +#define NXMAC_SEC_U_1AC_3_TX_TRIGGER_RST 0x0 +/// SEC_U_1AC_2_TX_TRIGGER field reset value +#define NXMAC_SEC_U_1AC_2_TX_TRIGGER_RST 0x0 +/// SEC_U_1AC_1_TX_TRIGGER field reset value +#define NXMAC_SEC_U_1AC_1_TX_TRIGGER_RST 0x0 +/// SEC_U_1AC_0_TX_TRIGGER field reset value +#define NXMAC_SEC_U_1AC_0_TX_TRIGGER_RST 0x0 + +/** + * @brief Constructs a value for the SEC_USERS_TX_INT_EVENT_SET register given values for its fields + * and writes the value to the register. + * + * @param[in] secu3ac3txbuftrigger - The value to use for the secU3ac3TxBufTrigger field. + * @param[in] secu3ac2txbuftrigger - The value to use for the secU3ac2TxBufTrigger field. + * @param[in] secu3ac1txbuftrigger - The value to use for the secU3ac1TxBufTrigger field. + * @param[in] secu3ac0txbuftrigger - The value to use for the secU3ac0TxBufTrigger field. + * @param[in] secu3ac3txtrigger - The value to use for the secU3ac3TxTrigger field. + * @param[in] secu3ac2txtrigger - The value to use for the secU3ac2TxTrigger field. + * @param[in] secu3ac1txtrigger - The value to use for the secU3ac1TxTrigger field. + * @param[in] secu3ac0txtrigger - The value to use for the secU3ac0TxTrigger field. + * @param[in] secu2ac3txbuftrigger - The value to use for the secU2ac3TxBufTrigger field. + * @param[in] secu2ac2txbuftrigger - The value to use for the secU2ac2TxBufTrigger field. + * @param[in] secu2ac1txbuftrigger - The value to use for the secU2ac1TxBufTrigger field. + * @param[in] secu2ac0txbuftrigger - The value to use for the secU2ac0TxBufTrigger field. + * @param[in] secu2ac3txtrigger - The value to use for the secU2ac3TxTrigger field. + * @param[in] secu2ac2txtrigger - The value to use for the secU2ac2TxTrigger field. + * @param[in] secu2ac1txtrigger - The value to use for the secU2ac1TxTrigger field. + * @param[in] secu2ac0txtrigger - The value to use for the secU2ac0TxTrigger field. + * @param[in] secu1ac3txbuftrigger - The value to use for the secU1ac3TxBufTrigger field. + * @param[in] secu1ac2txbuftrigger - The value to use for the secU1ac2TxBufTrigger field. + * @param[in] secu1ac1txbuftrigger - The value to use for the secU1ac1TxBufTrigger field. + * @param[in] secu1ac0txbuftrigger - The value to use for the secU1ac0TxBufTrigger field. + * @param[in] secu1ac3txtrigger - The value to use for the secU1ac3TxTrigger field. + * @param[in] secu1ac2txtrigger - The value to use for the secU1ac2TxTrigger field. + * @param[in] secu1ac1txtrigger - The value to use for the secU1ac1TxTrigger field. + * @param[in] secu1ac0txtrigger - The value to use for the secU1ac0TxTrigger field. + */ +__INLINE void nxmac_sec_users_tx_int_event_set_pack(uint8_t secu3ac3txbuftrigger, uint8_t secu3ac2txbuftrigger, uint8_t secu3ac1txbuftrigger, uint8_t secu3ac0txbuftrigger, uint8_t secu3ac3txtrigger, uint8_t secu3ac2txtrigger, uint8_t secu3ac1txtrigger, uint8_t secu3ac0txtrigger, uint8_t secu2ac3txbuftrigger, uint8_t secu2ac2txbuftrigger, uint8_t secu2ac1txbuftrigger, uint8_t secu2ac0txbuftrigger, uint8_t secu2ac3txtrigger, uint8_t secu2ac2txtrigger, uint8_t secu2ac1txtrigger, uint8_t secu2ac0txtrigger, uint8_t secu1ac3txbuftrigger, uint8_t secu1ac2txbuftrigger, uint8_t secu1ac1txbuftrigger, uint8_t secu1ac0txbuftrigger, uint8_t secu1ac3txtrigger, uint8_t secu1ac2txtrigger, uint8_t secu1ac1txtrigger, uint8_t secu1ac0txtrigger) +{ + ASSERT_ERR((((uint32_t)secu3ac3txbuftrigger << 23) & ~((uint32_t)0x00800000)) == 0); + ASSERT_ERR((((uint32_t)secu3ac2txbuftrigger << 22) & ~((uint32_t)0x00400000)) == 0); + ASSERT_ERR((((uint32_t)secu3ac1txbuftrigger << 21) & ~((uint32_t)0x00200000)) == 0); + ASSERT_ERR((((uint32_t)secu3ac0txbuftrigger << 20) & ~((uint32_t)0x00100000)) == 0); + ASSERT_ERR((((uint32_t)secu3ac3txtrigger << 19) & ~((uint32_t)0x00080000)) == 0); + ASSERT_ERR((((uint32_t)secu3ac2txtrigger << 18) & ~((uint32_t)0x00040000)) == 0); + ASSERT_ERR((((uint32_t)secu3ac1txtrigger << 17) & ~((uint32_t)0x00020000)) == 0); + ASSERT_ERR((((uint32_t)secu3ac0txtrigger << 16) & ~((uint32_t)0x00010000)) == 0); + ASSERT_ERR((((uint32_t)secu2ac3txbuftrigger << 15) & ~((uint32_t)0x00008000)) == 0); + ASSERT_ERR((((uint32_t)secu2ac2txbuftrigger << 14) & ~((uint32_t)0x00004000)) == 0); + ASSERT_ERR((((uint32_t)secu2ac1txbuftrigger << 13) & ~((uint32_t)0x00002000)) == 0); + ASSERT_ERR((((uint32_t)secu2ac0txbuftrigger << 12) & ~((uint32_t)0x00001000)) == 0); + ASSERT_ERR((((uint32_t)secu2ac3txtrigger << 11) & ~((uint32_t)0x00000800)) == 0); + ASSERT_ERR((((uint32_t)secu2ac2txtrigger << 10) & ~((uint32_t)0x00000400)) == 0); + ASSERT_ERR((((uint32_t)secu2ac1txtrigger << 9) & ~((uint32_t)0x00000200)) == 0); + ASSERT_ERR((((uint32_t)secu2ac0txtrigger << 8) & ~((uint32_t)0x00000100)) == 0); + ASSERT_ERR((((uint32_t)secu1ac3txbuftrigger << 7) & ~((uint32_t)0x00000080)) == 0); + ASSERT_ERR((((uint32_t)secu1ac2txbuftrigger << 6) & ~((uint32_t)0x00000040)) == 0); + ASSERT_ERR((((uint32_t)secu1ac1txbuftrigger << 5) & ~((uint32_t)0x00000020)) == 0); + ASSERT_ERR((((uint32_t)secu1ac0txbuftrigger << 4) & ~((uint32_t)0x00000010)) == 0); + ASSERT_ERR((((uint32_t)secu1ac3txtrigger << 3) & ~((uint32_t)0x00000008)) == 0); + ASSERT_ERR((((uint32_t)secu1ac2txtrigger << 2) & ~((uint32_t)0x00000004)) == 0); + ASSERT_ERR((((uint32_t)secu1ac1txtrigger << 1) & ~((uint32_t)0x00000002)) == 0); + ASSERT_ERR((((uint32_t)secu1ac0txtrigger << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR, ((uint32_t)secu3ac3txbuftrigger << 23) | ((uint32_t)secu3ac2txbuftrigger << 22) | ((uint32_t)secu3ac1txbuftrigger << 21) | ((uint32_t)secu3ac0txbuftrigger << 20) | ((uint32_t)secu3ac3txtrigger << 19) | ((uint32_t)secu3ac2txtrigger << 18) | ((uint32_t)secu3ac1txtrigger << 17) | ((uint32_t)secu3ac0txtrigger << 16) | ((uint32_t)secu2ac3txbuftrigger << 15) | ((uint32_t)secu2ac2txbuftrigger << 14) | ((uint32_t)secu2ac1txbuftrigger << 13) | ((uint32_t)secu2ac0txbuftrigger << 12) | ((uint32_t)secu2ac3txtrigger << 11) | ((uint32_t)secu2ac2txtrigger << 10) | ((uint32_t)secu2ac1txtrigger << 9) | ((uint32_t)secu2ac0txtrigger << 8) | ((uint32_t)secu1ac3txbuftrigger << 7) | ((uint32_t)secu1ac2txbuftrigger << 6) | ((uint32_t)secu1ac1txbuftrigger << 5) | ((uint32_t)secu1ac0txbuftrigger << 4) | ((uint32_t)secu1ac3txtrigger << 3) | ((uint32_t)secu1ac2txtrigger << 2) | ((uint32_t)secu1ac1txtrigger << 1) | ((uint32_t)secu1ac0txtrigger << 0)); +} + +/** + * @brief Unpacks SEC_USERS_TX_INT_EVENT_SET's fields from current value of the SEC_USERS_TX_INT_EVENT_SET register. + * + * Reads the SEC_USERS_TX_INT_EVENT_SET register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] secu3ac3txbuftrigger - Will be populated with the current value of this field from the register. + * @param[out] secu3ac2txbuftrigger - Will be populated with the current value of this field from the register. + * @param[out] secu3ac1txbuftrigger - Will be populated with the current value of this field from the register. + * @param[out] secu3ac0txbuftrigger - Will be populated with the current value of this field from the register. + * @param[out] secu3ac3txtrigger - Will be populated with the current value of this field from the register. + * @param[out] secu3ac2txtrigger - Will be populated with the current value of this field from the register. + * @param[out] secu3ac1txtrigger - Will be populated with the current value of this field from the register. + * @param[out] secu3ac0txtrigger - Will be populated with the current value of this field from the register. + * @param[out] secu2ac3txbuftrigger - Will be populated with the current value of this field from the register. + * @param[out] secu2ac2txbuftrigger - Will be populated with the current value of this field from the register. + * @param[out] secu2ac1txbuftrigger - Will be populated with the current value of this field from the register. + * @param[out] secu2ac0txbuftrigger - Will be populated with the current value of this field from the register. + * @param[out] secu2ac3txtrigger - Will be populated with the current value of this field from the register. + * @param[out] secu2ac2txtrigger - Will be populated with the current value of this field from the register. + * @param[out] secu2ac1txtrigger - Will be populated with the current value of this field from the register. + * @param[out] secu2ac0txtrigger - Will be populated with the current value of this field from the register. + * @param[out] secu1ac3txbuftrigger - Will be populated with the current value of this field from the register. + * @param[out] secu1ac2txbuftrigger - Will be populated with the current value of this field from the register. + * @param[out] secu1ac1txbuftrigger - Will be populated with the current value of this field from the register. + * @param[out] secu1ac0txbuftrigger - Will be populated with the current value of this field from the register. + * @param[out] secu1ac3txtrigger - Will be populated with the current value of this field from the register. + * @param[out] secu1ac2txtrigger - Will be populated with the current value of this field from the register. + * @param[out] secu1ac1txtrigger - Will be populated with the current value of this field from the register. + * @param[out] secu1ac0txtrigger - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_sec_users_tx_int_event_unpack(uint8_t *secu3ac3txbuftrigger, uint8_t *secu3ac2txbuftrigger, uint8_t *secu3ac1txbuftrigger, uint8_t *secu3ac0txbuftrigger, uint8_t *secu3ac3txtrigger, uint8_t *secu3ac2txtrigger, uint8_t *secu3ac1txtrigger, uint8_t *secu3ac0txtrigger, uint8_t *secu2ac3txbuftrigger, uint8_t *secu2ac2txbuftrigger, uint8_t *secu2ac1txbuftrigger, uint8_t *secu2ac0txbuftrigger, uint8_t *secu2ac3txtrigger, uint8_t *secu2ac2txtrigger, uint8_t *secu2ac1txtrigger, uint8_t *secu2ac0txtrigger, uint8_t *secu1ac3txbuftrigger, uint8_t *secu1ac2txbuftrigger, uint8_t *secu1ac1txbuftrigger, uint8_t *secu1ac0txbuftrigger, uint8_t *secu1ac3txtrigger, uint8_t *secu1ac2txtrigger, uint8_t *secu1ac1txtrigger, uint8_t *secu1ac0txtrigger) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR); + + *secu3ac3txbuftrigger = (localVal & ((uint32_t)0x00800000)) >> 23; + *secu3ac2txbuftrigger = (localVal & ((uint32_t)0x00400000)) >> 22; + *secu3ac1txbuftrigger = (localVal & ((uint32_t)0x00200000)) >> 21; + *secu3ac0txbuftrigger = (localVal & ((uint32_t)0x00100000)) >> 20; + *secu3ac3txtrigger = (localVal & ((uint32_t)0x00080000)) >> 19; + *secu3ac2txtrigger = (localVal & ((uint32_t)0x00040000)) >> 18; + *secu3ac1txtrigger = (localVal & ((uint32_t)0x00020000)) >> 17; + *secu3ac0txtrigger = (localVal & ((uint32_t)0x00010000)) >> 16; + *secu2ac3txbuftrigger = (localVal & ((uint32_t)0x00008000)) >> 15; + *secu2ac2txbuftrigger = (localVal & ((uint32_t)0x00004000)) >> 14; + *secu2ac1txbuftrigger = (localVal & ((uint32_t)0x00002000)) >> 13; + *secu2ac0txbuftrigger = (localVal & ((uint32_t)0x00001000)) >> 12; + *secu2ac3txtrigger = (localVal & ((uint32_t)0x00000800)) >> 11; + *secu2ac2txtrigger = (localVal & ((uint32_t)0x00000400)) >> 10; + *secu2ac1txtrigger = (localVal & ((uint32_t)0x00000200)) >> 9; + *secu2ac0txtrigger = (localVal & ((uint32_t)0x00000100)) >> 8; + *secu1ac3txbuftrigger = (localVal & ((uint32_t)0x00000080)) >> 7; + *secu1ac2txbuftrigger = (localVal & ((uint32_t)0x00000040)) >> 6; + *secu1ac1txbuftrigger = (localVal & ((uint32_t)0x00000020)) >> 5; + *secu1ac0txbuftrigger = (localVal & ((uint32_t)0x00000010)) >> 4; + *secu1ac3txtrigger = (localVal & ((uint32_t)0x00000008)) >> 3; + *secu1ac2txtrigger = (localVal & ((uint32_t)0x00000004)) >> 2; + *secu1ac1txtrigger = (localVal & ((uint32_t)0x00000002)) >> 1; + *secu1ac0txtrigger = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +/** + * @brief Returns the current value of the secU3ac3TxBufTrigger field in the SEC_USERS_TX_INT_EVENT_SET register. + * + * The SEC_USERS_TX_INT_EVENT_SET register will be read and the secU3ac3TxBufTrigger field's value will be returned. + * + * @return The current value of the secU3ac3TxBufTrigger field in the SEC_USERS_TX_INT_EVENT_SET register. + */ +__INLINE uint8_t nxmac_sec_u_3ac_3_tx_buf_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR); + return ((localVal & ((uint32_t)0x00800000)) >> 23); +} + +/** + * @brief Sets the secU3ac3TxBufTrigger field of the SEC_USERS_TX_INT_EVENT_SET register. + * + * The SEC_USERS_TX_INT_EVENT_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] secu3ac3txbuftrigger - The value to set the field to. + */ +__INLINE void nxmac_sec_u_3ac_3_tx_buf_trigger_setf(uint8_t secu3ac3txbuftrigger) +{ + ASSERT_ERR((((uint32_t)secu3ac3txbuftrigger << 23) & ~((uint32_t)0x00800000)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR, (uint32_t)secu3ac3txbuftrigger << 23); +} + +/** + * @brief Returns the current value of the secU3ac2TxBufTrigger field in the SEC_USERS_TX_INT_EVENT_SET register. + * + * The SEC_USERS_TX_INT_EVENT_SET register will be read and the secU3ac2TxBufTrigger field's value will be returned. + * + * @return The current value of the secU3ac2TxBufTrigger field in the SEC_USERS_TX_INT_EVENT_SET register. + */ +__INLINE uint8_t nxmac_sec_u_3ac_2_tx_buf_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR); + return ((localVal & ((uint32_t)0x00400000)) >> 22); +} + +/** + * @brief Sets the secU3ac2TxBufTrigger field of the SEC_USERS_TX_INT_EVENT_SET register. + * + * The SEC_USERS_TX_INT_EVENT_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] secu3ac2txbuftrigger - The value to set the field to. + */ +__INLINE void nxmac_sec_u_3ac_2_tx_buf_trigger_setf(uint8_t secu3ac2txbuftrigger) +{ + ASSERT_ERR((((uint32_t)secu3ac2txbuftrigger << 22) & ~((uint32_t)0x00400000)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR, (uint32_t)secu3ac2txbuftrigger << 22); +} + +/** + * @brief Returns the current value of the secU3ac1TxBufTrigger field in the SEC_USERS_TX_INT_EVENT_SET register. + * + * The SEC_USERS_TX_INT_EVENT_SET register will be read and the secU3ac1TxBufTrigger field's value will be returned. + * + * @return The current value of the secU3ac1TxBufTrigger field in the SEC_USERS_TX_INT_EVENT_SET register. + */ +__INLINE uint8_t nxmac_sec_u_3ac_1_tx_buf_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR); + return ((localVal & ((uint32_t)0x00200000)) >> 21); +} + +/** + * @brief Sets the secU3ac1TxBufTrigger field of the SEC_USERS_TX_INT_EVENT_SET register. + * + * The SEC_USERS_TX_INT_EVENT_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] secu3ac1txbuftrigger - The value to set the field to. + */ +__INLINE void nxmac_sec_u_3ac_1_tx_buf_trigger_setf(uint8_t secu3ac1txbuftrigger) +{ + ASSERT_ERR((((uint32_t)secu3ac1txbuftrigger << 21) & ~((uint32_t)0x00200000)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR, (uint32_t)secu3ac1txbuftrigger << 21); +} + +/** + * @brief Returns the current value of the secU3ac0TxBufTrigger field in the SEC_USERS_TX_INT_EVENT_SET register. + * + * The SEC_USERS_TX_INT_EVENT_SET register will be read and the secU3ac0TxBufTrigger field's value will be returned. + * + * @return The current value of the secU3ac0TxBufTrigger field in the SEC_USERS_TX_INT_EVENT_SET register. + */ +__INLINE uint8_t nxmac_sec_u_3ac_0_tx_buf_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR); + return ((localVal & ((uint32_t)0x00100000)) >> 20); +} + +/** + * @brief Sets the secU3ac0TxBufTrigger field of the SEC_USERS_TX_INT_EVENT_SET register. + * + * The SEC_USERS_TX_INT_EVENT_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] secu3ac0txbuftrigger - The value to set the field to. + */ +__INLINE void nxmac_sec_u_3ac_0_tx_buf_trigger_setf(uint8_t secu3ac0txbuftrigger) +{ + ASSERT_ERR((((uint32_t)secu3ac0txbuftrigger << 20) & ~((uint32_t)0x00100000)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR, (uint32_t)secu3ac0txbuftrigger << 20); +} + +/** + * @brief Returns the current value of the secU3ac3TxTrigger field in the SEC_USERS_TX_INT_EVENT_SET register. + * + * The SEC_USERS_TX_INT_EVENT_SET register will be read and the secU3ac3TxTrigger field's value will be returned. + * + * @return The current value of the secU3ac3TxTrigger field in the SEC_USERS_TX_INT_EVENT_SET register. + */ +__INLINE uint8_t nxmac_sec_u_3ac_3_tx_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR); + return ((localVal & ((uint32_t)0x00080000)) >> 19); +} + +/** + * @brief Sets the secU3ac3TxTrigger field of the SEC_USERS_TX_INT_EVENT_SET register. + * + * The SEC_USERS_TX_INT_EVENT_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] secu3ac3txtrigger - The value to set the field to. + */ +__INLINE void nxmac_sec_u_3ac_3_tx_trigger_setf(uint8_t secu3ac3txtrigger) +{ + ASSERT_ERR((((uint32_t)secu3ac3txtrigger << 19) & ~((uint32_t)0x00080000)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR, (uint32_t)secu3ac3txtrigger << 19); +} + +/** + * @brief Returns the current value of the secU3ac2TxTrigger field in the SEC_USERS_TX_INT_EVENT_SET register. + * + * The SEC_USERS_TX_INT_EVENT_SET register will be read and the secU3ac2TxTrigger field's value will be returned. + * + * @return The current value of the secU3ac2TxTrigger field in the SEC_USERS_TX_INT_EVENT_SET register. + */ +__INLINE uint8_t nxmac_sec_u_3ac_2_tx_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR); + return ((localVal & ((uint32_t)0x00040000)) >> 18); +} + +/** + * @brief Sets the secU3ac2TxTrigger field of the SEC_USERS_TX_INT_EVENT_SET register. + * + * The SEC_USERS_TX_INT_EVENT_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] secu3ac2txtrigger - The value to set the field to. + */ +__INLINE void nxmac_sec_u_3ac_2_tx_trigger_setf(uint8_t secu3ac2txtrigger) +{ + ASSERT_ERR((((uint32_t)secu3ac2txtrigger << 18) & ~((uint32_t)0x00040000)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR, (uint32_t)secu3ac2txtrigger << 18); +} + +/** + * @brief Returns the current value of the secU3ac1TxTrigger field in the SEC_USERS_TX_INT_EVENT_SET register. + * + * The SEC_USERS_TX_INT_EVENT_SET register will be read and the secU3ac1TxTrigger field's value will be returned. + * + * @return The current value of the secU3ac1TxTrigger field in the SEC_USERS_TX_INT_EVENT_SET register. + */ +__INLINE uint8_t nxmac_sec_u_3ac_1_tx_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR); + return ((localVal & ((uint32_t)0x00020000)) >> 17); +} + +/** + * @brief Sets the secU3ac1TxTrigger field of the SEC_USERS_TX_INT_EVENT_SET register. + * + * The SEC_USERS_TX_INT_EVENT_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] secu3ac1txtrigger - The value to set the field to. + */ +__INLINE void nxmac_sec_u_3ac_1_tx_trigger_setf(uint8_t secu3ac1txtrigger) +{ + ASSERT_ERR((((uint32_t)secu3ac1txtrigger << 17) & ~((uint32_t)0x00020000)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR, (uint32_t)secu3ac1txtrigger << 17); +} + +/** + * @brief Returns the current value of the secU3ac0TxTrigger field in the SEC_USERS_TX_INT_EVENT_SET register. + * + * The SEC_USERS_TX_INT_EVENT_SET register will be read and the secU3ac0TxTrigger field's value will be returned. + * + * @return The current value of the secU3ac0TxTrigger field in the SEC_USERS_TX_INT_EVENT_SET register. + */ +__INLINE uint8_t nxmac_sec_u_3ac_0_tx_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR); + return ((localVal & ((uint32_t)0x00010000)) >> 16); +} + +/** + * @brief Sets the secU3ac0TxTrigger field of the SEC_USERS_TX_INT_EVENT_SET register. + * + * The SEC_USERS_TX_INT_EVENT_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] secu3ac0txtrigger - The value to set the field to. + */ +__INLINE void nxmac_sec_u_3ac_0_tx_trigger_setf(uint8_t secu3ac0txtrigger) +{ + ASSERT_ERR((((uint32_t)secu3ac0txtrigger << 16) & ~((uint32_t)0x00010000)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR, (uint32_t)secu3ac0txtrigger << 16); +} + +/** + * @brief Returns the current value of the secU2ac3TxBufTrigger field in the SEC_USERS_TX_INT_EVENT_SET register. + * + * The SEC_USERS_TX_INT_EVENT_SET register will be read and the secU2ac3TxBufTrigger field's value will be returned. + * + * @return The current value of the secU2ac3TxBufTrigger field in the SEC_USERS_TX_INT_EVENT_SET register. + */ +__INLINE uint8_t nxmac_sec_u_2ac_3_tx_buf_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR); + return ((localVal & ((uint32_t)0x00008000)) >> 15); +} + +/** + * @brief Sets the secU2ac3TxBufTrigger field of the SEC_USERS_TX_INT_EVENT_SET register. + * + * The SEC_USERS_TX_INT_EVENT_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] secu2ac3txbuftrigger - The value to set the field to. + */ +__INLINE void nxmac_sec_u_2ac_3_tx_buf_trigger_setf(uint8_t secu2ac3txbuftrigger) +{ + ASSERT_ERR((((uint32_t)secu2ac3txbuftrigger << 15) & ~((uint32_t)0x00008000)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR, (uint32_t)secu2ac3txbuftrigger << 15); +} + +/** + * @brief Returns the current value of the secU2ac2TxBufTrigger field in the SEC_USERS_TX_INT_EVENT_SET register. + * + * The SEC_USERS_TX_INT_EVENT_SET register will be read and the secU2ac2TxBufTrigger field's value will be returned. + * + * @return The current value of the secU2ac2TxBufTrigger field in the SEC_USERS_TX_INT_EVENT_SET register. + */ +__INLINE uint8_t nxmac_sec_u_2ac_2_tx_buf_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR); + return ((localVal & ((uint32_t)0x00004000)) >> 14); +} + +/** + * @brief Sets the secU2ac2TxBufTrigger field of the SEC_USERS_TX_INT_EVENT_SET register. + * + * The SEC_USERS_TX_INT_EVENT_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] secu2ac2txbuftrigger - The value to set the field to. + */ +__INLINE void nxmac_sec_u_2ac_2_tx_buf_trigger_setf(uint8_t secu2ac2txbuftrigger) +{ + ASSERT_ERR((((uint32_t)secu2ac2txbuftrigger << 14) & ~((uint32_t)0x00004000)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR, (uint32_t)secu2ac2txbuftrigger << 14); +} + +/** + * @brief Returns the current value of the secU2ac1TxBufTrigger field in the SEC_USERS_TX_INT_EVENT_SET register. + * + * The SEC_USERS_TX_INT_EVENT_SET register will be read and the secU2ac1TxBufTrigger field's value will be returned. + * + * @return The current value of the secU2ac1TxBufTrigger field in the SEC_USERS_TX_INT_EVENT_SET register. + */ +__INLINE uint8_t nxmac_sec_u_2ac_1_tx_buf_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR); + return ((localVal & ((uint32_t)0x00002000)) >> 13); +} + +/** + * @brief Sets the secU2ac1TxBufTrigger field of the SEC_USERS_TX_INT_EVENT_SET register. + * + * The SEC_USERS_TX_INT_EVENT_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] secu2ac1txbuftrigger - The value to set the field to. + */ +__INLINE void nxmac_sec_u_2ac_1_tx_buf_trigger_setf(uint8_t secu2ac1txbuftrigger) +{ + ASSERT_ERR((((uint32_t)secu2ac1txbuftrigger << 13) & ~((uint32_t)0x00002000)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR, (uint32_t)secu2ac1txbuftrigger << 13); +} + +/** + * @brief Returns the current value of the secU2ac0TxBufTrigger field in the SEC_USERS_TX_INT_EVENT_SET register. + * + * The SEC_USERS_TX_INT_EVENT_SET register will be read and the secU2ac0TxBufTrigger field's value will be returned. + * + * @return The current value of the secU2ac0TxBufTrigger field in the SEC_USERS_TX_INT_EVENT_SET register. + */ +__INLINE uint8_t nxmac_sec_u_2ac_0_tx_buf_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR); + return ((localVal & ((uint32_t)0x00001000)) >> 12); +} + +/** + * @brief Sets the secU2ac0TxBufTrigger field of the SEC_USERS_TX_INT_EVENT_SET register. + * + * The SEC_USERS_TX_INT_EVENT_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] secu2ac0txbuftrigger - The value to set the field to. + */ +__INLINE void nxmac_sec_u_2ac_0_tx_buf_trigger_setf(uint8_t secu2ac0txbuftrigger) +{ + ASSERT_ERR((((uint32_t)secu2ac0txbuftrigger << 12) & ~((uint32_t)0x00001000)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR, (uint32_t)secu2ac0txbuftrigger << 12); +} + +/** + * @brief Returns the current value of the secU2ac3TxTrigger field in the SEC_USERS_TX_INT_EVENT_SET register. + * + * The SEC_USERS_TX_INT_EVENT_SET register will be read and the secU2ac3TxTrigger field's value will be returned. + * + * @return The current value of the secU2ac3TxTrigger field in the SEC_USERS_TX_INT_EVENT_SET register. + */ +__INLINE uint8_t nxmac_sec_u_2ac_3_tx_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR); + return ((localVal & ((uint32_t)0x00000800)) >> 11); +} + +/** + * @brief Sets the secU2ac3TxTrigger field of the SEC_USERS_TX_INT_EVENT_SET register. + * + * The SEC_USERS_TX_INT_EVENT_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] secu2ac3txtrigger - The value to set the field to. + */ +__INLINE void nxmac_sec_u_2ac_3_tx_trigger_setf(uint8_t secu2ac3txtrigger) +{ + ASSERT_ERR((((uint32_t)secu2ac3txtrigger << 11) & ~((uint32_t)0x00000800)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR, (uint32_t)secu2ac3txtrigger << 11); +} + +/** + * @brief Returns the current value of the secU2ac2TxTrigger field in the SEC_USERS_TX_INT_EVENT_SET register. + * + * The SEC_USERS_TX_INT_EVENT_SET register will be read and the secU2ac2TxTrigger field's value will be returned. + * + * @return The current value of the secU2ac2TxTrigger field in the SEC_USERS_TX_INT_EVENT_SET register. + */ +__INLINE uint8_t nxmac_sec_u_2ac_2_tx_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR); + return ((localVal & ((uint32_t)0x00000400)) >> 10); +} + +/** + * @brief Sets the secU2ac2TxTrigger field of the SEC_USERS_TX_INT_EVENT_SET register. + * + * The SEC_USERS_TX_INT_EVENT_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] secu2ac2txtrigger - The value to set the field to. + */ +__INLINE void nxmac_sec_u_2ac_2_tx_trigger_setf(uint8_t secu2ac2txtrigger) +{ + ASSERT_ERR((((uint32_t)secu2ac2txtrigger << 10) & ~((uint32_t)0x00000400)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR, (uint32_t)secu2ac2txtrigger << 10); +} + +/** + * @brief Returns the current value of the secU2ac1TxTrigger field in the SEC_USERS_TX_INT_EVENT_SET register. + * + * The SEC_USERS_TX_INT_EVENT_SET register will be read and the secU2ac1TxTrigger field's value will be returned. + * + * @return The current value of the secU2ac1TxTrigger field in the SEC_USERS_TX_INT_EVENT_SET register. + */ +__INLINE uint8_t nxmac_sec_u_2ac_1_tx_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR); + return ((localVal & ((uint32_t)0x00000200)) >> 9); +} + +/** + * @brief Sets the secU2ac1TxTrigger field of the SEC_USERS_TX_INT_EVENT_SET register. + * + * The SEC_USERS_TX_INT_EVENT_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] secu2ac1txtrigger - The value to set the field to. + */ +__INLINE void nxmac_sec_u_2ac_1_tx_trigger_setf(uint8_t secu2ac1txtrigger) +{ + ASSERT_ERR((((uint32_t)secu2ac1txtrigger << 9) & ~((uint32_t)0x00000200)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR, (uint32_t)secu2ac1txtrigger << 9); +} + +/** + * @brief Returns the current value of the secU2ac0TxTrigger field in the SEC_USERS_TX_INT_EVENT_SET register. + * + * The SEC_USERS_TX_INT_EVENT_SET register will be read and the secU2ac0TxTrigger field's value will be returned. + * + * @return The current value of the secU2ac0TxTrigger field in the SEC_USERS_TX_INT_EVENT_SET register. + */ +__INLINE uint8_t nxmac_sec_u_2ac_0_tx_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR); + return ((localVal & ((uint32_t)0x00000100)) >> 8); +} + +/** + * @brief Sets the secU2ac0TxTrigger field of the SEC_USERS_TX_INT_EVENT_SET register. + * + * The SEC_USERS_TX_INT_EVENT_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] secu2ac0txtrigger - The value to set the field to. + */ +__INLINE void nxmac_sec_u_2ac_0_tx_trigger_setf(uint8_t secu2ac0txtrigger) +{ + ASSERT_ERR((((uint32_t)secu2ac0txtrigger << 8) & ~((uint32_t)0x00000100)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR, (uint32_t)secu2ac0txtrigger << 8); +} + +/** + * @brief Returns the current value of the secU1ac3TxBufTrigger field in the SEC_USERS_TX_INT_EVENT_SET register. + * + * The SEC_USERS_TX_INT_EVENT_SET register will be read and the secU1ac3TxBufTrigger field's value will be returned. + * + * @return The current value of the secU1ac3TxBufTrigger field in the SEC_USERS_TX_INT_EVENT_SET register. + */ +__INLINE uint8_t nxmac_sec_u_1ac_3_tx_buf_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR); + return ((localVal & ((uint32_t)0x00000080)) >> 7); +} + +/** + * @brief Sets the secU1ac3TxBufTrigger field of the SEC_USERS_TX_INT_EVENT_SET register. + * + * The SEC_USERS_TX_INT_EVENT_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] secu1ac3txbuftrigger - The value to set the field to. + */ +__INLINE void nxmac_sec_u_1ac_3_tx_buf_trigger_setf(uint8_t secu1ac3txbuftrigger) +{ + ASSERT_ERR((((uint32_t)secu1ac3txbuftrigger << 7) & ~((uint32_t)0x00000080)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR, (uint32_t)secu1ac3txbuftrigger << 7); +} + +/** + * @brief Returns the current value of the secU1ac2TxBufTrigger field in the SEC_USERS_TX_INT_EVENT_SET register. + * + * The SEC_USERS_TX_INT_EVENT_SET register will be read and the secU1ac2TxBufTrigger field's value will be returned. + * + * @return The current value of the secU1ac2TxBufTrigger field in the SEC_USERS_TX_INT_EVENT_SET register. + */ +__INLINE uint8_t nxmac_sec_u_1ac_2_tx_buf_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR); + return ((localVal & ((uint32_t)0x00000040)) >> 6); +} + +/** + * @brief Sets the secU1ac2TxBufTrigger field of the SEC_USERS_TX_INT_EVENT_SET register. + * + * The SEC_USERS_TX_INT_EVENT_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] secu1ac2txbuftrigger - The value to set the field to. + */ +__INLINE void nxmac_sec_u_1ac_2_tx_buf_trigger_setf(uint8_t secu1ac2txbuftrigger) +{ + ASSERT_ERR((((uint32_t)secu1ac2txbuftrigger << 6) & ~((uint32_t)0x00000040)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR, (uint32_t)secu1ac2txbuftrigger << 6); +} + +/** + * @brief Returns the current value of the secU1ac1TxBufTrigger field in the SEC_USERS_TX_INT_EVENT_SET register. + * + * The SEC_USERS_TX_INT_EVENT_SET register will be read and the secU1ac1TxBufTrigger field's value will be returned. + * + * @return The current value of the secU1ac1TxBufTrigger field in the SEC_USERS_TX_INT_EVENT_SET register. + */ +__INLINE uint8_t nxmac_sec_u_1ac_1_tx_buf_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +/** + * @brief Sets the secU1ac1TxBufTrigger field of the SEC_USERS_TX_INT_EVENT_SET register. + * + * The SEC_USERS_TX_INT_EVENT_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] secu1ac1txbuftrigger - The value to set the field to. + */ +__INLINE void nxmac_sec_u_1ac_1_tx_buf_trigger_setf(uint8_t secu1ac1txbuftrigger) +{ + ASSERT_ERR((((uint32_t)secu1ac1txbuftrigger << 5) & ~((uint32_t)0x00000020)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR, (uint32_t)secu1ac1txbuftrigger << 5); +} + +/** + * @brief Returns the current value of the secU1ac0TxBufTrigger field in the SEC_USERS_TX_INT_EVENT_SET register. + * + * The SEC_USERS_TX_INT_EVENT_SET register will be read and the secU1ac0TxBufTrigger field's value will be returned. + * + * @return The current value of the secU1ac0TxBufTrigger field in the SEC_USERS_TX_INT_EVENT_SET register. + */ +__INLINE uint8_t nxmac_sec_u_1ac_0_tx_buf_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +/** + * @brief Sets the secU1ac0TxBufTrigger field of the SEC_USERS_TX_INT_EVENT_SET register. + * + * The SEC_USERS_TX_INT_EVENT_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] secu1ac0txbuftrigger - The value to set the field to. + */ +__INLINE void nxmac_sec_u_1ac_0_tx_buf_trigger_setf(uint8_t secu1ac0txbuftrigger) +{ + ASSERT_ERR((((uint32_t)secu1ac0txbuftrigger << 4) & ~((uint32_t)0x00000010)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR, (uint32_t)secu1ac0txbuftrigger << 4); +} + +/** + * @brief Returns the current value of the secU1ac3TxTrigger field in the SEC_USERS_TX_INT_EVENT_SET register. + * + * The SEC_USERS_TX_INT_EVENT_SET register will be read and the secU1ac3TxTrigger field's value will be returned. + * + * @return The current value of the secU1ac3TxTrigger field in the SEC_USERS_TX_INT_EVENT_SET register. + */ +__INLINE uint8_t nxmac_sec_u_1ac_3_tx_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +/** + * @brief Sets the secU1ac3TxTrigger field of the SEC_USERS_TX_INT_EVENT_SET register. + * + * The SEC_USERS_TX_INT_EVENT_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] secu1ac3txtrigger - The value to set the field to. + */ +__INLINE void nxmac_sec_u_1ac_3_tx_trigger_setf(uint8_t secu1ac3txtrigger) +{ + ASSERT_ERR((((uint32_t)secu1ac3txtrigger << 3) & ~((uint32_t)0x00000008)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR, (uint32_t)secu1ac3txtrigger << 3); +} + +/** + * @brief Returns the current value of the secU1ac2TxTrigger field in the SEC_USERS_TX_INT_EVENT_SET register. + * + * The SEC_USERS_TX_INT_EVENT_SET register will be read and the secU1ac2TxTrigger field's value will be returned. + * + * @return The current value of the secU1ac2TxTrigger field in the SEC_USERS_TX_INT_EVENT_SET register. + */ +__INLINE uint8_t nxmac_sec_u_1ac_2_tx_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +/** + * @brief Sets the secU1ac2TxTrigger field of the SEC_USERS_TX_INT_EVENT_SET register. + * + * The SEC_USERS_TX_INT_EVENT_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] secu1ac2txtrigger - The value to set the field to. + */ +__INLINE void nxmac_sec_u_1ac_2_tx_trigger_setf(uint8_t secu1ac2txtrigger) +{ + ASSERT_ERR((((uint32_t)secu1ac2txtrigger << 2) & ~((uint32_t)0x00000004)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR, (uint32_t)secu1ac2txtrigger << 2); +} + +/** + * @brief Returns the current value of the secU1ac1TxTrigger field in the SEC_USERS_TX_INT_EVENT_SET register. + * + * The SEC_USERS_TX_INT_EVENT_SET register will be read and the secU1ac1TxTrigger field's value will be returned. + * + * @return The current value of the secU1ac1TxTrigger field in the SEC_USERS_TX_INT_EVENT_SET register. + */ +__INLINE uint8_t nxmac_sec_u_1ac_1_tx_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +/** + * @brief Sets the secU1ac1TxTrigger field of the SEC_USERS_TX_INT_EVENT_SET register. + * + * The SEC_USERS_TX_INT_EVENT_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] secu1ac1txtrigger - The value to set the field to. + */ +__INLINE void nxmac_sec_u_1ac_1_tx_trigger_setf(uint8_t secu1ac1txtrigger) +{ + ASSERT_ERR((((uint32_t)secu1ac1txtrigger << 1) & ~((uint32_t)0x00000002)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR, (uint32_t)secu1ac1txtrigger << 1); +} + +/** + * @brief Returns the current value of the secU1ac0TxTrigger field in the SEC_USERS_TX_INT_EVENT_SET register. + * + * The SEC_USERS_TX_INT_EVENT_SET register will be read and the secU1ac0TxTrigger field's value will be returned. + * + * @return The current value of the secU1ac0TxTrigger field in the SEC_USERS_TX_INT_EVENT_SET register. + */ +__INLINE uint8_t nxmac_sec_u_1ac_0_tx_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/** + * @brief Sets the secU1ac0TxTrigger field of the SEC_USERS_TX_INT_EVENT_SET register. + * + * The SEC_USERS_TX_INT_EVENT_SET register will be read, modified to contain the new field value, and written. + * + * @param[in] secu1ac0txtrigger - The value to set the field to. + */ +__INLINE void nxmac_sec_u_1ac_0_tx_trigger_setf(uint8_t secu1ac0txtrigger) +{ + ASSERT_ERR((((uint32_t)secu1ac0txtrigger << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_SET_ADDR, (uint32_t)secu1ac0txtrigger << 0); +} + +#endif // RW_MUMIMO_TX_EN +/// @} + +#if RW_MUMIMO_TX_EN +/** + * @name SEC_USERS_TX_INT_EVENT_CLEAR register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     23   secU3ac3TxBufTrigger   0
+ *     22   secU3ac2TxBufTrigger   0
+ *     21   secU3ac1TxBufTrigger   0
+ *     20   secU3ac0TxBufTrigger   0
+ *     19    secU3ac3TxTrigger   0
+ *     18    secU3ac2TxTrigger   0
+ *     17    secU3ac1TxTrigger   0
+ *     16    secU3ac0TxTrigger   0
+ *     15   secU2ac3TxBufTrigger   0
+ *     14   secU2ac2TxBufTrigger   0
+ *     13   secU2ac1TxBufTrigger   0
+ *     12   secU2ac0TxBufTrigger   0
+ *     11    secU2ac3TxTrigger   0
+ *     10    secU2ac2TxTrigger   0
+ *     09    secU2ac1TxTrigger   0
+ *     08    secU2ac0TxTrigger   0
+ *     07   secU1ac3TxBufTrigger   0
+ *     06   secU1ac2TxBufTrigger   0
+ *     05   secU1ac1TxBufTrigger   0
+ *     04   secU1ac0TxBufTrigger   0
+ *     03    secU1ac3TxTrigger   0
+ *     02    secU1ac2TxTrigger   0
+ *     01    secU1ac1TxTrigger   0
+ *     00    secU1ac0TxTrigger   0
+ * 
+ * + * @{ + */ + +/// Address of the SEC_USERS_TX_INT_EVENT_CLEAR register +#define NXMAC_SEC_USERS_TX_INT_EVENT_CLEAR_ADDR 0xC0008368 +/// Offset of the SEC_USERS_TX_INT_EVENT_CLEAR register from the base address +#define NXMAC_SEC_USERS_TX_INT_EVENT_CLEAR_OFFSET 0x00000368 +/// Index of the SEC_USERS_TX_INT_EVENT_CLEAR register +#define NXMAC_SEC_USERS_TX_INT_EVENT_CLEAR_INDEX 0x000000DA +/// Reset value of the SEC_USERS_TX_INT_EVENT_CLEAR register +#define NXMAC_SEC_USERS_TX_INT_EVENT_CLEAR_RESET 0x00000000 + +/** + * @brief Sets the SEC_USERS_TX_INT_EVENT_CLEAR register to a value. + * The SEC_USERS_TX_INT_EVENT_CLEAR register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_sec_users_tx_int_event_clear(uint32_t value) +{ + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_CLEAR_ADDR, value); +} + +// fields defined in symmetrical set/clear register +/** + * @brief Constructs a value for the SEC_USERS_TX_INT_EVENT_CLEAR register given values for its fields + * and writes the value to the register. + * + * @param[in] secu3ac3txbuftrigger - The value to use for the secU3ac3TxBufTrigger field. + * @param[in] secu3ac2txbuftrigger - The value to use for the secU3ac2TxBufTrigger field. + * @param[in] secu3ac1txbuftrigger - The value to use for the secU3ac1TxBufTrigger field. + * @param[in] secu3ac0txbuftrigger - The value to use for the secU3ac0TxBufTrigger field. + * @param[in] secu3ac3txtrigger - The value to use for the secU3ac3TxTrigger field. + * @param[in] secu3ac2txtrigger - The value to use for the secU3ac2TxTrigger field. + * @param[in] secu3ac1txtrigger - The value to use for the secU3ac1TxTrigger field. + * @param[in] secu3ac0txtrigger - The value to use for the secU3ac0TxTrigger field. + * @param[in] secu2ac3txbuftrigger - The value to use for the secU2ac3TxBufTrigger field. + * @param[in] secu2ac2txbuftrigger - The value to use for the secU2ac2TxBufTrigger field. + * @param[in] secu2ac1txbuftrigger - The value to use for the secU2ac1TxBufTrigger field. + * @param[in] secu2ac0txbuftrigger - The value to use for the secU2ac0TxBufTrigger field. + * @param[in] secu2ac3txtrigger - The value to use for the secU2ac3TxTrigger field. + * @param[in] secu2ac2txtrigger - The value to use for the secU2ac2TxTrigger field. + * @param[in] secu2ac1txtrigger - The value to use for the secU2ac1TxTrigger field. + * @param[in] secu2ac0txtrigger - The value to use for the secU2ac0TxTrigger field. + * @param[in] secu1ac3txbuftrigger - The value to use for the secU1ac3TxBufTrigger field. + * @param[in] secu1ac2txbuftrigger - The value to use for the secU1ac2TxBufTrigger field. + * @param[in] secu1ac1txbuftrigger - The value to use for the secU1ac1TxBufTrigger field. + * @param[in] secu1ac0txbuftrigger - The value to use for the secU1ac0TxBufTrigger field. + * @param[in] secu1ac3txtrigger - The value to use for the secU1ac3TxTrigger field. + * @param[in] secu1ac2txtrigger - The value to use for the secU1ac2TxTrigger field. + * @param[in] secu1ac1txtrigger - The value to use for the secU1ac1TxTrigger field. + * @param[in] secu1ac0txtrigger - The value to use for the secU1ac0TxTrigger field. + */ +__INLINE void nxmac_sec_users_tx_int_event_clear_pack(uint8_t secu3ac3txbuftrigger, uint8_t secu3ac2txbuftrigger, uint8_t secu3ac1txbuftrigger, uint8_t secu3ac0txbuftrigger, uint8_t secu3ac3txtrigger, uint8_t secu3ac2txtrigger, uint8_t secu3ac1txtrigger, uint8_t secu3ac0txtrigger, uint8_t secu2ac3txbuftrigger, uint8_t secu2ac2txbuftrigger, uint8_t secu2ac1txbuftrigger, uint8_t secu2ac0txbuftrigger, uint8_t secu2ac3txtrigger, uint8_t secu2ac2txtrigger, uint8_t secu2ac1txtrigger, uint8_t secu2ac0txtrigger, uint8_t secu1ac3txbuftrigger, uint8_t secu1ac2txbuftrigger, uint8_t secu1ac1txbuftrigger, uint8_t secu1ac0txbuftrigger, uint8_t secu1ac3txtrigger, uint8_t secu1ac2txtrigger, uint8_t secu1ac1txtrigger, uint8_t secu1ac0txtrigger) +{ + ASSERT_ERR((((uint32_t)secu3ac3txbuftrigger << 23) & ~((uint32_t)0x00800000)) == 0); + ASSERT_ERR((((uint32_t)secu3ac2txbuftrigger << 22) & ~((uint32_t)0x00400000)) == 0); + ASSERT_ERR((((uint32_t)secu3ac1txbuftrigger << 21) & ~((uint32_t)0x00200000)) == 0); + ASSERT_ERR((((uint32_t)secu3ac0txbuftrigger << 20) & ~((uint32_t)0x00100000)) == 0); + ASSERT_ERR((((uint32_t)secu3ac3txtrigger << 19) & ~((uint32_t)0x00080000)) == 0); + ASSERT_ERR((((uint32_t)secu3ac2txtrigger << 18) & ~((uint32_t)0x00040000)) == 0); + ASSERT_ERR((((uint32_t)secu3ac1txtrigger << 17) & ~((uint32_t)0x00020000)) == 0); + ASSERT_ERR((((uint32_t)secu3ac0txtrigger << 16) & ~((uint32_t)0x00010000)) == 0); + ASSERT_ERR((((uint32_t)secu2ac3txbuftrigger << 15) & ~((uint32_t)0x00008000)) == 0); + ASSERT_ERR((((uint32_t)secu2ac2txbuftrigger << 14) & ~((uint32_t)0x00004000)) == 0); + ASSERT_ERR((((uint32_t)secu2ac1txbuftrigger << 13) & ~((uint32_t)0x00002000)) == 0); + ASSERT_ERR((((uint32_t)secu2ac0txbuftrigger << 12) & ~((uint32_t)0x00001000)) == 0); + ASSERT_ERR((((uint32_t)secu2ac3txtrigger << 11) & ~((uint32_t)0x00000800)) == 0); + ASSERT_ERR((((uint32_t)secu2ac2txtrigger << 10) & ~((uint32_t)0x00000400)) == 0); + ASSERT_ERR((((uint32_t)secu2ac1txtrigger << 9) & ~((uint32_t)0x00000200)) == 0); + ASSERT_ERR((((uint32_t)secu2ac0txtrigger << 8) & ~((uint32_t)0x00000100)) == 0); + ASSERT_ERR((((uint32_t)secu1ac3txbuftrigger << 7) & ~((uint32_t)0x00000080)) == 0); + ASSERT_ERR((((uint32_t)secu1ac2txbuftrigger << 6) & ~((uint32_t)0x00000040)) == 0); + ASSERT_ERR((((uint32_t)secu1ac1txbuftrigger << 5) & ~((uint32_t)0x00000020)) == 0); + ASSERT_ERR((((uint32_t)secu1ac0txbuftrigger << 4) & ~((uint32_t)0x00000010)) == 0); + ASSERT_ERR((((uint32_t)secu1ac3txtrigger << 3) & ~((uint32_t)0x00000008)) == 0); + ASSERT_ERR((((uint32_t)secu1ac2txtrigger << 2) & ~((uint32_t)0x00000004)) == 0); + ASSERT_ERR((((uint32_t)secu1ac1txtrigger << 1) & ~((uint32_t)0x00000002)) == 0); + ASSERT_ERR((((uint32_t)secu1ac0txtrigger << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_CLEAR_ADDR, ((uint32_t)secu3ac3txbuftrigger << 23) | ((uint32_t)secu3ac2txbuftrigger << 22) | ((uint32_t)secu3ac1txbuftrigger << 21) | ((uint32_t)secu3ac0txbuftrigger << 20) | ((uint32_t)secu3ac3txtrigger << 19) | ((uint32_t)secu3ac2txtrigger << 18) | ((uint32_t)secu3ac1txtrigger << 17) | ((uint32_t)secu3ac0txtrigger << 16) | ((uint32_t)secu2ac3txbuftrigger << 15) | ((uint32_t)secu2ac2txbuftrigger << 14) | ((uint32_t)secu2ac1txbuftrigger << 13) | ((uint32_t)secu2ac0txbuftrigger << 12) | ((uint32_t)secu2ac3txtrigger << 11) | ((uint32_t)secu2ac2txtrigger << 10) | ((uint32_t)secu2ac1txtrigger << 9) | ((uint32_t)secu2ac0txtrigger << 8) | ((uint32_t)secu1ac3txbuftrigger << 7) | ((uint32_t)secu1ac2txbuftrigger << 6) | ((uint32_t)secu1ac1txbuftrigger << 5) | ((uint32_t)secu1ac0txbuftrigger << 4) | ((uint32_t)secu1ac3txtrigger << 3) | ((uint32_t)secu1ac2txtrigger << 2) | ((uint32_t)secu1ac1txtrigger << 1) | ((uint32_t)secu1ac0txtrigger << 0)); +} + +/** + * @brief Sets the secU3ac3TxBufTrigger field of the SEC_USERS_TX_INT_EVENT_CLEAR register. + * + * The SEC_USERS_TX_INT_EVENT_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] secu3ac3txbuftrigger - The value to set the field to. + */ +__INLINE void nxmac_sec_u_3ac_3_tx_buf_trigger_clearf(uint8_t secu3ac3txbuftrigger) +{ + ASSERT_ERR((((uint32_t)secu3ac3txbuftrigger << 23) & ~((uint32_t)0x00800000)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_CLEAR_ADDR, (uint32_t)secu3ac3txbuftrigger << 23); +} + +/** + * @brief Sets the secU3ac2TxBufTrigger field of the SEC_USERS_TX_INT_EVENT_CLEAR register. + * + * The SEC_USERS_TX_INT_EVENT_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] secu3ac2txbuftrigger - The value to set the field to. + */ +__INLINE void nxmac_sec_u_3ac_2_tx_buf_trigger_clearf(uint8_t secu3ac2txbuftrigger) +{ + ASSERT_ERR((((uint32_t)secu3ac2txbuftrigger << 22) & ~((uint32_t)0x00400000)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_CLEAR_ADDR, (uint32_t)secu3ac2txbuftrigger << 22); +} + +/** + * @brief Sets the secU3ac1TxBufTrigger field of the SEC_USERS_TX_INT_EVENT_CLEAR register. + * + * The SEC_USERS_TX_INT_EVENT_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] secu3ac1txbuftrigger - The value to set the field to. + */ +__INLINE void nxmac_sec_u_3ac_1_tx_buf_trigger_clearf(uint8_t secu3ac1txbuftrigger) +{ + ASSERT_ERR((((uint32_t)secu3ac1txbuftrigger << 21) & ~((uint32_t)0x00200000)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_CLEAR_ADDR, (uint32_t)secu3ac1txbuftrigger << 21); +} + +/** + * @brief Sets the secU3ac0TxBufTrigger field of the SEC_USERS_TX_INT_EVENT_CLEAR register. + * + * The SEC_USERS_TX_INT_EVENT_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] secu3ac0txbuftrigger - The value to set the field to. + */ +__INLINE void nxmac_sec_u_3ac_0_tx_buf_trigger_clearf(uint8_t secu3ac0txbuftrigger) +{ + ASSERT_ERR((((uint32_t)secu3ac0txbuftrigger << 20) & ~((uint32_t)0x00100000)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_CLEAR_ADDR, (uint32_t)secu3ac0txbuftrigger << 20); +} + +/** + * @brief Sets the secU3ac3TxTrigger field of the SEC_USERS_TX_INT_EVENT_CLEAR register. + * + * The SEC_USERS_TX_INT_EVENT_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] secu3ac3txtrigger - The value to set the field to. + */ +__INLINE void nxmac_sec_u_3ac_3_tx_trigger_clearf(uint8_t secu3ac3txtrigger) +{ + ASSERT_ERR((((uint32_t)secu3ac3txtrigger << 19) & ~((uint32_t)0x00080000)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_CLEAR_ADDR, (uint32_t)secu3ac3txtrigger << 19); +} + +/** + * @brief Sets the secU3ac2TxTrigger field of the SEC_USERS_TX_INT_EVENT_CLEAR register. + * + * The SEC_USERS_TX_INT_EVENT_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] secu3ac2txtrigger - The value to set the field to. + */ +__INLINE void nxmac_sec_u_3ac_2_tx_trigger_clearf(uint8_t secu3ac2txtrigger) +{ + ASSERT_ERR((((uint32_t)secu3ac2txtrigger << 18) & ~((uint32_t)0x00040000)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_CLEAR_ADDR, (uint32_t)secu3ac2txtrigger << 18); +} + +/** + * @brief Sets the secU3ac1TxTrigger field of the SEC_USERS_TX_INT_EVENT_CLEAR register. + * + * The SEC_USERS_TX_INT_EVENT_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] secu3ac1txtrigger - The value to set the field to. + */ +__INLINE void nxmac_sec_u_3ac_1_tx_trigger_clearf(uint8_t secu3ac1txtrigger) +{ + ASSERT_ERR((((uint32_t)secu3ac1txtrigger << 17) & ~((uint32_t)0x00020000)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_CLEAR_ADDR, (uint32_t)secu3ac1txtrigger << 17); +} + +/** + * @brief Sets the secU3ac0TxTrigger field of the SEC_USERS_TX_INT_EVENT_CLEAR register. + * + * The SEC_USERS_TX_INT_EVENT_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] secu3ac0txtrigger - The value to set the field to. + */ +__INLINE void nxmac_sec_u_3ac_0_tx_trigger_clearf(uint8_t secu3ac0txtrigger) +{ + ASSERT_ERR((((uint32_t)secu3ac0txtrigger << 16) & ~((uint32_t)0x00010000)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_CLEAR_ADDR, (uint32_t)secu3ac0txtrigger << 16); +} + +/** + * @brief Sets the secU2ac3TxBufTrigger field of the SEC_USERS_TX_INT_EVENT_CLEAR register. + * + * The SEC_USERS_TX_INT_EVENT_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] secu2ac3txbuftrigger - The value to set the field to. + */ +__INLINE void nxmac_sec_u_2ac_3_tx_buf_trigger_clearf(uint8_t secu2ac3txbuftrigger) +{ + ASSERT_ERR((((uint32_t)secu2ac3txbuftrigger << 15) & ~((uint32_t)0x00008000)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_CLEAR_ADDR, (uint32_t)secu2ac3txbuftrigger << 15); +} + +/** + * @brief Sets the secU2ac2TxBufTrigger field of the SEC_USERS_TX_INT_EVENT_CLEAR register. + * + * The SEC_USERS_TX_INT_EVENT_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] secu2ac2txbuftrigger - The value to set the field to. + */ +__INLINE void nxmac_sec_u_2ac_2_tx_buf_trigger_clearf(uint8_t secu2ac2txbuftrigger) +{ + ASSERT_ERR((((uint32_t)secu2ac2txbuftrigger << 14) & ~((uint32_t)0x00004000)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_CLEAR_ADDR, (uint32_t)secu2ac2txbuftrigger << 14); +} + +/** + * @brief Sets the secU2ac1TxBufTrigger field of the SEC_USERS_TX_INT_EVENT_CLEAR register. + * + * The SEC_USERS_TX_INT_EVENT_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] secu2ac1txbuftrigger - The value to set the field to. + */ +__INLINE void nxmac_sec_u_2ac_1_tx_buf_trigger_clearf(uint8_t secu2ac1txbuftrigger) +{ + ASSERT_ERR((((uint32_t)secu2ac1txbuftrigger << 13) & ~((uint32_t)0x00002000)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_CLEAR_ADDR, (uint32_t)secu2ac1txbuftrigger << 13); +} + +/** + * @brief Sets the secU2ac0TxBufTrigger field of the SEC_USERS_TX_INT_EVENT_CLEAR register. + * + * The SEC_USERS_TX_INT_EVENT_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] secu2ac0txbuftrigger - The value to set the field to. + */ +__INLINE void nxmac_sec_u_2ac_0_tx_buf_trigger_clearf(uint8_t secu2ac0txbuftrigger) +{ + ASSERT_ERR((((uint32_t)secu2ac0txbuftrigger << 12) & ~((uint32_t)0x00001000)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_CLEAR_ADDR, (uint32_t)secu2ac0txbuftrigger << 12); +} + +/** + * @brief Sets the secU2ac3TxTrigger field of the SEC_USERS_TX_INT_EVENT_CLEAR register. + * + * The SEC_USERS_TX_INT_EVENT_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] secu2ac3txtrigger - The value to set the field to. + */ +__INLINE void nxmac_sec_u_2ac_3_tx_trigger_clearf(uint8_t secu2ac3txtrigger) +{ + ASSERT_ERR((((uint32_t)secu2ac3txtrigger << 11) & ~((uint32_t)0x00000800)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_CLEAR_ADDR, (uint32_t)secu2ac3txtrigger << 11); +} + +/** + * @brief Sets the secU2ac2TxTrigger field of the SEC_USERS_TX_INT_EVENT_CLEAR register. + * + * The SEC_USERS_TX_INT_EVENT_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] secu2ac2txtrigger - The value to set the field to. + */ +__INLINE void nxmac_sec_u_2ac_2_tx_trigger_clearf(uint8_t secu2ac2txtrigger) +{ + ASSERT_ERR((((uint32_t)secu2ac2txtrigger << 10) & ~((uint32_t)0x00000400)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_CLEAR_ADDR, (uint32_t)secu2ac2txtrigger << 10); +} + +/** + * @brief Sets the secU2ac1TxTrigger field of the SEC_USERS_TX_INT_EVENT_CLEAR register. + * + * The SEC_USERS_TX_INT_EVENT_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] secu2ac1txtrigger - The value to set the field to. + */ +__INLINE void nxmac_sec_u_2ac_1_tx_trigger_clearf(uint8_t secu2ac1txtrigger) +{ + ASSERT_ERR((((uint32_t)secu2ac1txtrigger << 9) & ~((uint32_t)0x00000200)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_CLEAR_ADDR, (uint32_t)secu2ac1txtrigger << 9); +} + +/** + * @brief Sets the secU2ac0TxTrigger field of the SEC_USERS_TX_INT_EVENT_CLEAR register. + * + * The SEC_USERS_TX_INT_EVENT_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] secu2ac0txtrigger - The value to set the field to. + */ +__INLINE void nxmac_sec_u_2ac_0_tx_trigger_clearf(uint8_t secu2ac0txtrigger) +{ + ASSERT_ERR((((uint32_t)secu2ac0txtrigger << 8) & ~((uint32_t)0x00000100)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_CLEAR_ADDR, (uint32_t)secu2ac0txtrigger << 8); +} + +/** + * @brief Sets the secU1ac3TxBufTrigger field of the SEC_USERS_TX_INT_EVENT_CLEAR register. + * + * The SEC_USERS_TX_INT_EVENT_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] secu1ac3txbuftrigger - The value to set the field to. + */ +__INLINE void nxmac_sec_u_1ac_3_tx_buf_trigger_clearf(uint8_t secu1ac3txbuftrigger) +{ + ASSERT_ERR((((uint32_t)secu1ac3txbuftrigger << 7) & ~((uint32_t)0x00000080)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_CLEAR_ADDR, (uint32_t)secu1ac3txbuftrigger << 7); +} + +/** + * @brief Sets the secU1ac2TxBufTrigger field of the SEC_USERS_TX_INT_EVENT_CLEAR register. + * + * The SEC_USERS_TX_INT_EVENT_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] secu1ac2txbuftrigger - The value to set the field to. + */ +__INLINE void nxmac_sec_u_1ac_2_tx_buf_trigger_clearf(uint8_t secu1ac2txbuftrigger) +{ + ASSERT_ERR((((uint32_t)secu1ac2txbuftrigger << 6) & ~((uint32_t)0x00000040)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_CLEAR_ADDR, (uint32_t)secu1ac2txbuftrigger << 6); +} + +/** + * @brief Sets the secU1ac1TxBufTrigger field of the SEC_USERS_TX_INT_EVENT_CLEAR register. + * + * The SEC_USERS_TX_INT_EVENT_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] secu1ac1txbuftrigger - The value to set the field to. + */ +__INLINE void nxmac_sec_u_1ac_1_tx_buf_trigger_clearf(uint8_t secu1ac1txbuftrigger) +{ + ASSERT_ERR((((uint32_t)secu1ac1txbuftrigger << 5) & ~((uint32_t)0x00000020)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_CLEAR_ADDR, (uint32_t)secu1ac1txbuftrigger << 5); +} + +/** + * @brief Sets the secU1ac0TxBufTrigger field of the SEC_USERS_TX_INT_EVENT_CLEAR register. + * + * The SEC_USERS_TX_INT_EVENT_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] secu1ac0txbuftrigger - The value to set the field to. + */ +__INLINE void nxmac_sec_u_1ac_0_tx_buf_trigger_clearf(uint8_t secu1ac0txbuftrigger) +{ + ASSERT_ERR((((uint32_t)secu1ac0txbuftrigger << 4) & ~((uint32_t)0x00000010)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_CLEAR_ADDR, (uint32_t)secu1ac0txbuftrigger << 4); +} + +/** + * @brief Sets the secU1ac3TxTrigger field of the SEC_USERS_TX_INT_EVENT_CLEAR register. + * + * The SEC_USERS_TX_INT_EVENT_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] secu1ac3txtrigger - The value to set the field to. + */ +__INLINE void nxmac_sec_u_1ac_3_tx_trigger_clearf(uint8_t secu1ac3txtrigger) +{ + ASSERT_ERR((((uint32_t)secu1ac3txtrigger << 3) & ~((uint32_t)0x00000008)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_CLEAR_ADDR, (uint32_t)secu1ac3txtrigger << 3); +} + +/** + * @brief Sets the secU1ac2TxTrigger field of the SEC_USERS_TX_INT_EVENT_CLEAR register. + * + * The SEC_USERS_TX_INT_EVENT_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] secu1ac2txtrigger - The value to set the field to. + */ +__INLINE void nxmac_sec_u_1ac_2_tx_trigger_clearf(uint8_t secu1ac2txtrigger) +{ + ASSERT_ERR((((uint32_t)secu1ac2txtrigger << 2) & ~((uint32_t)0x00000004)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_CLEAR_ADDR, (uint32_t)secu1ac2txtrigger << 2); +} + +/** + * @brief Sets the secU1ac1TxTrigger field of the SEC_USERS_TX_INT_EVENT_CLEAR register. + * + * The SEC_USERS_TX_INT_EVENT_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] secu1ac1txtrigger - The value to set the field to. + */ +__INLINE void nxmac_sec_u_1ac_1_tx_trigger_clearf(uint8_t secu1ac1txtrigger) +{ + ASSERT_ERR((((uint32_t)secu1ac1txtrigger << 1) & ~((uint32_t)0x00000002)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_CLEAR_ADDR, (uint32_t)secu1ac1txtrigger << 1); +} + +/** + * @brief Sets the secU1ac0TxTrigger field of the SEC_USERS_TX_INT_EVENT_CLEAR register. + * + * The SEC_USERS_TX_INT_EVENT_CLEAR register will be read, modified to contain the new field value, and written. + * + * @param[in] secu1ac0txtrigger - The value to set the field to. + */ +__INLINE void nxmac_sec_u_1ac_0_tx_trigger_clearf(uint8_t secu1ac0txtrigger) +{ + ASSERT_ERR((((uint32_t)secu1ac0txtrigger << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_CLEAR_ADDR, (uint32_t)secu1ac0txtrigger << 0); +} + +#endif // RW_MUMIMO_TX_EN +/// @} + +#if RW_MUMIMO_TX_EN +/** + * @name SEC_USERS_TX_INT_EVENT_UN_MASK register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31   masterSecUsersTxIntEn   0
+ *     23   masksecU3ac3TxBufTrigger   0
+ *     22   masksecU3ac2TxBufTrigger   0
+ *     21   masksecU3ac1TxBufTrigger   0
+ *     20   masksecU3ac0TxBufTrigger   0
+ *     19   masksecU3ac3TxTrigger   0
+ *     18   masksecU3ac2TxTrigger   0
+ *     17   masksecU3ac1TxTrigger   0
+ *     16   masksecU3ac0TxTrigger   0
+ *     15   masksecU2ac3TxBufTrigger   0
+ *     14   masksecU2ac2TxBufTrigger   0
+ *     13   masksecU2ac1TxBufTrigger   0
+ *     12   masksecU2ac0TxBufTrigger   0
+ *     11   masksecU2ac3TxTrigger   0
+ *     10   masksecU2ac2TxTrigger   0
+ *     09   masksecU2ac1TxTrigger   0
+ *     08   masksecU2ac0TxTrigger   0
+ *     07   masksecU1ac3TxBufTrigger   0
+ *     06   masksecU1ac2TxBufTrigger   0
+ *     05   masksecU1ac1TxBufTrigger   0
+ *     04   masksecU1ac0TxBufTrigger   0
+ *     03   masksecU1ac3TxTrigger   0
+ *     02   masksecU1ac2TxTrigger   0
+ *     01   masksecU1ac1TxTrigger   0
+ *     00   masksecU1ac0TxTrigger   0
+ * 
+ * + * @{ + */ + +/// Address of the SEC_USERS_TX_INT_EVENT_UN_MASK register +#define NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR 0xC000836C +/// Offset of the SEC_USERS_TX_INT_EVENT_UN_MASK register from the base address +#define NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_OFFSET 0x0000036C +/// Index of the SEC_USERS_TX_INT_EVENT_UN_MASK register +#define NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_INDEX 0x000000DB +/// Reset value of the SEC_USERS_TX_INT_EVENT_UN_MASK register +#define NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_RESET 0x00000000 + +/** + * @brief Returns the current value of the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be read and its value returned. + * @return The current value of the SEC_USERS_TX_INT_EVENT_UN_MASK register. + */ +__INLINE uint32_t nxmac_sec_users_tx_int_event_un_mask_get(void) +{ + return REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR); +} + +/** + * @brief Sets the SEC_USERS_TX_INT_EVENT_UN_MASK register to a value. + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_sec_users_tx_int_event_un_mask_set(uint32_t value) +{ + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR, value); +} + +// field definitions +/// MASTER_SEC_USERS_TX_INT_EN field bit +#define NXMAC_MASTER_SEC_USERS_TX_INT_EN_BIT ((uint32_t)0x80000000) +/// MASTER_SEC_USERS_TX_INT_EN field position +#define NXMAC_MASTER_SEC_USERS_TX_INT_EN_POS 31 +/// MASKSEC_U_3AC_3_TX_BUF_TRIGGER field bit +#define NXMAC_MASKSEC_U_3AC_3_TX_BUF_TRIGGER_BIT ((uint32_t)0x00800000) +/// MASKSEC_U_3AC_3_TX_BUF_TRIGGER field position +#define NXMAC_MASKSEC_U_3AC_3_TX_BUF_TRIGGER_POS 23 +/// MASKSEC_U_3AC_2_TX_BUF_TRIGGER field bit +#define NXMAC_MASKSEC_U_3AC_2_TX_BUF_TRIGGER_BIT ((uint32_t)0x00400000) +/// MASKSEC_U_3AC_2_TX_BUF_TRIGGER field position +#define NXMAC_MASKSEC_U_3AC_2_TX_BUF_TRIGGER_POS 22 +/// MASKSEC_U_3AC_1_TX_BUF_TRIGGER field bit +#define NXMAC_MASKSEC_U_3AC_1_TX_BUF_TRIGGER_BIT ((uint32_t)0x00200000) +/// MASKSEC_U_3AC_1_TX_BUF_TRIGGER field position +#define NXMAC_MASKSEC_U_3AC_1_TX_BUF_TRIGGER_POS 21 +/// MASKSEC_U_3AC_0_TX_BUF_TRIGGER field bit +#define NXMAC_MASKSEC_U_3AC_0_TX_BUF_TRIGGER_BIT ((uint32_t)0x00100000) +/// MASKSEC_U_3AC_0_TX_BUF_TRIGGER field position +#define NXMAC_MASKSEC_U_3AC_0_TX_BUF_TRIGGER_POS 20 +/// MASKSEC_U_3AC_3_TX_TRIGGER field bit +#define NXMAC_MASKSEC_U_3AC_3_TX_TRIGGER_BIT ((uint32_t)0x00080000) +/// MASKSEC_U_3AC_3_TX_TRIGGER field position +#define NXMAC_MASKSEC_U_3AC_3_TX_TRIGGER_POS 19 +/// MASKSEC_U_3AC_2_TX_TRIGGER field bit +#define NXMAC_MASKSEC_U_3AC_2_TX_TRIGGER_BIT ((uint32_t)0x00040000) +/// MASKSEC_U_3AC_2_TX_TRIGGER field position +#define NXMAC_MASKSEC_U_3AC_2_TX_TRIGGER_POS 18 +/// MASKSEC_U_3AC_1_TX_TRIGGER field bit +#define NXMAC_MASKSEC_U_3AC_1_TX_TRIGGER_BIT ((uint32_t)0x00020000) +/// MASKSEC_U_3AC_1_TX_TRIGGER field position +#define NXMAC_MASKSEC_U_3AC_1_TX_TRIGGER_POS 17 +/// MASKSEC_U_3AC_0_TX_TRIGGER field bit +#define NXMAC_MASKSEC_U_3AC_0_TX_TRIGGER_BIT ((uint32_t)0x00010000) +/// MASKSEC_U_3AC_0_TX_TRIGGER field position +#define NXMAC_MASKSEC_U_3AC_0_TX_TRIGGER_POS 16 +/// MASKSEC_U_2AC_3_TX_BUF_TRIGGER field bit +#define NXMAC_MASKSEC_U_2AC_3_TX_BUF_TRIGGER_BIT ((uint32_t)0x00008000) +/// MASKSEC_U_2AC_3_TX_BUF_TRIGGER field position +#define NXMAC_MASKSEC_U_2AC_3_TX_BUF_TRIGGER_POS 15 +/// MASKSEC_U_2AC_2_TX_BUF_TRIGGER field bit +#define NXMAC_MASKSEC_U_2AC_2_TX_BUF_TRIGGER_BIT ((uint32_t)0x00004000) +/// MASKSEC_U_2AC_2_TX_BUF_TRIGGER field position +#define NXMAC_MASKSEC_U_2AC_2_TX_BUF_TRIGGER_POS 14 +/// MASKSEC_U_2AC_1_TX_BUF_TRIGGER field bit +#define NXMAC_MASKSEC_U_2AC_1_TX_BUF_TRIGGER_BIT ((uint32_t)0x00002000) +/// MASKSEC_U_2AC_1_TX_BUF_TRIGGER field position +#define NXMAC_MASKSEC_U_2AC_1_TX_BUF_TRIGGER_POS 13 +/// MASKSEC_U_2AC_0_TX_BUF_TRIGGER field bit +#define NXMAC_MASKSEC_U_2AC_0_TX_BUF_TRIGGER_BIT ((uint32_t)0x00001000) +/// MASKSEC_U_2AC_0_TX_BUF_TRIGGER field position +#define NXMAC_MASKSEC_U_2AC_0_TX_BUF_TRIGGER_POS 12 +/// MASKSEC_U_2AC_3_TX_TRIGGER field bit +#define NXMAC_MASKSEC_U_2AC_3_TX_TRIGGER_BIT ((uint32_t)0x00000800) +/// MASKSEC_U_2AC_3_TX_TRIGGER field position +#define NXMAC_MASKSEC_U_2AC_3_TX_TRIGGER_POS 11 +/// MASKSEC_U_2AC_2_TX_TRIGGER field bit +#define NXMAC_MASKSEC_U_2AC_2_TX_TRIGGER_BIT ((uint32_t)0x00000400) +/// MASKSEC_U_2AC_2_TX_TRIGGER field position +#define NXMAC_MASKSEC_U_2AC_2_TX_TRIGGER_POS 10 +/// MASKSEC_U_2AC_1_TX_TRIGGER field bit +#define NXMAC_MASKSEC_U_2AC_1_TX_TRIGGER_BIT ((uint32_t)0x00000200) +/// MASKSEC_U_2AC_1_TX_TRIGGER field position +#define NXMAC_MASKSEC_U_2AC_1_TX_TRIGGER_POS 9 +/// MASKSEC_U_2AC_0_TX_TRIGGER field bit +#define NXMAC_MASKSEC_U_2AC_0_TX_TRIGGER_BIT ((uint32_t)0x00000100) +/// MASKSEC_U_2AC_0_TX_TRIGGER field position +#define NXMAC_MASKSEC_U_2AC_0_TX_TRIGGER_POS 8 +/// MASKSEC_U_1AC_3_TX_BUF_TRIGGER field bit +#define NXMAC_MASKSEC_U_1AC_3_TX_BUF_TRIGGER_BIT ((uint32_t)0x00000080) +/// MASKSEC_U_1AC_3_TX_BUF_TRIGGER field position +#define NXMAC_MASKSEC_U_1AC_3_TX_BUF_TRIGGER_POS 7 +/// MASKSEC_U_1AC_2_TX_BUF_TRIGGER field bit +#define NXMAC_MASKSEC_U_1AC_2_TX_BUF_TRIGGER_BIT ((uint32_t)0x00000040) +/// MASKSEC_U_1AC_2_TX_BUF_TRIGGER field position +#define NXMAC_MASKSEC_U_1AC_2_TX_BUF_TRIGGER_POS 6 +/// MASKSEC_U_1AC_1_TX_BUF_TRIGGER field bit +#define NXMAC_MASKSEC_U_1AC_1_TX_BUF_TRIGGER_BIT ((uint32_t)0x00000020) +/// MASKSEC_U_1AC_1_TX_BUF_TRIGGER field position +#define NXMAC_MASKSEC_U_1AC_1_TX_BUF_TRIGGER_POS 5 +/// MASKSEC_U_1AC_0_TX_BUF_TRIGGER field bit +#define NXMAC_MASKSEC_U_1AC_0_TX_BUF_TRIGGER_BIT ((uint32_t)0x00000010) +/// MASKSEC_U_1AC_0_TX_BUF_TRIGGER field position +#define NXMAC_MASKSEC_U_1AC_0_TX_BUF_TRIGGER_POS 4 +/// MASKSEC_U_1AC_3_TX_TRIGGER field bit +#define NXMAC_MASKSEC_U_1AC_3_TX_TRIGGER_BIT ((uint32_t)0x00000008) +/// MASKSEC_U_1AC_3_TX_TRIGGER field position +#define NXMAC_MASKSEC_U_1AC_3_TX_TRIGGER_POS 3 +/// MASKSEC_U_1AC_2_TX_TRIGGER field bit +#define NXMAC_MASKSEC_U_1AC_2_TX_TRIGGER_BIT ((uint32_t)0x00000004) +/// MASKSEC_U_1AC_2_TX_TRIGGER field position +#define NXMAC_MASKSEC_U_1AC_2_TX_TRIGGER_POS 2 +/// MASKSEC_U_1AC_1_TX_TRIGGER field bit +#define NXMAC_MASKSEC_U_1AC_1_TX_TRIGGER_BIT ((uint32_t)0x00000002) +/// MASKSEC_U_1AC_1_TX_TRIGGER field position +#define NXMAC_MASKSEC_U_1AC_1_TX_TRIGGER_POS 1 +/// MASKSEC_U_1AC_0_TX_TRIGGER field bit +#define NXMAC_MASKSEC_U_1AC_0_TX_TRIGGER_BIT ((uint32_t)0x00000001) +/// MASKSEC_U_1AC_0_TX_TRIGGER field position +#define NXMAC_MASKSEC_U_1AC_0_TX_TRIGGER_POS 0 + +/// MASTER_SEC_USERS_TX_INT_EN field reset value +#define NXMAC_MASTER_SEC_USERS_TX_INT_EN_RST 0x0 +/// MASKSEC_U_3AC_3_TX_BUF_TRIGGER field reset value +#define NXMAC_MASKSEC_U_3AC_3_TX_BUF_TRIGGER_RST 0x0 +/// MASKSEC_U_3AC_2_TX_BUF_TRIGGER field reset value +#define NXMAC_MASKSEC_U_3AC_2_TX_BUF_TRIGGER_RST 0x0 +/// MASKSEC_U_3AC_1_TX_BUF_TRIGGER field reset value +#define NXMAC_MASKSEC_U_3AC_1_TX_BUF_TRIGGER_RST 0x0 +/// MASKSEC_U_3AC_0_TX_BUF_TRIGGER field reset value +#define NXMAC_MASKSEC_U_3AC_0_TX_BUF_TRIGGER_RST 0x0 +/// MASKSEC_U_3AC_3_TX_TRIGGER field reset value +#define NXMAC_MASKSEC_U_3AC_3_TX_TRIGGER_RST 0x0 +/// MASKSEC_U_3AC_2_TX_TRIGGER field reset value +#define NXMAC_MASKSEC_U_3AC_2_TX_TRIGGER_RST 0x0 +/// MASKSEC_U_3AC_1_TX_TRIGGER field reset value +#define NXMAC_MASKSEC_U_3AC_1_TX_TRIGGER_RST 0x0 +/// MASKSEC_U_3AC_0_TX_TRIGGER field reset value +#define NXMAC_MASKSEC_U_3AC_0_TX_TRIGGER_RST 0x0 +/// MASKSEC_U_2AC_3_TX_BUF_TRIGGER field reset value +#define NXMAC_MASKSEC_U_2AC_3_TX_BUF_TRIGGER_RST 0x0 +/// MASKSEC_U_2AC_2_TX_BUF_TRIGGER field reset value +#define NXMAC_MASKSEC_U_2AC_2_TX_BUF_TRIGGER_RST 0x0 +/// MASKSEC_U_2AC_1_TX_BUF_TRIGGER field reset value +#define NXMAC_MASKSEC_U_2AC_1_TX_BUF_TRIGGER_RST 0x0 +/// MASKSEC_U_2AC_0_TX_BUF_TRIGGER field reset value +#define NXMAC_MASKSEC_U_2AC_0_TX_BUF_TRIGGER_RST 0x0 +/// MASKSEC_U_2AC_3_TX_TRIGGER field reset value +#define NXMAC_MASKSEC_U_2AC_3_TX_TRIGGER_RST 0x0 +/// MASKSEC_U_2AC_2_TX_TRIGGER field reset value +#define NXMAC_MASKSEC_U_2AC_2_TX_TRIGGER_RST 0x0 +/// MASKSEC_U_2AC_1_TX_TRIGGER field reset value +#define NXMAC_MASKSEC_U_2AC_1_TX_TRIGGER_RST 0x0 +/// MASKSEC_U_2AC_0_TX_TRIGGER field reset value +#define NXMAC_MASKSEC_U_2AC_0_TX_TRIGGER_RST 0x0 +/// MASKSEC_U_1AC_3_TX_BUF_TRIGGER field reset value +#define NXMAC_MASKSEC_U_1AC_3_TX_BUF_TRIGGER_RST 0x0 +/// MASKSEC_U_1AC_2_TX_BUF_TRIGGER field reset value +#define NXMAC_MASKSEC_U_1AC_2_TX_BUF_TRIGGER_RST 0x0 +/// MASKSEC_U_1AC_1_TX_BUF_TRIGGER field reset value +#define NXMAC_MASKSEC_U_1AC_1_TX_BUF_TRIGGER_RST 0x0 +/// MASKSEC_U_1AC_0_TX_BUF_TRIGGER field reset value +#define NXMAC_MASKSEC_U_1AC_0_TX_BUF_TRIGGER_RST 0x0 +/// MASKSEC_U_1AC_3_TX_TRIGGER field reset value +#define NXMAC_MASKSEC_U_1AC_3_TX_TRIGGER_RST 0x0 +/// MASKSEC_U_1AC_2_TX_TRIGGER field reset value +#define NXMAC_MASKSEC_U_1AC_2_TX_TRIGGER_RST 0x0 +/// MASKSEC_U_1AC_1_TX_TRIGGER field reset value +#define NXMAC_MASKSEC_U_1AC_1_TX_TRIGGER_RST 0x0 +/// MASKSEC_U_1AC_0_TX_TRIGGER field reset value +#define NXMAC_MASKSEC_U_1AC_0_TX_TRIGGER_RST 0x0 + +/** + * @brief Constructs a value for the SEC_USERS_TX_INT_EVENT_UN_MASK register given values for its fields + * and writes the value to the register. + * + * @param[in] mastersecuserstxinten - The value to use for the masterSecUsersTxIntEn field. + * @param[in] masksecu3ac3txbuftrigger - The value to use for the masksecU3ac3TxBufTrigger field. + * @param[in] masksecu3ac2txbuftrigger - The value to use for the masksecU3ac2TxBufTrigger field. + * @param[in] masksecu3ac1txbuftrigger - The value to use for the masksecU3ac1TxBufTrigger field. + * @param[in] masksecu3ac0txbuftrigger - The value to use for the masksecU3ac0TxBufTrigger field. + * @param[in] masksecu3ac3txtrigger - The value to use for the masksecU3ac3TxTrigger field. + * @param[in] masksecu3ac2txtrigger - The value to use for the masksecU3ac2TxTrigger field. + * @param[in] masksecu3ac1txtrigger - The value to use for the masksecU3ac1TxTrigger field. + * @param[in] masksecu3ac0txtrigger - The value to use for the masksecU3ac0TxTrigger field. + * @param[in] masksecu2ac3txbuftrigger - The value to use for the masksecU2ac3TxBufTrigger field. + * @param[in] masksecu2ac2txbuftrigger - The value to use for the masksecU2ac2TxBufTrigger field. + * @param[in] masksecu2ac1txbuftrigger - The value to use for the masksecU2ac1TxBufTrigger field. + * @param[in] masksecu2ac0txbuftrigger - The value to use for the masksecU2ac0TxBufTrigger field. + * @param[in] masksecu2ac3txtrigger - The value to use for the masksecU2ac3TxTrigger field. + * @param[in] masksecu2ac2txtrigger - The value to use for the masksecU2ac2TxTrigger field. + * @param[in] masksecu2ac1txtrigger - The value to use for the masksecU2ac1TxTrigger field. + * @param[in] masksecu2ac0txtrigger - The value to use for the masksecU2ac0TxTrigger field. + * @param[in] masksecu1ac3txbuftrigger - The value to use for the masksecU1ac3TxBufTrigger field. + * @param[in] masksecu1ac2txbuftrigger - The value to use for the masksecU1ac2TxBufTrigger field. + * @param[in] masksecu1ac1txbuftrigger - The value to use for the masksecU1ac1TxBufTrigger field. + * @param[in] masksecu1ac0txbuftrigger - The value to use for the masksecU1ac0TxBufTrigger field. + * @param[in] masksecu1ac3txtrigger - The value to use for the masksecU1ac3TxTrigger field. + * @param[in] masksecu1ac2txtrigger - The value to use for the masksecU1ac2TxTrigger field. + * @param[in] masksecu1ac1txtrigger - The value to use for the masksecU1ac1TxTrigger field. + * @param[in] masksecu1ac0txtrigger - The value to use for the masksecU1ac0TxTrigger field. + */ +__INLINE void nxmac_sec_users_tx_int_event_un_mask_pack(uint8_t mastersecuserstxinten, uint8_t masksecu3ac3txbuftrigger, uint8_t masksecu3ac2txbuftrigger, uint8_t masksecu3ac1txbuftrigger, uint8_t masksecu3ac0txbuftrigger, uint8_t masksecu3ac3txtrigger, uint8_t masksecu3ac2txtrigger, uint8_t masksecu3ac1txtrigger, uint8_t masksecu3ac0txtrigger, uint8_t masksecu2ac3txbuftrigger, uint8_t masksecu2ac2txbuftrigger, uint8_t masksecu2ac1txbuftrigger, uint8_t masksecu2ac0txbuftrigger, uint8_t masksecu2ac3txtrigger, uint8_t masksecu2ac2txtrigger, uint8_t masksecu2ac1txtrigger, uint8_t masksecu2ac0txtrigger, uint8_t masksecu1ac3txbuftrigger, uint8_t masksecu1ac2txbuftrigger, uint8_t masksecu1ac1txbuftrigger, uint8_t masksecu1ac0txbuftrigger, uint8_t masksecu1ac3txtrigger, uint8_t masksecu1ac2txtrigger, uint8_t masksecu1ac1txtrigger, uint8_t masksecu1ac0txtrigger) +{ + ASSERT_ERR((((uint32_t)mastersecuserstxinten << 31) & ~((uint32_t)0x80000000)) == 0); + ASSERT_ERR((((uint32_t)masksecu3ac3txbuftrigger << 23) & ~((uint32_t)0x00800000)) == 0); + ASSERT_ERR((((uint32_t)masksecu3ac2txbuftrigger << 22) & ~((uint32_t)0x00400000)) == 0); + ASSERT_ERR((((uint32_t)masksecu3ac1txbuftrigger << 21) & ~((uint32_t)0x00200000)) == 0); + ASSERT_ERR((((uint32_t)masksecu3ac0txbuftrigger << 20) & ~((uint32_t)0x00100000)) == 0); + ASSERT_ERR((((uint32_t)masksecu3ac3txtrigger << 19) & ~((uint32_t)0x00080000)) == 0); + ASSERT_ERR((((uint32_t)masksecu3ac2txtrigger << 18) & ~((uint32_t)0x00040000)) == 0); + ASSERT_ERR((((uint32_t)masksecu3ac1txtrigger << 17) & ~((uint32_t)0x00020000)) == 0); + ASSERT_ERR((((uint32_t)masksecu3ac0txtrigger << 16) & ~((uint32_t)0x00010000)) == 0); + ASSERT_ERR((((uint32_t)masksecu2ac3txbuftrigger << 15) & ~((uint32_t)0x00008000)) == 0); + ASSERT_ERR((((uint32_t)masksecu2ac2txbuftrigger << 14) & ~((uint32_t)0x00004000)) == 0); + ASSERT_ERR((((uint32_t)masksecu2ac1txbuftrigger << 13) & ~((uint32_t)0x00002000)) == 0); + ASSERT_ERR((((uint32_t)masksecu2ac0txbuftrigger << 12) & ~((uint32_t)0x00001000)) == 0); + ASSERT_ERR((((uint32_t)masksecu2ac3txtrigger << 11) & ~((uint32_t)0x00000800)) == 0); + ASSERT_ERR((((uint32_t)masksecu2ac2txtrigger << 10) & ~((uint32_t)0x00000400)) == 0); + ASSERT_ERR((((uint32_t)masksecu2ac1txtrigger << 9) & ~((uint32_t)0x00000200)) == 0); + ASSERT_ERR((((uint32_t)masksecu2ac0txtrigger << 8) & ~((uint32_t)0x00000100)) == 0); + ASSERT_ERR((((uint32_t)masksecu1ac3txbuftrigger << 7) & ~((uint32_t)0x00000080)) == 0); + ASSERT_ERR((((uint32_t)masksecu1ac2txbuftrigger << 6) & ~((uint32_t)0x00000040)) == 0); + ASSERT_ERR((((uint32_t)masksecu1ac1txbuftrigger << 5) & ~((uint32_t)0x00000020)) == 0); + ASSERT_ERR((((uint32_t)masksecu1ac0txbuftrigger << 4) & ~((uint32_t)0x00000010)) == 0); + ASSERT_ERR((((uint32_t)masksecu1ac3txtrigger << 3) & ~((uint32_t)0x00000008)) == 0); + ASSERT_ERR((((uint32_t)masksecu1ac2txtrigger << 2) & ~((uint32_t)0x00000004)) == 0); + ASSERT_ERR((((uint32_t)masksecu1ac1txtrigger << 1) & ~((uint32_t)0x00000002)) == 0); + ASSERT_ERR((((uint32_t)masksecu1ac0txtrigger << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR, ((uint32_t)mastersecuserstxinten << 31) | ((uint32_t)masksecu3ac3txbuftrigger << 23) | ((uint32_t)masksecu3ac2txbuftrigger << 22) | ((uint32_t)masksecu3ac1txbuftrigger << 21) | ((uint32_t)masksecu3ac0txbuftrigger << 20) | ((uint32_t)masksecu3ac3txtrigger << 19) | ((uint32_t)masksecu3ac2txtrigger << 18) | ((uint32_t)masksecu3ac1txtrigger << 17) | ((uint32_t)masksecu3ac0txtrigger << 16) | ((uint32_t)masksecu2ac3txbuftrigger << 15) | ((uint32_t)masksecu2ac2txbuftrigger << 14) | ((uint32_t)masksecu2ac1txbuftrigger << 13) | ((uint32_t)masksecu2ac0txbuftrigger << 12) | ((uint32_t)masksecu2ac3txtrigger << 11) | ((uint32_t)masksecu2ac2txtrigger << 10) | ((uint32_t)masksecu2ac1txtrigger << 9) | ((uint32_t)masksecu2ac0txtrigger << 8) | ((uint32_t)masksecu1ac3txbuftrigger << 7) | ((uint32_t)masksecu1ac2txbuftrigger << 6) | ((uint32_t)masksecu1ac1txbuftrigger << 5) | ((uint32_t)masksecu1ac0txbuftrigger << 4) | ((uint32_t)masksecu1ac3txtrigger << 3) | ((uint32_t)masksecu1ac2txtrigger << 2) | ((uint32_t)masksecu1ac1txtrigger << 1) | ((uint32_t)masksecu1ac0txtrigger << 0)); +} + +/** + * @brief Unpacks SEC_USERS_TX_INT_EVENT_UN_MASK's fields from current value of the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * + * Reads the SEC_USERS_TX_INT_EVENT_UN_MASK register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] mastersecuserstxinten - Will be populated with the current value of this field from the register. + * @param[out] masksecu3ac3txbuftrigger - Will be populated with the current value of this field from the register. + * @param[out] masksecu3ac2txbuftrigger - Will be populated with the current value of this field from the register. + * @param[out] masksecu3ac1txbuftrigger - Will be populated with the current value of this field from the register. + * @param[out] masksecu3ac0txbuftrigger - Will be populated with the current value of this field from the register. + * @param[out] masksecu3ac3txtrigger - Will be populated with the current value of this field from the register. + * @param[out] masksecu3ac2txtrigger - Will be populated with the current value of this field from the register. + * @param[out] masksecu3ac1txtrigger - Will be populated with the current value of this field from the register. + * @param[out] masksecu3ac0txtrigger - Will be populated with the current value of this field from the register. + * @param[out] masksecu2ac3txbuftrigger - Will be populated with the current value of this field from the register. + * @param[out] masksecu2ac2txbuftrigger - Will be populated with the current value of this field from the register. + * @param[out] masksecu2ac1txbuftrigger - Will be populated with the current value of this field from the register. + * @param[out] masksecu2ac0txbuftrigger - Will be populated with the current value of this field from the register. + * @param[out] masksecu2ac3txtrigger - Will be populated with the current value of this field from the register. + * @param[out] masksecu2ac2txtrigger - Will be populated with the current value of this field from the register. + * @param[out] masksecu2ac1txtrigger - Will be populated with the current value of this field from the register. + * @param[out] masksecu2ac0txtrigger - Will be populated with the current value of this field from the register. + * @param[out] masksecu1ac3txbuftrigger - Will be populated with the current value of this field from the register. + * @param[out] masksecu1ac2txbuftrigger - Will be populated with the current value of this field from the register. + * @param[out] masksecu1ac1txbuftrigger - Will be populated with the current value of this field from the register. + * @param[out] masksecu1ac0txbuftrigger - Will be populated with the current value of this field from the register. + * @param[out] masksecu1ac3txtrigger - Will be populated with the current value of this field from the register. + * @param[out] masksecu1ac2txtrigger - Will be populated with the current value of this field from the register. + * @param[out] masksecu1ac1txtrigger - Will be populated with the current value of this field from the register. + * @param[out] masksecu1ac0txtrigger - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_sec_users_tx_int_event_un_mask_unpack(uint8_t *mastersecuserstxinten, uint8_t *masksecu3ac3txbuftrigger, uint8_t *masksecu3ac2txbuftrigger, uint8_t *masksecu3ac1txbuftrigger, uint8_t *masksecu3ac0txbuftrigger, uint8_t *masksecu3ac3txtrigger, uint8_t *masksecu3ac2txtrigger, uint8_t *masksecu3ac1txtrigger, uint8_t *masksecu3ac0txtrigger, uint8_t *masksecu2ac3txbuftrigger, uint8_t *masksecu2ac2txbuftrigger, uint8_t *masksecu2ac1txbuftrigger, uint8_t *masksecu2ac0txbuftrigger, uint8_t *masksecu2ac3txtrigger, uint8_t *masksecu2ac2txtrigger, uint8_t *masksecu2ac1txtrigger, uint8_t *masksecu2ac0txtrigger, uint8_t *masksecu1ac3txbuftrigger, uint8_t *masksecu1ac2txbuftrigger, uint8_t *masksecu1ac1txbuftrigger, uint8_t *masksecu1ac0txbuftrigger, uint8_t *masksecu1ac3txtrigger, uint8_t *masksecu1ac2txtrigger, uint8_t *masksecu1ac1txtrigger, uint8_t *masksecu1ac0txtrigger) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR); + + *mastersecuserstxinten = (localVal & ((uint32_t)0x80000000)) >> 31; + *masksecu3ac3txbuftrigger = (localVal & ((uint32_t)0x00800000)) >> 23; + *masksecu3ac2txbuftrigger = (localVal & ((uint32_t)0x00400000)) >> 22; + *masksecu3ac1txbuftrigger = (localVal & ((uint32_t)0x00200000)) >> 21; + *masksecu3ac0txbuftrigger = (localVal & ((uint32_t)0x00100000)) >> 20; + *masksecu3ac3txtrigger = (localVal & ((uint32_t)0x00080000)) >> 19; + *masksecu3ac2txtrigger = (localVal & ((uint32_t)0x00040000)) >> 18; + *masksecu3ac1txtrigger = (localVal & ((uint32_t)0x00020000)) >> 17; + *masksecu3ac0txtrigger = (localVal & ((uint32_t)0x00010000)) >> 16; + *masksecu2ac3txbuftrigger = (localVal & ((uint32_t)0x00008000)) >> 15; + *masksecu2ac2txbuftrigger = (localVal & ((uint32_t)0x00004000)) >> 14; + *masksecu2ac1txbuftrigger = (localVal & ((uint32_t)0x00002000)) >> 13; + *masksecu2ac0txbuftrigger = (localVal & ((uint32_t)0x00001000)) >> 12; + *masksecu2ac3txtrigger = (localVal & ((uint32_t)0x00000800)) >> 11; + *masksecu2ac2txtrigger = (localVal & ((uint32_t)0x00000400)) >> 10; + *masksecu2ac1txtrigger = (localVal & ((uint32_t)0x00000200)) >> 9; + *masksecu2ac0txtrigger = (localVal & ((uint32_t)0x00000100)) >> 8; + *masksecu1ac3txbuftrigger = (localVal & ((uint32_t)0x00000080)) >> 7; + *masksecu1ac2txbuftrigger = (localVal & ((uint32_t)0x00000040)) >> 6; + *masksecu1ac1txbuftrigger = (localVal & ((uint32_t)0x00000020)) >> 5; + *masksecu1ac0txbuftrigger = (localVal & ((uint32_t)0x00000010)) >> 4; + *masksecu1ac3txtrigger = (localVal & ((uint32_t)0x00000008)) >> 3; + *masksecu1ac2txtrigger = (localVal & ((uint32_t)0x00000004)) >> 2; + *masksecu1ac1txtrigger = (localVal & ((uint32_t)0x00000002)) >> 1; + *masksecu1ac0txtrigger = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +/** + * @brief Returns the current value of the masterSecUsersTxIntEn field in the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be read and the masterSecUsersTxIntEn field's value will be returned. + * + * @return The current value of the masterSecUsersTxIntEn field in the SEC_USERS_TX_INT_EVENT_UN_MASK register. + */ +__INLINE uint8_t nxmac_master_sec_users_tx_int_en_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +/** + * @brief Sets the masterSecUsersTxIntEn field of the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be read, modified to contain the new field value, and written. + * + * @param[in] mastersecuserstxinten - The value to set the field to. + */ +__INLINE void nxmac_master_sec_users_tx_int_en_setf(uint8_t mastersecuserstxinten) +{ + ASSERT_ERR((((uint32_t)mastersecuserstxinten << 31) & ~((uint32_t)0x80000000)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR, (REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR) & ~((uint32_t)0x80000000)) | ((uint32_t)mastersecuserstxinten << 31)); +} + +/** + * @brief Returns the current value of the masksecU3ac3TxBufTrigger field in the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be read and the masksecU3ac3TxBufTrigger field's value will be returned. + * + * @return The current value of the masksecU3ac3TxBufTrigger field in the SEC_USERS_TX_INT_EVENT_UN_MASK register. + */ +__INLINE uint8_t nxmac_masksec_u_3ac_3_tx_buf_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR); + return ((localVal & ((uint32_t)0x00800000)) >> 23); +} + +/** + * @brief Sets the masksecU3ac3TxBufTrigger field of the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be read, modified to contain the new field value, and written. + * + * @param[in] masksecu3ac3txbuftrigger - The value to set the field to. + */ +__INLINE void nxmac_masksec_u_3ac_3_tx_buf_trigger_setf(uint8_t masksecu3ac3txbuftrigger) +{ + ASSERT_ERR((((uint32_t)masksecu3ac3txbuftrigger << 23) & ~((uint32_t)0x00800000)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR, (REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR) & ~((uint32_t)0x00800000)) | ((uint32_t)masksecu3ac3txbuftrigger << 23)); +} + +/** + * @brief Returns the current value of the masksecU3ac2TxBufTrigger field in the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be read and the masksecU3ac2TxBufTrigger field's value will be returned. + * + * @return The current value of the masksecU3ac2TxBufTrigger field in the SEC_USERS_TX_INT_EVENT_UN_MASK register. + */ +__INLINE uint8_t nxmac_masksec_u_3ac_2_tx_buf_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR); + return ((localVal & ((uint32_t)0x00400000)) >> 22); +} + +/** + * @brief Sets the masksecU3ac2TxBufTrigger field of the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be read, modified to contain the new field value, and written. + * + * @param[in] masksecu3ac2txbuftrigger - The value to set the field to. + */ +__INLINE void nxmac_masksec_u_3ac_2_tx_buf_trigger_setf(uint8_t masksecu3ac2txbuftrigger) +{ + ASSERT_ERR((((uint32_t)masksecu3ac2txbuftrigger << 22) & ~((uint32_t)0x00400000)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR, (REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR) & ~((uint32_t)0x00400000)) | ((uint32_t)masksecu3ac2txbuftrigger << 22)); +} + +/** + * @brief Returns the current value of the masksecU3ac1TxBufTrigger field in the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be read and the masksecU3ac1TxBufTrigger field's value will be returned. + * + * @return The current value of the masksecU3ac1TxBufTrigger field in the SEC_USERS_TX_INT_EVENT_UN_MASK register. + */ +__INLINE uint8_t nxmac_masksec_u_3ac_1_tx_buf_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR); + return ((localVal & ((uint32_t)0x00200000)) >> 21); +} + +/** + * @brief Sets the masksecU3ac1TxBufTrigger field of the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be read, modified to contain the new field value, and written. + * + * @param[in] masksecu3ac1txbuftrigger - The value to set the field to. + */ +__INLINE void nxmac_masksec_u_3ac_1_tx_buf_trigger_setf(uint8_t masksecu3ac1txbuftrigger) +{ + ASSERT_ERR((((uint32_t)masksecu3ac1txbuftrigger << 21) & ~((uint32_t)0x00200000)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR, (REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR) & ~((uint32_t)0x00200000)) | ((uint32_t)masksecu3ac1txbuftrigger << 21)); +} + +/** + * @brief Returns the current value of the masksecU3ac0TxBufTrigger field in the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be read and the masksecU3ac0TxBufTrigger field's value will be returned. + * + * @return The current value of the masksecU3ac0TxBufTrigger field in the SEC_USERS_TX_INT_EVENT_UN_MASK register. + */ +__INLINE uint8_t nxmac_masksec_u_3ac_0_tx_buf_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR); + return ((localVal & ((uint32_t)0x00100000)) >> 20); +} + +/** + * @brief Sets the masksecU3ac0TxBufTrigger field of the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be read, modified to contain the new field value, and written. + * + * @param[in] masksecu3ac0txbuftrigger - The value to set the field to. + */ +__INLINE void nxmac_masksec_u_3ac_0_tx_buf_trigger_setf(uint8_t masksecu3ac0txbuftrigger) +{ + ASSERT_ERR((((uint32_t)masksecu3ac0txbuftrigger << 20) & ~((uint32_t)0x00100000)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR, (REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR) & ~((uint32_t)0x00100000)) | ((uint32_t)masksecu3ac0txbuftrigger << 20)); +} + +/** + * @brief Returns the current value of the masksecU3ac3TxTrigger field in the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be read and the masksecU3ac3TxTrigger field's value will be returned. + * + * @return The current value of the masksecU3ac3TxTrigger field in the SEC_USERS_TX_INT_EVENT_UN_MASK register. + */ +__INLINE uint8_t nxmac_masksec_u_3ac_3_tx_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR); + return ((localVal & ((uint32_t)0x00080000)) >> 19); +} + +/** + * @brief Sets the masksecU3ac3TxTrigger field of the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be read, modified to contain the new field value, and written. + * + * @param[in] masksecu3ac3txtrigger - The value to set the field to. + */ +__INLINE void nxmac_masksec_u_3ac_3_tx_trigger_setf(uint8_t masksecu3ac3txtrigger) +{ + ASSERT_ERR((((uint32_t)masksecu3ac3txtrigger << 19) & ~((uint32_t)0x00080000)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR, (REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR) & ~((uint32_t)0x00080000)) | ((uint32_t)masksecu3ac3txtrigger << 19)); +} + +/** + * @brief Returns the current value of the masksecU3ac2TxTrigger field in the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be read and the masksecU3ac2TxTrigger field's value will be returned. + * + * @return The current value of the masksecU3ac2TxTrigger field in the SEC_USERS_TX_INT_EVENT_UN_MASK register. + */ +__INLINE uint8_t nxmac_masksec_u_3ac_2_tx_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR); + return ((localVal & ((uint32_t)0x00040000)) >> 18); +} + +/** + * @brief Sets the masksecU3ac2TxTrigger field of the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be read, modified to contain the new field value, and written. + * + * @param[in] masksecu3ac2txtrigger - The value to set the field to. + */ +__INLINE void nxmac_masksec_u_3ac_2_tx_trigger_setf(uint8_t masksecu3ac2txtrigger) +{ + ASSERT_ERR((((uint32_t)masksecu3ac2txtrigger << 18) & ~((uint32_t)0x00040000)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR, (REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR) & ~((uint32_t)0x00040000)) | ((uint32_t)masksecu3ac2txtrigger << 18)); +} + +/** + * @brief Returns the current value of the masksecU3ac1TxTrigger field in the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be read and the masksecU3ac1TxTrigger field's value will be returned. + * + * @return The current value of the masksecU3ac1TxTrigger field in the SEC_USERS_TX_INT_EVENT_UN_MASK register. + */ +__INLINE uint8_t nxmac_masksec_u_3ac_1_tx_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR); + return ((localVal & ((uint32_t)0x00020000)) >> 17); +} + +/** + * @brief Sets the masksecU3ac1TxTrigger field of the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be read, modified to contain the new field value, and written. + * + * @param[in] masksecu3ac1txtrigger - The value to set the field to. + */ +__INLINE void nxmac_masksec_u_3ac_1_tx_trigger_setf(uint8_t masksecu3ac1txtrigger) +{ + ASSERT_ERR((((uint32_t)masksecu3ac1txtrigger << 17) & ~((uint32_t)0x00020000)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR, (REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR) & ~((uint32_t)0x00020000)) | ((uint32_t)masksecu3ac1txtrigger << 17)); +} + +/** + * @brief Returns the current value of the masksecU3ac0TxTrigger field in the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be read and the masksecU3ac0TxTrigger field's value will be returned. + * + * @return The current value of the masksecU3ac0TxTrigger field in the SEC_USERS_TX_INT_EVENT_UN_MASK register. + */ +__INLINE uint8_t nxmac_masksec_u_3ac_0_tx_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR); + return ((localVal & ((uint32_t)0x00010000)) >> 16); +} + +/** + * @brief Sets the masksecU3ac0TxTrigger field of the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be read, modified to contain the new field value, and written. + * + * @param[in] masksecu3ac0txtrigger - The value to set the field to. + */ +__INLINE void nxmac_masksec_u_3ac_0_tx_trigger_setf(uint8_t masksecu3ac0txtrigger) +{ + ASSERT_ERR((((uint32_t)masksecu3ac0txtrigger << 16) & ~((uint32_t)0x00010000)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR, (REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR) & ~((uint32_t)0x00010000)) | ((uint32_t)masksecu3ac0txtrigger << 16)); +} + +/** + * @brief Returns the current value of the masksecU2ac3TxBufTrigger field in the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be read and the masksecU2ac3TxBufTrigger field's value will be returned. + * + * @return The current value of the masksecU2ac3TxBufTrigger field in the SEC_USERS_TX_INT_EVENT_UN_MASK register. + */ +__INLINE uint8_t nxmac_masksec_u_2ac_3_tx_buf_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR); + return ((localVal & ((uint32_t)0x00008000)) >> 15); +} + +/** + * @brief Sets the masksecU2ac3TxBufTrigger field of the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be read, modified to contain the new field value, and written. + * + * @param[in] masksecu2ac3txbuftrigger - The value to set the field to. + */ +__INLINE void nxmac_masksec_u_2ac_3_tx_buf_trigger_setf(uint8_t masksecu2ac3txbuftrigger) +{ + ASSERT_ERR((((uint32_t)masksecu2ac3txbuftrigger << 15) & ~((uint32_t)0x00008000)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR, (REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR) & ~((uint32_t)0x00008000)) | ((uint32_t)masksecu2ac3txbuftrigger << 15)); +} + +/** + * @brief Returns the current value of the masksecU2ac2TxBufTrigger field in the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be read and the masksecU2ac2TxBufTrigger field's value will be returned. + * + * @return The current value of the masksecU2ac2TxBufTrigger field in the SEC_USERS_TX_INT_EVENT_UN_MASK register. + */ +__INLINE uint8_t nxmac_masksec_u_2ac_2_tx_buf_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR); + return ((localVal & ((uint32_t)0x00004000)) >> 14); +} + +/** + * @brief Sets the masksecU2ac2TxBufTrigger field of the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be read, modified to contain the new field value, and written. + * + * @param[in] masksecu2ac2txbuftrigger - The value to set the field to. + */ +__INLINE void nxmac_masksec_u_2ac_2_tx_buf_trigger_setf(uint8_t masksecu2ac2txbuftrigger) +{ + ASSERT_ERR((((uint32_t)masksecu2ac2txbuftrigger << 14) & ~((uint32_t)0x00004000)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR, (REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR) & ~((uint32_t)0x00004000)) | ((uint32_t)masksecu2ac2txbuftrigger << 14)); +} + +/** + * @brief Returns the current value of the masksecU2ac1TxBufTrigger field in the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be read and the masksecU2ac1TxBufTrigger field's value will be returned. + * + * @return The current value of the masksecU2ac1TxBufTrigger field in the SEC_USERS_TX_INT_EVENT_UN_MASK register. + */ +__INLINE uint8_t nxmac_masksec_u_2ac_1_tx_buf_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR); + return ((localVal & ((uint32_t)0x00002000)) >> 13); +} + +/** + * @brief Sets the masksecU2ac1TxBufTrigger field of the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be read, modified to contain the new field value, and written. + * + * @param[in] masksecu2ac1txbuftrigger - The value to set the field to. + */ +__INLINE void nxmac_masksec_u_2ac_1_tx_buf_trigger_setf(uint8_t masksecu2ac1txbuftrigger) +{ + ASSERT_ERR((((uint32_t)masksecu2ac1txbuftrigger << 13) & ~((uint32_t)0x00002000)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR, (REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR) & ~((uint32_t)0x00002000)) | ((uint32_t)masksecu2ac1txbuftrigger << 13)); +} + +/** + * @brief Returns the current value of the masksecU2ac0TxBufTrigger field in the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be read and the masksecU2ac0TxBufTrigger field's value will be returned. + * + * @return The current value of the masksecU2ac0TxBufTrigger field in the SEC_USERS_TX_INT_EVENT_UN_MASK register. + */ +__INLINE uint8_t nxmac_masksec_u_2ac_0_tx_buf_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR); + return ((localVal & ((uint32_t)0x00001000)) >> 12); +} + +/** + * @brief Sets the masksecU2ac0TxBufTrigger field of the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be read, modified to contain the new field value, and written. + * + * @param[in] masksecu2ac0txbuftrigger - The value to set the field to. + */ +__INLINE void nxmac_masksec_u_2ac_0_tx_buf_trigger_setf(uint8_t masksecu2ac0txbuftrigger) +{ + ASSERT_ERR((((uint32_t)masksecu2ac0txbuftrigger << 12) & ~((uint32_t)0x00001000)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR, (REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR) & ~((uint32_t)0x00001000)) | ((uint32_t)masksecu2ac0txbuftrigger << 12)); +} + +/** + * @brief Returns the current value of the masksecU2ac3TxTrigger field in the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be read and the masksecU2ac3TxTrigger field's value will be returned. + * + * @return The current value of the masksecU2ac3TxTrigger field in the SEC_USERS_TX_INT_EVENT_UN_MASK register. + */ +__INLINE uint8_t nxmac_masksec_u_2ac_3_tx_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR); + return ((localVal & ((uint32_t)0x00000800)) >> 11); +} + +/** + * @brief Sets the masksecU2ac3TxTrigger field of the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be read, modified to contain the new field value, and written. + * + * @param[in] masksecu2ac3txtrigger - The value to set the field to. + */ +__INLINE void nxmac_masksec_u_2ac_3_tx_trigger_setf(uint8_t masksecu2ac3txtrigger) +{ + ASSERT_ERR((((uint32_t)masksecu2ac3txtrigger << 11) & ~((uint32_t)0x00000800)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR, (REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR) & ~((uint32_t)0x00000800)) | ((uint32_t)masksecu2ac3txtrigger << 11)); +} + +/** + * @brief Returns the current value of the masksecU2ac2TxTrigger field in the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be read and the masksecU2ac2TxTrigger field's value will be returned. + * + * @return The current value of the masksecU2ac2TxTrigger field in the SEC_USERS_TX_INT_EVENT_UN_MASK register. + */ +__INLINE uint8_t nxmac_masksec_u_2ac_2_tx_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR); + return ((localVal & ((uint32_t)0x00000400)) >> 10); +} + +/** + * @brief Sets the masksecU2ac2TxTrigger field of the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be read, modified to contain the new field value, and written. + * + * @param[in] masksecu2ac2txtrigger - The value to set the field to. + */ +__INLINE void nxmac_masksec_u_2ac_2_tx_trigger_setf(uint8_t masksecu2ac2txtrigger) +{ + ASSERT_ERR((((uint32_t)masksecu2ac2txtrigger << 10) & ~((uint32_t)0x00000400)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR, (REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR) & ~((uint32_t)0x00000400)) | ((uint32_t)masksecu2ac2txtrigger << 10)); +} + +/** + * @brief Returns the current value of the masksecU2ac1TxTrigger field in the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be read and the masksecU2ac1TxTrigger field's value will be returned. + * + * @return The current value of the masksecU2ac1TxTrigger field in the SEC_USERS_TX_INT_EVENT_UN_MASK register. + */ +__INLINE uint8_t nxmac_masksec_u_2ac_1_tx_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR); + return ((localVal & ((uint32_t)0x00000200)) >> 9); +} + +/** + * @brief Sets the masksecU2ac1TxTrigger field of the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be read, modified to contain the new field value, and written. + * + * @param[in] masksecu2ac1txtrigger - The value to set the field to. + */ +__INLINE void nxmac_masksec_u_2ac_1_tx_trigger_setf(uint8_t masksecu2ac1txtrigger) +{ + ASSERT_ERR((((uint32_t)masksecu2ac1txtrigger << 9) & ~((uint32_t)0x00000200)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR, (REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR) & ~((uint32_t)0x00000200)) | ((uint32_t)masksecu2ac1txtrigger << 9)); +} + +/** + * @brief Returns the current value of the masksecU2ac0TxTrigger field in the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be read and the masksecU2ac0TxTrigger field's value will be returned. + * + * @return The current value of the masksecU2ac0TxTrigger field in the SEC_USERS_TX_INT_EVENT_UN_MASK register. + */ +__INLINE uint8_t nxmac_masksec_u_2ac_0_tx_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR); + return ((localVal & ((uint32_t)0x00000100)) >> 8); +} + +/** + * @brief Sets the masksecU2ac0TxTrigger field of the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be read, modified to contain the new field value, and written. + * + * @param[in] masksecu2ac0txtrigger - The value to set the field to. + */ +__INLINE void nxmac_masksec_u_2ac_0_tx_trigger_setf(uint8_t masksecu2ac0txtrigger) +{ + ASSERT_ERR((((uint32_t)masksecu2ac0txtrigger << 8) & ~((uint32_t)0x00000100)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR, (REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR) & ~((uint32_t)0x00000100)) | ((uint32_t)masksecu2ac0txtrigger << 8)); +} + +/** + * @brief Returns the current value of the masksecU1ac3TxBufTrigger field in the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be read and the masksecU1ac3TxBufTrigger field's value will be returned. + * + * @return The current value of the masksecU1ac3TxBufTrigger field in the SEC_USERS_TX_INT_EVENT_UN_MASK register. + */ +__INLINE uint8_t nxmac_masksec_u_1ac_3_tx_buf_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR); + return ((localVal & ((uint32_t)0x00000080)) >> 7); +} + +/** + * @brief Sets the masksecU1ac3TxBufTrigger field of the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be read, modified to contain the new field value, and written. + * + * @param[in] masksecu1ac3txbuftrigger - The value to set the field to. + */ +__INLINE void nxmac_masksec_u_1ac_3_tx_buf_trigger_setf(uint8_t masksecu1ac3txbuftrigger) +{ + ASSERT_ERR((((uint32_t)masksecu1ac3txbuftrigger << 7) & ~((uint32_t)0x00000080)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR, (REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR) & ~((uint32_t)0x00000080)) | ((uint32_t)masksecu1ac3txbuftrigger << 7)); +} + +/** + * @brief Returns the current value of the masksecU1ac2TxBufTrigger field in the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be read and the masksecU1ac2TxBufTrigger field's value will be returned. + * + * @return The current value of the masksecU1ac2TxBufTrigger field in the SEC_USERS_TX_INT_EVENT_UN_MASK register. + */ +__INLINE uint8_t nxmac_masksec_u_1ac_2_tx_buf_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR); + return ((localVal & ((uint32_t)0x00000040)) >> 6); +} + +/** + * @brief Sets the masksecU1ac2TxBufTrigger field of the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be read, modified to contain the new field value, and written. + * + * @param[in] masksecu1ac2txbuftrigger - The value to set the field to. + */ +__INLINE void nxmac_masksec_u_1ac_2_tx_buf_trigger_setf(uint8_t masksecu1ac2txbuftrigger) +{ + ASSERT_ERR((((uint32_t)masksecu1ac2txbuftrigger << 6) & ~((uint32_t)0x00000040)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR, (REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR) & ~((uint32_t)0x00000040)) | ((uint32_t)masksecu1ac2txbuftrigger << 6)); +} + +/** + * @brief Returns the current value of the masksecU1ac1TxBufTrigger field in the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be read and the masksecU1ac1TxBufTrigger field's value will be returned. + * + * @return The current value of the masksecU1ac1TxBufTrigger field in the SEC_USERS_TX_INT_EVENT_UN_MASK register. + */ +__INLINE uint8_t nxmac_masksec_u_1ac_1_tx_buf_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +/** + * @brief Sets the masksecU1ac1TxBufTrigger field of the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be read, modified to contain the new field value, and written. + * + * @param[in] masksecu1ac1txbuftrigger - The value to set the field to. + */ +__INLINE void nxmac_masksec_u_1ac_1_tx_buf_trigger_setf(uint8_t masksecu1ac1txbuftrigger) +{ + ASSERT_ERR((((uint32_t)masksecu1ac1txbuftrigger << 5) & ~((uint32_t)0x00000020)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR, (REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR) & ~((uint32_t)0x00000020)) | ((uint32_t)masksecu1ac1txbuftrigger << 5)); +} + +/** + * @brief Returns the current value of the masksecU1ac0TxBufTrigger field in the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be read and the masksecU1ac0TxBufTrigger field's value will be returned. + * + * @return The current value of the masksecU1ac0TxBufTrigger field in the SEC_USERS_TX_INT_EVENT_UN_MASK register. + */ +__INLINE uint8_t nxmac_masksec_u_1ac_0_tx_buf_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +/** + * @brief Sets the masksecU1ac0TxBufTrigger field of the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be read, modified to contain the new field value, and written. + * + * @param[in] masksecu1ac0txbuftrigger - The value to set the field to. + */ +__INLINE void nxmac_masksec_u_1ac_0_tx_buf_trigger_setf(uint8_t masksecu1ac0txbuftrigger) +{ + ASSERT_ERR((((uint32_t)masksecu1ac0txbuftrigger << 4) & ~((uint32_t)0x00000010)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR, (REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR) & ~((uint32_t)0x00000010)) | ((uint32_t)masksecu1ac0txbuftrigger << 4)); +} + +/** + * @brief Returns the current value of the masksecU1ac3TxTrigger field in the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be read and the masksecU1ac3TxTrigger field's value will be returned. + * + * @return The current value of the masksecU1ac3TxTrigger field in the SEC_USERS_TX_INT_EVENT_UN_MASK register. + */ +__INLINE uint8_t nxmac_masksec_u_1ac_3_tx_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +/** + * @brief Sets the masksecU1ac3TxTrigger field of the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be read, modified to contain the new field value, and written. + * + * @param[in] masksecu1ac3txtrigger - The value to set the field to. + */ +__INLINE void nxmac_masksec_u_1ac_3_tx_trigger_setf(uint8_t masksecu1ac3txtrigger) +{ + ASSERT_ERR((((uint32_t)masksecu1ac3txtrigger << 3) & ~((uint32_t)0x00000008)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR, (REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR) & ~((uint32_t)0x00000008)) | ((uint32_t)masksecu1ac3txtrigger << 3)); +} + +/** + * @brief Returns the current value of the masksecU1ac2TxTrigger field in the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be read and the masksecU1ac2TxTrigger field's value will be returned. + * + * @return The current value of the masksecU1ac2TxTrigger field in the SEC_USERS_TX_INT_EVENT_UN_MASK register. + */ +__INLINE uint8_t nxmac_masksec_u_1ac_2_tx_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +/** + * @brief Sets the masksecU1ac2TxTrigger field of the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be read, modified to contain the new field value, and written. + * + * @param[in] masksecu1ac2txtrigger - The value to set the field to. + */ +__INLINE void nxmac_masksec_u_1ac_2_tx_trigger_setf(uint8_t masksecu1ac2txtrigger) +{ + ASSERT_ERR((((uint32_t)masksecu1ac2txtrigger << 2) & ~((uint32_t)0x00000004)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR, (REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR) & ~((uint32_t)0x00000004)) | ((uint32_t)masksecu1ac2txtrigger << 2)); +} + +/** + * @brief Returns the current value of the masksecU1ac1TxTrigger field in the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be read and the masksecU1ac1TxTrigger field's value will be returned. + * + * @return The current value of the masksecU1ac1TxTrigger field in the SEC_USERS_TX_INT_EVENT_UN_MASK register. + */ +__INLINE uint8_t nxmac_masksec_u_1ac_1_tx_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +/** + * @brief Sets the masksecU1ac1TxTrigger field of the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be read, modified to contain the new field value, and written. + * + * @param[in] masksecu1ac1txtrigger - The value to set the field to. + */ +__INLINE void nxmac_masksec_u_1ac_1_tx_trigger_setf(uint8_t masksecu1ac1txtrigger) +{ + ASSERT_ERR((((uint32_t)masksecu1ac1txtrigger << 1) & ~((uint32_t)0x00000002)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR, (REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR) & ~((uint32_t)0x00000002)) | ((uint32_t)masksecu1ac1txtrigger << 1)); +} + +/** + * @brief Returns the current value of the masksecU1ac0TxTrigger field in the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be read and the masksecU1ac0TxTrigger field's value will be returned. + * + * @return The current value of the masksecU1ac0TxTrigger field in the SEC_USERS_TX_INT_EVENT_UN_MASK register. + */ +__INLINE uint8_t nxmac_masksec_u_1ac_0_tx_trigger_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/** + * @brief Sets the masksecU1ac0TxTrigger field of the SEC_USERS_TX_INT_EVENT_UN_MASK register. + * + * The SEC_USERS_TX_INT_EVENT_UN_MASK register will be read, modified to contain the new field value, and written. + * + * @param[in] masksecu1ac0txtrigger - The value to set the field to. + */ +__INLINE void nxmac_masksec_u_1ac_0_tx_trigger_setf(uint8_t masksecu1ac0txtrigger) +{ + ASSERT_ERR((((uint32_t)masksecu1ac0txtrigger << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR, (REG_PL_RD(NXMAC_SEC_USERS_TX_INT_EVENT_UN_MASK_ADDR) & ~((uint32_t)0x00000001)) | ((uint32_t)masksecu1ac0txtrigger << 0)); +} + +#endif // RW_MUMIMO_TX_EN +/// @} + +/** + * @name DEBUG_BCN_S_PTR register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00     bcnStatusPointer   0x0
+ * 
+ * + * @{ + */ + +/// Address of the DEBUG_BCN_S_PTR register +#define NXMAC_DEBUG_BCN_S_PTR_ADDR 0xC0008524 +/// Offset of the DEBUG_BCN_S_PTR register from the base address +#define NXMAC_DEBUG_BCN_S_PTR_OFFSET 0x00000524 +/// Index of the DEBUG_BCN_S_PTR register +#define NXMAC_DEBUG_BCN_S_PTR_INDEX 0x00000149 +/// Reset value of the DEBUG_BCN_S_PTR register +#define NXMAC_DEBUG_BCN_S_PTR_RESET 0x00000000 + +/** + * @brief Returns the current value of the DEBUG_BCN_S_PTR register. + * The DEBUG_BCN_S_PTR register will be read and its value returned. + * @return The current value of the DEBUG_BCN_S_PTR register. + */ +__INLINE uint32_t nxmac_debug_bcn_s_ptr_get(void) +{ + return REG_PL_RD(NXMAC_DEBUG_BCN_S_PTR_ADDR); +} + +// field definitions +/// BCN_STATUS_POINTER field mask +#define NXMAC_BCN_STATUS_POINTER_MASK ((uint32_t)0xFFFFFFFF) +/// BCN_STATUS_POINTER field LSB position +#define NXMAC_BCN_STATUS_POINTER_LSB 0 +/// BCN_STATUS_POINTER field width +#define NXMAC_BCN_STATUS_POINTER_WIDTH ((uint32_t)0x00000020) + +/// BCN_STATUS_POINTER field reset value +#define NXMAC_BCN_STATUS_POINTER_RST 0x0 + +/** + * @brief Returns the current value of the bcnStatusPointer field in the DEBUG_BCN_S_PTR register. + * + * The DEBUG_BCN_S_PTR register will be read and the bcnStatusPointer field's value will be returned. + * + * @return The current value of the bcnStatusPointer field in the DEBUG_BCN_S_PTR register. + */ +__INLINE uint32_t nxmac_bcn_status_pointer_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DEBUG_BCN_S_PTR_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/// @} + +/** + * @name DEBUG_AC_0S_PTR register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00     ac0StatusPointer   0x0
+ * 
+ * + * @{ + */ + +/// Address of the DEBUG_AC_0S_PTR register +#define NXMAC_DEBUG_AC_0S_PTR_ADDR 0xC0008528 +/// Offset of the DEBUG_AC_0S_PTR register from the base address +#define NXMAC_DEBUG_AC_0S_PTR_OFFSET 0x00000528 +/// Index of the DEBUG_AC_0S_PTR register +#define NXMAC_DEBUG_AC_0S_PTR_INDEX 0x0000014A +/// Reset value of the DEBUG_AC_0S_PTR register +#define NXMAC_DEBUG_AC_0S_PTR_RESET 0x00000000 + +/** + * @brief Returns the current value of the DEBUG_AC_0S_PTR register. + * The DEBUG_AC_0S_PTR register will be read and its value returned. + * @return The current value of the DEBUG_AC_0S_PTR register. + */ +__INLINE uint32_t nxmac_debug_ac_0s_ptr_get(void) +{ + return REG_PL_RD(NXMAC_DEBUG_AC_0S_PTR_ADDR); +} + +// field definitions +/// AC_0_STATUS_POINTER field mask +#define NXMAC_AC_0_STATUS_POINTER_MASK ((uint32_t)0xFFFFFFFF) +/// AC_0_STATUS_POINTER field LSB position +#define NXMAC_AC_0_STATUS_POINTER_LSB 0 +/// AC_0_STATUS_POINTER field width +#define NXMAC_AC_0_STATUS_POINTER_WIDTH ((uint32_t)0x00000020) + +/// AC_0_STATUS_POINTER field reset value +#define NXMAC_AC_0_STATUS_POINTER_RST 0x0 + +/** + * @brief Returns the current value of the ac0StatusPointer field in the DEBUG_AC_0S_PTR register. + * + * The DEBUG_AC_0S_PTR register will be read and the ac0StatusPointer field's value will be returned. + * + * @return The current value of the ac0StatusPointer field in the DEBUG_AC_0S_PTR register. + */ +__INLINE uint32_t nxmac_ac_0_status_pointer_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DEBUG_AC_0S_PTR_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/// @} + +/** + * @name DEBUG_AC_1S_PTR register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00     ac1StatusPointer   0x0
+ * 
+ * + * @{ + */ + +/// Address of the DEBUG_AC_1S_PTR register +#define NXMAC_DEBUG_AC_1S_PTR_ADDR 0xC000852C +/// Offset of the DEBUG_AC_1S_PTR register from the base address +#define NXMAC_DEBUG_AC_1S_PTR_OFFSET 0x0000052C +/// Index of the DEBUG_AC_1S_PTR register +#define NXMAC_DEBUG_AC_1S_PTR_INDEX 0x0000014B +/// Reset value of the DEBUG_AC_1S_PTR register +#define NXMAC_DEBUG_AC_1S_PTR_RESET 0x00000000 + +/** + * @brief Returns the current value of the DEBUG_AC_1S_PTR register. + * The DEBUG_AC_1S_PTR register will be read and its value returned. + * @return The current value of the DEBUG_AC_1S_PTR register. + */ +__INLINE uint32_t nxmac_debug_ac_1s_ptr_get(void) +{ + return REG_PL_RD(NXMAC_DEBUG_AC_1S_PTR_ADDR); +} + +// field definitions +/// AC_1_STATUS_POINTER field mask +#define NXMAC_AC_1_STATUS_POINTER_MASK ((uint32_t)0xFFFFFFFF) +/// AC_1_STATUS_POINTER field LSB position +#define NXMAC_AC_1_STATUS_POINTER_LSB 0 +/// AC_1_STATUS_POINTER field width +#define NXMAC_AC_1_STATUS_POINTER_WIDTH ((uint32_t)0x00000020) + +/// AC_1_STATUS_POINTER field reset value +#define NXMAC_AC_1_STATUS_POINTER_RST 0x0 + +/** + * @brief Returns the current value of the ac1StatusPointer field in the DEBUG_AC_1S_PTR register. + * + * The DEBUG_AC_1S_PTR register will be read and the ac1StatusPointer field's value will be returned. + * + * @return The current value of the ac1StatusPointer field in the DEBUG_AC_1S_PTR register. + */ +__INLINE uint32_t nxmac_ac_1_status_pointer_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DEBUG_AC_1S_PTR_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/// @} + +/** + * @name DEBUG_AC_2S_PTR register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00     ac2StatusPointer   0x0
+ * 
+ * + * @{ + */ + +/// Address of the DEBUG_AC_2S_PTR register +#define NXMAC_DEBUG_AC_2S_PTR_ADDR 0xC0008530 +/// Offset of the DEBUG_AC_2S_PTR register from the base address +#define NXMAC_DEBUG_AC_2S_PTR_OFFSET 0x00000530 +/// Index of the DEBUG_AC_2S_PTR register +#define NXMAC_DEBUG_AC_2S_PTR_INDEX 0x0000014C +/// Reset value of the DEBUG_AC_2S_PTR register +#define NXMAC_DEBUG_AC_2S_PTR_RESET 0x00000000 + +/** + * @brief Returns the current value of the DEBUG_AC_2S_PTR register. + * The DEBUG_AC_2S_PTR register will be read and its value returned. + * @return The current value of the DEBUG_AC_2S_PTR register. + */ +__INLINE uint32_t nxmac_debug_ac_2s_ptr_get(void) +{ + return REG_PL_RD(NXMAC_DEBUG_AC_2S_PTR_ADDR); +} + +// field definitions +/// AC_2_STATUS_POINTER field mask +#define NXMAC_AC_2_STATUS_POINTER_MASK ((uint32_t)0xFFFFFFFF) +/// AC_2_STATUS_POINTER field LSB position +#define NXMAC_AC_2_STATUS_POINTER_LSB 0 +/// AC_2_STATUS_POINTER field width +#define NXMAC_AC_2_STATUS_POINTER_WIDTH ((uint32_t)0x00000020) + +/// AC_2_STATUS_POINTER field reset value +#define NXMAC_AC_2_STATUS_POINTER_RST 0x0 + +/** + * @brief Returns the current value of the ac2StatusPointer field in the DEBUG_AC_2S_PTR register. + * + * The DEBUG_AC_2S_PTR register will be read and the ac2StatusPointer field's value will be returned. + * + * @return The current value of the ac2StatusPointer field in the DEBUG_AC_2S_PTR register. + */ +__INLINE uint32_t nxmac_ac_2_status_pointer_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DEBUG_AC_2S_PTR_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/// @} + +/** + * @name DEBUG_AC_3S_PTR register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00     ac3StatusPointer   0x0
+ * 
+ * + * @{ + */ + +/// Address of the DEBUG_AC_3S_PTR register +#define NXMAC_DEBUG_AC_3S_PTR_ADDR 0xC0008534 +/// Offset of the DEBUG_AC_3S_PTR register from the base address +#define NXMAC_DEBUG_AC_3S_PTR_OFFSET 0x00000534 +/// Index of the DEBUG_AC_3S_PTR register +#define NXMAC_DEBUG_AC_3S_PTR_INDEX 0x0000014D +/// Reset value of the DEBUG_AC_3S_PTR register +#define NXMAC_DEBUG_AC_3S_PTR_RESET 0x00000000 + +/** + * @brief Returns the current value of the DEBUG_AC_3S_PTR register. + * The DEBUG_AC_3S_PTR register will be read and its value returned. + * @return The current value of the DEBUG_AC_3S_PTR register. + */ +__INLINE uint32_t nxmac_debug_ac_3s_ptr_get(void) +{ + return REG_PL_RD(NXMAC_DEBUG_AC_3S_PTR_ADDR); +} + +// field definitions +/// AC_3_STATUS_POINTER field mask +#define NXMAC_AC_3_STATUS_POINTER_MASK ((uint32_t)0xFFFFFFFF) +/// AC_3_STATUS_POINTER field LSB position +#define NXMAC_AC_3_STATUS_POINTER_LSB 0 +/// AC_3_STATUS_POINTER field width +#define NXMAC_AC_3_STATUS_POINTER_WIDTH ((uint32_t)0x00000020) + +/// AC_3_STATUS_POINTER field reset value +#define NXMAC_AC_3_STATUS_POINTER_RST 0x0 + +/** + * @brief Returns the current value of the ac3StatusPointer field in the DEBUG_AC_3S_PTR register. + * + * The DEBUG_AC_3S_PTR register will be read and the ac3StatusPointer field's value will be returned. + * + * @return The current value of the ac3StatusPointer field in the DEBUG_AC_3S_PTR register. + */ +__INLINE uint32_t nxmac_ac_3_status_pointer_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DEBUG_AC_3S_PTR_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/// @} + +/** + * @name DEBUG_TX_C_PTR register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00     txCurrentPointer   0x0
+ * 
+ * + * @{ + */ + +/// Address of the DEBUG_TX_C_PTR register +#define NXMAC_DEBUG_TX_C_PTR_ADDR 0xC0008540 +/// Offset of the DEBUG_TX_C_PTR register from the base address +#define NXMAC_DEBUG_TX_C_PTR_OFFSET 0x00000540 +/// Index of the DEBUG_TX_C_PTR register +#define NXMAC_DEBUG_TX_C_PTR_INDEX 0x00000150 +/// Reset value of the DEBUG_TX_C_PTR register +#define NXMAC_DEBUG_TX_C_PTR_RESET 0x00000000 + +/** + * @brief Returns the current value of the DEBUG_TX_C_PTR register. + * The DEBUG_TX_C_PTR register will be read and its value returned. + * @return The current value of the DEBUG_TX_C_PTR register. + */ +__INLINE uint32_t nxmac_debug_tx_c_ptr_get(void) +{ + return REG_PL_RD(NXMAC_DEBUG_TX_C_PTR_ADDR); +} + +// field definitions +/// TX_CURRENT_POINTER field mask +#define NXMAC_TX_CURRENT_POINTER_MASK ((uint32_t)0xFFFFFFFF) +/// TX_CURRENT_POINTER field LSB position +#define NXMAC_TX_CURRENT_POINTER_LSB 0 +/// TX_CURRENT_POINTER field width +#define NXMAC_TX_CURRENT_POINTER_WIDTH ((uint32_t)0x00000020) + +/// TX_CURRENT_POINTER field reset value +#define NXMAC_TX_CURRENT_POINTER_RST 0x0 + +/** + * @brief Returns the current value of the txCurrentPointer field in the DEBUG_TX_C_PTR register. + * + * The DEBUG_TX_C_PTR register will be read and the txCurrentPointer field's value will be returned. + * + * @return The current value of the txCurrentPointer field in the DEBUG_TX_C_PTR register. + */ +__INLINE uint32_t nxmac_tx_current_pointer_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DEBUG_TX_C_PTR_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/// @} + +/** + * @name DEBUG_RX_PAY_S_PTR register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00     rxPayStatPointer   0x0
+ * 
+ * + * @{ + */ + +/// Address of the DEBUG_RX_PAY_S_PTR register +#define NXMAC_DEBUG_RX_PAY_S_PTR_ADDR 0xC0008544 +/// Offset of the DEBUG_RX_PAY_S_PTR register from the base address +#define NXMAC_DEBUG_RX_PAY_S_PTR_OFFSET 0x00000544 +/// Index of the DEBUG_RX_PAY_S_PTR register +#define NXMAC_DEBUG_RX_PAY_S_PTR_INDEX 0x00000151 +/// Reset value of the DEBUG_RX_PAY_S_PTR register +#define NXMAC_DEBUG_RX_PAY_S_PTR_RESET 0x00000000 + +/** + * @brief Returns the current value of the DEBUG_RX_PAY_S_PTR register. + * The DEBUG_RX_PAY_S_PTR register will be read and its value returned. + * @return The current value of the DEBUG_RX_PAY_S_PTR register. + */ +__INLINE uint32_t nxmac_debug_rx_pay_s_ptr_get(void) +{ + return REG_PL_RD(NXMAC_DEBUG_RX_PAY_S_PTR_ADDR); +} + +// field definitions +/// RX_PAY_STAT_POINTER field mask +#define NXMAC_RX_PAY_STAT_POINTER_MASK ((uint32_t)0xFFFFFFFF) +/// RX_PAY_STAT_POINTER field LSB position +#define NXMAC_RX_PAY_STAT_POINTER_LSB 0 +/// RX_PAY_STAT_POINTER field width +#define NXMAC_RX_PAY_STAT_POINTER_WIDTH ((uint32_t)0x00000020) + +/// RX_PAY_STAT_POINTER field reset value +#define NXMAC_RX_PAY_STAT_POINTER_RST 0x0 + +/** + * @brief Returns the current value of the rxPayStatPointer field in the DEBUG_RX_PAY_S_PTR register. + * + * The DEBUG_RX_PAY_S_PTR register will be read and the rxPayStatPointer field's value will be returned. + * + * @return The current value of the rxPayStatPointer field in the DEBUG_RX_PAY_S_PTR register. + */ +__INLINE uint32_t nxmac_rx_pay_stat_pointer_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DEBUG_RX_PAY_S_PTR_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/// @} + +/** + * @name DEBUG_RX_HDR_C_PTR register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00     rxHdrStatPointer   0x0
+ * 
+ * + * @{ + */ + +/// Address of the DEBUG_RX_HDR_C_PTR register +#define NXMAC_DEBUG_RX_HDR_C_PTR_ADDR 0xC0008548 +/// Offset of the DEBUG_RX_HDR_C_PTR register from the base address +#define NXMAC_DEBUG_RX_HDR_C_PTR_OFFSET 0x00000548 +/// Index of the DEBUG_RX_HDR_C_PTR register +#define NXMAC_DEBUG_RX_HDR_C_PTR_INDEX 0x00000152 +/// Reset value of the DEBUG_RX_HDR_C_PTR register +#define NXMAC_DEBUG_RX_HDR_C_PTR_RESET 0x00000000 + +/** + * @brief Returns the current value of the DEBUG_RX_HDR_C_PTR register. + * The DEBUG_RX_HDR_C_PTR register will be read and its value returned. + * @return The current value of the DEBUG_RX_HDR_C_PTR register. + */ +__INLINE uint32_t nxmac_debug_rx_hdr_c_ptr_get(void) +{ + return REG_PL_RD(NXMAC_DEBUG_RX_HDR_C_PTR_ADDR); +} + +// field definitions +/// RX_HDR_STAT_POINTER field mask +#define NXMAC_RX_HDR_STAT_POINTER_MASK ((uint32_t)0xFFFFFFFF) +/// RX_HDR_STAT_POINTER field LSB position +#define NXMAC_RX_HDR_STAT_POINTER_LSB 0 +/// RX_HDR_STAT_POINTER field width +#define NXMAC_RX_HDR_STAT_POINTER_WIDTH ((uint32_t)0x00000020) + +/// RX_HDR_STAT_POINTER field reset value +#define NXMAC_RX_HDR_STAT_POINTER_RST 0x0 + +/** + * @brief Returns the current value of the rxHdrStatPointer field in the DEBUG_RX_HDR_C_PTR register. + * + * The DEBUG_RX_HDR_C_PTR register will be read and the rxHdrStatPointer field's value will be returned. + * + * @return The current value of the rxHdrStatPointer field in the DEBUG_RX_HDR_C_PTR register. + */ +__INLINE uint32_t nxmac_rx_hdr_stat_pointer_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DEBUG_RX_HDR_C_PTR_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/// @} + +/** + * @name DEBUG_RX_PAY_C_PTR register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00   rxPayCurrentPointer   0x0
+ * 
+ * + * @{ + */ + +/// Address of the DEBUG_RX_PAY_C_PTR register +#define NXMAC_DEBUG_RX_PAY_C_PTR_ADDR 0xC000854C +/// Offset of the DEBUG_RX_PAY_C_PTR register from the base address +#define NXMAC_DEBUG_RX_PAY_C_PTR_OFFSET 0x0000054C +/// Index of the DEBUG_RX_PAY_C_PTR register +#define NXMAC_DEBUG_RX_PAY_C_PTR_INDEX 0x00000153 +/// Reset value of the DEBUG_RX_PAY_C_PTR register +#define NXMAC_DEBUG_RX_PAY_C_PTR_RESET 0x00000000 + +/** + * @brief Returns the current value of the DEBUG_RX_PAY_C_PTR register. + * The DEBUG_RX_PAY_C_PTR register will be read and its value returned. + * @return The current value of the DEBUG_RX_PAY_C_PTR register. + */ +__INLINE uint32_t nxmac_debug_rx_pay_c_ptr_get(void) +{ + return REG_PL_RD(NXMAC_DEBUG_RX_PAY_C_PTR_ADDR); +} + +// field definitions +/// RX_PAY_CURRENT_POINTER field mask +#define NXMAC_RX_PAY_CURRENT_POINTER_MASK ((uint32_t)0xFFFFFFFF) +/// RX_PAY_CURRENT_POINTER field LSB position +#define NXMAC_RX_PAY_CURRENT_POINTER_LSB 0 +/// RX_PAY_CURRENT_POINTER field width +#define NXMAC_RX_PAY_CURRENT_POINTER_WIDTH ((uint32_t)0x00000020) + +/// RX_PAY_CURRENT_POINTER field reset value +#define NXMAC_RX_PAY_CURRENT_POINTER_RST 0x0 + +/** + * @brief Returns the current value of the rxPayCurrentPointer field in the DEBUG_RX_PAY_C_PTR register. + * + * The DEBUG_RX_PAY_C_PTR register will be read and the rxPayCurrentPointer field's value will be returned. + * + * @return The current value of the rxPayCurrentPointer field in the DEBUG_RX_PAY_C_PTR register. + */ +__INLINE uint32_t nxmac_rx_pay_current_pointer_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DEBUG_RX_PAY_C_PTR_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/// @} + +/** + * @name SW_PROFILING register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31             swProf31   0
+ *     30             swProf30   0
+ *     29             swProf29   0
+ *     28             swProf28   0
+ *     27             swProf27   0
+ *     26             swProf26   0
+ *     25             swProf25   0
+ *     24             swProf24   0
+ *     23             swProf23   0
+ *     22             swProf22   0
+ *     21             swProf21   0
+ *     20             swProf20   0
+ *     19             swProf19   0
+ *     18             swProf18   0
+ *     17             swProf17   0
+ *     16             swProf16   0
+ *     15             swProf15   0
+ *     14             swProf14   0
+ *     13             swProf13   0
+ *     12             swProf12   0
+ *     11             swProf11   0
+ *     10             swProf10   0
+ *     09              swProf9   0
+ *     08              swProf8   0
+ *     07              swProf7   0
+ *     06              swProf6   0
+ *     05              swProf5   0
+ *     04              swProf4   0
+ *     03              swProf3   0
+ *     02              swProf2   0
+ *     01              swProf1   0
+ *     00              swProf0   0
+ * 
+ * + * @{ + */ + +/// Address of the SW_PROFILING register +#define NXMAC_SW_PROFILING_ADDR 0xC0008560 +/// Offset of the SW_PROFILING register from the base address +#define NXMAC_SW_PROFILING_OFFSET 0x00000560 +/// Index of the SW_PROFILING register +#define NXMAC_SW_PROFILING_INDEX 0x00000158 +/// Reset value of the SW_PROFILING register +#define NXMAC_SW_PROFILING_RESET 0x00000000 + +/** + * @brief Returns the current value of the SW_PROFILING register. + * The SW_PROFILING register will be read and its value returned. + * @return The current value of the SW_PROFILING register. + */ +__INLINE uint32_t nxmac_sw_profiling_get(void) +{ + return REG_PL_RD(NXMAC_SW_PROFILING_ADDR); +} + +/** + * @brief Sets the SW_PROFILING register to a value. + * The SW_PROFILING register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_sw_profiling_set(uint32_t value) +{ + REG_PL_WR(NXMAC_SW_PROFILING_ADDR, value); +} + +// field definitions +/// SW_PROF_31 field bit +#define NXMAC_SW_PROF_31_BIT ((uint32_t)0x80000000) +/// SW_PROF_31 field position +#define NXMAC_SW_PROF_31_POS 31 +/// SW_PROF_30 field bit +#define NXMAC_SW_PROF_30_BIT ((uint32_t)0x40000000) +/// SW_PROF_30 field position +#define NXMAC_SW_PROF_30_POS 30 +/// SW_PROF_29 field bit +#define NXMAC_SW_PROF_29_BIT ((uint32_t)0x20000000) +/// SW_PROF_29 field position +#define NXMAC_SW_PROF_29_POS 29 +/// SW_PROF_28 field bit +#define NXMAC_SW_PROF_28_BIT ((uint32_t)0x10000000) +/// SW_PROF_28 field position +#define NXMAC_SW_PROF_28_POS 28 +/// SW_PROF_27 field bit +#define NXMAC_SW_PROF_27_BIT ((uint32_t)0x08000000) +/// SW_PROF_27 field position +#define NXMAC_SW_PROF_27_POS 27 +/// SW_PROF_26 field bit +#define NXMAC_SW_PROF_26_BIT ((uint32_t)0x04000000) +/// SW_PROF_26 field position +#define NXMAC_SW_PROF_26_POS 26 +/// SW_PROF_25 field bit +#define NXMAC_SW_PROF_25_BIT ((uint32_t)0x02000000) +/// SW_PROF_25 field position +#define NXMAC_SW_PROF_25_POS 25 +/// SW_PROF_24 field bit +#define NXMAC_SW_PROF_24_BIT ((uint32_t)0x01000000) +/// SW_PROF_24 field position +#define NXMAC_SW_PROF_24_POS 24 +/// SW_PROF_23 field bit +#define NXMAC_SW_PROF_23_BIT ((uint32_t)0x00800000) +/// SW_PROF_23 field position +#define NXMAC_SW_PROF_23_POS 23 +/// SW_PROF_22 field bit +#define NXMAC_SW_PROF_22_BIT ((uint32_t)0x00400000) +/// SW_PROF_22 field position +#define NXMAC_SW_PROF_22_POS 22 +/// SW_PROF_21 field bit +#define NXMAC_SW_PROF_21_BIT ((uint32_t)0x00200000) +/// SW_PROF_21 field position +#define NXMAC_SW_PROF_21_POS 21 +/// SW_PROF_20 field bit +#define NXMAC_SW_PROF_20_BIT ((uint32_t)0x00100000) +/// SW_PROF_20 field position +#define NXMAC_SW_PROF_20_POS 20 +/// SW_PROF_19 field bit +#define NXMAC_SW_PROF_19_BIT ((uint32_t)0x00080000) +/// SW_PROF_19 field position +#define NXMAC_SW_PROF_19_POS 19 +/// SW_PROF_18 field bit +#define NXMAC_SW_PROF_18_BIT ((uint32_t)0x00040000) +/// SW_PROF_18 field position +#define NXMAC_SW_PROF_18_POS 18 +/// SW_PROF_17 field bit +#define NXMAC_SW_PROF_17_BIT ((uint32_t)0x00020000) +/// SW_PROF_17 field position +#define NXMAC_SW_PROF_17_POS 17 +/// SW_PROF_16 field bit +#define NXMAC_SW_PROF_16_BIT ((uint32_t)0x00010000) +/// SW_PROF_16 field position +#define NXMAC_SW_PROF_16_POS 16 +/// SW_PROF_15 field bit +#define NXMAC_SW_PROF_15_BIT ((uint32_t)0x00008000) +/// SW_PROF_15 field position +#define NXMAC_SW_PROF_15_POS 15 +/// SW_PROF_14 field bit +#define NXMAC_SW_PROF_14_BIT ((uint32_t)0x00004000) +/// SW_PROF_14 field position +#define NXMAC_SW_PROF_14_POS 14 +/// SW_PROF_13 field bit +#define NXMAC_SW_PROF_13_BIT ((uint32_t)0x00002000) +/// SW_PROF_13 field position +#define NXMAC_SW_PROF_13_POS 13 +/// SW_PROF_12 field bit +#define NXMAC_SW_PROF_12_BIT ((uint32_t)0x00001000) +/// SW_PROF_12 field position +#define NXMAC_SW_PROF_12_POS 12 +/// SW_PROF_11 field bit +#define NXMAC_SW_PROF_11_BIT ((uint32_t)0x00000800) +/// SW_PROF_11 field position +#define NXMAC_SW_PROF_11_POS 11 +/// SW_PROF_10 field bit +#define NXMAC_SW_PROF_10_BIT ((uint32_t)0x00000400) +/// SW_PROF_10 field position +#define NXMAC_SW_PROF_10_POS 10 +/// SW_PROF_9 field bit +#define NXMAC_SW_PROF_9_BIT ((uint32_t)0x00000200) +/// SW_PROF_9 field position +#define NXMAC_SW_PROF_9_POS 9 +/// SW_PROF_8 field bit +#define NXMAC_SW_PROF_8_BIT ((uint32_t)0x00000100) +/// SW_PROF_8 field position +#define NXMAC_SW_PROF_8_POS 8 +/// SW_PROF_7 field bit +#define NXMAC_SW_PROF_7_BIT ((uint32_t)0x00000080) +/// SW_PROF_7 field position +#define NXMAC_SW_PROF_7_POS 7 +/// SW_PROF_6 field bit +#define NXMAC_SW_PROF_6_BIT ((uint32_t)0x00000040) +/// SW_PROF_6 field position +#define NXMAC_SW_PROF_6_POS 6 +/// SW_PROF_5 field bit +#define NXMAC_SW_PROF_5_BIT ((uint32_t)0x00000020) +/// SW_PROF_5 field position +#define NXMAC_SW_PROF_5_POS 5 +/// SW_PROF_4 field bit +#define NXMAC_SW_PROF_4_BIT ((uint32_t)0x00000010) +/// SW_PROF_4 field position +#define NXMAC_SW_PROF_4_POS 4 +/// SW_PROF_3 field bit +#define NXMAC_SW_PROF_3_BIT ((uint32_t)0x00000008) +/// SW_PROF_3 field position +#define NXMAC_SW_PROF_3_POS 3 +/// SW_PROF_2 field bit +#define NXMAC_SW_PROF_2_BIT ((uint32_t)0x00000004) +/// SW_PROF_2 field position +#define NXMAC_SW_PROF_2_POS 2 +/// SW_PROF_1 field bit +#define NXMAC_SW_PROF_1_BIT ((uint32_t)0x00000002) +/// SW_PROF_1 field position +#define NXMAC_SW_PROF_1_POS 1 +/// SW_PROF_0 field bit +#define NXMAC_SW_PROF_0_BIT ((uint32_t)0x00000001) +/// SW_PROF_0 field position +#define NXMAC_SW_PROF_0_POS 0 + +/// SW_PROF_31 field reset value +#define NXMAC_SW_PROF_31_RST 0x0 +/// SW_PROF_30 field reset value +#define NXMAC_SW_PROF_30_RST 0x0 +/// SW_PROF_29 field reset value +#define NXMAC_SW_PROF_29_RST 0x0 +/// SW_PROF_28 field reset value +#define NXMAC_SW_PROF_28_RST 0x0 +/// SW_PROF_27 field reset value +#define NXMAC_SW_PROF_27_RST 0x0 +/// SW_PROF_26 field reset value +#define NXMAC_SW_PROF_26_RST 0x0 +/// SW_PROF_25 field reset value +#define NXMAC_SW_PROF_25_RST 0x0 +/// SW_PROF_24 field reset value +#define NXMAC_SW_PROF_24_RST 0x0 +/// SW_PROF_23 field reset value +#define NXMAC_SW_PROF_23_RST 0x0 +/// SW_PROF_22 field reset value +#define NXMAC_SW_PROF_22_RST 0x0 +/// SW_PROF_21 field reset value +#define NXMAC_SW_PROF_21_RST 0x0 +/// SW_PROF_20 field reset value +#define NXMAC_SW_PROF_20_RST 0x0 +/// SW_PROF_19 field reset value +#define NXMAC_SW_PROF_19_RST 0x0 +/// SW_PROF_18 field reset value +#define NXMAC_SW_PROF_18_RST 0x0 +/// SW_PROF_17 field reset value +#define NXMAC_SW_PROF_17_RST 0x0 +/// SW_PROF_16 field reset value +#define NXMAC_SW_PROF_16_RST 0x0 +/// SW_PROF_15 field reset value +#define NXMAC_SW_PROF_15_RST 0x0 +/// SW_PROF_14 field reset value +#define NXMAC_SW_PROF_14_RST 0x0 +/// SW_PROF_13 field reset value +#define NXMAC_SW_PROF_13_RST 0x0 +/// SW_PROF_12 field reset value +#define NXMAC_SW_PROF_12_RST 0x0 +/// SW_PROF_11 field reset value +#define NXMAC_SW_PROF_11_RST 0x0 +/// SW_PROF_10 field reset value +#define NXMAC_SW_PROF_10_RST 0x0 +/// SW_PROF_9 field reset value +#define NXMAC_SW_PROF_9_RST 0x0 +/// SW_PROF_8 field reset value +#define NXMAC_SW_PROF_8_RST 0x0 +/// SW_PROF_7 field reset value +#define NXMAC_SW_PROF_7_RST 0x0 +/// SW_PROF_6 field reset value +#define NXMAC_SW_PROF_6_RST 0x0 +/// SW_PROF_5 field reset value +#define NXMAC_SW_PROF_5_RST 0x0 +/// SW_PROF_4 field reset value +#define NXMAC_SW_PROF_4_RST 0x0 +/// SW_PROF_3 field reset value +#define NXMAC_SW_PROF_3_RST 0x0 +/// SW_PROF_2 field reset value +#define NXMAC_SW_PROF_2_RST 0x0 +/// SW_PROF_1 field reset value +#define NXMAC_SW_PROF_1_RST 0x0 +/// SW_PROF_0 field reset value +#define NXMAC_SW_PROF_0_RST 0x0 + +/** + * @brief Constructs a value for the SW_PROFILING register given values for its fields + * and writes the value to the register. + * + * @param[in] swprof31 - The value to use for the swProf31 field. + * @param[in] swprof30 - The value to use for the swProf30 field. + * @param[in] swprof29 - The value to use for the swProf29 field. + * @param[in] swprof28 - The value to use for the swProf28 field. + * @param[in] swprof27 - The value to use for the swProf27 field. + * @param[in] swprof26 - The value to use for the swProf26 field. + * @param[in] swprof25 - The value to use for the swProf25 field. + * @param[in] swprof24 - The value to use for the swProf24 field. + * @param[in] swprof23 - The value to use for the swProf23 field. + * @param[in] swprof22 - The value to use for the swProf22 field. + * @param[in] swprof21 - The value to use for the swProf21 field. + * @param[in] swprof20 - The value to use for the swProf20 field. + * @param[in] swprof19 - The value to use for the swProf19 field. + * @param[in] swprof18 - The value to use for the swProf18 field. + * @param[in] swprof17 - The value to use for the swProf17 field. + * @param[in] swprof16 - The value to use for the swProf16 field. + * @param[in] swprof15 - The value to use for the swProf15 field. + * @param[in] swprof14 - The value to use for the swProf14 field. + * @param[in] swprof13 - The value to use for the swProf13 field. + * @param[in] swprof12 - The value to use for the swProf12 field. + * @param[in] swprof11 - The value to use for the swProf11 field. + * @param[in] swprof10 - The value to use for the swProf10 field. + * @param[in] swprof9 - The value to use for the swProf9 field. + * @param[in] swprof8 - The value to use for the swProf8 field. + * @param[in] swprof7 - The value to use for the swProf7 field. + * @param[in] swprof6 - The value to use for the swProf6 field. + * @param[in] swprof5 - The value to use for the swProf5 field. + * @param[in] swprof4 - The value to use for the swProf4 field. + * @param[in] swprof3 - The value to use for the swProf3 field. + * @param[in] swprof2 - The value to use for the swProf2 field. + * @param[in] swprof1 - The value to use for the swProf1 field. + * @param[in] swprof0 - The value to use for the swProf0 field. + */ +__INLINE void nxmac_sw_profiling_pack(uint8_t swprof31, uint8_t swprof30, uint8_t swprof29, uint8_t swprof28, uint8_t swprof27, uint8_t swprof26, uint8_t swprof25, uint8_t swprof24, uint8_t swprof23, uint8_t swprof22, uint8_t swprof21, uint8_t swprof20, uint8_t swprof19, uint8_t swprof18, uint8_t swprof17, uint8_t swprof16, uint8_t swprof15, uint8_t swprof14, uint8_t swprof13, uint8_t swprof12, uint8_t swprof11, uint8_t swprof10, uint8_t swprof9, uint8_t swprof8, uint8_t swprof7, uint8_t swprof6, uint8_t swprof5, uint8_t swprof4, uint8_t swprof3, uint8_t swprof2, uint8_t swprof1, uint8_t swprof0) +{ + ASSERT_ERR((((uint32_t)swprof31 << 31) & ~((uint32_t)0x80000000)) == 0); + ASSERT_ERR((((uint32_t)swprof30 << 30) & ~((uint32_t)0x40000000)) == 0); + ASSERT_ERR((((uint32_t)swprof29 << 29) & ~((uint32_t)0x20000000)) == 0); + ASSERT_ERR((((uint32_t)swprof28 << 28) & ~((uint32_t)0x10000000)) == 0); + ASSERT_ERR((((uint32_t)swprof27 << 27) & ~((uint32_t)0x08000000)) == 0); + ASSERT_ERR((((uint32_t)swprof26 << 26) & ~((uint32_t)0x04000000)) == 0); + ASSERT_ERR((((uint32_t)swprof25 << 25) & ~((uint32_t)0x02000000)) == 0); + ASSERT_ERR((((uint32_t)swprof24 << 24) & ~((uint32_t)0x01000000)) == 0); + ASSERT_ERR((((uint32_t)swprof23 << 23) & ~((uint32_t)0x00800000)) == 0); + ASSERT_ERR((((uint32_t)swprof22 << 22) & ~((uint32_t)0x00400000)) == 0); + ASSERT_ERR((((uint32_t)swprof21 << 21) & ~((uint32_t)0x00200000)) == 0); + ASSERT_ERR((((uint32_t)swprof20 << 20) & ~((uint32_t)0x00100000)) == 0); + ASSERT_ERR((((uint32_t)swprof19 << 19) & ~((uint32_t)0x00080000)) == 0); + ASSERT_ERR((((uint32_t)swprof18 << 18) & ~((uint32_t)0x00040000)) == 0); + ASSERT_ERR((((uint32_t)swprof17 << 17) & ~((uint32_t)0x00020000)) == 0); + ASSERT_ERR((((uint32_t)swprof16 << 16) & ~((uint32_t)0x00010000)) == 0); + ASSERT_ERR((((uint32_t)swprof15 << 15) & ~((uint32_t)0x00008000)) == 0); + ASSERT_ERR((((uint32_t)swprof14 << 14) & ~((uint32_t)0x00004000)) == 0); + ASSERT_ERR((((uint32_t)swprof13 << 13) & ~((uint32_t)0x00002000)) == 0); + ASSERT_ERR((((uint32_t)swprof12 << 12) & ~((uint32_t)0x00001000)) == 0); + ASSERT_ERR((((uint32_t)swprof11 << 11) & ~((uint32_t)0x00000800)) == 0); + ASSERT_ERR((((uint32_t)swprof10 << 10) & ~((uint32_t)0x00000400)) == 0); + ASSERT_ERR((((uint32_t)swprof9 << 9) & ~((uint32_t)0x00000200)) == 0); + ASSERT_ERR((((uint32_t)swprof8 << 8) & ~((uint32_t)0x00000100)) == 0); + ASSERT_ERR((((uint32_t)swprof7 << 7) & ~((uint32_t)0x00000080)) == 0); + ASSERT_ERR((((uint32_t)swprof6 << 6) & ~((uint32_t)0x00000040)) == 0); + ASSERT_ERR((((uint32_t)swprof5 << 5) & ~((uint32_t)0x00000020)) == 0); + ASSERT_ERR((((uint32_t)swprof4 << 4) & ~((uint32_t)0x00000010)) == 0); + ASSERT_ERR((((uint32_t)swprof3 << 3) & ~((uint32_t)0x00000008)) == 0); + ASSERT_ERR((((uint32_t)swprof2 << 2) & ~((uint32_t)0x00000004)) == 0); + ASSERT_ERR((((uint32_t)swprof1 << 1) & ~((uint32_t)0x00000002)) == 0); + ASSERT_ERR((((uint32_t)swprof0 << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_SW_PROFILING_ADDR, ((uint32_t)swprof31 << 31) | ((uint32_t)swprof30 << 30) | ((uint32_t)swprof29 << 29) | ((uint32_t)swprof28 << 28) | ((uint32_t)swprof27 << 27) | ((uint32_t)swprof26 << 26) | ((uint32_t)swprof25 << 25) | ((uint32_t)swprof24 << 24) | ((uint32_t)swprof23 << 23) | ((uint32_t)swprof22 << 22) | ((uint32_t)swprof21 << 21) | ((uint32_t)swprof20 << 20) | ((uint32_t)swprof19 << 19) | ((uint32_t)swprof18 << 18) | ((uint32_t)swprof17 << 17) | ((uint32_t)swprof16 << 16) | ((uint32_t)swprof15 << 15) | ((uint32_t)swprof14 << 14) | ((uint32_t)swprof13 << 13) | ((uint32_t)swprof12 << 12) | ((uint32_t)swprof11 << 11) | ((uint32_t)swprof10 << 10) | ((uint32_t)swprof9 << 9) | ((uint32_t)swprof8 << 8) | ((uint32_t)swprof7 << 7) | ((uint32_t)swprof6 << 6) | ((uint32_t)swprof5 << 5) | ((uint32_t)swprof4 << 4) | ((uint32_t)swprof3 << 3) | ((uint32_t)swprof2 << 2) | ((uint32_t)swprof1 << 1) | ((uint32_t)swprof0 << 0)); +} + +/** + * @brief Unpacks SW_PROFILING's fields from current value of the SW_PROFILING register. + * + * Reads the SW_PROFILING register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] swprof31 - Will be populated with the current value of this field from the register. + * @param[out] swprof30 - Will be populated with the current value of this field from the register. + * @param[out] swprof29 - Will be populated with the current value of this field from the register. + * @param[out] swprof28 - Will be populated with the current value of this field from the register. + * @param[out] swprof27 - Will be populated with the current value of this field from the register. + * @param[out] swprof26 - Will be populated with the current value of this field from the register. + * @param[out] swprof25 - Will be populated with the current value of this field from the register. + * @param[out] swprof24 - Will be populated with the current value of this field from the register. + * @param[out] swprof23 - Will be populated with the current value of this field from the register. + * @param[out] swprof22 - Will be populated with the current value of this field from the register. + * @param[out] swprof21 - Will be populated with the current value of this field from the register. + * @param[out] swprof20 - Will be populated with the current value of this field from the register. + * @param[out] swprof19 - Will be populated with the current value of this field from the register. + * @param[out] swprof18 - Will be populated with the current value of this field from the register. + * @param[out] swprof17 - Will be populated with the current value of this field from the register. + * @param[out] swprof16 - Will be populated with the current value of this field from the register. + * @param[out] swprof15 - Will be populated with the current value of this field from the register. + * @param[out] swprof14 - Will be populated with the current value of this field from the register. + * @param[out] swprof13 - Will be populated with the current value of this field from the register. + * @param[out] swprof12 - Will be populated with the current value of this field from the register. + * @param[out] swprof11 - Will be populated with the current value of this field from the register. + * @param[out] swprof10 - Will be populated with the current value of this field from the register. + * @param[out] swprof9 - Will be populated with the current value of this field from the register. + * @param[out] swprof8 - Will be populated with the current value of this field from the register. + * @param[out] swprof7 - Will be populated with the current value of this field from the register. + * @param[out] swprof6 - Will be populated with the current value of this field from the register. + * @param[out] swprof5 - Will be populated with the current value of this field from the register. + * @param[out] swprof4 - Will be populated with the current value of this field from the register. + * @param[out] swprof3 - Will be populated with the current value of this field from the register. + * @param[out] swprof2 - Will be populated with the current value of this field from the register. + * @param[out] swprof1 - Will be populated with the current value of this field from the register. + * @param[out] swprof0 - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_sw_profiling_unpack(uint8_t *swprof31, uint8_t *swprof30, uint8_t *swprof29, uint8_t *swprof28, uint8_t *swprof27, uint8_t *swprof26, uint8_t *swprof25, uint8_t *swprof24, uint8_t *swprof23, uint8_t *swprof22, uint8_t *swprof21, uint8_t *swprof20, uint8_t *swprof19, uint8_t *swprof18, uint8_t *swprof17, uint8_t *swprof16, uint8_t *swprof15, uint8_t *swprof14, uint8_t *swprof13, uint8_t *swprof12, uint8_t *swprof11, uint8_t *swprof10, uint8_t *swprof9, uint8_t *swprof8, uint8_t *swprof7, uint8_t *swprof6, uint8_t *swprof5, uint8_t *swprof4, uint8_t *swprof3, uint8_t *swprof2, uint8_t *swprof1, uint8_t *swprof0) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_PROFILING_ADDR); + + *swprof31 = (localVal & ((uint32_t)0x80000000)) >> 31; + *swprof30 = (localVal & ((uint32_t)0x40000000)) >> 30; + *swprof29 = (localVal & ((uint32_t)0x20000000)) >> 29; + *swprof28 = (localVal & ((uint32_t)0x10000000)) >> 28; + *swprof27 = (localVal & ((uint32_t)0x08000000)) >> 27; + *swprof26 = (localVal & ((uint32_t)0x04000000)) >> 26; + *swprof25 = (localVal & ((uint32_t)0x02000000)) >> 25; + *swprof24 = (localVal & ((uint32_t)0x01000000)) >> 24; + *swprof23 = (localVal & ((uint32_t)0x00800000)) >> 23; + *swprof22 = (localVal & ((uint32_t)0x00400000)) >> 22; + *swprof21 = (localVal & ((uint32_t)0x00200000)) >> 21; + *swprof20 = (localVal & ((uint32_t)0x00100000)) >> 20; + *swprof19 = (localVal & ((uint32_t)0x00080000)) >> 19; + *swprof18 = (localVal & ((uint32_t)0x00040000)) >> 18; + *swprof17 = (localVal & ((uint32_t)0x00020000)) >> 17; + *swprof16 = (localVal & ((uint32_t)0x00010000)) >> 16; + *swprof15 = (localVal & ((uint32_t)0x00008000)) >> 15; + *swprof14 = (localVal & ((uint32_t)0x00004000)) >> 14; + *swprof13 = (localVal & ((uint32_t)0x00002000)) >> 13; + *swprof12 = (localVal & ((uint32_t)0x00001000)) >> 12; + *swprof11 = (localVal & ((uint32_t)0x00000800)) >> 11; + *swprof10 = (localVal & ((uint32_t)0x00000400)) >> 10; + *swprof9 = (localVal & ((uint32_t)0x00000200)) >> 9; + *swprof8 = (localVal & ((uint32_t)0x00000100)) >> 8; + *swprof7 = (localVal & ((uint32_t)0x00000080)) >> 7; + *swprof6 = (localVal & ((uint32_t)0x00000040)) >> 6; + *swprof5 = (localVal & ((uint32_t)0x00000020)) >> 5; + *swprof4 = (localVal & ((uint32_t)0x00000010)) >> 4; + *swprof3 = (localVal & ((uint32_t)0x00000008)) >> 3; + *swprof2 = (localVal & ((uint32_t)0x00000004)) >> 2; + *swprof1 = (localVal & ((uint32_t)0x00000002)) >> 1; + *swprof0 = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +/** + * @brief Returns the current value of the swProf31 field in the SW_PROFILING register. + * + * The SW_PROFILING register will be read and the swProf31 field's value will be returned. + * + * @return The current value of the swProf31 field in the SW_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_prof_31_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +/** + * @brief Sets the swProf31 field of the SW_PROFILING register. + * + * The SW_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swprof31 - The value to set the field to. + */ +__INLINE void nxmac_sw_prof_31_setf(uint8_t swprof31) +{ + ASSERT_ERR((((uint32_t)swprof31 << 31) & ~((uint32_t)0x80000000)) == 0); + REG_PL_WR(NXMAC_SW_PROFILING_ADDR, (REG_PL_RD(NXMAC_SW_PROFILING_ADDR) & ~((uint32_t)0x80000000)) | ((uint32_t)swprof31 << 31)); +} + +/** + * @brief Returns the current value of the swProf30 field in the SW_PROFILING register. + * + * The SW_PROFILING register will be read and the swProf30 field's value will be returned. + * + * @return The current value of the swProf30 field in the SW_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_prof_30_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x40000000)) >> 30); +} + +/** + * @brief Sets the swProf30 field of the SW_PROFILING register. + * + * The SW_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swprof30 - The value to set the field to. + */ +__INLINE void nxmac_sw_prof_30_setf(uint8_t swprof30) +{ + ASSERT_ERR((((uint32_t)swprof30 << 30) & ~((uint32_t)0x40000000)) == 0); + REG_PL_WR(NXMAC_SW_PROFILING_ADDR, (REG_PL_RD(NXMAC_SW_PROFILING_ADDR) & ~((uint32_t)0x40000000)) | ((uint32_t)swprof30 << 30)); +} + +/** + * @brief Returns the current value of the swProf29 field in the SW_PROFILING register. + * + * The SW_PROFILING register will be read and the swProf29 field's value will be returned. + * + * @return The current value of the swProf29 field in the SW_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_prof_29_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x20000000)) >> 29); +} + +/** + * @brief Sets the swProf29 field of the SW_PROFILING register. + * + * The SW_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swprof29 - The value to set the field to. + */ +__INLINE void nxmac_sw_prof_29_setf(uint8_t swprof29) +{ + ASSERT_ERR((((uint32_t)swprof29 << 29) & ~((uint32_t)0x20000000)) == 0); + REG_PL_WR(NXMAC_SW_PROFILING_ADDR, (REG_PL_RD(NXMAC_SW_PROFILING_ADDR) & ~((uint32_t)0x20000000)) | ((uint32_t)swprof29 << 29)); +} + +/** + * @brief Returns the current value of the swProf28 field in the SW_PROFILING register. + * + * The SW_PROFILING register will be read and the swProf28 field's value will be returned. + * + * @return The current value of the swProf28 field in the SW_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_prof_28_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x10000000)) >> 28); +} + +/** + * @brief Sets the swProf28 field of the SW_PROFILING register. + * + * The SW_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swprof28 - The value to set the field to. + */ +__INLINE void nxmac_sw_prof_28_setf(uint8_t swprof28) +{ + ASSERT_ERR((((uint32_t)swprof28 << 28) & ~((uint32_t)0x10000000)) == 0); + REG_PL_WR(NXMAC_SW_PROFILING_ADDR, (REG_PL_RD(NXMAC_SW_PROFILING_ADDR) & ~((uint32_t)0x10000000)) | ((uint32_t)swprof28 << 28)); +} + +/** + * @brief Returns the current value of the swProf27 field in the SW_PROFILING register. + * + * The SW_PROFILING register will be read and the swProf27 field's value will be returned. + * + * @return The current value of the swProf27 field in the SW_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_prof_27_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x08000000)) >> 27); +} + +/** + * @brief Sets the swProf27 field of the SW_PROFILING register. + * + * The SW_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swprof27 - The value to set the field to. + */ +__INLINE void nxmac_sw_prof_27_setf(uint8_t swprof27) +{ + ASSERT_ERR((((uint32_t)swprof27 << 27) & ~((uint32_t)0x08000000)) == 0); + REG_PL_WR(NXMAC_SW_PROFILING_ADDR, (REG_PL_RD(NXMAC_SW_PROFILING_ADDR) & ~((uint32_t)0x08000000)) | ((uint32_t)swprof27 << 27)); +} + +/** + * @brief Returns the current value of the swProf26 field in the SW_PROFILING register. + * + * The SW_PROFILING register will be read and the swProf26 field's value will be returned. + * + * @return The current value of the swProf26 field in the SW_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_prof_26_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x04000000)) >> 26); +} + +/** + * @brief Sets the swProf26 field of the SW_PROFILING register. + * + * The SW_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swprof26 - The value to set the field to. + */ +__INLINE void nxmac_sw_prof_26_setf(uint8_t swprof26) +{ + ASSERT_ERR((((uint32_t)swprof26 << 26) & ~((uint32_t)0x04000000)) == 0); + REG_PL_WR(NXMAC_SW_PROFILING_ADDR, (REG_PL_RD(NXMAC_SW_PROFILING_ADDR) & ~((uint32_t)0x04000000)) | ((uint32_t)swprof26 << 26)); +} + +/** + * @brief Returns the current value of the swProf25 field in the SW_PROFILING register. + * + * The SW_PROFILING register will be read and the swProf25 field's value will be returned. + * + * @return The current value of the swProf25 field in the SW_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_prof_25_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x02000000)) >> 25); +} + +/** + * @brief Sets the swProf25 field of the SW_PROFILING register. + * + * The SW_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swprof25 - The value to set the field to. + */ +__INLINE void nxmac_sw_prof_25_setf(uint8_t swprof25) +{ + ASSERT_ERR((((uint32_t)swprof25 << 25) & ~((uint32_t)0x02000000)) == 0); + REG_PL_WR(NXMAC_SW_PROFILING_ADDR, (REG_PL_RD(NXMAC_SW_PROFILING_ADDR) & ~((uint32_t)0x02000000)) | ((uint32_t)swprof25 << 25)); +} + +/** + * @brief Returns the current value of the swProf24 field in the SW_PROFILING register. + * + * The SW_PROFILING register will be read and the swProf24 field's value will be returned. + * + * @return The current value of the swProf24 field in the SW_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_prof_24_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x01000000)) >> 24); +} + +/** + * @brief Sets the swProf24 field of the SW_PROFILING register. + * + * The SW_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swprof24 - The value to set the field to. + */ +__INLINE void nxmac_sw_prof_24_setf(uint8_t swprof24) +{ + ASSERT_ERR((((uint32_t)swprof24 << 24) & ~((uint32_t)0x01000000)) == 0); + REG_PL_WR(NXMAC_SW_PROFILING_ADDR, (REG_PL_RD(NXMAC_SW_PROFILING_ADDR) & ~((uint32_t)0x01000000)) | ((uint32_t)swprof24 << 24)); +} + +/** + * @brief Returns the current value of the swProf23 field in the SW_PROFILING register. + * + * The SW_PROFILING register will be read and the swProf23 field's value will be returned. + * + * @return The current value of the swProf23 field in the SW_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_prof_23_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00800000)) >> 23); +} + +/** + * @brief Sets the swProf23 field of the SW_PROFILING register. + * + * The SW_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swprof23 - The value to set the field to. + */ +__INLINE void nxmac_sw_prof_23_setf(uint8_t swprof23) +{ + ASSERT_ERR((((uint32_t)swprof23 << 23) & ~((uint32_t)0x00800000)) == 0); + REG_PL_WR(NXMAC_SW_PROFILING_ADDR, (REG_PL_RD(NXMAC_SW_PROFILING_ADDR) & ~((uint32_t)0x00800000)) | ((uint32_t)swprof23 << 23)); +} + +/** + * @brief Returns the current value of the swProf22 field in the SW_PROFILING register. + * + * The SW_PROFILING register will be read and the swProf22 field's value will be returned. + * + * @return The current value of the swProf22 field in the SW_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_prof_22_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00400000)) >> 22); +} + +/** + * @brief Sets the swProf22 field of the SW_PROFILING register. + * + * The SW_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swprof22 - The value to set the field to. + */ +__INLINE void nxmac_sw_prof_22_setf(uint8_t swprof22) +{ + ASSERT_ERR((((uint32_t)swprof22 << 22) & ~((uint32_t)0x00400000)) == 0); + REG_PL_WR(NXMAC_SW_PROFILING_ADDR, (REG_PL_RD(NXMAC_SW_PROFILING_ADDR) & ~((uint32_t)0x00400000)) | ((uint32_t)swprof22 << 22)); +} + +/** + * @brief Returns the current value of the swProf21 field in the SW_PROFILING register. + * + * The SW_PROFILING register will be read and the swProf21 field's value will be returned. + * + * @return The current value of the swProf21 field in the SW_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_prof_21_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00200000)) >> 21); +} + +/** + * @brief Sets the swProf21 field of the SW_PROFILING register. + * + * The SW_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swprof21 - The value to set the field to. + */ +__INLINE void nxmac_sw_prof_21_setf(uint8_t swprof21) +{ + ASSERT_ERR((((uint32_t)swprof21 << 21) & ~((uint32_t)0x00200000)) == 0); + REG_PL_WR(NXMAC_SW_PROFILING_ADDR, (REG_PL_RD(NXMAC_SW_PROFILING_ADDR) & ~((uint32_t)0x00200000)) | ((uint32_t)swprof21 << 21)); +} + +/** + * @brief Returns the current value of the swProf20 field in the SW_PROFILING register. + * + * The SW_PROFILING register will be read and the swProf20 field's value will be returned. + * + * @return The current value of the swProf20 field in the SW_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_prof_20_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00100000)) >> 20); +} + +/** + * @brief Sets the swProf20 field of the SW_PROFILING register. + * + * The SW_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swprof20 - The value to set the field to. + */ +__INLINE void nxmac_sw_prof_20_setf(uint8_t swprof20) +{ + ASSERT_ERR((((uint32_t)swprof20 << 20) & ~((uint32_t)0x00100000)) == 0); + REG_PL_WR(NXMAC_SW_PROFILING_ADDR, (REG_PL_RD(NXMAC_SW_PROFILING_ADDR) & ~((uint32_t)0x00100000)) | ((uint32_t)swprof20 << 20)); +} + +/** + * @brief Returns the current value of the swProf19 field in the SW_PROFILING register. + * + * The SW_PROFILING register will be read and the swProf19 field's value will be returned. + * + * @return The current value of the swProf19 field in the SW_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_prof_19_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00080000)) >> 19); +} + +/** + * @brief Sets the swProf19 field of the SW_PROFILING register. + * + * The SW_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swprof19 - The value to set the field to. + */ +__INLINE void nxmac_sw_prof_19_setf(uint8_t swprof19) +{ + ASSERT_ERR((((uint32_t)swprof19 << 19) & ~((uint32_t)0x00080000)) == 0); + REG_PL_WR(NXMAC_SW_PROFILING_ADDR, (REG_PL_RD(NXMAC_SW_PROFILING_ADDR) & ~((uint32_t)0x00080000)) | ((uint32_t)swprof19 << 19)); +} + +/** + * @brief Returns the current value of the swProf18 field in the SW_PROFILING register. + * + * The SW_PROFILING register will be read and the swProf18 field's value will be returned. + * + * @return The current value of the swProf18 field in the SW_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_prof_18_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00040000)) >> 18); +} + +/** + * @brief Sets the swProf18 field of the SW_PROFILING register. + * + * The SW_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swprof18 - The value to set the field to. + */ +__INLINE void nxmac_sw_prof_18_setf(uint8_t swprof18) +{ + ASSERT_ERR((((uint32_t)swprof18 << 18) & ~((uint32_t)0x00040000)) == 0); + REG_PL_WR(NXMAC_SW_PROFILING_ADDR, (REG_PL_RD(NXMAC_SW_PROFILING_ADDR) & ~((uint32_t)0x00040000)) | ((uint32_t)swprof18 << 18)); +} + +/** + * @brief Returns the current value of the swProf17 field in the SW_PROFILING register. + * + * The SW_PROFILING register will be read and the swProf17 field's value will be returned. + * + * @return The current value of the swProf17 field in the SW_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_prof_17_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00020000)) >> 17); +} + +/** + * @brief Sets the swProf17 field of the SW_PROFILING register. + * + * The SW_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swprof17 - The value to set the field to. + */ +__INLINE void nxmac_sw_prof_17_setf(uint8_t swprof17) +{ + ASSERT_ERR((((uint32_t)swprof17 << 17) & ~((uint32_t)0x00020000)) == 0); + REG_PL_WR(NXMAC_SW_PROFILING_ADDR, (REG_PL_RD(NXMAC_SW_PROFILING_ADDR) & ~((uint32_t)0x00020000)) | ((uint32_t)swprof17 << 17)); +} + +/** + * @brief Returns the current value of the swProf16 field in the SW_PROFILING register. + * + * The SW_PROFILING register will be read and the swProf16 field's value will be returned. + * + * @return The current value of the swProf16 field in the SW_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_prof_16_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00010000)) >> 16); +} + +/** + * @brief Sets the swProf16 field of the SW_PROFILING register. + * + * The SW_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swprof16 - The value to set the field to. + */ +__INLINE void nxmac_sw_prof_16_setf(uint8_t swprof16) +{ + ASSERT_ERR((((uint32_t)swprof16 << 16) & ~((uint32_t)0x00010000)) == 0); + REG_PL_WR(NXMAC_SW_PROFILING_ADDR, (REG_PL_RD(NXMAC_SW_PROFILING_ADDR) & ~((uint32_t)0x00010000)) | ((uint32_t)swprof16 << 16)); +} + +/** + * @brief Returns the current value of the swProf15 field in the SW_PROFILING register. + * + * The SW_PROFILING register will be read and the swProf15 field's value will be returned. + * + * @return The current value of the swProf15 field in the SW_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_prof_15_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00008000)) >> 15); +} + +/** + * @brief Sets the swProf15 field of the SW_PROFILING register. + * + * The SW_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swprof15 - The value to set the field to. + */ +__INLINE void nxmac_sw_prof_15_setf(uint8_t swprof15) +{ + ASSERT_ERR((((uint32_t)swprof15 << 15) & ~((uint32_t)0x00008000)) == 0); + REG_PL_WR(NXMAC_SW_PROFILING_ADDR, (REG_PL_RD(NXMAC_SW_PROFILING_ADDR) & ~((uint32_t)0x00008000)) | ((uint32_t)swprof15 << 15)); +} + +/** + * @brief Returns the current value of the swProf14 field in the SW_PROFILING register. + * + * The SW_PROFILING register will be read and the swProf14 field's value will be returned. + * + * @return The current value of the swProf14 field in the SW_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_prof_14_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00004000)) >> 14); +} + +/** + * @brief Sets the swProf14 field of the SW_PROFILING register. + * + * The SW_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swprof14 - The value to set the field to. + */ +__INLINE void nxmac_sw_prof_14_setf(uint8_t swprof14) +{ + ASSERT_ERR((((uint32_t)swprof14 << 14) & ~((uint32_t)0x00004000)) == 0); + REG_PL_WR(NXMAC_SW_PROFILING_ADDR, (REG_PL_RD(NXMAC_SW_PROFILING_ADDR) & ~((uint32_t)0x00004000)) | ((uint32_t)swprof14 << 14)); +} + +/** + * @brief Returns the current value of the swProf13 field in the SW_PROFILING register. + * + * The SW_PROFILING register will be read and the swProf13 field's value will be returned. + * + * @return The current value of the swProf13 field in the SW_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_prof_13_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00002000)) >> 13); +} + +/** + * @brief Sets the swProf13 field of the SW_PROFILING register. + * + * The SW_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swprof13 - The value to set the field to. + */ +__INLINE void nxmac_sw_prof_13_setf(uint8_t swprof13) +{ + ASSERT_ERR((((uint32_t)swprof13 << 13) & ~((uint32_t)0x00002000)) == 0); + REG_PL_WR(NXMAC_SW_PROFILING_ADDR, (REG_PL_RD(NXMAC_SW_PROFILING_ADDR) & ~((uint32_t)0x00002000)) | ((uint32_t)swprof13 << 13)); +} + +/** + * @brief Returns the current value of the swProf12 field in the SW_PROFILING register. + * + * The SW_PROFILING register will be read and the swProf12 field's value will be returned. + * + * @return The current value of the swProf12 field in the SW_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_prof_12_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00001000)) >> 12); +} + +/** + * @brief Sets the swProf12 field of the SW_PROFILING register. + * + * The SW_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swprof12 - The value to set the field to. + */ +__INLINE void nxmac_sw_prof_12_setf(uint8_t swprof12) +{ + ASSERT_ERR((((uint32_t)swprof12 << 12) & ~((uint32_t)0x00001000)) == 0); + REG_PL_WR(NXMAC_SW_PROFILING_ADDR, (REG_PL_RD(NXMAC_SW_PROFILING_ADDR) & ~((uint32_t)0x00001000)) | ((uint32_t)swprof12 << 12)); +} + +/** + * @brief Returns the current value of the swProf11 field in the SW_PROFILING register. + * + * The SW_PROFILING register will be read and the swProf11 field's value will be returned. + * + * @return The current value of the swProf11 field in the SW_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_prof_11_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000800)) >> 11); +} + +/** + * @brief Sets the swProf11 field of the SW_PROFILING register. + * + * The SW_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swprof11 - The value to set the field to. + */ +__INLINE void nxmac_sw_prof_11_setf(uint8_t swprof11) +{ + ASSERT_ERR((((uint32_t)swprof11 << 11) & ~((uint32_t)0x00000800)) == 0); + REG_PL_WR(NXMAC_SW_PROFILING_ADDR, (REG_PL_RD(NXMAC_SW_PROFILING_ADDR) & ~((uint32_t)0x00000800)) | ((uint32_t)swprof11 << 11)); +} + +/** + * @brief Returns the current value of the swProf10 field in the SW_PROFILING register. + * + * The SW_PROFILING register will be read and the swProf10 field's value will be returned. + * + * @return The current value of the swProf10 field in the SW_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_prof_10_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000400)) >> 10); +} + +/** + * @brief Sets the swProf10 field of the SW_PROFILING register. + * + * The SW_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swprof10 - The value to set the field to. + */ +__INLINE void nxmac_sw_prof_10_setf(uint8_t swprof10) +{ + ASSERT_ERR((((uint32_t)swprof10 << 10) & ~((uint32_t)0x00000400)) == 0); + REG_PL_WR(NXMAC_SW_PROFILING_ADDR, (REG_PL_RD(NXMAC_SW_PROFILING_ADDR) & ~((uint32_t)0x00000400)) | ((uint32_t)swprof10 << 10)); +} + +/** + * @brief Returns the current value of the swProf9 field in the SW_PROFILING register. + * + * The SW_PROFILING register will be read and the swProf9 field's value will be returned. + * + * @return The current value of the swProf9 field in the SW_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_prof_9_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000200)) >> 9); +} + +/** + * @brief Sets the swProf9 field of the SW_PROFILING register. + * + * The SW_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swprof9 - The value to set the field to. + */ +__INLINE void nxmac_sw_prof_9_setf(uint8_t swprof9) +{ + ASSERT_ERR((((uint32_t)swprof9 << 9) & ~((uint32_t)0x00000200)) == 0); + REG_PL_WR(NXMAC_SW_PROFILING_ADDR, (REG_PL_RD(NXMAC_SW_PROFILING_ADDR) & ~((uint32_t)0x00000200)) | ((uint32_t)swprof9 << 9)); +} + +/** + * @brief Returns the current value of the swProf8 field in the SW_PROFILING register. + * + * The SW_PROFILING register will be read and the swProf8 field's value will be returned. + * + * @return The current value of the swProf8 field in the SW_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_prof_8_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000100)) >> 8); +} + +/** + * @brief Sets the swProf8 field of the SW_PROFILING register. + * + * The SW_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swprof8 - The value to set the field to. + */ +__INLINE void nxmac_sw_prof_8_setf(uint8_t swprof8) +{ + ASSERT_ERR((((uint32_t)swprof8 << 8) & ~((uint32_t)0x00000100)) == 0); + REG_PL_WR(NXMAC_SW_PROFILING_ADDR, (REG_PL_RD(NXMAC_SW_PROFILING_ADDR) & ~((uint32_t)0x00000100)) | ((uint32_t)swprof8 << 8)); +} + +/** + * @brief Returns the current value of the swProf7 field in the SW_PROFILING register. + * + * The SW_PROFILING register will be read and the swProf7 field's value will be returned. + * + * @return The current value of the swProf7 field in the SW_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_prof_7_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000080)) >> 7); +} + +/** + * @brief Sets the swProf7 field of the SW_PROFILING register. + * + * The SW_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swprof7 - The value to set the field to. + */ +__INLINE void nxmac_sw_prof_7_setf(uint8_t swprof7) +{ + ASSERT_ERR((((uint32_t)swprof7 << 7) & ~((uint32_t)0x00000080)) == 0); + REG_PL_WR(NXMAC_SW_PROFILING_ADDR, (REG_PL_RD(NXMAC_SW_PROFILING_ADDR) & ~((uint32_t)0x00000080)) | ((uint32_t)swprof7 << 7)); +} + +/** + * @brief Returns the current value of the swProf6 field in the SW_PROFILING register. + * + * The SW_PROFILING register will be read and the swProf6 field's value will be returned. + * + * @return The current value of the swProf6 field in the SW_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_prof_6_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000040)) >> 6); +} + +/** + * @brief Sets the swProf6 field of the SW_PROFILING register. + * + * The SW_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swprof6 - The value to set the field to. + */ +__INLINE void nxmac_sw_prof_6_setf(uint8_t swprof6) +{ + ASSERT_ERR((((uint32_t)swprof6 << 6) & ~((uint32_t)0x00000040)) == 0); + REG_PL_WR(NXMAC_SW_PROFILING_ADDR, (REG_PL_RD(NXMAC_SW_PROFILING_ADDR) & ~((uint32_t)0x00000040)) | ((uint32_t)swprof6 << 6)); +} + +/** + * @brief Returns the current value of the swProf5 field in the SW_PROFILING register. + * + * The SW_PROFILING register will be read and the swProf5 field's value will be returned. + * + * @return The current value of the swProf5 field in the SW_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_prof_5_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +/** + * @brief Sets the swProf5 field of the SW_PROFILING register. + * + * The SW_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swprof5 - The value to set the field to. + */ +__INLINE void nxmac_sw_prof_5_setf(uint8_t swprof5) +{ + ASSERT_ERR((((uint32_t)swprof5 << 5) & ~((uint32_t)0x00000020)) == 0); + REG_PL_WR(NXMAC_SW_PROFILING_ADDR, (REG_PL_RD(NXMAC_SW_PROFILING_ADDR) & ~((uint32_t)0x00000020)) | ((uint32_t)swprof5 << 5)); +} + +/** + * @brief Returns the current value of the swProf4 field in the SW_PROFILING register. + * + * The SW_PROFILING register will be read and the swProf4 field's value will be returned. + * + * @return The current value of the swProf4 field in the SW_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_prof_4_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +/** + * @brief Sets the swProf4 field of the SW_PROFILING register. + * + * The SW_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swprof4 - The value to set the field to. + */ +__INLINE void nxmac_sw_prof_4_setf(uint8_t swprof4) +{ + ASSERT_ERR((((uint32_t)swprof4 << 4) & ~((uint32_t)0x00000010)) == 0); + REG_PL_WR(NXMAC_SW_PROFILING_ADDR, (REG_PL_RD(NXMAC_SW_PROFILING_ADDR) & ~((uint32_t)0x00000010)) | ((uint32_t)swprof4 << 4)); +} + +/** + * @brief Returns the current value of the swProf3 field in the SW_PROFILING register. + * + * The SW_PROFILING register will be read and the swProf3 field's value will be returned. + * + * @return The current value of the swProf3 field in the SW_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_prof_3_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +/** + * @brief Sets the swProf3 field of the SW_PROFILING register. + * + * The SW_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swprof3 - The value to set the field to. + */ +__INLINE void nxmac_sw_prof_3_setf(uint8_t swprof3) +{ + ASSERT_ERR((((uint32_t)swprof3 << 3) & ~((uint32_t)0x00000008)) == 0); + REG_PL_WR(NXMAC_SW_PROFILING_ADDR, (REG_PL_RD(NXMAC_SW_PROFILING_ADDR) & ~((uint32_t)0x00000008)) | ((uint32_t)swprof3 << 3)); +} + +/** + * @brief Returns the current value of the swProf2 field in the SW_PROFILING register. + * + * The SW_PROFILING register will be read and the swProf2 field's value will be returned. + * + * @return The current value of the swProf2 field in the SW_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_prof_2_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +/** + * @brief Sets the swProf2 field of the SW_PROFILING register. + * + * The SW_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swprof2 - The value to set the field to. + */ +__INLINE void nxmac_sw_prof_2_setf(uint8_t swprof2) +{ + ASSERT_ERR((((uint32_t)swprof2 << 2) & ~((uint32_t)0x00000004)) == 0); + REG_PL_WR(NXMAC_SW_PROFILING_ADDR, (REG_PL_RD(NXMAC_SW_PROFILING_ADDR) & ~((uint32_t)0x00000004)) | ((uint32_t)swprof2 << 2)); +} + +/** + * @brief Returns the current value of the swProf1 field in the SW_PROFILING register. + * + * The SW_PROFILING register will be read and the swProf1 field's value will be returned. + * + * @return The current value of the swProf1 field in the SW_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_prof_1_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +/** + * @brief Sets the swProf1 field of the SW_PROFILING register. + * + * The SW_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swprof1 - The value to set the field to. + */ +__INLINE void nxmac_sw_prof_1_setf(uint8_t swprof1) +{ + ASSERT_ERR((((uint32_t)swprof1 << 1) & ~((uint32_t)0x00000002)) == 0); + REG_PL_WR(NXMAC_SW_PROFILING_ADDR, (REG_PL_RD(NXMAC_SW_PROFILING_ADDR) & ~((uint32_t)0x00000002)) | ((uint32_t)swprof1 << 1)); +} + +/** + * @brief Returns the current value of the swProf0 field in the SW_PROFILING register. + * + * The SW_PROFILING register will be read and the swProf0 field's value will be returned. + * + * @return The current value of the swProf0 field in the SW_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_prof_0_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/** + * @brief Sets the swProf0 field of the SW_PROFILING register. + * + * The SW_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swprof0 - The value to set the field to. + */ +__INLINE void nxmac_sw_prof_0_setf(uint8_t swprof0) +{ + ASSERT_ERR((((uint32_t)swprof0 << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_SW_PROFILING_ADDR, (REG_PL_RD(NXMAC_SW_PROFILING_ADDR) & ~((uint32_t)0x00000001)) | ((uint32_t)swprof0 << 0)); +} + +/// @} + +/** + * @name SW_SET_PROFILING register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31          swSetProf31   0
+ *     30          swSetProf30   0
+ *     29          swSetProf29   0
+ *     28          swSetProf28   0
+ *     27          swSetProf27   0
+ *     26          swSetProf26   0
+ *     25          swSetProf25   0
+ *     24          swSetProf24   0
+ *     23          swSetProf23   0
+ *     22          swSetProf22   0
+ *     21          swSetProf21   0
+ *     20          swSetProf20   0
+ *     19          swSetProf19   0
+ *     18          swSetProf18   0
+ *     17          swSetProf17   0
+ *     16          swSetProf16   0
+ *     15          swSetProf15   0
+ *     14          swSetProf14   0
+ *     13          swSetProf13   0
+ *     12          swSetProf12   0
+ *     11          swSetProf11   0
+ *     10          swSetProf10   0
+ *     09           swSetProf9   0
+ *     08           swSetProf8   0
+ *     07           swSetProf7   0
+ *     06           swSetProf6   0
+ *     05           swSetProf5   0
+ *     04           swSetProf4   0
+ *     03           swSetProf3   0
+ *     02           swSetProf2   0
+ *     01           swSetProf1   0
+ *     00           swSetProf0   0
+ * 
+ * + * @{ + */ + +/// Address of the SW_SET_PROFILING register +#define NXMAC_SW_SET_PROFILING_ADDR 0xC0008564 +/// Offset of the SW_SET_PROFILING register from the base address +#define NXMAC_SW_SET_PROFILING_OFFSET 0x00000564 +/// Index of the SW_SET_PROFILING register +#define NXMAC_SW_SET_PROFILING_INDEX 0x00000159 +/// Reset value of the SW_SET_PROFILING register +#define NXMAC_SW_SET_PROFILING_RESET 0x00000000 + +/** + * @brief Returns the current value of the SW_SET_PROFILING register. + * The SW_SET_PROFILING register will be read and its value returned. + * @return The current value of the SW_SET_PROFILING register. + */ +__INLINE uint32_t nxmac_sw_set_profiling_get(void) +{ + return REG_PL_RD(NXMAC_SW_SET_PROFILING_ADDR); +} + +/** + * @brief Sets the SW_SET_PROFILING register to a value. + * The SW_SET_PROFILING register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_sw_set_profiling_set(uint32_t value) +{ + REG_PL_WR(NXMAC_SW_SET_PROFILING_ADDR, value); +} + +// field definitions +/// SW_SET_PROF_31 field bit +#define NXMAC_SW_SET_PROF_31_BIT ((uint32_t)0x80000000) +/// SW_SET_PROF_31 field position +#define NXMAC_SW_SET_PROF_31_POS 31 +/// SW_SET_PROF_30 field bit +#define NXMAC_SW_SET_PROF_30_BIT ((uint32_t)0x40000000) +/// SW_SET_PROF_30 field position +#define NXMAC_SW_SET_PROF_30_POS 30 +/// SW_SET_PROF_29 field bit +#define NXMAC_SW_SET_PROF_29_BIT ((uint32_t)0x20000000) +/// SW_SET_PROF_29 field position +#define NXMAC_SW_SET_PROF_29_POS 29 +/// SW_SET_PROF_28 field bit +#define NXMAC_SW_SET_PROF_28_BIT ((uint32_t)0x10000000) +/// SW_SET_PROF_28 field position +#define NXMAC_SW_SET_PROF_28_POS 28 +/// SW_SET_PROF_27 field bit +#define NXMAC_SW_SET_PROF_27_BIT ((uint32_t)0x08000000) +/// SW_SET_PROF_27 field position +#define NXMAC_SW_SET_PROF_27_POS 27 +/// SW_SET_PROF_26 field bit +#define NXMAC_SW_SET_PROF_26_BIT ((uint32_t)0x04000000) +/// SW_SET_PROF_26 field position +#define NXMAC_SW_SET_PROF_26_POS 26 +/// SW_SET_PROF_25 field bit +#define NXMAC_SW_SET_PROF_25_BIT ((uint32_t)0x02000000) +/// SW_SET_PROF_25 field position +#define NXMAC_SW_SET_PROF_25_POS 25 +/// SW_SET_PROF_24 field bit +#define NXMAC_SW_SET_PROF_24_BIT ((uint32_t)0x01000000) +/// SW_SET_PROF_24 field position +#define NXMAC_SW_SET_PROF_24_POS 24 +/// SW_SET_PROF_23 field bit +#define NXMAC_SW_SET_PROF_23_BIT ((uint32_t)0x00800000) +/// SW_SET_PROF_23 field position +#define NXMAC_SW_SET_PROF_23_POS 23 +/// SW_SET_PROF_22 field bit +#define NXMAC_SW_SET_PROF_22_BIT ((uint32_t)0x00400000) +/// SW_SET_PROF_22 field position +#define NXMAC_SW_SET_PROF_22_POS 22 +/// SW_SET_PROF_21 field bit +#define NXMAC_SW_SET_PROF_21_BIT ((uint32_t)0x00200000) +/// SW_SET_PROF_21 field position +#define NXMAC_SW_SET_PROF_21_POS 21 +/// SW_SET_PROF_20 field bit +#define NXMAC_SW_SET_PROF_20_BIT ((uint32_t)0x00100000) +/// SW_SET_PROF_20 field position +#define NXMAC_SW_SET_PROF_20_POS 20 +/// SW_SET_PROF_19 field bit +#define NXMAC_SW_SET_PROF_19_BIT ((uint32_t)0x00080000) +/// SW_SET_PROF_19 field position +#define NXMAC_SW_SET_PROF_19_POS 19 +/// SW_SET_PROF_18 field bit +#define NXMAC_SW_SET_PROF_18_BIT ((uint32_t)0x00040000) +/// SW_SET_PROF_18 field position +#define NXMAC_SW_SET_PROF_18_POS 18 +/// SW_SET_PROF_17 field bit +#define NXMAC_SW_SET_PROF_17_BIT ((uint32_t)0x00020000) +/// SW_SET_PROF_17 field position +#define NXMAC_SW_SET_PROF_17_POS 17 +/// SW_SET_PROF_16 field bit +#define NXMAC_SW_SET_PROF_16_BIT ((uint32_t)0x00010000) +/// SW_SET_PROF_16 field position +#define NXMAC_SW_SET_PROF_16_POS 16 +/// SW_SET_PROF_15 field bit +#define NXMAC_SW_SET_PROF_15_BIT ((uint32_t)0x00008000) +/// SW_SET_PROF_15 field position +#define NXMAC_SW_SET_PROF_15_POS 15 +/// SW_SET_PROF_14 field bit +#define NXMAC_SW_SET_PROF_14_BIT ((uint32_t)0x00004000) +/// SW_SET_PROF_14 field position +#define NXMAC_SW_SET_PROF_14_POS 14 +/// SW_SET_PROF_13 field bit +#define NXMAC_SW_SET_PROF_13_BIT ((uint32_t)0x00002000) +/// SW_SET_PROF_13 field position +#define NXMAC_SW_SET_PROF_13_POS 13 +/// SW_SET_PROF_12 field bit +#define NXMAC_SW_SET_PROF_12_BIT ((uint32_t)0x00001000) +/// SW_SET_PROF_12 field position +#define NXMAC_SW_SET_PROF_12_POS 12 +/// SW_SET_PROF_11 field bit +#define NXMAC_SW_SET_PROF_11_BIT ((uint32_t)0x00000800) +/// SW_SET_PROF_11 field position +#define NXMAC_SW_SET_PROF_11_POS 11 +/// SW_SET_PROF_10 field bit +#define NXMAC_SW_SET_PROF_10_BIT ((uint32_t)0x00000400) +/// SW_SET_PROF_10 field position +#define NXMAC_SW_SET_PROF_10_POS 10 +/// SW_SET_PROF_9 field bit +#define NXMAC_SW_SET_PROF_9_BIT ((uint32_t)0x00000200) +/// SW_SET_PROF_9 field position +#define NXMAC_SW_SET_PROF_9_POS 9 +/// SW_SET_PROF_8 field bit +#define NXMAC_SW_SET_PROF_8_BIT ((uint32_t)0x00000100) +/// SW_SET_PROF_8 field position +#define NXMAC_SW_SET_PROF_8_POS 8 +/// SW_SET_PROF_7 field bit +#define NXMAC_SW_SET_PROF_7_BIT ((uint32_t)0x00000080) +/// SW_SET_PROF_7 field position +#define NXMAC_SW_SET_PROF_7_POS 7 +/// SW_SET_PROF_6 field bit +#define NXMAC_SW_SET_PROF_6_BIT ((uint32_t)0x00000040) +/// SW_SET_PROF_6 field position +#define NXMAC_SW_SET_PROF_6_POS 6 +/// SW_SET_PROF_5 field bit +#define NXMAC_SW_SET_PROF_5_BIT ((uint32_t)0x00000020) +/// SW_SET_PROF_5 field position +#define NXMAC_SW_SET_PROF_5_POS 5 +/// SW_SET_PROF_4 field bit +#define NXMAC_SW_SET_PROF_4_BIT ((uint32_t)0x00000010) +/// SW_SET_PROF_4 field position +#define NXMAC_SW_SET_PROF_4_POS 4 +/// SW_SET_PROF_3 field bit +#define NXMAC_SW_SET_PROF_3_BIT ((uint32_t)0x00000008) +/// SW_SET_PROF_3 field position +#define NXMAC_SW_SET_PROF_3_POS 3 +/// SW_SET_PROF_2 field bit +#define NXMAC_SW_SET_PROF_2_BIT ((uint32_t)0x00000004) +/// SW_SET_PROF_2 field position +#define NXMAC_SW_SET_PROF_2_POS 2 +/// SW_SET_PROF_1 field bit +#define NXMAC_SW_SET_PROF_1_BIT ((uint32_t)0x00000002) +/// SW_SET_PROF_1 field position +#define NXMAC_SW_SET_PROF_1_POS 1 +/// SW_SET_PROF_0 field bit +#define NXMAC_SW_SET_PROF_0_BIT ((uint32_t)0x00000001) +/// SW_SET_PROF_0 field position +#define NXMAC_SW_SET_PROF_0_POS 0 + +/// SW_SET_PROF_31 field reset value +#define NXMAC_SW_SET_PROF_31_RST 0x0 +/// SW_SET_PROF_30 field reset value +#define NXMAC_SW_SET_PROF_30_RST 0x0 +/// SW_SET_PROF_29 field reset value +#define NXMAC_SW_SET_PROF_29_RST 0x0 +/// SW_SET_PROF_28 field reset value +#define NXMAC_SW_SET_PROF_28_RST 0x0 +/// SW_SET_PROF_27 field reset value +#define NXMAC_SW_SET_PROF_27_RST 0x0 +/// SW_SET_PROF_26 field reset value +#define NXMAC_SW_SET_PROF_26_RST 0x0 +/// SW_SET_PROF_25 field reset value +#define NXMAC_SW_SET_PROF_25_RST 0x0 +/// SW_SET_PROF_24 field reset value +#define NXMAC_SW_SET_PROF_24_RST 0x0 +/// SW_SET_PROF_23 field reset value +#define NXMAC_SW_SET_PROF_23_RST 0x0 +/// SW_SET_PROF_22 field reset value +#define NXMAC_SW_SET_PROF_22_RST 0x0 +/// SW_SET_PROF_21 field reset value +#define NXMAC_SW_SET_PROF_21_RST 0x0 +/// SW_SET_PROF_20 field reset value +#define NXMAC_SW_SET_PROF_20_RST 0x0 +/// SW_SET_PROF_19 field reset value +#define NXMAC_SW_SET_PROF_19_RST 0x0 +/// SW_SET_PROF_18 field reset value +#define NXMAC_SW_SET_PROF_18_RST 0x0 +/// SW_SET_PROF_17 field reset value +#define NXMAC_SW_SET_PROF_17_RST 0x0 +/// SW_SET_PROF_16 field reset value +#define NXMAC_SW_SET_PROF_16_RST 0x0 +/// SW_SET_PROF_15 field reset value +#define NXMAC_SW_SET_PROF_15_RST 0x0 +/// SW_SET_PROF_14 field reset value +#define NXMAC_SW_SET_PROF_14_RST 0x0 +/// SW_SET_PROF_13 field reset value +#define NXMAC_SW_SET_PROF_13_RST 0x0 +/// SW_SET_PROF_12 field reset value +#define NXMAC_SW_SET_PROF_12_RST 0x0 +/// SW_SET_PROF_11 field reset value +#define NXMAC_SW_SET_PROF_11_RST 0x0 +/// SW_SET_PROF_10 field reset value +#define NXMAC_SW_SET_PROF_10_RST 0x0 +/// SW_SET_PROF_9 field reset value +#define NXMAC_SW_SET_PROF_9_RST 0x0 +/// SW_SET_PROF_8 field reset value +#define NXMAC_SW_SET_PROF_8_RST 0x0 +/// SW_SET_PROF_7 field reset value +#define NXMAC_SW_SET_PROF_7_RST 0x0 +/// SW_SET_PROF_6 field reset value +#define NXMAC_SW_SET_PROF_6_RST 0x0 +/// SW_SET_PROF_5 field reset value +#define NXMAC_SW_SET_PROF_5_RST 0x0 +/// SW_SET_PROF_4 field reset value +#define NXMAC_SW_SET_PROF_4_RST 0x0 +/// SW_SET_PROF_3 field reset value +#define NXMAC_SW_SET_PROF_3_RST 0x0 +/// SW_SET_PROF_2 field reset value +#define NXMAC_SW_SET_PROF_2_RST 0x0 +/// SW_SET_PROF_1 field reset value +#define NXMAC_SW_SET_PROF_1_RST 0x0 +/// SW_SET_PROF_0 field reset value +#define NXMAC_SW_SET_PROF_0_RST 0x0 + +/** + * @brief Constructs a value for the SW_SET_PROFILING register given values for its fields + * and writes the value to the register. + * + * @param[in] swsetprof31 - The value to use for the swSetProf31 field. + * @param[in] swsetprof30 - The value to use for the swSetProf30 field. + * @param[in] swsetprof29 - The value to use for the swSetProf29 field. + * @param[in] swsetprof28 - The value to use for the swSetProf28 field. + * @param[in] swsetprof27 - The value to use for the swSetProf27 field. + * @param[in] swsetprof26 - The value to use for the swSetProf26 field. + * @param[in] swsetprof25 - The value to use for the swSetProf25 field. + * @param[in] swsetprof24 - The value to use for the swSetProf24 field. + * @param[in] swsetprof23 - The value to use for the swSetProf23 field. + * @param[in] swsetprof22 - The value to use for the swSetProf22 field. + * @param[in] swsetprof21 - The value to use for the swSetProf21 field. + * @param[in] swsetprof20 - The value to use for the swSetProf20 field. + * @param[in] swsetprof19 - The value to use for the swSetProf19 field. + * @param[in] swsetprof18 - The value to use for the swSetProf18 field. + * @param[in] swsetprof17 - The value to use for the swSetProf17 field. + * @param[in] swsetprof16 - The value to use for the swSetProf16 field. + * @param[in] swsetprof15 - The value to use for the swSetProf15 field. + * @param[in] swsetprof14 - The value to use for the swSetProf14 field. + * @param[in] swsetprof13 - The value to use for the swSetProf13 field. + * @param[in] swsetprof12 - The value to use for the swSetProf12 field. + * @param[in] swsetprof11 - The value to use for the swSetProf11 field. + * @param[in] swsetprof10 - The value to use for the swSetProf10 field. + * @param[in] swsetprof9 - The value to use for the swSetProf9 field. + * @param[in] swsetprof8 - The value to use for the swSetProf8 field. + * @param[in] swsetprof7 - The value to use for the swSetProf7 field. + * @param[in] swsetprof6 - The value to use for the swSetProf6 field. + * @param[in] swsetprof5 - The value to use for the swSetProf5 field. + * @param[in] swsetprof4 - The value to use for the swSetProf4 field. + * @param[in] swsetprof3 - The value to use for the swSetProf3 field. + * @param[in] swsetprof2 - The value to use for the swSetProf2 field. + * @param[in] swsetprof1 - The value to use for the swSetProf1 field. + * @param[in] swsetprof0 - The value to use for the swSetProf0 field. + */ +__INLINE void nxmac_sw_set_profiling_pack(uint8_t swsetprof31, uint8_t swsetprof30, uint8_t swsetprof29, uint8_t swsetprof28, uint8_t swsetprof27, uint8_t swsetprof26, uint8_t swsetprof25, uint8_t swsetprof24, uint8_t swsetprof23, uint8_t swsetprof22, uint8_t swsetprof21, uint8_t swsetprof20, uint8_t swsetprof19, uint8_t swsetprof18, uint8_t swsetprof17, uint8_t swsetprof16, uint8_t swsetprof15, uint8_t swsetprof14, uint8_t swsetprof13, uint8_t swsetprof12, uint8_t swsetprof11, uint8_t swsetprof10, uint8_t swsetprof9, uint8_t swsetprof8, uint8_t swsetprof7, uint8_t swsetprof6, uint8_t swsetprof5, uint8_t swsetprof4, uint8_t swsetprof3, uint8_t swsetprof2, uint8_t swsetprof1, uint8_t swsetprof0) +{ + ASSERT_ERR((((uint32_t)swsetprof31 << 31) & ~((uint32_t)0x80000000)) == 0); + ASSERT_ERR((((uint32_t)swsetprof30 << 30) & ~((uint32_t)0x40000000)) == 0); + ASSERT_ERR((((uint32_t)swsetprof29 << 29) & ~((uint32_t)0x20000000)) == 0); + ASSERT_ERR((((uint32_t)swsetprof28 << 28) & ~((uint32_t)0x10000000)) == 0); + ASSERT_ERR((((uint32_t)swsetprof27 << 27) & ~((uint32_t)0x08000000)) == 0); + ASSERT_ERR((((uint32_t)swsetprof26 << 26) & ~((uint32_t)0x04000000)) == 0); + ASSERT_ERR((((uint32_t)swsetprof25 << 25) & ~((uint32_t)0x02000000)) == 0); + ASSERT_ERR((((uint32_t)swsetprof24 << 24) & ~((uint32_t)0x01000000)) == 0); + ASSERT_ERR((((uint32_t)swsetprof23 << 23) & ~((uint32_t)0x00800000)) == 0); + ASSERT_ERR((((uint32_t)swsetprof22 << 22) & ~((uint32_t)0x00400000)) == 0); + ASSERT_ERR((((uint32_t)swsetprof21 << 21) & ~((uint32_t)0x00200000)) == 0); + ASSERT_ERR((((uint32_t)swsetprof20 << 20) & ~((uint32_t)0x00100000)) == 0); + ASSERT_ERR((((uint32_t)swsetprof19 << 19) & ~((uint32_t)0x00080000)) == 0); + ASSERT_ERR((((uint32_t)swsetprof18 << 18) & ~((uint32_t)0x00040000)) == 0); + ASSERT_ERR((((uint32_t)swsetprof17 << 17) & ~((uint32_t)0x00020000)) == 0); + ASSERT_ERR((((uint32_t)swsetprof16 << 16) & ~((uint32_t)0x00010000)) == 0); + ASSERT_ERR((((uint32_t)swsetprof15 << 15) & ~((uint32_t)0x00008000)) == 0); + ASSERT_ERR((((uint32_t)swsetprof14 << 14) & ~((uint32_t)0x00004000)) == 0); + ASSERT_ERR((((uint32_t)swsetprof13 << 13) & ~((uint32_t)0x00002000)) == 0); + ASSERT_ERR((((uint32_t)swsetprof12 << 12) & ~((uint32_t)0x00001000)) == 0); + ASSERT_ERR((((uint32_t)swsetprof11 << 11) & ~((uint32_t)0x00000800)) == 0); + ASSERT_ERR((((uint32_t)swsetprof10 << 10) & ~((uint32_t)0x00000400)) == 0); + ASSERT_ERR((((uint32_t)swsetprof9 << 9) & ~((uint32_t)0x00000200)) == 0); + ASSERT_ERR((((uint32_t)swsetprof8 << 8) & ~((uint32_t)0x00000100)) == 0); + ASSERT_ERR((((uint32_t)swsetprof7 << 7) & ~((uint32_t)0x00000080)) == 0); + ASSERT_ERR((((uint32_t)swsetprof6 << 6) & ~((uint32_t)0x00000040)) == 0); + ASSERT_ERR((((uint32_t)swsetprof5 << 5) & ~((uint32_t)0x00000020)) == 0); + ASSERT_ERR((((uint32_t)swsetprof4 << 4) & ~((uint32_t)0x00000010)) == 0); + ASSERT_ERR((((uint32_t)swsetprof3 << 3) & ~((uint32_t)0x00000008)) == 0); + ASSERT_ERR((((uint32_t)swsetprof2 << 2) & ~((uint32_t)0x00000004)) == 0); + ASSERT_ERR((((uint32_t)swsetprof1 << 1) & ~((uint32_t)0x00000002)) == 0); + ASSERT_ERR((((uint32_t)swsetprof0 << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_SW_SET_PROFILING_ADDR, ((uint32_t)swsetprof31 << 31) | ((uint32_t)swsetprof30 << 30) | ((uint32_t)swsetprof29 << 29) | ((uint32_t)swsetprof28 << 28) | ((uint32_t)swsetprof27 << 27) | ((uint32_t)swsetprof26 << 26) | ((uint32_t)swsetprof25 << 25) | ((uint32_t)swsetprof24 << 24) | ((uint32_t)swsetprof23 << 23) | ((uint32_t)swsetprof22 << 22) | ((uint32_t)swsetprof21 << 21) | ((uint32_t)swsetprof20 << 20) | ((uint32_t)swsetprof19 << 19) | ((uint32_t)swsetprof18 << 18) | ((uint32_t)swsetprof17 << 17) | ((uint32_t)swsetprof16 << 16) | ((uint32_t)swsetprof15 << 15) | ((uint32_t)swsetprof14 << 14) | ((uint32_t)swsetprof13 << 13) | ((uint32_t)swsetprof12 << 12) | ((uint32_t)swsetprof11 << 11) | ((uint32_t)swsetprof10 << 10) | ((uint32_t)swsetprof9 << 9) | ((uint32_t)swsetprof8 << 8) | ((uint32_t)swsetprof7 << 7) | ((uint32_t)swsetprof6 << 6) | ((uint32_t)swsetprof5 << 5) | ((uint32_t)swsetprof4 << 4) | ((uint32_t)swsetprof3 << 3) | ((uint32_t)swsetprof2 << 2) | ((uint32_t)swsetprof1 << 1) | ((uint32_t)swsetprof0 << 0)); +} + +/** + * @brief Unpacks SW_SET_PROFILING's fields from current value of the SW_SET_PROFILING register. + * + * Reads the SW_SET_PROFILING register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] swsetprof31 - Will be populated with the current value of this field from the register. + * @param[out] swsetprof30 - Will be populated with the current value of this field from the register. + * @param[out] swsetprof29 - Will be populated with the current value of this field from the register. + * @param[out] swsetprof28 - Will be populated with the current value of this field from the register. + * @param[out] swsetprof27 - Will be populated with the current value of this field from the register. + * @param[out] swsetprof26 - Will be populated with the current value of this field from the register. + * @param[out] swsetprof25 - Will be populated with the current value of this field from the register. + * @param[out] swsetprof24 - Will be populated with the current value of this field from the register. + * @param[out] swsetprof23 - Will be populated with the current value of this field from the register. + * @param[out] swsetprof22 - Will be populated with the current value of this field from the register. + * @param[out] swsetprof21 - Will be populated with the current value of this field from the register. + * @param[out] swsetprof20 - Will be populated with the current value of this field from the register. + * @param[out] swsetprof19 - Will be populated with the current value of this field from the register. + * @param[out] swsetprof18 - Will be populated with the current value of this field from the register. + * @param[out] swsetprof17 - Will be populated with the current value of this field from the register. + * @param[out] swsetprof16 - Will be populated with the current value of this field from the register. + * @param[out] swsetprof15 - Will be populated with the current value of this field from the register. + * @param[out] swsetprof14 - Will be populated with the current value of this field from the register. + * @param[out] swsetprof13 - Will be populated with the current value of this field from the register. + * @param[out] swsetprof12 - Will be populated with the current value of this field from the register. + * @param[out] swsetprof11 - Will be populated with the current value of this field from the register. + * @param[out] swsetprof10 - Will be populated with the current value of this field from the register. + * @param[out] swsetprof9 - Will be populated with the current value of this field from the register. + * @param[out] swsetprof8 - Will be populated with the current value of this field from the register. + * @param[out] swsetprof7 - Will be populated with the current value of this field from the register. + * @param[out] swsetprof6 - Will be populated with the current value of this field from the register. + * @param[out] swsetprof5 - Will be populated with the current value of this field from the register. + * @param[out] swsetprof4 - Will be populated with the current value of this field from the register. + * @param[out] swsetprof3 - Will be populated with the current value of this field from the register. + * @param[out] swsetprof2 - Will be populated with the current value of this field from the register. + * @param[out] swsetprof1 - Will be populated with the current value of this field from the register. + * @param[out] swsetprof0 - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_sw_set_profiling_unpack(uint8_t *swsetprof31, uint8_t *swsetprof30, uint8_t *swsetprof29, uint8_t *swsetprof28, uint8_t *swsetprof27, uint8_t *swsetprof26, uint8_t *swsetprof25, uint8_t *swsetprof24, uint8_t *swsetprof23, uint8_t *swsetprof22, uint8_t *swsetprof21, uint8_t *swsetprof20, uint8_t *swsetprof19, uint8_t *swsetprof18, uint8_t *swsetprof17, uint8_t *swsetprof16, uint8_t *swsetprof15, uint8_t *swsetprof14, uint8_t *swsetprof13, uint8_t *swsetprof12, uint8_t *swsetprof11, uint8_t *swsetprof10, uint8_t *swsetprof9, uint8_t *swsetprof8, uint8_t *swsetprof7, uint8_t *swsetprof6, uint8_t *swsetprof5, uint8_t *swsetprof4, uint8_t *swsetprof3, uint8_t *swsetprof2, uint8_t *swsetprof1, uint8_t *swsetprof0) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_SET_PROFILING_ADDR); + + *swsetprof31 = (localVal & ((uint32_t)0x80000000)) >> 31; + *swsetprof30 = (localVal & ((uint32_t)0x40000000)) >> 30; + *swsetprof29 = (localVal & ((uint32_t)0x20000000)) >> 29; + *swsetprof28 = (localVal & ((uint32_t)0x10000000)) >> 28; + *swsetprof27 = (localVal & ((uint32_t)0x08000000)) >> 27; + *swsetprof26 = (localVal & ((uint32_t)0x04000000)) >> 26; + *swsetprof25 = (localVal & ((uint32_t)0x02000000)) >> 25; + *swsetprof24 = (localVal & ((uint32_t)0x01000000)) >> 24; + *swsetprof23 = (localVal & ((uint32_t)0x00800000)) >> 23; + *swsetprof22 = (localVal & ((uint32_t)0x00400000)) >> 22; + *swsetprof21 = (localVal & ((uint32_t)0x00200000)) >> 21; + *swsetprof20 = (localVal & ((uint32_t)0x00100000)) >> 20; + *swsetprof19 = (localVal & ((uint32_t)0x00080000)) >> 19; + *swsetprof18 = (localVal & ((uint32_t)0x00040000)) >> 18; + *swsetprof17 = (localVal & ((uint32_t)0x00020000)) >> 17; + *swsetprof16 = (localVal & ((uint32_t)0x00010000)) >> 16; + *swsetprof15 = (localVal & ((uint32_t)0x00008000)) >> 15; + *swsetprof14 = (localVal & ((uint32_t)0x00004000)) >> 14; + *swsetprof13 = (localVal & ((uint32_t)0x00002000)) >> 13; + *swsetprof12 = (localVal & ((uint32_t)0x00001000)) >> 12; + *swsetprof11 = (localVal & ((uint32_t)0x00000800)) >> 11; + *swsetprof10 = (localVal & ((uint32_t)0x00000400)) >> 10; + *swsetprof9 = (localVal & ((uint32_t)0x00000200)) >> 9; + *swsetprof8 = (localVal & ((uint32_t)0x00000100)) >> 8; + *swsetprof7 = (localVal & ((uint32_t)0x00000080)) >> 7; + *swsetprof6 = (localVal & ((uint32_t)0x00000040)) >> 6; + *swsetprof5 = (localVal & ((uint32_t)0x00000020)) >> 5; + *swsetprof4 = (localVal & ((uint32_t)0x00000010)) >> 4; + *swsetprof3 = (localVal & ((uint32_t)0x00000008)) >> 3; + *swsetprof2 = (localVal & ((uint32_t)0x00000004)) >> 2; + *swsetprof1 = (localVal & ((uint32_t)0x00000002)) >> 1; + *swsetprof0 = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +/** + * @brief Returns the current value of the swSetProf31 field in the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read and the swSetProf31 field's value will be returned. + * + * @return The current value of the swSetProf31 field in the SW_SET_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_set_prof_31_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_SET_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +/** + * @brief Sets the swSetProf31 field of the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swsetprof31 - The value to set the field to. + */ +__INLINE void nxmac_sw_set_prof_31_setf(uint8_t swsetprof31) +{ + ASSERT_ERR((((uint32_t)swsetprof31 << 31) & ~((uint32_t)0x80000000)) == 0); + REG_PL_WR(NXMAC_SW_SET_PROFILING_ADDR, (uint32_t)swsetprof31 << 31); +} + +/** + * @brief Returns the current value of the swSetProf30 field in the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read and the swSetProf30 field's value will be returned. + * + * @return The current value of the swSetProf30 field in the SW_SET_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_set_prof_30_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_SET_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x40000000)) >> 30); +} + +/** + * @brief Sets the swSetProf30 field of the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swsetprof30 - The value to set the field to. + */ +__INLINE void nxmac_sw_set_prof_30_setf(uint8_t swsetprof30) +{ + ASSERT_ERR((((uint32_t)swsetprof30 << 30) & ~((uint32_t)0x40000000)) == 0); + REG_PL_WR(NXMAC_SW_SET_PROFILING_ADDR, (uint32_t)swsetprof30 << 30); +} + +/** + * @brief Returns the current value of the swSetProf29 field in the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read and the swSetProf29 field's value will be returned. + * + * @return The current value of the swSetProf29 field in the SW_SET_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_set_prof_29_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_SET_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x20000000)) >> 29); +} + +/** + * @brief Sets the swSetProf29 field of the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swsetprof29 - The value to set the field to. + */ +__INLINE void nxmac_sw_set_prof_29_setf(uint8_t swsetprof29) +{ + ASSERT_ERR((((uint32_t)swsetprof29 << 29) & ~((uint32_t)0x20000000)) == 0); + REG_PL_WR(NXMAC_SW_SET_PROFILING_ADDR, (uint32_t)swsetprof29 << 29); +} + +/** + * @brief Returns the current value of the swSetProf28 field in the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read and the swSetProf28 field's value will be returned. + * + * @return The current value of the swSetProf28 field in the SW_SET_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_set_prof_28_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_SET_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x10000000)) >> 28); +} + +/** + * @brief Sets the swSetProf28 field of the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swsetprof28 - The value to set the field to. + */ +__INLINE void nxmac_sw_set_prof_28_setf(uint8_t swsetprof28) +{ + ASSERT_ERR((((uint32_t)swsetprof28 << 28) & ~((uint32_t)0x10000000)) == 0); + REG_PL_WR(NXMAC_SW_SET_PROFILING_ADDR, (uint32_t)swsetprof28 << 28); +} + +/** + * @brief Returns the current value of the swSetProf27 field in the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read and the swSetProf27 field's value will be returned. + * + * @return The current value of the swSetProf27 field in the SW_SET_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_set_prof_27_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_SET_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x08000000)) >> 27); +} + +/** + * @brief Sets the swSetProf27 field of the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swsetprof27 - The value to set the field to. + */ +__INLINE void nxmac_sw_set_prof_27_setf(uint8_t swsetprof27) +{ + ASSERT_ERR((((uint32_t)swsetprof27 << 27) & ~((uint32_t)0x08000000)) == 0); + REG_PL_WR(NXMAC_SW_SET_PROFILING_ADDR, (uint32_t)swsetprof27 << 27); +} + +/** + * @brief Returns the current value of the swSetProf26 field in the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read and the swSetProf26 field's value will be returned. + * + * @return The current value of the swSetProf26 field in the SW_SET_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_set_prof_26_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_SET_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x04000000)) >> 26); +} + +/** + * @brief Sets the swSetProf26 field of the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swsetprof26 - The value to set the field to. + */ +__INLINE void nxmac_sw_set_prof_26_setf(uint8_t swsetprof26) +{ + ASSERT_ERR((((uint32_t)swsetprof26 << 26) & ~((uint32_t)0x04000000)) == 0); + REG_PL_WR(NXMAC_SW_SET_PROFILING_ADDR, (uint32_t)swsetprof26 << 26); +} + +/** + * @brief Returns the current value of the swSetProf25 field in the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read and the swSetProf25 field's value will be returned. + * + * @return The current value of the swSetProf25 field in the SW_SET_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_set_prof_25_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_SET_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x02000000)) >> 25); +} + +/** + * @brief Sets the swSetProf25 field of the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swsetprof25 - The value to set the field to. + */ +__INLINE void nxmac_sw_set_prof_25_setf(uint8_t swsetprof25) +{ + ASSERT_ERR((((uint32_t)swsetprof25 << 25) & ~((uint32_t)0x02000000)) == 0); + REG_PL_WR(NXMAC_SW_SET_PROFILING_ADDR, (uint32_t)swsetprof25 << 25); +} + +/** + * @brief Returns the current value of the swSetProf24 field in the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read and the swSetProf24 field's value will be returned. + * + * @return The current value of the swSetProf24 field in the SW_SET_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_set_prof_24_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_SET_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x01000000)) >> 24); +} + +/** + * @brief Sets the swSetProf24 field of the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swsetprof24 - The value to set the field to. + */ +__INLINE void nxmac_sw_set_prof_24_setf(uint8_t swsetprof24) +{ + ASSERT_ERR((((uint32_t)swsetprof24 << 24) & ~((uint32_t)0x01000000)) == 0); + REG_PL_WR(NXMAC_SW_SET_PROFILING_ADDR, (uint32_t)swsetprof24 << 24); +} + +/** + * @brief Returns the current value of the swSetProf23 field in the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read and the swSetProf23 field's value will be returned. + * + * @return The current value of the swSetProf23 field in the SW_SET_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_set_prof_23_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_SET_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00800000)) >> 23); +} + +/** + * @brief Sets the swSetProf23 field of the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swsetprof23 - The value to set the field to. + */ +__INLINE void nxmac_sw_set_prof_23_setf(uint8_t swsetprof23) +{ + ASSERT_ERR((((uint32_t)swsetprof23 << 23) & ~((uint32_t)0x00800000)) == 0); + REG_PL_WR(NXMAC_SW_SET_PROFILING_ADDR, (uint32_t)swsetprof23 << 23); +} + +/** + * @brief Returns the current value of the swSetProf22 field in the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read and the swSetProf22 field's value will be returned. + * + * @return The current value of the swSetProf22 field in the SW_SET_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_set_prof_22_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_SET_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00400000)) >> 22); +} + +/** + * @brief Sets the swSetProf22 field of the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swsetprof22 - The value to set the field to. + */ +__INLINE void nxmac_sw_set_prof_22_setf(uint8_t swsetprof22) +{ + ASSERT_ERR((((uint32_t)swsetprof22 << 22) & ~((uint32_t)0x00400000)) == 0); + REG_PL_WR(NXMAC_SW_SET_PROFILING_ADDR, (uint32_t)swsetprof22 << 22); +} + +/** + * @brief Returns the current value of the swSetProf21 field in the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read and the swSetProf21 field's value will be returned. + * + * @return The current value of the swSetProf21 field in the SW_SET_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_set_prof_21_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_SET_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00200000)) >> 21); +} + +/** + * @brief Sets the swSetProf21 field of the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swsetprof21 - The value to set the field to. + */ +__INLINE void nxmac_sw_set_prof_21_setf(uint8_t swsetprof21) +{ + ASSERT_ERR((((uint32_t)swsetprof21 << 21) & ~((uint32_t)0x00200000)) == 0); + REG_PL_WR(NXMAC_SW_SET_PROFILING_ADDR, (uint32_t)swsetprof21 << 21); +} + +/** + * @brief Returns the current value of the swSetProf20 field in the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read and the swSetProf20 field's value will be returned. + * + * @return The current value of the swSetProf20 field in the SW_SET_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_set_prof_20_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_SET_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00100000)) >> 20); +} + +/** + * @brief Sets the swSetProf20 field of the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swsetprof20 - The value to set the field to. + */ +__INLINE void nxmac_sw_set_prof_20_setf(uint8_t swsetprof20) +{ + ASSERT_ERR((((uint32_t)swsetprof20 << 20) & ~((uint32_t)0x00100000)) == 0); + REG_PL_WR(NXMAC_SW_SET_PROFILING_ADDR, (uint32_t)swsetprof20 << 20); +} + +/** + * @brief Returns the current value of the swSetProf19 field in the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read and the swSetProf19 field's value will be returned. + * + * @return The current value of the swSetProf19 field in the SW_SET_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_set_prof_19_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_SET_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00080000)) >> 19); +} + +/** + * @brief Sets the swSetProf19 field of the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swsetprof19 - The value to set the field to. + */ +__INLINE void nxmac_sw_set_prof_19_setf(uint8_t swsetprof19) +{ + ASSERT_ERR((((uint32_t)swsetprof19 << 19) & ~((uint32_t)0x00080000)) == 0); + REG_PL_WR(NXMAC_SW_SET_PROFILING_ADDR, (uint32_t)swsetprof19 << 19); +} + +/** + * @brief Returns the current value of the swSetProf18 field in the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read and the swSetProf18 field's value will be returned. + * + * @return The current value of the swSetProf18 field in the SW_SET_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_set_prof_18_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_SET_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00040000)) >> 18); +} + +/** + * @brief Sets the swSetProf18 field of the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swsetprof18 - The value to set the field to. + */ +__INLINE void nxmac_sw_set_prof_18_setf(uint8_t swsetprof18) +{ + ASSERT_ERR((((uint32_t)swsetprof18 << 18) & ~((uint32_t)0x00040000)) == 0); + REG_PL_WR(NXMAC_SW_SET_PROFILING_ADDR, (uint32_t)swsetprof18 << 18); +} + +/** + * @brief Returns the current value of the swSetProf17 field in the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read and the swSetProf17 field's value will be returned. + * + * @return The current value of the swSetProf17 field in the SW_SET_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_set_prof_17_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_SET_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00020000)) >> 17); +} + +/** + * @brief Sets the swSetProf17 field of the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swsetprof17 - The value to set the field to. + */ +__INLINE void nxmac_sw_set_prof_17_setf(uint8_t swsetprof17) +{ + ASSERT_ERR((((uint32_t)swsetprof17 << 17) & ~((uint32_t)0x00020000)) == 0); + REG_PL_WR(NXMAC_SW_SET_PROFILING_ADDR, (uint32_t)swsetprof17 << 17); +} + +/** + * @brief Returns the current value of the swSetProf16 field in the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read and the swSetProf16 field's value will be returned. + * + * @return The current value of the swSetProf16 field in the SW_SET_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_set_prof_16_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_SET_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00010000)) >> 16); +} + +/** + * @brief Sets the swSetProf16 field of the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swsetprof16 - The value to set the field to. + */ +__INLINE void nxmac_sw_set_prof_16_setf(uint8_t swsetprof16) +{ + ASSERT_ERR((((uint32_t)swsetprof16 << 16) & ~((uint32_t)0x00010000)) == 0); + REG_PL_WR(NXMAC_SW_SET_PROFILING_ADDR, (uint32_t)swsetprof16 << 16); +} + +/** + * @brief Returns the current value of the swSetProf15 field in the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read and the swSetProf15 field's value will be returned. + * + * @return The current value of the swSetProf15 field in the SW_SET_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_set_prof_15_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_SET_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00008000)) >> 15); +} + +/** + * @brief Sets the swSetProf15 field of the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swsetprof15 - The value to set the field to. + */ +__INLINE void nxmac_sw_set_prof_15_setf(uint8_t swsetprof15) +{ + ASSERT_ERR((((uint32_t)swsetprof15 << 15) & ~((uint32_t)0x00008000)) == 0); + REG_PL_WR(NXMAC_SW_SET_PROFILING_ADDR, (uint32_t)swsetprof15 << 15); +} + +/** + * @brief Returns the current value of the swSetProf14 field in the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read and the swSetProf14 field's value will be returned. + * + * @return The current value of the swSetProf14 field in the SW_SET_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_set_prof_14_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_SET_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00004000)) >> 14); +} + +/** + * @brief Sets the swSetProf14 field of the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swsetprof14 - The value to set the field to. + */ +__INLINE void nxmac_sw_set_prof_14_setf(uint8_t swsetprof14) +{ + ASSERT_ERR((((uint32_t)swsetprof14 << 14) & ~((uint32_t)0x00004000)) == 0); + REG_PL_WR(NXMAC_SW_SET_PROFILING_ADDR, (uint32_t)swsetprof14 << 14); +} + +/** + * @brief Returns the current value of the swSetProf13 field in the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read and the swSetProf13 field's value will be returned. + * + * @return The current value of the swSetProf13 field in the SW_SET_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_set_prof_13_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_SET_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00002000)) >> 13); +} + +/** + * @brief Sets the swSetProf13 field of the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swsetprof13 - The value to set the field to. + */ +__INLINE void nxmac_sw_set_prof_13_setf(uint8_t swsetprof13) +{ + ASSERT_ERR((((uint32_t)swsetprof13 << 13) & ~((uint32_t)0x00002000)) == 0); + REG_PL_WR(NXMAC_SW_SET_PROFILING_ADDR, (uint32_t)swsetprof13 << 13); +} + +/** + * @brief Returns the current value of the swSetProf12 field in the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read and the swSetProf12 field's value will be returned. + * + * @return The current value of the swSetProf12 field in the SW_SET_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_set_prof_12_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_SET_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00001000)) >> 12); +} + +/** + * @brief Sets the swSetProf12 field of the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swsetprof12 - The value to set the field to. + */ +__INLINE void nxmac_sw_set_prof_12_setf(uint8_t swsetprof12) +{ + ASSERT_ERR((((uint32_t)swsetprof12 << 12) & ~((uint32_t)0x00001000)) == 0); + REG_PL_WR(NXMAC_SW_SET_PROFILING_ADDR, (uint32_t)swsetprof12 << 12); +} + +/** + * @brief Returns the current value of the swSetProf11 field in the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read and the swSetProf11 field's value will be returned. + * + * @return The current value of the swSetProf11 field in the SW_SET_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_set_prof_11_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_SET_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000800)) >> 11); +} + +/** + * @brief Sets the swSetProf11 field of the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swsetprof11 - The value to set the field to. + */ +__INLINE void nxmac_sw_set_prof_11_setf(uint8_t swsetprof11) +{ + ASSERT_ERR((((uint32_t)swsetprof11 << 11) & ~((uint32_t)0x00000800)) == 0); + REG_PL_WR(NXMAC_SW_SET_PROFILING_ADDR, (uint32_t)swsetprof11 << 11); +} + +/** + * @brief Returns the current value of the swSetProf10 field in the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read and the swSetProf10 field's value will be returned. + * + * @return The current value of the swSetProf10 field in the SW_SET_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_set_prof_10_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_SET_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000400)) >> 10); +} + +/** + * @brief Sets the swSetProf10 field of the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swsetprof10 - The value to set the field to. + */ +__INLINE void nxmac_sw_set_prof_10_setf(uint8_t swsetprof10) +{ + ASSERT_ERR((((uint32_t)swsetprof10 << 10) & ~((uint32_t)0x00000400)) == 0); + REG_PL_WR(NXMAC_SW_SET_PROFILING_ADDR, (uint32_t)swsetprof10 << 10); +} + +/** + * @brief Returns the current value of the swSetProf9 field in the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read and the swSetProf9 field's value will be returned. + * + * @return The current value of the swSetProf9 field in the SW_SET_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_set_prof_9_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_SET_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000200)) >> 9); +} + +/** + * @brief Sets the swSetProf9 field of the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swsetprof9 - The value to set the field to. + */ +__INLINE void nxmac_sw_set_prof_9_setf(uint8_t swsetprof9) +{ + ASSERT_ERR((((uint32_t)swsetprof9 << 9) & ~((uint32_t)0x00000200)) == 0); + REG_PL_WR(NXMAC_SW_SET_PROFILING_ADDR, (uint32_t)swsetprof9 << 9); +} + +/** + * @brief Returns the current value of the swSetProf8 field in the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read and the swSetProf8 field's value will be returned. + * + * @return The current value of the swSetProf8 field in the SW_SET_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_set_prof_8_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_SET_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000100)) >> 8); +} + +/** + * @brief Sets the swSetProf8 field of the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swsetprof8 - The value to set the field to. + */ +__INLINE void nxmac_sw_set_prof_8_setf(uint8_t swsetprof8) +{ + ASSERT_ERR((((uint32_t)swsetprof8 << 8) & ~((uint32_t)0x00000100)) == 0); + REG_PL_WR(NXMAC_SW_SET_PROFILING_ADDR, (uint32_t)swsetprof8 << 8); +} + +/** + * @brief Returns the current value of the swSetProf7 field in the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read and the swSetProf7 field's value will be returned. + * + * @return The current value of the swSetProf7 field in the SW_SET_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_set_prof_7_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_SET_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000080)) >> 7); +} + +/** + * @brief Sets the swSetProf7 field of the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swsetprof7 - The value to set the field to. + */ +__INLINE void nxmac_sw_set_prof_7_setf(uint8_t swsetprof7) +{ + ASSERT_ERR((((uint32_t)swsetprof7 << 7) & ~((uint32_t)0x00000080)) == 0); + REG_PL_WR(NXMAC_SW_SET_PROFILING_ADDR, (uint32_t)swsetprof7 << 7); +} + +/** + * @brief Returns the current value of the swSetProf6 field in the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read and the swSetProf6 field's value will be returned. + * + * @return The current value of the swSetProf6 field in the SW_SET_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_set_prof_6_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_SET_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000040)) >> 6); +} + +/** + * @brief Sets the swSetProf6 field of the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swsetprof6 - The value to set the field to. + */ +__INLINE void nxmac_sw_set_prof_6_setf(uint8_t swsetprof6) +{ + ASSERT_ERR((((uint32_t)swsetprof6 << 6) & ~((uint32_t)0x00000040)) == 0); + REG_PL_WR(NXMAC_SW_SET_PROFILING_ADDR, (uint32_t)swsetprof6 << 6); +} + +/** + * @brief Returns the current value of the swSetProf5 field in the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read and the swSetProf5 field's value will be returned. + * + * @return The current value of the swSetProf5 field in the SW_SET_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_set_prof_5_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_SET_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +/** + * @brief Sets the swSetProf5 field of the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swsetprof5 - The value to set the field to. + */ +__INLINE void nxmac_sw_set_prof_5_setf(uint8_t swsetprof5) +{ + ASSERT_ERR((((uint32_t)swsetprof5 << 5) & ~((uint32_t)0x00000020)) == 0); + REG_PL_WR(NXMAC_SW_SET_PROFILING_ADDR, (uint32_t)swsetprof5 << 5); +} + +/** + * @brief Returns the current value of the swSetProf4 field in the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read and the swSetProf4 field's value will be returned. + * + * @return The current value of the swSetProf4 field in the SW_SET_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_set_prof_4_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_SET_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +/** + * @brief Sets the swSetProf4 field of the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swsetprof4 - The value to set the field to. + */ +__INLINE void nxmac_sw_set_prof_4_setf(uint8_t swsetprof4) +{ + ASSERT_ERR((((uint32_t)swsetprof4 << 4) & ~((uint32_t)0x00000010)) == 0); + REG_PL_WR(NXMAC_SW_SET_PROFILING_ADDR, (uint32_t)swsetprof4 << 4); +} + +/** + * @brief Returns the current value of the swSetProf3 field in the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read and the swSetProf3 field's value will be returned. + * + * @return The current value of the swSetProf3 field in the SW_SET_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_set_prof_3_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_SET_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +/** + * @brief Sets the swSetProf3 field of the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swsetprof3 - The value to set the field to. + */ +__INLINE void nxmac_sw_set_prof_3_setf(uint8_t swsetprof3) +{ + ASSERT_ERR((((uint32_t)swsetprof3 << 3) & ~((uint32_t)0x00000008)) == 0); + REG_PL_WR(NXMAC_SW_SET_PROFILING_ADDR, (uint32_t)swsetprof3 << 3); +} + +/** + * @brief Returns the current value of the swSetProf2 field in the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read and the swSetProf2 field's value will be returned. + * + * @return The current value of the swSetProf2 field in the SW_SET_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_set_prof_2_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_SET_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +/** + * @brief Sets the swSetProf2 field of the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swsetprof2 - The value to set the field to. + */ +__INLINE void nxmac_sw_set_prof_2_setf(uint8_t swsetprof2) +{ + ASSERT_ERR((((uint32_t)swsetprof2 << 2) & ~((uint32_t)0x00000004)) == 0); + REG_PL_WR(NXMAC_SW_SET_PROFILING_ADDR, (uint32_t)swsetprof2 << 2); +} + +/** + * @brief Returns the current value of the swSetProf1 field in the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read and the swSetProf1 field's value will be returned. + * + * @return The current value of the swSetProf1 field in the SW_SET_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_set_prof_1_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_SET_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +/** + * @brief Sets the swSetProf1 field of the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swsetprof1 - The value to set the field to. + */ +__INLINE void nxmac_sw_set_prof_1_setf(uint8_t swsetprof1) +{ + ASSERT_ERR((((uint32_t)swsetprof1 << 1) & ~((uint32_t)0x00000002)) == 0); + REG_PL_WR(NXMAC_SW_SET_PROFILING_ADDR, (uint32_t)swsetprof1 << 1); +} + +/** + * @brief Returns the current value of the swSetProf0 field in the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read and the swSetProf0 field's value will be returned. + * + * @return The current value of the swSetProf0 field in the SW_SET_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_set_prof_0_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_SET_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/** + * @brief Sets the swSetProf0 field of the SW_SET_PROFILING register. + * + * The SW_SET_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swsetprof0 - The value to set the field to. + */ +__INLINE void nxmac_sw_set_prof_0_setf(uint8_t swsetprof0) +{ + ASSERT_ERR((((uint32_t)swsetprof0 << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_SW_SET_PROFILING_ADDR, (uint32_t)swsetprof0 << 0); +} + +/// @} + +/** + * @name SW_CLEAR_PROFILING register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31        swClearProf31   0
+ *     30        swClearProf30   0
+ *     29        swClearProf29   0
+ *     28        swClearProf28   0
+ *     27        swClearProf27   0
+ *     26        swClearProf26   0
+ *     25        swClearProf25   0
+ *     24        swClearProf24   0
+ *     23        swClearProf23   0
+ *     22        swClearProf22   0
+ *     21        swClearProf21   0
+ *     20        swClearProf20   0
+ *     19        swClearProf19   0
+ *     18        swClearProf18   0
+ *     17        swClearProf17   0
+ *     16        swClearProf16   0
+ *     15        swClearProf15   0
+ *     14        swClearProf14   0
+ *     13        swClearProf13   0
+ *     12        swClearProf12   0
+ *     11        swClearProf11   0
+ *     10        swClearProf10   0
+ *     09         swClearProf9   0
+ *     08         swClearProf8   0
+ *     07         swClearProf7   0
+ *     06         swClearProf6   0
+ *     05         swClearProf5   0
+ *     04         swClearProf4   0
+ *     03         swClearProf3   0
+ *     02         swClearProf2   0
+ *     01         swClearProf1   0
+ *     00         swClearProf0   0
+ * 
+ * + * @{ + */ + +/// Address of the SW_CLEAR_PROFILING register +#define NXMAC_SW_CLEAR_PROFILING_ADDR 0xC0008568 +/// Offset of the SW_CLEAR_PROFILING register from the base address +#define NXMAC_SW_CLEAR_PROFILING_OFFSET 0x00000568 +/// Index of the SW_CLEAR_PROFILING register +#define NXMAC_SW_CLEAR_PROFILING_INDEX 0x0000015A +/// Reset value of the SW_CLEAR_PROFILING register +#define NXMAC_SW_CLEAR_PROFILING_RESET 0x00000000 + +/** + * @brief Returns the current value of the SW_CLEAR_PROFILING register. + * The SW_CLEAR_PROFILING register will be read and its value returned. + * @return The current value of the SW_CLEAR_PROFILING register. + */ +__INLINE uint32_t nxmac_sw_clear_profiling_get(void) +{ + return REG_PL_RD(NXMAC_SW_CLEAR_PROFILING_ADDR); +} + +/** + * @brief Sets the SW_CLEAR_PROFILING register to a value. + * The SW_CLEAR_PROFILING register will be written. + * @param value - The value to write. + */ +__INLINE void nxmac_sw_clear_profiling_clear(uint32_t value) +{ + REG_PL_WR(NXMAC_SW_CLEAR_PROFILING_ADDR, value); +} + +// field definitions +/// SW_CLEAR_PROF_31 field bit +#define NXMAC_SW_CLEAR_PROF_31_BIT ((uint32_t)0x80000000) +/// SW_CLEAR_PROF_31 field position +#define NXMAC_SW_CLEAR_PROF_31_POS 31 +/// SW_CLEAR_PROF_30 field bit +#define NXMAC_SW_CLEAR_PROF_30_BIT ((uint32_t)0x40000000) +/// SW_CLEAR_PROF_30 field position +#define NXMAC_SW_CLEAR_PROF_30_POS 30 +/// SW_CLEAR_PROF_29 field bit +#define NXMAC_SW_CLEAR_PROF_29_BIT ((uint32_t)0x20000000) +/// SW_CLEAR_PROF_29 field position +#define NXMAC_SW_CLEAR_PROF_29_POS 29 +/// SW_CLEAR_PROF_28 field bit +#define NXMAC_SW_CLEAR_PROF_28_BIT ((uint32_t)0x10000000) +/// SW_CLEAR_PROF_28 field position +#define NXMAC_SW_CLEAR_PROF_28_POS 28 +/// SW_CLEAR_PROF_27 field bit +#define NXMAC_SW_CLEAR_PROF_27_BIT ((uint32_t)0x08000000) +/// SW_CLEAR_PROF_27 field position +#define NXMAC_SW_CLEAR_PROF_27_POS 27 +/// SW_CLEAR_PROF_26 field bit +#define NXMAC_SW_CLEAR_PROF_26_BIT ((uint32_t)0x04000000) +/// SW_CLEAR_PROF_26 field position +#define NXMAC_SW_CLEAR_PROF_26_POS 26 +/// SW_CLEAR_PROF_25 field bit +#define NXMAC_SW_CLEAR_PROF_25_BIT ((uint32_t)0x02000000) +/// SW_CLEAR_PROF_25 field position +#define NXMAC_SW_CLEAR_PROF_25_POS 25 +/// SW_CLEAR_PROF_24 field bit +#define NXMAC_SW_CLEAR_PROF_24_BIT ((uint32_t)0x01000000) +/// SW_CLEAR_PROF_24 field position +#define NXMAC_SW_CLEAR_PROF_24_POS 24 +/// SW_CLEAR_PROF_23 field bit +#define NXMAC_SW_CLEAR_PROF_23_BIT ((uint32_t)0x00800000) +/// SW_CLEAR_PROF_23 field position +#define NXMAC_SW_CLEAR_PROF_23_POS 23 +/// SW_CLEAR_PROF_22 field bit +#define NXMAC_SW_CLEAR_PROF_22_BIT ((uint32_t)0x00400000) +/// SW_CLEAR_PROF_22 field position +#define NXMAC_SW_CLEAR_PROF_22_POS 22 +/// SW_CLEAR_PROF_21 field bit +#define NXMAC_SW_CLEAR_PROF_21_BIT ((uint32_t)0x00200000) +/// SW_CLEAR_PROF_21 field position +#define NXMAC_SW_CLEAR_PROF_21_POS 21 +/// SW_CLEAR_PROF_20 field bit +#define NXMAC_SW_CLEAR_PROF_20_BIT ((uint32_t)0x00100000) +/// SW_CLEAR_PROF_20 field position +#define NXMAC_SW_CLEAR_PROF_20_POS 20 +/// SW_CLEAR_PROF_19 field bit +#define NXMAC_SW_CLEAR_PROF_19_BIT ((uint32_t)0x00080000) +/// SW_CLEAR_PROF_19 field position +#define NXMAC_SW_CLEAR_PROF_19_POS 19 +/// SW_CLEAR_PROF_18 field bit +#define NXMAC_SW_CLEAR_PROF_18_BIT ((uint32_t)0x00040000) +/// SW_CLEAR_PROF_18 field position +#define NXMAC_SW_CLEAR_PROF_18_POS 18 +/// SW_CLEAR_PROF_17 field bit +#define NXMAC_SW_CLEAR_PROF_17_BIT ((uint32_t)0x00020000) +/// SW_CLEAR_PROF_17 field position +#define NXMAC_SW_CLEAR_PROF_17_POS 17 +/// SW_CLEAR_PROF_16 field bit +#define NXMAC_SW_CLEAR_PROF_16_BIT ((uint32_t)0x00010000) +/// SW_CLEAR_PROF_16 field position +#define NXMAC_SW_CLEAR_PROF_16_POS 16 +/// SW_CLEAR_PROF_15 field bit +#define NXMAC_SW_CLEAR_PROF_15_BIT ((uint32_t)0x00008000) +/// SW_CLEAR_PROF_15 field position +#define NXMAC_SW_CLEAR_PROF_15_POS 15 +/// SW_CLEAR_PROF_14 field bit +#define NXMAC_SW_CLEAR_PROF_14_BIT ((uint32_t)0x00004000) +/// SW_CLEAR_PROF_14 field position +#define NXMAC_SW_CLEAR_PROF_14_POS 14 +/// SW_CLEAR_PROF_13 field bit +#define NXMAC_SW_CLEAR_PROF_13_BIT ((uint32_t)0x00002000) +/// SW_CLEAR_PROF_13 field position +#define NXMAC_SW_CLEAR_PROF_13_POS 13 +/// SW_CLEAR_PROF_12 field bit +#define NXMAC_SW_CLEAR_PROF_12_BIT ((uint32_t)0x00001000) +/// SW_CLEAR_PROF_12 field position +#define NXMAC_SW_CLEAR_PROF_12_POS 12 +/// SW_CLEAR_PROF_11 field bit +#define NXMAC_SW_CLEAR_PROF_11_BIT ((uint32_t)0x00000800) +/// SW_CLEAR_PROF_11 field position +#define NXMAC_SW_CLEAR_PROF_11_POS 11 +/// SW_CLEAR_PROF_10 field bit +#define NXMAC_SW_CLEAR_PROF_10_BIT ((uint32_t)0x00000400) +/// SW_CLEAR_PROF_10 field position +#define NXMAC_SW_CLEAR_PROF_10_POS 10 +/// SW_CLEAR_PROF_9 field bit +#define NXMAC_SW_CLEAR_PROF_9_BIT ((uint32_t)0x00000200) +/// SW_CLEAR_PROF_9 field position +#define NXMAC_SW_CLEAR_PROF_9_POS 9 +/// SW_CLEAR_PROF_8 field bit +#define NXMAC_SW_CLEAR_PROF_8_BIT ((uint32_t)0x00000100) +/// SW_CLEAR_PROF_8 field position +#define NXMAC_SW_CLEAR_PROF_8_POS 8 +/// SW_CLEAR_PROF_7 field bit +#define NXMAC_SW_CLEAR_PROF_7_BIT ((uint32_t)0x00000080) +/// SW_CLEAR_PROF_7 field position +#define NXMAC_SW_CLEAR_PROF_7_POS 7 +/// SW_CLEAR_PROF_6 field bit +#define NXMAC_SW_CLEAR_PROF_6_BIT ((uint32_t)0x00000040) +/// SW_CLEAR_PROF_6 field position +#define NXMAC_SW_CLEAR_PROF_6_POS 6 +/// SW_CLEAR_PROF_5 field bit +#define NXMAC_SW_CLEAR_PROF_5_BIT ((uint32_t)0x00000020) +/// SW_CLEAR_PROF_5 field position +#define NXMAC_SW_CLEAR_PROF_5_POS 5 +/// SW_CLEAR_PROF_4 field bit +#define NXMAC_SW_CLEAR_PROF_4_BIT ((uint32_t)0x00000010) +/// SW_CLEAR_PROF_4 field position +#define NXMAC_SW_CLEAR_PROF_4_POS 4 +/// SW_CLEAR_PROF_3 field bit +#define NXMAC_SW_CLEAR_PROF_3_BIT ((uint32_t)0x00000008) +/// SW_CLEAR_PROF_3 field position +#define NXMAC_SW_CLEAR_PROF_3_POS 3 +/// SW_CLEAR_PROF_2 field bit +#define NXMAC_SW_CLEAR_PROF_2_BIT ((uint32_t)0x00000004) +/// SW_CLEAR_PROF_2 field position +#define NXMAC_SW_CLEAR_PROF_2_POS 2 +/// SW_CLEAR_PROF_1 field bit +#define NXMAC_SW_CLEAR_PROF_1_BIT ((uint32_t)0x00000002) +/// SW_CLEAR_PROF_1 field position +#define NXMAC_SW_CLEAR_PROF_1_POS 1 +/// SW_CLEAR_PROF_0 field bit +#define NXMAC_SW_CLEAR_PROF_0_BIT ((uint32_t)0x00000001) +/// SW_CLEAR_PROF_0 field position +#define NXMAC_SW_CLEAR_PROF_0_POS 0 + +/// SW_CLEAR_PROF_31 field reset value +#define NXMAC_SW_CLEAR_PROF_31_RST 0x0 +/// SW_CLEAR_PROF_30 field reset value +#define NXMAC_SW_CLEAR_PROF_30_RST 0x0 +/// SW_CLEAR_PROF_29 field reset value +#define NXMAC_SW_CLEAR_PROF_29_RST 0x0 +/// SW_CLEAR_PROF_28 field reset value +#define NXMAC_SW_CLEAR_PROF_28_RST 0x0 +/// SW_CLEAR_PROF_27 field reset value +#define NXMAC_SW_CLEAR_PROF_27_RST 0x0 +/// SW_CLEAR_PROF_26 field reset value +#define NXMAC_SW_CLEAR_PROF_26_RST 0x0 +/// SW_CLEAR_PROF_25 field reset value +#define NXMAC_SW_CLEAR_PROF_25_RST 0x0 +/// SW_CLEAR_PROF_24 field reset value +#define NXMAC_SW_CLEAR_PROF_24_RST 0x0 +/// SW_CLEAR_PROF_23 field reset value +#define NXMAC_SW_CLEAR_PROF_23_RST 0x0 +/// SW_CLEAR_PROF_22 field reset value +#define NXMAC_SW_CLEAR_PROF_22_RST 0x0 +/// SW_CLEAR_PROF_21 field reset value +#define NXMAC_SW_CLEAR_PROF_21_RST 0x0 +/// SW_CLEAR_PROF_20 field reset value +#define NXMAC_SW_CLEAR_PROF_20_RST 0x0 +/// SW_CLEAR_PROF_19 field reset value +#define NXMAC_SW_CLEAR_PROF_19_RST 0x0 +/// SW_CLEAR_PROF_18 field reset value +#define NXMAC_SW_CLEAR_PROF_18_RST 0x0 +/// SW_CLEAR_PROF_17 field reset value +#define NXMAC_SW_CLEAR_PROF_17_RST 0x0 +/// SW_CLEAR_PROF_16 field reset value +#define NXMAC_SW_CLEAR_PROF_16_RST 0x0 +/// SW_CLEAR_PROF_15 field reset value +#define NXMAC_SW_CLEAR_PROF_15_RST 0x0 +/// SW_CLEAR_PROF_14 field reset value +#define NXMAC_SW_CLEAR_PROF_14_RST 0x0 +/// SW_CLEAR_PROF_13 field reset value +#define NXMAC_SW_CLEAR_PROF_13_RST 0x0 +/// SW_CLEAR_PROF_12 field reset value +#define NXMAC_SW_CLEAR_PROF_12_RST 0x0 +/// SW_CLEAR_PROF_11 field reset value +#define NXMAC_SW_CLEAR_PROF_11_RST 0x0 +/// SW_CLEAR_PROF_10 field reset value +#define NXMAC_SW_CLEAR_PROF_10_RST 0x0 +/// SW_CLEAR_PROF_9 field reset value +#define NXMAC_SW_CLEAR_PROF_9_RST 0x0 +/// SW_CLEAR_PROF_8 field reset value +#define NXMAC_SW_CLEAR_PROF_8_RST 0x0 +/// SW_CLEAR_PROF_7 field reset value +#define NXMAC_SW_CLEAR_PROF_7_RST 0x0 +/// SW_CLEAR_PROF_6 field reset value +#define NXMAC_SW_CLEAR_PROF_6_RST 0x0 +/// SW_CLEAR_PROF_5 field reset value +#define NXMAC_SW_CLEAR_PROF_5_RST 0x0 +/// SW_CLEAR_PROF_4 field reset value +#define NXMAC_SW_CLEAR_PROF_4_RST 0x0 +/// SW_CLEAR_PROF_3 field reset value +#define NXMAC_SW_CLEAR_PROF_3_RST 0x0 +/// SW_CLEAR_PROF_2 field reset value +#define NXMAC_SW_CLEAR_PROF_2_RST 0x0 +/// SW_CLEAR_PROF_1 field reset value +#define NXMAC_SW_CLEAR_PROF_1_RST 0x0 +/// SW_CLEAR_PROF_0 field reset value +#define NXMAC_SW_CLEAR_PROF_0_RST 0x0 + +/** + * @brief Constructs a value for the SW_CLEAR_PROFILING register given values for its fields + * and writes the value to the register. + * + * @param[in] swclearprof31 - The value to use for the swClearProf31 field. + * @param[in] swclearprof30 - The value to use for the swClearProf30 field. + * @param[in] swclearprof29 - The value to use for the swClearProf29 field. + * @param[in] swclearprof28 - The value to use for the swClearProf28 field. + * @param[in] swclearprof27 - The value to use for the swClearProf27 field. + * @param[in] swclearprof26 - The value to use for the swClearProf26 field. + * @param[in] swclearprof25 - The value to use for the swClearProf25 field. + * @param[in] swclearprof24 - The value to use for the swClearProf24 field. + * @param[in] swclearprof23 - The value to use for the swClearProf23 field. + * @param[in] swclearprof22 - The value to use for the swClearProf22 field. + * @param[in] swclearprof21 - The value to use for the swClearProf21 field. + * @param[in] swclearprof20 - The value to use for the swClearProf20 field. + * @param[in] swclearprof19 - The value to use for the swClearProf19 field. + * @param[in] swclearprof18 - The value to use for the swClearProf18 field. + * @param[in] swclearprof17 - The value to use for the swClearProf17 field. + * @param[in] swclearprof16 - The value to use for the swClearProf16 field. + * @param[in] swclearprof15 - The value to use for the swClearProf15 field. + * @param[in] swclearprof14 - The value to use for the swClearProf14 field. + * @param[in] swclearprof13 - The value to use for the swClearProf13 field. + * @param[in] swclearprof12 - The value to use for the swClearProf12 field. + * @param[in] swclearprof11 - The value to use for the swClearProf11 field. + * @param[in] swclearprof10 - The value to use for the swClearProf10 field. + * @param[in] swclearprof9 - The value to use for the swClearProf9 field. + * @param[in] swclearprof8 - The value to use for the swClearProf8 field. + * @param[in] swclearprof7 - The value to use for the swClearProf7 field. + * @param[in] swclearprof6 - The value to use for the swClearProf6 field. + * @param[in] swclearprof5 - The value to use for the swClearProf5 field. + * @param[in] swclearprof4 - The value to use for the swClearProf4 field. + * @param[in] swclearprof3 - The value to use for the swClearProf3 field. + * @param[in] swclearprof2 - The value to use for the swClearProf2 field. + * @param[in] swclearprof1 - The value to use for the swClearProf1 field. + * @param[in] swclearprof0 - The value to use for the swClearProf0 field. + */ +__INLINE void nxmac_sw_clear_profiling_pack(uint8_t swclearprof31, uint8_t swclearprof30, uint8_t swclearprof29, uint8_t swclearprof28, uint8_t swclearprof27, uint8_t swclearprof26, uint8_t swclearprof25, uint8_t swclearprof24, uint8_t swclearprof23, uint8_t swclearprof22, uint8_t swclearprof21, uint8_t swclearprof20, uint8_t swclearprof19, uint8_t swclearprof18, uint8_t swclearprof17, uint8_t swclearprof16, uint8_t swclearprof15, uint8_t swclearprof14, uint8_t swclearprof13, uint8_t swclearprof12, uint8_t swclearprof11, uint8_t swclearprof10, uint8_t swclearprof9, uint8_t swclearprof8, uint8_t swclearprof7, uint8_t swclearprof6, uint8_t swclearprof5, uint8_t swclearprof4, uint8_t swclearprof3, uint8_t swclearprof2, uint8_t swclearprof1, uint8_t swclearprof0) +{ + ASSERT_ERR((((uint32_t)swclearprof31 << 31) & ~((uint32_t)0x80000000)) == 0); + ASSERT_ERR((((uint32_t)swclearprof30 << 30) & ~((uint32_t)0x40000000)) == 0); + ASSERT_ERR((((uint32_t)swclearprof29 << 29) & ~((uint32_t)0x20000000)) == 0); + ASSERT_ERR((((uint32_t)swclearprof28 << 28) & ~((uint32_t)0x10000000)) == 0); + ASSERT_ERR((((uint32_t)swclearprof27 << 27) & ~((uint32_t)0x08000000)) == 0); + ASSERT_ERR((((uint32_t)swclearprof26 << 26) & ~((uint32_t)0x04000000)) == 0); + ASSERT_ERR((((uint32_t)swclearprof25 << 25) & ~((uint32_t)0x02000000)) == 0); + ASSERT_ERR((((uint32_t)swclearprof24 << 24) & ~((uint32_t)0x01000000)) == 0); + ASSERT_ERR((((uint32_t)swclearprof23 << 23) & ~((uint32_t)0x00800000)) == 0); + ASSERT_ERR((((uint32_t)swclearprof22 << 22) & ~((uint32_t)0x00400000)) == 0); + ASSERT_ERR((((uint32_t)swclearprof21 << 21) & ~((uint32_t)0x00200000)) == 0); + ASSERT_ERR((((uint32_t)swclearprof20 << 20) & ~((uint32_t)0x00100000)) == 0); + ASSERT_ERR((((uint32_t)swclearprof19 << 19) & ~((uint32_t)0x00080000)) == 0); + ASSERT_ERR((((uint32_t)swclearprof18 << 18) & ~((uint32_t)0x00040000)) == 0); + ASSERT_ERR((((uint32_t)swclearprof17 << 17) & ~((uint32_t)0x00020000)) == 0); + ASSERT_ERR((((uint32_t)swclearprof16 << 16) & ~((uint32_t)0x00010000)) == 0); + ASSERT_ERR((((uint32_t)swclearprof15 << 15) & ~((uint32_t)0x00008000)) == 0); + ASSERT_ERR((((uint32_t)swclearprof14 << 14) & ~((uint32_t)0x00004000)) == 0); + ASSERT_ERR((((uint32_t)swclearprof13 << 13) & ~((uint32_t)0x00002000)) == 0); + ASSERT_ERR((((uint32_t)swclearprof12 << 12) & ~((uint32_t)0x00001000)) == 0); + ASSERT_ERR((((uint32_t)swclearprof11 << 11) & ~((uint32_t)0x00000800)) == 0); + ASSERT_ERR((((uint32_t)swclearprof10 << 10) & ~((uint32_t)0x00000400)) == 0); + ASSERT_ERR((((uint32_t)swclearprof9 << 9) & ~((uint32_t)0x00000200)) == 0); + ASSERT_ERR((((uint32_t)swclearprof8 << 8) & ~((uint32_t)0x00000100)) == 0); + ASSERT_ERR((((uint32_t)swclearprof7 << 7) & ~((uint32_t)0x00000080)) == 0); + ASSERT_ERR((((uint32_t)swclearprof6 << 6) & ~((uint32_t)0x00000040)) == 0); + ASSERT_ERR((((uint32_t)swclearprof5 << 5) & ~((uint32_t)0x00000020)) == 0); + ASSERT_ERR((((uint32_t)swclearprof4 << 4) & ~((uint32_t)0x00000010)) == 0); + ASSERT_ERR((((uint32_t)swclearprof3 << 3) & ~((uint32_t)0x00000008)) == 0); + ASSERT_ERR((((uint32_t)swclearprof2 << 2) & ~((uint32_t)0x00000004)) == 0); + ASSERT_ERR((((uint32_t)swclearprof1 << 1) & ~((uint32_t)0x00000002)) == 0); + ASSERT_ERR((((uint32_t)swclearprof0 << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_SW_CLEAR_PROFILING_ADDR, ((uint32_t)swclearprof31 << 31) | ((uint32_t)swclearprof30 << 30) | ((uint32_t)swclearprof29 << 29) | ((uint32_t)swclearprof28 << 28) | ((uint32_t)swclearprof27 << 27) | ((uint32_t)swclearprof26 << 26) | ((uint32_t)swclearprof25 << 25) | ((uint32_t)swclearprof24 << 24) | ((uint32_t)swclearprof23 << 23) | ((uint32_t)swclearprof22 << 22) | ((uint32_t)swclearprof21 << 21) | ((uint32_t)swclearprof20 << 20) | ((uint32_t)swclearprof19 << 19) | ((uint32_t)swclearprof18 << 18) | ((uint32_t)swclearprof17 << 17) | ((uint32_t)swclearprof16 << 16) | ((uint32_t)swclearprof15 << 15) | ((uint32_t)swclearprof14 << 14) | ((uint32_t)swclearprof13 << 13) | ((uint32_t)swclearprof12 << 12) | ((uint32_t)swclearprof11 << 11) | ((uint32_t)swclearprof10 << 10) | ((uint32_t)swclearprof9 << 9) | ((uint32_t)swclearprof8 << 8) | ((uint32_t)swclearprof7 << 7) | ((uint32_t)swclearprof6 << 6) | ((uint32_t)swclearprof5 << 5) | ((uint32_t)swclearprof4 << 4) | ((uint32_t)swclearprof3 << 3) | ((uint32_t)swclearprof2 << 2) | ((uint32_t)swclearprof1 << 1) | ((uint32_t)swclearprof0 << 0)); +} + +/** + * @brief Unpacks SW_CLEAR_PROFILING's fields from current value of the SW_CLEAR_PROFILING register. + * + * Reads the SW_CLEAR_PROFILING register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] swclearprof31 - Will be populated with the current value of this field from the register. + * @param[out] swclearprof30 - Will be populated with the current value of this field from the register. + * @param[out] swclearprof29 - Will be populated with the current value of this field from the register. + * @param[out] swclearprof28 - Will be populated with the current value of this field from the register. + * @param[out] swclearprof27 - Will be populated with the current value of this field from the register. + * @param[out] swclearprof26 - Will be populated with the current value of this field from the register. + * @param[out] swclearprof25 - Will be populated with the current value of this field from the register. + * @param[out] swclearprof24 - Will be populated with the current value of this field from the register. + * @param[out] swclearprof23 - Will be populated with the current value of this field from the register. + * @param[out] swclearprof22 - Will be populated with the current value of this field from the register. + * @param[out] swclearprof21 - Will be populated with the current value of this field from the register. + * @param[out] swclearprof20 - Will be populated with the current value of this field from the register. + * @param[out] swclearprof19 - Will be populated with the current value of this field from the register. + * @param[out] swclearprof18 - Will be populated with the current value of this field from the register. + * @param[out] swclearprof17 - Will be populated with the current value of this field from the register. + * @param[out] swclearprof16 - Will be populated with the current value of this field from the register. + * @param[out] swclearprof15 - Will be populated with the current value of this field from the register. + * @param[out] swclearprof14 - Will be populated with the current value of this field from the register. + * @param[out] swclearprof13 - Will be populated with the current value of this field from the register. + * @param[out] swclearprof12 - Will be populated with the current value of this field from the register. + * @param[out] swclearprof11 - Will be populated with the current value of this field from the register. + * @param[out] swclearprof10 - Will be populated with the current value of this field from the register. + * @param[out] swclearprof9 - Will be populated with the current value of this field from the register. + * @param[out] swclearprof8 - Will be populated with the current value of this field from the register. + * @param[out] swclearprof7 - Will be populated with the current value of this field from the register. + * @param[out] swclearprof6 - Will be populated with the current value of this field from the register. + * @param[out] swclearprof5 - Will be populated with the current value of this field from the register. + * @param[out] swclearprof4 - Will be populated with the current value of this field from the register. + * @param[out] swclearprof3 - Will be populated with the current value of this field from the register. + * @param[out] swclearprof2 - Will be populated with the current value of this field from the register. + * @param[out] swclearprof1 - Will be populated with the current value of this field from the register. + * @param[out] swclearprof0 - Will be populated with the current value of this field from the register. + */ +__INLINE void nxmac_sw_clear_profiling_unpack(uint8_t *swclearprof31, uint8_t *swclearprof30, uint8_t *swclearprof29, uint8_t *swclearprof28, uint8_t *swclearprof27, uint8_t *swclearprof26, uint8_t *swclearprof25, uint8_t *swclearprof24, uint8_t *swclearprof23, uint8_t *swclearprof22, uint8_t *swclearprof21, uint8_t *swclearprof20, uint8_t *swclearprof19, uint8_t *swclearprof18, uint8_t *swclearprof17, uint8_t *swclearprof16, uint8_t *swclearprof15, uint8_t *swclearprof14, uint8_t *swclearprof13, uint8_t *swclearprof12, uint8_t *swclearprof11, uint8_t *swclearprof10, uint8_t *swclearprof9, uint8_t *swclearprof8, uint8_t *swclearprof7, uint8_t *swclearprof6, uint8_t *swclearprof5, uint8_t *swclearprof4, uint8_t *swclearprof3, uint8_t *swclearprof2, uint8_t *swclearprof1, uint8_t *swclearprof0) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_CLEAR_PROFILING_ADDR); + + *swclearprof31 = (localVal & ((uint32_t)0x80000000)) >> 31; + *swclearprof30 = (localVal & ((uint32_t)0x40000000)) >> 30; + *swclearprof29 = (localVal & ((uint32_t)0x20000000)) >> 29; + *swclearprof28 = (localVal & ((uint32_t)0x10000000)) >> 28; + *swclearprof27 = (localVal & ((uint32_t)0x08000000)) >> 27; + *swclearprof26 = (localVal & ((uint32_t)0x04000000)) >> 26; + *swclearprof25 = (localVal & ((uint32_t)0x02000000)) >> 25; + *swclearprof24 = (localVal & ((uint32_t)0x01000000)) >> 24; + *swclearprof23 = (localVal & ((uint32_t)0x00800000)) >> 23; + *swclearprof22 = (localVal & ((uint32_t)0x00400000)) >> 22; + *swclearprof21 = (localVal & ((uint32_t)0x00200000)) >> 21; + *swclearprof20 = (localVal & ((uint32_t)0x00100000)) >> 20; + *swclearprof19 = (localVal & ((uint32_t)0x00080000)) >> 19; + *swclearprof18 = (localVal & ((uint32_t)0x00040000)) >> 18; + *swclearprof17 = (localVal & ((uint32_t)0x00020000)) >> 17; + *swclearprof16 = (localVal & ((uint32_t)0x00010000)) >> 16; + *swclearprof15 = (localVal & ((uint32_t)0x00008000)) >> 15; + *swclearprof14 = (localVal & ((uint32_t)0x00004000)) >> 14; + *swclearprof13 = (localVal & ((uint32_t)0x00002000)) >> 13; + *swclearprof12 = (localVal & ((uint32_t)0x00001000)) >> 12; + *swclearprof11 = (localVal & ((uint32_t)0x00000800)) >> 11; + *swclearprof10 = (localVal & ((uint32_t)0x00000400)) >> 10; + *swclearprof9 = (localVal & ((uint32_t)0x00000200)) >> 9; + *swclearprof8 = (localVal & ((uint32_t)0x00000100)) >> 8; + *swclearprof7 = (localVal & ((uint32_t)0x00000080)) >> 7; + *swclearprof6 = (localVal & ((uint32_t)0x00000040)) >> 6; + *swclearprof5 = (localVal & ((uint32_t)0x00000020)) >> 5; + *swclearprof4 = (localVal & ((uint32_t)0x00000010)) >> 4; + *swclearprof3 = (localVal & ((uint32_t)0x00000008)) >> 3; + *swclearprof2 = (localVal & ((uint32_t)0x00000004)) >> 2; + *swclearprof1 = (localVal & ((uint32_t)0x00000002)) >> 1; + *swclearprof0 = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +/** + * @brief Returns the current value of the swClearProf31 field in the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read and the swClearProf31 field's value will be returned. + * + * @return The current value of the swClearProf31 field in the SW_CLEAR_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_clear_prof_31_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_CLEAR_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +/** + * @brief Sets the swClearProf31 field of the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swclearprof31 - The value to set the field to. + */ +__INLINE void nxmac_sw_clear_prof_31_clearf(uint8_t swclearprof31) +{ + ASSERT_ERR((((uint32_t)swclearprof31 << 31) & ~((uint32_t)0x80000000)) == 0); + REG_PL_WR(NXMAC_SW_CLEAR_PROFILING_ADDR, (uint32_t)swclearprof31 << 31); +} + +/** + * @brief Returns the current value of the swClearProf30 field in the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read and the swClearProf30 field's value will be returned. + * + * @return The current value of the swClearProf30 field in the SW_CLEAR_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_clear_prof_30_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_CLEAR_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x40000000)) >> 30); +} + +/** + * @brief Sets the swClearProf30 field of the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swclearprof30 - The value to set the field to. + */ +__INLINE void nxmac_sw_clear_prof_30_clearf(uint8_t swclearprof30) +{ + ASSERT_ERR((((uint32_t)swclearprof30 << 30) & ~((uint32_t)0x40000000)) == 0); + REG_PL_WR(NXMAC_SW_CLEAR_PROFILING_ADDR, (uint32_t)swclearprof30 << 30); +} + +/** + * @brief Returns the current value of the swClearProf29 field in the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read and the swClearProf29 field's value will be returned. + * + * @return The current value of the swClearProf29 field in the SW_CLEAR_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_clear_prof_29_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_CLEAR_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x20000000)) >> 29); +} + +/** + * @brief Sets the swClearProf29 field of the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swclearprof29 - The value to set the field to. + */ +__INLINE void nxmac_sw_clear_prof_29_clearf(uint8_t swclearprof29) +{ + ASSERT_ERR((((uint32_t)swclearprof29 << 29) & ~((uint32_t)0x20000000)) == 0); + REG_PL_WR(NXMAC_SW_CLEAR_PROFILING_ADDR, (uint32_t)swclearprof29 << 29); +} + +/** + * @brief Returns the current value of the swClearProf28 field in the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read and the swClearProf28 field's value will be returned. + * + * @return The current value of the swClearProf28 field in the SW_CLEAR_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_clear_prof_28_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_CLEAR_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x10000000)) >> 28); +} + +/** + * @brief Sets the swClearProf28 field of the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swclearprof28 - The value to set the field to. + */ +__INLINE void nxmac_sw_clear_prof_28_clearf(uint8_t swclearprof28) +{ + ASSERT_ERR((((uint32_t)swclearprof28 << 28) & ~((uint32_t)0x10000000)) == 0); + REG_PL_WR(NXMAC_SW_CLEAR_PROFILING_ADDR, (uint32_t)swclearprof28 << 28); +} + +/** + * @brief Returns the current value of the swClearProf27 field in the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read and the swClearProf27 field's value will be returned. + * + * @return The current value of the swClearProf27 field in the SW_CLEAR_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_clear_prof_27_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_CLEAR_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x08000000)) >> 27); +} + +/** + * @brief Sets the swClearProf27 field of the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swclearprof27 - The value to set the field to. + */ +__INLINE void nxmac_sw_clear_prof_27_clearf(uint8_t swclearprof27) +{ + ASSERT_ERR((((uint32_t)swclearprof27 << 27) & ~((uint32_t)0x08000000)) == 0); + REG_PL_WR(NXMAC_SW_CLEAR_PROFILING_ADDR, (uint32_t)swclearprof27 << 27); +} + +/** + * @brief Returns the current value of the swClearProf26 field in the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read and the swClearProf26 field's value will be returned. + * + * @return The current value of the swClearProf26 field in the SW_CLEAR_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_clear_prof_26_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_CLEAR_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x04000000)) >> 26); +} + +/** + * @brief Sets the swClearProf26 field of the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swclearprof26 - The value to set the field to. + */ +__INLINE void nxmac_sw_clear_prof_26_clearf(uint8_t swclearprof26) +{ + ASSERT_ERR((((uint32_t)swclearprof26 << 26) & ~((uint32_t)0x04000000)) == 0); + REG_PL_WR(NXMAC_SW_CLEAR_PROFILING_ADDR, (uint32_t)swclearprof26 << 26); +} + +/** + * @brief Returns the current value of the swClearProf25 field in the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read and the swClearProf25 field's value will be returned. + * + * @return The current value of the swClearProf25 field in the SW_CLEAR_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_clear_prof_25_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_CLEAR_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x02000000)) >> 25); +} + +/** + * @brief Sets the swClearProf25 field of the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swclearprof25 - The value to set the field to. + */ +__INLINE void nxmac_sw_clear_prof_25_clearf(uint8_t swclearprof25) +{ + ASSERT_ERR((((uint32_t)swclearprof25 << 25) & ~((uint32_t)0x02000000)) == 0); + REG_PL_WR(NXMAC_SW_CLEAR_PROFILING_ADDR, (uint32_t)swclearprof25 << 25); +} + +/** + * @brief Returns the current value of the swClearProf24 field in the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read and the swClearProf24 field's value will be returned. + * + * @return The current value of the swClearProf24 field in the SW_CLEAR_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_clear_prof_24_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_CLEAR_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x01000000)) >> 24); +} + +/** + * @brief Sets the swClearProf24 field of the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swclearprof24 - The value to set the field to. + */ +__INLINE void nxmac_sw_clear_prof_24_clearf(uint8_t swclearprof24) +{ + ASSERT_ERR((((uint32_t)swclearprof24 << 24) & ~((uint32_t)0x01000000)) == 0); + REG_PL_WR(NXMAC_SW_CLEAR_PROFILING_ADDR, (uint32_t)swclearprof24 << 24); +} + +/** + * @brief Returns the current value of the swClearProf23 field in the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read and the swClearProf23 field's value will be returned. + * + * @return The current value of the swClearProf23 field in the SW_CLEAR_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_clear_prof_23_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_CLEAR_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00800000)) >> 23); +} + +/** + * @brief Sets the swClearProf23 field of the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swclearprof23 - The value to set the field to. + */ +__INLINE void nxmac_sw_clear_prof_23_clearf(uint8_t swclearprof23) +{ + ASSERT_ERR((((uint32_t)swclearprof23 << 23) & ~((uint32_t)0x00800000)) == 0); + REG_PL_WR(NXMAC_SW_CLEAR_PROFILING_ADDR, (uint32_t)swclearprof23 << 23); +} + +/** + * @brief Returns the current value of the swClearProf22 field in the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read and the swClearProf22 field's value will be returned. + * + * @return The current value of the swClearProf22 field in the SW_CLEAR_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_clear_prof_22_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_CLEAR_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00400000)) >> 22); +} + +/** + * @brief Sets the swClearProf22 field of the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swclearprof22 - The value to set the field to. + */ +__INLINE void nxmac_sw_clear_prof_22_clearf(uint8_t swclearprof22) +{ + ASSERT_ERR((((uint32_t)swclearprof22 << 22) & ~((uint32_t)0x00400000)) == 0); + REG_PL_WR(NXMAC_SW_CLEAR_PROFILING_ADDR, (uint32_t)swclearprof22 << 22); +} + +/** + * @brief Returns the current value of the swClearProf21 field in the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read and the swClearProf21 field's value will be returned. + * + * @return The current value of the swClearProf21 field in the SW_CLEAR_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_clear_prof_21_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_CLEAR_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00200000)) >> 21); +} + +/** + * @brief Sets the swClearProf21 field of the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swclearprof21 - The value to set the field to. + */ +__INLINE void nxmac_sw_clear_prof_21_clearf(uint8_t swclearprof21) +{ + ASSERT_ERR((((uint32_t)swclearprof21 << 21) & ~((uint32_t)0x00200000)) == 0); + REG_PL_WR(NXMAC_SW_CLEAR_PROFILING_ADDR, (uint32_t)swclearprof21 << 21); +} + +/** + * @brief Returns the current value of the swClearProf20 field in the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read and the swClearProf20 field's value will be returned. + * + * @return The current value of the swClearProf20 field in the SW_CLEAR_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_clear_prof_20_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_CLEAR_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00100000)) >> 20); +} + +/** + * @brief Sets the swClearProf20 field of the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swclearprof20 - The value to set the field to. + */ +__INLINE void nxmac_sw_clear_prof_20_clearf(uint8_t swclearprof20) +{ + ASSERT_ERR((((uint32_t)swclearprof20 << 20) & ~((uint32_t)0x00100000)) == 0); + REG_PL_WR(NXMAC_SW_CLEAR_PROFILING_ADDR, (uint32_t)swclearprof20 << 20); +} + +/** + * @brief Returns the current value of the swClearProf19 field in the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read and the swClearProf19 field's value will be returned. + * + * @return The current value of the swClearProf19 field in the SW_CLEAR_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_clear_prof_19_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_CLEAR_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00080000)) >> 19); +} + +/** + * @brief Sets the swClearProf19 field of the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swclearprof19 - The value to set the field to. + */ +__INLINE void nxmac_sw_clear_prof_19_clearf(uint8_t swclearprof19) +{ + ASSERT_ERR((((uint32_t)swclearprof19 << 19) & ~((uint32_t)0x00080000)) == 0); + REG_PL_WR(NXMAC_SW_CLEAR_PROFILING_ADDR, (uint32_t)swclearprof19 << 19); +} + +/** + * @brief Returns the current value of the swClearProf18 field in the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read and the swClearProf18 field's value will be returned. + * + * @return The current value of the swClearProf18 field in the SW_CLEAR_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_clear_prof_18_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_CLEAR_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00040000)) >> 18); +} + +/** + * @brief Sets the swClearProf18 field of the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swclearprof18 - The value to set the field to. + */ +__INLINE void nxmac_sw_clear_prof_18_clearf(uint8_t swclearprof18) +{ + ASSERT_ERR((((uint32_t)swclearprof18 << 18) & ~((uint32_t)0x00040000)) == 0); + REG_PL_WR(NXMAC_SW_CLEAR_PROFILING_ADDR, (uint32_t)swclearprof18 << 18); +} + +/** + * @brief Returns the current value of the swClearProf17 field in the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read and the swClearProf17 field's value will be returned. + * + * @return The current value of the swClearProf17 field in the SW_CLEAR_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_clear_prof_17_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_CLEAR_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00020000)) >> 17); +} + +/** + * @brief Sets the swClearProf17 field of the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swclearprof17 - The value to set the field to. + */ +__INLINE void nxmac_sw_clear_prof_17_clearf(uint8_t swclearprof17) +{ + ASSERT_ERR((((uint32_t)swclearprof17 << 17) & ~((uint32_t)0x00020000)) == 0); + REG_PL_WR(NXMAC_SW_CLEAR_PROFILING_ADDR, (uint32_t)swclearprof17 << 17); +} + +/** + * @brief Returns the current value of the swClearProf16 field in the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read and the swClearProf16 field's value will be returned. + * + * @return The current value of the swClearProf16 field in the SW_CLEAR_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_clear_prof_16_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_CLEAR_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00010000)) >> 16); +} + +/** + * @brief Sets the swClearProf16 field of the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swclearprof16 - The value to set the field to. + */ +__INLINE void nxmac_sw_clear_prof_16_clearf(uint8_t swclearprof16) +{ + ASSERT_ERR((((uint32_t)swclearprof16 << 16) & ~((uint32_t)0x00010000)) == 0); + REG_PL_WR(NXMAC_SW_CLEAR_PROFILING_ADDR, (uint32_t)swclearprof16 << 16); +} + +/** + * @brief Returns the current value of the swClearProf15 field in the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read and the swClearProf15 field's value will be returned. + * + * @return The current value of the swClearProf15 field in the SW_CLEAR_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_clear_prof_15_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_CLEAR_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00008000)) >> 15); +} + +/** + * @brief Sets the swClearProf15 field of the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swclearprof15 - The value to set the field to. + */ +__INLINE void nxmac_sw_clear_prof_15_clearf(uint8_t swclearprof15) +{ + ASSERT_ERR((((uint32_t)swclearprof15 << 15) & ~((uint32_t)0x00008000)) == 0); + REG_PL_WR(NXMAC_SW_CLEAR_PROFILING_ADDR, (uint32_t)swclearprof15 << 15); +} + +/** + * @brief Returns the current value of the swClearProf14 field in the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read and the swClearProf14 field's value will be returned. + * + * @return The current value of the swClearProf14 field in the SW_CLEAR_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_clear_prof_14_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_CLEAR_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00004000)) >> 14); +} + +/** + * @brief Sets the swClearProf14 field of the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swclearprof14 - The value to set the field to. + */ +__INLINE void nxmac_sw_clear_prof_14_clearf(uint8_t swclearprof14) +{ + ASSERT_ERR((((uint32_t)swclearprof14 << 14) & ~((uint32_t)0x00004000)) == 0); + REG_PL_WR(NXMAC_SW_CLEAR_PROFILING_ADDR, (uint32_t)swclearprof14 << 14); +} + +/** + * @brief Returns the current value of the swClearProf13 field in the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read and the swClearProf13 field's value will be returned. + * + * @return The current value of the swClearProf13 field in the SW_CLEAR_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_clear_prof_13_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_CLEAR_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00002000)) >> 13); +} + +/** + * @brief Sets the swClearProf13 field of the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swclearprof13 - The value to set the field to. + */ +__INLINE void nxmac_sw_clear_prof_13_clearf(uint8_t swclearprof13) +{ + ASSERT_ERR((((uint32_t)swclearprof13 << 13) & ~((uint32_t)0x00002000)) == 0); + REG_PL_WR(NXMAC_SW_CLEAR_PROFILING_ADDR, (uint32_t)swclearprof13 << 13); +} + +/** + * @brief Returns the current value of the swClearProf12 field in the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read and the swClearProf12 field's value will be returned. + * + * @return The current value of the swClearProf12 field in the SW_CLEAR_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_clear_prof_12_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_CLEAR_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00001000)) >> 12); +} + +/** + * @brief Sets the swClearProf12 field of the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swclearprof12 - The value to set the field to. + */ +__INLINE void nxmac_sw_clear_prof_12_clearf(uint8_t swclearprof12) +{ + ASSERT_ERR((((uint32_t)swclearprof12 << 12) & ~((uint32_t)0x00001000)) == 0); + REG_PL_WR(NXMAC_SW_CLEAR_PROFILING_ADDR, (uint32_t)swclearprof12 << 12); +} + +/** + * @brief Returns the current value of the swClearProf11 field in the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read and the swClearProf11 field's value will be returned. + * + * @return The current value of the swClearProf11 field in the SW_CLEAR_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_clear_prof_11_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_CLEAR_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000800)) >> 11); +} + +/** + * @brief Sets the swClearProf11 field of the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swclearprof11 - The value to set the field to. + */ +__INLINE void nxmac_sw_clear_prof_11_clearf(uint8_t swclearprof11) +{ + ASSERT_ERR((((uint32_t)swclearprof11 << 11) & ~((uint32_t)0x00000800)) == 0); + REG_PL_WR(NXMAC_SW_CLEAR_PROFILING_ADDR, (uint32_t)swclearprof11 << 11); +} + +/** + * @brief Returns the current value of the swClearProf10 field in the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read and the swClearProf10 field's value will be returned. + * + * @return The current value of the swClearProf10 field in the SW_CLEAR_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_clear_prof_10_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_CLEAR_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000400)) >> 10); +} + +/** + * @brief Sets the swClearProf10 field of the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swclearprof10 - The value to set the field to. + */ +__INLINE void nxmac_sw_clear_prof_10_clearf(uint8_t swclearprof10) +{ + ASSERT_ERR((((uint32_t)swclearprof10 << 10) & ~((uint32_t)0x00000400)) == 0); + REG_PL_WR(NXMAC_SW_CLEAR_PROFILING_ADDR, (uint32_t)swclearprof10 << 10); +} + +/** + * @brief Returns the current value of the swClearProf9 field in the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read and the swClearProf9 field's value will be returned. + * + * @return The current value of the swClearProf9 field in the SW_CLEAR_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_clear_prof_9_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_CLEAR_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000200)) >> 9); +} + +/** + * @brief Sets the swClearProf9 field of the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swclearprof9 - The value to set the field to. + */ +__INLINE void nxmac_sw_clear_prof_9_clearf(uint8_t swclearprof9) +{ + ASSERT_ERR((((uint32_t)swclearprof9 << 9) & ~((uint32_t)0x00000200)) == 0); + REG_PL_WR(NXMAC_SW_CLEAR_PROFILING_ADDR, (uint32_t)swclearprof9 << 9); +} + +/** + * @brief Returns the current value of the swClearProf8 field in the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read and the swClearProf8 field's value will be returned. + * + * @return The current value of the swClearProf8 field in the SW_CLEAR_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_clear_prof_8_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_CLEAR_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000100)) >> 8); +} + +/** + * @brief Sets the swClearProf8 field of the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swclearprof8 - The value to set the field to. + */ +__INLINE void nxmac_sw_clear_prof_8_clearf(uint8_t swclearprof8) +{ + ASSERT_ERR((((uint32_t)swclearprof8 << 8) & ~((uint32_t)0x00000100)) == 0); + REG_PL_WR(NXMAC_SW_CLEAR_PROFILING_ADDR, (uint32_t)swclearprof8 << 8); +} + +/** + * @brief Returns the current value of the swClearProf7 field in the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read and the swClearProf7 field's value will be returned. + * + * @return The current value of the swClearProf7 field in the SW_CLEAR_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_clear_prof_7_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_CLEAR_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000080)) >> 7); +} + +/** + * @brief Sets the swClearProf7 field of the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swclearprof7 - The value to set the field to. + */ +__INLINE void nxmac_sw_clear_prof_7_clearf(uint8_t swclearprof7) +{ + ASSERT_ERR((((uint32_t)swclearprof7 << 7) & ~((uint32_t)0x00000080)) == 0); + REG_PL_WR(NXMAC_SW_CLEAR_PROFILING_ADDR, (uint32_t)swclearprof7 << 7); +} + +/** + * @brief Returns the current value of the swClearProf6 field in the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read and the swClearProf6 field's value will be returned. + * + * @return The current value of the swClearProf6 field in the SW_CLEAR_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_clear_prof_6_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_CLEAR_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000040)) >> 6); +} + +/** + * @brief Sets the swClearProf6 field of the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swclearprof6 - The value to set the field to. + */ +__INLINE void nxmac_sw_clear_prof_6_clearf(uint8_t swclearprof6) +{ + ASSERT_ERR((((uint32_t)swclearprof6 << 6) & ~((uint32_t)0x00000040)) == 0); + REG_PL_WR(NXMAC_SW_CLEAR_PROFILING_ADDR, (uint32_t)swclearprof6 << 6); +} + +/** + * @brief Returns the current value of the swClearProf5 field in the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read and the swClearProf5 field's value will be returned. + * + * @return The current value of the swClearProf5 field in the SW_CLEAR_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_clear_prof_5_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_CLEAR_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +/** + * @brief Sets the swClearProf5 field of the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swclearprof5 - The value to set the field to. + */ +__INLINE void nxmac_sw_clear_prof_5_clearf(uint8_t swclearprof5) +{ + ASSERT_ERR((((uint32_t)swclearprof5 << 5) & ~((uint32_t)0x00000020)) == 0); + REG_PL_WR(NXMAC_SW_CLEAR_PROFILING_ADDR, (uint32_t)swclearprof5 << 5); +} + +/** + * @brief Returns the current value of the swClearProf4 field in the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read and the swClearProf4 field's value will be returned. + * + * @return The current value of the swClearProf4 field in the SW_CLEAR_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_clear_prof_4_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_CLEAR_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +/** + * @brief Sets the swClearProf4 field of the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swclearprof4 - The value to set the field to. + */ +__INLINE void nxmac_sw_clear_prof_4_clearf(uint8_t swclearprof4) +{ + ASSERT_ERR((((uint32_t)swclearprof4 << 4) & ~((uint32_t)0x00000010)) == 0); + REG_PL_WR(NXMAC_SW_CLEAR_PROFILING_ADDR, (uint32_t)swclearprof4 << 4); +} + +/** + * @brief Returns the current value of the swClearProf3 field in the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read and the swClearProf3 field's value will be returned. + * + * @return The current value of the swClearProf3 field in the SW_CLEAR_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_clear_prof_3_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_CLEAR_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +/** + * @brief Sets the swClearProf3 field of the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swclearprof3 - The value to set the field to. + */ +__INLINE void nxmac_sw_clear_prof_3_clearf(uint8_t swclearprof3) +{ + ASSERT_ERR((((uint32_t)swclearprof3 << 3) & ~((uint32_t)0x00000008)) == 0); + REG_PL_WR(NXMAC_SW_CLEAR_PROFILING_ADDR, (uint32_t)swclearprof3 << 3); +} + +/** + * @brief Returns the current value of the swClearProf2 field in the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read and the swClearProf2 field's value will be returned. + * + * @return The current value of the swClearProf2 field in the SW_CLEAR_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_clear_prof_2_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_CLEAR_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +/** + * @brief Sets the swClearProf2 field of the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swclearprof2 - The value to set the field to. + */ +__INLINE void nxmac_sw_clear_prof_2_clearf(uint8_t swclearprof2) +{ + ASSERT_ERR((((uint32_t)swclearprof2 << 2) & ~((uint32_t)0x00000004)) == 0); + REG_PL_WR(NXMAC_SW_CLEAR_PROFILING_ADDR, (uint32_t)swclearprof2 << 2); +} + +/** + * @brief Returns the current value of the swClearProf1 field in the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read and the swClearProf1 field's value will be returned. + * + * @return The current value of the swClearProf1 field in the SW_CLEAR_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_clear_prof_1_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_CLEAR_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +/** + * @brief Sets the swClearProf1 field of the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swclearprof1 - The value to set the field to. + */ +__INLINE void nxmac_sw_clear_prof_1_clearf(uint8_t swclearprof1) +{ + ASSERT_ERR((((uint32_t)swclearprof1 << 1) & ~((uint32_t)0x00000002)) == 0); + REG_PL_WR(NXMAC_SW_CLEAR_PROFILING_ADDR, (uint32_t)swclearprof1 << 1); +} + +/** + * @brief Returns the current value of the swClearProf0 field in the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read and the swClearProf0 field's value will be returned. + * + * @return The current value of the swClearProf0 field in the SW_CLEAR_PROFILING register. + */ +__INLINE uint8_t nxmac_sw_clear_prof_0_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_SW_CLEAR_PROFILING_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/** + * @brief Sets the swClearProf0 field of the SW_CLEAR_PROFILING register. + * + * The SW_CLEAR_PROFILING register will be read, modified to contain the new field value, and written. + * + * @param[in] swclearprof0 - The value to set the field to. + */ +__INLINE void nxmac_sw_clear_prof_0_clearf(uint8_t swclearprof0) +{ + ASSERT_ERR((((uint32_t)swclearprof0 << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(NXMAC_SW_CLEAR_PROFILING_ADDR, (uint32_t)swclearprof0 << 0); +} + +/// @} + +#if RW_MUMIMO_SEC_USER1_EN +/** + * @name DEBUG_SEC_U_1_TX_C_PTR register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00   secU1TxCurrentPointer   0x0
+ * 
+ * + * @{ + */ + +/// Address of the DEBUG_SEC_U_1_TX_C_PTR register +#define NXMAC_DEBUG_SEC_U_1_TX_C_PTR_ADDR 0xC0008570 +/// Offset of the DEBUG_SEC_U_1_TX_C_PTR register from the base address +#define NXMAC_DEBUG_SEC_U_1_TX_C_PTR_OFFSET 0x00000570 +/// Index of the DEBUG_SEC_U_1_TX_C_PTR register +#define NXMAC_DEBUG_SEC_U_1_TX_C_PTR_INDEX 0x0000015C +/// Reset value of the DEBUG_SEC_U_1_TX_C_PTR register +#define NXMAC_DEBUG_SEC_U_1_TX_C_PTR_RESET 0x00000000 + +/** + * @brief Returns the current value of the DEBUG_SEC_U_1_TX_C_PTR register. + * The DEBUG_SEC_U_1_TX_C_PTR register will be read and its value returned. + * @return The current value of the DEBUG_SEC_U_1_TX_C_PTR register. + */ +__INLINE uint32_t nxmac_debug_sec_u_1_tx_c_ptr_get(void) +{ + return REG_PL_RD(NXMAC_DEBUG_SEC_U_1_TX_C_PTR_ADDR); +} + +// field definitions +/// SEC_U_1_TX_CURRENT_POINTER field mask +#define NXMAC_SEC_U_1_TX_CURRENT_POINTER_MASK ((uint32_t)0xFFFFFFFF) +/// SEC_U_1_TX_CURRENT_POINTER field LSB position +#define NXMAC_SEC_U_1_TX_CURRENT_POINTER_LSB 0 +/// SEC_U_1_TX_CURRENT_POINTER field width +#define NXMAC_SEC_U_1_TX_CURRENT_POINTER_WIDTH ((uint32_t)0x00000020) + +/// SEC_U_1_TX_CURRENT_POINTER field reset value +#define NXMAC_SEC_U_1_TX_CURRENT_POINTER_RST 0x0 + +/** + * @brief Returns the current value of the secU1TxCurrentPointer field in the DEBUG_SEC_U_1_TX_C_PTR register. + * + * The DEBUG_SEC_U_1_TX_C_PTR register will be read and the secU1TxCurrentPointer field's value will be returned. + * + * @return The current value of the secU1TxCurrentPointer field in the DEBUG_SEC_U_1_TX_C_PTR register. + */ +__INLINE uint32_t nxmac_sec_u_1_tx_current_pointer_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DEBUG_SEC_U_1_TX_C_PTR_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +#endif // RW_MUMIMO_SEC_USER1_EN +/// @} + +#if RW_MUMIMO_SEC_USER2_EN +/** + * @name DEBUG_SEC_U_2_TX_C_PTR register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00   secU2TxCurrentPointer   0x0
+ * 
+ * + * @{ + */ + +/// Address of the DEBUG_SEC_U_2_TX_C_PTR register +#define NXMAC_DEBUG_SEC_U_2_TX_C_PTR_ADDR 0xC0008574 +/// Offset of the DEBUG_SEC_U_2_TX_C_PTR register from the base address +#define NXMAC_DEBUG_SEC_U_2_TX_C_PTR_OFFSET 0x00000574 +/// Index of the DEBUG_SEC_U_2_TX_C_PTR register +#define NXMAC_DEBUG_SEC_U_2_TX_C_PTR_INDEX 0x0000015D +/// Reset value of the DEBUG_SEC_U_2_TX_C_PTR register +#define NXMAC_DEBUG_SEC_U_2_TX_C_PTR_RESET 0x00000000 + +/** + * @brief Returns the current value of the DEBUG_SEC_U_2_TX_C_PTR register. + * The DEBUG_SEC_U_2_TX_C_PTR register will be read and its value returned. + * @return The current value of the DEBUG_SEC_U_2_TX_C_PTR register. + */ +__INLINE uint32_t nxmac_debug_sec_u_2_tx_c_ptr_get(void) +{ + return REG_PL_RD(NXMAC_DEBUG_SEC_U_2_TX_C_PTR_ADDR); +} + +// field definitions +/// SEC_U_2_TX_CURRENT_POINTER field mask +#define NXMAC_SEC_U_2_TX_CURRENT_POINTER_MASK ((uint32_t)0xFFFFFFFF) +/// SEC_U_2_TX_CURRENT_POINTER field LSB position +#define NXMAC_SEC_U_2_TX_CURRENT_POINTER_LSB 0 +/// SEC_U_2_TX_CURRENT_POINTER field width +#define NXMAC_SEC_U_2_TX_CURRENT_POINTER_WIDTH ((uint32_t)0x00000020) + +/// SEC_U_2_TX_CURRENT_POINTER field reset value +#define NXMAC_SEC_U_2_TX_CURRENT_POINTER_RST 0x0 + +/** + * @brief Returns the current value of the secU2TxCurrentPointer field in the DEBUG_SEC_U_2_TX_C_PTR register. + * + * The DEBUG_SEC_U_2_TX_C_PTR register will be read and the secU2TxCurrentPointer field's value will be returned. + * + * @return The current value of the secU2TxCurrentPointer field in the DEBUG_SEC_U_2_TX_C_PTR register. + */ +__INLINE uint32_t nxmac_sec_u_2_tx_current_pointer_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DEBUG_SEC_U_2_TX_C_PTR_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +#endif // RW_MUMIMO_SEC_USER2_EN +/// @} + +#if RW_MUMIMO_SEC_USER3_EN +/** + * @name DEBUG_SEC_U_3_TX_C_PTR register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00   secU3TxCurrentPointer   0x0
+ * 
+ * + * @{ + */ + +/// Address of the DEBUG_SEC_U_3_TX_C_PTR register +#define NXMAC_DEBUG_SEC_U_3_TX_C_PTR_ADDR 0xC0008578 +/// Offset of the DEBUG_SEC_U_3_TX_C_PTR register from the base address +#define NXMAC_DEBUG_SEC_U_3_TX_C_PTR_OFFSET 0x00000578 +/// Index of the DEBUG_SEC_U_3_TX_C_PTR register +#define NXMAC_DEBUG_SEC_U_3_TX_C_PTR_INDEX 0x0000015E +/// Reset value of the DEBUG_SEC_U_3_TX_C_PTR register +#define NXMAC_DEBUG_SEC_U_3_TX_C_PTR_RESET 0x00000000 + +/** + * @brief Returns the current value of the DEBUG_SEC_U_3_TX_C_PTR register. + * The DEBUG_SEC_U_3_TX_C_PTR register will be read and its value returned. + * @return The current value of the DEBUG_SEC_U_3_TX_C_PTR register. + */ +__INLINE uint32_t nxmac_debug_sec_u_3_tx_c_ptr_get(void) +{ + return REG_PL_RD(NXMAC_DEBUG_SEC_U_3_TX_C_PTR_ADDR); +} + +// field definitions +/// SEC_U_3_TX_CURRENT_POINTER field mask +#define NXMAC_SEC_U_3_TX_CURRENT_POINTER_MASK ((uint32_t)0xFFFFFFFF) +/// SEC_U_3_TX_CURRENT_POINTER field LSB position +#define NXMAC_SEC_U_3_TX_CURRENT_POINTER_LSB 0 +/// SEC_U_3_TX_CURRENT_POINTER field width +#define NXMAC_SEC_U_3_TX_CURRENT_POINTER_WIDTH ((uint32_t)0x00000020) + +/// SEC_U_3_TX_CURRENT_POINTER field reset value +#define NXMAC_SEC_U_3_TX_CURRENT_POINTER_RST 0x0 + +/** + * @brief Returns the current value of the secU3TxCurrentPointer field in the DEBUG_SEC_U_3_TX_C_PTR register. + * + * The DEBUG_SEC_U_3_TX_C_PTR register will be read and the secU3TxCurrentPointer field's value will be returned. + * + * @return The current value of the secU3TxCurrentPointer field in the DEBUG_SEC_U_3_TX_C_PTR register. + */ +__INLINE uint32_t nxmac_sec_u_3_tx_current_pointer_getf(void) +{ + uint32_t localVal = REG_PL_RD(NXMAC_DEBUG_SEC_U_3_TX_C_PTR_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +#endif // RW_MUMIMO_SEC_USER3_EN +/// @} +/*lint +e91*/ + +#endif // _REG_MAC_PL_H_ + +/// @} + diff --git a/beken_os/beken378/driver/common/reg/reg_mdm_cfg.h b/beken_os/beken378/driver/common/reg/reg_mdm_cfg.h new file mode 100755 index 0000000..e76c18e --- /dev/null +++ b/beken_os/beken378/driver/common/reg/reg_mdm_cfg.h @@ -0,0 +1,9788 @@ +/** + * @file reg_mdm_cfg.h + * @brief Definitions of the MDM HW block registers and register access functions. + * + * @defgroup REG_MDM_CFG REG_MDM_CFG + * @ingroup REG + * @{ + * + * @brief Definitions of the MDM HW block registers and register access functions. + */ +#ifndef _REG_MDM_CFG_H_ +#define _REG_MDM_CFG_H_ + +#include "co_int.h" +#include "_reg_mdm_cfg.h" +#include "compiler.h" +#include "arch.h" +#include "reg_access.h" + +/** @brief Number of registers in the REG_MDM_CFG peripheral. + */ +#define REG_MDM_CFG_COUNT 550 + +/** @brief Decoding mask of the REG_MDM_CFG peripheral registers from the CPU point of view. + */ +#define REG_MDM_CFG_DECODING_MASK 0x00000FFF + +/** + * @name RXMODES register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     17           PSSELECT40   0
+ *     16           PSSELECT20   0
+ *     14            FORCENSS1   0
+ *     13              FORCE40   0
+ *     12              FORCE20   0
+ *     09             RXSTBCEN   1
+ *     08             DUPMRCEN   1
+ *     04           RXALLOWVHT   1
+ *     03            RXALLOWGF   1
+ *     02            RXALLOWMM   1
+ *     01        RXALLOWLEGACY   1
+ *     00          RXALLOWDSSS   1
+ * 
+ * + * @{ + */ + +/// Address of the RXMODES register +#define MDM_RXMODES_ADDR 0x01000800 +/// Offset of the RXMODES register from the base address +#define MDM_RXMODES_OFFSET 0x00000800 +/// Index of the RXMODES register +#define MDM_RXMODES_INDEX 0x00000200 +/// Reset value of the RXMODES register +#define MDM_RXMODES_RESET 0x0000031F + +/** + * @brief Returns the current value of the RXMODES register. + * The RXMODES register will be read and its value returned. + * @return The current value of the RXMODES register. + */ +__INLINE uint32_t mdm_rxmodes_get(void) +{ + return REG_PL_RD(MDM_RXMODES_ADDR); +} + +/** + * @brief Sets the RXMODES register to a value. + * The RXMODES register will be written. + * @param value - The value to write. + */ +__INLINE void mdm_rxmodes_set(uint32_t value) +{ + REG_PL_WR(MDM_RXMODES_ADDR, value); +} + +// field definitions +/// PSSELECT40 field bit +#define MDM_PSSELECT40_BIT ((uint32_t)0x00020000) +/// PSSELECT40 field position +#define MDM_PSSELECT40_POS 17 +/// PSSELECT20 field bit +#define MDM_PSSELECT20_BIT ((uint32_t)0x00010000) +/// PSSELECT20 field position +#define MDM_PSSELECT20_POS 16 +/// FORCENSS1 field bit +#define MDM_FORCENSS1_BIT ((uint32_t)0x00004000) +/// FORCENSS1 field position +#define MDM_FORCENSS1_POS 14 +/// FORCE40 field bit +#define MDM_FORCE40_BIT ((uint32_t)0x00002000) +/// FORCE40 field position +#define MDM_FORCE40_POS 13 +/// FORCE20 field bit +#define MDM_FORCE20_BIT ((uint32_t)0x00001000) +/// FORCE20 field position +#define MDM_FORCE20_POS 12 +/// RXSTBCEN field bit +#define MDM_RXSTBCEN_BIT ((uint32_t)0x00000200) +/// RXSTBCEN field position +#define MDM_RXSTBCEN_POS 9 +/// DUPMRCEN field bit +#define MDM_DUPMRCEN_BIT ((uint32_t)0x00000100) +/// DUPMRCEN field position +#define MDM_DUPMRCEN_POS 8 +/// RXALLOWVHT field bit +#define MDM_RXALLOWVHT_BIT ((uint32_t)0x00000010) +/// RXALLOWVHT field position +#define MDM_RXALLOWVHT_POS 4 +/// RXALLOWGF field bit +#define MDM_RXALLOWGF_BIT ((uint32_t)0x00000008) +/// RXALLOWGF field position +#define MDM_RXALLOWGF_POS 3 +/// RXALLOWMM field bit +#define MDM_RXALLOWMM_BIT ((uint32_t)0x00000004) +/// RXALLOWMM field position +#define MDM_RXALLOWMM_POS 2 +/// RXALLOWLEGACY field bit +#define MDM_RXALLOWLEGACY_BIT ((uint32_t)0x00000002) +/// RXALLOWLEGACY field position +#define MDM_RXALLOWLEGACY_POS 1 +/// RXALLOWDSSS field bit +#define MDM_RXALLOWDSSS_BIT ((uint32_t)0x00000001) +/// RXALLOWDSSS field position +#define MDM_RXALLOWDSSS_POS 0 + +/// PSSELECT40 field reset value +#define MDM_PSSELECT40_RST 0x0 +/// PSSELECT20 field reset value +#define MDM_PSSELECT20_RST 0x0 +/// FORCENSS1 field reset value +#define MDM_FORCENSS1_RST 0x0 +/// FORCE40 field reset value +#define MDM_FORCE40_RST 0x0 +/// FORCE20 field reset value +#define MDM_FORCE20_RST 0x0 +/// RXSTBCEN field reset value +#define MDM_RXSTBCEN_RST 0x1 +/// DUPMRCEN field reset value +#define MDM_DUPMRCEN_RST 0x1 +/// RXALLOWVHT field reset value +#define MDM_RXALLOWVHT_RST 0x1 +/// RXALLOWGF field reset value +#define MDM_RXALLOWGF_RST 0x1 +/// RXALLOWMM field reset value +#define MDM_RXALLOWMM_RST 0x1 +/// RXALLOWLEGACY field reset value +#define MDM_RXALLOWLEGACY_RST 0x1 +/// RXALLOWDSSS field reset value +#define MDM_RXALLOWDSSS_RST 0x1 + +/** + * @brief Constructs a value for the RXMODES register given values for its fields + * and writes the value to the register. + * + * @param[in] psselect40 - The value to use for the PSSELECT40 field. + * @param[in] psselect20 - The value to use for the PSSELECT20 field. + * @param[in] forcenss1 - The value to use for the FORCENSS1 field. + * @param[in] force40 - The value to use for the FORCE40 field. + * @param[in] force20 - The value to use for the FORCE20 field. + * @param[in] rxstbcen - The value to use for the RXSTBCEN field. + * @param[in] dupmrcen - The value to use for the DUPMRCEN field. + * @param[in] rxallowvht - The value to use for the RXALLOWVHT field. + * @param[in] rxallowgf - The value to use for the RXALLOWGF field. + * @param[in] rxallowmm - The value to use for the RXALLOWMM field. + * @param[in] rxallowlegacy - The value to use for the RXALLOWLEGACY field. + * @param[in] rxallowdsss - The value to use for the RXALLOWDSSS field. + */ +__INLINE void mdm_rxmodes_pack(uint8_t psselect40, uint8_t psselect20, uint8_t forcenss1, uint8_t force40, uint8_t force20, uint8_t rxstbcen, uint8_t dupmrcen, uint8_t rxallowvht, uint8_t rxallowgf, uint8_t rxallowmm, uint8_t rxallowlegacy, uint8_t rxallowdsss) +{ + ASSERT_ERR((((uint32_t)psselect40 << 17) & ~((uint32_t)0x00020000)) == 0); + ASSERT_ERR((((uint32_t)psselect20 << 16) & ~((uint32_t)0x00010000)) == 0); + ASSERT_ERR((((uint32_t)forcenss1 << 14) & ~((uint32_t)0x00004000)) == 0); + ASSERT_ERR((((uint32_t)force40 << 13) & ~((uint32_t)0x00002000)) == 0); + ASSERT_ERR((((uint32_t)force20 << 12) & ~((uint32_t)0x00001000)) == 0); + ASSERT_ERR((((uint32_t)rxstbcen << 9) & ~((uint32_t)0x00000200)) == 0); + ASSERT_ERR((((uint32_t)dupmrcen << 8) & ~((uint32_t)0x00000100)) == 0); + ASSERT_ERR((((uint32_t)rxallowvht << 4) & ~((uint32_t)0x00000010)) == 0); + ASSERT_ERR((((uint32_t)rxallowgf << 3) & ~((uint32_t)0x00000008)) == 0); + ASSERT_ERR((((uint32_t)rxallowmm << 2) & ~((uint32_t)0x00000004)) == 0); + ASSERT_ERR((((uint32_t)rxallowlegacy << 1) & ~((uint32_t)0x00000002)) == 0); + ASSERT_ERR((((uint32_t)rxallowdsss << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(MDM_RXMODES_ADDR, ((uint32_t)psselect40 << 17) | ((uint32_t)psselect20 << 16) | ((uint32_t)forcenss1 << 14) | ((uint32_t)force40 << 13) | ((uint32_t)force20 << 12) | ((uint32_t)rxstbcen << 9) | ((uint32_t)dupmrcen << 8) | ((uint32_t)rxallowvht << 4) | ((uint32_t)rxallowgf << 3) | ((uint32_t)rxallowmm << 2) | ((uint32_t)rxallowlegacy << 1) | ((uint32_t)rxallowdsss << 0)); +} + +/** + * @brief Unpacks RXMODES's fields from current value of the RXMODES register. + * + * Reads the RXMODES register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] psselect40 - Will be populated with the current value of this field from the register. + * @param[out] psselect20 - Will be populated with the current value of this field from the register. + * @param[out] forcenss1 - Will be populated with the current value of this field from the register. + * @param[out] force40 - Will be populated with the current value of this field from the register. + * @param[out] force20 - Will be populated with the current value of this field from the register. + * @param[out] rxstbcen - Will be populated with the current value of this field from the register. + * @param[out] dupmrcen - Will be populated with the current value of this field from the register. + * @param[out] rxallowvht - Will be populated with the current value of this field from the register. + * @param[out] rxallowgf - Will be populated with the current value of this field from the register. + * @param[out] rxallowmm - Will be populated with the current value of this field from the register. + * @param[out] rxallowlegacy - Will be populated with the current value of this field from the register. + * @param[out] rxallowdsss - Will be populated with the current value of this field from the register. + */ +__INLINE void mdm_rxmodes_unpack(uint8_t *psselect40, uint8_t *psselect20, uint8_t *forcenss1, uint8_t *force40, uint8_t *force20, uint8_t *rxstbcen, uint8_t *dupmrcen, uint8_t *rxallowvht, uint8_t *rxallowgf, uint8_t *rxallowmm, uint8_t *rxallowlegacy, uint8_t *rxallowdsss) +{ + uint32_t localVal = REG_PL_RD(MDM_RXMODES_ADDR); + + *psselect40 = (localVal & ((uint32_t)0x00020000)) >> 17; + *psselect20 = (localVal & ((uint32_t)0x00010000)) >> 16; + *forcenss1 = (localVal & ((uint32_t)0x00004000)) >> 14; + *force40 = (localVal & ((uint32_t)0x00002000)) >> 13; + *force20 = (localVal & ((uint32_t)0x00001000)) >> 12; + *rxstbcen = (localVal & ((uint32_t)0x00000200)) >> 9; + *dupmrcen = (localVal & ((uint32_t)0x00000100)) >> 8; + *rxallowvht = (localVal & ((uint32_t)0x00000010)) >> 4; + *rxallowgf = (localVal & ((uint32_t)0x00000008)) >> 3; + *rxallowmm = (localVal & ((uint32_t)0x00000004)) >> 2; + *rxallowlegacy = (localVal & ((uint32_t)0x00000002)) >> 1; + *rxallowdsss = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +/** + * @brief Returns the current value of the PSSELECT40 field in the RXMODES register. + * + * The RXMODES register will be read and the PSSELECT40 field's value will be returned. + * + * @return The current value of the PSSELECT40 field in the RXMODES register. + */ +__INLINE uint8_t mdm_psselect40_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXMODES_ADDR); + return ((localVal & ((uint32_t)0x00020000)) >> 17); +} + +/** + * @brief Sets the PSSELECT40 field of the RXMODES register. + * + * The RXMODES register will be read, modified to contain the new field value, and written. + * + * @param[in] psselect40 - The value to set the field to. + */ +__INLINE void mdm_psselect40_setf(uint8_t psselect40) +{ + ASSERT_ERR((((uint32_t)psselect40 << 17) & ~((uint32_t)0x00020000)) == 0); + REG_PL_WR(MDM_RXMODES_ADDR, (REG_PL_RD(MDM_RXMODES_ADDR) & ~((uint32_t)0x00020000)) | ((uint32_t)psselect40 << 17)); +} + +/** + * @brief Returns the current value of the PSSELECT20 field in the RXMODES register. + * + * The RXMODES register will be read and the PSSELECT20 field's value will be returned. + * + * @return The current value of the PSSELECT20 field in the RXMODES register. + */ +__INLINE uint8_t mdm_psselect20_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXMODES_ADDR); + return ((localVal & ((uint32_t)0x00010000)) >> 16); +} + +/** + * @brief Sets the PSSELECT20 field of the RXMODES register. + * + * The RXMODES register will be read, modified to contain the new field value, and written. + * + * @param[in] psselect20 - The value to set the field to. + */ +__INLINE void mdm_psselect20_setf(uint8_t psselect20) +{ + ASSERT_ERR((((uint32_t)psselect20 << 16) & ~((uint32_t)0x00010000)) == 0); + REG_PL_WR(MDM_RXMODES_ADDR, (REG_PL_RD(MDM_RXMODES_ADDR) & ~((uint32_t)0x00010000)) | ((uint32_t)psselect20 << 16)); +} + +/** + * @brief Returns the current value of the FORCENSS1 field in the RXMODES register. + * + * The RXMODES register will be read and the FORCENSS1 field's value will be returned. + * + * @return The current value of the FORCENSS1 field in the RXMODES register. + */ +__INLINE uint8_t mdm_forcenss1_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXMODES_ADDR); + return ((localVal & ((uint32_t)0x00004000)) >> 14); +} + +/** + * @brief Sets the FORCENSS1 field of the RXMODES register. + * + * The RXMODES register will be read, modified to contain the new field value, and written. + * + * @param[in] forcenss1 - The value to set the field to. + */ +__INLINE void mdm_forcenss1_setf(uint8_t forcenss1) +{ + ASSERT_ERR((((uint32_t)forcenss1 << 14) & ~((uint32_t)0x00004000)) == 0); + REG_PL_WR(MDM_RXMODES_ADDR, (REG_PL_RD(MDM_RXMODES_ADDR) & ~((uint32_t)0x00004000)) | ((uint32_t)forcenss1 << 14)); +} + +/** + * @brief Returns the current value of the FORCE40 field in the RXMODES register. + * + * The RXMODES register will be read and the FORCE40 field's value will be returned. + * + * @return The current value of the FORCE40 field in the RXMODES register. + */ +__INLINE uint8_t mdm_force40_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXMODES_ADDR); + return ((localVal & ((uint32_t)0x00002000)) >> 13); +} + +/** + * @brief Sets the FORCE40 field of the RXMODES register. + * + * The RXMODES register will be read, modified to contain the new field value, and written. + * + * @param[in] force40 - The value to set the field to. + */ +__INLINE void mdm_force40_setf(uint8_t force40) +{ + ASSERT_ERR((((uint32_t)force40 << 13) & ~((uint32_t)0x00002000)) == 0); + REG_PL_WR(MDM_RXMODES_ADDR, (REG_PL_RD(MDM_RXMODES_ADDR) & ~((uint32_t)0x00002000)) | ((uint32_t)force40 << 13)); +} + +/** + * @brief Returns the current value of the FORCE20 field in the RXMODES register. + * + * The RXMODES register will be read and the FORCE20 field's value will be returned. + * + * @return The current value of the FORCE20 field in the RXMODES register. + */ +__INLINE uint8_t mdm_force20_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXMODES_ADDR); + return ((localVal & ((uint32_t)0x00001000)) >> 12); +} + +/** + * @brief Sets the FORCE20 field of the RXMODES register. + * + * The RXMODES register will be read, modified to contain the new field value, and written. + * + * @param[in] force20 - The value to set the field to. + */ +__INLINE void mdm_force20_setf(uint8_t force20) +{ + ASSERT_ERR((((uint32_t)force20 << 12) & ~((uint32_t)0x00001000)) == 0); + REG_PL_WR(MDM_RXMODES_ADDR, (REG_PL_RD(MDM_RXMODES_ADDR) & ~((uint32_t)0x00001000)) | ((uint32_t)force20 << 12)); +} + +/** + * @brief Returns the current value of the RXSTBCEN field in the RXMODES register. + * + * The RXMODES register will be read and the RXSTBCEN field's value will be returned. + * + * @return The current value of the RXSTBCEN field in the RXMODES register. + */ +__INLINE uint8_t mdm_rxstbcen_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXMODES_ADDR); + return ((localVal & ((uint32_t)0x00000200)) >> 9); +} + +/** + * @brief Sets the RXSTBCEN field of the RXMODES register. + * + * The RXMODES register will be read, modified to contain the new field value, and written. + * + * @param[in] rxstbcen - The value to set the field to. + */ +__INLINE void mdm_rxstbcen_setf(uint8_t rxstbcen) +{ + ASSERT_ERR((((uint32_t)rxstbcen << 9) & ~((uint32_t)0x00000200)) == 0); + REG_PL_WR(MDM_RXMODES_ADDR, (REG_PL_RD(MDM_RXMODES_ADDR) & ~((uint32_t)0x00000200)) | ((uint32_t)rxstbcen << 9)); +} + +/** + * @brief Returns the current value of the DUPMRCEN field in the RXMODES register. + * + * The RXMODES register will be read and the DUPMRCEN field's value will be returned. + * + * @return The current value of the DUPMRCEN field in the RXMODES register. + */ +__INLINE uint8_t mdm_dupmrcen_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXMODES_ADDR); + return ((localVal & ((uint32_t)0x00000100)) >> 8); +} + +/** + * @brief Sets the DUPMRCEN field of the RXMODES register. + * + * The RXMODES register will be read, modified to contain the new field value, and written. + * + * @param[in] dupmrcen - The value to set the field to. + */ +__INLINE void mdm_dupmrcen_setf(uint8_t dupmrcen) +{ + ASSERT_ERR((((uint32_t)dupmrcen << 8) & ~((uint32_t)0x00000100)) == 0); + REG_PL_WR(MDM_RXMODES_ADDR, (REG_PL_RD(MDM_RXMODES_ADDR) & ~((uint32_t)0x00000100)) | ((uint32_t)dupmrcen << 8)); +} + +/** + * @brief Returns the current value of the RXALLOWVHT field in the RXMODES register. + * + * The RXMODES register will be read and the RXALLOWVHT field's value will be returned. + * + * @return The current value of the RXALLOWVHT field in the RXMODES register. + */ +__INLINE uint8_t mdm_rxallowvht_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXMODES_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +/** + * @brief Sets the RXALLOWVHT field of the RXMODES register. + * + * The RXMODES register will be read, modified to contain the new field value, and written. + * + * @param[in] rxallowvht - The value to set the field to. + */ +__INLINE void mdm_rxallowvht_setf(uint8_t rxallowvht) +{ + ASSERT_ERR((((uint32_t)rxallowvht << 4) & ~((uint32_t)0x00000010)) == 0); + REG_PL_WR(MDM_RXMODES_ADDR, (REG_PL_RD(MDM_RXMODES_ADDR) & ~((uint32_t)0x00000010)) | ((uint32_t)rxallowvht << 4)); +} + +/** + * @brief Returns the current value of the RXALLOWGF field in the RXMODES register. + * + * The RXMODES register will be read and the RXALLOWGF field's value will be returned. + * + * @return The current value of the RXALLOWGF field in the RXMODES register. + */ +__INLINE uint8_t mdm_rxallowgf_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXMODES_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +/** + * @brief Sets the RXALLOWGF field of the RXMODES register. + * + * The RXMODES register will be read, modified to contain the new field value, and written. + * + * @param[in] rxallowgf - The value to set the field to. + */ +__INLINE void mdm_rxallowgf_setf(uint8_t rxallowgf) +{ + ASSERT_ERR((((uint32_t)rxallowgf << 3) & ~((uint32_t)0x00000008)) == 0); + REG_PL_WR(MDM_RXMODES_ADDR, (REG_PL_RD(MDM_RXMODES_ADDR) & ~((uint32_t)0x00000008)) | ((uint32_t)rxallowgf << 3)); +} + +/** + * @brief Returns the current value of the RXALLOWMM field in the RXMODES register. + * + * The RXMODES register will be read and the RXALLOWMM field's value will be returned. + * + * @return The current value of the RXALLOWMM field in the RXMODES register. + */ +__INLINE uint8_t mdm_rxallowmm_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXMODES_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +/** + * @brief Sets the RXALLOWMM field of the RXMODES register. + * + * The RXMODES register will be read, modified to contain the new field value, and written. + * + * @param[in] rxallowmm - The value to set the field to. + */ +__INLINE void mdm_rxallowmm_setf(uint8_t rxallowmm) +{ + ASSERT_ERR((((uint32_t)rxallowmm << 2) & ~((uint32_t)0x00000004)) == 0); + REG_PL_WR(MDM_RXMODES_ADDR, (REG_PL_RD(MDM_RXMODES_ADDR) & ~((uint32_t)0x00000004)) | ((uint32_t)rxallowmm << 2)); +} + +/** + * @brief Returns the current value of the RXALLOWLEGACY field in the RXMODES register. + * + * The RXMODES register will be read and the RXALLOWLEGACY field's value will be returned. + * + * @return The current value of the RXALLOWLEGACY field in the RXMODES register. + */ +__INLINE uint8_t mdm_rxallowlegacy_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXMODES_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +/** + * @brief Sets the RXALLOWLEGACY field of the RXMODES register. + * + * The RXMODES register will be read, modified to contain the new field value, and written. + * + * @param[in] rxallowlegacy - The value to set the field to. + */ +__INLINE void mdm_rxallowlegacy_setf(uint8_t rxallowlegacy) +{ + ASSERT_ERR((((uint32_t)rxallowlegacy << 1) & ~((uint32_t)0x00000002)) == 0); + REG_PL_WR(MDM_RXMODES_ADDR, (REG_PL_RD(MDM_RXMODES_ADDR) & ~((uint32_t)0x00000002)) | ((uint32_t)rxallowlegacy << 1)); +} + +/** + * @brief Returns the current value of the RXALLOWDSSS field in the RXMODES register. + * + * The RXMODES register will be read and the RXALLOWDSSS field's value will be returned. + * + * @return The current value of the RXALLOWDSSS field in the RXMODES register. + */ +__INLINE uint8_t mdm_rxallowdsss_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXMODES_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/** + * @brief Sets the RXALLOWDSSS field of the RXMODES register. + * + * The RXMODES register will be read, modified to contain the new field value, and written. + * + * @param[in] rxallowdsss - The value to set the field to. + */ +__INLINE void mdm_rxallowdsss_setf(uint8_t rxallowdsss) +{ + ASSERT_ERR((((uint32_t)rxallowdsss << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(MDM_RXMODES_ADDR, (REG_PL_RD(MDM_RXMODES_ADDR) & ~((uint32_t)0x00000001)) | ((uint32_t)rxallowdsss << 0)); +} + +/// @} + +/** + * @name RXTXPWRCTRL register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     02                 TXON   1
+ *     01             AGCCCAON   1
+ *     00                 RXON   1
+ * 
+ * + * @{ + */ + +/// Address of the RXTXPWRCTRL register +#define MDM_RXTXPWRCTRL_ADDR 0x01000804 +/// Offset of the RXTXPWRCTRL register from the base address +#define MDM_RXTXPWRCTRL_OFFSET 0x00000804 +/// Index of the RXTXPWRCTRL register +#define MDM_RXTXPWRCTRL_INDEX 0x00000201 +/// Reset value of the RXTXPWRCTRL register +#define MDM_RXTXPWRCTRL_RESET 0x00000007 + +/** + * @brief Returns the current value of the RXTXPWRCTRL register. + * The RXTXPWRCTRL register will be read and its value returned. + * @return The current value of the RXTXPWRCTRL register. + */ +__INLINE uint32_t mdm_rxtxpwrctrl_get(void) +{ + return REG_PL_RD(MDM_RXTXPWRCTRL_ADDR); +} + +/** + * @brief Sets the RXTXPWRCTRL register to a value. + * The RXTXPWRCTRL register will be written. + * @param value - The value to write. + */ +__INLINE void mdm_rxtxpwrctrl_set(uint32_t value) +{ + REG_PL_WR(MDM_RXTXPWRCTRL_ADDR, value); +} + +// field definitions +/// TXON field bit +#define MDM_TXON_BIT ((uint32_t)0x00000004) +/// TXON field position +#define MDM_TXON_POS 2 +/// AGCCCAON field bit +#define MDM_AGCCCAON_BIT ((uint32_t)0x00000002) +/// AGCCCAON field position +#define MDM_AGCCCAON_POS 1 +/// RXON field bit +#define MDM_RXON_BIT ((uint32_t)0x00000001) +/// RXON field position +#define MDM_RXON_POS 0 + +/// TXON field reset value +#define MDM_TXON_RST 0x1 +/// AGCCCAON field reset value +#define MDM_AGCCCAON_RST 0x1 +/// RXON field reset value +#define MDM_RXON_RST 0x1 + +/** + * @brief Constructs a value for the RXTXPWRCTRL register given values for its fields + * and writes the value to the register. + * + * @param[in] txon - The value to use for the TXON field. + * @param[in] agcccaon - The value to use for the AGCCCAON field. + * @param[in] rxon - The value to use for the RXON field. + */ +__INLINE void mdm_rxtxpwrctrl_pack(uint8_t txon, uint8_t agcccaon, uint8_t rxon) +{ + ASSERT_ERR((((uint32_t)txon << 2) & ~((uint32_t)0x00000004)) == 0); + ASSERT_ERR((((uint32_t)agcccaon << 1) & ~((uint32_t)0x00000002)) == 0); + ASSERT_ERR((((uint32_t)rxon << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(MDM_RXTXPWRCTRL_ADDR, ((uint32_t)txon << 2) | ((uint32_t)agcccaon << 1) | ((uint32_t)rxon << 0)); +} + +/** + * @brief Unpacks RXTXPWRCTRL's fields from current value of the RXTXPWRCTRL register. + * + * Reads the RXTXPWRCTRL register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] txon - Will be populated with the current value of this field from the register. + * @param[out] agcccaon - Will be populated with the current value of this field from the register. + * @param[out] rxon - Will be populated with the current value of this field from the register. + */ +__INLINE void mdm_rxtxpwrctrl_unpack(uint8_t *txon, uint8_t *agcccaon, uint8_t *rxon) +{ + uint32_t localVal = REG_PL_RD(MDM_RXTXPWRCTRL_ADDR); + + *txon = (localVal & ((uint32_t)0x00000004)) >> 2; + *agcccaon = (localVal & ((uint32_t)0x00000002)) >> 1; + *rxon = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +/** + * @brief Returns the current value of the TXON field in the RXTXPWRCTRL register. + * + * The RXTXPWRCTRL register will be read and the TXON field's value will be returned. + * + * @return The current value of the TXON field in the RXTXPWRCTRL register. + */ +__INLINE uint8_t mdm_txon_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXTXPWRCTRL_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +/** + * @brief Sets the TXON field of the RXTXPWRCTRL register. + * + * The RXTXPWRCTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] txon - The value to set the field to. + */ +__INLINE void mdm_txon_setf(uint8_t txon) +{ + ASSERT_ERR((((uint32_t)txon << 2) & ~((uint32_t)0x00000004)) == 0); + REG_PL_WR(MDM_RXTXPWRCTRL_ADDR, (REG_PL_RD(MDM_RXTXPWRCTRL_ADDR) & ~((uint32_t)0x00000004)) | ((uint32_t)txon << 2)); +} + +/** + * @brief Returns the current value of the AGCCCAON field in the RXTXPWRCTRL register. + * + * The RXTXPWRCTRL register will be read and the AGCCCAON field's value will be returned. + * + * @return The current value of the AGCCCAON field in the RXTXPWRCTRL register. + */ +__INLINE uint8_t mdm_agcccaon_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXTXPWRCTRL_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +/** + * @brief Sets the AGCCCAON field of the RXTXPWRCTRL register. + * + * The RXTXPWRCTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] agcccaon - The value to set the field to. + */ +__INLINE void mdm_agcccaon_setf(uint8_t agcccaon) +{ + ASSERT_ERR((((uint32_t)agcccaon << 1) & ~((uint32_t)0x00000002)) == 0); + REG_PL_WR(MDM_RXTXPWRCTRL_ADDR, (REG_PL_RD(MDM_RXTXPWRCTRL_ADDR) & ~((uint32_t)0x00000002)) | ((uint32_t)agcccaon << 1)); +} + +/** + * @brief Returns the current value of the RXON field in the RXTXPWRCTRL register. + * + * The RXTXPWRCTRL register will be read and the RXON field's value will be returned. + * + * @return The current value of the RXON field in the RXTXPWRCTRL register. + */ +__INLINE uint8_t mdm_rxon_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXTXPWRCTRL_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/** + * @brief Sets the RXON field of the RXTXPWRCTRL register. + * + * The RXTXPWRCTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] rxon - The value to set the field to. + */ +__INLINE void mdm_rxon_setf(uint8_t rxon) +{ + ASSERT_ERR((((uint32_t)rxon << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(MDM_RXTXPWRCTRL_ADDR, (REG_PL_RD(MDM_RXTXPWRCTRL_ADDR) & ~((uint32_t)0x00000001)) | ((uint32_t)rxon << 0)); +} + +/// @} + +/** + * @name STOCPECTRL0 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31        CFGSTO4TDCOMP   1
+ *     30           CFGCPEWALK   1
+ *     29            CFGSTOREF   1
+ *     28            CFGCPEREF   1
+ *     25         CPESLOPELGHT   1
+ *     24         STOSLOPELGHT   1
+ *     23              CPEMODE   1
+ *     22              STOMODE   1
+ *  16:11       MAXNTDSYNCHOFF   0x1F
+ *  10:05       MAXPTDSYNCHOFF   0x1F
+ *     04          STOFDCOMPEN   1
+ *     03        CPESLOPEESTEN   1
+ *     02          CPEFDCOMPEN   1
+ *     01        STOSLOPEESTEN   1
+ *     00          STOTDCOMPEN   1
+ * 
+ * + * @{ + */ + +/// Address of the STOCPECTRL0 register +#define MDM_STOCPECTRL0_ADDR 0x01000808 +/// Offset of the STOCPECTRL0 register from the base address +#define MDM_STOCPECTRL0_OFFSET 0x00000808 +/// Index of the STOCPECTRL0 register +#define MDM_STOCPECTRL0_INDEX 0x00000202 +/// Reset value of the STOCPECTRL0 register +#define MDM_STOCPECTRL0_RESET 0xF3C0FBFF + +/** + * @brief Returns the current value of the STOCPECTRL0 register. + * The STOCPECTRL0 register will be read and its value returned. + * @return The current value of the STOCPECTRL0 register. + */ +__INLINE uint32_t mdm_stocpectrl0_get(void) +{ + return REG_PL_RD(MDM_STOCPECTRL0_ADDR); +} + +/** + * @brief Sets the STOCPECTRL0 register to a value. + * The STOCPECTRL0 register will be written. + * @param value - The value to write. + */ +__INLINE void mdm_stocpectrl0_set(uint32_t value) +{ + REG_PL_WR(MDM_STOCPECTRL0_ADDR, value); +} + +// field definitions +/// CFGSTO4TDCOMP field bit +#define MDM_CFGSTO4TDCOMP_BIT ((uint32_t)0x80000000) +/// CFGSTO4TDCOMP field position +#define MDM_CFGSTO4TDCOMP_POS 31 +/// CFGCPEWALK field bit +#define MDM_CFGCPEWALK_BIT ((uint32_t)0x40000000) +/// CFGCPEWALK field position +#define MDM_CFGCPEWALK_POS 30 +/// CFGSTOREF field bit +#define MDM_CFGSTOREF_BIT ((uint32_t)0x20000000) +/// CFGSTOREF field position +#define MDM_CFGSTOREF_POS 29 +/// CFGCPEREF field bit +#define MDM_CFGCPEREF_BIT ((uint32_t)0x10000000) +/// CFGCPEREF field position +#define MDM_CFGCPEREF_POS 28 +/// CPESLOPELGHT field bit +#define MDM_CPESLOPELGHT_BIT ((uint32_t)0x02000000) +/// CPESLOPELGHT field position +#define MDM_CPESLOPELGHT_POS 25 +/// STOSLOPELGHT field bit +#define MDM_STOSLOPELGHT_BIT ((uint32_t)0x01000000) +/// STOSLOPELGHT field position +#define MDM_STOSLOPELGHT_POS 24 +/// CPEMODE field bit +#define MDM_CPEMODE_BIT ((uint32_t)0x00800000) +/// CPEMODE field position +#define MDM_CPEMODE_POS 23 +/// STOMODE field bit +#define MDM_STOMODE_BIT ((uint32_t)0x00400000) +/// STOMODE field position +#define MDM_STOMODE_POS 22 +/// MAXNTDSYNCHOFF field mask +#define MDM_MAXNTDSYNCHOFF_MASK ((uint32_t)0x0001F800) +/// MAXNTDSYNCHOFF field LSB position +#define MDM_MAXNTDSYNCHOFF_LSB 11 +/// MAXNTDSYNCHOFF field width +#define MDM_MAXNTDSYNCHOFF_WIDTH ((uint32_t)0x00000006) +/// MAXPTDSYNCHOFF field mask +#define MDM_MAXPTDSYNCHOFF_MASK ((uint32_t)0x000007E0) +/// MAXPTDSYNCHOFF field LSB position +#define MDM_MAXPTDSYNCHOFF_LSB 5 +/// MAXPTDSYNCHOFF field width +#define MDM_MAXPTDSYNCHOFF_WIDTH ((uint32_t)0x00000006) +/// STOFDCOMPEN field bit +#define MDM_STOFDCOMPEN_BIT ((uint32_t)0x00000010) +/// STOFDCOMPEN field position +#define MDM_STOFDCOMPEN_POS 4 +/// CPESLOPEESTEN field bit +#define MDM_CPESLOPEESTEN_BIT ((uint32_t)0x00000008) +/// CPESLOPEESTEN field position +#define MDM_CPESLOPEESTEN_POS 3 +/// CPEFDCOMPEN field bit +#define MDM_CPEFDCOMPEN_BIT ((uint32_t)0x00000004) +/// CPEFDCOMPEN field position +#define MDM_CPEFDCOMPEN_POS 2 +/// STOSLOPEESTEN field bit +#define MDM_STOSLOPEESTEN_BIT ((uint32_t)0x00000002) +/// STOSLOPEESTEN field position +#define MDM_STOSLOPEESTEN_POS 1 +/// STOTDCOMPEN field bit +#define MDM_STOTDCOMPEN_BIT ((uint32_t)0x00000001) +/// STOTDCOMPEN field position +#define MDM_STOTDCOMPEN_POS 0 + +/// CFGSTO4TDCOMP field reset value +#define MDM_CFGSTO4TDCOMP_RST 0x1 +/// CFGCPEWALK field reset value +#define MDM_CFGCPEWALK_RST 0x1 +/// CFGSTOREF field reset value +#define MDM_CFGSTOREF_RST 0x1 +/// CFGCPEREF field reset value +#define MDM_CFGCPEREF_RST 0x1 +/// CPESLOPELGHT field reset value +#define MDM_CPESLOPELGHT_RST 0x1 +/// STOSLOPELGHT field reset value +#define MDM_STOSLOPELGHT_RST 0x1 +/// CPEMODE field reset value +#define MDM_CPEMODE_RST 0x1 +/// STOMODE field reset value +#define MDM_STOMODE_RST 0x1 +/// MAXNTDSYNCHOFF field reset value +#define MDM_MAXNTDSYNCHOFF_RST 0x1F +/// MAXPTDSYNCHOFF field reset value +#define MDM_MAXPTDSYNCHOFF_RST 0x1F +/// STOFDCOMPEN field reset value +#define MDM_STOFDCOMPEN_RST 0x1 +/// CPESLOPEESTEN field reset value +#define MDM_CPESLOPEESTEN_RST 0x1 +/// CPEFDCOMPEN field reset value +#define MDM_CPEFDCOMPEN_RST 0x1 +/// STOSLOPEESTEN field reset value +#define MDM_STOSLOPEESTEN_RST 0x1 +/// STOTDCOMPEN field reset value +#define MDM_STOTDCOMPEN_RST 0x1 + +/** + * @brief Constructs a value for the STOCPECTRL0 register given values for its fields + * and writes the value to the register. + * + * @param[in] cfgsto4tdcomp - The value to use for the CFGSTO4TDCOMP field. + * @param[in] cfgcpewalk - The value to use for the CFGCPEWALK field. + * @param[in] cfgstoref - The value to use for the CFGSTOREF field. + * @param[in] cfgcperef - The value to use for the CFGCPEREF field. + * @param[in] cpeslopelght - The value to use for the CPESLOPELGHT field. + * @param[in] stoslopelght - The value to use for the STOSLOPELGHT field. + * @param[in] cpemode - The value to use for the CPEMODE field. + * @param[in] stomode - The value to use for the STOMODE field. + * @param[in] maxntdsynchoff - The value to use for the MAXNTDSYNCHOFF field. + * @param[in] maxptdsynchoff - The value to use for the MAXPTDSYNCHOFF field. + * @param[in] stofdcompen - The value to use for the STOFDCOMPEN field. + * @param[in] cpeslopeesten - The value to use for the CPESLOPEESTEN field. + * @param[in] cpefdcompen - The value to use for the CPEFDCOMPEN field. + * @param[in] stoslopeesten - The value to use for the STOSLOPEESTEN field. + * @param[in] stotdcompen - The value to use for the STOTDCOMPEN field. + */ +__INLINE void mdm_stocpectrl0_pack(uint8_t cfgsto4tdcomp, uint8_t cfgcpewalk, uint8_t cfgstoref, uint8_t cfgcperef, uint8_t cpeslopelght, uint8_t stoslopelght, uint8_t cpemode, uint8_t stomode, uint8_t maxntdsynchoff, uint8_t maxptdsynchoff, uint8_t stofdcompen, uint8_t cpeslopeesten, uint8_t cpefdcompen, uint8_t stoslopeesten, uint8_t stotdcompen) +{ + ASSERT_ERR((((uint32_t)cfgsto4tdcomp << 31) & ~((uint32_t)0x80000000)) == 0); + ASSERT_ERR((((uint32_t)cfgcpewalk << 30) & ~((uint32_t)0x40000000)) == 0); + ASSERT_ERR((((uint32_t)cfgstoref << 29) & ~((uint32_t)0x20000000)) == 0); + ASSERT_ERR((((uint32_t)cfgcperef << 28) & ~((uint32_t)0x10000000)) == 0); + ASSERT_ERR((((uint32_t)cpeslopelght << 25) & ~((uint32_t)0x02000000)) == 0); + ASSERT_ERR((((uint32_t)stoslopelght << 24) & ~((uint32_t)0x01000000)) == 0); + ASSERT_ERR((((uint32_t)cpemode << 23) & ~((uint32_t)0x00800000)) == 0); + ASSERT_ERR((((uint32_t)stomode << 22) & ~((uint32_t)0x00400000)) == 0); + ASSERT_ERR((((uint32_t)maxntdsynchoff << 11) & ~((uint32_t)0x0001F800)) == 0); + ASSERT_ERR((((uint32_t)maxptdsynchoff << 5) & ~((uint32_t)0x000007E0)) == 0); + ASSERT_ERR((((uint32_t)stofdcompen << 4) & ~((uint32_t)0x00000010)) == 0); + ASSERT_ERR((((uint32_t)cpeslopeesten << 3) & ~((uint32_t)0x00000008)) == 0); + ASSERT_ERR((((uint32_t)cpefdcompen << 2) & ~((uint32_t)0x00000004)) == 0); + ASSERT_ERR((((uint32_t)stoslopeesten << 1) & ~((uint32_t)0x00000002)) == 0); + ASSERT_ERR((((uint32_t)stotdcompen << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(MDM_STOCPECTRL0_ADDR, ((uint32_t)cfgsto4tdcomp << 31) | ((uint32_t)cfgcpewalk << 30) | ((uint32_t)cfgstoref << 29) | ((uint32_t)cfgcperef << 28) | ((uint32_t)cpeslopelght << 25) | ((uint32_t)stoslopelght << 24) | ((uint32_t)cpemode << 23) | ((uint32_t)stomode << 22) | ((uint32_t)maxntdsynchoff << 11) | ((uint32_t)maxptdsynchoff << 5) | ((uint32_t)stofdcompen << 4) | ((uint32_t)cpeslopeesten << 3) | ((uint32_t)cpefdcompen << 2) | ((uint32_t)stoslopeesten << 1) | ((uint32_t)stotdcompen << 0)); +} + +/** + * @brief Unpacks STOCPECTRL0's fields from current value of the STOCPECTRL0 register. + * + * Reads the STOCPECTRL0 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] cfgsto4tdcomp - Will be populated with the current value of this field from the register. + * @param[out] cfgcpewalk - Will be populated with the current value of this field from the register. + * @param[out] cfgstoref - Will be populated with the current value of this field from the register. + * @param[out] cfgcperef - Will be populated with the current value of this field from the register. + * @param[out] cpeslopelght - Will be populated with the current value of this field from the register. + * @param[out] stoslopelght - Will be populated with the current value of this field from the register. + * @param[out] cpemode - Will be populated with the current value of this field from the register. + * @param[out] stomode - Will be populated with the current value of this field from the register. + * @param[out] maxntdsynchoff - Will be populated with the current value of this field from the register. + * @param[out] maxptdsynchoff - Will be populated with the current value of this field from the register. + * @param[out] stofdcompen - Will be populated with the current value of this field from the register. + * @param[out] cpeslopeesten - Will be populated with the current value of this field from the register. + * @param[out] cpefdcompen - Will be populated with the current value of this field from the register. + * @param[out] stoslopeesten - Will be populated with the current value of this field from the register. + * @param[out] stotdcompen - Will be populated with the current value of this field from the register. + */ +__INLINE void mdm_stocpectrl0_unpack(uint8_t *cfgsto4tdcomp, uint8_t *cfgcpewalk, uint8_t *cfgstoref, uint8_t *cfgcperef, uint8_t *cpeslopelght, uint8_t *stoslopelght, uint8_t *cpemode, uint8_t *stomode, uint8_t *maxntdsynchoff, uint8_t *maxptdsynchoff, uint8_t *stofdcompen, uint8_t *cpeslopeesten, uint8_t *cpefdcompen, uint8_t *stoslopeesten, uint8_t *stotdcompen) +{ + uint32_t localVal = REG_PL_RD(MDM_STOCPECTRL0_ADDR); + + *cfgsto4tdcomp = (localVal & ((uint32_t)0x80000000)) >> 31; + *cfgcpewalk = (localVal & ((uint32_t)0x40000000)) >> 30; + *cfgstoref = (localVal & ((uint32_t)0x20000000)) >> 29; + *cfgcperef = (localVal & ((uint32_t)0x10000000)) >> 28; + *cpeslopelght = (localVal & ((uint32_t)0x02000000)) >> 25; + *stoslopelght = (localVal & ((uint32_t)0x01000000)) >> 24; + *cpemode = (localVal & ((uint32_t)0x00800000)) >> 23; + *stomode = (localVal & ((uint32_t)0x00400000)) >> 22; + *maxntdsynchoff = (localVal & ((uint32_t)0x0001F800)) >> 11; + *maxptdsynchoff = (localVal & ((uint32_t)0x000007E0)) >> 5; + *stofdcompen = (localVal & ((uint32_t)0x00000010)) >> 4; + *cpeslopeesten = (localVal & ((uint32_t)0x00000008)) >> 3; + *cpefdcompen = (localVal & ((uint32_t)0x00000004)) >> 2; + *stoslopeesten = (localVal & ((uint32_t)0x00000002)) >> 1; + *stotdcompen = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +/** + * @brief Returns the current value of the CFGSTO4TDCOMP field in the STOCPECTRL0 register. + * + * The STOCPECTRL0 register will be read and the CFGSTO4TDCOMP field's value will be returned. + * + * @return The current value of the CFGSTO4TDCOMP field in the STOCPECTRL0 register. + */ +__INLINE uint8_t mdm_cfgsto4tdcomp_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_STOCPECTRL0_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +/** + * @brief Sets the CFGSTO4TDCOMP field of the STOCPECTRL0 register. + * + * The STOCPECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] cfgsto4tdcomp - The value to set the field to. + */ +__INLINE void mdm_cfgsto4tdcomp_setf(uint8_t cfgsto4tdcomp) +{ + ASSERT_ERR((((uint32_t)cfgsto4tdcomp << 31) & ~((uint32_t)0x80000000)) == 0); + REG_PL_WR(MDM_STOCPECTRL0_ADDR, (REG_PL_RD(MDM_STOCPECTRL0_ADDR) & ~((uint32_t)0x80000000)) | ((uint32_t)cfgsto4tdcomp << 31)); +} + +/** + * @brief Returns the current value of the CFGCPEWALK field in the STOCPECTRL0 register. + * + * The STOCPECTRL0 register will be read and the CFGCPEWALK field's value will be returned. + * + * @return The current value of the CFGCPEWALK field in the STOCPECTRL0 register. + */ +__INLINE uint8_t mdm_cfgcpewalk_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_STOCPECTRL0_ADDR); + return ((localVal & ((uint32_t)0x40000000)) >> 30); +} + +/** + * @brief Sets the CFGCPEWALK field of the STOCPECTRL0 register. + * + * The STOCPECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] cfgcpewalk - The value to set the field to. + */ +__INLINE void mdm_cfgcpewalk_setf(uint8_t cfgcpewalk) +{ + ASSERT_ERR((((uint32_t)cfgcpewalk << 30) & ~((uint32_t)0x40000000)) == 0); + REG_PL_WR(MDM_STOCPECTRL0_ADDR, (REG_PL_RD(MDM_STOCPECTRL0_ADDR) & ~((uint32_t)0x40000000)) | ((uint32_t)cfgcpewalk << 30)); +} + +/** + * @brief Returns the current value of the CFGSTOREF field in the STOCPECTRL0 register. + * + * The STOCPECTRL0 register will be read and the CFGSTOREF field's value will be returned. + * + * @return The current value of the CFGSTOREF field in the STOCPECTRL0 register. + */ +__INLINE uint8_t mdm_cfgstoref_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_STOCPECTRL0_ADDR); + return ((localVal & ((uint32_t)0x20000000)) >> 29); +} + +/** + * @brief Sets the CFGSTOREF field of the STOCPECTRL0 register. + * + * The STOCPECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] cfgstoref - The value to set the field to. + */ +__INLINE void mdm_cfgstoref_setf(uint8_t cfgstoref) +{ + ASSERT_ERR((((uint32_t)cfgstoref << 29) & ~((uint32_t)0x20000000)) == 0); + REG_PL_WR(MDM_STOCPECTRL0_ADDR, (REG_PL_RD(MDM_STOCPECTRL0_ADDR) & ~((uint32_t)0x20000000)) | ((uint32_t)cfgstoref << 29)); +} + +/** + * @brief Returns the current value of the CFGCPEREF field in the STOCPECTRL0 register. + * + * The STOCPECTRL0 register will be read and the CFGCPEREF field's value will be returned. + * + * @return The current value of the CFGCPEREF field in the STOCPECTRL0 register. + */ +__INLINE uint8_t mdm_cfgcperef_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_STOCPECTRL0_ADDR); + return ((localVal & ((uint32_t)0x10000000)) >> 28); +} + +/** + * @brief Sets the CFGCPEREF field of the STOCPECTRL0 register. + * + * The STOCPECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] cfgcperef - The value to set the field to. + */ +__INLINE void mdm_cfgcperef_setf(uint8_t cfgcperef) +{ + ASSERT_ERR((((uint32_t)cfgcperef << 28) & ~((uint32_t)0x10000000)) == 0); + REG_PL_WR(MDM_STOCPECTRL0_ADDR, (REG_PL_RD(MDM_STOCPECTRL0_ADDR) & ~((uint32_t)0x10000000)) | ((uint32_t)cfgcperef << 28)); +} + +/** + * @brief Returns the current value of the CPESLOPELGHT field in the STOCPECTRL0 register. + * + * The STOCPECTRL0 register will be read and the CPESLOPELGHT field's value will be returned. + * + * @return The current value of the CPESLOPELGHT field in the STOCPECTRL0 register. + */ +__INLINE uint8_t mdm_cpeslopelght_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_STOCPECTRL0_ADDR); + return ((localVal & ((uint32_t)0x02000000)) >> 25); +} + +/** + * @brief Sets the CPESLOPELGHT field of the STOCPECTRL0 register. + * + * The STOCPECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] cpeslopelght - The value to set the field to. + */ +__INLINE void mdm_cpeslopelght_setf(uint8_t cpeslopelght) +{ + ASSERT_ERR((((uint32_t)cpeslopelght << 25) & ~((uint32_t)0x02000000)) == 0); + REG_PL_WR(MDM_STOCPECTRL0_ADDR, (REG_PL_RD(MDM_STOCPECTRL0_ADDR) & ~((uint32_t)0x02000000)) | ((uint32_t)cpeslopelght << 25)); +} + +/** + * @brief Returns the current value of the STOSLOPELGHT field in the STOCPECTRL0 register. + * + * The STOCPECTRL0 register will be read and the STOSLOPELGHT field's value will be returned. + * + * @return The current value of the STOSLOPELGHT field in the STOCPECTRL0 register. + */ +__INLINE uint8_t mdm_stoslopelght_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_STOCPECTRL0_ADDR); + return ((localVal & ((uint32_t)0x01000000)) >> 24); +} + +/** + * @brief Sets the STOSLOPELGHT field of the STOCPECTRL0 register. + * + * The STOCPECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] stoslopelght - The value to set the field to. + */ +__INLINE void mdm_stoslopelght_setf(uint8_t stoslopelght) +{ + ASSERT_ERR((((uint32_t)stoslopelght << 24) & ~((uint32_t)0x01000000)) == 0); + REG_PL_WR(MDM_STOCPECTRL0_ADDR, (REG_PL_RD(MDM_STOCPECTRL0_ADDR) & ~((uint32_t)0x01000000)) | ((uint32_t)stoslopelght << 24)); +} + +/** + * @brief Returns the current value of the CPEMODE field in the STOCPECTRL0 register. + * + * The STOCPECTRL0 register will be read and the CPEMODE field's value will be returned. + * + * @return The current value of the CPEMODE field in the STOCPECTRL0 register. + */ +__INLINE uint8_t mdm_cpemode_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_STOCPECTRL0_ADDR); + return ((localVal & ((uint32_t)0x00800000)) >> 23); +} + +/** + * @brief Sets the CPEMODE field of the STOCPECTRL0 register. + * + * The STOCPECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] cpemode - The value to set the field to. + */ +__INLINE void mdm_cpemode_setf(uint8_t cpemode) +{ + ASSERT_ERR((((uint32_t)cpemode << 23) & ~((uint32_t)0x00800000)) == 0); + REG_PL_WR(MDM_STOCPECTRL0_ADDR, (REG_PL_RD(MDM_STOCPECTRL0_ADDR) & ~((uint32_t)0x00800000)) | ((uint32_t)cpemode << 23)); +} + +/** + * @brief Returns the current value of the STOMODE field in the STOCPECTRL0 register. + * + * The STOCPECTRL0 register will be read and the STOMODE field's value will be returned. + * + * @return The current value of the STOMODE field in the STOCPECTRL0 register. + */ +__INLINE uint8_t mdm_stomode_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_STOCPECTRL0_ADDR); + return ((localVal & ((uint32_t)0x00400000)) >> 22); +} + +/** + * @brief Sets the STOMODE field of the STOCPECTRL0 register. + * + * The STOCPECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] stomode - The value to set the field to. + */ +__INLINE void mdm_stomode_setf(uint8_t stomode) +{ + ASSERT_ERR((((uint32_t)stomode << 22) & ~((uint32_t)0x00400000)) == 0); + REG_PL_WR(MDM_STOCPECTRL0_ADDR, (REG_PL_RD(MDM_STOCPECTRL0_ADDR) & ~((uint32_t)0x00400000)) | ((uint32_t)stomode << 22)); +} + +/** + * @brief Returns the current value of the MAXNTDSYNCHOFF field in the STOCPECTRL0 register. + * + * The STOCPECTRL0 register will be read and the MAXNTDSYNCHOFF field's value will be returned. + * + * @return The current value of the MAXNTDSYNCHOFF field in the STOCPECTRL0 register. + */ +__INLINE uint8_t mdm_maxntdsynchoff_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_STOCPECTRL0_ADDR); + return ((localVal & ((uint32_t)0x0001F800)) >> 11); +} + +/** + * @brief Sets the MAXNTDSYNCHOFF field of the STOCPECTRL0 register. + * + * The STOCPECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] maxntdsynchoff - The value to set the field to. + */ +__INLINE void mdm_maxntdsynchoff_setf(uint8_t maxntdsynchoff) +{ + ASSERT_ERR((((uint32_t)maxntdsynchoff << 11) & ~((uint32_t)0x0001F800)) == 0); + REG_PL_WR(MDM_STOCPECTRL0_ADDR, (REG_PL_RD(MDM_STOCPECTRL0_ADDR) & ~((uint32_t)0x0001F800)) | ((uint32_t)maxntdsynchoff << 11)); +} + +/** + * @brief Returns the current value of the MAXPTDSYNCHOFF field in the STOCPECTRL0 register. + * + * The STOCPECTRL0 register will be read and the MAXPTDSYNCHOFF field's value will be returned. + * + * @return The current value of the MAXPTDSYNCHOFF field in the STOCPECTRL0 register. + */ +__INLINE uint8_t mdm_maxptdsynchoff_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_STOCPECTRL0_ADDR); + return ((localVal & ((uint32_t)0x000007E0)) >> 5); +} + +/** + * @brief Sets the MAXPTDSYNCHOFF field of the STOCPECTRL0 register. + * + * The STOCPECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] maxptdsynchoff - The value to set the field to. + */ +__INLINE void mdm_maxptdsynchoff_setf(uint8_t maxptdsynchoff) +{ + ASSERT_ERR((((uint32_t)maxptdsynchoff << 5) & ~((uint32_t)0x000007E0)) == 0); + REG_PL_WR(MDM_STOCPECTRL0_ADDR, (REG_PL_RD(MDM_STOCPECTRL0_ADDR) & ~((uint32_t)0x000007E0)) | ((uint32_t)maxptdsynchoff << 5)); +} + +/** + * @brief Returns the current value of the STOFDCOMPEN field in the STOCPECTRL0 register. + * + * The STOCPECTRL0 register will be read and the STOFDCOMPEN field's value will be returned. + * + * @return The current value of the STOFDCOMPEN field in the STOCPECTRL0 register. + */ +__INLINE uint8_t mdm_stofdcompen_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_STOCPECTRL0_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +/** + * @brief Sets the STOFDCOMPEN field of the STOCPECTRL0 register. + * + * The STOCPECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] stofdcompen - The value to set the field to. + */ +__INLINE void mdm_stofdcompen_setf(uint8_t stofdcompen) +{ + ASSERT_ERR((((uint32_t)stofdcompen << 4) & ~((uint32_t)0x00000010)) == 0); + REG_PL_WR(MDM_STOCPECTRL0_ADDR, (REG_PL_RD(MDM_STOCPECTRL0_ADDR) & ~((uint32_t)0x00000010)) | ((uint32_t)stofdcompen << 4)); +} + +/** + * @brief Returns the current value of the CPESLOPEESTEN field in the STOCPECTRL0 register. + * + * The STOCPECTRL0 register will be read and the CPESLOPEESTEN field's value will be returned. + * + * @return The current value of the CPESLOPEESTEN field in the STOCPECTRL0 register. + */ +__INLINE uint8_t mdm_cpeslopeesten_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_STOCPECTRL0_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +/** + * @brief Sets the CPESLOPEESTEN field of the STOCPECTRL0 register. + * + * The STOCPECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] cpeslopeesten - The value to set the field to. + */ +__INLINE void mdm_cpeslopeesten_setf(uint8_t cpeslopeesten) +{ + ASSERT_ERR((((uint32_t)cpeslopeesten << 3) & ~((uint32_t)0x00000008)) == 0); + REG_PL_WR(MDM_STOCPECTRL0_ADDR, (REG_PL_RD(MDM_STOCPECTRL0_ADDR) & ~((uint32_t)0x00000008)) | ((uint32_t)cpeslopeesten << 3)); +} + +/** + * @brief Returns the current value of the CPEFDCOMPEN field in the STOCPECTRL0 register. + * + * The STOCPECTRL0 register will be read and the CPEFDCOMPEN field's value will be returned. + * + * @return The current value of the CPEFDCOMPEN field in the STOCPECTRL0 register. + */ +__INLINE uint8_t mdm_cpefdcompen_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_STOCPECTRL0_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +/** + * @brief Sets the CPEFDCOMPEN field of the STOCPECTRL0 register. + * + * The STOCPECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] cpefdcompen - The value to set the field to. + */ +__INLINE void mdm_cpefdcompen_setf(uint8_t cpefdcompen) +{ + ASSERT_ERR((((uint32_t)cpefdcompen << 2) & ~((uint32_t)0x00000004)) == 0); + REG_PL_WR(MDM_STOCPECTRL0_ADDR, (REG_PL_RD(MDM_STOCPECTRL0_ADDR) & ~((uint32_t)0x00000004)) | ((uint32_t)cpefdcompen << 2)); +} + +/** + * @brief Returns the current value of the STOSLOPEESTEN field in the STOCPECTRL0 register. + * + * The STOCPECTRL0 register will be read and the STOSLOPEESTEN field's value will be returned. + * + * @return The current value of the STOSLOPEESTEN field in the STOCPECTRL0 register. + */ +__INLINE uint8_t mdm_stoslopeesten_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_STOCPECTRL0_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +/** + * @brief Sets the STOSLOPEESTEN field of the STOCPECTRL0 register. + * + * The STOCPECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] stoslopeesten - The value to set the field to. + */ +__INLINE void mdm_stoslopeesten_setf(uint8_t stoslopeesten) +{ + ASSERT_ERR((((uint32_t)stoslopeesten << 1) & ~((uint32_t)0x00000002)) == 0); + REG_PL_WR(MDM_STOCPECTRL0_ADDR, (REG_PL_RD(MDM_STOCPECTRL0_ADDR) & ~((uint32_t)0x00000002)) | ((uint32_t)stoslopeesten << 1)); +} + +/** + * @brief Returns the current value of the STOTDCOMPEN field in the STOCPECTRL0 register. + * + * The STOCPECTRL0 register will be read and the STOTDCOMPEN field's value will be returned. + * + * @return The current value of the STOTDCOMPEN field in the STOCPECTRL0 register. + */ +__INLINE uint8_t mdm_stotdcompen_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_STOCPECTRL0_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/** + * @brief Sets the STOTDCOMPEN field of the STOCPECTRL0 register. + * + * The STOCPECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] stotdcompen - The value to set the field to. + */ +__INLINE void mdm_stotdcompen_setf(uint8_t stotdcompen) +{ + ASSERT_ERR((((uint32_t)stotdcompen << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(MDM_STOCPECTRL0_ADDR, (REG_PL_RD(MDM_STOCPECTRL0_ADDR) & ~((uint32_t)0x00000001)) | ((uint32_t)stotdcompen << 0)); +} + +/// @} + +/** + * @name STOCPECTRL1 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  17:00       STOSLOPEFORCED   0x0
+ * 
+ * + * @{ + */ + +/// Address of the STOCPECTRL1 register +#define MDM_STOCPECTRL1_ADDR 0x0100080C +/// Offset of the STOCPECTRL1 register from the base address +#define MDM_STOCPECTRL1_OFFSET 0x0000080C +/// Index of the STOCPECTRL1 register +#define MDM_STOCPECTRL1_INDEX 0x00000203 +/// Reset value of the STOCPECTRL1 register +#define MDM_STOCPECTRL1_RESET 0x00000000 + +/** + * @brief Returns the current value of the STOCPECTRL1 register. + * The STOCPECTRL1 register will be read and its value returned. + * @return The current value of the STOCPECTRL1 register. + */ +__INLINE uint32_t mdm_stocpectrl1_get(void) +{ + return REG_PL_RD(MDM_STOCPECTRL1_ADDR); +} + +/** + * @brief Sets the STOCPECTRL1 register to a value. + * The STOCPECTRL1 register will be written. + * @param value - The value to write. + */ +__INLINE void mdm_stocpectrl1_set(uint32_t value) +{ + REG_PL_WR(MDM_STOCPECTRL1_ADDR, value); +} + +// field definitions +/// STOSLOPEFORCED field mask +#define MDM_STOSLOPEFORCED_MASK ((uint32_t)0x0003FFFF) +/// STOSLOPEFORCED field LSB position +#define MDM_STOSLOPEFORCED_LSB 0 +/// STOSLOPEFORCED field width +#define MDM_STOSLOPEFORCED_WIDTH ((uint32_t)0x00000012) + +/// STOSLOPEFORCED field reset value +#define MDM_STOSLOPEFORCED_RST 0x0 + +/** + * @brief Returns the current value of the STOSLOPEFORCED field in the STOCPECTRL1 register. + * + * The STOCPECTRL1 register will be read and the STOSLOPEFORCED field's value will be returned. + * + * @return The current value of the STOSLOPEFORCED field in the STOCPECTRL1 register. + */ +__INLINE uint32_t mdm_stoslopeforced_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_STOCPECTRL1_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x0003FFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the STOSLOPEFORCED field of the STOCPECTRL1 register. + * + * The STOCPECTRL1 register will be read, modified to contain the new field value, and written. + * + * @param[in] stoslopeforced - The value to set the field to. + */ +__INLINE void mdm_stoslopeforced_setf(uint32_t stoslopeforced) +{ + ASSERT_ERR((((uint32_t)stoslopeforced << 0) & ~((uint32_t)0x0003FFFF)) == 0); + REG_PL_WR(MDM_STOCPECTRL1_ADDR, (uint32_t)stoslopeforced << 0); +} + +/// @} + +/** + * @name STOCPECTRL2 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  17:00       CPESLOPEFORCED   0x0
+ * 
+ * + * @{ + */ + +/// Address of the STOCPECTRL2 register +#define MDM_STOCPECTRL2_ADDR 0x01000810 +/// Offset of the STOCPECTRL2 register from the base address +#define MDM_STOCPECTRL2_OFFSET 0x00000810 +/// Index of the STOCPECTRL2 register +#define MDM_STOCPECTRL2_INDEX 0x00000204 +/// Reset value of the STOCPECTRL2 register +#define MDM_STOCPECTRL2_RESET 0x00000000 + +/** + * @brief Returns the current value of the STOCPECTRL2 register. + * The STOCPECTRL2 register will be read and its value returned. + * @return The current value of the STOCPECTRL2 register. + */ +__INLINE uint32_t mdm_stocpectrl2_get(void) +{ + return REG_PL_RD(MDM_STOCPECTRL2_ADDR); +} + +/** + * @brief Sets the STOCPECTRL2 register to a value. + * The STOCPECTRL2 register will be written. + * @param value - The value to write. + */ +__INLINE void mdm_stocpectrl2_set(uint32_t value) +{ + REG_PL_WR(MDM_STOCPECTRL2_ADDR, value); +} + +// field definitions +/// CPESLOPEFORCED field mask +#define MDM_CPESLOPEFORCED_MASK ((uint32_t)0x0003FFFF) +/// CPESLOPEFORCED field LSB position +#define MDM_CPESLOPEFORCED_LSB 0 +/// CPESLOPEFORCED field width +#define MDM_CPESLOPEFORCED_WIDTH ((uint32_t)0x00000012) + +/// CPESLOPEFORCED field reset value +#define MDM_CPESLOPEFORCED_RST 0x0 + +/** + * @brief Returns the current value of the CPESLOPEFORCED field in the STOCPECTRL2 register. + * + * The STOCPECTRL2 register will be read and the CPESLOPEFORCED field's value will be returned. + * + * @return The current value of the CPESLOPEFORCED field in the STOCPECTRL2 register. + */ +__INLINE uint32_t mdm_cpeslopeforced_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_STOCPECTRL2_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x0003FFFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the CPESLOPEFORCED field of the STOCPECTRL2 register. + * + * The STOCPECTRL2 register will be read, modified to contain the new field value, and written. + * + * @param[in] cpeslopeforced - The value to set the field to. + */ +__INLINE void mdm_cpeslopeforced_setf(uint32_t cpeslopeforced) +{ + ASSERT_ERR((((uint32_t)cpeslopeforced << 0) & ~((uint32_t)0x0003FFFF)) == 0); + REG_PL_WR(MDM_STOCPECTRL2_ADDR, (uint32_t)cpeslopeforced << 0); +} + +/// @} + +/** + * @name EQUALCTRL register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:29         FDDCWEIGHTP2   0x2
+ *  28:26         FDDCWEIGHTP1   0x3
+ *  25:23         FDDCWEIGHTM1   0x3
+ *  22:20         FDDCWEIGHTM2   0x2
+ *  18:16          QPBSKNSDTHR   0x4
+ *  15:12          QBPSKDETTHR   0xC
+ *  11:04     FDDCSNRTHRESHOLD   0x18
+ *     03           FDDCCOMPEN   1
+ *  02:00        EQUALCFGSATSB   0x3
+ * 
+ * + * @{ + */ + +/// Address of the EQUALCTRL register +#define MDM_EQUALCTRL_ADDR 0x01000814 +/// Offset of the EQUALCTRL register from the base address +#define MDM_EQUALCTRL_OFFSET 0x00000814 +/// Index of the EQUALCTRL register +#define MDM_EQUALCTRL_INDEX 0x00000205 +/// Reset value of the EQUALCTRL register +#define MDM_EQUALCTRL_RESET 0x4DA4C18B + +/** + * @brief Returns the current value of the EQUALCTRL register. + * The EQUALCTRL register will be read and its value returned. + * @return The current value of the EQUALCTRL register. + */ +__INLINE uint32_t mdm_equalctrl_get(void) +{ + return REG_PL_RD(MDM_EQUALCTRL_ADDR); +} + +/** + * @brief Sets the EQUALCTRL register to a value. + * The EQUALCTRL register will be written. + * @param value - The value to write. + */ +__INLINE void mdm_equalctrl_set(uint32_t value) +{ + REG_PL_WR(MDM_EQUALCTRL_ADDR, value); +} + +// field definitions +/// FDDCWEIGHTP2 field mask +#define MDM_FDDCWEIGHTP2_MASK ((uint32_t)0xE0000000) +/// FDDCWEIGHTP2 field LSB position +#define MDM_FDDCWEIGHTP2_LSB 29 +/// FDDCWEIGHTP2 field width +#define MDM_FDDCWEIGHTP2_WIDTH ((uint32_t)0x00000003) +/// FDDCWEIGHTP1 field mask +#define MDM_FDDCWEIGHTP1_MASK ((uint32_t)0x1C000000) +/// FDDCWEIGHTP1 field LSB position +#define MDM_FDDCWEIGHTP1_LSB 26 +/// FDDCWEIGHTP1 field width +#define MDM_FDDCWEIGHTP1_WIDTH ((uint32_t)0x00000003) +/// FDDCWEIGHTM1 field mask +#define MDM_FDDCWEIGHTM1_MASK ((uint32_t)0x03800000) +/// FDDCWEIGHTM1 field LSB position +#define MDM_FDDCWEIGHTM1_LSB 23 +/// FDDCWEIGHTM1 field width +#define MDM_FDDCWEIGHTM1_WIDTH ((uint32_t)0x00000003) +/// FDDCWEIGHTM2 field mask +#define MDM_FDDCWEIGHTM2_MASK ((uint32_t)0x00700000) +/// FDDCWEIGHTM2 field LSB position +#define MDM_FDDCWEIGHTM2_LSB 20 +/// FDDCWEIGHTM2 field width +#define MDM_FDDCWEIGHTM2_WIDTH ((uint32_t)0x00000003) +/// QPBSKNSDTHR field mask +#define MDM_QPBSKNSDTHR_MASK ((uint32_t)0x00070000) +/// QPBSKNSDTHR field LSB position +#define MDM_QPBSKNSDTHR_LSB 16 +/// QPBSKNSDTHR field width +#define MDM_QPBSKNSDTHR_WIDTH ((uint32_t)0x00000003) +/// QBPSKDETTHR field mask +#define MDM_QBPSKDETTHR_MASK ((uint32_t)0x0000F000) +/// QBPSKDETTHR field LSB position +#define MDM_QBPSKDETTHR_LSB 12 +/// QBPSKDETTHR field width +#define MDM_QBPSKDETTHR_WIDTH ((uint32_t)0x00000004) +/// FDDCSNRTHRESHOLD field mask +#define MDM_FDDCSNRTHRESHOLD_MASK ((uint32_t)0x00000FF0) +/// FDDCSNRTHRESHOLD field LSB position +#define MDM_FDDCSNRTHRESHOLD_LSB 4 +/// FDDCSNRTHRESHOLD field width +#define MDM_FDDCSNRTHRESHOLD_WIDTH ((uint32_t)0x00000008) +/// FDDCCOMPEN field bit +#define MDM_FDDCCOMPEN_BIT ((uint32_t)0x00000008) +/// FDDCCOMPEN field position +#define MDM_FDDCCOMPEN_POS 3 +/// EQUALCFGSATSB field mask +#define MDM_EQUALCFGSATSB_MASK ((uint32_t)0x00000007) +/// EQUALCFGSATSB field LSB position +#define MDM_EQUALCFGSATSB_LSB 0 +/// EQUALCFGSATSB field width +#define MDM_EQUALCFGSATSB_WIDTH ((uint32_t)0x00000003) + +/// FDDCWEIGHTP2 field reset value +#define MDM_FDDCWEIGHTP2_RST 0x2 +/// FDDCWEIGHTP1 field reset value +#define MDM_FDDCWEIGHTP1_RST 0x3 +/// FDDCWEIGHTM1 field reset value +#define MDM_FDDCWEIGHTM1_RST 0x3 +/// FDDCWEIGHTM2 field reset value +#define MDM_FDDCWEIGHTM2_RST 0x2 +/// QPBSKNSDTHR field reset value +#define MDM_QPBSKNSDTHR_RST 0x4 +/// QBPSKDETTHR field reset value +#define MDM_QBPSKDETTHR_RST 0xC +/// FDDCSNRTHRESHOLD field reset value +#define MDM_FDDCSNRTHRESHOLD_RST 0x18 +/// FDDCCOMPEN field reset value +#define MDM_FDDCCOMPEN_RST 0x1 +/// EQUALCFGSATSB field reset value +#define MDM_EQUALCFGSATSB_RST 0x3 + +/** + * @brief Constructs a value for the EQUALCTRL register given values for its fields + * and writes the value to the register. + * + * @param[in] fddcweightp2 - The value to use for the FDDCWEIGHTP2 field. + * @param[in] fddcweightp1 - The value to use for the FDDCWEIGHTP1 field. + * @param[in] fddcweightm1 - The value to use for the FDDCWEIGHTM1 field. + * @param[in] fddcweightm2 - The value to use for the FDDCWEIGHTM2 field. + * @param[in] qpbsknsdthr - The value to use for the QPBSKNSDTHR field. + * @param[in] qbpskdetthr - The value to use for the QBPSKDETTHR field. + * @param[in] fddcsnrthreshold - The value to use for the FDDCSNRTHRESHOLD field. + * @param[in] fddccompen - The value to use for the FDDCCOMPEN field. + * @param[in] equalcfgsatsb - The value to use for the EQUALCFGSATSB field. + */ +__INLINE void mdm_equalctrl_pack(uint8_t fddcweightp2, uint8_t fddcweightp1, uint8_t fddcweightm1, uint8_t fddcweightm2, uint8_t qpbsknsdthr, uint8_t qbpskdetthr, uint8_t fddcsnrthreshold, uint8_t fddccompen, uint8_t equalcfgsatsb) +{ + ASSERT_ERR((((uint32_t)fddcweightp2 << 29) & ~((uint32_t)0xE0000000)) == 0); + ASSERT_ERR((((uint32_t)fddcweightp1 << 26) & ~((uint32_t)0x1C000000)) == 0); + ASSERT_ERR((((uint32_t)fddcweightm1 << 23) & ~((uint32_t)0x03800000)) == 0); + ASSERT_ERR((((uint32_t)fddcweightm2 << 20) & ~((uint32_t)0x00700000)) == 0); + ASSERT_ERR((((uint32_t)qpbsknsdthr << 16) & ~((uint32_t)0x00070000)) == 0); + ASSERT_ERR((((uint32_t)qbpskdetthr << 12) & ~((uint32_t)0x0000F000)) == 0); + ASSERT_ERR((((uint32_t)fddcsnrthreshold << 4) & ~((uint32_t)0x00000FF0)) == 0); + ASSERT_ERR((((uint32_t)fddccompen << 3) & ~((uint32_t)0x00000008)) == 0); + ASSERT_ERR((((uint32_t)equalcfgsatsb << 0) & ~((uint32_t)0x00000007)) == 0); + REG_PL_WR(MDM_EQUALCTRL_ADDR, ((uint32_t)fddcweightp2 << 29) | ((uint32_t)fddcweightp1 << 26) | ((uint32_t)fddcweightm1 << 23) | ((uint32_t)fddcweightm2 << 20) | ((uint32_t)qpbsknsdthr << 16) | ((uint32_t)qbpskdetthr << 12) | ((uint32_t)fddcsnrthreshold << 4) | ((uint32_t)fddccompen << 3) | ((uint32_t)equalcfgsatsb << 0)); +} + +/** + * @brief Unpacks EQUALCTRL's fields from current value of the EQUALCTRL register. + * + * Reads the EQUALCTRL register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] fddcweightp2 - Will be populated with the current value of this field from the register. + * @param[out] fddcweightp1 - Will be populated with the current value of this field from the register. + * @param[out] fddcweightm1 - Will be populated with the current value of this field from the register. + * @param[out] fddcweightm2 - Will be populated with the current value of this field from the register. + * @param[out] qpbsknsdthr - Will be populated with the current value of this field from the register. + * @param[out] qbpskdetthr - Will be populated with the current value of this field from the register. + * @param[out] fddcsnrthreshold - Will be populated with the current value of this field from the register. + * @param[out] fddccompen - Will be populated with the current value of this field from the register. + * @param[out] equalcfgsatsb - Will be populated with the current value of this field from the register. + */ +__INLINE void mdm_equalctrl_unpack(uint8_t *fddcweightp2, uint8_t *fddcweightp1, uint8_t *fddcweightm1, uint8_t *fddcweightm2, uint8_t *qpbsknsdthr, uint8_t *qbpskdetthr, uint8_t *fddcsnrthreshold, uint8_t *fddccompen, uint8_t *equalcfgsatsb) +{ + uint32_t localVal = REG_PL_RD(MDM_EQUALCTRL_ADDR); + + *fddcweightp2 = (localVal & ((uint32_t)0xE0000000)) >> 29; + *fddcweightp1 = (localVal & ((uint32_t)0x1C000000)) >> 26; + *fddcweightm1 = (localVal & ((uint32_t)0x03800000)) >> 23; + *fddcweightm2 = (localVal & ((uint32_t)0x00700000)) >> 20; + *qpbsknsdthr = (localVal & ((uint32_t)0x00070000)) >> 16; + *qbpskdetthr = (localVal & ((uint32_t)0x0000F000)) >> 12; + *fddcsnrthreshold = (localVal & ((uint32_t)0x00000FF0)) >> 4; + *fddccompen = (localVal & ((uint32_t)0x00000008)) >> 3; + *equalcfgsatsb = (localVal & ((uint32_t)0x00000007)) >> 0; +} + +/** + * @brief Returns the current value of the FDDCWEIGHTP2 field in the EQUALCTRL register. + * + * The EQUALCTRL register will be read and the FDDCWEIGHTP2 field's value will be returned. + * + * @return The current value of the FDDCWEIGHTP2 field in the EQUALCTRL register. + */ +__INLINE uint8_t mdm_fddcweightp2_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_EQUALCTRL_ADDR); + return ((localVal & ((uint32_t)0xE0000000)) >> 29); +} + +/** + * @brief Sets the FDDCWEIGHTP2 field of the EQUALCTRL register. + * + * The EQUALCTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] fddcweightp2 - The value to set the field to. + */ +__INLINE void mdm_fddcweightp2_setf(uint8_t fddcweightp2) +{ + ASSERT_ERR((((uint32_t)fddcweightp2 << 29) & ~((uint32_t)0xE0000000)) == 0); + REG_PL_WR(MDM_EQUALCTRL_ADDR, (REG_PL_RD(MDM_EQUALCTRL_ADDR) & ~((uint32_t)0xE0000000)) | ((uint32_t)fddcweightp2 << 29)); +} + +/** + * @brief Returns the current value of the FDDCWEIGHTP1 field in the EQUALCTRL register. + * + * The EQUALCTRL register will be read and the FDDCWEIGHTP1 field's value will be returned. + * + * @return The current value of the FDDCWEIGHTP1 field in the EQUALCTRL register. + */ +__INLINE uint8_t mdm_fddcweightp1_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_EQUALCTRL_ADDR); + return ((localVal & ((uint32_t)0x1C000000)) >> 26); +} + +/** + * @brief Sets the FDDCWEIGHTP1 field of the EQUALCTRL register. + * + * The EQUALCTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] fddcweightp1 - The value to set the field to. + */ +__INLINE void mdm_fddcweightp1_setf(uint8_t fddcweightp1) +{ + ASSERT_ERR((((uint32_t)fddcweightp1 << 26) & ~((uint32_t)0x1C000000)) == 0); + REG_PL_WR(MDM_EQUALCTRL_ADDR, (REG_PL_RD(MDM_EQUALCTRL_ADDR) & ~((uint32_t)0x1C000000)) | ((uint32_t)fddcweightp1 << 26)); +} + +/** + * @brief Returns the current value of the FDDCWEIGHTM1 field in the EQUALCTRL register. + * + * The EQUALCTRL register will be read and the FDDCWEIGHTM1 field's value will be returned. + * + * @return The current value of the FDDCWEIGHTM1 field in the EQUALCTRL register. + */ +__INLINE uint8_t mdm_fddcweightm1_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_EQUALCTRL_ADDR); + return ((localVal & ((uint32_t)0x03800000)) >> 23); +} + +/** + * @brief Sets the FDDCWEIGHTM1 field of the EQUALCTRL register. + * + * The EQUALCTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] fddcweightm1 - The value to set the field to. + */ +__INLINE void mdm_fddcweightm1_setf(uint8_t fddcweightm1) +{ + ASSERT_ERR((((uint32_t)fddcweightm1 << 23) & ~((uint32_t)0x03800000)) == 0); + REG_PL_WR(MDM_EQUALCTRL_ADDR, (REG_PL_RD(MDM_EQUALCTRL_ADDR) & ~((uint32_t)0x03800000)) | ((uint32_t)fddcweightm1 << 23)); +} + +/** + * @brief Returns the current value of the FDDCWEIGHTM2 field in the EQUALCTRL register. + * + * The EQUALCTRL register will be read and the FDDCWEIGHTM2 field's value will be returned. + * + * @return The current value of the FDDCWEIGHTM2 field in the EQUALCTRL register. + */ +__INLINE uint8_t mdm_fddcweightm2_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_EQUALCTRL_ADDR); + return ((localVal & ((uint32_t)0x00700000)) >> 20); +} + +/** + * @brief Sets the FDDCWEIGHTM2 field of the EQUALCTRL register. + * + * The EQUALCTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] fddcweightm2 - The value to set the field to. + */ +__INLINE void mdm_fddcweightm2_setf(uint8_t fddcweightm2) +{ + ASSERT_ERR((((uint32_t)fddcweightm2 << 20) & ~((uint32_t)0x00700000)) == 0); + REG_PL_WR(MDM_EQUALCTRL_ADDR, (REG_PL_RD(MDM_EQUALCTRL_ADDR) & ~((uint32_t)0x00700000)) | ((uint32_t)fddcweightm2 << 20)); +} + +/** + * @brief Returns the current value of the QPBSKNSDTHR field in the EQUALCTRL register. + * + * The EQUALCTRL register will be read and the QPBSKNSDTHR field's value will be returned. + * + * @return The current value of the QPBSKNSDTHR field in the EQUALCTRL register. + */ +__INLINE uint8_t mdm_qpbsknsdthr_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_EQUALCTRL_ADDR); + return ((localVal & ((uint32_t)0x00070000)) >> 16); +} + +/** + * @brief Sets the QPBSKNSDTHR field of the EQUALCTRL register. + * + * The EQUALCTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] qpbsknsdthr - The value to set the field to. + */ +__INLINE void mdm_qpbsknsdthr_setf(uint8_t qpbsknsdthr) +{ + ASSERT_ERR((((uint32_t)qpbsknsdthr << 16) & ~((uint32_t)0x00070000)) == 0); + REG_PL_WR(MDM_EQUALCTRL_ADDR, (REG_PL_RD(MDM_EQUALCTRL_ADDR) & ~((uint32_t)0x00070000)) | ((uint32_t)qpbsknsdthr << 16)); +} + +/** + * @brief Returns the current value of the QBPSKDETTHR field in the EQUALCTRL register. + * + * The EQUALCTRL register will be read and the QBPSKDETTHR field's value will be returned. + * + * @return The current value of the QBPSKDETTHR field in the EQUALCTRL register. + */ +__INLINE uint8_t mdm_qbpskdetthr_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_EQUALCTRL_ADDR); + return ((localVal & ((uint32_t)0x0000F000)) >> 12); +} + +/** + * @brief Sets the QBPSKDETTHR field of the EQUALCTRL register. + * + * The EQUALCTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] qbpskdetthr - The value to set the field to. + */ +__INLINE void mdm_qbpskdetthr_setf(uint8_t qbpskdetthr) +{ + ASSERT_ERR((((uint32_t)qbpskdetthr << 12) & ~((uint32_t)0x0000F000)) == 0); + REG_PL_WR(MDM_EQUALCTRL_ADDR, (REG_PL_RD(MDM_EQUALCTRL_ADDR) & ~((uint32_t)0x0000F000)) | ((uint32_t)qbpskdetthr << 12)); +} + +/** + * @brief Returns the current value of the FDDCSNRTHRESHOLD field in the EQUALCTRL register. + * + * The EQUALCTRL register will be read and the FDDCSNRTHRESHOLD field's value will be returned. + * + * @return The current value of the FDDCSNRTHRESHOLD field in the EQUALCTRL register. + */ +__INLINE uint8_t mdm_fddcsnrthreshold_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_EQUALCTRL_ADDR); + return ((localVal & ((uint32_t)0x00000FF0)) >> 4); +} + +/** + * @brief Sets the FDDCSNRTHRESHOLD field of the EQUALCTRL register. + * + * The EQUALCTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] fddcsnrthreshold - The value to set the field to. + */ +__INLINE void mdm_fddcsnrthreshold_setf(uint8_t fddcsnrthreshold) +{ + ASSERT_ERR((((uint32_t)fddcsnrthreshold << 4) & ~((uint32_t)0x00000FF0)) == 0); + REG_PL_WR(MDM_EQUALCTRL_ADDR, (REG_PL_RD(MDM_EQUALCTRL_ADDR) & ~((uint32_t)0x00000FF0)) | ((uint32_t)fddcsnrthreshold << 4)); +} + +/** + * @brief Returns the current value of the FDDCCOMPEN field in the EQUALCTRL register. + * + * The EQUALCTRL register will be read and the FDDCCOMPEN field's value will be returned. + * + * @return The current value of the FDDCCOMPEN field in the EQUALCTRL register. + */ +__INLINE uint8_t mdm_fddccompen_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_EQUALCTRL_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +/** + * @brief Sets the FDDCCOMPEN field of the EQUALCTRL register. + * + * The EQUALCTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] fddccompen - The value to set the field to. + */ +__INLINE void mdm_fddccompen_setf(uint8_t fddccompen) +{ + ASSERT_ERR((((uint32_t)fddccompen << 3) & ~((uint32_t)0x00000008)) == 0); + REG_PL_WR(MDM_EQUALCTRL_ADDR, (REG_PL_RD(MDM_EQUALCTRL_ADDR) & ~((uint32_t)0x00000008)) | ((uint32_t)fddccompen << 3)); +} + +/** + * @brief Returns the current value of the EQUALCFGSATSB field in the EQUALCTRL register. + * + * The EQUALCTRL register will be read and the EQUALCFGSATSB field's value will be returned. + * + * @return The current value of the EQUALCFGSATSB field in the EQUALCTRL register. + */ +__INLINE uint8_t mdm_equalcfgsatsb_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_EQUALCTRL_ADDR); + return ((localVal & ((uint32_t)0x00000007)) >> 0); +} + +/** + * @brief Sets the EQUALCFGSATSB field of the EQUALCTRL register. + * + * The EQUALCTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] equalcfgsatsb - The value to set the field to. + */ +__INLINE void mdm_equalcfgsatsb_setf(uint8_t equalcfgsatsb) +{ + ASSERT_ERR((((uint32_t)equalcfgsatsb << 0) & ~((uint32_t)0x00000007)) == 0); + REG_PL_WR(MDM_EQUALCTRL_ADDR, (REG_PL_RD(MDM_EQUALCTRL_ADDR) & ~((uint32_t)0x00000007)) | ((uint32_t)equalcfgsatsb << 0)); +} + +/// @} + +/** + * @name SMOOTHCTRL register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  27:20        TDCYCROTVAL80   0x18
+ *     19             SMOOTHEN   1
+ *     18       CFGSMOOTHFORCE   1
+ *  17:16            CFGSMOOTH   0x0
+ *  15:08        TDCYCROTVAL40   0xC
+ *  07:00        TDCYCROTVAL20   0x6
+ * 
+ * + * @{ + */ + +/// Address of the SMOOTHCTRL register +#define MDM_SMOOTHCTRL_ADDR 0x01000818 +/// Offset of the SMOOTHCTRL register from the base address +#define MDM_SMOOTHCTRL_OFFSET 0x00000818 +/// Index of the SMOOTHCTRL register +#define MDM_SMOOTHCTRL_INDEX 0x00000206 +/// Reset value of the SMOOTHCTRL register +#define MDM_SMOOTHCTRL_RESET 0x018C0C06 + +/** + * @brief Returns the current value of the SMOOTHCTRL register. + * The SMOOTHCTRL register will be read and its value returned. + * @return The current value of the SMOOTHCTRL register. + */ +__INLINE uint32_t mdm_smoothctrl_get(void) +{ + return REG_PL_RD(MDM_SMOOTHCTRL_ADDR); +} + +/** + * @brief Sets the SMOOTHCTRL register to a value. + * The SMOOTHCTRL register will be written. + * @param value - The value to write. + */ +__INLINE void mdm_smoothctrl_set(uint32_t value) +{ + REG_PL_WR(MDM_SMOOTHCTRL_ADDR, value); +} + +// field definitions +/// TDCYCROTVAL80 field mask +#define MDM_TDCYCROTVAL80_MASK ((uint32_t)0x0FF00000) +/// TDCYCROTVAL80 field LSB position +#define MDM_TDCYCROTVAL80_LSB 20 +/// TDCYCROTVAL80 field width +#define MDM_TDCYCROTVAL80_WIDTH ((uint32_t)0x00000008) +/// SMOOTHEN field bit +#define MDM_SMOOTHEN_BIT ((uint32_t)0x00080000) +/// SMOOTHEN field position +#define MDM_SMOOTHEN_POS 19 +/// CFGSMOOTHFORCE field bit +#define MDM_CFGSMOOTHFORCE_BIT ((uint32_t)0x00040000) +/// CFGSMOOTHFORCE field position +#define MDM_CFGSMOOTHFORCE_POS 18 +/// CFGSMOOTH field mask +#define MDM_CFGSMOOTH_MASK ((uint32_t)0x00030000) +/// CFGSMOOTH field LSB position +#define MDM_CFGSMOOTH_LSB 16 +/// CFGSMOOTH field width +#define MDM_CFGSMOOTH_WIDTH ((uint32_t)0x00000002) +/// TDCYCROTVAL40 field mask +#define MDM_TDCYCROTVAL40_MASK ((uint32_t)0x0000FF00) +/// TDCYCROTVAL40 field LSB position +#define MDM_TDCYCROTVAL40_LSB 8 +/// TDCYCROTVAL40 field width +#define MDM_TDCYCROTVAL40_WIDTH ((uint32_t)0x00000008) +/// TDCYCROTVAL20 field mask +#define MDM_TDCYCROTVAL20_MASK ((uint32_t)0x000000FF) +/// TDCYCROTVAL20 field LSB position +#define MDM_TDCYCROTVAL20_LSB 0 +/// TDCYCROTVAL20 field width +#define MDM_TDCYCROTVAL20_WIDTH ((uint32_t)0x00000008) + +/// TDCYCROTVAL80 field reset value +#define MDM_TDCYCROTVAL80_RST 0x18 +/// SMOOTHEN field reset value +#define MDM_SMOOTHEN_RST 0x1 +/// CFGSMOOTHFORCE field reset value +#define MDM_CFGSMOOTHFORCE_RST 0x1 +/// CFGSMOOTH field reset value +#define MDM_CFGSMOOTH_RST 0x0 +/// TDCYCROTVAL40 field reset value +#define MDM_TDCYCROTVAL40_RST 0xC +/// TDCYCROTVAL20 field reset value +#define MDM_TDCYCROTVAL20_RST 0x6 + +/** + * @brief Constructs a value for the SMOOTHCTRL register given values for its fields + * and writes the value to the register. + * + * @param[in] tdcycrotval80 - The value to use for the TDCYCROTVAL80 field. + * @param[in] smoothen - The value to use for the SMOOTHEN field. + * @param[in] cfgsmoothforce - The value to use for the CFGSMOOTHFORCE field. + * @param[in] cfgsmooth - The value to use for the CFGSMOOTH field. + * @param[in] tdcycrotval40 - The value to use for the TDCYCROTVAL40 field. + * @param[in] tdcycrotval20 - The value to use for the TDCYCROTVAL20 field. + */ +__INLINE void mdm_smoothctrl_pack(uint8_t tdcycrotval80, uint8_t smoothen, uint8_t cfgsmoothforce, uint8_t cfgsmooth, uint8_t tdcycrotval40, uint8_t tdcycrotval20) +{ + ASSERT_ERR((((uint32_t)tdcycrotval80 << 20) & ~((uint32_t)0x0FF00000)) == 0); + ASSERT_ERR((((uint32_t)smoothen << 19) & ~((uint32_t)0x00080000)) == 0); + ASSERT_ERR((((uint32_t)cfgsmoothforce << 18) & ~((uint32_t)0x00040000)) == 0); + ASSERT_ERR((((uint32_t)cfgsmooth << 16) & ~((uint32_t)0x00030000)) == 0); + ASSERT_ERR((((uint32_t)tdcycrotval40 << 8) & ~((uint32_t)0x0000FF00)) == 0); + ASSERT_ERR((((uint32_t)tdcycrotval20 << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(MDM_SMOOTHCTRL_ADDR, ((uint32_t)tdcycrotval80 << 20) | ((uint32_t)smoothen << 19) | ((uint32_t)cfgsmoothforce << 18) | ((uint32_t)cfgsmooth << 16) | ((uint32_t)tdcycrotval40 << 8) | ((uint32_t)tdcycrotval20 << 0)); +} + +/** + * @brief Unpacks SMOOTHCTRL's fields from current value of the SMOOTHCTRL register. + * + * Reads the SMOOTHCTRL register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] tdcycrotval80 - Will be populated with the current value of this field from the register. + * @param[out] smoothen - Will be populated with the current value of this field from the register. + * @param[out] cfgsmoothforce - Will be populated with the current value of this field from the register. + * @param[out] cfgsmooth - Will be populated with the current value of this field from the register. + * @param[out] tdcycrotval40 - Will be populated with the current value of this field from the register. + * @param[out] tdcycrotval20 - Will be populated with the current value of this field from the register. + */ +__INLINE void mdm_smoothctrl_unpack(uint8_t *tdcycrotval80, uint8_t *smoothen, uint8_t *cfgsmoothforce, uint8_t *cfgsmooth, uint8_t *tdcycrotval40, uint8_t *tdcycrotval20) +{ + uint32_t localVal = REG_PL_RD(MDM_SMOOTHCTRL_ADDR); + + *tdcycrotval80 = (localVal & ((uint32_t)0x0FF00000)) >> 20; + *smoothen = (localVal & ((uint32_t)0x00080000)) >> 19; + *cfgsmoothforce = (localVal & ((uint32_t)0x00040000)) >> 18; + *cfgsmooth = (localVal & ((uint32_t)0x00030000)) >> 16; + *tdcycrotval40 = (localVal & ((uint32_t)0x0000FF00)) >> 8; + *tdcycrotval20 = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +/** + * @brief Returns the current value of the TDCYCROTVAL80 field in the SMOOTHCTRL register. + * + * The SMOOTHCTRL register will be read and the TDCYCROTVAL80 field's value will be returned. + * + * @return The current value of the TDCYCROTVAL80 field in the SMOOTHCTRL register. + */ +__INLINE uint8_t mdm_tdcycrotval80_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_SMOOTHCTRL_ADDR); + return ((localVal & ((uint32_t)0x0FF00000)) >> 20); +} + +/** + * @brief Sets the TDCYCROTVAL80 field of the SMOOTHCTRL register. + * + * The SMOOTHCTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] tdcycrotval80 - The value to set the field to. + */ +__INLINE void mdm_tdcycrotval80_setf(uint8_t tdcycrotval80) +{ + ASSERT_ERR((((uint32_t)tdcycrotval80 << 20) & ~((uint32_t)0x0FF00000)) == 0); + REG_PL_WR(MDM_SMOOTHCTRL_ADDR, (REG_PL_RD(MDM_SMOOTHCTRL_ADDR) & ~((uint32_t)0x0FF00000)) | ((uint32_t)tdcycrotval80 << 20)); +} + +/** + * @brief Returns the current value of the SMOOTHEN field in the SMOOTHCTRL register. + * + * The SMOOTHCTRL register will be read and the SMOOTHEN field's value will be returned. + * + * @return The current value of the SMOOTHEN field in the SMOOTHCTRL register. + */ +__INLINE uint8_t mdm_smoothen_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_SMOOTHCTRL_ADDR); + return ((localVal & ((uint32_t)0x00080000)) >> 19); +} + +/** + * @brief Sets the SMOOTHEN field of the SMOOTHCTRL register. + * + * The SMOOTHCTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] smoothen - The value to set the field to. + */ +__INLINE void mdm_smoothen_setf(uint8_t smoothen) +{ + ASSERT_ERR((((uint32_t)smoothen << 19) & ~((uint32_t)0x00080000)) == 0); + REG_PL_WR(MDM_SMOOTHCTRL_ADDR, (REG_PL_RD(MDM_SMOOTHCTRL_ADDR) & ~((uint32_t)0x00080000)) | ((uint32_t)smoothen << 19)); +} + +/** + * @brief Returns the current value of the CFGSMOOTHFORCE field in the SMOOTHCTRL register. + * + * The SMOOTHCTRL register will be read and the CFGSMOOTHFORCE field's value will be returned. + * + * @return The current value of the CFGSMOOTHFORCE field in the SMOOTHCTRL register. + */ +__INLINE uint8_t mdm_cfgsmoothforce_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_SMOOTHCTRL_ADDR); + return ((localVal & ((uint32_t)0x00040000)) >> 18); +} + +/** + * @brief Sets the CFGSMOOTHFORCE field of the SMOOTHCTRL register. + * + * The SMOOTHCTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] cfgsmoothforce - The value to set the field to. + */ +__INLINE void mdm_cfgsmoothforce_setf(uint8_t cfgsmoothforce) +{ + ASSERT_ERR((((uint32_t)cfgsmoothforce << 18) & ~((uint32_t)0x00040000)) == 0); + REG_PL_WR(MDM_SMOOTHCTRL_ADDR, (REG_PL_RD(MDM_SMOOTHCTRL_ADDR) & ~((uint32_t)0x00040000)) | ((uint32_t)cfgsmoothforce << 18)); +} + +/** + * @brief Returns the current value of the CFGSMOOTH field in the SMOOTHCTRL register. + * + * The SMOOTHCTRL register will be read and the CFGSMOOTH field's value will be returned. + * + * @return The current value of the CFGSMOOTH field in the SMOOTHCTRL register. + */ +__INLINE uint8_t mdm_cfgsmooth_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_SMOOTHCTRL_ADDR); + return ((localVal & ((uint32_t)0x00030000)) >> 16); +} + +/** + * @brief Sets the CFGSMOOTH field of the SMOOTHCTRL register. + * + * The SMOOTHCTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] cfgsmooth - The value to set the field to. + */ +__INLINE void mdm_cfgsmooth_setf(uint8_t cfgsmooth) +{ + ASSERT_ERR((((uint32_t)cfgsmooth << 16) & ~((uint32_t)0x00030000)) == 0); + REG_PL_WR(MDM_SMOOTHCTRL_ADDR, (REG_PL_RD(MDM_SMOOTHCTRL_ADDR) & ~((uint32_t)0x00030000)) | ((uint32_t)cfgsmooth << 16)); +} + +/** + * @brief Returns the current value of the TDCYCROTVAL40 field in the SMOOTHCTRL register. + * + * The SMOOTHCTRL register will be read and the TDCYCROTVAL40 field's value will be returned. + * + * @return The current value of the TDCYCROTVAL40 field in the SMOOTHCTRL register. + */ +__INLINE uint8_t mdm_tdcycrotval40_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_SMOOTHCTRL_ADDR); + return ((localVal & ((uint32_t)0x0000FF00)) >> 8); +} + +/** + * @brief Sets the TDCYCROTVAL40 field of the SMOOTHCTRL register. + * + * The SMOOTHCTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] tdcycrotval40 - The value to set the field to. + */ +__INLINE void mdm_tdcycrotval40_setf(uint8_t tdcycrotval40) +{ + ASSERT_ERR((((uint32_t)tdcycrotval40 << 8) & ~((uint32_t)0x0000FF00)) == 0); + REG_PL_WR(MDM_SMOOTHCTRL_ADDR, (REG_PL_RD(MDM_SMOOTHCTRL_ADDR) & ~((uint32_t)0x0000FF00)) | ((uint32_t)tdcycrotval40 << 8)); +} + +/** + * @brief Returns the current value of the TDCYCROTVAL20 field in the SMOOTHCTRL register. + * + * The SMOOTHCTRL register will be read and the TDCYCROTVAL20 field's value will be returned. + * + * @return The current value of the TDCYCROTVAL20 field in the SMOOTHCTRL register. + */ +__INLINE uint8_t mdm_tdcycrotval20_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_SMOOTHCTRL_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +/** + * @brief Sets the TDCYCROTVAL20 field of the SMOOTHCTRL register. + * + * The SMOOTHCTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] tdcycrotval20 - The value to set the field to. + */ +__INLINE void mdm_tdcycrotval20_setf(uint8_t tdcycrotval20) +{ + ASSERT_ERR((((uint32_t)tdcycrotval20 << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(MDM_SMOOTHCTRL_ADDR, (REG_PL_RD(MDM_SMOOTHCTRL_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)tdcycrotval20 << 0)); +} + +/// @} + +/** + * @name DCESTIMCTRL register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31              DCESTEN   1
+ *  30:24            STARTHTDC   0x0
+ *  22:16              STARTDC   0x0
+ *  13:08        DELAYNORMALGI   0x11
+ *  06:00            WAITHTSTF   0xF
+ * 
+ * + * @{ + */ + +/// Address of the DCESTIMCTRL register +#define MDM_DCESTIMCTRL_ADDR 0x0100081C +/// Offset of the DCESTIMCTRL register from the base address +#define MDM_DCESTIMCTRL_OFFSET 0x0000081C +/// Index of the DCESTIMCTRL register +#define MDM_DCESTIMCTRL_INDEX 0x00000207 +/// Reset value of the DCESTIMCTRL register +#define MDM_DCESTIMCTRL_RESET 0x8000110F + +/** + * @brief Returns the current value of the DCESTIMCTRL register. + * The DCESTIMCTRL register will be read and its value returned. + * @return The current value of the DCESTIMCTRL register. + */ +__INLINE uint32_t mdm_dcestimctrl_get(void) +{ + return REG_PL_RD(MDM_DCESTIMCTRL_ADDR); +} + +/** + * @brief Sets the DCESTIMCTRL register to a value. + * The DCESTIMCTRL register will be written. + * @param value - The value to write. + */ +__INLINE void mdm_dcestimctrl_set(uint32_t value) +{ + REG_PL_WR(MDM_DCESTIMCTRL_ADDR, value); +} + +// field definitions +/// DCESTEN field bit +#define MDM_DCESTEN_BIT ((uint32_t)0x80000000) +/// DCESTEN field position +#define MDM_DCESTEN_POS 31 +/// STARTHTDC field mask +#define MDM_STARTHTDC_MASK ((uint32_t)0x7F000000) +/// STARTHTDC field LSB position +#define MDM_STARTHTDC_LSB 24 +/// STARTHTDC field width +#define MDM_STARTHTDC_WIDTH ((uint32_t)0x00000007) +/// STARTDC field mask +#define MDM_STARTDC_MASK ((uint32_t)0x007F0000) +/// STARTDC field LSB position +#define MDM_STARTDC_LSB 16 +/// STARTDC field width +#define MDM_STARTDC_WIDTH ((uint32_t)0x00000007) +/// DELAYNORMALGI field mask +#define MDM_DELAYNORMALGI_MASK ((uint32_t)0x00003F00) +/// DELAYNORMALGI field LSB position +#define MDM_DELAYNORMALGI_LSB 8 +/// DELAYNORMALGI field width +#define MDM_DELAYNORMALGI_WIDTH ((uint32_t)0x00000006) +/// WAITHTSTF field mask +#define MDM_WAITHTSTF_MASK ((uint32_t)0x0000007F) +/// WAITHTSTF field LSB position +#define MDM_WAITHTSTF_LSB 0 +/// WAITHTSTF field width +#define MDM_WAITHTSTF_WIDTH ((uint32_t)0x00000007) + +/// DCESTEN field reset value +#define MDM_DCESTEN_RST 0x1 +/// STARTHTDC field reset value +#define MDM_STARTHTDC_RST 0x0 +/// STARTDC field reset value +#define MDM_STARTDC_RST 0x0 +/// DELAYNORMALGI field reset value +#define MDM_DELAYNORMALGI_RST 0x11 +/// WAITHTSTF field reset value +#define MDM_WAITHTSTF_RST 0xF + +/** + * @brief Constructs a value for the DCESTIMCTRL register given values for its fields + * and writes the value to the register. + * + * @param[in] dcesten - The value to use for the DCESTEN field. + * @param[in] starthtdc - The value to use for the STARTHTDC field. + * @param[in] startdc - The value to use for the STARTDC field. + * @param[in] delaynormalgi - The value to use for the DELAYNORMALGI field. + * @param[in] waithtstf - The value to use for the WAITHTSTF field. + */ +__INLINE void mdm_dcestimctrl_pack(uint8_t dcesten, uint8_t starthtdc, uint8_t startdc, uint8_t delaynormalgi, uint8_t waithtstf) +{ + ASSERT_ERR((((uint32_t)dcesten << 31) & ~((uint32_t)0x80000000)) == 0); + ASSERT_ERR((((uint32_t)starthtdc << 24) & ~((uint32_t)0x7F000000)) == 0); + ASSERT_ERR((((uint32_t)startdc << 16) & ~((uint32_t)0x007F0000)) == 0); + ASSERT_ERR((((uint32_t)delaynormalgi << 8) & ~((uint32_t)0x00003F00)) == 0); + ASSERT_ERR((((uint32_t)waithtstf << 0) & ~((uint32_t)0x0000007F)) == 0); + REG_PL_WR(MDM_DCESTIMCTRL_ADDR, ((uint32_t)dcesten << 31) | ((uint32_t)starthtdc << 24) | ((uint32_t)startdc << 16) | ((uint32_t)delaynormalgi << 8) | ((uint32_t)waithtstf << 0)); +} + +/** + * @brief Unpacks DCESTIMCTRL's fields from current value of the DCESTIMCTRL register. + * + * Reads the DCESTIMCTRL register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] dcesten - Will be populated with the current value of this field from the register. + * @param[out] starthtdc - Will be populated with the current value of this field from the register. + * @param[out] startdc - Will be populated with the current value of this field from the register. + * @param[out] delaynormalgi - Will be populated with the current value of this field from the register. + * @param[out] waithtstf - Will be populated with the current value of this field from the register. + */ +__INLINE void mdm_dcestimctrl_unpack(uint8_t *dcesten, uint8_t *starthtdc, uint8_t *startdc, uint8_t *delaynormalgi, uint8_t *waithtstf) +{ + uint32_t localVal = REG_PL_RD(MDM_DCESTIMCTRL_ADDR); + + *dcesten = (localVal & ((uint32_t)0x80000000)) >> 31; + *starthtdc = (localVal & ((uint32_t)0x7F000000)) >> 24; + *startdc = (localVal & ((uint32_t)0x007F0000)) >> 16; + *delaynormalgi = (localVal & ((uint32_t)0x00003F00)) >> 8; + *waithtstf = (localVal & ((uint32_t)0x0000007F)) >> 0; +} + +/** + * @brief Returns the current value of the DCESTEN field in the DCESTIMCTRL register. + * + * The DCESTIMCTRL register will be read and the DCESTEN field's value will be returned. + * + * @return The current value of the DCESTEN field in the DCESTIMCTRL register. + */ +__INLINE uint8_t mdm_dcesten_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_DCESTIMCTRL_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +/** + * @brief Sets the DCESTEN field of the DCESTIMCTRL register. + * + * The DCESTIMCTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] dcesten - The value to set the field to. + */ +__INLINE void mdm_dcesten_setf(uint8_t dcesten) +{ + ASSERT_ERR((((uint32_t)dcesten << 31) & ~((uint32_t)0x80000000)) == 0); + REG_PL_WR(MDM_DCESTIMCTRL_ADDR, (REG_PL_RD(MDM_DCESTIMCTRL_ADDR) & ~((uint32_t)0x80000000)) | ((uint32_t)dcesten << 31)); +} + +/** + * @brief Returns the current value of the STARTHTDC field in the DCESTIMCTRL register. + * + * The DCESTIMCTRL register will be read and the STARTHTDC field's value will be returned. + * + * @return The current value of the STARTHTDC field in the DCESTIMCTRL register. + */ +__INLINE uint8_t mdm_starthtdc_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_DCESTIMCTRL_ADDR); + return ((localVal & ((uint32_t)0x7F000000)) >> 24); +} + +/** + * @brief Sets the STARTHTDC field of the DCESTIMCTRL register. + * + * The DCESTIMCTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] starthtdc - The value to set the field to. + */ +__INLINE void mdm_starthtdc_setf(uint8_t starthtdc) +{ + ASSERT_ERR((((uint32_t)starthtdc << 24) & ~((uint32_t)0x7F000000)) == 0); + REG_PL_WR(MDM_DCESTIMCTRL_ADDR, (REG_PL_RD(MDM_DCESTIMCTRL_ADDR) & ~((uint32_t)0x7F000000)) | ((uint32_t)starthtdc << 24)); +} + +/** + * @brief Returns the current value of the STARTDC field in the DCESTIMCTRL register. + * + * The DCESTIMCTRL register will be read and the STARTDC field's value will be returned. + * + * @return The current value of the STARTDC field in the DCESTIMCTRL register. + */ +__INLINE uint8_t mdm_startdc_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_DCESTIMCTRL_ADDR); + return ((localVal & ((uint32_t)0x007F0000)) >> 16); +} + +/** + * @brief Sets the STARTDC field of the DCESTIMCTRL register. + * + * The DCESTIMCTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] startdc - The value to set the field to. + */ +__INLINE void mdm_startdc_setf(uint8_t startdc) +{ + ASSERT_ERR((((uint32_t)startdc << 16) & ~((uint32_t)0x007F0000)) == 0); + REG_PL_WR(MDM_DCESTIMCTRL_ADDR, (REG_PL_RD(MDM_DCESTIMCTRL_ADDR) & ~((uint32_t)0x007F0000)) | ((uint32_t)startdc << 16)); +} + +/** + * @brief Returns the current value of the DELAYNORMALGI field in the DCESTIMCTRL register. + * + * The DCESTIMCTRL register will be read and the DELAYNORMALGI field's value will be returned. + * + * @return The current value of the DELAYNORMALGI field in the DCESTIMCTRL register. + */ +__INLINE uint8_t mdm_delaynormalgi_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_DCESTIMCTRL_ADDR); + return ((localVal & ((uint32_t)0x00003F00)) >> 8); +} + +/** + * @brief Sets the DELAYNORMALGI field of the DCESTIMCTRL register. + * + * The DCESTIMCTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] delaynormalgi - The value to set the field to. + */ +__INLINE void mdm_delaynormalgi_setf(uint8_t delaynormalgi) +{ + ASSERT_ERR((((uint32_t)delaynormalgi << 8) & ~((uint32_t)0x00003F00)) == 0); + REG_PL_WR(MDM_DCESTIMCTRL_ADDR, (REG_PL_RD(MDM_DCESTIMCTRL_ADDR) & ~((uint32_t)0x00003F00)) | ((uint32_t)delaynormalgi << 8)); +} + +/** + * @brief Returns the current value of the WAITHTSTF field in the DCESTIMCTRL register. + * + * The DCESTIMCTRL register will be read and the WAITHTSTF field's value will be returned. + * + * @return The current value of the WAITHTSTF field in the DCESTIMCTRL register. + */ +__INLINE uint8_t mdm_waithtstf_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_DCESTIMCTRL_ADDR); + return ((localVal & ((uint32_t)0x0000007F)) >> 0); +} + +/** + * @brief Sets the WAITHTSTF field of the DCESTIMCTRL register. + * + * The DCESTIMCTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] waithtstf - The value to set the field to. + */ +__INLINE void mdm_waithtstf_setf(uint8_t waithtstf) +{ + ASSERT_ERR((((uint32_t)waithtstf << 0) & ~((uint32_t)0x0000007F)) == 0); + REG_PL_WR(MDM_DCESTIMCTRL_ADDR, (REG_PL_RD(MDM_DCESTIMCTRL_ADDR) & ~((uint32_t)0x0000007F)) | ((uint32_t)waithtstf << 0)); +} + +/// @} + +/** + * @name FECTRL0 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  22:16      TX80DIGGAINLIN0   0x20
+ *  14:08      TX40DIGGAINLIN0   0x20
+ *  06:00      TX20DIGGAINLIN0   0x20
+ * 
+ * + * @{ + */ + +/// Address of the FECTRL0 register +#define MDM_FECTRL0_ADDR 0x01000820 +/// Offset of the FECTRL0 register from the base address +#define MDM_FECTRL0_OFFSET 0x00000820 +/// Index of the FECTRL0 register +#define MDM_FECTRL0_INDEX 0x00000208 +/// Reset value of the FECTRL0 register +#define MDM_FECTRL0_RESET 0x00202020 + +/** + * @brief Returns the current value of the FECTRL0 register. + * The FECTRL0 register will be read and its value returned. + * @return The current value of the FECTRL0 register. + */ +__INLINE uint32_t mdm_fectrl0_get(void) +{ + return REG_PL_RD(MDM_FECTRL0_ADDR); +} + +/** + * @brief Sets the FECTRL0 register to a value. + * The FECTRL0 register will be written. + * @param value - The value to write. + */ +__INLINE void mdm_fectrl0_set(uint32_t value) +{ + REG_PL_WR(MDM_FECTRL0_ADDR, value); +} + +// field definitions +/// TX80DIGGAINLIN0 field mask +#define MDM_TX80DIGGAINLIN0_MASK ((uint32_t)0x007F0000) +/// TX80DIGGAINLIN0 field LSB position +#define MDM_TX80DIGGAINLIN0_LSB 16 +/// TX80DIGGAINLIN0 field width +#define MDM_TX80DIGGAINLIN0_WIDTH ((uint32_t)0x00000007) +/// TX40DIGGAINLIN0 field mask +#define MDM_TX40DIGGAINLIN0_MASK ((uint32_t)0x00007F00) +/// TX40DIGGAINLIN0 field LSB position +#define MDM_TX40DIGGAINLIN0_LSB 8 +/// TX40DIGGAINLIN0 field width +#define MDM_TX40DIGGAINLIN0_WIDTH ((uint32_t)0x00000007) +/// TX20DIGGAINLIN0 field mask +#define MDM_TX20DIGGAINLIN0_MASK ((uint32_t)0x0000007F) +/// TX20DIGGAINLIN0 field LSB position +#define MDM_TX20DIGGAINLIN0_LSB 0 +/// TX20DIGGAINLIN0 field width +#define MDM_TX20DIGGAINLIN0_WIDTH ((uint32_t)0x00000007) + +/// TX80DIGGAINLIN0 field reset value +#define MDM_TX80DIGGAINLIN0_RST 0x20 +/// TX40DIGGAINLIN0 field reset value +#define MDM_TX40DIGGAINLIN0_RST 0x20 +/// TX20DIGGAINLIN0 field reset value +#define MDM_TX20DIGGAINLIN0_RST 0x20 + +/** + * @brief Constructs a value for the FECTRL0 register given values for its fields + * and writes the value to the register. + * + * @param[in] tx80diggainlin0 - The value to use for the TX80DIGGAINLIN0 field. + * @param[in] tx40diggainlin0 - The value to use for the TX40DIGGAINLIN0 field. + * @param[in] tx20diggainlin0 - The value to use for the TX20DIGGAINLIN0 field. + */ +__INLINE void mdm_fectrl0_pack(uint8_t tx80diggainlin0, uint8_t tx40diggainlin0, uint8_t tx20diggainlin0) +{ + ASSERT_ERR((((uint32_t)tx80diggainlin0 << 16) & ~((uint32_t)0x007F0000)) == 0); + ASSERT_ERR((((uint32_t)tx40diggainlin0 << 8) & ~((uint32_t)0x00007F00)) == 0); + ASSERT_ERR((((uint32_t)tx20diggainlin0 << 0) & ~((uint32_t)0x0000007F)) == 0); + REG_PL_WR(MDM_FECTRL0_ADDR, ((uint32_t)tx80diggainlin0 << 16) | ((uint32_t)tx40diggainlin0 << 8) | ((uint32_t)tx20diggainlin0 << 0)); +} + +/** + * @brief Unpacks FECTRL0's fields from current value of the FECTRL0 register. + * + * Reads the FECTRL0 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] tx80diggainlin0 - Will be populated with the current value of this field from the register. + * @param[out] tx40diggainlin0 - Will be populated with the current value of this field from the register. + * @param[out] tx20diggainlin0 - Will be populated with the current value of this field from the register. + */ +__INLINE void mdm_fectrl0_unpack(uint8_t *tx80diggainlin0, uint8_t *tx40diggainlin0, uint8_t *tx20diggainlin0) +{ + uint32_t localVal = REG_PL_RD(MDM_FECTRL0_ADDR); + + *tx80diggainlin0 = (localVal & ((uint32_t)0x007F0000)) >> 16; + *tx40diggainlin0 = (localVal & ((uint32_t)0x00007F00)) >> 8; + *tx20diggainlin0 = (localVal & ((uint32_t)0x0000007F)) >> 0; +} + +/** + * @brief Returns the current value of the TX80DIGGAINLIN0 field in the FECTRL0 register. + * + * The FECTRL0 register will be read and the TX80DIGGAINLIN0 field's value will be returned. + * + * @return The current value of the TX80DIGGAINLIN0 field in the FECTRL0 register. + */ +__INLINE uint8_t mdm_tx80diggainlin0_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_FECTRL0_ADDR); + return ((localVal & ((uint32_t)0x007F0000)) >> 16); +} + +/** + * @brief Sets the TX80DIGGAINLIN0 field of the FECTRL0 register. + * + * The FECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] tx80diggainlin0 - The value to set the field to. + */ +__INLINE void mdm_tx80diggainlin0_setf(uint8_t tx80diggainlin0) +{ + ASSERT_ERR((((uint32_t)tx80diggainlin0 << 16) & ~((uint32_t)0x007F0000)) == 0); + REG_PL_WR(MDM_FECTRL0_ADDR, (REG_PL_RD(MDM_FECTRL0_ADDR) & ~((uint32_t)0x007F0000)) | ((uint32_t)tx80diggainlin0 << 16)); +} + +/** + * @brief Returns the current value of the TX40DIGGAINLIN0 field in the FECTRL0 register. + * + * The FECTRL0 register will be read and the TX40DIGGAINLIN0 field's value will be returned. + * + * @return The current value of the TX40DIGGAINLIN0 field in the FECTRL0 register. + */ +__INLINE uint8_t mdm_tx40diggainlin0_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_FECTRL0_ADDR); + return ((localVal & ((uint32_t)0x00007F00)) >> 8); +} + +/** + * @brief Sets the TX40DIGGAINLIN0 field of the FECTRL0 register. + * + * The FECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] tx40diggainlin0 - The value to set the field to. + */ +__INLINE void mdm_tx40diggainlin0_setf(uint8_t tx40diggainlin0) +{ + ASSERT_ERR((((uint32_t)tx40diggainlin0 << 8) & ~((uint32_t)0x00007F00)) == 0); + REG_PL_WR(MDM_FECTRL0_ADDR, (REG_PL_RD(MDM_FECTRL0_ADDR) & ~((uint32_t)0x00007F00)) | ((uint32_t)tx40diggainlin0 << 8)); +} + +/** + * @brief Returns the current value of the TX20DIGGAINLIN0 field in the FECTRL0 register. + * + * The FECTRL0 register will be read and the TX20DIGGAINLIN0 field's value will be returned. + * + * @return The current value of the TX20DIGGAINLIN0 field in the FECTRL0 register. + */ +__INLINE uint8_t mdm_tx20diggainlin0_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_FECTRL0_ADDR); + return ((localVal & ((uint32_t)0x0000007F)) >> 0); +} + +/** + * @brief Sets the TX20DIGGAINLIN0 field of the FECTRL0 register. + * + * The FECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] tx20diggainlin0 - The value to set the field to. + */ +__INLINE void mdm_tx20diggainlin0_setf(uint8_t tx20diggainlin0) +{ + ASSERT_ERR((((uint32_t)tx20diggainlin0 << 0) & ~((uint32_t)0x0000007F)) == 0); + REG_PL_WR(MDM_FECTRL0_ADDR, (REG_PL_RD(MDM_FECTRL0_ADDR) & ~((uint32_t)0x0000007F)) | ((uint32_t)tx20diggainlin0 << 0)); +} + +/// @} + +/** + * @name SMOOTHSNRTHR register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:08     SMOOTHSNRTHRHIGH   0x1B
+ *  07:00      SMOOTHSNRTHRMID   0xF
+ * 
+ * + * @{ + */ + +/// Address of the SMOOTHSNRTHR register +#define MDM_SMOOTHSNRTHR_ADDR 0x01000830 +/// Offset of the SMOOTHSNRTHR register from the base address +#define MDM_SMOOTHSNRTHR_OFFSET 0x00000830 +/// Index of the SMOOTHSNRTHR register +#define MDM_SMOOTHSNRTHR_INDEX 0x0000020C +/// Reset value of the SMOOTHSNRTHR register +#define MDM_SMOOTHSNRTHR_RESET 0x00001B0F + +/** + * @brief Returns the current value of the SMOOTHSNRTHR register. + * The SMOOTHSNRTHR register will be read and its value returned. + * @return The current value of the SMOOTHSNRTHR register. + */ +__INLINE uint32_t mdm_smoothsnrthr_get(void) +{ + return REG_PL_RD(MDM_SMOOTHSNRTHR_ADDR); +} + +/** + * @brief Sets the SMOOTHSNRTHR register to a value. + * The SMOOTHSNRTHR register will be written. + * @param value - The value to write. + */ +__INLINE void mdm_smoothsnrthr_set(uint32_t value) +{ + REG_PL_WR(MDM_SMOOTHSNRTHR_ADDR, value); +} + +// field definitions +/// SMOOTHSNRTHRHIGH field mask +#define MDM_SMOOTHSNRTHRHIGH_MASK ((uint32_t)0x0000FF00) +/// SMOOTHSNRTHRHIGH field LSB position +#define MDM_SMOOTHSNRTHRHIGH_LSB 8 +/// SMOOTHSNRTHRHIGH field width +#define MDM_SMOOTHSNRTHRHIGH_WIDTH ((uint32_t)0x00000008) +/// SMOOTHSNRTHRMID field mask +#define MDM_SMOOTHSNRTHRMID_MASK ((uint32_t)0x000000FF) +/// SMOOTHSNRTHRMID field LSB position +#define MDM_SMOOTHSNRTHRMID_LSB 0 +/// SMOOTHSNRTHRMID field width +#define MDM_SMOOTHSNRTHRMID_WIDTH ((uint32_t)0x00000008) + +/// SMOOTHSNRTHRHIGH field reset value +#define MDM_SMOOTHSNRTHRHIGH_RST 0x1B +/// SMOOTHSNRTHRMID field reset value +#define MDM_SMOOTHSNRTHRMID_RST 0xF + +/** + * @brief Constructs a value for the SMOOTHSNRTHR register given values for its fields + * and writes the value to the register. + * + * @param[in] smoothsnrthrhigh - The value to use for the SMOOTHSNRTHRHIGH field. + * @param[in] smoothsnrthrmid - The value to use for the SMOOTHSNRTHRMID field. + */ +__INLINE void mdm_smoothsnrthr_pack(uint8_t smoothsnrthrhigh, uint8_t smoothsnrthrmid) +{ + ASSERT_ERR((((uint32_t)smoothsnrthrhigh << 8) & ~((uint32_t)0x0000FF00)) == 0); + ASSERT_ERR((((uint32_t)smoothsnrthrmid << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(MDM_SMOOTHSNRTHR_ADDR, ((uint32_t)smoothsnrthrhigh << 8) | ((uint32_t)smoothsnrthrmid << 0)); +} + +/** + * @brief Unpacks SMOOTHSNRTHR's fields from current value of the SMOOTHSNRTHR register. + * + * Reads the SMOOTHSNRTHR register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] smoothsnrthrhigh - Will be populated with the current value of this field from the register. + * @param[out] smoothsnrthrmid - Will be populated with the current value of this field from the register. + */ +__INLINE void mdm_smoothsnrthr_unpack(uint8_t *smoothsnrthrhigh, uint8_t *smoothsnrthrmid) +{ + uint32_t localVal = REG_PL_RD(MDM_SMOOTHSNRTHR_ADDR); + + *smoothsnrthrhigh = (localVal & ((uint32_t)0x0000FF00)) >> 8; + *smoothsnrthrmid = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +/** + * @brief Returns the current value of the SMOOTHSNRTHRHIGH field in the SMOOTHSNRTHR register. + * + * The SMOOTHSNRTHR register will be read and the SMOOTHSNRTHRHIGH field's value will be returned. + * + * @return The current value of the SMOOTHSNRTHRHIGH field in the SMOOTHSNRTHR register. + */ +__INLINE uint8_t mdm_smoothsnrthrhigh_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_SMOOTHSNRTHR_ADDR); + return ((localVal & ((uint32_t)0x0000FF00)) >> 8); +} + +/** + * @brief Sets the SMOOTHSNRTHRHIGH field of the SMOOTHSNRTHR register. + * + * The SMOOTHSNRTHR register will be read, modified to contain the new field value, and written. + * + * @param[in] smoothsnrthrhigh - The value to set the field to. + */ +__INLINE void mdm_smoothsnrthrhigh_setf(uint8_t smoothsnrthrhigh) +{ + ASSERT_ERR((((uint32_t)smoothsnrthrhigh << 8) & ~((uint32_t)0x0000FF00)) == 0); + REG_PL_WR(MDM_SMOOTHSNRTHR_ADDR, (REG_PL_RD(MDM_SMOOTHSNRTHR_ADDR) & ~((uint32_t)0x0000FF00)) | ((uint32_t)smoothsnrthrhigh << 8)); +} + +/** + * @brief Returns the current value of the SMOOTHSNRTHRMID field in the SMOOTHSNRTHR register. + * + * The SMOOTHSNRTHR register will be read and the SMOOTHSNRTHRMID field's value will be returned. + * + * @return The current value of the SMOOTHSNRTHRMID field in the SMOOTHSNRTHR register. + */ +__INLINE uint8_t mdm_smoothsnrthrmid_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_SMOOTHSNRTHR_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +/** + * @brief Sets the SMOOTHSNRTHRMID field of the SMOOTHSNRTHR register. + * + * The SMOOTHSNRTHR register will be read, modified to contain the new field value, and written. + * + * @param[in] smoothsnrthrmid - The value to set the field to. + */ +__INLINE void mdm_smoothsnrthrmid_setf(uint8_t smoothsnrthrmid) +{ + ASSERT_ERR((((uint32_t)smoothsnrthrmid << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(MDM_SMOOTHSNRTHR_ADDR, (REG_PL_RD(MDM_SMOOTHSNRTHR_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)smoothsnrthrmid << 0)); +} + +/// @} + +/** + * @name RXCTRL0 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  20:16        TDBWDETWEIGHT   0x16
+ *     13         RXC2SDISBCFG   0
+ *     12          RXIQSWAPCFG   0
+ *     05          TDBWFORCE40   0
+ *     04          TDBWFORCE20   0
+ *     02         RATEERRORCFG   1
+ *     01        LSIGPARITYCFG   1
+ *     00          PROPMODECFG   0
+ * 
+ * + * @{ + */ + +/// Address of the RXCTRL0 register +#define MDM_RXCTRL0_ADDR 0x01000834 +/// Offset of the RXCTRL0 register from the base address +#define MDM_RXCTRL0_OFFSET 0x00000834 +/// Index of the RXCTRL0 register +#define MDM_RXCTRL0_INDEX 0x0000020D +/// Reset value of the RXCTRL0 register +#define MDM_RXCTRL0_RESET 0x00160006 + +/** + * @brief Returns the current value of the RXCTRL0 register. + * The RXCTRL0 register will be read and its value returned. + * @return The current value of the RXCTRL0 register. + */ +__INLINE uint32_t mdm_rxctrl0_get(void) +{ + return REG_PL_RD(MDM_RXCTRL0_ADDR); +} + +/** + * @brief Sets the RXCTRL0 register to a value. + * The RXCTRL0 register will be written. + * @param value - The value to write. + */ +__INLINE void mdm_rxctrl0_set(uint32_t value) +{ + REG_PL_WR(MDM_RXCTRL0_ADDR, value); +} + +// field definitions +/// TDBWDETWEIGHT field mask +#define MDM_TDBWDETWEIGHT_MASK ((uint32_t)0x001F0000) +/// TDBWDETWEIGHT field LSB position +#define MDM_TDBWDETWEIGHT_LSB 16 +/// TDBWDETWEIGHT field width +#define MDM_TDBWDETWEIGHT_WIDTH ((uint32_t)0x00000005) +/// RXC2SDISBCFG field bit +#define MDM_RXC2SDISBCFG_BIT ((uint32_t)0x00002000) +/// RXC2SDISBCFG field position +#define MDM_RXC2SDISBCFG_POS 13 +/// RXIQSWAPCFG field bit +#define MDM_RXIQSWAPCFG_BIT ((uint32_t)0x00001000) +/// RXIQSWAPCFG field position +#define MDM_RXIQSWAPCFG_POS 12 +/// TDBWFORCE40 field bit +#define MDM_TDBWFORCE40_BIT ((uint32_t)0x00000020) +/// TDBWFORCE40 field position +#define MDM_TDBWFORCE40_POS 5 +/// TDBWFORCE20 field bit +#define MDM_TDBWFORCE20_BIT ((uint32_t)0x00000010) +/// TDBWFORCE20 field position +#define MDM_TDBWFORCE20_POS 4 +/// RATEERRORCFG field bit +#define MDM_RATEERRORCFG_BIT ((uint32_t)0x00000004) +/// RATEERRORCFG field position +#define MDM_RATEERRORCFG_POS 2 +/// LSIGPARITYCFG field bit +#define MDM_LSIGPARITYCFG_BIT ((uint32_t)0x00000002) +/// LSIGPARITYCFG field position +#define MDM_LSIGPARITYCFG_POS 1 +/// PROPMODECFG field bit +#define MDM_PROPMODECFG_BIT ((uint32_t)0x00000001) +/// PROPMODECFG field position +#define MDM_PROPMODECFG_POS 0 + +/// TDBWDETWEIGHT field reset value +#define MDM_TDBWDETWEIGHT_RST 0x16 +/// RXC2SDISBCFG field reset value +#define MDM_RXC2SDISBCFG_RST 0x0 +/// RXIQSWAPCFG field reset value +#define MDM_RXIQSWAPCFG_RST 0x0 +/// TDBWFORCE40 field reset value +#define MDM_TDBWFORCE40_RST 0x0 +/// TDBWFORCE20 field reset value +#define MDM_TDBWFORCE20_RST 0x0 +/// RATEERRORCFG field reset value +#define MDM_RATEERRORCFG_RST 0x1 +/// LSIGPARITYCFG field reset value +#define MDM_LSIGPARITYCFG_RST 0x1 +/// PROPMODECFG field reset value +#define MDM_PROPMODECFG_RST 0x0 + +/** + * @brief Constructs a value for the RXCTRL0 register given values for its fields + * and writes the value to the register. + * + * @param[in] tdbwdetweight - The value to use for the TDBWDETWEIGHT field. + * @param[in] rxc2sdisbcfg - The value to use for the RXC2SDISBCFG field. + * @param[in] rxiqswapcfg - The value to use for the RXIQSWAPCFG field. + * @param[in] tdbwforce40 - The value to use for the TDBWFORCE40 field. + * @param[in] tdbwforce20 - The value to use for the TDBWFORCE20 field. + * @param[in] rateerrorcfg - The value to use for the RATEERRORCFG field. + * @param[in] lsigparitycfg - The value to use for the LSIGPARITYCFG field. + * @param[in] propmodecfg - The value to use for the PROPMODECFG field. + */ +__INLINE void mdm_rxctrl0_pack(uint8_t tdbwdetweight, uint8_t rxc2sdisbcfg, uint8_t rxiqswapcfg, uint8_t tdbwforce40, uint8_t tdbwforce20, uint8_t rateerrorcfg, uint8_t lsigparitycfg, uint8_t propmodecfg) +{ + ASSERT_ERR((((uint32_t)tdbwdetweight << 16) & ~((uint32_t)0x001F0000)) == 0); + ASSERT_ERR((((uint32_t)rxc2sdisbcfg << 13) & ~((uint32_t)0x00002000)) == 0); + ASSERT_ERR((((uint32_t)rxiqswapcfg << 12) & ~((uint32_t)0x00001000)) == 0); + ASSERT_ERR((((uint32_t)tdbwforce40 << 5) & ~((uint32_t)0x00000020)) == 0); + ASSERT_ERR((((uint32_t)tdbwforce20 << 4) & ~((uint32_t)0x00000010)) == 0); + ASSERT_ERR((((uint32_t)rateerrorcfg << 2) & ~((uint32_t)0x00000004)) == 0); + ASSERT_ERR((((uint32_t)lsigparitycfg << 1) & ~((uint32_t)0x00000002)) == 0); + ASSERT_ERR((((uint32_t)propmodecfg << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(MDM_RXCTRL0_ADDR, ((uint32_t)tdbwdetweight << 16) | ((uint32_t)rxc2sdisbcfg << 13) | ((uint32_t)rxiqswapcfg << 12) | ((uint32_t)tdbwforce40 << 5) | ((uint32_t)tdbwforce20 << 4) | ((uint32_t)rateerrorcfg << 2) | ((uint32_t)lsigparitycfg << 1) | ((uint32_t)propmodecfg << 0)); +} + +/** + * @brief Unpacks RXCTRL0's fields from current value of the RXCTRL0 register. + * + * Reads the RXCTRL0 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] tdbwdetweight - Will be populated with the current value of this field from the register. + * @param[out] rxc2sdisbcfg - Will be populated with the current value of this field from the register. + * @param[out] rxiqswapcfg - Will be populated with the current value of this field from the register. + * @param[out] tdbwforce40 - Will be populated with the current value of this field from the register. + * @param[out] tdbwforce20 - Will be populated with the current value of this field from the register. + * @param[out] rateerrorcfg - Will be populated with the current value of this field from the register. + * @param[out] lsigparitycfg - Will be populated with the current value of this field from the register. + * @param[out] propmodecfg - Will be populated with the current value of this field from the register. + */ +__INLINE void mdm_rxctrl0_unpack(uint8_t *tdbwdetweight, uint8_t *rxc2sdisbcfg, uint8_t *rxiqswapcfg, uint8_t *tdbwforce40, uint8_t *tdbwforce20, uint8_t *rateerrorcfg, uint8_t *lsigparitycfg, uint8_t *propmodecfg) +{ + uint32_t localVal = REG_PL_RD(MDM_RXCTRL0_ADDR); + + *tdbwdetweight = (localVal & ((uint32_t)0x001F0000)) >> 16; + *rxc2sdisbcfg = (localVal & ((uint32_t)0x00002000)) >> 13; + *rxiqswapcfg = (localVal & ((uint32_t)0x00001000)) >> 12; + *tdbwforce40 = (localVal & ((uint32_t)0x00000020)) >> 5; + *tdbwforce20 = (localVal & ((uint32_t)0x00000010)) >> 4; + *rateerrorcfg = (localVal & ((uint32_t)0x00000004)) >> 2; + *lsigparitycfg = (localVal & ((uint32_t)0x00000002)) >> 1; + *propmodecfg = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +/** + * @brief Returns the current value of the TDBWDETWEIGHT field in the RXCTRL0 register. + * + * The RXCTRL0 register will be read and the TDBWDETWEIGHT field's value will be returned. + * + * @return The current value of the TDBWDETWEIGHT field in the RXCTRL0 register. + */ +__INLINE uint8_t mdm_tdbwdetweight_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXCTRL0_ADDR); + return ((localVal & ((uint32_t)0x001F0000)) >> 16); +} + +/** + * @brief Sets the TDBWDETWEIGHT field of the RXCTRL0 register. + * + * The RXCTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] tdbwdetweight - The value to set the field to. + */ +__INLINE void mdm_tdbwdetweight_setf(uint8_t tdbwdetweight) +{ + ASSERT_ERR((((uint32_t)tdbwdetweight << 16) & ~((uint32_t)0x001F0000)) == 0); + REG_PL_WR(MDM_RXCTRL0_ADDR, (REG_PL_RD(MDM_RXCTRL0_ADDR) & ~((uint32_t)0x001F0000)) | ((uint32_t)tdbwdetweight << 16)); +} + +/** + * @brief Returns the current value of the RXC2SDISBCFG field in the RXCTRL0 register. + * + * The RXCTRL0 register will be read and the RXC2SDISBCFG field's value will be returned. + * + * @return The current value of the RXC2SDISBCFG field in the RXCTRL0 register. + */ +__INLINE uint8_t mdm_rxc2sdisbcfg_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXCTRL0_ADDR); + return ((localVal & ((uint32_t)0x00002000)) >> 13); +} + +/** + * @brief Sets the RXC2SDISBCFG field of the RXCTRL0 register. + * + * The RXCTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] rxc2sdisbcfg - The value to set the field to. + */ +__INLINE void mdm_rxc2sdisbcfg_setf(uint8_t rxc2sdisbcfg) +{ + ASSERT_ERR((((uint32_t)rxc2sdisbcfg << 13) & ~((uint32_t)0x00002000)) == 0); + REG_PL_WR(MDM_RXCTRL0_ADDR, (REG_PL_RD(MDM_RXCTRL0_ADDR) & ~((uint32_t)0x00002000)) | ((uint32_t)rxc2sdisbcfg << 13)); +} + +/** + * @brief Returns the current value of the RXIQSWAPCFG field in the RXCTRL0 register. + * + * The RXCTRL0 register will be read and the RXIQSWAPCFG field's value will be returned. + * + * @return The current value of the RXIQSWAPCFG field in the RXCTRL0 register. + */ +__INLINE uint8_t mdm_rxiqswapcfg_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXCTRL0_ADDR); + return ((localVal & ((uint32_t)0x00001000)) >> 12); +} + +/** + * @brief Sets the RXIQSWAPCFG field of the RXCTRL0 register. + * + * The RXCTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] rxiqswapcfg - The value to set the field to. + */ +__INLINE void mdm_rxiqswapcfg_setf(uint8_t rxiqswapcfg) +{ + ASSERT_ERR((((uint32_t)rxiqswapcfg << 12) & ~((uint32_t)0x00001000)) == 0); + REG_PL_WR(MDM_RXCTRL0_ADDR, (REG_PL_RD(MDM_RXCTRL0_ADDR) & ~((uint32_t)0x00001000)) | ((uint32_t)rxiqswapcfg << 12)); +} + +/** + * @brief Returns the current value of the TDBWFORCE40 field in the RXCTRL0 register. + * + * The RXCTRL0 register will be read and the TDBWFORCE40 field's value will be returned. + * + * @return The current value of the TDBWFORCE40 field in the RXCTRL0 register. + */ +__INLINE uint8_t mdm_tdbwforce40_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXCTRL0_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +/** + * @brief Sets the TDBWFORCE40 field of the RXCTRL0 register. + * + * The RXCTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] tdbwforce40 - The value to set the field to. + */ +__INLINE void mdm_tdbwforce40_setf(uint8_t tdbwforce40) +{ + ASSERT_ERR((((uint32_t)tdbwforce40 << 5) & ~((uint32_t)0x00000020)) == 0); + REG_PL_WR(MDM_RXCTRL0_ADDR, (REG_PL_RD(MDM_RXCTRL0_ADDR) & ~((uint32_t)0x00000020)) | ((uint32_t)tdbwforce40 << 5)); +} + +/** + * @brief Returns the current value of the TDBWFORCE20 field in the RXCTRL0 register. + * + * The RXCTRL0 register will be read and the TDBWFORCE20 field's value will be returned. + * + * @return The current value of the TDBWFORCE20 field in the RXCTRL0 register. + */ +__INLINE uint8_t mdm_tdbwforce20_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXCTRL0_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +/** + * @brief Sets the TDBWFORCE20 field of the RXCTRL0 register. + * + * The RXCTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] tdbwforce20 - The value to set the field to. + */ +__INLINE void mdm_tdbwforce20_setf(uint8_t tdbwforce20) +{ + ASSERT_ERR((((uint32_t)tdbwforce20 << 4) & ~((uint32_t)0x00000010)) == 0); + REG_PL_WR(MDM_RXCTRL0_ADDR, (REG_PL_RD(MDM_RXCTRL0_ADDR) & ~((uint32_t)0x00000010)) | ((uint32_t)tdbwforce20 << 4)); +} + +/** + * @brief Returns the current value of the RATEERRORCFG field in the RXCTRL0 register. + * + * The RXCTRL0 register will be read and the RATEERRORCFG field's value will be returned. + * + * @return The current value of the RATEERRORCFG field in the RXCTRL0 register. + */ +__INLINE uint8_t mdm_rateerrorcfg_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXCTRL0_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +/** + * @brief Sets the RATEERRORCFG field of the RXCTRL0 register. + * + * The RXCTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] rateerrorcfg - The value to set the field to. + */ +__INLINE void mdm_rateerrorcfg_setf(uint8_t rateerrorcfg) +{ + ASSERT_ERR((((uint32_t)rateerrorcfg << 2) & ~((uint32_t)0x00000004)) == 0); + REG_PL_WR(MDM_RXCTRL0_ADDR, (REG_PL_RD(MDM_RXCTRL0_ADDR) & ~((uint32_t)0x00000004)) | ((uint32_t)rateerrorcfg << 2)); +} + +/** + * @brief Returns the current value of the LSIGPARITYCFG field in the RXCTRL0 register. + * + * The RXCTRL0 register will be read and the LSIGPARITYCFG field's value will be returned. + * + * @return The current value of the LSIGPARITYCFG field in the RXCTRL0 register. + */ +__INLINE uint8_t mdm_lsigparitycfg_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXCTRL0_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +/** + * @brief Sets the LSIGPARITYCFG field of the RXCTRL0 register. + * + * The RXCTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] lsigparitycfg - The value to set the field to. + */ +__INLINE void mdm_lsigparitycfg_setf(uint8_t lsigparitycfg) +{ + ASSERT_ERR((((uint32_t)lsigparitycfg << 1) & ~((uint32_t)0x00000002)) == 0); + REG_PL_WR(MDM_RXCTRL0_ADDR, (REG_PL_RD(MDM_RXCTRL0_ADDR) & ~((uint32_t)0x00000002)) | ((uint32_t)lsigparitycfg << 1)); +} + +/** + * @brief Returns the current value of the PROPMODECFG field in the RXCTRL0 register. + * + * The RXCTRL0 register will be read and the PROPMODECFG field's value will be returned. + * + * @return The current value of the PROPMODECFG field in the RXCTRL0 register. + */ +__INLINE uint8_t mdm_propmodecfg_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXCTRL0_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/** + * @brief Sets the PROPMODECFG field of the RXCTRL0 register. + * + * The RXCTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] propmodecfg - The value to set the field to. + */ +__INLINE void mdm_propmodecfg_setf(uint8_t propmodecfg) +{ + ASSERT_ERR((((uint32_t)propmodecfg << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(MDM_RXCTRL0_ADDR, (REG_PL_RD(MDM_RXCTRL0_ADDR) & ~((uint32_t)0x00000001)) | ((uint32_t)propmodecfg << 0)); +} + +/// @} + +/** + * @name TXCTRL0 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     29         TXC2SDISBCFG   0
+ *     28          TXIQSWAPCFG   0
+ *  09:00         TXSTARTDELAY   0xB4
+ * 
+ * + * @{ + */ + +/// Address of the TXCTRL0 register +#define MDM_TXCTRL0_ADDR 0x01000838 +/// Offset of the TXCTRL0 register from the base address +#define MDM_TXCTRL0_OFFSET 0x00000838 +/// Index of the TXCTRL0 register +#define MDM_TXCTRL0_INDEX 0x0000020E +/// Reset value of the TXCTRL0 register +#define MDM_TXCTRL0_RESET 0x000000B4 + +/** + * @brief Returns the current value of the TXCTRL0 register. + * The TXCTRL0 register will be read and its value returned. + * @return The current value of the TXCTRL0 register. + */ +__INLINE uint32_t mdm_txctrl0_get(void) +{ + return REG_PL_RD(MDM_TXCTRL0_ADDR); +} + +/** + * @brief Sets the TXCTRL0 register to a value. + * The TXCTRL0 register will be written. + * @param value - The value to write. + */ +__INLINE void mdm_txctrl0_set(uint32_t value) +{ + REG_PL_WR(MDM_TXCTRL0_ADDR, value); +} + +// field definitions +/// TXC2SDISBCFG field bit +#define MDM_TXC2SDISBCFG_BIT ((uint32_t)0x20000000) +/// TXC2SDISBCFG field position +#define MDM_TXC2SDISBCFG_POS 29 +/// TXIQSWAPCFG field bit +#define MDM_TXIQSWAPCFG_BIT ((uint32_t)0x10000000) +/// TXIQSWAPCFG field position +#define MDM_TXIQSWAPCFG_POS 28 +/// TXSTARTDELAY field mask +#define MDM_TXSTARTDELAY_MASK ((uint32_t)0x000003FF) +/// TXSTARTDELAY field LSB position +#define MDM_TXSTARTDELAY_LSB 0 +/// TXSTARTDELAY field width +#define MDM_TXSTARTDELAY_WIDTH ((uint32_t)0x0000000A) + +/// TXC2SDISBCFG field reset value +#define MDM_TXC2SDISBCFG_RST 0x0 +/// TXIQSWAPCFG field reset value +#define MDM_TXIQSWAPCFG_RST 0x0 +/// TXSTARTDELAY field reset value +#define MDM_TXSTARTDELAY_RST 0xB4 + +/** + * @brief Constructs a value for the TXCTRL0 register given values for its fields + * and writes the value to the register. + * + * @param[in] txc2sdisbcfg - The value to use for the TXC2SDISBCFG field. + * @param[in] txiqswapcfg - The value to use for the TXIQSWAPCFG field. + * @param[in] txstartdelay - The value to use for the TXSTARTDELAY field. + */ +__INLINE void mdm_txctrl0_pack(uint8_t txc2sdisbcfg, uint8_t txiqswapcfg, uint16_t txstartdelay) +{ + ASSERT_ERR((((uint32_t)txc2sdisbcfg << 29) & ~((uint32_t)0x20000000)) == 0); + ASSERT_ERR((((uint32_t)txiqswapcfg << 28) & ~((uint32_t)0x10000000)) == 0); + ASSERT_ERR((((uint32_t)txstartdelay << 0) & ~((uint32_t)0x000003FF)) == 0); + REG_PL_WR(MDM_TXCTRL0_ADDR, ((uint32_t)txc2sdisbcfg << 29) | ((uint32_t)txiqswapcfg << 28) | ((uint32_t)txstartdelay << 0)); +} + +/** + * @brief Unpacks TXCTRL0's fields from current value of the TXCTRL0 register. + * + * Reads the TXCTRL0 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] txc2sdisbcfg - Will be populated with the current value of this field from the register. + * @param[out] txiqswapcfg - Will be populated with the current value of this field from the register. + * @param[out] txstartdelay - Will be populated with the current value of this field from the register. + */ +__INLINE void mdm_txctrl0_unpack(uint8_t *txc2sdisbcfg, uint8_t *txiqswapcfg, uint16_t *txstartdelay) +{ + uint32_t localVal = REG_PL_RD(MDM_TXCTRL0_ADDR); + + *txc2sdisbcfg = (localVal & ((uint32_t)0x20000000)) >> 29; + *txiqswapcfg = (localVal & ((uint32_t)0x10000000)) >> 28; + *txstartdelay = (localVal & ((uint32_t)0x000003FF)) >> 0; +} + +/** + * @brief Returns the current value of the TXC2SDISBCFG field in the TXCTRL0 register. + * + * The TXCTRL0 register will be read and the TXC2SDISBCFG field's value will be returned. + * + * @return The current value of the TXC2SDISBCFG field in the TXCTRL0 register. + */ +__INLINE uint8_t mdm_txc2sdisbcfg_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TXCTRL0_ADDR); + return ((localVal & ((uint32_t)0x20000000)) >> 29); +} + +/** + * @brief Sets the TXC2SDISBCFG field of the TXCTRL0 register. + * + * The TXCTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] txc2sdisbcfg - The value to set the field to. + */ +__INLINE void mdm_txc2sdisbcfg_setf(uint8_t txc2sdisbcfg) +{ + ASSERT_ERR((((uint32_t)txc2sdisbcfg << 29) & ~((uint32_t)0x20000000)) == 0); + REG_PL_WR(MDM_TXCTRL0_ADDR, (REG_PL_RD(MDM_TXCTRL0_ADDR) & ~((uint32_t)0x20000000)) | ((uint32_t)txc2sdisbcfg << 29)); +} + +/** + * @brief Returns the current value of the TXIQSWAPCFG field in the TXCTRL0 register. + * + * The TXCTRL0 register will be read and the TXIQSWAPCFG field's value will be returned. + * + * @return The current value of the TXIQSWAPCFG field in the TXCTRL0 register. + */ +__INLINE uint8_t mdm_txiqswapcfg_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TXCTRL0_ADDR); + return ((localVal & ((uint32_t)0x10000000)) >> 28); +} + +/** + * @brief Sets the TXIQSWAPCFG field of the TXCTRL0 register. + * + * The TXCTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] txiqswapcfg - The value to set the field to. + */ +__INLINE void mdm_txiqswapcfg_setf(uint8_t txiqswapcfg) +{ + ASSERT_ERR((((uint32_t)txiqswapcfg << 28) & ~((uint32_t)0x10000000)) == 0); + REG_PL_WR(MDM_TXCTRL0_ADDR, (REG_PL_RD(MDM_TXCTRL0_ADDR) & ~((uint32_t)0x10000000)) | ((uint32_t)txiqswapcfg << 28)); +} + +/** + * @brief Returns the current value of the TXSTARTDELAY field in the TXCTRL0 register. + * + * The TXCTRL0 register will be read and the TXSTARTDELAY field's value will be returned. + * + * @return The current value of the TXSTARTDELAY field in the TXCTRL0 register. + */ +__INLINE uint16_t mdm_txstartdelay_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TXCTRL0_ADDR); + return ((localVal & ((uint32_t)0x000003FF)) >> 0); +} + +/** + * @brief Sets the TXSTARTDELAY field of the TXCTRL0 register. + * + * The TXCTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] txstartdelay - The value to set the field to. + */ +__INLINE void mdm_txstartdelay_setf(uint16_t txstartdelay) +{ + ASSERT_ERR((((uint32_t)txstartdelay << 0) & ~((uint32_t)0x000003FF)) == 0); + REG_PL_WR(MDM_TXCTRL0_ADDR, (REG_PL_RD(MDM_TXCTRL0_ADDR) & ~((uint32_t)0x000003FF)) | ((uint32_t)txstartdelay << 0)); +} + +/// @} + +/** + * @name RXCTRL1 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  12:00           RXNDBPSMAX   0xC30
+ * 
+ * + * @{ + */ + +/// Address of the RXCTRL1 register +#define MDM_RXCTRL1_ADDR 0x0100083C +/// Offset of the RXCTRL1 register from the base address +#define MDM_RXCTRL1_OFFSET 0x0000083C +/// Index of the RXCTRL1 register +#define MDM_RXCTRL1_INDEX 0x0000020F +/// Reset value of the RXCTRL1 register +#define MDM_RXCTRL1_RESET 0x00000C30 + +/** + * @brief Returns the current value of the RXCTRL1 register. + * The RXCTRL1 register will be read and its value returned. + * @return The current value of the RXCTRL1 register. + */ +__INLINE uint32_t mdm_rxctrl1_get(void) +{ + return REG_PL_RD(MDM_RXCTRL1_ADDR); +} + +/** + * @brief Sets the RXCTRL1 register to a value. + * The RXCTRL1 register will be written. + * @param value - The value to write. + */ +__INLINE void mdm_rxctrl1_set(uint32_t value) +{ + REG_PL_WR(MDM_RXCTRL1_ADDR, value); +} + +// field definitions +/// RXNDBPSMAX field mask +#define MDM_RXNDBPSMAX_MASK ((uint32_t)0x00001FFF) +/// RXNDBPSMAX field LSB position +#define MDM_RXNDBPSMAX_LSB 0 +/// RXNDBPSMAX field width +#define MDM_RXNDBPSMAX_WIDTH ((uint32_t)0x0000000D) + +/// RXNDBPSMAX field reset value +#define MDM_RXNDBPSMAX_RST 0xC30 + +/** + * @brief Returns the current value of the RXNDBPSMAX field in the RXCTRL1 register. + * + * The RXCTRL1 register will be read and the RXNDBPSMAX field's value will be returned. + * + * @return The current value of the RXNDBPSMAX field in the RXCTRL1 register. + */ +__INLINE uint16_t mdm_rxndbpsmax_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXCTRL1_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x00001FFF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the RXNDBPSMAX field of the RXCTRL1 register. + * + * The RXCTRL1 register will be read, modified to contain the new field value, and written. + * + * @param[in] rxndbpsmax - The value to set the field to. + */ +__INLINE void mdm_rxndbpsmax_setf(uint16_t rxndbpsmax) +{ + ASSERT_ERR((((uint32_t)rxndbpsmax << 0) & ~((uint32_t)0x00001FFF)) == 0); + REG_PL_WR(MDM_RXCTRL1_ADDR, (uint32_t)rxndbpsmax << 0); +} + +/// @} + +/** + * @name CLKGATECTRL0 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31           PHYTXCLKEN   1
+ *     30           PHYRXCLKEN   1
+ *     29          AGCMEMCLKEN   1
+ *     28             AGCCLKEN   1
+ *     27             FE3CLKEN   1
+ *     26             FE2CLKEN   1
+ *     25             FE1CLKEN   1
+ *     24             FE0CLKEN   1
+ *     23          STOCPECLKEN   1
+ *     22             EQUCLKEN   1
+ *     21         TDCOMP3CLKEN   1
+ *     20         TDCOMP2CLKEN   1
+ *     19         TDCOMP1CLKEN   1
+ *     18         TDCOMP0CLKEN   1
+ *     17         TDFOESTCLKEN   1
+ *     16             TBECLKEN   1
+ *     15             VTBCLKEN   1
+ *     14         FFT3MEMCLKEN   1
+ *     13            FFT3CLKEN   1
+ *     12         FFT2MEMCLKEN   1
+ *     11            FFT2CLKEN   1
+ *     10         FFT1MEMCLKEN   1
+ *     09            FFT1CLKEN   1
+ *     08         FFT0MEMCLKEN   1
+ *     07            FFT0CLKEN   1
+ *     06           CHESTCLKEN   1
+ *     05            GMEMCLKEN   1
+ *     04            HMEMCLKEN   1
+ *     03            QMEMCLKEN   1
+ *     02        INTLVMEMCLKEN   1
+ *     01        INTLVVTBCLKEN   1
+ *     00        INTLVPHYCLKEN   1
+ * 
+ * + * @{ + */ + +/// Address of the CLKGATECTRL0 register +#define MDM_CLKGATECTRL0_ADDR 0x01000840 +/// Offset of the CLKGATECTRL0 register from the base address +#define MDM_CLKGATECTRL0_OFFSET 0x00000840 +/// Index of the CLKGATECTRL0 register +#define MDM_CLKGATECTRL0_INDEX 0x00000210 +/// Reset value of the CLKGATECTRL0 register +#define MDM_CLKGATECTRL0_RESET 0xFFFFFFFF + +/** + * @brief Returns the current value of the CLKGATECTRL0 register. + * The CLKGATECTRL0 register will be read and its value returned. + * @return The current value of the CLKGATECTRL0 register. + */ +__INLINE uint32_t mdm_clkgatectrl0_get(void) +{ + return REG_PL_RD(MDM_CLKGATECTRL0_ADDR); +} + +/** + * @brief Sets the CLKGATECTRL0 register to a value. + * The CLKGATECTRL0 register will be written. + * @param value - The value to write. + */ +__INLINE void mdm_clkgatectrl0_set(uint32_t value) +{ + REG_PL_WR(MDM_CLKGATECTRL0_ADDR, value); +} + +// field definitions +/// PHYTXCLKEN field bit +#define MDM_PHYTXCLKEN_BIT ((uint32_t)0x80000000) +/// PHYTXCLKEN field position +#define MDM_PHYTXCLKEN_POS 31 +/// PHYRXCLKEN field bit +#define MDM_PHYRXCLKEN_BIT ((uint32_t)0x40000000) +/// PHYRXCLKEN field position +#define MDM_PHYRXCLKEN_POS 30 +/// AGCMEMCLKEN field bit +#define MDM_AGCMEMCLKEN_BIT ((uint32_t)0x20000000) +/// AGCMEMCLKEN field position +#define MDM_AGCMEMCLKEN_POS 29 +/// AGCCLKEN field bit +#define MDM_AGCCLKEN_BIT ((uint32_t)0x10000000) +/// AGCCLKEN field position +#define MDM_AGCCLKEN_POS 28 +/// FE3CLKEN field bit +#define MDM_FE3CLKEN_BIT ((uint32_t)0x08000000) +/// FE3CLKEN field position +#define MDM_FE3CLKEN_POS 27 +/// FE2CLKEN field bit +#define MDM_FE2CLKEN_BIT ((uint32_t)0x04000000) +/// FE2CLKEN field position +#define MDM_FE2CLKEN_POS 26 +/// FE1CLKEN field bit +#define MDM_FE1CLKEN_BIT ((uint32_t)0x02000000) +/// FE1CLKEN field position +#define MDM_FE1CLKEN_POS 25 +/// FE0CLKEN field bit +#define MDM_FE0CLKEN_BIT ((uint32_t)0x01000000) +/// FE0CLKEN field position +#define MDM_FE0CLKEN_POS 24 +/// STOCPECLKEN field bit +#define MDM_STOCPECLKEN_BIT ((uint32_t)0x00800000) +/// STOCPECLKEN field position +#define MDM_STOCPECLKEN_POS 23 +/// EQUCLKEN field bit +#define MDM_EQUCLKEN_BIT ((uint32_t)0x00400000) +/// EQUCLKEN field position +#define MDM_EQUCLKEN_POS 22 +/// TDCOMP3CLKEN field bit +#define MDM_TDCOMP3CLKEN_BIT ((uint32_t)0x00200000) +/// TDCOMP3CLKEN field position +#define MDM_TDCOMP3CLKEN_POS 21 +/// TDCOMP2CLKEN field bit +#define MDM_TDCOMP2CLKEN_BIT ((uint32_t)0x00100000) +/// TDCOMP2CLKEN field position +#define MDM_TDCOMP2CLKEN_POS 20 +/// TDCOMP1CLKEN field bit +#define MDM_TDCOMP1CLKEN_BIT ((uint32_t)0x00080000) +/// TDCOMP1CLKEN field position +#define MDM_TDCOMP1CLKEN_POS 19 +/// TDCOMP0CLKEN field bit +#define MDM_TDCOMP0CLKEN_BIT ((uint32_t)0x00040000) +/// TDCOMP0CLKEN field position +#define MDM_TDCOMP0CLKEN_POS 18 +/// TDFOESTCLKEN field bit +#define MDM_TDFOESTCLKEN_BIT ((uint32_t)0x00020000) +/// TDFOESTCLKEN field position +#define MDM_TDFOESTCLKEN_POS 17 +/// TBECLKEN field bit +#define MDM_TBECLKEN_BIT ((uint32_t)0x00010000) +/// TBECLKEN field position +#define MDM_TBECLKEN_POS 16 +/// VTBCLKEN field bit +#define MDM_VTBCLKEN_BIT ((uint32_t)0x00008000) +/// VTBCLKEN field position +#define MDM_VTBCLKEN_POS 15 +/// FFT3MEMCLKEN field bit +#define MDM_FFT3MEMCLKEN_BIT ((uint32_t)0x00004000) +/// FFT3MEMCLKEN field position +#define MDM_FFT3MEMCLKEN_POS 14 +/// FFT3CLKEN field bit +#define MDM_FFT3CLKEN_BIT ((uint32_t)0x00002000) +/// FFT3CLKEN field position +#define MDM_FFT3CLKEN_POS 13 +/// FFT2MEMCLKEN field bit +#define MDM_FFT2MEMCLKEN_BIT ((uint32_t)0x00001000) +/// FFT2MEMCLKEN field position +#define MDM_FFT2MEMCLKEN_POS 12 +/// FFT2CLKEN field bit +#define MDM_FFT2CLKEN_BIT ((uint32_t)0x00000800) +/// FFT2CLKEN field position +#define MDM_FFT2CLKEN_POS 11 +/// FFT1MEMCLKEN field bit +#define MDM_FFT1MEMCLKEN_BIT ((uint32_t)0x00000400) +/// FFT1MEMCLKEN field position +#define MDM_FFT1MEMCLKEN_POS 10 +/// FFT1CLKEN field bit +#define MDM_FFT1CLKEN_BIT ((uint32_t)0x00000200) +/// FFT1CLKEN field position +#define MDM_FFT1CLKEN_POS 9 +/// FFT0MEMCLKEN field bit +#define MDM_FFT0MEMCLKEN_BIT ((uint32_t)0x00000100) +/// FFT0MEMCLKEN field position +#define MDM_FFT0MEMCLKEN_POS 8 +/// FFT0CLKEN field bit +#define MDM_FFT0CLKEN_BIT ((uint32_t)0x00000080) +/// FFT0CLKEN field position +#define MDM_FFT0CLKEN_POS 7 +/// CHESTCLKEN field bit +#define MDM_CHESTCLKEN_BIT ((uint32_t)0x00000040) +/// CHESTCLKEN field position +#define MDM_CHESTCLKEN_POS 6 +/// GMEMCLKEN field bit +#define MDM_GMEMCLKEN_BIT ((uint32_t)0x00000020) +/// GMEMCLKEN field position +#define MDM_GMEMCLKEN_POS 5 +/// HMEMCLKEN field bit +#define MDM_HMEMCLKEN_BIT ((uint32_t)0x00000010) +/// HMEMCLKEN field position +#define MDM_HMEMCLKEN_POS 4 +/// QMEMCLKEN field bit +#define MDM_QMEMCLKEN_BIT ((uint32_t)0x00000008) +/// QMEMCLKEN field position +#define MDM_QMEMCLKEN_POS 3 +/// INTLVMEMCLKEN field bit +#define MDM_INTLVMEMCLKEN_BIT ((uint32_t)0x00000004) +/// INTLVMEMCLKEN field position +#define MDM_INTLVMEMCLKEN_POS 2 +/// INTLVVTBCLKEN field bit +#define MDM_INTLVVTBCLKEN_BIT ((uint32_t)0x00000002) +/// INTLVVTBCLKEN field position +#define MDM_INTLVVTBCLKEN_POS 1 +/// INTLVPHYCLKEN field bit +#define MDM_INTLVPHYCLKEN_BIT ((uint32_t)0x00000001) +/// INTLVPHYCLKEN field position +#define MDM_INTLVPHYCLKEN_POS 0 + +/// PHYTXCLKEN field reset value +#define MDM_PHYTXCLKEN_RST 0x1 +/// PHYRXCLKEN field reset value +#define MDM_PHYRXCLKEN_RST 0x1 +/// AGCMEMCLKEN field reset value +#define MDM_AGCMEMCLKEN_RST 0x1 +/// AGCCLKEN field reset value +#define MDM_AGCCLKEN_RST 0x1 +/// FE3CLKEN field reset value +#define MDM_FE3CLKEN_RST 0x1 +/// FE2CLKEN field reset value +#define MDM_FE2CLKEN_RST 0x1 +/// FE1CLKEN field reset value +#define MDM_FE1CLKEN_RST 0x1 +/// FE0CLKEN field reset value +#define MDM_FE0CLKEN_RST 0x1 +/// STOCPECLKEN field reset value +#define MDM_STOCPECLKEN_RST 0x1 +/// EQUCLKEN field reset value +#define MDM_EQUCLKEN_RST 0x1 +/// TDCOMP3CLKEN field reset value +#define MDM_TDCOMP3CLKEN_RST 0x1 +/// TDCOMP2CLKEN field reset value +#define MDM_TDCOMP2CLKEN_RST 0x1 +/// TDCOMP1CLKEN field reset value +#define MDM_TDCOMP1CLKEN_RST 0x1 +/// TDCOMP0CLKEN field reset value +#define MDM_TDCOMP0CLKEN_RST 0x1 +/// TDFOESTCLKEN field reset value +#define MDM_TDFOESTCLKEN_RST 0x1 +/// TBECLKEN field reset value +#define MDM_TBECLKEN_RST 0x1 +/// VTBCLKEN field reset value +#define MDM_VTBCLKEN_RST 0x1 +/// FFT3MEMCLKEN field reset value +#define MDM_FFT3MEMCLKEN_RST 0x1 +/// FFT3CLKEN field reset value +#define MDM_FFT3CLKEN_RST 0x1 +/// FFT2MEMCLKEN field reset value +#define MDM_FFT2MEMCLKEN_RST 0x1 +/// FFT2CLKEN field reset value +#define MDM_FFT2CLKEN_RST 0x1 +/// FFT1MEMCLKEN field reset value +#define MDM_FFT1MEMCLKEN_RST 0x1 +/// FFT1CLKEN field reset value +#define MDM_FFT1CLKEN_RST 0x1 +/// FFT0MEMCLKEN field reset value +#define MDM_FFT0MEMCLKEN_RST 0x1 +/// FFT0CLKEN field reset value +#define MDM_FFT0CLKEN_RST 0x1 +/// CHESTCLKEN field reset value +#define MDM_CHESTCLKEN_RST 0x1 +/// GMEMCLKEN field reset value +#define MDM_GMEMCLKEN_RST 0x1 +/// HMEMCLKEN field reset value +#define MDM_HMEMCLKEN_RST 0x1 +/// QMEMCLKEN field reset value +#define MDM_QMEMCLKEN_RST 0x1 +/// INTLVMEMCLKEN field reset value +#define MDM_INTLVMEMCLKEN_RST 0x1 +/// INTLVVTBCLKEN field reset value +#define MDM_INTLVVTBCLKEN_RST 0x1 +/// INTLVPHYCLKEN field reset value +#define MDM_INTLVPHYCLKEN_RST 0x1 + +/** + * @brief Constructs a value for the CLKGATECTRL0 register given values for its fields + * and writes the value to the register. + * + * @param[in] phytxclken - The value to use for the PHYTXCLKEN field. + * @param[in] phyrxclken - The value to use for the PHYRXCLKEN field. + * @param[in] agcmemclken - The value to use for the AGCMEMCLKEN field. + * @param[in] agcclken - The value to use for the AGCCLKEN field. + * @param[in] fe3clken - The value to use for the FE3CLKEN field. + * @param[in] fe2clken - The value to use for the FE2CLKEN field. + * @param[in] fe1clken - The value to use for the FE1CLKEN field. + * @param[in] fe0clken - The value to use for the FE0CLKEN field. + * @param[in] stocpeclken - The value to use for the STOCPECLKEN field. + * @param[in] equclken - The value to use for the EQUCLKEN field. + * @param[in] tdcomp3clken - The value to use for the TDCOMP3CLKEN field. + * @param[in] tdcomp2clken - The value to use for the TDCOMP2CLKEN field. + * @param[in] tdcomp1clken - The value to use for the TDCOMP1CLKEN field. + * @param[in] tdcomp0clken - The value to use for the TDCOMP0CLKEN field. + * @param[in] tdfoestclken - The value to use for the TDFOESTCLKEN field. + * @param[in] tbeclken - The value to use for the TBECLKEN field. + * @param[in] vtbclken - The value to use for the VTBCLKEN field. + * @param[in] fft3memclken - The value to use for the FFT3MEMCLKEN field. + * @param[in] fft3clken - The value to use for the FFT3CLKEN field. + * @param[in] fft2memclken - The value to use for the FFT2MEMCLKEN field. + * @param[in] fft2clken - The value to use for the FFT2CLKEN field. + * @param[in] fft1memclken - The value to use for the FFT1MEMCLKEN field. + * @param[in] fft1clken - The value to use for the FFT1CLKEN field. + * @param[in] fft0memclken - The value to use for the FFT0MEMCLKEN field. + * @param[in] fft0clken - The value to use for the FFT0CLKEN field. + * @param[in] chestclken - The value to use for the CHESTCLKEN field. + * @param[in] gmemclken - The value to use for the GMEMCLKEN field. + * @param[in] hmemclken - The value to use for the HMEMCLKEN field. + * @param[in] qmemclken - The value to use for the QMEMCLKEN field. + * @param[in] intlvmemclken - The value to use for the INTLVMEMCLKEN field. + * @param[in] intlvvtbclken - The value to use for the INTLVVTBCLKEN field. + * @param[in] intlvphyclken - The value to use for the INTLVPHYCLKEN field. + */ +__INLINE void mdm_clkgatectrl0_pack(uint8_t phytxclken, uint8_t phyrxclken, uint8_t agcmemclken, uint8_t agcclken, uint8_t fe3clken, uint8_t fe2clken, uint8_t fe1clken, uint8_t fe0clken, uint8_t stocpeclken, uint8_t equclken, uint8_t tdcomp3clken, uint8_t tdcomp2clken, uint8_t tdcomp1clken, uint8_t tdcomp0clken, uint8_t tdfoestclken, uint8_t tbeclken, uint8_t vtbclken, uint8_t fft3memclken, uint8_t fft3clken, uint8_t fft2memclken, uint8_t fft2clken, uint8_t fft1memclken, uint8_t fft1clken, uint8_t fft0memclken, uint8_t fft0clken, uint8_t chestclken, uint8_t gmemclken, uint8_t hmemclken, uint8_t qmemclken, uint8_t intlvmemclken, uint8_t intlvvtbclken, uint8_t intlvphyclken) +{ + ASSERT_ERR((((uint32_t)phytxclken << 31) & ~((uint32_t)0x80000000)) == 0); + ASSERT_ERR((((uint32_t)phyrxclken << 30) & ~((uint32_t)0x40000000)) == 0); + ASSERT_ERR((((uint32_t)agcmemclken << 29) & ~((uint32_t)0x20000000)) == 0); + ASSERT_ERR((((uint32_t)agcclken << 28) & ~((uint32_t)0x10000000)) == 0); + ASSERT_ERR((((uint32_t)fe3clken << 27) & ~((uint32_t)0x08000000)) == 0); + ASSERT_ERR((((uint32_t)fe2clken << 26) & ~((uint32_t)0x04000000)) == 0); + ASSERT_ERR((((uint32_t)fe1clken << 25) & ~((uint32_t)0x02000000)) == 0); + ASSERT_ERR((((uint32_t)fe0clken << 24) & ~((uint32_t)0x01000000)) == 0); + ASSERT_ERR((((uint32_t)stocpeclken << 23) & ~((uint32_t)0x00800000)) == 0); + ASSERT_ERR((((uint32_t)equclken << 22) & ~((uint32_t)0x00400000)) == 0); + ASSERT_ERR((((uint32_t)tdcomp3clken << 21) & ~((uint32_t)0x00200000)) == 0); + ASSERT_ERR((((uint32_t)tdcomp2clken << 20) & ~((uint32_t)0x00100000)) == 0); + ASSERT_ERR((((uint32_t)tdcomp1clken << 19) & ~((uint32_t)0x00080000)) == 0); + ASSERT_ERR((((uint32_t)tdcomp0clken << 18) & ~((uint32_t)0x00040000)) == 0); + ASSERT_ERR((((uint32_t)tdfoestclken << 17) & ~((uint32_t)0x00020000)) == 0); + ASSERT_ERR((((uint32_t)tbeclken << 16) & ~((uint32_t)0x00010000)) == 0); + ASSERT_ERR((((uint32_t)vtbclken << 15) & ~((uint32_t)0x00008000)) == 0); + ASSERT_ERR((((uint32_t)fft3memclken << 14) & ~((uint32_t)0x00004000)) == 0); + ASSERT_ERR((((uint32_t)fft3clken << 13) & ~((uint32_t)0x00002000)) == 0); + ASSERT_ERR((((uint32_t)fft2memclken << 12) & ~((uint32_t)0x00001000)) == 0); + ASSERT_ERR((((uint32_t)fft2clken << 11) & ~((uint32_t)0x00000800)) == 0); + ASSERT_ERR((((uint32_t)fft1memclken << 10) & ~((uint32_t)0x00000400)) == 0); + ASSERT_ERR((((uint32_t)fft1clken << 9) & ~((uint32_t)0x00000200)) == 0); + ASSERT_ERR((((uint32_t)fft0memclken << 8) & ~((uint32_t)0x00000100)) == 0); + ASSERT_ERR((((uint32_t)fft0clken << 7) & ~((uint32_t)0x00000080)) == 0); + ASSERT_ERR((((uint32_t)chestclken << 6) & ~((uint32_t)0x00000040)) == 0); + ASSERT_ERR((((uint32_t)gmemclken << 5) & ~((uint32_t)0x00000020)) == 0); + ASSERT_ERR((((uint32_t)hmemclken << 4) & ~((uint32_t)0x00000010)) == 0); + ASSERT_ERR((((uint32_t)qmemclken << 3) & ~((uint32_t)0x00000008)) == 0); + ASSERT_ERR((((uint32_t)intlvmemclken << 2) & ~((uint32_t)0x00000004)) == 0); + ASSERT_ERR((((uint32_t)intlvvtbclken << 1) & ~((uint32_t)0x00000002)) == 0); + ASSERT_ERR((((uint32_t)intlvphyclken << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(MDM_CLKGATECTRL0_ADDR, ((uint32_t)phytxclken << 31) | ((uint32_t)phyrxclken << 30) | ((uint32_t)agcmemclken << 29) | ((uint32_t)agcclken << 28) | ((uint32_t)fe3clken << 27) | ((uint32_t)fe2clken << 26) | ((uint32_t)fe1clken << 25) | ((uint32_t)fe0clken << 24) | ((uint32_t)stocpeclken << 23) | ((uint32_t)equclken << 22) | ((uint32_t)tdcomp3clken << 21) | ((uint32_t)tdcomp2clken << 20) | ((uint32_t)tdcomp1clken << 19) | ((uint32_t)tdcomp0clken << 18) | ((uint32_t)tdfoestclken << 17) | ((uint32_t)tbeclken << 16) | ((uint32_t)vtbclken << 15) | ((uint32_t)fft3memclken << 14) | ((uint32_t)fft3clken << 13) | ((uint32_t)fft2memclken << 12) | ((uint32_t)fft2clken << 11) | ((uint32_t)fft1memclken << 10) | ((uint32_t)fft1clken << 9) | ((uint32_t)fft0memclken << 8) | ((uint32_t)fft0clken << 7) | ((uint32_t)chestclken << 6) | ((uint32_t)gmemclken << 5) | ((uint32_t)hmemclken << 4) | ((uint32_t)qmemclken << 3) | ((uint32_t)intlvmemclken << 2) | ((uint32_t)intlvvtbclken << 1) | ((uint32_t)intlvphyclken << 0)); +} + +/** + * @brief Unpacks CLKGATECTRL0's fields from current value of the CLKGATECTRL0 register. + * + * Reads the CLKGATECTRL0 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] phytxclken - Will be populated with the current value of this field from the register. + * @param[out] phyrxclken - Will be populated with the current value of this field from the register. + * @param[out] agcmemclken - Will be populated with the current value of this field from the register. + * @param[out] agcclken - Will be populated with the current value of this field from the register. + * @param[out] fe3clken - Will be populated with the current value of this field from the register. + * @param[out] fe2clken - Will be populated with the current value of this field from the register. + * @param[out] fe1clken - Will be populated with the current value of this field from the register. + * @param[out] fe0clken - Will be populated with the current value of this field from the register. + * @param[out] stocpeclken - Will be populated with the current value of this field from the register. + * @param[out] equclken - Will be populated with the current value of this field from the register. + * @param[out] tdcomp3clken - Will be populated with the current value of this field from the register. + * @param[out] tdcomp2clken - Will be populated with the current value of this field from the register. + * @param[out] tdcomp1clken - Will be populated with the current value of this field from the register. + * @param[out] tdcomp0clken - Will be populated with the current value of this field from the register. + * @param[out] tdfoestclken - Will be populated with the current value of this field from the register. + * @param[out] tbeclken - Will be populated with the current value of this field from the register. + * @param[out] vtbclken - Will be populated with the current value of this field from the register. + * @param[out] fft3memclken - Will be populated with the current value of this field from the register. + * @param[out] fft3clken - Will be populated with the current value of this field from the register. + * @param[out] fft2memclken - Will be populated with the current value of this field from the register. + * @param[out] fft2clken - Will be populated with the current value of this field from the register. + * @param[out] fft1memclken - Will be populated with the current value of this field from the register. + * @param[out] fft1clken - Will be populated with the current value of this field from the register. + * @param[out] fft0memclken - Will be populated with the current value of this field from the register. + * @param[out] fft0clken - Will be populated with the current value of this field from the register. + * @param[out] chestclken - Will be populated with the current value of this field from the register. + * @param[out] gmemclken - Will be populated with the current value of this field from the register. + * @param[out] hmemclken - Will be populated with the current value of this field from the register. + * @param[out] qmemclken - Will be populated with the current value of this field from the register. + * @param[out] intlvmemclken - Will be populated with the current value of this field from the register. + * @param[out] intlvvtbclken - Will be populated with the current value of this field from the register. + * @param[out] intlvphyclken - Will be populated with the current value of this field from the register. + */ +__INLINE void mdm_clkgatectrl0_unpack(uint8_t *phytxclken, uint8_t *phyrxclken, uint8_t *agcmemclken, uint8_t *agcclken, uint8_t *fe3clken, uint8_t *fe2clken, uint8_t *fe1clken, uint8_t *fe0clken, uint8_t *stocpeclken, uint8_t *equclken, uint8_t *tdcomp3clken, uint8_t *tdcomp2clken, uint8_t *tdcomp1clken, uint8_t *tdcomp0clken, uint8_t *tdfoestclken, uint8_t *tbeclken, uint8_t *vtbclken, uint8_t *fft3memclken, uint8_t *fft3clken, uint8_t *fft2memclken, uint8_t *fft2clken, uint8_t *fft1memclken, uint8_t *fft1clken, uint8_t *fft0memclken, uint8_t *fft0clken, uint8_t *chestclken, uint8_t *gmemclken, uint8_t *hmemclken, uint8_t *qmemclken, uint8_t *intlvmemclken, uint8_t *intlvvtbclken, uint8_t *intlvphyclken) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATECTRL0_ADDR); + + *phytxclken = (localVal & ((uint32_t)0x80000000)) >> 31; + *phyrxclken = (localVal & ((uint32_t)0x40000000)) >> 30; + *agcmemclken = (localVal & ((uint32_t)0x20000000)) >> 29; + *agcclken = (localVal & ((uint32_t)0x10000000)) >> 28; + *fe3clken = (localVal & ((uint32_t)0x08000000)) >> 27; + *fe2clken = (localVal & ((uint32_t)0x04000000)) >> 26; + *fe1clken = (localVal & ((uint32_t)0x02000000)) >> 25; + *fe0clken = (localVal & ((uint32_t)0x01000000)) >> 24; + *stocpeclken = (localVal & ((uint32_t)0x00800000)) >> 23; + *equclken = (localVal & ((uint32_t)0x00400000)) >> 22; + *tdcomp3clken = (localVal & ((uint32_t)0x00200000)) >> 21; + *tdcomp2clken = (localVal & ((uint32_t)0x00100000)) >> 20; + *tdcomp1clken = (localVal & ((uint32_t)0x00080000)) >> 19; + *tdcomp0clken = (localVal & ((uint32_t)0x00040000)) >> 18; + *tdfoestclken = (localVal & ((uint32_t)0x00020000)) >> 17; + *tbeclken = (localVal & ((uint32_t)0x00010000)) >> 16; + *vtbclken = (localVal & ((uint32_t)0x00008000)) >> 15; + *fft3memclken = (localVal & ((uint32_t)0x00004000)) >> 14; + *fft3clken = (localVal & ((uint32_t)0x00002000)) >> 13; + *fft2memclken = (localVal & ((uint32_t)0x00001000)) >> 12; + *fft2clken = (localVal & ((uint32_t)0x00000800)) >> 11; + *fft1memclken = (localVal & ((uint32_t)0x00000400)) >> 10; + *fft1clken = (localVal & ((uint32_t)0x00000200)) >> 9; + *fft0memclken = (localVal & ((uint32_t)0x00000100)) >> 8; + *fft0clken = (localVal & ((uint32_t)0x00000080)) >> 7; + *chestclken = (localVal & ((uint32_t)0x00000040)) >> 6; + *gmemclken = (localVal & ((uint32_t)0x00000020)) >> 5; + *hmemclken = (localVal & ((uint32_t)0x00000010)) >> 4; + *qmemclken = (localVal & ((uint32_t)0x00000008)) >> 3; + *intlvmemclken = (localVal & ((uint32_t)0x00000004)) >> 2; + *intlvvtbclken = (localVal & ((uint32_t)0x00000002)) >> 1; + *intlvphyclken = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +/** + * @brief Returns the current value of the PHYTXCLKEN field in the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read and the PHYTXCLKEN field's value will be returned. + * + * @return The current value of the PHYTXCLKEN field in the CLKGATECTRL0 register. + */ +__INLINE uint8_t mdm_phytxclken_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATECTRL0_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +/** + * @brief Sets the PHYTXCLKEN field of the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] phytxclken - The value to set the field to. + */ +__INLINE void mdm_phytxclken_setf(uint8_t phytxclken) +{ + ASSERT_ERR((((uint32_t)phytxclken << 31) & ~((uint32_t)0x80000000)) == 0); + REG_PL_WR(MDM_CLKGATECTRL0_ADDR, (REG_PL_RD(MDM_CLKGATECTRL0_ADDR) & ~((uint32_t)0x80000000)) | ((uint32_t)phytxclken << 31)); +} + +/** + * @brief Returns the current value of the PHYRXCLKEN field in the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read and the PHYRXCLKEN field's value will be returned. + * + * @return The current value of the PHYRXCLKEN field in the CLKGATECTRL0 register. + */ +__INLINE uint8_t mdm_phyrxclken_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATECTRL0_ADDR); + return ((localVal & ((uint32_t)0x40000000)) >> 30); +} + +/** + * @brief Sets the PHYRXCLKEN field of the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] phyrxclken - The value to set the field to. + */ +__INLINE void mdm_phyrxclken_setf(uint8_t phyrxclken) +{ + ASSERT_ERR((((uint32_t)phyrxclken << 30) & ~((uint32_t)0x40000000)) == 0); + REG_PL_WR(MDM_CLKGATECTRL0_ADDR, (REG_PL_RD(MDM_CLKGATECTRL0_ADDR) & ~((uint32_t)0x40000000)) | ((uint32_t)phyrxclken << 30)); +} + +/** + * @brief Returns the current value of the AGCMEMCLKEN field in the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read and the AGCMEMCLKEN field's value will be returned. + * + * @return The current value of the AGCMEMCLKEN field in the CLKGATECTRL0 register. + */ +__INLINE uint8_t mdm_agcmemclken_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATECTRL0_ADDR); + return ((localVal & ((uint32_t)0x20000000)) >> 29); +} + +/** + * @brief Sets the AGCMEMCLKEN field of the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] agcmemclken - The value to set the field to. + */ +__INLINE void mdm_agcmemclken_setf(uint8_t agcmemclken) +{ + ASSERT_ERR((((uint32_t)agcmemclken << 29) & ~((uint32_t)0x20000000)) == 0); + REG_PL_WR(MDM_CLKGATECTRL0_ADDR, (REG_PL_RD(MDM_CLKGATECTRL0_ADDR) & ~((uint32_t)0x20000000)) | ((uint32_t)agcmemclken << 29)); +} + +/** + * @brief Returns the current value of the AGCCLKEN field in the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read and the AGCCLKEN field's value will be returned. + * + * @return The current value of the AGCCLKEN field in the CLKGATECTRL0 register. + */ +__INLINE uint8_t mdm_agcclken_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATECTRL0_ADDR); + return ((localVal & ((uint32_t)0x10000000)) >> 28); +} + +/** + * @brief Sets the AGCCLKEN field of the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] agcclken - The value to set the field to. + */ +__INLINE void mdm_agcclken_setf(uint8_t agcclken) +{ + ASSERT_ERR((((uint32_t)agcclken << 28) & ~((uint32_t)0x10000000)) == 0); + REG_PL_WR(MDM_CLKGATECTRL0_ADDR, (REG_PL_RD(MDM_CLKGATECTRL0_ADDR) & ~((uint32_t)0x10000000)) | ((uint32_t)agcclken << 28)); +} + +/** + * @brief Returns the current value of the FE3CLKEN field in the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read and the FE3CLKEN field's value will be returned. + * + * @return The current value of the FE3CLKEN field in the CLKGATECTRL0 register. + */ +__INLINE uint8_t mdm_fe3clken_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATECTRL0_ADDR); + return ((localVal & ((uint32_t)0x08000000)) >> 27); +} + +/** + * @brief Sets the FE3CLKEN field of the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] fe3clken - The value to set the field to. + */ +__INLINE void mdm_fe3clken_setf(uint8_t fe3clken) +{ + ASSERT_ERR((((uint32_t)fe3clken << 27) & ~((uint32_t)0x08000000)) == 0); + REG_PL_WR(MDM_CLKGATECTRL0_ADDR, (REG_PL_RD(MDM_CLKGATECTRL0_ADDR) & ~((uint32_t)0x08000000)) | ((uint32_t)fe3clken << 27)); +} + +/** + * @brief Returns the current value of the FE2CLKEN field in the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read and the FE2CLKEN field's value will be returned. + * + * @return The current value of the FE2CLKEN field in the CLKGATECTRL0 register. + */ +__INLINE uint8_t mdm_fe2clken_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATECTRL0_ADDR); + return ((localVal & ((uint32_t)0x04000000)) >> 26); +} + +/** + * @brief Sets the FE2CLKEN field of the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] fe2clken - The value to set the field to. + */ +__INLINE void mdm_fe2clken_setf(uint8_t fe2clken) +{ + ASSERT_ERR((((uint32_t)fe2clken << 26) & ~((uint32_t)0x04000000)) == 0); + REG_PL_WR(MDM_CLKGATECTRL0_ADDR, (REG_PL_RD(MDM_CLKGATECTRL0_ADDR) & ~((uint32_t)0x04000000)) | ((uint32_t)fe2clken << 26)); +} + +/** + * @brief Returns the current value of the FE1CLKEN field in the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read and the FE1CLKEN field's value will be returned. + * + * @return The current value of the FE1CLKEN field in the CLKGATECTRL0 register. + */ +__INLINE uint8_t mdm_fe1clken_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATECTRL0_ADDR); + return ((localVal & ((uint32_t)0x02000000)) >> 25); +} + +/** + * @brief Sets the FE1CLKEN field of the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] fe1clken - The value to set the field to. + */ +__INLINE void mdm_fe1clken_setf(uint8_t fe1clken) +{ + ASSERT_ERR((((uint32_t)fe1clken << 25) & ~((uint32_t)0x02000000)) == 0); + REG_PL_WR(MDM_CLKGATECTRL0_ADDR, (REG_PL_RD(MDM_CLKGATECTRL0_ADDR) & ~((uint32_t)0x02000000)) | ((uint32_t)fe1clken << 25)); +} + +/** + * @brief Returns the current value of the FE0CLKEN field in the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read and the FE0CLKEN field's value will be returned. + * + * @return The current value of the FE0CLKEN field in the CLKGATECTRL0 register. + */ +__INLINE uint8_t mdm_fe0clken_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATECTRL0_ADDR); + return ((localVal & ((uint32_t)0x01000000)) >> 24); +} + +/** + * @brief Sets the FE0CLKEN field of the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] fe0clken - The value to set the field to. + */ +__INLINE void mdm_fe0clken_setf(uint8_t fe0clken) +{ + ASSERT_ERR((((uint32_t)fe0clken << 24) & ~((uint32_t)0x01000000)) == 0); + REG_PL_WR(MDM_CLKGATECTRL0_ADDR, (REG_PL_RD(MDM_CLKGATECTRL0_ADDR) & ~((uint32_t)0x01000000)) | ((uint32_t)fe0clken << 24)); +} + +/** + * @brief Returns the current value of the STOCPECLKEN field in the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read and the STOCPECLKEN field's value will be returned. + * + * @return The current value of the STOCPECLKEN field in the CLKGATECTRL0 register. + */ +__INLINE uint8_t mdm_stocpeclken_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATECTRL0_ADDR); + return ((localVal & ((uint32_t)0x00800000)) >> 23); +} + +/** + * @brief Sets the STOCPECLKEN field of the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] stocpeclken - The value to set the field to. + */ +__INLINE void mdm_stocpeclken_setf(uint8_t stocpeclken) +{ + ASSERT_ERR((((uint32_t)stocpeclken << 23) & ~((uint32_t)0x00800000)) == 0); + REG_PL_WR(MDM_CLKGATECTRL0_ADDR, (REG_PL_RD(MDM_CLKGATECTRL0_ADDR) & ~((uint32_t)0x00800000)) | ((uint32_t)stocpeclken << 23)); +} + +/** + * @brief Returns the current value of the EQUCLKEN field in the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read and the EQUCLKEN field's value will be returned. + * + * @return The current value of the EQUCLKEN field in the CLKGATECTRL0 register. + */ +__INLINE uint8_t mdm_equclken_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATECTRL0_ADDR); + return ((localVal & ((uint32_t)0x00400000)) >> 22); +} + +/** + * @brief Sets the EQUCLKEN field of the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] equclken - The value to set the field to. + */ +__INLINE void mdm_equclken_setf(uint8_t equclken) +{ + ASSERT_ERR((((uint32_t)equclken << 22) & ~((uint32_t)0x00400000)) == 0); + REG_PL_WR(MDM_CLKGATECTRL0_ADDR, (REG_PL_RD(MDM_CLKGATECTRL0_ADDR) & ~((uint32_t)0x00400000)) | ((uint32_t)equclken << 22)); +} + +/** + * @brief Returns the current value of the TDCOMP3CLKEN field in the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read and the TDCOMP3CLKEN field's value will be returned. + * + * @return The current value of the TDCOMP3CLKEN field in the CLKGATECTRL0 register. + */ +__INLINE uint8_t mdm_tdcomp3clken_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATECTRL0_ADDR); + return ((localVal & ((uint32_t)0x00200000)) >> 21); +} + +/** + * @brief Sets the TDCOMP3CLKEN field of the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] tdcomp3clken - The value to set the field to. + */ +__INLINE void mdm_tdcomp3clken_setf(uint8_t tdcomp3clken) +{ + ASSERT_ERR((((uint32_t)tdcomp3clken << 21) & ~((uint32_t)0x00200000)) == 0); + REG_PL_WR(MDM_CLKGATECTRL0_ADDR, (REG_PL_RD(MDM_CLKGATECTRL0_ADDR) & ~((uint32_t)0x00200000)) | ((uint32_t)tdcomp3clken << 21)); +} + +/** + * @brief Returns the current value of the TDCOMP2CLKEN field in the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read and the TDCOMP2CLKEN field's value will be returned. + * + * @return The current value of the TDCOMP2CLKEN field in the CLKGATECTRL0 register. + */ +__INLINE uint8_t mdm_tdcomp2clken_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATECTRL0_ADDR); + return ((localVal & ((uint32_t)0x00100000)) >> 20); +} + +/** + * @brief Sets the TDCOMP2CLKEN field of the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] tdcomp2clken - The value to set the field to. + */ +__INLINE void mdm_tdcomp2clken_setf(uint8_t tdcomp2clken) +{ + ASSERT_ERR((((uint32_t)tdcomp2clken << 20) & ~((uint32_t)0x00100000)) == 0); + REG_PL_WR(MDM_CLKGATECTRL0_ADDR, (REG_PL_RD(MDM_CLKGATECTRL0_ADDR) & ~((uint32_t)0x00100000)) | ((uint32_t)tdcomp2clken << 20)); +} + +/** + * @brief Returns the current value of the TDCOMP1CLKEN field in the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read and the TDCOMP1CLKEN field's value will be returned. + * + * @return The current value of the TDCOMP1CLKEN field in the CLKGATECTRL0 register. + */ +__INLINE uint8_t mdm_tdcomp1clken_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATECTRL0_ADDR); + return ((localVal & ((uint32_t)0x00080000)) >> 19); +} + +/** + * @brief Sets the TDCOMP1CLKEN field of the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] tdcomp1clken - The value to set the field to. + */ +__INLINE void mdm_tdcomp1clken_setf(uint8_t tdcomp1clken) +{ + ASSERT_ERR((((uint32_t)tdcomp1clken << 19) & ~((uint32_t)0x00080000)) == 0); + REG_PL_WR(MDM_CLKGATECTRL0_ADDR, (REG_PL_RD(MDM_CLKGATECTRL0_ADDR) & ~((uint32_t)0x00080000)) | ((uint32_t)tdcomp1clken << 19)); +} + +/** + * @brief Returns the current value of the TDCOMP0CLKEN field in the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read and the TDCOMP0CLKEN field's value will be returned. + * + * @return The current value of the TDCOMP0CLKEN field in the CLKGATECTRL0 register. + */ +__INLINE uint8_t mdm_tdcomp0clken_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATECTRL0_ADDR); + return ((localVal & ((uint32_t)0x00040000)) >> 18); +} + +/** + * @brief Sets the TDCOMP0CLKEN field of the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] tdcomp0clken - The value to set the field to. + */ +__INLINE void mdm_tdcomp0clken_setf(uint8_t tdcomp0clken) +{ + ASSERT_ERR((((uint32_t)tdcomp0clken << 18) & ~((uint32_t)0x00040000)) == 0); + REG_PL_WR(MDM_CLKGATECTRL0_ADDR, (REG_PL_RD(MDM_CLKGATECTRL0_ADDR) & ~((uint32_t)0x00040000)) | ((uint32_t)tdcomp0clken << 18)); +} + +/** + * @brief Returns the current value of the TDFOESTCLKEN field in the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read and the TDFOESTCLKEN field's value will be returned. + * + * @return The current value of the TDFOESTCLKEN field in the CLKGATECTRL0 register. + */ +__INLINE uint8_t mdm_tdfoestclken_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATECTRL0_ADDR); + return ((localVal & ((uint32_t)0x00020000)) >> 17); +} + +/** + * @brief Sets the TDFOESTCLKEN field of the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] tdfoestclken - The value to set the field to. + */ +__INLINE void mdm_tdfoestclken_setf(uint8_t tdfoestclken) +{ + ASSERT_ERR((((uint32_t)tdfoestclken << 17) & ~((uint32_t)0x00020000)) == 0); + REG_PL_WR(MDM_CLKGATECTRL0_ADDR, (REG_PL_RD(MDM_CLKGATECTRL0_ADDR) & ~((uint32_t)0x00020000)) | ((uint32_t)tdfoestclken << 17)); +} + +/** + * @brief Returns the current value of the TBECLKEN field in the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read and the TBECLKEN field's value will be returned. + * + * @return The current value of the TBECLKEN field in the CLKGATECTRL0 register. + */ +__INLINE uint8_t mdm_tbeclken_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATECTRL0_ADDR); + return ((localVal & ((uint32_t)0x00010000)) >> 16); +} + +/** + * @brief Sets the TBECLKEN field of the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] tbeclken - The value to set the field to. + */ +__INLINE void mdm_tbeclken_setf(uint8_t tbeclken) +{ + ASSERT_ERR((((uint32_t)tbeclken << 16) & ~((uint32_t)0x00010000)) == 0); + REG_PL_WR(MDM_CLKGATECTRL0_ADDR, (REG_PL_RD(MDM_CLKGATECTRL0_ADDR) & ~((uint32_t)0x00010000)) | ((uint32_t)tbeclken << 16)); +} + +/** + * @brief Returns the current value of the VTBCLKEN field in the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read and the VTBCLKEN field's value will be returned. + * + * @return The current value of the VTBCLKEN field in the CLKGATECTRL0 register. + */ +__INLINE uint8_t mdm_vtbclken_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATECTRL0_ADDR); + return ((localVal & ((uint32_t)0x00008000)) >> 15); +} + +/** + * @brief Sets the VTBCLKEN field of the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] vtbclken - The value to set the field to. + */ +__INLINE void mdm_vtbclken_setf(uint8_t vtbclken) +{ + ASSERT_ERR((((uint32_t)vtbclken << 15) & ~((uint32_t)0x00008000)) == 0); + REG_PL_WR(MDM_CLKGATECTRL0_ADDR, (REG_PL_RD(MDM_CLKGATECTRL0_ADDR) & ~((uint32_t)0x00008000)) | ((uint32_t)vtbclken << 15)); +} + +/** + * @brief Returns the current value of the FFT3MEMCLKEN field in the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read and the FFT3MEMCLKEN field's value will be returned. + * + * @return The current value of the FFT3MEMCLKEN field in the CLKGATECTRL0 register. + */ +__INLINE uint8_t mdm_fft3memclken_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATECTRL0_ADDR); + return ((localVal & ((uint32_t)0x00004000)) >> 14); +} + +/** + * @brief Sets the FFT3MEMCLKEN field of the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] fft3memclken - The value to set the field to. + */ +__INLINE void mdm_fft3memclken_setf(uint8_t fft3memclken) +{ + ASSERT_ERR((((uint32_t)fft3memclken << 14) & ~((uint32_t)0x00004000)) == 0); + REG_PL_WR(MDM_CLKGATECTRL0_ADDR, (REG_PL_RD(MDM_CLKGATECTRL0_ADDR) & ~((uint32_t)0x00004000)) | ((uint32_t)fft3memclken << 14)); +} + +/** + * @brief Returns the current value of the FFT3CLKEN field in the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read and the FFT3CLKEN field's value will be returned. + * + * @return The current value of the FFT3CLKEN field in the CLKGATECTRL0 register. + */ +__INLINE uint8_t mdm_fft3clken_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATECTRL0_ADDR); + return ((localVal & ((uint32_t)0x00002000)) >> 13); +} + +/** + * @brief Sets the FFT3CLKEN field of the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] fft3clken - The value to set the field to. + */ +__INLINE void mdm_fft3clken_setf(uint8_t fft3clken) +{ + ASSERT_ERR((((uint32_t)fft3clken << 13) & ~((uint32_t)0x00002000)) == 0); + REG_PL_WR(MDM_CLKGATECTRL0_ADDR, (REG_PL_RD(MDM_CLKGATECTRL0_ADDR) & ~((uint32_t)0x00002000)) | ((uint32_t)fft3clken << 13)); +} + +/** + * @brief Returns the current value of the FFT2MEMCLKEN field in the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read and the FFT2MEMCLKEN field's value will be returned. + * + * @return The current value of the FFT2MEMCLKEN field in the CLKGATECTRL0 register. + */ +__INLINE uint8_t mdm_fft2memclken_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATECTRL0_ADDR); + return ((localVal & ((uint32_t)0x00001000)) >> 12); +} + +/** + * @brief Sets the FFT2MEMCLKEN field of the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] fft2memclken - The value to set the field to. + */ +__INLINE void mdm_fft2memclken_setf(uint8_t fft2memclken) +{ + ASSERT_ERR((((uint32_t)fft2memclken << 12) & ~((uint32_t)0x00001000)) == 0); + REG_PL_WR(MDM_CLKGATECTRL0_ADDR, (REG_PL_RD(MDM_CLKGATECTRL0_ADDR) & ~((uint32_t)0x00001000)) | ((uint32_t)fft2memclken << 12)); +} + +/** + * @brief Returns the current value of the FFT2CLKEN field in the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read and the FFT2CLKEN field's value will be returned. + * + * @return The current value of the FFT2CLKEN field in the CLKGATECTRL0 register. + */ +__INLINE uint8_t mdm_fft2clken_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATECTRL0_ADDR); + return ((localVal & ((uint32_t)0x00000800)) >> 11); +} + +/** + * @brief Sets the FFT2CLKEN field of the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] fft2clken - The value to set the field to. + */ +__INLINE void mdm_fft2clken_setf(uint8_t fft2clken) +{ + ASSERT_ERR((((uint32_t)fft2clken << 11) & ~((uint32_t)0x00000800)) == 0); + REG_PL_WR(MDM_CLKGATECTRL0_ADDR, (REG_PL_RD(MDM_CLKGATECTRL0_ADDR) & ~((uint32_t)0x00000800)) | ((uint32_t)fft2clken << 11)); +} + +/** + * @brief Returns the current value of the FFT1MEMCLKEN field in the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read and the FFT1MEMCLKEN field's value will be returned. + * + * @return The current value of the FFT1MEMCLKEN field in the CLKGATECTRL0 register. + */ +__INLINE uint8_t mdm_fft1memclken_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATECTRL0_ADDR); + return ((localVal & ((uint32_t)0x00000400)) >> 10); +} + +/** + * @brief Sets the FFT1MEMCLKEN field of the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] fft1memclken - The value to set the field to. + */ +__INLINE void mdm_fft1memclken_setf(uint8_t fft1memclken) +{ + ASSERT_ERR((((uint32_t)fft1memclken << 10) & ~((uint32_t)0x00000400)) == 0); + REG_PL_WR(MDM_CLKGATECTRL0_ADDR, (REG_PL_RD(MDM_CLKGATECTRL0_ADDR) & ~((uint32_t)0x00000400)) | ((uint32_t)fft1memclken << 10)); +} + +/** + * @brief Returns the current value of the FFT1CLKEN field in the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read and the FFT1CLKEN field's value will be returned. + * + * @return The current value of the FFT1CLKEN field in the CLKGATECTRL0 register. + */ +__INLINE uint8_t mdm_fft1clken_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATECTRL0_ADDR); + return ((localVal & ((uint32_t)0x00000200)) >> 9); +} + +/** + * @brief Sets the FFT1CLKEN field of the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] fft1clken - The value to set the field to. + */ +__INLINE void mdm_fft1clken_setf(uint8_t fft1clken) +{ + ASSERT_ERR((((uint32_t)fft1clken << 9) & ~((uint32_t)0x00000200)) == 0); + REG_PL_WR(MDM_CLKGATECTRL0_ADDR, (REG_PL_RD(MDM_CLKGATECTRL0_ADDR) & ~((uint32_t)0x00000200)) | ((uint32_t)fft1clken << 9)); +} + +/** + * @brief Returns the current value of the FFT0MEMCLKEN field in the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read and the FFT0MEMCLKEN field's value will be returned. + * + * @return The current value of the FFT0MEMCLKEN field in the CLKGATECTRL0 register. + */ +__INLINE uint8_t mdm_fft0memclken_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATECTRL0_ADDR); + return ((localVal & ((uint32_t)0x00000100)) >> 8); +} + +/** + * @brief Sets the FFT0MEMCLKEN field of the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] fft0memclken - The value to set the field to. + */ +__INLINE void mdm_fft0memclken_setf(uint8_t fft0memclken) +{ + ASSERT_ERR((((uint32_t)fft0memclken << 8) & ~((uint32_t)0x00000100)) == 0); + REG_PL_WR(MDM_CLKGATECTRL0_ADDR, (REG_PL_RD(MDM_CLKGATECTRL0_ADDR) & ~((uint32_t)0x00000100)) | ((uint32_t)fft0memclken << 8)); +} + +/** + * @brief Returns the current value of the FFT0CLKEN field in the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read and the FFT0CLKEN field's value will be returned. + * + * @return The current value of the FFT0CLKEN field in the CLKGATECTRL0 register. + */ +__INLINE uint8_t mdm_fft0clken_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATECTRL0_ADDR); + return ((localVal & ((uint32_t)0x00000080)) >> 7); +} + +/** + * @brief Sets the FFT0CLKEN field of the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] fft0clken - The value to set the field to. + */ +__INLINE void mdm_fft0clken_setf(uint8_t fft0clken) +{ + ASSERT_ERR((((uint32_t)fft0clken << 7) & ~((uint32_t)0x00000080)) == 0); + REG_PL_WR(MDM_CLKGATECTRL0_ADDR, (REG_PL_RD(MDM_CLKGATECTRL0_ADDR) & ~((uint32_t)0x00000080)) | ((uint32_t)fft0clken << 7)); +} + +/** + * @brief Returns the current value of the CHESTCLKEN field in the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read and the CHESTCLKEN field's value will be returned. + * + * @return The current value of the CHESTCLKEN field in the CLKGATECTRL0 register. + */ +__INLINE uint8_t mdm_chestclken_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATECTRL0_ADDR); + return ((localVal & ((uint32_t)0x00000040)) >> 6); +} + +/** + * @brief Sets the CHESTCLKEN field of the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] chestclken - The value to set the field to. + */ +__INLINE void mdm_chestclken_setf(uint8_t chestclken) +{ + ASSERT_ERR((((uint32_t)chestclken << 6) & ~((uint32_t)0x00000040)) == 0); + REG_PL_WR(MDM_CLKGATECTRL0_ADDR, (REG_PL_RD(MDM_CLKGATECTRL0_ADDR) & ~((uint32_t)0x00000040)) | ((uint32_t)chestclken << 6)); +} + +/** + * @brief Returns the current value of the GMEMCLKEN field in the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read and the GMEMCLKEN field's value will be returned. + * + * @return The current value of the GMEMCLKEN field in the CLKGATECTRL0 register. + */ +__INLINE uint8_t mdm_gmemclken_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATECTRL0_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +/** + * @brief Sets the GMEMCLKEN field of the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] gmemclken - The value to set the field to. + */ +__INLINE void mdm_gmemclken_setf(uint8_t gmemclken) +{ + ASSERT_ERR((((uint32_t)gmemclken << 5) & ~((uint32_t)0x00000020)) == 0); + REG_PL_WR(MDM_CLKGATECTRL0_ADDR, (REG_PL_RD(MDM_CLKGATECTRL0_ADDR) & ~((uint32_t)0x00000020)) | ((uint32_t)gmemclken << 5)); +} + +/** + * @brief Returns the current value of the HMEMCLKEN field in the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read and the HMEMCLKEN field's value will be returned. + * + * @return The current value of the HMEMCLKEN field in the CLKGATECTRL0 register. + */ +__INLINE uint8_t mdm_hmemclken_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATECTRL0_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +/** + * @brief Sets the HMEMCLKEN field of the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] hmemclken - The value to set the field to. + */ +__INLINE void mdm_hmemclken_setf(uint8_t hmemclken) +{ + ASSERT_ERR((((uint32_t)hmemclken << 4) & ~((uint32_t)0x00000010)) == 0); + REG_PL_WR(MDM_CLKGATECTRL0_ADDR, (REG_PL_RD(MDM_CLKGATECTRL0_ADDR) & ~((uint32_t)0x00000010)) | ((uint32_t)hmemclken << 4)); +} + +/** + * @brief Returns the current value of the QMEMCLKEN field in the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read and the QMEMCLKEN field's value will be returned. + * + * @return The current value of the QMEMCLKEN field in the CLKGATECTRL0 register. + */ +__INLINE uint8_t mdm_qmemclken_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATECTRL0_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +/** + * @brief Sets the QMEMCLKEN field of the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] qmemclken - The value to set the field to. + */ +__INLINE void mdm_qmemclken_setf(uint8_t qmemclken) +{ + ASSERT_ERR((((uint32_t)qmemclken << 3) & ~((uint32_t)0x00000008)) == 0); + REG_PL_WR(MDM_CLKGATECTRL0_ADDR, (REG_PL_RD(MDM_CLKGATECTRL0_ADDR) & ~((uint32_t)0x00000008)) | ((uint32_t)qmemclken << 3)); +} + +/** + * @brief Returns the current value of the INTLVMEMCLKEN field in the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read and the INTLVMEMCLKEN field's value will be returned. + * + * @return The current value of the INTLVMEMCLKEN field in the CLKGATECTRL0 register. + */ +__INLINE uint8_t mdm_intlvmemclken_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATECTRL0_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +/** + * @brief Sets the INTLVMEMCLKEN field of the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] intlvmemclken - The value to set the field to. + */ +__INLINE void mdm_intlvmemclken_setf(uint8_t intlvmemclken) +{ + ASSERT_ERR((((uint32_t)intlvmemclken << 2) & ~((uint32_t)0x00000004)) == 0); + REG_PL_WR(MDM_CLKGATECTRL0_ADDR, (REG_PL_RD(MDM_CLKGATECTRL0_ADDR) & ~((uint32_t)0x00000004)) | ((uint32_t)intlvmemclken << 2)); +} + +/** + * @brief Returns the current value of the INTLVVTBCLKEN field in the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read and the INTLVVTBCLKEN field's value will be returned. + * + * @return The current value of the INTLVVTBCLKEN field in the CLKGATECTRL0 register. + */ +__INLINE uint8_t mdm_intlvvtbclken_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATECTRL0_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +/** + * @brief Sets the INTLVVTBCLKEN field of the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] intlvvtbclken - The value to set the field to. + */ +__INLINE void mdm_intlvvtbclken_setf(uint8_t intlvvtbclken) +{ + ASSERT_ERR((((uint32_t)intlvvtbclken << 1) & ~((uint32_t)0x00000002)) == 0); + REG_PL_WR(MDM_CLKGATECTRL0_ADDR, (REG_PL_RD(MDM_CLKGATECTRL0_ADDR) & ~((uint32_t)0x00000002)) | ((uint32_t)intlvvtbclken << 1)); +} + +/** + * @brief Returns the current value of the INTLVPHYCLKEN field in the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read and the INTLVPHYCLKEN field's value will be returned. + * + * @return The current value of the INTLVPHYCLKEN field in the CLKGATECTRL0 register. + */ +__INLINE uint8_t mdm_intlvphyclken_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATECTRL0_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/** + * @brief Sets the INTLVPHYCLKEN field of the CLKGATECTRL0 register. + * + * The CLKGATECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] intlvphyclken - The value to set the field to. + */ +__INLINE void mdm_intlvphyclken_setf(uint8_t intlvphyclken) +{ + ASSERT_ERR((((uint32_t)intlvphyclken << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(MDM_CLKGATECTRL0_ADDR, (REG_PL_RD(MDM_CLKGATECTRL0_ADDR) & ~((uint32_t)0x00000001)) | ((uint32_t)intlvphyclken << 0)); +} + +/// @} + +/** + * @name CLKGATECTRL1 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     05        RADARTIMCLKEN   1
+ *     04          MDMBTXCLKEN   1
+ *     03          MDMBRXCLKEN   1
+ * 
+ * + * @{ + */ + +/// Address of the CLKGATECTRL1 register +#define MDM_CLKGATECTRL1_ADDR 0x01000844 +/// Offset of the CLKGATECTRL1 register from the base address +#define MDM_CLKGATECTRL1_OFFSET 0x00000844 +/// Index of the CLKGATECTRL1 register +#define MDM_CLKGATECTRL1_INDEX 0x00000211 +/// Reset value of the CLKGATECTRL1 register +#define MDM_CLKGATECTRL1_RESET 0x00000038 + +/** + * @brief Returns the current value of the CLKGATECTRL1 register. + * The CLKGATECTRL1 register will be read and its value returned. + * @return The current value of the CLKGATECTRL1 register. + */ +__INLINE uint32_t mdm_clkgatectrl1_get(void) +{ + return REG_PL_RD(MDM_CLKGATECTRL1_ADDR); +} + +/** + * @brief Sets the CLKGATECTRL1 register to a value. + * The CLKGATECTRL1 register will be written. + * @param value - The value to write. + */ +__INLINE void mdm_clkgatectrl1_set(uint32_t value) +{ + REG_PL_WR(MDM_CLKGATECTRL1_ADDR, value); +} + +// field definitions +/// RADARTIMCLKEN field bit +#define MDM_RADARTIMCLKEN_BIT ((uint32_t)0x00000020) +/// RADARTIMCLKEN field position +#define MDM_RADARTIMCLKEN_POS 5 +/// MDMBTXCLKEN field bit +#define MDM_MDMBTXCLKEN_BIT ((uint32_t)0x00000010) +/// MDMBTXCLKEN field position +#define MDM_MDMBTXCLKEN_POS 4 +/// MDMBRXCLKEN field bit +#define MDM_MDMBRXCLKEN_BIT ((uint32_t)0x00000008) +/// MDMBRXCLKEN field position +#define MDM_MDMBRXCLKEN_POS 3 + +/// RADARTIMCLKEN field reset value +#define MDM_RADARTIMCLKEN_RST 0x1 +/// MDMBTXCLKEN field reset value +#define MDM_MDMBTXCLKEN_RST 0x1 +/// MDMBRXCLKEN field reset value +#define MDM_MDMBRXCLKEN_RST 0x1 + +/** + * @brief Constructs a value for the CLKGATECTRL1 register given values for its fields + * and writes the value to the register. + * + * @param[in] radartimclken - The value to use for the RADARTIMCLKEN field. + * @param[in] mdmbtxclken - The value to use for the MDMBTXCLKEN field. + * @param[in] mdmbrxclken - The value to use for the MDMBRXCLKEN field. + */ +__INLINE void mdm_clkgatectrl1_pack(uint8_t radartimclken, uint8_t mdmbtxclken, uint8_t mdmbrxclken) +{ + ASSERT_ERR((((uint32_t)radartimclken << 5) & ~((uint32_t)0x00000020)) == 0); + ASSERT_ERR((((uint32_t)mdmbtxclken << 4) & ~((uint32_t)0x00000010)) == 0); + ASSERT_ERR((((uint32_t)mdmbrxclken << 3) & ~((uint32_t)0x00000008)) == 0); + REG_PL_WR(MDM_CLKGATECTRL1_ADDR, ((uint32_t)radartimclken << 5) | ((uint32_t)mdmbtxclken << 4) | ((uint32_t)mdmbrxclken << 3)); +} + +/** + * @brief Unpacks CLKGATECTRL1's fields from current value of the CLKGATECTRL1 register. + * + * Reads the CLKGATECTRL1 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] radartimclken - Will be populated with the current value of this field from the register. + * @param[out] mdmbtxclken - Will be populated with the current value of this field from the register. + * @param[out] mdmbrxclken - Will be populated with the current value of this field from the register. + */ +__INLINE void mdm_clkgatectrl1_unpack(uint8_t *radartimclken, uint8_t *mdmbtxclken, uint8_t *mdmbrxclken) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATECTRL1_ADDR); + + *radartimclken = (localVal & ((uint32_t)0x00000020)) >> 5; + *mdmbtxclken = (localVal & ((uint32_t)0x00000010)) >> 4; + *mdmbrxclken = (localVal & ((uint32_t)0x00000008)) >> 3; +} + +/** + * @brief Returns the current value of the RADARTIMCLKEN field in the CLKGATECTRL1 register. + * + * The CLKGATECTRL1 register will be read and the RADARTIMCLKEN field's value will be returned. + * + * @return The current value of the RADARTIMCLKEN field in the CLKGATECTRL1 register. + */ +__INLINE uint8_t mdm_radartimclken_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATECTRL1_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +/** + * @brief Sets the RADARTIMCLKEN field of the CLKGATECTRL1 register. + * + * The CLKGATECTRL1 register will be read, modified to contain the new field value, and written. + * + * @param[in] radartimclken - The value to set the field to. + */ +__INLINE void mdm_radartimclken_setf(uint8_t radartimclken) +{ + ASSERT_ERR((((uint32_t)radartimclken << 5) & ~((uint32_t)0x00000020)) == 0); + REG_PL_WR(MDM_CLKGATECTRL1_ADDR, (REG_PL_RD(MDM_CLKGATECTRL1_ADDR) & ~((uint32_t)0x00000020)) | ((uint32_t)radartimclken << 5)); +} + +/** + * @brief Returns the current value of the MDMBTXCLKEN field in the CLKGATECTRL1 register. + * + * The CLKGATECTRL1 register will be read and the MDMBTXCLKEN field's value will be returned. + * + * @return The current value of the MDMBTXCLKEN field in the CLKGATECTRL1 register. + */ +__INLINE uint8_t mdm_mdmbtxclken_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATECTRL1_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +/** + * @brief Sets the MDMBTXCLKEN field of the CLKGATECTRL1 register. + * + * The CLKGATECTRL1 register will be read, modified to contain the new field value, and written. + * + * @param[in] mdmbtxclken - The value to set the field to. + */ +__INLINE void mdm_mdmbtxclken_setf(uint8_t mdmbtxclken) +{ + ASSERT_ERR((((uint32_t)mdmbtxclken << 4) & ~((uint32_t)0x00000010)) == 0); + REG_PL_WR(MDM_CLKGATECTRL1_ADDR, (REG_PL_RD(MDM_CLKGATECTRL1_ADDR) & ~((uint32_t)0x00000010)) | ((uint32_t)mdmbtxclken << 4)); +} + +/** + * @brief Returns the current value of the MDMBRXCLKEN field in the CLKGATECTRL1 register. + * + * The CLKGATECTRL1 register will be read and the MDMBRXCLKEN field's value will be returned. + * + * @return The current value of the MDMBRXCLKEN field in the CLKGATECTRL1 register. + */ +__INLINE uint8_t mdm_mdmbrxclken_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATECTRL1_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +/** + * @brief Sets the MDMBRXCLKEN field of the CLKGATECTRL1 register. + * + * The CLKGATECTRL1 register will be read, modified to contain the new field value, and written. + * + * @param[in] mdmbrxclken - The value to set the field to. + */ +__INLINE void mdm_mdmbrxclken_setf(uint8_t mdmbrxclken) +{ + ASSERT_ERR((((uint32_t)mdmbrxclken << 3) & ~((uint32_t)0x00000008)) == 0); + REG_PL_WR(MDM_CLKGATECTRL1_ADDR, (REG_PL_RD(MDM_CLKGATECTRL1_ADDR) & ~((uint32_t)0x00000008)) | ((uint32_t)mdmbrxclken << 3)); +} + +/// @} + +/** + * @name MEMCLKCTRL0 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     03        AGCMEMCLKCTRL   1
+ * 
+ * + * @{ + */ + +/// Address of the MEMCLKCTRL0 register +#define MDM_MEMCLKCTRL0_ADDR 0x01000848 +/// Offset of the MEMCLKCTRL0 register from the base address +#define MDM_MEMCLKCTRL0_OFFSET 0x00000848 +/// Index of the MEMCLKCTRL0 register +#define MDM_MEMCLKCTRL0_INDEX 0x00000212 +/// Reset value of the MEMCLKCTRL0 register +#define MDM_MEMCLKCTRL0_RESET 0x00000008 + +/** + * @brief Returns the current value of the MEMCLKCTRL0 register. + * The MEMCLKCTRL0 register will be read and its value returned. + * @return The current value of the MEMCLKCTRL0 register. + */ +__INLINE uint32_t mdm_memclkctrl0_get(void) +{ + return REG_PL_RD(MDM_MEMCLKCTRL0_ADDR); +} + +/** + * @brief Sets the MEMCLKCTRL0 register to a value. + * The MEMCLKCTRL0 register will be written. + * @param value - The value to write. + */ +__INLINE void mdm_memclkctrl0_set(uint32_t value) +{ + REG_PL_WR(MDM_MEMCLKCTRL0_ADDR, value); +} + +// field definitions +/// AGCMEMCLKCTRL field bit +#define MDM_AGCMEMCLKCTRL_BIT ((uint32_t)0x00000008) +/// AGCMEMCLKCTRL field position +#define MDM_AGCMEMCLKCTRL_POS 3 + +/// AGCMEMCLKCTRL field reset value +#define MDM_AGCMEMCLKCTRL_RST 0x1 + +/** + * @brief Returns the current value of the AGCMEMCLKCTRL field in the MEMCLKCTRL0 register. + * + * The MEMCLKCTRL0 register will be read and the AGCMEMCLKCTRL field's value will be returned. + * + * @return The current value of the AGCMEMCLKCTRL field in the MEMCLKCTRL0 register. + */ +__INLINE uint8_t mdm_agcmemclkctrl_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_MEMCLKCTRL0_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x00000008)) == 0); + return (localVal >> 3); +} + +/** + * @brief Sets the AGCMEMCLKCTRL field of the MEMCLKCTRL0 register. + * + * The MEMCLKCTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] agcmemclkctrl - The value to set the field to. + */ +__INLINE void mdm_agcmemclkctrl_setf(uint8_t agcmemclkctrl) +{ + ASSERT_ERR((((uint32_t)agcmemclkctrl << 3) & ~((uint32_t)0x00000008)) == 0); + REG_PL_WR(MDM_MEMCLKCTRL0_ADDR, (uint32_t)agcmemclkctrl << 3); +} + +/// @} + +/** + * @name IRQCTRL register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     14      IRQHTSIGVALIDEN   0
+ *     13       IRQLSIGVALIDEN   0
+ *     12      IRQTXOVERFLOWEN   0
+ *     11      IRQTXUNDERRUNEN   0
+ *     10      IRQCCA40SFALLEN   0
+ *     09      IRQCCA40SRISEEN   0
+ *     08           IRQTXENDEN   0
+ *     07           IRQRXENDEN   0
+ *     06      IRQCCA20PFALLEN   0
+ *     05      IRQCCA20SFALLEN   0
+ *     04      IRQCCA20PRISEEN   0
+ *     03      IRQCCA20SRISEEN   0
+ *     02        IRQPHYERROREN   0
+ *     01        IRQRADARDETEN   0
+ *     00      IRQCCATIMEOUTEN   0
+ * 
+ * + * @{ + */ + +/// Address of the IRQCTRL register +#define MDM_IRQCTRL_ADDR 0x0100084C +/// Offset of the IRQCTRL register from the base address +#define MDM_IRQCTRL_OFFSET 0x0000084C +/// Index of the IRQCTRL register +#define MDM_IRQCTRL_INDEX 0x00000213 +/// Reset value of the IRQCTRL register +#define MDM_IRQCTRL_RESET 0x00000000 + +/** + * @brief Returns the current value of the IRQCTRL register. + * The IRQCTRL register will be read and its value returned. + * @return The current value of the IRQCTRL register. + */ +__INLINE uint32_t mdm_irqctrl_get(void) +{ + return REG_PL_RD(MDM_IRQCTRL_ADDR); +} + +/** + * @brief Sets the IRQCTRL register to a value. + * The IRQCTRL register will be written. + * @param value - The value to write. + */ +__INLINE void mdm_irqctrl_set(uint32_t value) +{ + REG_PL_WR(MDM_IRQCTRL_ADDR, value); +} + +// field definitions +/// IRQHTSIGVALIDEN field bit +#define MDM_IRQHTSIGVALIDEN_BIT ((uint32_t)0x00004000) +/// IRQHTSIGVALIDEN field position +#define MDM_IRQHTSIGVALIDEN_POS 14 +/// IRQLSIGVALIDEN field bit +#define MDM_IRQLSIGVALIDEN_BIT ((uint32_t)0x00002000) +/// IRQLSIGVALIDEN field position +#define MDM_IRQLSIGVALIDEN_POS 13 +/// IRQTXOVERFLOWEN field bit +#define MDM_IRQTXOVERFLOWEN_BIT ((uint32_t)0x00001000) +/// IRQTXOVERFLOWEN field position +#define MDM_IRQTXOVERFLOWEN_POS 12 +/// IRQTXUNDERRUNEN field bit +#define MDM_IRQTXUNDERRUNEN_BIT ((uint32_t)0x00000800) +/// IRQTXUNDERRUNEN field position +#define MDM_IRQTXUNDERRUNEN_POS 11 +/// IRQCCA40SFALLEN field bit +#define MDM_IRQCCA40SFALLEN_BIT ((uint32_t)0x00000400) +/// IRQCCA40SFALLEN field position +#define MDM_IRQCCA40SFALLEN_POS 10 +/// IRQCCA40SRISEEN field bit +#define MDM_IRQCCA40SRISEEN_BIT ((uint32_t)0x00000200) +/// IRQCCA40SRISEEN field position +#define MDM_IRQCCA40SRISEEN_POS 9 +/// IRQTXENDEN field bit +#define MDM_IRQTXENDEN_BIT ((uint32_t)0x00000100) +/// IRQTXENDEN field position +#define MDM_IRQTXENDEN_POS 8 +/// IRQRXENDEN field bit +#define MDM_IRQRXENDEN_BIT ((uint32_t)0x00000080) +/// IRQRXENDEN field position +#define MDM_IRQRXENDEN_POS 7 +/// IRQCCA20PFALLEN field bit +#define MDM_IRQCCA20PFALLEN_BIT ((uint32_t)0x00000040) +/// IRQCCA20PFALLEN field position +#define MDM_IRQCCA20PFALLEN_POS 6 +/// IRQCCA20SFALLEN field bit +#define MDM_IRQCCA20SFALLEN_BIT ((uint32_t)0x00000020) +/// IRQCCA20SFALLEN field position +#define MDM_IRQCCA20SFALLEN_POS 5 +/// IRQCCA20PRISEEN field bit +#define MDM_IRQCCA20PRISEEN_BIT ((uint32_t)0x00000010) +/// IRQCCA20PRISEEN field position +#define MDM_IRQCCA20PRISEEN_POS 4 +/// IRQCCA20SRISEEN field bit +#define MDM_IRQCCA20SRISEEN_BIT ((uint32_t)0x00000008) +/// IRQCCA20SRISEEN field position +#define MDM_IRQCCA20SRISEEN_POS 3 +/// IRQPHYERROREN field bit +#define MDM_IRQPHYERROREN_BIT ((uint32_t)0x00000004) +/// IRQPHYERROREN field position +#define MDM_IRQPHYERROREN_POS 2 +/// IRQRADARDETEN field bit +#define MDM_IRQRADARDETEN_BIT ((uint32_t)0x00000002) +/// IRQRADARDETEN field position +#define MDM_IRQRADARDETEN_POS 1 +/// IRQCCATIMEOUTEN field bit +#define MDM_IRQCCATIMEOUTEN_BIT ((uint32_t)0x00000001) +/// IRQCCATIMEOUTEN field position +#define MDM_IRQCCATIMEOUTEN_POS 0 + +/// IRQHTSIGVALIDEN field reset value +#define MDM_IRQHTSIGVALIDEN_RST 0x0 +/// IRQLSIGVALIDEN field reset value +#define MDM_IRQLSIGVALIDEN_RST 0x0 +/// IRQTXOVERFLOWEN field reset value +#define MDM_IRQTXOVERFLOWEN_RST 0x0 +/// IRQTXUNDERRUNEN field reset value +#define MDM_IRQTXUNDERRUNEN_RST 0x0 +/// IRQCCA40SFALLEN field reset value +#define MDM_IRQCCA40SFALLEN_RST 0x0 +/// IRQCCA40SRISEEN field reset value +#define MDM_IRQCCA40SRISEEN_RST 0x0 +/// IRQTXENDEN field reset value +#define MDM_IRQTXENDEN_RST 0x0 +/// IRQRXENDEN field reset value +#define MDM_IRQRXENDEN_RST 0x0 +/// IRQCCA20PFALLEN field reset value +#define MDM_IRQCCA20PFALLEN_RST 0x0 +/// IRQCCA20SFALLEN field reset value +#define MDM_IRQCCA20SFALLEN_RST 0x0 +/// IRQCCA20PRISEEN field reset value +#define MDM_IRQCCA20PRISEEN_RST 0x0 +/// IRQCCA20SRISEEN field reset value +#define MDM_IRQCCA20SRISEEN_RST 0x0 +/// IRQPHYERROREN field reset value +#define MDM_IRQPHYERROREN_RST 0x0 +/// IRQRADARDETEN field reset value +#define MDM_IRQRADARDETEN_RST 0x0 +/// IRQCCATIMEOUTEN field reset value +#define MDM_IRQCCATIMEOUTEN_RST 0x0 + +/** + * @brief Constructs a value for the IRQCTRL register given values for its fields + * and writes the value to the register. + * + * @param[in] irqhtsigvaliden - The value to use for the IRQHTSIGVALIDEN field. + * @param[in] irqlsigvaliden - The value to use for the IRQLSIGVALIDEN field. + * @param[in] irqtxoverflowen - The value to use for the IRQTXOVERFLOWEN field. + * @param[in] irqtxunderrunen - The value to use for the IRQTXUNDERRUNEN field. + * @param[in] irqcca40sfallen - The value to use for the IRQCCA40SFALLEN field. + * @param[in] irqcca40sriseen - The value to use for the IRQCCA40SRISEEN field. + * @param[in] irqtxenden - The value to use for the IRQTXENDEN field. + * @param[in] irqrxenden - The value to use for the IRQRXENDEN field. + * @param[in] irqcca20pfallen - The value to use for the IRQCCA20PFALLEN field. + * @param[in] irqcca20sfallen - The value to use for the IRQCCA20SFALLEN field. + * @param[in] irqcca20priseen - The value to use for the IRQCCA20PRISEEN field. + * @param[in] irqcca20sriseen - The value to use for the IRQCCA20SRISEEN field. + * @param[in] irqphyerroren - The value to use for the IRQPHYERROREN field. + * @param[in] irqradardeten - The value to use for the IRQRADARDETEN field. + * @param[in] irqccatimeouten - The value to use for the IRQCCATIMEOUTEN field. + */ +__INLINE void mdm_irqctrl_pack(uint8_t irqhtsigvaliden, uint8_t irqlsigvaliden, uint8_t irqtxoverflowen, uint8_t irqtxunderrunen, uint8_t irqcca40sfallen, uint8_t irqcca40sriseen, uint8_t irqtxenden, uint8_t irqrxenden, uint8_t irqcca20pfallen, uint8_t irqcca20sfallen, uint8_t irqcca20priseen, uint8_t irqcca20sriseen, uint8_t irqphyerroren, uint8_t irqradardeten, uint8_t irqccatimeouten) +{ + ASSERT_ERR((((uint32_t)irqhtsigvaliden << 14) & ~((uint32_t)0x00004000)) == 0); + ASSERT_ERR((((uint32_t)irqlsigvaliden << 13) & ~((uint32_t)0x00002000)) == 0); + ASSERT_ERR((((uint32_t)irqtxoverflowen << 12) & ~((uint32_t)0x00001000)) == 0); + ASSERT_ERR((((uint32_t)irqtxunderrunen << 11) & ~((uint32_t)0x00000800)) == 0); + ASSERT_ERR((((uint32_t)irqcca40sfallen << 10) & ~((uint32_t)0x00000400)) == 0); + ASSERT_ERR((((uint32_t)irqcca40sriseen << 9) & ~((uint32_t)0x00000200)) == 0); + ASSERT_ERR((((uint32_t)irqtxenden << 8) & ~((uint32_t)0x00000100)) == 0); + ASSERT_ERR((((uint32_t)irqrxenden << 7) & ~((uint32_t)0x00000080)) == 0); + ASSERT_ERR((((uint32_t)irqcca20pfallen << 6) & ~((uint32_t)0x00000040)) == 0); + ASSERT_ERR((((uint32_t)irqcca20sfallen << 5) & ~((uint32_t)0x00000020)) == 0); + ASSERT_ERR((((uint32_t)irqcca20priseen << 4) & ~((uint32_t)0x00000010)) == 0); + ASSERT_ERR((((uint32_t)irqcca20sriseen << 3) & ~((uint32_t)0x00000008)) == 0); + ASSERT_ERR((((uint32_t)irqphyerroren << 2) & ~((uint32_t)0x00000004)) == 0); + ASSERT_ERR((((uint32_t)irqradardeten << 1) & ~((uint32_t)0x00000002)) == 0); + ASSERT_ERR((((uint32_t)irqccatimeouten << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(MDM_IRQCTRL_ADDR, ((uint32_t)irqhtsigvaliden << 14) | ((uint32_t)irqlsigvaliden << 13) | ((uint32_t)irqtxoverflowen << 12) | ((uint32_t)irqtxunderrunen << 11) | ((uint32_t)irqcca40sfallen << 10) | ((uint32_t)irqcca40sriseen << 9) | ((uint32_t)irqtxenden << 8) | ((uint32_t)irqrxenden << 7) | ((uint32_t)irqcca20pfallen << 6) | ((uint32_t)irqcca20sfallen << 5) | ((uint32_t)irqcca20priseen << 4) | ((uint32_t)irqcca20sriseen << 3) | ((uint32_t)irqphyerroren << 2) | ((uint32_t)irqradardeten << 1) | ((uint32_t)irqccatimeouten << 0)); +} + +/** + * @brief Unpacks IRQCTRL's fields from current value of the IRQCTRL register. + * + * Reads the IRQCTRL register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] irqhtsigvaliden - Will be populated with the current value of this field from the register. + * @param[out] irqlsigvaliden - Will be populated with the current value of this field from the register. + * @param[out] irqtxoverflowen - Will be populated with the current value of this field from the register. + * @param[out] irqtxunderrunen - Will be populated with the current value of this field from the register. + * @param[out] irqcca40sfallen - Will be populated with the current value of this field from the register. + * @param[out] irqcca40sriseen - Will be populated with the current value of this field from the register. + * @param[out] irqtxenden - Will be populated with the current value of this field from the register. + * @param[out] irqrxenden - Will be populated with the current value of this field from the register. + * @param[out] irqcca20pfallen - Will be populated with the current value of this field from the register. + * @param[out] irqcca20sfallen - Will be populated with the current value of this field from the register. + * @param[out] irqcca20priseen - Will be populated with the current value of this field from the register. + * @param[out] irqcca20sriseen - Will be populated with the current value of this field from the register. + * @param[out] irqphyerroren - Will be populated with the current value of this field from the register. + * @param[out] irqradardeten - Will be populated with the current value of this field from the register. + * @param[out] irqccatimeouten - Will be populated with the current value of this field from the register. + */ +__INLINE void mdm_irqctrl_unpack(uint8_t *irqhtsigvaliden, uint8_t *irqlsigvaliden, uint8_t *irqtxoverflowen, uint8_t *irqtxunderrunen, uint8_t *irqcca40sfallen, uint8_t *irqcca40sriseen, uint8_t *irqtxenden, uint8_t *irqrxenden, uint8_t *irqcca20pfallen, uint8_t *irqcca20sfallen, uint8_t *irqcca20priseen, uint8_t *irqcca20sriseen, uint8_t *irqphyerroren, uint8_t *irqradardeten, uint8_t *irqccatimeouten) +{ + uint32_t localVal = REG_PL_RD(MDM_IRQCTRL_ADDR); + + *irqhtsigvaliden = (localVal & ((uint32_t)0x00004000)) >> 14; + *irqlsigvaliden = (localVal & ((uint32_t)0x00002000)) >> 13; + *irqtxoverflowen = (localVal & ((uint32_t)0x00001000)) >> 12; + *irqtxunderrunen = (localVal & ((uint32_t)0x00000800)) >> 11; + *irqcca40sfallen = (localVal & ((uint32_t)0x00000400)) >> 10; + *irqcca40sriseen = (localVal & ((uint32_t)0x00000200)) >> 9; + *irqtxenden = (localVal & ((uint32_t)0x00000100)) >> 8; + *irqrxenden = (localVal & ((uint32_t)0x00000080)) >> 7; + *irqcca20pfallen = (localVal & ((uint32_t)0x00000040)) >> 6; + *irqcca20sfallen = (localVal & ((uint32_t)0x00000020)) >> 5; + *irqcca20priseen = (localVal & ((uint32_t)0x00000010)) >> 4; + *irqcca20sriseen = (localVal & ((uint32_t)0x00000008)) >> 3; + *irqphyerroren = (localVal & ((uint32_t)0x00000004)) >> 2; + *irqradardeten = (localVal & ((uint32_t)0x00000002)) >> 1; + *irqccatimeouten = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +/** + * @brief Returns the current value of the IRQHTSIGVALIDEN field in the IRQCTRL register. + * + * The IRQCTRL register will be read and the IRQHTSIGVALIDEN field's value will be returned. + * + * @return The current value of the IRQHTSIGVALIDEN field in the IRQCTRL register. + */ +__INLINE uint8_t mdm_irqhtsigvaliden_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_IRQCTRL_ADDR); + return ((localVal & ((uint32_t)0x00004000)) >> 14); +} + +/** + * @brief Sets the IRQHTSIGVALIDEN field of the IRQCTRL register. + * + * The IRQCTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] irqhtsigvaliden - The value to set the field to. + */ +__INLINE void mdm_irqhtsigvaliden_setf(uint8_t irqhtsigvaliden) +{ + ASSERT_ERR((((uint32_t)irqhtsigvaliden << 14) & ~((uint32_t)0x00004000)) == 0); + REG_PL_WR(MDM_IRQCTRL_ADDR, (REG_PL_RD(MDM_IRQCTRL_ADDR) & ~((uint32_t)0x00004000)) | ((uint32_t)irqhtsigvaliden << 14)); +} + +/** + * @brief Returns the current value of the IRQLSIGVALIDEN field in the IRQCTRL register. + * + * The IRQCTRL register will be read and the IRQLSIGVALIDEN field's value will be returned. + * + * @return The current value of the IRQLSIGVALIDEN field in the IRQCTRL register. + */ +__INLINE uint8_t mdm_irqlsigvaliden_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_IRQCTRL_ADDR); + return ((localVal & ((uint32_t)0x00002000)) >> 13); +} + +/** + * @brief Sets the IRQLSIGVALIDEN field of the IRQCTRL register. + * + * The IRQCTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] irqlsigvaliden - The value to set the field to. + */ +__INLINE void mdm_irqlsigvaliden_setf(uint8_t irqlsigvaliden) +{ + ASSERT_ERR((((uint32_t)irqlsigvaliden << 13) & ~((uint32_t)0x00002000)) == 0); + REG_PL_WR(MDM_IRQCTRL_ADDR, (REG_PL_RD(MDM_IRQCTRL_ADDR) & ~((uint32_t)0x00002000)) | ((uint32_t)irqlsigvaliden << 13)); +} + +/** + * @brief Returns the current value of the IRQTXOVERFLOWEN field in the IRQCTRL register. + * + * The IRQCTRL register will be read and the IRQTXOVERFLOWEN field's value will be returned. + * + * @return The current value of the IRQTXOVERFLOWEN field in the IRQCTRL register. + */ +__INLINE uint8_t mdm_irqtxoverflowen_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_IRQCTRL_ADDR); + return ((localVal & ((uint32_t)0x00001000)) >> 12); +} + +/** + * @brief Sets the IRQTXOVERFLOWEN field of the IRQCTRL register. + * + * The IRQCTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] irqtxoverflowen - The value to set the field to. + */ +__INLINE void mdm_irqtxoverflowen_setf(uint8_t irqtxoverflowen) +{ + ASSERT_ERR((((uint32_t)irqtxoverflowen << 12) & ~((uint32_t)0x00001000)) == 0); + REG_PL_WR(MDM_IRQCTRL_ADDR, (REG_PL_RD(MDM_IRQCTRL_ADDR) & ~((uint32_t)0x00001000)) | ((uint32_t)irqtxoverflowen << 12)); +} + +/** + * @brief Returns the current value of the IRQTXUNDERRUNEN field in the IRQCTRL register. + * + * The IRQCTRL register will be read and the IRQTXUNDERRUNEN field's value will be returned. + * + * @return The current value of the IRQTXUNDERRUNEN field in the IRQCTRL register. + */ +__INLINE uint8_t mdm_irqtxunderrunen_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_IRQCTRL_ADDR); + return ((localVal & ((uint32_t)0x00000800)) >> 11); +} + +/** + * @brief Sets the IRQTXUNDERRUNEN field of the IRQCTRL register. + * + * The IRQCTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] irqtxunderrunen - The value to set the field to. + */ +__INLINE void mdm_irqtxunderrunen_setf(uint8_t irqtxunderrunen) +{ + ASSERT_ERR((((uint32_t)irqtxunderrunen << 11) & ~((uint32_t)0x00000800)) == 0); + REG_PL_WR(MDM_IRQCTRL_ADDR, (REG_PL_RD(MDM_IRQCTRL_ADDR) & ~((uint32_t)0x00000800)) | ((uint32_t)irqtxunderrunen << 11)); +} + +/** + * @brief Returns the current value of the IRQCCA40SFALLEN field in the IRQCTRL register. + * + * The IRQCTRL register will be read and the IRQCCA40SFALLEN field's value will be returned. + * + * @return The current value of the IRQCCA40SFALLEN field in the IRQCTRL register. + */ +__INLINE uint8_t mdm_irqcca40sfallen_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_IRQCTRL_ADDR); + return ((localVal & ((uint32_t)0x00000400)) >> 10); +} + +/** + * @brief Sets the IRQCCA40SFALLEN field of the IRQCTRL register. + * + * The IRQCTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] irqcca40sfallen - The value to set the field to. + */ +__INLINE void mdm_irqcca40sfallen_setf(uint8_t irqcca40sfallen) +{ + ASSERT_ERR((((uint32_t)irqcca40sfallen << 10) & ~((uint32_t)0x00000400)) == 0); + REG_PL_WR(MDM_IRQCTRL_ADDR, (REG_PL_RD(MDM_IRQCTRL_ADDR) & ~((uint32_t)0x00000400)) | ((uint32_t)irqcca40sfallen << 10)); +} + +/** + * @brief Returns the current value of the IRQCCA40SRISEEN field in the IRQCTRL register. + * + * The IRQCTRL register will be read and the IRQCCA40SRISEEN field's value will be returned. + * + * @return The current value of the IRQCCA40SRISEEN field in the IRQCTRL register. + */ +__INLINE uint8_t mdm_irqcca40sriseen_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_IRQCTRL_ADDR); + return ((localVal & ((uint32_t)0x00000200)) >> 9); +} + +/** + * @brief Sets the IRQCCA40SRISEEN field of the IRQCTRL register. + * + * The IRQCTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] irqcca40sriseen - The value to set the field to. + */ +__INLINE void mdm_irqcca40sriseen_setf(uint8_t irqcca40sriseen) +{ + ASSERT_ERR((((uint32_t)irqcca40sriseen << 9) & ~((uint32_t)0x00000200)) == 0); + REG_PL_WR(MDM_IRQCTRL_ADDR, (REG_PL_RD(MDM_IRQCTRL_ADDR) & ~((uint32_t)0x00000200)) | ((uint32_t)irqcca40sriseen << 9)); +} + +/** + * @brief Returns the current value of the IRQTXENDEN field in the IRQCTRL register. + * + * The IRQCTRL register will be read and the IRQTXENDEN field's value will be returned. + * + * @return The current value of the IRQTXENDEN field in the IRQCTRL register. + */ +__INLINE uint8_t mdm_irqtxenden_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_IRQCTRL_ADDR); + return ((localVal & ((uint32_t)0x00000100)) >> 8); +} + +/** + * @brief Sets the IRQTXENDEN field of the IRQCTRL register. + * + * The IRQCTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] irqtxenden - The value to set the field to. + */ +__INLINE void mdm_irqtxenden_setf(uint8_t irqtxenden) +{ + ASSERT_ERR((((uint32_t)irqtxenden << 8) & ~((uint32_t)0x00000100)) == 0); + REG_PL_WR(MDM_IRQCTRL_ADDR, (REG_PL_RD(MDM_IRQCTRL_ADDR) & ~((uint32_t)0x00000100)) | ((uint32_t)irqtxenden << 8)); +} + +/** + * @brief Returns the current value of the IRQRXENDEN field in the IRQCTRL register. + * + * The IRQCTRL register will be read and the IRQRXENDEN field's value will be returned. + * + * @return The current value of the IRQRXENDEN field in the IRQCTRL register. + */ +__INLINE uint8_t mdm_irqrxenden_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_IRQCTRL_ADDR); + return ((localVal & ((uint32_t)0x00000080)) >> 7); +} + +/** + * @brief Sets the IRQRXENDEN field of the IRQCTRL register. + * + * The IRQCTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] irqrxenden - The value to set the field to. + */ +__INLINE void mdm_irqrxenden_setf(uint8_t irqrxenden) +{ + ASSERT_ERR((((uint32_t)irqrxenden << 7) & ~((uint32_t)0x00000080)) == 0); + REG_PL_WR(MDM_IRQCTRL_ADDR, (REG_PL_RD(MDM_IRQCTRL_ADDR) & ~((uint32_t)0x00000080)) | ((uint32_t)irqrxenden << 7)); +} + +/** + * @brief Returns the current value of the IRQCCA20PFALLEN field in the IRQCTRL register. + * + * The IRQCTRL register will be read and the IRQCCA20PFALLEN field's value will be returned. + * + * @return The current value of the IRQCCA20PFALLEN field in the IRQCTRL register. + */ +__INLINE uint8_t mdm_irqcca20pfallen_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_IRQCTRL_ADDR); + return ((localVal & ((uint32_t)0x00000040)) >> 6); +} + +/** + * @brief Sets the IRQCCA20PFALLEN field of the IRQCTRL register. + * + * The IRQCTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] irqcca20pfallen - The value to set the field to. + */ +__INLINE void mdm_irqcca20pfallen_setf(uint8_t irqcca20pfallen) +{ + ASSERT_ERR((((uint32_t)irqcca20pfallen << 6) & ~((uint32_t)0x00000040)) == 0); + REG_PL_WR(MDM_IRQCTRL_ADDR, (REG_PL_RD(MDM_IRQCTRL_ADDR) & ~((uint32_t)0x00000040)) | ((uint32_t)irqcca20pfallen << 6)); +} + +/** + * @brief Returns the current value of the IRQCCA20SFALLEN field in the IRQCTRL register. + * + * The IRQCTRL register will be read and the IRQCCA20SFALLEN field's value will be returned. + * + * @return The current value of the IRQCCA20SFALLEN field in the IRQCTRL register. + */ +__INLINE uint8_t mdm_irqcca20sfallen_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_IRQCTRL_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +/** + * @brief Sets the IRQCCA20SFALLEN field of the IRQCTRL register. + * + * The IRQCTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] irqcca20sfallen - The value to set the field to. + */ +__INLINE void mdm_irqcca20sfallen_setf(uint8_t irqcca20sfallen) +{ + ASSERT_ERR((((uint32_t)irqcca20sfallen << 5) & ~((uint32_t)0x00000020)) == 0); + REG_PL_WR(MDM_IRQCTRL_ADDR, (REG_PL_RD(MDM_IRQCTRL_ADDR) & ~((uint32_t)0x00000020)) | ((uint32_t)irqcca20sfallen << 5)); +} + +/** + * @brief Returns the current value of the IRQCCA20PRISEEN field in the IRQCTRL register. + * + * The IRQCTRL register will be read and the IRQCCA20PRISEEN field's value will be returned. + * + * @return The current value of the IRQCCA20PRISEEN field in the IRQCTRL register. + */ +__INLINE uint8_t mdm_irqcca20priseen_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_IRQCTRL_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +/** + * @brief Sets the IRQCCA20PRISEEN field of the IRQCTRL register. + * + * The IRQCTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] irqcca20priseen - The value to set the field to. + */ +__INLINE void mdm_irqcca20priseen_setf(uint8_t irqcca20priseen) +{ + ASSERT_ERR((((uint32_t)irqcca20priseen << 4) & ~((uint32_t)0x00000010)) == 0); + REG_PL_WR(MDM_IRQCTRL_ADDR, (REG_PL_RD(MDM_IRQCTRL_ADDR) & ~((uint32_t)0x00000010)) | ((uint32_t)irqcca20priseen << 4)); +} + +/** + * @brief Returns the current value of the IRQCCA20SRISEEN field in the IRQCTRL register. + * + * The IRQCTRL register will be read and the IRQCCA20SRISEEN field's value will be returned. + * + * @return The current value of the IRQCCA20SRISEEN field in the IRQCTRL register. + */ +__INLINE uint8_t mdm_irqcca20sriseen_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_IRQCTRL_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +/** + * @brief Sets the IRQCCA20SRISEEN field of the IRQCTRL register. + * + * The IRQCTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] irqcca20sriseen - The value to set the field to. + */ +__INLINE void mdm_irqcca20sriseen_setf(uint8_t irqcca20sriseen) +{ + ASSERT_ERR((((uint32_t)irqcca20sriseen << 3) & ~((uint32_t)0x00000008)) == 0); + REG_PL_WR(MDM_IRQCTRL_ADDR, (REG_PL_RD(MDM_IRQCTRL_ADDR) & ~((uint32_t)0x00000008)) | ((uint32_t)irqcca20sriseen << 3)); +} + +/** + * @brief Returns the current value of the IRQPHYERROREN field in the IRQCTRL register. + * + * The IRQCTRL register will be read and the IRQPHYERROREN field's value will be returned. + * + * @return The current value of the IRQPHYERROREN field in the IRQCTRL register. + */ +__INLINE uint8_t mdm_irqphyerroren_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_IRQCTRL_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +/** + * @brief Sets the IRQPHYERROREN field of the IRQCTRL register. + * + * The IRQCTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] irqphyerroren - The value to set the field to. + */ +__INLINE void mdm_irqphyerroren_setf(uint8_t irqphyerroren) +{ + ASSERT_ERR((((uint32_t)irqphyerroren << 2) & ~((uint32_t)0x00000004)) == 0); + REG_PL_WR(MDM_IRQCTRL_ADDR, (REG_PL_RD(MDM_IRQCTRL_ADDR) & ~((uint32_t)0x00000004)) | ((uint32_t)irqphyerroren << 2)); +} + +/** + * @brief Returns the current value of the IRQRADARDETEN field in the IRQCTRL register. + * + * The IRQCTRL register will be read and the IRQRADARDETEN field's value will be returned. + * + * @return The current value of the IRQRADARDETEN field in the IRQCTRL register. + */ +__INLINE uint8_t mdm_irqradardeten_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_IRQCTRL_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +/** + * @brief Sets the IRQRADARDETEN field of the IRQCTRL register. + * + * The IRQCTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] irqradardeten - The value to set the field to. + */ +__INLINE void mdm_irqradardeten_setf(uint8_t irqradardeten) +{ + ASSERT_ERR((((uint32_t)irqradardeten << 1) & ~((uint32_t)0x00000002)) == 0); + REG_PL_WR(MDM_IRQCTRL_ADDR, (REG_PL_RD(MDM_IRQCTRL_ADDR) & ~((uint32_t)0x00000002)) | ((uint32_t)irqradardeten << 1)); +} + +/** + * @brief Returns the current value of the IRQCCATIMEOUTEN field in the IRQCTRL register. + * + * The IRQCTRL register will be read and the IRQCCATIMEOUTEN field's value will be returned. + * + * @return The current value of the IRQCCATIMEOUTEN field in the IRQCTRL register. + */ +__INLINE uint8_t mdm_irqccatimeouten_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_IRQCTRL_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/** + * @brief Sets the IRQCCATIMEOUTEN field of the IRQCTRL register. + * + * The IRQCTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] irqccatimeouten - The value to set the field to. + */ +__INLINE void mdm_irqccatimeouten_setf(uint8_t irqccatimeouten) +{ + ASSERT_ERR((((uint32_t)irqccatimeouten << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(MDM_IRQCTRL_ADDR, (REG_PL_RD(MDM_IRQCTRL_ADDR) & ~((uint32_t)0x00000001)) | ((uint32_t)irqccatimeouten << 0)); +} + +/// @} + +/** + * @name IRQACK register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     14     IRQHTSIGVALIDACK   0
+ *     13      IRQLSIGVALIDACK   0
+ *     12     IRQTXOVERFLOWACK   0
+ *     11     IRQTXUNDERRUNACK   0
+ *     10     IRQCCA40SFALLACK   0
+ *     09     IRQCCA40SRISEACK   0
+ *     08          IRQTXENDACK   0
+ *     07          IRQRXENDACK   0
+ *     06     IRQCCA20PFALLACK   0
+ *     05     IRQCCA20SFALLACK   0
+ *     04     IRQCCA20PRISEACK   0
+ *     03     IRQCCA20SRISEACK   0
+ *     02       IRQPHYERRORACK   0
+ *     01       IRQRADARDETACK   0
+ *     00     IRQCCATIMEOUTACK   0
+ * 
+ * + * @{ + */ + +/// Address of the IRQACK register +#define MDM_IRQACK_ADDR 0x01000850 +/// Offset of the IRQACK register from the base address +#define MDM_IRQACK_OFFSET 0x00000850 +/// Index of the IRQACK register +#define MDM_IRQACK_INDEX 0x00000214 +/// Reset value of the IRQACK register +#define MDM_IRQACK_RESET 0x00000000 + +/** + * @brief Returns the current value of the IRQACK register. + * The IRQACK register will be read and its value returned. + * @return The current value of the IRQACK register. + */ +__INLINE uint32_t mdm_irqack_get(void) +{ + return REG_PL_RD(MDM_IRQACK_ADDR); +} + +/** + * @brief Sets the IRQACK register to a value. + * The IRQACK register will be written. + * @param value - The value to write. + */ +__INLINE void mdm_irqack_set(uint32_t value) +{ + REG_PL_WR(MDM_IRQACK_ADDR, value); +} + +// field definitions +/// IRQHTSIGVALIDACK field bit +#define MDM_IRQHTSIGVALIDACK_BIT ((uint32_t)0x00004000) +/// IRQHTSIGVALIDACK field position +#define MDM_IRQHTSIGVALIDACK_POS 14 +/// IRQLSIGVALIDACK field bit +#define MDM_IRQLSIGVALIDACK_BIT ((uint32_t)0x00002000) +/// IRQLSIGVALIDACK field position +#define MDM_IRQLSIGVALIDACK_POS 13 +/// IRQTXOVERFLOWACK field bit +#define MDM_IRQTXOVERFLOWACK_BIT ((uint32_t)0x00001000) +/// IRQTXOVERFLOWACK field position +#define MDM_IRQTXOVERFLOWACK_POS 12 +/// IRQTXUNDERRUNACK field bit +#define MDM_IRQTXUNDERRUNACK_BIT ((uint32_t)0x00000800) +/// IRQTXUNDERRUNACK field position +#define MDM_IRQTXUNDERRUNACK_POS 11 +/// IRQCCA40SFALLACK field bit +#define MDM_IRQCCA40SFALLACK_BIT ((uint32_t)0x00000400) +/// IRQCCA40SFALLACK field position +#define MDM_IRQCCA40SFALLACK_POS 10 +/// IRQCCA40SRISEACK field bit +#define MDM_IRQCCA40SRISEACK_BIT ((uint32_t)0x00000200) +/// IRQCCA40SRISEACK field position +#define MDM_IRQCCA40SRISEACK_POS 9 +/// IRQTXENDACK field bit +#define MDM_IRQTXENDACK_BIT ((uint32_t)0x00000100) +/// IRQTXENDACK field position +#define MDM_IRQTXENDACK_POS 8 +/// IRQRXENDACK field bit +#define MDM_IRQRXENDACK_BIT ((uint32_t)0x00000080) +/// IRQRXENDACK field position +#define MDM_IRQRXENDACK_POS 7 +/// IRQCCA20PFALLACK field bit +#define MDM_IRQCCA20PFALLACK_BIT ((uint32_t)0x00000040) +/// IRQCCA20PFALLACK field position +#define MDM_IRQCCA20PFALLACK_POS 6 +/// IRQCCA20SFALLACK field bit +#define MDM_IRQCCA20SFALLACK_BIT ((uint32_t)0x00000020) +/// IRQCCA20SFALLACK field position +#define MDM_IRQCCA20SFALLACK_POS 5 +/// IRQCCA20PRISEACK field bit +#define MDM_IRQCCA20PRISEACK_BIT ((uint32_t)0x00000010) +/// IRQCCA20PRISEACK field position +#define MDM_IRQCCA20PRISEACK_POS 4 +/// IRQCCA20SRISEACK field bit +#define MDM_IRQCCA20SRISEACK_BIT ((uint32_t)0x00000008) +/// IRQCCA20SRISEACK field position +#define MDM_IRQCCA20SRISEACK_POS 3 +/// IRQPHYERRORACK field bit +#define MDM_IRQPHYERRORACK_BIT ((uint32_t)0x00000004) +/// IRQPHYERRORACK field position +#define MDM_IRQPHYERRORACK_POS 2 +/// IRQRADARDETACK field bit +#define MDM_IRQRADARDETACK_BIT ((uint32_t)0x00000002) +/// IRQRADARDETACK field position +#define MDM_IRQRADARDETACK_POS 1 +/// IRQCCATIMEOUTACK field bit +#define MDM_IRQCCATIMEOUTACK_BIT ((uint32_t)0x00000001) +/// IRQCCATIMEOUTACK field position +#define MDM_IRQCCATIMEOUTACK_POS 0 + +/// IRQHTSIGVALIDACK field reset value +#define MDM_IRQHTSIGVALIDACK_RST 0x0 +/// IRQLSIGVALIDACK field reset value +#define MDM_IRQLSIGVALIDACK_RST 0x0 +/// IRQTXOVERFLOWACK field reset value +#define MDM_IRQTXOVERFLOWACK_RST 0x0 +/// IRQTXUNDERRUNACK field reset value +#define MDM_IRQTXUNDERRUNACK_RST 0x0 +/// IRQCCA40SFALLACK field reset value +#define MDM_IRQCCA40SFALLACK_RST 0x0 +/// IRQCCA40SRISEACK field reset value +#define MDM_IRQCCA40SRISEACK_RST 0x0 +/// IRQTXENDACK field reset value +#define MDM_IRQTXENDACK_RST 0x0 +/// IRQRXENDACK field reset value +#define MDM_IRQRXENDACK_RST 0x0 +/// IRQCCA20PFALLACK field reset value +#define MDM_IRQCCA20PFALLACK_RST 0x0 +/// IRQCCA20SFALLACK field reset value +#define MDM_IRQCCA20SFALLACK_RST 0x0 +/// IRQCCA20PRISEACK field reset value +#define MDM_IRQCCA20PRISEACK_RST 0x0 +/// IRQCCA20SRISEACK field reset value +#define MDM_IRQCCA20SRISEACK_RST 0x0 +/// IRQPHYERRORACK field reset value +#define MDM_IRQPHYERRORACK_RST 0x0 +/// IRQRADARDETACK field reset value +#define MDM_IRQRADARDETACK_RST 0x0 +/// IRQCCATIMEOUTACK field reset value +#define MDM_IRQCCATIMEOUTACK_RST 0x0 + +/** + * @brief Constructs a value for the IRQACK register given values for its fields + * and writes the value to the register. + * + * @param[in] irqhtsigvalidack - The value to use for the IRQHTSIGVALIDACK field. + * @param[in] irqlsigvalidack - The value to use for the IRQLSIGVALIDACK field. + * @param[in] irqtxoverflowack - The value to use for the IRQTXOVERFLOWACK field. + * @param[in] irqtxunderrunack - The value to use for the IRQTXUNDERRUNACK field. + * @param[in] irqcca40sfallack - The value to use for the IRQCCA40SFALLACK field. + * @param[in] irqcca40sriseack - The value to use for the IRQCCA40SRISEACK field. + * @param[in] irqtxendack - The value to use for the IRQTXENDACK field. + * @param[in] irqrxendack - The value to use for the IRQRXENDACK field. + * @param[in] irqcca20pfallack - The value to use for the IRQCCA20PFALLACK field. + * @param[in] irqcca20sfallack - The value to use for the IRQCCA20SFALLACK field. + * @param[in] irqcca20priseack - The value to use for the IRQCCA20PRISEACK field. + * @param[in] irqcca20sriseack - The value to use for the IRQCCA20SRISEACK field. + * @param[in] irqphyerrorack - The value to use for the IRQPHYERRORACK field. + * @param[in] irqradardetack - The value to use for the IRQRADARDETACK field. + * @param[in] irqccatimeoutack - The value to use for the IRQCCATIMEOUTACK field. + */ +__INLINE void mdm_irqack_pack(uint8_t irqhtsigvalidack, uint8_t irqlsigvalidack, uint8_t irqtxoverflowack, uint8_t irqtxunderrunack, uint8_t irqcca40sfallack, uint8_t irqcca40sriseack, uint8_t irqtxendack, uint8_t irqrxendack, uint8_t irqcca20pfallack, uint8_t irqcca20sfallack, uint8_t irqcca20priseack, uint8_t irqcca20sriseack, uint8_t irqphyerrorack, uint8_t irqradardetack, uint8_t irqccatimeoutack) +{ + ASSERT_ERR((((uint32_t)irqhtsigvalidack << 14) & ~((uint32_t)0x00004000)) == 0); + ASSERT_ERR((((uint32_t)irqlsigvalidack << 13) & ~((uint32_t)0x00002000)) == 0); + ASSERT_ERR((((uint32_t)irqtxoverflowack << 12) & ~((uint32_t)0x00001000)) == 0); + ASSERT_ERR((((uint32_t)irqtxunderrunack << 11) & ~((uint32_t)0x00000800)) == 0); + ASSERT_ERR((((uint32_t)irqcca40sfallack << 10) & ~((uint32_t)0x00000400)) == 0); + ASSERT_ERR((((uint32_t)irqcca40sriseack << 9) & ~((uint32_t)0x00000200)) == 0); + ASSERT_ERR((((uint32_t)irqtxendack << 8) & ~((uint32_t)0x00000100)) == 0); + ASSERT_ERR((((uint32_t)irqrxendack << 7) & ~((uint32_t)0x00000080)) == 0); + ASSERT_ERR((((uint32_t)irqcca20pfallack << 6) & ~((uint32_t)0x00000040)) == 0); + ASSERT_ERR((((uint32_t)irqcca20sfallack << 5) & ~((uint32_t)0x00000020)) == 0); + ASSERT_ERR((((uint32_t)irqcca20priseack << 4) & ~((uint32_t)0x00000010)) == 0); + ASSERT_ERR((((uint32_t)irqcca20sriseack << 3) & ~((uint32_t)0x00000008)) == 0); + ASSERT_ERR((((uint32_t)irqphyerrorack << 2) & ~((uint32_t)0x00000004)) == 0); + ASSERT_ERR((((uint32_t)irqradardetack << 1) & ~((uint32_t)0x00000002)) == 0); + ASSERT_ERR((((uint32_t)irqccatimeoutack << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(MDM_IRQACK_ADDR, ((uint32_t)irqhtsigvalidack << 14) | ((uint32_t)irqlsigvalidack << 13) | ((uint32_t)irqtxoverflowack << 12) | ((uint32_t)irqtxunderrunack << 11) | ((uint32_t)irqcca40sfallack << 10) | ((uint32_t)irqcca40sriseack << 9) | ((uint32_t)irqtxendack << 8) | ((uint32_t)irqrxendack << 7) | ((uint32_t)irqcca20pfallack << 6) | ((uint32_t)irqcca20sfallack << 5) | ((uint32_t)irqcca20priseack << 4) | ((uint32_t)irqcca20sriseack << 3) | ((uint32_t)irqphyerrorack << 2) | ((uint32_t)irqradardetack << 1) | ((uint32_t)irqccatimeoutack << 0)); +} + +/** + * @brief Unpacks IRQACK's fields from current value of the IRQACK register. + * + * Reads the IRQACK register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] irqhtsigvalidack - Will be populated with the current value of this field from the register. + * @param[out] irqlsigvalidack - Will be populated with the current value of this field from the register. + * @param[out] irqtxoverflowack - Will be populated with the current value of this field from the register. + * @param[out] irqtxunderrunack - Will be populated with the current value of this field from the register. + * @param[out] irqcca40sfallack - Will be populated with the current value of this field from the register. + * @param[out] irqcca40sriseack - Will be populated with the current value of this field from the register. + * @param[out] irqtxendack - Will be populated with the current value of this field from the register. + * @param[out] irqrxendack - Will be populated with the current value of this field from the register. + * @param[out] irqcca20pfallack - Will be populated with the current value of this field from the register. + * @param[out] irqcca20sfallack - Will be populated with the current value of this field from the register. + * @param[out] irqcca20priseack - Will be populated with the current value of this field from the register. + * @param[out] irqcca20sriseack - Will be populated with the current value of this field from the register. + * @param[out] irqphyerrorack - Will be populated with the current value of this field from the register. + * @param[out] irqradardetack - Will be populated with the current value of this field from the register. + * @param[out] irqccatimeoutack - Will be populated with the current value of this field from the register. + */ +__INLINE void mdm_irqack_unpack(uint8_t *irqhtsigvalidack, uint8_t *irqlsigvalidack, uint8_t *irqtxoverflowack, uint8_t *irqtxunderrunack, uint8_t *irqcca40sfallack, uint8_t *irqcca40sriseack, uint8_t *irqtxendack, uint8_t *irqrxendack, uint8_t *irqcca20pfallack, uint8_t *irqcca20sfallack, uint8_t *irqcca20priseack, uint8_t *irqcca20sriseack, uint8_t *irqphyerrorack, uint8_t *irqradardetack, uint8_t *irqccatimeoutack) +{ + uint32_t localVal = REG_PL_RD(MDM_IRQACK_ADDR); + + *irqhtsigvalidack = (localVal & ((uint32_t)0x00004000)) >> 14; + *irqlsigvalidack = (localVal & ((uint32_t)0x00002000)) >> 13; + *irqtxoverflowack = (localVal & ((uint32_t)0x00001000)) >> 12; + *irqtxunderrunack = (localVal & ((uint32_t)0x00000800)) >> 11; + *irqcca40sfallack = (localVal & ((uint32_t)0x00000400)) >> 10; + *irqcca40sriseack = (localVal & ((uint32_t)0x00000200)) >> 9; + *irqtxendack = (localVal & ((uint32_t)0x00000100)) >> 8; + *irqrxendack = (localVal & ((uint32_t)0x00000080)) >> 7; + *irqcca20pfallack = (localVal & ((uint32_t)0x00000040)) >> 6; + *irqcca20sfallack = (localVal & ((uint32_t)0x00000020)) >> 5; + *irqcca20priseack = (localVal & ((uint32_t)0x00000010)) >> 4; + *irqcca20sriseack = (localVal & ((uint32_t)0x00000008)) >> 3; + *irqphyerrorack = (localVal & ((uint32_t)0x00000004)) >> 2; + *irqradardetack = (localVal & ((uint32_t)0x00000002)) >> 1; + *irqccatimeoutack = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +/** + * @brief Returns the current value of the IRQHTSIGVALIDACK field in the IRQACK register. + * + * The IRQACK register will be read and the IRQHTSIGVALIDACK field's value will be returned. + * + * @return The current value of the IRQHTSIGVALIDACK field in the IRQACK register. + */ +__INLINE uint8_t mdm_irqhtsigvalidack_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_IRQACK_ADDR); + return ((localVal & ((uint32_t)0x00004000)) >> 14); +} + +/** + * @brief Sets the IRQHTSIGVALIDACK field of the IRQACK register. + * + * The IRQACK register will be read, modified to contain the new field value, and written. + * + * @param[in] irqhtsigvalidack - The value to set the field to. + */ +__INLINE void mdm_irqhtsigvalidack_setf(uint8_t irqhtsigvalidack) +{ + ASSERT_ERR((((uint32_t)irqhtsigvalidack << 14) & ~((uint32_t)0x00004000)) == 0); + REG_PL_WR(MDM_IRQACK_ADDR, (uint32_t)irqhtsigvalidack << 14); +} + +/** + * @brief Returns the current value of the IRQLSIGVALIDACK field in the IRQACK register. + * + * The IRQACK register will be read and the IRQLSIGVALIDACK field's value will be returned. + * + * @return The current value of the IRQLSIGVALIDACK field in the IRQACK register. + */ +__INLINE uint8_t mdm_irqlsigvalidack_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_IRQACK_ADDR); + return ((localVal & ((uint32_t)0x00002000)) >> 13); +} + +/** + * @brief Sets the IRQLSIGVALIDACK field of the IRQACK register. + * + * The IRQACK register will be read, modified to contain the new field value, and written. + * + * @param[in] irqlsigvalidack - The value to set the field to. + */ +__INLINE void mdm_irqlsigvalidack_setf(uint8_t irqlsigvalidack) +{ + ASSERT_ERR((((uint32_t)irqlsigvalidack << 13) & ~((uint32_t)0x00002000)) == 0); + REG_PL_WR(MDM_IRQACK_ADDR, (uint32_t)irqlsigvalidack << 13); +} + +/** + * @brief Returns the current value of the IRQTXOVERFLOWACK field in the IRQACK register. + * + * The IRQACK register will be read and the IRQTXOVERFLOWACK field's value will be returned. + * + * @return The current value of the IRQTXOVERFLOWACK field in the IRQACK register. + */ +__INLINE uint8_t mdm_irqtxoverflowack_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_IRQACK_ADDR); + return ((localVal & ((uint32_t)0x00001000)) >> 12); +} + +/** + * @brief Sets the IRQTXOVERFLOWACK field of the IRQACK register. + * + * The IRQACK register will be read, modified to contain the new field value, and written. + * + * @param[in] irqtxoverflowack - The value to set the field to. + */ +__INLINE void mdm_irqtxoverflowack_setf(uint8_t irqtxoverflowack) +{ + ASSERT_ERR((((uint32_t)irqtxoverflowack << 12) & ~((uint32_t)0x00001000)) == 0); + REG_PL_WR(MDM_IRQACK_ADDR, (uint32_t)irqtxoverflowack << 12); +} + +/** + * @brief Returns the current value of the IRQTXUNDERRUNACK field in the IRQACK register. + * + * The IRQACK register will be read and the IRQTXUNDERRUNACK field's value will be returned. + * + * @return The current value of the IRQTXUNDERRUNACK field in the IRQACK register. + */ +__INLINE uint8_t mdm_irqtxunderrunack_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_IRQACK_ADDR); + return ((localVal & ((uint32_t)0x00000800)) >> 11); +} + +/** + * @brief Sets the IRQTXUNDERRUNACK field of the IRQACK register. + * + * The IRQACK register will be read, modified to contain the new field value, and written. + * + * @param[in] irqtxunderrunack - The value to set the field to. + */ +__INLINE void mdm_irqtxunderrunack_setf(uint8_t irqtxunderrunack) +{ + ASSERT_ERR((((uint32_t)irqtxunderrunack << 11) & ~((uint32_t)0x00000800)) == 0); + REG_PL_WR(MDM_IRQACK_ADDR, (uint32_t)irqtxunderrunack << 11); +} + +/** + * @brief Returns the current value of the IRQCCA40SFALLACK field in the IRQACK register. + * + * The IRQACK register will be read and the IRQCCA40SFALLACK field's value will be returned. + * + * @return The current value of the IRQCCA40SFALLACK field in the IRQACK register. + */ +__INLINE uint8_t mdm_irqcca40sfallack_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_IRQACK_ADDR); + return ((localVal & ((uint32_t)0x00000400)) >> 10); +} + +/** + * @brief Sets the IRQCCA40SFALLACK field of the IRQACK register. + * + * The IRQACK register will be read, modified to contain the new field value, and written. + * + * @param[in] irqcca40sfallack - The value to set the field to. + */ +__INLINE void mdm_irqcca40sfallack_setf(uint8_t irqcca40sfallack) +{ + ASSERT_ERR((((uint32_t)irqcca40sfallack << 10) & ~((uint32_t)0x00000400)) == 0); + REG_PL_WR(MDM_IRQACK_ADDR, (uint32_t)irqcca40sfallack << 10); +} + +/** + * @brief Returns the current value of the IRQCCA40SRISEACK field in the IRQACK register. + * + * The IRQACK register will be read and the IRQCCA40SRISEACK field's value will be returned. + * + * @return The current value of the IRQCCA40SRISEACK field in the IRQACK register. + */ +__INLINE uint8_t mdm_irqcca40sriseack_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_IRQACK_ADDR); + return ((localVal & ((uint32_t)0x00000200)) >> 9); +} + +/** + * @brief Sets the IRQCCA40SRISEACK field of the IRQACK register. + * + * The IRQACK register will be read, modified to contain the new field value, and written. + * + * @param[in] irqcca40sriseack - The value to set the field to. + */ +__INLINE void mdm_irqcca40sriseack_setf(uint8_t irqcca40sriseack) +{ + ASSERT_ERR((((uint32_t)irqcca40sriseack << 9) & ~((uint32_t)0x00000200)) == 0); + REG_PL_WR(MDM_IRQACK_ADDR, (uint32_t)irqcca40sriseack << 9); +} + +/** + * @brief Returns the current value of the IRQTXENDACK field in the IRQACK register. + * + * The IRQACK register will be read and the IRQTXENDACK field's value will be returned. + * + * @return The current value of the IRQTXENDACK field in the IRQACK register. + */ +__INLINE uint8_t mdm_irqtxendack_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_IRQACK_ADDR); + return ((localVal & ((uint32_t)0x00000100)) >> 8); +} + +/** + * @brief Sets the IRQTXENDACK field of the IRQACK register. + * + * The IRQACK register will be read, modified to contain the new field value, and written. + * + * @param[in] irqtxendack - The value to set the field to. + */ +__INLINE void mdm_irqtxendack_setf(uint8_t irqtxendack) +{ + ASSERT_ERR((((uint32_t)irqtxendack << 8) & ~((uint32_t)0x00000100)) == 0); + REG_PL_WR(MDM_IRQACK_ADDR, (uint32_t)irqtxendack << 8); +} + +/** + * @brief Returns the current value of the IRQRXENDACK field in the IRQACK register. + * + * The IRQACK register will be read and the IRQRXENDACK field's value will be returned. + * + * @return The current value of the IRQRXENDACK field in the IRQACK register. + */ +__INLINE uint8_t mdm_irqrxendack_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_IRQACK_ADDR); + return ((localVal & ((uint32_t)0x00000080)) >> 7); +} + +/** + * @brief Sets the IRQRXENDACK field of the IRQACK register. + * + * The IRQACK register will be read, modified to contain the new field value, and written. + * + * @param[in] irqrxendack - The value to set the field to. + */ +__INLINE void mdm_irqrxendack_setf(uint8_t irqrxendack) +{ + ASSERT_ERR((((uint32_t)irqrxendack << 7) & ~((uint32_t)0x00000080)) == 0); + REG_PL_WR(MDM_IRQACK_ADDR, (uint32_t)irqrxendack << 7); +} + +/** + * @brief Returns the current value of the IRQCCA20PFALLACK field in the IRQACK register. + * + * The IRQACK register will be read and the IRQCCA20PFALLACK field's value will be returned. + * + * @return The current value of the IRQCCA20PFALLACK field in the IRQACK register. + */ +__INLINE uint8_t mdm_irqcca20pfallack_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_IRQACK_ADDR); + return ((localVal & ((uint32_t)0x00000040)) >> 6); +} + +/** + * @brief Sets the IRQCCA20PFALLACK field of the IRQACK register. + * + * The IRQACK register will be read, modified to contain the new field value, and written. + * + * @param[in] irqcca20pfallack - The value to set the field to. + */ +__INLINE void mdm_irqcca20pfallack_setf(uint8_t irqcca20pfallack) +{ + ASSERT_ERR((((uint32_t)irqcca20pfallack << 6) & ~((uint32_t)0x00000040)) == 0); + REG_PL_WR(MDM_IRQACK_ADDR, (uint32_t)irqcca20pfallack << 6); +} + +/** + * @brief Returns the current value of the IRQCCA20SFALLACK field in the IRQACK register. + * + * The IRQACK register will be read and the IRQCCA20SFALLACK field's value will be returned. + * + * @return The current value of the IRQCCA20SFALLACK field in the IRQACK register. + */ +__INLINE uint8_t mdm_irqcca20sfallack_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_IRQACK_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +/** + * @brief Sets the IRQCCA20SFALLACK field of the IRQACK register. + * + * The IRQACK register will be read, modified to contain the new field value, and written. + * + * @param[in] irqcca20sfallack - The value to set the field to. + */ +__INLINE void mdm_irqcca20sfallack_setf(uint8_t irqcca20sfallack) +{ + ASSERT_ERR((((uint32_t)irqcca20sfallack << 5) & ~((uint32_t)0x00000020)) == 0); + REG_PL_WR(MDM_IRQACK_ADDR, (uint32_t)irqcca20sfallack << 5); +} + +/** + * @brief Returns the current value of the IRQCCA20PRISEACK field in the IRQACK register. + * + * The IRQACK register will be read and the IRQCCA20PRISEACK field's value will be returned. + * + * @return The current value of the IRQCCA20PRISEACK field in the IRQACK register. + */ +__INLINE uint8_t mdm_irqcca20priseack_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_IRQACK_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +/** + * @brief Sets the IRQCCA20PRISEACK field of the IRQACK register. + * + * The IRQACK register will be read, modified to contain the new field value, and written. + * + * @param[in] irqcca20priseack - The value to set the field to. + */ +__INLINE void mdm_irqcca20priseack_setf(uint8_t irqcca20priseack) +{ + ASSERT_ERR((((uint32_t)irqcca20priseack << 4) & ~((uint32_t)0x00000010)) == 0); + REG_PL_WR(MDM_IRQACK_ADDR, (uint32_t)irqcca20priseack << 4); +} + +/** + * @brief Returns the current value of the IRQCCA20SRISEACK field in the IRQACK register. + * + * The IRQACK register will be read and the IRQCCA20SRISEACK field's value will be returned. + * + * @return The current value of the IRQCCA20SRISEACK field in the IRQACK register. + */ +__INLINE uint8_t mdm_irqcca20sriseack_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_IRQACK_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +/** + * @brief Sets the IRQCCA20SRISEACK field of the IRQACK register. + * + * The IRQACK register will be read, modified to contain the new field value, and written. + * + * @param[in] irqcca20sriseack - The value to set the field to. + */ +__INLINE void mdm_irqcca20sriseack_setf(uint8_t irqcca20sriseack) +{ + ASSERT_ERR((((uint32_t)irqcca20sriseack << 3) & ~((uint32_t)0x00000008)) == 0); + REG_PL_WR(MDM_IRQACK_ADDR, (uint32_t)irqcca20sriseack << 3); +} + +/** + * @brief Returns the current value of the IRQPHYERRORACK field in the IRQACK register. + * + * The IRQACK register will be read and the IRQPHYERRORACK field's value will be returned. + * + * @return The current value of the IRQPHYERRORACK field in the IRQACK register. + */ +__INLINE uint8_t mdm_irqphyerrorack_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_IRQACK_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +/** + * @brief Sets the IRQPHYERRORACK field of the IRQACK register. + * + * The IRQACK register will be read, modified to contain the new field value, and written. + * + * @param[in] irqphyerrorack - The value to set the field to. + */ +__INLINE void mdm_irqphyerrorack_setf(uint8_t irqphyerrorack) +{ + ASSERT_ERR((((uint32_t)irqphyerrorack << 2) & ~((uint32_t)0x00000004)) == 0); + REG_PL_WR(MDM_IRQACK_ADDR, (uint32_t)irqphyerrorack << 2); +} + +/** + * @brief Returns the current value of the IRQRADARDETACK field in the IRQACK register. + * + * The IRQACK register will be read and the IRQRADARDETACK field's value will be returned. + * + * @return The current value of the IRQRADARDETACK field in the IRQACK register. + */ +__INLINE uint8_t mdm_irqradardetack_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_IRQACK_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +/** + * @brief Sets the IRQRADARDETACK field of the IRQACK register. + * + * The IRQACK register will be read, modified to contain the new field value, and written. + * + * @param[in] irqradardetack - The value to set the field to. + */ +__INLINE void mdm_irqradardetack_setf(uint8_t irqradardetack) +{ + ASSERT_ERR((((uint32_t)irqradardetack << 1) & ~((uint32_t)0x00000002)) == 0); + REG_PL_WR(MDM_IRQACK_ADDR, (uint32_t)irqradardetack << 1); +} + +/** + * @brief Returns the current value of the IRQCCATIMEOUTACK field in the IRQACK register. + * + * The IRQACK register will be read and the IRQCCATIMEOUTACK field's value will be returned. + * + * @return The current value of the IRQCCATIMEOUTACK field in the IRQACK register. + */ +__INLINE uint8_t mdm_irqccatimeoutack_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_IRQACK_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/** + * @brief Sets the IRQCCATIMEOUTACK field of the IRQACK register. + * + * The IRQACK register will be read, modified to contain the new field value, and written. + * + * @param[in] irqccatimeoutack - The value to set the field to. + */ +__INLINE void mdm_irqccatimeoutack_setf(uint8_t irqccatimeoutack) +{ + ASSERT_ERR((((uint32_t)irqccatimeoutack << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(MDM_IRQACK_ADDR, (uint32_t)irqccatimeoutack << 0); +} + +/// @} + +/** + * @name TDCYCLSHTRL0 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  11:08             LTDCYCL4   0x3
+ *  07:04             LTDCYCL3   0x2
+ *  03:00             LTDCYCL2   0x1
+ * 
+ * + * @{ + */ + +/// Address of the TDCYCLSHTRL0 register +#define MDM_TDCYCLSHTRL0_ADDR 0x01000854 +/// Offset of the TDCYCLSHTRL0 register from the base address +#define MDM_TDCYCLSHTRL0_OFFSET 0x00000854 +/// Index of the TDCYCLSHTRL0 register +#define MDM_TDCYCLSHTRL0_INDEX 0x00000215 +/// Reset value of the TDCYCLSHTRL0 register +#define MDM_TDCYCLSHTRL0_RESET 0x00000321 + +/** + * @brief Returns the current value of the TDCYCLSHTRL0 register. + * The TDCYCLSHTRL0 register will be read and its value returned. + * @return The current value of the TDCYCLSHTRL0 register. + */ +__INLINE uint32_t mdm_tdcyclshtrl0_get(void) +{ + return REG_PL_RD(MDM_TDCYCLSHTRL0_ADDR); +} + +/** + * @brief Sets the TDCYCLSHTRL0 register to a value. + * The TDCYCLSHTRL0 register will be written. + * @param value - The value to write. + */ +__INLINE void mdm_tdcyclshtrl0_set(uint32_t value) +{ + REG_PL_WR(MDM_TDCYCLSHTRL0_ADDR, value); +} + +// field definitions +/// LTDCYCL4 field mask +#define MDM_LTDCYCL4_MASK ((uint32_t)0x00000F00) +/// LTDCYCL4 field LSB position +#define MDM_LTDCYCL4_LSB 8 +/// LTDCYCL4 field width +#define MDM_LTDCYCL4_WIDTH ((uint32_t)0x00000004) +/// LTDCYCL3 field mask +#define MDM_LTDCYCL3_MASK ((uint32_t)0x000000F0) +/// LTDCYCL3 field LSB position +#define MDM_LTDCYCL3_LSB 4 +/// LTDCYCL3 field width +#define MDM_LTDCYCL3_WIDTH ((uint32_t)0x00000004) +/// LTDCYCL2 field mask +#define MDM_LTDCYCL2_MASK ((uint32_t)0x0000000F) +/// LTDCYCL2 field LSB position +#define MDM_LTDCYCL2_LSB 0 +/// LTDCYCL2 field width +#define MDM_LTDCYCL2_WIDTH ((uint32_t)0x00000004) + +/// LTDCYCL4 field reset value +#define MDM_LTDCYCL4_RST 0x3 +/// LTDCYCL3 field reset value +#define MDM_LTDCYCL3_RST 0x2 +/// LTDCYCL2 field reset value +#define MDM_LTDCYCL2_RST 0x1 + +/** + * @brief Constructs a value for the TDCYCLSHTRL0 register given values for its fields + * and writes the value to the register. + * + * @param[in] ltdcycl4 - The value to use for the LTDCYCL4 field. + * @param[in] ltdcycl3 - The value to use for the LTDCYCL3 field. + * @param[in] ltdcycl2 - The value to use for the LTDCYCL2 field. + */ +__INLINE void mdm_tdcyclshtrl0_pack(uint8_t ltdcycl4, uint8_t ltdcycl3, uint8_t ltdcycl2) +{ + ASSERT_ERR((((uint32_t)ltdcycl4 << 8) & ~((uint32_t)0x00000F00)) == 0); + ASSERT_ERR((((uint32_t)ltdcycl3 << 4) & ~((uint32_t)0x000000F0)) == 0); + ASSERT_ERR((((uint32_t)ltdcycl2 << 0) & ~((uint32_t)0x0000000F)) == 0); + REG_PL_WR(MDM_TDCYCLSHTRL0_ADDR, ((uint32_t)ltdcycl4 << 8) | ((uint32_t)ltdcycl3 << 4) | ((uint32_t)ltdcycl2 << 0)); +} + +/** + * @brief Unpacks TDCYCLSHTRL0's fields from current value of the TDCYCLSHTRL0 register. + * + * Reads the TDCYCLSHTRL0 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] ltdcycl4 - Will be populated with the current value of this field from the register. + * @param[out] ltdcycl3 - Will be populated with the current value of this field from the register. + * @param[out] ltdcycl2 - Will be populated with the current value of this field from the register. + */ +__INLINE void mdm_tdcyclshtrl0_unpack(uint8_t *ltdcycl4, uint8_t *ltdcycl3, uint8_t *ltdcycl2) +{ + uint32_t localVal = REG_PL_RD(MDM_TDCYCLSHTRL0_ADDR); + + *ltdcycl4 = (localVal & ((uint32_t)0x00000F00)) >> 8; + *ltdcycl3 = (localVal & ((uint32_t)0x000000F0)) >> 4; + *ltdcycl2 = (localVal & ((uint32_t)0x0000000F)) >> 0; +} + +/** + * @brief Returns the current value of the LTDCYCL4 field in the TDCYCLSHTRL0 register. + * + * The TDCYCLSHTRL0 register will be read and the LTDCYCL4 field's value will be returned. + * + * @return The current value of the LTDCYCL4 field in the TDCYCLSHTRL0 register. + */ +__INLINE uint8_t mdm_ltdcycl4_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TDCYCLSHTRL0_ADDR); + return ((localVal & ((uint32_t)0x00000F00)) >> 8); +} + +/** + * @brief Sets the LTDCYCL4 field of the TDCYCLSHTRL0 register. + * + * The TDCYCLSHTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] ltdcycl4 - The value to set the field to. + */ +__INLINE void mdm_ltdcycl4_setf(uint8_t ltdcycl4) +{ + ASSERT_ERR((((uint32_t)ltdcycl4 << 8) & ~((uint32_t)0x00000F00)) == 0); + REG_PL_WR(MDM_TDCYCLSHTRL0_ADDR, (REG_PL_RD(MDM_TDCYCLSHTRL0_ADDR) & ~((uint32_t)0x00000F00)) | ((uint32_t)ltdcycl4 << 8)); +} + +/** + * @brief Returns the current value of the LTDCYCL3 field in the TDCYCLSHTRL0 register. + * + * The TDCYCLSHTRL0 register will be read and the LTDCYCL3 field's value will be returned. + * + * @return The current value of the LTDCYCL3 field in the TDCYCLSHTRL0 register. + */ +__INLINE uint8_t mdm_ltdcycl3_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TDCYCLSHTRL0_ADDR); + return ((localVal & ((uint32_t)0x000000F0)) >> 4); +} + +/** + * @brief Sets the LTDCYCL3 field of the TDCYCLSHTRL0 register. + * + * The TDCYCLSHTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] ltdcycl3 - The value to set the field to. + */ +__INLINE void mdm_ltdcycl3_setf(uint8_t ltdcycl3) +{ + ASSERT_ERR((((uint32_t)ltdcycl3 << 4) & ~((uint32_t)0x000000F0)) == 0); + REG_PL_WR(MDM_TDCYCLSHTRL0_ADDR, (REG_PL_RD(MDM_TDCYCLSHTRL0_ADDR) & ~((uint32_t)0x000000F0)) | ((uint32_t)ltdcycl3 << 4)); +} + +/** + * @brief Returns the current value of the LTDCYCL2 field in the TDCYCLSHTRL0 register. + * + * The TDCYCLSHTRL0 register will be read and the LTDCYCL2 field's value will be returned. + * + * @return The current value of the LTDCYCL2 field in the TDCYCLSHTRL0 register. + */ +__INLINE uint8_t mdm_ltdcycl2_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TDCYCLSHTRL0_ADDR); + return ((localVal & ((uint32_t)0x0000000F)) >> 0); +} + +/** + * @brief Sets the LTDCYCL2 field of the TDCYCLSHTRL0 register. + * + * The TDCYCLSHTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] ltdcycl2 - The value to set the field to. + */ +__INLINE void mdm_ltdcycl2_setf(uint8_t ltdcycl2) +{ + ASSERT_ERR((((uint32_t)ltdcycl2 << 0) & ~((uint32_t)0x0000000F)) == 0); + REG_PL_WR(MDM_TDCYCLSHTRL0_ADDR, (REG_PL_RD(MDM_TDCYCLSHTRL0_ADDR) & ~((uint32_t)0x0000000F)) | ((uint32_t)ltdcycl2 << 0)); +} + +/// @} + +/** + * @name TDCYCLSHTRL1 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  11:08            HTTDCYCL4   0xC
+ *  07:04            HTTDCYCL3   0x4
+ *  03:00            HTTDCYCL2   0x8
+ * 
+ * + * @{ + */ + +/// Address of the TDCYCLSHTRL1 register +#define MDM_TDCYCLSHTRL1_ADDR 0x01000858 +/// Offset of the TDCYCLSHTRL1 register from the base address +#define MDM_TDCYCLSHTRL1_OFFSET 0x00000858 +/// Index of the TDCYCLSHTRL1 register +#define MDM_TDCYCLSHTRL1_INDEX 0x00000216 +/// Reset value of the TDCYCLSHTRL1 register +#define MDM_TDCYCLSHTRL1_RESET 0x00000C48 + +/** + * @brief Returns the current value of the TDCYCLSHTRL1 register. + * The TDCYCLSHTRL1 register will be read and its value returned. + * @return The current value of the TDCYCLSHTRL1 register. + */ +__INLINE uint32_t mdm_tdcyclshtrl1_get(void) +{ + return REG_PL_RD(MDM_TDCYCLSHTRL1_ADDR); +} + +/** + * @brief Sets the TDCYCLSHTRL1 register to a value. + * The TDCYCLSHTRL1 register will be written. + * @param value - The value to write. + */ +__INLINE void mdm_tdcyclshtrl1_set(uint32_t value) +{ + REG_PL_WR(MDM_TDCYCLSHTRL1_ADDR, value); +} + +// field definitions +/// HTTDCYCL4 field mask +#define MDM_HTTDCYCL4_MASK ((uint32_t)0x00000F00) +/// HTTDCYCL4 field LSB position +#define MDM_HTTDCYCL4_LSB 8 +/// HTTDCYCL4 field width +#define MDM_HTTDCYCL4_WIDTH ((uint32_t)0x00000004) +/// HTTDCYCL3 field mask +#define MDM_HTTDCYCL3_MASK ((uint32_t)0x000000F0) +/// HTTDCYCL3 field LSB position +#define MDM_HTTDCYCL3_LSB 4 +/// HTTDCYCL3 field width +#define MDM_HTTDCYCL3_WIDTH ((uint32_t)0x00000004) +/// HTTDCYCL2 field mask +#define MDM_HTTDCYCL2_MASK ((uint32_t)0x0000000F) +/// HTTDCYCL2 field LSB position +#define MDM_HTTDCYCL2_LSB 0 +/// HTTDCYCL2 field width +#define MDM_HTTDCYCL2_WIDTH ((uint32_t)0x00000004) + +/// HTTDCYCL4 field reset value +#define MDM_HTTDCYCL4_RST 0xC +/// HTTDCYCL3 field reset value +#define MDM_HTTDCYCL3_RST 0x4 +/// HTTDCYCL2 field reset value +#define MDM_HTTDCYCL2_RST 0x8 + +/** + * @brief Constructs a value for the TDCYCLSHTRL1 register given values for its fields + * and writes the value to the register. + * + * @param[in] httdcycl4 - The value to use for the HTTDCYCL4 field. + * @param[in] httdcycl3 - The value to use for the HTTDCYCL3 field. + * @param[in] httdcycl2 - The value to use for the HTTDCYCL2 field. + */ +__INLINE void mdm_tdcyclshtrl1_pack(uint8_t httdcycl4, uint8_t httdcycl3, uint8_t httdcycl2) +{ + ASSERT_ERR((((uint32_t)httdcycl4 << 8) & ~((uint32_t)0x00000F00)) == 0); + ASSERT_ERR((((uint32_t)httdcycl3 << 4) & ~((uint32_t)0x000000F0)) == 0); + ASSERT_ERR((((uint32_t)httdcycl2 << 0) & ~((uint32_t)0x0000000F)) == 0); + REG_PL_WR(MDM_TDCYCLSHTRL1_ADDR, ((uint32_t)httdcycl4 << 8) | ((uint32_t)httdcycl3 << 4) | ((uint32_t)httdcycl2 << 0)); +} + +/** + * @brief Unpacks TDCYCLSHTRL1's fields from current value of the TDCYCLSHTRL1 register. + * + * Reads the TDCYCLSHTRL1 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] httdcycl4 - Will be populated with the current value of this field from the register. + * @param[out] httdcycl3 - Will be populated with the current value of this field from the register. + * @param[out] httdcycl2 - Will be populated with the current value of this field from the register. + */ +__INLINE void mdm_tdcyclshtrl1_unpack(uint8_t *httdcycl4, uint8_t *httdcycl3, uint8_t *httdcycl2) +{ + uint32_t localVal = REG_PL_RD(MDM_TDCYCLSHTRL1_ADDR); + + *httdcycl4 = (localVal & ((uint32_t)0x00000F00)) >> 8; + *httdcycl3 = (localVal & ((uint32_t)0x000000F0)) >> 4; + *httdcycl2 = (localVal & ((uint32_t)0x0000000F)) >> 0; +} + +/** + * @brief Returns the current value of the HTTDCYCL4 field in the TDCYCLSHTRL1 register. + * + * The TDCYCLSHTRL1 register will be read and the HTTDCYCL4 field's value will be returned. + * + * @return The current value of the HTTDCYCL4 field in the TDCYCLSHTRL1 register. + */ +__INLINE uint8_t mdm_httdcycl4_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TDCYCLSHTRL1_ADDR); + return ((localVal & ((uint32_t)0x00000F00)) >> 8); +} + +/** + * @brief Sets the HTTDCYCL4 field of the TDCYCLSHTRL1 register. + * + * The TDCYCLSHTRL1 register will be read, modified to contain the new field value, and written. + * + * @param[in] httdcycl4 - The value to set the field to. + */ +__INLINE void mdm_httdcycl4_setf(uint8_t httdcycl4) +{ + ASSERT_ERR((((uint32_t)httdcycl4 << 8) & ~((uint32_t)0x00000F00)) == 0); + REG_PL_WR(MDM_TDCYCLSHTRL1_ADDR, (REG_PL_RD(MDM_TDCYCLSHTRL1_ADDR) & ~((uint32_t)0x00000F00)) | ((uint32_t)httdcycl4 << 8)); +} + +/** + * @brief Returns the current value of the HTTDCYCL3 field in the TDCYCLSHTRL1 register. + * + * The TDCYCLSHTRL1 register will be read and the HTTDCYCL3 field's value will be returned. + * + * @return The current value of the HTTDCYCL3 field in the TDCYCLSHTRL1 register. + */ +__INLINE uint8_t mdm_httdcycl3_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TDCYCLSHTRL1_ADDR); + return ((localVal & ((uint32_t)0x000000F0)) >> 4); +} + +/** + * @brief Sets the HTTDCYCL3 field of the TDCYCLSHTRL1 register. + * + * The TDCYCLSHTRL1 register will be read, modified to contain the new field value, and written. + * + * @param[in] httdcycl3 - The value to set the field to. + */ +__INLINE void mdm_httdcycl3_setf(uint8_t httdcycl3) +{ + ASSERT_ERR((((uint32_t)httdcycl3 << 4) & ~((uint32_t)0x000000F0)) == 0); + REG_PL_WR(MDM_TDCYCLSHTRL1_ADDR, (REG_PL_RD(MDM_TDCYCLSHTRL1_ADDR) & ~((uint32_t)0x000000F0)) | ((uint32_t)httdcycl3 << 4)); +} + +/** + * @brief Returns the current value of the HTTDCYCL2 field in the TDCYCLSHTRL1 register. + * + * The TDCYCLSHTRL1 register will be read and the HTTDCYCL2 field's value will be returned. + * + * @return The current value of the HTTDCYCL2 field in the TDCYCLSHTRL1 register. + */ +__INLINE uint8_t mdm_httdcycl2_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TDCYCLSHTRL1_ADDR); + return ((localVal & ((uint32_t)0x0000000F)) >> 0); +} + +/** + * @brief Sets the HTTDCYCL2 field of the TDCYCLSHTRL1 register. + * + * The TDCYCLSHTRL1 register will be read, modified to contain the new field value, and written. + * + * @param[in] httdcycl2 - The value to set the field to. + */ +__INLINE void mdm_httdcycl2_setf(uint8_t httdcycl2) +{ + ASSERT_ERR((((uint32_t)httdcycl2 << 0) & ~((uint32_t)0x0000000F)) == 0); + REG_PL_WR(MDM_TDCYCLSHTRL1_ADDR, (REG_PL_RD(MDM_TDCYCLSHTRL1_ADDR) & ~((uint32_t)0x0000000F)) | ((uint32_t)httdcycl2 << 0)); +} + +/// @} + +/** + * @name SCRAMBLERCTRL register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  07:00            SCRAMSEED   0x0
+ * 
+ * + * @{ + */ + +/// Address of the SCRAMBLERCTRL register +#define MDM_SCRAMBLERCTRL_ADDR 0x0100085C +/// Offset of the SCRAMBLERCTRL register from the base address +#define MDM_SCRAMBLERCTRL_OFFSET 0x0000085C +/// Index of the SCRAMBLERCTRL register +#define MDM_SCRAMBLERCTRL_INDEX 0x00000217 +/// Reset value of the SCRAMBLERCTRL register +#define MDM_SCRAMBLERCTRL_RESET 0x00000000 + +/** + * @brief Returns the current value of the SCRAMBLERCTRL register. + * The SCRAMBLERCTRL register will be read and its value returned. + * @return The current value of the SCRAMBLERCTRL register. + */ +__INLINE uint32_t mdm_scramblerctrl_get(void) +{ + return REG_PL_RD(MDM_SCRAMBLERCTRL_ADDR); +} + +/** + * @brief Sets the SCRAMBLERCTRL register to a value. + * The SCRAMBLERCTRL register will be written. + * @param value - The value to write. + */ +__INLINE void mdm_scramblerctrl_set(uint32_t value) +{ + REG_PL_WR(MDM_SCRAMBLERCTRL_ADDR, value); +} + +// field definitions +/// SCRAMSEED field mask +#define MDM_SCRAMSEED_MASK ((uint32_t)0x000000FF) +/// SCRAMSEED field LSB position +#define MDM_SCRAMSEED_LSB 0 +/// SCRAMSEED field width +#define MDM_SCRAMSEED_WIDTH ((uint32_t)0x00000008) + +/// SCRAMSEED field reset value +#define MDM_SCRAMSEED_RST 0x0 + +/** + * @brief Returns the current value of the SCRAMSEED field in the SCRAMBLERCTRL register. + * + * The SCRAMBLERCTRL register will be read and the SCRAMSEED field's value will be returned. + * + * @return The current value of the SCRAMSEED field in the SCRAMBLERCTRL register. + */ +__INLINE uint8_t mdm_scramseed_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_SCRAMBLERCTRL_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x000000FF)) == 0); + return (localVal >> 0); +} + +/** + * @brief Sets the SCRAMSEED field of the SCRAMBLERCTRL register. + * + * The SCRAMBLERCTRL register will be read, modified to contain the new field value, and written. + * + * @param[in] scramseed - The value to set the field to. + */ +__INLINE void mdm_scramseed_setf(uint8_t scramseed) +{ + ASSERT_ERR((((uint32_t)scramseed << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(MDM_SCRAMBLERCTRL_ADDR, (uint32_t)scramseed << 0); +} + +/// @} + +/** + * @name TBECTRL0 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:24   CrossCorrSNRThreshold   0xC
+ *  23:16     TBECountAdjust80   0x11
+ *  15:08     TBECountAdjust40   0x7
+ *  07:00     TBECountAdjust20   0x0
+ * 
+ * + * @{ + */ + +/// Address of the TBECTRL0 register +#define MDM_TBECTRL0_ADDR 0x01000860 +/// Offset of the TBECTRL0 register from the base address +#define MDM_TBECTRL0_OFFSET 0x00000860 +/// Index of the TBECTRL0 register +#define MDM_TBECTRL0_INDEX 0x00000218 +/// Reset value of the TBECTRL0 register +#define MDM_TBECTRL0_RESET 0x0C110700 + +/** + * @brief Returns the current value of the TBECTRL0 register. + * The TBECTRL0 register will be read and its value returned. + * @return The current value of the TBECTRL0 register. + */ +__INLINE uint32_t mdm_tbectrl0_get(void) +{ + return REG_PL_RD(MDM_TBECTRL0_ADDR); +} + +/** + * @brief Sets the TBECTRL0 register to a value. + * The TBECTRL0 register will be written. + * @param value - The value to write. + */ +__INLINE void mdm_tbectrl0_set(uint32_t value) +{ + REG_PL_WR(MDM_TBECTRL0_ADDR, value); +} + +// field definitions +/// CROSS_CORR_SNR_THRESHOLD field mask +#define MDM_CROSS_CORR_SNR_THRESHOLD_MASK ((uint32_t)0xFF000000) +/// CROSS_CORR_SNR_THRESHOLD field LSB position +#define MDM_CROSS_CORR_SNR_THRESHOLD_LSB 24 +/// CROSS_CORR_SNR_THRESHOLD field width +#define MDM_CROSS_CORR_SNR_THRESHOLD_WIDTH ((uint32_t)0x00000008) +/// TBE_COUNT_ADJUST_80 field mask +#define MDM_TBE_COUNT_ADJUST_80_MASK ((uint32_t)0x00FF0000) +/// TBE_COUNT_ADJUST_80 field LSB position +#define MDM_TBE_COUNT_ADJUST_80_LSB 16 +/// TBE_COUNT_ADJUST_80 field width +#define MDM_TBE_COUNT_ADJUST_80_WIDTH ((uint32_t)0x00000008) +/// TBE_COUNT_ADJUST_40 field mask +#define MDM_TBE_COUNT_ADJUST_40_MASK ((uint32_t)0x0000FF00) +/// TBE_COUNT_ADJUST_40 field LSB position +#define MDM_TBE_COUNT_ADJUST_40_LSB 8 +/// TBE_COUNT_ADJUST_40 field width +#define MDM_TBE_COUNT_ADJUST_40_WIDTH ((uint32_t)0x00000008) +/// TBE_COUNT_ADJUST_20 field mask +#define MDM_TBE_COUNT_ADJUST_20_MASK ((uint32_t)0x000000FF) +/// TBE_COUNT_ADJUST_20 field LSB position +#define MDM_TBE_COUNT_ADJUST_20_LSB 0 +/// TBE_COUNT_ADJUST_20 field width +#define MDM_TBE_COUNT_ADJUST_20_WIDTH ((uint32_t)0x00000008) + +/// CROSS_CORR_SNR_THRESHOLD field reset value +#define MDM_CROSS_CORR_SNR_THRESHOLD_RST 0xC +/// TBE_COUNT_ADJUST_80 field reset value +#define MDM_TBE_COUNT_ADJUST_80_RST 0x11 +/// TBE_COUNT_ADJUST_40 field reset value +#define MDM_TBE_COUNT_ADJUST_40_RST 0x7 +/// TBE_COUNT_ADJUST_20 field reset value +#define MDM_TBE_COUNT_ADJUST_20_RST 0x0 + +/** + * @brief Constructs a value for the TBECTRL0 register given values for its fields + * and writes the value to the register. + * + * @param[in] crosscorrsnrthreshold - The value to use for the CrossCorrSNRThreshold field. + * @param[in] tbecountadjust80 - The value to use for the TBECountAdjust80 field. + * @param[in] tbecountadjust40 - The value to use for the TBECountAdjust40 field. + * @param[in] tbecountadjust20 - The value to use for the TBECountAdjust20 field. + */ +__INLINE void mdm_tbectrl0_pack(uint8_t crosscorrsnrthreshold, uint8_t tbecountadjust80, uint8_t tbecountadjust40, uint8_t tbecountadjust20) +{ + ASSERT_ERR((((uint32_t)crosscorrsnrthreshold << 24) & ~((uint32_t)0xFF000000)) == 0); + ASSERT_ERR((((uint32_t)tbecountadjust80 << 16) & ~((uint32_t)0x00FF0000)) == 0); + ASSERT_ERR((((uint32_t)tbecountadjust40 << 8) & ~((uint32_t)0x0000FF00)) == 0); + ASSERT_ERR((((uint32_t)tbecountadjust20 << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(MDM_TBECTRL0_ADDR, ((uint32_t)crosscorrsnrthreshold << 24) | ((uint32_t)tbecountadjust80 << 16) | ((uint32_t)tbecountadjust40 << 8) | ((uint32_t)tbecountadjust20 << 0)); +} + +/** + * @brief Unpacks TBECTRL0's fields from current value of the TBECTRL0 register. + * + * Reads the TBECTRL0 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] crosscorrsnrthreshold - Will be populated with the current value of this field from the register. + * @param[out] tbecountadjust80 - Will be populated with the current value of this field from the register. + * @param[out] tbecountadjust40 - Will be populated with the current value of this field from the register. + * @param[out] tbecountadjust20 - Will be populated with the current value of this field from the register. + */ +__INLINE void mdm_tbectrl0_unpack(uint8_t *crosscorrsnrthreshold, uint8_t *tbecountadjust80, uint8_t *tbecountadjust40, uint8_t *tbecountadjust20) +{ + uint32_t localVal = REG_PL_RD(MDM_TBECTRL0_ADDR); + + *crosscorrsnrthreshold = (localVal & ((uint32_t)0xFF000000)) >> 24; + *tbecountadjust80 = (localVal & ((uint32_t)0x00FF0000)) >> 16; + *tbecountadjust40 = (localVal & ((uint32_t)0x0000FF00)) >> 8; + *tbecountadjust20 = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +/** + * @brief Returns the current value of the CrossCorrSNRThreshold field in the TBECTRL0 register. + * + * The TBECTRL0 register will be read and the CrossCorrSNRThreshold field's value will be returned. + * + * @return The current value of the CrossCorrSNRThreshold field in the TBECTRL0 register. + */ +__INLINE uint8_t mdm_cross_corr_snr_threshold_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TBECTRL0_ADDR); + return ((localVal & ((uint32_t)0xFF000000)) >> 24); +} + +/** + * @brief Sets the CrossCorrSNRThreshold field of the TBECTRL0 register. + * + * The TBECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] crosscorrsnrthreshold - The value to set the field to. + */ +__INLINE void mdm_cross_corr_snr_threshold_setf(uint8_t crosscorrsnrthreshold) +{ + ASSERT_ERR((((uint32_t)crosscorrsnrthreshold << 24) & ~((uint32_t)0xFF000000)) == 0); + REG_PL_WR(MDM_TBECTRL0_ADDR, (REG_PL_RD(MDM_TBECTRL0_ADDR) & ~((uint32_t)0xFF000000)) | ((uint32_t)crosscorrsnrthreshold << 24)); +} + +/** + * @brief Returns the current value of the TBECountAdjust80 field in the TBECTRL0 register. + * + * The TBECTRL0 register will be read and the TBECountAdjust80 field's value will be returned. + * + * @return The current value of the TBECountAdjust80 field in the TBECTRL0 register. + */ +__INLINE uint8_t mdm_tbe_count_adjust_80_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TBECTRL0_ADDR); + return ((localVal & ((uint32_t)0x00FF0000)) >> 16); +} + +/** + * @brief Sets the TBECountAdjust80 field of the TBECTRL0 register. + * + * The TBECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] tbecountadjust80 - The value to set the field to. + */ +__INLINE void mdm_tbe_count_adjust_80_setf(uint8_t tbecountadjust80) +{ + ASSERT_ERR((((uint32_t)tbecountadjust80 << 16) & ~((uint32_t)0x00FF0000)) == 0); + REG_PL_WR(MDM_TBECTRL0_ADDR, (REG_PL_RD(MDM_TBECTRL0_ADDR) & ~((uint32_t)0x00FF0000)) | ((uint32_t)tbecountadjust80 << 16)); +} + +/** + * @brief Returns the current value of the TBECountAdjust40 field in the TBECTRL0 register. + * + * The TBECTRL0 register will be read and the TBECountAdjust40 field's value will be returned. + * + * @return The current value of the TBECountAdjust40 field in the TBECTRL0 register. + */ +__INLINE uint8_t mdm_tbe_count_adjust_40_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TBECTRL0_ADDR); + return ((localVal & ((uint32_t)0x0000FF00)) >> 8); +} + +/** + * @brief Sets the TBECountAdjust40 field of the TBECTRL0 register. + * + * The TBECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] tbecountadjust40 - The value to set the field to. + */ +__INLINE void mdm_tbe_count_adjust_40_setf(uint8_t tbecountadjust40) +{ + ASSERT_ERR((((uint32_t)tbecountadjust40 << 8) & ~((uint32_t)0x0000FF00)) == 0); + REG_PL_WR(MDM_TBECTRL0_ADDR, (REG_PL_RD(MDM_TBECTRL0_ADDR) & ~((uint32_t)0x0000FF00)) | ((uint32_t)tbecountadjust40 << 8)); +} + +/** + * @brief Returns the current value of the TBECountAdjust20 field in the TBECTRL0 register. + * + * The TBECTRL0 register will be read and the TBECountAdjust20 field's value will be returned. + * + * @return The current value of the TBECountAdjust20 field in the TBECTRL0 register. + */ +__INLINE uint8_t mdm_tbe_count_adjust_20_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TBECTRL0_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +/** + * @brief Sets the TBECountAdjust20 field of the TBECTRL0 register. + * + * The TBECTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] tbecountadjust20 - The value to set the field to. + */ +__INLINE void mdm_tbe_count_adjust_20_setf(uint8_t tbecountadjust20) +{ + ASSERT_ERR((((uint32_t)tbecountadjust20 << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(MDM_TBECTRL0_ADDR, (REG_PL_RD(MDM_TBECTRL0_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)tbecountadjust20 << 0)); +} + +/// @} + +/** + * @name TBECTRL1 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  30:24   PeakSearchStopHighSNR   0x3C
+ *  22:16   PeakSearchStartHighSNR   0x14
+ *  14:08   PeakSearchStopLowSNR   0x3E
+ *  06:00   PeakSearchStartLowSNR   0x14
+ * 
+ * + * @{ + */ + +/// Address of the TBECTRL1 register +#define MDM_TBECTRL1_ADDR 0x01000864 +/// Offset of the TBECTRL1 register from the base address +#define MDM_TBECTRL1_OFFSET 0x00000864 +/// Index of the TBECTRL1 register +#define MDM_TBECTRL1_INDEX 0x00000219 +/// Reset value of the TBECTRL1 register +#define MDM_TBECTRL1_RESET 0x3C143E14 + +/** + * @brief Returns the current value of the TBECTRL1 register. + * The TBECTRL1 register will be read and its value returned. + * @return The current value of the TBECTRL1 register. + */ +__INLINE uint32_t mdm_tbectrl1_get(void) +{ + return REG_PL_RD(MDM_TBECTRL1_ADDR); +} + +/** + * @brief Sets the TBECTRL1 register to a value. + * The TBECTRL1 register will be written. + * @param value - The value to write. + */ +__INLINE void mdm_tbectrl1_set(uint32_t value) +{ + REG_PL_WR(MDM_TBECTRL1_ADDR, value); +} + +// field definitions +/// PEAK_SEARCH_STOP_HIGH_SNR field mask +#define MDM_PEAK_SEARCH_STOP_HIGH_SNR_MASK ((uint32_t)0x7F000000) +/// PEAK_SEARCH_STOP_HIGH_SNR field LSB position +#define MDM_PEAK_SEARCH_STOP_HIGH_SNR_LSB 24 +/// PEAK_SEARCH_STOP_HIGH_SNR field width +#define MDM_PEAK_SEARCH_STOP_HIGH_SNR_WIDTH ((uint32_t)0x00000007) +/// PEAK_SEARCH_START_HIGH_SNR field mask +#define MDM_PEAK_SEARCH_START_HIGH_SNR_MASK ((uint32_t)0x007F0000) +/// PEAK_SEARCH_START_HIGH_SNR field LSB position +#define MDM_PEAK_SEARCH_START_HIGH_SNR_LSB 16 +/// PEAK_SEARCH_START_HIGH_SNR field width +#define MDM_PEAK_SEARCH_START_HIGH_SNR_WIDTH ((uint32_t)0x00000007) +/// PEAK_SEARCH_STOP_LOW_SNR field mask +#define MDM_PEAK_SEARCH_STOP_LOW_SNR_MASK ((uint32_t)0x00007F00) +/// PEAK_SEARCH_STOP_LOW_SNR field LSB position +#define MDM_PEAK_SEARCH_STOP_LOW_SNR_LSB 8 +/// PEAK_SEARCH_STOP_LOW_SNR field width +#define MDM_PEAK_SEARCH_STOP_LOW_SNR_WIDTH ((uint32_t)0x00000007) +/// PEAK_SEARCH_START_LOW_SNR field mask +#define MDM_PEAK_SEARCH_START_LOW_SNR_MASK ((uint32_t)0x0000007F) +/// PEAK_SEARCH_START_LOW_SNR field LSB position +#define MDM_PEAK_SEARCH_START_LOW_SNR_LSB 0 +/// PEAK_SEARCH_START_LOW_SNR field width +#define MDM_PEAK_SEARCH_START_LOW_SNR_WIDTH ((uint32_t)0x00000007) + +/// PEAK_SEARCH_STOP_HIGH_SNR field reset value +#define MDM_PEAK_SEARCH_STOP_HIGH_SNR_RST 0x3C +/// PEAK_SEARCH_START_HIGH_SNR field reset value +#define MDM_PEAK_SEARCH_START_HIGH_SNR_RST 0x14 +/// PEAK_SEARCH_STOP_LOW_SNR field reset value +#define MDM_PEAK_SEARCH_STOP_LOW_SNR_RST 0x3E +/// PEAK_SEARCH_START_LOW_SNR field reset value +#define MDM_PEAK_SEARCH_START_LOW_SNR_RST 0x14 + +/** + * @brief Constructs a value for the TBECTRL1 register given values for its fields + * and writes the value to the register. + * + * @param[in] peaksearchstophighsnr - The value to use for the PeakSearchStopHighSNR field. + * @param[in] peaksearchstarthighsnr - The value to use for the PeakSearchStartHighSNR field. + * @param[in] peaksearchstoplowsnr - The value to use for the PeakSearchStopLowSNR field. + * @param[in] peaksearchstartlowsnr - The value to use for the PeakSearchStartLowSNR field. + */ +__INLINE void mdm_tbectrl1_pack(uint8_t peaksearchstophighsnr, uint8_t peaksearchstarthighsnr, uint8_t peaksearchstoplowsnr, uint8_t peaksearchstartlowsnr) +{ + ASSERT_ERR((((uint32_t)peaksearchstophighsnr << 24) & ~((uint32_t)0x7F000000)) == 0); + ASSERT_ERR((((uint32_t)peaksearchstarthighsnr << 16) & ~((uint32_t)0x007F0000)) == 0); + ASSERT_ERR((((uint32_t)peaksearchstoplowsnr << 8) & ~((uint32_t)0x00007F00)) == 0); + ASSERT_ERR((((uint32_t)peaksearchstartlowsnr << 0) & ~((uint32_t)0x0000007F)) == 0); + REG_PL_WR(MDM_TBECTRL1_ADDR, ((uint32_t)peaksearchstophighsnr << 24) | ((uint32_t)peaksearchstarthighsnr << 16) | ((uint32_t)peaksearchstoplowsnr << 8) | ((uint32_t)peaksearchstartlowsnr << 0)); +} + +/** + * @brief Unpacks TBECTRL1's fields from current value of the TBECTRL1 register. + * + * Reads the TBECTRL1 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] peaksearchstophighsnr - Will be populated with the current value of this field from the register. + * @param[out] peaksearchstarthighsnr - Will be populated with the current value of this field from the register. + * @param[out] peaksearchstoplowsnr - Will be populated with the current value of this field from the register. + * @param[out] peaksearchstartlowsnr - Will be populated with the current value of this field from the register. + */ +__INLINE void mdm_tbectrl1_unpack(uint8_t *peaksearchstophighsnr, uint8_t *peaksearchstarthighsnr, uint8_t *peaksearchstoplowsnr, uint8_t *peaksearchstartlowsnr) +{ + uint32_t localVal = REG_PL_RD(MDM_TBECTRL1_ADDR); + + *peaksearchstophighsnr = (localVal & ((uint32_t)0x7F000000)) >> 24; + *peaksearchstarthighsnr = (localVal & ((uint32_t)0x007F0000)) >> 16; + *peaksearchstoplowsnr = (localVal & ((uint32_t)0x00007F00)) >> 8; + *peaksearchstartlowsnr = (localVal & ((uint32_t)0x0000007F)) >> 0; +} + +/** + * @brief Returns the current value of the PeakSearchStopHighSNR field in the TBECTRL1 register. + * + * The TBECTRL1 register will be read and the PeakSearchStopHighSNR field's value will be returned. + * + * @return The current value of the PeakSearchStopHighSNR field in the TBECTRL1 register. + */ +__INLINE uint8_t mdm_peak_search_stop_high_snr_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TBECTRL1_ADDR); + return ((localVal & ((uint32_t)0x7F000000)) >> 24); +} + +/** + * @brief Sets the PeakSearchStopHighSNR field of the TBECTRL1 register. + * + * The TBECTRL1 register will be read, modified to contain the new field value, and written. + * + * @param[in] peaksearchstophighsnr - The value to set the field to. + */ +__INLINE void mdm_peak_search_stop_high_snr_setf(uint8_t peaksearchstophighsnr) +{ + ASSERT_ERR((((uint32_t)peaksearchstophighsnr << 24) & ~((uint32_t)0x7F000000)) == 0); + REG_PL_WR(MDM_TBECTRL1_ADDR, (REG_PL_RD(MDM_TBECTRL1_ADDR) & ~((uint32_t)0x7F000000)) | ((uint32_t)peaksearchstophighsnr << 24)); +} + +/** + * @brief Returns the current value of the PeakSearchStartHighSNR field in the TBECTRL1 register. + * + * The TBECTRL1 register will be read and the PeakSearchStartHighSNR field's value will be returned. + * + * @return The current value of the PeakSearchStartHighSNR field in the TBECTRL1 register. + */ +__INLINE uint8_t mdm_peak_search_start_high_snr_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TBECTRL1_ADDR); + return ((localVal & ((uint32_t)0x007F0000)) >> 16); +} + +/** + * @brief Sets the PeakSearchStartHighSNR field of the TBECTRL1 register. + * + * The TBECTRL1 register will be read, modified to contain the new field value, and written. + * + * @param[in] peaksearchstarthighsnr - The value to set the field to. + */ +__INLINE void mdm_peak_search_start_high_snr_setf(uint8_t peaksearchstarthighsnr) +{ + ASSERT_ERR((((uint32_t)peaksearchstarthighsnr << 16) & ~((uint32_t)0x007F0000)) == 0); + REG_PL_WR(MDM_TBECTRL1_ADDR, (REG_PL_RD(MDM_TBECTRL1_ADDR) & ~((uint32_t)0x007F0000)) | ((uint32_t)peaksearchstarthighsnr << 16)); +} + +/** + * @brief Returns the current value of the PeakSearchStopLowSNR field in the TBECTRL1 register. + * + * The TBECTRL1 register will be read and the PeakSearchStopLowSNR field's value will be returned. + * + * @return The current value of the PeakSearchStopLowSNR field in the TBECTRL1 register. + */ +__INLINE uint8_t mdm_peak_search_stop_low_snr_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TBECTRL1_ADDR); + return ((localVal & ((uint32_t)0x00007F00)) >> 8); +} + +/** + * @brief Sets the PeakSearchStopLowSNR field of the TBECTRL1 register. + * + * The TBECTRL1 register will be read, modified to contain the new field value, and written. + * + * @param[in] peaksearchstoplowsnr - The value to set the field to. + */ +__INLINE void mdm_peak_search_stop_low_snr_setf(uint8_t peaksearchstoplowsnr) +{ + ASSERT_ERR((((uint32_t)peaksearchstoplowsnr << 8) & ~((uint32_t)0x00007F00)) == 0); + REG_PL_WR(MDM_TBECTRL1_ADDR, (REG_PL_RD(MDM_TBECTRL1_ADDR) & ~((uint32_t)0x00007F00)) | ((uint32_t)peaksearchstoplowsnr << 8)); +} + +/** + * @brief Returns the current value of the PeakSearchStartLowSNR field in the TBECTRL1 register. + * + * The TBECTRL1 register will be read and the PeakSearchStartLowSNR field's value will be returned. + * + * @return The current value of the PeakSearchStartLowSNR field in the TBECTRL1 register. + */ +__INLINE uint8_t mdm_peak_search_start_low_snr_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TBECTRL1_ADDR); + return ((localVal & ((uint32_t)0x0000007F)) >> 0); +} + +/** + * @brief Sets the PeakSearchStartLowSNR field of the TBECTRL1 register. + * + * The TBECTRL1 register will be read, modified to contain the new field value, and written. + * + * @param[in] peaksearchstartlowsnr - The value to set the field to. + */ +__INLINE void mdm_peak_search_start_low_snr_setf(uint8_t peaksearchstartlowsnr) +{ + ASSERT_ERR((((uint32_t)peaksearchstartlowsnr << 0) & ~((uint32_t)0x0000007F)) == 0); + REG_PL_WR(MDM_TBECTRL1_ADDR, (REG_PL_RD(MDM_TBECTRL1_ADDR) & ~((uint32_t)0x0000007F)) | ((uint32_t)peaksearchstartlowsnr << 0)); +} + +/// @} + +/** + * @name TBECTRL2 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:28    TDAdjust80ShortGI   0x0
+ *  27:24    TDAdjust40ShortGI   0x0
+ *  23:20    TDAdjust20ShortGI   0x0
+ *  16:12      PeakSearchDelta   0x7
+ *  07:00              TBEBias   0x5
+ * 
+ * + * @{ + */ + +/// Address of the TBECTRL2 register +#define MDM_TBECTRL2_ADDR 0x01000868 +/// Offset of the TBECTRL2 register from the base address +#define MDM_TBECTRL2_OFFSET 0x00000868 +/// Index of the TBECTRL2 register +#define MDM_TBECTRL2_INDEX 0x0000021A +/// Reset value of the TBECTRL2 register +#define MDM_TBECTRL2_RESET 0x00007005 + +/** + * @brief Returns the current value of the TBECTRL2 register. + * The TBECTRL2 register will be read and its value returned. + * @return The current value of the TBECTRL2 register. + */ +__INLINE uint32_t mdm_tbectrl2_get(void) +{ + return REG_PL_RD(MDM_TBECTRL2_ADDR); +} + +/** + * @brief Sets the TBECTRL2 register to a value. + * The TBECTRL2 register will be written. + * @param value - The value to write. + */ +__INLINE void mdm_tbectrl2_set(uint32_t value) +{ + REG_PL_WR(MDM_TBECTRL2_ADDR, value); +} + +// field definitions +/// TD_ADJUST_80_SHORT_GI field mask +#define MDM_TD_ADJUST_80_SHORT_GI_MASK ((uint32_t)0xF0000000) +/// TD_ADJUST_80_SHORT_GI field LSB position +#define MDM_TD_ADJUST_80_SHORT_GI_LSB 28 +/// TD_ADJUST_80_SHORT_GI field width +#define MDM_TD_ADJUST_80_SHORT_GI_WIDTH ((uint32_t)0x00000004) +/// TD_ADJUST_40_SHORT_GI field mask +#define MDM_TD_ADJUST_40_SHORT_GI_MASK ((uint32_t)0x0F000000) +/// TD_ADJUST_40_SHORT_GI field LSB position +#define MDM_TD_ADJUST_40_SHORT_GI_LSB 24 +/// TD_ADJUST_40_SHORT_GI field width +#define MDM_TD_ADJUST_40_SHORT_GI_WIDTH ((uint32_t)0x00000004) +/// TD_ADJUST_20_SHORT_GI field mask +#define MDM_TD_ADJUST_20_SHORT_GI_MASK ((uint32_t)0x00F00000) +/// TD_ADJUST_20_SHORT_GI field LSB position +#define MDM_TD_ADJUST_20_SHORT_GI_LSB 20 +/// TD_ADJUST_20_SHORT_GI field width +#define MDM_TD_ADJUST_20_SHORT_GI_WIDTH ((uint32_t)0x00000004) +/// PEAK_SEARCH_DELTA field mask +#define MDM_PEAK_SEARCH_DELTA_MASK ((uint32_t)0x0001F000) +/// PEAK_SEARCH_DELTA field LSB position +#define MDM_PEAK_SEARCH_DELTA_LSB 12 +/// PEAK_SEARCH_DELTA field width +#define MDM_PEAK_SEARCH_DELTA_WIDTH ((uint32_t)0x00000005) +/// TBE_BIAS field mask +#define MDM_TBE_BIAS_MASK ((uint32_t)0x000000FF) +/// TBE_BIAS field LSB position +#define MDM_TBE_BIAS_LSB 0 +/// TBE_BIAS field width +#define MDM_TBE_BIAS_WIDTH ((uint32_t)0x00000008) + +/// TD_ADJUST_80_SHORT_GI field reset value +#define MDM_TD_ADJUST_80_SHORT_GI_RST 0x0 +/// TD_ADJUST_40_SHORT_GI field reset value +#define MDM_TD_ADJUST_40_SHORT_GI_RST 0x0 +/// TD_ADJUST_20_SHORT_GI field reset value +#define MDM_TD_ADJUST_20_SHORT_GI_RST 0x0 +/// PEAK_SEARCH_DELTA field reset value +#define MDM_PEAK_SEARCH_DELTA_RST 0x7 +/// TBE_BIAS field reset value +#define MDM_TBE_BIAS_RST 0x5 + +/** + * @brief Constructs a value for the TBECTRL2 register given values for its fields + * and writes the value to the register. + * + * @param[in] tdadjust80shortgi - The value to use for the TDAdjust80ShortGI field. + * @param[in] tdadjust40shortgi - The value to use for the TDAdjust40ShortGI field. + * @param[in] tdadjust20shortgi - The value to use for the TDAdjust20ShortGI field. + * @param[in] peaksearchdelta - The value to use for the PeakSearchDelta field. + * @param[in] tbebias - The value to use for the TBEBias field. + */ +__INLINE void mdm_tbectrl2_pack(uint8_t tdadjust80shortgi, uint8_t tdadjust40shortgi, uint8_t tdadjust20shortgi, uint8_t peaksearchdelta, uint8_t tbebias) +{ + ASSERT_ERR((((uint32_t)tdadjust80shortgi << 28) & ~((uint32_t)0xF0000000)) == 0); + ASSERT_ERR((((uint32_t)tdadjust40shortgi << 24) & ~((uint32_t)0x0F000000)) == 0); + ASSERT_ERR((((uint32_t)tdadjust20shortgi << 20) & ~((uint32_t)0x00F00000)) == 0); + ASSERT_ERR((((uint32_t)peaksearchdelta << 12) & ~((uint32_t)0x0001F000)) == 0); + ASSERT_ERR((((uint32_t)tbebias << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(MDM_TBECTRL2_ADDR, ((uint32_t)tdadjust80shortgi << 28) | ((uint32_t)tdadjust40shortgi << 24) | ((uint32_t)tdadjust20shortgi << 20) | ((uint32_t)peaksearchdelta << 12) | ((uint32_t)tbebias << 0)); +} + +/** + * @brief Unpacks TBECTRL2's fields from current value of the TBECTRL2 register. + * + * Reads the TBECTRL2 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] tdadjust80shortgi - Will be populated with the current value of this field from the register. + * @param[out] tdadjust40shortgi - Will be populated with the current value of this field from the register. + * @param[out] tdadjust20shortgi - Will be populated with the current value of this field from the register. + * @param[out] peaksearchdelta - Will be populated with the current value of this field from the register. + * @param[out] tbebias - Will be populated with the current value of this field from the register. + */ +__INLINE void mdm_tbectrl2_unpack(uint8_t *tdadjust80shortgi, uint8_t *tdadjust40shortgi, uint8_t *tdadjust20shortgi, uint8_t *peaksearchdelta, uint8_t *tbebias) +{ + uint32_t localVal = REG_PL_RD(MDM_TBECTRL2_ADDR); + + *tdadjust80shortgi = (localVal & ((uint32_t)0xF0000000)) >> 28; + *tdadjust40shortgi = (localVal & ((uint32_t)0x0F000000)) >> 24; + *tdadjust20shortgi = (localVal & ((uint32_t)0x00F00000)) >> 20; + *peaksearchdelta = (localVal & ((uint32_t)0x0001F000)) >> 12; + *tbebias = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +/** + * @brief Returns the current value of the TDAdjust80ShortGI field in the TBECTRL2 register. + * + * The TBECTRL2 register will be read and the TDAdjust80ShortGI field's value will be returned. + * + * @return The current value of the TDAdjust80ShortGI field in the TBECTRL2 register. + */ +__INLINE uint8_t mdm_td_adjust_80_short_gi_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TBECTRL2_ADDR); + return ((localVal & ((uint32_t)0xF0000000)) >> 28); +} + +/** + * @brief Sets the TDAdjust80ShortGI field of the TBECTRL2 register. + * + * The TBECTRL2 register will be read, modified to contain the new field value, and written. + * + * @param[in] tdadjust80shortgi - The value to set the field to. + */ +__INLINE void mdm_td_adjust_80_short_gi_setf(uint8_t tdadjust80shortgi) +{ + ASSERT_ERR((((uint32_t)tdadjust80shortgi << 28) & ~((uint32_t)0xF0000000)) == 0); + REG_PL_WR(MDM_TBECTRL2_ADDR, (REG_PL_RD(MDM_TBECTRL2_ADDR) & ~((uint32_t)0xF0000000)) | ((uint32_t)tdadjust80shortgi << 28)); +} + +/** + * @brief Returns the current value of the TDAdjust40ShortGI field in the TBECTRL2 register. + * + * The TBECTRL2 register will be read and the TDAdjust40ShortGI field's value will be returned. + * + * @return The current value of the TDAdjust40ShortGI field in the TBECTRL2 register. + */ +__INLINE uint8_t mdm_td_adjust_40_short_gi_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TBECTRL2_ADDR); + return ((localVal & ((uint32_t)0x0F000000)) >> 24); +} + +/** + * @brief Sets the TDAdjust40ShortGI field of the TBECTRL2 register. + * + * The TBECTRL2 register will be read, modified to contain the new field value, and written. + * + * @param[in] tdadjust40shortgi - The value to set the field to. + */ +__INLINE void mdm_td_adjust_40_short_gi_setf(uint8_t tdadjust40shortgi) +{ + ASSERT_ERR((((uint32_t)tdadjust40shortgi << 24) & ~((uint32_t)0x0F000000)) == 0); + REG_PL_WR(MDM_TBECTRL2_ADDR, (REG_PL_RD(MDM_TBECTRL2_ADDR) & ~((uint32_t)0x0F000000)) | ((uint32_t)tdadjust40shortgi << 24)); +} + +/** + * @brief Returns the current value of the TDAdjust20ShortGI field in the TBECTRL2 register. + * + * The TBECTRL2 register will be read and the TDAdjust20ShortGI field's value will be returned. + * + * @return The current value of the TDAdjust20ShortGI field in the TBECTRL2 register. + */ +__INLINE uint8_t mdm_td_adjust_20_short_gi_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TBECTRL2_ADDR); + return ((localVal & ((uint32_t)0x00F00000)) >> 20); +} + +/** + * @brief Sets the TDAdjust20ShortGI field of the TBECTRL2 register. + * + * The TBECTRL2 register will be read, modified to contain the new field value, and written. + * + * @param[in] tdadjust20shortgi - The value to set the field to. + */ +__INLINE void mdm_td_adjust_20_short_gi_setf(uint8_t tdadjust20shortgi) +{ + ASSERT_ERR((((uint32_t)tdadjust20shortgi << 20) & ~((uint32_t)0x00F00000)) == 0); + REG_PL_WR(MDM_TBECTRL2_ADDR, (REG_PL_RD(MDM_TBECTRL2_ADDR) & ~((uint32_t)0x00F00000)) | ((uint32_t)tdadjust20shortgi << 20)); +} + +/** + * @brief Returns the current value of the PeakSearchDelta field in the TBECTRL2 register. + * + * The TBECTRL2 register will be read and the PeakSearchDelta field's value will be returned. + * + * @return The current value of the PeakSearchDelta field in the TBECTRL2 register. + */ +__INLINE uint8_t mdm_peak_search_delta_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TBECTRL2_ADDR); + return ((localVal & ((uint32_t)0x0001F000)) >> 12); +} + +/** + * @brief Sets the PeakSearchDelta field of the TBECTRL2 register. + * + * The TBECTRL2 register will be read, modified to contain the new field value, and written. + * + * @param[in] peaksearchdelta - The value to set the field to. + */ +__INLINE void mdm_peak_search_delta_setf(uint8_t peaksearchdelta) +{ + ASSERT_ERR((((uint32_t)peaksearchdelta << 12) & ~((uint32_t)0x0001F000)) == 0); + REG_PL_WR(MDM_TBECTRL2_ADDR, (REG_PL_RD(MDM_TBECTRL2_ADDR) & ~((uint32_t)0x0001F000)) | ((uint32_t)peaksearchdelta << 12)); +} + +/** + * @brief Returns the current value of the TBEBias field in the TBECTRL2 register. + * + * The TBECTRL2 register will be read and the TBEBias field's value will be returned. + * + * @return The current value of the TBEBias field in the TBECTRL2 register. + */ +__INLINE uint8_t mdm_tbe_bias_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TBECTRL2_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +/** + * @brief Sets the TBEBias field of the TBECTRL2 register. + * + * The TBECTRL2 register will be read, modified to contain the new field value, and written. + * + * @param[in] tbebias - The value to set the field to. + */ +__INLINE void mdm_tbe_bias_setf(uint8_t tbebias) +{ + ASSERT_ERR((((uint32_t)tbebias << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(MDM_TBECTRL2_ADDR, (REG_PL_RD(MDM_TBECTRL2_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)tbebias << 0)); +} + +/// @} + +/** + * @name TDFOCTRL0 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  21:12   AutoCorrCompareRatioHighSNR   0x200
+ *  09:00   AutoCorrCompareRatioLowSNR   0x19A
+ * 
+ * + * @{ + */ + +/// Address of the TDFOCTRL0 register +#define MDM_TDFOCTRL0_ADDR 0x0100086C +/// Offset of the TDFOCTRL0 register from the base address +#define MDM_TDFOCTRL0_OFFSET 0x0000086C +/// Index of the TDFOCTRL0 register +#define MDM_TDFOCTRL0_INDEX 0x0000021B +/// Reset value of the TDFOCTRL0 register +#define MDM_TDFOCTRL0_RESET 0x0020019A + +/** + * @brief Returns the current value of the TDFOCTRL0 register. + * The TDFOCTRL0 register will be read and its value returned. + * @return The current value of the TDFOCTRL0 register. + */ +__INLINE uint32_t mdm_tdfoctrl0_get(void) +{ + return REG_PL_RD(MDM_TDFOCTRL0_ADDR); +} + +/** + * @brief Sets the TDFOCTRL0 register to a value. + * The TDFOCTRL0 register will be written. + * @param value - The value to write. + */ +__INLINE void mdm_tdfoctrl0_set(uint32_t value) +{ + REG_PL_WR(MDM_TDFOCTRL0_ADDR, value); +} + +// field definitions +/// AUTO_CORR_COMPARE_RATIO_HIGH_SNR field mask +#define MDM_AUTO_CORR_COMPARE_RATIO_HIGH_SNR_MASK ((uint32_t)0x003FF000) +/// AUTO_CORR_COMPARE_RATIO_HIGH_SNR field LSB position +#define MDM_AUTO_CORR_COMPARE_RATIO_HIGH_SNR_LSB 12 +/// AUTO_CORR_COMPARE_RATIO_HIGH_SNR field width +#define MDM_AUTO_CORR_COMPARE_RATIO_HIGH_SNR_WIDTH ((uint32_t)0x0000000A) +/// AUTO_CORR_COMPARE_RATIO_LOW_SNR field mask +#define MDM_AUTO_CORR_COMPARE_RATIO_LOW_SNR_MASK ((uint32_t)0x000003FF) +/// AUTO_CORR_COMPARE_RATIO_LOW_SNR field LSB position +#define MDM_AUTO_CORR_COMPARE_RATIO_LOW_SNR_LSB 0 +/// AUTO_CORR_COMPARE_RATIO_LOW_SNR field width +#define MDM_AUTO_CORR_COMPARE_RATIO_LOW_SNR_WIDTH ((uint32_t)0x0000000A) + +/// AUTO_CORR_COMPARE_RATIO_HIGH_SNR field reset value +#define MDM_AUTO_CORR_COMPARE_RATIO_HIGH_SNR_RST 0x200 +/// AUTO_CORR_COMPARE_RATIO_LOW_SNR field reset value +#define MDM_AUTO_CORR_COMPARE_RATIO_LOW_SNR_RST 0x19A + +/** + * @brief Constructs a value for the TDFOCTRL0 register given values for its fields + * and writes the value to the register. + * + * @param[in] autocorrcompareratiohighsnr - The value to use for the AutoCorrCompareRatioHighSNR field. + * @param[in] autocorrcompareratiolowsnr - The value to use for the AutoCorrCompareRatioLowSNR field. + */ +__INLINE void mdm_tdfoctrl0_pack(uint16_t autocorrcompareratiohighsnr, uint16_t autocorrcompareratiolowsnr) +{ + ASSERT_ERR((((uint32_t)autocorrcompareratiohighsnr << 12) & ~((uint32_t)0x003FF000)) == 0); + ASSERT_ERR((((uint32_t)autocorrcompareratiolowsnr << 0) & ~((uint32_t)0x000003FF)) == 0); + REG_PL_WR(MDM_TDFOCTRL0_ADDR, ((uint32_t)autocorrcompareratiohighsnr << 12) | ((uint32_t)autocorrcompareratiolowsnr << 0)); +} + +/** + * @brief Unpacks TDFOCTRL0's fields from current value of the TDFOCTRL0 register. + * + * Reads the TDFOCTRL0 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] autocorrcompareratiohighsnr - Will be populated with the current value of this field from the register. + * @param[out] autocorrcompareratiolowsnr - Will be populated with the current value of this field from the register. + */ +__INLINE void mdm_tdfoctrl0_unpack(uint16_t *autocorrcompareratiohighsnr, uint16_t *autocorrcompareratiolowsnr) +{ + uint32_t localVal = REG_PL_RD(MDM_TDFOCTRL0_ADDR); + + *autocorrcompareratiohighsnr = (localVal & ((uint32_t)0x003FF000)) >> 12; + *autocorrcompareratiolowsnr = (localVal & ((uint32_t)0x000003FF)) >> 0; +} + +/** + * @brief Returns the current value of the AutoCorrCompareRatioHighSNR field in the TDFOCTRL0 register. + * + * The TDFOCTRL0 register will be read and the AutoCorrCompareRatioHighSNR field's value will be returned. + * + * @return The current value of the AutoCorrCompareRatioHighSNR field in the TDFOCTRL0 register. + */ +__INLINE uint16_t mdm_auto_corr_compare_ratio_high_snr_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TDFOCTRL0_ADDR); + return ((localVal & ((uint32_t)0x003FF000)) >> 12); +} + +/** + * @brief Sets the AutoCorrCompareRatioHighSNR field of the TDFOCTRL0 register. + * + * The TDFOCTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] autocorrcompareratiohighsnr - The value to set the field to. + */ +__INLINE void mdm_auto_corr_compare_ratio_high_snr_setf(uint16_t autocorrcompareratiohighsnr) +{ + ASSERT_ERR((((uint32_t)autocorrcompareratiohighsnr << 12) & ~((uint32_t)0x003FF000)) == 0); + REG_PL_WR(MDM_TDFOCTRL0_ADDR, (REG_PL_RD(MDM_TDFOCTRL0_ADDR) & ~((uint32_t)0x003FF000)) | ((uint32_t)autocorrcompareratiohighsnr << 12)); +} + +/** + * @brief Returns the current value of the AutoCorrCompareRatioLowSNR field in the TDFOCTRL0 register. + * + * The TDFOCTRL0 register will be read and the AutoCorrCompareRatioLowSNR field's value will be returned. + * + * @return The current value of the AutoCorrCompareRatioLowSNR field in the TDFOCTRL0 register. + */ +__INLINE uint16_t mdm_auto_corr_compare_ratio_low_snr_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TDFOCTRL0_ADDR); + return ((localVal & ((uint32_t)0x000003FF)) >> 0); +} + +/** + * @brief Sets the AutoCorrCompareRatioLowSNR field of the TDFOCTRL0 register. + * + * The TDFOCTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] autocorrcompareratiolowsnr - The value to set the field to. + */ +__INLINE void mdm_auto_corr_compare_ratio_low_snr_setf(uint16_t autocorrcompareratiolowsnr) +{ + ASSERT_ERR((((uint32_t)autocorrcompareratiolowsnr << 0) & ~((uint32_t)0x000003FF)) == 0); + REG_PL_WR(MDM_TDFOCTRL0_ADDR, (REG_PL_RD(MDM_TDFOCTRL0_ADDR) & ~((uint32_t)0x000003FF)) | ((uint32_t)autocorrcompareratiolowsnr << 0)); +} + +/// @} + +/** + * @name TDFOCTRL1 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  20:12   AutoCorrPlatSumEnd   0x42
+ *  08:00   AutoCorrPlatSumStart   0x32
+ * 
+ * + * @{ + */ + +/// Address of the TDFOCTRL1 register +#define MDM_TDFOCTRL1_ADDR 0x01000870 +/// Offset of the TDFOCTRL1 register from the base address +#define MDM_TDFOCTRL1_OFFSET 0x00000870 +/// Index of the TDFOCTRL1 register +#define MDM_TDFOCTRL1_INDEX 0x0000021C +/// Reset value of the TDFOCTRL1 register +#define MDM_TDFOCTRL1_RESET 0x00042032 + +/** + * @brief Returns the current value of the TDFOCTRL1 register. + * The TDFOCTRL1 register will be read and its value returned. + * @return The current value of the TDFOCTRL1 register. + */ +__INLINE uint32_t mdm_tdfoctrl1_get(void) +{ + return REG_PL_RD(MDM_TDFOCTRL1_ADDR); +} + +/** + * @brief Sets the TDFOCTRL1 register to a value. + * The TDFOCTRL1 register will be written. + * @param value - The value to write. + */ +__INLINE void mdm_tdfoctrl1_set(uint32_t value) +{ + REG_PL_WR(MDM_TDFOCTRL1_ADDR, value); +} + +// field definitions +/// AUTO_CORR_PLAT_SUM_END field mask +#define MDM_AUTO_CORR_PLAT_SUM_END_MASK ((uint32_t)0x001FF000) +/// AUTO_CORR_PLAT_SUM_END field LSB position +#define MDM_AUTO_CORR_PLAT_SUM_END_LSB 12 +/// AUTO_CORR_PLAT_SUM_END field width +#define MDM_AUTO_CORR_PLAT_SUM_END_WIDTH ((uint32_t)0x00000009) +/// AUTO_CORR_PLAT_SUM_START field mask +#define MDM_AUTO_CORR_PLAT_SUM_START_MASK ((uint32_t)0x000001FF) +/// AUTO_CORR_PLAT_SUM_START field LSB position +#define MDM_AUTO_CORR_PLAT_SUM_START_LSB 0 +/// AUTO_CORR_PLAT_SUM_START field width +#define MDM_AUTO_CORR_PLAT_SUM_START_WIDTH ((uint32_t)0x00000009) + +/// AUTO_CORR_PLAT_SUM_END field reset value +#define MDM_AUTO_CORR_PLAT_SUM_END_RST 0x42 +/// AUTO_CORR_PLAT_SUM_START field reset value +#define MDM_AUTO_CORR_PLAT_SUM_START_RST 0x32 + +/** + * @brief Constructs a value for the TDFOCTRL1 register given values for its fields + * and writes the value to the register. + * + * @param[in] autocorrplatsumend - The value to use for the AutoCorrPlatSumEnd field. + * @param[in] autocorrplatsumstart - The value to use for the AutoCorrPlatSumStart field. + */ +__INLINE void mdm_tdfoctrl1_pack(uint16_t autocorrplatsumend, uint16_t autocorrplatsumstart) +{ + ASSERT_ERR((((uint32_t)autocorrplatsumend << 12) & ~((uint32_t)0x001FF000)) == 0); + ASSERT_ERR((((uint32_t)autocorrplatsumstart << 0) & ~((uint32_t)0x000001FF)) == 0); + REG_PL_WR(MDM_TDFOCTRL1_ADDR, ((uint32_t)autocorrplatsumend << 12) | ((uint32_t)autocorrplatsumstart << 0)); +} + +/** + * @brief Unpacks TDFOCTRL1's fields from current value of the TDFOCTRL1 register. + * + * Reads the TDFOCTRL1 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] autocorrplatsumend - Will be populated with the current value of this field from the register. + * @param[out] autocorrplatsumstart - Will be populated with the current value of this field from the register. + */ +__INLINE void mdm_tdfoctrl1_unpack(uint16_t *autocorrplatsumend, uint16_t *autocorrplatsumstart) +{ + uint32_t localVal = REG_PL_RD(MDM_TDFOCTRL1_ADDR); + + *autocorrplatsumend = (localVal & ((uint32_t)0x001FF000)) >> 12; + *autocorrplatsumstart = (localVal & ((uint32_t)0x000001FF)) >> 0; +} + +/** + * @brief Returns the current value of the AutoCorrPlatSumEnd field in the TDFOCTRL1 register. + * + * The TDFOCTRL1 register will be read and the AutoCorrPlatSumEnd field's value will be returned. + * + * @return The current value of the AutoCorrPlatSumEnd field in the TDFOCTRL1 register. + */ +__INLINE uint16_t mdm_auto_corr_plat_sum_end_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TDFOCTRL1_ADDR); + return ((localVal & ((uint32_t)0x001FF000)) >> 12); +} + +/** + * @brief Sets the AutoCorrPlatSumEnd field of the TDFOCTRL1 register. + * + * The TDFOCTRL1 register will be read, modified to contain the new field value, and written. + * + * @param[in] autocorrplatsumend - The value to set the field to. + */ +__INLINE void mdm_auto_corr_plat_sum_end_setf(uint16_t autocorrplatsumend) +{ + ASSERT_ERR((((uint32_t)autocorrplatsumend << 12) & ~((uint32_t)0x001FF000)) == 0); + REG_PL_WR(MDM_TDFOCTRL1_ADDR, (REG_PL_RD(MDM_TDFOCTRL1_ADDR) & ~((uint32_t)0x001FF000)) | ((uint32_t)autocorrplatsumend << 12)); +} + +/** + * @brief Returns the current value of the AutoCorrPlatSumStart field in the TDFOCTRL1 register. + * + * The TDFOCTRL1 register will be read and the AutoCorrPlatSumStart field's value will be returned. + * + * @return The current value of the AutoCorrPlatSumStart field in the TDFOCTRL1 register. + */ +__INLINE uint16_t mdm_auto_corr_plat_sum_start_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TDFOCTRL1_ADDR); + return ((localVal & ((uint32_t)0x000001FF)) >> 0); +} + +/** + * @brief Sets the AutoCorrPlatSumStart field of the TDFOCTRL1 register. + * + * The TDFOCTRL1 register will be read, modified to contain the new field value, and written. + * + * @param[in] autocorrplatsumstart - The value to set the field to. + */ +__INLINE void mdm_auto_corr_plat_sum_start_setf(uint16_t autocorrplatsumstart) +{ + ASSERT_ERR((((uint32_t)autocorrplatsumstart << 0) & ~((uint32_t)0x000001FF)) == 0); + REG_PL_WR(MDM_TDFOCTRL1_ADDR, (REG_PL_RD(MDM_TDFOCTRL1_ADDR) & ~((uint32_t)0x000001FF)) | ((uint32_t)autocorrplatsumstart << 0)); +} + +/// @} + +/** + * @name TDFOCTRL2 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  28:20     AutoCorrPhSumEnd   0x4C
+ *  18:10   AutoCorrPhSumStart   0x1C
+ *  08:00   AutoCorrPlatFallSearchStart   0x44
+ * 
+ * + * @{ + */ + +/// Address of the TDFOCTRL2 register +#define MDM_TDFOCTRL2_ADDR 0x01000874 +/// Offset of the TDFOCTRL2 register from the base address +#define MDM_TDFOCTRL2_OFFSET 0x00000874 +/// Index of the TDFOCTRL2 register +#define MDM_TDFOCTRL2_INDEX 0x0000021D +/// Reset value of the TDFOCTRL2 register +#define MDM_TDFOCTRL2_RESET 0x04C07044 + +/** + * @brief Returns the current value of the TDFOCTRL2 register. + * The TDFOCTRL2 register will be read and its value returned. + * @return The current value of the TDFOCTRL2 register. + */ +__INLINE uint32_t mdm_tdfoctrl2_get(void) +{ + return REG_PL_RD(MDM_TDFOCTRL2_ADDR); +} + +/** + * @brief Sets the TDFOCTRL2 register to a value. + * The TDFOCTRL2 register will be written. + * @param value - The value to write. + */ +__INLINE void mdm_tdfoctrl2_set(uint32_t value) +{ + REG_PL_WR(MDM_TDFOCTRL2_ADDR, value); +} + +// field definitions +/// AUTO_CORR_PH_SUM_END field mask +#define MDM_AUTO_CORR_PH_SUM_END_MASK ((uint32_t)0x1FF00000) +/// AUTO_CORR_PH_SUM_END field LSB position +#define MDM_AUTO_CORR_PH_SUM_END_LSB 20 +/// AUTO_CORR_PH_SUM_END field width +#define MDM_AUTO_CORR_PH_SUM_END_WIDTH ((uint32_t)0x00000009) +/// AUTO_CORR_PH_SUM_START field mask +#define MDM_AUTO_CORR_PH_SUM_START_MASK ((uint32_t)0x0007FC00) +/// AUTO_CORR_PH_SUM_START field LSB position +#define MDM_AUTO_CORR_PH_SUM_START_LSB 10 +/// AUTO_CORR_PH_SUM_START field width +#define MDM_AUTO_CORR_PH_SUM_START_WIDTH ((uint32_t)0x00000009) +/// AUTO_CORR_PLAT_FALL_SEARCH_START field mask +#define MDM_AUTO_CORR_PLAT_FALL_SEARCH_START_MASK ((uint32_t)0x000001FF) +/// AUTO_CORR_PLAT_FALL_SEARCH_START field LSB position +#define MDM_AUTO_CORR_PLAT_FALL_SEARCH_START_LSB 0 +/// AUTO_CORR_PLAT_FALL_SEARCH_START field width +#define MDM_AUTO_CORR_PLAT_FALL_SEARCH_START_WIDTH ((uint32_t)0x00000009) + +/// AUTO_CORR_PH_SUM_END field reset value +#define MDM_AUTO_CORR_PH_SUM_END_RST 0x4C +/// AUTO_CORR_PH_SUM_START field reset value +#define MDM_AUTO_CORR_PH_SUM_START_RST 0x1C +/// AUTO_CORR_PLAT_FALL_SEARCH_START field reset value +#define MDM_AUTO_CORR_PLAT_FALL_SEARCH_START_RST 0x44 + +/** + * @brief Constructs a value for the TDFOCTRL2 register given values for its fields + * and writes the value to the register. + * + * @param[in] autocorrphsumend - The value to use for the AutoCorrPhSumEnd field. + * @param[in] autocorrphsumstart - The value to use for the AutoCorrPhSumStart field. + * @param[in] autocorrplatfallsearchstart - The value to use for the AutoCorrPlatFallSearchStart field. + */ +__INLINE void mdm_tdfoctrl2_pack(uint16_t autocorrphsumend, uint16_t autocorrphsumstart, uint16_t autocorrplatfallsearchstart) +{ + ASSERT_ERR((((uint32_t)autocorrphsumend << 20) & ~((uint32_t)0x1FF00000)) == 0); + ASSERT_ERR((((uint32_t)autocorrphsumstart << 10) & ~((uint32_t)0x0007FC00)) == 0); + ASSERT_ERR((((uint32_t)autocorrplatfallsearchstart << 0) & ~((uint32_t)0x000001FF)) == 0); + REG_PL_WR(MDM_TDFOCTRL2_ADDR, ((uint32_t)autocorrphsumend << 20) | ((uint32_t)autocorrphsumstart << 10) | ((uint32_t)autocorrplatfallsearchstart << 0)); +} + +/** + * @brief Unpacks TDFOCTRL2's fields from current value of the TDFOCTRL2 register. + * + * Reads the TDFOCTRL2 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] autocorrphsumend - Will be populated with the current value of this field from the register. + * @param[out] autocorrphsumstart - Will be populated with the current value of this field from the register. + * @param[out] autocorrplatfallsearchstart - Will be populated with the current value of this field from the register. + */ +__INLINE void mdm_tdfoctrl2_unpack(uint16_t *autocorrphsumend, uint16_t *autocorrphsumstart, uint16_t *autocorrplatfallsearchstart) +{ + uint32_t localVal = REG_PL_RD(MDM_TDFOCTRL2_ADDR); + + *autocorrphsumend = (localVal & ((uint32_t)0x1FF00000)) >> 20; + *autocorrphsumstart = (localVal & ((uint32_t)0x0007FC00)) >> 10; + *autocorrplatfallsearchstart = (localVal & ((uint32_t)0x000001FF)) >> 0; +} + +/** + * @brief Returns the current value of the AutoCorrPhSumEnd field in the TDFOCTRL2 register. + * + * The TDFOCTRL2 register will be read and the AutoCorrPhSumEnd field's value will be returned. + * + * @return The current value of the AutoCorrPhSumEnd field in the TDFOCTRL2 register. + */ +__INLINE uint16_t mdm_auto_corr_ph_sum_end_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TDFOCTRL2_ADDR); + return ((localVal & ((uint32_t)0x1FF00000)) >> 20); +} + +/** + * @brief Sets the AutoCorrPhSumEnd field of the TDFOCTRL2 register. + * + * The TDFOCTRL2 register will be read, modified to contain the new field value, and written. + * + * @param[in] autocorrphsumend - The value to set the field to. + */ +__INLINE void mdm_auto_corr_ph_sum_end_setf(uint16_t autocorrphsumend) +{ + ASSERT_ERR((((uint32_t)autocorrphsumend << 20) & ~((uint32_t)0x1FF00000)) == 0); + REG_PL_WR(MDM_TDFOCTRL2_ADDR, (REG_PL_RD(MDM_TDFOCTRL2_ADDR) & ~((uint32_t)0x1FF00000)) | ((uint32_t)autocorrphsumend << 20)); +} + +/** + * @brief Returns the current value of the AutoCorrPhSumStart field in the TDFOCTRL2 register. + * + * The TDFOCTRL2 register will be read and the AutoCorrPhSumStart field's value will be returned. + * + * @return The current value of the AutoCorrPhSumStart field in the TDFOCTRL2 register. + */ +__INLINE uint16_t mdm_auto_corr_ph_sum_start_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TDFOCTRL2_ADDR); + return ((localVal & ((uint32_t)0x0007FC00)) >> 10); +} + +/** + * @brief Sets the AutoCorrPhSumStart field of the TDFOCTRL2 register. + * + * The TDFOCTRL2 register will be read, modified to contain the new field value, and written. + * + * @param[in] autocorrphsumstart - The value to set the field to. + */ +__INLINE void mdm_auto_corr_ph_sum_start_setf(uint16_t autocorrphsumstart) +{ + ASSERT_ERR((((uint32_t)autocorrphsumstart << 10) & ~((uint32_t)0x0007FC00)) == 0); + REG_PL_WR(MDM_TDFOCTRL2_ADDR, (REG_PL_RD(MDM_TDFOCTRL2_ADDR) & ~((uint32_t)0x0007FC00)) | ((uint32_t)autocorrphsumstart << 10)); +} + +/** + * @brief Returns the current value of the AutoCorrPlatFallSearchStart field in the TDFOCTRL2 register. + * + * The TDFOCTRL2 register will be read and the AutoCorrPlatFallSearchStart field's value will be returned. + * + * @return The current value of the AutoCorrPlatFallSearchStart field in the TDFOCTRL2 register. + */ +__INLINE uint16_t mdm_auto_corr_plat_fall_search_start_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TDFOCTRL2_ADDR); + return ((localVal & ((uint32_t)0x000001FF)) >> 0); +} + +/** + * @brief Sets the AutoCorrPlatFallSearchStart field of the TDFOCTRL2 register. + * + * The TDFOCTRL2 register will be read, modified to contain the new field value, and written. + * + * @param[in] autocorrplatfallsearchstart - The value to set the field to. + */ +__INLINE void mdm_auto_corr_plat_fall_search_start_setf(uint16_t autocorrplatfallsearchstart) +{ + ASSERT_ERR((((uint32_t)autocorrplatfallsearchstart << 0) & ~((uint32_t)0x000001FF)) == 0); + REG_PL_WR(MDM_TDFOCTRL2_ADDR, (REG_PL_RD(MDM_TDFOCTRL2_ADDR) & ~((uint32_t)0x000001FF)) | ((uint32_t)autocorrplatfallsearchstart << 0)); +} + +/// @} + +/** + * @name TDFOCTRL3 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  23:12   TDFOPlatFallTimeOut   0x1F4
+ *  11:04     TDFOSNRThreshold   0xC
+ *  03:00    AutoCorrFallCount   0x1
+ * 
+ * + * @{ + */ + +/// Address of the TDFOCTRL3 register +#define MDM_TDFOCTRL3_ADDR 0x01000878 +/// Offset of the TDFOCTRL3 register from the base address +#define MDM_TDFOCTRL3_OFFSET 0x00000878 +/// Index of the TDFOCTRL3 register +#define MDM_TDFOCTRL3_INDEX 0x0000021E +/// Reset value of the TDFOCTRL3 register +#define MDM_TDFOCTRL3_RESET 0x001F40C1 + +/** + * @brief Returns the current value of the TDFOCTRL3 register. + * The TDFOCTRL3 register will be read and its value returned. + * @return The current value of the TDFOCTRL3 register. + */ +__INLINE uint32_t mdm_tdfoctrl3_get(void) +{ + return REG_PL_RD(MDM_TDFOCTRL3_ADDR); +} + +/** + * @brief Sets the TDFOCTRL3 register to a value. + * The TDFOCTRL3 register will be written. + * @param value - The value to write. + */ +__INLINE void mdm_tdfoctrl3_set(uint32_t value) +{ + REG_PL_WR(MDM_TDFOCTRL3_ADDR, value); +} + +// field definitions +/// TDFO_PLAT_FALL_TIME_OUT field mask +#define MDM_TDFO_PLAT_FALL_TIME_OUT_MASK ((uint32_t)0x00FFF000) +/// TDFO_PLAT_FALL_TIME_OUT field LSB position +#define MDM_TDFO_PLAT_FALL_TIME_OUT_LSB 12 +/// TDFO_PLAT_FALL_TIME_OUT field width +#define MDM_TDFO_PLAT_FALL_TIME_OUT_WIDTH ((uint32_t)0x0000000C) +/// TDFOSNR_THRESHOLD field mask +#define MDM_TDFOSNR_THRESHOLD_MASK ((uint32_t)0x00000FF0) +/// TDFOSNR_THRESHOLD field LSB position +#define MDM_TDFOSNR_THRESHOLD_LSB 4 +/// TDFOSNR_THRESHOLD field width +#define MDM_TDFOSNR_THRESHOLD_WIDTH ((uint32_t)0x00000008) +/// AUTO_CORR_FALL_COUNT field mask +#define MDM_AUTO_CORR_FALL_COUNT_MASK ((uint32_t)0x0000000F) +/// AUTO_CORR_FALL_COUNT field LSB position +#define MDM_AUTO_CORR_FALL_COUNT_LSB 0 +/// AUTO_CORR_FALL_COUNT field width +#define MDM_AUTO_CORR_FALL_COUNT_WIDTH ((uint32_t)0x00000004) + +/// TDFO_PLAT_FALL_TIME_OUT field reset value +#define MDM_TDFO_PLAT_FALL_TIME_OUT_RST 0x1F4 +/// TDFOSNR_THRESHOLD field reset value +#define MDM_TDFOSNR_THRESHOLD_RST 0xC +/// AUTO_CORR_FALL_COUNT field reset value +#define MDM_AUTO_CORR_FALL_COUNT_RST 0x1 + +/** + * @brief Constructs a value for the TDFOCTRL3 register given values for its fields + * and writes the value to the register. + * + * @param[in] tdfoplatfalltimeout - The value to use for the TDFOPlatFallTimeOut field. + * @param[in] tdfosnrthreshold - The value to use for the TDFOSNRThreshold field. + * @param[in] autocorrfallcount - The value to use for the AutoCorrFallCount field. + */ +__INLINE void mdm_tdfoctrl3_pack(uint16_t tdfoplatfalltimeout, uint8_t tdfosnrthreshold, uint8_t autocorrfallcount) +{ + ASSERT_ERR((((uint32_t)tdfoplatfalltimeout << 12) & ~((uint32_t)0x00FFF000)) == 0); + ASSERT_ERR((((uint32_t)tdfosnrthreshold << 4) & ~((uint32_t)0x00000FF0)) == 0); + ASSERT_ERR((((uint32_t)autocorrfallcount << 0) & ~((uint32_t)0x0000000F)) == 0); + REG_PL_WR(MDM_TDFOCTRL3_ADDR, ((uint32_t)tdfoplatfalltimeout << 12) | ((uint32_t)tdfosnrthreshold << 4) | ((uint32_t)autocorrfallcount << 0)); +} + +/** + * @brief Unpacks TDFOCTRL3's fields from current value of the TDFOCTRL3 register. + * + * Reads the TDFOCTRL3 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] tdfoplatfalltimeout - Will be populated with the current value of this field from the register. + * @param[out] tdfosnrthreshold - Will be populated with the current value of this field from the register. + * @param[out] autocorrfallcount - Will be populated with the current value of this field from the register. + */ +__INLINE void mdm_tdfoctrl3_unpack(uint16_t *tdfoplatfalltimeout, uint8_t *tdfosnrthreshold, uint8_t *autocorrfallcount) +{ + uint32_t localVal = REG_PL_RD(MDM_TDFOCTRL3_ADDR); + + *tdfoplatfalltimeout = (localVal & ((uint32_t)0x00FFF000)) >> 12; + *tdfosnrthreshold = (localVal & ((uint32_t)0x00000FF0)) >> 4; + *autocorrfallcount = (localVal & ((uint32_t)0x0000000F)) >> 0; +} + +/** + * @brief Returns the current value of the TDFOPlatFallTimeOut field in the TDFOCTRL3 register. + * + * The TDFOCTRL3 register will be read and the TDFOPlatFallTimeOut field's value will be returned. + * + * @return The current value of the TDFOPlatFallTimeOut field in the TDFOCTRL3 register. + */ +__INLINE uint16_t mdm_tdfo_plat_fall_time_out_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TDFOCTRL3_ADDR); + return ((localVal & ((uint32_t)0x00FFF000)) >> 12); +} + +/** + * @brief Sets the TDFOPlatFallTimeOut field of the TDFOCTRL3 register. + * + * The TDFOCTRL3 register will be read, modified to contain the new field value, and written. + * + * @param[in] tdfoplatfalltimeout - The value to set the field to. + */ +__INLINE void mdm_tdfo_plat_fall_time_out_setf(uint16_t tdfoplatfalltimeout) +{ + ASSERT_ERR((((uint32_t)tdfoplatfalltimeout << 12) & ~((uint32_t)0x00FFF000)) == 0); + REG_PL_WR(MDM_TDFOCTRL3_ADDR, (REG_PL_RD(MDM_TDFOCTRL3_ADDR) & ~((uint32_t)0x00FFF000)) | ((uint32_t)tdfoplatfalltimeout << 12)); +} + +/** + * @brief Returns the current value of the TDFOSNRThreshold field in the TDFOCTRL3 register. + * + * The TDFOCTRL3 register will be read and the TDFOSNRThreshold field's value will be returned. + * + * @return The current value of the TDFOSNRThreshold field in the TDFOCTRL3 register. + */ +__INLINE uint8_t mdm_tdfosnr_threshold_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TDFOCTRL3_ADDR); + return ((localVal & ((uint32_t)0x00000FF0)) >> 4); +} + +/** + * @brief Sets the TDFOSNRThreshold field of the TDFOCTRL3 register. + * + * The TDFOCTRL3 register will be read, modified to contain the new field value, and written. + * + * @param[in] tdfosnrthreshold - The value to set the field to. + */ +__INLINE void mdm_tdfosnr_threshold_setf(uint8_t tdfosnrthreshold) +{ + ASSERT_ERR((((uint32_t)tdfosnrthreshold << 4) & ~((uint32_t)0x00000FF0)) == 0); + REG_PL_WR(MDM_TDFOCTRL3_ADDR, (REG_PL_RD(MDM_TDFOCTRL3_ADDR) & ~((uint32_t)0x00000FF0)) | ((uint32_t)tdfosnrthreshold << 4)); +} + +/** + * @brief Returns the current value of the AutoCorrFallCount field in the TDFOCTRL3 register. + * + * The TDFOCTRL3 register will be read and the AutoCorrFallCount field's value will be returned. + * + * @return The current value of the AutoCorrFallCount field in the TDFOCTRL3 register. + */ +__INLINE uint8_t mdm_auto_corr_fall_count_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TDFOCTRL3_ADDR); + return ((localVal & ((uint32_t)0x0000000F)) >> 0); +} + +/** + * @brief Sets the AutoCorrFallCount field of the TDFOCTRL3 register. + * + * The TDFOCTRL3 register will be read, modified to contain the new field value, and written. + * + * @param[in] autocorrfallcount - The value to set the field to. + */ +__INLINE void mdm_auto_corr_fall_count_setf(uint8_t autocorrfallcount) +{ + ASSERT_ERR((((uint32_t)autocorrfallcount << 0) & ~((uint32_t)0x0000000F)) == 0); + REG_PL_WR(MDM_TDFOCTRL3_ADDR, (REG_PL_RD(MDM_TDFOCTRL3_ADDR) & ~((uint32_t)0x0000000F)) | ((uint32_t)autocorrfallcount << 0)); +} + +/// @} + +/** + * @name CLKGATEFCTRL0 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31        PHYTXCLKFORCE   0
+ *     30        PHYRXCLKFORCE   0
+ *     29       AGCMEMCLKFORCE   0
+ *     28          AGCCLKFORCE   0
+ *     27          FE3CLKFORCE   0
+ *     26          FE2CLKFORCE   0
+ *     25          FE1CLKFORCE   0
+ *     24          FE0CLKFORCE   0
+ *     23       STOCPECLKFORCE   0
+ *     22          EQUCLKFORCE   0
+ *     21      TDCOMP3CLKFORCE   0
+ *     20      TDCOMP2CLKFORCE   0
+ *     19      TDCOMP1CLKFORCE   0
+ *     18      TDCOMP0CLKFORCE   0
+ *     17      TDFOESTCLKFORCE   0
+ *     16          TBECLKFORCE   0
+ *     15          VTBCLKFORCE   0
+ *     14      FFT3MEMCLKFORCE   0
+ *     13         FFT3CLKFORCE   0
+ *     12      FFT2MEMCLKFORCE   0
+ *     11         FFT2CLKFORCE   0
+ *     10      FFT1MEMCLKFORCE   0
+ *     09         FFT1CLKFORCE   0
+ *     08      FFT0MEMCLKFORCE   0
+ *     07         FFT0CLKFORCE   0
+ *     06        CHESTCLKFORCE   0
+ *     05         GMEMCLKFORCE   0
+ *     04         HMEMCLKFORCE   0
+ *     03         QMEMCLKFORCE   0
+ *     02     INTLVMEMCLKFORCE   0
+ *     01     INTLVVTBCLKFORCE   0
+ *     00     INTLVPHYCLKFORCE   0
+ * 
+ * + * @{ + */ + +/// Address of the CLKGATEFCTRL0 register +#define MDM_CLKGATEFCTRL0_ADDR 0x0100087C +/// Offset of the CLKGATEFCTRL0 register from the base address +#define MDM_CLKGATEFCTRL0_OFFSET 0x0000087C +/// Index of the CLKGATEFCTRL0 register +#define MDM_CLKGATEFCTRL0_INDEX 0x0000021F +/// Reset value of the CLKGATEFCTRL0 register +#define MDM_CLKGATEFCTRL0_RESET 0x00000000 + +/** + * @brief Returns the current value of the CLKGATEFCTRL0 register. + * The CLKGATEFCTRL0 register will be read and its value returned. + * @return The current value of the CLKGATEFCTRL0 register. + */ +__INLINE uint32_t mdm_clkgatefctrl0_get(void) +{ + return REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR); +} + +/** + * @brief Sets the CLKGATEFCTRL0 register to a value. + * The CLKGATEFCTRL0 register will be written. + * @param value - The value to write. + */ +__INLINE void mdm_clkgatefctrl0_set(uint32_t value) +{ + REG_PL_WR(MDM_CLKGATEFCTRL0_ADDR, value); +} + +// field definitions +/// PHYTXCLKFORCE field bit +#define MDM_PHYTXCLKFORCE_BIT ((uint32_t)0x80000000) +/// PHYTXCLKFORCE field position +#define MDM_PHYTXCLKFORCE_POS 31 +/// PHYRXCLKFORCE field bit +#define MDM_PHYRXCLKFORCE_BIT ((uint32_t)0x40000000) +/// PHYRXCLKFORCE field position +#define MDM_PHYRXCLKFORCE_POS 30 +/// AGCMEMCLKFORCE field bit +#define MDM_AGCMEMCLKFORCE_BIT ((uint32_t)0x20000000) +/// AGCMEMCLKFORCE field position +#define MDM_AGCMEMCLKFORCE_POS 29 +/// AGCCLKFORCE field bit +#define MDM_AGCCLKFORCE_BIT ((uint32_t)0x10000000) +/// AGCCLKFORCE field position +#define MDM_AGCCLKFORCE_POS 28 +/// FE3CLKFORCE field bit +#define MDM_FE3CLKFORCE_BIT ((uint32_t)0x08000000) +/// FE3CLKFORCE field position +#define MDM_FE3CLKFORCE_POS 27 +/// FE2CLKFORCE field bit +#define MDM_FE2CLKFORCE_BIT ((uint32_t)0x04000000) +/// FE2CLKFORCE field position +#define MDM_FE2CLKFORCE_POS 26 +/// FE1CLKFORCE field bit +#define MDM_FE1CLKFORCE_BIT ((uint32_t)0x02000000) +/// FE1CLKFORCE field position +#define MDM_FE1CLKFORCE_POS 25 +/// FE0CLKFORCE field bit +#define MDM_FE0CLKFORCE_BIT ((uint32_t)0x01000000) +/// FE0CLKFORCE field position +#define MDM_FE0CLKFORCE_POS 24 +/// STOCPECLKFORCE field bit +#define MDM_STOCPECLKFORCE_BIT ((uint32_t)0x00800000) +/// STOCPECLKFORCE field position +#define MDM_STOCPECLKFORCE_POS 23 +/// EQUCLKFORCE field bit +#define MDM_EQUCLKFORCE_BIT ((uint32_t)0x00400000) +/// EQUCLKFORCE field position +#define MDM_EQUCLKFORCE_POS 22 +/// TDCOMP3CLKFORCE field bit +#define MDM_TDCOMP3CLKFORCE_BIT ((uint32_t)0x00200000) +/// TDCOMP3CLKFORCE field position +#define MDM_TDCOMP3CLKFORCE_POS 21 +/// TDCOMP2CLKFORCE field bit +#define MDM_TDCOMP2CLKFORCE_BIT ((uint32_t)0x00100000) +/// TDCOMP2CLKFORCE field position +#define MDM_TDCOMP2CLKFORCE_POS 20 +/// TDCOMP1CLKFORCE field bit +#define MDM_TDCOMP1CLKFORCE_BIT ((uint32_t)0x00080000) +/// TDCOMP1CLKFORCE field position +#define MDM_TDCOMP1CLKFORCE_POS 19 +/// TDCOMP0CLKFORCE field bit +#define MDM_TDCOMP0CLKFORCE_BIT ((uint32_t)0x00040000) +/// TDCOMP0CLKFORCE field position +#define MDM_TDCOMP0CLKFORCE_POS 18 +/// TDFOESTCLKFORCE field bit +#define MDM_TDFOESTCLKFORCE_BIT ((uint32_t)0x00020000) +/// TDFOESTCLKFORCE field position +#define MDM_TDFOESTCLKFORCE_POS 17 +/// TBECLKFORCE field bit +#define MDM_TBECLKFORCE_BIT ((uint32_t)0x00010000) +/// TBECLKFORCE field position +#define MDM_TBECLKFORCE_POS 16 +/// VTBCLKFORCE field bit +#define MDM_VTBCLKFORCE_BIT ((uint32_t)0x00008000) +/// VTBCLKFORCE field position +#define MDM_VTBCLKFORCE_POS 15 +/// FFT3MEMCLKFORCE field bit +#define MDM_FFT3MEMCLKFORCE_BIT ((uint32_t)0x00004000) +/// FFT3MEMCLKFORCE field position +#define MDM_FFT3MEMCLKFORCE_POS 14 +/// FFT3CLKFORCE field bit +#define MDM_FFT3CLKFORCE_BIT ((uint32_t)0x00002000) +/// FFT3CLKFORCE field position +#define MDM_FFT3CLKFORCE_POS 13 +/// FFT2MEMCLKFORCE field bit +#define MDM_FFT2MEMCLKFORCE_BIT ((uint32_t)0x00001000) +/// FFT2MEMCLKFORCE field position +#define MDM_FFT2MEMCLKFORCE_POS 12 +/// FFT2CLKFORCE field bit +#define MDM_FFT2CLKFORCE_BIT ((uint32_t)0x00000800) +/// FFT2CLKFORCE field position +#define MDM_FFT2CLKFORCE_POS 11 +/// FFT1MEMCLKFORCE field bit +#define MDM_FFT1MEMCLKFORCE_BIT ((uint32_t)0x00000400) +/// FFT1MEMCLKFORCE field position +#define MDM_FFT1MEMCLKFORCE_POS 10 +/// FFT1CLKFORCE field bit +#define MDM_FFT1CLKFORCE_BIT ((uint32_t)0x00000200) +/// FFT1CLKFORCE field position +#define MDM_FFT1CLKFORCE_POS 9 +/// FFT0MEMCLKFORCE field bit +#define MDM_FFT0MEMCLKFORCE_BIT ((uint32_t)0x00000100) +/// FFT0MEMCLKFORCE field position +#define MDM_FFT0MEMCLKFORCE_POS 8 +/// FFT0CLKFORCE field bit +#define MDM_FFT0CLKFORCE_BIT ((uint32_t)0x00000080) +/// FFT0CLKFORCE field position +#define MDM_FFT0CLKFORCE_POS 7 +/// CHESTCLKFORCE field bit +#define MDM_CHESTCLKFORCE_BIT ((uint32_t)0x00000040) +/// CHESTCLKFORCE field position +#define MDM_CHESTCLKFORCE_POS 6 +/// GMEMCLKFORCE field bit +#define MDM_GMEMCLKFORCE_BIT ((uint32_t)0x00000020) +/// GMEMCLKFORCE field position +#define MDM_GMEMCLKFORCE_POS 5 +/// HMEMCLKFORCE field bit +#define MDM_HMEMCLKFORCE_BIT ((uint32_t)0x00000010) +/// HMEMCLKFORCE field position +#define MDM_HMEMCLKFORCE_POS 4 +/// QMEMCLKFORCE field bit +#define MDM_QMEMCLKFORCE_BIT ((uint32_t)0x00000008) +/// QMEMCLKFORCE field position +#define MDM_QMEMCLKFORCE_POS 3 +/// INTLVMEMCLKFORCE field bit +#define MDM_INTLVMEMCLKFORCE_BIT ((uint32_t)0x00000004) +/// INTLVMEMCLKFORCE field position +#define MDM_INTLVMEMCLKFORCE_POS 2 +/// INTLVVTBCLKFORCE field bit +#define MDM_INTLVVTBCLKFORCE_BIT ((uint32_t)0x00000002) +/// INTLVVTBCLKFORCE field position +#define MDM_INTLVVTBCLKFORCE_POS 1 +/// INTLVPHYCLKFORCE field bit +#define MDM_INTLVPHYCLKFORCE_BIT ((uint32_t)0x00000001) +/// INTLVPHYCLKFORCE field position +#define MDM_INTLVPHYCLKFORCE_POS 0 + +/// PHYTXCLKFORCE field reset value +#define MDM_PHYTXCLKFORCE_RST 0x0 +/// PHYRXCLKFORCE field reset value +#define MDM_PHYRXCLKFORCE_RST 0x0 +/// AGCMEMCLKFORCE field reset value +#define MDM_AGCMEMCLKFORCE_RST 0x0 +/// AGCCLKFORCE field reset value +#define MDM_AGCCLKFORCE_RST 0x0 +/// FE3CLKFORCE field reset value +#define MDM_FE3CLKFORCE_RST 0x0 +/// FE2CLKFORCE field reset value +#define MDM_FE2CLKFORCE_RST 0x0 +/// FE1CLKFORCE field reset value +#define MDM_FE1CLKFORCE_RST 0x0 +/// FE0CLKFORCE field reset value +#define MDM_FE0CLKFORCE_RST 0x0 +/// STOCPECLKFORCE field reset value +#define MDM_STOCPECLKFORCE_RST 0x0 +/// EQUCLKFORCE field reset value +#define MDM_EQUCLKFORCE_RST 0x0 +/// TDCOMP3CLKFORCE field reset value +#define MDM_TDCOMP3CLKFORCE_RST 0x0 +/// TDCOMP2CLKFORCE field reset value +#define MDM_TDCOMP2CLKFORCE_RST 0x0 +/// TDCOMP1CLKFORCE field reset value +#define MDM_TDCOMP1CLKFORCE_RST 0x0 +/// TDCOMP0CLKFORCE field reset value +#define MDM_TDCOMP0CLKFORCE_RST 0x0 +/// TDFOESTCLKFORCE field reset value +#define MDM_TDFOESTCLKFORCE_RST 0x0 +/// TBECLKFORCE field reset value +#define MDM_TBECLKFORCE_RST 0x0 +/// VTBCLKFORCE field reset value +#define MDM_VTBCLKFORCE_RST 0x0 +/// FFT3MEMCLKFORCE field reset value +#define MDM_FFT3MEMCLKFORCE_RST 0x0 +/// FFT3CLKFORCE field reset value +#define MDM_FFT3CLKFORCE_RST 0x0 +/// FFT2MEMCLKFORCE field reset value +#define MDM_FFT2MEMCLKFORCE_RST 0x0 +/// FFT2CLKFORCE field reset value +#define MDM_FFT2CLKFORCE_RST 0x0 +/// FFT1MEMCLKFORCE field reset value +#define MDM_FFT1MEMCLKFORCE_RST 0x0 +/// FFT1CLKFORCE field reset value +#define MDM_FFT1CLKFORCE_RST 0x0 +/// FFT0MEMCLKFORCE field reset value +#define MDM_FFT0MEMCLKFORCE_RST 0x0 +/// FFT0CLKFORCE field reset value +#define MDM_FFT0CLKFORCE_RST 0x0 +/// CHESTCLKFORCE field reset value +#define MDM_CHESTCLKFORCE_RST 0x0 +/// GMEMCLKFORCE field reset value +#define MDM_GMEMCLKFORCE_RST 0x0 +/// HMEMCLKFORCE field reset value +#define MDM_HMEMCLKFORCE_RST 0x0 +/// QMEMCLKFORCE field reset value +#define MDM_QMEMCLKFORCE_RST 0x0 +/// INTLVMEMCLKFORCE field reset value +#define MDM_INTLVMEMCLKFORCE_RST 0x0 +/// INTLVVTBCLKFORCE field reset value +#define MDM_INTLVVTBCLKFORCE_RST 0x0 +/// INTLVPHYCLKFORCE field reset value +#define MDM_INTLVPHYCLKFORCE_RST 0x0 + +/** + * @brief Constructs a value for the CLKGATEFCTRL0 register given values for its fields + * and writes the value to the register. + * + * @param[in] phytxclkforce - The value to use for the PHYTXCLKFORCE field. + * @param[in] phyrxclkforce - The value to use for the PHYRXCLKFORCE field. + * @param[in] agcmemclkforce - The value to use for the AGCMEMCLKFORCE field. + * @param[in] agcclkforce - The value to use for the AGCCLKFORCE field. + * @param[in] fe3clkforce - The value to use for the FE3CLKFORCE field. + * @param[in] fe2clkforce - The value to use for the FE2CLKFORCE field. + * @param[in] fe1clkforce - The value to use for the FE1CLKFORCE field. + * @param[in] fe0clkforce - The value to use for the FE0CLKFORCE field. + * @param[in] stocpeclkforce - The value to use for the STOCPECLKFORCE field. + * @param[in] equclkforce - The value to use for the EQUCLKFORCE field. + * @param[in] tdcomp3clkforce - The value to use for the TDCOMP3CLKFORCE field. + * @param[in] tdcomp2clkforce - The value to use for the TDCOMP2CLKFORCE field. + * @param[in] tdcomp1clkforce - The value to use for the TDCOMP1CLKFORCE field. + * @param[in] tdcomp0clkforce - The value to use for the TDCOMP0CLKFORCE field. + * @param[in] tdfoestclkforce - The value to use for the TDFOESTCLKFORCE field. + * @param[in] tbeclkforce - The value to use for the TBECLKFORCE field. + * @param[in] vtbclkforce - The value to use for the VTBCLKFORCE field. + * @param[in] fft3memclkforce - The value to use for the FFT3MEMCLKFORCE field. + * @param[in] fft3clkforce - The value to use for the FFT3CLKFORCE field. + * @param[in] fft2memclkforce - The value to use for the FFT2MEMCLKFORCE field. + * @param[in] fft2clkforce - The value to use for the FFT2CLKFORCE field. + * @param[in] fft1memclkforce - The value to use for the FFT1MEMCLKFORCE field. + * @param[in] fft1clkforce - The value to use for the FFT1CLKFORCE field. + * @param[in] fft0memclkforce - The value to use for the FFT0MEMCLKFORCE field. + * @param[in] fft0clkforce - The value to use for the FFT0CLKFORCE field. + * @param[in] chestclkforce - The value to use for the CHESTCLKFORCE field. + * @param[in] gmemclkforce - The value to use for the GMEMCLKFORCE field. + * @param[in] hmemclkforce - The value to use for the HMEMCLKFORCE field. + * @param[in] qmemclkforce - The value to use for the QMEMCLKFORCE field. + * @param[in] intlvmemclkforce - The value to use for the INTLVMEMCLKFORCE field. + * @param[in] intlvvtbclkforce - The value to use for the INTLVVTBCLKFORCE field. + * @param[in] intlvphyclkforce - The value to use for the INTLVPHYCLKFORCE field. + */ +__INLINE void mdm_clkgatefctrl0_pack(uint8_t phytxclkforce, uint8_t phyrxclkforce, uint8_t agcmemclkforce, uint8_t agcclkforce, uint8_t fe3clkforce, uint8_t fe2clkforce, uint8_t fe1clkforce, uint8_t fe0clkforce, uint8_t stocpeclkforce, uint8_t equclkforce, uint8_t tdcomp3clkforce, uint8_t tdcomp2clkforce, uint8_t tdcomp1clkforce, uint8_t tdcomp0clkforce, uint8_t tdfoestclkforce, uint8_t tbeclkforce, uint8_t vtbclkforce, uint8_t fft3memclkforce, uint8_t fft3clkforce, uint8_t fft2memclkforce, uint8_t fft2clkforce, uint8_t fft1memclkforce, uint8_t fft1clkforce, uint8_t fft0memclkforce, uint8_t fft0clkforce, uint8_t chestclkforce, uint8_t gmemclkforce, uint8_t hmemclkforce, uint8_t qmemclkforce, uint8_t intlvmemclkforce, uint8_t intlvvtbclkforce, uint8_t intlvphyclkforce) +{ + ASSERT_ERR((((uint32_t)phytxclkforce << 31) & ~((uint32_t)0x80000000)) == 0); + ASSERT_ERR((((uint32_t)phyrxclkforce << 30) & ~((uint32_t)0x40000000)) == 0); + ASSERT_ERR((((uint32_t)agcmemclkforce << 29) & ~((uint32_t)0x20000000)) == 0); + ASSERT_ERR((((uint32_t)agcclkforce << 28) & ~((uint32_t)0x10000000)) == 0); + ASSERT_ERR((((uint32_t)fe3clkforce << 27) & ~((uint32_t)0x08000000)) == 0); + ASSERT_ERR((((uint32_t)fe2clkforce << 26) & ~((uint32_t)0x04000000)) == 0); + ASSERT_ERR((((uint32_t)fe1clkforce << 25) & ~((uint32_t)0x02000000)) == 0); + ASSERT_ERR((((uint32_t)fe0clkforce << 24) & ~((uint32_t)0x01000000)) == 0); + ASSERT_ERR((((uint32_t)stocpeclkforce << 23) & ~((uint32_t)0x00800000)) == 0); + ASSERT_ERR((((uint32_t)equclkforce << 22) & ~((uint32_t)0x00400000)) == 0); + ASSERT_ERR((((uint32_t)tdcomp3clkforce << 21) & ~((uint32_t)0x00200000)) == 0); + ASSERT_ERR((((uint32_t)tdcomp2clkforce << 20) & ~((uint32_t)0x00100000)) == 0); + ASSERT_ERR((((uint32_t)tdcomp1clkforce << 19) & ~((uint32_t)0x00080000)) == 0); + ASSERT_ERR((((uint32_t)tdcomp0clkforce << 18) & ~((uint32_t)0x00040000)) == 0); + ASSERT_ERR((((uint32_t)tdfoestclkforce << 17) & ~((uint32_t)0x00020000)) == 0); + ASSERT_ERR((((uint32_t)tbeclkforce << 16) & ~((uint32_t)0x00010000)) == 0); + ASSERT_ERR((((uint32_t)vtbclkforce << 15) & ~((uint32_t)0x00008000)) == 0); + ASSERT_ERR((((uint32_t)fft3memclkforce << 14) & ~((uint32_t)0x00004000)) == 0); + ASSERT_ERR((((uint32_t)fft3clkforce << 13) & ~((uint32_t)0x00002000)) == 0); + ASSERT_ERR((((uint32_t)fft2memclkforce << 12) & ~((uint32_t)0x00001000)) == 0); + ASSERT_ERR((((uint32_t)fft2clkforce << 11) & ~((uint32_t)0x00000800)) == 0); + ASSERT_ERR((((uint32_t)fft1memclkforce << 10) & ~((uint32_t)0x00000400)) == 0); + ASSERT_ERR((((uint32_t)fft1clkforce << 9) & ~((uint32_t)0x00000200)) == 0); + ASSERT_ERR((((uint32_t)fft0memclkforce << 8) & ~((uint32_t)0x00000100)) == 0); + ASSERT_ERR((((uint32_t)fft0clkforce << 7) & ~((uint32_t)0x00000080)) == 0); + ASSERT_ERR((((uint32_t)chestclkforce << 6) & ~((uint32_t)0x00000040)) == 0); + ASSERT_ERR((((uint32_t)gmemclkforce << 5) & ~((uint32_t)0x00000020)) == 0); + ASSERT_ERR((((uint32_t)hmemclkforce << 4) & ~((uint32_t)0x00000010)) == 0); + ASSERT_ERR((((uint32_t)qmemclkforce << 3) & ~((uint32_t)0x00000008)) == 0); + ASSERT_ERR((((uint32_t)intlvmemclkforce << 2) & ~((uint32_t)0x00000004)) == 0); + ASSERT_ERR((((uint32_t)intlvvtbclkforce << 1) & ~((uint32_t)0x00000002)) == 0); + ASSERT_ERR((((uint32_t)intlvphyclkforce << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(MDM_CLKGATEFCTRL0_ADDR, ((uint32_t)phytxclkforce << 31) | ((uint32_t)phyrxclkforce << 30) | ((uint32_t)agcmemclkforce << 29) | ((uint32_t)agcclkforce << 28) | ((uint32_t)fe3clkforce << 27) | ((uint32_t)fe2clkforce << 26) | ((uint32_t)fe1clkforce << 25) | ((uint32_t)fe0clkforce << 24) | ((uint32_t)stocpeclkforce << 23) | ((uint32_t)equclkforce << 22) | ((uint32_t)tdcomp3clkforce << 21) | ((uint32_t)tdcomp2clkforce << 20) | ((uint32_t)tdcomp1clkforce << 19) | ((uint32_t)tdcomp0clkforce << 18) | ((uint32_t)tdfoestclkforce << 17) | ((uint32_t)tbeclkforce << 16) | ((uint32_t)vtbclkforce << 15) | ((uint32_t)fft3memclkforce << 14) | ((uint32_t)fft3clkforce << 13) | ((uint32_t)fft2memclkforce << 12) | ((uint32_t)fft2clkforce << 11) | ((uint32_t)fft1memclkforce << 10) | ((uint32_t)fft1clkforce << 9) | ((uint32_t)fft0memclkforce << 8) | ((uint32_t)fft0clkforce << 7) | ((uint32_t)chestclkforce << 6) | ((uint32_t)gmemclkforce << 5) | ((uint32_t)hmemclkforce << 4) | ((uint32_t)qmemclkforce << 3) | ((uint32_t)intlvmemclkforce << 2) | ((uint32_t)intlvvtbclkforce << 1) | ((uint32_t)intlvphyclkforce << 0)); +} + +/** + * @brief Unpacks CLKGATEFCTRL0's fields from current value of the CLKGATEFCTRL0 register. + * + * Reads the CLKGATEFCTRL0 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] phytxclkforce - Will be populated with the current value of this field from the register. + * @param[out] phyrxclkforce - Will be populated with the current value of this field from the register. + * @param[out] agcmemclkforce - Will be populated with the current value of this field from the register. + * @param[out] agcclkforce - Will be populated with the current value of this field from the register. + * @param[out] fe3clkforce - Will be populated with the current value of this field from the register. + * @param[out] fe2clkforce - Will be populated with the current value of this field from the register. + * @param[out] fe1clkforce - Will be populated with the current value of this field from the register. + * @param[out] fe0clkforce - Will be populated with the current value of this field from the register. + * @param[out] stocpeclkforce - Will be populated with the current value of this field from the register. + * @param[out] equclkforce - Will be populated with the current value of this field from the register. + * @param[out] tdcomp3clkforce - Will be populated with the current value of this field from the register. + * @param[out] tdcomp2clkforce - Will be populated with the current value of this field from the register. + * @param[out] tdcomp1clkforce - Will be populated with the current value of this field from the register. + * @param[out] tdcomp0clkforce - Will be populated with the current value of this field from the register. + * @param[out] tdfoestclkforce - Will be populated with the current value of this field from the register. + * @param[out] tbeclkforce - Will be populated with the current value of this field from the register. + * @param[out] vtbclkforce - Will be populated with the current value of this field from the register. + * @param[out] fft3memclkforce - Will be populated with the current value of this field from the register. + * @param[out] fft3clkforce - Will be populated with the current value of this field from the register. + * @param[out] fft2memclkforce - Will be populated with the current value of this field from the register. + * @param[out] fft2clkforce - Will be populated with the current value of this field from the register. + * @param[out] fft1memclkforce - Will be populated with the current value of this field from the register. + * @param[out] fft1clkforce - Will be populated with the current value of this field from the register. + * @param[out] fft0memclkforce - Will be populated with the current value of this field from the register. + * @param[out] fft0clkforce - Will be populated with the current value of this field from the register. + * @param[out] chestclkforce - Will be populated with the current value of this field from the register. + * @param[out] gmemclkforce - Will be populated with the current value of this field from the register. + * @param[out] hmemclkforce - Will be populated with the current value of this field from the register. + * @param[out] qmemclkforce - Will be populated with the current value of this field from the register. + * @param[out] intlvmemclkforce - Will be populated with the current value of this field from the register. + * @param[out] intlvvtbclkforce - Will be populated with the current value of this field from the register. + * @param[out] intlvphyclkforce - Will be populated with the current value of this field from the register. + */ +__INLINE void mdm_clkgatefctrl0_unpack(uint8_t *phytxclkforce, uint8_t *phyrxclkforce, uint8_t *agcmemclkforce, uint8_t *agcclkforce, uint8_t *fe3clkforce, uint8_t *fe2clkforce, uint8_t *fe1clkforce, uint8_t *fe0clkforce, uint8_t *stocpeclkforce, uint8_t *equclkforce, uint8_t *tdcomp3clkforce, uint8_t *tdcomp2clkforce, uint8_t *tdcomp1clkforce, uint8_t *tdcomp0clkforce, uint8_t *tdfoestclkforce, uint8_t *tbeclkforce, uint8_t *vtbclkforce, uint8_t *fft3memclkforce, uint8_t *fft3clkforce, uint8_t *fft2memclkforce, uint8_t *fft2clkforce, uint8_t *fft1memclkforce, uint8_t *fft1clkforce, uint8_t *fft0memclkforce, uint8_t *fft0clkforce, uint8_t *chestclkforce, uint8_t *gmemclkforce, uint8_t *hmemclkforce, uint8_t *qmemclkforce, uint8_t *intlvmemclkforce, uint8_t *intlvvtbclkforce, uint8_t *intlvphyclkforce) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR); + + *phytxclkforce = (localVal & ((uint32_t)0x80000000)) >> 31; + *phyrxclkforce = (localVal & ((uint32_t)0x40000000)) >> 30; + *agcmemclkforce = (localVal & ((uint32_t)0x20000000)) >> 29; + *agcclkforce = (localVal & ((uint32_t)0x10000000)) >> 28; + *fe3clkforce = (localVal & ((uint32_t)0x08000000)) >> 27; + *fe2clkforce = (localVal & ((uint32_t)0x04000000)) >> 26; + *fe1clkforce = (localVal & ((uint32_t)0x02000000)) >> 25; + *fe0clkforce = (localVal & ((uint32_t)0x01000000)) >> 24; + *stocpeclkforce = (localVal & ((uint32_t)0x00800000)) >> 23; + *equclkforce = (localVal & ((uint32_t)0x00400000)) >> 22; + *tdcomp3clkforce = (localVal & ((uint32_t)0x00200000)) >> 21; + *tdcomp2clkforce = (localVal & ((uint32_t)0x00100000)) >> 20; + *tdcomp1clkforce = (localVal & ((uint32_t)0x00080000)) >> 19; + *tdcomp0clkforce = (localVal & ((uint32_t)0x00040000)) >> 18; + *tdfoestclkforce = (localVal & ((uint32_t)0x00020000)) >> 17; + *tbeclkforce = (localVal & ((uint32_t)0x00010000)) >> 16; + *vtbclkforce = (localVal & ((uint32_t)0x00008000)) >> 15; + *fft3memclkforce = (localVal & ((uint32_t)0x00004000)) >> 14; + *fft3clkforce = (localVal & ((uint32_t)0x00002000)) >> 13; + *fft2memclkforce = (localVal & ((uint32_t)0x00001000)) >> 12; + *fft2clkforce = (localVal & ((uint32_t)0x00000800)) >> 11; + *fft1memclkforce = (localVal & ((uint32_t)0x00000400)) >> 10; + *fft1clkforce = (localVal & ((uint32_t)0x00000200)) >> 9; + *fft0memclkforce = (localVal & ((uint32_t)0x00000100)) >> 8; + *fft0clkforce = (localVal & ((uint32_t)0x00000080)) >> 7; + *chestclkforce = (localVal & ((uint32_t)0x00000040)) >> 6; + *gmemclkforce = (localVal & ((uint32_t)0x00000020)) >> 5; + *hmemclkforce = (localVal & ((uint32_t)0x00000010)) >> 4; + *qmemclkforce = (localVal & ((uint32_t)0x00000008)) >> 3; + *intlvmemclkforce = (localVal & ((uint32_t)0x00000004)) >> 2; + *intlvvtbclkforce = (localVal & ((uint32_t)0x00000002)) >> 1; + *intlvphyclkforce = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +/** + * @brief Returns the current value of the PHYTXCLKFORCE field in the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read and the PHYTXCLKFORCE field's value will be returned. + * + * @return The current value of the PHYTXCLKFORCE field in the CLKGATEFCTRL0 register. + */ +__INLINE uint8_t mdm_phytxclkforce_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +/** + * @brief Sets the PHYTXCLKFORCE field of the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] phytxclkforce - The value to set the field to. + */ +__INLINE void mdm_phytxclkforce_setf(uint8_t phytxclkforce) +{ + ASSERT_ERR((((uint32_t)phytxclkforce << 31) & ~((uint32_t)0x80000000)) == 0); + REG_PL_WR(MDM_CLKGATEFCTRL0_ADDR, (REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR) & ~((uint32_t)0x80000000)) | ((uint32_t)phytxclkforce << 31)); +} + +/** + * @brief Returns the current value of the PHYRXCLKFORCE field in the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read and the PHYRXCLKFORCE field's value will be returned. + * + * @return The current value of the PHYRXCLKFORCE field in the CLKGATEFCTRL0 register. + */ +__INLINE uint8_t mdm_phyrxclkforce_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR); + return ((localVal & ((uint32_t)0x40000000)) >> 30); +} + +/** + * @brief Sets the PHYRXCLKFORCE field of the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] phyrxclkforce - The value to set the field to. + */ +__INLINE void mdm_phyrxclkforce_setf(uint8_t phyrxclkforce) +{ + ASSERT_ERR((((uint32_t)phyrxclkforce << 30) & ~((uint32_t)0x40000000)) == 0); + REG_PL_WR(MDM_CLKGATEFCTRL0_ADDR, (REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR) & ~((uint32_t)0x40000000)) | ((uint32_t)phyrxclkforce << 30)); +} + +/** + * @brief Returns the current value of the AGCMEMCLKFORCE field in the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read and the AGCMEMCLKFORCE field's value will be returned. + * + * @return The current value of the AGCMEMCLKFORCE field in the CLKGATEFCTRL0 register. + */ +__INLINE uint8_t mdm_agcmemclkforce_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR); + return ((localVal & ((uint32_t)0x20000000)) >> 29); +} + +/** + * @brief Sets the AGCMEMCLKFORCE field of the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] agcmemclkforce - The value to set the field to. + */ +__INLINE void mdm_agcmemclkforce_setf(uint8_t agcmemclkforce) +{ + ASSERT_ERR((((uint32_t)agcmemclkforce << 29) & ~((uint32_t)0x20000000)) == 0); + REG_PL_WR(MDM_CLKGATEFCTRL0_ADDR, (REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR) & ~((uint32_t)0x20000000)) | ((uint32_t)agcmemclkforce << 29)); +} + +/** + * @brief Returns the current value of the AGCCLKFORCE field in the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read and the AGCCLKFORCE field's value will be returned. + * + * @return The current value of the AGCCLKFORCE field in the CLKGATEFCTRL0 register. + */ +__INLINE uint8_t mdm_agcclkforce_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR); + return ((localVal & ((uint32_t)0x10000000)) >> 28); +} + +/** + * @brief Sets the AGCCLKFORCE field of the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] agcclkforce - The value to set the field to. + */ +__INLINE void mdm_agcclkforce_setf(uint8_t agcclkforce) +{ + ASSERT_ERR((((uint32_t)agcclkforce << 28) & ~((uint32_t)0x10000000)) == 0); + REG_PL_WR(MDM_CLKGATEFCTRL0_ADDR, (REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR) & ~((uint32_t)0x10000000)) | ((uint32_t)agcclkforce << 28)); +} + +/** + * @brief Returns the current value of the FE3CLKFORCE field in the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read and the FE3CLKFORCE field's value will be returned. + * + * @return The current value of the FE3CLKFORCE field in the CLKGATEFCTRL0 register. + */ +__INLINE uint8_t mdm_fe3clkforce_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR); + return ((localVal & ((uint32_t)0x08000000)) >> 27); +} + +/** + * @brief Sets the FE3CLKFORCE field of the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] fe3clkforce - The value to set the field to. + */ +__INLINE void mdm_fe3clkforce_setf(uint8_t fe3clkforce) +{ + ASSERT_ERR((((uint32_t)fe3clkforce << 27) & ~((uint32_t)0x08000000)) == 0); + REG_PL_WR(MDM_CLKGATEFCTRL0_ADDR, (REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR) & ~((uint32_t)0x08000000)) | ((uint32_t)fe3clkforce << 27)); +} + +/** + * @brief Returns the current value of the FE2CLKFORCE field in the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read and the FE2CLKFORCE field's value will be returned. + * + * @return The current value of the FE2CLKFORCE field in the CLKGATEFCTRL0 register. + */ +__INLINE uint8_t mdm_fe2clkforce_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR); + return ((localVal & ((uint32_t)0x04000000)) >> 26); +} + +/** + * @brief Sets the FE2CLKFORCE field of the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] fe2clkforce - The value to set the field to. + */ +__INLINE void mdm_fe2clkforce_setf(uint8_t fe2clkforce) +{ + ASSERT_ERR((((uint32_t)fe2clkforce << 26) & ~((uint32_t)0x04000000)) == 0); + REG_PL_WR(MDM_CLKGATEFCTRL0_ADDR, (REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR) & ~((uint32_t)0x04000000)) | ((uint32_t)fe2clkforce << 26)); +} + +/** + * @brief Returns the current value of the FE1CLKFORCE field in the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read and the FE1CLKFORCE field's value will be returned. + * + * @return The current value of the FE1CLKFORCE field in the CLKGATEFCTRL0 register. + */ +__INLINE uint8_t mdm_fe1clkforce_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR); + return ((localVal & ((uint32_t)0x02000000)) >> 25); +} + +/** + * @brief Sets the FE1CLKFORCE field of the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] fe1clkforce - The value to set the field to. + */ +__INLINE void mdm_fe1clkforce_setf(uint8_t fe1clkforce) +{ + ASSERT_ERR((((uint32_t)fe1clkforce << 25) & ~((uint32_t)0x02000000)) == 0); + REG_PL_WR(MDM_CLKGATEFCTRL0_ADDR, (REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR) & ~((uint32_t)0x02000000)) | ((uint32_t)fe1clkforce << 25)); +} + +/** + * @brief Returns the current value of the FE0CLKFORCE field in the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read and the FE0CLKFORCE field's value will be returned. + * + * @return The current value of the FE0CLKFORCE field in the CLKGATEFCTRL0 register. + */ +__INLINE uint8_t mdm_fe0clkforce_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR); + return ((localVal & ((uint32_t)0x01000000)) >> 24); +} + +/** + * @brief Sets the FE0CLKFORCE field of the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] fe0clkforce - The value to set the field to. + */ +__INLINE void mdm_fe0clkforce_setf(uint8_t fe0clkforce) +{ + ASSERT_ERR((((uint32_t)fe0clkforce << 24) & ~((uint32_t)0x01000000)) == 0); + REG_PL_WR(MDM_CLKGATEFCTRL0_ADDR, (REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR) & ~((uint32_t)0x01000000)) | ((uint32_t)fe0clkforce << 24)); +} + +/** + * @brief Returns the current value of the STOCPECLKFORCE field in the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read and the STOCPECLKFORCE field's value will be returned. + * + * @return The current value of the STOCPECLKFORCE field in the CLKGATEFCTRL0 register. + */ +__INLINE uint8_t mdm_stocpeclkforce_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR); + return ((localVal & ((uint32_t)0x00800000)) >> 23); +} + +/** + * @brief Sets the STOCPECLKFORCE field of the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] stocpeclkforce - The value to set the field to. + */ +__INLINE void mdm_stocpeclkforce_setf(uint8_t stocpeclkforce) +{ + ASSERT_ERR((((uint32_t)stocpeclkforce << 23) & ~((uint32_t)0x00800000)) == 0); + REG_PL_WR(MDM_CLKGATEFCTRL0_ADDR, (REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR) & ~((uint32_t)0x00800000)) | ((uint32_t)stocpeclkforce << 23)); +} + +/** + * @brief Returns the current value of the EQUCLKFORCE field in the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read and the EQUCLKFORCE field's value will be returned. + * + * @return The current value of the EQUCLKFORCE field in the CLKGATEFCTRL0 register. + */ +__INLINE uint8_t mdm_equclkforce_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR); + return ((localVal & ((uint32_t)0x00400000)) >> 22); +} + +/** + * @brief Sets the EQUCLKFORCE field of the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] equclkforce - The value to set the field to. + */ +__INLINE void mdm_equclkforce_setf(uint8_t equclkforce) +{ + ASSERT_ERR((((uint32_t)equclkforce << 22) & ~((uint32_t)0x00400000)) == 0); + REG_PL_WR(MDM_CLKGATEFCTRL0_ADDR, (REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR) & ~((uint32_t)0x00400000)) | ((uint32_t)equclkforce << 22)); +} + +/** + * @brief Returns the current value of the TDCOMP3CLKFORCE field in the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read and the TDCOMP3CLKFORCE field's value will be returned. + * + * @return The current value of the TDCOMP3CLKFORCE field in the CLKGATEFCTRL0 register. + */ +__INLINE uint8_t mdm_tdcomp3clkforce_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR); + return ((localVal & ((uint32_t)0x00200000)) >> 21); +} + +/** + * @brief Sets the TDCOMP3CLKFORCE field of the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] tdcomp3clkforce - The value to set the field to. + */ +__INLINE void mdm_tdcomp3clkforce_setf(uint8_t tdcomp3clkforce) +{ + ASSERT_ERR((((uint32_t)tdcomp3clkforce << 21) & ~((uint32_t)0x00200000)) == 0); + REG_PL_WR(MDM_CLKGATEFCTRL0_ADDR, (REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR) & ~((uint32_t)0x00200000)) | ((uint32_t)tdcomp3clkforce << 21)); +} + +/** + * @brief Returns the current value of the TDCOMP2CLKFORCE field in the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read and the TDCOMP2CLKFORCE field's value will be returned. + * + * @return The current value of the TDCOMP2CLKFORCE field in the CLKGATEFCTRL0 register. + */ +__INLINE uint8_t mdm_tdcomp2clkforce_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR); + return ((localVal & ((uint32_t)0x00100000)) >> 20); +} + +/** + * @brief Sets the TDCOMP2CLKFORCE field of the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] tdcomp2clkforce - The value to set the field to. + */ +__INLINE void mdm_tdcomp2clkforce_setf(uint8_t tdcomp2clkforce) +{ + ASSERT_ERR((((uint32_t)tdcomp2clkforce << 20) & ~((uint32_t)0x00100000)) == 0); + REG_PL_WR(MDM_CLKGATEFCTRL0_ADDR, (REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR) & ~((uint32_t)0x00100000)) | ((uint32_t)tdcomp2clkforce << 20)); +} + +/** + * @brief Returns the current value of the TDCOMP1CLKFORCE field in the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read and the TDCOMP1CLKFORCE field's value will be returned. + * + * @return The current value of the TDCOMP1CLKFORCE field in the CLKGATEFCTRL0 register. + */ +__INLINE uint8_t mdm_tdcomp1clkforce_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR); + return ((localVal & ((uint32_t)0x00080000)) >> 19); +} + +/** + * @brief Sets the TDCOMP1CLKFORCE field of the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] tdcomp1clkforce - The value to set the field to. + */ +__INLINE void mdm_tdcomp1clkforce_setf(uint8_t tdcomp1clkforce) +{ + ASSERT_ERR((((uint32_t)tdcomp1clkforce << 19) & ~((uint32_t)0x00080000)) == 0); + REG_PL_WR(MDM_CLKGATEFCTRL0_ADDR, (REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR) & ~((uint32_t)0x00080000)) | ((uint32_t)tdcomp1clkforce << 19)); +} + +/** + * @brief Returns the current value of the TDCOMP0CLKFORCE field in the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read and the TDCOMP0CLKFORCE field's value will be returned. + * + * @return The current value of the TDCOMP0CLKFORCE field in the CLKGATEFCTRL0 register. + */ +__INLINE uint8_t mdm_tdcomp0clkforce_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR); + return ((localVal & ((uint32_t)0x00040000)) >> 18); +} + +/** + * @brief Sets the TDCOMP0CLKFORCE field of the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] tdcomp0clkforce - The value to set the field to. + */ +__INLINE void mdm_tdcomp0clkforce_setf(uint8_t tdcomp0clkforce) +{ + ASSERT_ERR((((uint32_t)tdcomp0clkforce << 18) & ~((uint32_t)0x00040000)) == 0); + REG_PL_WR(MDM_CLKGATEFCTRL0_ADDR, (REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR) & ~((uint32_t)0x00040000)) | ((uint32_t)tdcomp0clkforce << 18)); +} + +/** + * @brief Returns the current value of the TDFOESTCLKFORCE field in the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read and the TDFOESTCLKFORCE field's value will be returned. + * + * @return The current value of the TDFOESTCLKFORCE field in the CLKGATEFCTRL0 register. + */ +__INLINE uint8_t mdm_tdfoestclkforce_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR); + return ((localVal & ((uint32_t)0x00020000)) >> 17); +} + +/** + * @brief Sets the TDFOESTCLKFORCE field of the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] tdfoestclkforce - The value to set the field to. + */ +__INLINE void mdm_tdfoestclkforce_setf(uint8_t tdfoestclkforce) +{ + ASSERT_ERR((((uint32_t)tdfoestclkforce << 17) & ~((uint32_t)0x00020000)) == 0); + REG_PL_WR(MDM_CLKGATEFCTRL0_ADDR, (REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR) & ~((uint32_t)0x00020000)) | ((uint32_t)tdfoestclkforce << 17)); +} + +/** + * @brief Returns the current value of the TBECLKFORCE field in the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read and the TBECLKFORCE field's value will be returned. + * + * @return The current value of the TBECLKFORCE field in the CLKGATEFCTRL0 register. + */ +__INLINE uint8_t mdm_tbeclkforce_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR); + return ((localVal & ((uint32_t)0x00010000)) >> 16); +} + +/** + * @brief Sets the TBECLKFORCE field of the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] tbeclkforce - The value to set the field to. + */ +__INLINE void mdm_tbeclkforce_setf(uint8_t tbeclkforce) +{ + ASSERT_ERR((((uint32_t)tbeclkforce << 16) & ~((uint32_t)0x00010000)) == 0); + REG_PL_WR(MDM_CLKGATEFCTRL0_ADDR, (REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR) & ~((uint32_t)0x00010000)) | ((uint32_t)tbeclkforce << 16)); +} + +/** + * @brief Returns the current value of the VTBCLKFORCE field in the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read and the VTBCLKFORCE field's value will be returned. + * + * @return The current value of the VTBCLKFORCE field in the CLKGATEFCTRL0 register. + */ +__INLINE uint8_t mdm_vtbclkforce_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR); + return ((localVal & ((uint32_t)0x00008000)) >> 15); +} + +/** + * @brief Sets the VTBCLKFORCE field of the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] vtbclkforce - The value to set the field to. + */ +__INLINE void mdm_vtbclkforce_setf(uint8_t vtbclkforce) +{ + ASSERT_ERR((((uint32_t)vtbclkforce << 15) & ~((uint32_t)0x00008000)) == 0); + REG_PL_WR(MDM_CLKGATEFCTRL0_ADDR, (REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR) & ~((uint32_t)0x00008000)) | ((uint32_t)vtbclkforce << 15)); +} + +/** + * @brief Returns the current value of the FFT3MEMCLKFORCE field in the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read and the FFT3MEMCLKFORCE field's value will be returned. + * + * @return The current value of the FFT3MEMCLKFORCE field in the CLKGATEFCTRL0 register. + */ +__INLINE uint8_t mdm_fft3memclkforce_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR); + return ((localVal & ((uint32_t)0x00004000)) >> 14); +} + +/** + * @brief Sets the FFT3MEMCLKFORCE field of the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] fft3memclkforce - The value to set the field to. + */ +__INLINE void mdm_fft3memclkforce_setf(uint8_t fft3memclkforce) +{ + ASSERT_ERR((((uint32_t)fft3memclkforce << 14) & ~((uint32_t)0x00004000)) == 0); + REG_PL_WR(MDM_CLKGATEFCTRL0_ADDR, (REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR) & ~((uint32_t)0x00004000)) | ((uint32_t)fft3memclkforce << 14)); +} + +/** + * @brief Returns the current value of the FFT3CLKFORCE field in the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read and the FFT3CLKFORCE field's value will be returned. + * + * @return The current value of the FFT3CLKFORCE field in the CLKGATEFCTRL0 register. + */ +__INLINE uint8_t mdm_fft3clkforce_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR); + return ((localVal & ((uint32_t)0x00002000)) >> 13); +} + +/** + * @brief Sets the FFT3CLKFORCE field of the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] fft3clkforce - The value to set the field to. + */ +__INLINE void mdm_fft3clkforce_setf(uint8_t fft3clkforce) +{ + ASSERT_ERR((((uint32_t)fft3clkforce << 13) & ~((uint32_t)0x00002000)) == 0); + REG_PL_WR(MDM_CLKGATEFCTRL0_ADDR, (REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR) & ~((uint32_t)0x00002000)) | ((uint32_t)fft3clkforce << 13)); +} + +/** + * @brief Returns the current value of the FFT2MEMCLKFORCE field in the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read and the FFT2MEMCLKFORCE field's value will be returned. + * + * @return The current value of the FFT2MEMCLKFORCE field in the CLKGATEFCTRL0 register. + */ +__INLINE uint8_t mdm_fft2memclkforce_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR); + return ((localVal & ((uint32_t)0x00001000)) >> 12); +} + +/** + * @brief Sets the FFT2MEMCLKFORCE field of the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] fft2memclkforce - The value to set the field to. + */ +__INLINE void mdm_fft2memclkforce_setf(uint8_t fft2memclkforce) +{ + ASSERT_ERR((((uint32_t)fft2memclkforce << 12) & ~((uint32_t)0x00001000)) == 0); + REG_PL_WR(MDM_CLKGATEFCTRL0_ADDR, (REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR) & ~((uint32_t)0x00001000)) | ((uint32_t)fft2memclkforce << 12)); +} + +/** + * @brief Returns the current value of the FFT2CLKFORCE field in the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read and the FFT2CLKFORCE field's value will be returned. + * + * @return The current value of the FFT2CLKFORCE field in the CLKGATEFCTRL0 register. + */ +__INLINE uint8_t mdm_fft2clkforce_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR); + return ((localVal & ((uint32_t)0x00000800)) >> 11); +} + +/** + * @brief Sets the FFT2CLKFORCE field of the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] fft2clkforce - The value to set the field to. + */ +__INLINE void mdm_fft2clkforce_setf(uint8_t fft2clkforce) +{ + ASSERT_ERR((((uint32_t)fft2clkforce << 11) & ~((uint32_t)0x00000800)) == 0); + REG_PL_WR(MDM_CLKGATEFCTRL0_ADDR, (REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR) & ~((uint32_t)0x00000800)) | ((uint32_t)fft2clkforce << 11)); +} + +/** + * @brief Returns the current value of the FFT1MEMCLKFORCE field in the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read and the FFT1MEMCLKFORCE field's value will be returned. + * + * @return The current value of the FFT1MEMCLKFORCE field in the CLKGATEFCTRL0 register. + */ +__INLINE uint8_t mdm_fft1memclkforce_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR); + return ((localVal & ((uint32_t)0x00000400)) >> 10); +} + +/** + * @brief Sets the FFT1MEMCLKFORCE field of the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] fft1memclkforce - The value to set the field to. + */ +__INLINE void mdm_fft1memclkforce_setf(uint8_t fft1memclkforce) +{ + ASSERT_ERR((((uint32_t)fft1memclkforce << 10) & ~((uint32_t)0x00000400)) == 0); + REG_PL_WR(MDM_CLKGATEFCTRL0_ADDR, (REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR) & ~((uint32_t)0x00000400)) | ((uint32_t)fft1memclkforce << 10)); +} + +/** + * @brief Returns the current value of the FFT1CLKFORCE field in the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read and the FFT1CLKFORCE field's value will be returned. + * + * @return The current value of the FFT1CLKFORCE field in the CLKGATEFCTRL0 register. + */ +__INLINE uint8_t mdm_fft1clkforce_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR); + return ((localVal & ((uint32_t)0x00000200)) >> 9); +} + +/** + * @brief Sets the FFT1CLKFORCE field of the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] fft1clkforce - The value to set the field to. + */ +__INLINE void mdm_fft1clkforce_setf(uint8_t fft1clkforce) +{ + ASSERT_ERR((((uint32_t)fft1clkforce << 9) & ~((uint32_t)0x00000200)) == 0); + REG_PL_WR(MDM_CLKGATEFCTRL0_ADDR, (REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR) & ~((uint32_t)0x00000200)) | ((uint32_t)fft1clkforce << 9)); +} + +/** + * @brief Returns the current value of the FFT0MEMCLKFORCE field in the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read and the FFT0MEMCLKFORCE field's value will be returned. + * + * @return The current value of the FFT0MEMCLKFORCE field in the CLKGATEFCTRL0 register. + */ +__INLINE uint8_t mdm_fft0memclkforce_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR); + return ((localVal & ((uint32_t)0x00000100)) >> 8); +} + +/** + * @brief Sets the FFT0MEMCLKFORCE field of the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] fft0memclkforce - The value to set the field to. + */ +__INLINE void mdm_fft0memclkforce_setf(uint8_t fft0memclkforce) +{ + ASSERT_ERR((((uint32_t)fft0memclkforce << 8) & ~((uint32_t)0x00000100)) == 0); + REG_PL_WR(MDM_CLKGATEFCTRL0_ADDR, (REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR) & ~((uint32_t)0x00000100)) | ((uint32_t)fft0memclkforce << 8)); +} + +/** + * @brief Returns the current value of the FFT0CLKFORCE field in the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read and the FFT0CLKFORCE field's value will be returned. + * + * @return The current value of the FFT0CLKFORCE field in the CLKGATEFCTRL0 register. + */ +__INLINE uint8_t mdm_fft0clkforce_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR); + return ((localVal & ((uint32_t)0x00000080)) >> 7); +} + +/** + * @brief Sets the FFT0CLKFORCE field of the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] fft0clkforce - The value to set the field to. + */ +__INLINE void mdm_fft0clkforce_setf(uint8_t fft0clkforce) +{ + ASSERT_ERR((((uint32_t)fft0clkforce << 7) & ~((uint32_t)0x00000080)) == 0); + REG_PL_WR(MDM_CLKGATEFCTRL0_ADDR, (REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR) & ~((uint32_t)0x00000080)) | ((uint32_t)fft0clkforce << 7)); +} + +/** + * @brief Returns the current value of the CHESTCLKFORCE field in the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read and the CHESTCLKFORCE field's value will be returned. + * + * @return The current value of the CHESTCLKFORCE field in the CLKGATEFCTRL0 register. + */ +__INLINE uint8_t mdm_chestclkforce_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR); + return ((localVal & ((uint32_t)0x00000040)) >> 6); +} + +/** + * @brief Sets the CHESTCLKFORCE field of the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] chestclkforce - The value to set the field to. + */ +__INLINE void mdm_chestclkforce_setf(uint8_t chestclkforce) +{ + ASSERT_ERR((((uint32_t)chestclkforce << 6) & ~((uint32_t)0x00000040)) == 0); + REG_PL_WR(MDM_CLKGATEFCTRL0_ADDR, (REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR) & ~((uint32_t)0x00000040)) | ((uint32_t)chestclkforce << 6)); +} + +/** + * @brief Returns the current value of the GMEMCLKFORCE field in the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read and the GMEMCLKFORCE field's value will be returned. + * + * @return The current value of the GMEMCLKFORCE field in the CLKGATEFCTRL0 register. + */ +__INLINE uint8_t mdm_gmemclkforce_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +/** + * @brief Sets the GMEMCLKFORCE field of the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] gmemclkforce - The value to set the field to. + */ +__INLINE void mdm_gmemclkforce_setf(uint8_t gmemclkforce) +{ + ASSERT_ERR((((uint32_t)gmemclkforce << 5) & ~((uint32_t)0x00000020)) == 0); + REG_PL_WR(MDM_CLKGATEFCTRL0_ADDR, (REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR) & ~((uint32_t)0x00000020)) | ((uint32_t)gmemclkforce << 5)); +} + +/** + * @brief Returns the current value of the HMEMCLKFORCE field in the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read and the HMEMCLKFORCE field's value will be returned. + * + * @return The current value of the HMEMCLKFORCE field in the CLKGATEFCTRL0 register. + */ +__INLINE uint8_t mdm_hmemclkforce_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +/** + * @brief Sets the HMEMCLKFORCE field of the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] hmemclkforce - The value to set the field to. + */ +__INLINE void mdm_hmemclkforce_setf(uint8_t hmemclkforce) +{ + ASSERT_ERR((((uint32_t)hmemclkforce << 4) & ~((uint32_t)0x00000010)) == 0); + REG_PL_WR(MDM_CLKGATEFCTRL0_ADDR, (REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR) & ~((uint32_t)0x00000010)) | ((uint32_t)hmemclkforce << 4)); +} + +/** + * @brief Returns the current value of the QMEMCLKFORCE field in the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read and the QMEMCLKFORCE field's value will be returned. + * + * @return The current value of the QMEMCLKFORCE field in the CLKGATEFCTRL0 register. + */ +__INLINE uint8_t mdm_qmemclkforce_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +/** + * @brief Sets the QMEMCLKFORCE field of the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] qmemclkforce - The value to set the field to. + */ +__INLINE void mdm_qmemclkforce_setf(uint8_t qmemclkforce) +{ + ASSERT_ERR((((uint32_t)qmemclkforce << 3) & ~((uint32_t)0x00000008)) == 0); + REG_PL_WR(MDM_CLKGATEFCTRL0_ADDR, (REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR) & ~((uint32_t)0x00000008)) | ((uint32_t)qmemclkforce << 3)); +} + +/** + * @brief Returns the current value of the INTLVMEMCLKFORCE field in the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read and the INTLVMEMCLKFORCE field's value will be returned. + * + * @return The current value of the INTLVMEMCLKFORCE field in the CLKGATEFCTRL0 register. + */ +__INLINE uint8_t mdm_intlvmemclkforce_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +/** + * @brief Sets the INTLVMEMCLKFORCE field of the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] intlvmemclkforce - The value to set the field to. + */ +__INLINE void mdm_intlvmemclkforce_setf(uint8_t intlvmemclkforce) +{ + ASSERT_ERR((((uint32_t)intlvmemclkforce << 2) & ~((uint32_t)0x00000004)) == 0); + REG_PL_WR(MDM_CLKGATEFCTRL0_ADDR, (REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR) & ~((uint32_t)0x00000004)) | ((uint32_t)intlvmemclkforce << 2)); +} + +/** + * @brief Returns the current value of the INTLVVTBCLKFORCE field in the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read and the INTLVVTBCLKFORCE field's value will be returned. + * + * @return The current value of the INTLVVTBCLKFORCE field in the CLKGATEFCTRL0 register. + */ +__INLINE uint8_t mdm_intlvvtbclkforce_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +/** + * @brief Sets the INTLVVTBCLKFORCE field of the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] intlvvtbclkforce - The value to set the field to. + */ +__INLINE void mdm_intlvvtbclkforce_setf(uint8_t intlvvtbclkforce) +{ + ASSERT_ERR((((uint32_t)intlvvtbclkforce << 1) & ~((uint32_t)0x00000002)) == 0); + REG_PL_WR(MDM_CLKGATEFCTRL0_ADDR, (REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR) & ~((uint32_t)0x00000002)) | ((uint32_t)intlvvtbclkforce << 1)); +} + +/** + * @brief Returns the current value of the INTLVPHYCLKFORCE field in the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read and the INTLVPHYCLKFORCE field's value will be returned. + * + * @return The current value of the INTLVPHYCLKFORCE field in the CLKGATEFCTRL0 register. + */ +__INLINE uint8_t mdm_intlvphyclkforce_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/** + * @brief Sets the INTLVPHYCLKFORCE field of the CLKGATEFCTRL0 register. + * + * The CLKGATEFCTRL0 register will be read, modified to contain the new field value, and written. + * + * @param[in] intlvphyclkforce - The value to set the field to. + */ +__INLINE void mdm_intlvphyclkforce_setf(uint8_t intlvphyclkforce) +{ + ASSERT_ERR((((uint32_t)intlvphyclkforce << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(MDM_CLKGATEFCTRL0_ADDR, (REG_PL_RD(MDM_CLKGATEFCTRL0_ADDR) & ~((uint32_t)0x00000001)) | ((uint32_t)intlvphyclkforce << 0)); +} + +/// @} + +/** + * @name CLKGATEFCTRL1 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     05     RADARTIMCLKFORCE   0
+ *     04       MDMBTXCLKFORCE   0
+ *     03       MDMBRXCLKFORCE   0
+ * 
+ * + * @{ + */ + +/// Address of the CLKGATEFCTRL1 register +#define MDM_CLKGATEFCTRL1_ADDR 0x01000880 +/// Offset of the CLKGATEFCTRL1 register from the base address +#define MDM_CLKGATEFCTRL1_OFFSET 0x00000880 +/// Index of the CLKGATEFCTRL1 register +#define MDM_CLKGATEFCTRL1_INDEX 0x00000220 +/// Reset value of the CLKGATEFCTRL1 register +#define MDM_CLKGATEFCTRL1_RESET 0x00000000 + +/** + * @brief Returns the current value of the CLKGATEFCTRL1 register. + * The CLKGATEFCTRL1 register will be read and its value returned. + * @return The current value of the CLKGATEFCTRL1 register. + */ +__INLINE uint32_t mdm_clkgatefctrl1_get(void) +{ + return REG_PL_RD(MDM_CLKGATEFCTRL1_ADDR); +} + +/** + * @brief Sets the CLKGATEFCTRL1 register to a value. + * The CLKGATEFCTRL1 register will be written. + * @param value - The value to write. + */ +__INLINE void mdm_clkgatefctrl1_set(uint32_t value) +{ + REG_PL_WR(MDM_CLKGATEFCTRL1_ADDR, value); +} + +// field definitions +/// RADARTIMCLKFORCE field bit +#define MDM_RADARTIMCLKFORCE_BIT ((uint32_t)0x00000020) +/// RADARTIMCLKFORCE field position +#define MDM_RADARTIMCLKFORCE_POS 5 +/// MDMBTXCLKFORCE field bit +#define MDM_MDMBTXCLKFORCE_BIT ((uint32_t)0x00000010) +/// MDMBTXCLKFORCE field position +#define MDM_MDMBTXCLKFORCE_POS 4 +/// MDMBRXCLKFORCE field bit +#define MDM_MDMBRXCLKFORCE_BIT ((uint32_t)0x00000008) +/// MDMBRXCLKFORCE field position +#define MDM_MDMBRXCLKFORCE_POS 3 + +/// RADARTIMCLKFORCE field reset value +#define MDM_RADARTIMCLKFORCE_RST 0x0 +/// MDMBTXCLKFORCE field reset value +#define MDM_MDMBTXCLKFORCE_RST 0x0 +/// MDMBRXCLKFORCE field reset value +#define MDM_MDMBRXCLKFORCE_RST 0x0 + +/** + * @brief Constructs a value for the CLKGATEFCTRL1 register given values for its fields + * and writes the value to the register. + * + * @param[in] radartimclkforce - The value to use for the RADARTIMCLKFORCE field. + * @param[in] mdmbtxclkforce - The value to use for the MDMBTXCLKFORCE field. + * @param[in] mdmbrxclkforce - The value to use for the MDMBRXCLKFORCE field. + */ +__INLINE void mdm_clkgatefctrl1_pack(uint8_t radartimclkforce, uint8_t mdmbtxclkforce, uint8_t mdmbrxclkforce) +{ + ASSERT_ERR((((uint32_t)radartimclkforce << 5) & ~((uint32_t)0x00000020)) == 0); + ASSERT_ERR((((uint32_t)mdmbtxclkforce << 4) & ~((uint32_t)0x00000010)) == 0); + ASSERT_ERR((((uint32_t)mdmbrxclkforce << 3) & ~((uint32_t)0x00000008)) == 0); + REG_PL_WR(MDM_CLKGATEFCTRL1_ADDR, ((uint32_t)radartimclkforce << 5) | ((uint32_t)mdmbtxclkforce << 4) | ((uint32_t)mdmbrxclkforce << 3)); +} + +/** + * @brief Unpacks CLKGATEFCTRL1's fields from current value of the CLKGATEFCTRL1 register. + * + * Reads the CLKGATEFCTRL1 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] radartimclkforce - Will be populated with the current value of this field from the register. + * @param[out] mdmbtxclkforce - Will be populated with the current value of this field from the register. + * @param[out] mdmbrxclkforce - Will be populated with the current value of this field from the register. + */ +__INLINE void mdm_clkgatefctrl1_unpack(uint8_t *radartimclkforce, uint8_t *mdmbtxclkforce, uint8_t *mdmbrxclkforce) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATEFCTRL1_ADDR); + + *radartimclkforce = (localVal & ((uint32_t)0x00000020)) >> 5; + *mdmbtxclkforce = (localVal & ((uint32_t)0x00000010)) >> 4; + *mdmbrxclkforce = (localVal & ((uint32_t)0x00000008)) >> 3; +} + +/** + * @brief Returns the current value of the RADARTIMCLKFORCE field in the CLKGATEFCTRL1 register. + * + * The CLKGATEFCTRL1 register will be read and the RADARTIMCLKFORCE field's value will be returned. + * + * @return The current value of the RADARTIMCLKFORCE field in the CLKGATEFCTRL1 register. + */ +__INLINE uint8_t mdm_radartimclkforce_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATEFCTRL1_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +/** + * @brief Sets the RADARTIMCLKFORCE field of the CLKGATEFCTRL1 register. + * + * The CLKGATEFCTRL1 register will be read, modified to contain the new field value, and written. + * + * @param[in] radartimclkforce - The value to set the field to. + */ +__INLINE void mdm_radartimclkforce_setf(uint8_t radartimclkforce) +{ + ASSERT_ERR((((uint32_t)radartimclkforce << 5) & ~((uint32_t)0x00000020)) == 0); + REG_PL_WR(MDM_CLKGATEFCTRL1_ADDR, (REG_PL_RD(MDM_CLKGATEFCTRL1_ADDR) & ~((uint32_t)0x00000020)) | ((uint32_t)radartimclkforce << 5)); +} + +/** + * @brief Returns the current value of the MDMBTXCLKFORCE field in the CLKGATEFCTRL1 register. + * + * The CLKGATEFCTRL1 register will be read and the MDMBTXCLKFORCE field's value will be returned. + * + * @return The current value of the MDMBTXCLKFORCE field in the CLKGATEFCTRL1 register. + */ +__INLINE uint8_t mdm_mdmbtxclkforce_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATEFCTRL1_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +/** + * @brief Sets the MDMBTXCLKFORCE field of the CLKGATEFCTRL1 register. + * + * The CLKGATEFCTRL1 register will be read, modified to contain the new field value, and written. + * + * @param[in] mdmbtxclkforce - The value to set the field to. + */ +__INLINE void mdm_mdmbtxclkforce_setf(uint8_t mdmbtxclkforce) +{ + ASSERT_ERR((((uint32_t)mdmbtxclkforce << 4) & ~((uint32_t)0x00000010)) == 0); + REG_PL_WR(MDM_CLKGATEFCTRL1_ADDR, (REG_PL_RD(MDM_CLKGATEFCTRL1_ADDR) & ~((uint32_t)0x00000010)) | ((uint32_t)mdmbtxclkforce << 4)); +} + +/** + * @brief Returns the current value of the MDMBRXCLKFORCE field in the CLKGATEFCTRL1 register. + * + * The CLKGATEFCTRL1 register will be read and the MDMBRXCLKFORCE field's value will be returned. + * + * @return The current value of the MDMBRXCLKFORCE field in the CLKGATEFCTRL1 register. + */ +__INLINE uint8_t mdm_mdmbrxclkforce_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_CLKGATEFCTRL1_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +/** + * @brief Sets the MDMBRXCLKFORCE field of the CLKGATEFCTRL1 register. + * + * The CLKGATEFCTRL1 register will be read, modified to contain the new field value, and written. + * + * @param[in] mdmbrxclkforce - The value to set the field to. + */ +__INLINE void mdm_mdmbrxclkforce_setf(uint8_t mdmbrxclkforce) +{ + ASSERT_ERR((((uint32_t)mdmbrxclkforce << 3) & ~((uint32_t)0x00000008)) == 0); + REG_PL_WR(MDM_CLKGATEFCTRL1_ADDR, (REG_PL_RD(MDM_CLKGATEFCTRL1_ADDR) & ~((uint32_t)0x00000008)) | ((uint32_t)mdmbrxclkforce << 3)); +} + +/// @} + +/** + * @name DCOFFSET0 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  23:16         TXIDCOFFSET0   0x0
+ *  07:00         TXQDCOFFSET0   0x0
+ * 
+ * + * @{ + */ + +/// Address of the DCOFFSET0 register +#define MDM_DCOFFSET0_ADDR 0x01000884 +/// Offset of the DCOFFSET0 register from the base address +#define MDM_DCOFFSET0_OFFSET 0x00000884 +/// Index of the DCOFFSET0 register +#define MDM_DCOFFSET0_INDEX 0x00000221 +/// Reset value of the DCOFFSET0 register +#define MDM_DCOFFSET0_RESET 0x00000000 + +/** + * @brief Returns the current value of the DCOFFSET0 register. + * The DCOFFSET0 register will be read and its value returned. + * @return The current value of the DCOFFSET0 register. + */ +__INLINE uint32_t mdm_dcoffset0_get(void) +{ + return REG_PL_RD(MDM_DCOFFSET0_ADDR); +} + +/** + * @brief Sets the DCOFFSET0 register to a value. + * The DCOFFSET0 register will be written. + * @param value - The value to write. + */ +__INLINE void mdm_dcoffset0_set(uint32_t value) +{ + REG_PL_WR(MDM_DCOFFSET0_ADDR, value); +} + +// field definitions +/// TXIDCOFFSET0 field mask +#define MDM_TXIDCOFFSET0_MASK ((uint32_t)0x00FF0000) +/// TXIDCOFFSET0 field LSB position +#define MDM_TXIDCOFFSET0_LSB 16 +/// TXIDCOFFSET0 field width +#define MDM_TXIDCOFFSET0_WIDTH ((uint32_t)0x00000008) +/// TXQDCOFFSET0 field mask +#define MDM_TXQDCOFFSET0_MASK ((uint32_t)0x000000FF) +/// TXQDCOFFSET0 field LSB position +#define MDM_TXQDCOFFSET0_LSB 0 +/// TXQDCOFFSET0 field width +#define MDM_TXQDCOFFSET0_WIDTH ((uint32_t)0x00000008) + +/// TXIDCOFFSET0 field reset value +#define MDM_TXIDCOFFSET0_RST 0x0 +/// TXQDCOFFSET0 field reset value +#define MDM_TXQDCOFFSET0_RST 0x0 + +/** + * @brief Constructs a value for the DCOFFSET0 register given values for its fields + * and writes the value to the register. + * + * @param[in] txidcoffset0 - The value to use for the TXIDCOFFSET0 field. + * @param[in] txqdcoffset0 - The value to use for the TXQDCOFFSET0 field. + */ +__INLINE void mdm_dcoffset0_pack(uint8_t txidcoffset0, uint8_t txqdcoffset0) +{ + ASSERT_ERR((((uint32_t)txidcoffset0 << 16) & ~((uint32_t)0x00FF0000)) == 0); + ASSERT_ERR((((uint32_t)txqdcoffset0 << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(MDM_DCOFFSET0_ADDR, ((uint32_t)txidcoffset0 << 16) | ((uint32_t)txqdcoffset0 << 0)); +} + +/** + * @brief Unpacks DCOFFSET0's fields from current value of the DCOFFSET0 register. + * + * Reads the DCOFFSET0 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] txidcoffset0 - Will be populated with the current value of this field from the register. + * @param[out] txqdcoffset0 - Will be populated with the current value of this field from the register. + */ +__INLINE void mdm_dcoffset0_unpack(uint8_t *txidcoffset0, uint8_t *txqdcoffset0) +{ + uint32_t localVal = REG_PL_RD(MDM_DCOFFSET0_ADDR); + + *txidcoffset0 = (localVal & ((uint32_t)0x00FF0000)) >> 16; + *txqdcoffset0 = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +/** + * @brief Returns the current value of the TXIDCOFFSET0 field in the DCOFFSET0 register. + * + * The DCOFFSET0 register will be read and the TXIDCOFFSET0 field's value will be returned. + * + * @return The current value of the TXIDCOFFSET0 field in the DCOFFSET0 register. + */ +__INLINE uint8_t mdm_txidcoffset0_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_DCOFFSET0_ADDR); + return ((localVal & ((uint32_t)0x00FF0000)) >> 16); +} + +/** + * @brief Sets the TXIDCOFFSET0 field of the DCOFFSET0 register. + * + * The DCOFFSET0 register will be read, modified to contain the new field value, and written. + * + * @param[in] txidcoffset0 - The value to set the field to. + */ +__INLINE void mdm_txidcoffset0_setf(uint8_t txidcoffset0) +{ + ASSERT_ERR((((uint32_t)txidcoffset0 << 16) & ~((uint32_t)0x00FF0000)) == 0); + REG_PL_WR(MDM_DCOFFSET0_ADDR, (REG_PL_RD(MDM_DCOFFSET0_ADDR) & ~((uint32_t)0x00FF0000)) | ((uint32_t)txidcoffset0 << 16)); +} + +/** + * @brief Returns the current value of the TXQDCOFFSET0 field in the DCOFFSET0 register. + * + * The DCOFFSET0 register will be read and the TXQDCOFFSET0 field's value will be returned. + * + * @return The current value of the TXQDCOFFSET0 field in the DCOFFSET0 register. + */ +__INLINE uint8_t mdm_txqdcoffset0_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_DCOFFSET0_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +/** + * @brief Sets the TXQDCOFFSET0 field of the DCOFFSET0 register. + * + * The DCOFFSET0 register will be read, modified to contain the new field value, and written. + * + * @param[in] txqdcoffset0 - The value to set the field to. + */ +__INLINE void mdm_txqdcoffset0_setf(uint8_t txqdcoffset0) +{ + ASSERT_ERR((((uint32_t)txqdcoffset0 << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(MDM_DCOFFSET0_ADDR, (REG_PL_RD(MDM_DCOFFSET0_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)txqdcoffset0 << 0)); +} + +/// @} + +/** + * @name SWRESET register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     12           AGCSWRESET   0
+ *     08           DSPSWRESET   0
+ *     04           FSMSWRESET   0
+ *     00           MDMSWRESET   0
+ * 
+ * + * @{ + */ + +/// Address of the SWRESET register +#define MDM_SWRESET_ADDR 0x01000894 +/// Offset of the SWRESET register from the base address +#define MDM_SWRESET_OFFSET 0x00000894 +/// Index of the SWRESET register +#define MDM_SWRESET_INDEX 0x00000225 +/// Reset value of the SWRESET register +#define MDM_SWRESET_RESET 0x00000000 + +/** + * @brief Returns the current value of the SWRESET register. + * The SWRESET register will be read and its value returned. + * @return The current value of the SWRESET register. + */ +__INLINE uint32_t mdm_swreset_get(void) +{ + return REG_PL_RD(MDM_SWRESET_ADDR); +} + +/** + * @brief Sets the SWRESET register to a value. + * The SWRESET register will be written. + * @param value - The value to write. + */ +__INLINE void mdm_swreset_set(uint32_t value) +{ + REG_PL_WR(MDM_SWRESET_ADDR, value); +} + +// field definitions +/// AGCSWRESET field bit +#define MDM_AGCSWRESET_BIT ((uint32_t)0x00001000) +/// AGCSWRESET field position +#define MDM_AGCSWRESET_POS 12 +/// DSPSWRESET field bit +#define MDM_DSPSWRESET_BIT ((uint32_t)0x00000100) +/// DSPSWRESET field position +#define MDM_DSPSWRESET_POS 8 +/// FSMSWRESET field bit +#define MDM_FSMSWRESET_BIT ((uint32_t)0x00000010) +/// FSMSWRESET field position +#define MDM_FSMSWRESET_POS 4 +/// MDMSWRESET field bit +#define MDM_MDMSWRESET_BIT ((uint32_t)0x00000001) +/// MDMSWRESET field position +#define MDM_MDMSWRESET_POS 0 + +/// AGCSWRESET field reset value +#define MDM_AGCSWRESET_RST 0x0 +/// DSPSWRESET field reset value +#define MDM_DSPSWRESET_RST 0x0 +/// FSMSWRESET field reset value +#define MDM_FSMSWRESET_RST 0x0 +/// MDMSWRESET field reset value +#define MDM_MDMSWRESET_RST 0x0 + +/** + * @brief Constructs a value for the SWRESET register given values for its fields + * and writes the value to the register. + * + * @param[in] agcswreset - The value to use for the AGCSWRESET field. + * @param[in] dspswreset - The value to use for the DSPSWRESET field. + * @param[in] fsmswreset - The value to use for the FSMSWRESET field. + * @param[in] mdmswreset - The value to use for the MDMSWRESET field. + */ +__INLINE void mdm_swreset_pack(uint8_t agcswreset, uint8_t dspswreset, uint8_t fsmswreset, uint8_t mdmswreset) +{ + ASSERT_ERR((((uint32_t)agcswreset << 12) & ~((uint32_t)0x00001000)) == 0); + ASSERT_ERR((((uint32_t)dspswreset << 8) & ~((uint32_t)0x00000100)) == 0); + ASSERT_ERR((((uint32_t)fsmswreset << 4) & ~((uint32_t)0x00000010)) == 0); + ASSERT_ERR((((uint32_t)mdmswreset << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(MDM_SWRESET_ADDR, ((uint32_t)agcswreset << 12) | ((uint32_t)dspswreset << 8) | ((uint32_t)fsmswreset << 4) | ((uint32_t)mdmswreset << 0)); +} + +/** + * @brief Unpacks SWRESET's fields from current value of the SWRESET register. + * + * Reads the SWRESET register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] agcswreset - Will be populated with the current value of this field from the register. + * @param[out] dspswreset - Will be populated with the current value of this field from the register. + * @param[out] fsmswreset - Will be populated with the current value of this field from the register. + * @param[out] mdmswreset - Will be populated with the current value of this field from the register. + */ +__INLINE void mdm_swreset_unpack(uint8_t *agcswreset, uint8_t *dspswreset, uint8_t *fsmswreset, uint8_t *mdmswreset) +{ + uint32_t localVal = REG_PL_RD(MDM_SWRESET_ADDR); + + *agcswreset = (localVal & ((uint32_t)0x00001000)) >> 12; + *dspswreset = (localVal & ((uint32_t)0x00000100)) >> 8; + *fsmswreset = (localVal & ((uint32_t)0x00000010)) >> 4; + *mdmswreset = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +/** + * @brief Returns the current value of the AGCSWRESET field in the SWRESET register. + * + * The SWRESET register will be read and the AGCSWRESET field's value will be returned. + * + * @return The current value of the AGCSWRESET field in the SWRESET register. + */ +__INLINE uint8_t mdm_agcswreset_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_SWRESET_ADDR); + return ((localVal & ((uint32_t)0x00001000)) >> 12); +} + +/** + * @brief Sets the AGCSWRESET field of the SWRESET register. + * + * The SWRESET register will be read, modified to contain the new field value, and written. + * + * @param[in] agcswreset - The value to set the field to. + */ +__INLINE void mdm_agcswreset_setf(uint8_t agcswreset) +{ + ASSERT_ERR((((uint32_t)agcswreset << 12) & ~((uint32_t)0x00001000)) == 0); + REG_PL_WR(MDM_SWRESET_ADDR, (REG_PL_RD(MDM_SWRESET_ADDR) & ~((uint32_t)0x00001000)) | ((uint32_t)agcswreset << 12)); +} + +/** + * @brief Returns the current value of the DSPSWRESET field in the SWRESET register. + * + * The SWRESET register will be read and the DSPSWRESET field's value will be returned. + * + * @return The current value of the DSPSWRESET field in the SWRESET register. + */ +__INLINE uint8_t mdm_dspswreset_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_SWRESET_ADDR); + return ((localVal & ((uint32_t)0x00000100)) >> 8); +} + +/** + * @brief Sets the DSPSWRESET field of the SWRESET register. + * + * The SWRESET register will be read, modified to contain the new field value, and written. + * + * @param[in] dspswreset - The value to set the field to. + */ +__INLINE void mdm_dspswreset_setf(uint8_t dspswreset) +{ + ASSERT_ERR((((uint32_t)dspswreset << 8) & ~((uint32_t)0x00000100)) == 0); + REG_PL_WR(MDM_SWRESET_ADDR, (REG_PL_RD(MDM_SWRESET_ADDR) & ~((uint32_t)0x00000100)) | ((uint32_t)dspswreset << 8)); +} + +/** + * @brief Returns the current value of the FSMSWRESET field in the SWRESET register. + * + * The SWRESET register will be read and the FSMSWRESET field's value will be returned. + * + * @return The current value of the FSMSWRESET field in the SWRESET register. + */ +__INLINE uint8_t mdm_fsmswreset_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_SWRESET_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +/** + * @brief Sets the FSMSWRESET field of the SWRESET register. + * + * The SWRESET register will be read, modified to contain the new field value, and written. + * + * @param[in] fsmswreset - The value to set the field to. + */ +__INLINE void mdm_fsmswreset_setf(uint8_t fsmswreset) +{ + ASSERT_ERR((((uint32_t)fsmswreset << 4) & ~((uint32_t)0x00000010)) == 0); + REG_PL_WR(MDM_SWRESET_ADDR, (REG_PL_RD(MDM_SWRESET_ADDR) & ~((uint32_t)0x00000010)) | ((uint32_t)fsmswreset << 4)); +} + +/** + * @brief Returns the current value of the MDMSWRESET field in the SWRESET register. + * + * The SWRESET register will be read and the MDMSWRESET field's value will be returned. + * + * @return The current value of the MDMSWRESET field in the SWRESET register. + */ +__INLINE uint8_t mdm_mdmswreset_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_SWRESET_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/** + * @brief Sets the MDMSWRESET field of the SWRESET register. + * + * The SWRESET register will be read, modified to contain the new field value, and written. + * + * @param[in] mdmswreset - The value to set the field to. + */ +__INLINE void mdm_mdmswreset_setf(uint8_t mdmswreset) +{ + ASSERT_ERR((((uint32_t)mdmswreset << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(MDM_SWRESET_ADDR, (REG_PL_RD(MDM_SWRESET_ADDR) & ~((uint32_t)0x00000001)) | ((uint32_t)mdmswreset << 0)); +} + +/// @} + + +#endif // _REG_MDM_CFG_H_ + +/// @} + diff --git a/beken_os/beken378/driver/common/reg/reg_mdm_stat.h b/beken_os/beken378/driver/common/reg/reg_mdm_stat.h new file mode 100755 index 0000000..97209af --- /dev/null +++ b/beken_os/beken378/driver/common/reg/reg_mdm_stat.h @@ -0,0 +1,3855 @@ +/** + * @file reg_mdm_stat.h + * @brief Definitions of the MDM HW block registers and register access functions. + * + * @defgroup REG_MDM_STAT REG_MDM_STAT + * @ingroup REG + * @{ + * + * @brief Definitions of the MDM HW block registers and register access functions. + */ +#ifndef _REG_MDM_STAT_H_ +#define _REG_MDM_STAT_H_ + +#include "co_int.h" +#include "_reg_mdm_stat.h" +#include "compiler.h" +#include "arch.h" +#include "reg_access.h" + +/** @brief Number of registers in the REG_MDM_STAT peripheral. + */ +#define REG_MDM_STAT_COUNT 27 + +/** @brief Decoding mask of the REG_MDM_STAT peripheral registers from the CPU point of view. + */ +#define REG_MDM_STAT_DECODING_MASK 0x0000007F + +/** + * @name NXVERSION register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00            PHYConfig   0x0
+ * 
+ * + * @{ + */ + +/// Address of the NXVERSION register +#define MDM_NXVERSION_ADDR 0x01000000 +/// Offset of the NXVERSION register from the base address +#define MDM_NXVERSION_OFFSET 0x00000000 +/// Index of the NXVERSION register +#define MDM_NXVERSION_INDEX 0x00000000 +/// Reset value of the NXVERSION register +#define MDM_NXVERSION_RESET 0x00000000 + +/** + * @brief Returns the current value of the NXVERSION register. + * The NXVERSION register will be read and its value returned. + * @return The current value of the NXVERSION register. + */ +__INLINE uint32_t mdm_nxversion_get(void) +{ + return REG_PL_RD(MDM_NXVERSION_ADDR); +} + +// field definitions +/// PHY_CONFIG field mask +#define MDM_PHY_CONFIG_MASK ((uint32_t)0xFFFFFFFF) +/// PHY_CONFIG field LSB position +#define MDM_PHY_CONFIG_LSB 0 +/// PHY_CONFIG field width +#define MDM_PHY_CONFIG_WIDTH ((uint32_t)0x00000020) + +/// PHY_CONFIG field reset value +#define MDM_PHY_CONFIG_RST 0x0 + +/** + * @brief Returns the current value of the PHYConfig field in the NXVERSION register. + * + * The NXVERSION register will be read and the PHYConfig field's value will be returned. + * + * @return The current value of the PHYConfig field in the NXVERSION register. + */ +__INLINE uint32_t mdm_phy_config_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_NXVERSION_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +/// @} + +/** + * @name TDOFFSETSTAT0 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  20:00        COARSEFOANGLE   0x0
+ * 
+ * + * @{ + */ + +/// Address of the TDOFFSETSTAT0 register +#define MDM_TDOFFSETSTAT0_ADDR 0x01000004 +/// Offset of the TDOFFSETSTAT0 register from the base address +#define MDM_TDOFFSETSTAT0_OFFSET 0x00000004 +/// Index of the TDOFFSETSTAT0 register +#define MDM_TDOFFSETSTAT0_INDEX 0x00000001 +/// Reset value of the TDOFFSETSTAT0 register +#define MDM_TDOFFSETSTAT0_RESET 0x00000000 + +/** + * @brief Returns the current value of the TDOFFSETSTAT0 register. + * The TDOFFSETSTAT0 register will be read and its value returned. + * @return The current value of the TDOFFSETSTAT0 register. + */ +__INLINE uint32_t mdm_tdoffsetstat0_get(void) +{ + return REG_PL_RD(MDM_TDOFFSETSTAT0_ADDR); +} + +// field definitions +/// COARSEFOANGLE field mask +#define MDM_COARSEFOANGLE_MASK ((uint32_t)0x001FFFFF) +/// COARSEFOANGLE field LSB position +#define MDM_COARSEFOANGLE_LSB 0 +/// COARSEFOANGLE field width +#define MDM_COARSEFOANGLE_WIDTH ((uint32_t)0x00000015) + +/// COARSEFOANGLE field reset value +#define MDM_COARSEFOANGLE_RST 0x0 + +/** + * @brief Returns the current value of the COARSEFOANGLE field in the TDOFFSETSTAT0 register. + * + * The TDOFFSETSTAT0 register will be read and the COARSEFOANGLE field's value will be returned. + * + * @return The current value of the COARSEFOANGLE field in the TDOFFSETSTAT0 register. + */ +__INLINE uint32_t mdm_coarsefoangle_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TDOFFSETSTAT0_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x001FFFFF)) == 0); + return (localVal >> 0); +} + +/// @} + +/** + * @name TDOFFSETSTAT1 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  20:00          FINEFOANGLE   0x0
+ * 
+ * + * @{ + */ + +/// Address of the TDOFFSETSTAT1 register +#define MDM_TDOFFSETSTAT1_ADDR 0x01000008 +/// Offset of the TDOFFSETSTAT1 register from the base address +#define MDM_TDOFFSETSTAT1_OFFSET 0x00000008 +/// Index of the TDOFFSETSTAT1 register +#define MDM_TDOFFSETSTAT1_INDEX 0x00000002 +/// Reset value of the TDOFFSETSTAT1 register +#define MDM_TDOFFSETSTAT1_RESET 0x00000000 + +/** + * @brief Returns the current value of the TDOFFSETSTAT1 register. + * The TDOFFSETSTAT1 register will be read and its value returned. + * @return The current value of the TDOFFSETSTAT1 register. + */ +__INLINE uint32_t mdm_tdoffsetstat1_get(void) +{ + return REG_PL_RD(MDM_TDOFFSETSTAT1_ADDR); +} + +// field definitions +/// FINEFOANGLE field mask +#define MDM_FINEFOANGLE_MASK ((uint32_t)0x001FFFFF) +/// FINEFOANGLE field LSB position +#define MDM_FINEFOANGLE_LSB 0 +/// FINEFOANGLE field width +#define MDM_FINEFOANGLE_WIDTH ((uint32_t)0x00000015) + +/// FINEFOANGLE field reset value +#define MDM_FINEFOANGLE_RST 0x0 + +/** + * @brief Returns the current value of the FINEFOANGLE field in the TDOFFSETSTAT1 register. + * + * The TDOFFSETSTAT1 register will be read and the FINEFOANGLE field's value will be returned. + * + * @return The current value of the FINEFOANGLE field in the TDOFFSETSTAT1 register. + */ +__INLINE uint32_t mdm_finefoangle_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TDOFFSETSTAT1_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x001FFFFF)) == 0); + return (localVal >> 0); +} + +/// @} + +/** + * @name FDTOFFSETSTAT0 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  29:12         STOSLOPESTAT   0x0
+ *  05:00       TDSYNCHOFFSTAT   0x0
+ * 
+ * + * @{ + */ + +/// Address of the FDTOFFSETSTAT0 register +#define MDM_FDTOFFSETSTAT0_ADDR 0x0100000C +/// Offset of the FDTOFFSETSTAT0 register from the base address +#define MDM_FDTOFFSETSTAT0_OFFSET 0x0000000C +/// Index of the FDTOFFSETSTAT0 register +#define MDM_FDTOFFSETSTAT0_INDEX 0x00000003 +/// Reset value of the FDTOFFSETSTAT0 register +#define MDM_FDTOFFSETSTAT0_RESET 0x00000000 + +/** + * @brief Returns the current value of the FDTOFFSETSTAT0 register. + * The FDTOFFSETSTAT0 register will be read and its value returned. + * @return The current value of the FDTOFFSETSTAT0 register. + */ +__INLINE uint32_t mdm_fdtoffsetstat0_get(void) +{ + return REG_PL_RD(MDM_FDTOFFSETSTAT0_ADDR); +} + +// field definitions +/// STOSLOPESTAT field mask +#define MDM_STOSLOPESTAT_MASK ((uint32_t)0x3FFFF000) +/// STOSLOPESTAT field LSB position +#define MDM_STOSLOPESTAT_LSB 12 +/// STOSLOPESTAT field width +#define MDM_STOSLOPESTAT_WIDTH ((uint32_t)0x00000012) +/// TDSYNCHOFFSTAT field mask +#define MDM_TDSYNCHOFFSTAT_MASK ((uint32_t)0x0000003F) +/// TDSYNCHOFFSTAT field LSB position +#define MDM_TDSYNCHOFFSTAT_LSB 0 +/// TDSYNCHOFFSTAT field width +#define MDM_TDSYNCHOFFSTAT_WIDTH ((uint32_t)0x00000006) + +/// STOSLOPESTAT field reset value +#define MDM_STOSLOPESTAT_RST 0x0 +/// TDSYNCHOFFSTAT field reset value +#define MDM_TDSYNCHOFFSTAT_RST 0x0 + +/** + * @brief Unpacks FDTOFFSETSTAT0's fields from current value of the FDTOFFSETSTAT0 register. + * + * Reads the FDTOFFSETSTAT0 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] stoslopestat - Will be populated with the current value of this field from the register. + * @param[out] tdsynchoffstat - Will be populated with the current value of this field from the register. + */ +__INLINE void mdm_fdtoffsetstat0_unpack(uint32_t *stoslopestat, uint8_t *tdsynchoffstat) +{ + uint32_t localVal = REG_PL_RD(MDM_FDTOFFSETSTAT0_ADDR); + + *stoslopestat = (localVal & ((uint32_t)0x3FFFF000)) >> 12; + *tdsynchoffstat = (localVal & ((uint32_t)0x0000003F)) >> 0; +} + +/** + * @brief Returns the current value of the STOSLOPESTAT field in the FDTOFFSETSTAT0 register. + * + * The FDTOFFSETSTAT0 register will be read and the STOSLOPESTAT field's value will be returned. + * + * @return The current value of the STOSLOPESTAT field in the FDTOFFSETSTAT0 register. + */ +__INLINE uint32_t mdm_stoslopestat_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_FDTOFFSETSTAT0_ADDR); + return ((localVal & ((uint32_t)0x3FFFF000)) >> 12); +} + +/** + * @brief Returns the current value of the TDSYNCHOFFSTAT field in the FDTOFFSETSTAT0 register. + * + * The FDTOFFSETSTAT0 register will be read and the TDSYNCHOFFSTAT field's value will be returned. + * + * @return The current value of the TDSYNCHOFFSTAT field in the FDTOFFSETSTAT0 register. + */ +__INLINE uint8_t mdm_tdsynchoffstat_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_FDTOFFSETSTAT0_ADDR); + return ((localVal & ((uint32_t)0x0000003F)) >> 0); +} + +/// @} + +/** + * @name FDTOFFSETSTAT1 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  17:00         CPESLOPESTAT   0x0
+ * 
+ * + * @{ + */ + +/// Address of the FDTOFFSETSTAT1 register +#define MDM_FDTOFFSETSTAT1_ADDR 0x01000010 +/// Offset of the FDTOFFSETSTAT1 register from the base address +#define MDM_FDTOFFSETSTAT1_OFFSET 0x00000010 +/// Index of the FDTOFFSETSTAT1 register +#define MDM_FDTOFFSETSTAT1_INDEX 0x00000004 +/// Reset value of the FDTOFFSETSTAT1 register +#define MDM_FDTOFFSETSTAT1_RESET 0x00000000 + +/** + * @brief Returns the current value of the FDTOFFSETSTAT1 register. + * The FDTOFFSETSTAT1 register will be read and its value returned. + * @return The current value of the FDTOFFSETSTAT1 register. + */ +__INLINE uint32_t mdm_fdtoffsetstat1_get(void) +{ + return REG_PL_RD(MDM_FDTOFFSETSTAT1_ADDR); +} + +// field definitions +/// CPESLOPESTAT field mask +#define MDM_CPESLOPESTAT_MASK ((uint32_t)0x0003FFFF) +/// CPESLOPESTAT field LSB position +#define MDM_CPESLOPESTAT_LSB 0 +/// CPESLOPESTAT field width +#define MDM_CPESLOPESTAT_WIDTH ((uint32_t)0x00000012) + +/// CPESLOPESTAT field reset value +#define MDM_CPESLOPESTAT_RST 0x0 + +/** + * @brief Returns the current value of the CPESLOPESTAT field in the FDTOFFSETSTAT1 register. + * + * The FDTOFFSETSTAT1 register will be read and the CPESLOPESTAT field's value will be returned. + * + * @return The current value of the CPESLOPESTAT field in the FDTOFFSETSTAT1 register. + */ +__INLINE uint32_t mdm_cpeslopestat_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_FDTOFFSETSTAT1_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x0003FFFF)) == 0); + return (localVal >> 0); +} + +/// @} + +/** + * @name RXFSMSTAT0 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:16           FDSYMBOLNR   0x0
+ *  15:00           TDSYMBOLNR   0x0
+ * 
+ * + * @{ + */ + +/// Address of the RXFSMSTAT0 register +#define MDM_RXFSMSTAT0_ADDR 0x01000014 +/// Offset of the RXFSMSTAT0 register from the base address +#define MDM_RXFSMSTAT0_OFFSET 0x00000014 +/// Index of the RXFSMSTAT0 register +#define MDM_RXFSMSTAT0_INDEX 0x00000005 +/// Reset value of the RXFSMSTAT0 register +#define MDM_RXFSMSTAT0_RESET 0x00000000 + +/** + * @brief Returns the current value of the RXFSMSTAT0 register. + * The RXFSMSTAT0 register will be read and its value returned. + * @return The current value of the RXFSMSTAT0 register. + */ +__INLINE uint32_t mdm_rxfsmstat0_get(void) +{ + return REG_PL_RD(MDM_RXFSMSTAT0_ADDR); +} + +// field definitions +/// FDSYMBOLNR field mask +#define MDM_FDSYMBOLNR_MASK ((uint32_t)0xFFFF0000) +/// FDSYMBOLNR field LSB position +#define MDM_FDSYMBOLNR_LSB 16 +/// FDSYMBOLNR field width +#define MDM_FDSYMBOLNR_WIDTH ((uint32_t)0x00000010) +/// TDSYMBOLNR field mask +#define MDM_TDSYMBOLNR_MASK ((uint32_t)0x0000FFFF) +/// TDSYMBOLNR field LSB position +#define MDM_TDSYMBOLNR_LSB 0 +/// TDSYMBOLNR field width +#define MDM_TDSYMBOLNR_WIDTH ((uint32_t)0x00000010) + +/// FDSYMBOLNR field reset value +#define MDM_FDSYMBOLNR_RST 0x0 +/// TDSYMBOLNR field reset value +#define MDM_TDSYMBOLNR_RST 0x0 + +/** + * @brief Unpacks RXFSMSTAT0's fields from current value of the RXFSMSTAT0 register. + * + * Reads the RXFSMSTAT0 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] fdsymbolnr - Will be populated with the current value of this field from the register. + * @param[out] tdsymbolnr - Will be populated with the current value of this field from the register. + */ +__INLINE void mdm_rxfsmstat0_unpack(uint16_t *fdsymbolnr, uint16_t *tdsymbolnr) +{ + uint32_t localVal = REG_PL_RD(MDM_RXFSMSTAT0_ADDR); + + *fdsymbolnr = (localVal & ((uint32_t)0xFFFF0000)) >> 16; + *tdsymbolnr = (localVal & ((uint32_t)0x0000FFFF)) >> 0; +} + +/** + * @brief Returns the current value of the FDSYMBOLNR field in the RXFSMSTAT0 register. + * + * The RXFSMSTAT0 register will be read and the FDSYMBOLNR field's value will be returned. + * + * @return The current value of the FDSYMBOLNR field in the RXFSMSTAT0 register. + */ +__INLINE uint16_t mdm_fdsymbolnr_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXFSMSTAT0_ADDR); + return ((localVal & ((uint32_t)0xFFFF0000)) >> 16); +} + +/** + * @brief Returns the current value of the TDSYMBOLNR field in the RXFSMSTAT0 register. + * + * The RXFSMSTAT0 register will be read and the TDSYMBOLNR field's value will be returned. + * + * @return The current value of the TDSYMBOLNR field in the RXFSMSTAT0 register. + */ +__INLINE uint16_t mdm_tdsymbolnr_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXFSMSTAT0_ADDR); + return ((localVal & ((uint32_t)0x0000FFFF)) >> 0); +} + +/// @} + +/** + * @name RXFSMSTAT1 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:24              FDSTATE   0x0
+ *  21:16             GILENGTH   0x0
+ *     13               STBCEN   0
+ *  11:10              TDBWREG   0x0
+ *  09:08              FDBWREG   0x0
+ *  06:04           RXMODESTAT   0x0
+ *  02:00         FDSYMBOLTYPE   0x0
+ * 
+ * + * @{ + */ + +/// Address of the RXFSMSTAT1 register +#define MDM_RXFSMSTAT1_ADDR 0x01000018 +/// Offset of the RXFSMSTAT1 register from the base address +#define MDM_RXFSMSTAT1_OFFSET 0x00000018 +/// Index of the RXFSMSTAT1 register +#define MDM_RXFSMSTAT1_INDEX 0x00000006 +/// Reset value of the RXFSMSTAT1 register +#define MDM_RXFSMSTAT1_RESET 0x00000000 + +/** + * @brief Returns the current value of the RXFSMSTAT1 register. + * The RXFSMSTAT1 register will be read and its value returned. + * @return The current value of the RXFSMSTAT1 register. + */ +__INLINE uint32_t mdm_rxfsmstat1_get(void) +{ + return REG_PL_RD(MDM_RXFSMSTAT1_ADDR); +} + +// field definitions +/// FDSTATE field mask +#define MDM_FDSTATE_MASK ((uint32_t)0xFF000000) +/// FDSTATE field LSB position +#define MDM_FDSTATE_LSB 24 +/// FDSTATE field width +#define MDM_FDSTATE_WIDTH ((uint32_t)0x00000008) +/// GILENGTH field mask +#define MDM_GILENGTH_MASK ((uint32_t)0x003F0000) +/// GILENGTH field LSB position +#define MDM_GILENGTH_LSB 16 +/// GILENGTH field width +#define MDM_GILENGTH_WIDTH ((uint32_t)0x00000006) +/// STBCEN field bit +#define MDM_STBCEN_BIT ((uint32_t)0x00002000) +/// STBCEN field position +#define MDM_STBCEN_POS 13 +/// TDBWREG field mask +#define MDM_TDBWREG_MASK ((uint32_t)0x00000C00) +/// TDBWREG field LSB position +#define MDM_TDBWREG_LSB 10 +/// TDBWREG field width +#define MDM_TDBWREG_WIDTH ((uint32_t)0x00000002) +/// FDBWREG field mask +#define MDM_FDBWREG_MASK ((uint32_t)0x00000300) +/// FDBWREG field LSB position +#define MDM_FDBWREG_LSB 8 +/// FDBWREG field width +#define MDM_FDBWREG_WIDTH ((uint32_t)0x00000002) +/// RXMODESTAT field mask +#define MDM_RXMODESTAT_MASK ((uint32_t)0x00000070) +/// RXMODESTAT field LSB position +#define MDM_RXMODESTAT_LSB 4 +/// RXMODESTAT field width +#define MDM_RXMODESTAT_WIDTH ((uint32_t)0x00000003) +/// FDSYMBOLTYPE field mask +#define MDM_FDSYMBOLTYPE_MASK ((uint32_t)0x00000007) +/// FDSYMBOLTYPE field LSB position +#define MDM_FDSYMBOLTYPE_LSB 0 +/// FDSYMBOLTYPE field width +#define MDM_FDSYMBOLTYPE_WIDTH ((uint32_t)0x00000003) + +/// FDSTATE field reset value +#define MDM_FDSTATE_RST 0x0 +/// GILENGTH field reset value +#define MDM_GILENGTH_RST 0x0 +/// STBCEN field reset value +#define MDM_STBCEN_RST 0x0 +/// TDBWREG field reset value +#define MDM_TDBWREG_RST 0x0 +/// FDBWREG field reset value +#define MDM_FDBWREG_RST 0x0 +/// RXMODESTAT field reset value +#define MDM_RXMODESTAT_RST 0x0 +/// FDSYMBOLTYPE field reset value +#define MDM_FDSYMBOLTYPE_RST 0x0 + +/** + * @brief Unpacks RXFSMSTAT1's fields from current value of the RXFSMSTAT1 register. + * + * Reads the RXFSMSTAT1 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] fdstate - Will be populated with the current value of this field from the register. + * @param[out] gilength - Will be populated with the current value of this field from the register. + * @param[out] stbcen - Will be populated with the current value of this field from the register. + * @param[out] tdbwreg - Will be populated with the current value of this field from the register. + * @param[out] fdbwreg - Will be populated with the current value of this field from the register. + * @param[out] rxmodestat - Will be populated with the current value of this field from the register. + * @param[out] fdsymboltype - Will be populated with the current value of this field from the register. + */ +__INLINE void mdm_rxfsmstat1_unpack(uint8_t *fdstate, uint8_t *gilength, uint8_t *stbcen, uint8_t *tdbwreg, uint8_t *fdbwreg, uint8_t *rxmodestat, uint8_t *fdsymboltype) +{ + uint32_t localVal = REG_PL_RD(MDM_RXFSMSTAT1_ADDR); + + *fdstate = (localVal & ((uint32_t)0xFF000000)) >> 24; + *gilength = (localVal & ((uint32_t)0x003F0000)) >> 16; + *stbcen = (localVal & ((uint32_t)0x00002000)) >> 13; + *tdbwreg = (localVal & ((uint32_t)0x00000C00)) >> 10; + *fdbwreg = (localVal & ((uint32_t)0x00000300)) >> 8; + *rxmodestat = (localVal & ((uint32_t)0x00000070)) >> 4; + *fdsymboltype = (localVal & ((uint32_t)0x00000007)) >> 0; +} + +/** + * @brief Returns the current value of the FDSTATE field in the RXFSMSTAT1 register. + * + * The RXFSMSTAT1 register will be read and the FDSTATE field's value will be returned. + * + * @return The current value of the FDSTATE field in the RXFSMSTAT1 register. + */ +__INLINE uint8_t mdm_fdstate_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXFSMSTAT1_ADDR); + return ((localVal & ((uint32_t)0xFF000000)) >> 24); +} + +/** + * @brief Returns the current value of the GILENGTH field in the RXFSMSTAT1 register. + * + * The RXFSMSTAT1 register will be read and the GILENGTH field's value will be returned. + * + * @return The current value of the GILENGTH field in the RXFSMSTAT1 register. + */ +__INLINE uint8_t mdm_gilength_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXFSMSTAT1_ADDR); + return ((localVal & ((uint32_t)0x003F0000)) >> 16); +} + +/** + * @brief Returns the current value of the STBCEN field in the RXFSMSTAT1 register. + * + * The RXFSMSTAT1 register will be read and the STBCEN field's value will be returned. + * + * @return The current value of the STBCEN field in the RXFSMSTAT1 register. + */ +__INLINE uint8_t mdm_stbcen_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXFSMSTAT1_ADDR); + return ((localVal & ((uint32_t)0x00002000)) >> 13); +} + +/** + * @brief Returns the current value of the TDBWREG field in the RXFSMSTAT1 register. + * + * The RXFSMSTAT1 register will be read and the TDBWREG field's value will be returned. + * + * @return The current value of the TDBWREG field in the RXFSMSTAT1 register. + */ +__INLINE uint8_t mdm_tdbwreg_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXFSMSTAT1_ADDR); + return ((localVal & ((uint32_t)0x00000C00)) >> 10); +} + +/** + * @brief Returns the current value of the FDBWREG field in the RXFSMSTAT1 register. + * + * The RXFSMSTAT1 register will be read and the FDBWREG field's value will be returned. + * + * @return The current value of the FDBWREG field in the RXFSMSTAT1 register. + */ +__INLINE uint8_t mdm_fdbwreg_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXFSMSTAT1_ADDR); + return ((localVal & ((uint32_t)0x00000300)) >> 8); +} + +/** + * @brief Returns the current value of the RXMODESTAT field in the RXFSMSTAT1 register. + * + * The RXFSMSTAT1 register will be read and the RXMODESTAT field's value will be returned. + * + * @return The current value of the RXMODESTAT field in the RXFSMSTAT1 register. + */ +__INLINE uint8_t mdm_rxmodestat_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXFSMSTAT1_ADDR); + return ((localVal & ((uint32_t)0x00000070)) >> 4); +} + +/** + * @brief Returns the current value of the FDSYMBOLTYPE field in the RXFSMSTAT1 register. + * + * The RXFSMSTAT1 register will be read and the FDSYMBOLTYPE field's value will be returned. + * + * @return The current value of the FDSYMBOLTYPE field in the RXFSMSTAT1 register. + */ +__INLINE uint8_t mdm_fdsymboltype_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXFSMSTAT1_ADDR); + return ((localVal & ((uint32_t)0x00000007)) >> 0); +} + +/// @} + +/** + * @name TXFSMSTAT1 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     00       PhyTxAbortStat   0
+ * 
+ * + * @{ + */ + +/// Address of the TXFSMSTAT1 register +#define MDM_TXFSMSTAT1_ADDR 0x0100001C +/// Offset of the TXFSMSTAT1 register from the base address +#define MDM_TXFSMSTAT1_OFFSET 0x0000001C +/// Index of the TXFSMSTAT1 register +#define MDM_TXFSMSTAT1_INDEX 0x00000007 +/// Reset value of the TXFSMSTAT1 register +#define MDM_TXFSMSTAT1_RESET 0x00000000 + +/** + * @brief Returns the current value of the TXFSMSTAT1 register. + * The TXFSMSTAT1 register will be read and its value returned. + * @return The current value of the TXFSMSTAT1 register. + */ +__INLINE uint32_t mdm_txfsmstat1_get(void) +{ + return REG_PL_RD(MDM_TXFSMSTAT1_ADDR); +} + +// field definitions +/// PHY_TX_ABORT_STAT field bit +#define MDM_PHY_TX_ABORT_STAT_BIT ((uint32_t)0x00000001) +/// PHY_TX_ABORT_STAT field position +#define MDM_PHY_TX_ABORT_STAT_POS 0 + +/// PHY_TX_ABORT_STAT field reset value +#define MDM_PHY_TX_ABORT_STAT_RST 0x0 + +/** + * @brief Returns the current value of the PhyTxAbortStat field in the TXFSMSTAT1 register. + * + * The TXFSMSTAT1 register will be read and the PhyTxAbortStat field's value will be returned. + * + * @return The current value of the PhyTxAbortStat field in the TXFSMSTAT1 register. + */ +__INLINE uint8_t mdm_phy_tx_abort_stat_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TXFSMSTAT1_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x00000001)) == 0); + return (localVal >> 0); +} + +/// @} + +/** + * @name ERRSTAT register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     06           TXOVERFLOW   0
+ *     05          TXFORMATERR   0
+ *     04           TXUNDERRUN   0
+ *     03            AGCUNLOCK   0
+ *     02          RXFORMATERR   0
+ *     01             HTSIGCRC   0
+ *     00           LSIGPARITY   0
+ * 
+ * + * @{ + */ + +/// Address of the ERRSTAT register +#define MDM_ERRSTAT_ADDR 0x01000020 +/// Offset of the ERRSTAT register from the base address +#define MDM_ERRSTAT_OFFSET 0x00000020 +/// Index of the ERRSTAT register +#define MDM_ERRSTAT_INDEX 0x00000008 +/// Reset value of the ERRSTAT register +#define MDM_ERRSTAT_RESET 0x00000000 + +/** + * @brief Returns the current value of the ERRSTAT register. + * The ERRSTAT register will be read and its value returned. + * @return The current value of the ERRSTAT register. + */ +__INLINE uint32_t mdm_errstat_get(void) +{ + return REG_PL_RD(MDM_ERRSTAT_ADDR); +} + +// field definitions +/// TXOVERFLOW field bit +#define MDM_TXOVERFLOW_BIT ((uint32_t)0x00000040) +/// TXOVERFLOW field position +#define MDM_TXOVERFLOW_POS 6 +/// TXFORMATERR field bit +#define MDM_TXFORMATERR_BIT ((uint32_t)0x00000020) +/// TXFORMATERR field position +#define MDM_TXFORMATERR_POS 5 +/// TXUNDERRUN field bit +#define MDM_TXUNDERRUN_BIT ((uint32_t)0x00000010) +/// TXUNDERRUN field position +#define MDM_TXUNDERRUN_POS 4 +/// AGCUNLOCK field bit +#define MDM_AGCUNLOCK_BIT ((uint32_t)0x00000008) +/// AGCUNLOCK field position +#define MDM_AGCUNLOCK_POS 3 +/// RXFORMATERR field bit +#define MDM_RXFORMATERR_BIT ((uint32_t)0x00000004) +/// RXFORMATERR field position +#define MDM_RXFORMATERR_POS 2 +/// HTSIGCRC field bit +#define MDM_HTSIGCRC_BIT ((uint32_t)0x00000002) +/// HTSIGCRC field position +#define MDM_HTSIGCRC_POS 1 +/// LSIGPARITY field bit +#define MDM_LSIGPARITY_BIT ((uint32_t)0x00000001) +/// LSIGPARITY field position +#define MDM_LSIGPARITY_POS 0 + +/// TXOVERFLOW field reset value +#define MDM_TXOVERFLOW_RST 0x0 +/// TXFORMATERR field reset value +#define MDM_TXFORMATERR_RST 0x0 +/// TXUNDERRUN field reset value +#define MDM_TXUNDERRUN_RST 0x0 +/// AGCUNLOCK field reset value +#define MDM_AGCUNLOCK_RST 0x0 +/// RXFORMATERR field reset value +#define MDM_RXFORMATERR_RST 0x0 +/// HTSIGCRC field reset value +#define MDM_HTSIGCRC_RST 0x0 +/// LSIGPARITY field reset value +#define MDM_LSIGPARITY_RST 0x0 + +/** + * @brief Unpacks ERRSTAT's fields from current value of the ERRSTAT register. + * + * Reads the ERRSTAT register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] txoverflow - Will be populated with the current value of this field from the register. + * @param[out] txformaterr - Will be populated with the current value of this field from the register. + * @param[out] txunderrun - Will be populated with the current value of this field from the register. + * @param[out] agcunlock - Will be populated with the current value of this field from the register. + * @param[out] rxformaterr - Will be populated with the current value of this field from the register. + * @param[out] htsigcrc - Will be populated with the current value of this field from the register. + * @param[out] lsigparity - Will be populated with the current value of this field from the register. + */ +__INLINE void mdm_errstat_unpack(uint8_t *txoverflow, uint8_t *txformaterr, uint8_t *txunderrun, uint8_t *agcunlock, uint8_t *rxformaterr, uint8_t *htsigcrc, uint8_t *lsigparity) +{ + uint32_t localVal = REG_PL_RD(MDM_ERRSTAT_ADDR); + + *txoverflow = (localVal & ((uint32_t)0x00000040)) >> 6; + *txformaterr = (localVal & ((uint32_t)0x00000020)) >> 5; + *txunderrun = (localVal & ((uint32_t)0x00000010)) >> 4; + *agcunlock = (localVal & ((uint32_t)0x00000008)) >> 3; + *rxformaterr = (localVal & ((uint32_t)0x00000004)) >> 2; + *htsigcrc = (localVal & ((uint32_t)0x00000002)) >> 1; + *lsigparity = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +/** + * @brief Returns the current value of the TXOVERFLOW field in the ERRSTAT register. + * + * The ERRSTAT register will be read and the TXOVERFLOW field's value will be returned. + * + * @return The current value of the TXOVERFLOW field in the ERRSTAT register. + */ +__INLINE uint8_t mdm_txoverflow_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_ERRSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000040)) >> 6); +} + +/** + * @brief Returns the current value of the TXFORMATERR field in the ERRSTAT register. + * + * The ERRSTAT register will be read and the TXFORMATERR field's value will be returned. + * + * @return The current value of the TXFORMATERR field in the ERRSTAT register. + */ +__INLINE uint8_t mdm_txformaterr_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_ERRSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +/** + * @brief Returns the current value of the TXUNDERRUN field in the ERRSTAT register. + * + * The ERRSTAT register will be read and the TXUNDERRUN field's value will be returned. + * + * @return The current value of the TXUNDERRUN field in the ERRSTAT register. + */ +__INLINE uint8_t mdm_txunderrun_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_ERRSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +/** + * @brief Returns the current value of the AGCUNLOCK field in the ERRSTAT register. + * + * The ERRSTAT register will be read and the AGCUNLOCK field's value will be returned. + * + * @return The current value of the AGCUNLOCK field in the ERRSTAT register. + */ +__INLINE uint8_t mdm_agcunlock_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_ERRSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +/** + * @brief Returns the current value of the RXFORMATERR field in the ERRSTAT register. + * + * The ERRSTAT register will be read and the RXFORMATERR field's value will be returned. + * + * @return The current value of the RXFORMATERR field in the ERRSTAT register. + */ +__INLINE uint8_t mdm_rxformaterr_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_ERRSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +/** + * @brief Returns the current value of the HTSIGCRC field in the ERRSTAT register. + * + * The ERRSTAT register will be read and the HTSIGCRC field's value will be returned. + * + * @return The current value of the HTSIGCRC field in the ERRSTAT register. + */ +__INLINE uint8_t mdm_htsigcrc_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_ERRSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +/** + * @brief Returns the current value of the LSIGPARITY field in the ERRSTAT register. + * + * The ERRSTAT register will be read and the LSIGPARITY field's value will be returned. + * + * @return The current value of the LSIGPARITY field in the ERRSTAT register. + */ +__INLINE uint8_t mdm_lsigparity_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_ERRSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/// @} + +/** + * @name IRQSTAT register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     14        IRQHTSIGVALID   0
+ *     13         IRQLSIGVALID   0
+ *     12        IRQTXOVERFLOW   0
+ *     11        IRQTXUNDERRUN   0
+ *     10        IRQCCA40SFALL   0
+ *     09        IRQCCA40SRISE   0
+ *     08             IRQTXEND   0
+ *     07             IRQRXEND   0
+ *     06        IRQCCA20PFALL   0
+ *     05        IRQCCA20SFALL   0
+ *     04        IRQCCA20PRISE   0
+ *     03        IRQCCA20SRISE   0
+ *     02          IRQPHYERROR   0
+ *     01          IRQRADARDET   0
+ *     00        IRQCCATIMEOUT   0
+ * 
+ * + * @{ + */ + +/// Address of the IRQSTAT register +#define MDM_IRQSTAT_ADDR 0x01000024 +/// Offset of the IRQSTAT register from the base address +#define MDM_IRQSTAT_OFFSET 0x00000024 +/// Index of the IRQSTAT register +#define MDM_IRQSTAT_INDEX 0x00000009 +/// Reset value of the IRQSTAT register +#define MDM_IRQSTAT_RESET 0x00000000 + +/** + * @brief Returns the current value of the IRQSTAT register. + * The IRQSTAT register will be read and its value returned. + * @return The current value of the IRQSTAT register. + */ +__INLINE uint32_t mdm_irqstat_get(void) +{ + return REG_PL_RD(MDM_IRQSTAT_ADDR); +} + +// field definitions +/// IRQHTSIGVALID field bit +#define MDM_IRQHTSIGVALID_BIT ((uint32_t)0x00004000) +/// IRQHTSIGVALID field position +#define MDM_IRQHTSIGVALID_POS 14 +/// IRQLSIGVALID field bit +#define MDM_IRQLSIGVALID_BIT ((uint32_t)0x00002000) +/// IRQLSIGVALID field position +#define MDM_IRQLSIGVALID_POS 13 +/// IRQTXOVERFLOW field bit +#define MDM_IRQTXOVERFLOW_BIT ((uint32_t)0x00001000) +/// IRQTXOVERFLOW field position +#define MDM_IRQTXOVERFLOW_POS 12 +/// IRQTXUNDERRUN field bit +#define MDM_IRQTXUNDERRUN_BIT ((uint32_t)0x00000800) +/// IRQTXUNDERRUN field position +#define MDM_IRQTXUNDERRUN_POS 11 +/// IRQCCA40SFALL field bit +#define MDM_IRQCCA40SFALL_BIT ((uint32_t)0x00000400) +/// IRQCCA40SFALL field position +#define MDM_IRQCCA40SFALL_POS 10 +/// IRQCCA40SRISE field bit +#define MDM_IRQCCA40SRISE_BIT ((uint32_t)0x00000200) +/// IRQCCA40SRISE field position +#define MDM_IRQCCA40SRISE_POS 9 +/// IRQTXEND field bit +#define MDM_IRQTXEND_BIT ((uint32_t)0x00000100) +/// IRQTXEND field position +#define MDM_IRQTXEND_POS 8 +/// IRQRXEND field bit +#define MDM_IRQRXEND_BIT ((uint32_t)0x00000080) +/// IRQRXEND field position +#define MDM_IRQRXEND_POS 7 +/// IRQCCA20PFALL field bit +#define MDM_IRQCCA20PFALL_BIT ((uint32_t)0x00000040) +/// IRQCCA20PFALL field position +#define MDM_IRQCCA20PFALL_POS 6 +/// IRQCCA20SFALL field bit +#define MDM_IRQCCA20SFALL_BIT ((uint32_t)0x00000020) +/// IRQCCA20SFALL field position +#define MDM_IRQCCA20SFALL_POS 5 +/// IRQCCA20PRISE field bit +#define MDM_IRQCCA20PRISE_BIT ((uint32_t)0x00000010) +/// IRQCCA20PRISE field position +#define MDM_IRQCCA20PRISE_POS 4 +/// IRQCCA20SRISE field bit +#define MDM_IRQCCA20SRISE_BIT ((uint32_t)0x00000008) +/// IRQCCA20SRISE field position +#define MDM_IRQCCA20SRISE_POS 3 +/// IRQPHYERROR field bit +#define MDM_IRQPHYERROR_BIT ((uint32_t)0x00000004) +/// IRQPHYERROR field position +#define MDM_IRQPHYERROR_POS 2 +/// IRQRADARDET field bit +#define MDM_IRQRADARDET_BIT ((uint32_t)0x00000002) +/// IRQRADARDET field position +#define MDM_IRQRADARDET_POS 1 +/// IRQCCATIMEOUT field bit +#define MDM_IRQCCATIMEOUT_BIT ((uint32_t)0x00000001) +/// IRQCCATIMEOUT field position +#define MDM_IRQCCATIMEOUT_POS 0 + +/// IRQHTSIGVALID field reset value +#define MDM_IRQHTSIGVALID_RST 0x0 +/// IRQLSIGVALID field reset value +#define MDM_IRQLSIGVALID_RST 0x0 +/// IRQTXOVERFLOW field reset value +#define MDM_IRQTXOVERFLOW_RST 0x0 +/// IRQTXUNDERRUN field reset value +#define MDM_IRQTXUNDERRUN_RST 0x0 +/// IRQCCA40SFALL field reset value +#define MDM_IRQCCA40SFALL_RST 0x0 +/// IRQCCA40SRISE field reset value +#define MDM_IRQCCA40SRISE_RST 0x0 +/// IRQTXEND field reset value +#define MDM_IRQTXEND_RST 0x0 +/// IRQRXEND field reset value +#define MDM_IRQRXEND_RST 0x0 +/// IRQCCA20PFALL field reset value +#define MDM_IRQCCA20PFALL_RST 0x0 +/// IRQCCA20SFALL field reset value +#define MDM_IRQCCA20SFALL_RST 0x0 +/// IRQCCA20PRISE field reset value +#define MDM_IRQCCA20PRISE_RST 0x0 +/// IRQCCA20SRISE field reset value +#define MDM_IRQCCA20SRISE_RST 0x0 +/// IRQPHYERROR field reset value +#define MDM_IRQPHYERROR_RST 0x0 +/// IRQRADARDET field reset value +#define MDM_IRQRADARDET_RST 0x0 +/// IRQCCATIMEOUT field reset value +#define MDM_IRQCCATIMEOUT_RST 0x0 + +/** + * @brief Unpacks IRQSTAT's fields from current value of the IRQSTAT register. + * + * Reads the IRQSTAT register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] irqhtsigvalid - Will be populated with the current value of this field from the register. + * @param[out] irqlsigvalid - Will be populated with the current value of this field from the register. + * @param[out] irqtxoverflow - Will be populated with the current value of this field from the register. + * @param[out] irqtxunderrun - Will be populated with the current value of this field from the register. + * @param[out] irqcca40sfall - Will be populated with the current value of this field from the register. + * @param[out] irqcca40srise - Will be populated with the current value of this field from the register. + * @param[out] irqtxend - Will be populated with the current value of this field from the register. + * @param[out] irqrxend - Will be populated with the current value of this field from the register. + * @param[out] irqcca20pfall - Will be populated with the current value of this field from the register. + * @param[out] irqcca20sfall - Will be populated with the current value of this field from the register. + * @param[out] irqcca20prise - Will be populated with the current value of this field from the register. + * @param[out] irqcca20srise - Will be populated with the current value of this field from the register. + * @param[out] irqphyerror - Will be populated with the current value of this field from the register. + * @param[out] irqradardet - Will be populated with the current value of this field from the register. + * @param[out] irqccatimeout - Will be populated with the current value of this field from the register. + */ +__INLINE void mdm_irqstat_unpack(uint8_t *irqhtsigvalid, uint8_t *irqlsigvalid, uint8_t *irqtxoverflow, uint8_t *irqtxunderrun, uint8_t *irqcca40sfall, uint8_t *irqcca40srise, uint8_t *irqtxend, uint8_t *irqrxend, uint8_t *irqcca20pfall, uint8_t *irqcca20sfall, uint8_t *irqcca20prise, uint8_t *irqcca20srise, uint8_t *irqphyerror, uint8_t *irqradardet, uint8_t *irqccatimeout) +{ + uint32_t localVal = REG_PL_RD(MDM_IRQSTAT_ADDR); + + *irqhtsigvalid = (localVal & ((uint32_t)0x00004000)) >> 14; + *irqlsigvalid = (localVal & ((uint32_t)0x00002000)) >> 13; + *irqtxoverflow = (localVal & ((uint32_t)0x00001000)) >> 12; + *irqtxunderrun = (localVal & ((uint32_t)0x00000800)) >> 11; + *irqcca40sfall = (localVal & ((uint32_t)0x00000400)) >> 10; + *irqcca40srise = (localVal & ((uint32_t)0x00000200)) >> 9; + *irqtxend = (localVal & ((uint32_t)0x00000100)) >> 8; + *irqrxend = (localVal & ((uint32_t)0x00000080)) >> 7; + *irqcca20pfall = (localVal & ((uint32_t)0x00000040)) >> 6; + *irqcca20sfall = (localVal & ((uint32_t)0x00000020)) >> 5; + *irqcca20prise = (localVal & ((uint32_t)0x00000010)) >> 4; + *irqcca20srise = (localVal & ((uint32_t)0x00000008)) >> 3; + *irqphyerror = (localVal & ((uint32_t)0x00000004)) >> 2; + *irqradardet = (localVal & ((uint32_t)0x00000002)) >> 1; + *irqccatimeout = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +/** + * @brief Returns the current value of the IRQHTSIGVALID field in the IRQSTAT register. + * + * The IRQSTAT register will be read and the IRQHTSIGVALID field's value will be returned. + * + * @return The current value of the IRQHTSIGVALID field in the IRQSTAT register. + */ +__INLINE uint8_t mdm_irqhtsigvalid_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_IRQSTAT_ADDR); + return ((localVal & ((uint32_t)0x00004000)) >> 14); +} + +/** + * @brief Returns the current value of the IRQLSIGVALID field in the IRQSTAT register. + * + * The IRQSTAT register will be read and the IRQLSIGVALID field's value will be returned. + * + * @return The current value of the IRQLSIGVALID field in the IRQSTAT register. + */ +__INLINE uint8_t mdm_irqlsigvalid_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_IRQSTAT_ADDR); + return ((localVal & ((uint32_t)0x00002000)) >> 13); +} + +/** + * @brief Returns the current value of the IRQTXOVERFLOW field in the IRQSTAT register. + * + * The IRQSTAT register will be read and the IRQTXOVERFLOW field's value will be returned. + * + * @return The current value of the IRQTXOVERFLOW field in the IRQSTAT register. + */ +__INLINE uint8_t mdm_irqtxoverflow_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_IRQSTAT_ADDR); + return ((localVal & ((uint32_t)0x00001000)) >> 12); +} + +/** + * @brief Returns the current value of the IRQTXUNDERRUN field in the IRQSTAT register. + * + * The IRQSTAT register will be read and the IRQTXUNDERRUN field's value will be returned. + * + * @return The current value of the IRQTXUNDERRUN field in the IRQSTAT register. + */ +__INLINE uint8_t mdm_irqtxunderrun_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_IRQSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000800)) >> 11); +} + +/** + * @brief Returns the current value of the IRQCCA40SFALL field in the IRQSTAT register. + * + * The IRQSTAT register will be read and the IRQCCA40SFALL field's value will be returned. + * + * @return The current value of the IRQCCA40SFALL field in the IRQSTAT register. + */ +__INLINE uint8_t mdm_irqcca40sfall_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_IRQSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000400)) >> 10); +} + +/** + * @brief Returns the current value of the IRQCCA40SRISE field in the IRQSTAT register. + * + * The IRQSTAT register will be read and the IRQCCA40SRISE field's value will be returned. + * + * @return The current value of the IRQCCA40SRISE field in the IRQSTAT register. + */ +__INLINE uint8_t mdm_irqcca40srise_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_IRQSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000200)) >> 9); +} + +/** + * @brief Returns the current value of the IRQTXEND field in the IRQSTAT register. + * + * The IRQSTAT register will be read and the IRQTXEND field's value will be returned. + * + * @return The current value of the IRQTXEND field in the IRQSTAT register. + */ +__INLINE uint8_t mdm_irqtxend_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_IRQSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000100)) >> 8); +} + +/** + * @brief Returns the current value of the IRQRXEND field in the IRQSTAT register. + * + * The IRQSTAT register will be read and the IRQRXEND field's value will be returned. + * + * @return The current value of the IRQRXEND field in the IRQSTAT register. + */ +__INLINE uint8_t mdm_irqrxend_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_IRQSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000080)) >> 7); +} + +/** + * @brief Returns the current value of the IRQCCA20PFALL field in the IRQSTAT register. + * + * The IRQSTAT register will be read and the IRQCCA20PFALL field's value will be returned. + * + * @return The current value of the IRQCCA20PFALL field in the IRQSTAT register. + */ +__INLINE uint8_t mdm_irqcca20pfall_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_IRQSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000040)) >> 6); +} + +/** + * @brief Returns the current value of the IRQCCA20SFALL field in the IRQSTAT register. + * + * The IRQSTAT register will be read and the IRQCCA20SFALL field's value will be returned. + * + * @return The current value of the IRQCCA20SFALL field in the IRQSTAT register. + */ +__INLINE uint8_t mdm_irqcca20sfall_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_IRQSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +/** + * @brief Returns the current value of the IRQCCA20PRISE field in the IRQSTAT register. + * + * The IRQSTAT register will be read and the IRQCCA20PRISE field's value will be returned. + * + * @return The current value of the IRQCCA20PRISE field in the IRQSTAT register. + */ +__INLINE uint8_t mdm_irqcca20prise_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_IRQSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +/** + * @brief Returns the current value of the IRQCCA20SRISE field in the IRQSTAT register. + * + * The IRQSTAT register will be read and the IRQCCA20SRISE field's value will be returned. + * + * @return The current value of the IRQCCA20SRISE field in the IRQSTAT register. + */ +__INLINE uint8_t mdm_irqcca20srise_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_IRQSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +/** + * @brief Returns the current value of the IRQPHYERROR field in the IRQSTAT register. + * + * The IRQSTAT register will be read and the IRQPHYERROR field's value will be returned. + * + * @return The current value of the IRQPHYERROR field in the IRQSTAT register. + */ +__INLINE uint8_t mdm_irqphyerror_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_IRQSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +/** + * @brief Returns the current value of the IRQRADARDET field in the IRQSTAT register. + * + * The IRQSTAT register will be read and the IRQRADARDET field's value will be returned. + * + * @return The current value of the IRQRADARDET field in the IRQSTAT register. + */ +__INLINE uint8_t mdm_irqradardet_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_IRQSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +/** + * @brief Returns the current value of the IRQCCATIMEOUT field in the IRQSTAT register. + * + * The IRQSTAT register will be read and the IRQCCATIMEOUT field's value will be returned. + * + * @return The current value of the IRQCCATIMEOUT field in the IRQSTAT register. + */ +__INLINE uint8_t mdm_irqccatimeout_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_IRQSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/// @} + +/** + * @name RXVECTOR0 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  15:12            RXLEGRATE   0x0
+ *  11:00          RXLEGLENGTH   0x0
+ * 
+ * + * @{ + */ + +/// Address of the RXVECTOR0 register +#define MDM_RXVECTOR0_ADDR 0x01000028 +/// Offset of the RXVECTOR0 register from the base address +#define MDM_RXVECTOR0_OFFSET 0x00000028 +/// Index of the RXVECTOR0 register +#define MDM_RXVECTOR0_INDEX 0x0000000A +/// Reset value of the RXVECTOR0 register +#define MDM_RXVECTOR0_RESET 0x00000000 + +/** + * @brief Returns the current value of the RXVECTOR0 register. + * The RXVECTOR0 register will be read and its value returned. + * @return The current value of the RXVECTOR0 register. + */ +__INLINE uint32_t mdm_rxvector0_get(void) +{ + return REG_PL_RD(MDM_RXVECTOR0_ADDR); +} + +// field definitions +/// RXLEGRATE field mask +#define MDM_RXLEGRATE_MASK ((uint32_t)0x0000F000) +/// RXLEGRATE field LSB position +#define MDM_RXLEGRATE_LSB 12 +/// RXLEGRATE field width +#define MDM_RXLEGRATE_WIDTH ((uint32_t)0x00000004) +/// RXLEGLENGTH field mask +#define MDM_RXLEGLENGTH_MASK ((uint32_t)0x00000FFF) +/// RXLEGLENGTH field LSB position +#define MDM_RXLEGLENGTH_LSB 0 +/// RXLEGLENGTH field width +#define MDM_RXLEGLENGTH_WIDTH ((uint32_t)0x0000000C) + +/// RXLEGRATE field reset value +#define MDM_RXLEGRATE_RST 0x0 +/// RXLEGLENGTH field reset value +#define MDM_RXLEGLENGTH_RST 0x0 + +/** + * @brief Unpacks RXVECTOR0's fields from current value of the RXVECTOR0 register. + * + * Reads the RXVECTOR0 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] rxlegrate - Will be populated with the current value of this field from the register. + * @param[out] rxleglength - Will be populated with the current value of this field from the register. + */ +__INLINE void mdm_rxvector0_unpack(uint8_t *rxlegrate, uint16_t *rxleglength) +{ + uint32_t localVal = REG_PL_RD(MDM_RXVECTOR0_ADDR); + + *rxlegrate = (localVal & ((uint32_t)0x0000F000)) >> 12; + *rxleglength = (localVal & ((uint32_t)0x00000FFF)) >> 0; +} + +/** + * @brief Returns the current value of the RXLEGRATE field in the RXVECTOR0 register. + * + * The RXVECTOR0 register will be read and the RXLEGRATE field's value will be returned. + * + * @return The current value of the RXLEGRATE field in the RXVECTOR0 register. + */ +__INLINE uint8_t mdm_rxlegrate_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXVECTOR0_ADDR); + return ((localVal & ((uint32_t)0x0000F000)) >> 12); +} + +/** + * @brief Returns the current value of the RXLEGLENGTH field in the RXVECTOR0 register. + * + * The RXVECTOR0 register will be read and the RXLEGLENGTH field's value will be returned. + * + * @return The current value of the RXLEGLENGTH field in the RXVECTOR0 register. + */ +__INLINE uint16_t mdm_rxleglength_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXVECTOR0_ADDR); + return ((localVal & ((uint32_t)0x00000FFF)) >> 0); +} + +/// @} + +/** + * @name RXVECTOR1 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31            RXPRETYPE   0
+ *  30:24                RXMCS   0x0
+ *     23          RXSMOOTHING   0
+ *  22:21               RXSTBC   0x0
+ *     20            RXSHORTGI   0
+ *  19:00           RXHTLENGTH   0x0
+ * 
+ * + * @{ + */ + +/// Address of the RXVECTOR1 register +#define MDM_RXVECTOR1_ADDR 0x0100002C +/// Offset of the RXVECTOR1 register from the base address +#define MDM_RXVECTOR1_OFFSET 0x0000002C +/// Index of the RXVECTOR1 register +#define MDM_RXVECTOR1_INDEX 0x0000000B +/// Reset value of the RXVECTOR1 register +#define MDM_RXVECTOR1_RESET 0x00000000 + +/** + * @brief Returns the current value of the RXVECTOR1 register. + * The RXVECTOR1 register will be read and its value returned. + * @return The current value of the RXVECTOR1 register. + */ +__INLINE uint32_t mdm_rxvector1_get(void) +{ + return REG_PL_RD(MDM_RXVECTOR1_ADDR); +} + +// field definitions +/// RXPRETYPE field bit +#define MDM_RXPRETYPE_BIT ((uint32_t)0x80000000) +/// RXPRETYPE field position +#define MDM_RXPRETYPE_POS 31 +/// RXMCS field mask +#define MDM_RXMCS_MASK ((uint32_t)0x7F000000) +/// RXMCS field LSB position +#define MDM_RXMCS_LSB 24 +/// RXMCS field width +#define MDM_RXMCS_WIDTH ((uint32_t)0x00000007) +/// RXSMOOTHING field bit +#define MDM_RXSMOOTHING_BIT ((uint32_t)0x00800000) +/// RXSMOOTHING field position +#define MDM_RXSMOOTHING_POS 23 +/// RXSTBC field mask +#define MDM_RXSTBC_MASK ((uint32_t)0x00600000) +/// RXSTBC field LSB position +#define MDM_RXSTBC_LSB 21 +/// RXSTBC field width +#define MDM_RXSTBC_WIDTH ((uint32_t)0x00000002) +/// RXSHORTGI field bit +#define MDM_RXSHORTGI_BIT ((uint32_t)0x00100000) +/// RXSHORTGI field position +#define MDM_RXSHORTGI_POS 20 +/// RXHTLENGTH field mask +#define MDM_RXHTLENGTH_MASK ((uint32_t)0x000FFFFF) +/// RXHTLENGTH field LSB position +#define MDM_RXHTLENGTH_LSB 0 +/// RXHTLENGTH field width +#define MDM_RXHTLENGTH_WIDTH ((uint32_t)0x00000014) + +/// RXPRETYPE field reset value +#define MDM_RXPRETYPE_RST 0x0 +/// RXMCS field reset value +#define MDM_RXMCS_RST 0x0 +/// RXSMOOTHING field reset value +#define MDM_RXSMOOTHING_RST 0x0 +/// RXSTBC field reset value +#define MDM_RXSTBC_RST 0x0 +/// RXSHORTGI field reset value +#define MDM_RXSHORTGI_RST 0x0 +/// RXHTLENGTH field reset value +#define MDM_RXHTLENGTH_RST 0x0 + +/** + * @brief Unpacks RXVECTOR1's fields from current value of the RXVECTOR1 register. + * + * Reads the RXVECTOR1 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] rxpretype - Will be populated with the current value of this field from the register. + * @param[out] rxmcs - Will be populated with the current value of this field from the register. + * @param[out] rxsmoothing - Will be populated with the current value of this field from the register. + * @param[out] rxstbc - Will be populated with the current value of this field from the register. + * @param[out] rxshortgi - Will be populated with the current value of this field from the register. + * @param[out] rxhtlength - Will be populated with the current value of this field from the register. + */ +__INLINE void mdm_rxvector1_unpack(uint8_t *rxpretype, uint8_t *rxmcs, uint8_t *rxsmoothing, uint8_t *rxstbc, uint8_t *rxshortgi, uint32_t *rxhtlength) +{ + uint32_t localVal = REG_PL_RD(MDM_RXVECTOR1_ADDR); + + *rxpretype = (localVal & ((uint32_t)0x80000000)) >> 31; + *rxmcs = (localVal & ((uint32_t)0x7F000000)) >> 24; + *rxsmoothing = (localVal & ((uint32_t)0x00800000)) >> 23; + *rxstbc = (localVal & ((uint32_t)0x00600000)) >> 21; + *rxshortgi = (localVal & ((uint32_t)0x00100000)) >> 20; + *rxhtlength = (localVal & ((uint32_t)0x000FFFFF)) >> 0; +} + +/** + * @brief Returns the current value of the RXPRETYPE field in the RXVECTOR1 register. + * + * The RXVECTOR1 register will be read and the RXPRETYPE field's value will be returned. + * + * @return The current value of the RXPRETYPE field in the RXVECTOR1 register. + */ +__INLINE uint8_t mdm_rxpretype_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXVECTOR1_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +/** + * @brief Returns the current value of the RXMCS field in the RXVECTOR1 register. + * + * The RXVECTOR1 register will be read and the RXMCS field's value will be returned. + * + * @return The current value of the RXMCS field in the RXVECTOR1 register. + */ +__INLINE uint8_t mdm_rxmcs_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXVECTOR1_ADDR); + return ((localVal & ((uint32_t)0x7F000000)) >> 24); +} + +/** + * @brief Returns the current value of the RXSMOOTHING field in the RXVECTOR1 register. + * + * The RXVECTOR1 register will be read and the RXSMOOTHING field's value will be returned. + * + * @return The current value of the RXSMOOTHING field in the RXVECTOR1 register. + */ +__INLINE uint8_t mdm_rxsmoothing_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXVECTOR1_ADDR); + return ((localVal & ((uint32_t)0x00800000)) >> 23); +} + +/** + * @brief Returns the current value of the RXSTBC field in the RXVECTOR1 register. + * + * The RXVECTOR1 register will be read and the RXSTBC field's value will be returned. + * + * @return The current value of the RXSTBC field in the RXVECTOR1 register. + */ +__INLINE uint8_t mdm_rxstbc_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXVECTOR1_ADDR); + return ((localVal & ((uint32_t)0x00600000)) >> 21); +} + +/** + * @brief Returns the current value of the RXSHORTGI field in the RXVECTOR1 register. + * + * The RXVECTOR1 register will be read and the RXSHORTGI field's value will be returned. + * + * @return The current value of the RXSHORTGI field in the RXVECTOR1 register. + */ +__INLINE uint8_t mdm_rxshortgi_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXVECTOR1_ADDR); + return ((localVal & ((uint32_t)0x00100000)) >> 20); +} + +/** + * @brief Returns the current value of the RXHTLENGTH field in the RXVECTOR1 register. + * + * The RXVECTOR1 register will be read and the RXHTLENGTH field's value will be returned. + * + * @return The current value of the RXHTLENGTH field in the RXVECTOR1 register. + */ +__INLINE uint32_t mdm_rxhtlength_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXVECTOR1_ADDR); + return ((localVal & ((uint32_t)0x000FFFFF)) >> 0); +} + +/// @} + +/** + * @name RXVECTOR2 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:24         RXANTENNASET   0x0
+ *     23     RXDOZENOTALLOWED   0
+ *     22              RXDYNBW   0
+ *     21          RXFECCODING   0
+ *     20             RXAGGREG   0
+ *  17:16           RXNUMEXTSS   0x0
+ *     12           RXSOUNDING   0
+ *  10:08             RXNUMSTS   0x0
+ *  05:04               RXCHBW   0x0
+ *  02:00             RXFORMAT   0x0
+ * 
+ * + * @{ + */ + +/// Address of the RXVECTOR2 register +#define MDM_RXVECTOR2_ADDR 0x01000030 +/// Offset of the RXVECTOR2 register from the base address +#define MDM_RXVECTOR2_OFFSET 0x00000030 +/// Index of the RXVECTOR2 register +#define MDM_RXVECTOR2_INDEX 0x0000000C +/// Reset value of the RXVECTOR2 register +#define MDM_RXVECTOR2_RESET 0x00000000 + +/** + * @brief Returns the current value of the RXVECTOR2 register. + * The RXVECTOR2 register will be read and its value returned. + * @return The current value of the RXVECTOR2 register. + */ +__INLINE uint32_t mdm_rxvector2_get(void) +{ + return REG_PL_RD(MDM_RXVECTOR2_ADDR); +} + +// field definitions +/// RXANTENNASET field mask +#define MDM_RXANTENNASET_MASK ((uint32_t)0xFF000000) +/// RXANTENNASET field LSB position +#define MDM_RXANTENNASET_LSB 24 +/// RXANTENNASET field width +#define MDM_RXANTENNASET_WIDTH ((uint32_t)0x00000008) +/// RXDOZENOTALLOWED field bit +#define MDM_RXDOZENOTALLOWED_BIT ((uint32_t)0x00800000) +/// RXDOZENOTALLOWED field position +#define MDM_RXDOZENOTALLOWED_POS 23 +/// RXDYNBW field bit +#define MDM_RXDYNBW_BIT ((uint32_t)0x00400000) +/// RXDYNBW field position +#define MDM_RXDYNBW_POS 22 +/// RXFECCODING field bit +#define MDM_RXFECCODING_BIT ((uint32_t)0x00200000) +/// RXFECCODING field position +#define MDM_RXFECCODING_POS 21 +/// RXAGGREG field bit +#define MDM_RXAGGREG_BIT ((uint32_t)0x00100000) +/// RXAGGREG field position +#define MDM_RXAGGREG_POS 20 +/// RXNUMEXTSS field mask +#define MDM_RXNUMEXTSS_MASK ((uint32_t)0x00030000) +/// RXNUMEXTSS field LSB position +#define MDM_RXNUMEXTSS_LSB 16 +/// RXNUMEXTSS field width +#define MDM_RXNUMEXTSS_WIDTH ((uint32_t)0x00000002) +/// RXSOUNDING field bit +#define MDM_RXSOUNDING_BIT ((uint32_t)0x00001000) +/// RXSOUNDING field position +#define MDM_RXSOUNDING_POS 12 +/// RXNUMSTS field mask +#define MDM_RXNUMSTS_MASK ((uint32_t)0x00000700) +/// RXNUMSTS field LSB position +#define MDM_RXNUMSTS_LSB 8 +/// RXNUMSTS field width +#define MDM_RXNUMSTS_WIDTH ((uint32_t)0x00000003) +/// RXCHBW field mask +#define MDM_RXCHBW_MASK ((uint32_t)0x00000030) +/// RXCHBW field LSB position +#define MDM_RXCHBW_LSB 4 +/// RXCHBW field width +#define MDM_RXCHBW_WIDTH ((uint32_t)0x00000002) +/// RXFORMAT field mask +#define MDM_RXFORMAT_MASK ((uint32_t)0x00000007) +/// RXFORMAT field LSB position +#define MDM_RXFORMAT_LSB 0 +/// RXFORMAT field width +#define MDM_RXFORMAT_WIDTH ((uint32_t)0x00000003) + +/// RXANTENNASET field reset value +#define MDM_RXANTENNASET_RST 0x0 +/// RXDOZENOTALLOWED field reset value +#define MDM_RXDOZENOTALLOWED_RST 0x0 +/// RXDYNBW field reset value +#define MDM_RXDYNBW_RST 0x0 +/// RXFECCODING field reset value +#define MDM_RXFECCODING_RST 0x0 +/// RXAGGREG field reset value +#define MDM_RXAGGREG_RST 0x0 +/// RXNUMEXTSS field reset value +#define MDM_RXNUMEXTSS_RST 0x0 +/// RXSOUNDING field reset value +#define MDM_RXSOUNDING_RST 0x0 +/// RXNUMSTS field reset value +#define MDM_RXNUMSTS_RST 0x0 +/// RXCHBW field reset value +#define MDM_RXCHBW_RST 0x0 +/// RXFORMAT field reset value +#define MDM_RXFORMAT_RST 0x0 + +/** + * @brief Unpacks RXVECTOR2's fields from current value of the RXVECTOR2 register. + * + * Reads the RXVECTOR2 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] rxantennaset - Will be populated with the current value of this field from the register. + * @param[out] rxdozenotallowed - Will be populated with the current value of this field from the register. + * @param[out] rxdynbw - Will be populated with the current value of this field from the register. + * @param[out] rxfeccoding - Will be populated with the current value of this field from the register. + * @param[out] rxaggreg - Will be populated with the current value of this field from the register. + * @param[out] rxnumextss - Will be populated with the current value of this field from the register. + * @param[out] rxsounding - Will be populated with the current value of this field from the register. + * @param[out] rxnumsts - Will be populated with the current value of this field from the register. + * @param[out] rxchbw - Will be populated with the current value of this field from the register. + * @param[out] rxformat - Will be populated with the current value of this field from the register. + */ +__INLINE void mdm_rxvector2_unpack(uint8_t *rxantennaset, uint8_t *rxdozenotallowed, uint8_t *rxdynbw, uint8_t *rxfeccoding, uint8_t *rxaggreg, uint8_t *rxnumextss, uint8_t *rxsounding, uint8_t *rxnumsts, uint8_t *rxchbw, uint8_t *rxformat) +{ + uint32_t localVal = REG_PL_RD(MDM_RXVECTOR2_ADDR); + + *rxantennaset = (localVal & ((uint32_t)0xFF000000)) >> 24; + *rxdozenotallowed = (localVal & ((uint32_t)0x00800000)) >> 23; + *rxdynbw = (localVal & ((uint32_t)0x00400000)) >> 22; + *rxfeccoding = (localVal & ((uint32_t)0x00200000)) >> 21; + *rxaggreg = (localVal & ((uint32_t)0x00100000)) >> 20; + *rxnumextss = (localVal & ((uint32_t)0x00030000)) >> 16; + *rxsounding = (localVal & ((uint32_t)0x00001000)) >> 12; + *rxnumsts = (localVal & ((uint32_t)0x00000700)) >> 8; + *rxchbw = (localVal & ((uint32_t)0x00000030)) >> 4; + *rxformat = (localVal & ((uint32_t)0x00000007)) >> 0; +} + +/** + * @brief Returns the current value of the RXANTENNASET field in the RXVECTOR2 register. + * + * The RXVECTOR2 register will be read and the RXANTENNASET field's value will be returned. + * + * @return The current value of the RXANTENNASET field in the RXVECTOR2 register. + */ +__INLINE uint8_t mdm_rxantennaset_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXVECTOR2_ADDR); + return ((localVal & ((uint32_t)0xFF000000)) >> 24); +} + +/** + * @brief Returns the current value of the RXDOZENOTALLOWED field in the RXVECTOR2 register. + * + * The RXVECTOR2 register will be read and the RXDOZENOTALLOWED field's value will be returned. + * + * @return The current value of the RXDOZENOTALLOWED field in the RXVECTOR2 register. + */ +__INLINE uint8_t mdm_rxdozenotallowed_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXVECTOR2_ADDR); + return ((localVal & ((uint32_t)0x00800000)) >> 23); +} + +/** + * @brief Returns the current value of the RXDYNBW field in the RXVECTOR2 register. + * + * The RXVECTOR2 register will be read and the RXDYNBW field's value will be returned. + * + * @return The current value of the RXDYNBW field in the RXVECTOR2 register. + */ +__INLINE uint8_t mdm_rxdynbw_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXVECTOR2_ADDR); + return ((localVal & ((uint32_t)0x00400000)) >> 22); +} + +/** + * @brief Returns the current value of the RXFECCODING field in the RXVECTOR2 register. + * + * The RXVECTOR2 register will be read and the RXFECCODING field's value will be returned. + * + * @return The current value of the RXFECCODING field in the RXVECTOR2 register. + */ +__INLINE uint8_t mdm_rxfeccoding_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXVECTOR2_ADDR); + return ((localVal & ((uint32_t)0x00200000)) >> 21); +} + +/** + * @brief Returns the current value of the RXAGGREG field in the RXVECTOR2 register. + * + * The RXVECTOR2 register will be read and the RXAGGREG field's value will be returned. + * + * @return The current value of the RXAGGREG field in the RXVECTOR2 register. + */ +__INLINE uint8_t mdm_rxaggreg_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXVECTOR2_ADDR); + return ((localVal & ((uint32_t)0x00100000)) >> 20); +} + +/** + * @brief Returns the current value of the RXNUMEXTSS field in the RXVECTOR2 register. + * + * The RXVECTOR2 register will be read and the RXNUMEXTSS field's value will be returned. + * + * @return The current value of the RXNUMEXTSS field in the RXVECTOR2 register. + */ +__INLINE uint8_t mdm_rxnumextss_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXVECTOR2_ADDR); + return ((localVal & ((uint32_t)0x00030000)) >> 16); +} + +/** + * @brief Returns the current value of the RXSOUNDING field in the RXVECTOR2 register. + * + * The RXVECTOR2 register will be read and the RXSOUNDING field's value will be returned. + * + * @return The current value of the RXSOUNDING field in the RXVECTOR2 register. + */ +__INLINE uint8_t mdm_rxsounding_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXVECTOR2_ADDR); + return ((localVal & ((uint32_t)0x00001000)) >> 12); +} + +/** + * @brief Returns the current value of the RXNUMSTS field in the RXVECTOR2 register. + * + * The RXVECTOR2 register will be read and the RXNUMSTS field's value will be returned. + * + * @return The current value of the RXNUMSTS field in the RXVECTOR2 register. + */ +__INLINE uint8_t mdm_rxnumsts_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXVECTOR2_ADDR); + return ((localVal & ((uint32_t)0x00000700)) >> 8); +} + +/** + * @brief Returns the current value of the RXCHBW field in the RXVECTOR2 register. + * + * The RXVECTOR2 register will be read and the RXCHBW field's value will be returned. + * + * @return The current value of the RXCHBW field in the RXVECTOR2 register. + */ +__INLINE uint8_t mdm_rxchbw_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXVECTOR2_ADDR); + return ((localVal & ((uint32_t)0x00000030)) >> 4); +} + +/** + * @brief Returns the current value of the RXFORMAT field in the RXVECTOR2 register. + * + * The RXVECTOR2 register will be read and the RXFORMAT field's value will be returned. + * + * @return The current value of the RXFORMAT field in the RXVECTOR2 register. + */ +__INLINE uint8_t mdm_rxformat_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXVECTOR2_ADDR); + return ((localVal & ((uint32_t)0x00000007)) >> 0); +} + +/// @} + +/** + * @name RXVECTOR3 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:24                RSSI4   0x0
+ *  23:16                RSSI3   0x0
+ *  15:08                RSSI2   0x0
+ *  07:00                RSSI1   0x0
+ * 
+ * + * @{ + */ + +/// Address of the RXVECTOR3 register +#define MDM_RXVECTOR3_ADDR 0x01000034 +/// Offset of the RXVECTOR3 register from the base address +#define MDM_RXVECTOR3_OFFSET 0x00000034 +/// Index of the RXVECTOR3 register +#define MDM_RXVECTOR3_INDEX 0x0000000D +/// Reset value of the RXVECTOR3 register +#define MDM_RXVECTOR3_RESET 0x00000000 + +/** + * @brief Returns the current value of the RXVECTOR3 register. + * The RXVECTOR3 register will be read and its value returned. + * @return The current value of the RXVECTOR3 register. + */ +__INLINE uint32_t mdm_rxvector3_get(void) +{ + return REG_PL_RD(MDM_RXVECTOR3_ADDR); +} + +// field definitions +/// RSSI4 field mask +#define MDM_RSSI4_MASK ((uint32_t)0xFF000000) +/// RSSI4 field LSB position +#define MDM_RSSI4_LSB 24 +/// RSSI4 field width +#define MDM_RSSI4_WIDTH ((uint32_t)0x00000008) +/// RSSI3 field mask +#define MDM_RSSI3_MASK ((uint32_t)0x00FF0000) +/// RSSI3 field LSB position +#define MDM_RSSI3_LSB 16 +/// RSSI3 field width +#define MDM_RSSI3_WIDTH ((uint32_t)0x00000008) +/// RSSI2 field mask +#define MDM_RSSI2_MASK ((uint32_t)0x0000FF00) +/// RSSI2 field LSB position +#define MDM_RSSI2_LSB 8 +/// RSSI2 field width +#define MDM_RSSI2_WIDTH ((uint32_t)0x00000008) +/// RSSI1 field mask +#define MDM_RSSI1_MASK ((uint32_t)0x000000FF) +/// RSSI1 field LSB position +#define MDM_RSSI1_LSB 0 +/// RSSI1 field width +#define MDM_RSSI1_WIDTH ((uint32_t)0x00000008) + +/// RSSI4 field reset value +#define MDM_RSSI4_RST 0x0 +/// RSSI3 field reset value +#define MDM_RSSI3_RST 0x0 +/// RSSI2 field reset value +#define MDM_RSSI2_RST 0x0 +/// RSSI1 field reset value +#define MDM_RSSI1_RST 0x0 + +/** + * @brief Unpacks RXVECTOR3's fields from current value of the RXVECTOR3 register. + * + * Reads the RXVECTOR3 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] rssi4 - Will be populated with the current value of this field from the register. + * @param[out] rssi3 - Will be populated with the current value of this field from the register. + * @param[out] rssi2 - Will be populated with the current value of this field from the register. + * @param[out] rssi1 - Will be populated with the current value of this field from the register. + */ +__INLINE void mdm_rxvector3_unpack(uint8_t *rssi4, uint8_t *rssi3, uint8_t *rssi2, uint8_t *rssi1) +{ + uint32_t localVal = REG_PL_RD(MDM_RXVECTOR3_ADDR); + + *rssi4 = (localVal & ((uint32_t)0xFF000000)) >> 24; + *rssi3 = (localVal & ((uint32_t)0x00FF0000)) >> 16; + *rssi2 = (localVal & ((uint32_t)0x0000FF00)) >> 8; + *rssi1 = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +/** + * @brief Returns the current value of the RSSI4 field in the RXVECTOR3 register. + * + * The RXVECTOR3 register will be read and the RSSI4 field's value will be returned. + * + * @return The current value of the RSSI4 field in the RXVECTOR3 register. + */ +__INLINE uint8_t mdm_rssi4_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXVECTOR3_ADDR); + return ((localVal & ((uint32_t)0xFF000000)) >> 24); +} + +/** + * @brief Returns the current value of the RSSI3 field in the RXVECTOR3 register. + * + * The RXVECTOR3 register will be read and the RSSI3 field's value will be returned. + * + * @return The current value of the RSSI3 field in the RXVECTOR3 register. + */ +__INLINE uint8_t mdm_rssi3_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXVECTOR3_ADDR); + return ((localVal & ((uint32_t)0x00FF0000)) >> 16); +} + +/** + * @brief Returns the current value of the RSSI2 field in the RXVECTOR3 register. + * + * The RXVECTOR3 register will be read and the RSSI2 field's value will be returned. + * + * @return The current value of the RSSI2 field in the RXVECTOR3 register. + */ +__INLINE uint8_t mdm_rssi2_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXVECTOR3_ADDR); + return ((localVal & ((uint32_t)0x0000FF00)) >> 8); +} + +/** + * @brief Returns the current value of the RSSI1 field in the RXVECTOR3 register. + * + * The RXVECTOR3 register will be read and the RSSI1 field's value will be returned. + * + * @return The current value of the RSSI1 field in the RXVECTOR3 register. + */ +__INLINE uint8_t mdm_rssi1_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXVECTOR3_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +/// @} + +/** + * @name RXVECTOR4 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  29:24            RXGROUPID   0x0
+ *  20:12         RXPARTIALAID   0x0
+ *  07:00                 RCPI   0x0
+ * 
+ * + * @{ + */ + +/// Address of the RXVECTOR4 register +#define MDM_RXVECTOR4_ADDR 0x01000038 +/// Offset of the RXVECTOR4 register from the base address +#define MDM_RXVECTOR4_OFFSET 0x00000038 +/// Index of the RXVECTOR4 register +#define MDM_RXVECTOR4_INDEX 0x0000000E +/// Reset value of the RXVECTOR4 register +#define MDM_RXVECTOR4_RESET 0x00000000 + +/** + * @brief Returns the current value of the RXVECTOR4 register. + * The RXVECTOR4 register will be read and its value returned. + * @return The current value of the RXVECTOR4 register. + */ +__INLINE uint32_t mdm_rxvector4_get(void) +{ + return REG_PL_RD(MDM_RXVECTOR4_ADDR); +} + +// field definitions +/// RXGROUPID field mask +#define MDM_RXGROUPID_MASK ((uint32_t)0x3F000000) +/// RXGROUPID field LSB position +#define MDM_RXGROUPID_LSB 24 +/// RXGROUPID field width +#define MDM_RXGROUPID_WIDTH ((uint32_t)0x00000006) +/// RXPARTIALAID field mask +#define MDM_RXPARTIALAID_MASK ((uint32_t)0x001FF000) +/// RXPARTIALAID field LSB position +#define MDM_RXPARTIALAID_LSB 12 +/// RXPARTIALAID field width +#define MDM_RXPARTIALAID_WIDTH ((uint32_t)0x00000009) +/// RCPI field mask +#define MDM_RCPI_MASK ((uint32_t)0x000000FF) +/// RCPI field LSB position +#define MDM_RCPI_LSB 0 +/// RCPI field width +#define MDM_RCPI_WIDTH ((uint32_t)0x00000008) + +/// RXGROUPID field reset value +#define MDM_RXGROUPID_RST 0x0 +/// RXPARTIALAID field reset value +#define MDM_RXPARTIALAID_RST 0x0 +/// RCPI field reset value +#define MDM_RCPI_RST 0x0 + +/** + * @brief Unpacks RXVECTOR4's fields from current value of the RXVECTOR4 register. + * + * Reads the RXVECTOR4 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] rxgroupid - Will be populated with the current value of this field from the register. + * @param[out] rxpartialaid - Will be populated with the current value of this field from the register. + * @param[out] rcpi - Will be populated with the current value of this field from the register. + */ +__INLINE void mdm_rxvector4_unpack(uint8_t *rxgroupid, uint16_t *rxpartialaid, uint8_t *rcpi) +{ + uint32_t localVal = REG_PL_RD(MDM_RXVECTOR4_ADDR); + + *rxgroupid = (localVal & ((uint32_t)0x3F000000)) >> 24; + *rxpartialaid = (localVal & ((uint32_t)0x001FF000)) >> 12; + *rcpi = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +/** + * @brief Returns the current value of the RXGROUPID field in the RXVECTOR4 register. + * + * The RXVECTOR4 register will be read and the RXGROUPID field's value will be returned. + * + * @return The current value of the RXGROUPID field in the RXVECTOR4 register. + */ +__INLINE uint8_t mdm_rxgroupid_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXVECTOR4_ADDR); + return ((localVal & ((uint32_t)0x3F000000)) >> 24); +} + +/** + * @brief Returns the current value of the RXPARTIALAID field in the RXVECTOR4 register. + * + * The RXVECTOR4 register will be read and the RXPARTIALAID field's value will be returned. + * + * @return The current value of the RXPARTIALAID field in the RXVECTOR4 register. + */ +__INLINE uint16_t mdm_rxpartialaid_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXVECTOR4_ADDR); + return ((localVal & ((uint32_t)0x001FF000)) >> 12); +} + +/** + * @brief Returns the current value of the RCPI field in the RXVECTOR4 register. + * + * The RXVECTOR4 register will be read and the RCPI field's value will be returned. + * + * @return The current value of the RCPI field in the RXVECTOR4 register. + */ +__INLINE uint8_t mdm_rcpi_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXVECTOR4_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +/// @} + +/** + * @name RXVECTOR5 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:24                 EVM4   0x0
+ *  23:16                 EVM3   0x0
+ *  15:08                 EVM2   0x0
+ *  07:00                 EVM1   0x0
+ * 
+ * + * @{ + */ + +/// Address of the RXVECTOR5 register +#define MDM_RXVECTOR5_ADDR 0x0100003C +/// Offset of the RXVECTOR5 register from the base address +#define MDM_RXVECTOR5_OFFSET 0x0000003C +/// Index of the RXVECTOR5 register +#define MDM_RXVECTOR5_INDEX 0x0000000F +/// Reset value of the RXVECTOR5 register +#define MDM_RXVECTOR5_RESET 0x00000000 + +/** + * @brief Returns the current value of the RXVECTOR5 register. + * The RXVECTOR5 register will be read and its value returned. + * @return The current value of the RXVECTOR5 register. + */ +__INLINE uint32_t mdm_rxvector5_get(void) +{ + return REG_PL_RD(MDM_RXVECTOR5_ADDR); +} + +// field definitions +/// EVM4 field mask +#define MDM_EVM4_MASK ((uint32_t)0xFF000000) +/// EVM4 field LSB position +#define MDM_EVM4_LSB 24 +/// EVM4 field width +#define MDM_EVM4_WIDTH ((uint32_t)0x00000008) +/// EVM3 field mask +#define MDM_EVM3_MASK ((uint32_t)0x00FF0000) +/// EVM3 field LSB position +#define MDM_EVM3_LSB 16 +/// EVM3 field width +#define MDM_EVM3_WIDTH ((uint32_t)0x00000008) +/// EVM2 field mask +#define MDM_EVM2_MASK ((uint32_t)0x0000FF00) +/// EVM2 field LSB position +#define MDM_EVM2_LSB 8 +/// EVM2 field width +#define MDM_EVM2_WIDTH ((uint32_t)0x00000008) +/// EVM1 field mask +#define MDM_EVM1_MASK ((uint32_t)0x000000FF) +/// EVM1 field LSB position +#define MDM_EVM1_LSB 0 +/// EVM1 field width +#define MDM_EVM1_WIDTH ((uint32_t)0x00000008) + +/// EVM4 field reset value +#define MDM_EVM4_RST 0x0 +/// EVM3 field reset value +#define MDM_EVM3_RST 0x0 +/// EVM2 field reset value +#define MDM_EVM2_RST 0x0 +/// EVM1 field reset value +#define MDM_EVM1_RST 0x0 + +/** + * @brief Unpacks RXVECTOR5's fields from current value of the RXVECTOR5 register. + * + * Reads the RXVECTOR5 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] evm4 - Will be populated with the current value of this field from the register. + * @param[out] evm3 - Will be populated with the current value of this field from the register. + * @param[out] evm2 - Will be populated with the current value of this field from the register. + * @param[out] evm1 - Will be populated with the current value of this field from the register. + */ +__INLINE void mdm_rxvector5_unpack(uint8_t *evm4, uint8_t *evm3, uint8_t *evm2, uint8_t *evm1) +{ + uint32_t localVal = REG_PL_RD(MDM_RXVECTOR5_ADDR); + + *evm4 = (localVal & ((uint32_t)0xFF000000)) >> 24; + *evm3 = (localVal & ((uint32_t)0x00FF0000)) >> 16; + *evm2 = (localVal & ((uint32_t)0x0000FF00)) >> 8; + *evm1 = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +/** + * @brief Returns the current value of the EVM4 field in the RXVECTOR5 register. + * + * The RXVECTOR5 register will be read and the EVM4 field's value will be returned. + * + * @return The current value of the EVM4 field in the RXVECTOR5 register. + */ +__INLINE uint8_t mdm_evm4_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXVECTOR5_ADDR); + return ((localVal & ((uint32_t)0xFF000000)) >> 24); +} + +/** + * @brief Returns the current value of the EVM3 field in the RXVECTOR5 register. + * + * The RXVECTOR5 register will be read and the EVM3 field's value will be returned. + * + * @return The current value of the EVM3 field in the RXVECTOR5 register. + */ +__INLINE uint8_t mdm_evm3_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXVECTOR5_ADDR); + return ((localVal & ((uint32_t)0x00FF0000)) >> 16); +} + +/** + * @brief Returns the current value of the EVM2 field in the RXVECTOR5 register. + * + * The RXVECTOR5 register will be read and the EVM2 field's value will be returned. + * + * @return The current value of the EVM2 field in the RXVECTOR5 register. + */ +__INLINE uint8_t mdm_evm2_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXVECTOR5_ADDR); + return ((localVal & ((uint32_t)0x0000FF00)) >> 8); +} + +/** + * @brief Returns the current value of the EVM1 field in the RXVECTOR5 register. + * + * The RXVECTOR5 register will be read and the EVM1 field's value will be returned. + * + * @return The current value of the EVM1 field in the RXVECTOR5 register. + */ +__INLINE uint8_t mdm_evm1_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RXVECTOR5_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +/// @} + +/** + * @name TXVECTOR0 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:24             SMMINDEX   0x0
+ *  23:16         TXANTENNASET   0x0
+ *  13:12               TXCHBW   0x0
+ *     11          TXSMOOTHING   0
+ *     10              TXDYNBW   0
+ *     09          TXFECCODING   0
+ *     08           TXSOUNDING   0
+ *  07:00            TXPWLEVEL   0x0
+ * 
+ * + * @{ + */ + +/// Address of the TXVECTOR0 register +#define MDM_TXVECTOR0_ADDR 0x01000040 +/// Offset of the TXVECTOR0 register from the base address +#define MDM_TXVECTOR0_OFFSET 0x00000040 +/// Index of the TXVECTOR0 register +#define MDM_TXVECTOR0_INDEX 0x00000010 +/// Reset value of the TXVECTOR0 register +#define MDM_TXVECTOR0_RESET 0x00000000 + +/** + * @brief Returns the current value of the TXVECTOR0 register. + * The TXVECTOR0 register will be read and its value returned. + * @return The current value of the TXVECTOR0 register. + */ +__INLINE uint32_t mdm_txvector0_get(void) +{ + return REG_PL_RD(MDM_TXVECTOR0_ADDR); +} + +// field definitions +/// SMMINDEX field mask +#define MDM_SMMINDEX_MASK ((uint32_t)0xFF000000) +/// SMMINDEX field LSB position +#define MDM_SMMINDEX_LSB 24 +/// SMMINDEX field width +#define MDM_SMMINDEX_WIDTH ((uint32_t)0x00000008) +/// TXANTENNASET field mask +#define MDM_TXANTENNASET_MASK ((uint32_t)0x00FF0000) +/// TXANTENNASET field LSB position +#define MDM_TXANTENNASET_LSB 16 +/// TXANTENNASET field width +#define MDM_TXANTENNASET_WIDTH ((uint32_t)0x00000008) +/// TXCHBW field mask +#define MDM_TXCHBW_MASK ((uint32_t)0x00003000) +/// TXCHBW field LSB position +#define MDM_TXCHBW_LSB 12 +/// TXCHBW field width +#define MDM_TXCHBW_WIDTH ((uint32_t)0x00000002) +/// TXSMOOTHING field bit +#define MDM_TXSMOOTHING_BIT ((uint32_t)0x00000800) +/// TXSMOOTHING field position +#define MDM_TXSMOOTHING_POS 11 +/// TXDYNBW field bit +#define MDM_TXDYNBW_BIT ((uint32_t)0x00000400) +/// TXDYNBW field position +#define MDM_TXDYNBW_POS 10 +/// TXFECCODING field bit +#define MDM_TXFECCODING_BIT ((uint32_t)0x00000200) +/// TXFECCODING field position +#define MDM_TXFECCODING_POS 9 +/// TXSOUNDING field bit +#define MDM_TXSOUNDING_BIT ((uint32_t)0x00000100) +/// TXSOUNDING field position +#define MDM_TXSOUNDING_POS 8 +/// TXPWLEVEL field mask +#define MDM_TXPWLEVEL_MASK ((uint32_t)0x000000FF) +/// TXPWLEVEL field LSB position +#define MDM_TXPWLEVEL_LSB 0 +/// TXPWLEVEL field width +#define MDM_TXPWLEVEL_WIDTH ((uint32_t)0x00000008) + +/// SMMINDEX field reset value +#define MDM_SMMINDEX_RST 0x0 +/// TXANTENNASET field reset value +#define MDM_TXANTENNASET_RST 0x0 +/// TXCHBW field reset value +#define MDM_TXCHBW_RST 0x0 +/// TXSMOOTHING field reset value +#define MDM_TXSMOOTHING_RST 0x0 +/// TXDYNBW field reset value +#define MDM_TXDYNBW_RST 0x0 +/// TXFECCODING field reset value +#define MDM_TXFECCODING_RST 0x0 +/// TXSOUNDING field reset value +#define MDM_TXSOUNDING_RST 0x0 +/// TXPWLEVEL field reset value +#define MDM_TXPWLEVEL_RST 0x0 + +/** + * @brief Unpacks TXVECTOR0's fields from current value of the TXVECTOR0 register. + * + * Reads the TXVECTOR0 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] smmindex - Will be populated with the current value of this field from the register. + * @param[out] txantennaset - Will be populated with the current value of this field from the register. + * @param[out] txchbw - Will be populated with the current value of this field from the register. + * @param[out] txsmoothing - Will be populated with the current value of this field from the register. + * @param[out] txdynbw - Will be populated with the current value of this field from the register. + * @param[out] txfeccoding - Will be populated with the current value of this field from the register. + * @param[out] txsounding - Will be populated with the current value of this field from the register. + * @param[out] txpwlevel - Will be populated with the current value of this field from the register. + */ +__INLINE void mdm_txvector0_unpack(uint8_t *smmindex, uint8_t *txantennaset, uint8_t *txchbw, uint8_t *txsmoothing, uint8_t *txdynbw, uint8_t *txfeccoding, uint8_t *txsounding, uint8_t *txpwlevel) +{ + uint32_t localVal = REG_PL_RD(MDM_TXVECTOR0_ADDR); + + *smmindex = (localVal & ((uint32_t)0xFF000000)) >> 24; + *txantennaset = (localVal & ((uint32_t)0x00FF0000)) >> 16; + *txchbw = (localVal & ((uint32_t)0x00003000)) >> 12; + *txsmoothing = (localVal & ((uint32_t)0x00000800)) >> 11; + *txdynbw = (localVal & ((uint32_t)0x00000400)) >> 10; + *txfeccoding = (localVal & ((uint32_t)0x00000200)) >> 9; + *txsounding = (localVal & ((uint32_t)0x00000100)) >> 8; + *txpwlevel = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +/** + * @brief Returns the current value of the SMMINDEX field in the TXVECTOR0 register. + * + * The TXVECTOR0 register will be read and the SMMINDEX field's value will be returned. + * + * @return The current value of the SMMINDEX field in the TXVECTOR0 register. + */ +__INLINE uint8_t mdm_smmindex_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TXVECTOR0_ADDR); + return ((localVal & ((uint32_t)0xFF000000)) >> 24); +} + +/** + * @brief Returns the current value of the TXANTENNASET field in the TXVECTOR0 register. + * + * The TXVECTOR0 register will be read and the TXANTENNASET field's value will be returned. + * + * @return The current value of the TXANTENNASET field in the TXVECTOR0 register. + */ +__INLINE uint8_t mdm_txantennaset_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TXVECTOR0_ADDR); + return ((localVal & ((uint32_t)0x00FF0000)) >> 16); +} + +/** + * @brief Returns the current value of the TXCHBW field in the TXVECTOR0 register. + * + * The TXVECTOR0 register will be read and the TXCHBW field's value will be returned. + * + * @return The current value of the TXCHBW field in the TXVECTOR0 register. + */ +__INLINE uint8_t mdm_txchbw_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TXVECTOR0_ADDR); + return ((localVal & ((uint32_t)0x00003000)) >> 12); +} + +/** + * @brief Returns the current value of the TXSMOOTHING field in the TXVECTOR0 register. + * + * The TXVECTOR0 register will be read and the TXSMOOTHING field's value will be returned. + * + * @return The current value of the TXSMOOTHING field in the TXVECTOR0 register. + */ +__INLINE uint8_t mdm_txsmoothing_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TXVECTOR0_ADDR); + return ((localVal & ((uint32_t)0x00000800)) >> 11); +} + +/** + * @brief Returns the current value of the TXDYNBW field in the TXVECTOR0 register. + * + * The TXVECTOR0 register will be read and the TXDYNBW field's value will be returned. + * + * @return The current value of the TXDYNBW field in the TXVECTOR0 register. + */ +__INLINE uint8_t mdm_txdynbw_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TXVECTOR0_ADDR); + return ((localVal & ((uint32_t)0x00000400)) >> 10); +} + +/** + * @brief Returns the current value of the TXFECCODING field in the TXVECTOR0 register. + * + * The TXVECTOR0 register will be read and the TXFECCODING field's value will be returned. + * + * @return The current value of the TXFECCODING field in the TXVECTOR0 register. + */ +__INLINE uint8_t mdm_txfeccoding_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TXVECTOR0_ADDR); + return ((localVal & ((uint32_t)0x00000200)) >> 9); +} + +/** + * @brief Returns the current value of the TXSOUNDING field in the TXVECTOR0 register. + * + * The TXVECTOR0 register will be read and the TXSOUNDING field's value will be returned. + * + * @return The current value of the TXSOUNDING field in the TXVECTOR0 register. + */ +__INLINE uint8_t mdm_txsounding_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TXVECTOR0_ADDR); + return ((localVal & ((uint32_t)0x00000100)) >> 8); +} + +/** + * @brief Returns the current value of the TXPWLEVEL field in the TXVECTOR0 register. + * + * The TXVECTOR0 register will be read and the TXPWLEVEL field's value will be returned. + * + * @return The current value of the TXPWLEVEL field in the TXVECTOR0 register. + */ +__INLINE uint8_t mdm_txpwlevel_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TXVECTOR0_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +/// @} + +/** + * @name TXVECTOR1 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  22:20             TXNUMSTS   0x0
+ *  17:16           TXNUMEXTSS   0x0
+ *  14:12             TXFORMAT   0x0
+ *     08              PRETYPE   0
+ *  06:00                TXMCS   0x0
+ * 
+ * + * @{ + */ + +/// Address of the TXVECTOR1 register +#define MDM_TXVECTOR1_ADDR 0x01000044 +/// Offset of the TXVECTOR1 register from the base address +#define MDM_TXVECTOR1_OFFSET 0x00000044 +/// Index of the TXVECTOR1 register +#define MDM_TXVECTOR1_INDEX 0x00000011 +/// Reset value of the TXVECTOR1 register +#define MDM_TXVECTOR1_RESET 0x00000000 + +/** + * @brief Returns the current value of the TXVECTOR1 register. + * The TXVECTOR1 register will be read and its value returned. + * @return The current value of the TXVECTOR1 register. + */ +__INLINE uint32_t mdm_txvector1_get(void) +{ + return REG_PL_RD(MDM_TXVECTOR1_ADDR); +} + +// field definitions +/// TXNUMSTS field mask +#define MDM_TXNUMSTS_MASK ((uint32_t)0x00700000) +/// TXNUMSTS field LSB position +#define MDM_TXNUMSTS_LSB 20 +/// TXNUMSTS field width +#define MDM_TXNUMSTS_WIDTH ((uint32_t)0x00000003) +/// TXNUMEXTSS field mask +#define MDM_TXNUMEXTSS_MASK ((uint32_t)0x00030000) +/// TXNUMEXTSS field LSB position +#define MDM_TXNUMEXTSS_LSB 16 +/// TXNUMEXTSS field width +#define MDM_TXNUMEXTSS_WIDTH ((uint32_t)0x00000002) +/// TXFORMAT field mask +#define MDM_TXFORMAT_MASK ((uint32_t)0x00007000) +/// TXFORMAT field LSB position +#define MDM_TXFORMAT_LSB 12 +/// TXFORMAT field width +#define MDM_TXFORMAT_WIDTH ((uint32_t)0x00000003) +/// PRETYPE field bit +#define MDM_PRETYPE_BIT ((uint32_t)0x00000100) +/// PRETYPE field position +#define MDM_PRETYPE_POS 8 +/// TXMCS field mask +#define MDM_TXMCS_MASK ((uint32_t)0x0000007F) +/// TXMCS field LSB position +#define MDM_TXMCS_LSB 0 +/// TXMCS field width +#define MDM_TXMCS_WIDTH ((uint32_t)0x00000007) + +/// TXNUMSTS field reset value +#define MDM_TXNUMSTS_RST 0x0 +/// TXNUMEXTSS field reset value +#define MDM_TXNUMEXTSS_RST 0x0 +/// TXFORMAT field reset value +#define MDM_TXFORMAT_RST 0x0 +/// PRETYPE field reset value +#define MDM_PRETYPE_RST 0x0 +/// TXMCS field reset value +#define MDM_TXMCS_RST 0x0 + +/** + * @brief Unpacks TXVECTOR1's fields from current value of the TXVECTOR1 register. + * + * Reads the TXVECTOR1 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] txnumsts - Will be populated with the current value of this field from the register. + * @param[out] txnumextss - Will be populated with the current value of this field from the register. + * @param[out] txformat - Will be populated with the current value of this field from the register. + * @param[out] pretype - Will be populated with the current value of this field from the register. + * @param[out] txmcs - Will be populated with the current value of this field from the register. + */ +__INLINE void mdm_txvector1_unpack(uint8_t *txnumsts, uint8_t *txnumextss, uint8_t *txformat, uint8_t *pretype, uint8_t *txmcs) +{ + uint32_t localVal = REG_PL_RD(MDM_TXVECTOR1_ADDR); + + *txnumsts = (localVal & ((uint32_t)0x00700000)) >> 20; + *txnumextss = (localVal & ((uint32_t)0x00030000)) >> 16; + *txformat = (localVal & ((uint32_t)0x00007000)) >> 12; + *pretype = (localVal & ((uint32_t)0x00000100)) >> 8; + *txmcs = (localVal & ((uint32_t)0x0000007F)) >> 0; +} + +/** + * @brief Returns the current value of the TXNUMSTS field in the TXVECTOR1 register. + * + * The TXVECTOR1 register will be read and the TXNUMSTS field's value will be returned. + * + * @return The current value of the TXNUMSTS field in the TXVECTOR1 register. + */ +__INLINE uint8_t mdm_txnumsts_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TXVECTOR1_ADDR); + return ((localVal & ((uint32_t)0x00700000)) >> 20); +} + +/** + * @brief Returns the current value of the TXNUMEXTSS field in the TXVECTOR1 register. + * + * The TXVECTOR1 register will be read and the TXNUMEXTSS field's value will be returned. + * + * @return The current value of the TXNUMEXTSS field in the TXVECTOR1 register. + */ +__INLINE uint8_t mdm_txnumextss_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TXVECTOR1_ADDR); + return ((localVal & ((uint32_t)0x00030000)) >> 16); +} + +/** + * @brief Returns the current value of the TXFORMAT field in the TXVECTOR1 register. + * + * The TXVECTOR1 register will be read and the TXFORMAT field's value will be returned. + * + * @return The current value of the TXFORMAT field in the TXVECTOR1 register. + */ +__INLINE uint8_t mdm_txformat_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TXVECTOR1_ADDR); + return ((localVal & ((uint32_t)0x00007000)) >> 12); +} + +/** + * @brief Returns the current value of the PRETYPE field in the TXVECTOR1 register. + * + * The TXVECTOR1 register will be read and the PRETYPE field's value will be returned. + * + * @return The current value of the PRETYPE field in the TXVECTOR1 register. + */ +__INLINE uint8_t mdm_pretype_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TXVECTOR1_ADDR); + return ((localVal & ((uint32_t)0x00000100)) >> 8); +} + +/** + * @brief Returns the current value of the TXMCS field in the TXVECTOR1 register. + * + * The TXVECTOR1 register will be read and the TXMCS field's value will be returned. + * + * @return The current value of the TXMCS field in the TXVECTOR1 register. + */ +__INLINE uint8_t mdm_txmcs_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TXVECTOR1_ADDR); + return ((localVal & ((uint32_t)0x0000007F)) >> 0); +} + +/// @} + +/** + * @name TXVECTOR2 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:16              SERVICE   0x0
+ *  15:12            TXLEGRATE   0x0
+ *  11:00          TXLEGLENTGH   0x0
+ * 
+ * + * @{ + */ + +/// Address of the TXVECTOR2 register +#define MDM_TXVECTOR2_ADDR 0x01000048 +/// Offset of the TXVECTOR2 register from the base address +#define MDM_TXVECTOR2_OFFSET 0x00000048 +/// Index of the TXVECTOR2 register +#define MDM_TXVECTOR2_INDEX 0x00000012 +/// Reset value of the TXVECTOR2 register +#define MDM_TXVECTOR2_RESET 0x00000000 + +/** + * @brief Returns the current value of the TXVECTOR2 register. + * The TXVECTOR2 register will be read and its value returned. + * @return The current value of the TXVECTOR2 register. + */ +__INLINE uint32_t mdm_txvector2_get(void) +{ + return REG_PL_RD(MDM_TXVECTOR2_ADDR); +} + +// field definitions +/// SERVICE field mask +#define MDM_SERVICE_MASK ((uint32_t)0xFFFF0000) +/// SERVICE field LSB position +#define MDM_SERVICE_LSB 16 +/// SERVICE field width +#define MDM_SERVICE_WIDTH ((uint32_t)0x00000010) +/// TXLEGRATE field mask +#define MDM_TXLEGRATE_MASK ((uint32_t)0x0000F000) +/// TXLEGRATE field LSB position +#define MDM_TXLEGRATE_LSB 12 +/// TXLEGRATE field width +#define MDM_TXLEGRATE_WIDTH ((uint32_t)0x00000004) +/// TXLEGLENTGH field mask +#define MDM_TXLEGLENTGH_MASK ((uint32_t)0x00000FFF) +/// TXLEGLENTGH field LSB position +#define MDM_TXLEGLENTGH_LSB 0 +/// TXLEGLENTGH field width +#define MDM_TXLEGLENTGH_WIDTH ((uint32_t)0x0000000C) + +/// SERVICE field reset value +#define MDM_SERVICE_RST 0x0 +/// TXLEGRATE field reset value +#define MDM_TXLEGRATE_RST 0x0 +/// TXLEGLENTGH field reset value +#define MDM_TXLEGLENTGH_RST 0x0 + +/** + * @brief Unpacks TXVECTOR2's fields from current value of the TXVECTOR2 register. + * + * Reads the TXVECTOR2 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] service - Will be populated with the current value of this field from the register. + * @param[out] txlegrate - Will be populated with the current value of this field from the register. + * @param[out] txleglentgh - Will be populated with the current value of this field from the register. + */ +__INLINE void mdm_txvector2_unpack(uint16_t *service, uint8_t *txlegrate, uint16_t *txleglentgh) +{ + uint32_t localVal = REG_PL_RD(MDM_TXVECTOR2_ADDR); + + *service = (localVal & ((uint32_t)0xFFFF0000)) >> 16; + *txlegrate = (localVal & ((uint32_t)0x0000F000)) >> 12; + *txleglentgh = (localVal & ((uint32_t)0x00000FFF)) >> 0; +} + +/** + * @brief Returns the current value of the SERVICE field in the TXVECTOR2 register. + * + * The TXVECTOR2 register will be read and the SERVICE field's value will be returned. + * + * @return The current value of the SERVICE field in the TXVECTOR2 register. + */ +__INLINE uint16_t mdm_service_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TXVECTOR2_ADDR); + return ((localVal & ((uint32_t)0xFFFF0000)) >> 16); +} + +/** + * @brief Returns the current value of the TXLEGRATE field in the TXVECTOR2 register. + * + * The TXVECTOR2 register will be read and the TXLEGRATE field's value will be returned. + * + * @return The current value of the TXLEGRATE field in the TXVECTOR2 register. + */ +__INLINE uint8_t mdm_txlegrate_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TXVECTOR2_ADDR); + return ((localVal & ((uint32_t)0x0000F000)) >> 12); +} + +/** + * @brief Returns the current value of the TXLEGLENTGH field in the TXVECTOR2 register. + * + * The TXVECTOR2 register will be read and the TXLEGLENTGH field's value will be returned. + * + * @return The current value of the TXLEGLENTGH field in the TXVECTOR2 register. + */ +__INLINE uint16_t mdm_txleglentgh_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TXVECTOR2_ADDR); + return ((localVal & ((uint32_t)0x00000FFF)) >> 0); +} + +/// @} + +/** + * @name TXVECTOR3 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  29:28               TXSTBC   0x0
+ *  26:24                  NTX   0x0
+ *     22            TXSHORTGI   0
+ *     21     TXDOZENOTALLOWED   0
+ *     20             TXAGGREG   0
+ *  19:00           TXHTLENGTH   0x0
+ * 
+ * + * @{ + */ + +/// Address of the TXVECTOR3 register +#define MDM_TXVECTOR3_ADDR 0x0100004C +/// Offset of the TXVECTOR3 register from the base address +#define MDM_TXVECTOR3_OFFSET 0x0000004C +/// Index of the TXVECTOR3 register +#define MDM_TXVECTOR3_INDEX 0x00000013 +/// Reset value of the TXVECTOR3 register +#define MDM_TXVECTOR3_RESET 0x00000000 + +/** + * @brief Returns the current value of the TXVECTOR3 register. + * The TXVECTOR3 register will be read and its value returned. + * @return The current value of the TXVECTOR3 register. + */ +__INLINE uint32_t mdm_txvector3_get(void) +{ + return REG_PL_RD(MDM_TXVECTOR3_ADDR); +} + +// field definitions +/// TXSTBC field mask +#define MDM_TXSTBC_MASK ((uint32_t)0x30000000) +/// TXSTBC field LSB position +#define MDM_TXSTBC_LSB 28 +/// TXSTBC field width +#define MDM_TXSTBC_WIDTH ((uint32_t)0x00000002) +/// NTX field mask +#define MDM_NTX_MASK ((uint32_t)0x07000000) +/// NTX field LSB position +#define MDM_NTX_LSB 24 +/// NTX field width +#define MDM_NTX_WIDTH ((uint32_t)0x00000003) +/// TXSHORTGI field bit +#define MDM_TXSHORTGI_BIT ((uint32_t)0x00400000) +/// TXSHORTGI field position +#define MDM_TXSHORTGI_POS 22 +/// TXDOZENOTALLOWED field bit +#define MDM_TXDOZENOTALLOWED_BIT ((uint32_t)0x00200000) +/// TXDOZENOTALLOWED field position +#define MDM_TXDOZENOTALLOWED_POS 21 +/// TXAGGREG field bit +#define MDM_TXAGGREG_BIT ((uint32_t)0x00100000) +/// TXAGGREG field position +#define MDM_TXAGGREG_POS 20 +/// TXHTLENGTH field mask +#define MDM_TXHTLENGTH_MASK ((uint32_t)0x000FFFFF) +/// TXHTLENGTH field LSB position +#define MDM_TXHTLENGTH_LSB 0 +/// TXHTLENGTH field width +#define MDM_TXHTLENGTH_WIDTH ((uint32_t)0x00000014) + +/// TXSTBC field reset value +#define MDM_TXSTBC_RST 0x0 +/// NTX field reset value +#define MDM_NTX_RST 0x0 +/// TXSHORTGI field reset value +#define MDM_TXSHORTGI_RST 0x0 +/// TXDOZENOTALLOWED field reset value +#define MDM_TXDOZENOTALLOWED_RST 0x0 +/// TXAGGREG field reset value +#define MDM_TXAGGREG_RST 0x0 +/// TXHTLENGTH field reset value +#define MDM_TXHTLENGTH_RST 0x0 + +/** + * @brief Unpacks TXVECTOR3's fields from current value of the TXVECTOR3 register. + * + * Reads the TXVECTOR3 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] txstbc - Will be populated with the current value of this field from the register. + * @param[out] ntx - Will be populated with the current value of this field from the register. + * @param[out] txshortgi - Will be populated with the current value of this field from the register. + * @param[out] txdozenotallowed - Will be populated with the current value of this field from the register. + * @param[out] txaggreg - Will be populated with the current value of this field from the register. + * @param[out] txhtlength - Will be populated with the current value of this field from the register. + */ +__INLINE void mdm_txvector3_unpack(uint8_t *txstbc, uint8_t *ntx, uint8_t *txshortgi, uint8_t *txdozenotallowed, uint8_t *txaggreg, uint32_t *txhtlength) +{ + uint32_t localVal = REG_PL_RD(MDM_TXVECTOR3_ADDR); + + *txstbc = (localVal & ((uint32_t)0x30000000)) >> 28; + *ntx = (localVal & ((uint32_t)0x07000000)) >> 24; + *txshortgi = (localVal & ((uint32_t)0x00400000)) >> 22; + *txdozenotallowed = (localVal & ((uint32_t)0x00200000)) >> 21; + *txaggreg = (localVal & ((uint32_t)0x00100000)) >> 20; + *txhtlength = (localVal & ((uint32_t)0x000FFFFF)) >> 0; +} + +/** + * @brief Returns the current value of the TXSTBC field in the TXVECTOR3 register. + * + * The TXVECTOR3 register will be read and the TXSTBC field's value will be returned. + * + * @return The current value of the TXSTBC field in the TXVECTOR3 register. + */ +__INLINE uint8_t mdm_txstbc_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TXVECTOR3_ADDR); + return ((localVal & ((uint32_t)0x30000000)) >> 28); +} + +/** + * @brief Returns the current value of the NTX field in the TXVECTOR3 register. + * + * The TXVECTOR3 register will be read and the NTX field's value will be returned. + * + * @return The current value of the NTX field in the TXVECTOR3 register. + */ +__INLINE uint8_t mdm_ntx_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TXVECTOR3_ADDR); + return ((localVal & ((uint32_t)0x07000000)) >> 24); +} + +/** + * @brief Returns the current value of the TXSHORTGI field in the TXVECTOR3 register. + * + * The TXVECTOR3 register will be read and the TXSHORTGI field's value will be returned. + * + * @return The current value of the TXSHORTGI field in the TXVECTOR3 register. + */ +__INLINE uint8_t mdm_txshortgi_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TXVECTOR3_ADDR); + return ((localVal & ((uint32_t)0x00400000)) >> 22); +} + +/** + * @brief Returns the current value of the TXDOZENOTALLOWED field in the TXVECTOR3 register. + * + * The TXVECTOR3 register will be read and the TXDOZENOTALLOWED field's value will be returned. + * + * @return The current value of the TXDOZENOTALLOWED field in the TXVECTOR3 register. + */ +__INLINE uint8_t mdm_txdozenotallowed_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TXVECTOR3_ADDR); + return ((localVal & ((uint32_t)0x00200000)) >> 21); +} + +/** + * @brief Returns the current value of the TXAGGREG field in the TXVECTOR3 register. + * + * The TXVECTOR3 register will be read and the TXAGGREG field's value will be returned. + * + * @return The current value of the TXAGGREG field in the TXVECTOR3 register. + */ +__INLINE uint8_t mdm_txaggreg_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TXVECTOR3_ADDR); + return ((localVal & ((uint32_t)0x00100000)) >> 20); +} + +/** + * @brief Returns the current value of the TXHTLENGTH field in the TXVECTOR3 register. + * + * The TXVECTOR3 register will be read and the TXHTLENGTH field's value will be returned. + * + * @return The current value of the TXHTLENGTH field in the TXVECTOR3 register. + */ +__INLINE uint32_t mdm_txhtlength_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TXVECTOR3_ADDR); + return ((localVal & ((uint32_t)0x000FFFFF)) >> 0); +} + +/// @} + +/** + * @name TXVECTOR4 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  17:12            TXGROUPID   0x0
+ *  08:00         TXPARTIALAID   0x0
+ * 
+ * + * @{ + */ + +/// Address of the TXVECTOR4 register +#define MDM_TXVECTOR4_ADDR 0x01000050 +/// Offset of the TXVECTOR4 register from the base address +#define MDM_TXVECTOR4_OFFSET 0x00000050 +/// Index of the TXVECTOR4 register +#define MDM_TXVECTOR4_INDEX 0x00000014 +/// Reset value of the TXVECTOR4 register +#define MDM_TXVECTOR4_RESET 0x00000000 + +/** + * @brief Returns the current value of the TXVECTOR4 register. + * The TXVECTOR4 register will be read and its value returned. + * @return The current value of the TXVECTOR4 register. + */ +__INLINE uint32_t mdm_txvector4_get(void) +{ + return REG_PL_RD(MDM_TXVECTOR4_ADDR); +} + +// field definitions +/// TXGROUPID field mask +#define MDM_TXGROUPID_MASK ((uint32_t)0x0003F000) +/// TXGROUPID field LSB position +#define MDM_TXGROUPID_LSB 12 +/// TXGROUPID field width +#define MDM_TXGROUPID_WIDTH ((uint32_t)0x00000006) +/// TXPARTIALAID field mask +#define MDM_TXPARTIALAID_MASK ((uint32_t)0x000001FF) +/// TXPARTIALAID field LSB position +#define MDM_TXPARTIALAID_LSB 0 +/// TXPARTIALAID field width +#define MDM_TXPARTIALAID_WIDTH ((uint32_t)0x00000009) + +/// TXGROUPID field reset value +#define MDM_TXGROUPID_RST 0x0 +/// TXPARTIALAID field reset value +#define MDM_TXPARTIALAID_RST 0x0 + +/** + * @brief Unpacks TXVECTOR4's fields from current value of the TXVECTOR4 register. + * + * Reads the TXVECTOR4 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] txgroupid - Will be populated with the current value of this field from the register. + * @param[out] txpartialaid - Will be populated with the current value of this field from the register. + */ +__INLINE void mdm_txvector4_unpack(uint8_t *txgroupid, uint16_t *txpartialaid) +{ + uint32_t localVal = REG_PL_RD(MDM_TXVECTOR4_ADDR); + + *txgroupid = (localVal & ((uint32_t)0x0003F000)) >> 12; + *txpartialaid = (localVal & ((uint32_t)0x000001FF)) >> 0; +} + +/** + * @brief Returns the current value of the TXGROUPID field in the TXVECTOR4 register. + * + * The TXVECTOR4 register will be read and the TXGROUPID field's value will be returned. + * + * @return The current value of the TXGROUPID field in the TXVECTOR4 register. + */ +__INLINE uint8_t mdm_txgroupid_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TXVECTOR4_ADDR); + return ((localVal & ((uint32_t)0x0003F000)) >> 12); +} + +/** + * @brief Returns the current value of the TXPARTIALAID field in the TXVECTOR4 register. + * + * The TXVECTOR4 register will be read and the TXPARTIALAID field's value will be returned. + * + * @return The current value of the TXPARTIALAID field in the TXVECTOR4 register. + */ +__INLINE uint16_t mdm_txpartialaid_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TXVECTOR4_ADDR); + return ((localVal & ((uint32_t)0x000001FF)) >> 0); +} + +/// @} + +/** + * @name TXVECDECSTAT register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     07          TXVECGI2ERR   0
+ *     06           TXVECBWERR   0
+ *     05         MTXVECGI1ERR   0
+ *     04          TXVECMCSERR   0
+ *     03          TXVECLEGERR   0
+ *     02         TXVECNULLERR   0
+ *     01          TXLECLENERR   0
+ *     00        TXVECSOUNDERR   0
+ * 
+ * + * @{ + */ + +/// Address of the TXVECDECSTAT register +#define MDM_TXVECDECSTAT_ADDR 0x01000054 +/// Offset of the TXVECDECSTAT register from the base address +#define MDM_TXVECDECSTAT_OFFSET 0x00000054 +/// Index of the TXVECDECSTAT register +#define MDM_TXVECDECSTAT_INDEX 0x00000015 +/// Reset value of the TXVECDECSTAT register +#define MDM_TXVECDECSTAT_RESET 0x00000000 + +/** + * @brief Returns the current value of the TXVECDECSTAT register. + * The TXVECDECSTAT register will be read and its value returned. + * @return The current value of the TXVECDECSTAT register. + */ +__INLINE uint32_t mdm_txvecdecstat_get(void) +{ + return REG_PL_RD(MDM_TXVECDECSTAT_ADDR); +} + +// field definitions +/// TXVECGI2ERR field bit +#define MDM_TXVECGI2ERR_BIT ((uint32_t)0x00000080) +/// TXVECGI2ERR field position +#define MDM_TXVECGI2ERR_POS 7 +/// TXVECBWERR field bit +#define MDM_TXVECBWERR_BIT ((uint32_t)0x00000040) +/// TXVECBWERR field position +#define MDM_TXVECBWERR_POS 6 +/// MTXVECGI1ERR field bit +#define MDM_MTXVECGI1ERR_BIT ((uint32_t)0x00000020) +/// MTXVECGI1ERR field position +#define MDM_MTXVECGI1ERR_POS 5 +/// TXVECMCSERR field bit +#define MDM_TXVECMCSERR_BIT ((uint32_t)0x00000010) +/// TXVECMCSERR field position +#define MDM_TXVECMCSERR_POS 4 +/// TXVECLEGERR field bit +#define MDM_TXVECLEGERR_BIT ((uint32_t)0x00000008) +/// TXVECLEGERR field position +#define MDM_TXVECLEGERR_POS 3 +/// TXVECNULLERR field bit +#define MDM_TXVECNULLERR_BIT ((uint32_t)0x00000004) +/// TXVECNULLERR field position +#define MDM_TXVECNULLERR_POS 2 +/// TXLECLENERR field bit +#define MDM_TXLECLENERR_BIT ((uint32_t)0x00000002) +/// TXLECLENERR field position +#define MDM_TXLECLENERR_POS 1 +/// TXVECSOUNDERR field bit +#define MDM_TXVECSOUNDERR_BIT ((uint32_t)0x00000001) +/// TXVECSOUNDERR field position +#define MDM_TXVECSOUNDERR_POS 0 + +/// TXVECGI2ERR field reset value +#define MDM_TXVECGI2ERR_RST 0x0 +/// TXVECBWERR field reset value +#define MDM_TXVECBWERR_RST 0x0 +/// MTXVECGI1ERR field reset value +#define MDM_MTXVECGI1ERR_RST 0x0 +/// TXVECMCSERR field reset value +#define MDM_TXVECMCSERR_RST 0x0 +/// TXVECLEGERR field reset value +#define MDM_TXVECLEGERR_RST 0x0 +/// TXVECNULLERR field reset value +#define MDM_TXVECNULLERR_RST 0x0 +/// TXLECLENERR field reset value +#define MDM_TXLECLENERR_RST 0x0 +/// TXVECSOUNDERR field reset value +#define MDM_TXVECSOUNDERR_RST 0x0 + +/** + * @brief Unpacks TXVECDECSTAT's fields from current value of the TXVECDECSTAT register. + * + * Reads the TXVECDECSTAT register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] txvecgi2err - Will be populated with the current value of this field from the register. + * @param[out] txvecbwerr - Will be populated with the current value of this field from the register. + * @param[out] mtxvecgi1err - Will be populated with the current value of this field from the register. + * @param[out] txvecmcserr - Will be populated with the current value of this field from the register. + * @param[out] txveclegerr - Will be populated with the current value of this field from the register. + * @param[out] txvecnullerr - Will be populated with the current value of this field from the register. + * @param[out] txleclenerr - Will be populated with the current value of this field from the register. + * @param[out] txvecsounderr - Will be populated with the current value of this field from the register. + */ +__INLINE void mdm_txvecdecstat_unpack(uint8_t *txvecgi2err, uint8_t *txvecbwerr, uint8_t *mtxvecgi1err, uint8_t *txvecmcserr, uint8_t *txveclegerr, uint8_t *txvecnullerr, uint8_t *txleclenerr, uint8_t *txvecsounderr) +{ + uint32_t localVal = REG_PL_RD(MDM_TXVECDECSTAT_ADDR); + + *txvecgi2err = (localVal & ((uint32_t)0x00000080)) >> 7; + *txvecbwerr = (localVal & ((uint32_t)0x00000040)) >> 6; + *mtxvecgi1err = (localVal & ((uint32_t)0x00000020)) >> 5; + *txvecmcserr = (localVal & ((uint32_t)0x00000010)) >> 4; + *txveclegerr = (localVal & ((uint32_t)0x00000008)) >> 3; + *txvecnullerr = (localVal & ((uint32_t)0x00000004)) >> 2; + *txleclenerr = (localVal & ((uint32_t)0x00000002)) >> 1; + *txvecsounderr = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +/** + * @brief Returns the current value of the TXVECGI2ERR field in the TXVECDECSTAT register. + * + * The TXVECDECSTAT register will be read and the TXVECGI2ERR field's value will be returned. + * + * @return The current value of the TXVECGI2ERR field in the TXVECDECSTAT register. + */ +__INLINE uint8_t mdm_txvecgi2err_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TXVECDECSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000080)) >> 7); +} + +/** + * @brief Returns the current value of the TXVECBWERR field in the TXVECDECSTAT register. + * + * The TXVECDECSTAT register will be read and the TXVECBWERR field's value will be returned. + * + * @return The current value of the TXVECBWERR field in the TXVECDECSTAT register. + */ +__INLINE uint8_t mdm_txvecbwerr_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TXVECDECSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000040)) >> 6); +} + +/** + * @brief Returns the current value of the MTXVECGI1ERR field in the TXVECDECSTAT register. + * + * The TXVECDECSTAT register will be read and the MTXVECGI1ERR field's value will be returned. + * + * @return The current value of the MTXVECGI1ERR field in the TXVECDECSTAT register. + */ +__INLINE uint8_t mdm_mtxvecgi1err_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TXVECDECSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000020)) >> 5); +} + +/** + * @brief Returns the current value of the TXVECMCSERR field in the TXVECDECSTAT register. + * + * The TXVECDECSTAT register will be read and the TXVECMCSERR field's value will be returned. + * + * @return The current value of the TXVECMCSERR field in the TXVECDECSTAT register. + */ +__INLINE uint8_t mdm_txvecmcserr_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TXVECDECSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000010)) >> 4); +} + +/** + * @brief Returns the current value of the TXVECLEGERR field in the TXVECDECSTAT register. + * + * The TXVECDECSTAT register will be read and the TXVECLEGERR field's value will be returned. + * + * @return The current value of the TXVECLEGERR field in the TXVECDECSTAT register. + */ +__INLINE uint8_t mdm_txveclegerr_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TXVECDECSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +/** + * @brief Returns the current value of the TXVECNULLERR field in the TXVECDECSTAT register. + * + * The TXVECDECSTAT register will be read and the TXVECNULLERR field's value will be returned. + * + * @return The current value of the TXVECNULLERR field in the TXVECDECSTAT register. + */ +__INLINE uint8_t mdm_txvecnullerr_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TXVECDECSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +/** + * @brief Returns the current value of the TXLECLENERR field in the TXVECDECSTAT register. + * + * The TXVECDECSTAT register will be read and the TXLECLENERR field's value will be returned. + * + * @return The current value of the TXLECLENERR field in the TXVECDECSTAT register. + */ +__INLINE uint8_t mdm_txleclenerr_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TXVECDECSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +/** + * @brief Returns the current value of the TXVECSOUNDERR field in the TXVECDECSTAT register. + * + * The TXVECDECSTAT register will be read and the TXVECSOUNDERR field's value will be returned. + * + * @return The current value of the TXVECSOUNDERR field in the TXVECDECSTAT register. + */ +__INLINE uint8_t mdm_txvecsounderr_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TXVECDECSTAT_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +/// @} + +/** + * @name MIMOCMDSTAT register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:24            MIMOCMDP3   0x0
+ *  23:16            MIMOCMDP2   0x0
+ *  15:08            MIMOCMDP1   0x0
+ *  07:00              MIMOCMD   0x0
+ * 
+ * + * @{ + */ + +/// Address of the MIMOCMDSTAT register +#define MDM_MIMOCMDSTAT_ADDR 0x01000058 +/// Offset of the MIMOCMDSTAT register from the base address +#define MDM_MIMOCMDSTAT_OFFSET 0x00000058 +/// Index of the MIMOCMDSTAT register +#define MDM_MIMOCMDSTAT_INDEX 0x00000016 +/// Reset value of the MIMOCMDSTAT register +#define MDM_MIMOCMDSTAT_RESET 0x00000000 + +/** + * @brief Returns the current value of the MIMOCMDSTAT register. + * The MIMOCMDSTAT register will be read and its value returned. + * @return The current value of the MIMOCMDSTAT register. + */ +__INLINE uint32_t mdm_mimocmdstat_get(void) +{ + return REG_PL_RD(MDM_MIMOCMDSTAT_ADDR); +} + +// field definitions +/// MIMOCMDP3 field mask +#define MDM_MIMOCMDP3_MASK ((uint32_t)0xFF000000) +/// MIMOCMDP3 field LSB position +#define MDM_MIMOCMDP3_LSB 24 +/// MIMOCMDP3 field width +#define MDM_MIMOCMDP3_WIDTH ((uint32_t)0x00000008) +/// MIMOCMDP2 field mask +#define MDM_MIMOCMDP2_MASK ((uint32_t)0x00FF0000) +/// MIMOCMDP2 field LSB position +#define MDM_MIMOCMDP2_LSB 16 +/// MIMOCMDP2 field width +#define MDM_MIMOCMDP2_WIDTH ((uint32_t)0x00000008) +/// MIMOCMDP1 field mask +#define MDM_MIMOCMDP1_MASK ((uint32_t)0x0000FF00) +/// MIMOCMDP1 field LSB position +#define MDM_MIMOCMDP1_LSB 8 +/// MIMOCMDP1 field width +#define MDM_MIMOCMDP1_WIDTH ((uint32_t)0x00000008) +/// MIMOCMD field mask +#define MDM_MIMOCMD_MASK ((uint32_t)0x000000FF) +/// MIMOCMD field LSB position +#define MDM_MIMOCMD_LSB 0 +/// MIMOCMD field width +#define MDM_MIMOCMD_WIDTH ((uint32_t)0x00000008) + +/// MIMOCMDP3 field reset value +#define MDM_MIMOCMDP3_RST 0x0 +/// MIMOCMDP2 field reset value +#define MDM_MIMOCMDP2_RST 0x0 +/// MIMOCMDP1 field reset value +#define MDM_MIMOCMDP1_RST 0x0 +/// MIMOCMD field reset value +#define MDM_MIMOCMD_RST 0x0 + +/** + * @brief Unpacks MIMOCMDSTAT's fields from current value of the MIMOCMDSTAT register. + * + * Reads the MIMOCMDSTAT register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] mimocmdp3 - Will be populated with the current value of this field from the register. + * @param[out] mimocmdp2 - Will be populated with the current value of this field from the register. + * @param[out] mimocmdp1 - Will be populated with the current value of this field from the register. + * @param[out] mimocmd - Will be populated with the current value of this field from the register. + */ +__INLINE void mdm_mimocmdstat_unpack(uint8_t *mimocmdp3, uint8_t *mimocmdp2, uint8_t *mimocmdp1, uint8_t *mimocmd) +{ + uint32_t localVal = REG_PL_RD(MDM_MIMOCMDSTAT_ADDR); + + *mimocmdp3 = (localVal & ((uint32_t)0xFF000000)) >> 24; + *mimocmdp2 = (localVal & ((uint32_t)0x00FF0000)) >> 16; + *mimocmdp1 = (localVal & ((uint32_t)0x0000FF00)) >> 8; + *mimocmd = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +/** + * @brief Returns the current value of the MIMOCMDP3 field in the MIMOCMDSTAT register. + * + * The MIMOCMDSTAT register will be read and the MIMOCMDP3 field's value will be returned. + * + * @return The current value of the MIMOCMDP3 field in the MIMOCMDSTAT register. + */ +__INLINE uint8_t mdm_mimocmdp3_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_MIMOCMDSTAT_ADDR); + return ((localVal & ((uint32_t)0xFF000000)) >> 24); +} + +/** + * @brief Returns the current value of the MIMOCMDP2 field in the MIMOCMDSTAT register. + * + * The MIMOCMDSTAT register will be read and the MIMOCMDP2 field's value will be returned. + * + * @return The current value of the MIMOCMDP2 field in the MIMOCMDSTAT register. + */ +__INLINE uint8_t mdm_mimocmdp2_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_MIMOCMDSTAT_ADDR); + return ((localVal & ((uint32_t)0x00FF0000)) >> 16); +} + +/** + * @brief Returns the current value of the MIMOCMDP1 field in the MIMOCMDSTAT register. + * + * The MIMOCMDSTAT register will be read and the MIMOCMDP1 field's value will be returned. + * + * @return The current value of the MIMOCMDP1 field in the MIMOCMDSTAT register. + */ +__INLINE uint8_t mdm_mimocmdp1_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_MIMOCMDSTAT_ADDR); + return ((localVal & ((uint32_t)0x0000FF00)) >> 8); +} + +/** + * @brief Returns the current value of the MIMOCMD field in the MIMOCMDSTAT register. + * + * The MIMOCMDSTAT register will be read and the MIMOCMD field's value will be returned. + * + * @return The current value of the MIMOCMD field in the MIMOCMDSTAT register. + */ +__INLINE uint8_t mdm_mimocmd_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_MIMOCMDSTAT_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +/// @} + +/** + * @name TBESTAT0 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  23:08     TBEMaxCorrValSum   0x0
+ *  07:00             TBECOUNT   0x0
+ * 
+ * + * @{ + */ + +/// Address of the TBESTAT0 register +#define MDM_TBESTAT0_ADDR 0x0100005C +/// Offset of the TBESTAT0 register from the base address +#define MDM_TBESTAT0_OFFSET 0x0000005C +/// Index of the TBESTAT0 register +#define MDM_TBESTAT0_INDEX 0x00000017 +/// Reset value of the TBESTAT0 register +#define MDM_TBESTAT0_RESET 0x00000000 + +/** + * @brief Returns the current value of the TBESTAT0 register. + * The TBESTAT0 register will be read and its value returned. + * @return The current value of the TBESTAT0 register. + */ +__INLINE uint32_t mdm_tbestat0_get(void) +{ + return REG_PL_RD(MDM_TBESTAT0_ADDR); +} + +// field definitions +/// TBE_MAX_CORR_VAL_SUM field mask +#define MDM_TBE_MAX_CORR_VAL_SUM_MASK ((uint32_t)0x00FFFF00) +/// TBE_MAX_CORR_VAL_SUM field LSB position +#define MDM_TBE_MAX_CORR_VAL_SUM_LSB 8 +/// TBE_MAX_CORR_VAL_SUM field width +#define MDM_TBE_MAX_CORR_VAL_SUM_WIDTH ((uint32_t)0x00000010) +/// TBECOUNT field mask +#define MDM_TBECOUNT_MASK ((uint32_t)0x000000FF) +/// TBECOUNT field LSB position +#define MDM_TBECOUNT_LSB 0 +/// TBECOUNT field width +#define MDM_TBECOUNT_WIDTH ((uint32_t)0x00000008) + +/// TBE_MAX_CORR_VAL_SUM field reset value +#define MDM_TBE_MAX_CORR_VAL_SUM_RST 0x0 +/// TBECOUNT field reset value +#define MDM_TBECOUNT_RST 0x0 + +/** + * @brief Unpacks TBESTAT0's fields from current value of the TBESTAT0 register. + * + * Reads the TBESTAT0 register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] tbemaxcorrvalsum - Will be populated with the current value of this field from the register. + * @param[out] tbecount - Will be populated with the current value of this field from the register. + */ +__INLINE void mdm_tbestat0_unpack(uint16_t *tbemaxcorrvalsum, uint8_t *tbecount) +{ + uint32_t localVal = REG_PL_RD(MDM_TBESTAT0_ADDR); + + *tbemaxcorrvalsum = (localVal & ((uint32_t)0x00FFFF00)) >> 8; + *tbecount = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +/** + * @brief Returns the current value of the TBEMaxCorrValSum field in the TBESTAT0 register. + * + * The TBESTAT0 register will be read and the TBEMaxCorrValSum field's value will be returned. + * + * @return The current value of the TBEMaxCorrValSum field in the TBESTAT0 register. + */ +__INLINE uint16_t mdm_tbe_max_corr_val_sum_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TBESTAT0_ADDR); + return ((localVal & ((uint32_t)0x00FFFF00)) >> 8); +} + +/** + * @brief Returns the current value of the TBECOUNT field in the TBESTAT0 register. + * + * The TBESTAT0 register will be read and the TBECOUNT field's value will be returned. + * + * @return The current value of the TBECOUNT field in the TBESTAT0 register. + */ +__INLINE uint8_t mdm_tbecount_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_TBESTAT0_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +/// @} + +/** + * @name AGCGAINSTAT register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  30:24             AGCGAIN3   0x0
+ *  22:16             AGCGAIN2   0x0
+ *  14:08             AGCGAIN1   0x0
+ *  06:00             AGCGAIN0   0x0
+ * 
+ * + * @{ + */ + +/// Address of the AGCGAINSTAT register +#define MDM_AGCGAINSTAT_ADDR 0x01000060 +/// Offset of the AGCGAINSTAT register from the base address +#define MDM_AGCGAINSTAT_OFFSET 0x00000060 +/// Index of the AGCGAINSTAT register +#define MDM_AGCGAINSTAT_INDEX 0x00000018 +/// Reset value of the AGCGAINSTAT register +#define MDM_AGCGAINSTAT_RESET 0x00000000 + +/** + * @brief Returns the current value of the AGCGAINSTAT register. + * The AGCGAINSTAT register will be read and its value returned. + * @return The current value of the AGCGAINSTAT register. + */ +__INLINE uint32_t mdm_agcgainstat_get(void) +{ + return REG_PL_RD(MDM_AGCGAINSTAT_ADDR); +} + +// field definitions +/// AGCGAIN3 field mask +#define MDM_AGCGAIN3_MASK ((uint32_t)0x7F000000) +/// AGCGAIN3 field LSB position +#define MDM_AGCGAIN3_LSB 24 +/// AGCGAIN3 field width +#define MDM_AGCGAIN3_WIDTH ((uint32_t)0x00000007) +/// AGCGAIN2 field mask +#define MDM_AGCGAIN2_MASK ((uint32_t)0x007F0000) +/// AGCGAIN2 field LSB position +#define MDM_AGCGAIN2_LSB 16 +/// AGCGAIN2 field width +#define MDM_AGCGAIN2_WIDTH ((uint32_t)0x00000007) +/// AGCGAIN1 field mask +#define MDM_AGCGAIN1_MASK ((uint32_t)0x00007F00) +/// AGCGAIN1 field LSB position +#define MDM_AGCGAIN1_LSB 8 +/// AGCGAIN1 field width +#define MDM_AGCGAIN1_WIDTH ((uint32_t)0x00000007) +/// AGCGAIN0 field mask +#define MDM_AGCGAIN0_MASK ((uint32_t)0x0000007F) +/// AGCGAIN0 field LSB position +#define MDM_AGCGAIN0_LSB 0 +/// AGCGAIN0 field width +#define MDM_AGCGAIN0_WIDTH ((uint32_t)0x00000007) + +/// AGCGAIN3 field reset value +#define MDM_AGCGAIN3_RST 0x0 +/// AGCGAIN2 field reset value +#define MDM_AGCGAIN2_RST 0x0 +/// AGCGAIN1 field reset value +#define MDM_AGCGAIN1_RST 0x0 +/// AGCGAIN0 field reset value +#define MDM_AGCGAIN0_RST 0x0 + +/** + * @brief Unpacks AGCGAINSTAT's fields from current value of the AGCGAINSTAT register. + * + * Reads the AGCGAINSTAT register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] agcgain3 - Will be populated with the current value of this field from the register. + * @param[out] agcgain2 - Will be populated with the current value of this field from the register. + * @param[out] agcgain1 - Will be populated with the current value of this field from the register. + * @param[out] agcgain0 - Will be populated with the current value of this field from the register. + */ +__INLINE void mdm_agcgainstat_unpack(uint8_t *agcgain3, uint8_t *agcgain2, uint8_t *agcgain1, uint8_t *agcgain0) +{ + uint32_t localVal = REG_PL_RD(MDM_AGCGAINSTAT_ADDR); + + *agcgain3 = (localVal & ((uint32_t)0x7F000000)) >> 24; + *agcgain2 = (localVal & ((uint32_t)0x007F0000)) >> 16; + *agcgain1 = (localVal & ((uint32_t)0x00007F00)) >> 8; + *agcgain0 = (localVal & ((uint32_t)0x0000007F)) >> 0; +} + +/** + * @brief Returns the current value of the AGCGAIN3 field in the AGCGAINSTAT register. + * + * The AGCGAINSTAT register will be read and the AGCGAIN3 field's value will be returned. + * + * @return The current value of the AGCGAIN3 field in the AGCGAINSTAT register. + */ +__INLINE uint8_t mdm_agcgain3_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_AGCGAINSTAT_ADDR); + return ((localVal & ((uint32_t)0x7F000000)) >> 24); +} + +/** + * @brief Returns the current value of the AGCGAIN2 field in the AGCGAINSTAT register. + * + * The AGCGAINSTAT register will be read and the AGCGAIN2 field's value will be returned. + * + * @return The current value of the AGCGAIN2 field in the AGCGAINSTAT register. + */ +__INLINE uint8_t mdm_agcgain2_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_AGCGAINSTAT_ADDR); + return ((localVal & ((uint32_t)0x007F0000)) >> 16); +} + +/** + * @brief Returns the current value of the AGCGAIN1 field in the AGCGAINSTAT register. + * + * The AGCGAINSTAT register will be read and the AGCGAIN1 field's value will be returned. + * + * @return The current value of the AGCGAIN1 field in the AGCGAINSTAT register. + */ +__INLINE uint8_t mdm_agcgain1_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_AGCGAINSTAT_ADDR); + return ((localVal & ((uint32_t)0x00007F00)) >> 8); +} + +/** + * @brief Returns the current value of the AGCGAIN0 field in the AGCGAINSTAT register. + * + * The AGCGAINSTAT register will be read and the AGCGAIN0 field's value will be returned. + * + * @return The current value of the AGCGAIN0 field in the AGCGAINSTAT register. + */ +__INLINE uint8_t mdm_agcgain0_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_AGCGAINSTAT_ADDR); + return ((localVal & ((uint32_t)0x0000007F)) >> 0); +} + +/// @} + +/** + * @name AGCADCPOWSTAT register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  30:24           ADCPOWDBV3   0x0
+ *  22:16           ADCPOWDBV2   0x0
+ *  14:08           ADCPOWDBV1   0x0
+ *  06:00           ADCPOWDBV0   0x0
+ * 
+ * + * @{ + */ + +/// Address of the AGCADCPOWSTAT register +#define MDM_AGCADCPOWSTAT_ADDR 0x01000064 +/// Offset of the AGCADCPOWSTAT register from the base address +#define MDM_AGCADCPOWSTAT_OFFSET 0x00000064 +/// Index of the AGCADCPOWSTAT register +#define MDM_AGCADCPOWSTAT_INDEX 0x00000019 +/// Reset value of the AGCADCPOWSTAT register +#define MDM_AGCADCPOWSTAT_RESET 0x00000000 + +/** + * @brief Returns the current value of the AGCADCPOWSTAT register. + * The AGCADCPOWSTAT register will be read and its value returned. + * @return The current value of the AGCADCPOWSTAT register. + */ +__INLINE uint32_t mdm_agcadcpowstat_get(void) +{ + return REG_PL_RD(MDM_AGCADCPOWSTAT_ADDR); +} + +// field definitions +/// ADCPOWDBV3 field mask +#define MDM_ADCPOWDBV3_MASK ((uint32_t)0x7F000000) +/// ADCPOWDBV3 field LSB position +#define MDM_ADCPOWDBV3_LSB 24 +/// ADCPOWDBV3 field width +#define MDM_ADCPOWDBV3_WIDTH ((uint32_t)0x00000007) +/// ADCPOWDBV2 field mask +#define MDM_ADCPOWDBV2_MASK ((uint32_t)0x007F0000) +/// ADCPOWDBV2 field LSB position +#define MDM_ADCPOWDBV2_LSB 16 +/// ADCPOWDBV2 field width +#define MDM_ADCPOWDBV2_WIDTH ((uint32_t)0x00000007) +/// ADCPOWDBV1 field mask +#define MDM_ADCPOWDBV1_MASK ((uint32_t)0x00007F00) +/// ADCPOWDBV1 field LSB position +#define MDM_ADCPOWDBV1_LSB 8 +/// ADCPOWDBV1 field width +#define MDM_ADCPOWDBV1_WIDTH ((uint32_t)0x00000007) +/// ADCPOWDBV0 field mask +#define MDM_ADCPOWDBV0_MASK ((uint32_t)0x0000007F) +/// ADCPOWDBV0 field LSB position +#define MDM_ADCPOWDBV0_LSB 0 +/// ADCPOWDBV0 field width +#define MDM_ADCPOWDBV0_WIDTH ((uint32_t)0x00000007) + +/// ADCPOWDBV3 field reset value +#define MDM_ADCPOWDBV3_RST 0x0 +/// ADCPOWDBV2 field reset value +#define MDM_ADCPOWDBV2_RST 0x0 +/// ADCPOWDBV1 field reset value +#define MDM_ADCPOWDBV1_RST 0x0 +/// ADCPOWDBV0 field reset value +#define MDM_ADCPOWDBV0_RST 0x0 + +/** + * @brief Unpacks AGCADCPOWSTAT's fields from current value of the AGCADCPOWSTAT register. + * + * Reads the AGCADCPOWSTAT register and populates all the _field variables with the corresponding + * values from the register. + * + * @param[out] adcpowdbv3 - Will be populated with the current value of this field from the register. + * @param[out] adcpowdbv2 - Will be populated with the current value of this field from the register. + * @param[out] adcpowdbv1 - Will be populated with the current value of this field from the register. + * @param[out] adcpowdbv0 - Will be populated with the current value of this field from the register. + */ +__INLINE void mdm_agcadcpowstat_unpack(uint8_t *adcpowdbv3, uint8_t *adcpowdbv2, uint8_t *adcpowdbv1, uint8_t *adcpowdbv0) +{ + uint32_t localVal = REG_PL_RD(MDM_AGCADCPOWSTAT_ADDR); + + *adcpowdbv3 = (localVal & ((uint32_t)0x7F000000)) >> 24; + *adcpowdbv2 = (localVal & ((uint32_t)0x007F0000)) >> 16; + *adcpowdbv1 = (localVal & ((uint32_t)0x00007F00)) >> 8; + *adcpowdbv0 = (localVal & ((uint32_t)0x0000007F)) >> 0; +} + +/** + * @brief Returns the current value of the ADCPOWDBV3 field in the AGCADCPOWSTAT register. + * + * The AGCADCPOWSTAT register will be read and the ADCPOWDBV3 field's value will be returned. + * + * @return The current value of the ADCPOWDBV3 field in the AGCADCPOWSTAT register. + */ +__INLINE uint8_t mdm_adcpowdbv3_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_AGCADCPOWSTAT_ADDR); + return ((localVal & ((uint32_t)0x7F000000)) >> 24); +} + +/** + * @brief Returns the current value of the ADCPOWDBV2 field in the AGCADCPOWSTAT register. + * + * The AGCADCPOWSTAT register will be read and the ADCPOWDBV2 field's value will be returned. + * + * @return The current value of the ADCPOWDBV2 field in the AGCADCPOWSTAT register. + */ +__INLINE uint8_t mdm_adcpowdbv2_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_AGCADCPOWSTAT_ADDR); + return ((localVal & ((uint32_t)0x007F0000)) >> 16); +} + +/** + * @brief Returns the current value of the ADCPOWDBV1 field in the AGCADCPOWSTAT register. + * + * The AGCADCPOWSTAT register will be read and the ADCPOWDBV1 field's value will be returned. + * + * @return The current value of the ADCPOWDBV1 field in the AGCADCPOWSTAT register. + */ +__INLINE uint8_t mdm_adcpowdbv1_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_AGCADCPOWSTAT_ADDR); + return ((localVal & ((uint32_t)0x00007F00)) >> 8); +} + +/** + * @brief Returns the current value of the ADCPOWDBV0 field in the AGCADCPOWSTAT register. + * + * The AGCADCPOWSTAT register will be read and the ADCPOWDBV0 field's value will be returned. + * + * @return The current value of the ADCPOWDBV0 field in the AGCADCPOWSTAT register. + */ +__INLINE uint8_t mdm_adcpowdbv0_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_AGCADCPOWSTAT_ADDR); + return ((localVal & ((uint32_t)0x0000007F)) >> 0); +} + +/// @} + +/** + * @name RADARFIFOSTAT register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     00         RADFIFOEMPTY   0
+ * 
+ * + * @{ + */ + +/// Address of the RADARFIFOSTAT register +#define MDM_RADARFIFOSTAT_ADDR 0x01000068 +/// Offset of the RADARFIFOSTAT register from the base address +#define MDM_RADARFIFOSTAT_OFFSET 0x00000068 +/// Index of the RADARFIFOSTAT register +#define MDM_RADARFIFOSTAT_INDEX 0x0000001A +/// Reset value of the RADARFIFOSTAT register +#define MDM_RADARFIFOSTAT_RESET 0x00000000 + +/** + * @brief Returns the current value of the RADARFIFOSTAT register. + * The RADARFIFOSTAT register will be read and its value returned. + * @return The current value of the RADARFIFOSTAT register. + */ +__INLINE uint32_t mdm_radarfifostat_get(void) +{ + return REG_PL_RD(MDM_RADARFIFOSTAT_ADDR); +} + +// field definitions +/// RADFIFOEMPTY field bit +#define MDM_RADFIFOEMPTY_BIT ((uint32_t)0x00000001) +/// RADFIFOEMPTY field position +#define MDM_RADFIFOEMPTY_POS 0 + +/// RADFIFOEMPTY field reset value +#define MDM_RADFIFOEMPTY_RST 0x0 + +/** + * @brief Returns the current value of the RADFIFOEMPTY field in the RADARFIFOSTAT register. + * + * The RADARFIFOSTAT register will be read and the RADFIFOEMPTY field's value will be returned. + * + * @return The current value of the RADFIFOEMPTY field in the RADARFIFOSTAT register. + */ +__INLINE uint8_t mdm_radfifoempty_getf(void) +{ + uint32_t localVal = REG_PL_RD(MDM_RADARFIFOSTAT_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x00000001)) == 0); + return (localVal >> 0); +} + +/// @} + + +#endif // _REG_MDM_STAT_H_ + +/// @} + diff --git a/beken_os/beken378/driver/common/reg/reg_rc.h b/beken_os/beken378/driver/common/reg/reg_rc.h new file mode 100755 index 0000000..0cec191 --- /dev/null +++ b/beken_os/beken378/driver/common/reg/reg_rc.h @@ -0,0 +1,3588 @@ +#ifndef _REG_RC_H_ +#define _REG_RC_H_ + +#include "co_int.h" +#include "_reg_rc.h" +#include "compiler.h" +#include "arch.h" +#include "reg_access.h" + +#define REG_RC_COUNT 107 + +#define REG_RC_DECODING_MASK 0x000001FF + +/** + * @brief CNTL_STAT register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31         FORCE_ENABLE   0
+ *     30            SPI_RESET   0
+ *  18:16             RC_STATE   0x0
+ *     12        CH0_SHDN_STAT   0
+ *     08               CH0_LD   0
+ *     03                RC_EN   0
+ *     00               CH0_EN   0
+ * 
+ */ +#define RC_CNTL_STAT_ADDR 0x01050000 +#define RC_CNTL_STAT_OFFSET 0x00000000 +#define RC_CNTL_STAT_INDEX 0x00000000 +#define RC_CNTL_STAT_RESET 0x00000000 + +__INLINE uint32_t rc_cntl_stat_get(void) +{ + return REG_PL_RD(RC_CNTL_STAT_ADDR); +} + +__INLINE void rc_cntl_stat_set(uint32_t value) +{ + REG_PL_WR(RC_CNTL_STAT_ADDR, value); +} + +// field definitions +#define RC_FORCE_ENABLE_BIT ((uint32_t)0x80000000) +#define RC_FORCE_ENABLE_POS 31 +#define RC_SPI_RESET_BIT ((uint32_t)0x40000000) +#define RC_SPI_RESET_POS 30 +#define RC_RC_STATE_MASK ((uint32_t)0x00070000) +#define RC_RC_STATE_LSB 16 +#define RC_RC_STATE_WIDTH ((uint32_t)0x00000003) +#define RC_CH0_SHDN_STAT_BIT ((uint32_t)0x00001000) +#define RC_CH0_SHDN_STAT_POS 12 +#define RC_CH0_LD_BIT ((uint32_t)0x00000100) +#define RC_CH0_LD_POS 8 +#define RC_RC_EN_BIT ((uint32_t)0x00000008) +#define RC_RC_EN_POS 3 +#define RC_CH0_EN_BIT ((uint32_t)0x00000001) +#define RC_CH0_EN_POS 0 + +#define RC_FORCE_ENABLE_RST 0x0 +#define RC_SPI_RESET_RST 0x0 +#define RC_RC_STATE_RST 0x0 +#define RC_CH0_SHDN_STAT_RST 0x0 +#define RC_CH0_LD_RST 0x0 +#define RC_RC_EN_RST 0x0 +#define RC_CH0_EN_RST 0x0 + +__INLINE void rc_cntl_stat_pack(uint8_t forceenable, uint8_t spireset, uint8_t ch0ld, uint8_t rcen, uint8_t ch0en) +{ + ASSERT_ERR((((uint32_t)forceenable << 31) & ~((uint32_t)0x80000000)) == 0); + ASSERT_ERR((((uint32_t)spireset << 30) & ~((uint32_t)0x40000000)) == 0); + ASSERT_ERR((((uint32_t)ch0ld << 8) & ~((uint32_t)0x00000100)) == 0); + ASSERT_ERR((((uint32_t)rcen << 3) & ~((uint32_t)0x00000008)) == 0); + ASSERT_ERR((((uint32_t)ch0en << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(RC_CNTL_STAT_ADDR, ((uint32_t)forceenable << 31) | ((uint32_t)spireset << 30) | ((uint32_t)ch0ld << 8) | ((uint32_t)rcen << 3) | ((uint32_t)ch0en << 0)); +} + +__INLINE void rc_cntl_stat_unpack(uint8_t *forceenable, uint8_t *spireset, uint8_t *rcstate, uint8_t *ch0shdnstat, uint8_t *ch0ld, uint8_t *rcen, uint8_t *ch0en) +{ + uint32_t localVal = REG_PL_RD(RC_CNTL_STAT_ADDR); + + *forceenable = (localVal & ((uint32_t)0x80000000)) >> 31; + *spireset = (localVal & ((uint32_t)0x40000000)) >> 30; + *rcstate = (localVal & ((uint32_t)0x00070000)) >> 16; + *ch0shdnstat = (localVal & ((uint32_t)0x00001000)) >> 12; + *ch0ld = (localVal & ((uint32_t)0x00000100)) >> 8; + *rcen = (localVal & ((uint32_t)0x00000008)) >> 3; + *ch0en = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +__INLINE uint8_t rc_force_enable_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_CNTL_STAT_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +__INLINE void rc_force_enable_setf(uint8_t forceenable) +{ + ASSERT_ERR((((uint32_t)forceenable << 31) & ~((uint32_t)0x80000000)) == 0); + REG_PL_WR(RC_CNTL_STAT_ADDR, (REG_PL_RD(RC_CNTL_STAT_ADDR) & ~((uint32_t)0x80000000)) | ((uint32_t)forceenable << 31)); +} + +__INLINE uint8_t rc_spi_reset_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_CNTL_STAT_ADDR); + return ((localVal & ((uint32_t)0x40000000)) >> 30); +} + +__INLINE void rc_spi_reset_setf(uint8_t spireset) +{ + ASSERT_ERR((((uint32_t)spireset << 30) & ~((uint32_t)0x40000000)) == 0); + REG_PL_WR(RC_CNTL_STAT_ADDR, (REG_PL_RD(RC_CNTL_STAT_ADDR) & ~((uint32_t)0x40000000)) | ((uint32_t)spireset << 30)); +} + +__INLINE uint8_t rc_rc_state_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_CNTL_STAT_ADDR); + return ((localVal & ((uint32_t)0x00070000)) >> 16); +} + +__INLINE uint8_t rc_ch0_shdn_stat_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_CNTL_STAT_ADDR); + return ((localVal & ((uint32_t)0x00001000)) >> 12); +} + +__INLINE uint8_t rc_ch0_ld_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_CNTL_STAT_ADDR); + return ((localVal & ((uint32_t)0x00000100)) >> 8); +} + +__INLINE void rc_ch0_ld_setf(uint8_t ch0ld) +{ + ASSERT_ERR((((uint32_t)ch0ld << 8) & ~((uint32_t)0x00000100)) == 0); + REG_PL_WR(RC_CNTL_STAT_ADDR, (REG_PL_RD(RC_CNTL_STAT_ADDR) & ~((uint32_t)0x00000100)) | ((uint32_t)ch0ld << 8)); +} + +__INLINE uint8_t rc_rc_en_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_CNTL_STAT_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +__INLINE void rc_rc_en_setf(uint8_t rcen) +{ + ASSERT_ERR((((uint32_t)rcen << 3) & ~((uint32_t)0x00000008)) == 0); + REG_PL_WR(RC_CNTL_STAT_ADDR, (REG_PL_RD(RC_CNTL_STAT_ADDR) & ~((uint32_t)0x00000008)) | ((uint32_t)rcen << 3)); +} + +__INLINE uint8_t rc_ch0_en_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_CNTL_STAT_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +__INLINE void rc_ch0_en_setf(uint8_t ch0en) +{ + ASSERT_ERR((((uint32_t)ch0en << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(RC_CNTL_STAT_ADDR, (REG_PL_RD(RC_CNTL_STAT_ADDR) & ~((uint32_t)0x00000001)) | ((uint32_t)ch0en << 0)); +} + +/** + * @brief BEKEN_SPI register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:28            PRESCALER   0x0
+ *  27:00         TRX_REG_STAT   0x0
+ * 
+ */ +#define RC_BEKEN_SPI_ADDR 0x01050004 +#define RC_BEKEN_SPI_OFFSET 0x00000004 +#define RC_BEKEN_SPI_INDEX 0x00000001 +#define RC_BEKEN_SPI_RESET 0x00000000 + +__INLINE uint32_t rc_beken_spi_get(void) +{ + return REG_PL_RD(RC_BEKEN_SPI_ADDR); +} + +__INLINE void rc_beken_spi_set(uint32_t value) +{ + REG_PL_WR(RC_BEKEN_SPI_ADDR, value); +} + +// field definitions +#define RC_PRESCALER_MASK ((uint32_t)0xF0000000) +#define RC_PRESCALER_LSB 28 +#define RC_PRESCALER_WIDTH ((uint32_t)0x00000004) +#define RC_TRX_REG_STAT_MASK ((uint32_t)0x0FFFFFFF) +#define RC_TRX_REG_STAT_LSB 0 +#define RC_TRX_REG_STAT_WIDTH ((uint32_t)0x0000001C) + +#define RC_PRESCALER_RST 0x0 +#define RC_TRX_REG_STAT_RST 0x0 + +__INLINE void rc_beken_spi_unpack(uint8_t *prescaler, uint32_t *trxregstat) +{ + uint32_t localVal = REG_PL_RD(RC_BEKEN_SPI_ADDR); + + *prescaler = (localVal & ((uint32_t)0xF0000000)) >> 28; + *trxregstat = (localVal & ((uint32_t)0x0FFFFFFF)) >> 0; +} + +__INLINE uint8_t rc_prescaler_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_BEKEN_SPI_ADDR); + return ((localVal & ((uint32_t)0xF0000000)) >> 28); +} + +__INLINE void rc_prescaler_setf(uint8_t prescaler) +{ + ASSERT_ERR((((uint32_t)prescaler << 28) & ~((uint32_t)0xF0000000)) == 0); + REG_PL_WR(RC_BEKEN_SPI_ADDR, (uint32_t)prescaler << 28); +} + +__INLINE uint32_t rc_trx_reg_stat_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_BEKEN_SPI_ADDR); + return ((localVal & ((uint32_t)0x0FFFFFFF)) >> 0); +} + +/** + * @brief CH0_OUTPOWER register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  07:00         CH0_OUTPOWER   0x0
+ * 
+ */ +#define RC_CH0_OUTPOWER_ADDR 0x01050014 +#define RC_CH0_OUTPOWER_OFFSET 0x00000014 +#define RC_CH0_OUTPOWER_INDEX 0x00000005 +#define RC_CH0_OUTPOWER_RESET 0x00000000 + +__INLINE uint32_t rc_ch0_outpower_get(void) +{ + return REG_PL_RD(RC_CH0_OUTPOWER_ADDR); +} + +__INLINE void rc_ch0_outpower_set(uint32_t value) +{ + REG_PL_WR(RC_CH0_OUTPOWER_ADDR, value); +} + +// field definitions +#define RC_CH0_OUTPOWER_MASK ((uint32_t)0x000000FF) +#define RC_CH0_OUTPOWER_LSB 0 +#define RC_CH0_OUTPOWER_WIDTH ((uint32_t)0x00000008) + +#define RC_CH0_OUTPOWER_RST 0x0 + +__INLINE uint8_t rc_ch0_outpower_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_CH0_OUTPOWER_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x000000FF)) == 0); + return (localVal >> 0); +} + +/** + * @brief CH0_RX_ONOFF_DELAY register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  23:16     CH0_RX_OFF_DELAY   0x0
+ *  07:00      CH0_RX_ON_DELAY   0x0
+ * 
+ */ +#define RC_CH0_RX_ONOFF_DELAY_ADDR 0x01050020 +#define RC_CH0_RX_ONOFF_DELAY_OFFSET 0x00000020 +#define RC_CH0_RX_ONOFF_DELAY_INDEX 0x00000008 +#define RC_CH0_RX_ONOFF_DELAY_RESET 0x00000000 + +__INLINE uint32_t rc_ch0_rx_onoff_delay_get(void) +{ + return REG_PL_RD(RC_CH0_RX_ONOFF_DELAY_ADDR); +} + +__INLINE void rc_ch0_rx_onoff_delay_set(uint32_t value) +{ + REG_PL_WR(RC_CH0_RX_ONOFF_DELAY_ADDR, value); +} + +// field definitions +#define RC_CH0_RX_OFF_DELAY_MASK ((uint32_t)0x00FF0000) +#define RC_CH0_RX_OFF_DELAY_LSB 16 +#define RC_CH0_RX_OFF_DELAY_WIDTH ((uint32_t)0x00000008) +#define RC_CH0_RX_ON_DELAY_MASK ((uint32_t)0x000000FF) +#define RC_CH0_RX_ON_DELAY_LSB 0 +#define RC_CH0_RX_ON_DELAY_WIDTH ((uint32_t)0x00000008) + +#define RC_CH0_RX_OFF_DELAY_RST 0x0 +#define RC_CH0_RX_ON_DELAY_RST 0x0 + +__INLINE void rc_ch0_rx_onoff_delay_pack(uint8_t ch0rxoffdelay, uint8_t ch0rxondelay) +{ + ASSERT_ERR((((uint32_t)ch0rxoffdelay << 16) & ~((uint32_t)0x00FF0000)) == 0); + ASSERT_ERR((((uint32_t)ch0rxondelay << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(RC_CH0_RX_ONOFF_DELAY_ADDR, ((uint32_t)ch0rxoffdelay << 16) | ((uint32_t)ch0rxondelay << 0)); +} + +__INLINE void rc_ch0_rx_onoff_delay_unpack(uint8_t *ch0rxoffdelay, uint8_t *ch0rxondelay) +{ + uint32_t localVal = REG_PL_RD(RC_CH0_RX_ONOFF_DELAY_ADDR); + + *ch0rxoffdelay = (localVal & ((uint32_t)0x00FF0000)) >> 16; + *ch0rxondelay = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +__INLINE uint8_t rc_ch0_rx_off_delay_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_CH0_RX_ONOFF_DELAY_ADDR); + return ((localVal & ((uint32_t)0x00FF0000)) >> 16); +} + +__INLINE void rc_ch0_rx_off_delay_setf(uint8_t ch0rxoffdelay) +{ + ASSERT_ERR((((uint32_t)ch0rxoffdelay << 16) & ~((uint32_t)0x00FF0000)) == 0); + REG_PL_WR(RC_CH0_RX_ONOFF_DELAY_ADDR, (REG_PL_RD(RC_CH0_RX_ONOFF_DELAY_ADDR) & ~((uint32_t)0x00FF0000)) | ((uint32_t)ch0rxoffdelay << 16)); +} + +__INLINE uint8_t rc_ch0_rx_on_delay_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_CH0_RX_ONOFF_DELAY_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +__INLINE void rc_ch0_rx_on_delay_setf(uint8_t ch0rxondelay) +{ + ASSERT_ERR((((uint32_t)ch0rxondelay << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(RC_CH0_RX_ONOFF_DELAY_ADDR, (REG_PL_RD(RC_CH0_RX_ONOFF_DELAY_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)ch0rxondelay << 0)); +} + +/** + * @brief CH0_TX_ONOFF_DELAY register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  23:16     CH0_TX_OFF_DELAY   0x0
+ *  07:00      CH0_TX_ON_DELAY   0x0
+ * 
+ */ +#define RC_CH0_TX_ONOFF_DELAY_ADDR 0x0105002C +#define RC_CH0_TX_ONOFF_DELAY_OFFSET 0x0000002C +#define RC_CH0_TX_ONOFF_DELAY_INDEX 0x0000000B +#define RC_CH0_TX_ONOFF_DELAY_RESET 0x00000000 + +__INLINE uint32_t rc_ch0_tx_onoff_delay_get(void) +{ + return REG_PL_RD(RC_CH0_TX_ONOFF_DELAY_ADDR); +} + +__INLINE void rc_ch0_tx_onoff_delay_set(uint32_t value) +{ + REG_PL_WR(RC_CH0_TX_ONOFF_DELAY_ADDR, value); +} + +// field definitions +#define RC_CH0_TX_OFF_DELAY_MASK ((uint32_t)0x00FF0000) +#define RC_CH0_TX_OFF_DELAY_LSB 16 +#define RC_CH0_TX_OFF_DELAY_WIDTH ((uint32_t)0x00000008) +#define RC_CH0_TX_ON_DELAY_MASK ((uint32_t)0x000000FF) +#define RC_CH0_TX_ON_DELAY_LSB 0 +#define RC_CH0_TX_ON_DELAY_WIDTH ((uint32_t)0x00000008) + +#define RC_CH0_TX_OFF_DELAY_RST 0x0 +#define RC_CH0_TX_ON_DELAY_RST 0x0 + +__INLINE void rc_ch0_tx_onoff_delay_pack(uint8_t ch0txoffdelay, uint8_t ch0txondelay) +{ + ASSERT_ERR((((uint32_t)ch0txoffdelay << 16) & ~((uint32_t)0x00FF0000)) == 0); + ASSERT_ERR((((uint32_t)ch0txondelay << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(RC_CH0_TX_ONOFF_DELAY_ADDR, ((uint32_t)ch0txoffdelay << 16) | ((uint32_t)ch0txondelay << 0)); +} + +__INLINE void rc_ch0_tx_onoff_delay_unpack(uint8_t *ch0txoffdelay, uint8_t *ch0txondelay) +{ + uint32_t localVal = REG_PL_RD(RC_CH0_TX_ONOFF_DELAY_ADDR); + + *ch0txoffdelay = (localVal & ((uint32_t)0x00FF0000)) >> 16; + *ch0txondelay = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +__INLINE uint8_t rc_ch0_tx_off_delay_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_CH0_TX_ONOFF_DELAY_ADDR); + return ((localVal & ((uint32_t)0x00FF0000)) >> 16); +} + +__INLINE void rc_ch0_tx_off_delay_setf(uint8_t ch0txoffdelay) +{ + ASSERT_ERR((((uint32_t)ch0txoffdelay << 16) & ~((uint32_t)0x00FF0000)) == 0); + REG_PL_WR(RC_CH0_TX_ONOFF_DELAY_ADDR, (REG_PL_RD(RC_CH0_TX_ONOFF_DELAY_ADDR) & ~((uint32_t)0x00FF0000)) | ((uint32_t)ch0txoffdelay << 16)); +} + +__INLINE uint8_t rc_ch0_tx_on_delay_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_CH0_TX_ONOFF_DELAY_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +__INLINE void rc_ch0_tx_on_delay_setf(uint8_t ch0txondelay) +{ + ASSERT_ERR((((uint32_t)ch0txondelay << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(RC_CH0_TX_ONOFF_DELAY_ADDR, (REG_PL_RD(RC_CH0_TX_ONOFF_DELAY_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)ch0txondelay << 0)); +} + +/** + * @brief CH0_PA_ONOFF_DELAY register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  23:16     CH0_PA_OFF_DELAY   0x0
+ *  07:00      CH0_PA_ON_DELAY   0x0
+ * 
+ */ +#define RC_CH0_PA_ONOFF_DELAY_ADDR 0x01050038 +#define RC_CH0_PA_ONOFF_DELAY_OFFSET 0x00000038 +#define RC_CH0_PA_ONOFF_DELAY_INDEX 0x0000000E +#define RC_CH0_PA_ONOFF_DELAY_RESET 0x00000000 + +__INLINE uint32_t rc_ch0_pa_onoff_delay_get(void) +{ + return REG_PL_RD(RC_CH0_PA_ONOFF_DELAY_ADDR); +} + +__INLINE void rc_ch0_pa_onoff_delay_set(uint32_t value) +{ + REG_PL_WR(RC_CH0_PA_ONOFF_DELAY_ADDR, value); +} + +// field definitions +#define RC_CH0_PA_OFF_DELAY_MASK ((uint32_t)0x00FF0000) +#define RC_CH0_PA_OFF_DELAY_LSB 16 +#define RC_CH0_PA_OFF_DELAY_WIDTH ((uint32_t)0x00000008) +#define RC_CH0_PA_ON_DELAY_MASK ((uint32_t)0x000000FF) +#define RC_CH0_PA_ON_DELAY_LSB 0 +#define RC_CH0_PA_ON_DELAY_WIDTH ((uint32_t)0x00000008) + +#define RC_CH0_PA_OFF_DELAY_RST 0x0 +#define RC_CH0_PA_ON_DELAY_RST 0x0 + +__INLINE void rc_ch0_pa_onoff_delay_pack(uint8_t ch0paoffdelay, uint8_t ch0paondelay) +{ + ASSERT_ERR((((uint32_t)ch0paoffdelay << 16) & ~((uint32_t)0x00FF0000)) == 0); + ASSERT_ERR((((uint32_t)ch0paondelay << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(RC_CH0_PA_ONOFF_DELAY_ADDR, ((uint32_t)ch0paoffdelay << 16) | ((uint32_t)ch0paondelay << 0)); +} + +__INLINE void rc_ch0_pa_onoff_delay_unpack(uint8_t *ch0paoffdelay, uint8_t *ch0paondelay) +{ + uint32_t localVal = REG_PL_RD(RC_CH0_PA_ONOFF_DELAY_ADDR); + + *ch0paoffdelay = (localVal & ((uint32_t)0x00FF0000)) >> 16; + *ch0paondelay = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +__INLINE uint8_t rc_ch0_pa_off_delay_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_CH0_PA_ONOFF_DELAY_ADDR); + return ((localVal & ((uint32_t)0x00FF0000)) >> 16); +} + +__INLINE void rc_ch0_pa_off_delay_setf(uint8_t ch0paoffdelay) +{ + ASSERT_ERR((((uint32_t)ch0paoffdelay << 16) & ~((uint32_t)0x00FF0000)) == 0); + REG_PL_WR(RC_CH0_PA_ONOFF_DELAY_ADDR, (REG_PL_RD(RC_CH0_PA_ONOFF_DELAY_ADDR) & ~((uint32_t)0x00FF0000)) | ((uint32_t)ch0paoffdelay << 16)); +} + +__INLINE uint8_t rc_ch0_pa_on_delay_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_CH0_PA_ONOFF_DELAY_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +__INLINE void rc_ch0_pa_on_delay_setf(uint8_t ch0paondelay) +{ + ASSERT_ERR((((uint32_t)ch0paondelay << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(RC_CH0_PA_ONOFF_DELAY_ADDR, (REG_PL_RD(RC_CH0_PA_ONOFF_DELAY_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)ch0paondelay << 0)); +} + +/** + * @brief CH0_SHDN_ONOFF_DELAY register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  23:16   CH0_SHDN_OFF_DELAY   0x0
+ *  07:00    CH0_SHDN_ON_DELAY   0x0
+ * 
+ */ +#define RC_CH0_SHDN_ONOFF_DELAY_ADDR 0x01050044 +#define RC_CH0_SHDN_ONOFF_DELAY_OFFSET 0x00000044 +#define RC_CH0_SHDN_ONOFF_DELAY_INDEX 0x00000011 +#define RC_CH0_SHDN_ONOFF_DELAY_RESET 0x00000000 + +__INLINE uint32_t rc_ch0_shdn_onoff_delay_get(void) +{ + return REG_PL_RD(RC_CH0_SHDN_ONOFF_DELAY_ADDR); +} + +__INLINE void rc_ch0_shdn_onoff_delay_set(uint32_t value) +{ + REG_PL_WR(RC_CH0_SHDN_ONOFF_DELAY_ADDR, value); +} + +// field definitions +#define RC_CH0_SHDN_OFF_DELAY_MASK ((uint32_t)0x00FF0000) +#define RC_CH0_SHDN_OFF_DELAY_LSB 16 +#define RC_CH0_SHDN_OFF_DELAY_WIDTH ((uint32_t)0x00000008) +#define RC_CH0_SHDN_ON_DELAY_MASK ((uint32_t)0x000000FF) +#define RC_CH0_SHDN_ON_DELAY_LSB 0 +#define RC_CH0_SHDN_ON_DELAY_WIDTH ((uint32_t)0x00000008) + +#define RC_CH0_SHDN_OFF_DELAY_RST 0x0 +#define RC_CH0_SHDN_ON_DELAY_RST 0x0 + +__INLINE void rc_ch0_shdn_onoff_delay_pack(uint8_t ch0shdnoffdelay, uint8_t ch0shdnondelay) +{ + ASSERT_ERR((((uint32_t)ch0shdnoffdelay << 16) & ~((uint32_t)0x00FF0000)) == 0); + ASSERT_ERR((((uint32_t)ch0shdnondelay << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(RC_CH0_SHDN_ONOFF_DELAY_ADDR, ((uint32_t)ch0shdnoffdelay << 16) | ((uint32_t)ch0shdnondelay << 0)); +} + +__INLINE void rc_ch0_shdn_onoff_delay_unpack(uint8_t *ch0shdnoffdelay, uint8_t *ch0shdnondelay) +{ + uint32_t localVal = REG_PL_RD(RC_CH0_SHDN_ONOFF_DELAY_ADDR); + + *ch0shdnoffdelay = (localVal & ((uint32_t)0x00FF0000)) >> 16; + *ch0shdnondelay = (localVal & ((uint32_t)0x000000FF)) >> 0; +} + +__INLINE uint8_t rc_ch0_shdn_off_delay_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_CH0_SHDN_ONOFF_DELAY_ADDR); + return ((localVal & ((uint32_t)0x00FF0000)) >> 16); +} + +__INLINE void rc_ch0_shdn_off_delay_setf(uint8_t ch0shdnoffdelay) +{ + ASSERT_ERR((((uint32_t)ch0shdnoffdelay << 16) & ~((uint32_t)0x00FF0000)) == 0); + REG_PL_WR(RC_CH0_SHDN_ONOFF_DELAY_ADDR, (REG_PL_RD(RC_CH0_SHDN_ONOFF_DELAY_ADDR) & ~((uint32_t)0x00FF0000)) | ((uint32_t)ch0shdnoffdelay << 16)); +} + +__INLINE uint8_t rc_ch0_shdn_on_delay_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_CH0_SHDN_ONOFF_DELAY_ADDR); + return ((localVal & ((uint32_t)0x000000FF)) >> 0); +} + +__INLINE void rc_ch0_shdn_on_delay_setf(uint8_t ch0shdnondelay) +{ + ASSERT_ERR((((uint32_t)ch0shdnondelay << 0) & ~((uint32_t)0x000000FF)) == 0); + REG_PL_WR(RC_CH0_SHDN_ONOFF_DELAY_ADDR, (REG_PL_RD(RC_CH0_SHDN_ONOFF_DELAY_ADDR) & ~((uint32_t)0x000000FF)) | ((uint32_t)ch0shdnondelay << 0)); +} + +/** + * @brief CH0_FORCE register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     16             F_CH0_EN   0
+ *  15:08              F_CH0_B   0x0
+ *     03           F_CH0_RXHP   0
+ *     02           F_CH0_TXEN   0
+ *     01           F_CH0_RXEN   0
+ *     00           F_CH0_SHDN   0
+ * 
+ */ +#define RC_CH0_FORCE_ADDR 0x01050064 +#define RC_CH0_FORCE_OFFSET 0x00000064 +#define RC_CH0_FORCE_INDEX 0x00000019 +#define RC_CH0_FORCE_RESET 0x00000000 + +__INLINE uint32_t rc_ch0_force_get(void) +{ + return REG_PL_RD(RC_CH0_FORCE_ADDR); +} + +__INLINE void rc_ch0_force_set(uint32_t value) +{ + REG_PL_WR(RC_CH0_FORCE_ADDR, value); +} + +// field definitions +#define RC_F_CH0_EN_BIT ((uint32_t)0x00010000) +#define RC_F_CH0_EN_POS 16 +#define RC_F_CH0_B_MASK ((uint32_t)0x0000FF00) +#define RC_F_CH0_B_LSB 8 +#define RC_F_CH0_B_WIDTH ((uint32_t)0x00000008) +#define RC_F_CH0_RXHP_BIT ((uint32_t)0x00000008) +#define RC_F_CH0_RXHP_POS 3 +#define RC_F_CH0_TXEN_BIT ((uint32_t)0x00000004) +#define RC_F_CH0_TXEN_POS 2 +#define RC_F_CH0_RXEN_BIT ((uint32_t)0x00000002) +#define RC_F_CH0_RXEN_POS 1 +#define RC_F_CH0_SHDN_BIT ((uint32_t)0x00000001) +#define RC_F_CH0_SHDN_POS 0 + +#define RC_F_CH0_EN_RST 0x0 +#define RC_F_CH0_B_RST 0x0 +#define RC_F_CH0_RXHP_RST 0x0 +#define RC_F_CH0_TXEN_RST 0x0 +#define RC_F_CH0_RXEN_RST 0x0 +#define RC_F_CH0_SHDN_RST 0x0 + +__INLINE void rc_ch0_force_pack(uint8_t fch0en, uint8_t fch0b, uint8_t fch0rxhp, uint8_t fch0txen, uint8_t fch0rxen, uint8_t fch0shdn) +{ + ASSERT_ERR((((uint32_t)fch0en << 16) & ~((uint32_t)0x00010000)) == 0); + ASSERT_ERR((((uint32_t)fch0b << 8) & ~((uint32_t)0x0000FF00)) == 0); + ASSERT_ERR((((uint32_t)fch0rxhp << 3) & ~((uint32_t)0x00000008)) == 0); + ASSERT_ERR((((uint32_t)fch0txen << 2) & ~((uint32_t)0x00000004)) == 0); + ASSERT_ERR((((uint32_t)fch0rxen << 1) & ~((uint32_t)0x00000002)) == 0); + ASSERT_ERR((((uint32_t)fch0shdn << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(RC_CH0_FORCE_ADDR, ((uint32_t)fch0en << 16) | ((uint32_t)fch0b << 8) | ((uint32_t)fch0rxhp << 3) | ((uint32_t)fch0txen << 2) | ((uint32_t)fch0rxen << 1) | ((uint32_t)fch0shdn << 0)); +} + +__INLINE void rc_ch0_force_unpack(uint8_t *fch0en, uint8_t *fch0b, uint8_t *fch0rxhp, uint8_t *fch0txen, uint8_t *fch0rxen, uint8_t *fch0shdn) +{ + uint32_t localVal = REG_PL_RD(RC_CH0_FORCE_ADDR); + + *fch0en = (localVal & ((uint32_t)0x00010000)) >> 16; + *fch0b = (localVal & ((uint32_t)0x0000FF00)) >> 8; + *fch0rxhp = (localVal & ((uint32_t)0x00000008)) >> 3; + *fch0txen = (localVal & ((uint32_t)0x00000004)) >> 2; + *fch0rxen = (localVal & ((uint32_t)0x00000002)) >> 1; + *fch0shdn = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +__INLINE uint8_t rc_f_ch0_en_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_CH0_FORCE_ADDR); + return ((localVal & ((uint32_t)0x00010000)) >> 16); +} + +__INLINE void rc_f_ch0_en_setf(uint8_t fch0en) +{ + ASSERT_ERR((((uint32_t)fch0en << 16) & ~((uint32_t)0x00010000)) == 0); + REG_PL_WR(RC_CH0_FORCE_ADDR, (REG_PL_RD(RC_CH0_FORCE_ADDR) & ~((uint32_t)0x00010000)) | ((uint32_t)fch0en << 16)); +} + +__INLINE uint8_t rc_f_ch0_b_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_CH0_FORCE_ADDR); + return ((localVal & ((uint32_t)0x0000FF00)) >> 8); +} + +__INLINE void rc_f_ch0_b_setf(uint8_t fch0b) +{ + ASSERT_ERR((((uint32_t)fch0b << 8) & ~((uint32_t)0x0000FF00)) == 0); + REG_PL_WR(RC_CH0_FORCE_ADDR, (REG_PL_RD(RC_CH0_FORCE_ADDR) & ~((uint32_t)0x0000FF00)) | ((uint32_t)fch0b << 8)); +} + +__INLINE uint8_t rc_f_ch0_rxhp_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_CH0_FORCE_ADDR); + return ((localVal & ((uint32_t)0x00000008)) >> 3); +} + +__INLINE void rc_f_ch0_rxhp_setf(uint8_t fch0rxhp) +{ + ASSERT_ERR((((uint32_t)fch0rxhp << 3) & ~((uint32_t)0x00000008)) == 0); + REG_PL_WR(RC_CH0_FORCE_ADDR, (REG_PL_RD(RC_CH0_FORCE_ADDR) & ~((uint32_t)0x00000008)) | ((uint32_t)fch0rxhp << 3)); +} + +__INLINE uint8_t rc_f_ch0_txen_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_CH0_FORCE_ADDR); + return ((localVal & ((uint32_t)0x00000004)) >> 2); +} + +__INLINE void rc_f_ch0_txen_setf(uint8_t fch0txen) +{ + ASSERT_ERR((((uint32_t)fch0txen << 2) & ~((uint32_t)0x00000004)) == 0); + REG_PL_WR(RC_CH0_FORCE_ADDR, (REG_PL_RD(RC_CH0_FORCE_ADDR) & ~((uint32_t)0x00000004)) | ((uint32_t)fch0txen << 2)); +} + +__INLINE uint8_t rc_f_ch0_rxen_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_CH0_FORCE_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +__INLINE void rc_f_ch0_rxen_setf(uint8_t fch0rxen) +{ + ASSERT_ERR((((uint32_t)fch0rxen << 1) & ~((uint32_t)0x00000002)) == 0); + REG_PL_WR(RC_CH0_FORCE_ADDR, (REG_PL_RD(RC_CH0_FORCE_ADDR) & ~((uint32_t)0x00000002)) | ((uint32_t)fch0rxen << 1)); +} + +__INLINE uint8_t rc_f_ch0_shdn_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_CH0_FORCE_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +__INLINE void rc_f_ch0_shdn_setf(uint8_t fch0shdn) +{ + ASSERT_ERR((((uint32_t)fch0shdn << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(RC_CH0_FORCE_ADDR, (REG_PL_RD(RC_CH0_FORCE_ADDR) & ~((uint32_t)0x00000001)) | ((uint32_t)fch0shdn << 0)); +} + +/** + * @brief MISC_FORCE register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     01              F_TX_ON   0
+ *     00              F_RX_ON   0
+ * 
+ */ +#define RC_MISC_FORCE_ADDR 0x01050070 +#define RC_MISC_FORCE_OFFSET 0x00000070 +#define RC_MISC_FORCE_INDEX 0x0000001C +#define RC_MISC_FORCE_RESET 0x00000000 + +__INLINE uint32_t rc_misc_force_get(void) +{ + return REG_PL_RD(RC_MISC_FORCE_ADDR); +} + +__INLINE void rc_misc_force_set(uint32_t value) +{ + REG_PL_WR(RC_MISC_FORCE_ADDR, value); +} + +// field definitions +#define RC_F_TX_ON_BIT ((uint32_t)0x00000002) +#define RC_F_TX_ON_POS 1 +#define RC_F_RX_ON_BIT ((uint32_t)0x00000001) +#define RC_F_RX_ON_POS 0 + +#define RC_F_TX_ON_RST 0x0 +#define RC_F_RX_ON_RST 0x0 + +__INLINE void rc_misc_force_pack(uint8_t ftxon, uint8_t frxon) +{ + ASSERT_ERR((((uint32_t)ftxon << 1) & ~((uint32_t)0x00000002)) == 0); + ASSERT_ERR((((uint32_t)frxon << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(RC_MISC_FORCE_ADDR, ((uint32_t)ftxon << 1) | ((uint32_t)frxon << 0)); +} + +__INLINE void rc_misc_force_unpack(uint8_t *ftxon, uint8_t *frxon) +{ + uint32_t localVal = REG_PL_RD(RC_MISC_FORCE_ADDR); + + *ftxon = (localVal & ((uint32_t)0x00000002)) >> 1; + *frxon = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +__INLINE uint8_t rc_f_tx_on_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_MISC_FORCE_ADDR); + return ((localVal & ((uint32_t)0x00000002)) >> 1); +} + +__INLINE void rc_f_tx_on_setf(uint8_t ftxon) +{ + ASSERT_ERR((((uint32_t)ftxon << 1) & ~((uint32_t)0x00000002)) == 0); + REG_PL_WR(RC_MISC_FORCE_ADDR, (REG_PL_RD(RC_MISC_FORCE_ADDR) & ~((uint32_t)0x00000002)) | ((uint32_t)ftxon << 1)); +} + +__INLINE uint8_t rc_f_rx_on_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_MISC_FORCE_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +__INLINE void rc_f_rx_on_setf(uint8_t frxon) +{ + ASSERT_ERR((((uint32_t)frxon << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(RC_MISC_FORCE_ADDR, (REG_PL_RD(RC_MISC_FORCE_ADDR) & ~((uint32_t)0x00000001)) | ((uint32_t)frxon << 0)); +} + +/** + * @brief FE_RX_DEL register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  11:00         FE_RX_ON_DEL   0x0
+ * 
+ */ +#define RC_FE_RX_DEL_ADDR 0x01050078 +#define RC_FE_RX_DEL_OFFSET 0x00000078 +#define RC_FE_RX_DEL_INDEX 0x0000001E +#define RC_FE_RX_DEL_RESET 0x00000000 + +__INLINE uint32_t rc_fe_rx_del_get(void) +{ + return REG_PL_RD(RC_FE_RX_DEL_ADDR); +} + +__INLINE void rc_fe_rx_del_set(uint32_t value) +{ + REG_PL_WR(RC_FE_RX_DEL_ADDR, value); +} + +// field definitions +#define RC_FE_RX_ON_DEL_MASK ((uint32_t)0x00000FFF) +#define RC_FE_RX_ON_DEL_LSB 0 +#define RC_FE_RX_ON_DEL_WIDTH ((uint32_t)0x0000000C) + +#define RC_FE_RX_ON_DEL_RST 0x0 + +__INLINE uint16_t rc_fe_rx_on_del_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_FE_RX_DEL_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x00000FFF)) == 0); + return (localVal >> 0); +} + +__INLINE void rc_fe_rx_on_del_setf(uint16_t ferxondel) +{ + ASSERT_ERR((((uint32_t)ferxondel << 0) & ~((uint32_t)0x00000FFF)) == 0); + REG_PL_WR(RC_FE_RX_DEL_ADDR, (uint32_t)ferxondel << 0); +} + +/** + * @brief TRX_REG0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00             TRX_REG0   0x0
+ * 
+ */ +#define RC_TRX_REG0_ADDR 0x01050080 +#define RC_TRX_REG0_OFFSET 0x00000080 +#define RC_TRX_REG0_INDEX 0x00000020 +#define RC_TRX_REG0_RESET 0x00000000 + +__INLINE uint32_t rc_trx_reg0_get(void) +{ + return REG_PL_RD(RC_TRX_REG0_ADDR); +} + +__INLINE void rc_trx_reg0_set(uint32_t value) +{ + REG_PL_WR(RC_TRX_REG0_ADDR, value); +} + +// field definitions +#define RC_TRX_REG0_MASK ((uint32_t)0xFFFFFFFF) +#define RC_TRX_REG0_LSB 0 +#define RC_TRX_REG0_WIDTH ((uint32_t)0x00000020) + +#define RC_TRX_REG0_RST 0x0 + +__INLINE uint32_t rc_trx_reg0_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_TRX_REG0_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void rc_trx_reg0_setf(uint32_t trxreg0) +{ + ASSERT_ERR((((uint32_t)trxreg0 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(RC_TRX_REG0_ADDR, (uint32_t)trxreg0 << 0); +} + +/** + * @brief TRX_REG1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00             TRX_REG1   0x0
+ * 
+ */ +#define RC_TRX_REG1_ADDR 0x01050084 +#define RC_TRX_REG1_OFFSET 0x00000084 +#define RC_TRX_REG1_INDEX 0x00000021 +#define RC_TRX_REG1_RESET 0x00000000 + +__INLINE uint32_t rc_trx_reg1_get(void) +{ + return REG_PL_RD(RC_TRX_REG1_ADDR); +} + +__INLINE void rc_trx_reg1_set(uint32_t value) +{ + REG_PL_WR(RC_TRX_REG1_ADDR, value); +} + +// field definitions +#define RC_TRX_REG1_MASK ((uint32_t)0xFFFFFFFF) +#define RC_TRX_REG1_LSB 0 +#define RC_TRX_REG1_WIDTH ((uint32_t)0x00000020) + +#define RC_TRX_REG1_RST 0x0 + +__INLINE uint32_t rc_trx_reg1_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_TRX_REG1_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void rc_trx_reg1_setf(uint32_t trxreg1) +{ + ASSERT_ERR((((uint32_t)trxreg1 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(RC_TRX_REG1_ADDR, (uint32_t)trxreg1 << 0); +} + +/** + * @brief TRX_REG2 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00             TRX_REG2   0x0
+ * 
+ */ +#define RC_TRX_REG2_ADDR 0x01050088 +#define RC_TRX_REG2_OFFSET 0x00000088 +#define RC_TRX_REG2_INDEX 0x00000022 +#define RC_TRX_REG2_RESET 0x00000000 + +__INLINE uint32_t rc_trx_reg2_get(void) +{ + return REG_PL_RD(RC_TRX_REG2_ADDR); +} + +__INLINE void rc_trx_reg2_set(uint32_t value) +{ + REG_PL_WR(RC_TRX_REG2_ADDR, value); +} + +// field definitions +#define RC_TRX_REG2_MASK ((uint32_t)0xFFFFFFFF) +#define RC_TRX_REG2_LSB 0 +#define RC_TRX_REG2_WIDTH ((uint32_t)0x00000020) + +#define RC_TRX_REG2_RST 0x0 + +__INLINE uint32_t rc_trx_reg2_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_TRX_REG2_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void rc_trx_reg2_setf(uint32_t trxreg2) +{ + ASSERT_ERR((((uint32_t)trxreg2 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(RC_TRX_REG2_ADDR, (uint32_t)trxreg2 << 0); +} + +/** + * @brief TRX_REG3 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00             TRX_REG3   0x0
+ * 
+ */ +#define RC_TRX_REG3_ADDR 0x0105008C +#define RC_TRX_REG3_OFFSET 0x0000008C +#define RC_TRX_REG3_INDEX 0x00000023 +#define RC_TRX_REG3_RESET 0x00000000 + +__INLINE uint32_t rc_trx_reg3_get(void) +{ + return REG_PL_RD(RC_TRX_REG3_ADDR); +} + +__INLINE void rc_trx_reg3_set(uint32_t value) +{ + REG_PL_WR(RC_TRX_REG3_ADDR, value); +} + +// field definitions +#define RC_TRX_REG3_MASK ((uint32_t)0xFFFFFFFF) +#define RC_TRX_REG3_LSB 0 +#define RC_TRX_REG3_WIDTH ((uint32_t)0x00000020) + +#define RC_TRX_REG3_RST 0x0 + +__INLINE uint32_t rc_trx_reg3_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_TRX_REG3_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void rc_trx_reg3_setf(uint32_t trxreg3) +{ + ASSERT_ERR((((uint32_t)trxreg3 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(RC_TRX_REG3_ADDR, (uint32_t)trxreg3 << 0); +} + +/** + * @brief TRX_REG4 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00             TRX_REG4   0x0
+ * 
+ */ +#define RC_TRX_REG4_ADDR 0x01050090 +#define RC_TRX_REG4_OFFSET 0x00000090 +#define RC_TRX_REG4_INDEX 0x00000024 +#define RC_TRX_REG4_RESET 0x00000000 + +__INLINE uint32_t rc_trx_reg4_get(void) +{ + return REG_PL_RD(RC_TRX_REG4_ADDR); +} + +__INLINE void rc_trx_reg4_set(uint32_t value) +{ + REG_PL_WR(RC_TRX_REG4_ADDR, value); +} + +// field definitions +#define RC_TRX_REG4_MASK ((uint32_t)0xFFFFFFFF) +#define RC_TRX_REG4_LSB 0 +#define RC_TRX_REG4_WIDTH ((uint32_t)0x00000020) + +#define RC_TRX_REG4_RST 0x0 + +__INLINE uint32_t rc_trx_reg4_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_TRX_REG4_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void rc_trx_reg4_setf(uint32_t trxreg4) +{ + ASSERT_ERR((((uint32_t)trxreg4 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(RC_TRX_REG4_ADDR, (uint32_t)trxreg4 << 0); +} + +/** + * @brief TRX_REG5 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00             TRX_REG5   0x0
+ * 
+ */ +#define RC_TRX_REG5_ADDR 0x01050094 +#define RC_TRX_REG5_OFFSET 0x00000094 +#define RC_TRX_REG5_INDEX 0x00000025 +#define RC_TRX_REG5_RESET 0x00000000 + +__INLINE uint32_t rc_trx_reg5_get(void) +{ + return REG_PL_RD(RC_TRX_REG5_ADDR); +} + +__INLINE void rc_trx_reg5_set(uint32_t value) +{ + REG_PL_WR(RC_TRX_REG5_ADDR, value); +} + +// field definitions +#define RC_TRX_REG5_MASK ((uint32_t)0xFFFFFFFF) +#define RC_TRX_REG5_LSB 0 +#define RC_TRX_REG5_WIDTH ((uint32_t)0x00000020) + +#define RC_TRX_REG5_RST 0x0 + +__INLINE uint32_t rc_trx_reg5_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_TRX_REG5_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void rc_trx_reg5_setf(uint32_t trxreg5) +{ + ASSERT_ERR((((uint32_t)trxreg5 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(RC_TRX_REG5_ADDR, (uint32_t)trxreg5 << 0); +} + +/** + * @brief TRX_REG6 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00             TRX_REG6   0x0
+ * 
+ */ +#define RC_TRX_REG6_ADDR 0x01050098 +#define RC_TRX_REG6_OFFSET 0x00000098 +#define RC_TRX_REG6_INDEX 0x00000026 +#define RC_TRX_REG6_RESET 0x00000000 + +__INLINE uint32_t rc_trx_reg6_get(void) +{ + return REG_PL_RD(RC_TRX_REG6_ADDR); +} + +__INLINE void rc_trx_reg6_set(uint32_t value) +{ + REG_PL_WR(RC_TRX_REG6_ADDR, value); +} + +// field definitions +#define RC_TRX_REG6_MASK ((uint32_t)0xFFFFFFFF) +#define RC_TRX_REG6_LSB 0 +#define RC_TRX_REG6_WIDTH ((uint32_t)0x00000020) + +#define RC_TRX_REG6_RST 0x0 + +__INLINE uint32_t rc_trx_reg6_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_TRX_REG6_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void rc_trx_reg6_setf(uint32_t trxreg6) +{ + ASSERT_ERR((((uint32_t)trxreg6 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(RC_TRX_REG6_ADDR, (uint32_t)trxreg6 << 0); +} + +/** + * @brief TRX_REG7 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00             TRX_REG7   0x0
+ * 
+ */ +#define RC_TRX_REG7_ADDR 0x0105009C +#define RC_TRX_REG7_OFFSET 0x0000009C +#define RC_TRX_REG7_INDEX 0x00000027 +#define RC_TRX_REG7_RESET 0x00000000 + +__INLINE uint32_t rc_trx_reg7_get(void) +{ + return REG_PL_RD(RC_TRX_REG7_ADDR); +} + +__INLINE void rc_trx_reg7_set(uint32_t value) +{ + REG_PL_WR(RC_TRX_REG7_ADDR, value); +} + +// field definitions +#define RC_TRX_REG7_MASK ((uint32_t)0xFFFFFFFF) +#define RC_TRX_REG7_LSB 0 +#define RC_TRX_REG7_WIDTH ((uint32_t)0x00000020) + +#define RC_TRX_REG7_RST 0x0 + +__INLINE uint32_t rc_trx_reg7_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_TRX_REG7_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void rc_trx_reg7_setf(uint32_t trxreg7) +{ + ASSERT_ERR((((uint32_t)trxreg7 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(RC_TRX_REG7_ADDR, (uint32_t)trxreg7 << 0); +} + +/** + * @brief TRX_REG8 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00             TRX_REG8   0x0
+ * 
+ */ +#define RC_TRX_REG8_ADDR 0x010500A0 +#define RC_TRX_REG8_OFFSET 0x000000A0 +#define RC_TRX_REG8_INDEX 0x00000028 +#define RC_TRX_REG8_RESET 0x00000000 + +__INLINE uint32_t rc_trx_reg8_get(void) +{ + return REG_PL_RD(RC_TRX_REG8_ADDR); +} + +__INLINE void rc_trx_reg8_set(uint32_t value) +{ + REG_PL_WR(RC_TRX_REG8_ADDR, value); +} + +// field definitions +#define RC_TRX_REG8_MASK ((uint32_t)0xFFFFFFFF) +#define RC_TRX_REG8_LSB 0 +#define RC_TRX_REG8_WIDTH ((uint32_t)0x00000020) + +#define RC_TRX_REG8_RST 0x0 + +__INLINE uint32_t rc_trx_reg8_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_TRX_REG8_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void rc_trx_reg8_setf(uint32_t trxreg8) +{ + ASSERT_ERR((((uint32_t)trxreg8 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(RC_TRX_REG8_ADDR, (uint32_t)trxreg8 << 0); +} + +/** + * @brief TRX_REG9 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00             TRX_REG9   0x0
+ * 
+ */ +#define RC_TRX_REG9_ADDR 0x010500A4 +#define RC_TRX_REG9_OFFSET 0x000000A4 +#define RC_TRX_REG9_INDEX 0x00000029 +#define RC_TRX_REG9_RESET 0x00000000 + +__INLINE uint32_t rc_trx_reg9_get(void) +{ + return REG_PL_RD(RC_TRX_REG9_ADDR); +} + +__INLINE void rc_trx_reg9_set(uint32_t value) +{ + REG_PL_WR(RC_TRX_REG9_ADDR, value); +} + +// field definitions +#define RC_TRX_REG9_MASK ((uint32_t)0xFFFFFFFF) +#define RC_TRX_REG9_LSB 0 +#define RC_TRX_REG9_WIDTH ((uint32_t)0x00000020) + +#define RC_TRX_REG9_RST 0x0 + +__INLINE uint32_t rc_trx_reg9_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_TRX_REG9_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void rc_trx_reg9_setf(uint32_t trxreg9) +{ + ASSERT_ERR((((uint32_t)trxreg9 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(RC_TRX_REG9_ADDR, (uint32_t)trxreg9 << 0); +} + +/** + * @brief TRX_REG10 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00            TRX_REG10   0x0
+ * 
+ */ +#define RC_TRX_REG10_ADDR 0x010500A8 +#define RC_TRX_REG10_OFFSET 0x000000A8 +#define RC_TRX_REG10_INDEX 0x0000002A +#define RC_TRX_REG10_RESET 0x00000000 + +__INLINE uint32_t rc_trx_reg10_get(void) +{ + return REG_PL_RD(RC_TRX_REG10_ADDR); +} + +__INLINE void rc_trx_reg10_set(uint32_t value) +{ + REG_PL_WR(RC_TRX_REG10_ADDR, value); +} + +// field definitions +#define RC_TRX_REG10_MASK ((uint32_t)0xFFFFFFFF) +#define RC_TRX_REG10_LSB 0 +#define RC_TRX_REG10_WIDTH ((uint32_t)0x00000020) + +#define RC_TRX_REG10_RST 0x0 + +__INLINE uint32_t rc_trx_reg10_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_TRX_REG10_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void rc_trx_reg10_setf(uint32_t trxreg10) +{ + ASSERT_ERR((((uint32_t)trxreg10 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(RC_TRX_REG10_ADDR, (uint32_t)trxreg10 << 0); +} + +/** + * @brief TRX_REG11 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00            TRX_REG11   0x0
+ * 
+ */ +#define RC_TRX_REG11_ADDR 0x010500AC +#define RC_TRX_REG11_OFFSET 0x000000AC +#define RC_TRX_REG11_INDEX 0x0000002B +#define RC_TRX_REG11_RESET 0x00000000 + +__INLINE uint32_t rc_trx_reg11_get(void) +{ + return REG_PL_RD(RC_TRX_REG11_ADDR); +} + +__INLINE void rc_trx_reg11_set(uint32_t value) +{ + REG_PL_WR(RC_TRX_REG11_ADDR, value); +} + +// field definitions +#define RC_TRX_REG11_MASK ((uint32_t)0xFFFFFFFF) +#define RC_TRX_REG11_LSB 0 +#define RC_TRX_REG11_WIDTH ((uint32_t)0x00000020) + +#define RC_TRX_REG11_RST 0x0 + +__INLINE uint32_t rc_trx_reg11_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_TRX_REG11_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void rc_trx_reg11_setf(uint32_t trxreg11) +{ + ASSERT_ERR((((uint32_t)trxreg11 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(RC_TRX_REG11_ADDR, (uint32_t)trxreg11 << 0); +} + +/** + * @brief TRX_REG12 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00            TRX_REG12   0x0
+ * 
+ */ +#define RC_TRX_REG12_ADDR 0x010500B0 +#define RC_TRX_REG12_OFFSET 0x000000B0 +#define RC_TRX_REG12_INDEX 0x0000002C +#define RC_TRX_REG12_RESET 0x00000000 + +__INLINE uint32_t rc_trx_reg12_get(void) +{ + return REG_PL_RD(RC_TRX_REG12_ADDR); +} + +__INLINE void rc_trx_reg12_set(uint32_t value) +{ + REG_PL_WR(RC_TRX_REG12_ADDR, value); +} + +// field definitions +#define RC_TRX_REG12_MASK ((uint32_t)0xFFFFFFFF) +#define RC_TRX_REG12_LSB 0 +#define RC_TRX_REG12_WIDTH ((uint32_t)0x00000020) + +#define RC_TRX_REG12_RST 0x0 + +__INLINE uint32_t rc_trx_reg12_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_TRX_REG12_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void rc_trx_reg12_setf(uint32_t trxreg12) +{ + ASSERT_ERR((((uint32_t)trxreg12 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(RC_TRX_REG12_ADDR, (uint32_t)trxreg12 << 0); +} + +/** + * @brief TRX_REG13 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00            TRX_REG13   0x0
+ * 
+ */ +#define RC_TRX_REG13_ADDR 0x010500B4 +#define RC_TRX_REG13_OFFSET 0x000000B4 +#define RC_TRX_REG13_INDEX 0x0000002D +#define RC_TRX_REG13_RESET 0x00000000 + +__INLINE uint32_t rc_trx_reg13_get(void) +{ + return REG_PL_RD(RC_TRX_REG13_ADDR); +} + +__INLINE void rc_trx_reg13_set(uint32_t value) +{ + REG_PL_WR(RC_TRX_REG13_ADDR, value); +} + +// field definitions +#define RC_TRX_REG13_MASK ((uint32_t)0xFFFFFFFF) +#define RC_TRX_REG13_LSB 0 +#define RC_TRX_REG13_WIDTH ((uint32_t)0x00000020) + +#define RC_TRX_REG13_RST 0x0 + +__INLINE uint32_t rc_trx_reg13_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_TRX_REG13_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void rc_trx_reg13_setf(uint32_t trxreg13) +{ + ASSERT_ERR((((uint32_t)trxreg13 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(RC_TRX_REG13_ADDR, (uint32_t)trxreg13 << 0); +} + +/** + * @brief TRX_REG14 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00            TRX_REG14   0x0
+ * 
+ */ +#define RC_TRX_REG14_ADDR 0x010500B8 +#define RC_TRX_REG14_OFFSET 0x000000B8 +#define RC_TRX_REG14_INDEX 0x0000002E +#define RC_TRX_REG14_RESET 0x00000000 + +__INLINE uint32_t rc_trx_reg14_get(void) +{ + return REG_PL_RD(RC_TRX_REG14_ADDR); +} + +__INLINE void rc_trx_reg14_set(uint32_t value) +{ + REG_PL_WR(RC_TRX_REG14_ADDR, value); +} + +// field definitions +#define RC_TRX_REG14_MASK ((uint32_t)0xFFFFFFFF) +#define RC_TRX_REG14_LSB 0 +#define RC_TRX_REG14_WIDTH ((uint32_t)0x00000020) + +#define RC_TRX_REG14_RST 0x0 + +__INLINE uint32_t rc_trx_reg14_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_TRX_REG14_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void rc_trx_reg14_setf(uint32_t trxreg14) +{ + ASSERT_ERR((((uint32_t)trxreg14 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(RC_TRX_REG14_ADDR, (uint32_t)trxreg14 << 0); +} + +/** + * @brief TRX_REG15 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00            TRX_REG15   0x0
+ * 
+ */ +#define RC_TRX_REG15_ADDR 0x010500BC +#define RC_TRX_REG15_OFFSET 0x000000BC +#define RC_TRX_REG15_INDEX 0x0000002F +#define RC_TRX_REG15_RESET 0x00000000 + +__INLINE uint32_t rc_trx_reg15_get(void) +{ + return REG_PL_RD(RC_TRX_REG15_ADDR); +} + +__INLINE void rc_trx_reg15_set(uint32_t value) +{ + REG_PL_WR(RC_TRX_REG15_ADDR, value); +} + +// field definitions +#define RC_TRX_REG15_MASK ((uint32_t)0xFFFFFFFF) +#define RC_TRX_REG15_LSB 0 +#define RC_TRX_REG15_WIDTH ((uint32_t)0x00000020) + +#define RC_TRX_REG15_RST 0x0 + +__INLINE uint32_t rc_trx_reg15_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_TRX_REG15_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void rc_trx_reg15_setf(uint32_t trxreg15) +{ + ASSERT_ERR((((uint32_t)trxreg15 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(RC_TRX_REG15_ADDR, (uint32_t)trxreg15 << 0); +} + +/** + * @brief TRX_REG16 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00            TRX_REG16   0x0
+ * 
+ */ +#define RC_TRX_REG16_ADDR 0x010500C0 +#define RC_TRX_REG16_OFFSET 0x000000C0 +#define RC_TRX_REG16_INDEX 0x00000030 +#define RC_TRX_REG16_RESET 0x00000000 + +__INLINE uint32_t rc_trx_reg16_get(void) +{ + return REG_PL_RD(RC_TRX_REG16_ADDR); +} + +__INLINE void rc_trx_reg16_set(uint32_t value) +{ + REG_PL_WR(RC_TRX_REG16_ADDR, value); +} + +// field definitions +#define RC_TRX_REG16_MASK ((uint32_t)0xFFFFFFFF) +#define RC_TRX_REG16_LSB 0 +#define RC_TRX_REG16_WIDTH ((uint32_t)0x00000020) + +#define RC_TRX_REG16_RST 0x0 + +__INLINE uint32_t rc_trx_reg16_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_TRX_REG16_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void rc_trx_reg16_setf(uint32_t trxreg16) +{ + ASSERT_ERR((((uint32_t)trxreg16 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(RC_TRX_REG16_ADDR, (uint32_t)trxreg16 << 0); +} + +/** + * @brief TRX_REG17 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00            TRX_REG17   0x0
+ * 
+ */ +#define RC_TRX_REG17_ADDR 0x010500C4 +#define RC_TRX_REG17_OFFSET 0x000000C4 +#define RC_TRX_REG17_INDEX 0x00000031 +#define RC_TRX_REG17_RESET 0x00000000 + +__INLINE uint32_t rc_trx_reg17_get(void) +{ + return REG_PL_RD(RC_TRX_REG17_ADDR); +} + +__INLINE void rc_trx_reg17_set(uint32_t value) +{ + REG_PL_WR(RC_TRX_REG17_ADDR, value); +} + +// field definitions +#define RC_TRX_REG17_MASK ((uint32_t)0xFFFFFFFF) +#define RC_TRX_REG17_LSB 0 +#define RC_TRX_REG17_WIDTH ((uint32_t)0x00000020) + +#define RC_TRX_REG17_RST 0x0 + +__INLINE uint32_t rc_trx_reg17_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_TRX_REG17_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void rc_trx_reg17_setf(uint32_t trxreg17) +{ + ASSERT_ERR((((uint32_t)trxreg17 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(RC_TRX_REG17_ADDR, (uint32_t)trxreg17 << 0); +} + +/** + * @brief TRX_REG18 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00            TRX_REG18   0x0
+ * 
+ */ +#define RC_TRX_REG18_ADDR 0x010500C8 +#define RC_TRX_REG18_OFFSET 0x000000C8 +#define RC_TRX_REG18_INDEX 0x00000032 +#define RC_TRX_REG18_RESET 0x00000000 + +__INLINE uint32_t rc_trx_reg18_get(void) +{ + return REG_PL_RD(RC_TRX_REG18_ADDR); +} + +__INLINE void rc_trx_reg18_set(uint32_t value) +{ + REG_PL_WR(RC_TRX_REG18_ADDR, value); +} + +// field definitions +#define RC_TRX_REG18_MASK ((uint32_t)0xFFFFFFFF) +#define RC_TRX_REG18_LSB 0 +#define RC_TRX_REG18_WIDTH ((uint32_t)0x00000020) + +#define RC_TRX_REG18_RST 0x0 + +__INLINE uint32_t rc_trx_reg18_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_TRX_REG18_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void rc_trx_reg18_setf(uint32_t trxreg18) +{ + ASSERT_ERR((((uint32_t)trxreg18 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(RC_TRX_REG18_ADDR, (uint32_t)trxreg18 << 0); +} + +/** + * @brief TRX_REG19 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00            TRX_REG19   0x0
+ * 
+ */ +#define RC_TRX_REG19_ADDR 0x010500CC +#define RC_TRX_REG19_OFFSET 0x000000CC +#define RC_TRX_REG19_INDEX 0x00000033 +#define RC_TRX_REG19_RESET 0x00000000 + +__INLINE uint32_t rc_trx_reg19_get(void) +{ + return REG_PL_RD(RC_TRX_REG19_ADDR); +} + +__INLINE void rc_trx_reg19_set(uint32_t value) +{ + REG_PL_WR(RC_TRX_REG19_ADDR, value); +} + +// field definitions +#define RC_TRX_REG19_MASK ((uint32_t)0xFFFFFFFF) +#define RC_TRX_REG19_LSB 0 +#define RC_TRX_REG19_WIDTH ((uint32_t)0x00000020) + +#define RC_TRX_REG19_RST 0x0 + +__INLINE uint32_t rc_trx_reg19_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_TRX_REG19_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void rc_trx_reg19_setf(uint32_t trxreg19) +{ + ASSERT_ERR((((uint32_t)trxreg19 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(RC_TRX_REG19_ADDR, (uint32_t)trxreg19 << 0); +} + +/** + * @brief TRX_REG20 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00            TRX_REG20   0x0
+ * 
+ */ +#define RC_TRX_REG20_ADDR 0x010500D0 +#define RC_TRX_REG20_OFFSET 0x000000D0 +#define RC_TRX_REG20_INDEX 0x00000034 +#define RC_TRX_REG20_RESET 0x00000000 + +__INLINE uint32_t rc_trx_reg20_get(void) +{ + return REG_PL_RD(RC_TRX_REG20_ADDR); +} + +__INLINE void rc_trx_reg20_set(uint32_t value) +{ + REG_PL_WR(RC_TRX_REG20_ADDR, value); +} + +// field definitions +#define RC_TRX_REG20_MASK ((uint32_t)0xFFFFFFFF) +#define RC_TRX_REG20_LSB 0 +#define RC_TRX_REG20_WIDTH ((uint32_t)0x00000020) + +#define RC_TRX_REG20_RST 0x0 + +__INLINE uint32_t rc_trx_reg20_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_TRX_REG20_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void rc_trx_reg20_setf(uint32_t trxreg20) +{ + ASSERT_ERR((((uint32_t)trxreg20 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(RC_TRX_REG20_ADDR, (uint32_t)trxreg20 << 0); +} + +/** + * @brief TRX_REG21 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00            TRX_REG21   0x0
+ * 
+ */ +#define RC_TRX_REG21_ADDR 0x010500D4 +#define RC_TRX_REG21_OFFSET 0x000000D4 +#define RC_TRX_REG21_INDEX 0x00000035 +#define RC_TRX_REG21_RESET 0x00000000 + +__INLINE uint32_t rc_trx_reg21_get(void) +{ + return REG_PL_RD(RC_TRX_REG21_ADDR); +} + +__INLINE void rc_trx_reg21_set(uint32_t value) +{ + REG_PL_WR(RC_TRX_REG21_ADDR, value); +} + +// field definitions +#define RC_TRX_REG21_MASK ((uint32_t)0xFFFFFFFF) +#define RC_TRX_REG21_LSB 0 +#define RC_TRX_REG21_WIDTH ((uint32_t)0x00000020) + +#define RC_TRX_REG21_RST 0x0 + +__INLINE uint32_t rc_trx_reg21_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_TRX_REG21_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void rc_trx_reg21_setf(uint32_t trxreg21) +{ + ASSERT_ERR((((uint32_t)trxreg21 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(RC_TRX_REG21_ADDR, (uint32_t)trxreg21 << 0); +} + +/** + * @brief TRX_REG22 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00            TRX_REG22   0x0
+ * 
+ */ +#define RC_TRX_REG22_ADDR 0x010500D8 +#define RC_TRX_REG22_OFFSET 0x000000D8 +#define RC_TRX_REG22_INDEX 0x00000036 +#define RC_TRX_REG22_RESET 0x00000000 + +__INLINE uint32_t rc_trx_reg22_get(void) +{ + return REG_PL_RD(RC_TRX_REG22_ADDR); +} + +__INLINE void rc_trx_reg22_set(uint32_t value) +{ + REG_PL_WR(RC_TRX_REG22_ADDR, value); +} + +// field definitions +#define RC_TRX_REG22_MASK ((uint32_t)0xFFFFFFFF) +#define RC_TRX_REG22_LSB 0 +#define RC_TRX_REG22_WIDTH ((uint32_t)0x00000020) + +#define RC_TRX_REG22_RST 0x0 + +__INLINE uint32_t rc_trx_reg22_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_TRX_REG22_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void rc_trx_reg22_setf(uint32_t trxreg22) +{ + ASSERT_ERR((((uint32_t)trxreg22 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(RC_TRX_REG22_ADDR, (uint32_t)trxreg22 << 0); +} + +/** + * @brief TRX_REG23 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00            TRX_REG23   0x0
+ * 
+ */ +#define RC_TRX_REG23_ADDR 0x010500DC +#define RC_TRX_REG23_OFFSET 0x000000DC +#define RC_TRX_REG23_INDEX 0x00000037 +#define RC_TRX_REG23_RESET 0x00000000 + +__INLINE uint32_t rc_trx_reg23_get(void) +{ + return REG_PL_RD(RC_TRX_REG23_ADDR); +} + +__INLINE void rc_trx_reg23_set(uint32_t value) +{ + REG_PL_WR(RC_TRX_REG23_ADDR, value); +} + +// field definitions +#define RC_TRX_REG23_MASK ((uint32_t)0xFFFFFFFF) +#define RC_TRX_REG23_LSB 0 +#define RC_TRX_REG23_WIDTH ((uint32_t)0x00000020) + +#define RC_TRX_REG23_RST 0x0 + +__INLINE uint32_t rc_trx_reg23_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_TRX_REG23_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void rc_trx_reg23_setf(uint32_t trxreg23) +{ + ASSERT_ERR((((uint32_t)trxreg23 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(RC_TRX_REG23_ADDR, (uint32_t)trxreg23 << 0); +} + +/** + * @brief TRX_REG24 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00            TRX_REG24   0x0
+ * 
+ */ +#define RC_TRX_REG24_ADDR 0x010500E0 +#define RC_TRX_REG24_OFFSET 0x000000E0 +#define RC_TRX_REG24_INDEX 0x00000038 +#define RC_TRX_REG24_RESET 0x00000000 + +__INLINE uint32_t rc_trx_reg24_get(void) +{ + return REG_PL_RD(RC_TRX_REG24_ADDR); +} + +__INLINE void rc_trx_reg24_set(uint32_t value) +{ + REG_PL_WR(RC_TRX_REG24_ADDR, value); +} + +// field definitions +#define RC_TRX_REG24_MASK ((uint32_t)0xFFFFFFFF) +#define RC_TRX_REG24_LSB 0 +#define RC_TRX_REG24_WIDTH ((uint32_t)0x00000020) + +#define RC_TRX_REG24_RST 0x0 + +__INLINE uint32_t rc_trx_reg24_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_TRX_REG24_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void rc_trx_reg24_setf(uint32_t trxreg24) +{ + ASSERT_ERR((((uint32_t)trxreg24 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(RC_TRX_REG24_ADDR, (uint32_t)trxreg24 << 0); +} + +/** + * @brief TRX_REG25 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00            TRX_REG25   0x0
+ * 
+ */ +#define RC_TRX_REG25_ADDR 0x010500E4 +#define RC_TRX_REG25_OFFSET 0x000000E4 +#define RC_TRX_REG25_INDEX 0x00000039 +#define RC_TRX_REG25_RESET 0x00000000 + +__INLINE uint32_t rc_trx_reg25_get(void) +{ + return REG_PL_RD(RC_TRX_REG25_ADDR); +} + +__INLINE void rc_trx_reg25_set(uint32_t value) +{ + REG_PL_WR(RC_TRX_REG25_ADDR, value); +} + +// field definitions +#define RC_TRX_REG25_MASK ((uint32_t)0xFFFFFFFF) +#define RC_TRX_REG25_LSB 0 +#define RC_TRX_REG25_WIDTH ((uint32_t)0x00000020) + +#define RC_TRX_REG25_RST 0x0 + +__INLINE uint32_t rc_trx_reg25_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_TRX_REG25_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void rc_trx_reg25_setf(uint32_t trxreg25) +{ + ASSERT_ERR((((uint32_t)trxreg25 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(RC_TRX_REG25_ADDR, (uint32_t)trxreg25 << 0); +} + +/** + * @brief TRX_REG26 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00            TRX_REG26   0x0
+ * 
+ */ +#define RC_TRX_REG26_ADDR 0x010500E8 +#define RC_TRX_REG26_OFFSET 0x000000E8 +#define RC_TRX_REG26_INDEX 0x0000003A +#define RC_TRX_REG26_RESET 0x00000000 + +__INLINE uint32_t rc_trx_reg26_get(void) +{ + return REG_PL_RD(RC_TRX_REG26_ADDR); +} + +__INLINE void rc_trx_reg26_set(uint32_t value) +{ + REG_PL_WR(RC_TRX_REG26_ADDR, value); +} + +// field definitions +#define RC_TRX_REG26_MASK ((uint32_t)0xFFFFFFFF) +#define RC_TRX_REG26_LSB 0 +#define RC_TRX_REG26_WIDTH ((uint32_t)0x00000020) + +#define RC_TRX_REG26_RST 0x0 + +__INLINE uint32_t rc_trx_reg26_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_TRX_REG26_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void rc_trx_reg26_setf(uint32_t trxreg26) +{ + ASSERT_ERR((((uint32_t)trxreg26 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(RC_TRX_REG26_ADDR, (uint32_t)trxreg26 << 0); +} + +/** + * @brief TRX_REG27 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00            TRX_REG27   0x0
+ * 
+ */ +#define RC_TRX_REG27_ADDR 0x010500EC +#define RC_TRX_REG27_OFFSET 0x000000EC +#define RC_TRX_REG27_INDEX 0x0000003B +#define RC_TRX_REG27_RESET 0x00000000 + +__INLINE uint32_t rc_trx_reg27_get(void) +{ + return REG_PL_RD(RC_TRX_REG27_ADDR); +} + +__INLINE void rc_trx_reg27_set(uint32_t value) +{ + REG_PL_WR(RC_TRX_REG27_ADDR, value); +} + +// field definitions +#define RC_TRX_REG27_MASK ((uint32_t)0xFFFFFFFF) +#define RC_TRX_REG27_LSB 0 +#define RC_TRX_REG27_WIDTH ((uint32_t)0x00000020) + +#define RC_TRX_REG27_RST 0x0 + +__INLINE uint32_t rc_trx_reg27_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_TRX_REG27_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void rc_trx_reg27_setf(uint32_t trxreg27) +{ + ASSERT_ERR((((uint32_t)trxreg27 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(RC_TRX_REG27_ADDR, (uint32_t)trxreg27 << 0); +} + +/** + * @brief RX_AVG_CALC register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31         RX_DC_CAL_EN   0
+ *     30          RX_AVG_MODE   0
+ *  23:12          RX_AVG_I_RD   0x0
+ *  11:00          RX_AVG_Q_RD   0x0
+ * 
+ */ +#define RC_RX_AVG_CALC_ADDR 0x010500F0 +#define RC_RX_AVG_CALC_OFFSET 0x000000F0 +#define RC_RX_AVG_CALC_INDEX 0x0000003C +#define RC_RX_AVG_CALC_RESET 0x00000000 + +__INLINE uint32_t rc_rx_avg_calc_get(void) +{ + return REG_PL_RD(RC_RX_AVG_CALC_ADDR); +} + +__INLINE void rc_rx_avg_calc_set(uint32_t value) +{ + REG_PL_WR(RC_RX_AVG_CALC_ADDR, value); +} + +// field definitions +#define RC_RX_DC_CAL_EN_BIT ((uint32_t)0x80000000) +#define RC_RX_DC_CAL_EN_POS 31 +#define RC_RX_AVG_MODE_BIT ((uint32_t)0x40000000) +#define RC_RX_AVG_MODE_POS 30 +#define RC_RX_AVG_I_RD_MASK ((uint32_t)0x00FFF000) +#define RC_RX_AVG_I_RD_LSB 12 +#define RC_RX_AVG_I_RD_WIDTH ((uint32_t)0x0000000C) +#define RC_RX_AVG_Q_RD_MASK ((uint32_t)0x00000FFF) +#define RC_RX_AVG_Q_RD_LSB 0 +#define RC_RX_AVG_Q_RD_WIDTH ((uint32_t)0x0000000C) + +#define RC_RX_DC_CAL_EN_RST 0x0 +#define RC_RX_AVG_MODE_RST 0x0 +#define RC_RX_AVG_I_RD_RST 0x0 +#define RC_RX_AVG_Q_RD_RST 0x0 + +__INLINE void rc_rx_avg_calc_pack(uint8_t rxdccalen, uint8_t rxavgmode, uint16_t rxavgird, uint16_t rxavgqrd) +{ + ASSERT_ERR((((uint32_t)rxdccalen << 31) & ~((uint32_t)0x80000000)) == 0); + ASSERT_ERR((((uint32_t)rxavgmode << 30) & ~((uint32_t)0x40000000)) == 0); + ASSERT_ERR((((uint32_t)rxavgird << 12) & ~((uint32_t)0x00FFF000)) == 0); + ASSERT_ERR((((uint32_t)rxavgqrd << 0) & ~((uint32_t)0x00000FFF)) == 0); + REG_PL_WR(RC_RX_AVG_CALC_ADDR, ((uint32_t)rxdccalen << 31) | ((uint32_t)rxavgmode << 30) | ((uint32_t)rxavgird << 12) | ((uint32_t)rxavgqrd << 0)); +} + +__INLINE void rc_rx_avg_calc_unpack(uint8_t *rxdccalen, uint8_t *rxavgmode, uint16_t *rxavgird, uint16_t *rxavgqrd) +{ + uint32_t localVal = REG_PL_RD(RC_RX_AVG_CALC_ADDR); + + *rxdccalen = (localVal & ((uint32_t)0x80000000)) >> 31; + *rxavgmode = (localVal & ((uint32_t)0x40000000)) >> 30; + *rxavgird = (localVal & ((uint32_t)0x00FFF000)) >> 12; + *rxavgqrd = (localVal & ((uint32_t)0x00000FFF)) >> 0; +} + +__INLINE uint8_t rc_rx_dc_cal_en_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_RX_AVG_CALC_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +__INLINE void rc_rx_dc_cal_en_setf(uint8_t rxdccalen) +{ + ASSERT_ERR((((uint32_t)rxdccalen << 31) & ~((uint32_t)0x80000000)) == 0); + REG_PL_WR(RC_RX_AVG_CALC_ADDR, (REG_PL_RD(RC_RX_AVG_CALC_ADDR) & ~((uint32_t)0x80000000)) | ((uint32_t)rxdccalen << 31)); +} + +__INLINE uint8_t rc_rx_avg_mode_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_RX_AVG_CALC_ADDR); + return ((localVal & ((uint32_t)0x40000000)) >> 30); +} + +__INLINE void rc_rx_avg_mode_setf(uint8_t rxavgmode) +{ + ASSERT_ERR((((uint32_t)rxavgmode << 30) & ~((uint32_t)0x40000000)) == 0); + REG_PL_WR(RC_RX_AVG_CALC_ADDR, (REG_PL_RD(RC_RX_AVG_CALC_ADDR) & ~((uint32_t)0x40000000)) | ((uint32_t)rxavgmode << 30)); +} + +__INLINE uint16_t rc_rx_avg_i_rd_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_RX_AVG_CALC_ADDR); + return ((localVal & ((uint32_t)0x00FFF000)) >> 12); +} + +__INLINE void rc_rx_avg_i_rd_setf(uint16_t rxavgird) +{ + ASSERT_ERR((((uint32_t)rxavgird << 12) & ~((uint32_t)0x00FFF000)) == 0); + REG_PL_WR(RC_RX_AVG_CALC_ADDR, (REG_PL_RD(RC_RX_AVG_CALC_ADDR) & ~((uint32_t)0x00FFF000)) | ((uint32_t)rxavgird << 12)); +} + +__INLINE uint16_t rc_rx_avg_q_rd_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_RX_AVG_CALC_ADDR); + return ((localVal & ((uint32_t)0x00000FFF)) >> 0); +} + +__INLINE void rc_rx_avg_q_rd_setf(uint16_t rxavgqrd) +{ + ASSERT_ERR((((uint32_t)rxavgqrd << 0) & ~((uint32_t)0x00000FFF)) == 0); + REG_PL_WR(RC_RX_AVG_CALC_ADDR, (REG_PL_RD(RC_RX_AVG_CALC_ADDR) & ~((uint32_t)0x00000FFF)) | ((uint32_t)rxavgqrd << 0)); +} + +/** + * @brief RX_CALIB_EN register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31            RX_CAL_EN   0
+ *     30           RX_COMP_EN   0
+ *  23:12           RX_DC_I_RD   0x0
+ *  11:00           RX_DC_Q_RD   0x0
+ * 
+ */ +#define RC_RX_CALIB_EN_ADDR 0x010500F8 +#define RC_RX_CALIB_EN_OFFSET 0x000000F8 +#define RC_RX_CALIB_EN_INDEX 0x0000003E +#define RC_RX_CALIB_EN_RESET 0x00000000 + +__INLINE uint32_t rc_rx_calib_en_get(void) +{ + return REG_PL_RD(RC_RX_CALIB_EN_ADDR); +} + +__INLINE void rc_rx_calib_en_set(uint32_t value) +{ + REG_PL_WR(RC_RX_CALIB_EN_ADDR, value); +} + +// field definitions +#define RC_RX_CAL_EN_BIT ((uint32_t)0x80000000) +#define RC_RX_CAL_EN_POS 31 +#define RC_RX_COMP_EN_BIT ((uint32_t)0x40000000) +#define RC_RX_COMP_EN_POS 30 +#define RC_RX_DC_I_RD_MASK ((uint32_t)0x00FFF000) +#define RC_RX_DC_I_RD_LSB 12 +#define RC_RX_DC_I_RD_WIDTH ((uint32_t)0x0000000C) +#define RC_RX_DC_Q_RD_MASK ((uint32_t)0x00000FFF) +#define RC_RX_DC_Q_RD_LSB 0 +#define RC_RX_DC_Q_RD_WIDTH ((uint32_t)0x0000000C) + +#define RC_RX_CAL_EN_RST 0x0 +#define RC_RX_COMP_EN_RST 0x0 +#define RC_RX_DC_I_RD_RST 0x0 +#define RC_RX_DC_Q_RD_RST 0x0 + +__INLINE void rc_rx_calib_en_pack(uint8_t rxcalen, uint8_t rxcompen, uint16_t rxdcird, uint16_t rxdcqrd) +{ + ASSERT_ERR((((uint32_t)rxcalen << 31) & ~((uint32_t)0x80000000)) == 0); + ASSERT_ERR((((uint32_t)rxcompen << 30) & ~((uint32_t)0x40000000)) == 0); + ASSERT_ERR((((uint32_t)rxdcird << 12) & ~((uint32_t)0x00FFF000)) == 0); + ASSERT_ERR((((uint32_t)rxdcqrd << 0) & ~((uint32_t)0x00000FFF)) == 0); + REG_PL_WR(RC_RX_CALIB_EN_ADDR, ((uint32_t)rxcalen << 31) | ((uint32_t)rxcompen << 30) | ((uint32_t)rxdcird << 12) | ((uint32_t)rxdcqrd << 0)); +} + +__INLINE void rc_rx_calib_en_unpack(uint8_t *rxcalen, uint8_t *rxcompen, uint16_t *rxdcird, uint16_t *rxdcqrd) +{ + uint32_t localVal = REG_PL_RD(RC_RX_CALIB_EN_ADDR); + + *rxcalen = (localVal & ((uint32_t)0x80000000)) >> 31; + *rxcompen = (localVal & ((uint32_t)0x40000000)) >> 30; + *rxdcird = (localVal & ((uint32_t)0x00FFF000)) >> 12; + *rxdcqrd = (localVal & ((uint32_t)0x00000FFF)) >> 0; +} + +__INLINE uint8_t rc_rx_cal_en_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_RX_CALIB_EN_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +__INLINE void rc_rx_cal_en_setf(uint8_t rxcalen) +{ + ASSERT_ERR((((uint32_t)rxcalen << 31) & ~((uint32_t)0x80000000)) == 0); + REG_PL_WR(RC_RX_CALIB_EN_ADDR, (REG_PL_RD(RC_RX_CALIB_EN_ADDR) & ~((uint32_t)0x80000000)) | ((uint32_t)rxcalen << 31)); +} + +__INLINE uint8_t rc_rx_comp_en_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_RX_CALIB_EN_ADDR); + return ((localVal & ((uint32_t)0x40000000)) >> 30); +} + +__INLINE void rc_rx_comp_en_setf(uint8_t rxcompen) +{ + ASSERT_ERR((((uint32_t)rxcompen << 30) & ~((uint32_t)0x40000000)) == 0); + REG_PL_WR(RC_RX_CALIB_EN_ADDR, (REG_PL_RD(RC_RX_CALIB_EN_ADDR) & ~((uint32_t)0x40000000)) | ((uint32_t)rxcompen << 30)); +} + +__INLINE uint16_t rc_rx_dc_i_rd_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_RX_CALIB_EN_ADDR); + return ((localVal & ((uint32_t)0x00FFF000)) >> 12); +} + +__INLINE void rc_rx_dc_i_rd_setf(uint16_t rxdcird) +{ + ASSERT_ERR((((uint32_t)rxdcird << 12) & ~((uint32_t)0x00FFF000)) == 0); + REG_PL_WR(RC_RX_CALIB_EN_ADDR, (REG_PL_RD(RC_RX_CALIB_EN_ADDR) & ~((uint32_t)0x00FFF000)) | ((uint32_t)rxdcird << 12)); +} + +__INLINE uint16_t rc_rx_dc_q_rd_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_RX_CALIB_EN_ADDR); + return ((localVal & ((uint32_t)0x00000FFF)) >> 0); +} + +__INLINE void rc_rx_dc_q_rd_setf(uint16_t rxdcqrd) +{ + ASSERT_ERR((((uint32_t)rxdcqrd << 0) & ~((uint32_t)0x00000FFF)) == 0); + REG_PL_WR(RC_RX_CALIB_EN_ADDR, (REG_PL_RD(RC_RX_CALIB_EN_ADDR) & ~((uint32_t)0x00000FFF)) | ((uint32_t)rxdcqrd << 0)); +} + +/** + * @brief RX_ERROR_RD register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  25:16        RX_AMP_ERR_RD   0x0
+ *  09:00      RX_PHASE_ERR_RD   0x0
+ * 
+ */ +#define RC_RX_ERROR_RD_ADDR 0x010500FC +#define RC_RX_ERROR_RD_OFFSET 0x000000FC +#define RC_RX_ERROR_RD_INDEX 0x0000003F +#define RC_RX_ERROR_RD_RESET 0x00000000 + +__INLINE uint32_t rc_rx_error_rd_get(void) +{ + return REG_PL_RD(RC_RX_ERROR_RD_ADDR); +} + +// field definitions +#define RC_RX_AMP_ERR_RD_MASK ((uint32_t)0x03FF0000) +#define RC_RX_AMP_ERR_RD_LSB 16 +#define RC_RX_AMP_ERR_RD_WIDTH ((uint32_t)0x0000000A) +#define RC_RX_PHASE_ERR_RD_MASK ((uint32_t)0x000003FF) +#define RC_RX_PHASE_ERR_RD_LSB 0 +#define RC_RX_PHASE_ERR_RD_WIDTH ((uint32_t)0x0000000A) + +#define RC_RX_AMP_ERR_RD_RST 0x0 +#define RC_RX_PHASE_ERR_RD_RST 0x0 + +__INLINE void rc_rx_error_rd_unpack(uint16_t *rxamperrrd, uint16_t *rxphaseerrrd) +{ + uint32_t localVal = REG_PL_RD(RC_RX_ERROR_RD_ADDR); + + *rxamperrrd = (localVal & ((uint32_t)0x03FF0000)) >> 16; + *rxphaseerrrd = (localVal & ((uint32_t)0x000003FF)) >> 0; +} + +__INLINE uint16_t rc_rx_amp_err_rd_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_RX_ERROR_RD_ADDR); + return ((localVal & ((uint32_t)0x03FF0000)) >> 16); +} + +__INLINE uint16_t rc_rx_phase_err_rd_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_RX_ERROR_RD_ADDR); + return ((localVal & ((uint32_t)0x000003FF)) >> 0); +} + +/** + * @brief RX_TY2_RD register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  09:00            RX_TY2_RD   0x0
+ * 
+ */ +#define RC_RX_TY2_RD_ADDR 0x01050100 +#define RC_RX_TY2_RD_OFFSET 0x00000100 +#define RC_RX_TY2_RD_INDEX 0x00000040 +#define RC_RX_TY2_RD_RESET 0x00000000 + +__INLINE uint32_t rc_rx_ty2_rd_get(void) +{ + return REG_PL_RD(RC_RX_TY2_RD_ADDR); +} + +// field definitions +#define RC_RX_TY2_RD_MASK ((uint32_t)0x000003FF) +#define RC_RX_TY2_RD_LSB 0 +#define RC_RX_TY2_RD_WIDTH ((uint32_t)0x0000000A) + +#define RC_RX_TY2_RD_RST 0x0 + +__INLINE uint16_t rc_rx_ty2_rd_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_RX_TY2_RD_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x000003FF)) == 0); + return (localVal >> 0); +} + +/** + * @brief RX_DC_WR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  23:12           RX_DC_I_WR   0x800
+ *  11:00           RX_DC_Q_WR   0x0
+ * 
+ */ +#define RC_RX_DC_WR_ADDR 0x01050104 +#define RC_RX_DC_WR_OFFSET 0x00000104 +#define RC_RX_DC_WR_INDEX 0x00000041 +#define RC_RX_DC_WR_RESET 0x00800000 + +__INLINE uint32_t rc_rx_dc_wr_get(void) +{ + return REG_PL_RD(RC_RX_DC_WR_ADDR); +} + +__INLINE void rc_rx_dc_wr_set(uint32_t value) +{ + REG_PL_WR(RC_RX_DC_WR_ADDR, value); +} + +// field definitions +#define RC_RX_DC_I_WR_MASK ((uint32_t)0x00FFF000) +#define RC_RX_DC_I_WR_LSB 12 +#define RC_RX_DC_I_WR_WIDTH ((uint32_t)0x0000000C) +#define RC_RX_DC_Q_WR_MASK ((uint32_t)0x00000FFF) +#define RC_RX_DC_Q_WR_LSB 0 +#define RC_RX_DC_Q_WR_WIDTH ((uint32_t)0x0000000C) + +#define RC_RX_DC_I_WR_RST 0x800 +#define RC_RX_DC_Q_WR_RST 0x0 + +__INLINE void rc_rx_dc_wr_pack(uint16_t rxdciwr, uint16_t rxdcqwr) +{ + ASSERT_ERR((((uint32_t)rxdciwr << 12) & ~((uint32_t)0x00FFF000)) == 0); + ASSERT_ERR((((uint32_t)rxdcqwr << 0) & ~((uint32_t)0x00000FFF)) == 0); + REG_PL_WR(RC_RX_DC_WR_ADDR, ((uint32_t)rxdciwr << 12) | ((uint32_t)rxdcqwr << 0)); +} + +__INLINE void rc_rx_dc_wr_unpack(uint16_t *rxdciwr, uint16_t *rxdcqwr) +{ + uint32_t localVal = REG_PL_RD(RC_RX_DC_WR_ADDR); + + *rxdciwr = (localVal & ((uint32_t)0x00FFF000)) >> 12; + *rxdcqwr = (localVal & ((uint32_t)0x00000FFF)) >> 0; +} + +__INLINE uint16_t rc_rx_dc_i_wr_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_RX_DC_WR_ADDR); + return ((localVal & ((uint32_t)0x00FFF000)) >> 12); +} + +__INLINE void rc_rx_dc_i_wr_setf(uint16_t rxdciwr) +{ + ASSERT_ERR((((uint32_t)rxdciwr << 12) & ~((uint32_t)0x00FFF000)) == 0); + REG_PL_WR(RC_RX_DC_WR_ADDR, (REG_PL_RD(RC_RX_DC_WR_ADDR) & ~((uint32_t)0x00FFF000)) | ((uint32_t)rxdciwr << 12)); +} + +__INLINE uint16_t rc_rx_dc_q_wr_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_RX_DC_WR_ADDR); + return ((localVal & ((uint32_t)0x00000FFF)) >> 0); +} + +__INLINE void rc_rx_dc_q_wr_setf(uint16_t rxdcqwr) +{ + ASSERT_ERR((((uint32_t)rxdcqwr << 0) & ~((uint32_t)0x00000FFF)) == 0); + REG_PL_WR(RC_RX_DC_WR_ADDR, (REG_PL_RD(RC_RX_DC_WR_ADDR) & ~((uint32_t)0x00000FFF)) | ((uint32_t)rxdcqwr << 0)); +} + +/** + * @brief RX_ERROR_WR register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  25:16        RX_AMP_ERR_WR   0x200
+ *  09:00      RX_PHASE_ERR_WR   0x200
+ * 
+ */ +#define RC_RX_ERROR_WR_ADDR 0x01050108 +#define RC_RX_ERROR_WR_OFFSET 0x00000108 +#define RC_RX_ERROR_WR_INDEX 0x00000042 +#define RC_RX_ERROR_WR_RESET 0x02000200 + +__INLINE uint32_t rc_rx_error_wr_get(void) +{ + return REG_PL_RD(RC_RX_ERROR_WR_ADDR); +} + +__INLINE void rc_rx_error_wr_set(uint32_t value) +{ + REG_PL_WR(RC_RX_ERROR_WR_ADDR, value); +} + +// field definitions +#define RC_RX_AMP_ERR_WR_MASK ((uint32_t)0x03FF0000) +#define RC_RX_AMP_ERR_WR_LSB 16 +#define RC_RX_AMP_ERR_WR_WIDTH ((uint32_t)0x0000000A) +#define RC_RX_PHASE_ERR_WR_MASK ((uint32_t)0x000003FF) +#define RC_RX_PHASE_ERR_WR_LSB 0 +#define RC_RX_PHASE_ERR_WR_WIDTH ((uint32_t)0x0000000A) + +#define RC_RX_AMP_ERR_WR_RST 0x200 +#define RC_RX_PHASE_ERR_WR_RST 0x200 + +__INLINE void rc_rx_error_wr_pack(uint16_t rxamperrwr, uint16_t rxphaseerrwr) +{ + ASSERT_ERR((((uint32_t)rxamperrwr << 16) & ~((uint32_t)0x03FF0000)) == 0); + ASSERT_ERR((((uint32_t)rxphaseerrwr << 0) & ~((uint32_t)0x000003FF)) == 0); + REG_PL_WR(RC_RX_ERROR_WR_ADDR, ((uint32_t)rxamperrwr << 16) | ((uint32_t)rxphaseerrwr << 0)); +} + +__INLINE void rc_rx_error_wr_unpack(uint16_t *rxamperrwr, uint16_t *rxphaseerrwr) +{ + uint32_t localVal = REG_PL_RD(RC_RX_ERROR_WR_ADDR); + + *rxamperrwr = (localVal & ((uint32_t)0x03FF0000)) >> 16; + *rxphaseerrwr = (localVal & ((uint32_t)0x000003FF)) >> 0; +} + +__INLINE uint16_t rc_rx_amp_err_wr_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_RX_ERROR_WR_ADDR); + return ((localVal & ((uint32_t)0x03FF0000)) >> 16); +} + +__INLINE void rc_rx_amp_err_wr_setf(uint16_t rxamperrwr) +{ + ASSERT_ERR((((uint32_t)rxamperrwr << 16) & ~((uint32_t)0x03FF0000)) == 0); + REG_PL_WR(RC_RX_ERROR_WR_ADDR, (REG_PL_RD(RC_RX_ERROR_WR_ADDR) & ~((uint32_t)0x03FF0000)) | ((uint32_t)rxamperrwr << 16)); +} + +__INLINE uint16_t rc_rx_phase_err_wr_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_RX_ERROR_WR_ADDR); + return ((localVal & ((uint32_t)0x000003FF)) >> 0); +} + +__INLINE void rc_rx_phase_err_wr_setf(uint16_t rxphaseerrwr) +{ + ASSERT_ERR((((uint32_t)rxphaseerrwr << 0) & ~((uint32_t)0x000003FF)) == 0); + REG_PL_WR(RC_RX_ERROR_WR_ADDR, (REG_PL_RD(RC_RX_ERROR_WR_ADDR) & ~((uint32_t)0x000003FF)) | ((uint32_t)rxphaseerrwr << 0)); +} + +/** + * @brief TX_MODE_CFG register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:30         TEST_PATTERN   0x0
+ *  25:16              I_CONST   0x200
+ *  09:00              Q_CONST   0x200
+ * 
+ */ +#define RC_TX_MODE_CFG_ADDR 0x01050130 +#define RC_TX_MODE_CFG_OFFSET 0x00000130 +#define RC_TX_MODE_CFG_INDEX 0x0000004C +#define RC_TX_MODE_CFG_RESET 0x02000200 + +__INLINE uint32_t rc_tx_mode_cfg_get(void) +{ + return REG_PL_RD(RC_TX_MODE_CFG_ADDR); +} + +__INLINE void rc_tx_mode_cfg_set(uint32_t value) +{ + REG_PL_WR(RC_TX_MODE_CFG_ADDR, value); +} + +// field definitions +#define RC_TEST_PATTERN_MASK ((uint32_t)0xC0000000) +#define RC_TEST_PATTERN_LSB 30 +#define RC_TEST_PATTERN_WIDTH ((uint32_t)0x00000002) +#define RC_I_CONST_MASK ((uint32_t)0x03FF0000) +#define RC_I_CONST_LSB 16 +#define RC_I_CONST_WIDTH ((uint32_t)0x0000000A) +#define RC_Q_CONST_MASK ((uint32_t)0x000003FF) +#define RC_Q_CONST_LSB 0 +#define RC_Q_CONST_WIDTH ((uint32_t)0x0000000A) + +#define RC_TEST_PATTERN_RST 0x0 +#define RC_I_CONST_RST 0x200 +#define RC_Q_CONST_RST 0x200 + +__INLINE void rc_tx_mode_cfg_pack(uint8_t testpattern, uint16_t iconst, uint16_t qconst) +{ + ASSERT_ERR((((uint32_t)testpattern << 30) & ~((uint32_t)0xC0000000)) == 0); + ASSERT_ERR((((uint32_t)iconst << 16) & ~((uint32_t)0x03FF0000)) == 0); + ASSERT_ERR((((uint32_t)qconst << 0) & ~((uint32_t)0x000003FF)) == 0); + REG_PL_WR(RC_TX_MODE_CFG_ADDR, ((uint32_t)testpattern << 30) | ((uint32_t)iconst << 16) | ((uint32_t)qconst << 0)); +} + +__INLINE void rc_tx_mode_cfg_unpack(uint8_t *testpattern, uint16_t *iconst, uint16_t *qconst) +{ + uint32_t localVal = REG_PL_RD(RC_TX_MODE_CFG_ADDR); + + *testpattern = (localVal & ((uint32_t)0xC0000000)) >> 30; + *iconst = (localVal & ((uint32_t)0x03FF0000)) >> 16; + *qconst = (localVal & ((uint32_t)0x000003FF)) >> 0; +} + +__INLINE uint8_t rc_test_pattern_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_TX_MODE_CFG_ADDR); + return ((localVal & ((uint32_t)0xC0000000)) >> 30); +} + +__INLINE void rc_test_pattern_setf(uint8_t testpattern) +{ + ASSERT_ERR((((uint32_t)testpattern << 30) & ~((uint32_t)0xC0000000)) == 0); + REG_PL_WR(RC_TX_MODE_CFG_ADDR, (REG_PL_RD(RC_TX_MODE_CFG_ADDR) & ~((uint32_t)0xC0000000)) | ((uint32_t)testpattern << 30)); +} + +__INLINE uint16_t rc_i_const_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_TX_MODE_CFG_ADDR); + return ((localVal & ((uint32_t)0x03FF0000)) >> 16); +} + +__INLINE void rc_i_const_setf(uint16_t iconst) +{ + ASSERT_ERR((((uint32_t)iconst << 16) & ~((uint32_t)0x03FF0000)) == 0); + REG_PL_WR(RC_TX_MODE_CFG_ADDR, (REG_PL_RD(RC_TX_MODE_CFG_ADDR) & ~((uint32_t)0x03FF0000)) | ((uint32_t)iconst << 16)); +} + +__INLINE uint16_t rc_q_const_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_TX_MODE_CFG_ADDR); + return ((localVal & ((uint32_t)0x000003FF)) >> 0); +} + +__INLINE void rc_q_const_setf(uint16_t qconst) +{ + ASSERT_ERR((((uint32_t)qconst << 0) & ~((uint32_t)0x000003FF)) == 0); + REG_PL_WR(RC_TX_MODE_CFG_ADDR, (REG_PL_RD(RC_TX_MODE_CFG_ADDR) & ~((uint32_t)0x000003FF)) | ((uint32_t)qconst << 0)); +} + +/** + * @brief TX_SIN_CFG register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:22             TX_SIN_F   0x0
+ *  17:16          TX_SIN_MODE   0x0
+ *  15:12           TX_SIN_AMP   0x0
+ * 
+ */ +#define RC_TX_SIN_CFG_ADDR 0x01050134 +#define RC_TX_SIN_CFG_OFFSET 0x00000134 +#define RC_TX_SIN_CFG_INDEX 0x0000004D +#define RC_TX_SIN_CFG_RESET 0x00000000 + +__INLINE uint32_t rc_tx_sin_cfg_get(void) +{ + return REG_PL_RD(RC_TX_SIN_CFG_ADDR); +} + +__INLINE void rc_tx_sin_cfg_set(uint32_t value) +{ + REG_PL_WR(RC_TX_SIN_CFG_ADDR, value); +} + +// field definitions +#define RC_TX_SIN_F_MASK ((uint32_t)0xFFC00000) +#define RC_TX_SIN_F_LSB 22 +#define RC_TX_SIN_F_WIDTH ((uint32_t)0x0000000A) +#define RC_TX_SIN_MODE_MASK ((uint32_t)0x00030000) +#define RC_TX_SIN_MODE_LSB 16 +#define RC_TX_SIN_MODE_WIDTH ((uint32_t)0x00000002) +#define RC_TX_SIN_AMP_MASK ((uint32_t)0x0000F000) +#define RC_TX_SIN_AMP_LSB 12 +#define RC_TX_SIN_AMP_WIDTH ((uint32_t)0x00000004) + +#define RC_TX_SIN_F_RST 0x0 +#define RC_TX_SIN_MODE_RST 0x0 +#define RC_TX_SIN_AMP_RST 0x0 + +__INLINE void rc_tx_sin_cfg_pack(uint16_t txsinf, uint8_t txsinmode, uint8_t txsinamp) +{ + ASSERT_ERR((((uint32_t)txsinf << 22) & ~((uint32_t)0xFFC00000)) == 0); + ASSERT_ERR((((uint32_t)txsinmode << 16) & ~((uint32_t)0x00030000)) == 0); + ASSERT_ERR((((uint32_t)txsinamp << 12) & ~((uint32_t)0x0000F000)) == 0); + REG_PL_WR(RC_TX_SIN_CFG_ADDR, ((uint32_t)txsinf << 22) | ((uint32_t)txsinmode << 16) | ((uint32_t)txsinamp << 12)); +} + +__INLINE void rc_tx_sin_cfg_unpack(uint16_t *txsinf, uint8_t *txsinmode, uint8_t *txsinamp) +{ + uint32_t localVal = REG_PL_RD(RC_TX_SIN_CFG_ADDR); + + *txsinf = (localVal & ((uint32_t)0xFFC00000)) >> 22; + *txsinmode = (localVal & ((uint32_t)0x00030000)) >> 16; + *txsinamp = (localVal & ((uint32_t)0x0000F000)) >> 12; +} + +__INLINE uint16_t rc_tx_sin_f_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_TX_SIN_CFG_ADDR); + return ((localVal & ((uint32_t)0xFFC00000)) >> 22); +} + +__INLINE void rc_tx_sin_f_setf(uint16_t txsinf) +{ + ASSERT_ERR((((uint32_t)txsinf << 22) & ~((uint32_t)0xFFC00000)) == 0); + REG_PL_WR(RC_TX_SIN_CFG_ADDR, (REG_PL_RD(RC_TX_SIN_CFG_ADDR) & ~((uint32_t)0xFFC00000)) | ((uint32_t)txsinf << 22)); +} + +__INLINE uint8_t rc_tx_sin_mode_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_TX_SIN_CFG_ADDR); + return ((localVal & ((uint32_t)0x00030000)) >> 16); +} + +__INLINE void rc_tx_sin_mode_setf(uint8_t txsinmode) +{ + ASSERT_ERR((((uint32_t)txsinmode << 16) & ~((uint32_t)0x00030000)) == 0); + REG_PL_WR(RC_TX_SIN_CFG_ADDR, (REG_PL_RD(RC_TX_SIN_CFG_ADDR) & ~((uint32_t)0x00030000)) | ((uint32_t)txsinmode << 16)); +} + +__INLINE uint8_t rc_tx_sin_amp_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_TX_SIN_CFG_ADDR); + return ((localVal & ((uint32_t)0x0000F000)) >> 12); +} + +__INLINE void rc_tx_sin_amp_setf(uint8_t txsinamp) +{ + ASSERT_ERR((((uint32_t)txsinamp << 12) & ~((uint32_t)0x0000F000)) == 0); + REG_PL_WR(RC_TX_SIN_CFG_ADDR, (REG_PL_RD(RC_TX_SIN_CFG_ADDR) & ~((uint32_t)0x0000F000)) | ((uint32_t)txsinamp << 12)); +} + +/** + * @brief TX_DC_COMP register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  25:16         TX_I_DC_COMP   0x200
+ *  09:00         TX_Q_DC_COMP   0x200
+ * 
+ */ +#define RC_TX_DC_COMP_ADDR 0x0105013C +#define RC_TX_DC_COMP_OFFSET 0x0000013C +#define RC_TX_DC_COMP_INDEX 0x0000004F +#define RC_TX_DC_COMP_RESET 0x02000200 + +__INLINE uint32_t rc_tx_dc_comp_get(void) +{ + return REG_PL_RD(RC_TX_DC_COMP_ADDR); +} + +__INLINE void rc_tx_dc_comp_set(uint32_t value) +{ + REG_PL_WR(RC_TX_DC_COMP_ADDR, value); +} + +// field definitions +#define RC_TX_I_DC_COMP_MASK ((uint32_t)0x03FF0000) +#define RC_TX_I_DC_COMP_LSB 16 +#define RC_TX_I_DC_COMP_WIDTH ((uint32_t)0x0000000A) +#define RC_TX_Q_DC_COMP_MASK ((uint32_t)0x000003FF) +#define RC_TX_Q_DC_COMP_LSB 0 +#define RC_TX_Q_DC_COMP_WIDTH ((uint32_t)0x0000000A) + +#define RC_TX_I_DC_COMP_RST 0x200 +#define RC_TX_Q_DC_COMP_RST 0x200 + +__INLINE void rc_tx_dc_comp_pack(uint16_t txidccomp, uint16_t txqdccomp) +{ + ASSERT_ERR((((uint32_t)txidccomp << 16) & ~((uint32_t)0x03FF0000)) == 0); + ASSERT_ERR((((uint32_t)txqdccomp << 0) & ~((uint32_t)0x000003FF)) == 0); + REG_PL_WR(RC_TX_DC_COMP_ADDR, ((uint32_t)txidccomp << 16) | ((uint32_t)txqdccomp << 0)); +} + +__INLINE void rc_tx_dc_comp_unpack(uint16_t *txidccomp, uint16_t *txqdccomp) +{ + uint32_t localVal = REG_PL_RD(RC_TX_DC_COMP_ADDR); + + *txidccomp = (localVal & ((uint32_t)0x03FF0000)) >> 16; + *txqdccomp = (localVal & ((uint32_t)0x000003FF)) >> 0; +} + +__INLINE uint16_t rc_tx_i_dc_comp_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_TX_DC_COMP_ADDR); + return ((localVal & ((uint32_t)0x03FF0000)) >> 16); +} + +__INLINE void rc_tx_i_dc_comp_setf(uint16_t txidccomp) +{ + ASSERT_ERR((((uint32_t)txidccomp << 16) & ~((uint32_t)0x03FF0000)) == 0); + REG_PL_WR(RC_TX_DC_COMP_ADDR, (REG_PL_RD(RC_TX_DC_COMP_ADDR) & ~((uint32_t)0x03FF0000)) | ((uint32_t)txidccomp << 16)); +} + +__INLINE uint16_t rc_tx_q_dc_comp_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_TX_DC_COMP_ADDR); + return ((localVal & ((uint32_t)0x000003FF)) >> 0); +} + +__INLINE void rc_tx_q_dc_comp_setf(uint16_t txqdccomp) +{ + ASSERT_ERR((((uint32_t)txqdccomp << 0) & ~((uint32_t)0x000003FF)) == 0); + REG_PL_WR(RC_TX_DC_COMP_ADDR, (REG_PL_RD(RC_TX_DC_COMP_ADDR) & ~((uint32_t)0x000003FF)) | ((uint32_t)txqdccomp << 0)); +} + +/** + * @brief TX_GAIN_COMP register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  25:16       TX_I_GAIN_COMP   0x3FF
+ *  09:00       TX_Q_GAIN_COMP   0x3FF
+ * 
+ */ +#define RC_TX_GAIN_COMP_ADDR 0x01050140 +#define RC_TX_GAIN_COMP_OFFSET 0x00000140 +#define RC_TX_GAIN_COMP_INDEX 0x00000050 +#define RC_TX_GAIN_COMP_RESET 0x03FF03FF + +__INLINE uint32_t rc_tx_gain_comp_get(void) +{ + return REG_PL_RD(RC_TX_GAIN_COMP_ADDR); +} + +__INLINE void rc_tx_gain_comp_set(uint32_t value) +{ + REG_PL_WR(RC_TX_GAIN_COMP_ADDR, value); +} + +// field definitions +#define RC_TX_I_GAIN_COMP_MASK ((uint32_t)0x03FF0000) +#define RC_TX_I_GAIN_COMP_LSB 16 +#define RC_TX_I_GAIN_COMP_WIDTH ((uint32_t)0x0000000A) +#define RC_TX_Q_GAIN_COMP_MASK ((uint32_t)0x000003FF) +#define RC_TX_Q_GAIN_COMP_LSB 0 +#define RC_TX_Q_GAIN_COMP_WIDTH ((uint32_t)0x0000000A) + +#define RC_TX_I_GAIN_COMP_RST 0x3FF +#define RC_TX_Q_GAIN_COMP_RST 0x3FF + +__INLINE void rc_tx_gain_comp_pack(uint16_t txigaincomp, uint16_t txqgaincomp) +{ + ASSERT_ERR((((uint32_t)txigaincomp << 16) & ~((uint32_t)0x03FF0000)) == 0); + ASSERT_ERR((((uint32_t)txqgaincomp << 0) & ~((uint32_t)0x000003FF)) == 0); + REG_PL_WR(RC_TX_GAIN_COMP_ADDR, ((uint32_t)txigaincomp << 16) | ((uint32_t)txqgaincomp << 0)); +} + +__INLINE void rc_tx_gain_comp_unpack(uint16_t *txigaincomp, uint16_t *txqgaincomp) +{ + uint32_t localVal = REG_PL_RD(RC_TX_GAIN_COMP_ADDR); + + *txigaincomp = (localVal & ((uint32_t)0x03FF0000)) >> 16; + *txqgaincomp = (localVal & ((uint32_t)0x000003FF)) >> 0; +} + +__INLINE uint16_t rc_tx_i_gain_comp_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_TX_GAIN_COMP_ADDR); + return ((localVal & ((uint32_t)0x03FF0000)) >> 16); +} + +__INLINE void rc_tx_i_gain_comp_setf(uint16_t txigaincomp) +{ + ASSERT_ERR((((uint32_t)txigaincomp << 16) & ~((uint32_t)0x03FF0000)) == 0); + REG_PL_WR(RC_TX_GAIN_COMP_ADDR, (REG_PL_RD(RC_TX_GAIN_COMP_ADDR) & ~((uint32_t)0x03FF0000)) | ((uint32_t)txigaincomp << 16)); +} + +__INLINE uint16_t rc_tx_q_gain_comp_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_TX_GAIN_COMP_ADDR); + return ((localVal & ((uint32_t)0x000003FF)) >> 0); +} + +__INLINE void rc_tx_q_gain_comp_setf(uint16_t txqgaincomp) +{ + ASSERT_ERR((((uint32_t)txqgaincomp << 0) & ~((uint32_t)0x000003FF)) == 0); + REG_PL_WR(RC_TX_GAIN_COMP_ADDR, (REG_PL_RD(RC_TX_GAIN_COMP_ADDR) & ~((uint32_t)0x000003FF)) | ((uint32_t)txqgaincomp << 0)); +} + +/** + * @brief TX_PHASE_TY2_COMP register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  25:16        TX_PHASE_COMP   0x200
+ *  09:00          TX_TY2_COMP   0x200
+ * 
+ */ +#define RC_TX_PHASE_TY2_COMP_ADDR 0x01050144 +#define RC_TX_PHASE_TY2_COMP_OFFSET 0x00000144 +#define RC_TX_PHASE_TY2_COMP_INDEX 0x00000051 +#define RC_TX_PHASE_TY2_COMP_RESET 0x02000200 + +__INLINE uint32_t rc_tx_phase_ty2_comp_get(void) +{ + return REG_PL_RD(RC_TX_PHASE_TY2_COMP_ADDR); +} + +__INLINE void rc_tx_phase_ty2_comp_set(uint32_t value) +{ + REG_PL_WR(RC_TX_PHASE_TY2_COMP_ADDR, value); +} + +// field definitions +#define RC_TX_PHASE_COMP_MASK ((uint32_t)0x03FF0000) +#define RC_TX_PHASE_COMP_LSB 16 +#define RC_TX_PHASE_COMP_WIDTH ((uint32_t)0x0000000A) +#define RC_TX_TY2_COMP_MASK ((uint32_t)0x000003FF) +#define RC_TX_TY2_COMP_LSB 0 +#define RC_TX_TY2_COMP_WIDTH ((uint32_t)0x0000000A) + +#define RC_TX_PHASE_COMP_RST 0x200 +#define RC_TX_TY2_COMP_RST 0x200 + +__INLINE void rc_tx_phase_ty2_comp_pack(uint16_t txphasecomp, uint16_t txty2comp) +{ + ASSERT_ERR((((uint32_t)txphasecomp << 16) & ~((uint32_t)0x03FF0000)) == 0); + ASSERT_ERR((((uint32_t)txty2comp << 0) & ~((uint32_t)0x000003FF)) == 0); + REG_PL_WR(RC_TX_PHASE_TY2_COMP_ADDR, ((uint32_t)txphasecomp << 16) | ((uint32_t)txty2comp << 0)); +} + +__INLINE void rc_tx_phase_ty2_comp_unpack(uint16_t *txphasecomp, uint16_t *txty2comp) +{ + uint32_t localVal = REG_PL_RD(RC_TX_PHASE_TY2_COMP_ADDR); + + *txphasecomp = (localVal & ((uint32_t)0x03FF0000)) >> 16; + *txty2comp = (localVal & ((uint32_t)0x000003FF)) >> 0; +} + +__INLINE uint16_t rc_tx_phase_comp_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_TX_PHASE_TY2_COMP_ADDR); + return ((localVal & ((uint32_t)0x03FF0000)) >> 16); +} + +__INLINE void rc_tx_phase_comp_setf(uint16_t txphasecomp) +{ + ASSERT_ERR((((uint32_t)txphasecomp << 16) & ~((uint32_t)0x03FF0000)) == 0); + REG_PL_WR(RC_TX_PHASE_TY2_COMP_ADDR, (REG_PL_RD(RC_TX_PHASE_TY2_COMP_ADDR) & ~((uint32_t)0x03FF0000)) | ((uint32_t)txphasecomp << 16)); +} + +__INLINE uint16_t rc_tx_ty2_comp_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_TX_PHASE_TY2_COMP_ADDR); + return ((localVal & ((uint32_t)0x000003FF)) >> 0); +} + +__INLINE void rc_tx_ty2_comp_setf(uint16_t txty2comp) +{ + ASSERT_ERR((((uint32_t)txty2comp << 0) & ~((uint32_t)0x000003FF)) == 0); + REG_PL_WR(RC_TX_PHASE_TY2_COMP_ADDR, (REG_PL_RD(RC_TX_PHASE_TY2_COMP_ADDR) & ~((uint32_t)0x000003FF)) | ((uint32_t)txty2comp << 0)); +} + +/** + * @brief TX_OTHER_CFG register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31           TX_IQ_SWAP   0
+ *  30:21     IQ_CONSTANT_POUT   0x0
+ *  19:16          TX_PRE_GAIN   0x0
+ *  15:06   IQ_CONSTANT_IQCAL_P   0x0
+ * 
+ */ +#define RC_TX_OTHER_CFG_ADDR 0x01050148 +#define RC_TX_OTHER_CFG_OFFSET 0x00000148 +#define RC_TX_OTHER_CFG_INDEX 0x00000052 +#define RC_TX_OTHER_CFG_RESET 0x00000000 + +__INLINE uint32_t rc_tx_other_cfg_get(void) +{ + return REG_PL_RD(RC_TX_OTHER_CFG_ADDR); +} + +__INLINE void rc_tx_other_cfg_set(uint32_t value) +{ + REG_PL_WR(RC_TX_OTHER_CFG_ADDR, value); +} + +// field definitions +#define RC_TX_IQ_SWAP_BIT ((uint32_t)0x80000000) +#define RC_TX_IQ_SWAP_POS 31 +#define RC_IQ_CONSTANT_POUT_MASK ((uint32_t)0x7FE00000) +#define RC_IQ_CONSTANT_POUT_LSB 21 +#define RC_IQ_CONSTANT_POUT_WIDTH ((uint32_t)0x0000000A) +#define RC_TX_PRE_GAIN_MASK ((uint32_t)0x000F0000) +#define RC_TX_PRE_GAIN_LSB 16 +#define RC_TX_PRE_GAIN_WIDTH ((uint32_t)0x00000004) +#define RC_IQ_CONSTANT_IQCAL_P_MASK ((uint32_t)0x0000FFC0) +#define RC_IQ_CONSTANT_IQCAL_P_LSB 6 +#define RC_IQ_CONSTANT_IQCAL_P_WIDTH ((uint32_t)0x0000000A) + +#define RC_TX_IQ_SWAP_RST 0x0 +#define RC_IQ_CONSTANT_POUT_RST 0x0 +#define RC_TX_PRE_GAIN_RST 0x0 +#define RC_IQ_CONSTANT_IQCAL_P_RST 0x0 + +__INLINE void rc_tx_other_cfg_pack(uint8_t txiqswap, uint16_t iqconstantpout, uint8_t txpregain, uint16_t iqconstantiqcalp) +{ + ASSERT_ERR((((uint32_t)txiqswap << 31) & ~((uint32_t)0x80000000)) == 0); + ASSERT_ERR((((uint32_t)iqconstantpout << 21) & ~((uint32_t)0x7FE00000)) == 0); + ASSERT_ERR((((uint32_t)txpregain << 16) & ~((uint32_t)0x000F0000)) == 0); + ASSERT_ERR((((uint32_t)iqconstantiqcalp << 6) & ~((uint32_t)0x0000FFC0)) == 0); + REG_PL_WR(RC_TX_OTHER_CFG_ADDR, ((uint32_t)txiqswap << 31) | ((uint32_t)iqconstantpout << 21) | ((uint32_t)txpregain << 16) | ((uint32_t)iqconstantiqcalp << 6)); +} + +__INLINE void rc_tx_other_cfg_unpack(uint8_t *txiqswap, uint16_t *iqconstantpout, uint8_t *txpregain, uint16_t *iqconstantiqcalp) +{ + uint32_t localVal = REG_PL_RD(RC_TX_OTHER_CFG_ADDR); + + *txiqswap = (localVal & ((uint32_t)0x80000000)) >> 31; + *iqconstantpout = (localVal & ((uint32_t)0x7FE00000)) >> 21; + *txpregain = (localVal & ((uint32_t)0x000F0000)) >> 16; + *iqconstantiqcalp = (localVal & ((uint32_t)0x0000FFC0)) >> 6; +} + +__INLINE uint8_t rc_tx_iq_swap_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_TX_OTHER_CFG_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +__INLINE void rc_tx_iq_swap_setf(uint8_t txiqswap) +{ + ASSERT_ERR((((uint32_t)txiqswap << 31) & ~((uint32_t)0x80000000)) == 0); + REG_PL_WR(RC_TX_OTHER_CFG_ADDR, (REG_PL_RD(RC_TX_OTHER_CFG_ADDR) & ~((uint32_t)0x80000000)) | ((uint32_t)txiqswap << 31)); +} + +__INLINE uint16_t rc_iq_constant_pout_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_TX_OTHER_CFG_ADDR); + return ((localVal & ((uint32_t)0x7FE00000)) >> 21); +} + +__INLINE void rc_iq_constant_pout_setf(uint16_t iqconstantpout) +{ + ASSERT_ERR((((uint32_t)iqconstantpout << 21) & ~((uint32_t)0x7FE00000)) == 0); + REG_PL_WR(RC_TX_OTHER_CFG_ADDR, (REG_PL_RD(RC_TX_OTHER_CFG_ADDR) & ~((uint32_t)0x7FE00000)) | ((uint32_t)iqconstantpout << 21)); +} + +__INLINE uint8_t rc_tx_pre_gain_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_TX_OTHER_CFG_ADDR); + return ((localVal & ((uint32_t)0x000F0000)) >> 16); +} + +__INLINE void rc_tx_pre_gain_setf(uint8_t txpregain) +{ + ASSERT_ERR((((uint32_t)txpregain << 16) & ~((uint32_t)0x000F0000)) == 0); + REG_PL_WR(RC_TX_OTHER_CFG_ADDR, (REG_PL_RD(RC_TX_OTHER_CFG_ADDR) & ~((uint32_t)0x000F0000)) | ((uint32_t)txpregain << 16)); +} + +__INLINE uint16_t rc_iq_constant_iqcal_p_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_TX_OTHER_CFG_ADDR); + return ((localVal & ((uint32_t)0x0000FFC0)) >> 6); +} + +__INLINE void rc_iq_constant_iqcal_p_setf(uint16_t iqconstantiqcalp) +{ + ASSERT_ERR((((uint32_t)iqconstantiqcalp << 6) & ~((uint32_t)0x0000FFC0)) == 0); + REG_PL_WR(RC_TX_OTHER_CFG_ADDR, (REG_PL_RD(RC_TX_OTHER_CFG_ADDR) & ~((uint32_t)0x0000FFC0)) | ((uint32_t)iqconstantiqcalp << 6)); +} + +/** + * @brief AGC_CFG register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31         AGC_MAP_MODE   0
+ *  30:29           AGC_LNA_RD   0x0
+ *     28           AGC_BUF_RD   0
+ *  27:24           AGC_PGA_RD   0x0
+ *  23:16              TSSI_RD   0x0
+ *  15:14           ST_SAR_ADC   0x1
+ *  13:12            ST_RX_ADC   0x1
+ *  11:10              TX_DC_N   0x1
+ *     09              DSEL_VA   0
+ *  08:01         TSSI_POUT_TH   0x40
+ *     00         ST_RX_ADC_IQ   0
+ * 
+ */ +#define RC_AGC_CFG_ADDR 0x01050150 +#define RC_AGC_CFG_OFFSET 0x00000150 +#define RC_AGC_CFG_INDEX 0x00000054 +#define RC_AGC_CFG_RESET 0x00005480 + +__INLINE uint32_t rc_agc_cfg_get(void) +{ + return REG_PL_RD(RC_AGC_CFG_ADDR); +} + +__INLINE void rc_agc_cfg_set(uint32_t value) +{ + REG_PL_WR(RC_AGC_CFG_ADDR, value); +} + +// field definitions +#define RC_AGC_MAP_MODE_BIT ((uint32_t)0x80000000) +#define RC_AGC_MAP_MODE_POS 31 +#define RC_AGC_LNA_RD_MASK ((uint32_t)0x60000000) +#define RC_AGC_LNA_RD_LSB 29 +#define RC_AGC_LNA_RD_WIDTH ((uint32_t)0x00000002) +#define RC_AGC_BUF_RD_BIT ((uint32_t)0x10000000) +#define RC_AGC_BUF_RD_POS 28 +#define RC_AGC_PGA_RD_MASK ((uint32_t)0x0F000000) +#define RC_AGC_PGA_RD_LSB 24 +#define RC_AGC_PGA_RD_WIDTH ((uint32_t)0x00000004) +#define RC_TSSI_RD_MASK ((uint32_t)0x00FF0000) +#define RC_TSSI_RD_LSB 16 +#define RC_TSSI_RD_WIDTH ((uint32_t)0x00000008) +#define RC_ST_SAR_ADC_MASK ((uint32_t)0x0000C000) +#define RC_ST_SAR_ADC_LSB 14 +#define RC_ST_SAR_ADC_WIDTH ((uint32_t)0x00000002) +#define RC_ST_RX_ADC_MASK ((uint32_t)0x00003000) +#define RC_ST_RX_ADC_LSB 12 +#define RC_ST_RX_ADC_WIDTH ((uint32_t)0x00000002) +#define RC_TX_DC_N_MASK ((uint32_t)0x00000C00) +#define RC_TX_DC_N_LSB 10 +#define RC_TX_DC_N_WIDTH ((uint32_t)0x00000002) +#define RC_DSEL_VA_BIT ((uint32_t)0x00000200) +#define RC_DSEL_VA_POS 9 +#define RC_TSSI_POUT_TH_MASK ((uint32_t)0x000001FE) +#define RC_TSSI_POUT_TH_LSB 1 +#define RC_TSSI_POUT_TH_WIDTH ((uint32_t)0x00000008) +#define RC_ST_RX_ADC_IQ_BIT ((uint32_t)0x00000001) +#define RC_ST_RX_ADC_IQ_POS 0 + +#define RC_AGC_MAP_MODE_RST 0x0 +#define RC_AGC_LNA_RD_RST 0x0 +#define RC_AGC_BUF_RD_RST 0x0 +#define RC_AGC_PGA_RD_RST 0x0 +#define RC_TSSI_RD_RST 0x0 +#define RC_ST_SAR_ADC_RST 0x1 +#define RC_ST_RX_ADC_RST 0x1 +#define RC_TX_DC_N_RST 0x1 +#define RC_DSEL_VA_RST 0x0 +#define RC_TSSI_POUT_TH_RST 0x40 +#define RC_ST_RX_ADC_IQ_RST 0x0 + +__INLINE void rc_agc_cfg_pack(uint8_t agcmapmode, uint8_t agclnard, uint8_t agcbufrd, uint8_t agcpgard, uint8_t tssird, uint8_t stsaradc, uint8_t strxadc, uint8_t txdcn, uint8_t dselva, uint8_t tssipoutth, uint8_t strxadciq) +{ + ASSERT_ERR((((uint32_t)agcmapmode << 31) & ~((uint32_t)0x80000000)) == 0); + ASSERT_ERR((((uint32_t)agclnard << 29) & ~((uint32_t)0x60000000)) == 0); + ASSERT_ERR((((uint32_t)agcbufrd << 28) & ~((uint32_t)0x10000000)) == 0); + ASSERT_ERR((((uint32_t)agcpgard << 24) & ~((uint32_t)0x0F000000)) == 0); + ASSERT_ERR((((uint32_t)tssird << 16) & ~((uint32_t)0x00FF0000)) == 0); + ASSERT_ERR((((uint32_t)stsaradc << 14) & ~((uint32_t)0x0000C000)) == 0); + ASSERT_ERR((((uint32_t)strxadc << 12) & ~((uint32_t)0x00003000)) == 0); + ASSERT_ERR((((uint32_t)txdcn << 10) & ~((uint32_t)0x00000C00)) == 0); + ASSERT_ERR((((uint32_t)dselva << 9) & ~((uint32_t)0x00000200)) == 0); + ASSERT_ERR((((uint32_t)tssipoutth << 1) & ~((uint32_t)0x000001FE)) == 0); + ASSERT_ERR((((uint32_t)strxadciq << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(RC_AGC_CFG_ADDR, ((uint32_t)agcmapmode << 31) | ((uint32_t)agclnard << 29) | ((uint32_t)agcbufrd << 28) | ((uint32_t)agcpgard << 24) | ((uint32_t)tssird << 16) | ((uint32_t)stsaradc << 14) | ((uint32_t)strxadc << 12) | ((uint32_t)txdcn << 10) | ((uint32_t)dselva << 9) | ((uint32_t)tssipoutth << 1) | ((uint32_t)strxadciq << 0)); +} + +__INLINE void rc_agc_cfg_unpack(uint8_t *agcmapmode, uint8_t *agclnard, uint8_t *agcbufrd, uint8_t *agcpgard, uint8_t *tssird, uint8_t *stsaradc, uint8_t *strxadc, uint8_t *txdcn, uint8_t *dselva, uint8_t *tssipoutth, uint8_t *strxadciq) +{ + uint32_t localVal = REG_PL_RD(RC_AGC_CFG_ADDR); + + *agcmapmode = (localVal & ((uint32_t)0x80000000)) >> 31; + *agclnard = (localVal & ((uint32_t)0x60000000)) >> 29; + *agcbufrd = (localVal & ((uint32_t)0x10000000)) >> 28; + *agcpgard = (localVal & ((uint32_t)0x0F000000)) >> 24; + *tssird = (localVal & ((uint32_t)0x00FF0000)) >> 16; + *stsaradc = (localVal & ((uint32_t)0x0000C000)) >> 14; + *strxadc = (localVal & ((uint32_t)0x00003000)) >> 12; + *txdcn = (localVal & ((uint32_t)0x00000C00)) >> 10; + *dselva = (localVal & ((uint32_t)0x00000200)) >> 9; + *tssipoutth = (localVal & ((uint32_t)0x000001FE)) >> 1; + *strxadciq = (localVal & ((uint32_t)0x00000001)) >> 0; +} + +__INLINE uint8_t rc_agc_map_mode_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_AGC_CFG_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +__INLINE void rc_agc_map_mode_setf(uint8_t agcmapmode) +{ + ASSERT_ERR((((uint32_t)agcmapmode << 31) & ~((uint32_t)0x80000000)) == 0); + REG_PL_WR(RC_AGC_CFG_ADDR, (REG_PL_RD(RC_AGC_CFG_ADDR) & ~((uint32_t)0x80000000)) | ((uint32_t)agcmapmode << 31)); +} + +__INLINE uint8_t rc_agc_lna_rd_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_AGC_CFG_ADDR); + return ((localVal & ((uint32_t)0x60000000)) >> 29); +} + +__INLINE void rc_agc_lna_rd_setf(uint8_t agclnard) +{ + ASSERT_ERR((((uint32_t)agclnard << 29) & ~((uint32_t)0x60000000)) == 0); + REG_PL_WR(RC_AGC_CFG_ADDR, (REG_PL_RD(RC_AGC_CFG_ADDR) & ~((uint32_t)0x60000000)) | ((uint32_t)agclnard << 29)); +} + +__INLINE uint8_t rc_agc_buf_rd_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_AGC_CFG_ADDR); + return ((localVal & ((uint32_t)0x10000000)) >> 28); +} + +__INLINE void rc_agc_buf_rd_setf(uint8_t agcbufrd) +{ + ASSERT_ERR((((uint32_t)agcbufrd << 28) & ~((uint32_t)0x10000000)) == 0); + REG_PL_WR(RC_AGC_CFG_ADDR, (REG_PL_RD(RC_AGC_CFG_ADDR) & ~((uint32_t)0x10000000)) | ((uint32_t)agcbufrd << 28)); +} + +__INLINE uint8_t rc_agc_pga_rd_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_AGC_CFG_ADDR); + return ((localVal & ((uint32_t)0x0F000000)) >> 24); +} + +__INLINE void rc_agc_pga_rd_setf(uint8_t agcpgard) +{ + ASSERT_ERR((((uint32_t)agcpgard << 24) & ~((uint32_t)0x0F000000)) == 0); + REG_PL_WR(RC_AGC_CFG_ADDR, (REG_PL_RD(RC_AGC_CFG_ADDR) & ~((uint32_t)0x0F000000)) | ((uint32_t)agcpgard << 24)); +} + +__INLINE uint8_t rc_tssi_rd_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_AGC_CFG_ADDR); + return ((localVal & ((uint32_t)0x00FF0000)) >> 16); +} + +__INLINE void rc_tssi_rd_setf(uint8_t tssird) +{ + ASSERT_ERR((((uint32_t)tssird << 16) & ~((uint32_t)0x00FF0000)) == 0); + REG_PL_WR(RC_AGC_CFG_ADDR, (REG_PL_RD(RC_AGC_CFG_ADDR) & ~((uint32_t)0x00FF0000)) | ((uint32_t)tssird << 16)); +} + +__INLINE uint8_t rc_st_sar_adc_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_AGC_CFG_ADDR); + return ((localVal & ((uint32_t)0x0000C000)) >> 14); +} + +__INLINE void rc_st_sar_adc_setf(uint8_t stsaradc) +{ + ASSERT_ERR((((uint32_t)stsaradc << 14) & ~((uint32_t)0x0000C000)) == 0); + REG_PL_WR(RC_AGC_CFG_ADDR, (REG_PL_RD(RC_AGC_CFG_ADDR) & ~((uint32_t)0x0000C000)) | ((uint32_t)stsaradc << 14)); +} + +__INLINE uint8_t rc_st_rx_adc_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_AGC_CFG_ADDR); + return ((localVal & ((uint32_t)0x00003000)) >> 12); +} + +__INLINE void rc_st_rx_adc_setf(uint8_t strxadc) +{ + ASSERT_ERR((((uint32_t)strxadc << 12) & ~((uint32_t)0x00003000)) == 0); + REG_PL_WR(RC_AGC_CFG_ADDR, (REG_PL_RD(RC_AGC_CFG_ADDR) & ~((uint32_t)0x00003000)) | ((uint32_t)strxadc << 12)); +} + +__INLINE uint8_t rc_tx_dc_n_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_AGC_CFG_ADDR); + return ((localVal & ((uint32_t)0x00000C00)) >> 10); +} + +__INLINE void rc_tx_dc_n_setf(uint8_t txdcn) +{ + ASSERT_ERR((((uint32_t)txdcn << 10) & ~((uint32_t)0x00000C00)) == 0); + REG_PL_WR(RC_AGC_CFG_ADDR, (REG_PL_RD(RC_AGC_CFG_ADDR) & ~((uint32_t)0x00000C00)) | ((uint32_t)txdcn << 10)); +} + +__INLINE uint8_t rc_dsel_va_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_AGC_CFG_ADDR); + return ((localVal & ((uint32_t)0x00000200)) >> 9); +} + +__INLINE void rc_dsel_va_setf(uint8_t dselva) +{ + ASSERT_ERR((((uint32_t)dselva << 9) & ~((uint32_t)0x00000200)) == 0); + REG_PL_WR(RC_AGC_CFG_ADDR, (REG_PL_RD(RC_AGC_CFG_ADDR) & ~((uint32_t)0x00000200)) | ((uint32_t)dselva << 9)); +} + +__INLINE uint8_t rc_tssi_pout_th_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_AGC_CFG_ADDR); + return ((localVal & ((uint32_t)0x000001FE)) >> 1); +} + +__INLINE void rc_tssi_pout_th_setf(uint8_t tssipoutth) +{ + ASSERT_ERR((((uint32_t)tssipoutth << 1) & ~((uint32_t)0x000001FE)) == 0); + REG_PL_WR(RC_AGC_CFG_ADDR, (REG_PL_RD(RC_AGC_CFG_ADDR) & ~((uint32_t)0x000001FE)) | ((uint32_t)tssipoutth << 1)); +} + +__INLINE uint8_t rc_st_rx_adc_iq_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_AGC_CFG_ADDR); + return ((localVal & ((uint32_t)0x00000001)) >> 0); +} + +__INLINE void rc_st_rx_adc_iq_setf(uint8_t strxadciq) +{ + ASSERT_ERR((((uint32_t)strxadciq << 0) & ~((uint32_t)0x00000001)) == 0); + REG_PL_WR(RC_AGC_CFG_ADDR, (REG_PL_RD(RC_AGC_CFG_ADDR) & ~((uint32_t)0x00000001)) | ((uint32_t)strxadciq << 0)); +} + +/** + * @brief TRX_SPI_INTLV register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *     31         TRX_BANK_RPT   0
+ *  09:00        TRX_SPI_INTLV   0x40
+ * 
+ */ +#define RC_TRX_SPI_INTLV_ADDR 0x01050170 +#define RC_TRX_SPI_INTLV_OFFSET 0x00000170 +#define RC_TRX_SPI_INTLV_INDEX 0x0000005C +#define RC_TRX_SPI_INTLV_RESET 0x00000040 + +__INLINE uint32_t rc_trx_spi_intlv_get(void) +{ + return REG_PL_RD(RC_TRX_SPI_INTLV_ADDR); +} + +__INLINE void rc_trx_spi_intlv_set(uint32_t value) +{ + REG_PL_WR(RC_TRX_SPI_INTLV_ADDR, value); +} + +// field definitions +#define RC_TRX_BANK_RPT_BIT ((uint32_t)0x80000000) +#define RC_TRX_BANK_RPT_POS 31 +#define RC_TRX_SPI_INTLV_MASK ((uint32_t)0x000003FF) +#define RC_TRX_SPI_INTLV_LSB 0 +#define RC_TRX_SPI_INTLV_WIDTH ((uint32_t)0x0000000A) + +#define RC_TRX_BANK_RPT_RST 0x0 +#define RC_TRX_SPI_INTLV_RST 0x40 + +__INLINE void rc_trx_spi_intlv_unpack(uint8_t *trxbankrpt, uint16_t *trxspiintlv) +{ + uint32_t localVal = REG_PL_RD(RC_TRX_SPI_INTLV_ADDR); + + *trxbankrpt = (localVal & ((uint32_t)0x80000000)) >> 31; + *trxspiintlv = (localVal & ((uint32_t)0x000003FF)) >> 0; +} + +__INLINE uint8_t rc_trx_bank_rpt_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_TRX_SPI_INTLV_ADDR); + return ((localVal & ((uint32_t)0x80000000)) >> 31); +} + +__INLINE uint16_t rc_trx_spi_intlv_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_TRX_SPI_INTLV_ADDR); + return ((localVal & ((uint32_t)0x000003FF)) >> 0); +} + +__INLINE void rc_trx_spi_intlv_setf(uint16_t trxspiintlv) +{ + ASSERT_ERR((((uint32_t)trxspiintlv << 0) & ~((uint32_t)0x000003FF)) == 0); + REG_PL_WR(RC_TRX_SPI_INTLV_ADDR, (uint32_t)trxspiintlv << 0); +} + +/** + * @brief ADDA_REG0 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00            ADDA_REG0   0x0
+ * 
+ */ +#define RC_ADDA_REG0_ADDR 0x01050190 +#define RC_ADDA_REG0_OFFSET 0x00000190 +#define RC_ADDA_REG0_INDEX 0x00000064 +#define RC_ADDA_REG0_RESET 0x00000000 + +__INLINE uint32_t rc_adda_reg0_get(void) +{ + return REG_PL_RD(RC_ADDA_REG0_ADDR); +} + +__INLINE void rc_adda_reg0_set(uint32_t value) +{ + REG_PL_WR(RC_ADDA_REG0_ADDR, value); +} + +// field definitions +#define RC_ADDA_REG0_MASK ((uint32_t)0xFFFFFFFF) +#define RC_ADDA_REG0_LSB 0 +#define RC_ADDA_REG0_WIDTH ((uint32_t)0x00000020) + +#define RC_ADDA_REG0_RST 0x0 + +__INLINE uint32_t rc_adda_reg0_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_ADDA_REG0_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void rc_adda_reg0_setf(uint32_t addareg0) +{ + ASSERT_ERR((((uint32_t)addareg0 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(RC_ADDA_REG0_ADDR, (uint32_t)addareg0 << 0); +} + +/** + * @brief ADDA_REG1 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00            ADDA_REG1   0x0
+ * 
+ */ +#define RC_ADDA_REG1_ADDR 0x01050194 +#define RC_ADDA_REG1_OFFSET 0x00000194 +#define RC_ADDA_REG1_INDEX 0x00000065 +#define RC_ADDA_REG1_RESET 0x00000000 + +__INLINE uint32_t rc_adda_reg1_get(void) +{ + return REG_PL_RD(RC_ADDA_REG1_ADDR); +} + +__INLINE void rc_adda_reg1_set(uint32_t value) +{ + REG_PL_WR(RC_ADDA_REG1_ADDR, value); +} + +// field definitions +#define RC_ADDA_REG1_MASK ((uint32_t)0xFFFFFFFF) +#define RC_ADDA_REG1_LSB 0 +#define RC_ADDA_REG1_WIDTH ((uint32_t)0x00000020) + +#define RC_ADDA_REG1_RST 0x0 + +__INLINE uint32_t rc_adda_reg1_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_ADDA_REG1_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void rc_adda_reg1_setf(uint32_t addareg1) +{ + ASSERT_ERR((((uint32_t)addareg1 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(RC_ADDA_REG1_ADDR, (uint32_t)addareg1 << 0); +} + +/** + * @brief ADDA_REG2 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00            ADDA_REG2   0x0
+ * 
+ */ +#define RC_ADDA_REG2_ADDR 0x01050198 +#define RC_ADDA_REG2_OFFSET 0x00000198 +#define RC_ADDA_REG2_INDEX 0x00000066 +#define RC_ADDA_REG2_RESET 0x00000000 + +__INLINE uint32_t rc_adda_reg2_get(void) +{ + return REG_PL_RD(RC_ADDA_REG2_ADDR); +} + +__INLINE void rc_adda_reg2_set(uint32_t value) +{ + REG_PL_WR(RC_ADDA_REG2_ADDR, value); +} + +// field definitions +#define RC_ADDA_REG2_MASK ((uint32_t)0xFFFFFFFF) +#define RC_ADDA_REG2_LSB 0 +#define RC_ADDA_REG2_WIDTH ((uint32_t)0x00000020) + +#define RC_ADDA_REG2_RST 0x0 + +__INLINE uint32_t rc_adda_reg2_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_ADDA_REG2_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void rc_adda_reg2_setf(uint32_t addareg2) +{ + ASSERT_ERR((((uint32_t)addareg2 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(RC_ADDA_REG2_ADDR, (uint32_t)addareg2 << 0); +} + +/** + * @brief ADDA_REG3 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00            ADDA_REG3   0x0
+ * 
+ */ +#define RC_ADDA_REG3_ADDR 0x0105019C +#define RC_ADDA_REG3_OFFSET 0x0000019C +#define RC_ADDA_REG3_INDEX 0x00000067 +#define RC_ADDA_REG3_RESET 0x00000000 + +__INLINE uint32_t rc_adda_reg3_get(void) +{ + return REG_PL_RD(RC_ADDA_REG3_ADDR); +} + +__INLINE void rc_adda_reg3_set(uint32_t value) +{ + REG_PL_WR(RC_ADDA_REG3_ADDR, value); +} + +// field definitions +#define RC_ADDA_REG3_MASK ((uint32_t)0xFFFFFFFF) +#define RC_ADDA_REG3_LSB 0 +#define RC_ADDA_REG3_WIDTH ((uint32_t)0x00000020) + +#define RC_ADDA_REG3_RST 0x0 + +__INLINE uint32_t rc_adda_reg3_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_ADDA_REG3_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void rc_adda_reg3_setf(uint32_t addareg3) +{ + ASSERT_ERR((((uint32_t)addareg3 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(RC_ADDA_REG3_ADDR, (uint32_t)addareg3 << 0); +} + +/** + * @brief ADDA_REG4 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00            ADDA_REG4   0x0
+ * 
+ */ +#define RC_ADDA_REG4_ADDR 0x010501A0 +#define RC_ADDA_REG4_OFFSET 0x000001A0 +#define RC_ADDA_REG4_INDEX 0x00000068 +#define RC_ADDA_REG4_RESET 0x00000000 + +__INLINE uint32_t rc_adda_reg4_get(void) +{ + return REG_PL_RD(RC_ADDA_REG4_ADDR); +} + +__INLINE void rc_adda_reg4_set(uint32_t value) +{ + REG_PL_WR(RC_ADDA_REG4_ADDR, value); +} + +// field definitions +#define RC_ADDA_REG4_MASK ((uint32_t)0xFFFFFFFF) +#define RC_ADDA_REG4_LSB 0 +#define RC_ADDA_REG4_WIDTH ((uint32_t)0x00000020) + +#define RC_ADDA_REG4_RST 0x0 + +__INLINE uint32_t rc_adda_reg4_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_ADDA_REG4_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void rc_adda_reg4_setf(uint32_t addareg4) +{ + ASSERT_ERR((((uint32_t)addareg4 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(RC_ADDA_REG4_ADDR, (uint32_t)addareg4 << 0); +} + +/** + * @brief ADDA_REG5 register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  31:00            ADDA_REG5   0x0
+ * 
+ */ +#define RC_ADDA_REG5_ADDR 0x010501A4 +#define RC_ADDA_REG5_OFFSET 0x000001A4 +#define RC_ADDA_REG5_INDEX 0x00000069 +#define RC_ADDA_REG5_RESET 0x00000000 + +__INLINE uint32_t rc_adda_reg5_get(void) +{ + return REG_PL_RD(RC_ADDA_REG5_ADDR); +} + +__INLINE void rc_adda_reg5_set(uint32_t value) +{ + REG_PL_WR(RC_ADDA_REG5_ADDR, value); +} + +// field definitions +#define RC_ADDA_REG5_MASK ((uint32_t)0xFFFFFFFF) +#define RC_ADDA_REG5_LSB 0 +#define RC_ADDA_REG5_WIDTH ((uint32_t)0x00000020) + +#define RC_ADDA_REG5_RST 0x0 + +__INLINE uint32_t rc_adda_reg5_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_ADDA_REG5_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0xFFFFFFFF)) == 0); + return (localVal >> 0); +} + +__INLINE void rc_adda_reg5_setf(uint32_t addareg5) +{ + ASSERT_ERR((((uint32_t)addareg5 << 0) & ~((uint32_t)0xFFFFFFFF)) == 0); + REG_PL_WR(RC_ADDA_REG5_ADDR, (uint32_t)addareg5 << 0); +} + +/** + * @brief ADDA_REG_STAT register definition + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  05:00        ADDA_REG_STAT   0x0
+ * 
+ */ +#define RC_ADDA_REG_STAT_ADDR 0x010501A8 +#define RC_ADDA_REG_STAT_OFFSET 0x000001A8 +#define RC_ADDA_REG_STAT_INDEX 0x0000006A +#define RC_ADDA_REG_STAT_RESET 0x00000000 + +__INLINE uint32_t rc_adda_reg_stat_get(void) +{ + return REG_PL_RD(RC_ADDA_REG_STAT_ADDR); +} + +__INLINE void rc_adda_reg_stat_set(uint32_t value) +{ + REG_PL_WR(RC_ADDA_REG_STAT_ADDR, value); +} + +// field definitions +#define RC_ADDA_REG_STAT_MASK ((uint32_t)0x0000003F) +#define RC_ADDA_REG_STAT_LSB 0 +#define RC_ADDA_REG_STAT_WIDTH ((uint32_t)0x00000006) + +#define RC_ADDA_REG_STAT_RST 0x0 + +__INLINE uint8_t rc_adda_reg_stat_getf(void) +{ + uint32_t localVal = REG_PL_RD(RC_ADDA_REG_STAT_ADDR); + ASSERT_ERR((localVal & ~((uint32_t)0x0000003F)) == 0); + return (localVal >> 0); +} + + +#endif // _REG_RC_H_ + diff --git a/beken_os/beken378/driver/dma/dma.c b/beken_os/beken378/driver/dma/dma.c new file mode 100755 index 0000000..5f276bc --- /dev/null +++ b/beken_os/beken378/driver/dma/dma.c @@ -0,0 +1,106 @@ +/** + **************************************************************************************** + * + * @file dma.c + * + * @brief IPC DMA utility functions + * + * Copyright (C) RivieraWaves 2011-2016 + * + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +// for NULL +#include +#include + +#include "dma.h" +#include "reg_dma.h" +#include "co_utils.h" +#include "ke_env.h" +#include "rxl_cntrl.h" +#include "ke_event.h" + +#include "include.h" +#include "arm_arch.h" +#include "mem_pub.h" +#include "uart_pub.h" + +#if CFG_GENERAL_DMA +#include "general_dma_pub.h" +#endif + +struct dma_env_tag dma_env; + +void dma_init(void) +{ + memset(dma_env.last_dma, 0, sizeof(dma_env.last_dma)); + + // configure the channel priorities + dma_channel_priority_set(0x0C); + + // configure the interrupts (enable all interrupts) + dma_int_unmask_set(DMA_LLI_IRQ_MASK); +} + +uint32_t dma_push(struct dma_desc *first, struct dma_desc *last, int channel_idx) +{ + uint32_t push_len = 0; + evt_field_t event = 0; + uint32_t go_on_flag = 1; + UINT32 access_category = 0; + struct dma_desc *ddesc; + + ddesc = first; + while(go_on_flag && ddesc) + { + ASSERT(ddesc->length < 2300); +#if CFG_GENERAL_DMA_ + gdma_memcpy((void *)ddesc->dest, (void *)ddesc->src, ddesc->length); +#else + os_memcpy((void *)ddesc->dest, (void *)ddesc->src, ddesc->length); +#endif + push_len += ddesc->length; + + if(ddesc == last) + { + go_on_flag = 0; + } + + ddesc = (struct dma_desc *)ddesc->next; + } + + switch(channel_idx) + { + case IPC_DMA_CHANNEL_CTRL_RX: + break; + + case IPC_DMA_CHANNEL_DATA_RX: + rxl_dma_int_handler(); + break; + + case IPC_DMA_CHANNEL_CTRL_TX: + break; + + case IPC_DMA_CHANNEL_DATA_TX: + access_category = AC_VI; + event = (ke_get_ac_payload_bit(access_category)); + break; + + default: + break; + } + + if(event) + { + ke_evt_set(event); + } + + return push_len; +} +// eof + diff --git a/beken_os/beken378/driver/dma/dma.h b/beken_os/beken378/driver/dma/dma.h new file mode 100755 index 0000000..5ed1313 --- /dev/null +++ b/beken_os/beken378/driver/dma/dma.h @@ -0,0 +1,179 @@ +/** + **************************************************************************************** + * + * @file dma.h + * + * @brief DMA utility functions + * + * Copyright (C) RivieraWaves 2011-2016 + * + **************************************************************************************** + */ + +#ifndef _IPC_DMA_H_ +#define _IPC_DMA_H_ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "co_int.h" + +// for target dependent macros +#include "rwnx_config.h" + +// for CO_BIT macro +#include "co_math.h" + +// for __INLINE +#include "compiler.h" + +// for register address +#include "reg_dma.h" + + +/** @defgroup DMA DMA + * @ingroup PLATFORM_DRIVERS + * @brief DMA utility functions + * @{ + */ + +/// DMA channel indexes +enum +{ + /// Upload control channel + IPC_DMA_CHANNEL_CTRL_RX, + /// Upload data channel + IPC_DMA_CHANNEL_DATA_RX, + /// Download control channel + IPC_DMA_CHANNEL_CTRL_TX, + /// Download data channel + IPC_DMA_CHANNEL_DATA_TX, + /// Number of DMA channels + IPC_DMA_CHANNEL_MAX, +}; + +/** DMA LLI assignment. This mapping is more important than it looks because of the way + * the interrupts are mapped on the reference IP interrupt controller: + * - LLI0 to 3 are mapped to a single interrupt and therefore the handler of the TX can + * be called directly since the interrupt controller is indexed + * - LLI4 to 7 are mapped to a single interrupt and therefore the handler of the RX can + * be called directly since the interrupt controller is indexed + */ +enum +{ + /// LLI for BK TX queue downloads + IPC_DMA_LLI_DATA_AC0_TX, + /// LLI for BE TX queue downloads + IPC_DMA_LLI_DATA_AC1_TX, + /// LLI for VI TX queue downloads + IPC_DMA_LLI_DATA_AC2_TX, + /// LLI for VO TX queue downloads + IPC_DMA_LLI_DATA_AC3_TX, + /// LLI for BCN TX queue downloads + IPC_DMA_LLI_DATA_BCN_TX, + /// LLI for RX transfers + IPC_DMA_LLI_DATA_RX0, + /// LLI for kernel messages upload + IPC_DMA_LLI_MSG, + /// LLI for debug messages upload + IPC_DMA_LLI_DBG, + /// LLI for BK TX queue confirmation uploads + IPC_DMA_LLI_CFM_AC0_TX, + /// LLI for BE TX queue confirmation uploads + IPC_DMA_LLI_CFM_AC1_TX, + /// LLI for VI TX queue confirmation uploads + IPC_DMA_LLI_CFM_AC2_TX, + /// LLI for VO TX queue confirmation uploads + IPC_DMA_LLI_CFM_AC3_TX, + /// LLI for BCN TX queue confirmation uploads + IPC_DMA_LLI_CFM_BCN_TX, + /// LLI for general purpose DMA downloads + IPC_DMA_LLI_GP_DL, + /// LLI for debug dump uploads + IPC_DMA_LLI_DBG_DUMP, + /// LLI for radar pulses uploads + IPC_DMA_LLI_RD, + /// Number of LLI used + IPC_DMA_LLI_MAX +}; + +#if NX_BEACONING +/// Mask of the DMA LLI IRQs status bits that are assigned for TX +#define IPC_DMA_LLI_TX_MASK 0x001F +/// Mask of the DMA LLI IRQs status bits that are assigned for CFM +#define IPC_DMA_LLI_CFM_MASK 0x1F00 +#else +/// Mask of the DMA LLI IRQs status bits that are assigned for TX +#define IPC_DMA_LLI_TX_MASK 0x000F +/// Mask of the DMA LLI IRQs status bits that are assigned for CFM +#define IPC_DMA_LLI_CFM_MASK 0x0F00 +#endif + +/// Mask of the DMA LLI IRQs status bits that are assigned for RX +#define IPC_DMA_LLI_RX_MASK 0x0020 + +/// Indicate that an LLI counter must be incremented at the end of the LLI process +#define IPC_DMA_LLI_COUNTER_EN 0x0010 +/// Mask of the LLI counter index to increment at the end of the LLI process +#define IPC_DMA_LLI_COUNTER_MASK 0x000F +/// Bit position of the LLI counter index +#define IPC_DMA_LLI_COUNTER_POS 0 + +/// Indicate that an IRQ must be generated at the end of the LLI process +#define IPC_DMA_LLI_IRQ_EN 0x1000 +/// Mask of the LLI IRQ index to generate at the end of the LLI process +#define IPC_DMA_LLI_IRQ_MASK 0x0F00 +/// Bit position of the LLI IRQ index +#define IPC_DMA_LLI_IRQ_POS 8 + +/// Element in the pool of TX DMA bridge descriptors. +struct dma_desc +{ + /** Application subsystem address which is used as source address for DMA payload + * transfer*/ + uint32_t src; + /** Points to the start of the embedded data buffer associated with this descriptor. + * This address acts as the destination address for the DMA payload transfer*/ + uint32_t dest; + /// Complete length of the buffer in memory + uint16_t length; + /// Control word for the DMA engine (e.g. for interrupt generation) + uint16_t ctrl; + /// Pointer to the next element of the chained list + uint32_t next; +}; + +/// Structure describing the DMA driver environment +struct dma_env_tag +{ + /** last DMA descriptor pushed for each channel, can point to descriptor already + * deallocated, but then will not be use`d because root register will be NULL + */ + volatile struct dma_desc *last_dma[IPC_DMA_CHANNEL_MAX]; +}; + +/// DMA environment structure +extern struct dma_env_tag dma_env; + +/** + **************************************************************************************** + * @brief Initialize the bridge DMA registers + **************************************************************************************** + */ +void dma_init(void); + + +/** + **************************************************************************************** + * @brief Chains a descriptor in the DMA + * + * + * @param[in] desc DMA descriptor filled by the caller + * @param[in] channel_idx Channel index + * + **************************************************************************************** + */ +uint32_t dma_push(struct dma_desc *first, struct dma_desc *last, int channel_idx); +#endif // _IPC_DMA_H_ + diff --git a/beken_os/beken378/driver/driver.c b/beken_os/beken378/driver/driver.c new file mode 100755 index 0000000..0ae16f5 --- /dev/null +++ b/beken_os/beken378/driver/driver.c @@ -0,0 +1,14 @@ +#include "include.h" +#include "driver_pub.h" +#include "dd_pub.h" +#include "drv_model_pub.h" + +UINT32 driver_init(void) +{ + drv_model_init(); + g_dd_init(); + + return 0; +} + +// eof diff --git a/beken_os/beken378/driver/entry/arch.h b/beken_os/beken378/driver/entry/arch.h new file mode 100755 index 0000000..c5d9176 --- /dev/null +++ b/beken_os/beken378/driver/entry/arch.h @@ -0,0 +1,111 @@ +/** + **************************************************************************************** + * + * @file arch.h + * + * @brief This file contains the definitions of the macros and functions that are + * architecture dependent. The implementation of those is implemented in the + * appropriate architecture directory. + * + * Copyright (C) RivieraWaves 2011-2016 + * + **************************************************************************************** + */ + + +#ifndef _ARCH_H_ +#define _ARCH_H_ + +/** + **************************************************************************************** + * @defgroup PLATFORM_DRIVERS PLATFORM_DRIVERS + * @ingroup MACSW + * @brief Declaration of the ATMEL AT91SAM261 architecture API. + * @{ + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @defgroup ARCH_AT91SAM9261 ARCH_AT91SAM9261 + * @ingroup PLATFORM_DRIVERS + * @brief Declaration of the ATMEL AT91SAM261 architecture API. + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "generic.h" +#include "co_int.h" +#include "compiler.h" +#include "portmacro.h" +#if CFG_SUPPORT_RTT +#include +#include +#endif + + +#define GLOBAL_INTERRUPT_START portENABLE_INTERRUPTS +#define GLOBAL_INTERRUPT_STOP portDISABLE_INTERRUPTS + +#if CFG_SUPPORT_RTT + +#define GLOBAL_INT_DECLARATION() rt_base_t irq_level +#define GLOBAL_INT_DISABLE() do{\ + irq_level = rt_hw_interrupt_disable();\ + }while(0) + + +#define GLOBAL_INT_RESTORE() do{ \ + rt_hw_interrupt_enable(irq_level);\ + }while(0) + +#else + +#define GLOBAL_INT_DECLARATION() uint32_t fiq_tmp, irq_tmp +#define GLOBAL_INT_DISABLE() do{\ + fiq_tmp = portDISABLE_FIQ();\ + irq_tmp = portDISABLE_IRQ();\ + }while(0) + + +#define GLOBAL_INT_RESTORE() do{ \ + if(!fiq_tmp) \ + { \ + portENABLE_FIQ(); \ + } \ + if(!irq_tmp) \ + { \ + portENABLE_IRQ(); \ + } \ + }while(0) +#endif + +/* + * CPU WORD SIZE + **************************************************************************************** + */ +/// ARM is a 32-bit CPU +#define CPU_WORD_SIZE 4 + +/* + * CPU Endianness + **************************************************************************************** + */ +/// ARM is little endian +#define CPU_LE 1 + +#define ASSERT_REC(cond) +#define ASSERT_REC_VAL(cond, ret) +#define ASSERT_REC_NO_RET(cond) + +#define ASSERT_ERR(cond) ASSERT(cond) +#define ASSERT_ERR2(cond, param0, param1) +#define ASSERT_WARN(cond) + +/// @} +/// @} +#endif // _ARCH_H_ diff --git a/beken_os/beken378/driver/entry/arch_main.c b/beken_os/beken378/driver/entry/arch_main.c new file mode 100755 index 0000000..d9c6ca3 --- /dev/null +++ b/beken_os/beken378/driver/entry/arch_main.c @@ -0,0 +1,195 @@ +/** + **************************************************************************************** + * + * @file arch_main.c + * + * @brief Main loop of the application. + * + * Copyright (C) Beken Corp 2011-2020 + * + **************************************************************************************** + */ +#include "include.h" +#include "driver_pub.h" +#include "func_pub.h" +#include "app.h" +#include "uart.h" +#include "arm_arch.h" +#include "ate_app.h" +#include "bk7011_cal_pub.h" +#include "start_type_pub.h" +#include "wdt_pub.h" +#include "icu_pub.h" + +beken_semaphore_t extended_app_sema = NULL; +#define EXTENDED_APP_STACK_SIZE 2048 + +extern void user_main_entry(void); + +void extended_app_launch_over(void) +{ + OSStatus ret; + ret = rtos_set_semaphore(&extended_app_sema); + + (void)ret; +} + +void extended_app_waiting_for_launch(void) +{ + OSStatus ret; + + ret = rtos_get_semaphore(&extended_app_sema, BEKEN_WAIT_FOREVER); + ASSERT(kNoErr == ret); + + (void)ret; +} + +static void extended_app_task_handler(void *arg) +{ + /* step 0: function layer initialization*/ + func_init_extended(); + +#ifdef VCS_RELEASE_VERSION + bk_printf("Version:%s\r\n",VCS_RELEASE_VERSION); +#endif + + /* step 1: startup application layer*/ + #if CFG_ENABLE_ATE_FEATURE + if(get_ate_mode_state()) + { + ate_start(); + } + else + #endif // CFG_ENABLE_ATE_FEATURE + { + app_start(); + } + + extended_app_launch_over(); + + rtos_delete_thread( NULL ); +} + +void extended_app_launch(void) +{ + OSStatus ret; + + ret = rtos_init_semaphore(&extended_app_sema, 1); + ASSERT(kNoErr == ret); + + ret = rtos_create_thread(NULL, + THD_EXTENDED_APP_PRIORITY, + "extended_app", + (beken_thread_function_t)extended_app_task_handler, + EXTENDED_APP_STACK_SIZE, + (beken_thread_arg_t)0); + ASSERT(kNoErr == ret); +} + + +// #include "driver_sys_ctrl.h" +#define REG_ICU_BASE_ADDR (0x00802000UL) +#define REG_ICU_INT_ENABLE_ADDR (REG_ICU_BASE_ADDR + 0x10 * 4) +#define REG_ICU_INT_GLOBAL_ENABLE_ADDR (REG_ICU_BASE_ADDR + 0x11 * 4) +#define REG_ICU_INT_RAW_STATUS_ADDR (REG_ICU_BASE_ADDR + 0x12 * 4) +#define REG_ICU_INT_STATUS_ADDR (REG_ICU_BASE_ADDR + 0x13 * 4) + +#define ATE_START_ADDR 0x120000 + +void intc_disable_top(void) +{ + u32 reg; + u32 param; + + param = 0xffffffff; + reg = REG_READ(REG_ICU_INT_GLOBAL_ENABLE_ADDR); + reg &= ~(param); + REG_WRITE(REG_ICU_INT_GLOBAL_ENABLE_ADDR, reg); +} + +void intc_forbidden_all(void) +{ + REG_WRITE(REG_ICU_INT_ENABLE_ADDR, 0); + REG_WRITE(REG_ICU_INT_GLOBAL_ENABLE_ADDR, 0); + REG_WRITE(REG_ICU_INT_RAW_STATUS_ADDR, REG_READ(REG_ICU_INT_RAW_STATUS_ADDR)); + REG_WRITE(REG_ICU_INT_STATUS_ADDR, REG_READ(REG_ICU_INT_STATUS_ADDR)); +} + +void sys_forbidden_interrupts(void) +{ + // __disable_irq(); + portDISABLE_IRQ(); + intc_disable_top(); + intc_forbidden_all(); +} + +void jump_pc_address(u32 ptr) +{ + typedef void (*jump_point)(void); + jump_point jump = (jump_point)ptr; + + (* jump)(); +} + +void delay_xtime(u32 time) +{ + u32 i, j; + for (i=0; imode == FFT_MODE_FFT) + { + value = FFT_CONF_INT_EN | FFT_CONF_ENABLE; + } + else if(fft_conf->mode == FFT_MODE_IFFT) + { + value = FFT_CONF_IFFT | FFT_CONF_INT_EN | FFT_CONF_ENABLE; + } + REG_WRITE(FFT_CONF, value); + + driver_fft.in = fft_conf->inbuf; + driver_fft.out = fft_conf->outbuf; + driver_fft.size = fft_conf->size; + driver_fft.busy_flag = 1; + + for(i = 0; i < fft_conf->size; i++) + { + value = (UINT16)(fft_conf->inbuf[i]) << 16 | (UINT16)(fft_conf->outbuf[i]); + Fft_Write_Data(value); + } + + Fft_Set_Start(); +} + +static void fir_single_enable(input_fir_t *fir_conf) +{ + int i; + UINT32 value = 0; + + if(fir_conf->fir_len > 64) + return; + + REG_WRITE(FIR_CONF, 0); + REG_WRITE(FFT_CONF, 0); + + value = (fir_conf->fir_len << FIR_CONF_LEN_POSI) + | (fir_conf->fir_cwidth << FIR_CONF_CWIDTH_POSI) + | (fir_conf->fir_dwidth << FIR_CONF_DWIDTH_POSI) + | FIR_CONF_INT_EN + | FIR_CONF_ENABLE; + REG_WRITE(FIR_CONF, value); + + driver_fft.mac_out = fir_conf->mac; + driver_fft.busy_flag = 1; + + for(i = 0; i < fir_conf->fir_len + 1; i++) + { + Fft_Write_Coef(fir_conf->coef[i]); + Fft_Write_Data(fir_conf->input[i]); + } + + Fft_Set_Start(); + + return; +} + +static __inline INT16 f_sat(int din) +{ + if (din > 32767) + return 32767; + if (din < -32767) + return -32767; + else + return(din); +} + +void fft_init(void) +{ + intc_service_register(IRQ_FFT, PRI_IRQ_FFT, fft_isr); + + sddev_register_dev(FFT_DEV_NAME, &fft_op); +} + +void fft_exit(void) +{ + sddev_unregister_dev(FFT_DEV_NAME); +} + +UINT32 fft_ctrl(UINT32 cmd, void *param) +{ + int ret = FFT_SUCCESS; + + switch(cmd) + { + case CMD_FFT_BUSY: + *((int *)param) = fft_busy(); + break; + case CMD_FFT_ENABLE: + fft_enable((input_fft_t *)param); + break; + case CMD_FIR_SIGNLE_ENABLE: + fir_single_enable((input_fir_t *)param); + break; + default: + ret = FFT_FAILURE; + break; + } + + return ret; +} + +void fft_isr(void) +{ + UINT32 int_status; + UINT8 FFT_int, FIR_int; + + int_status = REG_READ(FFT_STATUS); + FFT_int = int_status & FFT_STATUS_DONE; + FIR_int = int_status & FIR_STATUS_DONE; + + if(FFT_int) + { + int i; + int bit_ext; + INT32 temp, temp_out; + + bit_ext = (int_status & 0x00001fff) >> 7; + + if( bit_ext & 0x20 ) + { + bit_ext = 64 - bit_ext; + } + else + { + bit_ext = 0; + } + + for(i = 0; i < driver_fft.size; i++) + { + temp = Fft_Read_Data(); + temp_out = ((temp << 16) >> 16) << bit_ext ; + driver_fft.out[i] = f_sat(temp_out); + temp_out = (temp >> 16) << bit_ext; + driver_fft.in[i] = f_sat(temp_out); + } + + driver_fft.busy_flag = 0; + REG_WRITE(FFT_CONF, 0); + } + + if(FIR_int) + { + *driver_fft.mac_out = REG_READ(FFT_MAC_LOW); + + driver_fft.busy_flag = 0; + REG_WRITE(FIR_CONF, 0); + } +} diff --git a/beken_os/beken378/driver/fft/fft.h b/beken_os/beken378/driver/fft/fft.h new file mode 100755 index 0000000..fd2bd38 --- /dev/null +++ b/beken_os/beken378/driver/fft/fft.h @@ -0,0 +1,70 @@ +#ifndef _FFT_H_ +#define _FFT_H_ + +#define FFT_DEBUG + +#ifdef FFT_DEBUG +#define FFT_PRT os_printf +#define FFT_WARN warning_prf +#define FFT_FATAL fatal_prf +#else +#define FFT_PRT null_prf +#define FFT_WARN null_prf +#define FFT_FATAL null_prf +#endif + +#define FFT_BASE (0x00805000) + +#define FFT_CONF (FFT_BASE + 0 * 4) +#define FFT_CONF_MODE (0x01UL << 0) +#define FFT_CONF_IFFT (0x01UL << 1) +#define FFT_CONF_INT_EN (0x01UL << 2) +#define FFT_CONF_ENABLE (0x01UL << 3) +#define FFT_CONF_GAT (0x01UL << 4) + +#define FIR_CONF (FFT_BASE + 1 * 4) +#define FIR_CONF_LEN_POSI (0) +#define FIR_CONF_LEN_MASK (0xFF) +#define FIR_CONF_CWIDTH_POSI (8) +#define FIR_CONF_CWIDTH_MASK (0x07) +#define FIR_CONF_DWIDTH_POSI (11) +#define FIR_CONF_DWIDTH_MASK (0x07) +#define FIR_CONF_MODE (0x01UL << 14) +#define FIR_CONF_INT_EN (0x01UL << 15) +#define FIR_CONF_ENABLE (0x01UL << 16) + +#define FFT_DATA_PORT (FFT_BASE + 2 * 4) + +#define FFT_COEF_PORT (FFT_BASE + 3 * 4) + +#define FFT_MAC_LOW (FFT_BASE + 4 * 4) + +#define FFT_MAC_HIGH (FFT_BASE + 5 * 4) + +#define FFT_STATUS (FFT_BASE + 6 * 4) +#define FFT_STATUS_DONE (0x01UL << 0) +#define FIR_STATUS_DONE (0x01UL << 1) + +#define FFT_START (FFT_BASE + 7 * 4) + +#define FFT_MEMORY_BASE_ADDR (FFT_BASE+0x200) + +#define Fft_Set_Start() REG_WRITE(FFT_START, 0x1) +#define Fft_Write_Data(v) REG_WRITE(FFT_DATA_PORT, v) +#define Fft_Read_Data() REG_READ(FFT_DATA_PORT) +#define Fft_Write_Coef(v) REG_WRITE(FFT_COEF_PORT, v) + +typedef struct +{ + INT16 *in; + INT16 *out; + INT32 *mac_out; + volatile UINT8 busy_flag; + UINT16 size; +} driver_fft_t; + +/******************************************************************************* +* Function Declarations +*******************************************************************************/ +UINT32 fft_ctrl(UINT32 cmd, void *param); +#endif //_FFT_H_ diff --git a/beken_os/beken378/driver/flash/flash.c b/beken_os/beken378/driver/flash/flash.c new file mode 100755 index 0000000..f957c94 --- /dev/null +++ b/beken_os/beken378/driver/flash/flash.c @@ -0,0 +1,764 @@ +#include "include.h" +#include "arm_arch.h" +#include "sys_config.h" + +#include "flash.h" +#include "sys_ctrl.h" +#include "flash_pub.h" +#include "drv_model_pub.h" +#include +#include "uart_pub.h" +#include "sys_ctrl_pub.h" +#include "mcu_ps_pub.h" +#include "ate_app.h" + +static const flash_config_t flash_config[] = +{ + {0x1C7016, 1, 0x400000, 2, 0, 2, 0x1F, 0x1F, 0x00, 0x16, 0x01B, 0, 0, 0xA5, 0x01}, //en_25qh32b + {0x1C7015, 1, 0x200000, 2, 0, 2, 0x1F, 0x1F, 0x00, 0x0d, 0x0d, 0, 0, 0xA5, 0x01}, //en_25qh16b + {0x0B4014, 2, 0x100000, 2, 14, 2, 0x1F, 0x1F, 0x00, 0x0C, 0x101, 9, 1, 0xA0, 0x01}, //xtx_25f08b + {0x0B4015, 2, 0x200000, 2, 14, 2, 0x1F, 0x1F, 0x00, 0x0D, 0x101, 9, 1, 0xA0, 0x01}, //xtx_25f16b + {0x0B4016, 2, 0x400000, 2, 14, 2, 0x1F, 0x1F, 0x00, 0x0E, 0x101, 9, 1, 0xA0, 0x01}, //xtx_25f32b + {0x0E4016, 2, 0x400000, 2, 14, 2, 0x1F, 0x1F, 0x00, 0x0E, 0x101, 9, 1, 0xA0, 0x01}, //xtx_FT25H32 + {0xC84015, 2, 0x200000, 2, 14, 2, 0x1F, 0x1F, 0x00, 0x0D, 0x101, 9, 1, 0xA0, 0x01}, //gd_25q16c + {0xC84016, 2, 0x400000, 2, 14, 2, 0x1F, 0x1F, 0x00, 0x0E, 0x101, 9, 1, 0xA0, 0x01}, //gd_25q32c + {0xC86015, 2, 0x200000, 2, 14, 2, 0x1F, 0x1F, 0x00, 0x0D, 0x101, 9, 1, 0xA0, 0x01}, //gd_25w16e + {0xEF4016, 2, 0x400000, 2, 14, 2, 0x1F, 0x1F, 0x00, 0x00, 0x101, 9, 1, 0xA0, 0x01}, //w_25q32(bfj) + {0x204016, 2, 0x400000, 2, 14, 2, 0x1F, 0x1F, 0x00, 0x0E, 0x101, 9, 1, 0xA0, 0x01}, //xmc_25qh32b + {0xC22315, 1, 0x200000, 2, 0, 2, 0x0F, 0x0F, 0x00, 0x0A, 0x00E, 6, 1, 0xA5, 0x01}, //mx_25v16b + {0xEB6015, 2, 0x200000, 2, 14, 2, 0x1F, 0x1F, 0x00, 0x0D, 0x101, 9, 1, 0xA0, 0x01}, //zg_th25q16b + {0x000000, 2, 0x400000, 2, 0, 2, 0x1F, 0x00, 0x00, 0x00, 0x000, 0, 0, 0x00, 0x01}, //default +}; + +static const flash_config_t *flash_current_config = NULL; + +static UINT32 flash_id; +static DD_OPERATIONS flash_op = +{ + NULL, + NULL, + flash_read, + flash_write, + flash_ctrl +}; + +static void flash_get_current_flash_config(void) +{ + int i; + for(i = 0; i < (sizeof(flash_config) / sizeof(flash_config_t) - 1); i++) + { + if(flash_id == flash_config[i].flash_id) + { + flash_current_config = &flash_config[i]; + break; + } + } + if(i == (sizeof(flash_config) / sizeof(flash_config_t) - 1)) + { + flash_current_config = &flash_config[i]; + os_printf("choose default config\r\n"); + } +} + +static void flash_set_clk(UINT8 clk_conf) +{ + UINT32 value; + + value = REG_READ(REG_FLASH_CONF); + value &= ~(FLASH_CLK_CONF_MASK << FLASH_CLK_CONF_POSI); + value |= (clk_conf << FLASH_CLK_CONF_POSI); + REG_WRITE(REG_FLASH_CONF, value); +} + +void flash_enable_cpu_data_wr(void) +{ + UINT32 value; + + value = REG_READ(REG_FLASH_CONF); + value |= (CPU_DATA_WR_MASK << CPU_DATA_WR_POSI); + REG_WRITE(REG_FLASH_CONF, value); +} + +static void flash_disable_cpu_data_wr(void) +{ + UINT32 value; + + value = REG_READ(REG_FLASH_CONF); + value &= (~(CPU_DATA_WR_MASK << CPU_DATA_WR_POSI)); + + REG_WRITE(REG_FLASH_CONF, value); +} + +static void flash_write_enable(void) +{ + UINT32 value; + + value = (FLASH_OPCODE_WREN << OP_TYPE_SW_POSI) | OP_SW | WP_VALUE; + REG_WRITE(REG_FLASH_OPERATE_SW, value); + + while(REG_READ(REG_FLASH_OPERATE_SW) & BUSY_SW); +} + +static void flash_write_disable(void) +{ + UINT32 value; + + value = (FLASH_OPCODE_WRDI << OP_TYPE_SW_POSI) | OP_SW | WP_VALUE; + REG_WRITE(REG_FLASH_OPERATE_SW, value); + while(REG_READ(REG_FLASH_OPERATE_SW) & BUSY_SW); +} + + +static UINT16 flash_read_sr(UINT8 sr_width) +{ + UINT16 sr; + UINT32 value; + + while(REG_READ(REG_FLASH_OPERATE_SW) & BUSY_SW); + + value = (FLASH_OPCODE_RDSR << OP_TYPE_SW_POSI) | OP_SW | WP_VALUE; + REG_WRITE(REG_FLASH_OPERATE_SW, value); + while(REG_READ(REG_FLASH_OPERATE_SW) & BUSY_SW); + + value = REG_READ(REG_FLASH_SR_DATA_CRC_CNT); + sr = value & 0x00FF; + + if(sr_width == 2) + { + value = (FLASH_OPCODE_RDSR2 << OP_TYPE_SW_POSI) | OP_SW | WP_VALUE; + REG_WRITE(REG_FLASH_OPERATE_SW, value); + while(REG_READ(REG_FLASH_OPERATE_SW) & BUSY_SW); + + value = REG_READ(REG_FLASH_SR_DATA_CRC_CNT); + sr |= (value & 0x00FF) << 8; + } + //os_printf("--read sr:%x--\r\n",sr); + return sr; +} + +static void flash_write_sr(UINT8 sr_width, UINT16 val) +{ + UINT32 value; + GLOBAL_INT_DECLARATION(); + + GLOBAL_INT_DISABLE(); + while(REG_READ(REG_FLASH_OPERATE_SW) & BUSY_SW); + + value = REG_READ(REG_FLASH_CONF); + value &= ~(WRSR_DATA_MASK << WRSR_DATA_POSI); + + value |= (val << WRSR_DATA_POSI); + + REG_WRITE(REG_FLASH_CONF, value); + while(REG_READ(REG_FLASH_OPERATE_SW) & BUSY_SW); + + if(sr_width == 1) + { + value = (FLASH_OPCODE_WRSR << OP_TYPE_SW_POSI) | OP_SW | WP_VALUE; + REG_WRITE(REG_FLASH_OPERATE_SW, value); + } + else if(sr_width == 2) + { + value = (FLASH_OPCODE_WRSR2 << OP_TYPE_SW_POSI) | OP_SW | WP_VALUE; + REG_WRITE(REG_FLASH_OPERATE_SW, value); + } + + while(REG_READ(REG_FLASH_OPERATE_SW) & BUSY_SW); + GLOBAL_INT_RESTORE(); +} + +static UINT8 flash_read_qe(void) +{ + UINT8 temp; + UINT32 value; + + if(1 == flash_current_config->sr_size) + { + value = (FLASH_OPCODE_RDSR << OP_TYPE_SW_POSI) | OP_SW | WP_VALUE; + REG_WRITE(REG_FLASH_OPERATE_SW, value); + } + else + { + value = (FLASH_OPCODE_RDSR2 << OP_TYPE_SW_POSI) | OP_SW | WP_VALUE; + REG_WRITE(REG_FLASH_OPERATE_SW, value); + } + + while(REG_READ(REG_FLASH_OPERATE_SW) & BUSY_SW); + + value = REG_READ(REG_FLASH_SR_DATA_CRC_CNT); + temp = (value & 0xFF); + return temp; +} + +static void flash_set_qe(void) +{ + UINT32 value, param; + + while(REG_READ(REG_FLASH_OPERATE_SW) & BUSY_SW); + + param = flash_read_sr(flash_current_config->sr_size); + if((param & (flash_current_config->qe_bit << flash_current_config->qe_bit_post))) + { + return ; + } + value = REG_READ(REG_FLASH_CONF); + value &= ~(WRSR_DATA_MASK << WRSR_DATA_POSI); + value |= (((flash_current_config->qe_bit << flash_current_config->qe_bit_post) + | param) << WRSR_DATA_POSI); + REG_WRITE(REG_FLASH_CONF, value); + + value = REG_READ(REG_FLASH_OPERATE_SW); + + if(1 == flash_current_config->sr_size) + { + value = (value & (ADDR_SW_REG_MASK << ADDR_SW_REG_POSI)) + | (FLASH_OPCODE_WRSR << OP_TYPE_SW_POSI) | OP_SW | WP_VALUE; + } + else + { + value = (value & (ADDR_SW_REG_MASK << ADDR_SW_REG_POSI)) + | (FLASH_OPCODE_WRSR2 << OP_TYPE_SW_POSI) | OP_SW | WP_VALUE; + } + + REG_WRITE(REG_FLASH_OPERATE_SW, value); + + while(REG_READ(REG_FLASH_OPERATE_SW) & BUSY_SW); +} + +static void flash_set_qwfr(void) +{ + UINT32 value; + + value = REG_READ(REG_FLASH_CONF); + value &= ~(MODEL_SEL_MASK << MODEL_SEL_POSI); + value |= (flash_current_config->mode_sel << MODEL_SEL_POSI); + REG_WRITE(REG_FLASH_CONF, value); +} + +static void flash_clr_qwfr(void) +{ + UINT32 value; + + value = REG_READ(REG_FLASH_CONF); + value &= ~(MODEL_SEL_MASK << MODEL_SEL_POSI); + REG_WRITE(REG_FLASH_CONF, value); + + value = REG_READ(REG_FLASH_OPERATE_SW); + value = ((0 << ADDR_SW_REG_POSI) + | (FLASH_OPCODE_CRMR << OP_TYPE_SW_POSI) + | OP_SW + | (value & WP_VALUE)); + REG_WRITE(REG_FLASH_OPERATE_SW, value); + + while(REG_READ(REG_FLASH_OPERATE_SW) & BUSY_SW); +} + +static void flash_set_wsr(UINT16 data) +{ + UINT32 value; + + while(REG_READ(REG_FLASH_OPERATE_SW) & BUSY_SW); + + value = REG_READ(REG_FLASH_CONF); + value &= ~(WRSR_DATA_MASK << WRSR_DATA_POSI); + value |= (data << WRSR_DATA_POSI); + REG_WRITE(REG_FLASH_CONF, value); + + value = REG_READ(REG_FLASH_OPERATE_SW); + value = (value & (ADDR_SW_REG_MASK << ADDR_SW_REG_POSI)) + | (FLASH_OPCODE_WRSR2 << OP_TYPE_SW_POSI) | OP_SW | WP_VALUE; + REG_WRITE(REG_FLASH_OPERATE_SW, value); + + while(REG_READ(REG_FLASH_OPERATE_SW) & BUSY_SW); +} + +UINT8 flash_get_line_mode(void) +{ + return flash_current_config->line_mode; +} + +void flash_set_line_mode(UINT8 mode) +{ + UINT32 value; + + if(1 == mode) + { + flash_clr_qwfr(); + } + if(2 == mode) + { + flash_clr_qwfr(); + value = REG_READ(REG_FLASH_CONF); + value &= ~(MODEL_SEL_MASK << MODEL_SEL_POSI); + value |= ((MODE_DUAL & MODEL_SEL_MASK) << MODEL_SEL_POSI); + REG_WRITE(REG_FLASH_CONF, value); + } + else if(4 == mode) + { + flash_clr_qwfr(); + value = REG_READ(REG_FLASH_SR_DATA_CRC_CNT); + value &= ~(M_VALUE_MASK << M_VALUE_POST); + value |= (flash_current_config->m_value<< M_VALUE_POST); + + REG_WRITE(REG_FLASH_SR_DATA_CRC_CNT, value); + + value = REG_READ(REG_FLASH_SR_DATA_CRC_CNT); + + if(1 == flash_current_config->qe_bit) + { + flash_set_qe(); + } + + flash_set_qwfr(); + } +} + +static UINT32 flash_get_id(void) +{ + UINT32 value; + + value = (FLASH_OPCODE_RDID << OP_TYPE_SW_POSI) | OP_SW | WP_VALUE; + REG_WRITE(REG_FLASH_OPERATE_SW, value); + + while(REG_READ(REG_FLASH_OPERATE_SW) & BUSY_SW); + + flash_id = REG_READ(REG_FLASH_RDID_DATA_FLASH); + return flash_id; +} + +static UINT32 flash_read_mid(void) +{ + UINT32 value; + UINT32 flash_id; + + while(REG_READ(REG_FLASH_OPERATE_SW) & BUSY_SW); + + value = REG_READ(REG_FLASH_OPERATE_SW); + value = ((value & (ADDR_SW_REG_MASK << ADDR_SW_REG_POSI)) + | (FLASH_OPCODE_RDID << OP_TYPE_SW_POSI) + | OP_SW + | (value & WP_VALUE)); + REG_WRITE(REG_FLASH_OPERATE_SW, value); + while(REG_READ(REG_FLASH_OPERATE_SW) & BUSY_SW); + + flash_id = REG_READ(REG_FLASH_RDID_DATA_FLASH); + + return flash_id; +} + +static PROTECT_TYPE get_flash_protect(void) +{ + UINT16 sr_value, cmp, param, value, type; + + sr_value = flash_read_sr(flash_current_config->sr_size); + param = (sr_value >> flash_current_config->protect_post) & flash_current_config->protect_mask; + cmp = (sr_value >> flash_current_config->cmp_post) & 0x01; + value = (cmp << 8) | param; + + if(value == flash_current_config->protect_all) + { + type = FLASH_PROTECT_ALL; + } + else if(value == flash_current_config->protect_none) + { + type = FLASH_PROTECT_NONE; + } + else if(value == flash_current_config->protect_half) + { + type = FLASH_PROTECT_HALF; + } + else if(value == flash_current_config->unprotect_last_block) + { + type = FLASH_UNPROTECT_LAST_BLOCK; + } + else + { + type = -1; + } + + return type; +} + +static void set_flash_protect(PROTECT_TYPE type) +{ + UINT32 param, value, cmp; + + switch (type) + { + case FLASH_PROTECT_NONE: + param = flash_current_config->protect_none & 0xff; + cmp = (flash_current_config->protect_none >> 8) & 0xff; + break; + + case FLASH_PROTECT_ALL: + param = flash_current_config->protect_all & 0xff; + cmp = (flash_current_config->protect_all >> 8) & 0xff; + break; + + case FLASH_PROTECT_HALF: + param = flash_current_config->protect_half & 0xff; + cmp = (flash_current_config->protect_half >> 8) & 0xff; + break; + + case FLASH_UNPROTECT_LAST_BLOCK: + param = flash_current_config->unprotect_last_block& 0xff; + cmp = (flash_current_config->unprotect_last_block >> 8) & 0xff; + break; + + default: + param = flash_current_config->protect_all & 0xff; + cmp = (flash_current_config->protect_all >> 8) & 0xff; + break; + } + + value = flash_read_sr(flash_current_config->sr_size); + + if(((param << flash_current_config->protect_post) != + (value & (flash_current_config->protect_mask << flash_current_config->protect_post))) + || ((cmp << flash_current_config->cmp_post) != + (value & (0x01 << flash_current_config->cmp_post)))) + { + value = (value & (~(flash_current_config->protect_mask + << flash_current_config->protect_post))) + | (param << flash_current_config->protect_post); + value &= ~(1 << flash_current_config->cmp_post); + value |= ((cmp & 0x01) << flash_current_config->cmp_post); + //os_printf("--write status reg:%x,%x--\r\n", value, flash_current_config->sr_size); + flash_write_sr(flash_current_config->sr_size, value); + } +} +static void flash_erase_sector(UINT32 address) +{ + UINT32 value; + UINT32 erase_addr = address & 0xFFF000; + GLOBAL_INT_DECLARATION(); + + if(erase_addr >= flash_current_config->flash_size) + { + bk_printf("Erase error:invalid address0x%x\r\n", erase_addr); + return; + } + + GLOBAL_INT_DISABLE(); + while(REG_READ(REG_FLASH_OPERATE_SW) & BUSY_SW); + value = REG_READ(REG_FLASH_OPERATE_SW); + value = ((erase_addr << ADDR_SW_REG_POSI) + | (FLASH_OPCODE_SE << OP_TYPE_SW_POSI) + | OP_SW + | (value & WP_VALUE)); + REG_WRITE(REG_FLASH_OPERATE_SW, value); + while(REG_READ(REG_FLASH_OPERATE_SW) & BUSY_SW); + GLOBAL_INT_RESTORE(); +} + +static void flash_set_hpm(void) +{ + UINT32 value; + + while(REG_READ(REG_FLASH_OPERATE_SW) & BUSY_SW); + value = REG_READ(REG_FLASH_OPERATE_SW); + value = ((0x0 << ADDR_SW_REG_POSI) + | (FLASH_OPCODE_HPM << OP_TYPE_SW_POSI) + | (OP_SW) + | (value & WP_VALUE)); + REG_WRITE(REG_FLASH_OPERATE_SW, value); + while(REG_READ(REG_FLASH_OPERATE_SW) & BUSY_SW); +} + +static void flash_read_data(UINT8 *buffer, UINT32 address, UINT32 len) +{ + UINT32 i, reg_value; + UINT32 addr = address & (~0x1F); + UINT32 buf[8]; + UINT8 *pb = (UINT8 *)&buf[0]; + GLOBAL_INT_DECLARATION(); + + if(len == 0) + { + return; + } + + GLOBAL_INT_DISABLE(); + while(REG_READ(REG_FLASH_OPERATE_SW) & BUSY_SW); + while(len) + { + reg_value = REG_READ(REG_FLASH_OPERATE_SW); + reg_value = ((addr << ADDR_SW_REG_POSI) + | (FLASH_OPCODE_READ << OP_TYPE_SW_POSI) + | OP_SW + | (reg_value & WP_VALUE)); + REG_WRITE(REG_FLASH_OPERATE_SW, reg_value); + while(REG_READ(REG_FLASH_OPERATE_SW) & BUSY_SW); + addr += 32; + + for(i = 0; i < 8; i++) + { + buf[i] = REG_READ(REG_FLASH_DATA_FLASH_SW); + } + + for(i = address % 32; i < 32; i++) + { + *buffer++ = pb[i]; + address++; + len--; + if(len == 0) + { + break; + } + } + } + GLOBAL_INT_RESTORE(); +} + +static void flash_write_data(UINT8 *buffer, UINT32 address, UINT32 len) +{ + UINT32 i, reg_value; + UINT32 addr = address & (~0x1F); + UINT32 buf[8]; + UINT8 *pb = (UINT8 *)&buf[0]; + GLOBAL_INT_DECLARATION(); + + if((addr >= flash_current_config->flash_size) + || (len > flash_current_config->flash_size) + || ((addr + len) > flash_current_config->flash_size)) + { + bk_printf("Write error[addr:0x%x len:0x%x]\r\n", addr, len); + return; + } + + if(address % 32) + { + flash_read_data(pb, addr, 32); + } + else + { + memset(pb, 0xFF, 32); + } + + while(REG_READ(REG_FLASH_OPERATE_SW) & BUSY_SW); + while(len) + { + if(len < 32) + { + flash_read_data(pb, addr, 32); + while(REG_READ(REG_FLASH_OPERATE_SW) & BUSY_SW); + } + for (i = address % 32; i < 32; i++) + { + pb[i] = *buffer++; + address++; + len--; + if (len == 0) + break; + } + + GLOBAL_INT_DISABLE(); + for (i = 0; i < 8; i++) + { + REG_WRITE(REG_FLASH_DATA_SW_FLASH, buf[i]); + } + + reg_value = REG_READ(REG_FLASH_OPERATE_SW); + reg_value = ((addr << ADDR_SW_REG_POSI) + | (FLASH_OPCODE_PP << OP_TYPE_SW_POSI) + | OP_SW + | (reg_value & WP_VALUE)); + REG_WRITE(REG_FLASH_OPERATE_SW, reg_value); + while(REG_READ(REG_FLASH_OPERATE_SW) & BUSY_SW); + GLOBAL_INT_RESTORE(); + addr += 32; + memset(pb, 0xFF, 32); + } +} + + +void flash_protection_op(UINT8 mode, PROTECT_TYPE type) +{ + set_flash_protect(type); +} + +void flash_init(void) +{ + UINT32 id; + + while(REG_READ(REG_FLASH_OPERATE_SW) & BUSY_SW); + + id = flash_get_id(); + FLASH_PRT("[Flash]id:0x%x\r\n", id); + flash_get_current_flash_config(); + + set_flash_protect(FLASH_PROTECT_ALL); + flash_disable_cpu_data_wr(); + flash_set_line_mode(flash_current_config->line_mode); + + flash_set_clk(5); // 60M + + ddev_register_dev(FLASH_DEV_NAME, &flash_op); +} + +void flash_exit(void) +{ + ddev_unregister_dev(FLASH_DEV_NAME); +} + +UINT32 flash_read(char *user_buf, UINT32 count, UINT32 address) +{ + peri_busy_count_add(); + + flash_read_data((UINT8 *)user_buf, address, count); + + peri_busy_count_dec(); + + return FLASH_SUCCESS; +} + +UINT32 flash_write(char *user_buf, UINT32 count, UINT32 address) +{ + peri_busy_count_add(); + + if(4 == flash_current_config->line_mode) + { + flash_set_line_mode(LINE_MODE_TWO); + } + + flash_write_data((UINT8 *)user_buf, address, count); + + if(4 == flash_current_config->line_mode) + { + flash_set_line_mode(LINE_MODE_FOUR); + } + peri_busy_count_dec(); + + return FLASH_SUCCESS; +} + + +UINT32 flash_ctrl(UINT32 cmd, void *parm) +{ + UINT8 clk; + UINT16 wsr; + UINT32 address; + UINT32 reg; + UINT32 ret = FLASH_SUCCESS; + peri_busy_count_add(); + + if(4 == flash_current_config->line_mode) + { + flash_set_line_mode(LINE_MODE_TWO); + } + + switch(cmd) + { + case CMD_FLASH_SET_CLK: + clk = (*(UINT8 *)parm); + flash_set_clk(clk); + break; + + case CMD_FLASH_SET_DPLL: + ret = sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_SET_FLASH_DPLL, 0); + ASSERT(DRV_FAILURE != ret); + + reg = REG_READ(REG_FLASH_CONF); + reg &= ~(FLASH_CLK_CONF_MASK << FLASH_CLK_CONF_POSI); + reg = reg | (5 << FLASH_CLK_CONF_POSI); /*dco--9*/ + REG_WRITE(REG_FLASH_CONF, reg); + break; + + case CMD_FLASH_SET_DCO: + ret = sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_SET_FLASH_DCO, 0); + ASSERT(DRV_FAILURE != ret); + + reg = REG_READ(REG_FLASH_CONF); + reg &= ~(FLASH_CLK_CONF_MASK << FLASH_CLK_CONF_POSI); + if (get_ate_mode_state()) { + reg = reg | (0xB << FLASH_CLK_CONF_POSI); + } else { + reg = reg | (9 << FLASH_CLK_CONF_POSI); + } + REG_WRITE(REG_FLASH_CONF, reg); + + REG_WRITE(REG_FLASH_DATA_FLASH_SW, *((volatile UINT32 *)0x20000)); + break; + + case CMD_FLASH_WRITE_ENABLE: + flash_write_enable(); + break; + + case CMD_FLASH_WRITE_DISABLE: + flash_write_disable(); + break; + + case CMD_FLASH_READ_SR: + (*(UINT16 *)parm) = flash_read_sr(2); + break; + + case CMD_FLASH_WRITE_SR: + flash_write_sr(*(unsigned long *)parm & 0x00FF, ((*(unsigned long *)parm) >> 8) & 0x00FFFF); + break; + + case CMD_FLASH_READ_QE: + (*(UINT8 *)parm) = flash_read_qe(); + break; + + case CMD_FLASH_SET_QE: + if(flash_current_config->qe_bit) + { + flash_set_qe(); + } + break; + + case CMD_FLASH_SET_QWFR: + flash_set_qwfr(); + break; + + case CMD_FLASH_CLR_QWFR: + flash_clr_qwfr(); + break; + + case CMD_FLASH_SET_WSR: + wsr = (*(UINT16 *)parm); + flash_set_wsr(wsr); + break; + + case CMD_FLASH_GET_ID: + (*(UINT32 *)parm) = flash_get_id(); + break; + + case CMD_FLASH_READ_MID: + (*(UINT32 *)parm) = flash_read_mid(); + break; + + case CMD_FLASH_ERASE_SECTOR: + address = (*(UINT32 *)parm); + flash_erase_sector(address); + break; + + case CMD_FLASH_SET_HPM: + flash_set_hpm(); + break; + + case CMD_FLASH_GET_PROTECT: + (*(UINT32 *)parm) = get_flash_protect(); + break; + + case CMD_FLASH_SET_PROTECT: + reg = (*(UINT32 *)parm); + flash_protection_op(FLASH_XTX_16M_SR_WRITE_DISABLE, reg); + break; + + default: + ret = FLASH_FAILURE; + break; + } + + if(4 == flash_current_config->line_mode) + { + flash_set_line_mode(LINE_MODE_FOUR); + //os_printf("change line mode 4\r\n"); + } + + peri_busy_count_dec(); + return ret; +} +// eof + diff --git a/beken_os/beken378/driver/flash/flash.h b/beken_os/beken378/driver/flash/flash.h new file mode 100755 index 0000000..5ae9572 --- /dev/null +++ b/beken_os/beken378/driver/flash/flash.h @@ -0,0 +1,116 @@ +#ifndef _FLASH_H_ +#define _FLASH_H_ + +#include "include.h" + +#define FLASH_DEBUG + +#ifdef FLASH_DEBUG +#define FLASH_PRT os_printf +#define FLASH_WARN warning_prf +#define FLASH_FATAL fatal_prf +#else +#define FLASH_PRT null_prf +#define FLASH_WARN null_prf +#define FLASH_FATAL null_prf +#endif + +#define MODE_STD 0 +#define MODE_DUAL 1 +#define MODE_QUAD 2 + +#define FLASH_BASE (0x00803000) + +#define REG_FLASH_OPERATE_SW (FLASH_BASE + 0 * 4) +#define ADDR_SW_REG_POSI (0) +#define ADDR_SW_REG_MASK (0x00FFFFFF) +#define OP_TYPE_SW_POSI (24) +#define OP_TYPE_SW_MASK (0x1F) +#define OP_SW (0x01UL << 29) +#define WP_VALUE (0x01UL << 30) +#define BUSY_SW (0x01UL << 31) + +#define REG_FLASH_DATA_SW_FLASH (FLASH_BASE + 1 * 4) + +#define REG_FLASH_DATA_FLASH_SW (FLASH_BASE + 2 * 4) + +#define REG_FLASH_RDID_DATA_FLASH (FLASH_BASE + 4 * 4) + +#define REG_FLASH_SR_DATA_CRC_CNT (FLASH_BASE + 5 * 4) +#define SR_DATA_FLASH_POSI (0) +#define SR_DATA_FLASH_MASK (0xFF) +#define CRC_ERROR_COUNT_POSI (8) +#define CRC_ERROR_COUNT_MASK (0xFF) +#define DATA_FLASH_SW_SEL_POSI (16) +#define DATA_FLASH_SW_SEL_MASK (0x07) +#define DATA_SW_FLASH_SEL_POSI (19) +#define DATA_SW_FLASH_SEL_MASK (0x07) + +#define REG_FLASH_CONF (FLASH_BASE + 7 * 4) +#define FLASH_CLK_CONF_POSI (0) +#define FLASH_CLK_CONF_MASK (0x0F) +#define MODEL_SEL_POSI (4) +#define MODEL_SEL_MASK (0x1F) +#define FWREN_FLASH_CPU (0x01UL << 9) +#define WRSR_DATA_POSI (10) +#define WRSR_DATA_MASK (0x00FFFF) +#define CRC_EN (0x01UL << 26) + +#define CPU_DATA_WR_POSI (9) +#define CPU_DATA_WR_MASK (0x01) + +#define M_VALUE_POST 22 +#define M_VALUE_MASK 0xFF + +#define LINE_MODE_TWO 2 +#define LINE_MODE_FOUR 4 + +typedef enum +{ + FLASH_OPCODE_WREN = 1, + FLASH_OPCODE_WRDI = 2, + FLASH_OPCODE_RDSR = 3, + FLASH_OPCODE_WRSR = 4, + FLASH_OPCODE_READ = 5, + FLASH_OPCODE_RDSR2 = 6, + FLASH_OPCODE_WRSR2 = 7, + FLASH_OPCODE_PP = 12, + FLASH_OPCODE_SE = 13, + FLASH_OPCODE_BE1 = 14, + FLASH_OPCODE_BE2 = 15, + FLASH_OPCODE_CE = 16, + FLASH_OPCODE_DP = 17, + FLASH_OPCODE_RFDP = 18, + FLASH_OPCODE_RDID = 20, + FLASH_OPCODE_HPM = 21, + FLASH_OPCODE_CRMR = 22, + FLASH_OPCODE_CRMR2 = 23, +} FLASH_OPCODE; + +typedef struct +{ + uint32_t flash_id; + uint8_t sr_size; + uint32_t flash_size; + uint8_t line_mode; + uint8_t cmp_post; + uint8_t protect_post; + uint8_t protect_mask; + uint16_t protect_all; + uint16_t protect_none; + uint16_t protect_half; + uint16_t unprotect_last_block; + uint8_t qe_bit_post; + uint8_t qe_bit; + uint8_t m_value; + uint8_t mode_sel; +} flash_config_t; + +/******************************************************************************* +* Function Declarations +*******************************************************************************/ +UINT32 flash_read(char *user_buf, UINT32 count, UINT32 address); +UINT32 flash_write(char *user_buf, UINT32 count, UINT32 address); +UINT32 flash_ctrl(UINT32 cmd, void *parm); + +#endif //_FLASH_H_ diff --git a/beken_os/beken378/driver/general_dma/general_dma.c b/beken_os/beken378/driver/general_dma/general_dma.c new file mode 100755 index 0000000..b0f1b37 --- /dev/null +++ b/beken_os/beken378/driver/general_dma/general_dma.c @@ -0,0 +1,996 @@ +#include "include.h" +#include "arm_arch.h" + +#if CFG_GENERAL_DMA +#include "general_dma_pub.h" +#include "general_dma.h" + +#include "intc_pub.h" +#include "icu_pub.h" + +#include "drv_model_pub.h" +#include "mem_pub.h" + +static SDD_OPERATIONS gdma_op = +{ + gdma_ctrl +}; + +#if (CFG_SOC_NAME != SOC_BK7231) +void (*p_dma_fin_handler[GDMA_CHANNEL_MAX])(UINT32); +void (*p_dma_hfin_handler[GDMA_CHANNEL_MAX])(UINT32); +#endif + +static void gdma_isr(void); +static void dma_finnsh_callback_set(UINT32 channel, void (*func)(UINT32)); + + +static void gdma_set_dma_en(UINT32 channel, UINT32 enable) +{ + UINT32 reg_addr = GENER_DMA0_REG0_CONF + (channel * 8 * 4); + UINT32 reg_val = REG_READ(reg_addr); + if(enable) + reg_val |= GDMA_X_DMA_EN; + else + reg_val &= ~GDMA_X_DMA_EN; + REG_WRITE(reg_addr, reg_val); +} + +static UINT32 gdma_get_dma_en(UINT32 channel) +{ + UINT32 reg_addr = GENER_DMA0_REG0_CONF + (channel * 8 * 4); + + return REG_READ(reg_addr) & GDMA_X_DMA_EN; +} + +static void gdma_cfg_finish_inten(UINT32 channel, UINT32 enable) +{ + UINT32 reg_addr = GENER_DMA0_REG0_CONF + (channel * 8 * 4); + UINT32 reg_val = REG_READ(reg_addr); + if(enable) + reg_val |= GDMA_X_FIN_INTEN; + else + reg_val &= ~GDMA_X_FIN_INTEN; + REG_WRITE(reg_addr, reg_val); +} + +static void gdma_cfg_half_fin_inten(UINT32 channel, UINT32 enable) +{ + UINT32 reg_addr = GENER_DMA0_REG0_CONF + (channel * 8 * 4); + UINT32 reg_val = REG_READ(reg_addr); + if(enable) + reg_val |= GDMA_X_HFIN_INTEN; + else + reg_val &= ~GDMA_X_HFIN_INTEN; + REG_WRITE(reg_addr, reg_val); +} + +#if (CFG_SOC_NAME != SOC_BK7231) +static void gdma_cfg_work_mode(UINT32 channel, UINT32 repeat) +{ + UINT32 reg_addr = GENER_DMA0_REG0_CONF + (channel * 8 * 4); + UINT32 reg_val = REG_READ(reg_addr); + if(repeat) + reg_val |= GDMA_X_REPEAT_MODE; + else + reg_val &= ~GDMA_X_REPEAT_MODE; + REG_WRITE(reg_addr, reg_val); +} +#endif // (CFG_SOC_NAME != SOC_BK7231) + +static void gdma_cfg_srcdata_width(UINT32 channel, UINT32 bitwidth) +{ + UINT32 reg_addr = GENER_DMA0_REG0_CONF + (channel * 8 * 4); + UINT32 reg_val = REG_READ(reg_addr); + reg_val &= ~(GDMA_X_SRCDATA_WIDTH_MASK << GDMA_X_SRCDATA_WIDTH_POSI); + + switch(bitwidth) + { + case 8: + reg_val |= (GDMA_DATA_WIDTH_8BIT << GDMA_X_SRCDATA_WIDTH_POSI); + break; + case 16: + reg_val |= (GDMA_DATA_WIDTH_16BIT << GDMA_X_SRCDATA_WIDTH_POSI); + break; + case 32: + reg_val |= (GDMA_DATA_WIDTH_32BIT << GDMA_X_SRCDATA_WIDTH_POSI); + break; + default: + reg_val |= (GDMA_DATA_WIDTH_32BIT << GDMA_X_SRCDATA_WIDTH_POSI); + break; + } + REG_WRITE(reg_addr, reg_val); +} + +static void gdma_cfg_dstdata_width(UINT32 channel, UINT32 bitwidth) +{ + UINT32 reg_addr = GENER_DMA0_REG0_CONF + (channel * 8 * 4); + UINT32 reg_val = REG_READ(reg_addr); + reg_val &= ~(GDMA_X_DSTDATA_WIDTH_MASK << GDMA_X_DSTDATA_WIDTH_POSI); + + switch(bitwidth) + { + case 8: + reg_val |= (GDMA_DATA_WIDTH_8BIT << GDMA_X_DSTDATA_WIDTH_POSI); + break; + case 16: + reg_val |= (GDMA_DATA_WIDTH_16BIT << GDMA_X_DSTDATA_WIDTH_POSI); + break; + case 32: + reg_val |= (GDMA_DATA_WIDTH_32BIT << GDMA_X_DSTDATA_WIDTH_POSI); + break; + default: + reg_val |= (GDMA_DATA_WIDTH_32BIT << GDMA_X_DSTDATA_WIDTH_POSI); + break; + } + REG_WRITE(reg_addr, reg_val); +} + +static void gdma_cfg_srcaddr_increase(UINT32 channel, UINT32 incr) +{ + UINT32 reg_addr = GENER_DMA0_REG0_CONF + (channel * 8 * 4); + UINT32 reg_val = REG_READ(reg_addr); + if(incr) + reg_val |= GDMA_X_SRCADDR_INC; + else + reg_val &= ~GDMA_X_SRCADDR_INC; + REG_WRITE(reg_addr, reg_val); +} + +static void gdma_cfg_dstaddr_increase(UINT32 channel, UINT32 incr) +{ + UINT32 reg_addr = GENER_DMA0_REG0_CONF + (channel * 8 * 4); + UINT32 reg_val = REG_READ(reg_addr); + if(incr) + reg_val |= GDMA_X_DSTADDR_INC; + else + reg_val &= ~GDMA_X_DSTADDR_INC; + REG_WRITE(reg_addr, reg_val); +} + +static void gdma_cfg_srcaddr_loop(UINT32 channel, UINT32 loop) +{ + UINT32 reg_addr = GENER_DMA0_REG0_CONF + (channel * 8 * 4); + UINT32 reg_val = REG_READ(reg_addr); + if(loop) + reg_val |= GDMA_X_SRCADDR_LOOP; + else + reg_val &= ~GDMA_X_SRCADDR_LOOP; + REG_WRITE(reg_addr, reg_val); +} + +static void gdma_cfg_dstaddr_loop(UINT32 channel, UINT32 loop) +{ + UINT32 reg_addr = GENER_DMA0_REG0_CONF + (channel * 8 * 4); + UINT32 reg_val = REG_READ(reg_addr); + if(loop) + reg_val |= GDMA_X_DSTADDR_LOOP; + else + reg_val &= ~GDMA_X_DSTADDR_LOOP; + REG_WRITE(reg_addr, reg_val); +} + +static void gdma_set_channel_prioprity(UINT32 channel, UINT32 prio) +{ + UINT32 reg_addr = GENER_DMA0_REG0_CONF + (channel * 8 * 4); + UINT32 reg_val = REG_READ(reg_addr); + + reg_val &= ~(GDMA_X_CHNL_PRIO_MASK << GDMA_X_CHNL_PRIO_POSI); + reg_val |= ((prio & GDMA_X_CHNL_PRIO_MASK) << GDMA_X_CHNL_PRIO_POSI); + + REG_WRITE(reg_addr, reg_val); +} + +static void gdma_set_transfer_length(UINT32 channel, UINT32 len) +{ + UINT32 reg_addr = GENER_DMA0_REG0_CONF + (channel * 8 * 4); + UINT32 reg_val = REG_READ(reg_addr); + + reg_val &= ~(GDMA_X_TRANS_LEN_MASK << GDMA_X_TRANS_LEN_POSI); + reg_val |= (((len - 1) & GDMA_X_TRANS_LEN_MASK) << GDMA_X_TRANS_LEN_POSI); + + REG_WRITE(reg_addr, reg_val); +} + +static UINT32 gdma_get_transfer_length(UINT32 channel) +{ + UINT32 reg_addr = GENER_DMA0_REG0_CONF + (channel * 8 * 4); + UINT32 reg_val = REG_READ(reg_addr); + + return ((reg_val >> GDMA_X_TRANS_LEN_POSI) & GDMA_X_TRANS_LEN_MASK) + 1; +} + +static void gdma_set_dst_start_addr(UINT32 channel, void *dstptr) +{ + UINT32 reg_addr = GENER_DMA0_REG1_DST_START_ADDR + (channel * 8 * 4); + REG_WRITE(reg_addr, (UINT32)dstptr); +} + +static void gdma_set_src_start_addr(UINT32 channel, void *srcptr) +{ + UINT32 reg_addr = GENER_DMA0_REG2_SRC_START_ADDR + (channel * 8 * 4); + REG_WRITE(reg_addr, (UINT32)srcptr); +} + +static void gdma_set_dstloop_endaddr(UINT32 channel, void *dendptr) +{ + UINT32 reg_addr = GENER_DMA0_REG3_DSTLOOP_END_ADDR + (channel * 8 * 4); + REG_WRITE(reg_addr, (UINT32)dendptr); +} + +static void gdma_set_dstloop_startaddr(UINT32 channel, void *dstartptr) +{ + UINT32 reg_addr = GENER_DMA0_REG4_DSTLOOP_START_ADDR + (channel * 8 * 4); + REG_WRITE(reg_addr, (UINT32)dstartptr); +} + +static void gdma_set_srcloop_endaddr(UINT32 channel, void *sendptr) +{ + UINT32 reg_addr = GENER_DMA0_REG5_SRCLOOP_END_ADDR + (channel * 8 * 4); + REG_WRITE(reg_addr, (UINT32)sendptr); +} + +static void gdma_set_srcloop_startaddr(UINT32 channel, void *sstartptr) +{ + UINT32 reg_addr = GENER_DMA0_REG6_SRCLOOP_START_ADDR + (channel * 8 * 4); + REG_WRITE(reg_addr, (UINT32)sstartptr); +} + +#if (CFG_SOC_NAME == SOC_BK7231) +static UINT32 gdma_get_remain_len(UINT32 channel) +{ + UINT32 reg_addr = GENER_DMA0_REG7_REMAIN_LEN + (channel * 8 * 4); + return REG_READ(reg_addr) & GDMA_REMAIN_LEN_MASK; +} +#else +static UINT32 gdma_get_remain_len(UINT32 channel) +{ + UINT32 reg_addr = GENER_DMA0_REG30_INT_CNTS + (channel * 4); + UINT32 reg_val = REG_READ(reg_addr); + + return ((reg_val >> GDMA_X_REMAIN_LEN_POSI) & GDMA_X_REMAIN_LEN_MASK); +} + +static void gdma_set_src_reqmux(UINT32 channel, UINT32 reqmux) +{ + UINT32 reg_addr = GENER_DMA0_REG7_MUX_REQS + (channel * 8 * 4); + UINT32 reg_val = REG_READ(reg_addr); + + reg_val &= ~(GDMA_X_SRC_REQ_MASK << GDMA_X_SRC_REQ_POSI); + + reg_val |= ((reqmux & GDMA_X_SRC_REQ_MASK) << GDMA_X_SRC_REQ_POSI); + + REG_WRITE(reg_addr, reg_val); +} + +static void gdma_set_dst_reqmux(UINT32 channel, UINT32 reqmux) +{ + UINT32 reg_addr = GENER_DMA0_REG7_MUX_REQS + (channel * 8 * 4); + UINT32 reg_val = REG_READ(reg_addr); + + reg_val &= ~(GDMA_X_DST_REQ_MASK << GDMA_X_DST_REQ_POSI); + + reg_val |= ((reqmux & GDMA_X_DST_REQ_MASK) << GDMA_X_DST_REQ_POSI); + + REG_WRITE(reg_addr, reg_val); +} + +static void gdma_set_dctm_write_wd(UINT32 channel, UINT32 read4byte) +{ + UINT32 reg_addr = GENER_DMA0_REG7_MUX_REQS + (channel * 8 * 4); + UINT32 reg_val = REG_READ(reg_addr); + + if(read4byte) + reg_val |= GDMA_X_DTCM_WR_WAIT_WORD; + else + reg_val &= ~GDMA_X_DTCM_WR_WAIT_WORD; + REG_WRITE(reg_addr, reg_val); +} + +static UINT32 gdma_get_finish_cnt(UINT32 channel) +{ + UINT32 reg_addr = GENER_DMA0_REG30_INT_CNTS + (channel * 4); + UINT32 reg_val = REG_READ(reg_addr); + + return ((reg_val >> GDMA_X_FIN_CNT_POSI) & GDMA_X_FIN_CNT_MASK); +} + +static UINT32 gdma_get_half_finish_cnt(UINT32 channel) +{ + UINT32 reg_addr = GENER_DMA0_REG30_INT_CNTS + (channel * 4); + UINT32 reg_val = REG_READ(reg_addr); + + return ((reg_val >> GDMA_X_HFIN_CNT_POSI) & GDMA_X_HFIN_CNT_MASK); +} + +static void gdma_set_priority(UINT32 fixed) +{ + UINT32 reg_val = REG_READ(GENER_DMA_REG37_PRIO_MODE); + + if(fixed) + reg_val |= GDMA_PRIO_FIXED; + else + reg_val &= ~GDMA_PRIO_FIXED; + REG_WRITE(GENER_DMA_REG37_PRIO_MODE, reg_val); +} + +#endif // (CFG_SOC_NAME == SOC_BK7231) + +static UINT32 gdma_get_finish_interrupt_bit(UINT32 channel) +{ + #if (CFG_SOC_NAME == SOC_BK7231) + UINT32 reg_val = REG_READ(GENER_DMA_REG20_DMA_INT_STATUS); + #else + UINT32 reg_val = REG_READ(GENER_DMA_REG38_DMA_INT_STATUS); + #endif // (CFG_SOC_NAME == SOC_BK7231) + + reg_val &= GENER_DMA_FIN_INT_STATUS_MASK; + reg_val &= (0x1 << channel); + reg_val = reg_val >> channel;; + return reg_val; +} + +static void gdma_clr_finish_interrupt_bit(UINT32 channel) +{ + UINT32 reg_val; + + reg_val = ( 0x1 << channel); + + #if (CFG_SOC_NAME == SOC_BK7231) + REG_WRITE(GENER_DMA_REG20_DMA_INT_STATUS, reg_val); + #else + REG_WRITE(GENER_DMA_REG38_DMA_INT_STATUS, reg_val); + #endif // (CFG_SOC_NAME == SOC_BK7231) +} + +static UINT32 gdma_get_half_finish_interrupt_bit(UINT32 channel) +{ + #if (CFG_SOC_NAME == SOC_BK7231) + UINT32 reg_val = REG_READ(GENER_DMA_REG20_DMA_INT_STATUS); + #else + UINT32 reg_val = REG_READ(GENER_DMA_REG38_DMA_INT_STATUS); + #endif // (CFG_SOC_NAME == SOC_BK7231) + + reg_val &= (GENER_DMA_HFIN_INT_STATUS_MASK << GENER_DMA_HFIN_INT_STATUS_POSI); + reg_val &= (0x1 << (channel + GENER_DMA_HFIN_INT_STATUS_POSI)); + reg_val = (reg_val >> (channel + GENER_DMA_HFIN_INT_STATUS_POSI)); + return reg_val; +} + +static void gdma_clr_half_finish_interrupt_bit(UINT32 channel) +{ + UINT32 reg_val; + + reg_val = ( 0x1 << (channel + GENER_DMA_HFIN_INT_STATUS_POSI)); + + #if (CFG_SOC_NAME == SOC_BK7231) + REG_WRITE(GENER_DMA_REG20_DMA_INT_STATUS, reg_val); + #else + REG_WRITE(GENER_DMA_REG38_DMA_INT_STATUS, reg_val); + #endif // (CFG_SOC_NAME == SOC_BK7231) +} + +static void gdma_enable_interrupt(void) +{ + UINT32 param; + param = (IRQ_GDMA_BIT); + sddev_control(ICU_DEV_NAME, CMD_ICU_INT_ENABLE, ¶m); +} + +static void gdma_disable_interrupt(void) +{ + UINT32 param; + param = (IRQ_GDMA_BIT); + sddev_control(ICU_DEV_NAME, CMD_ICU_INT_DISABLE, ¶m); +} + +#if (CFG_SOC_NAME == SOC_BK7221U) +static void gdma_set_src_pause_addr(UINT32 channel, UINT32 addr) +{ + UINT32 param = addr; + UINT32 reg_addr = GENER_DMA0_REG40_SRC_PAUSE_ADDR + (channel * 4); + + //os_printf("set src pause:%d, %x\r\n", channel, addr); + REG_WRITE(reg_addr, addr); +} + +static UINT32 gdma_get_src_pause_addr(UINT32 channel) +{ + UINT32 reg_addr = GENER_DMA0_REG40_SRC_PAUSE_ADDR + (channel * 4); + UINT32 reg_val = REG_READ(reg_addr); + + return reg_val; +} + +static void gdma_set_dest_pause_addr(UINT32 channel, UINT32 addr) +{ + UINT32 param = addr; + UINT32 reg_addr = GENER_DMA0_REG48_DST_PAUSE_ADDR + (channel * 4); + + REG_WRITE(reg_addr, addr); +} + +static UINT32 gdma_get_dest_pause_addr(UINT32 channel) +{ + UINT32 reg_addr = GENER_DMA0_REG48_DST_PAUSE_ADDR + (channel * 4); + UINT32 reg_val = REG_READ(reg_addr); + + return reg_val; +} + +static UINT32 gdma_get_src_read_addr(UINT32 channel) +{ + UINT32 reg_addr = GENER_DMA0_REG50_SRC_RD_ADDR + (channel * 4); + UINT32 reg_val = REG_READ(reg_addr); + + //os_printf("get src read:%d, %x\r\n", channel, reg_val); + return reg_val; +} + +static UINT32 gdma_get_dest_write_addr(UINT32 channel) +{ + UINT32 reg_addr = GENER_DMA0_REG58_DST_WR_ADDR + (channel * 4); + UINT32 reg_val = REG_READ(reg_addr); + + return reg_val; +} +#endif // (CFG_SOC_NAME == SOC_BK7221U) + +/*---------------------------------------------------------------------------*/ +static int gdma_get_received_len(UINT32 channel) +{ + if(channel >= GDMA_CHANNEL_MAX) { + GENER_DMA_WPRT("gdma channel err\r\n"); + return 0; + } + + return (int)gdma_get_remain_len(channel); +} + +// no loop src, no loop dst +static void gdma_congfig_type0(GDMACFG_TPYES_PTR cfg) +{ + UINT32 reg_addr; + if(cfg->channel >= GDMA_CHANNEL_MAX) + { + GENER_DMA_WPRT("gdma channel err\r\n"); + return; + } + reg_addr = GENER_DMA0_REG0_CONF + (cfg->channel * 8 * 4); + REG_WRITE(reg_addr, 0); + + gdma_cfg_srcaddr_increase(cfg->channel, cfg->srcptr_incr); + gdma_cfg_dstaddr_increase(cfg->channel, cfg->dstptr_incr); + gdma_cfg_srcdata_width(cfg->channel, cfg->srcdat_width); + gdma_cfg_dstdata_width(cfg->channel, cfg->dstdat_width); + gdma_set_channel_prioprity(cfg->channel, cfg->prio); + //gdma_cfg_finish_inten(cfg->channel, 1); + + gdma_set_dst_start_addr(cfg->channel, cfg->dst_start_addr); + gdma_set_src_start_addr(cfg->channel, cfg->src_start_addr); +} + +// loop src, no loop dst +static void gdma_congfig_type1(GDMACFG_TPYES_PTR cfg) +{ + UINT32 reg_addr; + if(cfg->channel >= GDMA_CHANNEL_MAX) + { + GENER_DMA_WPRT("gdma channel err\r\n"); + return; + } + reg_addr = GENER_DMA0_REG0_CONF + (cfg->channel * 8 * 4); + REG_WRITE(reg_addr, 0); + + gdma_cfg_srcaddr_loop(cfg->channel, 1); + gdma_cfg_srcaddr_increase(cfg->channel, cfg->srcptr_incr); + gdma_cfg_dstaddr_increase(cfg->channel, cfg->dstptr_incr); + gdma_cfg_srcdata_width(cfg->channel, cfg->srcdat_width); + gdma_cfg_dstdata_width(cfg->channel, cfg->dstdat_width); + gdma_set_channel_prioprity(cfg->channel, cfg->prio); + //gdma_cfg_finish_inten(cfg->channel, 1); + + gdma_set_dst_start_addr(cfg->channel, cfg->dst_start_addr); + gdma_set_src_start_addr(cfg->channel, cfg->src_start_addr); + + gdma_set_srcloop_startaddr(cfg->channel, cfg->u.type1.src_loop_start_addr); + gdma_set_srcloop_endaddr(cfg->channel, cfg->u.type1.src_loop_end_addr); +} + +// no loop src, loop dst +static void gdma_congfig_type2(GDMACFG_TPYES_PTR cfg) +{ + UINT32 reg_addr; + if(cfg->channel >= GDMA_CHANNEL_MAX) + { + GENER_DMA_WPRT("gdma channel err\r\n"); + return; + } + reg_addr = GENER_DMA0_REG0_CONF + (cfg->channel * 8 * 4); + REG_WRITE(reg_addr, 0); + + gdma_cfg_dstaddr_loop(cfg->channel, 1); + gdma_cfg_srcaddr_increase(cfg->channel, cfg->srcptr_incr); + gdma_cfg_dstaddr_increase(cfg->channel, cfg->dstptr_incr); + gdma_cfg_srcdata_width(cfg->channel, cfg->srcdat_width); + gdma_cfg_dstdata_width(cfg->channel, cfg->dstdat_width); + gdma_set_channel_prioprity(cfg->channel, cfg->prio); + //gdma_cfg_finish_inten(cfg->channel, 1); + + gdma_set_dst_start_addr(cfg->channel, cfg->dst_start_addr); + gdma_set_src_start_addr(cfg->channel, cfg->src_start_addr); + + gdma_set_dstloop_startaddr(cfg->channel, cfg->u.type2.dst_loop_start_addr); + gdma_set_dstloop_endaddr(cfg->channel, cfg->u.type2.dst_loop_end_addr); +} + +// loop src, loop dst +static void gdma_congfig_type3(GDMACFG_TPYES_PTR cfg) +{ + UINT32 reg_addr; + if(cfg->channel >= GDMA_CHANNEL_MAX) + { + GENER_DMA_WPRT("gdma channel err\r\n"); + return; + } + reg_addr = GENER_DMA0_REG0_CONF + (cfg->channel * 8 * 4); + REG_WRITE(reg_addr, 0); + + gdma_cfg_srcaddr_loop(cfg->channel, 1); + gdma_cfg_dstaddr_loop(cfg->channel, 1); + + gdma_cfg_srcaddr_increase(cfg->channel, cfg->srcptr_incr); + gdma_cfg_dstaddr_increase(cfg->channel, cfg->dstptr_incr); + gdma_cfg_srcdata_width(cfg->channel, cfg->srcdat_width); + gdma_cfg_dstdata_width(cfg->channel, cfg->dstdat_width); + gdma_set_channel_prioprity(cfg->channel, cfg->prio); + //gdma_cfg_finish_inten(cfg->channel, 1); + + gdma_set_dst_start_addr(cfg->channel, cfg->dst_start_addr); + gdma_set_src_start_addr(cfg->channel, cfg->src_start_addr); + + gdma_set_srcloop_startaddr(cfg->channel, cfg->u.type3.src_loop_start_addr); + gdma_set_srcloop_endaddr(cfg->channel, cfg->u.type3.src_loop_end_addr); + gdma_set_dstloop_startaddr(cfg->channel, cfg->u.type3.dst_loop_start_addr); + gdma_set_dstloop_endaddr(cfg->channel, cfg->u.type3.dst_loop_end_addr); +} + + +#if(CFG_SOC_NAME != SOC_BK7231) +// memery to module fifo to , so dest is register -- src is memery and loop +static void gdma_congfig_type4(GDMACFG_TPYES_PTR cfg) +{ + UINT32 reg_addr; + if(cfg->channel >= GDMA_CHANNEL_MAX) + { + GENER_DMA_WPRT("gdma channel err\r\n"); + return; + } + reg_addr = GENER_DMA0_REG0_CONF + (cfg->channel * 8 * 4); + REG_WRITE(reg_addr, 0); + + gdma_set_src_reqmux(cfg->channel, cfg->src_module); + gdma_set_dst_reqmux(cfg->channel, cfg->dst_module); + gdma_cfg_work_mode(cfg->channel, 1); // repeat mode + + gdma_cfg_srcaddr_loop(cfg->channel, 1); + + gdma_cfg_dstaddr_increase(cfg->channel, 0); + gdma_cfg_srcaddr_increase(cfg->channel, cfg->srcptr_incr); + + gdma_cfg_srcdata_width(cfg->channel, cfg->srcdat_width); + gdma_cfg_dstdata_width(cfg->channel, cfg->dstdat_width); + gdma_set_channel_prioprity(cfg->channel, cfg->prio); + + gdma_set_dst_start_addr(cfg->channel, cfg->dst_start_addr); + gdma_set_src_start_addr(cfg->channel, cfg->src_start_addr); + + gdma_set_srcloop_startaddr(cfg->channel, cfg->u.type4.src_loop_start_addr); + gdma_set_srcloop_endaddr(cfg->channel, cfg->u.type4.src_loop_end_addr); + + if(cfg->fin_handler) { + gdma_cfg_finish_inten(cfg->channel, 1); + p_dma_fin_handler[cfg->channel] = cfg->fin_handler; + } + + if(cfg->half_fin_handler) { + gdma_cfg_half_fin_inten(cfg->channel, 1); + p_dma_hfin_handler[cfg->channel] = cfg->half_fin_handler; + } +} + +// module fifo to memery, so src is register -- dst is memery and loop +static void gdma_congfig_type5(GDMACFG_TPYES_PTR cfg) +{ + UINT32 reg_addr; + if(cfg->channel >= GDMA_CHANNEL_MAX) + { + GENER_DMA_WPRT("gdma channel err\r\n"); + return; + } + reg_addr = GENER_DMA0_REG0_CONF + (cfg->channel * 8 * 4); + REG_WRITE(reg_addr, 0); + + gdma_set_src_reqmux(cfg->channel, cfg->src_module); + gdma_set_dst_reqmux(cfg->channel, cfg->dst_module); + gdma_cfg_work_mode(cfg->channel, 1); // repeat mode + + gdma_cfg_dstaddr_loop(cfg->channel, 1); + + gdma_cfg_srcaddr_increase(cfg->channel, 0); + gdma_cfg_dstaddr_increase(cfg->channel, cfg->dstptr_incr); + + gdma_cfg_srcdata_width(cfg->channel, cfg->srcdat_width); + gdma_cfg_dstdata_width(cfg->channel, cfg->dstdat_width); + gdma_set_channel_prioprity(cfg->channel, cfg->prio); + + gdma_set_dst_start_addr(cfg->channel, cfg->dst_start_addr); + gdma_set_src_start_addr(cfg->channel, cfg->src_start_addr); + + gdma_set_dstloop_startaddr(cfg->channel, cfg->u.type5.dst_loop_start_addr); + gdma_set_dstloop_endaddr(cfg->channel, cfg->u.type5.dst_loop_end_addr); + + if(cfg->fin_handler) { + gdma_cfg_finish_inten(cfg->channel, 1); + p_dma_fin_handler[cfg->channel] = cfg->fin_handler; + } + + if(cfg->half_fin_handler) { + gdma_cfg_half_fin_inten(cfg->channel, 1); + p_dma_hfin_handler[cfg->channel] = cfg->half_fin_handler; + } +} + +static void gdma_congfig_type6(GDMACFG_TPYES_PTR cfg) +{ + GENER_DMA_WPRT("no gdma_congfig_type6\r\n"); + return; +} +#endif + +static UINT32 gdma_enable( GDMA_DO_PTR do_st ) +{ + GLOBAL_INT_DECLARATION(); + if(!do_st->length) + return 0; + + GLOBAL_INT_DISABLE(); + gdma_set_dst_start_addr(do_st->channel, do_st->dst_addr); + gdma_set_src_start_addr(do_st->channel, do_st->src_addr); + gdma_set_transfer_length(do_st->channel, do_st->length); + + GENER_DMA_PRT("%p,%p,%d\r\n", do_st->dst_addr, do_st->src_addr, do_st->length); + + gdma_set_dma_en(do_st->channel, 1); + #if (CFG_SOC_NAME == SOC_BK7231) + while(!gdma_get_finish_interrupt_bit(do_st->channel)); + gdma_clr_finish_interrupt_bit(do_st->channel); + #else + while(gdma_get_dma_en(do_st->channel)); + //gdma_clr_finish_interrupt_bit(do_st->channel); + #endif // (CFG_SOC_NAME == SOC_BK7231) + GLOBAL_INT_RESTORE(); + + return do_st->length; +} + +/*---------------------------------------------------------------------------*/ +void gdma_init(void) +{ + GDMACFG_TPYES_ST cfg; + + intc_service_register(IRQ_GENERDMA, PRI_IRQ_GENERDMA, gdma_isr); + sddev_register_dev(GDMA_DEV_NAME, &gdma_op); + + #if (CFG_SOC_NAME != SOC_BK7231) + for(int i=0; ichannel, dma_cfg->param); + break; + case CMD_GDMA_CFG_FIN_INT_ENABLE: + gdma_cfg_finish_inten(dma_cfg->channel, dma_cfg->param); + break; + case CMD_GDMA_CFG_HFIN_INT_ENABLE: + gdma_cfg_half_fin_inten(dma_cfg->channel, dma_cfg->param); + break; + #if (CFG_SOC_NAME != SOC_BK7231) + case CMD_GDMA_CFG_WORK_MODE: + gdma_cfg_work_mode(dma_cfg->channel, dma_cfg->param); + break; + #endif // (CFG_SOC_NAME != SOC_BK7231) + case CMD_GDMA_CFG_SRCDATA_WIDTH: + gdma_cfg_srcdata_width(dma_cfg->channel, dma_cfg->param); + break; + case CMD_GDMA_CFG_DSTDATA_WIDTH: + gdma_cfg_dstdata_width(dma_cfg->channel, dma_cfg->param); + break; + case CMD_GDMA_CFG_SRCADDR_INCREASE: + gdma_cfg_srcaddr_increase(dma_cfg->channel, dma_cfg->param); + break; + case CMD_GDMA_CFG_DSTADDR_INCREASE: + gdma_cfg_dstaddr_increase(dma_cfg->channel, dma_cfg->param); + break; + case CMD_GDMA_CFG_SRCADDR_LOOP: + gdma_cfg_srcaddr_loop(dma_cfg->channel, dma_cfg->param); + break; + case CMD_GDMA_CFG_DSTADDR_LOOP: + gdma_cfg_dstaddr_loop(dma_cfg->channel, dma_cfg->param); + break; + case CMD_GDMA_SET_CHNL_PRIO: + gdma_set_channel_prioprity(dma_cfg->channel, dma_cfg->param); + break; + case CMD_GDMA_SET_TRANS_LENGTH: + gdma_set_transfer_length(dma_cfg->channel, dma_cfg->param); + break; + case CMD_GDMA_SET_DST_START_ADDR: + gdma_set_dst_start_addr(dma_cfg->channel, (void *)dma_cfg->param); + break; + case CMD_GDMA_SET_SRC_START_ADDR: + gdma_set_src_start_addr(dma_cfg->channel, (void *)dma_cfg->param); + break; + case CMD_GDMA_SET_DST_LOOP_ENDADDR: + gdma_set_dstloop_endaddr(dma_cfg->channel, (void *)dma_cfg->param); + break; + case CMD_GDMA_SET_DST_LOOP_STARTADDR: + gdma_set_dstloop_startaddr(dma_cfg->channel, (void *)dma_cfg->param); + break; + case CMD_GDMA_SET_SRC_LOOP_ENDADDR: + gdma_set_srcloop_endaddr(dma_cfg->channel, (void *)dma_cfg->param); + break; + case CMD_GDMA_SET_SRC_LOOP_STARTADDR: + gdma_set_srcloop_startaddr(dma_cfg->channel, (void *)dma_cfg->param); + break; + case CMD_GDMA_GET_REMAIN_LENGTH: + ret = gdma_get_remain_len(dma_cfg->channel); + break; + #if (CFG_SOC_NAME != SOC_BK7231) + case CMD_GDMA_SET_DST_REQ_MUX: + gdma_set_dst_reqmux(dma_cfg->channel, dma_cfg->param); + break; + case CMD_GDMA_SET_SRC_REQ_MUX: + gdma_set_src_reqmux(dma_cfg->channel, dma_cfg->param); + break; + case CMD_GDMA_SET_DTCM_WRITE_WORD: + gdma_set_dctm_write_wd(dma_cfg->channel, dma_cfg->param); + break; + case CMD_GDMA_SET_FIN_CNT: + ret = gdma_get_finish_cnt((UINT32)param); + break; + case CMD_GDMA_SET_HFIN_CNT: + ret = gdma_get_half_finish_cnt(dma_cfg->channel); + break; + case CMD_GDMA_SET_PRIO_MODE: + gdma_set_priority(dma_cfg->param); + break; + #endif // (CFG_SOC_NAME != SOC_BK7231) + case CMD_GDMA_GET_FIN_INT_STATUS: + ret = gdma_get_finish_interrupt_bit(dma_cfg->channel); + break; + case CMD_GDMA_CLR_FIN_INT_STATUS: + gdma_clr_finish_interrupt_bit(dma_cfg->channel); + break; + case CMD_GDMA_GET_HFIN_INT_STATUS: + ret = gdma_get_half_finish_interrupt_bit(dma_cfg->channel); + break; + case CMD_GDMA_CLR_HFIN_INT_STATUS: + gdma_clr_half_finish_interrupt_bit(dma_cfg->channel); + break; + case CMD_GDMA_CFG_TYPE0: + gdma_congfig_type0((GDMACFG_TPYES_PTR)param); + break; + case CMD_GDMA_CFG_TYPE1: + gdma_congfig_type1((GDMACFG_TPYES_PTR)param); + break; + case CMD_GDMA_CFG_TYPE2: + gdma_congfig_type2((GDMACFG_TPYES_PTR)param); + break; + case CMD_GDMA_CFG_TYPE3: + gdma_congfig_type3((GDMACFG_TPYES_PTR)param); + break; +#if (CFG_SOC_NAME != SOC_BK7231) + case CMD_GDMA_CFG_TYPE4: + gdma_congfig_type4((GDMACFG_TPYES_PTR)param); + break; + case CMD_GDMA_CFG_TYPE5: + gdma_congfig_type5((GDMACFG_TPYES_PTR)param); + break; + case CMD_GDMA_CFG_TYPE6: + gdma_congfig_type6((GDMACFG_TPYES_PTR)param); + break; +#endif + case CMD_GDMA_ENABLE: + gdma_enable((GDMA_DO_PTR)param); + break; + #if (CFG_SOC_NAME != SOC_BK7231) + case CMD_GDMA_GET_LEFT_LEN: + ret = gdma_get_received_len((UINT32)param); + break; + #endif // (CFG_SOC_NAME != SOC_BK7231) + #if (CFG_SOC_NAME == SOC_BK7221U) + case CMD_GDMA_SET_SRC_PAUSE_ADDR: + gdma_set_src_pause_addr(dma_cfg->channel, dma_cfg->param); + break; + case CMD_GDMA_GET_SRC_PAUSE_ADDR: + ret = gdma_get_src_pause_addr(dma_cfg->channel); + break; + case CMD_GDMA_SET_DST_PAUSE_ADDR: + gdma_set_dest_pause_addr(dma_cfg->channel, dma_cfg->param); + break; + case CMD_GDMA_GET_DST_PAUSE_ADDR: + ret = gdma_get_src_pause_addr(dma_cfg->channel); + break; + case CMD_GDMA_GET_SRC_READ_ADDR: + ret = gdma_get_src_read_addr(dma_cfg->channel); + break; + case CMD_GDMA_GET_DST_WRITE_ADDR: + ret = gdma_get_dest_write_addr(dma_cfg->channel); + break; + case CMD_GDMA_SET_FIN_ISR: + dma_finnsh_callback_set(dma_cfg->channel, (void *)dma_cfg->param); + break; + #endif // (CFG_SOC_NAME == SOC_BK7221U) + default: + break; + } + + return ret; +} + +/*Before using this fuction, please config general dma moudule first*/ +void *gdma_memcpy(void *out, const void *in, UINT32 n) +{ + GLOBAL_INT_DECLARATION(); + GDMA_DO_ST do_st; + + do_st.channel = GDMA_CHANNEL_0; + do_st.src_addr = (void*)in; + do_st.length = n; + do_st.dst_addr = out; + GLOBAL_INT_DISABLE(); + gdma_enable(&do_st); + GLOBAL_INT_RESTORE(); + + return out; +} +static void dma_finnsh_callback_set(UINT32 channel, void (*func)(UINT32)) +{ + if(channel < GDMA_CHANNEL_MAX) { + p_dma_fin_handler[channel] = func; + } +} + + +static void gdma_isr(void) +{ + #if (CFG_SOC_NAME == SOC_BK7231) + GENER_DMA_PRT("gdma_isr is null\r\n"); + #else + UINT32 i, status, rev_len, cmp_bit; + + status = REG_READ(GENER_DMA_REG38_DMA_INT_STATUS); + + for(i = 0; i < GDMA_CHANNEL_MAX; i++) + { + rev_len = gdma_get_transfer_length(i) - gdma_get_remain_len(i); + cmp_bit = (1 << (i+GENER_DMA_HFIN_INT_STATUS_POSI)); + if(status & cmp_bit) + { + if(p_dma_hfin_handler[i]){ + p_dma_hfin_handler[i](0); + REG_WRITE(GENER_DMA_REG38_DMA_INT_STATUS, cmp_bit); + } + } + + cmp_bit = (1 << (i+GENER_DMA_FIN_INT_STATUS_POSI)); + if(status & cmp_bit) + { + if(p_dma_fin_handler[i]){ + p_dma_fin_handler[i](1); + REG_WRITE(GENER_DMA_REG38_DMA_INT_STATUS, cmp_bit); + } + } + } + #endif // (CFG_SOC_NAME == SOC_BK7231) +} + +#endif // CFG_GENERAL_DMA + diff --git a/beken_os/beken378/driver/general_dma/general_dma.h b/beken_os/beken378/driver/general_dma/general_dma.h new file mode 100755 index 0000000..9c6a0ea --- /dev/null +++ b/beken_os/beken378/driver/general_dma/general_dma.h @@ -0,0 +1,263 @@ +#ifndef __GENER_DMA_H__ +#define __GENER_DMA_H__ + +#if CFG_GENERAL_DMA + +//#define GENER_DMA_DEBUG + +#include "uart_pub.h" +#ifdef GENER_DMA_DEBUG +#define GENER_DMA_PRT os_printf +#define GENER_DMA_WPRT os_printf +#else +#define GENER_DMA_PRT null_prf +#define GENER_DMA_WPRT null_prf +#endif + +#define GENER_DMA_BASE (0x00809000) + +// DMA 0 +#define GENER_DMA0_REG0_CONF (GENER_DMA_BASE + 0x00*4) +#define GDMA_X_DMA_EN (1 << 0) +#define GDMA_X_FIN_INTEN (1 << 1) +#define GDMA_X_HFIN_INTEN (1 << 2) +#if (CFG_SOC_NAME != SOC_BK7231) +#define GDMA_X_REPEAT_MODE (1 << 3) +#endif // (CFG_SOC_NAME != SOC_BK7231) +#define GDMA_X_SRCDATA_WIDTH_POSI (4) +#define GDMA_X_SRCDATA_WIDTH_MASK (0x3) +#define GDMA_X_DSTDATA_WIDTH_POSI (6) +#define GDMA_X_DSTDATA_WIDTH_MASK (0x3) +#define GDMA_DATA_WIDTH_8BIT (0x0) +#define GDMA_DATA_WIDTH_16BIT (0x1) +#define GDMA_DATA_WIDTH_32BIT (0x2) +#define GDMA_X_SRCADDR_INC (1 << 8) +#define GDMA_X_DSTADDR_INC (1 << 9) +#define GDMA_X_SRCADDR_LOOP (1 << 10) +#define GDMA_X_DSTADDR_LOOP (1 << 11) +#define GDMA_X_CHNL_PRIO_POSI (12) +#define GDMA_X_CHNL_PRIO_MASK (0x3) +#define GDMA_X_TRANS_LEN_POSI (16) +#define GDMA_X_TRANS_LEN_MASK (0xffffU) + +#define GENER_DMA0_REG1_DST_START_ADDR (GENER_DMA_BASE + 0x01*4) + +#define GENER_DMA0_REG2_SRC_START_ADDR (GENER_DMA_BASE + 0x02*4) + +#define GENER_DMA0_REG3_DSTLOOP_END_ADDR (GENER_DMA_BASE + 0x03*4) + +#define GENER_DMA0_REG4_DSTLOOP_START_ADDR (GENER_DMA_BASE + 0x04*4) + +#define GENER_DMA0_REG5_SRCLOOP_END_ADDR (GENER_DMA_BASE + 0x05*4) + +#define GENER_DMA0_REG6_SRCLOOP_START_ADDR (GENER_DMA_BASE + 0x06*4) + +#if (CFG_SOC_NAME == SOC_BK7231) +#define GENER_DMA0_REG7_REMAIN_LEN (GENER_DMA_BASE + 0x07*4) +#define GDMA_REMAIN_LEN_MASK (0x1ffff) +#else +#define GENER_DMA0_REG7_MUX_REQS (GENER_DMA_BASE + 0x07*4) +#define GDMA_X_SRC_REQ_POSI (0) +#define GDMA_X_SRC_REQ_MASK (0xfU) +#define GDMA_X_DST_REQ_POSI (4) +#define GDMA_X_DST_REQ_MASK (0xfU) +#if (CFG_SOC_NAME == SOC_BK7221U) +#define GDMA_X_SRC_RD_INTVAL_POSI (12) +#define GDMA_X_SRC_RD_INTVAL_MASK (0xfU) +#define GDMA_X_DST_WR_INTVAL_POSI (16) +#define GDMA_X_DST_WR_INTVAL_MASK (0xfU) +#endif // (CFG_SOC_NAME == SOC_BK7221U) +#define GDMA_X_DTCM_WR_WAIT_WORD (1 << 8) +#endif // (CFG_SOC_NAME == SOC_BK7231) + +// DMA1 +#define GENER_DMA1_REG8_CONF (GENER_DMA_BASE + 0x08*4) + +#define GENER_DMA1_REG9_DST_START_ADDR (GENER_DMA_BASE + 0x09*4) + +#define GENER_DMA1_REGA_SRC_START_ADDR (GENER_DMA_BASE + 0x0A*4) + +#define GENER_DMA1_REGB_DSTLOOP_END_ADDR (GENER_DMA_BASE + 0x0B*4) + +#define GENER_DMA1_REGC_DSTLOOP_START_ADDR (GENER_DMA_BASE + 0x0C*4) + +#define GENER_DMA1_REGD_SRCLOOP_END_ADDR (GENER_DMA_BASE + 0x0D*4) + +#define GENER_DMA1_REGE_SRCLOOP_START_ADDR (GENER_DMA_BASE + 0x0E*4) + +#if (CFG_SOC_NAME == SOC_BK7231) +#define GENER_DMA1_REGF_REMAIN_LEN (GENER_DMA_BASE + 0x0F*4) +#else +#define GENER_DMA1_REGF_MUX_REQS (GENER_DMA_BASE + 0x0F*4) +#endif // (CFG_SOC_NAME == SOC_BK7231) + +// DMA2 +#define GENER_DMA2_REG10_CONF (GENER_DMA_BASE + 0x10*4) + +#define GENER_DMA2_REG11_DST_START_ADDR (GENER_DMA_BASE + 0x11*4) + +#define GENER_DMA2_REG12_SRC_START_ADDR (GENER_DMA_BASE + 0x12*4) + +#define GENER_DMA2_REG13_DSTLOOP_END_ADDR (GENER_DMA_BASE + 0x13*4) + +#define GENER_DMA2_REG14_DSTLOOP_START_ADDR (GENER_DMA_BASE + 0x14*4) + +#define GENER_DMA2_REG15_SRCLOOP_END_ADDR (GENER_DMA_BASE + 0x15*4) + +#define GENER_DMA2_REG16_SRCLOOP_START_ADDR (GENER_DMA_BASE + 0x16*4) + +#if (CFG_SOC_NAME == SOC_BK7231) +#define GENER_DMA2_REG17_REMAIN_LEN (GENER_DMA_BASE + 0x17*4) +#else +#define GENER_DMA2_REG17_MUX_REQS (GENER_DMA_BASE + 0x17*4) +#endif // (CFG_SOC_NAME == SOC_BK7231) + +// DMA3 +#define GENER_DMA3_REG18_CONF (GENER_DMA_BASE + 0x18*4) + +#define GENER_DMA3_REG19_DST_START_ADDR (GENER_DMA_BASE + 0x19*4) + +#define GENER_DMA3_REG1A_SRC_START_ADDR (GENER_DMA_BASE + 0x1A*4) + +#define GENER_DMA3_REG1B_DSTLOOP_END_ADDR (GENER_DMA_BASE + 0x1B*4) + +#define GENER_DMA3_REG1C_DSTLOOP_START_ADDR (GENER_DMA_BASE + 0x1C*4) + +#define GENER_DMA3_REG1D_SRCLOOP_END_ADDR (GENER_DMA_BASE + 0x1D*4) + +#define GENER_DMA3_REG1E_SRCLOOP_START_ADDR (GENER_DMA_BASE + 0x1E*4) + +#if (CFG_SOC_NAME == SOC_BK7231) +#define GENER_DMA3_REG1F_REMAIN_LEN (GENER_DMA_BASE + 0x1F*4) +#else +#define GENER_DMA3_REG1F_MUX_REQS (GENER_DMA_BASE + 0x1F*4) +#endif // (CFG_SOC_NAME == SOC_BK7231) + +#if (CFG_SOC_NAME == SOC_BK7231) +#define GENER_DMA_REG20_DMA_INT_STATUS (GENER_DMA_BASE + 0x20*4) +#define GENER_DMA_FIN_INT_STATUS_POSI (0) +#define GENER_DMA_FIN_INT_STATUS_MASK (0xf) +#define GENER_DMA_HFIN_INT_STATUS_POSI (8) +#define GENER_DMA_HFIN_INT_STATUS_MASK (0xf) +#else +// DMA4 +#define GENER_DMA4_REG20_CONF (GENER_DMA_BASE + 0x20*4) + +#define GENER_DMA4_REG21_DST_START_ADDR (GENER_DMA_BASE + 0x21*4) + +#define GENER_DMA4_REG22_SRC_START_ADDR (GENER_DMA_BASE + 0x22*4) + +#define GENER_DMA4_REG23_DSTLOOP_END_ADDR (GENER_DMA_BASE + 0x23*4) + +#define GENER_DMA4_REG24_DSTLOOP_START_ADDR (GENER_DMA_BASE + 0x24*4) + +#define GENER_DMA4_REG25_SRCLOOP_END_ADDR (GENER_DMA_BASE + 0x25*4) + +#define GENER_DMA4_REG26_SRCLOOP_START_ADDR (GENER_DMA_BASE + 0x26*4) + +#define GENER_DMA4_REG27_MUX_REQS (GENER_DMA_BASE + 0x27*4) + +// DMA5 +#define GENER_DMA5_REG28_CONF (GENER_DMA_BASE + 0x28*4) + +#define GENER_DMA5_REG29_DST_START_ADDR (GENER_DMA_BASE + 0x29*4) + +#define GENER_DMA5_REG2A_SRC_START_ADDR (GENER_DMA_BASE + 0x2A*4) + +#define GENER_DMA5_REG2B_DSTLOOP_END_ADDR (GENER_DMA_BASE + 0x2B*4) + +#define GENER_DMA5_REG2C_DSTLOOP_START_ADDR (GENER_DMA_BASE + 0x2C*4) + +#define GENER_DMA5_REG2D_SRCLOOP_END_ADDR (GENER_DMA_BASE + 0x2D*4) + +#define GENER_DMA5_REG2E_SRCLOOP_START_ADDR (GENER_DMA_BASE + 0x2E*4) + +#define GENER_DMA5_REG2F_MUX_REQS (GENER_DMA_BASE + 0x2F*4) + +#define GENER_DMA0_REG30_INT_CNTS (GENER_DMA_BASE + 0x30*4) +#define GDMA_X_REMAIN_LEN_POSI (0) +#define GDMA_X_REMAIN_LEN_MASK (0x1ffff) +#define GDMA_X_FIN_CNT_POSI (24) +#define GDMA_X_FIN_CNT_MASK (0xf) +#define GDMA_X_HFIN_CNT_POSI (28) +#define GDMA_X_HFIN_CNT_MASK (0xf) + +#define GENER_DMA1_REG31_INT_CNTS (GENER_DMA_BASE + 0x31*4) + +#define GENER_DMA2_REG32_INT_CNTS (GENER_DMA_BASE + 0x32*4) + +#define GENER_DMA3_REG32_INT_CNTS (GENER_DMA_BASE + 0x33*4) + +#define GENER_DMA4_REG34_INT_CNTS (GENER_DMA_BASE + 0x34*4) + +#define GENER_DMA5_REG35_INT_CNTS (GENER_DMA_BASE + 0x35*4) + +#define GENER_DMA_REG37_PRIO_MODE (GENER_DMA_BASE + 0x37*4) +#define GDMA_PRIO_FIXED (1 << 0) // 0: round-robin + +#define GENER_DMA_REG38_DMA_INT_STATUS (GENER_DMA_BASE + 0x38*4) +#define GENER_DMA_FIN_INT_STATUS_POSI (0) +#define GENER_DMA_FIN_INT_STATUS_MASK (0x3f) +#define GENER_DMA_HFIN_INT_STATUS_POSI (8) +#define GENER_DMA_HFIN_INT_STATUS_MASK (0x3f) + +#if (CFG_SOC_NAME == SOC_BK7221U) +#define GENER_DMA0_REG40_SRC_PAUSE_ADDR (GENER_DMA_BASE + 0x40*4) + +#define GENER_DMA1_REG41_SRC_PAUSE_ADDR (GENER_DMA_BASE + 0x41*4) + +#define GENER_DMA2_REG42_SRC_PAUSE_ADDR (GENER_DMA_BASE + 0x42*4) + +#define GENER_DMA3_REG43_SRC_PAUSE_ADDR (GENER_DMA_BASE + 0x43*4) + +#define GENER_DMA4_REG44_SRC_PAUSE_ADDR (GENER_DMA_BASE + 0x44*4) + +#define GENER_DMA5_REG45_SRC_PAUSE_ADDR (GENER_DMA_BASE + 0x45*4) + + +#define GENER_DMA0_REG48_DST_PAUSE_ADDR (GENER_DMA_BASE + 0x48*4) + +#define GENER_DMA1_REG49_DST_PAUSE_ADDR (GENER_DMA_BASE + 0x49*4) + +#define GENER_DMA2_REG4A_DST_PAUSE_ADDR (GENER_DMA_BASE + 0x4A*4) + +#define GENER_DMA3_REG4B_DST_PAUSE_ADDR (GENER_DMA_BASE + 0x4B*4) + +#define GENER_DMA4_REG4C_DST_PAUSE_ADDR (GENER_DMA_BASE + 0x4C*4) + +#define GENER_DMA5_REG4D_DST_PAUSE_ADDR (GENER_DMA_BASE + 0x4D*4) + + +#define GENER_DMA0_REG50_SRC_RD_ADDR (GENER_DMA_BASE + 0x50*4) + +#define GENER_DMA1_REG51_SRC_RD_ADDR (GENER_DMA_BASE + 0x51*4) + +#define GENER_DMA2_REG52_SRC_RD_ADDR (GENER_DMA_BASE + 0x52*4) + +#define GENER_DMA3_REG53_SRC_RD_ADDR (GENER_DMA_BASE + 0x53*4) + +#define GENER_DMA4_REG54_SRC_RD_ADDR (GENER_DMA_BASE + 0x54*4) + +#define GENER_DMA5_REG55_SRC_RD_ADDR (GENER_DMA_BASE + 0x55*4) + + +#define GENER_DMA0_REG58_DST_WR_ADDR (GENER_DMA_BASE + 0x58*4) + +#define GENER_DMA1_REG59_DST_WR_ADDR (GENER_DMA_BASE + 0x59*4) + +#define GENER_DMA2_REG5A_DST_WR_ADDR (GENER_DMA_BASE + 0x5A*4) + +#define GENER_DMA3_REG5B_DST_WR_ADDR (GENER_DMA_BASE + 0x5B*4) + +#define GENER_DMA4_REG5C_DST_WR_ADDR (GENER_DMA_BASE + 0x5C*4) + +#define GENER_DMA5_REG5D_DST_WR_ADDR (GENER_DMA_BASE + 0x5D*4) +#endif // (CFG_SOC_NAME == SOC_BK7221U) + +#endif // (CFG_SOC_NAME == SOC_BK7231) + +UINT32 gdma_ctrl(UINT32 cmd, void *param); + +#endif // CFG_GENERAL_DMA + +#endif // __GENER_DMA_H__ diff --git a/beken_os/beken378/driver/gpio/gpio.c b/beken_os/beken378/driver/gpio/gpio.c new file mode 100755 index 0000000..cdb90de --- /dev/null +++ b/beken_os/beken378/driver/gpio/gpio.c @@ -0,0 +1,825 @@ +#include "include.h" +#include "arm_arch.h" +#include "gpio_pub.h" +#include "gpio.h" +#include "drv_model_pub.h" +#include "sys_ctrl_pub.h" +#include "uart_pub.h" +#include "intc_pub.h" +#include "icu_pub.h" + +static void (*p_gpio_intr_handler[GPIONUM])(unsigned char ); + +static SDD_OPERATIONS gpio_op = +{ + gpio_ctrl +}; +static int gpio_ops_filter_flag = 0; + +void gpio_isr(void) +{ + int i; + unsigned long ulIntStatus; + + ulIntStatus = *(volatile UINT32 *)REG_GPIO_INTSTA; + for (i = 0; i < GPIONUM; i++) + { + if (ulIntStatus & (0x01UL << i)) + { + if (p_gpio_intr_handler[i] != NULL) + { + (void)p_gpio_intr_handler[i]((unsigned char)i); + } + } + } + + *(volatile UINT32 *)REG_GPIO_INTSTA = ulIntStatus; +} + +static UINT32 gpio_ops_filter(UINT32 index) +{ + UINT32 ret; + + ret = GPIO_FAILURE; + +#ifdef JTAG_GPIO_FILTER + if(gpio_ops_filter_flag) + { + return ret; + } + + if((GPIO20 == index) + || (GPIO21 == index) + || (GPIO22 == index) + || (GPIO23 == index)) + { + FATAL_PRT("[JTAG]gpio_filter_%d\r\n", index); + ret = GPIO_SUCCESS; + + goto filter_exit; + } +#endif + +#ifdef JTAG_GPIO_FILTER +filter_exit: +#endif + + return ret; +} + +void gpio_ops_disable_filter(void) +{ + gpio_ops_filter_flag = 1; +} + +void gpio_config(UINT32 index, UINT32 mode) +{ + UINT32 val; + UINT32 overstep = 0; + volatile UINT32 *gpio_cfg_addr; + + if(GPIO_SUCCESS == gpio_ops_filter(index)) + { + goto cfg_exit; + } + + if(index >= GPIONUM) + { + WARN_PRT("gpio_id_cross_border\r\n"); + + goto cfg_exit; + } + + #if (CFG_SOC_NAME != SOC_BK7231) + if(index >= GPIO32) + index += 16; + #endif // (CFG_SOC_NAME != SOC_BK7231) + + gpio_cfg_addr = (volatile UINT32 *)(REG_GPIO_CFG_BASE_ADDR + index * 4); + + switch(mode) + { + case GMODE_INPUT_PULLDOWN: + val = 0x2C; + break; + + case GMODE_OUTPUT: + val = 0x00; + break; + + case GMODE_SECOND_FUNC: + val = 0x48; + break; + + case GMODE_INPUT_PULLUP: + val = 0x3C; + break; + + case GMODE_INPUT: + val = 0x0C; + break; + + case GMODE_SECOND_FUNC_PULL_UP: + val = 0x78; + break; + + case GMODE_DEEP_PS: + case GMODE_SET_HIGH_IMPENDANCE: + val = 0x08; + break; + + default: + overstep = 1; + WARN_PRT("gpio_mode_exception:%d\r\n", mode); + break; + } + + if(0 == overstep) + { + REG_WRITE(gpio_cfg_addr, val); + } + +cfg_exit: + return; +} + +#if ((SOC_BK7231U == CFG_SOC_NAME) || (SOC_BK7221U == CFG_SOC_NAME)) +void gpio_usb_second_function(void) +{ + UINT32 val; + + val = REG_READ(REG_GPIO_FUNC_CFG_2); + val &= (~(GPIO_PCFG2_MASK(GPIO_USB_DP_PIN) + | GPIO_PCFG2_MASK(GPIO_USB_DN_PIN))); + val |= ( GPIO_PCFG2_2_FUNC(GPIO_USB_DP_PIN) + | GPIO_PCFG2_2_FUNC(GPIO_USB_DN_PIN)); + + REG_WRITE(REG_GPIO_FUNC_CFG_2, val); +} +#endif + +static void gpio_enable_second_function(UINT32 func_mode) +{ + UINT32 i; + UINT32 reg; + UINT32 modul_select = GPIO_MODUL_NONE; + UINT32 pmode = PERIAL_MODE_1; + UINT32 pmask = 0; + UINT32 end_index = 0; + UINT32 start_index = 0; + UINT32 config_mode = GMODE_SECOND_FUNC; + +#if ((SOC_BK7231U == CFG_SOC_NAME) || (SOC_BK7221U == CFG_SOC_NAME) || (SOC_BK7231N == CFG_SOC_NAME)) + UINT32 regist = 0, shift = 0; +#endif // (CFG_SOC_NAME != SOC_BK7231) + + switch(func_mode) + { + case GFUNC_MODE_UART2: + start_index = 0; + end_index = 1; + pmode = PERIAL_MODE_1; + config_mode = GMODE_SECOND_FUNC_PULL_UP; + break; + + case GFUNC_MODE_I2C2: + start_index = 0; + end_index = 1; + pmode = PERIAL_MODE_2; + break; + + case GFUNC_MODE_I2S: + start_index = 2; + end_index = 5; + pmode = PERIAL_MODE_1; + break; + + case GFUNC_MODE_ADC1: +#if (SOC_BK7231N == CFG_SOC_NAME) + start_index = 26; + end_index = 26; + pmode = PERIAL_MODE_1; + config_mode = GMODE_SET_HIGH_IMPENDANCE; +#else + start_index = 4; + end_index = 4; + pmode = PERIAL_MODE_2; +#endif + break; + + case GFUNC_MODE_ADC2: +#if (SOC_BK7231N == CFG_SOC_NAME) + start_index = 24; + end_index = 24; + pmode = PERIAL_MODE_3; + config_mode = GMODE_SET_HIGH_IMPENDANCE; +#else + start_index = 5; + end_index = 5; + pmode = PERIAL_MODE_2; +#endif + break; + + case GFUNC_MODE_CLK13M: + start_index = 6; + end_index = 6; + pmode = PERIAL_MODE_1; + break; + + case GFUNC_MODE_PWM0: + start_index = 6; + end_index = 6; + pmode = PERIAL_MODE_2; + break; + + case GFUNC_MODE_PWM1: + start_index = 7; + end_index = 7; + pmode = PERIAL_MODE_2; + break; + + case GFUNC_MODE_PWM2: + start_index = 8; + end_index = 8; + pmode = PERIAL_MODE_2; + break; + + case GFUNC_MODE_PWM3: + start_index = 9; + end_index = 9; + pmode = PERIAL_MODE_2; + break; + + case GFUNC_MODE_BT_PRIORITY: + start_index = 9; + end_index = 9; + pmode = PERIAL_MODE_1; + break; + + case GFUNC_MODE_WIFI_ACTIVE: + start_index = 7; + end_index = 7; + pmode = PERIAL_MODE_1; + break; + + case GFUNC_MODE_BT_ACTIVE: + start_index = 8; + end_index = 8; + pmode = PERIAL_MODE_1; + break; + + case GFUNC_MODE_UART1: + start_index = 10; + end_index = 13; + pmode = PERIAL_MODE_1; + config_mode = GMODE_SECOND_FUNC_PULL_UP; + break; + + case GFUNC_MODE_SD_DMA: + start_index = 14; + end_index = 19; + pmode = PERIAL_MODE_1; + modul_select = GPIO_SD_DMA_MODULE; + pmask = GPIO_SD_MODULE_MASK; + break; + + case GFUNC_MODE_SD_HOST: + start_index = 14; + end_index = 19; + pmode = PERIAL_MODE_1; + config_mode = GMODE_SECOND_FUNC_PULL_UP; + modul_select = GPIO_SD_HOST_MODULE; + pmask = GPIO_SD_MODULE_MASK; + break; + + case GFUNC_MODE_SPI_DMA: + start_index = 14; + end_index = 17; + pmode = PERIAL_MODE_2; + modul_select = GPIO_SPI_DMA_MODULE; + pmask = GPIO_SPI_MODULE_MASK; + break; + + case GFUNC_MODE_SPI: + start_index = 14; + end_index = 17; + pmode = PERIAL_MODE_2; + modul_select = GPIO_SPI_MODULE; + pmask = GPIO_SPI_MODULE_MASK; + break; + + case GFUNC_MODE_SPI_USE_GPIO_14: + start_index = 14; + end_index = 14; + pmode = PERIAL_MODE_2; + modul_select = GPIO_SPI_DMA_MODULE; + pmask = GPIO_SPI_MODULE_MASK; + break; + + case GFUNC_MODE_SPI_USE_GPIO_16_17: + start_index = 16; + end_index = 17; + pmode = PERIAL_MODE_2; + modul_select = GPIO_SPI_MODULE; + pmask = GPIO_SPI_MODULE_MASK; + break; + + case GFUNC_MODE_PWM4: +#if (CFG_SOC_NAME == SOC_BK7231) + start_index = 18; + end_index = 18; +#else + start_index = 24; + end_index = 24; +#endif + pmode = PERIAL_MODE_2; + break; + + case GFUNC_MODE_PWM5: +#if (CFG_SOC_NAME == SOC_BK7231) + start_index = 19; + end_index = 19; +#else + start_index = 26; + end_index = 26; +#endif + pmode = PERIAL_MODE_2; + break; + + case GFUNC_MODE_I2C1: + start_index = 20; + end_index = 21; + pmode = PERIAL_MODE_1; + break; + + case GFUNC_MODE_JTAG: + start_index = 20; + end_index = 23; + pmode = PERIAL_MODE_2; + break; + + case GFUNC_MODE_CLK26M: + start_index = 22; + end_index = 22; + pmode = PERIAL_MODE_1; + break; + + case GFUNC_MODE_ADC3: + start_index = 23; + end_index = 23; + pmode = PERIAL_MODE_1; + break; + +#if ((SOC_BK7231U == CFG_SOC_NAME) || (SOC_BK7221U == CFG_SOC_NAME) || (SOC_BK7231N == CFG_SOC_NAME)) + case GFUNC_MODE_DCMI: + start_index = 27; + end_index = 39; + pmode = PERIAL_MODE_1; + break; + + case GFUNC_MODE_ADC4: +#if (SOC_BK7231N == CFG_SOC_NAME) + start_index = 28; + end_index = 28; + pmode = PERIAL_MODE_2; + config_mode = GMODE_SET_HIGH_IMPENDANCE; +#else + start_index = 3; + end_index = 3; + pmode = PERIAL_MODE_2; +#endif + break; + + case GFUNC_MODE_ADC5: +#if (SOC_BK7231N == CFG_SOC_NAME) + start_index = 22; + end_index = 22; + pmode = PERIAL_MODE_1; + config_mode = GMODE_SET_HIGH_IMPENDANCE; +#else + start_index = 2; + end_index = 2; + pmode = PERIAL_MODE_2; +#endif + break; + + case GFUNC_MODE_ADC6: +#if (SOC_BK7231N == CFG_SOC_NAME) + start_index = 21; + end_index = 21; + pmode = PERIAL_MODE_1; + config_mode = GMODE_SET_HIGH_IMPENDANCE; +#else + start_index = 12; + end_index = 12; + pmode = PERIAL_MODE_2; +#endif + break; + + case GFUNC_MODE_ADC7: + start_index = 13; + end_index = 13; + pmode = PERIAL_MODE_2; + break; + case GFUNC_MODE_SD1_HOST: + start_index = 34; + end_index = 39; + pmode = PERIAL_MODE_2; + config_mode = GMODE_SECOND_FUNC_PULL_UP; + modul_select = GPIO_SD1_HOST_MODULE; + pmask = GPIO_SD_MODULE_MASK; + break; + case GFUNC_MODE_SPI1: + start_index = 30; + end_index = 33; + pmode = PERIAL_MODE_2; + modul_select = GPIO_SPI1_MODULE; + pmask = GPIO_SPI_MODULE_MASK; + break; + case GFUNC_MODE_SPI_DMA1: + start_index = 30; + end_index = 33; + pmode = PERIAL_MODE_2; + modul_select = GPIO_SPI1_DMA_MODULE; + pmask = GPIO_SPI_MODULE_MASK; + break; +#endif // (CFG_SOC_NAME != SOC_BK7231) + + default: + break; + } + + for(i = start_index; i <= end_index; i++) + { + #if ((SOC_BK7231U == CFG_SOC_NAME) || (SOC_BK7221U == CFG_SOC_NAME) || (SOC_BK7231N == CFG_SOC_NAME)) + if((func_mode == GFUNC_MODE_DCMI) && (i == GPIO28)) + continue; + #endif // (CFG_SOC_NAME != SOC_BK7231) + + #if ((SOC_BK7231U == CFG_SOC_NAME) || (SOC_BK7221U == CFG_SOC_NAME) || (SOC_BK7231N == CFG_SOC_NAME)) + if(i < GPIO16) { + regist = REG_GPIO_FUNC_CFG; + shift = i * 2; + } + else if(i < GPIO32) { + regist = REG_GPIO_FUNC_CFG_2; + shift = (i - 16) * 2; + } + else if(i < GPIONUM) { + regist = REG_GPIO_FUNC_CFG_3; + shift = (i - 32) * 2; + } + reg = REG_READ(regist); + + reg = (reg & ~(0x3u << shift)) | ((pmode & 0x3u) << shift); + REG_WRITE(regist, reg); + #else + reg = REG_READ(REG_GPIO_FUNC_CFG); + if(PERIAL_MODE_1 == pmode) + { + reg &= ~(BIT(i)); + } + else /*(PERIAL_MODE_2 == pmode)*/ + { + reg |= BIT(i); + } + REG_WRITE(REG_GPIO_FUNC_CFG, reg); + #endif // (CFG_SOC_NAME != SOC_BK7231) + + gpio_config(i, config_mode); + } + + + if(modul_select != GPIO_MODUL_NONE) + { + reg = REG_READ(REG_GPIO_MODULE_SELECT); + reg &= ~ (pmask); + reg |= modul_select; + REG_WRITE(REG_GPIO_MODULE_SELECT, reg); + } + return; +} + +UINT32 gpio_input(UINT32 id) +{ + UINT32 val = 0; + volatile UINT32 *gpio_cfg_addr; + + if(GPIO_SUCCESS == gpio_ops_filter(id)) + { + WARN_PRT("gpio_input_fail\r\n"); + goto input_exit; + } + #if (CFG_SOC_NAME != SOC_BK7231) + if(id >= GPIO32) + id += 16; + #endif // (CFG_SOC_NAME != SOC_BK7231) + + gpio_cfg_addr = (volatile UINT32 *)(REG_GPIO_CFG_BASE_ADDR + id * 4); + val = REG_READ(gpio_cfg_addr); + +input_exit: + return (val & GCFG_INPUT_BIT); +} + +void gpio_output(UINT32 id, UINT32 val) +{ + UINT32 reg_val; + volatile UINT32 *gpio_cfg_addr; + + if(GPIO_SUCCESS == gpio_ops_filter(id)) + { + WARN_PRT("gpio_output_fail\r\n"); + goto output_exit; + } + #if (CFG_SOC_NAME != SOC_BK7231) + if(id >= GPIO32) + id += 16; + #endif // (CFG_SOC_NAME != SOC_BK7231) + gpio_cfg_addr = (volatile UINT32 *)(REG_GPIO_CFG_BASE_ADDR + id * 4); + reg_val = REG_READ(gpio_cfg_addr); + + reg_val &= ~GCFG_OUTPUT_BIT; + reg_val |= (val & 0x01) << GCFG_OUTPUT_POS; + REG_WRITE(gpio_cfg_addr, reg_val); + +output_exit: + return; +} + +static void gpio_output_reverse(UINT32 id) +{ + UINT32 reg_val; + volatile UINT32 *gpio_cfg_addr; + + if(GPIO_SUCCESS == gpio_ops_filter(id)) + { + WARN_PRT("gpio_output_reverse_fail\r\n"); + goto reverse_exit; + } + + #if (CFG_SOC_NAME != SOC_BK7231) + if(id >= GPIO32) + id += 16; + #endif // (CFG_SOC_NAME != SOC_BK7231) + gpio_cfg_addr = (volatile UINT32 *)(REG_GPIO_CFG_BASE_ADDR + id * 4); + reg_val = REG_READ(gpio_cfg_addr); + + reg_val ^= GCFG_OUTPUT_BIT; + REG_WRITE(gpio_cfg_addr, reg_val); + +reverse_exit: + return; +} + + +static void gpio_disable_jtag(void) +{ +#ifndef JTAG_GPIO_FILTER + int id; + + /*config GPIO_PCFG*/ + //#error "todo" + + for(id = GPIO20; id <= GPIO23; id ++) + { + //gpio_config(id, GMODE_OUTPUT); + } +#endif +} + +void gpio_test_isr(unsigned char ucChannel) +{ + gpio_output(4, 1); // 161ms +} + +void gpio_int_disable(UINT32 index) +{ + *(volatile UINT32 *)REG_GPIO_INTEN &= ~(0x01 << index); +} + +void gpio_int_enable(UINT32 index, UINT32 mode, void (*p_Int_Handler)(unsigned char)) +{ + UINT32 param; + intc_service_register(IRQ_GPIO, PRI_IRQ_GPIO, gpio_isr); + param = IRQ_GPIO_BIT; + sddev_control(ICU_DEV_NAME, CMD_ICU_INT_ENABLE, ¶m); + + if(index >= GPIONUM) + { + WARN_PRT("gpio_id_cross_border\r\n"); + + return; + } + + mode &= 0x03; + if ((mode == 0) || (mode == 3)) + { + gpio_config(index, GMODE_INPUT_PULLUP); + } + else + { + gpio_config(index, GMODE_INPUT_PULLDOWN); + } + + if (index < 16) + { + *(volatile UINT32 *)REG_GPIO_INTLV0 = (*(volatile UINT32 *)REG_GPIO_INTLV0 & (~(0x03 << (index << 1)))) | (mode << (index << 1)); + } + else + { + *(volatile UINT32 *)REG_GPIO_INTLV1 = (*(volatile UINT32 *)REG_GPIO_INTLV1 & (~(0x03 << ((index - 16) << 1)))) | (mode << ((index - 16) << 1)); + } + + *(volatile UINT32 *)REG_GPIO_INTEN |= (0x01 << index); + + param = 0; + //while(param < 500) + while(param < 250) + { + UINT32 ulIntStatus = 0; + ulIntStatus = *(volatile UINT32 *)REG_GPIO_INTSTA; + if(ulIntStatus & (0x1UL << index)) + { + *(volatile UINT32 *)REG_GPIO_INTSTA |= (0x1UL << index); + // not break for mode=2 with pin high iput, case two intr + //break; + } + param++; + } + + p_gpio_intr_handler[index] = p_Int_Handler; +} + +void gpio_int_config(UINT32 index, UINT32 mode, void (*p_Int_Handler)(unsigned char)) +{ + UINT32 param; + intc_service_register(IRQ_GPIO, PRI_IRQ_GPIO, gpio_isr); + param = IRQ_GPIO_BIT; + sddev_control(ICU_DEV_NAME, CMD_ICU_INT_ENABLE, ¶m); + + if(index >= GPIONUM) + { + WARN_PRT("gpio_id_cross_border\r\n"); + + return; + } + + if (index < 16) + { + *(volatile UINT32 *)REG_GPIO_INTLV0 = (*(volatile UINT32 *)REG_GPIO_INTLV0 & (~(0x03 << (index << 1)))) | (mode << (index << 1)); + } + else + { + *(volatile UINT32 *)REG_GPIO_INTLV1 = (*(volatile UINT32 *)REG_GPIO_INTLV1 & (~(0x03 << ((index - 16) << 1)))) | (mode << ((index - 16) << 1)); + } + + p_gpio_intr_handler[index] = p_Int_Handler; + *(volatile UINT32 *)REG_GPIO_INTEN |= (0x01 << index); +} + +/*******************************************************************/ +void gpio_init(void) +{ +#if CFG_SYS_START_TIME + UINT32 param; +#endif + gpio_disable_jtag(); + + sddev_register_dev(GPIO_DEV_NAME, &gpio_op); +#if CFG_SYS_START_TIME + param = 3 | (GMODE_OUTPUT << 8); + gpio_ctrl(CMD_GPIO_CFG, ¶m); + gpio_output(3, 0); //141ms delta time = 13ms + param = 4 | (GMODE_OUTPUT << 8); + gpio_ctrl(CMD_GPIO_CFG, ¶m); + gpio_output(4, 0); + param = 5 | (GMODE_OUTPUT << 8); + gpio_ctrl(CMD_GPIO_CFG, ¶m); + gpio_output(5, 0); + + intc_service_register(IRQ_GPIO, PRI_IRQ_GPIO, gpio_isr); + param = IRQ_GPIO_BIT; + sddev_control(ICU_DEV_NAME, CMD_ICU_INT_ENABLE, ¶m); + + gpio_int_enable(2, 2, gpio_test_isr); + gpio_output(3, 1); // delta time = 3.1ms, delta time = 780us +#endif +} + +void gpio_exit(void) +{ + sddev_unregister_dev(GPIO_DEV_NAME); +} + +UINT32 gpio_ctrl(UINT32 cmd, void *param) +{ + UINT32 ret; + ret = GPIO_SUCCESS; + + switch(cmd) + { + case CMD_GPIO_CFG: + { + UINT32 id; + UINT32 mode; + + id = GPIO_CFG_PARAM_DEMUX_ID(*(UINT32 *)param); + mode = GPIO_CFG_PARAM_DEMUX_MODE(*(UINT32 *)param); + + gpio_config(id, mode); + + break; + } + + case CMD_GPIO_OUTPUT_REVERSE: + ASSERT(param); + + gpio_output_reverse(*(UINT32 *)param); + break; + + case CMD_GPIO_OUTPUT: + { + UINT32 id; + UINT32 val; + + id = GPIO_OUTPUT_DEMUX_ID(*(UINT32 *)param); + val = GPIO_OUTPUT_DEMUX_VAL(*(UINT32 *)param); + + gpio_output(id, val); + break; + } + + case CMD_GPIO_INPUT: + { + UINT32 id; + UINT32 val; + + ASSERT(param); + + id = *(UINT32 *)param; + val = gpio_input(id); + + ret = val; + break; + } + + case CMD_GPIO_ENABLE_SECOND: + { + UINT32 second_mode; + + ASSERT(param); + + second_mode = *(UINT32 *)param; + gpio_enable_second_function(second_mode); + break; + } + + case CMD_GPIO_CLR_DPLL_UNLOOK_INT: + REG_WRITE(REG_GPIO_DPLL_UNLOCK, 0x1); + break; + case CMD_GPIO_EN_DPLL_UNLOOK_INT: + { + UINT32 reg = REG_READ(REG_GPIO_DPLL_UNLOCK); + ASSERT(param); + UINT32 enable = *(UINT32 *)param; + if(enable) { + reg &= ~GPIO_EXTRAL_INT_MASK; + reg |= DPLL_UNLOCK_INT_EN; + REG_WRITE(REG_GPIO_DPLL_UNLOCK, reg); + } else { + reg &= ~GPIO_EXTRAL_INT_MASK; + reg &= ~DPLL_UNLOCK_INT_EN; + REG_WRITE(REG_GPIO_DPLL_UNLOCK, reg); + } + break; + } + + case CMD_GPIO_INT_ENABLE: + { + GPIO_INT_ST *ptr = param; + gpio_int_enable(ptr->id, ptr->mode, ptr->phandler); + break; + } + case CMD_GPIO_INT_DISABLE: + { + UINT32 id ; + id = *(UINT32 *)param; + gpio_int_disable(id); + break; + } + case CMD_GPIO_INT_CONFIG: + { + GPIO_INT_ST *ptr = param; + gpio_int_config(ptr->id, ptr->mode, ptr->phandler); + break; + } + + default: + break; + } + + return ret; +} + +// EOF diff --git a/beken_os/beken378/driver/gpio/gpio.h b/beken_os/beken378/driver/gpio/gpio.h new file mode 100755 index 0000000..50e2faf --- /dev/null +++ b/beken_os/beken378/driver/gpio/gpio.h @@ -0,0 +1,185 @@ +#ifndef _GPIO_H_ +#define _GPIO_H_ + +#include "sys_config.h" + +#define GPIO_PRT os_printf +#define WARN_PRT os_printf +#define FATAL_PRT os_printf + +#if CFG_JTAG_ENABLE +#define JTAG_GPIO_FILTER +#endif + +#define GPIO_INIT_FLAG ((UINT32)1) +#define GPIO_UNINIT_FLAG ((UINT32)-1) + +#define GPIO_BASE_ADDR (0x0802800) + +#define REG_GPIO_0_CONFIG (GPIO_BASE_ADDR + 0*4) +#define REG_GPIO_1_CONFIG (GPIO_BASE_ADDR + 1*4) +#define REG_GPIO_2_CONFIG (GPIO_BASE_ADDR + 2*4) +#define REG_GPIO_3_CONFIG (GPIO_BASE_ADDR + 3*4) +#define REG_GPIO_4_CONFIG (GPIO_BASE_ADDR + 4*4) +#define REG_GPIO_5_CONFIG (GPIO_BASE_ADDR + 5*4) +#define REG_GPIO_6_CONFIG (GPIO_BASE_ADDR + 6*4) +#define REG_GPIO_7_CONFIG (GPIO_BASE_ADDR + 7*4) +#define REG_GPIO_8_CONFIG (GPIO_BASE_ADDR + 8*4) +#define REG_GPIO_9_CONFIG (GPIO_BASE_ADDR + 9*4) +#define REG_GPIO_10_CONFIG (GPIO_BASE_ADDR + 10*4) +#define REG_GPIO_11_CONFIG (GPIO_BASE_ADDR + 11*4) +#define REG_GPIO_12_CONFIG (GPIO_BASE_ADDR + 12*4) +#define REG_GPIO_13_CONFIG (GPIO_BASE_ADDR + 13*4) +#define REG_GPIO_14_CONFIG (GPIO_BASE_ADDR + 14*4) +#define REG_GPIO_15_CONFIG (GPIO_BASE_ADDR + 15*4) +#define REG_GPIO_16_CONFIG (GPIO_BASE_ADDR + 16*4) +#define REG_GPIO_17_CONFIG (GPIO_BASE_ADDR + 17*4) +#define REG_GPIO_18_CONFIG (GPIO_BASE_ADDR + 18*4) +#define REG_GPIO_19_CONFIG (GPIO_BASE_ADDR + 19*4) +#define REG_GPIO_20_CONFIG (GPIO_BASE_ADDR + 20*4) +#define REG_GPIO_21_CONFIG (GPIO_BASE_ADDR + 21*4) +#define REG_GPIO_22_CONFIG (GPIO_BASE_ADDR + 22*4) +#define REG_GPIO_23_CONFIG (GPIO_BASE_ADDR + 23*4) +#define REG_GPIO_24_CONFIG (GPIO_BASE_ADDR + 24*4) +#define REG_GPIO_25_CONFIG (GPIO_BASE_ADDR + 25*4) +#define REG_GPIO_26_CONFIG (GPIO_BASE_ADDR + 26*4) +#define REG_GPIO_27_CONFIG (GPIO_BASE_ADDR + 27*4) +#define REG_GPIO_28_CONFIG (GPIO_BASE_ADDR + 28*4) +#define REG_GPIO_29_CONFIG (GPIO_BASE_ADDR + 29*4) +#define REG_GPIO_30_CONFIG (GPIO_BASE_ADDR + 30*4) +#define REG_GPIO_31_CONFIG (GPIO_BASE_ADDR + 31*4) + +#define REG_GPIO_CFG_BASE_ADDR (REG_GPIO_0_CONFIG) + + +#define GCFG_INPUT_POS 0 +#define GCFG_OUTPUT_POS 1 +#define GCFG_INPUT_ENABLE_POS 2 +#define GCFG_OUTPUT_ENABLE_POS 3 +#define GCFG_PULL_MODE_POS 4 +#define GCFG_PULL_ENABLE_POS 5 +#define GCFG_FUNCTION_ENABLE_POS 6 +#define GCFG_INPUT_MONITOR_POS 7 + + +#define GCFG_INPUT_BIT (1 << 0) +#define GCFG_OUTPUT_BIT (1 << 1) +#define GCFG_INPUT_ENABLE_BIT (1 << 2) +#define GCFG_OUTPUT_ENABLE_BIT (1 << 3) +#define GCFG_PULL_MODE_BIT (1 << 4) +#define GCFG_PULL_ENABLE_BIT (1 << 5) +#define GCFG_FUNCTION_ENABLE_BIT (1 << 6) +#define GCFG_INPUT_MONITOR_BIT (1 << 7) + + + +#define REG_GPIO_FUNC_CFG (GPIO_BASE_ADDR + 32*4) +#define PERIAL_MODE_1 (0) +#define PERIAL_MODE_2 (1) +#define PERIAL_MODE_3 (2) +#define PERIAL_MODE_4 (3) + +#define REG_GPIO_INTEN (GPIO_BASE_ADDR + 33*4) +#define REG_GPIO_INTLV0 (GPIO_BASE_ADDR + 34*4) +#define REG_GPIO_INTLV1 (GPIO_BASE_ADDR + 35*4) +#define REG_GPIO_INTSTA (GPIO_BASE_ADDR + 36*4) +#define REG_GPIO_DPLL_UNLOCK (GPIO_BASE_ADDR + 38*4) +#if (CFG_SOC_NAME == SOC_BK7231) +#define DPLL_UNLOCK_INT (1 << 0) +#else +#define DPLL_UNLOCK_INT_EN (1 << 0) +#define AUDIO_DPLL_UNLOCK_INT_EN (1 << 1) +#define DPLL_UNLOCK_INT (1 << 2) +#define AUDIO_DPLL_UNLOCK_INT (1 << 3) +#if (CFG_SOC_NAME == SOC_BK7221U) +#define USB_PLUG_IN_INT_EN (1 << 4) +#define USB_PLUG_OUT_INT_EN (1 << 5) +#define USB_PLUG_IN_INT (1 << 6) +#define USB_PLUG_OUT_INT (1 << 7) +#define GPIO_EXTRAL_INT_MASK (DPLL_UNLOCK_INT | AUDIO_DPLL_UNLOCK_INT | USB_PLUG_IN_INT | USB_PLUG_OUT_INT) +#else +#define GPIO_EXTRAL_INT_MASK (DPLL_UNLOCK_INT | AUDIO_DPLL_UNLOCK_INT) +#endif // (CFG_SOC_NAME == SOC_BK7221U) + +#endif // (CFG_SOC_NAME == SOC_BK7231) +#define REG_GPIO_DETECT (GPIO_BASE_ADDR + 39*4) +#define REG_GPIO_ENC_WORD (GPIO_BASE_ADDR + 40*4) +#define REG_GPIO_DBG_MSG (GPIO_BASE_ADDR + 41*4) +#define REG_GPIO_DBG_MUX (GPIO_BASE_ADDR + 42*4) +#define REG_GPIO_DBG_CFG (GPIO_BASE_ADDR + 43*4) +#define REG_GPIO_DBG_REPORT (GPIO_BASE_ADDR + 44*4) + +#define REG_GPIO_MODULE_SELECT (GPIO_BASE_ADDR + 45*4) +#define GPIO_MODUL_NONE 0xff + +#if (CFG_SOC_NAME != SOC_BK7231) +#define GPIO_SD_DMA_MODULE (0 << 2) +#define GPIO_SD_HOST_MODULE (1 << 2) +#define GPIO_SD1_DMA_MODULE (2 << 2) +#define GPIO_SD1_HOST_MODULE (3 << 2) +#define GPIO_SD_MODULE_POS 2 +#define GPIO_SD_MODULE_MASK (3 << GPIO_SD_MODULE_POS) +#else +#define GPIO_SD_DMA_MODULE (0 << 1) +#define GPIO_SD_HOST_MODULE (1 << 1) +#define GPIO_SD_MODULE_POS 1 +#define GPIO_SD_MODULE_MASK (1 << GPIO_SD_MODULE_POS) +#endif // (CFG_SOC_NAME != SOC_BK7231) + +#if (CFG_SOC_NAME != SOC_BK7231) +#define GPIO_SPI1_DMA_MODULE (2 << 0) +#define GPIO_SPI1_MODULE (3 << 0) +#define GPIO_SPI_DMA_MODULE (0 << 0) +#define GPIO_SPI_MODULE (1 << 0) +#define GPIO_SPI_MODULE_POS 0 +#define GPIO_SPI_MODULE_MASK (3 << GPIO_SPI_MODULE_POS) +#else +#define GPIO_SPI_DMA_MODULE (0 << 0) +#define GPIO_SPI_MODULE (1 << 0) +#define GPIO_SPI_MODULE_POS 0 +#define GPIO_SPI_MODULE_MASK (1 << GPIO_SPI_MODULE_POS) +#endif + +#if (CFG_SOC_NAME == SOC_BK7231) +#define REG_A0_CONFIG (GPIO_BASE_ADDR + 48*4) +#define REG_A1_CONFIG (GPIO_BASE_ADDR + 49*4) +#define REG_A2_CONFIG (GPIO_BASE_ADDR + 50*4) +#define REG_A3_CONFIG (GPIO_BASE_ADDR + 51*4) +#define REG_A4_CONFIG (GPIO_BASE_ADDR + 52*4) +#define REG_A5_CONFIG (GPIO_BASE_ADDR + 53*4) +#define REG_A6_CONFIG (GPIO_BASE_ADDR + 54*4) +#define REG_A7_CONFIG (GPIO_BASE_ADDR + 55*4) +#else +// for GPIO 16-31 +#define REG_GPIO_FUNC_CFG_2 (GPIO_BASE_ADDR + 46*4) +#define GPIO_PCFG2_POSI(x) (((x)-16)*2) +#define GPIO_PCFG2_MASK(x) (0x03UL << GPIO_PCFG2_POSI(x)) +#define GPIO_PCFG2_1_FUNC(x) (0x00UL << GPIO_PCFG2_POSI(x)) +#define GPIO_PCFG2_2_FUNC(x) (0x01UL << GPIO_PCFG2_POSI(x)) +#define GPIO_PCFG2_3_FUNC(x) (0x02UL << GPIO_PCFG2_POSI(x)) +#define GPIO_PCFG2_4_FUNC(x) (0x03UL << GPIO_PCFG2_POSI(x)) + + +// for GPIO 32-39 +#define REG_GPIO_FUNC_CFG_3 (GPIO_BASE_ADDR + 47*4) +#define GPIO_PCFG3_POSI(x) (((x)-32)*2) +#define GPIO_PCFG3_MASK(x) (0x03UL << GPIO_PCFG3_POSI(x)) +#define GPIO_PCFG3_1_FUNC(x) (0x00UL << GPIO_PCFG3_POSI(x)) +#define GPIO_PCFG3_2_FUNC(x) (0x01UL << GPIO_PCFG3_POSI(x)) +#define GPIO_PCFG3_3_FUNC(x) (0x02UL << GPIO_PCFG3_POSI(x)) +#define GPIO_PCFG3_4_FUNC(x) (0x03UL << GPIO_PCFG3_POSI(x)) + +#define REG_GPIO_32_CONFIG (GPIO_BASE_ADDR + 48*4) +#define REG_GPIO_33_CONFIG (GPIO_BASE_ADDR + 49*4) +#define REG_GPIO_34_CONFIG (GPIO_BASE_ADDR + 50*4) +#define REG_GPIO_35_CONFIG (GPIO_BASE_ADDR + 51*4) +#define REG_GPIO_36_CONFIG (GPIO_BASE_ADDR + 52*4) +#define REG_GPIO_37_CONFIG (GPIO_BASE_ADDR + 53*4) +#define REG_GPIO_38_CONFIG (GPIO_BASE_ADDR + 54*4) +#define REG_GPIO_39_CONFIG (GPIO_BASE_ADDR + 55*4) +#endif // #if (CFG_SOC_NAME == SOC_BK7231) + +#endif // _GPIO_H_ + +// EOF + diff --git a/beken_os/beken378/driver/i2c/i2c1.c b/beken_os/beken378/driver/i2c/i2c1.c new file mode 100755 index 0000000..168550c --- /dev/null +++ b/beken_os/beken378/driver/i2c/i2c1.c @@ -0,0 +1,613 @@ +#include "include.h" +#include "arm_arch.h" + +#include "i2c1.h" +#include "i2c_pub.h" + +#include "intc_pub.h" +#include "icu_pub.h" +#include "gpio_pub.h" + +#include "drv_model_pub.h" +#include "mem_pub.h" +#include "rtos_pub.h" + +typedef struct i2c1_msg +{ + UINT16 RegAddr; + UINT16 RemainNum; + UINT8 *pData; + UINT8 SalveID; + UINT8 AddrFlag; + UINT8 TransDone; + UINT8 ErrorNO; + UINT8 TxMode; //0: Read; 1: Write + UINT8 AddrWidth; +} I2C1_MSG_ST, *I2C1_MSG_PTR; + +static DD_OPERATIONS i2c1_op = +{ + i2c1_open, + i2c1_close, + i2c1_read, + i2c1_write, + i2c1_ctrl +}; + +volatile I2C1_MSG_ST gi2c1; + +static void i2c1_set_ensmb(UINT32 enable) +{ + UINT32 reg_addr = REG_I2C1_CONFIG; + UINT32 reg_val = REG_READ(reg_addr); + + if (enable) + { + reg_val |= I2C1_ENSMB; + } + else + { + reg_val &= ~I2C1_ENSMB; + } + REG_WRITE(reg_addr, reg_val); +} + +static void i2c1_set_smbus_sta(UINT32 enable) +{ + UINT32 reg_addr = REG_I2C1_CONFIG; + UINT32 reg_val = REG_READ(reg_addr); + + if (enable) + { + reg_val |= I2C1_STA; + } + else + { + reg_val &= ~I2C1_STA; + } + REG_WRITE(reg_addr, reg_val); +} + +static void i2c1_set_smbus_stop(UINT32 enable) +{ + UINT32 reg_addr = REG_I2C1_CONFIG; + UINT32 reg_val = REG_READ(reg_addr); + + if (enable) + { + reg_val |= I2C1_STO; + } + else + { + reg_val &= ~I2C1_STO; + } + REG_WRITE(reg_addr, reg_val); +} + +static void i2c1_set_smbus_ack_tx(UINT32 enable) +{ + UINT32 reg_addr = REG_I2C1_CONFIG; + UINT32 reg_val = REG_READ(reg_addr); + + if (enable) + { + reg_val |= I2C1_ACK_TX; + } + else + { + reg_val &= ~I2C1_ACK_TX; + } + REG_WRITE(reg_addr, reg_val); +} + +static void i2c1_set_smbus_tx_mode(UINT32 enable) +{ + UINT32 reg_addr = REG_I2C1_CONFIG; + UINT32 reg_val = REG_READ(reg_addr); + + if (enable) + { + reg_val |= I2C1_TX_MODE; + } + else + { + reg_val &= ~I2C1_TX_MODE; + } + REG_WRITE(reg_addr, reg_val); +} + +static void i2c1_set_freq_div(UINT32 div) +{ + UINT32 reg_addr = REG_I2C1_CONFIG; + UINT32 reg_val = REG_READ(reg_addr); + + reg_val = (reg_val & ~(I2C1_FREQ_DIV_MASK << I2C1_FREQ_DIV_POSI)) + | ((div & I2C1_FREQ_DIV_MASK) << I2C1_FREQ_DIV_POSI); + REG_WRITE(reg_addr, reg_val); +} + +static UINT32 i2c1_get_smbus_interrupt(void) +{ + UINT32 reg_addr = REG_I2C1_CONFIG; + UINT32 reg_val = REG_READ(reg_addr); + + return (reg_val & I2C1_SI) ? 1 : 0; +} + +static void i2c1_clear_smbus_interrupt(void) +{ + UINT32 reg_addr = REG_I2C1_CONFIG; + UINT32 reg_val = REG_READ(reg_addr); + + reg_val |= I2C1_SI; + + REG_WRITE(reg_addr, reg_val); +} + +static UINT32 i2c1_get_ack_rx(void) +{ + UINT32 reg_addr = REG_I2C1_CONFIG; + UINT32 reg_val = REG_READ(reg_addr); + + return (reg_val & I2C1_ACK_RX) ? 1 : 0; +} + +static UINT32 i2c1_get_ack_req(void) +{ + UINT32 reg_addr = REG_I2C1_CONFIG; + UINT32 reg_val = REG_READ(reg_addr); + + return (reg_val & I2C1_ACK_REQ) ? 1 : 0; +} + +static UINT32 i2c1_get_smbus_busy(void) +{ + UINT32 reg_addr = REG_I2C1_CONFIG; + UINT32 reg_val = REG_READ(reg_addr); + + return (reg_val & I2C1_BUSY) ? 1 : 0; +} + +//////////////////////////////////////////////////////////////////////////////// +static void i2c1_gpio_config(void) +{ + UINT32 param; + + param = GFUNC_MODE_I2C1; + sddev_control(GPIO_DEV_NAME, CMD_GPIO_ENABLE_SECOND, ¶m); +} + +static void i2c1_power_up(void) +{ + UINT32 param; + param = PWD_I2C1_CLK_BIT; + sddev_control(ICU_DEV_NAME, CMD_CLK_PWR_UP, ¶m); +} + +static void i2c1_power_down(void) +{ + UINT32 param; + param = PWD_I2C1_CLK_BIT; + sddev_control(ICU_DEV_NAME, CMD_CLK_PWR_DOWN, ¶m); +} + +static void i2c1_enable_interrupt(void) +{ + UINT32 param; + param = (IRQ_I2C1_BIT); + sddev_control(ICU_DEV_NAME, CMD_ICU_INT_ENABLE, ¶m); +} + +static void i2c1_disable_interrupt(void) +{ + UINT32 param; + param = (IRQ_I2C1_BIT); + sddev_control(ICU_DEV_NAME, CMD_ICU_INT_DISABLE, ¶m); +} + +static void i2c1_isr(void) +{ + unsigned long i2c1_config; + unsigned long work_mode, ack_rx, sta, si; + + i2c1_config = REG_READ(REG_I2C1_CONFIG); + si = i2c1_config & I2C1_SI; + + I2C1_PRT("i2c1_isr\r\n"); + I2C1_PRT("i2c1_isr: i2c1_config=0x%x\r\n", i2c1_config); + + if (!si) // not SMBUS/I2C Interrupt + { + I2C1_EPRT("i2c1_isr not SI! i2c1_config = 0x%lx\r\n", i2c1_config); + return; + } + + ack_rx = i2c1_config & I2C1_ACK_RX; + sta = i2c1_config & I2C1_STA; + work_mode = (gi2c1.TxMode & 0x01) ? 0x00 : 0x01; + + i2c1_config &= (~I2C1_STA); + i2c1_config &= (~I2C1_STO); + I2C1_PRT("1: gi2c1.AddrFlag=0x%x\r\n", gi2c1.AddrFlag); + switch (work_mode) + { + case 0x00: // master write + { + if (!ack_rx) // nack + { + i2c1_config |= I2C1_STO; // send stop + gi2c1.TransDone = 1; + gi2c1.ErrorNO = 1; + break; + } + I2C1_PRT("2: gi2c1.AddrFlag=0x%x\r\n", gi2c1.AddrFlag); + + if (gi2c1.AddrFlag & 0x10) // all address bytes has been tx, now tx data + { + if (gi2c1.RemainNum == 0) // all data bytes has been tx, now send stop + { + i2c1_config |= I2C1_STO; // send stop + gi2c1.TransDone = 1; + } + else + { + REG_WRITE(REG_I2C1_DAT, *gi2c1.pData); + gi2c1.pData ++; + gi2c1.RemainNum --; + } + break; + } + + if ((gi2c1.AddrFlag & 0x08) == 0) + { + if (gi2c1.AddrWidth == ADDR_WIDTH_8) + { + REG_WRITE(REG_I2C1_DAT, (gi2c1.RegAddr & 0xFF)); + gi2c1.AddrFlag |= 0x13; + } + else if (gi2c1.AddrWidth == ADDR_WIDTH_16) + { + REG_WRITE(REG_I2C1_DAT, (gi2c1.RegAddr >> 8)); + gi2c1.AddrFlag |= 0x08; + } + } + else + { + REG_WRITE(REG_I2C1_DAT, (gi2c1.RegAddr & 0xFF)); + gi2c1.AddrFlag |= 0x10; + } + } + break; + + case 0x01: // master read + { + if (((gi2c1.AddrFlag & 0x10) == 0) && (ack_rx == 0)) // NACK + { + i2c1_config = i2c1_config | I2C1_STO; + gi2c1.TransDone = 1; + gi2c1.ErrorNO = 1; + break; + } + + if (sta && !ack_rx) // when tx address, we need ACK + { + i2c1_config = i2c1_config | I2C1_STO; + gi2c1.TransDone = 1; + break; + } + + if (gi2c1.AddrFlag & 0x10) // all address has been tx, now rx data + { + i2c1_config &= (~I2C1_TX_MODE); + + if (sta) + { + i2c1_config = i2c1_config | I2C1_ACK_TX; // send ACK + break; + } + + *gi2c1.pData = REG_READ(REG_I2C1_DAT); + gi2c1.pData ++; + gi2c1.RemainNum --; + + if (gi2c1.RemainNum == 0) + { + i2c1_config = (i2c1_config & (~I2C1_ACK_TX)) | I2C1_STO; // send NACK and STOP + gi2c1.TransDone = 1; + } + else + { + i2c1_config = i2c1_config | I2C1_ACK_TX; // send ACK + } + break; + } + + if ((gi2c1.AddrFlag & 0x08) == 0) // inner address need to be tx + { + if (gi2c1.AddrWidth == ADDR_WIDTH_8) + { + REG_WRITE(REG_I2C1_DAT, (gi2c1.RegAddr & 0xFF)); + gi2c1.AddrFlag = (gi2c1.AddrFlag & (~0x0B)) | 0x0A; + } + else if (gi2c1.AddrWidth == ADDR_WIDTH_16) + { + REG_WRITE(REG_I2C1_DAT, (gi2c1.RegAddr >> 8)); + gi2c1.AddrFlag = (gi2c1.AddrFlag & (~0x0B)) | 0x08; + } + } + else if ((gi2c1.AddrFlag & 0x02) == 0) + { + REG_WRITE(REG_I2C1_DAT, (gi2c1.RegAddr & 0xFF)); + gi2c1.AddrFlag = (gi2c1.AddrFlag & (~0x0B)) | 0x0A; + } + else // inner address has been tx + { + i2c1_config |= I2C1_STA; + REG_WRITE(REG_I2C1_DAT, (gi2c1.SalveID << 1) | 0x01); + gi2c1.AddrFlag |= 0x13; + } + } + break; + + default: // by gwf + break; + } + + REG_WRITE(REG_I2C1_CONFIG, i2c1_config); + REG_WRITE(REG_I2C1_CONFIG, i2c1_config & (~I2C1_SI)); +} + +static void i2c1_software_init(void) +{ + ddev_register_dev(I2C1_DEV_NAME, &i2c1_op); +} + +static void i2c1_hardware_init(void) +{ + /* register interrupt */ + intc_service_register(IRQ_I2C1, PRI_IRQ_I2C1, i2c1_isr); + + /* clear all setting */ + REG_WRITE(REG_I2C1_CONFIG, 0); +} + +void i2c1_init(void) +{ + os_memset((unsigned char *)&gi2c1, 0, sizeof(I2C1_MSG_ST)); + i2c1_software_init(); + i2c1_hardware_init(); +} + +void i2c1_exit(void) +{ + REG_WRITE(REG_I2C1_CONFIG, 0); + + ddev_unregister_dev(I2C1_DEV_NAME); +} + +static UINT32 i2c1_open(UINT32 op_flag) +{ + // UINT32 reg; + os_printf("i2c1_open\r\n"); + if (op_flag) + { + i2c1_set_freq_div(op_flag); + } + else + { + i2c1_set_freq_div(I2C_CLK_DIVID(I2C_DEFAULT_BAUD)); // 400KHZ + } + + i2c1_enable_interrupt(); + i2c1_power_up(); + i2c1_gpio_config(); + + //i2c1_set_ensmb(1); + + return I2C1_SUCCESS; +} + +static UINT32 i2c1_close(void) +{ + os_printf("i2c1_close\r\n"); + i2c1_set_ensmb(0); + i2c1_disable_interrupt(); + i2c1_power_down(); + + return I2C1_SUCCESS; +} + +static UINT32 i2c1_read(char *user_buf, UINT32 count, UINT32 op_flag) +{ + UINT32 reg, start_tick, cur_tick; + I2C_OP_PTR i2c_op; + GLOBAL_INT_DECLARATION(); + + i2c_op = (I2C_OP_PTR)op_flag; + + I2C1_PRT("i2c1_read\r\n"); + + I2C1_PRT("i2c1_read: i2c_op->salve_id = 0x%x, i2c_op->op_addr = 0x%x\r\n", + i2c_op->salve_id, i2c_op->op_addr); + + I2C1_PRT("i2c1_read: count = %d\r\n", count); + + I2C1_PRT("i2c1_read: gi2c1.TransDone = %d\r\n", gi2c1.TransDone); + + if (gi2c1.TransDone != 0) + { + return 0; + } + + GLOBAL_INT_DISABLE(); + // write cycle, write the subaddr to device + gi2c1.TxMode = 0; + gi2c1.RegAddr = i2c_op->op_addr; + gi2c1.RemainNum = count; + gi2c1.pData = (UINT8 *)user_buf; + gi2c1.SalveID = i2c_op->salve_id; + gi2c1.AddrFlag = 0; + gi2c1.TransDone = 0; + gi2c1.ErrorNO = 0; + gi2c1.AddrWidth = i2c_op->addr_width; + + reg = REG_READ(REG_I2C1_CONFIG); + reg |= I2C1_TX_MODE | I2C1_ENSMB;// Set TXMODE | ENSMB + REG_WRITE(REG_I2C1_CONFIG, reg); + + reg = ((i2c_op->salve_id & 0x7f) << 1) + 0; // SET LSB 0 + REG_WRITE(REG_I2C1_DAT, reg); + + reg = REG_READ(REG_I2C1_CONFIG); + reg |= I2C1_STA;// Set STA + REG_WRITE(REG_I2C1_CONFIG, reg); + GLOBAL_INT_RESTORE(); + + start_tick = rtos_get_time(); + while (1) + { + if (gi2c1.TransDone == 0) + { + UINT32 past = 0; + cur_tick = rtos_get_time(); + past = (cur_tick >= start_tick) ? (cur_tick - start_tick) : (0xffffffffu - start_tick + cur_tick); + if ((past) > I2C_READ_WAIT_TIMEOUT) + { + gi2c1.ErrorNO = 1; + break; + } + //rtos_delay_milliseconds(10); + } + else + { + break; + } + } + + GLOBAL_INT_DISABLE(); + gi2c1.TransDone = 0; + GLOBAL_INT_RESTORE(); + + return gi2c1.ErrorNO; +} + +static UINT32 i2c1_write(char *user_buf, UINT32 count, UINT32 op_flag) +{ + UINT32 reg, start_tick, cur_tick; + I2C_OP_PTR i2c_op; + GLOBAL_INT_DECLARATION(); + + i2c_op = (I2C_OP_PTR)op_flag; + + I2C1_PRT("i2c1_write\r\n"); + + I2C1_PRT("i2c1_write: i2c_op->salve_id = 0x%x, i2c_op->op_addr = 0x%x\r\n", + i2c_op->salve_id, i2c_op->op_addr); + + I2C1_PRT("i2c1_write: count = %d\r\n", count); + + I2C1_PRT("i2c1_write: gi2c1.TransDone = %d\r\n", gi2c1.TransDone); + + if (gi2c1.TransDone != 0) + { + return 0; + } + + GLOBAL_INT_DISABLE(); + gi2c1.TxMode = 1; + gi2c1.RegAddr = i2c_op->op_addr; + gi2c1.RemainNum = count; + gi2c1.pData = (UINT8 *)user_buf; + gi2c1.SalveID = i2c_op->salve_id; + gi2c1.AddrFlag = 0; + gi2c1.TransDone = 0; + gi2c1.ErrorNO = 0; + gi2c1.AddrWidth = i2c_op->addr_width; + + reg = REG_READ(REG_I2C1_CONFIG); + reg |= I2C1_TX_MODE | I2C1_ENSMB;// Set TXMODE | ENSMB + REG_WRITE(REG_I2C1_CONFIG, reg); + + reg = ((i2c_op->salve_id & 0x7f) << 1) + 0; // SET LSB 0 + REG_WRITE(REG_I2C1_DAT, reg); + + reg = REG_READ(REG_I2C1_CONFIG); + reg |= I2C1_STA;// Set STA + REG_WRITE(REG_I2C1_CONFIG, reg); + GLOBAL_INT_RESTORE(); + + start_tick = rtos_get_time(); + while (1) + { + if (gi2c1.TransDone == 0) + { + UINT32 past = 0; + cur_tick = rtos_get_time(); + past = (cur_tick >= start_tick) ? (cur_tick - start_tick) : (0xffffffffu - start_tick + cur_tick); + if ((past) > I2C_WRITE_WAIT_TIMEOUT) + { + gi2c1.ErrorNO = 1; + break; + } + //rtos_delay_milliseconds(10); + } + else + { + break; + } + } + + GLOBAL_INT_DISABLE(); + gi2c1.TransDone = 0; + GLOBAL_INT_RESTORE(); + + return gi2c1.ErrorNO; +} + +static UINT32 i2c1_ctrl(UINT32 cmd, void *param) +{ + UINT32 ret = I2C1_SUCCESS; + + switch (cmd) + { + case I2C1_CMD_SET_ENSMB: + i2c1_set_ensmb(*((UINT32 *)param)); + break; + case I2C1_CMD_SET_SMBUS_STA: + i2c1_set_smbus_sta(*((UINT32 *)param)); + break; + case I2C1_CMD_SET_SMBUS_STOP: + i2c1_set_smbus_stop(*((UINT32 *)param)); + break; + case I2C1_CMD_SET_SMBUS_ACK_TX: + i2c1_set_smbus_ack_tx(*((UINT32 *)param)); + break; + case I2C1_CMD_SET_SMBUS_TX_MODE: + i2c1_set_smbus_tx_mode(*((UINT32 *)param)); + break; + case I2C1_CMD_SET_FREQ_DIV: + i2c1_set_freq_div(*((UINT32 *)param)); + break; + case I2C1_CMD_GET_SMBUS_INTERRUPT: + ret = i2c1_get_smbus_interrupt(); + break; + case I2C1_CMD_CLEAR_SMBUS_INTERRUPT: + i2c1_clear_smbus_interrupt(); + break; + case I2C1_CMD_GET_ACK_RX: + ret = i2c1_get_ack_rx(); + break; + case I2C1_CMD_GET_ACK_REQ: + ret = i2c1_get_ack_req(); + break; + case I2C1_CMD_GET_SMBUS_BUSY: + ret = i2c1_get_smbus_busy(); + break; + + default: + break; + } + + return ret; +} + diff --git a/beken_os/beken378/driver/i2c/i2c1.h b/beken_os/beken378/driver/i2c/i2c1.h new file mode 100755 index 0000000..95d901b --- /dev/null +++ b/beken_os/beken378/driver/i2c/i2c1.h @@ -0,0 +1,42 @@ +#ifndef _I2C1_H_ +#define _I2C1_H_ + +#include "uart_pub.h" +//#define I2C1_DEBUG + +#ifdef I2C1_DEBUG +#define I2C1_PRT os_printf +#define I2C1_WPRT warning_prf +#define I2C1_EPRT os_printf +#else +#define I2C1_PRT os_null_printf +#define I2C1_WPRT os_null_printf +#define I2C1_EPRT os_printf +#endif + +#define I2C1_BASE_ADDR (0x0802300) + +#define REG_I2C1_CONFIG (I2C1_BASE_ADDR + 4 * 0) +#define I2C1_ENSMB (1 << 0) +#define I2C1_STA (1 << 1) +#define I2C1_STO (1 << 2) +#define I2C1_ACK_TX (1 << 3) +#define I2C1_TX_MODE (1 << 4) +#define I2C1_FREQ_DIV_POSI (6) +#define I2C1_FREQ_DIV_MASK (0x3FF) +#define I2C1_SI (1 << 16) +#define I2C1_ACK_RX (1 << 17) +#define I2C1_ACK_REQ (1 << 18) +#define I2C1_BUSY (1 << 19) + +#define REG_I2C1_DAT (I2C1_BASE_ADDR + 4 * 1) +#define I2C1_DAT_MASK (0xFF) + +static UINT32 i2c1_open(UINT32 op_flag); +static UINT32 i2c1_close(void); +static UINT32 i2c1_read(char *user_buf, UINT32 count, UINT32 op_flag); +static UINT32 i2c1_write(char *user_buf, UINT32 count, UINT32 op_flag); +static UINT32 i2c1_ctrl(UINT32 cmd, void *param); + +#endif // _I2C1_H_ + diff --git a/beken_os/beken378/driver/i2c/i2c2.c b/beken_os/beken378/driver/i2c/i2c2.c new file mode 100755 index 0000000..5bcb4dc --- /dev/null +++ b/beken_os/beken378/driver/i2c/i2c2.c @@ -0,0 +1,1115 @@ +#include "include.h" +#include "arm_arch.h" + +#include "i2c2.h" +#include "i2c_pub.h" + +#include "intc_pub.h" +#include "icu_pub.h" +#include "gpio_pub.h" + +#include "drv_model_pub.h" +#include "mem_pub.h" +#include "common.h" +#include "rtos_pub.h" + + +static DD_OPERATIONS i2c2_op = +{ + i2c2_open, + i2c2_close, + i2c2_read, + i2c2_write, + i2c2_ctrl +}; + +__maybe_unused static void i2c2_set_slave_addr(UINT32 addr); +__maybe_unused static void i2c2_clk_source_set_26M(void); +static volatile I2C2_MSG_ST *gi2c2 ; + +static void i2c2_set_idle_cr(UINT32 idle_cr) +{ + UINT32 reg_val = REG_READ(REG_I2C2_CONFIG); + + reg_val = (reg_val & ~(I2C2_IDLE_CR_MASK << I2C2_IDLE_CR_POSI)) + | ((idle_cr & I2C2_IDLE_CR_MASK) << I2C2_IDLE_CR_POSI); + + REG_WRITE(REG_I2C2_CONFIG, reg_val); +} + +static void i2c2_set_scl_cr(UINT32 scl_cr) +{ + UINT32 reg_val = REG_READ(REG_I2C2_CONFIG); + + reg_val = (reg_val & ~(I2C2_SCL_CR_MASK << I2C2_SCL_CR_POSI)) + | ((scl_cr & I2C2_SCL_CR_MASK) << I2C2_SCL_CR_POSI); + + REG_WRITE(REG_I2C2_CONFIG, reg_val); +} + +static void i2c2_set_freq_div(UINT32 div) +{ + UINT32 reg_val = REG_READ(REG_I2C2_CONFIG); + + reg_val = (reg_val & ~(I2C2_FREQ_DIV_MASK << I2C2_FREQ_DIV_POSI)) + | ((div & I2C2_FREQ_DIV_MASK) << I2C2_FREQ_DIV_POSI); + + REG_WRITE(REG_I2C2_CONFIG, reg_val); +} + +static void i2c2_set_slave_addr(UINT32 addr) +{ + UINT32 reg_val = REG_READ(REG_I2C2_CONFIG); + + reg_val = (reg_val & ~(I2C2_SLV_ADDR_MASK << I2C2_SLV_ADDR_POSI)) + | ((addr & I2C2_SLV_ADDR_MASK) << I2C2_SLV_ADDR_POSI); + REG_WRITE(REG_I2C2_CONFIG, reg_val); +} + +static void i2c2_set_smbus_cs(UINT32 cs) +{ + UINT32 reg_val = REG_READ(REG_I2C2_CONFIG); + + reg_val = (reg_val & ~(I2C2_SMB_CS_MASK << I2C2_SMB_CS_POSI)) + | ((cs & I2C2_SMB_CS_MASK) << I2C2_SMB_CS_POSI); + REG_WRITE(REG_I2C2_CONFIG, reg_val); +} + +static void i2c2_set_timeout_en(UINT32 timeout) +{ + UINT32 reg_val = REG_READ(REG_I2C2_CONFIG); + + if (timeout) + { + reg_val |= I2C2_SMB_TOE; + } + else + { + reg_val &= ~I2C2_SMB_TOE; + } + REG_WRITE(REG_I2C2_CONFIG, reg_val); +} + +static void i2c2_set_free_detect(UINT32 free) +{ + UINT32 reg_val = REG_READ(REG_I2C2_CONFIG); + + if (free) + { + reg_val |= I2C2_SMB_FTE; + } + else + { + reg_val &= ~I2C2_SMB_FTE; + } + REG_WRITE(REG_I2C2_CONFIG, reg_val); +} + +static void i2c2_set_salve_en(UINT32 en) +{ + UINT32 reg_val = REG_READ(REG_I2C2_CONFIG); + + if (en) + { + reg_val |= I2C2_INH; + } + else + { + reg_val &= ~I2C2_INH; + } + REG_WRITE(REG_I2C2_CONFIG, reg_val); +} + +static void i2c2_set_smbus_en(UINT32 en) +{ + UINT32 reg_val = REG_READ(REG_I2C2_CONFIG); + + if (en) + { + reg_val |= I2C2_ENSMB; + } + else + { + reg_val &= ~I2C2_ENSMB; + } + REG_WRITE(REG_I2C2_CONFIG, reg_val); +} + +//////////////////////////////////////////////////////////////////////////////// +static void i2c2_clk_source_set_26M(void) +{ + UINT32 param; + param = PCLK_POSI_I2C2; + sddev_control(ICU_DEV_NAME, CMD_CONF_PCLK_26M, ¶m); +} + +static void i2c2_gpio_config(void) +{ + UINT32 param; + + param = GFUNC_MODE_I2C2; + sddev_control(GPIO_DEV_NAME, CMD_GPIO_ENABLE_SECOND, ¶m); +} + +static void i2c2_power_up(void) +{ + UINT32 param; + + //set 26M clock + param = PCLK_POSI_I2C2; + sddev_control(ICU_DEV_NAME, CMD_CONF_PCLK_26M, ¶m); + + param = PWD_I2C2_CLK_BIT; + sddev_control(ICU_DEV_NAME, CMD_CLK_PWR_UP, ¶m); +} + +static void i2c2_power_down(void) +{ + UINT32 param; + param = PWD_I2C2_CLK_BIT; + sddev_control(ICU_DEV_NAME, CMD_CLK_PWR_DOWN, ¶m); +} + +static void i2c2_enable_interrupt(void) +{ + UINT32 param; + param = (IRQ_I2C2_BIT); + sddev_control(ICU_DEV_NAME, CMD_ICU_INT_ENABLE, ¶m); +} + +static void i2c2_disable_interrupt(void) +{ + UINT32 param; + param = (IRQ_I2C2_BIT); + sddev_control(ICU_DEV_NAME, CMD_ICU_INT_DISABLE, ¶m); +} + +static void i2c2_send_addr(void) +{ + unsigned char tx_data; + + if ((gi2c2->WkMode & I2C2_MSG_WORK_MODE_AL_BIT) == 0) //7 bit address + { + tx_data = 0; + tx_data |= (gi2c2->SendAddr << 1); + tx_data &= ~0x01; + + if (gi2c2->WkMode == 0x01) //master read,without inner address + { + tx_data |= 0x01; + } + + REG_WRITE(REG_I2C2_DAT, tx_data); + + I2C2_PRT("send address:0x%x\r\n", tx_data); + + //modify addr flag for software state machine + gi2c2->AddrFlag ++; + + if ((gi2c2->WkMode == 0x00) || (gi2c2->WkMode == 0x01)) //master read/write 7bit without inner address + { + gi2c2->AddrFlag |= 0x13; + + I2C2_PRT("add_flag=%x\r\n", gi2c2->AddrFlag); + } + } + else //10 bit address + { + tx_data = 0xF0; // tx the first address byte with a WRITE in RW bit + tx_data |= (gi2c2->SendAddr >> 7) & 0x06; + REG_WRITE(REG_I2C2_DAT, tx_data); + + I2C2_PRT("send address:0x%x\r\n", tx_data); + + gi2c2->AddrFlag ++; + } +} + +static void i2c2_send_start(void) +{ + unsigned int cfg_data; + unsigned int int_mode; + + if (gi2c2->WkMode & I2C2_MSG_WORK_MODE_MS_BIT) //slave mode + { + return; + } + + if (gi2c2->WkMode & I2C2_MSG_WORK_MODE_RW_BIT) // read mode + { + if (gi2c2->AllDataNum > 12) + { + int_mode = 0x00; + } + else if (gi2c2->AllDataNum > 8) + { + int_mode = 0x01; + } + else if (gi2c2->AllDataNum > 4) + { + int_mode = 0x02; + } + else + { + int_mode = 0x03; + } + } + else // write mode + { + if (gi2c2->AllDataNum < 4 || (gi2c2->WkMode & I2C2_MSG_WORK_MODE_MS_BIT)) + { + int_mode = 0x00; + } + else + { + int_mode = 0x01; + } + } + + //write address into REG_I2C2_DATA + i2c2_send_addr(); + + // set start bit and mode int + cfg_data = REG_READ(REG_I2C2_STA); + cfg_data = cfg_data & 0xFFFBUL; + cfg_data |= (int_mode << 6); + cfg_data |= I2C2_SMBUS_STA; + + REG_WRITE(REG_I2C2_STA, cfg_data); +} + +static void i2c2_get_message(I2C2_MSG_ST *i2c2_config) +{ + gi2c2 = i2c2_config; + + I2C2_PRT("gi2c2.WkMode = 0x%x\r\n", gi2c2->WkMode); + I2C2_PRT("gi2c2.SalveID= 0x%x\r\n", gi2c2->Slave_addr); + I2C2_PRT("gi2c2.SendAddr = 0x%x\r\n", gi2c2->SendAddr); + I2C2_PRT("gi2c2.ack_check = %d\r\n", gi2c2->ack_check); + I2C2_PRT("gi2c2.AddrFlag = %d\r\n", gi2c2->AddrFlag); + I2C2_PRT("gi2c2.CurrentNum = %d\r\n", gi2c2->CurrentNum); + I2C2_PRT("gi2c2.InnerAddr = %d\r\n", gi2c2->InnerAddr); + I2C2_PRT("gi2c2.TransDone = %d\r\n", gi2c2->TransDone); + I2C2_PRT("gi2c2.AllDataNum = %d\r\n", gi2c2->AllDataNum); +} + +static UINT8 i2c2_get_busy(void) +{ + UINT32 value; + + value = REG_READ(REG_I2C2_STA); + + if (value & I2C2_BUSY) + { + I2C2_DEBUG_PRINTF("busy1: value=0x%x\r\n", value); + return 1; + } + + if (gi2c2->TransDone == 0) + { + I2C2_DEBUG_PRINTF("busy2:\r\n"); + return 1; + } + return 0; +} + +static void i2c2_isr(void) +{ + UINT32 i2c2_stat, i2c2_config; + UINT32 work_mode, ack, sta, sto, si; + volatile UINT8 fifo_empty_num = 0; + volatile UINT8 data_num = 0; + UINT8 i, uctemp, remain_data_cnt; + + i2c2_stat = REG_READ(REG_I2C2_STA); + si = i2c2_stat & I2C2_SMBUS_SI; + + I2C2_DEBUG_PRINTF("i2c2_stat=0x%x\r\n", i2c2_stat); + I2C2_DEBUG_PRINTF("A\r\n"); + + if (!si) + { + if (i2c2_stat & I2C2_SCL_TIMEOUT) // SCL low level over time interrupt + { + I2C2_EPRT("i\r\n"); + i2c2_open(0); + } + + if (i2c2_stat & I2C2_ARB_LOST) + { + i2c2_stat |= I2C2_ARB_LOST; + REG_WRITE(REG_I2C2_STA, i2c2_stat); + } + + return; + } + + i2c2_config = REG_READ(REG_I2C2_CONFIG); + REG_WRITE(REG_I2C2_CONFIG, i2c2_config & (~(I2C2_SMB_CS_MASK << I2C2_SMB_CS_POSI))); //fix bug + + I2C2_DEBUG_PRINTF("i2c2_config=0x%x\r\n", i2c2_config); + + ack = i2c2_stat & I2C2_SMBUS_ACK; + sto = i2c2_stat & I2C2_SMBUS_STOP; + sta = i2c2_stat & I2C2_SMBUS_STA; + + work_mode = gi2c2->WkMode & 0x03; + remain_data_cnt = gi2c2->AllDataNum - gi2c2->CurrentNum; + + switch (work_mode) + { + case 0x00: //master write + { + I2C2_DEBUG_PRINTF("B\r\n"); + + i2c2_stat &= ~I2C2_SMBUS_STA; + + if (gi2c2->ack_check && !ack) + { + i2c2_stat |= I2C2_SMBUS_STOP; //send stop + gi2c2->TransDone = 1; + + break; + } + + uctemp = gi2c2->AddrFlag; + + if (uctemp & 0x10) // all address bytes has been tx, now tx data + { + I2C2_DEBUG_PRINTF("F\r\n"); + + if (remain_data_cnt == 0) // all data bytes has been tx, now send stop + { + I2C2_DEBUG_PRINTF("H\r\n"); + i2c2_stat |= I2C2_SMBUS_STOP; //send stop + gi2c2->TransDone = 1; + + break; + } + + switch (i2c2_stat & 0x00C0) + { + case 0x00: + fifo_empty_num = 16; + break; + case 0x40: + fifo_empty_num = 12; + break; + case 0x80: + fifo_empty_num = 8; + break; + case 0xC0: + fifo_empty_num = 4; + break; + default : + fifo_empty_num = 0; + break; + + } + + if (remain_data_cnt < fifo_empty_num) + { + + I2C2_DEBUG_PRINTF("I\r\n"); + data_num = remain_data_cnt; + } + else + { + + I2C2_DEBUG_PRINTF("J\r\n"); + data_num = fifo_empty_num; + } + + for (i = 0; i < data_num; i++) + { + I2C2_DEBUG_PRINTF("K\r\n"); + + REG_WRITE(REG_I2C2_DAT, gi2c2->pData[gi2c2->CurrentNum]); + gi2c2->CurrentNum ++; + remain_data_cnt --; + } + + if (remain_data_cnt < fifo_empty_num) + { + + I2C2_DEBUG_PRINTF("L\r\n"); + i2c2_stat &= ~(I2C2_SMBUS_STA | I2C2_INT_MODE_MASK); + } + break; + } + + if (gi2c2->WkMode & I2C2_MSG_WORK_MODE_AL_BIT) //10bit address + { + I2C2_DEBUG_PRINTF("M\r\n"); + if (gi2c2->WkMode & I2C2_MSG_WORK_MODE_IA_BIT) //with inner address + { + if ((uctemp & 0x08) == 0) + { + if ((uctemp & 0x03) == 0x00) + { + I2C2_DEBUG_PRINTF("tx error!!!\r\n"); + break; + } + else if ((uctemp & 0x03) == 0x01) + { + + I2C2_DEBUG_PRINTF("O\r\n"); + gi2c2->SendAddr &= 0xFF; + REG_WRITE(REG_I2C2_DAT, gi2c2->SendAddr); + gi2c2->AddrFlag++; + } + else + { + I2C2_DEBUG_PRINTF("P\r\n"); + REG_WRITE(REG_I2C2_DAT, gi2c2->InnerAddr); + gi2c2->AddrFlag |= 0x1B; + } + } + else + { + gi2c2->AddrFlag |= 0x13; + } + } + else //without inner address + { + + I2C2_DEBUG_PRINTF("N\r\n"); + if ((uctemp & 0x03) == 0x00) + { + I2C2_DEBUG_PRINTF("tx error!!!\r\n"); + break; + } + else if ((uctemp & 0x03) == 0x01) + { + I2C2_DEBUG_PRINTF("O\r\n"); + gi2c2->SendAddr &= 0xFF; + REG_WRITE(REG_I2C2_DAT, gi2c2->SendAddr); + gi2c2->AddrFlag |= 0x13; + } + else + { + gi2c2->AddrFlag |= 0x13; + } + } + } + else //7 bit address + { + + I2C2_DEBUG_PRINTF("M'\r\n"); + if (gi2c2->WkMode & I2C2_MSG_WORK_MODE_IA_BIT) //with inner address + { + + I2C2_DEBUG_PRINTF("N\r\n"); + + if ((uctemp & 0x08) == 0) + { + I2C2_DEBUG_PRINTF("O\r\n"); + REG_WRITE(REG_I2C2_DAT, gi2c2->InnerAddr); //write inner address + + gi2c2->AddrFlag |= 0x13; + } + else + { + I2C2_DEBUG_PRINTF("P\r\n"); + gi2c2->AddrFlag |= 0x13; + } + } + else + { + gi2c2->AddrFlag |= 0x13; + } + } + break; + } + + case 0x01: //master read + { + i2c2_stat &= ~I2C2_SMBUS_STA; + I2C2_DEBUG_PRINTF("C\r\n"); + + if (sta && gi2c2->ack_check && !ack) + { + i2c2_stat = i2c2_stat | I2C2_SMBUS_STOP; //send stop + gi2c2->TransDone = 1; + + break; + } + + uctemp = gi2c2->AddrFlag; + + if (uctemp & 0x10) // all address bytes has been tx, now tx data + { + I2C2_DEBUG_PRINTF("D\r\n"); + + if (sta) + { + i2c2_stat = i2c2_stat | I2C2_SMBUS_ACK; //sen ack + break; + } + + switch (i2c2_stat & 0x00C0) + { + case 0x00: + data_num = 12; + break; + case 0x40: + data_num = 8; + break; + case 0x80: + data_num = 4; + break; + case 0xC0: + data_num = 1; + break; + default : + data_num = 0; + break; + } + + for (i = 0; i < data_num; i++) + { + I2C2_DEBUG_PRINTF("E\r\n"); + + gi2c2->pData[gi2c2->CurrentNum] = REG_READ(REG_I2C2_DAT); + gi2c2->CurrentNum ++; + remain_data_cnt --; + } + + if (remain_data_cnt == 0) // all data bytes has been tx, now send stop + { + I2C2_DEBUG_PRINTF("F\r\n"); + + i2c2_stat = (i2c2_stat & (~(I2C2_SMBUS_ACK | I2C2_SMBUS_STA))) | I2C2_SMBUS_STOP ; //send no ack/stop + gi2c2->TransDone = 1; + + } + else if (remain_data_cnt < data_num) + { + i2c2_stat = i2c2_stat | (I2C2_SMBUS_ACK | I2C2_INT_MODE_MASK); + } + else + { + i2c2_stat = i2c2_stat | I2C2_SMBUS_ACK ; + } + break; + } + if (gi2c2->WkMode & I2C2_MSG_WORK_MODE_AL_BIT) //10bit address + { + + I2C2_DEBUG_PRINTF("G\r\n"); + + if (gi2c2->WkMode & I2C2_MSG_WORK_MODE_IA_BIT) //with inner address + { + I2C2_DEBUG_PRINTF("F\r\n"); + + if ((uctemp & 0x08) == 0) + { + if ((uctemp & 0x03) == 0x00) + { + I2C2_DEBUG_PRINTF("tx error!!!\r\n"); + + break; + } + else if ((uctemp & 0x03) == 0x01) + { + REG_WRITE(REG_I2C2_DAT, gi2c2->SendAddr & 0xFF); + gi2c2->AddrFlag++; + } + else + { + REG_WRITE(REG_I2C2_DAT, gi2c2->InnerAddr); + gi2c2->AddrFlag |= 0x08; + } + } + else + { + if ((uctemp & 0x03) == 0x02) + { + i2c2_stat |= I2C2_SMBUS_STA; + REG_WRITE(REG_I2C2_DAT, ((gi2c2->SendAddr >> 7) & 0x06) | 0xF1); + gi2c2->AddrFlag |= 0x13; + } + else + { + I2C2_DEBUG_PRINTF("read error1!!!\r\n"); + break; + } + } + } + else //without inner address + { + + if ((uctemp & 0x03) == 0x00) + { + I2C2_DEBUG_PRINTF("read error1!!!\r\n"); + } + else if ((uctemp & 0x03) == 0x01) + { + REG_WRITE(REG_I2C2_DAT, gi2c2->SendAddr & 0xFF); + + gi2c2->AddrFlag ++; + } + else if ((uctemp & 0x03) == 0x02) + { + i2c2_stat |= I2C2_SMBUS_STA; + REG_WRITE(REG_I2C2_DAT, ((gi2c2->SendAddr >> 7) & 0x06) | 0xF1); + + gi2c2->AddrFlag |= 0x13; + } + else + { + I2C2_DEBUG_PRINTF("read error1!!!\r\n"); + break; + } + + } + } + else // 7 bite address + { + I2C2_DEBUG_PRINTF("H\r\n"); + + if (gi2c2->WkMode & I2C2_MSG_WORK_MODE_IA_BIT) //with inner address + { + I2C2_DEBUG_PRINTF("D\r\n"); + + if ((uctemp & 0x08) == 0) + { + REG_WRITE(REG_I2C2_DAT, gi2c2->InnerAddr); //write inner address + + gi2c2->AddrFlag = (gi2c2->AddrFlag & ~0x0B) | 0x0A; + } + else + { + i2c2_stat |= I2C2_SMBUS_STA; + REG_WRITE(REG_I2C2_DAT, (gi2c2->SendAddr << 1) | 0x01); + + gi2c2->AddrFlag |= 0x13; + } + } + else //without inner address + { + gi2c2->AddrFlag |= 0x13; + } + + } + break; + + } + case 0x02: // slave write + { + I2C2_DEBUG_PRINTF("d\r\n"); + + if (sto) // detect a STOP + { + + I2C2_DEBUG_PRINTF("k\r\n"); + + gi2c2->TransDone = 1; + break; + } + + + if (i2c2_stat & I2C2_ADDR_MATCH) // match address byte + { + + I2C2_DEBUG_PRINTF("l\r\n"); + + i2c2_stat |= I2C2_SMBUS_ACK; // send ACK for address byte + } + + if ((i2c2_stat & I2C2_TX_MODE) == 0) // read mode + { + break; + } + + + if (i2c2_stat & I2C2_SMBUS_ACK) // detect an ACK + { + + I2C2_DEBUG_PRINTF("i\r\n"); + + REG_WRITE(REG_I2C2_DAT, gi2c2->pData[gi2c2->CurrentNum]); + gi2c2->CurrentNum ++; + remain_data_cnt --; + + if (remain_data_cnt == 0) + { + I2C2_DEBUG_PRINTF("j\r\n"); + + // TODO + } + } + break; + } + case 0x03: // slave read + { + I2C2_DEBUG_PRINTF("e\r\n"); + + if (sto) // detect a STOP + { + gi2c2->TransDone = 1; + break; + } + + if (i2c2_stat & I2C2_ADDR_MATCH) // match address byte + { + + i2c2_stat |= I2C2_SMBUS_ACK; // send ACK + break; + } + + switch (i2c2_stat & I2C2_INT_MODE_MASK) + { + case 0x0000: + data_num = 12; + break; + case 0x0040: + data_num = 8; + break; + case 0x0080: + data_num = 4; + break; + case 0x00C0: + data_num = 1; + break; + default : + data_num = 0; + break; + } + + for (i = 0; i < data_num; i ++) + { + + gi2c2->pData[gi2c2->CurrentNum] = REG_READ(REG_I2C2_DAT); + gi2c2->CurrentNum ++; + remain_data_cnt --; + } + + if (remain_data_cnt == 0) + { + + i2c2_stat &= ~I2C2_SMBUS_ACK; // send NACK + gi2c2->TransDone = 1; + } + else if (remain_data_cnt < data_num) + { + + // send ACK, set int_mode + i2c2_stat = i2c2_stat | I2C2_SMBUS_ACK | I2C2_INT_MODE_MASK; + } + else + { + + i2c2_stat |= I2C2_SMBUS_ACK; // send ACK + } + break; + } + + default: + break; + } + + REG_WRITE(REG_I2C2_STA, i2c2_stat & (~I2C2_SMBUS_SI)); //clear si + REG_WRITE(REG_I2C2_CONFIG, i2c2_config); +} + +static void i2c2_software_init(void) +{ + ddev_register_dev(I2C2_DEV_NAME, &i2c2_op); +} + +static void i2c2_hardware_init(void) +{ + //UINT32 reg; + /* register interrupt */ + intc_service_register(IRQ_I2C2, PRI_IRQ_I2C2, i2c2_isr); + + /* clear all setting */ + REG_WRITE(REG_I2C2_CONFIG, 0); + REG_WRITE(REG_I2C2_STA, 0); +} + +void i2c2_init(void) +{ + gi2c2 = os_malloc(sizeof(I2C2_MSG_ST)); + os_memset((unsigned char *)gi2c2, 0, sizeof(I2C2_MSG_ST)); + + i2c2_software_init(); + i2c2_hardware_init(); +} + +void i2c2_exit(void) +{ + /* clear all setting */ + REG_WRITE(REG_I2C2_CONFIG, 0); + REG_WRITE(REG_I2C2_STA, 0); + + ddev_unregister_dev(I2C2_DEV_NAME); +} + +static UINT32 i2c2_open(UINT32 op_flag) +{ + UINT32 reg, reg1; + + reg = REG_READ(REG_I2C2_CONFIG); + reg1 = REG_READ(REG_I2C2_STA); + + if (reg & I2C2_ENSMB) + { + reg1 |= I2C2_SMBUS_STOP; + reg = 0; + } + + REG_WRITE(REG_I2C2_CONFIG, reg); + REG_WRITE(REG_I2C2_STA, reg1); + + if (op_flag) + { + i2c2_set_freq_div(op_flag); + } + else + { + i2c2_set_freq_div(I2C_CLK_DIVID(I2C_DEFAULT_BAUD)); + } + + i2c2_set_idle_cr(0x3); + i2c2_set_scl_cr(0x4); + i2c2_set_smbus_cs(0x3); + i2c2_set_timeout_en(1); + i2c2_set_free_detect(1); + i2c2_set_salve_en(0); // enable/disable i2c slave + + i2c2_enable_interrupt(); + i2c2_power_up(); + i2c2_gpio_config(); + + i2c2_set_smbus_en(1); + + reg = REG_READ(REG_I2C2_CONFIG); + + I2C2_DEBUG_PRINTF("REG_I2C2_CONFIG=0x%lx\r\n", reg); + + gi2c2->WkMode = op_flag & 0x0F; + + return I2C2_SUCCESS; +} + +static UINT32 i2c2_close(void) +{ + i2c2_set_smbus_en(0); + + i2c2_disable_interrupt(); + i2c2_power_down(); + + return I2C2_SUCCESS; +} + +static UINT32 i2c2_read(char *user_buf, UINT32 count, UINT32 op_flag) +{ + UINT32 reg, start_tick, cur_tick; + I2C_OP_PTR i2c_op; + GLOBAL_INT_DECLARATION(); + + i2c_op = (I2C_OP_PTR)op_flag; + + if (gi2c2->TransDone != 0) + { + return 0; + } + + GLOBAL_INT_DISABLE(); + gi2c2->AddrFlag = 0; + gi2c2->TransDone = 0; + gi2c2->ack_check = 1; + gi2c2->CurrentNum = 0; + gi2c2->AllDataNum = count; + gi2c2->pData = (UINT8 *)user_buf; + gi2c2->InnerAddr = i2c_op->op_addr; + gi2c2->SendAddr = i2c_op->salve_id; + gi2c2->Slave_addr = i2c_op->slave_addr; + gi2c2->WkMode |= (I2C2_MSG_WORK_MODE_RW_BIT); //READ + gi2c2->ErrorNO = 0; + + + I2C2_PRT("gi2c2.WkMode = 0x%x\r\n", gi2c2->WkMode); + I2C2_PRT("gi2c2.SalveID= 0x%x\r\n", gi2c2->Slave_addr); + I2C2_PRT("gi2c2.SendAddr = 0x%x\r\n", gi2c2->SendAddr); + I2C2_PRT("gi2c2.ack_check = %d\r\n", gi2c2->ack_check); + I2C2_PRT("gi2c2.AddrFlag = %d\r\n", gi2c2->AddrFlag); + I2C2_PRT("gi2c2.CurrentNum = %d\r\n", gi2c2->CurrentNum); + I2C2_PRT("gi2c2.InnerAddr = %d\r\n", gi2c2->InnerAddr); + I2C2_PRT("gi2c2.TransDone = %d\r\n", gi2c2->TransDone); + I2C2_PRT("gi2c2.AllDataNum = %d\r\n", gi2c2->AllDataNum); + + //write salve address + reg = REG_READ(REG_I2C2_CONFIG); + reg &= (~(0x3FF << I2C2_SLV_ADDR_POSI)); + reg = reg | (((gi2c2->Slave_addr) & 0x3FF) << I2C2_SLV_ADDR_POSI); + REG_WRITE(REG_I2C2_CONFIG, reg); + + reg = REG_READ(REG_I2C2_CONFIG); + I2C2_PRT("i2c2_config= %lx\r\n", reg); + + reg = REG_READ(REG_I2C2_STA); + I2C2_PRT("i2c2_stat= %lx\r\n", reg); + + i2c2_send_start(); + GLOBAL_INT_RESTORE(); + + start_tick = rtos_get_time(); + while(1) + { + if (i2c2_get_busy() == 1) + { + UINT32 past = 0; + cur_tick = rtos_get_time(); + past = (cur_tick >= start_tick) ? (cur_tick - start_tick) : (0xffffffffu - start_tick + cur_tick); + if ((past) > I2C_READ_WAIT_TIMEOUT) + { + gi2c2->ErrorNO = 1; + break; + } + //rtos_delay_milliseconds(10); + } + else + { + break; + } + } + + GLOBAL_INT_DISABLE(); + gi2c2->TransDone = 0; + GLOBAL_INT_RESTORE(); + + return gi2c2->ErrorNO; +} + +static UINT32 i2c2_write(char *user_buf, UINT32 count, UINT32 op_flag) +{ + UINT32 reg, start_tick, cur_tick; + I2C_OP_PTR i2c_op; + GLOBAL_INT_DECLARATION(); + + if (gi2c2->TransDone != 0) + { + return 0; + } + + GLOBAL_INT_DISABLE(); + i2c_op = (I2C_OP_PTR)op_flag; + + //os_printf("i2c2_write\r\n"); + gi2c2->AddrFlag = 0; + gi2c2->TransDone = 0; + gi2c2->ack_check = 1; + gi2c2->CurrentNum = 0; + gi2c2->AllDataNum = count; + gi2c2->pData = (UINT8 *)user_buf; + gi2c2->InnerAddr = i2c_op->op_addr; + gi2c2->SendAddr = i2c_op->salve_id; + gi2c2->Slave_addr = i2c_op->slave_addr; + gi2c2->WkMode &= (~I2C2_MSG_WORK_MODE_RW_BIT); //WRITE + + I2C2_PRT("gi2c2.WkMode = 0x%x\r\n", gi2c2->WkMode); + I2C2_PRT("gi2c2.SalveID= 0x%x\r\n", gi2c2->Slave_addr); + I2C2_PRT("gi2c2.SendAddr = 0x%x\r\n", gi2c2->SendAddr); + I2C2_PRT("gi2c2.ack_check = %d\r\n", gi2c2->ack_check); + I2C2_PRT("gi2c2.AddrFlag = %d\r\n", gi2c2->AddrFlag); + I2C2_PRT("gi2c2.CurrentNum = %d\r\n", gi2c2->CurrentNum); + I2C2_PRT("gi2c2.InnerAddr = %d\r\n", gi2c2->InnerAddr); + I2C2_PRT("gi2c2.TransDone = %d\r\n", gi2c2->TransDone); + I2C2_PRT("gi2c2.AllDataNum = %d\r\n", gi2c2->AllDataNum); + + // salve address---as slave + reg = REG_READ(REG_I2C2_CONFIG); + reg &= (~(0x3FF << I2C2_SLV_ADDR_POSI)); + reg = reg | (((gi2c2->Slave_addr) & 0x3FF) << I2C2_SLV_ADDR_POSI); + REG_WRITE(REG_I2C2_CONFIG, reg); + + reg = REG_READ(REG_I2C2_CONFIG); + I2C2_PRT("i2c2_config= %lx\r\n", reg); + + reg = REG_READ(REG_I2C2_STA); + I2C2_PRT("i2c2_stat= %lx\r\n", reg); + + i2c2_send_start(); + GLOBAL_INT_RESTORE(); + + start_tick = rtos_get_time(); + while(1) + { + if (i2c2_get_busy() == 1) + { + UINT32 past = 0; + cur_tick = rtos_get_time(); + past = (cur_tick >= start_tick) ? (cur_tick - start_tick) : (0xffffffffu - start_tick + cur_tick); + if ((past) > I2C_READ_WAIT_TIMEOUT) + { + gi2c2->ErrorNO = 1; + break; + } + //rtos_delay_milliseconds(10); + } + else + { + break; + } + } + + GLOBAL_INT_DISABLE(); + gi2c2->TransDone = 0; + GLOBAL_INT_RESTORE(); + + return gi2c2->ErrorNO; +} + +static UINT32 i2c2_ctrl(UINT32 cmd, void *param) +{ + UINT32 ret = I2C2_SUCCESS; + + switch (cmd) + { + case I2C2_CMD_SET_IDLE_CR: + i2c2_set_idle_cr(*((UINT32 *)param)); + break; + case I2C2_CMD_SET_SCL_CR: + i2c2_set_scl_cr(*((UINT32 *)param)); + break; + case I2C2_CMD_SET_FREQ_DIV: + i2c2_set_freq_div(*((UINT32 *)param)); + break; + case I2C2_CMD_SET_SMBUS_CS: + i2c2_set_smbus_cs(*((UINT32 *)param)); + break; + case I2C2_CMD_SET_TIMEOUT_EN: + i2c2_set_timeout_en(*((UINT32 *)param)); + break; + case I2C2_CMD_SET_FREE_DETECT: + i2c2_set_free_detect(*((UINT32 *)param)); + break; + case I2C2_CMD_SET_SLAVE_EN: + i2c2_set_salve_en(*((UINT32 *)param)); + break; + case I2C2_CMD_SET_SMBUS_EN: + i2c2_set_smbus_en(*((UINT32 *)param)); + break; + case I2C2_CMD_SET_POWER_UP: + i2c2_power_up(); + break; + case I2C2_CMD_SET_POWER_DOWN: + i2c2_power_down(); + break; + case I2C2_CMD_GET_MESSAGE: + i2c2_get_message(param); + break; + + default: + ret = I2C2_FAILURE; + break; + } + + return ret; +} + + + diff --git a/beken_os/beken378/driver/i2c/i2c2.h b/beken_os/beken378/driver/i2c/i2c2.h new file mode 100755 index 0000000..ae37477 --- /dev/null +++ b/beken_os/beken378/driver/i2c/i2c2.h @@ -0,0 +1,65 @@ +#ifndef _I2C2_H_ +#define _I2C2_H_ + +#include "uart_pub.h" + +#define I2C2_DEBUG +//#undef I2C2_DEBUG + +#define I2C2_PRT os_null_printf//os_printf + +#ifdef I2C2_DEBUG +#define I2C2_WPRT warning_prf +#define I2C2_EPRT os_printf +#define I2C2_DEBUG_PRINTF os_null_printf +#else +#define I2C2_WPRT os_null_printf +#define I2C2_EPRT os_printf +#define I2C2_DEBUG_PRINTF os_null_printf +#endif + +#define I2C2_BASE_ADDR (0x0802600) + +#define REG_I2C2_CONFIG (I2C2_BASE_ADDR + 4 * 0) +#define I2C2_IDLE_CR_POSI (0) +#define I2C2_IDLE_CR_MASK (0x7) +#define I2C2_SCL_CR_POSI (3) +#define I2C2_SCL_CR_MASK (0x7) +#define I2C2_FREQ_DIV_POSI (6) +#define I2C2_FREQ_DIV_MASK (0x3FF) +#define I2C2_SLV_ADDR_POSI (16) +#define I2C2_SLV_ADDR_MASK (0x3FF) +#define I2C2_SMB_CS_POSI (26) +#define I2C2_SMB_CS_MASK (0x3) +#define I2C2_SMB_TOE (1 << 28) +#define I2C2_SMB_FTE (1 << 29) +#define I2C2_INH (1 << 30) +#define I2C2_ENSMB (1 << 31) + +#define REG_I2C2_STA (I2C2_BASE_ADDR + 4 * 1) +#define I2C2_SMBUS_SI (1 << 0) +#define I2C2_SCL_TIMEOUT (1 << 1) +#define I2C2_ARB_LOST (1 << 3) +#define I2C2_RXFIFO_EMPTY (1 << 4) +#define I2C2_TXFIFO_FULL (1 << 5) +#define I2C2_INT_MODE_POSI (6 ) +#define I2C2_INT_MODE_MASK (0x03<< 6) +#define I2C2_SMBUS_ACK (1 << 8) +#define I2C2_SMBUS_STOP (1 << 9) +#define I2C2_SMBUS_STA (1 << 10) +#define I2C2_ADDR_MATCH (1 << 11) +#define I2C2_ACK_REQ (1 << 12) +#define I2C2_TX_MODE (1 << 13) +#define I2C2_MASTER (1 << 14) +#define I2C2_BUSY (1 << 15) + +#define REG_I2C2_DAT (I2C2_BASE_ADDR + 4 * 2) +#define I2C2_DAT_MASK (0xFF) + +static UINT32 i2c2_open(UINT32 op_flag); +static UINT32 i2c2_close(void); +static UINT32 i2c2_read(char *user_buf, UINT32 count, UINT32 op_flag); +static UINT32 i2c2_write(char *user_buf, UINT32 count, UINT32 op_flag); +static UINT32 i2c2_ctrl(UINT32 cmd, void *param); + +#endif // _I2C2_H_ diff --git a/beken_os/beken378/driver/i2c/i2c_pub.h b/beken_os/beken378/driver/i2c/i2c_pub.h new file mode 100755 index 0000000..8b03c11 --- /dev/null +++ b/beken_os/beken378/driver/i2c/i2c_pub.h @@ -0,0 +1,120 @@ +#ifndef __I2C1_PUB_H__ +#define __I2C1_PUB_H__ + +#define I2C1_FAILURE (1) +#define I2C1_SUCCESS (0) +#define I2C2_FAILURE (1) +#define I2C2_SUCCESS (0) + +#define I2C1_DEV_NAME "i2c1" +#define I2C2_DEV_NAME "i2c2" + +#define I2C1_CMD_MAGIC (0x0AB00000) +#define I2C2_CMD_MAGIC (0x0ABF0000) + +#include "uart_pub.h" +#define I2C_DEBUG +#undef I2C_DEBUG + +#ifdef I2C_DEBUG +#define I2C_PRT os_printf +#else +#define I2C_PRT null_prf +#define I2C_WPRT null_prf +#endif + +#define ADDR_WIDTH_8 1 +#define ADDR_WIDTH_16 2 + +enum +{ + I2C1_CMD_SET_ENSMB = I2C1_CMD_MAGIC + 1, + I2C1_CMD_SET_SMBUS_STA, + I2C1_CMD_SET_SMBUS_STOP, + I2C1_CMD_SET_SMBUS_ACK_TX, + I2C1_CMD_SET_SMBUS_TX_MODE, + I2C1_CMD_SET_FREQ_DIV, + I2C1_CMD_GET_SMBUS_INTERRUPT, + I2C1_CMD_CLEAR_SMBUS_INTERRUPT, + I2C1_CMD_GET_ACK_RX, + I2C1_CMD_GET_ACK_REQ, + I2C1_CMD_GET_SMBUS_BUSY, +}; + +enum +{ + I2C2_CMD_SET_IDLE_CR = I2C2_CMD_MAGIC + 1, + I2C2_CMD_SET_SCL_CR, + I2C2_CMD_SET_FREQ_DIV, + I2C2_CMD_SET_SMBUS_CS, + I2C2_CMD_SET_TIMEOUT_EN, + I2C2_CMD_SET_FREE_DETECT, + I2C2_CMD_SET_SLAVE_EN, + I2C2_CMD_SET_SMBUS_EN, + I2C2_CMD_SET_POWER_UP, + I2C2_CMD_SET_POWER_DOWN, + I2C2_CMD_GET_MESSAGE, + I2C2_CMD_GET_BUSY, +}; + +typedef struct i2c_op_st +{ + UINT8 addr_width; + UINT8 salve_id; + UINT16 op_addr; + UINT8 slave_addr; + UINT8 mode; +} I2C_OP_ST, *I2C_OP_PTR; + + +typedef struct i2c2_msg +{ + UINT8 TxMode; //0: Read; 1: Write + UINT8 WkMode; // work mode + //RW(bit 0): 0:write, 1:read + // MS(bit 1): 0:master, 1:slave + // AL(bit 2): 0:7bit address, 1:10bit address + // IA(bit 3): 0:without inner address, 1: with inner address + // reserved(bit [4:7]): reserved + UINT8 InnerAddr; + UINT8 SendAddr; //only master send address + UINT32 CurrentNum; + UINT32 AllDataNum; + UINT8 *pData; + UINT8 Slave_addr; //slave address + UINT8 AddrFlag; + UINT8 TransDone; + UINT8 ack_check; //0: don't care ACK; 1: care ACK + UINT8 ErrorNO; +} I2C2_MSG_ST, *I2C2_MSG_PTR; + +#define NUM_ROUND_UP(a,b) ((a) / (b) + (((a) % (b)) ? 1 : 0)) + +#if CFG_XTAL_FREQUENCE +#define I2C1_DEFAULT_CLK CFG_XTAL_FREQUENCE +#else +#define I2C1_DEFAULT_CLK 26000000 +#endif +#define I2C_BAUD_1KHZ 1000 +#define I2C_BAUD_100KHZ 100000 +#define I2C_BAUD_400KHZ 400000 +#define I2C_BAUD_4MHZ 4000000 +#define I2C_DEFAULT_BAUD I2C_BAUD_400KHZ +#define I2C_CLK_DIVID(rate) (NUM_ROUND_UP(NUM_ROUND_UP(I2C1_DEFAULT_CLK, rate) - 6, 3) - 1) +#define I2C_DEF_DIV 0x16 + +#define I2C2_MSG_WORK_MODE_RW_BIT (1<<0) /* 0:write, 1:read */ +#define I2C2_MSG_WORK_MODE_MS_BIT (1<<1) /* 0:master, 1:slave */ +#define I2C2_MSG_WORK_MODE_AL_BIT (1<<2) /* 0:7bit address, 1:10bit address */ +#define I2C2_MSG_WORK_MODE_IA_BIT (1<<3) /* 0:without inner address, 1: with inner address */ + +#define I2C_READ_WAIT_TIMEOUT (50) /* ms */ +#define I2C_WRITE_WAIT_TIMEOUT (50) /* ms */ + +void i2c1_init(void); +void i2c1_exit(void); +void i2c2_init(void); +void i2c2_exit(void); + +#endif // __I2C1_PUB_H__ + diff --git a/beken_os/beken378/driver/i2s/i2s.c b/beken_os/beken378/driver/i2s/i2s.c new file mode 100755 index 0000000..e876386 --- /dev/null +++ b/beken_os/beken378/driver/i2s/i2s.c @@ -0,0 +1,222 @@ +#include "include.h" +#include "arm_arch.h" + +#include "i2s.h" +#include "i2s_pub.h" +#include "gpio_pub.h" +#include "drv_model_pub.h" +#include "intc_pub.h" +#include "icu_pub.h" +#include "driver_audio_if_pub.h" +#include "uart_pub.h" +#include "music_msg_pub.h" +static SDD_OPERATIONS i2s_op = +{ + i2s_ctrl +}; +static UINT8 flag_i2s_active =0; + +static void i2s_clk_config(UINT8 enable) +{ + UINT32 param; + UINT32 cmd; + + if(enable) + cmd = CMD_CLK_PWR_UP; + else + cmd = CMD_CLK_PWR_DOWN; + + param = PWD_I2S_PCM_CLK_BIT; + sddev_control(ICU_DEV_NAME, cmd, ¶m); +} + +static void i2s_hw_init(void) +{ + UINT32 value_cfg2,value_cn; + UINT32 param = GFUNC_MODE_I2S; + sddev_control(GPIO_DEV_NAME, CMD_GPIO_ENABLE_SECOND, ¶m); + + i2s_clk_config(1); + + value_cfg2 = (2 << TXFIFO_TXFIFO_MODE) | (0 << TXFIFO_DOWN_SMPRATIO); + REG_WRITE(PCM_CFG2,value_cfg2); + value_cn = (1 << TX_FIFO0_LEVEL_POSI) | (1 << RX_FIFO_LEVEL_POSI); + REG_WRITE(PCM_CN,value_cn); +} + +static void i2s_active(int enable) +{ + UINT32 value_ctrl, value_cn,sts,param; + + os_printf("====i2s active:%x===\r\n",enable); + + value_ctrl = REG_READ(PCM_CTRL); + value_cn = REG_READ(PCM_CN); + if(enable) + { + flag_i2s_active =1; + value_ctrl |= I2S_PCM_EN; + value_cn |= TX_INT0_EN | TX_UDF0_EN|TX_INT1_EN | TX_UDF1_EN|TX_INT2_EN | TX_UDF2_EN; + } + else + { + flag_i2s_active = 0; + value_ctrl &= ~I2S_PCM_EN; + value_cn &= ~( TX_INT0_EN | TX_UDF0_EN|TX_INT1_EN | TX_UDF1_EN|TX_INT2_EN |TX_UDF2_EN| RX_INT_EN | RX_OVF_EN); + } + REG_WRITE(PCM_CTRL, value_ctrl); + REG_WRITE(PCM_CN, value_cn); + + sts = REG_READ(PCM_STAT); + REG_WRITE(PCM_STAT,sts); + + param = IRQ_I2S_PCM_BIT; + if(enable) + sddev_control(ICU_DEV_NAME, CMD_ICU_INT_ENABLE, ¶m); + else + sddev_control(ICU_DEV_NAME, CMD_ICU_INT_DISABLE, ¶m); + +} + +static void i2s_rx_active(int enable) +{ + UINT32 value_cn; + + value_cn = REG_READ(PCM_CN); + if(enable) + { + value_cn |= (RX_INT_EN | RX_OVF_EN | RX_FIFO_CLR); + } + else + { + value_cn &= ~(RX_INT_EN | RX_OVF_EN); + } + REG_WRITE(PCM_CN, value_cn); +} +/*default to slave mode*/ +static void i2s_set_freq_datawidth(i2s_rate_t *p_rate) +{ + UINT32 bitratio, value = 0; + + if( (p_rate->freq != 8000) && (p_rate->freq != 16000) && + (p_rate->freq != 24000) && (p_rate->freq != 32000) &&(p_rate->freq != 48000)&& + (p_rate->freq != 11025) && (p_rate->freq != 22050) &&(p_rate->freq != 44100) ) + { + return; + } + if(p_rate->datawidth > 32) + { + return; + } + + bitratio = ((I2S_SYS_CLK / (p_rate->freq * p_rate->datawidth ) / 4) - 1) & 0xFF; + value = (0 << MODE_SEL_POSI) + | ((p_rate->datawidth - 1) << DATALEN_POSI) + | ((p_rate->datawidth - 1) << SMPRATIO_POSI) + | (bitratio << BITRATIO_POSI)//this value is unused in slave mode + | (SLAVEEN); + REG_WRITE(PCM_CTRL, value); +} + +static void i2s_select_mode(UINT8 mode) +{ + UINT32 value; + + if(mode == 3 || mode > 7) + { + return; + } + + value = REG_READ(PCM_CTRL); + value &= ~(MODE_SEL_MASK << MODE_SEL_POSI); + value |= (mode << MODE_SEL_POSI); + REG_WRITE(PCM_CTRL, value); +} + +static void i2s_set_level(i2s_level_t *p_level) +{ + UINT32 value; + + value = REG_READ(PCM_CN); + + value &= ~((RX_FIFO_LEVEL_MASK << RX_FIFO_LEVEL_POSI) | (TX_FIFO0_LEVEL_MASK << TX_FIFO0_LEVEL_POSI)); + value |= ((p_level->rx_level << RX_FIFO_LEVEL_POSI) | (p_level->tx_level << TX_FIFO0_LEVEL_POSI)); + + REG_WRITE(PCM_CN, value); +} + +void i2s_init(void) +{ + intc_service_register(IRQ_I2S_PCM, PRI_IRQ_I2S_PCM, i2s_isr); + sddev_register_dev(I2S_DEV_NAME, &i2s_op); +} + +void i2s_exit(void) +{ + sddev_unregister_dev(I2S_DEV_NAME); +} + +UINT8 is_i2s_active(void) +{ + return flag_i2s_active; +} + +static UINT32 i2s_ctrl(UINT32 cmd, void *param) +{ + UINT8 ret = I2S_SUCCESS; + + switch(cmd) + { + case I2S_HW_SET: + i2s_hw_init(); + break; + case I2S_CMD_SET_FREQ_DATAWIDTH: + i2s_set_freq_datawidth((i2s_rate_t *)param); + break; + case I2S_CMD_ACTIVE: + i2s_active(*(UINT8 *)param); + break; + case I2S_CMD_RXACTIVE: + i2s_rx_active(*(UINT8 *)param); + break; + case I2S_CMD_SELECT_MODE: + i2s_select_mode(*(UINT8 *)param); + break; + case I2S_CMD_SET_LEVEL: + i2s_set_level((i2s_level_t *)param); + break; + default: + ret = I2S_FAILURE; + break; + } + return ret; +} + +void i2s_isr(void) +{ + uint32_t sts = REG_READ(PCM_STAT); + +#if (CONFIG_APP_MP3PLAYER==1) + uint16_t i; + uint16_t sample[32]; + uint16_t len = 0; + + if(sts & (TX_INT0|TX_UDF0)) + { + len = aud_get_buffer_length((uint8_t*)sample,32*2); + if( len != 0 ) + { + for( i = 0; i < len >> 1; i+= 2 ) + { + REG_WRITE(PCM_DAT0,sample[i]);//test_pcm[i]);// + REG_WRITE(PCM_DAT0,sample[i+1]);//test_pcm[i+1]);// + } + } + else + { + i2s_active(0); + } + } +#endif + REG_WRITE(PCM_STAT,sts); +} diff --git a/beken_os/beken378/driver/i2s/i2s.h b/beken_os/beken378/driver/i2s/i2s.h new file mode 100755 index 0000000..c52170b --- /dev/null +++ b/beken_os/beken378/driver/i2s/i2s.h @@ -0,0 +1,85 @@ +#ifndef _I2S_H_ +#define _I2S_H_ + +#define I2S_BASE (0x00802500) + +#define PCM_CTRL (I2S_BASE + 0 * 4) +#define BITRATIO_POSI (0) +#define BITRATIO_MASK (0xFF) +#define SMPRATIO_POSI (8) +#define SMPRATIO_MASK (0x1F) +#define PCM_DLEN_POSI (13) +#define PCM_DLEN_MASK (0x07) +#define DATALEN_POSI (16) +#define DATALEN_MASK (0x1F) +#define SYNCLEN_POSI (21) +#define SYNCLEN_MASK (0x07) +#define LSB_FIRST (0x01UL << 24) +#define SCK_INV (0x01UL << 25) +#define LRCK_RP (0x01UL << 26) +#define MODE_SEL_POSI (27) +#define MODE_SEL_MASK (0x07) +#define MSTEN (0x01UL << 30) +#define SLAVEEN (0 << 30) +#define I2S_PCM_EN (0x01UL << 31) + +#define PCM_CN (I2S_BASE + 1 * 4) +#define RX_INT_EN (0x01UL << 0) +#define TX_INT0_EN (0x01UL << 1) +#define TX_INT1_EN (0x01UL << 2) +#define TX_INT2_EN (0x01UL << 3) +#define RX_OVF_EN (0x01UL << 4) +#define TX_UDF0_EN (0x01UL << 5) +#define TX_UDF1_EN (0x01UL << 6) +#define TX_UDF2_EN (0x01UL << 7) +#define RX_FIFO_LEVEL_POSI (8) +#define RX_FIFO_LEVEL_MASK (0x03) +#define TX_FIFO0_LEVEL_POSI (10) +#define TX_FIFO0_LEVEL_MASK (0x03) +#define TX_FIFO1_LEVEL_POSI (12) +#define TX_FIFO1_LEVEL_MASK (0x03) +#define TX_FIFO2_LEVEL_POSI (14) +#define TX_FIFO2_LEVEL_MASK (0x03) +#define RX_FIFO_CLR (0x01UL << 16) +#define TX_FIFO0_CLR (0x01UL << 17) +#define TX_FIFO1_CLR (0x01UL << 18) +#define TX_FIFO2_CLR (0x01UL << 19) + +#define PCM_STAT (I2S_BASE + 2 * 4) +#define RX_INT (0x01UL << 0) +#define TX_INT0 (0x01UL << 1) +#define TX_INT1 (0x01UL << 2) +#define TX_INT2 (0x01UL << 3) +#define RX_OVF (0x01UL << 4) +#define TX_UDF0 (0x01UL << 5) +#define TX_UDF1 (0x01UL << 6) +#define TX_UDF2 (0x01UL << 7) +#define RX_FIFO0_EMPTY (0x01UL << 8) +#define RX_FIFO0_ALMOST_EMPTY (0x01UL << 9) +#define TX_FIFO0_FULL (0x01UL << 10) +#define TX_FIFO0_ALMOST_FULL (0x01UL << 11) +#define TX_FIFO1_FULL (0x01UL << 12) +#define TX_FIFO1_ALMOST_FULL (0x01UL << 13) +#define TX_FIFO2_FULL (0x01UL << 14) +#define TX_FIFO2_ALMOST_FULL (0x01UL << 15) + +#define PCM_DAT0 (I2S_BASE + 3 * 4) + +#define PCM_DAT1 (I2S_BASE + 4 * 4) + +#define PCM_DAT2 (I2S_BASE + 5 * 4) + +#define PCM_CFG2 (I2S_BASE + 6 * 4) + +#define TXFIFO_TXFIFO_MODE 6 +#define TXFIFO_BITSEQ_MODE 4 +#define TXFIFO_DOWN_SMPRATIO 0 + +//#define I2S_SYS_CLK 24576000 +#define I2S_SYS_CLK 26000000 + +/******************************************************************************* +* Function Declarations +*******************************************************************************/ +static UINT32 i2s_ctrl(UINT32 cmd, void *param); +#endif //_I2S_H_ diff --git a/beken_os/beken378/driver/icu/icu.c b/beken_os/beken378/driver/icu/icu.c new file mode 100755 index 0000000..fce984c --- /dev/null +++ b/beken_os/beken378/driver/icu/icu.c @@ -0,0 +1,191 @@ +#include "include.h" +#include "arm_arch.h" + +#include "icu_pub.h" +#include "icu.h" + +#include "drv_model_pub.h" + +static SDD_OPERATIONS icu_op = +{ + icu_ctrl +}; + +/*******************************************************************/ +void icu_init(void) +{ + UINT32 param; + + sddev_register_dev(ICU_DEV_NAME, &icu_op); + + /*pclk select 26m */ + #if (CFG_SOC_NAME == SOC_BK7231) + param = PCLK_POSI; + #else + param = PCLK_POSI_UART1 | PCLK_POSI_UART2 + | PCLK_POSI_SARADC | PCLK_POSI_PWMS | PCLK_POSI_SDIO + | PCLK_POSI_I2C1 | PCLK_POSI_I2C2; + #endif // (CFG_SOC_NAME == SOC_BK7231) + icu_ctrl(CMD_CONF_PCLK_26M, ¶m); + + #if (CFG_SOC_NAME == SOC_BK7231) + param = FIQ_MAILBOX0_BIT | FIQ_MAILBOX1_BIT; + icu_ctrl(CMD_ICU_INT_DISABLE, ¶m); + #endif // (CFG_SOC_NAME == SOC_BK7231) +} + +void icu_exit(void) +{ + sddev_unregister_dev(ICU_DEV_NAME); +} + +UINT32 icu_ctrl(UINT32 cmd, void *param) +{ + UINT32 ret; + UINT32 reg; + GLOBAL_INT_DECLARATION(); + + ret = ICU_SUCCESS; + + GLOBAL_INT_DISABLE(); + switch(cmd) + { + case CMD_CONF_PCLK_26M: + reg = REG_READ(ICU_PERI_CLK_MUX); + #if (CFG_SOC_NAME == SOC_BK7231) + reg |= (1 << (*(UINT32 *)param)); + #else + reg |= (*(UINT32 *)param); + #endif // (CFG_SOC_NAME == SOC_BK7231) + REG_WRITE(ICU_PERI_CLK_MUX, reg); + break; + + + case CMD_CONF_PWM_LPOCLK: + reg = REG_READ(ICU_PWM_CLK_MUX); + reg |= (1 << (*(UINT32 *)param)); + REG_WRITE(ICU_PWM_CLK_MUX, reg); + break; + + case CMD_CONF_PCLK_DCO: + reg = REG_READ(ICU_PERI_CLK_MUX); + #if (CFG_SOC_NAME == SOC_BK7231) + reg &= ~(1 << (*(UINT32 *)param)); + #else + reg &= ~(*(UINT32 *)param); + #endif // (CFG_SOC_NAME == SOC_BK7231) + REG_WRITE(ICU_PERI_CLK_MUX, reg); + break; + + case CMD_CONF_PWM_PCLK: + reg = REG_READ(ICU_PWM_CLK_MUX); + reg &= ~(1 << (*(UINT32 *)param)); + REG_WRITE(ICU_PWM_CLK_MUX, reg); + break; + + case CMD_CLK_PWR_UP: + reg = REG_READ(ICU_PERI_CLK_PWD); + reg &= ~(*(UINT32 *)param); + REG_WRITE(ICU_PERI_CLK_PWD, reg); + break; + + case CMD_CLK_PWR_DOWN: + reg = REG_READ(ICU_PERI_CLK_PWD); + reg |= (*(UINT32 *)param); + REG_WRITE(ICU_PERI_CLK_PWD, reg); + break; + + case CMD_TL410_CLK_PWR_UP: + reg = REG_READ(ICU_TL410_CLK_PWD); + reg &= ~(*(UINT32 *)param); + REG_WRITE(ICU_TL410_CLK_PWD, reg); + break; + + case CMD_TL410_CLK_PWR_DOWN: + reg = REG_READ(ICU_TL410_CLK_PWD); + reg |= (*(UINT32 *)param); + REG_WRITE(ICU_TL410_CLK_PWD, reg); + break; + + case CMD_ICU_CLKGATING_DISABLE: + reg = REG_READ(ICU_PERI_CLK_GATING); + reg |= (*(UINT32 *)param); + REG_WRITE(ICU_PERI_CLK_GATING, reg); + break; + + case CMD_ICU_CLKGATING_ENABLE: + reg = REG_READ(ICU_PERI_CLK_GATING); + reg &= ~(*(UINT32 *)param); + REG_WRITE(ICU_PERI_CLK_GATING, reg); + break; + + case CMD_ICU_INT_DISABLE: + reg = REG_READ(ICU_INTERRUPT_ENABLE); + reg &= ~(*(UINT32 *)param); + REG_WRITE(ICU_INTERRUPT_ENABLE, reg); + break; + + case CMD_ICU_INT_ENABLE: + reg = REG_READ(ICU_INTERRUPT_ENABLE); + reg |= (*(UINT32 *)param); + REG_WRITE(ICU_INTERRUPT_ENABLE, reg); + break; + + case CMD_ICU_GLOBAL_INT_DISABLE: + reg = REG_READ(ICU_GLOBAL_INT_EN); + reg &= ~(*(UINT32 *)param); + REG_WRITE(ICU_GLOBAL_INT_EN, reg); + break; + + case CMD_ICU_GLOBAL_INT_ENABLE: + reg = REG_READ(ICU_GLOBAL_INT_EN); + reg |= (*(UINT32 *)param); + REG_WRITE(ICU_GLOBAL_INT_EN, reg); + break; + + case CMD_GET_INTR_STATUS: + ret = REG_READ(ICU_INT_STATUS); + break; + + case CMD_CLR_INTR_STATUS: + ASSERT(param); + reg = REG_READ(ICU_INT_STATUS); + REG_WRITE(ICU_INT_STATUS, (reg | *(UINT32 *)param)); + break; + + case CMD_GET_INTR_RAW_STATUS: + ret = REG_READ(ICU_INT_RAW_STATUS); + break; + + case CMD_CLR_INTR_RAW_STATUS: + ASSERT(param); + reg = REG_READ(ICU_INT_RAW_STATUS); + REG_WRITE(ICU_INT_RAW_STATUS, (reg | *(UINT32 *)param)); + break; + + case CMD_SET_JTAG_MODE: + ASSERT(param); + if(JTAG_ARM_MODE == (*(UINT32 *)param)) + REG_WRITE(ICU_JTAG_SELECT, JTAG_SEL_WR_ARM); + else if(JTAG_TL410_MODE == (*(UINT32 *)param)) + REG_WRITE(ICU_JTAG_SELECT, JTAG_SEL_WR_TL4); + break; + + case CMD_GET_JTAG_MODE: + ret = REG_READ(ICU_JTAG_SELECT); + break; + + case CMD_ARM_WAKEUP: + reg = (*(UINT32*)param); + REG_WRITE(ICU_ARM_WAKEUP_EN, reg); + break; + + default: + break; + } + GLOBAL_INT_RESTORE(); + + return ret; +} + +// EOF diff --git a/beken_os/beken378/driver/icu/icu.h b/beken_os/beken378/driver/icu/icu.h new file mode 100755 index 0000000..f43c05c --- /dev/null +++ b/beken_os/beken378/driver/icu/icu.h @@ -0,0 +1,295 @@ +#ifndef _ICU_H_ +#define _ICU_H_ + +#define ICU_DEBUG + +#ifdef ICU_DEBUG +#define ICU_PRT os_printf +#define ICU_WARN warning_prf +#define ICU_FATAL fatal_prf +#else +#define ICU_PRT null_prf +#define ICU_WARN null_prf +#define ICU_FATAL null_prf +#endif + +#define ICU_BASE (0x00802000) + +#define ICU_PERI_CLK_MUX (ICU_BASE + 0 * 4) +#define PERI_CLK_26M_XTAL (1) +#define PERI_CLK_DCO (0) +#if (CFG_SOC_NAME == SOC_BK7231) +#define PERI_CLK_MUX_BIT (1 << 0) +#else +#define PERI_CLK_UART1 (1 << 0) +#define PERI_CLK_UART2 (1 << 1) +#define PERI_CLK_I2C1 (1 << 2) +#define PERI_CLK_IRDA (1 << 3) +#define PERI_CLK_I2C2 (1 << 4) +#define PERI_CLK_SARADC (1 << 5) // hardware bug: This two bits reversed +#define PERI_CLK_SPI (1 << 6) +#define PERI_CLK_PWMS (1 << 7) +#define PERI_CLK_SDIO (1 << 8) +#define PERI_CLK_SARADC_AUD (1 << 9) + +#define QSPI_CLK_MUX_POSI (16) +#define QSPI_CLK_MUX_MASK (0x3) +#define QSPI_CLK_MUX_DCO (0) +#define QSPI_CLK_MUX_26M (1) +#define QSPI_CLK_MUX_120M (2) +#if (CFG_SOC_NAME == SOC_BK7221U) +#define DCO_CLK_DIV_POSI (18) +#define DCO_CLK_DIV_MASK (0x3) +#define DCO_CLK_DIV_1 (0) +#define DCO_CLK_DIV_2 (1) +#define DCO_CLK_DIV_4 (2) +#define DCO_CLK_DIV_8 (3) +#endif // (CFG_SOC_NAME == SOC_BK7221U) +#endif // (CFG_SOC_NAME == SOC_BK7231) + +#define ICU_PWM_CLK_MUX (ICU_BASE + 1 * 4) +#define PWM_CLK_MUX_POSI (0) +#define PWM_CLK_MUX_MASK (0x3F) +#define PWM_CLK_LPO (1) +#define PWM_CLK_PCLK (0) + +#define ICU_PERI_CLK_PWD (ICU_BASE + 2 * 4) + +#if (CFG_SOC_NAME != SOC_BK7231) +#define PWD_TIMER_32K_CLK (1 << 21) +#define PWD_TIMER_26M_CLK (1 << 20) +#endif + +#define PWD_FFT_CLK (1 << 19) +#define PWD_USB_CLK (1 << 18) +#define PWD_SDIO_CLK (1 << 17) +#define PWD_TL410_WATCHDOG (1 << 16) +#define PWD_AUDIO_CLK (1 << 15) +#define PWD_PWM5_CLK (1 << 14) +#define PWD_PWM4_CLK (1 << 13) +#define PWD_PWM3_CLK (1 << 12) +#define PWD_PWM2_CLK (1 << 11) +#define PWD_PWM1_CLK (1 << 10) +#define PWD_PWM0_CLK (1 << 9) +#define PWD_ARM_WATCHDOG_CLK (1 << 8) +#define PWD_SARADC_CLK (1 << 7) +#define PWD_SPI_CLK (1 << 6) +#define PWD_I2C2_CLK (1 << 5) +#define PWD_I2S_PCM_CLK (1 << 4) +#define PWD_IRDA_CLK (1 << 3) +#define PWD_I2C1_CLK (1 << 2) +#define PWD_UART2_CLK (1 << 1) +#define PWD_UART1_CLK (1 << 0) + +#define ICU_PERI_CLK_GATING (ICU_BASE + 3 * 4) +#define CLKGATE_DISABLE_MAC_AHB (1 << 16) +#define CLKGATE_DISABLE_FFT_AHB (1 << 15) +#define CLKGATE_DISABLE_USB_AHB (1 << 14) +#define CLKGATE_DISABLE_SDIO_AHB (1 << 13) +#define CLKGATE_DISABLE_SARADC_APB (1 << 12) +#define CLKGATE_DISABLE_AUDIO_APB (1 << 11) +#define CLKGATE_DISABLE_PWM_APB (1 << 10) +#define CLKGATE_DISABLE_WATCHDOG_APB (1 << 9) +#define CLKGATE_DISABLE_GPIO_APB (1 << 8) +#define CLKGATE_DISABLE_SPI_APB (1 << 7) +#define CLKGATE_DISABLE_I2C2_APB (1 << 6) +#define CLKGATE_DISABLE_I2S_PCM_APB (1 << 5) +#define CLKGATE_DISABLE_IRDA_APB (1 << 4) +#define CLKGATE_DISABLE_I2C1_APB (1 << 3) +#define CLKGATE_DISABLE_UART2_APB (1 << 2) +#define CLKGATE_DISABLE_UART1_APB (1 << 1) +#define CLKGATE_DISABLE_ICU_APB (1 << 0) + +#define ICU_TL410_CLK_PWD (ICU_BASE + 4 * 4) +#define TL410_CLK_PWD_BIT (1 << 0) +#define BLE_CLK_PWD_BIT (1 << 1) + +#define ICU_CLK26M_DIV_FACTOR (ICU_BASE + 5 * 4) +#define CLK26M_DIV_FACTOR_POSI (0) +#define CLK26M_DIV_FACTOR_MASK (0x3) +#define CLK26M_DIVISION_1 (0x00) +#define CLK26M_DIVISION_2 (0x01) +#define CLK26M_DIVISION_4 (0x02) +#define CLK26M_DIVISION_8 (0x03) + +#define ICU_JTAG_SELECT (ICU_BASE + 6 * 4) +#define JTAG_SEL_WR_ARM (0x7111E968) +#define JTAG_SEL_WR_TL4 (0x7111E410) +#define JTAG_SEL_RD_ARM (0x00000000) +#define JTAG_SEL_RD_TL4 (0x00000001) + +#define ICU_INTERRUPT_ENABLE (ICU_BASE + 16 * 4) +#define FIQ_DPLL_UNLOCK_EN_BIT (1 << 28) +#define FIQ_SPI_DMA_EN_BIT (1 << 27) +#define FIQ_MAC_WAKEUP_EN_BIT (1 << 26) +#if (CFG_SOC_NAME == SOC_BK7231) +#define FIQ_MAILBOX1_EN_BIT (1 << 25) +#define FIQ_MAILBOX0_EN_BIT (1 << 24) +#else +#define FIQ_SECURITY_EN_BIT (1 << 25) +#define FIQ_USB_PLUG_INOUT_EN_BIT (1 << 24) +#endif // (CFG_SOC_NAME == SOC_BK7231) +#define FIQ_SDIO_DMA_EN_BIT (1 << 23) +#define FIQ_MAC_GENERAL_EN_BIT (1 << 22) +#define FIQ_MAC_PROT_TRIGGER_EN_BIT (1 << 21) +#define FIQ_MAC_TX_TRIGGER_EN_BIT (1 << 20) +#define FIQ_MAC_RX_TRIGGER_EN_BIT (1 << 19) +#define FIQ_MAC_TX_RX_MISC_EN_BIT (1 << 18) +#define FIQ_MAC_TX_RX_TIMER_EN_BIT (1 << 17) +#define FIQ_MODEM_EN_BIT (1 << 16) +#define IRQ_GDMA_EN_BIT (1 << 15) +#define IRQ_FFT_EN_BIT (1 << 14) +#define IRQ_USB_EN_BIT (1 << 13) +#define IRQ_SDIO_EN_BIT (1 << 12) +#define IRQ_SARADC_EN_BIT (1 << 11) +#define IRQ_AUDIO_EN_BIT (1 << 10) +#define IRQ_PWM_EN_BIT (1 << 9) +#define IRQ_TL410_WATCHDOG_EN_BIT (1 << 8) +#define IRQ_GPIO_EN_BIT (1 << 7) +#define IRQ_SPI_EN_BIT (1 << 6) +#define IRQ_I2C2_EN_BIT (1 << 5) +#define IRQ_I2S_PCM_EN_BIT (1 << 4) +#define IRQ_IRDA_EN_BIT (1 << 3) +#define IRQ_I2C1_EN_BIT (1 << 2) +#define IRQ_UART2_EN_BIT (1 << 1) +#define IRQ_UART1_EN_BIT (1 << 0) + +#define ICU_GLOBAL_INT_EN (ICU_BASE + 17 * 4) +#define GINTR_FIQ_EN (1 << 1) +#define GINTR_IRQ_EN (1 << 0) + +#define ICU_INT_RAW_STATUS (ICU_BASE + 18 * 4) +#define ICU_INT_STATUS (ICU_BASE + 19 * 4) +#if (CFG_SOC_NAME == SOC_BK7231) +#define FIQ_MAILBOX1_STATUS_BIT (1 << 25) +#define FIQ_MAILBOX0_STATUS_BIT (1 << 24) +#else +#define FIQ_SECURITY_STATUS_BIT (1 << 25) +#define FIQ_USB_PLUG_INOUT_STATUS_BIT (1 << 24) +#endif // (CFG_SOC_NAME == SOC_BK7231) +#define FIQ_SDIO_DMA_STATUS_BIT (1 << 23) +#define FIQ_MAC_GENERAL_STATUS_BIT (1 << 22) +#define FIQ_MAC_PROT_TRIGGER_STATUS_BIT (1 << 21) +#define FIQ_MAC_TX_TRIGGER_STATUS_BIT (1 << 20) +#define FIQ_MAC_RX_TRIGGER_STATUS_BIT (1 << 19) +#define FIQ_MAC_TX_RX_MISC_STATUS_BIT (1 << 18) +#define FIQ_MAC_TX_RX_TIMER_STATUS_BIT (1 << 17) +#define FIQ_MODEM_STATUS_BIT (1 << 16) +#define IRQ_RESERVED_STATUS_BIT (1 << 15) +#define IRQ_FFT_STATUS_BIT (1 << 14) +#define IRQ_USB_STATUS_BIT (1 << 13) +#define IRQ_SDIO_STATUS_BIT (1 << 12) +#define IRQ_SARADC_STATUS_BIT (1 << 11) +#define IRQ_AUDIO_STATUS_BIT (1 << 10) +#define IRQ_PWM_STATUS_BIT (1 << 9) +#define IRQ_TL410_WATCHDOG_STATUS_BIT (1 << 8) +#define IRQ_GPIO_STATUS_BIT (1 << 7) +#define IRQ_SPI_STATUS_BIT (1 << 6) +#define IRQ_I2C2_STATUS_BIT (1 << 5) +#define IRQ_I2S_PCM_STATUS_BIT (1 << 4) +#define IRQ_IRDA_STATUS_BIT (1 << 3) +#define IRQ_I2C1_STATUS_BIT (1 << 2) +#define IRQ_UART2_STATUS_BIT (1 << 1) +#define IRQ_UART1_STATUS_BIT (1 << 0) + +#define ICU_ARM_WAKEUP_EN (ICU_BASE + 20 * 4) +#define MAC_ARM_WAKEUP_EN_BIT (1 << 26) +#define MAILBOX1_ARM_WAKEUP_EN_BIT (1 << 25) +#define MAILBOX0_ARM_WAKEUP_EN_BIT (1 << 24) +#define SDIO_DMA_ARM_WAKEUP_EN_BIT (1 << 23) +#define MAC_GENERAL_ARM_WAKEUP_EN_BIT (1 << 22) +#define MAC_PROT_TRIGGER_ARM_WAKEUP_EN_BIT (1 << 21) +#define MAC_TX_TRIGGER_ARM_WAKEUP_EN_BIT (1 << 20) +#define MAC_RX_TRIGGER_ARM_WAKEUP_EN_BIT (1 << 19) +#define MAC_TX_RX_MISC_ARM_WAKEUP_EN_BIT (1 << 18) +#define MAC_TX_RX_TIMER_ARM_WAKEUP_EN_BIT (1 << 17) +#define MODEM_ARM_WAKEUP_EN_BIT (1 << 16) +#define RESERVED_ARM_WAKEUP_EN_BIT (1 << 15) +#define FFT_ARM_WAKEUP_EN_BIT (1 << 14) +#define USB_ARM_WAKEUP_EN_BIT (1 << 13) +#define SDIO_ARM_WAKEUP_EN_BIT (1 << 12) +#define SARADC_ARM_WAKEUP_EN_BIT (1 << 11) +#define AUDIO_ARM_WAKEUP_EN_BIT (1 << 10) +#define PWM_ARM_WAKEUP_EN_BIT (1 << 9) +#if (CFG_SOC_NAME == SOC_BK7231) +#define TL410_WATCHDOG_ARM_WAKEUP_EN_BIT (1 << 8) +#else +#define TIMER_ARM_WAKEUP_EN_BIT (1 << 8) +#endif +#define GPIO_ARM_WAKEUP_EN_BIT (1 << 7) +#define SPI_ARM_WAKEUP_EN_BIT (1 << 6) +#define I2C2_ARM_WAKEUP_EN_BIT (1 << 5) +#define I2S_PCM_ARM_WAKEUP_EN_BIT (1 << 4) +#define IRDA_ARM_WAKEUP_EN_BIT (1 << 3) +#define I2C1_ARM_WAKEUP_EN_BIT (1 << 2) +#define UART2_ARM_WAKEUP_EN_BIT (1 << 1) +#define UART1_ARM_WAKEUP_EN_BIT (1 << 0) + +#define ICU_TL4_INT_EN (ICU_BASE + 32 * 4) +#define TL4_INT_EN_MAILBOX1_BIT (1 << 17) +#define TL4_INT_EN_MAILBOX0_BIT (1 << 16) +#define TL4_INT_EN_RESERVE1_BIT (1 << 15) +#define TL4_INT_EN_FFT_BIT (1 << 14) +#define TL4_INT_EN_USB_BIT (1 << 13) +#define TL4_INT_EN_SDIO_BIT (1 << 12) +#define TL4_INT_EN_SARADC_BIT (1 << 11) +#define TL4_INT_EN_AUDIO_BIT (1 << 10) +#define TL4_INT_EN_PWM_BIT (1 << 9) +#define TL4_INT_EN_RESERVE0_BIT (1 << 8) +#define TL4_INT_EN_GPIO_BIT (1 << 7) +#define TL4_INT_EN_SPI_BIT (1 << 6) +#define TL4_INT_EN_I2C2_BIT (1 << 5) +#define TL4_INT_EN_I2S_PCM_BIT (1 << 4) +#define TL4_INT_EN_IRDA_BIT (1 << 3) +#define TL4_INT_EN_I2C1_BIT (1 << 2) +#define TL4_INT_EN_UART2_BIT (1 << 1) +#define TL4_INT_EN_UART1_BIT (1 << 0) + +#define ICU_TL4_INT_RAW_STATUS (ICU_BASE + 33 * 4) +#define ICU_TL4_INT_STATUS (ICU_BASE + 34 * 4) +#define TL4_MAILBOX1_STATUS_BIT (1 << 17) +#define TL4_MAILBOX0_STATUS_BIT (1 << 16) +#define TL4_RESERVE1_STATUS_BIT (1 << 15) +#define TL4_FFT_STATUS_BIT (1 << 14) +#define TL4_USB_STATUS_BIT (1 << 13) +#define TL4_SDIO_STATUS_BIT (1 << 12) +#define TL4_SARADC_STATUS_BIT (1 << 11) +#define TL4_AUDIO_STATUS_BIT (1 << 10) +#define TL4_PWM_STATUS_BIT (1 << 9) +#define TL4_RESERVE0_STATUS_BIT (1 << 8) +#define TL4_GPIO_STATUS_BIT (1 << 7) +#define TL4_SPI_STATUS_BIT (1 << 6) +#define TL4_I2C2_STATUS_BIT (1 << 5) +#define TL4_I2S_PCM_STATUS_BIT (1 << 4) +#define TL4_IRDA_STATUS_BIT (1 << 3) +#define TL4_I2C1_STATUS_BIT (1 << 2) +#define TL4_UART2_STATUS_BIT (1 << 1) +#define TL4_UART1_STATUS_BIT (1 << 0) + +#define ICU_TL4_WAKEUP_EN (ICU_BASE + 35 * 4) +#define TL4_MAILBOX1_WAKEUP_EN_BIT (1 << 17) +#define TL4_MAILBOX0_WAKEUP_EN_BIT (1 << 16) +#define TL4_RESERVE1_WAKEUP_EN_BIT (1 << 15) +#define TL4_FFT_WAKEUP_EN_BIT (1 << 14) +#define TL4_USB_WAKEUP_EN_BIT (1 << 13) +#define TL4_SDIO_WAKEUP_EN_BIT (1 << 12) +#define TL4_SARADC_WAKEUP_EN_BIT (1 << 11) +#define TL4_AUDIO_WAKEUP_EN_BIT (1 << 10) +#define TL4_PWM_WAKEUP_EN_BIT (1 << 9) +#define TL4_RESERVE0_WAKEUP_EN_BIT (1 << 8) +#define TL4_GPIO_WAKEUP_EN_BIT (1 << 7) +#define TL4_SPI_WAKEUP_EN_BIT (1 << 6) +#define TL4_I2C2_WAKEUP_EN_BIT (1 << 5) +#define TL4_I2S_PCM_WAKEUP_EN_BIT (1 << 4) +#define TL4_IRDA_WAKEUP_EN_BIT (1 << 3) +#define TL4_I2C1_WAKEUP_EN_BIT (1 << 2) +#define TL4_UART2_WAKEUP_EN_BIT (1 << 1) +#define TL4_UART1_WAKEUP_EN_BIT (1 << 0) + + +/******************************************************************************* +* Function Declarations +*******************************************************************************/ + +#endif //_ICU_H_ + diff --git a/beken_os/beken378/driver/include/arm_arch.h b/beken_os/beken378/driver/include/arm_arch.h new file mode 100755 index 0000000..4adffb2 --- /dev/null +++ b/beken_os/beken378/driver/include/arm_arch.h @@ -0,0 +1,58 @@ +#ifndef _ARM_ARCH_H_ +#define _ARM_ARCH_H_ + +/** + * RD an 8-bit register from the core + * @param _pBase core base address in memory + * @param _offset offset into the core's register space + * @return 8-bit datum + */ +#define REG_RD8(_pBase, _offset) *((volatile UINT8 *)(_pBase + _offset)) + +/** + * RD a 16-bit register from the core + * @param _pBase core base address in memory + * @param _offset offset into the core's register space + * @return 16-bit datum + */ +#define REG_RD16(_pBase, _offset) *((volatile UINT16 *)(_pBase + _offset)) + +/** + * RD a 32-bit register from the core + * @param _pBase core base address in memory + * @param _offset offset into the core's register space + * @return 32-bit datum + */ +#define REG_RD32(_pBase, _offset) *((volatile UINT32 *)(_pBase + _offset)) + +/** + * WR an 8-bit core register + * @param _pBase core base address in memory + * @param _offset offset into the core's register space + * @param _data 8-bit datum + */ +#define REG_WR8(_pBase, _offset, _data) \ + (*((volatile UINT8 *)(_pBase + _offset)) = _data) + +/** + * WR a 16-bit core register + * @param _pBase core base address in memory + * @param _offset offset into the core's register space + * @param _data 16-bit datum + */ +#define REG_WR16(_pBase, _offset, _data) \ + (*((volatile UINT16 *)(_pBase + _offset)) = _data) + +/** + * WR a 32-bit core register + * @param _pBase core base address in memory + * @param _offset offset into the core's register space + * @param _data 32-bit datum + */ +#define REG_WR32(_pBase, _offset, _data) \ + (*((volatile UINT32 *)(_pBase + _offset)) = _data) + +#define REG_READ(addr) (*((volatile UINT32 *)(addr))) +#define REG_WRITE(addr, _data) (*((volatile UINT32 *)(addr)) = (_data)) + +#endif diff --git a/beken_os/beken378/driver/include/bk_timer_pub.h b/beken_os/beken378/driver/include/bk_timer_pub.h new file mode 100755 index 0000000..87ab039 --- /dev/null +++ b/beken_os/beken378/driver/include/bk_timer_pub.h @@ -0,0 +1,48 @@ +#ifndef _BK_TIMER_PUB_H_ +#define _BK_TIMER_PUB_H_ + +#include "typedef.h" + +#define TIMER_DEV_NAME "bk_timer" + +#define BK_TIMER_FAILURE (1) +#define BK_TIMER_SUCCESS (0) + +#define TIMER_CMD_MAGIC (0xe340000) +enum +{ + CMD_TIMER_UNIT_ENABLE = TIMER_CMD_MAGIC + 1, + CMD_TIMER_UNIT_DISABLE, + CMD_TIMER_INIT_PARAM, + CMD_TIMER_INIT_PARAM_US, + CMD_TIMER_READ_CNT +}; + +enum +{ + BKTIMER0 = 0, + BKTIMER1, + BKTIMER2, + BKTIMER3, + BKTIMER4, + BKTIMER5, + BKTIMER_COUNT +}; + +typedef void (*TFUNC)(UINT8); + +typedef struct +{ + UINT8 channel; + UINT8 div; + UINT32 period; + TFUNC t_Int_Handler; +} timer_param_t; + +void bk_timer_init(void); +void bk_timer_exit(void); +void bk_timer_isr(void); + + +#endif //_TIMER_PUB_H_ + diff --git a/beken_os/beken378/driver/include/ble_api.h b/beken_os/beken378/driver/include/ble_api.h new file mode 100755 index 0000000..e6e1030 --- /dev/null +++ b/beken_os/beken378/driver/include/ble_api.h @@ -0,0 +1,392 @@ +#ifndef _BLE_API_H_ +#define _BLE_API_H_ + +#include "ble_pub.h" +#define ABIT(n) (1 << n) + +#define BK_PERM_SET(access, right) \ + (((BK_PERM_RIGHT_ ## right) << (access ## _POS)) & (access ## _MASK)) + +#define BK_PERM_GET(perm, access)\ + (((perm) & (access ## _MASK)) >> (access ## _POS)) + + +typedef enum +{ + /// Stop notification/indication + PRF_STOP_NTFIND = 0x0000, + /// Start notification + PRF_START_NTF, + /// Start indication + PRF_START_IND, +} prf_conf; + + +/** + * 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + * +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + * |EXT | WS | I | N | WR | WC | RD | B | NP | IP | WP | RP | + * +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + * + * Bit [0-1] : Read Permission (0 = NO_AUTH, 1 = UNAUTH, 2 = AUTH, 3 = SEC_CON) + * Bit [2-3] : Write Permission (0 = NO_AUTH, 1 = UNAUTH, 2 = AUTH, 3 = SEC_CON) + * Bit [4-5] : Indication Permission (0 = NO_AUTH, 1 = UNAUTH, 2 = AUTH, 3 = SEC_CON) + * Bit [6-7] : Notification Permission (0 = NO_AUTH, 1 = UNAUTH, 2 = AUTH, 3 = SEC_CON) + * + * Bit [8] : Broadcast permission + * Bit [9] : Read Command accepted + * Bit [10] : Write Command accepted + * Bit [11] : Write Request accepted + * Bit [12] : Send Notification + * Bit [13] : Send Indication + * Bit [14] : Write Signed accepted + * Bit [15] : Extended properties present + */ + +typedef enum +{ + /// Read Permission Mask + RP_MASK = 0x0003, + RP_POS = 0, + /// Write Permission Mask + WP_MASK = 0x000C, + WP_POS = 2, + /// Indication Access Mask + IP_MASK = 0x0030, + IP_POS = 4, + /// Notification Access Mask + NP_MASK = 0x00C0, + NP_POS = 6, + /// Broadcast descriptor present + BROADCAST_MASK = 0x0100, + BROADCAST_POS = 8, + /// Read Access Mask + RD_MASK = 0x0200, + RD_POS = 9, + /// Write Command Enabled attribute Mask + WRITE_COMMAND_MASK = 0x0400, + WRITE_COMMAND_POS = 10, + /// Write Request Enabled attribute Mask + WRITE_REQ_MASK = 0x0800, + WRITE_REQ_POS = 11, + /// Notification Access Mask + NTF_MASK = 0x1000, + NTF_POS = 12, + /// Indication Access Mask + IND_MASK = 0x2000, + IND_POS = 13, + /// Write Signed Enabled attribute Mask + WRITE_SIGNED_MASK = 0x4000, + WRITE_SIGNED_POS = 14, + /// Extended properties descriptor present + EXT_MASK = 0x8000, + EXT_POS = 15, +} bk_perm_mask; + +/** + * Attribute Extended permissions + * + * Extended Value permission bit field + * + * 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 + * +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + * | RI |UUID_LEN |EKS | Reserved | + * +----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+----+ + * + * Bit [0-11] : Reserved + * Bit [12] : Encryption key Size must be 16 bytes + * Bit [13-14]: UUID Length (0 = 16 bits, 1 = 32 bits, 2 = 128 bits, 3 = RFU) + * Bit [15] : Trigger Read Indication (0 = Value present in Database, 1 = Value not present in Database) + */ +typedef enum +{ + /// Check Encryption key size Mask + EKS_MASK = 0x1000, + EKS_POS = 12, + /// UUID Length + UUID_LEN_MASK = 0x6000, + UUID_LEN_POS = 13, + /// Read trigger Indication + RI_MASK = 0x8000, + RI_POS = 15, +}bk_ext_perm_mask; + +typedef enum +{ + /// Task that manage service is multi-instantiated + SVC_MI_MASK = 0x01, + SVC_MI_POS = 0, + /// Check Encryption key size for service Access + SVC_EKS_MASK = 0x02, + SVC_EKS_POS = 1, + /// Service Permission authentication + SVC_AUTH_MASK = 0x0C, + SVC_AUTH_POS = 2, + /// Disable the service + SVC_DIS_MASK = 0x10, + SVC_DIS_POS = 4, + /// Service UUID Length + SVC_UUID_LEN_MASK = 0x60, + SVC_UUID_LEN_POS = 5, + /// Service type Secondary + SVC_SECONDARY_MASK = 0x80, + SVC_SECONDARY_POS = 7, +}bk_svc_perm_mask; + +/// Attribute & Service access mode +enum +{ + /// Disable access + BK_PERM_RIGHT_DISABLE = 0, + /// Enable access + BK_PERM_RIGHT_ENABLE = 1, +}; + +/// Attribute & Service access rights +enum +{ + /// No Authentication + BK_PERM_RIGHT_NO_AUTH = 0, + /// Access Requires Unauthenticated link + BK_PERM_RIGHT_UNAUTH = 1, + /// Access Requires Authenticated link + BK_PERM_RIGHT_AUTH = 2, + /// Access Requires Secure Connection link + BK_PERM_RIGHT_SEC_CON = 3, +}; + +/// Attribute & Service UUID Length +enum +{ + /// 16 bits UUID + BK_PERM_RIGHT_UUID_16 = 0, + /// 32 bits UUID + BK_PERM_RIGHT_UUID_32 = 1, + /// 128 bits UUID + BK_PERM_RIGHT_UUID_128 = 2, + /// Invalid + BK_PERM_RIGHT_UUID_RFU = 3, +}; + +typedef enum +{ + ERR_SUCCESS = 0, + ERR_STACK_FAIL, + ERR_MEM_FAIL, + ERR_INVALID_ADV_DATA, + ERR_ADV_FAIL, + ERR_STOP_ADV_FAIL, + ERR_GATT_INDICATE_FAIL, + ERR_GATT_NOTIFY_FAIL, + ERR_SCAN_FAIL, + ERR_STOP_SCAN_FAIL, + ERR_CONN_FAIL, + ERR_STOP_CONN_FAIL, + ERR_DISCONN_FAIL, + ERR_READ_FAIL, + ERR_WRITE_FAIL, + ERR_REQ_RF, + ERR_PROFILE, + ERR_CREATE_DB, + ERR_CMD_NOT_SUPPORT, + /* Add more BLE error code hereafter */ +} ble_err_t; + +typedef enum +{ + ADV_NAME_SHORT = 0x8, + ADV_NAME_FULL +} adv_name_type_t; + +typedef enum +{ + AD_LIMITED = ABIT(0), /* Limited Discoverable */ + AD_GENERAL = ABIT(1), /* General Discoverable */ + AD_NO_BREDR = ABIT(2) /* BR/EDR not supported */ +} adv_flag_t; + +typedef struct +{ + uint8_t advData[MAX_ADV_DATA_LEN]; + uint8_t advDataLen; + uint8_t respData[MAX_ADV_DATA_LEN]; + uint8_t respDataLen; + uint8_t channel_map; + uint16_t interval_min; + uint16_t interval_max; + /* Subject to add more hereafter in the future */ +} adv_info_t; + +typedef struct +{ + uint8_t filter_en; + uint8_t channel_map; + uint16_t interval; + uint16_t window; +} scan_info_t; + +typedef enum +{ + BLE_STACK_OK = 0x0, + BLE_STACK_FAIL, + BLE_CONNECT, + BLE_DISCONNECT, + BLE_MTU_CHANGE, + BLE_CFG_NOTIFY, + BLE_CFG_INDICATE, + BLE_TX_DONE, + BLE_GEN_DH_KEY, + BLE_GET_KEY, + BLE_ATT_INFO_REQ, + BLE_CREATE_DB_OK, + BLE_CREATE_DB_FAIL, + + BLE_COMMON_EVT = 0x10, + BLE_ACTIVITY_CREATED_IND, + BLE_ACTIVITY_STOPPED_IND, + + BLE_UPDATA_ADV_DATA_IND, ////update adv data ind + BLE_UPDATA_SCAN_RSP_IND, ////update adv scan response data ind + + BLE_EVENT_MAX, +} ble_event_t; + +typedef enum +{ + /// Advertising activity + BLE_ACTV_TYPE_ADV = 0, + /// Scanning activity + BLE_ACTV_TYPE_SCAN, + /// Initiating activity + BLE_ACTV_TYPE_INIT, + /// Periodic synchronization activity + BLE_ACTV_TYPE_PER_SYNC, +}ble_actv_type; + +struct ble_activity_created_ind +{ + /// Activity identifier + uint8_t actv_idx; + /// Activity type + ble_actv_type actv_type; + /// Selected TX power for advertising activity + int8_t tx_pwr; +}; + +struct ble_disconnect_ind +{ + /// Connection handle + uint16_t conhdl; + /// Reason of disconnection + uint8_t reason; +}; + + +typedef struct +{ + uint16_t prf_id; + uint8_t att_idx; + uint16_t length; + uint8_t status; +} att_info_req_t; + +typedef struct +{ + uint16_t prf_id; + uint8_t att_idx; + uint8_t *value; + uint16_t len; +} write_req_t; + +typedef struct +{ + uint16_t prf_id; + uint8_t att_idx; + uint8_t *value; + uint16_t size; +} read_req_t; + +typedef struct +{ + uint8_t evt_type; + uint8_t adv_addr_type; + uint8_t adv_addr[6]; + uint8_t data_len; + uint8_t *data; + uint8_t rssi; +} recv_adv_t; + +struct ble_get_key_ind +{ + uint8_t *pri_key; + uint8_t pri_len; + /// X coordinate + uint8_t *pub_key_x; + uint8_t pub_x_len; + /// Y coordinate + uint8_t *pub_key_y; + uint8_t pub_y_len; +}; + +struct ble_gen_dh_key_ind +{ + /// Result (32 bytes) + uint8_t *result; + uint8_t len; +}; + +typedef struct +{ + /// 16 bits UUID LSB First + uint8_t uuid[16]; + /// Attribute Permissions (@see enum attm_perm_mask) + uint16_t perm; + /// Attribute Extended Permissions (@see enum attm_value_perm_mask) + uint16_t ext_perm; + /// Attribute Max Size + /// note: for characteristic declaration contains handle offset + /// note: for included service, contains target service handle + uint16_t max_size; +}bk_attm_desc_t; + +struct bk_ble_db_cfg +{ + uint16_t prf_task_id; + ///Service uuid + uint8_t uuid[16]; + ///Number of db + uint8_t att_db_nb; + ///Start handler, 0 means autoalloc + uint16_t start_hdl; + ///Attribute database + bk_attm_desc_t* att_db; + ///Service config + uint8_t svc_perm; +}; + +typedef void (*ble_event_cb_t)(ble_event_t event, void *param); +typedef void (*ble_recv_adv_cb_t)(recv_adv_t *recv_adv); +typedef uint8_t (*bk_ble_read_cb_t)(read_req_t *read_req); +typedef void (*bk_ble_write_cb_t)(write_req_t *write_req); + +extern ble_event_cb_t ble_event_cb; +extern ble_recv_adv_cb_t ble_recv_adv_cb; +extern bk_ble_read_cb_t bk_ble_read_cb; +extern bk_ble_write_cb_t bk_ble_write_cb; +extern adv_info_t adv_info; +extern scan_info_t scan_info; + +void ble_activate(char *ble_name); +void ble_set_write_cb(bk_ble_write_cb_t func); +void ble_set_event_cb(ble_event_cb_t func); +void ble_set_read_cb(bk_ble_read_cb_t func); +void ble_set_recv_adv_cb(ble_recv_adv_cb_t func); +ble_err_t bk_ble_create_db (struct bk_ble_db_cfg* ble_db_cfg); +ble_err_t bk_ble_send_ntf_value(uint32_t len, uint8_t *buf, uint16_t prf_id, uint16_t att_idx); +ble_err_t bk_ble_send_ind_value(uint32_t len, uint8_t *buf, uint16_t prf_id, uint16_t att_idx); + +extern void ble_event_cb_handler(ble_event_t event, void *param); +extern int ble_read_cb_handler(read_req_t *read_req); + +extern void appm_update_adv_state(char start); +#endif diff --git a/beken_os/beken378/driver/include/ble_pub.h b/beken_os/beken378/driver/include/ble_pub.h new file mode 100755 index 0000000..fd1b69b --- /dev/null +++ b/beken_os/beken378/driver/include/ble_pub.h @@ -0,0 +1,74 @@ +#ifndef _BLE_PUB_H_ +#define _BLE_PUB_H_ + +#include "rtos_pub.h" +#include "ble_rf_port.h" + +#define BLE_DEV_NAME "ble" + +#define BLE_CMD_MAGIC (0xe2a0000) + +#define MAX_ADV_DATA_LEN (0x1F) + +enum +{ + CMD_BLE_REG_INIT = BLE_CMD_MAGIC + 1, + CMD_BLE_REG_DEINIT, + CMD_BLE_SET_CHANNEL, + CMD_BLE_AUTO_CHANNEL_ENABLE, + CMD_BLE_AUTO_CHANNEL_DISABLE, + CMD_BLE_AUTO_SYNCWD_ENABLE, + CMD_BLE_AUTO_SYNCWD_DISABLE, + CMD_BLE_SET_PN9_TRX, + CMD_BLE_SET_GFSK_SYNCWD, + CMD_BLE_HOLD_PN9_ESTIMATE, + CMD_BLE_STOP_COUNTING, + CMD_BLE_START_COUNTING, + CMD_BLE_START_TX, + CMD_BLE_STOP_TX, +}; + +enum +{ + PN9_RX = 0, + PN9_TX +}; + +struct ble_session_env +{ + unsigned char ble_active; + unsigned ble_dut_flag; + uint32_t ble_sleep_enable; + uint32_t system_sleep_flag; + uint8_t ble_first_sleep; + uint8_t ble_deep_sleep; + uint8_t ble_init_over; +}; + +extern void set_ble_active_status(char active); +extern int get_ble_active_status(void); +extern void set_ble_dut_flag_status(char ble_dut_flag); +extern uint8 is_rf_switch_to_ble(void); +extern uint32_t rwip_get_current_time(void); +extern uint32_t rwip_get_next_target_time(void); +extern void ble_init(void); +extern void ble_exit(void); +extern void ble_dut_start(void); +extern UINT8 ble_is_start(void); +extern UINT8* ble_get_mac_addr(void); +extern UINT8* ble_get_name(void); +extern uint8_t if_ble_sleep(void); +extern void rf_wifi_used_clr(void); +extern void rf_wifi_used_set(void); +extern UINT32 if_rf_wifi_used(void ); +extern void rf_not_share_for_ble(void); +extern void rf_can_share_for_ble(void); + +#if CFG_USE_BLE_PS +extern void bk_ble_sleep_check(void); +#endif + +extern struct ble_session_env ble_session_ctx; +#endif /* _BLE_PUB_H_ */ +// eof + diff --git a/beken_os/beken378/driver/include/driver_codec_es8374_pub.h b/beken_os/beken378/driver/include/driver_codec_es8374_pub.h new file mode 100755 index 0000000..f2a19f8 --- /dev/null +++ b/beken_os/beken378/driver/include/driver_codec_es8374_pub.h @@ -0,0 +1,9 @@ +#ifndef _DRIVER_CODEC_ES8374_PUB_H_ +#define _DRIVER_CODEC_ES8374_PUB_H_ + +extern void es8374_codec_init(void); +extern void es8374_codec_configure(unsigned int fs, unsigned char datawidth); +extern void es8374_codec_close(void); +extern void es8374_codec_volume_control(unsigned char volume); +extern void es8374_codec_mute_control(BOOL enable); +#endif diff --git a/beken_os/beken378/driver/include/driver_pub.h b/beken_os/beken378/driver/include/driver_pub.h new file mode 100755 index 0000000..3c6368f --- /dev/null +++ b/beken_os/beken378/driver/include/driver_pub.h @@ -0,0 +1,8 @@ +#ifndef _DRIVER_PUB_H_ +#define _DRIVER_PUB_H_ + +extern UINT32 driver_init(void); + +#endif // _DRIVER_PUB_H_ +// eof + diff --git a/beken_os/beken378/driver/include/drv_model_pub.h b/beken_os/beken378/driver/include/drv_model_pub.h new file mode 100755 index 0000000..a90d78b --- /dev/null +++ b/beken_os/beken378/driver/include/drv_model_pub.h @@ -0,0 +1,55 @@ +#ifndef _DRV_MODEL_PUB_H_ +#define _DRV_MODEL_PUB_H_ + +#include "include.h" + +#define DRV_FAILURE ((UINT32)-5) +#define DRV_SUCCESS (0) + +#define DD_HANDLE_MAGIC_WORD (0xA5A50000) +#define DD_HANDLE_MAGIC_MASK (0xFFFF0000) +#define DD_HANDLE_ID_MASK (0x0000FFFF) + +#define DD_HANDLE_UNVALID ((UINT32)-1) +#define DD_ID_UNVALID ((UINT32)-1) + +typedef UINT32 DD_HANDLE; + +typedef struct _dd_operations_ +{ + UINT32 (*open) (UINT32 op_flag); + UINT32 (*close) (void); + UINT32 (*read) (char *user_buf, UINT32 count, UINT32 op_flag); + UINT32 (*write) (char *user_buf, UINT32 count, UINT32 op_flag); + UINT32 (*control) (UINT32 cmd, void *parm); +} DD_OPERATIONS; + +typedef struct _sdd_operations_ +{ + UINT32 (*control) (UINT32 cmd, void *parm); +} SDD_OPERATIONS; + +typedef enum _DD_OPEN_METHOD_ +{ + DD_OPEN_METHOD_ONE_TIME = 0, // open one time only + DD_OPEN_METHOD_MUTI_TIME // open multi times +} DD_OPEN_METHOD; + +/******************************************************************************* +* Function Declarations +*******************************************************************************/ +extern UINT32 drv_model_init(void); +extern UINT32 drv_model_uninit(void); +extern DD_HANDLE ddev_open(char *dev_name, UINT32 *status, UINT32 op_flag); +extern UINT32 ddev_close(DD_HANDLE handle); +extern UINT32 ddev_read(DD_HANDLE handle, char *user_buf , UINT32 count, UINT32 op_flag); +extern UINT32 ddev_write(DD_HANDLE handle, char *user_buf , UINT32 count, UINT32 op_flag); +extern UINT32 ddev_control(DD_HANDLE handle, UINT32 cmd, VOID *param); +extern UINT32 sddev_control(char *dev_name, UINT32 cmd, VOID *param); +extern UINT32 ddev_register_dev(char *dev_name, DD_OPERATIONS *optr); +extern UINT32 sddev_register_dev(char *dev_name, SDD_OPERATIONS *optr); +extern UINT32 ddev_unregister_dev(char *dev_name); +extern UINT32 sddev_unregister_dev(char *dev_name); + +#endif //_DRV_MODEL_PUB_H_ + diff --git a/beken_os/beken378/driver/include/fft_pub.h b/beken_os/beken378/driver/include/fft_pub.h new file mode 100755 index 0000000..b9bdac1 --- /dev/null +++ b/beken_os/beken378/driver/include/fft_pub.h @@ -0,0 +1,47 @@ +#ifndef _FFT_PUB_H_ +#define _FFT_PUB_H_ + +#define FFT_FAILURE (1) +#define FFT_SUCCESS (0) + +#define FFT_DEV_NAME "fft" + +#define FFT_CMD_MAGIC (0xe260000) +enum +{ + CMD_FFT_BUSY = FFT_CMD_MAGIC + 1, + CMD_FFT_ENABLE, + CMD_FIR_SIGNLE_ENABLE +}; + +enum +{ + FFT_MODE_FFT, + FFT_MODE_IFFT +}; + +typedef struct +{ + int mode; + INT16 *inbuf; + INT16 *outbuf; + UINT16 size; +} input_fft_t; + +typedef struct +{ + UINT8 fir_len; + UINT8 fir_cwidth; + UINT8 fir_dwidth; + INT16 *coef; + INT16 *input; + INT32 *mac; +} input_fir_t; + +/******************************************************************************* +* Function Declarations +*******************************************************************************/ +void fft_init(void); +void fft_exit(void); +void fft_isr(void); +#endif //_FFT_PUB_H_ diff --git a/beken_os/beken378/driver/include/flash_pub.h b/beken_os/beken378/driver/include/flash_pub.h new file mode 100755 index 0000000..5be95e0 --- /dev/null +++ b/beken_os/beken378/driver/include/flash_pub.h @@ -0,0 +1,65 @@ +#ifndef _FLASH_PUB_H +#define _FLASH_PUB_H + +#define FLASH_DEV_NAME ("flash") + +#define FLASH_FAILURE (1) +#define FLASH_SUCCESS (0) + +#define FLASH_CMD_MAGIC (0xe240000) +enum +{ + CMD_FLASH_SET_CLK = FLASH_CMD_MAGIC + 1, + CMD_FLASH_SET_DCO, + CMD_FLASH_SET_DPLL, + + CMD_FLASH_WRITE_ENABLE, + CMD_FLASH_WRITE_DISABLE, + + CMD_FLASH_READ_SR, + CMD_FLASH_WRITE_SR, + + CMD_FLASH_READ_QE, + CMD_FLASH_SET_QE, + + CMD_FLASH_SET_QWFR, + CMD_FLASH_CLR_QWFR, + + CMD_FLASH_SET_WSR, + CMD_FLASH_GET_ID, + CMD_FLASH_READ_MID, + CMD_FLASH_ERASE_SECTOR, + CMD_FLASH_SET_HPM, + CMD_FLASH_SET_PROTECT, + CMD_FLASH_GET_PROTECT +}; + +typedef enum +{ + FLASH_PROTECT_NONE, + FLASH_PROTECT_ALL, + FLASH_PROTECT_HALF, + FLASH_UNPROTECT_LAST_BLOCK +} PROTECT_TYPE; + +typedef enum +{ + FLASH_XTX_16M_SR_WRITE_DISABLE, + FLASH_XTX_16M_SR_WRITE_ENABLE +} XTX_FLASH_MODE; + +typedef struct +{ + UINT8 byte; + UINT16 value; +} flash_sr_t; + +/******************************************************************************* +* Function Declarations +*******************************************************************************/ +extern void flash_init(void); +extern void flash_exit(void); +extern UINT8 flash_get_line_mode(void); +extern void flash_set_line_mode(UINT8 ); + +#endif //_FLASH_PUB_H diff --git a/beken_os/beken378/driver/include/general_dma_pub.h b/beken_os/beken378/driver/include/general_dma_pub.h new file mode 100755 index 0000000..bc6fca5 --- /dev/null +++ b/beken_os/beken378/driver/include/general_dma_pub.h @@ -0,0 +1,190 @@ +#ifndef __GDMA_PUB_H__ +#define __GDMA_PUB_H__ + +#if CFG_GENERAL_DMA +#define GDMA_FAILURE (1) +#define GDMA_SUCCESS (0) + +#define GDMA_DEV_NAME "generaldma" + +#define GDMA_CMD_MAGIC (0x0e809000) + +enum +{ + CMD_GDMA_SET_DMA_ENABLE = GDMA_CMD_MAGIC + 1, + CMD_GDMA_CFG_FIN_INT_ENABLE, + CMD_GDMA_CFG_HFIN_INT_ENABLE, + CMD_GDMA_CFG_WORK_MODE, + CMD_GDMA_CFG_SRCDATA_WIDTH, + CMD_GDMA_CFG_DSTDATA_WIDTH, + CMD_GDMA_CFG_SRCADDR_INCREASE, + CMD_GDMA_CFG_DSTADDR_INCREASE, + CMD_GDMA_CFG_SRCADDR_LOOP, + CMD_GDMA_CFG_DSTADDR_LOOP, + CMD_GDMA_SET_CHNL_PRIO, + CMD_GDMA_SET_TRANS_LENGTH, + CMD_GDMA_SET_DST_START_ADDR, + CMD_GDMA_SET_SRC_START_ADDR, + CMD_GDMA_SET_DST_LOOP_ENDADDR, + CMD_GDMA_SET_DST_LOOP_STARTADDR, + CMD_GDMA_SET_SRC_LOOP_ENDADDR, + CMD_GDMA_SET_SRC_LOOP_STARTADDR, + CMD_GDMA_SET_DST_REQ_MUX, + CMD_GDMA_SET_SRC_REQ_MUX, + CMD_GDMA_SET_DTCM_WRITE_WORD, + CMD_GDMA_GET_REMAIN_LENGTH, + CMD_GDMA_SET_FIN_CNT, + CMD_GDMA_SET_HFIN_CNT, + CMD_GDMA_SET_PRIO_MODE, + CMD_GDMA_GET_FIN_INT_STATUS, + CMD_GDMA_CLR_FIN_INT_STATUS, + CMD_GDMA_GET_HFIN_INT_STATUS, + CMD_GDMA_CLR_HFIN_INT_STATUS, + CMD_GDMA_CFG_TYPE0, + CMD_GDMA_CFG_TYPE1, + CMD_GDMA_CFG_TYPE2, + CMD_GDMA_CFG_TYPE3, + CMD_GDMA_CFG_TYPE4, + CMD_GDMA_CFG_TYPE5, + CMD_GDMA_CFG_TYPE6, + CMD_GDMA_ENABLE, + CMD_GDMA_GET_LEFT_LEN, + CMD_GDMA_SET_SRC_PAUSE_ADDR, + CMD_GDMA_GET_SRC_PAUSE_ADDR, + CMD_GDMA_SET_DST_PAUSE_ADDR, + CMD_GDMA_GET_DST_PAUSE_ADDR, + CMD_GDMA_GET_SRC_READ_ADDR, + CMD_GDMA_GET_DST_WRITE_ADDR, + CMD_GDMA_SET_FIN_ISR, +}; + +#define GDMA_X_DST_DTCM_WR_REQ (0x0) +#define GDMA_X_DST_HSSPI_TX_REQ (0x1) +#define GDMA_X_DST_AUDIO_RX_REQ (0x2) +#define GDMA_X_DST_SDIO_TX_REQ (0x3) +#define GDMA_X_DST_UART1_TX_REQ (0x4) +#define GDMA_X_DST_UART2_TX_REQ (0x5) +#define GDMA_X_DST_I2S_TX_REQ (0x6) +#define GDMA_X_DST_GSPI_TX_REQ (0x7) +#define GDMA_X_DST_PSRAM_V_WR_REQ (0x9) +#define GDMA_X_DST_PSRAM_A_WR_REQ (0xA) +#define GDMA_X_SRC_DTCM_RD_REQ (0x0) +#define GDMA_X_SRC_HSSPI_RX_REQ (0x1) +#define GDMA_X_SRC_AUDIO_TX_REQ (0x2) +#define GDMA_X_SRC_SDIO_RX_REQ (0x3) +#define GDMA_X_SRC_UART1_RX_REQ (0x4) +#define GDMA_X_SRC_UART2_RX_REQ (0x5) +#define GDMA_X_SRC_I2S_RX_REQ (0x6) +#define GDMA_X_SRC_GSPI_RX_REQ (0x7) +#define GDMA_X_SRC_JPEG_WR_REQ (0x8) +#define GDMA_X_SRC_PSRAM_V_RD_REQ (0x9) +#define GDMA_X_SRC_PSRAM_A_RD_REQ (0xA) +#define GDMA_X_SRC_DST_RESERVE (0xB) + +enum +{ + GDMA_CHANNEL_0 = 0, + GDMA_CHANNEL_1, + GDMA_CHANNEL_2, + GDMA_CHANNEL_3, +#if (CFG_SOC_NAME == SOC_BK7231) + GDMA_CHANNEL_MAX, +#else + GDMA_CHANNEL_4, + GDMA_CHANNEL_5, + GDMA_CHANNEL_MAX +#endif // (CFG_SOC_NAME == SOC_BK7231) +}; + +#define GDMA_TYPE_0 (0U) // no loop src, no loop dst, no register +#define GDMA_TYPE_1 (1U) // loop src, no loop dst, no register +#define GDMA_TYPE_2 (2U) // no loop src, loop dst, no register +#define GDMA_TYPE_3 (3U) // loop src, loop dst, no register + +#define GDMA_TYPE_4 (4U) // loop src, no loop dst, register +#define GDMA_TYPE_5 (5U) // no loop src, loop dst, register +#define GDMA_TYPE_6 (6U) // loop src, loop dst, register + +typedef struct gdmacfg_types_st +{ + UINT32 channel; + UINT32 prio; + UINT8 dstptr_incr; + UINT8 srcptr_incr; + UINT8 dstdat_width; + UINT8 srcdat_width; + + void *src_start_addr; + void *dst_start_addr; + + UINT8 src_module; + UINT8 dst_module; + void (*fin_handler)(UINT32); + void (*half_fin_handler)(UINT32); + + union + { + struct + { + void *src_loop_start_addr; + void *src_loop_end_addr; + } type1; // loop src, no loop dst, no register + + struct + { + void *dst_loop_start_addr; + void *dst_loop_end_addr; + } type2; // no loop src, loop dst, no register + + struct + { + void *src_loop_start_addr; + void *src_loop_end_addr; + void *dst_loop_start_addr; + void *dst_loop_end_addr; + } type3; // loop src, loop dst, no register + + struct + { + void *src_loop_start_addr; + void *src_loop_end_addr; + } type4; // loop src, no loop dst, register + + struct + { + void *dst_loop_start_addr; + void *dst_loop_end_addr; + } type5; // no loop src, loop dst, register + + struct + { + void *src_loop_start_addr; + void *src_loop_end_addr; + void *dst_loop_start_addr; + void *dst_loop_end_addr; + } type6; // loop src, loop dst, register + } u; +} GDMACFG_TPYES_ST, *GDMACFG_TPYES_PTR; + +typedef struct gdma_do_st +{ + UINT32 channel; + void *src_addr; + void *dst_addr; + UINT32 length; +} GDMA_DO_ST, *GDMA_DO_PTR; + + +typedef struct generdam_cfg_st +{ + UINT32 param; + UINT32 channel; +} GDMA_CFG_ST, *GDMA_CFG_PTR; + +void gdma_init(void); +void gdma_exit(void); +void *gdma_memcpy(void *out, const void *in, UINT32 n); + +#endif // CFG_GENERAL_DMA + +#endif diff --git a/beken_os/beken378/driver/include/gpio_pub.h b/beken_os/beken378/driver/include/gpio_pub.h new file mode 100755 index 0000000..2fda038 --- /dev/null +++ b/beken_os/beken378/driver/include/gpio_pub.h @@ -0,0 +1,245 @@ +#ifndef _GPIO_PUB_H_ +#define _GPIO_PUB_H_ + +#include "generic.h" +#include "drv_model_pub.h" + +#define GPIO_FAILURE (1) +#define GPIO_SUCCESS (0) + +#define GPIO_DEV_NAME "gpio" + +#define GPIO_CFG_PARAM(id, mode) (id + ((mode & 0xff) << 8)) +#define GPIO_CFG_PARAM_DEMUX_ID(param) (param & 0xff) +#define GPIO_CFG_PARAM_DEMUX_MODE(param) ((param >> 8) & 0xff) + +#define GPIO_OUTPUT_PARAM(id, val) (id + ((val & 0xff) << 8)) +#define GPIO_OUTPUT_DEMUX_ID(param) (param & 0xff) +#define GPIO_OUTPUT_DEMUX_VAL(param) ((param >> 8) & 0xff) + + +#define GPIO_CMD_MAGIC (0xcaa0000) +enum +{ + CMD_GPIO_CFG = GPIO_CMD_MAGIC + 0, + CMD_GPIO_OUTPUT_REVERSE = GPIO_CMD_MAGIC + 1, + CMD_GPIO_ENABLE_SECOND = GPIO_CMD_MAGIC + 2, + CMD_GPIO_INPUT = GPIO_CMD_MAGIC + 3, + CMD_GPIO_OUTPUT = GPIO_CMD_MAGIC + 4, + CMD_GPIO_CLR_DPLL_UNLOOK_INT = GPIO_CMD_MAGIC + 5, + CMD_GPIO_EN_DPLL_UNLOOK_INT = GPIO_CMD_MAGIC + 6, + CMD_GPIO_INT_ENABLE = GPIO_CMD_MAGIC + 7, + CMD_GPIO_INT_DISABLE = GPIO_CMD_MAGIC + 8, + CMD_GPIO_INT_CONFIG = GPIO_CMD_MAGIC + 9, + CMD_GPIO_INT_CLEAR = GPIO_CMD_MAGIC + 10, +}; + + +enum +{ + GMODE_INPUT_PULLDOWN = 0, + GMODE_OUTPUT, + GMODE_SECOND_FUNC, + GMODE_INPUT_PULLUP, + GMODE_INPUT, + GMODE_SECOND_FUNC_PULL_UP,//Special for uart1 + GMODE_OUTPUT_PULLUP, + GMODE_SET_HIGH_IMPENDANCE, + GMODE_DEEP_PS, + GMODE_HIGH_Z +}; + +typedef enum +{ + GPIO0 = 0, + GPIO1, + GPIO2, + GPIO3, + GPIO4, + GPIO5, + GPIO6, + GPIO7, + GPIO8, + GPIO9, + GPIO10, + GPIO11, + GPIO12, + GPIO13, + GPIO14, + GPIO15, + GPIO16, + GPIO17, + GPIO18, + GPIO19, + GPIO20, + GPIO21, + GPIO22, + GPIO23, + GPIO24, + GPIO25, + GPIO26, + GPIO27, + GPIO28, + GPIO29, + GPIO30, + GPIO31, + GPIO32, + GPIO33, + GPIO34, + GPIO35, + GPIO36, + GPIO37, + GPIO38, + GPIO39, + GPIONUM +} GPIO_INDEX ; + +#define BITS_INT 32 + +enum +{ + GFUNC_MODE_UART2 = 0, + GFUNC_MODE_I2C2, + GFUNC_MODE_I2S, + GFUNC_MODE_ADC1, + GFUNC_MODE_ADC2, + GFUNC_MODE_CLK13M, + GFUNC_MODE_PWM0, + GFUNC_MODE_PWM1, + GFUNC_MODE_PWM2, + GFUNC_MODE_PWM3, + GFUNC_MODE_WIFI_ACTIVE, + GFUNC_MODE_BT_ACTIVE, + GFUNC_MODE_BT_PRIORITY, + GFUNC_MODE_UART1, + GFUNC_MODE_SD_DMA, + GFUNC_MODE_SD_HOST, + GFUNC_MODE_SPI_DMA, + GFUNC_MODE_SPI, + GFUNC_MODE_SPI_USE_GPIO_14, + GFUNC_MODE_SPI_USE_GPIO_16_17, + + GFUNC_MODE_PWM4, + GFUNC_MODE_PWM5, + GFUNC_MODE_I2C1, + GFUNC_MODE_JTAG, + GFUNC_MODE_CLK26M, + GFUNC_MODE_ADC3, + GFUNC_MODE_DCMI, + GFUNC_MODE_ADC4, + GFUNC_MODE_ADC5, + GFUNC_MODE_ADC6, + GFUNC_MODE_ADC7, + GFUNC_MODE_SD1_HOST, + GFUNC_MODE_SPI1, + GFUNC_MODE_SPI_DMA1, +}; + +enum +{ + GPIO_INT_LEVEL_LOW = 0, + GPIO_INT_LEVEL_HIGH = 1, + GPIO_INT_LEVEL_RISING = 2, + GPIO_INT_LEVEL_FALLING = 3 +}; + +typedef struct gpio_int_st +{ + UINT32 id; + UINT32 mode; + void * phandler; +}GPIO_INT_ST; + +extern UINT32 gpio_ctrl(UINT32 cmd, void *param); +__inline static void bk_gpio_config_input(GPIO_INDEX id) +{ + UINT32 ret; + UINT32 param; + + param = GPIO_CFG_PARAM(id, GMODE_INPUT); + ret = gpio_ctrl(CMD_GPIO_CFG, ¶m); + + ASSERT(GPIO_SUCCESS == ret); +} + +__inline static void bk_gpio_config_input_pup(GPIO_INDEX id) +{ + UINT32 ret; + UINT32 param; + + param = GPIO_CFG_PARAM(id, GMODE_INPUT_PULLUP); + ret = gpio_ctrl(CMD_GPIO_CFG, ¶m); + + ASSERT(GPIO_SUCCESS == ret); +} + +__inline static void bk_gpio_config_input_pdwn(GPIO_INDEX id) +{ + UINT32 ret; + UINT32 param; + + param = GPIO_CFG_PARAM(id, GMODE_INPUT_PULLDOWN); + ret = gpio_ctrl(CMD_GPIO_CFG, ¶m); + + ASSERT(GPIO_SUCCESS == ret); +} + +__inline static uint32_t bk_gpio_input(GPIO_INDEX id) +{ + UINT32 ret; + UINT32 param = id; + + ret = gpio_ctrl(CMD_GPIO_INPUT, ¶m); + + return ret; +} + +__inline static void bk_gpio_config_output(GPIO_INDEX id) +{ + UINT32 ret; + + UINT32 param; + + param = GPIO_CFG_PARAM(id, GMODE_OUTPUT); + ret = gpio_ctrl(CMD_GPIO_CFG, ¶m); + ASSERT(GPIO_SUCCESS == ret); +} + +__inline static void bk_gpio_output(GPIO_INDEX id,UINT32 val) +{ + UINT32 ret; + UINT32 param; + + param = GPIO_OUTPUT_PARAM(id, val); + ret = gpio_ctrl(CMD_GPIO_OUTPUT, ¶m); + ASSERT(GPIO_SUCCESS == ret); +} + +__inline static void bk_gpio_output_reverse(GPIO_INDEX id) +{ + UINT32 ret; + UINT32 param = id; + + ret = gpio_ctrl(CMD_GPIO_OUTPUT_REVERSE, ¶m); + ASSERT(GPIO_SUCCESS == ret); +} + +#if ((SOC_BK7231U == CFG_SOC_NAME) || (SOC_BK7221U == CFG_SOC_NAME)) +#define GPIO_USB_DP_PIN GPIO25 +#define GPIO_USB_DN_PIN GPIO28 + +extern void gpio_usb_second_function(void); +#endif + +extern UINT32 gpio_input(UINT32 id); +extern void gpio_init(void); +extern void gpio_exit(void); +void gpio_int_disable(UINT32 index); +void gpio_int_enable(UINT32 index, UINT32 mode, void (*p_Int_Handler)(unsigned char)); +void gpio_config( UINT32 index, UINT32 mode ) ; +void gpio_output(UINT32 id, UINT32 val); + +#endif // _GPIO_PUB_H_ + +// EOF + diff --git a/beken_os/beken378/driver/include/i2s_pub.h b/beken_os/beken378/driver/include/i2s_pub.h new file mode 100755 index 0000000..3076c20 --- /dev/null +++ b/beken_os/beken378/driver/include/i2s_pub.h @@ -0,0 +1,50 @@ +#ifndef _I2S_PUB_H_ +#define _I2S_PUB_H_ + +#define I2S_FAILURE (1) +#define I2S_SUCCESS (0) + +#define I2S_DEV_NAME "i2s" + +#define I2S_CMD_MAGIC (0xe280000) +enum +{ + I2S_HW_SET = I2S_CMD_MAGIC + 1, + I2S_CMD_SET_FREQ_DATAWIDTH, + I2S_CMD_ACTIVE, + I2S_CMD_RXACTIVE, + I2S_CMD_SELECT_MODE, + I2S_CMD_SET_LEVEL +}; + +enum +{ + I2S_MODE_I2S = 0, + I2S_MODE_LEFT_JUST = 1, + I2S_MODE_RIGHT_JUST = 2, + I2S_MODE_SHORT_SYNC = 4, + I2S_MODE_LONG_SYNC = 5, + I2S_MODE_NORMAL_2B_D = 6, + I2S_MODE_DELAY_2B_D = 7 +}; + +typedef struct +{ + UINT8 rx_level; + UINT8 tx_level; +} i2s_level_t; + +typedef struct +{ + UINT32 freq; + UINT16 datawidth; +} i2s_rate_t; + +/******************************************************************************* +* Function Declarations +*******************************************************************************/ +void i2s_init(void); +void i2s_exit(void); +void i2s_isr(void); +UINT8 is_i2s_active(void); +#endif //_I2S_PUB_H_ diff --git a/beken_os/beken378/driver/include/icu_pub.h b/beken_os/beken378/driver/include/icu_pub.h new file mode 100755 index 0000000..daa2c12 --- /dev/null +++ b/beken_os/beken378/driver/include/icu_pub.h @@ -0,0 +1,184 @@ +#ifndef _ICU_PUB_H_ +#define _ICU_PUB_H_ + +#define ICU_FAILURE (1) +#define ICU_SUCCESS (0) + +#define ICU_DEV_NAME "icu" + +#define ICU_CMD_MAGIC (0xe220000) +enum +{ + CMD_ICU_CLKGATING_DISABLE = ICU_CMD_MAGIC + 1, + CMD_ICU_CLKGATING_ENABLE, + CMD_ICU_INT_DISABLE, + CMD_ICU_INT_ENABLE, + CMD_ICU_GLOBAL_INT_DISABLE, + CMD_ICU_GLOBAL_INT_ENABLE, + CMD_GET_INTR_STATUS, + CMD_CLR_INTR_STATUS, + CMD_GET_INTR_RAW_STATUS, + CMD_CLR_INTR_RAW_STATUS, + CMD_CLK_PWR_DOWN, + CMD_CLK_PWR_UP, + CMD_CONF_PWM_PCLK, + CMD_CONF_PWM_LPOCLK, + CMD_TL410_CLK_PWR_DOWN, + CMD_TL410_CLK_PWR_UP, + CMD_CONF_PCLK_26M, + CMD_CONF_PCLK_DCO, + CMD_SET_JTAG_MODE, + CMD_GET_JTAG_MODE, + CMD_ARM_WAKEUP +}; + +/*CMD_CONF_PCLK*/ +#define PCLK_POSI (0) +#define PCLK_POSI_UART1 (1 << 0) +#define PCLK_POSI_UART2 (1 << 1) +#define PCLK_POSI_I2C1 (1 << 2) +#define PCLK_POSI_IRDA (1 << 3) +#define PCLK_POSI_I2C2 (1 << 4) +#if (CFG_SOC_NAME == SOC_BK7231N) +#define PCLK_POSI_SARADC (1 << 5) +#define PCLK_POSI_SPI (1 << 6) +#else +#define PCLK_POSI_SPI (1 << 5) +#define PCLK_POSI_SARADC (1 << 6) +#endif +#define PCLK_POSI_PWMS (1 << 7) +#define PCLK_POSI_SDIO (1 << 8) +#if (CFG_SOC_NAME == SOC_BK7231N) +#define PCLK_POSI_EFUSE (1 << 9) +#else +#define PCLK_POSI_SARADC_AUD (1 << 9) +#endif + +/*CMD_CONF_PWM_PCLK, CMD_CONF_PWM_LPOCLK*/ +#define PWM_MUX_POSI (0) +#define PWM_MUX_LPO (1) +#define PWM_MUX_PCLK (0) +// *param = channel_id + +/*CMD_CLK_PWR_DOWN CMD_CLK_PWR_UP*/ +#define PWD_JEPG_CLK_BIT (1 << 22) +#if (CFG_SOC_NAME != SOC_BK7231) +#define PWD_TIMER_32K_CLK_BIT (1 << 21) +#define PWD_TIMER_26M_CLK_BIT (1 << 20) +#endif +#define PWD_FFT_CLK_BIT (1 << 19) +#define PWD_USB_CLK_BIT (1 << 18) +#define PWD_SDIO_CLK_BIT (1 << 17) +#define PWD_TL410_WATCHDOG_BIT (1 << 16) +#define PWD_AUDIO_CLK_BIT (1 << 15) +#define PWD_PWM5_CLK_BIT (1 << 14) +#define PWD_PWM4_CLK_BIT (1 << 13) +#define PWD_PWM3_CLK_BIT (1 << 12) +#define PWD_PWM2_CLK_BIT (1 << 11) +#define PWD_PWM1_CLK_BIT (1 << 10) +#define PWD_PWM0_CLK_BIT (1 << 9) +#define PWD_ARM_WATCHDOG_CLK_BIT (1 << 8) +#define PWD_SARADC_CLK_BIT (1 << 7) +#define PWD_SPI_CLK_BIT (1 << 6) +#define PWD_I2C2_CLK_BIT (1 << 5) +#define PWD_I2S_PCM_CLK_BIT (1 << 4) +#define PWD_IRDA_CLK_BIT (1 << 3) +#define PWD_I2C1_CLK_BIT (1 << 2) +#define PWD_UART2_CLK_BIT (1 << 1) +#define PWD_UART1_CLK_BIT (1 << 0) + +/* CMD_ICU_CLKGATING_DISABLE CMD_ICU_CLKGATING_ENABLE*/ +#define CLKGATE_MAC_AHB_BIT (1 << 16) +#define CLKGATE_FFT_AHB_BIT (1 << 15) +#define CLKGATE_USB_AHB_BIT (1 << 14) +#define CLKGATE_SDIO_AHB_BIT (1 << 13) +#define CLKGATE_SARADC_APB_BIT (1 << 12) +#define CLKGATE_AUDIO_APB_BIT (1 << 11) +#define CLKGATE_PWM_APB_BIT (1 << 10) +#define CLKGATE_WATCHDOG_APB_BIT (1 << 9) +#define CLKGATE_GPIO_APB_BIT (1 << 8) +#define CLKGATE_SPI_APB_BIT (1 << 7) +#define CLKGATE_I2C2_APB_BIT (1 << 6) +#define CLKGATE_I2S_PCM_APB_BIT (1 << 5) +#define CLKGATE_IRDA_APB_BIT (1 << 4) +#define CLKGATE_I2C1_APB_BIT (1 << 3) +#define CLKGATE_UART2_APB_BIT (1 << 2) +#define CLKGATE_UART1_APB_BIT (1 << 1) +#define CLKGATE_ICU_APB_BIT (1 << 0) + +/* CMD ICU_TL410_CLK_PWD*/ +#define PWD_TL410_CLK_BIT (1 << 0) +#define PWD_BLE_CLK_BIT (1 << 1) + +/* ICU_JTAG_SELECT */ +#define JTAG_ARM_MODE 0 +#define JTAG_TL410_MODE 1 + +/*CMD_ICU_INT_DISABLE CMD_ICU_INT_ENABLE*/ +#define FIQ_JPEG_DECODER_BIT (1 << 29) +#define FIQ_DPLL_UNLOCK_BIT (1 << 28) +#define FIQ_SPI_DMA_BIT (1 << 27) +#define FIQ_MAC_WAKEUP_BIT (1 << 26) +#if (CFG_SOC_NAME == SOC_BK7221U) +#define FIQ_SECURITY_BIT (1 << 25) +#define FIQ_USB_PLUG_INOUT_BIT (1 << 24) +#else +#define FIQ_MAILBOX1_BIT (1 << 25) +#define FIQ_MAILBOX0_BIT (1 << 24) +#endif // (CFG_SOC_NAME == SOC_BK7221U) +#define FIQ_SDIO_DMA_BIT (1 << 23) +#define FIQ_MAC_GENERAL_BIT (1 << 22) +#define FIQ_MAC_PROT_TRIGGER_BIT (1 << 21) +#define FIQ_MAC_TX_TRIGGER_BIT (1 << 20) +#define FIQ_MAC_RX_TRIGGER_BIT (1 << 19) +#define FIQ_MAC_TX_RX_MISC_BIT (1 << 18) +#define FIQ_MAC_TX_RX_TIMER_BIT (1 << 17) +#define FIQ_MODEM_BIT (1 << 16) +#define IRQ_GDMA_BIT (1 << 15) +#define IRQ_FFT_BIT (1 << 14) +#define IRQ_USB_BIT (1 << 13) +#define IRQ_SDIO_BIT (1 << 12) +#define IRQ_SARADC_BIT (1 << 11) +#define IRQ_AUDIO_BIT (1 << 10) +#define IRQ_PWM_BIT (1 << 9) +#define IRQ_TL410_WATCHDOG_BIT (1 << 8) +#define IRQ_GPIO_BIT (1 << 7) +#define IRQ_SPI_BIT (1 << 6) +#define IRQ_I2C2_BIT (1 << 5) +#define IRQ_I2S_PCM_BIT (1 << 4) +#define IRQ_IRDA_BIT (1 << 3) +#define IRQ_I2C1_BIT (1 << 2) +#define IRQ_UART2_BIT (1 << 1) +#define IRQ_UART1_BIT (1 << 0) + +/* CMD_ICU_GLOBAL_INT_DISABLE CMD_ICU_GLOBAL_INT_ENABLE*/ +#define GINTR_FIQ_BIT (1 << 1) +#define GINTR_IRQ_BIT (1 << 0) + + +/* CMD_ARM_WAKEUP */ +#if (CFG_SOC_NAME == SOC_BK7231) +#define TL410_WATCHDOG_ARM_WAKEUP_EN_BIT (1 << 8) +#else +#define TIMER_ARM_WAKEUP_EN_BIT (1 << 8) +#endif + +#define BLE_ARM_WAKEUP_EN_BIT (1 << 30) +#if (CFG_SOC_NAME == SOC_BK7231N) +#define BTDM_ARM_WAKEUP_EN_BIT (1 << 29) +#endif +#define MAC_ARM_WAKEUP_EN_BIT (1 << 26) +#define GPIO_ARM_WAKEUP_EN_BIT (1 << 7) +#define PWM_ARM_WAKEUP_EN_BIT (1 << 9) +#define UART2_ARM_WAKEUP_EN_BIT (1 << 1) +#define UART1_ARM_WAKEUP_EN_BIT (1 << 0) + +/******************************************************************************* +* Function Declarations +*******************************************************************************/ +extern void icu_init(void); +extern void icu_exit(void); +extern UINT32 icu_ctrl(UINT32 cmd, void *param); + +#endif //_ICU_PUB_H_ + diff --git a/beken_os/beken378/driver/include/intc_pub.h b/beken_os/beken378/driver/include/intc_pub.h new file mode 100755 index 0000000..136b0c5 --- /dev/null +++ b/beken_os/beken378/driver/include/intc_pub.h @@ -0,0 +1,151 @@ +#ifndef _INTC_PUB_H_ +#define _INTC_PUB_H_ + +#include "generic.h" + +#if (CFG_SOC_NAME == SOC_BK7231N) +#define FIQ_BT (31) +#define FIQ_BLE (30) +#define FIQ_BTDM (29) +#define FIQ_DPLL_UNLOCK (28) +#define FIQ_MAC_WAKEUP (26) +#define FIQ_MAC_GENERAL (22) +#define FIQ_MAC_PROT_TRIGGER (21) +#define FIQ_MAC_TX_TRIGGER (20) +#define FIQ_MAC_RX_TRIGGER (19) +#define FIQ_MAC_TX_RX_MISC (18) +#define FIQ_MAC_TX_RX_TIMER (17) +#define FIQ_MODEM (16) + +#define IRQ_GENERDMA (15) +#define IRQ_LA (14) +#define IRQ_SEC (13) +#define IRQ_SDIO (12) +#define IRQ_SARADC (11) +#define IRQ_PWM (9) +#define IRQ_TIMER (8) +#define IRQ_GPIO (7) +#define IRQ_SPI (6) +#define IRQ_I2C2 (5) +#define IRQ_IRDA (3) +#define IRQ_I2C1 (2) +#define IRQ_UART2 (1) +#define IRQ_UART1 (0) +#else +#define FIQ_PSRAM (31) +#define FIQ_BLE (30) +#define FIQ_JPEG_ENCODER (29) +#define FIQ_DPLL_UNLOCK (28) +#define FIQ_SPI_DMA (27) +#define FIQ_MAC_WAKEUP (26) +#define FIQ_MAILBOX1 (25) +#define FIQ_MAILBOX0 (24) +#define FIQ_SDIO_DMA (23) +#define FIQ_MAC_GENERAL (22) +#define FIQ_MAC_PROT_TRIGGER (21) +#define FIQ_MAC_TX_TRIGGER (20) +#define FIQ_MAC_RX_TRIGGER (19) +#define FIQ_MAC_TX_RX_MISC (18) +#define FIQ_MAC_TX_RX_TIMER (17) +#define FIQ_MODEM (16) + +#define IRQ_GENERDMA (15) +#define IRQ_FFT (14) +#define IRQ_USB (13) +#define IRQ_SD (12) +#define IRQ_SARADC (11) +#define IRQ_AUDIO (10) +#define IRQ_PWM (9) +#if (CFG_SOC_NAME == SOC_BK7231) +#define IRQ_TL410_WATCHDOG (8) +#else +#define IRQ_TIMER (8) +#endif +#define IRQ_GPIO (7) +#define IRQ_SPI (6) +#define IRQ_I2C2 (5) +#define IRQ_I2S_PCM (4) +#define IRQ_IRDA (3) +#define IRQ_I2C1 (2) +#define IRQ_UART2 (1) +#define IRQ_UART1 (0) +#endif + +#if (CFG_SOC_NAME == SOC_BK7231N) +#define PRI_FIQ_BT (7) +#define PRI_FIQ_BLE (8) +#define PRI_FIQ_BTDM (13) +#define PRI_FIQ_DPLL_UNLOCK (29) +#define PRI_FIQ_MAC_WAKEUP (9) +#define PRI_FIQ_MAC_GENERAL (1) +#define PRI_FIQ_MAC_PROT_TRIGGER (6) +#define PRI_FIQ_MAC_TX_TRIGGER (3) +#define PRI_FIQ_MAC_RX_TRIGGER (4) +#define PRI_FIQ_MAC_TX_RX_MISC (5) +#define PRI_FIQ_MAC_TX_RX_TIMER (2) +#define PRI_FIQ_MODEM (10) + +#define PRI_IRQ_GENERDMA (28) +#define PRI_IRQ_LA (20) +#define PRI_IRQ_SEC (21) +#define PRI_IRQ_SDIO (22) +#define PRI_IRQ_SARADC (16) +#define PRI_IRQ_PWM (17) +#define PRI_IRQ_TIMER (18) +#define PRI_IRQ_GPIO (19) +#define PRI_IRQ_SPI (20) +#define PRI_IRQ_I2C2 (21) +#define PRI_IRQ_IRDA (23) +#define PRI_IRQ_I2C1 (24) +#define PRI_IRQ_UART2 (25) +#define PRI_IRQ_UART1 (26) +#else +#define PRI_FIQ_BLE (31) +#define PRI_FIQ_JPEG_DECODER (30) +#define PRI_FIQ_DPLL_UNLOCK (29) +#define PRI_FIQ_SPI_DMA (7) +#define PRI_FIQ_MAC_WAKEUP (9) +#define PRI_FIQ_MAILBOX1 (12) +#define PRI_FIQ_MAILBOX0 (11) +#define PRI_FIQ_SDIO_DMA (8) +#define PRI_FIQ_MAC_GENERAL (1) +#define PRI_FIQ_MAC_PROT_TRIGGER (6) +#define PRI_FIQ_MAC_TX_TRIGGER (3) +#define PRI_FIQ_MAC_RX_TRIGGER (4) +#define PRI_FIQ_MAC_TX_RX_MISC (5) +#define PRI_FIQ_MAC_TX_RX_TIMER (2) +#define PRI_FIQ_MODEM (10) + +#define PRI_IRQ_GENERDMA (28) +#define PRI_IRQ_FFT (13) +#define PRI_IRQ_USB (14) +#define PRI_IRQ_SD (15) +#define PRI_IRQ_SARADC (16) +#define PRI_IRQ_AUDIO (27) +#define PRI_IRQ_PWM (17) +#if (CFG_SOC_NAME == SOC_BK7231) +#define PRI_IRQ_TL410_WATCHDOG (18) +#else +#define PRI_IRQ_TIMER (18) +#endif +#define PRI_IRQ_GPIO (19) +#define PRI_IRQ_SPI (20) +#define PRI_IRQ_I2C2 (21) +#define PRI_IRQ_I2S_PCM (22) +#define PRI_IRQ_IRDA (23) +#define PRI_IRQ_I2C1 (24) +#define PRI_IRQ_UART2 (25) +#define PRI_IRQ_UART1 (26) +#endif + +typedef uint8 (*IRDA_CHECK_FUNC)(void); + +extern void intc_register_irda_check_func(IRDA_CHECK_FUNC func); +extern void intc_unregister_irda_check_func(); +extern void intc_service_register(UINT8 int_num, UINT8 int_pri, FUNCPTR isr); +extern void intc_spurious(void); +extern void intc_enable(int index); +extern void intc_disable(int index); + +#endif // _INTC_PUB_H_ +// eof diff --git a/beken_os/beken378/driver/include/irda_pub.h b/beken_os/beken378/driver/include/irda_pub.h new file mode 100755 index 0000000..1511174 --- /dev/null +++ b/beken_os/beken378/driver/include/irda_pub.h @@ -0,0 +1,26 @@ +#ifndef _IRDA_PUB_H_ +#define _IRDA_PUB_H_ + +#define IRDA_FAILURE (1) +#define IRDA_SUCCESS (0) + +#define IRDA_DEV_NAME "irda" + +#define IRDA_CMD_MAGIC (0xe290000) +enum +{ + IRDA_CMD_ACTIVE = IRDA_CMD_MAGIC + 1, + IRDA_CMD_SET_POLARITY, + IRDA_CMD_SET_CLK, + IRDA_CMD_GET_KEY, + TRNG_CMD_SET, + TRNG_CMD_GET +}; + +/******************************************************************************* +* Function Declarations +*******************************************************************************/ +void irda_init(void); +void irda_exit(void); +void irda_isr(void); +#endif //_IRDA_PUB_H_ diff --git a/beken_os/beken378/driver/include/mac_phy_bypass_pub.h b/beken_os/beken378/driver/include/mac_phy_bypass_pub.h new file mode 100755 index 0000000..6944adc --- /dev/null +++ b/beken_os/beken378/driver/include/mac_phy_bypass_pub.h @@ -0,0 +1,49 @@ +#ifndef _MAC_PHY_BYPASS_PUB_H_ +#define _MAC_PHY_BYPASS_PUB_H_ + +#define MPB_DEV_NAME "mac_phy_bypass" + + +#define MPB_CMD_MAGIC (0xcbe0000) +enum +{ + MCMD_RX_MODE_BYPASS_MAC = MPB_CMD_MAGIC + 0, + MCMD_TX_MODE_BYPASS_MAC = MPB_CMD_MAGIC + 1, + MCMD_TX_LEGACY_SET_LEN, + MCMD_TX_HT_VHT_SET_LEN, + MCMD_STOP_BYPASS_MAC, + MCMD_START_BYPASS_MAC, + MCMD_SET_BANDWIDTH, + MCMD_SET_GI, + MCMD_BYPASS_TX_SET_RATE_MFORMAT, + MCMD_SET_TXDELAY, +}; + +/*MCMD_TX_BYPASS_MAC_RATE*/ +#define PPDU_RATE_POSI (4) +#define PPDU_RATE_MASK (0xF) + +#define PPDU_BANDWIDTH_POSI (6) +#define PPDU_BANDWIDTH_MASK (0x1) + +#define PPDU_LEG_RATE_1MBPS (0x00) +#define PPDU_LEG_RATE_2MBPS (0x01) +#define PPDU_LEG_RATE_5_5MBPS (0x02) +#define PPDU_LEG_RATE_11MBPS (0x03) +#define PPDU_LEG_RATE_6MBPS (0x0B) +#define PPDU_LEG_RATE_9MBPS (0x0F) +#define PPDU_LEG_RATE_12MBPS (0x0A) +#define PPDU_LEG_RATE_18MBPS (0x0E) +#define PPDU_LEG_RATE_24MBPS (0x09) +#define PPDU_LEG_RATE_36MBPS (0x0D) +#define PPDU_LEG_RATE_48MBPS (0x08) +#define PPDU_LEG_RATE_54MBPS (0x0C) + +typedef struct mbps_txs_mfr_st { + UINT32 mod_format; + UINT32 rate; +}MBPS_TXS_MFR_ST, *MBPS_TXS_MFR_PTR; + +extern void mpb_init(void); +extern void mpb_exit(void); +#endif // _MAC_PHY_BYPASS_PUB_H_ diff --git a/beken_os/beken378/driver/include/pwm_pub.h b/beken_os/beken378/driver/include/pwm_pub.h new file mode 100755 index 0000000..4538acb --- /dev/null +++ b/beken_os/beken378/driver/include/pwm_pub.h @@ -0,0 +1,171 @@ +#ifndef _PWM_PUB_H_ +#define _PWM_PUB_H_ + +#define PWM_FAILURE (1) +#define PWM_SUCCESS (0) + +#define PWM_DEV_NAME "pwm" + +#define PWM_CMD_MAGIC (0xe230000) +enum +{ + CMD_PWM_UNIT_ENABLE = PWM_CMD_MAGIC + 1, + CMD_PWM_UNIT_DISABLE, + CMD_PWM_IR_ENABLE, + CMD_PWM_IR_DISABLE, + CMD_PWM_IR_CLEAR, + CMD_PWM_INIT_PARAM, + CMD_PWM_SET_DUTY_CYCLE, + CMD_PWM_SET_END_VALUE, + CMD_PWM_CAP_GET, + CMD_PWM_DEINIT_PARAM, + CMD_PWM_GROUP_ENABLE, + CMD_PWM_GROUP_DISABLE, + CMD_PWM_UPDATA_PARAM, + CMD_PWM_SINGLE_UPDATA_PARAM, + CMD_PWM_UPDATA_PARAM_ENABLE, + CMD_PWM_INIT_LEVL_SET_LOW, + CMD_PWM_INIT_LEVL_SET_HIGH, + CMD_PWM_SET_IR_CALLBACK, +}; + +enum +{ + PWM0 = 0, + PWM1, + PWM2, + PWM3, + PWM4, + PWM5, + PWM_COUNT +}; + +typedef void (*PFUNC)(UINT8); + + +#define PWM_ENABLE (0x01) +#define PWM_DISABLE (0x00) + +#define PWM_INT_EN (0x01) +#define PWM_INT_DIS (0x00) + +#if (CFG_SOC_NAME == SOC_BK7231N) +#define PWM_IDLE_MODE (0x00) +#define PWM_PWM_MODE (0x01) +#define PWM_TIMER_MODE (0x02) +#define PWM_CPUNTER_MODE (0x03) +#define PWM_CAP_POS_MODE (0x04) +#define PWM_CAP_NEG_MODE (0x05) +#define PWM_CAP_EDGE_MODE (0x06) +#else +#define PWM_PWM_MODE (0x00) +#define PWM_TIMER_MODE (0x01) +#define PWM_CAP_POS_MODE (0x02) +#define PWM_CAP_NEG_MODE (0x03) +#endif + +#define PWM_CLK_32K (0x00) +#define PWM_CLK_26M (0x01) +#define PWM_CLK_DCO (0x02) + +typedef struct +{ + UINT8 channel; + + union + { + UINT8 val; + struct + { +#if (CFG_SOC_NAME == SOC_BK7231N) + /* cfg--PWM config + * bit[2:0]: PWM mode selection + * 000:IDLE + * 001: PWM mode + * 010: TIMER + * 100: Capture (pos -> pos) + * 101: Capture (neg -> neg) + * 110: Capture (edge -> edge) + * bit[3]: PWM enable + * 0: PWM disable + * 1: PWM enable + * bit[4]: PWM interrupt enable + * 0: PWM interrupt disable + * 1: PWM interrupt enable + * bit[6:5]: PWM clock select + * 00: PWM clock LPO + * 01: PWM clock 26MHz + * 10/11: PWM clock DCO + */ + UINT8 mode: 3; + UINT8 en: 1; + UINT8 int_en: 1; + UINT8 clk: 2; + UINT8 rsv: 1; +#else + /* cfg--PWM config + * bit[0]: PWM enable + * 0: PWM disable + * 1: PWM enable + * bit[1]: PWM interrupt enable + * 0: PWM interrupt disable + * 1: PWM interrupt enable + * bit[3:2]: PWM mode selection + * 00: PWM mode + * 01: TIMER + * 10: Capture Posedge + * 11: Capture Negedge + * bit[5:4]: PWM clock select + * 00: PWM clock 32KHz + * 01: PWM clock 26MHz + * 10/11: PWM clock DPLL + * bit[7:6]: reserved + */ + UINT8 en: 1; + UINT8 int_en: 1; + UINT8 mode: 2; + UINT8 clk: 2; + UINT8 rsv: 2; +#endif + } bits; + } cfg; + +#if (CFG_SOC_NAME == SOC_BK7231) + UINT16 end_value; + UINT16 duty_cycle; +#elif (CFG_SOC_NAME == SOC_BK7231N) + UINT32 end_value; + UINT32 duty_cycle1; + UINT32 duty_cycle2; + UINT32 duty_cycle3; + UINT32 init_level0; + UINT32 init_level1; +#else + UINT32 end_value; + UINT32 duty_cycle; +#endif + PFUNC p_Int_Handler; +} pwm_param_t; + +typedef struct +{ + UINT32 ucChannel; + UINT32 value; +} pwm_capture_t; + +typedef struct +{ + UINT32 channel; + PFUNC p_Int_Handler; +} pwm_int_cfg_t; + +/******************************************************************************* +* Function Declarations +*******************************************************************************/ +extern void pwm_init(void); +extern void pwm_exit(void); +extern void pwm_isr(void); + +#endif //_PWM_PUB_H_ +// eof + diff --git a/beken_os/beken378/driver/include/rc_beken_pub.h b/beken_os/beken378/driver/include/rc_beken_pub.h new file mode 100755 index 0000000..a6653af --- /dev/null +++ b/beken_os/beken378/driver/include/rc_beken_pub.h @@ -0,0 +1,4 @@ +#ifndef _RC_BEKEN_PUB_H_ +#define _RC_BEKEN_PUB_H_ + +#endif // _RC_BEKEN_PUB_H_ diff --git a/beken_os/beken378/driver/include/saradc_pub.h b/beken_os/beken378/driver/include/saradc_pub.h new file mode 100755 index 0000000..d45f320 --- /dev/null +++ b/beken_os/beken378/driver/include/saradc_pub.h @@ -0,0 +1,100 @@ +#ifndef _SARADC_PUB_H_ +#define _SARADC_PUB_H_ + +#define SARADC_FAILURE (1) +#define SARADC_SUCCESS (0) + +#define SARADC_DEV_NAME "saradc" + +#define SARADC_CMD_MAGIC (0xe290000) +enum +{ + SARADC_CMD_SET_MODE = SARADC_CMD_MAGIC + 1, + SARADC_CMD_SET_CHANNEL, + SARADC_CMD_SET_SAMPLE_RATE, + SARADC_CMD_SET_WAITING_TIME, + SARADC_CMD_SET_VALID_MODE, + SARADC_CMD_CLEAR_INT, + SARADC_CMD_SET_CLK_RATE, + SARADC_CMD_RUN_OR_STOP_ADC, + SARADC_CMD_SET_CAL_VAL, + SARADC_CMD_SET_BYPASS_CALIB, + SARADC_CMD_SET_SAT_CTRL, + SARADC_CMD_PAUSE, + SARADC_CMD_RESUME, +}; + +typedef enum +{ + SARADC_CALIBRATE_LOW, + SARADC_CALIBRATE_HIGH +} SARADC_MODE; + +#define ADC_CONFIG_MODE_SLEEP (0x00UL) +#define ADC_CONFIG_MODE_STEP (0x01UL) +#define ADC_CONFIG_MODE_SOFT_CTRL (0x02UL) +#define ADC_CONFIG_MODE_CONTINUE (0x03UL) + +#define ADC_CONFIG_MODE_4CLK_DELAY (0x0UL) +#define ADC_CONFIG_MODE_8CLK_DELAY (0x1UL) +#define ADC_CONFIG_MODE_SHOULD_OFF (1 << 3) + +typedef struct +{ + UINT16 *pData; + volatile UINT8 current_sample_data_cnt; + volatile UINT8 current_read_data_cnt; + UINT8 data_buff_size; + volatile UINT8 has_data; /* 1: has data 0: no data*/ + volatile UINT8 all_done; /* 1: all done 0: still sampling*/ + UINT8 channel; + /* mode: ADC mode + * bit[0:1]: ADC operation mode + * 00: ADC power down mode + * 01: ADC one-step mode + * 10: ADC software control mode + * 11: ADC continuous mode + * bit[2:2]: delay clk(adc setting) + * 0: delay 4 clk + * 1: delay 8 clk + * bit[7:3]: reserved + */ + UINT8 mode; + void (*p_Int_Handler)(void); + unsigned char pre_div; // ADC pre-divide clk + unsigned char samp_rate; // ADC sample rate + unsigned char filter; //ADC filter +} saradc_desc_t; + +typedef struct +{ + UINT8 enable; + UINT8 channel; +} saradc_chan_t; + +typedef struct +{ + unsigned short val; + SARADC_MODE mode; +} saradc_cal_val_t; + +typedef struct _saradc_calibrate_val_ +{ + unsigned short low; + unsigned short high; +} saradc_calibrate_val; + + +/******************************************************************************* +* Function Declarations +*******************************************************************************/ +void saradc_disable(void); +void saradc_init(void); +void saradc_exit(void); +void saradc_isr(void); +float saradc_calculate(UINT16 adc_val); +void saradc_config_param_init(saradc_desc_t * adc_config); +void saradc_ensure_close(void); + +extern saradc_calibrate_val saradc_val; +#endif //_SARADC_PUB_H_ diff --git a/beken_os/beken378/driver/include/sdio_pub.h b/beken_os/beken378/driver/include/sdio_pub.h new file mode 100755 index 0000000..0f79b94 --- /dev/null +++ b/beken_os/beken378/driver/include/sdio_pub.h @@ -0,0 +1,58 @@ +#ifndef _SDIO_PUB_H_ +#define _SDIO_PUB_H_ + +#include "doubly_list.h" + + +//#define SDIO_TEST + +#define SDIO_DEV_NAME "sdio" + +#define SDIO_FAILURE ((UINT32)-1) +#define SDIO_SUCCESS (0) + +#define BLOCK_LEN (512 * 8) + +#define H2S_RD_SYNC (1) +#define H2S_WR_SYNC (2) +#define H2S_RD_SPECIAL (5) + +#define S2H_WR_SPECIAL (6) +#define S2H_RD_SYNC (3) +#define S2H_WR_SYNC (4) + +#define SDIO_DUMMY_BUFF_ADDR (0x100) +#define SDIO_DUMMY_LENGTH (0x100) + +#define SDIO_CMD_GET_FREE_NODE (0xBB) +#define SDIO_CMD_REG_RX_CALLBACK (0xBC) +#define SDIO_CMD_PUSH_FREE_NODE (0xBD) +#define SDIO_CMD_GET_CNT_FREE_NODE (0xBE) +#define SDIO_CMD_CLEAR_TX_VALID (0xC0) +#define SDIO_CMD_SET_TX_VALID (0xC1) +#define SDIO_CMD_PEEK_H2S_COUNT (0xC2) +#define SDIO_CMD_PEEK_S2H_COUNT (0xC3) + +typedef void (*SDIO_FUNC)(void *Lparam, void *Rparam); + +typedef struct _sdio_mem_node_ +{ + LIST_HEADER_T node_list; + + UINT8 *orig_addr; + + UINT8 *addr; + UINT32 length; + + SDIO_FUNC callback; + void *Lparam; + void *Rparam; +} SDIO_NODE_T, *SDIO_NODE_PTR; + +/******************************************************************************* +* Function Declarations +*******************************************************************************/ +extern void sdio_init(void); +extern void sdio_exit(void); + +#endif // _SDIO_PUB_H_ diff --git a/beken_os/beken378/driver/include/spi_pub.h b/beken_os/beken378/driver/include/spi_pub.h new file mode 100755 index 0000000..7c198c6 --- /dev/null +++ b/beken_os/beken378/driver/include/spi_pub.h @@ -0,0 +1,189 @@ +#ifndef _SPI_PUB_H_ +#define _SPI_PUB_H_ + +#define SPI_FAILURE (1) +#define SPI_SUCCESS (0) + +#define SPI_DEV_NAME "spi" +#define SPI2_DEV_NAME "spi2" +#define SPI3_DEV_NAME "spi3" + + +#define SPI_CMD_MAGIC (0xe250000) +enum +{ + CMD_SPI_UNIT_ENABLE = SPI_CMD_MAGIC + 1, + CMD_SPI_SET_MSTEN, + CMD_SPI_SET_CKPHA, + CMD_SPI_SET_CKPOL, + CMD_SPI_SET_BITWIDTH, + CMD_SPI_SET_NSSMD, + CMD_SPI_SET_CKR, + CMD_SPI_RXINT_EN, + CMD_SPI_TXINT_EN, + CMD_SPI_RXOVR_EN, + CMD_SPI_TXOVR_EN, + CMD_SPI_RXFIFO_CLR, + CMD_SPI_RXINT_MODE, + CMD_SPI_TXINT_MODE, + CMD_SPI_INIT_MSTEN, + CMD_SPI_GET_BUSY, + CMD_SPI_SET_RX_CALLBACK, + CMD_SPI_SET_TX_NEED_WRITE_CALLBACK, + CMD_SPI_SET_TX_FINISH_CALLBACK, + CMD_SPI_DEINIT_MSTEN, + CMD_SPI_LSB_EN, + CMD_SPI_TX_EN, + CMD_SPI_RX_EN, + CMD_SPI_TXFINISH_EN, + CMD_SPI_RXFINISH_EN, + CMD_SPI_TXTRANS_EN, + CMD_SPI_RXTRANS_EN, + CMD_SPI_CS_EN, + CMD_SPI_SET_TX_FINISH_INT_CALLBACK, + CMD_SPI_SET_RX_FINISH_INT_CALLBACK, + CMD_SPI_SET_3_LINE, +}; + +#define BK_SPI_DEBUG 0 +#include "uart_pub.h" +#if BK_SPI_DEBUG +#define BK_SPI_PRT null_prf +#define BK_SPI_WPRT warning_prf +#define BK_SPI_FATAL fatal_prf +#else +#define BK_SPI_PRT null_prf +#define BK_SPI_WPRT null_prf +#define BK_SPIFATAL null_prf +#endif + +#define USE_SPI_GPIO_14_17 (0) +#define USE_SPI_GPIO_30_33 (1) +#define USE_SPI_GPIO_NUM USE_SPI_GPIO_14_17 +#define SPI_FLASH_WP_GPIO_NUM (GPIO18) +#define SPI_FLASH_HOLD_GPIO_NUM (GPIO19) + +#define SPI_DEF_CLK_HZ (10 * 1000 * 1000) +#define TX_FINISH_FLAG (1 << 0) +#define RX_FINISH_FLAG (1 << 1) + + +#define BK_SPI_CPOL 0x01 +#define BK_SPI_CPHA 0x02 +#define SPI_DEF_MODE (~((BK_SPI_CPOL)|(BK_SPI_CPHA))) + +#define SPI_CPHA (1<<0) /* bit[0]:CPHA, clock phase */ +#define SPI_CPOL (1<<1) /* bit[1]:CPOL, clock polarity */ + +#define SPI_LSB (0<<2) /* bit[2]: 0-LSB */ +#define SPI_MSB (1<<2) /* bit[2]: 1-MSB */ + +#define SPI_MASTER (0<<3) /* SPI master device */ +#define SPI_SLAVE (1<<3) /* SPI slave device */ + +#define SPI_MODE_0 (0 | 0) /* CPOL = 0, CPHA = 0 */ +#define SPI_MODE_1 (0 | SPI_CPHA) /* CPOL = 0, CPHA = 1 */ +#define SPI_MODE_2 (SPI_CPOL | 0) /* CPOL = 1, CPHA = 0 */ +#define SPI_MODE_3 (SPI_CPOL | SPI_CPHA) /* CPOL = 1, CPHA = 1 */ + +struct spi_message +{ +#if (CFG_SOC_NAME != SOC_BK7231N) && (CFG_SOC_NAME != SOC_BK7236) + UINT8 *send_buf; + UINT32 send_len; + + UINT8 *recv_buf; + UINT32 recv_len; +#else + UINT8*send_buf; + UINT32 send_len; + + UINT8*recv_buf; + UINT32 recv_len; + +#endif +}; + +/** + * SPI configuration structure + */ +struct spi_configuration +{ + UINT8 mode; + UINT8 data_width; + UINT16 reserved; + UINT32 max_hz; +}; + +typedef void (*spi_callback)(int port, void *param); +struct spi_callback_des +{ + spi_callback callback; + void *param; +}; + +/******************************************************************************* +* Function Declarations +*******************************************************************************/ +UINT32 spi_read_rxfifo(UINT8 *data); +UINT32 spi_write_txfifo(UINT8 data); + +void spi_init(void); +void spi_exit(void); +void spi_isr(void); + +#if (CFG_SOC_NAME == SOC_BK7271) +void spi_channel_set(UINT8 channel ); +void spi2_init(void); +void spi2_exit(void); +void spi2_isr(void); +void spi3_init(void); +void spi3_exit(void); +void spi3_isr(void); +#endif + +/*slave api*/ +int bk_spi_slave_init(UINT32 rate, UINT32 mode); +int bk_spi_slave_xfer(struct spi_message *msg); +int bk_spi_slave_deinit(void); + +/*master api*/ +int bk_spi_master_init(UINT32 rate,UINT32 mode); +int bk_spi_master_xfer(struct spi_message *msg); +int bk_spi_master_deinit(void); + +#if CFG_USE_SPI_DMA +int bk_spi_master_dma_init(UINT32 mode, UINT32 rate, UINT32 flag); +int bk_spi_master_dma_rx_init(UINT32 mode , UINT32 rate); +int bk_spi_master_dma_tx_init(UINT32 mode , UINT32 rate); +int bk_spi_master_dma_recv(struct spi_message*spi_msg ); +int bk_spi_master_dma_send(struct spi_message*spi_msg ); +int bk_spi_master_dma_xfer(struct spi_message *spi_msg); +int bk_spi_get_status(void); + +int bk_spi_slave_dma_rx_init(UINT32 mode , UINT32 rate, struct spi_message*spi_msg ); +int bk_spi_slave_dma_tx_init(UINT32 mode , UINT32 rate, struct spi_message*spi_msg ); +int bk_spi_slave_dma_send(struct spi_message*spi_msg ); +int bk_spi_slave_dma_recv(struct spi_message*spi_msg ); + +void bk_master_dma_tx_disable(void); +void bk_master_dma_rx_disable(void); +void bk_slave_dma_tx_disable(void); +void bk_slave_dma_rx_disable(void); + + +//void bk_master_dma_tx_finshed_callback(void (*func)(void)); +//void bk_master_dma_rx_finshed_callback(void (*func)(void)); + +//Register spi interrupt callback +void bk_spi_tx_isr_callback(void (*func)(void)); +void bk_dma_tx_isr_callback(void (*func)(void)); +void bk_spi_rx_isr_callback(void (*func)(void)); +void bk_dma_rx_isr_callback(void (*func)(void)); + + + + + +#endif +#endif //_SPI_PUB_H_ diff --git a/beken_os/beken378/driver/include/sys_ctrl_pub.h b/beken_os/beken378/driver/include/sys_ctrl_pub.h new file mode 100755 index 0000000..6d43c7f --- /dev/null +++ b/beken_os/beken378/driver/include/sys_ctrl_pub.h @@ -0,0 +1,298 @@ +#ifndef _SCTRL_PUB_H_ +#define _SCTRL_PUB_H_ + +#define SCTRL_DEV_NAME "sys_ctrl" + +#define SCTRL_FAILURE ((UINT32)-1) +#define SCTRL_SUCCESS (0) + +#define SCTRL_CMD_MAGIC (0xC123000) + +enum +{ + CMD_GET_CHIP_ID = SCTRL_CMD_MAGIC + 1, + CMD_GET_DEVICE_ID = SCTRL_CMD_MAGIC + 2, + CMD_GET_SCTRL_CONTROL, + CMD_SET_SCTRL_CONTROL, + + CMD_SCTRL_MCLK_SELECT, + CMD_SCTRL_MCLK_DIVISION, + CMD_SCTRL_MCLK_MUX_GET, + CMD_SCTRL_MCLK_DIV_GET, + CMD_SCTRL_MCLK_LIMIT_FREQ_BIT_SET, + CMD_SCTRL_MCLK_LIMIT_FREQ_BIT_CLR, + + CMD_SCTRL_RESET_SET, + CMD_SCTRL_RESET_CLR, + CMD_SCTRL_MODEM_CORE_RESET, + CMD_SCTRL_MPIF_CLK_INVERT, + CMD_SCTRL_MODEM_SUBCHIP_RESET, + CMD_SCTRL_MAC_SUBSYS_RESET, + CMD_SCTRL_USB_SUBSYS_RESET, + CMD_SCTRL_DSP_SUBSYS_RESET, + CMD_SCTRL_BLK_ENABLE, + CMD_SCTRL_BLK_DISABLE, + CMD_SCTRL_DPLL_DIV_RESET, + + CMD_SCTRL_DSP_POWERDOWN, + CMD_SCTRL_DSP_POWERUP, + CMD_SCTRL_USB_POWERDOWN, + CMD_SCTRL_USB_POWERUP, + CMD_SCTRL_MAC_POWERDOWN, + CMD_SCTRL_MAC_POWERUP, + CMD_SCTRL_MODEM_POWERDOWN, + CMD_SCTRL_MODEM_POWERUP, + CMD_SCTRL_BLE_POWERDOWN, + CMD_SCTRL_BLE_POWERUP, + + CMD_SCTRL_CALI_DPLL, + + CMD_SCTRL_BIAS_REG_SET, + CMD_SCTRL_BIAS_REG_CLEAN, + CMD_SCTRL_BIAS_REG_READ, + CMD_SCTRL_BIAS_REG_WRITE, + + CMD_SCTRL_ANALOG_CTRL4_SET, + CMD_SCTRL_ANALOG_CTRL4_CLEAN, + + CMD_SCTRL_SET_FLASH_DCO, + CMD_SCTRL_SET_FLASH_DPLL, + CMD_SCTRL_NORMAL_SLEEP, + CMD_SCTRL_NORMAL_WAKEUP, + CMD_SCTRL_RTOS_IDLE_SLEEP, + CMD_SCTRL_RTOS_IDLE_WAKEUP, + CMD_SCTRL_RTOS_DEEP_SLEEP, + + #if (CFG_SOC_NAME != SOC_BK7231) + CMD_SCTRL_SET_XTALH_CTUNE, + CMD_SCTRL_GET_XTALH_CTUNE, + CMD_BLE_RF_BIT_SET, + CMD_BLE_RF_BIT_CLR, + CMD_BLE_RF_BIT_GET, + #if (CFG_SOC_NAME == SOC_BK7231N) + CMD_BLE_RF_PTA_EN, + CMD_BLE_RF_PTA_DIS, + #endif + CMD_EFUSE_WRITE_BYTE, + CMD_EFUSE_READ_BYTE, + CMD_GET_SCTRL_RETETION, + CMD_SET_SCTRL_RETETION, + #endif // (CFG_SOC_NAME != SOC_BK7231) + + CMD_SCTRL_SET_ANALOG0, + CMD_SCTRL_SET_ANALOG1, + CMD_SCTRL_SET_ANALOG2, + CMD_SCTRL_SET_ANALOG3, + CMD_SCTRL_SET_ANALOG4, + CMD_SCTRL_SET_ANALOG5, + CMD_SCTRL_SET_ANALOG6, + CMD_SCTRL_SET_ANALOG7, + CMD_SCTRL_SET_ANALOG8, + CMD_SCTRL_SET_ANALOG9, + CMD_SCTRL_SET_ANALOG10, + CMD_SCTRL_GET_ANALOG0, + CMD_SCTRL_GET_ANALOG1, + CMD_SCTRL_GET_ANALOG2, + CMD_SCTRL_GET_ANALOG3, + CMD_SCTRL_GET_ANALOG4, + CMD_SCTRL_GET_ANALOG5, + CMD_SCTRL_GET_ANALOG6, + CMD_SCTRL_GET_ANALOG7, + CMD_SCTRL_GET_ANALOG8, + CMD_SCTRL_GET_ANALOG9, + CMD_SCTRL_GET_ANALOG10, + #if (CFG_SOC_NAME == SOC_BK7221U) + CMD_SCTRL_OPEN_DAC_ANALOG, + CMD_SCTRL_CLOSE_DAC_ANALOG, + CMD_SCTRL_OPEN_ADC_MIC_ANALOG, + CMD_SCTRL_CLOSE_ADC_MIC_ANALOG, + CMD_SCTRL_ENALBLE_ADC_LINE_IN, + CMD_SCTRL_DISALBLE_ADC_LINE_IN, + CMD_SCTRL_SET_DAC_VOLUME_ANALOG, + CMD_SCTRL_SET_LINEIN_VOLUME_ANALOG, + + #endif // (CFG_SOC_NAME == SOC_BK7221) + CMD_SCTRL_SET_LOW_PWR_CLK, + CMD_SCTRL_SET_GADC_SEL, + CMD_SCTRL_SET_VDD_VALUE, + CMD_SCTRL_GET_VDD_VALUE, +}; + +/*CMD_SCTRL_MCLK_SELECT*/ +#define MCLK_SELECT_DCO (0x0) +#define MCLK_SELECT_26M_XTAL (0x1) +#define MCLK_SELECT_DPLL (0x2) +#define MCLK_SELECT_LPO (0x3) + +/*CMD_SCTRL_BLK_ENABLE CMD_SCTRL_BLK_DISABLE*/ +#if (CFG_SOC_NAME == SOC_BK7231) +#define BLK_BIT_LINEIN (1 << 19) +#define BLK_BIT_MIC_R_CHANNEL (1 << 18) +#define BLK_BIT_MIC_L_CHANNEL (1 << 17) +#define BLK_BIT_AUDIO_R_CHANNEL (1 << 16) +#define BLK_BIT_AUDIO_L_CHANNEL (1 << 15) +#define BLK_BIT_USB (1 << 14) +#elif (CFG_SOC_NAME == SOC_BK7231U) +#define BLK_BIT_NC (1 << 19) +#define BLK_BIT_MIC_QSPI_RAM_OR_FLASH (1 << 18) +#define BLK_BIT_MIC_PGA (1 << 17) +#define BLK_BIT_AUDIO_PLL (1 << 16) +#define BLK_BIT_AUDIO_RANDOM_GENERATOR (1 << 15) +#define BLK_BIT_USB (1 << 14) +#elif (CFG_SOC_NAME == SOC_BK7231N) +#define BLK_BIT_AUDIO_RANDOM_GENERATOR (1 << 15) +#elif (CFG_SOC_NAME == SOC_BK7221U) +#define BLK_BIT_NC (1 << 19) +#define BLK_BIT_MIC_QSPI_RAM_OR_FLASH (1 << 18) +#define BLK_BIT_AUDIO (1 << 17) +#define BLK_BIT_AUDIO_PLL (1 << 16) +#define BLK_BIT_AUDIO_RANDOM_GENERATOR (1 << 15) +#define BLK_BIT_USB (1 << 14) +#endif // (CFG_SOC_NAME == SOC_BK7231) +#define BLK_BIT_SARADC (1 << 13) +#define BLK_BIT_TEMPRATURE_SENSOR (1 << 12) +#define BLK_BIT_26M_XTAL_LOW_POWER (1 << 11) +#define BLK_BIT_XTAL2RF (1 << 10) +#define BLK_BIT_IO_LDO_LOW_POWER (1 << 09) +#define BLK_BIT_ANALOG_SYS_LDO (1 << 08) +#define BLK_BIT_DIGITAL_CORE_LDO_LOW_POWER (1 << 07) +#define BLK_BIT_DIGITAL_CORE (1 << 06) +#define BLK_BIT_DPLL_480M (1 << 05) +#define BLK_BIT_32K_XTAL (1 << 04) +#define BLK_BIT_26M_XTAL (1 << 03) +#define BLK_BIT_ROSC32K (1 << 02) +#define BLK_BIT_DCO (1 << 01) +#define BLK_BIT_FLASH (1 << 00) + +/* CMD_SCTRL_RESET _SET/_CLR*/ +#define PARAM_MODEM_CORE_RESET_BIT (1 << 6) +#define PARAM_TL410_EXT_WAIT_BIT (1 << 5) +#define PARAM_USB_SUBSYS_RESET_BIT (1 << 4) +#define PARAM_TL410_BOOT_BIT (1 << 3) +#define PARAM_MAC_SUBSYS_RESET_BIT (1 << 2) +#define PARAM_DSP_SUBSYS_RESET_BIT (1 << 1) +#define PARAM_MODEM_SUBCHIP_RESET_BIT (1 << 0) + +/* CMD_GET_SCTRL_CONTROL CMD_SET_SCTRL_CONTROL*/ +#define MCLK_MODE_DCO (0x0) +#define MCLK_MODE_26M_XTAL (0x1) +#define MCLK_MODE_DPLL (0x2) +#define MCLK_MODE_LPO (0x3) + +/*CMD_SCTRL_BIAS_REG_SET CMD_SCTRL_BIAS_REG_CLEAN*/ +#define PARAM_BIAS_CAL_OUT_POSI (16) +#define PARAM_BIAS_CAL_OUT_MASK (0x1F) +#define PARAM_LDO_VAL_MANUAL_POSI (8) +#define PARAM_LDO_VAL_MANUAL_MASK (0x1F) +#define PARAM_BIAS_CAL_MANUAL_BIT (1 << 4) +#define PARAM_BIAS_CAL_TRIGGER_BIT (1 << 0) + +/*CMD_SCTRL_ANALOG_CTRL4_SET CMD_SCTRL_ANALOG_CTRL4_CLEAN*/ +#define PARAM_VSEL_SYS_LDO_POSI (27) +#define PARAM_VSEL_SYS_LDO_MASK (0x3) + +#if (CFG_SOC_NAME == SOC_BK7231U) +#define DEFAULT_TXID_XTAL (0x19) +#elif (CFG_SOC_NAME == SOC_BK7231N) +#if (CFG_XTAL_FREQUENCE == CFG_XTAL_FREQUENCE_40M) +#define DEFAULT_TXID_XTAL (0x70) +#else +#define DEFAULT_TXID_XTAL_C (0x0C)//(12) +#define DEFAULT_TXID_XTAL (0x26)//(38) +#endif +#elif (CFG_SOC_NAME == SOC_BK7221U) +#define DEFAULT_TXID_XTAL (0x08) +#endif // (CFG_SOC_NAME == SOC_BK7231U) + +#if (CFG_SOC_NAME == SOC_BK7231N) +#define PARAM_XTALH_CTUNE_MASK (0x7F) + +#define PARAM_AUD_DAC_GAIN_MASK (0x1F) +#elif (CFG_SOC_NAME != SOC_BK7231) +#define PARAM_XTALH_CTUNE_MASK (0x3F) + +#define PARAM_AUD_DAC_GAIN_MASK (0x1F) +#endif // (CFG_SOC_NAME != SOC_BK7231) + +/*CMD_SCTRL_SET_LOW_PWR_CLK*/ +#define LPO_SELECT_ROSC (0x0) +#define LPO_SELECT_32K_XTAL (0x1) +#define LPO_SELECT_32K_DIV (0x2) + +#if (CFG_SOC_NAME == SOC_BK7231N) +#define SW_RETENTION_WDT_FLAG (1 << 16) +#define SW_RETENTION_WDT_FLAG_POS (16) +#define SW_RETENTION_VAL_MASK (0XFFFF) +#define SW_RETENTION_VAL_POS (0) +#endif + +typedef union +{ + UINT32 val; + struct + { + UINT32 mclk_mux: 2; + UINT32 resv0: 2; + UINT32 mclk_div: 4; + UINT32 flash_26m_select: 1; + UINT32 hclk_div2_en: 1; + UINT32 modem_clk480m_pwd: 1; + UINT32 mac_clk480m_pwd: 1; + UINT32 mpif_clk_inv: 1; + UINT32 sdio_clk_inv: 1; + UINT32 resv1: 18; + } bits; +} SYS_CTRL_U; + +typedef struct efuse_oper_st +{ + UINT8 addr; + UINT8 data; +} EFUSE_OPER_ST, *EFUSE_OPER_PTR; + +#define EFUSE_ENCRYPT_WORD_ADDR (0) +#define EFUSE_ENCRYPT_WORD_LEN (16) +#define EFUSE_UID_ADDR (16) +#define EFUSE_UID_LEN (8) +#define EFUSE_MAC_START_ADDR (24) +#define EFUSE_MAC_LEN (6) +#define EFUSE_USER_AREA_ADDR (30) +#define EFUSE_USER_AREA_LEN (1) +#define EFUSE_CTRL_ADDR (31) +#define EFUSE_USER_AREA_LEN (1) +#define EFUSE_INIT_VAL (0x0) + +#define EFUSE_CTRL_JTAG_DISABLE (1 << 7) +#define EFUSE_CTRL_FLASH_DOWNLOAD_DISABLE (1 << 6) +#define EFUSE_CTRL_ENCRYPT_EN (1 << 5) +#define EFUSE_CTRL_ENCRYPT_DISABLE_READ (1 << 4) +#define EFUSE_CTRL_ENCRYPT_DISABLE_WRITE (1 << 3) +#define EFUSE_CTRL_UID_DISABLE_WRITE (1 << 2) +#define EFUSE_CTRL_MAC_DISABLE_WRITE (1 << 1) +#define EFUSE_CTRL_ALL_AREA_DISABLE_WRITE (1 << 0) + + +#define LIMIT_FREQ_MCU_PS_BIT (1 << 0) +#define LIMIT_FREQ_LOW_TEMPRATURE_BIT (1 << 1) + +/******************************************************************************* +* Function Declarations +*******************************************************************************/ +extern void sctrl_init(void); +extern void sctrl_exit(void); + +extern void sctrl_normal_exit_sleep(void); +extern void sctrl_normal_enter_sleep(UINT32 peri_clk); +extern void sctrl_mcu_exit(void); +extern void sctrl_mcu_init(void); +extern void sctrl_mcu_sleep(UINT32 ); +extern UINT32 sctrl_mcu_wakeup(void); +extern void sctrl_ps_dump(); +extern void sctrl_rf_sleep(void); +extern void sctrl_rf_wakeup(void); +extern void sctrl_sta_ps_init(void); +extern void sctrl_flash_select_dco(void); +extern UINT8 sctrl_if_rf_sleep(void); +extern int bk_misc_wakeup_get_gpio_num(void); +extern UINT32 sctrl_get_deep_sleep_gpio_floating_map(void); +#endif // _SCTRL_PUB_H_ diff --git a/beken_os/beken378/driver/include/uart_pub.h b/beken_os/beken378/driver/include/uart_pub.h new file mode 100755 index 0000000..eb18491 --- /dev/null +++ b/beken_os/beken378/driver/include/uart_pub.h @@ -0,0 +1,129 @@ +#ifndef _UART_PUB_H +#define _UART_PUB_H + +#include +#include "include.h" +#if CFG_SUPPORT_ALIOS +#include "hal/soc/soc.h" +#endif + +#define os_printf bk_printf + +#define warning_prf bk_printf +#define fatal_prf bk_printf +#define null_prf os_null_printf + +#define UART_SUCCESS (0) +#define UART_FAILURE ((UINT32)-1) + +#define UART2_DEV_NAME ("uart2") /*debug purpose*/ +#define UART1_DEV_NAME ("uart1") /*comm purpose*/ + +#define UART_CMD_MAGIC (0xC124000) + +#define UART1_PORT 0 +#define UART2_PORT 1 + +enum +{ + CMD_SEND_BACKGROUND = UART_CMD_MAGIC + 0, + CMD_UART_RESET = UART_CMD_MAGIC + 1, + CMD_RX_COUNT, + CMD_RX_PEEK, + CMD_UART_INIT, + CMD_UART_SET_RX_CALLBACK, + CMD_UART_SET_TX_CALLBACK, + CMD_SET_STOP_END, + CMD_UART_SET_TX_FIFO_NEEDWR_CALLBACK, + CMD_SET_TX_FIFO_NEEDWR_INT, + CMD_DISABLE_UART_RX, +}; + +/* CMD_RX_PEEK*/ +#define URX_PEEK_SIG (0x0ee) + +typedef struct _peek_rx_ +{ + UINT32 sig; + + UINT32 len; + void *ptr; +} UART_PEEK_RX_T, *UART_PEEK_RX_PTR; + +typedef void (*uart_callback)(int uport, void *param); + +typedef struct uart_callback_des +{ + uart_callback callback; + void *param; +}UART_CALLBACK_RX_T, *UART_CALLBACK_RX_PTR; + +#if (!CFG_SUPPORT_ALIOS) +/** + * UART data width + */ +typedef enum +{ + DATA_WIDTH_5BIT, + DATA_WIDTH_6BIT, + DATA_WIDTH_7BIT, + DATA_WIDTH_8BIT +} uart_data_width_t; + +/** + * UART stop bits + */ +typedef enum +{ + BK_STOP_BITS_1, + BK_STOP_BITS_2, +} uart_stop_bits_t; + +/** + * UART flow control + */ +typedef enum +{ + FLOW_CTRL_DISABLED, + FLOW_CTRL_CTS, + FLOW_CTRL_RTS, + FLOW_CTRL_RTS_CTS +} uart_flow_control_t; + +/** + * UART parity + */ +typedef enum +{ + BK_PARITY_NO, + BK_PARITY_ODD, + BK_PARITY_EVEN, +} uart_parity_t; +#endif +/******************************************************************************* +* Function Declarations +*******************************************************************************/ +extern void uart1_init(void); +extern void uart1_exit(void); +extern void uart1_isr(void); + +extern void uart2_init(void); +extern void uart2_exit(void); +extern void uart2_isr(void); + +//extern INT32 os_null_printf(const char *fmt, ...); +#define os_null_printf(...) +extern void fatal_print(const char *fmt, ...); +extern void bk_printf(const char *fmt, ...); +extern void uart_send_byte(UINT8 ch, UINT8 data); +extern void bk_send_string(UINT8 uport, const char *string); +extern void uart_wait_tx_over(); +extern UINT8 uart_is_tx_fifo_empty(UINT8 uport); +extern UINT8 uart_is_tx_fifo_full(UINT8 uport); +extern int uart_read_byte(int uport); +extern int uart_write_byte(int uport, char c); +extern void print_hex_dump(const char *prefix, void *b, int len); +extern void bk_send_string(UINT8 uport, const char *string); +extern UINT8 get_printf_port(void); +#endif // _UART_PUB_H + diff --git a/beken_os/beken378/driver/include/usb_pub.h b/beken_os/beken378/driver/include/usb_pub.h new file mode 100755 index 0000000..1e2789a --- /dev/null +++ b/beken_os/beken378/driver/include/usb_pub.h @@ -0,0 +1,113 @@ +#ifndef _USB_PUB_H_ +#define _USB_PUB_H_ + +#include "include.h" + +#define UVC_DEMO_SUPPORT102 + +#define USB_FAILURE (1) +#define USB_SUCCESS (0) + +#define USB_DEV_NAME "usb" + +typedef void (*USB_FPTR)(void *, void *); + +#define USB_CMD_MAGIC (0xe550000) +enum +{ + UCMD_RESET = USB_CMD_MAGIC + 1, + + UCMD_MSC_REGISTER_FIDDLE_CB, + UCMD_UVC_REGISTER_CONFIG_NOTIFY_CB, + UCMD_UVC_REGISTER_RX_VSTREAM_CB, + UCMD_UVC_REGISTER_RX_VSTREAM_BUF_PTR, + UCMD_UVC_REGISTER_RX_VSTREAM_BUF_LEN, + + UCMD_UVC_SET_PARAM, + UCMD_UVC_START_STREAM, + UCMD_UVC_STOP_STREAM, + UCMD_UVC_GET_CONNECT_STATUS, + UCMD_UVC_RECEIVE_VSTREAM, + UCMD_UVC_ENABLE_MJPEG, + UCMD_UVC_ENABLE_H264, + + UCMD_USB_CONNECTED_REGISTER_CB +}; + +/*UCMD_UVC_SET_PARAM*/ +#define UVC_MUX_PARAM(resolution_id, fps) (fps + (resolution_id << 16)) +#define UVC_DEMUX_FPS(param) (param & 0xffff) +#define UVC_DEMUX_ID(param) ((param >> 16) & 0xffff) + +typedef enum +{ + USB_HOST_MODE = 0, + USB_DEVICE_MODE = 1 +} USB_MODE; + +/* + * The value is defined in field wWidth and wHeight in 'Video Streaming MJPEG +Frame Type Descriptor' + */ +#ifdef UVC_DEMO_SUPPORT100 +typedef enum +{ + U2_FRAME_640_480 = 1, + U2_FRAME_640_360 = 2, + U2_FRAME_320_240 = 3, + U2_FRAME_168_120 = 4, +} E_FRAME_ID_USB20; + +typedef enum +{ + U1_FRAME_640_480 = 1, + U1_FRAME_160_120 = 2, +} E_FRAME_ID_USB11; +#elif defined(UVC_DEMO_SUPPORT102) +typedef enum +{ + UVC_FRAME_352_288 = 0, + UVC_FRAME_320_240 = 1, + UVC_FRAME_640_360 = 2, + UVC_FRAME_640_480 = 3, + UVC_FRAME_COUNT +} E_FRAME_ID_USB20; +#endif + +typedef enum +{ + FPS_30 = 30, + FPS_25 = 25, + FPS_20 = 20, + FPS_15 = 15, + FPS_10 = 10, + FPS_5 = 5, +} E_FRAME_RATE_ID; + +/* +* Finish DRC interrupt processing +*/ +enum +{ + BSR_NONE_EVENT = 0, + BSR_ERROR_EVENT, + BSR_CONNECT_EVENT, + BSR_CONNECTED_EVENT, + + BSR_DISCONNECT_EVENT, + BSR_READ_OK_EVENT +}; + +/******************************************************************************* +* Function Declarations +*******************************************************************************/ +extern void usb_init(void); +extern void usb_exit(void); +extern uint32_t MUSB_HfiRead( uint32_t first_block, uint32_t block_num, uint8_t + *dest); +extern uint32_t MUSB_HfiWrite( uint32_t first_block, uint32_t block_num, uint8_t + *dest); +extern void MGC_RegisterCBTransferComplete(FUNCPTR func); +extern uint8_t MUSB_GetConnect_Flag(void); +#endif //_USB_PUB_H_ + diff --git a/beken_os/beken378/driver/include/wdt_pub.h b/beken_os/beken378/driver/include/wdt_pub.h new file mode 100755 index 0000000..cc07061 --- /dev/null +++ b/beken_os/beken378/driver/include/wdt_pub.h @@ -0,0 +1,25 @@ +#ifndef _WDT_PUB_H_ +#define _WDT_PUB_H_ + +#define WDT_FAILURE (1) +#define WDT_SUCCESS (0) + +#define WDT_DEV_NAME "wdt" + +#define WDT_CMD_MAGIC (0xe330000) +enum +{ + WCMD_POWER_UP = WDT_CMD_MAGIC + 1, + WCMD_SET_PERIOD, + WCMD_RELOAD_PERIOD, + WCMD_POWER_DOWN +}; + +/******************************************************************************* +* Function Declarations +*******************************************************************************/ +extern void wdt_init(void); +extern void wdt_exit(void); + +#endif //_WDT_PUB_H_ + diff --git a/beken_os/beken378/driver/intc/intc.c b/beken_os/beken378/driver/intc/intc.c new file mode 100755 index 0000000..eedc875 --- /dev/null +++ b/beken_os/beken378/driver/intc/intc.c @@ -0,0 +1,441 @@ +/** + **************************************************************************************** + * + * @file intc.c + * + * @brief Definition of the Interrupt Controller (INTCTRL) API. + * + * Copyright (C) RivieraWaves 2011-2016 + * + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "compiler.h" +#include "intc.h" +#include "intc_pub.h" +#include "include.h" +#include "arm_arch.h" +#include "drv_model_pub.h" +#include "icu_pub.h" +#include "mem_pub.h" +#include "uart_pub.h" + +#if CFG_SUPPORT_ALIOS +#include "ll.h" + +extern void do_irq( void ); +extern void do_fiq( void ); +extern void do_swi( void ); +#else +#include "power_save_pub.h" +#endif +#include "start_type_pub.h" + +ISR_T _isrs[INTC_MAX_COUNT] = {{{0, 0}},}; +static UINT32 isrs_mask = 0; +static ISR_LIST_T isr_hdr = {{&isr_hdr.isr, &isr_hdr.isr},}; +IRDA_CHECK_FUNC func_irda_check = NULL; + +void intc_register_irda_check_func(IRDA_CHECK_FUNC func) +{ + func_irda_check = func; +} + +void intc_unregister_irda_check_func() +{ + func_irda_check = NULL; +} + +void intc_hdl_entry(UINT32 int_status) +{ + UINT32 i; + ISR_T *f; + UINT32 status; + LIST_HEADER_T *n; + LIST_HEADER_T *pos; + + status = int_status & isrs_mask; + INTC_PRT("intc:%x:%x\r\n", int_status, status); + + #if CFG_USE_STA_PS + power_save_dtim_wake(status); + #endif + + list_for_each_safe(pos, n, &isr_hdr.isr) + { + f = list_entry(pos, ISR_T, list); + i = f->int_num; + + if ((BIT(i) & status)) + { + f->isr_func(); + status &= ~(BIT(i)); + } + + if(0 == status) + { + return; + } + } +} + +void intc_service_register(UINT8 int_num, UINT8 int_pri, FUNCPTR isr) +{ + LIST_HEADER_T *pos, *n; + ISR_T *tmp_ptr, *cur_ptr; + ISR_T buf_ele; + + GLOBAL_INT_DECLARATION(); + + buf_ele = _isrs[int_num]; + cur_ptr = &_isrs[int_num]; + cur_ptr->isr_func = isr; + cur_ptr->int_num = int_num; + cur_ptr->pri = int_pri; + + INTC_PRT("reg_isr:%d:%d:%p\r\n", int_num, int_pri, isr); + + GLOBAL_INT_DISABLE(); + if (list_empty(&isr_hdr.isr)) + { + list_add_head(&cur_ptr->list, &isr_hdr.isr); + goto ok; + } + + /* Insert the ISR to the function list, this list is sorted by priority number */ + list_for_each_safe(pos, n, &isr_hdr.isr) + { + tmp_ptr = list_entry(pos, ISR_T, list); + + if (int_pri < tmp_ptr->pri) + { + /* add entry at the head of the queue */ + list_add_tail(&cur_ptr->list, &tmp_ptr->list); + + INTC_PRT("reg_isr_o1\r\n"); + + goto ok; + } + else if (int_pri == tmp_ptr->pri) + { + INTC_PRT("reg_isr_error\r\n"); + goto error; + } + } + + list_add_tail(&cur_ptr->list, &isr_hdr.isr); + INTC_PRT("reg_isr_o2\r\n"); + +ok: + isrs_mask |= BIT(int_num); + GLOBAL_INT_RESTORE(); + + return; +error: + /* something wrong */ + _isrs[int_num] = buf_ele; + GLOBAL_INT_RESTORE(); + + return; +} + +void intc_service_change_handler(UINT8 int_num, FUNCPTR isr) +{ + LIST_HEADER_T *pos, *n; + ISR_T *tmp_ptr, *cur_ptr; + ISR_T buf_ele; + UINT8 int_pri; + + GLOBAL_INT_DECLARATION(); + + buf_ele = _isrs[int_num]; + cur_ptr = &_isrs[int_num]; + int_pri = cur_ptr->pri; + + if(!cur_ptr->isr_func) + return; + + INTC_PRT("reg_isr:%d:%d:%p\r\n", int_num, int_pri, isr); + + GLOBAL_INT_DISABLE(); + if (list_empty(&isr_hdr.isr)) + { + goto exit; + } + + /* Insert the ISR to the function list, this list is sorted by priority number */ + list_for_each_safe(pos, n, &isr_hdr.isr) + { + tmp_ptr = list_entry(pos, ISR_T, list); + + if (int_pri == tmp_ptr->pri) + { + buf_ele.isr_func = isr; + break; + } + } + +exit: + /* something wrong */ + _isrs[int_num] = buf_ele; + GLOBAL_INT_RESTORE(); + + return; +} + +/* + * FUNCTION DEFINITIONS + **************************************************************************************** + */ +void intc_spurious(void) +{ + ASSERT(0); +} + +void intc_enable(int index) +{ + UINT32 param; + + param = (1UL << index); + sddev_control(ICU_DEV_NAME, CMD_ICU_INT_ENABLE, ¶m); +} + +void intc_disable(int index) +{ + UINT32 param; + + param = (1UL << index); + sddev_control(ICU_DEV_NAME, CMD_ICU_INT_DISABLE, ¶m); +} + +void rf_ps_wakeup_isr_idle_int_cb() +{ +#if ( CONFIG_APP_MP3PLAYER == 1 ) + UINT32 irq_status; + + irq_status = sddev_control(ICU_DEV_NAME, CMD_GET_INTR_STATUS, 0); + + if(irq_status & 1<r0, regs->r1, regs->r2, regs->r3); + os_printf("r4:0x%08x r5:0x%08x r6:0x%08x r7:0x%08x\n", + regs->r4, regs->r5, regs->r6, regs->r7); + os_printf("r8:0x%08x sb:0x%08x sl:0x%08x fp:0x%08x\n", + regs->r8, regs->r9, regs->r10, regs->fp); + os_printf("ip:0x%08x sp:0x%08x lr:0x%08x pc:0x%08x\n", + regs->ip, regs->sp, regs->lr, regs->pc); + os_printf("SPSR:0x%08x\n", regs->spsr); + os_printf("CPSR:0x%08x\n", regs->cpsr); + + int i; + const unsigned int *reg1; + + os_printf("\nseparate regs:\n"); + + reg1 = (const unsigned int *)0x400024; + os_printf("SYS:cpsr r8-r14\n"); + for(i=0;i<0x20>>2;i++) + { + os_printf("0x%08x\n",*(reg1 + i)); + } + + os_printf("%s:cpsr spsr r8-r14\n", "IRQ"); + reg1 = (const unsigned int *)0x400044; + for(i=0;i<0x24>>2;i++) + { + os_printf("0x%08x\n",*(reg1 + i)); + } + + os_printf("%s:cpsr spsr r8-r14\n", "FIR"); + reg1 = (const unsigned int *)0x400068; + for(i=0;i<0x24>>2;i++) + { + os_printf("0x%08x\n",*(reg1 + i)); + } + + os_printf("%s:cpsr spsr r8-r14\n", "ABT"); + reg1 = (const unsigned int *)0x40008c; + for(i=0;i<0x24>>2;i++) + { + os_printf("0x%08x\n",*(reg1 + i)); + } + + os_printf("%s:cpsr spsr r8-r14\n", "UND"); + reg1 = (const unsigned int *)0x4000b0; + for(i=0;i<0x24>>2;i++) + { + os_printf("0x%08x\n",*(reg1 + i)); + } + + os_printf("%s:cpsr spsr r8-r14\n", "SVC"); + reg1 = (const unsigned int *)0x4000d4; + for(i=0;i<0x24>>2;i++) + { + os_printf("0x%08x\n",*(reg1 + i)); + } + + os_printf("\r\n"); + +} + +void bk_trap_udef(struct arm_registers *regs) +{ +#if (CFG_SOC_NAME == SOC_BK7231N) + *((volatile uint32_t *)START_TYPE_ADDR) = (uint32_t)(CRASH_UNDEFINED_VALUE & 0xffff); +#else + *((volatile uint32_t *)START_TYPE_ADDR) = (uint32_t)CRASH_UNDEFINED_VALUE; +#endif + os_printf("undef instruction\n"); + bk_show_register(regs); + bk_cpu_shutdown(); +} + +void bk_trap_pabt(struct arm_registers *regs) +{ +#if (CFG_SOC_NAME == SOC_BK7231N) + *((volatile uint32_t *)START_TYPE_ADDR) = (uint32_t)(CRASH_PREFETCH_ABORT_VALUE & 0xffff); +#else + *((volatile uint32_t *)START_TYPE_ADDR) = (uint32_t)CRASH_PREFETCH_ABORT_VALUE; +#endif + os_printf("prefetch abort\n"); + bk_show_register(regs); + bk_cpu_shutdown(); +} + +void bk_trap_dabt(struct arm_registers *regs) +{ +#if (CFG_SOC_NAME == SOC_BK7231N) + *((volatile uint32_t *)START_TYPE_ADDR) = (uint32_t)(CRASH_DATA_ABORT_VALUE & 0xffff); +#else + *((volatile uint32_t *)START_TYPE_ADDR) = (uint32_t)CRASH_DATA_ABORT_VALUE; +#endif + os_printf("data abort\n"); + bk_show_register(regs); + bk_cpu_shutdown(); +} + +void bk_trap_resv(struct arm_registers *regs) +{ +#if (CFG_SOC_NAME == SOC_BK7231N) + *((volatile uint32_t *)START_TYPE_ADDR) = (uint32_t)(CRASH_UNUSED_VALUE & 0xffff); +#else + *((volatile uint32_t *)START_TYPE_ADDR) = (uint32_t)CRASH_UNUSED_VALUE; +#endif + os_printf("not used\n"); + bk_show_register(regs); + bk_cpu_shutdown(); +} + +/// @} diff --git a/beken_os/beken378/driver/intc/intc.h b/beken_os/beken378/driver/intc/intc.h new file mode 100755 index 0000000..fbbaaf8 --- /dev/null +++ b/beken_os/beken378/driver/intc/intc.h @@ -0,0 +1,95 @@ +/** + **************************************************************************************** + * + * @file intc.h + * + * @brief Declaration of the Reference Interrupt Controller (INTC) API. + * + * Copyright (C) RivieraWaves 2011-2016 + * + **************************************************************************************** + */ + +#ifndef _INTC_H_ +#define _INTC_H_ + +#include "compiler.h" +#include "doubly_list.h" +#include "generic.h" + +//#define INTC_DEBUG + +#ifdef INTC_DEBUG +#define INTC_PRT os_printf +#define INTC_WPRT warning_prf +#else +#define INTC_PRT os_null_printf +#define INTC_WPRT os_null_printf +#endif + +#define INTC_MAX_COUNT 32 + + +struct arm_registers +{ + uint32_t r0; + uint32_t r1; + uint32_t r2; + uint32_t r3; + uint32_t r4; + uint32_t r5; + uint32_t r6; + uint32_t r7; + uint32_t r8; + uint32_t r9; + uint32_t r10; + uint32_t fp; + uint32_t ip; + uint32_t sp; + uint32_t lr; + uint32_t pc; + uint32_t spsr; + uint32_t cpsr; +}; + +typedef struct +{ + LIST_HEADER_T list; + + FUNCPTR isr_func; + + UINT8 pri; // priority + UINT8 int_num; + UINT16 resv; +} ISR_T; + +typedef struct +{ + LIST_HEADER_T isr; + + UINT8 max; // maximum interrupt number + UINT8 min; // minum interrupt number +} ISR_LIST_T; +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ +/** + **************************************************************************************** + * @brief Initialize and configure the reference INTCTRL. + * This function configures the INTC according to the system needs. + **************************************************************************************** + */ +extern void intc_init(void); +extern void intc_irq(void); +extern void intc_fiq(void); +extern void do_irq( void ); +extern void do_fiq( void ); +extern void do_swi( void ); +extern void do_undefined( void ); +extern void do_pabort( void ); +extern void do_dabort( void ); +extern void do_reserved( void ); +extern void intc_service_change_handler(UINT8 int_num, FUNCPTR isr); + +#endif // _INTC_H_ diff --git a/beken_os/beken378/driver/irda/irda.c b/beken_os/beken378/driver/irda/irda.c new file mode 100755 index 0000000..ddfb2eb --- /dev/null +++ b/beken_os/beken378/driver/irda/irda.c @@ -0,0 +1,232 @@ +#include "include.h" +#include "arm_arch.h" + +#include "irda.h" +#include "irda_pub.h" + +#include "drv_model_pub.h" +#include "intc_pub.h" +#include "rtos_pub.h" + + +#define IR_MAP \ +{ \ + 0x0, /* KEY_play */ \ + 0x5, /* KEY_VOL- */ \ + 0x6, /* KEY_VOL+ */ \ + 0x9, /* KEY_PREV */ \ + 0xa, /* KEY_NEXT */ \ + 0x4, /* KEY_MODE */ \ + 0x1, /* KEY_CH- */ \ + 0x2, /* KEY_CH+ */ \ + 0x8, /* KEY_0 */ \ + 0xc, /* KEY_1 */ \ + 0xd, /* KEY_2 */ \ + 0xe, /* KEY_3 */ \ + 0x10, /* KEY_4 */ \ + 0x11, /* KEY_5 */ \ + 0x12, /* KEY_6 */ \ + 0x14, /* KEY_7 */ \ + 0x15, /* KEY_8 */ \ + 0x16 /* KEY_9 */ \ +} +static UINT16 IR_Code[IR_CODE_SIZE] = IR_MAP; +static UINT32 Recv_IR_Code = 0xffffffff; + + +static SDD_OPERATIONS irda_op = { + irda_ctrl +}; + +static void irda_gpio_config() +{ +} + +static void irda_active(UINT8 enable) +{ + UINT32 value; + + value = REG_READ(IRDA_CTRL); + if(enable){ + value |= IRDA_NEC_EN; + }else{ + value &= ~IRDA_NEC_EN; + } + REG_WRITE(IRDA_CTRL, value); +} + +static void irda_set_polarity(UINT8 polarity) +{ + UINT32 value; + + value = REG_READ(IRDA_CTRL); + if(polarity){ + value |= IRDA_POLARITY; + }else{ + value &= ~IRDA_POLARITY; + } + REG_WRITE(IRDA_CTRL, value); +} + +static void irda_set_clk(UINT16 clk) +{ + UINT32 value; + + value = REG_READ(IRDA_CTRL); + value &= ~(CLK_DIVID_MASK << CLK_DIVID_POSI); + value |= (clk << CLK_DIVID_POSI); + REG_WRITE(IRDA_CTRL, value); +} + +static UINT32 irda_get_key(void) +{ + UINT32 tmp,index; + + tmp = Recv_IR_Code; + + if((tmp&0xFFFF) != IR_UserCode){ + return 0xFF; + } + + if((tmp&0xFF000000) & ((tmp&0xFF0000)<<8)){ + return 0xFF; + } + + tmp = (tmp>>16)&0xFF; + + for(index=0; indexrxbuf[0]); + + cfg.channel = p_ejpeg->dma_channel; + cfg.prio = 0; + cfg.u.type5.dst_loop_start_addr = &(p_ejpeg->rxbuf[0]); + cfg.u.type5.dst_loop_end_addr = &(p_ejpeg->rxbuf[p_ejpeg->rxbuf_len]); + + cfg.fin_handler = p_ejpeg->dma_rx_handler; + + cfg.src_module = GDMA_X_SRC_JPEG_WR_REQ; + cfg.dst_module = GDMA_X_DST_DTCM_WR_REQ; + + sddev_control(GDMA_DEV_NAME, CMD_GDMA_CFG_TYPE5, &cfg); + + en_cfg.channel = p_ejpeg->dma_channel; + en_cfg.param = p_ejpeg->node_len; // dma translen + sddev_control(GDMA_DEV_NAME, CMD_GDMA_SET_TRANS_LENGTH, &en_cfg); + + en_cfg.channel = p_ejpeg->dma_channel; + en_cfg.param = 1; + sddev_control(GDMA_DEV_NAME, CMD_GDMA_SET_DMA_ENABLE, &en_cfg); +} + +static void ejpeg_eixt_rxdma(void) +{ + GDMA_CFG_ST en_cfg; + + en_cfg.channel = p_ejpeg->dma_channel; + en_cfg.param = 1; + sddev_control(GDMA_DEV_NAME, CMD_GDMA_SET_DMA_ENABLE, &en_cfg); +} +#endif + +static void ejpeg_isr(void) +{ + UINT32 status = REG_READ(JPEG_REG6); + + if(status & START_FRM_INT_STATUS) { + if((p_ejpeg) &&(p_ejpeg->start_frame_handler)) { + p_ejpeg->start_frame_handler(); + } + } + + if(status & END_FRM_INT_STATUS) { + if((p_ejpeg) &&(p_ejpeg->end_frame_handler)) { + p_ejpeg->end_frame_handler(); + } + } + + REG_WRITE(JPEG_REG6, status); +} + +static void ejpeg_software_init(void) +{ + ddev_register_dev(EJPEG_DEV_NAME, &ejpeg_op); +} + +static void ejpeg_hardware_init(void) +{ + UINT32 reg; + /* register interrupt */ + intc_service_register(FIQ_JPEG_ENCODER, PRI_FIQ_JPEG_DECODER, ejpeg_isr); + + REG_WRITE(JPEG_REG0, 0); + + /* reset int status */ + reg = REG_READ(JPEG_REG6); + REG_WRITE(JPEG_REG6, reg); + + /* config gpio */ +} + +void ejpeg_init(void) +{ + ejpeg_software_init(); + ejpeg_hardware_init(); +} + +void ejpeg_exit(void) +{ + REG_WRITE(JPEG_REG0, 0); + REG_WRITE(JPEG_REG6, REG_READ(JPEG_REG6)); + + ddev_unregister_dev(EJPEG_DEV_NAME); +} + +static UINT32 ejpeg_open(UINT32 op_flag) +{ + // UINT32 reg; + if(!op_flag) { + EJPEG_PRT("ejpeg_open is NULL\r\n"); + return EJPEG_FAILURE; + } + + p_ejpeg = (DJPEG_DESC_PTR)op_flag; + + ejpeg_set_encoder_enable(0); + ejpeg_init_quant_table(); + + ejpeg_set_x_pixel(p_ejpeg->x_pixel); + ejpeg_set_y_pixel(p_ejpeg->y_pixel); + + if(p_ejpeg->start_frame_handler) + ejpeg_set_start_frame_int(1); + if(p_ejpeg->end_frame_handler) + ejpeg_set_end_frame_int(1); + + // this 4 byte size attched to the end of JPEG, use to check crc + ejpeg_enable_enc_size(1); + ejpeg_set_video_byte_reverse(1); + + ejpeg_set_target_high_byte(JPEG_BITRATE_MAX_SIZE); + ejpeg_set_target_low_byte(JPEG_BITRATE_MIN_SIZE); + ejpeg_set_bitrate_step(7); + ejpeg_enable_bitrate_ctrl(1); + + ejpeg_enable_interrupt(); + ejpeg_power_up(); + ejpeg_gpio_config(); + + #if CFG_GENERAL_DMA + ejpeg_config_rxdma(); + #endif + + ejpeg_set_encoder_enable(1); + + return EJPEG_SUCCESS; +} + +static UINT32 ejpeg_close(void) +{ + ejpeg_set_encoder_enable(0); + + #if CFG_GENERAL_DMA + ejpeg_eixt_rxdma(); + #endif + + ejpeg_disable_interrupt(); + ejpeg_power_down(); + + return EJPEG_SUCCESS; +} + +static UINT32 ejpeg_ctrl(UINT32 cmd, void *param) +{ + UINT32 ret = EJPEG_SUCCESS; + + switch(cmd) + { + case EJPEG_CMD_SET_START_FRAME_INT: + ejpeg_set_start_frame_int(*((UINT32 *)param)); + break; + case EJPEG_CMD_SET_END_FRAME_INT: + ejpeg_set_end_frame_int(*((UINT32 *)param)); + break; + case EJPEG_CMD_SET_MCLK_DIV: + ejpeg_set_mclk_div(*((UINT32 *)param)); + break; + case EJPEG_CMD_SET_VIDEO_BYTE_REVERSE: + ejpeg_set_video_byte_reverse(*((UINT32 *)param)); + break; + case EJPEG_CMD_SELECT_YUV_FORMAT: + ejpeg_select_yuv_format(*((UINT32 *)param)); + break; + case EJPEG_CMD_SET_ENCODER_ENABLE: + ejpeg_set_encoder_enable(*((UINT32 *)param)); + break; + case EJPEG_CMD_SET_X_PIXEL: + ejpeg_set_x_pixel(*((UINT32 *)param)); + break; + case EJPEG_CMD_ENABLE_ENC_SIZE: + ejpeg_enable_enc_size(*((UINT32 *)param)); + break; + case EJPEG_CMD_ENABLE_BITRATE_CTRL: + ejpeg_enable_bitrate_ctrl(*((UINT32 *)param)); + break; + case EJPEG_CMD_SET_BITRATE_STEP: + ejpeg_set_bitrate_step(*((UINT32 *)param)); + break; + case EJPEG_CMD_SET_HSYNC_REVERSE: + ejpeg_set_hsync_reverse(*((UINT32 *)param)); + break; + case EJPEG_CMD_SET_VSYNC_REVERSE: + ejpeg_set_vsync_reverse(*((UINT32 *)param)); + break; + case EJPEG_CMD_SET_Y_PIXEL: + ejpeg_set_y_pixel(*((UINT32 *)param)); + break; + case EJPEG_CMD_GET_TARGET_HIGH_BYTE: + ret = ejpeg_get_target_high_byte(); + break; + case EJPEG_CMD_GET_TARTGE_LOW_BYTE: + ret = ejpeg_get_target_low_byte(); + break; + case EJPEG_CMD_GET_FRAME_LEN: + ret = ejpeg_get_frame_len(); + break; + + default: + break; + } + + return ret; +} + +#endif diff --git a/beken_os/beken378/driver/jpeg/jpeg_encoder.h b/beken_os/beken378/driver/jpeg/jpeg_encoder.h new file mode 100755 index 0000000..8f1fe32 --- /dev/null +++ b/beken_os/beken378/driver/jpeg/jpeg_encoder.h @@ -0,0 +1,63 @@ +#ifndef _BK_JPEG_ENCODER_H_ +#define _BK_JPEG_ENCODER_H_ + +#define JPEG_BASE (0x0080A000) + +#define JPEG_REG0 (JPEG_BASE + 0 * 4) +#define START_FRM_INT (1 << 2) +#define END_FRM_INT (1 << 3) +#define DIV_POSI (4) +#define DIV_MASK (0x3) +#define DIV_24M (0) +#define DIV_16M (1) +#define DIV_12M (2) +#define DIV_24M_1 (3) + +#define JPEG_REG1 (JPEG_BASE + 1 * 4) +#define VIDEO_BYTE_REV (1 << 1) +#define YUV_FMT_SEL_POSI (2) +#define YUV_FMT_SEL_MASK (0x3) +#define YUV_FMT_YUYV (0) +#define YUV_FMT_UYVY (1) +#define YUV_FMT_YYUV (2) +#define YUV_FMT_UVYY (3) +#define JPEG_ENC_EN (1 << 4) +#define X_PIXEL_POSI (8) +#define X_PIXEL_MASK (0xFF) +#define JPEG_ENC_SIZE (1 << 16) +#define BIT_RATE_CTRL (1 << 17) +#define BIT_RATE_STEP_POSI (18) +#define BIT_RATE_STEP_MASK (0x7) +#define HSYNC_REV (1 << 21) +#define VSYNC_REV (1 << 22) +#define Y_PIXEL_POSI (24) +#define Y_PIXEL_MASK (0xF) + +#define JPEG_REG2 (JPEG_BASE + 2 * 4) +#define TARGET_BYTE_H_POSI (0) +#define TARGET_BYTE_H_MASK (0xFFFFFFFF) + +#define JPEG_REG3 (JPEG_BASE + 3 * 4) +#define TARGET_BYTE_L_POSI (0) +#define TARGET_BYTE_L_MASK (0xFFFFFFFF) + +#define JPEG_REG5 (JPEG_BASE + 5 * 4) +#define RX_FIFO_DATE_POSI (0) +#define RX_FIFO_DATE_MASK (0xFFFFFFFF) + +#define JPEG_REG6 (JPEG_BASE + 6 * 4) +#define START_FRM_INT_STATUS (1 << 0) +#define END_FRM_INT_STATUS (1 << 1) + +#define JPEG_REG7 (JPEG_BASE + 7 * 4) +#define BYTE_CNT_PFRM_POSI (0) +#define BYTE_CNT_PFRM_MASK (0xFFFFFFFF) + +#define JPEG_REG20_QUANT_TAB (JPEG_BASE + 0x20 * 4) +#define JPEG_QUANT_TAB_LEN (32) + +static UINT32 ejpeg_open(UINT32 op_flag); +static UINT32 ejpeg_close(void); +static UINT32 ejpeg_ctrl(UINT32 cmd, void *param); + +#endif // _BK_JPEG_H_ diff --git a/beken_os/beken378/driver/jpeg/jpeg_encoder_pub.h b/beken_os/beken378/driver/jpeg/jpeg_encoder_pub.h new file mode 100755 index 0000000..d543ad9 --- /dev/null +++ b/beken_os/beken378/driver/jpeg/jpeg_encoder_pub.h @@ -0,0 +1,71 @@ +#ifndef __JPEG_ENCODER_PUB_H__ +#define __JPEG_ENCODER_PUB_H__ + +#if CFG_USE_CAMERA_INTF +#define EJPEG_FAILURE (1) +#define EJPEG_SUCCESS (0) + +#define EJPEG_DEV_NAME "ejpeg" + +#define EJPEG_CMD_MAGIC (0x0EBC0000) + +#include "uart_pub.h" +#define EJPEG_DEBUG +#ifdef EJPEG_DEBUG +#define EJPEG_PRT os_printf +#else +#define EJPEG_PRT null_prf +#define EJPEG_WPRT null_prf +#endif + +typedef struct ejpeg_desc +{ + UINT8 *rxbuf; + + void (*node_full_handler)(void *curptr, UINT32 newlen, UINT32 is_eof, UINT32 frame_len); + void (*data_end_handler)(void); + + UINT16 rxbuf_len; + UINT16 rx_read_len; + UINT32 node_len; + + UINT16 x_pixel; + UINT16 y_pixel; + void (*start_frame_handler)(void); + void (*end_frame_handler)(void); +#if CFG_GENERAL_DMA + void (*dma_rx_handler)(UINT32); + UINT32 dma_channel; +#endif + //CTIMER_T delay_timer; +} DJPEG_DESC_ST, *DJPEG_DESC_PTR; + +enum +{ + EJPEG_CMD_SET_START_FRAME_INT = EJPEG_CMD_MAGIC + 1, + EJPEG_CMD_SET_END_FRAME_INT, + EJPEG_CMD_SET_MCLK_DIV, + EJPEG_CMD_SET_VIDEO_BYTE_REVERSE, + EJPEG_CMD_SELECT_YUV_FORMAT, + EJPEG_CMD_SET_ENCODER_ENABLE, + EJPEG_CMD_SET_X_PIXEL, + EJPEG_CMD_ENABLE_ENC_SIZE, + EJPEG_CMD_ENABLE_BITRATE_CTRL, + EJPEG_CMD_SET_BITRATE_STEP, + EJPEG_CMD_SET_HSYNC_REVERSE, + EJPEG_CMD_SET_VSYNC_REVERSE, + EJPEG_CMD_SET_Y_PIXEL, + EJPEG_CMD_GET_TARGET_HIGH_BYTE, + EJPEG_CMD_GET_TARTGE_LOW_BYTE, + EJPEG_CMD_GET_FRAME_LEN, +}; + + +#define Y_PIXEL_480 (60) // Y * 8 +#define X_PIXEL_640 (80) // X * 8 + +void ejpeg_init(void); +void ejpeg_exit(void); + +#endif // CFG_USE_JPEG_ENCODER +#endif // __JPEG_ENCODER_PUB_H__ diff --git a/beken_os/beken378/driver/macphy_bypass/mac_phy_bypass.c b/beken_os/beken378/driver/macphy_bypass/mac_phy_bypass.c new file mode 100755 index 0000000..f2348c7 --- /dev/null +++ b/beken_os/beken378/driver/macphy_bypass/mac_phy_bypass.c @@ -0,0 +1,260 @@ +#include "include.h" +#include "arm_arch.h" + +#include "mac_phy_bypass_pub.h" +#include "mac_phy_bypass.h" + +#include "drv_model_pub.h" +#include "uart_pub.h" + +UINT32 reg_134 = 0x00; +UINT32 reg_135 = 0xc4; +UINT32 reg_138 = 0x00; +UINT32 reg_139 = 0x10; +UINT32 reg_140 = 0x00; +UINT32 reg_129 = 0x00; +UINT32 reg_132 = 0x80; +UINT32 reg_133 = 0x00; +UINT32 g_band = 0; + +#if CFG_MAC_PHY_BAPASS +struct MPB_TypeDef mpb_regs = +{ + (volatile MPB_REG0x0_TypeDef *)(MPB_ADDR_BASE + 0 * 4), + (volatile MPB_REG0x1_TypeDef *)(MPB_ADDR_BASE + 1 * 4), + (volatile MPB_REG0x2_TypeDef *)(MPB_ADDR_BASE + 2 * 4), + (volatile MPB_REG0x3_TypeDef *)(MPB_ADDR_BASE + 3 * 4), + (volatile MPB_REG0x4_TypeDef *)(MPB_ADDR_BASE + 4 * 4), + (volatile MPB_REG0x8_TypeDef *)(MPB_ADDR_BASE + 8 * 4), + (volatile MPB_REG0x9_TypeDef *)(MPB_ADDR_BASE + 9 * 4), + (volatile MPB_REG0xA_TypeDef *)(MPB_ADDR_BASE + 10 * 4), + (volatile MPB_REG0xB_TypeDef *)(MPB_ADDR_BASE + 11 * 4), + + (volatile MPB_REG0x80_TypeDef *)(MPB_ADDR_BASE + 128 * 4), + (volatile MPB_REG0x81_TypeDef *)(MPB_ADDR_BASE + 129 * 4), + (volatile MPB_REG0x82_TypeDef *)(MPB_ADDR_BASE + 130 * 4), + (volatile MPB_REG0x83_TypeDef *)(MPB_ADDR_BASE + 131 * 4), + (volatile MPB_REG0x84_TypeDef *)(MPB_ADDR_BASE + 132 * 4), + (volatile MPB_REG0x85_TypeDef *)(MPB_ADDR_BASE + 133 * 4), + (volatile MPB_REG0x86_TypeDef *)(MPB_ADDR_BASE + 134 * 4), + (volatile MPB_REG0x87_TypeDef *)(MPB_ADDR_BASE + 135 * 4), + (volatile MPB_REG0x88_TypeDef *)(MPB_ADDR_BASE + 136 * 4), + (volatile MPB_REG0x89_TypeDef *)(MPB_ADDR_BASE + 137 * 4), + (volatile MPB_REG0x8A_TypeDef *)(MPB_ADDR_BASE + 138 * 4), + (volatile MPB_REG0x8B_TypeDef *)(MPB_ADDR_BASE + 139 * 4), + (volatile MPB_REG0x8C_TypeDef *)(MPB_ADDR_BASE + 140 * 4), + (volatile MPB_REG0x8D_TypeDef *)(MPB_ADDR_BASE + 141 * 4), + (volatile MPB_REG0x8E_TypeDef *)(MPB_ADDR_BASE + 142 * 4), + (volatile MPB_REG0x8F_TypeDef *)(MPB_ADDR_BASE + 143 * 4), +}; + +static SDD_OPERATIONS mpb_op = { + mpb_ctrl +}; + +void mpb_init(void) +{ + sddev_register_dev(MPB_DEV_NAME, &mpb_op); +} + +void mpb_exit(void) +{ + sddev_unregister_dev(MPB_DEV_NAME); +} + +void mpb_tx_mode(void) +{ + mpb_regs.r0->value = 0x00; + mpb_regs.r128->value = 0x34; + mpb_regs.r129->value = reg_129; + mpb_regs.r130->value = 0x00; + mpb_regs.r131->value = 0x00; + mpb_regs.r132->value = reg_132; + mpb_regs.r133->value = reg_133; + mpb_regs.r134->value = reg_134; + mpb_regs.r135->value = reg_135; + mpb_regs.r136->value = 0x00; + mpb_regs.r137->value = 0x00; + mpb_regs.r138->value = reg_138; + mpb_regs.r139->value = reg_139; + mpb_regs.r140->value = reg_140; + mpb_regs.r141->value = 0x00; + mpb_regs.r142->value = 0x00; + mpb_regs.r143->value = 0xff; + mpb_regs.r3->value = 0x1c20; ///0xEA6;//0xEA6,177 + mpb_regs.r2->value = 0x10; + //mpb_regs.r0->value = 0x01; +} + +void mpb_rx_mode(void) +{ + mpb_regs.r0->value = 0x00; + mpb_regs.r1->value = 0x05; + mpb_regs.r0->value = 0x21; +} + +void mpb_stop_trx(void) +{ + mpb_regs.r0->value &= (~0x01); +} + +void mpb_start_trx(void) +{ + mpb_regs.r0->value |= 0x01; + //REG_WRITE((0x0802800 + (18 * 4)), 0x02); +} + +void mpb_set_txdelay(UINT32 delay_us) +{ + UINT32 delay_us_value; + + if(g_band == 1) + delay_us_value = delay_us * 60; + else + delay_us_value = delay_us * 30; + + if(delay_us_value > 0xfffff) + delay_us_value = 0xfffff; + + mpb_regs.r3->value = delay_us_value; +} + +void mpb_set_txdelay_precision(float delay_us) +{ + UINT32 delay_us_value; + + if (g_band == 1) + { + delay_us_value = (UINT32)(delay_us * 60 + 0.5); + } + else + { + delay_us_value = (UINT32)(delay_us * 30 + 0.5); + } + + if (delay_us_value > 0xfffff) + { + delay_us_value = 0xfffff; + } + + mpb_regs.r3->value = delay_us_value; +} + +static UINT32 mpb_select_tx_rate(UINT32 rate) +{ + UINT32 param = rate; + + switch(rate) + { + case 1 : param = 0x0; break; // 1Mbps + case 2 : param = 0x1; break; // 2Mbps + case 5 : param = 0x2; break; // 5.5Mbps + case 11: param = 0x3; break; // 11Mbps + case 6 : param = 0xb; break; // 6Mbps + case 9 : param = 0xf; break; // 9Mbps + case 12: param = 0xa; break; // 12Mbps + case 18: param = 0xe; break; // 18Mbps + case 24: param = 0x9; break; // 24Mbps + case 36: param = 0xd; break; // 36Mbps + case 48: param = 0x8; break; // 48Mbps + case 54: param = 0xc; break; // 54Mbps + default: { + if(rate >= 128 && rate <=135) + param -= 128; + else { + os_printf("mpb_select_tx_rate wrong rate:%d\r\n", rate); + } + } + } + + os_printf("mpb_select_tx_rate rate:%d\r\n", param); + return param; +} + +UINT32 mpb_ctrl(UINT32 cmd, void *param) +{ + UINT32 len; +/// UINT32 reg; + + switch(cmd) + { + case MCMD_TX_LEGACY_SET_LEN: + len = (*(UINT32*)param); + reg_134 &= ~(0xff); + reg_135 &= ~(0xf); + reg_134 |= len & 0xff; + reg_135 |= (len >> 8) & 0xf; + break; + + case MCMD_TX_HT_VHT_SET_LEN: + len = (*(UINT32*)param); + reg_138 &= ~(0xff); + reg_139 &= ~(0xff); + reg_140 &= ~(0xf); + reg_138 |= len & 0xff; + reg_139 |= (len >> 8) & 0xff; + reg_140 |= (len >> 16) & 0xf; + break; + + case MCMD_TX_MODE_BYPASS_MAC: + mpb_tx_mode(); + break; + + case MCMD_RX_MODE_BYPASS_MAC: + mpb_rx_mode(); + break; + + case MCMD_STOP_BYPASS_MAC: + mpb_stop_trx(); + break; + + case MCMD_START_BYPASS_MAC: + mpb_start_trx(); + break; + + case MCMD_SET_BANDWIDTH: + reg_129 &= (~(PPDU_BANDWIDTH_MASK << PPDU_BANDWIDTH_POSI)); + reg_129 |= (((*(UINT32*)param)&&PPDU_BANDWIDTH_MASK)<< PPDU_BANDWIDTH_POSI); + g_band = (*(UINT32*)param); + break; + + case MCMD_SET_GI: //0x0: 800ns; 0x1: 400ns + reg_140 &= (~(0x1 << 6)); + reg_140 |= (((*(UINT32*)param)&&0x1)<< 6); + break; + + // for modulate format: 0x0: Non-HT; 0x1:Non-HT-DUP; 0x2: HT-MM; 0x3: HT-GF + // for rate: 0-11: b to g, mcs 0-7: MCS0 =128, MCS1=129 to CS7=135. + case MCMD_BYPASS_TX_SET_RATE_MFORMAT: { + MBPS_TXS_MFR_ST st =(*(MBPS_TXS_MFR_PTR)param); + + st.rate = mpb_select_tx_rate(st.rate); + + reg_132 &= ~(0xff); + reg_132 |= (0x80 | st.rate); + + reg_135 &= ~(0xf0); + if(st.mod_format >= 0x2) { + reg_135 |= 0xb0; + } + else { + reg_135 |= (st.rate & PPDU_RATE_MASK) << PPDU_RATE_POSI; + } + + reg_133 = st.mod_format; + break; + } + + case MCMD_SET_TXDELAY: + mpb_set_txdelay(*(UINT32*)param); + break; + + default: + break; + } + + return 0; +} + +#endif +// eof diff --git a/beken_os/beken378/driver/macphy_bypass/mac_phy_bypass.h b/beken_os/beken378/driver/macphy_bypass/mac_phy_bypass.h new file mode 100755 index 0000000..471a5f4 --- /dev/null +++ b/beken_os/beken378/driver/macphy_bypass/mac_phy_bypass.h @@ -0,0 +1,293 @@ +#ifndef _MAC_PHY_BYPASSH_ +#define _MAC_PHY_BYPASS_H_ + +#define MPB_ADDR_BASE (0x01060000) + +typedef union +{ + struct { + VU32 bypass_en:1; + VU32 resv0:3; + VU32 mode:2; + VU32 resv1:2; + VU32 single_txen:1; + VU32 resv2:23; + }bits; + + VU32 value; +}MPB_REG0x0_TypeDef; + +typedef union +{ + struct { + VU32 pre_rxdelay:20; + VU32 resv2:12; + }bits; + + VU32 value; +}MPB_REG0x1_TypeDef; + +typedef union +{ + struct { + VU32 rxdelay:20; + VU32 resv2:12; + }bits; + + VU32 value; +}MPB_REG0x2_TypeDef; + +typedef union +{ + struct { + VU32 pre_txdelay:20; + VU32 resv2:12; + }bits; + + VU32 value; +}MPB_REG0x3_TypeDef; + +typedef union +{ + struct { + VU32 txdelay:20; + VU32 resv2:12; + }bits; + + VU32 value; +}MPB_REG0x4_TypeDef; + +typedef union +{ + struct { + VU32 rxstat:20; + VU32 resv2:12; + }bits; + + VU32 value; +}MPB_REG0x8_TypeDef; + +typedef union +{ + struct { + VU32 txstat:20; + VU32 resv2:12; + }bits; + + VU32 value; +}MPB_REG0x9_TypeDef; + +typedef union +{ + struct { + VU32 rxerrstat:20; + VU32 resv2:12; + }bits; + + VU32 value; +}MPB_REG0xA_TypeDef; + +typedef union +{ + struct { + VU32 txerrstat:20; + VU32 resv2:12; + }bits; + + VU32 value; +}MPB_REG0xB_TypeDef; + + +typedef union +{ + struct { + VU32 txvector0:8; + VU32 resv1:24; + }bits; + + VU32 value; +}MPB_REG0x80_TypeDef; + +typedef union +{ + struct { + VU32 txvector1:8; + VU32 resv1:24; + }bits; + + VU32 value; +}MPB_REG0x81_TypeDef; + +typedef union +{ + struct { + VU32 txvector2:8; + VU32 resv1:24; + }bits; + + VU32 value; +}MPB_REG0x82_TypeDef; + +typedef union +{ + struct { + VU32 txvector3:8; + VU32 resv1:24; + }bits; + + VU32 value; +}MPB_REG0x83_TypeDef; + +typedef union +{ + struct { + VU32 txvector4:8; + VU32 resv1:24; + }bits; + + VU32 value; +}MPB_REG0x84_TypeDef; + +typedef union +{ + struct { + VU32 txvector5:8; + VU32 resv1:24; + }bits; + + VU32 value; +}MPB_REG0x85_TypeDef; + +typedef union +{ + struct { + VU32 txvector6:8; + VU32 resv1:24; + }bits; + + VU32 value; +}MPB_REG0x86_TypeDef; + +typedef union +{ + struct { + VU32 txvector7:8; + VU32 resv1:24; + }bits; + + VU32 value; +}MPB_REG0x87_TypeDef; + +typedef union +{ + struct { + VU32 txvector8:8; + VU32 resv1:24; + }bits; + + VU32 value; +}MPB_REG0x88_TypeDef; + +typedef union +{ + struct { + VU32 txvector9:8; + VU32 resv1:24; + }bits; + + VU32 value; +}MPB_REG0x89_TypeDef; + +typedef union +{ + struct { + VU32 txvector10:8; + VU32 resv1:24; + }bits; + + VU32 value; +}MPB_REG0x8A_TypeDef; + +typedef union +{ + struct { + VU32 txvector11:8; + VU32 resv1:24; + }bits; + + VU32 value; +}MPB_REG0x8B_TypeDef; + +typedef union +{ + struct { + VU32 txvector12:8; + VU32 resv1:24; + }bits; + + VU32 value; +}MPB_REG0x8C_TypeDef; + +typedef union +{ + struct { + VU32 txvector13:8; + VU32 resv1:24; + }bits; + + VU32 value; +}MPB_REG0x8D_TypeDef; + +typedef union +{ + struct { + VU32 txvector14:8; + VU32 resv1:24; + }bits; + + VU32 value; +}MPB_REG0x8E_TypeDef; + +typedef union +{ + struct { + VU32 txvector15:8; + VU32 resv1:24; + }bits; + + VU32 value; +}MPB_REG0x8F_TypeDef; + +struct MPB_TypeDef { + volatile MPB_REG0x0_TypeDef *r0; + volatile MPB_REG0x1_TypeDef *r1; + volatile MPB_REG0x2_TypeDef *r2; + volatile MPB_REG0x3_TypeDef *r3; + volatile MPB_REG0x4_TypeDef *r4; + volatile MPB_REG0x8_TypeDef *r8; + volatile MPB_REG0x9_TypeDef *r9; + volatile MPB_REG0xA_TypeDef *r10; + volatile MPB_REG0xB_TypeDef *r11; + + volatile MPB_REG0x80_TypeDef *r128; + volatile MPB_REG0x81_TypeDef *r129; + volatile MPB_REG0x82_TypeDef *r130; + volatile MPB_REG0x83_TypeDef *r131; + volatile MPB_REG0x84_TypeDef *r132; + volatile MPB_REG0x85_TypeDef *r133; + volatile MPB_REG0x86_TypeDef *r134; + volatile MPB_REG0x87_TypeDef *r135; + volatile MPB_REG0x88_TypeDef *r136; + volatile MPB_REG0x89_TypeDef *r137; + volatile MPB_REG0x8A_TypeDef *r138; + volatile MPB_REG0x8B_TypeDef *r139; + volatile MPB_REG0x8C_TypeDef *r140; + volatile MPB_REG0x8D_TypeDef *r141; + volatile MPB_REG0x8E_TypeDef *r142; + volatile MPB_REG0x8F_TypeDef *r143; +}; + +extern UINT32 mpb_ctrl(UINT32 cmd, void *param); +#endif // _MAC_PHY_BYPASS_H_ + +// eof diff --git a/beken_os/beken378/driver/phy/phy.h b/beken_os/beken378/driver/phy/phy.h new file mode 100755 index 0000000..f5df797 --- /dev/null +++ b/beken_os/beken378/driver/phy/phy.h @@ -0,0 +1,415 @@ +/** + **************************************************************************************** + * + * @file phy.h + * + * @brief Header file for nX Radio physical layer driver. + * + * Copyright (C) RivieraWaves 2011-2016 + * + **************************************************************************************** + */ +#ifndef _PHY_H_ +#define _PHY_H_ + +/* + **************************************************************************************** + * @defgroup PHY PHY + * @ingroup PLATFORM_DRIVERS + * @brief Declaration of the PHY Drivers + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +// default inclusion directives +#include "co_int.h" +#include "rwnx_config.h" + +//for __INLINE +#include "compiler.h" + +/* + * DEFINES + **************************************************************************************** + */ +/// Invalid value for some octet parameters reserved for the future +#define PHY_UNUSED 0xFF + +/// Maximum number of words in the configuration buffer +#define PHY_CFG_BUF_SIZE 16 + +enum +{ + /// 2.4GHz Band + PHY_BAND_2G4, + /// 5GHz band + PHY_BAND_5G, + /// Number of bands + PHY_BAND_MAX, +}; + +enum +{ + PHY_CHNL_BW_20, + PHY_CHNL_BW_40, + PHY_CHNL_BW_80, + PHY_CHNL_BW_160, + PHY_CHNL_BW_80P80, + PHY_CHNL_BW_OTHER, +}; + +enum +{ + /// Primary radar detection chain (i.e for the operating channel) + PHY_PRIM, + /// Secondary radar detection chain + PHY_SEC, +}; + +/// Structure containing the information about the PHY channel that was used for this RX +struct phy_channel_info +{ + /// PHY channel information 1 + uint32_t info1; + /// PHY channel information 2 + uint32_t info2; +}; + +struct phy_radar_pulse +{ + /// In our PHY a radar pulse is only one 32-bit word + uint32_t pulse; +}; + +/// Structure containing the parameters of the PHY configuration +struct phy_cfg_tag +{ + /// Buffer containing the parameters specific for the PHY used + uint32_t parameters[PHY_CFG_BUF_SIZE]; +}; + + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ + +/** + **************************************************************************************** + * @brief Modem and Radio initialization function. + * This function is called at platform reset and initializes modem, then radio. + * @param[in] cfg Pointer to the PHY parameters (used radio paths, other cfg) + **************************************************************************************** + */ +void phy_init(const struct phy_cfg_tag *config); + +/** + **************************************************************************************** + * @brief Resets some parts of the PHY. + * This function is called upon a system reset during the recovery procedure. + **************************************************************************************** + */ +void phy_reset(void); + + +/** + **************************************************************************************** + * @brief PHY version reading function. + * This function returns the PHY version on two 32-bit words. The format of these two + * words is PHY dependent. + * + * @param[out] version_1 Pointer to the 1st version word + * @param[out] version_2 Pointer to the 2nd version word + **************************************************************************************** + */ +void phy_get_version(uint32_t *version_1, uint32_t *version_2); + +/** + **************************************************************************************** + * @brief Set channel function. + * This function is called when the MAC stack needs to change the channel on which the + * radio is locked. + * The function is blocking until the PLL has locked on the new channel frequency. + * + * @param[in] band Band for which the channel index is specified + * @param[in] type Channel type for 20/40/80/160/80+80 or other + * @param[in] prim20_freq Primary 20MHz channel frequency (in MHz) + * @param[in] center1_freq Center frequency of whole channel (when contiguous), + * =prim20_freq for a 20MHz channel. Center or primary 80MHz channel + * if 80+80 type + * @param[in] center2_freq Center frequency of secondary 80MHz channel if 80+80 + * @param[in] index Index of the RF for which the channel has to be set (@PHY_PRIM: + * operating (primary RF)), 1: secondary RF (@PHY_SEC: used for + * additional radar detection). This parameter is reserved if no + * secondary RF is available in the system + **************************************************************************************** + */ +void phy_set_channel(uint8_t band, uint8_t type, uint16_t prim20_freq, + uint16_t center1_freq, uint16_t center2_freq, uint8_t index); + +/** + **************************************************************************************** + * @brief Get channel function. + * This function is called when the MAC stack needs to get the information on the channel + * on which the radio is currently locked. + * + * @param[out] info Pointer on the phy_channel_info structure used to return the + * information + * @param[in] index Index of the RF for which the channel has to be retrieved + * (@PHY_PRIM or @PHY_SEC) + * + **************************************************************************************** + */ +void phy_get_channel(struct phy_channel_info *info, uint8_t index); + +/** + **************************************************************************************** + * @brief PHY stop function. + * This function is called when the MAC stack needs to stop the PHY. + * It puts back the MAC HW to the IDLE state + **************************************************************************************** + */ +void phy_stop(void); + +/** + **************************************************************************************** + * @brief Compute the channel number from its center frequency and its band + * @param[in] band RF band (must be @ref PHY_BAND_2G4 or @ref PHY_BAND_5G) + * @param[in] freq Center frequency of the channel + **************************************************************************************** + */ +__INLINE int phy_freq_to_channel(uint8_t band, uint16_t freq) +{ + int channel = 0; + + do + { + //2.4.GHz + if (band == PHY_BAND_2G4) + { + // Check if frequency is in the expected range + if ((freq < 2412) || (freq > 2484)) + break; + + // Compute the channel number + if (freq == 2484) + channel = 14; + else + channel = (freq - 2407) / 5; + } + //5 GHz + else if (band == PHY_BAND_5G) + { + // Check if frequency is in the expected range + if ((freq < 5005) || (freq > 5825)) + break; + + // Compute the channel number + channel = (freq - 5000) / 5; + } + } + while(0); + + return (channel); +} + +/** + **************************************************************************************** + * @brief Compute the channel frequency from its number and band + * @param[in] band RF band (must be @ref PHY_BAND_2G4 or @ref PHY_BAND_5G) + * @param[in] channel Channel number + **************************************************************************************** + */ +__INLINE uint16_t phy_channel_to_freq(uint8_t band, int channel) +{ + uint16_t freq = (uint16_t) - 1; + + do + { + //2.4.GHz + if (band == PHY_BAND_2G4) + { + // Check if the channel number is in the expected range + if ((channel < 1) || (channel > 14)) + break; + + // Compute the channel number + if (channel == 14) + freq = 2484; + else + freq = 2407 + channel * 5; + } + //5 GHz + else if (band == PHY_BAND_5G) + { + // Check if frequency is in the expected range + if ((channel < 1) || (channel > 165)) + break; + + // Compute the channel number + freq = 5000 + channel * 5; + } + } + while(0); + + return (freq); +} + +/** + **************************************************************************************** + * @brief Modem interrupt service routine. + * This function is called when a Modem interrupt is asserted to the interrupt controller + **************************************************************************************** + */ +void phy_mdm_isr(void); + +/** + **************************************************************************************** + * @brief RC interrupt service routine. + * This function is called when a RC interrupt is asserted to the interrupt controller + **************************************************************************************** + */ +void phy_rc_isr(void); + +/** + **************************************************************************************** + * @brief Indicates if the PHY has radar pulses available or not. + * + * @param[in] rd_idx Index of the radar detection chain that needs to be checked + * (@PHY_PRIM or @PHY_SEC) + * + * @return true if pulse(s) is(are) available, false otherwise + * + **************************************************************************************** + */ +bool phy_has_radar_pulse(int rd_idx); + +/** + **************************************************************************************** + * @brief Read a radar pulse from the FIFO, and writes it to the buffer passed as parameter + * + * @param[in] rd_idx Index of the radar detection chain that needs to be read + * (@PHY_PRIM or @PHY_SEC) + * @param[out] pulse Pointer to the pulse structure where to write to + * + * @return true if a pulse has been written, false otherwise + * + **************************************************************************************** + */ +bool phy_get_radar_pulse(int rd_idx, struct phy_radar_pulse *pulse); + +/** + **************************************************************************************** + * @brief Return the Beamformee capability of the PHY + * + * @return true if Beamformee is supported by the PHY, false otherwise + **************************************************************************************** + */ +bool phy_bfmee_supported(void); + +/** + **************************************************************************************** + * @brief Return the Beamformer capability of the PHY + * + * @return true if Beamformer is supported by the PHY, false otherwise + **************************************************************************************** + */ +bool phy_bfmer_supported(void); + +/** + **************************************************************************************** + * @brief Return the MU-MIMO RX capability of the PHY + * + * @return true if MU-MIMO RX is supported by the PHY, false otherwise + **************************************************************************************** + */ +bool phy_mu_mimo_rx_supported(void); + +/** + **************************************************************************************** + * @brief Return the MU-MIMO TX capability of the PHY + * + * @return true if MU-MIMO TX is supported by the PHY, false otherwise + **************************************************************************************** + */ +bool phy_mu_mimo_tx_supported(void); + +#if RW_MUMIMO_RX_EN +/** + **************************************************************************************** + * @brief Set the MU-MIMO RX group information as received in the VHT Group ID action frame + * + * @param[in] membership_addr Address of the membership status in the received frame + * @param[in] userpos_addr Address of the user position array in the received frame + **************************************************************************************** + */ +void phy_set_group_id_info(uint32_t membership_addr, uint32_t userpos_addr); +#endif + +/** + **************************************************************************************** + * @brief Return the NSS of the PHY + * + * @return Number of Spatial Streams supported by the PHY (start from 0, 0 is for 1 SS) + **************************************************************************************** + */ +uint8_t phy_get_nss(void); + +/** + **************************************************************************************** + * @brief Return the NTX of the PHY + * + * @return Number of antenna supported for TX minus 1 (i.e. 0 means 1 antenna) + **************************************************************************************** + */ +uint8_t phy_get_ntx(void); + +/** + **************************************************************************************** + * @brief Get radio code to set a specific TX power + * Return the idx to use (set in policy table), to conigure a specific TX power. If the TX + * power requested is not possible, it should return idx to get the maximum TX power that + * do not exceed the request. In this case, power parameter should be updated tieh the + * actual TX power set. + * + * @param[in/out] power TX power (in dBm) to configure for the radio, (updated with + * the actual power set if request is not possible) + * @param[out] idx Idx to use in policy table to configure a tx power of + **************************************************************************************** + */ +void phy_get_rf_gain_idx(int8_t *power, uint8_t *idx); + + +/** + * @brief Get radio's transmission power capabilities + * + * @param[out] max Maximum TX power for the radio (in dBm) + * @param[out] min Minimum TX power for the radio (in dBm) + */ +void phy_get_rf_gain_capab(int8_t *max, int8_t *min); + +#if NX_DEBUG_DUMP +/** + **************************************************************************************** + * @brief Read the state of all PHY diagnostic ports and put it in the debug dump info + * structure + * + * @param[out] dbg_info Pointer to the debug dump information structure + * + **************************************************************************************** + */ +void phy_get_diag_state(struct dbg_debug_info_tag *dbg_info); +#endif + +void phy_enable_rx_switch(void); +void phy_disable_rx_switch(void); +uint8_t check_large_singal_status(void); +void update_large_singal_status(uint8_t status); +void phy_large_signal_support(int8_t rssi); +/// @} + +#endif //_PHY_H_ diff --git a/beken_os/beken378/driver/phy/phy_trident.c b/beken_os/beken378/driver/phy/phy_trident.c new file mode 100755 index 0000000..8d479cd --- /dev/null +++ b/beken_os/beken378/driver/phy/phy_trident.c @@ -0,0 +1,2389 @@ +/** + **************************************************************************************** + * + * @file phy_trident.c + * + * @brief File containing the nX Trident-based physical layer driver API. + * + * Copyright (C) Beken 2011-2016 + * + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +#include "rwnx_config.h" +#include "phy.h" +#include "ke_timer.h" +#include "rd.h" +#include "phy_trident.h" +#include "reg_mdm_stat.h" +#include "reg_mdm_cfg.h" +#include "reg_rc.h" +#include "reg_agc.h" +#include "include.h" +#include "arm_arch.h" +#include "dd_pub.h" +#include "drv_model_pub.h" +#include "sys_ctrl_pub.h" +#include "target_util_pub.h" +#include "uart_pub.h" +#include "intc_pub.h" +#include "power_save_pub.h" +#include "bk7011_cal_pub.h" + +/* + * STRUCTURES + **************************************************************************************** + */ +/// Structure containing the parameters of the Trident PHY configuration +struct phy_trd_cfg_tag +{ + /// MDM type(nxm)(upper nibble) and MDM2RF path mapping(lower nibble) + uint8_t path_mapping; + /// TX DC offset compensation + uint32_t tx_dc_off_comp; +}; + +/* + * GLOBALS + **************************************************************************************** + */ +/// Global PHY driver environment. +struct phy_env_tag phy_env[1]; + + +/* + * FUNCTION DEFINITIONS + **************************************************************************************** + */ + //BK,170206,solve input-power vs PER discontinuous issue. +#define NEW_AGC_PARA 1 +//BK,170206,solve large input-power 0% PER issue. +#define RF_DOWN_ENABLE 0 + +//#define CFG_SYS_CLOSE_CCA + +const uint32_t agc_ram_parameter[] = +{ +#if (CFG_SOC_NAME == SOC_BK7231N) + 0x30000000, + 0x01000000, + 0xa8000016, + 0x00000000, + 0x30000000, + 0x91000000, + 0x04104849, + 0x00000000, + 0x2000008f, + 0x04000072, + 0x00000000, + 0x34014000, + 0x10000001, + 0x0800001a, + 0x00000000, + 0x44008000, + 0x20000038, + 0x08000013, + 0x00000000, + 0x240c808f, + 0x080001b6, + 0x00000000, + 0x30000000, + 0x20090833, + 0x0400000b, + 0x00000000, + 0x30000000, + 0x41000000, + 0x0400001e, + 0x00000000, + 0x30000000, + 0x51000101, + 0x04000022, + 0x00000000, + 0x30000000, + 0x01000000, + 0x04000026, + 0x00000000, + 0x34010000, + 0x12007eeb, + 0x0870482a, + 0x00000000, + 0x34008001, + 0x64000001, + 0x0800002e, + 0x00000000, + 0x3402800f, + 0x68002101, + 0x08000032, + 0x00000000, + 0x0000139f, + 0x00000000, + 0x4400438f, + 0xa410497e, + 0x081049a2, + 0x00000000, + 0x30000000, + 0x94000000, + 0x0400003c, + 0x00000000, + 0x50000000, + 0x51000101, + 0x28000041, + 0x04000045, + 0x00000000, + 0x3400c000, + 0x120055e9, + 0x1c204832, + 0x00000000, + 0x3400c000, + 0x120037c9, + 0x1c204832, + 0x00000000, + 0x30000000, + 0x51000101, + 0x0410484d, + 0x00000000, + 0x30000000, + 0x13002189, + 0x1c000051, + 0x00000000, + 0x30000000, + 0x61020202, + 0x04000055, + 0x00000000, + 0x30000000, + 0x52000000, + 0x04000059, + 0x00000000, + 0x2400c000, + 0x0800005c, + 0x00000000, + 0x30000000, + 0x80000000, + 0x04104860, + 0x00000000, + 0x3400400f, + 0x52000000, + 0x08000064, + 0x00000000, + 0x340204af, + 0x31191910, + 0x08000068, + 0x00000000, + 0x30000eaf, + 0x51000101, + 0x0400006c, + 0x00000000, + 0x80000eaf, + 0x0c00007a, + 0x1000007d, + 0x14600080, + 0x04000032, + 0x00000000, + 0x340204af, + 0x31191910, + 0x08000076, + 0x00000000, + 0x3404ceaf, + 0x51000101, + 0x09800083, + 0x00000000, + 0x240a0eaf, + 0x09800083, + 0x00000000, + 0x24050eaf, + 0x09800083, + 0x00000000, + 0x24010eaf, + 0x09800083, + 0x00000000, + 0x60000eaf, + 0x65804888, + 0x6580008c, + 0x04104890, + 0x00000000, + 0x30000eaf, + 0x41000300, + 0x04000094, + 0x00000000, + 0x30000eaf, + 0x41000100, + 0x04000094, + 0x00000000, + 0x30000eaf, + 0x41000000, + 0x04000094, + 0x00000000, + 0x40000eaf, + 0xa400009c, + 0x04000098, + 0x00000000, + 0x30000000, + 0x14eaed83, + 0x1c00009c, + 0x00000000, + 0x24008000, + 0x0800009f, + 0x00000000, + 0x30000000, + 0x80000000, + 0x041048a3, + 0x00000000, + 0x30000000, + 0x10000000, + 0x040000a7, + 0x00000000, + 0x34014005, + 0x63000102, + 0x080000ab, + 0x00000000, + 0x30000007, + 0x50000001, + 0x040000af, + 0x00000000, + 0x30000007, + 0x32202071, + 0x040000b3, + 0x00000000, + 0x30000007, + 0x61030303, + 0x040000b7, + 0x00000000, + 0x340202ef, + 0x31202021, + 0x080000bb, + 0x00000000, + 0x34050aef, + 0x90000000, + 0x080000bf, + 0x00000000, + 0x30000aef, + 0x12000084, + 0x040000c3, + 0x00000000, + 0x30000aef, + 0x33000001, + 0x040000c7, + 0x00000000, + 0x60000eaf, + 0x658048cc, + 0x658000d0, + 0x041048d4, + 0x00000000, + 0x30000eaf, + 0x41000301, + 0x040000e0, + 0x00000000, + 0x30000eaf, + 0x41000101, + 0x040000e0, + 0x00000000, + 0x30000eaf, + 0x41000001, + 0x040000d8, + 0x00000000, + 0x30000eaf, + 0x51000001, + 0x040000dc, + 0x00000000, + 0x30000eaf, + 0x3400109c, + 0x040000e0, + 0x00000000, + 0x34190bef, + 0x52000000, + 0x080000e4, + 0x00000000, + 0x30000aef, + 0x33000101, + 0x040000e8, + 0x00000000, + 0xa0000eaf, + 0x6da048ef, + 0x658048f3, + 0x619000fb, + 0x69b000f7, + 0x041048ff, + 0x00000000, + 0x30000eaf, + 0x41030002, + 0x04000107, + 0x00000000, + 0x30000eaf, + 0x41000302, + 0x04000127, + 0x00000000, + 0x30000eaf, + 0x41010002, + 0x04000107, + 0x00000000, + 0x30000eaf, + 0x41000102, + 0x04000127, + 0x00000000, + 0x30000eaf, + 0x41000002, + 0x04000103, + 0x00000000, + 0x3000028f, + 0x51000001, + 0x0400019a, + 0x00000000, + 0x5000028f, + 0x51000001, + 0xa000019a, + 0x0400010c, + 0x00000000, + 0x3401428f, + 0x10000001, + 0x08000110, + 0x00000000, + 0x34010000, + 0x14eaed83, + 0x08000114, + 0x00000000, + 0x30000000, + 0x10000000, + 0x04000118, + 0x00000000, + 0x24014005, + 0x0800011b, + 0x00000000, + 0x3000128f, + 0x3400289c, + 0x0400011f, + 0x00000000, + 0x3000128f, + 0x35d4509c, + 0x04000123, + 0x00000000, + 0x3000128f, + 0x50000100, + 0x0400016b, + 0x00000000, + 0x7432028f, + 0x65000003, + 0x7c00012d, + 0x80104963, + 0x08000167, + 0x00000000, + 0x3000028f, + 0x41000000, + 0x04000131, + 0x00000000, + 0x8432028f, + 0x84000163, //huaming20201224 for rx sens + 0x80104963, + 0x08104937, + 0x8810493b, + 0x00000000, + 0x3000008f, + 0x41000000, + 0x881049a2, + 0x00000000, + 0x3000008f, + 0x41000000, + 0x04104834, + 0x00000000, + 0x34004005, + 0x61020202, + 0x08104943, + 0x00000000, + 0x6419000f, + 0x80104948, + 0x08000137, + 0x8810493b, + 0x00000000, + 0x3000000f, + 0x15eeea87, + 0x1c000150, + 0x00000000, + 0x3000000f, + 0x51000001, + 0x04000154, + 0x00000000, + 0x3000000f, + 0x10000001, + 0x0400014c, + 0x00000000, + 0x24008000, + 0x08000157, + 0x00000000, + 0x30000000, + 0x10000000, + 0x0400015b, + 0x00000000, + 0x34010005, + 0x61030303, + 0x0800015f, + 0x00000000, + 0x30000007, + 0x50000001, + 0x04000163, + 0x00000000, + 0x3000008f, + 0x41000000, + 0x88104834, + 0x00000000, + 0x3000038f, + 0x01000000, + 0x0400019a, + 0x00000000, + 0x4577138f, + 0x70000173, + 0x0800016f, + 0x00000000, + 0x3000038f, + 0x51000100, + 0x0400019a, + 0x00000000, + 0x3000138f, + 0x41000000, + 0x04000177, + 0x00000000, + 0x3000138f, + 0x65000003, + 0x0400017b, + 0x00000000, + 0x2000108f, + 0x881049a2, + 0x00000000, + 0x3000018f, + 0x66000001, + 0x04000182, + 0x00000000, + 0x34018000, + 0x10000001, + 0x08104986, + 0x00000000, + 0x30000000, + 0x61010101, + 0x0400018a, + 0x00000000, + 0x2403c00f, + 0x0800018d, + 0x00000000, + 0x5405000f, + 0x95000000, + 0xb4000192, + 0x08000196, + 0x00000000, + 0x3000000f, + 0x52000001, + 0x04000008, + 0x00000000, + 0x3000000f, + 0x52000000, + 0x0400000b, + 0x00000000, + 0x3401438f, + 0x10000001, + 0x0810499e, + 0x00000000, + 0x34010000, + 0x14ecec83, + 0x087049a6, + 0x00000000, + 0x34004000, + 0x95000000, + 0x0810480b, + 0x00000000, + 0x30000000, + 0x80000000, + 0x041049aa, + 0x00000000, + 0x30000000, + 0x95000000, + 0x041049ae, + 0x00000000, + 0x30000000, + 0x01000000, + 0x040001b2, + 0x00000000, + 0x30000000, + 0x12000084, + 0x0400002a, + 0x00000000, + 0x3000008f, + 0x14eaed83, + 0x1c0001ba, + 0x00000000, + 0x34010000, + 0x52000000, + 0x080001be, + 0x00000000, + 0x34008000, + 0x10000000, + 0x080001c2, + 0x00000000, + 0x24014005, + 0x080001c5, + 0x00000000, + 0x3000128f, + 0x3400209c, + 0x040001c9, + 0x00000000, + 0x3000128f, + 0x35d4509c, + 0x040001cd, + 0x00000000, + 0x3000128f, + 0x50000100, + 0x040001d1, + 0x00000000, + 0x4577138f, + 0x700001d5, + 0x0800016f, + 0x00000000, + 0x3000138f, + 0x41000000, + 0x040001d9, + 0x00000000, + 0x3000138f, + 0x65000003, + 0x040001dd, + 0x00000000, + 0x2000138f, + 0x881049a2, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x14090b11 +#else +0x30000000, +0x01000000, +0xa8000016, +0x00000000, +0x30000000, +0x91000000, +0x04104845, +0x00000000, +0x2000008f, +0x0400006e, +0x00000000, +0x30000000, +0x41000000, +0x0400001a, +0x00000000, +0x40000010, +0x74000013, +0x04000034, +0x00000000, +0x240c808f, +0x0800019a, +0x00000000, +0x30000000, +0x20070633, +0x0400000b, +0x00000000, +0x30000000, +0x51000101, +0x0400001e, +0x00000000, +0x34010000, +0x12007eeb, +0x08704822, +0x00000000, +0x30000000, +0x01000000, +0x04000026, +0x00000000, +0x34008001, +0x64000001, +0x0800002a, +0x00000000, +0x3402800f, +0x68002101, +0x0800002e, +0x00000000, +0x0000139f, +0x00000000, +0x4400438f, +0xa410496a, +0x08104986, +0x00000000, +0x30000000, +0x94000000, +0x04000038, +0x00000000, +0x50000000, +0x51000101, +0x2800003d, +0x04000041, +0x00000000, +0x3400c000, +0x12005ee9, +0x1c20482e, +0x00000000, +0x3400c000, +0x12001ec9, +0x1c20482e, +0x00000000, +0x30000000, +0x51000101, +0x04104849, +0x00000000, +0x30000000, +0x13002189, +0x1c00004d, +0x00000000, +0x30000000, +0x61020202, +0x04000051, +0x00000000, +0x30000000, +0x52000000, +0x04000055, +0x00000000, +0x2400c000, +0x08000058, +0x00000000, +0x30000000, +0x80000000, +0x0410485c, +0x00000000, +0x3400400f, +0x52000000, +0x08000060, +0x00000000, +0x340204af, +0x31191910, +0x08000064, +0x00000000, +0x30000eaf, +0x51000101, +0x04000068, +0x00000000, +0x80000eaf, +0x0c000076, +0x10000079, +0x1460007c, +0x0400002e, +0x00000000, +0x340204af, +0x31191910, +0x08000072, +0x00000000, +0x3404ceaf, +0x51000101, +0x0980007f, +0x00000000, +0x240a0eaf, +0x0980007f, +0x00000000, +0x24050eaf, +0x0980007f, +0x00000000, +0x24010eaf, +0x0980007f, +0x00000000, +0x60000eaf, +0x65804884, +0x65800088, +0x0410488c, +0x00000000, +0x30000eaf, +0x41000300, +0x04000090, +0x00000000, +0x30000eaf, +0x41000100, +0x04000090, +0x00000000, +0x30000eaf, +0x41000000, +0x04000090, +0x00000000, +0x40000eaf, +0xa4000098, +0x04000094, +0x00000000, +0x30000000, +0x14eaed83, +0x1c000098, +0x00000000, +0x40000000, +0x2400009c, +0x0400009f, +0x00000000, +0x24010000, +0x0800009f, +0x00000000, +0x30000000, +0x80000000, +0x041048a3, +0x00000000, +0x34014005, +0x63000102, +0x080000a7, +0x00000000, +0x30000007, +0x50000001, +0x040000ab, +0x00000000, +0x30000007, +0x32202071, +0x040000af, +0x00000000, +0x30000007, +0x61030303, +0x040000b3, +0x00000000, +0x340202ef, +0x31202021, +0x080000b7, +0x00000000, +0x34050aef, +0x90000000, +0x080000bb, +0x00000000, +0x30000aef, +0x12000084, +0x040000bf, +0x00000000, +0x30000aef, +0x33000001, +0x040000c3, +0x00000000, +0x60000eaf, +0x658048c8, +0x658000cc, +0x041048d0, +0x00000000, +0x30000eaf, +0x41000301, +0x040000dc, +0x00000000, +0x30000eaf, +0x41000101, +0x040000dc, +0x00000000, +0x30000eaf, +0x41000001, +0x040000d4, +0x00000000, +0x30000eaf, +0x51000001, +0x040000d8, +0x00000000, +0x30000eaf, +0x3400109c, +0x040000dc, +0x00000000, +0x34190bef, +0x52000000, +0x080000e0, +0x00000000, +0x30000aef, +0x33000101, +0x040000e4, +0x00000000, +0xa0000eaf, +0x6da048eb, +0x658048ef, +0x619000f7, +0x69b000f3, +0x041048fb, +0x00000000, +0x30000eaf, +0x41030002, +0x04000103, +0x00000000, +0x30000eaf, +0x41000302, +0x0400011b, +0x00000000, +0x30000eaf, +0x41010002, +0x04000103, +0x00000000, +0x30000eaf, +0x41000102, +0x0400011b, +0x00000000, +0x30000eaf, +0x41000002, +0x040000ff, +0x00000000, +0x3000028f, +0x51000001, +0x04000182, +0x00000000, +0x5000028f, +0x51000001, +0xa0000182, +0x04000108, +0x00000000, +0x34010000, +0x14eaed83, +0x0800010c, +0x00000000, +0x24014005, +0x0800010f, +0x00000000, +0x3000128f, +0x3400289c, +0x04000113, +0x00000000, +0x3000128f, +0x35d4509c, +0x04000117, +0x00000000, +0x3000128f, +0x50000100, +0x04000157, +0x00000000, +0x7432028f, +0x65000003, +0x7c000121, +0x8010494f, +0x08000153, +0x00000000, +0x3000028f, +0x41000000, +0x04000125, +0x00000000, +0x8432028f, +0x84000133, +0x8010494f, +0x0810492b, +0x8810492f, +0x00000000, +0x3000008f, +0x41000000, +0x88104986, +0x00000000, +0x3000008f, +0x41000000, +0x04104830, +0x00000000, +0x34004005, +0x61020202, +0x08104937, +0x00000000, +0x6419000f, +0x8010493c, +0x0800012b, +0x8810492f, +0x00000000, +0x3000000f, +0x15eeea87, +0x1c000140, +0x00000000, +0x3000000f, +0x51000001, +0x04000144, +0x00000000, +0x24010000, +0x08000147, +0x00000000, +0x34010005, +0x61030303, +0x0800014b, +0x00000000, +0x30000007, +0x50000001, +0x0400014f, +0x00000000, +0x3000008f, +0x41000000, +0x88104830, +0x00000000, +0x3000038f, +0x01000000, +0x04000182, +0x00000000, +0x4577138f, +0x7000015f, +0x0800015b, +0x00000000, +0x3000038f, +0x51000100, +0x04000182, +0x00000000, +0x3000138f, +0x41000000, +0x04000163, +0x00000000, +0x3000138f, +0x65000003, +0x04000167, +0x00000000, +0x2000108f, +0x88104986, +0x00000000, +0x3000018f, +0x66000001, +0x0400016e, +0x00000000, +0x30000000, +0x61010101, +0x04000172, +0x00000000, +0x2403c00f, +0x08000175, +0x00000000, +0x5405000f, +0x95000000, +0xb400017a, +0x0800017e, +0x00000000, +0x3000000f, +0x52000001, +0x04000008, +0x00000000, +0x3000000f, +0x52000000, +0x0400000b, +0x00000000, +0x34010000, +0x14ecec83, +0x0870498a, +0x00000000, +0x34004000, +0x95000000, +0x0810480b, +0x00000000, +0x30000000, +0x80000000, +0x0410498e, +0x00000000, +0x30000000, +0x95000000, +0x04104992, +0x00000000, +0x30000000, +0x01000000, +0x04000196, +0x00000000, +0x30000000, +0x12000084, +0x04000026, +0x00000000, +0x3000008f, +0x14eaed83, +0x1c00019e, +0x00000000, +0x34010000, +0x52000000, +0x080001a2, +0x00000000, +0x24014005, +0x080001a5, +0x00000000, +0x3000128f, +0x3400209c, +0x040001a9, +0x00000000, +0x3000128f, +0x35d4509c, +0x040001ad, +0x00000000, +0x3000128f, +0x50000100, +0x040001b1, +0x00000000, +0x4577138f, +0x700001b5, +0x0800015b, +0x00000000, +0x3000138f, +0x41000000, +0x040001b9, +0x00000000, +0x3000138f, +0x65000003, +0x040001bd, +0x00000000, +0x2000138f, +0x88104986, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x00000000, +0x14010b0b +#endif +}; + +void phy_pre_agc_init(void) +{ + uint32_t i; + uint32_t len; + uint32_t *src, *dst; + uint32_t agc_cntl_reg; + uint32_t clk_ctrl_reg; + + agc_cntl_reg = agc_rwnxagccntl_get(); + agc_cntl_reg |= AGC_AGCFSMRESET_BIT; + agc_rwnxagccntl_set(agc_cntl_reg); + + clk_ctrl_reg = mdm_memclkctrl0_get(); + clk_ctrl_reg &= ~MDM_AGCMEMCLKCTRL_BIT; + mdm_memclkctrl0_set(clk_ctrl_reg); + + /*init agc parameters*/ + len = sizeof(agc_ram_parameter) >> 2; + dst = (uint32_t *)PHY_AGC_UCODE_ADDR; + src = (uint32_t *)agc_ram_parameter; + for(i = 0; i < len; i ++) + { + *dst ++ = *src ++; + } + + mdm_agcclkforce_setf(1); /*the issue about reset agc*/ + + agc_cntl_reg = agc_rwnxagccntl_get(); + agc_cntl_reg &= ~AGC_AGCFSMRESET_BIT; + agc_rwnxagccntl_set(agc_cntl_reg); + + clk_ctrl_reg = mdm_memclkctrl0_get(); + clk_ctrl_reg |= MDM_AGCMEMCLKCTRL_BIT; + mdm_memclkctrl0_set(clk_ctrl_reg); +} + +/** + **************************************************************************************** + * @brief Perform a write access on radio registers through the radio controller. + * The SPI command is sent only to the radios on the used RC paths (rc_path_sel). + * To limit the RC register access, the whole RC register value is set in one access + * except the START_DONE bit which will trigger the SPI transfer and also signal its end + * when cleared by HW. + * + * @param[in] addr Address of the register to write in. + * @param[in] value Value to write. + * + * @warning The function does not check the consistency of the parameters provided. + **************************************************************************************** + */ +void phy_rc_rf_reg_write(uint8_t addr, uint16_t value) +{ +} + +/** + **************************************************************************************** + * @brief Trident board IO Expander init. + * Given it is the components which routes important power down and lock detect signals, + * it should be initialized first before the components are interacted with. + **************************************************************************************** + */ +void phy_iox_init(void) +{ +} + +/** + **************************************************************************************** + * @brief Trident board 8b ADCs initialization for RSSI/Temperature/Power read back. + **************************************************************************************** + */ +//todo init or cfg in case we change ADCs during run for rssi/power? +void phy_adc8b_init(void) +{ + //do nothing, use reg force when we'll need fcns to gather data +} + +/** + **************************************************************************************** + * @brief Trident board 12b ADCs calibration. + **************************************************************************************** + */ +void phy_adc12b_init(void) +{ +#if (TIADC_VER == 1) //TI ADC + //disable RC auto power mode + trd_adc_autopower_setf(0); + + //reset ADCs, + trd_adc_reset_setf(1); + trd_adc_reset_setf(0); + // prescaler=6: spi_freq=80/(presc+1) ; max 20MHz + trd_adc_spi_prescaler_setf(4); + + //switch off all ADCs + phy_trd_adc_reg_write(0x00, 0x00D, 7); + + //switch on used ADC + phy_trd_adc_reg_write(0x00, 0x000, phy_env->rf_path_sel); + + //OTHER REG SETTINGS + phy_trd_adc_reg_write(0x04, 0x000, phy_env->rf_path_sel); + // 2's complement + phy_trd_adc_reg_write(0x0A, 0x000, phy_env->rf_path_sel); + phy_trd_adc_reg_write(0x0B, 0x000, phy_env->rf_path_sel); + //fine gain 6dB + phy_trd_adc_reg_write(0x0C, 0x600, phy_env->rf_path_sel); + //Override, byte wise, MSB first, coarse gain 3.5dB,12 bits serial,ddr clocking, 2 wire interface + phy_trd_adc_reg_write(0x0D, 0x421, phy_env->rf_path_sel); //401 without coarse gain + //termination, drive clk output + phy_trd_adc_reg_write(0x10, 0x000, phy_env->rf_path_sel); + //bit/byte wise, termination of data outputs + phy_trd_adc_reg_write(0x11, 0x000, phy_env->rf_path_sel); + + //DESERIALIZER---------------------------- + //Path A + if (phy_is_bit_set(phy_env->rf_path_sel, RF_PATH_A)) + { + //deserializer reset + trd_deser_cha_rst_n_setf(0); + //lift reset + trd_deser_cha_rst_n_setf(1); + + //deserializer calibration + trd_deser_cha_calib_start_setf(1); + //poll until done + while(!trd_deser_cha_calib_done_getf()); + + //todo does the start have to be put back to 0 by SW or auto-clear at done? + trd_deser_cha_calib_start_setf(0); + } + //Path B + if (phy_is_bit_set(phy_env->rf_path_sel, RF_PATH_B)) + { + //deserializer reset + trd_deser_chb_rst_n_setf(0); + //lift reset + trd_deser_chb_rst_n_setf(1); + + //deserializer calibration + trd_deser_chb_calib_start_setf(1); + //poll until done + while(!trd_deser_chb_calib_done_getf()); + + //todo does the start have to be put back to 0 by SW or auto-clear at done? + trd_deser_chb_calib_start_setf(0); + } + //Path C + if (phy_is_bit_set(phy_env->rf_path_sel, RF_PATH_C)) + { + //deserializer reset + trd_deser_chc_rst_n_setf(0); + //lift reset + trd_deser_chc_rst_n_setf(1); + + //deserializer calibration + trd_deser_chc_calib_start_setf(1); + //poll until done + while(!trd_deser_chc_calib_done_getf()); + + //todo does the start have to be put back to 0 by SW or auto-clear at done? + trd_deser_chc_calib_start_setf(0); + } + +#else //Beken ADC + + rc_adda_reg0_set(0x0801A554); + rc_adda_reg1_set(0x88924204); + rc_adda_reg2_set(0x10484806); + rc_adda_reg3_set(0x8C0C80C8); + rc_adda_reg4_set(0x03010000); + rc_adda_reg5_set(0xF80022ED); + + while(rc_adda_reg_stat_getf() & 0x3f); +#endif +} + +/** + **************************************************************************************** + * @brief Adjust TX digital gains wrt DC offset compensation to avoid DACs saturation + **************************************************************************************** + */ +static void adjust_txdiggains(uint32_t dc_cmp) +{ + uint8_t i_abscmp, j_abscmp, max_abscmps; + + i_abscmp = (dc_cmp & MDM_TXIDCOFFSET0_MASK) >> MDM_TXIDCOFFSET0_LSB; + j_abscmp = (dc_cmp & MDM_TXQDCOFFSET0_MASK) >> MDM_TXQDCOFFSET0_LSB; + max_abscmps = i_abscmp > j_abscmp ? i_abscmp : j_abscmp; + + // 12bits range + mdm_fectrl0_pack(MDM_TX80DIGGAINLIN0_RST, + MDM_TX40DIGGAINLIN0_RST * (2047 - max_abscmps) / 2047, + MDM_TX20DIGGAINLIN0_RST * (2047 - max_abscmps) / 2047); +} + + +/** + **************************************************************************************** + * @brief Modem initialization function. + * This function is called at reset time together with radio init, and + * prepares the modem for rx or tx. + **************************************************************************************** + */ +static void phy_mdm_init(uint32_t tx_dc_off_comp) +{ + intc_service_register(FIQ_MODEM, PRI_FIQ_MODEM, phy_mdm_isr); + + //turn on the 3 blocks: TX, AGC-CCA, RX - they are at 1 by default in regs ... + mdm_rxtxpwrctrl_pack(1, 1, 1); + + mdm_dcoffset0_set(tx_dc_off_comp); + adjust_txdiggains(tx_dc_off_comp); + + // Parameters for 40MHz bandwidth by default + mdm_txctrl0_set(0x00000168); + + mdm_rxctrl0_set(0x00160005); + mdm_tbectrl0_set(0x0C0F0702); + +#if (NX_MDM_VER == 11) + mdm_tbectrl2_set(0x0FF07005); +#endif + + mdm_waithtstf_setf(15); + mdm_delaynormalgi_setf(17); + + // CPE mode + mdm_cpemode_setf(0); + + // Enable CCA lock IRQ + mdm_irqctrl_set(MDM_IRQCCATIMEOUTEN_BIT); + +#if (CFG_SOC_NAME == SOC_BK7231N) + REG_WRITE((REG_MDM_CFG_BASE_ADDR + 0x226 * 4), REG_READ(REG_MDM_CFG_BASE_ADDR + 0x226 * 4) & 0xFFFE); //peak_cancel_bypass=0 +#endif + + PHY_WPRT("phy_mdm_init-->Static MDM settings done\r\n"); +} + + +void phy_enable_lsig_intr(void) +{ + uint32_t val; + + val = mdm_irqctrl_get(); + val |= MDM_IRQLSIGVALIDEN_BIT; + mdm_irqctrl_set(val); + + os_printf("lsigEn-0x2000:%x\r\n", mdm_irqctrl_get()); + +} + +void phy_disable_lsig_intr(void) +{ + uint32_t val; + + val = mdm_irqctrl_get(); + val &= (~MDM_IRQLSIGVALIDEN_BIT); + mdm_irqctrl_set(val); + + os_printf("lsigDis-0x2000:%x\r\n", mdm_irqctrl_get()); +} + + +/** + **************************************************************************************** + * @brief AGC initialization function. + **************************************************************************************** + */ +static void phy_agc_init(void) +{ + phy_pre_agc_init(); + + // AGC events +#if (NX_MDM_VER == 10) + agc_rwnxagcevt2_set(0x3955b004); +#else +#if (CFG_SOC_NAME == SOC_BK7231N) + /* qunshan20210325 change from 0x806 to 0x506,aim to increase RSSI +3 */ + REG_PL_WR(REG_AGC_BASE_ADDR + 0x890, 0x506); // Enable AGC OPT + agc_rwnxagcevtsat_set(0x05044804); + agc_rwnxagcevtdet_set(0x3D401008); + agc_rwnxagcevtdis_set(0x3955B00B); + agc_rwnxagcevtdsssdet_set(0x3ff7500f); + + // ADC sat thd + agc_rwnxagcsat_set(0x8373335); +#else + REG_PL_WR(REG_AGC_BASE_ADDR + 0x890, (REG_PL_RD(REG_AGC_BASE_ADDR + 0x890) | 0x2)); // Enable AGC OPT + agc_rwnxagcevtsat_set(0x05044804); + agc_rwnxagcevtdet_set(0x3D401008); + agc_rwnxagcevtdis_set(0x3955B00B); + agc_rwnxagcevtdsssdet_set(0x3ff7500f); + + // ADC sat thd + agc_rwnxagcsat_set(0x8373335); +#endif +#endif + + //agc_rwnxagcevt2_set(0x3955b004); + + // AGCCROSS (disable crossing detection) + agc_rwnxagccross_set(0x002803f0); + + // AGCRAMP (reduce ramp-down detection level) + agc_rwnxagcramp_set(0x07200710); + + // RWNXAGCCCA1 (CCA{FALL,RISE}THRDBM) + // for when RWNXAGCCCACTRL[CCAENERGYEN] is on +#if defined(CFG_SYS_CLOSE_CCA) + agc_rwnxagccca1_set((agc_rwnxagccca1_get() & ~0x000ff0ff) | 0x000bf0c3); +#else + agc_rwnxagccca1_set((agc_rwnxagccca1_get() & ~0x000ff1ff) | 0x000bf0c3); +#endif + //os_printf("agc_rwnxagccca1=0x%x\n", agc_rwnxagccca1_get()); + + // RWNXAGCCCACTRL + agc_rwnxagcccactrl_set((agc_rwnxagcccactrl_get() & ~0x00000fff) | 0x00000377); + + // Configure CCA timeout + agc_rwnxagcccatimeout_set(8000000); // 100ms + + // AGCGain Range +#if (CFG_SOC_NAME == SOC_BK7231N) + agc_rwnxagcgainrg_set(0x4e08); +#else + agc_rfgainmaxdb_setf(0x4b); +#endif + + // AGC Power Estimate Bias +#if (CFG_SOC_NAME == SOC_BK7231N) + agc_vpeakadcqdbv_setf((uint8_t) - 32); //change MDM_reg819<23:16> from 0xEC to 0xE0 by cunliang20201112 +#else + agc_vpeakadcqdbv_setf((uint8_t) - 32); +#endif + + PHY_WPRT("phy_agc_init-->cca\r\n"); + +} + +/** + **************************************************************************************** + * @brief Set band 2.4GHz/5GHz in RC and RF chips. + * @param[in] band Band value - 0=2.4GHz, 1=5GHz + * @param[in] freq Channel frequency in MHz + **************************************************************************************** + */ +static void phy_set_band(uint8_t band, uint16_t freq) +{ + //MDM and AGC band related settings + if (band == PHY_BAND_2G4) + { + //mdm settings + mdm_rxallowdsss_setf(1); + //agc cca + agc_ofdmonly_setf(0); + } + else + { + //mdm settings + mdm_rxallowdsss_setf(0); + //agc cca + agc_ofdmonly_setf(1); + } +} + +/** + **************************************************************************************** + * @brief Function used to regroup the waiting , polling and Lock Detect values + * @return Boolean value of lock state: true=locked, false=lock failed + **************************************************************************************** + */ +static bool phy_locked(void) +{ + return true; +} + +#if !CFG_SUPPORT_CALIBRATION +#define RC_TRX_REG28_ADDR 0x08628078 + +__INLINE void rc_trx_reg28_set(uint32_t value) +{ + REG_PL_WR(RC_TRX_REG28_ADDR, value); +} +#endif +/** + **************************************************************************************** + * @brief MAXIM Radio(s) initialization function. + * This function is called at FW initialization or after phy_stop(). + * It will set RC register values and also RF register value using RC SPI control. Most + * of the register values set in the radio(s) are static for the duration of SW run. + **************************************************************************************** + */ +#if CFG_SUPPORT_CALIBRATION +extern INT32 rwnx_cal_load_trx_rcbekn_reg_val(void); +#endif +static void phy_rf_init(void) +{ +#if !CFG_SUPPORT_CALIBRATION + //initial Beken TRX +#if (CFG_RUNNING_PLATFORM == FPGA_PLATFORM) + rc_trx_reg0_set(0x0813EF5E); //RF Config. V1.6 + rc_trx_reg1_set(0x01000000); + rc_trx_reg2_set(0x00000000); + rc_trx_reg3_set(0x00000000); + rc_trx_reg4_set(0x28021D00); + rc_trx_reg5_set(0x05326C7A); + rc_trx_reg6_set(0x72ec820e); //0x00FF104C + rc_trx_reg7_set(0x0922483E); //0x0922483F 20150630 + rc_trx_reg8_set(0x0768A94A); + rc_trx_reg9_set(0x000003AF); + rc_trx_reg10_set(0x82383330); + rc_trx_reg11_set(0x16A46D84); + rc_trx_reg12_set(0x01A187DD);// //0x01A184CC 722 //0x01A187FF //0x01A1F4F1 Feb 09 2015 Allen + rc_trx_reg13_set(0xFDF90238); + rc_trx_reg14_set(0xFA01BCF0); + rc_trx_reg15_set(0x40000030); + rc_trx_reg16_set(0xF0000000); + rc_trx_reg17_set(0x00000000); + rc_trx_reg18_set(0x202D5D01);//0x206D5D01 + rc_trx_reg19_set(0x05164145); + rc_trx_reg20_set(0x8080FF30); // + rc_trx_reg21_set(0x80808080); + rc_trx_reg22_set(0x80808080); + rc_trx_reg23_set(0x80808080); + rc_trx_reg24_set(0x80808080); + rc_trx_reg25_set(0x80808080); + rc_trx_reg26_set(0x80808080); + rc_trx_reg27_set(0x80808080); + rc_trx_reg28_set(0x2004AFF9); +#else + rc_trx_reg0_set(0x0811EF5E); + rc_trx_reg1_set(0x01000000); + rc_trx_reg2_set(0x00000000); + rc_trx_reg3_set(0x00000000); + rc_trx_reg4_set(0x38025E88); + rc_trx_reg5_set(0x2555EC7A); + rc_trx_reg6_set(0x5FA4410C); + rc_trx_reg7_set(0x202C48F5); + rc_trx_reg8_set(0x076CA9CA); + rc_trx_reg9_set(0x000003AF); + rc_trx_reg10_set(0x82382330); + rc_trx_reg11_set(0x28444884); + rc_trx_reg12_set(0x01A183FD); + rc_trx_reg13_set(0xDDF90339); + rc_trx_reg14_set(0xDA01BCF0); + rc_trx_reg15_set(0x00018000); + rc_trx_reg16_set(0xD0000000); + rc_trx_reg17_set(0x00000000); + rc_trx_reg18_set(0xD0000C01); + rc_trx_reg19_set(0x7B305ECC); + rc_trx_reg20_set(0x827C827C); + rc_trx_reg21_set(0x86788678); + rc_trx_reg22_set(0x8C748C74); + rc_trx_reg23_set(0xA45F9868); + rc_trx_reg24_set(0xA45FA45F); + rc_trx_reg25_set(0xA55EA45F); + rc_trx_reg26_set(0xA55DA55E); + rc_trx_reg27_set(0xA55DA55D); + rc_trx_reg28_set(0x20000000); +#endif +#else + +#endif + + while(rc_beken_spi_get() & 0x0fffffff); //wait rf register write done + + rc_ch0_rx_onoff_delay_pack( 1, 1); + rc_ch0_tx_onoff_delay_pack( 1, 1); //old on delay 0x41 + rc_ch0_pa_onoff_delay_pack( 1, 0x10);//old on delay 0x41 + rc_ch0_shdn_onoff_delay_pack(1, 1); + rc_ch0_en_setf(1); + + rc_rc_en_setf(1); + PHY_WPRT("phy_rf_init-->RC static regs set and RC enabled\r\n"); + + if (!phy_locked()) + { + //todo do what??? + } +} + +/** + **************************************************************************************** + * @brief Trident board components init + **************************************************************************************** + */ +void phy_rcbeken_init() +{ +#if !CFG_SUPPORT_CALIBRATION +#if (CFG_RUNNING_PLATFORM == FPGA_PLATFORM) + rc_beken_spi_set(0x70000000); //set spi_prescaler. spi clock frequency set 5Mbps + rc_ch0_force_set(0x00010003); + rc_misc_force_set(0x00000001); + + //rc_rx_avg_calc_set(0x2004aff9); //huaming + rc_rx_avg_calc_set(0x3004aff9); + rc_rx_calib_en_set(0x00); // 0x4004aff9 + rc_rx_dc_wr_set(0x0004aff9); + rc_rx_error_wr_set(0x01ff0000); + rc_tx_mode_cfg_set(0x06000200); + rc_tx_sin_cfg_set(0x2cc0c000); + rc_tx_dc_comp_set(0x0202020b); + rc_tx_gain_comp_set(0x03ff03e0); //20150722 0x03ff03e2 + + rc_tx_phase_ty2_comp_set(0x021D01FE); + rc_tx_other_cfg_set(0xc8ac9d40); + + rc_agc_cfg_set(0x00445460); + rc_trx_spi_intlv_set(0x00000064); + +#else + rc_beken_spi_set(0xF0000000); //set spi_prescaler. spi clock frequency set 5Mbps + rc_ch0_force_set(0x00010005); + rc_misc_force_set(0x00000002); + + //rc_rx_avg_calc_set(0x2004aff9); //huaming + rc_rx_avg_calc_set(0x1002DF4B); + rc_rx_calib_en_set(0x00000000); // 0x4004aff9 + rc_rx_dc_wr_set(0x00000000); + rc_rx_error_wr_set(0x020003EC); + rc_tx_mode_cfg_set(0x218B018B); + rc_tx_sin_cfg_set(0x2CC02000); + rc_tx_dc_comp_set(0x020201F1); + rc_tx_gain_comp_set(0x03FF03F3); //20150722 0x03ff03e2 + + rc_tx_phase_ty2_comp_set(0x01F80200); + rc_tx_other_cfg_set(0x48A79D40); // soc platform, rc_beken 0x1050148<31bit> should be 0 + + rc_agc_cfg_set(0x0002567A); + rc_trx_spi_intlv_set(0x80000064); + +#endif +#else + rwnx_cal_load_trx_rcbekn_reg_val(); +#endif + rc_dsel_va_setf(0x1); /* TSSI or AGC gain setting for versiong A, output 0: TSSI 1:AGC gain setting*/ +} + +static void phy_trident_init(void) +{ + //IO Expander first - special component + phy_iox_init(); + + //RF Reset + rc_spi_reset_setf(1); + rc_spi_reset_setf(0); + + phy_rcbeken_init(); //rc_beken initial + + PHY_WPRT("phy_trident_init-->RF register reset done\r\n"); + + //phy path to rf path mapping (given at phy init from nvds) + + //front end delay + rc_fe_rx_del_set(0x12c); + + phy_adc12b_init(); + phy_adc8b_init(); +} + +static int force2040_toggle(uint8_t chantype) +{ + uint32_t rxmodes, f2040_val, f2040_msk; + volatile uint32_t i; + + f2040_msk = MDM_FORCE40_BIT | MDM_FORCE20_BIT; + if (chantype == PHY_CHNL_BW_20) + f2040_val = MDM_FORCE20_BIT; + else if (chantype == PHY_CHNL_BW_40) + f2040_val = MDM_FORCE40_BIT; + else + f2040_val = 0; + + rxmodes = (mdm_rxmodes_get() & ~f2040_msk) | f2040_val; + + mdm_rxmodes_set(rxmodes); + for(i = 0; i < 1000; i ++); + + /* + modem reset + */ + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_MODEM_CORE_RESET, 0); + + /* init some paramters of rf */ + phy_trident_init(); + phy_rf_init(); + + return 0; +} + +/** + **************************************************************************************** + * @brief Bandwidth change function. + * This function is called during set channel procedure if the bandwidth configuration + * has changed + * + * @param[in] bw Bandwidth type + **************************************************************************************** + */ +static void phy_change_bw(uint8_t bw) +{ + switch(bw) + { + case PHY_CHNL_BW_20: + mdm_txstartdelay_setf(0x000000b4); + mdm_tbectrl0_set(0x0C0F0700); + +#if (NX_MDM_VER == 11) + mdm_tbectrl2_set(0x00F07005); +#endif + + agc_rwnxagcaci20marg0_set(0); + agc_rwnxagcaci20marg1_set(0); + agc_rwnxagcaci20marg2_set(0); + break; + + case PHY_CHNL_BW_40: + mdm_txstartdelay_setf(0x00000160); + mdm_tbectrl0_set(0x0C0F0702); + +#if (NX_MDM_VER == 11) + mdm_tbectrl2_set(0x0FF07005); +#endif + + agc_rwnxagcaci20marg0_set(AGC_RWNXAGCACI20MARG0_RESET); + agc_rwnxagcaci20marg1_set(AGC_RWNXAGCACI20MARG1_RESET); + agc_rwnxagcaci20marg2_set(AGC_RWNXAGCACI20MARG2_RESET); + break; + + case PHY_CHNL_BW_80: + case PHY_CHNL_BW_160: + case PHY_CHNL_BW_80P80: + break; + default: + break; + } + + force2040_toggle(bw); +} + +void phy_init(const struct phy_cfg_tag *config) +{ + const struct phy_trd_cfg_tag *cfg = (const struct phy_trd_cfg_tag *)&config->parameters; + + //PHY ENVIRONMENT--------------------------------------------------------------------- + //mapping mdm phy paths to rf phy paths + phy_env->phy2rf = cfg->path_mapping & (0x0F); + + //Extract which RC and RF paths are used, MIMO or not + phy_get_config(cfg->path_mapping); + + //Band = 2.4GHz by default + phy_env->band = + phy_env->chnl_prim20_freq = + phy_env->chnl_center1_freq = + phy_env->chnl_center2_freq = + phy_env->chnl_type = PHY_UNUSED; + + PHY_WPRT("phy_init-->RC_PATHs=0x%X , RF_PATHS=0x%X\n", phy_env->rc_path_sel, phy_env->rf_path_sel); + + //PHY blocks initialization----------------------------------------------------------- + //TRIDENT components + phy_trident_init(); + + //Radios alone through RC + phy_rf_init(); + + //MODEM - contains AGC? + phy_mdm_init(cfg->tx_dc_off_comp); + + //AGC - separate or in MDM? + phy_agc_init(); + +#if defined(CFG_SYS_CLOSE_CCA) + extern uint8_t phy_close_cca(void); + phy_close_cca(); +#endif +} + +void rcbeken_reconfigure(void) +{ + UINT32 tmp; + + phy_rcbeken_init(); + rc_fe_rx_del_set(0x12c); + + /*restore phy channel*/ + #if (CFG_SOC_NAME == SOC_BK7231) + tmp = rc_trx_reg7_getf(); + tmp = (tmp & 0xff01ffff) | ((phy_env->chnl_center1_freq - 2400) << 17); + rc_trx_reg7_set(tmp); + #else + tmp = rc_trx_reg5_getf(); + tmp = (tmp & 0x01ffffff) | ((phy_env->chnl_center1_freq - 2400) << 25); + rc_trx_reg5_set(tmp); + #endif // (CFG_SOC_NAME == SOC_BK7231) + + rc_ch0_rx_onoff_delay_pack( 1, 1); + rc_ch0_tx_onoff_delay_pack( 1, 1); //old on delay 0x41 + rc_ch0_pa_onoff_delay_pack( 1, 0x10);//old on delay 0x41 + rc_ch0_shdn_onoff_delay_pack(1, 1); + rc_ch0_en_setf(1); + rc_rc_en_setf(1); +} + +#define RXVECT1_ARRAY_MAX 30 + +void phy_unsupported_modulation_check(void) +{ + uint32_t rx_vect0; + uint32_t rx_vect1[RXVECT1_ARRAY_MAX]; + uint32_t rx_vect2; + int8_t rx_rssi; + uint16_t rx_length, mcs; + int i; + + rx_vect0 = mdm_rxvector0_get(); + + do + { + // Ensure that the packet could be a non-legacy one + if ((rx_vect0 & MDM_RXLEGRATE_MASK) != (11 << MDM_RXLEGRATE_LSB)) + break; + + // Read the RSSI, which is already available + rx_rssi = 0xFF00 | mdm_rssi1_getf(); + if (rx_rssi < -40) + break; + + // Poll on the RXFORMAT until it is equal to HT, or timeout otherwise + // This loop duration, if we timeout, shall be at least 4us + for (i=0; i<100; i++) + { + rx_vect2 = mdm_rxvector2_get(); + if ((rx_vect2 & MDM_RXFORMAT_MASK) == 2) + break; + } + + // Check if the received format is HT + if ((rx_vect2 & MDM_RXFORMAT_MASK) != 2) + break; + //os_printf("HT Format\r\n"); + // Now read the RX vector 1 several times and store each value + // The duration between the first and the last read shall be around 6us + // This reads are done sequentially and not in a loop because the RX + // vector 1 is valid only for a few hundreds of ns and we don't want to + // suffer from the overhead of the looping + i = 0; + rx_vect1[i++] = mdm_rxvector1_get(); + rx_vect1[i++] = mdm_rxvector1_get(); + rx_vect1[i++] = mdm_rxvector1_get(); + rx_vect1[i++] = mdm_rxvector1_get(); + rx_vect1[i++] = mdm_rxvector1_get(); + rx_vect1[i++] = mdm_rxvector1_get(); + rx_vect1[i++] = mdm_rxvector1_get(); + rx_vect1[i++] = mdm_rxvector1_get(); + rx_vect1[i++] = mdm_rxvector1_get(); + rx_vect1[i++] = mdm_rxvector1_get(); + rx_vect1[i++] = mdm_rxvector1_get(); + rx_vect1[i++] = mdm_rxvector1_get(); + rx_vect1[i++] = mdm_rxvector1_get(); + rx_vect1[i++] = mdm_rxvector1_get(); + rx_vect1[i++] = mdm_rxvector1_get(); + rx_vect1[i++] = mdm_rxvector1_get(); + rx_vect1[i++] = mdm_rxvector1_get(); + rx_vect1[i++] = mdm_rxvector1_get(); + rx_vect1[i++] = mdm_rxvector1_get(); + rx_vect1[i++] = mdm_rxvector1_get(); + rx_vect1[i++] = mdm_rxvector1_get(); + rx_vect1[i++] = mdm_rxvector1_get(); + rx_vect1[i++] = mdm_rxvector1_get(); + rx_vect1[i++] = mdm_rxvector1_get(); + rx_vect1[i++] = mdm_rxvector1_get(); + rx_vect1[i++] = mdm_rxvector1_get(); + rx_vect1[i++] = mdm_rxvector1_get(); + rx_vect1[i++] = mdm_rxvector1_get(); + rx_vect1[i++] = mdm_rxvector1_get(); + rx_vect1[i++] = mdm_rxvector1_get(); // Don't read beyond the array size you defined !!! + + // Search in the RX vector 1 array the index of the latest non-null + // length value + for (i=(RXVECT1_ARRAY_MAX - 1); i>=0; i--) + { + if ((rx_vect1[i] & MDM_RXHTLENGTH_MASK) != 0) + break; + } + + // If we did not find any non-null length, don't consider the packet + if (i == -1) + break; + + //REG_WRITE( (0x0802800 +(17*4)), 0); + //os_printf("HT Format Length %d (i=%d) rssi=%d\r\n",rx_vect1[i] & MDM_RXHTLENGTH_MASK,i,rx_rssi); + // Check if the modulation is supported. We know that by checking if the + // index of the latest non-null length is the last one. Indeed in case + // the modulation is supported, the value of the rx vector 1 is kept valid + // until the end of the reception. Otherwise it is reset only a few hundreds + // of ns after becoming valid. Having a valid length in the latest RX vector 1 + // read therefore means that the modulation is supported and the packet will + // be uploaded in the normal RX path + if (i == (RXVECT1_ARRAY_MAX - 1)) + break; + + // Unsupported modulation received + // TODO Forward the length and RSSI indication of this packet to the upper layers + rx_length = rx_vect1[i] & MDM_RXHTLENGTH_MASK; + + mcs = ((rx_vect1[i] & MDM_RXMCS_MASK) >> MDM_RXMCS_LSB); + //if((mcs < 8) || (mcs > 15)) + { + //break; + } + + #if 1 + os_printf("Length %d (%d-%d), rssi %d, mcs %d, idx %i\n", + rx_length, + rx_vect1[i-1] & MDM_RXHTLENGTH_MASK, + rx_vect1[i+1] & MDM_RXHTLENGTH_MASK, + rx_rssi, + mcs, + i); + #else + hal_monitor_sig_content(100 + rx_rssi, rx_length); + #endif + } while(0); +} + +extern void rwnx_cal_set_rxswitch(UINT32 enable); +extern UINT32 rwnx_cal_get_rxswitch(void); + + +void phy_enable_rx_switch(void) +{ + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + rwnx_cal_set_rxswitch(1); + GLOBAL_INT_RESTORE(); + +} + +void phy_disable_rx_switch(void) +{ + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + rwnx_cal_set_rxswitch(0); + GLOBAL_INT_RESTORE(); + +} + +static uint8_t large_singal_status; + +uint8_t check_large_singal_status(void) +{ + return large_singal_status; +} + +void update_large_singal_status(uint8_t status) +{ + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + large_singal_status = status; + GLOBAL_INT_RESTORE(); +} + +int large_signal_cnt; +int small_signal_cnt; +int no_action_signal_cnt; +void phy_large_signal_support(int8_t rssi) +{ + extern int large_signal_cnt; + extern int small_signal_cnt; + + uint32_t rxswitch_en; + + GLOBAL_INT_DECLARATION(); + rxswitch_en = rwnx_cal_get_rxswitch(); + + if (rssi >= 128) + { + rssi -= 256; + } + if (!rxswitch_en) + { + rssi += 15; + } + + if (rssi >= -25) + { + large_signal_cnt ++; + small_signal_cnt = 0; + no_action_signal_cnt = 0; + } + else if (rssi <= -35) + { + large_signal_cnt = 0; + small_signal_cnt ++; + no_action_signal_cnt = 0; + } + else + { + no_action_signal_cnt++; + if(no_action_signal_cnt >= large_signal_cnt) + large_signal_cnt = 0; + if(no_action_signal_cnt >= small_signal_cnt) + small_signal_cnt = 0; + } + + if (rxswitch_en && (large_signal_cnt >= 10)) + { + //close rx switch + GLOBAL_INT_DISABLE(); + large_singal_status = 1; + phy_disable_rx_switch(); + GLOBAL_INT_RESTORE(); + } + + if(!rxswitch_en && (small_signal_cnt >= 10)) + { + //open rx switch + GLOBAL_INT_DISABLE(); + large_singal_status = 0; + phy_enable_rx_switch(); + GLOBAL_INT_RESTORE(); + } +} + +void phy_mdm_isr(void) +{ + uint32_t irq_status = mdm_irqstat_get(); + + // Acknowledge the pending interrupts + mdm_irqack_set(irq_status); + + if (irq_status & MDM_IRQLSIGVALIDEN_BIT) + { +#if CFG_RX_SENSITIVITY_TEST + extern UINT32 g_rxsens_start; + if (g_rxsens_start) + phy_large_signal_support(mdm_rssi1_getf()); + else +#endif + phy_unsupported_modulation_check(); + } + + ASSERT_REC(!(irq_status & MDM_IRQCCATIMEOUT_BIT)); +} + +void phy_rc_isr(void) +{ +} + +void phy_get_version(uint32_t *version_1, uint32_t *version_2) +{ + *version_1 = mdm_nxversion_get(); + // TODO Add version reading for other PHY elements than modem. + *version_2 = 0; +} + +extern void rwnx_cal_set_40M_setting(void); +void phy_set_channel(uint8_t band, uint8_t type, uint16_t prim20_freq, + uint16_t center1_freq, uint16_t center2_freq, uint8_t index) +{ + /*todo 11ac: when 2 radio transceivers on one path, careful how many writes go to both, + and when the two need separate SPi commands*/ + uint8_t psel = 0; + uint32_t tmp; + + //if same channel is set just skip + if ((phy_env->band == band) + && (phy_env->chnl_type == type) + && (phy_env->chnl_prim20_freq == prim20_freq) + && (phy_env->chnl_center1_freq == center1_freq) + && (phy_env->chnl_center2_freq == center2_freq)) + { + return; + } + + PHY_WPRT("phy_set_channel-->center1:%d center2:%d\r\n", center1_freq, center2_freq); + //todo add check for band 5+type 80, 160 and 80+80 + + /* Every time a channel is changed, RC is disabled causing the entire PHY shut down. + * Once all settings are made, RC is enable and SW polls status of wake up and lock + * to know when ready to use + */ + //Disable RC to turn everything off + rc_rc_en_setf(0); + //todo poll shutdown status bits for radios of interest + + if (phy_env->chnl_type != type) + { + phy_change_bw(type); + } + + //keep currently set values + phy_env->band = band; + phy_env->chnl_type = type; + phy_env->chnl_prim20_freq = prim20_freq; + phy_env->chnl_center1_freq = center1_freq; + phy_env->chnl_center2_freq = center2_freq; + + //BAND-------------------------------------------------------------------------------- + //set band info where needed(RC, Radios, ...) + phy_set_band(band, center1_freq); + + //TYPE-------------------------------------------------------------------------------- + //todo what values for LPF in RF?Now it's at default + switch(type) + { + case PHY_CHNL_BW_20: + psel = 0; + break; + + case PHY_CHNL_BW_40: + psel = (center1_freq + 10 - prim20_freq) / 20; + break; + + case PHY_CHNL_BW_80: + psel = (prim20_freq - (center1_freq - 30)) / 20; + case PHY_CHNL_BW_160: + case PHY_CHNL_BW_80P80: + break; + } + + //CHANNEL----------------------------------------------------------------------------- + + //Set Channel for Beken TRX + #if (CFG_SOC_NAME == SOC_BK7231) + tmp = rc_trx_reg7_getf(); + tmp = (tmp & 0xff01ffff) | ((center1_freq - 2400) << 17); + rc_trx_reg7_set(tmp); + #else + tmp = rc_trx_reg5_getf(); + tmp = (tmp & 0x01ffffff) | ((center1_freq - 2400) << 25); + rc_trx_reg5_set(tmp); + #endif // (CFG_SOC_NAME == SOC_BK7231) + + // Set the PSEL value in modem + mdm_psselect20_setf(psel & 0x01); + mdm_psselect40_setf((psel & 0x02) >> 1); + + //Enable RC and thus trigger the configuration start + rc_rc_en_setf(1); + + //Lock-------------------------------------------------------------------------------- + if (!phy_locked()) + { + //failure measures - reset, shut down... + } + + rc_ch0_tx_onoff_delay_set(0x00010010); + rc_ch0_pa_onoff_delay_set(0x000A00E0); + + if(type == PHY_CHNL_BW_40) { + rwnx_cal_set_40M_setting(); + } + else + { +#if (SOC_BK7231N == CFG_SOC_NAME) + extern void rwnx_cal_set_20M_setting(void); + rwnx_cal_set_20M_setting(); +#endif + } + +} + +void phy_get_channel(struct phy_channel_info *info, uint8_t index) +{ + // Map the band, channel type, primary channel index and center 1 index on info1 + info->info1 = phy_env->band | (phy_env->chnl_type << 8) | (phy_env->chnl_prim20_freq << 16); + + // Map center 2 index on info2 + info->info2 = phy_env->chnl_center1_freq | (phy_env->chnl_center2_freq << 16); +} + +void phy_stop(void) +{ + //RC disable only - everything will be shut down + rc_rc_en_setf(0); + + //todo stop modem and trident components too? + //todo anything else? +} + + +bool phy_has_radar_pulse(int rd_idx) +{ + return (mdm_radfifoempty_getf() == 0); +} + +bool phy_get_radar_pulse(int rd_idx, struct phy_radar_pulse *pulse) +{ + // Check if FIFO is empty + if (mdm_radfifoempty_getf()) + return (false); + + // FIFO is not empty, get an element + pulse->pulse = REG_PL_RD(0x60C04000); + + return (true); +} + +void phy_agc_reset(void) +{ + uint32_t mdm_reg; + + mdm_reg = mdm_swreset_get(); + mdm_reg |= MDM_MDMSWRESET_BIT; + mdm_swreset_set(mdm_reg); + + delay(10); + + mdm_reg = mdm_swreset_get(); + mdm_reg &= ~MDM_MDMSWRESET_BIT; + mdm_swreset_set(mdm_reg); +} + +bool phy_bfmee_supported(void) +{ + return false; +} + + +bool phy_bfmer_supported(void) +{ + return false; +} + +bool phy_mu_mimo_rx_supported(void) +{ + return false; +} + +bool phy_mu_mimo_tx_supported(void) +{ + return false; +} + +#if RW_MUMIMO_RX_EN +void phy_set_group_id_info(uint32_t membership_addr, uint32_t userpos_addr) +{ +} +#endif + +uint8_t phy_get_nss(void) +{ + return 0; +} + +uint8_t phy_get_ntx(void) +{ + return (0); +} + +//cca ctrl +void phy_open_cca(void) +{ + agc_rwnxagcccactrl_set((agc_rwnxagcccactrl_get() & ~0x00000fff) | 0x00000377); +} + +void phy_close_cca(void) +{ + agc_rwnxagcccactrl_set((agc_rwnxagcccactrl_get() & ~0x00000fff) & ~(0x00000377)); +} + +void phy_show_cca(void) +{ +} +/** + * TX power = idx * 0.5 + TX_GAIN_MIN + PA_GAIN + * + * idx = 2 * (TX power - TX_GAIN_MIN - PA_GAIN) + * + * idx = TX power - 5;//tpc + */ +void phy_get_rf_gain_idx(int8_t *power, uint8_t *idx) +{ + int8_t min, max, oft; + + if (phy_env->band == PHY_BAND_2G4) + { + min = PHY_TRIDENT_MIN_PWR_24G; +#if PHY_TRIDENT_LIMIT_PWR > PHY_TRIDENT_MAX_PWR_24G + max = PHY_TRIDENT_MAX_PWR_24G; +#else + max = PHY_TRIDENT_LIMIT_PWR; +#endif + oft = (PHY_TRIDENT_TX_GAIN_MIN + PHY_TRIDENT_PA_GAIN_24G); + } + else + { + min = PHY_TRIDENT_MIN_PWR_5G; +#if PHY_TRIDENT_LIMIT_PWR > PHY_TRIDENT_MAX_PWR_24G + max = PHY_TRIDENT_MAX_PWR_5G; +#else + max = PHY_TRIDENT_LIMIT_PWR; +#endif + oft = (PHY_TRIDENT_TX_GAIN_MIN + PHY_TRIDENT_PA_GAIN_5G); + } + + if (*power > max) + { + *power = max; + } + else if (*power < min) + { + *power = min; + } + + *idx = 2 * (*power - oft); +} + +void phy_get_rf_gain_capab(int8_t *max, int8_t *min) +{ + if (phy_env->band == PHY_BAND_2G4) + { + *max = PHY_TRIDENT_MAX_PWR_24G; + *min = PHY_TRIDENT_MIN_PWR_24G; + } + else + { + *max = PHY_TRIDENT_MAX_PWR_5G; + *min = PHY_TRIDENT_MIN_PWR_5G; + } +} + +void rc_reset_patch(void) +{ + if(rc_rc_en_getf() == 0) + { + os_printf("********* RC_BEKEN_RESET ***********!\r\n"); + + rcbeken_reconfigure(); + phy_agc_reset(); + } +} + +void phy_init_after_wakeup(void) +{ + uint16_t freq; + struct phy_cfg_tag cfg; + + freq = phy_env->chnl_center1_freq; + phy_env->chnl_center1_freq = 0; + + cfg.parameters[0] = 1; + cfg.parameters[1] = 0; + phy_init(&cfg); + + phy_set_channel(PHY_BAND_2G4, PHY_CHNL_BW_20, freq, freq, 0, PHY_PRIM); +} + +void phy_wakeup_rf_reinit(void) +{ + struct phy_env_tag phy_env_sleep; + + phy_env_sleep.band = phy_env->band; + phy_env_sleep.chnl_prim20_freq = phy_env->chnl_prim20_freq; + phy_env_sleep.chnl_center1_freq = phy_env->chnl_center1_freq; + phy_env_sleep.chnl_center2_freq = phy_env->chnl_center2_freq; + phy_env_sleep.chnl_type = phy_env->chnl_type; + + phy_env->band = + phy_env->chnl_prim20_freq = + phy_env->chnl_center1_freq = + phy_env->chnl_center2_freq = + phy_env->chnl_type = PHY_UNUSED; + + // recover trx setting + rwnx_cal_recover_rf_setting(); + + //MODEM - contains AGC? + phy_mdm_init(0); + + // recover channel setting + phy_set_channel(phy_env_sleep.band, phy_env_sleep.chnl_type, phy_env_sleep.chnl_prim20_freq, + phy_env_sleep.chnl_center1_freq, phy_env_sleep.chnl_center2_freq, PHY_PRIM); + +} + +void phy_wakeup_wifi_reinit(void) +{ + + //AGC - separate or in MDM? + phy_agc_init(); + + rwnx_cal_recover_wifi_setting(); +} +/// @} + diff --git a/beken_os/beken378/driver/phy/phy_trident.h b/beken_os/beken378/driver/phy/phy_trident.h new file mode 100755 index 0000000..3f79c06 --- /dev/null +++ b/beken_os/beken378/driver/phy/phy_trident.h @@ -0,0 +1,468 @@ +/** + **************************************************************************************** + * + * @file phy_trident.h + * + * @brief File containing the nX Trident Radio register access functions and defines. + * + * Copyright (C) RivieraWaves 2011-2016 + * + **************************************************************************************** + */ +#ifndef PHY_TRIDENT_H_ +#define PHY_TRIDENT_H_ + +#define PHY_DEBUG + +#ifdef PHY_DEBUG +#define PHY_PRT os_printf +#define PHY_WPRT os_null_printf +#else +#define PHY_PRT os_null_printf +#define PHY_WPRT os_null_printf +#endif + +/** + **************************************************************************************** + * @addtogroup PHY + * @brief This driver is specific to the TRIDENT radio board based PHY. A very light + * control on MODEM, AGC, RF (through RC) and TRIDENT board components is grouped into + * specific block control functions in this driver. Its content remains transparent to SW + * in order for other drivers to be usable with the same SW. The PHY driver represents the + * link between SW and PHY. + * + * !!! Trident related settings use A,B, C radio paths. + * !!! MDM and RC related settings use paths 0,1,2 + * One register will have the mapping between the two. + * + * The MAXIM2829 Radio(s) are controlled through the Radio Controller. + * @{ + **************************************************************************************** + */ + +/* + * INCLUDE FILES + **************************************************************************************** + */ +//for __INLINE +#include "compiler.h" + +#include "mac.h" + +/* + * DEFINES + **************************************************************************************** + */ +// Limit as defined per radio specifications +#define PHY_TRIDENT_MAX_PWR_24G 25 // dBm +#define PHY_TRIDENT_MIN_PWR_24G -6 // dBm + +#define PHY_TRIDENT_MAX_PWR_5G 22 // dBm +#define PHY_TRIDENT_MIN_PWR_5G -9 // dBm + +#define PHY_TRIDENT_PA_GAIN_24G 29 // dBm +#define PHY_TRIDENT_PA_GAIN_5G 26 // dBm + +#define PHY_TRIDENT_TX_GAIN_MIN -35 // dBm + +// To prevent distortion Limit pwr to 10 dBm +#define PHY_TRIDENT_LIMIT_PWR 10 // dBm + +///MAXIM radio SPI prescaler +#define RF_SPI_PRESCALER 2//for until debug over + +///Bit offset for generic enables for Radio path A +#define RF_PATH_A 0 +///Bit offset for generic enables for Radio path B +#define RF_PATH_B 1 +///Bit offset for generic enables for Radio path C +#define RF_PATH_C 2 + +///Bit offset for generic enables for MDM+RC path 0 +#define RC_PATH_0 0 +///Bit offset for generic enables for MDM+RC path 1 +#define RC_PATH_1 1 +///Bit offset for generic enables for MDM+RC path 2 +#define RC_PATH_2 2 + +//Upper nibble of PHY_CFG parameter of phy_init +#define MDM_TYPE_1x1 0x00 +#define MDM_TYPE_1x2 0x10 +#define MDM_TYPE_1x3 0x20 +#define MDM_TYPE_2x3 0x30 +#define MDM_TYPE_3x3 0x40 +//Lower nibble of PHY_CFG parameter of phy_init +#define MDM2RF_ABC 0x00 +#define MDM2RF_BCA 0x01 +#define MDM2RF_CAB 0x02 +#define MDM2RF_ACB 0x03 +#define MDM2RF_BAC 0x04 +#define MDM2RF_CBA 0x05 + +/* + * CHANNEL SYNTHESIZER SETTINGS FOR RF REGISTERS + **************************************************************************************** + */ +/// PHY driver context. +struct phy_env_tag +{ + ///Exact mapping of (MDM+RC) to Radio paths + uint8_t phy2rf; + ///Rf selection: b0=A, b1=B, b2=C + uint8_t rf_path_sel; + ///MDM+RC Path selection: b0=0, b1=1, b2=2 + uint8_t rc_path_sel; + ///MIMO enable + uint8_t mimo_en; + ///Number of Rx Paths (for modem setting) + uint8_t nb_rx_paths; + ///Current selected band + uint8_t band; + //20/40/80/160/80+80 channel type + uint8_t chnl_type; + ///Currently configured 20MHz primary frequency (in MHz) + uint16_t chnl_prim20_freq; + ///Currently configured nMHz contiguous channel (of primary 80 if 80+80) + uint16_t chnl_center1_freq; + ///Currently configured secondary 80MHz channel if 80+80, unused otherwise + uint16_t chnl_center2_freq; +}; + +/// Global PHY driver environment. +extern struct phy_env_tag phy_env[]; + +/* + * FUNCTION DECLARATIONS + **************************************************************************************** + */ +void phy_rc_rf_reg_write(uint8_t addr, uint16_t value); + +/* + * MAXIM 2829 REGISTER ACCESS + **************************************************************************************** + */ +#define RF_DONT_CARE 0 +#define RF_DEFAULT0 0 +#define RF_DEFAULT1 1 +#define RF_FIXED0 0 +#define RF_FIXED1 1 +#define RF_VCO_SPI_BANDSW_DIS 0 +#define RF_VCO_BANDSW_DIS 0 +#define RF_VCO_BANDSW_EN 1 +#define RF_5G_LOW 0 +#define RF_5G_HIGH 1 + +//parameters are in lowest to highest bit positions order +// STANDBY------------------------------------------------------------------------------- +#define RF_STANDBY_ADDR 0x02 +#define RF_STANDBY_RST 0x1007 +#define RF_STANDBY_FIXED 0x1007 + +__INLINE void rf_standby_set(uint8_t pa_bias, uint8_t v_ref, uint8_t mimo_sel) +{ + phy_rc_rf_reg_write(RF_STANDBY_ADDR, + RF_STANDBY_FIXED | (pa_bias << 10) | (v_ref << 11) | (mimo_sel << 13)); +} + +// INTEGER DIVIDER RATIO------------------------------------------------------------------ +//no fields to define - values in table contain mandatory 0 set fields +#define RF_INTDIV_ADDR 0x03 +#define RF_INTDIV_RST 0x30A2 + +__INLINE void rf_intdiv_set(uint16_t value) +{ + phy_rc_rf_reg_write(RF_INTDIV_ADDR, value); +} + +// FRACTIONAL DIVIDER RATIO--------------------------------------------------------------- +//no fields to define - LSBs of value in RF are intdiv register MSBs ! +#define RF_FRACDIV_ADDR 0x04 +#define RF_FRACDIV_RST 0x1DDD + +__INLINE void rf_fracdiv_set(uint16_t value) +{ + phy_rc_rf_reg_write(RF_FRACDIV_ADDR, value); +} + +// BAND SELECT---------------------------------------------------------------------------- +//register used only in 2.4GHz band and never enable band switching, in 5GHz RC_SHADOW programs it +#define RF_BANDSEL_ADDR 0x05 +#define RF_BANDSEL_RST 0x1824 +#define RF_BANDSEL_FIXED 0x1800 + +__INLINE void rf_bandsel_set(uint8_t band, uint8_t ref_div, uint8_t mimo) +{ + phy_rc_rf_reg_write(RF_BANDSEL_ADDR, + RF_BANDSEL_FIXED | (band) | (ref_div << 1) | (RF_DEFAULT1 << 5) | + (RF_DONT_CARE << 6) | (RF_VCO_BANDSW_DIS << 7) | (RF_VCO_SPI_BANDSW_DIS << 8) | + (RF_DONT_CARE << 9) | (mimo << 13)); +} + +// CALIBRATION--------------------------------------------------------------------------- +#define RF_CALIB_ADDR 0x06 +#define RF_CALIB_RST 0x1C00 +#define RF_CALIB_FIXED 0x0400 + +__INLINE void rf_calib_set(uint8_t rxcal_en, uint8_t txcal_en, uint8_t txcal_cntl) +{ + phy_rc_rf_reg_write(RF_CALIB_ADDR, + RF_CALIB_FIXED | (rxcal_en) | (txcal_en << 1) | (txcal_cntl << 11)); +} + +// LOW PASS FILTER------------------------------------------------------------------------ +#define RF_LPF_ADDR 0x07 +#define RF_LPF_RST 0x002A +#define RF_LPF_FIXED 0x0000 + +__INLINE void rf_lpf_set(uint8_t rx_cf_fine, uint8_t rx_cf_crs, uint8_t tx_cf_crs, uint8_t rssi_hbw_en) +{ + phy_rc_rf_reg_write(RF_LPF_ADDR, + RF_LPF_FIXED | (rx_cf_fine) | (rx_cf_crs << 3) | + (tx_cf_crs << 5) | (rssi_hbw_en << 11)); +} + +// RX CONTROL/RSSI------------------------------------------------------------------------ +#define RF_RXRSSI_ADDR 0x08 +#define RF_RXRSSIF_RST 0x0025 +#define RF_RXRSSIF_FIXED 0x0021 + +__INLINE void rf_rxrssi_set(uint8_t rx_cf, uint8_t temp_out_en, uint8_t rssi_mode, uint8_t rssi_range, uint8_t rx_vga_gain_prog_en) +{ + phy_rc_rf_reg_write(RF_RXRSSI_ADDR, + RF_RXRSSIF_FIXED | (rx_cf << 2) | (temp_out_en << 8) | + (rssi_mode << 10) | (rssi_range << 11) | (rx_vga_gain_prog_en << 12)); +} + +// TXLINEARITY/BB GAIN-------------------------------------------------------------------- +#define RF_TXLIN_ADDR 0x09 +#define RF_TXLIN_RST 0x0200 +#define RF_TXLIN_FIXED 0x0000 + +__INLINE void rf_txlin_set(uint8_t bb_gain, uint8_t upconv_lin, uint8_t vga_lin, uint8_t pa_lin, uint8_t tx_vga_gain_prog_en) +{ + phy_rc_rf_reg_write(RF_TXLIN_ADDR, + RF_TXLIN_FIXED | (bb_gain) | (upconv_lin << 2) | + (vga_lin << 6) | (pa_lin << 8) | (tx_vga_gain_prog_en << 10)); +} + +// PA BIAS DAC---------------------------------------------------------------------------- +#define RF_PABIAS_ADDR 0x0A +#define RF_PABIAS_RST 0x03C0 +#define RF_PABIAS_FIXED 0x0000 + +__INLINE void rf_pabias_set(uint8_t dac_o_cur, uint8_t dac_on_del) +{ + phy_rc_rf_reg_write(RF_PABIAS_ADDR, RF_PABIAS_FIXED | (dac_o_cur) | (dac_on_del << 6)); +} + +// RX GAIN-------------------------------------------------------------------------------- +#define RF_RXGAIN_ADDR 0x0B +#define RF_RXGAIN_RST 0x007F +#define RF_RXGAIN_FIXED 0x0000 +//todo check if two params or just one +__INLINE void rf_rxgain_set(uint8_t value) +{ + phy_rc_rf_reg_write(RF_RXGAIN_ADDR, RF_RXGAIN_FIXED | value); +} + +// TX VGA GAIN---------------------------------------------------------------------------- +#define RF_TXGAIN_ADDR 0x0C +#define RF_TXGAIN_RST 0x0000 +#define RF_TXGAIN_FIXED 0x0000 + +__INLINE void rf_txgain_set(uint8_t value) +{ + phy_rc_rf_reg_write(RF_TXGAIN_ADDR, RF_TXGAIN_FIXED | value); +} + + +/** + **************************************************************************************** + * @brief Simple check for set bits in a value + * @param[in] value A one byte value in which a certain bit will be checked for its state. + * @param[in] bit_pos Index of the bit to check, possible values from 0 to 7 + * @return True is the bit at the indicated position is set, False otherwise. + **************************************************************************************** + */ +__INLINE bool phy_is_bit_set(uint8_t value, uint8_t bit_pos) +{ + if ((value & (1 << bit_pos)) == (1 << bit_pos)) + return true; + return false; +} + +/** + **************************************************************************************** + * @brief Extraction of rf_sel and MIMO information out of MODEM type and MDM2RF path map + * @param[in] cfg Combined info with MDM2RF path mapping in lower nibble and Modem nxm type + * in upper nibble. + **************************************************************************************** + */ +__INLINE void phy_get_config(uint8_t cfg) +{ + uint8_t mdm_type = cfg & 0xF0; + + switch(mdm_type) + { + case MDM_TYPE_1x1: + { + phy_env->mimo_en = 0; + phy_env->nb_rx_paths = 1; + phy_env->rc_path_sel = (1 << RC_PATH_0); + } + break; + case MDM_TYPE_1x2: + { + phy_env->mimo_en = 1; + phy_env->nb_rx_paths = 2; + phy_env->rc_path_sel = (1 << RC_PATH_0) | (1 << RC_PATH_1); + } + break; + default: + { + phy_env->mimo_en = 1; + phy_env->nb_rx_paths = 3; + phy_env->rc_path_sel = (1 << RC_PATH_0) | (1 << RC_PATH_1) | (1 << RC_PATH_2); + } + break; + } + + switch(cfg & 0x0F) + { + //PHY 0,1,2 to RF A, B, C + case MDM2RF_ABC: + //get how many channels will be used rx+tx + // 1x1 - A alone + if (mdm_type == MDM_TYPE_1x1) + { + phy_env->rf_path_sel = (1 << RF_PATH_A); + } + // 1x2 - A&B + else if (mdm_type == MDM_TYPE_1x2) + { + phy_env->rf_path_sel = (1 << RF_PATH_A) | (1 << RF_PATH_B); + } + // 1x3, 2x3, 3x3 - all 3... + else + { + phy_env->rf_path_sel = (1 << RF_PATH_A) | (1 << RF_PATH_B) | (1 << RF_PATH_C); + } + break; + + //PHY 0,1,2 to RF B, C, A + case MDM2RF_BCA: + //get how many channels will be used rx+tx + // 1x1 - B alone + if (mdm_type == MDM_TYPE_1x1) + { + phy_env->rf_path_sel = (1 << RF_PATH_B); + } + // 1x2 - B&C + else if (mdm_type == MDM_TYPE_1x2) + { + phy_env->rf_path_sel = (1 << RF_PATH_B) | (1 << RF_PATH_C); + } + // 1x3, 2x3, 3x3 - all 3... + else + { + phy_env->rf_path_sel = (1 << RF_PATH_A) | (1 << RF_PATH_B) | (1 << RF_PATH_C); + } + break; + + //PHY 0,1,2 to RF C, A, B + case MDM2RF_CAB: + //get how many channels will be used rx+tx + // 1x1 - C alone + if (mdm_type == MDM_TYPE_1x1) + { + phy_env->rf_path_sel = (1 << RF_PATH_C); + } + // 1x2 - C&A + else if (mdm_type == MDM_TYPE_1x2) + { + phy_env->rf_path_sel = (1 << RF_PATH_C) | (1 << RF_PATH_A); + } + // 1x3, 2x3, 3x3 - all 3... + else + { + phy_env->rf_path_sel = (1 << RF_PATH_A) | (1 << RF_PATH_B) | (1 << RF_PATH_C); + } + break; + + //PHY 0,1,2 to RF A, C, B + case MDM2RF_ACB: + //get how many channels will be used rx+tx + // 1x1 - A alone + if (mdm_type == MDM_TYPE_1x1) + { + phy_env->rf_path_sel = (1 << RF_PATH_A); + } + // 1x2 - A&C + else if (mdm_type == MDM_TYPE_1x2) + { + phy_env->rf_path_sel = (1 << RF_PATH_A) | (1 << RF_PATH_C); + } + // 1x3, 2x3, 3x3 - all 3... + else + { + phy_env->rf_path_sel = (1 << RF_PATH_A) | (1 << RF_PATH_B) | (1 << RF_PATH_C); + } + break; + + //PHY 0,1,2 to RF B, A, C + case MDM2RF_BAC: + //get how many channels will be used rx+tx + // 1x1 - B alone + if (mdm_type == MDM_TYPE_1x1) + { + phy_env->rf_path_sel = (1 << RF_PATH_B); + } + // 1x2 - B&A + else if (mdm_type == MDM_TYPE_1x2) + { + phy_env->rf_path_sel = (1 << RF_PATH_B) | (1 << RF_PATH_A); + } + // 1x3, 2x3, 3x3 - all 3... + else + { + phy_env->rf_path_sel = (1 << RF_PATH_A) | (1 << RF_PATH_B) | (1 << RF_PATH_C); + } + break; + + //PHY 0,1,2 to RF C, B, A + case MDM2RF_CBA: + //get how many channels will be used rx+tx + // 1x1 - C alone + if (mdm_type == MDM_TYPE_1x1) + { + phy_env->rf_path_sel = (1 << RF_PATH_B); + } + // 1x2 - C&B + else if (mdm_type == MDM_TYPE_1x2) + { + phy_env->rf_path_sel = (1 << RF_PATH_C) | (1 << RF_PATH_B); + } + // 1x3, 2x3, 3x3 - all 3... + else + { + phy_env->rf_path_sel = (1 << RF_PATH_A) | (1 << RF_PATH_B) | (1 << RF_PATH_C); + } + break; + default: + break; + } +} + +extern void phy_init_after_wakeup(void); +extern void phy_disable_lsig_intr(void); +extern void phy_enable_lsig_intr(void); +extern void phy_wakeup_rf_reinit(void); +extern void phy_wakeup_wifi_reinit(void); +extern void phy_open_cca(void); +extern void phy_close_cca(void); +extern void phy_show_cca(void); + +/// @} +#endif /* PHY_TRIDENT_H_ */ + + diff --git a/beken_os/beken378/driver/pwm/bk_timer.c b/beken_os/beken378/driver/pwm/bk_timer.c new file mode 100755 index 0000000..f8108dd --- /dev/null +++ b/beken_os/beken378/driver/pwm/bk_timer.c @@ -0,0 +1,328 @@ +#include "include.h" +#include "arm_arch.h" +#include "bk_timer_pub.h" +#include "bk_timer.h" +#include "drv_model_pub.h" +#include "intc_pub.h" +#include "icu_pub.h" +#include "uart_pub.h" + +#if (CFG_SOC_NAME != SOC_BK7231) +static SDD_OPERATIONS bk_timer_op = +{ + bk_timer_ctrl +}; + +void (*p_TIMER_Int_Handler[TIMER_CHANNEL_NO])(UINT8) = {NULL,}; + +static UINT32 bk_timer_cal_endvalue(UINT32 ucChannel, UINT32 time_ms, UINT32 div) +{ + UINT64 value; + + if(div == 0) + div = 1; + + if(ucChannel < 3) + { + /*26m clock*/ + value = time_ms * 26000 / div; + } + else + { + /*32k clock*/ + value = time_ms * 32 / div; + } + + if(value > 0xffffffff) + value = 0xffffffff; + + return (UINT32)value; +} + +static UINT32 bk_timer_cal_endvalue_us(UINT32 ucChannel, UINT32 time_us, UINT32 div) +{ + UINT64 value; + + if(div == 0) + div = 1; + + /*26m clock*/ + value = time_us * 26 / div; + + if(value > 0xffffffff) + value = 0xffffffff; + + return (UINT32)value; +} + +static UINT32 init_timer_param(timer_param_t *timer_param) +{ + UINT32 value; + UINT32 ucChannel = timer_param->channel; + + if (timer_param == NULL) + { + return BK_TIMER_FAILURE; + } + + if (timer_param->channel > 5) + { + return BK_TIMER_FAILURE; + } + + + p_TIMER_Int_Handler[ucChannel] = timer_param->t_Int_Handler; + + if (ucChannel < 3) + { + value = (PWD_TIMER_26M_CLK_BIT); + sddev_control(ICU_DEV_NAME, CMD_CLK_PWR_UP, (void *)&value); + + value = bk_timer_cal_endvalue(ucChannel, timer_param->period, timer_param->div); + REG_WRITE(REG_TIMERCTLA_PERIOD_ADDR(ucChannel), value); + + value = REG_READ(TIMER0_2_CTL); + value &= ~(TIMERCTLA_CLKDIV_MASK << TIMERCTLA_CLKDIV_POSI); + value |= ((timer_param->div - 1) << TIMERCTLA_CLKDIV_POSI); + value |= (1 << ucChannel ); + REG_WRITE(TIMER0_2_CTL, value); + } + else + { + value = (PWD_TIMER_32K_CLK_BIT); + sddev_control(ICU_DEV_NAME, CMD_CLK_PWR_UP, (void *)&value); + + value = bk_timer_cal_endvalue(ucChannel, timer_param->period, timer_param->div); + REG_WRITE(REG_TIMERCTLB_PERIOD_ADDR(ucChannel), value); + + value = REG_READ(TIMER3_5_CTL); + value &= ~(TIMERCTLB_CLKDIV_MASK << TIMERCTLB_CLKDIV_POSI); + value |= ((timer_param->div - 1) << TIMERCTLB_CLKDIV_POSI); + value |= (1 << (ucChannel - 3)); + REG_WRITE(TIMER3_5_CTL, value); + } + + intc_enable(IRQ_TIMER); + + return BK_TIMER_SUCCESS; +} + +static UINT32 init_timer_param_us(timer_param_t *timer_param) +{ + UINT32 value; + UINT32 ucChannel = timer_param->channel; + + if (timer_param == NULL) + { + return BK_TIMER_FAILURE; + } + + if (timer_param->channel > 2) + { + return BK_TIMER_FAILURE; + } + + + p_TIMER_Int_Handler[ucChannel] = timer_param->t_Int_Handler; + + value = (PWD_TIMER_26M_CLK_BIT); + sddev_control(ICU_DEV_NAME, CMD_CLK_PWR_UP, (void *)&value); + + value = bk_timer_cal_endvalue_us(ucChannel, timer_param->period, timer_param->div); + REG_WRITE(REG_TIMERCTLA_PERIOD_ADDR(ucChannel), value); + + value = REG_READ(TIMER0_2_CTL); + value &= ~(TIMERCTLA_CLKDIV_MASK << TIMERCTLA_CLKDIV_POSI); + value |= ((timer_param->div - 1) << TIMERCTLA_CLKDIV_POSI); + value |= (1 << ucChannel ); + REG_WRITE(TIMER0_2_CTL, value); + + intc_enable(IRQ_TIMER); + + return BK_TIMER_SUCCESS; +} + +UINT32 bk_timer_ctrl(UINT32 cmd, void *param) +{ + int i_time_out; + UINT32 ret = BK_TIMER_SUCCESS; + UINT32 ucChannel; + UINT32 value; + timer_param_t *p_param; + + switch(cmd) + { + case CMD_TIMER_UNIT_ENABLE: + ucChannel = (*(UINT32 *)param); + if(ucChannel > 5) + { + ret = BK_TIMER_FAILURE; + break; + } + + if(ucChannel < 3) + { + value = REG_READ(TIMER0_2_CTL); + value |= (1 << ucChannel ); + value &= ~(0x7 << TIMERCTLB_INT_POSI); + value |= (0x1 << (TIMERCTLB_INT_POSI + ucChannel)); + REG_WRITE(TIMER0_2_CTL, value); + } + else + { + value = REG_READ(TIMER3_5_CTL); + value |= (1 << (ucChannel - 3)); + value &= ~(0x7 << TIMERCTLB_INT_POSI); + value |= (0x1 << (TIMERCTLB_INT_POSI + (ucChannel - 3))); + REG_WRITE(TIMER3_5_CTL, value); + } + break; + + case CMD_TIMER_UNIT_DISABLE: + ucChannel = (*(UINT32 *)param); + if(ucChannel > 5) + { + ret = BK_TIMER_FAILURE; + break; + } + + if(ucChannel < 3) + { + value = REG_READ(TIMER0_2_CTL); + value &= ~(0x7 << TIMERCTLB_INT_POSI); + value &= ~(1 << ucChannel ); + value |= (0x1 << (TIMERCTLB_INT_POSI + ucChannel)); + REG_WRITE(TIMER0_2_CTL, value); + } + else + { + value = REG_READ(TIMER3_5_CTL); + value &= ~(0x7 << TIMERCTLB_INT_POSI); + //os_printf("-%08x\r\n", value); + value &= ~(1 << (ucChannel - 3)); + value |= (0x1 << (TIMERCTLB_INT_POSI + (ucChannel - 3))); + //os_printf("%08x\r\n", value); + REG_WRITE(TIMER3_5_CTL, value); + } + break; + + case CMD_TIMER_INIT_PARAM: + p_param = (timer_param_t *)param; + ret = init_timer_param(p_param); + break; + + case CMD_TIMER_INIT_PARAM_US: + p_param = (timer_param_t *)param; + ret = init_timer_param_us(p_param); + break; + + case CMD_TIMER_READ_CNT: + p_param = (timer_param_t *)param; + i_time_out = 0; + if (p_param->channel < 3) + { + REG_WRITE(TIMER0_2_READ_CTL, ((p_param->channel) << 2) | 1); + while (REG_READ(TIMER0_2_READ_CTL) & 1) + { + i_time_out ++; + if (i_time_out > (120 * 1000)) + { + ret = BK_TIMER_FAILURE; + break; + } + } + if (i_time_out <= (120 * 1000)) + { + p_param->period = REG_READ(TIMER0_2_READ_VALUE); + } + } + else if (p_param->channel < 6) + { + REG_WRITE(TIMER3_5_READ_CTL, ((p_param->channel) << 2) | 1); + while (REG_READ(TIMER3_5_READ_CTL) & 1) + { + i_time_out ++; + if (i_time_out > (120 * 1000)) + { + ret = BK_TIMER_FAILURE; + break; + } + } + if (i_time_out <= (120 * 1000)) + { + p_param->period = REG_READ(TIMER3_5_READ_VALUE); + } + } + break; + + default: + ret = BK_TIMER_FAILURE; + break; + } + + return ret; +} + +void bk_timer_init(void) +{ + REG_WRITE(TIMER0_2_CTL, (7 << TIMERCTLA_CLKDIV_MASK)); + REG_WRITE(TIMER0_CNT, 0); + REG_WRITE(TIMER1_CNT, 0); + REG_WRITE(TIMER2_CNT, 0); + + REG_WRITE(TIMER3_5_CTL, (7 << TIMERCTLB_CLKDIV_MASK)); + REG_WRITE(TIMER3_CNT, 0); + REG_WRITE(TIMER4_CNT, 0); + REG_WRITE(TIMER5_CNT, 0); + + intc_service_register(IRQ_TIMER, PRI_IRQ_TIMER, bk_timer_isr); + sddev_register_dev(TIMER_DEV_NAME, &bk_timer_op); +} + +void bk_timer_exit(void) +{ + sddev_unregister_dev(TIMER_DEV_NAME); +} + +void bk_timer_isr(void) +{ + int i; + UINT32 status0; + UINT32 status1; + + status0 = REG_READ(TIMER0_2_CTL) & (0x7U << TIMERCTLA_INT_POSI); + for(i = 0; i < 3; i++) + { + if(status0 & (1 << (i + TIMERCTLA_INT_POSI))) + { + if(p_TIMER_Int_Handler[i]) + { + p_TIMER_Int_Handler[i]((UINT8)i); + } + } + } + + do + { + REG_WRITE(TIMER0_2_CTL, (REG_READ(TIMER0_2_CTL) & (~(0x7U << TIMERCTLA_INT_POSI))) | status0); + } while(REG_READ(TIMER0_2_CTL) & status0 & (0x7 << TIMERCTLA_INT_POSI)); + + status1 = REG_READ(TIMER3_5_CTL) & (0x7U << TIMERCTLB_INT_POSI); + for(i = 0; i < 3; i++) + { + if(status1 & (1 << (i + TIMERCTLB_INT_POSI))) + { + if(p_TIMER_Int_Handler[i + 3]) + { + p_TIMER_Int_Handler[i + 3]((UINT8)(i + 3)); + } + } + } + + do + { + REG_WRITE(TIMER3_5_CTL, (REG_READ(TIMER3_5_CTL) & (~(0x7U << TIMERCTLB_INT_POSI))) | status1); + } while(REG_READ(TIMER3_5_CTL) & status1 & (0x7U << TIMERCTLB_INT_POSI)); +} +#endif + diff --git a/beken_os/beken378/driver/pwm/bk_timer.h b/beken_os/beken378/driver/pwm/bk_timer.h new file mode 100755 index 0000000..8be490c --- /dev/null +++ b/beken_os/beken378/driver/pwm/bk_timer.h @@ -0,0 +1,74 @@ +#ifndef _BK_TIMER_H_ +#define _BK_TIMER_H_ + + +#include "pwm.h" + +#if (CFG_SOC_NAME != SOC_BK7231) +#define TIMER0_CNT (PWM_NEW_BASE + 0 * 4) + +#define TIMER1_CNT (PWM_NEW_BASE + 1 * 4) + +#define TIMER2_CNT (PWM_NEW_BASE + 2 * 4) + +#define TIMER0_2_CTL (PWM_NEW_BASE + 3 * 4) +#define TIMERCTL0_EN_BIT (0x01UL << 0) +#define TIMERCTL1_EN_BIT (0x01UL << 1) +#define TIMERCTL2_EN_BIT (0x01UL << 2) +#define TIMERCTLA_CLKDIV_POSI (3) +#define TIMERCTLA_CLKDIV_MASK (0x07) +#define TIMERCTL0_INT_BIT (0x01UL << 7) +#define TIMERCTL1_INT_BIT (0x01UL << 8) +#define TIMERCTL2_INT_BIT (0x01UL << 9) +#define TIMERCTLA_INT_POSI (7) +#define REG_TIMERCTLA_PERIOD_ADDR(n) (PWM_NEW_BASE + 0x04 * (n)) + +#if (CFG_SOC_NAME == SOC_BK7231U) || (SOC_BK7231N == CFG_SOC_NAME) +#define TIMER0_2_READ_CTL (PWM_NEW_BASE + 4 * 4) +#define TIMER0_2_READ_OP_BIT (1<<0) +#define TIMER0_2_READ_INDEX_POSI (2) +#define TIMER0_2_READ_INDEX_MASK (0x3) +#define TIMER0_2_READ_INDEX_0 (0) +#define TIMER0_2_READ_INDEX_1 (1) +#define TIMER0_2_READ_INDEX_2 (2) + +#define TIMER0_2_READ_VALUE (PWM_NEW_BASE + 5 * 4) +#endif + +#define TIMER3_CNT (PWM_NEW_BASE + 0x10 * 4) + +#define TIMER4_CNT (PWM_NEW_BASE + 0x11 * 4) + +#define TIMER5_CNT (PWM_NEW_BASE + 0x12 * 4) + +#define TIMER3_5_CTL (PWM_NEW_BASE + 0x13 * 4) +#define TIMERCTL3_EN_BIT (0x01UL << 0) +#define TIMERCTL4_EN_BIT (0x01UL << 1) +#define TIMERCTL5_EN_BIT (0x01UL << 2) +#define TIMERCTLB_CLKDIV_POSI (3) +#define TIMERCTLB_CLKDIV_MASK (0x07) +#define TIMERCTL3_INT_BIT (0x01UL << 7) +#define TIMERCTL4_INT_BIT (0x01UL << 8) +#define TIMERCTL5_INT_BIT (0x01UL << 9) +#define TIMERCTLB_INT_POSI (7) +#define REG_TIMERCTLB_PERIOD_ADDR(n) (PWM_NEW_BASE + 0x10 * 4 + 0x04 * (n - 3)) + +#if (CFG_SOC_NAME == SOC_BK7231U) || (SOC_BK7231N == CFG_SOC_NAME) +#define TIMER3_5_READ_CTL (PWM_NEW_BASE + 0x14 * 4) +#define TIMER3_5_READ_OP_BIT (1<<0) +#define TIMER3_5_READ_INDEX_POSI (2) +#define TIMER3_5_READ_INDEX_MASK (0x3) +#define TIMER3_5_READ_INDEX_3 (0) +#define TIMER3_5_READ_INDEX_4 (1) +#define TIMER3_5_READ_INDEX_5 (2) + +#define TIMER3_5_READ_VALUE (PWM_NEW_BASE + 0x15 * 4) +#endif + +#define TIMER_CHANNEL_NO 6 +#endif +UINT32 bk_timer_ctrl(UINT32 cmd, void *param); + +#endif //_TIMER_H_ + + diff --git a/beken_os/beken378/driver/pwm/mcu_ps_timer.c b/beken_os/beken378/driver/pwm/mcu_ps_timer.c new file mode 100755 index 0000000..ef7de40 --- /dev/null +++ b/beken_os/beken378/driver/pwm/mcu_ps_timer.c @@ -0,0 +1,171 @@ +#include "include.h" +#include "arm_arch.h" + +#include "pwm.h" +#include "pwm_pub.h" +#include "bk_timer_pub.h" +#include "bk_timer.h" +#include "icu_pub.h" +#include "fake_clock_pub.h" +#include "mcu_ps_pub.h" +#include "target_util_pub.h" +#include "wlan_ui_pub.h" +#include "intc_pub.h" + +#if (CFG_SOC_NAME == SOC_BK7231) +void ps_pwm_enable(void) +{ + UINT32 reg = 0; + reg = REG_READ(PWM_CTL); + reg &= (~(0xf<<(PS_PWM_ID*4))); + reg |= (0x7<<(PS_PWM_ID*4)); + REG_WRITE(PWM_CTL, reg); +} + +void ps_pwm_disable(void ) +{ + UINT32 reg; + reg = REG_READ(PWM_CTL); + REG_WRITE(PWM_CTL, reg & (~(0xf<<(PS_PWM_ID*4)))); +} + +void ps_pwm_set_period(UINT32 period, UINT8 clk_mux) +{ + UINT32 reg = 0,ch; + + ch = PS_PWM_ID; + if(PWM_MUX_LPO == clk_mux) + { + icu_ctrl(CMD_CONF_PWM_LPOCLK, (void *)&ch); + } + else + { + icu_ctrl(CMD_CONF_PWM_PCLK, (void *)&ch); + } + +#if (CFG_SOC_NAME == SOC_BK7231) + reg = 0; + reg |= period << PWM0_END_POSI | 0x0 << PWM0_DC_POSI; + REG_WRITE(MCU_PS_PWM_COUNTER , reg); +#else + reg = period; + REG_WRITE(MCU_PS_PWM_COUNTER , reg); + reg = 0; + REG_WRITE(MCU_PS_PWM_DUTY_CYCLE , reg); +#endif +} + + +void ps_pwm_reconfig(UINT32 period, UINT8 clk_mux) +{ + UINT32 param; + //disable +#if (CFG_SOC_NAME == SOC_BK7231) + ps_pwm_disable(); + delay(5); + //new + ps_pwm_set_period(period, clk_mux); + delay(1); + //reenable + ps_pwm_enable(); + + REG_WRITE(PWM_INTERRUPT_STATUS,0x1); +#else + ps_pwm_disable(); + //new + ps_pwm_set_period(period, clk_mux); + //reenable + ps_pwm_enable(); + delay(5); + + REG_WRITE(PWM_INTERRUPT_STATUS,0x3f); +#endif + +} + +void ps_pwm_suspend_tick(UINT32 period) +{ + ps_pwm_reconfig(period, PWM_MUX_LPO); +} + +void ps_pwm_resume_tick(void) +{ + ps_pwm_reconfig(fclk_cal_endvalue(PWM_CLK_26M), PWM_MUX_PCLK); +} + +UINT32 ps_pwm_int_status(void ) +{ + return ((REG_READ(ICU_INT_STATUS) & (CO_BIT(IRQ_PWM)))&& (REG_READ(PWM_INTERRUPT_STATUS) & 0x1)); +} +#endif + + +#if (CFG_SOC_NAME != SOC_BK7231) +void ps_timer3_enable(UINT32 period) +{ + UINT32 reg; + +#if (CFG_SOC_NAME == SOC_BK7231U) || (SOC_BK7231N == CFG_SOC_NAME) + reg = REG_READ(TIMER3_5_READ_CTL); + reg &= ~(TIMER3_5_READ_INDEX_MASK << TIMER3_5_READ_INDEX_POSI); + reg |= (TIMER3_5_READ_INDEX_3 << TIMER3_5_READ_INDEX_POSI); + REG_WRITE(TIMER3_5_READ_CTL,reg); +#endif + + reg = REG_READ(TIMER3_5_CTL); + reg &= (~TIMERCTL3_EN_BIT); + REG_WRITE(TIMER3_5_CTL,reg); + delay(2); + REG_WRITE(TIMER3_CNT,period); + delay(2); + reg = REG_READ(TIMER3_5_CTL); + reg |= (TIMERCTL3_EN_BIT); + reg &= ~(0x7 << TIMERCTLB_INT_POSI); + REG_WRITE(TIMER3_5_CTL,reg); +} + +void ps_timer3_measure_prepare(void) +{ +#if (CFG_SOC_NAME == SOC_BK7231U) || (SOC_BK7231N == CFG_SOC_NAME) + UINT32 reg; + if(! (REG_READ(TIMER3_5_CTL)&(TIMERCTL3_INT_BIT))) + { + reg = REG_READ(TIMER3_5_READ_CTL); + reg |= TIMER3_5_READ_OP_BIT; + REG_WRITE(TIMER3_5_READ_CTL,reg); + } +#endif +} + +UINT32 ps_timer3_disable(void) +{ + UINT32 reg,less; + if(REG_READ(TIMER3_5_CTL)&(TIMERCTL3_INT_BIT)) + { + less = REG_READ(TIMER3_CNT); + } + else + { +#if (CFG_SOC_NAME == SOC_BK7231U) || (SOC_BK7231N == CFG_SOC_NAME) + while(REG_READ(TIMER3_5_READ_CTL) & TIMER3_5_READ_OP_BIT); + less = REG_READ(TIMER3_5_READ_VALUE); +#else + less = REG_READ(TIMER3_CNT); +#endif + } + + reg = REG_READ(TIMER3_5_CTL); + reg &= (~TIMERCTL3_EN_BIT); + reg &= ~(0x7 << TIMERCTLB_INT_POSI); + REG_WRITE(TIMER3_5_CTL,reg); + delay(2); + REG_WRITE(TIMER3_CNT,FCLK_DURATION_MS*32); + delay(2); + reg = REG_READ(TIMER3_5_CTL); + reg |= (TIMERCTL3_EN_BIT); + REG_WRITE(TIMER3_5_CTL,reg); + + return (less/32); +} +#endif + diff --git a/beken_os/beken378/driver/pwm/pwm.c b/beken_os/beken378/driver/pwm/pwm.c new file mode 100755 index 0000000..aecde64 --- /dev/null +++ b/beken_os/beken378/driver/pwm/pwm.c @@ -0,0 +1,350 @@ +#include "include.h" +#include "arm_arch.h" + +#if (CFG_SOC_NAME != SOC_BK7231N) +#include "pwm.h" +#include "pwm_pub.h" + +#include "drv_model_pub.h" +#include "intc_pub.h" +#include "icu_pub.h" +#include "gpio_pub.h" +#include "uart_pub.h" + +static SDD_OPERATIONS pwm_op = +{ + pwm_ctrl +}; + +void (*p_PWM_Int_Handler[CHANNEL_NO])(UINT8); + +static void pwm_gpio_configuration(UINT8 chan, UINT8 enable) +{ + UINT32 ret; + UINT32 param; + + switch(chan) + { + case PWM0: + param = GFUNC_MODE_PWM0; + break; + + case PWM1: + param = GFUNC_MODE_PWM1; + break; + + case PWM2: + param = GFUNC_MODE_PWM2; + break; + + case PWM3: + param = GFUNC_MODE_PWM3; + break; + + case PWM4: + param = GFUNC_MODE_PWM4; + break; + + case PWM5: + param = GFUNC_MODE_PWM5; + break; + + default: + break; + } + + if(enable) + { + ret = sddev_control(GPIO_DEV_NAME, CMD_GPIO_ENABLE_SECOND, ¶m); + } + else + { + param = GPIO_CFG_PARAM(param, GMODE_INPUT); + ret = sddev_control(GPIO_DEV_NAME, CMD_GPIO_CFG, ¶m); + } + ASSERT(GPIO_SUCCESS == ret); +} + +static void pwm_icu_configuration(pwm_param_t *pwm_param, UINT8 enable) +{ + UINT32 ret; + UINT32 prm; + + /* set clock power down of icu module*/ + switch(pwm_param->channel) + { + case PWM0: + prm = PWD_PWM0_CLK_BIT; + break; + + case PWM1: + prm = PWD_PWM1_CLK_BIT; + break; + + case PWM2: + prm = PWD_PWM2_CLK_BIT; + break; + + case PWM3: + prm = PWD_PWM3_CLK_BIT; + break; + + case PWM4: + prm = PWD_PWM4_CLK_BIT; + break; + + case PWM5: + prm = PWD_PWM5_CLK_BIT; + break; + + default: + PWM_WARN("pwm_iconfig_fail\r\n"); + goto exit_icu; + } + + if(enable) + { + ret = sddev_control(ICU_DEV_NAME, CMD_CLK_PWR_UP, (void *)&prm); + ASSERT(ICU_SUCCESS == ret); + + if(PWM_CLK_32K == pwm_param->cfg.bits.clk) + { + prm = pwm_param->channel; + ret = sddev_control(ICU_DEV_NAME, CMD_CONF_PWM_LPOCLK, (void *)&prm); + } + else + { + prm = pwm_param->channel; + ret = sddev_control(ICU_DEV_NAME, CMD_CONF_PWM_PCLK, (void *)&prm); + } + ASSERT(ICU_SUCCESS == ret); + } + else + { + ret = sddev_control(ICU_DEV_NAME, CMD_CLK_PWR_DOWN, (void *)&prm); + ASSERT(ICU_SUCCESS == ret); + } + + if(PWM_INT_EN == pwm_param->cfg.bits.int_en) + { + prm = IRQ_PWM_BIT; + ret = sddev_control(ICU_DEV_NAME, CMD_ICU_INT_ENABLE, (void *)&prm); + } + +exit_icu: + + return; +} + +static void init_pwm_param(pwm_param_t *pwm_param, UINT8 enable) +{ + UINT32 value; + + if((pwm_param == NULL) + || (pwm_param->channel >= PWM_COUNT) + || (pwm_param->duty_cycle > pwm_param->end_value)) + { + return; + } + + if(pwm_param->cfg.bits.mode != PWM_TIMER_MODE) + { +#if (CFG_SOC_NAME == SOC_BK7231) + pwm_gpio_configuration(pwm_param->channel, enable); +#else + pwm_gpio_configuration(pwm_param->channel, enable); +#endif + } + +#if (CFG_SOC_NAME == SOC_BK7231) + value = (((UINT32)pwm_param->duty_cycle & 0x0000FFFF) << 16) + + ((UINT32)pwm_param->end_value & 0x0000FFFF); + REG_WRITE(REG_APB_BK_PWMn_CNT_ADDR(pwm_param->channel), value); +#else + value = ((UINT32)pwm_param->end_value); + REG_WRITE(REG_APB_BK_PWMn_END_ADDR(pwm_param->channel), value); + + value = ((UINT32)pwm_param->duty_cycle); + REG_WRITE(REG_APB_BK_PWMn_DC_ADDR(pwm_param->channel), value); +#endif + + value = REG_READ(PWM_CTL); + value = (value & (~(0x0F << (0x04 * pwm_param->channel)))) + | ((pwm_param->cfg.val & 0x0F) << (0x04 * pwm_param->channel)); + REG_WRITE(PWM_CTL, value); + + p_PWM_Int_Handler[pwm_param->channel] = pwm_param->p_Int_Handler; + + pwm_icu_configuration(pwm_param, enable); +} + +static UINT16 pwm_capture_value_get(UINT8 ucChannel) +{ + return REG_READ(REG_APB_BK_PWMn_CAP_ADDR(ucChannel)); +} + +static void pwm_set_duty_cycle(UINT8 ucChannel, UINT32 u32DutyCycle) +{ + REG_WRITE(REG_APB_BK_PWMn_DC_ADDR(ucChannel), u32DutyCycle); +} + +static void pwm_set_end_value(UINT8 ucChannel, UINT32 u32EndValue) +{ + REG_WRITE(REG_APB_BK_PWMn_END_ADDR(ucChannel), u32EndValue); +} + +static void pwm_int_handler_clear(UINT8 ucChannel) +{ + p_PWM_Int_Handler[ucChannel] = NULL; +} + +void pwm_init(void) +{ + REG_WRITE(PWM_CTL, 0x0); + + intc_service_register(IRQ_PWM, PRI_IRQ_PWM, pwm_isr); + + sddev_register_dev(PWM_DEV_NAME, &pwm_op); +} + +void pwm_exit(void) +{ + sddev_unregister_dev(PWM_DEV_NAME); +} + +UINT32 pwm_ctrl(UINT32 cmd, void *param) +{ + UINT32 ret = PWM_SUCCESS; + UINT32 ucChannel; + UINT32 value; + pwm_param_t *p_param; + pwm_capture_t *p_capture; + + switch(cmd) + { + case CMD_PWM_UNIT_ENABLE: + ucChannel = (*(UINT32 *)param); + if(ucChannel > 5) + { + ret = PWM_FAILURE; + break; + } + value = REG_READ(PWM_CTL); + value |= (1 << (ucChannel * 4)); + REG_WRITE(PWM_CTL, value); + break; + case CMD_PWM_UNIT_DISABLE: + ucChannel = (*(UINT32 *)param); + if(ucChannel > 5) + { + ret = PWM_FAILURE; + break; + } + value = REG_READ(PWM_CTL); + value &= ~(3 << (ucChannel * 4)); + REG_WRITE(PWM_CTL, value); + break; + case CMD_PWM_IR_ENABLE: + ucChannel = (*(UINT32 *)param); + if(ucChannel > 5) + { + ret = PWM_FAILURE; + break; + } + value = REG_READ(PWM_CTL); + value |= (2 << (ucChannel * 4)); + REG_WRITE(PWM_CTL, value); + break; + case CMD_PWM_IR_DISABLE: + ucChannel = (*(UINT32 *)param); + if(ucChannel > 5) + { + ret = PWM_FAILURE; + break; + } + value = REG_READ(PWM_CTL); + value &= ~(2 << (ucChannel * 4)); + REG_WRITE(PWM_CTL, value); + break; + case CMD_PWM_IR_CLEAR: + ucChannel = (*(UINT32 *)param); + if(ucChannel > 5) + { + ret = PWM_FAILURE; + break; + } + pwm_int_handler_clear(ucChannel); + break; + case CMD_PWM_INIT_PARAM: + p_param = (pwm_param_t *)param; + init_pwm_param(p_param, 1); + break; + case CMD_PWM_SET_DUTY_CYCLE: + p_param = (pwm_param_t *)param; + if(p_param->channel >= PWM_COUNT) + { + ret = PWM_FAILURE; + break; + } + pwm_set_duty_cycle(p_param->channel, p_param->duty_cycle); + break; + case CMD_PWM_SET_END_VALUE: + p_param = (pwm_param_t *)param; + if(p_param->channel >= PWM_COUNT) + { + ret = PWM_FAILURE; + break; + } + pwm_set_end_value(p_param->channel, p_param->end_value); + break; + case CMD_PWM_CAP_GET: + p_capture = (pwm_capture_t *)param; + if(p_capture->ucChannel >= PWM_COUNT) + { + ret = PWM_FAILURE; + break; + } + p_capture->value = pwm_capture_value_get(p_capture->ucChannel); + break; + case CMD_PWM_DEINIT_PARAM: + p_param = (pwm_param_t *)param; + init_pwm_param(p_param, 0); + break; + default: + ret = PWM_FAILURE; + break; + } + + return ret; +} + +void pwm_isr(void) +{ + int i; + UINT32 status; + + status = REG_READ(PWM_INTERRUPT_STATUS); + + for(i = 0; i < CHANNEL_NO; i++) + { + if(status & (1 << i)) + { + if(p_PWM_Int_Handler[i]) + { + p_PWM_Int_Handler[i]((UINT8)i); + do + { + REG_WRITE(PWM_INTERRUPT_STATUS, (1 << i)); + } + while(REG_READ(PWM_INTERRUPT_STATUS) & (1 << i)); + } + } + } + + do + { + REG_WRITE(PWM_INTERRUPT_STATUS, status); + } + while(REG_READ(PWM_INTERRUPT_STATUS) & status & 0x3F); +} +#endif diff --git a/beken_os/beken378/driver/pwm/pwm.h b/beken_os/beken378/driver/pwm/pwm.h new file mode 100755 index 0000000..ff51da6 --- /dev/null +++ b/beken_os/beken378/driver/pwm/pwm.h @@ -0,0 +1,243 @@ +#ifndef _PWM_H_ +#define _PWM_H_ + +#define PWM_DEBUG + +#ifdef PWM_DEBUG +#define PWM_PRT os_printf +#define PWM_WARN warning_prf +#define PWM_FATAL fatal_prf +#else +#define PWM_PRT null_prf +#define PWM_WARN null_prf +#define PWM_FATAL null_prf +#endif + +#define PWM_NEW_BASE (0x00802A00) + +#if (CFG_SOC_NAME == SOC_BK7231) +#define PWM_BASE (PWM_NEW_BASE) +#else +#define PWM_BASE (PWM_NEW_BASE + 0x20 * 4 ) +#endif + +#define PWM_CTL (PWM_BASE + 0 * 4) + +#define PWM0_EN_BIT (0x01UL << 0) +#define PWM0_INT_EN_BIT (0x01UL << 1) +#define PWM0_MODE_POSI (2) +#define PWM0_MODE_MASK (0x03) + +#define PWM1_EN_BIT (0x01UL << 4) +#define PWM1_INT_EN_BIT (0x01UL << 5) +#define PWM1_MODE_POSI (6) +#define PWM1_MODE_MASK (0x03) + +#define PWM2_EN_BIT (0x01UL << 8) +#define PWM2_INT_EN_BIT (0x01UL << 9) +#define PWM2_MODE_POSI (10) +#define PWM2_MODE_MASK (0x03) + +#define PWM3_EN_BIT (0x01UL << 12) +#define PWM3_INT_EN_BIT (0x01UL << 13) +#define PWM3_MODE_POSI (14) +#define PWM3_MODE_MASK (0x03) + +#define PWM4_EN_BIT (0x01UL << 16) +#define PWM4_INT_EN_BIT (0x01UL << 17) +#define PWM4_MODE_POSI (18) +#define PWM4_MODE_MASK (0x03) + +#define PWM5_EN_BIT (0x01UL << 20) +#define PWM5_INT_EN_BIT (0x01UL << 21) +#define PWM5_MODE_POSI (22) +#define PWM5_MODE_MASK (0x03) + +#define PWM_INTERRUPT_STATUS (PWM_BASE + 1 * 4) + +#define PWM0_INIT_BIT (0x01UL << 0) +#define PWM1_INIT_BIT (0x01UL << 1) +#define PWM2_INIT_BIT (0x01UL << 2) +#define PWM3_INIT_BIT (0x01UL << 3) +#define PWM4_INIT_BIT (0x01UL << 4) +#define PWM5_INIT_BIT (0x01UL << 5) + +#define PWM0_COUNTER (PWM_BASE + 2 * 4) + +#if (CFG_SOC_NAME == SOC_BK7231) +#define PWM0_END_POSI (0) +#define PWM0_END_MASK (0xFFFF) +#define PWM0_DC_POSI (16) +#define PWM0_DC_MASK (0xFFFF) + +#define PWM0_CAPTURE (PWM_BASE + 3 * 4) + +#define PWM0_CAP_OUT_POSI (0) +#define PWM0_CAP_OUT_MASK (0xFFFF) + +#define PWM1_COUNTER (PWM_BASE + 4 * 4) + +#define PWM1_END_POSI (0) +#define PWM1_END_MASK (0xFFFF) +#define PWM1_DC_POSI (16) +#define PWM1_DC_MASK (0xFFFF) + +#define PWM1_CAPTURE (PWM_BASE + 5 * 4) + +#define PWM1_CAP_OUT_POSI (0) +#define PWM1_CAP_OUT_MASK (0xFFFF) + +#define PWM2_COUNTER (PWM_BASE + 6 * 4) + +#define PWM2_END_POSI (0) +#define PWM2_END_MASK (0xFFFF) +#define PWM2_DC_POSI (16) +#define PWM2_DC_MASK (0xFFFF) + +#define PWM2_CAPTURE (PWM_BASE + 7 * 4) + +#define PWM2_CAP_OUT_POSI (0) +#define PWM2_CAP_OUT_MASK (0xFFFF) + +#define PWM3_COUNTER (PWM_BASE + 8 * 4) + +#define PWM3_END_POSI (0) +#define PWM3_END_MASK (0xFFFF) +#define PWM3_DC_POSI (16) +#define PWM3_DC_MASK (0xFFFF) + +#define PWM3_CAPTURE (PWM_BASE + 9 * 4) + +#define PWM3_CAP_OUT_POSI (0) +#define PWM3_CAP_OUT_MASK (0xFFFF) + +#define PWM4_COUNTER (PWM_BASE + 10 * 4) + +#define PWM4_END_POSI (0) +#define PWM4_END_MASK (0xFFFF) +#define PWM4_DC_POSI (16) +#define PWM4_DC_MASK (0xFFFF) + +#define PWM4_CAPTURE (PWM_BASE + 11 * 4) + +#define PWM4_CAP_OUT_POSI (0) +#define PWM4_CAP_OUT_MASK (0xFFFF) + +#define PWM5_COUNTER (PWM_BASE + 12 * 4) + +#define PWM5_END_POSI (0) +#define PWM5_END_MASK (0xFFFF) +#define PWM5_DC_POSI (16) +#define PWM5_DC_MASK (0xFFFF) + +#define PWM5_CAPTURE (PWM_BASE + 13 * 4) + +#define PWM5_CAP_OUT_POSI (0) +#define PWM5_CAP_OUT_MASK (0xFFFF) + +#define REG_APB_BK_PWMn_CNT_ADDR(n) (PWM_BASE + 0x08 + 2 * 0x04 * (n)) +#define REG_APB_BK_PWMn_CAP_ADDR(n) (PWM_BASE + 0x0C + 2 * 0x04 * (n)) + +#else +#define PWM0_END_POSI (0) +#define PWM0_END_MASK (0xFFFFFFFF) + +#define PWM0_DUTY_CYCLE (PWM_BASE + 3 * 4) + +#define PWM0_DC_POSI (0) +#define PWM0_DC_MASK (0xFFFFFFFF) + +#define PWM0_CAPTURE (PWM_BASE + 4 * 4) + +#define PWM0_CAP_OUT_POSI (0) +#define PWM0_CAP_OUT_MASK (0xFFFFFFFF) + +#define PWM1_COUNTER (PWM_BASE + 5 * 4) + +#define PWM1_END_POSI (0) +#define PWM1_END_MASK (0xFFFFFFFF) + +#define PWM1_DUTY_CYCLE (PWM_BASE + 6 * 4) + +#define PWM1_DC_POSI (0) +#define PWM1_DC_MASK (0xFFFFFFFF) + +#define PWM1_CAPTURE (PWM_BASE + 7 * 4) + +#define PWM1_CAP_OUT_POSI (0) +#define PWM1_CAP_OUT_MASK (0xFFFFFFFF) + +#define PWM2_COUNTER (PWM_BASE + 8 * 4) + +#define PWM2_END_POSI (0) +#define PWM2_END_MASK (0xFFFFFFFF) + +#define PWM2_DUTY_CYCLE (PWM_BASE + 9 * 4) + +#define PWM2_DC_POSI (0) +#define PWM2_DC_MASK (0xFFFFFFFF) + +#define PWM2_CAPTURE (PWM_BASE + 10 * 4) + +#define PWM2_CAP_OUT_POSI (0) +#define PWM2_CAP_OUT_MASK (0xFFFFFFFF) + +#define PWM3_COUNTER (PWM_BASE + 11 * 4) + +#define PWM3_END_POSI (0) +#define PWM3_END_MASK (0xFFFFFFFF) + +#define PWM3_DUTY_CYCLE (PWM_BASE + 12 * 4) + +#define PWM3_DC_POSI (0) +#define PWM3_DC_MASK (0xFFFFFFFF) + +#define PWM3_CAPTURE (PWM_BASE + 13 * 4) + +#define PWM3_CAP_OUT_POSI (0) +#define PWM3_CAP_OUT_MASK (0xFFFFFFFF) + +#define PWM4_COUNTER (PWM_BASE + 14 * 4) + +#define PWM4_END_POSI (0) +#define PWM4_END_MASK (0xFFFFFFFF) + +#define PWM4_DUTY_CYCLE (PWM_BASE + 15 * 4) + +#define PWM4_DC_POSI (0) +#define PWM4_DC_MASK (0xFFFFFFFF) + +#define PWM4_CAPTURE (PWM_BASE + 16 * 4) + +#define PWM4_CAP_OUT_POSI (0) +#define PWM4_CAP_OUT_MASK (0xFFFFFFFF) + +#define PWM5_COUNTER (PWM_BASE + 17 * 4) + +#define PWM5_END_POSI (0) +#define PWM5_END_MASK (0xFFFFFFFF) + +#define PWM5_DUTY_CYCLE (PWM_BASE + 18 * 4) + +#define PWM5_DC_POSI (0) +#define PWM5_DC_MASK (0xFFFFFFFF) + +#define PWM5_CAPTURE (PWM_BASE + 19 * 4) + +#define PWM5_CAP_OUT_POSI (0) +#define PWM5_CAP_OUT_MASK (0xFFFFFFFF) + +#define REG_APB_BK_PWMn_END_ADDR(n) (PWM_BASE + 0x08 + 3 * 0x04 * (n)) +#define REG_APB_BK_PWMn_DC_ADDR(n) (PWM_BASE + 0x0C + 3 * 0x04 * (n)) +#define REG_APB_BK_PWMn_CAP_ADDR(n) (PWM_BASE + 0x10 + 3 * 0x04 * (n)) + +#endif + +#define CHANNEL_NO 6 + +/******************************************************************************* +* Function Declarations +*******************************************************************************/ +UINT32 pwm_ctrl(UINT32 cmd, void *param); + +#endif //_PWM_H_ diff --git a/beken_os/beken378/driver/pwm/pwm_new.c b/beken_os/beken378/driver/pwm/pwm_new.c new file mode 100755 index 0000000..b2e4026 --- /dev/null +++ b/beken_os/beken378/driver/pwm/pwm_new.c @@ -0,0 +1,1273 @@ +#if (CFG_SOC_NAME == SOC_BK7231N) +#include "include.h" +#include "arm_arch.h" +#include + +#include "pwm_pub.h" + +#include "drv_model_pub.h" +#include "intc_pub.h" +#include "icu_pub.h" +#include "gpio_pub.h" +#include "uart_pub.h" +#include "pwm_new.h" + +UINT8 current_channel; +UINT8 current_group; + +static SDD_OPERATIONS pwm_op = +{ + pwm_ctrl +}; + +void (*p_PWM_Int_Handler[CHANNEL_NO])(UINT8); + +UINT8 get_current_group(UINT8 channel) +{ + if(channel >= PWM_COUNT) + { + bk_printf("PWM:channel error\r\n"); + return -1; + } + + if (channel < 2) + { + current_group = 0; + current_channel = channel; + } + else if (channel < 4) + { + current_group = 1; + current_channel = channel-2; + } + else + { + current_group = 2; + current_channel = channel-4; + } + + return current_group; +} + +UINT8 get_set_group(UINT8 channel) +{ + UINT8 set_group = 0; + + if(channel >= PWM_COUNT) + { + bk_printf("PWM:channel error\r\n"); + return -1; + } + + if (channel < 2) + { + set_group = 0; + } + else if (channel < 4) + { + set_group = 1; + } + else + { + set_group = 2; + } + + return set_group; +} + +UINT8 get_set_channel(UINT8 channel) +{ + UINT8 set_channel = 0; + UINT8 group = get_set_group(channel); + + set_channel = channel - 2*group; + + return set_channel; +} + +UINT32 pwm_check_group(UINT8 channel1,UINT8 channel2) +{ + UINT32 group; + + if(abs(channel2-channel1) ==1) + { + if(channel1==0) + { + if(channel2 ==1) + { + group= 1; + } + else + { + group= 0; + } + } + else if(channel1==1) + { + if(channel2 ==0) + { + group= 1; + } + else + { + group= 0; + } + } + else if(channel1==2) + { + if(channel2 ==3) + { + group= 1; + } + else + { + group= 0; + } + } + else if(channel1==3) + { + if(channel2 ==2) + { + group= 1; + } + else + { + group= 0; + } + } + else if(channel1==4) + { + if(channel2 ==5) + { + group= 1; + } + else + { + group= 0; + } + } + else + { + if(channel2 ==4) + { + group= 1; + } + else + { + group= 0; + } + } + } + else + { + group= 0; + } + + return group; +} + + +static void pwm_gpio_configuration(UINT8 chan, UINT8 enable) +{ + UINT32 ret; + UINT32 param; + + switch(chan) + { + case PWM0: + param = GFUNC_MODE_PWM0; + break; + + case PWM1: + param = GFUNC_MODE_PWM1; + break; + + case PWM2: + param = GFUNC_MODE_PWM2; + break; + + case PWM3: + param = GFUNC_MODE_PWM3; + break; + + case PWM4: + param = GFUNC_MODE_PWM4; + break; + + case PWM5: + param = GFUNC_MODE_PWM5; + break; + + default: + break; + } + + if(enable) + { + ret = sddev_control(GPIO_DEV_NAME, CMD_GPIO_ENABLE_SECOND, ¶m); + } + else + { + param = GPIO_CFG_PARAM(param, GMODE_INPUT); + ret = sddev_control(GPIO_DEV_NAME, CMD_GPIO_CFG, ¶m); + } + ASSERT(GPIO_SUCCESS == ret); +} + +static void pwm_icu_configuration(pwm_param_t *pwm_param, UINT8 enable) +{ + UINT32 ret; + UINT32 prm; + + /* set clock power down of icu module*/ + switch(pwm_param->channel) + { + case PWM0: + prm = PWD_PWM0_CLK_BIT; + break; + + case PWM1: + prm = PWD_PWM0_CLK_BIT; + break; + + case PWM2: + prm = PWD_PWM2_CLK_BIT; + break; + + case PWM3: + prm = PWD_PWM2_CLK_BIT; + break; + + case PWM4: + prm = PWD_PWM4_CLK_BIT; + break; + + case PWM5: + prm = PWD_PWM4_CLK_BIT; + break; + + default: + PWM_WARN("pwm_iconfig_fail\r\n"); + goto exit_icu; + } + + if(enable) + { + ret = sddev_control(ICU_DEV_NAME, CMD_CLK_PWR_UP, (void *)&prm); + ASSERT(ICU_SUCCESS == ret); + + if(PWM_CLK_32K == pwm_param->cfg.bits.clk) + { + prm = pwm_param->channel; + ret = sddev_control(ICU_DEV_NAME, CMD_CONF_PWM_LPOCLK, (void *)&prm); + } + else if (PWM_CLK_26M == pwm_param->cfg.bits.clk) + { + prm = PCLK_POSI_PWMS; + ret = sddev_control(ICU_DEV_NAME, CMD_CONF_PCLK_26M, (void *)&prm); + + prm = pwm_param->channel; + ret = sddev_control(ICU_DEV_NAME, CMD_CONF_PWM_PCLK, (void *)&prm); + } + else + { + prm = PCLK_POSI_PWMS; + ret = sddev_control(ICU_DEV_NAME, CMD_CONF_PCLK_DCO, (void *)&prm); + + prm = pwm_param->channel; + ret = sddev_control(ICU_DEV_NAME, CMD_CONF_PWM_PCLK, (void *)&prm); + + } + ASSERT(ICU_SUCCESS == ret); + } + else + { + ret = sddev_control(ICU_DEV_NAME, CMD_CLK_PWR_DOWN, (void *)&prm); + ASSERT(ICU_SUCCESS == ret); + } + + if(PWM_INT_EN == pwm_param->cfg.bits.int_en) + { + prm = IRQ_PWM_BIT; + ret = sddev_control(ICU_DEV_NAME, CMD_ICU_INT_ENABLE, (void *)&prm); + } + +exit_icu: + + return; +} + +UINT8 init_pwm_param(pwm_param_t *pwm_param, UINT8 enable) +{ + UINT32 value; + + if((pwm_param == NULL) + || (pwm_param->channel >= PWM_COUNT) + || (pwm_param->duty_cycle1 > pwm_param->end_value)) + { + return 1; + } + + if (pwm_param->channel < 2) + { + current_group = 0; + current_channel = pwm_param->channel; + } + else if (pwm_param->channel < 4) + { + current_group = 1; + current_channel = pwm_param->channel-2; + } + else + { + current_group = 2; + current_channel = pwm_param->channel-4; + } + + if (pwm_param->cfg.bits.mode != PWM_TIMER_MODE) + { +#if (CFG_SOC_NAME == SOC_BK7231) + pwm_gpio_configuration(pwm_param->channel, enable); +#else + pwm_gpio_configuration(pwm_param->channel, enable); +#endif + } + + //pwm mode set + value = REG_READ(REG_PWM_GROUP_CTRL_ADDR(current_group)); + + + value = (value & (~(0x07 << PWM_GROUP_MODE_SET_BIT(current_channel)))) + | (pwm_param->cfg.bits.mode << PWM_GROUP_MODE_SET_BIT(current_channel)); + + REG_WRITE(REG_PWM_GROUP_CTRL_ADDR(current_group), value); + + PWM_PRT("value:0x%x, group:%x, channel:%x\r\n",value,current_group, current_channel); + PWM_PRT("ctrl:0x%lx\r\n",REG_READ(REG_PWM_GROUP_CTRL_ADDR(current_group))); + + //pwm freq set +#if (CFG_SOC_NAME == SOC_BK7231) + value = (((UINT32)pwm_param->duty_cycle & 0x0000FFFF) << 16) + + ((UINT32)pwm_param->end_value & 0x0000FFFF); + REG_WRITE(REG_APB_BK_PWMn_CNT_ADDR(pwm_param->channel), value); +#else + if(current_channel == 0) + { + value = (UINT32) pwm_param->duty_cycle1; + REG_WRITE(REG_GROUP_PWM0_T1_ADDR(current_group), value); + + value = (UINT32) pwm_param->duty_cycle2; + REG_WRITE(REG_GROUP_PWM0_T2_ADDR(current_group), value); + + value = (UINT32) pwm_param->duty_cycle3; + REG_WRITE(REG_GROUP_PWM0_T3_ADDR(current_group), value); + + value = (UINT32) pwm_param->end_value; + REG_WRITE(REG_GROUP_PWM0_T4_ADDR(current_group), value); + } + else + { + value = (UINT32) pwm_param->duty_cycle1; + REG_WRITE(REG_GROUP_PWM1_T1_ADDR(current_group), value); + + value = (UINT32) pwm_param->duty_cycle2; + REG_WRITE(REG_GROUP_PWM1_T2_ADDR(current_group), value); + + value = (UINT32) pwm_param->duty_cycle3; + REG_WRITE(REG_GROUP_PWM1_T3_ADDR(current_group), value); + + value = (UINT32) pwm_param->end_value; + REG_WRITE(REG_GROUP_PWM1_T4_ADDR(current_group), value); + + } +#endif + + //clear int status + value = REG_READ(REG_PWM_GROUP_CTRL_ADDR(current_group)); + value = value & (~(PWM_GROUP_PWM_INT_STAT_CLEAR(0) | PWM_GROUP_PWM_INT_STAT_CLEAR(1))); // no clear other status + value = value | PWM_GROUP_PWM_INT_STAT_CLEAR(current_channel); + + REG_WRITE(REG_PWM_GROUP_CTRL_ADDR(current_group), value); + + p_PWM_Int_Handler[pwm_param->channel] = pwm_param->p_Int_Handler; + + //pwm int set + value = REG_READ(REG_PWM_GROUP_CTRL_ADDR(current_group)); + value = (value & (~(0x01 << PWM_GROUP_PWM_INT_ENABLE_BIT(current_channel)))) + | (pwm_param->cfg.bits.int_en << PWM_GROUP_PWM_INT_ENABLE_BIT(current_channel)); + REG_WRITE(REG_PWM_GROUP_CTRL_ADDR(current_group), value); + + PWM_PRT("mode: %x, REG_PWM_GROUP_CTRL= 0x%lx\r\n",pwm_param->cfg.val ,REG_READ (REG_PWM_GROUP_CTRL_ADDR(current_group))); + pwm_icu_configuration(pwm_param, enable); + + return 0; +} + +void pwm_unit_enable(UINT8 ucChannel) +{ + UINT32 value; + + if (ucChannel > PWM_CHANNEL_NUMBER_MAX) + { + return; + } + + if (ucChannel < 2) + { + current_group = 0; + current_channel = ucChannel; + } + else if (ucChannel < 4) + { + current_group = 1; + current_channel = ucChannel-2; + } + else + { + current_group = 2; + current_channel = ucChannel-4; + } + + value = REG_READ(REG_PWM_GROUP_CTRL_ADDR(current_group)); + value |= PWM_GROUP_PWM_ENABLE_MASK(current_channel); + REG_WRITE(REG_PWM_GROUP_CTRL_ADDR(current_group), value); +} + +void pwm_unit_disable(UINT8 ucChannel) +{ + UINT32 value; + if (ucChannel > PWM_CHANNEL_NUMBER_MAX) + { + return; + } + + if (ucChannel < 2) + { + current_group = 0; + current_channel = ucChannel; + } + else if (ucChannel < 4) + { + current_group = 1; + current_channel = ucChannel-2; + } + else + { + current_group = 2; + current_channel = ucChannel-4; + } + + value = REG_READ(REG_PWM_GROUP_CTRL_ADDR(current_group)); + value &= ~(PWM_GROUP_PWM_ENABLE_MASK(current_channel)); + REG_WRITE(REG_PWM_GROUP_CTRL_ADDR(current_group), value); +} + +void pwm_interrupt_enable(UINT8 ucChannel, UINT32 enable) +{ + UINT32 value; + if (ucChannel > PWM_CHANNEL_NUMBER_MAX) + { + return; + } + + if (ucChannel < 2) + { + current_group = 0; + current_channel = ucChannel; + } + else if (ucChannel < 4) + { + current_group = 1; + current_channel = ucChannel-2; + } + else + { + current_group = 2; + current_channel = ucChannel-4; + } + + if(enable) + { + //clear int status + value = REG_READ(REG_PWM_GROUP_CTRL_ADDR(current_group)); + value = value & (~(PWM_GROUP_PWM_INT_STAT_CLEAR(0) | PWM_GROUP_PWM_INT_STAT_CLEAR(1))); // no clear other status + value = value | PWM_GROUP_PWM_INT_STAT_CLEAR(current_channel); + } + + //pwm int set + value = REG_READ(REG_PWM_GROUP_CTRL_ADDR(current_group)); + value = (value & (~(0x01 << PWM_GROUP_PWM_INT_ENABLE_BIT(current_channel)))) + | ((enable & 1) << PWM_GROUP_PWM_INT_ENABLE_BIT(current_channel)); + REG_WRITE(REG_PWM_GROUP_CTRL_ADDR(current_group), value); + + if(enable) + { + value = IRQ_PWM_BIT; + sddev_control(ICU_DEV_NAME, CMD_ICU_INT_ENABLE, (void *)&value); + } +} + + UINT32 pwm_capture_value_get(UINT8 ucChannel) +{ + UINT32 value,state; + + if (ucChannel < 2) + { + current_group = 0; + current_channel = ucChannel; + } + else if (ucChannel < 4) + { + current_group = 1; + current_channel = ucChannel-2; + } + else + { + current_group = 2; + current_channel = ucChannel-4; + } + + + value = REG_READ(REG_GROUP_PWM_CPU_ADDR(current_group)); + value |= 1 << current_channel; + REG_WRITE(REG_GROUP_PWM_CPU_ADDR(current_group), value); + + PWM_PRT("channel: %x, REG_PWM_GROUP_CTRL= 0x%lx\r\n",current_channel ,REG_READ (REG_PWM_GROUP_CTRL_ADDR(current_group))); + + state = REG_READ(REG_GROUP_PWM_CPU_ADDR(current_group)); + while ((state & (1 << ucChannel) )== 0 ) + { + PWM_PRT("channel: "); + } + + if(current_channel == 1) + { + value = REG_READ(REG_GROUP_PWM1_RD_DATA_ADDR(current_group)); + return value; + } + else + { + value = REG_READ(REG_GROUP_PWM0_RD_DATA_ADDR(current_group)); + return value; + } + +} + +static void pwm_set_duty_cycle(UINT8 ucChannel, UINT32 u32DutyCycle) +{ + UINT32 value; + + if (ucChannel < 2) + { + current_group = 0; + current_channel = ucChannel; + } + else if (ucChannel < 4) + { + current_group = 1; + current_channel = ucChannel-2; + } + else + { + current_group = 2; + current_channel = ucChannel-4; + } + + //check last opreation work + value = REG_READ(REG_PWM_GROUP_CTRL_ADDR(current_group)); + if (value & (PWM_GROUP_PWM_CFG_UPDATA_MASK(current_channel))) + { + PWM_FATAL("[bk_error]:wait updata pwm param"); + } + + if (current_channel ==0 ) + { + REG_WRITE(REG_GROUP_PWM0_T1_ADDR(current_group), u32DutyCycle); + } + else + { + REG_WRITE(REG_GROUP_PWM1_T1_ADDR(current_group), u32DutyCycle); + } + + // bit 7/15 :cfg_updata enable + value = REG_READ(REG_PWM_GROUP_CTRL_ADDR(current_group)); + value |= PWM_GROUP_PWM_CFG_UPDATA_MASK(current_channel); + REG_WRITE(REG_PWM_GROUP_CTRL_ADDR(current_group), value); + +} + +static void pwm_set_end_value(UINT8 ucChannel, UINT32 u32EndValue) +{ + UINT32 value; + + if (ucChannel < 2) + { + current_group = 0; + current_channel = ucChannel; + } + else if (ucChannel < 4) + { + current_group = 1; + current_channel = ucChannel-2; + } + else + { + current_group = 2; + current_channel = ucChannel-4; + } + + //check last opreation work + value = REG_READ(REG_PWM_GROUP_CTRL_ADDR(current_group)); + if (value & (PWM_GROUP_PWM_CFG_UPDATA_MASK(current_channel))) + { + PWM_FATAL("[bk_error]:wait updata pwm param"); + } + + if (current_channel ==0 ) + { + REG_WRITE(REG_GROUP_PWM0_T4_ADDR(current_group), u32EndValue); + } + else + { + REG_WRITE(REG_GROUP_PWM1_T4_ADDR(current_group), u32EndValue); + } + + // bit 7/15 :cfg_updata enable + value = REG_READ(REG_PWM_GROUP_CTRL_ADDR(current_group)); + value |= PWM_GROUP_PWM_CFG_UPDATA_MASK(current_channel); + REG_WRITE(REG_PWM_GROUP_CTRL_ADDR(current_group), value); + +} + +void pwm_group_enable(UINT8 ucChannel) +{ + UINT32 value; + + if (ucChannel > PWM_CHANNEL_NUMBER_MAX) + { + return; + } + + if (ucChannel < 2) + { + current_group = 0; + } + else if (ucChannel < 4) + { + current_group = 1; + } + else + { + current_group = 2; + } + + value = REG_READ(REG_PWM_GROUP_CTRL_ADDR(current_group)); + value |= PWM_GROUP_PWM_ENABLE_MASK(0)|PWM_GROUP_PWM_ENABLE_MASK(1) ; + REG_WRITE(REG_PWM_GROUP_CTRL_ADDR(current_group), value); +} + +void pwm_group_mode_disable(UINT8 ucChannel) +{ + UINT32 value; + + if (ucChannel > PWM_CHANNEL_NUMBER_MAX) + { + return; + } + + if (ucChannel < 2) + { + current_group = 0; + } + else if (ucChannel < 4) + { + current_group = 1; + } + else + { + current_group = 2; + } + + value = REG_READ(REG_PWM_GROUP_CTRL_ADDR(current_group)); + value &=( ~( PWM_GROUP_PWM_ENABLE_MASK(0)|PWM_GROUP_PWM_ENABLE_MASK(1) + |PWM_GROUP_PWM_GROUP_MODE_MASK | PWM_GROUP_PWM_GROUP_MODE_ENABLE_MASK)); + REG_WRITE(REG_PWM_GROUP_CTRL_ADDR(current_group), value); +} + +void pwm_group_mode_enable(UINT8 ucChannel) +{ + UINT32 value; + + if (ucChannel < 2) + { + current_group = 0; + current_channel = ucChannel; + } + else if (ucChannel < 4) + { + current_group = 1; + } + else + { + current_group = 2; + } + + value = REG_READ(REG_PWM_GROUP_CTRL_ADDR(current_group)); + + //enable grounp pwm mode + value |= PWM_GROUP_PWM_GROUP_MODE_MASK |PWM_GROUP_PWM_GROUP_MODE_ENABLE_MASK; + REG_WRITE(REG_PWM_GROUP_CTRL_ADDR(current_group), value); + pwm_group_enable(ucChannel); + + PWM_PRT("ctrl:0x%lx\r\n",REG_READ(REG_PWM_GROUP_CTRL_ADDR(current_group))); +} + +UINT8 pwm_init_levl_set_low(UINT8 ucChannel) +{ + UINT32 value; + if (ucChannel > PWM_CHANNEL_NUMBER_MAX) + { + return 1; + } + + if (ucChannel < 2) + { + current_group = 0; + current_channel = ucChannel; + } + else if (ucChannel < 4) + { + current_group = 1; + current_channel = ucChannel-2; + } + else + { + current_group = 2; + current_channel = ucChannel-4; + } + + value = REG_READ(REG_PWM_GROUP_CTRL_ADDR(current_group)); + value &= ~(PWM_GROUP_PWM_INT_LEVL_MASK(current_channel)); + REG_WRITE(REG_PWM_GROUP_CTRL_ADDR(current_group), value); + + return 0; + +} + +UINT8 pwm_init_levl_set_high(UINT8 ucChannel) +{ + UINT32 value; + if (ucChannel > PWM_CHANNEL_NUMBER_MAX) + { + return 1; + } + + if (ucChannel < 2) + { + current_group = 0; + current_channel = ucChannel; + } + else if (ucChannel < 4) + { + current_group = 1; + current_channel = ucChannel-2; + } + else + { + current_group = 2; + current_channel = ucChannel-4; + } + + value = REG_READ(REG_PWM_GROUP_CTRL_ADDR(current_group)); + value |= PWM_GROUP_PWM_INT_LEVL_MASK(current_channel); + REG_WRITE(REG_PWM_GROUP_CTRL_ADDR(current_group), value); + + return 0; +} + +UINT8 pwm_init_levl_get(UINT8 ucChannel) +{ + UINT32 value,ret; + if (ucChannel > PWM_CHANNEL_NUMBER_MAX) + { + return 1; + } + + if (ucChannel < 2) + { + current_group = 0; + current_channel = ucChannel; + } + else if (ucChannel < 4) + { + current_group = 1; + current_channel = ucChannel-2; + } + else + { + current_group = 2; + current_channel = ucChannel-4; + } + + value = REG_READ(REG_PWM_GROUP_CTRL_ADDR(current_group)); + + ret = value & PWM_GROUP_PWM_INT_LEVL_MASK(current_channel); + if(ret !=0 ) + { + return 1; + } + else + { + return 0; + } + +} + +void pwm_update_param(pwm_param_t *pwm_param) +{ + UINT32 value; + + current_group = get_current_group(pwm_param->channel); + + /*value = REG_READ(REG_PWM_GROUP_CTRL_ADDR(current_group)); + if (value & (PWM_GROUP_PWM_CFG_UPDATA_MASK(current_channel))) + { + bk_printf("[bk_error]:wait updata pwm param\r\n"); + return 0; + }*/ + + if(current_channel == 0) + { + value = (UINT32) pwm_param->duty_cycle1; + REG_WRITE(REG_GROUP_PWM0_T1_ADDR(current_group), value); + + value = (UINT32) pwm_param->duty_cycle2; + REG_WRITE(REG_GROUP_PWM0_T2_ADDR(current_group), value); + + value = (UINT32) pwm_param->duty_cycle3; + REG_WRITE(REG_GROUP_PWM0_T3_ADDR(current_group), value); + + value = (UINT32) pwm_param->end_value; + REG_WRITE(REG_GROUP_PWM0_T4_ADDR(current_group), value); + } + else + { + value = (UINT32) pwm_param->duty_cycle1; + REG_WRITE(REG_GROUP_PWM1_T1_ADDR(current_group), value); + + value = (UINT32) pwm_param->duty_cycle2; + REG_WRITE(REG_GROUP_PWM1_T2_ADDR(current_group), value); + + value = (UINT32) pwm_param->duty_cycle3; + REG_WRITE(REG_GROUP_PWM1_T3_ADDR(current_group), value); + + value = (UINT32) pwm_param->end_value; + REG_WRITE(REG_GROUP_PWM1_T4_ADDR(current_group), value); + } +} + +UINT8 pwm_single_update_param(pwm_param_t *pwm_param) +{ + UINT32 value; + UINT8 group,channel; + + group = get_set_group(pwm_param->channel); + channel = get_set_channel(pwm_param->channel); + + if(channel == 0) + { + value = (UINT32) pwm_param->duty_cycle1; + REG_WRITE(REG_GROUP_PWM0_T1_ADDR(group), value); + + value = (UINT32) pwm_param->duty_cycle2; + REG_WRITE(REG_GROUP_PWM0_T2_ADDR(group), value); + + value = (UINT32) pwm_param->duty_cycle3; + REG_WRITE(REG_GROUP_PWM0_T3_ADDR(group), value); + + value = (UINT32) pwm_param->end_value; + REG_WRITE(REG_GROUP_PWM0_T4_ADDR(group), value); + } + else + { + value = (UINT32) pwm_param->duty_cycle1; + REG_WRITE(REG_GROUP_PWM1_T1_ADDR(group), value); + + value = (UINT32) pwm_param->duty_cycle2; + REG_WRITE(REG_GROUP_PWM1_T2_ADDR(group), value); + + value = (UINT32) pwm_param->duty_cycle3; + REG_WRITE(REG_GROUP_PWM1_T3_ADDR(group), value); + + value = (UINT32) pwm_param->end_value; + REG_WRITE(REG_GROUP_PWM1_T4_ADDR(group), value); + } + + return 0; +} + +UINT8 pwm_update_param_enable(UINT8 ucChannel) +{ + UINT32 value; + UINT8 group,channel; + + group = get_set_group(ucChannel); + channel = get_set_channel(ucChannel); + + // bit 7/15 :cfg_updata enable + value = REG_READ(REG_PWM_GROUP_CTRL_ADDR(group)); + value |= PWM_GROUP_PWM_CFG_UPDATA_MASK(channel); + REG_WRITE(REG_PWM_GROUP_CTRL_ADDR(group), value); + + return 0; +} + +UINT8 pwm_single_update_param_enable(UINT8 ucChannel,UINT32 level) +{ + UINT32 value; + UINT8 group,channel; + + group = get_set_group(ucChannel); + channel = get_set_channel(ucChannel); + + + // cfg_updata and initial level update enable + value = REG_READ(REG_PWM_GROUP_CTRL_ADDR(group)); + value &= ~(PWM_GROUP_PWM_INT_LEVL_MASK(channel)); + + value |= PWM_GROUP_PWM_CFG_UPDATA_MASK(channel) + | (level << PWM_GROUP_PWM_INT_LEVL_BIT(channel)); + REG_WRITE(REG_PWM_GROUP_CTRL_ADDR(group), value); + + return 0; +} + +void pwm_group_update_param_enable(UINT8 channel1,UINT8 channel2,pwm_param_t *pwm_param) +{ + UINT32 value; + + if(channel1 >= PWM_COUNT) + { + return; + } + + if (channel1 < 2) + { + current_group = 0; + current_channel = channel1; + } + else if (channel1 < 4) + { + current_group = 1; + current_channel = channel1-2; + } + else + { + current_group = 2; + current_channel = channel1-4; + } + + // bit 7/15 :cfg_updata and init_level enable + value = REG_READ(REG_PWM_GROUP_CTRL_ADDR(current_group)); + value &= ~ (PWM_GROUP_PWM_INT_LEVL_MASK(1)|PWM_GROUP_PWM_INT_LEVL_MASK(0)); + if(current_channel == 0) { + value |= PWM_GROUP_PWM_CFG_UPDATA_MASK(0) | PWM_GROUP_PWM_CFG_UPDATA_MASK(1) + | (pwm_param->init_level1 << PWM_GROUP_PWM_INT_LEVL_BIT(1)) + | (pwm_param->init_level0 << PWM_GROUP_PWM_INT_LEVL_BIT(0)); + } else { + value |= PWM_GROUP_PWM_CFG_UPDATA_MASK(0) | PWM_GROUP_PWM_CFG_UPDATA_MASK(1) + | (pwm_param->init_level0 << PWM_GROUP_PWM_INT_LEVL_BIT(1)) + | (pwm_param->init_level1 << PWM_GROUP_PWM_INT_LEVL_BIT(0)); + + } + + REG_WRITE(REG_PWM_GROUP_CTRL_ADDR(current_group), value); +} + +void pwm_nogroup_update_param_enable(UINT8 channel1,UINT8 channel2,pwm_param_t *pwm_param) +{ + UINT32 value1,value2,group1,group2,chan1,chan2; + + group1= get_current_group(channel1); + chan1 = current_channel; + + group2= get_current_group(channel2); + chan2 = current_channel; + + // bit 7/15 :cfg_updata and init_level enable + value1 = REG_READ(REG_PWM_GROUP_CTRL_ADDR(group1)); + value2 = REG_READ(REG_PWM_GROUP_CTRL_ADDR(group2)); + + value1 &= ~ PWM_GROUP_PWM_INT_LEVL_MASK(chan1); + value1 |= PWM_GROUP_PWM_CFG_UPDATA_MASK(chan1) + | (pwm_param->init_level0 << PWM_GROUP_PWM_INT_LEVL_BIT(chan1)); + + value2 &= ~ PWM_GROUP_PWM_INT_LEVL_MASK(chan2); + value2 |= PWM_GROUP_PWM_CFG_UPDATA_MASK(chan2) + | (pwm_param->init_level1 << PWM_GROUP_PWM_INT_LEVL_BIT(chan2)); + + REG_WRITE(REG_PWM_GROUP_CTRL_ADDR(group1), value1); + REG_WRITE(REG_PWM_GROUP_CTRL_ADDR(group2), value2); +} + +void pwm_param_clear(UINT8 ucChannel) +{ + if (ucChannel < 2) + { + current_group = 0; + current_channel = ucChannel; + } + else if (ucChannel < 4) + { + current_group = 1; + current_channel = ucChannel-2; + } + else + { + current_group = 2; + current_channel = ucChannel-4; + } + + + if(current_channel == 0) + { + REG_WRITE(REG_GROUP_PWM0_T1_ADDR(current_group), 0); + REG_WRITE(REG_GROUP_PWM0_T2_ADDR(current_group), 0); + REG_WRITE(REG_GROUP_PWM0_T3_ADDR(current_group), 0); + REG_WRITE(REG_GROUP_PWM0_T4_ADDR(current_group), 0); + } + else + { + REG_WRITE(REG_GROUP_PWM1_T1_ADDR(current_group), 0); + REG_WRITE(REG_GROUP_PWM1_T2_ADDR(current_group), 0); + REG_WRITE(REG_GROUP_PWM1_T3_ADDR(current_group), 0); + REG_WRITE(REG_GROUP_PWM1_T4_ADDR(current_group), 0); + } + +} + + +static void pwm_int_handler_clear(UINT8 ucChannel) +{ + p_PWM_Int_Handler[ucChannel] = NULL; +} + +void pwm_init(void) +{ + REG_WRITE(REG_PWM_GROUP_CTRL_ADDR(0), 0x0); + REG_WRITE(REG_PWM_GROUP_CTRL_ADDR(1), 0x0); + REG_WRITE(REG_PWM_GROUP_CTRL_ADDR(2), 0x0); + + intc_service_register(IRQ_PWM, PRI_IRQ_PWM, pwm_isr); + sddev_register_dev(PWM_DEV_NAME, &pwm_op); +} + +void pwm_exit(void) +{ + sddev_unregister_dev(PWM_DEV_NAME); +} + +UINT32 pwm_ctrl(UINT32 cmd, void *param) +{ + UINT32 ret = PWM_SUCCESS; + UINT32 ucChannel; + pwm_param_t *p_param; + pwm_capture_t *p_capture; + GLOBAL_INT_DECLARATION(); + + switch(cmd) + { + case CMD_PWM_UNIT_ENABLE: + ucChannel = (*(UINT32 *)param); + if(ucChannel > 5) + { + ret = PWM_FAILURE; + break; + } + pwm_unit_enable(ucChannel); + break; + case CMD_PWM_UNIT_DISABLE: + ucChannel = (*(UINT32 *)param); + if(ucChannel > 5) + { + ret = PWM_FAILURE; + break; + } + pwm_unit_disable(ucChannel); + pwm_param_clear(ucChannel); + break; + case CMD_PWM_IR_ENABLE: + if(param) + { + pwm_int_cfg_t *p_cfg = (pwm_int_cfg_t *)param; + GLOBAL_INT_DISABLE(); + pwm_interrupt_enable(p_cfg->channel, 1); + GLOBAL_INT_RESTORE(); + } + break; + case CMD_PWM_IR_DISABLE: + if(param) + { + pwm_int_cfg_t *p_cfg = (pwm_int_cfg_t *)param; + GLOBAL_INT_DISABLE(); + pwm_interrupt_enable(p_cfg->channel, 0); + GLOBAL_INT_RESTORE(); + } + break; + case CMD_PWM_SET_IR_CALLBACK: + if(param) + { + pwm_int_cfg_t *p_cfg = (pwm_int_cfg_t *)param; + if (p_cfg->channel <= PWM_CHANNEL_NUMBER_MAX) + { + GLOBAL_INT_DISABLE(); + p_PWM_Int_Handler[p_cfg->channel] = p_cfg->p_Int_Handler; + GLOBAL_INT_RESTORE(); + } + } + break; + case CMD_PWM_IR_CLEAR: + ucChannel = (*(UINT32 *)param); + if(ucChannel > 5) + { + ret = PWM_FAILURE; + break; + } + pwm_int_handler_clear(ucChannel); + break; + case CMD_PWM_INIT_PARAM: + p_param = (pwm_param_t *)param; + init_pwm_param(p_param, 1); + break; + case CMD_PWM_SET_DUTY_CYCLE: + p_param = (pwm_param_t *)param; + if(p_param->channel >= PWM_COUNT) + { + ret = PWM_FAILURE; + break; + } + pwm_set_duty_cycle(p_param->channel, p_param->duty_cycle1); + break; + case CMD_PWM_SET_END_VALUE: + p_param = (pwm_param_t *)param; + if(p_param->channel >= PWM_COUNT) + { + ret = PWM_FAILURE; + break; + } + pwm_set_end_value(p_param->channel, p_param->end_value); + break; + case CMD_PWM_CAP_GET: + p_capture = (pwm_capture_t *)param; + if(p_capture->ucChannel >= PWM_COUNT) + { + ret = PWM_FAILURE; + break; + } + p_capture->value = pwm_capture_value_get(p_capture->ucChannel); + break; + case CMD_PWM_DEINIT_PARAM: + p_param = (pwm_param_t *)param; + init_pwm_param(p_param, 0); + break; + case CMD_PWM_GROUP_ENABLE: + ucChannel = (*(UINT32 *)param); + if(ucChannel > 5) + { + ret = PWM_FAILURE; + break; + } + pwm_group_mode_enable(ucChannel); + break; + case CMD_PWM_GROUP_DISABLE: + ucChannel = (*(UINT32 *)param); + if(ucChannel > 5) + { + ret = PWM_FAILURE; + break; + } + pwm_group_mode_disable(ucChannel); + break; + case CMD_PWM_UPDATA_PARAM: + p_param = (pwm_param_t *)param; + pwm_update_param(p_param); + break; + case CMD_PWM_SINGLE_UPDATA_PARAM: + p_param = (pwm_param_t *)param; + pwm_single_update_param(p_param); + break; + case CMD_PWM_UPDATA_PARAM_ENABLE: + ucChannel = (*(UINT32 *)param); + if(ucChannel > 5) + { + ret = PWM_FAILURE; + break; + } + pwm_update_param_enable(ucChannel); + break; + case CMD_PWM_INIT_LEVL_SET_LOW: + ucChannel = (*(UINT32 *)param); + if(ucChannel > 5) + { + ret = PWM_FAILURE; + break; + } + pwm_init_levl_set_low(ucChannel); + break; + case CMD_PWM_INIT_LEVL_SET_HIGH: + ucChannel = (*(UINT32 *)param); + if(ucChannel > 5) + { + ret = PWM_FAILURE; + break; + } + pwm_init_levl_set_high(ucChannel); + break; + default: + ret = PWM_FAILURE; + break; + } + + return ret; +} + +//note:pwm mode no isr +void pwm_isr(void) +{ + int i; + UINT32 status, pwm_group, pwm_chan; + + for(i = 0; i < PWM_COUNT; i++) + { + if (i < 2) + { + pwm_group = 0; + pwm_chan = i; + } + else if (i < 4) + { + pwm_group = 1; + pwm_chan = i-2; + } + else + { + pwm_group = 2; + pwm_chan = i-4; + } + + status = REG_READ(REG_PWM_GROUP_CTRL_ADDR(pwm_group)); + if(status & PWM_GROUP_PWM_INT_STAT_MASK(pwm_chan)) + { + uint32_t value = REG_READ(REG_PWM_GROUP_CTRL_ADDR(pwm_group)); + value = value & (~(PWM_GROUP_PWM_INT_STAT_CLEAR(0) | PWM_GROUP_PWM_INT_STAT_CLEAR(1))); // no clear other status + value = value | PWM_GROUP_PWM_INT_STAT_CLEAR(pwm_chan); + REG_WRITE(REG_PWM_GROUP_CTRL_ADDR(pwm_group), value); + if(p_PWM_Int_Handler[i]) + { + p_PWM_Int_Handler[i]((UINT8)i); + } + } + } +} + +#endif diff --git a/beken_os/beken378/driver/pwm/pwm_new.h b/beken_os/beken378/driver/pwm/pwm_new.h new file mode 100755 index 0000000..5e00355 --- /dev/null +++ b/beken_os/beken378/driver/pwm/pwm_new.h @@ -0,0 +1,122 @@ +#ifndef _PWM_H_ +#define _PWM_H_ + +#if (CFG_SOC_NAME == SOC_BK7231N) + + +#ifdef PWM_DEBUG +#define PWM_PRT bk_printf +#define PWM_WARN warning_prf +#define PWM_FATAL bk_printf +#else +#define PWM_PRT null_prf +#define PWM_WARN null_prf +#define PWM_FATAL null_prf +#endif + +#define REG_PWM_BASE_ADDR (0x00802B00UL) +#define PWM_CHANNEL_NUMBER_ALL 6 +#define PWM_CHANNEL_NUMBER_MAX (PWM_CHANNEL_NUMBER_ALL - 1) +#define PWM_CHANNEL_NUMBER_MIN 0 + +#define REG_PWM_GROUP_ADDR(x) (REG_PWM_BASE_ADDR + (0x40 * x)) + +#define REG_PWM_GROUP_CTRL_ADDR(x) (REG_PWM_GROUP_ADDR(x) + 0x00 * 4) +#define REG_PWM_CTRL_MASK 0xFFFFFFFFUL +#define REG_PWM_GROUP_CTRL(x) (*((volatile unsigned long *) REG_PWM_GROUP_CTRL_ADDR(x))) + +#define PWM_GROUP_MODE_SET_BIT(x) (8*x) + +#define PWM_GROUP_PWM_ENABLE_BIT(x) (8*x + 3) +#define PWM_GROUP_PWM_ENABLE_MASK(x) (1 <> 31) + +#define POSRC_BEKEN_REG0x0_spi_reset 30 +#define BITRC_BEKEN_REG0x0_spi_reset 0x40000000 +#define SET_RC_BEKEN_REG0x0_spi_reset(val) ADDRC_BEKEN_REG0x0 = ((ADDRC_BEKEN_REG0x0 & (~0x40000000)) | (val << 30)) +#define SETF_RC_BEKEN_REG0x0_spi_reset ADDRC_BEKEN_REG0x0 |= 0x40000000 +#define CLRF_RC_BEKEN_REG0x0_spi_reset ADDRC_BEKEN_REG0x0 &= ~0x40000000 +#define GET_RC_BEKEN_REG0x0_spi_reset ((ADDRC_BEKEN_REG0x0 & 0x40000000) >> 30) + + +#define POSRC_BEKEN_REG0x0_rc_state 16 +#define BITRC_BEKEN_REG0x0_rc_state 0x70000 +#define SET_RC_BEKEN_REG0x0_rc_state(val) ADDRC_BEKEN_REG0x0 = ((ADDRC_BEKEN_REG0x0 & (~0x70000)) | (val << 16)) +#define GET_RC_BEKEN_REG0x0_rc_state ((ADDRC_BEKEN_REG0x0 & 0x70000) >> 16) + + +#define POSRC_BEKEN_REG0x0_ch0_shdn_stat 12 +#define BITRC_BEKEN_REG0x0_ch0_shdn_stat 0x1000 +#define SET_RC_BEKEN_REG0x0_ch0_shdn_stat(val) ADDRC_BEKEN_REG0x0 = ((ADDRC_BEKEN_REG0x0 & (~0x1000)) | (val << 12)) +#define SETF_RC_BEKEN_REG0x0_ch0_shdn_stat ADDRC_BEKEN_REG0x0 |= 0x1000 +#define CLRF_RC_BEKEN_REG0x0_ch0_shdn_stat ADDRC_BEKEN_REG0x0 &= ~0x1000 +#define GET_RC_BEKEN_REG0x0_ch0_shdn_stat ((ADDRC_BEKEN_REG0x0 & 0x1000) >> 12) + + +#define POSRC_BEKEN_REG0x0_ch0_ld 8 +#define BITRC_BEKEN_REG0x0_ch0_ld 0x100 +#define SET_RC_BEKEN_REG0x0_ch0_ld(val) ADDRC_BEKEN_REG0x0 = ((ADDRC_BEKEN_REG0x0 & (~0x100)) | (val << 8)) +#define SETF_RC_BEKEN_REG0x0_ch0_ld ADDRC_BEKEN_REG0x0 |= 0x100 +#define CLRF_RC_BEKEN_REG0x0_ch0_ld ADDRC_BEKEN_REG0x0 &= ~0x100 +#define GET_RC_BEKEN_REG0x0_ch0_ld ((ADDRC_BEKEN_REG0x0 & 0x100) >> 8) + + +#define POSRC_BEKEN_REG0x0_rc_en 3 +#define BITRC_BEKEN_REG0x0_rc_en 0x8 +#define SET_RC_BEKEN_REG0x0_rc_en(val) ADDRC_BEKEN_REG0x0 = ((ADDRC_BEKEN_REG0x0 & (~0x8)) | (val << 3)) +#define SETF_RC_BEKEN_REG0x0_rc_en ADDRC_BEKEN_REG0x0 |= 0x8 +#define CLRF_RC_BEKEN_REG0x0_rc_en ADDRC_BEKEN_REG0x0 &= ~0x8 +#define GET_RC_BEKEN_REG0x0_rc_en ((ADDRC_BEKEN_REG0x0 & 0x8) >> 3) + + +#define POSRC_BEKEN_REG0x0_ch0_en 0 +#define BITRC_BEKEN_REG0x0_ch0_en 0x1 +#define SET_RC_BEKEN_REG0x0_ch0_en(val) ADDRC_BEKEN_REG0x0 = ((ADDRC_BEKEN_REG0x0 & (~0x1)) | (val << 0)) +#define SETF_RC_BEKEN_REG0x0_ch0_en ADDRC_BEKEN_REG0x0 |= 0x1 +#define CLRF_RC_BEKEN_REG0x0_ch0_en ADDRC_BEKEN_REG0x0 &= ~0x1 +#define GET_RC_BEKEN_REG0x0_ch0_en (ADDRC_BEKEN_REG0x0 & 0x1) + +//ADDRC_BEKEN_REG0x1 +#define ADDRC_BEKEN_REG0x1 *((volatile unsigned long *) (0x01050000+0x1*4)) +#define POSRC_BEKEN_REG0x1_prescaler 28 +#define BITRC_BEKEN_REG0x1_prescaler 0xF0000000 +#define SET_RC_BEKEN_REG0x1_prescaler(val) ADDRC_BEKEN_REG0x1 = ((ADDRC_BEKEN_REG0x1 & (~0xF0000000)) | (val << 28)) +#define GET_RC_BEKEN_REG0x1_prescaler ((ADDRC_BEKEN_REG0x1 & 0xF0000000) >> 28) + +#define POSRC_BEKEN_REG0x1_trx_reg_stat 0 +#define BITRC_BEKEN_REG0x1_trx_reg_stat 0xFFFFFFF +#define SET_RC_BEKEN_REG0x1_trx_reg_stat(val) ADDRC_BEKEN_REG0x1 = ((ADDRC_BEKEN_REG0x1 & (~0xFFFFFFF)) | (val << 0)) +#define GET_RC_BEKEN_REG0x1_trx_reg_stat (ADDRC_BEKEN_REG0x1 & 0xFFFFFFF) + +//ADDRC_BEKEN_REG0x5 +#define ADDRC_BEKEN_REG0x5 *((volatile unsigned long *) (0x01050000+0x5*4)) + +#define POSRC_BEKEN_REG0x5_ch0_outpower 0 +#define BITRC_BEKEN_REG0x5_ch0_outpower 0xFF +#define SET_RC_BEKEN_REG0x5_ch0_outpower(val) ADDRC_BEKEN_REG0x5 = ((ADDRC_BEKEN_REG0x5 & (~0xFF)) | (val << 0)) +#define GET_RC_BEKEN_REG0x5_ch0_outpower (ADDRC_BEKEN_REG0x5 & 0xFF) + +//ADDRC_BEKEN_REG0x8 +#define ADDRC_BEKEN_REG0x8 *((volatile unsigned long *) (0x01050000+0x8*4)) + +#define POSRC_BEKEN_REG0x8_CH0_RX_OFF_DELAY 16 +#define BITRC_BEKEN_REG0x8_CH0_RX_OFF_DELAY 0xFF0000 +#define SET_RC_BEKEN_REG0x8_CH0_RX_OFF_DELAY(val) ADDRC_BEKEN_REG0x8 = ((ADDRC_BEKEN_REG0x8 & (~0xFF0000)) | (val << 16)) +#define GET_RC_BEKEN_REG0x8_CH0_RX_OFF_DELAY ((ADDRC_BEKEN_REG0x8 & 0xFF0000) >> 16) + + +#define POSRC_BEKEN_REG0x8_CH0_RX_ON_DELAY 0 +#define BITRC_BEKEN_REG0x8_CH0_RX_ON_DELAY 0xFF +#define SET_RC_BEKEN_REG0x8_CH0_RX_ON_DELAY(val) ADDRC_BEKEN_REG0x8 = ((ADDRC_BEKEN_REG0x8 & (~0xFF)) | (val << 0)) +#define GET_RC_BEKEN_REG0x8_CH0_RX_ON_DELAY (ADDRC_BEKEN_REG0x8 & 0xFF) + +//ADDRC_BEKEN_REG0xb +#define ADDRC_BEKEN_REG0xb *((volatile unsigned long *) (0x01050000+0xb*4)) + +#define POSRC_BEKEN_REG0xb_CH0_TX_OFF_DELAY 16 +#define BITRC_BEKEN_REG0xb_CH0_TX_OFF_DELAY 0xFF0000 +#define SET_RC_BEKEN_REG0xb_CH0_TX_OFF_DELAY(val) ADDRC_BEKEN_REG0xb = ((ADDRC_BEKEN_REG0xb & (~0xFF0000)) | (val << 16)) +#define GET_RC_BEKEN_REG0xb_CH0_TX_OFF_DELAY ((ADDRC_BEKEN_REG0xb & 0xFF0000) >> 16) + + +#define POSRC_BEKEN_REG0xb_CH0_TX_ON_DELAY 0 +#define BITRC_BEKEN_REG0xb_CH0_TX_ON_DELAY 0xFF +#define SET_RC_BEKEN_REG0xb_CH0_TX_ON_DELAY(val) ADDRC_BEKEN_REG0xb = ((ADDRC_BEKEN_REG0xb & (~0xFF)) | (val << 0)) +#define GET_RC_BEKEN_REG0xb_CH0_TX_ON_DELAY (ADDRC_BEKEN_REG0xb & 0xFF) + +//ADDRC_BEKEN_REG0xe +#define ADDRC_BEKEN_REG0xe *((volatile unsigned long *) (0x01050000+0xe*4)) + +#define POSRC_BEKEN_REG0xe_CH0_PA_OFF_DELAY 16 +#define BITRC_BEKEN_REG0xe_CH0_PA_OFF_DELAY 0xFF0000 +#define SET_RC_BEKEN_REG0xe_CH0_PA_OFF_DELAY(val) ADDRC_BEKEN_REG0xe = ((ADDRC_BEKEN_REG0xe & (~0xFF0000)) | (val << 16)) +#define GET_RC_BEKEN_REG0xe_CH0_PA_OFF_DELAY ((ADDRC_BEKEN_REG0xe & 0xFF0000) >> 16) + + +#define POSRC_BEKEN_REG0xe_CH0_PA_ON_DELAY 0 +#define BITRC_BEKEN_REG0xe_CH0_PA_ON_DELAY 0xFF +#define SET_RC_BEKEN_REG0xe_CH0_PA_ON_DELAY(val) ADDRC_BEKEN_REG0xe = ((ADDRC_BEKEN_REG0xe & (~0xFF)) | (val << 0)) +#define GET_RC_BEKEN_REG0xe_CH0_PA_ON_DELAY (ADDRC_BEKEN_REG0xe & 0xFF) + +//ADDRC_BEKEN_REG0x11 +#define ADDRC_BEKEN_REG0x11 *((volatile unsigned long *) (0x01050000+0x11*4)) + +#define POSRC_BEKEN_REG0x11_CH0_SHDN_OFF_DELAY 16 +#define BITRC_BEKEN_REG0x11_CH0_SHDN_OFF_DELAY 0xFF0000 +#define SET_RC_BEKEN_REG0x11_CH0_SHDN_OFF_DELAY(val) ADDRC_BEKEN_REG0x11 = ((ADDRC_BEKEN_REG0x11 & (~0xFF0000)) | (val << 16)) +#define GET_RC_BEKEN_REG0x11_CH0_SHDN_OFF_DELAY ((ADDRC_BEKEN_REG0x11 & 0xFF0000) >> 16) + + +#define POSRC_BEKEN_REG0x11_CH0_SHDN_ON_DELAY 0 +#define BITRC_BEKEN_REG0x11_CH0_SHDN_ON_DELAY 0xFF +#define SET_RC_BEKEN_REG0x11_CH0_SHDN_ON_DELAY(val) ADDRC_BEKEN_REG0x11 = ((ADDRC_BEKEN_REG0x11 & (~0xFF)) | (val << 0)) +#define GET_RC_BEKEN_REG0x11_CH0_SHDN_ON_DELAY (ADDRC_BEKEN_REG0x11 & 0xFF) + +//ADDRC_BEKEN_REG0x19 +#define ADDRC_BEKEN_REG0x19 *((volatile unsigned long *) (0x01050000+0x19*4)) + +#define POSRC_BEKEN_REG0x19_F_CH0_EN 16 +#define BITRC_BEKEN_REG0x19_F_CH0_EN 0x10000 +#define SET_RC_BEKEN_REG0x19_F_CH0_EN(val) ADDRC_BEKEN_REG0x19 = ((ADDRC_BEKEN_REG0x19 & (~0x10000)) | (val << 16)) +#define SETF_RC_BEKEN_REG0x19_F_CH0_EN ADDRC_BEKEN_REG0x19 |= 0x10000 +#define CLRF_RC_BEKEN_REG0x19_F_CH0_EN ADDRC_BEKEN_REG0x19 &= ~0x10000 +#define GET_RC_BEKEN_REG0x19_F_CH0_EN ((ADDRC_BEKEN_REG0x19 & 0x10000) >> 16) + +#define POSRC_BEKEN_REG0x19_F_CH0_B 8 +#define BITRC_BEKEN_REG0x19_F_CH0_B 0xFF00 +#define SET_RC_BEKEN_REG0x19_F_CH0_B(val) ADDRC_BEKEN_REG0x19 = ((ADDRC_BEKEN_REG0x19 & (~0xFF00)) | (val << 8)) +#define GET_RC_BEKEN_REG0x19_F_CH0_B ((ADDRC_BEKEN_REG0x19 & 0xFF00) >> 8) + + +#define POSRC_BEKEN_REG0x19_F_CH0_RXHP 3 +#define BITRC_BEKEN_REG0x19_F_CH0_RXHP 0x8 +#define SET_RC_BEKEN_REG0x19_F_CH0_RXHP(val) ADDRC_BEKEN_REG0x19 = ((ADDRC_BEKEN_REG0x19 & (~0x8)) | (val << 3)) +#define SETF_RC_BEKEN_REG0x19_F_CH0_RXHP ADDRC_BEKEN_REG0x19 |= 0x8 +#define CLRF_RC_BEKEN_REG0x19_F_CH0_RXHP ADDRC_BEKEN_REG0x19 &= ~0x8 +#define GET_RC_BEKEN_REG0x19_F_CH0_RXHP ((ADDRC_BEKEN_REG0x19 & 0x8) >> 3) + +#define POSRC_BEKEN_REG0x19_F_CH0_TXEN 2 +#define BITRC_BEKEN_REG0x19_F_CH0_TXEN 0x4 +#define SET_RC_BEKEN_REG0x19_F_CH0_TXEN(val) ADDRC_BEKEN_REG0x19 = ((ADDRC_BEKEN_REG0x19 & (~0x4)) | (val << 2)) +#define SETF_RC_BEKEN_REG0x19_F_CH0_TXEN ADDRC_BEKEN_REG0x19 |= 0x4 +#define CLRF_RC_BEKEN_REG0x19_F_CH0_TXEN ADDRC_BEKEN_REG0x19 &= ~0x4 +#define GET_RC_BEKEN_REG0x19_F_CH0_TXEN ((ADDRC_BEKEN_REG0x19 & 0x4) >> 2) + +#define POSRC_BEKEN_REG0x19_F_CH0_RXEN 1 +#define BITRC_BEKEN_REG0x19_F_CH0_RXEN 0x2 +#define SET_RC_BEKEN_REG0x19_F_CH0_RXEN(val) ADDRC_BEKEN_REG0x19 = ((ADDRC_BEKEN_REG0x19 & (~0x2)) | (val << 1)) +#define SETF_RC_BEKEN_REG0x19_F_CH0_RXEN ADDRC_BEKEN_REG0x19 |= 0x2 +#define CLRF_RC_BEKEN_REG0x19_F_CH0_RXEN ADDRC_BEKEN_REG0x19 &= ~0x2 +#define GET_RC_BEKEN_REG0x19_F_CH0_RXEN ((ADDRC_BEKEN_REG0x19 & 0x2) >> 1) + +#define POSRC_BEKEN_REG0x19_F_CH0_SHDN 0 +#define BITRC_BEKEN_REG0x19_F_CH0_SHDN 0x1 +#define SET_RC_BEKEN_REG0x19_F_CH0_SHDN(val) ADDRC_BEKEN_REG0x19 = ((ADDRC_BEKEN_REG0x19 & (~0x1)) | (val << 0)) +#define SETF_RC_BEKEN_REG0x19_F_CH0_SHDN ADDRC_BEKEN_REG0x19 |= 0x1 +#define CLRF_RC_BEKEN_REG0x19_F_CH0_SHDN ADDRC_BEKEN_REG0x19 &= ~0x1 +#define GET_RC_BEKEN_REG0x19_F_CH0_SHDN (ADDRC_BEKEN_REG0x19 & 0x1) + +//ADDRC_BEKEN_REG0x1c +#define ADDRC_BEKEN_REG0x1c *((volatile unsigned long *) (0x01050000+0x1c*4)) + +#define POSRC_BEKEN_REG0x1c_F_TX_ON 1 +#define BITRC_BEKEN_REG0x1c_F_TX_ON 0x2 +#define SET_RC_BEKEN_REG0x1c_F_TX_ON(val) ADDRC_BEKEN_REG0x1c = ((ADDRC_BEKEN_REG0x1c & (~0x2)) | (val << 1)) +#define SETF_RC_BEKEN_REG0x1c_F_TX_ON ADDRC_BEKEN_REG0x1c |= 0x2 +#define CLRF_RC_BEKEN_REG0x1c_F_TX_ON ADDRC_BEKEN_REG0x1c &= ~0x2 +#define GET_RC_BEKEN_REG0x1c_F_TX_ON ((ADDRC_BEKEN_REG0x1c & 0x2) >> 1) + +#define POSRC_BEKEN_REG0x1c_F_RX_ON 0 +#define BITRC_BEKEN_REG0x1c_F_RX_ON 0x1 +#define SET_RC_BEKEN_REG0x1c_F_RX_ON(val) ADDRC_BEKEN_REG0x1c = ((ADDRC_BEKEN_REG0x1c & (~0x1)) | (val << 0)) +#define SETF_RC_BEKEN_REG0x1c_F_RX_ON ADDRC_BEKEN_REG0x1c |= 0x1 +#define CLRF_RC_BEKEN_REG0x1c_F_RX_ON ADDRC_BEKEN_REG0x1c &= ~0x1 +#define GET_RC_BEKEN_REG0x1c_F_RX_ON (ADDRC_BEKEN_REG0x1c & 0x1) + +//ADDRC_BEKEN_REG0x1e +#define ADDRC_BEKEN_REG0x1e *((volatile unsigned long *) (0x01050000+0x1e*4)) + +#define POSRC_BEKEN_REG0x1e_FE_RX_ON_DEL 0 +#define BITRC_BEKEN_REG0x1e_FE_RX_ON_DEL 0xFFF +#define SET_RC_BEKEN_REG0x1e_FE_RX_ON_DEL(val) ADDRC_BEKEN_REG0x1e = ((ADDRC_BEKEN_REG0x1e & (~0xFFF)) | (val << 0)) +#define GET_RC_BEKEN_REG0x1e_FE_RX_ON_DEL (ADDRC_BEKEN_REG0x1e & 0xFFF) + +//ADDRC_BEKEN_REG0x3c +#define ADDRC_BEKEN_REG0x3c *((volatile unsigned long *) (0x01050000+0x3c*4)) +#define POSRC_BEKEN_REG0x3c_RX_DC_CAL_EN 31 +#define BITRC_BEKEN_REG0x3c_RX_DC_CAL_EN 0x80000000 +#define SET_RC_BEKEN_REG0x3c_RX_DC_CAL_EN(val) ADDRC_BEKEN_REG0x3c = ((ADDRC_BEKEN_REG0x3c & (~0x80000000)) | (val << 31)) +#define SETF_RC_BEKEN_REG0x3c_RX_DC_CAL_EN ADDRC_BEKEN_REG0x3c |= 0x80000000 +#define CLRF_RC_BEKEN_REG0x3c_RX_DC_CAL_EN ADDRC_BEKEN_REG0x3c &= ~0x80000000 +#define GET_RC_BEKEN_REG0x3c_RX_DC_CAL_EN ((ADDRC_BEKEN_REG0x3c & 0x80000000) >> 31) + +#define POSRC_BEKEN_REG0x3c_RX_AVG_MODE 30 +#define BITRC_BEKEN_REG0x3c_RX_AVG_MODE 0x40000000 +#define SET_RC_BEKEN_REG0x3c_RX_AVG_MODE(val) ADDRC_BEKEN_REG0x3c = ((ADDRC_BEKEN_REG0x3c & (~0x40000000)) | (val << 30)) +#define SETF_RC_BEKEN_REG0x3c_RX_AVG_MODE ADDRC_BEKEN_REG0x3c |= 0x40000000 +#define CLRF_RC_BEKEN_REG0x3c_RX_AVG_MODE ADDRC_BEKEN_REG0x3c &= ~0x40000000 +#define GET_RC_BEKEN_REG0x3c_RX_AVG_MODE ((ADDRC_BEKEN_REG0x3c & 0x40000000) >> 30) + +#define POSRC_BEKEN_REG0x3c_RX_IQ_SWAP 29 +#define BITRC_BEKEN_REG0x3c_RX_IQ_SWAP 0x20000000 +#define SET_RC_BEKEN_REG0x3c_RX_IQ_SWAP(val) ADDRC_BEKEN_REG0x3c = ((ADDRC_BEKEN_REG0x3c & (~0x20000000)) | (val << 29)) +#define SETF_RC_BEKEN_REG0x3c_RX_IQ_SWAP ADDRC_BEKEN_REG0x3c |= 0x20000000 +#define CLRF_RC_BEKEN_REG0x3c_RX_IQ_SWAP ADDRC_BEKEN_REG0x3c &= ~0x20000000 +#define GET_RC_BEKEN_REG0x3c_RX_IQ_SWAP ((ADDRC_BEKEN_REG0x3c & 0x20000000) >> 29) + +#define POSRC_BEKEN_REG0x3c_RX_HPF_BYPASS 28 +#define BITRC_BEKEN_REG0x3c_RX_HPF_BYPASS 0x10000000 +#define SET_RC_BEKEN_REG0x3c_RX_HPF_BYPASS(val) ADDRC_BEKEN_REG0x3c = ((ADDRC_BEKEN_REG0x3c & (~0x10000000)) | (val << 28)) +#define SETF_RC_BEKEN_REG0x3c_RX_HPF_BYPASS ADDRC_BEKEN_REG0x3c |= 0x10000000 +#define CLRF_RC_BEKEN_REG0x3c_RX_HPF_BYPASS ADDRC_BEKEN_REG0x3c &= ~0x10000000 +#define GET_RC_BEKEN_REG0x3c_RX_HPF_BYPASS ((ADDRC_BEKEN_REG0x3c & 0x10000000) >> 28) + + +#define POSRC_BEKEN_REG0x3c_RX_AVG_I_RD 12 +#define BITRC_BEKEN_REG0x3c_RX_AVG_I_RD 0xFFF000 +#define SET_RC_BEKEN_REG0x3c_RX_AVG_I_RD(val) ADDRC_BEKEN_REG0x3c = ((ADDRC_BEKEN_REG0x3c & (~0xFFF000)) | (val << 12)) +#define GET_RC_BEKEN_REG0x3c_RX_AVG_I_RD ((ADDRC_BEKEN_REG0x3c & 0xFFF000) >> 12) + +#define POSRC_BEKEN_REG0x3c_RX_AVG_Q_RD 0 +#define BITRC_BEKEN_REG0x3c_RX_AVG_Q_RD 0xFFF +#define SET_RC_BEKEN_REG0x3c_RX_AVG_Q_RD(val) ADDRC_BEKEN_REG0x3c = ((ADDRC_BEKEN_REG0x3c & (~0xFFF)) | (val << 0)) +#define GET_RC_BEKEN_REG0x3c_RX_AVG_Q_RD (ADDRC_BEKEN_REG0x3c & 0xFFF) + +//ADDRC_BEKEN_REG0x3e +#define ADDRC_BEKEN_REG0x3e *((volatile unsigned long *) (0x01050000+0x3e*4)) +#define POSRC_BEKEN_REG0x3e_RX_CAL_EN 31 +#define BITRC_BEKEN_REG0x3e_RX_CAL_EN 0x80000000 +#define SET_RC_BEKEN_REG0x3e_RX_CAL_EN(val) ADDRC_BEKEN_REG0x3e = ((ADDRC_BEKEN_REG0x3e & (~0x80000000)) | (val << 31)) +#define SETF_RC_BEKEN_REG0x3e_RX_CAL_EN ADDRC_BEKEN_REG0x3e |= 0x80000000 +#define CLRF_RC_BEKEN_REG0x3e_RX_CAL_EN ADDRC_BEKEN_REG0x3e &= ~0x80000000 +#define GET_RC_BEKEN_REG0x3e_RX_CAL_EN ((ADDRC_BEKEN_REG0x3e & 0x80000000) >> 31) + +#define POSRC_BEKEN_REG0x3e_RX_COMP_EN 30 +#define BITRC_BEKEN_REG0x3e_RX_COMP_EN 0x40000000 +#define SET_RC_BEKEN_REG0x3e_RX_COMP_EN(val) ADDRC_BEKEN_REG0x3e = ((ADDRC_BEKEN_REG0x3e & (~0x40000000)) | (val << 30)) +#define SETF_RC_BEKEN_REG0x3e_RX_COMP_EN ADDRC_BEKEN_REG0x3e |= 0x40000000 +#define CLRF_RC_BEKEN_REG0x3e_RX_COMP_EN ADDRC_BEKEN_REG0x3e &= ~0x40000000 +#define GET_RC_BEKEN_REG0x3e_RX_COMP_EN ((ADDRC_BEKEN_REG0x3e & 0x40000000) >> 30) + + +#define POSRC_BEKEN_REG0x3e_RX_DC_I_RD 12 +#define BITRC_BEKEN_REG0x3e_RX_DC_I_RD 0xFFF000 +#define SET_RC_BEKEN_REG0x3e_RX_DC_I_RD(val) ADDRC_BEKEN_REG0x3e = ((ADDRC_BEKEN_REG0x3e & (~0xFFF000)) | (val << 12)) +#define GET_RC_BEKEN_REG0x3e_RX_DC_I_RD ((ADDRC_BEKEN_REG0x3e & 0xFFF000) >> 12) + +#define POSRC_BEKEN_REG0x3e_RX_DC_Q_RD 0 +#define BITRC_BEKEN_REG0x3e_RX_DC_Q_RD 0xFFF +#define SET_RC_BEKEN_REG0x3e_RX_DC_Q_RD(val) ADDRC_BEKEN_REG0x3e = ((ADDRC_BEKEN_REG0x3e & (~0xFFF)) | (val << 0)) +#define GET_RC_BEKEN_REG0x3e_RX_DC_Q_RD (ADDRC_BEKEN_REG0x3e & 0xFFF) + +//ADDRC_BEKEN_REG0x3f +#define ADDRC_BEKEN_REG0x3f *((volatile unsigned long *) (0x01050000+0x3f*4)) + +#define POSRC_BEKEN_REG0x3f_RX_AMP_ERR_RD 16 +#define BITRC_BEKEN_REG0x3f_RX_AMP_ERR_RD 0x3FF0000 +#define SET_RC_BEKEN_REG0x3f_RX_AMP_ERR_RD(val) ADDRC_BEKEN_REG0x3f = ((ADDRC_BEKEN_REG0x3f & (~0x3FF0000)) | (val << 16)) +#define GET_RC_BEKEN_REG0x3f_RX_AMP_ERR_RD ((ADDRC_BEKEN_REG0x3f & 0x3FF0000) >> 16) + + +#define POSRC_BEKEN_REG0x3f_RX_PHASE_ERR_RD 0 +#define BITRC_BEKEN_REG0x3f_RX_PHASE_ERR_RD 0x3FF +#define SET_RC_BEKEN_REG0x3f_RX_PHASE_ERR_RD(val) ADDRC_BEKEN_REG0x3f = ((ADDRC_BEKEN_REG0x3f & (~0x3FF)) | (val << 0)) +#define GET_RC_BEKEN_REG0x3f_RX_PHASE_ERR_RD (ADDRC_BEKEN_REG0x3f & 0x3FF) + +//ADDRC_BEKEN_REG0x40 +#define ADDRC_BEKEN_REG0x40 *((volatile unsigned long *) (0x01050000+0x40*4)) + +#define POSRC_BEKEN_REG0x40_RX_TY2_RD 0 +#define BITRC_BEKEN_REG0x40_RX_TY2_RD 0x3FF +#define SET_RC_BEKEN_REG0x40_RX_TY2_RD(val) ADDRC_BEKEN_REG0x40 = ((ADDRC_BEKEN_REG0x40 & (~0x3FF)) | (val << 0)) +#define GET_RC_BEKEN_REG0x40_RX_TY2_RD (ADDRC_BEKEN_REG0x40 & 0x3FF) + +//ADDRC_BEKEN_REG0x41 +#define ADDRC_BEKEN_REG0x41 *((volatile unsigned long *) (0x01050000+0x41*4)) + +#define POSRC_BEKEN_REG0x41_RX_DC_I_WR 12 +#define BITRC_BEKEN_REG0x41_RX_DC_I_WR 0xFFF000 +#define SET_RC_BEKEN_REG0x41_RX_DC_I_WR(val) ADDRC_BEKEN_REG0x41 = ((ADDRC_BEKEN_REG0x41 & (~0xFFF000)) | (val << 12)) +#define GET_RC_BEKEN_REG0x41_RX_DC_I_WR ((ADDRC_BEKEN_REG0x41 & 0xFFF000) >> 12) + +#define POSRC_BEKEN_REG0x41_RX_DC_Q_WR 0 +#define BITRC_BEKEN_REG0x41_RX_DC_Q_WR 0xFFF +#define SET_RC_BEKEN_REG0x41_RX_DC_Q_WR(val) ADDRC_BEKEN_REG0x41 = ((ADDRC_BEKEN_REG0x41 & (~0xFFF)) | (val << 0)) +#define GET_RC_BEKEN_REG0x41_RX_DC_Q_WR (ADDRC_BEKEN_REG0x41 & 0xFFF) + +//ADDRC_BEKEN_REG0x42 +#define ADDRC_BEKEN_REG0x42 *((volatile unsigned long *) (0x01050000+0x42*4)) + +#define POSRC_BEKEN_REG0x42_RX_AMP_ERR_WR 16 +#define BITRC_BEKEN_REG0x42_RX_AMP_ERR_WR 0x3FF0000 +#define SET_RC_BEKEN_REG0x42_RX_AMP_ERR_WR(val) ADDRC_BEKEN_REG0x42 = ((ADDRC_BEKEN_REG0x42 & (~0x3FF0000)) | (val << 16)) +#define GET_RC_BEKEN_REG0x42_RX_AMP_ERR_WR ((ADDRC_BEKEN_REG0x42 & 0x3FF0000) >> 16) + + +#define POSRC_BEKEN_REG0x42_RX_PHASE_ERR_WR 0 +#define BITRC_BEKEN_REG0x42_RX_PHASE_ERR_WR 0x3FF +#define SET_RC_BEKEN_REG0x42_RX_PHASE_ERR_WR(val) ADDRC_BEKEN_REG0x42 = ((ADDRC_BEKEN_REG0x42 & (~0x3FF)) | (val << 0)) +#define GET_RC_BEKEN_REG0x42_RX_PHASE_ERR_WR (ADDRC_BEKEN_REG0x42 & 0x3FF) + +//ADDRC_BEKEN_REG0x4c +#define ADDRC_BEKEN_REG0x4c *((volatile unsigned long *) (0x01050000+0x4c*4)) +#define POSRC_BEKEN_REG0x4c_TEST_PATTERN 30 +#define BITRC_BEKEN_REG0x4c_TEST_PATTERN 0xC0000000 +#define SET_RC_BEKEN_REG0x4c_TEST_PATTERN(val) ADDRC_BEKEN_REG0x4c = ((ADDRC_BEKEN_REG0x4c & (~0xC0000000)) | (val << 30)) +#define GET_RC_BEKEN_REG0x4c_TEST_PATTERN ((ADDRC_BEKEN_REG0x4c & 0xC0000000) >> 30) + +#define POSRC_BEKEN_REG0x4c_TX_COMP_DIS 29 +#define BITRC_BEKEN_REG0x4c_TX_COMP_DIS 0x20000000 +#define SET_RC_BEKEN_REG0x4c_TX_COMP_DIS(val) ADDRC_BEKEN_REG0x4c = ((ADDRC_BEKEN_REG0x4c & (~0x20000000)) | (val << 29)) +#define SETF_RC_BEKEN_REG0x4c_TX_COMP_DIS ADDRC_BEKEN_REG0x4c |= 0x20000000 +#define CLRF_RC_BEKEN_REG0x4c_TX_COMP_DIS ADDRC_BEKEN_REG0x4c &= ~0x20000000 +#define GET_RC_BEKEN_REG0x4c_TX_COMP_DIS ((ADDRC_BEKEN_REG0x4c & 0x20000000) >> 29) + +#define POSRC_BEKEN_REG0x4c_DPD_EN 28 +#define BITRC_BEKEN_REG0x4c_DPD_EN 0x10000000 +#define SET_RC_BEKEN_REG0x4c_DPD_EN(val) ADDRC_BEKEN_REG0x4c = ((ADDRC_BEKEN_REG0x4c & (~0x10000000)) | (val << 28)) +#define SETF_RC_BEKEN_REG0x4c_DPD_EN ADDRC_BEKEN_REG0x4c |= 0x10000000 +#define CLRF_RC_BEKEN_REG0x4c_DPD_EN ADDRC_BEKEN_REG0x4c &= ~0x10000000 +#define GET_RC_BEKEN_REG0x4c_DPD_EN ((ADDRC_BEKEN_REG0x4c & 0x10000000) >> 28) + +#define POSRC_BEKEN_REG0x4c_DPD_CAL_EN 27 +#define BITRC_BEKEN_REG0x4c_DPD_CAL_EN 0x8000000 +#define SET_RC_BEKEN_REG0x4c_DPD_CAL_EN(val) ADDRC_BEKEN_REG0x4c = ((ADDRC_BEKEN_REG0x4c & (~0x8000000)) | (val << 27)) +#define SETF_RC_BEKEN_REG0x4c_DPD_CAL_EN ADDRC_BEKEN_REG0x4c |= 0x8000000 +#define CLRF_RC_BEKEN_REG0x4c_DPD_CAL_EN ADDRC_BEKEN_REG0x4c &= ~0x8000000 +#define GET_RC_BEKEN_REG0x4c_DPD_CAL_EN ((ADDRC_BEKEN_REG0x4c & 0x8000000) >> 27) + +#define POSRC_BEKEN_REG0x4c_DPD_COMP_EN 26 +#define BITRC_BEKEN_REG0x4c_DPD_COMP_EN 0x4000000 +#define SET_RC_BEKEN_REG0x4c_DPD_COMP_EN(val) ADDRC_BEKEN_REG0x4c = ((ADDRC_BEKEN_REG0x4c & (~0x4000000)) | (val << 26)) +#define SETF_RC_BEKEN_REG0x4c_DPD_COMP_EN ADDRC_BEKEN_REG0x4c |= 0x4000000 +#define CLRF_RC_BEKEN_REG0x4c_DPD_COMP_EN ADDRC_BEKEN_REG0x4c &= ~0x4000000 +#define GET_RC_BEKEN_REG0x4c_DPD_COMP_EN ((ADDRC_BEKEN_REG0x4c & 0x4000000) >> 26) + +#define POSRC_BEKEN_REG0x4c_I_CONSTANT 16 +#define BITRC_BEKEN_REG0x4c_I_CONSTANT 0x3FF0000 +#define SET_RC_BEKEN_REG0x4c_I_CONSTANT(val) ADDRC_BEKEN_REG0x4c = ((ADDRC_BEKEN_REG0x4c & (~0x3FF0000)) | (val << 16)) +#define GET_RC_BEKEN_REG0x4c_I_CONSTANT ((ADDRC_BEKEN_REG0x4c & 0x3FF0000) >> 16) + + +#define POSRC_BEKEN_REG0x4c_Q_CONSTANT 0 +#define BITRC_BEKEN_REG0x4c_Q_CONSTANT 0x3FF +#define SET_RC_BEKEN_REG0x4c_Q_CONSTANT(val) ADDRC_BEKEN_REG0x4c = ((ADDRC_BEKEN_REG0x4c & (~0x3FF)) | (val << 0)) +#define GET_RC_BEKEN_REG0x4c_Q_CONSTANT (ADDRC_BEKEN_REG0x4c & 0x3FF) + +//ADDRC_BEKEN_REG0x4d +#define ADDRC_BEKEN_REG0x4d *((volatile unsigned long *) (0x01050000+0x4d*4)) +#define POSRC_BEKEN_REG0x4d_TX_SIN_F 22 +#define BITRC_BEKEN_REG0x4d_TX_SIN_F 0xFFC00000 +#define SET_RC_BEKEN_REG0x4d_TX_SIN_F(val) ADDRC_BEKEN_REG0x4d = ((ADDRC_BEKEN_REG0x4d & (~0xFFC00000)) | (val << 22)) +#define GET_RC_BEKEN_REG0x4d_TX_SIN_F ((ADDRC_BEKEN_REG0x4d & 0xFFC00000) >> 22) + + +#define POSRC_BEKEN_REG0x4d_TX_SIN_MODE 16 +#define BITRC_BEKEN_REG0x4d_TX_SIN_MODE 0x30000 +#define SET_RC_BEKEN_REG0x4d_TX_SIN_MODE(val) ADDRC_BEKEN_REG0x4d = ((ADDRC_BEKEN_REG0x4d & (~0x30000)) | (val << 16)) +#define GET_RC_BEKEN_REG0x4d_TX_SIN_MODE ((ADDRC_BEKEN_REG0x4d & 0x30000) >> 16) + +#define POSRC_BEKEN_REG0x4d_TX_SIN_AMP 12 +#define BITRC_BEKEN_REG0x4d_TX_SIN_AMP 0xF000 +#define SET_RC_BEKEN_REG0x4d_TX_SIN_AMP(val) ADDRC_BEKEN_REG0x4d = ((ADDRC_BEKEN_REG0x4d & (~0xF000)) | (val << 12)) +#define GET_RC_BEKEN_REG0x4d_TX_SIN_AMP ((ADDRC_BEKEN_REG0x4d & 0xF000) >> 12) + + +//ADDRC_BEKEN_REG0x4f +#define ADDRC_BEKEN_REG0x4f *((volatile unsigned long *) (0x01050000+0x4f*4)) + +#define POSRC_BEKEN_REG0x4f_TX_I_DC_COMP 16 +#define BITRC_BEKEN_REG0x4f_TX_I_DC_COMP 0x3FF0000 +#define SET_RC_BEKEN_REG0x4f_TX_I_DC_COMP(val) ADDRC_BEKEN_REG0x4f = ((ADDRC_BEKEN_REG0x4f & (~0x3FF0000)) | (val << 16)) +#define GET_RC_BEKEN_REG0x4f_TX_I_DC_COMP ((ADDRC_BEKEN_REG0x4f & 0x3FF0000) >> 16) + + +#define POSRC_BEKEN_REG0x4f_TX_Q_DC_COMP 0 +#define BITRC_BEKEN_REG0x4f_TX_Q_DC_COMP 0x3FF +#define SET_RC_BEKEN_REG0x4f_TX_Q_DC_COMP(val) ADDRC_BEKEN_REG0x4f = ((ADDRC_BEKEN_REG0x4f & (~0x3FF)) | (val << 0)) +#define GET_RC_BEKEN_REG0x4f_TX_Q_DC_COMP (ADDRC_BEKEN_REG0x4f & 0x3FF) + +//ADDRC_BEKEN_REG0x50 +#define ADDRC_BEKEN_REG0x50 *((volatile unsigned long *) (0x01050000+0x50*4)) + +#define POSRC_BEKEN_REG0x50_TX_I_GAIN_COMP 16 +#define BITRC_BEKEN_REG0x50_TX_I_GAIN_COMP 0x3FF0000 +#define SET_RC_BEKEN_REG0x50_TX_I_GAIN_COMP(val) ADDRC_BEKEN_REG0x50 = ((ADDRC_BEKEN_REG0x50 & (~0x3FF0000)) | (val << 16)) +#define GET_RC_BEKEN_REG0x50_TX_I_GAIN_COMP ((ADDRC_BEKEN_REG0x50 & 0x3FF0000) >> 16) + + +#define POSRC_BEKEN_REG0x50_TX_Q_GAIN_COMP 0 +#define BITRC_BEKEN_REG0x50_TX_Q_GAIN_COMP 0x3FF +#define SET_RC_BEKEN_REG0x50_TX_Q_GAIN_COMP(val) ADDRC_BEKEN_REG0x50 = ((ADDRC_BEKEN_REG0x50 & (~0x3FF)) | (val << 0)) +#define GET_RC_BEKEN_REG0x50_TX_Q_GAIN_COMP (ADDRC_BEKEN_REG0x50 & 0x3FF) + +//ADDRC_BEKEN_REG0x51 +#define ADDRC_BEKEN_REG0x51 *((volatile unsigned long *) (0x01050000+0x51*4)) + +#define POSRC_BEKEN_REG0x51_TX_PHASE_COMP 16 +#define BITRC_BEKEN_REG0x51_TX_PHASE_COMP 0x3FF0000 +#define SET_RC_BEKEN_REG0x51_TX_PHASE_COMP(val) ADDRC_BEKEN_REG0x51 = ((ADDRC_BEKEN_REG0x51 & (~0x3FF0000)) | (val << 16)) +#define GET_RC_BEKEN_REG0x51_TX_PHASE_COMP ((ADDRC_BEKEN_REG0x51 & 0x3FF0000) >> 16) + + +#define POSRC_BEKEN_REG0x51_TX_TY2 0 +#define BITRC_BEKEN_REG0x51_TX_TY2 0x3FF +#define SET_RC_BEKEN_REG0x51_TX_TY2(val) ADDRC_BEKEN_REG0x51 = ((ADDRC_BEKEN_REG0x51 & (~0x3FF)) | (val << 0)) +#define GET_RC_BEKEN_REG0x51_TX_TY2 (ADDRC_BEKEN_REG0x51 & 0x3FF) + +//ADDRC_BEKEN_REG0x52 +#define ADDRC_BEKEN_REG0x52 *((volatile unsigned long *) (0x01050000+0x52*4)) +#define POSRC_BEKEN_REG0x52_TX_IQ_SWAP 31 +#define BITRC_BEKEN_REG0x52_TX_IQ_SWAP 0x80000000 +#define SET_RC_BEKEN_REG0x52_TX_IQ_SWAP(val) ADDRC_BEKEN_REG0x52 = ((ADDRC_BEKEN_REG0x52 & (~0x80000000)) | (val << 31)) +#define SETF_RC_BEKEN_REG0x52_TX_IQ_SWAP ADDRC_BEKEN_REG0x52 |= 0x80000000 +#define CLRF_RC_BEKEN_REG0x52_TX_IQ_SWAP ADDRC_BEKEN_REG0x52 &= ~0x80000000 +#define GET_RC_BEKEN_REG0x52_TX_IQ_SWAP ((ADDRC_BEKEN_REG0x52 & 0x80000000) >> 31) + +#define POSRC_BEKEN_REG0x52_IQ_CONSTANT_POUT 21 +#define BITRC_BEKEN_REG0x52_IQ_CONSTANT_POUT 0x7FE00000 +#define SET_RC_BEKEN_REG0x52_IQ_CONSTANT_POUT(val) ADDRC_BEKEN_REG0x52 = ((ADDRC_BEKEN_REG0x52 & (~0x7FE00000)) | (val << 21)) +#define GET_RC_BEKEN_REG0x52_IQ_CONSTANT_POUT ((ADDRC_BEKEN_REG0x52 & 0x7FE00000) >> 21) + +#define POSRC_BEKEN_REG0x52_TX_PRE_GAIN 16 +#define BITRC_BEKEN_REG0x52_TX_PRE_GAIN 0x1F0000 +#define SET_RC_BEKEN_REG0x52_TX_PRE_GAIN(val) ADDRC_BEKEN_REG0x52 = ((ADDRC_BEKEN_REG0x52 & (~0x1F0000)) | (val << 16)) +#define GET_RC_BEKEN_REG0x52_TX_PRE_GAIN ((ADDRC_BEKEN_REG0x52 & 0x1F0000) >> 16) + +#define POSRC_BEKEN_REG0x52_IQ_CONSTANT_IQCAL_P 6 +#define BITRC_BEKEN_REG0x52_IQ_CONSTANT_IQCAL_P 0xFFC0 +#define SET_RC_BEKEN_REG0x52_IQ_CONSTANT_IQCAL_P(val) ADDRC_BEKEN_REG0x52 = ((ADDRC_BEKEN_REG0x52 & (~0xFFC0)) | (val << 6)) +#define GET_RC_BEKEN_REG0x52_IQ_CONSTANT_IQCAL_P ((ADDRC_BEKEN_REG0x52 & 0xFFC0) >> 6) + + +//ADDRC_BEKEN_REG0x54 +#define ADDRC_BEKEN_REG0x54 *((volatile unsigned long *) (0x01050000+0x54*4)) +#define POSRC_BEKEN_REG0x54_AGC_MAP_MODE 31 +#define BITRC_BEKEN_REG0x54_AGC_MAP_MODE 0x80000000 +#define SET_RC_BEKEN_REG0x54_AGC_MAP_MODE(val) ADDRC_BEKEN_REG0x54 = ((ADDRC_BEKEN_REG0x54 & (~0x80000000)) | (val << 31)) +#define SETF_RC_BEKEN_REG0x54_AGC_MAP_MODE ADDRC_BEKEN_REG0x54 |= 0x80000000 +#define CLRF_RC_BEKEN_REG0x54_AGC_MAP_MODE ADDRC_BEKEN_REG0x54 &= ~0x80000000 +#define GET_RC_BEKEN_REG0x54_AGC_MAP_MODE ((ADDRC_BEKEN_REG0x54 & 0x80000000) >> 31) + +#define POSRC_BEKEN_REG0x54_AGC_LNA_RD 29 +#define BITRC_BEKEN_REG0x54_AGC_LNA_RD 0x60000000 +#define SET_RC_BEKEN_REG0x54_AGC_LNA_RD(val) ADDRC_BEKEN_REG0x54 = ((ADDRC_BEKEN_REG0x54 & (~0x60000000)) | (val << 29)) +#define GET_RC_BEKEN_REG0x54_AGC_LNA_RD ((ADDRC_BEKEN_REG0x54 & 0x60000000) >> 29) + +#define POSRC_BEKEN_REG0x54_AGC_BUF_RD 28 +#define BITRC_BEKEN_REG0x54_AGC_BUF_RD 0x10000000 +#define SET_RC_BEKEN_REG0x54_AGC_BUF_RD(val) ADDRC_BEKEN_REG0x54 = ((ADDRC_BEKEN_REG0x54 & (~0x10000000)) | (val << 28)) +#define SETF_RC_BEKEN_REG0x54_AGC_BUF_RD ADDRC_BEKEN_REG0x54 |= 0x10000000 +#define CLRF_RC_BEKEN_REG0x54_AGC_BUF_RD ADDRC_BEKEN_REG0x54 &= ~0x10000000 +#define GET_RC_BEKEN_REG0x54_AGC_BUF_RD ((ADDRC_BEKEN_REG0x54 & 0x10000000) >> 28) + +#define POSRC_BEKEN_REG0x54_AGC_PGA_RD 24 +#define BITRC_BEKEN_REG0x54_AGC_PGA_RD 0xF000000 +#define SET_RC_BEKEN_REG0x54_AGC_PGA_RD(val) ADDRC_BEKEN_REG0x54 = ((ADDRC_BEKEN_REG0x54 & (~0xF000000)) | (val << 24)) +#define GET_RC_BEKEN_REG0x54_AGC_PGA_RD ((ADDRC_BEKEN_REG0x54 & 0xF000000) >> 24) + +#define POSRC_BEKEN_REG0x54_TSSI_RD 16 +#define BITRC_BEKEN_REG0x54_TSSI_RD 0xFF0000 +#define SET_RC_BEKEN_REG0x54_TSSI_RD(val) ADDRC_BEKEN_REG0x54 = ((ADDRC_BEKEN_REG0x54 & (~0xFF0000)) | (val << 16)) +#define GET_RC_BEKEN_REG0x54_TSSI_RD ((ADDRC_BEKEN_REG0x54 & 0xFF0000) >> 16) + +#define POSRC_BEKEN_REG0x54_ST_SAR_ADC 14 +#define BITRC_BEKEN_REG0x54_ST_SAR_ADC 0xC000 +#define SET_RC_BEKEN_REG0x54_ST_SAR_ADC(val) ADDRC_BEKEN_REG0x54 = ((ADDRC_BEKEN_REG0x54 & (~0xC000)) | (val << 14)) +#define GET_RC_BEKEN_REG0x54_ST_SAR_ADC ((ADDRC_BEKEN_REG0x54 & 0xC000) >> 14) + +#define POSRC_BEKEN_REG0x54_ST_RX_ADC 12 +#define BITRC_BEKEN_REG0x54_ST_RX_ADC 0x3000 +#define SET_RC_BEKEN_REG0x54_ST_RX_ADC(val) ADDRC_BEKEN_REG0x54 = ((ADDRC_BEKEN_REG0x54 & (~0x3000)) | (val << 12)) +#define GET_RC_BEKEN_REG0x54_ST_RX_ADC ((ADDRC_BEKEN_REG0x54 & 0x3000) >> 12) + +#define POSRC_BEKEN_REG0x54_TX_DC_N 10 +#define BITRC_BEKEN_REG0x54_TX_DC_N 0xC00 +#define SET_RC_BEKEN_REG0x54_TX_DC_N(val) ADDRC_BEKEN_REG0x54 = ((ADDRC_BEKEN_REG0x54 & (~0xC00)) | (val << 10)) +#define GET_RC_BEKEN_REG0x54_TX_DC_N ((ADDRC_BEKEN_REG0x54 & 0xC00) >> 10) + +#define POSRC_BEKEN_REG0x54_DSEL_VA 9 +#define BITRC_BEKEN_REG0x54_DSEL_VA 0x200 +#define SET_RC_BEKEN_REG0x54_DSEL_VA(val) ADDRC_BEKEN_REG0x54 = ((ADDRC_BEKEN_REG0x54 & (~0x200)) | (val << 9)) +#define SETF_RC_BEKEN_REG0x54_DSEL_VA ADDRC_BEKEN_REG0x54 |= 0x200 +#define CLRF_RC_BEKEN_REG0x54_DSEL_VA ADDRC_BEKEN_REG0x54 &= ~0x200 +#define GET_RC_BEKEN_REG0x54_DSEL_VA ((ADDRC_BEKEN_REG0x54 & 0x200) >> 9) + +#define POSRC_BEKEN_REG0x54_TSSI_POUT_TH 1 +#define BITRC_BEKEN_REG0x54_TSSI_POUT_TH 0x1FE +#define SET_RC_BEKEN_REG0x54_TSSI_POUT_TH(val) ADDRC_BEKEN_REG0x54 = ((ADDRC_BEKEN_REG0x54 & (~0x1FE)) | (val << 1)) +#define GET_RC_BEKEN_REG0x54_TSSI_POUT_TH ((ADDRC_BEKEN_REG0x54 & 0x1FE) >> 1) + +#define POSRC_BEKEN_REG0x54_ST_RX_ADC_IQ 0 +#define BITRC_BEKEN_REG0x54_ST_RX_ADC_IQ 0x1 +#define SET_RC_BEKEN_REG0x54_ST_RX_ADC_IQ(val) ADDRC_BEKEN_REG0x54 = ((ADDRC_BEKEN_REG0x54 & (~0x1)) | (val << 0)) +#define SETF_RC_BEKEN_REG0x54_ST_RX_ADC_IQ ADDRC_BEKEN_REG0x54 |= 0x1 +#define CLRF_RC_BEKEN_REG0x54_ST_RX_ADC_IQ ADDRC_BEKEN_REG0x54 &= ~0x1 +#define GET_RC_BEKEN_REG0x54_ST_RX_ADC_IQ (ADDRC_BEKEN_REG0x54 & 0x1) + +//ADDRC_BEKEN_REG0x55 +#define ADDRC_BEKEN_REG0x55 *((volatile unsigned long *) (0x01050000+0x55*4)) + +#define POSRC_BEKEN_REG0x55_RX_SNR_SIG 16 +#define BITRC_BEKEN_REG0x55_RX_SNR_SIG 0x1FF0000 +#define SET_RC_BEKEN_REG0x55_RX_SNR_SIG(val) ADDRC_BEKEN_REG0x55 = ((ADDRC_BEKEN_REG0x55 & (~0x1FF0000)) | (val << 16)) +#define GET_RC_BEKEN_REG0x55_RX_SNR_SIG ((ADDRC_BEKEN_REG0x55 & 0x1FF0000) >> 16) + + +#define POSRC_BEKEN_REG0x55_RX_SNR_NOISE 0 +#define BITRC_BEKEN_REG0x55_RX_SNR_NOISE 0x1FF +#define SET_RC_BEKEN_REG0x55_RX_SNR_NOISE(val) ADDRC_BEKEN_REG0x55 = ((ADDRC_BEKEN_REG0x55 & (~0x1FF)) | (val << 0)) +#define GET_RC_BEKEN_REG0x55_RX_SNR_NOISE (ADDRC_BEKEN_REG0x55 & 0x1FF) + +//ADDRC_BEKEN_REG0x5c +#define ADDRC_BEKEN_REG0x5c *((volatile unsigned long *) (0x01050000+0x5c*4)) +#define POSRC_BEKEN_REG0x5c_trx_bank_rpt 31 +#define BITRC_BEKEN_REG0x5c_trx_bank_rpt 0x80000000 +#define SET_RC_BEKEN_REG0x5c_trx_bank_rpt(val) ADDRC_BEKEN_REG0x5c = ((ADDRC_BEKEN_REG0x5c & (~0x80000000)) | (val << 31)) +#define SETF_RC_BEKEN_REG0x5c_trx_bank_rpt ADDRC_BEKEN_REG0x5c |= 0x80000000 +#define CLRF_RC_BEKEN_REG0x5c_trx_bank_rpt ADDRC_BEKEN_REG0x5c &= ~0x80000000 +#define GET_RC_BEKEN_REG0x5c_trx_bank_rpt ((ADDRC_BEKEN_REG0x5c & 0x80000000) >> 31) + + +#define POSRC_BEKEN_REG0x5c_trx_spi_intval 0 +#define BITRC_BEKEN_REG0x5c_trx_spi_intval 0x3FF +#define SET_RC_BEKEN_REG0x5c_trx_spi_intval(val) ADDRC_BEKEN_REG0x5c = ((ADDRC_BEKEN_REG0x5c & (~0x3FF)) | (val << 0)) +#define GET_RC_BEKEN_REG0x5c_trx_spi_intval (ADDRC_BEKEN_REG0x5c & 0x3FF) + +//ADDRC_BEKEN_REG0x6a +#define ADDRC_BEKEN_REG0x6a *((volatile unsigned long *) (0x01050000+0x6a*4)) + +#define POSRC_BEKEN_REG0x6a_trx_ADDa_reg_stat 0 +#define BITRC_BEKEN_REG0x6a_trx_ADDa_reg_stat 0x3F +#define SET_RC_BEKEN_REG0x6a_trx_ADDa_reg_stat(val) ADDRC_BEKEN_REG0x6a = ((ADDRC_BEKEN_REG0x6a & (~0x3F)) | (val << 0)) +#define GET_RC_BEKEN_REG0x6a_trx_ADDa_reg_stat (ADDRC_BEKEN_REG0x6a & 0x3F) + +#endif // _RC_BEKEN_H_ diff --git a/beken_os/beken378/driver/rw_pub/rw_platf_pub.c b/beken_os/beken378/driver/rw_pub/rw_platf_pub.c new file mode 100755 index 0000000..5e4ee49 --- /dev/null +++ b/beken_os/beken378/driver/rw_pub/rw_platf_pub.c @@ -0,0 +1,42 @@ +#include "rw_platf_pub.h" +#include "sys_config.h" +#include "reg_mac_core.h" +#include "reg_mac_pl.h" +#include "mcu_ps_pub.h" + +extern void rwnxl_violence_reset_patch(void); +UINT32 mcu_ps_machw_reset(void); + +void rwxl_reset_patch(void) +{ + rwnxl_violence_reset_patch(); +} + +void hal_machw_init_diagnostic_ports(void) +{ + // Initialize diagnostic ports +#if (CFG_SOC_NAME == SOC_BK7231) + nxmac_debug_port_sel_pack(0x1C, 0x25); +#else + nxmac_debug_port_sel_pack(0x01, 0x07); + + //bypass buf fix + REG_PL_WR(0xc0000700, 0x08); +#endif // (CFG_SOC_NAME == SOC_BK7231) +} + +void hal_machw_before_reset_patch(void) +{ + #if CFG_USE_MCU_PS + mcu_ps_machw_cal(); + mcu_ps_machw_reset(); + #endif +} + +void hal_machw_after_reset_patch(void) +{ + #if CFG_USE_MCU_PS + mcu_ps_machw_init(); + #endif +} + diff --git a/beken_os/beken378/driver/rw_pub/rw_platf_pub.h b/beken_os/beken378/driver/rw_pub/rw_platf_pub.h new file mode 100755 index 0000000..aae8627 --- /dev/null +++ b/beken_os/beken378/driver/rw_pub/rw_platf_pub.h @@ -0,0 +1,10 @@ +#ifndef _RW_PLATF_PUB_H_ +#define _RW_PLATF_PUB_H_ + + +void rwxl_reset_patch(void); +void hal_machw_init_diagnostic_ports(void); +void hal_machw_before_reset_patch(void); +void hal_machw_after_reset_patch(void); + +#endif diff --git a/beken_os/beken378/driver/saradc/saradc.c b/beken_os/beken378/driver/saradc/saradc.c new file mode 100755 index 0000000..7586f51 --- /dev/null +++ b/beken_os/beken378/driver/saradc/saradc.c @@ -0,0 +1,654 @@ +#include "include.h" +#include "arm_arch.h" +#include "saradc.h" +#include "saradc_pub.h" +#include "drv_model_pub.h" +#include "intc_pub.h" +#include "icu_pub.h" +#include "sys_ctrl_pub.h" +#include "gpio_pub.h" +#include "uart_pub.h" +#include "mcu_ps_pub.h" +#include "temp_detect_pub.h" +#include + +#if CFG_SUPPORT_ALIOS +#include "ll.h" +#endif + +saradc_desc_t *saradc_desc = NULL; +saradc_calibrate_val saradc_val = { +#if (CFG_SOC_NAME == SOC_BK7231N) + 0x6B8, 0xD7A /* 1Volt, 2Volt*/ +#else + 0x55, 0x354 +#endif +}; +static volatile u8 saradc_is_busy = 0; +static DD_OPERATIONS saradc_op = { + saradc_open, + saradc_close, + NULL, + NULL, + saradc_ctrl +}; + +static void saradc_int_clr(void); + +static void saradc_flush(void) +{ + UINT32 value; + + value = REG_READ(SARADC_ADC_CONFIG); + value &= ~(SARADC_ADC_MODE_MASK << SARADC_ADC_MODE_POSI); + value &= ~(SARADC_ADC_CHNL_EN); + value |= SARADC_ADC_INT_CLR; + REG_WRITE(SARADC_ADC_CONFIG, value); + + // clear fifo + value = REG_READ(SARADC_ADC_CONFIG); + while((value & SARADC_ADC_FIFO_EMPTY) == 0) { + REG_READ(SARADC_ADC_DATA); + REG_READ(SARADC_ADC_DAT_AFTER_STA); + value = REG_READ(SARADC_ADC_CONFIG); + } + + saradc_int_clr(); +} + +void saradc_init(void) +{ + intc_service_register(IRQ_SARADC, PRI_IRQ_SARADC, saradc_isr); + + ddev_register_dev(SARADC_DEV_NAME, &saradc_op); + + saradc_flush(); +} + +void saradc_exit(void) +{ + ddev_unregister_dev(SARADC_DEV_NAME); +} + +static void saradc_enable_sysctrl(void) +{ + //UINT32 param = 0; + //sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_SET_GADC_SEL, ¶m); +} + +static void saradc_disable_sysctrl(void) +{ + //UINT32 param = 1; + //sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_SET_GADC_SEL, ¶m); +} + +static void saradc_enable_icu_config(void) +{ + UINT32 param; + param = PWD_SARADC_CLK_BIT; + sddev_control(ICU_DEV_NAME, CMD_CLK_PWR_UP, ¶m); +} + +static void saradc_disable_icu_config(void) +{ + UINT32 param; + param = PWD_SARADC_CLK_BIT; + sddev_control(ICU_DEV_NAME, CMD_CLK_PWR_DOWN, ¶m); +} + +static void saradc_enable_interrupt(void) +{ + UINT32 param; + param = (IRQ_SARADC_BIT); + sddev_control(ICU_DEV_NAME, CMD_ICU_INT_ENABLE, ¶m); +} + +static void saradc_disable_interrupt(void) +{ + UINT32 param; + param = (IRQ_SARADC_BIT); + sddev_control(ICU_DEV_NAME, CMD_ICU_INT_DISABLE, ¶m); +} + +static void saradc_gpio_config(void) +{ + UINT32 param; + + switch (saradc_desc->channel) + { + case 1: + { + param = GFUNC_MODE_ADC1; + sddev_control(GPIO_DEV_NAME, CMD_GPIO_ENABLE_SECOND, ¶m); + break; + } + case 2: + { + param = GFUNC_MODE_ADC2; + sddev_control(GPIO_DEV_NAME, CMD_GPIO_ENABLE_SECOND, ¶m); + break; + } + case 3: + { + param = GFUNC_MODE_ADC3; + sddev_control(GPIO_DEV_NAME, CMD_GPIO_ENABLE_SECOND, ¶m); + break; + } +#if ((SOC_BK7231U == CFG_SOC_NAME) || (SOC_BK7221U == CFG_SOC_NAME) || (SOC_BK7231N == CFG_SOC_NAME)) + case 4: { + param = GFUNC_MODE_ADC4; + sddev_control(GPIO_DEV_NAME, CMD_GPIO_ENABLE_SECOND, ¶m); + break; + } + case 5: { + param = GFUNC_MODE_ADC5; + sddev_control(GPIO_DEV_NAME, CMD_GPIO_ENABLE_SECOND, ¶m); + break; + } + case 6: { + param = GFUNC_MODE_ADC6; + sddev_control(GPIO_DEV_NAME, CMD_GPIO_ENABLE_SECOND, ¶m); + break; + } +#endif + default: + break; + } + +} + +static UINT32 saradc_open(UINT32 op_flag) +{ + UINT32 config_value = 0; + UINT32 sat_config_value = 0; + saradc_desc_t *p_saradc_desc; + + p_saradc_desc = (saradc_desc_t*)op_flag; + + if(p_saradc_desc->pData == NULL){ + return SARADC_FAILURE; + } + + if(p_saradc_desc->channel > SARADC_ADC_CHNL_MAX){ + return SARADC_FAILURE; + } + + if(p_saradc_desc->data_buff_size == 0){ + return SARADC_FAILURE; + } + + if (saradc_is_busy != 0) + { + return SARADC_FAILURE; + } + saradc_is_busy = 1; + + saradc_enable_sysctrl(); + saradc_enable_icu_config(); + + saradc_desc = p_saradc_desc; + saradc_desc->has_data = 0; + saradc_desc->all_done = 0; + saradc_desc->current_read_data_cnt = 0; + saradc_desc->current_sample_data_cnt = 0; + + saradc_gpio_config(); + + // clear fifo + config_value = REG_READ(SARADC_ADC_CONFIG); + while((config_value & SARADC_ADC_FIFO_EMPTY) == 0) { + REG_READ(SARADC_ADC_DATA); + REG_READ(SARADC_ADC_DAT_AFTER_STA); + config_value = REG_READ(SARADC_ADC_CONFIG); + } + saradc_int_clr(); + + config_value = ((saradc_desc->mode & SARADC_ADC_MODE_MASK) << SARADC_ADC_MODE_POSI) + | SARADC_ADC_CHNL_EN + | ((saradc_desc->channel & SARADC_ADC_CHNL_MASK) << SARADC_ADC_CHNL_POSI) + | (((saradc_desc->mode>>2)&0x01) << SARADC_ADC_DELAY_CLK_POSI) + | SARADC_ADC_INT_CLR + | ((saradc_desc->pre_div & SARADC_ADC_PRE_DIV_MASK) << SARADC_ADC_PRE_DIV_POSI) + | ((saradc_desc->samp_rate & SARADC_ADC_SAMPLE_RATE_MASK) << SARADC_ADC_SAMPLE_RATE_POSI) + | ((saradc_desc->filter & SARADC_ADC_FILTER_MASK)<< SARADC_ADC_FILTER_POSI); + REG_WRITE(SARADC_ADC_CONFIG, config_value); + +#if (CFG_SOC_NAME == SOC_BK7231N) + if (8 == saradc_desc->channel) + { + sat_config_value = SARADC_ADC_SAT_ENABLE + | ((0x03 & SARADC_ADC_SAT_CTRL_MASK) << SARADC_ADC_SAT_CTRL_POSI); + } + else if (ADC_TEMP_SENSER_CHANNEL == saradc_desc->channel) + { + sat_config_value = SARADC_ADC_SAT_ENABLE + | ((0x01 & SARADC_ADC_SAT_CTRL_MASK) << SARADC_ADC_SAT_CTRL_POSI); + } + else + { + sat_config_value = SARADC_ADC_SAT_ENABLE + | ((0x02 & SARADC_ADC_SAT_CTRL_MASK) << SARADC_ADC_SAT_CTRL_POSI); + } + REG_WRITE(SARADC_ADC_SATURATION_CFG, sat_config_value); + config_value = 1; + saradc_ctrl(SARADC_CMD_SET_BYPASS_CALIB, &config_value); +#elif (CFG_SOC_NAME != SOC_BK7231) + sat_config_value = SARADC_ADC_SAT_ENABLE + | ((0x03 & SARADC_ADC_SAT_CTRL_MASK) << SARADC_ADC_SAT_CTRL_POSI); + REG_WRITE(SARADC_ADC_SATURATION_CFG, sat_config_value); +#endif + + saradc_enable_interrupt(); + + return SARADC_SUCCESS; +} + +static UINT32 saradc_pause() +{ + UINT32 value; + + //saradc_disable_interrupt(); + saradc_disable_sysctrl(); + + value = REG_READ(SARADC_ADC_CONFIG); + value &= ~(SARADC_ADC_CHNL_EN); + value |= SARADC_ADC_INT_CLR; + REG_WRITE(SARADC_ADC_CONFIG, value); + + //saradc_disable_icu_config(); + + // clear fifo + value = REG_READ(SARADC_ADC_CONFIG); + while((value & SARADC_ADC_FIFO_EMPTY) == 0) { + REG_READ(SARADC_ADC_DATA); + REG_READ(SARADC_ADC_DAT_AFTER_STA); + value = REG_READ(SARADC_ADC_CONFIG); + } + + saradc_int_clr(); + return SARADC_SUCCESS; +} + +static UINT32 saradc_resume() +{ + UINT32 value = 0; + + saradc_enable_sysctrl(); + saradc_enable_icu_config(); + + // clear fifo + value = REG_READ(SARADC_ADC_CONFIG); + while((value & SARADC_ADC_FIFO_EMPTY) == 0) { + REG_READ(SARADC_ADC_DATA); + REG_READ(SARADC_ADC_DAT_AFTER_STA); + value = REG_READ(SARADC_ADC_CONFIG); + } + + saradc_int_clr(); + + value = REG_READ(SARADC_ADC_CONFIG); + value &= ~(SARADC_ADC_INT_CLR); + value |= SARADC_ADC_CHNL_EN; + REG_WRITE(SARADC_ADC_CONFIG, value); + + saradc_desc->current_sample_data_cnt = 0; + saradc_enable_interrupt(); + + return SARADC_SUCCESS; +} + +void saradc_disable(void) +{ + UINT32 value; + value = REG_READ(SARADC_ADC_CONFIG); + value &= (~SARADC_ADC_CHNL_EN); + REG_WRITE(SARADC_ADC_CONFIG, value) ; +} + +static UINT32 saradc_close(void) +{ + UINT32 value; + + GLOBAL_INT_DECLARATION(); + + GLOBAL_INT_DISABLE(); + saradc_disable_interrupt(); + saradc_disable_sysctrl(); + + value = REG_READ(SARADC_ADC_CONFIG); + value &= ~(SARADC_ADC_MODE_MASK << SARADC_ADC_MODE_POSI); + value &= ~(SARADC_ADC_CHNL_EN); + value |= SARADC_ADC_INT_CLR; + REG_WRITE(SARADC_ADC_CONFIG, value); + + // clear fifo + value = REG_READ(SARADC_ADC_CONFIG); + while((value & SARADC_ADC_FIFO_EMPTY) == 0) { + REG_READ(SARADC_ADC_DATA); + REG_READ(SARADC_ADC_DAT_AFTER_STA); + value = REG_READ(SARADC_ADC_CONFIG); + } + saradc_int_clr(); + + saradc_disable_icu_config(); + + saradc_is_busy = 0; + GLOBAL_INT_RESTORE(); + + return SARADC_SUCCESS; +} + +static UINT32 saradc_set_mode(UINT8 mode) +{ + UINT32 value; + + if(mode > 3){ + return SARADC_FAILURE; + } + + value = REG_READ(SARADC_ADC_CONFIG); + value &= ~(SARADC_ADC_MODE_MASK << SARADC_ADC_MODE_POSI); + value |= (mode << SARADC_ADC_MODE_POSI); + REG_WRITE(SARADC_ADC_CONFIG, value); + + return SARADC_SUCCESS; +} + +static UINT32 saradc_set_channel(saradc_chan_t *p_chan) +{ + UINT32 value; + + value = REG_READ(SARADC_ADC_CONFIG); + if(p_chan->enable == 0){ + value &= ~SARADC_ADC_CHNL_EN; + }else{ + value &= ~(SARADC_ADC_CHNL_MASK << SARADC_ADC_CHNL_POSI); + value |= (p_chan->channel << SARADC_ADC_CHNL_POSI); + value |= SARADC_ADC_CHNL_EN; + } + REG_WRITE(SARADC_ADC_CONFIG, value); + + return SARADC_SUCCESS; +} + +static UINT32 saradc_set_sample_rate(UINT8 rate) +{ + UINT32 value; + + if(rate > 3){ + return SARADC_FAILURE; + } + + value = REG_READ(SARADC_ADC_CONFIG); + value &= ~(SARADC_ADC_SAMPLE_RATE_MASK << SARADC_ADC_SAMPLE_RATE_POSI); + value |= (rate << SARADC_ADC_SAMPLE_RATE_POSI); + REG_WRITE(SARADC_ADC_CONFIG, value); + + return SARADC_SUCCESS; +} + +static UINT32 saradc_set_waiting_time(UINT8 time) +{ + UINT32 value, mode; + + value = REG_READ(SARADC_ADC_CONFIG); + + mode = value & (SARADC_ADC_MODE_MASK << SARADC_ADC_MODE_POSI); + if(mode == 0 || mode == 3){ + return SARADC_FAILURE; + } + + if(time == 0){ + value &= ~SARADC_ADC_SETTING; + }else{ + value |= SARADC_ADC_SETTING; + } + + REG_WRITE(SARADC_ADC_CONFIG, value); + + return SARADC_SUCCESS; +} + +static UINT32 saradc_set_valid_mode(UINT8 mode) +{ + + return SARADC_SUCCESS; +} + +static void saradc_int_clr(void) +{ + UINT32 value; + + do{ + value = REG_READ(SARADC_ADC_CONFIG); + value |= SARADC_ADC_INT_CLR; + REG_WRITE(SARADC_ADC_CONFIG, value); + }while(REG_READ(SARADC_ADC_CONFIG) & SARADC_ADC_INT_CLR); +} + +static UINT32 saradc_set_clk_rate(UINT8 rate) +{ + UINT32 value; + + if(rate > SARADC_ADC_PRE_DIV_MASK){ + return SARADC_FAILURE; + } + + value = REG_READ(SARADC_ADC_CONFIG); + value &= ~(SARADC_ADC_PRE_DIV_MASK << SARADC_ADC_PRE_DIV_POSI); + value |= (rate << SARADC_ADC_PRE_DIV_POSI); + REG_WRITE(SARADC_ADC_CONFIG, value); + + return SARADC_SUCCESS; +} + +static UINT32 saradc_run_or_stop_adc(UINT8 run_stop) +{ + UINT32 value; + + value = REG_READ(SARADC_ADC_CONFIG); + + if(run_stop) + value |= (SARADC_ADC_CHNL_EN); + else + value &= ~(SARADC_ADC_CHNL_EN); + + REG_WRITE(SARADC_ADC_CONFIG, value); + + return SARADC_SUCCESS; +} + +static UINT32 saradc_set_calibrate_val(saradc_cal_val_t *p_cal) +{ + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + if(SARADC_CALIBRATE_LOW == p_cal->mode) + { + saradc_val.low = p_cal->val; + } + else if(SARADC_CALIBRATE_HIGH == p_cal->mode) + { + saradc_val.high = p_cal->val; + } + else + { + GLOBAL_INT_RESTORE(); + return SARADC_FAILURE; + } + + GLOBAL_INT_RESTORE(); + return SARADC_SUCCESS; +} + +void saradc_config_param_init(saradc_desc_t* adc_config) +{ + memset(adc_config, 0x00, sizeof(saradc_desc_t)); + adc_config->channel = 1; + adc_config->current_read_data_cnt = 0; + adc_config->current_sample_data_cnt = 0; + adc_config->filter = 0; + adc_config->has_data = 0; + adc_config->all_done = 0; + adc_config->mode = (ADC_CONFIG_MODE_CONTINUE << 0) + |(ADC_CONFIG_MODE_4CLK_DELAY << 2) + |(ADC_CONFIG_MODE_SHOULD_OFF); + adc_config->pre_div = 0x10; + adc_config->samp_rate = 0x20; +} + +void saradc_ensure_close(void) +{ + if(saradc_desc->mode & ADC_CONFIG_MODE_SHOULD_OFF) + { + // close + saradc_close(); + } +} + +float saradc_calculate(UINT16 adc_val) +{ + float practic_voltage; +#if (CFG_SOC_NAME == SOC_BK7231N) + /* (adc_val - low) / (practic_voltage - 1Volt) = (high - low) / 1Volt */ + /* practic_voltage = (adc_val - low) / (high - low) + 1Volt */ + practic_voltage = (float)(adc_val - saradc_val.low); + practic_voltage = (practic_voltage / (float)(saradc_val.high - saradc_val.low)) + 1; +#else + practic_voltage = ((adc_val - saradc_val.low) * 1.8); + practic_voltage = (practic_voltage / (saradc_val.high - saradc_val.low)) + 0.2; +#endif + return practic_voltage; +} + + +static UINT32 saradc_ctrl(UINT32 cmd, void *param) +{ + UINT32 ret = SARADC_SUCCESS; +#if (CFG_SOC_NAME == SOC_BK7231N) + UINT32 value; +#endif + + peri_busy_count_add(); + + switch(cmd){ + case SARADC_CMD_SET_MODE: + ret = saradc_set_mode(*(UINT8 *)param); + break; + case SARADC_CMD_SET_CHANNEL: + ret = saradc_set_channel((saradc_chan_t *)param); + break; + case SARADC_CMD_SET_SAMPLE_RATE: + ret = saradc_set_sample_rate(*(UINT8 *)param); + break; + case SARADC_CMD_SET_WAITING_TIME: + ret = saradc_set_waiting_time(*(UINT8 *)param); + break; + case SARADC_CMD_SET_VALID_MODE: + ret = saradc_set_valid_mode(*(UINT8 *)param); + break; + case SARADC_CMD_CLEAR_INT: + saradc_int_clr(); + break; + case SARADC_CMD_SET_CLK_RATE: + ret = saradc_set_clk_rate(*(UINT8 *)param); + break; + case SARADC_CMD_RUN_OR_STOP_ADC: + ret = saradc_run_or_stop_adc(*(UINT8 *)param); + break; + case SARADC_CMD_SET_CAL_VAL: + ret = saradc_set_calibrate_val((saradc_cal_val_t *)param); + break; + case SARADC_CMD_PAUSE: + ret = saradc_pause(); + break; + case SARADC_CMD_RESUME: + ret = saradc_resume(); + break; +#if (CFG_SOC_NAME == SOC_BK7231N) + case SARADC_CMD_SET_BYPASS_CALIB: + value = REG_READ(SARADC_ADC_CTRL_CFG); + if (*(UINT32 *)param) + { + /* set */ + value |= SARADC_ADC_BYPASS_CALIB; + } + else + { + /* clear */ + value &= ~SARADC_ADC_BYPASS_CALIB; + } + REG_WRITE(SARADC_ADC_CTRL_CFG, value); + break; + case SARADC_CMD_SET_SAT_CTRL: + value = REG_READ(SARADC_ADC_SATURATION_CFG); + /* clear with mask */ + value &= ~(SARADC_ADC_SAT_CTRL_MASK << SARADC_ADC_SAT_CTRL_POSI); + /* set with param */ + value |= ((*(UINT32 *)param & SARADC_ADC_SAT_CTRL_MASK) << SARADC_ADC_SAT_CTRL_POSI); + REG_WRITE(SARADC_ADC_SATURATION_CFG, value); + break; +#endif + default: + ret = SARADC_FAILURE; + break; + } + + peri_busy_count_dec(); + + return ret; +} + +void saradc_isr(void) +{ + UINT32 value; + + value = REG_READ(SARADC_ADC_CONFIG); + while((value & SARADC_ADC_FIFO_EMPTY) == 0) + { + UINT16 dac_val; + + #if (CFG_SOC_NAME == SOC_BK7231) + dac_val = REG_READ(SARADC_ADC_DATA)&0x03FF; + #else + dac_val = REG_READ(SARADC_ADC_DAT_AFTER_STA)&0xFFFF; + #endif // (CFG_SOC_NAME == SOC_BK7231) + + if (saradc_desc->current_sample_data_cnt < saradc_desc->data_buff_size) + { + saradc_desc->pData[saradc_desc->current_sample_data_cnt++] = dac_val; + saradc_desc->has_data = 1; + + if ((saradc_desc->mode & 0x03) == 0x01) + { + value = REG_READ(SARADC_ADC_CONFIG); + value |= (1 << SARADC_ADC_MODE_POSI) | SARADC_ADC_CHNL_EN; + REG_WRITE(SARADC_ADC_CONFIG, value) ; + } + if(saradc_desc->current_sample_data_cnt == saradc_desc->data_buff_size) + { +#if (CFG_SOC_NAME == SOC_BK7231N) + saradc_pause(); +#endif + } + } + else + { + break; + } + + value = REG_READ(SARADC_ADC_CONFIG); + } + + if (saradc_desc->current_sample_data_cnt >= saradc_desc->data_buff_size) + { + saradc_desc->all_done = 1; + + if (saradc_desc->p_Int_Handler != NULL) + { + (void)saradc_desc->p_Int_Handler(); + } + } + + saradc_int_clr(); +} + diff --git a/beken_os/beken378/driver/saradc/saradc.h b/beken_os/beken378/driver/saradc/saradc.h new file mode 100755 index 0000000..7f6f180 --- /dev/null +++ b/beken_os/beken378/driver/saradc/saradc.h @@ -0,0 +1,113 @@ +#ifndef _SARADC_H_ +#define _SARADC_H_ + +#if (CFG_SOC_NAME == SOC_BK7231) +#define SARADC_BASE (0x00802C00) +#define SARADC_ADC_CONFIG (SARADC_BASE + 0 * 4) +#define SARADC_ADC_MODE_POSI (0) +#define SARADC_ADC_MODE_MASK (0x03) +#define SARADC_ADC_CHNL_EN (0x01UL << 2) +#define SARADC_ADC_CHNL_POSI (3) +#define SARADC_ADC_CHNL_MAX (7) +#define SARADC_ADC_CHNL_MASK (0x07) +#define SARADC_ADC_FIFO_FULL (0x01UL << 29) +#define SARADC_ADC_FIFO_EMPTY (0x01UL << 28) +#define SARADC_ADC_BUSY (0x01UL << 27) +#define SARADC_ADC_SAMPLE_RATE_POSI (16) +#define SARADC_ADC_SAMPLE_RATE_MASK (0x00FF) +#define SARADC_ADC_DELAY_CLK_POSI (6) +#define SARADC_ADC_SETTING (0x01UL << 6) +#define SARADC_ADC_INT_CLR (0x01UL << 7) +#define SARADC_ADC_PRE_DIV_POSI (8) +#define SARADC_ADC_PRE_DIV_MASK (0x00FF) +#define SARADC_ADC_FILTER_POSI (24) +#define SARADC_ADC_FILTER_MASK (0x07) + +#define SARADC_ADC_DATA (SARADC_BASE + 1 * 4) + +#elif (CFG_SOC_NAME == SOC_BK7231N) +#define SARADC_BASE (0x00802C00) +#define SARADC_ADC_CONFIG (SARADC_BASE + 0 * 4) +#define SARADC_ADC_MODE_POSI (0) +#define SARADC_ADC_MODE_MASK (0x03) +#define SARADC_ADC_CHNL_EN (0x01UL << 2) +#define SARADC_ADC_CHNL_POSI (3) +#define SARADC_ADC_CHNL_MAX (12) +#define SARADC_ADC_CHNL_MASK (0x0F) +#define SARADC_ADC_DELAY_CLK_POSI (7) +#define SARADC_ADC_SETTING (0x01UL << 7) +#define SARADC_ADC_INT_CLR (0x01UL << 8) +#define SARADC_ADC_PRE_DIV_POSI (9) +#define SARADC_ADC_PRE_DIV_MASK (0x3F) +#define SARADC_ADC_32M_MODE (0x01UL << 15) +#define SARADC_ADC_SAMPLE_RATE_POSI (16) +#define SARADC_ADC_SAMPLE_RATE_MASK (0x3F) +#define SARADC_ADC_FILTER_POSI (22) +#define SARADC_ADC_FILTER_MASK (0x7F) +#define SARADC_ADC_BUSY (0x01UL << 29) +#define SARADC_ADC_FIFO_EMPTY (0x01UL << 30) +#define SARADC_ADC_FIFO_FULL (0x01UL << 31) + +#define SARADC_ADC_DATA (SARADC_BASE + 1 * 4) + +#define SARADC_ADC_CTRL_CFG (SARADC_BASE + 2 * 4) +#define SARADC_ADC_BYPASS_CALIB (0x01UL << 10) +#define SARADC_ADC_STEADY_CTRL_POSI (5) +#define SARADC_ADC_STEADY_CTRL_MASK (0x7) +#define SARADC_ADC_ALMOST_CFG_POSI (0) +#define SARADC_ADC_ALMOST_CFG_MASK (0x1F) + +#define SARADC_ADC_SATURATION_CFG (SARADC_BASE + 3 * 4) +#define SARADC_ADC_SAT_CTRL_POSI (0) +#define SARADC_ADC_SAT_CTRL_MASK (0x3) +#define SARADC_ADC_SAT_ENABLE (0x01UL << 2) +#define SARADC_ADC_SAT_OVERFLOW (0x01UL << 3) + +#define SARADC_ADC_DAT_AFTER_STA (SARADC_BASE + 4 * 4) +#else +#define SARADC_BASE (0x00802C00) +#define SARADC_ADC_CONFIG (SARADC_BASE + 0 * 4) +#define SARADC_ADC_MODE_POSI (0) +#define SARADC_ADC_MODE_MASK (0x03) +#define SARADC_ADC_CHNL_EN (0x01UL << 2) +#define SARADC_ADC_CHNL_POSI (3) +#define SARADC_ADC_CHNL_MAX (12) +#define SARADC_ADC_CHNL_MASK (0x0F) +#define SARADC_ADC_DELAY_CLK_POSI (7) +#define SARADC_ADC_SETTING (0x01UL << 7) +#define SARADC_ADC_INT_CLR (0x01UL << 8) +#define SARADC_ADC_PRE_DIV_POSI (9) +#define SARADC_ADC_PRE_DIV_MASK (0x3F) +#define SARADC_ADC_32M_MODE (0x01UL << 15) +#define SARADC_ADC_SAMPLE_RATE_POSI (16) +#define SARADC_ADC_SAMPLE_RATE_MASK (0x3F) +#define SARADC_ADC_FILTER_POSI (22) +#define SARADC_ADC_FILTER_MASK (0x7F) +#define SARADC_ADC_BUSY (0x01UL << 29) +#define SARADC_ADC_FIFO_EMPTY (0x01UL << 30) +#define SARADC_ADC_FIFO_FULL (0x01UL << 31) + +#define SARADC_ADC_DATA (SARADC_BASE + 1 * 4) + +#define SARADC_ADC_CTRL_CFG (SARADC_BASE + 2 * 4) +#define SARADC_ADC_STEADY_CTRL_POSI (5) +#define SARADC_ADC_STEADY_CTRL_MASK (0x7) +#define SARADC_ADC_ALMOST_CFG_POSI (0) +#define SARADC_ADC_ALMOST_CFG_MASK (0x1F) + +#define SARADC_ADC_SATURATION_CFG (SARADC_BASE + 3 * 4) +#define SARADC_ADC_SAT_CTRL_POSI (0) +#define SARADC_ADC_SAT_CTRL_MASK (0x3) +#define SARADC_ADC_SAT_ENABLE (0x01UL << 2) +#define SARADC_ADC_SAT_OVERFLOW (0x01UL << 3) + +#define SARADC_ADC_DAT_AFTER_STA (SARADC_BASE + 4 * 4) +#endif + +/******************************************************************************* +* Function Declarations +*******************************************************************************/ +static UINT32 saradc_open(UINT32 op_flag); +static UINT32 saradc_close(void); +static UINT32 saradc_ctrl(UINT32 cmd, void *param); +#endif //_SARADC_H_ diff --git a/beken_os/beken378/driver/sdcard/sdcard.c b/beken_os/beken378/driver/sdcard/sdcard.c new file mode 100755 index 0000000..f347fe8 --- /dev/null +++ b/beken_os/beken378/driver/sdcard/sdcard.c @@ -0,0 +1,1168 @@ +#include "include.h" + +#include "sys_rtos.h" + +#if CFG_USE_SDCARD_HOST +#include "sdio_driver.h" +#include "rtos_pub.h" + +#include "sdcard.h" +#include "sdcard_pub.h" + +#include "drv_model_pub.h" +#include "sys_ctrl_pub.h" +#include "mem_pub.h" +#include "arch.h" +#include "arm_arch.h" +#include "gpio_pub.h" +#include "mcu_ps_pub.h" +#include "target_util_pub.h" + +/* Standard sd commands ( ) type argument response */ +#define GO_IDLE_STATE 0 /* bc */ +#define ALL_SEND_CID 2 +#define SEND_RELATIVE_ADDR 3 /* ac [31:16] RCA R6 */ +#define IO_SEND_OP_COND 5 /* ac R4 */ +#define SWITCH_FUNC 6 +#define SELECT_CARD 7 /* ac [31:16] RCA R7 */ +#define SEND_IF_COND 8 /* adtc R1 */ +#define SEND_CSD 9 +#define SEND_STATUS 13 +#define READ_SINGLE_BLOCK 17 +#define WRITE_BLOCK 24 +#define SD_APP_OP_COND 41 +#define IO_RW_DIRECT 52 /* ac [31:0] See below R5 */ +#define IO_RW_EXTENDED 53 /* adtc [31:0] See below R5 */ +#define APP_CMD 55 + +#define R5_COM_CRC_ERROR (1 << 15) /* er, b */ +#define R5_ILLEGAL_COMMAND (1 << 14) /* er, b */ +#define R5_ERROR (1 << 11) /* erx, c */ +#define R5_FUNCTION_NUMBER (1 << 9) /* er, c */ +#define R5_OUT_OF_RANGE (1 << 8) /* er, c */ +#define R5_STATUS(x) (x & 0xCB00) +#define R5_IO_CURRENT_STATE(x) ((x & 0x3000) >> 12) /* s, b */ + +/*STM32 register bit define*/ +#define SDIO_ICR_MASK 0x5FF +#define SDIO_STATIC_FLAGS ((UINT32)0x000005FF) +#define SDIO_FIFO_ADDRESS ((UINT32)0x40018080) + +#define OCR_MSK_BUSY 0x80000000 // Busy flag +#define OCR_MSK_HC 0x40000000 // High Capacity flag +#define OCR_MSK_VOLTAGE_ALL 0x00FF8000 // All Voltage flag + +#define SD_DEFAULT_OCR (OCR_MSK_VOLTAGE_ALL|OCR_MSK_HC) + +#define SD_MAX_VOLT_TRIAL ((INT32)0x0000FFFF) + +#define SD_CLK_PIN 34 +#define REG_A2_CONFIG ((0x0802800) + 50*4) + + +typedef void (*SD_DETECT_FUN)(void); + +typedef enum +{ + SD_CARD_IDLE = ((UINT32)0), + SD_CARD_READY = ((UINT32)1), + SD_CARD_IDENTIFICATION = ((UINT32)2), + SD_CARD_STANDBY = ((UINT32)3), + SD_CARD_TRANSFER = ((UINT32)4), + SD_CARD_SENDING = ((UINT32)5), + SD_CARD_RECEIVING = ((UINT32)6), + SD_CARD_PROGRAMMING = ((UINT32)7), + SD_CARD_DISCONNECTED = ((UINT32)8), + SD_CARD_ERROR = ((UINT32)0xff) +} SDCardState; + +typedef struct sdio_command +{ + UINT32 index; + UINT32 arg; + UINT32 flags; /* expected response type */ + UINT32 timeout; + UINT32 resp[4]; + void *data; /* data segment associated with cmd */ + SDIO_Error err; /* command error */ +} SDIO_CMD_S, *SDIO_CMD_PTR; + +typedef struct _sdcard_ +{ + UINT32 total_block; + UINT16 block_size; + UINT16 card_rca; + UINT16 init_flag; + UINT16 Addr_shift_bit; + SD_DETECT_FUN detect_func; +} SDCARD_S, *SDCARD_PTR; + +static SDCARD_S sdcard; +static DD_OPERATIONS sdcard_op = +{ + sdcard_open, + sdcard_close, + sdcard_read, + sdcard_write, + sdcard_ctrl +}; + + +#define SD_DEBOUNCE_COUNT 10 + +static uint8 sd_online = SD_CARD_OFFLINE; +static uint32 sd_clk_pin = SD_CLK_PIN; +static uint32 sd_cd_pin = SD_DETECT_DEFAULT_GPIO; + +static uint16 NoneedInitflag = 0; +uint8 SD_det_gpio_flag = 1; +static uint16 Sd_MMC_flag = 0; +static uint16 cnt_online = 0; +static beken_timer_t sd_cd_timer = {0}; + +/******************************************************************************/ +/***************************** public function ********************************/ +/******************************************************************************/ +static void sdio_hw_init(void) +{ + /* config sdcard gpio */ + sdio_gpio_config(); + + /* reset sdcard moudle register */ + sdio_register_reset(); + + /* set sdcard low clk */ + sdio_set_low_clk(); + + /* set sdcard clk enable*/ + sdio_clk_config(1); + +} + +static void sdio_send_cmd(SDIO_CMD_PTR sdio_cmd_ptr) +{ + sdio_sendcmd_function(sdio_cmd_ptr->index, + sdio_cmd_ptr->flags, + sdio_cmd_ptr->timeout, + (void *)sdio_cmd_ptr->arg); +} + +static void sdio_hw_uninit(void) +{ + UINT32 param; + + sdio_clk_config(0); + + if(!SD_det_gpio_flag) + { + param = GPIO_CFG_PARAM(sd_clk_pin, GMODE_INPUT_PULLUP); + sddev_control(GPIO_DEV_NAME, CMD_GPIO_CFG, ¶m); + } +} + +static void sdio_sw_init(void) +{ + os_memset((void *)&sdcard, 0, sizeof(SDCARD_S)); +} + +/******************************************************************************/ +/***************************** sdcard function ********************************/ +/******************************************************************************/ +/* GO_IDLE_STATE */ +static SDIO_Error sdcard_cmd0_process(void) +{ + SDIO_CMD_S cmd; + + cmd.index = GO_IDLE_STATE; + cmd.arg = 0; + cmd.flags = SD_CMD_NORESP; + cmd.timeout = DEF_LOW_SPEED_CMD_TIMEOUT;//DEF_CMD_TIME_OUT; + sdio_send_cmd(&cmd); + cmd.err = sdio_wait_cmd_response(cmd.index); + return cmd.err; +} + +static SDIO_Error sdcard_cmd1_process(void) +{ + SDIO_CMD_S cmd; + uint32 response, reg; + + cmd.index = 1; + cmd.arg = 0x40ff8000; + cmd.flags = SD_CMD_SHORT; + cmd.timeout = 0x900;//DEF_CMD_TIME_OUT; +cmd1_loop: + sdio_send_cmd(&cmd); + cmd.err = sdio_wait_cmd_response(cmd.index); + if(cmd.err == SD_OK) + { + sdio_get_cmdresponse_argument(0, &response); + if(!(response & OCR_MSK_VOLTAGE_ALL)) + cmd.err = SD_ERR_CMD41_CNT; + if(!(response & OCR_MSK_BUSY)) + goto cmd1_loop; + if(response & OCR_MSK_HC) + sdcard.Addr_shift_bit = 0; + else + sdcard.Addr_shift_bit = 9;//λ + } + reg = REG_READ(REG_SDCARD_FIFO_THRESHOLD); + reg |= 20; + REG_WRITE(REG_SDCARD_FIFO_THRESHOLD, reg); + + return cmd.err; +} + +static SDIO_Error sdcard_mmc_cmd8_process(void) +{ + int i, ret; + SDIO_CMD_S cmd; + uint32 response, reg; + uint32 tmp; + uint8 *tmpptr; + + tmpptr = (uint8 *)os_malloc(512); + if(tmpptr == NULL) + return 1; + os_memset(tmpptr, 0, 512); + + cmd.index = SEND_IF_COND; + cmd.arg = 0; + cmd.flags = SD_CMD_SHORT; + cmd.timeout = 0x90000; // DEF_CMD_TIME_OUT; + sdio_send_cmd(&cmd); + + REG_WRITE(REG_SDCARD_FIFO_THRESHOLD, (1 << 20));// reset first + REG_WRITE(REG_SDCARD_FIFO_THRESHOLD, 0x3ffff);// set fifo later + driver_sdcard_recv_data_start(DEF_CMD_TIME_OUT); + + tmp = 0; + ret = wait_Receive_Data(); + if(ret == SD_OK) + { + for (i = 0; i < 128; i++) + { + while(!(REG_READ(REG_SDCARD_FIFO_THRESHOLD) & (0x1 << 18))) + { + tmp++; + if(tmp > 0x20) + break; + } + + *((uint32 *)tmpptr + i) = REG_READ(REG_SDCARD_RD_DATA_ADDR); + } + sdcard.total_block = tmpptr[212] | (tmpptr[213] << 8) | (tmpptr[214] << 16) | (tmpptr[215] << 24); + } + + os_free(tmpptr); + + return ret; +} + + +static SDIO_Error sdcard_cmd8_process(void) +{ + SDIO_CMD_S cmd; + UINT8 voltage_accpet, check_pattern; + + cmd.index = SEND_IF_COND; + cmd.arg = 0x1AA; + cmd.flags = SD_CMD_SHORT; + cmd.timeout = DEF_LOW_SPEED_CMD_TIMEOUT; // DEF_CMD_TIME_OUT; + + sdio_send_cmd(&cmd); + cmd.err = sdio_wait_cmd_response(cmd.index); + + if(cmd.err == SD_CMD_RSP_TIMEOUT) + { + SDCARD_WARN("cmd8 noresp, voltage mismatch or Ver1.X SD or not SD\r\n"); + return SD_CMD_RSP_TIMEOUT; + } + else if(cmd.err == SD_CMD_CRC_FAIL) + { + SDCARD_WARN("cmd8 cmdcrc err\r\n"); + return SD_CMD_CRC_FAIL; + } + + SDCARD_PRT("found a Ver2.00 or later SDCard\r\n"); + + // check Valid Response, + // R7-[11:8]:voltage accepted, [7:0] echo-back of check pattern + sdio_get_cmdresponse_argument(0, &cmd.resp[0]); + + check_pattern = cmd.resp[0] & 0xff; + voltage_accpet = cmd.resp[0] >> 8 & 0xf; + + if(voltage_accpet == 0x1 && check_pattern == 0xaa) + { + SDCARD_PRT("support 2.7~3.6V\r\n"); + return SD_OK; + } + else + { + SDCARD_WARN("unsupport voltage\r\n"); + return SD_INVALID_VOLTRANGE; + } + return SD_OK; +} + +/*Send host capacity support information(HCS) and asks + the card to send its OCR in the response on CMD line*/ +static SDIO_Error sdcard_acmd41_process(UINT32 ocr) +{ + SDIO_CMD_S cmd; + + + cmd.index = APP_CMD; + cmd.arg = 0; + cmd.flags = SD_CMD_SHORT; + cmd.timeout = DEF_LOW_SPEED_CMD_TIMEOUT; // DEF_CMD_TIME_OUT; + sdio_send_cmd(&cmd); + cmd.err = sdio_wait_cmd_response(cmd.index); + if(cmd.err != SD_OK) + { + SDCARD_WARN("send cmd55 err:%d\r\n", cmd.err); + return cmd.err; + } + + + cmd.index = SD_APP_OP_COND; + cmd.arg = ocr; + cmd.flags = SD_CMD_SHORT; + cmd.timeout = DEF_LOW_SPEED_CMD_TIMEOUT;//DEF_CMD_TIME_OUT; + sdio_send_cmd(&cmd); + cmd.err = sdio_wait_cmd_response(cmd.index); + // why cmd41 always return crc fail? + if(cmd.err != SD_OK && cmd.err != SD_CMD_CRC_FAIL) + { + SDCARD_WARN("send cmd41 err:%d\r\n", cmd.err); + return cmd.err; + } + + return SD_OK; +} + +/*ask the CID number on the CMD line*/ +// Manufacturer ID MID 8 [127:120] +// OEM/Application ID OID 16 [119:104] +// Product name PNM 40 [103:64] +// Product revision PRV 8 [63:56] +// Product serial number PSN 32 [55:24] +// reserved -- 4 [23:20] +// Manufacturing date MDT 12 [19:8] +static SDIO_Error sdcard_cmd2_process(void) +{ + SDIO_CMD_S cmd; + + cmd.index = ALL_SEND_CID; + cmd.arg = 0; + cmd.flags = SD_CMD_LONG; + cmd.timeout = DEF_LOW_SPEED_CMD_TIMEOUT; // DEF_CMD_TIME_OUT; + sdio_send_cmd(&cmd); + cmd.err = sdio_wait_cmd_response(cmd.index); + + // dismiss the CID info + + return cmd.err; +} + +static SDIO_Error sdcard_mmc_cmd3_process(void) +{ + SDIO_CMD_S cmd; + + cmd.index = SEND_RELATIVE_ADDR; +#if 0 + cmd.arg = 0; +#else + sdcard.card_rca = 1; + cmd.arg = (sdcard.card_rca << 16); +#endif + cmd.flags = SD_CMD_SHORT; + cmd.timeout = DEF_LOW_SPEED_CMD_TIMEOUT;//DEF_CMD_TIME_OUT; + + sdio_send_cmd(&cmd); + cmd.err = sdio_wait_cmd_response(cmd.index); + + if(cmd.err == SD_CMD_RSP_TIMEOUT) + { + SDCARD_WARN("mmc cmd3 noresp \r\n"); + return SD_CMD_RSP_TIMEOUT; + } + else if(cmd.err == SD_CMD_CRC_FAIL) + { + SDCARD_WARN("mmc cmd3 cmdcrc err\r\n"); + return SD_CMD_CRC_FAIL; + } + +#if 0 + sdio_get_cmdresponse_argument(0, &cmd.resp[0]); + sdcard.card_rca = (UINT16) (cmd.resp[0] >> 16); +#endif + SDCARD_PRT("mmc cmd3 is ok, card rca:0x%x\r\n", sdcard.card_rca); + return SD_OK; +} + +/*ask the card to publish a new RCA*/ +static SDIO_Error sdcard_cmd3_process(void) +{ + SDIO_CMD_S cmd; + + cmd.index = SEND_RELATIVE_ADDR; + cmd.arg = 0; + cmd.flags = SD_CMD_SHORT; + cmd.timeout = DEF_LOW_SPEED_CMD_TIMEOUT;//DEF_CMD_TIME_OUT; + + sdio_send_cmd(&cmd); + cmd.err = sdio_wait_cmd_response(cmd.index); + + if(cmd.err == SD_CMD_RSP_TIMEOUT) + { + SDCARD_WARN("cmd3 noresp \r\n"); + return SD_CMD_RSP_TIMEOUT; + } + else if(cmd.err == SD_CMD_CRC_FAIL) + { + SDCARD_WARN("cmd3 cmdcrc err\r\n"); + return SD_CMD_CRC_FAIL; + } + + sdio_get_cmdresponse_argument(0, &cmd.resp[0]); + sdcard.card_rca = (UINT16) (cmd.resp[0] >> 16); + SDCARD_PRT("cmd3 is ok, card rca:0x%x\r\n", sdcard.card_rca); + return SD_OK; +} + +#define SD_CARD 0 +#define MMC_CARD 1 +/*get CSD Register content*/ +static SDIO_Error sdcard_cmd9_process(uint8 card_type) +{ + SDIO_CMD_S cmd; + int mult, csize; + + cmd.index = SEND_CSD; + cmd.arg = (UINT32)(sdcard.card_rca << 16); + cmd.flags = SD_CMD_LONG; + cmd.timeout = DEF_HIGH_SPEED_CMD_TIMEOUT;//DEF_CMD_TIME_OUT; + + sdio_send_cmd(&cmd); + cmd.err = sdio_wait_cmd_response(cmd.index); + if(cmd.err != SD_OK) + { + return cmd.err; + } + + sdio_get_cmdresponse_argument(0, &cmd.resp[0]); + sdio_get_cmdresponse_argument(1, &cmd.resp[1]); + sdio_get_cmdresponse_argument(2, &cmd.resp[2]); + + sdcard.block_size = 1 << ((cmd.resp[1] >> 16) & 0xf); + //os_printf("arg:%x %x %x %x size:%x\r\n", cmd.resp[0], + // cmd.resp[1], cmd.resp[2], cmd.resp[3], sdcard.block_size); + + if(card_type == SD_CARD) + { + + if((cmd.resp[0] >> 30) & 0x3 == 0) + { + csize = (((cmd.resp[1] & 0x3FF ) << 2) | ((cmd.resp[2] >> 30 ) & 0x3)); + mult = ( cmd.resp[2] >> 15 ) & 0x7; + + sdcard.total_block = (csize + 1 ) * ( 1 << (mult + 2 ) ); + sdcard.total_block *= (sdcard.block_size >> 9); + } + else + { + csize = (((cmd.resp[1] & 0x3F ) << 16) | ((cmd.resp[2] >> 16 ) & 0xFFFF)); + sdcard.total_block = (csize + 1) * 1024; + } + + os_printf("size:%x total_block:%x\r\n", sdcard.block_size, sdcard.total_block); + } + else + { + if(sdcard.Addr_shift_bit != 0) + { + csize = (((cmd.resp[1] & 0x3FF ) << 2) + | ((cmd.resp[2] >> 30 ) & 0x3)); + mult = ( cmd.resp[2] >> 15 ) & 0x7; + + sdcard.total_block = (csize + 1 ) * ( 1 << (mult + 2 ) ); + sdcard.total_block *= (sdcard.block_size >> 9); + } + else + { + sdcard.total_block = 0; + } + } + + sdcard.block_size = SD_DEFAULT_BLOCK_SIZE; + SDCARD_PRT("Bsize:%x;Total_block:%x\r\n", sdcard.block_size, sdcard.total_block); + ASSERT_ERR(sdcard.block_size == SD_DEFAULT_BLOCK_SIZE); + + return SD_OK; +} + + +/*select/deselect card*/ +static SDIO_Error sdcard_cmd7_process(void) +{ + SDIO_CMD_S cmd; + + cmd.index = SELECT_CARD; + cmd.arg = (UINT32)(sdcard.card_rca << 16); + cmd.flags = SD_CMD_SHORT; + cmd.timeout = DEF_HIGH_SPEED_CMD_TIMEOUT;// DEF_CMD_TIME_OUT; + + sdio_send_cmd(&cmd); + cmd.err = sdio_wait_cmd_response(cmd.index); + return cmd.err; +} + +/*set bus width*/ +static SDIO_Error sdcard_acmd6_process(void) +{ + SDIO_CMD_S cmd; + cmd.index = APP_CMD; + cmd.arg = (UINT32)(sdcard.card_rca << 16); + cmd.flags = SD_CMD_SHORT; + cmd.timeout = DEF_HIGH_SPEED_CMD_TIMEOUT;// DEF_CMD_TIME_OUT; + sdio_send_cmd(&cmd); + cmd.err = sdio_wait_cmd_response(cmd.index); + if(cmd.err != SD_OK) + return cmd.err; + + cmd.index = SWITCH_FUNC; +#ifdef CONFIG_SDCARD_BUSWIDTH_4LINE + cmd.arg = 2; +#else + cmd.arg = 0; +#endif + cmd.flags = SD_CMD_SHORT; + cmd.timeout = DEF_HIGH_SPEED_CMD_TIMEOUT;//DEF_CMD_TIME_OUT; + + sdio_send_cmd(&cmd); + cmd.err = sdio_wait_cmd_response(cmd.index); + + return cmd.err; +} + +static SDIO_Error sdcard_cmd18_process(uint32 addr) +{ + SDIO_CMD_S cmd; + + cmd.index = 18; + cmd.arg = addr; + cmd.flags = SD_CMD_SHORT; + cmd.timeout = 0x90000; + sdio_send_cmd(&cmd); + cmd.err = sdio_wait_cmd_response(cmd.index); + return cmd.err; +} +static SDIO_Error sdcard_cmd12_process(uint32 addr) +{ + SDIO_CMD_S cmd; + + cmd.index = 12; + cmd.arg = addr; + cmd.flags = SD_CMD_SHORT; + cmd.timeout = DEF_CMD_TIME_OUT; + sdio_send_cmd(&cmd); + cmd.err = sdio_wait_cmd_response(cmd.index); + return cmd.err; +} +static SDIO_Error sdcard_cmd17_process(uint32 addr) +{ + SDIO_CMD_S cmd; + + cmd.index = 17; + cmd.arg = addr; + cmd.flags = SD_CMD_SHORT; + cmd.timeout = 0x90000; + sdio_send_cmd(&cmd); + cmd.err = sdio_wait_cmd_response(cmd.index); + return cmd.err; +} + + +SDIO_Error sdcard_initialize(void) +{ + int i; + SDIO_Error err = SD_OK; + sdio_sw_init(); + vTaskDelay(20); + sdio_hw_init(); + vTaskDelay(30); + // rest card + err = sdcard_cmd0_process(); + if(err != SD_OK) + { + SDCARD_FATAL("send cmd0 err\r\n"); + goto err_return; + } + vTaskDelay(5); + + vTaskDelay(50); + err = sdcard_cmd1_process(); + os_printf("cmd 1:%x \r\n", err); + if(err == SD_OK) + { + goto MMC_init; + } + vTaskDelay(5); + + + // check support voltage + err = sdcard_cmd8_process(); + if(err != SD_OK && err != SD_CMD_RSP_TIMEOUT ) + { + SDCARD_FATAL("send cmd8 err\r\n"); + goto err_return; + } + + if(err == SD_OK) + { + int retry_time = SD_MAX_VOLT_TRIAL; + UINT32 resp0; + while(retry_time) + { + err = sdcard_acmd41_process(SD_DEFAULT_OCR); + if(err != SD_OK) + { + SDCARD_FATAL("send cmd55&cmd41 err:%d, quite loop\r\n", err); + goto err_return; + } + sdio_get_cmdresponse_argument(0, &resp0); + if(resp0 & OCR_MSK_BUSY) + { + if( resp0 & OCR_MSK_HC ) + sdcard.Addr_shift_bit = 0; + else + sdcard.Addr_shift_bit = 9; + break; + } + + vTaskDelay(2); + retry_time--; + } + if(!retry_time) + { + SDCARD_FATAL("send cmd55&cmd41 retry time out\r\n"); + return SD_INVALID_VOLTRANGE; + } + + SDCARD_PRT("send cmd55&cmd41 complete, card is ready\r\n"); + + if(resp0 & OCR_MSK_HC) + { + SDCARD_PRT("High Capacity SD Memory Card\r\n"); + } + else + { + SDCARD_PRT("Standard Capacity SD Memory Card\r\n"); + } + } + else if(err == SD_CMD_RSP_TIMEOUT) + { + int retry_time = SD_MAX_VOLT_TRIAL; + UINT32 resp0; + while(retry_time) + { + err = sdcard_acmd41_process(OCR_MSK_VOLTAGE_ALL); + if(err != SD_OK) + { + SDCARD_FATAL("send cmd55&cmd41 err, quite loop\r\n"); + goto err_return; + } + sdio_get_cmdresponse_argument(0, &resp0); + if(resp0 & OCR_MSK_BUSY) + break; + vTaskDelay(2); + retry_time--; + } + if(!retry_time) + { + SDCARD_FATAL("send cmd55&cmd41 retry time out, maybe a MMC card\r\n"); + err = SD_ERROR; + goto err_return; + } + SDCARD_PRT("send cmd55&cmd41 complete, SD V1.X card is ready\r\n"); + } + vTaskDelay(2); + // get CID, return R2 + err = sdcard_cmd2_process(); + if(err != SD_OK) + { + SDCARD_FATAL("send cmd2 err:%d\r\n", err); + goto err_return; + } + vTaskDelay(2); + // get RCA, + err = sdcard_cmd3_process(); + if(err != SD_OK) + { + SDCARD_FATAL("send cmd3 err:%d\r\n", err); + goto err_return; + } + + // change to high speed clk + sdio_set_high_clk(); + vTaskDelay(2); + // get CSD + err = sdcard_cmd9_process(SD_CARD); + if(err != SD_OK) + { + SDCARD_FATAL("send cmd9 err:%d\r\n", err); + goto err_return; + } + vTaskDelay(2); + // select card + err = sdcard_cmd7_process(); + if(err != SD_OK) + { + SDCARD_FATAL("send cmd7 err:%d\r\n", err); + goto err_return; + } + vTaskDelay(2); + // change bus width, for high speed + err = sdcard_acmd6_process(); + if(err != SD_OK) + { + SDCARD_FATAL("send acmd6 err:%d\r\n", err); + goto err_return; + } + + Sd_MMC_flag = SD_CARD; + err = SD_OK; + SDCARD_PRT("sdcard initialize is done\r\n"); + goto right_return; + +MMC_init: + err = sdcard_cmd2_process(); + os_printf("cmd 2 :%x\r\n", err); + if(err != SD_OK) + goto err_return; + err = sdcard_mmc_cmd3_process(); + os_printf("cmd 3 :%x\r\n", err); + sdio_set_high_clk(); + err = sdcard_cmd9_process(MMC_CARD); + os_printf("cmd 9 :%x\r\n", err); + if(sdcard.Addr_shift_bit == 0) + { + err = sdcard_mmc_cmd8_process(); + os_printf("cmd 8 :%x\r\n", err); + } + if(err != SD_OK) + goto err_return; + err = sdcard_cmd7_process(); + if(err != SD_OK) + goto err_return; + Sd_MMC_flag = MMC_CARD; + goto right_return; + +right_return: + NoneedInitflag = 1; +err_return: + sdio_clk_config(0); + return err; +} + +void sdcard_uninitialize(void) +{ + sdio_hw_uninit(); + sdio_sw_init(); + NoneedInitflag = 0; +} + +static SDIO_Error +sdcard_read_single_block(UINT8 *readbuff, UINT32 readaddr, UINT32 blocksize) +{ + SDIO_CMD_S cmd; + SDIO_Error ret; + + sdio_clk_config(1); + if(blocksize != SD_DEFAULT_BLOCK_SIZE) + { + ret = SD_ERROR; + goto read_return; + } + + ASSERT_ERR(sdcard.block_size == blocksize); + + // setup data reg first + sdio_set_data_timeout( DEF_HIGH_SPEED_CMD_TIMEOUT);//DEF_DATA_TIME_OUT); + sdio_setup_data(SDIO_RD_DATA, blocksize); + + cmd.index = READ_SINGLE_BLOCK; + cmd.arg = (UINT32)(readaddr << sdcard.Addr_shift_bit); + cmd.flags = SD_CMD_SHORT; + cmd.timeout = DEF_HIGH_SPEED_CMD_TIMEOUT;// DEF_CMD_TIME_OUT; + sdio_send_cmd(&cmd); + cmd.err = sdio_wait_cmd_response(cmd.index); + + ret = cmd.err; + + if(ret == SD_CMD_RSP_TIMEOUT) + { + SDCARD_FATAL("cmd17 noresp, readsingle block err\r\n"); + goto read_return; + } + else if(ret == SD_CMD_CRC_FAIL) + { + SDCARD_FATAL("cmd17 cmdcrc err, readsingle block err\r\n"); + goto read_return; + } + + cmd.err = sdcard_wait_receive_data((UINT32 *)readbuff); + ret = cmd.err; + + if(ret != SD_OK) + { + SDCARD_FATAL("read single block wait data receive err:%d\r\n", cmd.err); + goto read_return; + } +read_return: + sdio_clk_config(0); + return ret; +} + +static SDIO_Error +sdcard_write_single_block(UINT8 *writebuff, UINT32 writeaddr, UINT32 blocksize) +{ + SDIO_CMD_S cmd; + SDIO_Error ret; + + UINT32 check_status_times = 0xffff; + sdio_clk_config(1); + ASSERT_ERR(sdcard.block_size == blocksize); + if(blocksize != SD_DEFAULT_BLOCK_SIZE) + { + ret = SD_ERROR; + goto write_return; + } + + cmd.index = WRITE_BLOCK; + cmd.arg = (UINT32)(writeaddr << sdcard.Addr_shift_bit); + cmd.flags = SD_CMD_SHORT; + cmd.timeout = DEF_HIGH_SPEED_CMD_TIMEOUT;//DEF_CMD_TIME_OUT; + sdio_send_cmd(&cmd); + cmd.err = sdio_wait_cmd_response(cmd.index); + ret = cmd.err; + + if(ret == SD_CMD_RSP_TIMEOUT) + { + SDCARD_FATAL("cmd17 noresp, readsingle block err\r\n"); + goto write_return; + } + else if(cmd.err == SD_CMD_CRC_FAIL) + { + SDCARD_FATAL("cmd17 cmdcrc err, readsingle block err\r\n"); + goto write_return; + } + sdio_set_data_timeout( DEF_HIGH_SPEED_CMD_TIMEOUT);//DEF_DATA_TIME_OUT); + sdcard_write_data((UINT32 *)writebuff); + sdio_setup_data(SDIO_WR_DATA, blocksize); + ret = sdcard_wait_write_end(); + + ret = cmd.err; + if(ret != SD_OK) + { + SDCARD_FATAL("write single block wait data receive err:%d\r\n", cmd.err); + goto write_return; + } + +write_return: + sdio_clk_config(0); + return ret; +} + +void sdcard_init(void) +{ + ddev_register_dev(SDCARD_DEV_NAME, &sdcard_op); + //sdcard_cd_timer_init(); +} + +void sdcard_exit(void) +{ + ddev_unregister_dev(SDCARD_DEV_NAME); +} + + +/******************************************************************************/ +/***************************** sdcard API function ****************************/ +/******************************************************************************/ + +UINT32 sdcard_open(UINT32 op_flag) +{ + UINT8 cnt; + UINT32 param, reg; + /*ԽͣʱӵIJ*/ + if(NoneedInitflag == 1) + { + os_printf("no need initialize\r\n"); + if(!SD_det_gpio_flag) + { + param = GPIO_CFG_PARAM(sd_clk_pin, GMODE_SECOND_FUNC_PULL_UP); + sddev_control(GPIO_DEV_NAME, CMD_GPIO_CFG, ¶m); + } + + vTaskDelay(5); + sdio_clk_config(1); + vTaskDelay(5); + sdio_register_reenable(); + return SDCARD_SUCCESS; + } + + cnt = 3; + while(1) + { + if(sdcard_initialize() == SD_OK) + break; + if(--cnt == 0) + { + SDCARD_FATAL("sdcard_open err\r\n"); + return SDCARD_FAILURE; + } + } + + return SDCARD_SUCCESS; +} + +UINT32 sdcard_close(void) +{ + sdcard_uninitialize(); + return SDCARD_SUCCESS; +} + +UINT32 sdcard_read(char *user_buf, UINT32 count, UINT32 op_flag) +{ + SDIO_Error err = SD_OK; + UINT32 start_blk_addr; + UINT8 read_blk_numb, numb; + UINT8 *read_data_buf; + // check operate parameter + start_blk_addr = op_flag; + read_blk_numb = (UINT8)count; + read_data_buf = (UINT8 *)user_buf; + + peri_busy_count_add(); + for(numb = 0; numb < read_blk_numb; numb++) + { + + err = sdcard_read_single_block(read_data_buf, start_blk_addr, + SD_DEFAULT_BLOCK_SIZE); + if(err != SD_OK) + { + SDCARD_FATAL("sdcard_read err:%d, curblk:0x%x\r\n", err, start_blk_addr); + return (UINT32)err; + } + + start_blk_addr++; + read_data_buf += SD_DEFAULT_BLOCK_SIZE; + } + peri_busy_count_dec(); + return (UINT32)SD_OK; +} + +UINT32 sdcard_write(char *user_buf, UINT32 count, UINT32 op_flag) +{ + SDIO_Error err = SD_OK; + UINT32 start_blk_addr; + UINT8 write_blk_numb, numb; + UINT8 *write_data_buf; + peri_busy_count_add(); + + // check operate parameter + start_blk_addr = op_flag; + write_blk_numb = (UINT8)count; + write_data_buf = (UINT8 *)user_buf; + + for(numb = 0; numb < write_blk_numb; numb++) + { + err = sdcard_write_single_block(write_data_buf, start_blk_addr, + SD_DEFAULT_BLOCK_SIZE); + if(err != SD_OK) + { + SDCARD_FATAL("sdcard_write err:%d, curblk:0x%x\r\n", err, start_blk_addr); + return (UINT32)err; + } + + start_blk_addr++; + write_data_buf += SD_DEFAULT_BLOCK_SIZE; + } + + peri_busy_count_dec(); + + return (UINT32)SD_OK; +} + +UINT32 sdcard_ctrl(UINT32 cmd, void *parm) +{ + peri_busy_count_add(); + + switch(cmd) + { + default: + break; + } + + peri_busy_count_dec(); + + return 0; +} + + + +void app_sd_scanning(void) +{ + if(sdcard.detect_func) + { + (*sdcard.detect_func)(); + } +} + + +uint8 sd_clk_is_attached(void) +{ + uint32 tmp, mask, param ; + sdio_clk_config(0); + delay(1); + param = GPIO_CFG_PARAM(sd_clk_pin, GMODE_INPUT_PULLUP); + sddev_control(GPIO_DEV_NAME, CMD_GPIO_CFG, ¶m); + delay(5); + if(sddev_control(GPIO_DEV_NAME, CMD_GPIO_INPUT, &sd_clk_pin)) + { + GLOBAL_INT_DECLARATION(); + os_printf("sd is pull out in BSR:%x\r\n", sd_online); + GLOBAL_INT_DISABLE(); + if(sd_online == SD_CARD_ONLINE) + { + sd_online = SD_CARD_OFFLINE; + NoneedInitflag = 0; + } + GLOBAL_INT_RESTORE(); + return SD_CARD_OFFLINE; + } + else + { + param = GPIO_CFG_PARAM(sd_clk_pin, GMODE_SECOND_FUNC_PULL_UP); + sddev_control(GPIO_DEV_NAME, CMD_GPIO_CFG, ¶m); + delay(1); + sdio_clk_config(1); + return SD_CARD_ONLINE; + } +} + +/*ֵ:0 -- ޱ仯 + 1 -- SD INSERT + 2 -- SD PULLOUT +*/ +static void sd_detect_fun(void) +{ + if(!SD_det_gpio_flag) + { + volatile unsigned long *gpioconfig = (volatile unsigned long *)(REG_A2_CONFIG);//SD_CLK_PIN + uint32 detectstopflag = (*gpioconfig) & (1 << 6); + if(!detectstopflag ) + { + if(!sddev_control(GPIO_DEV_NAME, CMD_GPIO_INPUT, &sd_cd_pin)) + { + if (cnt_online < SD_DEBOUNCE_COUNT) + { + cnt_online ++; + } + else + { + if(SD_CARD_OFFLINE == sd_online) + { + os_printf("sd insert!!\r\n"); + sd_online = SD_CARD_ONLINE; + ;// + } + } + } + else + { + // os_printf("detect 1 :\r\n"); + if(SD_CARD_ONLINE == sd_online) + { + os_printf("sd desert!!\r\n"); + cnt_online = 0; + sd_online = SD_CARD_OFFLINE; + + NoneedInitflag = 0; + ;//Ƴ + } + } + } + } + else + { + if(sddev_control(GPIO_DEV_NAME, CMD_GPIO_INPUT, &sd_cd_pin)) + { + if(SD_CARD_ONLINE == sd_online) + { + cnt_online = 0; + sd_online = SD_CARD_OFFLINE; + + NoneedInitflag = 0; + os_printf("sd cd desert!!\r\n"); + ;//Ƴ + } + } + else + { + if (cnt_online < SD_DEBOUNCE_COUNT) + { + cnt_online ++; + } + else + { + if(SD_CARD_OFFLINE == sd_online) + { + sd_online = SD_CARD_ONLINE; + os_printf("sd cd insert!!\r\n"); + ;// + } + } + } + } +} + + +int sdcard_get_size( void ) +{ + return sdcard.total_block; +} +void clr_sd_noinitial_flag(void) +{ + NoneedInitflag = 0; +} + +void sdcard_cd_timer_handler(void *data) +{ + OSStatus err; + sd_detect_fun(); +} + +void sdcard_cd_timer_init(void) +{ + OSStatus err; + + err = rtos_init_timer(&sd_cd_timer, + 50, + (timer_handler_t)sdcard_cd_timer_handler, + NULL); + ASSERT(kNoErr == err); + + if(rtos_is_timer_init(&sd_cd_timer)) + { + err = rtos_start_timer(&sd_cd_timer); + ASSERT(kNoErr == err); + } +} + + + +#endif // CFG_USE_SDCARD_HOST +// EOF diff --git a/beken_os/beken378/driver/sdcard/sdcard.h b/beken_os/beken378/driver/sdcard/sdcard.h new file mode 100755 index 0000000..55aa425 --- /dev/null +++ b/beken_os/beken378/driver/sdcard/sdcard.h @@ -0,0 +1,20 @@ +#ifndef _SDCARD_H_ +#define _SDCARD_H_ + +#if CFG_USE_SDCARD_HOST +#include "sdcard_pub.h" + +/* API */ +extern UINT32 sdcard_open(UINT32 op_falag); + +extern UINT32 sdcard_close(void); + +extern UINT32 sdcard_read(char *user_buf, UINT32 count, UINT32 op_flag); + +extern UINT32 sdcard_write(char *user_buf, UINT32 count, UINT32 op_flag); + +extern UINT32 sdcard_ctrl(UINT32 cmd, void *parm); + +#endif // CFG_USE_SDCARD_HOST + +#endif diff --git a/beken_os/beken378/driver/sdcard/sdcard_pub.h b/beken_os/beken378/driver/sdcard/sdcard_pub.h new file mode 100755 index 0000000..4b1089d --- /dev/null +++ b/beken_os/beken378/driver/sdcard/sdcard_pub.h @@ -0,0 +1,25 @@ +#ifndef _SDCARD_PUB_H_ +#define _SDCARD_PUB_H_ + +#define SDCARD_SUCCESS (0) +#define SDCARD_FAILURE ((UINT32)-1) + +#define SDCARD_DEV_NAME ("sdcard") + + +#define SDCARD_CMD_MAGIC (0x8709000) + +enum +{ + CMD_SDCARD_SEND_BACKGROUND = SDCARD_CMD_MAGIC + 0, + CMD_SDCARD_RESET = SDCARD_CMD_MAGIC + 1, +}; + +/******************************************************************************* +* Function Declarations +*******************************************************************************/ +extern void sdcard_init(void); +extern void sdcard_exit(void); + +#endif + diff --git a/beken_os/beken378/driver/sdcard/sdio_driver.c b/beken_os/beken378/driver/sdcard/sdio_driver.c new file mode 100755 index 0000000..344ff75 --- /dev/null +++ b/beken_os/beken378/driver/sdcard/sdio_driver.c @@ -0,0 +1,432 @@ +#include "include.h" +#include "arm_arch.h" + +#if CFG_USE_SDCARD_HOST + +#include "sdio_driver.h" + +#include "drv_model_pub.h" +#include "sys_ctrl_pub.h" +#include "mem_pub.h" +#include "icu_pub.h" +#include "gpio_pub.h" + +/******************************************************************************/ +/**************************** platform function *******************************/ +/******************************************************************************/ + +static void +beken_sdcard_set_clk_div(UINT8 clkdiv) +{ + UINT32 reg; + + reg = REG_READ(REG_SDCARD_FIFO_THRESHOLD); + reg &= ~(SDCARD_FIFO_SD_RATE_SELECT_MASK << SDCARD_FIFO_SD_RATE_SELECT_POSI); + reg |= ((clkdiv & SDCARD_FIFO_SD_RATE_SELECT_MASK) + << SDCARD_FIFO_SD_RATE_SELECT_POSI); + REG_WRITE(REG_SDCARD_FIFO_THRESHOLD, reg); +} + + +/******************************************************************************/ +/**************************** interface function ******************************/ +/******************************************************************************/ +void sdio_set_low_clk(void) +{ + beken_sdcard_set_clk_div(CLK_200K); +} + +void sdio_set_high_clk(void) +{ + beken_sdcard_set_clk_div(CLK_6_5M); +} + +void sdio_gpio_config(void) +{ + UINT32 param; + #if (CFG_SOC_NAME == SOC_BK7221U) + param = GPIO_CFG_PARAM(SD_DETECT_DEFAULT_GPIO, GMODE_INPUT_PULLUP); + sddev_control(GPIO_DEV_NAME, CMD_GPIO_CFG, ¶m); + + param = GFUNC_MODE_SD1_HOST; + #else + param = GFUNC_MODE_SD_HOST; + #endif + sddev_control(GPIO_DEV_NAME, CMD_GPIO_ENABLE_SECOND, ¶m); +} + +void sdio_clk_config(UINT8 enable) +{ + UINT32 param; + UINT32 cmd; + + if(enable) + cmd = CMD_CLK_PWR_UP; + else + cmd = CMD_CLK_PWR_DOWN; + + param = PWD_SDIO_CLK_BIT; + sddev_control(ICU_DEV_NAME, cmd, ¶m); +} + +void sdio_register_reset(void) +{ + UINT32 reg; + + /* Clear cmd rsp int bit */ + reg = REG_READ(REG_SDCARD_CMD_RSP_INT_SEL); + REG_WRITE(REG_SDCARD_CMD_RSP_INT_SEL, reg); + + /* Clear tx/rx fifo */ + reg = SDCARD_FIFO_RX_FIFO_RST | SDCARD_FIFO_TX_FIFO_RST; + REG_WRITE(REG_SDCARD_FIFO_THRESHOLD, reg); + + /* Disabe all sdio interrupt */ + reg = 0; + REG_WRITE(REG_SDCARD_CMD_RSP_INT_MASK, reg); + + /* Config tx/rx fifo threshold */ + reg = ((SDCARD_RX_FIFO_THRD & SDCARD_FIFO_RX_FIFO_THRESHOLD_MASK) + << SDCARD_FIFO_RX_FIFO_THRESHOLD_POSI) + | ((SDCARD_TX_FIFO_THRD & SDCARD_FIFO_TX_FIFO_THRESHOLD_MASK) + << SDCARD_FIFO_TX_FIFO_THRESHOLD_POSI); + REG_WRITE(REG_SDCARD_FIFO_THRESHOLD, reg); +} + +void sdio_register_reenable(void) +{ + UINT32 reg; + + reg = REG_READ(REG_SDCARD_CMD_RSP_INT_SEL); + REG_WRITE(REG_SDCARD_CMD_RSP_INT_SEL, reg); + + reg = REG_READ(REG_SDCARD_FIFO_THRESHOLD); + reg |= (SDCARD_FIFO_RX_FIFO_RST | SDCARD_FIFO_TX_FIFO_RST | SDCARD_FIFO_SD_STA_RST); + REG_WRITE(REG_SDCARD_FIFO_THRESHOLD, reg); + + vTaskDelay(5); + /*Config tx/rx fifo threshold*/ + reg = ((SDCARD_RX_FIFO_THRD & SDCARD_FIFO_RX_FIFO_THRESHOLD_MASK) + << SDCARD_FIFO_RX_FIFO_THRESHOLD_POSI) + | ((SDCARD_TX_FIFO_THRD & SDCARD_FIFO_TX_FIFO_THRESHOLD_MASK) + << SDCARD_FIFO_TX_FIFO_THRESHOLD_POSI); + REG_WRITE(REG_SDCARD_FIFO_THRESHOLD, reg); +} + +void sdio_sendcmd_function( UINT8 cmd_index, UINT32 flag, + UINT32 timeout, VOID *arg ) +{ + UINT32 reg; + flag &= CMD_FLAG_MASK; + + reg = (UINT32)arg; + REG_WRITE(REG_SDCARD_CMD_SEND_AGUMENT, reg); + + reg = timeout; + REG_WRITE(REG_SDCARD_CMD_RSP_TIMER, reg); + + reg = ((((UINT32)cmd_index)&SDCARD_CMD_SEND_CTRL_CMD_INDEX_MASK) + << SDCARD_CMD_SEND_CTRL_CMD_INDEX_POSI) + | ((flag & SDCARD_CMD_SEND_CTRL_CMD_FLAGS_MASK) + << SDCARD_CMD_SEND_CTRL_CMD_FLAGS_POSI) + | SDCARD_CMD_SEND_CTRL_CMD_START; + REG_WRITE(REG_SDCARD_CMD_SEND_CTRL, reg); +} + +SDIO_Error sdio_wait_cmd_response(UINT32 cmd) +{ + UINT32 reg; + uint32 timeoutcnt = 0; + uint32 timeout2cnt = 0; + + while(1) + { + reg = REG_READ(REG_SDCARD_CMD_RSP_INT_SEL); + //wait until cmd response + if(reg & (SDCARD_CMDRSP_NORSP_END_INT + | SDCARD_CMDRSP_RSP_END_INT + | SDCARD_CMDRSP_TIMEOUT_INT) + ) + { + break; + } + +#if 1 + if(!SD_det_gpio_flag) + { + if(timeoutcnt++ >= SD_CLK_PIN_TIMEOUT1)//this value needs to be adjusted + { + if(SD_CARD_OFFLINE == sd_clk_is_attached())//detect sdcard is valid or not + { + REG_WRITE(REG_SDCARD_CMD_RSP_INT_SEL, reg);//clear the int flag + return SD_CMD_RSP_TIMEOUT; + } + else + { + if(timeout2cnt++ > 0x30000) + { + os_printf("===cmd timeout==:%x\r\n", reg); + return SD_CMD_RSP_TIMEOUT; + } + } + } + } + else + { + if(SD_CARD_OFFLINE == sd_is_attached())//detect sdcard is valid or not + { + REG_WRITE(REG_SDCARD_CMD_RSP_INT_SEL, reg);//clear the int flag + return SD_CMD_RSP_TIMEOUT; + } + } +#endif + } + + REG_WRITE(REG_SDCARD_CMD_RSP_INT_SEL, SD_CMD_RSP);//clear the int flag + if((reg & SDCARD_CMDRSP_TIMEOUT_INT) /*||(reg&SDCARD_CMDRSP_NORSP_END_INT)*/ ) + { + if((cmd != 1)) + { + SDCARD_WARN("sdcard cmd %x timeout,cmdresp_int_reg:0x%x\r\n", cmd , reg); + } + return SD_CMD_RSP_TIMEOUT; + } + if(reg & SDCARD_CMDRSP_CMD_CRC_FAIL) + { + + if((cmd != 41) && (cmd != 2) && (cmd != 9) && (cmd != 1)) + { + SDCARD_WARN("sdcard cmd %x crcfail,cmdresp_int_reg:0x%x\r\n", cmd , reg); + return SD_CMD_CRC_FAIL; + } + } + return SD_OK; +} + +void sdio_get_cmdresponse_argument(UINT8 num, UINT32 *resp) +{ + switch(num) + { + case 0: + *resp = REG_READ(REG_SDCARD_CMD_RSP_AGUMENT0); + break; + case 1: + *resp = REG_READ(REG_SDCARD_CMD_RSP_AGUMENT1); + break; + case 2: + *resp = REG_READ(REG_SDCARD_CMD_RSP_AGUMENT2); + break; + case 3: + *resp = REG_READ(REG_SDCARD_CMD_RSP_AGUMENT3); + break; + default: + break; + } +} + +void sdio_setup_data(UINT32 data_dir, UINT32 byte_len) +{ + UINT32 reg; + if(data_dir == SD_DATA_DIR_RD) + { + reg = REG_READ(REG_SDCARD_FIFO_THRESHOLD); + reg &= (3 << 21); + reg |= 0x3ffff; // set fifo + REG_WRITE(REG_SDCARD_FIFO_THRESHOLD, reg); + + reg = SDCARD_DATA_REC_CTRL_DATA_EN; + } + else + reg = SDCARD_DATA_REC_CTRL_DATA_WR_DATA_EN; + + reg |= SDCARD_DATA_REC_CTRL_DATA_BYTE_SEL + | ((byte_len & SDCARD_DATA_REC_CTRL_BLK_SIZE_MASK) + << SDCARD_DATA_REC_CTRL_BLK_SIZE_POSI) +#if CONFIG_SDCARD_BUSWIDTH_4LINE + | SDCARD_DATA_REC_CTRL_DATA_BUS +#endif + ; + + REG_WRITE(REG_SDCARD_DATA_REC_CTRL, reg); +} + +void sdio_set_data_timeout(UINT32 timeout) +{ + REG_WRITE(REG_SDCARD_DATA_REC_TIMER, timeout); +} + +void driver_sdcard_recv_data_start(int timeout ) +{ + REG_WRITE(REG_SDCARD_DATA_REC_TIMER, timeout); +#ifdef CONFIG_APP_SDCARD_4_LINE + REG_WRITE(REG_SDCARD_DATA_REC_CTRL, (0x1 | (1 << 2) | (512 << 4) | (1 << 17))); +#else + REG_WRITE(REG_SDCARD_DATA_REC_CTRL, (0x1 | (512 << 4) | (1 << 17))); +#endif +} + +void sdcard_set_host_buswidth_4line(void) +{ +} + +void sdcard_set_host_buswidth_1line(void) +{ +} + +SDIO_Error sdcard_wait_receive_data(UINT32 *receive_buf) +{ + UINT32 reg, i; + while(1) + { + reg = REG_READ(REG_SDCARD_CMD_RSP_INT_SEL); + if(reg & (SDCARD_CMDRSP_DATA_REC_END_INT + | SDCARD_CMDRSP_DATA_CRC_FAIL + | SDCARD_CMDRSP_DATA_TIME_OUT_INT)) + { + break; + } + } + + REG_WRITE(REG_SDCARD_CMD_RSP_INT_SEL, SD_DATA_RSP);//clear the int flag + if(reg & SDCARD_CMDRSP_DATA_TIME_OUT_INT) + { + return SD_DATA_TIMEOUT; + } + if(reg & SDCARD_CMDRSP_DATA_CRC_FAIL) + { + SDCARD_WARN("sdcard data crcfail,cmdresp_int_reg:0x%x\r\n", reg); + return SD_DATA_CRC_FAIL; + } + + for (i = 0; i < (SD_DEFAULT_BLOCK_SIZE >> 2); i++) + { + /* wait fifo data valid */ + while(1) + { + //software needn't handle dead-loop,hardware can garantee + if(REG_READ(REG_SDCARD_FIFO_THRESHOLD)&SDCARD_FIFO_RXFIFO_RD_READY) + break; + } + *(receive_buf + i) = REG_READ(REG_SDCARD_RD_DATA_ADDR); + } + + return SD_OK; + +} + +void sdcard_write_data(UINT32 *write_buf) +{ + UINT16 i; + UINT32 tmpval; + for(i = 0; i> 2; i++) + { + tmpval = ( (( write_buf[i] & 0xff) << 24 ) | + (((write_buf[i] >> 8) & 0xff ) << 16) | + (((write_buf[i] >> 16) & 0xff ) << 8) | + ((write_buf[i] >> 24) & 0xff ) ); + REG_WRITE(REG_SDCARD_WR_DATA_ADDR, tmpval); + } + +} + +SDIO_Error sdcard_wait_write_end(void) +{ + UINT32 reg; + while(1) + { + reg = REG_READ(REG_SDCARD_CMD_RSP_INT_SEL); + if(reg & (SDCARD_CMDRSP_DATA_WR_END_INT + | SDCARD_CMDRSP_DATA_CRC_FAIL + | SDCARD_CMDRSP_DATA_TIME_OUT_INT)) + { + break; + } + } + + REG_WRITE(REG_SDCARD_CMD_RSP_INT_SEL, SD_DATA_RSP);//clear the int flag + + if(reg & SDCARD_CMDRSP_DATA_TIME_OUT_INT) + { + return SD_DATA_TIMEOUT; + } + if(reg & SDCARD_CMDRSP_DATA_CRC_FAIL) + { + SDCARD_WARN("sdcard write data crcfail,cmdresp_int_reg:0x%x\r\n", reg); + return SD_DATA_CRC_FAIL; + } + + return SD_OK; +} + + +int wait_Receive_Data(void) +{ + uint32 ret = SD_ERR_LONG_TIME_NO_RESPONS, status = 0; + uint32 timeoutcnt = 0; + extern UINT32 rtos_get_time(void); + uint32 start_tm = rtos_get_time(); + while (1) + { + if(rtos_get_time() > start_tm + 4000) // 4s + { + ret = SD_ERR_LONG_TIME_NO_RESPONS; + break; + } + + status = REG_READ(REG_SDCARD_CMD_RSP_INT_SEL); + if (status & SDCARD_CMDRSP_DATA_REC_END_INT) + { + if (status & SDCARD_CMDRSP_DATA_CRC_FAIL) + { + os_printf("aaa\r\n"); + //ret = SD_DATA_CRC_FAIL; + ret = SD_OK; + } + else + { + ret = SD_OK; + } + break; + } + else if (status & SDCARD_CMDRSP_DATA_CRC_FAIL) + { + ret = SD_DATA_CRC_FAIL; + break; + } + else if (status & SDCARD_CMDRSP_DATA_TIME_OUT_INT) + { + ret = SD_DATA_TIMEOUT; + break; + } + if(!SD_det_gpio_flag) + { + if(timeoutcnt++ >= SD_CLK_PIN_TIMEOUT2) + { + if (SD_CARD_OFFLINE == sd_clk_is_attached()) + { + ret = SD_DATA_TIMEOUT; + break; + } + } + } + else + { + if(SD_CARD_OFFLINE == sd_is_attached()) + { + //detect sdcard is valid or not + ret = SD_DATA_TIMEOUT; + break; + } + } + } + + if((!SD_det_gpio_flag) && (SD_ERR_LONG_TIME_NO_RESPONS == ret)) + sd_clk_is_attached(); + + REG_WRITE(REG_SDCARD_CMD_RSP_INT_SEL, SD_DATA_RSP);/*< clear the int flag */ + return ret; +} + +#endif // CFG_USE_SDCARD_HOST +// EOF + diff --git a/beken_os/beken378/driver/sdcard/sdio_driver.h b/beken_os/beken378/driver/sdcard/sdio_driver.h new file mode 100755 index 0000000..ab1c6a7 --- /dev/null +++ b/beken_os/beken378/driver/sdcard/sdio_driver.h @@ -0,0 +1,206 @@ +#ifndef __SDIO_DRIVER_H__ +#define __SDIO_DRIVER_H__ + +#include "include.h" + +#include "uart_pub.h" +#define SDCARD_DEBUG + +#ifdef SDCARD_DEBUG +#define SDCARD_PRT os_printf +#define SDCARD_WARN warning_prf +#define SDCARD_FATAL fatal_prf +#else +#define SDCARD_PRT null_prf +#define SDCARD_WARN null_prf +#define SDCARD_FATAL null_prf +#endif + +// SDCARD REG +#define SDCARD_BASE_ADDR (0x00802D00) + +#define REG_SDCARD_CMD_SEND_CTRL (SDCARD_BASE_ADDR + 0*4) +#define SDCARD_CMD_SEND_CTRL_CMD_START (1 << 0) +#define SDCARD_CMD_SEND_CTRL_CMD_FLAGS_MASK (0x7) +#define SDCARD_CMD_SEND_CTRL_CMD_FLAGS_POSI (1) +#define SDCARD_CMD_SEND_CTRL_CMD_INDEX_MASK (0x3f) +#define SDCARD_CMD_SEND_CTRL_CMD_INDEX_POSI (4) + +#define REG_SDCARD_CMD_SEND_AGUMENT (SDCARD_BASE_ADDR + 1*4) +#define REG_SDCARD_CMD_RSP_TIMER (SDCARD_BASE_ADDR + 2*4) + +#define REG_SDCARD_DATA_REC_CTRL (SDCARD_BASE_ADDR + 3*4) +#define SDCARD_DATA_REC_CTRL_DATA_EN (1 << 0) +#define SDCARD_DATA_REC_CTRL_DATA_STOP_EN (1 << 1) +#define SDCARD_DATA_REC_CTRL_DATA_BUS (1 << 2) +#define SDCARD_DATA_REC_CTRL_DATA_MUL_BLK (1 << 3) +#define SDCARD_DATA_REC_CTRL_BLK_SIZE_MASK (0xfff) +#define SDCARD_DATA_REC_CTRL_BLK_SIZE_POSI (4) +#define SDCARD_DATA_REC_CTRL_DATA_WR_DATA_EN (1 << 16) +#define SDCARD_DATA_REC_CTRL_DATA_BYTE_SEL (1 << 17) + +#define REG_SDCARD_DATA_REC_TIMER (SDCARD_BASE_ADDR + 4*4) +#define REG_SDCARD_CMD_RSP_AGUMENT0 (SDCARD_BASE_ADDR + 5*4) +#define REG_SDCARD_CMD_RSP_AGUMENT1 (SDCARD_BASE_ADDR + 6*4) +#define REG_SDCARD_CMD_RSP_AGUMENT2 (SDCARD_BASE_ADDR + 7*4) +#define REG_SDCARD_CMD_RSP_AGUMENT3 (SDCARD_BASE_ADDR + 8*4) + +#define REG_SDCARD_CMD_RSP_INT_SEL (SDCARD_BASE_ADDR + 9*4) +#define SDCARD_CMDRSP_NORSP_END_INT (1 << 0) +#define SDCARD_CMDRSP_RSP_END_INT (1 << 1) +#define SDCARD_CMDRSP_TIMEOUT_INT (1 << 2) +#define SDCARD_CMDRSP_DATA_REC_END_INT (1 << 3) +#define SDCARD_CMDRSP_DATA_WR_END_INT (1 << 4) +#define SDCARD_CMDRSP_DATA_TIME_OUT_INT (1 << 5) +#define SDCARD_CMDRSP_RX_FIFO_NEED_READ (1 << 6) +#define SDCARD_CMDRSP_TX_FIFO_NEED_WRITE (1 << 7) +#define SDCARD_CMDRSP_RX_OVERFLOW (1 << 8) +#define SDCARD_CMDRSP_TX_FIFO_EMPTY (1 << 9) +#define SDCARD_CMDRSP_CMD_CRC_OK (1 << 10) +#define SDCARD_CMDRSP_CMD_CRC_FAIL (1 << 11) +#define SDCARD_CMDRSP_DATA_CRC_OK (1 << 12) +#define SDCARD_CMDRSP_DATA_CRC_FAIL (1 << 13) +#define SDCARD_CMDRSP_RSP_INDEX (0x3f<<14) +#define SDCARD_CMDRSP_WR_STATU (0x7<<20) +#define SDCARD_CMDRSP_DATA_BUSY (0x1<<23) + +#define REG_SDCARD_CMD_RSP_INT_MASK (SDCARD_BASE_ADDR + 10*4) +#define SDCARD_CMDRSP_NORSP_END_INT_MASK (1 << 0) +#define SDCARD_CMDRSP_RSP_END_INT_MASK (1 << 1) +#define SDCARD_CMDRSP_TIMEOUT_INT_MASK (1 << 2) +#define SDCARD_CMDRSP_DATA_REC_END_INT_MASK (1 << 3) +#define SDCARD_CMDRSP_DATA_WR_END_INT_MASK (1 << 4) +#define SDCARD_CMDRSP_DATA_TIME_OUT_INT_MASK (1 << 5) +#define SDCARD_CMDRSP_RX_FIFO_NEED_READ_MASK (1 << 6) +#define SDCARD_CMDRSP_TX_FIFO_NEED_WRITE_MASK (1 << 7) +#define SDCARD_CMDRSP_RX_OVERFLOW_MASK (1 << 8) +#define SDCARD_CMDRSP_TX_FIFO_EMPTY_MASK (1 << 9) + +#define REG_SDCARD_WR_DATA_ADDR (SDCARD_BASE_ADDR + 11*4) +#define REG_SDCARD_RD_DATA_ADDR (SDCARD_BASE_ADDR + 12*4) + +#define REG_SDCARD_FIFO_THRESHOLD (SDCARD_BASE_ADDR + 13*4) +#define SDCARD_FIFO_RX_FIFO_THRESHOLD_MASK (0xff) +#define SDCARD_FIFO_RX_FIFO_THRESHOLD_POSI (0) +#define SDCARD_FIFO_TX_FIFO_THRESHOLD_MASK (0xff) +#define SDCARD_FIFO_TX_FIFO_THRESHOLD_POSI (8) +#define SDCARD_FIFO_RX_FIFO_RST (1 << 16) +#define SDCARD_FIFO_TX_FIFO_RST (1 << 17) +#define SDCARD_FIFO_RXFIFO_RD_READY (1 << 18) +#define SDCARD_FIFO_TXFIFO_WR_READY (1 << 19) +#define SDCARD_FIFO_SD_STA_RST (1 << 20) +#define SDCARD_FIFO_SD_RATE_SELECT_POSI (21) +#define SDCARD_FIFO_SD_RATE_SELECT_MASK (0x3) + +// SDcard defination +/* Exported types ------------------------------------------------------------*/ +typedef enum +{ + SD_OK = 0, + SD_CMD_CRC_FAIL = (1), /*!< Command response received (but CRC check failed) */ + SD_DATA_CRC_FAIL = (2), /*!< Data bock sent/received (CRC check Failed) */ + SD_CMD_RSP_TIMEOUT = (3), /*!< Command response timeout */ + SD_DATA_TIMEOUT = (4), /*!< Data time out */ + + SD_INVALID_VOLTRANGE, + SD_R5_ERROR, /* A general or an unknown error occurred during the operation */ + SD_R5_ERR_FUNC_NUMB, /* An invalid function number was requested */ + SD_R5_OUT_OF_RANGE, /*The command's argument was out of the allowed range for this card*/ + SD_ERROR, + SD_ERR_LONG_TIME_NO_RESPONS, + SD_ERR_CMD41_CNT = 0xfffe +} SDIO_Error; + + +#define SD_CMD_NORESP 0 +#define SD_CMD_SHORT (CMD_FLAG_RESPONSE|CMD_FLAG_CRC_CHECK) +#define SD_CMD_LONG (CMD_FLAG_RESPONSE|CMD_FLAG_LONG_CMD\ + |CMD_FLAG_CRC_CHECK) + +#define SD_CMD_RSP (SDCARD_CMDRSP_NORSP_END_INT\ + |SDCARD_CMDRSP_RSP_END_INT\ + |SDCARD_CMDRSP_TIMEOUT_INT\ + |SDCARD_CMDRSP_CMD_CRC_FAIL) + +#define SD_DATA_RSP (SDCARD_CMDRSP_DATA_REC_END_INT\ + |SDCARD_CMDRSP_DATA_CRC_FAIL\ + |SDCARD_CMDRSP_DATA_WR_END_INT\ + |SDCARD_CMDRSP_DATA_TIME_OUT_INT) + + +#define SD_DATA_DIR_RD 0 +#define SD_DATA_DIR_WR 1 + +#define OCR_MSK_BUSY 0x80000000 // Busy flag +#define OCR_MSK_HC 0x40000000 // High Capacity flag +#define OCR_MSK_VOLTAGE_3_2V_3_3V 0x00100000 // Voltage 3.2V to 3.3V flag +#define OCR_MSK_VOLTAGE_ALL 0x00FF8000 // All Voltage flag + +#define SD_DEFAULT_OCR (OCR_MSK_VOLTAGE_ALL|OCR_MSK_HC) + +#define SD_MAX_VOLT_TRIAL ((INT32)0x0000FFFF) + +#define SD_DEFAULT_BLOCK_SIZE 512 +#define SDCARD_TX_FIFO_THRD (0x01) // 16byte +#define SDCARD_RX_FIFO_THRD (0x01) + +#define CLK_26M 0 +#define CLK_13M 1 +#define CLK_6_5M 2 +#define CLK_200K 3 + +#define CMD_FLAG_RESPONSE 0x01 +#define CMD_FLAG_LONG_CMD 0x02 +#define CMD_FLAG_CRC_CHECK 0x04 +#define CMD_FLAG_MASK 0x07 + +#define DEF_LOW_SPEED_CMD_TIMEOUT 100000 //200k -- about 5us (500ms) +#define DEF_LOW_SPEED_DATA_TIMEOUT 100000 + +#define DEF_HIGH_SPEED_CMD_TIMEOUT 20000000//26M - about 40ns (800ms) +#define DEF_HIGH_SPEED_DATA_TIMEOUT 10000000//about 400ms + +#define DEF_CMD_TIME_OUT 0x3000000 +#define DEF_DATA_TIME_OUT 0x3000000 + +#define SDIO_RD_DATA 0 +#define SDIO_WR_DATA 1 +#define SDIO_RD_AF_WR 2 + +#define SDIO_DEF_LINE_MODE 4 +#define SDIO_DEF_WORK_CLK 13 + + +#define SD_CLK_PIN_TIMEOUT1 0x1000 +#define SD_CLK_PIN_TIMEOUT2 0x8000 +#define SD_CARD_OFFLINE 0 +#define SD_CARD_ONLINE 1 +#define SD_DETECT_DEFAULT_GPIO 31 +extern uint8 SD_det_gpio_flag; + +// interface function +void sdio_set_low_clk(void); +void sdio_set_high_clk(void); +void sdio_gpio_config(void); +void sdio_clk_config(UINT8 enable); +void sdio_register_reset(void); +void sdio_sendcmd_function( UINT8 cmd_index, UINT32 flag, + UINT32 timeout, VOID *arg ); +SDIO_Error sdio_wait_cmd_response(UINT32 cmd); +void sdio_get_cmdresponse_argument(UINT8 num, UINT32 *resp); +void sdio_setup_data(UINT32 data_dir, UINT32 byte_len); +void sdio_set_data_timeout(UINT32 timeout); +void sdcard_set_host_buswidth_4line(void); +void sdcard_set_host_buswidth_1line(void); + +SDIO_Error sdcard_wait_receive_data(UINT32 *receive_buf); +SDIO_Error sdcard_wait_write_end(void); +void sdcard_write_data(UINT32 *write_buf); +void driver_sdcard_recv_data_start(int timeout ); +uint8 sd_clk_is_attached(void); +uint8 sd_is_attached(void); +void sdio_register_reenable(void); +int wait_Receive_Data(void); + +#endif + diff --git a/beken_os/beken378/driver/sdio/sdio.c b/beken_os/beken378/driver/sdio/sdio.c new file mode 100755 index 0000000..7463a70 --- /dev/null +++ b/beken_os/beken378/driver/sdio/sdio.c @@ -0,0 +1,773 @@ +#include "include.h" +#include "arm_arch.h" + +#include "sdio_pub.h" +#include "sdio.h" +#include "sutil.h" +#include "sdma_pub.h" +#include "intc_pub.h" + +#include "drv_model_pub.h" +#include "uart_pub.h" +#include "icu_pub.h" +#include "mem_pub.h" + +#include "co_math.h" +#include "gpio_pub.h" + +#if CFG_SDIO || CFG_SDIO_TRANS +#if FOR_SDIO_BLK_512 +#include "sdio_intf.h" +UINT8 beken_tx_sdio_s = 1; +UINT8 da_hd_err = 0; +#endif +STATIC SDIO_S sdio = +{ + 0, +}; + +STATIC DD_OPERATIONS sdio_op = +{ + sdio_open, + sdio_close, + sdio_read, + sdio_write, + sdio_ctrl +}; + +SDIO_NODE_PTR sdio_alloc_valid_node(UINT32 buf_size) +{ + UINT8 *buff_ptr; + SDIO_NODE_PTR temp_node_ptr; + SDIO_NODE_PTR mem_node_ptr = 0; + + if(0 == buf_size) + { + goto av_exit; + } + +#ifdef SUPPORT_STM32 + buf_size = su_align_power2(buf_size); +#endif + + temp_node_ptr = su_pop_node(&sdio.free_nodes); + if(temp_node_ptr) + { + buff_ptr = (UINT8 *)os_malloc(CFG_MSDU_RESV_HEAD_LEN + buf_size + + CFG_MSDU_RESV_TAIL_LEN + + MALLOC_MAGIC_LEN); + if(buff_ptr) + { + if(MALLOC_MAGIC_LEN) + { + //buff_ptr[(buf_size + MALLOC_MAGIC_LEN) - 1] = magic_byte0 ++; // MALLOC_MAGIC_BYTE0; + } + + temp_node_ptr->orig_addr = buff_ptr; + temp_node_ptr->addr = (UINT8 *)((UINT32)buff_ptr + CFG_MSDU_RESV_HEAD_LEN); + temp_node_ptr->length = buf_size; + mem_node_ptr = temp_node_ptr; + } + else + { + fatal_prf("alloc_null:%d\r\n", buf_size); + su_push_node(&sdio.free_nodes, temp_node_ptr); + } + } + else + { + fatal_prf("NoNode\r\n"); + } + +av_exit: + return mem_node_ptr; +} + +void sdio_free_valid_node(SDIO_NODE_PTR node_ptr) +{ + //UINT8 *buff_ptr; + + //buff_ptr = node_ptr->addr; + if(MALLOC_MAGIC_LEN) + { + //ASSERT(buff_ptr[node_ptr->length + MALLOC_MAGIC_LEN - 1] == (magic_byte00 ++)/*MALLOC_MAGIC_BYTE0*/); + //buff_ptr[node_ptr->length + MALLOC_MAGIC_LEN - 1] = MALLOC_MAGIC_BYTE1; + //os_memset(node_ptr->addr, MALLOC_MAGIC_BYTE1, node_ptr->length + MALLOC_MAGIC_LEN - 1); + } + + os_free(node_ptr->orig_addr); + node_ptr->addr = 0; + node_ptr->length = 0; + node_ptr->orig_addr = 0; + + su_push_node(&sdio.free_nodes, node_ptr); +} + + +void sdio_cmd_handler(void *buf, UINT32 len) +{ + UINT32 count; + UINT32 remain; + SDIO_PTR sdio_ptr; + SDIO_DCMD_PTR cmd_ptr; + SDIO_CMD_PTR reg_cmd_ptr; + SDIO_NODE_PTR mem_node_ptr = NULL; + +#if FOR_SDIO_BLK_512 + struct _stm32_frame_hdr *h_hd; + UINT32 m_size = 2048; +#endif + + ASSERT(NULL != buf) + ASSERT(buf == &sdio.cmd); + cmd_ptr = (SDIO_DCMD_PTR)buf; + reg_cmd_ptr = (SDIO_CMD_PTR)buf; + + sdma_fake_stop_dma(); + + sdio_ptr = &sdio; + switch(cmd_ptr->op_code) + { + case OPC_WR_DTCM : + { +#if FOR_SDIO_BLK_512 + sdio_ptr->rx_len = cmd_ptr->total_size; +#else + sdio_ptr->rx_len = cmd_ptr->data_len; + sdio_ptr->r_hdl_len = 0; +#endif + count = su_get_node_count(&sdio.rxing_list); + +#if FOR_SDIO_BLK_512 + if(count >= 2) + { + SDIO_WPRT("rxing_list:%d\r\n", count); + } + ASSERT(count < 2); +#endif + if(count) + { + mem_node_ptr = su_pop_node(&sdio.rxing_list); + } + else + { +#if FOR_SDIO_BLK_512 + if(1024 < cmd_ptr->total_size && cmd_ptr->total_size <= 1536) + m_size = 1536; + else if(0 < cmd_ptr->total_size && cmd_ptr->total_size <= 512) + m_size = 512; + else if(512 < cmd_ptr->total_size && cmd_ptr->total_size <= 1024) + m_size = 1024; + else + m_size = 2048; + + mem_node_ptr = sdio_alloc_valid_node(m_size); +#else + mem_node_ptr = sdio_alloc_valid_node(cmd_ptr->data_len); +#endif + } + +#if FOR_SDIO_BLK_512 + if((sdio_ptr->rx_seq != cmd_ptr->seq) && count) + { + sdio_free_valid_node(mem_node_ptr); + + if(1024 < cmd_ptr->total_size && cmd_ptr->total_size <= 1536) + m_size = 1536; + else if(0 < cmd_ptr->total_size && cmd_ptr->total_size <= 512) + m_size = 512; + else if(512 < cmd_ptr->total_size && cmd_ptr->total_size <= 1024) + m_size = 1024; + else + m_size = 2048; + mem_node_ptr = sdio_alloc_valid_node(m_size); + + sdio_ptr->rx_seq = cmd_ptr->seq; + } + if(sdio_ptr->rx_seq != cmd_ptr->seq && cmd_ptr->start_len) + { + da_hd_err = 1; + } + + if(sdio_ptr->rc_len != cmd_ptr->start_len) + { + sdio_ptr->rc_len = cmd_ptr->start_len; + sdio_ptr->r_hdl_len = cmd_ptr->start_len; + } +#endif + + if(mem_node_ptr) + { + + sdio_ptr->rx_status = RX_NODE_OK; +#if FOR_SDIO_BLK_512 + //ASSERT(cmd_ptr->size == cmd_ptr->data_len); + sdio_ptr->rx_transaction_len = cmd_ptr->data_len; +#else + remain = sdio_ptr->rx_len - sdio_ptr->r_hdl_len; + sdio_ptr->rx_transaction_len = MIN(BLOCK_LEN, remain); +#endif + + su_push_node(&sdio.rxing_list, mem_node_ptr); +#if FOR_SDIO_BLK_512 + sdma_start_rx(mem_node_ptr->addr + sdio_ptr->rc_len, sdio_ptr->rx_transaction_len); +#else + sdma_start_rx(mem_node_ptr->addr, sdio_ptr->rx_transaction_len); +#endif + } + else + { + sdio_ptr->rx_status = RX_NO_NODE; + } + break; + } + + case OPC_RD_DTCM : + { + + if(1 >= su_get_node_count(&sdio.tx_dat)) + { + sdio_ctrl(SDIO_CMD_CLEAR_TX_VALID, 0); + } + sdio_ptr->tx_len = cmd_ptr->data_len; + sdio_ptr->t_hdl_len = 0; + + count = su_get_node_count(&sdio.txing_list); + +#if FOR_SDIO_BLK_512 + if(count >= 2) + { + SDIO_WPRT("txing_list:%d\r\n", count); + } + ASSERT(count < 2); +#endif + + if(count) + { + mem_node_ptr = su_pop_node(&sdio.txing_list); + } + else + { + mem_node_ptr = su_pop_node(&sdio.tx_dat); +#if FOR_SDIO_BLK_512 + ASSERT(sdio_ptr->tc_len == 0); +#endif + } + + if(mem_node_ptr) + { + sdio_ptr->tx_status = TX_NODE_OK; + remain = sdio_ptr->tx_len - sdio_ptr->t_hdl_len; + +#if FOR_SDIO_BLK_512 + if(!count) + { + ASSERT(mem_node_ptr->addr); + h_hd = ( struct _stm32_frame_hdr *)mem_node_ptr->addr; + h_hd->seq = beken_tx_sdio_s++; + sdio_ptr->tx_seq = h_hd->seq; + } +#endif + sdio_ptr->tx_transaction_len = MIN(BLOCK_LEN, remain); + su_push_node(&sdio.txing_list, mem_node_ptr); +#if FOR_SDIO_BLK_512 + sdma_start_tx(mem_node_ptr->addr + sdio_ptr->tc_len, sdio_ptr->tx_transaction_len); +#else + sdma_start_tx(mem_node_ptr->addr, sdio_ptr->tx_transaction_len); +#endif + } + else + { + sdio_ptr->tx_status = TX_NO_NODE; + } + + break; + } + + case OPC_WR_REG : + { + UINT8 reg_numb = (reg_cmd_ptr->len - 4) >> 3; + UINT8 i; + UINT32 reg_addr, reg_val; + for(i = 0; i < reg_numb; i++) + { + reg_addr = reg_cmd_ptr->content[i]; + reg_val = reg_cmd_ptr->content[i + reg_numb]; + *((UINT32 *)reg_addr) = reg_val; + } + + break; + } + + case OPC_RD_REG : + { + UINT8 reg_numb = (reg_cmd_ptr->len - 4) >> 2; + UINT8 i; + UINT32 reg_addr, reg_val[16]; + for(i = 0; i < reg_numb; i++) + { + reg_addr = reg_cmd_ptr->content[i]; + reg_val[i] = *((UINT32 *)reg_addr); + } + + sdio_ptr->transaction_len = MIN(64, reg_numb << 2); + sdma_start_tx((UINT8 *)reg_val, sdio_ptr->transaction_len); + + break; + } + + default: + { + SDIO_WPRT("Exceptional cmd of sdio\r\n"); + break; + } + } +} + +void sdio_tx_cb(void) +{ + UINT32 remain; + SDIO_PTR sdio_ptr; + SDIO_NODE_PTR mem_node_ptr; +#if FOR_SDIO_BLK_512 + struct _stm32_frame_hdr *h_hd; +#endif + sdio_ptr = &sdio; +#if(! FOR_SDIO_BLK_512) + sdio_ptr->t_hdl_len += sdio_ptr->tx_transaction_len; +#endif + mem_node_ptr = su_pop_node(&sdio.txing_list); + if((0 == mem_node_ptr) + && (TX_NO_NODE == sdio_ptr->tx_status)) + { + SDIO_PRT("tx_cb_no_node\r\n"); + sdio_ptr->tx_status = TX_NODE_OK; + return; + } + + ASSERT(mem_node_ptr); +#if FOR_SDIO_BLK_512 + sdio_ptr->t_hdl_len += sdio_ptr->tx_transaction_len; + sdio_ptr->tc_len += sdio_ptr->tx_transaction_len; + + h_hd = (struct _stm32_frame_hdr *)mem_node_ptr->addr; + + if(mem_node_ptr->length <= sdio_ptr->tc_len) + { +#endif + if(mem_node_ptr->callback) + { + (mem_node_ptr->callback)(mem_node_ptr->Lparam, mem_node_ptr->Rparam); + } + + mem_node_ptr->callback = NULLPTR; + mem_node_ptr->Lparam = NULL; + mem_node_ptr->Rparam = NULL; + + sdio_free_valid_node(mem_node_ptr); + + remain = sdio_ptr->tx_len - sdio_ptr->t_hdl_len; + if(remain) + { + ASSERT(0); + } + else + { + /*sdma_start_cmd*/ + } +#if FOR_SDIO_BLK_512 + sdio_ptr->tc_len = 0; + } + else + { + su_push_node(&sdio.txing_list, mem_node_ptr); + } +#endif + +} + + +void sdio_rx_cb(UINT32 count) +{ + UINT32 remain; + SDIO_PTR sdio_ptr; + SDIO_NODE_PTR mem_node_ptr; +#if FOR_SDIO_BLK_512 + struct stm32_cmd_hdr *c_hd; + struct _stm32_frame_hdr *h_hd; + UINT8 data_err = 0; +#endif + sdio_ptr = &sdio; + +#if(! FOR_SDIO_BLK_512) + sdio_ptr->r_hdl_len += sdio_ptr->rx_transaction_len; +#endif + mem_node_ptr = su_pop_node(&sdio.rxing_list); + if((0 == mem_node_ptr) + && (RX_NO_NODE == sdio_ptr->rx_status)) + { + SDIO_WPRT("rx_cb_no_node\r\n"); + sdio_ptr->rx_status = RX_NODE_OK; + return; + } +#if FOR_SDIO_BLK_512 + if(0 == mem_node_ptr) + { + SDIO_WPRT("rx_no_nd %d %d\r\n", sdio_ptr->rc_len, sdio_ptr->r_hdl_len); + SDIO_WPRT("rxing_list:%d txing_list:%d\r\n", su_get_node_count(&sdio.rxing_list), + su_get_node_count(&sdio.txing_list)); + + sdio_ptr->rx_status = RX_NODE_OK; + return; + } + + sdio_ptr->r_hdl_len += sdio_ptr->rx_transaction_len; + sdio_ptr->rc_len += sdio_ptr->rx_transaction_len; + //mem_node_ptr->length = count; + + h_hd = (struct _stm32_frame_hdr *)mem_node_ptr->addr; + c_hd = (struct stm32_cmd_hdr *)(mem_node_ptr->addr + sizeof(*h_hd)); + + if(!h_hd->len && !h_hd->seq) + { + SDIO_WPRT("rcv er1?\r\n"); + } + if(h_hd->type > 4) + { + SDIO_WPRT("rcv er2? 0x%x \r\n", h_hd->type); + } + + if(h_hd->len > mem_node_ptr->length) + { + SDIO_WPRT("rcv er4? 0x%x\r\n", h_hd->len); + } + if(data_err) + { + sdio_free_valid_node(mem_node_ptr); + sdio_ptr->rc_len = 0; + sdio_ptr->r_hdl_len = 0; + return; + } + + sdio_ptr->rx_seq = h_hd->seq; + if(sdio_ptr->rc_len >= h_hd->len) + { + if(da_hd_err == 1) + { + SDIO_WPRT("rcv da_hd_err\r\n"); + sdio_free_valid_node(mem_node_ptr); + sdio_ptr->rc_len = 0; + sdio_ptr->r_hdl_len = 0; + da_hd_err = 0; + return; + } +#else + SDIO_PRT("rx_cb\r\n"); + ASSERT(mem_node_ptr); + + //mem_node_ptr->length = count; +#endif + + su_push_node(&sdio.rx_dat, mem_node_ptr); + if(sdio_ptr->rx_cb) + { + (*(sdio_ptr->rx_cb))(); + } + + remain = sdio_ptr->rx_len - sdio_ptr->r_hdl_len; + if(remain) + { + ASSERT(0); + } + else + { + /*sdma_start_cmd*/ + + } +#if FOR_SDIO_BLK_512 + sdio_ptr->rc_len = 0; + sdio_ptr->r_hdl_len = 0; + } + else + { + su_push_node(&sdio.rxing_list, mem_node_ptr); + } +#endif +} + +void sdio_register_rx_cb(FUNCPTR func) +{ + sdio.rx_cb = func; +} + +static void sdio_intfer_gpio_config(void) +{ + UINT32 param; + + param = GFUNC_MODE_SD_DMA; + sddev_control(GPIO_DEV_NAME, CMD_GPIO_ENABLE_SECOND, ¶m); +} +/**********************************************************************/ +void sdio_init(void) +{ + sdio_intfer_gpio_config(); + + INIT_LIST_HEAD(&sdio.tx_dat); + INIT_LIST_HEAD(&sdio.rx_dat); + INIT_LIST_HEAD(&sdio.txing_list); + INIT_LIST_HEAD(&sdio.rxing_list); + + su_init(&sdio); + +#if FOR_SDIO_BLK_512 + sdio.rc_len = 0; + sdio.tc_len = 0; +#endif + sdma_register_handler(sdio_tx_cb, sdio_rx_cb, sdio_cmd_handler); + sdma_init(); + + ddev_register_dev(SDIO_DEV_NAME, &sdio_op); + + SDIO_PRT("sdio_init\r\n"); +} + + +void sdio_exit(void) +{ + sdma_uninit(); + + ddev_unregister_dev(SDIO_DEV_NAME); +} + +UINT32 sdio_open(UINT32 op_flag) +{ + UINT32 reg; + + sdma_open(); + sdma_start_cmd((UINT8 *)&sdio.cmd, sizeof(sdio.cmd)); + + reg = *((volatile UINT32 *)((0x00802000 + 16 * 4))); + if(reg & (1 << FIQ_SDIO_DMA)) + { + ASSERT(0); + } + + intc_enable(FIQ_SDIO_DMA); + + return SDIO_SUCCESS; +} + +UINT32 sdio_close(void) +{ + sdma_close(); + + return SDIO_SUCCESS; +} + +UINT32 sdio_read(char *user_buf, UINT32 count, UINT32 op_flag) +{ + UINT32 ret; + UINT32 len; + SDIO_NODE_PTR mem_node_ptr; + + ret = SDIO_FAILURE; + + peri_busy_count_add(); + + if(S2H_RD_SYNC == op_flag) + { + if((NULLPTR == user_buf) + || (0 == count)) + { + goto rd_exit; + } + + mem_node_ptr = su_pop_node(&sdio.tx_dat); + if(mem_node_ptr) + { + len = MIN(count, mem_node_ptr->length); + os_memcpy(user_buf, mem_node_ptr->addr, len); + ret = mem_node_ptr->length; + + sdio_free_valid_node(mem_node_ptr); + } + else + { + ret = SDIO_FAILURE; + } + } + else if(H2S_RD_SYNC == op_flag) + { + if((NULLPTR == user_buf) + || (0 == count)) + { + goto rd_exit; + } + + mem_node_ptr = su_pop_node(&sdio.rx_dat); + if(mem_node_ptr) + { + len = MIN(count, mem_node_ptr->length); + os_memcpy(user_buf, mem_node_ptr->addr, len); + ret = mem_node_ptr->length; + + sdio_free_valid_node(mem_node_ptr); + } + else + { + ret = SDIO_FAILURE; + } + } + else if(H2S_RD_SPECIAL == op_flag) + { + mem_node_ptr = su_pop_node(&sdio.rx_dat); + if(mem_node_ptr) + { + mem_node_ptr->Lparam = &sdio.free_nodes; + mem_node_ptr->Rparam = mem_node_ptr; + + ret = (UINT32)mem_node_ptr; + } + else + { + ret = SDIO_FAILURE; + } + } + + peri_busy_count_dec(); + +rd_exit: + return ret; +} + +UINT32 sdio_write(char *user_buf, UINT32 count, UINT32 op_flag) +{ + UINT32 ret; + SDIO_NODE_PTR mem_node_ptr; + + ret = SDIO_FAILURE; + + peri_busy_count_add(); + + if(S2H_WR_SYNC == op_flag) + { + if((NULLPTR == user_buf) + || (0 == count)) + { + goto exit_wr; + } + + mem_node_ptr = sdio_alloc_valid_node(count); + if(mem_node_ptr) + { + os_memcpy(mem_node_ptr->addr, user_buf, count); + su_push_node(&sdio.tx_dat, mem_node_ptr); + sdio_ctrl(SDIO_CMD_SET_TX_VALID, 0); + + ret = SDIO_SUCCESS; + } + else + { + ret = SDIO_FAILURE; + } + } + else if(S2H_WR_SPECIAL == op_flag) + { + if((NULLPTR == user_buf) + || (0 == count)) + { + goto exit_wr; + } + + mem_node_ptr = (SDIO_NODE_PTR)user_buf; + su_push_node(&sdio.tx_dat, mem_node_ptr); + + sdio_ctrl(SDIO_CMD_SET_TX_VALID, 0); + ret = SDIO_SUCCESS; + } + else if(H2S_WR_SYNC == op_flag) + { + if((NULLPTR == user_buf) + || (0 == count)) + { + goto exit_wr; + } + + mem_node_ptr = sdio_alloc_valid_node(count); + if(mem_node_ptr) + { + os_memcpy(mem_node_ptr->addr, user_buf, count); + su_push_node(&sdio.rx_dat, mem_node_ptr); + + ret = SDIO_SUCCESS; + } + else + { + ret = SDIO_FAILURE; + } + } + + peri_busy_count_dec(); + +exit_wr: + return ret; +} + +UINT32 sdio_ctrl(UINT32 cmd, void *param) +{ + UINT32 ret; + SDIO_NODE_PTR mem_node_ptr; + + ret = SDIO_SUCCESS; + + peri_busy_count_add(); + + switch(cmd) + { + case SDIO_CMD_PUSH_FREE_NODE: + mem_node_ptr = (SDIO_NODE_PTR)param; + + sdio_free_valid_node(mem_node_ptr); + break; + + case SDIO_CMD_GET_FREE_NODE: + mem_node_ptr = sdio_alloc_valid_node(*(UINT32 *)param); + + ret = (UINT32)mem_node_ptr; + break; + + case SDIO_CMD_REG_RX_CALLBACK: + sdio_register_rx_cb((FUNCPTR)param); + break; + + case SDIO_CMD_GET_CNT_FREE_NODE: + *((UINT32 *)param) = su_get_node_count(&sdio.free_nodes); + break; + + case SDIO_CMD_CLEAR_TX_VALID: + sdma_clr_tx_valid(); + break; + + case SDIO_CMD_PEEK_S2H_COUNT: + ret = su_get_node_count(&sdio.tx_dat); + break; + + case SDIO_CMD_PEEK_H2S_COUNT: + ret = su_get_node_count(&sdio.rx_dat); + break; + + case SDIO_CMD_SET_TX_VALID: + sdma_set_tx_valid(); + break; + + default: + break; + } + + peri_busy_count_dec(); + + return ret; +} +#endif +// EOF + diff --git a/beken_os/beken378/driver/sdio/sdio.h b/beken_os/beken378/driver/sdio/sdio.h new file mode 100755 index 0000000..80df2d8 --- /dev/null +++ b/beken_os/beken378/driver/sdio/sdio.h @@ -0,0 +1,145 @@ +#ifndef _SDIO_H_ +#define _SDIO_H_ + +#include "doubly_list.h" +#include "rwnx_config.h" + +#define SDIO_DEBUG + +#ifdef SDIO_DEBUG +#define SDIO_PRT os_null_printf //os_printf +#define SDIO_WPRT warning_prf +#define STATIC +#else +#define SDIO_PRT os_null_printf +#define SDIO_WPRT os_null_printf +#define STATIC static +#endif + +#ifdef SDIO_DEBUG +#define MALLOC_MAGIC_LEN (8) +#else +#define MALLOC_MAGIC_LEN (0) +#endif + +#define MALLOC_MAGIC_BYTE0 (0xAA) +#define MALLOC_MAGIC_BYTE1 (0xBB) + +/*CMD BUFFER space: 64bytes*/ +#define MAX_CONTENT_COUNT (15) + +#define DIR_TO_DTCM (0x55) +#define DIR_FROM_DTCM (0xAA) + +typedef struct _sdio_cmd +{ + UINT8 op_code; + UINT8 len; + UINT8 flag; + UINT8 status; + + UINT32 content[MAX_CONTENT_COUNT]; +} SDIO_CMD_S, *SDIO_CMD_PTR; + + +typedef struct _sdio_dcmd +{ + UINT8 op_code; + UINT8 cmd_len; + UINT8 flag; + UINT8 status; + + UINT16 data_len; +#if FOR_SDIO_BLK_512 + UINT16 start_len; + UINT8 seq; + UINT8 reserve; + UINT16 total_size; + UINT32 content[MAX_CONTENT_COUNT - 2]; +#else + UINT16 reserve; + UINT32 content[MAX_CONTENT_COUNT - 1]; +#endif +} SDIO_DCMD_S, *SDIO_DCMD_PTR; + +#define RX_NODE_OK (0x1) +#define TX_NODE_OK (0x2) +#define RX_NO_NODE (0xA) +#define TX_NO_NODE (0xB) + +typedef struct _sdio_entity_ +{ + UINT16 rx_status; + UINT16 tx_status; +#if FOR_SDIO_BLK_512 + UINT32 tc_len; + UINT32 rc_len; + UINT8 tx_seq; + UINT8 rx_seq; +#endif + UINT32 rx_len; + UINT32 tx_len; + UINT32 r_hdl_len; + UINT32 t_hdl_len; + UINT32 tx_transaction_len; + UINT32 rx_transaction_len; + UINT32 transaction_len; + + SDIO_NODE_T snode[CELL_COUNT]; + + LIST_HEADER_T tx_dat; + LIST_HEADER_T txing_list; + + LIST_HEADER_T rx_dat; + LIST_HEADER_T rxing_list; + FUNCPTR rx_cb; + + LIST_HEADER_T free_nodes; + + SDIO_CMD_S cmd; +} SDIO_S, *SDIO_PTR; + +#define OPC_WR_REG (0xC5) +#define OPC_RD_REG (0x5C) +#define OPC_WR_DTCM (0xE3) +#define OPC_RD_DTCM (0x3E) + + +/*hardware access: sdio internal register*/ +#define SDIO_REG_CONFIG (0x10) +#define SDIO_CFG_BLK_MASK (0x07) +#define SDIO_CFG_BLK_POS (0) +#define SDIO_CFG_DATA_WIDTH_MASK (0x03) +#define SDIO_CFG_DATA_WIDTH_POS (4) + +#define SDIO_REG_RETRY_DIR (0x11) +#define RETRY_DIR_H2M (1 << 0) + +#define SDIO_REG_DATA_STOP (0x12) +#define DATA_STOP_RTX (1 << 0) + +#define SDIO_REG_PROG_PROTECT1 (0x13) +#define PROG_PROTECT_WORD1 (0xa5) + +#define SDIO_REG_PROG_PROTECT2 (0x14) +#define PROG_PROTECT_WORD2 (0xc3) + +#define SDIO_REG_SYS_CTRL (0x15) +#define SYS_CTRL_RESET (1 << 0) + + +/******************************************************************************* +* Function Declarations +*******************************************************************************/ +extern UINT32 sdio_open(UINT32 op_flag); + +extern UINT32 sdio_close(void); + +extern UINT32 sdio_read(char *user_buf, UINT32 count, UINT32 op_flag); + +extern UINT32 sdio_write(char *user_buf, UINT32 count, UINT32 op_flag); + +extern UINT32 sdio_ctrl(UINT32 cmd, void *parm); + + +#endif // _SDIO_H_ diff --git a/beken_os/beken378/driver/sdio/sdma.c b/beken_os/beken378/driver/sdio/sdma.c new file mode 100755 index 0000000..fbf3c1f --- /dev/null +++ b/beken_os/beken378/driver/sdio/sdma.c @@ -0,0 +1,297 @@ +#include "include.h" +#include "arm_arch.h" + +#include "uart_pub.h" +#include "sdma_pub.h" +#include "sdma.h" + +#include "mem_pub.h" +#include "intc_pub.h" + +#if CFG_SDIO || CFG_SDIO_TRANS +TX_FUNC intr_tx_func = 0; +RX_FUNC intr_rx_func = 0; +CMD_FUNC intr_cmd_func = 0; + +UINT8 *cmd_buf = 0; + +volatile UINT32 cmd_data_dir = SDMA_DIR_IDLE; + +void sdma_init(void) +{ + UINT32 reg; + +#if CFG_REAL_SDIO + intc_service_register(FIQ_SDIO_DMA, PRI_FIQ_SDIO_DMA, sdma_isr); +#endif + + reg = REG_READ(REG_SDMA_INTR_STATUS); + REG_WRITE(REG_SDMA_INTR_STATUS, reg); + sdma_clr_tx_valid(); +} + +void sdma_open(void) +{ + UINT32 reg; + + reg = SDMA_CONFIG_INTR_EN_TX + | SDMA_CONFIG_INTR_EN_RX + | SDMA_CONFIG_INTR_EN_CMD; + REG_WRITE(REG_SDMA_CONFIG, reg); +} + +void sdma_uninit(void) +{ +} + +void sdma_close(void) +{ + UINT32 reg; + + reg = REG_READ(REG_SDMA_CONFIG); + reg &= ~(SDMA_CONFIG_INTR_EN_TX + | SDMA_CONFIG_INTR_EN_RX + | SDMA_CONFIG_INTR_EN_CMD); + REG_WRITE(REG_SDMA_CONFIG, reg); +} + +#ifdef SDMA_INTERACT_WITH_HOST +UINT32 sdma_get_blk_len(void) +{ + UINT32 reg; + UINT32 power; + UINT32 blk_len; + + reg = REG_READ(REG_SDMA_INTERACTIVE_HOST); + power = (reg >> INTERACTIVE_BLK_LEN_POSI) & INTERACTIVE_BLK_LEN_MASK; + + blk_len = 2 << (power + 8); + + return blk_len; +} + +void sdma_set_tx_valid(void) +{ + UINT32 reg; + + reg = REG_READ(REG_SDMA_INTERACTIVE_HOST); + reg |= INTERACTIVE_RX_VALID_BIT; + REG_WRITE(REG_SDMA_INTERACTIVE_HOST, reg); +} + +void sdma_clr_tx_valid(void) +{ + UINT32 reg; + + reg = REG_READ(REG_SDMA_INTERACTIVE_HOST); + reg &= ~INTERACTIVE_RX_VALID_BIT; + REG_WRITE(REG_SDMA_INTERACTIVE_HOST, reg); +} + +void sdma_set_tx_dat_count(UINT32 val) +{ + UINT32 reg; + + reg = REG_READ(REG_SDMA_INTERACTIVE_HOST); + reg &= ~(INTERACTIVE_RX_COUNT_MASK << INTERACTIVE_RX_COUNT_POSI); + reg |= (val & INTERACTIVE_RX_COUNT_MASK) << INTERACTIVE_RX_COUNT_POSI; + REG_WRITE(REG_SDMA_INTERACTIVE_HOST, reg); +} +#endif // SDMA_INTERACT_WITH_HOST + +void sdma_register_handler(TX_FUNC tx_callback, + RX_FUNC rx_callback, + CMD_FUNC cmd_callback) +{ + if(tx_callback) + { + intr_tx_func = tx_callback; + } + + if(rx_callback) + { + intr_rx_func = rx_callback; + } + + if(cmd_callback) + { + intr_cmd_func = cmd_callback; + } + + return; +} + +UINT32 sdma_dma_start(UINT8 *buf, UINT32 len) +{ + UINT32 reg; + UINT32 addr; + + ASSERT(len); + ASSERT(buf); + + addr = (UINT32)buf; + + REG_WRITE(REG_SDMA_ADDR, addr); + + reg = REG_READ(REG_SDMA_CONFIG); + reg |= SDMA_CONFIG_ADDR_READY; + + REG_WRITE(REG_SDMA_CONFIG, reg); + + return 0; +} + +UINT32 sdma_start_tx(UINT8 *buf, UINT32 len) +{ + cmd_data_dir = SDMA_DIR_TX; + + return sdma_dma_start(buf, len); +} + +UINT32 sdma_start_rx(UINT8 *buf, UINT32 len) +{ + cmd_data_dir = SDMA_DIR_RX; + + return sdma_dma_start(buf, len); +} + +void sdma_fake_stop_dma(void) +{ + cmd_data_dir = SDMA_DIR_IDLE; +} + +UINT32 sdma_start_cmd(UINT8 *cmd, UINT32 len) +{ + UINT32 reg; + + if(len != CMD_BUF_MAX_LEN) + { + return SDMA_FAILURE; + } + + cmd_buf = cmd; + + /*startup dma*/ + reg = REG_READ(REG_SDMA_CONFIG); + if(reg & SDMA_CONFIG_ADDR_READY) + { + return SDMA_BUSY; + } + + reg |= SDMA_CONFIG_DMA_EN; + REG_WRITE(REG_SDMA_CONFIG, reg); + + return 0; +} + +void sdma_rd_cmd_content(void *buf, UINT32 len) +{ + UINT8 *src; + + if(len > CMD_BUF_MAX_LEN) + { + warning_prf("cmd_len_exception:%d\r\n", len); + len = CMD_BUF_MAX_LEN; + } + + src = (UINT8 *)REG_SDMA_CMD_BA; + os_memcpy(buf, src, len); + + return; +} + +void sdma_tx_isr_handler(UINT32 irq_status) +{ + if(irq_status & SDMA_INTR_TX_DATA_BIT) + { + SDMA_PRT("sdma_tx\r\n"); + REG_WRITE(REG_SDMA_INTR_STATUS, SDMA_INTR_TX_DATA_BIT); + cmd_data_dir = SDMA_DIR_IDLE; + if(intr_tx_func) + { + (*intr_tx_func)(); + } + } +} + +void sdma_rx_isr_handler(UINT32 irq_status) +{ + UINT32 rx_count; + + if(irq_status & SDMA_INTR_RX_DATA_BIT) + { + SDMA_PRT("sdma_rx\r\n"); + REG_WRITE(REG_SDMA_INTR_STATUS, SDMA_INTR_RX_DATA_BIT); + + cmd_data_dir = SDMA_DIR_IDLE; + + if(intr_rx_func) + { + rx_count = (REG_READ(REG_SDMA_COUNT)) & SDMA_COUNT_MASK; + (*intr_rx_func)(rx_count); + } + } +} + +void sdma_cmd_isr_handler(UINT32 irq_status) +{ + UINT32 rx_count; + + if(irq_status & SDMA_INTR_CMD_BIT) + { + SDMA_PRT("sdma_cmd\r\n"); + + if(intr_cmd_func) + { + rx_count = (REG_READ(REG_SDMA_COUNT)) & SDMA_COUNT_MASK; + + sdma_rd_cmd_content(cmd_buf, rx_count); + + (*intr_cmd_func)(cmd_buf, rx_count); + } + REG_WRITE(REG_SDMA_INTR_STATUS, SDMA_INTR_CMD_BIT); + } +} + +void sdma_isr(void) +{ + UINT32 irq_sta; + + /*0, get isr status*/ + irq_sta = REG_READ(REG_SDMA_INTR_STATUS); + + /*1, handle isr branch*/ + if(SDMA_DIR_TX == cmd_data_dir) + { + sdma_tx_isr_handler(irq_sta); + sdma_cmd_isr_handler(irq_sta); + sdma_rx_isr_handler(irq_sta); + } + else if(SDMA_DIR_RX == cmd_data_dir) + { + sdma_rx_isr_handler(irq_sta); + sdma_cmd_isr_handler(irq_sta); + sdma_tx_isr_handler(irq_sta); + } + else + { + sdma_cmd_isr_handler(irq_sta); + + + + sdma_rx_isr_handler(irq_sta); + sdma_tx_isr_handler(irq_sta); + } + + if(!((irq_sta & SDMA_INTR_CMD_BIT) + || (irq_sta & SDMA_INTR_RX_DATA_BIT) + || (irq_sta & SDMA_INTR_TX_DATA_BIT))) + { + warning_prf("sdma:contrary to expectation:%x\r\n", irq_sta); + } + + return; +} +#endif + +// EOF diff --git a/beken_os/beken378/driver/sdio/sdma.h b/beken_os/beken378/driver/sdio/sdma.h new file mode 100755 index 0000000..80aba9e --- /dev/null +++ b/beken_os/beken378/driver/sdio/sdma.h @@ -0,0 +1,71 @@ +#ifndef _SDMA_H_ +#define _SDMA_H_ + +//#define SDMA_DEBUG + +#ifdef SDMA_DEBUG + #define SDMA_PRT os_printf +#else + #define SDMA_PRT os_null_printf + #define SDMA_WPRT warning_prf +#endif + +#define SDMA_DIR_IDLE (0) +#define SDMA_DIR_TX (1) +#define SDMA_DIR_RX (2) + +#define SDIO_DMA_BASE (0x00801000) + +#define REG_SDMA_RESERVE (SDIO_DMA_BASE + 00*4) + +#define REG_SDMA_CONFIG (SDIO_DMA_BASE + 01*4) +#define SDMA_CONFIG_DMA_EN (1 << 0) +#define SDMA_CONFIG_ADDR_READY (1 << 1) +#define SDMA_CONFIG_INTR_EN_TX (1 << 5) +#define SDMA_CONFIG_INTR_EN_RX (1 << 6) +#define SDMA_CONFIG_INTR_EN_CMD (1 << 7) + +#define REG_SDMA_ADDR (SDIO_DMA_BASE + 02*4) + +#define REG_SDMA_COUNT (SDIO_DMA_BASE + 03*4) +#define SDMA_COUNT_MASK (0xFFFF) + +#define REG_SDMA_CMD_BA (SDIO_DMA_BASE + 04*4) + +#define REG_SDMA_CMD_BUF0 (SDIO_DMA_BASE + 04*4) +#define REG_SDMA_CMD_BUF1 (SDIO_DMA_BASE + 05*4) +#define REG_SDMA_CMD_BUF2 (SDIO_DMA_BASE + 06*4) +#define REG_SDMA_CMD_BUF3 (SDIO_DMA_BASE + 07*4) +#define REG_SDMA_CMD_BUF4 (SDIO_DMA_BASE + 08*4) +#define REG_SDMA_CMD_BUF5 (SDIO_DMA_BASE + 09*4) +#define REG_SDMA_CMD_BUF6 (SDIO_DMA_BASE + 10*4) +#define REG_SDMA_CMD_BUF7 (SDIO_DMA_BASE + 11*4) +#define REG_SDMA_CMD_BUF8 (SDIO_DMA_BASE + 12*4) +#define REG_SDMA_CMD_BUF9 (SDIO_DMA_BASE + 13*4) +#define REG_SDMA_CMD_BUF10 (SDIO_DMA_BASE + 14*4) +#define REG_SDMA_CMD_BUF11 (SDIO_DMA_BASE + 15*4) +#define REG_SDMA_CMD_BUF12 (SDIO_DMA_BASE + 16*4) +#define REG_SDMA_CMD_BUF13 (SDIO_DMA_BASE + 17*4) +#define REG_SDMA_CMD_BUF14 (SDIO_DMA_BASE + 18*4) +#define REG_SDMA_CMD_BUF15 (SDIO_DMA_BASE + 19*4) + +#define REG_SDMA_INTR_STATUS (SDIO_DMA_BASE + 20*4) +#define SDMA_INTR_TX_DATA_BIT (1 << 0) +#define SDMA_INTR_RX_DATA_BIT (1 << 1) +#define SDMA_INTR_CMD_BIT (1 << 2) + +#define REG_SDMA_INTERACTIVE_HOST (SDIO_DMA_BASE + 21*4) +#define INTERACTIVE_BLK_LEN_POSI (24) +#define INTERACTIVE_BLK_LEN_MASK (0x7) +#define INTERACTIVE_RX_VALID_BIT (1 << 23) +#define INTERACTIVE_RX_COUNT_POSI (0) +#define INTERACTIVE_RX_COUNT_MASK (0xFFFFF) + +/*sdm driver macro*/ +#define CMD_BUF_MAX_LEN (64) + +#define SDMA_BUSY ((UINT32)-2) +#define SDMA_FAILURE ((UINT32)-1) +#define SDMA_SUCCESS (0 + +#endif // _SDMA_H_ diff --git a/beken_os/beken378/driver/sdio/sdma_pub.h b/beken_os/beken378/driver/sdio/sdma_pub.h new file mode 100755 index 0000000..f6e31aa --- /dev/null +++ b/beken_os/beken378/driver/sdio/sdma_pub.h @@ -0,0 +1,38 @@ +#ifndef _SDMA_PUB_H_ +#define _SDMA_PUB_H_ + +#define SDMA_INTERACT_WITH_HOST + +typedef void (*TX_FUNC)(void); +typedef void (*CMD_FUNC)(void *buf, UINT32 len); +typedef void (*RX_FUNC)(UINT32 count); + +/******************************************************************************* +* Function Declarations +*******************************************************************************/ +extern void sdma_init(void); + +extern void sdma_open(void); + +extern void sdma_uninit(void); + +extern void sdma_close(void); + +#ifdef SDMA_INTERACT_WITH_HOST +extern UINT32 sdma_get_blk_len(void); +extern void sdma_set_tx_valid(void); +extern void sdma_clr_tx_valid(void); +extern void sdma_set_tx_dat_count(UINT32 val); +#endif // SDMA_INTERACT_WITH_HOST + +extern void sdma_register_handler(TX_FUNC tx_callback, + RX_FUNC rx_callback, + CMD_FUNC cmd_callback); + +extern UINT32 sdma_start_rx(UINT8 *buf, UINT32 len); +extern UINT32 sdma_start_tx(UINT8 *buf, UINT32 len); + +extern UINT32 sdma_start_cmd(UINT8 *cmd, UINT32 len); +extern void sdma_fake_stop_dma(void); +extern void sdma_isr(void); +#endif // _SDMA_PUB_H_ diff --git a/beken_os/beken378/driver/sdio/sutil.c b/beken_os/beken378/driver/sdio/sutil.c new file mode 100755 index 0000000..57e4cc5 --- /dev/null +++ b/beken_os/beken378/driver/sdio/sutil.c @@ -0,0 +1,99 @@ +#include "include.h" +#include "arm_arch.h" + +#include "uart_pub.h" +#include "sdio_pub.h" +#include "sdio.h" +#include "sutil.h" + +#include "rwnx_config.h" + +#if CFG_SDIO || CFG_SDIO_TRANS +void su_init(SDIO_PTR sdio_ptr) +{ + UINT32 i; + SDIO_NODE_PTR node_ptr; + + INIT_LIST_HEAD(&sdio_ptr->free_nodes); + + for(i = 0; i < CELL_COUNT; i ++) + { + node_ptr = &sdio_ptr->snode[i]; + + node_ptr->callback = NULLPTR; + node_ptr->Lparam = NULL; + node_ptr->Rparam = NULL; + node_ptr->addr = 0; + node_ptr->node_list.next = NULLPTR; + node_ptr->node_list.prev = NULLPTR; + + su_push_node(&sdio_ptr->free_nodes, node_ptr); + } +} + +void su_push_node(LIST_HEADER_T *head, SDIO_NODE_PTR node) +{ + GLOBAL_INT_DECLARATION(); + + GLOBAL_INT_DISABLE(); + list_add_tail(&node->node_list, head); + GLOBAL_INT_RESTORE(); +} + +SDIO_NODE_PTR su_pop_node(LIST_HEADER_T *head) +{ + LIST_HEADER_T *tmp; + LIST_HEADER_T *pos; + SDIO_NODE_PTR node; + + GLOBAL_INT_DECLARATION(); + + GLOBAL_INT_DISABLE(); + + node = NULLPTR; + list_for_each_safe(pos, tmp, head) + { + list_del(pos); + node = list_entry(pos, SDIO_NODE_T, node_list); + + break; + } + + GLOBAL_INT_RESTORE(); + + return node; +} + +UINT32 su_get_node_count(LIST_HEADER_T *head) +{ + UINT32 count = 0; + LIST_HEADER_T *tmp; + LIST_HEADER_T *pos; + + GLOBAL_INT_DECLARATION(); + + GLOBAL_INT_DISABLE(); + list_for_each_safe(pos, tmp, head) + { + count ++; + } + + + GLOBAL_INT_RESTORE(); + return count; +} + +UINT32 su_align_power2(UINT32 size) +{ + UINT32 i = 1; + + while(i < size) + { + i <<= 1; + } + + return i; +} +#endif +// EOF + diff --git a/beken_os/beken378/driver/sdio/sutil.h b/beken_os/beken378/driver/sdio/sutil.h new file mode 100755 index 0000000..907e259 --- /dev/null +++ b/beken_os/beken378/driver/sdio/sutil.h @@ -0,0 +1,17 @@ +#ifndef _SDIO_UTIL_H_ +#define _SDIO_UTIL_H_ + +/******************************************************************************* +* Function Declarations +*******************************************************************************/ +extern void su_init(SDIO_PTR sdio_ptr); + +extern void su_push_node(LIST_HEADER_T *head, SDIO_NODE_PTR node); + +extern SDIO_NODE_PTR su_pop_node(LIST_HEADER_T *head); + +extern UINT32 su_get_node_count(LIST_HEADER_T *head); + +extern UINT32 su_align_power2(UINT32 size); + +#endif // _SDIO_UTIL_H_ diff --git a/beken_os/beken378/driver/spi/spi.c b/beken_os/beken378/driver/spi/spi.c new file mode 100755 index 0000000..d33a8bd --- /dev/null +++ b/beken_os/beken378/driver/spi/spi.c @@ -0,0 +1,964 @@ +#include "include.h" +#include "arm_arch.h" + +#include "spi.h" +#include "spi_pub.h" + +#include "drv_model_pub.h" +#include "intc_pub.h" +#include "mcu_ps_pub.h" +#include "icu_pub.h" +#include "gpio_pub.h" +#include "uart_pub.h" + +static spi_config_t spi_config; +//volatile spi_trans_t spi_trans; +static spi_message_t spi_rx_msg,spi_tx_msg; + +static struct spi_callback_des spi_receive_end_callback = {NULL, NULL}; +static struct spi_callback_des spi_txfifo_needwr_callback = {NULL, NULL}; +static struct spi_callback_des spi_tx_end_callback = {NULL, NULL}; + + + + +static SDD_OPERATIONS spi_op = +{ + spi_ctrl +}; + +static void spi_active(BOOLEAN val) +{ + UINT32 value; + + value = REG_READ(SPI_CTRL); + if(val == 0) + { + value &= ~SPIEN; + } + else if(val == 1) + { + value |= SPIEN; + } + REG_WRITE(SPI_CTRL, value); +} + +static void spi_set_msten(UINT8 val) +{ + UINT32 value; + + value = REG_READ(SPI_CTRL); + if(val == 0) + { + value &= ~MSTEN; + } + else if(val == 1) + { + value |= MSTEN; + } + REG_WRITE(SPI_CTRL, value); + spi_config.master = val; +} + +static void spi_set_ckpha(UINT8 val) +{ + UINT32 value; + + value = REG_READ(SPI_CTRL); + if(val == 0) + { + value &= ~CKPHA; + } + else + { + value |= CKPHA; + } + REG_WRITE(SPI_CTRL, value); +} + +static void spi_set_skpol(UINT8 val) +{ + UINT32 value; + + value = REG_READ(SPI_CTRL); + if(val == 0) + { + value &= ~CKPOL; + } + else + { + value |= CKPOL; + } + REG_WRITE(SPI_CTRL, value); +} + + + +static void spi_set_bit_wdth(UINT8 val) +{ + UINT32 value; + + value = REG_READ(SPI_CTRL); + if(val == 0) + { + value &= ~BIT_WDTH; + } + else if(val == 1) + { + value |= BIT_WDTH; + } + REG_WRITE(SPI_CTRL, value); + spi_config.bit_wdth = val; +} + +static void spi_set_nssmd(UINT8 val) +{ + UINT32 value; + + value = REG_READ(SPI_CTRL); + + #if (CFG_SOC_NAME == SOC_BK7231U) + value &= ~(NSSMD_MASK << NSSMD_POSI); + if(val) + val=1; + else + val=0; + value |= (val << NSSMD_POSI); + #elif (CFG_SOC_NAME == SOC_BK7231N) + value &= ~(CTRL_NSSMD_3); + if(val) + value |= CTRL_NSSMD_4; + else + value |= CTRL_NSSMD_3; + #else + value |= (val << NSSMD_POSI); + #endif + REG_WRITE(SPI_CTRL, value); + spi_config.nss_mode = val; +} +//static void spi_set_ckr(UINT8 val) +//{ +// UINT32 value; +// +// value = REG_READ(SPI_CTRL); +// value &= ~(SPI_CKR_MASK << SPI_CKR_POSI); +// value |= (val << SPI_CKR_POSI); +// REG_WRITE(SPI_CTRL, value); +//} + +/* + spi_clk : 90M/3=30M - DC0180 - DIV2 + spi_clk : 90M/4=22.5M - DC0180 - DIV3 + spi_clk : 90M/5=18M - DC0180 - DIV4 + spi_clk : 90M/6=15M - DC0180 - DIV5 + spi_clk : 90M/7=12.85M - DC0180 - DIV6 + spi_clk : 90M/8=11.25M - DC0180 - DIV7 + spi_clk : 90M/9=10M - DC0180 - DIV8 + spi_clk : 90M/10=9M - DC0180 - DIV9 + spi_clk : 90M/11=8.18M - DC0180 - DIV10 +*/ +#define SPI_PERI_CLK_26M (26 * 1000 * 1000) +#define SPI_PERI_CLK_DCO (80 * 1000 * 1000) + +static void spi_set_clock(UINT32 max_hz) +{ + int source_clk = 0; + int spi_clk = 0; + int div = 0; + UINT32 param; + //os_printf("\rmax_hz :%d\r\n", max_hz); + + if ((max_hz == 26000000) || (max_hz == 13000000) || (max_hz == 6500000) ) + { + BK_SPI_PRT("config spi clk source 26MHz\n"); + + spi_clk = max_hz; + +#if CFG_XTAL_FREQUENCE + + source_clk = CFG_XTAL_FREQUENCE; +#else + source_clk = SPI_PERI_CLK_26M; +#endif + param = PCLK_POSI_SPI; + sddev_control(ICU_DEV_NAME, CMD_CONF_PCLK_26M, ¶m); + } + else if (max_hz > 4333000) + { + BK_SPI_PRT("config spi clk source DCO\n"); + + if(max_hz > 30000000) // 120M/2 / (2 + 1) = 30M + { + spi_clk = 30000000; + BK_SPI_PRT("input clk > 30MHz, set input clk = 30MHz\n"); + } else { + spi_clk = max_hz; + } + sddev_control(ICU_DEV_NAME, CMD_CLK_PWR_DOWN, ¶m); + source_clk = SPI_PERI_CLK_DCO; + param = PCLK_POSI_SPI; + sddev_control(ICU_DEV_NAME, CMD_CONF_PCLK_DCO, ¶m); + param = PWD_SPI_CLK_BIT; + sddev_control(ICU_DEV_NAME, CMD_CLK_PWR_UP, ¶m); + } + else + { + BK_SPI_PRT("config spi clk source 26MHz\n"); + + spi_clk = max_hz; +#if CFG_XTAL_FREQUENCE + source_clk = CFG_XTAL_FREQUENCE; +#else + source_clk = SPI_PERI_CLK_26M; +#endif + + param = PCLK_POSI_SPI; + sddev_control(ICU_DEV_NAME, CMD_CONF_PCLK_26M, ¶m); + } + if ((max_hz == 26000000) || (max_hz == 13000000) || (max_hz == 6500000)) + { + div = source_clk/spi_clk -1; + } + else + { + // spi_clk = in_clk / (2 * (div + 1)) + div = ((source_clk >> 1) / spi_clk); + + if (div < 2) + { + div = 2; + } + else if (div >= 255) + { + div = 255; + } + } + + param = REG_READ(SPI_CTRL); + param &= ~(SPI_CKR_MASK << SPI_CKR_POSI); + param |= (div << SPI_CKR_POSI); + REG_WRITE(SPI_CTRL, param); + + BK_SPI_PRT("\rdiv = %d \r\n", div); + BK_SPI_PRT("\rspi_clk = %d \r\n", spi_clk); + BK_SPI_PRT("\rsource_clk = %d \r\n", source_clk); + os_printf("\rtarget frequency = %d, actual frequency = %d \r\n", max_hz, source_clk / 2 / div); + spi_config.rate = spi_clk ; +} + +static void spi_set_tx_buff(struct spi_message *msg) +{ + if(msg->send_buf) + { + spi_tx_msg.ptr_buff = msg->send_buf; + spi_tx_msg.buff_len = msg->send_len; + spi_tx_msg.count = msg->send_len; + } + if(msg->recv_buf) + { + spi_rx_msg.ptr_buff = msg->recv_buf; + spi_rx_msg.buff_len = msg->recv_len; + spi_rx_msg.count = msg->recv_len; + } + +} +static void spi_rxint_enable(UINT8 val) +{ + UINT32 value; + + value = REG_READ(SPI_CTRL); + if(val == 0) + { + value &= ~RXINT_EN; + } + else if(val == 1) + { + value |= RXINT_EN; + } + REG_WRITE(SPI_CTRL, value); + spi_config.rx_int = val; + +} + +static void spi_txint_enable(UINT8 val) +{ + UINT32 value; + + value = REG_READ(SPI_CTRL); + if(val == 0) + { + value &= ~TXINT_EN; + } + else if(val == 1) + { + value |= TXINT_EN; + } + REG_WRITE(SPI_CTRL, value); + spi_config.tx_int = val; +} + +static void spi_rxovr_enable(UINT8 val) +{ + UINT32 value; + + value = REG_READ(SPI_CTRL); + if(val == 0) + { + value &= ~RXOVR_EN; + } + else if(val == 1) + { + value |= RXOVR_EN; + } + REG_WRITE(SPI_CTRL, value); + spi_config.rxovr_int = val; +} + +static void spi_txovr_enable(UINT8 val) +{ + UINT32 value; + + value = REG_READ(SPI_CTRL); + if(val == 0) + { + value &= ~TXOVR_EN; + } + else if(val == 1) + { + value |= TXOVR_EN; + } + REG_WRITE(SPI_CTRL, value); + spi_config.txovr_int = val; +} + +#if ((CFG_SOC_NAME != SOC_BK7231U ) && (CFG_SOC_NAME != SOC_BK7231N )) +static void spi_rxfifo_clr(void) +{ + UINT32 value; + + value = REG_READ(SPI_CTRL); + value |= RXFIFO_CLR; + REG_WRITE(SPI_CTRL, value); + +} + +static void spi_txfifo_clr(void) +{ + UINT32 value; + + value = REG_READ(SPI_CTRL); + value |= RXFIFO_CLR; + REG_WRITE(SPI_CTRL, value); +} +#endif + +static void spi_txint_mode(UINT8 val) +{ + UINT32 value; +#if ((CFG_SOC_NAME == SOC_BK7231U)|| (CFG_SOC_NAME == SOC_BK7231N)) + value = REG_READ(SPI_CTRL); + value &= ~(TXINT_MODE_MASK<callback; + spi_receive_end_callback.param = callback->param; + } + break; + case CMD_SPI_SET_TX_FINISH_CALLBACK: + { + struct spi_callback_des *callback = (struct spi_callback_des *)param; + spi_tx_end_callback.callback=callback->callback; + spi_tx_end_callback.param=callback->param; + } + break; + case CMD_SPI_RXOVR_EN: + spi_rxovr_enable(*(UINT8 *)param); + break; + case CMD_SPI_TXOVR_EN: + spi_txovr_enable(*(UINT8 *)param); + break; + #if ((CFG_SOC_NAME != SOC_BK7231U ) && (CFG_SOC_NAME != SOC_BK7231N )) + case CMD_SPI_RXFIFO_CLR: + spi_rxfifo_clr(); + break; + case CMD_SPI_TXFIFO_CLR: + spi_txfifo_clr(); + break; + #endif + case CMD_SPI_RXINT_MODE: + spi_rxint_mode(*(UINT8 *)param); + break; + case CMD_SPI_TXINT_MODE: + spi_txint_mode(*(UINT8 *)param); + break; +// case CMD_SPI_START_TRANS: +// spi_trans_start(*(UINT8 *)param); +// break; + case CMD_SPI_INIT_MSTEN: + spi_init_msten(*(UINT8 *)param); + break; + case CMD_SPI_DEINIT_MSTEN: + spi_deinit_msten(); + break; + case CMD_SPI_GET_BUSY: +#if (CFG_SOC_NAME != SOC_BK7231N) + (*((UINT8 *)param)) = spi_get_busy(); +#endif + break; + case CMD_SPI_SET_BUFF: + + spi_set_tx_buff((struct spi_message *)param); + break; +#if (CFG_SOC_NAME == SOC_BK7231N) + case CMD_SPI_LSB_EN: + spi_lsb_enbale(*(UINT8 *)param); + break; + case CMD_SPI_TX_EN: + spi_tx_enbale(*(UINT8 *)param); + break; + case CMD_SPI_RX_EN: + spi_rx_enbale(*(UINT8 *)param); + break; + case CMD_SPI_TXFINISH_EN: + spi_txfinish_enbale(*(UINT8 *)param); + break; + case CMD_SPI_RXFINISH_EN: + spi_rxfinish_enbale(*(UINT8 *)param); + break; + case CMD_SPI_TXTRANS_EN: + set_txtrans_len(*(UINT32 *)param); + break; + case CMD_SPI_RXTRANS_EN: + set_rxtrans_len(*(UINT32 *)param); + break; + case CMD_SPI_CS_EN: + spi_slave_set_cs_finish_interrupt(*(UINT32 *)param); + break; +#endif + + default: + ret = SPI_FAILURE; + break; + } + + peri_busy_count_dec(); + + return ret; +} + + + + +void spi_isr(void) +{ + UINT32 status, slv_status; + volatile UINT8 fifo_empty_num, data_num, rxfifo_empty; + UINT32 rx_date; + //REG_WRITE((0x00802800+(19*4)), 0x02); + //REG_WRITE((0x00802800+(0x1a*4)), 0x02); + //REG_WRITE((0x00802800+(0x1a*4)), 0x00); + + data_num = 0; /*fix warning by clang analyzer*/ + fifo_empty_num = 0; /*fix warning by clang analyzer*/ + +#if (CFG_SOC_NAME != SOC_BK7231N) + status = REG_READ(SPI_STAT); + slv_status = REG_READ(SPI_SLAVE_CTRL); + REG_WRITE(SPI_SLAVE_CTRL, slv_status); +#else + status = REG_READ(SPI_STAT); +// REG_WRITE(SPI_STAT, status); +#endif + REG_WRITE(SPI_STAT, status); + + BK_SPI_PRT("SPI_STAT:0x%08x\r\n", status); + //REG_WRITE((0x00802800+(19*4)), 0x00); + +#if (CFG_SOC_NAME != SOC_BK7231N) + if((status & RXINT) || (slv_status & SPI_S_CS_UP_INT_STATUS)) +#else + if( (status & RXINT) || (status & SPI_S_CS_UP_INT_STATUS) ) +#endif + { + + do{ + rx_date= REG_READ(SPI_DAT); + if(spi_rx_msg.count) + { + if(spi_rx_msg.ptr_buff) + { + *(spi_rx_msg.ptr_buff) = rx_date; + spi_rx_msg.ptr_buff++; + spi_rx_msg.count--; + } + + } + else + { + spi_rxint_enable(0); + break; + + } + + } + #if (CFG_SOC_NAME != SOC_BK7231N) + while((REG_READ(SPI_STAT) & RXFIFO_EMPTY) == 0); + #else + while(REG_READ(SPI_STAT) & RXFIFO_RD_READ); + #endif + if(spi_rx_msg.count==0) + { + spi_rxint_enable(0); + if(spi_receive_end_callback.callback) + spi_receive_end_callback.callback(0); + } + + } + + if(status & TXINT) + { + //REG_WRITE((0x00802800+(0x1c*4)), 0x02); + //REG_WRITE((0x00802800+(0x1c*4)), 0x00); + //os_printf("spi txint\r\n"); + + do{ + BK_SPI_PRT("Count:%d \r\n",spi_tx_msg.count); + if(spi_tx_msg.count) + { + + if(spi_tx_msg.ptr_buff) + { + REG_READ(SPI_DAT) = *(spi_tx_msg.ptr_buff); + spi_tx_msg.ptr_buff++; + + } + spi_tx_msg.count--; + } + else + { + spi_txint_enable(0); + break; + + } + + } + #if (CFG_SOC_NAME != SOC_BK7231N) + while((REG_READ(SPI_STAT) & TXFIFO_EMPTY)); + #else + while(REG_READ(SPI_STAT) & TXFIFO_WR_READ); + #endif + if (spi_tx_end_callback.callback != 0) + { + void *param = spi_tx_end_callback.param; + spi_tx_end_callback.callback( param); + } + else + { + /*fill txfifo with 0xff*/ + //spi_txfifo_fill(); + } + + } + + if(status & TXOVR) + { + os_printf("txovr\r\n"); + } + + if(status & RXOVR) + { + os_printf("rxovr\r\n"); + } + +#if (CFG_SOC_NAME == SOC_BK7231N) + if(status & RX_FINISH_INT) + { + os_printf("rx finish int \r\n"); + } +#endif + +#if (CFG_SOC_NAME != SOC_BK7231N) + if(status & MODF) + { + os_printf("spi mode error\r\n"); + } +#endif + +//#if (CFG_SOC_NAME != SOC_BK7231N) +// if(status & TXFIFO_EMPTY) +//#else +// if(status & TXFIFO_WR_READ) +//#endif +// { +// if (spi_tx_end_callback.callback != 0) +// { +// void *param = spi_tx_end_callback.param; +// uint8_t disenable=0; +// spi_ctrl(CMD_SPI_TX_EN, &disenable); +// spi_tx_end_callback.callback(0, param); +// } +// else +// { +// /*fill txfifo with 0xff*/ +// //spi_txfifo_fill(); +// } +// } +} +// eof + + +// eof + diff --git a/beken_os/beken378/driver/spi/spi.h b/beken_os/beken378/driver/spi/spi.h new file mode 100755 index 0000000..bc29c31 --- /dev/null +++ b/beken_os/beken378/driver/spi/spi.h @@ -0,0 +1,202 @@ +#ifndef _SPI_H_ +#define _SPI_H_ + +#define SPI_DEBUG + +#ifdef SPI_DEBUG +#define SPI_PRT os_printf +#define SPI_WARN warning_prf +#define SPI_FATAL fatal_prf +#else +#define SPI_PRT null_prf +#define SPI_WARN null_prf +#define SPI_FATAL null_prf +#endif + +#define SPI_BASE (0x00802700) + +#if (CFG_SOC_NAME == SOC_BK7231N) +#define SPI_CTRL (SPI_BASE + 0 * 4) + +#define TXINT_MODE_POSI 0 +#define TXINT_MODE_MASK (0x03UL << 0) +#define TXINT_MODE_1 (0x00UL << 0) +#define TXINT_MODE_16 (0x01UL << 0) +#define TXINT_MODE_32 (0x02UL << 0) +#define TXINT_MODE_48 (0x03UL << 0) + +#define RXINT_MODE_POSI 2 +#define RXINT_MODE_MASK (0x03UL << 2) +#define RXINT_MODE_1 (0x00UL << 2) +#define RXINT_MODE_16 (0x01UL << 2) +#define RXINT_MODE_32 (0x02UL << 2) +#define RXINT_MODE_48 (0x03UL << 2) +#define TXOVR_EN (0x01UL << 4) +#define RXOVR_EN (0x01UL << 5) +#define TXINT_EN (0x01UL << 6) +#define RXINT_EN (0x01UL << 7) +#define SPI_CKR_POSI (8) +#define SPI_CKR_MASK (0xFF) +#define SPI_S_CS_UP_INT_EN (0x01UL << 16) +#define CTRL_NSSMD_4 (0x00UL << 17) +#define CTRL_NSSMD_3 (0x01UL << 17) +#define BIT_WDTH (0x01UL << 18) +#define LSB_FIRST (0x01UL << 19) +#define MSB_FIRST (0x00UL << 19) +#define CKPOL (0x01UL << 20) +#define CKPHA (0x01UL << 21) +#define MSTEN (0x01UL << 22) +#define SPIEN (0x01UL << 23) + + +#define SPI_CONFIG (SPI_BASE + 0x1 * 4) +#define SPI_TX_EN (0x01UL << 0) +#define SPI_RX_EN (0x01UL << 1) +#define SPI_TX_FINISH_EN (0x01UL << 2) +#define SPI_RX_FINISH_EN (0x01UL << 3) +#define SPI_TX_TRAHS_LEN_POSI 8 +#define SPI_RX_TRAHS_LEN_POSI 20 + + +#define SPI_STAT (SPI_BASE + 0x2 * 4) +#define SPI_STAT_RXFIFO_RD_POSI 1 +#define SPI_STAT_TXFIFO_WR_POSI 2 +#define TXFIFO_WR_READ (0x01UL << 1) +#define RXFIFO_RD_READ (0x01UL << 2) +#define TXINT (0x01UL << 8) +#define RXINT (0x01UL << 9) +#define SPI_S_CS_UP_INT_STATUS (0x01UL << 10) +#define TXOVR (0x01UL << 11) +#define RXOVR (0x01UL << 12) +#define TX_FINISH_INT (0x01UL << 13) +#define RX_FINISH_INT (0x01UL << 14) +#define TXFIFO_CLR_EN (0x01UL << 16) +#define RXFIFO_CLR_EN (0x01UL << 17) + + +#define SPI_DAT (SPI_BASE + 3 * 4) +#define SPI_DAT_POSI (0) +#define SPI_DAT_MASK (0xFFFF) + +#elif (CFG_SOC_NAME == SOC_BK7231U) +#define SPI_CTRL (SPI_BASE + 0 * 4) +#define TXINT_MODE_POSI (0) +#define TXINT_MODE_MASK (0x3) +#define RXINT_MODE_POSI (2) +#define RXINT_MODE_MASK (0x3) +#define TXINT_MODE (0x01UL << 0) +#define RXINT_MODE (0x01UL << 2) +#define TXOVR_EN (0x01UL << 4) +#define RXOVR_EN (0x01UL << 5) +#define TXINT_EN (0x01UL << 6) +#define RXINT_EN (0x01UL << 7) +#define SPI_CKR_POSI (8) +#define SPI_CKR_MASK (0xFF) +#define NSSMD_POSI (16) +#define NSSMD_MASK (0x3) +#define BIT_WDTH (0x01UL << 18) +#define CKPOL (0x01UL << 20) +#define CKPHA (0x01UL << 21) +#define MSTEN (0x01UL << 22) +#define SPIEN (0x01UL << 23) + +#define SPI_STAT (SPI_BASE + 1 * 4) +#define TXFIFO_EMPTY (0x01UL << 0) +#define TXFIFO_FULL (0x01UL << 1) +#define RXFIFO_EMPTY (0x01UL << 2) +#define RXFIFO_FULL (0x01UL << 3) +#define TXINT (0x01UL << 8) +#define RXINT (0x01UL << 9) +#define MODF (0x01UL << 10) +#define TXOVR (0x01UL << 11) +#define RXOVR (0x01UL << 12) +#define SLVSEL (0x01UL << 14) +#define SPIBUSY (0x01UL << 15) + +#define SPI_DAT (SPI_BASE + 2 * 4) +#define SPI_DAT_POSI (0) +#define SPI_DAT_MASK (0xFFFF) + +#define SPI_SLAVE_CTRL (SPI_BASE + 3 * 4) +#define SPI_S_CS_UP_INT_EN (0x01UL << 1) +#define SPI_S_CS_UP_INT_STATUS (0x01UL << 4) + + +#else +#define SPI_CTRL (SPI_BASE + 0 * 4) +#define TXINT_MODE_POSI (0) +#define TXINT_MODE_MASK (0x3) +#define RXINT_MODE_POSI (2) +#define RXINT_MODE_MASK (0x3) +#define TXINT_MODE (0x01UL << 0) +#define RXINT_MODE (0x01UL << 1) +#define TXFIFO_CLR (0x01UL << 2) +#define RXFIFO_CLR (0x01UL << 3) +#define TXOVR_EN (0x01UL << 4) +#define RXOVR_EN (0x01UL << 5) +#define TXINT_EN (0x01UL << 6) +#define RXINT_EN (0x01UL << 7) +#define SPI_CKR_POSI (8) +#define SPI_CKR_MASK (0xFF) +#define NSSMD_POSI (16) +#define NSSMD_MASK (0x3) +#define BIT_WDTH (0x01UL << 18) +#define CKPOL (0x01UL << 20) +#define CKPHA (0x01UL << 21) +#define MSTEN (0x01UL << 22) +#define SPIEN (0x01UL << 23) + +#define SPI_STAT (SPI_BASE + 1 * 4) +#define TXFIFO_EMPTY (0x01UL << 0) +#define TXFIFO_FULL (0x01UL << 1) +#define RXFIFO_EMPTY (0x01UL << 2) +#define RXFIFO_FULL (0x01UL << 3) +#define TXINT (0x01UL << 8) +#define RXINT (0x01UL << 9) +#define MODF (0x01UL << 10) +#define TXOVR (0x01UL << 11) +#define RXOVR (0x01UL << 12) +#define SLVSEL (0x01UL << 14) +#define SPIBUSY (0x01UL << 15) + +#define SPI_DAT (SPI_BASE + 2 * 4) +#define SPI_DAT_POSI (0) +#define SPI_DAT_MASK (0xFFFF) + +#define SPI_SLAVE_CTRL (SPI_BASE + 3 * 4) +#define SPI_S_CS_UP_INT_EN (0x01UL << 1) +#define SPI_S_CS_UP_INT_STATUS (0x01UL << 4) + +#endif + + +typedef struct +{ + UINT32 rate; + UINT32 slave_cs_int:1; + UINT32 tx_int:1; + UINT32 tx_int_mode:2; + UINT32 txovr_int:1; + UINT32 rx_int:1; + UINT32 rx_int_mode:2; + UINT32 rxovr_int:1; + UINT32 master:1; + UINT32 nss_mode:2; + UINT32 ck_mode:2; + UINT32 bit_wdth:1; + UINT32 init_ok:1; + UINT32 undef:16; +} spi_config_t; +typedef struct +{ + + uint32_t count; + uint32_t buff_len; + uint8_t *ptr_buff; +} spi_message_t; + +/******************************************************************************* +* Function Declarations +*******************************************************************************/ +UINT32 spi_ctrl(UINT32 cmd, void *param); +#endif //_SPI_H_ diff --git a/beken_os/beken378/driver/spi/spi_bk7231n.c b/beken_os/beken378/driver/spi/spi_bk7231n.c new file mode 100755 index 0000000..1812b6d --- /dev/null +++ b/beken_os/beken378/driver/spi/spi_bk7231n.c @@ -0,0 +1,699 @@ +#include "include.h" +#include "arm_arch.h" +#include "sys_config.h" + +#if (CFG_SOC_NAME == SOC_BK7231N) +#include "spi_pub.h" +#include "drv_model_pub.h" +#include "intc_pub.h" +#include "mcu_ps_pub.h" +#include "icu_pub.h" +#include "gpio_pub.h" +#include "uart_pub.h" +#include "spi_bk7231n.h" + +#define SPI_PERI_CLK_26M (26 * 1000 * 1000) +#define SPI_PERI_CLK_DCO (120 * 1000 * 1000) + +static SDD_OPERATIONS spi_op = { + spi_ctrl +}; + +static void spi_active(BOOLEAN val) +{ + UINT32 value; + + value = REG_READ(SPI_CTRL); + if (val == 0) + value &= ~SPIEN; + else if (val == 1) + value |= SPIEN; + REG_WRITE(SPI_CTRL, value); +} + +static void spi_set_msten(UINT8 val) +{ + UINT32 value; + + value = REG_READ(SPI_CTRL); + if (val == 0) + value &= ~MSTEN; + else if (val == 1) + value |= MSTEN; + REG_WRITE(SPI_CTRL, value); +} + +static void spi_set_ckpha(UINT8 val) +{ + UINT32 value; + + value = REG_READ(SPI_CTRL); + if (val == 0) + value &= ~CKPHA; + else if (val == 1) + value |= CKPHA; + REG_WRITE(SPI_CTRL, value); +} + +static void spi_set_skpol(UINT8 val) +{ + UINT32 value; + + value = REG_READ(SPI_CTRL); + if (val == 0) + value &= ~CKPOL; + else if (val == 1) + value |= CKPOL; + REG_WRITE(SPI_CTRL, value); +} + +static void spi_set_bit_wdth(UINT8 val) +{ + UINT32 value; + + value = REG_READ(SPI_CTRL); + if (val == 0) + value &= ~BIT_WDTH; + else if (val == 1) + value |= BIT_WDTH; + REG_WRITE(SPI_CTRL, value); +} + +static void spi_set_nssmd(UINT8 val) +{ + UINT32 value; + + value = REG_READ(SPI_CTRL); + value &= ~CTRL_NSSMD_3; + value |= (val << 17); + REG_WRITE(SPI_CTRL, value); + +} + +static void spi_set_clock(UINT32 max_hz) +{ + int source_clk = 0; + int spi_clk = 0; + int div = 0; + UINT32 param; + //os_printf("\rmax_hz :%d\r\n", max_hz); + + if ((max_hz == 26000000) || (max_hz == 13000000) || (max_hz == 6500000)) { + BK_SPI_PRT("config spi clk 26MHz\n"); + + spi_clk = max_hz; + +#if CFG_XTAL_FREQUENCE + + source_clk = CFG_XTAL_FREQUENCE; +#else + source_clk = SPI_PERI_CLK_26M; +#endif + param = PCLK_POSI_SPI; + sddev_control(ICU_DEV_NAME, CMD_CONF_PCLK_26M, ¶m); + } else if (max_hz > 4333000) { + BK_SPI_PRT("config spi clk source DCO\n"); + + if (max_hz > 30000000) { // 120M/2 / (2 + 1) = 30M + spi_clk = 30000000; + BK_SPI_PRT("input clk > 30MHz, set input clk = 30MHz\n"); + } else + spi_clk = max_hz; + sddev_control(ICU_DEV_NAME, CMD_CLK_PWR_DOWN, ¶m); + source_clk = SPI_PERI_CLK_DCO; + param = PCLK_POSI_SPI; + sddev_control(ICU_DEV_NAME, CMD_CONF_PCLK_DCO, ¶m); + param = PWD_SPI_CLK_BIT; + sddev_control(ICU_DEV_NAME, CMD_CLK_PWR_UP, ¶m); + } else { + BK_SPI_PRT("config spi clk source 26MHz\n"); + + spi_clk = max_hz; +#if CFG_XTAL_FREQUENCE + source_clk = CFG_XTAL_FREQUENCE; +#else + source_clk = SPI_PERI_CLK_26M; +#endif + + param = PCLK_POSI_SPI; + sddev_control(ICU_DEV_NAME, CMD_CONF_PCLK_26M, ¶m); + } + if ((max_hz == 26000000) || (max_hz == 13000000) || (max_hz == 6500000)) + div = source_clk / spi_clk - 1; + else { + // spi_clk = in_clk / (2 * (div + 1)) + div = ((source_clk >> 1) / spi_clk); + + if (div < 2) + div = 2; + else if (div >= 255) + div = 255; + } + + param = REG_READ(SPI_CTRL); + param &= ~(SPI_CKR_MASK << SPI_CKR_POSI); + param |= (div << SPI_CKR_POSI); + REG_WRITE(SPI_CTRL, param); + + BK_SPI_PRT("\rdiv = %d \r\n", div); + BK_SPI_PRT("\rspi_clk = %d \r\n", spi_clk); + BK_SPI_PRT("\rsource_clk = %d \r\n", source_clk); + BK_SPI_PRT("\rtarget frequency = %d, actual frequency = %d \r\n", max_hz, source_clk / 2 / div); +} + + +static void spi_rxint_enable(UINT8 val) +{ + UINT32 value; + + value = REG_READ(SPI_CTRL); + if (val == 0) + value &= ~RXINT_EN; + else if (val == 1) + value |= RXINT_EN; + REG_WRITE(SPI_CTRL, value); +} + +static void spi_txint_enable(UINT8 val) +{ + UINT32 value; + + value = REG_READ(SPI_CTRL); + if (val == 0) + value &= ~TXINT_EN; + else if (val == 1) + value |= TXINT_EN; + REG_WRITE(SPI_CTRL, value); +} + +static void spi_rxovr_enable(UINT8 val) +{ + UINT32 value; + + value = REG_READ(SPI_CTRL); + if (val == 0) + value &= ~RXOVR_EN; + else if (val == 1) + value |= RXOVR_EN; + REG_WRITE(SPI_CTRL, value); +} + +static void spi_txovr_enable(UINT8 val) +{ + UINT32 value; + + value = REG_READ(SPI_CTRL); + if (val == 0) + value &= ~TXOVR_EN; + else if (val == 1) + value |= TXOVR_EN; + REG_WRITE(SPI_CTRL, value); +} + +static void spi_rxint_mode(UINT8 val) +{ + UINT32 value; + + value = REG_READ(SPI_CTRL); + + value &= ~(RXINT_MODE_MASK << RXINT_MODE_POSI); + value |= ((val & RXINT_MODE_MASK) << RXINT_MODE_POSI); + + REG_WRITE(SPI_CTRL, value); +} + +static void spi_txint_mode(UINT8 val) +{ + UINT32 value; + + value = REG_READ(SPI_CTRL); + + value &= ~(TXINT_MODE_MASK << TXINT_MODE_POSI); + value |= ((val & TXINT_MODE_MASK) << TXINT_MODE_POSI); + + REG_WRITE(SPI_CTRL, value); +} + +static void spi_slave_set_cs_finish_interrupt(UINT32 enable) +{ + UINT32 value; + + value = REG_READ(SPI_CTRL); + if (enable) + value |= SPI_S_CS_UP_INT_EN; + else + value &= ~(SPI_S_CS_UP_INT_EN); + REG_WRITE(SPI_CTRL, value); + + // don't clean cs finish status + value = REG_READ(SPI_STAT); + value &= ~(SPI_S_CS_UP_INT_STATUS); + REG_WRITE(SPI_STAT, value); +} + +static void spi_gpio_configuration(void) +{ + uint32_t val; + +#if (USE_SPI_GPIO_NUM == USE_SPI_GPIO_14_17) + val = GFUNC_MODE_SPI; +#elif (USE_SPI_GPIO_NUM == USE_SPI_GPIO_30_33) + val = GFUNC_MODE_SPI1; +#else +#error "USE_SPI_GPIO_NUM must set to gpio14-17 or gpio30-33" +#endif + sddev_control(GPIO_DEV_NAME, CMD_GPIO_ENABLE_SECOND, &val); +} + +static void spi_3_line_gpio_configuration(void) +{ + uint32_t val; + + val = GFUNC_MODE_SPI_USE_GPIO_14; + sddev_control(GPIO_DEV_NAME, CMD_GPIO_ENABLE_SECOND, &val); + + val = GFUNC_MODE_SPI_USE_GPIO_16_17; + sddev_control(GPIO_DEV_NAME, CMD_GPIO_ENABLE_SECOND, &val); + } + +static void spi_icu_configuration(UINT32 enable) +{ + UINT32 param; + + if (enable) { + param = PWD_SPI_CLK_BIT; + sddev_control(ICU_DEV_NAME, CMD_CLK_PWR_UP, ¶m); + + param = (IRQ_SPI_BIT); + sddev_control(ICU_DEV_NAME, CMD_ICU_INT_ENABLE, ¶m); + } else { + param = (IRQ_SPI_BIT); + sddev_control(ICU_DEV_NAME, CMD_ICU_INT_DISABLE, ¶m); + + param = PWD_SPI_CLK_BIT; + sddev_control(ICU_DEV_NAME, CMD_CLK_PWR_DOWN, ¶m); + } +} + +static void spi_lsb_enbale(UINT8 val) +{ + UINT32 value; + + value = REG_READ(SPI_CTRL); + if (val == 0) + value &= ~LSB_FIRST; + else if (val == 1) + value |= LSB_FIRST; + REG_WRITE(SPI_CTRL, value); +} + + +static void spi_tx_enbale(UINT8 val) +{ + UINT32 value; + + value = REG_READ(SPI_CONFIG); + if (val == 0) + value &= ~SPI_TX_EN; + else if (val == 1) + value |= SPI_TX_EN; + REG_WRITE(SPI_CONFIG, value); +} + +static void spi_rx_enbale(UINT8 val) +{ + UINT32 value; + + value = REG_READ(SPI_CONFIG); + if (val == 0) + value &= ~SPI_RX_EN; + else if (val == 1) + value |= SPI_RX_EN; + REG_WRITE(SPI_CONFIG, value); +} + +static void spi_txfinish_enbale(UINT8 val) +{ + UINT32 value; + + value = REG_READ(SPI_CONFIG); + if (val == 0) + value &= ~SPI_TX_FINISH_EN; + else if (val == 1) + value |= SPI_TX_FINISH_EN; + REG_WRITE(SPI_CONFIG, value); +} + +static void spi_rxfinish_enbale(UINT8 val) +{ + UINT32 value; + + value = REG_READ(SPI_CONFIG); + if (val == 0) + value &= ~SPI_RX_FINISH_EN; + else if (val == 1) + value |= SPI_RX_FINISH_EN; + REG_WRITE(SPI_CONFIG, value); + +} + +void set_txtrans_len(UINT32 val) +{ + UINT32 value; + + value = REG_READ(SPI_CONFIG); + + value &= ~(0xFFF << SPI_TX_TRAHS_LEN_POSI); + value |= ((val & 0xFFF) << SPI_TX_TRAHS_LEN_POSI); + + REG_WRITE(SPI_CONFIG, value); +} + +void set_rxtrans_len(UINT32 val) +{ + UINT32 value; + + value = REG_READ(SPI_CONFIG); + + value &= ~(0xFFF << SPI_RX_TRAHS_LEN_POSI); + value |= ((val & 0xFFF) << SPI_RX_TRAHS_LEN_POSI); + + REG_WRITE(SPI_CONFIG, value); +} + +static void spi_init_msten(UINT8 param) +{ + UINT32 value = 0; + UINT8 msten = (param & 0x0F); + + value = REG_READ(SPI_CTRL); + value &= ~((TXINT_MODE_MASK << TXINT_MODE_POSI) | (RXINT_MODE_MASK << RXINT_MODE_POSI)); + + value |= RXOVR_EN + | TXOVR_EN; + //| (0x3UL << RXINT_MODE_POSI) // fifo_level :32 + //| (0x3UL << TXINT_MODE_POSI); // fifo_level :32 + + REG_WRITE(SPI_CTRL, value); + if (msten == 0) + spi_slave_set_cs_finish_interrupt(1); + else + spi_slave_set_cs_finish_interrupt(0); + + spi_icu_configuration(1); + spi_gpio_configuration(); +} + +static void spi_deinit_msten(void) +{ + UINT32 status; + + spi_icu_configuration(0); + + REG_WRITE(SPI_CTRL, 0); + + status = REG_READ(SPI_STAT); + REG_WRITE(SPI_STAT, status); +} + +static void spi_rxfifo_clr(void) +{ + UINT32 value; + + value = REG_READ(SPI_STAT); + + while (value & RXFIFO_RD_READ) { + REG_READ(SPI_DAT); + value = REG_READ(SPI_STAT); + } +} + +UINT32 spi_read_rxfifo(UINT8 *data) +{ + UINT32 value; + + value = REG_READ(SPI_STAT); + + if (value & RXFIFO_RD_READ) { + value = REG_READ(SPI_DAT); + if (data) + *data = value; + return 1; + } + + return 0; +} + +UINT32 spi_write_txfifo(UINT8 data) +{ + UINT32 value; + + value = REG_READ(SPI_STAT); + + if (value & TXFIFO_WR_READ) { + REG_WRITE(SPI_DAT, data); + return 1; + } + + return 0; +} + +static struct spi_callback_des spi_receive_callback = {NULL, NULL}; +static struct spi_callback_des spi_txfifo_needwr_callback = {NULL, NULL}; +static struct spi_callback_des spi_tx_end_callback = {NULL, NULL}; +static void (*spi_tx_finish_callback)(UINT32)=NULL; +static void (*spi_rx_finish_callback)(UINT32)=NULL; + +static void spi_rx_callback_set(spi_callback callback, void *param) +{ + spi_receive_callback.callback = callback; + spi_receive_callback.param = param; +} + +static void spi_tx_fifo_needwr_callback_set(spi_callback callback, void *param) +{ + spi_txfifo_needwr_callback.callback = callback; + spi_txfifo_needwr_callback.param = param; +} + +static void spi_tx_end_callback_set(spi_callback callback, void *param) +{ + spi_tx_end_callback.callback = callback; + spi_tx_end_callback.param = param; +} +void spi_rx_finnsh_int_callback_set(void (*func)(UINT32)) +{ + spi_rx_finish_callback = func; +} +void spi_tx_finnsh_int_callback_set(void (*func)(UINT32)) +{ + spi_tx_finish_callback = func; +} + + +void spi_init(void) +{ + intc_service_register(IRQ_SPI, PRI_IRQ_SPI, spi_isr); + + sddev_register_dev(SPI_DEV_NAME, &spi_op); +} + +void spi_exit(void) +{ + sddev_unregister_dev(SPI_DEV_NAME); +} + +UINT32 spi_ctrl(UINT32 cmd, void *param) +{ + UINT32 ret = SPI_SUCCESS; + + peri_busy_count_add(); + + switch (cmd) { + case CMD_SPI_UNIT_ENABLE: + spi_active(*(UINT8 *)param); + break; + case CMD_SPI_SET_MSTEN: + spi_set_msten(*(UINT8 *)param); + break; + case CMD_SPI_SET_CKPHA: + spi_set_ckpha(*(UINT8 *)param); + break; + case CMD_SPI_SET_CKPOL: + spi_set_skpol(*(UINT8 *)param); + break; + case CMD_SPI_SET_BITWIDTH: + spi_set_bit_wdth(*(UINT8 *)param); + break; + case CMD_SPI_SET_NSSMD: + spi_set_nssmd(*(UINT8 *)param); + break; + case CMD_SPI_SET_CKR: + spi_set_clock(*(UINT32 *)param); + break; + case CMD_SPI_RXINT_EN: + spi_rxint_enable(*(UINT8 *)param); + break; + case CMD_SPI_TXINT_EN: + spi_txint_enable(*(UINT8 *)param); + break; + case CMD_SPI_RXOVR_EN: + spi_rxovr_enable(*(UINT8 *)param); + break; + case CMD_SPI_TXOVR_EN: + spi_txovr_enable(*(UINT8 *)param); + break; + case CMD_SPI_RXFIFO_CLR: + spi_rxfifo_clr(); + break; + case CMD_SPI_RXINT_MODE: + spi_rxint_mode(*(UINT8 *)param); + break; + case CMD_SPI_TXINT_MODE: + spi_txint_mode(*(UINT8 *)param); + break; + case CMD_SPI_INIT_MSTEN: + spi_init_msten(*(UINT8 *)param); + break; + case CMD_SPI_GET_BUSY: + + break; + case CMD_SPI_SET_RX_CALLBACK: { + struct spi_callback_des *callback = (struct spi_callback_des *)param; + spi_rx_callback_set(callback->callback, callback->param); + } + break; + case CMD_SPI_SET_TX_NEED_WRITE_CALLBACK: { + struct spi_callback_des *callback = (struct spi_callback_des *)param; + spi_tx_fifo_needwr_callback_set(callback->callback, callback->param); + } + break; + case CMD_SPI_SET_TX_FINISH_CALLBACK: { + struct spi_callback_des *callback = (struct spi_callback_des *)param; + spi_tx_end_callback_set(callback->callback, callback->param); + } + break; + case CMD_SPI_DEINIT_MSTEN: + spi_deinit_msten(); + break; + case CMD_SPI_LSB_EN: + spi_lsb_enbale(*(UINT8 *)param); + break; + case CMD_SPI_TX_EN: + spi_tx_enbale(*(UINT8 *)param); + break; + case CMD_SPI_RX_EN: + spi_rx_enbale(*(UINT8 *)param); + break; + case CMD_SPI_TXFINISH_EN: + spi_txfinish_enbale(*(UINT8 *)param); + break; + case CMD_SPI_RXFINISH_EN: + spi_rxfinish_enbale(*(UINT8 *)param); + break; + case CMD_SPI_TXTRANS_EN: + set_txtrans_len(*(UINT32 *)param); + break; + case CMD_SPI_RXTRANS_EN: + set_rxtrans_len(*(UINT32 *)param); + break; + case CMD_SPI_CS_EN: + spi_slave_set_cs_finish_interrupt(*(UINT32 *)param); + break; + case CMD_SPI_SET_TX_FINISH_INT_CALLBACK: + spi_tx_finnsh_int_callback_set((void (*)(UINT32))(param)); + break; + case CMD_SPI_SET_RX_FINISH_INT_CALLBACK: + spi_rx_finnsh_int_callback_set((void (*)(UINT32))(param)); + break; + case CMD_SPI_SET_3_LINE: + spi_3_line_gpio_configuration(); + break; + + default: + ret = SPI_FAILURE; + break; + } + + peri_busy_count_dec(); + + return ret; +} + +void spi_isr(void) +{ + UINT32 status; + status = REG_READ(SPI_STAT); + REG_WRITE(SPI_STAT, status); + + if ((status & RXINT) || (status & SPI_S_CS_UP_INT_STATUS)) { + REG_WRITE((0x00802800 + (0x18 * 4)), 0x02); + + if (spi_receive_callback.callback != 0) { + REG_WRITE((0x00802800 + (0x1a * 4)), 0x02); + REG_WRITE((0x00802800 + (0x1a * 4)), 0x00); + + void *param = spi_receive_callback.param; + int is_rx_end = (status & SPI_S_CS_UP_INT_STATUS) ? 1 : 0; + spi_receive_callback.callback(is_rx_end, param); + } else { + /*drop data*/ + spi_rxfifo_clr(); + } + + REG_WRITE((0x00802800 + (0x18 * 4)), 0x00); + } + + if (status & TXINT) { + os_printf("spi txint\r\n"); + + if (spi_txfifo_needwr_callback.callback != 0) { + void *param = spi_txfifo_needwr_callback.param; + + spi_txfifo_needwr_callback.callback(0, param); + } else { + /*fill txfifo with 0xff*/ + //spi_txfifo_fill(); + } + } + + if (status & TXOVR) + os_printf("txovr\r\n"); + + if (status & RXOVR) + os_printf("rxovr\r\n"); + + if (status & TX_FINISH_INT) + { + // 清发送中断 + spi_tx_enbale(0); + if(spi_tx_finish_callback) + { + spi_tx_finish_callback(0); + } + } + if (status & RX_FINISH_INT) + { + spi_rx_enbale(0); + if(spi_rx_finish_callback) + { + spi_rx_finish_callback(0); + } + + } + //判断是否可写 + // if (status & TXFIFO_WR_READ) { + // os_printf("2\r\n"); + // if (spi_tx_end_callback.callback != 0) { + // void *param = spi_tx_end_callback.param; + // spi_tx_end_callback.callback(0, param); + // } else { + // /*fill txfifo with 0xff*/ + // //spi_txfifo_fill(); + // } + // } +} +// eof +#endif + + diff --git a/beken_os/beken378/driver/spi/spi_bk7231n.h b/beken_os/beken378/driver/spi/spi_bk7231n.h new file mode 100755 index 0000000..c568451 --- /dev/null +++ b/beken_os/beken378/driver/spi/spi_bk7231n.h @@ -0,0 +1,89 @@ +#ifndef _SPI_H_ +#define _SPI_H_ + +#if(CFG_SOC_NAME == SOC_BK7231N) + +#define SPI_DEBUG +#ifdef SPI_DEBUG +#define SPI_PRT os_printf +#define SPI_WARN warning_prf +#define SPI_FATAL fatal_prf +#else +#define SPI_PRT null_prf +#define SPI_WARN null_prf +#define SPI_FATAL null_prf +#endif + +#define SPI_BASE (0x00802700) + +#define SPI_CTRL (SPI_BASE + 0 * 4) +#define TXINT_MODE_POSI 0 +#define TXINT_MODE_MASK (0x03UL << 0) +#define TXINT_MODE_1 (0x00UL << 0) +#define TXINT_MODE_16 (0x01UL << 0) +#define TXINT_MODE_32 (0x02UL << 0) +#define TXINT_MODE_48 (0x03UL << 0) + +#define RXINT_MODE_POSI 2 +#define RXINT_MODE_MASK (0x03UL << 2) +#define RXINT_MODE_1 (0x00UL << 2) +#define RXINT_MODE_16 (0x01UL << 2) +#define RXINT_MODE_32 (0x02UL << 2) +#define RXINT_MODE_48 (0x03UL << 2) +#define TXOVR_EN (0x01UL << 4) +#define RXOVR_EN (0x01UL << 5) +#define TXINT_EN (0x01UL << 6) +#define RXINT_EN (0x01UL << 7) +#define SPI_CKR_POSI (8) +#define SPI_CKR_MASK (0xFF) +#define SPI_S_CS_UP_INT_EN (0x01UL << 16) +#define CTRL_NSSMD_4 (0x00UL << 17) +#define CTRL_NSSMD_3 (0x01UL << 17) +#define BIT_WDTH (0x01UL << 18) +#define LSB_FIRST (0x01UL << 19) +#define MSB_FIRST (0x00UL << 19) +#define CKPOL (0x01UL << 20) +#define CKPHA (0x01UL << 21) +#define MSTEN (0x01UL << 22) +#define SPIEN (0x01UL << 23) + + +#define SPI_CONFIG (SPI_BASE + 0x1 * 4) +#define SPI_TX_EN (0x01UL << 0) +#define SPI_RX_EN (0x01UL << 1) +#define SPI_TX_FINISH_EN (0x01UL << 2) +#define SPI_RX_FINISH_EN (0x01UL << 3) +#define SPI_TX_TRAHS_LEN_POSI 8 +#define SPI_RX_TRAHS_LEN_POSI 20 + + +#define SPI_STAT (SPI_BASE + 0x2 * 4) +#define SPI_STAT_RXFIFO_RD_POSI 1 +#define SPI_STAT_TXFIFO_WR_POSI 2 +#define TXFIFO_WR_READ (0x01UL << 1) +#define RXFIFO_RD_READ (0x01UL << 2) +#define TXINT (0x01UL << 8) +#define RXINT (0x01UL << 9) +#define SPI_S_CS_UP_INT_STATUS (0x01UL << 10) +#define TXOVR (0x01UL << 11) +#define RXOVR (0x01UL << 12) +#define TX_FINISH_INT (0x01UL << 13) +#define RX_FINISH_INT (0x01UL << 14) +#define TXFIFO_CLR_EN (0x01UL << 16) +#define RXFIFO_CLR_EN (0x01UL << 17) + + +#define SPI_DAT (SPI_BASE + 3 * 4) +#define SPI_DAT_POSI (0) +#define SPI_DAT_MASK (0xFFFF) + +/******************************************************************************* +* Function Declarations +*******************************************************************************/ +UINT32 spi_ctrl(UINT32 cmd, void *param); + +#endif //(CFG_SOC_NAME == SOC_BK7231N) +#endif //_SPI_H_ + + + diff --git a/beken_os/beken378/driver/spi/spi_master_bk7231n.c b/beken_os/beken378/driver/spi/spi_master_bk7231n.c new file mode 100755 index 0000000..0c9584f --- /dev/null +++ b/beken_os/beken378/driver/spi/spi_master_bk7231n.c @@ -0,0 +1,892 @@ +#include "include.h" +#include "arm_arch.h" +#include "typedef.h" +#include "arm_arch.h" +#include "sys_config.h" + +#if(CFG_SOC_NAME == SOC_BK7231N) +#include "icu_pub.h" +#include "spi_pub.h" +#include "sys_ctrl_pub.h" +#include "drv_model_pub.h" +#include "mem_pub.h" +#include "rtos_pub.h" +#include "general_dma_pub.h" +#include "general_dma.h" +#include "spi_bk7231n.h" + +#if CFG_USE_SPI_MASTER +struct bk_spi_dev { + UINT8 init_spi:1; + UINT8 init_dma_tx:1; + UINT8 init_dma_rx:1; + UINT8 undef:5; + + UINT8 *tx_ptr; + UINT8 *rx_ptr; + UINT32 tx_len; + UINT32 rx_len; + beken_semaphore_t tx_sem; + beken_semaphore_t rx_sem; + beken_semaphore_t dma_rx_sem; + beken_semaphore_t dma_tx_sem; + beken_mutex_t mutex; + UINT32 rx_offset; + UINT32 rx_drop; + UINT32 total_len; + volatile UINT32 flag; + + + +}; + +static struct bk_spi_dev *spi_dev; + + +static unsigned char isr_mode = 0; //0--- spi中断 1- dma中断 + +static void bk_spi_rx_callback(int is_rx_end, void *param) +{ + UINT8 ch, *rxbuf; + UINT32 offset, drop; + + GLOBAL_INT_DECLARATION(); + + rxbuf = spi_dev->rx_ptr; + drop = spi_dev->rx_drop; + offset = spi_dev->rx_offset; + + while (1) { + if (spi_read_rxfifo(&ch) == 0) + break; + + if (rxbuf) { + if (drop != 0) + drop--; + else { + if (offset < spi_dev->rx_len) { + rxbuf[offset] = ch; + offset++; + } else + BK_SPI_WPRT("rx over flow:%02x, %d\r\n", ch, spi_dev->rx_len); + } + } + } + + GLOBAL_INT_DISABLE(); + spi_dev->rx_drop = drop; + spi_dev->rx_offset = offset; + GLOBAL_INT_RESTORE(); +} + +static void bk_spi_tx_needwrite_callback(int port, void *param) +{ + UINT8 *tx_ptr = spi_dev->tx_ptr, data; + UINT32 tx_len = spi_dev->tx_len, total_len = spi_dev->total_len, tx_ok = 0; + + UINT8 *rxbuf; + UINT32 offset, drop; + + rxbuf = spi_dev->rx_ptr; + drop = spi_dev->rx_drop; + offset = spi_dev->rx_offset; + + GLOBAL_INT_DECLARATION(); + + while (total_len) { + tx_ok = 0; + + if (tx_len) { + data = *tx_ptr; + if (spi_write_txfifo(data) == 1) { + tx_ok = 1; + + tx_len --; + tx_ptr ++; + } + } else { + data = 0xff; + if (spi_write_txfifo(data) == 1) + tx_ok = 1; + } + + /* check rx data to prevent rx over flow */ + if (spi_read_rxfifo(&data) == 1) { + if (rxbuf) { + if (drop != 0) + drop--; + else { + if (offset < spi_dev->rx_len) { + rxbuf[offset] = data; + offset++; + } else + BK_SPI_WPRT("0 rx over flow:%02x, %d\r\n", data, spi_dev->rx_len); + } + } + } + + if (tx_ok == 1) { + total_len --; + if (total_len == 0) { + UINT32 enable = 0; + sddev_control(SPI_DEV_NAME, CMD_SPI_TXINT_EN, (void *)&enable); + BK_SPI_PRT("tx fin\r\n"); + break; + } + } else + break; + } + + GLOBAL_INT_DISABLE(); + spi_dev->tx_ptr = tx_ptr; + spi_dev->tx_len = tx_len; + spi_dev->total_len = total_len; + + spi_dev->rx_drop = drop; + spi_dev->rx_offset = offset; + GLOBAL_INT_RESTORE(); + +} + +static void bk_spi_tx_finish_callback(int port, void *param) +{ + BK_SPI_PRT("%d\r\n",__LINE__); + if ((spi_dev->total_len == 0) && ((spi_dev->flag & TX_FINISH_FLAG) == 0)) { + spi_dev->flag |= TX_FINISH_FLAG; + rtos_set_semaphore(&spi_dev->tx_sem); + BK_SPI_PRT("tx end\r\n"); + } +} + +static void bk_spi_configure(UINT32 rate, UINT32 mode) +{ + UINT32 param; + struct spi_callback_des spi_dev_cb; + + + param = 0; + sddev_control(SPI_DEV_NAME, CMD_SPI_INIT_MSTEN, (void *)¶m); + + /* data bit width */ + param = 0; + sddev_control(SPI_DEV_NAME, CMD_SPI_SET_BITWIDTH, (void *)¶m); + + /* baudrate */ + BK_SPI_PRT("max_hz = %d \n", rate); + sddev_control(SPI_DEV_NAME, CMD_SPI_SET_CKR, (void *)&rate); + + /* mode */ + if (mode & BK_SPI_CPOL) + param = 1; + else + param = 0; + sddev_control(SPI_DEV_NAME, CMD_SPI_SET_CKPOL, (void *)¶m); + + /* CPHA */ + if (mode & BK_SPI_CPHA) + param = 1; + else + param = 0; + sddev_control(SPI_DEV_NAME, CMD_SPI_SET_CKPHA, (void *)¶m); + + /* Master */ + param = 1; + sddev_control(SPI_DEV_NAME, CMD_SPI_SET_MSTEN, (void *)¶m); + param = 1; + sddev_control(SPI_DEV_NAME, CMD_SPI_SET_NSSMD, (void *)¶m); + + /* set call back func */ + spi_dev_cb.callback = bk_spi_rx_callback; + spi_dev_cb.param = NULL; + sddev_control(SPI_DEV_NAME, CMD_SPI_SET_RX_CALLBACK, (void *)&spi_dev_cb); + + spi_dev_cb.callback = bk_spi_tx_needwrite_callback; + spi_dev_cb.param = NULL; + sddev_control(SPI_DEV_NAME, CMD_SPI_SET_TX_NEED_WRITE_CALLBACK, (void *)&spi_dev_cb); + + spi_dev_cb.callback = bk_spi_tx_finish_callback; + spi_dev_cb.param = NULL; + sddev_control(SPI_DEV_NAME, CMD_SPI_SET_TX_FINISH_CALLBACK, (void *)&spi_dev_cb); + + /* enable spi */ + param = 1; + sddev_control(SPI_DEV_NAME, CMD_SPI_UNIT_ENABLE, (void *)¶m); + + BK_SPI_PRT("spi_master:[CTRL]:0x%08x \n", REG_READ(SPI_CTRL)); +} + +static void bk_spi_unconfigure(void) +{ + sddev_control(SPI_DEV_NAME, CMD_SPI_DEINIT_MSTEN, NULL); +} + +int bk_spi_master_xfer(struct spi_message *msg) +{ + UINT32 param, total_size; + + ASSERT(spi_dev != NULL); + ASSERT(msg != NULL); + + rtos_lock_mutex(&spi_dev->mutex); + + total_size = msg->recv_len + msg->send_len; + if (total_size) { + GLOBAL_INT_DECLARATION(); + + /* initial spi_dev */ + GLOBAL_INT_DISABLE(); + spi_dev->tx_ptr = msg->send_buf; + spi_dev->tx_len = msg->send_len; + + spi_dev->rx_ptr = msg->recv_buf; + spi_dev->rx_len = msg->recv_len; + spi_dev->rx_offset = 0; + spi_dev->rx_drop = msg->send_len; + + spi_dev->total_len = total_size; + spi_dev->flag &= ~(TX_FINISH_FLAG); + GLOBAL_INT_RESTORE(); + + /* take CS */ + param = 0x2; + sddev_control(SPI_DEV_NAME, CMD_SPI_SET_NSSMD, (void *)¶m); + + /* enabel tx & rx interrupt */ + param = 1; + sddev_control(SPI_DEV_NAME, CMD_SPI_RXINT_EN, (void *)¶m); + sddev_control(SPI_DEV_NAME, CMD_SPI_TXINT_EN, (void *)¶m); + + //os_printf("0 %d\r\n", total_size); + + /* wait tx finish */ + rtos_get_semaphore(&spi_dev->tx_sem, BEKEN_NEVER_TIMEOUT); + + //os_printf("1 %d\r\n", total_size); + + /* disable tx & rx interrupt again */ + param = 0; + sddev_control(SPI_DEV_NAME, CMD_SPI_RXINT_EN, (void *)¶m); + sddev_control(SPI_DEV_NAME, CMD_SPI_TXINT_EN, (void *)¶m); + + /* release CS */ + param = 0x3; + sddev_control(SPI_DEV_NAME, CMD_SPI_SET_NSSMD, (void *)¶m); + + /* initial spi_dev with zero*/ + GLOBAL_INT_DISABLE(); + spi_dev->tx_ptr = NULL; + spi_dev->tx_len = 0; + + spi_dev->rx_ptr = NULL; + spi_dev->rx_len = 0; + + spi_dev->total_len = 0; + spi_dev->flag |= TX_FINISH_FLAG; + GLOBAL_INT_RESTORE(); + } + + rtos_unlock_mutex(&spi_dev->mutex); + + return msg->recv_len; +} + +int bk_spi_master_init(UINT32 rate, UINT32 mode) +{ + OSStatus result = 0; + + if (spi_dev) + bk_spi_master_deinit(); + + spi_dev = os_malloc(sizeof(struct bk_spi_dev)); + if (!spi_dev) { + BK_SPI_PRT("[spi]:malloc memory for spi_dev failed\n"); + result = -1; + goto _exit; + } + os_memset(spi_dev, 0, sizeof(struct bk_spi_dev)); + + + result = rtos_init_semaphore(&spi_dev->tx_sem, 1); + if (result != kNoErr) { + BK_SPI_PRT("[spi]: spi tx semp init failed\n"); + goto _exit; + } + + result = rtos_init_mutex(&spi_dev->mutex); + if (result != kNoErr) { + BK_SPI_PRT("[spi]: spi mutex init failed\n"); + goto _exit; + } + + spi_dev->tx_ptr = NULL; + spi_dev->tx_len = 0; + spi_dev->flag |= TX_FINISH_FLAG; + + bk_spi_configure(rate, mode); + + return 0; + +_exit: + if (spi_dev->mutex) + rtos_deinit_mutex(&spi_dev->mutex); + + if (spi_dev->tx_sem) + rtos_deinit_semaphore(&spi_dev->tx_sem); + + if (spi_dev) { + os_free(spi_dev); + spi_dev = NULL; + } + + return 1; +} + +int bk_spi_master_deinit(void) +{ + if (spi_dev == NULL) + return 0; + + if (spi_dev->mutex) + rtos_lock_mutex(&spi_dev->mutex); + + if (spi_dev->tx_sem) + rtos_deinit_semaphore(&spi_dev->tx_sem); + if (spi_dev->rx_sem) + rtos_deinit_semaphore(&spi_dev->rx_sem); + if (spi_dev->dma_tx_sem) + rtos_deinit_semaphore(&spi_dev->dma_tx_sem); + if (spi_dev->dma_rx_sem) + rtos_deinit_semaphore(&spi_dev->dma_rx_sem); + + if (spi_dev->mutex) { + rtos_unlock_mutex(&spi_dev->mutex); + rtos_deinit_mutex(&spi_dev->mutex); + } + + if (spi_dev) { + os_free(spi_dev); + spi_dev = NULL; + } + + bk_spi_unconfigure(); + + return 0; +} + +#if CFG_USE_SPI_DMA + +#define SPI_TEST_POART1 0 +#define SPI_TEST_POART2 1 +#define SPI_TX_BUFFER_SIZE 30*24 +#define SPI_RX_BUFFER_SIZE 30*24 +#define SPI_RX_DMA_CHANNEL GDMA_CHANNEL_1 +#define SPI_TX_DMA_CHANNEL GDMA_CHANNEL_3 + +void spi_debug_prt(void); +void spi_dma_tx_enable(UINT8 enable); +void spi_dma_rx_enable(UINT8 enable); +void spi_dma_tx_half_handler(UINT32 param); +void spi_dma_rx_half_handler(UINT32 param); + +static void (*user_dma_tx_finish_callback)(void)=NULL; +static void (*user_dma_rx_finish_callback)(void)=NULL; + +void bk_spi_dma_rx_finish_callback(UINT32 param) +{ + os_printf("%s %d\r\n",__func__,__LINE__); + spi_dev->flag &= ~(RX_FINISH_FLAG); + rtos_set_semaphore(&spi_dev->dma_rx_sem); + if(user_dma_rx_finish_callback) + { + user_dma_rx_finish_callback(); + } +} + +void bk_spi_dma_tx_finish_callback(UINT32 param) +{ + // os_printf("%s %d\r\n",__func__,__LINE__); + spi_dev->flag &= ~(TX_FINISH_FLAG); + rtos_set_semaphore(&spi_dev->dma_tx_sem); + if(user_dma_tx_finish_callback) + { + user_dma_tx_finish_callback(); + } +} + +int spi_dma_master_tx_init(struct spi_message *spi_msg) +{ + GDMACFG_TPYES_ST init_cfg; + GDMA_CFG_ST en_cfg; + + os_printf("spi tx init\r\n"); + os_memset(&init_cfg, 0, sizeof(GDMACFG_TPYES_ST)); + os_memset(&en_cfg, 0, sizeof(GDMA_CFG_ST)); + + init_cfg.dstdat_width = 8; + init_cfg.srcdat_width = 32; + init_cfg.dstptr_incr = 0; + init_cfg.srcptr_incr = 1; + + init_cfg.src_start_addr = spi_msg->send_buf; + init_cfg.dst_start_addr = (void *)SPI_DAT; + + init_cfg.channel = SPI_TX_DMA_CHANNEL ; + init_cfg.prio = 0; + init_cfg.u.type4.src_loop_start_addr = spi_msg->send_buf; + init_cfg.u.type4.src_loop_end_addr = spi_msg->send_buf + spi_msg->send_len; + + if(!isr_mode) { + init_cfg.half_fin_handler = NULL; + init_cfg.fin_handler = NULL; + spi_ctrl(CMD_SPI_SET_TX_FINISH_INT_CALLBACK, (void *) bk_spi_dma_tx_finish_callback); + } else { + init_cfg.half_fin_handler = NULL; + init_cfg.fin_handler = bk_spi_dma_tx_finish_callback; + } + + init_cfg.src_module = GDMA_X_SRC_DTCM_RD_REQ; + init_cfg.dst_module = GDMA_X_DST_GSPI_TX_REQ; + + sddev_control(GDMA_DEV_NAME, CMD_GDMA_CFG_TYPE4, (void *)&init_cfg); + + en_cfg.channel = SPI_TX_DMA_CHANNEL; + en_cfg.param = spi_msg->send_len; // dma translen + sddev_control(GDMA_DEV_NAME, CMD_GDMA_SET_TRANS_LENGTH, (void *)&en_cfg); + + en_cfg.channel = SPI_TX_DMA_CHANNEL; + en_cfg.param = 0; // 0:not repeat 1:repeat + sddev_control(GDMA_DEV_NAME, CMD_GDMA_CFG_WORK_MODE, (void *)&en_cfg); + + en_cfg.channel = SPI_TX_DMA_CHANNEL; + en_cfg.param = 0; // src no loop + sddev_control(GDMA_DEV_NAME, CMD_GDMA_CFG_SRCADDR_LOOP, &en_cfg); + + return 0; +} + +int spi_dma_master_rx_init(struct spi_message *spi_msg) +{ + GDMACFG_TPYES_ST init_cfg; + GDMA_CFG_ST en_cfg; + + os_printf("spi rx init\r\n"); + os_memset(&init_cfg, 0, sizeof(GDMACFG_TPYES_ST)); + os_memset(&en_cfg, 0, sizeof(GDMA_CFG_ST)); + + init_cfg.dstdat_width = 32; + init_cfg.srcdat_width = 8; + init_cfg.dstptr_incr = 1; + init_cfg.srcptr_incr = 0; + + init_cfg.src_start_addr = (void *)SPI_DAT; + init_cfg.dst_start_addr = spi_msg->recv_buf; + + init_cfg.channel = SPI_RX_DMA_CHANNEL; + init_cfg.prio = 0; + init_cfg.u.type5.dst_loop_start_addr = spi_msg->recv_buf; + init_cfg.u.type5.dst_loop_end_addr = spi_msg->recv_buf + spi_msg->recv_len; + + init_cfg.half_fin_handler = NULL; + init_cfg.fin_handler = NULL; + spi_ctrl(CMD_SPI_SET_RX_FINISH_INT_CALLBACK, (void *) bk_spi_dma_rx_finish_callback); + + init_cfg.src_module = GDMA_X_SRC_GSPI_RX_REQ; + init_cfg.dst_module = GDMA_X_DST_DTCM_WR_REQ; + + sddev_control(GDMA_DEV_NAME, CMD_GDMA_CFG_TYPE5, (void *)&init_cfg); + + en_cfg.channel = SPI_RX_DMA_CHANNEL; + en_cfg.param = spi_msg->recv_len; // dma translen + sddev_control(GDMA_DEV_NAME, CMD_GDMA_SET_TRANS_LENGTH, (void *)&en_cfg); + + + en_cfg.channel = SPI_RX_DMA_CHANNEL; + en_cfg.param = 0; // 0:not repeat 1:repeat + sddev_control(GDMA_DEV_NAME, CMD_GDMA_CFG_WORK_MODE, (void *)&en_cfg); + + en_cfg.channel = SPI_RX_DMA_CHANNEL; + en_cfg.param = 0; // src no loop + sddev_control(GDMA_DEV_NAME, CMD_GDMA_CFG_DSTADDR_LOOP, &en_cfg); + + return 0; +} + + +void bk_spi_master_dma_config(UINT32 mode, UINT32 rate) +{ + UINT32 param; + os_printf("mode:%d, rate:%d\r\n", mode, rate); + bk_spi_configure(rate, mode); + + //disable tx/rx int disable + param = 0; + sddev_control(SPI_DEV_NAME, CMD_SPI_TXINT_EN, (void *)¶m); + + param = 0; + sddev_control(SPI_DEV_NAME, CMD_SPI_RXINT_EN, (void *)¶m); + + //disable rx/tx finish enable bit + if(!isr_mode) { + param = 1; + sddev_control(SPI_DEV_NAME, CMD_SPI_TXFINISH_EN, (void *)¶m); + + param = 1; + sddev_control(SPI_DEV_NAME, CMD_SPI_RXFINISH_EN, (void *)¶m); + } + + //disable rx/tx over + param = 0; + sddev_control(SPI_DEV_NAME, CMD_SPI_RXOVR_EN, (void *)¶m); + + param = 0; + sddev_control(SPI_DEV_NAME, CMD_SPI_TXOVR_EN, (void *)¶m); + + param = 1; + sddev_control(SPI_DEV_NAME, CMD_SPI_SET_NSSMD, (void *)¶m); + sddev_control(SPI_DEV_NAME, CMD_SPI_SET_3_LINE, NULL); + + param = 0; + sddev_control(SPI_DEV_NAME, CMD_SPI_SET_BITWIDTH, (void *)¶m); + + //disable CSN intterrupt + param = 0; + sddev_control(SPI_DEV_NAME, CMD_SPI_CS_EN, (void *)¶m); + + //clk test + //param = 5000000; + //sddev_control(SPI_DEV_NAME, CMD_SPI_SET_CKR, (void *)¶m); + + os_printf("[CTRL]:0x%08x \n", REG_READ(SPI_CTRL)); + os_printf("[CONFIG]:0x%08x \n", REG_READ(SPI_CONFIG)); + +} + +int bk_spi_master_dma_tx_rx_init(UINT32 mode, UINT32 rate, struct spi_message *spi_msg) +{ + OSStatus result = 0; + + UINT32 param = 0; + + if(spi_dev) + bk_spi_master_deinit(); + spi_dev = os_malloc(sizeof(struct bk_spi_dev)); + if (!spi_dev) { + BK_SPI_PRT("[spi]:malloc memory for spi_dev failed\n"); + result = 1; + goto _exit; + } + os_memset(spi_dev, 0, sizeof(struct bk_spi_dev)); + + result = rtos_init_semaphore(&spi_dev->dma_tx_sem, 1); + if (result != kNoErr) { + BK_SPI_PRT("[spi]: spi tx semp init failed\n"); + result = 2; + goto _exit; + } + + result = rtos_init_semaphore(&spi_dev->dma_rx_sem, 1); + if (result != kNoErr) { + BK_SPI_PRT("[spi]: spi tx semp init failed\n"); + result = 3; + goto _exit; + } + + bk_spi_master_dma_config(mode, rate); + + spi_dma_master_tx_init(spi_msg); + spi_dma_tx_enable(0); + spi_dev->init_dma_tx = 1; + spi_dev->tx_ptr = spi_msg->send_buf; + spi_dev->tx_len = spi_msg->send_len; + sddev_control(SPI_DEV_NAME, CMD_SPI_TXTRANS_EN, (void *)&spi_msg->send_len); + param = spi_msg->recv_len; + sddev_control(SPI_DEV_NAME, CMD_SPI_RXTRANS_EN, (void *)&spi_msg->recv_len); + spi_dma_master_rx_init(spi_msg); + spi_dma_rx_enable(0); + spi_dev->init_dma_rx = 1; + spi_dev->rx_ptr = spi_msg->recv_buf; + spi_dev->rx_len = spi_msg->recv_len; + + return result; + _exit: + + bk_spi_master_deinit(); + return result; +} + +void bk_spi_tx_isr_callback(void (*func)(void)) +{ + user_dma_tx_finish_callback = func; + isr_mode = 0; + +} + +void bk_dma_tx_isr_callback(void (*func)(void)) +{ + user_dma_tx_finish_callback = func; + isr_mode = 1; +} + +void bk_spi_rx_isr_callback(void (*func)(void)) +{ + user_dma_rx_finish_callback = func; + isr_mode = 0; +} + +void bk_dma_rx_isr_callback(void (*func)(void)) +{ + user_dma_rx_finish_callback = func; + isr_mode = 1; +} + + + +int bk_spi_master_dma_tx_init(UINT32 mode, UINT32 rate, struct spi_message *spi_msg) +{ + OSStatus result = 0; + + if (spi_dev) + bk_spi_master_deinit(); + + spi_dev = os_malloc(sizeof(struct bk_spi_dev)); + if (!spi_dev) { + BK_SPI_PRT("[spi]:malloc memory for spi_dev failed\n"); + result = -1; + goto _exit; + } + os_memset(spi_dev, 0, sizeof(struct bk_spi_dev)); + + result = rtos_init_semaphore(&spi_dev->dma_tx_sem, 1); + if (result != kNoErr) { + BK_SPI_PRT("[spi]: spi tx semp init failed\n"); + goto _exit; + } + + bk_spi_master_dma_config(mode, rate); + + spi_dma_master_tx_init(spi_msg); + spi_dma_tx_enable(0); + if(!isr_mode) { + spi_ctrl(CMD_SPI_TXTRANS_EN, (void *)&spi_msg->send_len); + } else { + UINT32 param = 0; + spi_ctrl(CMD_SPI_TXTRANS_EN, (void *)¶m); + + } + + spi_dev->init_dma_tx = 1; + spi_dev->tx_ptr = spi_msg->send_buf; + spi_dev->tx_len = spi_msg->send_len; + + return 0; + +_exit: + + bk_spi_master_deinit(); + + return 1; +} + +int bk_spi_master_dma_rx_init(UINT32 mode, UINT32 rate, struct spi_message *spi_msg) +{ + OSStatus result = 0; + + UINT32 param = 0; + + if (spi_dev) + bk_spi_master_deinit(); + + spi_dev = os_malloc(sizeof(struct bk_spi_dev)); + if (!spi_dev) { + BK_SPI_PRT("[spi]:malloc memory for spi_dev failed\n"); + result = -1; + goto _exit; + } + os_memset(spi_dev, 0, sizeof(struct bk_spi_dev)); + + + result = rtos_init_semaphore(&spi_dev->dma_rx_sem, 1); + if (result != kNoErr) { + BK_SPI_PRT("[spi]: spi tx semp init failed\n"); + goto _exit; + } + + bk_spi_master_dma_config(mode, rate); + spi_dma_rx_enable(0); + + param = spi_msg->recv_len; + sddev_control(SPI_DEV_NAME, CMD_SPI_RXTRANS_EN, (void *)¶m); + + spi_dma_master_rx_init(spi_msg); + spi_dma_rx_enable(0); + spi_dev->init_dma_rx = 1; + spi_dev->rx_ptr = spi_msg->recv_buf; + spi_dev->rx_len = spi_msg->recv_len; + return 0; + + _exit: + + bk_spi_master_deinit(); + + + return 1; +} + +int bk_spi_master_dma_send(struct spi_message *spi_msg) +{ + int ret=0; + + GLOBAL_INT_DECLARATION(); + ASSERT(spi_msg != NULL); + if(spi_dev->init_dma_tx == 0 || spi_dev==NULL) + { + bk_printf("spi send no init!\n"); + return -1; + } + // if(spi_dev->flag&TX_FINISH_FLAG) + // { + // bk_printf("%s %d\r\n",__func__,__LINE__); + // return -2; + // } + + if(spi_dev->tx_ptr != spi_msg->send_buf) + { + GDMA_CFG_ST en_cfg; + en_cfg.channel = SPI_TX_DMA_CHANNEL; + en_cfg.param = (UINT32)spi_msg->send_buf; // dma dst addr + gdma_ctrl(CMD_GDMA_SET_SRC_START_ADDR, (void *)&en_cfg); + spi_dev->tx_ptr = spi_msg->send_buf; + } + if(spi_dev->tx_len != spi_msg->send_len) + { + GDMA_CFG_ST en_cfg; + if(!isr_mode) { + spi_ctrl(CMD_SPI_TXTRANS_EN, (void *)&spi_msg->send_len); + } + en_cfg.channel = SPI_TX_DMA_CHANNEL; + en_cfg.param = spi_msg->send_len; // dma translen + gdma_ctrl(CMD_GDMA_SET_TRANS_LENGTH, (void *)&en_cfg); + spi_dev->tx_len = spi_msg->send_len; + } + + GLOBAL_INT_DISABLE(); + spi_dev->flag |= TX_FINISH_FLAG; + GLOBAL_INT_RESTORE(); + + spi_dma_tx_enable(1); + + /* wait tx finish */ + if(user_dma_tx_finish_callback == NULL) + { + //因为写DMA是主动操作,所以DMA传输完成后,SPI不一定发送完成了。 + + rtos_get_semaphore(&spi_dev->dma_tx_sem, BEKEN_NEVER_TIMEOUT); + ret = spi_dev->flag; + } + else + ret = 0; + + if (spi_msg->send_buf != NULL) + return ret; + else { + //os_printf("spi_dma tx error send_buff\r\n", spi_msg->send_buf); + return -3; + } +} + + +int bk_spi_master_dma_recv(struct spi_message *spi_msg) +{ + int ret=0; + + GLOBAL_INT_DECLARATION(); + ASSERT(spi_msg != NULL); + + if(spi_dev->init_dma_rx == 0 || spi_dev==NULL) + { + bk_printf("spi recv no init!\n"); + return -1; + } + if(spi_dev->flag&RX_FINISH_FLAG) + { + return -2; + } + if(spi_dev->rx_ptr != spi_msg->recv_buf) + { + GDMA_CFG_ST en_cfg; + en_cfg.channel = SPI_RX_DMA_CHANNEL; + en_cfg.param = (UINT32)spi_msg->recv_buf; // dma dst addr + gdma_ctrl( CMD_GDMA_SET_DST_START_ADDR, (void *)&en_cfg); + spi_dev->rx_ptr = spi_msg->recv_buf; + + } + if(spi_dev->rx_len != spi_msg->recv_len) + { + GDMA_CFG_ST en_cfg; + //设置spi读长度 + spi_ctrl(CMD_SPI_RXTRANS_EN, (void *)&spi_msg->recv_len); //最多12bit + //设置DMA长度 + en_cfg.channel = SPI_RX_DMA_CHANNEL; + en_cfg.param = spi_msg->recv_len; // dma translen + gdma_ctrl(CMD_GDMA_SET_TRANS_LENGTH, (void *)&en_cfg); + spi_dev->rx_len = spi_msg->recv_len; + } + + GLOBAL_INT_DISABLE(); + spi_dev->flag |= RX_FINISH_FLAG; + GLOBAL_INT_RESTORE(); + spi_dma_rx_enable(1); + + if(user_dma_rx_finish_callback == NULL) + { + rtos_get_semaphore(&spi_dev->dma_rx_sem, BEKEN_NEVER_TIMEOUT); + ret = spi_dev->flag; + } + else + ret = 0; + + if (spi_msg->recv_buf != NULL) + return ret; + else { + //os_printf("spi_dma rx error recv_buff\r\n", spi_msg->recv_buf); + return -3; + } +} + + +#if 0 +void bk_master_dma_tx_finshed_callback(void (*func)(void)) +{ + user_dma_tx_finish_callback = func; + +} +void bk_master_dma_rx_finshed_callback(void (*func)(void)) +{ + user_dma_rx_finish_callback = func; + +} +#endif +void bk_master_dma_tx_disable(void) +{ + //GDMA_CFG_ST en_cfg; + + spi_dma_tx_enable(0); + spi_dev->flag &= (~TX_FINISH_FLAG); + + +} + +void bk_master_dma_rx_disable(void) +{ + //GDMA_CFG_ST en_cfg; + spi_dma_rx_enable(0); + spi_dev->flag &= (~RX_FINISH_FLAG); + +} +#endif //CFG_USE_SPI_DMA +#endif // CFG_USE_SPI_MASTER +#endif //(CFG_SOC_NAME == SOC_BK7231N) + + + + diff --git a/beken_os/beken378/driver/spi/spi_master_bk7231n_new.c b/beken_os/beken378/driver/spi/spi_master_bk7231n_new.c new file mode 100644 index 0000000..aee187c --- /dev/null +++ b/beken_os/beken378/driver/spi/spi_master_bk7231n_new.c @@ -0,0 +1,492 @@ +#include "include.h" +#include "arm_arch.h" +#include "typedef.h" +#include "arm_arch.h" +#include "sys_config.h" + +#if(CFG_SOC_NAME == SOC_BK7231N) +#include "icu_pub.h" +#include "spi_pub.h" +#include "sys_ctrl_pub.h" +#include "drv_model_pub.h" +#include "mem_pub.h" +#include "rtos_pub.h" +#include "general_dma_pub.h" +#include "general_dma.h" +#include "spi_bk7231n.h" + +#define MAX_LEN_ONCE 4095 //单次收发最大长度4095 + +#if CFG_USE_SPI_MASTER +struct bk_spi_dev { + UINT8 init_dma_tx:1; + UINT8 init_dma_rx:1; + UINT8 last_pack:1; //是否为最后一包 + UINT8 busy_flag:1; + UINT8 spci_flag:1; //特殊标志,为1时, 使用dma中断,可以支持大于4K数据发送,仅send接口 + UINT8 undef:3; + beken_semaphore_t finish_sem; +}; + +static void bk_spi_master_config(UINT32 mode, UINT32 rate); + +static struct bk_spi_dev *spi_dev; + +static void bk_spi_configure(UINT32 rate, UINT32 mode) +{ + UINT32 param; + + param = 0; + sddev_control(SPI_DEV_NAME, CMD_SPI_INIT_MSTEN, (void *)¶m); + + /* data bit width */ + param = 0; + sddev_control(SPI_DEV_NAME, CMD_SPI_SET_BITWIDTH, (void *)¶m); + + /* baudrate */ + BK_SPI_PRT("max_hz = %d \n", rate); + sddev_control(SPI_DEV_NAME, CMD_SPI_SET_CKR, (void *)&rate); + + /* mode */ + if (mode & BK_SPI_CPOL) + param = 1; + else + param = 0; + sddev_control(SPI_DEV_NAME, CMD_SPI_SET_CKPOL, (void *)¶m); + + /* CPHA */ + if (mode & BK_SPI_CPHA) + param = 1; + else + param = 0; + sddev_control(SPI_DEV_NAME, CMD_SPI_SET_CKPHA, (void *)¶m); + + /* Master */ + param = 1; + sddev_control(SPI_DEV_NAME, CMD_SPI_SET_MSTEN, (void *)¶m); + param = 1; + sddev_control(SPI_DEV_NAME, CMD_SPI_SET_NSSMD, (void *)¶m); + + /* enable spi */ + param = 1; + sddev_control(SPI_DEV_NAME, CMD_SPI_UNIT_ENABLE, (void *)¶m); + + os_printf("spi_master:[CTRL]:0x%08x \n", REG_READ(SPI_CTRL)); +} + +static void bk_spi_unconfigure(void) +{ + sddev_control(SPI_DEV_NAME, CMD_SPI_DEINIT_MSTEN, NULL); +} + +int bk_spi_master_deinit(void) +{ + if (spi_dev == NULL) + return 0; + + if (spi_dev->finish_sem) + rtos_deinit_semaphore(&spi_dev->finish_sem); + + if (spi_dev) { + os_free(spi_dev); + spi_dev = NULL; + } + + bk_spi_unconfigure(); + return 0; +} + +#if CFG_USE_SPI_DMA + +#define SPI_RX_DMA_CHANNEL GDMA_CHANNEL_1 +#define SPI_TX_DMA_CHANNEL GDMA_CHANNEL_3 + +void spi_dma_tx_enable(UINT8 enable); +void spi_dma_rx_enable(UINT8 enable); + +//spi 中断,按时到达,最大发送4095字节 +static void bk_spi_dma_finish_callback(UINT32 param) +{ + spi_dev->busy_flag = spi_dev->last_pack ? false : true; + rtos_set_semaphore(&spi_dev->finish_sem); +} + +//dma中断回调,会提前几个时钟到达,长度无限制 +static void bk_spi_dma_irq_cb(UINT32 param) +{ + spi_dev->busy_flag = false; + rtos_set_semaphore(&spi_dev->finish_sem); +} + +static int spi_dma_master_tx_init(void) +{ + GDMACFG_TPYES_ST init_cfg; + GDMA_CFG_ST en_cfg; + + os_memset(&init_cfg, 0, sizeof(GDMACFG_TPYES_ST)); + os_memset(&en_cfg, 0, sizeof(GDMA_CFG_ST)); + + init_cfg.dstdat_width = 8; + init_cfg.srcdat_width = 32; + init_cfg.dstptr_incr = 0; + init_cfg.srcptr_incr = 1; + + init_cfg.dst_start_addr = (void *)SPI_DAT; + init_cfg.channel = SPI_TX_DMA_CHANNEL; + init_cfg.prio = 0; + if(spi_dev->spci_flag) + init_cfg.fin_handler = bk_spi_dma_irq_cb; + else + init_cfg.fin_handler = NULL; + init_cfg.src_module = GDMA_X_SRC_DTCM_RD_REQ; + init_cfg.dst_module = GDMA_X_DST_GSPI_TX_REQ; + sddev_control(GDMA_DEV_NAME, CMD_GDMA_CFG_TYPE4, (void *)&init_cfg); + + int param = 1; + sddev_control(SPI_DEV_NAME, CMD_SPI_TXFINISH_EN, (void *)¶m); //开接收中断 + spi_ctrl(CMD_SPI_SET_TX_FINISH_INT_CALLBACK, (void *) bk_spi_dma_finish_callback); //设置回调,在回调中发送信号量 + + en_cfg.channel = SPI_TX_DMA_CHANNEL; + en_cfg.param = 0; // 0:not repeat 1:repeat + sddev_control(GDMA_DEV_NAME, CMD_GDMA_CFG_WORK_MODE, (void *)&en_cfg); + + en_cfg.channel = SPI_TX_DMA_CHANNEL; + en_cfg.param = 0; // src no loop + sddev_control(GDMA_DEV_NAME, CMD_GDMA_CFG_SRCADDR_LOOP, &en_cfg); + + spi_dma_tx_enable(0); + return 0; +} + +static int spi_dma_master_rx_init(void) +{ + GDMACFG_TPYES_ST init_cfg; + GDMA_CFG_ST en_cfg; + + os_memset(&init_cfg, 0, sizeof(GDMACFG_TPYES_ST)); + os_memset(&en_cfg, 0, sizeof(GDMA_CFG_ST)); + + init_cfg.dstdat_width = 32; + init_cfg.srcdat_width = 8; + init_cfg.dstptr_incr = 1; + init_cfg.srcptr_incr = 0; + + init_cfg.src_start_addr = (void *)SPI_DAT; + init_cfg.channel = SPI_RX_DMA_CHANNEL; + init_cfg.prio = 0; + init_cfg.src_module = GDMA_X_SRC_GSPI_RX_REQ; + init_cfg.dst_module = GDMA_X_DST_DTCM_WR_REQ; + sddev_control(GDMA_DEV_NAME, CMD_GDMA_CFG_TYPE5, (void *)&init_cfg); + + int param = 1; + sddev_control(SPI_DEV_NAME, CMD_SPI_RXFINISH_EN, (void *)¶m); //开接收中断 + spi_ctrl(CMD_SPI_SET_RX_FINISH_INT_CALLBACK, (void *) bk_spi_dma_finish_callback); //设置回调,在回调中发送信号量 + + en_cfg.channel = SPI_RX_DMA_CHANNEL; + en_cfg.param = 0; // 0:not repeat 1:repeat + sddev_control(GDMA_DEV_NAME, CMD_GDMA_CFG_WORK_MODE, (void *)&en_cfg); + + en_cfg.channel = SPI_RX_DMA_CHANNEL; + en_cfg.param = 0; // src no loop + sddev_control(GDMA_DEV_NAME, CMD_GDMA_CFG_DSTADDR_LOOP, &en_cfg); + + spi_dma_rx_enable(0); + return 0; +} + +static void bk_spi_master_config(UINT32 mode, UINT32 rate) +{ + UINT32 param; + os_printf("mode:%d, rate:%d\r\n", mode, rate); + bk_spi_configure(rate, mode); + + //disable tx/rx int disable + param = 0; + sddev_control(SPI_DEV_NAME, CMD_SPI_TXINT_EN, (void *)¶m); + + param = 0; + sddev_control(SPI_DEV_NAME, CMD_SPI_RXINT_EN, (void *)¶m); + + //disable rx/tx over + param = 0; + sddev_control(SPI_DEV_NAME, CMD_SPI_RXOVR_EN, (void *)¶m); + + param = 0; + sddev_control(SPI_DEV_NAME, CMD_SPI_TXOVR_EN, (void *)¶m); + + param = 1; + sddev_control(SPI_DEV_NAME, CMD_SPI_SET_NSSMD, (void *)¶m); + sddev_control(SPI_DEV_NAME, CMD_SPI_SET_3_LINE, NULL); + + param = 0; + sddev_control(SPI_DEV_NAME, CMD_SPI_SET_BITWIDTH, (void *)¶m); + + //disable CSN intterrupt + param = 0; + sddev_control(SPI_DEV_NAME, CMD_SPI_CS_EN, (void *)¶m); + + //clk test + //param = 5000000; + //sddev_control(SPI_DEV_NAME, CMD_SPI_SET_CKR, (void *)¶m); + + os_printf("[CTRL]:0x%08x \n", REG_READ(SPI_CTRL)); + os_printf("[CONFIG]:0x%08x \n", REG_READ(SPI_CONFIG)); +} + +int bk_spi_master_dma_init(UINT32 mode, UINT32 rate, UINT32 flag) +{ + OSStatus result = 0; + + if(spi_dev) + bk_spi_master_deinit(); + spi_dev = os_malloc(sizeof(struct bk_spi_dev)); + if (!spi_dev) { + BK_SPI_PRT("[spi]:malloc memory for spi_dev failed\n"); + result = 1; + goto _exit; + } + os_memset(spi_dev, 0, sizeof(struct bk_spi_dev)); + + result = rtos_init_semaphore(&spi_dev->finish_sem, 1); + if (result != kNoErr) { + BK_SPI_PRT("[spi]: spi dam sem init failed\n"); + result = 2; + goto _exit; + } + + spi_dev->spci_flag= flag; + bk_spi_master_config(mode, rate); + spi_dma_master_tx_init(); + spi_dev->init_dma_tx = 1; + spi_dma_master_rx_init(); + spi_dev->init_dma_rx = 1; + + return result; +_exit: + + bk_spi_master_deinit(); + return result; +} + +int bk_spi_master_dma_tx_init(UINT32 mode, UINT32 rate) +{ + OSStatus result = 0; + if (spi_dev) + bk_spi_master_deinit(); + + spi_dev = os_malloc(sizeof(struct bk_spi_dev)); + if (!spi_dev) { + os_printf("[spi]:malloc memory for spi_dev failed\n"); + result = -1; + goto _exit; + } + os_memset(spi_dev, 0, sizeof(struct bk_spi_dev)); + + result = rtos_init_semaphore(&spi_dev->finish_sem, 1); + if (result != kNoErr) { + os_printf("[spi]: spi tx semp init failed\n"); + goto _exit; + } + + // 初始化spi + bk_spi_master_config(mode, rate); + // 初始化dma + spi_dma_master_tx_init(); + spi_dev->init_dma_tx = 1; + return 0; + +_exit: + bk_spi_master_deinit(); + return 1; +} + +int bk_spi_master_dma_rx_init(UINT32 mode, UINT32 rate) +{ + OSStatus result = 0; + + if (spi_dev) + bk_spi_master_deinit(); + + spi_dev = os_malloc(sizeof(struct bk_spi_dev)); + if (!spi_dev) { + os_printf("[spi]:malloc memory for spi_dev failed\n"); + result = -1; + goto _exit; + } + os_memset(spi_dev, 0, sizeof(struct bk_spi_dev)); + + result = rtos_init_semaphore(&spi_dev->finish_sem, 1); + if (result != kNoErr) { + os_printf("[spi]: spi tx semp init failed\n"); + goto _exit; + } + + bk_spi_master_config(mode, rate); + spi_dma_master_rx_init(); + spi_dev->init_dma_rx = 1; + return 0; + +_exit: + bk_spi_master_deinit(); + return 1; +} + +int bk_spi_master_dma_send(struct spi_message *spi_msg) +{ + if(spi_msg == NULL) { + return -1; + } else if(spi_msg->send_buf == NULL || spi_msg->send_len == 0) { + return -1; + } + if(NULL == spi_dev) { + bk_printf("spi send no init!\n"); + return -1; + } else if(spi_dev->init_dma_tx == 0) { + return -1; + } + spi_dev->busy_flag = true; + int offset = 0; + GDMA_CFG_ST en_cfg; + int len = spi_msg->send_len ; + + if(spi_dev->spci_flag) { + UINT32 param = 0; + spi_ctrl(CMD_SPI_TXTRANS_EN, (void *)¶m); //为0时,为dma中断 + + en_cfg.channel = SPI_TX_DMA_CHANNEL; + en_cfg.param = (UINT32)(spi_msg->send_buf + offset); // dma dst addr + // 设置dma start addr + gdma_ctrl(CMD_GDMA_SET_SRC_START_ADDR, (void *)&en_cfg); + // 设置dma 发送长度 + en_cfg.param = spi_msg->send_len; // dma translen + gdma_ctrl(CMD_GDMA_SET_TRANS_LENGTH, (void *)&en_cfg); + + //开启dma传输 + spi_dev->busy_flag = true; + spi_dma_tx_enable(1); + rtos_get_semaphore(&spi_dev->finish_sem, BEKEN_NEVER_TIMEOUT); + } else { + while(len > 0) { + spi_msg->send_len = len > MAX_LEN_ONCE ? MAX_LEN_ONCE : len; + spi_dev->last_pack = spi_msg->send_len > MAX_LEN_ONCE ? false : true; + // 设置spi 触发中断长度 + spi_ctrl(CMD_SPI_TXTRANS_EN, (void *)&spi_msg->send_len); + + en_cfg.channel = SPI_TX_DMA_CHANNEL; + en_cfg.param = (UINT32)(spi_msg->send_buf + offset); // dma dst addr + // 设置dma start addr + gdma_ctrl(CMD_GDMA_SET_SRC_START_ADDR, (void *)&en_cfg); + // 设置dma 发送长度 + en_cfg.param = spi_msg->send_len; // dma translen + gdma_ctrl(CMD_GDMA_SET_TRANS_LENGTH, (void *)&en_cfg); + + //开启dma传输 + spi_dma_tx_enable(1); + rtos_get_semaphore(&spi_dev->finish_sem, BEKEN_NEVER_TIMEOUT); + len -= spi_msg->send_len; + offset += spi_msg->send_len; + } + } + return 0; +} + +int bk_spi_master_dma_recv(struct spi_message *spi_msg) +{ + if(spi_msg == NULL) { + return -1; + } else if(spi_msg->recv_buf == NULL || spi_msg->recv_len == 0) { + return -1; + } + + if(NULL == spi_dev) { + bk_printf("spi send no init!\n"); + return -1; + } else if(spi_dev->init_dma_rx == 0) { + return -1; + } + spi_dev->busy_flag = true; + int offset = 0; + GDMA_CFG_ST en_cfg; + int len = spi_msg->recv_len ; + + while(len > 0) { + spi_msg->recv_len = len > MAX_LEN_ONCE ? MAX_LEN_ONCE : len; + spi_dev->last_pack = spi_msg->recv_len > MAX_LEN_ONCE ? false : true; + + spi_ctrl(CMD_SPI_RXTRANS_EN, (void *)&spi_msg->recv_len); //设置接收触发中断 + + en_cfg.channel = SPI_RX_DMA_CHANNEL; + en_cfg.param = (UINT32)(spi_msg->recv_buf + offset); // dma dst addr + gdma_ctrl(CMD_GDMA_SET_DST_START_ADDR, (void *)&en_cfg); + + en_cfg.param = spi_msg->recv_len; // dma translen + gdma_ctrl(CMD_GDMA_SET_TRANS_LENGTH, (void *)&en_cfg); + + spi_dma_rx_enable(1); + rtos_get_semaphore(&spi_dev->finish_sem, BEKEN_NEVER_TIMEOUT); + len -= spi_msg->recv_len; + offset += spi_msg->recv_len; + } + + return 0; +} + +// 全双工收发接口,也可仅发送或仅接收 +//存在问题,收发同时时,接收会丢掉一个字节,在2M频率下 +int bk_spi_master_dma_xfer(struct spi_message *spi_msg) +{ + if(spi_msg == NULL || NULL == spi_dev) { + return -1; + } + if(spi_msg->recv_buf == NULL) spi_msg->recv_len = 0; + if(spi_msg->send_buf == NULL) spi_msg->send_len = 0; + //全双工模式,发送与接收长度必须一致 + if(spi_msg->recv_buf != NULL && spi_msg->send_buf != NULL && spi_msg->recv_len != spi_msg->send_len) { + return -1; + } + + spi_dev->busy_flag = true; + int len = spi_msg->recv_len > 0 ? spi_msg->recv_len : spi_msg->send_len; + int offset = 0; + GDMA_CFG_ST en_cfg; + + while(len > 0) { + if(spi_msg->recv_buf) { + spi_msg->recv_len = len > MAX_LEN_ONCE ? MAX_LEN_ONCE : len; + spi_dev->last_pack = spi_msg->recv_len > MAX_LEN_ONCE ? false : true; + spi_ctrl(CMD_SPI_RXTRANS_EN, (void *)&spi_msg->recv_len); //设置接收触发中断 + en_cfg.channel = SPI_RX_DMA_CHANNEL; + en_cfg.param = (UINT32)(spi_msg->recv_buf + offset); // dma dst addr + gdma_ctrl(CMD_GDMA_SET_DST_START_ADDR, (void *)&en_cfg); + en_cfg.param = spi_msg->recv_len; // dma translen + gdma_ctrl(CMD_GDMA_SET_TRANS_LENGTH, (void *)&en_cfg); + } + + if(spi_msg->send_buf) { + spi_msg->send_len = len > MAX_LEN_ONCE ? MAX_LEN_ONCE : len; + spi_dev->last_pack = spi_msg->send_len > MAX_LEN_ONCE ? false : true; + spi_ctrl(CMD_SPI_TXTRANS_EN, (void *)&spi_msg->send_len); + en_cfg.channel = SPI_TX_DMA_CHANNEL; + en_cfg.param = (UINT32)(spi_msg->send_buf + offset); // dma dst addr + gdma_ctrl(CMD_GDMA_SET_SRC_START_ADDR, (void *)&en_cfg); + en_cfg.param = spi_msg->send_len; // dma translen + gdma_ctrl(CMD_GDMA_SET_TRANS_LENGTH, (void *)&en_cfg); + } + if(spi_msg->send_buf && spi_msg->send_len > 0) + spi_dma_tx_enable(1); + if(spi_msg->recv_buf && spi_msg->recv_len > 0) + spi_dma_rx_enable(1); + rtos_get_semaphore(&spi_dev->finish_sem, BEKEN_NEVER_TIMEOUT); + len = spi_msg->recv_len > 0 ? (len - spi_msg->recv_len) : (len - spi_msg->send_len); + offset += spi_msg->recv_len > 0 ? spi_msg->recv_len : spi_msg->send_len; + } + return 0; +} + +int bk_spi_get_status(void) { + return spi_dev->busy_flag; +} + +#endif //CFG_USE_SPI_DMA +#endif // CFG_USE_SPI_MASTER +#endif //(CFG_SOC_NAME == SOC_BK7231N) diff --git a/beken_os/beken378/driver/spi/spi_slave_bk7231n.c b/beken_os/beken378/driver/spi/spi_slave_bk7231n.c new file mode 100755 index 0000000..7bd54a3 --- /dev/null +++ b/beken_os/beken378/driver/spi/spi_slave_bk7231n.c @@ -0,0 +1,943 @@ +#include "include.h" +#include "arm_arch.h" +#include "typedef.h" +#include "arm_arch.h" +#include "icu_pub.h" +#include "sys_config.h" + +#if(CFG_SOC_NAME == SOC_BK7231N) +#include "spi_bk7231n.h" +#include "spi_pub.h" +#include "gpio_pub.h" +#include "sys_ctrl_pub.h" +#include "drv_model_pub.h" +#include "mem_pub.h" +#include "rtos_pub.h" +#include "general_dma_pub.h" +#include "general_dma.h" + +#if CFG_USE_SPI_SLAVE +#define TRUE 1 +#define FALSE 0 + +#define SPI_SLAVE_RX_FIFO_LEN (512) + +struct spi_rx_fifo { + UINT8 *buffer; + + UINT16 put_index, get_index; + + UINT32 is_full; +}; + +struct bk_spi_slave_dev { + UINT32 flag; + + beken_semaphore_t tx_sem; + UINT8 *tx_ptr; + UINT32 tx_len; + + beken_semaphore_t rx_sem; + struct spi_rx_fifo *rx_fifo; + + beken_mutex_t mutex; +}; + +static struct bk_spi_slave_dev *spi_slave_dev; + +UINT32 bk_spi_slave_get_rx_fifo(void) +{ + UINT32 rx_length; + struct spi_rx_fifo *rx_fifo = spi_slave_dev->rx_fifo; + GLOBAL_INT_DECLARATION(); + + /* get rx length */ + GLOBAL_INT_DISABLE(); + + rx_length = (rx_fifo->put_index >= rx_fifo->get_index) ? + (rx_fifo->put_index - rx_fifo->get_index) : + (SPI_SLAVE_RX_FIFO_LEN - (rx_fifo->get_index - rx_fifo->put_index)); + + GLOBAL_INT_RESTORE(); + + return rx_length; +} + +static void bk_spi_slave_spi_rx_callback(int is_rx_end, void *param) +{ + UINT8 ch; + struct spi_rx_fifo *rx_fifo; + //GLOBAL_INT_DECLARATION(); + + rx_fifo = (struct spi_rx_fifo *)spi_slave_dev->rx_fifo; + ASSERT(rx_fifo != NULL); + + os_printf("rx callback:%d\r\n ", is_rx_end); + //REG_WRITE((0x00802800+(18*4)), 0x02); + while (1) { + if (spi_read_rxfifo(&ch) == 0) + break; + //REG_WRITE((0x00802800+(0x1a*4)), 0x02); + //REG_WRITE((0x00802800+(0x1a*4)), 0x00); + //GLOBAL_INT_DISABLE(); + + rx_fifo->buffer[rx_fifo->put_index] = ch; + rx_fifo->put_index += 1; + if (rx_fifo->put_index >= SPI_SLAVE_RX_FIFO_LEN) + rx_fifo->put_index = 0; + + if (rx_fifo->put_index == rx_fifo->get_index) { + rx_fifo->get_index += 1; + rx_fifo->is_full = TRUE; + if (rx_fifo->get_index >= SPI_SLAVE_RX_FIFO_LEN) + rx_fifo->get_index = 0; + } + //GLOBAL_INT_RESTORE(); + + if (spi_slave_dev->tx_ptr == NULL) + spi_write_txfifo(0xFF); + } + + if (is_rx_end) { + // only rx end happened, wake up rx_semp + os_printf("--> rx end\r\n"); + rtos_set_semaphore(&spi_slave_dev->rx_sem); + } + //REG_WRITE((0x00802800+(18*4)), 0x00); +} + +static int bk_spi_slave_get_rx_data(UINT8 *rx_buf, int len) +{ + struct spi_rx_fifo *rx_fifo; + rx_fifo = (struct spi_rx_fifo *)spi_slave_dev->rx_fifo; + int size = len; + //os_printf("len:%d\r\n", len); + + //os_printf("rx_fifo:%d\r\n", rx_fifo); + + ASSERT(rx_fifo != NULL); + + //os_printf("rx_buf:%d\r\n", rx_buf); + + if (rx_buf == NULL) + return 0; + + //os_printf("%d %d %d\r\n", bk_spi_slave_get_rx_fifo(), + //rx_fifo->get_index, rx_fifo->put_index); + + while (size) { + uint8_t ch; + GLOBAL_INT_DECLARATION(); + + GLOBAL_INT_DISABLE(); + + if ((rx_fifo->get_index == rx_fifo->put_index) + && (rx_fifo->is_full == FALSE)) { + GLOBAL_INT_RESTORE(); + os_printf("break:get rx data \r\n"); + break; + } + + ch = rx_fifo->buffer[rx_fifo->get_index]; + rx_fifo->get_index += 1; + if (rx_fifo->get_index >= SPI_SLAVE_RX_FIFO_LEN) + rx_fifo->get_index = 0; + + if (rx_fifo->is_full == TRUE) + rx_fifo->is_full = FALSE; + + GLOBAL_INT_RESTORE(); + + *rx_buf = ch & 0xff; + rx_buf ++; + size --; + + } + + return (len - size); +} + +static void bk_spi_slave_tx_needwrite_callback(int port, void *param) +{ + UINT8 *tx_ptr = spi_slave_dev->tx_ptr; + UINT32 tx_len = spi_slave_dev->tx_len; + GLOBAL_INT_DECLARATION(); + + if (tx_ptr && tx_len) { + UINT8 data = *tx_ptr; + + while (spi_write_txfifo(data) == 1) { + spi_read_rxfifo(&data); + tx_len --; + tx_ptr ++; + if (tx_len == 0) { + UINT32 enable = 0; + sddev_control(SPI_DEV_NAME, CMD_SPI_TXINT_EN, (void *)&enable); + break; + } + data = *tx_ptr; + } + } else { + //rt_kprintf("nw:%p,%d\r\n", tx_ptr, tx_len); + while (spi_write_txfifo(0xff)) { + if (tx_len) + tx_len--; + + if (tx_len == 0) { + os_printf("close tx\r\n"); + UINT32 enable = 0; + sddev_control(SPI_DEV_NAME, CMD_SPI_TXINT_EN, (void *)&enable); + break; + } + } + } + + GLOBAL_INT_DISABLE(); + spi_slave_dev->tx_ptr = tx_ptr; + spi_slave_dev->tx_len = tx_len; + GLOBAL_INT_RESTORE(); + +} + +static void bk_spi_slave_tx_finish_callback(int port, void *param) +{ + if ((spi_slave_dev->tx_len == 0) && (spi_slave_dev->tx_ptr)) { + if ((spi_slave_dev->flag & TX_FINISH_FLAG) == 0) { + spi_slave_dev->flag |= TX_FINISH_FLAG; + rtos_set_semaphore(&spi_slave_dev->tx_sem); + } + } +} + +static void bk_spi_slave_configure(UINT32 rate, UINT32 mode) +{ + UINT32 param; + struct spi_callback_des spi_dev_cb; + + /* data bit width */ + param = 0; + sddev_control(SPI_DEV_NAME, CMD_SPI_SET_BITWIDTH, (void *)¶m); + + /* baudrate */ + BK_SPI_PRT("max_hz = %d \n", rate); + sddev_control(SPI_DEV_NAME, CMD_SPI_SET_CKR, (void *)&rate); + + /* mode */ + if (mode & BK_SPI_CPOL) + param = 1; + else + param = 0; + sddev_control(SPI_DEV_NAME, CMD_SPI_SET_CKPOL, (void *)¶m); + + /* CPHA */ + if (mode & BK_SPI_CPHA) + param = 1; + else + param = 0; + sddev_control(SPI_DEV_NAME, CMD_SPI_SET_CKPHA, (void *)¶m); + + /* slave */ + param = 0; + sddev_control(SPI_DEV_NAME, CMD_SPI_SET_MSTEN, (void *)¶m); + + // 4line :7231N nssms is 0 + param = 0; + sddev_control(SPI_DEV_NAME, CMD_SPI_SET_NSSMD, (void *)¶m); + + param = 0; + sddev_control(SPI_DEV_NAME, CMD_SPI_INIT_MSTEN, (void *)¶m); + + + /* set call back func */ + spi_dev_cb.callback = bk_spi_slave_spi_rx_callback; + spi_dev_cb.param = NULL; + sddev_control(SPI_DEV_NAME, CMD_SPI_SET_RX_CALLBACK, (void *)&spi_dev_cb); + + spi_dev_cb.callback = bk_spi_slave_tx_needwrite_callback; + spi_dev_cb.param = NULL; + sddev_control(SPI_DEV_NAME, CMD_SPI_SET_TX_NEED_WRITE_CALLBACK, (void *)&spi_dev_cb); + + spi_dev_cb.callback = bk_spi_slave_tx_finish_callback; + spi_dev_cb.param = NULL; + sddev_control(SPI_DEV_NAME, CMD_SPI_SET_TX_FINISH_CALLBACK, (void *)&spi_dev_cb); + + param = 0; + sddev_control(SPI_DEV_NAME, CMD_SPI_LSB_EN, (void *)¶m); + + //enable rx/tx finish enable bit + param = 1; + sddev_control(SPI_DEV_NAME, CMD_SPI_TXFINISH_EN, (void *)¶m); + + param = 1; + sddev_control(SPI_DEV_NAME, CMD_SPI_RXFINISH_EN, (void *)¶m); + +#ifdef SPI_DMA_TRANS + //disable rx int bit + param = 0; +#else + //disable rx int bit + param = 1; +#endif + sddev_control(SPI_DEV_NAME, CMD_SPI_RXINT_EN, (void *)¶m); + + /* enable spi */ + param = 1; + sddev_control(SPI_DEV_NAME, CMD_SPI_UNIT_ENABLE, (void *)¶m); + + //BK_SPI_PRT("spi_slave [CTRL]:0x%08x \n", REG_READ(SPI_CTRL)); + //BK_SPI_PRT("spi_slave [CONFIG]:0x%08x \n", REG_READ(SPI_CONFIG)); + + +} + +static void bk_spi_slave_unconfigure(void) +{ + sddev_control(SPI_DEV_NAME, CMD_SPI_DEINIT_MSTEN, NULL); +} + +int bk_spi_slave_xfer(struct spi_message *msg) +{ + UINT8 *recv_ptr = NULL; + const UINT8 *send_ptr = NULL; + UINT32 param, send_len, recv_len; + GLOBAL_INT_DECLARATION(); + + ASSERT(spi_slave_dev != NULL); + ASSERT(msg != NULL); + + rtos_lock_mutex(&spi_slave_dev->mutex); + + recv_ptr = msg->recv_buf; + recv_len = msg->recv_len; + send_ptr = msg->send_buf; + send_len = msg->send_len; + + //new spi hardware bug + param = send_len - 1; + sddev_control(SPI_DEV_NAME, CMD_SPI_TXTRANS_EN, (void *)¶m); + + param = recv_len; + sddev_control(SPI_DEV_NAME, CMD_SPI_RXTRANS_EN, (void *)¶m); + + //enbale rx/tx enable bit + param = 1; + sddev_control(SPI_DEV_NAME, CMD_SPI_TX_EN, (void *)¶m); + + param = 1; + sddev_control(SPI_DEV_NAME, CMD_SPI_RX_EN, (void *)¶m); + + BK_SPI_PRT("spi_slave [CTRL]:0x%08x \n", REG_READ(SPI_CTRL)); + BK_SPI_PRT("spi_slave [CONFIG]:0x%08x \n", REG_READ(SPI_CONFIG)); + + + if ((send_ptr) && send_len) { + GLOBAL_INT_DISABLE(); + spi_slave_dev->tx_ptr = (UINT8 *)send_ptr; + spi_slave_dev->tx_len = send_len; + spi_slave_dev->flag &= ~(TX_FINISH_FLAG); + GLOBAL_INT_RESTORE(); + + param = 1; + sddev_control(SPI_DEV_NAME, CMD_SPI_TXINT_EN, (void *)¶m); + + //BK_SPI_PRT("0 %p-%d\r\n", send_ptr, send_len); + rtos_get_semaphore(&spi_slave_dev->tx_sem, BEKEN_NEVER_TIMEOUT); + + param = 0; + sddev_control(SPI_DEV_NAME, CMD_SPI_TXINT_EN, (void *)¶m); + + GLOBAL_INT_DISABLE(); + spi_slave_dev->tx_ptr = NULL; + spi_slave_dev->tx_len = 0; + spi_slave_dev->flag |= TX_FINISH_FLAG; + GLOBAL_INT_RESTORE(); + + //BK_SPI_PRT("1 %p-%d\r\n", send_ptr, send_len); + param = send_len; + } else if ((recv_ptr) && recv_len) { + OSStatus err; + int len; + + GLOBAL_INT_DISABLE(); + spi_slave_dev->tx_ptr = NULL; + spi_slave_dev->tx_len = recv_len; + GLOBAL_INT_RESTORE(); + + param = 1; + sddev_control(SPI_DEV_NAME, CMD_SPI_TXINT_EN, (void *)¶m); + + do { + len = bk_spi_slave_get_rx_data(recv_ptr, recv_len); + if (len == 0) { + err = rtos_get_semaphore(&spi_slave_dev->rx_sem, BEKEN_WAIT_FOREVER); + if (err != kNoErr) + break; + } + } while (len == 0); + + param = 0; + sddev_control(SPI_DEV_NAME, CMD_SPI_TXINT_EN, (void *)¶m); + + // clear all rx semp for this time + do { + err = rtos_get_semaphore(&spi_slave_dev->rx_sem, 0); + } while (err == kNoErr); + + param = len; + } + + rtos_unlock_mutex(&spi_slave_dev->mutex); + + return param; +} + +int bk_spi_slave_init(UINT32 rate, UINT32 mode) +{ + OSStatus result = 0; + + if (spi_slave_dev) + bk_spi_slave_deinit(); + + spi_slave_dev = os_malloc(sizeof(struct bk_spi_slave_dev)); + if (!spi_slave_dev) { + BK_SPI_PRT("[spi]:malloc memory for spi_dev failed\n"); + result = -1; + goto _exit; + } + os_memset(spi_slave_dev, 0, sizeof(struct bk_spi_slave_dev)); + + result = rtos_init_semaphore(&spi_slave_dev->tx_sem, 1); + if (result != kNoErr) { + BK_SPI_PRT("[spi]: spi tx semp init failed\n"); + goto _exit; + } + + result = rtos_init_semaphore(&spi_slave_dev->rx_sem, 1); + if (result != kNoErr) { + BK_SPI_PRT("[spi]: spi rx semp init failed\n"); + goto _exit; + } + + result = rtos_init_mutex(&spi_slave_dev->mutex); + if (result != kNoErr) { + BK_SPI_PRT("[spi]: spi mutex init failed\n"); + goto _exit; + } + + struct spi_rx_fifo *rx_fifo; + + rx_fifo = (struct spi_rx_fifo *)os_malloc(sizeof(struct spi_rx_fifo) + + SPI_SLAVE_RX_FIFO_LEN); + if (!rx_fifo) { + BK_SPI_PRT("[spi]: spi rx fifo malloc failed\n"); + goto _exit; + } + + rx_fifo->buffer = (uint8_t *)(rx_fifo + 1); + os_memset(rx_fifo->buffer, 0, SPI_SLAVE_RX_FIFO_LEN); + rx_fifo->put_index = 0; + rx_fifo->get_index = 0; + rx_fifo->is_full = 0; + + spi_slave_dev->rx_fifo = rx_fifo; + + spi_slave_dev->tx_ptr = NULL; + spi_slave_dev->tx_len = 0; + spi_slave_dev->flag |= TX_FINISH_FLAG; + + bk_spi_slave_configure(rate, mode); + + return 0; + +_exit: + if (spi_slave_dev->mutex) + rtos_deinit_mutex(&spi_slave_dev->mutex); + + if (spi_slave_dev->tx_sem) + rtos_deinit_semaphore(&spi_slave_dev->tx_sem); + + if (spi_slave_dev->rx_sem) + rtos_deinit_semaphore(&spi_slave_dev->rx_sem); + + if (spi_slave_dev->rx_fifo) + os_free(spi_slave_dev->rx_fifo); + + if (spi_slave_dev) { + os_free(spi_slave_dev); + spi_slave_dev = NULL; + } + + return 1; +} + + +int bk_spi_slave_deinit(void) +{ + if (spi_slave_dev == NULL) + return 0; + + bk_spi_slave_unconfigure(); + + if (spi_slave_dev->mutex) + rtos_lock_mutex(&spi_slave_dev->mutex); + + if (spi_slave_dev->tx_sem) + rtos_deinit_semaphore(&spi_slave_dev->tx_sem); + + if (spi_slave_dev->rx_sem) + rtos_deinit_semaphore(&spi_slave_dev->rx_sem); + + if (spi_slave_dev->rx_fifo) + os_free(spi_slave_dev->rx_fifo); + + if (spi_slave_dev->mutex) { + rtos_unlock_mutex(&spi_slave_dev->mutex); + rtos_deinit_mutex(&spi_slave_dev->mutex); + } + + os_free(spi_slave_dev); + spi_slave_dev = NULL; + + return 0; +} + +#if CFG_USE_SPI_DMA +volatile int dma_trans_flag = 0; + +#define SPI_TEST_POART1 0 +#define SPI_TEST_POART2 1 +#define SPI_TX_BUFFER_SIZE 1024 +#define SPI_RX_BUFFER_SIZE 1024*2 +#define SPI_RX_DMA_CHANNEL GDMA_CHANNEL_1 +#define SPI_TX_DMA_CHANNEL GDMA_CHANNEL_3 + +void spi_dma_tx_enable(UINT8 enable); + +void spi_dma_tx_half_handler(UINT32 param) +{ + + //os_printf("spi_dma half handler\r\n"); +} + +void spi_dma_tx_finish_handler(UINT32 param) +{ + + if ((spi_slave_dev->flag & TX_FINISH_FLAG) == 0) { + spi_slave_dev->flag |= TX_FINISH_FLAG; + rtos_set_semaphore(&spi_slave_dev->tx_sem); + } + + //os_printf("spi_dma finish handler\r\n"); +} +void spi_dma_rx_half_handler(UINT32 param) +{ + dma_trans_flag |= 1; + //os_printf("spi_dma rx half hander\r\n"); +} + +void spi_dma_rx_finish_handler(UINT32 param) +{ + dma_trans_flag |= 2; + + rtos_set_semaphore(&spi_slave_dev->rx_sem); + //os_printf("spi_dma rx finish hander\r\n"); +} + + +void spi_debug_prt(void) +{ + int reg_addr = 0; + + // wf debug + reg_addr = REG_READ(GENER_DMA0_REG0_CONF + ((0x08) * 4)); + BK_SPI_PRT("reg08:0x%lx\r\n", reg_addr); + reg_addr = REG_READ(GENER_DMA0_REG0_CONF + ((0x09) * 4)); + BK_SPI_PRT("reg09:0x%lx\r\n", reg_addr); + reg_addr = REG_READ(GENER_DMA0_REG0_CONF + ((0x0a) * 4)); + BK_SPI_PRT("reg0a:0x%lx\r\n", reg_addr); + reg_addr = REG_READ(GENER_DMA0_REG0_CONF + ((0x1b) * 4)); + BK_SPI_PRT("reg0b:0x%lx\r\n", reg_addr); + reg_addr = REG_READ(GENER_DMA0_REG0_CONF + ((0x0c) * 4)); + BK_SPI_PRT("reg0c:0x%lx\r\n", reg_addr); + reg_addr = REG_READ(GENER_DMA0_REG0_CONF + ((0x0d) * 4)); + BK_SPI_PRT("reg0d:0x%lx\r\n", reg_addr); + reg_addr = REG_READ(GENER_DMA0_REG0_CONF + ((0x0e) * 4)); + BK_SPI_PRT("reg0e:0x%lx\r\n", reg_addr); + reg_addr = REG_READ(GENER_DMA0_REG0_CONF + ((0x0f) * 4)); + BK_SPI_PRT("reg0f:0x%lx\r\n", reg_addr); +} + +void spi_dma_tx_init(struct spi_message *spi_msg) +{ + GDMACFG_TPYES_ST init_cfg; + GDMA_CFG_ST en_cfg; + + os_printf("spi tx init\r\n"); + os_memset(&init_cfg, 0, sizeof(GDMACFG_TPYES_ST)); + os_memset(&en_cfg, 0, sizeof(GDMA_CFG_ST)); + + init_cfg.dstdat_width = 8; + init_cfg.srcdat_width = 32; + init_cfg.dstptr_incr = 0; + init_cfg.srcptr_incr = 1; + + init_cfg.src_start_addr = spi_msg->send_buf; + init_cfg.dst_start_addr = (void *)SPI_DAT; + + init_cfg.channel = SPI_TX_DMA_CHANNEL ; + init_cfg.prio = 0; + init_cfg.u.type4.src_loop_start_addr = spi_msg->send_buf; + init_cfg.u.type4.src_loop_end_addr = spi_msg->send_buf + spi_msg->send_len; + + init_cfg.half_fin_handler = spi_dma_tx_half_handler; + init_cfg.fin_handler = spi_dma_tx_finish_handler; + + init_cfg.src_module = GDMA_X_SRC_DTCM_RD_REQ; + init_cfg.dst_module = GDMA_X_DST_GSPI_TX_REQ; + + sddev_control(GDMA_DEV_NAME, CMD_GDMA_CFG_TYPE4, (void *)&init_cfg); + + en_cfg.channel = SPI_TX_DMA_CHANNEL; + en_cfg.param = spi_msg->send_len; // dma translen + sddev_control(GDMA_DEV_NAME, CMD_GDMA_SET_TRANS_LENGTH, (void *)&en_cfg); + + en_cfg.channel = SPI_TX_DMA_CHANNEL; + en_cfg.param = 0; // 0:not repeat 1:repeat + sddev_control(GDMA_DEV_NAME, CMD_GDMA_CFG_WORK_MODE, (void *)&en_cfg); +} + +void spi_dma_rx_init(struct spi_message *spi_msg) +{ + GDMACFG_TPYES_ST init_cfg; + GDMA_CFG_ST en_cfg; + + os_printf("spi rx init\r\n"); + os_memset(&init_cfg, 0, sizeof(GDMACFG_TPYES_ST)); + os_memset(&en_cfg, 0, sizeof(GDMA_CFG_ST)); + + init_cfg.dstdat_width = 32; + init_cfg.srcdat_width = 8; + init_cfg.dstptr_incr = 1; + init_cfg.srcptr_incr = 0; + + init_cfg.src_start_addr = (void *)SPI_DAT; + init_cfg.dst_start_addr = spi_msg->recv_buf; + + init_cfg.channel = SPI_RX_DMA_CHANNEL; + init_cfg.prio = 0; + init_cfg.u.type5.dst_loop_start_addr = spi_msg->recv_buf; + init_cfg.u.type5.dst_loop_end_addr = spi_msg->recv_buf + spi_msg->recv_len; + + init_cfg.half_fin_handler = spi_dma_rx_half_handler; + init_cfg.fin_handler = spi_dma_rx_finish_handler; + + init_cfg.src_module = GDMA_X_SRC_GSPI_RX_REQ; + init_cfg.dst_module = GDMA_X_DST_DTCM_WR_REQ; + + sddev_control(GDMA_DEV_NAME, CMD_GDMA_CFG_TYPE5, (void *)&init_cfg); + + en_cfg.channel = SPI_RX_DMA_CHANNEL; + en_cfg.param = spi_msg->recv_len; // dma translen + sddev_control(GDMA_DEV_NAME, CMD_GDMA_SET_TRANS_LENGTH, (void *)&en_cfg); + + + en_cfg.channel = SPI_RX_DMA_CHANNEL; + en_cfg.param = 1; // 0:not repeat 1:repeat + sddev_control(GDMA_DEV_NAME, CMD_GDMA_CFG_WORK_MODE, (void *)&en_cfg); +} + +void spi_dma_tx_enable(UINT8 enable) +{ + int param; + GDMA_CFG_ST en_cfg; + + + //enable tx + param = enable; + spi_ctrl( CMD_SPI_TX_EN, (void *)¶m); + en_cfg.channel = SPI_TX_DMA_CHANNEL; + + if (enable) + en_cfg.param = 1; + else + en_cfg.param = 0; + gdma_ctrl(CMD_GDMA_SET_DMA_ENABLE, &en_cfg); + +} + +void spi_dma_rx_enable(UINT8 enable) +{ + int param ; + GDMA_CFG_ST en_cfg; + + en_cfg.channel = SPI_RX_DMA_CHANNEL; + if (enable) + en_cfg.param = 1; + else + en_cfg.param = 0; + gdma_ctrl(CMD_GDMA_SET_DMA_ENABLE, &en_cfg); + //enable rx + param = enable; + spi_ctrl(CMD_SPI_RX_EN, (void *)¶m); +} + +void bk_spi_slave_dma_config(UINT32 mode, UINT32 rate) +{ + UINT32 param; + os_printf("spi slave mode:%d, rate;%d\r\n", mode, rate); + bk_spi_slave_configure(rate, mode); + + //disable tx/rx int disable + param = 0; + sddev_control(SPI_DEV_NAME, CMD_SPI_TXINT_EN, (void *)¶m); + + param = 0; + sddev_control(SPI_DEV_NAME, CMD_SPI_RXINT_EN, (void *)¶m); + + //disable rx/tx finish enable bit + param = 0; + sddev_control(SPI_DEV_NAME, CMD_SPI_TXFINISH_EN, (void *)¶m); + + param = 0; + sddev_control(SPI_DEV_NAME, CMD_SPI_RXFINISH_EN, (void *)¶m); + + //disable rx/tx over + param = 0; + sddev_control(SPI_DEV_NAME, CMD_SPI_RXOVR_EN, (void *)¶m); + + param = 0; + sddev_control(SPI_DEV_NAME, CMD_SPI_TXOVR_EN, (void *)¶m); + + //disable CSN intterrupt + param = 0; + sddev_control(SPI_DEV_NAME, CMD_SPI_CS_EN, (void *)¶m); + + os_printf("slave [CTRL]:0x%08x \n", REG_READ(SPI_CTRL)); + os_printf("slave [CONFIG]:0x%08x \n", REG_READ(SPI_CONFIG)); +} + +int bk_spi_slave_dma_rx_init(UINT32 mode, UINT32 rate, struct spi_message *spi_msg) +{ + OSStatus result = 0; + + if (spi_slave_dev) + bk_spi_slave_deinit(); + + spi_slave_dev = os_malloc(sizeof(struct bk_spi_slave_dev)); + if (!spi_slave_dev) { + BK_SPI_PRT("[spi]:malloc memory for spi_dev failed\n"); + result = -1; + goto _exit; + } + os_memset(spi_slave_dev, 0, sizeof(struct bk_spi_slave_dev)); + + result = rtos_init_semaphore(&spi_slave_dev->rx_sem, 1); + if (result != kNoErr) { + BK_SPI_PRT("[spi]: spi rx semp init failed\n"); + goto _exit; + } + + bk_spi_slave_dma_config(mode, rate); + spi_dma_rx_init(spi_msg); + + return result; + +_exit: + + if (spi_slave_dev->rx_sem) + rtos_deinit_semaphore(&spi_slave_dev->rx_sem); + + if (spi_slave_dev) { + os_free(spi_slave_dev); + spi_slave_dev = NULL; + } + + return result; +} + +int bk_spi_slave_dma_tx_init(UINT32 mode, UINT32 rate, struct spi_message *spi_msg) +{ + OSStatus result = 0; + + if (spi_slave_dev) + bk_spi_slave_deinit(); + + spi_slave_dev = os_malloc(sizeof(struct bk_spi_slave_dev)); + if (!spi_slave_dev) { + BK_SPI_PRT("[spi]:malloc memory for spi_dev failed\n"); + result = -1; + goto _exit; + } + os_memset(spi_slave_dev, 0, sizeof(struct bk_spi_slave_dev)); + + result = rtos_init_semaphore(&spi_slave_dev->tx_sem, 1); + if (result != kNoErr) { + BK_SPI_PRT("[spi]: spi tx semp init failed\n"); + goto _exit; + } + + bk_spi_slave_dma_config(mode, rate); + spi_dma_tx_init(spi_msg); + + return result; + +_exit: + + if (spi_slave_dev->tx_sem) + rtos_deinit_semaphore(&spi_slave_dev->tx_sem); + + if (spi_slave_dev) { + os_free(spi_slave_dev); + spi_slave_dev = NULL; + } + + return result; +} + + +int bk_spi_slave_dma_send(struct spi_message *spi_msg) +{ + GLOBAL_INT_DECLARATION(); + ASSERT(spi_msg != NULL); + + GLOBAL_INT_DISABLE(); + spi_slave_dev->flag &= ~(TX_FINISH_FLAG); + GLOBAL_INT_RESTORE(); + + spi_dma_tx_enable(1); + + rtos_get_semaphore(&spi_slave_dev->tx_sem, BEKEN_NEVER_TIMEOUT); + + dma_trans_flag = 0; + + if (spi_msg->send_buf != NULL) + return dma_trans_flag; + else { + //os_printf("spi_dma tx error send_buff\r\n", spi_msg->send_buf); + return 1; + } +} + + +int bk_spi_slave_dma_recv(struct spi_message *spi_msg) +{ + GLOBAL_INT_DECLARATION(); + ASSERT(spi_msg != NULL); + + GLOBAL_INT_DISABLE(); + spi_dma_rx_enable(1); + GLOBAL_INT_RESTORE(); + + rtos_get_semaphore(&spi_slave_dev->rx_sem, BEKEN_WAIT_FOREVER); + + os_printf("get rx sem\n"); + return 0; +} + +void bk_slave_dma_tx_disable(void) +{ + GDMA_CFG_ST en_cfg; + + en_cfg.channel = SPI_TX_DMA_CHANNEL; + en_cfg.param = 0; + sddev_control(GDMA_DEV_NAME, CMD_GDMA_SET_DMA_ENABLE, &en_cfg); +} + +void bk_slave_dma_rx_disable(void) +{ + GDMA_CFG_ST en_cfg; + + en_cfg.channel = SPI_RX_DMA_CHANNEL; + en_cfg.param = 0; + sddev_control(GDMA_DEV_NAME, CMD_GDMA_SET_DMA_ENABLE, &en_cfg); +} + +#define LOOP_TEST_LEN 30*24 + +void spi_rx_loop_test(void *arg) +{ + struct spi_message msg; + + UINT8 *buf, *tx_buff; + int rx_len, ret, i; + int cnt = 0; + int err_cnt; + + rx_len = LOOP_TEST_LEN; + + //os_printf("spi dma rx: rx_len:%d\n", rx_len); + + tx_buff = os_malloc(rx_len * sizeof(UINT8)); + for (i = 0 ; i < 30 * 24; i++) + tx_buff[i] = 0x60 + i ; + + buf = os_malloc(rx_len * sizeof(UINT8)); + + if (!buf) + os_printf("spimalloc err\r\n"); + + os_memset(buf, 0, rx_len); + + msg.send_buf = NULL; + msg.send_len = 0; + msg.recv_buf = buf; + msg.recv_len = rx_len; + + UINT8 mode = SPI_MODE_0 | SPI_MSB | SPI_SLAVE; + UINT32 max_hz = 8 * 1000 * 1000; + + bk_spi_slave_dma_rx_init(mode, max_hz, &msg); + + while (1) { + err_cnt = 0; + ret = bk_spi_slave_dma_recv(&msg); + if (ret == 0) { + bk_slave_dma_rx_disable(); + for (i = 0; i < LOOP_TEST_LEN; i++) { + if (buf[i] != tx_buff[i]) { + if (err_cnt > 4) + break; + + os_printf("tx_buff[%d]=0x%x, buff[%d]=0x%x, \r\n", i, tx_buff[i], i, buf[i]); + err_cnt ++; + } + } + } + + cnt ++; + + os_printf("cnt:%d\r\n", cnt); + os_memset(buf, 0x55, rx_len); + } +} + +#if (!CFG_SUPPORT_RTT) + +xTaskHandle spi_dma_slave_rx_thread_handle = NULL; +uint32 spi_dma_slave_rx_thread_main(void) +{ + int ret; + + ret = rtos_create_thread(&spi_dma_slave_rx_thread_handle, + BEKEN_DEFAULT_WORKER_PRIORITY, + "spidma", + (beken_thread_function_t)spi_rx_loop_test, + 4096, + (beken_thread_arg_t)0); + if (ret != kNoErr) { + bk_printf("Error: airkiss_start_process: %d\r\n", ret); + goto init_err; + } + + return kNoErr; + +init_err: + return kGeneralErr; +} + +#endif +#endif //CFG_USE_SPI_DMA +#endif // CFG_USE_SPI_SLAVE +#endif //(CFG_SOC_NAME == SOC_BK7231N) + + diff --git a/beken_os/beken378/driver/spidma/spidma.c b/beken_os/beken378/driver/spidma/spidma.c new file mode 100755 index 0000000..3f8e699 --- /dev/null +++ b/beken_os/beken378/driver/spidma/spidma.c @@ -0,0 +1,549 @@ +#include "include.h" +#include "arm_arch.h" + +#if CFG_USE_SPIDMA + +#include "uart_pub.h" +#include "spidma_pub.h" +#include "spidma.h" + +#include "mem_pub.h" +#include "intc_pub.h" + +#include "icu_pub.h" +#include "gpio_pub.h" + +#if CFG_GENERAL_DMA +#include "general_dma_pub.h" +#endif + + +SPIDMA_DESC_PTR p_spidma_desc; +static DD_OPERATIONS spidma_op = +{ + spidma_open, + spidma_close, + NULL, + NULL, + spidma_ctrl +}; + +static void spidma_config_sck_invert(UINT32 negedge) +{ + UINT32 reg; + reg = REG_READ(SPI_DMA_REG0); + if(negedge) + reg |= SPIDMA_REG0_SCK_INV; + else + reg &= ~(SPIDMA_REG0_SCK_INV); + REG_WRITE(SPI_DMA_REG0, reg); +} + +static void spidma_config_LSB_first_transfer(UINT32 ture) +{ + UINT32 reg; + reg = REG_READ(SPI_DMA_REG0); + if(ture) + reg |= SPIDMA_REG0_LSB_FIRST; + else + reg &= ~(SPIDMA_REG0_LSB_FIRST); + REG_WRITE(SPI_DMA_REG0, reg); +} + +static void spidma_config_3wire_mode(UINT32 ture) +{ + UINT32 reg; + reg = REG_READ(SPI_DMA_REG0); + if(ture) + reg |= SPIDMA_REG0_WIRE3_EN; + else + reg &= ~(SPIDMA_REG0_WIRE3_EN); + REG_WRITE(SPI_DMA_REG0, reg); +} + +static void spidma_config_rxdata_timeout_val(UINT32 timeout) +{ + REG_WRITE(SPI_DMA_REG1, timeout & SPIDMA_REG1_TIMEOUT_MASK); +} + +#if (CFG_SOC_NAME == SOC_BK7231) +static void spidma_config_rxbuf_start_addr(UINT8 *rxbufptr) +{ + REG_WRITE(SPI_DMA_REG2_RXBUF_ADDR, (UINT32)rxbufptr); +} + +#ifdef SPIDMA_GET_RX_BUF_ADDR +static UINT8 *spidma_get_rxbuf_start_addr(void) +{ + return (UINT8 *)REG_READ(SPI_DMA_REG2_RXBUF_ADDR); +} +#endif + +static void spidma_config_rxbuf_length(UINT32 rxbuflen) +{ + UINT32 reg; + switch(rxbuflen) + { + case 1024: + reg = SPIDMA_RXBUFLEN_1024B; + break; + case 2048: + reg = SPIDMA_RXBUFLEN_2048B; + break; + case 4096: + reg = SPIDMA_RXBUFLEN_4096B; + break; + case 8192: + reg = SPIDMA_RXBUFLEN_8192B; + break; + case 16384: + reg = SPIDMA_RXBUFLEN_16384B; + break; + case 32768: + reg = SPIDMA_RXBUFLEN_32768B; + break; + case 65536: + reg = SPIDMA_RXBUFLEN_65536B; + break; + default: + reg = SPIDMA_RXBUFLEN_1024B; + break; + } + + REG_WRITE(SPI_DMA_REG3_RXBUF_LEN, reg); +} + +static void spidma_config_rx_threshold_int(UINT32 threshold) +{ + REG_WRITE(SPI_DMA_REG4_RXBUF_THRE, (threshold - 1)&SPIDMA_REG4_RXBUF_THRE_MASK); +} + +static UINT32 spidma_get_rx_threshold_val(void) +{ + return (REG_READ(SPI_DMA_REG4_RXBUF_THRE)&SPIDMA_REG4_RXBUF_THRE_MASK) + 1; +} + +static UINT32 spidma_config_get_rxbuf_readptr(void) +{ + return REG_READ(SPI_DMA_REG5_RXBUF_RDPTR) & SPIDMA_REG5_RXBUF_RDPTR_MASK; +} + +static void spidma_config_set_rxbuf_readptr(UINT32 rdptr) +{ + REG_WRITE(SPI_DMA_REG5_RXBUF_RDPTR, rdptr & SPIDMA_REG5_RXBUF_RDPTR_MASK); +} + +static UINT32 spidma_get_rxbuf_writeptr(void) +{ + return REG_READ(SPI_DMA_REG6_RXBUF_WRPTR)&SPIDMA_REG6_RXBUF_WRPTR_MASK; +} + +static void spidma_config_txbuf_start_addr(UINT8 *txbufptr) +{ + REG_WRITE(SPI_DMA_REG7_TXBUF_ADDR, (UINT32)txbufptr); +} + +static void spidma_config_txbuf_length(UINT32 txbuflen) +{ + REG_WRITE(SPI_DMA_REG8_TXBUF_LEN, txbuflen); +} + +static void spidma_set_txbuf_valid(UINT32 ture) +{ + if(ture) + REG_WRITE(SPI_DMA_REG9_TXBUF_VALID, 0x1); + else + REG_WRITE(SPI_DMA_REG9_TXBUF_VALID, 0x0); +} + +static UINT32 spidma_set_rxbuf_valid_datalen(void) +{ + return REG_READ(SPI_DMA_REG11) & SPIDMA_REG11_RXBUF_VLDNUM_MASK; +} +#endif // (CFG_SOC_NAME == SOC_BK7231) + +static void spidma_enable_interrupt(void) +{ + UINT32 param; + param = (FIQ_SPI_DMA_BIT); + sddev_control(ICU_DEV_NAME, CMD_ICU_INT_ENABLE, ¶m); +} + +static void spidma_disable_interrupt(void) +{ + UINT32 param; + param = (FIQ_SPI_DMA_BIT); + sddev_control(ICU_DEV_NAME, CMD_ICU_INT_DISABLE, ¶m); +} + +static void spidma_gpio_config(void) +{ + UINT32 param; + param = GFUNC_MODE_SPI_DMA; + sddev_control(GPIO_DEV_NAME, CMD_GPIO_ENABLE_SECOND, ¶m); +} + +#if (CFG_SOC_NAME != SOC_BK7231) +#if CFG_GENERAL_DMA +static void spidma_config_rxdma(void) +{ + GDMACFG_TPYES_ST cfg; + GDMA_CFG_ST en_cfg; + os_memset(&cfg, 0, sizeof(GDMACFG_TPYES_ST)); + + cfg.dstdat_width = 32; + cfg.srcdat_width = 8; + cfg.dstptr_incr = 1; + cfg.srcptr_incr = 0; + cfg.src_start_addr = (void*)SPI_DMA_REG3_RXFIFO; + cfg.dst_start_addr = &(p_spidma_desc->rxbuf[0]); + + cfg.channel = p_spidma_desc->dma_channel; + cfg.prio = 0; + cfg.u.type5.dst_loop_start_addr = &(p_spidma_desc->rxbuf[0]); + cfg.u.type5.dst_loop_end_addr = &(p_spidma_desc->rxbuf[p_spidma_desc->rxbuf_len]); + + //cfg.half_fin_handler = spidma_rxdma_handler; + cfg.fin_handler = p_spidma_desc->dma_rx_handler; + + cfg.src_module = GDMA_X_SRC_HSSPI_RX_REQ; + cfg.dst_module = GDMA_X_DST_DTCM_WR_REQ; + + sddev_control(GDMA_DEV_NAME, CMD_GDMA_CFG_TYPE5, &cfg); + + en_cfg.channel = p_spidma_desc->dma_channel; + en_cfg.param = p_spidma_desc->node_len; // dma translen + sddev_control(GDMA_DEV_NAME, CMD_GDMA_SET_TRANS_LENGTH, &en_cfg); + + en_cfg.channel = p_spidma_desc->dma_channel; + en_cfg.param = 1; + sddev_control(GDMA_DEV_NAME, CMD_GDMA_SET_DMA_ENABLE, &en_cfg); +} + +static void spidma_exit_rxdma(void) +{ + GDMA_CFG_ST en_cfg; + + en_cfg.channel = p_spidma_desc->dma_channel; + en_cfg.param = 0; // disable + sddev_control(GDMA_DEV_NAME, CMD_GDMA_SET_DMA_ENABLE, &en_cfg); +} +#endif // CFG_GENERAL_DMA +#endif // (CFG_SOC_NAME == SOC_BK7231) + +static void spidma_software_init(void) +{ + p_spidma_desc = NULL; + ddev_register_dev(SPIDMA_DEV_NAME, &spidma_op); +} + +static void spidma_hardware_init(void) +{ + UINT32 reg; + /* register interrupt */ + intc_service_register(FIQ_SPI_DMA, PRI_FIQ_SPI_DMA, spidma_isr); + + /* config spidma register0 to 0 */ + REG_WRITE(SPI_DMA_REG0, 0); + + /* config spidma registers, rx first */ + spidma_config_rxdata_timeout_val(SPIDMA_DEF_RXDATA_TIMEOUT_VAL); + + #if (CFG_SOC_NAME == SOC_BK7231) + spidma_config_rxbuf_start_addr(NULL); + spidma_config_rxbuf_length(0); + spidma_config_set_rxbuf_readptr(0); + spidma_config_rx_threshold_int(SPIDMA_DEF_RXDATA_THRE_INT); + + /* tx */ + spidma_config_txbuf_start_addr(NULL); + spidma_config_txbuf_length(0); + spidma_set_txbuf_valid(0); + + /* reset int status */ + reg = REG_READ(SPI_DMA_REG10_INT_STATUS); + REG_WRITE(SPI_DMA_REG10_INT_STATUS, reg); + REG_WRITE(SPI_DMA_REG11, 0); + #else + + /* reset int status */ + reg = REG_READ(SPI_DMA_REG5_STA); + REG_WRITE(SPI_DMA_REG5_STA, reg); + #endif // (CFG_SOC_NAME == SOC_BK7231) + + /* config gpio for spidam */ + spidma_gpio_config(); + +} + +void spidma_init(void) +{ + spidma_software_init(); + spidma_hardware_init(); +} + +static UINT32 spidma_open(UINT32 op_flag) +{ + UINT32 reg; + + if(!op_flag) + { + SPI_DMA_PRT("spidma_open op_flag is NULL\r\n"); + return SPIDMA_FAILURE; + } + + p_spidma_desc = (SPIDMA_DESC_PTR)op_flag; + + if(!p_spidma_desc->node_len) + { + SPI_DMA_PRT("spidma_open node_len is 0\r\n"); + return SPIDMA_FAILURE; + } + + spidma_config_rxdata_timeout_val(p_spidma_desc->timeout_val); + + #if (CFG_SOC_NAME == SOC_BK7231) + spidma_config_rxbuf_start_addr(p_spidma_desc->rxbuf); + spidma_config_rxbuf_length((p_spidma_desc->rxbuf_len)); + spidma_config_set_rxbuf_readptr(0); + spidma_config_rx_threshold_int((p_spidma_desc->mode >> SPIDMA_DESC_RX_THRED_POSI) + &SPIDMA_DESC_RX_THRED_MASK); + + //spidma_config_txbuf_start_addr(p_spidma_desc->txbuf); + spidma_config_txbuf_start_addr(NULL); + spidma_config_txbuf_length(0); + spidma_set_txbuf_valid(0); + + spidma_config_sck_invert((p_spidma_desc->mode >> SPIDMA_DESC_SCK_MODE_POSI) + &SPIDMA_DESC_SCK_MODE_MASK); + spidma_config_LSB_first_transfer((p_spidma_desc->mode >> SPIDMA_DESC_LSB_FIRST_POSI) + &SPIDMA_DESC_LSB_FIRST_MASK); + spidma_config_3wire_mode((p_spidma_desc->mode >> SPIDMA_DESC_3WIRE_MODE_POSI) + &SPIDMA_DESC_3WIRE_MODE_MASK); + reg = SPIDMA_REG0_SPI_EN + | SPIDMA_REG0_DMA_EN + | SPIDMA_REG0_TIMEOUT_INTEN + | SPIDMA_REG0_RXBUF_THRED_INTEN + | SPIDMA_REG0_TX_FINISH_INTEN + | SPIDMA_REG0_RXEN; + #else + #if CFG_GENERAL_DMA + spidma_config_rxdma(); + #endif + + spidma_config_sck_invert((p_spidma_desc->mode >> SPIDMA_DESC_SCK_MODE_POSI) + &SPIDMA_DESC_SCK_MODE_MASK); + spidma_config_LSB_first_transfer((p_spidma_desc->mode >> SPIDMA_DESC_LSB_FIRST_POSI) + &SPIDMA_DESC_LSB_FIRST_MASK); + spidma_config_3wire_mode((p_spidma_desc->mode >> SPIDMA_DESC_3WIRE_MODE_POSI) + &SPIDMA_DESC_3WIRE_MODE_MASK); + reg = SPIDMA_REG0_SPI_EN + | SPIDMA_REG0_TIMEOUT_INTEN + | SPIDMA_REG0_RXEN; + #endif // (CFG_SOC_NAME == SOC_BK7231) + + REG_WRITE(SPI_DMA_REG0, reg); + spidma_enable_interrupt(); + + return SPIDMA_SUCCESS; +} + +void spidma_uninit(void) +{ + +} + +static UINT32 spidma_close(void) +{ + UINT32 reg; + + #if (CFG_SOC_NAME != SOC_BK7231) + #if CFG_GENERAL_DMA + spidma_exit_rxdma(); + #endif + #endif // (CFG_SOC_NAME == SOC_BK7231) + + spidma_disable_interrupt(); + + reg = REG_READ(SPI_DMA_REG0); + #if (CFG_SOC_NAME == SOC_BK7231) + reg &= ~(SPIDMA_REG0_SPI_EN + | SPIDMA_REG0_DMA_EN + | SPIDMA_REG0_TIMEOUT_INTEN + | SPIDMA_REG0_RXBUF_THRED_INTEN + | SPIDMA_REG0_TX_FINISH_INTEN + | SPIDMA_REG0_RXEN); + #else + reg &= ~(SPIDMA_REG0_SPI_EN + | SPIDMA_REG0_TIMEOUT_INTEN + //| SPIDMA_REG0_TX_FINISH_INTEN + | SPIDMA_REG0_RXEN); + #endif // (CFG_SOC_NAME == SOC_BK7231) + REG_WRITE(SPI_DMA_REG0, reg); + + return SPIDMA_SUCCESS; +} + +#if (CFG_SOC_NAME == SOC_BK7231) +static void spidma_rx_handler(UINT32 timeout) +{ + UINT32 copy_len = 0, thre = 0, left_len = 0; + INT32 valid = 0; + UINT8 *rdaddr; + UINT32 cur_posi = spidma_config_get_rxbuf_readptr(); + + //REG_WRITE((0x00802800+(29*4)), 0x02); + + valid = REG_READ(SPI_DMA_REG11) & SPIDMA_REG11_RXBUF_VLDNUM_MASK; + thre = p_spidma_desc->node_len; + + left_len = (timeout) ? 0 : thre; + + while(valid > left_len ) { + copy_len = (valid > thre) ? thre : valid; + rdaddr = p_spidma_desc->rxbuf + (cur_posi & (p_spidma_desc->rxbuf_len - 1)); + if(p_spidma_desc->rx_handler != NULL) { + p_spidma_desc->rx_handler(rdaddr, copy_len); + } + valid -= copy_len; + cur_posi += copy_len; + } + + spidma_config_set_rxbuf_readptr(cur_posi); + + if(timeout) { + REG_WRITE(SPI_DMA_REG10_INT_STATUS, SPIDMA_INTSTA_RX_TIMEOUT); + if(p_spidma_desc->rx_timeout != NULL) + { + p_spidma_desc->rx_timeout(); + } + } + else { + REG_WRITE(SPI_DMA_REG10_INT_STATUS, SPIDMA_INTSTA_RXBUF_THRE); + } + + //REG_WRITE((0x00802800+(29*4)), 0x00); +} +#else +static void spidma_rx_handler() +{ + if(p_spidma_desc->end_frame_handler != NULL) + { + p_spidma_desc->end_frame_handler(); + } + + REG_WRITE(SPI_DMA_REG5_STA, SPIDMA_INTSTA_RX_TIMEOUT); +} +#endif // (CFG_SOC_NAME == SOC_BK7231) + +static void spidma_txfinish_handler(void) +{ + if(p_spidma_desc->tx_handler != NULL) + p_spidma_desc->tx_handler(); + //REG_WRITE(SPI_DMA_REG10_INT_STATUS, SPIDMA_INTSTA_TXFINISH); +} + +static void spidma_isr(void) +{ + UINT32 spidma_sta; + + #if (CFG_SOC_NAME == SOC_BK7231) + /*0, get isr status*/ + spidma_sta = REG_READ(SPI_DMA_REG10_INT_STATUS); + + /*1, handle isr branch*/ + if(spidma_sta & SPIDMA_INTSTA_RXBUF_THRE) + { + SPI_DMA_PRT("0\r\n"); + spidma_rx_handler(0); + } + else if(spidma_sta & SPIDMA_INTSTA_RX_TIMEOUT) + { + SPI_DMA_PRT("1\r\n"); + spidma_rx_handler(1); + } + if(spidma_sta & SPIDMA_INTSTA_TXFINISH) + { + SPI_DMA_PRT("2\r\n"); + spidma_txfinish_handler(); + } + #else + spidma_sta = REG_READ(SPI_DMA_REG5_STA); + + /*1, handle isr branch*/ + if(spidma_sta & SPIDMA_INTSTA_RX_TIMEOUT) + { + spidma_rx_handler(); + } + else if(spidma_sta & SPIDMA_INTSTA_TIMING_ERR) + { + os_printf("hspi_timing err\r\n"); + } + if(spidma_sta & SPIDMA_STA_TXFIFO_EMPTY) + { + spidma_txfinish_handler(); + } + #endif // (CFG_SOC_NAME == SOC_BK7231) +} + +static UINT32 spidma_ctrl(UINT32 cmd, void *param) +{ + UINT32 ret = SPIDMA_SUCCESS; + switch(cmd) + { + case SPIDMA_CMD_CONF_SCK_INV: + spidma_config_sck_invert(*((UINT32 *)param)); + break; + case SPIDMA_CMD_CONF_LSB_FIRST: + spidma_config_LSB_first_transfer(*((UINT32 *)param)); + break; + case SPIDMA_CMD_CONF_3WIRE_EN: + spidma_config_3wire_mode(*((UINT32 *)param)); + break; + case SPIDMA_CMD_CONF_TIMEOUT_VAL: + spidma_config_rxdata_timeout_val(*((UINT32 *)param)); + break; + #if (CFG_SOC_NAME == SOC_BK7231) + case SPIDMA_CMD_CONF_RXBUF_ADDR: + spidma_config_rxbuf_start_addr((UINT8 *)param); + break; + case SPIDMA_CMD_CONF_RXBUF_LEN: + spidma_config_rxbuf_length(*((UINT32 *)param)); + break; + case SPIDMA_CMD_CONF_RXDATA_THRE: + spidma_config_rx_threshold_int(*((UINT32 *)param)); + break; + case SPIDMA_CMD_GET_RXDATA_THRE: + ret = spidma_get_rx_threshold_val(); + break; + case SPIDMA_CMD_GET_RXBUF_RDPTR: + ret = spidma_config_get_rxbuf_readptr(); + break; + case SPIDMA_CMD_SET_RXBUF_RDPTR: + spidma_config_set_rxbuf_readptr(*((UINT32 *)param)); + break; + case SPIDMA_CMD_GET_RXBUF_WRPTR: + ret = spidma_get_rxbuf_writeptr(); + break; + case SPIDMA_CMD_CONF_TXBUF_ADDR: + spidma_config_txbuf_start_addr((UINT8 *)param); + break; + case SPIDMA_CMD_CONF_TXBUF_LEN: + spidma_config_txbuf_length(*((UINT32 *)param)); + break; + case SPIDMA_CMD_CONF_TXBUF_VALID: + spidma_set_txbuf_valid(*((UINT32 *)param)); + break; + case SPIDMA_CMD_GET_RXBUF_VALID_DATALEN: + ret = spidma_set_rxbuf_valid_datalen(); + break; + #endif // (CFG_SOC_NAME == SOC_BK7231) + default: + break; + } + + return ret; +} + +#endif // CFG_USE_SPIDMA + diff --git a/beken_os/beken378/driver/spidma/spidma.h b/beken_os/beken378/driver/spidma/spidma.h new file mode 100755 index 0000000..fb70a3c --- /dev/null +++ b/beken_os/beken378/driver/spidma/spidma.h @@ -0,0 +1,104 @@ +#ifndef __SPI_DMA_H__ +#define __SPI_DMA_H__ + +//#define SPI_DMA_DEBUG +#ifdef SPI_DMA_DEBUG +#define SPI_DMA_PRT os_printf +#else +#define SPI_DMA_PRT null_prf +#define SPI_DMA_WPRT null_prf +#endif + +#define SPI_DMA_BASE (0x00808000) + +#define SPI_DMA_REG0 (SPI_DMA_BASE + 0x00*4) +#define SPIDMA_REG0_SPI_EN (1 << 0) +#define SPIDMA_REG0_SCK_INV (1 << 1) +#define SPIDMA_REG0_LSB_FIRST (1 << 2) +#define SPIDMA_REG0_WIRE3_EN (1 << 3) +#if (CFG_SOC_NAME == SOC_BK7231) +#define SPIDMA_REG0_DMA_EN (1 << 4) +#define SPIDMA_REG0_TIMEOUT_INTEN (1 << 5) +#define SPIDMA_REG0_RXBUF_THRED_INTEN (1 << 6) +#define SPIDMA_REG0_TX_FINISH_INTEN (1 << 7) +#define SPIDMA_REG0_RXEN (1 << 8) +#else +#define SPIDMA_REG0_TIMEOUT_INTEN (1 << 4) +#define SPIDMA_REG0_TX_FINISH_INTEN (1 << 5) +#define SPIDMA_REG0_RXEN (1 << 6) +#endif // (CFG_SOC_NAME == SOC_BK7231) + +#define SPI_DMA_REG1 (SPI_DMA_BASE + 0x01*4) +#define SPIDMA_REG1_TIMEOUT_MASK (0xffffffU) + +#if (CFG_SOC_NAME == SOC_BK7231) +#define SPI_DMA_REG2_RXBUF_ADDR (SPI_DMA_BASE + 0x02*4) + +#define SPI_DMA_REG3_RXBUF_LEN (SPI_DMA_BASE + 0x03*4) +#define SPIDMA_REG3_RXBUF_LEN_MASK (0x7U) +#define SPIDMA_RXBUFLEN_1024B (0x0U) +#define SPIDMA_RXBUFLEN_2048B (0x1U) +#define SPIDMA_RXBUFLEN_4096B (0x2U) +#define SPIDMA_RXBUFLEN_8192B (0x3U) +#define SPIDMA_RXBUFLEN_16384B (0x4U) +#define SPIDMA_RXBUFLEN_32768B (0x5U) +#define SPIDMA_RXBUFLEN_65536B (0x6U) + +#define SPI_DMA_REG4_RXBUF_THRE (SPI_DMA_BASE + 0x04*4) +#define SPIDMA_REG4_RXBUF_THRE_MASK (0xffffU) + +#define SPI_DMA_REG5_RXBUF_RDPTR (SPI_DMA_BASE + 0x05*4) +#define SPIDMA_REG5_RXBUF_RDPTR_MASK (0xffffU) + +#define SPI_DMA_REG6_RXBUF_WRPTR (SPI_DMA_BASE + 0x06*4) +#define SPIDMA_REG6_RXBUF_WRPTR_MASK (0xffffU) + +#define SPI_DMA_REG7_TXBUF_ADDR (SPI_DMA_BASE + 0x07*4) + +#define SPI_DMA_REG8_TXBUF_LEN (SPI_DMA_BASE + 0x08*4) + +#define SPI_DMA_REG9_TXBUF_VALID (SPI_DMA_BASE + 0x09*4) + +#define SPI_DMA_REG10_INT_STATUS (SPI_DMA_BASE + 0x0a*4) +#define SPIDMA_INTSTA_RXBUF_THRE (1 << 0) +#define SPIDMA_INTSTA_RX_TIMEOUT (1 << 1) +#define SPIDMA_INTSTA_TXFINISH (1 << 2) + +#define SPI_DMA_REG11 (SPI_DMA_BASE + 0x0b*4) +#define SPIDMA_REG11_RXBUF_VLDNUM_POSI (0) +#define SPIDMA_REG11_RXBUF_VLDNUM_MASK (0xffffU) +#define SPIDMA_REG11_TIMING_ERR_STATUS (1 << 16) +#define SPIDMA_REG11_RXFIFO_OVERFLOW (1 << 17) +#define SPIDMA_REG11_RXFIFO_EMPTY (1 << 18) +#define SPIDMA_REG11_RXFIFO_FULL (1 << 19) +#define SPIDMA_REG11_RXBUF_FULL (1 << 20) +#define SPIDMA_REG11_RXBUF_EMPTY (1 << 21) +#else +#define SPI_DMA_REG3_RXFIFO (SPI_DMA_BASE + 0x03*4) +#define SPIDMA_REG3_RXFIFO_MASK (0xffffffffU) + +#define SPI_DMA_REG4_TXFIFO (SPI_DMA_BASE + 0x04*4) +#define SPIDMA_REG4_TXFIFO_MASK (0xffffffffU) + +#define SPI_DMA_REG5_STA (SPI_DMA_BASE + 0x05*4) +#define SPIDMA_INTSTA_RX_TIMEOUT (1 << 0) +#define SPIDMA_INTSTA_TIMING_ERR (1 << 1) +#define SPIDMA_STA_RXFIFO_OVERFLOW (1 << 2) +#define SPIDMA_STA_TXFIFO_OVERFLOW (1 << 3) +#define SPIDMA_STA_RXFIFO_EMPTY (1 << 4) +#define SPIDMA_STA_RXFIFO_FULL (1 << 5) +#define SPIDMA_STA_TXFIFO_EMPTY (1 << 6) +#define SPIDMA_STA_TXFIFO_FULL (1 << 7) +#endif // (CFG_SOC_NAME == SOC_BK7231) + + +#if CFG_USE_SPIDMA +static void spidma_isr(void); +static void spidma_rx_callback(UINT16 used_data_len); +static UINT32 spidma_open(UINT32 op_flag); +static UINT32 spidma_close(void); +static UINT32 spidma_ctrl(UINT32 cmd, void *param); +#endif + +#endif // __SPI_DMA_H__ + diff --git a/beken_os/beken378/driver/spidma/spidma_pub.h b/beken_os/beken378/driver/spidma/spidma_pub.h new file mode 100755 index 0000000..f5bf137 --- /dev/null +++ b/beken_os/beken378/driver/spidma/spidma_pub.h @@ -0,0 +1,120 @@ +#ifndef __SPI_DMA_PUB_H__ +#define __SPI_DMA_PUB_H__ + +#if CFG_USE_SPIDMA +#include "rtos_pub.h" + +#define SPIDMA_FAILURE (1) +#define SPIDMA_SUCCESS (0) + +#define SPIDMA_DEV_NAME "spidma" + +#define SPIDMA_CMD_MAGIC (0x0BCD0000) + +enum +{ + SPIDMA_CMD_CONF_SCK_INV = SPIDMA_CMD_MAGIC + 1, + SPIDMA_CMD_CONF_LSB_FIRST, + SPIDMA_CMD_CONF_3WIRE_EN, + SPIDMA_CMD_CONF_TIMEOUT_VAL, + SPIDMA_CMD_CONF_RXBUF_ADDR, + SPIDMA_CMD_CONF_RXBUF_LEN, + SPIDMA_CMD_CONF_RXDATA_THRE, + SPIDMA_CMD_GET_RXDATA_THRE, + SPIDMA_CMD_GET_RXBUF_RDPTR, + SPIDMA_CMD_SET_RXBUF_RDPTR, + SPIDMA_CMD_GET_RXBUF_WRPTR, + SPIDMA_CMD_CONF_TXBUF_ADDR, + SPIDMA_CMD_CONF_TXBUF_LEN, + SPIDMA_CMD_CONF_TXBUF_VALID, + SPIDMA_CMD_GET_RXBUF_VALID_DATALEN, +}; + +#define SPIDMA_DESC_SCK_MODE_MASK (0x1) +#define SPIDMA_DESC_SCK_MODE_POSI (0) +#define SPIDMA_DESC_LSB_FIRST_MASK (0x1) +#define SPIDMA_DESC_LSB_FIRST_POSI (1) +#define SPIDMA_DESC_3WIRE_MODE_MASK (0x1) +#define SPIDMA_DESC_3WIRE_MODE_POSI (2) +#define SPIDMA_DESC_RX_THRED_MASK (0xffffU) +#define SPIDMA_DESC_RX_THRED_POSI (3) +#define SPIDMA_DESC_CALLBK_RD_NEWP_MASK (0xffffU) +#define SPIDMA_DESC_CALLBK_CLR_RXTHRE_POSI (16) +#define SPIDMA_DESC_CALLBK_CLR_RXTIO_POSI (17) +#define SPIDMA_DESC_CALLBK_CLR_TXFIN_POSI (18) + +#if (CFG_SOC_NAME == SOC_BK7231) +typedef struct spidma_desc +{ + UINT8 *rxbuf; + UINT8 *txbuf; + UINT16 rxbuf_len; + UINT16 txbuf_len; + void (*rx_handler)(void *curptr, UINT32 newlen); + void (*rx_timeout)(void); + void (*tx_handler)(void); + /* mode: SPIDMA mode + * bit[0]: SPIDMA sck clock invert + * 0: posedge sample data + * 1: negedge sample data + * bit[1]: SPIDMA LSB transfer first + * 0: MSB transfer first + * 1: LSB transfer first + * bit[2]: SPIDMA 3-wire mode + * 0: 4-wire mode + * 1: 3-wire mode + * bit[3:19]: 16bit SPIDMA rxbuf threshold val + */ + UINT32 mode; + UINT32 timeout_val; + UINT32 node_len; +} SPIDMA_DESC_ST, *SPIDMA_DESC_PTR; +#else +typedef struct spidma_desc +{ + UINT8 *rxbuf; + + void (*node_full_handler)(void *curptr, UINT32 newlen, UINT32 is_eof, UINT32 frame_len); + void (*data_end_handler)(void); + + UINT16 rxbuf_len; + UINT16 rx_read_len; + UINT32 node_len; + + + UINT8 *txbuf; + void (*tx_handler)(void); + + /* mode: SPIDMA mode + * bit[0]: SPIDMA sck clock invert + * 0: posedge sample data + * 1: negedge sample data + * bit[1]: SPIDMA LSB transfer first + * 0: MSB transfer first + * 1: LSB transfer first + * bit[2]: SPIDMA 3-wire mode + * 0: 4-wire mode + * 1: 3-wire mode + * bit[3:19]: 16bit SPIDMA rxbuf threshold val + */ + UINT32 mode; + UINT32 timeout_val; + UINT32 txbuf_len; + void (*end_frame_handler)(void); +#if CFG_GENERAL_DMA + void (*dma_rx_handler)(UINT32); + UINT32 dma_channel; +#endif +} SPIDMA_DESC_ST, *SPIDMA_DESC_PTR; +#endif + +#define SPIDMA_DEF_RXDATA_TIMEOUT_VAL (800) // Unit is Tahb_clk +#define SPIDMA_DEF_RXDATA_THRE_INT (4096) //(1024) + +void spidma_init(void); +void spidma_uninit(void); + +#endif // CFG_USE_SPIDMA + +#endif + diff --git a/beken_os/beken378/driver/sys_ctrl/sys_ctrl.c b/beken_os/beken378/driver/sys_ctrl/sys_ctrl.c new file mode 100755 index 0000000..5e799df --- /dev/null +++ b/beken_os/beken378/driver/sys_ctrl/sys_ctrl.c @@ -0,0 +1,2249 @@ +#include "include.h" +#include "arm_arch.h" + +#include "sys_ctrl_pub.h" +#include "sys_ctrl.h" +#include "target_util_pub.h" +#include "drv_model_pub.h" +#include "uart_pub.h" +#include "flash_pub.h" +#include "power_save_pub.h" +#include "intc_pub.h" +#include "icu_pub.h" +#include "gpio_pub.h" +#include "reg_rc.h" +#include "co_math.h" +#include "rw_pub.h" +#include "manual_ps_pub.h" +#include "mcu_ps_pub.h" +#include "ps_debug_pub.h" +#include "ble_pub.h" +#include "start_type_pub.h" +#include "bk7011_cal_pub.h" +#include "phy_trident.h" +#include "wdt_pub.h" + +#define DPLL_DIV 0x0 +#define DCO_CALIB_26M 0x1 +#define DCO_CALIB_60M 0x2 +#define DCO_CALIB_80M 0x3 +#define DCO_CALIB_120M 0x4 +#define DCO_CALIB_180M 0x5 + +#if (CFG_SOC_NAME == SOC_BK7221U) +#define DCO_CLK_SELECT DCO_CALIB_180M +#define USE_DCO_CLK_POWON 1 +#else +#define DCO_CLK_SELECT DCO_CALIB_120M +#define USE_DCO_CLK_POWON 0 //BK7231N could not using DCO as main clock when boot since DCO_AMSEL_BIT should be disable during calibration +#endif + +static UINT32 limit_freq_status = 0; +static SCTRL_PS_SAVE_VALUES ps_saves[2]; +#if CFG_USE_LOW_IDLE_PS +static UINT32 ps_saves_gpio_cfgs[32]; +#endif +extern UINT32 wdt_ctrl(UINT32 cmd, void *param); + + +static UINT32 deep_sleep_gpio_floating_map = 0; + +static SCTRL_MCU_PS_INFO sctrl_mcu_ps_info = +{ + .hw_sleep = 0, + .mcu_use_dco = 0, + .first_sleep = 1, +}; + + +static SDD_OPERATIONS sctrl_op = +{ + sctrl_ctrl +}; + +UINT8 rf_sleeped = 0; +UINT8 sta_rf_sleeped = 0; + +extern void WFI( void ); +/**********************************************************************/ +void sctrl_dpll_delay10us(void) +{ + volatile UINT32 i = 0; + + for(i = 0; i < DPLL_DELAY_TIME_10US; i ++) + { + ; + } +} + +void sctrl_dpll_delay200us(void) +{ + volatile UINT32 i = 0; + + for(i = 0; i < DPLL_DELAY_TIME_200US; i ++) + { + ; + } +} + +void sctrl_ps_dpll_delay(UINT32 time) +{ + volatile UINT32 i = 0; + + for(i = 0; i < time; i ++) + { + ; + } +} + +void sctrl_cali_dpll(UINT8 flag) +{ + UINT32 param; + extern void bk7011_update_tx_power_when_cal_dpll(int start_or_stop); + + bk7011_update_tx_power_when_cal_dpll(1); + param = sctrl_analog_get(SCTRL_ANALOG_CTRL0); + param &= ~(SPI_TRIG_BIT); + sctrl_analog_set(SCTRL_ANALOG_CTRL0, param); + + if(!flag) + sctrl_dpll_delay10us(); + else + sctrl_ps_dpll_delay(60); + + param |= (SPI_TRIG_BIT); + sctrl_analog_set(SCTRL_ANALOG_CTRL0, param); + + param = sctrl_analog_get(SCTRL_ANALOG_CTRL0); + param &= ~(SPI_DET_EN); + sctrl_analog_set(SCTRL_ANALOG_CTRL0, param); + + if(!flag) + sctrl_dpll_delay200us(); + else + sctrl_ps_dpll_delay(340); + + param = sctrl_analog_get(SCTRL_ANALOG_CTRL0); + param |= (SPI_DET_EN); + sctrl_analog_set(SCTRL_ANALOG_CTRL0, param); + + bk7011_update_tx_power_when_cal_dpll(0); +} + +void sctrl_dpll_isr(void) +{ + if ((DEVICE_ID_BK7231N_P & DEVICE_ID_MASK) != (sctrl_ctrl(CMD_GET_DEVICE_ID, NULL) & DEVICE_ID_MASK)) + { + os_null_printf("BIAS Cali\r\n"); + bk7011_cal_bias(); + } + sddev_control(GPIO_DEV_NAME, CMD_GPIO_CLR_DPLL_UNLOOK_INT, NULL); + sctrl_cali_dpll(0); + + os_printf("DPLL Unlock\r\n"); +} + +void sctrl_dpll_int_open(void) +{ + UINT32 param; + param = (FIQ_DPLL_UNLOCK_BIT); + sddev_control(ICU_DEV_NAME, CMD_ICU_INT_ENABLE, ¶m); + + #if (CFG_SOC_NAME != SOC_BK7231) + param = 1; + sddev_control(GPIO_DEV_NAME, CMD_GPIO_EN_DPLL_UNLOOK_INT, ¶m); + #endif +} + +void sctrl_dpll_int_close(void) +{ + UINT32 param; + + #if (CFG_SOC_NAME != SOC_BK7231) + param = 0; + sddev_control(GPIO_DEV_NAME, CMD_GPIO_EN_DPLL_UNLOOK_INT, ¶m); + #endif + + param = (FIQ_DPLL_UNLOCK_BIT); + sddev_control(ICU_DEV_NAME, CMD_ICU_INT_DISABLE, ¶m); +} + +void sctrl_dco_cali(UINT32 speed) +{ + UINT32 reg_val; + + switch(speed) + { + case DCO_CALIB_180M: + reg_val = sctrl_analog_get(SCTRL_ANALOG_CTRL1); + reg_val &= ~((DCO_CNTI_MASK << DCO_CNTI_POSI) | (DCO_DIV_MASK << DCO_DIV_POSI)); + reg_val |= ((0xDD & DCO_CNTI_MASK) << DCO_CNTI_POSI); +#if (CFG_SOC_NAME != SOC_BK7231N) + reg_val |= DIV_BYPASS_BIT; +#endif + sctrl_analog_set(SCTRL_ANALOG_CTRL1, reg_val); + break; + + case DCO_CALIB_120M: + reg_val = sctrl_analog_get(SCTRL_ANALOG_CTRL1); + reg_val &= ~((DCO_CNTI_MASK << DCO_CNTI_POSI) | (DCO_DIV_MASK << DCO_DIV_POSI)); + reg_val |= ((0x127 & DCO_CNTI_MASK) << DCO_CNTI_POSI); + sctrl_analog_set(SCTRL_ANALOG_CTRL1, reg_val); + break; + + case DCO_CALIB_80M: + reg_val = sctrl_analog_get(SCTRL_ANALOG_CTRL1); + reg_val &= ~((DCO_CNTI_MASK << DCO_CNTI_POSI) | (DCO_DIV_MASK << DCO_DIV_POSI)); + reg_val |= ((0x0C5 & DCO_CNTI_MASK) << DCO_CNTI_POSI); + sctrl_analog_set(SCTRL_ANALOG_CTRL1, reg_val); + break; + + case DCO_CALIB_60M: + reg_val = sctrl_analog_get(SCTRL_ANALOG_CTRL1); + reg_val &= ~((DCO_CNTI_MASK << DCO_CNTI_POSI) | (DCO_DIV_MASK << DCO_DIV_POSI)); + reg_val |= ((0x127 & DCO_CNTI_MASK) << DCO_CNTI_POSI); + reg_val |= ((0x02 & DCO_DIV_MASK) << DCO_DIV_POSI); + sctrl_analog_set(SCTRL_ANALOG_CTRL1, reg_val); + break; + + default: + reg_val = sctrl_analog_get(SCTRL_ANALOG_CTRL1); + reg_val &= ~((DCO_CNTI_MASK << DCO_CNTI_POSI) | (DCO_DIV_MASK << DCO_DIV_POSI)); + reg_val |= ((0xC0 & DCO_CNTI_MASK) << DCO_CNTI_POSI); + reg_val |= ((0x03 & DCO_DIV_MASK) << DCO_DIV_POSI); + sctrl_analog_set(SCTRL_ANALOG_CTRL1, reg_val); + break; + } + + reg_val = sctrl_analog_get(SCTRL_ANALOG_CTRL1); + reg_val &= ~(SPI_RST_BIT); +#if (CFG_SOC_NAME == SOC_BK7231N) + reg_val &= ~(DCO_AMSEL_BIT); +#endif + sctrl_analog_set(SCTRL_ANALOG_CTRL1, reg_val); + + reg_val = sctrl_analog_get(SCTRL_ANALOG_CTRL1); + reg_val |= SPI_RST_BIT; + sctrl_analog_set(SCTRL_ANALOG_CTRL1, reg_val); + + reg_val = sctrl_analog_get(SCTRL_ANALOG_CTRL1); + reg_val |= DCO_TRIG_BIT; + sctrl_analog_set(SCTRL_ANALOG_CTRL1, reg_val); + + reg_val = sctrl_analog_get(SCTRL_ANALOG_CTRL1); + reg_val &= ~(DCO_TRIG_BIT); + sctrl_analog_set(SCTRL_ANALOG_CTRL1, reg_val); +} + +void sctrl_set_cpu_clk_dco(void) +{ + UINT32 reg_val; + + reg_val = REG_READ(SCTRL_CONTROL); + reg_val &= ~(MCLK_MUX_MASK << MCLK_MUX_POSI); + + reg_val |= ((MCLK_FIELD_DCO&MCLK_MUX_MASK) << MCLK_MUX_POSI); + reg_val |= HCLK_DIV2_EN_BIT; + delay(10); + REG_WRITE(SCTRL_CONTROL, reg_val); + reg_val &= ~(MCLK_DIV_MASK << MCLK_DIV_POSI); + REG_WRITE(SCTRL_CONTROL, reg_val); +} + +#if CFG_USE_STA_PS +void sctrl_flash_select_dco(void) +{ + UINT32 reg; + UINT32 status; + DD_HANDLE flash_hdl; + + /* Flash 26MHz clock select dco clock*/ + flash_hdl = ddev_open(FLASH_DEV_NAME, &status, 0); + ASSERT(DD_HANDLE_UNVALID != flash_hdl); + ddev_control(flash_hdl, CMD_FLASH_SET_DCO, 0); + /* flash get id shouldn't remove*/ + ddev_control(flash_hdl, CMD_FLASH_GET_ID, ®); +} + +void sctrl_sta_ps_init(void) +{ + UINT32 reg; + extern void power_save_wakeup_isr(void); + + reg = REG_READ(SCTRL_LOW_PWR_CLK); + reg &=~(LPO_CLK_MUX_MASK); +#if (CFG_SOC_NAME == SOC_BK7231) + reg |=(LPO_SRC_32K_DIV << LPO_CLK_MUX_POSI); +#else + reg |=(LPO_SRC_ROSC << LPO_CLK_MUX_POSI); +#endif + REG_WRITE(SCTRL_LOW_PWR_CLK, reg); + +#if ((CFG_SOC_NAME == SOC_BK7231U) || (CFG_SOC_NAME == SOC_BK7221U)) + reg = REG_READ(SCTRL_BLOCK_EN_MUX); + reg &=~(0x1FF); + reg |=(0x40); + REG_WRITE(SCTRL_BLOCK_EN_MUX, reg); +#endif + + #if PS_WAKEUP_MOTHOD_RW + intc_service_register(FIQ_MAC_WAKEUP, PRI_FIQ_MAC_WAKEUP, power_save_wakeup_isr); + nxmac_enable_lp_clk_switch_setf(0x01); + os_null_printf("sctrl_sta_ps_init\r\n"); + #endif + + sctrl_flash_select_dco(); + + power_save_rf_ps_wkup_semlist_init(); + +} +#endif + +#if CFG_USE_BLE_PS +void sctrl_ble_ps_init(void) +{ +} +#endif + +void sctrl_init(void) +{ + UINT32 param; + + sddev_register_dev(SCTRL_DEV_NAME, &sctrl_op); + +#if (CFG_SUPPORT_BOOTLOADER) + /* huaming20210729: system power up with 26MHZ, to fix bootup hung issue */ + /* huaming20220625: clock source change policy: "high->low: mux,div; low->high: div,mux" */ + + param = REG_READ(SCTRL_CONTROL); + param &= ~(MCLK_MUX_MASK << MCLK_MUX_POSI); + param |= (MCLK_FIELD_26M_XTAL << MCLK_MUX_POSI); + REG_WRITE(SCTRL_CONTROL, param); + param &= ~(MCLK_DIV_MASK << MCLK_DIV_POSI); + REG_WRITE(SCTRL_CONTROL, param); +#else + /*enable blk clk + Attention: ENABLE 26m xtal block(BLK_BIT_26M_XTAL), for protect 32k circuit + */ + param = BLK_BIT_26M_XTAL | BLK_BIT_DPLL_480M | BLK_BIT_XTAL2RF | BLK_BIT_DCO; + sctrl_ctrl(CMD_SCTRL_BLK_ENABLE, ¶m); +#endif + + /*sys_ctrl <0x4c> */ + param = 0x00171710;//0x00151510; LDO BIAS CALIBRATION + REG_WRITE(SCTRL_BIAS, param); + + /*sys_ctrl <0x16>, trig spi */ + //170209,from 0x819A54B to 0x819A55B for auto detect dpll unlock + //170614 from 0x819A55B to 0x819A59B for more easy to trigger + //BK7231U 2018.11.06 from 0xF819A59B to 0x0819A59B for xtal current + #if (CFG_SOC_NAME == SOC_BK7231) + param = 0x819A59B; +#elif (CFG_SOC_NAME == SOC_BK7231N) +#if (CFG_XTAL_FREQUENCE == CFG_XTAL_FREQUENCE_40M) + param = 0x71125B57; +#else + param = 0x71104953;//wangjian20200918 Reg0x16<3:1>=1 Reg0x16<9>=0 Reg0x16<13:10>=2 +#endif + #else + param = 0x0819A59B;//0x819A59B; + #endif // (CFG_SOC_NAME == SOC_BK7231) + sctrl_analog_set(SCTRL_ANALOG_CTRL0, param); + + sctrl_cali_dpll(0); + +#if (CFG_SOC_NAME == SOC_BK7231N) + param = 0x3CC019C2;//wangjian20200918 Reg0x17<1>=1 +#else + param = 0x6AC03102; +#endif + sctrl_analog_set(SCTRL_ANALOG_CTRL1, param); + /*do dco Calibration*/ + sctrl_dco_cali(DCO_CLK_SELECT); + + #if (CFG_SOC_NAME == SOC_BK7231) + param = 0x24006000; +#elif (CFG_SOC_NAME == SOC_BK7231N) + if ((DEVICE_ID_BK7231N_P & DEVICE_ID_MASK) == (sctrl_ctrl(CMD_GET_DEVICE_ID, NULL) & DEVICE_ID_MASK)) + { + param = 0x580120E2;//wangjian20210422<28:23>=30 as default for BK7231P, qunshan20211109<17:16>=1 for BK7231P + } + else + { + param = 0x500020E2;//0x400020E0; //wangjian20200822 0x40032030->0x48032030->0x48022032//wangjian20200903<17:16>=0//qunshan20201127<28:23>=20 + } +#else + param = 0x24006080; // xtalh_ctune // 24006080 + param &= ~(XTALH_CTUNE_MASK<< XTALH_CTUNE_POSI); + param |= ((0x10&XTALH_CTUNE_MASK) << XTALH_CTUNE_POSI); + #endif // (CFG_SOC_NAME == SOC_BK7231) + sctrl_analog_set(SCTRL_ANALOG_CTRL2, param); + + #if (CFG_SOC_NAME == SOC_BK7221U) + param = CHARGE_ANALOG_CTRL3_CHARGE_DEFAULT_VALUE; +#elif (CFG_SOC_NAME == SOC_BK7231N) + param = 0x70000000; //wangjiang20200822 0x00000000->0x70000000 + #else + param = 0x4FE06C50; + #endif + sctrl_analog_set(SCTRL_ANALOG_CTRL3, param); + + /*sys_ctrl <0x1a> */ + #if (CFG_SOC_NAME == SOC_BK7231) + param = 0x59E04520; + #elif (CFG_SOC_NAME == SOC_BK7221U) + param = CHARGE_ANALOG_CTRL4_CHARGE_DEFAULT_VALUE; +#elif (CFG_SOC_NAME == SOC_BK7231N) + param = 0x19C04520; + #else + param = 0x59C04520; // 0x59E04520 + #endif // (CFG_SOC_NAME == SOC_BK7231) + sctrl_analog_set(SCTRL_ANALOG_CTRL4, param); + + /*regist intteruppt handler for Dpll unlock*/ + intc_service_register(FIQ_DPLL_UNLOCK, PRI_FIQ_DPLL_UNLOCK, sctrl_dpll_isr); + + /*mac & modem power up */ + sctrl_ctrl(CMD_SCTRL_MAC_POWERUP, NULL); + sctrl_ctrl(CMD_SCTRL_MODEM_POWERUP, NULL); + + sctrl_sub_reset(); + +#if (CFG_SOC_NAME == SOC_BK7231N) + if ((DEVICE_ID_BK7231N_P & DEVICE_ID_MASK) != (sctrl_ctrl(CMD_GET_DEVICE_ID, NULL) & DEVICE_ID_MASK)) { + sctrl_fix_dpll_div(); + } +#endif + + /*sys ctrl clk gating, for rx dma dead*/ + REG_WRITE(SCTRL_CLK_GATING, 0x3f); + + /* increase VDD voltage*/ + #if 1//CFG_SYS_REDUCE_NORMAL_POWER + param = 4; + #else + param = 5; + #endif + /* zhangheng modify to 4 without enable CFG_SYS_REDUCE_NORMAL_POWER, to reduce power by set vdd value, advised by xubin */ + param = 4; + sctrl_ctrl(CMD_SCTRL_SET_VDD_VALUE, ¶m); + + /*32K Rosc calib*/ + REG_WRITE(SCTRL_ROSC_CAL, 0x7); + + #if (CFG_SOC_NAME == SOC_BK7221U) + #if (CFG_USE_AUDIO) + sctrl_analog_set(SCTRL_ANALOG_CTRL8, 0x0033187C); + sctrl_analog_set(SCTRL_ANALOG_CTRL9, 0x82204007); + sctrl_analog_set(SCTRL_ANALOG_CTRL10, 0x80801433); + #endif // CFG_USE_AUDIO + #endif // (CFG_SOC_NAME == SOC_BK7221U) + + #if (RHINO_CONFIG_CPU_PWR_MGMT & CFG_USE_STA_PS) + sctrl_mcu_init(); + #endif + + /*config main clk*/ + #if USE_DCO_CLK_POWON + sctrl_set_cpu_clk_dco(); + #else + param = REG_READ(SCTRL_CONTROL); + param &= ~(MCLK_DIV_MASK << MCLK_DIV_POSI); + #if (CFG_SOC_NAME == SOC_BK7221U) + /* BK7221U ahb bus max rate is 90MHZ, so ahb bus need div 2 from MCU clock */ + /* AHB bus is very import to AUDIO and DMA */ + param |= HCLK_DIV2_EN_BIT; + #endif // (CFG_SOC_NAME == SOC_BK7221U) + #if CFG_SYS_REDUCE_NORMAL_POWER + param |= ((MCLK_DIV_7 & MCLK_DIV_MASK) << MCLK_DIV_POSI); + #elif (CFG_SOC_NAME == SOC_BK7231N) + param |= ((MCLK_DIV_5 & MCLK_DIV_MASK) << MCLK_DIV_POSI); + #else // CFG_SYS_REDUCE_NORMAL_POWER + param |= ((MCLK_DIV_3 & MCLK_DIV_MASK) << MCLK_DIV_POSI); + #endif // CFG_SYS_REDUCE_NORMAL_POWER + REG_WRITE(SCTRL_CONTROL, param); + param &= ~(MCLK_MUX_MASK << MCLK_MUX_POSI); + param |= ((MCLK_FIELD_DPLL & MCLK_MUX_MASK) << MCLK_MUX_POSI); + REG_WRITE(SCTRL_CONTROL, param); + #endif // (!USE_DCO_CLK_POWON) + +} + +void sctrl_exit(void) +{ + sddev_unregister_dev(SCTRL_DEV_NAME); +} + +void sctrl_modem_core_reset(void) +{ + sctrl_ctrl(CMD_SCTRL_MODEM_CORE_RESET, 0); +} + +void sctrl_sub_reset(void) +{ + sctrl_ctrl(CMD_SCTRL_MPIF_CLK_INVERT, 0); + sctrl_ctrl(CMD_SCTRL_MODEM_CORE_RESET, 0); + sctrl_ctrl(CMD_SCTRL_MODEM_SUBCHIP_RESET, 0); + sctrl_ctrl(CMD_SCTRL_MAC_SUBSYS_RESET, 0); + sctrl_ctrl(CMD_SCTRL_USB_SUBSYS_RESET, 0); +} + +void ps_delay(volatile UINT16 times) +{ + UINT32 delay = times; + while(delay--) ; +} + +void sctrl_ps_dump() +{ + UINT32 i; + + os_printf("reg dump\r\n"); + os_printf("sys\r\n0x%8x:0x%8x\r\n", SCTRL_CONTROL, REG_READ(SCTRL_CONTROL)); + os_printf("0x%8x:0x%8x\r\n", SCTRL_MODEM_CORE_RESET_PHY_HCLK, REG_READ(SCTRL_MODEM_CORE_RESET_PHY_HCLK)); + os_printf("0x%8x:0x%8x\r\n", SCTRL_BLOCK_EN_CFG, REG_READ(SCTRL_BLOCK_EN_CFG)); + os_printf("0x%8x:0x%8x\r\n", SCTRL_ROSC_CAL, REG_READ(SCTRL_ROSC_CAL)); + os_printf("0x%8x:0x%8x\r\n", SCTRL_ANALOG_CTRL2, sctrl_analog_get(SCTRL_ANALOG_CTRL2)); + os_printf("0x%8x:0x%8x\r\n", ICU_INTERRUPT_ENABLE, REG_READ(ICU_INTERRUPT_ENABLE)); + os_printf("0x%8x:0x%8x\r\n", ICU_PERI_CLK_PWD, REG_READ(ICU_PERI_CLK_PWD)); + os_printf("0x%8x:0x%8x\r\n", SCTRL_SLEEP, REG_READ(SCTRL_SLEEP)); + os_printf("0x%8x:0x%8x\r\n", ICU_ARM_WAKEUP_EN, REG_READ(ICU_ARM_WAKEUP_EN)); + os_printf("mac\r\n0x%8x:0x%8x\r\n", NXMAC_TIMERS_INT_UN_MASK_ADDR, nxmac_timers_int_un_mask_get()); + os_printf("0x%8x:0x%8x\r\n", NXMAC_DOZE_CNTRL_1_ADDR, nxmac_doze_cntrl_1_get()); + os_printf("0x%8x:0x%8x\r\n", NXMAC_DOZE_CNTRL_2_ADDR, nxmac_doze_cntrl_2_get()); + os_printf("0x%8x:0x%8x\r\n", NXMAC_BCN_CNTRL_1_ADDR, nxmac_bcn_cntrl_1_get()); + os_printf("saves dump\r\n"); + for(i = 0; i < (3 * (sizeof(SCTRL_PS_SAVE_VALUES) / 4)); i++) + os_printf(" %d 0x%x\r\n", i, *((UINT32 *)(&ps_saves) + i)); +} + +void sctrl_hw_sleep(UINT32 peri_clk) +{ + UINT32 reg; + PS_DEBUG_DOWN_TRIGER; + + if(4 == flash_get_line_mode()) + { + flash_set_line_mode(2); + } + + + if(power_save_if_rf_sleep()) + { + reg = REG_READ(ICU_ARM_WAKEUP_EN); + reg |= (MAC_ARM_WAKEUP_EN_BIT); + REG_WRITE(ICU_ARM_WAKEUP_EN, reg); + } + + #if CFG_USE_BLE_PS + if(if_ble_sleep()) + { + reg = REG_READ(ICU_ARM_WAKEUP_EN); + reg |= (BLE_ARM_WAKEUP_EN_BIT); + #if (CFG_SOC_NAME == SOC_BK7231N) + reg |= (BTDM_ARM_WAKEUP_EN_BIT); + #endif + + REG_WRITE(ICU_ARM_WAKEUP_EN, reg); + } + #endif + + PS_DEBUG_DOWN_TRIGER; + +#if ((CFG_SOC_NAME == SOC_BK7231) || (CFG_SOC_NAME == SOC_BK7231U) || (CFG_SOC_NAME == SOC_BK7221U)) + REG_WRITE(SCTRL_ROSC_CAL, 0x35); + REG_WRITE(SCTRL_ROSC_CAL, 0x37); +#endif + + if(sctrl_mcu_ps_info.mcu_use_dco == 0) + { + /* MCLK(main clock) select:dco*/ + reg = REG_READ(SCTRL_CONTROL); + reg &= ~(MCLK_DIV_MASK << MCLK_DIV_POSI); + REG_WRITE(SCTRL_CONTROL, reg); + reg = REG_READ(SCTRL_CONTROL); + reg &= ~(MCLK_MUX_MASK << MCLK_MUX_POSI); + REG_WRITE(SCTRL_CONTROL, reg); + PS_DEBUG_DOWN_TRIGER; + } + + /*close 32K Rosc calib*/ +#if (CFG_SOC_NAME == SOC_BK7231) + REG_WRITE(SCTRL_ROSC_CAL, 0x36); +#endif + PS_DEBUG_DOWN_TRIGER; + /* dpll division reset*/ + reg = REG_READ(SCTRL_CONTROL); + reg |= DPLL_CLKDIV_RESET_BIT; + REG_WRITE(SCTRL_CONTROL, reg); + PS_DEBUG_DOWN_TRIGER; + /* dpll (480m) & xtal2rf disable*/ + reg = REG_READ(SCTRL_BLOCK_EN_CFG); + reg &= ~(BLOCK_EN_WORD_MASK << BLOCK_EN_WORD_POSI); + reg = reg | (BLOCK_EN_WORD_PWD << BLOCK_EN_WORD_POSI); + reg &= ~(BLK_EN_DPLL_480M | BLK_EN_XTAL2RF ); + REG_WRITE(SCTRL_BLOCK_EN_CFG, reg); + PS_DEBUG_DOWN_TRIGER; + /* center bias power down*/ + reg = sctrl_analog_get(SCTRL_ANALOG_CTRL2); + reg &= (~(CENTRAL_BAIS_ENABLE_BIT)); + sctrl_analog_set(SCTRL_ANALOG_CTRL2, reg); + sctrl_mcu_ps_info.hw_sleep = 1; + + while(sctrl_analog_get(SCTRL_ANALOG_CTRL2) & (CENTRAL_BAIS_ENABLE_BIT)); + + PS_DEBUG_DOWN_TRIGER; +#if PS_CLOSE_PERI_CLK + /* close all peri clock*/ + ps_saves[0].peri_clk_cfg= REG_READ(ICU_PERI_CLK_PWD); + REG_WRITE(ICU_PERI_CLK_PWD, peri_clk); +#endif + + ps_delay(1); + /* arm clock disable */ + reg = REG_READ(SCTRL_SLEEP); + reg &= ~(SLEEP_MODE_MASK << SLEEP_MODE_POSI); + reg = reg | SLEEP_MODE_CFG_NORMAL_VOL_WORD; + REG_WRITE(SCTRL_SLEEP, reg); + ps_delay(1);//5 +} + +void sctrl_hw_wakeup() +{ + UINT32 reg; + + PS_DEBUG_BCN_TRIGER; + /* center bias power on*/ + reg = sctrl_analog_get(SCTRL_ANALOG_CTRL2); + reg |= CENTRAL_BAIS_ENABLE_BIT; + sctrl_analog_set(SCTRL_ANALOG_CTRL2, reg); + + while((sctrl_analog_get(SCTRL_ANALOG_CTRL2) & CENTRAL_BAIS_ENABLE_BIT) == 0); + + + /*dpll(480m) & xtal2rf enable*/ + reg = REG_READ(SCTRL_BLOCK_EN_CFG); + reg &= ~(BLOCK_EN_WORD_MASK << BLOCK_EN_WORD_POSI); + reg |= (BLOCK_EN_WORD_PWD << BLOCK_EN_WORD_POSI); + reg |= ( BLK_EN_DPLL_480M | BLK_EN_XTAL2RF ); + REG_WRITE(SCTRL_BLOCK_EN_CFG, reg); + ps_delay(10); + PS_DEBUG_BCN_TRIGER; + + if(sctrl_mcu_ps_info.mcu_use_dco == 0) + { + /* MCLK(main clock) select:26M*/ + reg = REG_READ(SCTRL_CONTROL); + reg &= ~(MCLK_MUX_MASK << MCLK_MUX_POSI); + reg |= ((MCLK_FIELD_26M_XTAL & MCLK_MUX_MASK) << MCLK_MUX_POSI); + REG_WRITE(SCTRL_CONTROL, reg); + + ps_delay(500); + PS_DEBUG_BCN_TRIGER; + /* dpll division reset release*/ + reg = REG_READ(SCTRL_CONTROL); + reg &= ~(DPLL_CLKDIV_RESET_BIT); + REG_WRITE(SCTRL_CONTROL, reg); + + /* MCLK(main clock) select:dpll*//* MCLK division*/ + reg = REG_READ(SCTRL_CONTROL); + reg &= ~(MCLK_DIV_MASK << MCLK_DIV_POSI); + reg |= ((MCLK_DIV_7 & MCLK_DIV_MASK) << MCLK_DIV_POSI); + REG_WRITE(SCTRL_CONTROL, reg); + + reg = REG_READ(SCTRL_CONTROL); + reg &= ~(MCLK_MUX_MASK << MCLK_MUX_POSI); + reg |= ((MCLK_FIELD_DPLL & MCLK_MUX_MASK) << MCLK_MUX_POSI); + REG_WRITE(SCTRL_CONTROL, reg); + PS_DEBUG_BCN_TRIGER; + + } + else + { + ps_delay(500); + + /* dpll division reset release*/ + reg = REG_READ(SCTRL_CONTROL); + reg &= ~(DPLL_CLKDIV_RESET_BIT); + REG_WRITE(SCTRL_CONTROL, reg); + PS_DEBUG_BCN_TRIGER; + + } + + sctrl_mcu_ps_info.hw_sleep = 0; + sctrl_cali_dpll(1); + PS_DEBUG_BCN_TRIGER; + gpio_ctrl(CMD_GPIO_CLR_DPLL_UNLOOK_INT, NULL); + + #if ((CFG_SOC_NAME == SOC_BK7231) || (CFG_SOC_NAME == SOC_BK7231U) || (CFG_SOC_NAME == SOC_BK7221U)) + /*open 32K Rosc calib*/ + REG_WRITE(SCTRL_ROSC_CAL, 0x35); + REG_WRITE(SCTRL_ROSC_CAL, 0x37); + #endif + + if(4 == flash_get_line_mode()) + { + flash_set_line_mode(4); + } + PS_DEBUG_BCN_TRIGER; +} + +UINT8 sctrl_if_rf_sleep(void) +{ + UINT32 value; + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + value = rf_sleeped; + GLOBAL_INT_RESTORE(); + return value; +} + +void sctrl_rf_sleep(void) +{ + UINT32 reg; + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + if(0 == rf_sleeped) + { + /*Disable BK7011*/ + rc_cntl_stat_set(0x0); + rf_sleeped = 1; + PS_DEBUG_CK_TRIGER; + + /* Modem AHB clock disable*/ + reg = REG_READ(SCTRL_MODEM_CORE_RESET_PHY_HCLK); + reg &= ~PHY_HCLK_EN_BIT; + REG_WRITE(SCTRL_MODEM_CORE_RESET_PHY_HCLK, reg); + /* Modem Subsystem clock 480m disable*/ + reg = REG_READ(SCTRL_CONTROL); + REG_WRITE(SCTRL_CONTROL, reg | MODEM_CLK480M_PWD_BIT); + PS_DEBUG_CK_TRIGER; + } + + GLOBAL_INT_RESTORE(); +} + +void sctrl_rf_wakeup(void) +{ + UINT32 reg; + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + if(rf_sleeped == 1) + { + /* Modem AHB clock enable*/ + reg = REG_READ(SCTRL_MODEM_CORE_RESET_PHY_HCLK); + REG_WRITE(SCTRL_MODEM_CORE_RESET_PHY_HCLK, reg | PHY_HCLK_EN_BIT); + + /* Modem Subsystem clock 480m enable*/ + reg = REG_READ(SCTRL_CONTROL); + reg &= ~MODEM_CLK480M_PWD_BIT; + REG_WRITE(SCTRL_CONTROL, reg); + + /*Enable BK7011:rc_en,ch0_en*/ + rc_cntl_stat_set(0x09); + PS_DEBUG_UP_TRIGER; + +#if (CFG_SOC_NAME == SOC_BK7231N) + if ((DEVICE_ID_BK7231N_P & DEVICE_ID_MASK) != (sctrl_ctrl(CMD_GET_DEVICE_ID, NULL) & DEVICE_ID_MASK)) { + sctrl_fix_dpll_div(); + } +#endif + + phy_wakeup_rf_reinit(); + phy_wakeup_wifi_reinit(); + + rf_sleeped = 0; + } + GLOBAL_INT_RESTORE(); +} + + +void sctrl_set_rf_sleep(void) +{ + extern UINT32 if_other_mode_rf_sleep(void); + + if(power_save_if_rf_sleep() + && if_other_mode_rf_sleep() +#if (CFG_SOC_NAME != SOC_BK7231) + && (!(REG_READ(SCTRL_CONTROL) & BLE_RF_EN_BIT)) +#endif + ) + { + sctrl_rf_sleep(); + } +} + +#if CFG_USE_STA_PS + +void sctrl_sta_rf_sleep(void) +{ + UINT32 reg; + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + + if(power_save_if_rf_sleep() + && (sta_rf_sleeped == 0) + ) + { + PS_DEBUG_CK_TRIGER; + + sctrl_set_rf_sleep(); + /* MAC AHB slave clock disable */ + reg = REG_READ(SCTRL_MODEM_CORE_RESET_PHY_HCLK); + reg &= ~MAC_HCLK_EN_BIT; + REG_WRITE(SCTRL_MODEM_CORE_RESET_PHY_HCLK, reg); + /* Mac Subsystem clock 480m disable*/ + reg = REG_READ(SCTRL_CONTROL); + REG_WRITE(SCTRL_CONTROL, reg | MAC_CLK480M_PWD_BIT); + PS_DEBUG_CK_TRIGER; + + sta_rf_sleeped = 1; + } + + GLOBAL_INT_RESTORE(); +} +void sctrl_sta_rf_wakeup(void) +{ + UINT32 reg; + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + if( sta_rf_sleeped == 1 ) + { + PS_DEBUG_UP_TRIGER; + if(sctrl_mcu_ps_info.hw_sleep == 1) + { + //if rf add mcu up meanwhile + os_null_printf("err, hw not up\r\n"); + } + + /* MAC AHB slave clock enable*/ + reg = REG_READ(SCTRL_MODEM_CORE_RESET_PHY_HCLK); + REG_WRITE(SCTRL_MODEM_CORE_RESET_PHY_HCLK, reg | MAC_HCLK_EN_BIT); + + /* Mac Subsystem clock 480m enable*/ + reg = REG_READ(SCTRL_CONTROL); + reg &= ~MAC_CLK480M_PWD_BIT; + REG_WRITE(SCTRL_CONTROL, reg); + PS_DEBUG_UP_TRIGER; + + sctrl_rf_wakeup(); + + phy_wakeup_wifi_reinit(); + + sta_rf_sleeped = 0; + } + GLOBAL_INT_RESTORE(); +} +#endif + + +#if CFG_USE_MCU_PS +UINT8 sctrl_if_mcu_can_sleep(void) +{ + return ((power_save_if_rf_sleep()) +#if CFG_USE_BLE_PS + && if_ble_sleep() +#else +#if (CFG_SOC_NAME != SOC_BK7231) + && (!(REG_READ(SCTRL_CONTROL) & BLE_RF_EN_BIT)) +#endif +#endif + && sctrl_if_rf_sleep() + && (sctrl_mcu_ps_info.hw_sleep == 0)); +} + +void sctrl_mcu_sleep(UINT32 peri_clk) +{ + UINT32 reg; + + if(sctrl_if_mcu_can_sleep()) + { + reg = REG_READ(ICU_ARM_WAKEUP_EN); + + if(sctrl_mcu_ps_info.first_sleep == 1) + { + reg = 0x0; + sctrl_mcu_ps_info.first_sleep = 0; + } +#if (CHIP_U_MCU_WKUP_USE_TIMER && (CFG_SOC_NAME != SOC_BK7231)) + reg |= (TIMER_ARM_WAKEUP_EN_BIT | UART2_ARM_WAKEUP_EN_BIT + | UART1_ARM_WAKEUP_EN_BIT| GPIO_ARM_WAKEUP_EN_BIT + | PWM_ARM_WAKEUP_EN_BIT); +#else + reg |= (PWM_ARM_WAKEUP_EN_BIT | UART2_ARM_WAKEUP_EN_BIT + | UART1_ARM_WAKEUP_EN_BIT| GPIO_ARM_WAKEUP_EN_BIT + ); +#endif + + REG_WRITE(ICU_ARM_WAKEUP_EN, reg); + +#if(CFG_SOC_NAME == SOC_BK7231N) + reg = REG_READ(ICU_PERI_CLK_PWD); + reg |= (PWD_ARM_WATCHDOG_CLK_BIT); + REG_WRITE(ICU_PERI_CLK_PWD, reg); +#endif + sctrl_hw_sleep(peri_clk); + } + else + { + PS_DEBUG_DOWN_TRIGER; + delay(1); +#if PS_CLOSE_PERI_CLK + /* close all peri clock*/ + ps_saves[0].peri_clk_cfg= REG_READ(ICU_PERI_CLK_PWD); + REG_WRITE(ICU_PERI_CLK_PWD, peri_clk); +#endif + + PS_DEBUG_DOWN_TRIGER; +#if (CFG_SOC_NAME == SOC_BK7231) + REG_WRITE(SCTRL_ROSC_CAL, 0x35); + REG_WRITE(SCTRL_ROSC_CAL, 0x37); +#endif + WFI(); + } + delay(5); +} +UINT32 sctrl_mcu_wakeup(void) +{ + UINT32 wkup_type; + + if(sctrl_mcu_ps_info.hw_sleep == 1) + { + sctrl_hw_wakeup(); + + #if PS_CLOSE_PERI_CLK + REG_WRITE(ICU_PERI_CLK_PWD, ps_saves[0].peri_clk_cfg); + #endif + #if(CFG_SOC_NAME == SOC_BK7231N) + UINT32 reg = REG_READ(ICU_PERI_CLK_PWD); + reg &= ~(PWD_ARM_WATCHDOG_CLK_BIT); + REG_WRITE(ICU_PERI_CLK_PWD, reg); + #endif + wkup_type = 1; + } + else + { + PS_DEBUG_BCN_TRIGER; + delay(2); + PS_DEBUG_BCN_TRIGER; + + #if PS_CLOSE_PERI_CLK + /* recovery periphral unit clock config*/ + REG_WRITE(ICU_PERI_CLK_PWD, ps_saves[0].peri_clk_cfg); + #endif + wkup_type = 0; + } + return wkup_type; +} + + +void sctrl_mcu_init(void) +{ + UINT32 reg; + + reg = LIMIT_FREQ_MCU_PS_BIT; + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_MCLK_LIMIT_FREQ_BIT_SET, ®); +} + +void sctrl_mcu_exit(void) +{ + UINT32 reg; + + reg = LIMIT_FREQ_MCU_PS_BIT; + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_MCLK_LIMIT_FREQ_BIT_CLR, ®); +} +#endif + +void sctrl_subsys_power(UINT32 cmd) +{ + UINT32 reg = 0; + UINT32 reg_val; + UINT32 reg_word = 0; + + switch(cmd) + { + case CMD_SCTRL_DSP_POWERDOWN: + reg = SCTRL_DSP_PWR; + reg_word = DSP_PWD; + break; + + case CMD_SCTRL_DSP_POWERUP: + reg = SCTRL_DSP_PWR; + reg_word = DSP_PWU; + break; + +#if (CFG_SOC_NAME != SOC_BK7231N) + case CMD_SCTRL_USB_POWERDOWN: + reg = SCTRL_USB_PWR; + reg_word = USB_PWD; + break; + + case CMD_SCTRL_USB_POWERUP: + reg = SCTRL_USB_PWR; + reg_word = USB_PWU; + break; +#endif + + case CMD_SCTRL_MAC_POWERDOWN: + reg = SCTRL_PWR_MAC_MODEM; + reg_val = REG_READ(SCTRL_PWR_MAC_MODEM); + reg_val &= ~(MAC_PWD_MASK << MAC_PWD_POSI); + reg_val |= MAC_PWD << MAC_PWD_POSI; + reg_word = reg_val; + break; + + case CMD_SCTRL_MAC_POWERUP: + reg = SCTRL_PWR_MAC_MODEM; + reg_val = REG_READ(SCTRL_PWR_MAC_MODEM); + reg_val &= ~(MAC_PWD_MASK << MAC_PWD_POSI); + reg_val |= MAC_PWU << MAC_PWD_POSI; + reg_word = reg_val; + break; + + case CMD_SCTRL_MODEM_POWERDOWN: + reg = SCTRL_PWR_MAC_MODEM; + reg_val = REG_READ(SCTRL_PWR_MAC_MODEM); + reg_val &= ~(MODEM_PWD_MASK << MODEM_PWD_POSI); + reg_val |= MODEM_PWD << MODEM_PWD_POSI; + reg_word = reg_val; + break; + + case CMD_SCTRL_BLE_POWERDOWN: + reg = SCTRL_USB_PWR; + reg_val = REG_READ(SCTRL_USB_PWR); + reg_val &= ~(BLE_PWD_MASK << BLE_PWD_POSI); + reg_val |= BLE_PWD << BLE_PWD_POSI; + reg_word = reg_val; + break; + + case CMD_SCTRL_MODEM_POWERUP: + reg = SCTRL_PWR_MAC_MODEM; + reg_val = REG_READ(SCTRL_PWR_MAC_MODEM); + reg_val &= ~(MODEM_PWD_MASK << MODEM_PWD_POSI); + reg_val |= MODEM_PWU << MODEM_PWD_POSI; + reg_word = reg_val; + break; + + case CMD_SCTRL_BLE_POWERUP: + reg = SCTRL_USB_PWR; + reg_val = REG_READ(SCTRL_USB_PWR); + reg_val &= ~(BLE_PWD_MASK << BLE_PWD_POSI); + reg_val |= BLE_PWU << BLE_PWD_POSI; + reg_word = reg_val; + break; + + default: + break; + } + + if(reg) + { + REG_WRITE(reg, reg_word); + } +} + +void sctrl_subsys_reset(UINT32 cmd) +{ + UINT32 reg = 0; + UINT32 reset_word = 0; + + switch(cmd) + { + case CMD_SCTRL_MODEM_SUBCHIP_RESET: + reg = SCTRL_MODEM_SUBCHIP_RESET_REQ; + reset_word = MODEM_SUBCHIP_RESET_WORD; + break; + + case CMD_SCTRL_MAC_SUBSYS_RESET: + reg = SCTRL_MAC_SUBSYS_RESET_REQ; + reset_word = MAC_SUBSYS_RESET_WORD; + break; + + case CMD_SCTRL_USB_SUBSYS_RESET: + reg = SCTRL_USB_SUBSYS_RESET_REQ; + reset_word = USB_SUBSYS_RESET_WORD; + break; + + case CMD_SCTRL_DSP_SUBSYS_RESET: + reg = SCTRL_DSP_SUBSYS_RESET_REQ; + reset_word = DSP_SUBSYS_RESET_WORD; + break; + + default: + break; + } + + if(reg) + { + REG_WRITE(reg, reset_word); + delay(10); + REG_WRITE(reg, 0); + } + + return; +} + +#if (CFG_SOC_NAME == SOC_BK7231N) +void sctrl_fix_dpll_div() +{ + volatile INT32 i; + uint32 reg; + uint32 cpu_clock; + + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + + reg = REG_READ(SCTRL_CONTROL); + cpu_clock = reg & 0xFF; + reg = (reg & 0xFFFFFF00) | 0x52; + REG_WRITE(SCTRL_CONTROL, reg); + + for(i = 0; i < 100; i ++); + + REG_WRITE(SCTRL_MODEM_SUBCHIP_RESET_REQ, MODEM_SUBCHIP_RESET_WORD); + REG_WRITE(SCTRL_CONTROL, REG_READ(SCTRL_CONTROL) | (1 << 14)); + + for(i = 0; i < 100; i ++); + + REG_WRITE(SCTRL_MODEM_SUBCHIP_RESET_REQ, 0); + REG_WRITE(SCTRL_CONTROL, REG_READ(SCTRL_CONTROL) & ~(1 << 14)); + + for(i = 0; i < 100; i ++); + + reg = REG_READ(SCTRL_CONTROL); + reg = (reg & 0xFFFFFF00) | cpu_clock; + REG_WRITE(SCTRL_CONTROL, reg); + + for(i = 0; i < 100; i ++); + + GLOBAL_INT_RESTORE(); +} + +void sctrl_mdm_reset(void) +{ + volatile INT32 i; + GLOBAL_INT_DECLARATION(); + + os_printf("sctrl_mdm_reset\r\n"); + + // Disable the interrupts + GLOBAL_INT_DISABLE(); + + if (1) + { + /* MAC reset */ + REG_WRITE(SCTRL_MODEM_SUBCHIP_RESET_REQ, MODEM_SUBCHIP_RESET_WORD); + REG_WRITE(SCTRL_CONTROL, REG_READ(SCTRL_CONTROL) | DPLL_CLKDIV_RESET_BIT); + + for(i = 0; i < 100; i++); + + REG_WRITE(SCTRL_MODEM_SUBCHIP_RESET_REQ, 0); + REG_WRITE(SCTRL_CONTROL, REG_READ(SCTRL_CONTROL) & ~DPLL_CLKDIV_RESET_BIT); + + for(i = 0; i < 100; i++); + } + else + { + /* Modem pwd */ + sctrl_ctrl(CMD_SCTRL_MODEM_POWERDOWN, NULL); + REG_WRITE(SCTRL_CONTROL, REG_READ(SCTRL_CONTROL) | DPLL_CLKDIV_RESET_BIT); + + for(i = 0; i < 100; i++); + + /* Modem pwu */ + sctrl_ctrl(CMD_SCTRL_MODEM_POWERUP, NULL); + REG_WRITE(SCTRL_CONTROL, REG_READ(SCTRL_CONTROL) & ~DPLL_CLKDIV_RESET_BIT); + + for(i = 0; i < 100; i++); + } + + phy_wakeup_rf_reinit(); + phy_wakeup_wifi_reinit(); + + // Restore the interrupts + GLOBAL_INT_RESTORE(); +} +#endif + +#if CFG_USE_LOW_IDLE_PS +void sctrl_enter_rtos_idle_sleep(UINT32 peri_clk) +{ + DD_HANDLE flash_hdl; + UINT32 status; + UINT32 reg; + int i; + + uart_wait_tx_over(); + + /* close all peri int*/ + ps_saves[1].int_enable_cfg = REG_READ(ICU_INTERRUPT_ENABLE); + REG_WRITE(ICU_INTERRUPT_ENABLE, 0); + /* MAC AHB slave clock disable */ + reg = REG_READ(SCTRL_MODEM_CORE_RESET_PHY_HCLK); + reg &= ~MAC_HCLK_EN_BIT; + REG_WRITE(SCTRL_MODEM_CORE_RESET_PHY_HCLK, reg); + + /* Mac Subsystem clock 480m disable*/ + reg = REG_READ(SCTRL_CONTROL); + REG_WRITE(SCTRL_CONTROL, reg | MAC_CLK480M_PWD_BIT); + + /* Modem pwd*/ + REG_WRITE(SCTRL_PWR_MAC_MODEM, MODEM_PWD); + + /* Modem AHB clock disable*/ + reg = REG_READ(SCTRL_MODEM_CORE_RESET_PHY_HCLK); + reg &= ~PHY_HCLK_EN_BIT; + REG_WRITE(SCTRL_MODEM_CORE_RESET_PHY_HCLK, reg); + + /* Modem Subsystem clock 480m disable*/ + reg = REG_READ(SCTRL_CONTROL); + REG_WRITE(SCTRL_CONTROL, reg | MODEM_CLK480M_PWD_BIT); + + /* Flash 26MHz clock select dco clock*/ + flash_hdl = ddev_open(FLASH_DEV_NAME, &status, 0); + ASSERT(DD_HANDLE_UNVALID != flash_hdl); + ddev_control(flash_hdl, CMD_FLASH_SET_DCO, 0); + + /* MCLK(main clock) select:dco*/ /* MCLK division*/ + reg = REG_READ(SCTRL_CONTROL); + reg &= ~(MCLK_MUX_MASK << MCLK_MUX_POSI); + reg &= ~(MCLK_DIV_MASK << MCLK_DIV_POSI); + REG_WRITE(SCTRL_CONTROL, reg); + + /*close 32K Rosc calib*/ + REG_WRITE(SCTRL_ROSC_CAL, 0x36); + + /* dpll division reset*/ + reg = REG_READ(SCTRL_CONTROL); + reg |= (0x1<<14); + REG_WRITE(SCTRL_CONTROL, reg); + + /* dpll (480m) & 26m xtal & xtal2rf & Vsys disable*/ + reg = REG_READ(SCTRL_BLOCK_EN_CFG); + reg &= ~(BLOCK_EN_WORD_MASK << BLOCK_EN_WORD_POSI); + reg = reg | (BLOCK_EN_WORD_PWD << BLOCK_EN_WORD_POSI); + reg &= ~(BLK_EN_DPLL_480M | BLK_EN_26M_XTAL | BLK_EN_XTAL2RF | BLK_EN_ANALOG_SYS_LDO); + REG_WRITE(SCTRL_BLOCK_EN_CFG, reg); + reg = REG_READ(SCTRL_BLOCK_EN_MUX); + reg = reg | (0x1 << 4); + REG_WRITE(SCTRL_BLOCK_EN_MUX, reg); + + /* close all peri clock*/ + ps_saves[1].peri_clk_cfg= REG_READ(ICU_PERI_CLK_PWD); + REG_WRITE(ICU_PERI_CLK_PWD, peri_clk); + + /* vdddig decrease to 0.9v*/ + REG_WRITE(SCTRL_DIGTAL_VDD, 0x20); + + /* set all gpio to high-z state*/ + for(i =2; i < 32; i ++) + { + ps_saves_gpio_cfgs[i] = REG_READ(0x00802800+i*4); + REG_WRITE(0x00802800+i*4, 0x2c); + } + + /* arm clock disable */ + reg = REG_READ(SCTRL_SLEEP); + reg &= ~(SLEEP_MODE_MASK << SLEEP_MODE_POSI); + reg = reg | SLEEP_MODE_CFG_NORMAL_VOL_WORD; + REG_WRITE(SCTRL_SLEEP, reg); + delay(5); +} + +void sctrl_exit_rtos_idle_sleep(void) +{ + UINT32 reg; + int i; + + /* vdddig increase to 1.2v*/ + REG_WRITE(SCTRL_DIGTAL_VDD, 0x40); + PS_DEBUG_UP_OUT; + + /*dpll(480m) & 26m xtal & xtal2rf enable*/ + reg = REG_READ(SCTRL_BLOCK_EN_MUX); + reg &= ~(0x1 << 4); + REG_WRITE(SCTRL_BLOCK_EN_MUX, reg); + reg = REG_READ(SCTRL_BLOCK_EN_CFG); + reg &= ~(BLOCK_EN_WORD_MASK << BLOCK_EN_WORD_POSI); + reg |= (BLOCK_EN_WORD_PWD << BLOCK_EN_WORD_POSI); + reg |= (BLK_EN_26M_XTAL | BLK_EN_DPLL_480M | BLK_EN_XTAL2RF | BLK_EN_ANALOG_SYS_LDO); + REG_WRITE(SCTRL_BLOCK_EN_CFG, reg); + + delay(1); //delay 1.1ms for 26MHz DCO clock. need change for other dco clock frequency + sctrl_cali_dpll(0); + /* dpll division reset release*/ + reg = REG_READ(SCTRL_CONTROL); + reg &= ~(0x1<<14); + REG_WRITE(SCTRL_CONTROL, reg); + + /* MCLK(main clock) select:dpll*//* MCLK division*/ + reg = REG_READ(SCTRL_CONTROL); + reg &= ~(MCLK_DIV_MASK << MCLK_DIV_POSI); + reg &= ~(MCLK_MUX_MASK << MCLK_MUX_POSI); + reg |= ((MCLK_DIV_7 & MCLK_DIV_MASK) << MCLK_DIV_POSI); + reg |= ((MCLK_FIELD_DPLL & MCLK_MUX_MASK) << MCLK_MUX_POSI); + REG_WRITE(SCTRL_CONTROL, reg); + + /* Flash clock select dpll clock*/ + { + DD_HANDLE flash_hdl; + UINT32 status; + flash_hdl = ddev_open(FLASH_DEV_NAME, &status, 0); + ASSERT(DD_HANDLE_UNVALID != flash_hdl); + ddev_control(flash_hdl, CMD_FLASH_SET_DPLL, 0); + } + + /*open 32K Rosc calib*/ + REG_WRITE(SCTRL_ROSC_CAL, 0x37); + + /* MAC AHB slave clock enable*/ + reg = REG_READ(SCTRL_MODEM_CORE_RESET_PHY_HCLK); + REG_WRITE(SCTRL_MODEM_CORE_RESET_PHY_HCLK, reg | MAC_HCLK_EN_BIT); + + /* Mac Subsystem clock 480m enable*/ + reg = REG_READ(SCTRL_CONTROL); + reg &= ~MAC_CLK480M_PWD_BIT; + REG_WRITE(SCTRL_CONTROL, reg); + + /* Modem AHB clock enable*/ + reg = REG_READ(SCTRL_MODEM_CORE_RESET_PHY_HCLK); + REG_WRITE(SCTRL_MODEM_CORE_RESET_PHY_HCLK, reg | PHY_HCLK_EN_BIT); + + /* Modem Subsystem clock 480m enable*/ + reg = REG_READ(SCTRL_CONTROL); + reg &= ~MODEM_CLK480M_PWD_BIT; + REG_WRITE(SCTRL_CONTROL, reg); + + /* Modem pwd*/ + reg = REG_READ(SCTRL_PWR_MAC_MODEM); + reg &= ~(MODEM_PWD_MASK << MODEM_PWD_POSI); + reg = reg | (0 << MODEM_PWD_POSI); + REG_WRITE(SCTRL_PWR_MAC_MODEM, reg); + + /* recovery periphral unit clock config*/ + REG_WRITE(ICU_PERI_CLK_PWD, ps_saves[1].peri_clk_cfg); + + /* recovery periphral unit int config*/ + REG_WRITE(ICU_INTERRUPT_ENABLE, ps_saves[1].int_enable_cfg); + /* recovery gpio configuration*/ + for(i = 2; i < 32; i ++) + { + if(i!=10&&i!=11&&i!=14&&i!=15&&i!=17) + REG_WRITE(0x00802800+i*4, ps_saves_gpio_cfgs[i]); + else if(i!=16 && i!=10) + REG_WRITE(0x00802800+i*4, 0x0); + } + + os_null_printf("idle wake up!\r\n"); +} + +#endif + +#if CFG_USE_DEEP_PS +void sctrl_enter_rtos_deep_sleep(PS_DEEP_CTRL_PARAM *deep_param) +{ + DD_HANDLE flash_hdl; + UINT32 status; + UINT32 param; + UINT32 reg; + UINT32 i; + + uart_wait_tx_over(); + + /* close all peri clock*/ + REG_WRITE(ICU_PERI_CLK_PWD, 0xfffff); // icu: 0x2; + +#if CFG_USE_UART2 + uart2_exit(); +#endif +#if CFG_USE_UART1 + uart1_exit(); +#endif + +#if (CFG_SOC_NAME == SOC_BK7231U) || (SOC_BK7231N == CFG_SOC_NAME) + reg = REG_READ(SCTRL_LOW_PWR_CLK); + reg &=~(LPO_CLK_MUX_MASK); + reg |=(LPO_SRC_ROSC << LPO_CLK_MUX_POSI); + REG_WRITE(SCTRL_LOW_PWR_CLK, reg); + + REG_WRITE(SCTRL_ROSC_CAL, 0x75); + REG_WRITE(SCTRL_ROSC_CAL, 0x77); +#else + /*ana_reg set*/ + REG_WRITE(SCTRL_ANALOG_CTRL0, 0x7819a59b); + REG_WRITE(SCTRL_ANALOG_CTRL1, 0x7819a59b); + REG_WRITE(SCTRL_ANALOG_CTRL2, 0x84036080); + REG_WRITE(SCTRL_ANALOG_CTRL3, 0x180004a0); + REG_WRITE(SCTRL_ANALOG_CTRL4, 0x84200e52); + REG_WRITE(SCTRL_ANALOG_CTRL5, 0x3b13b13b); +#if (CFG_SOC_NAME != SOC_BK7231) + REG_WRITE(SCTRL_ANALOG_CTRL6, 0xb09350); +#endif +#if (CFG_SOC_NAME == SOC_BK7221U) + REG_WRITE(SCTRL_ANALOG_CTRL7, 0x441a7f0); + REG_WRITE(SCTRL_ANALOG_CTRL8, 0x3b187c); + REG_WRITE(SCTRL_ANALOG_CTRL9, 0x82204007); + REG_WRITE(SCTRL_ANALOG_CTRL10, 0x80801432); +#endif +#endif + ps_delay(10); + /*clear int*/ + REG_WRITE(ICU_INTERRUPT_ENABLE, 0); + + extern void gpio_ops_disable_filter(void); + gpio_ops_disable_filter(); + + /* disable gpio0~31*/ + REG_WRITE(SCTRL_GPIO_WAKEUP_EN,0x0); //sys_ctrl : 0x48; + REG_WRITE(SCTRL_GPIO_WAKEUP_INT_STATUS,0xFFFFFFFF); //sys_ctrl : 0x4a; + +#if (CFG_SOC_NAME != SOC_BK7231N) + /* disable gpio32~39*/ + REG_WRITE(SCTRL_GPIO_WAKEUP_EN1,0x0); //sys_ctrl : 0x51; + REG_WRITE(SCTRL_GPIO_WAKEUP_INT_STATUS1,0xFF); //sys_ctrl : 0x53; +#endif + + REG_WRITE(SCTRL_BLOCK_EN_MUX, 0x0); //sys_ctrl : 0x4F; + + /* ROSC_TIMER_int_clear*/ + reg = REG_READ(SCTRL_ROSC_TIMER); + reg = reg| ROSC_TIMER_INT_STATUS_BIT ; + REG_WRITE(SCTRL_ROSC_TIMER,reg); //sys_ctrl : 0x47; + + /*ROSC_TIMER close */ + reg = REG_READ(SCTRL_ROSC_TIMER); + reg = reg & (~ROSC_TIMER_ENABLE_BIT); //'C' + REG_WRITE(SCTRL_ROSC_TIMER,reg); + + reg = REG_READ(SCTRL_LOW_PWR_CLK); + reg &=~(LPO_CLK_MUX_MASK); + if(deep_param->lpo_32k_src == LPO_SELECT_32K_XTAL) + { + reg |=(LPO_SRC_32K_XTAL << LPO_CLK_MUX_POSI); + } + else + { + reg |=(LPO_SRC_ROSC << LPO_CLK_MUX_POSI); + } + + REG_WRITE(SCTRL_LOW_PWR_CLK, reg); //sys_ctrl : 0x40; + + /* close all peri int*/ + // REG_WRITE(ICU_INTERRUPT_ENABLE, 0); + + /* MAC pwd*/ + REG_WRITE(SCTRL_PWR_MAC_MODEM, MAC_PWD << MAC_PWD_POSI); //sys_ctrl : 0x43; + + /* MAC AHB slave clock disable */ + reg = REG_READ(SCTRL_MODEM_CORE_RESET_PHY_HCLK); + reg &= ~MAC_HCLK_EN_BIT; + REG_WRITE(SCTRL_MODEM_CORE_RESET_PHY_HCLK, reg); + + /* Mac Subsystem clock 480m disable*/ + reg = REG_READ(SCTRL_CONTROL); + REG_WRITE(SCTRL_CONTROL, reg | MAC_CLK480M_PWD_BIT); + + /* Modem pwd*/ + REG_WRITE(SCTRL_PWR_MAC_MODEM, MODEM_PWD << MODEM_PWD_POSI); + + /* Modem AHB clock disable*/ + reg = REG_READ(SCTRL_MODEM_CORE_RESET_PHY_HCLK); + reg &= ~PHY_HCLK_EN_BIT; + REG_WRITE(SCTRL_MODEM_CORE_RESET_PHY_HCLK, reg); + + /* Modem Subsystem clock 480m disable*/ + reg = REG_READ(SCTRL_CONTROL); + REG_WRITE(SCTRL_CONTROL, reg | MODEM_CLK480M_PWD_BIT); + + /* Flash 26MHz clock select dco clock*/ + flash_hdl = ddev_open(FLASH_DEV_NAME, &status, 0); + ASSERT(DD_HANDLE_UNVALID != flash_hdl); + ddev_control(flash_hdl, CMD_FLASH_SET_DCO, 0); + + /* MCLK(main clock) select:dco*/ /* MCLK division*/ + reg = REG_READ(SCTRL_CONTROL); + reg &= ~(MCLK_MUX_MASK << MCLK_MUX_POSI); + reg &= ~(MCLK_DIV_MASK << MCLK_DIV_POSI); + REG_WRITE(SCTRL_CONTROL, reg); //0x02 + + if(deep_param->lpo_32k_src == LPO_SELECT_32K_XTAL) + { + reg = REG_READ(SCTRL_CONTROL); + reg =((reg & (~0xF0)) | (0<<4)); + reg =((reg & (~0x03)) | (0<lpo_32k_src == LPO_SELECT_32K_XTAL) + { + reg = (reg |BLK_EN_32K_XTAL|BLK_EN_26M_XTAL); + } + REG_WRITE(SCTRL_BLOCK_EN_CFG, reg); //sys_ctrl : 0x4B; //'E' + +#if (CFG_SOC_NAME != SOC_BK7231U) && (SOC_BK7231N != CFG_SOC_NAME) + reg = REG_READ(SCTRL_ROSC_CAL); //ROSC Calibration disable + reg =(reg & (~0x01)); + REG_WRITE(SCTRL_ROSC_CAL, reg); +#endif + + for(i=0; i GPIO1) && (i < GPIO6)) + || ((i > GPIO11) && (i < GPIO14)) + || ((i > GPIO17) && (i < GPIO20)) + || ((i > GPIO24) && (i < GPIO26)) + || ((i > GPIO26) && (i < GPIO28))) + { + continue; + } +#endif + if(((i < BITS_INT)&&(deep_param->gpio_stay_lo_map & (0x01UL << i))) + ||((i >= BITS_INT)&&(deep_param->gpio_stay_hi_map & (0x01UL << (i - BITS_INT)))) ) + { + continue; + } + param = GPIO_CFG_PARAM(i, GMODE_DEEP_PS); /*set gpio 0~39 as high impendance*/ + sddev_control(GPIO_DEV_NAME, CMD_GPIO_CFG, ¶m); + } + + if (((deep_param->wake_up_way & PS_DEEP_WAKEUP_RTC)) + && (deep_param->sleep_time!= 0xffffffff)) + { + /*ROSC_TIMER init*/ +#if (CFG_SOC_NAME != SOC_BK7231) + reg = (deep_param->sleep_time >> 16)& 0xffff; //'A' + REG_WRITE(SCTRL_ROSC_TIMER_H,reg); +#endif + + reg = REG_READ(SCTRL_ROSC_TIMER); + reg |= ROSC_TIMER_INT_STATUS_BIT; //'C' + REG_WRITE(SCTRL_ROSC_TIMER,reg); //sys_ctrl : 0x47; + + reg = REG_READ(SCTRL_ROSC_TIMER); + reg &= ~(ROSC_TIMER_PERIOD_MASK << ROSC_TIMER_PERIOD_POSI); + reg |= ((deep_param->sleep_time & ROSC_TIMER_PERIOD_MASK) << ROSC_TIMER_PERIOD_POSI); + REG_WRITE(SCTRL_ROSC_TIMER,reg); //sys_ctrl : 0x47; //'D' + + reg = REG_READ(SCTRL_ROSC_TIMER); + reg |= ROSC_TIMER_ENABLE_BIT; + REG_WRITE(SCTRL_ROSC_TIMER,reg); //sys_ctrl : 0x47; //'B' + + if(deep_param->lpo_32k_src == LPO_SELECT_32K_XTAL) + { + REG_WRITE(SCTRL_CONTROL, 0x330100); + REG_WRITE(SCTRL_BLOCK_EN_CFG, (0x15D|(0xA5C<<20))); + REG_WRITE(SCTRL_ROSC_CAL, 0x30); + REG_WRITE(SCTRL_LOW_PWR_CLK, 0x01); + REG_WRITE(SCTRL_MODEM_CORE_RESET_PHY_HCLK, 0x03); + REG_WRITE(SCTRL_CLK_GATING, 0x1ff); + } + } + + if ((deep_param->wake_up_way & PS_DEEP_WAKEUP_GPIO)) + { + for (i = 0; i < BITS_INT; i++) + { +#if(BITS_INT > GPIONUM) + if(i >= GPIONUM) + { + break; + } +#endif + +#if (CFG_SOC_NAME == SOC_BK7231N) + if(((i > GPIO1) && (i < GPIO6)) + || ((i > GPIO11) && (i < GPIO14)) + || ((i > GPIO17) && (i < GPIO20)) + || ((i > GPIO24) && (i < GPIO26)) + || ((i > GPIO26) && (i < GPIO28))) + { + continue; + } +#endif + if (deep_param->gpio_index_map & (0x01UL << i)) /*set gpio 0~31 mode*/ + { + if( deep_param->gpio_edge_map & (0x01UL << i)) //0:high,1:low. + { + if(deep_sleep_gpio_floating_map & (0x01UL << i)) + { + param = GPIO_CFG_PARAM(i, GMODE_INPUT); + } else { + param = GPIO_CFG_PARAM(i, GMODE_INPUT_PULLUP); + } + + sddev_control(GPIO_DEV_NAME, CMD_GPIO_CFG, ¶m); + if(0x1 != (UINT32)gpio_ctrl( CMD_GPIO_INPUT, &i)) + { /*check gpio really input value,to correct wrong edge setting*/ + param = GPIO_CFG_PARAM(i, GMODE_INPUT); + sddev_control(GPIO_DEV_NAME, CMD_GPIO_CFG, ¶m); + deep_param->gpio_edge_map &= ~(0x01UL << i); + } + } + else + { + if(deep_sleep_gpio_floating_map & (0x01UL << i)) + { + param = GPIO_CFG_PARAM(i, GMODE_INPUT); + } else { + param = GPIO_CFG_PARAM(i, GMODE_INPUT_PULLDOWN); + } + sddev_control(GPIO_DEV_NAME, CMD_GPIO_CFG, ¶m); + if(0x0 != (UINT32)gpio_ctrl( CMD_GPIO_INPUT, &i)) + { /*check gpio really input value,to correct wrong edge setting*/ + param = GPIO_CFG_PARAM(i, GMODE_INPUT); + sddev_control(GPIO_DEV_NAME, CMD_GPIO_CFG, ¶m); + deep_param->gpio_edge_map |= (0x01UL << i); + } + } + } + } + +#if (CFG_SOC_NAME != SOC_BK7231N) + for (i = 0; i < (GPIONUM - BITS_INT); i++) + { + if (deep_param->gpio_last_index_map & (0x01UL << i)) /*set gpio 32~39 mode*/ + { + if( deep_param->gpio_last_edge_map & (0x01UL << i)) + { + param = GPIO_CFG_PARAM(i + BITS_INT, GMODE_INPUT_PULLUP); + sddev_control(GPIO_DEV_NAME, CMD_GPIO_CFG, ¶m); + reg = i + BITS_INT; + if(0x1 != (UINT32)gpio_ctrl( CMD_GPIO_INPUT, ®)) + { /*check gpio really input value,to correct wrong edge setting*/ + param = GPIO_CFG_PARAM(i + BITS_INT, GMODE_INPUT); + sddev_control(GPIO_DEV_NAME, CMD_GPIO_CFG, ¶m); + deep_param->gpio_last_edge_map &= ~(0x01UL << i); + } + } + else + { + param = GPIO_CFG_PARAM(i + BITS_INT, GMODE_INPUT_PULLDOWN); + sddev_control(GPIO_DEV_NAME, CMD_GPIO_CFG, ¶m); + reg = i + BITS_INT; + if(0x0 != (UINT32)gpio_ctrl( CMD_GPIO_INPUT, ®)) + { /*check gpio really input value,to correct wrong edge setting*/ + param = GPIO_CFG_PARAM(i + BITS_INT, GMODE_INPUT); + sddev_control(GPIO_DEV_NAME, CMD_GPIO_CFG, ¶m); + deep_param->gpio_last_edge_map |= (0x01UL << i); + } + } + } + } +#endif + /* set gpio 0~31 mode*/ + reg = 0xFFFFFFFF; + REG_WRITE(SCTRL_GPIO_WAKEUP_INT_STATUS,reg); + reg = deep_param->gpio_edge_map; + REG_WRITE(SCTRL_GPIO_WAKEUP_TYPE,reg); + reg = deep_param->gpio_index_map; + REG_WRITE(SCTRL_GPIO_WAKEUP_EN,reg); + + /* set gpio 31~32 mode*/ +#if (CFG_SOC_NAME != SOC_BK7231N) + reg = 0xFF; + REG_WRITE(SCTRL_GPIO_WAKEUP_INT_STATUS1,reg); + + reg = deep_param->gpio_last_edge_map; + REG_WRITE(SCTRL_GPIO_WAKEUP_TYPE1,reg); + + reg = deep_param->gpio_last_index_map; + REG_WRITE(SCTRL_GPIO_WAKEUP_EN1,reg); +#else + reg = 0xFFFFFFFF; + REG_WRITE(SCTRL_GPIO_WAKEUP_TYPE_SELECT,reg); +#endif + } + +#if (CFG_SOC_NAME != SOC_BK7231N) + REG_WRITE(SCTRL_USB_PLUG_WAKEUP,USB_PLUG_IN_INT_BIT|USB_PLUG_OUT_INT_BIT); + if(deep_param->wake_up_way & PS_DEEP_WAKEUP_USB) + { + REG_WRITE(SCTRL_USB_PLUG_WAKEUP,USB_PLUG_IN_EN_BIT|USB_PLUG_OUT_EN_BIT); + } +#endif + +#ifdef BK_DEEP_SLEEP_DEBUG + BK_DEEP_SLEEP_PRT("SCTRL_CONTROL=0x%08X\r\n", REG_READ(SCTRL_CONTROL)); + BK_DEEP_SLEEP_PRT("SCTRL_SLEEP=0x%08X\r\n", REG_READ(SCTRL_SLEEP)); + BK_DEEP_SLEEP_PRT("SCTRL_ROSC_TIMER=0x%08X\r\n", REG_READ(SCTRL_ROSC_TIMER)); + BK_DEEP_SLEEP_PRT("SCTRL_BLOCK_EN_CFG=0x%08X\r\n", REG_READ(SCTRL_BLOCK_EN_CFG)); + BK_DEEP_SLEEP_PRT("SCTRL_ROSC_CAL=0x%08X\r\n", REG_READ(SCTRL_ROSC_CAL)); + BK_DEEP_SLEEP_PRT("SCTRL_BLOCK_EN_MUX=0x%08X\r\n", REG_READ(SCTRL_BLOCK_EN_MUX)); + BK_DEEP_SLEEP_PRT("SCTRL_LOW_PWR_CLK=0x%08X\r\n", REG_READ(SCTRL_LOW_PWR_CLK)); + BK_DEEP_SLEEP_PRT("SCTRL_PWR_MAC_MODEM=0x%08X\r\n", REG_READ(SCTRL_PWR_MAC_MODEM)); + BK_DEEP_SLEEP_PRT("SCTRL_MODEM_CORE_RESET_PHY_HCLK=0x%08X\r\n", REG_READ(SCTRL_MODEM_CORE_RESET_PHY_HCLK)); + BK_DEEP_SLEEP_PRT("SCTRL_CLK_GATING=0x%08X\r\n", REG_READ(SCTRL_CLK_GATING)); + BK_DEEP_SLEEP_PRT("SCTRL_GPIO_WAKEUP_INT_STATUS=0x%08X\r\n", REG_READ(SCTRL_GPIO_WAKEUP_INT_STATUS)); + BK_DEEP_SLEEP_PRT("SCTRL_GPIO_WAKEUP_TYPE=0x%08X\r\n", REG_READ(SCTRL_GPIO_WAKEUP_TYPE)); + BK_DEEP_SLEEP_PRT("SCTRL_GPIO_WAKEUP_EN=0x%08X\r\n", REG_READ(SCTRL_GPIO_WAKEUP_EN)); + BK_DEEP_SLEEP_PRT("SCTRL_GPIO_WAKEUP_INT_STATUS1=0x%08X\r\n", REG_READ(SCTRL_GPIO_WAKEUP_INT_STATUS1)); + BK_DEEP_SLEEP_PRT("SCTRL_GPIO_WAKEUP_TYPE1=0x%08X\r\n", REG_READ(SCTRL_GPIO_WAKEUP_TYPE1)); + BK_DEEP_SLEEP_PRT("SCTRL_GPIO_WAKEUP_EN1=0x%08X\r\n", REG_READ(SCTRL_GPIO_WAKEUP_EN1)); +#endif + + /* enter deep_sleep mode */ + reg = REG_READ(SCTRL_SLEEP); + reg &= ~(SLEEP_MODE_MASK << SLEEP_MODE_POSI); + reg = reg | SLEEP_MODE_CFG_DEEP_WORD; + REG_WRITE(SCTRL_SLEEP, reg); + + delay(5); +} + +RESET_SOURCE_STATUS sctrl_get_deep_sleep_wake_soure(void) +{ + RESET_SOURCE_STATUS waked_source = 0; + + if(REG_READ(SCTRL_ROSC_TIMER) & ROSC_TIMER_INT_STATUS_BIT) + { + waked_source = RESET_SOURCE_DEEPPS_RTC; + } + else if(REG_READ(SCTRL_GPIO_WAKEUP_INT_STATUS) +#if (CFG_SOC_NAME != SOC_BK7231N) + || REG_READ(SCTRL_GPIO_WAKEUP_INT_STATUS1) +#endif + ) + { + waked_source = RESET_SOURCE_DEEPPS_GPIO; + } + + return waked_source; +} + + +//Ҫ sctrl_enter_rtos_deep_sleep ǰ +void sctrl_set_deep_sleep_gpio_floating_map(UINT32 gpio_last_floating_map) +{ + deep_sleep_gpio_floating_map = gpio_last_floating_map; +} + + +#endif + +#if (CFG_SOC_NAME != SOC_BK7231) +static int sctrl_read_efuse(void *param) +{ + UINT32 reg, ret = -1; + EFUSE_OPER_PTR efuse; + efuse = (EFUSE_OPER_PTR)param; + + if(efuse) { + reg = REG_READ(SCTRL_EFUSE_CTRL); + reg &= ~(EFUSE_OPER_ADDR_MASK << EFUSE_OPER_ADDR_POSI); + reg &= ~(EFUSE_OPER_DIR); + + reg |= ((efuse->addr & EFUSE_OPER_ADDR_MASK) << EFUSE_OPER_ADDR_POSI); + reg |= (EFUSE_OPER_EN); + REG_WRITE(SCTRL_EFUSE_CTRL, reg); + + do { + reg = REG_READ(SCTRL_EFUSE_CTRL); + }while(reg & EFUSE_OPER_EN); + + reg = REG_READ(SCTRL_EFUSE_OPTR); + if(reg & EFUSE_OPER_RD_DATA_VALID) { + efuse->data = ((reg >> EFUSE_OPER_RD_DATA_POSI) & EFUSE_OPER_RD_DATA_MASK); + ret = 0; + } else { + efuse->data = 0xFF; + } + } + return ret; +} + +static int sctrl_write_efuse(void *param) +{ + UINT32 reg, ret = -1; + EFUSE_OPER_ST *efuse, efuse_bak; + + efuse = (EFUSE_OPER_PTR)param; + if(efuse) { + efuse_bak.addr = efuse->addr; + efuse_bak.data = efuse->data; + if(sctrl_read_efuse(&efuse_bak) == 0) { + //read before write, ensure this byte no wrote + if(EFUSE_INIT_VAL != efuse_bak.data) + return -1; + } + + // enable vdd2.5v first + reg = REG_READ(SCTRL_CONTROL); + reg |= EFUSE_VDD25_EN; + REG_WRITE(SCTRL_CONTROL, reg); + + reg = REG_READ(SCTRL_EFUSE_CTRL); + reg &= ~(EFUSE_OPER_ADDR_MASK << EFUSE_OPER_ADDR_POSI); + reg &= ~(EFUSE_OPER_WR_DATA_MASK << EFUSE_OPER_WR_DATA_POSI); + + reg |= EFUSE_OPER_DIR; + reg |= ((efuse->addr & EFUSE_OPER_ADDR_MASK) << EFUSE_OPER_ADDR_POSI); + reg |= ((efuse->data & EFUSE_OPER_WR_DATA_MASK) << EFUSE_OPER_WR_DATA_POSI); + reg |= EFUSE_OPER_EN; + REG_WRITE(SCTRL_EFUSE_CTRL, reg); + + do { + reg = REG_READ(SCTRL_EFUSE_CTRL); + }while(reg & EFUSE_OPER_EN); + + // disable vdd2.5v at last + reg = REG_READ(SCTRL_CONTROL); + reg &= ~EFUSE_VDD25_EN; + REG_WRITE(SCTRL_CONTROL, reg); + + // check, so read + reg = efuse->data; + efuse->data = 0; + if(sctrl_read_efuse(param) == 0) { + if(((UINT8)reg) == efuse->data) + ret = 0; + } + } + return ret; +} +#endif // (CFG_SOC_NAME != SOC_BK7231) + +UINT32 sctrl_ctrl(UINT32 cmd, void *param) +{ + UINT32 ret; + UINT32 reg; + GLOBAL_INT_DECLARATION(); + + ret = SCTRL_SUCCESS; + GLOBAL_INT_DISABLE(); + switch(cmd) + { +#if PS_SUPPORT_MANUAL_SLEEP + case CMD_SCTRL_NORMAL_SLEEP: + sctrl_rf_sleep(); + sctrl_hw_sleep(*(UINT32 *)param); + break; + + case CMD_SCTRL_NORMAL_WAKEUP: + sctrl_hw_wakeup(); + delay(50); + sctrl_rf_wakeup(); + break; +#endif +#if CFG_USE_LOW_IDLE_PS + case CMD_SCTRL_RTOS_IDLE_SLEEP: + sctrl_enter_rtos_idle_sleep(*(UINT32 *)param); + break; + + case CMD_SCTRL_RTOS_IDLE_WAKEUP: + sctrl_exit_rtos_idle_sleep(); + break; +#endif + +#if CFG_USE_DEEP_PS + case CMD_SCTRL_RTOS_DEEP_SLEEP: + sctrl_enter_rtos_deep_sleep((PS_DEEP_CTRL_PARAM *)param); + break; +#endif + + case CMD_GET_CHIP_ID: + ret = REG_READ(SCTRL_CHIP_ID); + break; + + case CMD_SCTRL_SET_FLASH_DPLL: + reg = REG_READ(SCTRL_CONTROL); + reg |= FLASH_26M_MUX_BIT; + REG_WRITE(SCTRL_CONTROL, reg); + break; + + case CMD_SCTRL_SET_FLASH_DCO: + reg = REG_READ(SCTRL_CONTROL); + reg &= ~FLASH_26M_MUX_BIT; + REG_WRITE(SCTRL_CONTROL, reg); + break; + + case CMD_SCTRL_DSP_POWERDOWN: + case CMD_SCTRL_USB_POWERDOWN: + case CMD_SCTRL_MODEM_POWERDOWN: + case CMD_SCTRL_MAC_POWERDOWN: + case CMD_SCTRL_DSP_POWERUP: + case CMD_SCTRL_USB_POWERUP: + case CMD_SCTRL_MAC_POWERUP: + case CMD_SCTRL_MODEM_POWERUP: + case CMD_SCTRL_BLE_POWERDOWN: + case CMD_SCTRL_BLE_POWERUP: + sctrl_subsys_power(cmd); + break; + + case CMD_GET_DEVICE_ID: + ret = REG_READ(SCTRL_DEVICE_ID); + break; + + case CMD_GET_SCTRL_CONTROL: + *((UINT32 *)param) = REG_READ(SCTRL_CONTROL); + break; + + case CMD_SET_SCTRL_CONTROL: + REG_WRITE(SCTRL_CONTROL, *((UINT32 *)param)); + break; + + case CMD_SCTRL_MCLK_SELECT: + reg = REG_READ(SCTRL_CONTROL); + reg &= ~(MCLK_MUX_MASK << MCLK_MUX_POSI); + reg |= ((*(UINT32 *)param) & MCLK_MUX_MASK) << MCLK_MUX_POSI; + REG_WRITE(SCTRL_CONTROL, reg); + break; + + case CMD_SCTRL_MCLK_DIVISION: + reg = REG_READ(SCTRL_CONTROL); + reg &= ~(MCLK_DIV_MASK << MCLK_DIV_POSI); + reg |= ((*(UINT32 *)param) & MCLK_DIV_MASK) << MCLK_DIV_POSI; + REG_WRITE(SCTRL_CONTROL, reg); + break; + + case CMD_SCTRL_MCLK_MUX_GET: + reg = ((REG_READ(SCTRL_CONTROL) >> MCLK_MUX_POSI) & MCLK_MUX_MASK); + *(UINT32 *)param = reg; + break; + + case CMD_SCTRL_MCLK_DIV_GET: + reg = ((REG_READ(SCTRL_CONTROL) >> MCLK_DIV_POSI) & MCLK_DIV_MASK); + *(UINT32 *)param = reg; + break; + + case CMD_SCTRL_MCLK_LIMIT_FREQ_BIT_SET: + limit_freq_status |= (*(UINT32 *)param); + os_null_printf("l:%x %x\r\n",limit_freq_status,(*(UINT32 *)param)); + if(limit_freq_status) + { + reg = REG_READ(SCTRL_CONTROL); + reg &= ~(MCLK_DIV_MASK << MCLK_DIV_POSI); + #if (CFG_SOC_NAME == SOC_BK7221U) + reg &= ~HCLK_DIV2_EN_BIT; + #endif + reg |= ((MCLK_DIV_7 & MCLK_DIV_MASK) << MCLK_DIV_POSI); + reg &= ~(MCLK_MUX_MASK << MCLK_MUX_POSI); + reg |= ((MCLK_FIELD_DPLL & MCLK_MUX_MASK) << MCLK_MUX_POSI); + REG_WRITE(SCTRL_CONTROL, reg); + } + break; + + case CMD_SCTRL_MCLK_LIMIT_FREQ_BIT_CLR: + limit_freq_status &= ~(*(UINT32 *)param); + os_null_printf("f:%x %x\r\n",limit_freq_status,(*(UINT32 *)param)); + if(0 == limit_freq_status) + { + #if (USE_DCO_CLK_POWON ) + sctrl_set_cpu_clk_dco(); + #else + reg = REG_READ(SCTRL_CONTROL); + reg &= ~(MCLK_DIV_MASK << MCLK_DIV_POSI); + #if (CFG_SOC_NAME == SOC_BK7221U) + reg |= HCLK_DIV2_EN_BIT; + #endif +#if (CFG_SOC_NAME == SOC_BK7231N) + reg |= ((MCLK_DIV_5 & MCLK_DIV_MASK) << MCLK_DIV_POSI); +#else + reg |= ((MCLK_DIV_3 & MCLK_DIV_MASK) << MCLK_DIV_POSI); +#endif + REG_WRITE(SCTRL_CONTROL, reg); + #endif + } + break; + + case CMD_SCTRL_RESET_SET: + reg = REG_READ(SCTRL_RESET); + reg |= ((*(UINT32 *)param) & SCTRL_RESET_MASK); + REG_WRITE(SCTRL_RESET, reg); + break; + + case CMD_SCTRL_RESET_CLR: + reg = REG_READ(SCTRL_RESET); + reg &= ~((*(UINT32 *)param) & SCTRL_RESET_MASK); + REG_WRITE(SCTRL_RESET, reg); + break; + + case CMD_SCTRL_MODEM_SUBCHIP_RESET: + case CMD_SCTRL_MAC_SUBSYS_RESET: + case CMD_SCTRL_USB_SUBSYS_RESET: + case CMD_SCTRL_DSP_SUBSYS_RESET: + sctrl_subsys_reset(cmd); + break; + + case CMD_SCTRL_MODEM_CORE_RESET: + ret = REG_READ(SCTRL_MODEM_CORE_RESET_PHY_HCLK); + ret = ret & (~((MODEM_CORE_RESET_MASK) << MODEM_CORE_RESET_POSI)); + reg = ret | ((MODEM_CORE_RESET_WORD & MODEM_CORE_RESET_MASK) + << MODEM_CORE_RESET_POSI); + REG_WRITE(SCTRL_MODEM_CORE_RESET_PHY_HCLK, reg); + + delay(1); + reg = ret; + REG_WRITE(SCTRL_MODEM_CORE_RESET_PHY_HCLK, reg); + + /*resetting, and waiting for done*/ + reg = REG_READ(SCTRL_RESET); + while(reg & MODEM_CORE_RESET_BIT) + { + delay(10); + reg = REG_READ(SCTRL_RESET); + } + ret = SCTRL_SUCCESS; + break; + + case CMD_SCTRL_MPIF_CLK_INVERT: + reg = REG_READ(SCTRL_CONTROL); + reg |= MPIF_CLK_INVERT_BIT; + REG_WRITE(SCTRL_CONTROL, reg); + break; + + case CMD_SCTRL_BLK_ENABLE: + reg = REG_READ(SCTRL_BLOCK_EN_CFG); + reg &= (~(BLOCK_EN_WORD_MASK << BLOCK_EN_WORD_POSI)); + reg |= (BLOCK_EN_WORD_PWD & BLOCK_EN_WORD_MASK) << BLOCK_EN_WORD_POSI; + reg |= ((*(UINT32 *)param) & BLOCK_EN_VALID_MASK); + REG_WRITE(SCTRL_BLOCK_EN_CFG, reg); + break; + + case CMD_SCTRL_BLK_DISABLE: + CHECK_OPERATE_RF_REG_IF_IN_SLEEP(); + reg = REG_READ(SCTRL_BLOCK_EN_CFG); + reg &= (~(BLOCK_EN_WORD_MASK << BLOCK_EN_WORD_POSI)); + reg |= (BLOCK_EN_WORD_PWD & BLOCK_EN_WORD_MASK) << BLOCK_EN_WORD_POSI; + reg &= ~((*(UINT32 *)param) & BLOCK_EN_VALID_MASK); + REG_WRITE(SCTRL_BLOCK_EN_CFG, reg); + CHECK_OPERATE_RF_REG_IF_IN_SLEEP_END(); + break; + + case CMD_SCTRL_BIAS_REG_SET: + reg = REG_READ(SCTRL_BIAS); + reg |= (*(UINT32 *)param); + REG_WRITE(SCTRL_BIAS, reg); + break; + + case CMD_SCTRL_BIAS_REG_CLEAN: + reg = REG_READ(SCTRL_BIAS); + reg &= ~(*(UINT32 *)param); + REG_WRITE(SCTRL_BIAS, reg); + break; + + case CMD_SCTRL_BIAS_REG_READ: + ret = REG_READ(SCTRL_BIAS); + break; + + case CMD_SCTRL_BIAS_REG_WRITE: + REG_WRITE(SCTRL_BIAS, *(UINT32 *)param); + break; + + case CMD_SCTRL_ANALOG_CTRL4_SET: + reg = sctrl_analog_get(SCTRL_ANALOG_CTRL4); + reg |= (*(UINT32 *)param); + sctrl_analog_set(SCTRL_ANALOG_CTRL4, reg); + break; + + case CMD_SCTRL_ANALOG_CTRL4_CLEAN: + reg = sctrl_analog_get(SCTRL_ANALOG_CTRL4); + reg &= ~(*(UINT32 *)param); + sctrl_analog_set(SCTRL_ANALOG_CTRL4, reg); + break; + + case CMD_SCTRL_CALI_DPLL: + sctrl_cali_dpll(0); + break; + +#if (CFG_SOC_NAME != SOC_BK7231) + case CMD_SCTRL_SET_XTALH_CTUNE: + reg = sctrl_analog_get(SCTRL_ANALOG_CTRL2); + reg &= ~(XTALH_CTUNE_MASK<< XTALH_CTUNE_POSI); + reg |= (((*(UINT32 *)param) &XTALH_CTUNE_MASK) << XTALH_CTUNE_POSI); + sctrl_analog_set(SCTRL_ANALOG_CTRL2, reg); + break; + + case CMD_SCTRL_GET_XTALH_CTUNE: + reg = sctrl_analog_get(SCTRL_ANALOG_CTRL2); + ret = ((reg >> XTALH_CTUNE_POSI) & XTALH_CTUNE_MASK); + break; + + case CMD_BLE_RF_BIT_SET: + reg = REG_READ(SCTRL_CONTROL); + reg |= BLE_RF_EN_BIT; + REG_WRITE(SCTRL_CONTROL, reg); + break; + + case CMD_BLE_RF_BIT_CLR: + reg = REG_READ(SCTRL_CONTROL); + reg &= ~(BLE_RF_EN_BIT); + REG_WRITE(SCTRL_CONTROL, reg); + break; +#if (CFG_SOC_NAME == SOC_BK7231N) + case CMD_BLE_RF_PTA_EN: + reg = REG_READ(SCTRL_CONTROL); + reg |= (BLE_RF_PTA_EN_BIT); + REG_WRITE(SCTRL_CONTROL, reg); + break; + case CMD_BLE_RF_PTA_DIS: + reg = REG_READ(SCTRL_CONTROL); + reg &= ~(BLE_RF_PTA_EN_BIT); + REG_WRITE(SCTRL_CONTROL, reg); + break; +#endif + + case CMD_BLE_RF_BIT_GET: + reg = REG_READ(SCTRL_CONTROL); + *((UINT32 *)param) = reg & (BLE_RF_EN_BIT); + break; + + case CMD_EFUSE_WRITE_BYTE: + ret = sctrl_write_efuse(param); + break; + + case CMD_EFUSE_READ_BYTE: + ret = sctrl_read_efuse(param); + break; + +#endif // (CFG_SOC_NAME != SOC_BK7231) + +#if (CFG_SOC_NAME == SOC_BK7221U) + case CMD_SCTRL_OPEN_DAC_ANALOG: + reg = sctrl_analog_get(SCTRL_ANALOG_CTRL9); + reg |= EN_AUD_DAC_L | EN_AUD_DAC_R + | DAC_PA_OUTPUT_EN | DAC_DRIVER_OUTPUT_EN + | AUD_DAC_DGA_EN; + sctrl_analog_set(SCTRL_ANALOG_CTRL9, reg); + + reg = sctrl_analog_get(SCTRL_ANALOG_CTRL10); + reg |= DAC_N_END_OUPT_L | DAC_N_END_OUPT_R; + sctrl_analog_set(SCTRL_ANALOG_CTRL10, reg); + break; + + case CMD_SCTRL_CLOSE_DAC_ANALOG: + reg = sctrl_analog_get(SCTRL_ANALOG_CTRL9); + reg &= ~(EN_AUD_DAC_L | EN_AUD_DAC_R + | DAC_PA_OUTPUT_EN | DAC_DRIVER_OUTPUT_EN + | AUD_DAC_DGA_EN); + sctrl_analog_set(SCTRL_ANALOG_CTRL9, reg); + + reg = sctrl_analog_get(SCTRL_ANALOG_CTRL10); + reg &= ~(DAC_N_END_OUPT_L | DAC_N_END_OUPT_R); + sctrl_analog_set(SCTRL_ANALOG_CTRL10, reg); + break; + + case CMD_SCTRL_OPEN_ADC_MIC_ANALOG: + reg = sctrl_analog_get(SCTRL_ANALOG_CTRL8); + reg &= ~(SPI_PWD_AUD_ADC_L | SPI_PWD_AUD_ADC_R); + sctrl_analog_set(SCTRL_ANALOG_CTRL8, reg); + break; + + case CMD_SCTRL_CLOSE_ADC_MIC_ANALOG: + reg = sctrl_analog_get(SCTRL_ANALOG_CTRL8); + reg |= (SPI_PWD_AUD_ADC_L | SPI_PWD_AUD_ADC_R); + sctrl_analog_set(SCTRL_ANALOG_CTRL8, reg); + break; + + case CMD_SCTRL_ENALBLE_ADC_LINE_IN: + reg = sctrl_analog_get(SCTRL_ANALOG_CTRL8); + reg |= LINE_IN_EN; + sctrl_analog_set(SCTRL_ANALOG_CTRL8, reg); + break; + + case CMD_SCTRL_DISALBLE_ADC_LINE_IN: + reg = sctrl_analog_get(SCTRL_ANALOG_CTRL8); + reg &= ~LINE_IN_EN; + sctrl_analog_set(SCTRL_ANALOG_CTRL8, reg); + break; + + case CMD_SCTRL_SET_DAC_VOLUME_ANALOG: + reg = sctrl_analog_get(SCTRL_ANALOG_CTRL8); + reg &= ~(AUD_DAC_GAIN_MASK << AUD_DAC_GAIN_POSI); + reg |= (((*(UINT32 *)param) & AUD_DAC_GAIN_MASK) << AUD_DAC_GAIN_POSI); + sctrl_analog_set(SCTRL_ANALOG_CTRL8, reg); + break; + + case CMD_SCTRL_SET_LINEIN_VOLUME_ANALOG: + reg = sctrl_analog_get(SCTRL_ANALOG_CTRL8); + reg &= ~(LINE_IN_GAIN_MASK << LINE_IN_GAIN_POSI); + reg |= (((*(UINT32 *)param) & LINE_IN_GAIN_MASK) << LINE_IN_GAIN_POSI); + sctrl_analog_set(SCTRL_ANALOG_CTRL8, reg); + break; + +#endif // (CFG_SOC_NAME == SOC_BK7221U) + case CMD_SCTRL_SET_ANALOG0: + sctrl_analog_set(SCTRL_ANALOG_CTRL0, (*(UINT32 *)param)); + break; + case CMD_SCTRL_SET_ANALOG1: + sctrl_analog_set(SCTRL_ANALOG_CTRL1, (*(UINT32 *)param)); + break; + case CMD_SCTRL_SET_ANALOG2: + sctrl_analog_set(SCTRL_ANALOG_CTRL2, (*(UINT32 *)param)); + break; + case CMD_SCTRL_SET_ANALOG3: + sctrl_analog_set(SCTRL_ANALOG_CTRL3, (*(UINT32 *)param)); + break; + case CMD_SCTRL_SET_ANALOG4: + sctrl_analog_set(SCTRL_ANALOG_CTRL4, (*(UINT32 *)param)); + break; + case CMD_SCTRL_SET_ANALOG5: + sctrl_analog_set(SCTRL_ANALOG_CTRL5, (*(UINT32 *)param)); + break; + case CMD_SCTRL_GET_ANALOG0: + ret = sctrl_analog_get(SCTRL_ANALOG_CTRL0); + break; + case CMD_SCTRL_GET_ANALOG1: + ret = sctrl_analog_get(SCTRL_ANALOG_CTRL1); + break; + case CMD_SCTRL_GET_ANALOG2: + ret = sctrl_analog_get(SCTRL_ANALOG_CTRL2); + break; + case CMD_SCTRL_GET_ANALOG3: + ret = sctrl_analog_get(SCTRL_ANALOG_CTRL3); + break; + case CMD_SCTRL_GET_ANALOG4: + ret = sctrl_analog_get(SCTRL_ANALOG_CTRL4); + break; + case CMD_SCTRL_GET_ANALOG5: + ret = sctrl_analog_get(SCTRL_ANALOG_CTRL5); + break; + case CMD_SCTRL_SET_LOW_PWR_CLK: + reg = REG_READ(SCTRL_LOW_PWR_CLK); + reg &=~(LPO_CLK_MUX_MASK); + reg |=((*(UINT32 *)param) << LPO_CLK_MUX_POSI); + REG_WRITE(SCTRL_LOW_PWR_CLK, reg); + break; + case CMD_SCTRL_SET_GADC_SEL: + #if (CFG_SOC_NAME == SOC_BK7231N) + reg = sctrl_analog_get(SCTRL_ANALOG_CTRL4); + reg &= ~(GADC_CAL_SEL_MASK << GADC_CAL_SEL_POSI); + reg |= (((*(UINT32 *)param) & GADC_CAL_SEL_MASK) << GADC_CAL_SEL_POSI); + sctrl_analog_set(SCTRL_ANALOG_CTRL4, reg); + #endif + break; + case CMD_SCTRL_SET_VDD_VALUE: + reg = REG_READ(SCTRL_DIGTAL_VDD); + reg &= (~(DIG_VDD_ACTIVE_MASK << DIG_VDD_ACTIVE_POSI)); + reg |=((*(UINT32 *)param) << DIG_VDD_ACTIVE_POSI); + REG_WRITE(SCTRL_DIGTAL_VDD, reg); + break; + case CMD_SCTRL_GET_VDD_VALUE: + reg = REG_READ(SCTRL_DIGTAL_VDD); + ret = (reg >> DIG_VDD_ACTIVE_POSI) & DIG_VDD_ACTIVE_MASK; + break; + + case CMD_GET_SCTRL_RETETION: + *((UINT32 *)param) = REG_READ(SCTRL_SW_RETENTION); + break; + + case CMD_SET_SCTRL_RETETION: + REG_WRITE(SCTRL_SW_RETENTION, *((UINT32 *)param)); + break; + + default: + ret = SCTRL_FAILURE; + break; + } + GLOBAL_INT_RESTORE(); + + return ret; +} + +// EOF diff --git a/beken_os/beken378/driver/sys_ctrl/sys_ctrl.h b/beken_os/beken378/driver/sys_ctrl/sys_ctrl.h new file mode 100755 index 0000000..3a2d797 --- /dev/null +++ b/beken_os/beken378/driver/sys_ctrl/sys_ctrl.h @@ -0,0 +1,537 @@ +#ifndef _SCTRL_H_ +#define _SCTRL_H_ + +//#define SCTRL_DEBUG + +#ifdef SCTRL_DEBUG +#define SCTRL_PRT os_printf +#else +#define SCTRL_PRT os_null_printf +#endif + +#define DPLL_DELAY_TIME_10US 120 +#define DPLL_DELAY_TIME_200US 3400 + +#define SCTRL_BASE (0x00800000) + +#define SCTRL_CHIP_ID (SCTRL_BASE + 00 * 4) +#define CHIP_ID_DEFAULT (0x7111) +#define CHIP_ID_BK7231N (0x7231C) + +#define SCTRL_DEVICE_ID (SCTRL_BASE + 01 * 4) +#define DEVICE_ID_MASK (0xFFFF0000) //as wangjian advised, only check high 16 bits +#define DEVICE_ID_DEFAULT (0x20150414) +#define DEVICE_ID_BK7231N_B (0x20521024) +#define DEVICE_ID_BK7231N_C (0x20521025) +#define DEVICE_ID_BK7231N_D (0x20521026) +#define DEVICE_ID_BK7231N_E (0x20521027) +#define DEVICE_ID_BK7231N_F (0x20521028) +#define DEVICE_ID_BK7231N_N (0x20521010) +#define DEVICE_ID_BK7231N_P (0x20A21020) + +#define SCTRL_CONTROL (SCTRL_BASE + 02 * 4) +#if (CFG_SOC_NAME == SOC_BK7221U) +#define EFUSE_VDD25_EN (1 << 23) +#define FLASH_SPI_MUX_BIT (1 << 22) +#define PSRAM_VDDPAD_VOLT_POSI (20) +#define PSRAM_VDDPAD_VOLT_MASK (0x3) +#define FLASH_SCK_IOCAP_POSI (18) +#define FLASH_SCK_IOCAP_MASK (0x3) +#define QSPI_IO_VOLT_POSI (16) +#define QSPI_IO_VOLT_MASK (0x3) +#define BLE_RF_EN_BIT (1 << 15) +#elif (CFG_SOC_NAME == SOC_BK7231U) +#define EFUSE_VDD25_EN (1 << 23) +#define PSRAM_VDDPAD_VOLT_POSI (20) +#define PSRAM_VDDPAD_VOLT_MASK (0x3) +#define FLASH_SCK_IOCAP_POSI (18) +#define FLASH_SCK_IOCAP_MASK (0x3) +#define QSPI_IO_VOLT_POSI (16) +#define QSPI_IO_VOLT_MASK (0x3) +#define BLE_RF_EN_BIT (1 << 15) +#elif (CFG_SOC_NAME == SOC_BK7231N) +#define BLE_RF_PTA_EN_BIT (1 << 24) +#define EFUSE_VDD25_EN (1 << 23) +#define FLASH_SPI_MUX_BIT (1 << 22) +#define FLASH_SCK_IOCAP_POSI (18) +#define FLASH_SCK_IOCAP_MASK (0x3) +#define BLE_RF_EN_BIT (1 << 15) +#endif // (CFG_SOC_NAME == SOC_BK7221U) +#define DPLL_CLKDIV_RESET_BIT (1 << 14) +#define SDIO_CLK_INVERT_BIT (1 << 13) +#define MPIF_CLK_INVERT_BIT (1 << 12) +#define MAC_CLK480M_PWD_BIT (1 << 11) +#define MODEM_CLK480M_PWD_BIT (1 << 10) +#define HCLK_DIV2_EN_BIT (1 << 9) +#define FLASH_26M_MUX_BIT (1 << 8) + +#define MCLK_DIV_MASK (0x0F) +#define MCLK_DIV_POSI (4) +#define MCLK_DIV_1 (1) +#define MCLK_DIV_2 (2) +#define MCLK_DIV_3 (3) +#define MCLK_DIV_5 (5) +#define MCLK_DIV_6 (6) +#define MCLK_DIV_7 (7) +#define MCLK_DIV_10 (10) +#define MCLK_DIV_16 (16) + +#define MCLK_MUX_MASK (0x03) +#define MCLK_MUX_POSI (0) +#define MCLK_FIELD_DCO (0x0) +#define MCLK_FIELD_26M_XTAL (0x1) +#define MCLK_FIELD_DPLL (0x2) +#define MCLK_FIELD_LPO (0x3) + +#define SCTRL_CLK_GATING (SCTRL_BASE + 3 * 4) +#define MAC_PI_CLKGATING_BIT (1 << 8) +#define MAC_PI_RX_CLKGATING_BIT (1 << 7) +#define MAC_PI_TX_CLKGATING_BIT (1 << 6) +#define MAC_PRI_CLKGATING_BIT (1 << 5) +#define MAC_CRYPT_CLKGATING_BIT (1 << 4) +#define MAC_CORE_TX_CLKGATING_BIT (1 << 3) +#define MAC_CORE_RX_CLKGATING_BIT (1 << 2) +#define MAC_WT_CLKGATING_BIT (1 << 1) +#define MAC_MPIF_CLKGATING_BIT (1 << 0) + +#define SCTRL_RESET (SCTRL_BASE + 4 * 4) +#define SCTRL_RESET_MASK (0x7F) +#if (CFG_SOC_NAME != SOC_BK7231) +#define BLE_SUBSYS_RESET (1 << 8) +#endif // (CFG_SOC_NAME != SOC_BK7231) +#define MAC_WAKEUP_ARM (1 << 7) +#define MODEM_CORE_RESET_BIT (1 << 6) +#if (CFG_SOC_NAME == SOC_BK7231N) +#define BOOT_MODE_BIT (1 << 9) +#define MAC_SUBSYS_RESET_BIT (1 << 2) +#else +#define TL410_EXT_WAIT_BIT (1 << 5) +#define USB_SUBSYS_RESET_BIT (1 << 4) +#define TL410_BOOT_BIT (1 << 3) +#define MAC_SUBSYS_RESET_BIT (1 << 2) +#define DSP_SUBSYS_RESET_BIT (1 << 1) +#endif +#define MODEM_SUBCHIP_RESET_BIT (1 << 0) + +#define SCTRL_FLASH_DELAY (SCTRL_BASE + 7 * 4) +#define FLASH_DELAY_CYCLE_POSI (0) +#define FLASH_DELAY_CYCLE_MASK (0xFFF) + +#define SCTRL_MODEM_SUBCHIP_RESET_REQ (SCTRL_BASE + 8 * 4) +#define MODEM_SUBCHIP_RESET_WORD (0x7111e802) + +#define SCTRL_MAC_SUBSYS_RESET_REQ (SCTRL_BASE + 9 * 4) +#define MAC_SUBSYS_RESET_WORD (0x7111C802) + +#define SCTRL_USB_SUBSYS_RESET_REQ (SCTRL_BASE + 10 * 4) +#define USB_SUBSYS_RESET_WORD (0x7111C12B) + +#define SCTRL_DSP_SUBSYS_RESET_REQ (SCTRL_BASE + 11 * 4) +#define DSP_SUBSYS_RESET_WORD (0x7111C410) + +#define SCTRL_MODEM_CORE_RESET_PHY_HCLK (SCTRL_BASE + 12 * 4) +#define MODEM_CORE_RESET_POSI (16) +#define MODEM_CORE_RESET_MASK (0xFFFF) +#define MODEM_CORE_RESET_WORD (0xE802U) +#define MAC_HCLK_EN_BIT (1 << 1) +#define PHY_HCLK_EN_BIT (1 << 0) + +#define SCTRL_DEBUG13 (SCTRL_BASE + 13 * 4) +#define DBGMACCLKSEL_POSI (20) +#define DBGMACCLKSEL_MASK (0x1) +#define SMPSOURCE_POSI (16) +#define SMPSOURCE_MASK (0xF) +#define DBGMDMBANK1MUX_POSI (8) +#define DBGMDMBANK1MUX_MASK (0x1F) +#define DBGMDMBANK0MUX_POSI (02) +#define DBGMDMBANK0MUX_MASK (0x1F) + +#define SCTRL_DEBUG14_MODEM_BANK (SCTRL_BASE + 14 * 4) +#define SCTRL_DEBUG15_MAC_BANK (SCTRL_BASE + 15 * 4) + + +#define SCTRL_ANALOG_SPI (SCTRL_BASE + 16 * 4) +#define ANA_SPI_FREQ_DIV_POSI (26) +#define ANA_SPI_FREQ_DIV_MASK (0x3F) +#if (CFG_SOC_NAME == SOC_BK7231) +#define ANA_SPI_STATE_POSI (0) +#define ANA_SPI_STAET_MASK (0x1F) +#elif (CFG_SOC_NAME == SOC_BK7231U) || (SOC_BK7231N == CFG_SOC_NAME) +#define ANA_SPI_STATE_POSI (0) +#define ANA_SPI_STAET_MASK (0x7F) +#elif (CFG_SOC_NAME == SOC_BK7221U) +#define ANA_SPI_STATE_POSI (0) +#define ANA_SPI_STAET_MASK (0x7FF) +#endif + +#if (CFG_SOC_NAME != SOC_BK7231N) +#define SCTRL_LA_SAMPLE (SCTRL_BASE + 18 * 4) +#define LA_SMP_LEN_POSI (16) +#define LA_SMP_LEN_MASK (0xFFFF) +#define LA_SMP_FINISH_BIT (1 << 3) +#define LA_SMP_CLK_INVERT (1 << 2) +#define LA_SMP_MODE_POSI (0) +#define LA_SMP_MODE_MASK (0x3) + +#define SCTRL_LA_SAMPLE_VALUE (SCTRL_BASE + 19 * 4) +#define SCTRL_LA_SAMPLE_MASK (SCTRL_BASE + 20 * 4) +#define SCTRL_LA_SAMPLE_DMA_START_ADDR (SCTRL_BASE + 21 * 4) +#endif + +#define SCTRL_ANALOG_CTRL0 (SCTRL_BASE + 22 * 4) +#if (CFG_SOC_NAME == SOC_BK7231N) +#define LPEN_DPLL (1 << 27) +#endif +#define SPI_TRIG_BIT (1 << 19) +#define SPI_DET_EN (1 << 4) + +#define SCTRL_ANALOG_CTRL1 (SCTRL_BASE + 23 * 4) +#if (CFG_SOC_NAME == SOC_BK7231N) +#define ROSC_TSTEN_BIT (1 << 31) +#define DCO_TSTEN_BIT (1 << 30) +#define DCO_DIV_POSI (27) +#define DCO_DIV_MASK (0x7U) +#define DCO_AMSEL_BIT (1 << 26) +#define SPI_RST_BIT (1 << 25) +#define DCO_CNTI_POSI (16) +#define DCO_CNTI_MASK (0x1FFU) +#define DCO_TRIG_BIT (1 << 15) +#define DCO_ICTRL_POSI (11) +#define DCO_ICTRL_MASK (0x7U) +#define DCO_MSW_POSI (2) +#define DCO_MSW_MASK (0x1FFU) +#define DPLL_VREFSEL_BIT (1 << 1) +#else +#define DIV_BYPASS_BIT (1 << 31) +#define SPI_RST_BIT (1 << 25) +#define DCO_CNTI_POSI (16) +#define DCO_CNTI_MASK (0x1FFU) +#define DCO_TRIG_BIT (1 << 15) +#define DCO_DIV_POSI (12) +#define DCO_DIV_MASK (0x3U) +#endif + +#define SCTRL_ANALOG_CTRL2 (SCTRL_BASE + 24 * 4) +#define CENTRAL_BAIS_ENABLE_BIT (1 << 13) +#if (CFG_SOC_NAME == SOC_BK7231N) +#define XTALH_CTUNE_POSI (2) +#define XTALH_CTUNE_MASK (0x7FU) +#define BANDGAP_CAL_MANUAL_POSI (23) +#define BANDGAP_CAL_MANUAL_MASK (0x3FU) +#elif (CFG_SOC_NAME != SOC_BK7231) +#define XTALH_CTUNE_POSI (2) +#define XTALH_CTUNE_MASK (0x3FU) +#endif // (CFG_SOC_NAME == SOC_BK7231) +#define TRXT_TST_ENABLE_BIT (1 << 12) + +#define SCTRL_ANALOG_CTRL3 (SCTRL_BASE + 25 * 4) + +#define SCTRL_ANALOG_CTRL4 (SCTRL_BASE + 26 * 4) +#if (CFG_SOC_NAME == SOC_BK7231N) +#define GADC_CAL_SEL_POSI (19) +#define GADC_CAL_SEL_MASK (0x3) +#else +#define VSEL_SYS_LDO_POSI (27) +#define VSEL_SYS_LDO_MASK (0x3) +#endif // (CFG_SOC_NAME == SOC_BK7231N) + +#define SCTRL_ANALOG_CTRL5 (SCTRL_BASE + 0x1B*4) + +#if (CFG_SOC_NAME != SOC_BK7231) +#define SCTRL_ANALOG_CTRL6 (SCTRL_BASE + 0x1C*4) + +#define SCTRL_EFUSE_CTRL (SCTRL_BASE + 0x1D*4) +#define EFUSE_OPER_EN (1 << 0) +#define EFUSE_OPER_DIR (1 << 1) +#define EFUSE_OPER_ADDR_POSI (8) +#define EFUSE_OPER_ADDR_MASK (0x1F) +#define EFUSE_OPER_WR_DATA_POSI (16) +#define EFUSE_OPER_WR_DATA_MASK (0xFF) + +#define SCTRL_EFUSE_OPTR (SCTRL_BASE + 0x1E*4) +#define EFUSE_OPER_RD_DATA_POSI (0) +#define EFUSE_OPER_RD_DATA_MASK (0xFF) +#define EFUSE_OPER_RD_DATA_VALID (1 << 8) + + +#define SCTRL_DMA_PRIO_VAL (SCTRL_BASE + 0x1F*4) + +#define SCTRL_BLE_SUBSYS_RESET_REQ (SCTRL_BASE + 0x20*4) +#if (CFG_SOC_NAME == SOC_BK7221U) +#define SCTRL_CHARGE_STATUS (SCTRL_BASE + 0x21*4) + +#define SCTRL_ANALOG_CTRL7 (SCTRL_BASE + 0x22*4) + +#define SCTRL_ANALOG_CTRL8 (SCTRL_BASE + 0x23*4) +#define LINE_IN_EN (1 << 24) +#define LINE_IN_GAIN_MASK (0x3) +#define LINE_IN_GAIN_POSI (22) +#define SPI_PWD_AUD_ADC_L (1 << 21) +#define SPI_PWD_AUD_ADC_R (1 << 20) +#define AUD_DAC_GAIN_MASK (0x1F) +#define AUD_DAC_GAIN_POSI (2) + +#define SCTRL_ANALOG_CTRL9 (SCTRL_BASE + 0x24*4) +#define EN_AUD_DAC_L (1 << 30) +#define EN_AUD_DAC_R (1 << 29) +#define DAC_PA_OUTPUT_EN (1 << 24) +#define DAC_DRIVER_OUTPUT_EN (1 << 23) +#define AUD_DAC_DGA_EN (1 << 6) + +#define SCTRL_ANALOG_CTRL10 (SCTRL_BASE + 0x25*4) +#define DAC_N_END_OUPT_L (1 << 8) +#define DAC_N_END_OUPT_R (1 << 7) + +#elif (CFG_SOC_NAME == SOC_BK7231N) +#define SCTRL_ANALOG_STATE (SCTRL_BASE + 0x21*4) +#define ANALOG_STATE_MASK (0xFF) +#define ANALOG_STATE_POS (0) +#endif // (CFG_SOC_NAME == SOC_BK7221U) +#endif // (CFG_SOC_NAME != SOC_BK7221U) + +#define SCTRL_LOW_PWR_CLK (SCTRL_BASE + 64 * 4) +#define LPO_CLK_MUX_POSI (0) +#define LPO_CLK_MUX_MASK (0x3) +#define LPO_SRC_ROSC (0x0) +#define LPO_SRC_32K_XTAL (0x1) +#define LPO_SRC_32K_DIV (0x2) + +#define DEEP_SLEEP_LPO_SRC LPO_SRC_32K_XTAL + +#define SCTRL_SLEEP (SCTRL_BASE + 65 * 4) +#define PROCORE_DLY_POSI (20) +#define PROCORE_DLY_MASK (0xF) +#if (CFG_SOC_NAME == SOC_BK7231N) +#define GPIO_SLEEP_SWITCH_BIT (1 << 19) +#define DCO_PWD_SLEEP_BIT (1 << 17) +#define FLASH_PWD_SLEEP_BIT (1 << 18) +#else +#define DCO_PWD_SLEEP_BIT (1 << 18) +#define FLASH_PWD_SLEEP_BIT (1 << 17) +#endif +#define ROSC_PWD_DEEPSLEEP_BIT (1 << 16) +#define SLEEP_MODE_POSI (0) +#define SLEEP_MODE_MASK (0xFFFF) +#define SLEEP_MODE_CFG_NORMAL_VOL_WORD (0x4F89) +#define SLEEP_MODE_CFG_LOW_VOL_WORD (0xB706) +#define SLEEP_MODE_CFG_DEEP_WORD (0xADC1) + +#define SCTRL_DIGTAL_VDD (SCTRL_BASE + 66 * 4) +#define DIG_VDD_ACTIVE_POSI (4) +#define DIG_VDD_ACTIVE_MASK (0x7) +#define DIG_VDD_SLEEP_POSI (0) +#define DIG_VDD_SLEEP_MASK (0x7) +#define VDD_1_DOT_51 (0x7) +#define VDD_1_DOT_38 (0x6) +#define VDD_1_DOT_25 (0x5) +#define VDD_1_DOT_12 (0x4) +#define VDD_0_DOT_99 (0x3) +#define VDD_0_DOT_86 (0x2) +#define VDD_0_DOT_73 (0x1) +#define VDD_0_DOT_60 (0x0) + +#define SCTRL_PWR_MAC_MODEM (SCTRL_BASE + 67 * 4) +#define MAC_PWD_POSI (16) +#define MAC_PWD_MASK (0xFFFFU) +#define MODEM_PWD_POSI (0) +#define MODEM_PWD_MASK (0xFFFFU) +#define MAC_PWD (0xD802U) +#define MODEM_PWD (0xD802U) +#define MAC_PWU (0x0001U) +#define MODEM_PWU (0x0001U) + +#define SCTRL_DSP_PWR (SCTRL_BASE + 68 * 4) +#define DSP_PWD_POSI (0) +#define DSP_PWD_MASK (0xFFFF) +#define DSP_PWD (0xD410) +#define DSP_PWU (0x0001) + +#define SCTRL_USB_PWR (SCTRL_BASE + 69 * 4) +#define BLE_PWD_POSI (16) +#define BLE_PWD_MASK (0xFFFF) +#define BLE_PWD (0xDB1E) +#define BLE_PWU (0x0001) +#if (CFG_SOC_NAME != SOC_BK7231N) +#define USB_PWD_POSI (0) +#define USB_PWD_MASK (0xFFFF) +#define USB_PWD (0xD12B) +#define USB_PWU (0x0001) +#endif + +#define SCTRL_PMU_STATUS (SCTRL_BASE + 70 * 4) +#define PMU_MAC_POWER_DOWN_BIT (1 << 3) +#define PMU_MODEM_POWER_DOWN_BIT (1 << 2) +#if (CFG_SOC_NAME != SOC_BK7231N) +#define PMU_DSP_POWER_DOWN_BIT (1 << 1) +#define PMU_USB_POWER_DOWN_BIT (1 << 0) +#endif + +#define SCTRL_ROSC_TIMER (SCTRL_BASE + 71 * 4) +#define ROSC_TIMER_PERIOD_POSI (16) +#define ROSC_TIMER_PERIOD_MASK (0xFFFF) +#define ROSC_TIMER_INT_STATUS_BIT (1 << 8) +#define ROSC_TIMER_ENABLE_BIT (1 << 0) + +#define SCTRL_GPIO_WAKEUP_EN (SCTRL_BASE + 72 * 4) +#define SCTRL_GPIO_WAKEUP_TYPE (SCTRL_BASE + 73 * 4) +#define SCTRL_GPIO_WAKEUP_INT_STATUS (SCTRL_BASE + 74 * 4) +#define GPIO_WAKEUP_ENABLE_FLAG (1) +#define GPIO_WAKEUP_TYPE_POSITIVE_EDGE (0) +#define GPIO_WAKEUP_TYPE_NEGATIVE_EDGE (1) + +#if (CFG_SOC_NAME != SOC_BK7231N) +#define SCTRL_USB_PLUG_WAKEUP (SCTRL_BASE + 78 * 4) +#define USB_PLUG_IN_EN_BIT (1 << 0) +#define USB_PLUG_OUT_EN_BIT (1 << 1) +#define USB_PLUG_IN_INT_BIT (1 << 2) +#define USB_PLUG_OUT_INT_BIT (1 << 3) +#endif + +#if (CFG_SOC_NAME == SOC_BK7231N) +#define SCTRL_GPIO_WAKEUP_TYPE_SELECT (SCTRL_BASE + 78 * 4) +#else +#define SCTRL_GPIO_WAKEUP_EN1 (SCTRL_BASE + 81 * 4) +#define SCTRL_GPIO_WAKEUP_TYPE1 (SCTRL_BASE + 82 * 4) +#define SCTRL_GPIO_WAKEUP_INT_STATUS1 (SCTRL_BASE + 83 * 4) +#endif + +enum +{ + SYSCTRL_GPIO00_ID = 0, + SYSCTRL_GPIO01_ID, + SYSCTRL_GPIO02_ID, + SYSCTRL_GPIO03_ID, + SYSCTRL_GPIO04_ID, + SYSCTRL_GPIO05_ID, + SYSCTRL_GPIO06_ID, + SYSCTRL_GPIO07_ID, + SYSCTRL_GPIO08_ID, + SYSCTRL_GPIO09_ID, + SYSCTRL_GPIO10_ID, + SYSCTRL_GPIO11_ID, + SYSCTRL_GPIO12_ID, + SYSCTRL_GPIO13_ID, + SYSCTRL_GPIO14_ID, + SYSCTRL_GPIO15_ID, + SYSCTRL_GPIO16_ID, + SYSCTRL_GPIO17_ID, + SYSCTRL_GPIO18_ID, + SYSCTRL_GPIO19_ID, + SYSCTRL_GPIO20_ID, + SYSCTRL_GPIO21_ID, + SYSCTRL_GPIO22_ID, + SYSCTRL_GPIO23_ID, + SYSCTRL_GPIO24_ID, + SYSCTRL_GPIO25_ID, + SYSCTRL_GPIO26_ID, + SYSCTRL_GPIO27_ID, + SYSCTRL_GPIO28_ID, + SYSCTRL_GPIO29_ID, + SYSCTRL_GPIO30_ID, + SYSCTRL_GPIO31_ID +}; + + +#define SCTRL_BLOCK_EN_CFG (SCTRL_BASE + 75 * 4) +#define BLOCK_EN_WORD_POSI (20) +#define BLOCK_EN_WORD_MASK (0xFFFUL) +#define BLOCK_EN_WORD_PWD (0xA5CUL) + +#define BLOCK_EN_VALID_MASK (0xFFFFF) + +#if (CFG_SOC_NAME == SOC_BK7231) +#define BLK_EN_BIT_LINEIN (1 << 19) +#define BLK_EN_MIC_R_CHANNEL (1 << 18) +#define BLK_EN_MIC_L_CHANNEL (1 << 17) +#define BLK_EN_AUDIO_R_CHANNEL (1 << 16) +#define BLK_EN_AUDIO_L_CHANNEL (1 << 15) +#elif (CFG_SOC_NAME == SOC_BK7231U) || (CFG_SOC_NAME == SOC_BK7231N) +#define BLK_EN_NC (1 << 19) +#define BLK_EN_MIC_QSPI_RAM_OR_FLASH (1 << 18) +#define BLK_EN_MIC_PGA (1 << 17) +#define BLK_EN_AUDIO_PLL (1 << 16) +#define BLK_EN_AUDIO_RANDOM_GENERATOR (1 << 15) +#elif (CFG_SOC_NAME == SOC_BK7221U) +#define BLK_EN_NC (1 << 19) +#define BLK_EN_MIC_QSPI_RAM_OR_FLASH (1 << 18) +#define BLK_EN_AUDIO (1 << 17) +#define BLK_EN_AUDIO_PLL (1 << 16) +#define BLK_EN_AUDIO_RANDOM_GENERATOR (1 << 15) +#endif // (CFG_SOC_NAME == SOC_BK7231) +#define BLK_EN_SARADC (1 << 13) +#define BLK_EN_TEMPRATURE_SENSOR (1 << 12) +#define BLK_EN_26M_XTAL_LOW_POWER (1 << 11) +#define BLK_EN_XTAL2RF (1 << 10) +#define BLK_EN_IO_LDO_LOW_POWER (1 << 09) +#define BLK_EN_ANALOG_SYS_LDO (1 << 8) +#define BLK_EN_DIGITAL_CORE_LDO_LOW_POWER (1 << 07) +#define BLK_EN_DIGITAL_CORE (1 << 06) +#define BLK_EN_DPLL_480M (1 << 05) +#define BLK_EN_32K_XTAL (1 << 04) +#define BLK_EN_26M_XTAL (1 << 03) +#define BLK_EN_ROSC32K (1 << 02) +#define BLK_EN_DCO (1 << 01) +#define BLK_EN_FLASH (1 << 00) + + +#define SCTRL_BIAS (SCTRL_BASE + 76 * 4) +#define BIAS_CAL_OUT_POSI (16) +#define BIAS_CAL_OUT_MASK (0x1F) +#define LDO_VAL_MANUAL_POSI (8) +#define LDO_VAL_MANUAL_MASK (0x1F) +#define BIAS_CAL_MANUAL_BIT (1 << 4) +#define BIAS_CAL_TRIGGER_BIT (1 << 0) + + +#define SCTRL_ROSC_CAL (SCTRL_BASE + 77 * 4) +#define ROSC_CAL_MANU_FIN_POSI (22) +#define ROSC_CAL_MANU_FIN_MASK (0x1FF) +#define ROSC_CAL_MANU_CIN_POSI (17) +#define ROSC_CAL_MANU_CIN_MASK (0x1F) +#define ROSC_CAL_MANU_EN_BIT (1 << 16) +#define ROSC_CAL_INTVAL_POSI (4) +#define ROSC_CAL_INTVAL_MASK (0x7) +#define ROSC_CAL_MODE_BIT (1 << 2) +#define ROSC_CAL_TRIG_BIT (1 << 1) +#define ROSC_CAL_EN_BIT (1 << 0) + +#define SCTRL_BLOCK_EN_MUX (SCTRL_BASE + 79 * 4) +#define SCTRL_ROSC_TIMER_H (SCTRL_BASE + 80 * 4) +#define ROSC_TIMER_H_PERIOD_POSI (0) +#define ROSC_TIMER_H_PERIOD_MASK (0xFFFF) + + +#define SCTRL_SW_RETENTION (SCTRL_BASE + 84 * 4) + +#define DCO_CNTI_120M (0x127U) // set DCO out clk with 120M + +__inline static UINT32 sctrl_analog_get(UINT32 address) +{ + while(REG_READ(SCTRL_ANALOG_SPI) & (ANA_SPI_STAET_MASK< +#include + +#pragma import(__use_no_semihosting_swi) + +#define ITM_Port8(n) (*((volatile unsigned char *)(0xE0000000+4*n))) +#define ITM_Port16(n) (*((volatile unsigned short*)(0xE0000000+4*n))) +#define ITM_Port32(n) (*((volatile unsigned long *)(0xE0000000+4*n))) + +#define DEMCR (*((volatile unsigned long *)(0xE000EDFC))) +#define TRCENA 0x01000000 + +/*---------------------------------------------------------------------------*/ +struct __FILE +{ + int handle; /* Add whatever you need here */ +}; +FILE __stdout; +FILE __stdin; + +/*---------------------------------------------------------------------------*/ +int sendchar(int ch) +{ + if (DEMCR & TRCENA) + { + while (ITM_Port32(0) == 0); + + ITM_Port8(0) = ch; + } + + return(ch); +} + +/*---------------------------------------------------------------------------*/ +int fputc(int ch, FILE *f) +{ + return (sendchar(ch)); +} + +/*---------------------------------------------------------------------------*/ +int fgetc(FILE *f) +{ + return (-1); +} + +/*---------------------------------------------------------------------------*/ +int ferror(FILE *f) +{ + /* Your implementation of ferror */ + return EOF; +} + +/*---------------------------------------------------------------------------*/ +void _ttywrch(int ch) +{ + sendchar(ch); +} + +/*---------------------------------------------------------------------------*/ +void _sys_exit(int return_code) +{ +label: + goto label; /* endless loop */ +} +#endif // KEIL_SIMULATOR + +// eof + diff --git a/beken_os/beken378/driver/uart/printf.c b/beken_os/beken378/driver/uart/printf.c new file mode 100755 index 0000000..624d890 --- /dev/null +++ b/beken_os/beken378/driver/uart/printf.c @@ -0,0 +1,1262 @@ +/* + * Copyright (c) 1995 Patrick Powell. + * + * This code is based on code written by Patrick Powell . + * It may be used for any purpose as long as this notice remains intact on all + * source code distributions. + */ + +/* + * Copyright (c) 2008 Holger Weiss. + * + * This version of the code is maintained by Holger Weiss . + * My changes to the code may freely be used, modified and/or redistributed for + * any purpose. It would be nice if additions and fixes to this file (including + * trivial code cleanups) would be sent back in order to let me include them in + * the version available at . + * However, this is not a requirement for using or redistributing (possibly + * modified) versions of this file, nor is leaving this notice intact mandatory. + */ + +#include +#include /* For *_MAX. */ +#include /* For intmax_t (if not defined in ). */ +#include /* For ptrdiff_t. */ +#include /* For intmax_t. */ +#include /* For pow(3), NAN, and INFINITY. */ +#include /* For strcmp(3). */ +#include "mem_pub.h" +#include "uart_pub.h" + +#define VA_START(ap, last) va_start(ap, last) +#define VA_SHIFT(ap, value, type) /* No-op for ANSI C. */ + +/* Support for unsigned long long int. We may also need ULLONG_MAX. */ +#ifndef ULONG_MAX /* We may need ULONG_MAX as a fallback. */ +#ifdef UINT_MAX +#define ULONG_MAX UINT_MAX +#else +#define ULONG_MAX INT_MAX +#endif /* defined(UINT_MAX) */ +#endif /* !defined(ULONG_MAX) */ +#ifdef ULLONG +#undef ULLONG +#endif /* defined(ULLONG) */ +#if HAVE_UNSIGNED_LONG_LONG_INT +#define ULLONG unsigned long long int +#ifndef ULLONG_MAX +#define ULLONG_MAX ULONG_MAX +#endif /* !defined(ULLONG_MAX) */ +#else +#define ULLONG unsigned long int +#ifdef ULLONG_MAX +#undef ULLONG_MAX +#endif /* defined(ULLONG_MAX) */ +#define ULLONG_MAX ULONG_MAX +#endif /* HAVE_LONG_LONG_INT */ + +/* Support for uintmax_t. We also need UINTMAX_MAX. */ +#ifdef UINTMAX_T +#undef UINTMAX_T +#endif /* defined(UINTMAX_T) */ +#if HAVE_UINTMAX_T || defined(uintmax_t) +#define UINTMAX_T uintmax_t +#ifndef UINTMAX_MAX +#define UINTMAX_MAX ULLONG_MAX +#endif /* !defined(UINTMAX_MAX) */ +#else +#define UINTMAX_T ULLONG +#ifdef UINTMAX_MAX +#undef UINTMAX_MAX +#endif /* defined(UINTMAX_MAX) */ +#define UINTMAX_MAX ULLONG_MAX +#endif /* HAVE_UINTMAX_T || defined(uintmax_t) */ + +/* Support for long double. */ +#ifndef LDOUBLE +#if HAVE_LONG_DOUBLE +#define LDOUBLE long double +#else +#define LDOUBLE double +#endif /* HAVE_LONG_DOUBLE */ +#endif /* !defined(LDOUBLE) */ + +/* Support for long long int. */ +#ifndef LLONG +#if HAVE_LONG_LONG_INT +#define LLONG long long int +#else +#define LLONG long int +#endif /* HAVE_LONG_LONG_INT */ +#endif /* !defined(LLONG) */ + +/* Support for intmax_t. */ +#ifndef INTMAX_T +#if HAVE_INTMAX_T || defined(intmax_t) +#define INTMAX_T intmax_t +#else +#define INTMAX_T LLONG +#endif /* HAVE_INTMAX_T || defined(intmax_t) */ +#endif /* !defined(INTMAX_T) */ + +/* Support for uintptr_t. */ +#ifndef UINTPTR_T +#if HAVE_UINTPTR_T || defined(uintptr_t) +#define UINTPTR_T uintptr_t +#else +#define UINTPTR_T unsigned long int +#endif /* HAVE_UINTPTR_T || defined(uintptr_t) */ +#endif /* !defined(UINTPTR_T) */ + +/* Support for ptrdiff_t. */ +#ifndef PTRDIFF_T +#if HAVE_PTRDIFF_T || defined(ptrdiff_t) +#define PTRDIFF_T ptrdiff_t +#else +#define PTRDIFF_T long int +#endif /* HAVE_PTRDIFF_T || defined(ptrdiff_t) */ +#endif /* !defined(PTRDIFF_T) */ + +/* + * We need an unsigned integer type corresponding to ptrdiff_t (cf. C99: + * 7.19.6.1, 7). However, we'll simply use PTRDIFF_T and convert it to an + * unsigned type if necessary. This should work just fine in practice. + */ +#ifndef UPTRDIFF_T +#define UPTRDIFF_T PTRDIFF_T +#endif /* !defined(UPTRDIFF_T) */ + +/* + * We need a signed integer type corresponding to size_t (cf. C99: 7.19.6.1, 7). + * However, we'll simply use size_t and convert it to a signed type if + * necessary. This should work just fine in practice. + */ +#ifndef SSIZE_T +#define SSIZE_T size_t +#endif /* !defined(SSIZE_T) */ + +/* + * Buffer size to hold the octal string representation of UINT128_MAX without + * nul-termination ("3777777777777777777777777777777777777777777"). + */ +#ifdef MAX_CONVERT_LENGTH +#undef MAX_CONVERT_LENGTH +#endif /* defined(MAX_CONVERT_LENGTH) */ +#define MAX_CONVERT_LENGTH 43 + +/* Format read states. */ +#define PRINT_S_DEFAULT 0 +#define PRINT_S_FLAGS 1 +#define PRINT_S_WIDTH 2 +#define PRINT_S_DOT 3 +#define PRINT_S_PRECISION 4 +#define PRINT_S_MOD 5 +#define PRINT_S_CONV 6 + +/* Format flags. */ +#define PRINT_F_MINUS (1 << 0) +#define PRINT_F_PLUS (1 << 1) +#define PRINT_F_SPACE (1 << 2) +#define PRINT_F_NUM (1 << 3) +#define PRINT_F_ZERO (1 << 4) +#define PRINT_F_QUOTE (1 << 5) +#define PRINT_F_UP (1 << 6) +#define PRINT_F_UNSIGNED (1 << 7) +#define PRINT_F_TYPE_G (1 << 8) +#define PRINT_F_TYPE_E (1 << 9) + +/* Conversion flags. */ +#define PRINT_C_CHAR 1 +#define PRINT_C_SHORT 2 +#define PRINT_C_LONG 3 +#define PRINT_C_LLONG 4 +#define PRINT_C_LDOUBLE 5 +#define PRINT_C_SIZE 6 +#define PRINT_C_PTRDIFF 7 +#define PRINT_C_INTMAX 8 + +#ifndef MAX +#define MAX(x, y) ((x >= y) ? x : y) +#endif /* !defined(MAX) */ +#ifndef CHARTOINT +#define CHARTOINT(ch) (ch - '0') +#endif /* !defined(CHARTOINT) */ +#ifndef ISDIGIT +#define ISDIGIT(ch) ('0' <= (unsigned char)ch && (unsigned char)ch <= '9') +#endif /* !defined(ISDIGIT) */ +#ifndef ISNAN +#define ISNAN(x) (x != x) +#endif /* !defined(ISNAN) */ +#ifndef ISINF +#define ISINF(x) (x != 0.0 && x + x == x) +#endif /* !defined(ISINF) */ + +#ifdef OUTCHAR +#undef OUTCHAR +#endif /* defined(OUTCHAR) */ +#define OUTCHAR(str, len, size, ch) \ +do { \ + if (len + 1 < size) \ + str[len] = ch; \ + (len)++; \ +} while (/* CONSTCOND */ 0) + +static void fmtstr(char *, size_t *, size_t, const char *, int, int, int); +static void fmtint(char *, size_t *, size_t, INTMAX_T, int, int, int, int); +static void fmtflt(char *, size_t *, size_t, LDOUBLE, int, int, int, int *); +static void printsep(char *, size_t *, size_t); +static int getnumsep(int); +static int getexponent(LDOUBLE); +static int convert(UINTMAX_T, char *, size_t, int, int); +static UINTMAX_T cast(LDOUBLE); +static UINTMAX_T myround(LDOUBLE); +static LDOUBLE mypow10(int); +static void fmtmac(char *buf, size_t *len, size_t size, const unsigned char *mac, int caps); +static void fmtip(char *buf, size_t *len, size_t size, unsigned int value); + +int __wrap_vsnprintf(char *str, size_t size, const char *format, va_list args) +{ + LDOUBLE fvalue; + INTMAX_T value; + unsigned char cvalue; + const char *strvalue; + INTMAX_T *intmaxptr; + PTRDIFF_T *ptrdiffptr; + SSIZE_T *sizeptr; + LLONG *llongptr; + long int *longptr; + int *intptr; + short int *shortptr; + signed char *charptr; + size_t len = 0; + int overflow = 0; + int base = 0; + int cflags = 0; + int flags = 0; + int width = 0; + int precision = -1; + int state = PRINT_S_DEFAULT; + char ch = *format++; + + /* + * C99 says: "If `n' is zero, nothing is written, and `s' may be a null + * pointer." (7.19.6.5, 2) We're forgiving and allow a NULL pointer + * even if a size larger than zero was specified. At least NetBSD's + * snprintf(3) does the same, as well as other versions of this file. + * (Though some of these versions will write to a non-NULL buffer even + * if a size of zero was specified, which violates the standard.) + */ + if (str == NULL && size != 0) + size = 0; + + while (ch != '\0') { + switch (state) { + case PRINT_S_DEFAULT: + if (ch == '%') + state = PRINT_S_FLAGS; + else + OUTCHAR(str, len, size, ch); + ch = *format++; + break; + case PRINT_S_FLAGS: + switch (ch) { + case '-': + flags |= PRINT_F_MINUS; + ch = *format++; + break; + case '+': + flags |= PRINT_F_PLUS; + ch = *format++; + break; + case ' ': + flags |= PRINT_F_SPACE; + ch = *format++; + break; + case '#': + flags |= PRINT_F_NUM; + ch = *format++; + break; + case '0': + flags |= PRINT_F_ZERO; + ch = *format++; + break; + case '\'': /* SUSv2 flag (not in C99). */ + flags |= PRINT_F_QUOTE; + ch = *format++; + break; + default: + state = PRINT_S_WIDTH; + break; + } + break; + case PRINT_S_WIDTH: + if (ISDIGIT(ch)) { + ch = CHARTOINT(ch); + if (width > (INT_MAX - ch) / 10) { + overflow = 1; + goto out; + } + width = 10 * width + ch; + ch = *format++; + } else if (ch == '*') { + /* + * C99 says: "A negative field width argument is + * taken as a `-' flag followed by a positive + * field width." (7.19.6.1, 5) + */ + if ((width = va_arg(args, int)) < 0) { + flags |= PRINT_F_MINUS; + width = -width; + } + ch = *format++; + state = PRINT_S_DOT; + } else + state = PRINT_S_DOT; + break; + case PRINT_S_DOT: + if (ch == '.') { + state = PRINT_S_PRECISION; + ch = *format++; + } else + state = PRINT_S_MOD; + break; + case PRINT_S_PRECISION: + if (precision == -1) + precision = 0; + if (ISDIGIT(ch)) { + ch = CHARTOINT(ch); + if (precision > (INT_MAX - ch) / 10) { + overflow = 1; + goto out; + } + precision = 10 * precision + ch; + ch = *format++; + } else if (ch == '*') { + /* + * C99 says: "A negative precision argument is + * taken as if the precision were omitted." + * (7.19.6.1, 5) + */ + if ((precision = va_arg(args, int)) < 0) + precision = -1; + ch = *format++; + state = PRINT_S_MOD; + } else + state = PRINT_S_MOD; + break; + case PRINT_S_MOD: + switch (ch) { + case 'h': + ch = *format++; + if (ch == 'h') { /* It's a char. */ + ch = *format++; + cflags = PRINT_C_CHAR; + } else + cflags = PRINT_C_SHORT; + break; + case 'l': + ch = *format++; + if (ch == 'l') { /* It's a long long. */ + ch = *format++; + cflags = PRINT_C_LLONG; + } else + cflags = PRINT_C_LONG; + break; + case 'L': + cflags = PRINT_C_LDOUBLE; + ch = *format++; + break; + case 'j': + cflags = PRINT_C_INTMAX; + ch = *format++; + break; + case 't': + cflags = PRINT_C_PTRDIFF; + ch = *format++; + break; + case 'z': + cflags = PRINT_C_SIZE; + ch = *format++; + break; + } + state = PRINT_S_CONV; + break; + case PRINT_S_CONV: + switch (ch) { + case 'd': + /* FALLTHROUGH */ + case 'i': + switch (cflags) { + case PRINT_C_CHAR: + value = (signed char)va_arg(args, int); + break; + case PRINT_C_SHORT: + value = (short int)va_arg(args, int); + break; + case PRINT_C_LONG: + value = va_arg(args, long int); + break; + case PRINT_C_LLONG: + value = va_arg(args, LLONG); + break; + case PRINT_C_SIZE: + value = va_arg(args, SSIZE_T); + break; + case PRINT_C_INTMAX: + value = va_arg(args, INTMAX_T); + break; + case PRINT_C_PTRDIFF: + value = va_arg(args, PTRDIFF_T); + break; + default: + value = va_arg(args, int); + break; + } + fmtint(str, &len, size, value, 10, width, + precision, flags); + break; + case 'X': + flags |= PRINT_F_UP; + /* FALLTHROUGH */ + case 'x': + base = 16; + /* FALLTHROUGH */ + case 'o': + if (base == 0) + base = 8; + /* FALLTHROUGH */ + case 'u': + if (base == 0) + base = 10; + flags |= PRINT_F_UNSIGNED; + switch (cflags) { + case PRINT_C_CHAR: + value = (unsigned char)va_arg(args, + unsigned int); + break; + case PRINT_C_SHORT: + value = (unsigned short int)va_arg(args, + unsigned int); + break; + case PRINT_C_LONG: + value = va_arg(args, unsigned long int); + break; + case PRINT_C_LLONG: + value = va_arg(args, ULLONG); + break; + case PRINT_C_SIZE: + value = va_arg(args, size_t); + break; + case PRINT_C_INTMAX: + value = va_arg(args, UINTMAX_T); + break; + case PRINT_C_PTRDIFF: + value = va_arg(args, UPTRDIFF_T); + break; + default: + value = va_arg(args, unsigned int); + break; + } + fmtint(str, &len, size, (UINTMAX_T)value, base, width, + precision, flags); + break; + case 'A': + /* Not yet supported, we'll use "%F". */ + /* FALLTHROUGH */ + case 'F': + flags |= PRINT_F_UP; + case 'a': + /* Not yet supported, we'll use "%f". */ + /* FALLTHROUGH */ + case 'f': + if (cflags == PRINT_C_LDOUBLE) + fvalue = va_arg(args, LDOUBLE); + else + fvalue = va_arg(args, double); + fmtflt(str, &len, size, fvalue, width, + precision, flags, &overflow); + if (overflow) + goto out; + break; + case 'E': + flags |= PRINT_F_UP; + /* FALLTHROUGH */ + case 'e': + flags |= PRINT_F_TYPE_E; + if (cflags == PRINT_C_LDOUBLE) + fvalue = va_arg(args, LDOUBLE); + else + fvalue = va_arg(args, double); + fmtflt(str, &len, size, fvalue, width, + precision, flags, &overflow); + if (overflow) + goto out; + break; + case 'G': + flags |= PRINT_F_UP; + /* FALLTHROUGH */ + case 'g': + flags |= PRINT_F_TYPE_G; + if (cflags == PRINT_C_LDOUBLE) + fvalue = va_arg(args, LDOUBLE); + else + fvalue = va_arg(args, double); + /* + * If the precision is zero, it is treated as + * one (cf. C99: 7.19.6.1, 8). + */ + if (precision == 0) + precision = 1; + fmtflt(str, &len, size, fvalue, width, + precision, flags, &overflow); + if (overflow) + goto out; + break; + case 'c': + cvalue = va_arg(args, int); + OUTCHAR(str, len, size, cvalue); + break; + case 's': + strvalue = va_arg(args, char *); + fmtstr(str, &len, size, strvalue, width, + precision, flags); + break; + case 'p': + /* + * C99 says: "The value of the pointer is + * converted to a sequence of printing + * characters, in an implementation-defined + * manner." (C99: 7.19.6.1, 8) + */ + if (*format == 'm' || *format == 'M') { + ///char mac_lower[17]; + unsigned char *macstr; + if (*format == 'M') + flags |= PRINT_F_UP; + format++; + if ((macstr = va_arg(args, unsigned char *)) == NULL) + macstr = (unsigned char *)"\x00\x00\x00\x00\x00\x00"; + fmtmac(str, &len, size, macstr, flags & PRINT_F_UP); + + break; + } else if (*format == 'i' || *format == 'I') { + format++; + value = va_arg(args, unsigned int); + fmtip(str, &len, size, (unsigned int)value); + break; + } else { + if ((strvalue = va_arg(args, void *)) == NULL) { + /* + * We use the glibc format. BSD prints + * "0x0", SysV "0". + */ + fmtstr(str, &len, size, "(nil)", width, + -1, flags); + } else { + /* + * We use the BSD/glibc format. SysV + * omits the "0x" prefix (which we emit + * using the PRINT_F_NUM flag). + */ + flags |= PRINT_F_NUM; + flags |= PRINT_F_UNSIGNED; + fmtint(str, &len, size, + (UINTPTR_T)strvalue, 16, width, + precision, flags); + } + } + break; + case 'n': + switch (cflags) { + case PRINT_C_CHAR: + charptr = va_arg(args, signed char *); + *charptr = len; + break; + case PRINT_C_SHORT: + shortptr = va_arg(args, short int *); + *shortptr = len; + break; + case PRINT_C_LONG: + longptr = va_arg(args, long int *); + *longptr = len; + break; + case PRINT_C_LLONG: + llongptr = va_arg(args, LLONG *); + *llongptr = len; + break; + case PRINT_C_SIZE: + /* + * C99 says that with the "z" length + * modifier, "a following `n' conversion + * specifier applies to a pointer to a + * signed integer type corresponding to + * size_t argument." (7.19.6.1, 7) + */ + sizeptr = va_arg(args, SSIZE_T *); + *sizeptr = len; + break; + case PRINT_C_INTMAX: + intmaxptr = va_arg(args, INTMAX_T *); + *intmaxptr = len; + break; + case PRINT_C_PTRDIFF: + ptrdiffptr = va_arg(args, PTRDIFF_T *); + *ptrdiffptr = len; + break; + default: + intptr = va_arg(args, int *); + *intptr = len; + break; + } + break; + case '%': /* Print a "%" character verbatim. */ + OUTCHAR(str, len, size, ch); + break; + default: /* Skip other characters. */ + break; + } + ch = *format++; + state = PRINT_S_DEFAULT; + base = cflags = flags = width = 0; + precision = -1; + break; + } + } +out: + if (len < size) + str[len] = '\0'; + else if (size > 0) + str[size - 1] = '\0'; + + if (overflow || len >= INT_MAX) { + //errno = overflow ? EOVERFLOW : ERANGE; + return -1; + } + return (int)len; +} + +static void fmtstr(char *str, size_t *len, size_t size, const char *value, int width, + int precision, int flags) +{ + int padlen, strln; /* Amount to pad. */ + int noprecision = (precision == -1); + + if (value == NULL) /* We're forgiving. */ + value = "(null)"; + + /* If a precision was specified, don't read the string past it. */ + for (strln = 0; value[strln] != '\0' && + (noprecision || strln < precision); strln++) + continue; + + if ((padlen = width - strln) < 0) + padlen = 0; + if (flags & PRINT_F_MINUS) /* Left justify. */ + padlen = -padlen; + + while (padlen > 0) { /* Leading spaces. */ + OUTCHAR(str, *len, size, ' '); + padlen--; + } + while (*value != '\0' && (noprecision || precision-- > 0)) { + OUTCHAR(str, *len, size, *value); + value++; + } + while (padlen < 0) { /* Trailing spaces. */ + OUTCHAR(str, *len, size, ' '); + padlen++; + } +} + +static void fmtint(char *str, size_t *len, size_t size, INTMAX_T value, int base, int width, + int precision, int flags) +{ + UINTMAX_T uvalue; + char iconvert[MAX_CONVERT_LENGTH]; + char sign = 0; + char hexprefix = 0; + int spadlen = 0; /* Amount to space pad. */ + int zpadlen = 0; /* Amount to zero pad. */ + int pos; + int separators = (flags & PRINT_F_QUOTE); + int noprecision = (precision == -1); + + if (flags & PRINT_F_UNSIGNED) + uvalue = value; + else { + uvalue = (value >= 0) ? value : -value; + if (value < 0) + sign = '-'; + else if (flags & PRINT_F_PLUS) /* Do a sign. */ + sign = '+'; + else if (flags & PRINT_F_SPACE) + sign = ' '; + } + + pos = convert(uvalue, iconvert, sizeof(iconvert), base, + flags & PRINT_F_UP); + + if (flags & PRINT_F_NUM && uvalue != 0) { + /* + * C99 says: "The result is converted to an `alternative form'. + * For `o' conversion, it increases the precision, if and only + * if necessary, to force the first digit of the result to be a + * zero (if the value and precision are both 0, a single 0 is + * printed). For `x' (or `X') conversion, a nonzero result has + * `0x' (or `0X') prefixed to it." (7.19.6.1, 6) + */ + switch (base) { + case 8: + if (precision <= pos) + precision = pos + 1; + break; + case 16: + hexprefix = (flags & PRINT_F_UP) ? 'X' : 'x'; + break; + } + } + + if (separators) /* Get the number of group separators we'll print. */ + separators = getnumsep(pos); + + zpadlen = precision - pos - separators; + spadlen = width /* Minimum field width. */ + - separators /* Number of separators. */ + - MAX(precision, pos) /* Number of integer digits. */ + - ((sign != 0) ? 1 : 0) /* Will we print a sign? */ + - ((hexprefix != 0) ? 2 : 0); /* Will we print a prefix? */ + + if (zpadlen < 0) + zpadlen = 0; + if (spadlen < 0) + spadlen = 0; + + /* + * C99 says: "If the `0' and `-' flags both appear, the `0' flag is + * ignored. For `d', `i', `o', `u', `x', and `X' conversions, if a + * precision is specified, the `0' flag is ignored." (7.19.6.1, 6) + */ + if (flags & PRINT_F_MINUS) /* Left justify. */ + spadlen = -spadlen; + else if (flags & PRINT_F_ZERO && noprecision) { + zpadlen += spadlen; + spadlen = 0; + } + while (spadlen > 0) { /* Leading spaces. */ + OUTCHAR(str, *len, size, ' '); + spadlen--; + } + if (sign != 0) /* Sign. */ + OUTCHAR(str, *len, size, sign); + if (hexprefix != 0) { /* A "0x" or "0X" prefix. */ + OUTCHAR(str, *len, size, '0'); + OUTCHAR(str, *len, size, hexprefix); + } + while (zpadlen > 0) { /* Leading zeros. */ + OUTCHAR(str, *len, size, '0'); + zpadlen--; + } + while (pos > 0) { /* The actual digits. */ + pos--; + OUTCHAR(str, *len, size, iconvert[pos]); + if (separators > 0 && pos > 0 && pos % 3 == 0) + printsep(str, len, size); + } + while (spadlen < 0) { /* Trailing spaces. */ + OUTCHAR(str, *len, size, ' '); + spadlen++; + } +} + +static void fmtflt(char *str, size_t *len, size_t size, LDOUBLE fvalue, int width, + int precision, int flags, int *overflow) +{ + LDOUBLE ufvalue; + UINTMAX_T intpart; + UINTMAX_T fracpart; + UINTMAX_T mask; + const char *infnan = NULL; + char iconvert[MAX_CONVERT_LENGTH]; + char fconvert[MAX_CONVERT_LENGTH]; + char econvert[4]; /* "e-12" (without nul-termination). */ + char esign = 0; + char sign = 0; + int leadfraczeros = 0; + int exponent = 0; + int emitpoint = 0; + int omitzeros = 0; + int omitcount = 0; + int padlen = 0; + int epos = 0; + int fpos = 0; + int ipos = 0; + int separators = (flags & PRINT_F_QUOTE); + int estyle = (flags & PRINT_F_TYPE_E); + + /* + * AIX' man page says the default is 0, but C99 and at least Solaris' + * and NetBSD's man pages say the default is 6, and sprintf(3) on AIX + * defaults to 6. + */ + if (precision == -1) + precision = 6; + + if (fvalue < 0.0) + sign = '-'; + else if (flags & PRINT_F_PLUS) /* Do a sign. */ + sign = '+'; + else if (flags & PRINT_F_SPACE) + sign = ' '; + + if (ISNAN(fvalue)) + infnan = (flags & PRINT_F_UP) ? "NAN" : "nan"; + else if (ISINF(fvalue)) + infnan = (flags & PRINT_F_UP) ? "INF" : "inf"; + + if (infnan != NULL) { + if (sign != 0) + iconvert[ipos++] = sign; + while (*infnan != '\0') + iconvert[ipos++] = *infnan++; + fmtstr(str, len, size, iconvert, width, ipos, flags); + return; + } + + /* "%e" (or "%E") or "%g" (or "%G") conversion. */ + if (flags & PRINT_F_TYPE_E || flags & PRINT_F_TYPE_G) { + if (flags & PRINT_F_TYPE_G) { + /* + * For "%g" (and "%G") conversions, the precision + * specifies the number of significant digits, which + * includes the digits in the integer part. The + * conversion will or will not be using "e-style" (like + * "%e" or "%E" conversions) depending on the precision + * and on the exponent. However, the exponent can be + * affected by rounding the converted value, so we'll + * leave this decision for later. Until then, we'll + * assume that we're going to do an "e-style" conversion + * (in order to get the exponent calculated). For + * "e-style", the precision must be decremented by one. + */ + precision--; + /* + * For "%g" (and "%G") conversions, trailing zeros are + * removed from the fractional portion of the result + * unless the "#" flag was specified. + */ + if (!(flags & PRINT_F_NUM)) + omitzeros = 1; + } + exponent = getexponent(fvalue); + estyle = 1; + } + +again: + /* + * Sorry, we only support 9, 19, or 38 digits (that is, the number of + * digits of the 32-bit, the 64-bit, or the 128-bit UINTMAX_MAX value + * minus one) past the decimal point due to our conversion method. + */ + switch (sizeof(UINTMAX_T)) { + case 16: + if (precision > 38) + precision = 38; + break; + case 8: + if (precision > 19) + precision = 19; + break; + default: + if (precision > 9) + precision = 9; + break; + } + + ufvalue = (fvalue >= 0.0) ? fvalue : -fvalue; + if (estyle) /* We want exactly one integer digit. */ + ufvalue /= mypow10(exponent); + + if ((intpart = cast(ufvalue)) == UINTMAX_MAX) { + *overflow = 1; + return; + } + + /* + * Factor of ten with the number of digits needed for the fractional + * part. For example, if the precision is 3, the mask will be 1000. + */ + mask = mypow10(precision); + /* + * We "cheat" by converting the fractional part to integer by + * multiplying by a factor of ten. + */ + if ((fracpart = myround(mask * (ufvalue - intpart))) >= mask) { + /* + * For example, ufvalue = 2.99962, intpart = 2, and mask = 1000 + * (because precision = 3). Now, myround(1000 * 0.99962) will + * return 1000. So, the integer part must be incremented by one + * and the fractional part must be set to zero. + */ + intpart++; + fracpart = 0; + if (estyle && intpart == 10) { + /* + * The value was rounded up to ten, but we only want one + * integer digit if using "e-style". So, the integer + * part must be set to one and the exponent must be + * incremented by one. + */ + intpart = 1; + exponent++; + } + } + + /* + * Now that we know the real exponent, we can check whether or not to + * use "e-style" for "%g" (and "%G") conversions. If we don't need + * "e-style", the precision must be adjusted and the integer and + * fractional parts must be recalculated from the original value. + * + * C99 says: "Let P equal the precision if nonzero, 6 if the precision + * is omitted, or 1 if the precision is zero. Then, if a conversion + * with style `E' would have an exponent of X: + * + * - if P > X >= -4, the conversion is with style `f' (or `F') and + * precision P - (X + 1). + * + * - otherwise, the conversion is with style `e' (or `E') and precision + * P - 1." (7.19.6.1, 8) + * + * Note that we had decremented the precision by one. + */ + if (flags & PRINT_F_TYPE_G && estyle && + precision + 1 > exponent && exponent >= -4) { + precision -= exponent; + estyle = 0; + goto again; + } + + if (estyle) { + if (exponent < 0) { + exponent = -exponent; + esign = '-'; + } else + esign = '+'; + + /* + * Convert the exponent. The sizeof(econvert) is 4. So, the + * econvert buffer can hold e.g. "e+99" and "e-99". We don't + * support an exponent which contains more than two digits. + * Therefore, the following stores are safe. + */ + epos = convert(exponent, econvert, 2, 10, 0); + /* + * C99 says: "The exponent always contains at least two digits, + * and only as many more digits as necessary to represent the + * exponent." (7.19.6.1, 8) + */ + if (epos == 1) + econvert[epos++] = '0'; + econvert[epos++] = esign; + econvert[epos++] = (flags & PRINT_F_UP) ? 'E' : 'e'; + } + + /* Convert the integer part and the fractional part. */ + ipos = convert(intpart, iconvert, sizeof(iconvert), 10, 0); + if (fracpart != 0) /* convert() would return 1 if fracpart == 0. */ + fpos = convert(fracpart, fconvert, sizeof(fconvert), 10, 0); + + leadfraczeros = precision - fpos; + + if (omitzeros) { + if (fpos > 0) /* Omit trailing fractional part zeros. */ + while (omitcount < fpos && fconvert[omitcount] == '0') + omitcount++; + else { /* The fractional part is zero, omit it completely. */ + omitcount = precision; + leadfraczeros = 0; + } + precision -= omitcount; + } + + /* + * Print a decimal point if either the fractional part is non-zero + * and/or the "#" flag was specified. + */ + if (precision > 0 || flags & PRINT_F_NUM) + emitpoint = 1; + if (separators) /* Get the number of group separators we'll print. */ + separators = getnumsep(ipos); + + padlen = width /* Minimum field width. */ + - ipos /* Number of integer digits. */ + - epos /* Number of exponent characters. */ + - precision /* Number of fractional digits. */ + - separators /* Number of group separators. */ + - (emitpoint ? 1 : 0) /* Will we print a decimal point? */ + - ((sign != 0) ? 1 : 0); /* Will we print a sign character? */ + + if (padlen < 0) + padlen = 0; + + /* + * C99 says: "If the `0' and `-' flags both appear, the `0' flag is + * ignored." (7.19.6.1, 6) + */ + if (flags & PRINT_F_MINUS) /* Left justifty. */ + padlen = -padlen; + else if (flags & PRINT_F_ZERO && padlen > 0) { + if (sign != 0) { /* Sign. */ + OUTCHAR(str, *len, size, sign); + sign = 0; + } + while (padlen > 0) { /* Leading zeros. */ + OUTCHAR(str, *len, size, '0'); + padlen--; + } + } + while (padlen > 0) { /* Leading spaces. */ + OUTCHAR(str, *len, size, ' '); + padlen--; + } + if (sign != 0) /* Sign. */ + OUTCHAR(str, *len, size, sign); + while (ipos > 0) { /* Integer part. */ + ipos--; + OUTCHAR(str, *len, size, iconvert[ipos]); + if (separators > 0 && ipos > 0 && ipos % 3 == 0) + printsep(str, len, size); + } + if (emitpoint) { /* Decimal point. */ + OUTCHAR(str, *len, size, '.'); + } + while (leadfraczeros > 0) { /* Leading fractional part zeros. */ + OUTCHAR(str, *len, size, '0'); + leadfraczeros--; + } + while (fpos > omitcount) { /* The remaining fractional part. */ + fpos--; + OUTCHAR(str, *len, size, fconvert[fpos]); + } + while (epos > 0) { /* Exponent. */ + epos--; + OUTCHAR(str, *len, size, econvert[epos]); + } + while (padlen < 0) { /* Trailing spaces. */ + OUTCHAR(str, *len, size, ' '); + padlen++; + } +} + +static void printsep(char *str, size_t *len, size_t size) +{ + OUTCHAR(str, *len, size, ','); +} + +static int getnumsep(int digits) +{ + int separators = (digits - ((digits % 3 == 0) ? 1 : 0)) / 3; + + return separators; +} + +static int getexponent(LDOUBLE value) +{ + LDOUBLE tmp = (value >= 0.0) ? value : -value; + int exponent = 0; + + /* + * We check for 99 > exponent > -99 in order to work around possible + * endless loops which could happen (at least) in the second loop (at + * least) if we're called with an infinite value. However, we checked + * for infinity before calling this function using our ISINF() macro, so + * this might be somewhat paranoid. + */ + while (tmp < 1.0 && tmp > 0.0 && --exponent > -99) + tmp *= 10; + while (tmp >= 10.0 && ++exponent < 99) + tmp /= 10; + + return exponent; +} + +static int convert(UINTMAX_T value, char *buf, size_t size, int base, int caps) +{ + const char *digits = caps ? "0123456789ABCDEF" : "0123456789abcdef"; + size_t pos = 0; + + /* We return an unterminated buffer with the digits in reverse order. */ + do { + buf[pos++] = digits[value % base]; + value /= base; + } while (value != 0 && pos < size); + + return (int)pos; +} + +static int convert_ip(unsigned int value, char *buf, size_t size) +{ + const char *digits = "0123456789"; + int i; + unsigned char c; + size_t pos = 0; + + for (i = 0; i < 4; i++) { + c = (value >> (i*8)) & 0xff; + + /* We return an unterminated buffer with the digits in reverse order. */ + do { + buf[pos++] = digits[c % 10]; + c /= 10; + } while (c != 0 && pos < size); + + if (i != 3 && pos < size) + buf[pos++] = '.'; + } + + return (int)pos; +} + +/* TODO: IPv6 */ +static void fmtip(char *buf, size_t *len, size_t size, unsigned int value) +{ + int pos; + char ip_buf[18]; + + pos = convert_ip(value, ip_buf, sizeof(ip_buf)); + if (pos > 0) pos--; + for (; pos >= 0; pos--) + OUTCHAR(buf, *len, size, ip_buf[pos]); +} + +static void fmtmac(char *buf, size_t *len, size_t size, const unsigned char *mac, int caps) +{ + const char *digits = caps ? "0123456789ABCDEF" : "0123456789abcdef"; +/// size_t pos = 0; + int i; + unsigned char c; + + for (i = 0; i < 6; i++) { + c = mac[i]; + OUTCHAR(buf, *len, size, digits[(c >> 4) & 0xf]); + OUTCHAR(buf, *len, size, digits[c & 0xf]); + if (i != 5) + OUTCHAR(buf, *len, size, ':'); + } +} + +static UINTMAX_T cast(LDOUBLE value) +{ + UINTMAX_T result; + + /* + * We check for ">=" and not for ">" because if UINTMAX_MAX cannot be + * represented exactly as an LDOUBLE value (but is less than LDBL_MAX), + * it may be increased to the nearest higher representable value for the + * comparison (cf. C99: 6.3.1.4, 2). It might then equal the LDOUBLE + * value although converting the latter to UINTMAX_T would overflow. + */ + if (value >= UINTMAX_MAX) + return UINTMAX_MAX; + + result = value; + /* + * At least on NetBSD/sparc64 3.0.2 and 4.99.30, casting long double to + * an integer type converts e.g. 1.9 to 2 instead of 1 (which violates + * the standard). Sigh. + */ + return (result <= value) ? result : result - 1; +} + +static UINTMAX_T myround(LDOUBLE value) +{ + UINTMAX_T intpart = cast(value); + + return ((value -= intpart) < 0.5) ? intpart : intpart + 1; +} + +static LDOUBLE mypow10(int exponent) +{ + LDOUBLE result = 1; + + while (exponent > 0) { + result *= 10; + exponent--; + } + while (exponent < 0) { + result /= 10; + exponent++; + } + return result; +} + +int __wrap_vasprintf(char **ret, const char *format, va_list ap) +{ + size_t size; + int len; + va_list aq; + + va_copy(aq, ap); + len = __wrap_vsnprintf(NULL, 0, format, aq); + va_end(aq); + + if (len < 0 || (*ret = os_malloc(size = len + 1)) == NULL) + return -1; + + return __wrap_vsnprintf(*ret, size, format, ap); +} + +int __wrap_snprintf(char *str, size_t size, const char *format, ...) +{ + va_list ap; + int len; + + va_start(ap, format); + len = __wrap_vsnprintf(str, size, format, ap); + va_end(ap); + + return len; +} + +int __wrap_asprintf(char **ret, const char *format, ...) +{ + va_list ap; + int len; + + va_start(ap, format); + len = __wrap_vasprintf(ret, format, ap); + va_end(ap); + return len; +} + +int __wrap_sprintf(char *str, const char *format, ...) +{ + va_list ap; + int len; + + va_start(ap, format); + len = __wrap_vsnprintf(str, INT_MAX, format, ap); + va_end(ap); + + return len; +} + +void __wrap_printf(const char *fmt, ...) +{ + va_list ap; + char string[128]; + + va_start(ap, fmt); + __wrap_vsnprintf(string, sizeof(string) - 1, fmt, ap); + string[127] = 0; + bk_send_string(get_printf_port(), string); + va_end(ap); +} + +int __wrap_puts(const char *s) +{ + bk_send_string(get_printf_port(), s); + + return 1; /* non-negative value returned */ +} + diff --git a/beken_os/beken378/driver/uart/uart.h b/beken_os/beken378/driver/uart/uart.h new file mode 100755 index 0000000..ee0d5d1 --- /dev/null +++ b/beken_os/beken378/driver/uart/uart.h @@ -0,0 +1,305 @@ +#ifndef _UART_H_ +#define _UART_H_ + +#include "include.h" +#include "fifo.h" +#include "uart_pub.h" + +//#define UART_DEBUG + +#ifdef UART_DEBUG +#define UART_PRT os_printf +#define UART_WPRT warning_prf +#else +#define UART_PRT os_null_printf +#define UART_WPRT os_null_printf +#endif + +#define UART_INDEX_1 (1) +#define UART_INDEX_2 (2) + +#if (!CFG_SUPPORT_ALIOS) +typedef struct +{ + uint32_t baud_rate; + uart_data_width_t data_width; + uart_parity_t parity; + uart_stop_bits_t stop_bits; + uart_flow_control_t flow_control; + uint8_t flags; /**< if set, UART can wake up MCU from stop mode, reference: @ref UART_WAKEUP_DISABLE and @ref UART_WAKEUP_ENABLE*/ +} uart_config_t; +#endif + +#if (CFG_RUNNING_PLATFORM == FPGA_PLATFORM) +#define UART_SELECT_CFG UART_INDEX_1 +#else +#define UART_SELECT_CFG UART_INDEX_2 +#endif + +#if (UART_SELECT_CFG == UART_INDEX_1) +#define IRQ_UART IRQ_UART1 +#define PRI_IRQ_UART PRI_IRQ_UART1 +#define PWD_UART_CLK_BIT PWD_UART1_CLK_BIT +#define GFUNC_MODE_UART GFUNC_MODE_UART1 +#define IRQ_UART_BIT IRQ_UART1_BIT +#else /* UART_INDEX_2 */ +#define IRQ_UART IRQ_UART2 +#define PRI_IRQ_UART PRI_IRQ_UART2 +#define PWD_UART_CLK_BIT PWD_UART2_CLK_BIT +#define GFUNC_MODE_UART GFUNC_MODE_UART2 +#define IRQ_UART_BIT IRQ_UART2_BIT +#endif + +#define DEBUG_PRT_MAX_CNT (16) + +#if CFG_UART_DEBUG_COMMAND_LINE +#define RX_RB_LENGTH (128) // 64 +#define TX_RB_LENGTH (64) +#else +#define RX_RB_LENGTH (64) +#define TX_RB_LENGTH (64) +#endif + +#define CARRIAGE_RETURN(buf, count) \ + do { \ + buf[count - 1] = '\r'; \ + buf[count] = '\n'; \ + buf[count + 1] = 0; \ + rc += 1; \ + } while (0) + +/* uart parameter config----start*/ +#define UART_BAUDRATE_3250000 3250000 +#define UART_BAUDRATE_2000000 2000000 +#define UART_BAUDRATE_921600 921600 +#define UART_BAUDRATE_460800 460800 +#define UART_BAUDRATE_230400 230400 +#define UART_BAUDRATE_115200 115200 //default +#define UART_BAUDRATE_3000 3250 +#define UART_BAUDRATE_19200 19200 + +#define UART_BAUD_RATE UART_BAUDRATE_115200 + +#define UART_CLOCK_FREQ_10M 10000000 +#define UART_CLOCK_FREQ_48M 48000000 +#define UART_CLOCK_FREQ_24M 24000000 +#define UART_CLOCK_FREQ_26M 26000000 +#define UART_CLOCK_FREQ_52M 52000000 +#define UART_CLOCK_FREQ_120M 120000000 + +#if (CFG_RUNNING_PLATFORM == FPGA_PLATFORM) +#define UART_CLOCK UART_CLOCK_FREQ_24M +#else +#define UART_CLOCK UART_CLOCK_FREQ_26M +#endif // CFG_RUNNING_PLATFORM == FPGA_PLATFORM + +#define TX_FIFO_THRD (0x40) +#define RX_FIFO_THRD (0x30) + +#define DEF_TX_EN 0x1 +#define DEF_RX_EN 0x1 +#define DEF_IRDA_MODE 0x0 // 0:uart mode 1:IRDA MODE +#define DEF_DATA_LEN 0x3 // 0=5bit, 1=6bit, 2=7bit, 3=8bit +#define DEF_PARITY_EN 0x0 // 0=no parity 1: enable parity +#define DEF_PARITY_MODE 0x0 // 0:odd 1: even +#define DEF_STOP_BIT 0x0 // 1bit + +#define FLOW_CTRL_HIGH_CNT (96) +#define FLOW_CTRL_LOW_CNT (32) + +#define DEBUG_TX_FIFO_MAX_COUNT 16 + +/* uart parameter config----end*/ + +typedef struct _uart_ +{ + UINT16 status; + + KFIFO_PTR rx; + + KFIFO_PTR tx; +} UART_S, *UART_PTR; + + +#if (0 == CFG_RELEASE_FIRMWARE) +#define DEAD_WHILE() do{ \ + while(1);\ + }while(0) +#else +#define DEAD_WHILE() do{ \ + os_printf("dead\r\n");\ + }while(0) +#endif + +#if (UART_SELECT_CFG == UART_INDEX_1) +#define UART_BASE_ADDR (0x0802100) +#else +#define UART_BASE_ADDR (0x0802200) +#endif + +#define UART1_BASE_ADDR (0x0802100) +#define UART2_BASE_ADDR (0x0802200) + +#define REG_UART1_CONFIG (UART1_BASE_ADDR + 4 * 0) +#define REG_UART2_CONFIG (UART2_BASE_ADDR + 4 * 0) + +#define UART_TX_ENABLE (1 << 0) +#define UART_RX_ENABLE (1 << 1) +#define UART_IRDA (1 << 2) +#define UART_DATA_LEN_POSI (3) +#define UART_DATA_LEN_MASK (0x03) +#define UART_PAR_EN (1 << 5) +#define UART_PAR_ODD_MODE (1 << 6) +#define UART_STOP_LEN_2 (1 << 7) +#define UART_CLK_DIVID_POSI (8) +#define UART_CLK_DIVID_MASK (0x1FFF) + +#define REG_UART1_FIFO_CONFIG (UART1_BASE_ADDR + 4 * 1) +#define REG_UART2_FIFO_CONFIG (UART2_BASE_ADDR + 4 * 1) +#define TX_FIFO_THRESHOLD_MASK (0xFF) +#define TX_FIFO_THRESHOLD_POSI (0) +#define RX_FIFO_THRESHOLD_MASK (0xFF) +#define RX_FIFO_THRESHOLD_POSI (8) +#define RX_STOP_DETECT_TIME_MASK (0x03) +#define RX_STOP_DETECT_TIME_POSI (16) +#define RX_STOP_DETECT_TIME32 (0) +#define RX_STOP_DETECT_TIME64 (1) +#define RX_STOP_DETECT_TIME128 (2) +#define RX_STOP_DETECT_TIME256 (3) + +#define REG_UART1_FIFO_STATUS (UART1_BASE_ADDR + 4 * 2) +#define REG_UART2_FIFO_STATUS (UART2_BASE_ADDR + 4 * 2) +#define TX_FIFO_COUNT_MASK (0xFF) +#define TX_FIFO_COUNT_POSI (0) +#define RX_FIFO_COUNT_MASK (0xFF) +#define RX_FIFO_COUNT_POSI (8) +#define TX_FIFO_FULL (1 << 16) +#define TX_FIFO_EMPTY (1 << 17) +#define RX_FIFO_FULL (1 << 18) +#define RX_FIFO_EMPTY (1 << 19) +#define FIFO_WR_READY (1 << 20) +#define FIFO_RD_READY (1 << 21) + +#define REG_UART1_FIFO_PORT (UART1_BASE_ADDR + 4 * 3) +#define REG_UART2_FIFO_PORT (UART2_BASE_ADDR + 4 * 3) +#define UART_TX_FIFO_DIN_MASK (0xFF) +#define UART_TX_FIFO_DIN_POSI (0) +#define UART_RX_FIFO_DOUT_MASK (0xFF) +#define UART_RX_FIFO_DOUT_POSI (8) + +#define REG_UART1_INTR_ENABLE (UART1_BASE_ADDR + 4 * 4) +#define REG_UART2_INTR_ENABLE (UART2_BASE_ADDR + 4 * 4) +#define TX_FIFO_NEED_WRITE_EN (1 << 0) +#define RX_FIFO_NEED_READ_EN (1 << 1) +#define RX_FIFO_OVER_FLOW_EN (1 << 2) +#define UART_RX_PARITY_ERR_EN (1 << 3) +#define UART_RX_STOP_ERR_EN (1 << 4) +#define UART_TX_STOP_END_EN (1 << 5) +#define UART_RX_STOP_END_EN (1 << 6) +#define UART_RXD_WAKEUP_EN (1 << 7) + +#define REG_UART1_INTR_STATUS (UART1_BASE_ADDR + 4 * 5) +#define REG_UART2_INTR_STATUS (UART2_BASE_ADDR + 4 * 5) +#define TX_FIFO_NEED_WRITE_STA (1 << 0) +#define RX_FIFO_NEED_READ_STA (1 << 1) +#define RX_FIFO_OVER_FLOW_STA (1 << 2) +#define UART_RX_PARITY_ERR_STA (1 << 3) +#define UART_RX_STOP_ERR_STA (1 << 4) +#define UART_TX_STOP_END_STA (1 << 5) +#define UART_RX_STOP_END_STA (1 << 6) +#define UART_RXD_WAKEUP_STA (1 << 7) + +#define REG_UART1_FLOW_CONFIG (UART1_BASE_ADDR + 4 * 6) +#define REG_UART2_FLOW_CONFIG (UART2_BASE_ADDR + 4 * 6) +#define FLOW_CTRL_LOW_CNT_MASK (0xFF) +#define FLOW_CTRL_LOW_CNT_POSI (0) +#define FLOW_CTRL_HIGH_CNT_MASK (0xFF) +#define FLOW_CTRL_HIGH_CNT_POSI (8) +#define FLOW_CONTROL_EN (1 << 16) +//only valid for uart1 +#define RTS_POLARITY_SEL (1<<17) +#define CTS_POLARITY_SEL (1<<18) + +#define REG_UART1_WAKE_CONFIG (UART1_BASE_ADDR + 4 * 7) +#define REG_UART2_WAKE_CONFIG (UART2_BASE_ADDR + 4 * 7) +#define UART_WAKE_COUNT_MASK (0x3FF) +#define UART_WAKE_COUNT_POSI (0) +#define UART_TXD_WAIT_CNT_MASK (0x3FF) +#define UART_TXD_WAIT_CNT_POSI (10) +#define UART_RXD_WAKE_EN (1 << 20) +#define UART_TXD_WAKE_EN (1 << 21) +#define RXD_NEGEDGE_WAKE_EN (1 << 22) + +#define UART1_TX_WRITE_READY (REG_READ(REG_UART1_FIFO_STATUS) & FIFO_WR_READY) +#define UART2_TX_WRITE_READY (REG_READ(REG_UART2_FIFO_STATUS) & FIFO_WR_READY) + +#define UART_WRITE_BYTE(ch,v) do \ + { \ + v = (v & UART_TX_FIFO_DIN_MASK) \ + << UART_TX_FIFO_DIN_POSI; \ + if(0 == ch) \ + REG_WRITE(REG_UART1_FIFO_PORT, v); \ + else \ + REG_WRITE(REG_UART2_FIFO_PORT, v);\ + }while(0) +#define UART_READ_BYTE(ch,v) do \ + { \ + if(0 == ch) \ + v = (REG_READ(REG_UART1_FIFO_PORT) \ + >> UART_RX_FIFO_DOUT_POSI) \ + & UART_RX_FIFO_DOUT_MASK;\ + else \ + v = (REG_READ(REG_UART2_FIFO_PORT) \ + >> UART_RX_FIFO_DOUT_POSI) \ + & UART_RX_FIFO_DOUT_MASK;\ + }while(0) + +#define UART_READ_BYTE_DISCARD(ch) do \ + { \ + if(0 == ch) \ + REG_READ(REG_UART1_FIFO_PORT);\ + else \ + REG_READ(REG_UART2_FIFO_PORT);\ + }while(0) + + + +#define UART2_TX_FIFO_EMPTY_GET() ((REG_READ(REG_UART2_FIFO_STATUS) & TX_FIFO_EMPTY)>>17) +#define UART1_TX_FIFO_EMPTY_GET() ((REG_READ(REG_UART1_FIFO_STATUS) & TX_FIFO_EMPTY)>>17) + + +/******************************************************************************* +* Function Declarations +*******************************************************************************/ +#if CFG_UART_DEBUG_COMMAND_LINE +extern UINT32 uart_sw_init(UINT8 ch); +extern UINT32 uart_sw_uninit(UINT8 ch); +extern void uart_fifo_flush(UINT8 ch); +extern void uart_hw_uninit(UINT8 ch); +extern void uart_reset(UINT8 ch); + +extern UINT32 uart_write_fifo_frame(UINT8 ch, KFIFO_PTR tx_ptr, UINT32 count); +extern UINT32 uart_read_fifo_frame(UINT8 ch, KFIFO_PTR rx_ptr); + +extern UINT32 uart1_open(UINT32 op_flag); +extern UINT32 uart1_close(void); +extern UINT32 uart1_read(char *user_buf, UINT32 count, UINT32 op_flag); +extern UINT32 uart1_write(char *user_buf, UINT32 count, UINT32 op_flag); +extern UINT32 uart1_ctrl(UINT32 cmd, void *parm); + +extern UINT32 uart2_open(UINT32 op_flag); +extern UINT32 uart2_close(void); +extern UINT32 uart2_read(char *user_buf, UINT32 count, UINT32 op_flag); +extern UINT32 uart2_write(char *user_buf, UINT32 count, UINT32 op_flag); +extern UINT32 uart2_ctrl(UINT32 cmd, void *parm); +#endif + +int uart_read_byte(int uport); +int uart_write_byte(int uport, char c); +int uart_rx_callback_set(int uport, uart_callback callback, void *param); +int uart_tx_fifo_needwr_callback_set(int uport, uart_callback callback, void *param); +int uart_tx_end_callback_set(int uport, uart_callback callback, void *param); +void uart_set_tx_stop_end_int(UINT8 uport, UINT8 set); +void uart_set_tx_fifo_needwr_int(UINT8 uport, UINT8 set); + +#endif // _UART_H_ diff --git a/beken_os/beken378/driver/uart/uart_bk.c b/beken_os/beken378/driver/uart/uart_bk.c new file mode 100755 index 0000000..7cf4f20 --- /dev/null +++ b/beken_os/beken378/driver/uart/uart_bk.c @@ -0,0 +1,1150 @@ +#include "include.h" +#include "arm_arch.h" + +#include "uart_pub.h" +#include "uart.h" + +#include "drv_model_pub.h" +#include "sys_ctrl_pub.h" +#include "mem_pub.h" +#include "icu_pub.h" +#include "gpio_pub.h" +#include "sys_version.h" +#include "ate_app.h" +#include + +#include "mem_pub.h" +#include "intc_pub.h" +#if CFG_USE_STA_PS +#include "power_save_pub.h" +#endif +#include "mcu_ps_pub.h" + +#if CFG_SUPPORT_RTT +#include +#include +#endif + +static struct uart_callback_des uart_receive_callback[2] = {{NULL}, {NULL}}; +static struct uart_callback_des uart_txfifo_needwr_callback[2] = {{NULL}, {NULL}}; +static struct uart_callback_des uart_tx_end_callback[2] = {{NULL}, {NULL}}; + +extern uint32_t get_ate_mode_state(void); + +#ifndef KEIL_SIMULATOR +#if CFG_UART_DEBUG_COMMAND_LINE +UART_S uart[2] = +{ + {0, 0, 0}, + {0, 0, 0} +}; + +static DD_OPERATIONS uart1_op = +{ + uart1_open, + uart1_close, + uart1_read, + uart1_write, + uart1_ctrl +}; + +static DD_OPERATIONS uart2_op = +{ + uart2_open, + uart2_close, + uart2_read, + uart2_write, + uart2_ctrl +}; +#endif + +UINT8 uart_is_tx_fifo_empty(UINT8 uport) +{ + UINT32 param; + + if(UART1_PORT == uport) + param = REG_READ(REG_UART1_FIFO_STATUS); + else + param = REG_READ(REG_UART2_FIFO_STATUS); + + return (param & TX_FIFO_EMPTY) != 0 ? 1 : 0; +} + +UINT8 uart_is_tx_fifo_full(UINT8 uport) +{ + UINT32 param; + + if(UART1_PORT == uport) + param = REG_READ(REG_UART1_FIFO_STATUS); + else + param = REG_READ(REG_UART2_FIFO_STATUS); + + return (param & TX_FIFO_FULL) != 0 ? 1 : 0; +} + +void bk_send_byte(UINT8 uport, UINT8 data) +{ + if(UART1_PORT == uport) + while(!UART1_TX_WRITE_READY); + else + while(!UART2_TX_WRITE_READY); + + UART_WRITE_BYTE(uport, data); +} + +void bk_send_string(UINT8 uport, const char *string) +{ + const char *p = string; + while(*string) + { + if (*string == '\n') { + if (p == string || *(string - 1) != '\r') + bk_send_byte(uport, '\r'); // append '\r' + } + bk_send_byte(uport, *string++); + } +} +static UINT8 pirntf_port = 2; +UINT8 get_printf_port(void) +{ + return pirntf_port; +} +void set_printf_port(UINT8 port) +{ + pirntf_port = port; +} + +/*uart2 as deubg port*/ +char string[256]; +void *print_handle = NULL; + +void bk_printf(const char *fmt, ...) +{ + va_list ap; + bool is_interrupt = false; + BaseType_t state = 0; + + // get os ticks + state = xTaskGetSchedulerState(); + + // if in interrupt handler + if (bk_wlan_get_INT_status() == 1) { + is_interrupt = true; + } + + // sure rtos is running + if (state != taskSCHEDULER_NOT_STARTED) { + if (NULL == print_handle) { + print_handle = xSemaphoreCreateRecursiveMutex(); + } + + if (is_interrupt == false) { + xSemaphoreTakeRecursive(print_handle, portMAX_DELAY); + } + } + + va_start(ap, fmt); + vsnprintf(string, sizeof(string) - 1, fmt, ap); + string[255] = 0; + +#if ATE_APP_FUN + if(get_ate_mode_state()) + { + bk_send_string(UART1_PORT, string); + } + else +#endif + { + if(get_printf_port() == 1) + bk_send_string(UART1_PORT, string); + else + bk_send_string(UART2_PORT, string); + } + va_end(ap); + + if (state != taskSCHEDULER_NOT_STARTED) { + if (is_interrupt == false) { + xSemaphoreGiveRecursive(print_handle); + } + } +} + +void print_hex_dump(const char *prefix, void *buf, int len) +{ + int i; + u8 *b = buf; + + if (prefix) + os_printf("%s", prefix); + for (i = 0; i < len; i++) + os_printf("%02X ", b[i]); + os_printf("\n"); +} + +void fatal_print(const char *fmt, ...) +{ + os_printf(fmt); + + DEAD_WHILE(); +} + +void uart_hw_init(UINT8 uport) +{ + UINT32 reg, baud_div; + UINT32 conf_reg_addr, fifo_conf_reg_addr; + UINT32 flow_conf_reg_addr, wake_conf_reg_addr, intr_reg_addr; + + baud_div = UART_CLOCK / UART_BAUD_RATE; + baud_div = baud_div - 1; + + if(UART1_PORT == uport) + { + conf_reg_addr = REG_UART1_CONFIG; + fifo_conf_reg_addr = REG_UART1_FIFO_CONFIG; + flow_conf_reg_addr = REG_UART1_FLOW_CONFIG; + wake_conf_reg_addr = REG_UART1_WAKE_CONFIG; + intr_reg_addr = REG_UART1_INTR_ENABLE; + } + else + { + conf_reg_addr = REG_UART2_CONFIG; + fifo_conf_reg_addr = REG_UART2_FIFO_CONFIG; + flow_conf_reg_addr = REG_UART2_FLOW_CONFIG; + wake_conf_reg_addr = REG_UART2_WAKE_CONFIG; + intr_reg_addr = REG_UART2_INTR_ENABLE; + } + + reg = UART_TX_ENABLE + | UART_RX_ENABLE + | ((DEF_DATA_LEN & UART_DATA_LEN_MASK) << UART_DATA_LEN_POSI) + | ((baud_div & UART_CLK_DIVID_MASK) << UART_CLK_DIVID_POSI); + REG_WRITE(conf_reg_addr, reg); + + reg = ((TX_FIFO_THRD & TX_FIFO_THRESHOLD_MASK) << TX_FIFO_THRESHOLD_POSI) + | ((RX_FIFO_THRD & RX_FIFO_THRESHOLD_MASK) << RX_FIFO_THRESHOLD_POSI) + | ((RX_STOP_DETECT_TIME32 & RX_STOP_DETECT_TIME_MASK) << RX_STOP_DETECT_TIME_POSI); + REG_WRITE(fifo_conf_reg_addr, reg); + + REG_WRITE(flow_conf_reg_addr, 0); + REG_WRITE(wake_conf_reg_addr, 0); + + reg = RX_FIFO_NEED_READ_EN | UART_RX_STOP_END_EN; + REG_WRITE(intr_reg_addr, reg); + + return; +} + +void uart_hw_set_change(UINT8 uport, uart_config_t *uart_config) +{ + UINT32 reg, baud_div, width; +#if CFG_SUPPORT_ALIOS + hal_uart_parity_t parity_en; + hal_uart_stop_bits_t stop_bits; +#else + uart_parity_t parity_en; + uart_stop_bits_t stop_bits; +#endif + UINT8 parity_mode = 0; + UINT32 intr_ena_reg_addr, conf_reg_addr, fifi_conf_reg_addr; + UINT32 flow_conf_reg_addr, wake_reg_addr; + + if(UART1_PORT == uport) + { + intr_ena_reg_addr = REG_UART1_INTR_ENABLE; + conf_reg_addr = REG_UART1_CONFIG; + fifi_conf_reg_addr = REG_UART1_FIFO_CONFIG; + flow_conf_reg_addr = REG_UART1_FLOW_CONFIG; + wake_reg_addr = REG_UART1_WAKE_CONFIG; + } + else + { + intr_ena_reg_addr = REG_UART2_INTR_ENABLE; + conf_reg_addr = REG_UART2_CONFIG; + fifi_conf_reg_addr = REG_UART2_FIFO_CONFIG; + flow_conf_reg_addr = REG_UART2_FLOW_CONFIG; + wake_reg_addr = REG_UART2_WAKE_CONFIG; + } + REG_WRITE(intr_ena_reg_addr, 0);//disable int + + baud_div = UART_CLOCK / uart_config->baud_rate; + baud_div = baud_div - 1; + width = uart_config->data_width; + parity_en = uart_config->parity; + stop_bits = uart_config->stop_bits; + + if(parity_en) + { +#if CFG_SUPPORT_ALIOS + if(parity_en == ODD_PARITY) +#else + if(parity_en == BK_PARITY_ODD) +#endif + parity_mode = 1; + else + parity_mode = 0; + parity_en = 1; + } + + reg = UART_TX_ENABLE + | UART_RX_ENABLE + | ((width & UART_DATA_LEN_MASK) << UART_DATA_LEN_POSI) + | (parity_en << 5) + | (parity_mode << 6) + | (stop_bits << 7) + | ((baud_div & UART_CLK_DIVID_MASK) << UART_CLK_DIVID_POSI); + + width = ((width & UART_DATA_LEN_MASK) << UART_DATA_LEN_POSI); + REG_WRITE(conf_reg_addr, reg); + + reg = ((TX_FIFO_THRD & TX_FIFO_THRESHOLD_MASK) << TX_FIFO_THRESHOLD_POSI) + | ((RX_FIFO_THRD & RX_FIFO_THRESHOLD_MASK) << RX_FIFO_THRESHOLD_POSI) + | ((RX_STOP_DETECT_TIME32 & RX_STOP_DETECT_TIME_MASK) << RX_STOP_DETECT_TIME_POSI); + REG_WRITE(fifi_conf_reg_addr, reg); + + REG_WRITE(flow_conf_reg_addr, 0); + REG_WRITE(wake_reg_addr, 0); + + reg = RX_FIFO_NEED_READ_EN | UART_RX_STOP_END_EN; + REG_WRITE(intr_ena_reg_addr, reg); +} + + +#if CFG_UART_DEBUG_COMMAND_LINE +UINT32 uart_sw_init(UINT8 uport) +{ + uart[uport].rx = kfifo_alloc(RX_RB_LENGTH); + uart[uport].tx = kfifo_alloc(TX_RB_LENGTH); + + if((!uart[uport].tx) || (!uart[uport].rx)) + { + if(uart[uport].tx) + { + kfifo_free(uart[uport].tx); + } + + if(uart[uport].rx) + { + kfifo_free(uart[uport].rx); + } + return UART_FAILURE; + } + + return UART_SUCCESS; +} + +UINT32 uart_sw_uninit(UINT8 uport) +{ + if(uart[uport].tx) + { + kfifo_free(uart[uport].tx); + } + + if(uart[uport].rx) + { + kfifo_free(uart[uport].rx); + } + + os_memset(&uart[uport], 0, sizeof(uart[uport])); + + return UART_SUCCESS; +} + +void uart_fifo_flush(UINT8 uport) +{ + UINT32 val; + UINT32 reg; + UINT32 reg_addr; + + if(UART1_PORT == uport) + reg_addr = REG_UART1_CONFIG; + else + reg_addr = REG_UART2_CONFIG; + + val = REG_READ(reg_addr); + + reg = val & (~(UART_TX_ENABLE | UART_RX_ENABLE)); + + REG_WRITE(reg_addr, reg); + REG_WRITE(reg_addr, val); +} + +void uart_hw_uninit(UINT8 uport) +{ + UINT32 i; + UINT32 reg; + UINT32 rx_count; + UINT32 intr_ena_reg_addr, conf_reg_addr, fifostatus_reg_addr; + if(UART1_PORT == uport) + { + intr_ena_reg_addr = REG_UART1_INTR_ENABLE; + conf_reg_addr = REG_UART1_CONFIG; + fifostatus_reg_addr = REG_UART1_FIFO_STATUS; + } + else + { + intr_ena_reg_addr = REG_UART2_INTR_ENABLE; + conf_reg_addr = REG_UART2_CONFIG; + fifostatus_reg_addr = REG_UART2_FIFO_STATUS; + } + /*disable rtx intr*/ + reg = REG_READ(intr_ena_reg_addr); + reg &= (~(RX_FIFO_NEED_READ_EN | UART_RX_STOP_END_EN)); + REG_WRITE(intr_ena_reg_addr, reg); + + /* flush fifo*/ + uart_fifo_flush(uport); + + /* disable rtx*/ + reg = REG_READ(conf_reg_addr); + reg = reg & (~(UART_TX_ENABLE | UART_RX_ENABLE)); + REG_WRITE(conf_reg_addr, reg); + + /* double discard fifo data*/ + reg = REG_READ(fifostatus_reg_addr); + rx_count = (reg >> RX_FIFO_COUNT_POSI) & RX_FIFO_COUNT_MASK; + for(i = 0; i < rx_count; i ++) + { + UART_READ_BYTE_DISCARD(uport); + } +} + +void uart_reset(UINT8 uport) +{ + if(UART1_PORT == uport) + { + uart1_exit(); + uart1_init(); + } + else + { + uart2_exit(); + uart2_init(); + } +} + +void uart_send_backgroud(void) +{ + /* send the buf at backgroud context*/ + uart_write_fifo_frame(UART2_PORT, uart[UART2_PORT].tx, DEBUG_PRT_MAX_CNT); +} + +UINT32 uart_write_fifo_frame(UINT8 uport, KFIFO_PTR tx_ptr, UINT32 count) +{ + UINT32 len; + UINT32 ret; + UINT32 val; + + len = 0; + + while(1) + { + ret = kfifo_get(tx_ptr, (UINT8 *)&val, 1); + if(0 == ret) + { + break; + } + + +#if __CC_ARM + uart_send_byte(uport, (UINT8)val); +#else + bk_send_byte(uport, (UINT8)val); +#endif + + len += ret; + if(len >= count) + { + break; + } + } + + return len; +} + +UINT32 uart_read_fifo_frame(UINT8 uport, KFIFO_PTR rx_ptr) +{ + UINT32 val; + UINT32 rx_count, fifo_status_reg; + + if(UART1_PORT == uport) + fifo_status_reg = REG_UART1_FIFO_STATUS; + else + fifo_status_reg = REG_UART2_FIFO_STATUS; + + rx_count = 0; + while(REG_READ(fifo_status_reg) & FIFO_RD_READY) + { + UART_READ_BYTE(uport, val); + rx_count += kfifo_put(rx_ptr, (UINT8 *)&val, 1); + } + + return rx_count; +} + +void uart_set_tx_fifo_needwr_int(UINT8 uport, UINT8 set) +{ + UINT32 reg; + + if(UART1_PORT == uport) + reg = REG_READ(REG_UART1_INTR_ENABLE); + else + reg = REG_READ(REG_UART2_INTR_ENABLE); + + if(set == 1) + { + reg |= (TX_FIFO_NEED_WRITE_EN); + } + else + { + reg &= ~(TX_FIFO_NEED_WRITE_EN); + } + + if(UART1_PORT == uport){ + //rt_kprintf("set_tx_fifo:%d\r\n", set); + REG_WRITE(REG_UART1_INTR_ENABLE, reg); + } + else + REG_WRITE(REG_UART2_INTR_ENABLE, reg); +} + +void uart_set_tx_stop_end_int(UINT8 uport, UINT8 set) +{ + UINT32 reg; + + if(UART1_PORT == uport) + reg = REG_READ(REG_UART1_INTR_ENABLE); + else + reg = REG_READ(REG_UART2_INTR_ENABLE); + + if(set == 1) + { + reg |= (UART_TX_STOP_END_EN); + } + else + { + reg &= ~(UART_TX_STOP_END_EN); + } + + if(UART1_PORT == uport) + REG_WRITE(REG_UART1_INTR_ENABLE, reg); + else + REG_WRITE(REG_UART2_INTR_ENABLE, reg); +} + +void uart_disable_rx(UINT8 uport) +{ + UINT32 reg; + + if(UART1_PORT == uport) + reg = REG_READ(REG_UART1_CONFIG); + else + reg = REG_READ(REG_UART2_CONFIG); + + reg &= ~(UART_RX_ENABLE); + + if(UART1_PORT == uport){ + //rt_kprintf("set_tx_fifo:%d\r\n", set); + REG_WRITE(REG_UART1_CONFIG, reg); + } + else + REG_WRITE(REG_UART2_CONFIG, reg); +} + +/*******************************************************************/ +void uart1_isr(void) +{ + + UINT32 status; + UINT32 intr_en; + UINT32 intr_status; + + intr_en = REG_READ(REG_UART1_INTR_ENABLE); + intr_status = REG_READ(REG_UART1_INTR_STATUS); + REG_WRITE(REG_UART1_INTR_STATUS, intr_status); + status = intr_status & intr_en; + + if(status & (RX_FIFO_NEED_READ_STA | UART_RX_STOP_END_STA)) + { +#if ATE_APP_FUN + if(get_ate_mode_state()) + { + uart_read_fifo_frame(UART1_PORT, uart[UART1_PORT].rx); + } +#endif + + if (uart_receive_callback[0].callback != 0) + { + void *param = uart_receive_callback[0].param; + + uart_receive_callback[0].callback(UART1_PORT, param); + } + else + { + uart_read_byte(UART1_PORT); /*drop data for rtt*/ + } + } + + if(status & TX_FIFO_NEED_WRITE_STA) + { + if (uart_txfifo_needwr_callback[0].callback != 0) + { + void *param = uart_txfifo_needwr_callback[0].param; + + uart_txfifo_needwr_callback[0].callback(UART1_PORT, param); + } + } + + if(status & RX_FIFO_OVER_FLOW_STA) + { + } + + if(status & UART_RX_PARITY_ERR_STA) + { + uart_fifo_flush(UART1_PORT); + } + + if(status & UART_RX_STOP_ERR_STA) + { + } + + if(status & UART_TX_STOP_END_STA) + { + if (uart_tx_end_callback[0].callback != 0) + { + void *param = uart_tx_end_callback[0].param; + + uart_tx_end_callback[0].callback(UART1_PORT, param); + } + } + + if(status & UART_RXD_WAKEUP_STA) + { + } +} + +void uart1_init(void) +{ + UINT32 ret; + UINT32 param; + UINT32 intr_status; + + ret = uart_sw_init(UART1_PORT); + ASSERT(UART_SUCCESS == ret); + + ddev_register_dev(UART1_DEV_NAME, &uart1_op); + + intc_service_register(IRQ_UART1, PRI_IRQ_UART1, uart1_isr); + + param = PWD_UART1_CLK_BIT; + sddev_control(ICU_DEV_NAME, CMD_CLK_PWR_UP, ¶m); + + param = GFUNC_MODE_UART1; + sddev_control(GPIO_DEV_NAME, CMD_GPIO_ENABLE_SECOND, ¶m); + uart_hw_init(UART1_PORT); + + /*irq enable, Be careful: it is best that irq enable at open routine*/ + intr_status = REG_READ(REG_UART1_INTR_STATUS); + REG_WRITE(REG_UART1_INTR_STATUS, intr_status); + + param = IRQ_UART1_BIT; + sddev_control(ICU_DEV_NAME, CMD_ICU_INT_ENABLE, ¶m); +} + +void uart1_exit(void) +{ + UINT32 param; + + /*irq enable, Be careful: it is best that irq enable at close routine*/ + param = IRQ_UART1_BIT; + sddev_control(ICU_DEV_NAME, CMD_ICU_INT_DISABLE, ¶m); + + uart_hw_uninit(UART1_PORT); + + ddev_unregister_dev(UART1_DEV_NAME); + + uart_sw_uninit(UART1_PORT); +} + +UINT32 uart1_open(UINT32 op_flag) +{ + uart1_init(); + + return UART_SUCCESS; +} + +UINT32 uart1_close(void) +{ + uart1_exit(); + + return UART_SUCCESS; +} + +UINT32 uart1_read(char *user_buf, UINT32 count, UINT32 op_flag) +{ + return kfifo_get(uart[UART1_PORT].rx, (UINT8 *)user_buf, count); +} + +UINT32 uart1_write(char *user_buf, UINT32 count, UINT32 op_flag) +{ + return kfifo_put(uart[UART1_PORT].tx, (UINT8 *)user_buf, count); +} + +UINT32 uart1_ctrl(UINT32 cmd, void *parm) +{ + UINT32 ret; + peri_busy_count_add(); + + ret = UART_SUCCESS; + switch(cmd) + { + case CMD_SEND_BACKGROUND: + // uart_send_backgroud(); + break; + + case CMD_UART_RESET: + uart_reset(UART1_PORT); + break; + + case CMD_RX_COUNT: + ret = kfifo_data_size(uart[UART1_PORT].rx); + break; + + case CMD_RX_PEEK: + { + UART_PEEK_RX_PTR peek; + + peek = (UART_PEEK_RX_PTR)parm; + + if(!((URX_PEEK_SIG != peek->sig) + || (NULLPTR == peek->ptr) + || (0 == peek->len))) + { + ret = kfifo_out_peek(uart[UART1_PORT].rx, peek->ptr, peek->len); + } + + break; + } + case CMD_UART_INIT: + uart_hw_set_change(UART1_PORT, parm); + break; + case CMD_UART_SET_RX_CALLBACK: + if (parm) + { + struct uart_callback_des *uart_callback; + + uart_callback = (struct uart_callback_des *)parm; + + uart_rx_callback_set(UART1_PORT, uart_callback->callback, uart_callback->param); + } + else + { + uart_rx_callback_set(UART1_PORT, NULL, NULL); + } + break; + case CMD_UART_SET_TX_CALLBACK: + if (parm) + { + struct uart_callback_des *uart_callback; + + uart_callback = (struct uart_callback_des *)parm; + + uart_tx_end_callback_set(UART1_PORT, uart_callback->callback, uart_callback->param); + } + else + { + uart_tx_end_callback_set(UART1_PORT, NULL, NULL); + } + break; + case CMD_UART_SET_TX_FIFO_NEEDWR_CALLBACK: + if (parm) + { + struct uart_callback_des *uart_callback; + + uart_callback = (struct uart_callback_des *)parm; + + uart_tx_fifo_needwr_callback_set(UART1_PORT, uart_callback->callback, uart_callback->param); + } + else + { + uart_tx_fifo_needwr_callback_set(UART1_PORT, NULL, NULL); + } + break; + case CMD_SET_STOP_END: + uart_set_tx_stop_end_int(UART1_PORT, *(UINT8 *)parm); + break; + + case CMD_SET_TX_FIFO_NEEDWR_INT: + uart_set_tx_fifo_needwr_int(UART1_PORT, *(UINT8 *)parm); + break; + + case CMD_DISABLE_UART_RX: + uart_disable_rx(UART1_PORT); + + default: + break; + } + + peri_busy_count_dec(); + + return ret; +} + + +void uart2_isr(void) +{ +#if CFG_UART_DEBUG_COMMAND_LINE + UINT32 status; + UINT32 intr_en; + UINT32 intr_status; + + intr_en = REG_READ(REG_UART2_INTR_ENABLE); + intr_status = REG_READ(REG_UART2_INTR_STATUS); + REG_WRITE(REG_UART2_INTR_STATUS, intr_status); + status = intr_status & intr_en; + + if(status & (RX_FIFO_NEED_READ_STA | UART_RX_STOP_END_STA)) + { + #if (!CFG_SUPPORT_RTT) + uart_read_fifo_frame(UART2_PORT, uart[UART2_PORT].rx); + #endif + + if (uart_receive_callback[1].callback != 0) + { + void *param = uart_receive_callback[1].param; + + uart_receive_callback[1].callback(UART2_PORT, param); + } + else + { + uart_read_byte(UART2_PORT); /*drop data for rtt*/ + } + } + + if(status & TX_FIFO_NEED_WRITE_STA) + { + if (uart_txfifo_needwr_callback[1].callback != 0) + { + void *param = uart_txfifo_needwr_callback[1].param; + + uart_txfifo_needwr_callback[1].callback(UART2_PORT, param); + } + } + + if(status & RX_FIFO_OVER_FLOW_STA) + { + } + + if(status & UART_RX_PARITY_ERR_STA) + { + uart_fifo_flush(UART2_PORT); + } + + if(status & UART_RX_STOP_ERR_STA) + { + } + + if(status & UART_TX_STOP_END_STA) + { + if (uart_tx_end_callback[1].callback != 0) + { + void *param = uart_tx_end_callback[1].param; + + uart_tx_end_callback[1].callback(UART2_PORT, param); + } + } + + if(status & UART_RXD_WAKEUP_STA) + { + } + +#endif +} +void uart2_init(void) +{ + UINT32 ret; + UINT32 param; + UINT32 intr_status; + + ret = uart_sw_init(UART2_PORT); + ASSERT(UART_SUCCESS == ret); + + ddev_register_dev(UART2_DEV_NAME, &uart2_op); + + intc_service_register(IRQ_UART2, PRI_IRQ_UART2, uart2_isr); + + param = PWD_UART2_CLK_BIT; + sddev_control(ICU_DEV_NAME, CMD_CLK_PWR_UP, ¶m); + + param = GFUNC_MODE_UART2; + sddev_control(GPIO_DEV_NAME, CMD_GPIO_ENABLE_SECOND, ¶m); + uart_hw_init(UART2_PORT); + + /*irq enable, Be careful: it is best that irq enable at open routine*/ + intr_status = REG_READ(REG_UART2_INTR_STATUS); + REG_WRITE(REG_UART2_INTR_STATUS, intr_status); + + param = IRQ_UART2_BIT; + sddev_control(ICU_DEV_NAME, CMD_ICU_INT_ENABLE, ¶m); + +#if 0 + os_printf("\r\n\r\n/*Version Information**************"); + os_printf("\r\n * release_version:%s", RELEASE_VERSION); + os_printf("\r\n * release_time:%s", RELEASE_TIME); + os_printf("\r\n * full_mac_version:%s", FMALL_VERSION); + os_printf("\r\n * mac_lib_version:%s", FMAC_LIB_VERSON); + os_printf("\r\n * bulid date:%s, time:%s", __DATE__, __TIME__); + os_printf("\r\n *Version Over**********************/\r\n\r\n"); +#endif +} + +void uart2_exit(void) +{ + UINT32 param; + + /*irq enable, Be careful: it is best that irq enable at close routine*/ + param = IRQ_UART2_BIT; + sddev_control(ICU_DEV_NAME, CMD_ICU_INT_DISABLE, ¶m); + + uart_hw_uninit(UART2_PORT); + + ddev_unregister_dev(UART2_DEV_NAME); + + uart_sw_uninit(UART2_PORT); +} + +UINT32 uart2_open(UINT32 op_flag) +{ + uart2_init(); + + return UART_SUCCESS; +} + +UINT32 uart2_close(void) +{ + uart2_exit(); + + return UART_SUCCESS; +} + +UINT32 uart2_read(char *user_buf, UINT32 count, UINT32 op_flag) +{ + return kfifo_get(uart[UART2_PORT].rx, (UINT8 *)user_buf, count); +} + +UINT32 uart2_write(char *user_buf, UINT32 count, UINT32 op_flag) +{ + return kfifo_put(uart[UART2_PORT].tx, (UINT8 *)user_buf, count); +} + +UINT32 uart2_ctrl(UINT32 cmd, void *parm) +{ + UINT32 ret; + + peri_busy_count_add(); + + ret = UART_SUCCESS; + switch(cmd) + { + case CMD_SEND_BACKGROUND: + uart_send_backgroud(); + break; + + case CMD_UART_RESET: + uart_reset(UART2_PORT); + break; + + case CMD_RX_COUNT: + ret = kfifo_data_size(uart[UART2_PORT].rx); + break; + + case CMD_RX_PEEK: + { + UART_PEEK_RX_PTR peek; + + peek = (UART_PEEK_RX_PTR)parm; + + if(!((URX_PEEK_SIG != peek->sig) + || (NULLPTR == peek->ptr) + || (0 == peek->len))) + { + ret = kfifo_out_peek(uart[UART2_PORT].rx, peek->ptr, peek->len); + } + + break; + } + case CMD_UART_INIT: + uart_hw_set_change(UART2_PORT, parm); + break; + case CMD_UART_SET_RX_CALLBACK: + if (parm) + { + struct uart_callback_des *uart_callback; + + uart_callback = (struct uart_callback_des *)parm; + + uart_rx_callback_set(UART2_PORT, uart_callback->callback, uart_callback->param); + } + else + { + uart_rx_callback_set(UART2_PORT, NULL, NULL); + } + break; + case CMD_UART_SET_TX_CALLBACK: + if (parm) + { + struct uart_callback_des *uart_callback; + + uart_callback = (struct uart_callback_des *)parm; + + uart_tx_end_callback_set(UART2_PORT, uart_callback->callback, uart_callback->param); + } + else + { + uart_tx_end_callback_set(UART2_PORT, NULL, NULL); + } + break; + case CMD_UART_SET_TX_FIFO_NEEDWR_CALLBACK: + if (parm) + { + struct uart_callback_des *uart_callback; + + uart_callback = (struct uart_callback_des *)parm; + + uart_tx_fifo_needwr_callback_set(UART2_PORT, uart_callback->callback, uart_callback->param); + } + else + { + uart_tx_fifo_needwr_callback_set(UART2_PORT, NULL, NULL); + } + break; + case CMD_SET_STOP_END: + uart_set_tx_stop_end_int(UART2_PORT, *(UINT8 *)parm); + break; + + case CMD_SET_TX_FIFO_NEEDWR_INT: + uart_set_tx_fifo_needwr_int(UART2_PORT, *(UINT8 *)parm); + break; + + case CMD_DISABLE_UART_RX: + uart_disable_rx(UART2_PORT); + break; + + default: + break; + } + + peri_busy_count_dec(); + + return ret; +} + +void uart_wait_tx_over() +{ + while (UART2_TX_FIFO_EMPTY_GET() == 0) + { + } + + while (UART1_TX_FIFO_EMPTY_GET() == 0) + { + } +} +#endif // (!CFG_UART_DEBUG_COMMAND_LINE) + +#endif // KEIL_SIMULATOR + +#if 0 +INT32 os_null_printf(const char *fmt, ...) +{ + return 0; +} +#endif + +int uart_read_byte(int uport) +{ + int val = -1; + UINT32 fifo_status_reg; + + if (UART1_PORT == uport) + fifo_status_reg = REG_UART1_FIFO_STATUS; + else + fifo_status_reg = REG_UART2_FIFO_STATUS; + + if (REG_READ(fifo_status_reg) & FIFO_RD_READY) + UART_READ_BYTE(uport, val); + + return val; +} + +int uart_write_byte(int uport, char c) +{ + if (UART1_PORT == uport) + while(!UART1_TX_WRITE_READY); + else + while(!UART2_TX_WRITE_READY); + + UART_WRITE_BYTE(uport, c); + + return (1); +} + +int uart_rx_callback_set(int uport, uart_callback callback, void *param) +{ + if (uport == UART1_PORT) + { + uart_receive_callback[0].callback = callback; + uart_receive_callback[0].param = param; + } + else if (uport == UART2_PORT) + { + uart_receive_callback[1].callback = callback; + uart_receive_callback[1].param = param; + } + else + { + return -1; + } + + return 0; +} + +int uart_tx_fifo_needwr_callback_set(int uport, uart_callback callback, void *param) +{ + if (uport == UART1_PORT) + { + uart_txfifo_needwr_callback[0].callback = callback; + uart_txfifo_needwr_callback[0].param = param; + } + else if (uport == UART2_PORT) + { + uart_txfifo_needwr_callback[1].callback = callback; + uart_txfifo_needwr_callback[1].param = param; + } + else + { + return -1; + } + + return 0; +} + +int uart_tx_end_callback_set(int uport, uart_callback callback, void *param) +{ + if (uport == UART1_PORT) + { + uart_tx_end_callback[0].callback = callback; + uart_tx_end_callback[0].param = param; + } + else if (uport == UART2_PORT) + { + uart_tx_end_callback[1].callback = callback; + uart_tx_end_callback[1].param = param; + } + else + { + return -1; + } + + return 0; +} + +// EOF diff --git a/beken_os/beken378/driver/wdt/wdt.c b/beken_os/beken378/driver/wdt/wdt.c new file mode 100755 index 0000000..1a62c4e --- /dev/null +++ b/beken_os/beken378/driver/wdt/wdt.c @@ -0,0 +1,92 @@ +#include "include.h" +#include "arm_arch.h" + +#include "wdt_pub.h" +#include "wdt.h" +#include "icu_pub.h" + +#include "drv_model_pub.h" +#include "start_type_pub.h" + +static SDD_OPERATIONS wdt_op = { + wdt_ctrl +}; +static uint32_t g_wdt_period = 0; + +/*******************************************************************/ +#if 1 +void wdt_init(void) +{ + sddev_register_dev(WDT_DEV_NAME, &wdt_op); +} + +void wdt_exit(void) +{ + sddev_unregister_dev(WDT_DEV_NAME); +} + +UINT32 wdt_ctrl(UINT32 cmd, void *param) +{ + UINT32 ret; + UINT32 reg; + UINT32 parameter; + + ret = WDT_SUCCESS; + switch(cmd) + { + case WCMD_POWER_DOWN: + g_wdt_period = 0; + + parameter = PWD_ARM_WATCHDOG_CLK_BIT; + ret = sddev_control(ICU_DEV_NAME, CMD_CLK_PWR_DOWN, (void *)¶meter); + ASSERT(ICU_SUCCESS == ret); + break; + + case WCMD_POWER_UP: + parameter = PWD_ARM_WATCHDOG_CLK_BIT; + ret = sddev_control(ICU_DEV_NAME, CMD_CLK_PWR_UP, (void *)¶meter); + ASSERT(ICU_SUCCESS == ret); + break; + + case WCMD_RELOAD_PERIOD: + reg = WDT_1ST_KEY << WDT_KEY_POSI; + reg |= (g_wdt_period & WDT_PERIOD_MASK) << WDT_PERIOD_POSI; + REG_WRITE(WDT_CTRL_REG, reg); + + sctrl_dpll_delay200us(); + + reg = WDT_2ND_KEY << WDT_KEY_POSI; + reg |= (g_wdt_period & WDT_PERIOD_MASK) << WDT_PERIOD_POSI; + REG_WRITE(WDT_CTRL_REG, reg); + + sctrl_dpll_delay200us(); + + bk_misc_update_set_type(RESET_SOURCE_WATCHDOG); + break; + + case WCMD_SET_PERIOD: + ASSERT(param); + g_wdt_period = (*(UINT32 *)param); + + reg = WDT_1ST_KEY << WDT_KEY_POSI; + reg |= ((*(UINT32 *)param) & WDT_PERIOD_MASK) << WDT_PERIOD_POSI; + REG_WRITE(WDT_CTRL_REG, reg); + + sctrl_dpll_delay200us(); + + reg = WDT_2ND_KEY << WDT_KEY_POSI; + reg |= ((*(UINT32 *)param) & WDT_PERIOD_MASK) << WDT_PERIOD_POSI; + REG_WRITE(WDT_CTRL_REG, reg); + + sctrl_dpll_delay200us(); + break; + + default: + break; + } + + return ret; +} +#endif + +// EOF diff --git a/beken_os/beken378/driver/wdt/wdt.h b/beken_os/beken378/driver/wdt/wdt.h new file mode 100755 index 0000000..a45dc1a --- /dev/null +++ b/beken_os/beken378/driver/wdt/wdt.h @@ -0,0 +1,33 @@ +#ifndef _WDT_H_ +#define _WDT_H_ + +#define WDT_DEBUG + +#ifdef WDT_DEBUG + #define WDT_PRT os_printf + #define WDT_WARN warning_prf + #define WDT_FATAL fatal_prf +#else + #define WDT_PRT null_prf + #define WDT_WARN null_prf + #define WDT_FATAL null_prf +#endif + +#define WDT_BASE (0x00802900) + +#define WDT_CTRL_REG (WDT_BASE + 0 * 4) +#define WDT_KEY_POSI (16) +#define WDT_KEY_MASK (0xFF) +#define WDT_1ST_KEY (0x5A) +#define WDT_2ND_KEY (0xA5) + +#define WDT_PERIOD_POSI (0) +#define WDT_PERIOD_MASK (0xFFFF) + +/******************************************************************************* +* Function Declarations +*******************************************************************************/ +extern UINT32 wdt_ctrl(UINT32 cmd, void *param); + +#endif //_WDT_H_ + diff --git a/beken_os/beken378/func/audio/audio_intf.c b/beken_os/beken378/func/audio/audio_intf.c new file mode 100755 index 0000000..1bd5484 --- /dev/null +++ b/beken_os/beken378/func/audio/audio_intf.c @@ -0,0 +1,505 @@ +#include "include.h" +#include "arm_arch.h" +#if CFG_USE_AUDIO +#include "audio_pub.h" + +#include "mem_pub.h" +#include "drv_model_pub.h" +#include "sys_rtos.h" +#include "rtos_pub.h" +#include "error.h" + +//#include "song.h" + +#define AUD_INTF_DEBUG +#include "uart_pub.h" +#ifdef AUD_INTF_DEBUG +#define AUD_INTF_PRT os_printf +#define AUD_INTF_WPRT warning_prf +#define AUD_INTF_FATAL fatal_prf +#else +#define AUD_INTF_PRT null_prf +#define AUD_INTF_WPRT null_prf +#define AUD_INTF_FATAL null_prf +#endif + +enum +{ + AUD_INTF_DAC_FILL_TIMER = 0, + AUD_INTF_DAC_PLAY, + AUD_INTF_DAC_PAUSE, + AUD_INTF_DAC_SET_VOLUME, + + AUD_INTF_ADC_GET_TIMER, + AUD_INTF_ADC_PLAY, + AUD_INTF_ADC_PAUSE, + AUD_INTF_ADC_LINEIN_TIMER, + + AUD_INTF_SET_SAMPLE_RATE, + + AUD_INTF_EXIT, + + +}; + +typedef struct audio_message +{ + UINT32 audio_msg; +}AUDIO_MSG_T; +#define AUDIO_QITEM_COUNT (5) + +beken_queue_t audio_msg_que = NULL; +xTaskHandle audio_handle = NULL; + +void audio_intf_send_msg(u32 new_msg); + + +#if CFG_USE_AUD_DAC +AUD_DAC_CFG_ST aud_dac_cfg; +DD_HANDLE aud_dac_hdl = DD_HANDLE_UNVALID; + +#define AUD_DAC_BUF_LEN (4 * 1024) +UINT8 audio_dac_buf[AUD_DAC_BUF_LEN]; +UINT8 *audio_read; + +#define DAC_TIMER_INTVAL (15) +beken_timer_t audio_dac_fill_timer; + +static void audio_intf_dac_timer_poll(void) +{ +#if 0 + UINT32 free_len; + UINT32 left = (QQQG + sizeof(QQQG)) - audio_read; + + free_len = ddev_control(aud_dac_hdl, AUD_DAC_CMD_GET_FREE_BUF_SIZE, NULL); + + if(free_len < left) { + ddev_write(aud_dac_hdl, (char *)audio_read, free_len, 0); + audio_read += free_len; + } + else if(left) { + UINT32 copy_from_start = free_len - left; + ddev_write(aud_dac_hdl, (char *)audio_read, left, 0); + ddev_write(aud_dac_hdl, (char *)QQQG, copy_from_start, 0); + audio_read = (UINT8*)&QQQG[copy_from_start]; + } + + //AUD_INTF_PRT("%d,%d\r\n", free_len, left); + + rtos_reload_timer(&audio_dac_fill_timer); + //AUD_INTF_PRT("audio_intf_dac_timer_poll, restart timer\r\n"); +#endif +} + +static void audio_intf_dac_timer_handler(void *data) +{ + audio_intf_send_msg(AUD_INTF_DAC_FILL_TIMER); +} + +static void audio_intf_dac_pause_poll(void) +{ + ddev_control(aud_dac_hdl, AUD_DAC_CMD_PAUSE, NULL); +} + +void audio_intf_dac_pause(void) +{ + audio_intf_send_msg(AUD_INTF_DAC_PAUSE); +} + +static void audio_intf_dac_play_poll(void) +{ + ddev_control(aud_dac_hdl, AUD_DAC_CMD_PLAY, NULL); +} + +void audio_intf_dac_play(void) +{ + audio_intf_send_msg(AUD_INTF_DAC_PLAY); +} + +static void audio_intf_dac_set_volume_poll(void) +{ + static UINT32 dac_vol = 0; + + dac_vol++; + if(dac_vol >= 20) + dac_vol = 0; + + AUD_INTF_PRT("set dac vol :%d\r\n", dac_vol); + + ddev_control(aud_dac_hdl, AUD_DAC_CMD_SET_VOLUME, &dac_vol); +} + +void audio_intf_dac_set_volume(void) +{ + audio_intf_send_msg(AUD_INTF_DAC_SET_VOLUME); +} + +#endif // CFG_USE_AUD_DAC + +#if CFG_USE_AUD_ADC +AUD_ADC_CFG_ST aud_adc_cfg; +DD_HANDLE aud_adc_hdl = DD_HANDLE_UNVALID; + +#define AUD_ADC_BUF_LEN (3 * 1024) +UINT8 audio_adc_buf[AUD_ADC_BUF_LEN]; + +#define AUD_ADC_DATA_LEN (2 * 1024) +UINT8 adc_data[AUD_ADC_DATA_LEN]; + +#define ADC_TIMER_INTVAL (4) +beken_timer_t audio_adc_get_timer; + +#define ADC_LINEIN_DETECT_TIMER_INTVAL (10) +beken_timer_t audio_adc_linein_timer; + +static void audio_intf_adc_timer_poll(void) +{ + UINT32 mic_filled_len, audio_free_len, copy_len; + + audio_free_len = ddev_control(aud_dac_hdl, AUD_DAC_CMD_GET_FREE_BUF_SIZE, NULL); + mic_filled_len = ddev_control(aud_adc_hdl, AUD_ADC_CMD_GET_FILL_BUF_SIZE, NULL); + + copy_len = (audio_free_len > mic_filled_len)? mic_filled_len : audio_free_len; + + if(copy_len) + { + if(copy_len > AUD_ADC_DATA_LEN) { + copy_len = AUD_ADC_DATA_LEN; + + } + ddev_read(aud_adc_hdl, (char *)adc_data, copy_len, 0); + ddev_write(aud_dac_hdl, (char *)adc_data, copy_len, 0); + } + + //AUD_INTF_PRT("%d\r\n", copy_len); + + rtos_reload_timer(&audio_adc_get_timer); +} + +static void audio_intf_adc_timer_handler(void *data) +{ + audio_intf_send_msg(AUD_INTF_ADC_GET_TIMER); +} + +static void audio_intf_adc_pause_poll(void) +{ + ddev_control(aud_adc_hdl, AUD_ADC_CMD_PAUSE, NULL); +} + +void audio_intf_adc_pause(void) +{ + audio_intf_send_msg(AUD_INTF_ADC_PAUSE); +} + +static void audio_intf_adc_play_poll(void) +{ + ddev_control(aud_adc_hdl, AUD_ADC_CMD_PLAY, NULL); +} + +void audio_intf_adc_play(void) +{ + audio_intf_send_msg(AUD_INTF_ADC_PLAY); +} + +static void audio_intf_adc_linein_timer_poll(void) +{ + ddev_control(aud_adc_hdl, AUD_ADC_CMD_DO_LINEIN_DETECT, NULL); + + rtos_reload_timer(&audio_adc_linein_timer); + //AUD_INTF_PRT("restart timer\r\n"); +} + +static void audio_intf_adc_linein_timer_handler(void *data) +{ + audio_intf_send_msg(AUD_INTF_ADC_LINEIN_TIMER); +} +#endif + +UINT32 sample_rate_tab[] = {8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000}; +static void audio_intf_set_sample_rate_poll(void) +{ + static UINT32 i = 0; + UINT32 param = 0; + + i++; + if(i >= sizeof(sample_rate_tab)/4) + i = 0; + + param = sample_rate_tab[i]; + + #if CFG_USE_AUD_DAC + ddev_control(aud_dac_hdl, AUD_DAC_CMD_SET_SAMPLE_RATE, ¶m); + #endif + + #if CFG_USE_AUD_ADC + ddev_control(aud_adc_hdl, AUD_ADC_CMD_SET_SAMPLE_RATE, ¶m); + #endif + + AUD_INTF_PRT("set sample rate:%d\r\n", param); +} + +void audio_intf_set_sample_rate(void) +{ + audio_intf_send_msg(AUD_INTF_SET_SAMPLE_RATE); +} + +static void audio_intf_main( beken_thread_arg_t data ) +{ + OSStatus err; + UINT32 status; + GLOBAL_INT_DECLARATION(); + +#if CFG_USE_AUD_DAC + aud_dac_cfg.buf = &audio_dac_buf[0]; + aud_dac_cfg.buf_len = AUD_DAC_BUF_LEN; + aud_dac_cfg.freq = 44100; + aud_dac_cfg.channels = 2; + aud_dac_cfg.dma_mode = 0; + #if AUD_USE_EXT_PA + aud_dac_cfg.mute_pin = AUD_DAC_MUTE_PIN; + #else + aud_dac_cfg.mute_pin = 0; + #endif + + //audio_read = (UINT8*)&QQQG[0]; + + GLOBAL_INT_DISABLE(); + aud_dac_hdl = ddev_open(AUD_DAC_DEV_NAME, &status, (UINT32)&aud_dac_cfg); + status = status; + if(DD_HANDLE_UNVALID == aud_dac_hdl) + { + GLOBAL_INT_RESTORE(); + goto audio_exit; + } + GLOBAL_INT_RESTORE(); +#if 0 + err = rtos_init_timer(&audio_dac_fill_timer, + DAC_TIMER_INTVAL, + audio_intf_dac_timer_handler, + (void *)0); + ASSERT(kNoErr == err); + + err = rtos_start_timer(&audio_dac_fill_timer); + ASSERT(kNoErr == err); +#endif +#endif + +#if CFG_USE_AUD_ADC + aud_adc_cfg.buf = &audio_adc_buf[0]; + aud_adc_cfg.buf_len = AUD_ADC_BUF_LEN; + aud_adc_cfg.freq = 44100; + aud_adc_cfg.channels = 2; + + aud_adc_cfg.mode = 0; + //aud_adc_cfg.mode |= AUD_ADC_MODE_DMA_BIT; + aud_adc_cfg.linein_detect_pin = AUD_ADC_LINEIN_DETECT_PIN; + + GLOBAL_INT_DISABLE(); + aud_adc_hdl = ddev_open(AUD_ADC_DEV_NAME, &status, (UINT32)&aud_adc_cfg); + status = status; + if(DD_HANDLE_UNVALID == aud_adc_hdl) + { + GLOBAL_INT_RESTORE(); + goto audio_exit; + } + GLOBAL_INT_RESTORE(); + + #if !AUD_ADC_DAC_HARDWARD_LOOPBACK + err = rtos_init_timer(&audio_adc_get_timer, + ADC_TIMER_INTVAL, + audio_intf_adc_timer_handler, + (void *)0); + ASSERT(kNoErr == err); + + err = rtos_start_timer(&audio_adc_get_timer); + ASSERT(kNoErr == err); + #endif + + err = rtos_init_timer(&audio_adc_linein_timer, + ADC_LINEIN_DETECT_TIMER_INTVAL, + audio_intf_adc_linein_timer_handler, + (void *)0); + ASSERT(kNoErr == err); + + err = rtos_start_timer(&audio_adc_linein_timer); + ASSERT(kNoErr == err); +#endif + + while(1) + { + AUDIO_MSG_T msg; + err = rtos_pop_from_queue(&audio_msg_que, &msg, BEKEN_WAIT_FOREVER); + if(kNoErr == err) { + switch(msg.audio_msg) + { + #if CFG_USE_AUD_DAC + case AUD_INTF_DAC_FILL_TIMER: + { + audio_intf_dac_timer_poll(); + } + break; + + case AUD_INTF_DAC_PLAY: + { + audio_intf_dac_play_poll(); + } + break; + + case AUD_INTF_DAC_PAUSE: + { + audio_intf_dac_pause_poll(); + } + break; + + case AUD_INTF_DAC_SET_VOLUME: + { + audio_intf_dac_set_volume_poll(); + } + break; + + #endif // CFG_USE_AUD_DAC + + #if CFG_USE_AUD_ADC + case AUD_INTF_ADC_GET_TIMER: + { + audio_intf_adc_timer_poll(); + } + break; + + case AUD_INTF_ADC_PLAY: + { + audio_intf_adc_play_poll(); + } + break; + + case AUD_INTF_ADC_PAUSE: + { + audio_intf_adc_pause_poll(); + } + break; + + case AUD_INTF_ADC_LINEIN_TIMER: + { + audio_intf_adc_linein_timer_poll(); + } + break; + #endif // CFG_USE_AUD_DAC + + case AUD_INTF_SET_SAMPLE_RATE: + { + audio_intf_set_sample_rate_poll(); + } + break; + + case AUD_INTF_EXIT: + { + AUD_INTF_FATAL("exit aud intf\r\n"); + goto audio_exit; + } + break; + + default: + break; + } + } + } + +audio_exit: + + #if CFG_USE_AUD_DAC + GLOBAL_INT_DISABLE(); + status = ddev_close(aud_dac_hdl); + GLOBAL_INT_RESTORE(); + aud_dac_hdl = DD_HANDLE_UNVALID; + + err = rtos_deinit_timer(&audio_dac_fill_timer); + ASSERT(kNoErr == err); + #endif // CFG_USE_AUD_DAC + + #if CFG_USE_AUD_ADC + GLOBAL_INT_DISABLE(); + status = ddev_close(aud_adc_hdl); + GLOBAL_INT_RESTORE(); + aud_adc_hdl = DD_HANDLE_UNVALID; + + err = rtos_deinit_timer(&audio_adc_get_timer); + ASSERT(kNoErr == err); + + err = rtos_deinit_timer(&audio_adc_linein_timer); + ASSERT(kNoErr == err); + #endif // CFG_USE_AUD_ADC + + rtos_deinit_queue(&audio_msg_que); + audio_msg_que = NULL; + + audio_handle = NULL; + rtos_delete_thread(NULL); +} + +UINT32 audio_intf_init(void) +{ + int ret; + + if((!audio_handle) && (!audio_msg_que)) + { + + ret = rtos_init_queue(&audio_msg_que, + "audio_queue", + sizeof(AUDIO_MSG_T), + AUDIO_QITEM_COUNT); + if (kNoErr != ret) + { + AUD_INTF_FATAL("audio_intf ceate queue failed\r\n"); + return kGeneralErr; + } + + ret = rtos_create_thread(&audio_handle, + BEKEN_DEFAULT_WORKER_PRIORITY, + "audio", + (beken_thread_function_t)audio_intf_main, + 1024, + NULL); + if (ret != kNoErr) + { + rtos_deinit_queue(&audio_msg_que); + audio_msg_que = NULL; + AUD_INTF_FATAL("Error: Failed to create audio_intf: %d\r\n", ret); + return kGeneralErr; + } + } + + return kNoErr; +} + +void audio_intf_uninit(void) +{ + int ret; + + if((audio_handle) && (audio_msg_que)) + { + audio_intf_send_msg(AUD_INTF_EXIT); + + // wait untill task exit + while(audio_handle) + rtos_delay_milliseconds(100); + } +} + +void audio_intf_send_msg(u32 new_msg) +{ + OSStatus ret; + AUDIO_MSG_T msg; + + if(audio_msg_que) { + msg.audio_msg = new_msg; + + ret = rtos_push_to_queue(&audio_msg_que, &msg, BEKEN_NO_WAIT); + if(kNoErr != ret) + { + os_printf("audio_intf_send_msg failed\r\n"); + } + } +} + + +#endif // CFG_USE_AUDIO diff --git a/beken_os/beken378/func/bk7011_cal/bk7011_cal.c b/beken_os/beken378/func/bk7011_cal/bk7011_cal.c new file mode 100755 index 0000000..11e3ec6 --- /dev/null +++ b/beken_os/beken378/func/bk7011_cal/bk7011_cal.c @@ -0,0 +1,3 @@ +#include "include.h" + +// eof diff --git a/beken_os/beken378/func/bk7011_cal/bk7011_cal.h b/beken_os/beken378/func/bk7011_cal/bk7011_cal.h new file mode 100755 index 0000000..e5c0c38 --- /dev/null +++ b/beken_os/beken378/func/bk7011_cal/bk7011_cal.h @@ -0,0 +1,14 @@ +#ifndef _BK7011_CAL_H_ +#define _BK7011_CAL_H_ + +#if (CFG_SOC_NAME == SOC_BK7231) +#include "bk7231_cal.h" +#elif (CFG_SOC_NAME == SOC_BK7231U) +#include "bk7231U_cal.h" +#elif (CFG_SOC_NAME == SOC_BK7231N) +#include "bk7231N_cal.h" +#elif (CFG_SOC_NAME == SOC_BK7221U) +#include "bk7221U_cal.h" +#endif + +#endif // _BK7011_CAL_H_ diff --git a/beken_os/beken378/func/bk7011_cal/bk7221U_cal.c b/beken_os/beken378/func/bk7011_cal/bk7221U_cal.c new file mode 100755 index 0000000..918cf46 --- /dev/null +++ b/beken_os/beken378/func/bk7011_cal/bk7221U_cal.c @@ -0,0 +1,5091 @@ +#include "include.h" + +#if (CFG_SOC_NAME == SOC_BK7221U) +#include "arm_arch.h" +#include "target_util_pub.h" +#include "mem_pub.h" +#include "drv_model_pub.h" +#include "sys_ctrl_pub.h" +#include "phy.h" +#include "bk7011_cal_pub.h" +#include "bk7011_cal.h" +#include +#include "flash_pub.h" + +#ifdef INCLUDE_OS +#include "cmd_evm.h" +#include "temp_detect_pub.h" +#endif + +#define CAL_RESULT_TO_FLASH 0 +#define CAL_RESULT_FLASH_ADDR 0x000F1000UL + +#if CFG_SUPPORT_CALIBRATION +#define TX_WANTED_POWER_CAL 0 +#define TX_IQ_POWER_CAL 1 +#define TX_IQ_LOOPBACK_POWER_CAL 2 +#define TX_DC_CAL 0 +#define TX_DC_CAL_IQ 1 +#define TX_DC_LOOPBACK_CAL_IQ 2 +#define TX_GAIN_IMB_CAL 0 +#define TX_GAIN_LOOPBACK_IMB_CAL 1 +#define TX_PHASE_IMB_CAL 0 +#define TX_PHASE_LOOPBACK_IMB_CAL 1 + + +#define CAL_DEBUG 1 +#include "uart_pub.h" +#if CAL_DEBUG +#define CAL_PRT null_prf +#define CAL_WARN null_prf// warning_prf +#define CAL_FATAL fatal_prf +#define CAL_TIM_PRT os_printf +#define CAL_FLASH_PRT os_printf +#else +#define CAL_PRT null_prf +#define CAL_WARN null_prf +#define CAL_FATAL null_prf +#define CAL_TIM_PRT null_prf +#define CAL_FLASH_PRT null_prf +#endif + + +extern void bk7011_cal_pll(void); + + +static INT32 gtx_dc_n = 0;//the times of first dc cal. +static UINT32 gst_rx_adc = CAL_DELAY100US; +static UINT32 gst_sar_adc = CAL_DELAY05US; +//static UINT8 pwr_nstep = 0; + +#define BK7231_56PIN_BOARD 1 +#define BK7231_32PIN_BOARD 2 +#define BK7231_32PIN_TZH_BOARD 3 +#define BK7231U_BOARD 4 + +#define TRX_REG_0XA_VAL 0x036F1055 +#define TRX_REG_0XB_VAL 0x85248957 +#define TRX_REG_0XC_VAL 0x05228654 +#define TRX_REG_0XD_VAL 0xDDF90339 +#define TSSI_POUT_TH 0x50 + +#if 0 +int TXIQ_IMB_TSSI_TH = 105; // 75-165 +15 +#else +#define TXIQ_IMB_TSSI_TH 70 +#endif + +#if 0 +int TXIQ_IMB_TSSI_TH_LOOPBACK = 90; // 20-250 +20 +#else +#define TXIQ_IMB_TSSI_TH_LOOPBACK 60 +#endif + +#define No_TXPOWERCAL 0 +#if 0 +int TXIQ_TSSI_TH = 0x40; +#else +#define TXIQ_TSSI_TH 0x40 +#endif +#define TRX_REG_0XD_TX_IQ_VAL 0xD9FF0338 //0xD9FF0338 //0214 +#define TRX_REG_0XD_TX_LOOPBACK_IQ_VAL 0xD9FE7FF1 //0214 0xD9FE7FF1 + +#define TRX_REG_0XC_TXLO_LEAKAGE_VAL 0x5228100 + +#define TRX_REG_0XC_RXIQ_VAL 0x5228565 // 1A244ED //0215 increasse gain due to load antenna 01A244DD +#define TRX_REG_0XE_RXIQ_VAL 0xD9F87FF1 //0214 FDF87FF1 + + +#if 0 +INT32 gi_dc_tx_pa_dgainPA30 = 2; // 1-5 +INT32 gi_dc_tx_pa_dgainbuf30 = 6; // 4-7 +INT32 gi_gain_tx_pa_dgainPA30 = 2; // 1-4 +INT32 gi_gain_tx_pa_dgainbuf30 = 5; // 2-5 +#else +#define gi_dc_tx_pa_dgainPA30 7 +#define gi_dc_tx_pa_dgainbuf30 6 +#define gi_gain_tx_pa_dgainPA30 2 +#define gi_gain_tx_pa_dgainbuf30 4 +#endif + +#if 0 +INT32 gi_dc_tx_loopback_pa_dgainPA30 = 5; // 3-5 +INT32 gi_dc_tx_loopback_pa_dgainbuf30 = 7; // 4-7 +INT32 gi_gain_tx_loopback_pa_dgainPA30 = 6; // 3-7 +INT32 gi_gain_tx_loopback_pa_dgainbuf30 = 6; // 3-7 +INT32 gi_phase_tx_loopback_pa_dgainPA30 = 6; // 3-7 +INT32 gi_phase_tx_loopback_pa_dgainbuf30 = 5; // 3-7 +#else +#define gi_dc_tx_loopback_pa_dgainPA30 7 +#define gi_dc_tx_loopback_pa_dgainbuf30 6 +#define gi_gain_tx_loopback_pa_dgainPA30 6 +#define gi_gain_tx_loopback_pa_dgainbuf30 4 +#define gi_phase_tx_loopback_pa_dgainPA30 6 +#define gi_phase_tx_loopback_pa_dgainbuf30 4 +#endif + +#if 0 +INT32 gi_cal_rx_iq_pa_dgainPA30 = 5; // 3-7 +INT32 gi_cal_rx_iq_pa_dgainbuf30 = 5; // 3-7 +#else +#define gi_cal_rx_iq_pa_dgainPA30 4 +#define gi_cal_rx_iq_pa_dgainbuf30 5 +#endif + + +#ifdef CALIBRATE_TIMES +#define SCAN_IQ_FILTER_CORNER +#undef SCAN_IQ_FILTER_CORNER + +int calibrate_times_all = CALIBRATE_TIMES; +int calibrate_time = 0; + +int *p_gbias_after_cal_array = NULL; +int *p_gav_tssi_array = NULL; +int *p_gtx_ifilter_corner_array = NULL; +int *p_gtx_qfilter_corner_array = NULL; +#ifdef SCAN_IQ_FILTER_CORNER +int index_test[500*5]; +float float2_test[500*5]; +UINT32 g_sctrl_bias_reg = 0; +UINT32 *p_g_sctrl_bias_reg_array = NULL; +int grx_avg_i_14M = 0; +int grx_avg_i_14M2 = 0; +int grx_avg_q_14M = 0; +int grx_avg_q_14M2 = 0; +int *p_grx_avg_i_14M_array = NULL; +int *p_grx_avg_i_14M_array2 = NULL; +int *p_grx_avg_q_14M_array = NULL; +int *p_grx_avg_q_14M_array2 = NULL; +#endif +int *p_rx_amp_err_rd_array = NULL; +int *p_rx_phase_err_rd_array = NULL; +int *p_rx_ty2_rd_array = NULL; + +int *p_gtx_i_dc_comp_array = NULL; +int *p_gtx_q_dc_comp_array = NULL; +int *p_gtx_i_gain_comp_array = NULL; +int *p_gtx_q_gain_comp_array = NULL; +int *p_gtx_phase_comp_array = NULL; + +int *p_gtx_i_dc_comp_temp_array = NULL; +int *p_gtx_q_dc_comp_temp_array = NULL; +int *p_gtx_i_gain_comp_temp_array = NULL; +int *p_gtx_q_gain_comp_temp_array = NULL; +int *p_gtx_phase_comp_temp_array = NULL; + +int *p_g_rx_dc_gain_tab_array = NULL; +/*int rx_amp_err_rd_array[CALIBRATE_TIMES]; +int rx_phase_err_rd_array[CALIBRATE_TIMES]; +int gtx_i_gain_comp_temp_array[CALIBRATE_TIMES]; +int gtx_q_gain_comp_temp_array[CALIBRATE_TIMES]; +int gtx_phase_comp_temp_array[CALIBRATE_TIMES]; +int gtx_i_gain_comp_array[CALIBRATE_TIMES]; +int gtx_q_gain_comp_array[CALIBRATE_TIMES]; +int gtx_phase_comp_array[CALIBRATE_TIMES];*/ +#endif + +#define TRX_BEKEN_REGS \ +{ \ + 0x00039042, /* 00-R0x00, // */ \ + 0xF45B747B, /* 01-R0x01, // */ \ + 0x4CAD2213, /* 02-R0x02, // */ \ + 0x7C945A75, /* 03-R0x03, // */ \ + 0x13D0110F, /* 04-R0x04, // */ \ + 0x1804AA47, /* 05-R0x05, // */ \ + 0x5FA44100, /* 06-R0x06, // */ \ + 0x000020F5, /* 07-R0x07, // 00F5:4th;20F5:2nd */ \ + 0x072C29DE, /* 08-R0x08, // */ \ + 0x000163AF, /* 09-R0x09, // */ \ + TRX_REG_0XA_VAL, /* 10-R0x0A, // */ \ + TRX_REG_0XB_VAL, /* 11-R0x0B, // */ \ + TRX_REG_0XC_VAL, /* 12-R0x0C, // */ \ + 0xDDF90339, /* 13-R0x0D, // */ \ + 0xDA01BCF0, /* 14-R0x0E, // */ \ + 0x00018000, /* 15-R0x0F, // */ \ + 0xD0000000, /* 16-R0x10, // */ \ + 0x00000000, /* 17-R0x11, // */ \ + 0xF0090481, /* 18-R0x12, // */ \ + 0x7B305ECC, /* 19-R0x13, // */ \ + 0x827C827C, /* 20-R0x14, // */ \ + 0x86788678, /* 21-R0x15, // */ \ + 0x8C748C74, /* 22-R0x16, // */ \ + 0xA45F9868, /* 23-R0x17, // */ \ + 0xA45FA45F, /* 24-R0x18, // */ \ + 0xA55EA45F, /* 25-R0x19, // */ \ + 0xA55DA55E, /* 26-R0x1A, // */ \ + 0xA55DA55D, /* 27-R0x1B, // */ \ + 0x20000000 /* 28-R0x1C, // */ \ +}; + +#define RC_BEKEN_REGS \ +{ \ + 0x00000009, /* 00-R0x0, 0x0000; */ \ + 0xF0000000, /* 01-R0x1, 0x0004; */ \ + 0x00000030, /* 02-R0x5, 0x0014; */ \ + 0x00010001, /* 03-R0x8, 0x0020; */ \ + 0x000100e0, /* 04-R0xB, 0x002C; */ \ + 0x00010070, /* 05-R0xE, 0x0038; */ \ + 0x00010001, /* 06-R0x11, 0x0044; */ \ + 0x00010005, /* 07-R0x19, 0x0064; */ \ + 0x00000002, /* 08-R0x1C, 0x0070; */ \ + 0x0000012c, /* 09-R0x1E, 0x0078; */ \ + 0x1002DF4B, /* 10-R0x3C, 0x00F0; */ \ + 0x00000000, /* 11-R0x3E, 0x00F8; */ \ + 0x03E803CB, /* 12-R0x3F, 0x00FC; */ \ + 0x00000001, /* 13-R0x40, 0x0100; */ \ + 0x00000000, /* 14-R0x41, 0x0104; */ \ + 0x02000041, /* 15-R0x42, 0x0108; */ \ + 0x018B018B, /* 16-R0x4C, 0x0130; */ \ + 0x2CC02000, /* 17-R0x4D, 0x0134; */ \ + 0x02000200, /* 18-R0x4F, 0x013C; */ \ + 0x03ff03ff, /* 19-R0x50, 0x0140; */ \ + 0x02000200, /* 20-R0x51, 0x0144; */ \ + 0x44108800, /* 21-R0x52, 0x0148; */ \ + (0x00025600|((TSSI_POUT_TH)<<1)), /* 22-R0x54, 0x0150; */ \ + 0x00000000, /* 23-R0x55, 0x0154; */ \ + 0x80000064, /* 24-R0x5C, 0x0170; */ \ + 0x00000005, /* 25-R0x4E, 0x0138; */ \ + 0x00000000, /* 26-R0x5A, 0x0168; */ \ + 0x00000000, /* 27-R0x5B, 0x016C; */ \ + 0x00000000, /* 28-R0x6A, 0x01A8; */ \ + 0x00000000, /* 29-R0x70, 0x01C0; */ \ + 0x00000000, /* 30-R0x71, 0x01C4; */ \ + 0x00000000, /* 31-R0x72, 0x01C8; */ \ + 0x00000000, /* 32-R0x73, 0x01CC; */ \ + 0x00000000, /* 33-R0x74, 0x01D0; */ \ + 0x00000000, /* 34-R0x75, 0x01D4; */ \ + 0x00000000, /* 35-R0x76, 0x01D8; */ \ + 0x00000000, /* 36-R0x77, 0x01DC; */ \ +}; + +const static INT32 bk7011_trx_val1[32] = TRX_BEKEN_REGS; +const static INT32 bk7011_rc_val1[37] = RC_BEKEN_REGS; + +static INT32 bk7011_trx_val[32] = TRX_BEKEN_REGS; +static INT32 bk7011_rc_val[37] = RC_BEKEN_REGS; + +//static UINT8 gstat_cal = 1; // 1: calibration not done, 0: done + +//INT32 gconst_iqcal_p = 0xB0;//117; 0x10-0x80 0x10 +#define gconst_iqcal_p 0x130 + +INT32 gconst_pout = 0x210; +INT32 gav_tssi = 0; +INT32 gav_tssi_temp = 0; +INT32 grc_reg_map[32]; +UINT8 gbias_after_cal = 0; + +//INT32 gpll_lock_err = 1; + +//INT32 gadda_map[6]; +//INT32 gdc_goldval[32]= {0}; +//INT32 g_tri_offset = 0; + +INT32 gtx_dcorMod = 0x4; +INT32 gtx_dcorPA = 0x8; +INT32 gtx_pre_gain = 0x7; + +INT32 gtx_dcorMod_temp = 0x4; +INT32 gtx_dcorPA_temp = 0x8; +INT32 gtx_pre_gain_temp = 0x7; + +INT32 gtx_dcorMod_temp_loopback = 0x4; +INT32 gtx_dcorPA_temp_loopback = 0x8; +INT32 gtx_pre_gain_temp_loopback = 0x7; + +INT32 gtx_i_dc_comp_loopback = 0x202; +INT32 gtx_q_dc_comp_loopback = 0x1ff; + +INT32 gtx_i_gain_comp_loopback = 0x3ff; +INT32 gtx_q_gain_comp_loopback = 0x3f3; + +INT32 gtx_i_dc_comp = 0x200; +INT32 gtx_q_dc_comp = 0x200; + +INT32 gtx_i_gain_comp = 0x3ff; +INT32 gtx_q_gain_comp = 0x3ff; + +INT32 gtx_ifilter_corner = 0x10; +INT32 gtx_qfilter_corner = 0x10; + +INT32 gtx_phase_comp_loopback = 0x200; +INT32 gtx_phase_ty2_loopback = 0x200; + +INT32 gtx_phase_comp = 0x200; +INT32 gtx_phase_ty2 = 0x200; + +INT32 gtx_power_cal_mode = TX_WANTED_POWER_CAL; +INT32 gtx_dc_cal_mode = TX_DC_CAL; +INT32 gtx_gain_imb_cal_mode = TX_GAIN_IMB_CAL; +INT32 gtx_phase_imb_cal_mode = TX_PHASE_IMB_CAL; + +INT32 gtx_band = 0x4a; + +INT32 g_rx_dc_gain_tab[8] = +{ + 0x827C827C, + 0x86788678, + 0x8C748C74, + 0xA45F9868, + 0xA45FA45F, + 0xA55EA45F, + 0xA55DA55E, + 0xA55DA55D +}; + +INT32 grx_amp_err_wr = 0x200; +INT32 grx_phase_err_wr = 0x041; + +#define PWRI(gain, rb_28_31, rc_8_11, rc_4_7, rc_0_3, ra_8_13, ra_0_1) \ +{ \ + .unuse = 0, \ + .pregain = gain, \ + .regb_28_31 = rb_28_31, \ + .regc_8_11 = rc_8_11, \ + .regc_4_7 = rc_4_7, \ + .regc_0_3 = rc_0_3, \ + .rega_8_13 = ra_8_13, \ + .rega_0_1 = ra_0_1 \ +} + +PWR_REGS cfg_tab_b[32] = { + // pregain REGB<31:28> REGC<11:8> REGC<7:4> REGC<3:0> REGA<13:8> REGA<1:0> +PWRI( 0x6 , 0x8, 2, 2, 2, 0x20, 0x0 ), // 0 +PWRI( 0xF , 0x8, 2, 3, 3, 0x20, 0x0 ), // 1 +PWRI( 0x5 , 0x8, 2, 3, 3, 0x20, 0x0 ), // 2 +PWRI( 0x12 , 0x8, 2, 4, 4, 0x20, 0x0 ), // 3 +PWRI( 0x10 , 0x8, 2, 4, 4, 0x20, 0x0 ), // 4 +PWRI( 0xC , 0x8, 2, 4, 4, 0x20, 0x0 ), // 5 +PWRI( 0x1A , 0x8, 4, 4, 4, 0x20, 0x0 ), // 6 +PWRI( 0x18 , 0x8, 4, 4, 4, 0x30, 0x0 ), // 7 +PWRI( 0x16 , 0x8, 4, 4, 4, 0x30, 0x0 ), // 8 +PWRI( 0x14 , 0x8, 4, 4, 4, 0x30, 0x0 ), // 9 +PWRI( 0x12 , 0x8, 4, 4, 4, 0x30, 0x0 ), // 10 +PWRI( 0x1B , 0x8, 5, 4, 4, 0x30, 0x0 ), // 11 +PWRI( 0x19 , 0x8, 5, 4, 4, 0x30, 0x0 ), // 12 +PWRI( 0x17 , 0x8, 5, 4, 4, 0x30, 0x0 ), // 13 +PWRI( 0x15 , 0x8, 5, 4, 4, 0x30, 0x0 ), // 14 +PWRI( 0x13 , 0x8, 5, 4, 4, 0x30, 0x0 ), // 15 +PWRI( 0x11 , 0x8, 5, 4, 4, 0x30, 0x0 ), // 16 +PWRI( 0xF , 0x8, 5, 4, 4, 0x30, 0x0 ), // 17 +PWRI( 0xD , 0x8, 5, 4, 4, 0x30, 0x0 ), // 18 +PWRI( 0xB , 0x8, 5, 4, 4, 0x30, 0x0 ), // 19 +PWRI( 0x9 , 0x8, 5, 4, 4, 0x30, 0x0 ), // 20 +PWRI( 0x11 , 0x8, 6, 4, 4, 0x30, 0x0 ), // 21 +PWRI( 0xF , 0x8, 6, 4, 4, 0x30, 0x0 ), // 22 +PWRI( 0xD , 0x8, 6, 4, 4, 0x30, 0x0 ), // 23 +PWRI( 0xB , 0x8, 6, 4, 4, 0x30, 0x0 ), // 24 +PWRI( 0xF , 0x8, 6, 5, 4, 0x30, 0x0 ), // 25 +PWRI( 0xE , 0x8, 6, 5, 4, 0x30, 0x0 ), // 26 +PWRI( 0xD , 0x8, 6, 5, 4, 0x30, 0x0 ), // 27 +PWRI( 0xB , 0x8, 6, 5, 4, 0x30, 0x0 ), // 28 +PWRI( 0x9 , 0x8, 6, 5, 4, 0x30, 0x0 ), // 29 +PWRI( 0x7 , 0x8, 6, 5, 4, 0x30, 0x0 ), // 30 +PWRI( 0x5 , 0x8, 6, 5, 4, 0x30, 0x0 ), // 31 +}; + + + +PWR_REGS cfg_tab_g[32] = { + // pregain REGB<31:28> REGC<11:8> REGC<7:4> REGC<3:0> REGA<13:8> REGA<1:0> +PWRI( 0x0 , 8, 2, 3, 3, 0x10, 0x1 ), // 0 +PWRI( 0xB , 8, 4, 4, 3, 0x10, 0x1 ), // 1 +PWRI( 0x7 , 8, 4, 4, 3, 0x10, 0x1 ), // 2 +PWRI( 0x0 , 8, 4, 4, 3, 0x10, 0x1 ), // 3 +PWRI( 0x15 , 8, 5, 4, 4, 0x10, 0x1 ), // 4 +PWRI( 0x13 , 8, 5, 4, 4, 0x10, 0x1 ), // 5 +PWRI( 0x11 , 8, 5, 4, 4, 0x10, 0x1 ), // 6 +PWRI( 0xF , 8, 5, 4, 4, 0x10, 0x1 ), // 7 +PWRI( 0xC , 8, 5, 4, 4, 0x10, 0x1 ), // 8 +PWRI( 0xA , 8, 5, 4, 4, 0x10, 0x1 ), // 9 +PWRI( 0x8 , 8, 5, 4, 4, 0x10, 0x1 ), // 10 +PWRI( 0x6 , 8, 5, 4, 4, 0x10, 0x1 ), // 11 +PWRI( 0xF , 8, 6, 4, 4, 0x10, 0x1 ), // 12 +PWRI( 0xD , 8, 6, 4, 4, 0x10, 0x1 ), // 13 +PWRI( 0xB , 8, 6, 4, 4, 0x10, 0x1 ), // 14 +PWRI( 0x9 , 8, 6, 4, 4, 0x10, 0x1 ), // 15 +PWRI( 0x7 , 8, 6, 4, 4, 0x10, 0x1 ), // 16 +PWRI( 0x5 , 8, 6, 4, 4, 0x10, 0x1 ), // 17 +PWRI( 0x3 , 8, 6, 4, 4, 0x10, 0x1 ), // 18 +PWRI( 0x0 , 8, 6, 4, 4, 0x10, 0x1 ), // 19 +PWRI( 0x5 , 8, 6, 5, 4, 0x10, 0x1 ), // 20 +PWRI( 0x3 , 8, 6, 5, 4, 0x10, 0x1 ), // 21 +PWRI( 0x0 , 8, 6, 5, 4, 0x10, 0x1 ), // 22 +PWRI( 0x8 , 8, 6, 5, 5, 0x10, 0x1 ), // 23 +PWRI( 0x6 , 8, 6, 5, 5, 0x10, 0x1 ), // 24 +PWRI( 0x4 , 8, 6, 5, 5, 0x10, 0x1 ), // 25 +PWRI( 0x2 , 8, 6, 5, 5, 0x10, 0x1 ), // 26 +PWRI( 0x0 , 8, 6, 5, 5, 0x10, 0x1 ), // 27 +PWRI( 0x2 , 8, 6, 6, 5, 0x10, 0x1 ), // 28 +PWRI( 0x0 , 8, 6, 6, 5, 0x10, 0x1 ), // 29 +PWRI( 0x6 , 8, 7, 6, 5, 0x10, 0x1 ), // 30 +PWRI( 0x4 , 8, 7, 6, 5, 0x10, 0x1 ), // 31 +}; + +struct BK7011RCBEKEN_TypeDef BK7011RCBEKEN = +{ + (volatile BK7011_RC_BEKEN_REG0x0_TypeDef *) (RC_BEKEN_BASE + 0 * 4), + (volatile BK7011_RC_BEKEN_REG0x1_TypeDef *) (RC_BEKEN_BASE + 1 * 4), + (volatile BK7011_RC_BEKEN_REG0x5_TypeDef *) (RC_BEKEN_BASE + 5 * 4), + (volatile BK7011_RC_BEKEN_REG0x8_TypeDef *) (RC_BEKEN_BASE + 8 * 4), + (volatile BK7011_RC_BEKEN_REG0xB_TypeDef *) (RC_BEKEN_BASE + 11 * 4), + (volatile BK7011_RC_BEKEN_REG0xE_TypeDef *) (RC_BEKEN_BASE + 14 * 4), + (volatile BK7011_RC_BEKEN_REG0x11_TypeDef *)(RC_BEKEN_BASE + 17 * 4), + (volatile BK7011_RC_BEKEN_REG0x19_TypeDef *)(RC_BEKEN_BASE + 25 * 4), + (volatile BK7011_RC_BEKEN_REG0x1C_TypeDef *)(RC_BEKEN_BASE + 28 * 4), + (volatile BK7011_RC_BEKEN_REG0x1E_TypeDef *)(RC_BEKEN_BASE + 30 * 4), + (volatile BK7011_RC_BEKEN_REG0x3C_TypeDef *)(RC_BEKEN_BASE + 60 * 4), + (volatile BK7011_RC_BEKEN_REG0x3E_TypeDef *)(RC_BEKEN_BASE + 62 * 4), + (volatile BK7011_RC_BEKEN_REG0x3F_TypeDef *)(RC_BEKEN_BASE + 63 * 4), + (volatile BK7011_RC_BEKEN_REG0x40_TypeDef *)(RC_BEKEN_BASE + 64 * 4), + (volatile BK7011_RC_BEKEN_REG0x41_TypeDef *)(RC_BEKEN_BASE + 65 * 4), + (volatile BK7011_RC_BEKEN_REG0x42_TypeDef *)(RC_BEKEN_BASE + 66 * 4), + (volatile BK7011_RC_BEKEN_REG0x4C_TypeDef *)(RC_BEKEN_BASE + 76 * 4), + (volatile BK7011_RC_BEKEN_REG0x4D_TypeDef *)(RC_BEKEN_BASE + 77 * 4), + (volatile BK7011_RC_BEKEN_REG0x4E_TypeDef *)(RC_BEKEN_BASE + 78 * 4), + (volatile BK7011_RC_BEKEN_REG0x4F_TypeDef *)(RC_BEKEN_BASE + 79 * 4), + (volatile BK7011_RC_BEKEN_REG0x50_TypeDef *)(RC_BEKEN_BASE + 80 * 4), + (volatile BK7011_RC_BEKEN_REG0x51_TypeDef *)(RC_BEKEN_BASE + 81 * 4), + (volatile BK7011_RC_BEKEN_REG0x52_TypeDef *)(RC_BEKEN_BASE + 82 * 4), + (volatile BK7011_RC_BEKEN_REG0x54_TypeDef *)(RC_BEKEN_BASE + 84 * 4), + (volatile BK7011_RC_BEKEN_REG0x55_TypeDef *)(RC_BEKEN_BASE + 85 * 4), + (volatile BK7011_RC_BEKEN_REG0x5A_TypeDef *)(RC_BEKEN_BASE + 90 * 4), + (volatile BK7011_RC_BEKEN_REG0x5B_TypeDef *)(RC_BEKEN_BASE + 91 * 4), + (volatile BK7011_RC_BEKEN_REG0x5C_TypeDef *)(RC_BEKEN_BASE + 92 * 4), + (volatile BK7011_RC_BEKEN_REG0x6A_TypeDef *)(RC_BEKEN_BASE + 106 * 4), + (volatile BK7011_RC_BEKEN_REG0x70_TypeDef *)(RC_BEKEN_BASE + 112 * 4), + (volatile BK7011_RC_BEKEN_REG0x71_TypeDef *)(RC_BEKEN_BASE + 113 * 4), + (volatile BK7011_RC_BEKEN_REG0x72_TypeDef *)(RC_BEKEN_BASE + 114 * 4), + (volatile BK7011_RC_BEKEN_REG0x73_TypeDef *)(RC_BEKEN_BASE + 115 * 4), + (volatile BK7011_RC_BEKEN_REG0x74_TypeDef *)(RC_BEKEN_BASE + 116 * 4), + (volatile BK7011_RC_BEKEN_REG0x75_TypeDef *)(RC_BEKEN_BASE + 117 * 4), + (volatile BK7011_RC_BEKEN_REG0x76_TypeDef *)(RC_BEKEN_BASE + 118 * 4), + (volatile BK7011_RC_BEKEN_REG0x77_TypeDef *)(RC_BEKEN_BASE + 119 * 4), +}; + +struct BK7011TRxV2A_TypeDef BK7011TRX = +{ + (BK7011_TRxV2A_REG0x0_TypeDef *)(&grc_reg_map[0]), + (BK7011_TRxV2A_REG0x1_TypeDef *)(&grc_reg_map[1]), + (BK7011_TRxV2A_REG0x2_TypeDef *)(&grc_reg_map[2]), + (BK7011_TRxV2A_REG0x3_TypeDef *)(&grc_reg_map[3]), + (BK7011_TRxV2A_REG0x4_TypeDef *)(&grc_reg_map[4]), + (BK7011_TRxV2A_REG0x5_TypeDef *)(&grc_reg_map[5]), + (BK7011_TRxV2A_REG0x6_TypeDef *)(&grc_reg_map[6]), + (BK7011_TRxV2A_REG0x7_TypeDef *)(&grc_reg_map[7]), + (BK7011_TRxV2A_REG0x8_TypeDef *)(&grc_reg_map[8]), + (BK7011_TRxV2A_REG0x9_TypeDef *)(&grc_reg_map[9]), + (BK7011_TRxV2A_REG0xA_TypeDef *)(&grc_reg_map[10]), + (BK7011_TRxV2A_REG0xB_TypeDef *)(&grc_reg_map[11]), + (BK7011_TRxV2A_REG0xC_TypeDef *)(&grc_reg_map[12]), + (BK7011_TRxV2A_REG0xD_TypeDef *)(&grc_reg_map[13]), + (BK7011_TRxV2A_REG0xE_TypeDef *)(&grc_reg_map[14]), + (BK7011_TRxV2A_REG0xF_TypeDef *)(&grc_reg_map[15]), + (BK7011_TRxV2A_REG0x10_TypeDef *)(&grc_reg_map[16]), + (BK7011_TRxV2A_REG0x11_TypeDef *)(&grc_reg_map[17]), + (BK7011_TRxV2A_REG0x12_TypeDef *)(&grc_reg_map[18]), + (BK7011_TRxV2A_REG0x13_TypeDef *)(&grc_reg_map[19]), + (BK7011_TRxV2A_REG0x14_TypeDef *)(&grc_reg_map[20]), + (BK7011_TRxV2A_REG0x15_TypeDef *)(&grc_reg_map[21]), + (BK7011_TRxV2A_REG0x16_TypeDef *)(&grc_reg_map[22]), + (BK7011_TRxV2A_REG0x17_TypeDef *)(&grc_reg_map[23]), + (BK7011_TRxV2A_REG0x18_TypeDef *)(&grc_reg_map[24]), + (BK7011_TRxV2A_REG0x19_TypeDef *)(&grc_reg_map[25]), + (BK7011_TRxV2A_REG0x1A_TypeDef *)(&grc_reg_map[26]), + (BK7011_TRxV2A_REG0x1B_TypeDef *)(&grc_reg_map[27]), + (BK7011_TRxV2A_REG0x1C_TypeDef *)(&grc_reg_map[28]), +}; + +struct BK7011TRxV2A_TypeDef BK7011TRXONLY = +{ + (volatile BK7011_TRxV2A_REG0x0_TypeDef *) (TRX_BEKEN_BASE + 0 * 4), + (volatile BK7011_TRxV2A_REG0x1_TypeDef *) (TRX_BEKEN_BASE + 1 * 4), + (volatile BK7011_TRxV2A_REG0x2_TypeDef *) (TRX_BEKEN_BASE + 2 * 4), + (volatile BK7011_TRxV2A_REG0x3_TypeDef *) (TRX_BEKEN_BASE + 3 * 4), + (volatile BK7011_TRxV2A_REG0x4_TypeDef *) (TRX_BEKEN_BASE + 4 * 4), + (volatile BK7011_TRxV2A_REG0x5_TypeDef *) (TRX_BEKEN_BASE + 5 * 4), + (volatile BK7011_TRxV2A_REG0x6_TypeDef *) (TRX_BEKEN_BASE + 6 * 4), + (volatile BK7011_TRxV2A_REG0x7_TypeDef *) (TRX_BEKEN_BASE + 7 * 4), + (volatile BK7011_TRxV2A_REG0x8_TypeDef *) (TRX_BEKEN_BASE + 8 * 4), + (volatile BK7011_TRxV2A_REG0x9_TypeDef *) (TRX_BEKEN_BASE + 9 * 4), + (volatile BK7011_TRxV2A_REG0xA_TypeDef *) (TRX_BEKEN_BASE + 10 * 4), + (volatile BK7011_TRxV2A_REG0xB_TypeDef *) (TRX_BEKEN_BASE + 11 * 4), + (volatile BK7011_TRxV2A_REG0xC_TypeDef *) (TRX_BEKEN_BASE + 12 * 4), + (volatile BK7011_TRxV2A_REG0xD_TypeDef *) (TRX_BEKEN_BASE + 13 * 4), + (volatile BK7011_TRxV2A_REG0xE_TypeDef *) (TRX_BEKEN_BASE + 14 * 4), + (volatile BK7011_TRxV2A_REG0xF_TypeDef *) (TRX_BEKEN_BASE + 15 * 4), + (volatile BK7011_TRxV2A_REG0x10_TypeDef *)(TRX_BEKEN_BASE + 16 * 4), + (volatile BK7011_TRxV2A_REG0x11_TypeDef *)(TRX_BEKEN_BASE + 17 * 4), + (volatile BK7011_TRxV2A_REG0x12_TypeDef *)(TRX_BEKEN_BASE + 18 * 4), + (volatile BK7011_TRxV2A_REG0x13_TypeDef *)(TRX_BEKEN_BASE + 19 * 4), + (volatile BK7011_TRxV2A_REG0x14_TypeDef *)(TRX_BEKEN_BASE + 20 * 4), + (volatile BK7011_TRxV2A_REG0x15_TypeDef *)(TRX_BEKEN_BASE + 21 * 4), + (volatile BK7011_TRxV2A_REG0x16_TypeDef *)(TRX_BEKEN_BASE + 22 * 4), + (volatile BK7011_TRxV2A_REG0x17_TypeDef *)(TRX_BEKEN_BASE + 23 * 4), + (volatile BK7011_TRxV2A_REG0x18_TypeDef *)(TRX_BEKEN_BASE + 24 * 4), + (volatile BK7011_TRxV2A_REG0x19_TypeDef *)(TRX_BEKEN_BASE + 25 * 4), + (volatile BK7011_TRxV2A_REG0x1A_TypeDef *)(TRX_BEKEN_BASE + 26 * 4), + (volatile BK7011_TRxV2A_REG0x1B_TypeDef *)(TRX_BEKEN_BASE + 27 * 4), + (volatile BK7011_TRxV2A_REG0x1C_TypeDef *)(TRX_BEKEN_BASE + 28 * 4), +}; + +void delay05us(INT32 num) +{ + volatile INT32 i, j; + //REG_WRITE((0x0802800+(18*4)), 0x02); + + for(i = 0; i < num; i ++) + { + for(j = 0; j < 5; j ++) + ; + } + //REG_WRITE((0x0802800+(18*4)), 0x00); +} + +void delay100us(INT32 num) +{ + volatile INT32 i, j; + //REG_WRITE((0x0802800+(18*4)), 0x02); + + for(i = 0; i < num; i ++) + { + for(j = 0; j < 1050; j ++) + ; + } + //REG_WRITE((0x0802800+(18*4)), 0x00); +} + + +#define CAL_WR_TRXREGS(reg) do{\ + while(BK7011RCBEKEN.REG0x1->value & (0x1 << reg));\ + BK7011TRXONLY.REG##reg->value = BK7011TRX.REG##reg->value;\ + cal_delay(6);\ + while(BK7011RCBEKEN.REG0x1->value & (0x1 << reg));\ + }while(0) + + +void rwnx_cal_load_default_result(void) +{ + gtx_dcorMod = (bk7011_trx_val[11] >> 12) & 0xf; + gtx_dcorPA = (bk7011_trx_val[12] >> 12) & 0xf; + gtx_pre_gain = (bk7011_rc_val[21] >> 16) & 0x1f; + + gtx_i_dc_comp = (bk7011_rc_val[18] >> 16) & 0x3ff; + gtx_q_dc_comp = bk7011_rc_val[18] & 0x3ff; + + gtx_i_gain_comp = (bk7011_rc_val[19] >> 16) & 0x3ff; + gtx_q_gain_comp = bk7011_rc_val[19] & 0x3ff; + + gtx_ifilter_corner = (bk7011_trx_val[6] >> 10) & 0x3f; + gtx_qfilter_corner = (bk7011_trx_val[6] >> 4) & 0x3f; + gtx_phase_comp = (bk7011_rc_val[20] >> 16) & 0x3ff; + gtx_phase_ty2 = bk7011_rc_val[20] & 0x3ff; + + gtx_band = (bk7011_trx_val[3] >> 17) & 0x7f; + + g_rx_dc_gain_tab[0] = bk7011_trx_val[20]; + g_rx_dc_gain_tab[1] = bk7011_trx_val[21]; + g_rx_dc_gain_tab[2] = bk7011_trx_val[22]; + g_rx_dc_gain_tab[3] = bk7011_trx_val[23]; + g_rx_dc_gain_tab[4] = bk7011_trx_val[24]; + g_rx_dc_gain_tab[5] = bk7011_trx_val[25]; + g_rx_dc_gain_tab[6] = bk7011_trx_val[26]; + g_rx_dc_gain_tab[7] = bk7011_trx_val[27]; + + grx_amp_err_wr = (bk7011_rc_val[15] >> 16) & 0x3ff; + grx_phase_err_wr = bk7011_rc_val[15] & 0x3ff; + + //gstat_cal = (bk7011_rc_val[16] >> 29) & 0x1; +} +/* +void printf_trx_rc_value(void) +{ + int i; + printf("printf_trx_rc_value:\r\n"); + for (i=0; i<32; i++) + { + printf("bk7011_trx_val[%d] = 0x%x\r\n", i, bk7011_trx_val[i]); + } + for (i=0; i<32; i++) + { + printf("bk7011_rc_val[%d] = 0x%x\r\n", i, bk7011_rc_val[i]); + } + + printf("BK7011RCBEKEN.REG0x0->value = 0x%x\r\n", BK7011RCBEKEN.REG0x0->value); + printf("BK7011RCBEKEN.REG0x1->value = 0x%x\r\n", BK7011RCBEKEN.REG0x1->value); + printf("BK7011RCBEKEN.REG0x5->value = 0x%x\r\n", BK7011RCBEKEN.REG0x5->value); + printf("BK7011RCBEKEN.REG0x8->value = 0x%x\r\n", BK7011RCBEKEN.REG0x8->value); + printf("BK7011RCBEKEN.REG0xB->value = 0x%x\r\n", BK7011RCBEKEN.REG0xB->value); + printf("BK7011RCBEKEN.REG0xE->value = 0x%x\r\n", BK7011RCBEKEN.REG0xE->value); + printf("BK7011RCBEKEN.REG0x11->value = 0x%x\r\n", BK7011RCBEKEN.REG0x11->value); + printf("BK7011RCBEKEN.REG0x19->value = 0x%x\r\n", BK7011RCBEKEN.REG0x19->value); + printf("BK7011RCBEKEN.REG0x1C->value = 0x%x\r\n", BK7011RCBEKEN.REG0x1C->value); + printf("BK7011RCBEKEN.REG0x1E->value = 0x%x\r\n", BK7011RCBEKEN.REG0x1E->value); + printf("BK7011RCBEKEN.REG0x3C->value = 0x%x\r\n", BK7011RCBEKEN.REG0x3C->value); + printf("BK7011RCBEKEN.REG0x3E->value = 0x%x\r\n", BK7011RCBEKEN.REG0x3E->value); + printf("BK7011RCBEKEN.REG0x3F->value = 0x%x\r\n", BK7011RCBEKEN.REG0x3F->value); + printf("BK7011RCBEKEN.REG0x40->value = 0x%x\r\n", BK7011RCBEKEN.REG0x40->value); + printf("BK7011RCBEKEN.REG0x41->value = 0x%x\r\n", BK7011RCBEKEN.REG0x41->value); + printf("BK7011RCBEKEN.REG0x42->value = 0x%x\r\n", BK7011RCBEKEN.REG0x42->value); + printf("BK7011RCBEKEN.REG0x4C->value = 0x%x\r\n", BK7011RCBEKEN.REG0x4C->value); + printf("BK7011RCBEKEN.REG0x4D->value = 0x%x\r\n", BK7011RCBEKEN.REG0x4D->value); + printf("BK7011RCBEKEN.REG0x4F->value = 0x%x\r\n", BK7011RCBEKEN.REG0x4F->value); + printf("BK7011RCBEKEN.REG0x50->value = 0x%x\r\n", BK7011RCBEKEN.REG0x50->value); + printf("BK7011RCBEKEN.REG0x51->value = 0x%x\r\n", BK7011RCBEKEN.REG0x51->value); + printf("BK7011RCBEKEN.REG0x52->value = 0x%x\r\n", BK7011RCBEKEN.REG0x52->value); + printf("BK7011RCBEKEN.REG0x54->value = 0x%x\r\n", BK7011RCBEKEN.REG0x54->value); + printf("BK7011RCBEKEN.REG0x55->value = 0x%x\r\n", BK7011RCBEKEN.REG0x55->value); + printf("BK7011RCBEKEN.REG0x5C->value = 0x%x\r\n", BK7011RCBEKEN.REG0x5C->value); + + printf("BK7011TRXONLY.REG0x0->value = 0x%x\r\n", BK7011TRXONLY.REG0x0->value); + printf("BK7011TRXONLY.REG0x1->value = 0x%x\r\n", BK7011TRXONLY.REG0x1->value); + printf("BK7011TRXONLY.REG0x2->value = 0x%x\r\n", BK7011TRXONLY.REG0x2->value); + printf("BK7011TRXONLY.REG0x3->value = 0x%x\r\n", BK7011TRXONLY.REG0x3->value); + printf("BK7011TRXONLY.REG0x4->value = 0x%x\r\n", BK7011TRXONLY.REG0x4->value); + printf("BK7011TRXONLY.REG0x5->value = 0x%x\r\n", BK7011TRXONLY.REG0x5->value); + printf("BK7011TRXONLY.REG0x6->value = 0x%x\r\n", BK7011TRXONLY.REG0x6->value); + printf("BK7011TRXONLY.REG0x7->value = 0x%x\r\n", BK7011TRXONLY.REG0x7->value); + printf("BK7011TRXONLY.REG0x8->value = 0x%x\r\n", BK7011TRXONLY.REG0x8->value); + printf("BK7011TRXONLY.REG0x9->value = 0x%x\r\n", BK7011TRXONLY.REG0x9->value); + printf("BK7011TRXONLY.REG0xA->value = 0x%x\r\n", BK7011TRXONLY.REG0xA->value); + printf("BK7011TRXONLY.REG0xB->value = 0x%x\r\n", BK7011TRXONLY.REG0xB->value); + printf("BK7011TRXONLY.REG0xC->value = 0x%x\r\n", BK7011TRXONLY.REG0xC->value); + printf("BK7011TRXONLY.REG0xD->value = 0x%x\r\n", BK7011TRXONLY.REG0xD->value); + printf("BK7011TRXONLY.REG0xE->value = 0x%x\r\n", BK7011TRXONLY.REG0xE->value); + printf("BK7011TRXONLY.REG0xF->value = 0x%x\r\n", BK7011TRXONLY.REG0xF->value); + printf("BK7011TRXONLY.REG0x10->value = 0x%x\r\n", BK7011TRXONLY.REG0x10->value); + printf("BK7011TRXONLY.REG0x11->value = 0x%x\r\n", BK7011TRXONLY.REG0x11->value); + printf("BK7011TRXONLY.REG0x12->value = 0x%x\r\n", BK7011TRXONLY.REG0x12->value); + printf("BK7011TRXONLY.REG0x13->value = 0x%x\r\n", BK7011TRXONLY.REG0x13->value); + printf("BK7011TRXONLY.REG0x14->value = 0x%x\r\n", BK7011TRXONLY.REG0x14->value); + printf("BK7011TRXONLY.REG0x15->value = 0x%x\r\n", BK7011TRXONLY.REG0x15->value); + printf("BK7011TRXONLY.REG0x16->value = 0x%x\r\n", BK7011TRXONLY.REG0x16->value); + printf("BK7011TRXONLY.REG0x17->value = 0x%x\r\n", BK7011TRXONLY.REG0x17->value); + printf("BK7011TRXONLY.REG0x18->value = 0x%x\r\n", BK7011TRXONLY.REG0x18->value); + printf("BK7011TRXONLY.REG0x19->value = 0x%x\r\n", BK7011TRXONLY.REG0x19->value); + printf("BK7011TRXONLY.REG0x1A->value = 0x%x\r\n", BK7011TRXONLY.REG0x1A->value); + printf("BK7011TRXONLY.REG0x1B->value = 0x%x\r\n", BK7011TRXONLY.REG0x1B->value); +} +*/ +#ifdef CALIBRATE_TIMES +void calibration_result_print(void) +{ + int i, j; + int max, min; + + + os_printf("gtx_dcorMod_temp: 0x%x\r\n", gtx_dcorMod_temp); + os_printf("gtx_dcorPA_temp: 0x%x\r\n", gtx_dcorPA_temp); + os_printf("gtx_pre_gain_temp: 0x%x\r\n", gtx_pre_gain_temp); + + os_printf("gtx_dcorMod_temp_loopback: 0x%x\r\n", gtx_dcorMod_temp_loopback); + os_printf("gtx_dcorPA_temp_loopback: 0x%x\r\n", gtx_dcorPA_temp_loopback); + os_printf("gtx_pre_gain_temp_loopback: 0x%x\r\n", gtx_pre_gain_temp_loopback); + + max = -1100, min = 1100; +// printf("\r\ngbias_after_cal[] = \r\n"); + for (i=0; i p_gbias_after_cal_array[i]) + { + min = p_gbias_after_cal_array[i]; + } +// printf("%d\r\n", p_gbias_after_cal_array[i]); + } + printf("gbias_after_cal: min = %d, max = %d, max-min = %d\r\n", min, max, max-min); + + max = -1100, min = 1100; +// printf("\r\ngav_tssi[] = \r\n"); + for (i=0; i p_gav_tssi_array[i]) + { + min = p_gav_tssi_array[i]; + } +// printf("%d\r\n", p_gav_tssi_array[i]); + } + printf("gav_tssi: min = %d, max = %d, max-min = %d\r\n", min, max, max-min); + + printf("\r\n"); + + max = -1100, min = 1100; +// printf("\r\ngtx_ifilter_corner[] = \r\n"); + for (i=0; i p_gtx_ifilter_corner_array[i]) + { + min = p_gtx_ifilter_corner_array[i]; + } +#ifdef SCAN_IQ_FILTER_CORNER + printf("0x%x\t%d\t%d\t%d\r\n", p_g_sctrl_bias_reg_array[i], p_gtx_ifilter_corner_array[i], + p_grx_avg_i_14M_array[i], p_grx_avg_i_14M_array2[i]); + for (j=0; j<5; j++) + { + printf(" %d\t%f\r\n", index_test[i*5+j], float2_test[i*5+j]); + } +#endif + } + printf("gtx_ifilter_corner: min = %d, max = %d, max-min = %d\r\n", min, max, max-min); + + max = -1100, min = 1100; +// printf("\r\ngtx_qfilter_corner[] = \r\n"); + for (i=0; i p_gtx_qfilter_corner_array[i]) + { + min = p_gtx_qfilter_corner_array[i]; + } +#ifdef SCAN_IQ_FILTER_CORNER + printf("%d\t%d\t%d\r\n", p_gtx_qfilter_corner_array[i], p_grx_avg_q_14M_array[i], p_grx_avg_q_14M_array2[i]); +#endif + } + printf("gtx_qfilter_corner: min = %d, max = %d, max-min = %d\r\n", min, max, max-min); + + if (1) + { + int p_gtx_filter_corner[CALIBRATE_TIMES]; + for (i=0; i p_gtx_filter_corner[i]) + { + min = p_gtx_filter_corner[i]; + } + } + printf("p_gtx_filter_corner: min = %d, max = %d, max-min = %d\r\n", min, max, max-min); + } + + printf("\r\n"); + + max = -1100, min = 1100; +// printf("\r\ntx_i_dc_comp[] = \r\n"); + for (i=0; i p_gtx_i_dc_comp_array[i]) + { + min = p_gtx_i_dc_comp_array[i]; + } +// printf("%d\r\n", p_gtx_i_dc_comp_array[i]); + } + printf("tx_i_dc_comp: min = %d, max = %d, max-min = %d\r\n", min, max, max-min); + + max = -1100, min = 1100; +// printf("\r\ntx_q_dc_comp[] = \r\n"); + for (i=0; i p_gtx_q_dc_comp_array[i]) + { + min = p_gtx_q_dc_comp_array[i]; + } +// printf("%d\r\n", p_gtx_q_dc_comp_array[i]); + } + printf("tx_q_dc_comp: min = %d, max = %d, max-min = %d\r\n", min, max, max-min); + + max = -1100, min = 1100; +// printf("\r\ntx_i_gain_comp[] = \r\n"); + for (i=0; i p_gtx_i_gain_comp_array[i]) + { + min = p_gtx_i_gain_comp_array[i]; + } +// printf("%d\r\n", p_gtx_i_gain_comp_array[i]); + } + printf("tx_i_gain_comp: min = %d, max = %d, max-min = %d\r\n", min, max, max-min); + + max = -1100, min = 1100; +// printf("\r\ntx_q_gain_comp[] = \r\n"); + for (i=0; i p_gtx_q_gain_comp_array[i]) + { + min = p_gtx_q_gain_comp_array[i]; + } +// printf("%d\r\n", p_gtx_q_gain_comp_array[i]); + } + printf("tx_q_gain_comp: min = %d, max = %d, max-min = %d\r\n", min, max, max-min); + + max = -1100, min = 1100; +// printf("\r\ntx_phase_comp[] = \r\n"); + for (i=0; i p_gtx_phase_comp_array[i]) + { + min = p_gtx_phase_comp_array[i]; + } +// printf("%d\r\n", p_gtx_phase_comp_array[i]); + } + printf("tx_phase_comp: min = %d, max = %d, max-min = %d\r\n", min, max, max-min); + + printf("\r\n"); + + max = -1100, min = 1100; +// printf("\r\ntx_i_dc_comp_temp[] = \r\n"); + for (i=0; i p_gtx_i_dc_comp_temp_array[i]) + { + min = p_gtx_i_dc_comp_temp_array[i]; + } +// printf("%d\r\n", p_gtx_i_dc_comp_temp_array[i]); + } + printf("tx_i_dc_comp_temp: min = %d, max = %d, max-min = %d\r\n", min, max, max-min); + + max = -1100, min = 1100; +// printf("\r\ntx_q_dc_comp_temp[] = \r\n"); + for (i=0; i p_gtx_q_dc_comp_temp_array[i]) + { + min = p_gtx_q_dc_comp_temp_array[i]; + } +// printf("%d\r\n", p_gtx_q_dc_comp_temp_array[i]); + } + printf("tx_q_dc_comp_temp: min = %d, max = %d, max-min = %d\r\n", min, max, max-min); + + + max = -1100, min = 1100; +// printf("\r\ntx_i_gain_comp_temp[] = \r\n"); + for (i=0; i p_gtx_i_gain_comp_temp_array[i]) + { + min = p_gtx_i_gain_comp_temp_array[i]; + } +// printf("%d\r\n", p_gtx_i_gain_comp_temp_array[i]); + } + printf("tx_i_gain_comp_temp: min = %d, max = %d, max-min = %d\r\n", min, max, max-min); + + max = -1100, min = 1100; +// printf("\r\ntx_q_gain_comp_temp[] = \r\n"); + for (i=0; i p_gtx_q_gain_comp_temp_array[i]) + { + min = p_gtx_q_gain_comp_temp_array[i]; + } +// printf("%d\r\n", p_gtx_q_gain_comp_temp_array[i]); + } + printf("tx_q_gain_comp_temp: min = %d, max = %d, max-min = %d\r\n", min, max, max-min); + + max = -1100, min = 1100; +// printf("\r\ntx_phase_comp_temp[] = \r\n"); + for (i=0; i p_gtx_phase_comp_temp_array[i]) + { + min = p_gtx_phase_comp_temp_array[i]; + } +// printf("%d\r\n", p_gtx_phase_comp_temp_array[i]); + } + printf("tx_phase_comp_temp: min = %d, max = %d, max-min = %d\r\n", min, max, max-min); + + printf("\r\n"); + + max = -1100, min = 1100; +// printf("\r\nrx_amp_err_rd[] = \r\n"); + for (i=0; i p_rx_amp_err_rd_array[i]) + { + min = p_rx_amp_err_rd_array[i]; + } +// printf("%d\r\n", p_rx_amp_err_rd_array[i]); + } + printf("rx_amp_err_rd: min = %d, max = %d, max-min = %d\r\n", min, max, max-min); + + max = -1100, min = 1100; +// printf("\r\nrx_phase_err_rd[] = \r\n"); + for (i=0; i p_rx_phase_err_rd_array[i]) + { + min = p_rx_phase_err_rd_array[i]; + } +// printf("%d\r\n", p_rx_phase_err_rd_array[i]); + } + printf("rx_phase_err_rd: min = %d, max = %d, max-min = %d\r\n", min, max, max-min); + + max = -1100, min = 1100; +// printf("\r\nrx_ty2_rd[] = \r\n"); + for (i=0; i p_rx_ty2_rd_array[i]) + { + min = p_rx_ty2_rd_array[i]; + } +// printf("%d\r\n", p_rx_ty2_rd_array[i]); + } + printf("rx_ty2_rd: min = %d, max = %d, max-min = %d\r\n", min, max, max-min); + + for (j = 0; j < 8; j++) + { + int iTemp; + os_printf("\r\n"); + + max = -1100, min = 1100; + for (i = 0; i < calibrate_time; i++) + { + iTemp = p_g_rx_dc_gain_tab_array[j * CALIBRATE_TIMES + i]; + if (max < (iTemp & 0x00FF)) + { + max = iTemp & 0x00FF; + } + if (min > (iTemp & 0x00FF)) + { + min = iTemp & 0x00FF; + } + } + os_printf("g_rx_dc_gain_tab[%d].i_%ddb: min = %d, max = %d, max-min = %d\r\n", j, j * 6, min, max, max - min); + + max = -1100, min = 1100; + for (i = 0; i < calibrate_time; i++) + { + iTemp = p_g_rx_dc_gain_tab_array[j * CALIBRATE_TIMES + i] >> 8; + if (max < (iTemp & 0x00FF)) + { + max = iTemp & 0x00FF; + } + if (min > (iTemp & 0x00FF)) + { + min = iTemp & 0x00FF; + } + } + printf("g_rx_dc_gain_tab[%d].q_%ddb: min = %d, max = %d, max-min = %d\r\n", j, j * 6, min, max, max - min); + + max = -1100, min = 1100; + for (i = 0; i < calibrate_time; i++) + { + iTemp = p_g_rx_dc_gain_tab_array[j * CALIBRATE_TIMES + i] >> 16; + if (max < (iTemp & 0x00FF)) + { + max = iTemp & 0x00FF; + } + if (min > (iTemp & 0x00FF)) + { + min = iTemp & 0x00FF; + } + } + printf("g_rx_dc_gain_tab[%d].i_%ddb: min = %d, max = %d, max-min = %d\r\n", j, j * 6 + 3, min, max, max - min); + + max = -1100, min = 1100; + for (i = 0; i < calibrate_time; i++) + { + iTemp = p_g_rx_dc_gain_tab_array[j * CALIBRATE_TIMES + i] >> 24; + if (max < (iTemp & 0x00FF)) + { + max = iTemp & 0x00FF; + } + if (min > (iTemp & 0x00FF)) + { + min = iTemp & 0x00FF; + } + } + printf("g_rx_dc_gain_tab[%d].q_%ddb: min = %d, max = %d, max-min = %d\r\n", j, j * 6 + 3, min, max, max - min); + } +} + +void calibration_auto_test(unsigned long ul_calibrate_times) +{ + int i; + int gbias_after_cal_array[CALIBRATE_TIMES]; + int gav_tssi_array[CALIBRATE_TIMES]; + int rx_amp_err_rd_array[CALIBRATE_TIMES]; + int rx_phase_err_rd_array[CALIBRATE_TIMES]; + int rx_ty2_rd_array[CALIBRATE_TIMES]; + int gtx_ifilter_corner_array[CALIBRATE_TIMES]; + int gtx_qfilter_corner_array[CALIBRATE_TIMES]; +#ifdef SCAN_IQ_FILTER_CORNER + UINT32 sctrl_bias_reg_array[CALIBRATE_TIMES]; + int rx_avg_i_14M_array[CALIBRATE_TIMES]; + int rx_avg_i_14M_array2[CALIBRATE_TIMES]; + int rx_avg_q_14M_array[CALIBRATE_TIMES]; + int rx_avg_q_14M_array2[CALIBRATE_TIMES]; +#endif + + int gtx_i_dc_comp_array[CALIBRATE_TIMES]; + int gtx_q_dc_comp_array[CALIBRATE_TIMES]; + int gtx_i_gain_comp_array[CALIBRATE_TIMES]; + int gtx_q_gain_comp_array[CALIBRATE_TIMES]; + int gtx_phase_comp_array[CALIBRATE_TIMES]; + + int gtx_i_dc_comp_temp_array[CALIBRATE_TIMES]; + int gtx_q_dc_comp_temp_array[CALIBRATE_TIMES]; + int gtx_i_gain_comp_temp_array[CALIBRATE_TIMES]; + int gtx_q_gain_comp_temp_array[CALIBRATE_TIMES]; + int gtx_phase_comp_temp_array[CALIBRATE_TIMES]; + + int g_rx_dc_gain_tab_array[8][CALIBRATE_TIMES]; + + if (ul_calibrate_times == 0) + { + calibrate_times_all = CALIBRATE_TIMES; + } + else + { + calibrate_times_all = ul_calibrate_times; + } + + p_gbias_after_cal_array = gbias_after_cal_array; + p_gav_tssi_array = gav_tssi_array; + p_rx_amp_err_rd_array = rx_amp_err_rd_array; + p_rx_ty2_rd_array = rx_ty2_rd_array; + p_rx_phase_err_rd_array = rx_phase_err_rd_array; + p_gtx_ifilter_corner_array = gtx_ifilter_corner_array; + p_gtx_qfilter_corner_array = gtx_qfilter_corner_array; +#ifdef SCAN_IQ_FILTER_CORNER + p_g_sctrl_bias_reg_array = sctrl_bias_reg_array; + p_grx_avg_i_14M_array = rx_avg_i_14M_array; + p_grx_avg_i_14M_array2 = rx_avg_i_14M_array2; + p_grx_avg_q_14M_array = rx_avg_q_14M_array; + p_grx_avg_q_14M_array2 = rx_avg_q_14M_array2; +#endif + p_gtx_i_dc_comp_array = gtx_i_dc_comp_array; + p_gtx_q_dc_comp_array = gtx_q_dc_comp_array; + p_gtx_i_gain_comp_array = gtx_i_gain_comp_array; + p_gtx_q_gain_comp_array = gtx_q_gain_comp_array; + p_gtx_phase_comp_array = gtx_phase_comp_array; + p_gtx_i_dc_comp_temp_array = gtx_i_dc_comp_temp_array; + p_gtx_q_dc_comp_temp_array = gtx_q_dc_comp_temp_array; + p_gtx_i_gain_comp_temp_array = gtx_i_gain_comp_temp_array; + p_gtx_q_gain_comp_temp_array = gtx_q_gain_comp_temp_array; + p_gtx_phase_comp_temp_array = gtx_phase_comp_temp_array; + p_g_rx_dc_gain_tab_array = &(g_rx_dc_gain_tab_array[0][0]); + +/* +gi_gain_tx_pa_dgainPA30 = 2; +gi_gain_tx_pa_dgainbuf30 = 4; +for (gi_dc_tx_pa_dgainPA30=1; gi_dc_tx_pa_dgainPA30<=5; gi_dc_tx_pa_dgainPA30++) +{ +for (gi_dc_tx_pa_dgainbuf30=4; gi_dc_tx_pa_dgainbuf30<=6; gi_dc_tx_pa_dgainbuf30++) +{ + calibrate_time = 0; + os_printf("\r\n\r\n***********************************************************************\r\n" + "calibration_auto_test: \r\n"); + os_printf("gi_dc_tx_pa_dgainPA30 = %d\r\n", gi_dc_tx_pa_dgainPA30); + os_printf("gi_dc_tx_pa_dgainbuf30 = %d\r\n", gi_dc_tx_pa_dgainbuf30); + os_printf("gi_gain_tx_pa_dgainPA30 = %d\r\n", gi_gain_tx_pa_dgainPA30); + os_printf("gi_gain_tx_pa_dgainbuf30 = %d\r\n\r\n", gi_gain_tx_pa_dgainbuf30); + for (i=0; ibits.lpfcapcalq50 = lpfcap_q; + BK7011TRX.REG0x6->bits.lpfcapcali50 = lpfcap_i; + CAL_WR_TRXREGS(0x6); + bk7011_trx_val[6] = BK7011TRX.REG0x6->value; +} + +#if CFG_SUPPORT_MANUAL_CALI +static UINT32 rwnx_cal_translate_tx_rate(UINT32 rate) +{ + UINT32 param; + + switch(rate) + { + case 0 : + param = 1; + break; // 1Mbps + case 1 : + param = 2; + break; // 2Mbps + case 2 : + param = 5; + break; // 5.5Mbps + case 3: + param = 11; + break; // 11Mbps + case 4: + param = 6; + break; // 6Mbps + case 5 : + param = 9; + break; // 9Mbps + case 6: + param = 12; + break; // 12Mbps + case 7: + param = 18; + break; // 18Mbps + case 8: + param = 24; + break; // 24Mbps + case 9: + param = 36; + break; // 36Mbps + case 10: + param = 48; + break; // 48Mbps + case 11: + param = 54; + break; // 54Mbps + default: + param = rate; + break; // 54Mbps + } + + return param; +} + +static UINT32 rwnx_cal_translate_tx_rate_for_n(UINT32 rate, UINT32 bandwidth) +{ + UINT32 param; + + switch(rate) + { + case 128 : + case 129 : + case 130 : + case 131 : + case 132 : + case 133 : + param = rate - 123; + break; // MCS0-5 the same rate indx as 9M to 36M + + case 134: + case 135: + if(bandwidth == PHY_CHNL_BW_20) + param = 11; // MCS6-7the same rate indx as to 54M - band:20M + else + param = 12; // MCS6-7the same rate indx as to 135M - band:40M + break; + + default: + param = rate; + break; + } + + return param; +} +#endif + +//static INT32 cur_rate; +void rwnx_cal_set_txpwr_by_rate(INT32 rate, UINT32 test_mode) +{ +#if CFG_SUPPORT_MANUAL_CALI + UINT32 ret; + UINT32 pwr_gain; + + struct phy_channel_info info; + UINT32 channel, bandwidth; // PHY_CHNL_BW_20, PHY_CHNL_BW_40: + + phy_get_channel(&info, 0); + bandwidth = (info.info1 >> 8) & 0xff; + +// channel = (BK7011TRXONLY.REG0x7->bits.chin60 - 7)/5; + channel = (BK7011TRXONLY.REG0x5->bits.chspi - 7)/5; + if(channel > 14) + channel = 14; + if(!manual_cal_get_txpwr(rwnx_cal_translate_tx_rate(rate), + channel, bandwidth, &pwr_gain)) + { + // unable get txpwr from manual cal + return; + } + + ret = manual_cal_get_pwr_idx_shift(rate, bandwidth, &pwr_gain); + if(!ret ){ + // unable get txpwr from manual cal + return; + } else if(ret == 1) { + rwnx_cal_set_txpwr(pwr_gain, EVM_DEFUALT_B_RATE); + } else if(ret == 2) { + rwnx_cal_set_txpwr(pwr_gain, EVM_DEFUALT_RATE); + } + + if(rate <= 3) { + // just for 11b + BK7011TRX.REG0x6->bits.lpfcapcalq50 = 0x3f; + BK7011TRX.REG0x6->bits.lpfcapcali50 = 0x3f; + CAL_WR_TRXREGS(0x6); + }else { + BK7011TRX.REG0x6->value = bk7011_trx_val[6]; + CAL_WR_TRXREGS(0x6); + } + + if(test_mode) + { + os_printf("add extral movement in test\r\n"); + + #if CFG_USE_TEMPERATURE_DETECT + temp_detect_uninit(); + #endif + + //BK7011TRX.REG0x6->bits.lpfcapcalq50 = 0x3f; + //BK7011TRX.REG0x6->bits.lpfcapcali50 = 0x3f; + //CAL_WR_TRXREGS(0x6); + + BK7011TRX.REG0xB->value = 0xF0248033; + CAL_WR_TRXREGS(0xB); + + BK7011TRX.REG0xC->value = 0x1A287CC; + CAL_WR_TRXREGS(0xC); + + BK7011TRX.REG0x13->bits.icpoff20 = 0; + CAL_WR_TRXREGS(0x13); + + if(rate <= 3) { + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = ((bk7011_rc_val[18]>>16) & 0x3ff) + 0x20; + BK7011RCBEKEN.REG0x52->bits.TXPREGAIN = 0; + } + } else { + //BK7011TRX.REG0x6->value = bk7011_trx_val[6]; + //CAL_WR_TRXREGS(0x6); + + BK7011TRX.REG0xB->value = bk7011_trx_val[11]; + CAL_WR_TRXREGS(0xB); + + BK7011TRX.REG0xC->value = bk7011_trx_val[12]; + CAL_WR_TRXREGS(0xC); + + BK7011TRX.REG0x13->value = bk7011_trx_val[19]; + CAL_WR_TRXREGS(0x13); + + BK7011RCBEKEN.REG0x4F->value = bk7011_rc_val[18]; + + BK7011RCBEKEN.REG0x52->value = bk7011_rc_val[21]; + } +#endif +} + +#if CFG_SUPPORT_MANUAL_CALI +void rwnx_cal_set_txpwr(UINT32 pwr_gain, UINT32 grate) +{ + const PWR_REGS *pcfg; + + if(pwr_gain > 32) { + os_printf("set_txpwr unknow pwr idx:%d \r\n", pwr_gain); + return; + } + + if(grate == EVM_DEFUALT_B_RATE) { + // for b + pcfg = cfg_tab_b + pwr_gain; + } else if(grate == EVM_DEFUALT_RATE) { + // for g + pcfg = cfg_tab_g + pwr_gain; + } else { + os_printf("set_txpwr unknow rate:%d \r\n", grate); + return; + } + + os_printf("idx:%02d,r:%03d- pg:%02x, %01x, %01x, %01x, %01x, %01x, %01x\r\n", pwr_gain, grate, + pcfg->pregain, pcfg->regb_28_31, pcfg->regc_8_11,pcfg->regc_4_7, pcfg->regc_0_3, + pcfg->rega_8_13, pcfg->rega_0_1); + + BK7011RCBEKEN.REG0x52->bits.TXPREGAIN = gtx_pre_gain = pcfg->pregain; + bk7011_rc_val[21] = BK7011RCBEKEN.REG0x52->value; + + + BK7011TRX.REG0xA->bits.disrefPA10 = pcfg->rega_0_1; + BK7011TRX.REG0xA->bits.dbpaa30 = pcfg->rega_8_13; + CAL_WR_TRXREGS(0xA); + bk7011_trx_val[10] = BK7011TRXONLY.REG0xA->value ; + + BK7011TRX.REG0xB->bits.gctrlmod30 = pcfg->regb_28_31; + CAL_WR_TRXREGS(0xB); + bk7011_trx_val[11] = BK7011TRXONLY.REG0xB->value ; + + BK7011TRX.REG0xC->bits.dgainpga = pcfg->regc_0_3; + BK7011TRX.REG0xC->bits.dgainbuf30 = pcfg->regc_4_7; + BK7011TRX.REG0xC->bits.dgainPA30 = pcfg->regc_8_11; + CAL_WR_TRXREGS(0xC); + bk7011_trx_val[12] = BK7011TRXONLY.REG0xC->value ; +} + +void rwnx_cal_set_reg_mod_pa(UINT16 reg_mod, UINT16 reg_pa) +{ + gtx_dcorMod = (INT32)reg_mod, + gtx_dcorPA = (INT32)reg_pa; + BK7011TRXONLY.REG0xB->bits.dcorMod30 = gtx_dcorMod; + BK7011TRXONLY.REG0xC->bits.dcorPA30 = gtx_dcorPA; + bk7011_trx_val[11] = BK7011TRXONLY.REG0xB->value; + bk7011_trx_val[12] = BK7011TRXONLY.REG0xC->value; +} +#endif + +#if CFG_USE_TEMPERATURE_DETECT +#ifdef INCLUDE_OS +void rwnx_cal_do_temp_detect(UINT16 cur_val, UINT16 thre, UINT16 *last) +{ + TMP_PWR_PTR tmp_pwr_ptr; + tmp_pwr_ptr = manual_cal_set_tmp_pwr(cur_val, thre, last); + if(tmp_pwr_ptr) + { + rwnx_cal_set_reg_mod_pa(tmp_pwr_ptr->mod, tmp_pwr_ptr->pa); + } +} +#endif +#endif // CFG_USE_TEMPERATURE_DETECT + +void rwnx_tx_cal_save_cal_result(void) +{ + // Manual calibration not used PA & MOD, but use pre_gain + #if CFG_SUPPORT_MANUAL_CALI + gtx_dcorMod = 0x8; + gtx_dcorPA = 0x8; + #if CFG_USE_TEMPERATURE_DETECT + manual_cal_tmp_pwr_init_reg(gtx_dcorMod, gtx_dcorPA); + #endif // CFG_USE_TEMPERATURE_DETECT + #endif + + bk7011_trx_val[11] = (bk7011_trx_val[11] & (~(0xf << 12))) | (((0xf)>x_dcorMod) << 12); + bk7011_trx_val[12] = (bk7011_trx_val[12] & (~(0xf << 12))) | (((0xf)>x_dcorPA) << 12); + bk7011_rc_val[21] = (bk7011_rc_val[21] & (~(0x1f << 16))) | (((0x1f)>x_pre_gain) << 16); + + bk7011_rc_val[18] = (bk7011_rc_val[18] & (~(0x3ff << 16))) | (((0x3ff)>x_i_dc_comp) << 16); + bk7011_rc_val[18] = (bk7011_rc_val[18] & (~0x3ff)) | ((0x3ff)>x_q_dc_comp); + + bk7011_rc_val[19] = (bk7011_rc_val[19] & (~(0x3ff << 16))) | (((0x3ff)>x_i_gain_comp) << 16); + bk7011_rc_val[19] = (bk7011_rc_val[19] & (~0x3ff)) | ((0x3ff)>x_q_gain_comp); + + bk7011_trx_val[6] = (bk7011_trx_val[6] & (~(0x3f << 10))) | (((0x3f)>x_ifilter_corner) << 10); + bk7011_trx_val[6] = (bk7011_trx_val[6] & (~(0x3f << 4))) | (((0x3f)>x_qfilter_corner) << 4); + + bk7011_rc_val[20] = (bk7011_rc_val[20] & (~(0x3ff << 16))) | (((0x3ff)>x_phase_comp) << 16); + bk7011_rc_val[20] = (bk7011_rc_val[20] & (~0x3ff)) | ((0x3ff)>x_phase_ty2); + + bk7011_rc_val[26] = (bk7011_rc_val[26] & (~(0x3f << 16))) | (((0x3f)>x_ifilter_corner) << 16); + bk7011_rc_val[26] = (bk7011_rc_val[26] & (~(0x3f << 8))) | (((0x3f)>x_ifilter_corner) << 8); + bk7011_rc_val[26] = (bk7011_rc_val[26] & (~(0x3f << 0))) | (((0x3f)>x_ifilter_corner) << 0); + + bk7011_rc_val[27] = (bk7011_rc_val[27] & (~(0x3f << 16))) | (((0x3f)>x_qfilter_corner) << 16); + bk7011_rc_val[27] = (bk7011_rc_val[27] & (~(0x3f << 8))) | (((0x3f)>x_qfilter_corner) << 8); + bk7011_rc_val[27] = (bk7011_rc_val[27] & (~(0x3f << 0))) | (((0x3f)>x_qfilter_corner) << 0); + + //if(gstat_cal) + //bk7011_rc_val[16] = bk7011_rc_val[16] | (1 << 29); + //else + //bk7011_rc_val[16] = bk7011_rc_val[16] & (~(1 << 29)); +} + +void rwnx_rx_cal_save_cal_result(void) +{ + bk7011_trx_val[20] = g_rx_dc_gain_tab[0]; + bk7011_trx_val[21] = g_rx_dc_gain_tab[1]; + bk7011_trx_val[22] = g_rx_dc_gain_tab[2]; + bk7011_trx_val[23] = g_rx_dc_gain_tab[3]; + bk7011_trx_val[24] = g_rx_dc_gain_tab[4]; + bk7011_trx_val[25] = g_rx_dc_gain_tab[5]; + bk7011_trx_val[26] = g_rx_dc_gain_tab[6]; + bk7011_trx_val[27] = g_rx_dc_gain_tab[7]; + + bk7011_rc_val[15] = (bk7011_rc_val[15] & (~(0x3ff << 16))) | (((0x3ff)&grx_amp_err_wr) << 16); + bk7011_rc_val[15] = (bk7011_rc_val[15] & (~0x3ff)) | ((0x3ff)&grx_phase_err_wr); +} + +/******************************************************************************* +* Function Implemantation +*******************************************************************************/ +void bk7011_read_cal_param(void) +{ + gtx_dc_n = (BK7011RCBEKEN.REG0x54->bits.TXDCN & 0x03) + 2; + gst_sar_adc = ((BK7011RCBEKEN.REG0x54->bits.STSARADC & 0x03) + 1) * CAL_DELAY05US; + gst_rx_adc = ((BK7011RCBEKEN.REG0x54->bits.STRXADC & 0x03) + 1) * CAL_DELAY100US; + //gconst_iqcal_p = BK7011RCBEKEN.REG0x52->bits.IQCONSTANTIQCALP - 512; + //gconst_iqcal_p = abs(gconst_iqcal_p); + gconst_pout = BK7011RCBEKEN.REG0x52->bits.IQCONSTANTPOUT; + + return; +} + +INT32 rwnx_cal_load_trx_rcbekn_reg_val(void) +{ +#if (CFG_RUNNING_PLATFORM == FPGA_PLATFORM) + +#else + BK7011RCBEKEN.REG0x0->value = bk7011_rc_val[0]; + BK7011RCBEKEN.REG0x1->value = bk7011_rc_val[1]; + BK7011RCBEKEN.REG0x5->value = bk7011_rc_val[2]; + BK7011RCBEKEN.REG0x8->value = bk7011_rc_val[3]; + BK7011RCBEKEN.REG0xB->value = bk7011_rc_val[4]; + BK7011RCBEKEN.REG0xE->value = bk7011_rc_val[5]; + BK7011RCBEKEN.REG0x11->value = bk7011_rc_val[6]; + BK7011RCBEKEN.REG0x19->value = bk7011_rc_val[7]; + BK7011RCBEKEN.REG0x1C->value = bk7011_rc_val[8]; + BK7011RCBEKEN.REG0x1E->value = bk7011_rc_val[9]; + + /**********NEW ADDED************/ + BK7011RCBEKEN.REG0x3C->value = bk7011_rc_val[10]; + BK7011RCBEKEN.REG0x3E->value = bk7011_rc_val[11]; + BK7011RCBEKEN.REG0x3F->value = bk7011_rc_val[12]; + BK7011RCBEKEN.REG0x40->value = bk7011_rc_val[13]; + BK7011RCBEKEN.REG0x41->value = bk7011_rc_val[14]; + BK7011RCBEKEN.REG0x42->value = bk7011_rc_val[15]; + BK7011RCBEKEN.REG0x4C->value = bk7011_rc_val[16]; + BK7011RCBEKEN.REG0x4D->value = bk7011_rc_val[17]; + BK7011RCBEKEN.REG0x4F->value = bk7011_rc_val[18]; + BK7011RCBEKEN.REG0x50->value = bk7011_rc_val[19]; + BK7011RCBEKEN.REG0x51->value = bk7011_rc_val[20]; + BK7011RCBEKEN.REG0x52->value = bk7011_rc_val[21]; + BK7011RCBEKEN.REG0x54->value = bk7011_rc_val[22]; + BK7011RCBEKEN.REG0x55->value = bk7011_rc_val[23]; + BK7011RCBEKEN.REG0x5C->value = bk7011_rc_val[24]; + + BK7011RCBEKEN.REG0x4E->value = bk7011_rc_val[25]; + BK7011RCBEKEN.REG0x5A->value = bk7011_rc_val[26]; + BK7011RCBEKEN.REG0x5B->value = bk7011_rc_val[27]; + BK7011RCBEKEN.REG0x6A->value = bk7011_rc_val[28]; + BK7011RCBEKEN.REG0x70->value = bk7011_rc_val[29]; + BK7011RCBEKEN.REG0x71->value = bk7011_rc_val[30]; + BK7011RCBEKEN.REG0x72->value = bk7011_rc_val[31]; + BK7011RCBEKEN.REG0x73->value = bk7011_rc_val[32]; + BK7011RCBEKEN.REG0x74->value = bk7011_rc_val[33]; + BK7011RCBEKEN.REG0x75->value = bk7011_rc_val[34]; + BK7011RCBEKEN.REG0x76->value = bk7011_rc_val[35]; + BK7011RCBEKEN.REG0x77->value = bk7011_rc_val[36]; + + //BK7011RCBEKEN.REG0x3C->bits.RXIQSWAP = 1; /* I/Q SWAP*/ + +#endif + + os_memcpy(grc_reg_map, bk7011_trx_val, sizeof(INT32) * 29); + while(BK7011RCBEKEN.REG0x1->value & 0x0FFFFFFF) + { + cpu_delay(1); + } + + BK7011TRXONLY.REG0x0->value = bk7011_trx_val[0]; + BK7011TRXONLY.REG0x1->value = bk7011_trx_val[1]; + BK7011TRXONLY.REG0x2->value = bk7011_trx_val[2]; + BK7011TRXONLY.REG0x3->value = bk7011_trx_val[3]; + BK7011TRXONLY.REG0x4->value = bk7011_trx_val[4]; + BK7011TRXONLY.REG0x5->value = bk7011_trx_val[5]; + BK7011TRXONLY.REG0x6->value = bk7011_trx_val[6]; + BK7011TRXONLY.REG0x7->value = bk7011_trx_val[7]; + BK7011TRXONLY.REG0x8->value = bk7011_trx_val[8]; + BK7011TRXONLY.REG0x9->value = bk7011_trx_val[9]; + BK7011TRXONLY.REG0xA->value = bk7011_trx_val[10]; + BK7011TRXONLY.REG0xB->value = bk7011_trx_val[11]; + BK7011TRXONLY.REG0xC->value = bk7011_trx_val[12]; + BK7011TRXONLY.REG0xD->value = bk7011_trx_val[13]; + BK7011TRXONLY.REG0xE->value = bk7011_trx_val[14]; + BK7011TRXONLY.REG0xF->value = bk7011_trx_val[15]; + BK7011TRXONLY.REG0x10->value = bk7011_trx_val[16]; + BK7011TRXONLY.REG0x11->value = bk7011_trx_val[17]; + BK7011TRXONLY.REG0x12->value = bk7011_trx_val[18]; + BK7011TRXONLY.REG0x13->value = bk7011_trx_val[19]; + BK7011TRXONLY.REG0x14->value = bk7011_trx_val[20]; + BK7011TRXONLY.REG0x15->value = bk7011_trx_val[21]; + BK7011TRXONLY.REG0x16->value = bk7011_trx_val[22]; + BK7011TRXONLY.REG0x17->value = bk7011_trx_val[23]; + BK7011TRXONLY.REG0x18->value = bk7011_trx_val[24]; + BK7011TRXONLY.REG0x19->value = bk7011_trx_val[25]; + BK7011TRXONLY.REG0x1A->value = bk7011_trx_val[26]; + BK7011TRXONLY.REG0x1B->value = bk7011_trx_val[27]; + + while(BK7011RCBEKEN.REG0x1->value & 0x0FFFFFFF) + { + cpu_delay(1); + } + +#ifdef BK7011_VER_A + //os_memcpy(gadda_map, bk7011_adda_val, sizeof(INT32) * 6); + + //BK7011ADDA.REG0x0->value = bk7011_adda_val[0]; + //BK7011ADDA.REG0x1->value = bk7011_adda_val[1]; + //BK7011ADDA.REG0x2->value = bk7011_adda_val[2]; + //BK7011ADDA.REG0x3->value = bk7011_adda_val[3]; + //BK7011ADDA.REG0x4->value = bk7011_adda_val[4]; + //BK7011ADDA.REG0x5->value = bk7011_adda_val[5]; + //BK7011ADDAMAP.REG0x0->value = bk7011_adda_val[0]; + //BK7011ADDAMAP.REG0x1->value = bk7011_adda_val[1]; + //BK7011ADDAMAP.REG0x2->value = bk7011_adda_val[2]; + //BK7011ADDAMAP.REG0x3->value = bk7011_adda_val[3]; + //BK7011ADDAMAP.REG0x4->value = bk7011_adda_val[4]; + //BK7011ADDAMAP.REG0x5->value = bk7011_adda_val[5]; +#endif + +#ifdef BK7011_VER_A + //BK7011RCBEKEN.REG0x54->bits.DSELVA = 0; +#endif + + //BK7011ICU.REG0x3->bits.addaclkinv = 1; + //BK7011ICU.REG0x3->bits.txdacgain = 1 + +#if No_TXPOWERCAL + BK7011TRX.REG0xB->value = TRX_REG_0XB_VAL; + CAL_WR_TRXREGS(0xB); + BK7011TRX.REG0xC->value = TRX_REG_0XC_VAL; + CAL_WR_TRXREGS(0xC); + + BK7011RCBEKEN.REG0x52->bits.TXPREGAIN = 7; +#endif + + // cal rf pll when reload trx and rc beken value + bk7011_cal_pll(); + return 0; +} + +INT32 rwnx_cal_save_trx_rcbekn_reg_val(void) +{ +#if (CFG_RUNNING_PLATFORM == FPGA_PLATFORM) + +#else + bk7011_rc_val[0] = BK7011RCBEKEN.REG0x0->value ; + bk7011_rc_val[1] = BK7011RCBEKEN.REG0x1->value ; + bk7011_rc_val[2] = BK7011RCBEKEN.REG0x5->value ; + bk7011_rc_val[3] = BK7011RCBEKEN.REG0x8->value ; + bk7011_rc_val[4] = BK7011RCBEKEN.REG0xB->value ; + bk7011_rc_val[5] = BK7011RCBEKEN.REG0xE->value ; + bk7011_rc_val[6] = BK7011RCBEKEN.REG0x11->value; + bk7011_rc_val[7] = BK7011RCBEKEN.REG0x19->value; + bk7011_rc_val[8] = BK7011RCBEKEN.REG0x1C->value; + bk7011_rc_val[9] = BK7011RCBEKEN.REG0x1E->value; + + /**********NEW ADDED************/ + bk7011_rc_val[10] = BK7011RCBEKEN.REG0x3C->value; + bk7011_rc_val[11] = BK7011RCBEKEN.REG0x3E->value; + bk7011_rc_val[12] = BK7011RCBEKEN.REG0x3F->value; + bk7011_rc_val[13] = BK7011RCBEKEN.REG0x40->value; + bk7011_rc_val[14] = BK7011RCBEKEN.REG0x41->value; + bk7011_rc_val[15] = BK7011RCBEKEN.REG0x42->value; + bk7011_rc_val[16] = BK7011RCBEKEN.REG0x4C->value; + bk7011_rc_val[17] = BK7011RCBEKEN.REG0x4D->value; + bk7011_rc_val[18] = BK7011RCBEKEN.REG0x4F->value; + bk7011_rc_val[19] = BK7011RCBEKEN.REG0x50->value; + bk7011_rc_val[20] = BK7011RCBEKEN.REG0x51->value; + bk7011_rc_val[21] = BK7011RCBEKEN.REG0x52->value; + bk7011_rc_val[22] = BK7011RCBEKEN.REG0x54->value; + bk7011_rc_val[23] = BK7011RCBEKEN.REG0x55->value; + bk7011_rc_val[24] = BK7011RCBEKEN.REG0x5C->value; + + bk7011_rc_val[25] = BK7011RCBEKEN.REG0x4E->value; + bk7011_rc_val[26] = BK7011RCBEKEN.REG0x5A->value; + bk7011_rc_val[27] = BK7011RCBEKEN.REG0x5B->value; + bk7011_rc_val[28] = BK7011RCBEKEN.REG0x6A->value; + bk7011_rc_val[29] = BK7011RCBEKEN.REG0x70->value; + bk7011_rc_val[30] = BK7011RCBEKEN.REG0x71->value; + bk7011_rc_val[31] = BK7011RCBEKEN.REG0x72->value; + bk7011_rc_val[32] = BK7011RCBEKEN.REG0x73->value; + bk7011_rc_val[33] = BK7011RCBEKEN.REG0x74->value; + bk7011_rc_val[34] = BK7011RCBEKEN.REG0x75->value; + bk7011_rc_val[35] = BK7011RCBEKEN.REG0x76->value; + bk7011_rc_val[36] = BK7011RCBEKEN.REG0x77->value; + + //BK7011RCBEKEN.REG0x3C->bits.RXIQSWAP = 1; /* I/Q SWAP*/ + +#endif + + bk7011_trx_val[0] = BK7011TRXONLY.REG0x0->value ; + bk7011_trx_val[1] = BK7011TRXONLY.REG0x1->value ; + bk7011_trx_val[2] = BK7011TRXONLY.REG0x2->value ; + bk7011_trx_val[3] = BK7011TRXONLY.REG0x3->value ; + bk7011_trx_val[4] = BK7011TRXONLY.REG0x4->value ; + bk7011_trx_val[5] = BK7011TRXONLY.REG0x5->value ; + bk7011_trx_val[6] = BK7011TRXONLY.REG0x6->value ; + bk7011_trx_val[7] = BK7011TRXONLY.REG0x7->value ; + bk7011_trx_val[8] = BK7011TRXONLY.REG0x8->value ; + bk7011_trx_val[9] = BK7011TRXONLY.REG0x9->value ; + bk7011_trx_val[10] = BK7011TRXONLY.REG0xA->value ; + bk7011_trx_val[11] = BK7011TRXONLY.REG0xB->value ; + bk7011_trx_val[12] = BK7011TRXONLY.REG0xC->value ; + bk7011_trx_val[13] = BK7011TRXONLY.REG0xD->value ; + bk7011_trx_val[14] = BK7011TRXONLY.REG0xE->value ; + bk7011_trx_val[15] = BK7011TRXONLY.REG0xF->value ; + bk7011_trx_val[16] = BK7011TRXONLY.REG0x10->value; + bk7011_trx_val[17] = BK7011TRXONLY.REG0x11->value; + bk7011_trx_val[18] = BK7011TRXONLY.REG0x12->value; + bk7011_trx_val[19] = BK7011TRXONLY.REG0x13->value; + bk7011_trx_val[20] = BK7011TRXONLY.REG0x14->value; + bk7011_trx_val[21] = BK7011TRXONLY.REG0x15->value; + bk7011_trx_val[22] = BK7011TRXONLY.REG0x16->value; + bk7011_trx_val[23] = BK7011TRXONLY.REG0x17->value; + bk7011_trx_val[24] = BK7011TRXONLY.REG0x18->value; + bk7011_trx_val[25] = BK7011TRXONLY.REG0x19->value; + bk7011_trx_val[26] = BK7011TRXONLY.REG0x1A->value; + bk7011_trx_val[27] = BK7011TRXONLY.REG0x1B->value; + + os_memcpy(grc_reg_map, bk7011_trx_val, sizeof(INT32) * 29); + while(BK7011RCBEKEN.REG0x1->value & 0x0FFFFFFF) + { + cpu_delay(1); + } + + return 0; +} + +void bk7011_cal_ready(void) +{ + rwnx_cal_load_trx_rcbekn_reg_val(); + + bk7011_read_cal_param(); + rwnx_cal_load_default_result(); + + cpu_delay(1000); + /*step 4.2*/ + BK7011RCBEKEN.REG0x4C->bits.TXCOMPDIS = 0; + //gstat_cal = 0; // calibration start + + return; +} + +void bk7011_cal_dpll(void) +{ + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_CALI_DPLL, NULL); +} + + +#define BAND_CAL_GPIO_TIMES 10 +#define BAND_CAL_ADD_STEP 8 +#define BAND_CAL_VAL_MAX 0x7FU +#define BAND_CAL_VAL_MIN 0x00U + +#ifdef INCLUDE_OS +#include "rtos_pub.h" +#define BAND_CAL_TIMER_INTVAL 500 // ms +beken_timer_t band_timer; +#endif + +void bk7011_band_cal(void) +{ + UINT32 band, band_min, band_max; + UINT32 unlocked; + + // backup register + gtx_band = BK7011TRX.REG0x3->bits.bandm60; + + band = BAND_CAL_VAL_MIN - BAND_CAL_ADD_STEP; + do { + band += BAND_CAL_ADD_STEP; + if(band > BAND_CAL_VAL_MAX) { + os_printf("band cal failed- band up to 127\r\n"); + goto band_exit; + } + + BK7011TRX.REG0x3->bits.bandm60 = band; + CAL_WR_TRXREGS(0x3); + delay100us(10);//delay 1ms + + unlocked = 0; + for(int i=0; ibits.ch0ld) + unlocked = 1; + } + }while(unlocked); + + //os_printf("found band:%02x\r\n", band); + band_min = band_max = band; + + do { + if(band_min <= BAND_CAL_VAL_MIN) { + break; + } + band_min--; + + BK7011TRX.REG0x3->bits.bandm60 = band_min; + CAL_WR_TRXREGS(0x3); + delay100us(10);//delay 1ms + + unlocked = 0; + for(int i=0; ibits.ch0ld) + unlocked = 1; + } + }while(!unlocked); + + //os_printf("found band_min:%02x\r\n", band_min); + + do { + if(band_max >= BAND_CAL_VAL_MAX) { + os_printf("band cal failed- chspi_max up to 0x7F\r\n"); + break; + } + + band_max++; + BK7011TRX.REG0x3->bits.bandm60 = band_max; + CAL_WR_TRXREGS(0x3); + delay100us(10);//delay 1ms + + unlocked = 0; + for(int i=0; ibits.ch0ld) + unlocked = 1; + } + }while(!unlocked); + + band = (band_max + band_min) / 2; + //os_printf("found band_max:%02x- last:%02x\r\n", band_max, band); + + gtx_band = band; +band_exit: + // end, recovery register + BK7011TRX.REG0x3->bits.bandm60 = gtx_band; + CAL_WR_TRXREGS(0x3); + bk7011_trx_val[3] = (bk7011_trx_val[3] & (~(0x7f << 17))) | (((0x7f)>x_band) << 17); +} + +void bk7011_band_timer_handler(void* data) +{ + UINT32 unlocked; + + unlocked = 0; + for(int i=0; ibits.ch0ld) + unlocked = 1; + } + + //os_printf("band:%d\r\n", unlocked); + if(unlocked){ + bk7011_band_cal(); + } +} + +void bk7011_band_detect(void) +{ +#ifdef INCLUDE_OS + rtos_init_timer(&band_timer, + BAND_CAL_TIMER_INTVAL, + bk7011_band_timer_handler, + (void *)0); + rtos_start_timer(&band_timer); +#endif +} + +#define BIAS_DIFF_VAL1 (4u) +#define BIAS_DIFF_VAL2 (2u) +void bk7011_cal_bias(void) +{ + UINT32 param, param2; + // BK7011TRX.REG0xF->bits.biascalmanual = 0; + param = PARAM_BIAS_CAL_MANUAL_BIT; + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_BIAS_REG_CLEAN, ¶m); + + // BK7011TRX.REG0xF->bits.biascaltrig = 0; + param = PARAM_BIAS_CAL_TRIGGER_BIT; + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_BIAS_REG_CLEAN, ¶m); + //trx_reg_is_write(st_TRXREG0F); + //BK7011TRXONLY.REG0xF->value = BK7011TRX.REG0xF->value; + cpu_delay(100); + // BK7011TRX.REG0xF->bits.biascaltrig = 1; + param = PARAM_BIAS_CAL_TRIGGER_BIT; + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_BIAS_REG_SET, ¶m); + + //trx_reg_is_write(st_TRXREG0F); + //BK7011TRXONLY.REG0xF->value = BK7011TRX.REG0xF->value; + cpu_delay(DELAY1US * 40);//40us = 30 + 10; + + //Read SYS_CTRL.REG0x4C->bias_cal_out + param = sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_BIAS_REG_READ, ¶m); + param = (param >> PARAM_BIAS_CAL_OUT_POSI) & PARAM_BIAS_CAL_OUT_MASK; + + //First, Write SYS_CTRL.REG0x4C->ldo_val_man = bias_cal_out + BIAS_DIFF_VAL1 + param += BIAS_DIFF_VAL1; + param2 = param; + if (param > 0x1f) param = 0x1f; + param = ((param & PARAM_BIAS_CAL_OUT_MASK) << PARAM_LDO_VAL_MANUAL_POSI) + | PARAM_BIAS_CAL_MANUAL_BIT; + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_BIAS_REG_WRITE, ¶m); + + //Second, Write SYS_CTRL.REG0x4C->ldo_val_man = ldo_val_man - BIAS_DIFF_VAL2 + param = param2 - BIAS_DIFF_VAL2; + if (param > 0x1f) param = 0x1f; + gbias_after_cal = param; + param = ((param & PARAM_BIAS_CAL_OUT_MASK) << PARAM_LDO_VAL_MANUAL_POSI) + | PARAM_BIAS_CAL_MANUAL_BIT; + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_BIAS_REG_WRITE, ¶m); + + + //param = ((0x3 & PARAM_VSEL_SYS_LDO_MASK)<< PARAM_VSEL_SYS_LDO_POSI); + //sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_ANALOG_CTRL4_SET, ¶m); + + return; +} + +void bk7011_cal_pll(void) +{ +#if 1 + // uint32_t loop = 0, val; + + // do + { +#if 0 + +#else + + /*reg0x10 enrfpll = 1*/ + BK7011TRX.REG0x10->bits.enrfpll = 1; + BK7011TRX.REG0x10->bits.endpll = 1; + CAL_WR_TRXREGS(0x10); + + /*reg0x00 spitrig = 0->1->0*/ +/* BK7011TRX.REG0x0->bits.spitrig = 0; + CAL_WR_TRXREGS(0x0); + BK7011TRX.REG0x0->bits.spitrig = 1; + CAL_WR_TRXREGS(0x0); + BK7011TRX.REG0x0->bits.spitrig = 0; + CAL_WR_TRXREGS(0x0);*/ + + /*reg0x05 spitrigger = 0->1->0*/ +// BK7011TRX.REG0x5->bits.spitrigger = 0; +// BK7011TRX.REG0x5->bits.errdetspien = 0; +// CAL_WR_TRXREGS(0x5); + +// BK7011TRX.REG0x5->bits.spitrigger = 1; +// CAL_WR_TRXREGS(0x5); +// BK7011TRX.REG0x5->bits.spitrigger = 0; +// CAL_WR_TRXREGS(0x5); +// BK7011TRX.REG0x5->bits.errdetspien = 1; +// CAL_WR_TRXREGS(0x5); + BK7011TRX.REG0x3->bits.spi_trigger = 1; + CAL_WR_TRXREGS(0x3); + BK7011TRX.REG0x3->bits.spi_trigger = 0; + CAL_WR_TRXREGS(0x3); + BK7011TRX.REG0x3->bits.errdet_spien = 1; + CAL_WR_TRXREGS(0x3); +#endif + + cpu_delay(DELAY1US * 10); + + } + +// bk7011_trx_val[5] = (bk7011_trx_val[5] & (~(0x3))) | (0x1); //7231 for pll unlock detection,7231u for doubler + +#endif +} + + +void bk7011_tx_cal_en(void) +{ + BK7011RCBEKEN.REG0x0->bits.forceenable = 1; + cpu_delay(1); + BK7011RCBEKEN.REG0x19->bits.FCH0EN = 1; + BK7011RCBEKEN.REG0x19->bits.FCH0SHDN = 1; + BK7011RCBEKEN.REG0x19->bits.FCH0RXEN = 0; + BK7011RCBEKEN.REG0x19->bits.FCH0TXEN = 1; + BK7011RCBEKEN.REG0x1C->bits.FRXON = 0; + BK7011RCBEKEN.REG0x1C->bits.FTXON = 1; + //BK7011RCBEKEN.REG0x4D->bits.TXSINF = 0x1A; + + return; +} + +static INT32 bk7011_get_tx_output_power(void) +{ + int i; + INT32 tssioutpower = 0; + + for (i = 0; i < 4; i++) + { + cal_delay(1 * gst_sar_adc); + tssioutpower += BK7011RCBEKEN.REG0x54->bits.TSSIRD; + } + + if(gtx_power_cal_mode == TX_WANTED_POWER_CAL) // + { + + tssioutpower = tssioutpower / 4 - TSSI_POUT_TH - gav_tssi_temp; + } + else if(gtx_power_cal_mode == TX_IQ_POWER_CAL) // + { + + tssioutpower = tssioutpower / 4 - TXIQ_IMB_TSSI_TH - gav_tssi_temp; + } + else + { + tssioutpower = tssioutpower / 4 - TXIQ_IMB_TSSI_TH_LOOPBACK - gav_tssi_temp; + } + + + tssioutpower = abs(tssioutpower); + + return tssioutpower; +} + +static INT32 bk7011_set_tx_pa(INT32 val1, INT32 val2, INT32 val3, INT32 val4) +{ + BK7011TRX.REG0xC->bits.dgainPA30 = val1; + BK7011TRX.REG0xC->bits.dgainbuf30 = val2; + BK7011TRX.REG0xC->bits.dgainpga = val3; + BK7011TRX.REG0xB->bits.gctrlmod30 = val4; + CAL_WR_TRXREGS(0xC); + CAL_WR_TRXREGS(0xB); + + return 0; +} + +#define GET_AV_TSSI_CNT 4 + +INT32 bk7011_cal_tx_output_power(INT32 *val) +{ + INT32 gold_index = 0; + INT32 tssilow = 0; + INT32 tssihigh = 0; + INT32 index; + INT16 high, low, tx_fre_gain; + INT32 cnt = 0; + + //BK7011ADDAMAP.REG0x5->bits.vc40 = 0x1f; + //BK7011ADDA.REG0x5->value = BK7011ADDAMAP.REG0x5->value; + + // bk7011_rc_val[12]-16:20=7, 0x53479D40, 21 REG_0x52 + BK7011RCBEKEN.REG0x52->bits.TXPREGAIN = 7; + + BK7011TRX.REG0xB->value = TRX_REG_0XB_VAL; + CAL_WR_TRXREGS(0xB); + + BK7011RCBEKEN.REG0x4C->bits.ICONSTANT = 0x200; + BK7011RCBEKEN.REG0x4C->bits.QCONSTANT = 0x200; + BK7011TRX.REG0xC->value = TRX_REG_0XC_TXLO_LEAKAGE_VAL; + BK7011RCBEKEN.REG0x4C->bits.TESTPATTERN = 1; + if (gtx_power_cal_mode == TX_WANTED_POWER_CAL) + { + BK7011TRX.REG0xD->value = TRX_REG_0XD_VAL; + BK7011TRX.REG0xA->value = TRX_REG_0XA_VAL;//by yiming 20170315; + BK7011TRX.REG0xB->value = TRX_REG_0XB_VAL;//; + BK7011TRX.REG0xC->value = TRX_REG_0XC_VAL;//; + CAL_WR_TRXREGS(0xC); + BK7011TRX.REG0x0->bits.TSSIsel = 1; + BK7011TRX.REG0x0->bits.enDCcal = 0; + BK7011TRX.REG0x0->bits.enIQcal = 0; + BK7011TRX.REG0x0->bits.enPcal = 1; + BK7011TRX.REG0x0->bits.tssi_selrange = 0; + } + else if(gtx_power_cal_mode == TX_IQ_POWER_CAL) + { + BK7011TRX.REG0xD->value = TRX_REG_0XD_TX_IQ_VAL; + BK7011TRX.REG0xA->value = TRX_REG_0XA_VAL;//0x036F0757;//by yiming 20170315; + BK7011TRX.REG0xB->value = TRX_REG_0XB_VAL;//0x17248757;//; + BK7011TRX.REG0xC->value = TRX_REG_0XC_VAL;//0x05228765;//; + CAL_WR_TRXREGS(0xC); + + bk7011_set_tx_pa(gi_gain_tx_pa_dgainPA30, gi_gain_tx_pa_dgainbuf30, 0, 8); + BK7011TRX.REG0x0->bits.TSSIsel = 0; + BK7011TRX.REG0x0->bits.enDCcal = 0; + BK7011TRX.REG0x0->bits.enIQcal = 1; + BK7011TRX.REG0x0->bits.enPcal = 0; + BK7011TRX.REG0x0->bits.tssi_selrange = 0; + } + else //gtx_power_cal_mode == TX_IQ_LOOPBACK_POWER_CAL + { + BK7011TRX.REG0xD->value = TRX_REG_0XD_TX_LOOPBACK_IQ_VAL; + BK7011TRX.REG0xA->value = TRX_REG_0XA_VAL;//0x036F0757;//by yiming 20170315; + BK7011TRX.REG0xB->value = TRX_REG_0XB_VAL;//0x17248757;//; + BK7011TRX.REG0xC->value = TRX_REG_0XC_VAL;//0x05228765;//; + CAL_WR_TRXREGS(0xC); + bk7011_set_tx_pa(gi_gain_tx_loopback_pa_dgainPA30, gi_gain_tx_loopback_pa_dgainbuf30, 0, 8); + BK7011TRX.REG0x0->bits.TSSIsel = 0; + BK7011TRX.REG0x0->bits.enDCcal = 0; + BK7011TRX.REG0x0->bits.enIQcal = 1; + BK7011TRX.REG0x0->bits.enPcal = 0; + BK7011TRX.REG0x0->bits.tssi_selrange = 0; + } + + BK7011TRX.REG0x0->bits.tssi_statectrl = 1; + BK7011TRX.REG0xD->bits.entssi = 1; + BK7011TRX.REG0xD->bits.entssiadc = 1;//20170503 enable TSSI +// BK7011TRX.REG0x0->bits.tssi_selrange = 1; +// BK7011TRX.REG0x0->bits.enPcaliGm = 0; + BK7011TRX.REG0xF->bits.tssi_cal_en = 1; + CAL_WR_TRXREGS(0x0); + CAL_WR_TRXREGS(0xA); + CAL_WR_TRXREGS(0xD); + CAL_WR_TRXREGS(0xC); + CAL_WR_TRXREGS(0xF); + BK7011TRX.REG0xB->bits.dcorMod30 = 0; + CAL_WR_TRXREGS(0xB); + cal_delay(150);//for reg C,D,F write spi=80/16=5M,total time is 21.6us + cal_delay(5 * gst_sar_adc); + + gav_tssi_temp = 0; + for(cnt = 0; cnt < GET_AV_TSSI_CNT; cnt++) + { + cal_delay(1 * gst_sar_adc); + gav_tssi_temp += BK7011RCBEKEN.REG0x54->bits.TSSIRD; + } + cnt = 0; + gav_tssi_temp /= GET_AV_TSSI_CNT;//Get small power tssi of each sample to remove tssi dc + if (gtx_power_cal_mode == TX_WANTED_POWER_CAL) + { + gav_tssi = gav_tssi_temp; + } + + if (gtx_power_cal_mode == TX_WANTED_POWER_CAL) + { + BK7011RCBEKEN.REG0x4C->bits.ICONSTANT = gconst_pout; + BK7011RCBEKEN.REG0x4C->bits.QCONSTANT = gconst_pout; + BK7011TRX.REG0xC->value = TRX_REG_0XC_VAL;//; + CAL_WR_TRXREGS(0xC); + BK7011TRX.REG0x0->bits.TSSIsel = 1; + BK7011TRX.REG0x0->bits.enDCcal = 0; + BK7011TRX.REG0x0->bits.enIQcal = 0; + BK7011TRX.REG0x0->bits.enPcal = 1; + BK7011TRX.REG0x0->bits.tssi_selrange = 0; + } + else if(gtx_power_cal_mode == TX_IQ_POWER_CAL) + { + BK7011RCBEKEN.REG0x4C->bits.ICONSTANT = 0x230; + BK7011RCBEKEN.REG0x4C->bits.QCONSTANT = 0x230; + BK7011TRX.REG0xC->value = 0x05228245;//0x05228765;//; + CAL_WR_TRXREGS(0xC); + bk7011_set_tx_pa(gi_gain_tx_pa_dgainPA30, gi_gain_tx_pa_dgainbuf30, 0, 8); + BK7011TRX.REG0x0->bits.TSSIsel = 0; + BK7011TRX.REG0x0->bits.enDCcal = 0; + BK7011TRX.REG0x0->bits.enIQcal = 1; + BK7011TRX.REG0x0->bits.enPcal = 0; + BK7011TRX.REG0x0->bits.tssi_selrange = 0; + } + else //gtx_power_cal_mode == TX_IQ_LOOPBACK_POWER_CAL + { + BK7011RCBEKEN.REG0x4C->bits.ICONSTANT = 0x260;//by yiming 20170315; 250 + BK7011RCBEKEN.REG0x4C->bits.QCONSTANT = 0x260; + BK7011TRX.REG0xC->value = 0x05228245;//0x05228765;//; + CAL_WR_TRXREGS(0xC); + bk7011_set_tx_pa(gi_gain_tx_loopback_pa_dgainPA30, gi_gain_tx_loopback_pa_dgainbuf30, 0, 8); + BK7011TRX.REG0x0->bits.TSSIsel = 0; + BK7011TRX.REG0x0->bits.enDCcal = 0; + BK7011TRX.REG0x0->bits.enIQcal = 1; + BK7011TRX.REG0x0->bits.enPcal = 0; + BK7011TRX.REG0x0->bits.tssi_selrange = 0; + } + + BK7011TRX.REG0x0->bits.tssi_statectrl = 1; +// BK7011TRX.REG0x0->bits.enPcaliGm = 0; + BK7011TRX.REG0xF->bits.tssi_cal_en = 1; + BK7011TRX.REG0xC->bits.dcorPA30 = 8; + + CAL_WR_TRXREGS(0x0); + CAL_WR_TRXREGS(0xA); + CAL_WR_TRXREGS(0xD); + CAL_WR_TRXREGS(0xC); + CAL_WR_TRXREGS(0xF); + BK7011RCBEKEN.REG0x4C->bits.TESTPATTERN = 1; + + low = 0;//170703,for TZH limited from 2 to 6 + high = 15; + + BK7011TRX.REG0xB->bits.dcorMod30 = low; + CAL_WR_TRXREGS(0xB); + cal_delay(CAL_TX_NUM);//first sar dac delay needs double time + tssilow = bk7011_get_tx_output_power(); + + + BK7011TRX.REG0xB->bits.dcorMod30 = high; + CAL_WR_TRXREGS(0xB); + tssihigh = bk7011_get_tx_output_power(); + + do + { + CAL_PRT("cnt:%d, index:%d, tssilow:0x%x-%d, tssihigh:0x%x-%d\r\n", + cnt++, index, tssilow, low, tssihigh, high); + if(tssilow < tssihigh) + { + index = low; + high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011TRX.REG0xB->bits.dcorMod30 = high; + CAL_WR_TRXREGS(0xB); + tssihigh = bk7011_get_tx_output_power(); + } + else + { + index = high; + low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011TRX.REG0xB->bits.dcorMod30 = low; + CAL_WR_TRXREGS(0xB); + tssilow = bk7011_get_tx_output_power(); + } + } + while((high - low) > 1); + + index = ((tssilow < tssihigh) ? low : high); + if (gtx_power_cal_mode == TX_WANTED_POWER_CAL) + { + gtx_dcorMod = index; + } +#ifdef CALIBRATE_TIMES + else if(gtx_power_cal_mode == TX_IQ_POWER_CAL) + { + if (p_gbias_after_cal_array == NULL) + { + CAL_TIM_PRT("bk7011 TX IQ Cal. Output Power: \r\ntx_dcorMod= %d, ", index); + } + gtx_dcorMod_temp = index; + + } + else + { + if (p_gbias_after_cal_array == NULL) + { + CAL_TIM_PRT("bk7011 TX LOOPBACK IQ Cal. Output Power: \r\ntx_dcorMod= %d, ", index); + } + gtx_dcorMod_temp_loopback = index; + + + } + +#endif + + CAL_PRT("gtx_dcorMod over: 0x%x\r\n", gtx_dcorMod); + CAL_PRT("cnt:%d, index:%d, tssilow:0x%x-%d, tssihigh:0x%x-%d\r\n", + cnt++, index, tssilow, low, tssihigh, high); + + BK7011TRX.REG0xB->bits.dcorMod30 = index; + CAL_WR_TRXREGS(0xB); + gold_index = index << 8; + cal_delay(6); + + //BK7011TRX.REG0xB->bits.dcorMod30 = index; // dcormod30 optimum + //trx_reg_is_write(st_TRXREG0B); + //BK7011TRXONLY.REG0xB->value = BK7011TRX.REG0xB->value; + if (gtx_power_cal_mode == TX_WANTED_POWER_CAL) + { + low = 8;//170703,for TZH limited to 8 + high = 8; + } + else + { + low = 0;//170703,for TZH limited to 8 + high = 15; + } + BK7011TRX.REG0xC->bits.dcorPA30 = low; + CAL_WR_TRXREGS(0xC); + tssilow = bk7011_get_tx_output_power(); + + BK7011TRX.REG0xC->bits.dcorPA30 = high; + CAL_WR_TRXREGS(0xC); + tssihigh = bk7011_get_tx_output_power(); + + do + { + CAL_PRT("cnt:%d, index:%d, tssilow:0x%x-%d, tssihigh:0x%x-%d\r\n", + cnt++, index, tssilow, low, tssihigh, high); + if(tssilow < tssihigh) + { + index = low; + high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011TRX.REG0xC->bits.dcorPA30 = high; + CAL_WR_TRXREGS(0xC); + tssihigh = bk7011_get_tx_output_power(); + } + else + { + index = high; + low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011TRX.REG0xC->bits.dcorPA30 = low; + CAL_WR_TRXREGS(0xC); + tssilow = bk7011_get_tx_output_power(); + } + } + while((high - low) > 1); + + index = ((tssilow < tssihigh) ? low : high); + if (gtx_power_cal_mode == TX_WANTED_POWER_CAL) + { + gtx_dcorPA = index; + } +#ifdef CALIBRATE_TIMES + else if(gtx_power_cal_mode == TX_IQ_POWER_CAL) + { + if (p_gbias_after_cal_array == NULL) + { + CAL_TIM_PRT("tx_dcorPA= %d\r\n", index); + } + gtx_dcorPA_temp = index; + } + else + { + if (p_gbias_after_cal_array == NULL) + { + CAL_TIM_PRT("tx_dcorPA= %d\r\n", index); + } + gtx_dcorPA_temp_loopback = index; + } +#endif + BK7011TRX.REG0xC->bits.dcorPA30 = index; + CAL_WR_TRXREGS(0xC); + gold_index += index; + + //method2: first searching "dcorPA30",then serching "dcormod30"; + /**************************************************************** + * + *****************************************************************/ + *val = gold_index; + + CAL_PRT("gtx_dcorMod:0x%x, gtx_dcorPA:0x%x\r\n", gtx_dcorMod, gtx_dcorPA); + +#if 1 //170703,for TZH no pre_gain calibration + tx_fre_gain = BK7011RCBEKEN.REG0x52->bits.TXPREGAIN; + //CAL_WARN("tx_fre_gain:0x%x\r\n", tx_fre_gain); + if (gtx_power_cal_mode == TX_WANTED_POWER_CAL) + { + if(tx_fre_gain > 7) + low = tx_fre_gain - 7; + else + low = 0; + high = tx_fre_gain + 7; + } + else + { + if(tx_fre_gain > 2) + low = tx_fre_gain - 2; + else + low = 0; + high = tx_fre_gain + 2; + } + + BK7011RCBEKEN.REG0x52->bits.TXPREGAIN = low; + + //cpu_delay(1); +// tssilow = bk7011_get_tx_output_power_pregain(); + tssilow = bk7011_get_tx_output_power(); + + BK7011RCBEKEN.REG0x52->bits.TXPREGAIN = high; + //cpu_delay(1); +// tssihigh = bk7011_get_tx_output_power_pregain(); + tssihigh = bk7011_get_tx_output_power(); + + do + { + if(tssilow < tssihigh) + { + index = low; + high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x52->bits.TXPREGAIN = high; + //cpu_delay(1); + // tssihigh = bk7011_get_tx_output_power_pregain(); + tssihigh = bk7011_get_tx_output_power(); + } + else + { + index = high; + low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x52->bits.TXPREGAIN = low; + //cpu_delay(1); + // tssilow = bk7011_get_tx_output_power_pregain(); + tssilow = bk7011_get_tx_output_power(); + } + + } + while((high - low) > 1); + + index = ((tssilow < tssihigh) ? low : high); + + BK7011RCBEKEN.REG0x52->bits.TXPREGAIN = index; + if (gtx_power_cal_mode == TX_WANTED_POWER_CAL) + { + gtx_pre_gain = index; + } +#ifdef CALIBRATE_TIMES + else if(gtx_power_cal_mode == TX_IQ_POWER_CAL) + { + if (p_gbias_after_cal_array == NULL) + { + CAL_TIM_PRT("tx_pre_gain= %d\r\n", index); + } + gtx_pre_gain_temp = index; + } + else + { + if (p_gbias_after_cal_array == NULL) + { + CAL_TIM_PRT("tx_pre_gain= %d\r\n", index); + } + gtx_pre_gain_temp_loopback = index; + + } +#endif + + CAL_PRT("gtx_pre_gain:0x%x\r\n", gtx_pre_gain); +#endif + +#if 0 + if(gtx_dcorMod >= 0xa && gtx_dcorPA >= 0xc) + while(1); +#endif + + return (gold_index); +} + +void bk7011_micopwr_config_tssi_read_prepare(void) +{ + BK7011TRX.REG0x0->bits.TSSIsel = 1; + BK7011TRX.REG0x0->bits.enDCcal = 0; + BK7011TRX.REG0x0->bits.enIQcal = 0; + BK7011TRX.REG0x0->bits.enPcal = 1; + BK7011TRX.REG0x0->bits.tssi_statectrl = 1; + BK7011TRX.REG0xD->bits.entssi = 1; + BK7011TRX.REG0xD->bits.entssiadc = 1;//20170503 enable TSSI + BK7011TRX.REG0x0->bits.tssi_selrange = 1; +// BK7011TRX.REG0x0->bits.enPcaliGm = 0; + BK7011TRX.REG0xF->bits.tssi_cal_en = 1; + + CAL_WR_TRXREGS(0x0); + CAL_WR_TRXREGS(0xD); +// CAL_WR_TRXREGS(0xC); + CAL_WR_TRXREGS(0xF); +} + +#include "math.h" +#define TSSI_TAB_LEN 40 +#define TEMP_TAB_LEN 10 +UINT8 tssi_tab[TSSI_TAB_LEN]; +UINT8 temp_tab[TSSI_TAB_LEN]; + +void bk7011_micopwr_tssi_read(void) +{ + UINT32 i; + REG_WRITE((0x0802800 + (18 * 4)), 0x00); + for(i = 0; i < TSSI_TAB_LEN; i++) + { + tssi_tab[i] = BK7011RCBEKEN.REG0x54->bits.TSSIRD & 0xff; + } + //REG_WRITE((0x0802800 + (18 * 4)), 0x00); +} + +void bk7011_micopwr_tssi_show(void) +{ + UINT32 i, s = 0; + double sd = 0; + os_printf("\r\n tssi tab: \r\n"); + for(i = 0; i < TSSI_TAB_LEN; i++) + { + os_printf("%d, ", tssi_tab[i]); + if((i + 1) % 16 == 0) + os_printf("\r\n"); + } + + for(i = 0; i < TSSI_TAB_LEN; i++) + { + s += tssi_tab[i] * tssi_tab[i]; + } + sd = sqrt((double)(s / TSSI_TAB_LEN)); + os_printf("\r\nsd = %f\r\n", sd); +} + +static INT32 bk7011_update_tx_power(void) +{ +#ifdef CALIBRATE_TIMES + bk7011_set_tx_pa(gi_dc_tx_pa_dgainPA30, gi_dc_tx_pa_dgainbuf30, 0, 8);// mod gain should be same as the powser cal. setting +#else + bk7011_set_tx_pa(gi_dc_tx_pa_dgainPA30, gi_dc_tx_pa_dgainbuf30, 0, 8); +#endif + return 0; +} + +static INT32 bk7011_update_tx_loopback_power(void) +{ +#ifdef CALIBRATE_TIMES + bk7011_set_tx_pa(gi_dc_tx_loopback_pa_dgainPA30, gi_dc_tx_loopback_pa_dgainbuf30, 0, 8); +#else + bk7011_set_tx_pa(gi_dc_tx_loopback_pa_dgainPA30, gi_dc_tx_loopback_pa_dgainbuf30, 0, 8); +#endif + return 0; +} + +static INT32 bk7011_get_tx_dc(void) +{ + INT32 detect_dc = 0; + INT16 i; + + + + cpu_delay(200);//18us + + for(i = 0; i < SUMNUMBERS; i++) + { + cal_delay(5 * gst_sar_adc); + detect_dc += BK7011RCBEKEN.REG0x54->bits.TSSIRD; + } + + return detect_dc; +} +/* +static INT32 bk7011_get_tx_dc_1(void) +{ + INT32 detect_dc = 0; + INT16 i; + + + //BK7011TRXONLY.REG0xD->value = BK7011TRX.REG0xD->value; + CAL_WR_TRXREGS(0xC); + CAL_WR_TRXREGS(0xF); + + cpu_delay(200); + for(i = 0; i < SUMNUMBERS; i++) + { + cal_delay(5 * gst_sar_adc); + detect_dc += BK7011RCBEKEN.REG0x54->bits.TSSIRD; + } + return detect_dc; +} +*/ + +INT32 bk7011_cal_tx_dc(INT32 *val) +{ + INT32 detect_dc_low = 0; + INT32 detect_dc_high = 0; + INT16 high, low; + INT32 index, gold_index = 0; + INT32 i_index, q_index; + INT32 srchcnt = 0; + INT16 search_thrd = 64;//128;//DC search range search_thrd=512 gtx_dc_n=3, search_thrd=256 gtx_dc_n=2, search_thrd=128 gtx_dc_n=1 + /*step 4*/ + + + if(gtx_dc_cal_mode == TX_DC_CAL) + { + BK7011TRX.REG0xD->value = TRX_REG_0XD_TX_IQ_VAL; //BK7011TRXREG0xD;// + CAL_WR_TRXREGS(0xD); + bk7011_update_tx_power(); + BK7011TRX.REG0xB->bits.gctrlmod30 = (TRX_REG_0XB_VAL >> 28) & 0x0F; + CAL_WR_TRXREGS(0xB); + } + else if (gtx_dc_cal_mode == TX_DC_CAL_IQ) + { + BK7011TRX.REG0xD->value = TRX_REG_0XD_TX_IQ_VAL; //BK7011TRXREG0xD;// + CAL_WR_TRXREGS(0xD); + bk7011_update_tx_power(); + } + else if (gtx_dc_cal_mode == TX_DC_LOOPBACK_CAL_IQ) + { + BK7011TRX.REG0xD->value = TRX_REG_0XD_TX_LOOPBACK_IQ_VAL; + CAL_WR_TRXREGS(0xD); + bk7011_update_tx_loopback_power(); + } + + +#ifdef CALIBRATE_TIMES + if (p_gbias_after_cal_array == NULL) + { + if(gtx_dc_cal_mode == TX_DC_CAL) + { + CAL_TIM_PRT("\r\nbk7011_cal_tx_dc: \r\n"); + } + if(gtx_dc_cal_mode == TX_DC_CAL_IQ) + { + CAL_TIM_PRT("\r\nbk7011_cal_tx_dc_iq: \r\n"); + } + else if (gtx_dc_cal_mode == TX_DC_LOOPBACK_CAL_IQ) + { + CAL_TIM_PRT("\r\nbk7011_cal_tx_loopback_dc_iq: \r\n"); + } + CAL_TIM_PRT("dgainPA30 = %d\r\n", BK7011TRX.REG0xC->bits.dgainPA30 ); + CAL_TIM_PRT("dgainbuf30 =%d\r\n", BK7011TRX.REG0xC->bits.dgainbuf30); + CAL_TIM_PRT("dgainpga = %d\r\n", BK7011TRX.REG0xC->bits.dgainpga ); + CAL_TIM_PRT("gctrlmod30 = %d\r\n", BK7011TRX.REG0xB->bits.gctrlmod30); + } +#endif + + //[-512 511]---->[0,1023]; + + // I DC calibration; + BK7011RCBEKEN.REG0x4F->bits.TXQDCCOMP = UNSIGNEDOFFSET10 + 0; //default + + if(gtx_dc_cal_mode == TX_DC_CAL) + { + low = UNSIGNEDOFFSET10 - MINOFFSET ; + high = UNSIGNEDOFFSET10 + MINOFFSET ; + } + else if (gtx_dc_cal_mode == TX_DC_CAL_IQ) + { + low = UNSIGNEDOFFSET10 - MINOFFSET ; + high = UNSIGNEDOFFSET10 + MINOFFSET ; + } + else if (gtx_dc_cal_mode == TX_DC_LOOPBACK_CAL_IQ) + { + low = UNSIGNEDOFFSET10 - 3 * MINOFFSET ; + high = UNSIGNEDOFFSET10 + 3 * MINOFFSET ; + } + + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = low; + + //20170330 + BK7011RCBEKEN.REG0x4C->bits.ICONSTANT = UNSIGNEDOFFSET10 - 1; + BK7011RCBEKEN.REG0x4C->bits.QCONSTANT = UNSIGNEDOFFSET10 - 1 ; + BK7011RCBEKEN.REG0x4C->bits.TESTPATTERN = 1; + BK7011TRX.REG0x0->bits.TSSIsel = 0; + BK7011TRX.REG0x0->bits.enDCcal = 1; + BK7011TRX.REG0x0->bits.tssi_selrange = 1;//inverse 20141014 + BK7011TRX.REG0x0->bits.tssi_statectrl = 1; + BK7011TRX.REG0x0->bits.enIQcal = 0; + BK7011TRX.REG0x0->bits.enPcal = 0; +// BK7011TRX.REG0x0->bits.enPcaliGm = 0; + BK7011TRX.REG0xF->bits.tssi_cal_en = 1; + //20170330 + + CAL_WR_TRXREGS(0x0); + //BK7011TRXONLY.REG0xD->value = BK7011TRX.REG0xD->value; + CAL_WR_TRXREGS(0xC); + CAL_WR_TRXREGS(0xF); + cal_delay(CAL_TX_NUM);//first sar dac delay needs double time + + detect_dc_low = bk7011_get_tx_dc(); + + + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + //Step 1 3~6 search; + srchcnt = 0; + + + if(detect_dc_low < detect_dc_high) + { + high = 511; + low = high - search_thrd; + } + else + { + low = 512; + high = low + search_thrd; + } + + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = low; + detect_dc_low = bk7011_get_tx_dc(); + + do + { + if(detect_dc_low < detect_dc_high) + { + index = low; + high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + + } + else + { + index = high; + low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = low; + detect_dc_low = bk7011_get_tx_dc(); + } + srchcnt++; + if(srchcnt > gtx_dc_n) + break; + } + while((high - low) > 1); + + //Step 2 search; + + //BK7011TRX.REG0x0->bits.tssi_selrange = 0;//20170330 YIMING + BK7011TRX.REG0x0->value = 0x00019041; + CAL_WR_TRXREGS(0x0); + + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = low; + detect_dc_low = bk7011_get_tx_dc(); + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + + do + { + if(detect_dc_low < detect_dc_high) + { + index = low; + high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + + } + else + { + index = high; + low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = low; + detect_dc_low = bk7011_get_tx_dc(); + } + } + while((high - low) > 1); + i_index = ((detect_dc_low < detect_dc_high) ? low : high); + + // Q DC calibration; + //Step 1 3~6 search; + if ((gtx_dc_cal_mode == TX_DC_CAL) || (gtx_dc_cal_mode == TX_DC_CAL_IQ)) + { + low = UNSIGNEDOFFSET10 - MINOFFSET ; + high = UNSIGNEDOFFSET10 + MINOFFSET ; + } + else if (gtx_dc_cal_mode == TX_DC_LOOPBACK_CAL_IQ) + { + low = UNSIGNEDOFFSET10 - 3 * MINOFFSET ; + high = UNSIGNEDOFFSET10 + 3 * MINOFFSET ; + } + + //20170330 + + //BK7011TRX.REG0x0->bits.tssi_selrange = 1;//inverse 20141014 + BK7011TRX.REG0x0->value = 0x00079042; + CAL_WR_TRXREGS(0x0); + + //20170330 + srchcnt = 0; + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = i_index; //default + + BK7011RCBEKEN.REG0x4F->bits.TXQDCCOMP = low; + detect_dc_low = bk7011_get_tx_dc(); + + + BK7011RCBEKEN.REG0x4F->bits.TXQDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + + + if(detect_dc_low < detect_dc_high) + { + + high = 511; + low = high - search_thrd; + } + else + { + low = 512; + high = low + search_thrd; + } + + BK7011RCBEKEN.REG0x4F->bits.TXQDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + BK7011RCBEKEN.REG0x4F->bits.TXQDCCOMP = low; + detect_dc_low = bk7011_get_tx_dc(); + + do + { + if(detect_dc_low < detect_dc_high) + { + index = low; + high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x4F->bits.TXQDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + + } + else + { + index = high; + low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x4F->bits.TXQDCCOMP = low; + detect_dc_low = bk7011_get_tx_dc(); + } + srchcnt++; + if(srchcnt > gtx_dc_n) + break; + } + while((high - low) > 1); + + //Step 2 search; + + //BK7011TRX.REG0x0->bits.tssi_selrange = 0;//20170330 YIMING + BK7011TRX.REG0x0->value = 0x00019041; + CAL_WR_TRXREGS(0x0); + + BK7011RCBEKEN.REG0x4F->bits.TXQDCCOMP = low; + detect_dc_low = bk7011_get_tx_dc(); + BK7011RCBEKEN.REG0x4F->bits.TXQDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + do + { + if(detect_dc_low < detect_dc_high) + { + index = low; + high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x4F->bits.TXQDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + + } + else + { + index = high; + low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x4F->bits.TXQDCCOMP = low; + detect_dc_low = bk7011_get_tx_dc(); + } + } + while((high - low) > 1); + + q_index = ((detect_dc_low < detect_dc_high) ? low : high); + + + + if(gtx_dc_cal_mode == TX_DC_CAL) + { + gtx_q_dc_comp = q_index; + CAL_WARN("gtx_q_dc_comp:0x%x\r\n", gtx_q_dc_comp); + } + else if(gtx_dc_cal_mode == TX_DC_CAL_IQ) + { + gtx_q_dc_comp = q_index; + CAL_WARN("gtx_q_dc_comp_iq:0x%x\r\n", gtx_q_dc_comp); + } + else if (gtx_dc_cal_mode == TX_DC_LOOPBACK_CAL_IQ) + { + gtx_q_dc_comp_loopback = q_index; +#ifdef CALIBRATE_TIMES + if (p_gtx_q_dc_comp_temp_array != NULL) + { + p_gtx_q_dc_comp_temp_array[calibrate_time] = q_index; + } +#endif + CAL_WARN("gtx_q_dc_comp_loopback_iq:0x%x\r\n", gtx_q_dc_comp_loopback); + } + gold_index += q_index; + + // 2nd I DC calibration; + //Step 1 3~6 search; + if ((gtx_dc_cal_mode == TX_DC_CAL) || (gtx_dc_cal_mode == TX_DC_CAL_IQ)) + { + low = UNSIGNEDOFFSET10 - MINOFFSET ; + high = UNSIGNEDOFFSET10 + MINOFFSET ; + } + else// (gtx_dc_cal_mode == TX_DC_LOOPBACK_CAL_IQ) + { + low = UNSIGNEDOFFSET10 - 3 * MINOFFSET ; + high = UNSIGNEDOFFSET10 + 3 * MINOFFSET ; + } + //20170330 + + //BK7011TRX.REG0x0->bits.tssi_selrange = 1;//inverse 20141014 + BK7011TRX.REG0x0->value = 0x00079042; + CAL_WR_TRXREGS(0x0); + + //20170330 + + + srchcnt = 0; + BK7011RCBEKEN.REG0x4F->bits.TXQDCCOMP = q_index; // optimum + + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = low; + detect_dc_low = bk7011_get_tx_dc(); + + + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + //low = 0; + //high = 1023; + + + if(detect_dc_low < detect_dc_high) + { + high = 511; + low = high - search_thrd; + } + else + { + low = 512; + high = low + search_thrd; + } + + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = low; + detect_dc_low = bk7011_get_tx_dc(); + + do + { + if(detect_dc_low < detect_dc_high) + { + index = low; + high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + } + else + { + index = high; + low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = low; + detect_dc_low = bk7011_get_tx_dc(); + } + srchcnt++; + if(srchcnt > gtx_dc_n) break; + } + while((high - low) > 1); + + //Step 2 search; + + //BK7011TRX.REG0x0->bits.tssi_selrange = 0;//20170330 YIMING + BK7011TRX.REG0x0->value = 0x00019041; + CAL_WR_TRXREGS(0x0); + + + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = low; + detect_dc_low = bk7011_get_tx_dc(); + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + do + { + + if(detect_dc_low < detect_dc_high) + { + index = low; + high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + + } + else + { + index = high; + low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = low; + detect_dc_low = bk7011_get_tx_dc(); + } + } + while((high - low) > 1); + + + i_index = ((detect_dc_low < detect_dc_high) ? low : high); + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = i_index; + if(gtx_dc_cal_mode == TX_DC_CAL) + { + gtx_i_dc_comp = i_index; + CAL_WARN("gtx_i_dc_comp:0x%x\r\n", gtx_i_dc_comp); + } + else if(gtx_dc_cal_mode == TX_DC_CAL_IQ) + { + gtx_i_dc_comp = i_index; + CAL_WARN("gtx_i_dc_comp_iq:0x%x\r\n", gtx_i_dc_comp); + } + else if (gtx_dc_cal_mode == TX_DC_LOOPBACK_CAL_IQ) + { + gtx_i_dc_comp_loopback= i_index; + #ifdef CALIBRATE_TIMES + if (p_gtx_i_dc_comp_temp_array != NULL) + { + p_gtx_i_dc_comp_temp_array[calibrate_time] = i_index; + } + #endif + CAL_WARN("gtx_i_dc_comp_loopback_iq:0x%x\r\n", gtx_i_dc_comp_loopback); + } + + gold_index += (i_index << 16); + *val = gold_index; + (void)index; + + //BK7011TRX.REG0x0->bits.tssi_selrange = 1;//inverse 20141014 + BK7011TRX.REG0x0->value = 0x00079042; + CAL_WR_TRXREGS(0x0); + + return gold_index; +} + + +#define TSSI_RD_TIMES 8 +static INT32 bk7011_get_tx_i_gain(void) +{ + int i; + INT32 detector_i_gain_p, detector_i_gain_n, detector_i_gain; + + BK7011RCBEKEN.REG0x4C->bits.ICONSTANT = UNSIGNEDOFFSET10 + gconst_iqcal_p; + BK7011RCBEKEN.REG0x4C->bits.QCONSTANT = UNSIGNEDOFFSET10 + 0; + detector_i_gain_p = 0; + for (i=0; ibits.TSSIRD; + } + + BK7011RCBEKEN.REG0x4C->bits.ICONSTANT = UNSIGNEDOFFSET10 - gconst_iqcal_p; + BK7011RCBEKEN.REG0x4C->bits.QCONSTANT = UNSIGNEDOFFSET10 + 0; + detector_i_gain_n = 0; + for (i=0; ibits.TSSIRD; + } + + detector_i_gain = detector_i_gain_p + detector_i_gain_n; + return detector_i_gain; +} +static INT32 bk7011_get_tx_q_gain(void) +{ + int i; + INT32 detector_q_gain_p, detector_q_gain_n, detector_q_gain; + + BK7011RCBEKEN.REG0x4C->bits.ICONSTANT = UNSIGNEDOFFSET10 + 0; + BK7011RCBEKEN.REG0x4C->bits.QCONSTANT = UNSIGNEDOFFSET10 + gconst_iqcal_p; + detector_q_gain_p = 0; + for (i=0; ibits.TSSIRD; + } + + BK7011RCBEKEN.REG0x4C->bits.ICONSTANT = UNSIGNEDOFFSET10 + 0; + BK7011RCBEKEN.REG0x4C->bits.QCONSTANT = UNSIGNEDOFFSET10 - gconst_iqcal_p; + detector_q_gain_n = 0; + for (i=0; ibits.TSSIRD; + } + + detector_q_gain = detector_q_gain_p + detector_q_gain_n; + return detector_q_gain; +} +static INT32 bk7011_get_tx_i_phase(void) +{ + int i; + INT32 detector_i_phase_n, detector_i_phase_p, detector_i_phase; + + + BK7011RCBEKEN.REG0x4C->bits.ICONSTANT = UNSIGNEDOFFSET10 + (gconst_iqcal_p*10)/14; + BK7011RCBEKEN.REG0x4C->bits.QCONSTANT = UNSIGNEDOFFSET10 - (gconst_iqcal_p*10)/14; + detector_i_phase_p = 0; + for (i=0; ibits.TSSIRD; + } + + BK7011RCBEKEN.REG0x4C->bits.ICONSTANT = UNSIGNEDOFFSET10 - (gconst_iqcal_p*10)/14; + BK7011RCBEKEN.REG0x4C->bits.QCONSTANT = UNSIGNEDOFFSET10 + (gconst_iqcal_p*10)/14; + detector_i_phase_n = 0; + for (i=0; ibits.TSSIRD; + } + + detector_i_phase = detector_i_phase_p + detector_i_phase_n; + return detector_i_phase; +} +static INT32 bk7011_get_tx_q_phase(void) +{ + int i; + INT32 detector_q_phase_n, detector_q_phase_p, detector_q_phase; + + BK7011RCBEKEN.REG0x4C->bits.ICONSTANT = UNSIGNEDOFFSET10 + (gconst_iqcal_p*10)/14; + BK7011RCBEKEN.REG0x4C->bits.QCONSTANT = UNSIGNEDOFFSET10 + (gconst_iqcal_p*10)/14; + detector_q_phase_p = 0; + for (i=0; ibits.TSSIRD; + } + + BK7011RCBEKEN.REG0x4C->bits.ICONSTANT = UNSIGNEDOFFSET10 - (gconst_iqcal_p*10)/14; + BK7011RCBEKEN.REG0x4C->bits.QCONSTANT = UNSIGNEDOFFSET10 - (gconst_iqcal_p*10)/14; + detector_q_phase_n = 0; + for (i=0; ibits.TSSIRD; + } + + detector_q_phase = detector_q_phase_p + detector_q_phase_n; + return detector_q_phase; +} +static INT32 bk7011_get_rx_i_avg_signed(void) +{ + INT32 val; +#ifdef BK7011_VER_A + val = BK7011RCBEKEN.REG0x3C->bits.RXAVGIRD; +#else + val = BK7011RCBEKEN.REG0x3C->bits.RXAVGIRD; +#endif + + return val; +// if(val & 0x00000800) +// { +// val |= 0xfffff000; +// } + +// return abs(val); +} + +static INT32 bk7011_get_rx_q_avg_signed(void) +{ + INT32 val; + +#ifdef BK7011_VER_A + val = BK7011RCBEKEN.REG0x3C->bits.RXAVGQRD; +#else + val = BK7011RCBEKEN.REG0x3C->bits.RXAVGQRD; +#endif + + return val; + +// if(val & 0x00000800) +// { +// val |= 0xfffff000; +// } +// return abs(val); +} + +INT32 bk7011_cal_tx_gain_imbalance(INT32 *val) +{ + INT32 detect_gain_low = 0; + INT32 detect_gain_high = 0; + INT16 high, low; + INT32 index = 0, gold_index = 0; + INT32 detector_i_gain; + INT32 detector_q_gain; + + if(gtx_gain_imb_cal_mode == TX_GAIN_IMB_CAL) + { + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = gtx_i_dc_comp; + BK7011RCBEKEN.REG0x4F->bits.TXQDCCOMP = gtx_q_dc_comp; + BK7011TRX.REG0xD->value = TRX_REG_0XD_TX_IQ_VAL;//BK7011TRXREG0xD;//0214 close the TX switch to ellimite the antenna infect + CAL_WR_TRXREGS(0xD); + } + else + { + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = gtx_i_dc_comp_loopback; + BK7011RCBEKEN.REG0x4F->bits.TXQDCCOMP = gtx_q_dc_comp_loopback; + BK7011TRX.REG0xD->value = TRX_REG_0XD_TX_LOOPBACK_IQ_VAL; + CAL_WR_TRXREGS(0xD); + + } + + BK7011RCBEKEN.REG0x50->bits.TXIGAINCOMP = 1023; + BK7011RCBEKEN.REG0x50->bits.TXQGAINCOMP = 1023; + BK7011RCBEKEN.REG0x4C->bits.TESTPATTERN = 1; + + +#ifdef CALIBRATE_TIMES + if(gtx_gain_imb_cal_mode == TX_GAIN_IMB_CAL) + { + bk7011_set_tx_pa(gi_gain_tx_pa_dgainPA30, gi_gain_tx_pa_dgainbuf30, 3, 8); + } + else + { + bk7011_set_tx_pa(gi_gain_tx_loopback_pa_dgainPA30, gi_gain_tx_loopback_pa_dgainbuf30, 3, 8); + } + if (p_gbias_after_cal_array == NULL) + { + if(gtx_gain_imb_cal_mode == TX_GAIN_IMB_CAL) + { + CAL_TIM_PRT("\r\nbk7011_cal_tx_gain_imbalance\r\n"); + } + else + { + CAL_TIM_PRT("\r\nbk7011_cal_tx_loopback_gain_imbalance\r\n"); + } + + CAL_TIM_PRT("dgainPA30 = %d\r\n", BK7011TRX.REG0xC->bits.dgainPA30 ); //?? + CAL_TIM_PRT("dgainbuf30 =%d\r\n", BK7011TRX.REG0xC->bits.dgainbuf30); //?? + CAL_TIM_PRT("dgainpga = %d\r\n", BK7011TRX.REG0xC->bits.dgainpga ); //?? + CAL_TIM_PRT("gctrlmod30 = %d\r\n", BK7011TRX.REG0xB->bits.gctrlmod30); + } +#else + if(gtx_gain_imb_cal_mode == TX_GAIN_IMB_CAL) + { + bk7011_set_tx_pa(gi_gain_tx_pa_dgainPA30, gi_gain_tx_pa_dgainbuf30, 3, 8); + } + else + { + bk7011_set_tx_pa(gi_gain_tx_loopback_pa_dgainPA30, gi_gain_tx_loopback_pa_dgainbuf30, 3, 8); + } +#endif + + + BK7011TRX.REG0x0->bits.TSSIsel = 0; + BK7011TRX.REG0x0->bits.enDCcal = 0; + BK7011TRX.REG0x0->bits.tssi_statectrl = 1; + BK7011TRX.REG0x0->bits.tssi_selrange = 0; + BK7011TRX.REG0x0->bits.enIQcal = 1; + BK7011TRX.REG0x0->bits.enPcal = 0; +// BK7011TRX.REG0x0->bits.enPcaliGm = 0; + + BK7011TRX.REG0xF->bits.tssi_cal_en = 1; + BK7011TRX.REG0x0->value = 0x0001A24E;//0x00019041; + CAL_WR_TRXREGS(0x0); + CAL_WR_TRXREGS(0xC); + CAL_WR_TRXREGS(0xB); + CAL_WR_TRXREGS(0xF); + + if(gtx_gain_imb_cal_mode == TX_GAIN_IMB_CAL) + { + gtx_i_gain_comp = BK7011RCBEKEN.REG0x50->bits.TXIGAINCOMP; + gtx_q_gain_comp = BK7011RCBEKEN.REG0x50->bits.TXQGAINCOMP; + } + else + { + gtx_i_gain_comp_loopback = BK7011RCBEKEN.REG0x50->bits.TXIGAINCOMP; + gtx_q_gain_comp_loopback = BK7011RCBEKEN.REG0x50->bits.TXQGAINCOMP; + } + + cpu_delay(500); + detector_i_gain = bk7011_get_tx_i_gain(); + detector_q_gain = bk7011_get_tx_q_gain(); + + if(abs(detector_q_gain - detector_i_gain) < 3) + { + *val = 0; + if(gtx_gain_imb_cal_mode == TX_GAIN_IMB_CAL) + { + gtx_i_gain_comp = BK7011RCBEKEN.REG0x50->bits.TXIGAINCOMP; + gtx_q_gain_comp = BK7011RCBEKEN.REG0x50->bits.TXQGAINCOMP; + } + else + { + gtx_i_gain_comp_loopback = BK7011RCBEKEN.REG0x50->bits.TXIGAINCOMP; + gtx_q_gain_comp_loopback = BK7011RCBEKEN.REG0x50->bits.TXQGAINCOMP; + } + + return (BK7011RCBEKEN.REG0x50->bits.TXQGAINCOMP + (BK7011RCBEKEN.REG0x50->bits.TXIGAINCOMP << 16)); + } + + if(detector_i_gain > detector_q_gain) // TX_Q_GAIN_COMP NOT CHANGED + { + BK7011RCBEKEN.REG0x50->bits.TXQGAINCOMP = 1023; + low = 0; + BK7011RCBEKEN.REG0x50->bits.TXIGAINCOMP = low; + detector_i_gain = bk7011_get_tx_i_gain(); + detector_q_gain = bk7011_get_tx_q_gain(); + + detect_gain_low = abs(detector_i_gain - detector_q_gain); + + high = 1023; + BK7011RCBEKEN.REG0x50->bits.TXIGAINCOMP = high; + detector_i_gain = bk7011_get_tx_i_gain(); + detector_q_gain = bk7011_get_tx_q_gain(); + + detect_gain_high = abs(detector_i_gain - detector_q_gain); + do + { + if(detect_gain_low < detect_gain_high) + { + index = low; + high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x50->bits.TXIGAINCOMP = high; + detector_i_gain = bk7011_get_tx_i_gain(); + detector_q_gain = bk7011_get_tx_q_gain(); + detect_gain_high = abs(detector_i_gain - detector_q_gain); + } + else + { + index = high; + low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x50->bits.TXIGAINCOMP = low; + detector_i_gain = bk7011_get_tx_i_gain(); + detector_q_gain = bk7011_get_tx_q_gain(); + detect_gain_low = abs(detector_i_gain - detector_q_gain); + } + + } + while((high - low) > 1); + index = ((detect_gain_low < detect_gain_high) ? low : high); + BK7011RCBEKEN.REG0x50->bits.TXIGAINCOMP = index; + + if(gtx_gain_imb_cal_mode == TX_GAIN_IMB_CAL) + { + gtx_i_gain_comp = index; + } + else + { + gtx_i_gain_comp_loopback= index; + } + gold_index = (index << 16) + 1023; + } + else //// TX_I_GAIN_COMP NOT CHANGED + { + BK7011RCBEKEN.REG0x50->bits.TXIGAINCOMP = 1023; + low = 0; + BK7011RCBEKEN.REG0x50->bits.TXQGAINCOMP = low; + detector_i_gain = bk7011_get_tx_i_gain(); + detector_q_gain = bk7011_get_tx_q_gain(); + + detect_gain_low = abs(detector_i_gain - detector_q_gain); + + high = 1023; + BK7011RCBEKEN.REG0x50->bits.TXQGAINCOMP = high; + detector_i_gain = bk7011_get_tx_i_gain(); + detector_q_gain = bk7011_get_tx_q_gain(); + + detect_gain_high = abs(detector_i_gain - detector_q_gain); + do + { + if(detect_gain_low < detect_gain_high) + { + index = low; + high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x50->bits.TXQGAINCOMP = high; + detector_i_gain = bk7011_get_tx_i_gain(); + detector_q_gain = bk7011_get_tx_q_gain(); + detect_gain_high = abs(detector_i_gain - detector_q_gain); + } + else + { + index = high; + low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x50->bits.TXQGAINCOMP = low; + detector_i_gain = bk7011_get_tx_i_gain(); + detector_q_gain = bk7011_get_tx_q_gain(); + detect_gain_low = abs(detector_i_gain - detector_q_gain); + } + + } + while((high - low) > 1); + index = ((detect_gain_low < detect_gain_high) ? low : high); + BK7011RCBEKEN.REG0x50->bits.TXQGAINCOMP = index; + if(gtx_gain_imb_cal_mode == TX_GAIN_IMB_CAL) + { + gtx_q_gain_comp = index; + } + else + { + gtx_q_gain_comp_loopback= index; + } + gold_index += (1023 << 16) + index; + } + + *val = gold_index; + if(gtx_gain_imb_cal_mode == TX_GAIN_IMB_CAL) + { + CAL_WARN("gtx_i_gain_comp:%d\r\n", gtx_i_gain_comp); + CAL_WARN("gtx_q_gain_comp:%d\r\n", gtx_q_gain_comp); + } + + BK7011TRX.REG0x0->value = 0x00039042;// + CAL_WR_TRXREGS(0x0); + return gold_index; +} + + +static INT32 bk7011_cal_tx_ty2(INT32 tx_phase_comp) +{ + float ty1, ty1_sqr, ty2; + INT32 tx_ty2; + + ty1 = -1.0 * ((tx_phase_comp - 512) * (tx_phase_comp - 512)) / (1024.0 * 1024.0); + ty1_sqr = ty1 * ty1; + ty2 = 1 - ty1 / 2 + 3 * ty1_sqr / 8; + tx_ty2 = (INT32)((ty2 - 0.5) * 1024 + 0.5); + + return tx_ty2; +} + +INT32 bk7011_cal_tx_phase_imbalance(INT32 *val) +{ + INT32 detect_phase_low = 0; + INT32 detect_phase_high = 0; + INT16 high, low; + INT32 index = 0, gold_index = 0; + INT32 detector_i_phase; + INT32 detector_q_phase; + + if(gtx_phase_imb_cal_mode == TX_PHASE_IMB_CAL) + { + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = gtx_i_dc_comp; + BK7011RCBEKEN.REG0x4F->bits.TXQDCCOMP = gtx_q_dc_comp; + BK7011RCBEKEN.REG0x50->bits.TXIGAINCOMP = gtx_i_gain_comp; + BK7011RCBEKEN.REG0x50->bits.TXQGAINCOMP = gtx_q_gain_comp; + BK7011TRX.REG0xD->value = TRX_REG_0XD_TX_IQ_VAL;//BK7011TRXREG0xD;//0214 close the TX switch to ellimite the antenna infect + CAL_WR_TRXREGS(0xD); + } + else + { + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = gtx_i_dc_comp_loopback; + BK7011RCBEKEN.REG0x4F->bits.TXQDCCOMP = gtx_q_dc_comp_loopback; + BK7011RCBEKEN.REG0x50->bits.TXIGAINCOMP = gtx_i_gain_comp_loopback; + BK7011RCBEKEN.REG0x50->bits.TXQGAINCOMP = gtx_q_gain_comp_loopback; + BK7011TRX.REG0xD->value = TRX_REG_0XD_TX_LOOPBACK_IQ_VAL; + CAL_WR_TRXREGS(0xD); + } + + BK7011RCBEKEN.REG0x51->bits.TXPHASECOMP = 512; + BK7011RCBEKEN.REG0x51->bits.TXTY2 = 512; + + BK7011RCBEKEN.REG0x4C->bits.TESTPATTERN = 1; + +#ifdef CALIBRATE_TIMES + if(gtx_phase_imb_cal_mode == TX_PHASE_IMB_CAL) + { + bk7011_set_tx_pa(gi_gain_tx_pa_dgainPA30, gi_gain_tx_pa_dgainbuf30, 3, 8); + } + else + { + bk7011_set_tx_pa(gi_phase_tx_loopback_pa_dgainPA30, gi_phase_tx_loopback_pa_dgainbuf30,3, 8); + + } + + if (p_gbias_after_cal_array == NULL) + { + if(gtx_phase_imb_cal_mode == TX_PHASE_IMB_CAL) + { + CAL_TIM_PRT("\r\nbk7011_cal_tx_phase_imbalance: \r\n"); + } + else + { + CAL_TIM_PRT("\r\nbk7011_cal_tx_loopback_phase_imbalance: \r\n"); + + } + + CAL_TIM_PRT("dgainPA30 = %d\r\n", BK7011TRX.REG0xC->bits.dgainPA30 ); //?? + CAL_TIM_PRT("dgainbuf30 =%d\r\n", BK7011TRX.REG0xC->bits.dgainbuf30); //?? + CAL_TIM_PRT("dgainpga = %d\r\n", BK7011TRX.REG0xC->bits.dgainpga ); //?? + CAL_TIM_PRT("gctrlmod30 = %d\r\n", BK7011TRX.REG0xB->bits.gctrlmod30); + } +#else + if(gtx_phase_imb_cal_mode == TX_PHASE_IMB_CAL) + { + bk7011_set_tx_pa(gi_gain_tx_pa_dgainPA30, gi_gain_tx_pa_dgainbuf30, 3, 8); + } + else + { + bk7011_set_tx_pa(gi_phase_tx_loopback_pa_dgainPA30, gi_phase_tx_loopback_pa_dgainbuf30,3, 8); + + } +#endif + + + BK7011TRX.REG0x0->bits.TSSIsel = 0; + BK7011TRX.REG0x0->bits.enDCcal = 0; + BK7011TRX.REG0x0->bits.tssi_statectrl = 1; + BK7011TRX.REG0x0->bits.tssi_selrange = 1; + BK7011TRX.REG0x0->bits.enIQcal = 1; + BK7011TRX.REG0x0->bits.enPcal = 0; +// BK7011TRX.REG0x0->bits.enPcaliGm = 0; + BK7011TRX.REG0xF->bits.tssi_cal_en = 1; + BK7011TRX.REG0x0->value = 0x0001A24E;// + + CAL_WR_TRXREGS(0x0); + CAL_WR_TRXREGS(0xC); + CAL_WR_TRXREGS(0xB); + CAL_WR_TRXREGS(0xF); + + low = bk7011_cal_tx_ty2(512); + low = 1 + 256; + BK7011RCBEKEN.REG0x51->bits.TXPHASECOMP = low; + BK7011RCBEKEN.REG0x51->bits.TXTY2 = bk7011_cal_tx_ty2( low); + detector_i_phase = bk7011_get_tx_i_phase(); + detector_q_phase = bk7011_get_tx_q_phase(); + detect_phase_low = abs(detector_i_phase - detector_q_phase); + + high = 1023 - 256; + BK7011RCBEKEN.REG0x51->bits.TXPHASECOMP = high; + BK7011RCBEKEN.REG0x51->bits.TXTY2 = bk7011_cal_tx_ty2( high); + detector_i_phase = bk7011_get_tx_i_phase(); + detector_q_phase = bk7011_get_tx_q_phase(); + detect_phase_high = abs(detector_i_phase - detector_q_phase); + + do + { + if(detect_phase_low < detect_phase_high) + { + index = low; + high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x51->bits.TXPHASECOMP = high; + BK7011RCBEKEN.REG0x51->bits.TXTY2 = bk7011_cal_tx_ty2( high); + detector_i_phase = bk7011_get_tx_i_phase(); + detector_q_phase = bk7011_get_tx_q_phase(); + detect_phase_high = abs(detector_i_phase - detector_q_phase); + } + else + { + index = high; + low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x51->bits.TXPHASECOMP = low; + BK7011RCBEKEN.REG0x51->bits.TXTY2 = bk7011_cal_tx_ty2( low); + detector_i_phase = bk7011_get_tx_i_phase(); + detector_q_phase = bk7011_get_tx_q_phase(); + detect_phase_low = abs(detector_i_phase - detector_q_phase); + } + } + while((high - low) > 1); + index = ((detect_phase_low < detect_phase_high) ? low : high); + BK7011RCBEKEN.REG0x51->bits.TXPHASECOMP = index; + + if(gtx_phase_imb_cal_mode == TX_PHASE_IMB_CAL) + { + gtx_phase_comp = BK7011RCBEKEN.REG0x51->bits.TXPHASECOMP; + gtx_phase_ty2 = BK7011RCBEKEN.REG0x51->bits.TXTY2; + + CAL_WARN("gtx_phase_comp:%d\r\n", gtx_phase_comp); + CAL_WARN("gtx_phase_ty2:%d\r\n", gtx_phase_ty2); + } + else + { + gtx_phase_comp_loopback = BK7011RCBEKEN.REG0x51->bits.TXPHASECOMP; + gtx_phase_ty2_loopback = BK7011RCBEKEN.REG0x51->bits.TXTY2; + +#ifdef CALIBRATE_TIMES + if (p_gtx_phase_comp_temp_array != NULL) + { + p_gtx_phase_comp_temp_array[calibrate_time] = gtx_phase_comp_loopback; + } +#endif + + CAL_WARN("tx_phase_comp:%d\r\n", gtx_phase_comp_loopback); + CAL_WARN("tx_phase_ty2:%d\r\n", gtx_phase_ty2_loopback); + } + gold_index = index; + BK7011TRX.REG0x0->value = 0x00039042;// + CAL_WR_TRXREGS(0x0); + return gold_index; +} + + +static float bk7011_get_tx_filter_i_ratio(void) +{ + INT32 rx_avg_i_14M, rx_avg_i_500K; + float rx_avg_ratio; + BK7011RCBEKEN.REG0x4D->bits.TXSINF = 250; // 9.7MHz + cal_delay_100us(3*gst_rx_adc); + rx_avg_i_14M = bk7011_get_rx_i_avg_signed(); + BK7011RCBEKEN.REG0x4D->bits.TXSINF = 125; // 4.85MHz; + cal_delay_100us(3*gst_rx_adc); + rx_avg_i_500K = bk7011_get_rx_i_avg_signed(); +// if(rx_avg_i_14M > 0) + { + rx_avg_ratio = abs(1.0 * rx_avg_i_500K / rx_avg_i_14M - 1.36); + return rx_avg_ratio; + } +// else +// { +// return -1.0; +// } +} + + +static float bk7011_get_tx_filter_i_ratio1(void) +{ + int i; + INT32 rx_avg_i_14M_array[100], rx_avg_i_500K_array[100]; + INT32 rx_avg_i_14M = 0, rx_avg_i_500K = 0; + float rx_avg_ratio; + BK7011RCBEKEN.REG0x4D->bits.TXSINF = 250; // 9.7MHz 20180308 BY YIMING; + + cal_delay_100us(2*gst_rx_adc); + for (i=0; i<40; i++) + { + cal_delay_100us(gst_rx_adc); + rx_avg_i_14M_array[i] = bk7011_get_rx_i_avg_signed(); + rx_avg_i_14M += rx_avg_i_14M_array[i]; + } + BK7011RCBEKEN.REG0x4D->bits.TXSINF = 125; // 4.85MHz; + + cal_delay_100us(2*gst_rx_adc); + for (i=0; i<40; i++) + { + cal_delay_100us(gst_rx_adc); + rx_avg_i_500K_array[i] = bk7011_get_rx_i_avg_signed(); + rx_avg_i_500K += rx_avg_i_500K_array[i]; + } +// if(rx_avg_i_14M > 0) + { + rx_avg_ratio = abs(1.0 * rx_avg_i_500K / rx_avg_i_14M - 1.36); + return rx_avg_ratio; + } +// else +// { +// return -1.0; +// } +} + + +static float bk7011_get_tx_filter_q_ratio(void) +{ + INT32 rx_avg_q_14M = 0, rx_avg_q_500K = 0; + float rx_avg_ratio; + BK7011RCBEKEN.REG0x4D->bits.TXSINF = 250; // 9.7MHz; + cal_delay_100us(3*gst_rx_adc); + rx_avg_q_14M = bk7011_get_rx_q_avg_signed(); + BK7011RCBEKEN.REG0x4D->bits.TXSINF = 125; // 4.85MHz; + cal_delay_100us(3*gst_rx_adc); + rx_avg_q_500K = bk7011_get_rx_q_avg_signed(); +// if(rx_avg_i_14M > 0) + { + rx_avg_ratio = abs(1.0 * rx_avg_q_500K / rx_avg_q_14M - 1.36); + return rx_avg_ratio; + } +// else +// { +// return -1.0; +// } +} + +static float bk7011_get_tx_filter_q_ratio1(void) +{ + int i; + INT32 rx_avg_q_14M_array[100], rx_avg_q_500K_array[100]; + INT32 rx_avg_q_14M = 0, rx_avg_q_500K = 0; + float rx_avg_ratio; + BK7011RCBEKEN.REG0x4D->bits.TXSINF = 250; // 9.7MHz; + + cal_delay_100us(2*gst_rx_adc); + for (i=0; i<40; i++) + { + cal_delay_100us(gst_rx_adc); + rx_avg_q_14M_array[i] = bk7011_get_rx_q_avg_signed(); + rx_avg_q_14M += rx_avg_q_14M_array[i]; + } + BK7011RCBEKEN.REG0x4D->bits.TXSINF = 125; // 4.85MHz; + + cal_delay_100us(2*gst_rx_adc); + for (i=0; i<40; i++) + { + cal_delay_100us(gst_rx_adc); + rx_avg_q_500K_array[i] = bk7011_get_rx_q_avg_signed(); + rx_avg_q_500K += rx_avg_q_500K_array[i]; + } +// if(rx_avg_q_14M > 0) + { + rx_avg_ratio = abs(1.0 * rx_avg_q_500K / rx_avg_q_14M - 1.36); + return rx_avg_ratio; + } +// else +// { +// return -1.0; +// } +} + +INT32 bk7011_cal_tx_filter_corner(INT32 *val) +{ + int i; + float float_1 = 1100.00; + float float_2 = 1100.00; + float tx_avg_ratio_low = 0.0; + float tx_avg_ratio_high = 0.0; + INT16 high, low; + INT32 index = 0, gold_index = 0; + + BK7011TRX.REG0x6->bits.capcal_sel = 0; + CAL_WR_TRXREGS(0x6); + + BK7011RCBEKEN.REG0x1C->bits.FRXON = 1; + // I CAL + BK7011TRX.REG0x6->bits.lpfcapcali50 = 0x20; + BK7011TRX.REG0xD->value = 0xFC4E03B9;//BK7011TRXREG0xD;//0xE00F02B9;//0xFC4E03B9;// + CAL_WR_TRXREGS(0x6); + CAL_WR_TRXREGS(0xD); + + //12/10/2014 for D version + BK7011TRX.REG0x0->bits.tssi_statectrl = 1; + BK7011TRX.REG0xF->bits.tssi_cal_en = 0; + BK7011TRX.REG0xF->bits.sinad_rx_en = 0; + CAL_WR_TRXREGS(0x0); + CAL_WR_TRXREGS(0xF); + + + BK7011RCBEKEN.REG0x4C->bits.TESTPATTERN = 2; + BK7011RCBEKEN.REG0x4D->bits.TXSINMODE = 1; + BK7011RCBEKEN.REG0x4D->bits.TXSINAMP = 6; + BK7011RCBEKEN.REG0x3C->bits.RXDCCALEN = 1; + BK7011RCBEKEN.REG0x3C->bits.RXAVGMODE = 1; + + + //cpu_delay(gst_rx_adc); + + low = 0; + BK7011TRX.REG0x6->bits.lpfcapcali50 = low; + CAL_WR_TRXREGS(0x6); + + tx_avg_ratio_low = bk7011_get_tx_filter_i_ratio(); + + high = 63; + BK7011TRX.REG0x6->bits.lpfcapcali50 = high; + CAL_WR_TRXREGS(0x6); + + tx_avg_ratio_high = bk7011_get_tx_filter_i_ratio(); + + do + { + if(tx_avg_ratio_low < tx_avg_ratio_high) + { + index = low; + high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011TRX.REG0x6->bits.lpfcapcali50 = high; + CAL_WR_TRXREGS(0x6); + tx_avg_ratio_high = bk7011_get_tx_filter_i_ratio(); + } + else + { + index = high; + low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011TRX.REG0x6->bits.lpfcapcali50 = low; + CAL_WR_TRXREGS(0x6); + tx_avg_ratio_low = bk7011_get_tx_filter_i_ratio(); + } + } + while((high - low) > 1); + index = ((tx_avg_ratio_low < tx_avg_ratio_high) ? low : high); + gold_index = index << 8; +// gtx_ifilter_corner = index; + + for (i=0; i<5; i++) + { + if (((index - 2 + i) >= 0) && ((index - 2 + i) < 64)) + { + BK7011TRX.REG0x6->bits.lpfcapcali50 = index - 2 + i; + CAL_WR_TRXREGS(0x6); +#ifdef SCAN_IQ_FILTER_CORNER + index_test[i+calibrate_time*5] = index - 2 + i; +#endif + float_2 = bk7011_get_tx_filter_i_ratio1(); +#ifdef SCAN_IQ_FILTER_CORNER + float2_test[i+calibrate_time*5] = float_2; +#endif + if (float_1 > float_2) + { + float_1 = float_2; + gtx_ifilter_corner = index - 2 + i; + } +// if (gtx_ifilter_corner == 11) +// { +// gtx_ifilter_corner = 11; +// } + } + } + + +#ifdef SCAN_IQ_FILTER_CORNER + g_sctrl_bias_reg = sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_BIAS_REG_READ, &g_sctrl_bias_reg); + g_sctrl_bias_reg = (g_sctrl_bias_reg >> PARAM_LDO_VAL_MANUAL_POSI) & PARAM_LDO_VAL_MANUAL_MASK; + + + BK7011TRX.REG0x6->bits.lpfcapcali50 = gtx_ifilter_corner; + CAL_WR_TRXREGS(0x6); + + grx_avg_i_14M = 0; + for (i=0; i<8; i++) + { + grx_avg_i_14M += bk7011_get_rx_i_avg_signed(); + } + + grx_avg_i_14M2 = 0; + BK7011RCBEKEN.REG0x4D->bits.TXSINF = 255; // 14MHz; + for (i=0; i<8; i++) + { + cal_delay_100us(3*gst_rx_adc); + grx_avg_i_14M2 += bk7011_get_rx_i_avg_signed(); + } +#endif + + // Q CAL + BK7011TRX.REG0x6->bits.lpfcapcalq50 = 0x20; + BK7011TRX.REG0xD->value = 0xFC4E03B9;//BK7011TRXREG0xD;//0xE00F02B9;//0xFC4E03B9;// + CAL_WR_TRXREGS(0x6); + CAL_WR_TRXREGS(0xD); + + //12/10/2014 for D version + BK7011TRX.REG0x0->bits.tssi_statectrl = 1; + BK7011TRX.REG0xF->bits.tssi_cal_en = 0; + BK7011TRX.REG0xF->bits.sinad_rx_en = 0; + CAL_WR_TRXREGS(0x0); + CAL_WR_TRXREGS(0xF); + + + BK7011RCBEKEN.REG0x4C->bits.TESTPATTERN = 2; + BK7011RCBEKEN.REG0x4D->bits.TXSINMODE = 2; + BK7011RCBEKEN.REG0x4D->bits.TXSINAMP = 6; + BK7011RCBEKEN.REG0x3C->bits.RXDCCALEN = 1; + BK7011RCBEKEN.REG0x3C->bits.RXAVGMODE = 1; + + + //cpu_delay(gst_rx_adc); + + low = 0; + BK7011TRX.REG0x6->bits.lpfcapcalq50 = low; + CAL_WR_TRXREGS(0x6); + + tx_avg_ratio_low = bk7011_get_tx_filter_q_ratio(); + + high = 63; + BK7011TRX.REG0x6->bits.lpfcapcalq50 = high; + CAL_WR_TRXREGS(0x6); + + tx_avg_ratio_high = bk7011_get_tx_filter_q_ratio(); + + do + { + if(tx_avg_ratio_low < tx_avg_ratio_high) + { + index = low; + high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011TRX.REG0x6->bits.lpfcapcalq50 = high; + CAL_WR_TRXREGS(0x6); + tx_avg_ratio_high = bk7011_get_tx_filter_q_ratio(); + } + else + { + index = high; + low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011TRX.REG0x6->bits.lpfcapcalq50 = low; + CAL_WR_TRXREGS(0x6); + tx_avg_ratio_low = bk7011_get_tx_filter_q_ratio(); + } + } + while((high - low) > 1); + index = ((tx_avg_ratio_low < tx_avg_ratio_high) ? low : high); + gold_index += index; +// gtx_qfilter_corner = index; + + float_1 = 1100; + for (i=0; i<5; i++) + { + if (((index - 2 + i) >= 0) && ((index - 2 + i) < 64)) + { + BK7011TRX.REG0x6->bits.lpfcapcalq50 = index - 2 + i; + CAL_WR_TRXREGS(0x6); + float_2 = bk7011_get_tx_filter_q_ratio1(); + if (float_1 > float_2) + { + float_1 = float_2; + gtx_qfilter_corner = index - 2 + i; + } + } + } + +#ifdef SCAN_IQ_FILTER_CORNER + + BK7011TRX.REG0x6->bits.lpfcapcalq50 = gtx_qfilter_corner; + CAL_WR_TRXREGS(0x6); + + grx_avg_q_14M = bk7011_get_rx_q_avg_signed(); + + + BK7011RCBEKEN.REG0x4D->bits.TXSINF = 255; // 14MHz; + cal_delay_100us(3*gst_rx_adc); + grx_avg_q_14M2 = bk7011_get_rx_q_avg_signed(); +#endif + + + // Q CAL + /* 20170504 iq used same value + + BK7011TRX.REG0x6->bits.lpfcapcalq50 = 0x20; + BK7011TRX.REG0xD->value = 0xFC4E03B9;//BK7011TRXREG0xD; + CAL_WR_TRXREGS(0x6); + CAL_WR_TRXREGS(0xD); + + //12/10/2014 for D version + BK7011TRX.REG0xF->bits.tssicalen = 0; + BK7011TRX.REG0xF->bits.sinadrxen = 0; + CAL_WR_TRXREGS(0xF); + + BK7011RCBEKEN.REG0x4C->bits.TESTPATTERN = 2; + BK7011RCBEKEN.REG0x4D->bits.TXSINMODE = 2; + BK7011RCBEKEN.REG0x4D->bits.TXSINAMP = 4; + BK7011RCBEKEN.REG0x3C->bits.RXDCCALEN = 1; + BK7011RCBEKEN.REG0x3C->bits.RXAVGMODE = 1; + + low = 0; + BK7011TRX.REG0x6->bits.lpfcapcalq50 = low; + CAL_WR_TRXREGS(0x6); + + tx_avg_ratio_low = bk7011_get_tx_filter_q_ratio(); + + high = 63; + BK7011TRX.REG0x6->bits.lpfcapcalq50 = high; + CAL_WR_TRXREGS(0x6); + + tx_avg_ratio_high = bk7011_get_tx_filter_q_ratio(); + + do + { + if(tx_avg_ratio_low < tx_avg_ratio_high) + { + index = low; + high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011TRX.REG0x6->bits.lpfcapcalq50 = high; + CAL_WR_TRXREGS(0x6); + + tx_avg_ratio_high = bk7011_get_tx_filter_q_ratio(); + } + else + { + index = high; + low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011TRX.REG0x6->bits.lpfcapcalq50 = low; + CAL_WR_TRXREGS(0x6); + + tx_avg_ratio_low = bk7011_get_tx_filter_q_ratio(); + } + } + while((high - low) > 1); + index = ((tx_avg_ratio_low < tx_avg_ratio_high) ? low : high); + gold_index += index; + gtx_qfilter_corner = index;//((index + ((gold_index & 0x0000ff00)>>8))>>1); + +*/ + BK7011TRX.REG0x6->bits.lpfcapcali50 = gtx_ifilter_corner; + BK7011TRX.REG0x6->bits.lpfcapcalq50 = gtx_qfilter_corner;//160405 iq used same value + //gtx_qfilter_corner = gtx_ifilter_corner; + CAL_WARN("gtx_ifilter_corner over: 0x%x\r\n", gtx_ifilter_corner); + CAL_WARN("gtx_qfilter_corner over: 0x%x\r\n", gtx_qfilter_corner); + + //BK7011TRX.REG0x6->bits.lpfcapcalq50 = gtx_qfilter_corner; + CAL_WR_TRXREGS(0x6); + + *val = gold_index; + return (gold_index); +} + +void bk7011_rx_cal_en(void) +{ + BK7011RCBEKEN.REG0x3E->bits.RXCOMPEN = 0; + + BK7011RCBEKEN.REG0x1C->bits.FRXON = 1; + BK7011RCBEKEN.REG0x1C->bits.FTXON = 0; + + BK7011RCBEKEN.REG0x0->bits.forceenable = 1; + cpu_delay(1); + BK7011RCBEKEN.REG0x19->bits.FCH0SHDN = 1; + BK7011RCBEKEN.REG0x19->bits.FCH0TXEN = 0; + BK7011RCBEKEN.REG0x19->bits.FCH0RXEN = 1; + BK7011RCBEKEN.REG0x19->bits.FCH0EN = 1; + + // ADC clock change to 80M + BK7011TRX.REG0xF->bits.clkadc_sel = 0;//20170331 1 --> 0 + CAL_WR_TRXREGS(0xF); + + BK7011TRX.REG0x12->bits.adcrefbwsel = 0;//20170331 1-->0 + CAL_WR_TRXREGS(0x12); +} + +INT32 bk7011_cal_rx_dc(void) +{ + INT32 index = 0; + INT32 i, j, k, t, curr, value; + + + /*step 2*/ + BK7011RCBEKEN.REG0x3C->bits.RXDCCALEN = 1; + BK7011RCBEKEN.REG0x3C->bits.RXAVGMODE = 0; + BK7011RCBEKEN.REG0x19->bits.FCH0RXHP = 0; //huaming.jiang 20141017 + BK7011RCBEKEN.REG0x1C->bits.FTXON = 0; + BK7011RCBEKEN.REG0x1C->bits.FRXON = 1; + +// BK7011TRX.REG0x7->bits.chin60 = 0x64; +// CAL_WR_TRXREGS(0x7); + BK7011TRX.REG0x5->bits.chspi = 0x64; + CAL_WR_TRXREGS(0x5); + delay100us(1);//delay 100us for RFPLL + + BK7011TRX.REG0xE->value = 0xDA01BCF0; /// D801BCF0;//170217 + CAL_WR_TRXREGS(0xE); + + for(i = 0; i < 16; i ++) + { + BK7011RCBEKEN.REG0x19->bits.FCH0B = (0x70 | i); + for(j = 0; j < 2; j ++) + { + index = 128; + k = 6; + do + { + //set dc offset + value = (*((volatile unsigned long *)(TRX_BEKEN_BASE + (0x14 + i / 2) * 4))); + curr = ~(0xff << (16 * (i % 2) + 8 * j)); + value &= curr; + curr = (index << (16 * (i % 2) + 8 * j)); + value |= curr; + (*((volatile unsigned long *)(TRX_BEKEN_BASE + (0x14 + i / 2) * 4))) = value; + while(BK7011RCBEKEN.REG0x1->value & 0xfffffff); + cal_delay_100us(gst_rx_adc); + + //read dc avg, and calc mean + value = 0; + for(t = 0; t < 10; t ++) + { + if(j == 0) curr = BK7011RCBEKEN.REG0x3C->bits.RXAVGIRD; + else curr = BK7011RCBEKEN.REG0x3C->bits.RXAVGQRD; + if(curr >= 2048) curr -= 4096; + value += curr; + cpu_delay(100); + } + curr = value / 10; + + //calc new dc offset + if(curr > 0) index += (0x1 << k); + else index -= (0x1 << k); + k --; + } + while((k >= 0) && ((curr >= 16) || (curr <= -16))); + if(k < 0) + { + value = (*((volatile unsigned long *)(TRX_BEKEN_BASE + (0x14 + i / 2) * 4))); + curr = ~(0xff << (16 * (i % 2) + 8 * j)); + value &= curr; + curr = (index << (16 * (i % 2) + 8 * j)); + value |= curr; + (*((volatile unsigned long *)(TRX_BEKEN_BASE + (0x14 + i / 2) * 4))) = value; + while(BK7011RCBEKEN.REG0x1->value & 0xfffffff); + } + } + } + + g_rx_dc_gain_tab[0] = BK7011TRXONLY.REG0x14->value; + g_rx_dc_gain_tab[1] = BK7011TRXONLY.REG0x15->value; + g_rx_dc_gain_tab[2] = BK7011TRXONLY.REG0x16->value; + g_rx_dc_gain_tab[3] = BK7011TRXONLY.REG0x17->value; + g_rx_dc_gain_tab[4] = BK7011TRXONLY.REG0x18->value; + g_rx_dc_gain_tab[5] = BK7011TRXONLY.REG0x19->value; + g_rx_dc_gain_tab[6] = BK7011TRXONLY.REG0x1A->value; + g_rx_dc_gain_tab[7] = BK7011TRXONLY.REG0x1B->value; + CAL_WARN("g_rx_dc_gain_tab 0 over: 0x%x\r\n", g_rx_dc_gain_tab[0]); + CAL_WARN("g_rx_dc_gain_tab 1 over: 0x%x\r\n", g_rx_dc_gain_tab[1]); + CAL_WARN("g_rx_dc_gain_tab 2 over: 0x%x\r\n", g_rx_dc_gain_tab[2]); + CAL_WARN("g_rx_dc_gain_tab 3 over: 0x%x\r\n", g_rx_dc_gain_tab[3]); + CAL_WARN("g_rx_dc_gain_tab 4 over: 0x%x\r\n", g_rx_dc_gain_tab[4]); + CAL_WARN("g_rx_dc_gain_tab 5 over: 0x%x\r\n", g_rx_dc_gain_tab[5]); + CAL_WARN("g_rx_dc_gain_tab 6 over: 0x%x\r\n", g_rx_dc_gain_tab[6]); + CAL_WARN("g_rx_dc_gain_tab 7 over: 0x%x\r\n", g_rx_dc_gain_tab[7]); + + BK7011RCBEKEN.REG0x3C->bits.RXDCCALEN = 0; + +// BK7011TRX.REG0x7->bits.chin60 = 0xc; +// CAL_WR_TRXREGS(0x7); + BK7011TRX.REG0x5->bits.chspi = 0xc; + CAL_WR_TRXREGS(0x5); + delay100us(1);//delay 100us for RFPLL + + return 0; +} + +INT32 bk7011_cal_rx_iq(INT32 *val) +{ + // INT32 rx_dc_i_rd, rx_dc_q_rd; + INT32 rx_amp_err_rd, rx_phase_err_rd, rx_ty2_rd; + INT32 rx_amp_err_wr; + INT32 rx_phase_err_wr; + float amp_err, phase_err, ty2_err; + INT32 gold_index = 0; + INT32 i, curr, value, value1, value2; + //bk7011_load_rxiq_init_cfg(); //v1.5 + + /*step 1*/ + BK7011RCBEKEN.REG0x1C->bits.FRXON = 1; + BK7011RCBEKEN.REG0x1C->bits.FTXON = 1; + + //BK7011ADDAMAP.REG0x5->bits.vc40 = 0x1f; + //BK7011ADDA.REG0x5->value = BK7011ADDAMAP.REG0x5->value; + + BK7011TRX.REG0x0->bits.tssi_statectrl = 1; + BK7011TRX.REG0xF->bits.tssi_cal_en = 0; + BK7011TRX.REG0xF->bits.sinad_rx_en = 0; + CAL_WR_TRXREGS(0x0); + CAL_WR_TRXREGS(0xF); + +#if 0 + BK7011TRX.REG0x9->bits.grxi2vspi10 = 1; //12dB + BK7011TRX.REG0x9->bits.agcrxfeEn = 0; //disable agc + + BK7011TRX.REG0x7->bits.autorxifgen = 0;//disable agc + BK7011TRX.REG0x7->bits.spilpfrxg30 = 0x0a; //33dB; + + //BK7011TRX.REG0x7->bits.digdcoen = 0; + CAL_WR_TRXREGS(0x7); + CAL_WR_TRXREGS(0x9); +#endif + + BK7011TRX.REG0xE->value = TRX_REG_0XE_RXIQ_VAL; + CAL_WR_TRXREGS(0xE); + //BK7011TRX.REG0xC->value = TRX_REG_0XC_RXIQ_VAL; + bk7011_set_tx_pa(gi_cal_rx_iq_pa_dgainPA30, gi_cal_rx_iq_pa_dgainbuf30, 4, 4); + + BK7011RCBEKEN.REG0x19->bits.FCH0B = 0x1a;//decrease 6dB + + + /*searching...*/ + BK7011RCBEKEN.REG0x3E->bits.RXCALEN = 1; + BK7011RCBEKEN.REG0x4C->bits.TESTPATTERN = 2; + BK7011RCBEKEN.REG0x4D->bits.TXSINMODE = 0; + BK7011RCBEKEN.REG0x4D->bits.TXSINAMP = 0x04; // increase 6dB + //BK7011RCBEKEN.REG0x3C->bits.RXAVGMODE = 0; + //BK7011RCBEKEN.REG0x3C->bits.RXDCCALEN = 1; + BK7011RCBEKEN.REG0x4D->bits.TXSINF = 179; // 7MHz; + cal_delay_100us(6*gst_rx_adc); + cpu_delay(500 * DELAY1US); + + //rx_dc_i_rd = BK7011RCBEKEN.REG0x3C->bits.RXAVGIRD; + //rx_dc_q_rd = BK7011RCBEKEN.REG0x3C->bits.RXAVGQRD; + + BK7011RCBEKEN.REG0x41->bits.RXDCIWR = 0x0; + BK7011RCBEKEN.REG0x41->bits.RXDCQWR = 0x0; + + //BK7011RCBEKEN.REG0x3C->bits.RXAVGMODE = 1; + //BK7011RCBEKEN.REG0x3C->bits.RXDCCALEN = 0; + + value = 0; + value1 = 0; + value2 = 0; + for(i = 0; i < 2; i ++) + { + curr = BK7011RCBEKEN.REG0x3F->bits.RXAMPERRRD; + value += curr - ((curr < 512) ? 0: 1024); + curr = BK7011RCBEKEN.REG0x3F->bits.RXPHASEERRRD; + value1 += curr - ((curr < 512) ? 0: 1024); + curr = BK7011RCBEKEN.REG0x40->bits.RXTY2RD; + value2 += curr - ((curr < 512) ? 0: 1024); + cpu_delay(gst_rx_adc); + } + rx_amp_err_rd = value / 2; + rx_phase_err_rd = value1 / 2; + rx_ty2_rd = value2 / 2; +/* rx_amp_err_rd = value; + rx_phase_err_rd = value1; + rx_ty2_rd = value2;*/ + + +#ifdef CALIBRATE_TIMES // by gwf + if (p_rx_amp_err_rd_array != NULL) + { + int rx_amp_err_rd_temp; + int rx_phase_err_rd_temp; + int rx_ty2_rd_temp; + if (rx_amp_err_rd & 0x200) + { + rx_amp_err_rd_temp = rx_amp_err_rd | 0xFFFFFC00; + } + else + { + rx_amp_err_rd_temp = rx_amp_err_rd & 0x000003FF; + } + if (rx_phase_err_rd & 0x200) + { + rx_phase_err_rd_temp = rx_phase_err_rd | 0xFFFFFC00; + } + else + { + rx_phase_err_rd_temp = rx_phase_err_rd & 0x000003FF; + } + if (rx_ty2_rd & 0x200) + { + rx_ty2_rd_temp = rx_ty2_rd | 0xFFFFFC00; + } + else + { + rx_ty2_rd_temp = rx_ty2_rd & 0x000003FF; + } + p_rx_amp_err_rd_array[calibrate_time] = rx_amp_err_rd_temp; + p_rx_phase_err_rd_array[calibrate_time] = rx_phase_err_rd_temp; + p_rx_ty2_rd_array[calibrate_time] = rx_ty2_rd_temp; +// printf("rx_amp_err_rd = %d %d\r\n", rx_amp_err_rd, rx_amp_err_rd_temp); +// printf("rx_phase_err_rd = %d %d\r\n", rx_phase_err_rd, rx_phase_err_rd_temp); + } + else +#endif + { + CAL_FATAL("[rx_iq]rx_amp_err_rd: 0x%03x\r\n", rx_amp_err_rd ); + CAL_FATAL("[rx_iq]rx_phase_err_rd: 0x%03x\r\n", rx_phase_err_rd ); + CAL_FATAL("[rx_iq]rx_ty2_rd: 0x%03x\r\n", rx_ty2_rd ); + } + + amp_err = 1.0 * rx_amp_err_rd / 1024; + phase_err = 1.0 * rx_phase_err_rd / 1024; + ty2_err = 1.0 * rx_ty2_rd / 1024; + + + //rx_amp_err_wr = (INT32) (512 * (ty2_err + 1) / (amp_err + 1) + 0.5); + //rx_phase_err_wr = (INT32) (512 * phase_err * (ty2_err + 1) + 0.5); + rx_amp_err_wr = (INT32) (512 * (ty2_err + 1) / (amp_err + 1)); + rx_phase_err_wr = (INT32) (512 * phase_err * (ty2_err + 1)); + + BK7011RCBEKEN.REG0x42->bits.RXPHASEERRWR = rx_phase_err_wr; + BK7011RCBEKEN.REG0x42->bits.RXAMPERRWR = rx_amp_err_wr; + BK7011RCBEKEN.REG0x3E->bits.RXCOMPEN = 1; + BK7011RCBEKEN.REG0x3E->bits.RXCALEN = 0; + + grx_amp_err_wr = rx_amp_err_wr; + grx_phase_err_wr = rx_phase_err_wr; + + CAL_WARN("grx_amp_err_wr:0x%03x\r\n", grx_amp_err_wr); + CAL_WARN("grx_phase_err_wr:0x%03x\r\n", grx_phase_err_wr); + + gold_index = (rx_amp_err_wr << 16 ) + rx_phase_err_wr; + *val = gold_index; + + BK7011TRX.REG0x9->bits.agcrxfeEn = 1; //enable agc + BK7011TRX.REG0x7->bits.autorxifgen = 1;//ensable agc + CAL_WR_TRXREGS(0x7); + CAL_WR_TRXREGS(0x9); + + return gold_index; +} + +void bk7011_set_rx_avg_dc(void) +{ + INT32 rx_dc_i_rd, rx_dc_q_rd; + + BK7011RCBEKEN.REG0x3E->bits.RXCOMPEN = 0; + BK7011RCBEKEN.REG0x3C->bits.RXAVGMODE = 0; + BK7011RCBEKEN.REG0x3C->bits.RXDCCALEN = 1; + cal_delay_100us(gst_rx_adc); + BK7011RCBEKEN.REG0x3C->bits.RXDCCALEN = 0; + + rx_dc_i_rd = BK7011RCBEKEN.REG0x3C->bits.RXAVGIRD; + rx_dc_q_rd = BK7011RCBEKEN.REG0x3C->bits.RXAVGQRD; + BK7011RCBEKEN.REG0x41->bits.RXDCIWR = rx_dc_i_rd; + BK7011RCBEKEN.REG0x41->bits.RXDCQWR = rx_dc_q_rd; + + BK7011RCBEKEN.REG0x3E->bits.RXCOMPEN = 1; + + return; +} + +INT32 bk7011_load_calibration_cfg(void) +{ + BK7011RCBEKEN.REG0x0->value = BK7011RCBEKEN.REG0x0->value; + BK7011RCBEKEN.REG0x1->value = BK7011RCBEKEN.REG0x1->value; + BK7011RCBEKEN.REG0x5->value = BK7011RCBEKEN.REG0x5->value ; + BK7011RCBEKEN.REG0x8->value = BK7011RCBEKEN.REG0x8->value; + BK7011RCBEKEN.REG0xB->value = BK7011RCBEKEN.REG0xB->value; + BK7011RCBEKEN.REG0x11->value = BK7011RCBEKEN.REG0x11->value; + BK7011RCBEKEN.REG0x19->value = BK7011RCBEKEN.REG0x19->value; + BK7011RCBEKEN.REG0x1E->value = BK7011RCBEKEN.REG0x1E->value; + + /**********NEW ADDED************/ + BK7011RCBEKEN.REG0x3C->value = BK7011RCBEKEN.REG0x3C->value; + BK7011RCBEKEN.REG0x3E->value = BK7011RCBEKEN.REG0x3E->value; + BK7011RCBEKEN.REG0x3F->value = BK7011RCBEKEN.REG0x3F->value; + BK7011RCBEKEN.REG0x40->value = BK7011RCBEKEN.REG0x40->value; + BK7011RCBEKEN.REG0x41->value = BK7011RCBEKEN.REG0x41->value; + BK7011RCBEKEN.REG0x42->value = BK7011RCBEKEN.REG0x42->value ; + BK7011RCBEKEN.REG0x4C->value = BK7011RCBEKEN.REG0x4C->value; + BK7011RCBEKEN.REG0x4D->value = BK7011RCBEKEN.REG0x4D->value; + BK7011RCBEKEN.REG0x4F->value = BK7011RCBEKEN.REG0x4F->value; + BK7011RCBEKEN.REG0x50->value = BK7011RCBEKEN.REG0x50->value; + BK7011RCBEKEN.REG0x51->value = BK7011RCBEKEN.REG0x51->value; + BK7011RCBEKEN.REG0x52->value = BK7011RCBEKEN.REG0x52->value; + BK7011RCBEKEN.REG0x54->value = BK7011RCBEKEN.REG0x54->value; + BK7011RCBEKEN.REG0x5C->value = BK7011RCBEKEN.REG0x5C->value; + + while(BK7011RCBEKEN.REG0x1->value & 0x0FFFFFFF) + { + cpu_delay(1); + } + BK7011TRXONLY.REG0x0->value = grc_reg_map[0]; + BK7011TRXONLY.REG0x1->value = grc_reg_map[1]; + BK7011TRXONLY.REG0x2->value = grc_reg_map[2]; + BK7011TRXONLY.REG0x3->value = grc_reg_map[3]; + BK7011TRXONLY.REG0x4->value = grc_reg_map[4]; + BK7011TRXONLY.REG0x6->value = grc_reg_map[6]; + BK7011TRXONLY.REG0x7->value = grc_reg_map[7]; + BK7011TRXONLY.REG0x8->value = grc_reg_map[8]; + BK7011TRXONLY.REG0x9->value = grc_reg_map[9]; + BK7011TRXONLY.REG0xA->value = grc_reg_map[10]; + BK7011TRXONLY.REG0xB->value = grc_reg_map[11]; + BK7011TRXONLY.REG0xC->value = grc_reg_map[12]; + BK7011TRXONLY.REG0xD->value = grc_reg_map[13]; + BK7011TRXONLY.REG0xE->value = grc_reg_map[14]; + BK7011TRXONLY.REG0x11->value = grc_reg_map[17]; + BK7011TRXONLY.REG0x12->value = grc_reg_map[18]; + BK7011TRXONLY.REG0x13->value = grc_reg_map[19]; + BK7011TRXONLY.REG0x14->value = grc_reg_map[20]; + BK7011TRXONLY.REG0x15->value = grc_reg_map[21]; + BK7011TRXONLY.REG0x16->value = grc_reg_map[22]; + BK7011TRXONLY.REG0x17->value = grc_reg_map[23]; + BK7011TRXONLY.REG0x18->value = grc_reg_map[24]; + BK7011TRXONLY.REG0x19->value = grc_reg_map[25]; + BK7011TRXONLY.REG0x1A->value = grc_reg_map[26]; + BK7011TRXONLY.REG0x1B->value = grc_reg_map[27]; + + while(BK7011RCBEKEN.REG0x1->value & 0x0FFFFFFF) + { + cpu_delay(1); + } + + BK7011TRX.REG0x7->bits.autorxifgen = 0; + BK7011TRX.REG0x7->bits.dig_dcoen = 0; + BK7011TRX.REG0x7->bits.spilpfrxg30 = 6; + CAL_WR_TRXREGS(0x7); + + BK7011TRX.REG0x6->bits.lpfcapcali50 = gtx_ifilter_corner; + BK7011TRX.REG0x6->bits.lpfcapcalq50 = gtx_qfilter_corner; + CAL_WR_TRXREGS(0x6); + + bk7011_set_rx_avg_dc(); // 11/11/2014 + + return 0; +} + +void bk7011_set_tx_after_cal(void) +{ + BK7011RCBEKEN.REG0x0->bits.forceenable = 0; + cpu_delay(1); + BK7011RCBEKEN.REG0x19->bits.FCH0EN = 1; + BK7011RCBEKEN.REG0x19->bits.FCH0SHDN = 1; + BK7011RCBEKEN.REG0x19->bits.FCH0RXEN = 0; + BK7011RCBEKEN.REG0x19->bits.FCH0TXEN = 1; + BK7011RCBEKEN.REG0x1C->bits.FRXON = 0; + BK7011RCBEKEN.REG0x1C->bits.FTXON = 1; + BK7011RCBEKEN.REG0x4C->bits.TESTPATTERN = 0; + //BK7011ICU.REG0x1->bits.txon = 1; + //BK7011ICU.REG0x1->bits.rxon = 0; +} + +void bk7011_set_rx_after_cal(void) +{ + BK7011RCBEKEN.REG0x0->bits.forceenable = 0; + cpu_delay(1); + BK7011RCBEKEN.REG0x19->bits.FCH0EN = 1; + BK7011RCBEKEN.REG0x19->bits.FCH0SHDN = 1; + BK7011RCBEKEN.REG0x19->bits.FCH0RXEN = 1; + BK7011RCBEKEN.REG0x19->bits.FCH0TXEN = 0; + BK7011RCBEKEN.REG0x1C->bits.FRXON = 1; + BK7011RCBEKEN.REG0x1C->bits.FTXON = 0; + BK7011RCBEKEN.REG0x4C->bits.TESTPATTERN = 0; + + BK7011TRX.REG0xE->value = 0xDA01BCF0; + CAL_WR_TRXREGS(0xE); + + + //BK7011TRX.REG0xC->value = TRX_REG_0XC_VAL; //170217 delete + //CAL_WR_TRXREGS(0xC); + + //BK7011ICU.REG0x1->bits.txon = 0; + //BK7011ICU.REG0x1->bits.rxon = 1; + + // ADC clock change to 40M + BK7011TRX.REG0xF->bits.clkadc_sel = 0; + CAL_WR_TRXREGS(0xF); + + BK7011TRX.REG0x12->bits.adcrefbwsel = 0; + CAL_WR_TRXREGS(0x12); + +} + +extern void mpb_tx_mode(void); + +#define CALI_DPD_TEST 0 +#if CALI_DPD_TEST +#define I_TABLE_ADDR 0x01050400 +#define Q_TABLE_ADDR 0x01050600 + +static UINT16 i_table_val[256] = +{ + 0, 6, 13, 19, 26, 35, 40, 47, 52, 57, 68, 73, 76, 82, 88, 91, 96, 102, 107, 107, 118, 118, 120, 127, 132, 134, 139, 141, 146, 149, 152, 158, 161, 161, 163, 164, 168, 172, 172, 176, 181, 177, 179, 181, 185, 187, 189, 185, 191, 195, 196, 195, 196, 197, 203, 198, 204, 201, 207, 199, 206, 207, 207, 207, 207, 210, 210, 212, 214, 215, 215, 215, 206, 216, 215, 221, 217, 219, 215, 219, 222, 222, 225, 229, 225, 223, 228, 226, 226, 229, 229, 226, 225, 227, 226, 226, 228, 232, 230, 229, 230, 231, 230, 231, 234, 235, 236, 238, 241, 244, 245, 247, 248, 251, 252, 255, 255, 258, 259, 262, 263, 265, 267, 268, 271, 272, 275, 275, 278, 280, 282, 284, 287, 288, 291, 293, 295, 297, 299, 301, 304, 306, 308, 310, 312, 314, 317, 319, 321, 323, 325, 327, 330, 332, 334, 336, 338, 341, 343, 345, 347, 349, 351, 354, 356, 358, 360, 362, 364, 367, 369, 371, 373, 375, 377, 380, 382, 384, 386, 388, 390, 393, 395, 397, 399, 401, 403, 406, 408, 410, 412, 414, 416, 419, 421, 423, 425, 427, 429, 432, 434, 436, 438, 440, 442, 445, 447, 449, 451, 453, 455, 458, 460, 462, 464, 466, 468, 471, 473, 475, 477, 479, 481, 484, 486, 488, 490, 492, 495, 497, 499, 501, 503, 505, 508, 510, 512, 514, 516, 518, 521, 523, 525, 527, 529, 531, 534, 536, 538, 540, 542, 544, 547, 549, 551, 562 +}; + +static UINT16 q_table_val[256] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 1, 5, 8, 5, 9, 6, 5, 7, 4, 7, 8, 17, 13, 12, 14, 15, 12, 12, 18, 12, 13, 16, 16, 17, 19, 20, 24, 22, 30, 23, 21, 24, 30, 27, 26, 24, 27, 26, 30, 28, 30, 32, 31, 31, 32, 32, 33, 35, 35, 33, 35, 34, 32, 32, 32, 34, 33, 32, 31, 32, 30, 33, 29, 30, 29, 30, 29, 29, 28, 27, 29, 27, 28, 26, 26, 26, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 30, 30, 30, 30, 30, 31, 31, 31, 31, 31, 32, 32, 32, 32, 32, 33, 33, 33, 33, 33, 34, 34, 34, 34, 34, 35, 35, 35, 35, 35, 36, 36, 36, 36, 36, 37, 37, 37, 37, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 42, 42, 42, 42, 42, 43, 43, 43, 43, 43, 44, 44, 44, 44, 44, 45, 45, 45, 45, 45, 46, 46, 46, 46, 46, 47, 47, 47, 47, 48, 48, 48, 48, 48, 49, 49, 49, 49, 49, 50, 50, 50, 50, 50, 51, 51, 51, 51, 51, 52, 52, 48 +}; + +UINT32 bk7211_cal_tx_dpd_load(void) +{ + + UINT16 *i_tbl_addr = (UINT16 *)I_TABLE_ADDR; + UINT16 *q_tbl_addr = (UINT16 *)Q_TABLE_ADDR; + UINT16 k; + + BK7011RCBEKEN.REG0x4C->bits.DPDEN = 0; + + os_memcpy(i_tbl_addr, (UINT16 *)&i_table_val[0], 256 * 2); + os_memcpy(q_tbl_addr, (UINT16 *)&q_table_val[0], 256 * 2); + +#if 1 + for(k = 0; k < 256; k++) + { + i_tbl_addr[k] = 1; + q_tbl_addr[k] = 0; + } +#endif + return 0; + +} +#endif + +#if CAL_RESULT_TO_FLASH +void write_cal_result_to_flash(void) +{ + UINT32 param; + UINT32 param1; + char cTemp[sizeof(bk7011_rc_val) + sizeof(bk7011_trx_val)]; + char cTemp1[sizeof(bk7011_rc_val) + sizeof(bk7011_trx_val)]; + + CAL_FLASH_PRT("write cal result to flash\r\n"); + +// flash_ctrl(CMD_FLASH_READ_SR, ¶m); +// os_printf("param = 0x%x\r\n", param); + #if CFG_SUPPORT_ALIOS + hal_flash_dis_secure(0, 0, 0); + #else + bk_flash_enable_security(FLASH_PROTECT_NONE); + #endif +// os_printf("param1 = 0x%x\r\n", param1); + +// param = CAL_RESULT_FLASH_ADDR; +// flash_ctrl(CMD_FLASH_ERASE_SECTOR, ¶m); + flash_erase_sector(CAL_RESULT_FLASH_ADDR); + + memcpy(cTemp, bk7011_rc_val, sizeof(bk7011_rc_val)); + memcpy(cTemp+sizeof(bk7011_rc_val), bk7011_trx_val, sizeof(bk7011_trx_val)); +// memset(cTemp, 0, sizeof(cTemp)); + flash_write(cTemp, sizeof(cTemp), CAL_RESULT_FLASH_ADDR); + flash_read(cTemp1, sizeof(cTemp1), CAL_RESULT_FLASH_ADDR); + if (memcmp(cTemp, cTemp1, sizeof(cTemp1)) == 0) + { + CAL_FLASH_PRT("memcmp OK\r\n"); + } + else + { + CAL_FLASH_PRT("memcmp fail\r\n"); + } + +// param = 2 | ((param&0x00FFFF)<<8); + #if CFG_SUPPORT_ALIOS + hal_flash_enable_secure(0, 0, 0); + #else + bk_flash_enable_security(FLASH_UNPROTECT_LAST_BLOCK); + #endif +// param = 0; +// flash_ctrl(CMD_FLASH_READ_SR, ¶m); +// os_printf("param = 0x%x\r\n", param); + + os_printf("write cal result to flash OK\r\n"); +} +#endif + +char read_cal_result_from_flash(void) +{ +#if CAL_RESULT_TO_FLASH + char cTemp[sizeof(bk7011_rc_val) + sizeof(bk7011_trx_val)]; + + CAL_FLASH_PRT("read_cal_result_from_flash\r\n"); + memset(cTemp, 0, sizeof(cTemp)); + flash_read(cTemp, sizeof(cTemp), CAL_RESULT_FLASH_ADDR); + if ((cTemp[0] == 0xFF) && (cTemp[4] == 0xFF) && (cTemp[8] == 0xFF) && (cTemp[12] == 0xFF)) + { + return 0; + } + else + { + memcpy(bk7011_rc_val, cTemp, sizeof(bk7011_rc_val)); + memcpy(bk7011_trx_val, cTemp+sizeof(bk7011_rc_val), sizeof(bk7011_trx_val)); + rwnx_cal_load_default_result(); + rwnx_cal_load_trx_rcbekn_reg_val(); +// printf_trx_rc_value(); + os_printf("read cal result from flash OK\r\n"); + return 1; + } +#else + return 0; +#endif +} + +#if CAL_RESULT_TO_FLASH +void flash_test(void) +{ + UINT32 param; + char cTemp[0x1000]; + char cTemp1[0x1000]; + int i; + + flash_read(cTemp, 0x1000, 0xF4000); + os_printf("cTemp:\r\n"); + for (i=0; i<0x1000; i++) + { + os_printf("%x ", cTemp[i]); + } + os_printf("\r\n"); + + #if CFG_SUPPORT_ALIOS + hal_flash_dis_secure(0, 0, 0); + #else + bk_flash_enable_security(FLASH_PROTECT_NONE); + #endif + param = 0xF4000; + flash_ctrl(CMD_FLASH_ERASE_SECTOR, ¶m); + + flash_read(cTemp, 0x1000, 0xF4000); + os_printf("cTemp:\r\n"); + for (i=0; i<0x1000; i++) + { + os_printf("%x ", cTemp[i]); + } + os_printf("\r\n"); + + for (i=0; i<0x1000; i++) + { + cTemp[i] = i; + } + os_printf("cTemp:\r\n"); + for (i=0; i<0x1000; i++) + { + os_printf("%x ", cTemp[i]); + } + os_printf("\r\n"); + + flash_write(cTemp, 0x1000, 0xF4000); + + memset(cTemp1, 0, 0x1000); + os_printf("cTemp1:\r\n"); + for (i=0; i<0x1000; i++) + { + os_printf("%x ", cTemp1[i]); + } + os_printf("\r\n"); + flash_read(cTemp1, 0x1000, 0xF4000); + + os_printf("cTemp1:\r\n"); + for (i=0; i<0x1000; i++) + { + os_printf("%x ", cTemp1[i]); + } + + os_printf("\r\n"); + if (memcmp(cTemp, cTemp1, sizeof(cTemp)) == 0) + { + os_printf("memcmp OK\r\n"); + } + else + { + os_printf("memcmp ERROR\r\n"); + } +} +#endif + +void sctrl_dpll_int_open(void); +void calibration_main(void) +{ + INT32 goldval[32] = {0}; + +// printf("calibration_main: %s %s\r\n", __DATE__, __TIME__); + memcpy(bk7011_trx_val, bk7011_trx_val1, sizeof(bk7011_trx_val)); + memcpy(bk7011_rc_val, bk7011_rc_val1, sizeof(bk7011_rc_val)); + + //REG_WRITE((0x0802800 + (18 * 4)), 0x02); + BK7011RCBEKEN.REG0x4C->bits.TXCOMPDIS = 0; + bk7011_cal_ready(); + bk7011_cal_bias(); + + //bk7011_doubler_cal(); + //bk7011_band_cal(); + + //bk7011_cal_pll(); + //bk7011_rfpll_ld(); + + bk7011_cal_dpll(); + sctrl_dpll_int_open(); + + BK7011TRX.REG0xA->value = TRX_REG_0XA_VAL; + CAL_WR_TRXREGS(0xA); + BK7011TRX.REG0xB->value = TRX_REG_0XB_VAL; + CAL_WR_TRXREGS(0xB); + BK7011TRX.REG0xC->value = TRX_REG_0XC_VAL; + CAL_WR_TRXREGS(0xC); + + + if (read_cal_result_from_flash() == 1) + { + return; + } + + +// BK7011TRX.REG0x7->bits.chin60 = 0x00;//2400MHz descrease the external interference +// CAL_WR_TRXREGS(0x7); + BK7011TRX.REG0x5->bits.chspi = 0x00;//2400MHz descrease the external interference + CAL_WR_TRXREGS(0x5); + delay100us(1);//delay 100us for RFPLL + + bk7011_tx_cal_en(); + bk7011_cal_bias(); + bk7011_cal_tx_filter_corner(goldval); + + gtx_power_cal_mode = TX_IQ_POWER_CAL; + bk7011_cal_tx_output_power(goldval); // First cal just to enable BK7231 TX work for temp. balance + + //bk7011_cal_bias();//second cal after PA on; + + //bk7011_cal_pll();//second cal after PA on; + //delay100us(1);//delay 100us for RFPLL + + // gtx_power_cal_mode = TX_IQ_POWER_CAL; + // bk7011_cal_tx_output_power(goldval); // real PA cal. + + BK7011TRX.REG0xB->bits.gctrlmod30 = 0x8; + CAL_WR_TRXREGS(0xB); + + gtx_dc_cal_mode = TX_DC_CAL_IQ; + bk7011_cal_tx_dc(goldval); + +/* + gtx_power_cal_mode = TX_WANTED_POWER_CAL; + cpu_delay(100); + bk7011_cal_tx_output_power(goldval); // +*/ + + + gtx_gain_imb_cal_mode = TX_GAIN_IMB_CAL; + bk7011_cal_tx_gain_imbalance(goldval); + + gtx_phase_imb_cal_mode = TX_PHASE_IMB_CAL; + bk7011_cal_tx_phase_imbalance(goldval); + + +// BK7011TRX.REG0xB->value = TRX_REG_0XB_VAL; + + gtx_dc_cal_mode = TX_DC_CAL; + bk7011_cal_tx_dc(goldval); + +// BK7011TRX.REG0x7->bits.chin60 = 0x5d;//2495MHz +// CAL_WR_TRXREGS(0x7); + BK7011TRX.REG0x5->bits.chspi = 0x5d;//2495MHz + CAL_WR_TRXREGS(0x5); + delay100us(1);//delay 100us for RFPLL + + + bk7011_cal_bias(); + + + gtx_power_cal_mode = TX_WANTED_POWER_CAL; + +// BK7011TRX.REG0x7->bits.chin60 = 0xc;//fix to this channel for power cal. +// CAL_WR_TRXREGS(0x7); + BK7011TRX.REG0x5->bits.chspi = 0xc;//fix to this channel for power cal. + CAL_WR_TRXREGS(0x5); + delay100us(1);//delay 100us for RFPLL + + bk7011_cal_tx_output_power(goldval); // Actual Power cal. + + bk7011_set_tx_after_cal(); + rwnx_tx_cal_save_cal_result();//by yiming 20170315 + +// BK7011TRX.REG0x7->bits.chin60 = 0x5d;//2495MHz +// CAL_WR_TRXREGS(0x7); + BK7011TRX.REG0x5->bits.chspi = 0x5d;//2495MHz + CAL_WR_TRXREGS(0x5); + delay100us(1);//delay 100us for RFPLL + + bk7011_rx_cal_en(); + bk7011_cal_rx_dc(); + + bk7011_tx_cal_en(); + + BK7011TRX.REG0x5->bits.chspi = 0x5d;//2495MHz + CAL_WR_TRXREGS(0x5); + delay100us(1);//delay 100us for RFPLL + + + //20170804 by yiming + gtx_power_cal_mode = TX_IQ_LOOPBACK_POWER_CAL; + bk7011_cal_tx_output_power(goldval); + bk7011_cal_bias(); + bk7011_cal_pll(); + delay100us(1);//delay 100us for RFPLL + + gtx_power_cal_mode = TX_IQ_LOOPBACK_POWER_CAL; + bk7011_cal_tx_output_power(goldval); + + gtx_dc_cal_mode = TX_DC_LOOPBACK_CAL_IQ; + bk7011_cal_tx_dc(goldval);//Loopback DC cal. + + + gtx_gain_imb_cal_mode = TX_GAIN_LOOPBACK_IMB_CAL; + bk7011_cal_tx_gain_imbalance(goldval); + +#ifdef CALIBRATE_TIMES + if (p_gtx_i_gain_comp_temp_array != NULL) + { +// gtx_i_gain_comp_temp_array[calibrate_time] = BK7011RCBEKEN.REG0x50->bits.TXIGAINCOMP; +// gtx_q_gain_comp_temp_array[calibrate_time] = BK7011RCBEKEN.REG0x50->bits.TXQGAINCOMP; + p_gtx_i_gain_comp_temp_array[calibrate_time] =( (*((volatile unsigned long * )(0x01050000 + 0x50*4))) >> 16) & 0x03FF ; + p_gtx_q_gain_comp_temp_array[calibrate_time] = (*((volatile unsigned long * )(0x01050000 + 0x50*4))) & 0x03FF ; + } +#endif + + gtx_phase_imb_cal_mode = TX_PHASE_LOOPBACK_IMB_CAL; + bk7011_cal_tx_phase_imbalance(goldval); + + bk7011_rx_cal_en(); + bk7011_cal_rx_iq(goldval); + + + bk7011_load_calibration_cfg(); + bk7011_set_rx_after_cal(); + //REG_WRITE((0x0802800 + (18 * 4)), 0x00); + + //rwnx_cal_read_current_cal_result(); + rwnx_rx_cal_save_cal_result(); + rwnx_cal_load_default_result(); + rwnx_cal_read_current_cal_result(); + BK7011RCBEKEN.REG0x4C->bits.TXCOMPDIS = 0; + + rwnx_tx_cal_save_cal_result();//by yiming 20170315 + rwnx_cal_load_trx_rcbekn_reg_val(); + +#if CALI_DPD_TEST + rwnx_cal_load_trx_rcbekn_reg_val(); + bk7211_cal_tx_dpd_load(); +#endif + bk7011_cal_dpll(); + sctrl_dpll_int_open(); +/* + gtx_power_cal_mode = TX_WANTED_POWER_CAL; + cpu_delay(100); + bk7011_cal_tx_output_power(goldval); // +*/ +#if CAL_RESULT_TO_FLASH + write_cal_result_to_flash(); +// printf_trx_rc_value(); +#endif + return ; +} + +void do_calibration_in_temp_dect(void) +{ + INT32 goldval[32] = {0}; + +// BK7011TRX.REG0x7->bits.chin60 = 0xc;//fix to this channel for power cal. +// CAL_WR_TRXREGS(0x7); + BK7011TRX.REG0x5->bits.chspi = 0xc;//fix to this channel for power cal. + CAL_WR_TRXREGS(0x5); + delay100us(1);//delay 100us for RFPLL + + bk7011_read_cal_param(); + rwnx_cal_load_default_result(); + cpu_delay(10);//cpu_delay(10); 20160801 + + bk7011_cal_bias(); + + BK7011RCBEKEN.REG0x4C->bits.TXCOMPDIS = 0; + + bk7011_tx_cal_en(); + //gtxoutput = 1; + //bk7011_cal_tx_output_power(goldval); // first time + + gtx_power_cal_mode = TX_WANTED_POWER_CAL; + bk7011_cal_tx_output_power(goldval); // second time + + bk7011_set_tx_after_cal(); + //REG_WRITE((0x0802800 + (19 * 4)), 0x00); + + //rwnx_cal_read_current_cal_result(); + rwnx_tx_cal_save_cal_result(); + rwnx_cal_load_default_result(); + rwnx_cal_read_current_cal_result(); + BK7011RCBEKEN.REG0x4C->bits.TXCOMPDIS = 0; + + bk7011_cal_dpll(); + sctrl_dpll_int_open(); + + return ; +} + +UINT32 dgainpga = 0; +void turnoff_PA_in_temp_dect(void) +{ + dgainpga = BK7011TRXONLY.REG0xC->bits.dgainpga; + BK7011TRX.REG0xC->bits.dgainpga = 0; + + CAL_WR_TRXREGS(0xC); +} + +void turnon_PA_in_temp_dect(void) +{ + BK7011TRX.REG0xC->bits.dgainpga = dgainpga; + CAL_WR_TRXREGS(0xC); +} + +void bk7011_la_sample_print(UINT32 isrx) +{ + UINT32 reg_val, i, len; + UINT8 *buf; + + #define LA_SAMPLE_BUF_LEN (90 *1024) + + buf = os_malloc(LA_SAMPLE_BUF_LEN); + if(!buf) { + os_printf("la_sample_print no buffer\r\n"); + return; + } + + //len = 128 * 1024 / 4; + len = LA_SAMPLE_BUF_LEN / 4; + + REG_WRITE((0x00800000 + 0x12*4), 0x0); + + REG_WRITE((0x00800000 + 0x15*4), (UINT32)buf); + REG_WRITE((0x00800000 + 0x12*4), (len << 16) | 0x4); + + //ADC Data + if(isrx) { + REG_WRITE((0x01060000+0x0*4), 0x21); // addMACPHY_BYPASS_Reg0x0 = 0x21; + delay100us(100); + } + REG_WRITE((0x00800000 + 0xd*4), 0x00040000); // addSYS_CTRL_Reg0xd = 0x00040000; + REG_WRITE((0x00800000 + 0x14*4), 0xfe000000); // addSYS_CTRL_Reg0x14 = 0xfe000000; + if(isrx) { + REG_WRITE((0x00800000 + 0x13*4), 0x0a000000); // addSYS_CTRL_Reg0x13 = 0x0a000000; + } else { + REG_WRITE((0x00800000 + 0x13*4), 0x0c000000); // addSYS_CTRL_Reg0x13 = 0x0c000000; + } + reg_val = REG_READ((0x00800000 + 0x12*4)); // set_SYS_CTRL_Reg0x12_LaSmpMode(0x1); + reg_val = (reg_val & (~0x3)) | 0x01; + REG_WRITE((0x00800000 + 0x12*4), reg_val); + + do { + reg_val = REG_READ((0x00800000 + 0x12*4)); + os_printf("abc:%x\r\n",reg_val&0x8); + } while(reg_val & 0x8); // while(!get_SYS_CTRL_Reg0x12_LaSmpFinish) + + delay100us(100); + + reg_val = REG_READ((0x00800000 + 0x12*4)); // set_SYS_CTRL_Reg0x12_LaSmpMode(0x0); + reg_val = (reg_val & (~0x3)) | 0x00; + REG_WRITE((0x00800000 + 0x12*4), reg_val); + + for(i = 0; i < len; i ++) + { + os_printf("%08x\r\n", *((uint32_t *)(buf+i*4))); + } + + os_free(buf); +} + + +#else /* CFG_SUPPORT_CALIBRATION */ +/*INT32 rwnx_cal_load_trx_rcbekn_reg_val(void) +{ +} +INT32 rwnx_cal_save_trx_rcbekn_reg_val(void) +{ +} +void rwnx_cal_set_txpwr_by_rate(INT32 rate) +{ +} +void calibration_main(void) +{ +} +void calibration_auto_test(void) +{ +}*/ +#endif /* CFG_SUPPORT_CALIBRATION */ + +#endif // (CFG_SOC_NAME != SOC_BK7231) +// eof + diff --git a/beken_os/beken378/func/bk7011_cal/bk7221U_cal.h b/beken_os/beken378/func/bk7011_cal/bk7221U_cal.h new file mode 100755 index 0000000..50ada12 --- /dev/null +++ b/beken_os/beken378/func/bk7011_cal/bk7221U_cal.h @@ -0,0 +1,1877 @@ +#ifndef _BK7231U_CAL_H_ +#define _BK7231U_CAL_H_ + +#if (CFG_SOC_NAME == SOC_BK7221U) + +#define INCLUDE_OS + +#define CALIBRATE_TIMES 2000 +#undef CALIBRATE_TIMES // by gwf + +#define REGTRXV2A +#define BK7011_VER_A + +//#define _11MBPS_MAX_POWER + +void delay05us(INT32 num); + + + + +#define trx_reg_is_write(st_trxreg) while(BK7011RCBEKEN.REG0x1->value & st_trxreg) {cpu_delay(1);} + +#define DETECT_LOOPCNT 10 +#define GOLD_OUTPUT_POWER 56 +#define UNSIGNEDOFFSET10 512 +#define I_Q_CAP_DIF 32 +#define CONSTANT_RCIQ 117 +#define SUMNUMBERS 4 +#define MINOFFSET 16 + +//#define DPDCALILEN 256 + +#define cpu_delay(val) delay(MAX(1, val/100)) +#define DELAY1US 100 +//#define DELAY05US 1 + +#define cal_delay(val) delay05us(MAX(1, val)) // 8us +//#define CAL_DELAY1US 2 +//#define CAL_DELAY05US 20 //20160804 1:0.5us 2:1us +#define CAL_DELAY05US 2 // 20170503 2:1.5us 2 to 20 for debug 20180227 +#define CAL_TX_NUM 50 +#define CAL_RX_NUM 5 + +#define cal_delay_100us(val) delay100us(MAX(1, val)) // 200us +#define CAL_DELAY100US 1 //20160804 1:100us 2:200us // 20170503 1:150us 2:300us + + +//#define BK7011TRXREG0xD 0xDDFF0339 +//#define BK7011TRXREG0xC 0x01A147EE//0x01A183FD +/* +#define DGAINPA20 3 +#define DGAINBUF20 3 +#define GCTRLPGA40 0xf +#define GCTRLMOD30 0x04 +#define TSSI_DELTA (2) // 10 +#define TSSI_IS_VALID(val) (((val) 0xf0 ) && ((val) > 0x20))?1:0) +#define TSSI_IS_TOO_LOW(val) (((val)<(0x00 * SUMNUMBERS))?1:0) //0x37 +#define TSSI_IS_TOO_HIGH(val) (((val)> (0xff * SUMNUMBERS))?1:0) //0xe0 +*/ +#define st_TRXREG00 (1<<0) +#define st_TRXREG01 (1<<1) +#define st_TRXREG02 (1<<2) +#define st_TRXREG03 (1<<3) +#define st_TRXREG04 (1<<4) +#define st_TRXREG05 (1<<5) +#define st_TRXREG06 (1<<6) +#define st_TRXREG07 (1<<7) +#define st_TRXREG08 (1<<8) +#define st_TRXREG09 (1<<9) +#define st_TRXREG0A (1<<10) +#define st_TRXREG0B (1<<11) +#define st_TRXREG0C (1<<12) +#define st_TRXREG0D (1<<13) +#define st_TRXREG0E (1<<14) +#define st_TRXREG0F (1<<15) +#define st_TRXREG10 (1<<16) +#define st_TRXREG11 (1<<17) +#define st_TRXREG12 (1<<18) +#define st_TRXREG13 (1<<19) +#define st_TRXREG14 (1<<20) +#define st_TRXREG15 (1<<21) +#define st_TRXREG16 (1<<22) +#define st_TRXREG17 (1<<23) +#define st_TRXREG18 (1<<24) +#define st_TRXREG19 (1<<25) +#define st_TRXREG1A (1<<26) +#define st_TRXREG1B (1<<27) + +#define abs(a) ((a) < 0 ?(-1*(a)):(a)) + +#ifndef __BK7011RCBEKEN_H__ +#define __BK7011RCBEKEN_H__ + +#define RC_BEKEN_BASE 0x01050000 + +/// REG0x0 +typedef union +{ + struct + { + volatile unsigned int ch0en : 1; /**< Enable BK7011 (1: Enable) */ + volatile unsigned int Reserved : 2; /**< NC */ + volatile unsigned int rcen : 1; /**< Enable BK7011 (1: Enable) */ + volatile unsigned int Reserved_ : 4; /**< NC */ + volatile unsigned int ch0ld : 1; /**< BK7011 LDֵǷ */ + volatile unsigned int lnarssi : 1; /**< BK7011 LNA RSSI״̬ */ + volatile unsigned int Reserved__ : 2; /**< NC */ + volatile unsigned int ch0shdnstat : 1; /**< BK7011Ƿshutdown״̬ */ + volatile unsigned int Reserved___ : 3; /**< NC */ + volatile unsigned int rcstate : 3; /**< ǰRC״̬;0x00=SPI_RESET ;0x01=SHUTDOWN ;0x02=WAIT_SPI (SPIڲ);0x03=WAIT_LOCKRFPLLLock;0x04=ACTIVE */ + volatile unsigned int Reserved____ : 11; /**< NC */ + volatile unsigned int spireset : 1; /**< Reset BK7011SPIĴ */ + volatile unsigned int forceenable : 1; /**< ǿƿBK7011Ľӿź */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x0_TypeDef; + +/// REG0x1 +typedef union +{ + struct + { + volatile unsigned int trxregstat : 28; /**< TRx Register Stat.;0x0: register is idle;0x1: register is updating. Can not write register again */ + volatile unsigned int prescaler : 4; /**< SPIʱƵʿ=RC_Clock (80 MHz)/2/PRESCALE */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x1_TypeDef; + +/// REG0x5 +typedef union +{ + struct + { + volatile unsigned int ch0outpower : 8; /**< No description */ + volatile unsigned int Reserved : 24; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x5_TypeDef; + +/// REG0x8 +typedef union +{ + struct + { + volatile unsigned int CH0RXONDELAY : 8; /**< No description */ + volatile unsigned int Reserved : 8; /**< NC */ + volatile unsigned int CH0RXOFFDELAY : 8; /**< No description */ + volatile unsigned int Reserved_ : 8; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x8_TypeDef; + +/// REG0xB +typedef union +{ + struct + { + volatile unsigned int CH0TXONDELAY : 8; /**< No description */ + volatile unsigned int Reserved : 8; /**< NC */ + volatile unsigned int CH0TXOFFDELAY : 8; /**< No description */ + volatile unsigned int Reserved_ : 8; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0xB_TypeDef; + +/// REG0xE +typedef union +{ + struct + { + volatile unsigned int CH0PAONDELAY : 8; /**< No description */ + volatile unsigned int Reserved : 8; /**< NC */ + volatile unsigned int CH0PAOFFDELAY : 8; /**< No description */ + volatile unsigned int Reserved_ : 8; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0xE_TypeDef; + +/// REG0x11 +typedef union +{ + struct + { + volatile unsigned int CH0SHDNONDELAY : 8; /**< No description */ + volatile unsigned int Reserved : 8; /**< NC */ + volatile unsigned int CH0SHDNOFFDELAY : 8; /**< No description */ + volatile unsigned int Reserved_ : 8; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x11_TypeDef; + +/// REG0x19 +typedef union +{ + struct + { + volatile unsigned int FCH0SHDN : 1; /**< ǿģʽµSHDN */ + volatile unsigned int FCH0RXEN : 1; /**< ǿģʽµRXEN */ + volatile unsigned int FCH0TXEN : 1; /**< ǿģʽµTXEN */ + volatile unsigned int FCH0RXHP : 1; /**< ǿģʽµRXHP */ + volatile unsigned int Reserved : 4; /**< NC */ + volatile unsigned int FCH0B : 8; /**< ǿģʽ */ + volatile unsigned int FCH0EN : 1; /**< ǿƿRFӿź */ + volatile unsigned int Reserved_ : 15; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x19_TypeDef; + +/// REG0x1C +typedef union +{ + struct + { + volatile unsigned int FRXON : 1; /**< ǿģʽRX ON */ + volatile unsigned int FTXON : 1; /**< ǿģʽTX ON */ + volatile unsigned int Reserved : 30; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x1C_TypeDef; + +/// REG0x1E +typedef union +{ + struct + { + volatile unsigned int FERXONDEL : 12; /**< No description */ + volatile unsigned int Reserved : 20; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x1E_TypeDef; + +/// REG0x3C +typedef union +{ + struct + { + volatile unsigned int RXAVGQRD : 12; /**< Q· */ + volatile unsigned int RXAVGIRD : 12; /**< I· */ + volatile unsigned int Reserved : 4; /**< NC */ + volatile unsigned int RXHPFBYPASS : 1; /**< RX HPF bypass */ + volatile unsigned int RXIQSWAP : 1; /**< RX IQ SWAP */ + volatile unsigned int RXAVGMODE : 1; /**< 0ȡźŵƽֵ;1ȡźžֵƽֵ */ + volatile unsigned int RXDCCALEN : 1; /**< ʹRX DC(1) */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x3C_TypeDef; + +/// REG0x3E +typedef union +{ + struct + { + volatile unsigned int RXDCQRD : 12; /**< Q·DC */ + volatile unsigned int RXDCIRD : 12; /**< I·DC */ + volatile unsigned int Reserved : 6; /**< NC */ + volatile unsigned int RXCOMPEN : 1; /**< ʹMismatch(1) */ + volatile unsigned int RXCALEN : 1; /**< ʹMismatch(1) */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x3E_TypeDef; + +/// REG0x3F +typedef union +{ + struct + { + volatile unsigned int RXPHASEERRRD : 10; /**< Ƴλphase_err_est*2^9з */ + volatile unsigned int Reserved : 6; /**< NC */ + volatile unsigned int RXAMPERRRD : 10; /**< Ƴķamp_err_est*2^9з */ + volatile unsigned int Reserved_ : 6; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x3F_TypeDef; + +/// REG0x40 +typedef union +{ + struct + { + volatile unsigned int RXTY2RD : 10; /**< ƳTY2(ty2-0.5)*2^10з */ + volatile unsigned int Reserved : 22; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x40_TypeDef; + +/// REG0x41 +typedef union +{ + struct + { + volatile unsigned int RXDCQWR : 12; /**< ʱʹõQ·DC */ + volatile unsigned int RXDCIWR : 12; /**< ʱʹõI·DC */ + volatile unsigned int Reserved : 8; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x41_TypeDef; + +/// REG0x42 +typedef union +{ + struct + { + volatile unsigned int RXPHASEERRWR : 10; /**< ʱʹõphase_err*ty2*2^9 */ + volatile unsigned int Reserved : 6; /**< NC */ + volatile unsigned int RXAMPERRWR : 10; /**< ʱʹõty2/(1+amp_err)*2^9 */ + volatile unsigned int Reserved_ : 6; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x42_TypeDef; + +/// REG0x4C +typedef union +{ + struct + { + volatile unsigned int QCONSTANT : 10; /**< 䳣ʱQֵ */ + volatile unsigned int Reserved : 6; /**< NC */ + volatile unsigned int ICONSTANT : 10; /**< 䳣ʱIֵ */ + volatile unsigned int DPDCOMPEN : 1; /**< DPD Compensation Enable */ + volatile unsigned int DPDCALEN : 1; /**< DPD Calculation Enable */ + volatile unsigned int DPDEN : 1; /**< DPD Enable] */ + volatile unsigned int TXCOMPDIS : 1; /**< Ͳֹܽ;0x0: ʹܷͲ;0x1: ֹͲ */ + volatile unsigned int TESTPATTERN : 2; /**< 0ģʽModem */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x4C_TypeDef; + +/// REG0x4D +typedef union +{ + struct + { + volatile unsigned int Reserved : 12; /**< NC */ + volatile unsigned int TXSINAMP : 4; /**< ҲȵϵСʾx.yyyΧ[0 15/8] */ + volatile unsigned int TXSINMODE : 2; /**< 0I/Q·临Ҳ;1I·䣬Q·0;2Q·䣬I·0;3 */ + volatile unsigned int Reserved_ : 4; /**< NC */ + volatile unsigned int TXSINF : 10; /**< ҲƵ;TX_SIN_F=2*pi*F/80e6*2^8FǷƵ */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x4D_TypeDef; + +/// REG0x4E +typedef union +{ + struct + { + volatile unsigned int hbf40sel : 1; /**< 40Mģʽϲ˲ϵ 1 beken ϵ 0rw ϵ */ + volatile unsigned int hbf40bp : 1; /**< 40Mģʽϲ˲ bypass */ + volatile unsigned int hbf20sel : 1; /**< 20Mģʽϲ˲ϵ 1 beken ϵ 0rw ϵ */ + volatile unsigned int hbf20bp : 1; /**< 20Mģʽϲ˲ bypass */ + volatile unsigned int Reserved_ : 28; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x4E_TypeDef; + +/// REG0x4F +typedef union +{ + struct + { + volatile unsigned int TXQDCCOMP : 10; /**< Q DC offset[-512 511] */ + volatile unsigned int Reserved : 6; /**< NC */ + volatile unsigned int TXIDCCOMP : 10; /**< I DC offset[-512 511] */ + volatile unsigned int Reserved_ : 6; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x4F_TypeDef; + +/// REG0x50 +typedef union +{ + struct + { + volatile unsigned int TXQGAINCOMP : 10; /**< 0 ~ 1023/1024step:1/1024 */ + volatile unsigned int Reserved : 6; /**< NC */ + volatile unsigned int TXIGAINCOMP : 10; /**< 0 ~ 1023/1024step:1/1024 */ + volatile unsigned int Reserved_ : 6; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x50_TypeDef; + +/// REG0x51 +typedef union +{ + struct + { + volatile unsigned int TXTY2 : 10; /**< 512/1024 ~ (512+1023)/1024step:1/1024 */ + volatile unsigned int Reserved : 6; /**< NC */ + volatile unsigned int TXPHASECOMP : 10; /**< -512/1024~ 511/1024step:1/1024 */ + volatile unsigned int Reserved_ : 6; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x51_TypeDef; + +/// REG0x52 +typedef union +{ + struct + { + volatile unsigned int Reserved : 6; /**< NC */ + volatile unsigned int IQCONSTANTIQCALP : 10; /**< IQУ׼IQ CONSTANT ֵֵ */ + volatile unsigned int TXPREGAIN : 5; /**< IQź;01.75 dB;. 31-6dB;; */ + volatile unsigned int IQCONSTANTPOUT : 10; /**< У׼IQ CONSTANT ֵ */ + volatile unsigned int TXIQSWAP : 1; /**< IQ Swap */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x52_TypeDef; + +/// REG0x54 +typedef union +{ + struct + { + volatile unsigned int STRXADCIQ : 1; /**< RX ADC IQУ׼ Settling time 0:300us;1:600us */ + volatile unsigned int TSSIPOUTTH : 8; /**< У׼ʶӦTSSI */ + volatile unsigned int DSELVA : 1; /**< TSSI or AGC gain setting for versiong A, output 0: TSSI 1:AGC gain setting */ + volatile unsigned int TXDCN : 2; /**< TX DC ַһִв 0:3Σ1:4Σ2:5Σ3:6 */ + volatile unsigned int STRXADC : 2; /**< RX ADC Settling time 0:100us;1:200us;2:300us;3:400us */ + volatile unsigned int STSARADC : 2; /**< SAR ADC Settling time 0:0.5us;1:1us;2:1.5us;3:2us */ + volatile unsigned int TSSIRD : 8; /**< TSSI Value. Just valid during tssi_cal_en assert */ + volatile unsigned int AGCPGARD : 4; /**< AGCPGA */ + volatile unsigned int AGCBUFRD : 1; /**< AGCBUF */ + volatile unsigned int AGCLNARD : 2; /**< AGCLNA */ + volatile unsigned int AGCMAPMODE : 1; /**< 0ӳ䷽ʽһ;1ӳ䷽ʽ */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x54_TypeDef; + +/// REG0x55 +typedef union +{ + struct + { + volatile unsigned int RXSNRNOISE : 9; /**< rx noise for sinar test */ + volatile unsigned int Reserved : 7; /**< NC */ + volatile unsigned int RXSNRSIG : 9; /**< rx signal for sinar test */ + volatile unsigned int Reserved_ : 7; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x55_TypeDef; + +/// REG0x5A +typedef union +{ + struct + { + volatile unsigned int TXCALCAPI : 6; /**< I path calib capacity for transmit mode */ + volatile unsigned int Reserved__ : 2; /**< NC */ + volatile unsigned int RXCALCAPI : 6; /**< I path calib capacity for receive mode */ + volatile unsigned int Reserved : 2; /**< NC */ + volatile unsigned int STANDBYCALCAPI : 6; /**< I path calib capacity for standby mode */ + volatile unsigned int Reserved_ : 10; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x5A_TypeDef; + +/// REG0x5B +typedef union +{ + struct + { + volatile unsigned int TXCALCAPQ : 6; /**< Q path calib capacity for transmit mode */ + volatile unsigned int Reserved__ : 2; /**< NC */ + volatile unsigned int RXCALCAPQ : 6; /**< Q path calib capacity for receive mode */ + volatile unsigned int Reserved : 2; /**< NC */ + volatile unsigned int STANDBYCALCAPQ : 6; /**< Q path calib capacity for standby mode */ + volatile unsigned int Reserved_ : 10; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x5B_TypeDef; + +/// REG0x5C +typedef union +{ + struct + { + volatile unsigned int trxspiintval : 10; /**< TRX SPI Transfer Interval. Unit is 12.5ns */ + volatile unsigned int Reserved : 14; /**< NC */ + volatile unsigned int Reserved_ : 7; /**< Reserved */ + volatile unsigned int trxbankrpt : 1; /**< TRX Bank Report. 0x0:bank0; 0x1:bank1 */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x5C_TypeDef; + +/// REG0x6A +typedef union +{ + struct + { + volatile unsigned int trxaddaregstat : 6; /**< ADC&DAC Register Status.;0x0: register is idle;0x1: register is updating. Can not write register again */ + volatile unsigned int Reserved : 26; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x6A_TypeDef; + +/// REG0x70 +typedef union +{ + struct + { + volatile unsigned int palevel0map : 16; /**< PA Level0 Mapping Value */ + volatile unsigned int palevel1map : 16; /**< PA Level1 Mapping Value */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x70_TypeDef; + +/// REG0x71 +typedef union +{ + struct + { + volatile unsigned int palevel2map : 16; /**< PA Level2 Mapping Value */ + volatile unsigned int palevel3map : 16; /**< PA Level3 Mapping Value */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x71_TypeDef; + +/// REG0x72 +typedef union +{ + struct + { + volatile unsigned int palevel4map : 16; /**< PA Level4 Mapping Value */ + volatile unsigned int palevel5map : 16; /**< PA Level5 Mapping Value */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x72_TypeDef; + +/// REG0x73 +typedef union +{ + struct + { + volatile unsigned int palevel6map : 16; /**< PA Level6 Mapping Value */ + volatile unsigned int palevel7map : 16; /**< PA Level7 Mapping Value */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x73_TypeDef; + +/// REG0x74 +typedef union +{ + struct + { + volatile unsigned int palevel8map : 16; /**< PA Level8 Mapping Value */ + volatile unsigned int palevel9map : 16; /**< PA Level9 Mapping Value */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x74_TypeDef; + +/// REG0x75 +typedef union +{ + struct + { + volatile unsigned int palevel10map : 16; /**< PA Level10 Mapping Value */ + volatile unsigned int palevel11map : 16; /**< PA Level11 Mapping Value */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x75_TypeDef; + +/// REG0x76 +typedef union +{ + struct + { + volatile unsigned int palevel12map : 16; /**< PA Level12 Mapping Value */ + volatile unsigned int palevel13map : 16; /**< PA Level13 Mapping Value */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x76_TypeDef; + +/// REG0x77 +typedef union +{ + struct + { + volatile unsigned int palevel4map : 16; /**< PA Level4 Mapping Value */ + volatile unsigned int palevel5map : 16; /**< PA Level5 Mapping Value */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x77_TypeDef; + +/// BK7011RCBEKEN +struct BK7011RCBEKEN_TypeDef +{ + volatile BK7011_RC_BEKEN_REG0x0_TypeDef *REG0x0; + volatile BK7011_RC_BEKEN_REG0x1_TypeDef *REG0x1; + volatile BK7011_RC_BEKEN_REG0x5_TypeDef *REG0x5; + volatile BK7011_RC_BEKEN_REG0x8_TypeDef *REG0x8; + volatile BK7011_RC_BEKEN_REG0xB_TypeDef *REG0xB; + volatile BK7011_RC_BEKEN_REG0xE_TypeDef *REG0xE; + volatile BK7011_RC_BEKEN_REG0x11_TypeDef *REG0x11; + volatile BK7011_RC_BEKEN_REG0x19_TypeDef *REG0x19; + volatile BK7011_RC_BEKEN_REG0x1C_TypeDef *REG0x1C; + volatile BK7011_RC_BEKEN_REG0x1E_TypeDef *REG0x1E; + volatile BK7011_RC_BEKEN_REG0x3C_TypeDef *REG0x3C; + volatile BK7011_RC_BEKEN_REG0x3E_TypeDef *REG0x3E; + volatile BK7011_RC_BEKEN_REG0x3F_TypeDef *REG0x3F; + volatile BK7011_RC_BEKEN_REG0x40_TypeDef *REG0x40; + volatile BK7011_RC_BEKEN_REG0x41_TypeDef *REG0x41; + volatile BK7011_RC_BEKEN_REG0x42_TypeDef *REG0x42; + volatile BK7011_RC_BEKEN_REG0x4C_TypeDef *REG0x4C; + volatile BK7011_RC_BEKEN_REG0x4D_TypeDef *REG0x4D; + volatile BK7011_RC_BEKEN_REG0x4E_TypeDef *REG0x4E; + volatile BK7011_RC_BEKEN_REG0x4F_TypeDef *REG0x4F; + volatile BK7011_RC_BEKEN_REG0x50_TypeDef *REG0x50; + volatile BK7011_RC_BEKEN_REG0x51_TypeDef *REG0x51; + volatile BK7011_RC_BEKEN_REG0x52_TypeDef *REG0x52; + volatile BK7011_RC_BEKEN_REG0x54_TypeDef *REG0x54; + volatile BK7011_RC_BEKEN_REG0x55_TypeDef *REG0x55; + volatile BK7011_RC_BEKEN_REG0x5A_TypeDef *REG0x5A; + volatile BK7011_RC_BEKEN_REG0x5B_TypeDef *REG0x5B; + volatile BK7011_RC_BEKEN_REG0x5C_TypeDef *REG0x5C; + volatile BK7011_RC_BEKEN_REG0x6A_TypeDef *REG0x6A; + volatile BK7011_RC_BEKEN_REG0x70_TypeDef *REG0x70; + volatile BK7011_RC_BEKEN_REG0x71_TypeDef *REG0x71; + volatile BK7011_RC_BEKEN_REG0x72_TypeDef *REG0x72; + volatile BK7011_RC_BEKEN_REG0x73_TypeDef *REG0x73; + volatile BK7011_RC_BEKEN_REG0x74_TypeDef *REG0x74; + volatile BK7011_RC_BEKEN_REG0x75_TypeDef *REG0x75; + volatile BK7011_RC_BEKEN_REG0x76_TypeDef *REG0x76; + volatile BK7011_RC_BEKEN_REG0x77_TypeDef *REG0x77; +}; +#endif + +#ifndef __BK7011TRxV2A_H__ +#define __BK7011TRxV2A_H__ + +#define TRX_BEKEN_BASE 0x01050080 + +#if 1 +/// REG0x0 +typedef union +{ + struct + { + volatile unsigned long TSSliref : 2; + volatile unsigned long gTSSI10 : 2; + volatile unsigned long stbTSSI10 : 2; + volatile unsigned long PcalATT : 3; + volatile unsigned long enPcal : 1; + volatile unsigned long enIQcal : 1; + volatile unsigned long rstTSSI : 1; + volatile unsigned long enDCcal : 1; + volatile unsigned long TSSIsel : 1; + volatile unsigned long enTSSItst : 1; + volatile unsigned long vseltssi : 2; + volatile unsigned long tssi_statectrl : 1; + volatile unsigned long tssi_selrange : 1; + volatile unsigned long NC : 13; + } bits; + volatile unsigned int value; +}BK7011_TRxV2A_REG0x0_TypeDef; + +/// REG0x1 +typedef union +{ + struct + { + volatile unsigned long cpsel_tx : 2; + volatile unsigned long cp3_tx : 1; + volatile unsigned long cp2_tx : 2; + volatile unsigned long cp1_tx : 2; + volatile unsigned long ictrl_rx : 4; + volatile unsigned long cpsel_rx : 2; + volatile unsigned long Rp3_rx : 3; + volatile unsigned long Rp2_rx : 3; + volatile unsigned long LPFRz_rx : 4; + volatile unsigned long Ioffset_rx : 4; + volatile unsigned long cp3_rx : 1; + volatile unsigned long cp2_rx : 2; + volatile unsigned long cp1_rx : 2; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x1_TypeDef; + +/// REG0x2 +typedef union +{ + struct + { + volatile unsigned long vcoampctrl : 1; + volatile unsigned long vrefLctrl : 2; + volatile unsigned long vrefHctrl : 2; + volatile unsigned long reset_Ncounter : 1; + volatile unsigned long reset_Nload : 1; + volatile unsigned long tristate : 1; + volatile unsigned long selpol : 1; + volatile unsigned long cpswen : 1; + volatile unsigned long NC : 3; + volatile unsigned long open : 1; + volatile unsigned long ictrl_tx : 4; + volatile unsigned long Rp3_tx : 3; + volatile unsigned long Rp2_tx : 3; + volatile unsigned long LPFRz_tx : 4; + volatile unsigned long Ioffset_tx : 4; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x2_TypeDef; + +/// REG0x3 +typedef union +{ + struct + { + volatile unsigned long vnwl : 2; + volatile unsigned long vnwh : 2; + volatile unsigned long rvco20 : 3; + volatile unsigned long nwresc : 2; + volatile unsigned long nwlpfen : 1; + volatile unsigned long spi_trigger : 1; + volatile unsigned long errdet_spien : 1; + volatile unsigned long ckref_loop_sel : 1; + volatile unsigned long ckref_NL_sel : 1; + volatile unsigned long Nrsten : 1; + volatile unsigned long Int_mod : 1; + volatile unsigned long manual : 1; + volatile unsigned long bandm60 : 7; + volatile unsigned long Nmanual : 8; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x3_TypeDef; + +/// REG0x4 +typedef union +{ + struct + { + volatile unsigned long nsdmlsb : 8; + volatile unsigned long pnen : 1; + volatile unsigned long vbncdiv3G : 2; + volatile unsigned long itunediv3G : 1; + volatile unsigned long vbncdiv6G : 2; + volatile unsigned long itunediv6G : 1; + volatile unsigned long nc : 5; + volatile unsigned long mixer_gmctrl : 3; + volatile unsigned long pwd_mixampdet : 1; + volatile unsigned long mixer_ampdetc : 1; + volatile unsigned long mixerItune : 1; + volatile unsigned long mixerCtune : 6; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x4_TypeDef; + +/// REG0x5 +typedef union +{ + struct + { + volatile unsigned long men_db : 1; + volatile unsigned long flag_polsel_db : 1; + volatile unsigned long en_db : 1; + volatile unsigned long dlym_db : 5; + volatile unsigned long calen_db : 1; + volatile unsigned long cal_trig_db : 1; + volatile unsigned long NC : 1; + volatile unsigned long cp_ldo : 2; + volatile unsigned long pll_ldo : 2; + volatile unsigned long vco_ldo : 2; + volatile unsigned long cp_rst : 1; + volatile unsigned long sdm_rstn : 1; + volatile unsigned long cksel_sdm : 2; + volatile unsigned long cksel_bcal : 1; + volatile unsigned long refsel : 1; + volatile unsigned long pwdvco : 1; + volatile unsigned long pwdpll : 1; + volatile unsigned long chspi : 7; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x5_TypeDef; + +/// REG0x6 +typedef union +{ + struct + { + volatile unsigned long vcmsel10 : 2; + volatile unsigned long capcal_sel : 1; + volatile unsigned long dpd_en : 1; + volatile unsigned long lpfcapcalq50 : 6; + volatile unsigned long lpfcapcali50 : 6; + volatile unsigned long dcocq : 8; + volatile unsigned long dcoci : 8; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x6_TypeDef; + +/// REG0x7 +typedef union +{ + struct + { + volatile unsigned long dig_dcoen : 1; + volatile unsigned long spilpfrxg30 : 4; + volatile unsigned long autorxifgen : 1; + volatile unsigned long dcoc_ctl : 2; + volatile unsigned long lpfvcmic10 : 2; + volatile unsigned long lpftxTest : 1; + volatile unsigned long NC : 21; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x7_TypeDef; + +/// REG0x8 +typedef union +{ + struct + { + volatile unsigned long isrxref10 : 2; + volatile unsigned long isrxlna30 : 4; + volatile unsigned long NC1 : 3; + volatile unsigned long isrxlnac10 : 2; + volatile unsigned long isrxdiv10 : 2; + volatile unsigned long NC2 : 1; + volatile unsigned long rssith50 : 6; + volatile unsigned long isrssigm10 : 2; + volatile unsigned long rssiten : 1; + volatile unsigned long NC3 : 9; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x8_TypeDef; + +/// REG0x9 +typedef union +{ + struct + { + volatile unsigned long agcrxfeEn : 1; + volatile unsigned long grxlnaspi10 : 2; + volatile unsigned long grxi2vspi10 : 2; + volatile unsigned long vsrxlnaldo10 : 2; + volatile unsigned long grxlnacali20 : 3; + volatile unsigned long vsrxmixldo10 : 2; + volatile unsigned long vbsrxlo20 : 3; + volatile unsigned long vresrxlo : 1; + volatile unsigned long ibsrxi2v10 : 2; + volatile unsigned long vcmsrxi2v : 1; + volatile unsigned long NC : 13; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x9_TypeDef; + +/// REG0xA +typedef union +{ + struct + { + volatile unsigned long disrefPA10 : 2; + volatile unsigned long disrefpga10 : 2; + volatile unsigned long dbpab30 : 4; + volatile unsigned long dbpaa30 : 6; + volatile unsigned long NC : 2; + volatile unsigned long dcapbuf30 : 4; + volatile unsigned long dbbuf30 : 4; + volatile unsigned long dbcbuf30 : 4; + volatile unsigned long dbcpa20 : 3; + volatile unsigned long pamapen : 1; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0xA_TypeDef; + +/// REG0xB +typedef union +{ + struct + { + volatile unsigned long dcpga30 : 4; + volatile unsigned long dbpga30 : 4; + volatile unsigned long dcappga30 : 4; + volatile unsigned long dcorMod30 : 4; + volatile unsigned long dvlo30 : 4; + volatile unsigned long dvcmo30 : 4; + volatile unsigned long dcapmod30 : 4; + volatile unsigned long gctrlmod30 : 4; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0xB_TypeDef; + +/// REG0xC +typedef union +{ + struct + { + volatile unsigned long dgainpga : 4; + volatile unsigned long dgainbuf30 : 4; + volatile unsigned long dgainPA30 : 4; + volatile unsigned long dcorPA30 : 4; + volatile unsigned long vregSel30 : 4; + volatile unsigned long LOvbnc : 2; + volatile unsigned long LOisel : 2; + volatile unsigned long dvbb : 4; + volatile unsigned long dtr30 : 4; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0xC_TypeDef; + +/// REG0xD +typedef union +{ + struct + { + volatile unsigned long dacselection : 1; + volatile unsigned long lpfrxbw : 1; + volatile unsigned long lpftxbw : 1; + volatile unsigned long lpftrxsw : 1; + volatile unsigned long enlpf : 1; + volatile unsigned long enif : 1; + volatile unsigned long endcoc : 1; + volatile unsigned long enrxadc : 1; + volatile unsigned long entxdac : 1; + volatile unsigned long entxdacbias : 1; + volatile unsigned long enrxrssi : 1; + volatile unsigned long enrxref : 1; + volatile unsigned long enrxi2v : 1; + volatile unsigned long enrxmix : 1; + volatile unsigned long enlnacal : 1; + volatile unsigned long enlna : 1; + volatile unsigned long txvinsel : 1; + volatile unsigned long entssi : 1; + volatile unsigned long entssiadc : 1; + volatile unsigned long entxferef : 1; + volatile unsigned long entxfebias : 1; + volatile unsigned long entxv2i : 1; + volatile unsigned long entxlo : 1; + volatile unsigned long entxpga : 1; + volatile unsigned long enpa : 1; + volatile unsigned long enrxsw : 1; + volatile unsigned long entxsw : 1; + volatile unsigned long trswpll : 1; + volatile unsigned long enrfpll : 1; + volatile unsigned long endobuler : 1; + volatile unsigned long endpll : 1; + volatile unsigned long enxtal : 1; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0xD_TypeDef; + +/// REG0xE +typedef union +{ + struct + { + volatile unsigned long dacselection : 1; + volatile unsigned long lpfrxbw : 1; + volatile unsigned long lpftxbw : 1; + volatile unsigned long lpftrxsw : 1; + volatile unsigned long enlpf : 1; + volatile unsigned long enif : 1; + volatile unsigned long endcoc : 1; + volatile unsigned long enrxadc : 1; + volatile unsigned long entxdac : 1; + volatile unsigned long entxdacbias : 1; + volatile unsigned long enrxrssi : 1; + volatile unsigned long enrxref : 1; + volatile unsigned long enrxi2v : 1; + volatile unsigned long enrxmix : 1; + volatile unsigned long enlnacal : 1; + volatile unsigned long enlna : 1; + volatile unsigned long txvinsel : 1; + volatile unsigned long entssi : 1; + volatile unsigned long entssiadc : 1; + volatile unsigned long entxferef : 1; + volatile unsigned long entxfebias : 1; + volatile unsigned long entxv2i : 1; + volatile unsigned long entxlo : 1; + volatile unsigned long entxpga : 1; + volatile unsigned long enpa : 1; + volatile unsigned long enrxsw : 1; + volatile unsigned long entxsw : 1; + volatile unsigned long trswpll : 1; + volatile unsigned long enrfpll : 1; + volatile unsigned long endobuler : 1; + volatile unsigned long endpll : 1; + volatile unsigned long enxtal : 1; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0xE_TypeDef; + +/// REG0xF +typedef union +{ + struct + { + volatile unsigned long reg_bank_sel : 1; + volatile unsigned long clkdac_sel : 1; + volatile unsigned long clkadc_sel : 1; + volatile unsigned long NC1 : 2; + volatile unsigned long sinad_tx_en : 1; + volatile unsigned long sinad_rx_en : 1; + volatile unsigned long tssi_cal_en : 1; + volatile unsigned long NC2 : 5; + volatile unsigned long sinad_hpf_coef : 2; + volatile unsigned long clkdac_inv : 1; + volatile unsigned long clkadc_inv : 1; + volatile unsigned long NC3 : 11; + volatile unsigned long sysldoen : 1; + volatile unsigned long sysldolp : 1; + volatile unsigned long endspvdd : 1; + volatile unsigned long digldolp : 1; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0xF_TypeDef; + +/// REG0x10 +typedef union +{ + struct + { + volatile unsigned long dacselection : 1; + volatile unsigned long lpfrxbw : 1; + volatile unsigned long lpftxbw : 1; + volatile unsigned long lpftrxsw : 1; + volatile unsigned long enlpf : 1; + volatile unsigned long enif : 1; + volatile unsigned long endcoc : 1; + volatile unsigned long enrxadc : 1; + volatile unsigned long entxdac : 1; + volatile unsigned long entxdacbias : 1; + volatile unsigned long enrxrssi : 1; + volatile unsigned long enrxref : 1; + volatile unsigned long enrxi2v : 1; + volatile unsigned long enrxmix : 1; + volatile unsigned long enlnacal : 1; + volatile unsigned long enlna : 1; + volatile unsigned long txvinsel : 1; + volatile unsigned long entssi : 1; + volatile unsigned long entssiadc : 1; + volatile unsigned long entxferef : 1; + volatile unsigned long entxfebias : 1; + volatile unsigned long entxv2i : 1; + volatile unsigned long entxlo : 1; + volatile unsigned long entxpga : 1; + volatile unsigned long enpa : 1; + volatile unsigned long enrxsw : 1; + volatile unsigned long entxsw : 1; + volatile unsigned long trswpll : 1; + volatile unsigned long enrfpll : 1; + volatile unsigned long endobuler : 1; + volatile unsigned long endpll : 1; + volatile unsigned long enxtal : 1; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x10_TypeDef; + +/// REG0x11 +typedef union +{ + struct + { + volatile unsigned long tx_sinad_table : 11; + volatile unsigned long NC : 21; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x11_TypeDef; + +/// REG0x12 +typedef union +{ + struct + { + volatile unsigned long lpfouttsten : 1; + volatile unsigned long lpfintsten : 1; + volatile unsigned long ifbufic20 : 3; + volatile unsigned long adcrefsel : 2; + volatile unsigned long ldoadda : 2; + volatile unsigned long buftstselection : 3; + volatile unsigned long NC : 1; + volatile unsigned long entstbufldo : 1; + volatile unsigned long adcinSel : 1; + volatile unsigned long en_gmboost : 1; + volatile unsigned long adciselr20 : 3; + volatile unsigned long adciselc20 : 3; + volatile unsigned long adcrefbwsel : 1; + volatile unsigned long adcten : 1; + volatile unsigned long fictrl30 : 4; + volatile unsigned long flvcm10 : 2; + volatile unsigned long ldoifsel3v10 : 2; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x12_TypeDef; + +/// REG0x13 +typedef union +{ + struct + { + volatile unsigned long r2_rx : 2; + volatile unsigned long c1_rx : 2; + volatile unsigned long rz_rx : 5; + volatile unsigned long icp_rx : 5; + volatile unsigned long icpoff20 : 3; + volatile unsigned long icpsel : 1; + volatile unsigned long r2_tx : 2; + volatile unsigned long c1_tx : 2; + volatile unsigned long rz_tx : 5; + volatile unsigned long icp_tx : 5; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x13_TypeDef; + +/// REG0x14 +typedef union +{ + struct + { + volatile unsigned long dc_i_0db : 8; + volatile unsigned long dc_q_0db : 8; + volatile unsigned long dc_i_3db : 8; + volatile unsigned long dc_q_3db : 8; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x14_TypeDef; + +/// REG0x15 +typedef union +{ + struct + { + volatile unsigned long dc_i_6db : 8; + volatile unsigned long dc_q_6db : 8; + volatile unsigned long dc_i_9db : 8; + volatile unsigned long dc_q_9db : 8; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x15_TypeDef; + +/// REG0x16 +typedef union +{ + struct + { + volatile unsigned long dc_i_12db : 8; + volatile unsigned long dc_q_12db : 8; + volatile unsigned long dc_i_15db : 8; + volatile unsigned long dc_q_15db : 8; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x16_TypeDef; + +/// REG0x17 +typedef union +{ + struct + { + volatile unsigned long dc_i_18db : 8; + volatile unsigned long dc_q_18db : 8; + volatile unsigned long dc_i_21db : 8; + volatile unsigned long dc_q_21db : 8; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x17_TypeDef; + +/// REG0x18 +typedef union +{ + struct + { + volatile unsigned long dc_i_24db : 8; + volatile unsigned long dc_q_24db : 8; + volatile unsigned long dc_i_27db : 8; + volatile unsigned long dc_q_27db : 8; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x18_TypeDef; + +/// REG0x19 +typedef union +{ + struct + { + volatile unsigned long dc_i_30db : 8; + volatile unsigned long dc_q_30db : 8; + volatile unsigned long dc_i_33db : 8; + volatile unsigned long dc_q_33db : 8; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x19_TypeDef; + +/// REG0x1A +typedef union +{ + struct + { + volatile unsigned long dc_i_36db : 8; + volatile unsigned long dc_q_36db : 8; + volatile unsigned long dc_i_39db : 8; + volatile unsigned long dc_q_39db : 8; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x1A_TypeDef; + +/// REG0x1B +typedef union +{ + struct + { + volatile unsigned long dc_i_42db : 8; + volatile unsigned long dc_q_42db : 8; + volatile unsigned long dc_i_45db : 8; + volatile unsigned long dc_q_45db : 8; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x1B_TypeDef; + +/// REG0x1C +typedef union +{ + struct + { + volatile unsigned long dac_out_qspi : 10; + volatile unsigned long NC1 : 2; + volatile unsigned long dac_out_ispi : 10; + volatile unsigned long NC2 : 10; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x1C_TypeDef; + +#else + +/// REG0x0 +typedef union +{ + struct + { + volatile unsigned int pwdpll : 1; /**< pwdpll */ + volatile unsigned int cp20 : 3; /**< cp curent control 0to 350uA 50uA step */ + volatile unsigned int spideten : 1; /**< unlock detect enable fron spi 1:enable */ + volatile unsigned int hvref10 : 2; /**< high vth control for unlock detect 00:0.85V;01:0.9V;10:0.95V;11:1.05V */ + volatile unsigned int lvref10 : 2; /**< low vth control for unlock detect 00:0.2V;01:0.3V;10:0.35V;11:0.4V */ + volatile unsigned int Rzctrl26M : 1; /**< Rz ctrl in 26M mode:1:normal;0:add 14K */ + volatile unsigned int LoopRzctrl30 : 4; /**< Rz ctrl:2K to 17K,1K step */ + volatile unsigned int rpc10 : 2; /**< second pole Rp ctrl:00:30K;01:10K;10:22K;11:2K */ + volatile unsigned int nsyn : 1; /**< N divider rst */ + volatile unsigned int cksel10 : 2; /**< 0:26M;1:40M;2:24M;3:19.2M */ + volatile unsigned int spitrig : 1; /**< SPI band selection trigger signal */ + volatile unsigned int CKEn : 1; /**< 1: Enable all clock phases(480M/160M); 0 : Disable all clocks; */ + volatile unsigned int band41 : 4; /**< band manual value */ + volatile unsigned int bandmanual : 1; /**< 1:band manual;0:band auto */ + volatile unsigned int dsptrig : 1; /**< band selection trigger signal */ + volatile unsigned int xtalIctrl : 1; /**< 0:large current;1:small current */ + volatile unsigned int ckTestEn : 1; /**< 1: Enable clock test path; 0 : Disable clock test path; */ + volatile unsigned int xamp31 : 3; /**< xtal OSC amp control */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x0_TypeDef; + +/// REG0x1 +typedef union +{ + struct + { + volatile unsigned int acoef80 : 9; /**< ˲֧·ϵ */ + volatile unsigned int bcoef20 : 3; /**< ˲propotional֧·ϵ */ + volatile unsigned int bckphoffset50 : 6; /**< PD˵divʱӵӳ */ + volatile unsigned int rckphoffset50 : 6; /**< PD˵refʱӵӳ */ + volatile unsigned int bypass52M : 1; /**< bypass 52Mʱӣ26Mʱ */ + volatile unsigned int tst2xpden : 1; /**< ѡҪźţ1ΪPD0Ϊ52Mʱ */ + volatile unsigned int tst2xen : 1; /**< ʹܲ */ + volatile unsigned int calspitrig : 1; /**< ͨĴƵʵУ׼ʱдΪ0дΪ1 */ + volatile unsigned int bypassdmsb : 1; /**< ˲ʱbypassDmsb֧· */ + volatile unsigned int manual : 1; /**< DmsbDlsbΪֶ */ + volatile unsigned int frecalbypass : 1; /**< bypass ƵʵԶУ׼ܣֶ */ + volatile unsigned int rstnspi : 1; /**< ͨĴreset */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x1_TypeDef; + +/// REG0x2 +typedef union +{ + struct + { + volatile unsigned int arbpden : 1; /**< ͨĴʹarbiter BBPD */ + volatile unsigned int endoubler : 1; /**< ͨĴʹdoubler */ + volatile unsigned int trackenspi : 1; /**< ͨĴʹܿ㷨 */ + volatile unsigned int Dcal80 : 9; /**< ͨĴֶDcal */ + volatile unsigned int Dmsbspi20 : 3; /**< ͨĴֶDmsb */ + volatile unsigned int Dlsbspi40 : 5; /**< ͨĴֶDlsb */ + volatile unsigned int updatecycle110 : 12; /**< ÿ㷨ʱݵʱ */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x2_TypeDef; + +/// REG0x3 +typedef union +{ + struct + { + volatile unsigned int numdn110 : 12; /**< λͺĴ */ + volatile unsigned int numup110 : 12; /**< λǰĴ */ + volatile unsigned int arbpddelay30 : 4; /**< arbiter BBPDеdelay */ + volatile unsigned int hysen : 1; /**< ʹλij͹ */ + volatile unsigned int phacalbypass : 1; /**< ˲ʱУ׼ɺԲʹλtracking,ӶУ׼ĽǷȷ */ + volatile unsigned int f2xldovsel3v10 : 2; /**< LDOѹLDOһλÿλѾlevel shiftת001.2V01 101.3V111.4V */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x3_TypeDef; + +/// REG0x4 +typedef union +{ + struct + { + volatile unsigned int manual : 1; /**< vco manual band control enable 1:manual */ + volatile unsigned int bandm60 : 7; /**< vco band manual control */ + volatile unsigned int calresc10 : 2; /**< vco nwell voltage for calibration:00,0.5V;01,0.6V;10,0.7V;11,0.8V */ + volatile unsigned int rvco20 : 3; /**< rfpll vco bias current control */ + volatile unsigned int cpldo10 : 2; /**< Charge Pump LDO voltage control. */ + volatile unsigned int NC : 1; /**< No description */ + volatile unsigned int trswspi : 1; /**< trsw spi control:0,spi;1:cpu */ + volatile unsigned int trswen : 1; /**< enable cpu trsw control 1:enable */ + volatile unsigned int nrsten : 1; /**< N counter reset enable */ + volatile unsigned int reset : 1; /**< reset rfpll fb divider loading */ + volatile unsigned int pwdlogen : 1; /**< power down rfpll LO generation */ + volatile unsigned int pwdvco : 1; /**< power down rfpll vco */ + volatile unsigned int pwdpll : 1; /**< power down rfpll pll */ + volatile unsigned int nint70 : 8; /**< power down rfpll vco */ + volatile unsigned int intmode : 1; /**< power down rfpll pll */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x4_TypeDef; + +/// REG0x5 +typedef union +{ + struct + { + volatile unsigned int errdetspien : 1; /**< spi enable rfpll unlock detection */ + volatile unsigned int spitrigger : 1; /**< VCO calibration trigger from spi */ + volatile unsigned int ckrefsel : 1; /**< reference clock freq select: 0, 26M; 1, 52M */ + volatile unsigned int ckpsel : 1; /**< reference clock pol select */ + volatile unsigned int locap30 : 4; /**< LO Mixer load cap control */ + volatile unsigned int lmngm20 : 3; /**< LO Mixer negative resistor control */ + volatile unsigned int sdiv210 : 2; /**< rpll 3.2G div2 input dc bias control */ + volatile unsigned int pllldo10 : 2; /**< pll ldo output voltage control: 00, 1.2V; 01 1.3V; 10, 1.4V;11 1.5V */ + volatile unsigned int vcoldo10 : 2; /**< vco ldo output voltage control: 00, 1.2V; 01 1.3V; 10, 1.4V;11 1.5V */ + volatile unsigned int lwvref10 : 2; /**< unlock detection voltage control(low) */ + volatile unsigned int lnvref10 : 2; /**< cdyn detection voltage control(low) */ + volatile unsigned int hwvref10 : 2; /**< unlock detection voltage control(high) */ + volatile unsigned int hnvref10 : 2; /**< cdyn detection voltage control(high) */ + volatile unsigned int captunedir : 1; /**< cap tune direction */ + volatile unsigned int pwdcpamp10 : 2; /**< 00,cp with op fb; 01, cp wi up/dn connect together; 11, cp wi up/dn connect to gnd/vdd */ + volatile unsigned int dcal30 : 4; /**< rfpll cp bias current calibration */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x5_TypeDef; + +/// REG0x6 +typedef union +{ + struct + { + volatile unsigned int vcmsel10 : 2; /**< ADC OP CM voltage adjustment(0:0.625 */ + volatile unsigned int tmpEn : 1; /**< 1: Enable temperature sensor; 0 : Disable temperature sensor; */ + volatile unsigned int NC : 1; /**< Reserved */ + volatile unsigned int lpfcapcalq50 : 6; /**< lpf Q path calibiration input */ + volatile unsigned int lpfcapcali50 : 6; /**< lpf I path calibiration input */ + volatile unsigned int dcocq : 8; /**< dcoc Q path input */ + volatile unsigned int dcoci : 8; /**< dcoc I path input */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x6_TypeDef; + +/// REG0x7 +typedef union +{ + struct + { + volatile unsigned int digdcoen : 1; /**< dcoc input selection,1: digital 0: spi */ + volatile unsigned int spilpfrxg30 : 4; /**< rxif gain, 0000-1111 0dB - 45dB step:3dB */ + volatile unsigned int autorxifgen : 1; /**< rxif gain control selection, 1: auto control 0: spi */ + volatile unsigned int pwdxtalbuf : 1; /**< 1: Power-down crystal oscillator buffer;;0: Enable crystal oscillator buffer; */ + volatile unsigned int pwdxtalcore : 1; /**< 1: Power-down crystal oscillator core;;0: Enable crystal oscillator core; */ + volatile unsigned int lpfvcmic10 : 2; /**< control auxiliary pmos pair gate voltage,default 01 */ + volatile unsigned int lpftxTest : 1; /**< tx test control bit,1 : tx test mode 0: default */ + volatile unsigned int xtalenref : 1; /**< 1: Enable crystal oscillator output as the reference to RF PLL only;;0: Enable crystal oscillator output as the reference to frequency doubler only. */ + volatile unsigned int voc1v210 : 2; /**< SPI/Digital regulator output programming; 00:1.2;01:1.3;10,1.4;11:1.5 */ + volatile unsigned int swm1v210 : 2; /**< Path selection of the switched output in low-power mode,00: shutdown, 01: high res, 10:res/2,11:res/3 */ + volatile unsigned int NC : 1; /**< NC */ + volatile unsigned int chin60 : 7; /**< substitute for cpu channel value */ + volatile unsigned int cksdmsel20 : 3; /**< rfpll sigma delta clock select:;0: 26MHz;;1: 40MHz;;2: 24MHz;;3: 19.2MHz;;4: 52MHz;;5:104MHz; */ + volatile unsigned int ckbandsel10 : 2; /**< vco band calibration clock select:;0: 26MHz;;1: 40MHz;;2: 24MHz;;3: 19.2MHz; */ + volatile unsigned int var10 : 2; /**< Kvco control: 0:40MHz/V;1:60MHz/V;2:60MHz/V;3:80MHz/V */ + volatile unsigned int enckcali : 1; /**< 0:VCO calibration clock do not power down;1: auto power down vco calibration clock; */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x7_TypeDef; + +/// REG0x8 +typedef union +{ + struct + { + volatile unsigned int vsrxmixldo10 : 2; /**< rx mixer LDO vout 00-11 1.2-1.5V */ + volatile unsigned int vsrxlnaldo10 : 2; /**< rx lna LDO vout 00-11 1.2-1.5V */ + volatile unsigned int isrxref10 : 2; /**< rx ref ib selection 00-11 10-15uA */ + volatile unsigned int isrxlna20 : 3; /**< rx lna ib selection 000-111 50-110uA */ + volatile unsigned int isrxlnac10 : 2; /**< rx lnacali ib selection 00-11 40-70uA */ + volatile unsigned int isrxdiv10 : 2; /**< rx div ib selection 00-11 10-25uA */ + volatile unsigned int vbsrxlo20 : 3; /**< rx lo biasing voltage: 000-111 0.4-0.75V */ + volatile unsigned int vresrxlo : 1; /**< rx lo vb ref voltage: 0-1 0.4-0.5V */ + volatile unsigned int ibsrxi2v10 : 2; /**< rx i2v ib selection 00-11 5-15uA */ + volatile unsigned int vcmsrxi2v : 1; /**< rx i2v vcm selction 0-1 0.6-0.5V */ + volatile unsigned int isrssigm10 : 2; /**< rx rssi gm ib selection 00-11 40-55uA */ + volatile unsigned int stbrssi10 : 2; /**< rx rssi stable time 00-11 150-450ns step:100ns */ + volatile unsigned int rssith50 : 6; /**< rx rssi threshhold Pant=-29dBm(th=000111) 0:-37dBm step:1dB */ + volatile unsigned int nc : 2; /**< reserved */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x8_TypeDef; + +/// REG0x9 +typedef union +{ + struct + { + volatile unsigned int agcrxfeEn : 1; /**< enble rxfe agc by mcu, 0/1 gctr by spi/mcu */ + volatile unsigned int grxlnaspi10 : 2; /**< rx lna gain 00-11 0/+6/+12/+18dBr */ + volatile unsigned int grxi2vspi10 : 2; /**< rx i2v gain 00-11 0/+6/+6/+12dBr */ + volatile unsigned int grssi10 : 2; /**< rx rssi option gain */ + volatile unsigned int grxlnacali20 : 3; /**< rx lan cali gain,000-111 -50~-5.5 caliin->i2vout step:6dB */ + volatile unsigned int rssiten : 1; /**< rssi analog v output test enable */ + volatile unsigned int dcaprxi2v10 : 2; /**< V2T: I2V feedback cap tuning 00-11: + 0/1p/2p/3p */ + volatile unsigned int drxfbrm : 1; /**< V2T: feedback mathing res on */ + volatile unsigned int dcaptrsw20 : 3; /**< V2T: 7/0 @ tx/rx mode */ + volatile unsigned int nc : 15; /**< reserved */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x9_TypeDef; + +/// REG0xA +typedef union +{ + struct + { + volatile unsigned int disrefPA10 : 2; /**< PA reference bias current programming for Constant-gm bias circuit,10u to 16.5uA */ + volatile unsigned int disrefpga10 : 2; /**< RFPGA reference bias current programming for Constant-gm bias circuit,10u to 16.5uA */ + volatile unsigned int dbpab30 : 4; /**< PA class-B input bias level programming */ + volatile unsigned int dbpaa30 : 4; /**< PA class-A input bias level programming */ + volatile unsigned int dbcpa10 : 2; /**< PA cascode device bias level programming,00(2.2v), 01(2.5v), 10(2.8v),11(3.0v) */ + volatile unsigned int noConn10 : 2; /**< No Connected */ + volatile unsigned int dcapbuf30 : 4; /**< PA buf output capacitor tuning */ + volatile unsigned int dbbuf30 : 4; /**< PA buf input device bias level programming */ + volatile unsigned int dbcbuf10 : 2; /**< PA buf cascode device bias level programming,00(2.2v), 01(2.5v), 10(2.8v),11(3.0v) */ + volatile unsigned int noConn10_ : 2; /**< No Connected */ + volatile unsigned int dtr30 : 4; /**< PA ramping-up time selection,0.13us(1111) to 3.45us(0000) */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0xA_TypeDef; + +/// REG0xB +typedef union +{ + struct + { + volatile unsigned int dcpga20 : 3; /**< RFPGA cascode device biaslevel programming */ + volatile unsigned int noConn : 1; /**< No Connected */ + volatile unsigned int dbpga30 : 4; /**< RFPGA input device bias level programming */ + volatile unsigned int dcappga30 : 4; /**< RFPGA output capacitor tuning */ + volatile unsigned int dcorMod30 : 4; /**< Modulator&RFPGA gain tuning for Pout calibration */ + volatile unsigned int dvlo20 : 3; /**< Modulator LO bias level programming,0.9v~1.07v,100(1.0v) */ + volatile unsigned int noConn_ : 1; /**< No Connected */ + volatile unsigned int dvcmo20 : 3; /**< Modulator V-I common mode voltage selection,010(vdd/2) */ + volatile unsigned int noConn__ : 1; /**< No Connected */ + volatile unsigned int dcapmod30 : 4; /**< Modulator output capacitor tuning */ + volatile unsigned int gctrlmod30 : 4; /**< Modulator gain control,3dB/step,0001(default gain+3),0010,0100(default gain-3),1000(default gain-6) */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0xB_TypeDef; + +/// REG0xC +typedef union +{ + struct + { + volatile unsigned int gctrlpga20 : 3; /**< RFPGA gain control. 111(max),110(max-3),101(max-6),100(max-9),011(max-12),010(max-18),001(max-24),000(max-30) */ + volatile unsigned int noConn : 1; /**< No Connected */ + volatile unsigned int dgainbuf20 : 3; /**< PA buf gain control,10dB(1111)~-5dB(001),4.5dB/step */ + volatile unsigned int noConn_ : 1; /**< No Connected */ + volatile unsigned int dgainPA20 : 3; /**< PA gain control,9dB(111)~-4dB(001),5dB/step */ + volatile unsigned int enTSSItst : 1; /**< TSSI test enable */ + volatile unsigned int dcorPA30 : 4; /**< PA gain tuning for Pout calibration */ + volatile unsigned int vregsel10 : 2; /**< RFLDO output voltage selection.00:1.2v; 01:1.3v; 10:1.4v; 11:1.5v */ + volatile unsigned int TSSIiref10 : 2; /**< TSSI reference bias current programming for Constant-gm bias circuit,10u to 16.5uA */ + volatile unsigned int gtssi10 : 2; /**< TSSI output gain programming,4K(00)/5K(01)/6K(10)/7K(11) */ + volatile unsigned int stbtssi10 : 2; /**< TSSI output stable time programming,0.15us(00) to 0.45us(11) */ + volatile unsigned int PcaliATTs10 : 2; /**< TSSI Pout calibration input attenuation selection,00(-6dB)~11(-24dB),6dB/step */ + volatile unsigned int enPcaliGm : 1; /**< TSSI Pout calibration option to enable Gm1 */ + volatile unsigned int enPcali : 1; /**< TSSI Pout calibration enable */ + volatile unsigned int enIQcali : 1; /**< TSSI IQ calibration enable */ + volatile unsigned int enDCcaliGm1 : 1; /**< TSSI DC calibration Gm1 block enable for -30~-15dBm input range */ + volatile unsigned int enDCcali : 1; /**< DC/IQ calibration enable.enDCcali=1 for DC or IQ calibration */ + volatile unsigned int TSSIsel : 1; /**< TSSI output selection.TSSIsel=1 for Pout calibration;TSSIsel=0 for DC/IQ calibration */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0xC_TypeDef; + +/// REG0xD +typedef union +{ + struct + { + volatile unsigned int dacselection : 1; /**< 0: external dac, 1: internal dac */ + volatile unsigned int lpfrxbw : 1; /**< lpf rx bandwidth selection 1: high bandwidth(19MHz) 0: low bandwidth(9MHz); */ + volatile unsigned int lpftxbw : 1; /**< lpf tx bandwidth selection 1: high bandwidth(29MHz) 0: low bandwidth(14MHz); */ + volatile unsigned int lpftrxsw : 1; /**< LPF tx rx switch(1:tx,0:rx) */ + volatile unsigned int enlpf : 1; /**< LPF enable */ + volatile unsigned int enif : 1; /**< ADC, DAC Ldo enable */ + volatile unsigned int endcoc : 1; /**< DCOC DAC enable */ + volatile unsigned int enrxadc : 1; /**< RX ADC enable */ + volatile unsigned int entxdac : 1; /**< TX dac enable */ + volatile unsigned int entxdacbias : 1; /**< TX dac bias enable */ + volatile unsigned int enrxrssi : 1; /**< RX RF Rssi enable */ + volatile unsigned int enrxref : 1; /**< RX RF Vref enable */ + volatile unsigned int enrxi2v : 1; /**< RX I2V enable */ + volatile unsigned int enrxmix : 1; /**< RX mixer enable */ + volatile unsigned int enlnacal : 1; /**< RX look back lna input enable */ + volatile unsigned int enlna : 1; /**< Rxfe lna enable */ + volatile unsigned int txvinsel : 1; /**< Txfe input selection(0,cal when need bypass TX filter,1:normal) */ + volatile unsigned int entssi : 1; /**< Txfe tssi enable */ + volatile unsigned int entssiadc : 1; /**< Txfe tssi adc enable */ + volatile unsigned int entxferef : 1; /**< Txfe reference enable */ + volatile unsigned int entxfebias : 1; /**< Txfe bias enable */ + volatile unsigned int entxv2i : 1; /**< Tx v2i enable */ + volatile unsigned int entxlo : 1; /**< Tx LO enable */ + volatile unsigned int entxpga : 1; /**< TX PGA enable */ + volatile unsigned int enpa : 1; /**< Tx PA enable */ + volatile unsigned int enrxsw : 1; /**< RX switch enable */ + volatile unsigned int entxsw : 1; /**< TX switch enable */ + volatile unsigned int trswpll : 1; /**< rf pll tx rx switch */ + volatile unsigned int enrfpll : 1; /**< rf pll enable */ + volatile unsigned int endobuler : 1; /**< dobuler enable */ + volatile unsigned int endpll : 1; /**< digital pll enable */ + volatile unsigned int enxtal : 1; /**< xtal enable signal */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0xD_TypeDef; + +/// REG0xE +typedef union +{ + struct + { + volatile unsigned int dacselection : 1; /**< 0: external dac, 1: internal dac */ + volatile unsigned int lpfrxbw : 1; /**< lpf rx bandwidth selection 1: high bandwidth(19MHz) 0: low bandwidth(9MHz); */ + volatile unsigned int lpftxbw : 1; /**< lpf tx bandwidth selection 1: high bandwidth(29MHz) 0: low bandwidth(14MHz); */ + volatile unsigned int lpftrxsw : 1; /**< LPF tx rx switch(1:tx,0:rx) */ + volatile unsigned int enlpf : 1; /**< LPF enable */ + volatile unsigned int enif : 1; /**< ADC, DAC Ldo enable */ + volatile unsigned int endcoc : 1; /**< DCOC DAC enable */ + volatile unsigned int enrxadc : 1; /**< RX ADC enable */ + volatile unsigned int entxdac : 1; /**< TX dac enable */ + volatile unsigned int entxdacbias : 1; /**< TX dac bias enable */ + volatile unsigned int enrxrssi : 1; /**< RX RF Rssi enable */ + volatile unsigned int enrxref : 1; /**< RX RF Vref enable */ + volatile unsigned int enrxi2v : 1; /**< RX I2V enable */ + volatile unsigned int enrxmix : 1; /**< RX mixer enable */ + volatile unsigned int enlnacal : 1; /**< RX look back lna input enable */ + volatile unsigned int enlna : 1; /**< Rxfe lna enable */ + volatile unsigned int txvinsel : 1; /**< Txfe input selection(0,cal when need bypass TX filter,1:normal) */ + volatile unsigned int entssi : 1; /**< Txfe tssi enable */ + volatile unsigned int entssiadc : 1; /**< Txfe tssi adc enable */ + volatile unsigned int entxferef : 1; /**< Txfe reference enable */ + volatile unsigned int entxfebias : 1; /**< Txfe bias enable */ + volatile unsigned int entxv2i : 1; /**< Tx v2i enable */ + volatile unsigned int entxlo : 1; /**< Tx LO enable */ + volatile unsigned int entxpga : 1; /**< TX PGA enable */ + volatile unsigned int enpa : 1; /**< Tx PA enable */ + volatile unsigned int enrxsw : 1; /**< RX switch enable */ + volatile unsigned int entxsw : 1; /**< TX switch enable */ + volatile unsigned int trswpll : 1; /**< rf pll tx rx switch */ + volatile unsigned int enrfpll : 1; /**< rf pll enable */ + volatile unsigned int endobuler : 1; /**< dobuler enable */ + volatile unsigned int endpll : 1; /**< digital pll enable */ + volatile unsigned int enxtal : 1; /**< xtal enable signal */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0xE_TypeDef; + +/// REG0xF +typedef union +{ + struct + { + volatile unsigned int regbanksel : 1; /**< Register Bank Select. 0x0: Bank0 (Reg00~Reg14); ; 0x1: Bank1 (Reg16~Reg30) */ + volatile unsigned int clkdacsel : 1; /**< DAC Clock Select. 0x0: 80MHz; 0x1: 160MHz */ + volatile unsigned int clkadcsel : 1; /**< ADCClock Select. 0x0: 40MHz; 0x1: 80MHz */ + volatile unsigned int NC : 1; /**< NC */ + volatile unsigned int NC_ : 1; /**< NC */ + volatile unsigned int sinadtxen : 1; /**< TX Sinad Enable */ + volatile unsigned int sinadrxen : 1; /**< RX Sinad Detect Enable */ + volatile unsigned int tssicalen : 1; /**< TSSI Calibration Enable, enable 40M clock */ + volatile unsigned int NC__ : 5; /**< NC */ + volatile unsigned int sinadhpfcoef : 2; /**< HPF Coefficence for RX Siand Detect. 0x0: 1/8 0x1: 1/32; 0x2: 1/128; 0x3: 1/1024 */ + volatile unsigned int clkdacinv : 1; /**< DAC Clock Invert */ + volatile unsigned int clkadcinv : 1; /**< ADC Clock Invert */ + volatile unsigned int reserved : 11; /**< Reserved */ + volatile unsigned int sysldoen : 1; /**< enable sysldo */ + volatile unsigned int sysldolp : 1; /**< sysldo low power enable */ + volatile unsigned int endspvdd : 1; /**< dsp vdd enable */ + volatile unsigned int digldolp : 1; /**< digldo low power enable */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0xF_TypeDef; + +/// REG0x10 +typedef union +{ + struct + { + volatile unsigned int dacselection : 1; /**< 0: external dac, 1: internal dac */ + volatile unsigned int lpfrxbw : 1; /**< lpf rx bandwidth selection 1: high bandwidth(19MHz) 0: low bandwidth(9MHz); */ + volatile unsigned int lpftxbw : 1; /**< lpf tx bandwidth selection 1: high bandwidth(29MHz) 0: low bandwidth(14MHz); */ + volatile unsigned int lpftrxsw : 1; /**< LPF tx rx switch(1:tx,0:rx) */ + volatile unsigned int enlpf : 1; /**< LPF enable */ + volatile unsigned int enif : 1; /**< ADC, DAC Ldo enable */ + volatile unsigned int endcoc : 1; /**< DCOC DAC enable */ + volatile unsigned int enrxadc : 1; /**< RX ADC enable */ + volatile unsigned int entxdac : 1; /**< TX dac enable */ + volatile unsigned int entxdacbias : 1; /**< TX dac bias enable */ + volatile unsigned int enrxrssi : 1; /**< RX RF Rssi enable */ + volatile unsigned int enrxref : 1; /**< RX RF Vref enable */ + volatile unsigned int enrxi2v : 1; /**< RX I2V enable */ + volatile unsigned int enrxmix : 1; /**< RX mixer enable */ + volatile unsigned int enlnacal : 1; /**< RX look back lna input enable */ + volatile unsigned int enlna : 1; /**< Rxfe lna enable */ + volatile unsigned int txvinsel : 1; /**< Txfe input selection(0,cal when need bypass TX filter,1:normal) */ + volatile unsigned int entssi : 1; /**< Txfe tssi enable */ + volatile unsigned int entssiadc : 1; /**< Txfe tssi adc enable */ + volatile unsigned int entxferef : 1; /**< Txfe reference enable */ + volatile unsigned int entxfebias : 1; /**< Txfe bias enable */ + volatile unsigned int entxv2i : 1; /**< Tx v2i enable */ + volatile unsigned int entxlo : 1; /**< Tx LO enable */ + volatile unsigned int entxpga : 1; /**< TX PGA enable */ + volatile unsigned int enpa : 1; /**< Tx PA enable */ + volatile unsigned int enrxsw : 1; /**< RX switch enable */ + volatile unsigned int entxsw : 1; /**< TX switch enable */ + volatile unsigned int trswpll : 1; /**< rf pll tx rx switch */ + volatile unsigned int enrfpll : 1; /**< rf pll enable */ + volatile unsigned int endobuler : 1; /**< dobuler enable */ + volatile unsigned int endpll : 1; /**< digital pll enable */ + volatile unsigned int enxtal : 1; /**< xtal enable signal */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x10_TypeDef; + +/// REG0x11 +typedef union +{ + struct + { + volatile unsigned int txsinadtable : 11; /**< TX Sinad Table;D[0] = 0: Write I Path Table Data;D[0] = 1: Write Q Path Table Data;LSBD[1] ;Both I and Q need 16 number data */ + volatile unsigned int reserved : 21; /**< Reserved */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x11_TypeDef; + +/// REG0x12 +typedef union +{ + struct + { + volatile unsigned int lpfouttsten : 1; /**< lpf output test enable,0:disenable,1:enable */ + volatile unsigned int lpfintsten : 1; /**< lpf input test enable,0:disenable,1:enable */ + volatile unsigned int ifbufic20 : 3; /**< test buffer bias current control,0:low, 1:high */ + volatile unsigned int ifadcvcmsel : 2; /**< if adc reference voltage selection. */ + volatile unsigned int ldodpll10 : 2; /**< digital pll and xtal ldo voutselection. 00:low, 11:high */ + volatile unsigned int NC : 1; /**< Reserved bit; */ + volatile unsigned int buftstselection : 1; /**< buffer input selection:1:lpf, 0:rssidactst,rssitst,tssitst,adcstst1 */ + volatile unsigned int entstbufldo : 1; /**< enable test buffer ldo, 0:disenable,1:enable */ + volatile unsigned int NC_ : 1; /**< Reserved bit; */ + volatile unsigned int dldovctrl10 : 2; /**< dig do output control voltage: 0:1.2V 0.1V/step */ + volatile unsigned int adcinSel : 1; /**< SAR ADC input selection;0:TSSI, 1:Temperature */ + volatile unsigned int adciselr20 : 3; /**< adc reference bias current selection,0:0.45x,1:0.5x,2:0.55X,3:0.6x,4:0.9x,5:1X,6:1.1X,7:1.2X */ + volatile unsigned int adciselc20 : 3; /**< adc core bias current selection,0:5x,1:0.6x,2:0.7X,3:0.8x,4:1.0x,5:1.2X,6:1.4X,7:1.7X */ + volatile unsigned int adcrefbwsel : 1; /**< adc bandwidth selection.0:40MHz, 1:80MHz */ + volatile unsigned int adcten : 1; /**< adc test enable(1:only I work, 0:both path work) */ + volatile unsigned int fictrl30 : 4; /**< lpf bias current selection, 0:low, 15:high */ + volatile unsigned int flvcm10 : 2; /**< lpf common mode voltage selection,00:low , 11: high */ + volatile unsigned int ldoifsel3v10 : 2; /**< If ldo vout selection:00:low, 11: high */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x12_TypeDef; + +/// REG0x13 +typedef union +{ + struct + { + volatile unsigned int r2rx10 : 2; /**< rx mode loopfilter R2 control */ + volatile unsigned int c1rx10 : 2; /**< rx mode loopfilter C1 control */ + volatile unsigned int rzrx40 : 5; /**< rx mode loopfilter Rz control */ + volatile unsigned int icprx40 : 5; /**< rx mode cp current control */ + volatile unsigned int icpoff20 : 3; /**< cp offset current control */ + volatile unsigned int icpsel : 1; /**< icp bias select: 0, internal; 1, external */ + volatile unsigned int r2tx10 : 2; /**< tx mode loopfilter R2 control */ + volatile unsigned int c1tx10 : 2; /**< tx mode loopfilter C1 control */ + volatile unsigned int rztx40 : 5; /**< tx mode loopfilter Rz control */ + volatile unsigned int icptx40 : 5; /**< tx mode cp current control */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x13_TypeDef; + +/// REG0x14 +typedef union +{ + struct + { + volatile unsigned int dci0db : 8; /**< RX dcoc I path input for 0dB of PGA */ + volatile unsigned int dcq0db : 8; /**< RX dcoc Q path input for 0dB of PGA */ + volatile unsigned int dci3db : 8; /**< RX dcoc I path input for 3dB of PGA */ + volatile unsigned int dcq3db : 8; /**< RX dcoc Q path input for 3dB of PGA */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x14_TypeDef; + +/// REG0x15 +typedef union +{ + struct + { + volatile unsigned int dci6db : 8; /**< RX dcoc I path input for 6dB of PGA */ + volatile unsigned int dcq6db : 8; /**< RX dcoc Q path input for 6dB of PGA */ + volatile unsigned int dci9db : 8; /**< RX dcoc I path input for 9dB of PGA */ + volatile unsigned int dcq9db : 8; /**< RX dcoc Q path input for 9dB of PGA */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x15_TypeDef; + +/// REG0x16 +typedef union +{ + struct + { + volatile unsigned int dci12db : 8; /**< RX dcoc I path input for 12dB of PGA */ + volatile unsigned int dcq12db : 8; /**< RX dcoc Q path input for 12dB of PGA */ + volatile unsigned int dci15db : 8; /**< RX dcoc I path input for 15dB of PGA */ + volatile unsigned int dcq15db : 8; /**< RX dcoc Q path input for 15dB of PGA */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x16_TypeDef; + +/// REG0x17 +typedef union +{ + struct + { + volatile unsigned int dci18db : 8; /**< RX dcoc I path input for 18dB of PGA */ + volatile unsigned int dcq18db : 8; /**< RX dcoc Q path input for 18dB of PGA */ + volatile unsigned int dci21db : 8; /**< RX dcoc I path input for 21dB of PGA */ + volatile unsigned int dcq21db : 8; /**< RX dcoc Q path input for 21dB of PGA */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x17_TypeDef; + +/// REG0x18 +typedef union +{ + struct + { + volatile unsigned int dci24db : 8; /**< RX dcoc I path input for 24dB of PGA */ + volatile unsigned int dcq24db : 8; /**< RX dcoc Q path input for 24dB of PGA */ + volatile unsigned int dci27db : 8; /**< RX dcoc I path input for 27dB of PGA */ + volatile unsigned int dcq27db : 8; /**< RX dcoc Q path input for 27dB of PGA */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x18_TypeDef; + +/// REG0x19 +typedef union +{ + struct + { + volatile unsigned int dci30db : 8; /**< RX dcoc I path input for 30dB of PGA */ + volatile unsigned int dcq30db : 8; /**< RX dcoc Q path input for 30dB of PGA */ + volatile unsigned int dci33db : 8; /**< RX dcoc I path input for 33dB of PGA */ + volatile unsigned int dcq33db : 8; /**< RX dcoc Q path input for 33dB of PGA */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x19_TypeDef; + +/// REG0x1A +typedef union +{ + struct + { + volatile unsigned int dci36db : 8; /**< RX dcoc I path input for 36dB of PGA */ + volatile unsigned int dcq36db : 8; /**< RX dcoc Q path input for 36dB of PGA */ + volatile unsigned int dci39db : 8; /**< RX dcoc I path input for 39dB of PGA */ + volatile unsigned int dcq39db : 8; /**< RX dcoc Q path input for 39dB of PGA */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x1A_TypeDef; + +/// REG0x1B +typedef union +{ + struct + { + volatile unsigned int dci42db : 8; /**< RX dcoc I path input for 42dB of PGA */ + volatile unsigned int dcq42db : 8; /**< RX dcoc Q path input for 42dB of PGA */ + volatile unsigned int dci45db : 8; /**< RX dcoc I path input for 45dB of PGA */ + volatile unsigned int dcq45db : 8; /**< RX dcoc Q path input for 45dB of PGA */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x1B_TypeDef; + +/// REG0x1C +typedef union +{ + struct + { + volatile unsigned int dacoutqspi90 : 10; /**< DAC Q channel input in analog test only; */ + volatile unsigned int NC : 2; /**< Reserved bits; */ + volatile unsigned int dacoutispi90 : 10; /**< DAC I channel input in analog test only; */ + volatile unsigned int NC_ : 10; /**< Reserved bits; */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x1C_TypeDef; // trx reg28 just for test +#define BK7011_TRxV2ABASE 0X00800080 +#endif + +/// BK7011TRxV2A +struct BK7011TRxV2A_TypeDef +{ + volatile BK7011_TRxV2A_REG0x0_TypeDef *REG0x0; + volatile BK7011_TRxV2A_REG0x1_TypeDef *REG0x1; + volatile BK7011_TRxV2A_REG0x2_TypeDef *REG0x2; + volatile BK7011_TRxV2A_REG0x3_TypeDef *REG0x3; + volatile BK7011_TRxV2A_REG0x4_TypeDef *REG0x4; + volatile BK7011_TRxV2A_REG0x5_TypeDef *REG0x5; + volatile BK7011_TRxV2A_REG0x6_TypeDef *REG0x6; + volatile BK7011_TRxV2A_REG0x7_TypeDef *REG0x7; + volatile BK7011_TRxV2A_REG0x8_TypeDef *REG0x8; + volatile BK7011_TRxV2A_REG0x9_TypeDef *REG0x9; + volatile BK7011_TRxV2A_REG0xA_TypeDef *REG0xA; + volatile BK7011_TRxV2A_REG0xB_TypeDef *REG0xB; + volatile BK7011_TRxV2A_REG0xC_TypeDef *REG0xC; + volatile BK7011_TRxV2A_REG0xD_TypeDef *REG0xD; + volatile BK7011_TRxV2A_REG0xE_TypeDef *REG0xE; + volatile BK7011_TRxV2A_REG0xF_TypeDef *REG0xF; + volatile BK7011_TRxV2A_REG0x10_TypeDef *REG0x10; + volatile BK7011_TRxV2A_REG0x11_TypeDef *REG0x11; + volatile BK7011_TRxV2A_REG0x12_TypeDef *REG0x12; + volatile BK7011_TRxV2A_REG0x13_TypeDef *REG0x13; + volatile BK7011_TRxV2A_REG0x14_TypeDef *REG0x14; + volatile BK7011_TRxV2A_REG0x15_TypeDef *REG0x15; + volatile BK7011_TRxV2A_REG0x16_TypeDef *REG0x16; + volatile BK7011_TRxV2A_REG0x17_TypeDef *REG0x17; + volatile BK7011_TRxV2A_REG0x18_TypeDef *REG0x18; + volatile BK7011_TRxV2A_REG0x19_TypeDef *REG0x19; + volatile BK7011_TRxV2A_REG0x1A_TypeDef *REG0x1A; + volatile BK7011_TRxV2A_REG0x1B_TypeDef *REG0x1B; + volatile BK7011_TRxV2A_REG0x1C_TypeDef *REG0x1C; +}; +#endif + +/// POWER +typedef struct +{ + unsigned int rega_0_1 : 2; + unsigned int rega_8_13 : 6; + unsigned int regb_28_31 : 4; + unsigned int regc_0_3 : 4; + unsigned int regc_4_7 : 4; + unsigned int regc_8_11 : 4; + unsigned int pregain : 5; + unsigned int unuse : 3; +} PWR_REGS; + +/******************************************************************************* +* Function Declarations +*******************************************************************************/ +#endif // (CFG_SOC_NAME != SOC_BK7231) + +#endif // _BK7231U_CAL_H_ \ No newline at end of file diff --git a/beken_os/beken378/func/bk7011_cal/bk7231N_cal.c b/beken_os/beken378/func/bk7011_cal/bk7231N_cal.c new file mode 100755 index 0000000..603e617 --- /dev/null +++ b/beken_os/beken378/func/bk7011_cal/bk7231N_cal.c @@ -0,0 +1,5782 @@ + +#include "include.h" +#if (CFG_SOC_NAME == SOC_BK7231N) +#include "arm_arch.h" +#include "target_util_pub.h" +#include "mem_pub.h" +#include "drv_model_pub.h" +#include "sys_ctrl_pub.h" +#include "phy.h" +#include "bk7011_cal_pub.h" +#include "bk7011_cal.h" +#include +#include "flash_pub.h" + +#ifdef INCLUDE_OS +#include "cmd_evm.h" +#include "temp_detect_pub.h" +#endif + +#include "power_save_pub.h" +#include "gpio.h" +#include "gpio_pub.h" +#include "icu_pub.h" +#include "saradc_pub.h" +#include "sys_ctrl.h" +#include "param_config.h" +#include "str_pub.h" +#include "reg_mdm_cfg.h" + +#define CAL_RESULT_TO_FLASH 0 +#define CAL_RESULT_FLASH_ADDR 0x000F1000UL +#define RCB_POWER_TABLE_ADDR 0x01050200 + +/* 12 bits, [-2^11, 2^11]==>[0x800, 0x7FF]==>[-2048,2047] */ +#define BK_TX_DAC_SIGNED_MIN 0x800 +#define BK_TX_DAC_SIGNED_MAX 0x7FF +#define BK_TX_DAC_UNSIGNED_MAX 0x1000 +#define BK_TX_DAC_UNSIGNED_MASK 0xFFF +#define BK_TX_DAC_UNSIGNED_MASK_GAIN 0xFA0 +#define BK_TX_DAC_COEF 4 // 2^(12-10) from 10 bits to 12 bits + +#if CFG_SUPPORT_CALIBRATION +#define TX_WANTED_POWER_CAL 0 +#define TX_IQ_POWER_CAL 1 +#define TX_IQ_LOOPBACK_POWER_CAL 2 +#define TX_DC_CAL 0 +#define TX_DC_CAL_IQ 1 +#define TX_DC_LOOPBACK_CAL_IQ 2 +#define TX_GAIN_IMB_CAL 0 +#define TX_GAIN_LOOPBACK_IMB_CAL 1 +#define TX_PHASE_IMB_CAL 0 +#define TX_PHASE_LOOPBACK_IMB_CAL 1 + +extern void bk7011_cal_pll(void); + +#if DIFFERENCE_PIECES_CFG +static UINT8 bk7011_cal_dcormod_get(void); +#endif + +void rwnx_set_tpc_txpwr_by_tmpdetect(INT16 shift_b, INT16 shift_g); +UINT32 manual_cal_txpwr_tab_ready_in_flash(void); +extern uint32_t get_ate_mode_state(void); +extern UINT32 gtest_mode; + +#define TRX_REG_0XA_VAL 0x80631DFF +#define TRX_REG_0XB_VAL 0xA9758ACE//0xAF758FCE//AF758FCE A9758ACE //yongguang modify +#define TRX_REG_0XC_VAL 0x06782EAA //0x067827CC +#define TRX_REG_0XD_VAL 0xDDF90339//0xD9FB0339 +#define TSSI_POUT_TH_G 0x7D//0xB5 actually, yongguang20200918 tune it for workaround +#define TSSI_POUT_TH_B 0xD0//0xE0 actually, yongguang20200918 tune it for workaround + +#define POWER_TABLE_11B_1DB_STEP (2) /* refer to cfg_tab_b, 0.50db for each step */ +#define POWER_TABLE_11G_1DB_STEP (4) /* refer to cfg_tab_g, 0.25db for each step */ + +#define POWER_CALI_11B_SHIFT (0) /* add 0db for 11b when auto calibration for tuya, should adjust this for each batch */ +#define POWER_CALI_11G_SHIFT (0) /* add 2db for 11g when auto calibration for tuya, should adjust this for each batch */ + +#define TXIQ_IMB_TSSI_TH 0x35B// (0x840-0x180) + +#define TXIQ_IMB_TSSI_TH_LOOPBACK 60 + +#define No_TXPOWERCAL 0 +#define TXIQ_TSSI_TH 0x40 +#define TRX_REG_0XD_TX_IQ_VAL 0xDDFB0339 //0xD9FF0338 //0214 //wyg1/17 +#define TRX_REG_0XD_TX_IQ_VAL_GAIN_PHASE 0xD9FB0339 //0xD9FF0338 //wyg1/17 +#define TRX_REG_0XD_TX_LOOPBACK_IQ_VAL 0xD9FE7FF1 //0214 0xD9FE7FF1 +#define TRX_REG_0XD_TX_FILTER_IQ_VAL 0xFC4E03B9 + +#define TRX_REG_0XC_RXIQ_VAL TRX_REG_0XC_VAL // 1A244ED //0215 increasse gain due to load antenna 01A244DD +#define TRX_REG_0XE_RXIQ_VAL 0xD9F87FF1 //0214 FDF87FF1 + + +#define gi_dc_tx_pa_dgainPA30 1 +#define gi_dc_tx_pa_dgainbuf30 7 +#define gi_gain_tx_pa_dgainPA30 1 +#define gi_gain_tx_pa_dgainbuf30 1 +#define gi_gain_tx_pa_dgainbuf30_BK7231P 3 + +#define gi_dc_tx_loopback_pa_dgainPA30 7 +#define gi_dc_tx_loopback_pa_dgainbuf30 6 +#define gi_gain_tx_loopback_pa_dgainPA30 6 +#define gi_gain_tx_loopback_pa_dgainbuf30 4 +#define gi_phase_tx_loopback_pa_dgainPA30 6 +#define gi_phase_tx_loopback_pa_dgainbuf30 4 + +#define gi_cal_rx_iq_pa_dgainPA30 4 +#define gi_cal_rx_iq_pa_dgainbuf30 5 + +#define CALI_MODE_UNKNOWN -1 + +static BK7011_CALI_CONTEXT gcali_context = +{ + 2, /* gtx_dc_n, the times of first dc cal. (64 * BK_TX_DAC_COEF)=2^8 */ + CAL_DELAY100US, /* gst_rx_adc */ + CAL_DELAY05US, /* gst_sar_adc */ + + CALI_MODE_UNKNOWN, /* cali_mode */ + TSSI_POUT_TH_B, /* gtx_tssi_thred_b */ + TSSI_POUT_TH_G, /* gtx_tssi_thred_g */ + + 0, /* is_tpc_used */ + +#if CFG_USE_TEMPERATURE_DETECT + 0, /* ble_pwr_indx */ + 0, /* ble_pwr_shift */ +#endif + DEVICE_ID_BK7231N_D & DEVICE_ID_MASK, /* device_id */ +}; + +static BK7011_CALI_RESULT gcali_result = +{ + 0, /* gbias_after_cal */ + 0, /* gav_tssi */ + + BK_TX_DAC_SIGNED_MIN, /* gtx_i_dc_comp */ + BK_TX_DAC_SIGNED_MIN, /* gtx_q_dc_comp */ + BK_TX_DAC_SIGNED_MIN + (BK_TX_DAC_COEF * 2), /* gtx_i_dc_comp_loopback */ + BK_TX_DAC_SIGNED_MAX, /* gtx_q_dc_comp_loopback */ + + BK_TX_DAC_UNSIGNED_MASK, /* gtx_i_gain_comp */ + BK_TX_DAC_UNSIGNED_MASK, /* gtx_q_gain_comp */ + BK_TX_DAC_UNSIGNED_MASK, /* gtx_i_gain_comp_loopback */ + BK_TX_DAC_UNSIGNED_MASK - 12 * BK_TX_DAC_COEF, /* gtx_q_gain_comp_loopback */ + + BK_TX_DAC_SIGNED_MIN, /* gtx_phase_comp */ + BK_TX_DAC_SIGNED_MIN, /* gtx_phase_ty2 */ + BK_TX_DAC_SIGNED_MIN, /* gtx_phase_comp_loopback */ + BK_TX_DAC_SIGNED_MIN, /* gtx_phase_ty2_loopback */ + + 0x10, /* gtx_ifilter_corner */ + 0x10, /* gtx_qfilter_corner */ + + 0x400, /* const_iqcal_p */ //0x3B0 + + BK_TX_DAC_SIGNED_MIN, /* grx_amp_err_wr */ + 0x041 * BK_TX_DAC_COEF, /* grx_phase_err_wr */ + + 0, /* rx_amp_err_rd */ + 0, /* rx_phase_err_rd */ + 0, /* rx_ty2_rd */ + + { + 0x807C807C, + 0x80788078, + 0x80788078, + 0x88688870, + 0x88688868, + 0x88688868, + 0x88688868, + 0x88688868 + }, /* g_rx_dc_gain_tab */ +}; + +const static UINT32 BK7231N_TRX_ROM[] = { + 0x04138462, /* 00-R0x00, // */ +#if (CFG_XTAL_FREQUENCE == CFG_XTAL_FREQUENCE_40M) + 0xAFBBC311, /* 01-R0x01, //AE09C081 26M spur 0xF259347B;*/ + 0xCFA28802, /* 02-R0x02, // 0xC3A28800*/ + 0x000023E4, /* 03-R0x03, // 0x00002164 0x000023E4 */ + 0x65C89655, /* 04-R0x04, // */ + 0x18C031AA, /* 05-R0x05, // */ +#else + 0xFE09C189, /* 01-R0x01, //AE09C081 26M spur 0xF259347B;*/ //wanjian20200907 0xAE09C181->0xFE09C189 + 0xCFA28800, /* 02-R0x02, // 0xC3A28800*/ + 0x000023E4, /* 03-R0x03, // 0x00002164 0x000023E4 */ //wangjian20200828 0x00002164->0x000023E4 + 0x65C89659, /* 04-R0x04, // */ //wanjian20200907 0x65C89655->0x65C89659 + 0xA8C030AA, /* 05-R0x05, // */ +#endif + 0x727A0004, /* 06-R0x06, // */ + 0x0226826A, /* 07-R0x07, // 00F5:4th;20F5:2nd *///wyg F7E6026B //desheng20200827 0x57E6826B //guo20200831 <26:22>=8 + 0x28A8088A, /* 08-R0x08, // */ //wangjian20200822 0x082C091F->0x08AC091F //wangjian20200828 0x08AC088A //huamin20200902 <29>=1 + 0x001E077E, /* 09-R0x09, // */ //wangjian20200822 0x001E676F->0x001E076F //huamin20200915 <4:3>=3 + TRX_REG_0XA_VAL, /* 10-R0x0A, // */ + TRX_REG_0XB_VAL, /* 11-R0x0B, // */ + TRX_REG_0XC_VAL, /* 12-R0x0C, // */ + TRX_REG_0XD_VAL, /* 13-R0x0D, // */ + 0xDA01BCF0, /* 14-R0x0E, // */ + 0x00008000, /* 15-R0x0F, // */ + 0xD8C00130, /* 16-R0x10, //0xD8800130 */ + 0x00000000, /* 17-R0x11, // */ + 0x47390195, /* 18-R0x12, // 0xF0090481 */ //wangjiang20200822 0x473AC015->0x473AC195 //desheng20200827 0x473AC195->47390195 + 0x7B305ECC, /* 19-R0x13, // */ + 0x807C807C, /* 20-R0x14, // */ + 0x80788078, /* 21-R0x15, // */ + 0x80788078, /* 22-R0x16, // */ + 0x88688870, /* 23-R0x17, // */ + 0x88688868, /* 24-R0x18, // */ + 0x88688868, /* 25-R0x19, // */ + 0x88688868, /* 26-R0x1A, // */ + 0x88688868, /* 27-R0x1B, // */ + 0x10F8FFA7 /* 28-R0x1C, // */ +}; + +const static UINT32 BK7231N_RC_ROM[] = { + 0x00000009, /* 00-R0x0, 0x0000; */ + 0xF0000000, /* 01-R0x1, 0x0004; */ + 0x00000030, /* 02-R0x5, 0x0014; */ + 0x00010001, /* 03-R0x8, 0x0020; */ + 0x000100e0, /* 04-R0xB, 0x002C; */ + 0x00010070, /* 05-R0xE, 0x0038; */ + 0x00010001, /* 06-R0x11, 0x0044; */ + 0x00010005, /* 07-R0x19, 0x0064; */ + TRX_REG_0XD_VAL, /* 07-R0x1A, 0x0068; the same with BK7231N_TRX_RAM.REG0xD */ + 0x00000002, /* 08-R0x1C, 0x0070; */ + 0x0000012c, /* 09-R0x1E, 0x0078; */ + 0x10F8FFA7, /* 10-R0x3C, 0x00F0; */ + 0x00F8FFA7, /* 11-R0x3E, 0x00F8; */ + 0x00BA0201, /* 12-R0x3F, 0x00FC; */ + 0x00000095, /* 13-R0x40, 0x0100; */ + 0x00000000, /* 14-R0x41, 0x0104; */ + 0x03570108, /* 15-R0x42, 0x0108; */ + 0x00000200, /* 15-R0x43, 0x010C; */ + 0x08000800, /* 16-R0x4C, 0x0130; */ + 0x2CC02000, /* 17-R0x4D, 0x0134; */ + 0x00000001, /* 25-R0x4E, 0x0138; */ + 0x07B507DE, /* 18-R0x4F, 0x013C; */ + 0x0FFF0FFF, /* 19-R0x50, 0x0140; */ + 0x08000800, /* 20-R0x51, 0x0144; */ + 0xC4008800, /* 21-R0x52, 0x0148; */ + (0x007456A8|((TSSI_POUT_TH_G)<<1)), /* 22-R0x54, 0x0150; */ + 0x00000000, /* 23-R0x55, 0x0154; */ + 0x00000000, /* 24-R0x56, 0x0158; */ + 0x80B2E065, /* 25-R0x57, 0x015C; */ + 0x00000000, /* 26-R0x5A, 0x0168; */ + 0x00000000, /* 27-R0x5B, 0x016C; */ + 0x80000064, /* 24-R0x5C, 0x0170; */ + 0x00000000, /* 28-R0x6A, 0x01A8; */ +}; + +static BK7231N_TRX_TypeDef BK7231N_TRX_RAM; +static BK7231N_RC_TypeDef BK7231N_RC_RAM; + +INT32 gtx_dcorMod = 0x4; +INT32 gtx_dcorPA = 0x8; +INT32 gtx_pre_gain = 0x10; + +INT32 gtx_dcorMod_temp = 0x4; +INT32 gtx_dcorPA_temp = 0x8; +INT32 gtx_pre_gain_temp = 0x7; + +struct cal_pwr_st +{ + UINT8 idx; + UINT8 mode; +}; + +struct cal_pwr_st g_pwr_current; + +#include "net_param_pub.h" + +#define PWRI(gain, rb_28_31, pactrl, padctrl, rc_0_2, ra_8_13, ra_4_7, ra_0_1) \ +{ \ + .unuse = 0, \ + .pregain = gain, \ + .regc_8_10 = pactrl, \ + .regc_4_6 = padctrl, \ +} + +#define PWR_GAIN_BASE_B (0xE0A2A000) +#define TCP_PAMAP_TAB_B_LEN (48) +const static PWR_REGS cfg_tab_b[TCP_PAMAP_TAB_B_LEN] = { + // pregain REGB<31:28> REGC<10:8> REGC<6:4> REGC<2:0> REGA<13:8> REGA<7:4> REGA<1:0> +PWRI( 0x83C , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 0 7.5 dBm +PWRI( 0x83F , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 1 8 dBm +PWRI( 0x843 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 2 8.5 dBm +PWRI( 0x847 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 3 9 dBm +PWRI( 0x84B , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 4 9.5 dBm +PWRI( 0x84F , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 5 10 dBm +PWRI( 0x854 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 6 10.5 dBm +PWRI( 0x859 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 7 11 dBm +PWRI( 0x85E , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 8 11.5 dBm +PWRI( 0x864 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 9 12 dBm +PWRI( 0x86A , 0xA, 7, 4, 3, 0x20, 0x0, 0x2 ), // 10 12.5 dBm +PWRI( 0x870 , 0xA, 7, 4, 3, 0x20, 0x0, 0x2 ), // 11 13 dBm +PWRI( 0x877 , 0xA, 7, 4, 3, 0x20, 0x0, 0x2 ), // 12 13.5 dBm +PWRI( 0x87E , 0xA, 7, 4, 3, 0x20, 0x0, 0x2 ), // 13 14 dBm +PWRI( 0x885 , 0xA, 7, 4, 3, 0x20, 0x0, 0x2 ), // 14 14.5 dBm +PWRI( 0x88D , 0xA, 7, 4, 3, 0x20, 0x0, 0x2 ), // 15 15 dBm +PWRI( 0x896 , 0xA, 7, 5, 5, 0x20, 0x0, 0x2 ), // 16 15.5 dBm +PWRI( 0x89F , 0xA, 7, 5, 5, 0x20, 0x0, 0x2 ), // 17 16 dBm +PWRI( 0x8A8 , 0xA, 7, 5, 5, 0x20, 0x0, 0x2 ), // 18 16.5 dBm +PWRI( 0x8B2 , 0xA, 7, 5, 5, 0x20, 0x0, 0x2 ), // 19 17 dBm +PWRI( 0x8BC , 0xA, 7, 5, 5, 0x20, 0x0, 0x2 ), // 20 17.5 dBm +PWRI( 0x8C8 , 0xA, 7, 5, 5, 0x20, 0x0, 0x2 ), // 21 18 dBm +PWRI( 0x8D3 , 0xA, 7, 5, 5, 0x20, 0x0, 0x2 ), // 22 18.5 dBm +PWRI( 0x8E0 , 0xA, 7, 5, 5, 0x20, 0x0, 0x2 ), // 23 19 dBm +PWRI( 0x8ED , 0xA, 7, 5, 5, 0x20, 0x0, 0x2 ), // 24 19.5 dBm +PWRI( 0x8FB , 0xA, 7, 5, 5, 0x20, 0x0, 0x2 ), // 25 20 dBm +PWRI( 0x90A , 0xA, 7, 5, 5, 0x20, 0x0, 0x2 ), // 26 20.5 dBm +PWRI( 0x91A , 0xA, 7, 5, 5, 0x20, 0x0, 0x2 ), // 27 21 dBm +PWRI( 0x92B , 0xA, 7, 5, 5, 0x20, 0x0, 0x2 ), // 28 21.5 dBm +PWRI( 0x93C , 0xA, 7, 5, 5, 0x20, 0x0, 0x2 ), // 29 22 dBm +PWRI( 0x94F , 0xA, 7, 6, 5, 0x20, 0x0, 0x2 ), // 30 22.5 dBm +PWRI( 0x963 , 0xA, 7, 6, 6, 0x20, 0x0, 0x2 ), // 31 23 dBm +PWRI( 0x978 , 0xA, 7, 4, 4, 0x20, 0x1, 0x1 ), // 32 23.5 dBm +PWRI( 0x98E , 0xA, 7, 4, 4, 0x20, 0x1, 0x1 ), // 33 24 dBm +PWRI( 0x9A6 , 0xA, 7, 5, 4, 0x20, 0x1, 0x1 ), // 34 24.5 dBm +PWRI( 0x9BF , 0xA, 7, 5, 4, 0x20, 0x1, 0x1 ), // 35 25 dBm +PWRI( 0x9D9 , 0xA, 7, 5, 4, 0x20, 0x1, 0x1 ), // 36 25.5 dBm +PWRI( 0x9F5 , 0xA, 7, 5, 4, 0x20, 0x1, 0x1 ), // 37 26 dBm +PWRI( 0xA13 , 0xA, 7, 5, 5, 0x20, 0x1, 0x1 ), // 38 26.5 dBm +PWRI( 0xA33 , 0xA, 7, 5, 5, 0x20, 0x1, 0x1 ), // 39 27 dBm +PWRI( 0xA54 , 0xA, 7, 5, 5, 0x20, 0x1, 0x1 ), // 40 27.5 dBm +PWRI( 0xA77 , 0xA, 7, 5, 5, 0x20, 0x1, 0x1 ), // 41 28 dBm +PWRI( 0xA9D , 0xA, 7, 5, 5, 0x20, 0x1, 0x1 ), // 42 28.5 dBm +PWRI( 0xAC4 , 0xA, 7, 5, 5, 0x20, 0x1, 0x1 ), // 43 29 dBm +PWRI( 0xAEE , 0xA, 7, 5, 5, 0x20, 0x1, 0x1 ), // 44 29.5 dBm +PWRI( 0xB1B , 0xA, 7, 5, 5, 0x20, 0x1, 0x1 ), // 45 30 dBm +PWRI( 0xB4A , 0xA, 7, 5, 5, 0x20, 0x1, 0x1 ), // 46 30.5 dBm +PWRI( 0xB7C , 0xA, 7, 5, 5, 0x20, 0x1, 0x1 ), // 47 31 dBm +}; + +#define PWR_GAIN_BASE_G (0xE0AB1000) +#define TCP_PAMAP_TAB_G_LEN (80) +const static PWR_REGS cfg_tab_g[TCP_PAMAP_TAB_G_LEN] = { + // pregain REGB<31:28> REGC<10:8> REGC<6:4> REGC<2:0> REGA<13:8> REGA<7:4> REGA<1:0> +PWRI( 0x85E , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 0 2.5 dBm +PWRI( 0x860 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 1 2.75 dBm +PWRI( 0x863 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 2 3 dBm +PWRI( 0x866 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 3 3.25 dBm +PWRI( 0x869 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 4 3.5 dBm +PWRI( 0x86C , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 5 3.75 dBm +PWRI( 0x86F , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 6 4 dBm +PWRI( 0x873 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 7 4.25 dBm +PWRI( 0x876 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 8 4.5 dBm +PWRI( 0x879 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 9 4.75 dBm +PWRI( 0x87D , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 10 5 dBm +PWRI( 0x881 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 11 5.25 dBm +PWRI( 0x884 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 12 5.5 dBm +PWRI( 0x888 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 13 5.75 dBm +PWRI( 0x88C , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 14 6 dBm +PWRI( 0x890 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 15 6.25 dBm +PWRI( 0x895 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 16 6.5 dBm +PWRI( 0x899 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 17 6.75 dBm +PWRI( 0x89D , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 18 7 dBm +PWRI( 0x8A2 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 19 7.25 dBm +PWRI( 0x8A7 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 20 7.5 dBm +PWRI( 0x8AC , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 21 7.75 dBm +PWRI( 0x8B1 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 22 8 dBm +PWRI( 0x8B6 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 23 8.25 dBm +PWRI( 0x8BB , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 24 8.5 dBm +PWRI( 0x8C0 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 25 8.75 dBm +PWRI( 0x8C6 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 26 9 dBm +PWRI( 0x8CC , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 27 9.25 dBm +PWRI( 0x8D2 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 28 9.5 dBm +PWRI( 0x8D8 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 29 9.75 dBm +PWRI( 0x8DE , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 30 10 dBm +PWRI( 0x8E5 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 31 10.25 dBm +PWRI( 0x8EB , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 32 10.5 dBm +PWRI( 0x8F2 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 33 10.75 dBm +PWRI( 0x8F9 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 34 11 dBm + +PWRI( 0x901 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 35 11.25 dBm +PWRI( 0x908 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 36 11.5 dBm +PWRI( 0x910 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 37 11.75 dBm +PWRI( 0x918 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 38 12 dBm +PWRI( 0x920 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 39 12.25 dBm +PWRI( 0x928 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 40 12.5 dBm +PWRI( 0x931 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 41 12.75 dBm +PWRI( 0x93A , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 42 13 dBm +PWRI( 0x943 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 43 13.25 dBm +PWRI( 0x94D , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 44 13.5 dBm +PWRI( 0x956 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 45 13.75 dBm +PWRI( 0x960 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 46 14 dBm +PWRI( 0x96B , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 47 14.25 dBm +PWRI( 0x975 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 48 14.5 dBm +PWRI( 0x980 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 49 14.75 dBm +PWRI( 0x98B , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 50 15 dBm +PWRI( 0x997 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 51 15.25 dBm +PWRI( 0x9A3 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 52 15.5 dBm +PWRI( 0x9AF , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 53 15.75 dBm +PWRI( 0x9BB , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 54 16 dBm +PWRI( 0x9C8 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 55 16.25 dBm +PWRI( 0x9D6 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 56 16.5 dBm +PWRI( 0x9E0 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 57 16.75 dBm +PWRI( 0x9F2 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 58 17 dBm +PWRI( 0xA00 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 59 17.25 dBm +PWRI( 0xA0F , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 60 17.5 dBm +PWRI( 0xA1E , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 61 17.75 dBm +PWRI( 0xA2E , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 62 18 dBm +PWRI( 0xA3F , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 63 18.25 dBm +PWRI( 0xA4F , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 64 18.5 dBm +PWRI( 0xA61 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 65 18.75 dBm +PWRI( 0xA72 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 66 19 dBm +PWRI( 0xA85 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 67 19.25 dBm +PWRI( 0xA98 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 68 19.5 dBm +PWRI( 0xAAB , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 69 19.75 dBm +PWRI( 0xABF , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 70 20 dBm +PWRI( 0xAD3 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 71 20.25 dBm +PWRI( 0xAE9 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 72 20.5 dBm +PWRI( 0xAFE , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 73 20.75 dBm +PWRI( 0xB15 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 74 21 dBm +PWRI( 0xB2C , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 75 21.25 dBm +PWRI( 0xB43 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 76 21.5 dBm +PWRI( 0xB5C , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 77 21.75 dBm +PWRI( 0xB75 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 78 22 dBm +PWRI( 0xB8F , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 79 22.25 dBm +}; + +#define PWR_GAIN_BASE_BLE (0xE12B1000) +#define TCP_PAMAP_TAB_BLE_LEN (80) +const static PWR_REGS cfg_tab_ble[TCP_PAMAP_TAB_BLE_LEN] = +{ + // pregain REGB<31:28> REGC<10:8> REGC<6:4> REGC<2:0> REGA<13:8> REGA<7:4> REGA<1:0> +PWRI( 0x80B , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 0 -7.5 dBm +PWRI( 0x81F , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 1 21 dBm +PWRI( 0x820 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 2 21.25 dBm +PWRI( 0x821 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 3 21.5 dBm +PWRI( 0x822 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 4 21.75 dBm +PWRI( 0x823 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 5 22 dBm +PWRI( 0x824 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 6 2.5 dBm +PWRI( 0x825 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 7 2.75 dBm +PWRI( 0x826 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 8 3 dBm +PWRI( 0x828 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 9 3.25 dBm +PWRI( 0x829 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 10 3.5 dBm +PWRI( 0x82A , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 11 3.75 dBm +PWRI( 0x82B , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 12 4 dBm +PWRI( 0x82C , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 13 4.25 dBm +PWRI( 0x82E , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 14 4.5 dBm +PWRI( 0x82F , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 15 4.75 dBm +PWRI( 0x830 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 16 5 dBm +PWRI( 0x832 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 17 5.25 dBm +PWRI( 0x833 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 18 5.5 dBm +PWRI( 0x835 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 19 5.75 dBm +PWRI( 0x836 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 20 6 dBm +PWRI( 0x838 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 21 6.25 dBm +PWRI( 0x839 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 22 6.5 dBm +PWRI( 0x83B , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 23 6.75 dBm +PWRI( 0x83D , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 24 7 dBm +PWRI( 0x83F , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 25 7.25 dBm +PWRI( 0x840 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 26 7.5 dBm +PWRI( 0x842 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 27 7.75 dBm +PWRI( 0x844 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 28 8 dBm +PWRI( 0x846 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 29 8.25 dBm +PWRI( 0x848 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 30 8.5 dBm +PWRI( 0x84A , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 31 8.75 dBm +PWRI( 0x84D , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 32 9 dBm +PWRI( 0x84F , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 33 9.25 dBm +PWRI( 0x851 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 34 9.5 dBm +PWRI( 0x854 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 35 9.75 dBm +PWRI( 0x856 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 36 10 dBm +PWRI( 0x858 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 37 10.25 dBm +PWRI( 0x85B , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 38 10.5 dBm +PWRI( 0x85E , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 39 10.75 dBm +PWRI( 0x860 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 40 11 dBm +PWRI( 0x863 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 41 11.25 dBm +PWRI( 0x866 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 42 11.5 dBm +PWRI( 0x869 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 43 11.75 dBm +PWRI( 0x86C , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 44 12 dBm +PWRI( 0x86F , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 45 12.25 dBm +PWRI( 0x873 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 46 12.5 dBm +PWRI( 0x876 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 47 12.75 dBm +PWRI( 0x879 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 48 13 dBm +PWRI( 0x87D , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 49 13.25 dBm +PWRI( 0x881 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 50 13.5 dBm +PWRI( 0x884 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 51 13.75 dBm +PWRI( 0x888 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 52 14 dBm +PWRI( 0x88C , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 53 14.25 dBm +PWRI( 0x890 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 54 14.5 dBm +PWRI( 0x895 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 55 14.75 dBm +PWRI( 0x899 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 56 15 dBm +PWRI( 0x89D , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 57 15.25 dBm +PWRI( 0x8A2 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 58 15.5 dBm +PWRI( 0x8A7 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 59 15.75 dBm +PWRI( 0x8AC , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 60 16 dBm +PWRI( 0x8B1 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 61 16.25 dBm +PWRI( 0x8B6 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 62 16.5 dBm +PWRI( 0x8BB , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 63 16.75 dBm +PWRI( 0x8C0 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 64 17 dBm +PWRI( 0x8C6 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 65 17.25 dBm +PWRI( 0x8CC , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 66 17.5 dBm +PWRI( 0x8D2 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 67 17.75 dBm +PWRI( 0x8D8 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 68 18 dBm +PWRI( 0x8DE , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 69 18.25 dBm +PWRI( 0x8E5 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 70 18.5 dBm +PWRI( 0x8EB , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 71 18.75 dBm +PWRI( 0x8F2 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 72 19 dBm +PWRI( 0x8F9 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 73 19.25 dBm +PWRI( 0x901 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 74 19.5 dBm +PWRI( 0x908 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 75 19.75 dBm +PWRI( 0x910 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 76 20 dBm +PWRI( 0x918 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 77 20.25 dBm +PWRI( 0x920 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 78 20.5 dBm +PWRI( 0x928 , 0xA, 7, 3, 2, 0x20, 0x0, 0x2 ), // 79 20.75 dBm +}; + +#define TCP_PAMAP_TAB_LEN (TCP_PAMAP_TAB_B_LEN+TCP_PAMAP_TAB_G_LEN) + +const struct BK7011RCBEKEN_TypeDef BK7231N_RC_REG = +{ + (volatile BK7011_RC_BEKEN_REG0x0_TypeDef *) (RC_BEKEN_BASE + 0 * 4), + (volatile BK7011_RC_BEKEN_REG0x1_TypeDef *) (RC_BEKEN_BASE + 1 * 4), + (volatile BK7011_RC_BEKEN_REG0x5_TypeDef *) (RC_BEKEN_BASE + 5 * 4), + (volatile BK7011_RC_BEKEN_REG0x8_TypeDef *) (RC_BEKEN_BASE + 8 * 4), + (volatile BK7011_RC_BEKEN_REG0xB_TypeDef *) (RC_BEKEN_BASE + 11 * 4), + (volatile BK7011_RC_BEKEN_REG0xE_TypeDef *) (RC_BEKEN_BASE + 14 * 4), + (volatile BK7011_RC_BEKEN_REG0x11_TypeDef *)(RC_BEKEN_BASE + 17 * 4), + (volatile BK7011_RC_BEKEN_REG0x19_TypeDef *)(RC_BEKEN_BASE + 25 * 4), + (volatile BK7011_RC_BEKEN_REG0x1A_TypeDef *)(RC_BEKEN_BASE + 0x1A * 4), + (volatile BK7011_RC_BEKEN_REG0x1C_TypeDef *)(RC_BEKEN_BASE + 28 * 4), + (volatile BK7011_RC_BEKEN_REG0x1E_TypeDef *)(RC_BEKEN_BASE + 30 * 4), + (volatile BK7011_RC_BEKEN_REG0x3C_TypeDef *)(RC_BEKEN_BASE + 60 * 4), + (volatile BK7011_RC_BEKEN_REG0x3E_TypeDef *)(RC_BEKEN_BASE + 62 * 4), + (volatile BK7011_RC_BEKEN_REG0x3F_TypeDef *)(RC_BEKEN_BASE + 63 * 4), + (volatile BK7011_RC_BEKEN_REG0x40_TypeDef *)(RC_BEKEN_BASE + 64 * 4), + (volatile BK7011_RC_BEKEN_REG0x41_TypeDef *)(RC_BEKEN_BASE + 65 * 4), + (volatile BK7011_RC_BEKEN_REG0x42_TypeDef *)(RC_BEKEN_BASE + 66 * 4), + (volatile BK7011_RC_BEKEN_REG0x43_TypeDef *)(RC_BEKEN_BASE + 0x43 * 4), + (volatile BK7011_RC_BEKEN_REG0x4C_TypeDef *)(RC_BEKEN_BASE + 76 * 4), + (volatile BK7011_RC_BEKEN_REG0x4D_TypeDef *)(RC_BEKEN_BASE + 77 * 4), + (volatile BK7011_RC_BEKEN_REG0x4E_TypeDef *)(RC_BEKEN_BASE + 78 * 4), + (volatile BK7011_RC_BEKEN_REG0x4F_TypeDef *)(RC_BEKEN_BASE + 79 * 4), + (volatile BK7011_RC_BEKEN_REG0x50_TypeDef *)(RC_BEKEN_BASE + 80 * 4), + (volatile BK7011_RC_BEKEN_REG0x51_TypeDef *)(RC_BEKEN_BASE + 81 * 4), + (volatile BK7011_RC_BEKEN_REG0x52_TypeDef *)(RC_BEKEN_BASE + 82 * 4), + (volatile BK7011_RC_BEKEN_REG0x54_TypeDef *)(RC_BEKEN_BASE + 84 * 4), + (volatile BK7011_RC_BEKEN_REG0x55_TypeDef *)(RC_BEKEN_BASE + 85 * 4), + (volatile BK7011_RC_BEKEN_REG0x56_TypeDef *)(RC_BEKEN_BASE + 0x56 * 4), + (volatile BK7011_RC_BEKEN_REG0x57_TypeDef *)(RC_BEKEN_BASE + 0x57 * 4), + (volatile BK7011_RC_BEKEN_REG0x5A_TypeDef *)(RC_BEKEN_BASE + 90 * 4), + (volatile BK7011_RC_BEKEN_REG0x5B_TypeDef *)(RC_BEKEN_BASE + 91 * 4), + (volatile BK7011_RC_BEKEN_REG0x5C_TypeDef *)(RC_BEKEN_BASE + 92 * 4), + (volatile BK7011_RC_BEKEN_REG0x6A_TypeDef *)(RC_BEKEN_BASE + 106 * 4), +}; + +const struct BK7231N_TRX_REG_TypeDef BK7231N_TRX_REG = +{ + (volatile BK7011_TRxV2A_REG0x0_TypeDef *) (TRX_BEKEN_BASE + 0 * 4), + (volatile BK7011_TRxV2A_REG0x1_TypeDef *) (TRX_BEKEN_BASE + 1 * 4), + (volatile BK7011_TRxV2A_REG0x2_TypeDef *) (TRX_BEKEN_BASE + 2 * 4), + (volatile BK7011_TRxV2A_REG0x3_TypeDef *) (TRX_BEKEN_BASE + 3 * 4), + (volatile BK7011_TRxV2A_REG0x4_TypeDef *) (TRX_BEKEN_BASE + 4 * 4), + (volatile BK7011_TRxV2A_REG0x5_TypeDef *) (TRX_BEKEN_BASE + 5 * 4), + (volatile BK7011_TRxV2A_REG0x6_TypeDef *) (TRX_BEKEN_BASE + 6 * 4), + (volatile BK7011_TRxV2A_REG0x7_TypeDef *) (TRX_BEKEN_BASE + 7 * 4), + (volatile BK7011_TRxV2A_REG0x8_TypeDef *) (TRX_BEKEN_BASE + 8 * 4), + (volatile BK7011_TRxV2A_REG0x9_TypeDef *) (TRX_BEKEN_BASE + 9 * 4), + (volatile BK7011_TRxV2A_REG0xA_TypeDef *) (TRX_BEKEN_BASE + 10 * 4), + (volatile BK7011_TRxV2A_REG0xB_TypeDef *) (TRX_BEKEN_BASE + 11 * 4), + (volatile BK7011_TRxV2A_REG0xC_TypeDef *) (TRX_BEKEN_BASE + 12 * 4), + (volatile BK7011_TRxV2A_REG0xD_TypeDef *) (TRX_BEKEN_BASE + 13 * 4), + (volatile BK7011_TRxV2A_REG0xE_TypeDef *) (TRX_BEKEN_BASE + 14 * 4), + (volatile BK7011_TRxV2A_REG0xF_TypeDef *) (TRX_BEKEN_BASE + 15 * 4), + (volatile BK7011_TRxV2A_REG0x10_TypeDef *)(TRX_BEKEN_BASE + 16 * 4), + (volatile BK7011_TRxV2A_REG0x11_TypeDef *)(TRX_BEKEN_BASE + 17 * 4), + (volatile BK7011_TRxV2A_REG0x12_TypeDef *)(TRX_BEKEN_BASE + 18 * 4), + (volatile BK7011_TRxV2A_REG0x13_TypeDef *)(TRX_BEKEN_BASE + 19 * 4), + (volatile BK7011_TRxV2A_REG0x14_TypeDef *)(TRX_BEKEN_BASE + 20 * 4), + (volatile BK7011_TRxV2A_REG0x15_TypeDef *)(TRX_BEKEN_BASE + 21 * 4), + (volatile BK7011_TRxV2A_REG0x16_TypeDef *)(TRX_BEKEN_BASE + 22 * 4), + (volatile BK7011_TRxV2A_REG0x17_TypeDef *)(TRX_BEKEN_BASE + 23 * 4), + (volatile BK7011_TRxV2A_REG0x18_TypeDef *)(TRX_BEKEN_BASE + 24 * 4), + (volatile BK7011_TRxV2A_REG0x19_TypeDef *)(TRX_BEKEN_BASE + 25 * 4), + (volatile BK7011_TRxV2A_REG0x1A_TypeDef *)(TRX_BEKEN_BASE + 26 * 4), + (volatile BK7011_TRxV2A_REG0x1B_TypeDef *)(TRX_BEKEN_BASE + 27 * 4), + (volatile BK7011_TRxV2A_REG0x1C_TypeDef *)(TRX_BEKEN_BASE + 28 * 4), +}; + +struct temp_cal_pwr_st g_temp_pwr_current = {16, EVM_DEFUALT_RATE, 0, 0}; + +void delay05us(INT32 num) +{ + volatile INT32 i, j; + + for(i = 0; i < num; i ++) + { + for(j = 0; j < 5; j ++) + ; + } +} + +void delay100us(INT32 num) +{ + volatile INT32 i, j; + + for(i = 0; i < num; i ++) + { + for(j = 0; j < 1050; j ++) + ; + } +} + +#if 0 +#define CAL_WR_TRXREGS(reg) do{\ + CHECK_OPERATE_RF_REG_IF_IN_SLEEP();\ + while(BK7231N_RC_REG.REG0x1->value & (0x1 << reg));\ + BK7231N_TRX_REG.REG##reg->value = BK7231N_TRX_RAM.REG##reg.value;\ + cal_delay(6);\ + while(BK7231N_RC_REG.REG0x1->value & (0x1 << reg));\ + CHECK_OPERATE_RF_REG_IF_IN_SLEEP_END();\ + }while(0) +#else +void CAL_WR_TRXREGS(int reg) +{ + uint32_t *trx_reg_ptr = ((uint32_t **)&BK7231N_TRX_REG)[reg]; + uint32_t trx_ram_value = ((uint32_t *)&BK7231N_TRX_RAM)[reg]; + + CHECK_OPERATE_RF_REG_IF_IN_SLEEP(); + while(BK7231N_RC_REG.REG0x1->value & (0x1 << reg)); + *trx_reg_ptr = trx_ram_value; + cal_delay(6); + while(BK7231N_RC_REG.REG0x1->value & (0x1 << reg)); + CHECK_OPERATE_RF_REG_IF_IN_SLEEP_END(); +} +#endif + +void rwnx_cal_load_default_result(void) +{ + //gtx_dcorMod = BK7231N_TRX_RAM.REG0xB.bits.padCa; //changed + //gtx_dcorPA = BK7231N_TRX_RAM.REG0xC.bits.Rgm; //changed + // gtx_pre_gain = BK7231N_RC_RAM.REG0x52.bits.Reserved_; //changed + + gcali_result.gtx_i_dc_comp = BK7231N_RC_RAM.REG0x4F.bits.TXIDCCOMP; + gcali_result.gtx_q_dc_comp = BK7231N_RC_RAM.REG0x4F.bits.TXQDCCOMP; + + gcali_result.gtx_i_gain_comp = BK7231N_RC_RAM.REG0x50.bits.TXIGAINCOMP; + gcali_result.gtx_q_gain_comp = BK7231N_RC_RAM.REG0x50.bits.TXQGAINCOMP; + + //gcali_result.gtx_ifilter_corner = BK7231N_TRX_RAM.REG0x6.bits.lpfcapcali50; + //gcali_result.gtx_ifilter_corner += BK7231N_TRX_RAM.REG0x7.bits.lpfcapcali << 6; + //gcali_result.gtx_qfilter_corner = BK7231N_TRX_RAM.REG0x6.bits.lpfcapcalq50; + //gcali_result.gtx_qfilter_corner += BK7231N_TRX_RAM.REG0x7.bits.lpfcapcalq << 6; + gcali_result.gtx_phase_comp = BK7231N_RC_RAM.REG0x51.bits.TXPHASECOMP; + gcali_result.gtx_phase_ty2 = BK7231N_RC_RAM.REG0x51.bits.TXTY2; + + gcali_result.g_rx_dc_gain_tab[0] = BK7231N_TRX_RAM.REG0x14.value; + gcali_result.g_rx_dc_gain_tab[1] = BK7231N_TRX_RAM.REG0x15.value; + gcali_result.g_rx_dc_gain_tab[2] = BK7231N_TRX_RAM.REG0x16.value; + gcali_result.g_rx_dc_gain_tab[3] = BK7231N_TRX_RAM.REG0x17.value; + gcali_result.g_rx_dc_gain_tab[4] = BK7231N_TRX_RAM.REG0x18.value; + gcali_result.g_rx_dc_gain_tab[5] = BK7231N_TRX_RAM.REG0x19.value; + gcali_result.g_rx_dc_gain_tab[6] = BK7231N_TRX_RAM.REG0x1A.value; + gcali_result.g_rx_dc_gain_tab[7] = BK7231N_TRX_RAM.REG0x1B.value; + + gcali_result.grx_amp_err_wr = BK7231N_RC_RAM.REG0x42.bits.RXAMPERRWR; + gcali_result.grx_phase_err_wr = BK7231N_RC_RAM.REG0x42.bits.RXPHASEERRWR; + + //gstat_cal = (BK7231N_RC_RAM[16] >> 29) & 0x1; +} + +void rwnx_cal_read_current_cal_result(BK7011_CALI_RESULT *cali_result) +{ + memcpy(cali_result, &gcali_result, sizeof(gcali_result)); +} + +void calibration_print_result() +{ + CAL_FATAL("*********** finally result 7231N **********\r\n"); + CAL_FATAL("gbias_after_cal: 0x%x\r\n", gcali_result.gbias_after_cal); + CAL_FATAL("gav_tssi: 0x%x\r\n", gcali_result.gav_tssi); + CAL_FATAL("gtx_q_dc_comp:0x%x\r\n", gcali_result.gtx_q_dc_comp); + CAL_FATAL("gtx_i_dc_comp:0x%x\r\n", gcali_result.gtx_i_dc_comp); + CAL_FATAL("gtx_i_gain_comp:0x%x\r\n", gcali_result.gtx_i_gain_comp); + CAL_FATAL("gtx_q_gain_comp:0x%x\r\n", gcali_result.gtx_q_gain_comp); + CAL_FATAL("gtx_phase_comp:0x%x\r\n", gcali_result.gtx_phase_comp); + CAL_FATAL("gtx_phase_ty2:0x%x\r\n", gcali_result.gtx_phase_ty2); + CAL_FATAL("gtx_ifilter_corner over: 0x%x\r\n", gcali_result.gtx_ifilter_corner); + CAL_FATAL("gtx_qfilter_corner over: 0x%x\r\n", gcali_result.gtx_qfilter_corner); + CAL_FATAL("const_iqcal_p over: 0x%x\r\n", gcali_result.const_iqcal_p); + CAL_FATAL("gtx_dcorMod:0x%x, gtx_dcorPA:0x%x\r\n", gtx_dcorMod, gtx_dcorPA); + CAL_FATAL("gtx_pre_gain:0x%x\r\n", gtx_pre_gain); + CAL_FATAL("g_rx_dc_gain_tab 0 over: 0x%x\r\n", gcali_result.g_rx_dc_gain_tab[0]); + CAL_FATAL("g_rx_dc_gain_tab 1 over: 0x%x\r\n", gcali_result.g_rx_dc_gain_tab[1]); + CAL_FATAL("g_rx_dc_gain_tab 2 over: 0x%x\r\n", gcali_result.g_rx_dc_gain_tab[2]); + CAL_FATAL("g_rx_dc_gain_tab 3 over: 0x%x\r\n", gcali_result.g_rx_dc_gain_tab[3]); + CAL_FATAL("g_rx_dc_gain_tab 4 over: 0x%x\r\n", gcali_result.g_rx_dc_gain_tab[4]); + CAL_FATAL("g_rx_dc_gain_tab 5 over: 0x%x\r\n", gcali_result.g_rx_dc_gain_tab[5]); + CAL_FATAL("g_rx_dc_gain_tab 6 over: 0x%x\r\n", gcali_result.g_rx_dc_gain_tab[6]); + CAL_FATAL("g_rx_dc_gain_tab 7 over: 0x%x\r\n", gcali_result.g_rx_dc_gain_tab[7]); + + CAL_FATAL("grx_amp_err_wr:0x%03x\r\n", gcali_result.grx_amp_err_wr); + CAL_FATAL("grx_phase_err_wr:0x%03x\r\n", gcali_result.grx_phase_err_wr); + CAL_FATAL("**************************************\r\n"); +} + +void calibration_print_results(BK7011_CALI_RESULT *cali_result, int calibrate_time) +{ + int i, j; + int tx_filter_corner_max, tx_filter_corner_min; + int tx_filter_corner; + BK7011_CALI_RESULT max; + BK7011_CALI_RESULT min; + + os_printf("gtx_dcorMod_temp: 0x%x\r\n", gtx_dcorMod_temp); + os_printf("gtx_dcorPA_temp: 0x%x\r\n", gtx_dcorPA_temp); + os_printf("gtx_pre_gain_temp: 0x%x\r\n", gtx_pre_gain_temp); + + tx_filter_corner_max = -1100 * BK_TX_DAC_COEF; + tx_filter_corner_min = 1100 * BK_TX_DAC_COEF; + + max.gbias_after_cal = -1100 * BK_TX_DAC_COEF; + min.gbias_after_cal = 1100 * BK_TX_DAC_COEF; + max.gav_tssi = -1100 * BK_TX_DAC_COEF; + min.gav_tssi = 1100 * BK_TX_DAC_COEF; + max.gtx_ifilter_corner = -1100 * BK_TX_DAC_COEF; + min.gtx_ifilter_corner = 1100 * BK_TX_DAC_COEF; + max.gtx_qfilter_corner = -1100 * BK_TX_DAC_COEF; + min.gtx_qfilter_corner = 1100 * BK_TX_DAC_COEF; + max.gtx_i_dc_comp = -1100 * BK_TX_DAC_COEF; + min.gtx_i_dc_comp = 1100 * BK_TX_DAC_COEF; + max.gtx_q_dc_comp = -1100 * BK_TX_DAC_COEF; + min.gtx_q_dc_comp = 1100 * BK_TX_DAC_COEF; + max.gtx_i_gain_comp = -1100 * BK_TX_DAC_COEF; + min.gtx_i_gain_comp = 1100 * BK_TX_DAC_COEF; + max.gtx_q_gain_comp = -1100 * BK_TX_DAC_COEF; + min.gtx_q_gain_comp = 1100 * BK_TX_DAC_COEF; + max.gtx_phase_comp = -1100 * BK_TX_DAC_COEF; + min.gtx_phase_comp = 1100 * BK_TX_DAC_COEF; + max.gtx_phase_ty2 = -1100 * BK_TX_DAC_COEF; + min.gtx_phase_ty2 = 1100 * BK_TX_DAC_COEF; + max.gtx_i_dc_comp_loopback = -1100 * BK_TX_DAC_COEF; + min.gtx_i_dc_comp_loopback = 1100 * BK_TX_DAC_COEF; + max.gtx_q_dc_comp_loopback = -1100 * BK_TX_DAC_COEF; + min.gtx_q_dc_comp_loopback = 1100 * BK_TX_DAC_COEF; + max.gtx_i_gain_comp_loopback = -1100 * BK_TX_DAC_COEF; + min.gtx_i_gain_comp_loopback = 1100 * BK_TX_DAC_COEF; + max.gtx_q_gain_comp_loopback = -1100 * BK_TX_DAC_COEF; + min.gtx_q_gain_comp_loopback = 1100 * BK_TX_DAC_COEF; + max.gtx_phase_comp_loopback = -1100 * BK_TX_DAC_COEF; + min.gtx_phase_comp_loopback = 1100 * BK_TX_DAC_COEF; + max.gtx_phase_ty2_loopback = -1100 * BK_TX_DAC_COEF; + min.gtx_phase_ty2_loopback = 1100 * BK_TX_DAC_COEF; + max.rx_amp_err_rd = -1100 * BK_TX_DAC_COEF; + min.rx_amp_err_rd = 1100 * BK_TX_DAC_COEF; + max.rx_phase_err_rd = -1100 * BK_TX_DAC_COEF; + min.rx_phase_err_rd = 1100 * BK_TX_DAC_COEF; + max.rx_ty2_rd = -1100 * BK_TX_DAC_COEF; + min.rx_ty2_rd = 1100 * BK_TX_DAC_COEF; + + for (i = 0; i < calibrate_time; i++) + { + //bias_after_cal: + if (max.gbias_after_cal < cali_result[i].gbias_after_cal) + { + max.gbias_after_cal = cali_result[i].gbias_after_cal; + } + if (min.gbias_after_cal > cali_result[i].gbias_after_cal) + { + min.gbias_after_cal = cali_result[i].gbias_after_cal; + } + + //av_tssi: + if (max.gav_tssi < cali_result[i].gav_tssi) + { + max.gav_tssi = cali_result[i].gav_tssi; + } + if (min.gav_tssi > cali_result[i].gav_tssi) + { + min.gav_tssi = cali_result[i].gav_tssi; + } + + //tx_ifilter_corner: + if (max.gtx_ifilter_corner < cali_result[i].gtx_ifilter_corner) + { + max.gtx_ifilter_corner = cali_result[i].gtx_ifilter_corner; + } + if (min.gtx_ifilter_corner > cali_result[i].gtx_ifilter_corner) + { + min.gtx_ifilter_corner = cali_result[i].gtx_ifilter_corner; + } + + //gtx_qfilter_corner: + if (max.gtx_qfilter_corner < cali_result[i].gtx_qfilter_corner) + { + max.gtx_qfilter_corner = cali_result[i].gtx_qfilter_corner; + } + if (min.gtx_qfilter_corner > cali_result[i].gtx_qfilter_corner) + { + min.gtx_qfilter_corner = cali_result[i].gtx_qfilter_corner; + } + + tx_filter_corner = cali_result[i].gtx_ifilter_corner - cali_result[i].gtx_qfilter_corner; + if (tx_filter_corner_max < tx_filter_corner) + { + tx_filter_corner_max = tx_filter_corner; + } + if (tx_filter_corner_min > tx_filter_corner) + { + tx_filter_corner_min = tx_filter_corner; + } + + //tx_i_dc_comp: + if (max.gtx_i_dc_comp < cali_result[i].gtx_i_dc_comp) + { + max.gtx_i_dc_comp = cali_result[i].gtx_i_dc_comp; + } + if (min.gtx_i_dc_comp > cali_result[i].gtx_i_dc_comp) + { + min.gtx_i_dc_comp = cali_result[i].gtx_i_dc_comp; + } + + //tx_q_dc_comp: + if (max.gtx_q_dc_comp < cali_result[i].gtx_q_dc_comp) + { + max.gtx_q_dc_comp = cali_result[i].gtx_q_dc_comp; + } + if (min.gtx_q_dc_comp > cali_result[i].gtx_q_dc_comp) + { + min.gtx_q_dc_comp = cali_result[i].gtx_q_dc_comp; + } + + //tx_i_gain_comp: + if (max.gtx_i_gain_comp < cali_result[i].gtx_i_gain_comp) + { + max.gtx_i_gain_comp = cali_result[i].gtx_i_gain_comp; + } + if (min.gtx_i_gain_comp > cali_result[i].gtx_i_gain_comp) + { + min.gtx_i_gain_comp = cali_result[i].gtx_i_gain_comp; + } + + //tx_q_gain_comp: + if (max.gtx_q_gain_comp < cali_result[i].gtx_q_gain_comp) + { + max.gtx_q_gain_comp = cali_result[i].gtx_q_gain_comp; + } + if (min.gtx_q_gain_comp > cali_result[i].gtx_q_gain_comp) + { + min.gtx_q_gain_comp = cali_result[i].gtx_q_gain_comp; + } + + //tx_phase_comp: + if (max.gtx_phase_comp < cali_result[i].gtx_phase_comp) + { + max.gtx_phase_comp = cali_result[i].gtx_phase_comp; + } + if (min.gtx_phase_comp > cali_result[i].gtx_phase_comp) + { + min.gtx_phase_comp = cali_result[i].gtx_phase_comp; + } + + //gtx_phase_ty2: + if (max.gtx_phase_ty2 < cali_result[i].gtx_phase_ty2) + { + max.gtx_phase_ty2 = cali_result[i].gtx_phase_ty2; + } + if (min.gtx_phase_ty2 > cali_result[i].gtx_phase_ty2) + { + min.gtx_phase_ty2 = cali_result[i].gtx_phase_ty2; + } + + //tx_i_dc_comp_temp: + if (max.gtx_i_dc_comp_loopback < cali_result[i].gtx_i_dc_comp_loopback) + { + max.gtx_i_dc_comp_loopback = cali_result[i].gtx_i_dc_comp_loopback; + } + if (min.gtx_i_dc_comp_loopback > cali_result[i].gtx_i_dc_comp_loopback) + { + min.gtx_i_dc_comp_loopback = cali_result[i].gtx_i_dc_comp_loopback; + } + + //tx_q_dc_comp_temp: + if (max.gtx_q_dc_comp_loopback < cali_result[i].gtx_q_dc_comp_loopback) + { + max.gtx_q_dc_comp_loopback = cali_result[i].gtx_q_dc_comp_loopback; + } + if (min.gtx_q_dc_comp_loopback > cali_result[i].gtx_q_dc_comp_loopback) + { + min.gtx_q_dc_comp_loopback = cali_result[i].gtx_q_dc_comp_loopback; + } + + //tx_i_gain_comp_temp: + if (max.gtx_i_gain_comp_loopback < cali_result[i].gtx_i_gain_comp_loopback) + { + max.gtx_i_gain_comp_loopback = cali_result[i].gtx_i_gain_comp_loopback; + } + if (min.gtx_i_gain_comp_loopback > cali_result[i].gtx_i_gain_comp_loopback) + { + min.gtx_i_gain_comp_loopback = cali_result[i].gtx_i_gain_comp_loopback; + } + + //tx_q_gain_comp_temp: + if (max.gtx_q_gain_comp_loopback < cali_result[i].gtx_q_gain_comp_loopback) + { + max.gtx_q_gain_comp_loopback = cali_result[i].gtx_q_gain_comp_loopback; + } + if (min.gtx_q_gain_comp_loopback > cali_result[i].gtx_q_gain_comp_loopback) + { + min.gtx_q_gain_comp_loopback = cali_result[i].gtx_q_gain_comp_loopback; + } + + //tx_phase_comp_temp: + if (max.gtx_phase_comp_loopback < cali_result[i].gtx_phase_comp_loopback) + { + max.gtx_phase_comp_loopback = cali_result[i].gtx_phase_comp_loopback; + } + if (min.gtx_phase_comp_loopback > cali_result[i].gtx_phase_comp_loopback) + { + min.gtx_phase_comp_loopback = cali_result[i].gtx_phase_comp_loopback; + } + + //tx_phase_ty2_temp: + if (max.gtx_phase_ty2_loopback < cali_result[i].gtx_phase_ty2_loopback) + { + max.gtx_phase_ty2_loopback = cali_result[i].gtx_phase_ty2_loopback; + } + if (min.gtx_phase_ty2_loopback > cali_result[i].gtx_phase_ty2_loopback) + { + min.gtx_phase_ty2_loopback = cali_result[i].gtx_phase_ty2_loopback; + } + + //rx_amp_err_rd: + if (max.rx_amp_err_rd < cali_result[i].rx_amp_err_rd) + { + max.rx_amp_err_rd = cali_result[i].rx_amp_err_rd; + } + if (min.rx_amp_err_rd > cali_result[i].rx_amp_err_rd) + { + min.rx_amp_err_rd = cali_result[i].rx_amp_err_rd; + } + + //rx_phase_err_rd: + if (max.rx_phase_err_rd < cali_result[i].rx_phase_err_rd) + { + max.rx_phase_err_rd = cali_result[i].rx_phase_err_rd; + } + if (min.rx_phase_err_rd > cali_result[i].rx_phase_err_rd) + { + min.rx_phase_err_rd = cali_result[i].rx_phase_err_rd; + } + + //rx_ty2_rd: + if (max.rx_ty2_rd < cali_result[i].rx_ty2_rd) + { + max.rx_ty2_rd = cali_result[i].rx_ty2_rd; + } + if (min.rx_ty2_rd > cali_result[i].rx_ty2_rd) + { + min.rx_ty2_rd = cali_result[i].rx_ty2_rd; + } + } + + + for (j = 0; j < 8; j++) + { + int iTemp; + os_printf("\r\n"); + + max.g_rx_dc_gain_tab[j] = -1100 * BK_TX_DAC_COEF; + min.g_rx_dc_gain_tab[j] = 1100 * BK_TX_DAC_COEF; + for (i = 0; i < calibrate_time; i++) + { + iTemp = cali_result[i].g_rx_dc_gain_tab[j]; + if (max.g_rx_dc_gain_tab[j] < (iTemp & 0x00FF)) + { + max.g_rx_dc_gain_tab[j] = iTemp & 0x00FF; + } + if (min.g_rx_dc_gain_tab[j] > (iTemp & 0x00FF)) + { + min.g_rx_dc_gain_tab[j] = iTemp & 0x00FF; + } + } + os_printf("g_rx_dc_gain_tab[%d].i_%ddb: min = %d, max = %d, max-min = %d\r\n", j, j * 6, min.g_rx_dc_gain_tab[j], max.g_rx_dc_gain_tab[j], max.g_rx_dc_gain_tab[j] - min.g_rx_dc_gain_tab[j]); + + max.g_rx_dc_gain_tab[j] = -1100 * BK_TX_DAC_COEF; + min.g_rx_dc_gain_tab[j] = 1100 * BK_TX_DAC_COEF; + for (i = 0; i < calibrate_time; i++) + { + iTemp = cali_result[i].g_rx_dc_gain_tab[j] >> 8; + if (max.g_rx_dc_gain_tab[j] < (iTemp & 0x00FF)) + { + max.g_rx_dc_gain_tab[j] = iTemp & 0x00FF; + } + if (min.g_rx_dc_gain_tab[j] > (iTemp & 0x00FF)) + { + min.g_rx_dc_gain_tab[j] = iTemp & 0x00FF; + } + } + + max.g_rx_dc_gain_tab[j] = -1100 * BK_TX_DAC_COEF; + min.g_rx_dc_gain_tab[j] = 1100 * BK_TX_DAC_COEF; + for (i = 0; i < calibrate_time; i++) + { + iTemp = cali_result[i].g_rx_dc_gain_tab[j] >> 16; + if (max.g_rx_dc_gain_tab[j] < (iTemp & 0x00FF)) + { + max.g_rx_dc_gain_tab[j] = iTemp & 0x00FF; + } + if (min.g_rx_dc_gain_tab[j] > (iTemp & 0x00FF)) + { + min.g_rx_dc_gain_tab[j] = iTemp & 0x00FF; + } + } + + max.g_rx_dc_gain_tab[j] = -1100 * BK_TX_DAC_COEF; + min.g_rx_dc_gain_tab[j] = 1100 * BK_TX_DAC_COEF; + for (i = 0; i < calibrate_time; i++) + { + iTemp = cali_result[i].g_rx_dc_gain_tab[j] >> 24; + if (max.g_rx_dc_gain_tab[j] < (iTemp & 0x00FF)) + { + max.g_rx_dc_gain_tab[j] = iTemp & 0x00FF; + } + if (min.g_rx_dc_gain_tab[j] > (iTemp & 0x00FF)) + { + min.g_rx_dc_gain_tab[j] = iTemp & 0x00FF; + } + } + } +} + +void calibration_auto_test(unsigned long ul_calibrate_times) +{ + BK7011_CALI_RESULT *cali_results; + uint32_t start, end; + int index; + + if (ul_calibrate_times == 0) + { + ul_calibrate_times = 100; + } + + cali_results = (BK7011_CALI_RESULT *)malloc(ul_calibrate_times * sizeof(BK7011_CALI_RESULT)); + if (NULL == cali_results) + { + CAL_FATAL("malloc(%d*sizeof(%d)) failed\r\n", ul_calibrate_times, sizeof(BK7011_CALI_RESULT)); + return; + } + + CAL_FATAL("\r\n***********************************************************************\r\n" + "calibration_auto_test: \r\n"); + start = rtos_get_time(); + for (index=0; index> 6) & 0x3; + BK7231N_TRX_RAM.REG0x6.bits.lpfcapcali50 = lpfcap_i & 0x3F; + BK7231N_TRX_RAM.REG0x7.bits.lpfcapcali = (lpfcap_i >> 6) & 0x3; + CAL_WR_TRXREGS(0x6); + CAL_WR_TRXREGS(0x7); + CAL_TIM_PRT("[%d]v=0x%x,0x%x ram=0x%x,0x%x reg=0x%x,0x%x\n", __LINE__, lpfcap_i, lpfcap_q, BK7231N_TRX_RAM.REG0x6.bits.lpfcapcali50, BK7231N_TRX_RAM.REG0x6.bits.lpfcapcalq50, BK7231N_TRX_REG.REG0x6->bits.lpfcapcali50, BK7231N_TRX_REG.REG0x6->bits.lpfcapcalq50); +} + +#if CFG_SUPPORT_MANUAL_CALI +static UINT32 rwnx_cal_translate_tx_rate(UINT32 rate) +{ + UINT32 param; + + switch(rate) + { + case 0 : + param = 1; + break; // 1Mbps + case 1 : + param = 2; + break; // 2Mbps + case 2 : + param = 5; + break; // 5.5Mbps + case 3: + param = 11; + break; // 11Mbps + case 4: + param = 6; + break; // 6Mbps + case 5 : + param = 9; + break; // 9Mbps + case 6: + param = 12; + break; // 12Mbps + case 7: + param = 18; + break; // 18Mbps + case 8: + param = 24; + break; // 24Mbps + case 9: + param = 36; + break; // 36Mbps + case 10: + param = 48; + break; // 48Mbps + case 11: + param = 54; + break; // 54Mbps + default: + param = rate; + break; // 54Mbps + } + + return param; +} + +UINT32 rwnx_cal_translate_tx_rate_for_n(UINT32 rate, UINT32 bandwidth) +{ + UINT32 param; + + switch(rate) + { + case 128 : + case 129 : + case 130 : + case 131 : + case 132 : + case 133 : + param = rate - 123; + break; // MCS0-5 the same rate indx as 9M to 36M + + case 134: + case 135: + if(bandwidth == PHY_CHNL_BW_20) + param = 11; // MCS6-7the same rate indx as to 54M - band:20M + else + param = 12; // MCS6-7the same rate indx as to 135M - band:40M + break; + + default: + param = rate; + break; + } + + return param; +} +#endif + +//static INT32 cur_rate; +void rwnx_cal_set_txpwr_by_rate(INT32 rate, UINT32 test_mode) +{ +#if CFG_SUPPORT_MANUAL_CALI + UINT32 ret; + UINT32 pwr_gain; + + struct phy_channel_info info; + UINT32 channel, bandwidth; // PHY_CHNL_BW_20, PHY_CHNL_BW_40: + + phy_get_channel(&info, 0); + bandwidth = (info.info1 >> 8) & 0xff; + + channel = (((info.info2 & 0xffff) - 2400) - 7)/5; + if(channel > 14) + channel = 14; + + if(!manual_cal_get_txpwr(rwnx_cal_translate_tx_rate(rate), + channel, bandwidth, &pwr_gain)) + { + // unable get txpwr from manual cal + return; + } + + if (test_mode == 0) + { + ret = manual_cal_get_pwr_idx_shift(rate, bandwidth, &pwr_gain); + } + else + { + ret = 2; + if((bandwidth == PHY_CHNL_BW_20) && (rate <= 3)) + { + ret = 1; + } + } + os_null_printf("txpwr info- r:%d, c:%d, b:%d -- idx1:%d, idx2: %d\r\n", + rate, channel, bandwidth, pwr_gain, ret); + if(!ret ){ + // unable get txpwr from manual cal + return; + } else if(ret == 1) { + rwnx_cal_set_txpwr(pwr_gain, EVM_DEFUALT_B_RATE); + } else if(ret == 2) { + rwnx_cal_set_txpwr(pwr_gain, EVM_DEFUALT_RATE); + } + + if ((test_mode) && ((rate <= 4) || (rate == 128))) + { + // just for 11b/11g_6Mbps/MCS0 + BK7231N_RC_REG.REG0x5A->bits.TXCALCAPI = 0xff; + BK7231N_RC_REG.REG0x5B->bits.TXCALCAPQ = 0xff; + if ((rate <= 3) && (channel == 14)) + { + BK7231N_RC_REG.REG0x5A->bits.TXCALCAPI = 0x7f; + BK7231N_RC_REG.REG0x5B->bits.TXCALCAPQ = 0x7f; + REG_WRITE((REG_MDM_CFG_BASE_ADDR + 0xC00 * 4), REG_READ(REG_MDM_CFG_BASE_ADDR + 0xC00 * 4) | 0x1); + } + } + else if (rate <= 1) + { + // just for 11b_1Mbps/11b_2Mbps + BK7231N_RC_REG.REG0x5A->bits.TXCALCAPI = 0x7f; + BK7231N_RC_REG.REG0x5B->bits.TXCALCAPQ = 0xff; + } + else if (rate <= 3) + { + // just for 11b_5.5Mbps/11b_11Mbps + BK7231N_RC_REG.REG0x5A->bits.TXCALCAPI = 0xff; + BK7231N_RC_REG.REG0x5B->bits.TXCALCAPQ = 0xff; + } + else + { + // restore iq for 11g/11n + extern UINT32 g_lpf_cal_i; + extern UINT32 g_lpf_cal_q; + BK7231N_RC_REG.REG0x5A->bits.TXCALCAPI = g_lpf_cal_i; + BK7231N_RC_REG.REG0x5B->bits.TXCALCAPQ = g_lpf_cal_q; + } + + if(test_mode) + { + /* change TRX_REG4 in FCC mode */ + if ((DEVICE_ID_BK7231N_P & DEVICE_ID_MASK) == gcali_context.device_id) + { + /* rvco 9->F by d.guo20210430 to fix dpll unlock when high temperature */ + if ((BK7231N_TRX_RAM.REG0x4.bits.Rvco != 0xF) + || (BK7231N_TRX_RAM.REG0x4.bits.Itune_vco_spi != 0x1C)) + { + BK7231N_TRX_RAM.REG0x4.bits.Rvco = 0xF; + BK7231N_TRX_RAM.REG0x4.bits.Itune_vco_spi = 0x1C; + CAL_WR_TRXREGS(0x4); + } + } + else if (BK7231N_TRX_RAM.REG0x4.bits.Itune_vco_spi != 0x2C) + { + BK7231N_TRX_RAM.REG0x4.bits.Itune_vco_spi = 0x2C; + CAL_WR_TRXREGS(0x4); + } + } +#endif +} + +UINT32 rwnx_setting_for_single_rate(INT32 rate) +{ + // qunshan20210405 set filter like none-signal mode + if (!get_ate_mode_state()) + { + return 0; + } + if (rate < 0) + { + // restore iq for 11g/11n + extern UINT32 g_lpf_cal_i; + extern UINT32 g_lpf_cal_q; + BK7231N_RC_REG.REG0x5A->bits.TXCALCAPI = g_lpf_cal_i; + BK7231N_RC_REG.REG0x5B->bits.TXCALCAPQ = g_lpf_cal_q; + } + else if ((gtest_mode) && ((rate <= 4) || (rate == 128))) + { + // just for 11b/11g_6Mbps/MCS0 + BK7231N_RC_REG.REG0x5A->bits.TXCALCAPI = 0xff; + BK7231N_RC_REG.REG0x5B->bits.TXCALCAPQ = 0xff; + } + else if (rate <= 1) + { + // just for 11b_1Mbps/11b_2Mbps + BK7231N_RC_REG.REG0x5A->bits.TXCALCAPI = 0x7f; + BK7231N_RC_REG.REG0x5B->bits.TXCALCAPQ = 0xff; + } + else if (rate <= 3) + { + // just for 11b_5.5Mbps/11b_11Mbps + BK7231N_RC_REG.REG0x5A->bits.TXCALCAPI = 0xff; + BK7231N_RC_REG.REG0x5B->bits.TXCALCAPQ = 0xff; + } + else + { + // restore iq for 11g/11n + extern UINT32 g_lpf_cal_i; + extern UINT32 g_lpf_cal_q; + BK7231N_RC_REG.REG0x5A->bits.TXCALCAPI = g_lpf_cal_i; + BK7231N_RC_REG.REG0x5B->bits.TXCALCAPQ = g_lpf_cal_q; + } + + return 0; +} + +void ble_cal_set_txpwr(uint8_t idx) +{ + const PWR_REGS *pcfg; + volatile UINT32 txpwr; + + *((volatile unsigned int *)0XC0010004) = 3 << 18; + + if (idx > TCP_PAMAP_TAB_BLE_LEN) { + idx = TCP_PAMAP_TAB_BLE_LEN; + } + + if (check_large_singal_status()) + phy_enable_rx_switch(); + + if(rwnx_sys_is_enable_hw_tpc()) + rwnx_no_use_tpc_set_pwr(); + + pcfg = cfg_tab_ble + idx; + + BK7231N_TRX_RAM.REG0x8.bits.rssith50 = 0xf; + CAL_WR_TRXREGS(0x8); + + BK7231N_RC_REG.REG0x3C->bits.RXHPFBYPASS = 0x1; + + REG_WRITE((RCB_POWER_TABLE_ADDR + (0x7F * 4)), PWR_GAIN_BASE_BLE | pcfg->pregain); + txpwr = REG_READ(RCB_POWER_TABLE_ADDR + (0x7F * 4)); + (void)txpwr; +} + +void ble_cal_recover_txpwr(void) +{ + BK7231N_TRX_RAM.REG0x8.value = BK7231N_TRX_ROM[8]; + CAL_WR_TRXREGS(0x8); + + *((volatile unsigned int *)0XC0010004) = 0; + + if (check_large_singal_status()) + phy_disable_rx_switch(); + + if (rwnx_sys_is_enable_hw_tpc()) { + rwnx_use_tpc_set_pwr(); + } + + BK7231N_RC_REG.REG0x3C->bits.RXHPFBYPASS = 0x0; +} + +extern void tpc_init(void); +extern void tpc_deinit(void); +struct temp_cal_pwr_st g_temp_pwr_current_tpc = {0, EVM_DEFUALT_RATE, 0, 0}; +void rwnx_set_tpc_txpwr_by_tmpdetect(INT16 shift_b, INT16 shift_g) +{ + g_temp_pwr_current_tpc.shift_g = shift_g; + g_temp_pwr_current_tpc.shift = shift_b; + +#ifdef ATE_PRINT_DEBUG + os_printf("td set tpc pwr: shift_b:%d, shift_g:%d\r\n", + shift_b, shift_g); +#endif +} + +UINT32 rwnx_tpc_pwr_idx_translate(UINT32 pwr_gain, UINT32 rate, UINT32 print_log) +{ + INT16 idx = TCP_PAMAP_TAB_LEN - 1; + INT16 shift; + INT16 idx_max; + + if(rate == EVM_DEFUALT_B_RATE) { + // for b + idx_max = TCP_PAMAP_TAB_B_LEN; + shift = g_temp_pwr_current_tpc.shift; + } else if(rate == EVM_DEFUALT_RATE) { + // for g + idx_max = TCP_PAMAP_TAB_G_LEN; + shift = g_temp_pwr_current_tpc.shift_g; + } else { + os_printf("no support :%d\r\n", rate); + return idx; + } + + idx = pwr_gain + shift; + + if(idx >= idx_max) { + idx = idx_max - 1; + } else if (idx < 0) + idx = 0; + +#if CFG_USE_TEMPERATURE_DETECT + g_temp_pwr_current_tpc.idx = idx; +#endif + + if (print_log) + { + os_null_printf("translate idx1:%d, td_shift:%d, b/g:%d --- idx2:%d\r\n", pwr_gain, + shift, rate, idx); + } + + return idx; +} + +UINT32 rwnx_tpc_get_pwridx_by_rate(UINT32 rate, UINT32 print_log) +{ + UINT32 ret, ret_bak; + UINT32 pwr_gain; + UINT32 pwr_gain_base = 0; + const PWR_REGS *pcfg; + static UINT32 last_ret = 0; + struct phy_channel_info info; + UINT32 channel, bandwidth; // PHY_CHNL_BW_20, PHY_CHNL_BW_40: + + phy_get_channel(&info, 0); + bandwidth = (info.info1 >> 8) & 0xff; + if(rate <= 128) + bandwidth = 0; + + channel = (((info.info2 & 0xffff) - 2400) - 7)/5; + + if(channel > 14) + channel = 14; + + if(manual_cal_get_txpwr(rwnx_cal_translate_tx_rate(rate), + channel, bandwidth, &pwr_gain) == 0) + { + os_null_printf("unable get txpwr %d, %d, %d\r\n", rate, channel, bandwidth); + return 0; + } + + ret_bak = ret = manual_cal_get_pwr_idx_shift(rate, bandwidth, &pwr_gain); + + if(!ret ){ + os_null_printf("unable get txpwr shift %d, %d, %d\r\n", rate, channel, bandwidth); + return 0; + } else if(ret == 1) { + ret = rwnx_tpc_pwr_idx_translate(pwr_gain, EVM_DEFUALT_B_RATE, 0); + pwr_gain_base = PWR_GAIN_BASE_B; + pcfg = cfg_tab_b + ret; + } else if(ret == 2) { + ret = rwnx_tpc_pwr_idx_translate(pwr_gain, EVM_DEFUALT_RATE, 0); + pwr_gain_base = PWR_GAIN_BASE_G; + pcfg = cfg_tab_g + ret; + ret += TCP_PAMAP_TAB_B_LEN; + } + + if (last_ret != ret || print_log) + { + INT16 shift = g_temp_pwr_current.shift; + if(ret_bak == 2) { + shift = g_temp_pwr_current.shift_g; + } + + CAL_FATAL("tpc info- r:%d, c:%d, b:%d -- idx1:%d+(%d), idx2: %d\r\n", + rate, channel, bandwidth, pwr_gain, shift, ret); + + CAL_PRT("b[31-12]:0x%05x, c[11-0]:0x%03x\r\n", pwr_gain_base >> 12, pcfg->pregain); + + (void)shift; + } + last_ret = ret; + + return ret; + +} + +void rwnx_use_tpc_set_pwr(void) +{ + #if CFG_SUPPORT_TPC_PA_MAP + BK7231N_RC_REG.REG0x4C->bits.TXPOWTBLEN = 1; + BK7231N_RC_RAM.REG0x4C.bits.TXPOWTBLEN = 1; + + gcali_context.is_tpc_used = 1; + #endif +} + +void rwnx_no_use_tpc_set_pwr(void) +{ + #if CFG_SUPPORT_TPC_PA_MAP + BK7231N_RC_REG.REG0x4C->bits.TXPOWTBLEN = 0; + BK7231N_RC_RAM.REG0x4C.bits.TXPOWTBLEN = 0; + #endif +} + +UINT32 rwnx_is_tpc_bit_on(void) +{ + return (BK7231N_RC_REG.REG0x4C->bits.TXPOWTBLEN == 1)? 1: 0; +} + +UINT32 rwnx_sys_is_enable_hw_tpc(void) +{ + return (gcali_context.is_tpc_used == 1)? 1: 0; +} + +void rwnx_tpc_pa_map_init(void) +{ + UINT32 index; + const PWR_REGS *pcfg; + + BK7231N_RC_REG.REG0x4C->bits.TXPOWTBLEN = 0; + pcfg = cfg_tab_b; + for (index = 0; index < TCP_PAMAP_TAB_B_LEN; index++) + { + REG_WRITE((RCB_POWER_TABLE_ADDR + (index * 4)), PWR_GAIN_BASE_B | pcfg->pregain); + pcfg++; + } + pcfg = cfg_tab_g; + for (index = TCP_PAMAP_TAB_B_LEN; index < TCP_PAMAP_TAB_LEN; index++) + { + REG_WRITE((RCB_POWER_TABLE_ADDR + (index * 4)), PWR_GAIN_BASE_G | pcfg->pregain); + pcfg++; + } + rwnx_use_tpc_set_pwr(); + + BK7231N_TRX_RAM.REG0xC.bits.pamapen = 1; + CAL_WR_TRXREGS(0xC); +} + +void rwnx_cal_initial_calibration(void) +{ + rwnx_cal_set_txpwr(40, EVM_DEFUALT_RATE); + + rwnx_tpc_pa_map_init(); +} + +void rwnx_cal_set_reg_adda_ldo(UINT32 val) +{ +// os_printf("set_reg_adda_ldo:%d \r\n", val); + + val = val & 0x3; + + BK7231N_TRX_RAM.REG0x12.bits.ldoadda = val; + CAL_WR_TRXREGS(0x12); +} + +void rwnx_cal_set_rxswitch(UINT32 enable) +{ + if(enable) + BK7231N_TRX_RAM.REG0xE.bits.enrxsw = 1; + else + BK7231N_TRX_RAM.REG0xE.bits.enrxsw = 0; + CAL_WR_TRXREGS(0xD); +} + +UINT32 rwnx_cal_get_rxswitch(void) +{ + return (UINT32)BK7231N_TRX_REG.REG0xE->bits.enrxsw; +} + + +void rwnx_cal_en_extra_txpa(void) +{ + BK7231N_TRX_RAM.REG0x10.value = BK7231N_TRX_REG.REG0xD->value; + BK7231N_TRX_RAM.REG0x10.bits.entxfebias = 0; + CAL_WR_TRXREGS(0x10); +} + +void rwnx_cal_dis_extra_txpa(void) +{ + BK7231N_TRX_RAM.REG0x10.value = BK7231N_TRX_ROM[0x10]; + CAL_WR_TRXREGS(0x10); +} + +void rwnx_cal_set_bw_i2v(int enable) +{ + BK7231N_TRX_RAM.REG0x9.bits.bw_i2v = enable ? 1 : 0; + CAL_WR_TRXREGS(0x9); +} + +void rwnx_cal_en_rx_filter_offset(void) +{ + BK7231N_RC_RAM.REG0x5B.bits.RXCALCAPQ = gcali_result.gtx_qfilter_corner+0x64; + BK7231N_RC_RAM.REG0x5A.bits.RXCALCAPI = gcali_result.gtx_ifilter_corner+0x64; + BK7231N_RC_REG.REG0x5A->value = BK7231N_RC_RAM.REG0x5A.value; + BK7231N_RC_REG.REG0x5B->value = BK7231N_RC_RAM.REG0x5B.value; +} + +void rwnx_cal_dis_rx_filter_offset(void) +{ + BK7231N_RC_RAM.REG0x5B.bits.RXCALCAPQ = gcali_result.gtx_qfilter_corner; + BK7231N_RC_RAM.REG0x5A.bits.RXCALCAPI = gcali_result.gtx_ifilter_corner; + BK7231N_RC_REG.REG0x5A->value = BK7231N_RC_RAM.REG0x5A.value; + BK7231N_RC_REG.REG0x5B->value = BK7231N_RC_RAM.REG0x5B.value; +} + +void rwnx_cal_set_reg_rx_ldo(void) +{ + BK7231N_TRX_RAM.REG0x9.bits.vsrxlnaldo10 = 0x3; + CAL_WR_TRXREGS(0x9); +} + +void rwnx_cal_set_40M_extra_setting(UINT8 val) +{ + if (1==val) + { + BK7231N_TRX_RAM.REG0xF.bits.clkadc_sel = 1; + CAL_WR_TRXREGS(0xF); + } + else + { + BK7231N_TRX_RAM.REG0xF.bits.clkadc_sel = 0; + CAL_WR_TRXREGS(0xF); + } +} + +void rwnx_cal_set_40M_setting(void) +{ + //BK7231N_TRX_RAM.REG0x12.bits.adcrefbwsel = 1; + //BK7231N_TRX_RAM.REG0x12.bits.adciselc20 = 0x4; + //BK7231N_TRX_RAM.REG0x12.bits.adciselr20 = 0x4; + BK7231N_TRX_RAM.REG0x12.bits.fictrl30 = 7; + CAL_WR_TRXREGS(0x12); + + BK7231N_TRX_RAM.REG0xD.bits.lpfrxbw = 1; + BK7231N_TRX_RAM.REG0xD.bits.lpftxbw = 1; + CAL_WR_TRXREGS(0xD); + BK7231N_RC_REG.REG0x1A->value = BK7231N_TRX_RAM.REG0xD.value; + + BK7231N_TRX_RAM.REG0xE.bits.lpfrxbw = 1; + BK7231N_TRX_RAM.REG0xE.bits.lpftxbw = 1; + CAL_WR_TRXREGS(0xE); + + BK7231N_TRX_RAM.REG0x10.bits.lpfrxbw = 1; + BK7231N_TRX_RAM.REG0x10.bits.lpftxbw = 1; + CAL_WR_TRXREGS(0x10); + + BK7231N_TRX_RAM.REG0xF.bits.clkdac_sel = 1; + BK7231N_TRX_RAM.REG0xF.bits.clkadc_sel = 1; + CAL_WR_TRXREGS(0xF); +} + +void rwnx_cal_set_20M_setting(void) +{ + //BK7231N_TRX_RAM.REG0x12.bits.adcrefbwsel = 1; + //BK7231N_TRX_RAM.REG0x12.bits.adciselc20 = 0x4; + //BK7231N_TRX_RAM.REG0x12.bits.adciselr20 = 0x4; + BK7231N_TRX_RAM.REG0x12.bits.fictrl30 = 7; + CAL_WR_TRXREGS(0x12); + + BK7231N_TRX_RAM.REG0xD.bits.lpfrxbw = 0; + BK7231N_TRX_RAM.REG0xD.bits.lpftxbw = 0; + CAL_WR_TRXREGS(0xD); + BK7231N_RC_REG.REG0x1A->value = BK7231N_TRX_RAM.REG0xD.value; + + BK7231N_TRX_RAM.REG0xE.bits.lpfrxbw = 0; + BK7231N_TRX_RAM.REG0xE.bits.lpftxbw = 0; + CAL_WR_TRXREGS(0xE); + + BK7231N_TRX_RAM.REG0x10.bits.lpfrxbw = 0; + BK7231N_TRX_RAM.REG0x10.bits.lpftxbw = 0; + CAL_WR_TRXREGS(0x10); + + // cunliang20210512 keep TRX_F<1>=1 to fix evm burst issue + if (get_ate_mode_state()) + { + BK7231N_TRX_RAM.REG0xF.bits.clkdac_sel = 1; + } + else + { + BK7231N_TRX_RAM.REG0xF.bits.clkdac_sel = 0; + } + BK7231N_TRX_RAM.REG0xF.bits.clkadc_sel = 0; + CAL_WR_TRXREGS(0xF); +} + +#if CFG_SUPPORT_MANUAL_CALI +void rwnx_cal_set_txpwr(UINT32 pwr_gain, UINT32 grate) +{ + const PWR_REGS *pcfg; + UINT32 pwr_gain_base = 0; + volatile UINT32 txpwr; + + g_temp_pwr_current.idx = pwr_gain; + g_temp_pwr_current.mode = grate; + +#if CFG_USE_TEMPERATURE_DETECT + INT16 shift = g_temp_pwr_current.shift; + + if(g_temp_pwr_current.mode == EVM_DEFUALT_RATE) + shift = g_temp_pwr_current.shift_g; + +#ifdef ATE_PRINT_DEBUG + os_null_printf("-----pwr_gain:%d, rate=%d, g_idx:%d, shift_b:%d, shift_g:%d\n", + pwr_gain, + grate, + g_temp_pwr_current.idx, + g_temp_pwr_current.shift, + g_temp_pwr_current.shift_g); +#endif + + pwr_gain = g_temp_pwr_current.idx + shift; + +#endif // CFG_USE_TEMPERATURE_DETECT + + if(grate == EVM_DEFUALT_B_RATE) { + // for b + if(pwr_gain > TCP_PAMAP_TAB_B_LEN - 1) + { + pwr_gain = TCP_PAMAP_TAB_B_LEN - 1; + g_temp_pwr_current.idx = pwr_gain; + } + pcfg = cfg_tab_b + pwr_gain; + pwr_gain_base = PWR_GAIN_BASE_B; + } else if(grate == EVM_DEFUALT_RATE) { + // for g + if(pwr_gain > TCP_PAMAP_TAB_G_LEN - 1) + { + pwr_gain = TCP_PAMAP_TAB_G_LEN - 1; + g_temp_pwr_current.idx = pwr_gain; + } + pcfg = cfg_tab_g + pwr_gain; + pwr_gain_base = PWR_GAIN_BASE_G; + } else { + os_null_printf("set_txpwr unknow rate:%d \r\n", grate); + return; + } + + if(get_ate_mode_state()) { +#ifdef ATE_PRINT_DEBUG + os_null_printf("idx:%02d,r:%03d- pg:0x%02x, %01x, %01x, %01x, %01x, %02x, %02x, %01x,\r\n", pwr_gain, grate, + pcfg->pregain, pcfg->regb_28_31, pcfg->regc_8_10,pcfg->regc_4_6, pcfg->regc_0_2, + pcfg->rega_8_13, pcfg->rega_4_7, pcfg->rega_0_1); + os_null_printf("Xtal C: %d\r\n", manual_cal_get_xtal()); +#else + os_printf("idx:%02d\r\n", pwr_gain); +#endif + } + + CHECK_OPERATE_RF_REG_IF_IN_SLEEP(); + + if (get_ate_mode_state()) { + REG_WRITE((RCB_POWER_TABLE_ADDR + (0x34 * 4)), pwr_gain_base | pcfg->pregain); //0xE98B7150 + txpwr = REG_READ(RCB_POWER_TABLE_ADDR + (0x34 * 4)); + } else if(grate == EVM_DEFUALT_B_RATE) { + REG_WRITE((RCB_POWER_TABLE_ADDR + (pwr_gain * 4)), pwr_gain_base | pcfg->pregain); //0xE98B7150 + txpwr = REG_READ(RCB_POWER_TABLE_ADDR + (pwr_gain * 4)); + } else { + REG_WRITE((RCB_POWER_TABLE_ADDR + TCP_PAMAP_TAB_B_LEN * 4 + (pwr_gain * 4)), pwr_gain_base | pcfg->pregain); //0xE98B7150 + txpwr = REG_READ(RCB_POWER_TABLE_ADDR + TCP_PAMAP_TAB_B_LEN * 4 + (pwr_gain * 4)); + } + (void)txpwr; + + CAL_WR_TRXREGS(0xB); + + if(grate == EVM_DEFUALT_B_RATE) + { + BK7231N_TRX_RAM.REG0xA.bits.Dvb=0xA; // 0X5063DDFF;//0X8063DDFF + BK7231N_TRX_RAM.REG0xC.bits.Gmgain=0x8; //0X04783E98;//0X04782EA8 + BK7231N_TRX_RAM.REG0x0.bits.tspi = 0x4; + BK7231N_TRX_RAM.REG0x0.bits.Dtau = 0x3; + } + else if(grate == EVM_DEFUALT_RATE) + { + BK7231N_TRX_RAM.REG0xA.bits.Dvb=0x6; //0X5063DDFF;//0X8063DDFF + BK7231N_TRX_RAM.REG0xC.bits.Gmgain=0xA; //0X04783E98;//0X04782EA8 + + BK7231N_TRX_RAM.REG0x0.bits.tspi = 0x5; + BK7231N_TRX_RAM.REG0x0.bits.Dtau = 0x8; + } + CAL_WR_TRXREGS(0xC); + CAL_WR_TRXREGS(0xA); + CAL_WR_TRXREGS(0x0); + os_null_printf("%s:%d padctrl=0x%x->0xC,pactrl=0x%x->0xE pregain=0x%x\r\n", __FUNCTION__, __LINE__, pcfg->regc_4_6, pcfg->regc_8_10, pcfg->pregain); + CHECK_OPERATE_RF_REG_IF_IN_SLEEP_END(); + g_pwr_current.idx = pwr_gain; + g_pwr_current.mode = grate; +} + +#if CFG_USE_TEMPERATURE_DETECT +extern UINT32 ble_in_dut_mode(void); +void rwnx_cal_set_txpwr_by_tmpdetect(INT16 shift_b, INT16 shift_g) +{ + UINT32 should_do = 0; + + if(g_temp_pwr_current.shift != shift_b) + { + g_temp_pwr_current.shift = shift_b; + should_do = 1; + } + + if(g_temp_pwr_current.shift_g!= shift_g) + { + g_temp_pwr_current.shift_g = shift_g; + should_do = 1; + } + + if( should_do) + { +#ifdef ATE_PRINT_DEBUG + os_printf("td set pwr: shift_b:%d, shift_g:%d, rate:%d\r\n", + g_temp_pwr_current.shift, + g_temp_pwr_current.shift_g, + g_temp_pwr_current.mode); +#endif + + if ((rwnx_is_tpc_bit_on() == 0) && (ble_in_dut_mode() == 0)) + { + rwnx_cal_set_txpwr(g_temp_pwr_current.idx, g_temp_pwr_current.mode); + } + else + { + + } + } +} +#endif // CFG_USE_TEMPERATURE_DETECT + +void rwnx_cal_set_reg_mod_pa(UINT16 reg_mod, UINT16 reg_pa) +{ + CHECK_OPERATE_RF_REG_IF_IN_SLEEP(); + + gtx_dcorMod = (INT32)reg_mod, + gtx_dcorPA = (INT32)reg_pa; + //BK7231N_TRX_REG.REG0xB->bits.dcorMod30 = gtx_dcorMod; + //BK7231N_TRX_REG.REG0xC->bits.dcorPA30 = gtx_dcorPA; + CHECK_OPERATE_RF_REG_IF_IN_SLEEP_END(); +} + +void rwnx_cal_recover_txpwr_for_wifi(void) +{ + if(gcali_context.is_tpc_used) + { + rwnx_use_tpc_set_pwr(); + } + else + { + rwnx_cal_set_txpwr(g_pwr_current.idx, g_pwr_current.mode); + } +} + +#endif + +#if CFG_USE_TEMPERATURE_DETECT +extern void bk7011_cal_rx_adc_restore(int enter_or_exit); +extern void bk7011_cal_rx_adc_dlym(); +void rwnx_cal_do_temp_detect(UINT16 cur_val, UINT16 thre, UINT16 *last) +{ + static UINT16 last_val; + TMP_PWR_PTR tmp_pwr_ptr; + + if (cur_val == 0) + { + /* 0 is invalid, but saradc may return 0 in power save mode */ + return; + } + tmp_pwr_ptr = manual_cal_set_tmp_pwr(cur_val, thre, last); + if(tmp_pwr_ptr) + { + if ((last_val >= cur_val + ADC_TMEP_LSB_PER_10DEGREE) || (cur_val >= last_val + ADC_TMEP_LSB_PER_10DEGREE)) + { + bk7011_cal_rx_adc_restore(1); + bk7011_cal_rx_adc_dlym(); + bk7011_cal_rx_adc_restore(0); + last_val = cur_val; + } + //BK7231N_TRX_RAM.REG0xC.bits.dcorPA30 = tmp_pwr_ptr->trx0x0c_12_15; + CAL_WR_TRXREGS(0xC); + + manual_cal_do_xtal_temp_delta_set(tmp_pwr_ptr->xtal_c_dlta); + manual_cal_do_xtal_cali(cur_val, 0, 0, 0); + + rwnx_cal_set_txpwr_by_tmpdetect((INT16)tmp_pwr_ptr->p_index_delta, (INT16)tmp_pwr_ptr->p_index_delta_g); + rwnx_set_tpc_txpwr_by_tmpdetect((INT16)tmp_pwr_ptr->p_index_delta, (INT16)tmp_pwr_ptr->p_index_delta_g); + } +} +#endif // CFG_USE_TEMPERATURE_DETECT + +void rwnx_tx_cal_save_cal_result(void) +{ + // Manual calibration not used PA & MOD, but use pre_gain + #if CFG_SUPPORT_MANUAL_CALI + // gtx_dcorMod = 0xc;//0x8; + //gtx_dcorPA = 0x5;//0x8; + #if CFG_USE_TEMPERATURE_DETECT + manual_cal_tmp_pwr_init_reg(gtx_dcorMod, gtx_dcorPA); + #endif // CFG_USE_TEMPERATURE_DETECT + #endif + + BK7231N_RC_RAM.REG0x4F.bits.TXIDCCOMP = gcali_result.gtx_i_dc_comp; + BK7231N_RC_RAM.REG0x4F.bits.TXQDCCOMP = gcali_result.gtx_q_dc_comp; + + BK7231N_RC_RAM.REG0x50.bits.TXIGAINCOMP = gcali_result.gtx_i_gain_comp; + BK7231N_RC_RAM.REG0x50.bits.TXQGAINCOMP = gcali_result.gtx_q_gain_comp; + + BK7231N_TRX_RAM.REG0x6.bits.lpfcapcalq50 = gcali_result.gtx_qfilter_corner & 0x3F; + BK7231N_TRX_RAM.REG0x7.bits.lpfcapcalq = (gcali_result.gtx_qfilter_corner >> 6) & 0x3; + BK7231N_TRX_RAM.REG0x6.bits.lpfcapcali50 = gcali_result.gtx_ifilter_corner & 0x3F; + BK7231N_TRX_RAM.REG0x7.bits.lpfcapcali = (gcali_result.gtx_ifilter_corner >> 6) & 0x3; + + BK7231N_RC_RAM.REG0x51.bits.TXPHASECOMP = gcali_result.gtx_phase_comp; + BK7231N_RC_RAM.REG0x51.bits.TXTY2 = gcali_result.gtx_phase_ty2; + + BK7231N_RC_RAM.REG0x5A.bits.TXCALCAPI = gcali_result.gtx_ifilter_corner; + BK7231N_RC_RAM.REG0x5A.bits.RXCALCAPI = gcali_result.gtx_ifilter_corner+0x64; + BK7231N_RC_RAM.REG0x5A.bits.STANDBYCALCAPI = gcali_result.gtx_ifilter_corner; + + BK7231N_RC_RAM.REG0x5B.bits.STANDBYCALCAPQ = gcali_result.gtx_qfilter_corner; + BK7231N_RC_RAM.REG0x5B.bits.RXCALCAPQ = gcali_result.gtx_qfilter_corner+0x64; + BK7231N_RC_RAM.REG0x5B.bits.TXCALCAPQ = gcali_result.gtx_qfilter_corner; +} + +void rwnx_rx_cal_save_cal_result(void) +{ + BK7231N_TRX_RAM.REG0x14.value = gcali_result.g_rx_dc_gain_tab[0]; + BK7231N_TRX_RAM.REG0x15.value = gcali_result.g_rx_dc_gain_tab[1]; + BK7231N_TRX_RAM.REG0x16.value = gcali_result.g_rx_dc_gain_tab[2]; + BK7231N_TRX_RAM.REG0x17.value = gcali_result.g_rx_dc_gain_tab[3]; + BK7231N_TRX_RAM.REG0x18.value = gcali_result.g_rx_dc_gain_tab[4]; + BK7231N_TRX_RAM.REG0x19.value = gcali_result.g_rx_dc_gain_tab[5]; + BK7231N_TRX_RAM.REG0x1A.value = gcali_result.g_rx_dc_gain_tab[6]; + BK7231N_TRX_RAM.REG0x1B.value = gcali_result.g_rx_dc_gain_tab[7]; + + BK7231N_RC_RAM.REG0x42.bits.RXAMPERRWR = gcali_result.grx_amp_err_wr; + BK7231N_RC_RAM.REG0x42.bits.RXPHASEERRWR = gcali_result.grx_phase_err_wr; +} + +/******************************************************************************* +* Function Implemantation +*******************************************************************************/ +void bk7011_read_cal_param(void) +{ + gcali_context.gtx_dc_n = 2;//gst_sar_adc=4 gst_rx_adc=2 +#if 0 + gcali_context.gst_sar_adc = ((BK7231N_RC_REG.REG0x54->bits.STSARADC & 0x03) + 1) * CAL_DELAY05US;//CAL_DELAY05US= 2 + gcali_context.gst_rx_adc = ((BK7231N_RC_REG.REG0x54->bits.STRXADC & 0x03) + 1) * CAL_DELAY100US;//CAL_DELAY100US=1 + gconst_pout = BK7231N_RC_REG.REG0x52->bits.IQCONSTANTPOUT; +#endif + + return; +} + +static void rwnx_cal_recover_rcbeken_reg_val(void) +{ + BK7231N_RC_REG.REG0x0->value = BK7231N_RC_RAM.REG0x0.value; + BK7231N_RC_REG.REG0x1->value = BK7231N_RC_RAM.REG0x1.value; + BK7231N_RC_REG.REG0x5->value = BK7231N_RC_RAM.REG0x5.value; + BK7231N_RC_REG.REG0x8->value = BK7231N_RC_RAM.REG0x8.value; + BK7231N_RC_REG.REG0xB->value = BK7231N_RC_RAM.REG0xB.value; + BK7231N_RC_REG.REG0xE->value = BK7231N_RC_RAM.REG0xE.value; + BK7231N_RC_REG.REG0x11->value = BK7231N_RC_RAM.REG0x11.value; + BK7231N_RC_REG.REG0x19->value = BK7231N_RC_RAM.REG0x19.value; + //BK7231N_RC_REG.REG0x1A->value = BK7231N_RC_RAM.REG0x1A.value; + BK7231N_RC_REG.REG0x1C->value = BK7231N_RC_RAM.REG0x1C.value; + BK7231N_RC_REG.REG0x1E->value = BK7231N_RC_RAM.REG0x1E.value; + + /**********NEW ADDED************/ + BK7231N_RC_REG.REG0x3C->value = BK7231N_RC_RAM.REG0x3C.value; + BK7231N_RC_REG.REG0x3E->value = BK7231N_RC_RAM.REG0x3E.value; + BK7231N_RC_REG.REG0x3F->value = BK7231N_RC_RAM.REG0x3F.value; + BK7231N_RC_REG.REG0x40->value = BK7231N_RC_RAM.REG0x40.value; + BK7231N_RC_REG.REG0x41->value = BK7231N_RC_RAM.REG0x41.value; + BK7231N_RC_REG.REG0x42->value = BK7231N_RC_RAM.REG0x42.value; + //BK7231N_RC_REG.REG0x43->value = BK7231N_RC_RAM.REG0x43.value; + BK7231N_RC_REG.REG0x4C->value = BK7231N_RC_RAM.REG0x4C.value; + BK7231N_RC_REG.REG0x4D->value = BK7231N_RC_RAM.REG0x4D.value; + BK7231N_RC_REG.REG0x4F->value = BK7231N_RC_RAM.REG0x4F.value; + BK7231N_RC_REG.REG0x50->value = BK7231N_RC_RAM.REG0x50.value; + BK7231N_RC_REG.REG0x51->value = BK7231N_RC_RAM.REG0x51.value; + BK7231N_RC_REG.REG0x52->value = BK7231N_RC_RAM.REG0x52.value; + BK7231N_RC_REG.REG0x54->value = BK7231N_RC_RAM.REG0x54.value; + BK7231N_RC_REG.REG0x55->value = BK7231N_RC_RAM.REG0x55.value; + BK7231N_RC_REG.REG0x5C->value = BK7231N_RC_RAM.REG0x5C.value; + + BK7231N_RC_REG.REG0x4E->value = BK7231N_RC_RAM.REG0x4E.value; + //BK7231N_RC_REG.REG0x56->value = BK7231N_RC_RAM.REG0x56.value; + //BK7231N_RC_REG.REG0x57->value = BK7231N_RC_RAM.REG0x57.value; + BK7231N_RC_REG.REG0x5A->value = BK7231N_RC_RAM.REG0x5A.value; + BK7231N_RC_REG.REG0x5B->value = BK7231N_RC_RAM.REG0x5B.value; + BK7231N_RC_REG.REG0x6A->value = BK7231N_RC_RAM.REG0x6A.value; +} + +static void rwnx_cal_recover_trx_reg_val(void) +{ + BK7231N_TRX_REG.REG0x0->value = BK7231N_TRX_RAM.REG0x0.value; + BK7231N_TRX_REG.REG0x1->value = BK7231N_TRX_RAM.REG0x1.value; + BK7231N_TRX_REG.REG0x2->value = BK7231N_TRX_RAM.REG0x2.value; + BK7231N_TRX_REG.REG0x3->value = BK7231N_TRX_RAM.REG0x3.value; + BK7231N_TRX_REG.REG0x4->value = BK7231N_TRX_RAM.REG0x4.value; + BK7231N_TRX_REG.REG0x5->value = BK7231N_TRX_RAM.REG0x5.value; + BK7231N_TRX_REG.REG0x6->value = BK7231N_TRX_RAM.REG0x6.value; + BK7231N_TRX_REG.REG0x7->value = BK7231N_TRX_RAM.REG0x7.value; + BK7231N_TRX_REG.REG0x8->value = BK7231N_TRX_RAM.REG0x8.value; + BK7231N_TRX_REG.REG0x9->value = BK7231N_TRX_RAM.REG0x9.value; + BK7231N_TRX_REG.REG0xA->value = BK7231N_TRX_RAM.REG0xA.value; + BK7231N_TRX_REG.REG0xB->value = BK7231N_TRX_RAM.REG0xB.value; + BK7231N_TRX_REG.REG0xC->value = BK7231N_TRX_RAM.REG0xC.value; + BK7231N_TRX_REG.REG0xD->value = BK7231N_TRX_RAM.REG0xD.value; + BK7231N_TRX_REG.REG0xE->value = BK7231N_TRX_RAM.REG0xE.value; + BK7231N_TRX_REG.REG0xF->value = BK7231N_TRX_RAM.REG0xF.value; + BK7231N_TRX_REG.REG0x10->value = BK7231N_TRX_RAM.REG0x10.value; + BK7231N_TRX_REG.REG0x11->value = BK7231N_TRX_RAM.REG0x11.value; + BK7231N_TRX_REG.REG0x12->value = BK7231N_TRX_RAM.REG0x12.value; + BK7231N_TRX_REG.REG0x13->value = BK7231N_TRX_RAM.REG0x13.value; + BK7231N_TRX_REG.REG0x14->value = BK7231N_TRX_RAM.REG0x14.value; + BK7231N_TRX_REG.REG0x15->value = BK7231N_TRX_RAM.REG0x15.value; + BK7231N_TRX_REG.REG0x16->value = BK7231N_TRX_RAM.REG0x16.value; + BK7231N_TRX_REG.REG0x17->value = BK7231N_TRX_RAM.REG0x17.value; + BK7231N_TRX_REG.REG0x18->value = BK7231N_TRX_RAM.REG0x18.value; + BK7231N_TRX_REG.REG0x19->value = BK7231N_TRX_RAM.REG0x19.value; + BK7231N_TRX_REG.REG0x1A->value = BK7231N_TRX_RAM.REG0x1A.value; + BK7231N_TRX_REG.REG0x1B->value = BK7231N_TRX_RAM.REG0x1B.value; + + BK7231N_RC_REG.REG0x1A->value = BK7231N_TRX_RAM.REG0xD.value; + +} + +void rwnx_cal_recover_rf_setting(void) +{ + rwnx_cal_recover_rcbeken_reg_val(); + rwnx_cal_recover_trx_reg_val(); +} + +void rwnx_cal_recover_wifi_setting(void) +{ + //rwnx_cal_recover_trx_reg_val(); + rwnx_tpc_pa_map_init(); +} + +INT32 rwnx_cal_load_trx_rcbekn_reg_val(void) +{ +#if (CFG_RUNNING_PLATFORM == FPGA_PLATFORM) + +#else + rwnx_cal_recover_rcbeken_reg_val(); +#endif + + while(BK7231N_RC_REG.REG0x1->value & 0x0FFFFFFF) + { + cpu_delay(1); + } + rwnx_cal_recover_trx_reg_val(); + while(BK7231N_RC_REG.REG0x1->value & 0x0FFFFFFF) + { + cpu_delay(1); + } + +#if No_TXPOWERCAL + BK7231N_TRX_RAM.REG0xC.value = TRX_REG_0XC_VAL; + CAL_WR_TRXREGS(0xC); + + //BK7231N_RC_REG.REG0x52->bits.TXPREGAIN = 7; +#endif + + // cal rf pll when reload trx and rc beken value + bk7011_cal_pll(); + + return 0; +} + +INT32 rwnx_cal_save_trx_rcbekn_reg_val(void) +{ +#if (CFG_RUNNING_PLATFORM == FPGA_PLATFORM) + +#else + BK7231N_RC_RAM.REG0x0.value = BK7231N_RC_REG.REG0x0->value; + BK7231N_RC_RAM.REG0x1.value = BK7231N_RC_REG.REG0x1->value; + BK7231N_RC_RAM.REG0x5.value = BK7231N_RC_REG.REG0x5->value; + BK7231N_RC_RAM.REG0x8.value = BK7231N_RC_REG.REG0x8->value; + BK7231N_RC_RAM.REG0xB.value = BK7231N_RC_REG.REG0xB->value; + BK7231N_RC_RAM.REG0xE.value = BK7231N_RC_REG.REG0xE->value; + BK7231N_RC_RAM.REG0x11.value = BK7231N_RC_REG.REG0x11->value; + BK7231N_RC_RAM.REG0x19.value = BK7231N_RC_REG.REG0x19->value; + BK7231N_RC_RAM.REG0x1C.value = BK7231N_RC_REG.REG0x1C->value; + BK7231N_RC_RAM.REG0x1E.value = BK7231N_RC_REG.REG0x1E->value; + + /**********NEW ADDED************/ + BK7231N_RC_RAM.REG0x3C.value = BK7231N_RC_REG.REG0x3C->value; + BK7231N_RC_RAM.REG0x3E.value = BK7231N_RC_REG.REG0x3E->value; + BK7231N_RC_RAM.REG0x3F.value = BK7231N_RC_REG.REG0x3F->value; + BK7231N_RC_RAM.REG0x40.value = BK7231N_RC_REG.REG0x40->value; + BK7231N_RC_RAM.REG0x41.value = BK7231N_RC_REG.REG0x41->value; + BK7231N_RC_RAM.REG0x42.value = BK7231N_RC_REG.REG0x42->value; + BK7231N_RC_RAM.REG0x4C.value = BK7231N_RC_REG.REG0x4C->value; + BK7231N_RC_RAM.REG0x4D.value = BK7231N_RC_REG.REG0x4D->value; + BK7231N_RC_RAM.REG0x4F.value = BK7231N_RC_REG.REG0x4F->value; + BK7231N_RC_RAM.REG0x50.value = BK7231N_RC_REG.REG0x50->value; + BK7231N_RC_RAM.REG0x51.value = BK7231N_RC_REG.REG0x51->value; + BK7231N_RC_RAM.REG0x52.value = BK7231N_RC_REG.REG0x52->value; + BK7231N_RC_RAM.REG0x54.value = BK7231N_RC_REG.REG0x54->value; + BK7231N_RC_RAM.REG0x55.value = BK7231N_RC_REG.REG0x55->value; + BK7231N_RC_RAM.REG0x5C.value = BK7231N_RC_REG.REG0x5C->value; + + BK7231N_RC_RAM.REG0x4E.value = BK7231N_RC_REG.REG0x4E->value; + BK7231N_RC_RAM.REG0x5A.value = BK7231N_RC_REG.REG0x5A->value; + BK7231N_RC_RAM.REG0x5B.value = BK7231N_RC_REG.REG0x5B->value; + BK7231N_RC_RAM.REG0x6A.value = BK7231N_RC_REG.REG0x6A->value; +#if 0 + BK7231N_RC_RAM[29] = BK7231N_RC_REG.REG0x70->value; + BK7231N_RC_RAM[30] = BK7231N_RC_REG.REG0x71->value; + BK7231N_RC_RAM[31] = BK7231N_RC_REG.REG0x72->value; + BK7231N_RC_RAM[32] = BK7231N_RC_REG.REG0x73->value; + BK7231N_RC_RAM[33] = BK7231N_RC_REG.REG0x74->value; + BK7231N_RC_RAM[34] = BK7231N_RC_REG.REG0x75->value; + BK7231N_RC_RAM[35] = BK7231N_RC_REG.REG0x76->value; + BK7231N_RC_RAM[36] = BK7231N_RC_REG.REG0x77->value; +#endif + //BK7231N_RC_REG.REG0x3C->bits.RXIQSWAP = 1; /* I/Q SWAP*/ + +#endif + + BK7231N_TRX_RAM.REG0x0.value = BK7231N_TRX_REG.REG0x0->value ; + BK7231N_TRX_RAM.REG0x1.value = BK7231N_TRX_REG.REG0x1->value ; + BK7231N_TRX_RAM.REG0x2.value = BK7231N_TRX_REG.REG0x2->value ; + BK7231N_TRX_RAM.REG0x3.value = BK7231N_TRX_REG.REG0x3->value ; + BK7231N_TRX_RAM.REG0x4.value = BK7231N_TRX_REG.REG0x4->value ; + BK7231N_TRX_RAM.REG0x5.value = BK7231N_TRX_REG.REG0x5->value ; + BK7231N_TRX_RAM.REG0x6.value = BK7231N_TRX_REG.REG0x6->value ; + BK7231N_TRX_RAM.REG0x7.value = BK7231N_TRX_REG.REG0x7->value ; + BK7231N_TRX_RAM.REG0x8.value = BK7231N_TRX_REG.REG0x8->value ; + BK7231N_TRX_RAM.REG0x9.value = BK7231N_TRX_REG.REG0x9->value ; + BK7231N_TRX_RAM.REG0xA.value = BK7231N_TRX_REG.REG0xA->value ; + BK7231N_TRX_RAM.REG0xB.value = BK7231N_TRX_REG.REG0xB->value ; + BK7231N_TRX_RAM.REG0xC.value = BK7231N_TRX_REG.REG0xC->value ; + BK7231N_TRX_RAM.REG0xD.value = BK7231N_TRX_REG.REG0xD->value ; + BK7231N_TRX_RAM.REG0xE.value = BK7231N_TRX_REG.REG0xE->value ; + BK7231N_TRX_RAM.REG0xF.value = BK7231N_TRX_REG.REG0xF->value ; + BK7231N_TRX_RAM.REG0x10.value = BK7231N_TRX_REG.REG0x10->value; + BK7231N_TRX_RAM.REG0x11.value = BK7231N_TRX_REG.REG0x11->value; + BK7231N_TRX_RAM.REG0x12.value = BK7231N_TRX_REG.REG0x12->value; + BK7231N_TRX_RAM.REG0x13.value = BK7231N_TRX_REG.REG0x13->value; + BK7231N_TRX_RAM.REG0x14.value = BK7231N_TRX_REG.REG0x14->value; + BK7231N_TRX_RAM.REG0x15.value = BK7231N_TRX_REG.REG0x15->value; + BK7231N_TRX_RAM.REG0x16.value = BK7231N_TRX_REG.REG0x16->value; + BK7231N_TRX_RAM.REG0x17.value = BK7231N_TRX_REG.REG0x17->value; + BK7231N_TRX_RAM.REG0x18.value = BK7231N_TRX_REG.REG0x18->value; + BK7231N_TRX_RAM.REG0x19.value = BK7231N_TRX_REG.REG0x19->value; + BK7231N_TRX_RAM.REG0x1A.value = BK7231N_TRX_REG.REG0x1A->value; + BK7231N_TRX_RAM.REG0x1B.value = BK7231N_TRX_REG.REG0x1B->value; + + while(BK7231N_RC_REG.REG0x1->value & 0x0FFFFFFF) + { + cpu_delay(1); + } + + return 0; +} + +typedef struct +{ + DD_HANDLE handle; + saradc_desc_t desc; + UINT16 buffer[32]; +} cali_saradc_desc_t; +static cali_saradc_desc_t *cali_saradc_desc; + +void bk7011_cal_saradc_close(cali_saradc_desc_t *cali_saradc_ptr) +{ + UINT32 param; + + if (NULL != cali_saradc_ptr) + { + INT32 value = 0; + ddev_control(cali_saradc_desc->handle, SARADC_CMD_SET_BYPASS_CALIB, &value); + + ddev_close(cali_saradc_ptr->handle); + cali_saradc_ptr->handle = DD_HANDLE_UNVALID; + } + + param = PWD_SARADC_CLK_BIT; + sddev_control(ICU_DEV_NAME, CMD_CLK_PWR_DOWN, ¶m); + + param = BLK_BIT_SARADC; + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_BLK_DISABLE, ¶m); + + free(cali_saradc_ptr); + cali_saradc_desc = NULL; + + //BK7231N_TRX_RAM.REG0x2.bits.ampctrl_m = 0; + BK7231N_TRX_RAM.REG0x9.bits.agcrxfeEn = 1; + BK7231N_TRX_RAM.REG0x12.bits.buftstselection = 0; + BK7231N_TRX_RAM.REG0x12.bits.entstbufldo = 0; + BK7231N_TRX_RAM.REG0x6.bits.capcal_sel = 1; + + //CAL_WR_TRXREGS(0x2); + CAL_WR_TRXREGS(0x9); + CAL_WR_TRXREGS(0x12); + CAL_WR_TRXREGS(0x6); + +} + +cali_saradc_desc_t *bk7011_cal_saradc_open() +{ + UINT32 param; + + //BK7231N_TRX_RAM.REG0x2.bits.ampctrl_m = 1; + BK7231N_TRX_RAM.REG0xD.bits.entssi = 1; + BK7231N_TRX_RAM.REG0x12.bits.buftstselection = 3; + BK7231N_TRX_RAM.REG0x12.bits.entstbufldo = 1; + //CAL_WR_TRXREGS(0x2); + CAL_WR_TRXREGS(0xD); + CAL_WR_TRXREGS(0x12); + BK7231N_RC_REG.REG0x1A->value = BK7231N_TRX_RAM.REG0xD.value; + + if (NULL != cali_saradc_desc) + { + return cali_saradc_desc; + } + + cali_saradc_desc = (cali_saradc_desc_t *)malloc(sizeof(cali_saradc_desc_t)); + if (NULL == cali_saradc_desc) + { + return cali_saradc_desc; + } + + param = PWD_SARADC_CLK_BIT; + sddev_control(ICU_DEV_NAME, CMD_CLK_PWR_UP, ¶m);//REG_0x200FFFD7C + + param = BLK_BIT_SARADC; + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_BLK_ENABLE, ¶m); + + memset(cali_saradc_desc, 0x00, sizeof(cali_saradc_desc_t)); + cali_saradc_desc->desc.channel = 8; + cali_saradc_desc->desc.data_buff_size = sizeof(cali_saradc_desc->buffer) / sizeof(cali_saradc_desc->buffer[0]); + cali_saradc_desc->desc.mode = (ADC_CONFIG_MODE_CONTINUE << 0) + |(ADC_CONFIG_MODE_4CLK_DELAY << 2); + cali_saradc_desc->desc.has_data = 0; + cali_saradc_desc->desc.current_read_data_cnt = 0; + cali_saradc_desc->desc.current_sample_data_cnt = 0; + cali_saradc_desc->desc.pre_div = 0x04;//0x10; /* 26/[2*(4+1)]=2.6 < 120/[2*(16+1)]=3.53 */ + cali_saradc_desc->desc.samp_rate = 0x20; + cali_saradc_desc->desc.pData = cali_saradc_desc->buffer; + + cali_saradc_desc->handle = ddev_open(SARADC_DEV_NAME, ¶m, (UINT32)&cali_saradc_desc->desc); + if (DD_HANDLE_UNVALID == cali_saradc_desc->handle) + { + bk_printf("ddev_open(%s) failed\n", SARADC_DEV_NAME); + bk7011_cal_saradc_close(cali_saradc_desc); + cali_saradc_desc = NULL; + } + + { + INT32 value = 1; + ddev_control(cali_saradc_desc->handle, SARADC_CMD_SET_BYPASS_CALIB, &value); + } + + return cali_saradc_desc; +} + +UINT32 bk7011_cal_saradc_runorstop(cali_saradc_desc_t *cali_saradc_ptr, UINT8 run_stop) +{ + if (NULL == cali_saradc_ptr) + { + return DRV_FAILURE; + } + return ddev_control(cali_saradc_ptr->handle, SARADC_CMD_RUN_OR_STOP_ADC, (VOID *)&run_stop); +} + +UINT32 bk7011_cal_saradc_read(cali_saradc_desc_t *cali_saradc_ptr) +{ + INT32 index; + INT32 count = 20; + UINT32 sum = 0; + + delay05us(15); + for (index = 0; index < count; index++) { + sum += REG_READ(SCTRL_BASE + 0x22 * 4); + } + + return sum / count; +} + +void bk7011_cal_ready(void) +{ + rwnx_cal_load_trx_rcbekn_reg_val(); + + bk7011_cal_saradc_open(); + + bk7011_read_cal_param(); + rwnx_cal_load_default_result(); + + cpu_delay(1000); + /*step 4.2*/ + BK7231N_RC_REG.REG0x4C->bits.TXCOMPDIS = 0; + + return; +} + +void bk7011_cal_dpll(void) +{ + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_CALI_DPLL, NULL); +} + +void bk7011_update_tx_power_when_cal_dpll(int start_or_stop) +{ + extern UINT32 gtest_mode; + static UINT8 TRX_Oxc_pactrl; + static UINT32 RCB_PWTBL_0x34; + volatile UINT32 txpwr; + + if (!gtest_mode) + { + return; + } + + //bk_printf("[in] TRX_Oxc_pactrl=0x%x,RCB_PWTBL_0x34=0x%x\n", BK7231N_TRX_REG.REG0xC->value, REG_READ(RCB_POWER_TABLE_ADDR + (0x34 * 4))); + if (start_or_stop) + { + /* start */ + /* 1. save TRX_Oxc, RCB_PWTBL_0x34 */ + TRX_Oxc_pactrl = BK7231N_TRX_RAM.REG0xC.bits.pactrl; + RCB_PWTBL_0x34 = REG_READ(RCB_POWER_TABLE_ADDR + (0x34 * 4)); + /* 2. set TRX_Oxc<11:8>=0, RCB_PWTBL_0x34<31:30>=0 */ + BK7231N_TRX_RAM.REG0xC.bits.pactrl = 0x0; + REG_WRITE((RCB_POWER_TABLE_ADDR + (0x34 * 4)), RCB_PWTBL_0x34 & 0x3FFFFFFF); + } + else + { + /* stop */ + /* 3. restore TRX_Oxc, RCB_PWTBL_0x34 */ + BK7231N_TRX_RAM.REG0xC.bits.pactrl = TRX_Oxc_pactrl; + REG_WRITE((RCB_POWER_TABLE_ADDR + (0x34 * 4)), RCB_PWTBL_0x34); + } + txpwr = REG_READ(RCB_POWER_TABLE_ADDR + (0x34 * 4)); + (void)txpwr; + CAL_WR_TRXREGS(0xC); + //bk_printf("[out] TRX_Oxc_pactrl=0x%x,RCB_PWTBL_0x34=0x%x\n", BK7231N_TRX_REG.REG0xC->value, REG_READ(RCB_POWER_TABLE_ADDR + (0x34 * 4))); +} + +#define BAND_CAL_GPIO_TIMES 10 +#define BAND_CAL_ADD_STEP 8 +#define BAND_CAL_VAL_MAX 0x7FU +#define BAND_CAL_VAL_MIN 0x00U + +#define BIAS_DIFF_VAL1 (6u) +#define BIAS_DIFF_VAL2 (2u) +void bk7011_cal_bias(void) +{ + extern void bk7011_update_tx_power_when_cal_dpll(int start_or_stop); + UINT32 param, param2; + bk7011_update_tx_power_when_cal_dpll(1); + // BK7231N_TRX_RAM.REG0xF->bits.biascalmanual = 0; + param = PARAM_BIAS_CAL_MANUAL_BIT; + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_BIAS_REG_CLEAN, ¶m); + + // BK7231N_TRX_RAM.REG0xF->bits.biascaltrig = 0; + param = PARAM_BIAS_CAL_TRIGGER_BIT; + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_BIAS_REG_CLEAN, ¶m); + //trx_reg_is_write(st_TRXREG0F); + //BK7231N_TRX_REG.REG0xF->value = BK7231N_TRX_RAM.REG0xF->value; + cpu_delay(100); + // BK7231N_TRX_RAM.REG0xF->bits.biascaltrig = 1; + param = PARAM_BIAS_CAL_TRIGGER_BIT; + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_BIAS_REG_SET, ¶m); + + //trx_reg_is_write(st_TRXREG0F); + //BK7231N_TRX_REG.REG0xF->value = BK7231N_TRX_RAM.REG0xF->value; + cpu_delay(DELAY1US * 40);//40us = 30 + 10; + + //Read SYS_CTRL.REG0x4C->bias_cal_out + param = sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_BIAS_REG_READ, ¶m); + param = (param >> PARAM_BIAS_CAL_OUT_POSI) & PARAM_BIAS_CAL_OUT_MASK; + + //First, Write SYS_CTRL.REG0x4C->ldo_val_man = bias_cal_out + BIAS_DIFF_VAL1 + param += BIAS_DIFF_VAL1; + param2 = param; + if (param > 0x1f) param = 0x1f; + param = ((param & PARAM_BIAS_CAL_OUT_MASK) << PARAM_LDO_VAL_MANUAL_POSI) + | PARAM_BIAS_CAL_MANUAL_BIT; + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_BIAS_REG_WRITE, ¶m); + + //Second, Write SYS_CTRL.REG0x4C->ldo_val_man = ldo_val_man - BIAS_DIFF_VAL2 + param = param2 - BIAS_DIFF_VAL2; + if (param > 0x1f) param = 0x1f; + gcali_result.gbias_after_cal = param; + param = ((param & PARAM_BIAS_CAL_OUT_MASK) << PARAM_LDO_VAL_MANUAL_POSI) + | PARAM_BIAS_CAL_MANUAL_BIT; + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_BIAS_REG_WRITE, ¶m); + + bk7011_update_tx_power_when_cal_dpll(0); + + return; +} + +static UINT8 bandgap_calm_in_efuse = 0xFF; +static temperature_type last_temperature_type = TEMPERATURE_TYPE_UNKNOWN; /* uninitialized when power up */ +void bk7011_cal_vdddig_by_temperature(temperature_type new_temperature_type) +{ + if (new_temperature_type == last_temperature_type) + { + return; + } + + last_temperature_type = new_temperature_type; + if (gtest_mode) + { + return; + } + + bk_printf("temperature_type=%d\r\n", new_temperature_type); + if (TEMPERATURE_TYPE_LOW == new_temperature_type) + { + if ((DEVICE_ID_BK7231N_P & DEVICE_ID_MASK) == gcali_context.device_id) + { + BK7231N_TRX_RAM.REG0x4.bits.Rvco = 0x9; + } + BK7231N_TRX_RAM.REG0x4.bits.Itune_vco_spi = 0x19; + } + else if (TEMPERATURE_TYPE_HIGH == new_temperature_type) + { + if ((DEVICE_ID_BK7231N_P & DEVICE_ID_MASK) == gcali_context.device_id) + { + /* rvco 9->F by d.guo20210430 to fix dpll unlock when high temperature */ + BK7231N_TRX_RAM.REG0x4.bits.Rvco = 0xF; + BK7231N_TRX_RAM.REG0x4.bits.Itune_vco_spi = 0x1C; + } + else + { + BK7231N_TRX_RAM.REG0x4.bits.Itune_vco_spi = 0x2C; + } + } + else + { + if ((DEVICE_ID_BK7231N_P & DEVICE_ID_MASK) == gcali_context.device_id) + { + BK7231N_TRX_RAM.REG0x4.bits.Rvco = 0x9; + } + BK7231N_TRX_RAM.REG0x4.bits.Itune_vco_spi = 0x19; + } + CAL_WR_TRXREGS(0x4); +} + +void manual_cal_load_bandgap_calm(void) +{ +#define VDDIG_MAX 6 +#define VDDIG_MIN 3 + int32_t old_vddig; + int32_t new_vddig; + uint32_t analog2; + uint32_t old_bandgap_calm; + uint32_t new_bandgap_calm; + uint32_t device_id; + + bandgap_calm_in_efuse = wifi_read_efuse(17); + if ((0xFF == bandgap_calm_in_efuse) || (0x00 == bandgap_calm_in_efuse)) + { + bandgap_calm_in_efuse = 0xFF; + return; + } + CAL_PRT("bandgap_calm_in_efuse=0x%x\r\n", bandgap_calm_in_efuse); + analog2 = sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_GET_ANALOG2, &analog2); + old_bandgap_calm = (analog2 >> BANDGAP_CAL_MANUAL_POSI) & BANDGAP_CAL_MANUAL_MASK; + old_vddig = (int32_t)sctrl_ctrl(CMD_SCTRL_GET_VDD_VALUE, NULL); + new_bandgap_calm = (uint32_t)(bandgap_calm_in_efuse & 0x3F); + new_vddig = (int32_t)((bandgap_calm_in_efuse >> 6) & 0x3); + if (3 != new_vddig) + { + new_vddig += 4; + } + if ((old_bandgap_calm != new_bandgap_calm) || (old_vddig != new_vddig)) + { + /* keep vdddig and bandgap as calibrated by factory in new version */ + device_id = sctrl_ctrl(CMD_GET_DEVICE_ID, NULL); + if ((device_id == DEVICE_ID_BK7231N_B) + || (device_id == DEVICE_ID_BK7231N_C) + || (device_id == DEVICE_ID_BK7231N_D) + || (device_id == DEVICE_ID_BK7231N_E) + || (device_id == DEVICE_ID_BK7231N_F)) + { + /* keep bandgap_calm in [0x10, 0x30) */ + if ((new_bandgap_calm >= 0x30) && (new_vddig < VDDIG_MAX)) + { + new_vddig = new_vddig + 1; + new_bandgap_calm = new_bandgap_calm - 0x20; + } + else if ((new_bandgap_calm < 0x10) && (new_vddig > VDDIG_MIN)) + { + new_vddig = new_vddig - 1; + new_bandgap_calm = new_bandgap_calm + 0x20; + } + } + + if ((new_vddig < VDDIG_MIN) || (new_vddig > VDDIG_MAX)) + { + new_vddig = old_vddig; + new_bandgap_calm = (uint32_t)old_bandgap_calm; + } + + bk_printf("[load]bandgap_calm=0x%x->0x%x,vddig=%d->%d\r\n", bandgap_calm_in_efuse, new_bandgap_calm, old_vddig, new_vddig); + + analog2 &= ~(BANDGAP_CAL_MANUAL_MASK << BANDGAP_CAL_MANUAL_POSI); + analog2 |= (new_bandgap_calm << BANDGAP_CAL_MANUAL_POSI); + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_SET_ANALOG2, &analog2); + if (old_vddig != new_vddig) + { + sctrl_ctrl(CMD_SCTRL_SET_VDD_VALUE, (void *)&new_vddig); + } + } +} + +void bk7011_cal_pll(void) +{ + /*reg0x10 enrfpll = 1*/ + BK7231N_TRX_RAM.REG0x10.bits.enrfpll = 1; + BK7231N_TRX_RAM.REG0x10.bits.endpll = 1; + CAL_WR_TRXREGS(0x10); + + cpu_delay(DELAY1US * 10); +} + +void bk7011_set_rfcali_mode(int mode) +{ + if((mode != CALI_MODE_AUTO) && (mode != CALI_MODE_MANUAL)) + { + CAL_FATAL("rfcali_mode 0/1\r\n"); + return; + } + + gcali_context.cali_mode = mode; + + save_info_item(RF_CFG_MODE_ITEM, (UINT8 *)&gcali_context.cali_mode, NULL, NULL); + + os_printf("set rfcali_mode:%d\r\n", gcali_context.cali_mode); +} + +UINT32 rwnx_cal_load_user_rfcali_mode(int *rfcali_mode) +{ + #define RF_MODE_GPIO_ID (GPIO1) + #define RF_MODE_AUTOCALI_GPIO_LEVEL (0) + #define RF_MODE_MANULCALI_GPIO_LEVEL (1) + + UINT32 gpio_level, second_func, ret, mode = 0, txpwr_state; + GLOBAL_INT_DECLARATION(); + + GLOBAL_INT_DISABLE(); + /* checking RX of UART2 */ + bk_gpio_config_input_pup(RF_MODE_GPIO_ID); + + txpwr_state = manual_cal_txpwr_tab_ready_in_flash(); + + gpio_level = bk_gpio_input(RF_MODE_GPIO_ID); + + second_func = GFUNC_MODE_UART2; + gpio_ctrl(CMD_GPIO_ENABLE_SECOND, &second_func); + GLOBAL_INT_RESTORE(); + + ret = 0; + bk_printf("gpio_level=%d,txpwr_state=%d\r\n", gpio_level, txpwr_state); + if(gpio_level == (UINT32)RF_MODE_AUTOCALI_GPIO_LEVEL) + { + if(txpwr_state != TXPWR_NONE_RD) + { + mode = CALI_MODE_MANUAL; // manual rf cali + } + else + { + mode = CALI_MODE_AUTO; // auto rf cali + } + } + else if(gpio_level == (UINT32)RF_MODE_MANULCALI_GPIO_LEVEL) + { + mode = CALI_MODE_MANUAL; // manual rf cali + } + + if(rfcali_mode) + { + ret = 1; + *rfcali_mode = mode; + } + + return ret; +} + +void bk7011_get_rfcali_mode(void) +{ + int cali_mode, in_valid = 1; + GLOBAL_INT_DECLARATION(); + + GLOBAL_INT_DISABLE(); + if(get_info_item(RF_CFG_MODE_ITEM, (UINT8 *)&cali_mode, NULL, NULL)) + { + if((cali_mode == CALI_MODE_AUTO) || (cali_mode == CALI_MODE_MANUAL)) + { + gcali_context.cali_mode = cali_mode; + os_null_printf("load flash rfcali mode:%d \r\n", cali_mode); + in_valid = 0; + } + else + { + os_null_printf("rfcali_mode other:%d\r\n", cali_mode); + in_valid = 1; + } + } + + if(in_valid == 1) + { + if(rwnx_cal_load_user_rfcali_mode) + { + UINT32 is_used = rwnx_cal_load_user_rfcali_mode(&cali_mode); + if(is_used) + { + in_valid = 0; + gcali_context.cali_mode = cali_mode; + os_null_printf("user define rfcali mode:%d \r\n", cali_mode); + } + } + } + + if(in_valid == 1) + { + if(manual_cal_txpwr_tab_ready_in_flash() != TXPWR_NONE_RD) + { + // found rfcali flag in flash, turn it to manual mode + gcali_context.cali_mode = CALI_MODE_MANUAL; + in_valid = 0; + } + } + GLOBAL_INT_RESTORE(); + + os_printf("get rfcali_mode:%d\r\n", gcali_context.cali_mode); +} + +int bk7011_is_rfcali_mode_auto(void) +{ + if (CALI_MODE_UNKNOWN == gcali_context.cali_mode) + { + bk7011_get_rfcali_mode(); + } + return (gcali_context.cali_mode == CALI_MODE_AUTO) ? 1 : 0; +} + +void bk7011_set_rf_config_tssithred_b(int tssi_thred_b) +{ + if((tssi_thred_b < 0) || (tssi_thred_b > 0xffU)) + { + CAL_FATAL("b tssi range:0-255, %d\r\n", tssi_thred_b); + return; + } + + gcali_context.gtx_tssi_thred_b = tssi_thred_b; + + save_info_item(RF_CFG_TSSI_ITEM, (UINT8 *)&gcali_context.gtx_tssi_thred_b, NULL, NULL); + + os_printf("set b_tssi_thred:0x%x\r\n", gcali_context.gtx_tssi_thred_b); +} + +void bk7011_set_rf_config_tssithred_g(int tssi_thred_g) +{ + if((tssi_thred_g < 0) || (tssi_thred_g > 0xff)) + { + CAL_FATAL("g tssi range:0-255, %d\r\n", tssi_thred_g); + return; + } + + gcali_context.gtx_tssi_thred_g = tssi_thred_g; + + save_info_item(RF_CFG_TSSI_ITEM, (UINT8 *)&gcali_context.gtx_tssi_thred_g, NULL, NULL); + + os_printf("set g_tssi_thred:%d\r\n", gcali_context.gtx_tssi_thred_g); +} + +void bk7011_get_txpwr_config_reg(void) +{ + int tssi_thred; + +#if CFG_ENABLE_ATE_FEATURE + // load from flash first + if(get_info_item(RF_CFG_TSSI_ITEM, (UINT8 *)&tssi_thred, NULL, NULL)) + { + gcali_context.gtx_tssi_thred_g = tssi_thred; + os_null_printf("load flash tssi_th:g-%d \r\n", gcali_context.gtx_tssi_thred_g); + } + // otherwise check if user set default value + else +#endif + if(rwnx_cal_load_user_g_tssi_threshold) + { + UINT32 is_used = rwnx_cal_load_user_g_tssi_threshold(&tssi_thred); + if(is_used) + { + gcali_context.gtx_tssi_thred_g = tssi_thred; + os_null_printf("user define tssi_th:g-%d \r\n", gcali_context.gtx_tssi_thred_g); + } + } + +#if CFG_ENABLE_ATE_FEATURE + if(get_info_item(RF_CFG_TSSI_ITEM, (UINT8 *)&tssi_thred, NULL, NULL)) + { + gcali_context.gtx_tssi_thred_b = tssi_thred; + os_null_printf("load flash tssi_th:b-%d \r\n", gcali_context.gtx_tssi_thred_b); + } + else +#endif + if(rwnx_cal_load_user_b_tssi_threshold) + { + UINT32 is_used = rwnx_cal_load_user_b_tssi_threshold(&tssi_thred); + if(is_used) + { + gcali_context.gtx_tssi_thred_b = tssi_thred; + os_null_printf("user define tssi_th:b-%d \r\n", gcali_context.gtx_tssi_thred_b); + } + } + + os_printf("tssi_th:b-%d, g-%d\r\n", gcali_context.gtx_tssi_thred_b, gcali_context.gtx_tssi_thred_g); +} + +void bk7011_tx_cal_en(void) +{ + BK7231N_RC_REG.REG0x0->bits.forceenable = 1; + cpu_delay(1); + BK7231N_RC_REG.REG0x19->bits.FCH0EN = 1; + BK7231N_RC_REG.REG0x19->bits.FCH0SHDN = 1; + BK7231N_RC_REG.REG0x19->bits.FCH0RXEN = 0; + BK7231N_RC_REG.REG0x19->bits.FCH0TXEN = 1; + BK7231N_RC_REG.REG0x1C->bits.FRXON = 0; + BK7231N_RC_REG.REG0x1C->bits.FTXON = 1; + //BK7231N_RC_REG.REG0x4D->bits.TXSINF = 0x1A; + + //BK7011ICU.REG0x3->value = 0x00010002; + return; +} + +static INT32 bk7011_get_tx_output_power(INT32 tx_power_cal_mode, INT32 gav_tssi_temp) +{ + INT32 tssioutpower = bk7011_cal_saradc_read(cali_saradc_desc); + + if(tx_power_cal_mode == TX_WANTED_POWER_CAL) // + { + #if DIFFERENCE_PIECES_CFG + tssioutpower = tssioutpower - gcali_context.gtx_tssi_thred_g - gav_tssi_temp; + //bk_printf("tssioutpower:%d\n",tssioutpower); + #else + tssioutpower = tssioutpower - TSSI_POUT_TH_G - gav_tssi_temp; + + #endif + } + else if(tx_power_cal_mode == TX_IQ_POWER_CAL) // + { + + //tssioutpower = tssioutpower - TXIQ_IMB_TSSI_TH - gav_tssi_temp; + //tssioutpower = tssioutpower - TXIQ_IMB_TSSI_TH; + tssioutpower = abs(tssioutpower - TXIQ_IMB_TSSI_TH - gav_tssi_temp); + + } + else + { + tssioutpower = tssioutpower - TXIQ_IMB_TSSI_TH_LOOPBACK - gav_tssi_temp; + } + + + tssioutpower = abs(tssioutpower); + + return tssioutpower; +} + + +static INT32 bk7011_set_tx_pa(INT32 val1, INT32 val2, INT32 val3, INT32 val4) +{ + BK7231N_TRX_RAM.REG0xC.bits.pactrl = val1; + BK7231N_TRX_RAM.REG0xC.bits.padctrl = val2; + CAL_WR_TRXREGS(0xC); + + return 0; +} + +INT32 bk7011_cal_tx_output_power(INT32 tx_power_cal_mode) +{ + INT32 gold_index = 0; + INT32 tssilow = 0; + INT32 tssihigh = 0; + INT32 index = 0; + INT16 high, low; + INT32 gav_tssi_temp = 0; + + bk7011_cal_saradc_runorstop(cali_saradc_desc, 1); + + BK7231N_RC_REG.REG0x4C->bits.ICONSTANT = BK_TX_DAC_SIGNED_MIN; + BK7231N_RC_REG.REG0x4C->bits.QCONSTANT = BK_TX_DAC_SIGNED_MIN; + BK7231N_TRX_RAM.REG0xC.value = TRX_REG_0XC_VAL; + BK7231N_RC_REG.REG0x4C->bits.TESTPATTERN = 1; + BK7231N_RC_REG.REG0x43->bits.PRE_GAIN_2ND = 0x90;//wyg for iqpower + + if (tx_power_cal_mode == TX_WANTED_POWER_CAL) + { + BK7231N_TRX_RAM.REG0xD.value = TRX_REG_0XD_VAL; + BK7231N_TRX_RAM.REG0xA.value = TRX_REG_0XA_VAL;//by yiming 20170315; + BK7231N_TRX_RAM.REG0x0.bits.TSSIsel = 1; + BK7231N_TRX_RAM.REG0x0.bits.enDCcal = 0; + BK7231N_TRX_RAM.REG0x0.bits.enIQcal = 0; + BK7231N_TRX_RAM.REG0x0.bits.enPcal = 1; + } + else if(tx_power_cal_mode == TX_IQ_POWER_CAL) + { + BK7231N_TRX_RAM.REG0xD.value = TRX_REG_0XD_TX_IQ_VAL_GAIN_PHASE; + BK7231N_TRX_RAM.REG0xA.value = TRX_REG_0XA_VAL;//0x036F0757;//by yiming 20170315; + if ((DEVICE_ID_BK7231N_P & DEVICE_ID_MASK) == gcali_context.device_id) + { + bk7011_set_tx_pa(gi_gain_tx_pa_dgainPA30, gi_gain_tx_pa_dgainbuf30_BK7231P, 0, 8); + } + else + { + bk7011_set_tx_pa(gi_gain_tx_pa_dgainPA30, gi_gain_tx_pa_dgainbuf30, 0, 8); + } + + BK7231N_TRX_RAM.REG0x0.bits.TSSIsel = 0; + BK7231N_TRX_RAM.REG0x0.bits.enDCcal = 0; + BK7231N_TRX_RAM.REG0x0.bits.enIQcal = 1; + BK7231N_TRX_RAM.REG0x0.bits.enPcal = 0; + BK7231N_TRX_RAM.REG0x0.value =0x04238462; //second iqpower + + BK7231N_RC_REG.REG0x1A->value = BK7231N_TRX_RAM.REG0xD.value; + //BK7231N_TRX_RAM.REG0x0.bits.tssi_selrange = 0; + } + else //tx_power_cal_mode == TX_IQ_LOOPBACK_POWER_CAL + { + BK7231N_TRX_RAM.REG0xD.value = TRX_REG_0XD_TX_LOOPBACK_IQ_VAL; + BK7231N_TRX_RAM.REG0xA.value = TRX_REG_0XA_VAL;//0x036F0757;//by yiming 20170315; + bk7011_set_tx_pa(gi_gain_tx_loopback_pa_dgainPA30, gi_gain_tx_loopback_pa_dgainbuf30, 0, 8); + BK7231N_TRX_RAM.REG0x0.bits.TSSIsel = 0; + BK7231N_TRX_RAM.REG0x0.bits.enDCcal = 0; + BK7231N_TRX_RAM.REG0x0.bits.enIQcal = 1; + BK7231N_TRX_RAM.REG0x0.bits.enPcal = 0; + //BK7231N_TRX_RAM.REG0x0.bits.tssi_selrange = 0; + } + + BK7231N_TRX_RAM.REG0xD.bits.entssi = 1; + BK7231N_TRX_RAM.REG0xD.bits.entssiadc = 1;//20170503 enable TSSI + BK7231N_TRX_RAM.REG0xF.bits.tssi_cal_en = 1; + + BK7231N_TRX_RAM.REG0x12.bits.buftstselection = 3; + BK7231N_TRX_RAM.REG0x12.bits.entstbufldo = 1; + + + CAL_WR_TRXREGS(0x12); + + CAL_WR_TRXREGS(0x0); + CAL_WR_TRXREGS(0xA); + CAL_WR_TRXREGS(0xD); + BK7231N_RC_REG.REG0x1A->value = BK7231N_TRX_RAM.REG0xD.value; + CAL_WR_TRXREGS(0xC); + CAL_WR_TRXREGS(0xF); + cal_delay(150);//for reg C,D,F write spi=80/16=5M,total time is 21.6us + cal_delay(5 * gcali_context.gst_sar_adc); + + delay05us(10); + gav_tssi_temp = bk7011_cal_saradc_read(cali_saradc_desc);//Get small power tssi of each sample to remove tssi dc + + if (tx_power_cal_mode == TX_WANTED_POWER_CAL) + { + gcali_result.gav_tssi = gav_tssi_temp; + ///bk_printf("gav_tssi:%d\n",gav_tssi); + + BK7231N_RC_REG.REG0x4C->bits.ICONSTANT =BK_TX_DAC_SIGNED_MIN-0x200 ;//wyg + BK7231N_RC_REG.REG0x4C->bits.QCONSTANT = BK_TX_DAC_SIGNED_MIN-0x200 ;//wyg + BK7231N_TRX_RAM.REG0x0.bits.TSSIsel = 1; + BK7231N_TRX_RAM.REG0x0.bits.enDCcal = 0; + BK7231N_TRX_RAM.REG0x0.bits.enIQcal = 0; + BK7231N_TRX_RAM.REG0x0.bits.enPcal = 1; + //BK7231N_TRX_RAM.REG0x0.bits.tssi_selrange = 0; + } + else if(tx_power_cal_mode == TX_IQ_POWER_CAL) + { + BK7231N_RC_REG.REG0x4C->bits.ICONSTANT = BK_TX_DAC_SIGNED_MIN ; + BK7231N_RC_REG.REG0x4C->bits.QCONSTANT = BK_TX_DAC_SIGNED_MIN ; + + //bk7011_set_tx_pa(gi_gain_tx_pa_dgainPA30, gi_gain_tx_pa_dgainbuf30, 0, 8); + BK7231N_TRX_RAM.REG0x0.bits.TSSIsel = 0; + BK7231N_TRX_RAM.REG0x0.bits.enDCcal = 0; + BK7231N_TRX_RAM.REG0x0.bits.enIQcal = 1; + BK7231N_TRX_RAM.REG0x0.bits.enPcal = 0; + //BK7231N_TRX_RAM.REG0x0.bits.tssi_selrange = 0; + } + else //tx_power_cal_mode == TX_IQ_LOOPBACK_POWER_CAL + { + BK7231N_RC_REG.REG0x4C->bits.ICONSTANT = BK_TX_DAC_SIGNED_MIN + BK_TX_DAC_COEF * 0x60;//by yiming 20170315; 250 + BK7231N_RC_REG.REG0x4C->bits.QCONSTANT = BK_TX_DAC_SIGNED_MIN + BK_TX_DAC_COEF * 0x60; + bk7011_set_tx_pa(gi_gain_tx_loopback_pa_dgainPA30, gi_gain_tx_loopback_pa_dgainbuf30, 0, 8); + BK7231N_TRX_RAM.REG0x0.bits.TSSIsel = 0; + BK7231N_TRX_RAM.REG0x0.bits.enDCcal = 0; + BK7231N_TRX_RAM.REG0x0.bits.enIQcal = 1; + BK7231N_TRX_RAM.REG0x0.bits.enPcal = 0; + //BK7231N_TRX_RAM.REG0x0.bits.tssi_selrange = 0; + } + +// BK7231N_TRX_RAM.REG0x0->bits.enPcaliGm = 0; + BK7231N_TRX_RAM.REG0xF.bits.tssi_cal_en = 1; + //BK7231N_TRX_RAM.REG0xC->bits.dcorPA30 = 8; + + CAL_WR_TRXREGS(0x0); + CAL_WR_TRXREGS(0xA); + CAL_WR_TRXREGS(0xD); + BK7231N_RC_REG.REG0x1A->value = BK7231N_TRX_RAM.REG0xD.value; + CAL_WR_TRXREGS(0xF); + BK7231N_RC_REG.REG0x4C->bits.TESTPATTERN = 1; + + if(tx_power_cal_mode == TX_IQ_POWER_CAL) + { + low = 0x800;//170703,for TZH limited from 2 to 6 + high = 0x0; + + BK7231N_RC_REG.REG0x4C->bits.ICONSTANT = low; + BK7231N_RC_REG.REG0x4C->bits.QCONSTANT = low; + cal_delay(CAL_TX_NUM);//first sar dac delay needs double time + tssilow = bk7011_get_tx_output_power(tx_power_cal_mode, gav_tssi_temp); + + BK7231N_RC_REG.REG0x4C->bits.ICONSTANT = high; + BK7231N_RC_REG.REG0x4C->bits.QCONSTANT = high; + + cal_delay(CAL_TX_NUM);//first sar dac delay needs double time + + tssihigh = bk7011_get_tx_output_power(tx_power_cal_mode, gav_tssi_temp); + + do + { + if(tssilow < tssihigh) + { + index = low; + high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + + BK7231N_RC_REG.REG0x4C->bits.ICONSTANT = high; + BK7231N_RC_REG.REG0x4C->bits.QCONSTANT = high; + + tssihigh = bk7011_get_tx_output_power(tx_power_cal_mode, gav_tssi_temp); + } + else + { + index = high; + low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + + BK7231N_RC_REG.REG0x4C->bits.ICONSTANT = low; + BK7231N_RC_REG.REG0x4C->bits.QCONSTANT = low; + + tssilow = bk7011_get_tx_output_power(tx_power_cal_mode, gav_tssi_temp); + } + } + while((low - high) > 1); + index = ((tssilow < tssihigh) ? low : high); + + if (index) + { + /* index=0 cause (const_iqcal_p + UNSIGNEDOFFSET10)=0x1000 overflow, use default */ + gcali_result.const_iqcal_p=0x800-index; + } + } + + gold_index = index << 8; + cal_delay(6); + + /* restore changed registers, 20210507: except REG0xC/REG0xD to avoid large signal */ + BK7231N_TRX_RAM.REG0x0.bits.TSSIsel = 0; + BK7231N_TRX_RAM.REG0x0.bits.enIQcal = 1; + BK7231N_TRX_RAM.REG0x0.bits.enPcal = 0; + BK7231N_TRX_RAM.REG0xF.bits.tssi_cal_en = 0; + BK7231N_RC_REG.REG0x43->bits.PRE_GAIN_2ND = 0x200;// + CAL_WR_TRXREGS(0x0); + BK7231N_RC_REG.REG0x1A->value = BK7231N_TRX_RAM.REG0xD.value; + CAL_WR_TRXREGS(0xF); + + bk7011_cal_saradc_runorstop(cali_saradc_desc, 0); + + return (gold_index); +} + +static INT32 bk7011_get_tx_tssi(INT32 tssi_thred, INT32 tssi_offset) +{ + INT32 tssioutpower = bk7011_cal_saradc_read(cali_saradc_desc); + + tssioutpower = tssioutpower - tssi_thred - tssi_offset; + + tssioutpower = abs(tssioutpower); + + return tssioutpower; +} + +#define AUTO_CAL_PTR null_prf +#define AUTO_CAL_NPTR null_prf +static void bk7011_do_atuo_tx_cal_print(const char *fmt, ...) +{ + UINT32 is_on = 1; + if (rwnx_cal_is_auto_rfcali_printf_on) + { + is_on = rwnx_cal_is_auto_rfcali_printf_on(); + } + if(is_on) + { + va_list ap; + int length; + char string[128]; + + va_start(ap, fmt); + length = vsnprintf(string, sizeof(string) - 1, fmt, ap); + if (length > sizeof(string) - 1) + { + length = sizeof(string) - 1; + } + string[length] = '\0'; + va_end(ap); + bk_printf("%s", string); + } +} + +static UINT32 bk7011_do_atuo_tx_cal(UINT32 channel, UINT32 rate, INT32 tssi_thred, INT32 tssi_offset) +{ + INT32 tssilow = 0; + INT32 tssihigh = 0; + INT32 index = 0; +/// UINT32 pwr_idx; + INT16 pwr_idx_high, pwr_idx_low; + const PWR_REGS *pcfg; + + if ((channel < 1) || (channel > 14)) + { + AUTO_CAL_NPTR("wrong channel:%d\r\n", channel); + return 16; + } + else + { + AUTO_CAL_NPTR("\r\n ******** do chan:%d ********\r\n", channel); + if (channel != 14) + { + BK7231N_TRX_RAM.REG0x5.bits.chspi = 12 + 5 * (channel - 1); + } + else + { + BK7231N_TRX_RAM.REG0x5.bits.chspi = 84; + } + } + + // do for channel + CAL_WR_TRXREGS(0x5); + delay100us(1); + + pwr_idx_low = 0x000; + + if (EVM_DEFUALT_B_RATE == rate) + { + pcfg = cfg_tab_b; + pwr_idx_high = TCP_PAMAP_TAB_B_LEN - 1; + } + else + { + pcfg = cfg_tab_g; + pwr_idx_high = TCP_PAMAP_TAB_G_LEN - 1; + } + + BK7231N_RC_REG.REG0x43->bits.PRE_GAIN_2ND = (pcfg[pwr_idx_low].pregain & 0x3FF); + cal_delay(CAL_TX_NUM);//first sar dac delay needs double time + tssilow = bk7011_get_tx_tssi(tssi_thred, tssi_offset); + CAL_WR_TRXREGS(0xC); + + BK7231N_RC_REG.REG0x43->bits.PRE_GAIN_2ND = (pcfg[pwr_idx_high].pregain & 0x3FF); + + cal_delay(CAL_TX_NUM);//first sar dac delay needs double time + + tssihigh = bk7011_get_tx_tssi(tssi_thred, tssi_offset); + AUTO_CAL_PTR("pwr_gain_low[%d]=0x%x,pwr_gain_high[%d]=0x%x,tssilow=0x%x,tssihigh=0x%x\n", pwr_idx_low, pcfg[pwr_idx_low].pregain, pwr_idx_high, pcfg[pwr_idx_high].pregain, tssilow, tssihigh); + do + { + if (tssilow < tssihigh) + { + if (tssilow <= 3) + { + break; + } + index = ((pwr_idx_high-pwr_idx_low) >> 3); + if (0 == index) + { + index = 1; + } + pwr_idx_high -= index; + + BK7231N_RC_REG.REG0x43->bits.PRE_GAIN_2ND = (pcfg[pwr_idx_high].pregain & 0x3FF); + + tssihigh = bk7011_get_tx_tssi(tssi_thred, tssi_offset); + } + else + { + if (tssihigh <= 3) + { + break; + } + index = ((pwr_idx_high-pwr_idx_low) >> 3); + if (0 == index) + { + index = 1; + } + pwr_idx_low += index; + + BK7231N_RC_REG.REG0x43->bits.PRE_GAIN_2ND = (pcfg[pwr_idx_low].pregain & 0x3FF); + + tssilow = bk7011_get_tx_tssi(tssi_thred, tssi_offset); + } + AUTO_CAL_PTR("pwr_gain_low[%d]=0x%x,pwr_gain_high[%d]=0x%x,tssilow=0x%x,tssihigh=0x%x\n", pwr_idx_low, pcfg[pwr_idx_low].pregain, pwr_idx_high, pcfg[pwr_idx_high].pregain, tssilow, tssihigh); + } + while ((pwr_idx_high-pwr_idx_low) > 1); + index = ((tssilow < tssihigh) ? pwr_idx_low : pwr_idx_high); + bk7011_do_atuo_tx_cal_print("rate=%d,channel=%d,tssi_thred=0x%x,tssi_offset=0x%x,index=%d\n", rate, channel, tssi_thred, tssi_offset, index); + + return (index); +} + +INT32 bk7011_cal_auto_tx_power(void) +{ + extern UINT32 g_dif_g_n40; + extern void manual_cal_11b_2_ble(void); + UINT32 channel, rate, pwr_idx, tssi_thred; + INT32 tssi_offset; + INT32 tssi_index; + UINT32 tssi_sum = 0; + + bk7011_cal_saradc_runorstop(cali_saradc_desc, 1); + + BK7231N_RC_REG.REG0x4C->bits.TESTPATTERN = 1; + BK7231N_RC_REG.REG0x1A->value = BK7231N_TRX_RAM.REG0xD.value; + + // tx chanin gain setting + BK7231N_TRX_RAM.REG0xD.value = TRX_REG_0XD_VAL; + BK7231N_TRX_RAM.REG0xA.value = 0x8063DDFF;//by yg 20200915; + BK7231N_TRX_RAM.REG0xC.value = TRX_REG_0XC_VAL;//; + BK7231N_TRX_RAM.REG0x0.bits.TSSIsel = 1; + BK7231N_TRX_RAM.REG0x0.bits.enDCcal = 0; + BK7231N_TRX_RAM.REG0x0.bits.enIQcal = 0; + BK7231N_TRX_RAM.REG0x0.bits.enPcal = 1; + BK7231N_TRX_RAM.REG0x0.value = 0x528826F; + + BK7231N_TRX_RAM.REG0xD.bits.entssi = 1; + BK7231N_TRX_RAM.REG0xD.bits.entssiadc = 1;//20170503 enable TSSI + BK7231N_TRX_RAM.REG0xF.bits.tssi_cal_en = 1; + BK7231N_TRX_RAM.REG0x12.bits.buftstselection = 3; + BK7231N_TRX_RAM.REG0x12.bits.entstbufldo = 1; + + CAL_WR_TRXREGS(0x0); + CAL_WR_TRXREGS(0xA); + CAL_WR_TRXREGS(0xC); + CAL_WR_TRXREGS(0xD); + CAL_WR_TRXREGS(0xF); + CAL_WR_TRXREGS(0x12); + cal_delay(150);//for reg C,D,F write spi=80/16=5M,total time is 21.6us + cal_delay(5 * gcali_context.gst_sar_adc); + + // Set tssi offset + BK7231N_RC_REG.REG0x4C->bits.ICONSTANT = BK_TX_DAC_SIGNED_MIN ;///0x200; + BK7231N_RC_REG.REG0x4C->bits.QCONSTANT = BK_TX_DAC_SIGNED_MIN ;///0x200; + BK7231N_RC_REG.REG0x43->bits.PRE_GAIN_2ND = 0x0;// + for (tssi_index = 0; tssi_index < 20; tssi_index++) + { + tssi_sum += bk7011_cal_saradc_read(cali_saradc_desc);//Get small power tssi of each sample to remove tssi dc + } + tssi_offset = tssi_sum / tssi_index; + + // tx sinewave setting + rate = EVM_DEFUALT_RATE; + tssi_thred = gcali_context.gtx_tssi_thred_g; + BK7231N_RC_REG.REG0x4C->bits.ICONSTANT = 0x627; + BK7231N_RC_REG.REG0x4C->bits.QCONSTANT = 0x627; + + /* add 4db power gain for 11g */ + channel = 1; + pwr_idx = bk7011_do_atuo_tx_cal(channel, rate, tssi_thred, tssi_offset); + pwr_idx += POWER_TABLE_11G_1DB_STEP * POWER_CALI_11G_SHIFT; + manual_cal_save_txpwr(rate, channel, pwr_idx); + pwr_idx = (pwr_idx > g_dif_g_n40) ? (pwr_idx - g_dif_g_n40) : 0; + manual_cal_save_txpwr(135, 3, pwr_idx); + + channel = 7; + pwr_idx = bk7011_do_atuo_tx_cal(channel, rate, tssi_thred, tssi_offset); + pwr_idx += POWER_TABLE_11G_1DB_STEP * POWER_CALI_11G_SHIFT; + manual_cal_save_txpwr(rate, channel, pwr_idx); + pwr_idx = (pwr_idx > g_dif_g_n40) ? (pwr_idx - g_dif_g_n40) : 0; + manual_cal_save_txpwr(135, 7, pwr_idx); + + channel = 13; + pwr_idx = bk7011_do_atuo_tx_cal(channel, rate, tssi_thred, tssi_offset); + pwr_idx += POWER_TABLE_11G_1DB_STEP * POWER_CALI_11G_SHIFT; + manual_cal_save_txpwr(rate, channel, pwr_idx); + pwr_idx = (pwr_idx > g_dif_g_n40) ? (pwr_idx - g_dif_g_n40) : 0; + manual_cal_save_txpwr(135, 11, pwr_idx); + + rate = EVM_DEFUALT_B_RATE; + tssi_thred = gcali_context.gtx_tssi_thred_b; + BK7231N_RC_REG.REG0x4C->bits.ICONSTANT = 0x380; + BK7231N_RC_REG.REG0x4C->bits.QCONSTANT = 0x380; + + /* add 2db power gain for 11b */ + channel = 1; + pwr_idx = bk7011_do_atuo_tx_cal(channel, rate, tssi_thred, tssi_offset); + manual_cal_save_txpwr(rate, channel, pwr_idx + POWER_TABLE_11B_1DB_STEP * POWER_CALI_11B_SHIFT); + + channel = 7; + pwr_idx = bk7011_do_atuo_tx_cal(channel, rate, tssi_thred, tssi_offset); + manual_cal_save_txpwr(rate, channel, pwr_idx + POWER_TABLE_11B_1DB_STEP * POWER_CALI_11B_SHIFT); + + channel = 13; + pwr_idx = bk7011_do_atuo_tx_cal(channel, rate, tssi_thred, tssi_offset); + manual_cal_save_txpwr(rate, channel, pwr_idx + POWER_TABLE_11B_1DB_STEP * POWER_CALI_11B_SHIFT); + + manual_cal_11b_2_ble(); + + manual_cal_fitting_txpwr_tab(); + + // exit, recover setting + BK7231N_TRX_RAM.REG0x0.bits.TSSIsel = 0; + BK7231N_TRX_RAM.REG0x0.bits.enIQcal = 1; + BK7231N_TRX_RAM.REG0x0.bits.enPcal = 0; + BK7231N_TRX_RAM.REG0xC.value = TRX_REG_0XC_VAL; + BK7231N_TRX_RAM.REG0xD.value = TRX_REG_0XD_VAL; + BK7231N_TRX_RAM.REG0xF.bits.tssi_cal_en = 0; + CAL_WR_TRXREGS(0x0); + CAL_WR_TRXREGS(0xC); + CAL_WR_TRXREGS(0xD); + CAL_WR_TRXREGS(0xF); + + BK7231N_RC_REG.REG0x1A->value = BK7231N_TRX_RAM.REG0xD.value; + BK7231N_RC_REG.REG0x43->bits.PRE_GAIN_2ND = 0x200; + BK7231N_RC_REG.REG0x4C->bits.TESTPATTERN = 0; + + bk7011_cal_saradc_runorstop(cali_saradc_desc, 0); + + return 0; +} + +void bk7011_set_const_iqcal_p(INT32 const_iqcal_p) +{ + gcali_result.const_iqcal_p = const_iqcal_p; +} + +void bk7011_micopwr_config_tssi_read_prepare(void) +{ + //BK7231N_TRX_RAM.REG0x0.bits.TSSIsel = 1; + BK7231N_TRX_RAM.REG0x0.bits.enDCcal = 0; + BK7231N_TRX_RAM.REG0x0.bits.enIQcal = 0; + BK7231N_TRX_RAM.REG0x0.bits.enPcal = 1; + BK7231N_TRX_RAM.REG0xD.bits.entssi = 1; + //BK7231N_TRX_RAM.REG0xF.bits.tssi_cal_en = 1; + + BK7231N_TRX_RAM.REG0x12.bits.buftstselection = 3; + BK7231N_TRX_RAM.REG0x12.bits.entstbufldo = 1; + + CAL_WR_TRXREGS(0x0); + CAL_WR_TRXREGS(0xD); + BK7231N_RC_REG.REG0x1A->value = BK7231N_TRX_RAM.REG0xD.value; + //CAL_WR_TRXREGS(0xF); + CAL_WR_TRXREGS(0x12); +} + +static INT32 bk7011_update_tx_power(void) +{ + bk7011_set_tx_pa(gi_dc_tx_pa_dgainPA30, gi_dc_tx_pa_dgainbuf30, 0, 8); + return 0; +} + +static INT32 bk7011_update_tx_loopback_power(void) +{ + bk7011_set_tx_pa(gi_dc_tx_loopback_pa_dgainPA30, gi_dc_tx_loopback_pa_dgainbuf30, 0, 8); + return 0; +} + +static INT32 bk7011_get_tx_dc(void) +{ + return bk7011_cal_saradc_read(cali_saradc_desc); +} + +INT32 bk7011_cal_tx_dc_new(INT32 tx_dc_cal_mode) +{ + INT32 detect_dc_low = 0; + INT32 detect_dc_high = 0; + INT16 high, low; + INT32 gold_index = 0; + INT32 i_index, q_index; + INT16 search_thrd = 64 * BK_TX_DAC_COEF;//128;//DC search range search_thrd=512 gtx_dc_n=3, search_thrd=256 gtx_dc_n=2, search_thrd=128 gtx_dc_n=1 + + bk7011_cal_saradc_runorstop(cali_saradc_desc, 1); + + BK7231N_TRX_RAM.REG0x7.bits.txif_2rd = 0x0; + BK7231N_TRX_RAM.REG0x7.bits.abws_en = 0x0; + BK7231N_TRX_RAM.REG0xD.bits.entssi = 1; + BK7231N_TRX_RAM.REG0x12.bits.buftstselection = 3; + BK7231N_TRX_RAM.REG0x12.bits.entstbufldo = 1; + BK7231N_RC_REG.REG0x43->bits.PRE_GAIN_2ND = 0x200; + + CAL_WR_TRXREGS(0x7); + CAL_WR_TRXREGS(0xD); + BK7231N_RC_REG.REG0x1A->value = BK7231N_TRX_RAM.REG0xD.value; + CAL_WR_TRXREGS(0x12); + if(tx_dc_cal_mode == TX_DC_CAL) + { + BK7231N_TRX_RAM.REG0xD.value = TRX_REG_0XD_TX_IQ_VAL; //BK7011TRXREG0xD;// + CAL_WR_TRXREGS(0xD); + BK7231N_RC_REG.REG0x1A->value = BK7231N_TRX_RAM.REG0xD.value; + bk7011_update_tx_power(); + } + else if (tx_dc_cal_mode == TX_DC_CAL_IQ) + { + BK7231N_TRX_RAM.REG0xD.value = TRX_REG_0XD_TX_IQ_VAL; //BK7011TRXREG0xD;// + CAL_WR_TRXREGS(0xD); + BK7231N_RC_REG.REG0x1A->value = BK7231N_TRX_RAM.REG0xD.value; + bk7011_update_tx_power(); + + } + else if (tx_dc_cal_mode == TX_DC_LOOPBACK_CAL_IQ) + { + BK7231N_TRX_RAM.REG0xD.value = TRX_REG_0XD_TX_LOOPBACK_IQ_VAL; + CAL_WR_TRXREGS(0xD); + BK7231N_RC_REG.REG0x1A->value = BK7231N_TRX_RAM.REG0xD.value; + bk7011_update_tx_loopback_power(); + } + + if(tx_dc_cal_mode == TX_DC_CAL) + { + CAL_PRT("\r\nbk7011_cal_tx_dc: \r\n"); + } + if(tx_dc_cal_mode == TX_DC_CAL_IQ) + { + CAL_PRT("\r\nbk7011_cal_tx_dc_iq: \r\n"); + } + else if (tx_dc_cal_mode == TX_DC_LOOPBACK_CAL_IQ) + { + CAL_PRT("\r\nbk7011_cal_tx_loopback_dc_iq: \r\n"); + } + CAL_PRT("pactrl = %d\r\n", BK7231N_TRX_RAM.REG0xC.bits.pactrl ); + CAL_PRT("padctrl =%d\r\n", BK7231N_TRX_RAM.REG0xC.bits.padctrl); + //[-512 511]---->[0,BK_TX_DAC_UNSIGNED_MASK]; + + //20170330 + BK7231N_RC_REG.REG0x4F->bits.TXIDCCOMP = 0x800;//wyg + BK7231N_RC_REG.REG0x4F->bits.TXQDCCOMP = 0x800;//wyg + BK7231N_RC_REG.REG0x50->bits.TXIGAINCOMP=0xfff;//wyg + BK7231N_RC_REG.REG0x50->bits.TXQGAINCOMP=0xfff;//wyg + BK7231N_RC_REG.REG0x51->bits.TXPHASECOMP = 0x800;//wyg + BK7231N_RC_REG.REG0x51->bits.TXTY2 = 0x800;//wyg + + BK7231N_RC_REG.REG0x4C->bits.ICONSTANT = UNSIGNEDOFFSET10 - 1; + BK7231N_RC_REG.REG0x4C->bits.QCONSTANT = UNSIGNEDOFFSET10 - 1 ; + BK7231N_RC_REG.REG0x4C->bits.TESTPATTERN = 1; + + BK7231N_TRX_RAM.REG0x0.bits.enDCcal = 1; + //BK7231N_TRX_RAM.REG0x0->bits.tssi_selrange = 1;//inverse 20141014 + //BK7231N_TRX_RAM.REG0x0->bits.tssi_statectrl = 1; + BK7231N_TRX_RAM.REG0x0.bits.enIQcal = 0; + BK7231N_TRX_RAM.REG0x0.bits.enPcal = 0; + BK7231N_TRX_RAM.REG0x0.bits.tssiDC_gc = 0;//wyg + BK7231N_TRX_RAM.REG0xF.bits.tssi_cal_en = 1; + //20170330 + BK7231N_TRX_RAM.REG0xC.bits.pamapen = 0; + + BK7231N_TRX_RAM.REG0x5.bits.chspi = 5; + CAL_WR_TRXREGS(0x5); + + CAL_WR_TRXREGS(0x0); + CAL_WR_TRXREGS(0xC); + CAL_WR_TRXREGS(0xF); + cal_delay(CAL_TX_NUM);//first sar dac delay needs double time + +if (1) //fix default Q, calibrate I +{ + // I DC calibration; + BK7231N_RC_REG.REG0x4F->bits.TXQDCCOMP = UNSIGNEDOFFSET10 + 0; //default + + if(tx_dc_cal_mode == TX_DC_CAL) + { + low = UNSIGNEDOFFSET10 - MINOFFSET ; + high = UNSIGNEDOFFSET10 + MINOFFSET ; + } + else if (tx_dc_cal_mode == TX_DC_CAL_IQ) + { + low = UNSIGNEDOFFSET10 - MINOFFSET ; + high = UNSIGNEDOFFSET10 + MINOFFSET ; + } + else if (tx_dc_cal_mode == TX_DC_LOOPBACK_CAL_IQ) + { + low = UNSIGNEDOFFSET10 - 3 * MINOFFSET ; + high = UNSIGNEDOFFSET10 + 3 * MINOFFSET ; + } + else + { + low = BK7231N_RC_REG.REG0x4F->bits.TXIDCCOMP; + high = BK7231N_RC_REG.REG0x4F->bits.TXIDCCOMP; + } + BK7231N_RC_REG.REG0x4F->bits.TXIDCCOMP = low; + + detect_dc_low = bk7011_get_tx_dc(); + + + BK7231N_RC_REG.REG0x4F->bits.TXIDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + //Step 1 3~6 search; + + CAL_TIM_PRT("%d:(low=0x%x) detect_dc_low=%d,(high=0x%x) detect_dc_high=%d\n", __LINE__, low, detect_dc_low, high, detect_dc_high); + + if (detect_dc_low < detect_dc_high) + { + high = BK_TX_DAC_SIGNED_MAX; + low = high - search_thrd; + } + else + { + low = BK_TX_DAC_SIGNED_MIN; + high = low + search_thrd; + } + + BK7231N_RC_REG.REG0x4F->bits.TXIDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + BK7231N_RC_REG.REG0x4F->bits.TXIDCCOMP = low; + detect_dc_low = bk7011_get_tx_dc(); + + CAL_TIM_PRT("%d:(low=0x%x) detect_dc_low=%d,(high=0x%x) detect_dc_high=%d\n", __LINE__, low, detect_dc_low, high, detect_dc_high); + do + { + if(detect_dc_low < detect_dc_high) + { + high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7231N_RC_REG.REG0x4F->bits.TXIDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + + } + else + { + low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7231N_RC_REG.REG0x4F->bits.TXIDCCOMP = low; + detect_dc_low = bk7011_get_tx_dc(); + } + CAL_TIM_PRT("%d:(low=0x%x) detect_dc_low=%d,(high=0x%x) detect_dc_high=%d\n", __LINE__, low, detect_dc_low, high, detect_dc_high); + } + while((high - low) > 1); + i_index = ((detect_dc_low < detect_dc_high) ? low : high); +} + +if (2) //fix calibrated I, calibrated Q +{ + // Q DC calibration; + //Step 1 3~6 search; + if ((tx_dc_cal_mode == TX_DC_CAL) || (tx_dc_cal_mode == TX_DC_CAL_IQ)) + { + low = UNSIGNEDOFFSET10 - MINOFFSET ; + high = UNSIGNEDOFFSET10 + MINOFFSET ; + } + else if (tx_dc_cal_mode == TX_DC_LOOPBACK_CAL_IQ) + { + low = UNSIGNEDOFFSET10 - 3 * MINOFFSET ; + high = UNSIGNEDOFFSET10 + 3 * MINOFFSET ; + } + + //20170330 + BK7231N_RC_REG.REG0x4F->bits.TXIDCCOMP = i_index; //default + + BK7231N_RC_REG.REG0x4F->bits.TXQDCCOMP = low; + detect_dc_low = bk7011_get_tx_dc(); + + + BK7231N_RC_REG.REG0x4F->bits.TXQDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + + CAL_TIM_PRT("%d:(low=0x%x) detect_dc_low=%d,(high=0x%x) detect_dc_high=%d\n", __LINE__, low, detect_dc_low, high, detect_dc_high); + if(detect_dc_low < detect_dc_high) + { + + high = BK_TX_DAC_SIGNED_MAX; + low = high - search_thrd; + } + else + { + low = BK_TX_DAC_SIGNED_MIN; + high = low + search_thrd; + } + + BK7231N_RC_REG.REG0x4F->bits.TXQDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + BK7231N_RC_REG.REG0x4F->bits.TXQDCCOMP = low; + detect_dc_low = bk7011_get_tx_dc(); + + CAL_TIM_PRT("%d:(low=0x%x) detect_dc_low=%d,(high=0x%x) detect_dc_high=%d\n", __LINE__, low, detect_dc_low, high, detect_dc_high); + do + { + if(detect_dc_low < detect_dc_high) + { + high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7231N_RC_REG.REG0x4F->bits.TXQDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + + } + else + { + low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7231N_RC_REG.REG0x4F->bits.TXQDCCOMP = low; + detect_dc_low = bk7011_get_tx_dc(); + } + CAL_TIM_PRT("%d:(low=0x%x) detect_dc_low=%d,(high=0x%x) detect_dc_high=%d\n", __LINE__, low, detect_dc_low, high, detect_dc_high); + } + while((high - low) > 1); + q_index = ((detect_dc_low < detect_dc_high) ? low : high); +} + + if (3) //fix calibrated Q, calibrated I again + { + // 2nd I DC calibration; + //Step 1 3~6 search; + if ((tx_dc_cal_mode == TX_DC_CAL) || (tx_dc_cal_mode == TX_DC_CAL_IQ)) + { + low = UNSIGNEDOFFSET10 - MINOFFSET ; + high = UNSIGNEDOFFSET10 + MINOFFSET ; + } + else// (tx_dc_cal_mode == TX_DC_LOOPBACK_CAL_IQ) + { + low = UNSIGNEDOFFSET10 - 3 * MINOFFSET ; + high = UNSIGNEDOFFSET10 + 3 * MINOFFSET ; + } + + BK7231N_TRX_RAM.REG0x0.bits.tssiDC_gc = 3;//wyg + CAL_WR_TRXREGS(0x0); + BK7231N_RC_REG.REG0x4F->bits.TXQDCCOMP = q_index; // optimum + + BK7231N_RC_REG.REG0x4F->bits.TXIDCCOMP = low; + detect_dc_low = bk7011_get_tx_dc(); + + + BK7231N_RC_REG.REG0x4F->bits.TXIDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + + CAL_TIM_PRT("%d:(low=0x%x) detect_dc_low=%d,(high=0x%x) detect_dc_high=%d\n", __LINE__, low, detect_dc_low, high, detect_dc_high); + + if(detect_dc_low < detect_dc_high) + { + high = BK_TX_DAC_SIGNED_MAX; + low = high - search_thrd; + } + else + { + low = BK_TX_DAC_SIGNED_MIN; + high = low + search_thrd; + } + + BK7231N_RC_REG.REG0x4F->bits.TXIDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + BK7231N_RC_REG.REG0x4F->bits.TXIDCCOMP = low; + detect_dc_low = bk7011_get_tx_dc(); + + CAL_TIM_PRT("%d:adc(0x%x)=%d,adc(0x%x)=%d\n", __LINE__, low, detect_dc_low, high, detect_dc_high); + do + { + if(detect_dc_low < detect_dc_high) + { + high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7231N_RC_REG.REG0x4F->bits.TXIDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + } + else + { + low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7231N_RC_REG.REG0x4F->bits.TXIDCCOMP = low; + detect_dc_low = bk7011_get_tx_dc(); + } + CAL_TIM_PRT("%d:(low=0x%x) detect_dc_low=%d,(high=0x%x) detect_dc_high=%d\n", __LINE__, low, detect_dc_low, high, detect_dc_high); + } + while((high - low) > 1); + i_index = ((detect_dc_low < detect_dc_high) ? low : high); + } + + if(tx_dc_cal_mode == TX_DC_CAL) + { + gcali_result.gtx_i_dc_comp = i_index ;//190614 I compensate + CAL_PRT("gtx_i_dc_comp:0x%x\r\n", gcali_result.gtx_i_dc_comp); + } + else if(tx_dc_cal_mode == TX_DC_CAL_IQ) + { + gcali_result.gtx_i_dc_comp = i_index; + CAL_PRT("gtx_i_dc_comp_iq:0x%x\r\n", gcali_result.gtx_i_dc_comp); + } + else if (tx_dc_cal_mode == TX_DC_LOOPBACK_CAL_IQ) + { + gcali_result.gtx_i_dc_comp_loopback = i_index; + CAL_PRT("gtx_i_dc_comp_loopback_iq:0x%x\r\n", gcali_result.gtx_i_dc_comp_loopback); + } + + if(tx_dc_cal_mode == TX_DC_CAL) + { + gcali_result.gtx_q_dc_comp = q_index ;//190614 Q compensate + CAL_PRT("gtx_q_dc_comp:0x%x\r\n", gcali_result.gtx_q_dc_comp); + } + else if(tx_dc_cal_mode == TX_DC_CAL_IQ) + { + gcali_result.gtx_q_dc_comp = q_index; + CAL_PRT("gtx_q_dc_comp_iq:0x%x\r\n", gcali_result.gtx_q_dc_comp); + } + else if (tx_dc_cal_mode == TX_DC_LOOPBACK_CAL_IQ) + { + gcali_result.gtx_q_dc_comp_loopback = q_index; + CAL_PRT("gtx_q_dc_comp_loopback_iq:0x%x\r\n", gcali_result.gtx_q_dc_comp_loopback); + } + + gold_index = q_index + (i_index << 16); + + /* restore changed registers */ + BK7231N_TRX_RAM.REG0x0.bits.enIQcal = 1; + BK7231N_TRX_RAM.REG0x0.bits.enDCcal = 0; + BK7231N_TRX_RAM.REG0x5.bits.chspi = 0; + BK7231N_TRX_RAM.REG0xC.bits.padctrl = 0xC; + BK7231N_TRX_RAM.REG0xD.value = TRX_REG_0XD_VAL; + BK7231N_TRX_RAM.REG0xF.bits.tssi_cal_en = 0; + + CAL_WR_TRXREGS(0x0); + CAL_WR_TRXREGS(0x5); + CAL_WR_TRXREGS(0xC); + CAL_WR_TRXREGS(0xD); + BK7231N_RC_REG.REG0x1A->value = BK7231N_TRX_RAM.REG0xD.value; + CAL_WR_TRXREGS(0xF); + + bk7011_cal_saradc_runorstop(cali_saradc_desc, 0); + + return gold_index; +} + +#define TSSI_RD_TIMES 1//8 +INT32 bk7011_get_tx_i_gain(void) +{ + INT32 detector_i_gain_p, detector_i_gain_n, detector_i_gain; + + BK7231N_RC_REG.REG0x4C->bits.ICONSTANT = UNSIGNEDOFFSET10 + (gcali_result.const_iqcal_p+0x100); + BK7231N_RC_REG.REG0x4C->bits.QCONSTANT = UNSIGNEDOFFSET10 + 0; + detector_i_gain_p = bk7011_cal_saradc_read(cali_saradc_desc) * TSSI_RD_TIMES; + + BK7231N_RC_REG.REG0x4C->bits.ICONSTANT = UNSIGNEDOFFSET10 - (gcali_result.const_iqcal_p+0x100);//wyg + BK7231N_RC_REG.REG0x4C->bits.QCONSTANT = UNSIGNEDOFFSET10 + 0;//wyg + detector_i_gain_n = bk7011_cal_saradc_read(cali_saradc_desc) * TSSI_RD_TIMES;//wyg + + detector_i_gain = detector_i_gain_p + detector_i_gain_n; + + return detector_i_gain; +} + +INT32 bk7011_get_tx_q_gain(void) +{ + INT32 detector_q_gain_p, detector_q_gain_n, detector_q_gain; + + BK7231N_RC_REG.REG0x4C->bits.ICONSTANT = UNSIGNEDOFFSET10 + 0; + BK7231N_RC_REG.REG0x4C->bits.QCONSTANT = UNSIGNEDOFFSET10 + (gcali_result.const_iqcal_p+0x100); + detector_q_gain_p = bk7011_cal_saradc_read(cali_saradc_desc) * TSSI_RD_TIMES; + + BK7231N_RC_REG.REG0x4C->bits.ICONSTANT = UNSIGNEDOFFSET10 + 0;//wyg + BK7231N_RC_REG.REG0x4C->bits.QCONSTANT = UNSIGNEDOFFSET10 - (gcali_result.const_iqcal_p+0x100);//wyg + detector_q_gain_n = bk7011_cal_saradc_read(cali_saradc_desc) * TSSI_RD_TIMES;//wyg + + detector_q_gain = detector_q_gain_p + detector_q_gain_n; + + return detector_q_gain; +} + +INT32 bk7011_get_tx_i_phase(void) +{ + INT32 detector_i_phase_n, detector_i_phase_p, detector_i_phase; + + + BK7231N_RC_REG.REG0x4C->bits.ICONSTANT = UNSIGNEDOFFSET10 + gcali_result.const_iqcal_p; + BK7231N_RC_REG.REG0x4C->bits.QCONSTANT = UNSIGNEDOFFSET10 - gcali_result.const_iqcal_p; + detector_i_phase_p = bk7011_cal_saradc_read(cali_saradc_desc) * TSSI_RD_TIMES; + + BK7231N_RC_REG.REG0x4C->bits.ICONSTANT = UNSIGNEDOFFSET10 - (gcali_result.const_iqcal_p); + BK7231N_RC_REG.REG0x4C->bits.QCONSTANT = UNSIGNEDOFFSET10 + (gcali_result.const_iqcal_p); + detector_i_phase_n = bk7011_cal_saradc_read(cali_saradc_desc) * TSSI_RD_TIMES; + + detector_i_phase = detector_i_phase_p + detector_i_phase_n;//wyg + + return detector_i_phase; +} + +INT32 bk7011_get_tx_q_phase(void) +{ + INT32 detector_q_phase_n, detector_q_phase_p, detector_q_phase; + + BK7231N_RC_REG.REG0x4C->bits.ICONSTANT = UNSIGNEDOFFSET10 + gcali_result.const_iqcal_p; + BK7231N_RC_REG.REG0x4C->bits.QCONSTANT = UNSIGNEDOFFSET10 + gcali_result.const_iqcal_p; + detector_q_phase_p = bk7011_cal_saradc_read(cali_saradc_desc) * TSSI_RD_TIMES; + + BK7231N_RC_REG.REG0x4C->bits.ICONSTANT = UNSIGNEDOFFSET10 - (gcali_result.const_iqcal_p); + BK7231N_RC_REG.REG0x4C->bits.QCONSTANT = UNSIGNEDOFFSET10 - (gcali_result.const_iqcal_p); + detector_q_phase_n = bk7011_cal_saradc_read(cali_saradc_desc) * TSSI_RD_TIMES; + + detector_q_phase = detector_q_phase_p + detector_q_phase_n;//wyg + + return detector_q_phase; +} + +static INT32 bk7011_get_rx_i_avg_signed(void) +{ + INT32 val; + val = BK7231N_RC_REG.REG0x3C->bits.RXAVGIRD; + + return val; +} + +static INT32 bk7011_get_rx_q_avg_signed(void) +{ + INT32 val; + + val = BK7231N_RC_REG.REG0x3C->bits.RXAVGQRD; + + return val; +} + +INT32 bk7011_cal_tx_gain_imbalance(INT32 tx_gain_imb_cal_mode) +{ + INT32 detect_gain_low = 0; + INT32 detect_gain_high = 0; + INT16 high, low; + INT32 index = 0, gold_index = 0; + INT32 detector_i_gain; + INT32 detector_q_gain; + + bk7011_cal_saradc_runorstop(cali_saradc_desc, 1); + BK7231N_RC_REG.REG0x50->bits.TXIGAINCOMP = BK_TX_DAC_UNSIGNED_MASK_GAIN;//1023; + BK7231N_RC_REG.REG0x50->bits.TXQGAINCOMP = BK_TX_DAC_UNSIGNED_MASK_GAIN;//1023; + BK7231N_RC_REG.REG0x4C->bits.TESTPATTERN = 1; + + + BK7231N_TRX_RAM.REG0xD.bits.entssi = 1; + //BK7231N_TRX_RAM.REG0xF.bits.tssi_cal_en = 1; + BK7231N_TRX_RAM.REG0x12.bits.buftstselection = 3; + BK7231N_TRX_RAM.REG0x12.bits.entstbufldo = 1; + + CAL_WR_TRXREGS(0xD); + BK7231N_RC_REG.REG0x1A->value = BK7231N_TRX_RAM.REG0xD.value; + //CAL_WR_TRXREGS(0xF); + CAL_WR_TRXREGS(0x12); + + BK7231N_TRX_RAM.REG0x0.bits.TSSIsel = 0; + BK7231N_TRX_RAM.REG0x0.bits.enDCcal = 0; + BK7231N_TRX_RAM.REG0x0.bits.tssiIQ_gc = 0; + BK7231N_TRX_RAM.REG0x0.bits.enIQcal = 1; + BK7231N_TRX_RAM.REG0x0.bits.enPcal = 0; +// BK7231N_TRX_RAM.REG0x0.bits.enPcaliGm = 0; + + BK7231N_TRX_RAM.REG0xF.bits.tssi_cal_en = 1; + BK7231N_TRX_RAM.REG0xD.bits.entxsw= 0; + BK7231N_TRX_RAM.REG0xC.bits.padctrl= 0x1; + BK7231N_TRX_RAM.REG0xC.bits.pactrl= 1; + BK7231N_RC_REG.REG0x43->bits.PRE_GAIN_2ND = 0x90; + CAL_WR_TRXREGS(0x0); + CAL_WR_TRXREGS(0xC); + CAL_WR_TRXREGS(0xD); + BK7231N_RC_REG.REG0x1A->value = BK7231N_TRX_RAM.REG0xD.value; + CAL_WR_TRXREGS(0xF); + if(tx_gain_imb_cal_mode == TX_GAIN_IMB_CAL) + { + BK7231N_RC_REG.REG0x4F->bits.TXIDCCOMP = gcali_result.gtx_i_dc_comp; + BK7231N_RC_REG.REG0x4F->bits.TXQDCCOMP = gcali_result.gtx_q_dc_comp; + BK7231N_TRX_RAM.REG0xD.value = TRX_REG_0XD_TX_IQ_VAL_GAIN_PHASE;//wyg + CAL_WR_TRXREGS(0xD); + BK7231N_RC_REG.REG0x1A->value = BK7231N_TRX_RAM.REG0xD.value; + } + else + { + BK7231N_RC_REG.REG0x4F->bits.TXIDCCOMP = gcali_result.gtx_i_dc_comp_loopback; + BK7231N_RC_REG.REG0x4F->bits.TXQDCCOMP = gcali_result.gtx_q_dc_comp_loopback; + BK7231N_TRX_RAM.REG0xD.value = TRX_REG_0XD_TX_LOOPBACK_IQ_VAL; + CAL_WR_TRXREGS(0xD); + BK7231N_RC_REG.REG0x1A->value = BK7231N_TRX_RAM.REG0xD.value; + } + + + if(tx_gain_imb_cal_mode == TX_GAIN_IMB_CAL) + { + CAL_PRT("\r\nbk7011_cal_tx_gain_imbalance\r\n"); + } + else + { + CAL_PRT("\r\nbk7011_cal_tx_loopback_gain_imbalance\r\n"); + } + + CAL_PRT("pactrl = %d\r\n", BK7231N_TRX_RAM.REG0xC.bits.pactrl ); //?? + CAL_PRT("padctrl =%d\r\n", BK7231N_TRX_RAM.REG0xC.bits.padctrl); //?? + + if(tx_gain_imb_cal_mode == TX_GAIN_IMB_CAL) + { + gcali_result.gtx_i_gain_comp = BK7231N_RC_REG.REG0x50->bits.TXIGAINCOMP; + gcali_result.gtx_q_gain_comp = BK7231N_RC_REG.REG0x50->bits.TXQGAINCOMP; + } + else + { + gcali_result.gtx_i_gain_comp_loopback = BK7231N_RC_REG.REG0x50->bits.TXIGAINCOMP; + gcali_result.gtx_q_gain_comp_loopback = BK7231N_RC_REG.REG0x50->bits.TXQGAINCOMP; + } + + cpu_delay(500); + detector_i_gain = bk7011_get_tx_i_gain(); + detector_q_gain = bk7011_get_tx_q_gain(); + + CAL_TIM_PRT("%d:(i_comp=0x%x) detector_i_gain=%d,(q_comp=0x%x) detector_q_gain=%d\n", __LINE__, BK7231N_RC_REG.REG0x50->bits.TXIGAINCOMP, detector_i_gain, BK7231N_RC_REG.REG0x50->bits.TXQGAINCOMP, detector_q_gain); + if(abs(detector_q_gain - detector_i_gain) < 3) + { + if(tx_gain_imb_cal_mode == TX_GAIN_IMB_CAL) + { + gcali_result.gtx_i_gain_comp = BK7231N_RC_REG.REG0x50->bits.TXIGAINCOMP; + gcali_result.gtx_q_gain_comp = BK7231N_RC_REG.REG0x50->bits.TXQGAINCOMP; + } + else + { + gcali_result.gtx_i_gain_comp_loopback = BK7231N_RC_REG.REG0x50->bits.TXIGAINCOMP; + gcali_result.gtx_q_gain_comp_loopback = BK7231N_RC_REG.REG0x50->bits.TXQGAINCOMP; + } + + bk7011_cal_saradc_runorstop(cali_saradc_desc, 0); + return (BK7231N_RC_REG.REG0x50->bits.TXQGAINCOMP + (BK7231N_RC_REG.REG0x50->bits.TXIGAINCOMP << 16)); + } + + if(detector_i_gain > detector_q_gain) // TX_Q_GAIN_COMP NOT CHANGED + { + BK7231N_RC_REG.REG0x50->bits.TXQGAINCOMP = BK_TX_DAC_UNSIGNED_MASK_GAIN;//1023; + low = 0; + BK7231N_RC_REG.REG0x50->bits.TXIGAINCOMP = low; + detector_i_gain = bk7011_get_tx_i_gain(); + detector_q_gain = bk7011_get_tx_q_gain(); + + detect_gain_low = abs(detector_i_gain - detector_q_gain); + + high = BK_TX_DAC_UNSIGNED_MASK; + BK7231N_RC_REG.REG0x50->bits.TXIGAINCOMP = high; + detector_i_gain = bk7011_get_tx_i_gain(); + detector_q_gain = bk7011_get_tx_q_gain(); + + detect_gain_high = abs(detector_i_gain - detector_q_gain); + + do + { + if(detect_gain_low < detect_gain_high) + { + index = low; + high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7231N_RC_REG.REG0x50->bits.TXIGAINCOMP = high; + detector_i_gain = bk7011_get_tx_i_gain(); + detector_q_gain = bk7011_get_tx_q_gain(); + detect_gain_high = abs(detector_i_gain - detector_q_gain); + } + else + { + index = high; + low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7231N_RC_REG.REG0x50->bits.TXIGAINCOMP = low; + detector_i_gain = bk7011_get_tx_i_gain(); + detector_q_gain = bk7011_get_tx_q_gain(); + detect_gain_low = abs(detector_i_gain - detector_q_gain); + } + + } + while((high - low) > 1); + index = ((detect_gain_low < detect_gain_high) ? low : high); + BK7231N_RC_REG.REG0x50->bits.TXIGAINCOMP = index; + + if(tx_gain_imb_cal_mode == TX_GAIN_IMB_CAL) + { + gcali_result.gtx_i_gain_comp = index; + } + else + { + gcali_result.gtx_i_gain_comp_loopback= index; + } + gold_index = (index << 16) + BK_TX_DAC_UNSIGNED_MASK_GAIN;//1023; + } + else //// TX_I_GAIN_COMP NOT CHANGED + { + BK7231N_RC_REG.REG0x50->bits.TXIGAINCOMP = BK_TX_DAC_UNSIGNED_MASK;//1023; + low = 0; + BK7231N_RC_REG.REG0x50->bits.TXQGAINCOMP = low; + detector_i_gain = bk7011_get_tx_i_gain(); + detector_q_gain = bk7011_get_tx_q_gain(); + + detect_gain_low = abs(detector_i_gain - detector_q_gain); + + high = BK_TX_DAC_UNSIGNED_MASK; + BK7231N_RC_REG.REG0x50->bits.TXQGAINCOMP = high; + detector_i_gain = bk7011_get_tx_i_gain(); + detector_q_gain = bk7011_get_tx_q_gain(); + + detect_gain_high = abs(detector_i_gain - detector_q_gain); + do + { + if(detect_gain_low < detect_gain_high) + { + index = low; + high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7231N_RC_REG.REG0x50->bits.TXQGAINCOMP = high; + detector_i_gain = bk7011_get_tx_i_gain(); + detector_q_gain = bk7011_get_tx_q_gain(); + detect_gain_high = abs(detector_i_gain - detector_q_gain); + } + else + { + index = high; + low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7231N_RC_REG.REG0x50->bits.TXQGAINCOMP = low; + detector_i_gain = bk7011_get_tx_i_gain(); + detector_q_gain = bk7011_get_tx_q_gain(); + detect_gain_low = abs(detector_i_gain - detector_q_gain); + } + + } + while((high - low) > 1); + index = ((detect_gain_low < detect_gain_high) ? low : high); + BK7231N_RC_REG.REG0x50->bits.TXQGAINCOMP = index; + if(tx_gain_imb_cal_mode == TX_GAIN_IMB_CAL) + { + gcali_result.gtx_q_gain_comp = index; + } + else + { + gcali_result.gtx_q_gain_comp_loopback= index; + } + gold_index += (BK_TX_DAC_UNSIGNED_MASK_GAIN << 16) + index;//(1023 << 16) + index; + } + + if(tx_gain_imb_cal_mode == TX_GAIN_IMB_CAL) + { + CAL_PRT("gtx_i_gain_comp:0x%x\r\n", gcali_result.gtx_i_gain_comp); + CAL_PRT("gtx_q_gain_comp:0x%x\r\n", gcali_result.gtx_q_gain_comp); + } + + /* restore changed registers, 20210507 except REG0xC/REG0xD to avoid large signal */ + BK7231N_TRX_RAM.REG0x0.bits.tssiIQ_gc = 1; + BK7231N_TRX_RAM.REG0xF.bits.tssi_cal_en = 0; + BK7231N_RC_REG.REG0x43->bits.PRE_GAIN_2ND = 0x200;// + CAL_WR_TRXREGS(0x0); + BK7231N_RC_REG.REG0x1A->value = BK7231N_TRX_RAM.REG0xD.value; + CAL_WR_TRXREGS(0xF); + + bk7011_cal_saradc_runorstop(cali_saradc_desc, 0); + return gold_index; +} + +static INT32 bk7011_cal_tx_ty2(INT32 tx_phase_comp) +{ + float ty1, ty1_sqr, ty2; + INT32 tx_ty2; + + ty1 = (-1.0 * (tx_phase_comp - BK_TX_DAC_SIGNED_MIN) * (tx_phase_comp - BK_TX_DAC_SIGNED_MIN)) / (BK_TX_DAC_UNSIGNED_MAX * BK_TX_DAC_UNSIGNED_MAX); + ty1_sqr = ty1 * ty1; + ty2 = 1 - ty1 / 2 + 3 * ty1_sqr / 8; + tx_ty2 = (INT32)((ty2 - 0.5) * BK_TX_DAC_UNSIGNED_MAX + 0.5); + + return tx_ty2; +} + +INT32 bk7011_cal_tx_phase_imbalance(INT32 tx_phase_imb_cal_mode) +{ + INT32 detect_phase_low = 0; + INT32 detect_phase_high = 0; + INT16 high, low; + INT32 index = 0, gold_index = 0; + INT32 detector_i_phase; + INT32 detector_q_phase; + + bk7011_cal_saradc_runorstop(cali_saradc_desc, 1); + + if(tx_phase_imb_cal_mode == TX_PHASE_IMB_CAL) + { + BK7231N_RC_REG.REG0x4F->bits.TXIDCCOMP = gcali_result.gtx_i_dc_comp; + BK7231N_RC_REG.REG0x4F->bits.TXQDCCOMP = gcali_result.gtx_q_dc_comp; + BK7231N_RC_REG.REG0x50->bits.TXIGAINCOMP = gcali_result.gtx_i_gain_comp; + BK7231N_RC_REG.REG0x50->bits.TXQGAINCOMP = gcali_result.gtx_q_gain_comp; + BK7231N_TRX_RAM.REG0xD.value = TRX_REG_0XD_TX_IQ_VAL_GAIN_PHASE;//wyg//BK7011TRXREG0xD;//0214 close the TX switch to ellimite the antenna infect + CAL_WR_TRXREGS(0xD); + BK7231N_RC_REG.REG0x1A->value = BK7231N_TRX_RAM.REG0xD.value; + } + else + { + BK7231N_RC_REG.REG0x4F->bits.TXIDCCOMP = gcali_result.gtx_i_dc_comp_loopback; + BK7231N_RC_REG.REG0x4F->bits.TXQDCCOMP = gcali_result.gtx_q_dc_comp_loopback; + BK7231N_RC_REG.REG0x50->bits.TXIGAINCOMP = gcali_result.gtx_i_gain_comp_loopback; + BK7231N_RC_REG.REG0x50->bits.TXQGAINCOMP = gcali_result.gtx_q_gain_comp_loopback; + BK7231N_TRX_RAM.REG0xD.value = TRX_REG_0XD_TX_LOOPBACK_IQ_VAL; + CAL_WR_TRXREGS(0xD); + BK7231N_RC_REG.REG0x1A->value = BK7231N_TRX_RAM.REG0xD.value; + } + + + BK7231N_RC_REG.REG0x51->bits.TXPHASECOMP = BK_TX_DAC_SIGNED_MIN; + BK7231N_RC_REG.REG0x51->bits.TXTY2 = BK_TX_DAC_SIGNED_MIN; + + BK7231N_RC_REG.REG0x4C->bits.TESTPATTERN = 1; + + if(tx_phase_imb_cal_mode == TX_PHASE_IMB_CAL) + { + CAL_PRT("\r\nbk7011_cal_tx_phase_imbalance: \r\n"); + } + else + { + CAL_PRT("\r\nbk7011_cal_tx_loopback_phase_imbalance: \r\n"); + + } + + CAL_PRT("pactrl = %d\r\n", BK7231N_TRX_RAM.REG0xC.bits.pactrl ); //?? + CAL_PRT("padctrl =%d\r\n", BK7231N_TRX_RAM.REG0xC.bits.padctrl); //?? + + BK7231N_TRX_RAM.REG0x0.bits.TSSIsel = 0; + BK7231N_TRX_RAM.REG0x0.bits.enDCcal = 0; + BK7231N_TRX_RAM.REG0x0.bits.tssiIQ_gc = 0; + BK7231N_TRX_RAM.REG0x0.bits.enIQcal = 1; + BK7231N_TRX_RAM.REG0x0.bits.enPcal = 0; +// BK7231N_TRX_RAM.REG0x0->bits.enPcaliGm = 0; + BK7231N_TRX_RAM.REG0xF.bits.tssi_cal_en = 1; + BK7231N_TRX_RAM.REG0xD.bits.entxsw= 0; + BK7231N_TRX_RAM.REG0xC.bits.padctrl= 0x1; + BK7231N_TRX_RAM.REG0xC.bits.pactrl= 1; + BK7231N_RC_REG.REG0x43->bits.PRE_GAIN_2ND = 0x90;// + + CAL_WR_TRXREGS(0x0); + CAL_WR_TRXREGS(0xC); + CAL_WR_TRXREGS(0xD); + BK7231N_RC_REG.REG0x1A->value = BK7231N_TRX_RAM.REG0xD.value; + CAL_WR_TRXREGS(0xF); + + //low = bk7011_cal_tx_ty2(BK_TX_DAC_SIGNED_MIN); + low = (1 + 256) * BK_TX_DAC_COEF; + BK7231N_RC_REG.REG0x51->bits.TXPHASECOMP = low; + BK7231N_RC_REG.REG0x51->bits.TXTY2 = bk7011_cal_tx_ty2( low); + detector_i_phase = bk7011_get_tx_i_phase(); + detector_q_phase = bk7011_get_tx_q_phase(); + detect_phase_low = abs(detector_i_phase - detector_q_phase); + + high = BK_TX_DAC_UNSIGNED_MASK - 1024;//1023 - 256; + BK7231N_RC_REG.REG0x51->bits.TXPHASECOMP = high; + BK7231N_RC_REG.REG0x51->bits.TXTY2 = bk7011_cal_tx_ty2( high); + detector_i_phase = bk7011_get_tx_i_phase(); + detector_q_phase = bk7011_get_tx_q_phase(); + detect_phase_high = abs(detector_i_phase - detector_q_phase); + + CAL_TIM_PRT("%d:low(0x%x)=%d,high(0x%x)=%d\n", __LINE__, low, detect_phase_low, high, detect_phase_high); + + do + { + if(detect_phase_low < detect_phase_high) + { + index = low; + high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7231N_RC_REG.REG0x51->bits.TXPHASECOMP = high; + BK7231N_RC_REG.REG0x51->bits.TXTY2 = bk7011_cal_tx_ty2( high); + detector_i_phase = bk7011_get_tx_i_phase(); + detector_q_phase = bk7011_get_tx_q_phase(); + detect_phase_high = abs(detector_i_phase - detector_q_phase); + CAL_TIM_PRT("%d:low(0x%x)=%d,high(0x%x)=%d\n", __LINE__, low, detect_phase_low, high, detect_phase_high); + } + else + { + index = high; + low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7231N_RC_REG.REG0x51->bits.TXPHASECOMP = low; + BK7231N_RC_REG.REG0x51->bits.TXTY2 = bk7011_cal_tx_ty2( low); + detector_i_phase = bk7011_get_tx_i_phase(); + detector_q_phase = bk7011_get_tx_q_phase(); + detect_phase_low = abs(detector_i_phase - detector_q_phase); + CAL_TIM_PRT("%d:low(0x%x)=%d,high(0x%x)=%d\n", __LINE__, low, detect_phase_low, high, detect_phase_high); + } + } + while((high - low) > 1); + index = ((detect_phase_low < detect_phase_high) ? low : high); + BK7231N_RC_REG.REG0x51->bits.TXPHASECOMP = index; + + if(tx_phase_imb_cal_mode == TX_PHASE_IMB_CAL) + { + gcali_result.gtx_phase_comp = BK7231N_RC_REG.REG0x51->bits.TXPHASECOMP; + gcali_result.gtx_phase_ty2 = BK7231N_RC_REG.REG0x51->bits.TXTY2; + + CAL_PRT("gtx_phase_comp:0x%x\r\n", gcali_result.gtx_phase_comp); + CAL_PRT("gtx_phase_ty2:0x%x\r\n", gcali_result.gtx_phase_ty2); + + gold_index = (gcali_result.gtx_phase_comp << 16) + gcali_result.gtx_phase_ty2; + } + else + { + gcali_result.gtx_phase_comp_loopback = BK7231N_RC_REG.REG0x51->bits.TXPHASECOMP; + gcali_result.gtx_phase_ty2_loopback = BK7231N_RC_REG.REG0x51->bits.TXTY2; + + CAL_PRT("tx_phase_comp:0x%x\r\n", gcali_result.gtx_phase_comp_loopback); + CAL_PRT("tx_phase_ty2:0x%x\r\n", gcali_result.gtx_phase_ty2_loopback); + + gold_index = (gcali_result.gtx_phase_comp_loopback << 16) + gcali_result.gtx_phase_ty2_loopback; + } + + /* restore changed registers, 20210507 except REG0xC/REG0xD to avoid large signal */ + BK7231N_TRX_RAM.REG0x0.bits.tssiIQ_gc = 1; + BK7231N_TRX_RAM.REG0xF.bits.tssi_cal_en = 0; + + CAL_WR_TRXREGS(0x0); + BK7231N_RC_REG.REG0x1A->value = BK7231N_TRX_RAM.REG0xD.value; + CAL_WR_TRXREGS(0xF); + BK7231N_RC_REG.REG0x43->bits.PRE_GAIN_2ND = 0x200;// + bk7011_cal_saradc_runorstop(cali_saradc_desc, 0); + return gold_index; +} + +static float bk7011_get_tx_filter_i_ratio(void) +{ + INT32 rx_avg_i_14M, rx_avg_i_500K; + float rx_avg_ratio; + BK7231N_RC_REG.REG0x4D->bits.TXSINF = 250; // 9.7MHz + cal_delay_100us(3*gcali_context.gst_rx_adc); + rx_avg_i_14M = bk7011_get_rx_i_avg_signed(); + BK7231N_RC_REG.REG0x4D->bits.TXSINF = 125; // 4.85MHz; + cal_delay_100us(3*gcali_context.gst_rx_adc); + rx_avg_i_500K = bk7011_get_rx_i_avg_signed(); +// if(rx_avg_i_14M > 0) + { + rx_avg_ratio = abs(1.0 * rx_avg_i_500K / rx_avg_i_14M - 1.377); + return rx_avg_ratio; + } +// else +// { +// return -1.0; +// } +} + + +static float bk7011_get_tx_filter_i_ratio1(void) +{ + int i; + INT32 rx_avg_i_14M_array[40], rx_avg_i_500K_array[40]; + INT32 rx_avg_i_14M = 0, rx_avg_i_500K = 0; + float rx_avg_ratio; + BK7231N_RC_REG.REG0x4D->bits.TXSINF = 250; // 9.7MHz 20180308 BY YIMING; + + cal_delay_100us(2*gcali_context.gst_rx_adc); + for (i=0; i<40; i++) + { + cal_delay_100us(gcali_context.gst_rx_adc); + rx_avg_i_14M_array[i] = bk7011_get_rx_i_avg_signed(); + rx_avg_i_14M += rx_avg_i_14M_array[i]; + } + BK7231N_RC_REG.REG0x4D->bits.TXSINF = 125; // 4.85MHz; + + cal_delay_100us(2*gcali_context.gst_rx_adc); + for (i=0; i<40; i++) + { + cal_delay_100us(gcali_context.gst_rx_adc); + rx_avg_i_500K_array[i] = bk7011_get_rx_i_avg_signed(); + rx_avg_i_500K += rx_avg_i_500K_array[i]; + } +// if(rx_avg_i_14M > 0) + { + rx_avg_ratio = abs(1.0 * rx_avg_i_500K / rx_avg_i_14M - 1.377); + return rx_avg_ratio; + } +// else +// { +// return -1.0; +// } +} + + +static float bk7011_get_tx_filter_q_ratio(void) +{ + INT32 rx_avg_q_14M = 0, rx_avg_q_500K = 0; + float rx_avg_ratio; + BK7231N_RC_REG.REG0x4D->bits.TXSINF = 250; // 9.7MHz; + cal_delay_100us(3*gcali_context.gst_rx_adc); + rx_avg_q_14M = bk7011_get_rx_q_avg_signed(); + BK7231N_RC_REG.REG0x4D->bits.TXSINF = 125; // 4.85MHz; + cal_delay_100us(3*gcali_context.gst_rx_adc); + rx_avg_q_500K = bk7011_get_rx_q_avg_signed(); +// if(rx_avg_i_14M > 0) + { + rx_avg_ratio = abs(1.0 * rx_avg_q_500K / rx_avg_q_14M - 1.377); + return rx_avg_ratio; + } +} + +static float bk7011_get_tx_filter_q_ratio1(void) +{ + int i; + INT32 rx_avg_q_14M_array[40], rx_avg_q_500K_array[40]; + INT32 rx_avg_q_14M = 0, rx_avg_q_500K = 0; + float rx_avg_ratio; + BK7231N_RC_REG.REG0x4D->bits.TXSINF = 250; // 9.7MHz; + + cal_delay_100us(2*gcali_context.gst_rx_adc); + for (i=0; i<40; i++) + { + cal_delay_100us(gcali_context.gst_rx_adc); + rx_avg_q_14M_array[i] = bk7011_get_rx_q_avg_signed(); + rx_avg_q_14M += rx_avg_q_14M_array[i]; + } + BK7231N_RC_REG.REG0x4D->bits.TXSINF = 125; // 4.85MHz; + + cal_delay_100us(2*gcali_context.gst_rx_adc); + for (i=0; i<40; i++) + { + cal_delay_100us(gcali_context.gst_rx_adc); + rx_avg_q_500K_array[i] = bk7011_get_rx_q_avg_signed(); + rx_avg_q_500K += rx_avg_q_500K_array[i]; + } +// if(rx_avg_q_14M > 0) + { + rx_avg_ratio = abs(1.0 * rx_avg_q_500K / rx_avg_q_14M - 1.377); + return rx_avg_ratio; + } +} + +void bk7011_get_tx_filter_corner(INT32 *tx_ifilter_corner, INT32 *tx_qfilter_corner) +{ + *tx_ifilter_corner = gcali_result.gtx_ifilter_corner; + *tx_qfilter_corner = gcali_result.gtx_qfilter_corner; +} + +void bk7011_get_tx_dc_comp(INT32 *tx_i_dc_comp, INT32 *tx_q_dc_comp) +{ + *tx_i_dc_comp = gcali_result.gtx_i_dc_comp; + *tx_q_dc_comp = gcali_result.gtx_q_dc_comp; +} + +void bk7011_get_tx_gain_comp(INT32 *tx_i_gain_comp, INT32 *tx_q_gain_comp) +{ + *tx_i_gain_comp = gcali_result.gtx_i_gain_comp; + *tx_q_gain_comp = gcali_result.gtx_q_gain_comp; +} + +void bk7011_get_tx_phase(INT32 *tx_phase_comp, INT32 *tx_phase_ty2) +{ + *tx_phase_comp = gcali_result.gtx_phase_comp; + *tx_phase_ty2 = gcali_result.gtx_phase_ty2; +} + +void bk7011_get_rx_err_wr(INT32 *rx_amp_err_wr, INT32 *rx_phase_err_wr, INT32 *rx_dc_gain_tab) +{ + *rx_phase_err_wr = gcali_result.grx_phase_err_wr; + *rx_amp_err_wr = gcali_result.grx_amp_err_wr; + os_memcpy(rx_dc_gain_tab, gcali_result.g_rx_dc_gain_tab, sizeof(gcali_result.g_rx_dc_gain_tab)); +} + +void bk7011_get_tx_tssi_thred(INT32 *tx_tssi_thred_b, INT32 *tx_tssi_thred_g) +{ + *tx_tssi_thred_b = gcali_context.gtx_tssi_thred_b; + *tx_tssi_thred_g = gcali_context.gtx_tssi_thred_g; +} + +INT32 bk7011_cal_tx_filter_corner() +{ + int i; + float float_1 = 1100.00; + float float_2 = 1100.00; + float tx_avg_ratio_low = 0.0; + float tx_avg_ratio_high = 0.0; + INT16 high, low; + INT32 index = 0, gold_index = 0; + + BK7231N_TRX_RAM.REG0x6.bits.capcal_sel = 0; + CAL_WR_TRXREGS(0x6); + + BK7231N_RC_REG.REG0x52->bits.TXIQSWAP = 0; /* I/Q SWAP*/ + BK7231N_RC_REG.REG0x1C->bits.FRXON = 1; + // I CAL + BK7231N_TRX_RAM.REG0x6.bits.lpfcapcali50 = 0x00; + BK7231N_TRX_RAM.REG0x7.bits.lpfcapcali = 0x02; + BK7231N_TRX_RAM.REG0x7.bits.txif_2rd = 0x0; + BK7231N_TRX_RAM.REG0x7.bits.abws_en = 0x0; + + BK7231N_TRX_RAM.REG0xD.value = TRX_REG_0XD_TX_FILTER_IQ_VAL;//BK7011TRXREG0xD;//0xE00F02B9;//0xFC4E03B9;// + CAL_WR_TRXREGS(0x7); + CAL_WR_TRXREGS(0x6); + CAL_WR_TRXREGS(0xD); + BK7231N_RC_REG.REG0x1A->value = BK7231N_TRX_RAM.REG0xD.value; + + //12/10/2014 for D version + //BK7231N_TRX_RAM.REG0x0->bits.tssi_statectrl = 1; + BK7231N_TRX_RAM.REG0xF.bits.tssi_cal_en = 0; + BK7231N_TRX_RAM.REG0xF.bits.sinad_rx_en = 0; + CAL_WR_TRXREGS(0x0); + CAL_WR_TRXREGS(0xF); + + BK7231N_RC_REG.REG0x4C->bits.TESTPATTERN = 2; + BK7231N_RC_REG.REG0x4D->bits.TXSINMODE = 1; + BK7231N_RC_REG.REG0x4D->bits.TXSINAMP = 6; + BK7231N_RC_REG.REG0x3C->bits.RXDCCALEN = 1; + BK7231N_RC_REG.REG0x3C->bits.RXAVGMODE = 1; + + low = 0; + BK7231N_TRX_RAM.REG0x6.bits.lpfcapcali50 = low & 0x3F; + BK7231N_TRX_RAM.REG0x7.bits.lpfcapcali = (low >> 6) & 0x3; + CAL_WR_TRXREGS(0x6); + CAL_WR_TRXREGS(0x7); + + tx_avg_ratio_low = bk7011_get_tx_filter_i_ratio(); + + high = 255; + BK7231N_TRX_RAM.REG0x6.bits.lpfcapcali50 = high & 0x3F; + BK7231N_TRX_RAM.REG0x7.bits.lpfcapcali = (high >> 6) & 0x3; + CAL_WR_TRXREGS(0x6); + CAL_WR_TRXREGS(0x7); + + tx_avg_ratio_high = bk7011_get_tx_filter_i_ratio(); + + do + { + if(tx_avg_ratio_low < tx_avg_ratio_high) + { + index = low; + high = high - ((high - low) >> 2); + //high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7231N_TRX_RAM.REG0x6.bits.lpfcapcali50 = high & 0x3F; + BK7231N_TRX_RAM.REG0x7.bits.lpfcapcali = (high >> 6) & 0x3; + CAL_WR_TRXREGS(0x6); + CAL_WR_TRXREGS(0x7); + tx_avg_ratio_high = bk7011_get_tx_filter_i_ratio(); + } + else + { + index = high; + low = low + ((high - low) >> 2); + //low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7231N_TRX_RAM.REG0x6.bits.lpfcapcali50 = low & 0x3F; + BK7231N_TRX_RAM.REG0x7.bits.lpfcapcali = (low >> 6) & 0x3; + CAL_WR_TRXREGS(0x6); + CAL_WR_TRXREGS(0x7); + tx_avg_ratio_low = bk7011_get_tx_filter_i_ratio(); + } + } + while((high - low) > 3); + index = ((tx_avg_ratio_low < tx_avg_ratio_high) ? low : high); + gcali_result.gtx_ifilter_corner = index ; + gold_index = index << 8; + + for (i=0; i<7; i++) + { + if (((index - 2 + i) >= 0) && ((index - 2 + i) < 256)) + { + BK7231N_TRX_RAM.REG0x6.bits.lpfcapcali50 = (index - 2 + i) & 0x3F; + BK7231N_TRX_RAM.REG0x7.bits.lpfcapcali = ((index - 2 + i) >> 6) & 0x3; + CAL_WR_TRXREGS(0x6); + CAL_WR_TRXREGS(0x7); + float_2 = bk7011_get_tx_filter_i_ratio1(); + if (float_1 > float_2) + { + float_1 = float_2; + gcali_result.gtx_ifilter_corner = index - 2 + i; + } + } + } + + gcali_result.gtx_ifilter_corner = gcali_result.gtx_ifilter_corner - 1; + + // Q CAL + BK7231N_TRX_RAM.REG0x6.bits.lpfcapcalq50 = 0x00; + BK7231N_TRX_RAM.REG0x7.bits.lpfcapcalq = 0x02; + BK7231N_TRX_RAM.REG0xD.value = TRX_REG_0XD_TX_FILTER_IQ_VAL;//BK7011TRXREG0xD;//0xE00F02B9;//0xFC4E03B9;// + CAL_WR_TRXREGS(0x6); + CAL_WR_TRXREGS(0x7); + CAL_WR_TRXREGS(0xD); + BK7231N_RC_REG.REG0x1A->value = BK7231N_TRX_RAM.REG0xD.value; + + //12/10/2014 for D version + BK7231N_TRX_RAM.REG0xF.bits.tssi_cal_en = 0; + BK7231N_TRX_RAM.REG0xF.bits.sinad_rx_en = 0; + CAL_WR_TRXREGS(0xF); + + BK7231N_RC_REG.REG0x4C->bits.TESTPATTERN = 2; + BK7231N_RC_REG.REG0x4D->bits.TXSINMODE = 2; + BK7231N_RC_REG.REG0x4D->bits.TXSINAMP = 6; + BK7231N_RC_REG.REG0x3C->bits.RXDCCALEN = 1; + BK7231N_RC_REG.REG0x3C->bits.RXAVGMODE = 1; + + low = 0; + BK7231N_TRX_RAM.REG0x6.bits.lpfcapcalq50 = low & 0x3F; + BK7231N_TRX_RAM.REG0x7.bits.lpfcapcalq = (low >> 6) & 0x3; + CAL_WR_TRXREGS(0x6); + CAL_WR_TRXREGS(0x7); + + tx_avg_ratio_low = bk7011_get_tx_filter_q_ratio(); + high = 255; + BK7231N_TRX_RAM.REG0x6.bits.lpfcapcalq50 = high & 0x3F; + BK7231N_TRX_RAM.REG0x7.bits.lpfcapcalq = (high >> 6) & 0x3; + CAL_WR_TRXREGS(0x6); + CAL_WR_TRXREGS(0x7); + + tx_avg_ratio_high = bk7011_get_tx_filter_q_ratio(); + do + { + if(tx_avg_ratio_low < tx_avg_ratio_high) + { + index = low; + high = high - ((high - low) >> 2); + //high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7231N_TRX_RAM.REG0x6.bits.lpfcapcalq50 = high & 0x3F; + BK7231N_TRX_RAM.REG0x7.bits.lpfcapcalq = (high >> 6) & 0x3; + CAL_WR_TRXREGS(0x6); + CAL_WR_TRXREGS(0x7); + tx_avg_ratio_high = bk7011_get_tx_filter_q_ratio(); + } + else + { + index = high; + low = low + ((high - low) >> 2); + //low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7231N_TRX_RAM.REG0x6.bits.lpfcapcalq50 = low & 0x3F; + BK7231N_TRX_RAM.REG0x7.bits.lpfcapcalq = (low >> 6) & 0x3; + CAL_WR_TRXREGS(0x6); + CAL_WR_TRXREGS(0x7); + tx_avg_ratio_low = bk7011_get_tx_filter_q_ratio(); + } + } + while((high - low) > 3); + index = ((tx_avg_ratio_low < tx_avg_ratio_high) ? low : high); + gcali_result.gtx_qfilter_corner = index ; + + gold_index += index; + + float_1 = 1100; + for (i=0; i<7; i++) + { + if (((index - 2 + i) >= 0) && ((index - 2 + i) < 256)) + { + BK7231N_TRX_RAM.REG0x6.bits.lpfcapcalq50 = (index - 2 + i) & 0x3F; + BK7231N_TRX_RAM.REG0x7.bits.lpfcapcalq = ((index - 2 + i) >> 6) & 0x3; + CAL_WR_TRXREGS(0x6); + CAL_WR_TRXREGS(0x7); + float_2 = bk7011_get_tx_filter_q_ratio1(); + if (float_1 > float_2) + { + float_1 = float_2; + gcali_result.gtx_qfilter_corner = index - 2 + i; + } + } + } + + rwnx_cal_set_lpfcap_iq(gcali_result.gtx_ifilter_corner, gcali_result.gtx_qfilter_corner); + //gtx_qfilter_corner = gtx_ifilter_corner; + CAL_PRT("gtx_ifilter_corner over: 0x%x\r\n", gcali_result.gtx_ifilter_corner); + CAL_PRT("gtx_qfilter_corner over: 0x%x\r\n", gcali_result.gtx_qfilter_corner); + + /* restore changed registers */ + //rwnx_cal_set_lpfcap_iq(0, 0); + BK7231N_RC_REG.REG0x52->bits.TXIQSWAP = 1; /* I/Q SWAP*/ + + return (gold_index); +} + +void bk7011_rx_cal_en(void) +{ + BK7231N_RC_REG.REG0x3E->bits.RXCOMPEN = 0; + + BK7231N_RC_REG.REG0x1C->bits.FRXON = 1; + BK7231N_RC_REG.REG0x1C->bits.FTXON = 0; + + BK7231N_RC_REG.REG0x0->bits.forceenable = 1; + cpu_delay(1); + BK7231N_RC_REG.REG0x19->bits.FCH0SHDN = 1; + BK7231N_RC_REG.REG0x19->bits.FCH0TXEN = 0; + BK7231N_RC_REG.REG0x19->bits.FCH0RXEN = 1; + BK7231N_RC_REG.REG0x19->bits.FCH0EN = 1; + + // ADC clock change to 80M + BK7231N_TRX_RAM.REG0xF.bits.clkadc_sel = 0;//20170331 1 --> 0 + CAL_WR_TRXREGS(0xF); +} + +void bk7011_cal_rx_adc_dlym() +{ + UINT32 state; + UINT32 REG0x7_value = BK7231N_TRX_RAM.REG0x7.value; + + BK7231N_TRX_RAM.REG0xF.bits.clkadc_sel = 1; + CAL_WR_TRXREGS(0xF); + + BK7231N_TRX_RAM.REG0x7.bits.adc_dly_men = 0; + BK7231N_TRX_RAM.REG0x7.bits.autorxifgen = 0; + BK7231N_TRX_RAM.REG0x7.bits.spilpfrxg30 = 0; + CAL_WR_TRXREGS(0x7); + + BK7231N_TRX_RAM.REG0x12.bits.pwd_adccal = 1; + CAL_WR_TRXREGS(0x12); + BK7231N_TRX_RAM.REG0x12.bits.pwd_adccal = 0; + CAL_WR_TRXREGS(0x12); + delay05us(10); + + state = REG_READ(SCTRL_ANALOG_STATE); + state = (state >> 8) & 0x7F; + BK7231N_TRX_RAM.REG0x12.bits.adc_dlym = state; + CAL_WR_TRXREGS(0x12); + + BK7231N_TRX_RAM.REG0x7.value = REG0x7_value; + CAL_WR_TRXREGS(0x7); + + BK7231N_TRX_RAM.REG0xF.bits.clkadc_sel = 0; + CAL_WR_TRXREGS(0xF); +} + +void bk7011_cal_rx_adc_restore(int enter_or_exit) +{ + static UINT32 REG0x0_value; + static UINT32 REG0x19_value; + static UINT32 REG0x1C_value; + static UINT32 REG0x3E_value; + static UINT32 REG0xF_value; + + if (enter_or_exit) + { + /* enter */ + REG0x0_value = BK7231N_RC_REG.REG0x0->bits.forceenable; + REG0x19_value = BK7231N_RC_REG.REG0x19->value; + REG0x1C_value = BK7231N_RC_REG.REG0x1C->value; + REG0x3E_value = BK7231N_RC_REG.REG0x3E->value; + REG0xF_value = BK7231N_TRX_RAM.REG0xF.value; + + BK7231N_RC_REG.REG0x3E->bits.RXCOMPEN = 0; + + BK7231N_RC_REG.REG0x1C->bits.FRXON = 1; + BK7231N_RC_REG.REG0x1C->bits.FTXON = 0; + + BK7231N_RC_REG.REG0x0->bits.forceenable = 1; + cpu_delay(1); + BK7231N_RC_REG.REG0x19->bits.FCH0SHDN = 1; + BK7231N_RC_REG.REG0x19->bits.FCH0TXEN = 0; + BK7231N_RC_REG.REG0x19->bits.FCH0RXEN = 1; + BK7231N_RC_REG.REG0x19->bits.FCH0EN = 1; + + // ADC clock change to 80M + BK7231N_TRX_RAM.REG0xF.bits.clkadc_sel = 0;//20170331 1 --> 0 + CAL_WR_TRXREGS(0xF); + } + else + { + /* exit */ + BK7231N_RC_REG.REG0x3E->value = REG0x3E_value; + + BK7231N_RC_REG.REG0x1C->value = REG0x1C_value; + + BK7231N_RC_REG.REG0x0->bits.forceenable = REG0x0_value; + cpu_delay(1); + BK7231N_RC_REG.REG0x19->value = REG0x19_value; + + // ADC clock change to 80M + BK7231N_TRX_RAM.REG0xF.value = REG0xF_value;//20170331 1 --> 0 + CAL_WR_TRXREGS(0xF); + + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_MODEM_CORE_RESET, 0); + } +} + +INT32 bk7011_cal_rx_dc(void) +{ + INT32 index = 0; + INT32 i, j, k, t, curr, value; + UINT32 rx_dc_gain_tab_temp[8]; + UINT32 rx_dc_gain_tab_temp1[8]; + + BK7231N_TRX_RAM.REG0x7.bits.dig_dcoen = 1; //dco input using digital + BK7231N_TRX_RAM.REG0x7.bits.autorxifgen = 1; + CAL_WR_TRXREGS(0x7); + + BK7231N_TRX_RAM.REG0x14.bits.dc_i_0db=0x80; + BK7231N_TRX_RAM.REG0x14.bits.dc_q_0db=0x80; + BK7231N_TRX_RAM.REG0x14.bits.dc_i_3db=0x80; + BK7231N_TRX_RAM.REG0x14.bits.dc_q_3db=0x80; + + BK7231N_TRX_RAM.REG0x15.bits.dc_i_6db=0x80; + BK7231N_TRX_RAM.REG0x15.bits.dc_q_6db=0x80; + BK7231N_TRX_RAM.REG0x15.bits.dc_i_9db=0x80; + BK7231N_TRX_RAM.REG0x15.bits.dc_q_9db=0x80; + + BK7231N_TRX_RAM.REG0x16.bits.dc_i_12db=0x80; + BK7231N_TRX_RAM.REG0x16.bits.dc_q_12db=0x80; + BK7231N_TRX_RAM.REG0x16.bits.dc_i_15db=0x80; + BK7231N_TRX_RAM.REG0x16.bits.dc_q_15db=0x80; + + BK7231N_TRX_RAM.REG0x17.bits.dc_i_18db=0x80; + BK7231N_TRX_RAM.REG0x17.bits.dc_q_18db=0x80; + BK7231N_TRX_RAM.REG0x17.bits.dc_i_21db=0x80; + BK7231N_TRX_RAM.REG0x17.bits.dc_q_21db=0x80; + + BK7231N_TRX_RAM.REG0x18.bits.dc_i_24db=0x80; + BK7231N_TRX_RAM.REG0x18.bits.dc_q_24db=0x80; + BK7231N_TRX_RAM.REG0x18.bits.dc_i_27db=0x80; + BK7231N_TRX_RAM.REG0x18.bits.dc_q_27db=0x80; + + BK7231N_TRX_RAM.REG0x19.bits.dc_i_30db=0x80; + BK7231N_TRX_RAM.REG0x19.bits.dc_q_30db=0x80; + BK7231N_TRX_RAM.REG0x19.bits.dc_i_33db=0x80; + BK7231N_TRX_RAM.REG0x19.bits.dc_q_33db=0x80; + + BK7231N_TRX_RAM.REG0x1A.bits.dc_i_36db=0x80; + BK7231N_TRX_RAM.REG0x1A.bits.dc_q_36db=0x80; + BK7231N_TRX_RAM.REG0x1A.bits.dc_i_39db=0x80; + BK7231N_TRX_RAM.REG0x1A.bits.dc_q_39db=0x80; + + BK7231N_TRX_RAM.REG0x1B.bits.dc_i_42db=0x80; + BK7231N_TRX_RAM.REG0x1B.bits.dc_q_42db=0x80; + BK7231N_TRX_RAM.REG0x1B.bits.dc_i_45db=0x80; + BK7231N_TRX_RAM.REG0x1B.bits.dc_q_45db=0x80; + /*step 2*/ + BK7231N_RC_REG.REG0x3C->bits.RXDCCALEN = 1; + BK7231N_RC_REG.REG0x3C->bits.RXAVGMODE = 0; + BK7231N_RC_REG.REG0x19->bits.FCH0RXHP = 0; //huaming.jiang 20141017 + BK7231N_RC_REG.REG0x1C->bits.FTXON = 0; + BK7231N_RC_REG.REG0x1C->bits.FRXON = 1; + + BK7231N_TRX_RAM.REG0x5.bits.chspi = 0x0;//2400MHz, 20181120 from 0x64 to 0x0; + CAL_WR_TRXREGS(0x5); + delay100us(1);//delay 100us for RFPLL + + BK7231N_TRX_RAM.REG0xE.value = 0xD801BCF0;//0xD8013CF0;//0xDA01BCF0; /// D801BCF0;//170217 + CAL_WR_TRXREGS(0xE); + + BK7231N_RC_REG.REG0x52->bits.TXIQSWAP = 0; /* I/Q SWAP*/ + + for(i = 0; i < 16; i ++) + { + BK7231N_RC_REG.REG0x19->bits.FCH0B = (0x70 | i); + for(j = 0; j < 2; j ++) + { + index = 128; + k = 6; + do + { + CAL_PRT("%d:REG0x%x,bits[%d-%d]=0x%x\n", __LINE__, (0x14 + i / 2), + 16 * (i % 2) + 8 * j + 7, + 16 * (i % 2) + 8 * j, + index << (16 * (i % 2) + 8 * j)); + + //set dc offset + value = (*((volatile unsigned long *)(TRX_BEKEN_BASE + (0x14 + i / 2) * 4))); + curr = ~(0xff << (16 * (i % 2) + 8 * j)); + value &= curr; + curr = (index << (16 * (i % 2) + 8 * j)); + value |= curr; + (*((volatile unsigned long *)(TRX_BEKEN_BASE + (0x14 + i / 2) * 4))) = value; + while(BK7231N_RC_REG.REG0x1->value & 0xfffffff); + cal_delay_100us(gcali_context.gst_rx_adc); + + //read dc avg, and calc mean + CAL_PRT("%d:RXAVG_RD=", __LINE__); + value = 0; + for(t = 0; t < 1; t ++) + { + if(j == 0) curr = BK7231N_RC_REG.REG0x3C->bits.RXAVGIRD; + else curr = BK7231N_RC_REG.REG0x3C->bits.RXAVGQRD; + CAL_PRT("0x%x,", curr); + if(curr >= 2048) curr -= 4096; + value += curr; + cpu_delay(100); + } + curr = value / 1; + CAL_PRT(" RXAVG=0x%x\n", curr); + + //calc new dc offset + if(curr > 0) index += (0x1 << k); + else index -= (0x1 << k); + k --; + } + while((k >= 0) && ((curr >= 16) || (curr <= -16))); + if(k < 0) + { + value = (*((volatile unsigned long *)(TRX_BEKEN_BASE + (0x14 + i / 2) * 4))); + curr = ~(0xff << (16 * (i % 2) + 8 * j)); + value &= curr; + curr = (index << (16 * (i % 2) + 8 * j)); + value |= curr; + (*((volatile unsigned long *)(TRX_BEKEN_BASE + (0x14 + i / 2) * 4))) = value; + while(BK7231N_RC_REG.REG0x1->value & 0xfffffff); + } + } + } + + rx_dc_gain_tab_temp[0] = BK7231N_TRX_REG.REG0x14->value; + rx_dc_gain_tab_temp[1] = BK7231N_TRX_REG.REG0x15->value; + rx_dc_gain_tab_temp[2] = BK7231N_TRX_REG.REG0x16->value; + rx_dc_gain_tab_temp[3] = BK7231N_TRX_REG.REG0x17->value; + rx_dc_gain_tab_temp[4] = BK7231N_TRX_REG.REG0x18->value; + rx_dc_gain_tab_temp[5] = BK7231N_TRX_REG.REG0x19->value; + rx_dc_gain_tab_temp[6] = BK7231N_TRX_REG.REG0x1A->value; + rx_dc_gain_tab_temp[7] = BK7231N_TRX_REG.REG0x1B->value; + + BK7231N_TRX_RAM.REG0x5.bits.chspi = 0x55;//2485MHz; + CAL_WR_TRXREGS(0x5); + delay100us(1);//delay 100us for RFPLL + + BK7231N_TRX_RAM.REG0xE.value = 0xD801BCF0;//0xD8013CF0;//0xDA01BCF0; /// D801BCF0;//170217 + CAL_WR_TRXREGS(0xE); + + for(i = 0; i < 16; i ++) + { + BK7231N_RC_REG.REG0x19->bits.FCH0B = (0x70 | i); + for(j = 0; j < 2; j ++) + { + index = 128; + k = 6; + do + { + //set dc offset + value = (*((volatile unsigned long *)(TRX_BEKEN_BASE + (0x14 + i / 2) * 4))); + curr = ~(0xff << (16 * (i % 2) + 8 * j)); + value &= curr; + curr = (index << (16 * (i % 2) + 8 * j)); + value |= curr; + (*((volatile unsigned long *)(TRX_BEKEN_BASE + (0x14 + i / 2) * 4))) = value; + while(BK7231N_RC_REG.REG0x1->value & 0xfffffff); + cal_delay_100us(gcali_context.gst_rx_adc); + + //read dc avg, and calc mean + value = 0; + for(t = 0; t < 1; t ++) + { + if(j == 0) curr = BK7231N_RC_REG.REG0x3C->bits.RXAVGIRD; + else curr = BK7231N_RC_REG.REG0x3C->bits.RXAVGQRD; + + if(curr >= 2048) curr -= 4096; + value += curr; + cpu_delay(100); + } + curr = value / 1; + //calc new dc offset + if(curr > 0) index += (0x1 << k); + else index -= (0x1 << k); + k --; + } + while((k >= 0) && ((curr >= 16) || (curr <= -16))); + if(k < 0) + { + value = (*((volatile unsigned long *)(TRX_BEKEN_BASE + (0x14 + i / 2) * 4))); + + curr = ~(0xff << (16 * (i % 2) + 8 * j)); + value &= curr; + + curr = (index << (16 * (i % 2) + 8 * j)); + value |= curr; + + (*((volatile unsigned long *)(TRX_BEKEN_BASE + (0x14 + i / 2) * 4))) = value; + while(BK7231N_RC_REG.REG0x1->value & 0xfffffff); + } + } + } + + rx_dc_gain_tab_temp1[0] = BK7231N_TRX_REG.REG0x14->value; + rx_dc_gain_tab_temp1[1] = BK7231N_TRX_REG.REG0x15->value; + rx_dc_gain_tab_temp1[2] = BK7231N_TRX_REG.REG0x16->value; + rx_dc_gain_tab_temp1[3] = BK7231N_TRX_REG.REG0x17->value; + rx_dc_gain_tab_temp1[4] = BK7231N_TRX_REG.REG0x18->value; + rx_dc_gain_tab_temp1[5] = BK7231N_TRX_REG.REG0x19->value; + rx_dc_gain_tab_temp1[6] = BK7231N_TRX_REG.REG0x1A->value; + rx_dc_gain_tab_temp1[7] = BK7231N_TRX_REG.REG0x1B->value; + + for (i=0; i<8; i++) + { + gcali_result.g_rx_dc_gain_tab[i] = ((((rx_dc_gain_tab_temp[i] & 0x000000FF) + (rx_dc_gain_tab_temp1[i] & 0x000000FF)) / 2) & 0x000000FF) + | ((((rx_dc_gain_tab_temp[i] & 0x0000FF00) + (rx_dc_gain_tab_temp1[i] & 0x0000FF00)) / 2) & 0x0000FF00) + | ((((rx_dc_gain_tab_temp[i] & 0x00FF0000) + (rx_dc_gain_tab_temp1[i] & 0x00FF0000)) / 2) & 0x00FF0000) + | ((((((rx_dc_gain_tab_temp[i] >> 8) & 0x00FF0000) + ((rx_dc_gain_tab_temp1[i] >> 8) & 0x00FF0000)) / 2) & 0x00FF0000) << 8); + } + + //hengzh:should be BK7231N_TRX_RAM + BK7231N_TRX_RAM.REG0x14.value = gcali_result.g_rx_dc_gain_tab[0]; + CAL_WR_TRXREGS(0x14); + BK7231N_TRX_RAM.REG0x15.value = gcali_result.g_rx_dc_gain_tab[1]; + CAL_WR_TRXREGS(0x15); + BK7231N_TRX_RAM.REG0x16.value = gcali_result.g_rx_dc_gain_tab[2]; + CAL_WR_TRXREGS(0x16); + BK7231N_TRX_RAM.REG0x17.value = gcali_result.g_rx_dc_gain_tab[3]; + CAL_WR_TRXREGS(0x17); + BK7231N_TRX_RAM.REG0x18.value = gcali_result.g_rx_dc_gain_tab[4]; + CAL_WR_TRXREGS(0x18); + BK7231N_TRX_RAM.REG0x19.value = gcali_result.g_rx_dc_gain_tab[5]; + CAL_WR_TRXREGS(0x19); + BK7231N_TRX_RAM.REG0x1A.value = gcali_result.g_rx_dc_gain_tab[6]; + CAL_WR_TRXREGS(0x1A); + BK7231N_TRX_RAM.REG0x1B.value = gcali_result.g_rx_dc_gain_tab[7]; + CAL_WR_TRXREGS(0x1B); + + + /* + CAL_PRT("%d:g_rx_dc_gain_tab 0 over: 0x%x\r\n", __LINE__,gcali_result.g_rx_dc_gain_tab[0]); + CAL_PRT("%d:g_rx_dc_gain_tab 1 over: 0x%x\r\n", __LINE__,gcali_result.g_rx_dc_gain_tab[1]); + CAL_PRT("%d:g_rx_dc_gain_tab 2 over: 0x%x\r\n",__LINE__, gcali_result.g_rx_dc_gain_tab[2]); + CAL_PRT("%d:g_rx_dc_gain_tab 3 over: 0x%x\r\n", __LINE__,gcali_result.g_rx_dc_gain_tab[3]); + CAL_PRT("%d:g_rx_dc_gain_tab 4 over: 0x%x\r\n", __LINE__,gcali_result.g_rx_dc_gain_tab[4]); + CAL_PRT("%d:g_rx_dc_gain_tab 5 over: 0x%x\r\n", __LINE__,gcali_result.g_rx_dc_gain_tab[5]); + CAL_PRT("%d:g_rx_dc_gain_tab 6 over: 0x%x\r\n", __LINE__,gcali_result.g_rx_dc_gain_tab[6]); + CAL_PRT("%d:g_rx_dc_gain_tab 7 over: 0x%x\r\n", __LINE__,gcali_result.g_rx_dc_gain_tab[7]); +*/ + BK7231N_RC_REG.REG0x3C->bits.RXDCCALEN = 0; + + BK7231N_TRX_RAM.REG0x7.bits.dig_dcoen = 1; + BK7231N_TRX_RAM.REG0x7.bits.autorxifgen = 1; + CAL_WR_TRXREGS(0x7); + BK7231N_TRX_RAM.REG0x5.bits.chspi = 0xc; + CAL_WR_TRXREGS(0x5); + delay100us(1);//delay 100us for RFPLL + + BK7231N_RC_REG.REG0x52->bits.TXIQSWAP = 1; /* I/Q SWAP*/ + return 0; +} + +INT32 bk7011_cal_rx_iq() +{ + // INT32 rx_dc_i_rd, rx_dc_q_rd; + INT32 rx_amp_err_rd, rx_phase_err_rd, rx_ty2_rd; + INT32 rx_amp_err_wr; + INT32 rx_phase_err_wr; + float amp_err, phase_err, ty2_err; + INT32 gold_index = 0; + INT32 i, curr, value, value1, value2; + //bk7011_load_rxiq_init_cfg(); //v1.5 + + /*step 1*/ + BK7231N_RC_REG.REG0x1C->bits.FRXON = 1; + BK7231N_RC_REG.REG0x1C->bits.FTXON = 1; + + BK7231N_TRX_RAM.REG0xF.bits.tssi_cal_en = 0; + BK7231N_TRX_RAM.REG0xF.bits.sinad_rx_en = 0; + CAL_WR_TRXREGS(0xF); + +#if 0 + BK7231N_TRX_RAM.REG0x9->bits.grxi2vspi10 = 1; //12dB + BK7231N_TRX_RAM.REG0x9->bits.agcrxfeEn = 0; //disable agc + + BK7231N_TRX_RAM.REG0x7->bits.autorxifgen = 0;//disable agc + BK7231N_TRX_RAM.REG0x7->bits.spilpfrxg30 = 0x0a; //33dB; + + //BK7231N_TRX_RAM.REG0x7->bits.digdcoen = 0; + CAL_WR_TRXREGS(0x7); + CAL_WR_TRXREGS(0x9); +#endif + + BK7231N_TRX_RAM.REG0xE.value = TRX_REG_0XE_RXIQ_VAL; + CAL_WR_TRXREGS(0xE); + //BK7231N_TRX_RAM.REG0xC.value = TRX_REG_0XC_RXIQ_VAL; + bk7011_set_tx_pa(gi_cal_rx_iq_pa_dgainPA30, gi_cal_rx_iq_pa_dgainbuf30, 4, 4); + + BK7231N_RC_REG.REG0x19->bits.FCH0B = 0x1a;//decrease 6dB + + + /*searching...*/ + BK7231N_RC_REG.REG0x3E->bits.RXCALEN = 1; + BK7231N_RC_REG.REG0x4C->bits.TESTPATTERN = 2; + BK7231N_RC_REG.REG0x4D->bits.TXSINMODE = 0; + BK7231N_RC_REG.REG0x4D->bits.TXSINAMP = 0x04; // increase 6dB + BK7231N_RC_REG.REG0x4D->bits.TXSINF = 179; // 7MHz; + cal_delay_100us(6*gcali_context.gst_rx_adc); + cpu_delay(500 * DELAY1US); + + BK7231N_RC_REG.REG0x41->bits.RXDCIWR = 0x0; + BK7231N_RC_REG.REG0x41->bits.RXDCQWR = 0x0; + + value = 0; + value1 = 0; + value2 = 0; + for(i = 0; i < 2; i ++) + { + curr = BK7231N_RC_REG.REG0x3F->bits.RXAMPERRRD; + value += curr - ((curr < BK_TX_DAC_SIGNED_MIN) ? 0: BK_TX_DAC_UNSIGNED_MAX); + curr = BK7231N_RC_REG.REG0x3F->bits.RXPHASEERRRD; + value1 += curr - ((curr < BK_TX_DAC_SIGNED_MIN) ? 0: BK_TX_DAC_UNSIGNED_MAX); + curr = BK7231N_RC_REG.REG0x40->bits.RXTY2RD; + value2 += curr - ((curr < BK_TX_DAC_SIGNED_MIN) ? 0: BK_TX_DAC_UNSIGNED_MAX); + cpu_delay(gcali_context.gst_rx_adc); + } + rx_amp_err_rd = value / 2; + rx_phase_err_rd = value1 / 2; + rx_ty2_rd = value2 / 2; + + if (1) // by gwf + { + int rx_amp_err_rd_temp; + int rx_phase_err_rd_temp; + int rx_ty2_rd_temp; + if (rx_amp_err_rd & 0x200) + { + rx_amp_err_rd_temp = rx_amp_err_rd | 0xFFFFFC00; + } + else + { + rx_amp_err_rd_temp = rx_amp_err_rd & 0x000003FF; + } + if (rx_phase_err_rd & 0x200) + { + rx_phase_err_rd_temp = rx_phase_err_rd | 0xFFFFFC00; + } + else + { + rx_phase_err_rd_temp = rx_phase_err_rd & 0x000003FF; + } + if (rx_ty2_rd & 0x200) + { + rx_ty2_rd_temp = rx_ty2_rd | 0xFFFFFC00; + } + else + { + rx_ty2_rd_temp = rx_ty2_rd & 0x000003FF; + } + gcali_result.rx_amp_err_rd = rx_amp_err_rd_temp; + gcali_result.rx_phase_err_rd = rx_phase_err_rd_temp; + gcali_result.rx_ty2_rd = rx_ty2_rd_temp; + } + else + { + CAL_FATAL("[rx_iq]rx_amp_err_rd: 0x%03x\r\n", rx_amp_err_rd ); + CAL_FATAL("[rx_iq]rx_phase_err_rd: 0x%03x\r\n", rx_phase_err_rd ); + CAL_FATAL("[rx_iq]rx_ty2_rd: 0x%03x\r\n", rx_ty2_rd ); + } + + amp_err = 1.0 * rx_amp_err_rd / 1024; + phase_err = 1.0 * rx_phase_err_rd / 1024; + ty2_err = 1.0 * rx_ty2_rd / 1024; + + rx_amp_err_wr = (INT32) (512 * (ty2_err + 1) / (amp_err + 1)); + rx_phase_err_wr = (INT32) (512 * phase_err * (ty2_err + 1)); + + + + BK7231N_RC_REG.REG0x42->bits.RXPHASEERRWR = rx_phase_err_wr; + BK7231N_RC_REG.REG0x42->bits.RXAMPERRWR = rx_amp_err_wr; + BK7231N_RC_REG.REG0x3E->bits.RXCOMPEN = 1; + BK7231N_RC_REG.REG0x3E->bits.RXCALEN = 0; + + gcali_result.grx_amp_err_wr = rx_amp_err_wr; + gcali_result.grx_phase_err_wr = rx_phase_err_wr; + + CAL_PRT("grx_amp_err_wr:0x%03x\r\n", rx_amp_err_wr); + CAL_PRT("grx_phase_err_wr:0x%03x\r\n", rx_phase_err_wr); + + gold_index = (rx_amp_err_wr << 16 ) + rx_phase_err_wr; + /* restore changed registers */ + BK7231N_TRX_RAM.REG0xC.value = TRX_REG_0XC_VAL; + BK7231N_TRX_RAM.REG0x9.bits.agcrxfeEn = 1; //enable agc + BK7231N_TRX_RAM.REG0x7.bits.autorxifgen = 1;//ensable agc + + CAL_WR_TRXREGS(0x7); + CAL_WR_TRXREGS(0x9); + CAL_WR_TRXREGS(0xC); + + return gold_index; +} + +void bk7011_set_rx_avg_dc(void) +{ + INT32 rx_dc_i_rd, rx_dc_q_rd; + + BK7231N_RC_REG.REG0x3E->bits.RXCOMPEN = 0; + BK7231N_RC_REG.REG0x3C->bits.RXAVGMODE = 0; + BK7231N_RC_REG.REG0x3C->bits.RXDCCALEN = 1; + cal_delay_100us(gcali_context.gst_rx_adc); + BK7231N_RC_REG.REG0x3C->bits.RXDCCALEN = 0; + + rx_dc_i_rd = BK7231N_RC_REG.REG0x3C->bits.RXAVGIRD; + rx_dc_q_rd = BK7231N_RC_REG.REG0x3C->bits.RXAVGQRD; + BK7231N_RC_REG.REG0x41->bits.RXDCIWR = rx_dc_i_rd; + BK7231N_RC_REG.REG0x41->bits.RXDCQWR = rx_dc_q_rd; + + BK7231N_RC_REG.REG0x3E->bits.RXCOMPEN = 1; + + return; +} + +INT32 bk7011_load_calibration_cfg(void) +{ + BK7231N_RC_REG.REG0x0->value = BK7231N_RC_REG.REG0x0->value; + BK7231N_RC_REG.REG0x1->value = BK7231N_RC_REG.REG0x1->value; + BK7231N_RC_REG.REG0x5->value = BK7231N_RC_REG.REG0x5->value ; + BK7231N_RC_REG.REG0x8->value = BK7231N_RC_REG.REG0x8->value; + BK7231N_RC_REG.REG0xB->value = BK7231N_RC_REG.REG0xB->value; + BK7231N_RC_REG.REG0x11->value = BK7231N_RC_REG.REG0x11->value; + BK7231N_RC_REG.REG0x19->value = BK7231N_RC_REG.REG0x19->value; + BK7231N_RC_REG.REG0x1E->value = BK7231N_RC_REG.REG0x1E->value; + + /**********NEW ADDED************/ + BK7231N_RC_REG.REG0x3C->value = BK7231N_RC_REG.REG0x3C->value; + BK7231N_RC_REG.REG0x3E->value = BK7231N_RC_REG.REG0x3E->value; + BK7231N_RC_REG.REG0x3F->value = BK7231N_RC_REG.REG0x3F->value; + BK7231N_RC_REG.REG0x40->value = BK7231N_RC_REG.REG0x40->value; + BK7231N_RC_REG.REG0x41->value = BK7231N_RC_REG.REG0x41->value; + BK7231N_RC_REG.REG0x42->value = BK7231N_RC_REG.REG0x42->value ; + BK7231N_RC_REG.REG0x4C->value = BK7231N_RC_REG.REG0x4C->value; + BK7231N_RC_REG.REG0x4D->value = BK7231N_RC_REG.REG0x4D->value; + BK7231N_RC_REG.REG0x4F->value = BK7231N_RC_REG.REG0x4F->value; + BK7231N_RC_REG.REG0x50->value = BK7231N_RC_REG.REG0x50->value; + BK7231N_RC_REG.REG0x51->value = BK7231N_RC_REG.REG0x51->value; + BK7231N_RC_REG.REG0x52->value = BK7231N_RC_REG.REG0x52->value; + BK7231N_RC_REG.REG0x54->value = BK7231N_RC_REG.REG0x54->value; + BK7231N_RC_REG.REG0x5C->value = BK7231N_RC_REG.REG0x5C->value; + + while(BK7231N_RC_REG.REG0x1->value & 0x0FFFFFFF) + { + cpu_delay(1); + } + + CAL_WR_TRXREGS(0x0); + CAL_WR_TRXREGS(0x1); + CAL_WR_TRXREGS(0x2); + CAL_WR_TRXREGS(0x3); + CAL_WR_TRXREGS(0x4); + CAL_WR_TRXREGS(0x5); + CAL_WR_TRXREGS(0x6); + CAL_WR_TRXREGS(0x7); + CAL_WR_TRXREGS(0x8); + CAL_WR_TRXREGS(0x9); + CAL_WR_TRXREGS(0xA); + CAL_WR_TRXREGS(0xB); + CAL_WR_TRXREGS(0xC); + CAL_WR_TRXREGS(0xD); + BK7231N_RC_REG.REG0x1A->value = BK7231N_TRX_RAM.REG0xD.value; + CAL_WR_TRXREGS(0xE); + CAL_WR_TRXREGS(0xF); + CAL_WR_TRXREGS(0x10); + CAL_WR_TRXREGS(0x11); + CAL_WR_TRXREGS(0x12); + CAL_WR_TRXREGS(0x13); + CAL_WR_TRXREGS(0x14); + CAL_WR_TRXREGS(0x15); + CAL_WR_TRXREGS(0x16); + CAL_WR_TRXREGS(0x17); + CAL_WR_TRXREGS(0x18); + CAL_WR_TRXREGS(0x19); + CAL_WR_TRXREGS(0x1A); + CAL_WR_TRXREGS(0x1B); + + BK7231N_TRX_RAM.REG0x7.bits.autorxifgen = 1; + BK7231N_TRX_RAM.REG0x7.bits.dig_dcoen = 1; + BK7231N_TRX_RAM.REG0x7.bits.spilpfrxg30 = 5; + CAL_WR_TRXREGS(0x7); + + CAL_PRT("[%s:%d]v=0x%x,0x%x\n", __FUNCTION__, __LINE__, gcali_result.gtx_ifilter_corner, gcali_result.gtx_qfilter_corner); + rwnx_cal_set_lpfcap_iq(gcali_result.gtx_ifilter_corner, gcali_result.gtx_qfilter_corner); + + bk7011_set_rx_avg_dc(); // 11/11/2014 + + return 0; +} + +void bk7011_set_tx_after_cal(void) +{ + BK7231N_RC_REG.REG0x0->bits.forceenable = 0; + cpu_delay(1); + BK7231N_RC_REG.REG0x19->bits.FCH0EN = 1; + BK7231N_RC_REG.REG0x19->bits.FCH0SHDN = 1; + BK7231N_RC_REG.REG0x19->bits.FCH0RXEN = 0; + BK7231N_RC_REG.REG0x19->bits.FCH0TXEN = 1; + BK7231N_RC_REG.REG0x1C->bits.FRXON = 0; + BK7231N_RC_REG.REG0x1C->bits.FTXON = 1; + BK7231N_RC_REG.REG0x4C->bits.TESTPATTERN = 0; +#if DIFFERENCE_PIECES_CFG + BK7231N_RC_REG.REG0x0->bits.ch0en = 0; +#endif +} + +void bk7011_set_rx_after_cal(void) +{ +#if 0 + BK7231N_RC_REG.REG0x0->bits.forceenable = 0; + cpu_delay(1); + BK7231N_RC_REG.REG0x19->bits.FCH0EN = 1; + BK7231N_RC_REG.REG0x19->bits.FCH0SHDN = 1; + BK7231N_RC_REG.REG0x19->bits.FCH0RXEN = 1; + BK7231N_RC_REG.REG0x19->bits.FCH0TXEN = 0; + BK7231N_RC_REG.REG0x1C->bits.FRXON = 1; + BK7231N_RC_REG.REG0x1C->bits.FTXON = 0; + BK7231N_RC_REG.REG0x4C->bits.TESTPATTERN = 0; +#endif +#if DIFFERENCE_PIECES_CFG + BK7231N_RC_REG.REG0x0->bits.ch0en = 0; +#endif + BK7231N_RC_RAM.REG0x3C.bits.RXHPFBYPASS = 0; + BK7231N_TRX_RAM.REG0xE.value = 0xDA01BCF0; + CAL_WR_TRXREGS(0xE); +} + +extern void mpb_tx_mode(void); + +#define CALI_DPD_TEST 0 +#if CALI_DPD_TEST +#define I_TABLE_ADDR 0x01050400 +#define Q_TABLE_ADDR 0x01050600 + +static UINT16 i_table_val[256] = +{ + 0, 6, 13, 19, 26, 35, 40, 47, 52, 57, 68, 73, 76, 82, 88, 91, 96, 102, 107, 107, 118, 118, 120, 127, 132, 134, 139, 141, 146, 149, 152, 158, 161, 161, 163, 164, 168, 172, 172, 176, 181, 177, 179, 181, 185, 187, 189, 185, 191, 195, 196, 195, 196, 197, 203, 198, 204, 201, 207, 199, 206, 207, 207, 207, 207, 210, 210, 212, 214, 215, 215, 215, 206, 216, 215, 221, 217, 219, 215, 219, 222, 222, 225, 229, 225, 223, 228, 226, 226, 229, 229, 226, 225, 227, 226, 226, 228, 232, 230, 229, 230, 231, 230, 231, 234, 235, 236, 238, 241, 244, 245, 247, 248, 251, 252, 255, 255, 258, 259, 262, 263, 265, 267, 268, 271, 272, 275, 275, 278, 280, 282, 284, 287, 288, 291, 293, 295, 297, 299, 301, 304, 306, 308, 310, 312, 314, 317, 319, 321, 323, 325, 327, 330, 332, 334, 336, 338, 341, 343, 345, 347, 349, 351, 354, 356, 358, 360, 362, 364, 367, 369, 371, 373, 375, 377, 380, 382, 384, 386, 388, 390, 393, 395, 397, 399, 401, 403, 406, 408, 410, 412, 414, 416, 419, 421, 423, 425, 427, 429, 432, 434, 436, 438, 440, 442, 445, 447, 449, 451, 453, 455, 458, 460, 462, 464, 466, 468, 471, 473, 475, 477, 479, 481, 484, 486, 488, 490, 492, 495, 497, 499, 501, 503, 505, 508, 510, 512, 514, 516, 518, 521, 523, 525, 527, 529, 531, 534, 536, 538, 540, 542, 544, 547, 549, 551, 562 +}; + +static UINT16 q_table_val[256] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 1, 5, 8, 5, 9, 6, 5, 7, 4, 7, 8, 17, 13, 12, 14, 15, 12, 12, 18, 12, 13, 16, 16, 17, 19, 20, 24, 22, 30, 23, 21, 24, 30, 27, 26, 24, 27, 26, 30, 28, 30, 32, 31, 31, 32, 32, 33, 35, 35, 33, 35, 34, 32, 32, 32, 34, 33, 32, 31, 32, 30, 33, 29, 30, 29, 30, 29, 29, 28, 27, 29, 27, 28, 26, 26, 26, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 30, 30, 30, 30, 30, 31, 31, 31, 31, 31, 32, 32, 32, 32, 32, 33, 33, 33, 33, 33, 34, 34, 34, 34, 34, 35, 35, 35, 35, 35, 36, 36, 36, 36, 36, 37, 37, 37, 37, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 42, 42, 42, 42, 42, 43, 43, 43, 43, 43, 44, 44, 44, 44, 44, 45, 45, 45, 45, 45, 46, 46, 46, 46, 46, 47, 47, 47, 47, 48, 48, 48, 48, 48, 49, 49, 49, 49, 49, 50, 50, 50, 50, 50, 51, 51, 51, 51, 51, 52, 52, 48 +}; + +UINT32 bk7211_cal_tx_dpd_load(void) +{ + + UINT16 *i_tbl_addr = (UINT16 *)I_TABLE_ADDR; + UINT16 *q_tbl_addr = (UINT16 *)Q_TABLE_ADDR; + UINT16 k; + + BK7231N_RC_REG.REG0x4C->bits.DPDEN = 0; + + os_memcpy(i_tbl_addr, (UINT16 *)&i_table_val[0], 256 * 2); + os_memcpy(q_tbl_addr, (UINT16 *)&q_table_val[0], 256 * 2); + +#if 1 + for(k = 0; k < 256; k++) + { + i_tbl_addr[k] = 1; + q_tbl_addr[k] = 0; + } +#endif + return 0; + +} +#endif + +#if CAL_RESULT_TO_FLASH +void write_cal_result_to_flash(void) +{ + UINT32 param; + UINT32 param1; + char cTemp[sizeof(BK7231N_RC_RAM) + sizeof(BK7231N_TRX_RAM)]; + char cTemp1[sizeof(BK7231N_RC_RAM) + sizeof(BK7231N_TRX_RAM)]; + + CAL_FLASH_PRT("write cal result to flash\r\n"); + +// flash_ctrl(CMD_FLASH_READ_SR, ¶m); +// CAL_FLASH_PRT("param = 0x%x\r\n", param); + #if CFG_SUPPORT_ALIOS + hal_flash_dis_secure(0, 0, 0); + #else + bk_flash_enable_security(NONE); + #endif +// CAL_FLASH_PRT("param1 = 0x%x\r\n", param1); + +// param = CAL_RESULT_FLASH_ADDR; +// flash_ctrl(CMD_FLASH_ERASE_SECTOR, ¶m); + flash_erase_sector(CAL_RESULT_FLASH_ADDR); + + memcpy(cTemp, BK7231N_RC_RAM, sizeof(BK7231N_RC_RAM)); + memcpy(cTemp+sizeof(BK7231N_RC_RAM), BK7231N_TRX_RAM, sizeof(BK7231N_TRX_RAM)); +// memset(cTemp, 0, sizeof(cTemp)); + flash_write(cTemp, sizeof(cTemp), CAL_RESULT_FLASH_ADDR); + flash_read(cTemp1, sizeof(cTemp1), CAL_RESULT_FLASH_ADDR); + if (memcmp(cTemp, cTemp1, sizeof(cTemp1)) == 0) + { + CAL_FLASH_PRT("memcmp OK\r\n"); + } + else + { + CAL_FLASH_PRT("memcmp fail\r\n"); + } + +// param = 2 | ((param&0x00FFFF)<<8); + #if CFG_SUPPORT_ALIOS + hal_flash_enable_secure(0, 0, 0); + #else + bk_flash_enable_security(FLASH_UNPROTECT_LAST_BLOCK); + #endif +// param = 0; +// flash_ctrl(CMD_FLASH_READ_SR, ¶m); +// CAL_FLASH_PRT("param = 0x%x\r\n", param); + + CAL_FLASH_PRT("write cal result to flash OK\r\n"); +} +#endif + +char read_cal_result_from_flash(void) +{ +#if CAL_RESULT_TO_FLASH + char cTemp[sizeof(BK7231N_RC_RAM) + sizeof(BK7231N_TRX_RAM)]; + + CAL_FLASH_PRT("read_cal_result_from_flash\r\n"); + memset(cTemp, 0, sizeof(cTemp)); + flash_read(cTemp, sizeof(cTemp), CAL_RESULT_FLASH_ADDR); + if ((cTemp[0] == 0xFF) && (cTemp[4] == 0xFF) && (cTemp[8] == 0xFF) && (cTemp[12] == 0xFF)) + { + return 0; + } + else + { + memcpy(BK7231N_RC_RAM, cTemp, sizeof(BK7231N_RC_RAM)); + memcpy(BK7231N_TRX_RAM, cTemp+sizeof(BK7231N_RC_RAM), sizeof(BK7231N_TRX_RAM)); + rwnx_cal_load_default_result(); + rwnx_cal_load_trx_rcbekn_reg_val(); +// printf_trx_rc_value(); + CAL_FLASH_PRT("read cal result from flash OK\r\n"); + return 1; + } +#else + return 0; +#endif +} + +void load_reg (void) +{ + BK7231N_RC_REG.REG0x0->value = BK7231N_RC_RAM.REG0x0.value; + BK7231N_RC_REG.REG0x1->value = BK7231N_RC_RAM.REG0x1.value | 0xFFFFFFF; + BK7231N_RC_REG.REG0x5->value = BK7231N_RC_RAM.REG0x5.value; + BK7231N_RC_REG.REG0x8->value = BK7231N_RC_RAM.REG0x8.value; + BK7231N_RC_REG.REG0xB->value = BK7231N_RC_RAM.REG0xB.value; + BK7231N_RC_REG.REG0xE->value = BK7231N_RC_RAM.REG0xE.value; + BK7231N_RC_REG.REG0x11->value = BK7231N_RC_RAM.REG0x11.value; + BK7231N_RC_REG.REG0x19->value = BK7231N_RC_RAM.REG0x19.value; + BK7231N_RC_REG.REG0x1C->value = BK7231N_RC_RAM.REG0x1C.value; + BK7231N_RC_REG.REG0x1E->value = BK7231N_RC_RAM.REG0x1E.value; + + /**********NEW ADDED************/ + BK7231N_RC_REG.REG0x3C->value = BK7231N_RC_RAM.REG0x3C.value; + BK7231N_RC_REG.REG0x3E->value = BK7231N_RC_RAM.REG0x3E.value; + BK7231N_RC_REG.REG0x3F->value = BK7231N_RC_RAM.REG0x3F.value; + BK7231N_RC_REG.REG0x40->value = BK7231N_RC_RAM.REG0x40.value; + BK7231N_RC_REG.REG0x41->value = BK7231N_RC_RAM.REG0x41.value; + BK7231N_RC_REG.REG0x42->value = BK7231N_RC_RAM.REG0x42.value; + BK7231N_RC_REG.REG0x4C->value = BK7231N_RC_RAM.REG0x4C.value; + BK7231N_RC_REG.REG0x4D->value = BK7231N_RC_RAM.REG0x4D.value; + BK7231N_RC_REG.REG0x4F->value = BK7231N_RC_RAM.REG0x4F.value; + BK7231N_RC_REG.REG0x50->value = BK7231N_RC_RAM.REG0x50.value; + BK7231N_RC_REG.REG0x51->value = BK7231N_RC_RAM.REG0x51.value; + BK7231N_RC_REG.REG0x52->value = BK7231N_RC_RAM.REG0x52.value; + BK7231N_RC_REG.REG0x54->value = BK7231N_RC_RAM.REG0x54.value; + BK7231N_RC_REG.REG0x55->value = BK7231N_RC_RAM.REG0x55.value; + BK7231N_RC_REG.REG0x5C->value = BK7231N_RC_RAM.REG0x5C.value; + + BK7231N_RC_REG.REG0x4E->value = BK7231N_RC_RAM.REG0x4E.value; + BK7231N_RC_REG.REG0x5A->value = BK7231N_RC_RAM.REG0x5A.value; + BK7231N_RC_REG.REG0x5B->value = BK7231N_RC_RAM.REG0x5B.value; + BK7231N_RC_REG.REG0x6A->value = BK7231N_RC_RAM.REG0x6A.value; + + while(BK7231N_RC_REG.REG0x1->value & 0x0FFFFFFF) + { + cpu_delay(1); + } + + BK7231N_TRX_REG.REG0x0->value = BK7231N_TRX_RAM.REG0x0.value; + BK7231N_TRX_REG.REG0x1->value = BK7231N_TRX_RAM.REG0x1.value; + BK7231N_TRX_REG.REG0x2->value = BK7231N_TRX_RAM.REG0x2.value; + BK7231N_TRX_REG.REG0x3->value = BK7231N_TRX_RAM.REG0x3.value; + BK7231N_TRX_REG.REG0x4->value = BK7231N_TRX_RAM.REG0x4.value; + BK7231N_TRX_REG.REG0x5->value = BK7231N_TRX_RAM.REG0x5.value; + BK7231N_TRX_REG.REG0x6->value = BK7231N_TRX_RAM.REG0x6.value; + BK7231N_TRX_REG.REG0x7->value = BK7231N_TRX_RAM.REG0x7.value; + BK7231N_TRX_REG.REG0x8->value = BK7231N_TRX_RAM.REG0x8.value; + BK7231N_TRX_REG.REG0x9->value = BK7231N_TRX_RAM.REG0x9.value; + BK7231N_TRX_REG.REG0xA->value = BK7231N_TRX_RAM.REG0xA.value; + BK7231N_TRX_REG.REG0xB->value = BK7231N_TRX_RAM.REG0xB.value; + BK7231N_TRX_REG.REG0xC->value = BK7231N_TRX_RAM.REG0xC.value; + BK7231N_TRX_REG.REG0xD->value = BK7231N_TRX_RAM.REG0xD.value; + BK7231N_TRX_REG.REG0xE->value = BK7231N_TRX_RAM.REG0xE.value; + BK7231N_TRX_REG.REG0xF->value = BK7231N_TRX_RAM.REG0xF.value; + BK7231N_TRX_REG.REG0x10->value = BK7231N_TRX_RAM.REG0x10.value; + BK7231N_TRX_REG.REG0x11->value = BK7231N_TRX_RAM.REG0x11.value; + BK7231N_TRX_REG.REG0x12->value = BK7231N_TRX_RAM.REG0x12.value; + BK7231N_TRX_REG.REG0x13->value = BK7231N_TRX_RAM.REG0x13.value; + BK7231N_TRX_REG.REG0x14->value = BK7231N_TRX_RAM.REG0x14.value; + BK7231N_TRX_REG.REG0x15->value = BK7231N_TRX_RAM.REG0x15.value; + BK7231N_TRX_REG.REG0x16->value = BK7231N_TRX_RAM.REG0x16.value; + BK7231N_TRX_REG.REG0x17->value = BK7231N_TRX_RAM.REG0x17.value; + BK7231N_TRX_REG.REG0x18->value = BK7231N_TRX_RAM.REG0x18.value; + BK7231N_TRX_REG.REG0x19->value = BK7231N_TRX_RAM.REG0x19.value; + BK7231N_TRX_REG.REG0x1A->value = BK7231N_TRX_RAM.REG0x1A.value; + BK7231N_TRX_REG.REG0x1B->value = BK7231N_TRX_RAM.REG0x1B.value; + + while(BK7231N_RC_REG.REG0x1->value & 0x0FFFFFFF) + { + cpu_delay(1); + } + return ; +} + +void rwnx_cal_apply_reg_patch(UINT32 device_id) +{ + UINT32 chip_id; + + chip_id = sctrl_ctrl(CMD_GET_CHIP_ID, NULL); + if (CHIP_ID_BK7231N != chip_id) + { + return; + } + + switch (device_id & DEVICE_ID_MASK) + { + case DEVICE_ID_BK7231N_P & DEVICE_ID_MASK: + BK7231N_TRX_RAM.REG0xB.value = 0xCA984210; + BK7231N_TRX_RAM.REG0xC.bits.Dibias = 7; + CAL_WR_TRXREGS(0xB); + CAL_WR_TRXREGS(0xC); + break; + + default: + break; + } +} + +void sctrl_dpll_int_open(void); +void calibration_main(void) +{ + volatile UINT32 txpwr; + + if (CALI_MODE_UNKNOWN == gcali_context.cali_mode) + { + bk7011_get_rfcali_mode(); + } +#if DIFFERENCE_PIECES_CFG + bk7011_get_txpwr_config_reg(); +#endif + + gcali_context.device_id = sctrl_ctrl(CMD_GET_DEVICE_ID, NULL); + gcali_context.device_id &= DEVICE_ID_MASK; + + REG_WRITE((RCB_POWER_TABLE_ADDR + (0x34 * 4)), 0xE0B318E0);//E98B7150 + txpwr = REG_READ(RCB_POWER_TABLE_ADDR + (0x34 * 4)); + (void)txpwr; + + /* remove this workaround after using 26MHz as saradc source */ +#if 0 + analog1 = sctrl_ctrl(CMD_SCTRL_GET_ANALOG1, NULL); + analog1 |= (DCO_AMSEL_BIT); + sctrl_ctrl(CMD_SCTRL_SET_ANALOG1, (void *)&analog1); +#endif + + memcpy(&BK7231N_TRX_RAM, BK7231N_TRX_ROM, sizeof(BK7231N_TRX_RAM)); + memcpy(&BK7231N_RC_RAM, BK7231N_RC_ROM, sizeof(BK7231N_RC_RAM)); + rwnx_cal_apply_reg_patch(gcali_context.device_id); + + //REG_WRITE((0x0802800 + (18 * 4)), 0x02); + BK7231N_RC_REG.REG0x4C->bits.TXCOMPDIS = 0; + bk7011_cal_ready(); + bk7011_cal_bias(); + + bk7011_cal_dpll(); + sctrl_dpll_int_open(); + + BK7231N_TRX_RAM.REG0xA.value = TRX_REG_0XA_VAL; + CAL_WR_TRXREGS(0xA); + BK7231N_TRX_RAM.REG0xC.value = TRX_REG_0XC_VAL; + CAL_WR_TRXREGS(0xC); + BK7231N_RC_REG.REG0x3C->bits.RXHPFBYPASS = 1;// Disable HPF for calibration + + + if (read_cal_result_from_flash() == 1) + { + rwnx_cal_apply_reg_patch(gcali_context.device_id); + return; + } + + +// BK7231N_TRX_RAM.REG0x7->bits.chin60 = 0x00;//2400MHz descrease the external interference +// CAL_WR_TRXREGS(0x7); + BK7231N_TRX_RAM.REG0x5.bits.chspi = 0x00;//2400MHz descrease the external interference + CAL_WR_TRXREGS(0x5); + delay100us(1);//delay 100us for RFPLL + + bk7011_tx_cal_en(); + bk7011_cal_bias(); + + bk7011_cal_tx_dc_new(TX_DC_CAL); + + bk7011_cal_tx_output_power(TX_IQ_POWER_CAL); // First cal just to enable BK7231 TX work for temp. balance + + bk7011_cal_tx_gain_imbalance(TX_GAIN_IMB_CAL); + + bk7011_cal_tx_phase_imbalance(TX_PHASE_IMB_CAL); + + bk7011_cal_tx_filter_corner(); + + BK7231N_TRX_RAM.REG0x5.bits.chspi = 0x5d;//2495MHz + CAL_WR_TRXREGS(0x5); + delay100us(1);//delay 100us for RFPLL + + + bk7011_cal_bias(); + + if(bk7011_is_rfcali_mode_auto()) + { + bk7011_cal_auto_tx_power(); + } + + BK7231N_TRX_RAM.REG0x5.bits.chspi = 0xc;//fix to this channel for power cal. + CAL_WR_TRXREGS(0x5); + delay100us(1);//delay 100us for RFPLL + + //20210507 remove to avoid large signal + //*goldval = bk7011_cal_tx_output_power(TX_WANTED_POWER_CAL); // Actual Power cal. + + bk7011_set_tx_after_cal(); + rwnx_tx_cal_save_cal_result();//by yiming 20170315 + + BK7231N_TRX_RAM.REG0x5.bits.chspi = 0x5d;//2495MHz + CAL_WR_TRXREGS(0x5); + delay100us(1);//delay 100us for RFPLL + + bk7011_rx_cal_en(); + bk7011_cal_rx_adc_dlym();//add by desheng + bk7011_cal_rx_dc(); + + bk7011_tx_cal_en(); + + BK7231N_TRX_RAM.REG0x5.bits.chspi = 0x5d;//2495MHz + CAL_WR_TRXREGS(0x5); + delay100us(1);//delay 100us for RFPLL + + + //20170804 by yiming + //*goldval = bk7011_cal_tx_output_power(TX_IQ_LOOPBACK_POWER_CAL); + bk7011_cal_bias(); + bk7011_cal_pll(); + delay100us(1);//delay 100us for RFPLL + + //*goldval = bk7011_cal_tx_output_power(TX_IQ_LOOPBACK_POWER_CAL); + + // *goldval = bk7011_cal_tx_dc_new(TX_DC_LOOPBACK_CAL_IQ);//Loopback DC cal. + + //*goldval = bk7011_cal_tx_gain_imbalance(TX_GAIN_LOOPBACK_IMB_CAL); + + //*goldval = bk7011_cal_tx_phase_imbalance(TX_PHASE_LOOPBACK_IMB_CAL); + + //bk7011_rx_cal_en(); + //bk7011_cal_rx_iq(); + + + bk7011_load_calibration_cfg(); + bk7011_set_rx_after_cal(); + //REG_WRITE((0x0802800 + (18 * 4)), 0x00); + + //rwnx_rx_cal_save_cal_result(); + rwnx_cal_load_default_result(); + //rwnx_cal_read_current_cal_result(); + BK7231N_RC_REG.REG0x4C->bits.TXCOMPDIS = 0; + + rwnx_tx_cal_save_cal_result();//by yiming 20170315 + rwnx_cal_load_trx_rcbekn_reg_val(); + +#if CALI_DPD_TEST + bk7211_cal_tx_dpd_load(); +#endif + bk7011_cal_dpll(); + sctrl_dpll_int_open(); +/* + cpu_delay(100); + *goldval = bk7011_cal_tx_output_power(TX_WANTED_POWER_CAL); // +*/ +#if CAL_RESULT_TO_FLASH + write_cal_result_to_flash(); +// printf_trx_rc_value(); +#endif + + bk7011_cal_saradc_close(cali_saradc_desc); + + bk_printf("calibration_main over\r\n"); + + + BK7231N_TRX_RAM.REG0x0.bits.tssi_atten = 0x2; + CAL_WR_TRXREGS(0x0); + BK7231N_TRX_RAM.REG0xA.bits.Dvncref=0x3; + CAL_WR_TRXREGS(0xA); + BK7231N_TRX_RAM.REG0xC.value = TRX_REG_0XC_VAL; + CAL_WR_TRXREGS(0xC); + BK7231N_TRX_RAM.REG0xD.value = TRX_REG_0XD_VAL; + CAL_WR_TRXREGS(0xD); + BK7231N_RC_REG.REG0x1A->value = BK7231N_TRX_RAM.REG0xD.value; + rwnx_cal_apply_reg_patch(gcali_context.device_id); + +#if 0 + analog1 = sctrl_ctrl(CMD_SCTRL_GET_ANALOG1, NULL); + analog1 &= ~(DCO_AMSEL_BIT); + sctrl_ctrl(CMD_SCTRL_SET_ANALOG1, (void *)&analog1); +#endif + + return ; +} + +void turnoff_PA_in_temp_dect(void) +{ + CHECK_OPERATE_RF_REG_IF_IN_SLEEP(); + //dgainpga = BK7231N_TRX_REG.REG0xC->bits.dgainpga; + //BK7231N_TRX_RAM.REG0xC->bits.dgainpga = 0; + + //CAL_WR_TRXREGS(0xC); + CHECK_OPERATE_RF_REG_IF_IN_SLEEP_END(); +} + +void turnon_PA_in_temp_dect(void) +{ + CHECK_OPERATE_RF_REG_IF_IN_SLEEP(); + //BK7231N_TRX_RAM.REG0xC.bits.dgainpga = dgainpga; + //CAL_WR_TRXREGS(0xC); + CHECK_OPERATE_RF_REG_IF_IN_SLEEP_END(); +} + +#define MPB_ADDR_BASE (0x01060000) +#define SCTRL_BASE (0x00800000) +#define LA_ADDR (0x00808000) +void bk7011_la_sample_print(UINT32 isrx) +{ + UINT32 reg_val, i, len; + UINT8 *buf; + + // please do tx / rx before call the function + // tx, use txevm + // rx, use rxsens + + #define LA_SAMPLE_BUF_LEN (96 *1024) + buf = os_malloc(LA_SAMPLE_BUF_LEN); + if(!buf) { + os_printf("la_sample_print no buffer\r\n"); + return; + } + len = LA_SAMPLE_BUF_LEN / 4; + + REG_WRITE((LA_ADDR + 0x4*4), (UINT32)buf); + + if(1 == isrx) + { + //RX ADC Data + REG_WRITE((SCTRL_BASE + 0xd*4), 0x00040000); + REG_WRITE((LA_ADDR + 0x2*4), 0xfe000000); + REG_WRITE((LA_ADDR + 0x1*4), 0x0a000000); + } + else if(2 == isrx) + { + //RX DAC Data + REG_WRITE((SCTRL_BASE + 0xd*4), 0x00040000); + REG_WRITE((LA_ADDR + 0x2*4), 0xfe000000); + REG_WRITE((LA_ADDR + 0x1*4), 0x0c000000); + } + else + { + //TX DAC Data + REG_WRITE((SCTRL_BASE + 0xd*4), 0x00030000); + REG_WRITE((LA_ADDR + 0x2*4), 0x00700000); + REG_WRITE((LA_ADDR + 0x1*4), 0x00600000); + + BK7231N_TRX_RAM.REG0xF.bits.clkdac_inv = 0; + CAL_WR_TRXREGS(0xC); + } + + reg_val = 0x15; + reg_val |= (len << 12); + REG_WRITE((LA_ADDR + 0x0*4), reg_val); + + do + { + reg_val = REG_READ((LA_ADDR + 0x0*4)); + os_printf("abc:%x\r\n",reg_val&0x8); + } while((reg_val & 0x8) != 0x8); + + delay100us(100); + + reg_val = REG_READ((LA_ADDR + 0x0*4)); + reg_val = (reg_val & (~0x3)) | 0x00; + REG_WRITE((LA_ADDR + 0x0*4), reg_val); + + for(i = 0; i < len; i ++) + { + os_printf("%08x\r\n", *((uint32_t *)(buf+i*4))); + } + + os_free(buf); +} + +void bk7011_max_rxsens_setting(void) +{ + // cunliang20210407 keep signal/unsignal register the same, qunshan confirmed + if (get_ate_mode_state()) + { + return; + } + BK7231N_TRX_RAM.REG0x8.bits.isrxref10 = 3; + BK7231N_TRX_RAM.REG0x8.bits.isrxlna30 = 15; + CAL_WR_TRXREGS(0x8); +} + +void bk7011_normal_rxsens_setting(void) +{ + // cunliang20210407 keep signal/unsignal register the same, qunshan confirmed + if (get_ate_mode_state()) + { + return; + } + BK7231N_TRX_RAM.REG0x8.bits.isrxref10 = 2; + BK7231N_TRX_RAM.REG0x8.bits.isrxlna30 = 7; + CAL_WR_TRXREGS(0x8); +} + +void bk7011_default_rxsens_setting(void) +{ + // cunliang20210407 keep signal/unsignal register the same, qunshan confirmed + if (get_ate_mode_state()) + { + return; + } + BK7231N_TRX_RAM.REG0x8.bits.isrxref10 = 2; + BK7231N_TRX_RAM.REG0x8.bits.isrxlna30 = 7; + CAL_WR_TRXREGS(0x8); +} + +#include "str_pub.h" +static int rfcali_cfg_tssi_b(int argc, char **argv) +{ + int tssi_thred_b; + + if(argc != 2) + { + os_null_printf("rfcali_cfg_tssi 0-255(for b)\r\n"); + return 0; + } + + tssi_thred_b = os_strtoul(argv[1], NULL, 10); + + os_printf("cmd set tssi b_thred:%d\r\n", tssi_thred_b); + + bk7011_set_rf_config_tssithred_b(tssi_thred_b); + return 0; +} + +static int rfcali_cfg_tssi_g(int argc, char **argv) +{ + int tssi_thred_g; + + if(argc != 2) + { + os_null_printf("rfcali_cfg_tssi 0-255(for b)\r\n"); + return 0; + } + + tssi_thred_g = os_strtoul(argv[1], NULL, 10); + + os_printf("cmd set tssi g_thred:%d\r\n", tssi_thred_g); + + bk7011_set_rf_config_tssithred_g(tssi_thred_g); + return 0; +} + +static int rfcali_cfg_rate_dist(int argc, char **argv) +{ + int dist_b, dist_g, dist_n40, dist_ble; + + if(argc != 5) + { + os_null_printf("rfcali_cfg_rate_dist b g n40 ble (0-31)\r\n"); + return 0; + } + + dist_b = os_strtoul(argv[1], NULL, 10); + dist_g = os_strtoul(argv[2], NULL, 10); + dist_n40 = os_strtoul(argv[3], NULL, 10); + dist_ble = os_strtoul(argv[4], NULL, 10); + + if((dist_b > 31) || (dist_g > 31) || (dist_n40 > 31) || (dist_ble > 31)) + { + os_null_printf("rate_dist range:-31 - 31\r\n"); + return 0; + } + + if((dist_b < -31) || (dist_g < -31) || (dist_n40 < -31) || (dist_ble < -31)) + { + os_null_printf("rate_dist range:-31 - 31\r\n"); + return 0; + } + + //manual_cal_set_rate_dist_for_txpwr(dist_b, dist_g, dist_n40, dist_ble); + + return 0; +} + +static int rfcali_cfg_mode(int argc, char **argv) +{ + int rfcali_mode = 0; + + if(argc != 2) + { + os_printf("rfcali_mode 0/1\r\n"); + return 0; + } + + rfcali_mode = os_strtoul(argv[1], NULL, 10); + + if((rfcali_mode != CALI_MODE_AUTO) && (rfcali_mode != CALI_MODE_MANUAL)) + { + os_printf("rfcali_mode 0/1, %d\r\n", rfcali_mode); + return 0; + } + + bk7011_set_rfcali_mode(rfcali_mode); + + return 0; +} + +static int rfcali_show_data(int argc, char **argv) +{ + manual_cal_show_txpwr_tab(); + + return 0; +} + +#if CFG_SUPPORT_RTT +FINSH_FUNCTION_EXPORT_ALIAS(rfcali_cfg_tssi_b, __cmd_rfcali_cfg_tssi_b, rfcali cfg tssi); +FINSH_FUNCTION_EXPORT_ALIAS(rfcali_cfg_mode, __cmd_rfcali_cfg_mode, rfcali cfg mode); +FINSH_FUNCTION_EXPORT_ALIAS(rfcali_cfg_rate_dist, __cmd_rfcali_cfg_rate_dist, rfcali cfg rate_dist); +FINSH_FUNCTION_EXPORT_ALIAS(rfcali_cfg_tssi_g, __cmd_rfcali_cfg_tssi_g, rfcali cfg tssi); +FINSH_FUNCTION_EXPORT_ALIAS(rfcali_show_data, __cmd_rfcali_show_data, rfcali show data); +#else +void cmd_rfcali_cfg_mode(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + rfcali_cfg_mode(argc, argv); +} + +void cmd_rfcali_cfg_rate_dist(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + rfcali_cfg_rate_dist(argc, argv); +} + +void cmd_rfcali_cfg_tssi_g(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + rfcali_cfg_tssi_g(argc, argv); +} + +void cmd_rfcali_cfg_tssi_b(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + rfcali_cfg_tssi_b(argc, argv); +} + +void cmd_rfcali_show_data(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + rfcali_show_data(argc, argv); +} +#endif + +#endif /* CFG_SUPPORT_CALIBRATION */ + +#include "sys_ctrl.h" +void bk_dump_regs() +{ + bk_printf("0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", + BK7231N_RC_REG.REG0x0->value, + BK7231N_RC_REG.REG0x1->value, + BK7231N_RC_REG.REG0x5->value, + BK7231N_RC_REG.REG0x8->value, + BK7231N_RC_REG.REG0xB->value, + BK7231N_RC_REG.REG0xE->value, + BK7231N_RC_REG.REG0x11->value, + BK7231N_RC_REG.REG0x19->value); + bk_printf("0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", + BK7231N_RC_REG.REG0x1C->value, + BK7231N_RC_REG.REG0x1E->value, + BK7231N_RC_REG.REG0x3C->value, + BK7231N_RC_REG.REG0x3E->value, + BK7231N_RC_REG.REG0x3F->value, + BK7231N_RC_REG.REG0x40->value, + BK7231N_RC_REG.REG0x41->value, + BK7231N_RC_REG.REG0x42->value); + bk_printf("0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", + BK7231N_RC_REG.REG0x4C->value, + BK7231N_RC_REG.REG0x4D->value, + BK7231N_RC_REG.REG0x4F->value, + BK7231N_RC_REG.REG0x50->value, + BK7231N_RC_REG.REG0x51->value, + BK7231N_RC_REG.REG0x52->value, + BK7231N_RC_REG.REG0x54->value, + BK7231N_RC_REG.REG0x55->value); + bk_printf("0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", + BK7231N_RC_REG.REG0x5C->value, + BK7231N_RC_REG.REG0x4E->value, + BK7231N_RC_REG.REG0x5A->value, + BK7231N_RC_REG.REG0x5B->value, + BK7231N_RC_REG.REG0x6A->value, 0, 0, 0); + + bk_printf("0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", + BK7231N_TRX_REG.REG0x0->value, + BK7231N_TRX_REG.REG0x1->value, + BK7231N_TRX_REG.REG0x2->value, + BK7231N_TRX_REG.REG0x3->value, + BK7231N_TRX_REG.REG0x4->value, + BK7231N_TRX_REG.REG0x5->value, + BK7231N_TRX_REG.REG0x6->value, + BK7231N_TRX_REG.REG0x7->value); + bk_printf("0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", + BK7231N_TRX_REG.REG0x8->value, + BK7231N_TRX_REG.REG0x9->value, + BK7231N_TRX_REG.REG0xA->value, + BK7231N_TRX_REG.REG0xB->value, + BK7231N_TRX_REG.REG0xC->value, + BK7231N_TRX_REG.REG0xD->value, + BK7231N_TRX_REG.REG0xE->value, + BK7231N_TRX_REG.REG0xF->value); + bk_printf("0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", + BK7231N_TRX_REG.REG0x10->value, + BK7231N_TRX_REG.REG0x11->value, + BK7231N_TRX_REG.REG0x12->value, + BK7231N_TRX_REG.REG0x13->value, + BK7231N_TRX_REG.REG0x14->value, + BK7231N_TRX_REG.REG0x15->value, + BK7231N_TRX_REG.REG0x16->value, + BK7231N_TRX_REG.REG0x17->value); + bk_printf("0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", + BK7231N_TRX_REG.REG0x18->value, + BK7231N_TRX_REG.REG0x19->value, + BK7231N_TRX_REG.REG0x1A->value, + BK7231N_TRX_REG.REG0x1B->value, 0, 0, 0, 0); + + bk_printf("0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", + sctrl_analog_get(SCTRL_ANALOG_CTRL0), + sctrl_analog_get(SCTRL_ANALOG_CTRL1), + sctrl_analog_get(SCTRL_ANALOG_CTRL2), + sctrl_analog_get(SCTRL_ANALOG_CTRL3), + sctrl_analog_get(SCTRL_ANALOG_CTRL4), + sctrl_analog_get(SCTRL_ANALOG_CTRL5), + sctrl_analog_get(SCTRL_ANALOG_CTRL6), + 0); +} + +#endif // (CFG_SOC_NAME != SOC_BK7231) +// eof + diff --git a/beken_os/beken378/func/bk7011_cal/bk7231N_cal.h b/beken_os/beken378/func/bk7011_cal/bk7231N_cal.h new file mode 100755 index 0000000..cdd5764 --- /dev/null +++ b/beken_os/beken378/func/bk7011_cal/bk7231N_cal.h @@ -0,0 +1,1476 @@ +#ifndef _BK7231U_CAL_H_ +#define _BK7231U_CAL_H_ + +#include "uart_pub.h" + +#define CAL_DEBUG 1 +#if CAL_DEBUG +#define CAL_PRT null_prf +#define CAL_WARN null_prf// warning_prf +#define CAL_FATAL null_prf +#define CAL_TIM_PRT null_prf +#define CAL_FLASH_PRT os_printf +#else +#define CAL_PRT null_prf +#define CAL_WARN null_prf +#define CAL_FATAL null_prf +#define CAL_TIM_PRT null_prf +#define CAL_FLASH_PRT null_prf +#endif + +#if (CFG_SOC_NAME != SOC_BK7231) + +#define INCLUDE_OS + +//#define SCAN_IQ_FILTER_CORNER + +////Difference between pieces +#define DIFFERENCE_PIECES_CFG 0 + +//#define _11MBPS_MAX_POWER + +void delay05us(INT32 num); + +#define trx_reg_is_write(st_trxreg) while(BK7231N_RC_REG.REG0x1->value & st_trxreg) {cpu_delay(1);} + +#define DETECT_LOOPCNT 10 +#define GOLD_OUTPUT_POWER 56 +#define UNSIGNEDOFFSET10 0x800 +#define I_Q_CAP_DIF 32 +#define CONSTANT_RCIQ 117 +#define SUMNUMBERS 1 +#define MINOFFSET 64//16 + +//#define DPDCALILEN 256 + +#define cpu_delay(val) delay(MAX(1, val/100)) +#define DELAY1US 100 +//#define DELAY05US 1 + +#define cal_delay(val) delay05us(MAX(1, val)) // 8us +//#define CAL_DELAY1US 2 +//#define CAL_DELAY05US 20 //20160804 1:0.5us 2:1us +#define CAL_DELAY05US 2 // 20170503 2:1.5us 2 to 20 for debug 20180227 +#define CAL_TX_NUM 50 +#define CAL_RX_NUM 5 + +#define cal_delay_100us(val) delay100us(MAX(1, val)) // 200us +#define CAL_DELAY100US 1 //20160804 1:100us 2:200us // 20170503 1:150us 2:300us + + +//#define BK7011TRXREG0xD 0xDDFF0339 +//#define BK7011TRXREG0xC 0x01A147EE//0x01A183FD +/* +#define DGAINPA20 3 +#define DGAINBUF20 3 +#define GCTRLPGA40 0xf +#define GCTRLMOD30 0x04 +#define TSSI_DELTA (2) // 10 +#define TSSI_IS_VALID(val) (((val) 0xf0 ) && ((val) > 0x20))?1:0) +#define TSSI_IS_TOO_LOW(val) (((val)<(0x00 * SUMNUMBERS))?1:0) //0x37 +#define TSSI_IS_TOO_HIGH(val) (((val)> (0xff * SUMNUMBERS))?1:0) //0xe0 +*/ +#define st_TRXREG00 (1<<0) +#define st_TRXREG01 (1<<1) +#define st_TRXREG02 (1<<2) +#define st_TRXREG03 (1<<3) +#define st_TRXREG04 (1<<4) +#define st_TRXREG05 (1<<5) +#define st_TRXREG06 (1<<6) +#define st_TRXREG07 (1<<7) +#define st_TRXREG08 (1<<8) +#define st_TRXREG09 (1<<9) +#define st_TRXREG0A (1<<10) +#define st_TRXREG0B (1<<11) +#define st_TRXREG0C (1<<12) +#define st_TRXREG0D (1<<13) +#define st_TRXREG0E (1<<14) +#define st_TRXREG0F (1<<15) +#define st_TRXREG10 (1<<16) +#define st_TRXREG11 (1<<17) +#define st_TRXREG12 (1<<18) +#define st_TRXREG13 (1<<19) +#define st_TRXREG14 (1<<20) +#define st_TRXREG15 (1<<21) +#define st_TRXREG16 (1<<22) +#define st_TRXREG17 (1<<23) +#define st_TRXREG18 (1<<24) +#define st_TRXREG19 (1<<25) +#define st_TRXREG1A (1<<26) +#define st_TRXREG1B (1<<27) + +#define abs(a) ((a) < 0 ?(-1*(a)):(a)) + +#ifndef __BK7011RCBEKEN_H__ +#define __BK7011RCBEKEN_H__ + +#define RC_BEKEN_BASE 0x01050000 + +/// REG0x0 +typedef union +{ + struct + { + volatile unsigned int ch0en : 1; /**< Enable BK7011 (1: Enable) */ + volatile unsigned int Reserved : 2; /**< NC */ + volatile unsigned int rcen : 1; /**< Enable BK7011 (1: Enable) */ + volatile unsigned int Reserved_ : 4; /**< NC */ + volatile unsigned int ch0ld : 1; /**< BK7011 LDֵǷ */ + volatile unsigned int lnarssi : 1; /**< BK7011 LNA RSSI״̬ */ + volatile unsigned int Reserved__ : 2; /**< NC */ + volatile unsigned int ch0shdnstat : 1; /**< BK7011Ƿshutdown״̬ */ + volatile unsigned int Reserved___ : 3; /**< NC */ + volatile unsigned int rcstate : 3; /**< ǰRC״̬;0x00=SPI_RESET ;0x01=SHUTDOWN ;0x02=WAIT_SPI (SPIڲ);0x03=WAIT_LOCKRFPLLLock;0x04=ACTIVE */ + volatile unsigned int Reserved____ : 11; /**< NC */ + volatile unsigned int spireset : 1; /**< Reset BK7011SPIĴ */ + volatile unsigned int forceenable : 1; /**< ǿƿBK7011Ľӿź */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x0_TypeDef; + +/// REG0x1 +typedef union +{ + struct + { + volatile unsigned int trxregstat : 28; /**< TRx Register Stat.;0x0: register is idle;0x1: register is updating. Can not write register again */ + volatile unsigned int prescaler : 4; /**< SPIʱƵʿ=RC_Clock (80 MHz)/2/PRESCALE */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x1_TypeDef; + +/// REG0x5 +typedef union +{ + struct + { + volatile unsigned int ch0outpower : 8; /**< No description */ + volatile unsigned int Reserved : 24; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x5_TypeDef; + +/// REG0x8 +typedef union +{ + struct + { + volatile unsigned int CH0RXONDELAY : 8; /**< No description */ + volatile unsigned int Reserved : 8; /**< NC */ + volatile unsigned int CH0RXOFFDELAY : 8; /**< No description */ + volatile unsigned int Reserved_ : 8; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x8_TypeDef; + +/// REG0xB +typedef union +{ + struct + { + volatile unsigned int CH0TXONDELAY : 8; /**< No description */ + volatile unsigned int Reserved : 8; /**< NC */ + volatile unsigned int CH0TXOFFDELAY : 8; /**< No description */ + volatile unsigned int Reserved_ : 8; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0xB_TypeDef; + +/// REG0xE +typedef union +{ + struct + { + volatile unsigned int CH0PAONDELAY : 8; /**< No description */ + volatile unsigned int Reserved : 8; /**< NC */ + volatile unsigned int CH0PAOFFDELAY : 8; /**< No description */ + volatile unsigned int Reserved_ : 8; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0xE_TypeDef; + +/// REG0x11 +typedef union +{ + struct + { + volatile unsigned int CH0SHDNONDELAY : 8; /**< No description */ + volatile unsigned int Reserved : 8; /**< NC */ + volatile unsigned int CH0SHDNOFFDELAY : 8; /**< No description */ + volatile unsigned int Reserved_ : 8; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x11_TypeDef; + +/// REG0x19 +typedef union +{ + struct + { + volatile unsigned int FCH0SHDN : 1; /**< ǿģʽµSHDN */ + volatile unsigned int FCH0RXEN : 1; /**< ǿģʽµRXEN */ + volatile unsigned int FCH0TXEN : 1; /**< ǿģʽµTXEN */ + volatile unsigned int FCH0RXHP : 1; /**< ǿģʽµRXHP */ + volatile unsigned int Reserved : 4; /**< NC */ + volatile unsigned int FCH0B : 8; /**< ǿģʽ */ + volatile unsigned int FCH0EN : 1; /**< ǿƿRFӿź */ + volatile unsigned int Reserved_ : 15; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x19_TypeDef; + +/// REG0x1A +typedef union +{ + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x1A_TypeDef; + +/// REG0x1C +typedef union +{ + struct + { + volatile unsigned int FRXON : 1; /**< ǿģʽRX ON */ + volatile unsigned int FTXON : 1; /**< ǿģʽTX ON */ + volatile unsigned int Reserved : 30; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x1C_TypeDef; + +/// REG0x1E +typedef union +{ + struct + { + volatile unsigned int FERXONDEL : 12; /**< No description */ + volatile unsigned int Reserved : 20; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x1E_TypeDef; + +/// REG0x3C +typedef union +{ + struct + { + volatile unsigned int RXAVGQRD : 12; /**< Q· */ + volatile unsigned int RXAVGIRD : 12; /**< I· */ + volatile unsigned int Reserved : 3; /**< NC */ + volatile unsigned int RX_ATTEN_SWITCH_COEX : 1; /**< 0x0: RF Attenuation and Rx Switch controlled sperately 0x1: RF Attenuation and Rx Switch controlled at the same time */ + volatile unsigned int RXHPFBYPASS : 1; /**< RX HPF bypass */ + volatile unsigned int RXIQSWAP : 1; /**< RX IQ SWAP */ + volatile unsigned int RXAVGMODE : 1; /**< 0ȡźŵƽֵ;1ȡźžֵƽֵ */ + volatile unsigned int RXDCCALEN : 1; /**< ʹRX DC(1) */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x3C_TypeDef; + +/// REG0x3E +typedef union +{ + struct + { + volatile unsigned int RXDCQRD : 12; /**< Q·DC */ + volatile unsigned int RXDCIRD : 12; /**< I·DC */ + volatile unsigned int Reserved : 6; /**< NC */ + volatile unsigned int RXCOMPEN : 1; /**< ʹMismatch(1) */ + volatile unsigned int RXCALEN : 1; /**< ʹMismatch(1) */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x3E_TypeDef; + +/// REG0x3F +typedef union +{ + struct + { + volatile unsigned int RXPHASEERRRD : 10; /**< Ƴλphase_err_est*2^9з */ + volatile unsigned int Reserved : 6; /**< NC */ + volatile unsigned int RXAMPERRRD : 10; /**< Ƴķamp_err_est*2^9з */ + volatile unsigned int Reserved_ : 6; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x3F_TypeDef; + +/// REG0x40 +typedef union +{ + struct + { + volatile unsigned int RXTY2RD : 10; /**< ƳTY2(ty2-0.5)*2^10з */ + volatile unsigned int Reserved : 22; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x40_TypeDef; + +/// REG0x41 +typedef union +{ + struct + { + volatile unsigned int RXDCQWR : 12; /**< ʱʹõQ·DC */ + volatile unsigned int RXDCIWR : 12; /**< ʱʹõI·DC */ + volatile unsigned int Reserved : 8; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x41_TypeDef; + +/// REG0x42 +typedef union +{ + struct + { + volatile unsigned int RXPHASEERRWR : 10; /**< ʱʹõphase_err*ty2*2^9 */ + volatile unsigned int Reserved : 6; /**< NC */ + volatile unsigned int RXAMPERRWR : 10; /**< ʱʹõty2/(1+amp_err)*2^9 */ + volatile unsigned int Reserved_ : 6; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x42_TypeDef; + +/// REG0x43 +typedef union +{ + struct + { + volatile unsigned int PRE_GAIN_2ND : 10; /**< 2nd stage PreGain */ + volatile unsigned int Reserved : 2; /**< NC */ + volatile unsigned int TRIANGLE_AMP : 1; /**< DzȷΧ0 2048~2560 1 2048~3072 */ + volatile unsigned int DPD_ADDR_SCALE : 1; /**< PD ַţ01/2 1: 1/4 */ + volatile unsigned int Reserved_ : 18; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x43_TypeDef; + +/// REG0x4C +typedef union +{ + struct + { + volatile unsigned int QCONSTANT : 12; /**< 䳣ʱQֵ */ + volatile unsigned int Reserved : 3; /**< NC */ + volatile unsigned int DPD_EN : 1; /**< DPD enable */ + volatile unsigned int ICONSTANT : 12; /**< 䳣ʱIֵ */ + volatile unsigned int TXPOWTBLEN : 1; /**< Tx Power Table Enable; 0x0: Tableд; 0x1: ӲTable */ + volatile unsigned int TXCOMPDIS : 1; /**< Ͳֹܽ;0x0: ʹܷͲ;0x1: ֹͲ */ + volatile unsigned int TESTPATTERN : 2; /**< 0ģʽModem; 1I/Q䳣; 2I/QҲ; 3I/QDz */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x4C_TypeDef; + +/// REG0x4D +typedef union +{ + struct + { + volatile unsigned int Reserved : 12; /**< NC */ + volatile unsigned int TXSINAMP : 4; /**< ҲȵϵСʾx.yyyΧ[0 15/8] */ + volatile unsigned int TXSINMODE : 2; /**< 0I/Q·临Ҳ;1I·䣬Q·0;2Q·䣬I·0;3 */ + volatile unsigned int Reserved_ : 4; /**< NC */ + volatile unsigned int TXSINF : 10; /**< ҲƵ;TX_SIN_F=2*pi*F/80e6*2^8FǷƵ */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x4D_TypeDef; + +/// REG0x4E +typedef union +{ + struct + { + volatile unsigned int hbf40sel : 1; /**< 40Mģʽϲ˲ϵ 1 beken ϵ 0rw ϵ */ + volatile unsigned int hbf40bp : 1; /**< 40Mģʽϲ˲ bypass */ + volatile unsigned int hbf20sel : 1; /**< 20Mģʽϲ˲ϵ 1 beken ϵ 0rw ϵ */ + volatile unsigned int hbf20bp : 1; /**< 20Mģʽϲ˲ bypass */ + volatile unsigned int Reserved_ : 28; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x4E_TypeDef; + +/// REG0x4F +typedef union +{ + struct + { + volatile unsigned int TXQDCCOMP : 12; /**< Q DC offset[-512 511] */ + volatile unsigned int Reserved : 4; /**< NC */ + volatile unsigned int TXIDCCOMP : 12; /**< I DC offset[-512 511] */ + volatile unsigned int Reserved_ : 4; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x4F_TypeDef; + +/// REG0x50 +typedef union +{ + struct + { + volatile unsigned int TXQGAINCOMP : 12; /**< 0 ~ 1023/1024step:1/1024 */ + volatile unsigned int Reserved : 4; /**< NC */ + volatile unsigned int TXIGAINCOMP : 12; /**< 0 ~ 1023/1024step:1/1024 */ + volatile unsigned int Reserved_ : 4; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x50_TypeDef; + +/// REG0x51 +typedef union +{ + struct + { + volatile unsigned int TXTY2 : 12; /**< 512/1024 ~ (512+1023)/1024step:1/1024 */ + volatile unsigned int Reserved : 4; /**< NC */ + volatile unsigned int TXPHASECOMP : 12; /**< -512/1024~ 511/1024step:1/1024 */ + volatile unsigned int Reserved_ : 4; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x51_TypeDef; + +/// REG0x52 +typedef union +{ + struct + { + volatile unsigned int Reserved : 6; /**< NC */ + volatile unsigned int IQCONSTANTIQCALP : 10; /**< IQУ׼IQ CONSTANT ֵֵ */ + volatile unsigned int Reserved_ : 5; /**< IQź;01.75 dB;. 31-6dB;; */ + volatile unsigned int IQCONSTANTPOUT : 10; /**< У׼IQ CONSTANT ֵ */ + volatile unsigned int TXIQSWAP : 1; /**< IQ Swap */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x52_TypeDef; + +/// REG0x54 +typedef union +{ + struct + { + volatile unsigned int STRXADCIQ : 1; /**< RX ADC IQУ׼ Settling time 0:300us;1:600us */ + volatile unsigned int TSSIPOUTTH : 8; /**< У׼ʶӦTSSI */ + volatile unsigned int DSELVA : 1; /**< TSSI or AGC gain setting for versiong A, output 0: TSSI 1:AGC gain setting */ + volatile unsigned int TXDCN : 2; /**< TX DC ַһִв 0:3Σ1:4Σ2:5Σ3:6 */ + volatile unsigned int TSSIRD : 12; /**< TSSI Value. Just valid during tssi_cal_en assert */ + volatile unsigned int AGCPGARD : 4; /**< AGCPGA */ + volatile unsigned int AGCBUFRD : 1; /**< AGCBUF */ + volatile unsigned int AGCLNARD : 2; /**< AGCLNA */ + volatile unsigned int AGCMAPMODE : 1; /**< 0ӳ䷽ʽһ;1ӳ䷽ʽ */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x54_TypeDef; + +/// REG0x55 +typedef union +{ + struct + { + volatile unsigned int RXSNRNOISE : 9; /**< rx noise for sinar test */ + volatile unsigned int Reserved : 7; /**< NC */ + volatile unsigned int RXSNRSIG : 9; /**< rx signal for sinar test */ + volatile unsigned int Reserved_ : 7; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x55_TypeDef; + +/// REG0x56 +typedef union +{ + struct + { + volatile unsigned int rf_bias_cout : 5; /**< rf bias calib result */ + volatile unsigned int Reserved : 27; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x56_TypeDef; + +/// REG0x57 +typedef union +{ + struct + { + volatile unsigned int adc_rssi : 12; /**< rf lna sat for record */ + volatile unsigned int adc_rssi_rec_max : 12; /**< rf gain is according to maxium rssi */ + volatile unsigned int rf_gain_rec_max : 7; /**< maxium adc rssi be recorded */ + volatile unsigned int rf_lna_sat_rec : 1; /**< rx adc rssi */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x57_TypeDef; + +/// REG0x5A +typedef union +{ + struct + { + volatile unsigned int TXCALCAPI : 8; /**< I path calib capacity for transmit mode */ + volatile unsigned int RXCALCAPI : 8; /**< I path calib capacity for receive mode */ + volatile unsigned int STANDBYCALCAPI : 8; /**< I path calib capacity for standby mode */ + volatile unsigned int Reserved_ : 8; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x5A_TypeDef; + +/// REG0x5B +typedef union +{ + struct + { + volatile unsigned int TXCALCAPQ : 8; /**< Q path calib capacity for transmit mode */ + volatile unsigned int RXCALCAPQ : 8; /**< Q path calib capacity for receive mode */ + volatile unsigned int STANDBYCALCAPQ : 8; /**< Q path calib capacity for standby mode */ + volatile unsigned int Reserved_ : 8; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x5B_TypeDef; + +/// REG0x5C +typedef union +{ + struct + { + volatile unsigned int trxspiintval : 10; /**< TRX SPI Transfer Interval. Unit is 12.5ns */ + volatile unsigned int Reserved : 14; /**< NC */ + volatile unsigned int Reserved_ : 7; /**< Reserved */ + volatile unsigned int trxbankrpt : 1; /**< TRX Bank Report. 0x0:bank0; 0x1:bank1 */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x5C_TypeDef; + +/// REG0x6A +typedef union +{ + struct + { + volatile unsigned int trxaddaregstat : 6; /**< ADC&DAC Register Status.;0x0: register is idle;0x1: register is updating. Can not write register again */ + volatile unsigned int Reserved : 26; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x6A_TypeDef; + +#if 0 +/// REG0x70 +typedef union +{ + struct + { + volatile unsigned int palevel0map : 16; /**< PA Level0 Mapping Value */ + volatile unsigned int palevel1map : 16; /**< PA Level1 Mapping Value */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x70_TypeDef; + +/// REG0x71 +typedef union +{ + struct + { + volatile unsigned int palevel2map : 16; /**< PA Level2 Mapping Value */ + volatile unsigned int palevel3map : 16; /**< PA Level3 Mapping Value */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x71_TypeDef; + +/// REG0x72 +typedef union +{ + struct + { + volatile unsigned int palevel4map : 16; /**< PA Level4 Mapping Value */ + volatile unsigned int palevel5map : 16; /**< PA Level5 Mapping Value */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x72_TypeDef; + +/// REG0x73 +typedef union +{ + struct + { + volatile unsigned int palevel6map : 16; /**< PA Level6 Mapping Value */ + volatile unsigned int palevel7map : 16; /**< PA Level7 Mapping Value */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x73_TypeDef; + +/// REG0x74 +typedef union +{ + struct + { + volatile unsigned int palevel8map : 16; /**< PA Level8 Mapping Value */ + volatile unsigned int palevel9map : 16; /**< PA Level9 Mapping Value */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x74_TypeDef; + +/// REG0x75 +typedef union +{ + struct + { + volatile unsigned int palevel10map : 16; /**< PA Level10 Mapping Value */ + volatile unsigned int palevel11map : 16; /**< PA Level11 Mapping Value */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x75_TypeDef; + +/// REG0x76 +typedef union +{ + struct + { + volatile unsigned int palevel12map : 16; /**< PA Level12 Mapping Value */ + volatile unsigned int palevel13map : 16; /**< PA Level13 Mapping Value */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x76_TypeDef; + +/// REG0x77 +typedef union +{ + struct + { + volatile unsigned int palevel4map : 16; /**< PA Level4 Mapping Value */ + volatile unsigned int palevel5map : 16; /**< PA Level5 Mapping Value */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x77_TypeDef; +#endif + +/// BK7231N_RC_REG +struct BK7011RCBEKEN_TypeDef +{ + volatile BK7011_RC_BEKEN_REG0x0_TypeDef *REG0x0; + volatile BK7011_RC_BEKEN_REG0x1_TypeDef *REG0x1; + volatile BK7011_RC_BEKEN_REG0x5_TypeDef *REG0x5; + volatile BK7011_RC_BEKEN_REG0x8_TypeDef *REG0x8; + volatile BK7011_RC_BEKEN_REG0xB_TypeDef *REG0xB; + volatile BK7011_RC_BEKEN_REG0xE_TypeDef *REG0xE; + volatile BK7011_RC_BEKEN_REG0x11_TypeDef *REG0x11; + volatile BK7011_RC_BEKEN_REG0x19_TypeDef *REG0x19; + volatile BK7011_RC_BEKEN_REG0x1A_TypeDef *REG0x1A; + volatile BK7011_RC_BEKEN_REG0x1C_TypeDef *REG0x1C; + volatile BK7011_RC_BEKEN_REG0x1E_TypeDef *REG0x1E; + volatile BK7011_RC_BEKEN_REG0x3C_TypeDef *REG0x3C; + volatile BK7011_RC_BEKEN_REG0x3E_TypeDef *REG0x3E; + volatile BK7011_RC_BEKEN_REG0x3F_TypeDef *REG0x3F; + volatile BK7011_RC_BEKEN_REG0x40_TypeDef *REG0x40; + volatile BK7011_RC_BEKEN_REG0x41_TypeDef *REG0x41; + volatile BK7011_RC_BEKEN_REG0x42_TypeDef *REG0x42; + volatile BK7011_RC_BEKEN_REG0x43_TypeDef *REG0x43; + volatile BK7011_RC_BEKEN_REG0x4C_TypeDef *REG0x4C; + volatile BK7011_RC_BEKEN_REG0x4D_TypeDef *REG0x4D; + volatile BK7011_RC_BEKEN_REG0x4E_TypeDef *REG0x4E; + volatile BK7011_RC_BEKEN_REG0x4F_TypeDef *REG0x4F; + volatile BK7011_RC_BEKEN_REG0x50_TypeDef *REG0x50; + volatile BK7011_RC_BEKEN_REG0x51_TypeDef *REG0x51; + volatile BK7011_RC_BEKEN_REG0x52_TypeDef *REG0x52; + volatile BK7011_RC_BEKEN_REG0x54_TypeDef *REG0x54; + volatile BK7011_RC_BEKEN_REG0x55_TypeDef *REG0x55; + volatile BK7011_RC_BEKEN_REG0x56_TypeDef *REG0x56; + volatile BK7011_RC_BEKEN_REG0x57_TypeDef *REG0x57; + volatile BK7011_RC_BEKEN_REG0x5A_TypeDef *REG0x5A; + volatile BK7011_RC_BEKEN_REG0x5B_TypeDef *REG0x5B; + volatile BK7011_RC_BEKEN_REG0x5C_TypeDef *REG0x5C; + volatile BK7011_RC_BEKEN_REG0x6A_TypeDef *REG0x6A; + #if 0 + volatile BK7011_RC_BEKEN_REG0x70_TypeDef *REG0x70; + volatile BK7011_RC_BEKEN_REG0x71_TypeDef *REG0x71; + volatile BK7011_RC_BEKEN_REG0x72_TypeDef *REG0x72; + volatile BK7011_RC_BEKEN_REG0x73_TypeDef *REG0x73; + volatile BK7011_RC_BEKEN_REG0x74_TypeDef *REG0x74; + volatile BK7011_RC_BEKEN_REG0x75_TypeDef *REG0x75; + volatile BK7011_RC_BEKEN_REG0x76_TypeDef *REG0x76; + volatile BK7011_RC_BEKEN_REG0x77_TypeDef *REG0x77; + #endif +}; + +typedef struct +{ + BK7011_RC_BEKEN_REG0x0_TypeDef REG0x0; + BK7011_RC_BEKEN_REG0x1_TypeDef REG0x1; + BK7011_RC_BEKEN_REG0x5_TypeDef REG0x5; + BK7011_RC_BEKEN_REG0x8_TypeDef REG0x8; + BK7011_RC_BEKEN_REG0xB_TypeDef REG0xB; + BK7011_RC_BEKEN_REG0xE_TypeDef REG0xE; + BK7011_RC_BEKEN_REG0x11_TypeDef REG0x11; + BK7011_RC_BEKEN_REG0x19_TypeDef REG0x19; + BK7011_RC_BEKEN_REG0x1A_TypeDef REG0x1A; + BK7011_RC_BEKEN_REG0x1C_TypeDef REG0x1C; + BK7011_RC_BEKEN_REG0x1E_TypeDef REG0x1E; + BK7011_RC_BEKEN_REG0x3C_TypeDef REG0x3C; + BK7011_RC_BEKEN_REG0x3E_TypeDef REG0x3E; + BK7011_RC_BEKEN_REG0x3F_TypeDef REG0x3F; + BK7011_RC_BEKEN_REG0x40_TypeDef REG0x40; + BK7011_RC_BEKEN_REG0x41_TypeDef REG0x41; + BK7011_RC_BEKEN_REG0x42_TypeDef REG0x42; + BK7011_RC_BEKEN_REG0x43_TypeDef REG0x43; + BK7011_RC_BEKEN_REG0x4C_TypeDef REG0x4C; + BK7011_RC_BEKEN_REG0x4D_TypeDef REG0x4D; + BK7011_RC_BEKEN_REG0x4E_TypeDef REG0x4E; + BK7011_RC_BEKEN_REG0x4F_TypeDef REG0x4F; + BK7011_RC_BEKEN_REG0x50_TypeDef REG0x50; + BK7011_RC_BEKEN_REG0x51_TypeDef REG0x51; + BK7011_RC_BEKEN_REG0x52_TypeDef REG0x52; + BK7011_RC_BEKEN_REG0x54_TypeDef REG0x54; + BK7011_RC_BEKEN_REG0x55_TypeDef REG0x55; + BK7011_RC_BEKEN_REG0x56_TypeDef REG0x56; + BK7011_RC_BEKEN_REG0x57_TypeDef REG0x57; + BK7011_RC_BEKEN_REG0x5A_TypeDef REG0x5A; + BK7011_RC_BEKEN_REG0x5B_TypeDef REG0x5B; + BK7011_RC_BEKEN_REG0x5C_TypeDef REG0x5C; + BK7011_RC_BEKEN_REG0x6A_TypeDef REG0x6A; +} BK7231N_RC_TypeDef; +#endif + +#ifndef __BK7011TRxV2A_H__ +#define __BK7011TRxV2A_H__ + +#define TRX_BEKEN_BASE 0x01050080 + +/// REG0x0 +typedef union +{ + struct + { + volatile unsigned long tssi_atten : 3; //Signal attenuation programming in power calibration: 000:6dB; 111:12dB; ~1dB/LSB; + volatile unsigned long tssiIQ_gc : 2; //Gain selection in IQcal when gctune_en=0; + volatile unsigned long tssiDC_gc : 2; //Gain selection in Dccal when gctune_en=0; + volatile unsigned long tssi_gc : 2; //Fixed gain in Dccal and Iqcal; <1>: stage 1, <0>: stage 2; 1:-3dB; 0: 0dB; + volatile unsigned long enPcal : 1; //1: Enable output power calibration; 0 : otherwise; + volatile unsigned long enIQcal : 1; //1: Enable IQ mismatch calibration; 0 : otherwise; + volatile unsigned long gctune_en : 1; //0: Separate Dccal and Iqcal gain settling; 0 : fixed gain for both; + volatile unsigned long enDCcal : 1; //1: Enable LO leakage calibration; 0 : otherwise; + volatile unsigned long TSSIsel : 1; //No internal connection + volatile unsigned long NC : 2; + volatile unsigned long Dtau : 4; //PA bias settling time programming; 1000:400ns; ~50n/LSB + volatile unsigned long Dvldo : 2; //Gm LDO output programming: (00,01,10) => [1.2, 1.3, 1.4] + volatile unsigned long Dvnlo : 2; //Mixer LO dc bias programming: 0.8*Vrefm + Vrefm*Dvnlo/16; + volatile unsigned long tspi : 8; //Reserved control bits; + } bits; + volatile unsigned int value; +}BK7011_TRxV2A_REG0x0_TypeDef; + +/// REG0x1 +typedef union +{ + struct + { + volatile unsigned long Icpmis_en : 1; //enable the Icp mismatch function + volatile unsigned long cp_ictrl_mode : 1; //controlling the current bias mode in the CP + volatile unsigned long cphalf_spi : 1; //set the cp out to vdd/2 + volatile unsigned long Icp_offset : 4; //controlling the offset current in the CP + volatile unsigned long Icp_core : 5; //controlling the CP current in the high power mode + volatile unsigned long Cp2 : 2; //controlling the loop of filter of PLL + volatile unsigned long Rp2 : 3; //controlling the loop of filter of PLL + volatile unsigned long loopRz_lp : 4; //controlling resistor of zero point in the loop filter in the high power mode + volatile unsigned long Cp1 : 2; //controlling the loop of filter of PLL + volatile unsigned long Rp3 : 3; //controlling the loop of filter of PLL + volatile unsigned long Cp3 : 1; //controlling the loop of filter of PLL + volatile unsigned long open : 1; //enable the OP in the CP,help to improve the mismatch between UP and DOWN + volatile unsigned long Icp_bias : 4; //tunning the bias current in the CP of RFPLL + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x1_TypeDef; + +/// REG0x2 +typedef union +{ + struct + { + volatile unsigned long NA1 : 1; + volatile unsigned long clksel_cal : 1; //choosing the clock of calibration + volatile unsigned long bypass_opt : 1; //by pass the option in the frequency calibration block + volatile unsigned long manual_band : 1; //enable the band controlling mannualy + volatile unsigned long bandcal_spi : 8; //bandcal controlling by spi + volatile unsigned long band_spi_trgger : 1; //trigger the band calibration + volatile unsigned long bandcal_force : 1; //force the bandcal_en signal to '1' or '0' by spi + volatile unsigned long NA2 : 1; + volatile unsigned long hvref : 2; //set the detected votage in the locked detector + volatile unsigned long lvref : 2; //set the detected votage in the locked detector + volatile unsigned long done_delay : 4; //delay time of band callibration + volatile unsigned long ampautocal : 1; //enable the amplitude calibration of VCO + volatile unsigned long ampcal_en : 1; //enable the calibration function of amplitude + volatile unsigned long ampctrl_m : 1; //controlling the amplitude of VCO mannualy + volatile unsigned long errdet_en : 1; //enable the lock detector block + volatile unsigned long errdet_spien : 1; //enable output the lock detector function + volatile unsigned long NA3 : 2; + volatile unsigned long pllen : 1; //enable PLL loop in the top by spi + volatile unsigned long vcoen : 1; //enable VCO in the top by spi + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x2_TypeDef; + +/// REG0x3 +typedef union +{ + struct + { + volatile unsigned long amp_txbuf : 3; // + volatile unsigned long lobuf_ampctrl : 3; //controlling the amplitude of LO buffer + volatile unsigned long itune_LODIV : 2; //controlling the bias current in the divier-by-2 of LO chain + volatile unsigned long vbn_LODIV : 2; //controlling the bias voltage in the divier-by-2 of LO chain + volatile unsigned long NA1 : 1; + volatile unsigned long ictrl_mode : 1; //change the working mode of bias current in the VCO + volatile unsigned long ampsel : 3; //controlling the amplitude value of amplitude calibration in the normal working + volatile unsigned long NA2 : 17; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x3_TypeDef; + +/// REG0x4 +typedef union +{ + struct + { + volatile unsigned long Itune_vco_spi : 6; //controlling the bias current of VCO + volatile unsigned long Rvco : 4; //controlling the bias current of VCO + volatile unsigned long vnw : 4; //controlling the bias voltage of Kmod varactor array + volatile unsigned long reset_spi : 1; //Reset spi of SDM in PLL + volatile unsigned long Nrsten : 1; //enable the reset function both PFD and Ncounter + volatile unsigned long tristate_spi : 1; //enable the tristate in the PFD + volatile unsigned long selvcopol : 1; //change the direction of PFD between positive and negative + volatile unsigned long Nclken_spi : 1; //enable the Nclk output + volatile unsigned long Nint : 10; //The feedback N value in manual control mode + volatile unsigned long pfddly : 2; //pfd delay time controlling + volatile unsigned long int_mode : 1; //loop int mode enable + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x4_TypeDef; + +/// REG0x5 +typedef union +{ + struct + { + volatile unsigned long nsdmlsb : 8; //amplitude of noise input of SDM + volatile unsigned long cksel_sdm : 3; //set the clock frequency of SDM,0:26M;1:40M, + volatile unsigned long NA1 : 1; + volatile unsigned long pnen : 1; //enable the phase noise improvement in the SDM + volatile unsigned long sdm_rstn : 1; //reset the SDM in the RFPLL + volatile unsigned long NA2 : 5; + volatile unsigned long podge_sel : 1; //choosing the clock edge of SDM + volatile unsigned long vcoldo_sel : 3; //set the output voltage of vco ldo + volatile unsigned long NA3 : 2; + volatile unsigned long chspi : 7; //set the frequency channel by spi: (2400+chspi)MHZ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x5_TypeDef; + +/// REG0x6 +typedef union +{ + struct + { + volatile unsigned long vtsel : 1; //temp_det output voltage slelction 0:high resolution/1:low resolution + volatile unsigned long md_ten : 1; //adc internal signal test enable + volatile unsigned long capcal_sel : 1; //filter cap control selection, 1:from dig; 0 :from spi + volatile unsigned long dpd_en : 1; //dpd cal path enable + volatile unsigned long lpfcapcalq50 : 6; //lpf Q path calibiration input (low 6bits) + volatile unsigned long lpfcapcali50 : 6; //lpf I path calibiration input (low 6bits) + volatile unsigned long dcocq : 8; //dcoc Q path input + volatile unsigned long dcoci : 8; //dcoc I path input + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x6_TypeDef; + +/// REG0x7 +typedef union +{ + struct + { + volatile unsigned long dig_dcoen : 1; //dcoc input selection,1: digital 0: spi + volatile unsigned long spilpfrxg30 : 4; //rxif gain, 0000-1111 0dB - 45dB step:3dB + volatile unsigned long autorxifgen : 1; //rxif gain control selection, 1: auto control 0: spi + volatile unsigned long dcoc_ctl : 2; //dcoc gain contrl + volatile unsigned long txgs : 1; //txif gain option + volatile unsigned long NC1 : 1; + volatile unsigned long lpftxTest : 1; //lpf tx test control bit,1 : tx test mode 0: default + volatile unsigned long lpen : 1; //IF filter low power mode enable + volatile unsigned long iqsw : 1; //IF filter output iq swap + volatile unsigned long txif_2rd : 1; //Tx filter 2nd mode enable + volatile unsigned long abws_en : 1; //Tx filter control mode selection 0: from dig/1:from spi + volatile unsigned long adc_dly_men : 1; //adc delay manual selection enable + volatile unsigned long dac_isel_buf : 3; //dac buffer bias current selection + volatile unsigned long dac_isel_opa : 3; //dac opamp bias current selection + volatile unsigned long dac_delay : 5; //dac delay selection + volatile unsigned long dac_ck_edge : 1; //dac clock edge selection + volatile unsigned long lpfcapcalq : 2; //lpf q path calibiration input (high 2bits) + volatile unsigned long lpfcapcali : 2; //lpf I path calibiration input (high 2bits) + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x7_TypeDef; + +/// REG0x8 +typedef union +{ + struct + { + volatile unsigned long isrxref10 : 2; //rx ref ib selection 00-11 10-15uA + volatile unsigned long isrxlna30 : 4; //rx lna ib selection 000-111 50-110uA + volatile unsigned long NC1 : 1; + volatile unsigned long isv2i : 2; //v2i bias current selection + volatile unsigned long isrxlnac10 : 2; //rx lnacali ib selection 00-11 40-70uA + volatile unsigned long isrxdiv10 : 2; //rx div ib selection 00-11 10-25uA + volatile unsigned long NC2 : 1; + volatile unsigned long rssith50 : 6; //rx rssi threshhold Pant=-29dBm(th=000111) 0:-37dBm step:1dB + volatile unsigned long isrssigm10 : 2; //rx rssi gm ib selection 00-11 40-55uA + volatile unsigned long rssiten : 1; //rssi analog v output test enable + volatile unsigned long cloadlna : 2; //LNA load capacitor tunning + volatile unsigned long lnacali_tune : 1; //lna_cali phase tune + volatile unsigned long NC3 : 3; + volatile unsigned long att_g : 1; //lna att level selection 0:-12dB/1:-15dB + volatile unsigned long auto_att_en : 1; //lna input attenuation mode 0:from spi/1:from dig + volatile unsigned long atten_spi : 1; //lna input attenuation by spi 0:0dB/1:-12dB + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x8_TypeDef; + +/// REG0x9 +typedef union +{ + struct + { + volatile unsigned long agcrxfeEn : 1; //enble rxfe agc by mcu, 0/1 gctr by spi/mcu + volatile unsigned long grxlnaspi10 : 2; //rx lna gain 00-11 0/+6/+12/+18dBr + volatile unsigned long grxi2vspi10 : 2; //rx i2v gain 00-11 0/+6/+6/+12dBr + volatile unsigned long vsrxlnaldo10 : 3; //rx lna LDO vout 1~5 /1.0V~1.2V + volatile unsigned long NC1 : 1; + volatile unsigned long vsrxmixldo10 : 3; //rx mixer LDO vout 1~5 /1.0V~1.2V + volatile unsigned long vbsrxlo20 : 3; //rx lo biasing voltage: 000-111 0.4-0.75V + volatile unsigned long NC2 : 1; + volatile unsigned long ibsrxi2v10 : 2; //rx i2v ib selection 00-11 5-15uA + volatile unsigned long vcmsrxi2v : 1; //rx i2v vcm selction 0-1 0.6-0.5V + volatile unsigned long NC3 : 1; + volatile unsigned long grxi2v_opt : 1; //i2v optional gain control (4dB) + volatile unsigned long abws_en_i2v : 1; //i2v bandwith auto selection enable + volatile unsigned long bw_i2v : 1; + volatile unsigned long NC4 : 9; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x9_TypeDef; + +/// REG0xA +typedef union +{ + struct + { + volatile unsigned long Dvncmix : 4; //Mixer cascode device gate bias voltage programming: Vnc=Vrefm+|Vthp|+30mV*Dvncmix + volatile unsigned long Dvncpad : 4; //PA driver cascode device bias voltage programming: Vnc = Vncref+33mV*Dncpad + volatile unsigned long Drefmixlo : 3; //Mixer switching quad gate bias reference voltage programming: Vref=1.1V+120mV*(1+Drefmixlo) + volatile unsigned long Drefmix : 3; //Mixer cascode device gate bias reference voltage programming: Vrefm=1.1V+120mV*(1+Drefmix) + volatile unsigned long Dvncref : 2; //PA and PAD Vncref programming; Vncref=V(50uA->ndiode)+500mV+60mV*Dvncref + volatile unsigned long Dvnc : 4; //PA and PAD cascode device gate bias voltage programming: Vnc_mV=Vncref+33*Dvnc + volatile unsigned long Dvb : 4; //PA Class-B path bias voltage programming, Vnb_mV=25*(1+Dvb) + volatile unsigned long Dib : 4; //No internal connection + volatile unsigned long Dia : 4; //PA Class-A path bias current programming, Ibias_uA=200 + 50 * Dia + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0xA_TypeDef; + +/// REG0xB +typedef union +{ + struct + { + volatile unsigned long padCd : 4; //PAD output capacitor tunning; Group-D; For channels (100:101)_####; + volatile unsigned long padCc : 4; //PAD output capacitor tunning; Group-C; For channels 100_####; + volatile unsigned long padCb : 4; //PAD output capacitor tunning; Group-B; For channels 010_####; + volatile unsigned long padCa : 4; //PAD output capacitor tunning; Group-A; For channels (000:001)_####; + volatile unsigned long modCd : 4; //Modulator output capacitor tunning; Group-D; For channels (100:101)_####; + volatile unsigned long modCc : 4; //Modulator output capacitor tunning; Group-C; For channels 100_####; + volatile unsigned long modCb : 4; //Modulator output capacitor tunning; Group-B; For channels 010_####; + volatile unsigned long modCa : 4; //Modulator output capacitor tunning; Group-A; For channels (000:001)_####; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0xB_TypeDef; + +/// REG0xC +typedef union +{ + struct + { + volatile unsigned long Gmgain : 4; //V2I Gm gain programming: Active units = 1 + Dgmgain + volatile unsigned long padctrl : 4; //PAD gain control by units: <3>=16; <2>=8; <1>= 4; <0>=4; + volatile unsigned long pactrl : 4; //PA output power control; (one PA slice)/(one bit) + volatile unsigned long Rgm : 4; //V2I input resistor programming: 0000: by-pass; 0001:max_gain; 1111:min_gain; gain step: -0.5dB/LSB; + volatile unsigned long Dgmdc : 4; //Baseband output (V2I) DC current programming: 20uA*Dgmdc + volatile unsigned long Dipad : 4; //PAD bias current programming, Ibias_uA=50 + 50*Dipad; + volatile unsigned long Dibias : 4; //TXFE signal path unit current programming (to compensate corner variation) + volatile unsigned long NC : 3; + volatile unsigned long pamapen : 1; //0: spi power control option; 1: direct digital power control (per packet); + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0xC_TypeDef; + +/// REG0xD +typedef union +{ + struct + { + volatile unsigned long dacselection : 1; //0: external dac, 1: internal dac + volatile unsigned long lpfrxbw : 1; //lpf rx bandwidth selection 1: high bandwidth(19MHz) 0: low bandwidth(9MHz); + volatile unsigned long lpftxbw : 1; //lpf tx bandwidth selection 1: high bandwidth(29MHz) 0: low bandwidth(14MHz); + volatile unsigned long lpftrxsw : 1; //LPF tx rx switch(1:tx,0:rx) + volatile unsigned long enlpf : 1; //LPF enable + volatile unsigned long enif : 1; //ADC, DAC Ldo enable + volatile unsigned long endcoc : 1; //DCOC DAC enable + volatile unsigned long enrxadc : 1; //RX ADC enable + volatile unsigned long entxdac : 1; //TX dac enable + volatile unsigned long entxdacbias : 1; //TX dac bias enable + volatile unsigned long enrxrssi : 1; //RX RF Rssi enable + volatile unsigned long enrxref : 1; //RX RF Vref enable + volatile unsigned long enrxi2v : 1; //RX I2V enable + volatile unsigned long enrxmix : 1; //RX mixer enable + volatile unsigned long enlnacal : 1; //RX look back lna input enable + volatile unsigned long enlna : 1; //Rxfe lna enable + volatile unsigned long txvinsel : 1; //Txfe input selection(0,cal when need bypass TX filter,1:normal) + volatile unsigned long entssi : 1; //Txfe tssi enable + volatile unsigned long entssiadc : 1; //Txfe tssi adc enable + volatile unsigned long entxferef : 1; //Txfe reference enable + volatile unsigned long entxfebias : 1; //Txfe bias enable + volatile unsigned long entxv2i : 1; //Tx v2i enable + volatile unsigned long entxlo : 1; //Tx LO enable + volatile unsigned long entxpga : 1; //TX PGA enable + volatile unsigned long enpa : 1; //Tx PA enable + volatile unsigned long enrxsw : 1; //RX switch enable + volatile unsigned long entxsw : 1; //TX switch enable + volatile unsigned long trswpll : 1; //rf pll tx rx switch + volatile unsigned long enrfpll : 1; //rf pll enable + volatile unsigned long endobuler : 1; //dobuler enable + volatile unsigned long endpll : 1; //digital pll enable + volatile unsigned long enxtal : 1; //xtal enable signal + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0xD_TypeDef; + +/// REG0xE +typedef union +{ + struct + { + volatile unsigned long dacselection : 1; //0: external dac, 1: internal dac + volatile unsigned long lpfrxbw : 1; //lpf rx bandwidth selection 1: high bandwidth(19MHz) 0: low bandwidth(9MHz); + volatile unsigned long lpftxbw : 1; //lpf tx bandwidth selection 1: high bandwidth(29MHz) 0: low bandwidth(14MHz); + volatile unsigned long lpftrxsw : 1; //LPF tx rx switch(1:tx,0:rx) + volatile unsigned long enlpf : 1; //LPF enable + volatile unsigned long enif : 1; //ADC, DAC Ldo enable + volatile unsigned long endcoc : 1; //DCOC DAC enable + volatile unsigned long enrxadc : 1; //RX ADC enable + volatile unsigned long entxdac : 1; //TX dac enable + volatile unsigned long entxdacbias : 1; //TX dac bias enable + volatile unsigned long enrxrssi : 1; //RX RF Rssi enable + volatile unsigned long enrxref : 1; //RX RF Vref enable + volatile unsigned long enrxi2v : 1; //RX I2V enable + volatile unsigned long enrxmix : 1; //RX mixer enable + volatile unsigned long enlnacal : 1; //RX look back lna input enable + volatile unsigned long enlna : 1; //Rxfe lna enable + volatile unsigned long txvinsel : 1; //Txfe input selection(0,cal when need bypass TX filter,1:normal) + volatile unsigned long entssi : 1; //Txfe tssi enable + volatile unsigned long entssiadc : 1; //Txfe tssi adc enable + volatile unsigned long entxferef : 1; //Txfe reference enable + volatile unsigned long entxfebias : 1; //Txfe bias enable + volatile unsigned long entxv2i : 1; //Tx v2i enable + volatile unsigned long entxlo : 1; //Tx LO enable + volatile unsigned long entxpga : 1; //TX PGA enable + volatile unsigned long enpa : 1; //Tx PA enable + volatile unsigned long enrxsw : 1; //RX switch enable + volatile unsigned long entxsw : 1; //TX switch enable + volatile unsigned long trswpll : 1; //rf pll tx rx switch + volatile unsigned long enrfpll : 1; //rf pll enable + volatile unsigned long endobuler : 1; //dobuler enable + volatile unsigned long endpll : 1; //digital pll enable + volatile unsigned long enxtal : 1; //xtal enable signal + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0xE_TypeDef; + +/// REG0xF +typedef union +{ + struct + { + volatile unsigned long NC : 1; // + volatile unsigned long clkdac_sel : 1; //DAC Clock Select. 0x0: 80MHz; 0x1: 160MHz + volatile unsigned long clkadc_sel : 1; //ADCClock Select. 0x0: 40MHz; 0x1: 80MHz + volatile unsigned long NC1 : 2; // + volatile unsigned long sinad_tx_en : 1; //TX Sinad Enable + volatile unsigned long sinad_rx_en : 1; //RX Sinad Detect Enable + volatile unsigned long tssi_cal_en : 1; //TSSI Calibration Enable, enable 40M clock + volatile unsigned long NC2 : 5; // + volatile unsigned long sinad_hpf_coef : 2; //HPF Coefficence for RX Siand Detect. 0x0: 1/8 0x1: 1/32; 0x2: 1/128; 0x3: 1/1024 + volatile unsigned long clkdac_inv : 1; //DAC Clock Invert + volatile unsigned long clkadc_inv : 1; //ADC Clock Invert +#if 0 + volatile unsigned long NC3 : 11; + volatile unsigned long sysldoen : 1; + volatile unsigned long sysldolp : 1; + volatile unsigned long endspvdd : 1; + volatile unsigned long digldolp : 1; + #endif + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0xF_TypeDef; + +/// REG0x10 +typedef union +{ + struct + { + volatile unsigned long dacselection : 1; //0: external dac, 1: internal dac + volatile unsigned long lpfrxbw : 1; //lpf rx bandwidth selection 1: high bandwidth(19MHz) 0: low bandwidth(9MHz); + volatile unsigned long lpftxbw : 1; //lpf tx bandwidth selection 1: high bandwidth(29MHz) 0: low bandwidth(14MHz); + volatile unsigned long lpftrxsw : 1; //LPF tx rx switch(1:tx,0:rx) + volatile unsigned long enlpf : 1; //LPF enable + volatile unsigned long enif : 1; //ADC, DAC Ldo enable + volatile unsigned long endcoc : 1; //DCOC DAC enable + volatile unsigned long enrxadc : 1; //RX ADC enable + volatile unsigned long entxdac : 1; //TX dac enable + volatile unsigned long entxdacbias : 1; //TX dac bias enable + volatile unsigned long enrxrssi : 1; //RX RF Rssi enable + volatile unsigned long enrxref : 1; //RX RF Vref enable + volatile unsigned long enrxi2v : 1; //RX I2V enable + volatile unsigned long enrxmix : 1; //RX mixer enable + volatile unsigned long enlnacal : 1; //RX look back lna input enable + volatile unsigned long enlna : 1; //Rxfe lna enable + volatile unsigned long txvinsel : 1; //Txfe input selection(0,cal when need bypass TX filter,1:normal) + volatile unsigned long entssi : 1; //Txfe tssi enable + volatile unsigned long entssiadc : 1; //Txfe tssi adc enable + volatile unsigned long entxferef : 1; //Txfe reference enable + volatile unsigned long entxfebias : 1; //Txfe bias enable + volatile unsigned long entxv2i : 1; //Tx v2i enable + volatile unsigned long entxlo : 1; //Tx LO enable + volatile unsigned long entxpga : 1; //TX PGA enable + volatile unsigned long enpa : 1; //Tx PA enable + volatile unsigned long enrxsw : 1; //RX switch enable + volatile unsigned long entxsw : 1; //TX switch enable + volatile unsigned long trswpll : 1; //rf pll tx rx switch + volatile unsigned long enrfpll : 1; //rf pll enable + volatile unsigned long endobuler : 1; //dobuler enable + volatile unsigned long endpll : 1; //digital pll enable + volatile unsigned long enxtal : 1; //xtal enable signal + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x10_TypeDef; + +/// REG0x11 +typedef union +{ + struct + { + volatile unsigned long tx_sinad_table : 11; //TX Sinad Table; D[0] = 0: Write I Path Table Data; D[0] = 1: Write Q Path Table Data; LSBoD[1] ; Both I and Q need 16 number data + volatile unsigned long NC : 21; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x11_TypeDef; + +/// REG0x12 +typedef union +{ + struct + { + volatile unsigned long lpfouttsten : 1; //lpf output test enable,0:disenable,1:enable + volatile unsigned long lpfintsten : 1; //lpf input test enable,0:disenable,1:enable + volatile unsigned long ifbufic20 : 3; //test buffer bias current control,0:low, 1:high + volatile unsigned long entstbufldo : 1; //enable test buffer :disenable,1:enable + volatile unsigned long adc_vref_sel : 1; //adc refere voltage selection 0:vref/1:avdd + volatile unsigned long ldoadda : 2; //adc ldo voltage selection,1.0~1.2 + volatile unsigned long buftstselection : 2; //buffer input selection:1:lpf, 0:rssidactst,rssitst,tssitst,adcstst1 + volatile unsigned long pwd_adccal : 1; //power down adc calibration + volatile unsigned long adc_dlym : 7; //adc delay time selection + volatile unsigned long adc_cksel : 2; //adc clock pulse width selection + volatile unsigned long adciselc : 3; //adc core bias current selection,0:5x,1:0.6x,2:0.7X,3:0.8x,4:1.0x,5:1.2X,6:1.4X,7:1.7X + volatile unsigned long fictrl30 : 4; //lpf bias current selection, 0:low, 15:high + volatile unsigned long flvcm10 : 2; //lpf common mode voltage selection,00:low , 11: high + volatile unsigned long ldoifsel3v10 : 2; //If ldo vout selection:00:low, 11: high + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x12_TypeDef; + +/// REG0x13 +typedef union +{ + struct + { + volatile unsigned long r2_rx : 2; //rx mode loopfilter R2 control + volatile unsigned long c1_rx : 2; //rx mode loopfilter C1 control + volatile unsigned long rz_rx : 5; //rx mode loopfilter Rz control + volatile unsigned long icp_rx : 5; //rx mode cp current control + volatile unsigned long icpoff20 : 3; //cp offset current control + volatile unsigned long icpsel : 1; //icp bias select: 0, internal; 1, external + volatile unsigned long r2_tx : 2; //tx mode loopfilter R2 control + volatile unsigned long c1_tx : 2; //tx mode loopfilter C1 control + volatile unsigned long rz_tx : 5; //tx mode loopfilter Rz control + volatile unsigned long icp_tx : 5; //tx mode cp current control + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x13_TypeDef; + +/// REG0x14 +typedef union +{ + struct + { + volatile unsigned long dc_i_0db : 8; //RX dcoc I path input for 0dB of PGA + volatile unsigned long dc_q_0db : 8; //RX dcoc Q path input for 0dB of PGA + volatile unsigned long dc_i_3db : 8; //RX dcoc I path input for 3dB of PGA + volatile unsigned long dc_q_3db : 8; //RX dcoc Q path input for 3dB of PGA + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x14_TypeDef; + +/// REG0x15 +typedef union +{ + struct + { + volatile unsigned long dc_i_6db : 8; //RX dcoc I path input for 6dB of PGA + volatile unsigned long dc_q_6db : 8; //RX dcoc Q path input for 6dB of PGA + volatile unsigned long dc_i_9db : 8; //RX dcoc I path input for 9dB of PGA + volatile unsigned long dc_q_9db : 8; //RX dcoc Q path input for 9dB of PGA + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x15_TypeDef; + +/// REG0x16 +typedef union +{ + struct + { + volatile unsigned long dc_i_12db : 8; //RX dcoc I path input for 12dB of PGA + volatile unsigned long dc_q_12db : 8; //RX dcoc Q path input for 12dB of PGA + volatile unsigned long dc_i_15db : 8; //RX dcoc I path input for 15dB of PGA + volatile unsigned long dc_q_15db : 8; //RX dcoc Q path input for 15dB of PGA + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x16_TypeDef; + +/// REG0x17 +typedef union +{ + struct + { + volatile unsigned long dc_i_18db : 8; //RX dcoc I path input for 18dB of PGA + volatile unsigned long dc_q_18db : 8; //RX dcoc Q path input for 18dB of PGA + volatile unsigned long dc_i_21db : 8; //RX dcoc I path input for 21dB of PGA + volatile unsigned long dc_q_21db : 8; //RX dcoc Q path input for 21dB of PGA + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x17_TypeDef; + +/// REG0x18 +typedef union +{ + struct + { + volatile unsigned long dc_i_24db : 8; //RX dcoc I path input for 24dB of PGA + volatile unsigned long dc_q_24db : 8; //RX dcoc Q path input for 24dB of PGA + volatile unsigned long dc_i_27db : 8; //RX dcoc I path input for 27dB of PGA + volatile unsigned long dc_q_27db : 8; //RX dcoc Q path input for 27dB of PGA + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x18_TypeDef; + +/// REG0x19 +typedef union +{ + struct + { + volatile unsigned long dc_i_30db : 8; //RX dcoc I path input for 30dB of PGA + volatile unsigned long dc_q_30db : 8; //RX dcoc Q path input for 30dB of PGA + volatile unsigned long dc_i_33db : 8; //RX dcoc I path input for 33dB of PGA + volatile unsigned long dc_q_33db : 8; //RX dcoc Q path input for 33dB of PGA + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x19_TypeDef; + +/// REG0x1A +typedef union +{ + struct + { + volatile unsigned long dc_i_36db : 8; //RX dcoc I path input for 36dB of PGA + volatile unsigned long dc_q_36db : 8; //RX dcoc Q path input for 36dB of PGA + volatile unsigned long dc_i_39db : 8; //RX dcoc I path input for 39dB of PGA + volatile unsigned long dc_q_39db : 8; //RX dcoc Q path input for 39dB of PGA + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x1A_TypeDef; + +/// REG0x1B +typedef union +{ + struct + { + volatile unsigned long dc_i_42db : 8; //RX dcoc I path input for 42dB of PGA + volatile unsigned long dc_q_42db : 8; //RX dcoc Q path input for 42dB of PGA + volatile unsigned long dc_i_45db : 8; //RX dcoc I path input for 45dB of PGA + volatile unsigned long dc_q_45db : 8; //RX dcoc Q path input for 45dB of PGA + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x1B_TypeDef; + +/// REG0x1C +typedef union +{ + struct + { + volatile unsigned long dac_out_qspi : 10; //DAC Q channel input in analog test only; + volatile unsigned long NC1 : 2; + volatile unsigned long dac_out_ispi : 10; //DAC I channel input in analog test only; + volatile unsigned long NC2 : 10; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x1C_TypeDef; + + +/// BK7011TRxV2A +struct BK7231N_TRX_REG_TypeDef +{ + volatile BK7011_TRxV2A_REG0x0_TypeDef *REG0x0; + volatile BK7011_TRxV2A_REG0x1_TypeDef *REG0x1; + volatile BK7011_TRxV2A_REG0x2_TypeDef *REG0x2; + volatile BK7011_TRxV2A_REG0x3_TypeDef *REG0x3; + volatile BK7011_TRxV2A_REG0x4_TypeDef *REG0x4; + volatile BK7011_TRxV2A_REG0x5_TypeDef *REG0x5; + volatile BK7011_TRxV2A_REG0x6_TypeDef *REG0x6; + volatile BK7011_TRxV2A_REG0x7_TypeDef *REG0x7; + volatile BK7011_TRxV2A_REG0x8_TypeDef *REG0x8; + volatile BK7011_TRxV2A_REG0x9_TypeDef *REG0x9; + volatile BK7011_TRxV2A_REG0xA_TypeDef *REG0xA; + volatile BK7011_TRxV2A_REG0xB_TypeDef *REG0xB; + volatile BK7011_TRxV2A_REG0xC_TypeDef *REG0xC; + volatile BK7011_TRxV2A_REG0xD_TypeDef *REG0xD; + volatile BK7011_TRxV2A_REG0xE_TypeDef *REG0xE; + volatile BK7011_TRxV2A_REG0xF_TypeDef *REG0xF; + volatile BK7011_TRxV2A_REG0x10_TypeDef *REG0x10; + volatile BK7011_TRxV2A_REG0x11_TypeDef *REG0x11; + volatile BK7011_TRxV2A_REG0x12_TypeDef *REG0x12; + volatile BK7011_TRxV2A_REG0x13_TypeDef *REG0x13; + volatile BK7011_TRxV2A_REG0x14_TypeDef *REG0x14; + volatile BK7011_TRxV2A_REG0x15_TypeDef *REG0x15; + volatile BK7011_TRxV2A_REG0x16_TypeDef *REG0x16; + volatile BK7011_TRxV2A_REG0x17_TypeDef *REG0x17; + volatile BK7011_TRxV2A_REG0x18_TypeDef *REG0x18; + volatile BK7011_TRxV2A_REG0x19_TypeDef *REG0x19; + volatile BK7011_TRxV2A_REG0x1A_TypeDef *REG0x1A; + volatile BK7011_TRxV2A_REG0x1B_TypeDef *REG0x1B; + volatile BK7011_TRxV2A_REG0x1C_TypeDef *REG0x1C; +}; + +typedef struct +{ + BK7011_TRxV2A_REG0x0_TypeDef REG0x0; + BK7011_TRxV2A_REG0x1_TypeDef REG0x1; + BK7011_TRxV2A_REG0x2_TypeDef REG0x2; + BK7011_TRxV2A_REG0x3_TypeDef REG0x3; + BK7011_TRxV2A_REG0x4_TypeDef REG0x4; + BK7011_TRxV2A_REG0x5_TypeDef REG0x5; + BK7011_TRxV2A_REG0x6_TypeDef REG0x6; + BK7011_TRxV2A_REG0x7_TypeDef REG0x7; + BK7011_TRxV2A_REG0x8_TypeDef REG0x8; + BK7011_TRxV2A_REG0x9_TypeDef REG0x9; + BK7011_TRxV2A_REG0xA_TypeDef REG0xA; + BK7011_TRxV2A_REG0xB_TypeDef REG0xB; + BK7011_TRxV2A_REG0xC_TypeDef REG0xC; + BK7011_TRxV2A_REG0xD_TypeDef REG0xD; + BK7011_TRxV2A_REG0xE_TypeDef REG0xE; + BK7011_TRxV2A_REG0xF_TypeDef REG0xF; + BK7011_TRxV2A_REG0x10_TypeDef REG0x10; + BK7011_TRxV2A_REG0x11_TypeDef REG0x11; + BK7011_TRxV2A_REG0x12_TypeDef REG0x12; + BK7011_TRxV2A_REG0x13_TypeDef REG0x13; + BK7011_TRxV2A_REG0x14_TypeDef REG0x14; + BK7011_TRxV2A_REG0x15_TypeDef REG0x15; + BK7011_TRxV2A_REG0x16_TypeDef REG0x16; + BK7011_TRxV2A_REG0x17_TypeDef REG0x17; + BK7011_TRxV2A_REG0x18_TypeDef REG0x18; + BK7011_TRxV2A_REG0x19_TypeDef REG0x19; + BK7011_TRxV2A_REG0x1A_TypeDef REG0x1A; + BK7011_TRxV2A_REG0x1B_TypeDef REG0x1B; + BK7011_TRxV2A_REG0x1C_TypeDef REG0x1C; +} BK7231N_TRX_TypeDef; +#endif + +/// POWER +typedef struct +{ + unsigned int regc_4_6 : 4; + unsigned int regc_8_10 : 4; + unsigned int pregain : 12; + unsigned int unuse : 12; +} PWR_REGS; + +typedef unsigned int PWR_REGS_TPC; + +typedef struct +{ + INT32 gtx_dc_n;//the times of first dc cal. (64 * BK_TX_DAC_COEF)=2^8 + UINT32 gst_rx_adc; + UINT32 gst_sar_adc; + + UINT32 cali_mode; + INT32 gtx_tssi_thred_b; + INT32 gtx_tssi_thred_g; + + UINT32 is_tpc_used; + +#if CFG_USE_TEMPERATURE_DETECT + INT16 ble_pwr_indx; + INT16 ble_pwr_shift; +#endif + UINT32 device_id; +} BK7011_CALI_CONTEXT; + +typedef struct +{ + INT32 gbias_after_cal; + INT32 gav_tssi; + + INT32 gtx_i_dc_comp; + INT32 gtx_q_dc_comp; + INT32 gtx_i_dc_comp_loopback; + INT32 gtx_q_dc_comp_loopback; + + INT32 gtx_i_gain_comp; + INT32 gtx_q_gain_comp; + INT32 gtx_i_gain_comp_loopback; + INT32 gtx_q_gain_comp_loopback; + + INT32 gtx_phase_comp; + INT32 gtx_phase_ty2; + INT32 gtx_phase_comp_loopback; + INT32 gtx_phase_ty2_loopback; + + INT32 gtx_ifilter_corner; + INT32 gtx_qfilter_corner; + + INT32 const_iqcal_p; + + INT32 grx_amp_err_wr; + INT32 grx_phase_err_wr; + +#ifdef SCAN_IQ_FILTER_CORNER + UINT32 g_sctrl_bias_reg; + INT32 grx_avg_i_14M; + INT32 grx_avg_i_14M2; + INT32 grx_avg_q_14M; + INT32 grx_avg_q_14M2; + INT32 index_test[5]; + float float2_test[5]; +#endif + + INT32 rx_amp_err_rd; + INT32 rx_phase_err_rd; + INT32 rx_ty2_rd; + + INT32 g_rx_dc_gain_tab[8]; +} BK7011_CALI_RESULT; + +/******************************************************************************* +* Function Declarations +*******************************************************************************/ +void rwnx_cal_en_rx_filter_offset(void); +void rwnx_cal_set_bw_i2v(int enable); +void rwnx_cal_dis_rx_filter_offset(void); + +#endif // (CFG_SOC_NAME != SOC_BK7231) + +#endif // _BK7231U_CAL_H_ diff --git a/beken_os/beken378/func/bk7011_cal/bk7231U_cal.c b/beken_os/beken378/func/bk7011_cal/bk7231U_cal.c new file mode 100755 index 0000000..2295699 --- /dev/null +++ b/beken_os/beken378/func/bk7011_cal/bk7231U_cal.c @@ -0,0 +1,6423 @@ + +#include "include.h" +#if (CFG_SOC_NAME == SOC_BK7231U) + +#include "arm_arch.h" + +#include "target_util_pub.h" +#include "mem_pub.h" + +#include "drv_model_pub.h" +#include "sys_ctrl_pub.h" +#include "phy.h" + +#include "bk7011_cal_pub.h" +#include "bk7011_cal.h" + +#include +#include "flash_pub.h" +#ifdef INCLUDE_OS +#include "cmd_evm.h" +#include "temp_detect_pub.h" +#endif +#include "power_save_pub.h" + +#define CAL_RESULT_TO_FLASH 0 +#define CAL_RESULT_FLASH_ADDR 0x000F1000UL + + +#if CFG_SUPPORT_CALIBRATION + +#define TX_WANTED_POWER_CAL 0 +#define TX_IQ_POWER_CAL 1 +#define TX_IQ_LOOPBACK_POWER_CAL 2 +#define TX_DC_CAL 0 +#define TX_DC_CAL_IQ 1 +#define TX_DC_LOOPBACK_CAL_IQ 2 +#define TX_GAIN_IMB_CAL 0 +#define TX_GAIN_LOOPBACK_IMB_CAL 1 +#define TX_PHASE_IMB_CAL 0 +#define TX_PHASE_LOOPBACK_IMB_CAL 1 + + +#define CAL_DEBUG 1 +#include "uart_pub.h" +#if CAL_DEBUG +#define CAL_PRT null_prf +#define CAL_WARN null_prf// warning_prf +#define CAL_FATAL fatal_prf +#define CAL_TIM_PRT os_printf +#define CAL_FLASH_PRT os_printf +#else +#define CAL_PRT null_prf +#define CAL_WARN null_prf +#define CAL_FATAL null_prf +#define CAL_TIM_PRT null_prf +#define CAL_FLASH_PRT null_prf +#endif + + +extern void bk7011_cal_pll(void); +static void bk7011_cal_dcormod_save_base(INT32 mod); +static void bk7011_cal_dcormod_do_fitting(void); +static UINT8 bk7011_cal_dcormod_get(void); +void rwnx_cal_set_txpwr_ble(UINT32 pwr_gain); +void rwnx_set_tpc_txpwr_by_tmpdetect(INT16 shift_b, INT16 shift_g); +void rwnx_cal_set_ble_txpwr_by_tmpdetect(INT16 shift_ble); +extern UINT32 ble_in_dut_mode(void); +extern uint8 is_rf_switch_to_ble(void); +extern uint32_t get_ate_mode_state(void); +extern void rwnx_cal_enable_lpfcap_iq_from_digit(UINT32 enable); + + +static INT32 gtx_dc_n = 0;//the times of first dc cal. +static UINT32 gst_rx_adc = CAL_DELAY100US; +static UINT32 gst_sar_adc = CAL_DELAY05US; +//static UINT8 pwr_nstep = 0; + +#define BK7231_56PIN_BOARD 1 +#define BK7231_32PIN_BOARD 2 +#define BK7231_32PIN_TZH_BOARD 3 +#define BK7231U_BOARD 4 + +//#define BOARD BK7231_32PIN_TZH_BOARD +#define BOARD BK7231U_BOARD + +#if (BOARD == BK7231_56PIN_BOARD) +#define TRX_REG_0XA_VAL 0x036F0757 +#define TRX_REG_0XB_VAL 0x20240077 +#define TRX_REG_0XC_VAL 0x01A267EE +#define TRX_REG_0XD_VAL 0xDDF90339 +#define TSSI_POUT_TH 0x50 //0x50:RF components for best power,0x43:for best sens +#elif (BOARD == BK7231_32PIN_BOARD) +#define TRX_REG_0XA_VAL 0x036F0757 +#define TRX_REG_0XB_VAL 0x17248757 +#define TRX_REG_0XC_VAL 0x5228765 +#define TRX_REG_0XD_VAL 0xDDF90339 +#define TSSI_POUT_TH 0x80 +#elif (BOARD == BK7231_32PIN_TZH_BOARD) +#define TRX_REG_0XA_VAL 0x036F0757 +#define TRX_REG_0XB_VAL 0x20242077 +#define TRX_REG_0XC_VAL 0x5228765 +#define TRX_REG_0XD_VAL 0xDDF90339 +#define TSSI_POUT_TH 0x60 +#elif (BOARD == BK7231U_BOARD) +#define TRX_REG_0XA_VAL 0x036F2075//0x036A2075 +#define TRX_REG_0XB_VAL 0xA7248F37//0x45248437 +#define TRX_REG_0XC_VAL 0x0022A755 +#define TRX_REG_0XD_VAL 0xDDF90339 +#define TSSI_POUT_TH 0x54 ///0x50 +#endif + +#if 0 +int TXIQ_IMB_TSSI_TH = 105; // 75-165 +15 +#else +#define TXIQ_IMB_TSSI_TH 70 +#endif + +#if 0 +int TXIQ_IMB_TSSI_TH_LOOPBACK = 90; // 20-250 +20 +#else +#define TXIQ_IMB_TSSI_TH_LOOPBACK 60 +#endif + +#define No_TXPOWERCAL 0 +#if 0 +int TXIQ_TSSI_TH = 0x40; +#else +#define TXIQ_TSSI_TH 0x40 +#endif +#define TRX_REG_0XD_TX_IQ_VAL 0xD9FF0338 //0xD9FF0338 //0214 +#define TRX_REG_0XD_TX_LOOPBACK_IQ_VAL 0xD9FE7FF1 //0214 0xD9FE7FF1 + +#define TRX_REG_0XC_TXLO_LEAKAGE_VAL 0x5228100 + +#define TRX_REG_0XC_RXIQ_VAL 0x5228565 // 1A244ED //0215 increasse gain due to load antenna 01A244DD +#define TRX_REG_0XE_RXIQ_VAL 0xD9F87FF1 //0214 FDF87FF1 + + +#if 0 +INT32 gi_dc_tx_pa_dgainPA30 = 2; // 1-5 +INT32 gi_dc_tx_pa_dgainbuf30 = 6; // 4-7 +INT32 gi_gain_tx_pa_dgainPA30 = 2; // 1-4 +INT32 gi_gain_tx_pa_dgainbuf30 = 5; // 2-5 +#else +#define gi_dc_tx_pa_dgainPA30 7 +#define gi_dc_tx_pa_dgainbuf30 6 +#define gi_gain_tx_pa_dgainPA30 2 +#define gi_gain_tx_pa_dgainbuf30 4 +#endif + +#if 0 +INT32 gi_dc_tx_loopback_pa_dgainPA30 = 5; // 3-5 +INT32 gi_dc_tx_loopback_pa_dgainbuf30 = 7; // 4-7 +INT32 gi_gain_tx_loopback_pa_dgainPA30 = 6; // 3-7 +INT32 gi_gain_tx_loopback_pa_dgainbuf30 = 6; // 3-7 +INT32 gi_phase_tx_loopback_pa_dgainPA30 = 6; // 3-7 +INT32 gi_phase_tx_loopback_pa_dgainbuf30 = 5; // 3-7 +#else +#define gi_dc_tx_loopback_pa_dgainPA30 7 +#define gi_dc_tx_loopback_pa_dgainbuf30 6 +#define gi_gain_tx_loopback_pa_dgainPA30 6 +#define gi_gain_tx_loopback_pa_dgainbuf30 4 +#define gi_phase_tx_loopback_pa_dgainPA30 6 +#define gi_phase_tx_loopback_pa_dgainbuf30 4 +#endif + +#if 0 +INT32 gi_cal_rx_iq_pa_dgainPA30 = 5; // 3-7 +INT32 gi_cal_rx_iq_pa_dgainbuf30 = 5; // 3-7 +#else +#define gi_cal_rx_iq_pa_dgainPA30 4 +#define gi_cal_rx_iq_pa_dgainbuf30 5 +#endif + + +#ifdef CALIBRATE_TIMES +#define SCAN_IQ_FILTER_CORNER +#undef SCAN_IQ_FILTER_CORNER + +int calibrate_times_all = CALIBRATE_TIMES; +int calibrate_time = 0; + +int *p_gbias_after_cal_array = NULL; +int *p_gav_tssi_array = NULL; +int *p_gtx_ifilter_corner_array = NULL; +int *p_gtx_qfilter_corner_array = NULL; +#ifdef SCAN_IQ_FILTER_CORNER +int index_test[500*5]; +float float2_test[500*5]; +UINT32 g_sctrl_bias_reg = 0; +UINT32 *p_g_sctrl_bias_reg_array = NULL; +int grx_avg_i_14M = 0; +int grx_avg_i_14M2 = 0; +int grx_avg_q_14M = 0; +int grx_avg_q_14M2 = 0; +int *p_grx_avg_i_14M_array = NULL; +int *p_grx_avg_i_14M_array2 = NULL; +int *p_grx_avg_q_14M_array = NULL; +int *p_grx_avg_q_14M_array2 = NULL; +#endif +int *p_rx_amp_err_rd_array = NULL; +int *p_rx_phase_err_rd_array = NULL; +int *p_rx_ty2_rd_array = NULL; + +int *p_gtx_i_dc_comp_array = NULL; +int *p_gtx_q_dc_comp_array = NULL; +int *p_gtx_i_gain_comp_array = NULL; +int *p_gtx_q_gain_comp_array = NULL; +int *p_gtx_phase_comp_array = NULL; + +int *p_gtx_i_dc_comp_temp_array = NULL; +int *p_gtx_q_dc_comp_temp_array = NULL; +int *p_gtx_i_gain_comp_temp_array = NULL; +int *p_gtx_q_gain_comp_temp_array = NULL; +int *p_gtx_phase_comp_temp_array = NULL; + +int *p_g_rx_dc_gain_tab_array = NULL; +/*int rx_amp_err_rd_array[CALIBRATE_TIMES]; +int rx_phase_err_rd_array[CALIBRATE_TIMES]; +int gtx_i_gain_comp_temp_array[CALIBRATE_TIMES]; +int gtx_q_gain_comp_temp_array[CALIBRATE_TIMES]; +int gtx_phase_comp_temp_array[CALIBRATE_TIMES]; +int gtx_i_gain_comp_array[CALIBRATE_TIMES]; +int gtx_q_gain_comp_array[CALIBRATE_TIMES]; +int gtx_phase_comp_array[CALIBRATE_TIMES];*/ +#endif + +#define TRX_BEKEN_REGS \ +{ \ + 0x00039042, /* 00-R0x00, // */ \ + 0xF0D9347B, /* 01-R0x01, // 26M spur 0xF259347B;*/ \ + 0x4CAD2213, /* 02-R0x02, // */ \ + 0x7C945A75, /* 03-R0x03, // */ \ + 0x13D0110F, /* 04-R0x04, // */ \ + 0x1804AA47, /* 05-R0x05, // */ \ + 0x5FA44100, /* 06-R0x06, // */ \ + 0x000020F5, /* 07-R0x07, // 00F5:4th;20F5:2nd */ \ + 0x0728289E, /* 08-R0x08, // 0x072A289E */ \ + 0x000163AF, /* 09-R0x09, // */ \ + TRX_REG_0XA_VAL, /* 10-R0x0A, // */ \ + TRX_REG_0XB_VAL, /* 11-R0x0B, // */ \ + TRX_REG_0XC_VAL, /* 12-R0x0C, // */ \ + 0xDDF90339, /* 13-R0x0D, // */ \ + 0xDA01BCF0, /* 14-R0x0E, // */ \ + 0x00018000, /* 15-R0x0F, // */ \ + 0xD8800000, /* 16-R0x10, // */ \ + 0x00000000, /* 17-R0x11, // */ \ + 0xD0090481, /* 18-R0x12, // 0xF0090481 */ \ + 0x7B305ECC, /* 19-R0x13, // */ \ + 0x827C827C, /* 20-R0x14, // */ \ + 0x86788678, /* 21-R0x15, // */ \ + 0x8C748C74, /* 22-R0x16, // */ \ + 0xA45F9868, /* 23-R0x17, // */ \ + 0xA45FA45F, /* 24-R0x18, // */ \ + 0xA55EA45F, /* 25-R0x19, // */ \ + 0xA55DA55E, /* 26-R0x1A, // */ \ + 0xA55DA55D, /* 27-R0x1B, // */ \ + 0x20000000 /* 28-R0x1C, // */ \ +}; + +#define RC_BEKEN_REGS \ +{ \ + 0x00000009, /* 00-R0x0, 0x0000; */ \ + 0xF0000000, /* 01-R0x1, 0x0004; */ \ + 0x00000030, /* 02-R0x5, 0x0014; */ \ + 0x00010001, /* 03-R0x8, 0x0020; */ \ + 0x000100e0, /* 04-R0xB, 0x002C; */ \ + 0x00010070, /* 05-R0xE, 0x0038; */ \ + 0x00010001, /* 06-R0x11, 0x0044; */ \ + 0x00010005, /* 07-R0x19, 0x0064; */ \ + 0x00000002, /* 08-R0x1C, 0x0070; */ \ + 0x0000012c, /* 09-R0x1E, 0x0078; */ \ + 0x1002DF4B, /* 10-R0x3C, 0x00F0; */ \ + 0x00000000, /* 11-R0x3E, 0x00F8; */ \ + 0x03E803CB, /* 12-R0x3F, 0x00FC; */ \ + 0x00000001, /* 13-R0x40, 0x0100; */ \ + 0x00000000, /* 14-R0x41, 0x0104; */ \ + 0x02000041, /* 15-R0x42, 0x0108; */ \ + 0x018B018B, /* 16-R0x4C, 0x0130; */ \ + 0x2CC02000, /* 17-R0x4D, 0x0134; */ \ + 0x02000200, /* 18-R0x4F, 0x013C; */ \ + 0x03ff03ff, /* 19-R0x50, 0x0140; */ \ + 0x02000200, /* 20-R0x51, 0x0144; */ \ + 0x44108800, /* 21-R0x52, 0x0148; */ \ + (0x00025600|((TSSI_POUT_TH)<<1)), /* 22-R0x54, 0x0150; */ \ + 0x00000000, /* 23-R0x55, 0x0154; */ \ + 0x80000064, /* 24-R0x5C, 0x0170; */ \ + 0x00000001, /* 25-R0x4E, 0x0138; */ \ + 0x00000000, /* 26-R0x5A, 0x0168; */ \ + 0x00000000, /* 27-R0x5B, 0x016C; */ \ + 0x00000000, /* 28-R0x6A, 0x01A8; */ \ + 0x00000000, /* 29-R0x70, 0x01C0; */ \ + 0x00000000, /* 30-R0x71, 0x01C4; */ \ + 0x00000000, /* 31-R0x72, 0x01C8; */ \ + 0x00000000, /* 32-R0x73, 0x01CC; */ \ + 0x00000000, /* 33-R0x74, 0x01D0; */ \ + 0x00000000, /* 34-R0x75, 0x01D4; */ \ + 0x00000000, /* 35-R0x76, 0x01D8; */ \ + 0x00000000, /* 36-R0x77, 0x01DC; */ \ +}; + +const static INT32 bk7011_trx_val1[32] = TRX_BEKEN_REGS; +const static INT32 bk7011_rc_val1[37] = RC_BEKEN_REGS; + +static INT32 bk7011_trx_val[32] = TRX_BEKEN_REGS; +static INT32 bk7011_rc_val[37] = RC_BEKEN_REGS; + +//static UINT8 gstat_cal = 1; // 1: calibration not done, 0: done + +//INT32 gconst_iqcal_p = 0xB0;//117; 0x10-0x80 0x10 +#define gconst_iqcal_p 0xB0 + +INT32 gconst_pout = 0x210; +INT32 gav_tssi = 0; +INT32 gav_tssi_temp = 0; +INT32 grc_reg_map[32]; +UINT8 gbias_after_cal = 0; + +//INT32 gpll_lock_err = 1; + +//INT32 gadda_map[6]; +//INT32 gdc_goldval[32]= {0}; +//INT32 g_tri_offset = 0; + +INT32 gtx_dcorMod = 0x4; +INT32 gtx_dcorPA = 0x8; +INT32 gtx_pre_gain = 0x10; + +INT32 gtx_dcorMod_temp = 0x4; +INT32 gtx_dcorPA_temp = 0x8; +INT32 gtx_pre_gain_temp = 0x7; + +INT32 gtx_dcorMod_temp_loopback = 0x4; +INT32 gtx_dcorPA_temp_loopback = 0x8; +INT32 gtx_pre_gain_temp_loopback = 0x7; + +INT32 gtx_i_dc_comp_loopback = 0x202; +INT32 gtx_q_dc_comp_loopback = 0x1ff; + +INT32 gtx_i_gain_comp_loopback = 0x3ff; +INT32 gtx_q_gain_comp_loopback = 0x3f3; + +INT32 gtx_i_dc_comp = 0x200; +INT32 gtx_q_dc_comp = 0x200; + +INT32 gtx_i_gain_comp = 0x3ff; +INT32 gtx_q_gain_comp = 0x3ff; + +INT32 gtx_ifilter_corner = 0x10; +INT32 gtx_qfilter_corner = 0x10; +UINT32 g_capcal_sel = 14; + +INT32 gtx_phase_comp_loopback = 0x200; +INT32 gtx_phase_ty2_loopback = 0x200; + +INT32 gtx_phase_comp = 0x200; +INT32 gtx_phase_ty2 = 0x200; + +INT32 gtx_power_cal_mode = TX_WANTED_POWER_CAL; +INT32 gtx_dc_cal_mode = TX_DC_CAL; +INT32 gtx_gain_imb_cal_mode = TX_GAIN_IMB_CAL; +INT32 gtx_phase_imb_cal_mode = TX_PHASE_IMB_CAL; + +INT32 gtx_band = 0x4a; +static UINT32 is_tpc_used = 0; + +typedef enum{ + CM_TX_DCOR_MOD_FLAG = 0, + CM_TX_DCOR_PA_FLAG, // 1 + CM_TX_PREGAIN_FLAG, // 2 + CM_TX_I_DC_COMP_FLAG, // 3 + CM_TX_Q_DC_COMP_FLAG, // 4 + CM_TX_I_GAIN_COMP_FLAG, // 5 + CM_TX_Q_GAIN_COMP_FLAG, // 6 + CM_TX_I_FILTER_CORNER_FLAG, // 7 + CM_TX_Q_FILTER_CORNER_FLAG, // 8 + CM_TX_PHASE_COMP_FLAG, // 9 + CM_TX_PHASE_TY2_FLAG, // 10 + CM_RX_DC_GAIN_TAB_FLAG, // 11 + CM_RX_AMP_ERR_WR_FLAG, // 12 + CM_RX_PHASE_ERR_WR_FLAG, // 13 +}CM_FLAG; + +static UINT32 cali_main_flags = 0; +#define CM_SET_FLAG_BIT(bit) cali_main_flags |= (1 << (bit)) +#define CM_CLR_FLAG_BIT(bit) cali_main_flags &= ~(1 << (bit)) +#define CM_CLR_FLAG_ALLBIT() cali_main_flags = 0 +#define CM_FLAG_IS_SET() (cali_main_flags != 0)? 1 : 0 + +struct cal_pwr_st +{ + UINT8 idx; + UINT8 mode; +}; + +struct cal_pwr_st g_pwr_current; + +INT32 g_rx_dc_gain_tab[8] = +{ + 0x827C827C, + 0x86788678, + 0x8C748C74, + 0xA45F9868, + 0xA45FA45F, + 0xA55EA45F, + 0xA55DA55E, + 0xA55DA55D +}; + +INT32 grx_amp_err_wr = 0x200; +INT32 grx_phase_err_wr = 0x041; + +#include "net_param_pub.h" + +#define CALI_MODE_AUTO 0 +#define CALI_MODE_MANUAL 1 + +UINT32 g_cali_mode = CALI_MODE_AUTO; +INT32 gtx_tssi_thred = TSSI_POUT_TH; + +#define PWRI(gain, rb_28_31, rc_8_10, rc_4_6, rc_0_2, ra_8_13, ra_4_7, ra_0_1) \ +{ \ + .unuse = 0, \ + .pregain = gain, \ + .regb_28_31 = rb_28_31, \ + .regc_8_10 = rc_8_10, \ + .regc_4_6 = rc_4_6, \ + .regc_0_2 = rc_0_2, \ + .rega_8_13 = ra_8_13, \ + .rega_4_7 = ra_4_7, \ + .rega_0_1 = ra_0_1, \ +} + +PWR_REGS cfg_tab_b[32] = { + // pregain REGB<31:28> REGC<10:8> REGC<6:4> REGC<2:0> REGA<13:8> REGA<7:4> REGA<1:0> + PWRI( 0x16 , 0xA, 7, 3, 1, 0x20, 0x7, 0x1 ), // 0 + PWRI( 0x13 , 0xA, 7, 3, 1, 0x20, 0x7, 0x1 ), // 1 + PWRI( 0x10 , 0xA, 7, 3, 1, 0x20, 0x7, 0x1 ), // 2 + PWRI( 0x19 , 0xA, 7, 3, 2, 0x20, 0x7, 0x1 ), // 3 + PWRI( 0x16 , 0xA, 7, 3, 2, 0x20, 0x7, 0x1 ), // 4 + PWRI( 0x13 , 0xA, 7, 3, 2, 0x20, 0x7, 0x1 ), // 5 + PWRI( 0x10 , 0xA, 7, 3, 2, 0x20, 0x7, 0x1 ), // 6 + PWRI( 0xD , 0xA, 7, 3, 2, 0x20, 0x7, 0x1 ), // 7 + PWRI( 0xA , 0xA, 7, 3, 2, 0x20, 0x7, 0x1 ), // 8 + PWRI( 0x7 , 0xA, 7, 3, 2, 0x20, 0x7, 0x1 ), // 9 + PWRI( 0x4 , 0xA, 7, 3, 2, 0x20, 0x7, 0x1 ), // 10 + PWRI( 0x1 , 0xA, 7, 3, 2, 0x20, 0x7, 0x1 ), // 11 + PWRI( 0x12 , 0xA, 7, 4, 3, 0x20, 0x7, 0x1 ), // 12 + PWRI( 0xF , 0xA, 7, 4, 3, 0x20, 0x7, 0x1 ), // 13 + PWRI( 0xC , 0xA, 7, 4, 3, 0x20, 0x7, 0x1 ), // 14 + PWRI( 0x9 , 0xA, 7, 4, 3, 0x20, 0x7, 0x1 ), // 15 + PWRI( 0x6 , 0xA, 7, 4, 3, 0x20, 0x7, 0x1 ), // 16 + PWRI( 0x3 , 0xA, 7, 4, 3, 0x20, 0x7, 0x1 ), // 17 + PWRI( 0x1E , 0xA, 7, 5, 5, 0x20, 0x7, 0x1 ), // 18 + PWRI( 0x1C , 0xA, 7, 5, 5, 0x20, 0x7, 0x1 ), // 19 + PWRI( 0x1A , 0xA, 7, 5, 5, 0x20, 0x7, 0x1 ), // 20 + PWRI( 0x18 , 0xA, 7, 5, 5, 0x20, 0x7, 0x1 ), // 21 + PWRI( 0x16 , 0xA, 7, 5, 5, 0x20, 0x7, 0x1 ), // 22 + PWRI( 0x14 , 0xA, 7, 5, 5, 0x20, 0x7, 0x1 ), // 23 + PWRI( 0x12 , 0xA, 7, 5, 5, 0x20, 0x7, 0x1 ), // 24 + PWRI( 0x10 , 0xA, 7, 5, 5, 0x20, 0x7, 0x1 ), // 25 + PWRI( 0xE , 0xA, 7, 5, 5, 0x20, 0x7, 0x1 ), // 26 + PWRI( 0xC , 0xA, 7, 5, 5, 0x20, 0x7, 0x1 ), // 27 + PWRI( 0x9 , 0xA, 7, 5, 5, 0x20, 0x7, 0x1 ), // 28 + PWRI( 0x6 , 0xA, 7, 5, 5, 0x20, 0x7, 0x1 ), // 29 + PWRI( 0x3 , 0xA, 7, 5, 5, 0x20, 0x7, 0x1 ), // 30 + PWRI( 0x0 , 0xA, 7, 5, 5, 0x20, 0x7, 0x1 ), // 31 +}; + +PWR_REGS cfg_tab_g[32] = { + // pregain REGB<31:28> REGC<10:8> REGC<6:4> REGC<2:0> REGA<13:8> REGA<7:4> REGA<1:0> + PWRI( 0x18, 0xA, 7, 5, 2, 0x20, 0x7, 0x1 ), // 0 + PWRI( 0x15, 0xA, 7, 5, 2, 0x20, 0x7, 0x1 ), // 1 + PWRI( 0x1E, 0xA, 7, 5, 3, 0x20, 0x7, 0x1 ), // 2 + PWRI( 0x1B, 0xA, 7, 5, 3, 0x20, 0x7, 0x1 ), // 3 + PWRI( 0x18, 0xA, 7, 5, 3, 0x20, 0x7, 0x1 ), // 4 + PWRI( 0x15, 0xA, 7, 5, 3, 0x20, 0x7, 0x1 ), // 5 + PWRI( 0x12, 0xA, 7, 5, 3, 0x20, 0x7, 0x1 ), // 6 + PWRI( 0xF , 0xA, 7, 5, 3, 0x20, 0x7, 0x1 ), // 7 + PWRI( 0xC , 0xA, 7, 5, 3, 0x20, 0x7, 0x1 ), // 8 + PWRI( 0x9 , 0xA, 7, 5, 3, 0x20, 0x7, 0x1 ), // 9 + PWRI( 0x1F, 0xA, 7, 5, 5, 0x20, 0x7, 0x1 ), // 10 + PWRI( 0x1D, 0xA, 7, 5, 5, 0x20, 0x7, 0x1 ), // 11 + PWRI( 0x1A, 0xA, 7, 5, 5, 0x20, 0x7, 0x1 ), // 12 + PWRI( 0x17, 0xA, 7, 5, 5, 0x20, 0x7, 0x1 ), // 13 + PWRI( 0x14, 0xA, 7, 5, 5, 0x20, 0x7, 0x1 ), // 14 + PWRI( 0x11, 0xA, 7, 5, 5, 0x20, 0x7, 0x1 ), // 15 + PWRI( 0xE , 0xA, 7, 5, 5, 0x20, 0x7, 0x1 ), // 16 + PWRI( 0xB , 0xA, 7, 5, 5, 0x20, 0x7, 0x1 ), // 17 + PWRI( 0x8 , 0xA, 7, 5, 5, 0x20, 0x7, 0x1 ), // 18 + PWRI( 0x5 , 0xA, 7, 5, 5, 0x20, 0x7, 0x1 ), // 19 + PWRI( 0x2 , 0xA, 7, 5, 5, 0x20, 0x7, 0x1 ), // 20 + PWRI( 0x0 , 0xA, 7, 5, 5, 0x20, 0x7, 0x1 ), // 21 + PWRI( 0xF , 0xA, 7, 6, 6, 0x20, 0x7, 0x1 ), // 22 + PWRI( 0xC , 0xA, 7, 6, 6, 0x20, 0x7, 0x1 ), // 23 + PWRI( 0x9 , 0xA, 7, 6, 6, 0x20, 0x7, 0x1 ), // 24 + PWRI( 0x6 , 0xA, 7, 6, 6, 0x20, 0x7, 0x1 ), // 25 + PWRI( 0x3 , 0xA, 7, 6, 6, 0x20, 0x7, 0x1 ), // 26 + PWRI( 0x0 , 0xA, 7, 6, 6, 0x20, 0x7, 0x1 ), // 27 + PWRI( 0xC , 0xA, 7, 7, 6, 0x20, 0x7, 0x2 ), // 28 + PWRI( 0x9 , 0xA, 7, 7, 6, 0x20, 0x7, 0x2 ), // 29 + PWRI( 0x6 , 0xA, 7, 7, 6, 0x20, 0x7, 0x2 ), // 30 + PWRI( 0x3 , 0xA, 7, 7, 6, 0x20, 0x7, 0x2 ), // 31 +}; + +PWR_REGS cfg_tab_ble[32] = { + // pregain REGB<31:28> REGC<11:8> REGC<7:4> REGC<3:0> REGA<13:8> REGA<7:4> REGA<1:0> + PWRI( 0x1F, 0xF, 1, 0, 0, 0x20, 0x0, 0x2 ), // 0 + PWRI( 0x1E, 0xA, 1, 3, 3, 0x20, 0x0, 0x2 ), // 1 + PWRI( 0x1B, 0xA, 1, 3, 3, 0x20, 0x0, 0x2 ), // 2 + PWRI( 0x18, 0xA, 1, 3, 3, 0x20, 0x0, 0x2 ), // 3 + PWRI( 0x15, 0xA, 1, 3, 3, 0x20, 0x0, 0x2 ), // 4 + PWRI( 0x12, 0xA, 1, 3, 3, 0x20, 0x0, 0x2 ), // 5 + PWRI( 0xF , 0xA, 1, 3, 3, 0x20, 0x0, 0x2 ), // 6 + PWRI( 0xC , 0xA, 1, 3, 3, 0x20, 0x0, 0x2 ), // 7 + PWRI( 0x9 , 0xA, 1, 3, 3, 0x20, 0x0, 0x2 ), // 8 + PWRI( 0x6 , 0xA, 1, 3, 3, 0x20, 0x0, 0x2 ), // 9 + PWRI( 0x3 , 0xA, 1, 3, 3, 0x20, 0x0, 0x2 ), // 10 + PWRI( 0x0 , 0xA, 1, 3, 3, 0x20, 0x0, 0x2 ), // 11 + PWRI( 0x1F, 0xA, 1, 5, 5, 0x20, 0x0, 0x2 ), // 12 + PWRI( 0x1C, 0xA, 1, 5, 5, 0x20, 0x0, 0x2 ), // 13 + PWRI( 0x19, 0xA, 1, 5, 5, 0x20, 0x0, 0x2 ), // 14 + PWRI( 0x16, 0xA, 1, 5, 5, 0x20, 0x0, 0x2 ), // 15 + PWRI( 0x13, 0xA, 1, 5, 5, 0x20, 0x0, 0x2 ), // 16 + PWRI( 0x11, 0xA, 1, 5, 5, 0x20, 0x0, 0x2 ), // 17 + PWRI( 0xE , 0xA, 1, 5, 5, 0x20, 0x0, 0x2 ), // 18 + PWRI( 0xC , 0xA, 1, 5, 5, 0x20, 0x0, 0x2 ), // 19 + PWRI( 0x9 , 0xA, 1, 5, 5, 0x20, 0x0, 0x2 ), // 20 + PWRI( 0x7 , 0xA, 1, 5, 5, 0x20, 0x0, 0x2 ), // 21 + PWRI( 0x4 , 0xA, 1, 5, 5, 0x20, 0x0, 0x2 ), // 22 + PWRI( 0x2 , 0xA, 1, 5, 5, 0x20, 0x0, 0x2 ), // 23 + PWRI( 0x0 , 0xA, 1, 5, 5, 0x20, 0x0, 0x2 ), // 24 + PWRI( 0x11, 0xA, 2, 4, 5, 0x20, 0x0, 0x2 ), // 25 + PWRI( 0xF , 0xA, 2, 4, 5, 0x20, 0x0, 0x2 ), // 26 + PWRI( 0xC , 0xA, 2, 4, 5, 0x20, 0x0, 0x2 ), // 27 + PWRI( 0x9 , 0xA, 2, 4, 5, 0x20, 0x0, 0x2 ), // 28 + PWRI( 0x6 , 0xA, 2, 4, 5, 0x20, 0x0, 0x2 ), // 29 + PWRI( 0x3 , 0xA, 2, 4, 5, 0x20, 0x0, 0x2 ), // 30 + PWRI( 0x0 , 0xA, 2, 4, 5, 0x20, 0x0, 0x2 ), // 31 +}; + +#define TCP_PAMAP_TAB_LEN (16) +#define TCP_PAMAP_DEF_PREGAIN (0x0) +#define TCP_PAMAP_DEF_A13_8 (0x20) +#define TCP_PAMAP_DEF_A7_4 (0x1) +#define TCP_PAMAP_DEF_A1_0 (0x1) + +#define TPCI(rb_28_31, rc_0_3, rc_4_7, rc_8_11) \ + { \ + .regb_28_31 = rb_28_31, \ + .regc_0_3 = rc_0_3, \ + .regc_4_7 = rc_4_7, \ + .regc_8_11 = rc_8_11, \ + .value = (rb_28_31<<12)+(rc_0_3<<8)+(rc_4_7<<4)+(rc_8_11) \ + } + +const PWR_REGS_TPC cfg_tab_tpc[TCP_PAMAP_TAB_LEN] = { + // REGB<31:28> REGC<3:0> REGC<7:4> REGC<11:8> value + TPCI( 0xC, 2, 3, 7), // 0 + TPCI( 0xA, 2, 3, 7), // 1 + TPCI( 0x8, 2, 3, 7), // 2 + TPCI( 0xB, 3, 3, 7), // 3 + TPCI( 0x9, 3, 3, 7), // 4 + TPCI( 0xC, 3, 5, 7), // 5 + TPCI( 0xA, 3, 5, 7), // 6 + TPCI( 0x8, 3, 5, 7), // 7 + TPCI( 0xB, 4, 5, 7), // 8 + TPCI( 0x9, 4, 5, 7), // 9 + TPCI( 0x7, 4, 5, 7), // 10 + TPCI( 0xA, 5, 5, 7), // 11 + TPCI( 0x8, 5, 5, 7), // 12 + TPCI( 0x6, 5, 5, 7), // 13 + TPCI( 0x9, 6, 5, 7), // 14 + TPCI( 0x7, 6, 5, 7), // 15 +}; + +const UINT8 b_map[32] = { + 2, 3, 3, 4, // 0 - 3 + 4, 5, 5, 6, // 4 - 7 + 7, 7, 8, 8, // 8 - 11 + 9, 9, 10, 10, // 12 - 15 + 11, 11, 12, 12, // 16 - 19 + 12, 13, 13, 13, // 20 - 23 + 14, 14, 14, 14, // 24 - 27 + 15, 15, 15, 15, // 28 - 31 +}; + +const UINT8 gn_map[32] = { + 0, 0, 0, 0, // 0 - 3 + 1, 2, 2, 3, // 4 - 7 + 4, 4, 4, 5, // 8 - 11 + 5, 6, 7, 7, // 12 - 15 + 8, 9, 10, 10, // 16 - 19 + 11, 12, 12, 12, // 20 - 23 + 13, 13, 14, 14, // 24 - 27 + 14, 15, 15, 15, // 28 - 31 +}; + +struct BK7011RCBEKEN_TypeDef BK7011RCBEKEN = +{ + (volatile BK7011_RC_BEKEN_REG0x0_TypeDef *) (RC_BEKEN_BASE + 0 * 4), + (volatile BK7011_RC_BEKEN_REG0x1_TypeDef *) (RC_BEKEN_BASE + 1 * 4), + (volatile BK7011_RC_BEKEN_REG0x5_TypeDef *) (RC_BEKEN_BASE + 5 * 4), + (volatile BK7011_RC_BEKEN_REG0x8_TypeDef *) (RC_BEKEN_BASE + 8 * 4), + (volatile BK7011_RC_BEKEN_REG0xB_TypeDef *) (RC_BEKEN_BASE + 11 * 4), + (volatile BK7011_RC_BEKEN_REG0xE_TypeDef *) (RC_BEKEN_BASE + 14 * 4), + (volatile BK7011_RC_BEKEN_REG0x11_TypeDef *)(RC_BEKEN_BASE + 17 * 4), + (volatile BK7011_RC_BEKEN_REG0x19_TypeDef *)(RC_BEKEN_BASE + 25 * 4), + (volatile BK7011_RC_BEKEN_REG0x1C_TypeDef *)(RC_BEKEN_BASE + 28 * 4), + (volatile BK7011_RC_BEKEN_REG0x1E_TypeDef *)(RC_BEKEN_BASE + 30 * 4), + (volatile BK7011_RC_BEKEN_REG0x3C_TypeDef *)(RC_BEKEN_BASE + 60 * 4), + (volatile BK7011_RC_BEKEN_REG0x3E_TypeDef *)(RC_BEKEN_BASE + 62 * 4), + (volatile BK7011_RC_BEKEN_REG0x3F_TypeDef *)(RC_BEKEN_BASE + 63 * 4), + (volatile BK7011_RC_BEKEN_REG0x40_TypeDef *)(RC_BEKEN_BASE + 64 * 4), + (volatile BK7011_RC_BEKEN_REG0x41_TypeDef *)(RC_BEKEN_BASE + 65 * 4), + (volatile BK7011_RC_BEKEN_REG0x42_TypeDef *)(RC_BEKEN_BASE + 66 * 4), + (volatile BK7011_RC_BEKEN_REG0x4C_TypeDef *)(RC_BEKEN_BASE + 76 * 4), + (volatile BK7011_RC_BEKEN_REG0x4D_TypeDef *)(RC_BEKEN_BASE + 77 * 4), + (volatile BK7011_RC_BEKEN_REG0x4E_TypeDef *)(RC_BEKEN_BASE + 78 * 4), + (volatile BK7011_RC_BEKEN_REG0x4F_TypeDef *)(RC_BEKEN_BASE + 79 * 4), + (volatile BK7011_RC_BEKEN_REG0x50_TypeDef *)(RC_BEKEN_BASE + 80 * 4), + (volatile BK7011_RC_BEKEN_REG0x51_TypeDef *)(RC_BEKEN_BASE + 81 * 4), + (volatile BK7011_RC_BEKEN_REG0x52_TypeDef *)(RC_BEKEN_BASE + 82 * 4), + (volatile BK7011_RC_BEKEN_REG0x54_TypeDef *)(RC_BEKEN_BASE + 84 * 4), + (volatile BK7011_RC_BEKEN_REG0x55_TypeDef *)(RC_BEKEN_BASE + 85 * 4), + (volatile BK7011_RC_BEKEN_REG0x5A_TypeDef *)(RC_BEKEN_BASE + 90 * 4), + (volatile BK7011_RC_BEKEN_REG0x5B_TypeDef *)(RC_BEKEN_BASE + 91 * 4), + (volatile BK7011_RC_BEKEN_REG0x5C_TypeDef *)(RC_BEKEN_BASE + 92 * 4), + (volatile BK7011_RC_BEKEN_REG0x6A_TypeDef *)(RC_BEKEN_BASE + 106 * 4), + (volatile BK7011_RC_BEKEN_REG0x70_TypeDef *)(RC_BEKEN_BASE + 112 * 4), + (volatile BK7011_RC_BEKEN_REG0x71_TypeDef *)(RC_BEKEN_BASE + 113 * 4), + (volatile BK7011_RC_BEKEN_REG0x72_TypeDef *)(RC_BEKEN_BASE + 114 * 4), + (volatile BK7011_RC_BEKEN_REG0x73_TypeDef *)(RC_BEKEN_BASE + 115 * 4), + (volatile BK7011_RC_BEKEN_REG0x74_TypeDef *)(RC_BEKEN_BASE + 116 * 4), + (volatile BK7011_RC_BEKEN_REG0x75_TypeDef *)(RC_BEKEN_BASE + 117 * 4), + (volatile BK7011_RC_BEKEN_REG0x76_TypeDef *)(RC_BEKEN_BASE + 118 * 4), + (volatile BK7011_RC_BEKEN_REG0x77_TypeDef *)(RC_BEKEN_BASE + 119 * 4), +}; + +struct BK7011TRxV2A_TypeDef BK7011TRX = +{ + (BK7011_TRxV2A_REG0x0_TypeDef *)(&grc_reg_map[0]), + (BK7011_TRxV2A_REG0x1_TypeDef *)(&grc_reg_map[1]), + (BK7011_TRxV2A_REG0x2_TypeDef *)(&grc_reg_map[2]), + (BK7011_TRxV2A_REG0x3_TypeDef *)(&grc_reg_map[3]), + (BK7011_TRxV2A_REG0x4_TypeDef *)(&grc_reg_map[4]), + (BK7011_TRxV2A_REG0x5_TypeDef *)(&grc_reg_map[5]), + (BK7011_TRxV2A_REG0x6_TypeDef *)(&grc_reg_map[6]), + (BK7011_TRxV2A_REG0x7_TypeDef *)(&grc_reg_map[7]), + (BK7011_TRxV2A_REG0x8_TypeDef *)(&grc_reg_map[8]), + (BK7011_TRxV2A_REG0x9_TypeDef *)(&grc_reg_map[9]), + (BK7011_TRxV2A_REG0xA_TypeDef *)(&grc_reg_map[10]), + (BK7011_TRxV2A_REG0xB_TypeDef *)(&grc_reg_map[11]), + (BK7011_TRxV2A_REG0xC_TypeDef *)(&grc_reg_map[12]), + (BK7011_TRxV2A_REG0xD_TypeDef *)(&grc_reg_map[13]), + (BK7011_TRxV2A_REG0xE_TypeDef *)(&grc_reg_map[14]), + (BK7011_TRxV2A_REG0xF_TypeDef *)(&grc_reg_map[15]), + (BK7011_TRxV2A_REG0x10_TypeDef *)(&grc_reg_map[16]), + (BK7011_TRxV2A_REG0x11_TypeDef *)(&grc_reg_map[17]), + (BK7011_TRxV2A_REG0x12_TypeDef *)(&grc_reg_map[18]), + (BK7011_TRxV2A_REG0x13_TypeDef *)(&grc_reg_map[19]), + (BK7011_TRxV2A_REG0x14_TypeDef *)(&grc_reg_map[20]), + (BK7011_TRxV2A_REG0x15_TypeDef *)(&grc_reg_map[21]), + (BK7011_TRxV2A_REG0x16_TypeDef *)(&grc_reg_map[22]), + (BK7011_TRxV2A_REG0x17_TypeDef *)(&grc_reg_map[23]), + (BK7011_TRxV2A_REG0x18_TypeDef *)(&grc_reg_map[24]), + (BK7011_TRxV2A_REG0x19_TypeDef *)(&grc_reg_map[25]), + (BK7011_TRxV2A_REG0x1A_TypeDef *)(&grc_reg_map[26]), + (BK7011_TRxV2A_REG0x1B_TypeDef *)(&grc_reg_map[27]), + (BK7011_TRxV2A_REG0x1C_TypeDef *)(&grc_reg_map[28]), +}; + +struct BK7011TRxV2A_TypeDef BK7011TRXONLY = +{ + (volatile BK7011_TRxV2A_REG0x0_TypeDef *) (TRX_BEKEN_BASE + 0 * 4), + (volatile BK7011_TRxV2A_REG0x1_TypeDef *) (TRX_BEKEN_BASE + 1 * 4), + (volatile BK7011_TRxV2A_REG0x2_TypeDef *) (TRX_BEKEN_BASE + 2 * 4), + (volatile BK7011_TRxV2A_REG0x3_TypeDef *) (TRX_BEKEN_BASE + 3 * 4), + (volatile BK7011_TRxV2A_REG0x4_TypeDef *) (TRX_BEKEN_BASE + 4 * 4), + (volatile BK7011_TRxV2A_REG0x5_TypeDef *) (TRX_BEKEN_BASE + 5 * 4), + (volatile BK7011_TRxV2A_REG0x6_TypeDef *) (TRX_BEKEN_BASE + 6 * 4), + (volatile BK7011_TRxV2A_REG0x7_TypeDef *) (TRX_BEKEN_BASE + 7 * 4), + (volatile BK7011_TRxV2A_REG0x8_TypeDef *) (TRX_BEKEN_BASE + 8 * 4), + (volatile BK7011_TRxV2A_REG0x9_TypeDef *) (TRX_BEKEN_BASE + 9 * 4), + (volatile BK7011_TRxV2A_REG0xA_TypeDef *) (TRX_BEKEN_BASE + 10 * 4), + (volatile BK7011_TRxV2A_REG0xB_TypeDef *) (TRX_BEKEN_BASE + 11 * 4), + (volatile BK7011_TRxV2A_REG0xC_TypeDef *) (TRX_BEKEN_BASE + 12 * 4), + (volatile BK7011_TRxV2A_REG0xD_TypeDef *) (TRX_BEKEN_BASE + 13 * 4), + (volatile BK7011_TRxV2A_REG0xE_TypeDef *) (TRX_BEKEN_BASE + 14 * 4), + (volatile BK7011_TRxV2A_REG0xF_TypeDef *) (TRX_BEKEN_BASE + 15 * 4), + (volatile BK7011_TRxV2A_REG0x10_TypeDef *)(TRX_BEKEN_BASE + 16 * 4), + (volatile BK7011_TRxV2A_REG0x11_TypeDef *)(TRX_BEKEN_BASE + 17 * 4), + (volatile BK7011_TRxV2A_REG0x12_TypeDef *)(TRX_BEKEN_BASE + 18 * 4), + (volatile BK7011_TRxV2A_REG0x13_TypeDef *)(TRX_BEKEN_BASE + 19 * 4), + (volatile BK7011_TRxV2A_REG0x14_TypeDef *)(TRX_BEKEN_BASE + 20 * 4), + (volatile BK7011_TRxV2A_REG0x15_TypeDef *)(TRX_BEKEN_BASE + 21 * 4), + (volatile BK7011_TRxV2A_REG0x16_TypeDef *)(TRX_BEKEN_BASE + 22 * 4), + (volatile BK7011_TRxV2A_REG0x17_TypeDef *)(TRX_BEKEN_BASE + 23 * 4), + (volatile BK7011_TRxV2A_REG0x18_TypeDef *)(TRX_BEKEN_BASE + 24 * 4), + (volatile BK7011_TRxV2A_REG0x19_TypeDef *)(TRX_BEKEN_BASE + 25 * 4), + (volatile BK7011_TRxV2A_REG0x1A_TypeDef *)(TRX_BEKEN_BASE + 26 * 4), + (volatile BK7011_TRxV2A_REG0x1B_TypeDef *)(TRX_BEKEN_BASE + 27 * 4), + (volatile BK7011_TRxV2A_REG0x1C_TypeDef *)(TRX_BEKEN_BASE + 28 * 4), +}; + +struct temp_cal_pwr_st g_temp_pwr_current = {16, EVM_DEFUALT_RATE, 0, 0}; + +void delay05us(INT32 num) +{ + volatile INT32 i, j; + //REG_WRITE((0x0802800+(18*4)), 0x02); + + for(i = 0; i < num; i ++) + { + for(j = 0; j < 5; j ++) + ; + } + //REG_WRITE((0x0802800+(18*4)), 0x00); +} + +void delay100us(INT32 num) +{ + volatile INT32 i, j; + //REG_WRITE((0x0802800+(18*4)), 0x02); + + for(i = 0; i < num; i ++) + { + for(j = 0; j < 1050; j ++) + ; + } + //REG_WRITE((0x0802800+(18*4)), 0x00); +} + + +#define CAL_WR_TRXREGS(reg) do{\ + CHECK_OPERATE_RF_REG_IF_IN_SLEEP();\ + while(BK7011RCBEKEN.REG0x1->value & (0x1 << reg));\ + BK7011TRXONLY.REG##reg->value = BK7011TRX.REG##reg->value;\ + cal_delay(6);\ + while(BK7011RCBEKEN.REG0x1->value & (0x1 << reg));\ + CHECK_OPERATE_RF_REG_IF_IN_SLEEP_END();\ + }while(0) + + +void rwnx_cal_load_default_result(void) +{ + gtx_dcorMod = (bk7011_trx_val[11] >> 12) & 0xf; + gtx_dcorPA = (bk7011_trx_val[12] >> 12) & 0xf; + gtx_pre_gain = (bk7011_rc_val[21] >> 16) & 0x1f; + + gtx_i_dc_comp = (bk7011_rc_val[18] >> 16) & 0x3ff; + gtx_q_dc_comp = bk7011_rc_val[18] & 0x3ff; + + gtx_i_gain_comp = (bk7011_rc_val[19] >> 16) & 0x3ff; + gtx_q_gain_comp = bk7011_rc_val[19] & 0x3ff; + + gtx_ifilter_corner = (bk7011_trx_val[6] >> 10) & 0x3f; + gtx_qfilter_corner = (bk7011_trx_val[6] >> 4) & 0x3f; + gtx_phase_comp = (bk7011_rc_val[20] >> 16) & 0x3ff; + gtx_phase_ty2 = bk7011_rc_val[20] & 0x3ff; + + gtx_band = (bk7011_trx_val[3] >> 17) & 0x7f; + + g_rx_dc_gain_tab[0] = bk7011_trx_val[20]; + g_rx_dc_gain_tab[1] = bk7011_trx_val[21]; + g_rx_dc_gain_tab[2] = bk7011_trx_val[22]; + g_rx_dc_gain_tab[3] = bk7011_trx_val[23]; + g_rx_dc_gain_tab[4] = bk7011_trx_val[24]; + g_rx_dc_gain_tab[5] = bk7011_trx_val[25]; + g_rx_dc_gain_tab[6] = bk7011_trx_val[26]; + g_rx_dc_gain_tab[7] = bk7011_trx_val[27]; + + grx_amp_err_wr = (bk7011_rc_val[15] >> 16) & 0x3ff; + grx_phase_err_wr = bk7011_rc_val[15] & 0x3ff; + + //gstat_cal = (bk7011_rc_val[16] >> 29) & 0x1; +} +/* +void printf_trx_rc_value(void) +{ + int i; + printf("printf_trx_rc_value:\r\n"); + for (i=0; i<32; i++) + { + printf("bk7011_trx_val[%d] = 0x%x\r\n", i, bk7011_trx_val[i]); + } + for (i=0; i<32; i++) + { + printf("bk7011_rc_val[%d] = 0x%x\r\n", i, bk7011_rc_val[i]); + } + + printf("BK7011RCBEKEN.REG0x0->value = 0x%x\r\n", BK7011RCBEKEN.REG0x0->value); + printf("BK7011RCBEKEN.REG0x1->value = 0x%x\r\n", BK7011RCBEKEN.REG0x1->value); + printf("BK7011RCBEKEN.REG0x5->value = 0x%x\r\n", BK7011RCBEKEN.REG0x5->value); + printf("BK7011RCBEKEN.REG0x8->value = 0x%x\r\n", BK7011RCBEKEN.REG0x8->value); + printf("BK7011RCBEKEN.REG0xB->value = 0x%x\r\n", BK7011RCBEKEN.REG0xB->value); + printf("BK7011RCBEKEN.REG0xE->value = 0x%x\r\n", BK7011RCBEKEN.REG0xE->value); + printf("BK7011RCBEKEN.REG0x11->value = 0x%x\r\n", BK7011RCBEKEN.REG0x11->value); + printf("BK7011RCBEKEN.REG0x19->value = 0x%x\r\n", BK7011RCBEKEN.REG0x19->value); + printf("BK7011RCBEKEN.REG0x1C->value = 0x%x\r\n", BK7011RCBEKEN.REG0x1C->value); + printf("BK7011RCBEKEN.REG0x1E->value = 0x%x\r\n", BK7011RCBEKEN.REG0x1E->value); + printf("BK7011RCBEKEN.REG0x3C->value = 0x%x\r\n", BK7011RCBEKEN.REG0x3C->value); + printf("BK7011RCBEKEN.REG0x3E->value = 0x%x\r\n", BK7011RCBEKEN.REG0x3E->value); + printf("BK7011RCBEKEN.REG0x3F->value = 0x%x\r\n", BK7011RCBEKEN.REG0x3F->value); + printf("BK7011RCBEKEN.REG0x40->value = 0x%x\r\n", BK7011RCBEKEN.REG0x40->value); + printf("BK7011RCBEKEN.REG0x41->value = 0x%x\r\n", BK7011RCBEKEN.REG0x41->value); + printf("BK7011RCBEKEN.REG0x42->value = 0x%x\r\n", BK7011RCBEKEN.REG0x42->value); + printf("BK7011RCBEKEN.REG0x4C->value = 0x%x\r\n", BK7011RCBEKEN.REG0x4C->value); + printf("BK7011RCBEKEN.REG0x4D->value = 0x%x\r\n", BK7011RCBEKEN.REG0x4D->value); + printf("BK7011RCBEKEN.REG0x4F->value = 0x%x\r\n", BK7011RCBEKEN.REG0x4F->value); + printf("BK7011RCBEKEN.REG0x50->value = 0x%x\r\n", BK7011RCBEKEN.REG0x50->value); + printf("BK7011RCBEKEN.REG0x51->value = 0x%x\r\n", BK7011RCBEKEN.REG0x51->value); + printf("BK7011RCBEKEN.REG0x52->value = 0x%x\r\n", BK7011RCBEKEN.REG0x52->value); + printf("BK7011RCBEKEN.REG0x54->value = 0x%x\r\n", BK7011RCBEKEN.REG0x54->value); + printf("BK7011RCBEKEN.REG0x55->value = 0x%x\r\n", BK7011RCBEKEN.REG0x55->value); + printf("BK7011RCBEKEN.REG0x5C->value = 0x%x\r\n", BK7011RCBEKEN.REG0x5C->value); + + printf("BK7011TRXONLY.REG0x0->value = 0x%x\r\n", BK7011TRXONLY.REG0x0->value); + printf("BK7011TRXONLY.REG0x1->value = 0x%x\r\n", BK7011TRXONLY.REG0x1->value); + printf("BK7011TRXONLY.REG0x2->value = 0x%x\r\n", BK7011TRXONLY.REG0x2->value); + printf("BK7011TRXONLY.REG0x3->value = 0x%x\r\n", BK7011TRXONLY.REG0x3->value); + printf("BK7011TRXONLY.REG0x4->value = 0x%x\r\n", BK7011TRXONLY.REG0x4->value); + printf("BK7011TRXONLY.REG0x5->value = 0x%x\r\n", BK7011TRXONLY.REG0x5->value); + printf("BK7011TRXONLY.REG0x6->value = 0x%x\r\n", BK7011TRXONLY.REG0x6->value); + printf("BK7011TRXONLY.REG0x7->value = 0x%x\r\n", BK7011TRXONLY.REG0x7->value); + printf("BK7011TRXONLY.REG0x8->value = 0x%x\r\n", BK7011TRXONLY.REG0x8->value); + printf("BK7011TRXONLY.REG0x9->value = 0x%x\r\n", BK7011TRXONLY.REG0x9->value); + printf("BK7011TRXONLY.REG0xA->value = 0x%x\r\n", BK7011TRXONLY.REG0xA->value); + printf("BK7011TRXONLY.REG0xB->value = 0x%x\r\n", BK7011TRXONLY.REG0xB->value); + printf("BK7011TRXONLY.REG0xC->value = 0x%x\r\n", BK7011TRXONLY.REG0xC->value); + printf("BK7011TRXONLY.REG0xD->value = 0x%x\r\n", BK7011TRXONLY.REG0xD->value); + printf("BK7011TRXONLY.REG0xE->value = 0x%x\r\n", BK7011TRXONLY.REG0xE->value); + printf("BK7011TRXONLY.REG0xF->value = 0x%x\r\n", BK7011TRXONLY.REG0xF->value); + printf("BK7011TRXONLY.REG0x10->value = 0x%x\r\n", BK7011TRXONLY.REG0x10->value); + printf("BK7011TRXONLY.REG0x11->value = 0x%x\r\n", BK7011TRXONLY.REG0x11->value); + printf("BK7011TRXONLY.REG0x12->value = 0x%x\r\n", BK7011TRXONLY.REG0x12->value); + printf("BK7011TRXONLY.REG0x13->value = 0x%x\r\n", BK7011TRXONLY.REG0x13->value); + printf("BK7011TRXONLY.REG0x14->value = 0x%x\r\n", BK7011TRXONLY.REG0x14->value); + printf("BK7011TRXONLY.REG0x15->value = 0x%x\r\n", BK7011TRXONLY.REG0x15->value); + printf("BK7011TRXONLY.REG0x16->value = 0x%x\r\n", BK7011TRXONLY.REG0x16->value); + printf("BK7011TRXONLY.REG0x17->value = 0x%x\r\n", BK7011TRXONLY.REG0x17->value); + printf("BK7011TRXONLY.REG0x18->value = 0x%x\r\n", BK7011TRXONLY.REG0x18->value); + printf("BK7011TRXONLY.REG0x19->value = 0x%x\r\n", BK7011TRXONLY.REG0x19->value); + printf("BK7011TRXONLY.REG0x1A->value = 0x%x\r\n", BK7011TRXONLY.REG0x1A->value); + printf("BK7011TRXONLY.REG0x1B->value = 0x%x\r\n", BK7011TRXONLY.REG0x1B->value); +} +*/ +#ifdef CALIBRATE_TIMES +void calibration_result_print(void) +{ + int i, j; + int max, min; + + + os_printf("gtx_dcorMod_temp: 0x%x\r\n", gtx_dcorMod_temp); + os_printf("gtx_dcorPA_temp: 0x%x\r\n", gtx_dcorPA_temp); + os_printf("gtx_pre_gain_temp: 0x%x\r\n", gtx_pre_gain_temp); + + os_printf("gtx_dcorMod_temp_loopback: 0x%x\r\n", gtx_dcorMod_temp_loopback); + os_printf("gtx_dcorPA_temp_loopback: 0x%x\r\n", gtx_dcorPA_temp_loopback); + os_printf("gtx_pre_gain_temp_loopback: 0x%x\r\n", gtx_pre_gain_temp_loopback); + + max = -1100, min = 1100; +// printf("\r\ngbias_after_cal[] = \r\n"); + for (i=0; i p_gbias_after_cal_array[i]) + { + min = p_gbias_after_cal_array[i]; + } +// printf("%d\r\n", p_gbias_after_cal_array[i]); + } + printf("gbias_after_cal: min = %d, max = %d, max-min = %d\r\n", min, max, max-min); + + max = -1100, min = 1100; +// printf("\r\ngav_tssi[] = \r\n"); + for (i=0; i p_gav_tssi_array[i]) + { + min = p_gav_tssi_array[i]; + } +// printf("%d\r\n", p_gav_tssi_array[i]); + } + printf("gav_tssi: min = %d, max = %d, max-min = %d\r\n", min, max, max-min); + + printf("\r\n"); + + max = -1100, min = 1100; +// printf("\r\ngtx_ifilter_corner[] = \r\n"); + for (i=0; i p_gtx_ifilter_corner_array[i]) + { + min = p_gtx_ifilter_corner_array[i]; + } +#ifdef SCAN_IQ_FILTER_CORNER + printf("0x%x\t%d\t%d\t%d\r\n", p_g_sctrl_bias_reg_array[i], p_gtx_ifilter_corner_array[i], + p_grx_avg_i_14M_array[i], p_grx_avg_i_14M_array2[i]); + for (j=0; j<5; j++) + { + printf(" %d\t%f\r\n", index_test[i*5+j], float2_test[i*5+j]); + } +#endif + } + printf("gtx_ifilter_corner: min = %d, max = %d, max-min = %d\r\n", min, max, max-min); + + max = -1100, min = 1100; +// printf("\r\ngtx_qfilter_corner[] = \r\n"); + for (i=0; i p_gtx_qfilter_corner_array[i]) + { + min = p_gtx_qfilter_corner_array[i]; + } +#ifdef SCAN_IQ_FILTER_CORNER + printf("%d\t%d\t%d\r\n", p_gtx_qfilter_corner_array[i], p_grx_avg_q_14M_array[i], p_grx_avg_q_14M_array2[i]); +#endif + } + printf("gtx_qfilter_corner: min = %d, max = %d, max-min = %d\r\n", min, max, max-min); + + if (1) + { + int p_gtx_filter_corner[CALIBRATE_TIMES]; + for (i=0; i p_gtx_filter_corner[i]) + { + min = p_gtx_filter_corner[i]; + } + } + printf("p_gtx_filter_corner: min = %d, max = %d, max-min = %d\r\n", min, max, max-min); + } + + printf("\r\n"); + + max = -1100, min = 1100; +// printf("\r\ntx_i_dc_comp[] = \r\n"); + for (i=0; i p_gtx_i_dc_comp_array[i]) + { + min = p_gtx_i_dc_comp_array[i]; + } +// printf("%d\r\n", p_gtx_i_dc_comp_array[i]); + } + printf("tx_i_dc_comp: min = %d, max = %d, max-min = %d\r\n", min, max, max-min); + + max = -1100, min = 1100; +// printf("\r\ntx_q_dc_comp[] = \r\n"); + for (i=0; i p_gtx_q_dc_comp_array[i]) + { + min = p_gtx_q_dc_comp_array[i]; + } +// printf("%d\r\n", p_gtx_q_dc_comp_array[i]); + } + printf("tx_q_dc_comp: min = %d, max = %d, max-min = %d\r\n", min, max, max-min); + + max = -1100, min = 1100; +// printf("\r\ntx_i_gain_comp[] = \r\n"); + for (i=0; i p_gtx_i_gain_comp_array[i]) + { + min = p_gtx_i_gain_comp_array[i]; + } +// printf("%d\r\n", p_gtx_i_gain_comp_array[i]); + } + printf("tx_i_gain_comp: min = %d, max = %d, max-min = %d\r\n", min, max, max-min); + + max = -1100, min = 1100; +// printf("\r\ntx_q_gain_comp[] = \r\n"); + for (i=0; i p_gtx_q_gain_comp_array[i]) + { + min = p_gtx_q_gain_comp_array[i]; + } +// printf("%d\r\n", p_gtx_q_gain_comp_array[i]); + } + printf("tx_q_gain_comp: min = %d, max = %d, max-min = %d\r\n", min, max, max-min); + + max = -1100, min = 1100; +// printf("\r\ntx_phase_comp[] = \r\n"); + for (i=0; i p_gtx_phase_comp_array[i]) + { + min = p_gtx_phase_comp_array[i]; + } +// printf("%d\r\n", p_gtx_phase_comp_array[i]); + } + printf("tx_phase_comp: min = %d, max = %d, max-min = %d\r\n", min, max, max-min); + + printf("\r\n"); + + max = -1100, min = 1100; +// printf("\r\ntx_i_dc_comp_temp[] = \r\n"); + for (i=0; i p_gtx_i_dc_comp_temp_array[i]) + { + min = p_gtx_i_dc_comp_temp_array[i]; + } +// printf("%d\r\n", p_gtx_i_dc_comp_temp_array[i]); + } + printf("tx_i_dc_comp_temp: min = %d, max = %d, max-min = %d\r\n", min, max, max-min); + + max = -1100, min = 1100; +// printf("\r\ntx_q_dc_comp_temp[] = \r\n"); + for (i=0; i p_gtx_q_dc_comp_temp_array[i]) + { + min = p_gtx_q_dc_comp_temp_array[i]; + } +// printf("%d\r\n", p_gtx_q_dc_comp_temp_array[i]); + } + printf("tx_q_dc_comp_temp: min = %d, max = %d, max-min = %d\r\n", min, max, max-min); + + + max = -1100, min = 1100; +// printf("\r\ntx_i_gain_comp_temp[] = \r\n"); + for (i=0; i p_gtx_i_gain_comp_temp_array[i]) + { + min = p_gtx_i_gain_comp_temp_array[i]; + } +// printf("%d\r\n", p_gtx_i_gain_comp_temp_array[i]); + } + printf("tx_i_gain_comp_temp: min = %d, max = %d, max-min = %d\r\n", min, max, max-min); + + max = -1100, min = 1100; +// printf("\r\ntx_q_gain_comp_temp[] = \r\n"); + for (i=0; i p_gtx_q_gain_comp_temp_array[i]) + { + min = p_gtx_q_gain_comp_temp_array[i]; + } +// printf("%d\r\n", p_gtx_q_gain_comp_temp_array[i]); + } + printf("tx_q_gain_comp_temp: min = %d, max = %d, max-min = %d\r\n", min, max, max-min); + + max = -1100, min = 1100; +// printf("\r\ntx_phase_comp_temp[] = \r\n"); + for (i=0; i p_gtx_phase_comp_temp_array[i]) + { + min = p_gtx_phase_comp_temp_array[i]; + } +// printf("%d\r\n", p_gtx_phase_comp_temp_array[i]); + } + printf("tx_phase_comp_temp: min = %d, max = %d, max-min = %d\r\n", min, max, max-min); + + printf("\r\n"); + + max = -1100, min = 1100; +// printf("\r\nrx_amp_err_rd[] = \r\n"); + for (i=0; i p_rx_amp_err_rd_array[i]) + { + min = p_rx_amp_err_rd_array[i]; + } +// printf("%d\r\n", p_rx_amp_err_rd_array[i]); + } + printf("rx_amp_err_rd: min = %d, max = %d, max-min = %d\r\n", min, max, max-min); + + max = -1100, min = 1100; +// printf("\r\nrx_phase_err_rd[] = \r\n"); + for (i=0; i p_rx_phase_err_rd_array[i]) + { + min = p_rx_phase_err_rd_array[i]; + } +// printf("%d\r\n", p_rx_phase_err_rd_array[i]); + } + printf("rx_phase_err_rd: min = %d, max = %d, max-min = %d\r\n", min, max, max-min); + + max = -1100, min = 1100; +// printf("\r\nrx_ty2_rd[] = \r\n"); + for (i=0; i p_rx_ty2_rd_array[i]) + { + min = p_rx_ty2_rd_array[i]; + } +// printf("%d\r\n", p_rx_ty2_rd_array[i]); + } + printf("rx_ty2_rd: min = %d, max = %d, max-min = %d\r\n", min, max, max-min); + + for (j = 0; j < 8; j++) + { + int iTemp; + os_printf("\r\n"); + + max = -1100, min = 1100; + for (i = 0; i < calibrate_time; i++) + { + iTemp = p_g_rx_dc_gain_tab_array[j * CALIBRATE_TIMES + i]; + if (max < (iTemp & 0x00FF)) + { + max = iTemp & 0x00FF; + } + if (min > (iTemp & 0x00FF)) + { + min = iTemp & 0x00FF; + } + } + os_printf("g_rx_dc_gain_tab[%d].i_%ddb: min = %d, max = %d, max-min = %d\r\n", j, j * 6, min, max, max - min); + + max = -1100, min = 1100; + for (i = 0; i < calibrate_time; i++) + { + iTemp = p_g_rx_dc_gain_tab_array[j * CALIBRATE_TIMES + i] >> 8; + if (max < (iTemp & 0x00FF)) + { + max = iTemp & 0x00FF; + } + if (min > (iTemp & 0x00FF)) + { + min = iTemp & 0x00FF; + } + } + printf("g_rx_dc_gain_tab[%d].q_%ddb: min = %d, max = %d, max-min = %d\r\n", j, j * 6, min, max, max - min); + + max = -1100, min = 1100; + for (i = 0; i < calibrate_time; i++) + { + iTemp = p_g_rx_dc_gain_tab_array[j * CALIBRATE_TIMES + i] >> 16; + if (max < (iTemp & 0x00FF)) + { + max = iTemp & 0x00FF; + } + if (min > (iTemp & 0x00FF)) + { + min = iTemp & 0x00FF; + } + } + printf("g_rx_dc_gain_tab[%d].i_%ddb: min = %d, max = %d, max-min = %d\r\n", j, j * 6 + 3, min, max, max - min); + + max = -1100, min = 1100; + for (i = 0; i < calibrate_time; i++) + { + iTemp = p_g_rx_dc_gain_tab_array[j * CALIBRATE_TIMES + i] >> 24; + if (max < (iTemp & 0x00FF)) + { + max = iTemp & 0x00FF; + } + if (min > (iTemp & 0x00FF)) + { + min = iTemp & 0x00FF; + } + } + printf("g_rx_dc_gain_tab[%d].q_%ddb: min = %d, max = %d, max-min = %d\r\n", j, j * 6 + 3, min, max, max - min); + } +} + +void calibration_auto_test(unsigned long ul_calibrate_times) +{ + int i; + int gbias_after_cal_array[CALIBRATE_TIMES]; + int gav_tssi_array[CALIBRATE_TIMES]; + int rx_amp_err_rd_array[CALIBRATE_TIMES]; + int rx_phase_err_rd_array[CALIBRATE_TIMES]; + int rx_ty2_rd_array[CALIBRATE_TIMES]; + int gtx_ifilter_corner_array[CALIBRATE_TIMES]; + int gtx_qfilter_corner_array[CALIBRATE_TIMES]; +#ifdef SCAN_IQ_FILTER_CORNER + UINT32 sctrl_bias_reg_array[CALIBRATE_TIMES]; + int rx_avg_i_14M_array[CALIBRATE_TIMES]; + int rx_avg_i_14M_array2[CALIBRATE_TIMES]; + int rx_avg_q_14M_array[CALIBRATE_TIMES]; + int rx_avg_q_14M_array2[CALIBRATE_TIMES]; +#endif + + int gtx_i_dc_comp_array[CALIBRATE_TIMES]; + int gtx_q_dc_comp_array[CALIBRATE_TIMES]; + int gtx_i_gain_comp_array[CALIBRATE_TIMES]; + int gtx_q_gain_comp_array[CALIBRATE_TIMES]; + int gtx_phase_comp_array[CALIBRATE_TIMES]; + + int gtx_i_dc_comp_temp_array[CALIBRATE_TIMES]; + int gtx_q_dc_comp_temp_array[CALIBRATE_TIMES]; + int gtx_i_gain_comp_temp_array[CALIBRATE_TIMES]; + int gtx_q_gain_comp_temp_array[CALIBRATE_TIMES]; + int gtx_phase_comp_temp_array[CALIBRATE_TIMES]; + + int g_rx_dc_gain_tab_array[8][CALIBRATE_TIMES]; + + if (ul_calibrate_times == 0) + { + calibrate_times_all = CALIBRATE_TIMES; + } + else + { + calibrate_times_all = ul_calibrate_times; + } + + p_gbias_after_cal_array = gbias_after_cal_array; + p_gav_tssi_array = gav_tssi_array; + p_rx_amp_err_rd_array = rx_amp_err_rd_array; + p_rx_ty2_rd_array = rx_ty2_rd_array; + p_rx_phase_err_rd_array = rx_phase_err_rd_array; + p_gtx_ifilter_corner_array = gtx_ifilter_corner_array; + p_gtx_qfilter_corner_array = gtx_qfilter_corner_array; +#ifdef SCAN_IQ_FILTER_CORNER + p_g_sctrl_bias_reg_array = sctrl_bias_reg_array; + p_grx_avg_i_14M_array = rx_avg_i_14M_array; + p_grx_avg_i_14M_array2 = rx_avg_i_14M_array2; + p_grx_avg_q_14M_array = rx_avg_q_14M_array; + p_grx_avg_q_14M_array2 = rx_avg_q_14M_array2; +#endif + p_gtx_i_dc_comp_array = gtx_i_dc_comp_array; + p_gtx_q_dc_comp_array = gtx_q_dc_comp_array; + p_gtx_i_gain_comp_array = gtx_i_gain_comp_array; + p_gtx_q_gain_comp_array = gtx_q_gain_comp_array; + p_gtx_phase_comp_array = gtx_phase_comp_array; + p_gtx_i_dc_comp_temp_array = gtx_i_dc_comp_temp_array; + p_gtx_q_dc_comp_temp_array = gtx_q_dc_comp_temp_array; + p_gtx_i_gain_comp_temp_array = gtx_i_gain_comp_temp_array; + p_gtx_q_gain_comp_temp_array = gtx_q_gain_comp_temp_array; + p_gtx_phase_comp_temp_array = gtx_phase_comp_temp_array; + p_g_rx_dc_gain_tab_array = &(g_rx_dc_gain_tab_array[0][0]); + +/* +gi_gain_tx_pa_dgainPA30 = 2; +gi_gain_tx_pa_dgainbuf30 = 4; +for (gi_dc_tx_pa_dgainPA30=1; gi_dc_tx_pa_dgainPA30<=5; gi_dc_tx_pa_dgainPA30++) +{ +for (gi_dc_tx_pa_dgainbuf30=4; gi_dc_tx_pa_dgainbuf30<=6; gi_dc_tx_pa_dgainbuf30++) +{ + calibrate_time = 0; + os_printf("\r\n\r\n***********************************************************************\r\n" + "calibration_auto_test: \r\n"); + os_printf("gi_dc_tx_pa_dgainPA30 = %d\r\n", gi_dc_tx_pa_dgainPA30); + os_printf("gi_dc_tx_pa_dgainbuf30 = %d\r\n", gi_dc_tx_pa_dgainbuf30); + os_printf("gi_gain_tx_pa_dgainPA30 = %d\r\n", gi_gain_tx_pa_dgainPA30); + os_printf("gi_gain_tx_pa_dgainbuf30 = %d\r\n\r\n", gi_gain_tx_pa_dgainbuf30); + for (i=0; ibits.lpfcapcalq50 = lpfcap_q; + BK7011TRX.REG0x6->bits.lpfcapcali50 = lpfcap_i; + CAL_WR_TRXREGS(0x6); + bk7011_trx_val[6] = BK7011TRX.REG0x6->value; +} + +void rwnx_cal_enable_lpfcap_iq_from_digit(UINT32 enable) +{ + if(enable) + BK7011TRX.REG0x6->bits.capcal_sel = 1; + else + BK7011TRX.REG0x6->bits.capcal_sel = 0; + + CAL_WR_TRXREGS(0x6); + bk7011_trx_val[6] = BK7011TRX.REG0x6->value; +} + +#if CFG_SUPPORT_MANUAL_CALI +static UINT32 rwnx_cal_translate_tx_rate(UINT32 rate) +{ + UINT32 param; + + switch(rate) + { + case 0 : + param = 1; + break; // 1Mbps + case 1 : + param = 2; + break; // 2Mbps + case 2 : + param = 5; + break; // 5.5Mbps + case 3: + param = 11; + break; // 11Mbps + case 4: + param = 6; + break; // 6Mbps + case 5 : + param = 9; + break; // 9Mbps + case 6: + param = 12; + break; // 12Mbps + case 7: + param = 18; + break; // 18Mbps + case 8: + param = 24; + break; // 24Mbps + case 9: + param = 36; + break; // 36Mbps + case 10: + param = 48; + break; // 48Mbps + case 11: + param = 54; + break; // 54Mbps + default: + param = rate; + break; // 54Mbps + } + + return param; +} + +static UINT32 rwnx_cal_translate_tx_rate_for_n(UINT32 rate, UINT32 bandwidth) +{ + UINT32 param; + + switch(rate) + { + case 128 : + case 129 : + case 130 : + case 131 : + case 132 : + case 133 : + param = rate - 123; + break; // MCS0-5 the same rate indx as 9M to 36M + + case 134: + case 135: + if(bandwidth == PHY_CHNL_BW_20) + param = 11; // MCS6-7the same rate indx as to 54M - band:20M + else + param = 12; // MCS6-7the same rate indx as to 135M - band:40M + break; + + default: + param = rate; + break; + } + + return param; +} +#endif + +//static INT32 cur_rate; +void rwnx_cal_set_txpwr_by_rate(INT32 rate, UINT32 test_mode) +{ +#if CFG_SUPPORT_MANUAL_CALI + UINT32 ret; + UINT32 pwr_gain; + + struct phy_channel_info info; + UINT32 channel, bandwidth; // PHY_CHNL_BW_20, PHY_CHNL_BW_40: + + phy_get_channel(&info, 0); + bandwidth = (info.info1 >> 8) & 0xff; + + channel = (((info.info2 & 0xffff) - 2400) - 7)/5; + if(channel > 14) + channel = 14; + if(!manual_cal_get_txpwr(rwnx_cal_translate_tx_rate(rate), + channel, bandwidth, &pwr_gain)) + { + // unable get txpwr from manual cal + return; + } + + manual_cal_get_dbm_by_rate(rate, bandwidth); + + if(test_mode == 0) + { + ret = manual_cal_get_pwr_idx_shift(rate, bandwidth, &pwr_gain); + } + else + { + ret = 2; + if((bandwidth == PHY_CHNL_BW_20) && (rate <= 3)) + { + ret = 1; + } + } + + if(!ret ){ + // unable get txpwr from manual cal + return; + } else if(ret == 1) { + rwnx_cal_set_txpwr(pwr_gain, EVM_DEFUALT_B_RATE); + } else if(ret == 2) { + rwnx_cal_set_txpwr(pwr_gain, EVM_DEFUALT_RATE); + } + + //if(rate <= 3) + if((rate <= 4) || (rate == 128)) + { + // just for 11b + //BK7011TRX.REG0x6->bits.lpfcapcalq50 = 0x3f; + //BK7011TRX.REG0x6->bits.lpfcapcali50 = 0x3f; + //CAL_WR_TRXREGS(0x6); + BK7011RCBEKEN.REG0x5A->bits.TXCALCAPI = 0x3f; + BK7011RCBEKEN.REG0x5B->bits.TXCALCAPQ = 0x3f; + } + else + { + BK7011RCBEKEN.REG0x5A->bits.TXCALCAPI = gtx_ifilter_corner; + BK7011RCBEKEN.REG0x5B->bits.TXCALCAPQ = gtx_qfilter_corner; + //BK7011TRX.REG0x6->value = bk7011_trx_val[6]; + //CAL_WR_TRXREGS(0x6); + } + +#endif +} + +void rwnx_cal_set_txpwr_by_channel(UINT32 channel) +{ + UINT32 pwr_gain, rate; + + rate = EVM_DEFUALT_BLE_RATE; + + if(!manual_cal_get_txpwr(rate, channel, 0, &pwr_gain)) + { + // unable get txpwr from manual cal + return; + } + + if(get_ate_mode_state()) + { +#ifdef ATE_PRINT_DEBUG + os_printf("set pwr:%d - c:%d\r\n", pwr_gain, channel); +#else + os_printf("c:%d\r\n", channel); +#endif + } + + CHECK_OPERATE_RF_REG_IF_IN_SLEEP(); + rwnx_cal_set_txpwr_ble(pwr_gain); + CHECK_OPERATE_RF_REG_IF_IN_SLEEP_END(); +} + +extern void tpc_init(void); +extern void tpc_deinit(void); +struct temp_cal_pwr_st g_temp_pwr_current_tpc = {0, EVM_DEFUALT_RATE, 0, 0}; +void rwnx_set_tpc_txpwr_by_tmpdetect(INT16 shift_b, INT16 shift_g) +{ + g_temp_pwr_current_tpc.shift_g = shift_g; + g_temp_pwr_current_tpc.shift = shift_b; + + if(ble_in_dut_mode() == 0) + { + os_printf("td set tpc pwr: shift_b:%d, shift_g:%d\r\n", + shift_b, shift_g); + } +} + +UINT32 rwnx_tpc_pwr_idx_translate(UINT32 pwr_gain, UINT32 rate, UINT32 print_log) +{ + const UINT8 *idx_tab; + INT16 idx = TCP_PAMAP_TAB_LEN - 1; + INT16 shift; + + if(rate == EVM_DEFUALT_B_RATE) { + // for b + idx_tab = b_map; + shift = g_temp_pwr_current_tpc.shift; + } else if(rate == EVM_DEFUALT_RATE) { + // for g + idx_tab = gn_map; + shift = g_temp_pwr_current_tpc.shift_g; + } else { + os_printf("no support :%d\r\n", rate); + return idx; + } + +#if CFG_USE_TEMPERATURE_DETECT + idx = pwr_gain + shift; + + if(idx > 32) { + idx = 32; + }else if (idx < 0) + idx = 0; + + g_temp_pwr_current_tpc.idx = idx; +#endif + + idx = idx_tab[idx]; + + if(idx > 16) { + idx = 16; + } + + if (print_log) + { + os_printf("translate idx1:%d, td_shift:%d, b/g:%d --- idx2:%d\r\n", pwr_gain, + shift, rate, idx); + + } + + return idx; + +} + +UINT32 rwnx_tpc_get_pwridx_by_rate(UINT32 rate, UINT32 print_log) +{ + UINT32 ret, ret_bak; + UINT32 pwr_gain; + + struct phy_channel_info info; + UINT32 channel, bandwidth; // PHY_CHNL_BW_20, PHY_CHNL_BW_40: + + phy_get_channel(&info, 0); + bandwidth = (info.info1 >> 8) & 0xff; + if(rate <= 128) + bandwidth = 0; + + channel = (((info.info2 & 0xffff) - 2400) - 7)/5; + + if(channel > 14) + channel = 14; + + if(manual_cal_get_txpwr(rwnx_cal_translate_tx_rate(rate), + channel, bandwidth, &pwr_gain) == 0) + { + os_printf("unable get txpwr %d, %d, %d\r\n", rate, channel, bandwidth); + return 0; + } + + ret_bak = ret = manual_cal_get_pwr_idx_shift(rate, bandwidth, &pwr_gain); + + if(!ret ){ + os_printf("unable get txpwr shift %d, %d, %d\r\n", rate, channel, bandwidth); + return 0; + } else if(ret == 1) { + ret = rwnx_tpc_pwr_idx_translate(pwr_gain, EVM_DEFUALT_B_RATE, 0); + } else if(ret == 2) { + ret = rwnx_tpc_pwr_idx_translate(pwr_gain, EVM_DEFUALT_RATE, 0); + } + + if (print_log) + { + INT16 shift = g_temp_pwr_current.shift; + if(ret_bak == 2) { + shift = g_temp_pwr_current.shift_g; + } + + os_printf("tpc info- r:%d, c:%d, b:%d -- idx1:%d+(%d), idx2: %d\r\n", + rate, channel, bandwidth, pwr_gain, shift, ret); + + const PWR_REGS_TPC *ptr = &cfg_tab_tpc[ret]; + os_printf("b[31-28]:0x%02x, c[3-0]:0x%02x, c[7-4]:0x%02x, c[11-8]:0x%02x\r\n", + ptr->regb_28_31, ptr->regc_0_3, ptr->regc_4_7, ptr->regc_8_11); + } + + return ret; + +} + +void rwnx_use_tpc_set_pwr(void) +{ + #if CFG_SUPPORT_TPC_PA_MAP + tpc_init(); + + BK7011RCBEKEN.REG0x52->bits.TXPREGAIN = gtx_pre_gain = TCP_PAMAP_DEF_PREGAIN; + bk7011_rc_val[21] = BK7011RCBEKEN.REG0x52->value; + + BK7011TRX.REG0xA->bits.dbpab30 = TCP_PAMAP_DEF_A7_4; + BK7011TRX.REG0xA->bits.dbpaa30 = TCP_PAMAP_DEF_A13_8; + BK7011TRX.REG0xA->bits.disrefPA10 = TCP_PAMAP_DEF_A1_0; + BK7011TRX.REG0xA->bits.pamapen = 1; + CAL_WR_TRXREGS(0xA); + bk7011_trx_val[10] = BK7011TRXONLY.REG0xA->value; + + is_tpc_used = 1; + #endif +} + +void rwnx_no_use_tpc_set_pwr(void) +{ + tpc_deinit(); + + BK7011TRX.REG0xA->bits.pamapen = 0; + CAL_WR_TRXREGS(0xA); + bk7011_trx_val[10] = BK7011TRXONLY.REG0xA->value; +} + +UINT32 rwnx_is_tpc_bit_on(void) +{ + return (BK7011TRX.REG0xA->bits.pamapen == 1)? 1: 0; +} + +UINT32 rwnx_sys_is_enable_hw_tpc(void) +{ + return (is_tpc_used == 1)? 1: 0; +} + +void rwnx_tpc_pa_map_init(void) +{ + BK7011RCBEKEN.REG0x70->bits.palevel0map = cfg_tab_tpc[0].value; + BK7011RCBEKEN.REG0x70->bits.palevel1map = cfg_tab_tpc[1].value; + bk7011_rc_val[29] = BK7011RCBEKEN.REG0x70->value; + + BK7011RCBEKEN.REG0x71->bits.palevel2map = cfg_tab_tpc[2].value; + BK7011RCBEKEN.REG0x71->bits.palevel3map = cfg_tab_tpc[3].value; + bk7011_rc_val[30] = BK7011RCBEKEN.REG0x71->value; + + BK7011RCBEKEN.REG0x72->bits.palevel4map = cfg_tab_tpc[4].value; + BK7011RCBEKEN.REG0x72->bits.palevel5map = cfg_tab_tpc[5].value; + bk7011_rc_val[31] = BK7011RCBEKEN.REG0x72->value; + + BK7011RCBEKEN.REG0x73->bits.palevel6map = cfg_tab_tpc[6].value; + BK7011RCBEKEN.REG0x73->bits.palevel7map = cfg_tab_tpc[7].value; + bk7011_rc_val[32] = BK7011RCBEKEN.REG0x73->value; + + BK7011RCBEKEN.REG0x74->bits.palevel8map = cfg_tab_tpc[8].value; + BK7011RCBEKEN.REG0x74->bits.palevel9map = cfg_tab_tpc[9].value; + bk7011_rc_val[33] = BK7011RCBEKEN.REG0x74->value; + + BK7011RCBEKEN.REG0x75->bits.palevel10map = cfg_tab_tpc[10].value; + BK7011RCBEKEN.REG0x75->bits.palevel11map = cfg_tab_tpc[11].value; + bk7011_rc_val[34] = BK7011RCBEKEN.REG0x75->value; + + BK7011RCBEKEN.REG0x76->bits.palevel12map = cfg_tab_tpc[12].value; + BK7011RCBEKEN.REG0x76->bits.palevel13map = cfg_tab_tpc[13].value; + bk7011_rc_val[35] = BK7011RCBEKEN.REG0x76->value; + + BK7011RCBEKEN.REG0x77->bits.palevel4map = cfg_tab_tpc[14].value; + BK7011RCBEKEN.REG0x77->bits.palevel5map = cfg_tab_tpc[15].value; + bk7011_rc_val[36] = BK7011RCBEKEN.REG0x77->value; + + rwnx_use_tpc_set_pwr(); + + os_printf("rwnx_tpc_pa_map_init\r\n"); +} + +void rwnx_cal_initial_calibration(void) +{ + rwnx_cal_set_txpwr(12, EVM_DEFUALT_RATE); + + rwnx_tpc_pa_map_init(); +} + +void rwnx_cal_set_reg_adda_ldo(UINT32 val) +{ +// os_printf("set_reg_adda_ldo:%d \r\n", val); + + val = val & 0x3; + + BK7011TRX.REG0x12->bits.ldoadda = val; + CAL_WR_TRXREGS(0x12); +} + +void rwnx_cal_en_extra_txpa(void) +{ + BK7011TRX.REG0x10->value = BK7011TRXONLY.REG0xD->value; + BK7011TRX.REG0x10->bits.entxfebias = 0; + CAL_WR_TRXREGS(0x10); +} + +void rwnx_cal_dis_extra_txpa(void) +{ + BK7011TRX.REG0x10->value = bk7011_trx_val[16]; + CAL_WR_TRXREGS(0x10); +} + +void rwnx_cal_set_reg_rx_ldo(void) +{ +// os_printf("set_reg_adda_ldo:%d \r\n", val); + + BK7011TRX.REG0x9->bits.vsrxlnaldo10 = 0x3; + CAL_WR_TRXREGS(0x9); + + //BK7011TRX.REG0x5->bits.cp_ldo = 0x0; + //BK7011TRX.REG0x5->bits.pll_ldo = 0x0; + //BK7011TRX.REG0x5->bits.vco_ldo = 0x0; + //CAL_WR_TRXREGS(0x5); +} + +void rwnx_cal_set_40M_extra_setting(UINT8 val) +{ + if (1==val) + { + BK7011TRX.REG0xF->bits.clkadc_sel = 1; + CAL_WR_TRXREGS(0xF); + } + else + { + BK7011TRX.REG0xF->bits.clkadc_sel = 0; + CAL_WR_TRXREGS(0xF); + } +} + +void rwnx_cal_set_40M_setting(void) +{ + BK7011TRX.REG0x12->bits.adcrefbwsel = 1; + BK7011TRX.REG0x12->bits.adciselc20 = 0x4; + BK7011TRX.REG0x12->bits.adciselr20 = 0x4; + BK7011TRX.REG0x12->bits.fictrl30 = 7; + CAL_WR_TRXREGS(0x12); + + BK7011TRX.REG0xD->bits.lpfrxbw = 1; + BK7011TRX.REG0xD->bits.lpftxbw = 1; + CAL_WR_TRXREGS(0xD); + + BK7011TRX.REG0xE->bits.lpfrxbw = 1; + BK7011TRX.REG0xE->bits.lpftxbw = 1; + CAL_WR_TRXREGS(0xE); + + BK7011TRX.REG0x10->bits.lpfrxbw = 1; + BK7011TRX.REG0x10->bits.lpftxbw = 1; + CAL_WR_TRXREGS(0x10); + + BK7011TRX.REG0xF->bits.clkdac_sel = 1; + BK7011TRX.REG0xF->bits.clkadc_sel = 1; + CAL_WR_TRXREGS(0xF); +} + +#if CFG_SUPPORT_MANUAL_CALI +void rwnx_cal_set_txpwr(UINT32 pwr_gain, UINT32 grate) +{ + const PWR_REGS *pcfg; + + if(pwr_gain > 32) { + os_printf("set_txpwr unknow pwr idx:%d \r\n", pwr_gain); + return; + } + + g_temp_pwr_current.idx = pwr_gain; + g_temp_pwr_current.mode = grate; + +#if CFG_USE_TEMPERATURE_DETECT + INT16 shift = g_temp_pwr_current.shift; + + if(g_temp_pwr_current.mode == EVM_DEFUALT_RATE) + shift = g_temp_pwr_current.shift_g; + + if(ble_in_dut_mode() ==0 ) + { + bk_printf("-----pwr_gain:%d, g_idx:%d, shift_b:%d, shift_g:%d\n", + pwr_gain, + g_temp_pwr_current.idx, + g_temp_pwr_current.shift, + g_temp_pwr_current.shift_g); + } + + pwr_gain = g_temp_pwr_current.idx + shift; + + if(pwr_gain > 32) + { + pwr_gain = 32; + } + if(ble_in_dut_mode() ==0 ) + { + bk_printf("-----[pwr_gain]%d\n",pwr_gain); + } +#endif // CFG_USE_TEMPERATURE_DETECT + + if(grate == EVM_DEFUALT_B_RATE) { + // for b + pcfg = cfg_tab_b + pwr_gain; + } else if(grate == EVM_DEFUALT_RATE) { + // for g + pcfg = cfg_tab_g + pwr_gain; + } else if(grate == EVM_DEFUALT_BLE_RATE) { + // for BLE + pcfg = cfg_tab_ble + pwr_gain; + } else { + os_printf("set_txpwr unknow rate:%d \r\n", grate); + return; + } + + if(get_ate_mode_state()) { +#ifdef ATE_PRINT_DEBUG + os_printf("idx:%02d,r:%03d- pg:0x%02x, %01x, %01x, %01x, %01x, %02x, %02x, %01x,\r\n", pwr_gain, grate, + pcfg->pregain, pcfg->regb_28_31, pcfg->regc_8_10,pcfg->regc_4_6, pcfg->regc_0_2, + pcfg->rega_8_13, pcfg->rega_4_7, pcfg->rega_0_1); + os_printf("Xtal C: %d\r\n", manual_cal_get_xtal()); +#else + os_printf("idx:%02d\r\n", pwr_gain); +#endif + #if DIFFERENCE_PIECES_CFG + os_printf("Mod :0x%x\r\n", bk7011_cal_dcormod_get()); + #endif + } + + CHECK_OPERATE_RF_REG_IF_IN_SLEEP(); + BK7011RCBEKEN.REG0x52->bits.TXPREGAIN = gtx_pre_gain = pcfg->pregain; + bk7011_rc_val[21] = BK7011RCBEKEN.REG0x52->value; + + BK7011TRX.REG0xA->bits.dbpab30 = pcfg->rega_4_7; + BK7011TRX.REG0xA->bits.dbpaa30 = pcfg->rega_8_13; + BK7011TRX.REG0xA->bits.disrefPA10 = pcfg->rega_0_1; + CAL_WR_TRXREGS(0xA); + bk7011_trx_val[10] = BK7011TRXONLY.REG0xA->value ; + + BK7011TRX.REG0xB->bits.gctrlmod30 = pcfg->regb_28_31; +#if DIFFERENCE_PIECES_CFG + BK7011TRX.REG0xB->bits.dcorMod30 = bk7011_cal_dcormod_get(); +#endif + CAL_WR_TRXREGS(0xB); + bk7011_trx_val[11] = BK7011TRXONLY.REG0xB->value ; + + BK7011TRX.REG0xC->bits.dgainpga = pcfg->regc_0_2; + BK7011TRX.REG0xC->bits.dgainbuf30 = pcfg->regc_4_6; + BK7011TRX.REG0xC->bits.dgainPA30 = pcfg->regc_8_10; + CAL_WR_TRXREGS(0xC); + bk7011_trx_val[12] = BK7011TRXONLY.REG0xC->value ; + CHECK_OPERATE_RF_REG_IF_IN_SLEEP_END(); + g_pwr_current.idx = pwr_gain; + g_pwr_current.mode = grate; +} + +#if CFG_USE_TEMPERATURE_DETECT +void rwnx_cal_set_txpwr_by_tmpdetect(INT16 shift_b, INT16 shift_g) +{ + UINT32 should_do = 0; + + if(g_temp_pwr_current.shift != shift_b) + { + g_temp_pwr_current.shift = shift_b; + should_do = 1; + } + + if(g_temp_pwr_current.shift_g!= shift_g) + { + g_temp_pwr_current.shift_g = shift_g; + should_do = 1; + } + + if( should_do) + { + if(ble_in_dut_mode() ==0 ) + { + os_printf("td set pwr: shift_b:%d, shift_g:%d, rate:%d\r\n", + g_temp_pwr_current.shift, + g_temp_pwr_current.shift_g, + g_temp_pwr_current.mode); + } + + if((rwnx_is_tpc_bit_on() == 0) && (is_rf_switch_to_ble() == 0)) + { + rwnx_cal_set_txpwr(g_temp_pwr_current.idx, g_temp_pwr_current.mode); + } + else + { + + } + } +} +#endif // CFG_USE_TEMPERATURE_DETECT + +void rwnx_cal_set_reg_mod_pa(UINT16 reg_mod, UINT16 reg_pa) +{ + CHECK_OPERATE_RF_REG_IF_IN_SLEEP(); + + gtx_dcorMod = (INT32)reg_mod, + gtx_dcorPA = (INT32)reg_pa; + BK7011TRXONLY.REG0xB->bits.dcorMod30 = gtx_dcorMod; + BK7011TRXONLY.REG0xC->bits.dcorPA30 = gtx_dcorPA; + bk7011_trx_val[11] = BK7011TRXONLY.REG0xB->value; + bk7011_trx_val[12] = BK7011TRXONLY.REG0xC->value; + CHECK_OPERATE_RF_REG_IF_IN_SLEEP_END(); +} + +#if CFG_USE_TEMPERATURE_DETECT +INT16 g_ble_pwr_indx = 0, g_ble_pwr_shift = 0; +#endif + +void rwnx_cal_set_txpwr_ble(UINT32 pwr_gain) +{ + const PWR_REGS *pcfg; + + if(pwr_gain > 32) { + os_printf("set_txpwr unknow pwr idx:%d \r\n", pwr_gain); + return; + } + + if(is_tpc_used) + rwnx_no_use_tpc_set_pwr(); + +#if CFG_USE_TEMPERATURE_DETECT + INT16 pwr_idx; + + pwr_idx = (INT16)pwr_gain; + pwr_idx += g_ble_pwr_shift; + + if(ble_in_dut_mode()) + { + //os_printf("ble setpwr idx:%d, g_td_shift:%d, idx_new:%d\r\n", + // pwr_gain, g_ble_pwr_shift, pwr_idx); + } + + if(pwr_idx > 32) + { + pwr_idx = 32; + } + else if(pwr_idx < 0) + { + pwr_idx = 0; + } + + g_ble_pwr_indx = pwr_gain = pwr_idx; +#endif + + pcfg = cfg_tab_ble + pwr_gain; + + if(get_ate_mode_state()) { +#ifdef ATE_PRINT_DEBUG + os_printf("idx:%02d,ble- pg:0x%02x, %01x, %01x, %01x, %01x, %02x, %02x, %01x,\r\n", pwr_gain, + pcfg->pregain, pcfg->regb_28_31, pcfg->regc_8_10,pcfg->regc_4_6, pcfg->regc_0_2, + pcfg->rega_0_1, pcfg->rega_4_7); + os_printf("Xtal C: %d\r\n", manual_cal_get_xtal()); +#else + os_printf("idx:%02d\r\n", pwr_gain); +#endif + } + + BK7011RCBEKEN.REG0x52->bits.TXPREGAIN = gtx_pre_gain = pcfg->pregain; + bk7011_rc_val[21] = BK7011RCBEKEN.REG0x52->value; + + + BK7011TRX.REG0xA->bits.dbpab30 = pcfg->rega_4_7; + BK7011TRX.REG0xA->bits.dbpaa30 = pcfg->rega_8_13; + BK7011TRX.REG0xA->bits.disrefPA10 = pcfg->rega_0_1; + CAL_WR_TRXREGS(0xA); + bk7011_trx_val[10] = BK7011TRXONLY.REG0xA->value ; + + BK7011TRX.REG0xB->bits.gctrlmod30 = pcfg->regb_28_31; +#if DIFFERENCE_PIECES_CFG + BK7011TRX.REG0xB->bits.dcorMod30 = bk7011_cal_dcormod_get(); +#endif + CAL_WR_TRXREGS(0xB); + bk7011_trx_val[11] = BK7011TRXONLY.REG0xB->value ; + + BK7011TRX.REG0xC->bits.dgainpga = pcfg->regc_0_2; + BK7011TRX.REG0xC->bits.dgainbuf30 = pcfg->regc_4_6; + BK7011TRX.REG0xC->bits.dgainPA30 = pcfg->regc_8_10; + CAL_WR_TRXREGS(0xC); + bk7011_trx_val[12] = BK7011TRXONLY.REG0xC->value ; +} + +#if CFG_USE_TEMPERATURE_DETECT +void rwnx_cal_set_ble_txpwr_by_tmpdetect(INT16 shift_ble) +{ + UINT32 should_do = 0; + + if(g_ble_pwr_shift != shift_ble) + { + g_ble_pwr_shift = shift_ble; + if(shift_ble) + should_do = 1; + } + + if( should_do) + { + //if(ble_in_dut_mode() ==0 ) + { + os_printf("td set ble pwr: shift:%d, cur_idx:%d\r\n", + g_ble_pwr_shift, + g_ble_pwr_indx); + } + + if(is_rf_switch_to_ble()) + rwnx_cal_set_txpwr_ble(g_ble_pwr_indx); + } +} +#endif // CFG_USE_TEMPERATURE_DETECT + +void rwnx_cal_set_txpwr_for_ble_boardcast(void) +{ + //rwnx_cal_set_txpwr_ble(12); + rwnx_cal_set_txpwr_by_channel(19); // channel 2440 +} + +void rwnx_cal_recover_txpwr_for_wifi(void) +{ + if(is_tpc_used) + { + rwnx_use_tpc_set_pwr(); + } + else + { + rwnx_cal_set_txpwr(g_pwr_current.idx, g_pwr_current.mode); + } +} + +void rwnx_cal_ble_set_rfconfig(void) +{ + BK7011TRX.REG0x8->bits.rssith50 = 0xf; + CAL_WR_TRXREGS(0x8); +} + +void rwnx_cal_ble_recover_rfconfig(void) +{ + BK7011TRX.REG0x8->value = bk7011_trx_val[8]; + CAL_WR_TRXREGS(0x8); +} + +#endif + +#if CFG_USE_TEMPERATURE_DETECT +#ifdef INCLUDE_OS +void rwnx_cal_do_temp_detect(UINT16 cur_val, UINT16 thre, UINT16 *last) +{ + TMP_PWR_PTR tmp_pwr_ptr; + tmp_pwr_ptr = manual_cal_set_tmp_pwr(cur_val, thre, last); + if(tmp_pwr_ptr) + { + #if CFG_TEMP_DETECT_VERSION == CFG_TEMP_DETECT_VERSION1 + #if CFG_TEMP_DIFF_PWR_FREQOFFSET + //BK7011TRX.REG0xC->bits.dcorPA30 = tmp_pwr_ptr->trx0x0c_12_15; + //CAL_WR_TRXREGS(0xC); + + manual_cal_do_xtal_temp_delta_set(tmp_pwr_ptr->xtal_c_dlta); + manual_cal_do_xtal_cali(cur_val, 0, 0, 0); + + rwnx_cal_set_txpwr_by_tmpdetect((INT16)tmp_pwr_ptr->p_index_delta, (INT16)tmp_pwr_ptr->p_index_delta_g); + rwnx_set_tpc_txpwr_by_tmpdetect((INT16)tmp_pwr_ptr->p_index_delta, (INT16)tmp_pwr_ptr->p_index_delta_g); + rwnx_cal_set_ble_txpwr_by_tmpdetect((INT16)tmp_pwr_ptr->p_index_delta_ble); + #endif + #else + rwnx_cal_set_reg_mod_pa(tmp_pwr_ptr->mod, tmp_pwr_ptr->pa); + #endif + + } +} +#endif +#endif // CFG_USE_TEMPERATURE_DETECT + +void rwnx_tx_cal_save_cal_result(void) +{ + int val; + // Manual calibration not used PA & MOD, but use pre_gain + #if CFG_SUPPORT_MANUAL_CALI + gtx_dcorMod = 0x8; + gtx_dcorPA = 0xA; + #if CFG_USE_TEMPERATURE_DETECT + manual_cal_tmp_pwr_init_reg(gtx_dcorMod, gtx_dcorPA); + #endif // CFG_USE_TEMPERATURE_DETECT + #endif + + bk7011_trx_val[11] = (bk7011_trx_val[11] & (~(0xf << 12))) | (((0xf)>x_dcorMod) << 12); + bk7011_trx_val[12] = (bk7011_trx_val[12] & (~(0xf << 12))) | (((0xf)>x_dcorPA) << 12); + bk7011_rc_val[21] = (bk7011_rc_val[21] & (~(0x1f << 16))) | (((0x1f)>x_pre_gain) << 16); + + bk7011_rc_val[18] = (bk7011_rc_val[18] & (~(0x3ff << 16))) | (((0x3ff)>x_i_dc_comp) << 16); + bk7011_rc_val[18] = (bk7011_rc_val[18] & (~0x3ff)) | ((0x3ff)>x_q_dc_comp); + + bk7011_rc_val[19] = (bk7011_rc_val[19] & (~(0x3ff << 16))) | (((0x3ff)>x_i_gain_comp) << 16); + bk7011_rc_val[19] = (bk7011_rc_val[19] & (~0x3ff)) | ((0x3ff)>x_q_gain_comp); + + bk7011_trx_val[6] = (bk7011_trx_val[6] & (~(0x3f << 10))) | (((0x3f)>x_ifilter_corner) << 10); + bk7011_trx_val[6] = (bk7011_trx_val[6] & (~(0x3f << 4))) | (((0x3f)>x_qfilter_corner) << 4); + + bk7011_rc_val[20] = (bk7011_rc_val[20] & (~(0x3ff << 16))) | (((0x3ff)>x_phase_comp) << 16); + bk7011_rc_val[20] = (bk7011_rc_val[20] & (~0x3ff)) | ((0x3ff)>x_phase_ty2); + + bk7011_rc_val[26] = (bk7011_rc_val[26] & (~(0x3f << 16))) | (((0x3f)>x_ifilter_corner) << 16); + val = gtx_ifilter_corner + g_capcal_sel; + if(val > 0x3f) + val = 0x3f; + bk7011_rc_val[26] = (bk7011_rc_val[26] & (~(0x3f << 8))) | (((0x3f)&val ) << 8); + bk7011_rc_val[26] = (bk7011_rc_val[26] & (~(0x3f << 0))) | (((0x3f)>x_ifilter_corner) << 0); + + + bk7011_rc_val[27] = (bk7011_rc_val[27] & (~(0x3f << 16))) | (((0x3f)>x_qfilter_corner) << 16); + val = gtx_qfilter_corner + g_capcal_sel; + if(val > 0x3f) + val = 0x3f; + bk7011_rc_val[27] = (bk7011_rc_val[27] & (~(0x3f << 8))) | (((0x3f)&val) << 8); + bk7011_rc_val[27] = (bk7011_rc_val[27] & (~(0x3f << 0))) | (((0x3f)>x_qfilter_corner) << 0); + + //if(gstat_cal) + //bk7011_rc_val[16] = bk7011_rc_val[16] | (1 << 29); + //else + //bk7011_rc_val[16] = bk7011_rc_val[16] & (~(1 << 29)); +} + +void rwnx_rx_cal_save_cal_result(void) +{ + bk7011_trx_val[20] = g_rx_dc_gain_tab[0]; + bk7011_trx_val[21] = g_rx_dc_gain_tab[1]; + bk7011_trx_val[22] = g_rx_dc_gain_tab[2]; + bk7011_trx_val[23] = g_rx_dc_gain_tab[3]; + bk7011_trx_val[24] = g_rx_dc_gain_tab[4]; + bk7011_trx_val[25] = g_rx_dc_gain_tab[5]; + bk7011_trx_val[26] = g_rx_dc_gain_tab[6]; + bk7011_trx_val[27] = g_rx_dc_gain_tab[7]; + + bk7011_rc_val[15] = (bk7011_rc_val[15] & (~(0x3ff << 16))) | (((0x3ff)&grx_amp_err_wr) << 16); + bk7011_rc_val[15] = (bk7011_rc_val[15] & (~0x3ff)) | ((0x3ff)&grx_phase_err_wr); +} + +/******************************************************************************* +* Function Implemantation +*******************************************************************************/ +void bk7011_read_cal_param(void) +{ + //gtx_dc_n = (BK7011RCBEKEN.REG0x54->bits.TXDCN & 0x03) + 2; + gst_sar_adc = ((BK7011RCBEKEN.REG0x54->bits.STSARADC & 0x03) + 1) * CAL_DELAY05US; + gst_rx_adc = ((BK7011RCBEKEN.REG0x54->bits.STRXADC & 0x03) + 1) * CAL_DELAY100US; + //gconst_iqcal_p = BK7011RCBEKEN.REG0x52->bits.IQCONSTANTIQCALP - 512; + //gconst_iqcal_p = abs(gconst_iqcal_p); + gconst_pout = BK7011RCBEKEN.REG0x52->bits.IQCONSTANTPOUT; + + return; +} + +INT32 rwnx_cal_load_trx_rcbekn_reg_val(void) +{ +#if (CFG_RUNNING_PLATFORM == FPGA_PLATFORM) + +#else + BK7011RCBEKEN.REG0x0->value = bk7011_rc_val[0]; + BK7011RCBEKEN.REG0x1->value = bk7011_rc_val[1]; + BK7011RCBEKEN.REG0x5->value = bk7011_rc_val[2]; + BK7011RCBEKEN.REG0x8->value = bk7011_rc_val[3]; + BK7011RCBEKEN.REG0xB->value = bk7011_rc_val[4]; + BK7011RCBEKEN.REG0xE->value = bk7011_rc_val[5]; + BK7011RCBEKEN.REG0x11->value = bk7011_rc_val[6]; + BK7011RCBEKEN.REG0x19->value = bk7011_rc_val[7]; + BK7011RCBEKEN.REG0x1C->value = bk7011_rc_val[8]; + BK7011RCBEKEN.REG0x1E->value = bk7011_rc_val[9]; + + /**********NEW ADDED************/ + BK7011RCBEKEN.REG0x3C->value = bk7011_rc_val[10]; + BK7011RCBEKEN.REG0x3E->value = bk7011_rc_val[11]; + BK7011RCBEKEN.REG0x3F->value = bk7011_rc_val[12]; + BK7011RCBEKEN.REG0x40->value = bk7011_rc_val[13]; + BK7011RCBEKEN.REG0x41->value = bk7011_rc_val[14]; + BK7011RCBEKEN.REG0x42->value = bk7011_rc_val[15]; + BK7011RCBEKEN.REG0x4C->value = bk7011_rc_val[16]; + BK7011RCBEKEN.REG0x4D->value = bk7011_rc_val[17]; + BK7011RCBEKEN.REG0x4F->value = bk7011_rc_val[18]; + BK7011RCBEKEN.REG0x50->value = bk7011_rc_val[19]; + BK7011RCBEKEN.REG0x51->value = bk7011_rc_val[20]; + BK7011RCBEKEN.REG0x52->value = bk7011_rc_val[21]; + BK7011RCBEKEN.REG0x54->value = bk7011_rc_val[22]; + BK7011RCBEKEN.REG0x55->value = bk7011_rc_val[23]; + BK7011RCBEKEN.REG0x5C->value = bk7011_rc_val[24]; + + BK7011RCBEKEN.REG0x4E->value = bk7011_rc_val[25]; + BK7011RCBEKEN.REG0x5A->value = bk7011_rc_val[26]; + BK7011RCBEKEN.REG0x5B->value = bk7011_rc_val[27]; + BK7011RCBEKEN.REG0x6A->value = bk7011_rc_val[28]; + BK7011RCBEKEN.REG0x70->value = bk7011_rc_val[29]; + BK7011RCBEKEN.REG0x71->value = bk7011_rc_val[30]; + BK7011RCBEKEN.REG0x72->value = bk7011_rc_val[31]; + BK7011RCBEKEN.REG0x73->value = bk7011_rc_val[32]; + BK7011RCBEKEN.REG0x74->value = bk7011_rc_val[33]; + BK7011RCBEKEN.REG0x75->value = bk7011_rc_val[34]; + BK7011RCBEKEN.REG0x76->value = bk7011_rc_val[35]; + BK7011RCBEKEN.REG0x77->value = bk7011_rc_val[36]; + + //BK7011RCBEKEN.REG0x3C->bits.RXIQSWAP = 1; /* I/Q SWAP*/ + +#endif + + os_memcpy(grc_reg_map, bk7011_trx_val, sizeof(INT32) * 29); + while(BK7011RCBEKEN.REG0x1->value & 0x0FFFFFFF) + { + cpu_delay(1); + } + + BK7011TRXONLY.REG0x0->value = bk7011_trx_val[0]; + BK7011TRXONLY.REG0x1->value = bk7011_trx_val[1]; + BK7011TRXONLY.REG0x2->value = bk7011_trx_val[2]; + BK7011TRXONLY.REG0x3->value = bk7011_trx_val[3]; + BK7011TRXONLY.REG0x4->value = bk7011_trx_val[4]; + BK7011TRXONLY.REG0x5->value = bk7011_trx_val[5]; + BK7011TRXONLY.REG0x6->value = bk7011_trx_val[6]; + BK7011TRXONLY.REG0x7->value = bk7011_trx_val[7]; + BK7011TRXONLY.REG0x8->value = bk7011_trx_val[8]; + BK7011TRXONLY.REG0x9->value = bk7011_trx_val[9]; + BK7011TRXONLY.REG0xA->value = bk7011_trx_val[10]; + BK7011TRXONLY.REG0xB->value = bk7011_trx_val[11]; + BK7011TRXONLY.REG0xC->value = bk7011_trx_val[12]; + BK7011TRXONLY.REG0xD->value = bk7011_trx_val[13]; + BK7011TRXONLY.REG0xE->value = bk7011_trx_val[14]; + BK7011TRXONLY.REG0xF->value = bk7011_trx_val[15]; + BK7011TRXONLY.REG0x10->value = bk7011_trx_val[16]; + BK7011TRXONLY.REG0x11->value = bk7011_trx_val[17]; + BK7011TRXONLY.REG0x12->value = bk7011_trx_val[18]; + BK7011TRXONLY.REG0x13->value = bk7011_trx_val[19]; + BK7011TRXONLY.REG0x14->value = bk7011_trx_val[20]; + BK7011TRXONLY.REG0x15->value = bk7011_trx_val[21]; + BK7011TRXONLY.REG0x16->value = bk7011_trx_val[22]; + BK7011TRXONLY.REG0x17->value = bk7011_trx_val[23]; + BK7011TRXONLY.REG0x18->value = bk7011_trx_val[24]; + BK7011TRXONLY.REG0x19->value = bk7011_trx_val[25]; + BK7011TRXONLY.REG0x1A->value = bk7011_trx_val[26]; + BK7011TRXONLY.REG0x1B->value = bk7011_trx_val[27]; + + while(BK7011RCBEKEN.REG0x1->value & 0x0FFFFFFF) + { + cpu_delay(1); + } + +#ifdef BK7011_VER_A + //os_memcpy(gadda_map, bk7011_adda_val, sizeof(INT32) * 6); + + //BK7011ADDA.REG0x0->value = bk7011_adda_val[0]; + //BK7011ADDA.REG0x1->value = bk7011_adda_val[1]; + //BK7011ADDA.REG0x2->value = bk7011_adda_val[2]; + //BK7011ADDA.REG0x3->value = bk7011_adda_val[3]; + //BK7011ADDA.REG0x4->value = bk7011_adda_val[4]; + //BK7011ADDA.REG0x5->value = bk7011_adda_val[5]; + //BK7011ADDAMAP.REG0x0->value = bk7011_adda_val[0]; + //BK7011ADDAMAP.REG0x1->value = bk7011_adda_val[1]; + //BK7011ADDAMAP.REG0x2->value = bk7011_adda_val[2]; + //BK7011ADDAMAP.REG0x3->value = bk7011_adda_val[3]; + //BK7011ADDAMAP.REG0x4->value = bk7011_adda_val[4]; + //BK7011ADDAMAP.REG0x5->value = bk7011_adda_val[5]; +#endif + +#ifdef BK7011_VER_A + //BK7011RCBEKEN.REG0x54->bits.DSELVA = 0; +#endif + + //BK7011ICU.REG0x3->bits.addaclkinv = 1; + //BK7011ICU.REG0x3->bits.txdacgain = 1 + +#if No_TXPOWERCAL + BK7011TRX.REG0xB->value = TRX_REG_0XB_VAL; + CAL_WR_TRXREGS(0xB); + BK7011TRX.REG0xC->value = TRX_REG_0XC_VAL; + CAL_WR_TRXREGS(0xC); + + BK7011RCBEKEN.REG0x52->bits.TXPREGAIN = 7; +#endif + + // cal rf pll when reload trx and rc beken value + bk7011_cal_pll(); + + return 0; +} + +INT32 rwnx_cal_save_trx_rcbekn_reg_val(void) +{ +#if (CFG_RUNNING_PLATFORM == FPGA_PLATFORM) + +#else + bk7011_rc_val[0] = BK7011RCBEKEN.REG0x0->value ; + bk7011_rc_val[1] = BK7011RCBEKEN.REG0x1->value ; + bk7011_rc_val[2] = BK7011RCBEKEN.REG0x5->value ; + bk7011_rc_val[3] = BK7011RCBEKEN.REG0x8->value ; + bk7011_rc_val[4] = BK7011RCBEKEN.REG0xB->value ; + bk7011_rc_val[5] = BK7011RCBEKEN.REG0xE->value ; + bk7011_rc_val[6] = BK7011RCBEKEN.REG0x11->value; + bk7011_rc_val[7] = BK7011RCBEKEN.REG0x19->value; + bk7011_rc_val[8] = BK7011RCBEKEN.REG0x1C->value; + bk7011_rc_val[9] = BK7011RCBEKEN.REG0x1E->value; + + /**********NEW ADDED************/ + bk7011_rc_val[10] = BK7011RCBEKEN.REG0x3C->value; + bk7011_rc_val[11] = BK7011RCBEKEN.REG0x3E->value; + bk7011_rc_val[12] = BK7011RCBEKEN.REG0x3F->value; + bk7011_rc_val[13] = BK7011RCBEKEN.REG0x40->value; + bk7011_rc_val[14] = BK7011RCBEKEN.REG0x41->value; + bk7011_rc_val[15] = BK7011RCBEKEN.REG0x42->value; + bk7011_rc_val[16] = BK7011RCBEKEN.REG0x4C->value; + bk7011_rc_val[17] = BK7011RCBEKEN.REG0x4D->value; + bk7011_rc_val[18] = BK7011RCBEKEN.REG0x4F->value; + bk7011_rc_val[19] = BK7011RCBEKEN.REG0x50->value; + bk7011_rc_val[20] = BK7011RCBEKEN.REG0x51->value; + bk7011_rc_val[21] = BK7011RCBEKEN.REG0x52->value; + bk7011_rc_val[22] = BK7011RCBEKEN.REG0x54->value; + bk7011_rc_val[23] = BK7011RCBEKEN.REG0x55->value; + bk7011_rc_val[24] = BK7011RCBEKEN.REG0x5C->value; + + bk7011_rc_val[25] = BK7011RCBEKEN.REG0x4E->value; + bk7011_rc_val[26] = BK7011RCBEKEN.REG0x5A->value; + bk7011_rc_val[27] = BK7011RCBEKEN.REG0x5B->value; + bk7011_rc_val[28] = BK7011RCBEKEN.REG0x6A->value; + bk7011_rc_val[29] = BK7011RCBEKEN.REG0x70->value; + bk7011_rc_val[30] = BK7011RCBEKEN.REG0x71->value; + bk7011_rc_val[31] = BK7011RCBEKEN.REG0x72->value; + bk7011_rc_val[32] = BK7011RCBEKEN.REG0x73->value; + bk7011_rc_val[33] = BK7011RCBEKEN.REG0x74->value; + bk7011_rc_val[34] = BK7011RCBEKEN.REG0x75->value; + bk7011_rc_val[35] = BK7011RCBEKEN.REG0x76->value; + bk7011_rc_val[36] = BK7011RCBEKEN.REG0x77->value; + + //BK7011RCBEKEN.REG0x3C->bits.RXIQSWAP = 1; /* I/Q SWAP*/ + +#endif + + bk7011_trx_val[0] = BK7011TRXONLY.REG0x0->value ; + bk7011_trx_val[1] = BK7011TRXONLY.REG0x1->value ; + bk7011_trx_val[2] = BK7011TRXONLY.REG0x2->value ; + bk7011_trx_val[3] = BK7011TRXONLY.REG0x3->value ; + bk7011_trx_val[4] = BK7011TRXONLY.REG0x4->value ; + bk7011_trx_val[5] = BK7011TRXONLY.REG0x5->value ; + bk7011_trx_val[6] = BK7011TRXONLY.REG0x6->value ; + bk7011_trx_val[7] = BK7011TRXONLY.REG0x7->value ; + bk7011_trx_val[8] = BK7011TRXONLY.REG0x8->value ; + bk7011_trx_val[9] = BK7011TRXONLY.REG0x9->value ; + bk7011_trx_val[10] = BK7011TRXONLY.REG0xA->value ; + bk7011_trx_val[11] = BK7011TRXONLY.REG0xB->value ; + bk7011_trx_val[12] = BK7011TRXONLY.REG0xC->value ; + bk7011_trx_val[13] = BK7011TRXONLY.REG0xD->value ; + bk7011_trx_val[14] = BK7011TRXONLY.REG0xE->value ; + bk7011_trx_val[15] = BK7011TRXONLY.REG0xF->value ; + bk7011_trx_val[16] = BK7011TRXONLY.REG0x10->value; + bk7011_trx_val[17] = BK7011TRXONLY.REG0x11->value; + bk7011_trx_val[18] = BK7011TRXONLY.REG0x12->value; + bk7011_trx_val[19] = BK7011TRXONLY.REG0x13->value; + bk7011_trx_val[20] = BK7011TRXONLY.REG0x14->value; + bk7011_trx_val[21] = BK7011TRXONLY.REG0x15->value; + bk7011_trx_val[22] = BK7011TRXONLY.REG0x16->value; + bk7011_trx_val[23] = BK7011TRXONLY.REG0x17->value; + bk7011_trx_val[24] = BK7011TRXONLY.REG0x18->value; + bk7011_trx_val[25] = BK7011TRXONLY.REG0x19->value; + bk7011_trx_val[26] = BK7011TRXONLY.REG0x1A->value; + bk7011_trx_val[27] = BK7011TRXONLY.REG0x1B->value; + + os_memcpy(grc_reg_map, bk7011_trx_val, sizeof(INT32) * 29); + while(BK7011RCBEKEN.REG0x1->value & 0x0FFFFFFF) + { + cpu_delay(1); + } + + return 0; +} + +void bk7011_cal_ready(void) +{ + rwnx_cal_load_trx_rcbekn_reg_val(); + + bk7011_read_cal_param(); + rwnx_cal_load_default_result(); + + cpu_delay(1000); + /*step 4.2*/ + BK7011RCBEKEN.REG0x4C->bits.TXCOMPDIS = 0; + //gstat_cal = 0; // calibration start + + return; +} + +void bk7011_cal_dpll(void) +{ + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_CALI_DPLL, NULL); +} + + +#define BAND_CAL_GPIO_TIMES 10 +#define BAND_CAL_ADD_STEP 8 +#define BAND_CAL_VAL_MAX 0x7FU +#define BAND_CAL_VAL_MIN 0x00U + +#ifdef INCLUDE_OS +#include "rtos_pub.h" +#define BAND_CAL_TIMER_INTVAL 500 // ms +beken_timer_t band_timer; +#endif + +void bk7011_band_cal(void) +{ + UINT32 band, band_min, band_max; + UINT32 unlocked; + + // backup register + gtx_band = BK7011TRX.REG0x3->bits.bandm60; + + band = BAND_CAL_VAL_MIN - BAND_CAL_ADD_STEP; + do { + band += BAND_CAL_ADD_STEP; + if(band > BAND_CAL_VAL_MAX) { + os_printf("band cal failed- band up to 127\r\n"); + goto band_exit; + } + + BK7011TRX.REG0x3->bits.bandm60 = band; + CAL_WR_TRXREGS(0x3); + delay100us(10);//delay 1ms + + unlocked = 0; + for(int i=0; ibits.ch0ld) + unlocked = 1; + } + }while(unlocked); + + //os_printf("found band:%02x\r\n", band); + band_min = band_max = band; + + do { + if(band_min <= BAND_CAL_VAL_MIN) { + break; + } + band_min--; + + BK7011TRX.REG0x3->bits.bandm60 = band_min; + CAL_WR_TRXREGS(0x3); + delay100us(10);//delay 1ms + + unlocked = 0; + for(int i=0; ibits.ch0ld) + unlocked = 1; + } + }while(!unlocked); + + //os_printf("found band_min:%02x\r\n", band_min); + + do { + if(band_max >= BAND_CAL_VAL_MAX) { + os_printf("band cal failed- chspi_max up to 0x7F\r\n"); + break; + } + + band_max++; + BK7011TRX.REG0x3->bits.bandm60 = band_max; + CAL_WR_TRXREGS(0x3); + delay100us(10);//delay 1ms + + unlocked = 0; + for(int i=0; ibits.ch0ld) + unlocked = 1; + } + }while(!unlocked); + + band = (band_max + band_min) / 2; + //os_printf("found band_max:%02x- last:%02x\r\n", band_max, band); + + gtx_band = band; +band_exit: + // end, recovery register + BK7011TRX.REG0x3->bits.bandm60 = gtx_band; + CAL_WR_TRXREGS(0x3); + bk7011_trx_val[3] = (bk7011_trx_val[3] & (~(0x7f << 17))) | (((0x7f)>x_band) << 17); +} + +void bk7011_band_timer_handler(void* data) +{ + UINT32 unlocked; + + unlocked = 0; + for(int i=0; ibits.ch0ld) + unlocked = 1; + } + + //os_printf("band:%d\r\n", unlocked); + if(unlocked){ + bk7011_band_cal(); + } +} + +void bk7011_band_detect(void) +{ +#ifdef INCLUDE_OS + rtos_init_timer(&band_timer, + BAND_CAL_TIMER_INTVAL, + bk7011_band_timer_handler, + (void *)0); + rtos_start_timer(&band_timer); +#endif +} + +#define BIAS_DIFF_VAL1 (4u) +#define BIAS_DIFF_VAL2 (2u) +void bk7011_cal_bias(void) +{ + UINT32 param, param2; + // BK7011TRX.REG0xF->bits.biascalmanual = 0; + param = PARAM_BIAS_CAL_MANUAL_BIT; + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_BIAS_REG_CLEAN, ¶m); + + // BK7011TRX.REG0xF->bits.biascaltrig = 0; + param = PARAM_BIAS_CAL_TRIGGER_BIT; + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_BIAS_REG_CLEAN, ¶m); + //trx_reg_is_write(st_TRXREG0F); + //BK7011TRXONLY.REG0xF->value = BK7011TRX.REG0xF->value; + cpu_delay(100); + // BK7011TRX.REG0xF->bits.biascaltrig = 1; + param = PARAM_BIAS_CAL_TRIGGER_BIT; + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_BIAS_REG_SET, ¶m); + + //trx_reg_is_write(st_TRXREG0F); + //BK7011TRXONLY.REG0xF->value = BK7011TRX.REG0xF->value; + cpu_delay(DELAY1US * 40);//40us = 30 + 10; + + //Read SYS_CTRL.REG0x4C->bias_cal_out + param = sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_BIAS_REG_READ, ¶m); + param = (param >> PARAM_BIAS_CAL_OUT_POSI) & PARAM_BIAS_CAL_OUT_MASK; + + //First, Write SYS_CTRL.REG0x4C->ldo_val_man = bias_cal_out + BIAS_DIFF_VAL1 + param += BIAS_DIFF_VAL1; + param2 = param; + if (param > 0x1f) param = 0x1f; + param = ((param & PARAM_BIAS_CAL_OUT_MASK) << PARAM_LDO_VAL_MANUAL_POSI) + | PARAM_BIAS_CAL_MANUAL_BIT; + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_BIAS_REG_WRITE, ¶m); + + //Second, Write SYS_CTRL.REG0x4C->ldo_val_man = ldo_val_man - BIAS_DIFF_VAL2 + param = param2 - BIAS_DIFF_VAL2; + if (param > 0x1f) param = 0x1f; + gbias_after_cal = param; + param = ((param & PARAM_BIAS_CAL_OUT_MASK) << PARAM_LDO_VAL_MANUAL_POSI) + | PARAM_BIAS_CAL_MANUAL_BIT; + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_BIAS_REG_WRITE, ¶m); + + + //param = ((0x3 & PARAM_VSEL_SYS_LDO_MASK)<< PARAM_VSEL_SYS_LDO_POSI); + //sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_ANALOG_CTRL4_SET, ¶m); + + return; +} + +void bk7011_cal_pll(void) +{ +#if 1 + // uint32_t loop = 0, val; + + // do + { +#if 0 + +#else + + /*reg0x10 enrfpll = 1*/ + BK7011TRX.REG0x10->bits.enrfpll = 1; + BK7011TRX.REG0x10->bits.endpll = 1; + CAL_WR_TRXREGS(0x10); + + /*reg0x00 spitrig = 0->1->0*/ +/* BK7011TRX.REG0x0->bits.spitrig = 0; + CAL_WR_TRXREGS(0x0); + BK7011TRX.REG0x0->bits.spitrig = 1; + CAL_WR_TRXREGS(0x0); + BK7011TRX.REG0x0->bits.spitrig = 0; + CAL_WR_TRXREGS(0x0);*/ + + /*reg0x05 spitrigger = 0->1->0*/ +// BK7011TRX.REG0x5->bits.spitrigger = 0; +// BK7011TRX.REG0x5->bits.errdetspien = 0; +// CAL_WR_TRXREGS(0x5); + +// BK7011TRX.REG0x5->bits.spitrigger = 1; +// CAL_WR_TRXREGS(0x5); +// BK7011TRX.REG0x5->bits.spitrigger = 0; +// CAL_WR_TRXREGS(0x5); +// BK7011TRX.REG0x5->bits.errdetspien = 1; +// CAL_WR_TRXREGS(0x5); + BK7011TRX.REG0x3->bits.spi_trigger = 1; + CAL_WR_TRXREGS(0x3); + BK7011TRX.REG0x3->bits.spi_trigger = 0; + CAL_WR_TRXREGS(0x3); + BK7011TRX.REG0x3->bits.errdet_spien = 1; + CAL_WR_TRXREGS(0x3); +#endif + + cpu_delay(DELAY1US * 10); + + } + +// bk7011_trx_val[5] = (bk7011_trx_val[5] & (~(0x3))) | (0x1); //7231 for pll unlock detection,7231u for doubler + +#endif +} + +void bk7011_set_rfcali_mode(int mode) +{ + if((mode != CALI_MODE_AUTO) && (mode != CALI_MODE_MANUAL)) + { + os_printf("rfcali_mode 0/1\r\n"); + return; + } + + g_cali_mode = mode; + + save_info_item(RF_CFG_MODE_ITEM, (UINT8 *)&g_cali_mode, NULL, NULL); + + os_printf("set rfcali_mode:%d\r\n", g_cali_mode); +} + +void bk7011_get_rfcali_mode(void) +{ + int cali_mode; +#if CFG_ENABLE_ATE_FEATURE + if(get_info_item(RF_CFG_MODE_ITEM, (UINT8 *)&cali_mode, NULL, NULL)) + { + g_cali_mode = cali_mode; + } +#endif + os_printf("get rfcali_mode:%d\r\n", g_cali_mode); +} + +int bk7011_is_rfcali_mode_auto(void) +{ + return (g_cali_mode == CALI_MODE_AUTO) ? 1 : 0; +} + +void bk7011_set_rf_config_tssithred(int tssi_thred) +{ + if((tssi_thred < 0) || (tssi_thred > 0xffU)) + { + os_printf("tssi range:0-255, %d\r\n", tssi_thred); + return; + } + + gtx_tssi_thred = tssi_thred; + + save_info_item(RF_CFG_TSSI_ITEM, (UINT8 *)>x_tssi_thred, NULL, NULL); + + os_printf("set tssi_thred:0x%x\r\n", gtx_tssi_thred); +} + +void bk7011_get_txpwr_config_reg(void) +{ + int tssi_thred; + + if(!bk7011_is_rfcali_mode_auto()) + { + // manual cali, no need load tssi thred + return; + } + +#if CFG_ENABLE_ATE_FEATURE + if(get_info_item(RF_CFG_TSSI_ITEM, (UINT8 *)&tssi_thred, NULL, NULL)) + { + gtx_tssi_thred = tssi_thred; + } +#endif + + os_printf("tssi_th:0x%x\r\n", gtx_tssi_thred); +} + +void bk7011_tx_cal_en(void) +{ + BK7011RCBEKEN.REG0x0->bits.forceenable = 1; + cpu_delay(1); + BK7011RCBEKEN.REG0x19->bits.FCH0EN = 1; + BK7011RCBEKEN.REG0x19->bits.FCH0SHDN = 1; + BK7011RCBEKEN.REG0x19->bits.FCH0RXEN = 0; + BK7011RCBEKEN.REG0x19->bits.FCH0TXEN = 1; + BK7011RCBEKEN.REG0x1C->bits.FRXON = 0; + BK7011RCBEKEN.REG0x1C->bits.FTXON = 1; + //BK7011RCBEKEN.REG0x4D->bits.TXSINF = 0x1A; + + //BK7011ICU.REG0x3->value = 0x00010002; + return; +} + +#define ADV_TSSI_CNT_MAX 8 +#define ADV_TSSI_MIN 0 +#define ADV_DROP_THRED 50 +static UINT32 bk7011_get_cnt_tssi(int cnt, UINT32 *adv_tssi, int cmp_min) +{ + UINT32 tssi_tab[ADV_TSSI_CNT_MAX], i, totoal, tssi, cnt_bak; + //os_memset(tssi_tab, 0, sizeof(UINT32) *ADV_TSSI_CNT_MAX); + + if(cnt > ADV_TSSI_CNT_MAX) + { + cnt = ADV_TSSI_CNT_MAX; + } + + totoal = 0; + for (i = 0; i < cnt; ) + { + cal_delay(1 * gst_sar_adc); + tssi = BK7011RCBEKEN.REG0x54->bits.TSSIRD; + CAL_PRT("tssi:%d", tssi); + if((tssi <= ADV_TSSI_MIN) && (cmp_min == 1)) + { + // this print for warning + os_printf(" <=%d, drop\r\n", ADV_TSSI_MIN); + continue; + } + CAL_PRT("\r\n", tssi); + tssi_tab[i] = tssi; + totoal += tssi; + i++; + } + + // get adv for first + tssi = totoal / cnt; + cnt_bak = cnt; + totoal = 0; + for (i = 0; i < cnt; i++) + { + UINT32 dist; + + if(tssi_tab[i] >= tssi) + dist = tssi_tab[i] - tssi; + else + dist = tssi - tssi_tab[i]; + + // drop + if(dist >= ADV_DROP_THRED) + { + CAL_PRT("found :|%d-%d| >= %d\r\n", tssi_tab[i], tssi, ADV_DROP_THRED); + tssi_tab[i] = 0; + cnt_bak--; + } + + totoal += tssi_tab[i]; + } + + // get adv second time, cnt_bak may not equ to cnt + if(cnt_bak == 0) // check 0 + cnt_bak = 1; + + tssi = totoal / cnt_bak; + totoal = tssi * cnt; + + if(adv_tssi) + *adv_tssi = tssi; + + CAL_PRT("ret %d times with total %d\r\n", cnt, totoal); + + return totoal; +} + +static INT32 bk7011_get_tx_output_power(void) +{ + INT32 tssioutpower = 0; + + tssioutpower = bk7011_get_cnt_tssi(4, NULL, 0); + + if(gtx_power_cal_mode == TX_WANTED_POWER_CAL) // + { + + #if DIFFERENCE_PIECES_CFG + tssioutpower = tssioutpower / 4 - gtx_tssi_thred - gav_tssi_temp; + //bk_printf("tssioutpower:%d\n",tssioutpower); + #else + tssioutpower = tssioutpower / 4 - TSSI_POUT_TH - gav_tssi_temp; + #endif + } + else if(gtx_power_cal_mode == TX_IQ_POWER_CAL) // + { + + tssioutpower = tssioutpower / 4 - TXIQ_IMB_TSSI_TH - gav_tssi_temp; + } + else + { + tssioutpower = tssioutpower / 4 - TXIQ_IMB_TSSI_TH_LOOPBACK - gav_tssi_temp; + } + + + tssioutpower = abs(tssioutpower); + //tssioutpower = abs((INT32)(((INT32)BK7011RCBEKEN.REG0x54->bits.TSSIRD) - gconst_tssi_pout_th)); + + return tssioutpower; +} + + +static INT32 bk7011_set_tx_pa(INT32 val1, INT32 val2, INT32 val3, INT32 val4) +{ + BK7011TRX.REG0xC->bits.dgainPA30 = val1; + BK7011TRX.REG0xC->bits.dgainbuf30 = val2; + BK7011TRX.REG0xC->bits.dgainpga = val3; + BK7011TRX.REG0xB->bits.gctrlmod30 = val4; + CAL_WR_TRXREGS(0xC); + CAL_WR_TRXREGS(0xB); + + return 0; +} + +#define GET_AV_TSSI_CNT 4 + +INT32 bk7011_cal_tx_output_power(INT32 *val) +{ + INT32 gold_index = 0; + INT32 tssilow = 0; + INT32 tssihigh = 0; + INT32 index; + INT16 high, low, tx_fre_gain; + INT32 cnt = 0; + + //BK7011ADDAMAP.REG0x5->bits.vc40 = 0x1f; + //BK7011ADDA.REG0x5->value = BK7011ADDAMAP.REG0x5->value; + + // bk7011_rc_val[12]-16:20=7, 0x53479D40, 21 REG_0x52 + BK7011RCBEKEN.REG0x52->bits.TXPREGAIN = 7; + + BK7011TRX.REG0xB->value = TRX_REG_0XB_VAL; + CAL_WR_TRXREGS(0xB); + + BK7011RCBEKEN.REG0x4C->bits.ICONSTANT = 0x200; + BK7011RCBEKEN.REG0x4C->bits.QCONSTANT = 0x200; + BK7011TRX.REG0xC->value = TRX_REG_0XC_TXLO_LEAKAGE_VAL; + BK7011RCBEKEN.REG0x4C->bits.TESTPATTERN = 1; + if (gtx_power_cal_mode == TX_WANTED_POWER_CAL) + { + #if DIFFERENCE_PIECES_CFG + BK7011RCBEKEN.REG0x4C->bits.ICONSTANT = 0x280;///0x200; + BK7011RCBEKEN.REG0x4C->bits.QCONSTANT = 0x280;///0x200; + BK7011RCBEKEN.REG0x4C->bits.TESTPATTERN = 1; + BK7011RCBEKEN.REG0x0->bits.ch0en = 1; ///add + + BK7011TRX.REG0xD->value = 0xDDF90339;///TRX_REG_0XD_VAL; + BK7011TRX.REG0xA->value = 0x036F2075;///TRX_REG_0XA_VAL;//by yiming 20170315; + BK7011TRX.REG0xB->value = 0xA7248F37;///TRX_REG_0XB_VAL;//; + BK7011TRX.REG0xC->value = 0x00228765;///TRX_REG_0XC_VAL;//; + BK7011RCBEKEN.REG0x52->bits.TXPREGAIN = 0x07; + CAL_WR_TRXREGS(0xB); + BK7011TRX.REG0xC->bits.dgainPA30 = 0; ///2 + BK7011TRX.REG0xC->bits.dgainbuf30 = 0; ///2 + + BK7011TRX.REG0xD->bits.entxsw = 1; + BK7011TRX.REG0xD->bits.enrxsw = 0; + + CAL_WR_TRXREGS(0xC); + BK7011TRX.REG0x0->bits.TSSIsel = 1; + BK7011TRX.REG0x0->bits.enDCcal = 0; + BK7011TRX.REG0x0->bits.enIQcal = 0; + BK7011TRX.REG0x0->bits.enPcal = 1; + BK7011TRX.REG0x0->bits.tssi_selrange = 0; + BK7011TRX.REG0x0->bits.PcalATT = 2; + #else + BK7011TRX.REG0xD->value = TRX_REG_0XD_VAL; + BK7011TRX.REG0xA->value = TRX_REG_0XA_VAL;//by yiming 20170315; + BK7011TRX.REG0xB->value = TRX_REG_0XB_VAL;//; + BK7011TRX.REG0xC->value = TRX_REG_0XC_VAL;//; + CAL_WR_TRXREGS(0xC); + BK7011TRX.REG0x0->bits.TSSIsel = 1; + BK7011TRX.REG0x0->bits.enDCcal = 0; + BK7011TRX.REG0x0->bits.enIQcal = 0; + BK7011TRX.REG0x0->bits.enPcal = 1; + BK7011TRX.REG0x0->bits.tssi_selrange = 0; + #endif + } + else if(gtx_power_cal_mode == TX_IQ_POWER_CAL) + { + BK7011TRX.REG0xD->value = TRX_REG_0XD_TX_IQ_VAL; + BK7011TRX.REG0xA->value = TRX_REG_0XA_VAL;//0x036F0757;//by yiming 20170315; + BK7011TRX.REG0xB->value = TRX_REG_0XB_VAL;//0x17248757;//; + BK7011TRX.REG0xC->value = TRX_REG_0XC_VAL;//0x05228765;//; + CAL_WR_TRXREGS(0xC); + + bk7011_set_tx_pa(gi_gain_tx_pa_dgainPA30, gi_gain_tx_pa_dgainbuf30, 0, 8); + BK7011TRX.REG0x0->bits.TSSIsel = 0; + BK7011TRX.REG0x0->bits.enDCcal = 0; + BK7011TRX.REG0x0->bits.enIQcal = 1; + BK7011TRX.REG0x0->bits.enPcal = 0; + BK7011TRX.REG0x0->bits.tssi_selrange = 0; + } + else //gtx_power_cal_mode == TX_IQ_LOOPBACK_POWER_CAL + { + BK7011TRX.REG0xD->value = TRX_REG_0XD_TX_LOOPBACK_IQ_VAL; + BK7011TRX.REG0xA->value = TRX_REG_0XA_VAL;//0x036F0757;//by yiming 20170315; + BK7011TRX.REG0xB->value = TRX_REG_0XB_VAL;//0x17248757;//; + BK7011TRX.REG0xC->value = TRX_REG_0XC_VAL;//0x05228765;//; + CAL_WR_TRXREGS(0xC); + bk7011_set_tx_pa(gi_gain_tx_loopback_pa_dgainPA30, gi_gain_tx_loopback_pa_dgainbuf30, 0, 8); + BK7011TRX.REG0x0->bits.TSSIsel = 0; + BK7011TRX.REG0x0->bits.enDCcal = 0; + BK7011TRX.REG0x0->bits.enIQcal = 1; + BK7011TRX.REG0x0->bits.enPcal = 0; + BK7011TRX.REG0x0->bits.tssi_selrange = 0; + } + +#if DIFFERENCE_PIECES_CFG + if (gtx_power_cal_mode == TX_WANTED_POWER_CAL) + { + BK7011TRX.REG0x0->bits.tssi_statectrl = 0; + } + else{ + BK7011TRX.REG0x0->bits.tssi_statectrl = 1; + } +#else + BK7011TRX.REG0x0->bits.tssi_statectrl = 1; +#endif + + BK7011TRX.REG0xD->bits.entssi = 1; + BK7011TRX.REG0xD->bits.entssiadc = 1;//20170503 enable TSSI +// BK7011TRX.REG0x0->bits.tssi_selrange = 1; +// BK7011TRX.REG0x0->bits.enPcaliGm = 0; + BK7011TRX.REG0xF->bits.tssi_cal_en = 1; + CAL_WR_TRXREGS(0x0); + CAL_WR_TRXREGS(0xA); + CAL_WR_TRXREGS(0xD); + CAL_WR_TRXREGS(0xC); + CAL_WR_TRXREGS(0xF); + BK7011TRX.REG0xB->bits.dcorMod30 = 0; + CAL_WR_TRXREGS(0xB); + cal_delay(150);//for reg C,D,F write spi=80/16=5M,total time is 21.6us + cal_delay(5 * gst_sar_adc); + + gav_tssi_temp = 0; + gav_tssi_temp = bk7011_get_cnt_tssi(GET_AV_TSSI_CNT, NULL, 0); + cnt = 0; + gav_tssi_temp /= GET_AV_TSSI_CNT;//Get small power tssi of each sample to remove tssi dc + if (gtx_power_cal_mode == TX_WANTED_POWER_CAL) + { + gav_tssi = gav_tssi_temp; + ///bk_printf("gav_tssi:%d\n",gav_tssi); + } + + if (gtx_power_cal_mode == TX_WANTED_POWER_CAL) + { + #if DIFFERENCE_PIECES_CFG + /* + BK7011RCBEKEN.REG0x4C->bits.ICONSTANT = 0x280;//gconst_pout; + BK7011RCBEKEN.REG0x4C->bits.QCONSTANT = 0x280;//gconst_pout; + BK7011TRX.REG0xC->value = TRX_REG_0XC_VAL;//; + + BK7011TRX.REG0xC->bits.dgainPA30 = 2;//; + BK7011TRX.REG0xC->bits.dgainbuf30 = 2;//; + + CAL_WR_TRXREGS(0xC); + BK7011TRX.REG0x0->bits.TSSIsel = 1; + BK7011TRX.REG0x0->bits.enDCcal = 0; + BK7011TRX.REG0x0->bits.enIQcal = 0; + BK7011TRX.REG0x0->bits.enPcal = 1; + BK7011TRX.REG0x0->bits.tssi_selrange = 0; + */ + BK7011RCBEKEN.REG0x4C->bits.ICONSTANT = 0x280;///0x200; + BK7011RCBEKEN.REG0x4C->bits.QCONSTANT = 0x280;///0x200; + BK7011RCBEKEN.REG0x0->bits.ch0en = 1; ///add + + // BK7011TRX.REG0xD->value = 0xDDF90339;///TRX_REG_0XD_VAL; + BK7011TRX.REG0xA->value = 0x036F2075;///TRX_REG_0XA_VAL;//by yiming 20170315; + BK7011TRX.REG0xB->value = 0xA7248F37;///TRX_REG_0XB_VAL;//; + BK7011TRX.REG0xC->value = 0x00228765;///TRX_REG_0XC_VAL;//; + + CAL_WR_TRXREGS(0xC); + CAL_WR_TRXREGS(0xB); + //BK7011RCBEKEN.REG0x52->bits.TXPREGAIN = 0x07; ///ADD + + BK7011TRX.REG0xD->bits.entxsw = 1; + BK7011TRX.REG0xD->bits.enrxsw = 0; + + //CAL_WR_TRXREGS(0xD); + + BK7011TRX.REG0x0->bits.TSSIsel = 1; + BK7011TRX.REG0x0->bits.enDCcal = 0; + BK7011TRX.REG0x0->bits.enIQcal = 0; + BK7011TRX.REG0x0->bits.enPcal = 1; + BK7011TRX.REG0x0->bits.tssi_selrange = 0; + BK7011TRX.REG0x0->bits.PcalATT = 2; + #else + BK7011RCBEKEN.REG0x4C->bits.ICONSTANT = gconst_pout; + BK7011RCBEKEN.REG0x4C->bits.QCONSTANT = gconst_pout; + BK7011TRX.REG0xC->value = TRX_REG_0XC_VAL;//; + CAL_WR_TRXREGS(0xC); + BK7011TRX.REG0x0->bits.TSSIsel = 1; + BK7011TRX.REG0x0->bits.enDCcal = 0; + BK7011TRX.REG0x0->bits.enIQcal = 0; + BK7011TRX.REG0x0->bits.enPcal = 1; + BK7011TRX.REG0x0->bits.tssi_selrange = 0; + #endif + } + else if(gtx_power_cal_mode == TX_IQ_POWER_CAL) + { + BK7011RCBEKEN.REG0x4C->bits.ICONSTANT = 0x230; + BK7011RCBEKEN.REG0x4C->bits.QCONSTANT = 0x230; + BK7011TRX.REG0xC->value = 0x05228245;//0x05228765;//; + CAL_WR_TRXREGS(0xC); + bk7011_set_tx_pa(gi_gain_tx_pa_dgainPA30, gi_gain_tx_pa_dgainbuf30, 0, 8); + BK7011TRX.REG0x0->bits.TSSIsel = 0; + BK7011TRX.REG0x0->bits.enDCcal = 0; + BK7011TRX.REG0x0->bits.enIQcal = 1; + BK7011TRX.REG0x0->bits.enPcal = 0; + BK7011TRX.REG0x0->bits.tssi_selrange = 0; + } + else //gtx_power_cal_mode == TX_IQ_LOOPBACK_POWER_CAL + { + BK7011RCBEKEN.REG0x4C->bits.ICONSTANT = 0x260;//by yiming 20170315; 250 + BK7011RCBEKEN.REG0x4C->bits.QCONSTANT = 0x260; + BK7011TRX.REG0xC->value = 0x05228245;//0x05228765;//; + CAL_WR_TRXREGS(0xC); + bk7011_set_tx_pa(gi_gain_tx_loopback_pa_dgainPA30, gi_gain_tx_loopback_pa_dgainbuf30, 0, 8); + BK7011TRX.REG0x0->bits.TSSIsel = 0; + BK7011TRX.REG0x0->bits.enDCcal = 0; + BK7011TRX.REG0x0->bits.enIQcal = 1; + BK7011TRX.REG0x0->bits.enPcal = 0; + BK7011TRX.REG0x0->bits.tssi_selrange = 0; + } + +#if DIFFERENCE_PIECES_CFG + ///BK7011TRX.REG0x0->bits.tssi_statectrl = 1; + if (gtx_power_cal_mode == TX_WANTED_POWER_CAL) + { + BK7011TRX.REG0x0->bits.tssi_statectrl = 0; + } + else{ + BK7011TRX.REG0x0->bits.tssi_statectrl = 1; + } +#else + BK7011TRX.REG0x0->bits.tssi_statectrl = 1; +#endif + +// BK7011TRX.REG0x0->bits.enPcaliGm = 0; + BK7011TRX.REG0xF->bits.tssi_cal_en = 1; + BK7011TRX.REG0xC->bits.dcorPA30 = 8; + + CAL_WR_TRXREGS(0x0); + CAL_WR_TRXREGS(0xA); + CAL_WR_TRXREGS(0xD); + CAL_WR_TRXREGS(0xC); + CAL_WR_TRXREGS(0xF); + BK7011RCBEKEN.REG0x4C->bits.TESTPATTERN = 1; + +#if DIFFERENCE_PIECES_CFG + if(gtx_power_cal_mode == TX_WANTED_POWER_CAL) + { + index = 0; + tssilow = 0; + tssihigh = 0; + cnt = 0; + + BK7011TRX.REG0xB->bits.dcorMod30 = cnt; + CAL_WR_TRXREGS(0xB); + tssilow = bk7011_get_tx_output_power(); + index = cnt; + + CAL_PRT("cnt:%d, index:%d, tssilow:%d, tssihigh:%d\r\n", + cnt, index, tssilow, tssihigh); + + cnt ++; + + while(cnt <= 15) + { + BK7011TRX.REG0xB->bits.dcorMod30 = cnt; + CAL_WR_TRXREGS(0xB); + tssihigh = bk7011_get_tx_output_power(); + + if(tssihigh < tssilow) + { + index = cnt; + tssilow = tssihigh; + } + + CAL_PRT("cnt:%d, index:%d, tssilow:%d, tssihigh:%d\r\n", + cnt, index, tssilow, tssihigh); + + cnt ++; + } + } + else +#endif + { + low = 0;//170703,for TZH limited from 2 to 6 + high = 15; + + BK7011TRX.REG0xB->bits.dcorMod30 = low; + CAL_WR_TRXREGS(0xB); + cal_delay(CAL_TX_NUM);//first sar dac delay needs double time + tssilow = bk7011_get_tx_output_power(); + + BK7011TRX.REG0xB->bits.dcorMod30 = high; + CAL_WR_TRXREGS(0xB); + tssihigh = bk7011_get_tx_output_power(); + + do + { + if(tssilow < tssihigh) + { + index = low; + high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011TRX.REG0xB->bits.dcorMod30 = high; + CAL_WR_TRXREGS(0xB); + tssihigh = bk7011_get_tx_output_power(); + } + else + { + index = high; + low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011TRX.REG0xB->bits.dcorMod30 = low; + CAL_WR_TRXREGS(0xB); + tssilow = bk7011_get_tx_output_power(); + } + } + while((high - low) > 1); + index = ((tssilow < tssihigh) ? low : high); + } + + + if (gtx_power_cal_mode == TX_WANTED_POWER_CAL) + { + gtx_dcorMod = index; + //bk_printf("gtx_dcorMod=%d\n",gtx_dcorMod); + } +#ifdef CALIBRATE_TIMES + else if(gtx_power_cal_mode == TX_IQ_POWER_CAL) + { + if (p_gbias_after_cal_array == NULL) + { + CAL_TIM_PRT("bk7011 TX IQ Cal. Output Power: \r\ntx_dcorMod= %d, ", index); + } + gtx_dcorMod_temp = index; + + } + else + { + if (p_gbias_after_cal_array == NULL) + { + CAL_TIM_PRT("bk7011 TX LOOPBACK IQ Cal. Output Power: \r\ntx_dcorMod= %d, ", index); + } + gtx_dcorMod_temp_loopback = index; + + + } + +#endif + + CAL_PRT("gtx_dcorMod over: 0x%x\r\n", gtx_dcorMod); + CAL_PRT("cnt:%d, index:%d, tssilow:0x%x-%d, tssihigh:0x%x-%d\r\n", + cnt++, index, tssilow, low, tssihigh, high); + + BK7011TRX.REG0xB->bits.dcorMod30 = index; + CAL_WR_TRXREGS(0xB); + gold_index = index << 8; + cal_delay(6); + + //BK7011TRX.REG0xB->bits.dcorMod30 = index; // dcormod30 optimum + //trx_reg_is_write(st_TRXREG0B); + //BK7011TRXONLY.REG0xB->value = BK7011TRX.REG0xB->value; + if (gtx_power_cal_mode == TX_WANTED_POWER_CAL) + { + low = 8;//170703,for TZH limited to 8 + high = 8; + } + else + { + low = 0;//170703,for TZH limited to 8 + high = 15; + } + BK7011TRX.REG0xC->bits.dcorPA30 = low; + CAL_WR_TRXREGS(0xC); + tssilow = bk7011_get_tx_output_power(); + + BK7011TRX.REG0xC->bits.dcorPA30 = high; + CAL_WR_TRXREGS(0xC); + tssihigh = bk7011_get_tx_output_power(); + + do + { + CAL_PRT("cnt:%d, index:%d, tssilow:0x%x-%d, tssihigh:0x%x-%d\r\n", + cnt++, index, tssilow, low, tssihigh, high); + if(tssilow < tssihigh) + { + index = low; + high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011TRX.REG0xC->bits.dcorPA30 = high; + CAL_WR_TRXREGS(0xC); + tssihigh = bk7011_get_tx_output_power(); + } + else + { + index = high; + low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011TRX.REG0xC->bits.dcorPA30 = low; + CAL_WR_TRXREGS(0xC); + tssilow = bk7011_get_tx_output_power(); + } + } + while((high - low) > 1); + + index = ((tssilow < tssihigh) ? low : high); + if (gtx_power_cal_mode == TX_WANTED_POWER_CAL) + { + gtx_dcorPA = index; + } +#ifdef CALIBRATE_TIMES + else if(gtx_power_cal_mode == TX_IQ_POWER_CAL) + { + if (p_gbias_after_cal_array == NULL) + { + CAL_TIM_PRT("tx_dcorPA= %d\r\n", index); + } + gtx_dcorPA_temp = index; + } + else + { + if (p_gbias_after_cal_array == NULL) + { + CAL_TIM_PRT("tx_dcorPA= %d\r\n", index); + } + gtx_dcorPA_temp_loopback = index; + } +#endif + BK7011TRX.REG0xC->bits.dcorPA30 = index; + CAL_WR_TRXREGS(0xC); + gold_index += index; + + //method2: first searching "dcorPA30",then serching "dcormod30"; + /**************************************************************** + * + *****************************************************************/ + *val = gold_index; + + CAL_PRT("gtx_dcorMod:0x%x, gtx_dcorPA:0x%x\r\n", gtx_dcorMod, gtx_dcorPA); + +#if 1 //170703,for TZH no pre_gain calibration + tx_fre_gain = BK7011RCBEKEN.REG0x52->bits.TXPREGAIN; + //CAL_WARN("tx_fre_gain:0x%x\r\n", tx_fre_gain); + if (gtx_power_cal_mode == TX_WANTED_POWER_CAL) + { + if(tx_fre_gain > 7) + low = tx_fre_gain - 7; + else + low = 0; + high = tx_fre_gain + 7; + } + else + { + if(tx_fre_gain > 2) + low = tx_fre_gain - 2; + else + low = 0; + high = tx_fre_gain + 2; + } + + BK7011RCBEKEN.REG0x52->bits.TXPREGAIN = low; + + //cpu_delay(1); +// tssilow = bk7011_get_tx_output_power_pregain(); + tssilow = bk7011_get_tx_output_power(); + + BK7011RCBEKEN.REG0x52->bits.TXPREGAIN = high; + //cpu_delay(1); +// tssihigh = bk7011_get_tx_output_power_pregain(); + tssihigh = bk7011_get_tx_output_power(); + + do + { + if(tssilow < tssihigh) + { + index = low; + high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x52->bits.TXPREGAIN = high; + //cpu_delay(1); + // tssihigh = bk7011_get_tx_output_power_pregain(); + tssihigh = bk7011_get_tx_output_power(); + } + else + { + index = high; + low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x52->bits.TXPREGAIN = low; + //cpu_delay(1); + // tssilow = bk7011_get_tx_output_power_pregain(); + tssilow = bk7011_get_tx_output_power(); + } + + } + while((high - low) > 1); + + index = ((tssilow < tssihigh) ? low : high); + + BK7011RCBEKEN.REG0x52->bits.TXPREGAIN = index; + if (gtx_power_cal_mode == TX_WANTED_POWER_CAL) + { + gtx_pre_gain = index; + } +#ifdef CALIBRATE_TIMES + else if(gtx_power_cal_mode == TX_IQ_POWER_CAL) + { + if (p_gbias_after_cal_array == NULL) + { + CAL_TIM_PRT("tx_pre_gain= %d\r\n", index); + } + gtx_pre_gain_temp = index; + } + else + { + if (p_gbias_after_cal_array == NULL) + { + CAL_TIM_PRT("tx_pre_gain= %d\r\n", index); + } + gtx_pre_gain_temp_loopback = index; + + } +#endif + + CAL_PRT("gtx_pre_gain:0x%x\r\n", gtx_pre_gain); +#endif + +#if 0 + if(gtx_dcorMod >= 0xa && gtx_dcorPA >= 0xc) + while(1); +#endif + + return (gold_index); +} + +void bk7011_micopwr_config_tssi_read_prepare(void) +{ + BK7011TRX.REG0x0->bits.TSSIsel = 1; + BK7011TRX.REG0x0->bits.enDCcal = 0; + BK7011TRX.REG0x0->bits.enIQcal = 0; + BK7011TRX.REG0x0->bits.enPcal = 1; + BK7011TRX.REG0x0->bits.tssi_statectrl = 1; + BK7011TRX.REG0xD->bits.entssi = 1; + BK7011TRX.REG0xD->bits.entssiadc = 1;//20170503 enable TSSI + BK7011TRX.REG0x0->bits.tssi_selrange = 1; +// BK7011TRX.REG0x0->bits.enPcaliGm = 0; + BK7011TRX.REG0xF->bits.tssi_cal_en = 1; + + CAL_WR_TRXREGS(0x0); + CAL_WR_TRXREGS(0xD); +// CAL_WR_TRXREGS(0xC); + CAL_WR_TRXREGS(0xF); +} + +#include "math.h" +#define TSSI_TAB_LEN 40 +#define TEMP_TAB_LEN 10 +UINT8 tssi_tab[TSSI_TAB_LEN]; +UINT8 temp_tab[TSSI_TAB_LEN]; + +void bk7011_micopwr_tssi_read(void) +{ + UINT32 i; + REG_WRITE((0x0802800 + (18 * 4)), 0x00); + for(i = 0; i < TSSI_TAB_LEN; i++) + { + tssi_tab[i] = BK7011RCBEKEN.REG0x54->bits.TSSIRD & 0xff; + } + //REG_WRITE((0x0802800 + (18 * 4)), 0x00); +} + +void bk7011_micopwr_tssi_show(void) +{ + UINT32 i, s = 0; + double sd = 0; + os_printf("\r\n tssi tab: \r\n"); + for(i = 0; i < TSSI_TAB_LEN; i++) + { + os_printf("%d, ", tssi_tab[i]); + if((i + 1) % 16 == 0) + os_printf("\r\n"); + } + + for(i = 0; i < TSSI_TAB_LEN; i++) + { + s += tssi_tab[i] * tssi_tab[i]; + } + sd = sqrt((double)(s / TSSI_TAB_LEN)); + os_printf("\r\nsd = %f\r\n", sd); +} + +static INT32 bk7011_update_tx_power(void) +{ +#ifdef CALIBRATE_TIMES + bk7011_set_tx_pa(gi_dc_tx_pa_dgainPA30, gi_dc_tx_pa_dgainbuf30, 0, 8);// mod gain should be same as the powser cal. setting +#else + bk7011_set_tx_pa(gi_dc_tx_pa_dgainPA30, gi_dc_tx_pa_dgainbuf30, 0, 8); +#endif + return 0; +} + +static INT32 bk7011_update_tx_loopback_power(void) +{ +#ifdef CALIBRATE_TIMES + bk7011_set_tx_pa(gi_dc_tx_loopback_pa_dgainPA30, gi_dc_tx_loopback_pa_dgainbuf30, 0, 8); +#else + bk7011_set_tx_pa(gi_dc_tx_loopback_pa_dgainPA30, gi_dc_tx_loopback_pa_dgainbuf30, 0, 8); +#endif + return 0; +} + +static INT32 bk7011_get_tx_dc(void) +{ + INT32 detect_dc = 0; + + cpu_delay(200);//18us + + detect_dc = bk7011_get_cnt_tssi(SUMNUMBERS, NULL, 0); + + return detect_dc; +} + +INT32 bk7011_cal_tx_dc(INT32 *val) +{ + INT32 detect_dc_low = 0; + INT32 detect_dc_high = 0; + INT16 high, low; + INT32 index, gold_index = 0; + INT32 i_index, q_index; + INT32 srchcnt = 0; + INT16 search_thrd = 64;//128;//DC search range search_thrd=512 gtx_dc_n=3, search_thrd=256 gtx_dc_n=2, search_thrd=128 gtx_dc_n=1 + /*step 4*/ + + + if(gtx_dc_cal_mode == TX_DC_CAL) + { + BK7011TRX.REG0xD->value = TRX_REG_0XD_TX_IQ_VAL; //BK7011TRXREG0xD;// + CAL_WR_TRXREGS(0xD); + bk7011_update_tx_power(); + BK7011TRX.REG0xB->bits.gctrlmod30 = (TRX_REG_0XB_VAL >> 28) & 0x0F; + CAL_WR_TRXREGS(0xB); + } + else if (gtx_dc_cal_mode == TX_DC_CAL_IQ) + { + BK7011TRX.REG0xD->value = TRX_REG_0XD_TX_IQ_VAL; //BK7011TRXREG0xD;// + CAL_WR_TRXREGS(0xD); + bk7011_update_tx_power(); + } + else if (gtx_dc_cal_mode == TX_DC_LOOPBACK_CAL_IQ) + { + BK7011TRX.REG0xD->value = TRX_REG_0XD_TX_LOOPBACK_IQ_VAL; + CAL_WR_TRXREGS(0xD); + bk7011_update_tx_loopback_power(); + } + + +#ifdef CALIBRATE_TIMES + if (p_gbias_after_cal_array == NULL) + { + if(gtx_dc_cal_mode == TX_DC_CAL) + { + CAL_TIM_PRT("\r\nbk7011_cal_tx_dc: \r\n"); + } + if(gtx_dc_cal_mode == TX_DC_CAL_IQ) + { + CAL_TIM_PRT("\r\nbk7011_cal_tx_dc_iq: \r\n"); + } + else if (gtx_dc_cal_mode == TX_DC_LOOPBACK_CAL_IQ) + { + CAL_TIM_PRT("\r\nbk7011_cal_tx_loopback_dc_iq: \r\n"); + } + CAL_TIM_PRT("dgainPA30 = %d\r\n", BK7011TRX.REG0xC->bits.dgainPA30 ); + CAL_TIM_PRT("dgainbuf30 =%d\r\n", BK7011TRX.REG0xC->bits.dgainbuf30); + CAL_TIM_PRT("dgainpga = %d\r\n", BK7011TRX.REG0xC->bits.dgainpga ); + CAL_TIM_PRT("gctrlmod30 = %d\r\n", BK7011TRX.REG0xB->bits.gctrlmod30); + } +#endif + + //[-512 511]---->[0,1023]; + + // I DC calibration; + BK7011RCBEKEN.REG0x4F->bits.TXQDCCOMP = UNSIGNEDOFFSET10 + 0; //default + + if(gtx_dc_cal_mode == TX_DC_CAL) + { + low = UNSIGNEDOFFSET10 - MINOFFSET ; + high = UNSIGNEDOFFSET10 + MINOFFSET ; + } + else if (gtx_dc_cal_mode == TX_DC_CAL_IQ) + { + low = UNSIGNEDOFFSET10 - MINOFFSET ; + high = UNSIGNEDOFFSET10 + MINOFFSET ; + } + else if (gtx_dc_cal_mode == TX_DC_LOOPBACK_CAL_IQ) + { + low = UNSIGNEDOFFSET10 - 3 * MINOFFSET ; + high = UNSIGNEDOFFSET10 + 3 * MINOFFSET ; + } + else + { + low = BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP; + high = BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP; + } + + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = low; + + //20170330 + BK7011RCBEKEN.REG0x4C->bits.ICONSTANT = UNSIGNEDOFFSET10 - 1; + BK7011RCBEKEN.REG0x4C->bits.QCONSTANT = UNSIGNEDOFFSET10 - 1 ; + BK7011RCBEKEN.REG0x4C->bits.TESTPATTERN = 1; + BK7011TRX.REG0x0->bits.TSSIsel = 0; + BK7011TRX.REG0x0->bits.enDCcal = 1; + BK7011TRX.REG0x0->bits.tssi_selrange = 1;//inverse 20141014 + BK7011TRX.REG0x0->bits.tssi_statectrl = 1; + BK7011TRX.REG0x0->bits.enIQcal = 0; + BK7011TRX.REG0x0->bits.enPcal = 0; +// BK7011TRX.REG0x0->bits.enPcaliGm = 0; + BK7011TRX.REG0xF->bits.tssi_cal_en = 1; + //20170330 + + CAL_WR_TRXREGS(0x0); + //BK7011TRXONLY.REG0xD->value = BK7011TRX.REG0xD->value; + CAL_WR_TRXREGS(0xC); + CAL_WR_TRXREGS(0xF); + cal_delay(CAL_TX_NUM);//first sar dac delay needs double time + + detect_dc_low = bk7011_get_tx_dc(); + + + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + //Step 1 3~6 search; + srchcnt = 0; + + + if(detect_dc_low < detect_dc_high) + { + high = 511; + low = high - search_thrd; + } + else + { + low = 512; + high = low + search_thrd; + } + + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = low; + detect_dc_low = bk7011_get_tx_dc(); + + do + { + if(detect_dc_low < detect_dc_high) + { + index = low; + high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + + } + else + { + index = high; + low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = low; + detect_dc_low = bk7011_get_tx_dc(); + } + srchcnt++; + if(srchcnt > gtx_dc_n) + break; + } + while((high - low) > 1); + + //Step 2 search; + + //BK7011TRX.REG0x0->bits.tssi_selrange = 0;//20170330 YIMING + BK7011TRX.REG0x0->value = 0x00019041; + CAL_WR_TRXREGS(0x0); + + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = low; + detect_dc_low = bk7011_get_tx_dc(); + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + + do + { + if(detect_dc_low < detect_dc_high) + { + index = low; + high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + + } + else + { + index = high; + low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = low; + detect_dc_low = bk7011_get_tx_dc(); + } + } + while((high - low) > 1); + i_index = ((detect_dc_low < detect_dc_high) ? low : high); + + // Q DC calibration; + //Step 1 3~6 search; + if ((gtx_dc_cal_mode == TX_DC_CAL) || (gtx_dc_cal_mode == TX_DC_CAL_IQ)) + { + low = UNSIGNEDOFFSET10 - MINOFFSET ; + high = UNSIGNEDOFFSET10 + MINOFFSET ; + } + else if (gtx_dc_cal_mode == TX_DC_LOOPBACK_CAL_IQ) + { + low = UNSIGNEDOFFSET10 - 3 * MINOFFSET ; + high = UNSIGNEDOFFSET10 + 3 * MINOFFSET ; + } + + //20170330 + + //BK7011TRX.REG0x0->bits.tssi_selrange = 1;//inverse 20141014 + BK7011TRX.REG0x0->value = 0x00079042; + CAL_WR_TRXREGS(0x0); + + //20170330 + srchcnt = 0; + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = i_index; //default + + BK7011RCBEKEN.REG0x4F->bits.TXQDCCOMP = low; + detect_dc_low = bk7011_get_tx_dc(); + + + BK7011RCBEKEN.REG0x4F->bits.TXQDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + + + if(detect_dc_low < detect_dc_high) + { + + high = 511; + low = high - search_thrd; + } + else + { + low = 512; + high = low + search_thrd; + } + + BK7011RCBEKEN.REG0x4F->bits.TXQDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + BK7011RCBEKEN.REG0x4F->bits.TXQDCCOMP = low; + detect_dc_low = bk7011_get_tx_dc(); + + do + { + if(detect_dc_low < detect_dc_high) + { + index = low; + high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x4F->bits.TXQDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + + } + else + { + index = high; + low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x4F->bits.TXQDCCOMP = low; + detect_dc_low = bk7011_get_tx_dc(); + } + srchcnt++; + if(srchcnt > gtx_dc_n) + break; + } + while((high - low) > 1); + + //Step 2 search; + + //BK7011TRX.REG0x0->bits.tssi_selrange = 0;//20170330 YIMING + BK7011TRX.REG0x0->value = 0x00019041; + CAL_WR_TRXREGS(0x0); + + BK7011RCBEKEN.REG0x4F->bits.TXQDCCOMP = low; + detect_dc_low = bk7011_get_tx_dc(); + BK7011RCBEKEN.REG0x4F->bits.TXQDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + do + { + if(detect_dc_low < detect_dc_high) + { + index = low; + high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x4F->bits.TXQDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + + } + else + { + index = high; + low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x4F->bits.TXQDCCOMP = low; + detect_dc_low = bk7011_get_tx_dc(); + } + } + while((high - low) > 1); + + q_index = ((detect_dc_low < detect_dc_high) ? low : high); + + + + if(gtx_dc_cal_mode == TX_DC_CAL) + { + gtx_q_dc_comp = q_index + 1;//190614 Q compensate + CAL_WARN("gtx_q_dc_comp:0x%x\r\n", gtx_q_dc_comp); + } + else if(gtx_dc_cal_mode == TX_DC_CAL_IQ) + { + gtx_q_dc_comp = q_index; + CAL_WARN("gtx_q_dc_comp_iq:0x%x\r\n", gtx_q_dc_comp); + } + else if (gtx_dc_cal_mode == TX_DC_LOOPBACK_CAL_IQ) + { + gtx_q_dc_comp_loopback = q_index; +#ifdef CALIBRATE_TIMES + if (p_gtx_q_dc_comp_temp_array != NULL) + { + p_gtx_q_dc_comp_temp_array[calibrate_time] = q_index; + } +#endif + CAL_WARN("gtx_q_dc_comp_loopback_iq:0x%x\r\n", gtx_q_dc_comp_loopback); + } + gold_index += q_index; + + // 2nd I DC calibration; + //Step 1 3~6 search; + if ((gtx_dc_cal_mode == TX_DC_CAL) || (gtx_dc_cal_mode == TX_DC_CAL_IQ)) + { + low = UNSIGNEDOFFSET10 - MINOFFSET ; + high = UNSIGNEDOFFSET10 + MINOFFSET ; + } + else// (gtx_dc_cal_mode == TX_DC_LOOPBACK_CAL_IQ) + { + low = UNSIGNEDOFFSET10 - 3 * MINOFFSET ; + high = UNSIGNEDOFFSET10 + 3 * MINOFFSET ; + } + //20170330 + + //BK7011TRX.REG0x0->bits.tssi_selrange = 1;//inverse 20141014 + BK7011TRX.REG0x0->value = 0x00079042; + CAL_WR_TRXREGS(0x0); + + //20170330 + + + srchcnt = 0; + BK7011RCBEKEN.REG0x4F->bits.TXQDCCOMP = q_index; // optimum + + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = low; + detect_dc_low = bk7011_get_tx_dc(); + + + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + //low = 0; + //high = 1023; + + + if(detect_dc_low < detect_dc_high) + { + high = 511; + low = high - search_thrd; + } + else + { + low = 512; + high = low + search_thrd; + } + + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = low; + detect_dc_low = bk7011_get_tx_dc(); + + do + { + if(detect_dc_low < detect_dc_high) + { + index = low; + high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + } + else + { + index = high; + low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = low; + detect_dc_low = bk7011_get_tx_dc(); + } + srchcnt++; + if(srchcnt > gtx_dc_n) break; + } + while((high - low) > 1); + + //Step 2 search; + + //BK7011TRX.REG0x0->bits.tssi_selrange = 0;//20170330 YIMING + BK7011TRX.REG0x0->value = 0x00019041; + CAL_WR_TRXREGS(0x0); + + + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = low; + detect_dc_low = bk7011_get_tx_dc(); + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + do + { + + if(detect_dc_low < detect_dc_high) + { + index = low; + high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + + } + else + { + index = high; + low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = low; + detect_dc_low = bk7011_get_tx_dc(); + } + } + while((high - low) > 1); + + + i_index = ((detect_dc_low < detect_dc_high) ? low : high); + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = i_index; + if(gtx_dc_cal_mode == TX_DC_CAL) + { + gtx_i_dc_comp = i_index + 1;//190614 I compensate + CAL_WARN("gtx_i_dc_comp:0x%x\r\n", gtx_i_dc_comp); + } + else if(gtx_dc_cal_mode == TX_DC_CAL_IQ) + { + gtx_i_dc_comp = i_index; + CAL_WARN("gtx_i_dc_comp_iq:0x%x\r\n", gtx_i_dc_comp); + } + else if (gtx_dc_cal_mode == TX_DC_LOOPBACK_CAL_IQ) + { + gtx_i_dc_comp_loopback= i_index; + #ifdef CALIBRATE_TIMES + if (p_gtx_i_dc_comp_temp_array != NULL) + { + p_gtx_i_dc_comp_temp_array[calibrate_time] = i_index; + } + #endif + CAL_WARN("gtx_i_dc_comp_loopback_iq:0x%x\r\n", gtx_i_dc_comp_loopback); + } + + gold_index += (i_index << 16); + *val = gold_index; + (void)index; + + //BK7011TRX.REG0x0->bits.tssi_selrange = 1;//inverse 20141014 + BK7011TRX.REG0x0->value = 0x00079042; + CAL_WR_TRXREGS(0x0); + + return gold_index; +} + + +#define TSSI_RD_TIMES 8 +static INT32 bk7011_get_tx_i_gain(void) +{ + INT32 detector_i_gain_p, detector_i_gain_n, detector_i_gain; + + BK7011RCBEKEN.REG0x4C->bits.ICONSTANT = UNSIGNEDOFFSET10 + gconst_iqcal_p; + BK7011RCBEKEN.REG0x4C->bits.QCONSTANT = UNSIGNEDOFFSET10 + 0; + detector_i_gain_p = 0; + detector_i_gain_p = bk7011_get_cnt_tssi(TSSI_RD_TIMES, NULL, 1); + + BK7011RCBEKEN.REG0x4C->bits.ICONSTANT = UNSIGNEDOFFSET10 - gconst_iqcal_p; + BK7011RCBEKEN.REG0x4C->bits.QCONSTANT = UNSIGNEDOFFSET10 + 0; + detector_i_gain_n = 0; + detector_i_gain_n = bk7011_get_cnt_tssi(TSSI_RD_TIMES, NULL, 1); + + detector_i_gain = detector_i_gain_p + detector_i_gain_n; + return detector_i_gain; +} +static INT32 bk7011_get_tx_q_gain(void) +{ + INT32 detector_q_gain_p, detector_q_gain_n, detector_q_gain; + + BK7011RCBEKEN.REG0x4C->bits.ICONSTANT = UNSIGNEDOFFSET10 + 0; + BK7011RCBEKEN.REG0x4C->bits.QCONSTANT = UNSIGNEDOFFSET10 + gconst_iqcal_p; + detector_q_gain_p = 0; + detector_q_gain_p = bk7011_get_cnt_tssi(TSSI_RD_TIMES, NULL, 1); + + BK7011RCBEKEN.REG0x4C->bits.ICONSTANT = UNSIGNEDOFFSET10 + 0; + BK7011RCBEKEN.REG0x4C->bits.QCONSTANT = UNSIGNEDOFFSET10 - gconst_iqcal_p; + detector_q_gain_n = 0; + detector_q_gain_n = bk7011_get_cnt_tssi(TSSI_RD_TIMES, NULL, 1); + + detector_q_gain = detector_q_gain_p + detector_q_gain_n; + return detector_q_gain; +} +static INT32 bk7011_get_tx_i_phase(void) +{ + INT32 detector_i_phase_n, detector_i_phase_p, detector_i_phase; + + BK7011RCBEKEN.REG0x4C->bits.ICONSTANT = UNSIGNEDOFFSET10 + (gconst_iqcal_p*10)/14; + BK7011RCBEKEN.REG0x4C->bits.QCONSTANT = UNSIGNEDOFFSET10 - (gconst_iqcal_p*10)/14; + detector_i_phase_p = 0; + detector_i_phase_p = bk7011_get_cnt_tssi(TSSI_RD_TIMES, NULL, 1); + + BK7011RCBEKEN.REG0x4C->bits.ICONSTANT = UNSIGNEDOFFSET10 - (gconst_iqcal_p*10)/14; + BK7011RCBEKEN.REG0x4C->bits.QCONSTANT = UNSIGNEDOFFSET10 + (gconst_iqcal_p*10)/14; + detector_i_phase_n = 0; + detector_i_phase_n = bk7011_get_cnt_tssi(TSSI_RD_TIMES, NULL, 1); + + detector_i_phase = detector_i_phase_p + detector_i_phase_n; + return detector_i_phase; +} +static INT32 bk7011_get_tx_q_phase(void) +{ + INT32 detector_q_phase_n, detector_q_phase_p, detector_q_phase; + + BK7011RCBEKEN.REG0x4C->bits.ICONSTANT = UNSIGNEDOFFSET10 + (gconst_iqcal_p*10)/14; + BK7011RCBEKEN.REG0x4C->bits.QCONSTANT = UNSIGNEDOFFSET10 + (gconst_iqcal_p*10)/14; + detector_q_phase_p = 0; + detector_q_phase_p = bk7011_get_cnt_tssi(TSSI_RD_TIMES, NULL, 1); + + BK7011RCBEKEN.REG0x4C->bits.ICONSTANT = UNSIGNEDOFFSET10 - (gconst_iqcal_p*10)/14; + BK7011RCBEKEN.REG0x4C->bits.QCONSTANT = UNSIGNEDOFFSET10 - (gconst_iqcal_p*10)/14; + detector_q_phase_n = 0; + detector_q_phase_n = bk7011_get_cnt_tssi(TSSI_RD_TIMES, NULL, 1); + + detector_q_phase = detector_q_phase_p + detector_q_phase_n; + return detector_q_phase; +} +static INT32 bk7011_get_rx_i_avg_signed(void) +{ + INT32 val; +#ifdef BK7011_VER_A + val = BK7011RCBEKEN.REG0x3C->bits.RXAVGIRD; +#else + val = BK7011RCBEKEN.REG0x3C->bits.RXAVGIRD; +#endif + + return val; +// if(val & 0x00000800) +// { +// val |= 0xfffff000; +// } + +// return abs(val); +} + +static INT32 bk7011_get_rx_q_avg_signed(void) +{ + INT32 val; + +#ifdef BK7011_VER_A + val = BK7011RCBEKEN.REG0x3C->bits.RXAVGQRD; +#else + val = BK7011RCBEKEN.REG0x3C->bits.RXAVGQRD; +#endif + + return val; + +// if(val & 0x00000800) +// { +// val |= 0xfffff000; +// } +// return abs(val); +} + +INT32 bk7011_cal_tx_gain_imbalance(INT32 *val) +{ + INT32 detect_gain_low = 0; + INT32 detect_gain_high = 0; + INT16 high, low; + INT32 index = 0, gold_index = 0; + INT32 detector_i_gain; + INT32 detector_q_gain; + + if(gtx_gain_imb_cal_mode == TX_GAIN_IMB_CAL) + { + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = gtx_i_dc_comp; + BK7011RCBEKEN.REG0x4F->bits.TXQDCCOMP = gtx_q_dc_comp; + BK7011TRX.REG0xD->value = TRX_REG_0XD_TX_IQ_VAL;//BK7011TRXREG0xD;//0214 close the TX switch to ellimite the antenna infect + CAL_WR_TRXREGS(0xD); + } + else + { + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = gtx_i_dc_comp_loopback; + BK7011RCBEKEN.REG0x4F->bits.TXQDCCOMP = gtx_q_dc_comp_loopback; + BK7011TRX.REG0xD->value = TRX_REG_0XD_TX_LOOPBACK_IQ_VAL; + CAL_WR_TRXREGS(0xD); + + } + + BK7011RCBEKEN.REG0x50->bits.TXIGAINCOMP = 1023; + BK7011RCBEKEN.REG0x50->bits.TXQGAINCOMP = 1023; + BK7011RCBEKEN.REG0x4C->bits.TESTPATTERN = 1; + + +#ifdef CALIBRATE_TIMES + if(gtx_gain_imb_cal_mode == TX_GAIN_IMB_CAL) + { + bk7011_set_tx_pa(gi_gain_tx_pa_dgainPA30, gi_gain_tx_pa_dgainbuf30, 3, 8); + } + else + { + bk7011_set_tx_pa(gi_gain_tx_loopback_pa_dgainPA30, gi_gain_tx_loopback_pa_dgainbuf30, 3, 8); + } + if (p_gbias_after_cal_array == NULL) + { + if(gtx_gain_imb_cal_mode == TX_GAIN_IMB_CAL) + { + CAL_TIM_PRT("\r\nbk7011_cal_tx_gain_imbalance\r\n"); + } + else + { + CAL_TIM_PRT("\r\nbk7011_cal_tx_loopback_gain_imbalance\r\n"); + } + + CAL_TIM_PRT("dgainPA30 = %d\r\n", BK7011TRX.REG0xC->bits.dgainPA30 ); //?? + CAL_TIM_PRT("dgainbuf30 =%d\r\n", BK7011TRX.REG0xC->bits.dgainbuf30); //?? + CAL_TIM_PRT("dgainpga = %d\r\n", BK7011TRX.REG0xC->bits.dgainpga ); //?? + CAL_TIM_PRT("gctrlmod30 = %d\r\n", BK7011TRX.REG0xB->bits.gctrlmod30); + } +#else + if(gtx_gain_imb_cal_mode == TX_GAIN_IMB_CAL) + { + bk7011_set_tx_pa(gi_gain_tx_pa_dgainPA30, gi_gain_tx_pa_dgainbuf30, 3, 8); + } + else + { + bk7011_set_tx_pa(gi_gain_tx_loopback_pa_dgainPA30, gi_gain_tx_loopback_pa_dgainbuf30, 3, 8); + } +#endif + + + BK7011TRX.REG0x0->bits.TSSIsel = 0; + BK7011TRX.REG0x0->bits.enDCcal = 0; + BK7011TRX.REG0x0->bits.tssi_statectrl = 1; + BK7011TRX.REG0x0->bits.tssi_selrange = 0; + BK7011TRX.REG0x0->bits.enIQcal = 1; + BK7011TRX.REG0x0->bits.enPcal = 0; +// BK7011TRX.REG0x0->bits.enPcaliGm = 0; + + BK7011TRX.REG0xF->bits.tssi_cal_en = 1; + BK7011TRX.REG0x0->value = 0x0001A24E;//0x00019041; + CAL_WR_TRXREGS(0x0); + CAL_WR_TRXREGS(0xC); + CAL_WR_TRXREGS(0xB); + CAL_WR_TRXREGS(0xF); + + if(gtx_gain_imb_cal_mode == TX_GAIN_IMB_CAL) + { + gtx_i_gain_comp = BK7011RCBEKEN.REG0x50->bits.TXIGAINCOMP; + gtx_q_gain_comp = BK7011RCBEKEN.REG0x50->bits.TXQGAINCOMP; + } + else + { + gtx_i_gain_comp_loopback = BK7011RCBEKEN.REG0x50->bits.TXIGAINCOMP; + gtx_q_gain_comp_loopback = BK7011RCBEKEN.REG0x50->bits.TXQGAINCOMP; + } + + cpu_delay(500); + detector_i_gain = bk7011_get_tx_i_gain(); + detector_q_gain = bk7011_get_tx_q_gain(); + + if(abs(detector_q_gain - detector_i_gain) < 3) + { + *val = 0; + if(gtx_gain_imb_cal_mode == TX_GAIN_IMB_CAL) + { + gtx_i_gain_comp = BK7011RCBEKEN.REG0x50->bits.TXIGAINCOMP; + gtx_q_gain_comp = BK7011RCBEKEN.REG0x50->bits.TXQGAINCOMP; + } + else + { + gtx_i_gain_comp_loopback = BK7011RCBEKEN.REG0x50->bits.TXIGAINCOMP; + gtx_q_gain_comp_loopback = BK7011RCBEKEN.REG0x50->bits.TXQGAINCOMP; + } + + return (BK7011RCBEKEN.REG0x50->bits.TXQGAINCOMP + (BK7011RCBEKEN.REG0x50->bits.TXIGAINCOMP << 16)); + } + + if(detector_i_gain > detector_q_gain) // TX_Q_GAIN_COMP NOT CHANGED + { + BK7011RCBEKEN.REG0x50->bits.TXQGAINCOMP = 1023; + low = 0; + BK7011RCBEKEN.REG0x50->bits.TXIGAINCOMP = low; + detector_i_gain = bk7011_get_tx_i_gain(); + detector_q_gain = bk7011_get_tx_q_gain(); + + detect_gain_low = abs(detector_i_gain - detector_q_gain); + + high = 1023; + BK7011RCBEKEN.REG0x50->bits.TXIGAINCOMP = high; + detector_i_gain = bk7011_get_tx_i_gain(); + detector_q_gain = bk7011_get_tx_q_gain(); + + detect_gain_high = abs(detector_i_gain - detector_q_gain); + do + { + if(detect_gain_low < detect_gain_high) + { + index = low; + high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x50->bits.TXIGAINCOMP = high; + detector_i_gain = bk7011_get_tx_i_gain(); + detector_q_gain = bk7011_get_tx_q_gain(); + detect_gain_high = abs(detector_i_gain - detector_q_gain); + } + else + { + index = high; + low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x50->bits.TXIGAINCOMP = low; + detector_i_gain = bk7011_get_tx_i_gain(); + detector_q_gain = bk7011_get_tx_q_gain(); + detect_gain_low = abs(detector_i_gain - detector_q_gain); + } + + } + while((high - low) > 1); + index = ((detect_gain_low < detect_gain_high) ? low : high); + BK7011RCBEKEN.REG0x50->bits.TXIGAINCOMP = index; + + if(gtx_gain_imb_cal_mode == TX_GAIN_IMB_CAL) + { + gtx_i_gain_comp = index; + } + else + { + gtx_i_gain_comp_loopback= index; + } + gold_index = (index << 16) + 1023; + } + else //// TX_I_GAIN_COMP NOT CHANGED + { + BK7011RCBEKEN.REG0x50->bits.TXIGAINCOMP = 1023; + low = 0; + BK7011RCBEKEN.REG0x50->bits.TXQGAINCOMP = low; + detector_i_gain = bk7011_get_tx_i_gain(); + detector_q_gain = bk7011_get_tx_q_gain(); + + detect_gain_low = abs(detector_i_gain - detector_q_gain); + + high = 1023; + BK7011RCBEKEN.REG0x50->bits.TXQGAINCOMP = high; + detector_i_gain = bk7011_get_tx_i_gain(); + detector_q_gain = bk7011_get_tx_q_gain(); + + detect_gain_high = abs(detector_i_gain - detector_q_gain); + do + { + if(detect_gain_low < detect_gain_high) + { + index = low; + high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x50->bits.TXQGAINCOMP = high; + detector_i_gain = bk7011_get_tx_i_gain(); + detector_q_gain = bk7011_get_tx_q_gain(); + detect_gain_high = abs(detector_i_gain - detector_q_gain); + } + else + { + index = high; + low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x50->bits.TXQGAINCOMP = low; + detector_i_gain = bk7011_get_tx_i_gain(); + detector_q_gain = bk7011_get_tx_q_gain(); + detect_gain_low = abs(detector_i_gain - detector_q_gain); + } + + } + while((high - low) > 1); + index = ((detect_gain_low < detect_gain_high) ? low : high); + BK7011RCBEKEN.REG0x50->bits.TXQGAINCOMP = index; + if(gtx_gain_imb_cal_mode == TX_GAIN_IMB_CAL) + { + gtx_q_gain_comp = index; + } + else + { + gtx_q_gain_comp_loopback= index; + } + gold_index += (1023 << 16) + index; + } + + *val = gold_index; + if(gtx_gain_imb_cal_mode == TX_GAIN_IMB_CAL) + { + CAL_WARN("gtx_i_gain_comp:%d\r\n", gtx_i_gain_comp); + CAL_WARN("gtx_q_gain_comp:%d\r\n", gtx_q_gain_comp); + } + + BK7011TRX.REG0x0->value = 0x00039042;// + CAL_WR_TRXREGS(0x0); + return gold_index; +} + + +static INT32 bk7011_cal_tx_ty2(INT32 tx_phase_comp) +{ + float ty1, ty1_sqr, ty2; + INT32 tx_ty2; + + ty1 = -1.0 * ((tx_phase_comp - 512) * (tx_phase_comp - 512)) / (1024.0 * 1024.0); + ty1_sqr = ty1 * ty1; + ty2 = 1 - ty1 / 2 + 3 * ty1_sqr / 8; + tx_ty2 = (INT32)((ty2 - 0.5) * 1024 + 0.5); + + return tx_ty2; +} + +INT32 bk7011_cal_tx_phase_imbalance(INT32 *val) +{ + INT32 detect_phase_low = 0; + INT32 detect_phase_high = 0; + INT16 high, low; + INT32 index = 0, gold_index = 0; + INT32 detector_i_phase; + INT32 detector_q_phase; + + if(gtx_phase_imb_cal_mode == TX_PHASE_IMB_CAL) + { + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = gtx_i_dc_comp; + BK7011RCBEKEN.REG0x4F->bits.TXQDCCOMP = gtx_q_dc_comp; + BK7011RCBEKEN.REG0x50->bits.TXIGAINCOMP = gtx_i_gain_comp; + BK7011RCBEKEN.REG0x50->bits.TXQGAINCOMP = gtx_q_gain_comp; + BK7011TRX.REG0xD->value = TRX_REG_0XD_TX_IQ_VAL;//BK7011TRXREG0xD;//0214 close the TX switch to ellimite the antenna infect + CAL_WR_TRXREGS(0xD); + } + else + { + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = gtx_i_dc_comp_loopback; + BK7011RCBEKEN.REG0x4F->bits.TXQDCCOMP = gtx_q_dc_comp_loopback; + BK7011RCBEKEN.REG0x50->bits.TXIGAINCOMP = gtx_i_gain_comp_loopback; + BK7011RCBEKEN.REG0x50->bits.TXQGAINCOMP = gtx_q_gain_comp_loopback; + BK7011TRX.REG0xD->value = TRX_REG_0XD_TX_LOOPBACK_IQ_VAL; + CAL_WR_TRXREGS(0xD); + } + + BK7011RCBEKEN.REG0x51->bits.TXPHASECOMP = 512; + BK7011RCBEKEN.REG0x51->bits.TXTY2 = 512; + + BK7011RCBEKEN.REG0x4C->bits.TESTPATTERN = 1; + +#ifdef CALIBRATE_TIMES + if(gtx_phase_imb_cal_mode == TX_PHASE_IMB_CAL) + { + bk7011_set_tx_pa(gi_gain_tx_pa_dgainPA30, gi_gain_tx_pa_dgainbuf30, 3, 8); + } + else + { + bk7011_set_tx_pa(gi_phase_tx_loopback_pa_dgainPA30, gi_phase_tx_loopback_pa_dgainbuf30,3, 8); + + } + + if (p_gbias_after_cal_array == NULL) + { + if(gtx_phase_imb_cal_mode == TX_PHASE_IMB_CAL) + { + CAL_TIM_PRT("\r\nbk7011_cal_tx_phase_imbalance: \r\n"); + } + else + { + CAL_TIM_PRT("\r\nbk7011_cal_tx_loopback_phase_imbalance: \r\n"); + + } + + CAL_TIM_PRT("dgainPA30 = %d\r\n", BK7011TRX.REG0xC->bits.dgainPA30 ); //?? + CAL_TIM_PRT("dgainbuf30 =%d\r\n", BK7011TRX.REG0xC->bits.dgainbuf30); //?? + CAL_TIM_PRT("dgainpga = %d\r\n", BK7011TRX.REG0xC->bits.dgainpga ); //?? + CAL_TIM_PRT("gctrlmod30 = %d\r\n", BK7011TRX.REG0xB->bits.gctrlmod30); + } +#else + if(gtx_phase_imb_cal_mode == TX_PHASE_IMB_CAL) + { + bk7011_set_tx_pa(gi_gain_tx_pa_dgainPA30, gi_gain_tx_pa_dgainbuf30, 3, 8); + } + else + { + bk7011_set_tx_pa(gi_phase_tx_loopback_pa_dgainPA30, gi_phase_tx_loopback_pa_dgainbuf30,3, 8); + + } +#endif + + + BK7011TRX.REG0x0->bits.TSSIsel = 0; + BK7011TRX.REG0x0->bits.enDCcal = 0; + BK7011TRX.REG0x0->bits.tssi_statectrl = 1; + BK7011TRX.REG0x0->bits.tssi_selrange = 1; + BK7011TRX.REG0x0->bits.enIQcal = 1; + BK7011TRX.REG0x0->bits.enPcal = 0; +// BK7011TRX.REG0x0->bits.enPcaliGm = 0; + BK7011TRX.REG0xF->bits.tssi_cal_en = 1; + BK7011TRX.REG0x0->value = 0x0001A24E;// + + CAL_WR_TRXREGS(0x0); + CAL_WR_TRXREGS(0xC); + CAL_WR_TRXREGS(0xB); + CAL_WR_TRXREGS(0xF); + + low = bk7011_cal_tx_ty2(512); + low = 1 + 256; + BK7011RCBEKEN.REG0x51->bits.TXPHASECOMP = low; + BK7011RCBEKEN.REG0x51->bits.TXTY2 = bk7011_cal_tx_ty2( low); + detector_i_phase = bk7011_get_tx_i_phase(); + detector_q_phase = bk7011_get_tx_q_phase(); + detect_phase_low = abs(detector_i_phase - detector_q_phase); + + high = 1023 - 256; + BK7011RCBEKEN.REG0x51->bits.TXPHASECOMP = high; + BK7011RCBEKEN.REG0x51->bits.TXTY2 = bk7011_cal_tx_ty2( high); + detector_i_phase = bk7011_get_tx_i_phase(); + detector_q_phase = bk7011_get_tx_q_phase(); + detect_phase_high = abs(detector_i_phase - detector_q_phase); + + do + { + if(detect_phase_low < detect_phase_high) + { + index = low; + high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x51->bits.TXPHASECOMP = high; + BK7011RCBEKEN.REG0x51->bits.TXTY2 = bk7011_cal_tx_ty2( high); + detector_i_phase = bk7011_get_tx_i_phase(); + detector_q_phase = bk7011_get_tx_q_phase(); + detect_phase_high = abs(detector_i_phase - detector_q_phase); + } + else + { + index = high; + low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x51->bits.TXPHASECOMP = low; + BK7011RCBEKEN.REG0x51->bits.TXTY2 = bk7011_cal_tx_ty2( low); + detector_i_phase = bk7011_get_tx_i_phase(); + detector_q_phase = bk7011_get_tx_q_phase(); + detect_phase_low = abs(detector_i_phase - detector_q_phase); + } + } + while((high - low) > 1); + index = ((detect_phase_low < detect_phase_high) ? low : high); + BK7011RCBEKEN.REG0x51->bits.TXPHASECOMP = index; + + if(gtx_phase_imb_cal_mode == TX_PHASE_IMB_CAL) + { + gtx_phase_comp = BK7011RCBEKEN.REG0x51->bits.TXPHASECOMP; + gtx_phase_ty2 = BK7011RCBEKEN.REG0x51->bits.TXTY2; + + CAL_WARN("gtx_phase_comp:%d\r\n", gtx_phase_comp); + CAL_WARN("gtx_phase_ty2:%d\r\n", gtx_phase_ty2); + } + else + { + gtx_phase_comp_loopback = BK7011RCBEKEN.REG0x51->bits.TXPHASECOMP; + gtx_phase_ty2_loopback = BK7011RCBEKEN.REG0x51->bits.TXTY2; + +#ifdef CALIBRATE_TIMES + if (p_gtx_phase_comp_temp_array != NULL) + { + p_gtx_phase_comp_temp_array[calibrate_time] = gtx_phase_comp_loopback; + } +#endif + + CAL_WARN("tx_phase_comp:%d\r\n", gtx_phase_comp_loopback); + CAL_WARN("tx_phase_ty2:%d\r\n", gtx_phase_ty2_loopback); + } + gold_index = index; + BK7011TRX.REG0x0->value = 0x00039042;// + CAL_WR_TRXREGS(0x0); + return gold_index; +} + + +static float bk7011_get_tx_filter_i_ratio(void) +{ + INT32 rx_avg_i_14M, rx_avg_i_500K; + float rx_avg_ratio; + BK7011RCBEKEN.REG0x4D->bits.TXSINF = 250; // 9.7MHz + cal_delay_100us(3*gst_rx_adc); + rx_avg_i_14M = bk7011_get_rx_i_avg_signed(); + BK7011RCBEKEN.REG0x4D->bits.TXSINF = 125; // 4.85MHz; + cal_delay_100us(3*gst_rx_adc); + rx_avg_i_500K = bk7011_get_rx_i_avg_signed(); +// if(rx_avg_i_14M > 0) + { + rx_avg_ratio = abs(1.0 * rx_avg_i_500K / rx_avg_i_14M - 1.36); + return rx_avg_ratio; + } +// else +// { +// return -1.0; +// } +} + + +static float bk7011_get_tx_filter_i_ratio1(void) +{ + int i; + INT32 rx_avg_i_14M_array[100], rx_avg_i_500K_array[100]; + INT32 rx_avg_i_14M = 0, rx_avg_i_500K = 0; + float rx_avg_ratio; + BK7011RCBEKEN.REG0x4D->bits.TXSINF = 250; // 9.7MHz 20180308 BY YIMING; + + cal_delay_100us(2*gst_rx_adc); + for (i=0; i<40; i++) + { + cal_delay_100us(gst_rx_adc); + rx_avg_i_14M_array[i] = bk7011_get_rx_i_avg_signed(); + rx_avg_i_14M += rx_avg_i_14M_array[i]; + } + BK7011RCBEKEN.REG0x4D->bits.TXSINF = 125; // 4.85MHz; + + cal_delay_100us(2*gst_rx_adc); + for (i=0; i<40; i++) + { + cal_delay_100us(gst_rx_adc); + rx_avg_i_500K_array[i] = bk7011_get_rx_i_avg_signed(); + rx_avg_i_500K += rx_avg_i_500K_array[i]; + } +// if(rx_avg_i_14M > 0) + { + rx_avg_ratio = abs(1.0 * rx_avg_i_500K / rx_avg_i_14M - 1.36); + return rx_avg_ratio; + } +// else +// { +// return -1.0; +// } +} + + +static float bk7011_get_tx_filter_q_ratio(void) +{ + INT32 rx_avg_q_14M = 0, rx_avg_q_500K = 0; + float rx_avg_ratio; + BK7011RCBEKEN.REG0x4D->bits.TXSINF = 250; // 9.7MHz; + cal_delay_100us(3*gst_rx_adc); + rx_avg_q_14M = bk7011_get_rx_q_avg_signed(); + BK7011RCBEKEN.REG0x4D->bits.TXSINF = 125; // 4.85MHz; + cal_delay_100us(3*gst_rx_adc); + rx_avg_q_500K = bk7011_get_rx_q_avg_signed(); +// if(rx_avg_i_14M > 0) + { + rx_avg_ratio = abs(1.0 * rx_avg_q_500K / rx_avg_q_14M - 1.36); + return rx_avg_ratio; + } +// else +// { +// return -1.0; +// } +} + +static float bk7011_get_tx_filter_q_ratio1(void) +{ + int i; + INT32 rx_avg_q_14M_array[100], rx_avg_q_500K_array[100]; + INT32 rx_avg_q_14M = 0, rx_avg_q_500K = 0; + float rx_avg_ratio; + BK7011RCBEKEN.REG0x4D->bits.TXSINF = 250; // 9.7MHz; + + cal_delay_100us(2*gst_rx_adc); + for (i=0; i<40; i++) + { + cal_delay_100us(gst_rx_adc); + rx_avg_q_14M_array[i] = bk7011_get_rx_q_avg_signed(); + rx_avg_q_14M += rx_avg_q_14M_array[i]; + } + BK7011RCBEKEN.REG0x4D->bits.TXSINF = 125; // 4.85MHz; + + cal_delay_100us(2*gst_rx_adc); + for (i=0; i<40; i++) + { + cal_delay_100us(gst_rx_adc); + rx_avg_q_500K_array[i] = bk7011_get_rx_q_avg_signed(); + rx_avg_q_500K += rx_avg_q_500K_array[i]; + } +// if(rx_avg_q_14M > 0) + { + rx_avg_ratio = abs(1.0 * rx_avg_q_500K / rx_avg_q_14M - 1.36); + return rx_avg_ratio; + } +// else +// { +// return -1.0; +// } +} + +extern int manual_cal_load_calimain_tag_from_flash(UINT32 tag, int *tag_addr, int tag_size); +INT32 bk7011_cal_tx_filter_corner(INT32 *val) +{ + int i; + float float_1 = 1100.00; + float float_2 = 1100.00; + float tx_avg_ratio_low = 0.0; + float tx_avg_ratio_high = 0.0; + INT16 high, low; + INT32 index = 0, gold_index = 0; + + do + { + int ret_i, tx_ifilter, ret_q, tx_qfilter; + + if(manual_cal_need_load_cmtag_from_flash() == 0) + { + break; + } + + ret_i = manual_cal_load_calimain_tag_from_flash(CM_TX_I_FILTER_CORNER, &tx_ifilter, sizeof(int)); + ret_q = manual_cal_load_calimain_tag_from_flash(CM_TX_Q_FILTER_CORNER, &tx_qfilter, sizeof(int)); + + if((ret_i == 1) && (ret_q == 1)) + { + // found in flash + CAL_WARN("gtx_ifilter_corner in flash: 0x%x\r\n", tx_ifilter); + CAL_WARN("gtx_qfilter_corner in flash: 0x%x\r\n", tx_qfilter); + } + else if((ret_i == 0) || (ret_q == 0)) + { + // tag not valid + break; + } + // ret < 0, means not found in flash + else if((ret_i == -1) || (ret_q == -1)) + { + // not tlv in flash + manual_set_cmtag(LOAD_FROM_CALI); + break; + } + else if((ret_i <= -2) || (ret_q <= -2)) + { + // has tlv, but no CALI_MAIN_TX tag + #if 1 + CM_SET_FLAG_BIT(CM_TX_I_FILTER_CORNER_FLAG); + CM_SET_FLAG_BIT(CM_TX_Q_FILTER_CORNER_FLAG); + break; + #else + tx_ifilter = 0xd; + tx_ifilter = 0xd; + CAL_FATAL("gtx_ifilter_corner default: 0x%x\r\n", tx_ifilter); + CAL_FATAL("gtx_qfilter_corner default: 0x%x\r\n", tx_qfilter); + #endif + } + + gtx_ifilter_corner = tx_ifilter; + gtx_qfilter_corner = tx_qfilter; + BK7011TRX.REG0x6->bits.lpfcapcali50 = gtx_ifilter_corner; + BK7011TRX.REG0x6->bits.lpfcapcalq50 = gtx_qfilter_corner; + CAL_WR_TRXREGS(0x6); + + return 0; + }while(0); + + BK7011TRX.REG0x6->bits.capcal_sel = 0; + CAL_WR_TRXREGS(0x6); + + BK7011RCBEKEN.REG0x1C->bits.FRXON = 1; + // I CAL + BK7011TRX.REG0x6->bits.lpfcapcali50 = 0x20; + BK7011TRX.REG0xD->value = 0xFC4E03B9;//BK7011TRXREG0xD;//0xE00F02B9;//0xFC4E03B9;// + CAL_WR_TRXREGS(0x6); + CAL_WR_TRXREGS(0xD); + + //12/10/2014 for D version + BK7011TRX.REG0x0->bits.tssi_statectrl = 1; + BK7011TRX.REG0xF->bits.tssi_cal_en = 0; + BK7011TRX.REG0xF->bits.sinad_rx_en = 0; + CAL_WR_TRXREGS(0x0); + CAL_WR_TRXREGS(0xF); + + + BK7011RCBEKEN.REG0x4C->bits.TESTPATTERN = 2; + BK7011RCBEKEN.REG0x4D->bits.TXSINMODE = 1; + BK7011RCBEKEN.REG0x4D->bits.TXSINAMP = 6; + BK7011RCBEKEN.REG0x3C->bits.RXDCCALEN = 1; + BK7011RCBEKEN.REG0x3C->bits.RXAVGMODE = 1; + + + //cpu_delay(gst_rx_adc); + + low = 0; + BK7011TRX.REG0x6->bits.lpfcapcali50 = low; + CAL_WR_TRXREGS(0x6); + + tx_avg_ratio_low = bk7011_get_tx_filter_i_ratio(); + + high = 63; + BK7011TRX.REG0x6->bits.lpfcapcali50 = high; + CAL_WR_TRXREGS(0x6); + + tx_avg_ratio_high = bk7011_get_tx_filter_i_ratio(); + + do + { + if(tx_avg_ratio_low < tx_avg_ratio_high) + { + index = low; + high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011TRX.REG0x6->bits.lpfcapcali50 = high; + CAL_WR_TRXREGS(0x6); + tx_avg_ratio_high = bk7011_get_tx_filter_i_ratio(); + } + else + { + index = high; + low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011TRX.REG0x6->bits.lpfcapcali50 = low; + CAL_WR_TRXREGS(0x6); + tx_avg_ratio_low = bk7011_get_tx_filter_i_ratio(); + } + } + while((high - low) > 1); + index = ((tx_avg_ratio_low < tx_avg_ratio_high) ? low : high); + gold_index = index << 8; +// gtx_ifilter_corner = index; + + for (i=0; i<5; i++) + { + if (((index - 2 + i) >= 0) && ((index - 2 + i) < 64)) + { + BK7011TRX.REG0x6->bits.lpfcapcali50 = index - 2 + i; + CAL_WR_TRXREGS(0x6); +#ifdef SCAN_IQ_FILTER_CORNER + index_test[i+calibrate_time*5] = index - 2 + i; +#endif + float_2 = bk7011_get_tx_filter_i_ratio1(); +#ifdef SCAN_IQ_FILTER_CORNER + float2_test[i+calibrate_time*5] = float_2; +#endif + if (float_1 > float_2) + { + float_1 = float_2; + gtx_ifilter_corner = index - 2 + i; + } +// if (gtx_ifilter_corner == 11) +// { +// gtx_ifilter_corner = 11; +// } + } + } + + +#ifdef SCAN_IQ_FILTER_CORNER + g_sctrl_bias_reg = sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_BIAS_REG_READ, &g_sctrl_bias_reg); + g_sctrl_bias_reg = (g_sctrl_bias_reg >> PARAM_LDO_VAL_MANUAL_POSI) & PARAM_LDO_VAL_MANUAL_MASK; + + + BK7011TRX.REG0x6->bits.lpfcapcali50 = gtx_ifilter_corner; + CAL_WR_TRXREGS(0x6); + + grx_avg_i_14M = 0; + for (i=0; i<8; i++) + { + grx_avg_i_14M += bk7011_get_rx_i_avg_signed(); + } + + grx_avg_i_14M2 = 0; + BK7011RCBEKEN.REG0x4D->bits.TXSINF = 255; // 14MHz; + for (i=0; i<8; i++) + { + cal_delay_100us(3*gst_rx_adc); + grx_avg_i_14M2 += bk7011_get_rx_i_avg_signed(); + } +#endif + + // Q CAL + BK7011TRX.REG0x6->bits.lpfcapcalq50 = 0x20; + BK7011TRX.REG0xD->value = 0xFC4E03B9;//BK7011TRXREG0xD;//0xE00F02B9;//0xFC4E03B9;// + CAL_WR_TRXREGS(0x6); + CAL_WR_TRXREGS(0xD); + + //12/10/2014 for D version + BK7011TRX.REG0x0->bits.tssi_statectrl = 1; + BK7011TRX.REG0xF->bits.tssi_cal_en = 0; + BK7011TRX.REG0xF->bits.sinad_rx_en = 0; + CAL_WR_TRXREGS(0x0); + CAL_WR_TRXREGS(0xF); + + + BK7011RCBEKEN.REG0x4C->bits.TESTPATTERN = 2; + BK7011RCBEKEN.REG0x4D->bits.TXSINMODE = 2; + BK7011RCBEKEN.REG0x4D->bits.TXSINAMP = 6; + BK7011RCBEKEN.REG0x3C->bits.RXDCCALEN = 1; + BK7011RCBEKEN.REG0x3C->bits.RXAVGMODE = 1; + + + //cpu_delay(gst_rx_adc); + + low = 0; + BK7011TRX.REG0x6->bits.lpfcapcalq50 = low; + CAL_WR_TRXREGS(0x6); + + tx_avg_ratio_low = bk7011_get_tx_filter_q_ratio(); + + high = 63; + BK7011TRX.REG0x6->bits.lpfcapcalq50 = high; + CAL_WR_TRXREGS(0x6); + + tx_avg_ratio_high = bk7011_get_tx_filter_q_ratio(); + + do + { + if(tx_avg_ratio_low < tx_avg_ratio_high) + { + index = low; + high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011TRX.REG0x6->bits.lpfcapcalq50 = high; + CAL_WR_TRXREGS(0x6); + tx_avg_ratio_high = bk7011_get_tx_filter_q_ratio(); + } + else + { + index = high; + low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011TRX.REG0x6->bits.lpfcapcalq50 = low; + CAL_WR_TRXREGS(0x6); + tx_avg_ratio_low = bk7011_get_tx_filter_q_ratio(); + } + } + while((high - low) > 1); + index = ((tx_avg_ratio_low < tx_avg_ratio_high) ? low : high); + gold_index += index; +// gtx_qfilter_corner = index; + + float_1 = 1100; + for (i=0; i<5; i++) + { + if (((index - 2 + i) >= 0) && ((index - 2 + i) < 64)) + { + BK7011TRX.REG0x6->bits.lpfcapcalq50 = index - 2 + i; + CAL_WR_TRXREGS(0x6); + float_2 = bk7011_get_tx_filter_q_ratio1(); + if (float_1 > float_2) + { + float_1 = float_2; + gtx_qfilter_corner = index - 2 + i; + } + } + } + +#ifdef SCAN_IQ_FILTER_CORNER + + BK7011TRX.REG0x6->bits.lpfcapcalq50 = gtx_qfilter_corner; + CAL_WR_TRXREGS(0x6); + + grx_avg_q_14M = bk7011_get_rx_q_avg_signed(); + + + BK7011RCBEKEN.REG0x4D->bits.TXSINF = 255; // 14MHz; + cal_delay_100us(3*gst_rx_adc); + grx_avg_q_14M2 = bk7011_get_rx_q_avg_signed(); +#endif + + + // Q CAL + /* 20170504 iq used same value + + BK7011TRX.REG0x6->bits.lpfcapcalq50 = 0x20; + BK7011TRX.REG0xD->value = 0xFC4E03B9;//BK7011TRXREG0xD; + CAL_WR_TRXREGS(0x6); + CAL_WR_TRXREGS(0xD); + + //12/10/2014 for D version + BK7011TRX.REG0xF->bits.tssicalen = 0; + BK7011TRX.REG0xF->bits.sinadrxen = 0; + CAL_WR_TRXREGS(0xF); + + BK7011RCBEKEN.REG0x4C->bits.TESTPATTERN = 2; + BK7011RCBEKEN.REG0x4D->bits.TXSINMODE = 2; + BK7011RCBEKEN.REG0x4D->bits.TXSINAMP = 4; + BK7011RCBEKEN.REG0x3C->bits.RXDCCALEN = 1; + BK7011RCBEKEN.REG0x3C->bits.RXAVGMODE = 1; + + low = 0; + BK7011TRX.REG0x6->bits.lpfcapcalq50 = low; + CAL_WR_TRXREGS(0x6); + + tx_avg_ratio_low = bk7011_get_tx_filter_q_ratio(); + + high = 63; + BK7011TRX.REG0x6->bits.lpfcapcalq50 = high; + CAL_WR_TRXREGS(0x6); + + tx_avg_ratio_high = bk7011_get_tx_filter_q_ratio(); + + do + { + if(tx_avg_ratio_low < tx_avg_ratio_high) + { + index = low; + high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011TRX.REG0x6->bits.lpfcapcalq50 = high; + CAL_WR_TRXREGS(0x6); + + tx_avg_ratio_high = bk7011_get_tx_filter_q_ratio(); + } + else + { + index = high; + low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011TRX.REG0x6->bits.lpfcapcalq50 = low; + CAL_WR_TRXREGS(0x6); + + tx_avg_ratio_low = bk7011_get_tx_filter_q_ratio(); + } + } + while((high - low) > 1); + index = ((tx_avg_ratio_low < tx_avg_ratio_high) ? low : high); + gold_index += index; + gtx_qfilter_corner = index;//((index + ((gold_index & 0x0000ff00)>>8))>>1); + +*/ + BK7011TRX.REG0x6->bits.lpfcapcali50 = gtx_ifilter_corner; + BK7011TRX.REG0x6->bits.lpfcapcalq50 = gtx_qfilter_corner;//160405 iq used same value + //gtx_qfilter_corner = gtx_ifilter_corner; + CAL_WARN("gtx_ifilter_corner over: 0x%x\r\n", gtx_ifilter_corner); + CAL_WARN("gtx_qfilter_corner over: 0x%x\r\n", gtx_qfilter_corner); + + //BK7011TRX.REG0x6->bits.lpfcapcalq50 = gtx_qfilter_corner; + CAL_WR_TRXREGS(0x6); + + *val = gold_index; + return (gold_index); +} + +void bk7011_rx_cal_en(void) +{ + BK7011RCBEKEN.REG0x3E->bits.RXCOMPEN = 0; + + BK7011RCBEKEN.REG0x1C->bits.FRXON = 1; + BK7011RCBEKEN.REG0x1C->bits.FTXON = 0; + + BK7011RCBEKEN.REG0x0->bits.forceenable = 1; + cpu_delay(1); + BK7011RCBEKEN.REG0x19->bits.FCH0SHDN = 1; + BK7011RCBEKEN.REG0x19->bits.FCH0TXEN = 0; + BK7011RCBEKEN.REG0x19->bits.FCH0RXEN = 1; + BK7011RCBEKEN.REG0x19->bits.FCH0EN = 1; + + // ADC clock change to 80M + BK7011TRX.REG0xF->bits.clkadc_sel = 0;//20170331 1 --> 0 + CAL_WR_TRXREGS(0xF); + + BK7011TRX.REG0x12->bits.adcrefbwsel = 0;//20170331 1-->0 + CAL_WR_TRXREGS(0x12); +} + +INT32 bk7011_cal_rx_dc(void) +{ + INT32 index = 0; + INT32 i, j, k, t, curr, value; + UINT32 rx_dc_gain_tab_temp[8]; + UINT32 rx_dc_gain_tab_temp1[8]; + + + /*step 2*/ + BK7011RCBEKEN.REG0x3C->bits.RXDCCALEN = 1; + BK7011RCBEKEN.REG0x3C->bits.RXAVGMODE = 0; + BK7011RCBEKEN.REG0x19->bits.FCH0RXHP = 0; //huaming.jiang 20141017 + BK7011RCBEKEN.REG0x1C->bits.FTXON = 0; + BK7011RCBEKEN.REG0x1C->bits.FRXON = 1; + + + BK7011TRX.REG0x5->bits.chspi = 0x0;//2400MHz, 20181120 from 0x64 to 0x0; + CAL_WR_TRXREGS(0x5); + delay100us(1);//delay 100us for RFPLL + + BK7011TRX.REG0xE->value = 0xDA01BCF0; /// D801BCF0;//170217 + CAL_WR_TRXREGS(0xE); + + for(i = 0; i < 16; i ++) + { + BK7011RCBEKEN.REG0x19->bits.FCH0B = (0x70 | i); + for(j = 0; j < 2; j ++) + { + index = 128; + k = 6; + do + { + //set dc offset + value = (*((volatile unsigned long *)(TRX_BEKEN_BASE + (0x14 + i / 2) * 4))); + curr = ~(0xff << (16 * (i % 2) + 8 * j)); + value &= curr; + curr = (index << (16 * (i % 2) + 8 * j)); + value |= curr; + (*((volatile unsigned long *)(TRX_BEKEN_BASE + (0x14 + i / 2) * 4))) = value; + while(BK7011RCBEKEN.REG0x1->value & 0xfffffff); + cal_delay_100us(gst_rx_adc); + + //read dc avg, and calc mean + value = 0; + for(t = 0; t < 10; t ++) + { + if(j == 0) curr = BK7011RCBEKEN.REG0x3C->bits.RXAVGIRD; + else curr = BK7011RCBEKEN.REG0x3C->bits.RXAVGQRD; + if(curr >= 2048) curr -= 4096; + value += curr; + cpu_delay(100); + } + curr = value / 10; + + //calc new dc offset + if(curr > 0) index += (0x1 << k); + else index -= (0x1 << k); + k --; + } + while((k >= 0) && ((curr >= 16) || (curr <= -16))); + if(k < 0) + { + value = (*((volatile unsigned long *)(TRX_BEKEN_BASE + (0x14 + i / 2) * 4))); + curr = ~(0xff << (16 * (i % 2) + 8 * j)); + value &= curr; + curr = (index << (16 * (i % 2) + 8 * j)); + value |= curr; + (*((volatile unsigned long *)(TRX_BEKEN_BASE + (0x14 + i / 2) * 4))) = value; + while(BK7011RCBEKEN.REG0x1->value & 0xfffffff); + } + } + } + + rx_dc_gain_tab_temp[0] = BK7011TRXONLY.REG0x14->value; + rx_dc_gain_tab_temp[1] = BK7011TRXONLY.REG0x15->value; + rx_dc_gain_tab_temp[2] = BK7011TRXONLY.REG0x16->value; + rx_dc_gain_tab_temp[3] = BK7011TRXONLY.REG0x17->value; + rx_dc_gain_tab_temp[4] = BK7011TRXONLY.REG0x18->value; + rx_dc_gain_tab_temp[5] = BK7011TRXONLY.REG0x19->value; + rx_dc_gain_tab_temp[6] = BK7011TRXONLY.REG0x1A->value; + rx_dc_gain_tab_temp[7] = BK7011TRXONLY.REG0x1B->value; + + BK7011TRX.REG0x5->bits.chspi = 0x55;//2485MHz; + CAL_WR_TRXREGS(0x5); + delay100us(1);//delay 100us for RFPLL + + BK7011TRX.REG0xE->value = 0xDA01BCF0; /// D801BCF0;//170217 + CAL_WR_TRXREGS(0xE); + + for(i = 0; i < 16; i ++) + { + BK7011RCBEKEN.REG0x19->bits.FCH0B = (0x70 | i); + for(j = 0; j < 2; j ++) + { + index = 128; + k = 6; + do + { + //set dc offset + value = (*((volatile unsigned long *)(TRX_BEKEN_BASE + (0x14 + i / 2) * 4))); + curr = ~(0xff << (16 * (i % 2) + 8 * j)); + value &= curr; + curr = (index << (16 * (i % 2) + 8 * j)); + value |= curr; + (*((volatile unsigned long *)(TRX_BEKEN_BASE + (0x14 + i / 2) * 4))) = value; + while(BK7011RCBEKEN.REG0x1->value & 0xfffffff); + cal_delay_100us(gst_rx_adc); + + //read dc avg, and calc mean + value = 0; + for(t = 0; t < 10; t ++) + { + if(j == 0) curr = BK7011RCBEKEN.REG0x3C->bits.RXAVGIRD; + else curr = BK7011RCBEKEN.REG0x3C->bits.RXAVGQRD; + if(curr >= 2048) curr -= 4096; + value += curr; + cpu_delay(100); + } + curr = value / 10; + + //calc new dc offset + if(curr > 0) index += (0x1 << k); + else index -= (0x1 << k); + k --; + } + while((k >= 0) && ((curr >= 16) || (curr <= -16))); + if(k < 0) + { + value = (*((volatile unsigned long *)(TRX_BEKEN_BASE + (0x14 + i / 2) * 4))); + curr = ~(0xff << (16 * (i % 2) + 8 * j)); + value &= curr; + curr = (index << (16 * (i % 2) + 8 * j)); + value |= curr; + (*((volatile unsigned long *)(TRX_BEKEN_BASE + (0x14 + i / 2) * 4))) = value; + while(BK7011RCBEKEN.REG0x1->value & 0xfffffff); + } + } + } + + rx_dc_gain_tab_temp1[0] = BK7011TRXONLY.REG0x14->value; + rx_dc_gain_tab_temp1[1] = BK7011TRXONLY.REG0x15->value; + rx_dc_gain_tab_temp1[2] = BK7011TRXONLY.REG0x16->value; + rx_dc_gain_tab_temp1[3] = BK7011TRXONLY.REG0x17->value; + rx_dc_gain_tab_temp1[4] = BK7011TRXONLY.REG0x18->value; + rx_dc_gain_tab_temp1[5] = BK7011TRXONLY.REG0x19->value; + rx_dc_gain_tab_temp1[6] = BK7011TRXONLY.REG0x1A->value; + rx_dc_gain_tab_temp1[7] = BK7011TRXONLY.REG0x1B->value; + + for (i=0; i<8; i++) + { + g_rx_dc_gain_tab[i] = ((((rx_dc_gain_tab_temp[i] & 0x000000FF) + (rx_dc_gain_tab_temp1[i] & 0x000000FF)) / 2) & 0x000000FF) + | ((((rx_dc_gain_tab_temp[i] & 0x0000FF00) + (rx_dc_gain_tab_temp1[i] & 0x0000FF00)) / 2) & 0x0000FF00) + | ((((rx_dc_gain_tab_temp[i] & 0x00FF0000) + (rx_dc_gain_tab_temp1[i] & 0x00FF0000)) / 2) & 0x00FF0000) + | ((((((rx_dc_gain_tab_temp[i] >> 8) & 0x00FF0000) + ((rx_dc_gain_tab_temp1[i] >> 8) & 0x00FF0000)) / 2) & 0x00FF0000) << 8); + } + + BK7011TRXONLY.REG0x14->value = g_rx_dc_gain_tab[0]; + CAL_WR_TRXREGS(0x14); + BK7011TRXONLY.REG0x15->value = g_rx_dc_gain_tab[1]; + CAL_WR_TRXREGS(0x15); + BK7011TRXONLY.REG0x16->value = g_rx_dc_gain_tab[2]; + CAL_WR_TRXREGS(0x16); + BK7011TRXONLY.REG0x17->value = g_rx_dc_gain_tab[3]; + CAL_WR_TRXREGS(0x17); + BK7011TRXONLY.REG0x18->value = g_rx_dc_gain_tab[4]; + CAL_WR_TRXREGS(0x18); + BK7011TRXONLY.REG0x19->value = g_rx_dc_gain_tab[5]; + CAL_WR_TRXREGS(0x19); + BK7011TRXONLY.REG0x1A->value = g_rx_dc_gain_tab[6]; + CAL_WR_TRXREGS(0x1A); + BK7011TRXONLY.REG0x1B->value = g_rx_dc_gain_tab[7]; + CAL_WR_TRXREGS(0x1B); + + + + CAL_WARN("g_rx_dc_gain_tab 0 over: 0x%x\r\n", g_rx_dc_gain_tab[0]); + CAL_WARN("g_rx_dc_gain_tab 1 over: 0x%x\r\n", g_rx_dc_gain_tab[1]); + CAL_WARN("g_rx_dc_gain_tab 2 over: 0x%x\r\n", g_rx_dc_gain_tab[2]); + CAL_WARN("g_rx_dc_gain_tab 3 over: 0x%x\r\n", g_rx_dc_gain_tab[3]); + CAL_WARN("g_rx_dc_gain_tab 4 over: 0x%x\r\n", g_rx_dc_gain_tab[4]); + CAL_WARN("g_rx_dc_gain_tab 5 over: 0x%x\r\n", g_rx_dc_gain_tab[5]); + CAL_WARN("g_rx_dc_gain_tab 6 over: 0x%x\r\n", g_rx_dc_gain_tab[6]); + CAL_WARN("g_rx_dc_gain_tab 7 over: 0x%x\r\n", g_rx_dc_gain_tab[7]); + + BK7011RCBEKEN.REG0x3C->bits.RXDCCALEN = 0; + +// BK7011TRX.REG0x7->bits.chin60 = 0xc; +// CAL_WR_TRXREGS(0x7); + BK7011TRX.REG0x5->bits.chspi = 0xc; + CAL_WR_TRXREGS(0x5); + delay100us(1);//delay 100us for RFPLL + + return 0; + (void)t; +} + +INT32 bk7011_cal_rx_iq(INT32 *val) +{ + // INT32 rx_dc_i_rd, rx_dc_q_rd; + INT32 rx_amp_err_rd, rx_phase_err_rd, rx_ty2_rd; + INT32 rx_amp_err_wr; + INT32 rx_phase_err_wr; + float amp_err, phase_err, ty2_err; + INT32 gold_index = 0; + INT32 i, curr, value, value1, value2; + //bk7011_load_rxiq_init_cfg(); //v1.5 + + do + { + int ret_i, tx_ifilter, ret_q, tx_qfilter; + + if(manual_cal_need_load_cmtag_from_flash() == 0) + { + break; + } + + ret_i = manual_cal_load_calimain_tag_from_flash(CM_RX_AMP_ERR_WR, &rx_amp_err_wr, sizeof(int)); + ret_q = manual_cal_load_calimain_tag_from_flash(CM_RX_PHASE_ERR_WR, &rx_phase_err_wr, sizeof(int)); + + if((ret_i == 1) && (ret_q == 1)) + { + // found in flash + CAL_WARN("grx_amp_err_wr in flash: 0x%x\r\n", rx_amp_err_wr); + CAL_WARN("grx_phase_err_wr in flash: 0x%x\r\n", rx_phase_err_wr); + } + else if((ret_i == 0) || (ret_q == 0)) + { + // tag not valid + break; + } + // ret < 0, means not found in flash + else if((ret_i == -1) || (ret_q == -1)) + { + // not tlv in flash + manual_set_cmtag(LOAD_FROM_CALI); + break; + } + else if((ret_i <= -2) || (ret_q <= -2)) + { + // has tlv, but no CALI_MAIN_TX tag + CM_SET_FLAG_BIT(CM_RX_AMP_ERR_WR_FLAG); + CM_SET_FLAG_BIT(CM_RX_PHASE_ERR_WR_FLAG); + break; + } + + grx_amp_err_wr = rx_amp_err_wr; + grx_phase_err_wr = rx_phase_err_wr; + BK7011RCBEKEN.REG0x42->bits.RXAMPERRWR = rx_amp_err_wr; + BK7011RCBEKEN.REG0x42->bits.RXPHASEERRWR = rx_phase_err_wr; + + return 0; + (void)tx_qfilter; + (void)tx_ifilter; + }while(0); + + /*step 1*/ + BK7011RCBEKEN.REG0x1C->bits.FRXON = 1; + BK7011RCBEKEN.REG0x1C->bits.FTXON = 1; + + //BK7011ADDAMAP.REG0x5->bits.vc40 = 0x1f; + //BK7011ADDA.REG0x5->value = BK7011ADDAMAP.REG0x5->value; + + BK7011TRX.REG0x0->bits.tssi_statectrl = 1; + BK7011TRX.REG0xF->bits.tssi_cal_en = 0; + BK7011TRX.REG0xF->bits.sinad_rx_en = 0; + CAL_WR_TRXREGS(0x0); + CAL_WR_TRXREGS(0xF); + +#if 0 + BK7011TRX.REG0x9->bits.grxi2vspi10 = 1; //12dB + BK7011TRX.REG0x9->bits.agcrxfeEn = 0; //disable agc + + BK7011TRX.REG0x7->bits.autorxifgen = 0;//disable agc + BK7011TRX.REG0x7->bits.spilpfrxg30 = 0x0a; //33dB; + + //BK7011TRX.REG0x7->bits.digdcoen = 0; + CAL_WR_TRXREGS(0x7); + CAL_WR_TRXREGS(0x9); +#endif + + BK7011TRX.REG0xE->value = TRX_REG_0XE_RXIQ_VAL; + CAL_WR_TRXREGS(0xE); + //BK7011TRX.REG0xC->value = TRX_REG_0XC_RXIQ_VAL; + bk7011_set_tx_pa(gi_cal_rx_iq_pa_dgainPA30, gi_cal_rx_iq_pa_dgainbuf30, 4, 4); + + BK7011RCBEKEN.REG0x19->bits.FCH0B = 0x1a;//decrease 6dB + + + /*searching...*/ + BK7011RCBEKEN.REG0x3E->bits.RXCALEN = 1; + BK7011RCBEKEN.REG0x4C->bits.TESTPATTERN = 2; + BK7011RCBEKEN.REG0x4D->bits.TXSINMODE = 0; + BK7011RCBEKEN.REG0x4D->bits.TXSINAMP = 0x04; // increase 6dB + //BK7011RCBEKEN.REG0x3C->bits.RXAVGMODE = 0; + //BK7011RCBEKEN.REG0x3C->bits.RXDCCALEN = 1; + BK7011RCBEKEN.REG0x4D->bits.TXSINF = 179; // 7MHz; + cal_delay_100us(6*gst_rx_adc); + cpu_delay(500 * DELAY1US); + + //rx_dc_i_rd = BK7011RCBEKEN.REG0x3C->bits.RXAVGIRD; + //rx_dc_q_rd = BK7011RCBEKEN.REG0x3C->bits.RXAVGQRD; + + BK7011RCBEKEN.REG0x41->bits.RXDCIWR = 0x0; + BK7011RCBEKEN.REG0x41->bits.RXDCQWR = 0x0; + + //BK7011RCBEKEN.REG0x3C->bits.RXAVGMODE = 1; + //BK7011RCBEKEN.REG0x3C->bits.RXDCCALEN = 0; + + value = 0; + value1 = 0; + value2 = 0; + for(i = 0; i < 2; i ++) + { + curr = BK7011RCBEKEN.REG0x3F->bits.RXAMPERRRD; + value += curr - ((curr < 512) ? 0: 1024); + curr = BK7011RCBEKEN.REG0x3F->bits.RXPHASEERRRD; + value1 += curr - ((curr < 512) ? 0: 1024); + curr = BK7011RCBEKEN.REG0x40->bits.RXTY2RD; + value2 += curr - ((curr < 512) ? 0: 1024); + cpu_delay(gst_rx_adc); + } + rx_amp_err_rd = value / 2; + rx_phase_err_rd = value1 / 2; + rx_ty2_rd = value2 / 2; +/* rx_amp_err_rd = value; + rx_phase_err_rd = value1; + rx_ty2_rd = value2;*/ + + +#ifdef CALIBRATE_TIMES // by gwf + if (p_rx_amp_err_rd_array != NULL) + { + int rx_amp_err_rd_temp; + int rx_phase_err_rd_temp; + int rx_ty2_rd_temp; + if (rx_amp_err_rd & 0x200) + { + rx_amp_err_rd_temp = rx_amp_err_rd | 0xFFFFFC00; + } + else + { + rx_amp_err_rd_temp = rx_amp_err_rd & 0x000003FF; + } + if (rx_phase_err_rd & 0x200) + { + rx_phase_err_rd_temp = rx_phase_err_rd | 0xFFFFFC00; + } + else + { + rx_phase_err_rd_temp = rx_phase_err_rd & 0x000003FF; + } + if (rx_ty2_rd & 0x200) + { + rx_ty2_rd_temp = rx_ty2_rd | 0xFFFFFC00; + } + else + { + rx_ty2_rd_temp = rx_ty2_rd & 0x000003FF; + } + p_rx_amp_err_rd_array[calibrate_time] = rx_amp_err_rd_temp; + p_rx_phase_err_rd_array[calibrate_time] = rx_phase_err_rd_temp; + p_rx_ty2_rd_array[calibrate_time] = rx_ty2_rd_temp; +// printf("rx_amp_err_rd = %d %d\r\n", rx_amp_err_rd, rx_amp_err_rd_temp); +// printf("rx_phase_err_rd = %d %d\r\n", rx_phase_err_rd, rx_phase_err_rd_temp); + } + else +#endif + { + CAL_FATAL("[rx_iq]rx_amp_err_rd: 0x%03x\r\n", rx_amp_err_rd ); + CAL_FATAL("[rx_iq]rx_phase_err_rd: 0x%03x\r\n", rx_phase_err_rd ); + CAL_FATAL("[rx_iq]rx_ty2_rd: 0x%03x\r\n", rx_ty2_rd ); + } + + amp_err = 1.0 * rx_amp_err_rd / 1024; + phase_err = 1.0 * rx_phase_err_rd / 1024; + ty2_err = 1.0 * rx_ty2_rd / 1024; + + + //rx_amp_err_wr = (INT32) (512 * (ty2_err + 1) / (amp_err + 1) + 0.5); + //rx_phase_err_wr = (INT32) (512 * phase_err * (ty2_err + 1) + 0.5); + rx_amp_err_wr = (INT32) (512 * (ty2_err + 1) / (amp_err + 1)); + rx_phase_err_wr = (INT32) (512 * phase_err * (ty2_err + 1)); + + BK7011RCBEKEN.REG0x42->bits.RXPHASEERRWR = rx_phase_err_wr; + BK7011RCBEKEN.REG0x42->bits.RXAMPERRWR = rx_amp_err_wr; + BK7011RCBEKEN.REG0x3E->bits.RXCOMPEN = 1; + BK7011RCBEKEN.REG0x3E->bits.RXCALEN = 0; + + grx_amp_err_wr = rx_amp_err_wr; + grx_phase_err_wr = rx_phase_err_wr; + + CAL_WARN("grx_amp_err_wr:0x%03x\r\n", grx_amp_err_wr); + CAL_WARN("grx_phase_err_wr:0x%03x\r\n", grx_phase_err_wr); + + gold_index = (rx_amp_err_wr << 16 ) + rx_phase_err_wr; + *val = gold_index; + + BK7011TRX.REG0x9->bits.agcrxfeEn = 1; //enable agc + BK7011TRX.REG0x7->bits.autorxifgen = 1;//ensable agc + CAL_WR_TRXREGS(0x7); + CAL_WR_TRXREGS(0x9); + + return gold_index; +} + +void bk7011_set_rx_avg_dc(void) +{ + INT32 rx_dc_i_rd, rx_dc_q_rd; + + BK7011RCBEKEN.REG0x3E->bits.RXCOMPEN = 0; + BK7011RCBEKEN.REG0x3C->bits.RXAVGMODE = 0; + BK7011RCBEKEN.REG0x3C->bits.RXDCCALEN = 1; + cal_delay_100us(gst_rx_adc); + BK7011RCBEKEN.REG0x3C->bits.RXDCCALEN = 0; + + rx_dc_i_rd = BK7011RCBEKEN.REG0x3C->bits.RXAVGIRD; + rx_dc_q_rd = BK7011RCBEKEN.REG0x3C->bits.RXAVGQRD; + BK7011RCBEKEN.REG0x41->bits.RXDCIWR = rx_dc_i_rd; + BK7011RCBEKEN.REG0x41->bits.RXDCQWR = rx_dc_q_rd; + + BK7011RCBEKEN.REG0x3E->bits.RXCOMPEN = 1; + + return; +} + +INT32 bk7011_load_calibration_cfg(void) +{ + BK7011RCBEKEN.REG0x0->value = BK7011RCBEKEN.REG0x0->value; + BK7011RCBEKEN.REG0x1->value = BK7011RCBEKEN.REG0x1->value; + BK7011RCBEKEN.REG0x5->value = BK7011RCBEKEN.REG0x5->value ; + BK7011RCBEKEN.REG0x8->value = BK7011RCBEKEN.REG0x8->value; + BK7011RCBEKEN.REG0xB->value = BK7011RCBEKEN.REG0xB->value; + BK7011RCBEKEN.REG0x11->value = BK7011RCBEKEN.REG0x11->value; + BK7011RCBEKEN.REG0x19->value = BK7011RCBEKEN.REG0x19->value; + BK7011RCBEKEN.REG0x1E->value = BK7011RCBEKEN.REG0x1E->value; + + /**********NEW ADDED************/ + BK7011RCBEKEN.REG0x3C->value = BK7011RCBEKEN.REG0x3C->value; + BK7011RCBEKEN.REG0x3E->value = BK7011RCBEKEN.REG0x3E->value; + BK7011RCBEKEN.REG0x3F->value = BK7011RCBEKEN.REG0x3F->value; + BK7011RCBEKEN.REG0x40->value = BK7011RCBEKEN.REG0x40->value; + BK7011RCBEKEN.REG0x41->value = BK7011RCBEKEN.REG0x41->value; + BK7011RCBEKEN.REG0x42->value = BK7011RCBEKEN.REG0x42->value ; + BK7011RCBEKEN.REG0x4C->value = BK7011RCBEKEN.REG0x4C->value; + BK7011RCBEKEN.REG0x4D->value = BK7011RCBEKEN.REG0x4D->value; + BK7011RCBEKEN.REG0x4F->value = BK7011RCBEKEN.REG0x4F->value; + BK7011RCBEKEN.REG0x50->value = BK7011RCBEKEN.REG0x50->value; + BK7011RCBEKEN.REG0x51->value = BK7011RCBEKEN.REG0x51->value; + BK7011RCBEKEN.REG0x52->value = BK7011RCBEKEN.REG0x52->value; + BK7011RCBEKEN.REG0x54->value = BK7011RCBEKEN.REG0x54->value; + BK7011RCBEKEN.REG0x5C->value = BK7011RCBEKEN.REG0x5C->value; + + while(BK7011RCBEKEN.REG0x1->value & 0x0FFFFFFF) + { + cpu_delay(1); + } + BK7011TRXONLY.REG0x0->value = grc_reg_map[0]; + BK7011TRXONLY.REG0x1->value = grc_reg_map[1]; + BK7011TRXONLY.REG0x2->value = grc_reg_map[2]; + BK7011TRXONLY.REG0x3->value = grc_reg_map[3]; + BK7011TRXONLY.REG0x4->value = grc_reg_map[4]; + BK7011TRXONLY.REG0x6->value = grc_reg_map[6]; + BK7011TRXONLY.REG0x7->value = grc_reg_map[7]; + BK7011TRXONLY.REG0x8->value = grc_reg_map[8]; + BK7011TRXONLY.REG0x9->value = grc_reg_map[9]; + BK7011TRXONLY.REG0xA->value = grc_reg_map[10]; + BK7011TRXONLY.REG0xB->value = grc_reg_map[11]; + BK7011TRXONLY.REG0xC->value = grc_reg_map[12]; + BK7011TRXONLY.REG0xD->value = grc_reg_map[13]; + BK7011TRXONLY.REG0xE->value = grc_reg_map[14]; + BK7011TRXONLY.REG0x11->value = grc_reg_map[17]; + BK7011TRXONLY.REG0x12->value = grc_reg_map[18]; + BK7011TRXONLY.REG0x13->value = grc_reg_map[19]; + BK7011TRXONLY.REG0x14->value = grc_reg_map[20]; + BK7011TRXONLY.REG0x15->value = grc_reg_map[21]; + BK7011TRXONLY.REG0x16->value = grc_reg_map[22]; + BK7011TRXONLY.REG0x17->value = grc_reg_map[23]; + BK7011TRXONLY.REG0x18->value = grc_reg_map[24]; + BK7011TRXONLY.REG0x19->value = grc_reg_map[25]; + BK7011TRXONLY.REG0x1A->value = grc_reg_map[26]; + BK7011TRXONLY.REG0x1B->value = grc_reg_map[27]; + + while(BK7011RCBEKEN.REG0x1->value & 0x0FFFFFFF) + { + cpu_delay(1); + } + + BK7011TRX.REG0x7->bits.autorxifgen = 0; + BK7011TRX.REG0x7->bits.dig_dcoen = 0; + BK7011TRX.REG0x7->bits.spilpfrxg30 = 6; + CAL_WR_TRXREGS(0x7); + + BK7011TRX.REG0x6->bits.lpfcapcali50 = gtx_ifilter_corner; + BK7011TRX.REG0x6->bits.lpfcapcalq50 = gtx_qfilter_corner; + CAL_WR_TRXREGS(0x6); + + bk7011_set_rx_avg_dc(); // 11/11/2014 + + return 0; +} + +void bk7011_set_tx_after_cal(void) +{ + BK7011RCBEKEN.REG0x0->bits.forceenable = 0; + cpu_delay(1); + BK7011RCBEKEN.REG0x19->bits.FCH0EN = 1; + BK7011RCBEKEN.REG0x19->bits.FCH0SHDN = 1; + BK7011RCBEKEN.REG0x19->bits.FCH0RXEN = 0; + BK7011RCBEKEN.REG0x19->bits.FCH0TXEN = 1; + BK7011RCBEKEN.REG0x1C->bits.FRXON = 0; + BK7011RCBEKEN.REG0x1C->bits.FTXON = 1; + BK7011RCBEKEN.REG0x4C->bits.TESTPATTERN = 0; +#if DIFFERENCE_PIECES_CFG + BK7011RCBEKEN.REG0x0->bits.ch0en = 0; +#endif + //BK7011ICU.REG0x1->bits.txon = 1; + //BK7011ICU.REG0x1->bits.rxon = 0; +} + +void bk7011_set_rx_after_cal(void) +{ + BK7011RCBEKEN.REG0x0->bits.forceenable = 0; + cpu_delay(1); + BK7011RCBEKEN.REG0x19->bits.FCH0EN = 1; + BK7011RCBEKEN.REG0x19->bits.FCH0SHDN = 1; + BK7011RCBEKEN.REG0x19->bits.FCH0RXEN = 1; + BK7011RCBEKEN.REG0x19->bits.FCH0TXEN = 0; + BK7011RCBEKEN.REG0x1C->bits.FRXON = 1; + BK7011RCBEKEN.REG0x1C->bits.FTXON = 0; + BK7011RCBEKEN.REG0x4C->bits.TESTPATTERN = 0; +#if DIFFERENCE_PIECES_CFG + BK7011RCBEKEN.REG0x0->bits.ch0en = 0; +#endif + BK7011TRX.REG0xE->value = 0xDA01BCF0; + CAL_WR_TRXREGS(0xE); + + + //BK7011TRX.REG0xC->value = TRX_REG_0XC_VAL; //170217 delete + //CAL_WR_TRXREGS(0xC); + + //BK7011ICU.REG0x1->bits.txon = 0; + //BK7011ICU.REG0x1->bits.rxon = 1; + + // ADC clock change to 40M + BK7011TRX.REG0xF->bits.clkadc_sel = 0; + CAL_WR_TRXREGS(0xF); + + BK7011TRX.REG0x12->bits.adcrefbwsel = 0; + CAL_WR_TRXREGS(0x12); + +} + +extern void mpb_tx_mode(void); + +#define CALI_DPD_TEST 0 +#if CALI_DPD_TEST +#define I_TABLE_ADDR 0x01050400 +#define Q_TABLE_ADDR 0x01050600 + +static UINT16 i_table_val[256] = +{ + 0, 6, 13, 19, 26, 35, 40, 47, 52, 57, 68, 73, 76, 82, 88, 91, 96, 102, 107, 107, 118, 118, 120, 127, 132, 134, 139, 141, 146, 149, 152, 158, 161, 161, 163, 164, 168, 172, 172, 176, 181, 177, 179, 181, 185, 187, 189, 185, 191, 195, 196, 195, 196, 197, 203, 198, 204, 201, 207, 199, 206, 207, 207, 207, 207, 210, 210, 212, 214, 215, 215, 215, 206, 216, 215, 221, 217, 219, 215, 219, 222, 222, 225, 229, 225, 223, 228, 226, 226, 229, 229, 226, 225, 227, 226, 226, 228, 232, 230, 229, 230, 231, 230, 231, 234, 235, 236, 238, 241, 244, 245, 247, 248, 251, 252, 255, 255, 258, 259, 262, 263, 265, 267, 268, 271, 272, 275, 275, 278, 280, 282, 284, 287, 288, 291, 293, 295, 297, 299, 301, 304, 306, 308, 310, 312, 314, 317, 319, 321, 323, 325, 327, 330, 332, 334, 336, 338, 341, 343, 345, 347, 349, 351, 354, 356, 358, 360, 362, 364, 367, 369, 371, 373, 375, 377, 380, 382, 384, 386, 388, 390, 393, 395, 397, 399, 401, 403, 406, 408, 410, 412, 414, 416, 419, 421, 423, 425, 427, 429, 432, 434, 436, 438, 440, 442, 445, 447, 449, 451, 453, 455, 458, 460, 462, 464, 466, 468, 471, 473, 475, 477, 479, 481, 484, 486, 488, 490, 492, 495, 497, 499, 501, 503, 505, 508, 510, 512, 514, 516, 518, 521, 523, 525, 527, 529, 531, 534, 536, 538, 540, 542, 544, 547, 549, 551, 562 +}; + +static UINT16 q_table_val[256] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 1, 5, 8, 5, 9, 6, 5, 7, 4, 7, 8, 17, 13, 12, 14, 15, 12, 12, 18, 12, 13, 16, 16, 17, 19, 20, 24, 22, 30, 23, 21, 24, 30, 27, 26, 24, 27, 26, 30, 28, 30, 32, 31, 31, 32, 32, 33, 35, 35, 33, 35, 34, 32, 32, 32, 34, 33, 32, 31, 32, 30, 33, 29, 30, 29, 30, 29, 29, 28, 27, 29, 27, 28, 26, 26, 26, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 30, 30, 30, 30, 30, 31, 31, 31, 31, 31, 32, 32, 32, 32, 32, 33, 33, 33, 33, 33, 34, 34, 34, 34, 34, 35, 35, 35, 35, 35, 36, 36, 36, 36, 36, 37, 37, 37, 37, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 42, 42, 42, 42, 42, 43, 43, 43, 43, 43, 44, 44, 44, 44, 44, 45, 45, 45, 45, 45, 46, 46, 46, 46, 46, 47, 47, 47, 47, 48, 48, 48, 48, 48, 49, 49, 49, 49, 49, 50, 50, 50, 50, 50, 51, 51, 51, 51, 51, 52, 52, 48 +}; + +UINT32 bk7211_cal_tx_dpd_load(void) +{ + + UINT16 *i_tbl_addr = (UINT16 *)I_TABLE_ADDR; + UINT16 *q_tbl_addr = (UINT16 *)Q_TABLE_ADDR; + UINT16 k; + + BK7011RCBEKEN.REG0x4C->bits.DPDEN = 0; + + os_memcpy(i_tbl_addr, (UINT16 *)&i_table_val[0], 256 * 2); + os_memcpy(q_tbl_addr, (UINT16 *)&q_table_val[0], 256 * 2); + +#if 1 + for(k = 0; k < 256; k++) + { + i_tbl_addr[k] = 1; + q_tbl_addr[k] = 0; + } +#endif + return 0; + +} +#endif + +#if CAL_RESULT_TO_FLASH +void write_cal_result_to_flash(void) +{ + UINT32 param; + UINT32 param1; + char cTemp[sizeof(bk7011_rc_val) + sizeof(bk7011_trx_val)]; + char cTemp1[sizeof(bk7011_rc_val) + sizeof(bk7011_trx_val)]; + + CAL_FLASH_PRT("write cal result to flash\r\n"); + +// flash_ctrl(CMD_FLASH_READ_SR, ¶m); +// os_printf("param = 0x%x\r\n", param); + #if CFG_SUPPORT_ALIOS + hal_flash_dis_secure(0, 0, 0); + #else + bk_flash_enable_security(NONE); + #endif +// os_printf("param1 = 0x%x\r\n", param1); + +// param = CAL_RESULT_FLASH_ADDR; +// flash_ctrl(CMD_FLASH_ERASE_SECTOR, ¶m); + flash_erase_sector(CAL_RESULT_FLASH_ADDR); + + memcpy(cTemp, bk7011_rc_val, sizeof(bk7011_rc_val)); + memcpy(cTemp+sizeof(bk7011_rc_val), bk7011_trx_val, sizeof(bk7011_trx_val)); +// memset(cTemp, 0, sizeof(cTemp)); + flash_write(cTemp, sizeof(cTemp), CAL_RESULT_FLASH_ADDR); + flash_read(cTemp1, sizeof(cTemp1), CAL_RESULT_FLASH_ADDR); + if (memcmp(cTemp, cTemp1, sizeof(cTemp1)) == 0) + { + CAL_FLASH_PRT("memcmp OK\r\n"); + } + else + { + CAL_FLASH_PRT("memcmp fail\r\n"); + } + +// param = 2 | ((param&0x00FFFF)<<8); + #if CFG_SUPPORT_ALIOS + hal_flash_enable_secure(0, 0, 0); + #else + bk_flash_enable_security(ALL); + #endif +// param = 0; +// flash_ctrl(CMD_FLASH_READ_SR, ¶m); +// os_printf("param = 0x%x\r\n", param); + + os_printf("write cal result to flash OK\r\n"); +} +#endif + +char read_cal_result_from_flash(void) +{ +#if CAL_RESULT_TO_FLASH + char cTemp[sizeof(bk7011_rc_val) + sizeof(bk7011_trx_val)]; + + CAL_FLASH_PRT("read_cal_result_from_flash\r\n"); + memset(cTemp, 0, sizeof(cTemp)); + flash_read(cTemp, sizeof(cTemp), CAL_RESULT_FLASH_ADDR); + if ((cTemp[0] == 0xFF) && (cTemp[4] == 0xFF) && (cTemp[8] == 0xFF) && (cTemp[12] == 0xFF)) + { + return 0; + } + else + { + memcpy(bk7011_rc_val, cTemp, sizeof(bk7011_rc_val)); + memcpy(bk7011_trx_val, cTemp+sizeof(bk7011_rc_val), sizeof(bk7011_trx_val)); + rwnx_cal_load_default_result(); + rwnx_cal_load_trx_rcbekn_reg_val(); +// printf_trx_rc_value(); + os_printf("read cal result from flash OK\r\n"); + return 1; + } +#else + return 0; +#endif +} + +#if CAL_RESULT_TO_FLASH +void flash_test(void) +{ + UINT32 param; + char cTemp[0x1000]; + char cTemp1[0x1000]; + int i; + + flash_read(cTemp, 0x1000, 0xF4000); + os_printf("cTemp:\r\n"); + for (i=0; i<0x1000; i++) + { + os_printf("%x ", cTemp[i]); + } + os_printf("\r\n"); + + #if CFG_SUPPORT_ALIOS + hal_flash_dis_secure(0, 0, 0); + #else + bk_flash_enable_security(NONE); + #endif + param = 0xF4000; + flash_ctrl(CMD_FLASH_ERASE_SECTOR, ¶m); + + flash_read(cTemp, 0x1000, 0xF4000); + os_printf("cTemp:\r\n"); + for (i=0; i<0x1000; i++) + { + os_printf("%x ", cTemp[i]); + } + os_printf("\r\n"); + + for (i=0; i<0x1000; i++) + { + cTemp[i] = i; + } + os_printf("cTemp:\r\n"); + for (i=0; i<0x1000; i++) + { + os_printf("%x ", cTemp[i]); + } + os_printf("\r\n"); + + flash_write(cTemp, 0x1000, 0xF4000); + + memset(cTemp1, 0, 0x1000); + os_printf("cTemp1:\r\n"); + for (i=0; i<0x1000; i++) + { + os_printf("%x ", cTemp1[i]); + } + os_printf("\r\n"); + flash_read(cTemp1, 0x1000, 0xF4000); + + os_printf("cTemp1:\r\n"); + for (i=0; i<0x1000; i++) + { + os_printf("%x ", cTemp1[i]); + } + + os_printf("\r\n"); + if (memcmp(cTemp, cTemp1, sizeof(cTemp)) == 0) + { + os_printf("memcmp OK\r\n"); + } + else + { + os_printf("memcmp ERROR\r\n"); + } +} +#endif + +UINT32 bk7011_set_ldo_manual(void) +{ + UINT32 param, val, param_bak; + param_bak = param = sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_BIAS_REG_READ, ¶m); + val = (param >> PARAM_LDO_VAL_MANUAL_POSI) & PARAM_LDO_VAL_MANUAL_MASK; + + val = (val > 2)? (val - 2) : 0; + param &= ~(PARAM_LDO_VAL_MANUAL_MASK << PARAM_LDO_VAL_MANUAL_POSI); + param |= ((val & PARAM_LDO_VAL_MANUAL_MASK) << PARAM_LDO_VAL_MANUAL_POSI); + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_BIAS_REG_WRITE, ¶m); + + return param_bak; +} + +void bk7011_recover_ldo_manual(UINT32 param) +{ + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_BIAS_REG_WRITE, ¶m); +} + +void sctrl_dpll_int_open(void); +void calibration_main(void) +{ + INT32 goldval[32] = {0}; + UINT32 param_bak, ldoadda_bak; + + CM_CLR_FLAG_ALLBIT(); + +#if DIFFERENCE_PIECES_CFG + bk7011_get_rfcali_mode(); + bk7011_get_txpwr_config_reg(); +#endif + +// printf("calibration_main: %s %s\r\n", __DATE__, __TIME__); + memcpy(bk7011_trx_val, bk7011_trx_val1, sizeof(bk7011_trx_val)); + memcpy(bk7011_rc_val, bk7011_rc_val1, sizeof(bk7011_rc_val)); + + //REG_WRITE((0x0802800 + (18 * 4)), 0x02); + BK7011RCBEKEN.REG0x4C->bits.TXCOMPDIS = 0; + bk7011_cal_ready(); + bk7011_cal_bias(); + + // setting for tssi stable + param_bak = bk7011_set_ldo_manual(); + ldoadda_bak = BK7011TRX.REG0x12->bits.ldoadda; + rwnx_cal_set_reg_adda_ldo(0); + + //bk7011_doubler_cal(); + //bk7011_band_cal(); + + //bk7011_cal_pll(); + //bk7011_rfpll_ld(); + + bk7011_cal_dpll(); + sctrl_dpll_int_open(); + + BK7011TRX.REG0xA->value = TRX_REG_0XA_VAL; + CAL_WR_TRXREGS(0xA); + BK7011TRX.REG0xB->value = TRX_REG_0XB_VAL; + CAL_WR_TRXREGS(0xB); + BK7011TRX.REG0xC->value = TRX_REG_0XC_VAL; + CAL_WR_TRXREGS(0xC); + BK7011RCBEKEN.REG0x3C->bits.RXHPFBYPASS = 1;// Disable HPF for calibration + + + if (read_cal_result_from_flash() == 1) + { + return; + } + + +// BK7011TRX.REG0x7->bits.chin60 = 0x00;//2400MHz descrease the external interference +// CAL_WR_TRXREGS(0x7); + BK7011TRX.REG0x5->bits.chspi = 0x00;//2400MHz descrease the external interference + CAL_WR_TRXREGS(0x5); + delay100us(1);//delay 100us for RFPLL + + bk7011_tx_cal_en(); + bk7011_cal_bias(); + bk7011_cal_tx_filter_corner(goldval); + + gtx_power_cal_mode = TX_IQ_POWER_CAL; + bk7011_cal_tx_output_power(goldval); // First cal just to enable BK7231 TX work for temp. balance + + //bk7011_cal_bias();//second cal after PA on; + + //bk7011_cal_pll();//second cal after PA on; + //delay100us(1);//delay 100us for RFPLL + + // gtx_power_cal_mode = TX_IQ_POWER_CAL; + // bk7011_cal_tx_output_power(goldval); // real PA cal. + + BK7011TRX.REG0xB->bits.gctrlmod30 = 0x8; + CAL_WR_TRXREGS(0xB); + + gtx_dc_cal_mode = TX_DC_CAL_IQ; + bk7011_cal_tx_dc(goldval); + +/* + gtx_power_cal_mode = TX_WANTED_POWER_CAL; + cpu_delay(100); + bk7011_cal_tx_output_power(goldval); // +*/ + + + gtx_gain_imb_cal_mode = TX_GAIN_IMB_CAL; + bk7011_cal_tx_gain_imbalance(goldval); + + gtx_phase_imb_cal_mode = TX_PHASE_IMB_CAL; + bk7011_cal_tx_phase_imbalance(goldval); + + +// BK7011TRX.REG0xB->value = TRX_REG_0XB_VAL; + + gtx_dc_cal_mode = TX_DC_CAL; + bk7011_cal_tx_dc(goldval); + +// BK7011TRX.REG0x7->bits.chin60 = 0x5d;//2495MHz +// CAL_WR_TRXREGS(0x7); + BK7011TRX.REG0x5->bits.chspi = 0x5d;//2495MHz + CAL_WR_TRXREGS(0x5); + delay100us(1);//delay 100us for RFPLL + + + bk7011_cal_bias(); + + + gtx_power_cal_mode = TX_WANTED_POWER_CAL; +#if DIFFERENCE_PIECES_CFG + if(!bk7011_is_rfcali_mode_auto()) + { + BK7011TRX.REG0x5->bits.chspi = 0x2A;//fix to this channel for power cal. + CAL_WR_TRXREGS(0x5); + delay100us(1);//delay 100us for RFPLL + bk7011_cal_tx_output_power(goldval); // Actual Power cal. + } + else + { + //bk_printf("2412\n"); + BK7011TRX.REG0x5->bits.chspi = 12; // 2412 + CAL_WR_TRXREGS(0x5); + delay100us(1);//delay 100us for RFPLL + bk7011_cal_tx_output_power(goldval); // Actual Power cal. + bk7011_cal_dcormod_save_base(gtx_dcorMod); + //bk_printf("2442\n"); + + BK7011TRX.REG0x5->bits.chspi = 42; // 2442 + CAL_WR_TRXREGS(0x5); + delay100us(1);//delay 100us for RFPLL + bk7011_cal_tx_output_power(goldval); // Actual Power cal. + bk7011_cal_dcormod_save_base(gtx_dcorMod); + //bk_printf("2472\n"); + + BK7011TRX.REG0x5->bits.chspi = 72; // 2472 + CAL_WR_TRXREGS(0x5); + delay100us(1);//delay 100us for RFPLL + bk7011_cal_tx_output_power(goldval); // Actual Power cal. + bk7011_cal_dcormod_save_base(gtx_dcorMod); + + bk7011_cal_dcormod_do_fitting(); + } +#else +// BK7011TRX.REG0x7->bits.chin60 = 0xc;//fix to this channel for power cal. +// CAL_WR_TRXREGS(0x7); + BK7011TRX.REG0x5->bits.chspi = 0xc;//fix to this channel for power cal. + CAL_WR_TRXREGS(0x5); + delay100us(1);//delay 100us for RFPLL + + bk7011_cal_tx_output_power(goldval); // Actual Power cal. +#endif + + bk7011_set_tx_after_cal(); + rwnx_tx_cal_save_cal_result();//by yiming 20170315 + +// BK7011TRX.REG0x7->bits.chin60 = 0x5d;//2495MHz +// CAL_WR_TRXREGS(0x7); + BK7011TRX.REG0x5->bits.chspi = 0x5d;//2495MHz + CAL_WR_TRXREGS(0x5); + delay100us(1);//delay 100us for RFPLL + + bk7011_rx_cal_en(); + bk7011_cal_rx_dc(); + + bk7011_tx_cal_en(); + + BK7011TRX.REG0x5->bits.chspi = 0x5d;//2495MHz + CAL_WR_TRXREGS(0x5); + delay100us(1);//delay 100us for RFPLL + + + //20170804 by yiming + gtx_power_cal_mode = TX_IQ_LOOPBACK_POWER_CAL; + bk7011_cal_tx_output_power(goldval); + bk7011_cal_bias(); + bk7011_cal_pll(); + delay100us(1);//delay 100us for RFPLL + + gtx_power_cal_mode = TX_IQ_LOOPBACK_POWER_CAL; + bk7011_cal_tx_output_power(goldval); + + gtx_dc_cal_mode = TX_DC_LOOPBACK_CAL_IQ; + bk7011_cal_tx_dc(goldval);//Loopback DC cal. + + + gtx_gain_imb_cal_mode = TX_GAIN_LOOPBACK_IMB_CAL; + bk7011_cal_tx_gain_imbalance(goldval); + +#ifdef CALIBRATE_TIMES + if (p_gtx_i_gain_comp_temp_array != NULL) + { +// gtx_i_gain_comp_temp_array[calibrate_time] = BK7011RCBEKEN.REG0x50->bits.TXIGAINCOMP; +// gtx_q_gain_comp_temp_array[calibrate_time] = BK7011RCBEKEN.REG0x50->bits.TXQGAINCOMP; + p_gtx_i_gain_comp_temp_array[calibrate_time] =( (*((volatile unsigned long * )(0x01050000 + 0x50*4))) >> 16) & 0x03FF ; + p_gtx_q_gain_comp_temp_array[calibrate_time] = (*((volatile unsigned long * )(0x01050000 + 0x50*4))) & 0x03FF ; + } +#endif + + gtx_phase_imb_cal_mode = TX_PHASE_LOOPBACK_IMB_CAL; + bk7011_cal_tx_phase_imbalance(goldval); + + bk7011_rx_cal_en(); + bk7011_cal_rx_iq(goldval); + + + bk7011_load_calibration_cfg(); + bk7011_set_rx_after_cal(); + //REG_WRITE((0x0802800 + (18 * 4)), 0x00); + + //rwnx_cal_read_current_cal_result(); + rwnx_rx_cal_save_cal_result(); + rwnx_cal_load_default_result(); + rwnx_cal_read_current_cal_result(); + BK7011RCBEKEN.REG0x4C->bits.TXCOMPDIS = 0; + + rwnx_tx_cal_save_cal_result();//by yiming 20170315 + rwnx_cal_load_trx_rcbekn_reg_val(); + +#if CALI_DPD_TEST + rwnx_cal_load_trx_rcbekn_reg_val(); + bk7211_cal_tx_dpd_load(); +#endif + bk7011_cal_dpll(); + sctrl_dpll_int_open(); + + // set i&q lpfcap select from digit in default + rwnx_cal_enable_lpfcap_iq_from_digit(1); + + // recover for tssi stable + bk7011_recover_ldo_manual(param_bak); + rwnx_cal_set_reg_adda_ldo(ldoadda_bak); + + if(CM_FLAG_IS_SET()) + { + manual_cal_save_cailmain_tx_tab_to_flash(); + manual_cal_save_cailmain_rx_tab_to_flash(); + } +/* + gtx_power_cal_mode = TX_WANTED_POWER_CAL; + cpu_delay(100); + bk7011_cal_tx_output_power(goldval); // +*/ +#if CAL_RESULT_TO_FLASH + write_cal_result_to_flash(); +// printf_trx_rc_value(); +#endif + return ; +} + +void do_all_calibration(void) +{ + if(manual_cal_need_load_cmtag_from_flash()) + { + // last status is LOAD_FROM_FLASH, means it may load from flash or default + manual_set_cmtag(LOAD_FROM_CALI); + + // only do one time in every pow on + calibration_main(); + + rwnx_tpc_pa_map_init(); + } +} + +void do_calibration_in_temp_dect(void) +{ + INT32 goldval[32] = {0}; + +// BK7011TRX.REG0x7->bits.chin60 = 0xc;//fix to this channel for power cal. +// CAL_WR_TRXREGS(0x7); + BK7011TRX.REG0x5->bits.chspi = 0xc;//fix to this channel for power cal. + CAL_WR_TRXREGS(0x5); + delay100us(1);//delay 100us for RFPLL + + bk7011_read_cal_param(); + rwnx_cal_load_default_result(); + cpu_delay(10);//cpu_delay(10); 20160801 + + bk7011_cal_bias(); + + BK7011RCBEKEN.REG0x4C->bits.TXCOMPDIS = 0; + + bk7011_tx_cal_en(); + //gtxoutput = 1; + //bk7011_cal_tx_output_power(goldval); // first time + + gtx_power_cal_mode = TX_WANTED_POWER_CAL; + bk7011_cal_tx_output_power(goldval); // second time + + bk7011_set_tx_after_cal(); + //REG_WRITE((0x0802800 + (19 * 4)), 0x00); + + //rwnx_cal_read_current_cal_result(); + rwnx_tx_cal_save_cal_result(); + rwnx_cal_load_default_result(); + rwnx_cal_read_current_cal_result(); + BK7011RCBEKEN.REG0x4C->bits.TXCOMPDIS = 0; + + bk7011_cal_dpll(); + sctrl_dpll_int_open(); + + return ; +} + +UINT32 dgainpga = 0; +void turnoff_PA_in_temp_dect(void) +{ + CHECK_OPERATE_RF_REG_IF_IN_SLEEP(); + dgainpga = BK7011TRXONLY.REG0xC->bits.dgainpga; + BK7011TRX.REG0xC->bits.dgainpga = 0; + + CAL_WR_TRXREGS(0xC); + CHECK_OPERATE_RF_REG_IF_IN_SLEEP_END(); +} + +void turnon_PA_in_temp_dect(void) +{ + CHECK_OPERATE_RF_REG_IF_IN_SLEEP(); + BK7011TRX.REG0xC->bits.dgainpga = dgainpga; + CAL_WR_TRXREGS(0xC); + CHECK_OPERATE_RF_REG_IF_IN_SLEEP_END(); +} + +void bk7011_la_sample_print(UINT32 isrx) +{ + UINT32 reg_val, i, len; + UINT8 *buf; + + #define LA_SAMPLE_BUF_LEN (90 *1024) + + buf = os_malloc(LA_SAMPLE_BUF_LEN); + if(!buf) { + os_printf("la_sample_print no buffer\r\n"); + return; + } + + //len = 128 * 1024 / 4; + len = LA_SAMPLE_BUF_LEN / 4; + + REG_WRITE((0x00800000 + 0x12*4), 0x0); + + REG_WRITE((0x00800000 + 0x15*4), (UINT32)buf); + REG_WRITE((0x00800000 + 0x12*4), (len << 16) | 0x4); + + //ADC Data + if(isrx) { + REG_WRITE((0x01060000+0x0*4), 0x21); // addMACPHY_BYPASS_Reg0x0 = 0x21; + delay100us(100); + } + REG_WRITE((0x00800000 + 0xd*4), 0x00040000); // addSYS_CTRL_Reg0xd = 0x00040000; + REG_WRITE((0x00800000 + 0x14*4), 0xfe000000); // addSYS_CTRL_Reg0x14 = 0xfe000000; + if(isrx) { + REG_WRITE((0x00800000 + 0x13*4), 0x0a000000); // addSYS_CTRL_Reg0x13 = 0x0a000000; + } else { + REG_WRITE((0x00800000 + 0x13*4), 0x0c000000); // addSYS_CTRL_Reg0x13 = 0x0c000000; + } + reg_val = REG_READ((0x00800000 + 0x12*4)); // set_SYS_CTRL_Reg0x12_LaSmpMode(0x1); + reg_val = (reg_val & (~0x3)) | 0x01; + REG_WRITE((0x00800000 + 0x12*4), reg_val); + + do { + reg_val = REG_READ((0x00800000 + 0x12*4)); + os_printf("abc:%x\r\n",reg_val&0x8); + } while(reg_val & 0x8); // while(!get_SYS_CTRL_Reg0x12_LaSmpFinish) + + delay100us(100); + + reg_val = REG_READ((0x00800000 + 0x12*4)); // set_SYS_CTRL_Reg0x12_LaSmpMode(0x0); + reg_val = (reg_val & (~0x3)) | 0x00; + REG_WRITE((0x00800000 + 0x12*4), reg_val); + + for(i = 0; i < len; i ++) + { + os_printf("%08x\r\n", *((uint32_t *)(buf+i*4))); + } + + os_free(buf); +} + +void bk7011_max_rxsens_setting(void) +{ + BK7011TRX.REG0x8->bits.isrxref10 = 3; + BK7011TRX.REG0x8->bits.isrxlna30 = 15; + CAL_WR_TRXREGS(0x8); + bk7011_trx_val[8] = BK7011TRXONLY.REG0x8->value ; +} + +void bk7011_normal_rxsens_setting(void) +{ + BK7011TRX.REG0x8->bits.isrxref10 = 2; + BK7011TRX.REG0x8->bits.isrxlna30 = 7; + CAL_WR_TRXREGS(0x8); + bk7011_trx_val[8] = BK7011TRXONLY.REG0x8->value ; +} + +void bk7011_default_rxsens_setting(void) +{ + BK7011TRX.REG0x8->bits.isrxref10 = 2; + BK7011TRX.REG0x8->bits.isrxlna30 = 7; + CAL_WR_TRXREGS(0x8); + bk7011_trx_val[8] = BK7011TRXONLY.REG0x8->value ; +} + +UINT8 gtx_dcorMod_tab[14] = {0}; +void bk7011_cal_dcormod_show(void) +{ + os_printf("\r\n dcormod tab:\r\n"); + for(int i=0; i<14; i++) { + os_printf("ch:%2d: mod:%02x\r\n", i+1, gtx_dcorMod_tab[i]); + } +} + +static void bk7011_cal_dcormod_save_base(INT32 mod) +{ + UINT32 channel = BK7011TRXONLY.REG0x5->bits.chspi; + + if(channel < 12) + channel = 1; + else + channel = (channel - 7)/5; + + if(channel > 14) + channel = 14; + + if((channel == 1) || (channel == 7) || (channel == 13)) + { + if((mod >= 0) && (mod <= 15)) + { + gtx_dcorMod_tab[channel-1] = mod; + } + else + { + os_printf("save base failed:ch:%d, mod:%x\r\n", channel, mod); + } + } +} + +static void bk7011_cal_dcormod_do_fitting(void) +{ + UINT8 mod_ch; + bk_printf("gtx_dcorMod_tab[]:%x,%x,%x\n",gtx_dcorMod_tab[0],gtx_dcorMod_tab[6],gtx_dcorMod_tab[12]); + // ch4, use ch1 & ch7 + mod_ch = gtx_dcorMod_tab[0] + gtx_dcorMod_tab[6]; + gtx_dcorMod_tab[3] = mod_ch >> 1; + + // ch10, use ch7 & ch13 + mod_ch = gtx_dcorMod_tab[6] + gtx_dcorMod_tab[12]; + gtx_dcorMod_tab[9] = mod_ch >> 1; + + mod_ch = gtx_dcorMod_tab[0]; + for(int i=1; i<14; i++) + { + // ch 1 4 7 10 13 + if((i == 0) || (i == 3) || (i == 6) || (i == 9) || (i == 12)) + mod_ch = gtx_dcorMod_tab[i]; + else + gtx_dcorMod_tab[i] = mod_ch; + } +} + +static UINT8 bk7011_cal_dcormod_get(void) +{ + if(bk7011_is_rfcali_mode_auto()) + { + UINT32 channel = BK7011TRXONLY.REG0x5->bits.chspi; + + if(channel < 12) + channel = 1; + else + channel = (channel - 7)/5; + + if(channel > 14) + channel = 14; + + return gtx_dcorMod_tab[channel-1]; + } + else + return gtx_dcorMod; +} + +#else /* CFG_SUPPORT_CALIBRATION */ +/*INT32 rwnx_cal_load_trx_rcbekn_reg_val(void) +{ +} +INT32 rwnx_cal_save_trx_rcbekn_reg_val(void) +{ +} +void rwnx_cal_set_txpwr_by_rate(INT32 rate) +{ +} +void calibration_main(void) +{ +} +void calibration_auto_test(void) +{ +}*/ +#endif /* CFG_SUPPORT_CALIBRATION */ + +#endif // (CFG_SOC_NAME != SOC_BK7231) +// eof + diff --git a/beken_os/beken378/func/bk7011_cal/bk7231U_cal.h b/beken_os/beken378/func/bk7011_cal/bk7231U_cal.h new file mode 100755 index 0000000..111eea2 --- /dev/null +++ b/beken_os/beken378/func/bk7011_cal/bk7231U_cal.h @@ -0,0 +1,1875 @@ +#ifndef _BK7231U_CAL_H_ +#define _BK7231U_CAL_H_ + +#if (CFG_SOC_NAME != SOC_BK7231) + +#define INCLUDE_OS + +#define CALIBRATE_TIMES 2000 +#undef CALIBRATE_TIMES // by gwf + +#define REGTRXV2A +#define BK7011_VER_A + +////Difference between pieces +#define DIFFERENCE_PIECES_CFG 0 + +//#define _11MBPS_MAX_POWER + +void delay05us(INT32 num); + +#define trx_reg_is_write(st_trxreg) while(BK7011RCBEKEN.REG0x1->value & st_trxreg) {cpu_delay(1);} + +#define DETECT_LOOPCNT 10 +#define GOLD_OUTPUT_POWER 56 +#define UNSIGNEDOFFSET10 512 +#define I_Q_CAP_DIF 32 +#define CONSTANT_RCIQ 117 +#define SUMNUMBERS 4 +#define MINOFFSET 16 + +//#define DPDCALILEN 256 + +#define cpu_delay(val) delay(MAX(1, val/100)) +#define DELAY1US 100 +//#define DELAY05US 1 + +#define cal_delay(val) delay05us(MAX(1, val)) // 8us +//#define CAL_DELAY1US 2 +//#define CAL_DELAY05US 20 //20160804 1:0.5us 2:1us +#define CAL_DELAY05US 2 // 20170503 2:1.5us 2 to 20 for debug 20180227 +#define CAL_TX_NUM 50 +#define CAL_RX_NUM 5 + +#define cal_delay_100us(val) delay100us(MAX(1, val)) // 200us +#define CAL_DELAY100US 1 //20160804 1:100us 2:200us // 20170503 1:150us 2:300us + + +#define st_TRXREG00 (1<<0) +#define st_TRXREG01 (1<<1) +#define st_TRXREG02 (1<<2) +#define st_TRXREG03 (1<<3) +#define st_TRXREG04 (1<<4) +#define st_TRXREG05 (1<<5) +#define st_TRXREG06 (1<<6) +#define st_TRXREG07 (1<<7) +#define st_TRXREG08 (1<<8) +#define st_TRXREG09 (1<<9) +#define st_TRXREG0A (1<<10) +#define st_TRXREG0B (1<<11) +#define st_TRXREG0C (1<<12) +#define st_TRXREG0D (1<<13) +#define st_TRXREG0E (1<<14) +#define st_TRXREG0F (1<<15) +#define st_TRXREG10 (1<<16) +#define st_TRXREG11 (1<<17) +#define st_TRXREG12 (1<<18) +#define st_TRXREG13 (1<<19) +#define st_TRXREG14 (1<<20) +#define st_TRXREG15 (1<<21) +#define st_TRXREG16 (1<<22) +#define st_TRXREG17 (1<<23) +#define st_TRXREG18 (1<<24) +#define st_TRXREG19 (1<<25) +#define st_TRXREG1A (1<<26) +#define st_TRXREG1B (1<<27) + +#define abs(a) ((a) < 0 ?(-1*(a)):(a)) + +#ifndef __BK7011RCBEKEN_H__ +#define __BK7011RCBEKEN_H__ + +#define RC_BEKEN_BASE 0x01050000 + +/// REG0x0 +typedef union +{ + struct + { + volatile unsigned int ch0en : 1; /**< Enable BK7011 (1: Enable) */ + volatile unsigned int Reserved : 2; /**< NC */ + volatile unsigned int rcen : 1; /**< Enable BK7011 (1: Enable) */ + volatile unsigned int Reserved_ : 4; /**< NC */ + volatile unsigned int ch0ld : 1; /**< BK7011 LDֵǷ */ + volatile unsigned int lnarssi : 1; /**< BK7011 LNA RSSI״̬ */ + volatile unsigned int Reserved__ : 2; /**< NC */ + volatile unsigned int ch0shdnstat : 1; /**< BK7011Ƿshutdown״̬ */ + volatile unsigned int Reserved___ : 3; /**< NC */ + volatile unsigned int rcstate : 3; /**< ǰRC״̬;0x00=SPI_RESET ;0x01=SHUTDOWN ;0x02=WAIT_SPI (SPIڲ);0x03=WAIT_LOCKRFPLLLock;0x04=ACTIVE */ + volatile unsigned int Reserved____ : 11; /**< NC */ + volatile unsigned int spireset : 1; /**< Reset BK7011SPIĴ */ + volatile unsigned int forceenable : 1; /**< ǿƿBK7011Ľӿź */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x0_TypeDef; + +/// REG0x1 +typedef union +{ + struct + { + volatile unsigned int trxregstat : 28; /**< TRx Register Stat.;0x0: register is idle;0x1: register is updating. Can not write register again */ + volatile unsigned int prescaler : 4; /**< SPIʱƵʿ=RC_Clock (80 MHz)/2/PRESCALE */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x1_TypeDef; + +/// REG0x5 +typedef union +{ + struct + { + volatile unsigned int ch0outpower : 8; /**< No description */ + volatile unsigned int Reserved : 24; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x5_TypeDef; + +/// REG0x8 +typedef union +{ + struct + { + volatile unsigned int CH0RXONDELAY : 8; /**< No description */ + volatile unsigned int Reserved : 8; /**< NC */ + volatile unsigned int CH0RXOFFDELAY : 8; /**< No description */ + volatile unsigned int Reserved_ : 8; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x8_TypeDef; + +/// REG0xB +typedef union +{ + struct + { + volatile unsigned int CH0TXONDELAY : 8; /**< No description */ + volatile unsigned int Reserved : 8; /**< NC */ + volatile unsigned int CH0TXOFFDELAY : 8; /**< No description */ + volatile unsigned int Reserved_ : 8; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0xB_TypeDef; + +/// REG0xE +typedef union +{ + struct + { + volatile unsigned int CH0PAONDELAY : 8; /**< No description */ + volatile unsigned int Reserved : 8; /**< NC */ + volatile unsigned int CH0PAOFFDELAY : 8; /**< No description */ + volatile unsigned int Reserved_ : 8; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0xE_TypeDef; + +/// REG0x11 +typedef union +{ + struct + { + volatile unsigned int CH0SHDNONDELAY : 8; /**< No description */ + volatile unsigned int Reserved : 8; /**< NC */ + volatile unsigned int CH0SHDNOFFDELAY : 8; /**< No description */ + volatile unsigned int Reserved_ : 8; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x11_TypeDef; + +/// REG0x19 +typedef union +{ + struct + { + volatile unsigned int FCH0SHDN : 1; /**< ǿģʽµSHDN */ + volatile unsigned int FCH0RXEN : 1; /**< ǿģʽµRXEN */ + volatile unsigned int FCH0TXEN : 1; /**< ǿģʽµTXEN */ + volatile unsigned int FCH0RXHP : 1; /**< ǿģʽµRXHP */ + volatile unsigned int Reserved : 4; /**< NC */ + volatile unsigned int FCH0B : 8; /**< ǿģʽ */ + volatile unsigned int FCH0EN : 1; /**< ǿƿRFӿź */ + volatile unsigned int Reserved_ : 15; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x19_TypeDef; + +/// REG0x1C +typedef union +{ + struct + { + volatile unsigned int FRXON : 1; /**< ǿģʽRX ON */ + volatile unsigned int FTXON : 1; /**< ǿģʽTX ON */ + volatile unsigned int Reserved : 30; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x1C_TypeDef; + +/// REG0x1E +typedef union +{ + struct + { + volatile unsigned int FERXONDEL : 12; /**< No description */ + volatile unsigned int Reserved : 20; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x1E_TypeDef; + +/// REG0x3C +typedef union +{ + struct + { + volatile unsigned int RXAVGQRD : 12; /**< Q· */ + volatile unsigned int RXAVGIRD : 12; /**< I· */ + volatile unsigned int Reserved : 4; /**< NC */ + volatile unsigned int RXHPFBYPASS : 1; /**< RX HPF bypass */ + volatile unsigned int RXIQSWAP : 1; /**< RX IQ SWAP */ + volatile unsigned int RXAVGMODE : 1; /**< 0ȡźŵƽֵ;1ȡźžֵƽֵ */ + volatile unsigned int RXDCCALEN : 1; /**< ʹRX DC(1) */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x3C_TypeDef; + +/// REG0x3E +typedef union +{ + struct + { + volatile unsigned int RXDCQRD : 12; /**< Q·DC */ + volatile unsigned int RXDCIRD : 12; /**< I·DC */ + volatile unsigned int Reserved : 6; /**< NC */ + volatile unsigned int RXCOMPEN : 1; /**< ʹMismatch(1) */ + volatile unsigned int RXCALEN : 1; /**< ʹMismatch(1) */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x3E_TypeDef; + +/// REG0x3F +typedef union +{ + struct + { + volatile unsigned int RXPHASEERRRD : 10; /**< Ƴλphase_err_est*2^9з */ + volatile unsigned int Reserved : 6; /**< NC */ + volatile unsigned int RXAMPERRRD : 10; /**< Ƴķamp_err_est*2^9з */ + volatile unsigned int Reserved_ : 6; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x3F_TypeDef; + +/// REG0x40 +typedef union +{ + struct + { + volatile unsigned int RXTY2RD : 10; /**< ƳTY2(ty2-0.5)*2^10з */ + volatile unsigned int Reserved : 22; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x40_TypeDef; + +/// REG0x41 +typedef union +{ + struct + { + volatile unsigned int RXDCQWR : 12; /**< ʱʹõQ·DC */ + volatile unsigned int RXDCIWR : 12; /**< ʱʹõI·DC */ + volatile unsigned int Reserved : 8; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x41_TypeDef; + +/// REG0x42 +typedef union +{ + struct + { + volatile unsigned int RXPHASEERRWR : 10; /**< ʱʹõphase_err*ty2*2^9 */ + volatile unsigned int Reserved : 6; /**< NC */ + volatile unsigned int RXAMPERRWR : 10; /**< ʱʹõty2/(1+amp_err)*2^9 */ + volatile unsigned int Reserved_ : 6; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x42_TypeDef; + +/// REG0x4C +typedef union +{ + struct + { + volatile unsigned int QCONSTANT : 10; /**< 䳣ʱQֵ */ + volatile unsigned int Reserved : 6; /**< NC */ + volatile unsigned int ICONSTANT : 10; /**< 䳣ʱIֵ */ + volatile unsigned int DPDCOMPEN : 1; /**< DPD Compensation Enable */ + volatile unsigned int DPDCALEN : 1; /**< DPD Calculation Enable */ + volatile unsigned int DPDEN : 1; /**< DPD Enable] */ + volatile unsigned int TXCOMPDIS : 1; /**< Ͳֹܽ;0x0: ʹܷͲ;0x1: ֹͲ */ + volatile unsigned int TESTPATTERN : 2; /**< 0ģʽModem */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x4C_TypeDef; + +/// REG0x4D +typedef union +{ + struct + { + volatile unsigned int Reserved : 12; /**< NC */ + volatile unsigned int TXSINAMP : 4; /**< ҲȵϵСʾx.yyyΧ[0 15/8] */ + volatile unsigned int TXSINMODE : 2; /**< 0I/Q·临Ҳ;1I·䣬Q·0;2Q·䣬I·0;3 */ + volatile unsigned int Reserved_ : 4; /**< NC */ + volatile unsigned int TXSINF : 10; /**< ҲƵ;TX_SIN_F=2*pi*F/80e6*2^8FǷƵ */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x4D_TypeDef; + +/// REG0x4E +typedef union +{ + struct + { + volatile unsigned int hbf40sel : 1; /**< 40Mģʽϲ˲ϵ 1 beken ϵ 0rw ϵ */ + volatile unsigned int hbf40bp : 1; /**< 40Mģʽϲ˲ bypass */ + volatile unsigned int hbf20sel : 1; /**< 20Mģʽϲ˲ϵ 1 beken ϵ 0rw ϵ */ + volatile unsigned int hbf20bp : 1; /**< 20Mģʽϲ˲ bypass */ + volatile unsigned int Reserved_ : 28; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x4E_TypeDef; + +/// REG0x4F +typedef union +{ + struct + { + volatile unsigned int TXQDCCOMP : 10; /**< Q DC offset[-512 511] */ + volatile unsigned int Reserved : 6; /**< NC */ + volatile unsigned int TXIDCCOMP : 10; /**< I DC offset[-512 511] */ + volatile unsigned int Reserved_ : 6; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x4F_TypeDef; + +/// REG0x50 +typedef union +{ + struct + { + volatile unsigned int TXQGAINCOMP : 10; /**< 0 ~ 1023/1024step:1/1024 */ + volatile unsigned int Reserved : 6; /**< NC */ + volatile unsigned int TXIGAINCOMP : 10; /**< 0 ~ 1023/1024step:1/1024 */ + volatile unsigned int Reserved_ : 6; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x50_TypeDef; + +/// REG0x51 +typedef union +{ + struct + { + volatile unsigned int TXTY2 : 10; /**< 512/1024 ~ (512+1023)/1024step:1/1024 */ + volatile unsigned int Reserved : 6; /**< NC */ + volatile unsigned int TXPHASECOMP : 10; /**< -512/1024~ 511/1024step:1/1024 */ + volatile unsigned int Reserved_ : 6; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x51_TypeDef; + +/// REG0x52 +typedef union +{ + struct + { + volatile unsigned int Reserved : 6; /**< NC */ + volatile unsigned int IQCONSTANTIQCALP : 10; /**< IQУ׼IQ CONSTANT ֵֵ */ + volatile unsigned int TXPREGAIN : 5; /**< IQź;01.75 dB;. 31-6dB;; */ + volatile unsigned int IQCONSTANTPOUT : 10; /**< У׼IQ CONSTANT ֵ */ + volatile unsigned int TXIQSWAP : 1; /**< IQ Swap */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x52_TypeDef; + +/// REG0x54 +typedef union +{ + struct + { + volatile unsigned int STRXADCIQ : 1; /**< RX ADC IQУ׼ Settling time 0:300us;1:600us */ + volatile unsigned int TSSIPOUTTH : 8; /**< У׼ʶӦTSSI */ + volatile unsigned int DSELVA : 1; /**< TSSI or AGC gain setting for versiong A, output 0: TSSI 1:AGC gain setting */ + volatile unsigned int TXDCN : 2; /**< TX DC ַһִв 0:3Σ1:4Σ2:5Σ3:6 */ + volatile unsigned int STRXADC : 2; /**< RX ADC Settling time 0:100us;1:200us;2:300us;3:400us */ + volatile unsigned int STSARADC : 2; /**< SAR ADC Settling time 0:0.5us;1:1us;2:1.5us;3:2us */ + volatile unsigned int TSSIRD : 8; /**< TSSI Value. Just valid during tssi_cal_en assert */ + volatile unsigned int AGCPGARD : 4; /**< AGCPGA */ + volatile unsigned int AGCBUFRD : 1; /**< AGCBUF */ + volatile unsigned int AGCLNARD : 2; /**< AGCLNA */ + volatile unsigned int AGCMAPMODE : 1; /**< 0ӳ䷽ʽһ;1ӳ䷽ʽ */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x54_TypeDef; + +/// REG0x55 +typedef union +{ + struct + { + volatile unsigned int RXSNRNOISE : 9; /**< rx noise for sinar test */ + volatile unsigned int Reserved : 7; /**< NC */ + volatile unsigned int RXSNRSIG : 9; /**< rx signal for sinar test */ + volatile unsigned int Reserved_ : 7; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x55_TypeDef; + +/// REG0x5A +typedef union +{ + struct + { + volatile unsigned int TXCALCAPI : 6; /**< I path calib capacity for transmit mode */ + volatile unsigned int Reserved__ : 2; /**< NC */ + volatile unsigned int RXCALCAPI : 6; /**< I path calib capacity for receive mode */ + volatile unsigned int Reserved : 2; /**< NC */ + volatile unsigned int STANDBYCALCAPI : 6; /**< I path calib capacity for standby mode */ + volatile unsigned int Reserved_ : 10; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x5A_TypeDef; + +/// REG0x5B +typedef union +{ + struct + { + volatile unsigned int TXCALCAPQ : 6; /**< Q path calib capacity for transmit mode */ + volatile unsigned int Reserved__ : 2; /**< NC */ + volatile unsigned int RXCALCAPQ : 6; /**< Q path calib capacity for receive mode */ + volatile unsigned int Reserved : 2; /**< NC */ + volatile unsigned int STANDBYCALCAPQ : 6; /**< Q path calib capacity for standby mode */ + volatile unsigned int Reserved_ : 10; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x5B_TypeDef; + +/// REG0x5C +typedef union +{ + struct + { + volatile unsigned int trxspiintval : 10; /**< TRX SPI Transfer Interval. Unit is 12.5ns */ + volatile unsigned int Reserved : 14; /**< NC */ + volatile unsigned int Reserved_ : 7; /**< Reserved */ + volatile unsigned int trxbankrpt : 1; /**< TRX Bank Report. 0x0:bank0; 0x1:bank1 */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x5C_TypeDef; + +/// REG0x6A +typedef union +{ + struct + { + volatile unsigned int trxaddaregstat : 6; /**< ADC&DAC Register Status.;0x0: register is idle;0x1: register is updating. Can not write register again */ + volatile unsigned int Reserved : 26; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x6A_TypeDef; + +/// REG0x70 +typedef union +{ + struct + { + volatile unsigned int palevel0map : 16; /**< PA Level0 Mapping Value */ + volatile unsigned int palevel1map : 16; /**< PA Level1 Mapping Value */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x70_TypeDef; + +/// REG0x71 +typedef union +{ + struct + { + volatile unsigned int palevel2map : 16; /**< PA Level2 Mapping Value */ + volatile unsigned int palevel3map : 16; /**< PA Level3 Mapping Value */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x71_TypeDef; + +/// REG0x72 +typedef union +{ + struct + { + volatile unsigned int palevel4map : 16; /**< PA Level4 Mapping Value */ + volatile unsigned int palevel5map : 16; /**< PA Level5 Mapping Value */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x72_TypeDef; + +/// REG0x73 +typedef union +{ + struct + { + volatile unsigned int palevel6map : 16; /**< PA Level6 Mapping Value */ + volatile unsigned int palevel7map : 16; /**< PA Level7 Mapping Value */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x73_TypeDef; + +/// REG0x74 +typedef union +{ + struct + { + volatile unsigned int palevel8map : 16; /**< PA Level8 Mapping Value */ + volatile unsigned int palevel9map : 16; /**< PA Level9 Mapping Value */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x74_TypeDef; + +/// REG0x75 +typedef union +{ + struct + { + volatile unsigned int palevel10map : 16; /**< PA Level10 Mapping Value */ + volatile unsigned int palevel11map : 16; /**< PA Level11 Mapping Value */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x75_TypeDef; + +/// REG0x76 +typedef union +{ + struct + { + volatile unsigned int palevel12map : 16; /**< PA Level12 Mapping Value */ + volatile unsigned int palevel13map : 16; /**< PA Level13 Mapping Value */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x76_TypeDef; + +/// REG0x77 +typedef union +{ + struct + { + volatile unsigned int palevel4map : 16; /**< PA Level4 Mapping Value */ + volatile unsigned int palevel5map : 16; /**< PA Level5 Mapping Value */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x77_TypeDef; + +/// BK7011RCBEKEN +struct BK7011RCBEKEN_TypeDef +{ + volatile BK7011_RC_BEKEN_REG0x0_TypeDef *REG0x0; + volatile BK7011_RC_BEKEN_REG0x1_TypeDef *REG0x1; + volatile BK7011_RC_BEKEN_REG0x5_TypeDef *REG0x5; + volatile BK7011_RC_BEKEN_REG0x8_TypeDef *REG0x8; + volatile BK7011_RC_BEKEN_REG0xB_TypeDef *REG0xB; + volatile BK7011_RC_BEKEN_REG0xE_TypeDef *REG0xE; + volatile BK7011_RC_BEKEN_REG0x11_TypeDef *REG0x11; + volatile BK7011_RC_BEKEN_REG0x19_TypeDef *REG0x19; + volatile BK7011_RC_BEKEN_REG0x1C_TypeDef *REG0x1C; + volatile BK7011_RC_BEKEN_REG0x1E_TypeDef *REG0x1E; + volatile BK7011_RC_BEKEN_REG0x3C_TypeDef *REG0x3C; + volatile BK7011_RC_BEKEN_REG0x3E_TypeDef *REG0x3E; + volatile BK7011_RC_BEKEN_REG0x3F_TypeDef *REG0x3F; + volatile BK7011_RC_BEKEN_REG0x40_TypeDef *REG0x40; + volatile BK7011_RC_BEKEN_REG0x41_TypeDef *REG0x41; + volatile BK7011_RC_BEKEN_REG0x42_TypeDef *REG0x42; + volatile BK7011_RC_BEKEN_REG0x4C_TypeDef *REG0x4C; + volatile BK7011_RC_BEKEN_REG0x4D_TypeDef *REG0x4D; + volatile BK7011_RC_BEKEN_REG0x4E_TypeDef *REG0x4E; + volatile BK7011_RC_BEKEN_REG0x4F_TypeDef *REG0x4F; + volatile BK7011_RC_BEKEN_REG0x50_TypeDef *REG0x50; + volatile BK7011_RC_BEKEN_REG0x51_TypeDef *REG0x51; + volatile BK7011_RC_BEKEN_REG0x52_TypeDef *REG0x52; + volatile BK7011_RC_BEKEN_REG0x54_TypeDef *REG0x54; + volatile BK7011_RC_BEKEN_REG0x55_TypeDef *REG0x55; + volatile BK7011_RC_BEKEN_REG0x5A_TypeDef *REG0x5A; + volatile BK7011_RC_BEKEN_REG0x5B_TypeDef *REG0x5B; + volatile BK7011_RC_BEKEN_REG0x5C_TypeDef *REG0x5C; + volatile BK7011_RC_BEKEN_REG0x6A_TypeDef *REG0x6A; + volatile BK7011_RC_BEKEN_REG0x70_TypeDef *REG0x70; + volatile BK7011_RC_BEKEN_REG0x71_TypeDef *REG0x71; + volatile BK7011_RC_BEKEN_REG0x72_TypeDef *REG0x72; + volatile BK7011_RC_BEKEN_REG0x73_TypeDef *REG0x73; + volatile BK7011_RC_BEKEN_REG0x74_TypeDef *REG0x74; + volatile BK7011_RC_BEKEN_REG0x75_TypeDef *REG0x75; + volatile BK7011_RC_BEKEN_REG0x76_TypeDef *REG0x76; + volatile BK7011_RC_BEKEN_REG0x77_TypeDef *REG0x77; +}; +#endif + +#ifndef __BK7011TRxV2A_H__ +#define __BK7011TRxV2A_H__ + +#define TRX_BEKEN_BASE 0x01050080 + +#if 1 +/// REG0x0 +typedef union +{ + struct + { + volatile unsigned long TSSliref : 2; + volatile unsigned long gTSSI10 : 2; + volatile unsigned long stbTSSI10 : 2; + volatile unsigned long PcalATT : 3; + volatile unsigned long enPcal : 1; + volatile unsigned long enIQcal : 1; + volatile unsigned long rstTSSI : 1; + volatile unsigned long enDCcal : 1; + volatile unsigned long TSSIsel : 1; + volatile unsigned long enTSSItst : 1; + volatile unsigned long vseltssi : 2; + volatile unsigned long tssi_statectrl : 1; + volatile unsigned long tssi_selrange : 1; + volatile unsigned long NC : 13; + } bits; + volatile unsigned int value; +}BK7011_TRxV2A_REG0x0_TypeDef; + +/// REG0x1 +typedef union +{ + struct + { + volatile unsigned long cpsel_tx : 2; + volatile unsigned long cp3_tx : 1; + volatile unsigned long cp2_tx : 2; + volatile unsigned long cp1_tx : 2; + volatile unsigned long ictrl_rx : 4; + volatile unsigned long cpsel_rx : 2; + volatile unsigned long Rp3_rx : 3; + volatile unsigned long Rp2_rx : 3; + volatile unsigned long LPFRz_rx : 4; + volatile unsigned long Ioffset_rx : 4; + volatile unsigned long cp3_rx : 1; + volatile unsigned long cp2_rx : 2; + volatile unsigned long cp1_rx : 2; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x1_TypeDef; + +/// REG0x2 +typedef union +{ + struct + { + volatile unsigned long vcoampctrl : 1; + volatile unsigned long vrefLctrl : 2; + volatile unsigned long vrefHctrl : 2; + volatile unsigned long reset_Ncounter : 1; + volatile unsigned long reset_Nload : 1; + volatile unsigned long tristate : 1; + volatile unsigned long selpol : 1; + volatile unsigned long cpswen : 1; + volatile unsigned long NC : 3; + volatile unsigned long open : 1; + volatile unsigned long ictrl_tx : 4; + volatile unsigned long Rp3_tx : 3; + volatile unsigned long Rp2_tx : 3; + volatile unsigned long LPFRz_tx : 4; + volatile unsigned long Ioffset_tx : 4; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x2_TypeDef; + +/// REG0x3 +typedef union +{ + struct + { + volatile unsigned long vnwl : 2; + volatile unsigned long vnwh : 2; + volatile unsigned long rvco20 : 3; + volatile unsigned long nwresc : 2; + volatile unsigned long nwlpfen : 1; + volatile unsigned long spi_trigger : 1; + volatile unsigned long errdet_spien : 1; + volatile unsigned long ckref_loop_sel : 1; + volatile unsigned long ckref_NL_sel : 1; + volatile unsigned long Nrsten : 1; + volatile unsigned long Int_mod : 1; + volatile unsigned long manual : 1; + volatile unsigned long bandm60 : 7; + volatile unsigned long Nmanual : 8; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x3_TypeDef; + +/// REG0x4 +typedef union +{ + struct + { + volatile unsigned long nsdmlsb : 8; + volatile unsigned long pnen : 1; + volatile unsigned long vbncdiv3G : 2; + volatile unsigned long itunediv3G : 1; + volatile unsigned long vbncdiv6G : 2; + volatile unsigned long itunediv6G : 1; + volatile unsigned long nc : 5; + volatile unsigned long mixer_gmctrl : 3; + volatile unsigned long pwd_mixampdet : 1; + volatile unsigned long mixer_ampdetc : 1; + volatile unsigned long mixerItune : 1; + volatile unsigned long mixerCtune : 6; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x4_TypeDef; + +/// REG0x5 +typedef union +{ + struct + { + volatile unsigned long men_db : 1; + volatile unsigned long flag_polsel_db : 1; + volatile unsigned long en_db : 1; + volatile unsigned long dlym_db : 5; + volatile unsigned long calen_db : 1; + volatile unsigned long cal_trig_db : 1; + volatile unsigned long NC : 1; + volatile unsigned long cp_ldo : 2; + volatile unsigned long pll_ldo : 2; + volatile unsigned long vco_ldo : 2; + volatile unsigned long cp_rst : 1; + volatile unsigned long sdm_rstn : 1; + volatile unsigned long cksel_sdm : 2; + volatile unsigned long cksel_bcal : 1; + volatile unsigned long refsel : 1; + volatile unsigned long pwdvco : 1; + volatile unsigned long pwdpll : 1; + volatile unsigned long chspi : 7; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x5_TypeDef; + +/// REG0x6 +typedef union +{ + struct + { + volatile unsigned long vcmsel10 : 2; + volatile unsigned long capcal_sel : 1; + volatile unsigned long dpd_en : 1; + volatile unsigned long lpfcapcalq50 : 6; + volatile unsigned long lpfcapcali50 : 6; + volatile unsigned long dcocq : 8; + volatile unsigned long dcoci : 8; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x6_TypeDef; + +/// REG0x7 +typedef union +{ + struct + { + volatile unsigned long dig_dcoen : 1; + volatile unsigned long spilpfrxg30 : 4; + volatile unsigned long autorxifgen : 1; + volatile unsigned long dcoc_ctl : 2; + volatile unsigned long lpfvcmic10 : 2; + volatile unsigned long lpftxTest : 1; + volatile unsigned long NC : 21; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x7_TypeDef; + +/// REG0x8 +typedef union +{ + struct + { + volatile unsigned long isrxref10 : 2; + volatile unsigned long isrxlna30 : 4; + volatile unsigned long NC1 : 3; + volatile unsigned long isrxlnac10 : 2; + volatile unsigned long isrxdiv10 : 2; + volatile unsigned long NC2 : 1; + volatile unsigned long rssith50 : 6; + volatile unsigned long isrssigm10 : 2; + volatile unsigned long rssiten : 1; + volatile unsigned long NC3 : 9; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x8_TypeDef; + +/// REG0x9 +typedef union +{ + struct + { + volatile unsigned long agcrxfeEn : 1; + volatile unsigned long grxlnaspi10 : 2; + volatile unsigned long grxi2vspi10 : 2; + volatile unsigned long vsrxlnaldo10 : 2; + volatile unsigned long grxlnacali20 : 3; + volatile unsigned long vsrxmixldo10 : 2; + volatile unsigned long vbsrxlo20 : 3; + volatile unsigned long vresrxlo : 1; + volatile unsigned long ibsrxi2v10 : 2; + volatile unsigned long vcmsrxi2v : 1; + volatile unsigned long NC : 13; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x9_TypeDef; + +/// REG0xA +typedef union +{ + struct + { + volatile unsigned long disrefPA10 : 2; + volatile unsigned long disrefpga10 : 2; + volatile unsigned long dbpab30 : 4; + volatile unsigned long dbpaa30 : 6; + volatile unsigned long NC : 2; + volatile unsigned long dcapbuf30 : 4; + volatile unsigned long dbbuf30 : 4; + volatile unsigned long dbcbuf30 : 4; + volatile unsigned long dbcpa20 : 3; + volatile unsigned long pamapen : 1; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0xA_TypeDef; + +/// REG0xB +typedef union +{ + struct + { + volatile unsigned long dcpga30 : 4; + volatile unsigned long dbpga30 : 4; + volatile unsigned long dcappga30 : 4; + volatile unsigned long dcorMod30 : 4; + volatile unsigned long dvlo30 : 4; + volatile unsigned long dvcmo30 : 4; + volatile unsigned long dcapmod30 : 4; + volatile unsigned long gctrlmod30 : 4; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0xB_TypeDef; + +/// REG0xC +typedef union +{ + struct + { + volatile unsigned long dgainpga : 4; + volatile unsigned long dgainbuf30 : 4; + volatile unsigned long dgainPA30 : 4; + volatile unsigned long dcorPA30 : 4; + volatile unsigned long vregSel30 : 4; + volatile unsigned long LOvbnc : 2; + volatile unsigned long LOisel : 2; + volatile unsigned long dvbb : 4; + volatile unsigned long dtr30 : 4; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0xC_TypeDef; + +/// REG0xD +typedef union +{ + struct + { + volatile unsigned long dacselection : 1; + volatile unsigned long lpfrxbw : 1; + volatile unsigned long lpftxbw : 1; + volatile unsigned long lpftrxsw : 1; + volatile unsigned long enlpf : 1; + volatile unsigned long enif : 1; + volatile unsigned long endcoc : 1; + volatile unsigned long enrxadc : 1; + volatile unsigned long entxdac : 1; + volatile unsigned long entxdacbias : 1; + volatile unsigned long enrxrssi : 1; + volatile unsigned long enrxref : 1; + volatile unsigned long enrxi2v : 1; + volatile unsigned long enrxmix : 1; + volatile unsigned long enlnacal : 1; + volatile unsigned long enlna : 1; + volatile unsigned long txvinsel : 1; + volatile unsigned long entssi : 1; + volatile unsigned long entssiadc : 1; + volatile unsigned long entxferef : 1; + volatile unsigned long entxfebias : 1; + volatile unsigned long entxv2i : 1; + volatile unsigned long entxlo : 1; + volatile unsigned long entxpga : 1; + volatile unsigned long enpa : 1; + volatile unsigned long enrxsw : 1; + volatile unsigned long entxsw : 1; + volatile unsigned long trswpll : 1; + volatile unsigned long enrfpll : 1; + volatile unsigned long endobuler : 1; + volatile unsigned long endpll : 1; + volatile unsigned long enxtal : 1; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0xD_TypeDef; + +/// REG0xE +typedef union +{ + struct + { + volatile unsigned long dacselection : 1; + volatile unsigned long lpfrxbw : 1; + volatile unsigned long lpftxbw : 1; + volatile unsigned long lpftrxsw : 1; + volatile unsigned long enlpf : 1; + volatile unsigned long enif : 1; + volatile unsigned long endcoc : 1; + volatile unsigned long enrxadc : 1; + volatile unsigned long entxdac : 1; + volatile unsigned long entxdacbias : 1; + volatile unsigned long enrxrssi : 1; + volatile unsigned long enrxref : 1; + volatile unsigned long enrxi2v : 1; + volatile unsigned long enrxmix : 1; + volatile unsigned long enlnacal : 1; + volatile unsigned long enlna : 1; + volatile unsigned long txvinsel : 1; + volatile unsigned long entssi : 1; + volatile unsigned long entssiadc : 1; + volatile unsigned long entxferef : 1; + volatile unsigned long entxfebias : 1; + volatile unsigned long entxv2i : 1; + volatile unsigned long entxlo : 1; + volatile unsigned long entxpga : 1; + volatile unsigned long enpa : 1; + volatile unsigned long enrxsw : 1; + volatile unsigned long entxsw : 1; + volatile unsigned long trswpll : 1; + volatile unsigned long enrfpll : 1; + volatile unsigned long endobuler : 1; + volatile unsigned long endpll : 1; + volatile unsigned long enxtal : 1; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0xE_TypeDef; + +/// REG0xF +typedef union +{ + struct + { + volatile unsigned long reg_bank_sel : 1; + volatile unsigned long clkdac_sel : 1; + volatile unsigned long clkadc_sel : 1; + volatile unsigned long NC1 : 2; + volatile unsigned long sinad_tx_en : 1; + volatile unsigned long sinad_rx_en : 1; + volatile unsigned long tssi_cal_en : 1; + volatile unsigned long NC2 : 5; + volatile unsigned long sinad_hpf_coef : 2; + volatile unsigned long clkdac_inv : 1; + volatile unsigned long clkadc_inv : 1; + volatile unsigned long NC3 : 11; + volatile unsigned long sysldoen : 1; + volatile unsigned long sysldolp : 1; + volatile unsigned long endspvdd : 1; + volatile unsigned long digldolp : 1; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0xF_TypeDef; + +/// REG0x10 +typedef union +{ + struct + { + volatile unsigned long dacselection : 1; + volatile unsigned long lpfrxbw : 1; + volatile unsigned long lpftxbw : 1; + volatile unsigned long lpftrxsw : 1; + volatile unsigned long enlpf : 1; + volatile unsigned long enif : 1; + volatile unsigned long endcoc : 1; + volatile unsigned long enrxadc : 1; + volatile unsigned long entxdac : 1; + volatile unsigned long entxdacbias : 1; + volatile unsigned long enrxrssi : 1; + volatile unsigned long enrxref : 1; + volatile unsigned long enrxi2v : 1; + volatile unsigned long enrxmix : 1; + volatile unsigned long enlnacal : 1; + volatile unsigned long enlna : 1; + volatile unsigned long txvinsel : 1; + volatile unsigned long entssi : 1; + volatile unsigned long entssiadc : 1; + volatile unsigned long entxferef : 1; + volatile unsigned long entxfebias : 1; + volatile unsigned long entxv2i : 1; + volatile unsigned long entxlo : 1; + volatile unsigned long entxpga : 1; + volatile unsigned long enpa : 1; + volatile unsigned long enrxsw : 1; + volatile unsigned long entxsw : 1; + volatile unsigned long trswpll : 1; + volatile unsigned long enrfpll : 1; + volatile unsigned long endobuler : 1; + volatile unsigned long endpll : 1; + volatile unsigned long enxtal : 1; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x10_TypeDef; + +/// REG0x11 +typedef union +{ + struct + { + volatile unsigned long tx_sinad_table : 11; + volatile unsigned long NC : 21; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x11_TypeDef; + +/// REG0x12 +typedef union +{ + struct + { + volatile unsigned long lpfouttsten : 1; + volatile unsigned long lpfintsten : 1; + volatile unsigned long ifbufic20 : 3; + volatile unsigned long adcrefsel : 2; + volatile unsigned long ldoadda : 2; + volatile unsigned long buftstselection : 3; + volatile unsigned long NC : 1; + volatile unsigned long entstbufldo : 1; + volatile unsigned long adcinSel : 1; + volatile unsigned long en_gmboost : 1; + volatile unsigned long adciselr20 : 3; + volatile unsigned long adciselc20 : 3; + volatile unsigned long adcrefbwsel : 1; + volatile unsigned long adcten : 1; + volatile unsigned long fictrl30 : 4; + volatile unsigned long flvcm10 : 2; + volatile unsigned long ldoifsel3v10 : 2; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x12_TypeDef; + +/// REG0x13 +typedef union +{ + struct + { + volatile unsigned long r2_rx : 2; + volatile unsigned long c1_rx : 2; + volatile unsigned long rz_rx : 5; + volatile unsigned long icp_rx : 5; + volatile unsigned long icpoff20 : 3; + volatile unsigned long icpsel : 1; + volatile unsigned long r2_tx : 2; + volatile unsigned long c1_tx : 2; + volatile unsigned long rz_tx : 5; + volatile unsigned long icp_tx : 5; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x13_TypeDef; + +/// REG0x14 +typedef union +{ + struct + { + volatile unsigned long dc_i_0db : 8; + volatile unsigned long dc_q_0db : 8; + volatile unsigned long dc_i_3db : 8; + volatile unsigned long dc_q_3db : 8; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x14_TypeDef; + +/// REG0x15 +typedef union +{ + struct + { + volatile unsigned long dc_i_6db : 8; + volatile unsigned long dc_q_6db : 8; + volatile unsigned long dc_i_9db : 8; + volatile unsigned long dc_q_9db : 8; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x15_TypeDef; + +/// REG0x16 +typedef union +{ + struct + { + volatile unsigned long dc_i_12db : 8; + volatile unsigned long dc_q_12db : 8; + volatile unsigned long dc_i_15db : 8; + volatile unsigned long dc_q_15db : 8; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x16_TypeDef; + +/// REG0x17 +typedef union +{ + struct + { + volatile unsigned long dc_i_18db : 8; + volatile unsigned long dc_q_18db : 8; + volatile unsigned long dc_i_21db : 8; + volatile unsigned long dc_q_21db : 8; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x17_TypeDef; + +/// REG0x18 +typedef union +{ + struct + { + volatile unsigned long dc_i_24db : 8; + volatile unsigned long dc_q_24db : 8; + volatile unsigned long dc_i_27db : 8; + volatile unsigned long dc_q_27db : 8; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x18_TypeDef; + +/// REG0x19 +typedef union +{ + struct + { + volatile unsigned long dc_i_30db : 8; + volatile unsigned long dc_q_30db : 8; + volatile unsigned long dc_i_33db : 8; + volatile unsigned long dc_q_33db : 8; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x19_TypeDef; + +/// REG0x1A +typedef union +{ + struct + { + volatile unsigned long dc_i_36db : 8; + volatile unsigned long dc_q_36db : 8; + volatile unsigned long dc_i_39db : 8; + volatile unsigned long dc_q_39db : 8; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x1A_TypeDef; + +/// REG0x1B +typedef union +{ + struct + { + volatile unsigned long dc_i_42db : 8; + volatile unsigned long dc_q_42db : 8; + volatile unsigned long dc_i_45db : 8; + volatile unsigned long dc_q_45db : 8; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x1B_TypeDef; + +/// REG0x1C +typedef union +{ + struct + { + volatile unsigned long dac_out_qspi : 10; + volatile unsigned long NC1 : 2; + volatile unsigned long dac_out_ispi : 10; + volatile unsigned long NC2 : 10; + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x1C_TypeDef; + +#else + +/// REG0x0 +typedef union +{ + struct + { + volatile unsigned int pwdpll : 1; /**< pwdpll */ + volatile unsigned int cp20 : 3; /**< cp curent control 0to 350uA 50uA step */ + volatile unsigned int spideten : 1; /**< unlock detect enable fron spi 1:enable */ + volatile unsigned int hvref10 : 2; /**< high vth control for unlock detect 00:0.85V;01:0.9V;10:0.95V;11:1.05V */ + volatile unsigned int lvref10 : 2; /**< low vth control for unlock detect 00:0.2V;01:0.3V;10:0.35V;11:0.4V */ + volatile unsigned int Rzctrl26M : 1; /**< Rz ctrl in 26M mode:1:normal;0:add 14K */ + volatile unsigned int LoopRzctrl30 : 4; /**< Rz ctrl:2K to 17K,1K step */ + volatile unsigned int rpc10 : 2; /**< second pole Rp ctrl:00:30K;01:10K;10:22K;11:2K */ + volatile unsigned int nsyn : 1; /**< N divider rst */ + volatile unsigned int cksel10 : 2; /**< 0:26M;1:40M;2:24M;3:19.2M */ + volatile unsigned int spitrig : 1; /**< SPI band selection trigger signal */ + volatile unsigned int CKEn : 1; /**< 1: Enable all clock phases(480M/160M); 0 : Disable all clocks; */ + volatile unsigned int band41 : 4; /**< band manual value */ + volatile unsigned int bandmanual : 1; /**< 1:band manual;0:band auto */ + volatile unsigned int dsptrig : 1; /**< band selection trigger signal */ + volatile unsigned int xtalIctrl : 1; /**< 0:large current;1:small current */ + volatile unsigned int ckTestEn : 1; /**< 1: Enable clock test path; 0 : Disable clock test path; */ + volatile unsigned int xamp31 : 3; /**< xtal OSC amp control */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x0_TypeDef; + +/// REG0x1 +typedef union +{ + struct + { + volatile unsigned int acoef80 : 9; /**< ˲֧·ϵ */ + volatile unsigned int bcoef20 : 3; /**< ˲propotional֧·ϵ */ + volatile unsigned int bckphoffset50 : 6; /**< PD˵divʱӵӳ */ + volatile unsigned int rckphoffset50 : 6; /**< PD˵refʱӵӳ */ + volatile unsigned int bypass52M : 1; /**< bypass 52Mʱӣ26Mʱ */ + volatile unsigned int tst2xpden : 1; /**< ѡҪźţ1ΪPD0Ϊ52Mʱ */ + volatile unsigned int tst2xen : 1; /**< ʹܲ */ + volatile unsigned int calspitrig : 1; /**< ͨĴƵʵУ׼ʱдΪ0дΪ1 */ + volatile unsigned int bypassdmsb : 1; /**< ˲ʱbypassDmsb֧· */ + volatile unsigned int manual : 1; /**< DmsbDlsbΪֶ */ + volatile unsigned int frecalbypass : 1; /**< bypass ƵʵԶУ׼ܣֶ */ + volatile unsigned int rstnspi : 1; /**< ͨĴreset */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x1_TypeDef; + +/// REG0x2 +typedef union +{ + struct + { + volatile unsigned int arbpden : 1; /**< ͨĴʹarbiter BBPD */ + volatile unsigned int endoubler : 1; /**< ͨĴʹdoubler */ + volatile unsigned int trackenspi : 1; /**< ͨĴʹܿ㷨 */ + volatile unsigned int Dcal80 : 9; /**< ͨĴֶDcal */ + volatile unsigned int Dmsbspi20 : 3; /**< ͨĴֶDmsb */ + volatile unsigned int Dlsbspi40 : 5; /**< ͨĴֶDlsb */ + volatile unsigned int updatecycle110 : 12; /**< ÿ㷨ʱݵʱ */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x2_TypeDef; + +/// REG0x3 +typedef union +{ + struct + { + volatile unsigned int numdn110 : 12; /**< λͺĴ */ + volatile unsigned int numup110 : 12; /**< λǰĴ */ + volatile unsigned int arbpddelay30 : 4; /**< arbiter BBPDеdelay */ + volatile unsigned int hysen : 1; /**< ʹλij͹ */ + volatile unsigned int phacalbypass : 1; /**< ˲ʱУ׼ɺԲʹλtracking,ӶУ׼ĽǷȷ */ + volatile unsigned int f2xldovsel3v10 : 2; /**< LDOѹLDOһλÿλѾlevel shiftת001.2V01 101.3V111.4V */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x3_TypeDef; + +/// REG0x4 +typedef union +{ + struct + { + volatile unsigned int manual : 1; /**< vco manual band control enable 1:manual */ + volatile unsigned int bandm60 : 7; /**< vco band manual control */ + volatile unsigned int calresc10 : 2; /**< vco nwell voltage for calibration:00,0.5V;01,0.6V;10,0.7V;11,0.8V */ + volatile unsigned int rvco20 : 3; /**< rfpll vco bias current control */ + volatile unsigned int cpldo10 : 2; /**< Charge Pump LDO voltage control. */ + volatile unsigned int NC : 1; /**< No description */ + volatile unsigned int trswspi : 1; /**< trsw spi control:0,spi;1:cpu */ + volatile unsigned int trswen : 1; /**< enable cpu trsw control 1:enable */ + volatile unsigned int nrsten : 1; /**< N counter reset enable */ + volatile unsigned int reset : 1; /**< reset rfpll fb divider loading */ + volatile unsigned int pwdlogen : 1; /**< power down rfpll LO generation */ + volatile unsigned int pwdvco : 1; /**< power down rfpll vco */ + volatile unsigned int pwdpll : 1; /**< power down rfpll pll */ + volatile unsigned int nint70 : 8; /**< power down rfpll vco */ + volatile unsigned int intmode : 1; /**< power down rfpll pll */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x4_TypeDef; + +/// REG0x5 +typedef union +{ + struct + { + volatile unsigned int errdetspien : 1; /**< spi enable rfpll unlock detection */ + volatile unsigned int spitrigger : 1; /**< VCO calibration trigger from spi */ + volatile unsigned int ckrefsel : 1; /**< reference clock freq select: 0, 26M; 1, 52M */ + volatile unsigned int ckpsel : 1; /**< reference clock pol select */ + volatile unsigned int locap30 : 4; /**< LO Mixer load cap control */ + volatile unsigned int lmngm20 : 3; /**< LO Mixer negative resistor control */ + volatile unsigned int sdiv210 : 2; /**< rpll 3.2G div2 input dc bias control */ + volatile unsigned int pllldo10 : 2; /**< pll ldo output voltage control: 00, 1.2V; 01 1.3V; 10, 1.4V;11 1.5V */ + volatile unsigned int vcoldo10 : 2; /**< vco ldo output voltage control: 00, 1.2V; 01 1.3V; 10, 1.4V;11 1.5V */ + volatile unsigned int lwvref10 : 2; /**< unlock detection voltage control(low) */ + volatile unsigned int lnvref10 : 2; /**< cdyn detection voltage control(low) */ + volatile unsigned int hwvref10 : 2; /**< unlock detection voltage control(high) */ + volatile unsigned int hnvref10 : 2; /**< cdyn detection voltage control(high) */ + volatile unsigned int captunedir : 1; /**< cap tune direction */ + volatile unsigned int pwdcpamp10 : 2; /**< 00,cp with op fb; 01, cp wi up/dn connect together; 11, cp wi up/dn connect to gnd/vdd */ + volatile unsigned int dcal30 : 4; /**< rfpll cp bias current calibration */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x5_TypeDef; + +/// REG0x6 +typedef union +{ + struct + { + volatile unsigned int vcmsel10 : 2; /**< ADC OP CM voltage adjustment(0:0.625 */ + volatile unsigned int tmpEn : 1; /**< 1: Enable temperature sensor; 0 : Disable temperature sensor; */ + volatile unsigned int NC : 1; /**< Reserved */ + volatile unsigned int lpfcapcalq50 : 6; /**< lpf Q path calibiration input */ + volatile unsigned int lpfcapcali50 : 6; /**< lpf I path calibiration input */ + volatile unsigned int dcocq : 8; /**< dcoc Q path input */ + volatile unsigned int dcoci : 8; /**< dcoc I path input */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x6_TypeDef; + +/// REG0x7 +typedef union +{ + struct + { + volatile unsigned int digdcoen : 1; /**< dcoc input selection,1: digital 0: spi */ + volatile unsigned int spilpfrxg30 : 4; /**< rxif gain, 0000-1111 0dB - 45dB step:3dB */ + volatile unsigned int autorxifgen : 1; /**< rxif gain control selection, 1: auto control 0: spi */ + volatile unsigned int pwdxtalbuf : 1; /**< 1: Power-down crystal oscillator buffer;;0: Enable crystal oscillator buffer; */ + volatile unsigned int pwdxtalcore : 1; /**< 1: Power-down crystal oscillator core;;0: Enable crystal oscillator core; */ + volatile unsigned int lpfvcmic10 : 2; /**< control auxiliary pmos pair gate voltage,default 01 */ + volatile unsigned int lpftxTest : 1; /**< tx test control bit,1 : tx test mode 0: default */ + volatile unsigned int xtalenref : 1; /**< 1: Enable crystal oscillator output as the reference to RF PLL only;;0: Enable crystal oscillator output as the reference to frequency doubler only. */ + volatile unsigned int voc1v210 : 2; /**< SPI/Digital regulator output programming; 00:1.2;01:1.3;10,1.4;11:1.5 */ + volatile unsigned int swm1v210 : 2; /**< Path selection of the switched output in low-power mode,00: shutdown, 01: high res, 10:res/2,11:res/3 */ + volatile unsigned int NC : 1; /**< NC */ + volatile unsigned int chin60 : 7; /**< substitute for cpu channel value */ + volatile unsigned int cksdmsel20 : 3; /**< rfpll sigma delta clock select:;0: 26MHz;;1: 40MHz;;2: 24MHz;;3: 19.2MHz;;4: 52MHz;;5:104MHz; */ + volatile unsigned int ckbandsel10 : 2; /**< vco band calibration clock select:;0: 26MHz;;1: 40MHz;;2: 24MHz;;3: 19.2MHz; */ + volatile unsigned int var10 : 2; /**< Kvco control: 0:40MHz/V;1:60MHz/V;2:60MHz/V;3:80MHz/V */ + volatile unsigned int enckcali : 1; /**< 0:VCO calibration clock do not power down;1: auto power down vco calibration clock; */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x7_TypeDef; + +/// REG0x8 +typedef union +{ + struct + { + volatile unsigned int vsrxmixldo10 : 2; /**< rx mixer LDO vout 00-11 1.2-1.5V */ + volatile unsigned int vsrxlnaldo10 : 2; /**< rx lna LDO vout 00-11 1.2-1.5V */ + volatile unsigned int isrxref10 : 2; /**< rx ref ib selection 00-11 10-15uA */ + volatile unsigned int isrxlna20 : 3; /**< rx lna ib selection 000-111 50-110uA */ + volatile unsigned int isrxlnac10 : 2; /**< rx lnacali ib selection 00-11 40-70uA */ + volatile unsigned int isrxdiv10 : 2; /**< rx div ib selection 00-11 10-25uA */ + volatile unsigned int vbsrxlo20 : 3; /**< rx lo biasing voltage: 000-111 0.4-0.75V */ + volatile unsigned int vresrxlo : 1; /**< rx lo vb ref voltage: 0-1 0.4-0.5V */ + volatile unsigned int ibsrxi2v10 : 2; /**< rx i2v ib selection 00-11 5-15uA */ + volatile unsigned int vcmsrxi2v : 1; /**< rx i2v vcm selction 0-1 0.6-0.5V */ + volatile unsigned int isrssigm10 : 2; /**< rx rssi gm ib selection 00-11 40-55uA */ + volatile unsigned int stbrssi10 : 2; /**< rx rssi stable time 00-11 150-450ns step:100ns */ + volatile unsigned int rssith50 : 6; /**< rx rssi threshhold Pant=-29dBm(th=000111) 0:-37dBm step:1dB */ + volatile unsigned int nc : 2; /**< reserved */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x8_TypeDef; + +/// REG0x9 +typedef union +{ + struct + { + volatile unsigned int agcrxfeEn : 1; /**< enble rxfe agc by mcu, 0/1 gctr by spi/mcu */ + volatile unsigned int grxlnaspi10 : 2; /**< rx lna gain 00-11 0/+6/+12/+18dBr */ + volatile unsigned int grxi2vspi10 : 2; /**< rx i2v gain 00-11 0/+6/+6/+12dBr */ + volatile unsigned int grssi10 : 2; /**< rx rssi option gain */ + volatile unsigned int grxlnacali20 : 3; /**< rx lan cali gain,000-111 -50~-5.5 caliin->i2vout step:6dB */ + volatile unsigned int rssiten : 1; /**< rssi analog v output test enable */ + volatile unsigned int dcaprxi2v10 : 2; /**< V2T: I2V feedback cap tuning 00-11: + 0/1p/2p/3p */ + volatile unsigned int drxfbrm : 1; /**< V2T: feedback mathing res on */ + volatile unsigned int dcaptrsw20 : 3; /**< V2T: 7/0 @ tx/rx mode */ + volatile unsigned int nc : 15; /**< reserved */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x9_TypeDef; + +/// REG0xA +typedef union +{ + struct + { + volatile unsigned int disrefPA10 : 2; /**< PA reference bias current programming for Constant-gm bias circuit,10u to 16.5uA */ + volatile unsigned int disrefpga10 : 2; /**< RFPGA reference bias current programming for Constant-gm bias circuit,10u to 16.5uA */ + volatile unsigned int dbpab30 : 4; /**< PA class-B input bias level programming */ + volatile unsigned int dbpaa30 : 4; /**< PA class-A input bias level programming */ + volatile unsigned int dbcpa10 : 2; /**< PA cascode device bias level programming,00(2.2v), 01(2.5v), 10(2.8v),11(3.0v) */ + volatile unsigned int noConn10 : 2; /**< No Connected */ + volatile unsigned int dcapbuf30 : 4; /**< PA buf output capacitor tuning */ + volatile unsigned int dbbuf30 : 4; /**< PA buf input device bias level programming */ + volatile unsigned int dbcbuf10 : 2; /**< PA buf cascode device bias level programming,00(2.2v), 01(2.5v), 10(2.8v),11(3.0v) */ + volatile unsigned int noConn10_ : 2; /**< No Connected */ + volatile unsigned int dtr30 : 4; /**< PA ramping-up time selection,0.13us(1111) to 3.45us(0000) */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0xA_TypeDef; + +/// REG0xB +typedef union +{ + struct + { + volatile unsigned int dcpga20 : 3; /**< RFPGA cascode device biaslevel programming */ + volatile unsigned int noConn : 1; /**< No Connected */ + volatile unsigned int dbpga30 : 4; /**< RFPGA input device bias level programming */ + volatile unsigned int dcappga30 : 4; /**< RFPGA output capacitor tuning */ + volatile unsigned int dcorMod30 : 4; /**< Modulator&RFPGA gain tuning for Pout calibration */ + volatile unsigned int dvlo20 : 3; /**< Modulator LO bias level programming,0.9v~1.07v,100(1.0v) */ + volatile unsigned int noConn_ : 1; /**< No Connected */ + volatile unsigned int dvcmo20 : 3; /**< Modulator V-I common mode voltage selection,010(vdd/2) */ + volatile unsigned int noConn__ : 1; /**< No Connected */ + volatile unsigned int dcapmod30 : 4; /**< Modulator output capacitor tuning */ + volatile unsigned int gctrlmod30 : 4; /**< Modulator gain control,3dB/step,0001(default gain+3),0010,0100(default gain-3),1000(default gain-6) */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0xB_TypeDef; + +/// REG0xC +typedef union +{ + struct + { + volatile unsigned int gctrlpga20 : 3; /**< RFPGA gain control. 111(max),110(max-3),101(max-6),100(max-9),011(max-12),010(max-18),001(max-24),000(max-30) */ + volatile unsigned int noConn : 1; /**< No Connected */ + volatile unsigned int dgainbuf20 : 3; /**< PA buf gain control,10dB(1111)~-5dB(001),4.5dB/step */ + volatile unsigned int noConn_ : 1; /**< No Connected */ + volatile unsigned int dgainPA20 : 3; /**< PA gain control,9dB(111)~-4dB(001),5dB/step */ + volatile unsigned int enTSSItst : 1; /**< TSSI test enable */ + volatile unsigned int dcorPA30 : 4; /**< PA gain tuning for Pout calibration */ + volatile unsigned int vregsel10 : 2; /**< RFLDO output voltage selection.00:1.2v; 01:1.3v; 10:1.4v; 11:1.5v */ + volatile unsigned int TSSIiref10 : 2; /**< TSSI reference bias current programming for Constant-gm bias circuit,10u to 16.5uA */ + volatile unsigned int gtssi10 : 2; /**< TSSI output gain programming,4K(00)/5K(01)/6K(10)/7K(11) */ + volatile unsigned int stbtssi10 : 2; /**< TSSI output stable time programming,0.15us(00) to 0.45us(11) */ + volatile unsigned int PcaliATTs10 : 2; /**< TSSI Pout calibration input attenuation selection,00(-6dB)~11(-24dB),6dB/step */ + volatile unsigned int enPcaliGm : 1; /**< TSSI Pout calibration option to enable Gm1 */ + volatile unsigned int enPcali : 1; /**< TSSI Pout calibration enable */ + volatile unsigned int enIQcali : 1; /**< TSSI IQ calibration enable */ + volatile unsigned int enDCcaliGm1 : 1; /**< TSSI DC calibration Gm1 block enable for -30~-15dBm input range */ + volatile unsigned int enDCcali : 1; /**< DC/IQ calibration enable.enDCcali=1 for DC or IQ calibration */ + volatile unsigned int TSSIsel : 1; /**< TSSI output selection.TSSIsel=1 for Pout calibration;TSSIsel=0 for DC/IQ calibration */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0xC_TypeDef; + +/// REG0xD +typedef union +{ + struct + { + volatile unsigned int dacselection : 1; /**< 0: external dac, 1: internal dac */ + volatile unsigned int lpfrxbw : 1; /**< lpf rx bandwidth selection 1: high bandwidth(19MHz) 0: low bandwidth(9MHz); */ + volatile unsigned int lpftxbw : 1; /**< lpf tx bandwidth selection 1: high bandwidth(29MHz) 0: low bandwidth(14MHz); */ + volatile unsigned int lpftrxsw : 1; /**< LPF tx rx switch(1:tx,0:rx) */ + volatile unsigned int enlpf : 1; /**< LPF enable */ + volatile unsigned int enif : 1; /**< ADC, DAC Ldo enable */ + volatile unsigned int endcoc : 1; /**< DCOC DAC enable */ + volatile unsigned int enrxadc : 1; /**< RX ADC enable */ + volatile unsigned int entxdac : 1; /**< TX dac enable */ + volatile unsigned int entxdacbias : 1; /**< TX dac bias enable */ + volatile unsigned int enrxrssi : 1; /**< RX RF Rssi enable */ + volatile unsigned int enrxref : 1; /**< RX RF Vref enable */ + volatile unsigned int enrxi2v : 1; /**< RX I2V enable */ + volatile unsigned int enrxmix : 1; /**< RX mixer enable */ + volatile unsigned int enlnacal : 1; /**< RX look back lna input enable */ + volatile unsigned int enlna : 1; /**< Rxfe lna enable */ + volatile unsigned int txvinsel : 1; /**< Txfe input selection(0,cal when need bypass TX filter,1:normal) */ + volatile unsigned int entssi : 1; /**< Txfe tssi enable */ + volatile unsigned int entssiadc : 1; /**< Txfe tssi adc enable */ + volatile unsigned int entxferef : 1; /**< Txfe reference enable */ + volatile unsigned int entxfebias : 1; /**< Txfe bias enable */ + volatile unsigned int entxv2i : 1; /**< Tx v2i enable */ + volatile unsigned int entxlo : 1; /**< Tx LO enable */ + volatile unsigned int entxpga : 1; /**< TX PGA enable */ + volatile unsigned int enpa : 1; /**< Tx PA enable */ + volatile unsigned int enrxsw : 1; /**< RX switch enable */ + volatile unsigned int entxsw : 1; /**< TX switch enable */ + volatile unsigned int trswpll : 1; /**< rf pll tx rx switch */ + volatile unsigned int enrfpll : 1; /**< rf pll enable */ + volatile unsigned int endobuler : 1; /**< dobuler enable */ + volatile unsigned int endpll : 1; /**< digital pll enable */ + volatile unsigned int enxtal : 1; /**< xtal enable signal */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0xD_TypeDef; + +/// REG0xE +typedef union +{ + struct + { + volatile unsigned int dacselection : 1; /**< 0: external dac, 1: internal dac */ + volatile unsigned int lpfrxbw : 1; /**< lpf rx bandwidth selection 1: high bandwidth(19MHz) 0: low bandwidth(9MHz); */ + volatile unsigned int lpftxbw : 1; /**< lpf tx bandwidth selection 1: high bandwidth(29MHz) 0: low bandwidth(14MHz); */ + volatile unsigned int lpftrxsw : 1; /**< LPF tx rx switch(1:tx,0:rx) */ + volatile unsigned int enlpf : 1; /**< LPF enable */ + volatile unsigned int enif : 1; /**< ADC, DAC Ldo enable */ + volatile unsigned int endcoc : 1; /**< DCOC DAC enable */ + volatile unsigned int enrxadc : 1; /**< RX ADC enable */ + volatile unsigned int entxdac : 1; /**< TX dac enable */ + volatile unsigned int entxdacbias : 1; /**< TX dac bias enable */ + volatile unsigned int enrxrssi : 1; /**< RX RF Rssi enable */ + volatile unsigned int enrxref : 1; /**< RX RF Vref enable */ + volatile unsigned int enrxi2v : 1; /**< RX I2V enable */ + volatile unsigned int enrxmix : 1; /**< RX mixer enable */ + volatile unsigned int enlnacal : 1; /**< RX look back lna input enable */ + volatile unsigned int enlna : 1; /**< Rxfe lna enable */ + volatile unsigned int txvinsel : 1; /**< Txfe input selection(0,cal when need bypass TX filter,1:normal) */ + volatile unsigned int entssi : 1; /**< Txfe tssi enable */ + volatile unsigned int entssiadc : 1; /**< Txfe tssi adc enable */ + volatile unsigned int entxferef : 1; /**< Txfe reference enable */ + volatile unsigned int entxfebias : 1; /**< Txfe bias enable */ + volatile unsigned int entxv2i : 1; /**< Tx v2i enable */ + volatile unsigned int entxlo : 1; /**< Tx LO enable */ + volatile unsigned int entxpga : 1; /**< TX PGA enable */ + volatile unsigned int enpa : 1; /**< Tx PA enable */ + volatile unsigned int enrxsw : 1; /**< RX switch enable */ + volatile unsigned int entxsw : 1; /**< TX switch enable */ + volatile unsigned int trswpll : 1; /**< rf pll tx rx switch */ + volatile unsigned int enrfpll : 1; /**< rf pll enable */ + volatile unsigned int endobuler : 1; /**< dobuler enable */ + volatile unsigned int endpll : 1; /**< digital pll enable */ + volatile unsigned int enxtal : 1; /**< xtal enable signal */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0xE_TypeDef; + +/// REG0xF +typedef union +{ + struct + { + volatile unsigned int regbanksel : 1; /**< Register Bank Select. 0x0: Bank0 (Reg00~Reg14); ; 0x1: Bank1 (Reg16~Reg30) */ + volatile unsigned int clkdacsel : 1; /**< DAC Clock Select. 0x0: 80MHz; 0x1: 160MHz */ + volatile unsigned int clkadcsel : 1; /**< ADCClock Select. 0x0: 40MHz; 0x1: 80MHz */ + volatile unsigned int NC : 1; /**< NC */ + volatile unsigned int NC_ : 1; /**< NC */ + volatile unsigned int sinadtxen : 1; /**< TX Sinad Enable */ + volatile unsigned int sinadrxen : 1; /**< RX Sinad Detect Enable */ + volatile unsigned int tssicalen : 1; /**< TSSI Calibration Enable, enable 40M clock */ + volatile unsigned int NC__ : 5; /**< NC */ + volatile unsigned int sinadhpfcoef : 2; /**< HPF Coefficence for RX Siand Detect. 0x0: 1/8 0x1: 1/32; 0x2: 1/128; 0x3: 1/1024 */ + volatile unsigned int clkdacinv : 1; /**< DAC Clock Invert */ + volatile unsigned int clkadcinv : 1; /**< ADC Clock Invert */ + volatile unsigned int reserved : 11; /**< Reserved */ + volatile unsigned int sysldoen : 1; /**< enable sysldo */ + volatile unsigned int sysldolp : 1; /**< sysldo low power enable */ + volatile unsigned int endspvdd : 1; /**< dsp vdd enable */ + volatile unsigned int digldolp : 1; /**< digldo low power enable */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0xF_TypeDef; + +/// REG0x10 +typedef union +{ + struct + { + volatile unsigned int dacselection : 1; /**< 0: external dac, 1: internal dac */ + volatile unsigned int lpfrxbw : 1; /**< lpf rx bandwidth selection 1: high bandwidth(19MHz) 0: low bandwidth(9MHz); */ + volatile unsigned int lpftxbw : 1; /**< lpf tx bandwidth selection 1: high bandwidth(29MHz) 0: low bandwidth(14MHz); */ + volatile unsigned int lpftrxsw : 1; /**< LPF tx rx switch(1:tx,0:rx) */ + volatile unsigned int enlpf : 1; /**< LPF enable */ + volatile unsigned int enif : 1; /**< ADC, DAC Ldo enable */ + volatile unsigned int endcoc : 1; /**< DCOC DAC enable */ + volatile unsigned int enrxadc : 1; /**< RX ADC enable */ + volatile unsigned int entxdac : 1; /**< TX dac enable */ + volatile unsigned int entxdacbias : 1; /**< TX dac bias enable */ + volatile unsigned int enrxrssi : 1; /**< RX RF Rssi enable */ + volatile unsigned int enrxref : 1; /**< RX RF Vref enable */ + volatile unsigned int enrxi2v : 1; /**< RX I2V enable */ + volatile unsigned int enrxmix : 1; /**< RX mixer enable */ + volatile unsigned int enlnacal : 1; /**< RX look back lna input enable */ + volatile unsigned int enlna : 1; /**< Rxfe lna enable */ + volatile unsigned int txvinsel : 1; /**< Txfe input selection(0,cal when need bypass TX filter,1:normal) */ + volatile unsigned int entssi : 1; /**< Txfe tssi enable */ + volatile unsigned int entssiadc : 1; /**< Txfe tssi adc enable */ + volatile unsigned int entxferef : 1; /**< Txfe reference enable */ + volatile unsigned int entxfebias : 1; /**< Txfe bias enable */ + volatile unsigned int entxv2i : 1; /**< Tx v2i enable */ + volatile unsigned int entxlo : 1; /**< Tx LO enable */ + volatile unsigned int entxpga : 1; /**< TX PGA enable */ + volatile unsigned int enpa : 1; /**< Tx PA enable */ + volatile unsigned int enrxsw : 1; /**< RX switch enable */ + volatile unsigned int entxsw : 1; /**< TX switch enable */ + volatile unsigned int trswpll : 1; /**< rf pll tx rx switch */ + volatile unsigned int enrfpll : 1; /**< rf pll enable */ + volatile unsigned int endobuler : 1; /**< dobuler enable */ + volatile unsigned int endpll : 1; /**< digital pll enable */ + volatile unsigned int enxtal : 1; /**< xtal enable signal */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x10_TypeDef; + +/// REG0x11 +typedef union +{ + struct + { + volatile unsigned int txsinadtable : 11; /**< TX Sinad Table;D[0] = 0: Write I Path Table Data;D[0] = 1: Write Q Path Table Data;LSBD[1] ;Both I and Q need 16 number data */ + volatile unsigned int reserved : 21; /**< Reserved */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x11_TypeDef; + +/// REG0x12 +typedef union +{ + struct + { + volatile unsigned int lpfouttsten : 1; /**< lpf output test enable,0:disenable,1:enable */ + volatile unsigned int lpfintsten : 1; /**< lpf input test enable,0:disenable,1:enable */ + volatile unsigned int ifbufic20 : 3; /**< test buffer bias current control,0:low, 1:high */ + volatile unsigned int ifadcvcmsel : 2; /**< if adc reference voltage selection. */ + volatile unsigned int ldodpll10 : 2; /**< digital pll and xtal ldo voutselection. 00:low, 11:high */ + volatile unsigned int NC : 1; /**< Reserved bit; */ + volatile unsigned int buftstselection : 1; /**< buffer input selection:1:lpf, 0:rssidactst,rssitst,tssitst,adcstst1 */ + volatile unsigned int entstbufldo : 1; /**< enable test buffer ldo, 0:disenable,1:enable */ + volatile unsigned int NC_ : 1; /**< Reserved bit; */ + volatile unsigned int dldovctrl10 : 2; /**< dig do output control voltage: 0:1.2V 0.1V/step */ + volatile unsigned int adcinSel : 1; /**< SAR ADC input selection;0:TSSI, 1:Temperature */ + volatile unsigned int adciselr20 : 3; /**< adc reference bias current selection,0:0.45x,1:0.5x,2:0.55X,3:0.6x,4:0.9x,5:1X,6:1.1X,7:1.2X */ + volatile unsigned int adciselc20 : 3; /**< adc core bias current selection,0:5x,1:0.6x,2:0.7X,3:0.8x,4:1.0x,5:1.2X,6:1.4X,7:1.7X */ + volatile unsigned int adcrefbwsel : 1; /**< adc bandwidth selection.0:40MHz, 1:80MHz */ + volatile unsigned int adcten : 1; /**< adc test enable(1:only I work, 0:both path work) */ + volatile unsigned int fictrl30 : 4; /**< lpf bias current selection, 0:low, 15:high */ + volatile unsigned int flvcm10 : 2; /**< lpf common mode voltage selection,00:low , 11: high */ + volatile unsigned int ldoifsel3v10 : 2; /**< If ldo vout selection:00:low, 11: high */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x12_TypeDef; + +/// REG0x13 +typedef union +{ + struct + { + volatile unsigned int r2rx10 : 2; /**< rx mode loopfilter R2 control */ + volatile unsigned int c1rx10 : 2; /**< rx mode loopfilter C1 control */ + volatile unsigned int rzrx40 : 5; /**< rx mode loopfilter Rz control */ + volatile unsigned int icprx40 : 5; /**< rx mode cp current control */ + volatile unsigned int icpoff20 : 3; /**< cp offset current control */ + volatile unsigned int icpsel : 1; /**< icp bias select: 0, internal; 1, external */ + volatile unsigned int r2tx10 : 2; /**< tx mode loopfilter R2 control */ + volatile unsigned int c1tx10 : 2; /**< tx mode loopfilter C1 control */ + volatile unsigned int rztx40 : 5; /**< tx mode loopfilter Rz control */ + volatile unsigned int icptx40 : 5; /**< tx mode cp current control */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x13_TypeDef; + +/// REG0x14 +typedef union +{ + struct + { + volatile unsigned int dci0db : 8; /**< RX dcoc I path input for 0dB of PGA */ + volatile unsigned int dcq0db : 8; /**< RX dcoc Q path input for 0dB of PGA */ + volatile unsigned int dci3db : 8; /**< RX dcoc I path input for 3dB of PGA */ + volatile unsigned int dcq3db : 8; /**< RX dcoc Q path input for 3dB of PGA */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x14_TypeDef; + +/// REG0x15 +typedef union +{ + struct + { + volatile unsigned int dci6db : 8; /**< RX dcoc I path input for 6dB of PGA */ + volatile unsigned int dcq6db : 8; /**< RX dcoc Q path input for 6dB of PGA */ + volatile unsigned int dci9db : 8; /**< RX dcoc I path input for 9dB of PGA */ + volatile unsigned int dcq9db : 8; /**< RX dcoc Q path input for 9dB of PGA */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x15_TypeDef; + +/// REG0x16 +typedef union +{ + struct + { + volatile unsigned int dci12db : 8; /**< RX dcoc I path input for 12dB of PGA */ + volatile unsigned int dcq12db : 8; /**< RX dcoc Q path input for 12dB of PGA */ + volatile unsigned int dci15db : 8; /**< RX dcoc I path input for 15dB of PGA */ + volatile unsigned int dcq15db : 8; /**< RX dcoc Q path input for 15dB of PGA */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x16_TypeDef; + +/// REG0x17 +typedef union +{ + struct + { + volatile unsigned int dci18db : 8; /**< RX dcoc I path input for 18dB of PGA */ + volatile unsigned int dcq18db : 8; /**< RX dcoc Q path input for 18dB of PGA */ + volatile unsigned int dci21db : 8; /**< RX dcoc I path input for 21dB of PGA */ + volatile unsigned int dcq21db : 8; /**< RX dcoc Q path input for 21dB of PGA */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x17_TypeDef; + +/// REG0x18 +typedef union +{ + struct + { + volatile unsigned int dci24db : 8; /**< RX dcoc I path input for 24dB of PGA */ + volatile unsigned int dcq24db : 8; /**< RX dcoc Q path input for 24dB of PGA */ + volatile unsigned int dci27db : 8; /**< RX dcoc I path input for 27dB of PGA */ + volatile unsigned int dcq27db : 8; /**< RX dcoc Q path input for 27dB of PGA */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x18_TypeDef; + +/// REG0x19 +typedef union +{ + struct + { + volatile unsigned int dci30db : 8; /**< RX dcoc I path input for 30dB of PGA */ + volatile unsigned int dcq30db : 8; /**< RX dcoc Q path input for 30dB of PGA */ + volatile unsigned int dci33db : 8; /**< RX dcoc I path input for 33dB of PGA */ + volatile unsigned int dcq33db : 8; /**< RX dcoc Q path input for 33dB of PGA */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x19_TypeDef; + +/// REG0x1A +typedef union +{ + struct + { + volatile unsigned int dci36db : 8; /**< RX dcoc I path input for 36dB of PGA */ + volatile unsigned int dcq36db : 8; /**< RX dcoc Q path input for 36dB of PGA */ + volatile unsigned int dci39db : 8; /**< RX dcoc I path input for 39dB of PGA */ + volatile unsigned int dcq39db : 8; /**< RX dcoc Q path input for 39dB of PGA */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x1A_TypeDef; + +/// REG0x1B +typedef union +{ + struct + { + volatile unsigned int dci42db : 8; /**< RX dcoc I path input for 42dB of PGA */ + volatile unsigned int dcq42db : 8; /**< RX dcoc Q path input for 42dB of PGA */ + volatile unsigned int dci45db : 8; /**< RX dcoc I path input for 45dB of PGA */ + volatile unsigned int dcq45db : 8; /**< RX dcoc Q path input for 45dB of PGA */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x1B_TypeDef; + +/// REG0x1C +typedef union +{ + struct + { + volatile unsigned int dacoutqspi90 : 10; /**< DAC Q channel input in analog test only; */ + volatile unsigned int NC : 2; /**< Reserved bits; */ + volatile unsigned int dacoutispi90 : 10; /**< DAC I channel input in analog test only; */ + volatile unsigned int NC_ : 10; /**< Reserved bits; */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x1C_TypeDef; // trx reg28 just for test +#define BK7011_TRxV2ABASE 0X00800080 +#endif + +/// BK7011TRxV2A +struct BK7011TRxV2A_TypeDef +{ + volatile BK7011_TRxV2A_REG0x0_TypeDef *REG0x0; + volatile BK7011_TRxV2A_REG0x1_TypeDef *REG0x1; + volatile BK7011_TRxV2A_REG0x2_TypeDef *REG0x2; + volatile BK7011_TRxV2A_REG0x3_TypeDef *REG0x3; + volatile BK7011_TRxV2A_REG0x4_TypeDef *REG0x4; + volatile BK7011_TRxV2A_REG0x5_TypeDef *REG0x5; + volatile BK7011_TRxV2A_REG0x6_TypeDef *REG0x6; + volatile BK7011_TRxV2A_REG0x7_TypeDef *REG0x7; + volatile BK7011_TRxV2A_REG0x8_TypeDef *REG0x8; + volatile BK7011_TRxV2A_REG0x9_TypeDef *REG0x9; + volatile BK7011_TRxV2A_REG0xA_TypeDef *REG0xA; + volatile BK7011_TRxV2A_REG0xB_TypeDef *REG0xB; + volatile BK7011_TRxV2A_REG0xC_TypeDef *REG0xC; + volatile BK7011_TRxV2A_REG0xD_TypeDef *REG0xD; + volatile BK7011_TRxV2A_REG0xE_TypeDef *REG0xE; + volatile BK7011_TRxV2A_REG0xF_TypeDef *REG0xF; + volatile BK7011_TRxV2A_REG0x10_TypeDef *REG0x10; + volatile BK7011_TRxV2A_REG0x11_TypeDef *REG0x11; + volatile BK7011_TRxV2A_REG0x12_TypeDef *REG0x12; + volatile BK7011_TRxV2A_REG0x13_TypeDef *REG0x13; + volatile BK7011_TRxV2A_REG0x14_TypeDef *REG0x14; + volatile BK7011_TRxV2A_REG0x15_TypeDef *REG0x15; + volatile BK7011_TRxV2A_REG0x16_TypeDef *REG0x16; + volatile BK7011_TRxV2A_REG0x17_TypeDef *REG0x17; + volatile BK7011_TRxV2A_REG0x18_TypeDef *REG0x18; + volatile BK7011_TRxV2A_REG0x19_TypeDef *REG0x19; + volatile BK7011_TRxV2A_REG0x1A_TypeDef *REG0x1A; + volatile BK7011_TRxV2A_REG0x1B_TypeDef *REG0x1B; + volatile BK7011_TRxV2A_REG0x1C_TypeDef *REG0x1C; +}; +#endif + +/// POWER +typedef struct +{ + unsigned int rega_4_7 : 4; + unsigned int rega_0_1 : 2; + unsigned int rega_8_13 : 6; + unsigned int regb_28_31 : 4; + unsigned int regc_0_2 : 3; + unsigned int regc_4_6 : 3; + unsigned int regc_8_10 : 3; + unsigned int pregain : 5; + unsigned int unuse : 2; +} PWR_REGS; + +typedef struct +{ + unsigned int regb_28_31 : 4; + unsigned int regc_0_3 : 4; + unsigned int regc_4_7 : 4; + unsigned int regc_8_11 : 4; + unsigned short value; +} PWR_REGS_TPC; + +/******************************************************************************* +* Function Declarations +*******************************************************************************/ +#endif // (CFG_SOC_NAME != SOC_BK7231) + +#endif // _BK7231U_CAL_H_ diff --git a/beken_os/beken378/func/bk7011_cal/bk7231_cal.c b/beken_os/beken378/func/bk7011_cal/bk7231_cal.c new file mode 100755 index 0000000..8bba3cd --- /dev/null +++ b/beken_os/beken378/func/bk7011_cal/bk7231_cal.c @@ -0,0 +1,4129 @@ +#include "include.h" + +#if (CFG_SOC_NAME == SOC_BK7231) +#include "arm_arch.h" +#include "target_util_pub.h" +#include "mem_pub.h" +#include "drv_model_pub.h" +#include "sys_ctrl_pub.h" +#include "phy.h" +#include "bk7011_cal_pub.h" +#include "bk7011_cal.h" +#include +#include "flash_pub.h" +#include "cmd_evm.h" +#include "temp_detect_pub.h" +#include "power_save_pub.h" + +#define CAL_RESULT_TO_FLASH 0 +#define CAL_RESULT_FLASH_ADDR 0x000F1000UL + + +#if CFG_SUPPORT_CALIBRATION +#define TX_WANTED_POWER_CAL 0 +#define TX_IQ_POWER_CAL 1 +#define TX_IQ_LOOPBACK_POWER_CAL 2 +#define TX_DC_CAL 0 +#define TX_DC_LOOPBACK_CAL 1 +#define TX_GAIN_IMB_CAL 0 +#define TX_GAIN_LOOPBACK_IMB_CAL 1 +#define TX_PHASE_IMB_CAL 0 +#define TX_PHASE_LOOPBACK_IMB_CAL 1 + +static INT32 gtx_dc_n = 0;//the times of first dc cal. +static UINT32 gst_rx_adc = CAL_DELAY100US; +static UINT32 gst_sar_adc = CAL_DELAY05US; + +#define BK7231_56PIN_BOARD 1 +#define BK7231_32PIN_BOARD 2 +#define BK7231_32PIN_TZH_BOARD 3 + +#define BOARD BK7231_32PIN_TZH_BOARD + +#if (BOARD == BK7231_56PIN_BOARD) +#define TRX_REG_0XA_VAL 0x83703274 +#define TRX_REG_0XB_VAL 0x20240077 +#define TRX_REG_0XC_VAL 0x01A267EE +#define TRX_REG_0XD_VAL 0xDDF90339 +#define TSSI_POUT_TH 0x50 //0x50:RF components for best power,0x43:for best sens +#else +#if (BOARD == BK7231_32PIN_BOARD) +#define TRX_REG_0XA_VAL 0x83703274 +#define TRX_REG_0XB_VAL 0x20246077 +#define TRX_REG_0XC_VAL 0x01A287EE +#define TRX_REG_0XD_VAL 0xDDF90339 +#define TSSI_POUT_TH 0x80 +#else +#if (BOARD == BK7231_32PIN_TZH_BOARD) +#define TRX_REG_0XA_VAL 0x83703274 +#define TRX_REG_0XB_VAL 0x20248077 +#define TRX_REG_0XC_VAL 0x01A287EE +#define TRX_REG_0XD_VAL 0xDDF90339 +#define TSSI_POUT_TH 0x60 +#endif +#endif +#endif + +#if 1 +#define TXIQ_IMB_TSSI_TH 105 +#endif + +#if 1 +#define TXIQ_IMB_TSSI_TH_LOOPBACK 90 +#endif + +#define No_TXPOWERCAL 0 +#if 1 +#define TXIQ_TSSI_TH 0x40 +#endif +#define TRX_REG_0XD_TX_IQ_VAL 0xD9FF0338 //0214 +#define TRX_REG_0XD_TX_LOOPBACK_IQ_VAL 0xD9FE7FF1 //0214 + +#define TRX_REG_0XC_TXLO_LEAKAGE_VAL 0x1A28188 + +#define TRX_REG_0XC_RXIQ_VAL 0x1A245ED // 1A244ED //0215 increasse gain due to load antenna 01A244DD +#define TRX_REG_0XE_RXIQ_VAL 0xD9F87FF1 //0214 FDF87FF1 + + +#if 1 +#define gi_dc_tx_pa_dgainPA20 7 +#define gi_dc_tx_pa_dgainbuf20 6 +#define gi_gain_tx_pa_dgainPA20 2 +#define gi_gain_tx_pa_dgainbuf20 4 +#endif + +#if 1 +#define gi_dc_tx_loopback_pa_dgainPA20 7 +#define gi_dc_tx_loopback_pa_dgainbuf20 7 +#define gi_gain_tx_loopback_pa_dgainPA20 6 +#define gi_gain_tx_loopback_pa_dgainbuf20 5 +#define gi_phase_tx_loopback_pa_dgainPA20 6 +#define gi_phase_tx_loopback_pa_dgainbuf20 6 +#endif + +#if 1 +#define gi_cal_rx_iq_pa_dgainPA20 4 +#define gi_cal_rx_iq_pa_dgainbuf20 5 +#endif + +#define CALIBRATE_TIMES 2000 +#undef CALIBRATE_TIMES // by gwf + +#ifdef CALIBRATE_TIMES +int calibrate_time = 0; + +int *p_gbias_after_cal_array = NULL; +int *p_gav_tssi_array = NULL; +int *p_gtx_ifilter_corner_array = NULL; +int *p_gtx_qfilter_corner_array = NULL; +int *p_rx_amp_err_rd_array = NULL; +int *p_rx_phase_err_rd_array = NULL; +int *p_rx_ty2_rd_array = NULL; + +int *p_gtx_i_dc_comp_array = NULL; +int *p_gtx_q_dc_comp_array = NULL; +int *p_gtx_i_gain_comp_array = NULL; +int *p_gtx_q_gain_comp_array = NULL; +int *p_gtx_phase_comp_array = NULL; + +int *p_gtx_i_dc_comp_temp_array = NULL; +int *p_gtx_q_dc_comp_temp_array = NULL; +int *p_gtx_i_gain_comp_temp_array = NULL; +int *p_gtx_q_gain_comp_temp_array = NULL; +int *p_gtx_phase_comp_temp_array = NULL; + +int *p_g_rx_dc_gain_tab_array = NULL; +#endif + +static INT32 bk7011_trx_val[32] = +{ + 0x0811EF5E, // 0 + 0x01000000, + 0x00000000, + 0x00000000, + 0x38025E88, + 0x2555EC7A, // 5 + 0x5FA44104,//0x5FA4410C, + 0x201848F5,//20170315 by yiming + #if CFG_SYS_REDUCE_NORMAL_POWER + 0x076AA885,//0x076CA9C9 by wangjian + #else + 0x076CA9C8, + #endif + 0x000003AF, // 9,from 3AF to 3BF ,add fixed 6dB gain + TRX_REG_0XA_VAL,//0x83373330, + TRX_REG_0XB_VAL,//0x4A444B24, + TRX_REG_0XC_VAL,//0x01A187EE, // 0x01A147FE is use for high temp calib + 0xDDF90339,// 0xD + 0xDA01BCF0,// 0xE + 0x00018000,// 0xF ADC sample rate clk 40M + 0xD0000000, + 0x00000000, + 0xF0090481,//0x12,from 0xF0090501 to 0xF0090481 ad/da LDO voltage reduced 50mv + 0x7B305ECC, + 0x827C827C, // 0x14 + 0x86788678, + 0x8C748C74, + 0xA45F9868, + 0xA45FA45F, + 0xA55EA45F, // 0x19 + 0xA55DA55E, + 0xA55DA55D, + 0x20000000 // 0x1C +}; + +static INT32 bk7011_rc_val[32] = +{ + 0x00000009,//00 REG_0x0, 0x0000; + 0xF0000000,//01 REG_0x1, 0x0004; + 0x00000030,//02 REG_0x5, 0x0014; + 0x00010001,//03 REG_0x8, 0x0020; + 0x000100e0,//04 REG_0xB, 0x002C; + 0x00010070,//05 REG_0xE, 0x0038; + 0x00010001,//06 REG_0x11, 0x0044; + 0x00010005,//07 REG_0x19, 0x0064; + 0x00000002,//08 REG_0x1c, 0x0070; + 0x0000012c,//09 REG_0x1E, 0x0078; + 0x1002DF4B,//10 REG_0x3C, 0x00F0; + 0x40000000,//11 REG_0x3E, 0x00F8; // enable comp bit + 0x03E803CB,//12 REG_0x3F, 0x00FC; + 0x00000001,//13 REG_0x40, 0x0100; + 0x00000000,//14 REG_0x41, 0x0104; + 0x02000041,//15 REG_0x42, 0x0108; + 0x018B018B,//16 REG_0x4C, 0x0130;//20170321 + 0x2CC02000,//17 REG_0x4D, 0x0134; + 0x02000200,//18 REG_0x4F, 0x013C; + 0x03FF03FF,//19 REG_0x50, 0x0140; + 0x02000200,//20 REG_0x51, 0x0144; + 0x50079D40,//21 REG_0x52, 0x0148; 0x4A443B24 0x53479D40 + (0x00025600 | ((TSSI_POUT_TH) << 1)), //22 REG_0x54, 0x0150; 0x00025646-1us 2E600 20170503 reduce RX ADC time 2D600 + 0x00000000,//23 REG_0x55, 0x0154; + 0x80000064,//24 REG_0x5C, 0x0170; +}; + +//static UINT8 gstat_cal = 1; // 1: calibration not done, 0: done + +INT32 gconst_iqcal_p = 117; +INT32 gconst_pout = 0x210; +INT32 gav_tssi = 0; +INT32 gav_tssi_temp = 0; +INT32 grc_reg_map[32]; +UINT8 gbias_after_cal = 0; + +INT32 gtx_dcorMod = 0x4; +INT32 gtx_dcorPA = 0x8; +INT32 gtx_pre_gain = 0x7; + +INT32 gtx_dcorMod_temp = 0x4; +INT32 gtx_dcorPA_temp = 0x8; +INT32 gtx_pre_gain_temp = 0x7; + +INT32 gtx_dcorMod_temp_loopback = 0x4; +INT32 gtx_dcorPA_temp_loopback = 0x8; +INT32 gtx_pre_gain_temp_loopback = 0x7; + +INT32 gtx_i_dc_comp_loopback = 0x202; +INT32 gtx_q_dc_comp_loopback = 0x1ff; + +INT32 gtx_i_gain_comp_loopback = 0x3ff; +INT32 gtx_q_gain_comp_loopback = 0x3f3; + +INT32 gtx_i_dc_comp = 0x202; +INT32 gtx_q_dc_comp = 0x1ff; + +INT32 gtx_i_gain_comp = 0x3ff; +INT32 gtx_q_gain_comp = 0x3f3; + +INT32 gtx_ifilter_corner = 0x10; +INT32 gtx_qfilter_corner = 0x10; + +INT32 gtx_phase_comp_loopback = 0x200; +INT32 gtx_phase_ty2_loopback = 0x200; + +INT32 gtx_phase_comp = 0x200; +INT32 gtx_phase_ty2 = 0x200; + +INT32 gtx_power_cal_mode = TX_WANTED_POWER_CAL; +INT32 gtx_dc_cal_mode = TX_DC_CAL; +INT32 gtx_gain_imb_cal_mode = TX_GAIN_IMB_CAL; +INT32 gtx_phase_imb_cal_mode = TX_PHASE_IMB_CAL; + +INT32 g_rx_dc_gain_tab[8] = +{ + 0x827C827C, + 0x86788678, + 0x8C748C74, + 0xA45F9868, + 0xA45FA45F, + 0xA55EA45F, + 0xA55DA55E, + 0xA55DA55D +}; + +INT32 grx_amp_err_wr = 0x200; +INT32 grx_phase_err_wr = 0x041; +FP32 max_txpwr = 0; + +#define PWRI(gain, rb_28_31, rc_8_10, rc_4_6, rc_0_2, ra_8_11) \ +{ \ + .unuse = 0, \ + .pregain = gain, \ + .regb_28_31 = rb_28_31, \ + .regc_8_10 = rc_8_10, \ + .regc_4_6 = rc_4_6, \ + .regc_0_2 = rc_0_2, \ + .rega_8_11 = ra_8_11 \ +} + +PWR_REGS cfg_tab_b[32] = +{ + // pregain REGB<31:28> REGC<8:10> REGC<6:4> REGC<2:0> REGA<11:8> +PWRI( 0x00 , 0xF, 2, 3, 6, 2 ), // 0 +PWRI( 0x0A , 0xF, 2, 4, 6, 2 ), // 1 +PWRI( 0x05 , 0xF, 2, 4, 6, 2 ), // 2 +PWRI( 0x00 , 0xF, 2, 4, 6, 2 ), // 3 +PWRI( 0x0B , 0xF, 3, 4, 6, 2 ), // 4 +PWRI( 0x07 , 0xF, 3, 4, 6, 2 ), // 5 +PWRI( 0x02 , 0xF, 3, 4, 6, 2 ), // 6 +PWRI( 0x07 , 0xF, 3, 5, 6, 2 ), // 7 +PWRI( 0x05 , 0xF, 3, 5, 6, 2 ), // 8 +PWRI( 0x02 , 0xF, 3, 5, 6, 2 ), // 9 +PWRI( 0x00 , 0xF, 3, 5, 6, 2 ), // 10 +PWRI( 0x00 , 0xF, 4, 5, 6, 4 ), // 11 +PWRI( 0x0B , 0xF, 5, 5, 6, 4 ), // 12 +PWRI( 0x0A , 0xF, 6, 6, 5, 4 ), // 13 +PWRI( 0x08 , 0xF, 6, 6, 5, 4 ), // 14 +PWRI( 0x05 , 0xF, 6, 6, 5, 4 ), // 15 +PWRI( 0x02 , 0xF, 6, 6, 5, 4 ), // 16 +PWRI( 0x0E , 0xF, 6, 6, 6, 4 ), // 17 +PWRI( 0x0C , 0xF, 6, 6, 6, 4 ), // 18 +PWRI( 0x0A , 0xF, 6, 6, 6, 4 ), // 19 +PWRI( 0x08 , 0xF, 6, 6, 6, 4 ), // 20 +PWRI( 0x05 , 0xF, 6, 6, 6, 4 ), // 21 +PWRI( 0x0C , 0xF, 7, 6, 6, 4 ), // 22 +PWRI( 0x09 , 0xF, 7, 6, 6, 4 ), // 23 +PWRI( 0x07 , 0xF, 7, 6, 6, 4 ), // 24 +PWRI( 0x05 , 0xF, 7, 6, 6, 4 ), // 25 +PWRI( 0x0E , 0xF, 7, 6, 7, 5 ), // 26 +PWRI( 0x0B , 0xF, 7, 6, 7, 5 ), // 27 +PWRI( 0x00 , 0xF, 7, 6, 6, 7 ), // 28 +PWRI( 0x00 , 0xF, 7, 7, 6, 7 ), // 29 +PWRI( 0x08 , 0xF, 7, 7, 7, 7 ), // 30 +PWRI( 0x00 , 0xF, 7, 7, 7, 7 ), // 31 +}; + +PWR_REGS cfg_tab_g[32] = { + // pregain REGB<31:28> REGC<8:10> REGC<6:4> REGC<2:0> REGA<11:8> +PWRI( 0xA , 4, 4, 4, 5, 2 ), // 0 +PWRI( 0x4 , 4, 4, 4, 5, 2 ), // 1 +PWRI( 0x2 , 4, 5, 5, 4, 2 ), // 2 +PWRI( 0x4 , 4, 6, 5, 4, 2 ), // 3 +PWRI( 0x0 , 4, 6, 5, 4, 2 ), // 4 +PWRI( 0xA , 4, 6, 5, 5, 2 ), // 5 +PWRI( 0x9 , 4, 6, 5, 5, 2 ), // 6 +PWRI( 0x7 , 4, 6, 5, 5, 2 ), // 7 +PWRI( 0x5 , 4, 6, 5, 5, 2 ), // 8 +PWRI( 0x3 , 4, 6, 5, 5, 2 ), // 9 +PWRI( 0x1 , 4, 6, 5, 5, 2 ), // 10 +PWRI( 0x4 , 4, 7, 5, 5, 2 ), // 11 +PWRI( 0x2 , 4, 7, 5, 5, 2 ), // 12 +PWRI( 0x0 , 4, 7, 5, 5, 2 ), // 13 +PWRI( 0x4 , 4, 7, 6, 5, 2 ), // 14 +PWRI( 0x2 , 4, 7, 6, 5, 2 ), // 15 +PWRI( 0x0 , 4, 7, 6, 5, 2 ), // 16 +PWRI( 0xB , 4, 7, 6, 6, 2 ), // 17 +PWRI( 0x8 , 4, 7, 6, 6, 2 ), // 18 +PWRI( 0x5 , 4, 7, 6, 6, 2 ), // 19 +PWRI( 0x3 , 4, 7, 6, 6, 2 ), // 20 +PWRI( 0x7 , 4, 7, 7, 6, 2 ), // 21 +PWRI( 0x4 , 4, 7, 7, 6, 2 ), // 22 +PWRI( 0x2 , 4, 7, 7, 6, 2 ), // 23 +PWRI( 0x0 , 4, 7, 7, 6, 2 ), // 24 +PWRI( 0x2 , 2, 7, 6, 6, 2 ), // 25 +PWRI( 0x4 , 2, 7, 7, 6, 2 ), // 26 +PWRI( 0x2 , 2, 7, 7, 6, 2 ), // 27 +PWRI( 0x0 , 2, 7, 7, 6, 2 ), // 28 +PWRI( 0x6 , 5, 7, 6, 6, 2 ), // 29 +PWRI( 0x0 , 5, 7, 6, 6, 2 ), // 30 +PWRI( 0x0 , 5, 7, 7, 6, 2 ), // 31 +}; + +FP32 rate_tab_b[32] = { + 9.9, // 0 + 10.3, // 1 + 10.8, // 2 + 11.3, // 3 + 11.8, // 4 + 12.3, // 5 + 12.7, // 6 + 13.2, // 7 + 13.7, // 8 + 14.2, // 9 + 14.7, // 10 + 15.2, // 11 + 15.6, // 12 + 16.1, // 13 + 16.3, // 14 + 16.6, // 15 + 17.0, // 16 + 17.3, // 17 + 17.5, // 18 + 17.8, // 19 + 18.0, // 20 + 18.1, // 21 + 18.3, // 22 + 18.4, // 23 + 18.5, // 24 + 18.6, // 25 + 18.8, // 26 + 19.0, // 27 + 19.1, // 28 + 19.1, // 29 + 19.1, // 30 + 19.2 // 31 +}; + +FP32 rate_tab_g[32] = { + 3.6, // 0 + 4.8, // 1 + 5.7, // 2 + 6.2, // 3 + 6.7, // 4 + 7.2, // 5 + 7.7, // 6 + 8.2, // 7 + 8.7, // 8 + 9.2, // 9 + 9.7, // 10 + 10.1, // 11 + 10.6, // 12 + 11.1, // 13 + 11.6, // 14 + 12.0, // 15 + 12.3, // 16 + 12.8, // 17 + 13.2, // 18 + 13.6, // 19 + 13.9, // 20 + 14.3, // 21 + 14.6, // 22 + 15.2, // 23 + 15.6, // 24 + 15.9, // 25 + 16.4, // 26 + 17.1, // 27 + 17.4, // 28 + 17.8, // 29 + 18.0, // 30 + 18.3 // 31 +}; + + +struct BK7011RCBEKEN_TypeDef BK7011RCBEKEN = +{ + (volatile BK7011_RC_BEKEN_REG0x0_TypeDef *) (RC_BEKEN_BASE + 0 * 4), + (volatile BK7011_RC_BEKEN_REG0x1_TypeDef *) (RC_BEKEN_BASE + 1 * 4), + (volatile BK7011_RC_BEKEN_REG0x5_TypeDef *) (RC_BEKEN_BASE + 5 * 4), + (volatile BK7011_RC_BEKEN_REG0x8_TypeDef *) (RC_BEKEN_BASE + 8 * 4), + (volatile BK7011_RC_BEKEN_REG0xB_TypeDef *) (RC_BEKEN_BASE + 11 * 4), + (volatile BK7011_RC_BEKEN_REG0xE_TypeDef *) (RC_BEKEN_BASE + 14 * 4), + (volatile BK7011_RC_BEKEN_REG0x11_TypeDef *)(RC_BEKEN_BASE + 17 * 4), + (volatile BK7011_RC_BEKEN_REG0x19_TypeDef *)(RC_BEKEN_BASE + 25 * 4), + (volatile BK7011_RC_BEKEN_REG0x1C_TypeDef *)(RC_BEKEN_BASE + 28 * 4), + (volatile BK7011_RC_BEKEN_REG0x1E_TypeDef *)(RC_BEKEN_BASE + 30 * 4), + (volatile BK7011_RC_BEKEN_REG0x3C_TypeDef *)(RC_BEKEN_BASE + 60 * 4), + (volatile BK7011_RC_BEKEN_REG0x3E_TypeDef *)(RC_BEKEN_BASE + 62 * 4), + (volatile BK7011_RC_BEKEN_REG0x3F_TypeDef *)(RC_BEKEN_BASE + 63 * 4), + (volatile BK7011_RC_BEKEN_REG0x40_TypeDef *)(RC_BEKEN_BASE + 64 * 4), + (volatile BK7011_RC_BEKEN_REG0x41_TypeDef *)(RC_BEKEN_BASE + 65 * 4), + (volatile BK7011_RC_BEKEN_REG0x42_TypeDef *)(RC_BEKEN_BASE + 66 * 4), + (volatile BK7011_RC_BEKEN_REG0x4C_TypeDef *)(RC_BEKEN_BASE + 76 * 4), + (volatile BK7011_RC_BEKEN_REG0x4D_TypeDef *)(RC_BEKEN_BASE + 77 * 4), + (volatile BK7011_RC_BEKEN_REG0x4F_TypeDef *)(RC_BEKEN_BASE + 79 * 4), + (volatile BK7011_RC_BEKEN_REG0x50_TypeDef *)(RC_BEKEN_BASE + 80 * 4), + (volatile BK7011_RC_BEKEN_REG0x51_TypeDef *)(RC_BEKEN_BASE + 81 * 4), + (volatile BK7011_RC_BEKEN_REG0x52_TypeDef *)(RC_BEKEN_BASE + 82 * 4), + (volatile BK7011_RC_BEKEN_REG0x54_TypeDef *)(RC_BEKEN_BASE + 84 * 4), + (volatile BK7011_RC_BEKEN_REG0x55_TypeDef *)(RC_BEKEN_BASE + 85 * 4), + (volatile BK7011_RC_BEKEN_REG0x5C_TypeDef *)(RC_BEKEN_BASE + 92 * 4), + (volatile BK7011_RC_BEKEN_REG0x6A_TypeDef *)(RC_BEKEN_BASE + 106 * 4), +}; + +struct BK7011TRxV2A_TypeDef BK7011TRX = +{ + (BK7011_TRxV2A_REG0x0_TypeDef *)(&grc_reg_map[0]), + (BK7011_TRxV2A_REG0x1_TypeDef *)(&grc_reg_map[1]), + (BK7011_TRxV2A_REG0x2_TypeDef *)(&grc_reg_map[2]), + (BK7011_TRxV2A_REG0x3_TypeDef *)(&grc_reg_map[3]), + (BK7011_TRxV2A_REG0x4_TypeDef *)(&grc_reg_map[4]), + (BK7011_TRxV2A_REG0x5_TypeDef *)(&grc_reg_map[5]), + (BK7011_TRxV2A_REG0x6_TypeDef *)(&grc_reg_map[6]), + (BK7011_TRxV2A_REG0x7_TypeDef *)(&grc_reg_map[7]), + (BK7011_TRxV2A_REG0x8_TypeDef *)(&grc_reg_map[8]), + (BK7011_TRxV2A_REG0x9_TypeDef *)(&grc_reg_map[9]), + (BK7011_TRxV2A_REG0xA_TypeDef *)(&grc_reg_map[10]), + (BK7011_TRxV2A_REG0xB_TypeDef *)(&grc_reg_map[11]), + (BK7011_TRxV2A_REG0xC_TypeDef *)(&grc_reg_map[12]), + (BK7011_TRxV2A_REG0xD_TypeDef *)(&grc_reg_map[13]), + (BK7011_TRxV2A_REG0xE_TypeDef *)(&grc_reg_map[14]), + (BK7011_TRxV2A_REG0xF_TypeDef *)(&grc_reg_map[15]), + (BK7011_TRxV2A_REG0x10_TypeDef *)(&grc_reg_map[16]), + (BK7011_TRxV2A_REG0x11_TypeDef *)(&grc_reg_map[17]), + (BK7011_TRxV2A_REG0x12_TypeDef *)(&grc_reg_map[18]), + (BK7011_TRxV2A_REG0x13_TypeDef *)(&grc_reg_map[19]), + (BK7011_TRxV2A_REG0x14_TypeDef *)(&grc_reg_map[20]), + (BK7011_TRxV2A_REG0x15_TypeDef *)(&grc_reg_map[21]), + (BK7011_TRxV2A_REG0x16_TypeDef *)(&grc_reg_map[22]), + (BK7011_TRxV2A_REG0x17_TypeDef *)(&grc_reg_map[23]), + (BK7011_TRxV2A_REG0x18_TypeDef *)(&grc_reg_map[24]), + (BK7011_TRxV2A_REG0x19_TypeDef *)(&grc_reg_map[25]), + (BK7011_TRxV2A_REG0x1A_TypeDef *)(&grc_reg_map[26]), + (BK7011_TRxV2A_REG0x1B_TypeDef *)(&grc_reg_map[27]), + (BK7011_TRxV2A_REG0x1C_TypeDef *)(&grc_reg_map[28]), +}; + +struct BK7011TRxV2A_TypeDef BK7011TRXONLY = +{ + (volatile BK7011_TRxV2A_REG0x0_TypeDef *) (TRX_BEKEN_BASE + 0 * 4), + (volatile BK7011_TRxV2A_REG0x1_TypeDef *) (TRX_BEKEN_BASE + 1 * 4), + (volatile BK7011_TRxV2A_REG0x2_TypeDef *) (TRX_BEKEN_BASE + 2 * 4), + (volatile BK7011_TRxV2A_REG0x3_TypeDef *) (TRX_BEKEN_BASE + 3 * 4), + (volatile BK7011_TRxV2A_REG0x4_TypeDef *) (TRX_BEKEN_BASE + 4 * 4), + (volatile BK7011_TRxV2A_REG0x5_TypeDef *) (TRX_BEKEN_BASE + 5 * 4), + (volatile BK7011_TRxV2A_REG0x6_TypeDef *) (TRX_BEKEN_BASE + 6 * 4), + (volatile BK7011_TRxV2A_REG0x7_TypeDef *) (TRX_BEKEN_BASE + 7 * 4), + (volatile BK7011_TRxV2A_REG0x8_TypeDef *) (TRX_BEKEN_BASE + 8 * 4), + (volatile BK7011_TRxV2A_REG0x9_TypeDef *) (TRX_BEKEN_BASE + 9 * 4), + (volatile BK7011_TRxV2A_REG0xA_TypeDef *) (TRX_BEKEN_BASE + 10 * 4), + (volatile BK7011_TRxV2A_REG0xB_TypeDef *) (TRX_BEKEN_BASE + 11 * 4), + (volatile BK7011_TRxV2A_REG0xC_TypeDef *) (TRX_BEKEN_BASE + 12 * 4), + (volatile BK7011_TRxV2A_REG0xD_TypeDef *) (TRX_BEKEN_BASE + 13 * 4), + (volatile BK7011_TRxV2A_REG0xE_TypeDef *) (TRX_BEKEN_BASE + 14 * 4), + (volatile BK7011_TRxV2A_REG0xF_TypeDef *) (TRX_BEKEN_BASE + 15 * 4), + (volatile BK7011_TRxV2A_REG0x10_TypeDef *)(TRX_BEKEN_BASE + 16 * 4), + (volatile BK7011_TRxV2A_REG0x11_TypeDef *)(TRX_BEKEN_BASE + 17 * 4), + (volatile BK7011_TRxV2A_REG0x12_TypeDef *)(TRX_BEKEN_BASE + 18 * 4), + (volatile BK7011_TRxV2A_REG0x13_TypeDef *)(TRX_BEKEN_BASE + 19 * 4), + (volatile BK7011_TRxV2A_REG0x14_TypeDef *)(TRX_BEKEN_BASE + 20 * 4), + (volatile BK7011_TRxV2A_REG0x15_TypeDef *)(TRX_BEKEN_BASE + 21 * 4), + (volatile BK7011_TRxV2A_REG0x16_TypeDef *)(TRX_BEKEN_BASE + 22 * 4), + (volatile BK7011_TRxV2A_REG0x17_TypeDef *)(TRX_BEKEN_BASE + 23 * 4), + (volatile BK7011_TRxV2A_REG0x18_TypeDef *)(TRX_BEKEN_BASE + 24 * 4), + (volatile BK7011_TRxV2A_REG0x19_TypeDef *)(TRX_BEKEN_BASE + 25 * 4), + (volatile BK7011_TRxV2A_REG0x1A_TypeDef *)(TRX_BEKEN_BASE + 26 * 4), + (volatile BK7011_TRxV2A_REG0x1B_TypeDef *)(TRX_BEKEN_BASE + 27 * 4), + (volatile BK7011_TRxV2A_REG0x1C_TypeDef *)(TRX_BEKEN_BASE + 28 * 4), +}; + +void bk7011_cal_pll(void); + +void delay05us(INT32 num) +{ + volatile INT32 i, j; + //REG_WRITE((0x0802800+(18*4)), 0x02); + + for(i = 0; i < num; i ++) + { + for(j = 0; j < 5; j ++) + ; + } + //REG_WRITE((0x0802800+(18*4)), 0x00); +} + +void delay100us(INT32 num) +{ + volatile INT32 i, j; + //REG_WRITE((0x0802800+(18*4)), 0x02); + + for(i = 0; i < num; i ++) + { + for(j = 0; j < 1050; j ++) + ; + } + //REG_WRITE((0x0802800+(18*4)), 0x00); +} + + +#define CAL_WR_TRXREGS(reg) do{\ + CHECK_OPERATE_RF_REG_IF_IN_SLEEP();\ + while(BK7011RCBEKEN.REG0x1->value & (0x1 << reg));\ + BK7011TRXONLY.REG##reg->value = BK7011TRX.REG##reg->value;\ + cal_delay(6);\ + while(BK7011RCBEKEN.REG0x1->value & (0x1 << reg));\ + CHECK_OPERATE_RF_REG_IF_IN_SLEEP_END();\ + }while(0) + + +void rwnx_cal_load_default_result(void) +{ + gtx_dcorMod = (bk7011_trx_val[11] >> 12) & 0xf; + gtx_dcorPA = (bk7011_trx_val[12] >> 12) & 0xf; + gtx_pre_gain = (bk7011_rc_val[21] >> 16) & 0x1f; + + gtx_i_dc_comp = (bk7011_rc_val[18] >> 16) & 0x3ff; + gtx_q_dc_comp = bk7011_rc_val[18] & 0x3ff; + + gtx_i_gain_comp = (bk7011_rc_val[19] >> 16) & 0x3ff; + gtx_q_gain_comp = bk7011_rc_val[19] & 0x3ff; + + gtx_ifilter_corner = (bk7011_trx_val[6] >> 10) & 0x3f; + gtx_qfilter_corner = (bk7011_trx_val[6] >> 4) & 0x3f; + gtx_phase_comp = (bk7011_rc_val[20] >> 16) & 0x3ff; + gtx_phase_ty2 = bk7011_rc_val[20] & 0x3ff; + + g_rx_dc_gain_tab[0] = bk7011_trx_val[20]; + g_rx_dc_gain_tab[1] = bk7011_trx_val[21]; + g_rx_dc_gain_tab[2] = bk7011_trx_val[22]; + g_rx_dc_gain_tab[3] = bk7011_trx_val[23]; + g_rx_dc_gain_tab[4] = bk7011_trx_val[24]; + g_rx_dc_gain_tab[5] = bk7011_trx_val[25]; + g_rx_dc_gain_tab[6] = bk7011_trx_val[26]; + g_rx_dc_gain_tab[7] = bk7011_trx_val[27]; + + grx_amp_err_wr = (bk7011_rc_val[15] >> 16) & 0x3ff; + grx_phase_err_wr = bk7011_rc_val[15] & 0x3ff; + + //gstat_cal = (bk7011_rc_val[16] >> 29) & 0x1; +} + +#ifdef CALIBRATE_TIMES +void calibration_result_print(void) +{ + int i, j; + int max, min; + + + os_printf("gtx_dcorMod_temp: 0x%x\r\n", gtx_dcorMod_temp); + os_printf("gtx_dcorPA_temp: 0x%x\r\n", gtx_dcorPA_temp); + os_printf("gtx_pre_gain_temp: 0x%x\r\n", gtx_pre_gain_temp); + + os_printf("gtx_dcorMod_temp_loopback: 0x%x\r\n", gtx_dcorMod_temp_loopback); + os_printf("gtx_dcorPA_temp_loopback: 0x%x\r\n", gtx_dcorPA_temp_loopback); + os_printf("gtx_pre_gain_temp_loopback: 0x%x\r\n", gtx_pre_gain_temp_loopback); + + max = -1100, min = 1100; + for (i = 0; i < calibrate_time; i++) + { + if (max < p_gbias_after_cal_array[i]) + { + max = p_gbias_after_cal_array[i]; + } + if (min > p_gbias_after_cal_array[i]) + { + min = p_gbias_after_cal_array[i]; + } + } + os_printf("gbias_after_cal: min = %d, max = %d, max-min = %d\r\n", min, max, max - min); + + max = -1100, min = 1100; + for (i = 0; i < calibrate_time; i++) + { + if (max < p_gav_tssi_array[i]) + { + max = p_gav_tssi_array[i]; + } + if (min > p_gav_tssi_array[i]) + { + min = p_gav_tssi_array[i]; + } + } + os_printf("gav_tssi: min = %d, max = %d, max-min = %d\r\n", min, max, max - min); + + os_printf("\r\n"); + + max = -1100, min = 1100; + for (i = 0; i < calibrate_time; i++) + { + if (max < p_gtx_ifilter_corner_array[i]) + { + max = p_gtx_ifilter_corner_array[i]; + } + if (min > p_gtx_ifilter_corner_array[i]) + { + min = p_gtx_ifilter_corner_array[i]; + } + } + os_printf("gtx_ifilter_corner: min = %d, max = %d, max-min = %d\r\n", min, max, max - min); + + max = -1100, min = 1100; + for (i = 0; i < calibrate_time; i++) + { + if (max < p_gtx_qfilter_corner_array[i]) + { + max = p_gtx_qfilter_corner_array[i]; + } + if (min > p_gtx_qfilter_corner_array[i]) + { + min = p_gtx_qfilter_corner_array[i]; + } + } + os_printf("gtx_qfilter_corner: min = %d, max = %d, max-min = %d\r\n", min, max, max - min); + + os_printf("\r\n"); + + max = -1100, min = 1100; + for (i = 0; i < calibrate_time; i++) + { + if (max < p_gtx_i_dc_comp_array[i]) + { + max = p_gtx_i_dc_comp_array[i]; + } + if (min > p_gtx_i_dc_comp_array[i]) + { + min = p_gtx_i_dc_comp_array[i]; + } + } + os_printf("tx_i_dc_comp: min = %d, max = %d, max-min = %d\r\n", min, max, max - min); + + max = -1100, min = 1100; + for (i = 0; i < calibrate_time; i++) + { + if (max < p_gtx_q_dc_comp_array[i]) + { + max = p_gtx_q_dc_comp_array[i]; + } + if (min > p_gtx_q_dc_comp_array[i]) + { + min = p_gtx_q_dc_comp_array[i]; + } + } + os_printf("tx_q_dc_comp: min = %d, max = %d, max-min = %d\r\n", min, max, max - min); + + max = -1100, min = 1100; + for (i = 0; i < calibrate_time; i++) + { + if (max < p_gtx_i_gain_comp_array[i]) + { + max = p_gtx_i_gain_comp_array[i]; + } + if (min > p_gtx_i_gain_comp_array[i]) + { + min = p_gtx_i_gain_comp_array[i]; + } + } + os_printf("tx_i_gain_comp: min = %d, max = %d, max-min = %d\r\n", min, max, max - min); + + max = -1100, min = 1100; + for (i = 0; i < calibrate_time; i++) + { + if (max < p_gtx_q_gain_comp_array[i]) + { + max = p_gtx_q_gain_comp_array[i]; + } + if (min > p_gtx_q_gain_comp_array[i]) + { + min = p_gtx_q_gain_comp_array[i]; + } + } + os_printf("tx_q_gain_comp: min = %d, max = %d, max-min = %d\r\n", min, max, max - min); + + max = -1100, min = 1100; + for (i = 0; i < calibrate_time; i++) + { + if (max < p_gtx_phase_comp_array[i]) + { + max = p_gtx_phase_comp_array[i]; + } + if (min > p_gtx_phase_comp_array[i]) + { + min = p_gtx_phase_comp_array[i]; + } + } + os_printf("tx_phase_comp: min = %d, max = %d, max-min = %d\r\n", min, max, max - min); + + os_printf("\r\n"); + + max = -1100, min = 1100; + for (i = 0; i < calibrate_time; i++) + { + if (max < p_gtx_i_dc_comp_temp_array[i]) + { + max = p_gtx_i_dc_comp_temp_array[i]; + } + if (min > p_gtx_i_dc_comp_temp_array[i]) + { + min = p_gtx_i_dc_comp_temp_array[i]; + } + } + os_printf("tx_i_dc_comp_temp: min = %d, max = %d, max-min = %d\r\n", min, max, max - min); + + max = -1100, min = 1100; + for (i = 0; i < calibrate_time; i++) + { + if (max < p_gtx_q_dc_comp_temp_array[i]) + { + max = p_gtx_q_dc_comp_temp_array[i]; + } + if (min > p_gtx_q_dc_comp_temp_array[i]) + { + min = p_gtx_q_dc_comp_temp_array[i]; + } + } + os_printf("tx_q_dc_comp_temp: min = %d, max = %d, max-min = %d\r\n", min, max, max - min); + + + max = -1100, min = 1100; + for (i = 0; i < calibrate_time; i++) + { + if (max < p_gtx_i_gain_comp_temp_array[i]) + { + max = p_gtx_i_gain_comp_temp_array[i]; + } + if (min > p_gtx_i_gain_comp_temp_array[i]) + { + min = p_gtx_i_gain_comp_temp_array[i]; + } + } + os_printf("tx_i_gain_comp_temp: min = %d, max = %d, max-min = %d\r\n", min, max, max - min); + + max = -1100, min = 1100; + for (i = 0; i < calibrate_time; i++) + { + if (max < p_gtx_q_gain_comp_temp_array[i]) + { + max = p_gtx_q_gain_comp_temp_array[i]; + } + if (min > p_gtx_q_gain_comp_temp_array[i]) + { + min = p_gtx_q_gain_comp_temp_array[i]; + } + } + os_printf("tx_q_gain_comp_temp: min = %d, max = %d, max-min = %d\r\n", min, max, max - min); + + max = -1100, min = 1100; + for (i = 0; i < calibrate_time; i++) + { + if (max < p_gtx_phase_comp_temp_array[i]) + { + max = p_gtx_phase_comp_temp_array[i]; + } + if (min > p_gtx_phase_comp_temp_array[i]) + { + min = p_gtx_phase_comp_temp_array[i]; + } + } + os_printf("tx_phase_comp_temp: min = %d, max = %d, max-min = %d\r\n", min, max, max - min); + + os_printf("\r\n"); + + max = -1100, min = 1100; + for (i = 0; i < calibrate_time; i++) + { + if (max < p_rx_amp_err_rd_array[i]) + { + max = p_rx_amp_err_rd_array[i]; + } + if (min > p_rx_amp_err_rd_array[i]) + { + min = p_rx_amp_err_rd_array[i]; + } + } + os_printf("rx_amp_err_rd: min = %d, max = %d, max-min = %d\r\n", min, max, max - min); + + max = -1100, min = 1100; + for (i = 0; i < calibrate_time; i++) + { + if (max < p_rx_phase_err_rd_array[i]) + { + max = p_rx_phase_err_rd_array[i]; + } + if (min > p_rx_phase_err_rd_array[i]) + { + min = p_rx_phase_err_rd_array[i]; + } + } + os_printf("rx_phase_err_rd: min = %d, max = %d, max-min = %d\r\n", min, max, max - min); + + max = -1100, min = 1100; + for (i = 0; i < calibrate_time; i++) + { + if (max < p_rx_ty2_rd_array[i]) + { + max = p_rx_ty2_rd_array[i]; + } + if (min > p_rx_ty2_rd_array[i]) + { + min = p_rx_ty2_rd_array[i]; + } + } + os_printf("rx_ty2_rd: min = %d, max = %d, max-min = %d\r\n", min, max, max - min); + + for (j = 0; j < 8; j++) + { + int iTemp; + os_printf("\r\n"); + + max = -1100, min = 1100; + for (i = 0; i < calibrate_time; i++) + { + iTemp = p_g_rx_dc_gain_tab_array[j * CALIBRATE_TIMES + i]; + if (max < (iTemp & 0x00FF)) + { + max = iTemp & 0x00FF; + } + if (min > (iTemp & 0x00FF)) + { + min = iTemp & 0x00FF; + } + } + os_printf("g_rx_dc_gain_tab[%d].i_%ddb: min = %d, max = %d, max-min = %d\r\n", j, j * 6, min, max, max - min); + + max = -1100, min = 1100; + for (i = 0; i < calibrate_time; i++) + { + iTemp = p_g_rx_dc_gain_tab_array[j * CALIBRATE_TIMES + i] >> 8; + if (max < (iTemp & 0x00FF)) + { + max = iTemp & 0x00FF; + } + if (min > (iTemp & 0x00FF)) + { + min = iTemp & 0x00FF; + } + } + os_printf("g_rx_dc_gain_tab[%d].q_%ddb: min = %d, max = %d, max-min = %d\r\n", j, j * 6, min, max, max - min); + + max = -1100, min = 1100; + for (i = 0; i < calibrate_time; i++) + { + iTemp = p_g_rx_dc_gain_tab_array[j * CALIBRATE_TIMES + i] >> 16; + if (max < (iTemp & 0x00FF)) + { + max = iTemp & 0x00FF; + } + if (min > (iTemp & 0x00FF)) + { + min = iTemp & 0x00FF; + } + } + os_printf("g_rx_dc_gain_tab[%d].i_%ddb: min = %d, max = %d, max-min = %d\r\n", j, j * 6 + 3, min, max, max - min); + + max = -1100, min = 1100; + for (i = 0; i < calibrate_time; i++) + { + iTemp = p_g_rx_dc_gain_tab_array[j * CALIBRATE_TIMES + i] >> 24; + if (max < (iTemp & 0x00FF)) + { + max = iTemp & 0x00FF; + } + if (min > (iTemp & 0x00FF)) + { + min = iTemp & 0x00FF; + } + } + os_printf("g_rx_dc_gain_tab[%d].q_%ddb: min = %d, max = %d, max-min = %d\r\n", j, j * 6 + 3, min, max, max - min); + } +} + +void calibration_auto_test(void) +{ + int i; + int gbias_after_cal_array[CALIBRATE_TIMES]; + int gav_tssi_array[CALIBRATE_TIMES]; + int rx_amp_err_rd_array[CALIBRATE_TIMES]; + int rx_phase_err_rd_array[CALIBRATE_TIMES]; + int rx_ty2_rd_array[CALIBRATE_TIMES]; + int gtx_ifilter_corner_array[CALIBRATE_TIMES]; + int gtx_qfilter_corner_array[CALIBRATE_TIMES]; + + int gtx_i_dc_comp_array[CALIBRATE_TIMES]; + int gtx_q_dc_comp_array[CALIBRATE_TIMES]; + int gtx_i_gain_comp_array[CALIBRATE_TIMES]; + int gtx_q_gain_comp_array[CALIBRATE_TIMES]; + int gtx_phase_comp_array[CALIBRATE_TIMES]; + + int gtx_i_dc_comp_temp_array[CALIBRATE_TIMES]; + int gtx_q_dc_comp_temp_array[CALIBRATE_TIMES]; + int gtx_i_gain_comp_temp_array[CALIBRATE_TIMES]; + int gtx_q_gain_comp_temp_array[CALIBRATE_TIMES]; + int gtx_phase_comp_temp_array[CALIBRATE_TIMES]; + + int g_rx_dc_gain_tab_array[8][CALIBRATE_TIMES]; + + p_gbias_after_cal_array = gbias_after_cal_array; + p_gav_tssi_array = gav_tssi_array; + p_rx_amp_err_rd_array = rx_amp_err_rd_array; + p_rx_ty2_rd_array = rx_ty2_rd_array; + p_rx_phase_err_rd_array = rx_phase_err_rd_array; + p_gtx_ifilter_corner_array = gtx_ifilter_corner_array; + p_gtx_qfilter_corner_array = gtx_qfilter_corner_array; + p_gtx_i_dc_comp_array = gtx_i_dc_comp_array; + p_gtx_q_dc_comp_array = gtx_q_dc_comp_array; + p_gtx_i_gain_comp_array = gtx_i_gain_comp_array; + p_gtx_q_gain_comp_array = gtx_q_gain_comp_array; + p_gtx_phase_comp_array = gtx_phase_comp_array; + p_gtx_i_dc_comp_temp_array = gtx_i_dc_comp_temp_array; + p_gtx_q_dc_comp_temp_array = gtx_q_dc_comp_temp_array; + p_gtx_i_gain_comp_temp_array = gtx_i_gain_comp_temp_array; + p_gtx_q_gain_comp_temp_array = gtx_q_gain_comp_temp_array; + p_gtx_phase_comp_temp_array = gtx_phase_comp_temp_array; + p_g_rx_dc_gain_tab_array = &(g_rx_dc_gain_tab_array[0][0]); + + calibrate_time = 0; + os_printf("\r\n\r\n***********************************************************************\r\n" + "calibration_auto_test: \r\n"); + for (i = 0; i < CALIBRATE_TIMES; i++) + { + calibration_main(); + } + calibration_result_print(); + os_printf("***********************************************************************\r\n"); + + p_gbias_after_cal_array = NULL; + p_gav_tssi_array = NULL; + p_rx_amp_err_rd_array = NULL; + p_rx_phase_err_rd_array = NULL; + p_rx_ty2_rd_array = NULL; + p_gtx_i_dc_comp_array = NULL; + p_gtx_q_dc_comp_array = NULL; + p_gtx_i_gain_comp_array = NULL; + p_gtx_q_gain_comp_array = NULL; + p_gtx_phase_comp_array = NULL; + p_gtx_ifilter_corner_array = NULL; + p_gtx_qfilter_corner_array = NULL; + p_gtx_i_dc_comp_temp_array = NULL; + p_gtx_q_dc_comp_temp_array = NULL; + p_gtx_i_gain_comp_temp_array = NULL; + p_gtx_q_gain_comp_temp_array = NULL; + p_gtx_phase_comp_temp_array = NULL; + p_g_rx_dc_gain_tab_array = NULL; +} +#else +void calibration_auto_test(void) +{ +} +#endif + +void rwnx_cal_read_current_cal_result(void) +{ +#ifdef CALIBRATE_TIMES + if (p_gtx_phase_comp_array != NULL) + { + p_gbias_after_cal_array[calibrate_time] = gbias_after_cal; + p_gav_tssi_array[calibrate_time] = gav_tssi; + p_gtx_phase_comp_array[calibrate_time] = gtx_phase_comp; + p_gtx_i_dc_comp_array[calibrate_time] = gtx_i_dc_comp; + p_gtx_q_dc_comp_array[calibrate_time] = gtx_q_dc_comp; + p_gtx_i_gain_comp_array[calibrate_time] = gtx_i_gain_comp; + p_gtx_q_gain_comp_array[calibrate_time] = gtx_q_gain_comp; + p_gtx_ifilter_corner_array[calibrate_time] = gtx_ifilter_corner; + p_gtx_qfilter_corner_array[calibrate_time] = gtx_qfilter_corner; + + p_g_rx_dc_gain_tab_array[0 * CALIBRATE_TIMES + calibrate_time] = g_rx_dc_gain_tab[0]; + p_g_rx_dc_gain_tab_array[1 * CALIBRATE_TIMES + calibrate_time] = g_rx_dc_gain_tab[1]; + p_g_rx_dc_gain_tab_array[2 * CALIBRATE_TIMES + calibrate_time] = g_rx_dc_gain_tab[2]; + p_g_rx_dc_gain_tab_array[3 * CALIBRATE_TIMES + calibrate_time] = g_rx_dc_gain_tab[3]; + p_g_rx_dc_gain_tab_array[4 * CALIBRATE_TIMES + calibrate_time] = g_rx_dc_gain_tab[4]; + p_g_rx_dc_gain_tab_array[5 * CALIBRATE_TIMES + calibrate_time] = g_rx_dc_gain_tab[5]; + p_g_rx_dc_gain_tab_array[6 * CALIBRATE_TIMES + calibrate_time] = g_rx_dc_gain_tab[6]; + p_g_rx_dc_gain_tab_array[7 * CALIBRATE_TIMES + calibrate_time] = g_rx_dc_gain_tab[7]; + calibrate_time ++; + } + else +#endif + { + CAL_FATAL("*********** finally result **********\r\n"); + CAL_FATAL("gbias_after_cal: 0x%x\r\n", gbias_after_cal); + CAL_FATAL("gav_tssi: 0x%x\r\n", gav_tssi); + CAL_FATAL("gtx_q_dc_comp:0x%x\r\n", gtx_q_dc_comp); + CAL_FATAL("gtx_i_dc_comp:0x%x\r\n", gtx_i_dc_comp); + CAL_FATAL("gtx_i_gain_comp:%d\r\n", gtx_i_gain_comp); + CAL_FATAL("gtx_q_gain_comp:%d\r\n", gtx_q_gain_comp); + CAL_FATAL("gtx_phase_comp:%d\r\n", gtx_phase_comp); + CAL_FATAL("gtx_phase_ty2:%d\r\n", gtx_phase_ty2); + CAL_FATAL("gtx_ifilter_corner over: 0x%x\r\n", gtx_ifilter_corner); + CAL_FATAL("gtx_qfilter_corner over: 0x%x\r\n", gtx_qfilter_corner); + CAL_FATAL("gtx_dcorMod:0x%x, gtx_dcorPA:0x%x\r\n", gtx_dcorMod, gtx_dcorPA); + CAL_FATAL("gtx_pre_gain:0x%x\r\n", gtx_pre_gain); + CAL_FATAL("g_rx_dc_gain_tab 0 over: 0x%x\r\n", g_rx_dc_gain_tab[0]); + CAL_FATAL("g_rx_dc_gain_tab 1 over: 0x%x\r\n", g_rx_dc_gain_tab[1]); + CAL_FATAL("g_rx_dc_gain_tab 2 over: 0x%x\r\n", g_rx_dc_gain_tab[2]); + CAL_FATAL("g_rx_dc_gain_tab 3 over: 0x%x\r\n", g_rx_dc_gain_tab[3]); + CAL_FATAL("g_rx_dc_gain_tab 4 over: 0x%x\r\n", g_rx_dc_gain_tab[4]); + CAL_FATAL("g_rx_dc_gain_tab 5 over: 0x%x\r\n", g_rx_dc_gain_tab[5]); + CAL_FATAL("g_rx_dc_gain_tab 6 over: 0x%x\r\n", g_rx_dc_gain_tab[6]); + CAL_FATAL("g_rx_dc_gain_tab 7 over: 0x%x\r\n", g_rx_dc_gain_tab[7]); + + CAL_FATAL("grx_amp_err_wr:0x%03x\r\n", grx_amp_err_wr); + CAL_FATAL("grx_phase_err_wr:0x%03x\r\n", grx_phase_err_wr); + CAL_FATAL("**************************************\r\n"); + } +} + +#if CFG_SUPPORT_MANUAL_CALI +static UINT32 rwnx_cal_translate_tx_rate(UINT32 rate) +{ + UINT32 param; + + switch(rate) + { + case 0 : + param = 1; + break; // 1Mbps + case 1 : + param = 2; + break; // 2Mbps + case 2 : + param = 5; + break; // 5.5Mbps + case 3: + param = 11; + break; // 11Mbps + case 4: + param = 6; + break; // 6Mbps + case 5 : + param = 9; + break; // 9Mbps + case 6: + param = 12; + break; // 12Mbps + case 7: + param = 18; + break; // 18Mbps + case 8: + param = 24; + break; // 24Mbps + case 9: + param = 36; + break; // 36Mbps + case 10: + param = 48; + break; // 48Mbps + case 11: + param = 54; + break; // 54Mbps + default: + param = rate; + break; // 54Mbps + } + + return param; +} + +static UINT32 rwnx_cal_translate_tx_rate_for_n(UINT32 rate, UINT32 bandwidth) +{ + UINT32 param; + + switch(rate) + { + case 128 : + case 129 : + case 130 : + case 131 : + case 132 : + case 133 : + param = rate - 123; + break; // MCS0-5 the same rate indx as 9M to 36M + + case 134: + case 135: + if(bandwidth == PHY_CHNL_BW_20) + param = 11; // MCS6-7the same rate indx as to 54M - band:20M + else + param = 12; // MCS6-7the same rate indx as to 135M - band:40M + break; + + default: + param = rate; + break; + } + + return param; +} +#endif + +//static INT32 cur_rate; +void rwnx_cal_set_txpwr_by_rate(INT32 rate, UINT32 test_mode) +{ + UINT32 ret; + UINT32 pwr_gain; + +#if CFG_SUPPORT_MANUAL_CALI + struct phy_channel_info info; + UINT32 channel, bandwidth; // PHY_CHNL_BW_20, PHY_CHNL_BW_40: + + phy_get_channel(&info, 0); + bandwidth = (info.info1 >> 8) & 0xff; + + channel = (BK7011TRXONLY.REG0x7->bits.chin60 - 7)/5; + if(channel > 14) + channel = 14; + if(!manual_cal_get_txpwr(rwnx_cal_translate_tx_rate(rate), + channel, bandwidth, &pwr_gain)) + { + // unable get txpwr from manual cal + return; + } + + ret = manual_cal_get_pwr_idx_shift(rate, bandwidth, &pwr_gain); + if(!ret ){ + // unable get txpwr from manual cal + return; + } else if(ret == 1) { + rwnx_cal_set_txpwr(pwr_gain, EVM_DEFUALT_B_RATE); + } else if(ret == 2) { + rwnx_cal_set_txpwr(pwr_gain, EVM_DEFUALT_RATE); + } + + if(test_mode) + { + os_printf("add extral movement in test\r\n"); + + #if CFG_USE_TEMPERATURE_DETECT + temp_detect_uninit(); + #endif + + BK7011TRX.REG0x6->bits.lpfcapcalq50 = 0x3f; + BK7011TRX.REG0x6->bits.lpfcapcali50 = 0x3f; + CAL_WR_TRXREGS(0x6); + + BK7011TRX.REG0xB->value = 0xF0248033; + CAL_WR_TRXREGS(0xB); + + BK7011TRX.REG0xC->value = 0x1A287CC; + CAL_WR_TRXREGS(0xC); + + BK7011TRX.REG0x13->bits.icpoff20 = 0; + CAL_WR_TRXREGS(0x13); + + if(rate <= 3) { + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = ((bk7011_rc_val[18]>>16) & 0x3ff) + 0x20; + BK7011RCBEKEN.REG0x52->bits.TXPREGAIN = 0; + } + } else { + BK7011TRX.REG0x6->value = bk7011_trx_val[6]; + CAL_WR_TRXREGS(0x6); + + BK7011TRX.REG0xB->value = bk7011_trx_val[11]; + CAL_WR_TRXREGS(0xB); + + BK7011TRX.REG0xC->value = bk7011_trx_val[12]; + CAL_WR_TRXREGS(0xC); + + BK7011TRX.REG0x13->value = bk7011_trx_val[19]; + CAL_WR_TRXREGS(0x13); + + BK7011RCBEKEN.REG0x4F->value = bk7011_rc_val[18]; + + BK7011RCBEKEN.REG0x52->value = bk7011_rc_val[21]; + } +#endif +} + +void rwnx_cal_set_max_twper(FP32 max_tx_pwr) +{ + max_txpwr = max_tx_pwr; +} + +void rwnx_cal_set_40M_setting(void) +{ + BK7011TRX.REG0x12->bits.adcrefbwsel = 1; + BK7011TRX.REG0x12->bits.adciselc20 = 0x4; + BK7011TRX.REG0x12->bits.adciselr20 = 0x4; + CAL_WR_TRXREGS(0x12); + + BK7011TRX.REG0xD->bits.lpfrxbw = 1; + BK7011TRX.REG0xD->bits.lpftxbw = 1; + CAL_WR_TRXREGS(0xD); + + BK7011TRX.REG0xE->bits.lpfrxbw = 1; + BK7011TRX.REG0xE->bits.lpftxbw = 1; + CAL_WR_TRXREGS(0xE); + + BK7011TRX.REG0x10->bits.lpfrxbw = 1; + BK7011TRX.REG0x10->bits.lpftxbw = 1; + CAL_WR_TRXREGS(0x10); + + BK7011TRX.REG0xF->bits.clkdacsel = 1; + BK7011TRX.REG0xF->bits.clkadcsel = 1; + CAL_WR_TRXREGS(0xF); +} + +#if CFG_SUPPORT_MANUAL_CALI + +struct cal_pwr_st { + UINT8 idx; + UINT8 mode; + UINT16 shift; +}; + +struct cal_pwr_st g_pwr_current = {16, EVM_DEFUALT_RATE, 0}; +void rwnx_cal_set_txpwr(UINT32 pwr_gain, UINT32 grate) +{ + const PWR_REGS *pcfg; + + if(pwr_gain > 32) { + os_printf("set_txpwr unknow pwr idx:%d \r\n", pwr_gain); + return; + } + + g_pwr_current.idx = pwr_gain; + g_pwr_current.mode = grate; + + #if CFG_USE_TEMPERATURE_DETECT + pwr_gain = g_pwr_current.idx + g_pwr_current.shift; + //os_printf("temp shift: %d\r\n", g_pwr_current.shift); + + if(pwr_gain > 32) { + pwr_gain = 32; + } + #endif // CFG_USE_TEMPERATURE_DETECT + + if(grate == EVM_DEFUALT_B_RATE) { + // for b + if(max_txpwr) + { + while(pwr_gain) + { + if(rate_tab_b[pwr_gain] > max_txpwr) + { + pwr_gain--; + } + else + { + break; + } + } + } + pcfg = cfg_tab_b + pwr_gain; + } else if(grate == EVM_DEFUALT_RATE) { + // for g + if(max_txpwr) + { + while(pwr_gain) + { + if(rate_tab_g[pwr_gain] > max_txpwr) + { + pwr_gain--; + } + else + { + break; + } + } + } + pcfg = cfg_tab_g + pwr_gain; + } else { + os_printf("set_txpwr unknow rate:%d \r\n", grate); + return; + } + + //os_printf("idx_t:%d\r\n", pwr_gain); + if(pwr_gain > 32) { + pwr_gain = 32; + } + + CHECK_OPERATE_RF_REG_IF_IN_SLEEP(); + BK7011RCBEKEN.REG0x52->bits.TXPREGAIN = gtx_pre_gain = pcfg->pregain; + bk7011_rc_val[21] = BK7011RCBEKEN.REG0x52->value; + + BK7011TRX.REG0xA->bits.dbpaa30 = pcfg->rega_8_11; + CAL_WR_TRXREGS(0xA); + bk7011_trx_val[10] = BK7011TRXONLY.REG0xA->value ; + + BK7011TRX.REG0xB->bits.gctrlmod30 = pcfg->regb_28_31; + CAL_WR_TRXREGS(0xB); + bk7011_trx_val[11] = BK7011TRXONLY.REG0xB->value ; + + BK7011TRX.REG0xC->bits.gctrlpga20 = pcfg->regc_0_2; + BK7011TRX.REG0xC->bits.dgainbuf20 = pcfg->regc_4_6; + BK7011TRX.REG0xC->bits.dgainPA20 = pcfg->regc_8_10; + CAL_WR_TRXREGS(0xC); + bk7011_trx_val[12] = BK7011TRXONLY.REG0xC->value ; + CHECK_OPERATE_RF_REG_IF_IN_SLEEP_END(); +} + +#if CFG_USE_TEMPERATURE_DETECT +void rwnx_cal_set_txpwr_by_tmpdetect(UINT16 shift) +{ + g_pwr_current.shift = shift; + if(shift) + { + os_printf("temd set pwr: idx:%d, rate:%d\r\n", g_pwr_current.idx + shift, g_pwr_current.mode); + rwnx_cal_set_txpwr(g_pwr_current.idx, g_pwr_current.mode); + } +} +#endif // CFG_USE_TEMPERATURE_DETECT + +void rwnx_cal_set_reg_mod_pa(UINT16 reg_mod, UINT16 reg_pa) +{ + CHECK_OPERATE_RF_REG_IF_IN_SLEEP(); + + gtx_dcorMod = (INT32)reg_mod, + gtx_dcorPA = (INT32)reg_pa; + BK7011TRX.REG0xB->bits.dcorMod30 = gtx_dcorMod; + CAL_WR_TRXREGS(0xB); + BK7011TRX.REG0xC->bits.dcorPA30 = gtx_dcorPA; + CAL_WR_TRXREGS(0xC); + + bk7011_trx_val[11] = BK7011TRXONLY.REG0xB->value; + bk7011_trx_val[12] = BK7011TRXONLY.REG0xC->value; + + CHECK_OPERATE_RF_REG_IF_IN_SLEEP_END(); + +} +#endif + +#if CFG_USE_TEMPERATURE_DETECT +void rwnx_cal_do_temp_detect(UINT16 cur_val, UINT16 thre, UINT16 *last) +{ + TMP_PWR_PTR tmp_pwr_ptr; + tmp_pwr_ptr = manual_cal_set_tmp_pwr(cur_val, thre, last); + if(tmp_pwr_ptr) + { + rwnx_cal_set_reg_mod_pa(tmp_pwr_ptr->mod, tmp_pwr_ptr->pa); + + rwnx_cal_set_txpwr_by_tmpdetect(tmp_pwr_ptr->pwr_idx_shift); + } +} +#endif // CFG_USE_TEMPERATURE_DETECT + +void rwnx_tx_cal_save_cal_result(void) +{ + // Manual calibration not used PA & MOD, but use pre_gain + #if CFG_SUPPORT_MANUAL_CALI + gtx_dcorMod = 0x8; + gtx_dcorPA = 0x8; + #if CFG_USE_TEMPERATURE_DETECT + manual_cal_tmp_pwr_init_reg(gtx_dcorMod, gtx_dcorPA); + #endif // CFG_USE_TEMPERATURE_DETECT + #endif + + bk7011_trx_val[11] = (bk7011_trx_val[11] & (~(0xf << 12))) | (((0xf)>x_dcorMod) << 12); + bk7011_trx_val[12] = (bk7011_trx_val[12] & (~(0xf << 12))) | (((0xf)>x_dcorPA) << 12); + bk7011_rc_val[21] = (bk7011_rc_val[21] & (~(0x1f << 16))) | (((0x1f)>x_pre_gain) << 16); + + bk7011_rc_val[18] = (bk7011_rc_val[18] & (~(0x3ff << 16))) | (((0x3ff)>x_i_dc_comp) << 16); + bk7011_rc_val[18] = (bk7011_rc_val[18] & (~0x3ff)) | ((0x3ff)>x_q_dc_comp); + + bk7011_rc_val[19] = (bk7011_rc_val[19] & (~(0x3ff << 16))) | (((0x3ff)>x_i_gain_comp) << 16); + bk7011_rc_val[19] = (bk7011_rc_val[19] & (~0x3ff)) | ((0x3ff)>x_q_gain_comp); + + bk7011_trx_val[6] = (bk7011_trx_val[6] & (~(0x3f << 10))) | (((0x3f)>x_ifilter_corner) << 10); + bk7011_trx_val[6] = (bk7011_trx_val[6] & (~(0x3f << 4))) | (((0x3f)>x_qfilter_corner) << 4); + + bk7011_rc_val[20] = (bk7011_rc_val[20] & (~(0x3ff << 16))) | (((0x3ff)>x_phase_comp) << 16); + bk7011_rc_val[20] = (bk7011_rc_val[20] & (~0x3ff)) | ((0x3ff)>x_phase_ty2); + + //if(gstat_cal) + //bk7011_rc_val[16] = bk7011_rc_val[16] | (1 << 29); + //else + //bk7011_rc_val[16] = bk7011_rc_val[16] & (~(1 << 29)); +} + +void rwnx_rx_cal_save_cal_result(void) +{ + bk7011_trx_val[20] = g_rx_dc_gain_tab[0]; + bk7011_trx_val[21] = g_rx_dc_gain_tab[1]; + bk7011_trx_val[22] = g_rx_dc_gain_tab[2]; + bk7011_trx_val[23] = g_rx_dc_gain_tab[3]; + bk7011_trx_val[24] = g_rx_dc_gain_tab[4]; + bk7011_trx_val[25] = g_rx_dc_gain_tab[5]; + bk7011_trx_val[26] = g_rx_dc_gain_tab[6]; + bk7011_trx_val[27] = g_rx_dc_gain_tab[7]; + + bk7011_rc_val[15] = (bk7011_rc_val[15] & (~(0x3ff << 16))) | (((0x3ff)&grx_amp_err_wr) << 16); + bk7011_rc_val[15] = (bk7011_rc_val[15] & (~0x3ff)) | ((0x3ff)&grx_phase_err_wr); +} + +/******************************************************************************* +* Function Implemantation +*******************************************************************************/ +void bk7011_read_cal_param(void) +{ + gtx_dc_n = (BK7011RCBEKEN.REG0x54->bits.TXDCN & 0x03) + 2; + gst_sar_adc = ((BK7011RCBEKEN.REG0x54->bits.STSARADC & 0x03) + 1) * CAL_DELAY05US; + gst_rx_adc = ((BK7011RCBEKEN.REG0x54->bits.STRXADC & 0x03) + 1) * CAL_DELAY100US; + gconst_iqcal_p = BK7011RCBEKEN.REG0x52->bits.IQCONSTANTIQCALP - 512; + gconst_iqcal_p = abs(gconst_iqcal_p); + gconst_pout = BK7011RCBEKEN.REG0x52->bits.IQCONSTANTPOUT; + + return; +} + +INT32 rwnx_cal_load_trx_rcbekn_reg_val(void) +{ +#if (CFG_RUNNING_PLATFORM == FPGA_PLATFORM) + +#else + BK7011RCBEKEN.REG0x0->value = bk7011_rc_val[0]; + BK7011RCBEKEN.REG0x1->value = bk7011_rc_val[1]; + BK7011RCBEKEN.REG0x5->value = bk7011_rc_val[2]; + BK7011RCBEKEN.REG0x8->value = bk7011_rc_val[3]; + BK7011RCBEKEN.REG0xB->value = bk7011_rc_val[4]; + BK7011RCBEKEN.REG0xE->value = bk7011_rc_val[5]; + BK7011RCBEKEN.REG0x11->value = bk7011_rc_val[6]; + BK7011RCBEKEN.REG0x19->value = bk7011_rc_val[7]; + BK7011RCBEKEN.REG0x1C->value = bk7011_rc_val[8]; + BK7011RCBEKEN.REG0x0->value = bk7011_rc_val[0]; + BK7011RCBEKEN.REG0x1E->value = bk7011_rc_val[9]; + + /**********NEW ADDED************/ + BK7011RCBEKEN.REG0x3C->value = bk7011_rc_val[10]; + BK7011RCBEKEN.REG0x3E->value = bk7011_rc_val[11]; + BK7011RCBEKEN.REG0x3F->value = bk7011_rc_val[12]; + BK7011RCBEKEN.REG0x40->value = bk7011_rc_val[13]; + BK7011RCBEKEN.REG0x41->value = bk7011_rc_val[14]; + BK7011RCBEKEN.REG0x42->value = bk7011_rc_val[15]; + BK7011RCBEKEN.REG0x4C->value = bk7011_rc_val[16]; + BK7011RCBEKEN.REG0x4D->value = bk7011_rc_val[17]; + BK7011RCBEKEN.REG0x4F->value = bk7011_rc_val[18]; + BK7011RCBEKEN.REG0x50->value = bk7011_rc_val[19]; + BK7011RCBEKEN.REG0x51->value = bk7011_rc_val[20]; + BK7011RCBEKEN.REG0x52->value = bk7011_rc_val[21]; + BK7011RCBEKEN.REG0x54->value = bk7011_rc_val[22]; + BK7011RCBEKEN.REG0x55->value = bk7011_rc_val[23]; + BK7011RCBEKEN.REG0x5C->value = bk7011_rc_val[24]; + + //BK7011RCBEKEN.REG0x3C->bits.RXIQSWAP = 1; /* I/Q SWAP*/ + +#endif + + os_memcpy(grc_reg_map, bk7011_trx_val, sizeof(INT32) * 29); + while(BK7011RCBEKEN.REG0x1->value & 0x0FFFFFFF) + { + cpu_delay(1); + } + + BK7011TRXONLY.REG0x0->value = bk7011_trx_val[0]; + BK7011TRXONLY.REG0x1->value = bk7011_trx_val[1]; + BK7011TRXONLY.REG0x2->value = bk7011_trx_val[2]; + BK7011TRXONLY.REG0x3->value = bk7011_trx_val[3]; + BK7011TRXONLY.REG0x4->value = bk7011_trx_val[4]; + BK7011TRXONLY.REG0x5->value = bk7011_trx_val[5]; + BK7011TRXONLY.REG0x6->value = bk7011_trx_val[6]; + BK7011TRXONLY.REG0x7->value = bk7011_trx_val[7]; + BK7011TRXONLY.REG0x8->value = bk7011_trx_val[8]; + BK7011TRXONLY.REG0x9->value = bk7011_trx_val[9]; + BK7011TRXONLY.REG0xA->value = bk7011_trx_val[10]; + BK7011TRXONLY.REG0xB->value = bk7011_trx_val[11]; + BK7011TRXONLY.REG0xC->value = bk7011_trx_val[12]; + BK7011TRXONLY.REG0xD->value = bk7011_trx_val[13]; + BK7011TRXONLY.REG0xE->value = bk7011_trx_val[14]; + BK7011TRXONLY.REG0xF->value = bk7011_trx_val[15]; + BK7011TRXONLY.REG0x10->value = bk7011_trx_val[16]; + BK7011TRXONLY.REG0x11->value = bk7011_trx_val[17]; + BK7011TRXONLY.REG0x12->value = bk7011_trx_val[18]; + BK7011TRXONLY.REG0x13->value = bk7011_trx_val[19]; + BK7011TRXONLY.REG0x14->value = bk7011_trx_val[20]; + BK7011TRXONLY.REG0x15->value = bk7011_trx_val[21]; + BK7011TRXONLY.REG0x16->value = bk7011_trx_val[22]; + BK7011TRXONLY.REG0x17->value = bk7011_trx_val[23]; + BK7011TRXONLY.REG0x18->value = bk7011_trx_val[24]; + BK7011TRXONLY.REG0x19->value = bk7011_trx_val[25]; + BK7011TRXONLY.REG0x1A->value = bk7011_trx_val[26]; + BK7011TRXONLY.REG0x1B->value = bk7011_trx_val[27]; + + while(BK7011RCBEKEN.REG0x1->value & 0x0FFFFFFF) + { + cpu_delay(1); + } + +#ifdef BK7011_VER_A + //os_memcpy(gadda_map, bk7011_adda_val, sizeof(INT32) * 6); + + //BK7011ADDA.REG0x0->value = bk7011_adda_val[0]; + //BK7011ADDA.REG0x1->value = bk7011_adda_val[1]; + //BK7011ADDA.REG0x2->value = bk7011_adda_val[2]; + //BK7011ADDA.REG0x3->value = bk7011_adda_val[3]; + //BK7011ADDA.REG0x4->value = bk7011_adda_val[4]; + //BK7011ADDA.REG0x5->value = bk7011_adda_val[5]; + //BK7011ADDAMAP.REG0x0->value = bk7011_adda_val[0]; + //BK7011ADDAMAP.REG0x1->value = bk7011_adda_val[1]; + //BK7011ADDAMAP.REG0x2->value = bk7011_adda_val[2]; + //BK7011ADDAMAP.REG0x3->value = bk7011_adda_val[3]; + //BK7011ADDAMAP.REG0x4->value = bk7011_adda_val[4]; + //BK7011ADDAMAP.REG0x5->value = bk7011_adda_val[5]; +#endif + +#ifdef BK7011_VER_A + //BK7011RCBEKEN.REG0x54->bits.DSELVA = 0; +#endif + + //BK7011ICU.REG0x3->bits.addaclkinv = 1; + //BK7011ICU.REG0x3->bits.txdacgain = 1 + +#if No_TXPOWERCAL + BK7011TRX.REG0xB->value = TRX_REG_0XB_VAL; + CAL_WR_TRXREGS(0xB); + BK7011TRX.REG0xC->value = TRX_REG_0XC_VAL; + CAL_WR_TRXREGS(0xC); + + BK7011RCBEKEN.REG0x52->bits.TXPREGAIN = 7; +#endif + + // cal rf pll when reload trx and rc beken value + bk7011_cal_pll(); + return 0; +} + +INT32 rwnx_cal_save_trx_rcbekn_reg_val(void) +{ +#if (CFG_RUNNING_PLATFORM == FPGA_PLATFORM) + +#else + bk7011_rc_val[0] = BK7011RCBEKEN.REG0x0->value ; + bk7011_rc_val[1] = BK7011RCBEKEN.REG0x1->value ; + bk7011_rc_val[2] = BK7011RCBEKEN.REG0x5->value ; + bk7011_rc_val[3] = BK7011RCBEKEN.REG0x8->value ; + bk7011_rc_val[4] = BK7011RCBEKEN.REG0xB->value ; + bk7011_rc_val[5] = BK7011RCBEKEN.REG0xE->value ; + bk7011_rc_val[6] = BK7011RCBEKEN.REG0x11->value; + bk7011_rc_val[7] = BK7011RCBEKEN.REG0x19->value; + bk7011_rc_val[8] = BK7011RCBEKEN.REG0x1C->value; + bk7011_rc_val[0] = BK7011RCBEKEN.REG0x0->value ; + bk7011_rc_val[9] = BK7011RCBEKEN.REG0x1E->value; + + /**********NEW ADDED************/ + bk7011_rc_val[10] = BK7011RCBEKEN.REG0x3C->value; + bk7011_rc_val[11] = BK7011RCBEKEN.REG0x3E->value; + bk7011_rc_val[12] = BK7011RCBEKEN.REG0x3F->value; + bk7011_rc_val[13] = BK7011RCBEKEN.REG0x40->value; + bk7011_rc_val[14] = BK7011RCBEKEN.REG0x41->value; + bk7011_rc_val[15] = BK7011RCBEKEN.REG0x42->value; + bk7011_rc_val[16] = BK7011RCBEKEN.REG0x4C->value; + bk7011_rc_val[17] = BK7011RCBEKEN.REG0x4D->value; + bk7011_rc_val[18] = BK7011RCBEKEN.REG0x4F->value; + bk7011_rc_val[19] = BK7011RCBEKEN.REG0x50->value; + bk7011_rc_val[20] = BK7011RCBEKEN.REG0x51->value; + bk7011_rc_val[21] = BK7011RCBEKEN.REG0x52->value; + bk7011_rc_val[22] = BK7011RCBEKEN.REG0x54->value; + bk7011_rc_val[23] = BK7011RCBEKEN.REG0x55->value; + bk7011_rc_val[24] = BK7011RCBEKEN.REG0x5C->value; + + //BK7011RCBEKEN.REG0x3C->bits.RXIQSWAP = 1; /* I/Q SWAP*/ + +#endif + + bk7011_trx_val[0] = BK7011TRXONLY.REG0x0->value ; + bk7011_trx_val[1] = BK7011TRXONLY.REG0x1->value ; + bk7011_trx_val[2] = BK7011TRXONLY.REG0x2->value ; + bk7011_trx_val[3] = BK7011TRXONLY.REG0x3->value ; + bk7011_trx_val[4] = BK7011TRXONLY.REG0x4->value ; + bk7011_trx_val[5] = BK7011TRXONLY.REG0x5->value ; + bk7011_trx_val[6] = BK7011TRXONLY.REG0x6->value ; + bk7011_trx_val[7] = BK7011TRXONLY.REG0x7->value ; + bk7011_trx_val[8] = BK7011TRXONLY.REG0x8->value ; + bk7011_trx_val[9] = BK7011TRXONLY.REG0x9->value ; + bk7011_trx_val[10] = BK7011TRXONLY.REG0xA->value ; + bk7011_trx_val[11] = BK7011TRXONLY.REG0xB->value ; + bk7011_trx_val[12] = BK7011TRXONLY.REG0xC->value ; + bk7011_trx_val[13] = BK7011TRXONLY.REG0xD->value ; + bk7011_trx_val[14] = BK7011TRXONLY.REG0xE->value ; + bk7011_trx_val[15] = BK7011TRXONLY.REG0xF->value ; + bk7011_trx_val[16] = BK7011TRXONLY.REG0x10->value; + bk7011_trx_val[17] = BK7011TRXONLY.REG0x11->value; + bk7011_trx_val[18] = BK7011TRXONLY.REG0x12->value; + bk7011_trx_val[19] = BK7011TRXONLY.REG0x13->value; + bk7011_trx_val[20] = BK7011TRXONLY.REG0x14->value; + bk7011_trx_val[21] = BK7011TRXONLY.REG0x15->value; + bk7011_trx_val[22] = BK7011TRXONLY.REG0x16->value; + bk7011_trx_val[23] = BK7011TRXONLY.REG0x17->value; + bk7011_trx_val[24] = BK7011TRXONLY.REG0x18->value; + bk7011_trx_val[25] = BK7011TRXONLY.REG0x19->value; + bk7011_trx_val[26] = BK7011TRXONLY.REG0x1A->value; + bk7011_trx_val[27] = BK7011TRXONLY.REG0x1B->value; + + os_memcpy(grc_reg_map, bk7011_trx_val, sizeof(INT32) * 29); + while(BK7011RCBEKEN.REG0x1->value & 0x0FFFFFFF) + { + cpu_delay(1); + } + + return 0; +} + +void bk7011_cal_ready(void) +{ + rwnx_cal_load_trx_rcbekn_reg_val(); + + bk7011_read_cal_param(); + rwnx_cal_load_default_result(); + + cpu_delay(1000); + /*step 4.2*/ + BK7011RCBEKEN.REG0x4C->bits.TXCOMPDIS = 0; + //gstat_cal = 0; // calibration start + + return; +} + +void bk7011_cal_dpll(void) +{ + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_CALI_DPLL, NULL); +} + +#define BIAS_DIFF_VAL1 (4u) +#define BIAS_DIFF_VAL2 (2u) +void bk7011_cal_bias(void) +{ + UINT32 param, param2; + // BK7011TRX.REG0xF->bits.biascalmanual = 0; + param = PARAM_BIAS_CAL_MANUAL_BIT; + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_BIAS_REG_CLEAN, ¶m); + + // BK7011TRX.REG0xF->bits.biascaltrig = 0; + param = PARAM_BIAS_CAL_TRIGGER_BIT; + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_BIAS_REG_CLEAN, ¶m); + //trx_reg_is_write(st_TRXREG0F); + //BK7011TRXONLY.REG0xF->value = BK7011TRX.REG0xF->value; + cpu_delay(100); + // BK7011TRX.REG0xF->bits.biascaltrig = 1; + param = PARAM_BIAS_CAL_TRIGGER_BIT; + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_BIAS_REG_SET, ¶m); + + //trx_reg_is_write(st_TRXREG0F); + //BK7011TRXONLY.REG0xF->value = BK7011TRX.REG0xF->value; + cpu_delay(DELAY1US * 40);//40us = 30 + 10; + + //Read SYS_CTRL.REG0x4C->bias_cal_out + param = sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_BIAS_REG_READ, ¶m); + param = (param >> PARAM_BIAS_CAL_OUT_POSI) & PARAM_BIAS_CAL_OUT_MASK; + + //First, Write SYS_CTRL.REG0x4C->ldo_val_man = bias_cal_out + BIAS_DIFF_VAL1 + param += BIAS_DIFF_VAL1; + param2 = param; + if (param > 0x1f) param = 0x1f; + param = ((param & PARAM_BIAS_CAL_OUT_MASK) << PARAM_LDO_VAL_MANUAL_POSI) + | PARAM_BIAS_CAL_MANUAL_BIT; + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_BIAS_REG_WRITE, ¶m); + + //Second, Write SYS_CTRL.REG0x4C->ldo_val_man = ldo_val_man - BIAS_DIFF_VAL2 + param = param2 - BIAS_DIFF_VAL2; + if (param > 0x1f) param = 0x1f; + gbias_after_cal = param; + param = ((param & PARAM_BIAS_CAL_OUT_MASK) << PARAM_LDO_VAL_MANUAL_POSI) + | PARAM_BIAS_CAL_MANUAL_BIT; + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_BIAS_REG_WRITE, ¶m); + + + //param = ((0x3 & PARAM_VSEL_SYS_LDO_MASK)<< PARAM_VSEL_SYS_LDO_POSI); + //sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_ANALOG_CTRL4_SET, ¶m); + + return; +} + +void bk7011_cal_pll(void) +{ +#if 1 + // uint32_t loop = 0, val; + + // do + { +#if 0 + +#else + + /*reg0x10 enrfpll = 1*/ + BK7011TRX.REG0x10->bits.enrfpll = 1; + BK7011TRX.REG0x10->bits.endpll = 1; + CAL_WR_TRXREGS(0x10); + + /*reg0x00 spitrig = 0->1->0*/ + BK7011TRX.REG0x0->bits.spitrig = 0; + CAL_WR_TRXREGS(0x0); + BK7011TRX.REG0x0->bits.spitrig = 1; + CAL_WR_TRXREGS(0x0); + BK7011TRX.REG0x0->bits.spitrig = 0; + CAL_WR_TRXREGS(0x0); + + /*reg0x05 spitrigger = 0->1->0*/ + BK7011TRX.REG0x5->bits.spitrigger = 0; + BK7011TRX.REG0x5->bits.errdetspien = 0; + CAL_WR_TRXREGS(0x5); + BK7011TRX.REG0x5->bits.spitrigger = 1; + CAL_WR_TRXREGS(0x5); + BK7011TRX.REG0x5->bits.spitrigger = 0; + CAL_WR_TRXREGS(0x5); + BK7011TRX.REG0x5->bits.errdetspien = 1; + CAL_WR_TRXREGS(0x5); +#endif + + cpu_delay(DELAY1US * 10); + + } + +#endif +} + + +void bk7011_tx_cal_en(void) +{ + BK7011RCBEKEN.REG0x0->bits.forceenable = 1; + cpu_delay(1); + BK7011RCBEKEN.REG0x19->bits.FCH0EN = 1; + BK7011RCBEKEN.REG0x19->bits.FCH0SHDN = 1; + BK7011RCBEKEN.REG0x19->bits.FCH0RXEN = 0; + BK7011RCBEKEN.REG0x19->bits.FCH0TXEN = 1; + BK7011RCBEKEN.REG0x1C->bits.FRXON = 0; + BK7011RCBEKEN.REG0x1C->bits.FTXON = 1; + //BK7011RCBEKEN.REG0x4D->bits.TXSINF = 0x1A; + + //BK7011ICU.REG0x3->value = 0x00010002; + return; +} + +static INT32 bk7011_get_tx_output_power(void) +{ + int i; + INT32 tssioutpower = 0; + + for (i = 0; i < 4; i++) + { + cal_delay(1 * gst_sar_adc); + tssioutpower += BK7011RCBEKEN.REG0x54->bits.TSSIRD; + } + + if(gtx_power_cal_mode == TX_WANTED_POWER_CAL) // + { + + tssioutpower = tssioutpower / 4 - TSSI_POUT_TH - gav_tssi_temp; + } + else if(gtx_power_cal_mode == TX_IQ_POWER_CAL) // + { + + tssioutpower = tssioutpower / 4 - TXIQ_IMB_TSSI_TH - gav_tssi_temp; + } + else + { + tssioutpower = tssioutpower / 4 - TXIQ_IMB_TSSI_TH_LOOPBACK - gav_tssi_temp; + } + + + tssioutpower = abs(tssioutpower); + //tssioutpower = abs((INT32)(((INT32)BK7011RCBEKEN.REG0x54->bits.TSSIRD) - gconst_tssi_pout_th)); + + return tssioutpower; +} + + +static INT32 bk7011_set_tx_pa(INT32 val1, INT32 val2, INT32 val3, INT32 val4) +{ + BK7011TRX.REG0xC->bits.dgainPA20 = val1; + BK7011TRX.REG0xC->bits.dgainbuf20 = val2; + BK7011TRX.REG0xC->bits.gctrlpga20 = val3; + BK7011TRX.REG0xB->bits.gctrlmod30 = val4; + CAL_WR_TRXREGS(0xC); + CAL_WR_TRXREGS(0xB); + + return 0; +} + +#define GET_AV_TSSI_CNT 4 + +INT32 bk7011_cal_tx_output_power(INT32 *val) +{ + INT32 gold_index = 0; + INT32 tssilow = 0; + INT32 tssihigh = 0; + INT32 index = 0; + INT16 high, low, tx_fre_gain; + INT32 cnt = 0; + + // bk7011_rc_val[12]-16:20=7, 0x53479D40, 21 REG_0x52 + BK7011RCBEKEN.REG0x52->bits.TXPREGAIN = 7; + + BK7011TRX.REG0xB->value = TRX_REG_0XB_VAL; + CAL_WR_TRXREGS(0xB); + + BK7011RCBEKEN.REG0x4C->bits.ICONSTANT = 0x200; + BK7011RCBEKEN.REG0x4C->bits.QCONSTANT = 0x200; + BK7011TRX.REG0xC->value = TRX_REG_0XC_TXLO_LEAKAGE_VAL; + BK7011RCBEKEN.REG0x4C->bits.TESTPATTERN = 1; + if (gtx_power_cal_mode == TX_WANTED_POWER_CAL) + { + BK7011TRX.REG0xD->value = TRX_REG_0XD_VAL; + BK7011TRX.REG0xA->value = TRX_REG_0XA_VAL;//by yiming 20170315; + BK7011TRX.REG0xB->value = TRX_REG_0XB_VAL;//; + BK7011TRX.REG0xC->value = TRX_REG_0XC_VAL;//; + BK7011TRX.REG0xC->bits.TSSIsel = 1; + BK7011TRX.REG0xC->bits.enDCcali = 0; + BK7011TRX.REG0xC->bits.enIQcali = 0; + BK7011TRX.REG0xC->bits.enPcali = 1; + } + else if(gtx_power_cal_mode == TX_IQ_POWER_CAL) + { + BK7011TRX.REG0xD->value = TRX_REG_0XD_TX_IQ_VAL; + BK7011TRX.REG0xA->value = 0x83703274;//by yiming 20170315; + BK7011TRX.REG0xB->value = 0x20246077;//; + BK7011TRX.REG0xC->value = 0x01A282CE;//;0x01A287EE + bk7011_set_tx_pa(gi_gain_tx_pa_dgainPA20, gi_gain_tx_pa_dgainbuf20, 5, 8); + BK7011TRX.REG0xC->bits.TSSIsel = 0; + BK7011TRX.REG0xC->bits.enDCcali = 1; + BK7011TRX.REG0xC->bits.enIQcali = 1; + BK7011TRX.REG0xC->bits.enPcali = 0; + } + else //gtx_power_cal_mode == TX_IQ_LOOPBACK_POWER_CAL + { + BK7011TRX.REG0xD->value = TRX_REG_0XD_TX_LOOPBACK_IQ_VAL; + BK7011TRX.REG0xA->value = 0x83703274;//by yiming 20170315; + BK7011TRX.REG0xB->value = 0x20246077;//; + BK7011TRX.REG0xC->value = 0x01A282CE;//;0x01A287EE + bk7011_set_tx_pa(gi_gain_tx_loopback_pa_dgainPA20, gi_gain_tx_loopback_pa_dgainbuf20, 5, 8); + BK7011TRX.REG0xC->bits.TSSIsel = 0; + BK7011TRX.REG0xC->bits.enDCcali = 1; + BK7011TRX.REG0xC->bits.enIQcali = 1; + BK7011TRX.REG0xC->bits.enPcali = 0; + } + + BK7011TRX.REG0xD->bits.entssi = 1; + BK7011TRX.REG0xD->bits.entssiadc = 1;//20170503 enable TSSI + BK7011TRX.REG0xC->bits.enDCcaliGm1 = 0; + BK7011TRX.REG0xC->bits.enPcaliGm = 0; + BK7011TRX.REG0xF->bits.tssicalen = 1; + CAL_WR_TRXREGS(0xA); + CAL_WR_TRXREGS(0xD); + CAL_WR_TRXREGS(0xC); + CAL_WR_TRXREGS(0xF); + BK7011TRX.REG0xB->bits.dcorMod30 = 0; + CAL_WR_TRXREGS(0xB); + cal_delay(150);//for reg C,D,F write spi=80/16=5M,total time is 21.6us + cal_delay(5 * gst_sar_adc); + + gav_tssi_temp = 0; + for(cnt = 0; cnt < GET_AV_TSSI_CNT; cnt++) + { + cal_delay(1 * gst_sar_adc); + gav_tssi_temp += BK7011RCBEKEN.REG0x54->bits.TSSIRD; + } + cnt = 0; + gav_tssi_temp /= GET_AV_TSSI_CNT;//Get small power tssi of each sample to remove tssi dc + if (gtx_power_cal_mode == TX_WANTED_POWER_CAL) + { + gav_tssi = gav_tssi_temp; + } + + if (gtx_power_cal_mode == TX_WANTED_POWER_CAL) + { + BK7011RCBEKEN.REG0x4C->bits.ICONSTANT = gconst_pout; + BK7011RCBEKEN.REG0x4C->bits.QCONSTANT = gconst_pout; + BK7011TRX.REG0xC->value = TRX_REG_0XC_VAL;//; + CAL_WR_TRXREGS(0xC); + BK7011TRX.REG0xC->bits.TSSIsel = 1; + BK7011TRX.REG0xC->bits.enDCcali = 0; + BK7011TRX.REG0xC->bits.enIQcali = 0; + BK7011TRX.REG0xC->bits.enPcali = 1; + + } + else if(gtx_power_cal_mode == TX_IQ_POWER_CAL) + { + BK7011RCBEKEN.REG0x4C->bits.ICONSTANT = 0x240; + BK7011RCBEKEN.REG0x4C->bits.QCONSTANT = 0x240; + BK7011TRX.REG0xC->value = 0x01A282CE;//;0x01A287EE + CAL_WR_TRXREGS(0xC); + bk7011_set_tx_pa(gi_gain_tx_pa_dgainPA20, gi_gain_tx_pa_dgainbuf20, 5, 8); + BK7011TRX.REG0xC->bits.TSSIsel = 0; + BK7011TRX.REG0xC->bits.enDCcali = 1; + BK7011TRX.REG0xC->bits.enIQcali = 1; + BK7011TRX.REG0xC->bits.enPcali = 0; + } + else //gtx_power_cal_mode == TX_IQ_LOOPBACK_POWER_CAL + { + BK7011RCBEKEN.REG0x4C->bits.ICONSTANT = 0x260;//by yiming 20170315; 250 + BK7011RCBEKEN.REG0x4C->bits.QCONSTANT = 0x260; + BK7011TRX.REG0xC->value = 0x01A282CE;//;0x01A287EE + CAL_WR_TRXREGS(0xC); + bk7011_set_tx_pa(gi_gain_tx_loopback_pa_dgainPA20, gi_gain_tx_loopback_pa_dgainbuf20, 5, 8); + BK7011TRX.REG0xC->bits.TSSIsel = 0; + BK7011TRX.REG0xC->bits.enDCcali = 1; + BK7011TRX.REG0xC->bits.enIQcali = 1; + BK7011TRX.REG0xC->bits.enPcali = 0; + } + + BK7011TRX.REG0xC->bits.enDCcaliGm1 = 0; + BK7011TRX.REG0xC->bits.enPcaliGm = 0; + BK7011TRX.REG0xF->bits.tssicalen = 1; + BK7011TRX.REG0xC->bits.dcorPA30 = 8; + + CAL_WR_TRXREGS(0xA); + CAL_WR_TRXREGS(0xD); + CAL_WR_TRXREGS(0xC); + CAL_WR_TRXREGS(0xF); + BK7011RCBEKEN.REG0x4C->bits.TESTPATTERN = 1; + + low = 0; + high = 8; + + BK7011TRX.REG0xB->bits.dcorMod30 = low; + CAL_WR_TRXREGS(0xB); + cal_delay(CAL_TX_NUM);//first sar dac delay needs double time + tssilow = bk7011_get_tx_output_power(); + + + BK7011TRX.REG0xB->bits.dcorMod30 = high; + CAL_WR_TRXREGS(0xB); + tssihigh = bk7011_get_tx_output_power(); + + do + { + CAL_PRT("cnt:%d, index:%d, tssilow:0x%x-%d, tssihigh:0x%x-%d\r\n", + cnt++, index, tssilow, low, tssihigh, high); + if(tssilow < tssihigh) + { + index = low; + high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011TRX.REG0xB->bits.dcorMod30 = high; + CAL_WR_TRXREGS(0xB); + tssihigh = bk7011_get_tx_output_power(); + } + else + { + index = high; + low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011TRX.REG0xB->bits.dcorMod30 = low; + CAL_WR_TRXREGS(0xB); + tssilow = bk7011_get_tx_output_power(); + } + } + while((high - low) > 1); + + index = ((tssilow < tssihigh) ? low : high); + if (gtx_power_cal_mode == TX_WANTED_POWER_CAL) + { + gtx_dcorMod = index; + } +#ifdef CALIBRATE_TIMES + else if(gtx_power_cal_mode == TX_IQ_POWER_CAL) + { + if (p_gbias_after_cal_array == NULL) + { + CAL_TIM_PRT("bk7011 TX IQ Cal. Output Power: \r\ntx_dcorMod= %d, ", index); + } + gtx_dcorMod_temp = index; + + } + else + { + if (p_gbias_after_cal_array == NULL) + { + CAL_TIM_PRT("bk7011 TX IQ Cal. Output Power: \r\ntx_dcorMod= %d, ", index); + } + gtx_dcorMod_temp_loopback = index; + } + +#endif + + CAL_PRT("gtx_dcorMod over: 0x%x\r\n", gtx_dcorMod); + CAL_PRT("cnt:%d, index:%d, tssilow:0x%x-%d, tssihigh:0x%x-%d\r\n", + cnt++, index, tssilow, low, tssihigh, high); + + BK7011TRX.REG0xB->bits.dcorMod30 = index; + CAL_WR_TRXREGS(0xB); + gold_index = index << 8; + cal_delay(6); + + //BK7011TRX.REG0xB->bits.dcorMod30 = index; // dcormod30 optimum + //trx_reg_is_write(st_TRXREG0B); + //BK7011TRXONLY.REG0xB->value = BK7011TRX.REG0xB->value; + low = 0; + high = 8; + BK7011TRX.REG0xC->bits.dcorPA30 = low; + CAL_WR_TRXREGS(0xC); + tssilow = bk7011_get_tx_output_power(); + + BK7011TRX.REG0xC->bits.dcorPA30 = high; + CAL_WR_TRXREGS(0xC); + tssihigh = bk7011_get_tx_output_power(); + + do + { + CAL_PRT("cnt:%d, index:%d, tssilow:0x%x-%d, tssihigh:0x%x-%d\r\n", + cnt++, index, tssilow, low, tssihigh, high); + if(tssilow < tssihigh) + { + index = low; + high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011TRX.REG0xC->bits.dcorPA30 = high; + CAL_WR_TRXREGS(0xC); + tssihigh = bk7011_get_tx_output_power(); + } + else + { + index = high; + low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011TRX.REG0xC->bits.dcorPA30 = low; + CAL_WR_TRXREGS(0xC); + tssilow = bk7011_get_tx_output_power(); + } + } + while((high - low) > 1); + + index = ((tssilow < tssihigh) ? low : high); + if (gtx_power_cal_mode == TX_WANTED_POWER_CAL) + { + gtx_dcorPA = index; + } +#ifdef CALIBRATE_TIMES + else if(gtx_power_cal_mode == TX_IQ_POWER_CAL) + { + if (p_gbias_after_cal_array == NULL) + { + CAL_TIM_PRT("tx_dcorPA= %d\r\n", index); + } + gtx_dcorPA_temp = index; + } + else + { + if (p_gbias_after_cal_array == NULL) + { + CAL_TIM_PRT("tx_dcorPA= %d\r\n", index); + } + gtx_dcorPA_temp_loopback = index; + } +#endif + BK7011TRX.REG0xC->bits.dcorPA30 = index; + CAL_WR_TRXREGS(0xC); + gold_index += index; + + //method2: first searching "dcorPA30",then serching "dcormod30"; + /**************************************************************** + * + *****************************************************************/ + *val = gold_index; + + CAL_PRT("gtx_dcorMod:0x%x, gtx_dcorPA:0x%x\r\n", gtx_dcorMod, gtx_dcorPA); + +#if 1 + tx_fre_gain = BK7011RCBEKEN.REG0x52->bits.TXPREGAIN; + //CAL_WARN("tx_fre_gain:0x%x\r\n", tx_fre_gain); + + if(tx_fre_gain > 2) + low = tx_fre_gain - 2; + else + low = 0; + high = tx_fre_gain + 2; + + + BK7011RCBEKEN.REG0x52->bits.TXPREGAIN = low; + + //cpu_delay(1); + // tssilow = bk7011_get_tx_output_power_pregain(); + tssilow = bk7011_get_tx_output_power(); + + BK7011RCBEKEN.REG0x52->bits.TXPREGAIN = high; + //cpu_delay(1); + // tssihigh = bk7011_get_tx_output_power_pregain(); + tssihigh = bk7011_get_tx_output_power(); + + do + { + if(tssilow < tssihigh) + { + index = low; + high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x52->bits.TXPREGAIN = high; + //cpu_delay(1); + // tssihigh = bk7011_get_tx_output_power_pregain(); + tssihigh = bk7011_get_tx_output_power(); + } + else + { + index = high; + low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x52->bits.TXPREGAIN = low; + //cpu_delay(1); + // tssilow = bk7011_get_tx_output_power_pregain(); + tssilow = bk7011_get_tx_output_power(); + } + + } + while((high - low) > 1); + + index = ((tssilow < tssihigh) ? low : high); + + BK7011RCBEKEN.REG0x52->bits.TXPREGAIN = index; + if (gtx_power_cal_mode == TX_WANTED_POWER_CAL) + { + gtx_pre_gain = index; + } +#ifdef CALIBRATE_TIMES + else if(gtx_power_cal_mode == TX_IQ_POWER_CAL) + { + if (p_gbias_after_cal_array == NULL) + { + CAL_TIM_PRT("tx_pre_gain= %d\r\n", index); + } + gtx_pre_gain_temp = index; + } + else + { + if (p_gbias_after_cal_array == NULL) + { + CAL_TIM_PRT("tx_pre_gain= %d\r\n", index); + } + gtx_pre_gain_temp_loopback = index; + + } +#endif + + CAL_PRT("gtx_pre_gain:0x%x\r\n", gtx_pre_gain); +#endif + +#if 0 + if(gtx_dcorMod >= 0xa && gtx_dcorPA >= 0xc) + while(1); +#endif + + return (gold_index); +} + +#if 0 +void bk7011_micopwr_config_tssi_read_prepare(void) +{ + BK7011TRX.REG0xC->bits.TSSIsel = 1; + BK7011TRX.REG0xC->bits.enDCcali = 0; + BK7011TRX.REG0xC->bits.enIQcali = 0; + BK7011TRX.REG0xC->bits.enPcali = 1; + BK7011TRX.REG0xD->bits.entssi = 1; + BK7011TRX.REG0xD->bits.entssiadc = 1;//20170503 enable TSSI + BK7011TRX.REG0xC->bits.enDCcaliGm1 = 0; + BK7011TRX.REG0xC->bits.enPcaliGm = 0; + BK7011TRX.REG0xF->bits.tssicalen = 1; + + CAL_WR_TRXREGS(0xD); + CAL_WR_TRXREGS(0xC); + CAL_WR_TRXREGS(0xF); +} + +#include "math.h" +#define TSSI_TAB_LEN 40 +#define TEMP_TAB_LEN 10 +//UINT8 tssi_tab[TSSI_TAB_LEN]; +UINT8 temp_tab[TSSI_TAB_LEN]; + +void bk7011_micopwr_tssi_read(void) +{ + UINT32 i; + REG_WRITE((0x0802800 + (18 * 4)), 0x00); + for(i = 0; i < TSSI_TAB_LEN; i++) + { + tssi_tab[i] = BK7011RCBEKEN.REG0x54->bits.TSSIRD & 0xff; + } + //REG_WRITE((0x0802800 + (18 * 4)), 0x00); +} + +void bk7011_micopwr_tssi_show(void) +{ + UINT32 i, s = 0; + double sd = 0; + os_printf("\r\n tssi tab: \r\n"); + for(i = 0; i < TSSI_TAB_LEN; i++) + { + os_printf("%d, ", tssi_tab[i]); + if((i + 1) % 16 == 0) + os_printf("\r\n"); + } + + for(i = 0; i < TSSI_TAB_LEN; i++) + { + s += tssi_tab[i] * tssi_tab[i]; + } + sd = sqrt((double)(s / TSSI_TAB_LEN)); + os_printf("\r\nsd = %f\r\n", sd); +} +#endif + +static INT32 bk7011_update_tx_power(void) +{ +#ifdef CALIBRATE_TIMES + bk7011_set_tx_pa(gi_dc_tx_pa_dgainPA20, gi_dc_tx_pa_dgainbuf20, 6, 2);// mod gain should be same as the powser cal. setting +#else + bk7011_set_tx_pa(gi_dc_tx_pa_dgainPA20, gi_dc_tx_pa_dgainbuf20, 6, 2); +#endif + return 0; +} + +static INT32 bk7011_update_tx_loopback_power(void) +{ +#ifdef CALIBRATE_TIMES + bk7011_set_tx_pa(gi_dc_tx_loopback_pa_dgainPA20, gi_dc_tx_loopback_pa_dgainbuf20, 5, 8); +#else + bk7011_set_tx_pa(gi_dc_tx_loopback_pa_dgainPA20, gi_dc_tx_loopback_pa_dgainbuf20, 5, 8); +#endif + return 0; +} + +static INT32 bk7011_get_tx_dc(void) +{ + INT32 detect_dc = 0; + INT16 i; + + + + cpu_delay(200);//18us + + for(i = 0; i < SUMNUMBERS; i++) + { + cal_delay(5 * gst_sar_adc); + detect_dc += BK7011RCBEKEN.REG0x54->bits.TSSIRD; + } + + return detect_dc; +} +/* +static INT32 bk7011_get_tx_dc_1(void) +{ + INT32 detect_dc = 0; + INT16 i; + + + //BK7011TRXONLY.REG0xD->value = BK7011TRX.REG0xD->value; + CAL_WR_TRXREGS(0xC); + CAL_WR_TRXREGS(0xF); + + cpu_delay(200); + for(i = 0; i < SUMNUMBERS; i++) + { + cal_delay(5 * gst_sar_adc); + detect_dc += BK7011RCBEKEN.REG0x54->bits.TSSIRD; + } + return detect_dc; +} +*/ + +INT32 bk7011_cal_tx_dc(INT32 *val) +{ + INT32 detect_dc_low = 0; + INT32 detect_dc_high = 0; + INT16 high, low; + INT32 index, gold_index = 0; + INT32 i_index, q_index; + INT32 srchcnt = 0; + INT16 search_thrd = 64;//DC search range search_thrd=64 gtx_dc_n=0,search_thrd=512 gtx_dc_n=3,search_thrd=256 gtx_dc_n=2, search_thrd=128 gtx_dc_n=1 + /*step 4*/ + + + if(gtx_dc_cal_mode == TX_DC_CAL) + { + BK7011TRX.REG0xD->value = TRX_REG_0XD_TX_IQ_VAL; //BK7011TRXREG0xD;// + CAL_WR_TRXREGS(0xD); + bk7011_update_tx_power(); + } + else// (gtx_dc_cal_mode == TX_DC_LOOPBACK_CAL) + { + BK7011TRX.REG0xD->value = TRX_REG_0XD_TX_LOOPBACK_IQ_VAL; + CAL_WR_TRXREGS(0xD); + bk7011_update_tx_loopback_power(); + } + + + + +#ifdef CALIBRATE_TIMES + if (p_gbias_after_cal_array == NULL) + { + if(gtx_dc_cal_mode == TX_DC_CAL) + { + CAL_TIM_PRT("\r\nbk7011_cal_tx_dc: \r\n"); + } + else// (gtx_dc_cal_mode == TX_DC_LOOPBACK_CAL) + { + CAL_TIM_PRT("\r\nbk7011_cal_tx_loopback_dc: \r\n"); + } + CAL_TIM_PRT("dgainPA20 = %d\r\n", BK7011TRX.REG0xC->bits.dgainPA20 ); + CAL_TIM_PRT("dgainbuf20 =%d\r\n", BK7011TRX.REG0xC->bits.dgainbuf20); + CAL_TIM_PRT("gctrlpga20 = %d\r\n", BK7011TRX.REG0xC->bits.gctrlpga20 ); + CAL_TIM_PRT("gctrlmod30 = %d\r\n", BK7011TRX.REG0xB->bits.gctrlmod30); + } +#endif + + //[-512 511]---->[0,1023]; + + // I DC calibration; + BK7011RCBEKEN.REG0x4F->bits.TXQDCCOMP = UNSIGNEDOFFSET10 + 0; //default + + if(gtx_dc_cal_mode == TX_DC_CAL) + { + low = UNSIGNEDOFFSET10 - MINOFFSET ; + high = UNSIGNEDOFFSET10 + MINOFFSET ; + } + else// (gtx_dc_cal_mode == TX_DC_LOOPBACK_CAL) + { + low = UNSIGNEDOFFSET10 - 3 * MINOFFSET ; + high = UNSIGNEDOFFSET10 + 3 * MINOFFSET ; + } + + + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = low; + + //20170330 + BK7011RCBEKEN.REG0x4C->bits.ICONSTANT = UNSIGNEDOFFSET10 - 1; + BK7011RCBEKEN.REG0x4C->bits.QCONSTANT = UNSIGNEDOFFSET10 - 1 ; + BK7011RCBEKEN.REG0x4C->bits.TESTPATTERN = 1; + BK7011TRX.REG0xC->bits.TSSIsel = 0; + BK7011TRX.REG0xC->bits.enDCcali = 1; + BK7011TRX.REG0xC->bits.enDCcaliGm1 = 0;//inverse 20141014 + BK7011TRX.REG0xC->bits.enIQcali = 0; + BK7011TRX.REG0xC->bits.enPcali = 0; + BK7011TRX.REG0xC->bits.enPcaliGm = 0; + BK7011TRX.REG0xF->bits.tssicalen = 1; + //20170330 + + //BK7011TRXONLY.REG0xD->value = BK7011TRX.REG0xD->value; + CAL_WR_TRXREGS(0xC); + CAL_WR_TRXREGS(0xF); + cal_delay(CAL_TX_NUM);//first sar dac delay needs double time + + detect_dc_low = bk7011_get_tx_dc(); + + + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + //Step 1 3~6 search; + srchcnt = 0; + + + + if(detect_dc_low < detect_dc_high) + { + high = 511; + low = high - search_thrd; + } + else + { + low = 512; + high = low + search_thrd; + } + + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = low; + detect_dc_low = bk7011_get_tx_dc(); + + do + { + if(detect_dc_low < detect_dc_high) + { + index = low; + high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + + } + else + { + index = high; + low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = low; + detect_dc_low = bk7011_get_tx_dc(); + } + srchcnt++; + if(srchcnt > gtx_dc_n) + break; + } + while((high - low) > 1); + + //Step 2 search; + + BK7011TRX.REG0xC->bits.enDCcaliGm1 = 1;//20170330 YIMING + + + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = low; + detect_dc_low = bk7011_get_tx_dc(); + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + + do + { + if(detect_dc_low < detect_dc_high) + { + index = low; + high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + + } + else + { + index = high; + low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = low; + detect_dc_low = bk7011_get_tx_dc(); + } + } + while((high - low) > 1); + i_index = ((detect_dc_low < detect_dc_high) ? low : high); + + // Q DC calibration; + //Step 1 3~6 search; + if(gtx_dc_cal_mode == TX_DC_CAL) + { + low = UNSIGNEDOFFSET10 - MINOFFSET ; + high = UNSIGNEDOFFSET10 + MINOFFSET ; + } + else// (gtx_dc_cal_mode == TX_DC_LOOPBACK_CAL) + { + low = UNSIGNEDOFFSET10 - 3 * MINOFFSET ; + high = UNSIGNEDOFFSET10 + 3 * MINOFFSET ; + } + + //20170330 + + BK7011TRX.REG0xC->bits.enDCcaliGm1 = 0;//inverse 20141014 + + //20170330 + srchcnt = 0; + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = i_index; //default + + BK7011RCBEKEN.REG0x4F->bits.TXQDCCOMP = low; + detect_dc_low = bk7011_get_tx_dc(); + + + BK7011RCBEKEN.REG0x4F->bits.TXQDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + + + if(detect_dc_low < detect_dc_high) + { + + high = 511; + low = high - search_thrd; + } + else + { + low = 512; + high = low + search_thrd; + } + + BK7011RCBEKEN.REG0x4F->bits.TXQDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + BK7011RCBEKEN.REG0x4F->bits.TXQDCCOMP = low; + detect_dc_low = bk7011_get_tx_dc(); + + do + { + + if(detect_dc_low < detect_dc_high) + { + index = low; + high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x4F->bits.TXQDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + + } + else + { + index = high; + low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x4F->bits.TXQDCCOMP = low; + detect_dc_low = bk7011_get_tx_dc(); + } + srchcnt++; + if(srchcnt > gtx_dc_n) + break; + } + while((high - low) > 1); + + //Step 2 search; + + BK7011TRX.REG0xC->bits.enDCcaliGm1 = 1;//20170330 YIMING + + + BK7011RCBEKEN.REG0x4F->bits.TXQDCCOMP = low; + detect_dc_low = bk7011_get_tx_dc(); + BK7011RCBEKEN.REG0x4F->bits.TXQDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + do + { + + + + if(detect_dc_low < detect_dc_high) + { + index = low; + high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x4F->bits.TXQDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + + } + else + { + index = high; + low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x4F->bits.TXQDCCOMP = low; + detect_dc_low = bk7011_get_tx_dc(); + } + } + while((high - low) > 1); + + q_index = ((detect_dc_low < detect_dc_high) ? low : high); + + + + if(gtx_dc_cal_mode == TX_DC_CAL) + { + gtx_q_dc_comp = q_index; + CAL_WARN("gtx_q_dc_comp:0x%x\r\n", gtx_q_dc_comp); + } + else// (gtx_dc_cal_mode == TX_DC_LOOPBACK_CAL) + { + gtx_q_dc_comp_loopback = q_index; +#ifdef CALIBRATE_TIMES + if (p_gtx_q_dc_comp_temp_array != NULL) + { + p_gtx_q_dc_comp_temp_array[calibrate_time] = q_index; + } +#endif + } + gold_index += q_index; + + // 2nd I DC calibration; + //Step 1 3~6 search; + if(gtx_dc_cal_mode == TX_DC_CAL) + { + low = UNSIGNEDOFFSET10 - MINOFFSET ; + high = UNSIGNEDOFFSET10 + MINOFFSET ; + } + else// (gtx_dc_cal_mode == TX_DC_LOOPBACK_CAL) + { + low = UNSIGNEDOFFSET10 - 3 * MINOFFSET ; + high = UNSIGNEDOFFSET10 + 3 * MINOFFSET ; + } + //20170330 + + BK7011TRX.REG0xC->bits.enDCcaliGm1 = 0;//inverse 20141014 + + //20170330 + + + srchcnt = 0; + BK7011RCBEKEN.REG0x4F->bits.TXQDCCOMP = q_index; // optimum + + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = low; + detect_dc_low = bk7011_get_tx_dc(); + + + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + //low = 0; + //high = 1023; + + + + + + if(detect_dc_low < detect_dc_high) + { + + high = 511; + low = high - search_thrd; + } + else + { + low = 512; + high = low + search_thrd; + } + + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = low; + detect_dc_low = bk7011_get_tx_dc(); + + do + { + + + if(detect_dc_low < detect_dc_high) + { + index = low; + high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + } + else + { + index = high; + low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = low; + detect_dc_low = bk7011_get_tx_dc(); + } + srchcnt++; + if(srchcnt > gtx_dc_n) break; + } + while((high - low) > 1); + + //Step 2 search; + + BK7011TRX.REG0xC->bits.enDCcaliGm1 = 1;//20170330 YIMING + + + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = low; + detect_dc_low = bk7011_get_tx_dc(); + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + do + { + + if(detect_dc_low < detect_dc_high) + { + index = low; + high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = high; + detect_dc_high = bk7011_get_tx_dc(); + + } + else + { + index = high; + low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = low; + detect_dc_low = bk7011_get_tx_dc(); + } + } + while((high - low) > 1); + + + i_index = ((detect_dc_low < detect_dc_high) ? low : high); + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = i_index; + if(gtx_dc_cal_mode == TX_DC_CAL) + { + gtx_i_dc_comp = i_index; + CAL_WARN("gtx_i_dc_comp:0x%x\r\n", gtx_i_dc_comp); + } + else// (gtx_dc_cal_mode == TX_DC_LOOPBACK_CAL) + { + gtx_i_dc_comp_loopback = i_index; +#ifdef CALIBRATE_TIMES + if (p_gtx_i_dc_comp_temp_array != NULL) + { + p_gtx_i_dc_comp_temp_array[calibrate_time] = i_index; + } +#endif + } + + gold_index += (i_index << 16); + *val = gold_index; + (void)index; + return gold_index; +} + + +#define TSSI_RD_TIMES 8 +static INT32 bk7011_get_tx_i_gain(void) +{ + int i; + INT32 detector_i_gain_p, detector_i_gain_n, detector_i_gain; + + BK7011RCBEKEN.REG0x4C->bits.ICONSTANT = UNSIGNEDOFFSET10 + gconst_iqcal_p; + BK7011RCBEKEN.REG0x4C->bits.QCONSTANT = UNSIGNEDOFFSET10 + 0; + detector_i_gain_p = 0; + for (i = 0; i < TSSI_RD_TIMES; i++) + { + cal_delay(1 * gst_sar_adc); + detector_i_gain_p += BK7011RCBEKEN.REG0x54->bits.TSSIRD; + } + + BK7011RCBEKEN.REG0x4C->bits.ICONSTANT = UNSIGNEDOFFSET10 - gconst_iqcal_p; + BK7011RCBEKEN.REG0x4C->bits.QCONSTANT = UNSIGNEDOFFSET10 + 0; + detector_i_gain_n = 0; + for (i = 0; i < TSSI_RD_TIMES; i++) + { + cal_delay(1 * gst_sar_adc); + detector_i_gain_n += BK7011RCBEKEN.REG0x54->bits.TSSIRD; + } + + detector_i_gain = detector_i_gain_p + detector_i_gain_n; + return detector_i_gain; +} +static INT32 bk7011_get_tx_q_gain(void) +{ + int i; + INT32 detector_q_gain_p, detector_q_gain_n, detector_q_gain; + + BK7011RCBEKEN.REG0x4C->bits.ICONSTANT = UNSIGNEDOFFSET10 + 0; + BK7011RCBEKEN.REG0x4C->bits.QCONSTANT = UNSIGNEDOFFSET10 + gconst_iqcal_p; + detector_q_gain_p = 0; + for (i = 0; i < TSSI_RD_TIMES; i++) + { + cal_delay(1 * gst_sar_adc); + detector_q_gain_p += BK7011RCBEKEN.REG0x54->bits.TSSIRD; + } + + BK7011RCBEKEN.REG0x4C->bits.ICONSTANT = UNSIGNEDOFFSET10 + 0; + BK7011RCBEKEN.REG0x4C->bits.QCONSTANT = UNSIGNEDOFFSET10 - gconst_iqcal_p; + detector_q_gain_n = 0; + for (i = 0; i < TSSI_RD_TIMES; i++) + { + cal_delay(1 * gst_sar_adc); + detector_q_gain_n += BK7011RCBEKEN.REG0x54->bits.TSSIRD; + } + + detector_q_gain = detector_q_gain_p + detector_q_gain_n; + return detector_q_gain; +} +static INT32 bk7011_get_tx_i_phase(void) +{ + int i; + INT32 detector_i_phase_n, detector_i_phase_p, detector_i_phase; + + + BK7011RCBEKEN.REG0x4C->bits.ICONSTANT = UNSIGNEDOFFSET10 + gconst_iqcal_p; + BK7011RCBEKEN.REG0x4C->bits.QCONSTANT = UNSIGNEDOFFSET10 - gconst_iqcal_p; + detector_i_phase_p = 0; + for (i = 0; i < TSSI_RD_TIMES; i++) + { + cal_delay(1 * gst_sar_adc); + detector_i_phase_p += BK7011RCBEKEN.REG0x54->bits.TSSIRD; + } + + BK7011RCBEKEN.REG0x4C->bits.ICONSTANT = UNSIGNEDOFFSET10 - gconst_iqcal_p; + BK7011RCBEKEN.REG0x4C->bits.QCONSTANT = UNSIGNEDOFFSET10 + gconst_iqcal_p; + detector_i_phase_n = 0; + for (i = 0; i < TSSI_RD_TIMES; i++) + { + cal_delay(1 * gst_sar_adc); + detector_i_phase_n += BK7011RCBEKEN.REG0x54->bits.TSSIRD; + } + + detector_i_phase = detector_i_phase_p + detector_i_phase_n; + return detector_i_phase; +} +static INT32 bk7011_get_tx_q_phase(void) +{ + int i; + INT32 detector_q_phase_n, detector_q_phase_p, detector_q_phase; + + BK7011RCBEKEN.REG0x4C->bits.ICONSTANT = UNSIGNEDOFFSET10 + gconst_iqcal_p; + BK7011RCBEKEN.REG0x4C->bits.QCONSTANT = UNSIGNEDOFFSET10 + gconst_iqcal_p; + detector_q_phase_p = 0; + for (i = 0; i < TSSI_RD_TIMES; i++) + { + cal_delay(1 * gst_sar_adc); + detector_q_phase_p += BK7011RCBEKEN.REG0x54->bits.TSSIRD; + } + + BK7011RCBEKEN.REG0x4C->bits.ICONSTANT = UNSIGNEDOFFSET10 - gconst_iqcal_p; + BK7011RCBEKEN.REG0x4C->bits.QCONSTANT = UNSIGNEDOFFSET10 - gconst_iqcal_p; + detector_q_phase_n = 0; + for (i = 0; i < TSSI_RD_TIMES; i++) + { + cal_delay(1 * gst_sar_adc); + detector_q_phase_n += BK7011RCBEKEN.REG0x54->bits.TSSIRD; + } + + detector_q_phase = detector_q_phase_p + detector_q_phase_n; + return detector_q_phase; +} +static INT32 bk7011_get_rx_i_avg_signed(void) +{ + INT32 val; +#ifdef BK7011_VER_A + val = BK7011RCBEKEN.REG0x3C->bits.RXAVGIRD; +#else + val = BK7011RCBEKEN.REG0x3C->bits.RXAVGIRD; +#endif + + if(val & 0x00000800) + { + val |= 0xfffff000; + } + + return abs(val); +} +/* +static INT32 bk7011_get_rx_q_avg_signed(void) +{ + INT32 val; + +#ifdef BK7011_VER_A + val = BK7011RCBEKEN.REG0x3C->bits.RXAVGQRD; +#else + val = BK7011RCBEKEN.REG0x3C->bits.RXAVGQRD; +#endif + + if(val & 0x00000800) + { + val |= 0xfffff000; + } + return abs(val); +} +*/ +INT32 bk7011_cal_tx_gain_imbalance(INT32 *val) +{ + INT32 detect_gain_low = 0; + INT32 detect_gain_high = 0; + INT16 high, low; + INT32 index = 0, gold_index = 0; + INT32 detector_i_gain; + INT32 detector_q_gain; + if(gtx_gain_imb_cal_mode == TX_GAIN_IMB_CAL) + { + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = gtx_i_dc_comp; + BK7011RCBEKEN.REG0x4F->bits.TXQDCCOMP = gtx_q_dc_comp; + BK7011TRX.REG0xD->value = TRX_REG_0XD_TX_IQ_VAL;//BK7011TRXREG0xD;//0214 close the TX switch to ellimite the antenna infect + CAL_WR_TRXREGS(0xD); + } + else + { + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = gtx_i_dc_comp_loopback; + BK7011RCBEKEN.REG0x4F->bits.TXQDCCOMP = gtx_q_dc_comp_loopback; + BK7011TRX.REG0xD->value = TRX_REG_0XD_TX_LOOPBACK_IQ_VAL; + CAL_WR_TRXREGS(0xD); + + } + + BK7011RCBEKEN.REG0x50->bits.TXIGAINCOMP = 1023; + BK7011RCBEKEN.REG0x50->bits.TXQGAINCOMP = 1023; + BK7011RCBEKEN.REG0x4C->bits.TESTPATTERN = 1; + + +#ifdef CALIBRATE_TIMES + if(gtx_gain_imb_cal_mode == TX_GAIN_IMB_CAL) + { + bk7011_set_tx_pa(gi_gain_tx_pa_dgainPA20, gi_gain_tx_pa_dgainbuf20, 5, 8); + } + else + { + bk7011_set_tx_pa(gi_gain_tx_loopback_pa_dgainPA20, gi_gain_tx_loopback_pa_dgainbuf20, 5, 8); + } + if (p_gbias_after_cal_array == NULL) + { + if(gtx_gain_imb_cal_mode == TX_GAIN_IMB_CAL) + { + CAL_TIM_PRT("\r\nbk7011_cal_tx_gain_imbalance\r\n"); + } + else + { + CAL_TIM_PRT("\r\nbk7011_cal_tx_loopback_gain_imbalance\r\n"); + } + + CAL_TIM_PRT("dgainPA20 = %d\r\n", BK7011TRX.REG0xC->bits.dgainPA20 ); + CAL_TIM_PRT("dgainbuf20 =%d\r\n", BK7011TRX.REG0xC->bits.dgainbuf20); + CAL_TIM_PRT("gctrlpga20 = %d\r\n", BK7011TRX.REG0xC->bits.gctrlpga20 ); + CAL_TIM_PRT("gctrlmod30 = %d\r\n", BK7011TRX.REG0xB->bits.gctrlmod30); + } +#else + if(gtx_gain_imb_cal_mode == TX_GAIN_IMB_CAL) + { + bk7011_set_tx_pa(gi_gain_tx_pa_dgainPA20, gi_gain_tx_pa_dgainbuf20, 5, 8); + } + else + { + bk7011_set_tx_pa(gi_gain_tx_loopback_pa_dgainPA20, gi_gain_tx_loopback_pa_dgainbuf20, 5, 8); + } +#endif + + + BK7011TRX.REG0xC->bits.TSSIsel = 0; + BK7011TRX.REG0xC->bits.enDCcali = 1; + BK7011TRX.REG0xC->bits.enDCcaliGm1 = 0; + BK7011TRX.REG0xC->bits.enIQcali = 1; + BK7011TRX.REG0xC->bits.enPcali = 0; + BK7011TRX.REG0xC->bits.enPcaliGm = 0; + BK7011TRX.REG0xF->bits.tssicalen = 1; + CAL_WR_TRXREGS(0xC); + CAL_WR_TRXREGS(0xB); + CAL_WR_TRXREGS(0xF); + + if(gtx_gain_imb_cal_mode == TX_GAIN_IMB_CAL) + { + gtx_i_gain_comp = BK7011RCBEKEN.REG0x50->bits.TXIGAINCOMP; + gtx_q_gain_comp = BK7011RCBEKEN.REG0x50->bits.TXQGAINCOMP; + } + else + { + gtx_i_gain_comp_loopback = BK7011RCBEKEN.REG0x50->bits.TXIGAINCOMP; + gtx_q_gain_comp_loopback = BK7011RCBEKEN.REG0x50->bits.TXQGAINCOMP; + } + + cpu_delay(500); + detector_i_gain = bk7011_get_tx_i_gain(); + detector_q_gain = bk7011_get_tx_q_gain(); + + if(abs(detector_q_gain - detector_i_gain) < 3) + { + *val = 0; + if(gtx_gain_imb_cal_mode == TX_GAIN_IMB_CAL) + { + gtx_i_gain_comp = BK7011RCBEKEN.REG0x50->bits.TXIGAINCOMP; + gtx_q_gain_comp = BK7011RCBEKEN.REG0x50->bits.TXQGAINCOMP; + } + else + { + gtx_i_gain_comp_loopback = BK7011RCBEKEN.REG0x50->bits.TXIGAINCOMP; + gtx_q_gain_comp_loopback = BK7011RCBEKEN.REG0x50->bits.TXQGAINCOMP; + } + + return (BK7011RCBEKEN.REG0x50->bits.TXQGAINCOMP + (BK7011RCBEKEN.REG0x50->bits.TXIGAINCOMP << 16)); + } + + if(detector_i_gain > detector_q_gain) // TX_Q_GAIN_COMP NOT CHANGED + { + BK7011RCBEKEN.REG0x50->bits.TXQGAINCOMP = 1023; + low = 0; + BK7011RCBEKEN.REG0x50->bits.TXIGAINCOMP = low; + detector_i_gain = bk7011_get_tx_i_gain(); + detector_q_gain = bk7011_get_tx_q_gain(); + + detect_gain_low = abs(detector_i_gain - detector_q_gain); + + high = 1023; + BK7011RCBEKEN.REG0x50->bits.TXIGAINCOMP = high; + detector_i_gain = bk7011_get_tx_i_gain(); + detector_q_gain = bk7011_get_tx_q_gain(); + + detect_gain_high = abs(detector_i_gain - detector_q_gain); + do + { + if(detect_gain_low < detect_gain_high) + { + index = low; + high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x50->bits.TXIGAINCOMP = high; + detector_i_gain = bk7011_get_tx_i_gain(); + detector_q_gain = bk7011_get_tx_q_gain(); + detect_gain_high = abs(detector_i_gain - detector_q_gain); + } + else + { + index = high; + low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x50->bits.TXIGAINCOMP = low; + detector_i_gain = bk7011_get_tx_i_gain(); + detector_q_gain = bk7011_get_tx_q_gain(); + detect_gain_low = abs(detector_i_gain - detector_q_gain); + } + + } + while((high - low) > 1); + index = ((detect_gain_low < detect_gain_high) ? low : high); + BK7011RCBEKEN.REG0x50->bits.TXIGAINCOMP = index; + + if(gtx_gain_imb_cal_mode == TX_GAIN_IMB_CAL) + { + gtx_i_gain_comp = index; + } + else + { + gtx_i_gain_comp_loopback = index; + } + gold_index = (index << 16) + 1023; + } + else //// TX_I_GAIN_COMP NOT CHANGED + { + BK7011RCBEKEN.REG0x50->bits.TXIGAINCOMP = 1023; + low = 0; + BK7011RCBEKEN.REG0x50->bits.TXQGAINCOMP = low; + detector_i_gain = bk7011_get_tx_i_gain(); + detector_q_gain = bk7011_get_tx_q_gain(); + + detect_gain_low = abs(detector_i_gain - detector_q_gain); + + high = 1023; + BK7011RCBEKEN.REG0x50->bits.TXQGAINCOMP = high; + detector_i_gain = bk7011_get_tx_i_gain(); + detector_q_gain = bk7011_get_tx_q_gain(); + + detect_gain_high = abs(detector_i_gain - detector_q_gain); + do + { + if(detect_gain_low < detect_gain_high) + { + index = low; + high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x50->bits.TXQGAINCOMP = high; + detector_i_gain = bk7011_get_tx_i_gain(); + detector_q_gain = bk7011_get_tx_q_gain(); + detect_gain_high = abs(detector_i_gain - detector_q_gain); + } + else + { + index = high; + low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x50->bits.TXQGAINCOMP = low; + detector_i_gain = bk7011_get_tx_i_gain(); + detector_q_gain = bk7011_get_tx_q_gain(); + detect_gain_low = abs(detector_i_gain - detector_q_gain); + } + + } + while((high - low) > 1); + index = ((detect_gain_low < detect_gain_high) ? low : high); + BK7011RCBEKEN.REG0x50->bits.TXQGAINCOMP = index; + if(gtx_gain_imb_cal_mode == TX_GAIN_IMB_CAL) + { + gtx_q_gain_comp = index; + } + else + { + gtx_q_gain_comp_loopback = index; + } + gold_index += (1023 << 16) + index; + } + + *val = gold_index; + if(gtx_gain_imb_cal_mode == TX_GAIN_IMB_CAL) + { + CAL_WARN("gtx_i_gain_comp:%d\r\n", gtx_i_gain_comp); + CAL_WARN("gtx_q_gain_comp:%d\r\n", gtx_q_gain_comp); + } + + return gold_index; +} + + +static INT32 bk7011_cal_tx_ty2(INT32 tx_phase_comp) +{ + float ty1, ty1_sqr, ty2; + INT32 tx_ty2; + + ty1 = -1.0 * ((tx_phase_comp - 512) * (tx_phase_comp - 512)) / (1024.0 * 1024.0); + ty1_sqr = ty1 * ty1; + ty2 = 1 - ty1 / 2 + 3 * ty1_sqr / 8; + tx_ty2 = (INT32)((ty2 - 0.5) * 1024 + 0.5); + + return tx_ty2; +} + +INT32 bk7011_cal_tx_phase_imbalance(INT32 *val) +{ + INT32 detect_phase_low = 0; + INT32 detect_phase_high = 0; + INT16 high, low; + INT32 index = 0, gold_index = 0; + INT32 detector_i_phase; + INT32 detector_q_phase; + + if(gtx_phase_imb_cal_mode == TX_PHASE_IMB_CAL) + { + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = gtx_i_dc_comp; + BK7011RCBEKEN.REG0x4F->bits.TXQDCCOMP = gtx_q_dc_comp; + BK7011RCBEKEN.REG0x50->bits.TXIGAINCOMP = gtx_i_gain_comp; + BK7011RCBEKEN.REG0x50->bits.TXQGAINCOMP = gtx_q_gain_comp; + BK7011TRX.REG0xD->value = TRX_REG_0XD_TX_IQ_VAL;//BK7011TRXREG0xD;//0214 close the TX switch to ellimite the antenna infect + CAL_WR_TRXREGS(0xD); + } + else + { + BK7011RCBEKEN.REG0x4F->bits.TXIDCCOMP = gtx_i_dc_comp_loopback; + BK7011RCBEKEN.REG0x4F->bits.TXQDCCOMP = gtx_q_dc_comp_loopback; + BK7011RCBEKEN.REG0x50->bits.TXIGAINCOMP = gtx_i_gain_comp_loopback; + BK7011RCBEKEN.REG0x50->bits.TXQGAINCOMP = gtx_q_gain_comp_loopback; + BK7011TRX.REG0xD->value = TRX_REG_0XD_TX_LOOPBACK_IQ_VAL; + CAL_WR_TRXREGS(0xD); + + } + + BK7011RCBEKEN.REG0x51->bits.TXPHASECOMP = 512; + BK7011RCBEKEN.REG0x51->bits.TXTY2 = 512; + BK7011RCBEKEN.REG0x4C->bits.TESTPATTERN = 1; + +#ifdef CALIBRATE_TIMES + if(gtx_phase_imb_cal_mode == TX_PHASE_IMB_CAL) + { + bk7011_set_tx_pa(gi_gain_tx_pa_dgainPA20, gi_gain_tx_pa_dgainbuf20, 5, 8); + } + else + { + bk7011_set_tx_pa(gi_phase_tx_loopback_pa_dgainPA20, gi_phase_tx_loopback_pa_dgainbuf20, 5, 8); + + } + + if (p_gbias_after_cal_array == NULL) + { + if(gtx_phase_imb_cal_mode == TX_PHASE_IMB_CAL) + { + CAL_TIM_PRT("\r\nbk7011_cal_tx_phase_imbalance: \r\n"); + } + else + { + CAL_TIM_PRT("\r\nbk7011_cal_tx_loopback_phase_imbalance: \r\n"); + + } + + CAL_TIM_PRT("dgainPA20 = %d\r\n", BK7011TRX.REG0xC->bits.dgainPA20 ); + CAL_TIM_PRT("dgainbuf20 =%d\r\n", BK7011TRX.REG0xC->bits.dgainbuf20); + CAL_TIM_PRT("gctrlpga20 = %d\r\n", BK7011TRX.REG0xC->bits.gctrlpga20 ); + CAL_TIM_PRT("gctrlmod30 = %d\r\n", BK7011TRX.REG0xB->bits.gctrlmod30); + } +#else + if(gtx_phase_imb_cal_mode == TX_PHASE_IMB_CAL) + { + bk7011_set_tx_pa(gi_gain_tx_pa_dgainPA20, gi_gain_tx_pa_dgainbuf20, 5, 8); + } + else + { + bk7011_set_tx_pa(gi_phase_tx_loopback_pa_dgainPA20, gi_phase_tx_loopback_pa_dgainbuf20, 5, 8); + } +#endif + + + BK7011TRX.REG0xC->bits.TSSIsel = 0; + BK7011TRX.REG0xC->bits.enDCcali = 1; + BK7011TRX.REG0xC->bits.enDCcaliGm1 = 0; + BK7011TRX.REG0xC->bits.enIQcali = 1; + BK7011TRX.REG0xC->bits.enPcali = 0; + BK7011TRX.REG0xC->bits.enPcaliGm = 0; + BK7011TRX.REG0xF->bits.tssicalen = 1; + + CAL_WR_TRXREGS(0xC); + CAL_WR_TRXREGS(0xB); + CAL_WR_TRXREGS(0xF); + + low = bk7011_cal_tx_ty2(512); + low = 1; + BK7011RCBEKEN.REG0x51->bits.TXPHASECOMP = low; + BK7011RCBEKEN.REG0x51->bits.TXTY2 = bk7011_cal_tx_ty2( low); + detector_i_phase = bk7011_get_tx_i_phase(); + detector_q_phase = bk7011_get_tx_q_phase(); + detect_phase_low = abs(detector_i_phase - detector_q_phase); + + high = 1023; + BK7011RCBEKEN.REG0x51->bits.TXPHASECOMP = high; + BK7011RCBEKEN.REG0x51->bits.TXTY2 = bk7011_cal_tx_ty2( high); + detector_i_phase = bk7011_get_tx_i_phase(); + detector_q_phase = bk7011_get_tx_q_phase(); + detect_phase_high = abs(detector_i_phase - detector_q_phase); + + do + { + if(detect_phase_low < detect_phase_high) + { + index = low; + high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x51->bits.TXPHASECOMP = high; + BK7011RCBEKEN.REG0x51->bits.TXTY2 = bk7011_cal_tx_ty2( high); + detector_i_phase = bk7011_get_tx_i_phase(); + detector_q_phase = bk7011_get_tx_q_phase(); + detect_phase_high = abs(detector_i_phase - detector_q_phase); + } + else + { + index = high; + low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011RCBEKEN.REG0x51->bits.TXPHASECOMP = low; + BK7011RCBEKEN.REG0x51->bits.TXTY2 = bk7011_cal_tx_ty2( low); + detector_i_phase = bk7011_get_tx_i_phase(); + detector_q_phase = bk7011_get_tx_q_phase(); + detect_phase_low = abs(detector_i_phase - detector_q_phase); + } + } + while((high - low) > 1); + index = ((detect_phase_low < detect_phase_high) ? low : high); + BK7011RCBEKEN.REG0x51->bits.TXPHASECOMP = index; + + if(gtx_phase_imb_cal_mode == TX_PHASE_IMB_CAL) + { + gtx_phase_comp = BK7011RCBEKEN.REG0x51->bits.TXPHASECOMP; + gtx_phase_ty2 = BK7011RCBEKEN.REG0x51->bits.TXTY2; + + CAL_WARN("gtx_phase_comp:%d\r\n", gtx_phase_comp); + CAL_WARN("gtx_phase_ty2:%d\r\n", gtx_phase_ty2); + } + else + { + gtx_phase_comp_loopback = BK7011RCBEKEN.REG0x51->bits.TXPHASECOMP; + gtx_phase_ty2_loopback = BK7011RCBEKEN.REG0x51->bits.TXTY2; + +#ifdef CALIBRATE_TIMES + if (p_gtx_phase_comp_temp_array != NULL) + { + p_gtx_phase_comp_temp_array[calibrate_time] = gtx_phase_comp_loopback; + } +#endif + + CAL_WARN("tx_phase_comp:%d\r\n", gtx_phase_comp_loopback); + CAL_WARN("tx_phase_ty2:%d\r\n", gtx_phase_ty2_loopback); + + } + + gold_index = index; + return gold_index; +} + + +static float bk7011_get_tx_filter_i_ratio(void) +{ + INT32 rx_avg_i_14M, rx_avg_i_500K; + float rx_avg_ratio; + BK7011RCBEKEN.REG0x4D->bits.TXSINF = 358; // 14MHz; + cal_delay_100us(gst_rx_adc); + rx_avg_i_14M = bk7011_get_rx_i_avg_signed(); + BK7011RCBEKEN.REG0x4D->bits.TXSINF = 13; // 500KHz; + cal_delay_100us(gst_rx_adc); + rx_avg_i_500K = bk7011_get_rx_i_avg_signed(); + if(rx_avg_i_14M > 0) + { + rx_avg_ratio = abs(1.0 * rx_avg_i_500K / rx_avg_i_14M - 1.414); + return rx_avg_ratio; + } + else + { + return -1.0; + } +} + +INT32 bk7011_cal_tx_filter_corner(INT32 *val) +{ + + float tx_avg_ratio_low = 0.0; + float tx_avg_ratio_high = 0.0; + INT16 high, low; + INT32 index = 0, gold_index = 0; + + BK7011RCBEKEN.REG0x1C->bits.FRXON = 1; + // I CAL + BK7011TRX.REG0x6->bits.lpfcapcali50 = 0x20; + BK7011TRX.REG0xD->value = 0xFC4E03B9;//BK7011TRXREG0xD;//0xE00F02B9;//0xFC4E03B9;// + CAL_WR_TRXREGS(0x6); + CAL_WR_TRXREGS(0xD); + + //12/10/2014 for D version + BK7011TRX.REG0xF->bits.tssicalen = 0; + BK7011TRX.REG0xF->bits.sinadrxen = 0; + CAL_WR_TRXREGS(0xF); + + + BK7011RCBEKEN.REG0x4C->bits.TESTPATTERN = 2; + BK7011RCBEKEN.REG0x4D->bits.TXSINMODE = 1; + BK7011RCBEKEN.REG0x4D->bits.TXSINAMP = 4; + BK7011RCBEKEN.REG0x3C->bits.RXDCCALEN = 1; + BK7011RCBEKEN.REG0x3C->bits.RXAVGMODE = 1; + + + //cpu_delay(gst_rx_adc); + + low = 0; + BK7011TRX.REG0x6->bits.lpfcapcali50 = low; + CAL_WR_TRXREGS(0x6); + + tx_avg_ratio_low = bk7011_get_tx_filter_i_ratio(); + + high = 63; + BK7011TRX.REG0x6->bits.lpfcapcali50 = high; + CAL_WR_TRXREGS(0x6); + + tx_avg_ratio_high = bk7011_get_tx_filter_i_ratio(); + + do + { + if(tx_avg_ratio_low < tx_avg_ratio_high) + { + index = low; + high = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011TRX.REG0x6->bits.lpfcapcali50 = high; + CAL_WR_TRXREGS(0x6); + tx_avg_ratio_high = bk7011_get_tx_filter_i_ratio(); + } + else + { + index = high; + low = ((low + high) >> 1) + (((low + high) & 0x01) ? 1 : 0); + BK7011TRX.REG0x6->bits.lpfcapcali50 = low; + CAL_WR_TRXREGS(0x6); + tx_avg_ratio_low = bk7011_get_tx_filter_i_ratio(); + } + } + while((high - low) > 1); + index = ((tx_avg_ratio_low < tx_avg_ratio_high) ? low : high); + gold_index = index << 8; + gtx_ifilter_corner = index; + // Q CAL + + BK7011TRX.REG0x6->bits.lpfcapcali50 = gtx_ifilter_corner; + BK7011TRX.REG0x6->bits.lpfcapcalq50 = gtx_ifilter_corner;//160405 iq used same value + gtx_qfilter_corner = gtx_ifilter_corner; + CAL_WARN("gtx_ifilter_corner over: 0x%x\r\n", gtx_ifilter_corner); + CAL_WARN("gtx_qfilter_corner over: 0x%x\r\n", gtx_qfilter_corner); + + CAL_WR_TRXREGS(0x6); + + *val = gold_index; + return (gold_index); +} + +void bk7011_rx_cal_en(void) +{ + BK7011RCBEKEN.REG0x3E->bits.RXCOMPEN = 0; + + BK7011RCBEKEN.REG0x1C->bits.FRXON = 1; + BK7011RCBEKEN.REG0x1C->bits.FTXON = 0; + + BK7011RCBEKEN.REG0x0->bits.forceenable = 1; + cpu_delay(1); + BK7011RCBEKEN.REG0x19->bits.FCH0SHDN = 1; + BK7011RCBEKEN.REG0x19->bits.FCH0TXEN = 0; + BK7011RCBEKEN.REG0x19->bits.FCH0RXEN = 1; + BK7011RCBEKEN.REG0x19->bits.FCH0EN = 1; + + // ADC clock change to 80M + BK7011TRX.REG0xF->bits.clkadcsel = 0;//20170331 1 --> 0 + CAL_WR_TRXREGS(0xF); + + BK7011TRX.REG0x12->bits.adcrefbwsel = 0;//20170331 1-->0 + CAL_WR_TRXREGS(0x12); +} + +INT32 bk7011_cal_rx_dc(void) +{ + INT32 index = 0; + INT32 i, j, k, t, curr, value; + + + /*step 2*/ + BK7011RCBEKEN.REG0x3C->bits.RXDCCALEN = 1; + BK7011RCBEKEN.REG0x3C->bits.RXAVGMODE = 0; + BK7011RCBEKEN.REG0x19->bits.FCH0RXHP = 0; //huaming.jiang 20141017 + BK7011RCBEKEN.REG0x1C->bits.FTXON = 0; + BK7011RCBEKEN.REG0x1C->bits.FRXON = 1; + + BK7011TRX.REG0x7->bits.chin60 = 0x64; + CAL_WR_TRXREGS(0x7); + delay100us(1);//delay 100us for RFPLL + + BK7011TRX.REG0xE->value = 0xDA01BCF0; /// D801BCF0;//170217 + CAL_WR_TRXREGS(0xE); + + for(i = 0; i < 16; i ++) + { + BK7011RCBEKEN.REG0x19->bits.FCH0B = (0x70 | i); + for(j = 0; j < 2; j ++) + { + index = 128; + k = 6; + do + { + //set dc offset + value = (*((volatile unsigned long *)(TRX_BEKEN_BASE + (0x14 + i / 2) * 4))); + curr = ~(0xff << (16 * (i % 2) + 8 * j)); + value &= curr; + curr = (index << (16 * (i % 2) + 8 * j)); + value |= curr; + (*((volatile unsigned long *)(TRX_BEKEN_BASE + (0x14 + i / 2) * 4))) = value; + while(BK7011RCBEKEN.REG0x1->value & 0xfffffff); + cal_delay_100us(gst_rx_adc); + + //read dc avg, and calc mean + value = 0; + for(t = 0; t < 10; t ++) + { + if(j == 0) curr = BK7011RCBEKEN.REG0x3C->bits.RXAVGIRD; + else curr = BK7011RCBEKEN.REG0x3C->bits.RXAVGQRD; + if(curr >= 2048) curr -= 4096; + value += curr; + cpu_delay(100); + } + curr = value / 10; + + //calc new dc offset + if(curr > 0) index += (0x1 << k); + else index -= (0x1 << k); + k --; + } + while((k >= 0) && ((curr >= 16) || (curr <= -16))); + if(k < 0) + { + value = (*((volatile unsigned long *)(TRX_BEKEN_BASE + (0x14 + i / 2) * 4))); + curr = ~(0xff << (16 * (i % 2) + 8 * j)); + value &= curr; + curr = (index << (16 * (i % 2) + 8 * j)); + value |= curr; + (*((volatile unsigned long *)(TRX_BEKEN_BASE + (0x14 + i / 2) * 4))) = value; + while(BK7011RCBEKEN.REG0x1->value & 0xfffffff); + } + } + } + + g_rx_dc_gain_tab[0] = BK7011TRXONLY.REG0x14->value; + g_rx_dc_gain_tab[1] = BK7011TRXONLY.REG0x15->value; + g_rx_dc_gain_tab[2] = BK7011TRXONLY.REG0x16->value; + g_rx_dc_gain_tab[3] = BK7011TRXONLY.REG0x17->value; + g_rx_dc_gain_tab[4] = BK7011TRXONLY.REG0x18->value; + g_rx_dc_gain_tab[5] = BK7011TRXONLY.REG0x19->value; + g_rx_dc_gain_tab[6] = BK7011TRXONLY.REG0x1A->value; + g_rx_dc_gain_tab[7] = BK7011TRXONLY.REG0x1B->value; + CAL_WARN("g_rx_dc_gain_tab 0 over: 0x%x\r\n", g_rx_dc_gain_tab[0]); + CAL_WARN("g_rx_dc_gain_tab 1 over: 0x%x\r\n", g_rx_dc_gain_tab[1]); + CAL_WARN("g_rx_dc_gain_tab 2 over: 0x%x\r\n", g_rx_dc_gain_tab[2]); + CAL_WARN("g_rx_dc_gain_tab 3 over: 0x%x\r\n", g_rx_dc_gain_tab[3]); + CAL_WARN("g_rx_dc_gain_tab 4 over: 0x%x\r\n", g_rx_dc_gain_tab[4]); + CAL_WARN("g_rx_dc_gain_tab 5 over: 0x%x\r\n", g_rx_dc_gain_tab[5]); + CAL_WARN("g_rx_dc_gain_tab 6 over: 0x%x\r\n", g_rx_dc_gain_tab[6]); + CAL_WARN("g_rx_dc_gain_tab 7 over: 0x%x\r\n", g_rx_dc_gain_tab[7]); + + BK7011RCBEKEN.REG0x3C->bits.RXDCCALEN = 0; + + BK7011TRX.REG0x7->bits.chin60 = 0xc; + CAL_WR_TRXREGS(0x7); + delay100us(1);//delay 100us for RFPLL + + return 0; +} + +INT32 bk7011_cal_rx_iq(INT32 *val) +{ + INT32 rx_amp_err_rd, rx_phase_err_rd, rx_ty2_rd; + INT32 rx_amp_err_wr; + INT32 rx_phase_err_wr; + float amp_err, phase_err, ty2_err; + INT32 gold_index = 0; + INT32 i, curr, value, value1, value2; + + /*step 1*/ + BK7011RCBEKEN.REG0x1C->bits.FRXON = 1; + BK7011RCBEKEN.REG0x1C->bits.FTXON = 1; + + BK7011TRX.REG0xF->bits.tssicalen = 0; + BK7011TRX.REG0xF->bits.sinadrxen = 0; + CAL_WR_TRXREGS(0xF); + + BK7011TRX.REG0xE->value = TRX_REG_0XE_RXIQ_VAL; + CAL_WR_TRXREGS(0xE); + bk7011_set_tx_pa(gi_cal_rx_iq_pa_dgainPA20, gi_cal_rx_iq_pa_dgainbuf20, 4, 4); + + BK7011RCBEKEN.REG0x19->bits.FCH0B = 0x1a;//decrease 6dB + + /*searching...*/ + BK7011RCBEKEN.REG0x3E->bits.RXCALEN = 1; + BK7011RCBEKEN.REG0x4C->bits.TESTPATTERN = 2; + BK7011RCBEKEN.REG0x4D->bits.TXSINMODE = 0; + BK7011RCBEKEN.REG0x4D->bits.TXSINAMP = 0x04; // increase 6dB + BK7011RCBEKEN.REG0x4D->bits.TXSINF = 179; // 7MHz; + cal_delay_100us(6 * gst_rx_adc); + cpu_delay(500 * DELAY1US); + + BK7011RCBEKEN.REG0x41->bits.RXDCIWR = 0x0; + BK7011RCBEKEN.REG0x41->bits.RXDCQWR = 0x0; + + value = 0; + value1 = 0; + value2 = 0; + for(i = 0; i < 2; i ++) + { + curr = BK7011RCBEKEN.REG0x3F->bits.RXAMPERRRD; + value += curr - ((curr < 512) ? 0 : 1024); + curr = BK7011RCBEKEN.REG0x3F->bits.RXPHASEERRRD; + value1 += curr - ((curr < 512) ? 0 : 1024); + curr = BK7011RCBEKEN.REG0x40->bits.RXTY2RD; + value2 += curr - ((curr < 512) ? 0 : 1024); + cpu_delay(gst_rx_adc); + } + rx_amp_err_rd = value / 2; + rx_phase_err_rd = value1 / 2; + rx_ty2_rd = value2 / 2; + +#ifdef CALIBRATE_TIMES // by gwf + if (p_rx_amp_err_rd_array != NULL) + { + int rx_amp_err_rd_temp; + int rx_phase_err_rd_temp; + int rx_ty2_rd_temp; + if (rx_amp_err_rd & 0x200) + { + rx_amp_err_rd_temp = rx_amp_err_rd | 0xFFFFFC00; + } + else + { + rx_amp_err_rd_temp = rx_amp_err_rd & 0x000003FF; + } + if (rx_phase_err_rd & 0x200) + { + rx_phase_err_rd_temp = rx_phase_err_rd | 0xFFFFFC00; + } + else + { + rx_phase_err_rd_temp = rx_phase_err_rd & 0x000003FF; + } + if (rx_ty2_rd & 0x200) + { + rx_ty2_rd_temp = rx_ty2_rd | 0xFFFFFC00; + } + else + { + rx_ty2_rd_temp = rx_ty2_rd & 0x000003FF; + } + p_rx_amp_err_rd_array[calibrate_time] = rx_amp_err_rd_temp; + p_rx_phase_err_rd_array[calibrate_time] = rx_phase_err_rd_temp; + p_rx_ty2_rd_array[calibrate_time] = rx_ty2_rd_temp; + } + else +#endif + { + CAL_FATAL("[rx_iq]rx_amp_err_rd: 0x%03x\r\n", rx_amp_err_rd ); + CAL_FATAL("[rx_iq]rx_phase_err_rd: 0x%03x\r\n", rx_phase_err_rd ); + CAL_FATAL("[rx_iq]rx_ty2_rd: 0x%03x\r\n", rx_ty2_rd ); + } + + amp_err = 1.0 * rx_amp_err_rd / 1024; + phase_err = 1.0 * rx_phase_err_rd / 1024; + ty2_err = 1.0 * rx_ty2_rd / 1024; + + rx_amp_err_wr = (INT32) (512 * (ty2_err + 1) / (amp_err + 1)); + rx_phase_err_wr = (INT32) (512 * phase_err * (ty2_err + 1)); + + BK7011RCBEKEN.REG0x42->bits.RXPHASEERRWR = rx_phase_err_wr; + BK7011RCBEKEN.REG0x42->bits.RXAMPERRWR = rx_amp_err_wr; + BK7011RCBEKEN.REG0x3E->bits.RXCOMPEN = 1; + BK7011RCBEKEN.REG0x3E->bits.RXCALEN = 0; + + grx_amp_err_wr = rx_amp_err_wr; + grx_phase_err_wr = rx_phase_err_wr; + + CAL_WARN("grx_amp_err_wr:0x%03x\r\n", grx_amp_err_wr); + CAL_WARN("grx_phase_err_wr:0x%03x\r\n", grx_phase_err_wr); + + gold_index = (rx_amp_err_wr << 16 ) + rx_phase_err_wr; + *val = gold_index; + + BK7011TRX.REG0x9->bits.agcrxfeEn = 1; //enable agc + BK7011TRX.REG0x7->bits.autorxifgen = 1;//ensable agc + CAL_WR_TRXREGS(0x7); + CAL_WR_TRXREGS(0x9); + + return gold_index; +} + +void bk7011_set_rx_avg_dc(void) +{ + INT32 rx_dc_i_rd, rx_dc_q_rd; + + BK7011RCBEKEN.REG0x3E->bits.RXCOMPEN = 0; + BK7011RCBEKEN.REG0x3C->bits.RXAVGMODE = 0; + BK7011RCBEKEN.REG0x3C->bits.RXDCCALEN = 1; + cal_delay_100us(gst_rx_adc); + BK7011RCBEKEN.REG0x3C->bits.RXDCCALEN = 0; + + rx_dc_i_rd = BK7011RCBEKEN.REG0x3C->bits.RXAVGIRD; + rx_dc_q_rd = BK7011RCBEKEN.REG0x3C->bits.RXAVGQRD; + BK7011RCBEKEN.REG0x41->bits.RXDCIWR = rx_dc_i_rd; + BK7011RCBEKEN.REG0x41->bits.RXDCQWR = rx_dc_q_rd; + + BK7011RCBEKEN.REG0x3E->bits.RXCOMPEN = 1; + + return; +} + +INT32 bk7011_load_calibration_cfg(void) +{ + BK7011RCBEKEN.REG0x0->value = BK7011RCBEKEN.REG0x0->value; + BK7011RCBEKEN.REG0x1->value = BK7011RCBEKEN.REG0x1->value; + BK7011RCBEKEN.REG0x5->value = BK7011RCBEKEN.REG0x5->value ; + BK7011RCBEKEN.REG0x8->value = BK7011RCBEKEN.REG0x8->value; + BK7011RCBEKEN.REG0xB->value = BK7011RCBEKEN.REG0xB->value; + BK7011RCBEKEN.REG0x11->value = BK7011RCBEKEN.REG0x11->value; + BK7011RCBEKEN.REG0x19->value = BK7011RCBEKEN.REG0x19->value; + BK7011RCBEKEN.REG0x1E->value = BK7011RCBEKEN.REG0x1E->value; + + /**********NEW ADDED************/ + BK7011RCBEKEN.REG0x3C->value = BK7011RCBEKEN.REG0x3C->value; + BK7011RCBEKEN.REG0x3E->value = BK7011RCBEKEN.REG0x3E->value; + BK7011RCBEKEN.REG0x3F->value = BK7011RCBEKEN.REG0x3F->value; + BK7011RCBEKEN.REG0x40->value = BK7011RCBEKEN.REG0x40->value; + BK7011RCBEKEN.REG0x41->value = BK7011RCBEKEN.REG0x41->value; + BK7011RCBEKEN.REG0x42->value = BK7011RCBEKEN.REG0x42->value ; + BK7011RCBEKEN.REG0x4C->value = BK7011RCBEKEN.REG0x4C->value; + BK7011RCBEKEN.REG0x4D->value = BK7011RCBEKEN.REG0x4D->value; + BK7011RCBEKEN.REG0x4F->value = BK7011RCBEKEN.REG0x4F->value; + BK7011RCBEKEN.REG0x50->value = BK7011RCBEKEN.REG0x50->value; + BK7011RCBEKEN.REG0x51->value = BK7011RCBEKEN.REG0x51->value; + BK7011RCBEKEN.REG0x52->value = BK7011RCBEKEN.REG0x52->value; + BK7011RCBEKEN.REG0x54->value = BK7011RCBEKEN.REG0x54->value; + BK7011RCBEKEN.REG0x5C->value = BK7011RCBEKEN.REG0x5C->value; + + while(BK7011RCBEKEN.REG0x1->value & 0x0FFFFFFF) + { + cpu_delay(1); + } + BK7011TRXONLY.REG0x0->value = grc_reg_map[0]; + BK7011TRXONLY.REG0x1->value = grc_reg_map[1]; + BK7011TRXONLY.REG0x2->value = grc_reg_map[2]; + BK7011TRXONLY.REG0x3->value = grc_reg_map[3]; + BK7011TRXONLY.REG0x4->value = grc_reg_map[4]; + BK7011TRXONLY.REG0x6->value = grc_reg_map[6]; + BK7011TRXONLY.REG0x7->value = grc_reg_map[7]; + BK7011TRXONLY.REG0x8->value = grc_reg_map[8]; + BK7011TRXONLY.REG0x9->value = grc_reg_map[9]; + BK7011TRXONLY.REG0xA->value = grc_reg_map[10]; + BK7011TRXONLY.REG0xB->value = grc_reg_map[11]; + BK7011TRXONLY.REG0xC->value = grc_reg_map[12]; + BK7011TRXONLY.REG0xD->value = grc_reg_map[13]; + BK7011TRXONLY.REG0xE->value = grc_reg_map[14]; + BK7011TRXONLY.REG0x11->value = grc_reg_map[17]; + BK7011TRXONLY.REG0x12->value = grc_reg_map[18]; + BK7011TRXONLY.REG0x13->value = grc_reg_map[19]; + BK7011TRXONLY.REG0x14->value = grc_reg_map[20]; + BK7011TRXONLY.REG0x15->value = grc_reg_map[21]; + BK7011TRXONLY.REG0x16->value = grc_reg_map[22]; + BK7011TRXONLY.REG0x17->value = grc_reg_map[23]; + BK7011TRXONLY.REG0x18->value = grc_reg_map[24]; + BK7011TRXONLY.REG0x19->value = grc_reg_map[25]; + BK7011TRXONLY.REG0x1A->value = grc_reg_map[26]; + BK7011TRXONLY.REG0x1B->value = grc_reg_map[27]; + + while(BK7011RCBEKEN.REG0x1->value & 0x0FFFFFFF) + { + cpu_delay(1); + } + + BK7011TRX.REG0x7->bits.autorxifgen = 0; + BK7011TRX.REG0x7->bits.digdcoen = 0; + BK7011TRX.REG0x7->bits.spilpfrxg30 = 6; + CAL_WR_TRXREGS(0x7); + + BK7011TRX.REG0x6->bits.lpfcapcali50 = gtx_ifilter_corner; + BK7011TRX.REG0x6->bits.lpfcapcalq50 = gtx_ifilter_corner; + CAL_WR_TRXREGS(0x6); + + bk7011_set_rx_avg_dc(); // 11/11/2014 + + return 0; +} + +void bk7011_set_tx_after_cal(void) +{ + BK7011RCBEKEN.REG0x0->bits.forceenable = 0; + cpu_delay(1); + BK7011RCBEKEN.REG0x19->bits.FCH0EN = 1; + BK7011RCBEKEN.REG0x19->bits.FCH0SHDN = 1; + BK7011RCBEKEN.REG0x19->bits.FCH0RXEN = 0; + BK7011RCBEKEN.REG0x19->bits.FCH0TXEN = 1; + BK7011RCBEKEN.REG0x1C->bits.FRXON = 0; + BK7011RCBEKEN.REG0x1C->bits.FTXON = 1; + BK7011RCBEKEN.REG0x4C->bits.TESTPATTERN = 0; +} + +void bk7011_set_rx_after_cal(void) +{ + BK7011RCBEKEN.REG0x0->bits.forceenable = 0; + cpu_delay(1); + BK7011RCBEKEN.REG0x19->bits.FCH0EN = 1; + BK7011RCBEKEN.REG0x19->bits.FCH0SHDN = 1; + BK7011RCBEKEN.REG0x19->bits.FCH0RXEN = 1; + BK7011RCBEKEN.REG0x19->bits.FCH0TXEN = 0; + BK7011RCBEKEN.REG0x1C->bits.FRXON = 1; + BK7011RCBEKEN.REG0x1C->bits.FTXON = 0; + BK7011RCBEKEN.REG0x4C->bits.TESTPATTERN = 0; + + BK7011TRX.REG0xE->value = 0xDA01BCF0; + CAL_WR_TRXREGS(0xE); + + // ADC clock change to 40M + BK7011TRX.REG0xF->bits.clkadcsel = 0; + CAL_WR_TRXREGS(0xF); + + BK7011TRX.REG0x12->bits.adcrefbwsel = 0; + CAL_WR_TRXREGS(0x12); + +} + +extern void mpb_tx_mode(void); + +#define CALI_DPD_TEST 0 +#if CALI_DPD_TEST +#define I_TABLE_ADDR 0x01050400 +#define Q_TABLE_ADDR 0x01050600 + +static UINT16 i_table_val[256] = +{ + 0, 6, 13, 19, 26, 35, 40, 47, 52, 57, 68, 73, 76, 82, 88, 91, 96, 102, 107, 107, 118, 118, 120, 127, 132, 134, 139, 141, 146, 149, 152, 158, 161, 161, 163, 164, 168, 172, 172, 176, 181, 177, 179, 181, 185, 187, 189, 185, 191, 195, 196, 195, 196, 197, 203, 198, 204, 201, 207, 199, 206, 207, 207, 207, 207, 210, 210, 212, 214, 215, 215, 215, 206, 216, 215, 221, 217, 219, 215, 219, 222, 222, 225, 229, 225, 223, 228, 226, 226, 229, 229, 226, 225, 227, 226, 226, 228, 232, 230, 229, 230, 231, 230, 231, 234, 235, 236, 238, 241, 244, 245, 247, 248, 251, 252, 255, 255, 258, 259, 262, 263, 265, 267, 268, 271, 272, 275, 275, 278, 280, 282, 284, 287, 288, 291, 293, 295, 297, 299, 301, 304, 306, 308, 310, 312, 314, 317, 319, 321, 323, 325, 327, 330, 332, 334, 336, 338, 341, 343, 345, 347, 349, 351, 354, 356, 358, 360, 362, 364, 367, 369, 371, 373, 375, 377, 380, 382, 384, 386, 388, 390, 393, 395, 397, 399, 401, 403, 406, 408, 410, 412, 414, 416, 419, 421, 423, 425, 427, 429, 432, 434, 436, 438, 440, 442, 445, 447, 449, 451, 453, 455, 458, 460, 462, 464, 466, 468, 471, 473, 475, 477, 479, 481, 484, 486, 488, 490, 492, 495, 497, 499, 501, 503, 505, 508, 510, 512, 514, 516, 518, 521, 523, 525, 527, 529, 531, 534, 536, 538, 540, 542, 544, 547, 549, 551, 562 +}; + +static UINT16 q_table_val[256] = +{ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 2, 1, 5, 8, 5, 9, 6, 5, 7, 4, 7, 8, 17, 13, 12, 14, 15, 12, 12, 18, 12, 13, 16, 16, 17, 19, 20, 24, 22, 30, 23, 21, 24, 30, 27, 26, 24, 27, 26, 30, 28, 30, 32, 31, 31, 32, 32, 33, 35, 35, 33, 35, 34, 32, 32, 32, 34, 33, 32, 31, 32, 30, 33, 29, 30, 29, 30, 29, 29, 28, 27, 29, 27, 28, 26, 26, 26, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 29, 29, 29, 29, 29, 30, 30, 30, 30, 30, 31, 31, 31, 31, 31, 32, 32, 32, 32, 32, 33, 33, 33, 33, 33, 34, 34, 34, 34, 34, 35, 35, 35, 35, 35, 36, 36, 36, 36, 36, 37, 37, 37, 37, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 42, 42, 42, 42, 42, 43, 43, 43, 43, 43, 44, 44, 44, 44, 44, 45, 45, 45, 45, 45, 46, 46, 46, 46, 46, 47, 47, 47, 47, 48, 48, 48, 48, 48, 49, 49, 49, 49, 49, 50, 50, 50, 50, 50, 51, 51, 51, 51, 51, 52, 52, 48 +}; + +UINT32 bk7211_cal_tx_dpd_load(void) +{ + + UINT16 *i_tbl_addr = (UINT16 *)I_TABLE_ADDR; + UINT16 *q_tbl_addr = (UINT16 *)Q_TABLE_ADDR; + UINT16 k; + + BK7011RCBEKEN.REG0x4C->bits.DPDEN = 0; + + os_memcpy(i_tbl_addr, (UINT16 *)&i_table_val[0], 256 * 2); + os_memcpy(q_tbl_addr, (UINT16 *)&q_table_val[0], 256 * 2); + +#if 1 + for(k = 0; k < 256; k++) + { + i_tbl_addr[k] = 1; + q_tbl_addr[k] = 0; + } +#endif + return 0; + +} +#endif + +#if CAL_RESULT_TO_FLASH +void write_cal_result_to_flash(void) +{ + UINT32 param; + UINT32 param1; + char cTemp[sizeof(bk7011_rc_val) + sizeof(bk7011_trx_val)]; + char cTemp1[sizeof(bk7011_rc_val) + sizeof(bk7011_trx_val)]; + + CAL_FLASH_PRT("write cal result to flash\r\n"); + + #if CFG_SUPPORT_ALIOS + hal_flash_dis_secure(0, 0, 0); + #else + bk_flash_enable_security(FLASH_PROTECT_NONE); + #endif + + flash_erase_sector(CAL_RESULT_FLASH_ADDR); + + memcpy(cTemp, bk7011_rc_val, sizeof(bk7011_rc_val)); + memcpy(cTemp + sizeof(bk7011_rc_val), bk7011_trx_val, sizeof(bk7011_trx_val)); + + flash_write(cTemp, sizeof(cTemp), CAL_RESULT_FLASH_ADDR); + flash_read(cTemp1, sizeof(cTemp1), CAL_RESULT_FLASH_ADDR); + if (memcmp(cTemp, cTemp1, sizeof(cTemp1)) == 0) + { + CAL_FLASH_PRT("memcmp OK\r\n"); + } + else + { + CAL_FLASH_PRT("memcmp fail\r\n"); + } + + #if CFG_SUPPORT_ALIOS + hal_flash_enable_secure(0, 0, 0); + #else + bk_flash_enable_security(FLASH_PROTECT_ALL); + #endif + + os_printf("write cal result to flash OK\r\n"); +} +#endif + +char read_cal_result_from_flash(void) +{ +#if CAL_RESULT_TO_FLASH + char cTemp[sizeof(bk7011_rc_val) + sizeof(bk7011_trx_val)]; + + CAL_FLASH_PRT("read_cal_result_from_flash\r\n"); + memset(cTemp, 0, sizeof(cTemp)); + flash_read(cTemp, sizeof(cTemp), CAL_RESULT_FLASH_ADDR); + if ((cTemp[0] == 0xFF) && (cTemp[4] == 0xFF) && (cTemp[8] == 0xFF) && (cTemp[12] == 0xFF)) + { + return 0; + } + else + { + memcpy(bk7011_rc_val, cTemp, sizeof(bk7011_rc_val)); + memcpy(bk7011_trx_val, cTemp + sizeof(bk7011_rc_val), sizeof(bk7011_trx_val)); + rwnx_cal_load_default_result(); + rwnx_cal_load_trx_rcbekn_reg_val(); + os_printf("read cal result from flash OK\r\n"); + + return 1; + } +#else + return 0; +#endif +} + +#if CAL_RESULT_TO_FLASH +void flash_test(void) +{ + UINT32 param; + char cTemp[0x1000]; + char cTemp1[0x1000]; + int i; + + flash_read(cTemp, 0x1000, 0xF4000); + os_printf("cTemp:\r\n"); + for (i = 0; i < 0x1000; i++) + { + os_printf("%x ", cTemp[i]); + } + os_printf("\r\n"); + + #if CFG_SUPPORT_ALIOS + hal_flash_dis_secure(0, 0, 0); + #else + bk_flash_enable_security(FLASH_PROTECT_NONE); + #endif + param = 0xF4000; + flash_ctrl(CMD_FLASH_ERASE_SECTOR, ¶m); + + flash_read(cTemp, 0x1000, 0xF4000); + os_printf("cTemp:\r\n"); + for (i = 0; i < 0x1000; i++) + { + os_printf("%x ", cTemp[i]); + } + os_printf("\r\n"); + + for (i = 0; i < 0x1000; i++) + { + cTemp[i] = i; + } + os_printf("cTemp:\r\n"); + for (i = 0; i < 0x1000; i++) + { + os_printf("%x ", cTemp[i]); + } + os_printf("\r\n"); + + flash_write(cTemp, 0x1000, 0xF4000); + + memset(cTemp1, 0, 0x1000); + os_printf("cTemp1:\r\n"); + for (i = 0; i < 0x1000; i++) + { + os_printf("%x ", cTemp1[i]); + } + os_printf("\r\n"); + flash_read(cTemp1, 0x1000, 0xF4000); + + os_printf("cTemp1:\r\n"); + for (i = 0; i < 0x1000; i++) + { + os_printf("%x ", cTemp1[i]); + } + + os_printf("\r\n"); + if (memcmp(cTemp, cTemp1, sizeof(cTemp)) == 0) + { + os_printf("memcmp OK\r\n"); + } + else + { + os_printf("memcmp ERROR\r\n"); + } +} +#endif + +void rwnx_cal_initial_calibration(void) +{ + rwnx_cal_set_txpwr(16, EVM_DEFUALT_RATE); +} + +void sctrl_dpll_int_open(void); +void calibration_main(void) +{ + INT32 goldval[32] = {0}; + + BK7011RCBEKEN.REG0x4C->bits.TXCOMPDIS = 0; + bk7011_cal_ready(); + bk7011_cal_bias(); + + bk7011_cal_dpll(); + sctrl_dpll_int_open(); + + bk7011_cal_pll(); + + BK7011TRX.REG0xA->value = TRX_REG_0XA_VAL; + CAL_WR_TRXREGS(0xA); + BK7011TRX.REG0xB->value = TRX_REG_0XB_VAL; + CAL_WR_TRXREGS(0xB); + BK7011TRX.REG0xC->value = TRX_REG_0XC_VAL; + CAL_WR_TRXREGS(0xC); + + if (read_cal_result_from_flash() == 1) + { + return; + } + + BK7011TRX.REG0x7->bits.chin60 = 0x00;//2400MHz descrease the external interference + CAL_WR_TRXREGS(0x7); + delay100us(1);//delay 100us for RFPLL + + bk7011_tx_cal_en(); + gtx_power_cal_mode = TX_IQ_POWER_CAL; + bk7011_cal_tx_output_power(goldval); // + + gtx_dc_cal_mode = TX_DC_CAL; + bk7011_cal_tx_dc(goldval); + + gtx_gain_imb_cal_mode = TX_GAIN_IMB_CAL; + bk7011_cal_tx_gain_imbalance(goldval); + + gtx_phase_imb_cal_mode = TX_PHASE_IMB_CAL; + bk7011_cal_tx_phase_imbalance(goldval); + + + BK7011TRX.REG0x7->bits.chin60 = 0x5d;//2495MHz + CAL_WR_TRXREGS(0x7); + delay100us(1);//delay 100us for RFPLL + + bk7011_cal_tx_filter_corner(goldval); + bk7011_cal_bias(); + + gtx_power_cal_mode = TX_WANTED_POWER_CAL; + + BK7011TRX.REG0x7->bits.chin60 = 0xc;//fix to this channel for power cal. + CAL_WR_TRXREGS(0x7); + delay100us(1);//delay 100us for RFPLL + + //bk7011_cal_tx_output_power(goldval); // Actual Power cal. + + bk7011_set_tx_after_cal(); + rwnx_tx_cal_save_cal_result();//by yiming 20170315 + + bk7011_rx_cal_en(); + bk7011_cal_rx_dc(); + + bk7011_tx_cal_en(); + + + BK7011TRX.REG0x7->bits.chin60 = 0x5d;//2495MHz + CAL_WR_TRXREGS(0x7); + delay100us(1);//delay 100us for RFPLL + + gtx_power_cal_mode = TX_IQ_LOOPBACK_POWER_CAL; + bk7011_cal_tx_output_power(goldval); + + gtx_dc_cal_mode = TX_DC_LOOPBACK_CAL; + bk7011_cal_tx_dc(goldval);//Loopback DC cal. + + + gtx_gain_imb_cal_mode = TX_GAIN_LOOPBACK_IMB_CAL; + bk7011_cal_tx_gain_imbalance(goldval); + +#ifdef CALIBRATE_TIMES + if (p_gtx_i_gain_comp_temp_array != NULL) + { + p_gtx_i_gain_comp_temp_array[calibrate_time] = ( (*((volatile unsigned long * )(0x01050000 + 0x50 * 4))) >> 16) & 0x03FF ; + p_gtx_q_gain_comp_temp_array[calibrate_time] = (*((volatile unsigned long * )(0x01050000 + 0x50 * 4))) & 0x03FF ; + } +#endif + + gtx_phase_imb_cal_mode = TX_PHASE_LOOPBACK_IMB_CAL; + bk7011_cal_tx_phase_imbalance(goldval); + + bk7011_rx_cal_en(); + bk7011_cal_rx_iq(goldval); + + bk7011_load_calibration_cfg(); + bk7011_set_rx_after_cal(); + + rwnx_rx_cal_save_cal_result(); + rwnx_cal_load_default_result(); + rwnx_cal_read_current_cal_result(); + BK7011RCBEKEN.REG0x4C->bits.TXCOMPDIS = 0; + + rwnx_tx_cal_save_cal_result();//by yiming 20170315 + rwnx_cal_load_trx_rcbekn_reg_val(); + +#if CALI_DPD_TEST + rwnx_cal_load_trx_rcbekn_reg_val(); + bk7211_cal_tx_dpd_load(); +#endif + +#if CAL_RESULT_TO_FLASH + write_cal_result_to_flash(); +#endif + return ; +} + +void do_calibration_in_temp_dect(void) +{ + INT32 goldval[32] = {0}; + + BK7011TRX.REG0x7->bits.chin60 = 0xc;//fix to this channel for power cal. + CAL_WR_TRXREGS(0x7); + delay100us(1);//delay 100us for RFPLL + + bk7011_read_cal_param(); + rwnx_cal_load_default_result(); + cpu_delay(10);//cpu_delay(10); 20160801 + + bk7011_cal_bias(); + bk7011_cal_dpll(); + sctrl_dpll_int_open(); + + BK7011RCBEKEN.REG0x4C->bits.TXCOMPDIS = 0; + + bk7011_tx_cal_en(); + + gtx_power_cal_mode = TX_WANTED_POWER_CAL; + //bk7011_cal_tx_output_power(goldval); // second time + + bk7011_set_tx_after_cal(); + + //rwnx_cal_read_current_cal_result(); + rwnx_tx_cal_save_cal_result(); + rwnx_cal_load_default_result(); + rwnx_cal_read_current_cal_result(); + BK7011RCBEKEN.REG0x4C->bits.TXCOMPDIS = 0; + + return ; +} + +UINT32 gctrlpga20 = 0; +void turnoff_PA_in_temp_dect(void) +{ + CHECK_OPERATE_RF_REG_IF_IN_SLEEP(); + + gctrlpga20 = BK7011TRXONLY.REG0xC->bits.gctrlpga20; + BK7011TRX.REG0xC->bits.gctrlpga20 = 0; + CAL_WR_TRXREGS(0xC); + CHECK_OPERATE_RF_REG_IF_IN_SLEEP_END(); +} + +void turnon_PA_in_temp_dect(void) +{ + CHECK_OPERATE_RF_REG_IF_IN_SLEEP(); + + BK7011TRX.REG0xC->bits.gctrlpga20 = gctrlpga20; + CAL_WR_TRXREGS(0xC); + CHECK_OPERATE_RF_REG_IF_IN_SLEEP_END(); +} + +void rwnx_cal_set_40M_extra_setting(UINT8 val) +{ + +} + +void rwnx_cal_set_reg_adda_ldo(UINT32 val) +{ + +} + +void bk7011_max_rxsens_setting(void) +{ + +} + +void bk7011_default_rxsens_setting(void) +{ + +} + +UINT32 rwnx_tpc_pwr_idx_translate(UINT32 pwr_gain, UINT32 rate, UINT32 print_log) +{ + return pwr_gain; +} + +UINT32 rwnx_tpc_get_pwridx_by_rate(UINT32 rate, UINT32 print_log) +{ + return 0; +} + +void rwnx_use_tpc_set_pwr(void) +{ + +} + +void rwnx_no_use_tpc_set_pwr(void) +{ + +} + +UINT32 rwnx_is_tpc_bit_on(void) +{ + return 0; +} + +UINT32 rwnx_sys_is_enable_hw_tpc(void) +{ + return 0; +} + +void rwnx_tpc_pa_map_init(void) +{ + +} + +#else /* CFG_SUPPORT_CALIBRATION */ +#endif /* CFG_SUPPORT_CALIBRATION */ + +#endif // (CFG_SOC_NAME == SOC_BK7231) +// eof + diff --git a/beken_os/beken378/func/bk7011_cal/bk7231_cal.h b/beken_os/beken378/func/bk7011_cal/bk7231_cal.h new file mode 100755 index 0000000..87c1eb8 --- /dev/null +++ b/beken_os/beken378/func/bk7011_cal/bk7231_cal.h @@ -0,0 +1,1134 @@ +#ifndef _BK7231_CAL_H_ +#define _BK7231_CAL_H_ + +#if (CFG_SOC_NAME == SOC_BK7231) + +#include "uart_pub.h" + +#define CAL_DEBUG 0 + +#if CAL_DEBUG +#define CAL_PRT null_prf +#define CAL_WARN null_prf +#define CAL_FATAL fatal_prf +#define CAL_TIM_PRT os_printf +#define CAL_FLASH_PRT os_printf +#else +#define CAL_PRT null_prf +#define CAL_WARN null_prf +#define CAL_FATAL null_prf +#define CAL_TIM_PRT null_prf +#define CAL_FLASH_PRT null_prf +#endif + +#define REGTRXV2A +#define BK7011_VER_A + +//#define _11MBPS_MAX_POWER + +void delay05us(INT32 num); + +#define trx_reg_is_write(st_trxreg) while(BK7011RCBEKEN.REG0x1->value & st_trxreg) {cpu_delay(1);} + +#define DETECT_LOOPCNT 10 +#define GOLD_OUTPUT_POWER 56 +#define UNSIGNEDOFFSET10 512 +#define I_Q_CAP_DIF 32 +#define CONSTANT_RCIQ 117 +#define SUMNUMBERS 4 +#define MINOFFSET 16 + +#define cpu_delay(val) delay(MAX(1, val/100)) +#define DELAY1US 100 + +#define cal_delay(val) delay05us(MAX(1, val)) // 8us +#define CAL_DELAY05US 2 // 20170503 2:1.5us +#define CAL_TX_NUM 50 +#define CAL_RX_NUM 5 + +#define cal_delay_100us(val) delay100us(MAX(1, val)) // 200us +#define CAL_DELAY100US 1 //20160804 1:100us 2:200us // 20170503 1:150us 2:300us + +#define st_TRXREG00 (1<<0) +#define st_TRXREG01 (1<<1) +#define st_TRXREG02 (1<<2) +#define st_TRXREG03 (1<<3) +#define st_TRXREG04 (1<<4) +#define st_TRXREG05 (1<<5) +#define st_TRXREG06 (1<<6) +#define st_TRXREG07 (1<<7) +#define st_TRXREG08 (1<<8) +#define st_TRXREG09 (1<<9) +#define st_TRXREG0A (1<<10) +#define st_TRXREG0B (1<<11) +#define st_TRXREG0C (1<<12) +#define st_TRXREG0D (1<<13) +#define st_TRXREG0E (1<<14) +#define st_TRXREG0F (1<<15) +#define st_TRXREG10 (1<<16) +#define st_TRXREG11 (1<<17) +#define st_TRXREG12 (1<<18) +#define st_TRXREG13 (1<<19) +#define st_TRXREG14 (1<<20) +#define st_TRXREG15 (1<<21) +#define st_TRXREG16 (1<<22) +#define st_TRXREG17 (1<<23) +#define st_TRXREG18 (1<<24) +#define st_TRXREG19 (1<<25) +#define st_TRXREG1A (1<<26) +#define st_TRXREG1B (1<<27) + +#define abs(a) ((a) < 0 ?(-1*(a)):(a)) + +#ifndef __BK7011RCBEKEN_H__ +#define __BK7011RCBEKEN_H__ + +#define RC_BEKEN_BASE 0x01050000 + +/// REG0x0 +typedef union +{ + struct + { + volatile unsigned int ch0en : 1; /**< Enable BK7011 (1: Enable) */ + volatile unsigned int Reserved : 2; /**< NC */ + volatile unsigned int rcen : 1; /**< Enable BK7011 (1: Enable) */ + volatile unsigned int Reserved_ : 4; /**< NC */ + volatile unsigned int ch0ld : 1; /**< BK7011 LDֵǷ */ + volatile unsigned int Reserved__ : 3; /**< NC */ + volatile unsigned int ch0shdnstat : 1; /**< BK7011Ƿshutdown״̬ */ + volatile unsigned int Reserved___ : 3; /**< NC */ + volatile unsigned int rcstate : 3; /**< ǰRC״̬;0x00=SPI_RESET ;0x01=SHUTDOWN ;0x02=WAIT_SPI (SPIڲ);0x03=WAIT_LOCKRFPLLLock;0x04=ACTIVE */ + volatile unsigned int Reserved____ : 11; /**< NC */ + volatile unsigned int spireset : 1; /**< Reset BK7011SPIĴ */ + volatile unsigned int forceenable : 1; /**< ǿƿBK7011Ľӿź */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x0_TypeDef; + +/// REG0x1 +typedef union +{ + struct + { + volatile unsigned int trxregstat : 28; /**< TRx Register Stat.;0x0: register is idle;0x1: register is updating. Can not write register again */ + volatile unsigned int prescaler : 4; /**< SPIʱƵʿ=RC_Clock (80 MHz)/2/PRESCALE */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x1_TypeDef; + +/// REG0x5 +typedef union +{ + struct + { + volatile unsigned int ch0outpower : 8; /**< No description */ + volatile unsigned int Reserved : 24; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x5_TypeDef; + +/// REG0x8 +typedef union +{ + struct + { + volatile unsigned int CH0RXONDELAY : 8; /**< No description */ + volatile unsigned int Reserved : 8; /**< NC */ + volatile unsigned int CH0RXOFFDELAY : 8; /**< No description */ + volatile unsigned int Reserved_ : 8; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x8_TypeDef; + +/// REG0xB +typedef union +{ + struct + { + volatile unsigned int CH0TXONDELAY : 8; /**< No description */ + volatile unsigned int Reserved : 8; /**< NC */ + volatile unsigned int CH0TXOFFDELAY : 8; /**< No description */ + volatile unsigned int Reserved_ : 8; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0xB_TypeDef; + +/// REG0xE +typedef union +{ + struct + { + volatile unsigned int CH0PAONDELAY : 8; /**< No description */ + volatile unsigned int Reserved : 8; /**< NC */ + volatile unsigned int CH0PAOFFDELAY : 8; /**< No description */ + volatile unsigned int Reserved_ : 8; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0xE_TypeDef; + +/// REG0x11 +typedef union +{ + struct + { + volatile unsigned int CH0SHDNONDELAY : 8; /**< No description */ + volatile unsigned int Reserved : 8; /**< NC */ + volatile unsigned int CH0SHDNOFFDELAY : 8; /**< No description */ + volatile unsigned int Reserved_ : 8; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x11_TypeDef; + +/// REG0x19 +typedef union +{ + struct + { + volatile unsigned int FCH0SHDN : 1; /**< ǿģʽµSHDN */ + volatile unsigned int FCH0RXEN : 1; /**< ǿģʽµRXEN */ + volatile unsigned int FCH0TXEN : 1; /**< ǿģʽµTXEN */ + volatile unsigned int FCH0RXHP : 1; /**< ǿģʽµRXHP */ + volatile unsigned int Reserved : 4; /**< NC */ + volatile unsigned int FCH0B : 8; /**< ǿģʽ */ + volatile unsigned int FCH0EN : 1; /**< ǿƿRFӿź */ + volatile unsigned int Reserved_ : 15; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x19_TypeDef; + +/// REG0x1C +typedef union +{ + struct + { + volatile unsigned int FRXON : 1; /**< ǿģʽRX ON */ + volatile unsigned int FTXON : 1; /**< ǿģʽTX ON */ + volatile unsigned int Reserved : 30; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x1C_TypeDef; + +/// REG0x1E +typedef union +{ + struct + { + volatile unsigned int FERXONDEL : 12; /**< No description */ + volatile unsigned int Reserved : 20; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x1E_TypeDef; + +/// REG0x3C +typedef union +{ + struct + { + volatile unsigned int RXAVGQRD : 12; /**< Q· */ + volatile unsigned int RXAVGIRD : 12; /**< I· */ + volatile unsigned int Reserved : 4; /**< NC */ + volatile unsigned int RXHPFBYPASS : 1; /**< RX HPF bypass */ + volatile unsigned int RXIQSWAP : 1; /**< RX IQ SWAP */ + volatile unsigned int RXAVGMODE : 1; /**< 0ȡźŵƽֵ;1ȡźžֵƽֵ */ + volatile unsigned int RXDCCALEN : 1; /**< ʹRX DC(1) */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x3C_TypeDef; + +/// REG0x3E +typedef union +{ + struct + { + volatile unsigned int RXDCQRD : 12; /**< Q·DC */ + volatile unsigned int RXDCIRD : 12; /**< I·DC */ + volatile unsigned int Reserved : 6; /**< NC */ + volatile unsigned int RXCOMPEN : 1; /**< ʹMismatch(1) */ + volatile unsigned int RXCALEN : 1; /**< ʹMismatch(1) */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x3E_TypeDef; + +/// REG0x3F +typedef union +{ + struct + { + volatile unsigned int RXPHASEERRRD : 10; /**< Ƴλphase_err_est*2^9з */ + volatile unsigned int Reserved : 6; /**< NC */ + volatile unsigned int RXAMPERRRD : 10; /**< Ƴķamp_err_est*2^9з */ + volatile unsigned int Reserved_ : 6; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x3F_TypeDef; + +/// REG0x40 +typedef union +{ + struct + { + volatile unsigned int RXTY2RD : 10; /**< ƳTY2(ty2-0.5)*2^10з */ + volatile unsigned int Reserved : 22; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x40_TypeDef; + +/// REG0x41 +typedef union +{ + struct + { + volatile unsigned int RXDCQWR : 12; /**< ʱʹõQ·DC */ + volatile unsigned int RXDCIWR : 12; /**< ʱʹõI·DC */ + volatile unsigned int Reserved : 8; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x41_TypeDef; + +/// REG0x42 +typedef union +{ + struct + { + volatile unsigned int RXPHASEERRWR : 10; /**< ʱʹõphase_err*ty2*2^9 */ + volatile unsigned int Reserved : 6; /**< NC */ + volatile unsigned int RXAMPERRWR : 10; /**< ʱʹõty2/(1+amp_err)*2^9 */ + volatile unsigned int Reserved_ : 6; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x42_TypeDef; + +/// REG0x4C +typedef union +{ + struct + { + volatile unsigned int QCONSTANT : 10; /**< 䳣ʱQֵ */ + volatile unsigned int Reserved : 6; /**< NC */ + volatile unsigned int ICONSTANT : 10; /**< 䳣ʱIֵ */ + volatile unsigned int DPDCOMPEN : 1; /**< DPD Compensation Enable */ + volatile unsigned int DPDCALEN : 1; /**< DPD Calculation Enable */ + volatile unsigned int DPDEN : 1; /**< DPD Enable] */ + volatile unsigned int TXCOMPDIS : 1; /**< Ͳֹܽ;0x0: ʹܷͲ;0x1: ֹͲ */ + volatile unsigned int TESTPATTERN : 2; /**< 0ģʽModem */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x4C_TypeDef; + +/// REG0x4D +typedef union +{ + struct + { + volatile unsigned int Reserved : 12; /**< NC */ + volatile unsigned int TXSINAMP : 4; /**< ҲȵϵСʾx.yyyΧ[0 15/8] */ + volatile unsigned int TXSINMODE : 2; /**< 0I/Q·临Ҳ;1I·䣬Q·0;2Q·䣬I·0;3 */ + volatile unsigned int Reserved_ : 4; /**< NC */ + volatile unsigned int TXSINF : 10; /**< ҲƵ;TX_SIN_F=2*pi*F/80e6*2^8FǷƵ */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x4D_TypeDef; + +/// REG0x4F +typedef union +{ + struct + { + volatile unsigned int TXQDCCOMP : 10; /**< Q DC offset[-512 511] */ + volatile unsigned int Reserved : 6; /**< NC */ + volatile unsigned int TXIDCCOMP : 10; /**< I DC offset[-512 511] */ + volatile unsigned int Reserved_ : 6; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x4F_TypeDef; + +/// REG0x50 +typedef union +{ + struct + { + volatile unsigned int TXQGAINCOMP : 10; /**< 0 ~ 1023/1024step:1/1024 */ + volatile unsigned int Reserved : 6; /**< NC */ + volatile unsigned int TXIGAINCOMP : 10; /**< 0 ~ 1023/1024step:1/1024 */ + volatile unsigned int Reserved_ : 6; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x50_TypeDef; + +/// REG0x51 +typedef union +{ + struct + { + volatile unsigned int TXTY2 : 10; /**< 512/1024 ~ (512+1023)/1024step:1/1024 */ + volatile unsigned int Reserved : 6; /**< NC */ + volatile unsigned int TXPHASECOMP : 10; /**< -512/1024~ 511/1024step:1/1024 */ + volatile unsigned int Reserved_ : 6; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x51_TypeDef; + +/// REG0x52 +typedef union +{ + struct + { + volatile unsigned int Reserved : 6; /**< NC */ + volatile unsigned int IQCONSTANTIQCALP : 10; /**< IQУ׼IQ CONSTANT ֵֵ */ + volatile unsigned int TXPREGAIN : 5; /**< IQź;01.75 dB;. 31-6dB;; */ + volatile unsigned int IQCONSTANTPOUT : 10; /**< У׼IQ CONSTANT ֵ */ + volatile unsigned int TXIQSWAP : 1; /**< IQ Swap */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x52_TypeDef; + +/// REG0x54 +typedef union +{ + struct + { + volatile unsigned int STRXADCIQ : 1; /**< RX ADC IQУ׼ Settling time 0:300us;1:600us */ + volatile unsigned int TSSIPOUTTH : 8; /**< У׼ʶӦTSSI */ + volatile unsigned int DSELVA : 1; /**< TSSI or AGC gain setting for versiong A, output 0: TSSI 1:AGC gain setting */ + volatile unsigned int TXDCN : 2; /**< TX DC ַһִв 0:3Σ1:4Σ2:5Σ3:6 */ + volatile unsigned int STRXADC : 2; /**< RX ADC Settling time 0:100us;1:200us;2:300us;3:400us */ + volatile unsigned int STSARADC : 2; /**< SAR ADC Settling time 0:0.5us;1:1us;2:1.5us;3:2us */ + volatile unsigned int TSSIRD : 8; /**< TSSI Value. Just valid during tssi_cal_en assert */ + volatile unsigned int AGCPGARD : 4; /**< AGCPGA */ + volatile unsigned int AGCBUFRD : 1; /**< AGCBUF */ + volatile unsigned int AGCLNARD : 2; /**< AGCLNA */ + volatile unsigned int AGCMAPMODE : 1; /**< 0ӳ䷽ʽһ;1ӳ䷽ʽ */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x54_TypeDef; + +/// REG0x55 +typedef union +{ + struct + { + volatile unsigned int RXSNRNOISE : 9; /**< rx noise for sinar test */ + volatile unsigned int Reserved : 7; /**< NC */ + volatile unsigned int RXSNRSIG : 9; /**< rx signal for sinar test */ + volatile unsigned int Reserved_ : 7; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x55_TypeDef; + +/// REG0x5C +typedef union +{ + struct + { + volatile unsigned int trxspiintval : 10; /**< TRX SPI Transfer Interval. Unit is 12.5ns */ + volatile unsigned int Reserved : 14; /**< NC */ + volatile unsigned int Reserved_ : 7; /**< Reserved */ + volatile unsigned int trxbankrpt : 1; /**< TRX Bank Report. 0x0:bank0; 0x1:bank1 */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x5C_TypeDef; + +/// REG0x6A +typedef union +{ + struct + { + volatile unsigned int trxaddaregstat : 6; /**< ADC&DAC Register Status.;0x0: register is idle;0x1: register is updating. Can not write register again */ + volatile unsigned int Reserved : 26; /**< NC */ + } bits; + volatile unsigned int value; +} BK7011_RC_BEKEN_REG0x6A_TypeDef; + +/// BK7011RCBEKEN +struct BK7011RCBEKEN_TypeDef +{ + volatile BK7011_RC_BEKEN_REG0x0_TypeDef *REG0x0; + volatile BK7011_RC_BEKEN_REG0x1_TypeDef *REG0x1; + volatile BK7011_RC_BEKEN_REG0x5_TypeDef *REG0x5; + volatile BK7011_RC_BEKEN_REG0x8_TypeDef *REG0x8; + volatile BK7011_RC_BEKEN_REG0xB_TypeDef *REG0xB; + volatile BK7011_RC_BEKEN_REG0xE_TypeDef *REG0xE; + volatile BK7011_RC_BEKEN_REG0x11_TypeDef *REG0x11; + volatile BK7011_RC_BEKEN_REG0x19_TypeDef *REG0x19; + volatile BK7011_RC_BEKEN_REG0x1C_TypeDef *REG0x1C; + volatile BK7011_RC_BEKEN_REG0x1E_TypeDef *REG0x1E; + volatile BK7011_RC_BEKEN_REG0x3C_TypeDef *REG0x3C; + volatile BK7011_RC_BEKEN_REG0x3E_TypeDef *REG0x3E; + volatile BK7011_RC_BEKEN_REG0x3F_TypeDef *REG0x3F; + volatile BK7011_RC_BEKEN_REG0x40_TypeDef *REG0x40; + volatile BK7011_RC_BEKEN_REG0x41_TypeDef *REG0x41; + volatile BK7011_RC_BEKEN_REG0x42_TypeDef *REG0x42; + volatile BK7011_RC_BEKEN_REG0x4C_TypeDef *REG0x4C; + volatile BK7011_RC_BEKEN_REG0x4D_TypeDef *REG0x4D; + volatile BK7011_RC_BEKEN_REG0x4F_TypeDef *REG0x4F; + volatile BK7011_RC_BEKEN_REG0x50_TypeDef *REG0x50; + volatile BK7011_RC_BEKEN_REG0x51_TypeDef *REG0x51; + volatile BK7011_RC_BEKEN_REG0x52_TypeDef *REG0x52; + volatile BK7011_RC_BEKEN_REG0x54_TypeDef *REG0x54; + volatile BK7011_RC_BEKEN_REG0x55_TypeDef *REG0x55; + volatile BK7011_RC_BEKEN_REG0x5C_TypeDef *REG0x5C; + volatile BK7011_RC_BEKEN_REG0x6A_TypeDef *REG0x6A; +}; +#endif + +#ifndef __BK7011TRxV2A_H__ +#define __BK7011TRxV2A_H__ + +#define TRX_BEKEN_BASE 0x01050080 + +/// REG0x0 +typedef union +{ + struct + { + volatile unsigned int pwdpll : 1; /**< pwdpll */ + volatile unsigned int cp20 : 3; /**< cp curent control 0to 350uA 50uA step */ + volatile unsigned int spideten : 1; /**< unlock detect enable fron spi 1:enable */ + volatile unsigned int hvref10 : 2; /**< high vth control for unlock detect 00:0.85V;01:0.9V;10:0.95V;11:1.05V */ + volatile unsigned int lvref10 : 2; /**< low vth control for unlock detect 00:0.2V;01:0.3V;10:0.35V;11:0.4V */ + volatile unsigned int Rzctrl26M : 1; /**< Rz ctrl in 26M mode:1:normal;0:add 14K */ + volatile unsigned int LoopRzctrl30 : 4; /**< Rz ctrl:2K to 17K,1K step */ + volatile unsigned int rpc10 : 2; /**< second pole Rp ctrl:00:30K;01:10K;10:22K;11:2K */ + volatile unsigned int nsyn : 1; /**< N divider rst */ + volatile unsigned int cksel10 : 2; /**< 0:26M;1:40M;2:24M;3:19.2M */ + volatile unsigned int spitrig : 1; /**< SPI band selection trigger signal */ + volatile unsigned int CKEn : 1; /**< 1: Enable all clock phases(480M/160M); 0 : Disable all clocks; */ + volatile unsigned int band41 : 4; /**< band manual value */ + volatile unsigned int bandmanual : 1; /**< 1:band manual;0:band auto */ + volatile unsigned int dsptrig : 1; /**< band selection trigger signal */ + volatile unsigned int xtalIctrl : 1; /**< 0:large current;1:small current */ + volatile unsigned int ckTestEn : 1; /**< 1: Enable clock test path; 0 : Disable clock test path; */ + volatile unsigned int xamp31 : 3; /**< xtal OSC amp control */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x0_TypeDef; + +/// REG0x1 +typedef union +{ + struct + { + volatile unsigned int acoef80 : 9; /**< ˲֧·ϵ */ + volatile unsigned int bcoef20 : 3; /**< ˲propotional֧·ϵ */ + volatile unsigned int bckphoffset50 : 6; /**< PD˵divʱӵӳ */ + volatile unsigned int rckphoffset50 : 6; /**< PD˵refʱӵӳ */ + volatile unsigned int bypass52M : 1; /**< bypass 52Mʱӣ26Mʱ */ + volatile unsigned int tst2xpden : 1; /**< ѡҪźţ1ΪPD0Ϊ52Mʱ */ + volatile unsigned int tst2xen : 1; /**< ʹܲ */ + volatile unsigned int calspitrig : 1; /**< ͨĴƵʵУ׼ʱдΪ0дΪ1 */ + volatile unsigned int bypassdmsb : 1; /**< ˲ʱbypassDmsb֧· */ + volatile unsigned int manual : 1; /**< DmsbDlsbΪֶ */ + volatile unsigned int frecalbypass : 1; /**< bypass ƵʵԶУ׼ܣֶ */ + volatile unsigned int rstnspi : 1; /**< ͨĴreset */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x1_TypeDef; + +/// REG0x2 +typedef union +{ + struct + { + volatile unsigned int arbpden : 1; /**< ͨĴʹarbiter BBPD */ + volatile unsigned int endoubler : 1; /**< ͨĴʹdoubler */ + volatile unsigned int trackenspi : 1; /**< ͨĴʹܿ㷨 */ + volatile unsigned int Dcal80 : 9; /**< ͨĴֶDcal */ + volatile unsigned int Dmsbspi20 : 3; /**< ͨĴֶDmsb */ + volatile unsigned int Dlsbspi40 : 5; /**< ͨĴֶDlsb */ + volatile unsigned int updatecycle110 : 12; /**< ÿ㷨ʱݵʱ */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x2_TypeDef; + +/// REG0x3 +typedef union +{ + struct + { + volatile unsigned int numdn110 : 12; /**< λͺĴ */ + volatile unsigned int numup110 : 12; /**< λǰĴ */ + volatile unsigned int arbpddelay30 : 4; /**< arbiter BBPDеdelay */ + volatile unsigned int hysen : 1; /**< ʹλij͹ */ + volatile unsigned int phacalbypass : 1; /**< ˲ʱУ׼ɺԲʹλtracking,ӶУ׼ĽǷȷ */ + volatile unsigned int f2xldovsel3v10 : 2; /**< LDOѹLDOһλÿλѾlevel shiftת001.2V01 101.3V111.4V */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x3_TypeDef; + +/// REG0x4 +typedef union +{ + struct + { + volatile unsigned int manual : 1; /**< vco manual band control enable 1:manual */ + volatile unsigned int bandm60 : 7; /**< vco band manual control */ + volatile unsigned int calresc10 : 2; /**< vco nwell voltage for calibration:00,0.5V;01,0.6V;10,0.7V;11,0.8V */ + volatile unsigned int rvco20 : 3; /**< rfpll vco bias current control */ + volatile unsigned int cpldo10 : 2; /**< Charge Pump LDO voltage control. */ + volatile unsigned int NC : 1; /**< No description */ + volatile unsigned int trswspi : 1; /**< trsw spi control:0,spi;1:cpu */ + volatile unsigned int trswen : 1; /**< enable cpu trsw control 1:enable */ + volatile unsigned int nrsten : 1; /**< N counter reset enable */ + volatile unsigned int reset : 1; /**< reset rfpll fb divider loading */ + volatile unsigned int pwdlogen : 1; /**< power down rfpll LO generation */ + volatile unsigned int pwdvco : 1; /**< power down rfpll vco */ + volatile unsigned int pwdpll : 1; /**< power down rfpll pll */ + volatile unsigned int nint70 : 8; /**< power down rfpll vco */ + volatile unsigned int intmode : 1; /**< power down rfpll pll */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x4_TypeDef; + +/// REG0x5 +typedef union +{ + struct + { + volatile unsigned int errdetspien : 1; /**< spi enable rfpll unlock detection */ + volatile unsigned int spitrigger : 1; /**< VCO calibration trigger from spi */ + volatile unsigned int ckrefsel : 1; /**< reference clock freq select: 0, 26M; 1, 52M */ + volatile unsigned int ckpsel : 1; /**< reference clock pol select */ + volatile unsigned int locap30 : 4; /**< LO Mixer load cap control */ + volatile unsigned int lmngm20 : 3; /**< LO Mixer negative resistor control */ + volatile unsigned int sdiv210 : 2; /**< rpll 3.2G div2 input dc bias control */ + volatile unsigned int pllldo10 : 2; /**< pll ldo output voltage control: 00, 1.2V; 01 1.3V; 10, 1.4V;11 1.5V */ + volatile unsigned int vcoldo10 : 2; /**< vco ldo output voltage control: 00, 1.2V; 01 1.3V; 10, 1.4V;11 1.5V */ + volatile unsigned int lwvref10 : 2; /**< unlock detection voltage control(low) */ + volatile unsigned int lnvref10 : 2; /**< cdyn detection voltage control(low) */ + volatile unsigned int hwvref10 : 2; /**< unlock detection voltage control(high) */ + volatile unsigned int hnvref10 : 2; /**< cdyn detection voltage control(high) */ + volatile unsigned int captunedir : 1; /**< cap tune direction */ + volatile unsigned int pwdcpamp10 : 2; /**< 00,cp with op fb; 01, cp wi up/dn connect together; 11, cp wi up/dn connect to gnd/vdd */ + volatile unsigned int dcal30 : 4; /**< rfpll cp bias current calibration */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x5_TypeDef; + +/// REG0x6 +typedef union +{ + struct + { + volatile unsigned int vcmsel10 : 2; /**< ADC OP CM voltage adjustment(0:0.625 */ + volatile unsigned int tmpEn : 1; /**< 1: Enable temperature sensor; 0 : Disable temperature sensor; */ + volatile unsigned int NC : 1; /**< Reserved */ + volatile unsigned int lpfcapcalq50 : 6; /**< lpf Q path calibiration input */ + volatile unsigned int lpfcapcali50 : 6; /**< lpf I path calibiration input */ + volatile unsigned int dcocq : 8; /**< dcoc Q path input */ + volatile unsigned int dcoci : 8; /**< dcoc I path input */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x6_TypeDef; + +/// REG0x7 +typedef union +{ + struct + { + volatile unsigned int digdcoen : 1; /**< dcoc input selection,1: digital 0: spi */ + volatile unsigned int spilpfrxg30 : 4; /**< rxif gain, 0000-1111 0dB - 45dB step:3dB */ + volatile unsigned int autorxifgen : 1; /**< rxif gain control selection, 1: auto control 0: spi */ + volatile unsigned int pwdxtalbuf : 1; /**< 1: Power-down crystal oscillator buffer;;0: Enable crystal oscillator buffer; */ + volatile unsigned int pwdxtalcore : 1; /**< 1: Power-down crystal oscillator core;;0: Enable crystal oscillator core; */ + volatile unsigned int lpfvcmic10 : 2; /**< control auxiliary pmos pair gate voltage,default 01 */ + volatile unsigned int lpftxTest : 1; /**< tx test control bit,1 : tx test mode 0: default */ + volatile unsigned int xtalenref : 1; /**< 1: Enable crystal oscillator output as the reference to RF PLL only;;0: Enable crystal oscillator output as the reference to frequency doubler only. */ + volatile unsigned int voc1v210 : 2; /**< SPI/Digital regulator output programming; 00:1.2;01:1.3;10,1.4;11:1.5 */ + volatile unsigned int swm1v210 : 2; /**< Path selection of the switched output in low-power mode,00: shutdown, 01: high res, 10:res/2,11:res/3 */ + volatile unsigned int NC : 1; /**< NC */ + volatile unsigned int chin60 : 7; /**< substitute for cpu channel value */ + volatile unsigned int cksdmsel20 : 3; /**< rfpll sigma delta clock select:;0: 26MHz;;1: 40MHz;;2: 24MHz;;3: 19.2MHz;;4: 52MHz;;5:104MHz; */ + volatile unsigned int ckbandsel10 : 2; /**< vco band calibration clock select:;0: 26MHz;;1: 40MHz;;2: 24MHz;;3: 19.2MHz; */ + volatile unsigned int var10 : 2; /**< Kvco control: 0:40MHz/V;1:60MHz/V;2:60MHz/V;3:80MHz/V */ + volatile unsigned int enckcali : 1; /**< 0:VCO calibration clock do not power down;1: auto power down vco calibration clock; */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x7_TypeDef; + +/// REG0x8 +typedef union +{ + struct + { + volatile unsigned int vsrxmixldo10 : 2; /**< rx mixer LDO vout 00-11 1.2-1.5V */ + volatile unsigned int vsrxlnaldo10 : 2; /**< rx lna LDO vout 00-11 1.2-1.5V */ + volatile unsigned int isrxref10 : 2; /**< rx ref ib selection 00-11 10-15uA */ + volatile unsigned int isrxlna20 : 3; /**< rx lna ib selection 000-111 50-110uA */ + volatile unsigned int isrxlnac10 : 2; /**< rx lnacali ib selection 00-11 40-70uA */ + volatile unsigned int isrxdiv10 : 2; /**< rx div ib selection 00-11 10-25uA */ + volatile unsigned int vbsrxlo20 : 3; /**< rx lo biasing voltage: 000-111 0.4-0.75V */ + volatile unsigned int vresrxlo : 1; /**< rx lo vb ref voltage: 0-1 0.4-0.5V */ + volatile unsigned int ibsrxi2v10 : 2; /**< rx i2v ib selection 00-11 5-15uA */ + volatile unsigned int vcmsrxi2v : 1; /**< rx i2v vcm selction 0-1 0.6-0.5V */ + volatile unsigned int isrssigm10 : 2; /**< rx rssi gm ib selection 00-11 40-55uA */ + volatile unsigned int stbrssi10 : 2; /**< rx rssi stable time 00-11 150-450ns step:100ns */ + volatile unsigned int rssith50 : 6; /**< rx rssi threshhold Pant=-29dBm(th=000111) 0:-37dBm step:1dB */ + volatile unsigned int nc : 2; /**< reserved */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x8_TypeDef; + +/// REG0x9 +typedef union +{ + struct + { + volatile unsigned int agcrxfeEn : 1; /**< enble rxfe agc by mcu, 0/1 gctr by spi/mcu */ + volatile unsigned int grxlnaspi10 : 2; /**< rx lna gain 00-11 0/+6/+12/+18dBr */ + volatile unsigned int grxi2vspi10 : 2; /**< rx i2v gain 00-11 0/+6/+6/+12dBr */ + volatile unsigned int grssi10 : 2; /**< rx rssi option gain */ + volatile unsigned int grxlnacali20 : 3; /**< rx lan cali gain,000-111 -50~-5.5 caliin->i2vout step:6dB */ + volatile unsigned int rssiten : 1; /**< rssi analog v output test enable */ + volatile unsigned int dcaprxi2v10 : 2; /**< V2T: I2V feedback cap tuning 00-11: + 0/1p/2p/3p */ + volatile unsigned int drxfbrm : 1; /**< V2T: feedback mathing res on */ + volatile unsigned int dcaptrsw20 : 3; /**< V2T: 7/0 @ tx/rx mode */ + volatile unsigned int nc : 15; /**< reserved */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x9_TypeDef; + +/// REG0xA +typedef union +{ + struct + { + volatile unsigned int disrefPA10 : 2; /**< PA reference bias current programming for Constant-gm bias circuit,10u to 16.5uA */ + volatile unsigned int disrefpga10 : 2; /**< RFPGA reference bias current programming for Constant-gm bias circuit,10u to 16.5uA */ + volatile unsigned int dbpab30 : 4; /**< PA class-B input bias level programming */ + volatile unsigned int dbpaa30 : 4; /**< PA class-A input bias level programming */ + volatile unsigned int dbcpa10 : 2; /**< PA cascode device bias level programming,00(2.2v), 01(2.5v), 10(2.8v),11(3.0v) */ + volatile unsigned int noConn10 : 2; /**< No Connected */ + volatile unsigned int dcapbuf30 : 4; /**< PA buf output capacitor tuning */ + volatile unsigned int dbbuf30 : 4; /**< PA buf input device bias level programming */ + volatile unsigned int dbcbuf10 : 2; /**< PA buf cascode device bias level programming,00(2.2v), 01(2.5v), 10(2.8v),11(3.0v) */ + volatile unsigned int noConn10_ : 2; /**< No Connected */ + volatile unsigned int dtr30 : 4; /**< PA ramping-up time selection,0.13us(1111) to 3.45us(0000) */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0xA_TypeDef; + +/// REG0xB +typedef union +{ + struct + { + volatile unsigned int dcpga20 : 3; /**< RFPGA cascode device biaslevel programming */ + volatile unsigned int noConn : 1; /**< No Connected */ + volatile unsigned int dbpga30 : 4; /**< RFPGA input device bias level programming */ + volatile unsigned int dcappga30 : 4; /**< RFPGA output capacitor tuning */ + volatile unsigned int dcorMod30 : 4; /**< Modulator&RFPGA gain tuning for Pout calibration */ + volatile unsigned int dvlo20 : 3; /**< Modulator LO bias level programming,0.9v~1.07v,100(1.0v) */ + volatile unsigned int noConn_ : 1; /**< No Connected */ + volatile unsigned int dvcmo20 : 3; /**< Modulator V-I common mode voltage selection,010(vdd/2) */ + volatile unsigned int noConn__ : 1; /**< No Connected */ + volatile unsigned int dcapmod30 : 4; /**< Modulator output capacitor tuning */ + volatile unsigned int gctrlmod30 : 4; /**< Modulator gain control,3dB/step,0001(default gain+3),0010,0100(default gain-3),1000(default gain-6) */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0xB_TypeDef; + +/// REG0xC +typedef union +{ + struct + { + volatile unsigned int gctrlpga20 : 3; /**< RFPGA gain control. 111(max),110(max-3),101(max-6),100(max-9),011(max-12),010(max-18),001(max-24),000(max-30) */ + volatile unsigned int noConn : 1; /**< No Connected */ + volatile unsigned int dgainbuf20 : 3; /**< PA buf gain control,10dB(1111)~-5dB(001),4.5dB/step */ + volatile unsigned int noConn_ : 1; /**< No Connected */ + volatile unsigned int dgainPA20 : 3; /**< PA gain control,9dB(111)~-4dB(001),5dB/step */ + volatile unsigned int enTSSItst : 1; /**< TSSI test enable */ + volatile unsigned int dcorPA30 : 4; /**< PA gain tuning for Pout calibration */ + volatile unsigned int vregsel10 : 2; /**< RFLDO output voltage selection.00:1.2v; 01:1.3v; 10:1.4v; 11:1.5v */ + volatile unsigned int TSSIiref10 : 2; /**< TSSI reference bias current programming for Constant-gm bias circuit,10u to 16.5uA */ + volatile unsigned int gtssi10 : 2; /**< TSSI output gain programming,4K(00)/5K(01)/6K(10)/7K(11) */ + volatile unsigned int stbtssi10 : 2; /**< TSSI output stable time programming,0.15us(00) to 0.45us(11) */ + volatile unsigned int PcaliATTs10 : 2; /**< TSSI Pout calibration input attenuation selection,00(-6dB)~11(-24dB),6dB/step */ + volatile unsigned int enPcaliGm : 1; /**< TSSI Pout calibration option to enable Gm1 */ + volatile unsigned int enPcali : 1; /**< TSSI Pout calibration enable */ + volatile unsigned int enIQcali : 1; /**< TSSI IQ calibration enable */ + volatile unsigned int enDCcaliGm1 : 1; /**< TSSI DC calibration Gm1 block enable for -30~-15dBm input range */ + volatile unsigned int enDCcali : 1; /**< DC/IQ calibration enable.enDCcali=1 for DC or IQ calibration */ + volatile unsigned int TSSIsel : 1; /**< TSSI output selection.TSSIsel=1 for Pout calibration;TSSIsel=0 for DC/IQ calibration */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0xC_TypeDef; + +/// REG0xD +typedef union +{ + struct + { + volatile unsigned int dacselection : 1; /**< 0: external dac, 1: internal dac */ + volatile unsigned int lpfrxbw : 1; /**< lpf rx bandwidth selection 1: high bandwidth(19MHz) 0: low bandwidth(9MHz); */ + volatile unsigned int lpftxbw : 1; /**< lpf tx bandwidth selection 1: high bandwidth(29MHz) 0: low bandwidth(14MHz); */ + volatile unsigned int lpftrxsw : 1; /**< LPF tx rx switch(1:tx,0:rx) */ + volatile unsigned int enlpf : 1; /**< LPF enable */ + volatile unsigned int enif : 1; /**< ADC, DAC Ldo enable */ + volatile unsigned int endcoc : 1; /**< DCOC DAC enable */ + volatile unsigned int enrxadc : 1; /**< RX ADC enable */ + volatile unsigned int entxdac : 1; /**< TX dac enable */ + volatile unsigned int entxdacbias : 1; /**< TX dac bias enable */ + volatile unsigned int enrxrssi : 1; /**< RX RF Rssi enable */ + volatile unsigned int enrxref : 1; /**< RX RF Vref enable */ + volatile unsigned int enrxi2v : 1; /**< RX I2V enable */ + volatile unsigned int enrxmix : 1; /**< RX mixer enable */ + volatile unsigned int enlnacal : 1; /**< RX look back lna input enable */ + volatile unsigned int enlna : 1; /**< Rxfe lna enable */ + volatile unsigned int txvinsel : 1; /**< Txfe input selection(0,cal when need bypass TX filter,1:normal) */ + volatile unsigned int entssi : 1; /**< Txfe tssi enable */ + volatile unsigned int entssiadc : 1; /**< Txfe tssi adc enable */ + volatile unsigned int entxferef : 1; /**< Txfe reference enable */ + volatile unsigned int entxfebias : 1; /**< Txfe bias enable */ + volatile unsigned int entxv2i : 1; /**< Tx v2i enable */ + volatile unsigned int entxlo : 1; /**< Tx LO enable */ + volatile unsigned int entxpga : 1; /**< TX PGA enable */ + volatile unsigned int enpa : 1; /**< Tx PA enable */ + volatile unsigned int enrxsw : 1; /**< RX switch enable */ + volatile unsigned int entxsw : 1; /**< TX switch enable */ + volatile unsigned int trswpll : 1; /**< rf pll tx rx switch */ + volatile unsigned int enrfpll : 1; /**< rf pll enable */ + volatile unsigned int endobuler : 1; /**< dobuler enable */ + volatile unsigned int endpll : 1; /**< digital pll enable */ + volatile unsigned int enxtal : 1; /**< xtal enable signal */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0xD_TypeDef; + +/// REG0xE +typedef union +{ + struct + { + volatile unsigned int dacselection : 1; /**< 0: external dac, 1: internal dac */ + volatile unsigned int lpfrxbw : 1; /**< lpf rx bandwidth selection 1: high bandwidth(19MHz) 0: low bandwidth(9MHz); */ + volatile unsigned int lpftxbw : 1; /**< lpf tx bandwidth selection 1: high bandwidth(29MHz) 0: low bandwidth(14MHz); */ + volatile unsigned int lpftrxsw : 1; /**< LPF tx rx switch(1:tx,0:rx) */ + volatile unsigned int enlpf : 1; /**< LPF enable */ + volatile unsigned int enif : 1; /**< ADC, DAC Ldo enable */ + volatile unsigned int endcoc : 1; /**< DCOC DAC enable */ + volatile unsigned int enrxadc : 1; /**< RX ADC enable */ + volatile unsigned int entxdac : 1; /**< TX dac enable */ + volatile unsigned int entxdacbias : 1; /**< TX dac bias enable */ + volatile unsigned int enrxrssi : 1; /**< RX RF Rssi enable */ + volatile unsigned int enrxref : 1; /**< RX RF Vref enable */ + volatile unsigned int enrxi2v : 1; /**< RX I2V enable */ + volatile unsigned int enrxmix : 1; /**< RX mixer enable */ + volatile unsigned int enlnacal : 1; /**< RX look back lna input enable */ + volatile unsigned int enlna : 1; /**< Rxfe lna enable */ + volatile unsigned int txvinsel : 1; /**< Txfe input selection(0,cal when need bypass TX filter,1:normal) */ + volatile unsigned int entssi : 1; /**< Txfe tssi enable */ + volatile unsigned int entssiadc : 1; /**< Txfe tssi adc enable */ + volatile unsigned int entxferef : 1; /**< Txfe reference enable */ + volatile unsigned int entxfebias : 1; /**< Txfe bias enable */ + volatile unsigned int entxv2i : 1; /**< Tx v2i enable */ + volatile unsigned int entxlo : 1; /**< Tx LO enable */ + volatile unsigned int entxpga : 1; /**< TX PGA enable */ + volatile unsigned int enpa : 1; /**< Tx PA enable */ + volatile unsigned int enrxsw : 1; /**< RX switch enable */ + volatile unsigned int entxsw : 1; /**< TX switch enable */ + volatile unsigned int trswpll : 1; /**< rf pll tx rx switch */ + volatile unsigned int enrfpll : 1; /**< rf pll enable */ + volatile unsigned int endobuler : 1; /**< dobuler enable */ + volatile unsigned int endpll : 1; /**< digital pll enable */ + volatile unsigned int enxtal : 1; /**< xtal enable signal */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0xE_TypeDef; + +/// REG0xF +typedef union +{ + struct + { + volatile unsigned int regbanksel : 1; /**< Register Bank Select. 0x0: Bank0 (Reg00~Reg14); ; 0x1: Bank1 (Reg16~Reg30) */ + volatile unsigned int clkdacsel : 1; /**< DAC Clock Select. 0x0: 80MHz; 0x1: 160MHz */ + volatile unsigned int clkadcsel : 1; /**< ADCClock Select. 0x0: 40MHz; 0x1: 80MHz */ + volatile unsigned int NC : 1; /**< NC */ + volatile unsigned int NC_ : 1; /**< NC */ + volatile unsigned int sinadtxen : 1; /**< TX Sinad Enable */ + volatile unsigned int sinadrxen : 1; /**< RX Sinad Detect Enable */ + volatile unsigned int tssicalen : 1; /**< TSSI Calibration Enable, enable 40M clock */ + volatile unsigned int NC__ : 5; /**< NC */ + volatile unsigned int sinadhpfcoef : 2; /**< HPF Coefficence for RX Siand Detect. 0x0: 1/8 0x1: 1/32; 0x2: 1/128; 0x3: 1/1024 */ + volatile unsigned int clkdacinv : 1; /**< DAC Clock Invert */ + volatile unsigned int clkadcinv : 1; /**< ADC Clock Invert */ + volatile unsigned int reserved : 11; /**< Reserved */ + volatile unsigned int sysldoen : 1; /**< enable sysldo */ + volatile unsigned int sysldolp : 1; /**< sysldo low power enable */ + volatile unsigned int endspvdd : 1; /**< dsp vdd enable */ + volatile unsigned int digldolp : 1; /**< digldo low power enable */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0xF_TypeDef; + +/// REG0x10 +typedef union +{ + struct + { + volatile unsigned int dacselection : 1; /**< 0: external dac, 1: internal dac */ + volatile unsigned int lpfrxbw : 1; /**< lpf rx bandwidth selection 1: high bandwidth(19MHz) 0: low bandwidth(9MHz); */ + volatile unsigned int lpftxbw : 1; /**< lpf tx bandwidth selection 1: high bandwidth(29MHz) 0: low bandwidth(14MHz); */ + volatile unsigned int lpftrxsw : 1; /**< LPF tx rx switch(1:tx,0:rx) */ + volatile unsigned int enlpf : 1; /**< LPF enable */ + volatile unsigned int enif : 1; /**< ADC, DAC Ldo enable */ + volatile unsigned int endcoc : 1; /**< DCOC DAC enable */ + volatile unsigned int enrxadc : 1; /**< RX ADC enable */ + volatile unsigned int entxdac : 1; /**< TX dac enable */ + volatile unsigned int entxdacbias : 1; /**< TX dac bias enable */ + volatile unsigned int enrxrssi : 1; /**< RX RF Rssi enable */ + volatile unsigned int enrxref : 1; /**< RX RF Vref enable */ + volatile unsigned int enrxi2v : 1; /**< RX I2V enable */ + volatile unsigned int enrxmix : 1; /**< RX mixer enable */ + volatile unsigned int enlnacal : 1; /**< RX look back lna input enable */ + volatile unsigned int enlna : 1; /**< Rxfe lna enable */ + volatile unsigned int txvinsel : 1; /**< Txfe input selection(0,cal when need bypass TX filter,1:normal) */ + volatile unsigned int entssi : 1; /**< Txfe tssi enable */ + volatile unsigned int entssiadc : 1; /**< Txfe tssi adc enable */ + volatile unsigned int entxferef : 1; /**< Txfe reference enable */ + volatile unsigned int entxfebias : 1; /**< Txfe bias enable */ + volatile unsigned int entxv2i : 1; /**< Tx v2i enable */ + volatile unsigned int entxlo : 1; /**< Tx LO enable */ + volatile unsigned int entxpga : 1; /**< TX PGA enable */ + volatile unsigned int enpa : 1; /**< Tx PA enable */ + volatile unsigned int enrxsw : 1; /**< RX switch enable */ + volatile unsigned int entxsw : 1; /**< TX switch enable */ + volatile unsigned int trswpll : 1; /**< rf pll tx rx switch */ + volatile unsigned int enrfpll : 1; /**< rf pll enable */ + volatile unsigned int endobuler : 1; /**< dobuler enable */ + volatile unsigned int endpll : 1; /**< digital pll enable */ + volatile unsigned int enxtal : 1; /**< xtal enable signal */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x10_TypeDef; + +/// REG0x11 +typedef union +{ + struct + { + volatile unsigned int txsinadtable : 11; /**< TX Sinad Table;D[0] = 0: Write I Path Table Data;D[0] = 1: Write Q Path Table Data;LSBD[1] ;Both I and Q need 16 number data */ + volatile unsigned int reserved : 21; /**< Reserved */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x11_TypeDef; + +/// REG0x12 +typedef union +{ + struct + { + volatile unsigned int lpfouttsten : 1; /**< lpf output test enable,0:disenable,1:enable */ + volatile unsigned int lpfintsten : 1; /**< lpf input test enable,0:disenable,1:enable */ + volatile unsigned int ifbufic20 : 3; /**< test buffer bias current control,0:low, 1:high */ + volatile unsigned int ifadcvcmsel : 2; /**< if adc reference voltage selection. */ + volatile unsigned int ldodpll10 : 2; /**< digital pll and xtal ldo voutselection. 00:low, 11:high */ + volatile unsigned int NC : 1; /**< Reserved bit; */ + volatile unsigned int buftstselection : 1; /**< buffer input selection:1:lpf, 0:rssidactst,rssitst,tssitst,adcstst1 */ + volatile unsigned int entstbufldo : 1; /**< enable test buffer ldo, 0:disenable,1:enable */ + volatile unsigned int NC_ : 1; /**< Reserved bit; */ + volatile unsigned int dldovctrl10 : 2; /**< dig do output control voltage: 0:1.2V 0.1V/step */ + volatile unsigned int adcinSel : 1; /**< SAR ADC input selection;0:TSSI, 1:Temperature */ + volatile unsigned int adciselr20 : 3; /**< adc reference bias current selection,0:0.45x,1:0.5x,2:0.55X,3:0.6x,4:0.9x,5:1X,6:1.1X,7:1.2X */ + volatile unsigned int adciselc20 : 3; /**< adc core bias current selection,0:5x,1:0.6x,2:0.7X,3:0.8x,4:1.0x,5:1.2X,6:1.4X,7:1.7X */ + volatile unsigned int adcrefbwsel : 1; /**< adc bandwidth selection.0:40MHz, 1:80MHz */ + volatile unsigned int adcten : 1; /**< adc test enable(1:only I work, 0:both path work) */ + volatile unsigned int fictrl30 : 4; /**< lpf bias current selection, 0:low, 15:high */ + volatile unsigned int flvcm10 : 2; /**< lpf common mode voltage selection,00:low , 11: high */ + volatile unsigned int ldoifsel3v10 : 2; /**< If ldo vout selection:00:low, 11: high */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x12_TypeDef; + +/// REG0x13 +typedef union +{ + struct + { + volatile unsigned int r2rx10 : 2; /**< rx mode loopfilter R2 control */ + volatile unsigned int c1rx10 : 2; /**< rx mode loopfilter C1 control */ + volatile unsigned int rzrx40 : 5; /**< rx mode loopfilter Rz control */ + volatile unsigned int icprx40 : 5; /**< rx mode cp current control */ + volatile unsigned int icpoff20 : 3; /**< cp offset current control */ + volatile unsigned int icpsel : 1; /**< icp bias select: 0, internal; 1, external */ + volatile unsigned int r2tx10 : 2; /**< tx mode loopfilter R2 control */ + volatile unsigned int c1tx10 : 2; /**< tx mode loopfilter C1 control */ + volatile unsigned int rztx40 : 5; /**< tx mode loopfilter Rz control */ + volatile unsigned int icptx40 : 5; /**< tx mode cp current control */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x13_TypeDef; + +/// REG0x14 +typedef union +{ + struct + { + volatile unsigned int dci0db : 8; /**< RX dcoc I path input for 0dB of PGA */ + volatile unsigned int dcq0db : 8; /**< RX dcoc Q path input for 0dB of PGA */ + volatile unsigned int dci3db : 8; /**< RX dcoc I path input for 3dB of PGA */ + volatile unsigned int dcq3db : 8; /**< RX dcoc Q path input for 3dB of PGA */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x14_TypeDef; + +/// REG0x15 +typedef union +{ + struct + { + volatile unsigned int dci6db : 8; /**< RX dcoc I path input for 6dB of PGA */ + volatile unsigned int dcq6db : 8; /**< RX dcoc Q path input for 6dB of PGA */ + volatile unsigned int dci9db : 8; /**< RX dcoc I path input for 9dB of PGA */ + volatile unsigned int dcq9db : 8; /**< RX dcoc Q path input for 9dB of PGA */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x15_TypeDef; + +/// REG0x16 +typedef union +{ + struct + { + volatile unsigned int dci12db : 8; /**< RX dcoc I path input for 12dB of PGA */ + volatile unsigned int dcq12db : 8; /**< RX dcoc Q path input for 12dB of PGA */ + volatile unsigned int dci15db : 8; /**< RX dcoc I path input for 15dB of PGA */ + volatile unsigned int dcq15db : 8; /**< RX dcoc Q path input for 15dB of PGA */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x16_TypeDef; + +/// REG0x17 +typedef union +{ + struct + { + volatile unsigned int dci18db : 8; /**< RX dcoc I path input for 18dB of PGA */ + volatile unsigned int dcq18db : 8; /**< RX dcoc Q path input for 18dB of PGA */ + volatile unsigned int dci21db : 8; /**< RX dcoc I path input for 21dB of PGA */ + volatile unsigned int dcq21db : 8; /**< RX dcoc Q path input for 21dB of PGA */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x17_TypeDef; + +/// REG0x18 +typedef union +{ + struct + { + volatile unsigned int dci24db : 8; /**< RX dcoc I path input for 24dB of PGA */ + volatile unsigned int dcq24db : 8; /**< RX dcoc Q path input for 24dB of PGA */ + volatile unsigned int dci27db : 8; /**< RX dcoc I path input for 27dB of PGA */ + volatile unsigned int dcq27db : 8; /**< RX dcoc Q path input for 27dB of PGA */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x18_TypeDef; + +/// REG0x19 +typedef union +{ + struct + { + volatile unsigned int dci30db : 8; /**< RX dcoc I path input for 30dB of PGA */ + volatile unsigned int dcq30db : 8; /**< RX dcoc Q path input for 30dB of PGA */ + volatile unsigned int dci33db : 8; /**< RX dcoc I path input for 33dB of PGA */ + volatile unsigned int dcq33db : 8; /**< RX dcoc Q path input for 33dB of PGA */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x19_TypeDef; + +/// REG0x1A +typedef union +{ + struct + { + volatile unsigned int dci36db : 8; /**< RX dcoc I path input for 36dB of PGA */ + volatile unsigned int dcq36db : 8; /**< RX dcoc Q path input for 36dB of PGA */ + volatile unsigned int dci39db : 8; /**< RX dcoc I path input for 39dB of PGA */ + volatile unsigned int dcq39db : 8; /**< RX dcoc Q path input for 39dB of PGA */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x1A_TypeDef; + +/// REG0x1B +typedef union +{ + struct + { + volatile unsigned int dci42db : 8; /**< RX dcoc I path input for 42dB of PGA */ + volatile unsigned int dcq42db : 8; /**< RX dcoc Q path input for 42dB of PGA */ + volatile unsigned int dci45db : 8; /**< RX dcoc I path input for 45dB of PGA */ + volatile unsigned int dcq45db : 8; /**< RX dcoc Q path input for 45dB of PGA */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x1B_TypeDef; + +/// REG0x1C +typedef union +{ + struct + { + volatile unsigned int dacoutqspi90 : 10; /**< DAC Q channel input in analog test only; */ + volatile unsigned int NC : 2; /**< Reserved bits; */ + volatile unsigned int dacoutispi90 : 10; /**< DAC I channel input in analog test only; */ + volatile unsigned int NC_ : 10; /**< Reserved bits; */ + } bits; + volatile unsigned int value; +} BK7011_TRxV2A_REG0x1C_TypeDef; // trx reg28 just for test +#define BK7011_TRxV2ABASE 0X00800080 + +/// BK7011TRxV2A +struct BK7011TRxV2A_TypeDef +{ + volatile BK7011_TRxV2A_REG0x0_TypeDef *REG0x0; + volatile BK7011_TRxV2A_REG0x1_TypeDef *REG0x1; + volatile BK7011_TRxV2A_REG0x2_TypeDef *REG0x2; + volatile BK7011_TRxV2A_REG0x3_TypeDef *REG0x3; + volatile BK7011_TRxV2A_REG0x4_TypeDef *REG0x4; + volatile BK7011_TRxV2A_REG0x5_TypeDef *REG0x5; + volatile BK7011_TRxV2A_REG0x6_TypeDef *REG0x6; + volatile BK7011_TRxV2A_REG0x7_TypeDef *REG0x7; + volatile BK7011_TRxV2A_REG0x8_TypeDef *REG0x8; + volatile BK7011_TRxV2A_REG0x9_TypeDef *REG0x9; + volatile BK7011_TRxV2A_REG0xA_TypeDef *REG0xA; + volatile BK7011_TRxV2A_REG0xB_TypeDef *REG0xB; + volatile BK7011_TRxV2A_REG0xC_TypeDef *REG0xC; + volatile BK7011_TRxV2A_REG0xD_TypeDef *REG0xD; + volatile BK7011_TRxV2A_REG0xE_TypeDef *REG0xE; + volatile BK7011_TRxV2A_REG0xF_TypeDef *REG0xF; + volatile BK7011_TRxV2A_REG0x10_TypeDef *REG0x10; + volatile BK7011_TRxV2A_REG0x11_TypeDef *REG0x11; + volatile BK7011_TRxV2A_REG0x12_TypeDef *REG0x12; + volatile BK7011_TRxV2A_REG0x13_TypeDef *REG0x13; + volatile BK7011_TRxV2A_REG0x14_TypeDef *REG0x14; + volatile BK7011_TRxV2A_REG0x15_TypeDef *REG0x15; + volatile BK7011_TRxV2A_REG0x16_TypeDef *REG0x16; + volatile BK7011_TRxV2A_REG0x17_TypeDef *REG0x17; + volatile BK7011_TRxV2A_REG0x18_TypeDef *REG0x18; + volatile BK7011_TRxV2A_REG0x19_TypeDef *REG0x19; + volatile BK7011_TRxV2A_REG0x1A_TypeDef *REG0x1A; + volatile BK7011_TRxV2A_REG0x1B_TypeDef *REG0x1B; + volatile BK7011_TRxV2A_REG0x1C_TypeDef *REG0x1C; +}; +#endif + +/// POWER +typedef struct +{ + unsigned int rega_8_11 : 4; + unsigned int regc_0_2 : 3; + unsigned int regc_4_6 : 3; + unsigned int regc_8_10 : 3; + unsigned int regb_28_31 : 4; + unsigned int pregain : 5; + unsigned int unuse : 10; +} PWR_REGS; + +/******************************************************************************* +* Function Declarations +*******************************************************************************/ +#endif // (CFG_SOC_NAME == SOC_BK7231) + +#endif // _BK7231_CAL_H_ \ No newline at end of file diff --git a/beken_os/beken378/func/bk7011_cal/manual_cal_bk7231.c b/beken_os/beken378/func/bk7011_cal/manual_cal_bk7231.c new file mode 100755 index 0000000..cb3a097 --- /dev/null +++ b/beken_os/beken378/func/bk7011_cal/manual_cal_bk7231.c @@ -0,0 +1,1870 @@ +#include "include.h" + +#if (CFG_SOC_NAME == SOC_BK7231) +#include "arm_arch.h" +#if CFG_SUPPORT_MANUAL_CALI +#include "target_util_pub.h" +#include "mem_pub.h" + +#include "drv_model_pub.h" +#include "sys_ctrl_pub.h" +#include "phy.h" + +#include "bk7011_cal_pub.h" +#include "bk7011_cal.h" + +#include +#include "flash_pub.h" +#include "temp_detect_pub.h" +#include "saradc_pub.h" +#include "param_config.h" + +#include "rtos_pub.h" +#if CFG_SUPPORT_ALIOS +#include "hal/soc/soc.h" +#else +#include "BkDriverFlash.h" +#endif +#include "power_save_pub.h" + +#define TXPWR_DEFAULT_TAB 1 + +/* support max work cuurent<250mA@3.3V */ +#define CFG_SUPPORT_LOW_MAX_CURRENT 1 + +#define MCAL_SAVE_MAC_ADDR 1 + +#define WLAN_2_4_G_CHANNEL_NUM (14) +#define MAX_RATE_FOR_B_5M (5) // 5.5M +#define MAX_RATE_FOR_B (11) // 11M +#define MAX_RATE_FOR_G (54) // 54M +#define MAX_RATE_MIX_N (128) // MCS0 +#define MAX_RATE_FOR_N (135) // MCS7 + +#define MOD_DIST_G_BW_N20 (2) +#define MOD_DIST_G_BW_N40 (4) + +#define TXPWR_ELEM_INUSED (0) +#define TXPWR_ELEM_UNUSED (1) + +#define BK_FLASH_SECTOR_SIZE (4*1024) +#define BK_FLASH_WRITE_CHECK_TIMES 3 + +#define MCAL_DEBUG 0 +#include "uart_pub.h" +#if MCAL_DEBUG +#define MCAL_PRT null_prf +#define MCAL_WARN os_printf +#define MCAL_FATAL fatal_prf +#else +#define MCAL_PRT null_prf +#define MCAL_WARN null_prf +#define MCAL_FATAL null_prf +#endif + +#define BK_FLASH_OPT_TLV_HEADER (0x00564c54) // ASIC TLV +typedef enum{ + TXID = 0x11111100, + TXPWR_TAB_TAB = 0x22222200, + TXEND = 0xeeeeeeee, + TXNON = 0xffffffff +}TXSTRUCT; + +#define DEFAULT_TXID_ID (12345678) +#define DEFAULT_TXID_THERMAL (360) +#define DEFAULT_TXID_CHANNEL (22222222) +#undef DEFAULT_TXID_XTAL +#define DEFAULT_TXID_XTAL (33333333) +typedef enum{ + TXID_ID = TXID+1, + TXID_MAC, + TXID_THERMAL, + TXID_CHANNEL, + TXID_XTAL, + TXID_ADC, + TXID_END, + TXID_NON = TXID+0xFF +}TXIDList; + +typedef enum{ + TXPWR_ENABLE_ID = TXPWR_TAB_TAB+1, + TXPWR_TAB_B_ID, + TXPWR_TAB_G_ID, + TXPWR_TAB_N_ID, + TXPWR_TAB_DIF_GN20_ID, + TXPWR_TAB_DIF_GN40_ID, + TXPWR_END, + TXPWR_NON = TXPWR_TAB_TAB+0xFF +}TXPWR_ELEM_ID; + +typedef enum { + TXPWR_NONE_RD = 0u, + TXPWR_TAB_B_RD = 0x1u, + TXPWR_TAB_G_RD = 0x2u, + TXPWR_TAB_N_RD = 0x4u, +} TXPWR_IS_RD; + + +/* bit[7]: TXPWR flag + * 0: invalid + * 1: used + * bit[4:0]: 5bit TXPWR pwr_gain; + */ +#define FLAG_MASK (0x1u) +#define FLAG_POSI (7) +#define GAIN_MASK (0x1fu) +#define GET_TXPWR_GAIN(p) ((p)->value & GAIN_MASK) +#define SET_TXPWR_GAIN(p, gain) {(p)->value &= (~GAIN_MASK); \ + (p)->value |= (gain&GAIN_MASK);} + +#define GET_TXPWR_FLAG(p) (((p)->value>>FLAG_POSI)&FLAG_MASK) +#define SET_TXPWR_FLAG(p, flag) {(p)->value &= (~(FLAG_MASK<value |= ((flag&FLAG_MASK)< WLAN_2_4_G_CHANNEL_NUM)) { + MCAL_WARN("Manual cal wrong channel:%d\r\n", channel); + return; + } + + channel -= 1; + + if((rate <= MAX_RATE_FOR_B_5M) || (rate == MAX_RATE_FOR_B)) { + txpwr_tab_ptr = >xpwr_tab_b[channel]; + } else if(rate <= MAX_RATE_FOR_G) { + txpwr_tab_ptr = >xpwr_tab_g[channel]; + is_g_rate = 1; + } else if(rate <= MAX_RATE_FOR_N && rate >= MAX_RATE_MIX_N) { + txpwr_tab_ptr = >xpwr_tab_n_40[channel]; + } else { + MCAL_FATAL("Manual cal wrong rate:%d\r\n", rate); + return; + } + + SET_TXPWR_GAIN(txpwr_tab_ptr, pwr_gain); + SET_TXPWR_FLAG(txpwr_tab_ptr, TXPWR_ELEM_INUSED); + + if(is_g_rate) { + // need save n20 + os_memcpy(>xpwr_tab_n[channel], >xpwr_tab_g[channel], sizeof(TXPWR_ST)); + manual_cal_adjust_fitting(>xpwr_tab_n[channel], g_dif_g_n20); + MCAL_PRT("fit n20 tab with dist:%d\r\n", g_dif_g_n20); + } +} + +#if CFG_SUPPORT_LOW_MAX_CURRENT//Max default work current<250mA@3.3V + const UINT16 shift_tab_b[4] = {0, 0, 0, 0}; // 11M base,5.5M,2M,1M + const UINT16 shift_tab_g[8] = {0, 2, 4, 4, 4, 4, 4, 4}; // 54M base - 6M + const UINT16 shift_tab_n[1] = {0}; // for MCS7 +#else + const UINT16 shift_tab_b[4] = {0, 2, 4, 6}; // 11M base,5.5M,2M,1M + const UINT16 shift_tab_g[8] = {0, 2, 4, 6, 8, 10, 12, 14}; // 54M base - 6M + const UINT16 shift_tab_n[1] = {0}; // for MCS7 +#endif + +UINT32 manual_cal_get_pwr_idx_shift(UINT32 rate, UINT32 bandwidth, UINT32 *pwr_gain) +{ + const UINT16 *shift; + UINT32 idex, ret = 2; + + if(bandwidth == PHY_CHNL_BW_20) + { + if(rate <= 3){ + shift = shift_tab_b; + idex = 3 - rate; + ret = 1; + } + else if(rate <= 11 ){ // for g: 6-54M -- 3-11 + shift = shift_tab_g; + idex = 11 - rate; + }else if((rate >= 128) && (rate < 135)){ // for MCS0-6 + shift = shift_tab_g; + idex = 134 - rate; + }else if(rate == 135){ // for MCS7 + shift = shift_tab_n; + idex = 0; + }else{ + MCAL_FATAL("\r\nget_pwr_idx_shift wrong rate:%d\r\n", rate); + return 0; + } + } + else { + if((rate >= 128) && (rate < 135)){ + shift = shift_tab_g; + idex = 134 - rate; + }else if(rate == 135){ // for MCS7 + shift = shift_tab_n; + idex = 0; + }else{ + MCAL_FATAL("\r\nget_pwr_idx_shift wrong rate:%d\r\n", rate); + return 0; + } + } + + MCAL_PRT("get_pwr_info: idx: %d, pwr:%d", shift[idex], *pwr_gain); + + idex = shift[idex] + *pwr_gain; + *pwr_gain = (idex > 31)? 31: idex; + + MCAL_PRT("--pwr:%d\r\n", *pwr_gain); + + return ret; +} + +int manual_cal_get_txpwr(UINT32 rate, UINT32 channel, UINT32 bandwidth, UINT32 *pwr_gain) +{ + TXPWR_PTR txpwr_tab_ptr = NULL; + + if((channel == 0) || (channel > WLAN_2_4_G_CHANNEL_NUM)) { + MCAL_WARN("Manual cal wrong channel:%d\r\n", channel); + return 0; + } + + if((bandwidth != PHY_CHNL_BW_20) && (bandwidth != PHY_CHNL_BW_40)) { + MCAL_WARN("Manual cal wrong bandwidth:%d\r\n", bandwidth); + return 0; + } + + channel -= 1; + + if(bandwidth == PHY_CHNL_BW_20) { + if((rate <= MAX_RATE_FOR_B_5M) || (rate == MAX_RATE_FOR_B)) { + txpwr_tab_ptr = >xpwr_tab_b[channel]; + } else if(rate < MAX_RATE_FOR_N) { + // MAX_RATE_FOR_N is right, for only MCS7 need change + txpwr_tab_ptr = >xpwr_tab_g[channel]; + } else if(rate == MAX_RATE_FOR_N){ + txpwr_tab_ptr = >xpwr_tab_n[channel]; + } else { + MCAL_FATAL("\r\nManual cal wrong rate:%d\r\n", rate); + return 0; + } + } else { + if(rate < MAX_RATE_FOR_N && rate >= MAX_RATE_MIX_N) { + // MAX_RATE_FOR_N is right, for only MCS7 need change + txpwr_tab_ptr = >xpwr_tab_g[channel]; + } else if(rate == MAX_RATE_FOR_N) { + // MAX_RATE_FOR_N_40 + txpwr_tab_ptr = >xpwr_tab_n_40[channel]; + } else { + MCAL_FATAL("\r\nManual cal wrong rate with BW40? %d:%d\r\n", bandwidth, rate); + txpwr_tab_ptr = >xpwr_tab_g[channel]; + } + } + + *pwr_gain = GET_TXPWR_GAIN(txpwr_tab_ptr); + MCAL_PRT("get txpwrtab gain:%d,ch:%d\r\n", *pwr_gain, channel+1); + + return 1; +} + + +void manual_cal_show_txpwr_tab(void) +{ + TXPWR_PTR txpwr_tab_ptr = NULL; + UINT32 i; + + MCAL_PRT("txpwr table for b:\r\n"); + for(i=0; ivalue, + GET_TXPWR_FLAG(txpwr_tab_ptr), GET_TXPWR_GAIN(txpwr_tab_ptr)); + } + + MCAL_PRT("\r\ntxpwr table for g:\r\n"); + for(i=0; ivalue, + GET_TXPWR_FLAG(txpwr_tab_ptr), GET_TXPWR_GAIN(txpwr_tab_ptr)); + } + + MCAL_PRT("\r\ntxpwr table for n20:\r\n"); + for(i=0; ivalue, + GET_TXPWR_FLAG(txpwr_tab_ptr), GET_TXPWR_GAIN(txpwr_tab_ptr)); + } + + MCAL_PRT("\r\ntxpwr table for n40:\r\n"); + for(i=0; ivalue, + GET_TXPWR_FLAG(txpwr_tab_ptr), GET_TXPWR_GAIN(txpwr_tab_ptr)); + } + + MCAL_PRT("\r\n sys temper:%d\r\n", g_cur_temp); +} + +TXPWR_IS_RD manual_cal_txpwr_tab_is_fitted(void) +{ + return (TXPWR_TAB_B_RD | TXPWR_TAB_G_RD | TXPWR_TAB_N_RD); +} + +static void manual_cal_adjust_fitting(TXPWR_PTR ptr, UINT16 dist) +{ + UINT16 gain; + //if(GET_TXPWR_FLAG(ptr) == TXPWR_ELEM_UNUSED) + // return; + + gain = GET_TXPWR_GAIN(ptr); + gain = (gain > dist)? gain - dist : 0; + + SET_TXPWR_GAIN(ptr, gain); +} + +static void manual_cal_do_fitting_base(TXPWR_PTR dst, TXPWR_PTR srclow, TXPWR_PTR srchigh) +{ + UINT16 gain = 0, dist; + + if((GET_TXPWR_FLAG(srclow) == TXPWR_ELEM_UNUSED) + || (GET_TXPWR_FLAG(srchigh) == TXPWR_ELEM_UNUSED)) + return; + + if(GET_TXPWR_GAIN(srclow) > GET_TXPWR_GAIN(srchigh)) { + dist = GET_TXPWR_GAIN(srclow) - GET_TXPWR_GAIN(srchigh); + gain = (UINT16)((float)(dist) / 3.0 + 0.5) + GET_TXPWR_GAIN(srchigh) + 1; + //gain = (UINT16)((float)(dist) / 2.0 + 0.5) + GET_TXPWR_GAIN(srchigh); + } + else { + dist = GET_TXPWR_GAIN(srchigh) - GET_TXPWR_GAIN(srclow); + gain = (UINT16)((float)(dist) / 3.0 + 0.5) + GET_TXPWR_GAIN(srclow) + 1; + //gain = (UINT16)((float)(dist) / 2.0 + 0.5) + GET_TXPWR_GAIN(srclow); + } + + SET_TXPWR_GAIN(dst, gain); + SET_TXPWR_FLAG(dst, TXPWR_ELEM_INUSED); +} + +static void manual_cal_do_fitting(TXPWR_PTR dst, TXPWR_PTR srclow, TXPWR_PTR srchigh) +{ + UINT16 gain = 0; + + if((GET_TXPWR_FLAG(srclow) == TXPWR_ELEM_UNUSED) + || (GET_TXPWR_FLAG(srchigh) == TXPWR_ELEM_UNUSED)) + return; + + gain = (UINT16)((float)(GET_TXPWR_GAIN(srclow) + GET_TXPWR_GAIN(srchigh)) / 2 + 0.5); + SET_TXPWR_GAIN(dst, gain); + SET_TXPWR_FLAG(dst, TXPWR_ELEM_INUSED); +} + +UINT32 manual_cal_fitting_txpwr_tab(void) +{ + UINT32 ret = 0, i; + TXPWR_PTR tab_ptr = NULL; + + // for b, check ch1, ch7, ch13 is in used + tab_ptr = gtxpwr_tab_b; + if((GET_TXPWR_FLAG(&tab_ptr[0]) == TXPWR_ELEM_UNUSED) + ||(GET_TXPWR_FLAG(&tab_ptr[12]) == TXPWR_ELEM_UNUSED) ){ + MCAL_WARN("txpwr table for b fitting failed!, ch1 ch13 unused\r\n"); + } else { + if(GET_TXPWR_FLAG(&tab_ptr[6]) == TXPWR_ELEM_UNUSED) { + // fitting ch7, use ch1, ch13 + manual_cal_do_fitting_base(&tab_ptr[6], &tab_ptr[0], &tab_ptr[12]); + } + // fitting ch4, use ch1, ch7 + manual_cal_do_fitting(&tab_ptr[3], &tab_ptr[0], &tab_ptr[6]); + // fitting ch2, use ch1, ch4 + manual_cal_do_fitting(&tab_ptr[1], &tab_ptr[0], &tab_ptr[3]); + // fitting ch3, use ch2, ch4 + manual_cal_do_fitting(&tab_ptr[2], &tab_ptr[1], &tab_ptr[3]); + // fitting ch5, use ch4, ch7 + manual_cal_do_fitting(&tab_ptr[4], &tab_ptr[3], &tab_ptr[6]); + // fitting ch6, use ch5, ch7 + manual_cal_do_fitting(&tab_ptr[5], &tab_ptr[4], &tab_ptr[6]); + + // fitting ch10, use ch7, ch13 + manual_cal_do_fitting(&tab_ptr[9], &tab_ptr[6], &tab_ptr[12]); + // fitting ch8, use ch7, ch10 + manual_cal_do_fitting(&tab_ptr[7], &tab_ptr[6], &tab_ptr[9]); + // fitting ch9, use ch8, ch10 + manual_cal_do_fitting(&tab_ptr[8], &tab_ptr[7], &tab_ptr[9]); + // fitting ch11, use ch10, ch13 + manual_cal_do_fitting(&tab_ptr[10], &tab_ptr[9], &tab_ptr[12]); + // fitting ch12, use ch11, ch13 + manual_cal_do_fitting(&tab_ptr[11], &tab_ptr[10], &tab_ptr[12]); + + // fitting ch14, the same as ch13 + manual_cal_do_fitting(&tab_ptr[13], &tab_ptr[12], &tab_ptr[12]); + + // clear flag, only base change set used + for(i=0; i 31) + diff = 31; + + g_dif_g_n20 = (diff&GAIN_MASK); + manual_cal_fit_txpwr_tab_n_20(g_dif_g_n20); +} + +void manual_cal_set_dif_g_n40(UINT32 diff) +{ + if(diff == g_dif_g_n40) { + MCAL_PRT("no need to do, same with g_dif_g_n40:%d\r\n", g_dif_g_n40); + return; + } + + if(diff > 31) + diff = 31; + + g_dif_g_n40 = (diff&GAIN_MASK); + manual_cal_fit_txpwr_tab_n_40(g_dif_g_n40); +} + +//////////////////////////////////////////////////////////////////////////////// +static UINT32 manual_cal_search_opt_tab(UINT32 *len) +{ + UINT32 ret = 0, status; + DD_HANDLE flash_handle; + TXPWR_ELEM_ST head; + #if CFG_SUPPORT_ALIOS + hal_logic_partition_t *pt = hal_flash_get_info(HAL_PARTITION_RF_FIRMWARE); + #else + bk_logic_partition_t *pt = bk_flash_get_info(BK_PARTITION_RF_FIRMWARE); + #endif + + *len = 0; + flash_handle = ddev_open(FLASH_DEV_NAME, &status, 0); + ddev_read(flash_handle, (char *)&head, sizeof(TXPWR_ELEM_ST), pt->partition_start_addr);//TXPWR_TAB_FLASH_ADDR); + if(BK_FLASH_OPT_TLV_HEADER == head.type){ + *len = head.len + sizeof(TAG_TXPWR_ST); + ret = 1; + } + ddev_close(flash_handle); + + return ret; +} + +static UINT32 manual_cal_search_txpwr_tab(UINT32 type, UINT32 start_addr) +{ + UINT32 status, addr, end_addr; + DD_HANDLE flash_handle; + TXPWR_ELEM_ST head; + + status = manual_cal_search_opt_tab(&addr); + if(!status) { + return 0; + } + + flash_handle = ddev_open(FLASH_DEV_NAME, &status, 0); + ddev_read(flash_handle, (char *)&head, sizeof(TXPWR_ELEM_ST), start_addr); + addr = start_addr + sizeof(TXPWR_ELEM_ST); + end_addr = addr + head.len; + while(addr < end_addr) { + ddev_read(flash_handle, (char *)&head, sizeof(TXPWR_ELEM_ST), addr); + if(type == head.type){ + break; + } else { + addr += sizeof(TXPWR_ELEM_ST); + addr += head.len; + } + } + + if(addr >= end_addr) { + addr = 0; + } + ddev_close(flash_handle); + + return addr; +} + +static UINT8 manual_cal_update_flash_area(UINT32 addr_offset, char *buf, UINT32 len) +{ + DD_HANDLE flash_handle = DD_HANDLE_UNVALID; + UINT32 param, status, write_len, write_addr, flash_len; + UINT8 ret = 0; + UINT8 *read_buf = NULL; + UINT8 check_times = BK_FLASH_WRITE_CHECK_TIMES; + #if CFG_SUPPORT_ALIOS + hal_logic_partition_t *pt = hal_flash_get_info(HAL_PARTITION_RF_FIRMWARE); + #else + bk_logic_partition_t *pt = bk_flash_get_info(BK_PARTITION_RF_FIRMWARE); + #endif + + if(addr_offset > (BK_FLASH_SECTOR_SIZE)){ + MCAL_FATAL("write flash addroffset error:%08x\r\n", addr_offset); + return 1; + } + if(len == 0) + return 0; + + status = manual_cal_search_opt_tab(&flash_len); + if(status && (flash_len >= (addr_offset + len))) { + // read all flash otp + write_len = flash_len; + } else { + write_len = addr_offset + len; + } + + write_addr = pt->partition_start_addr;//TXPWR_TAB_FLASH_ADDR; + + read_buf = (UINT8*)os_malloc(write_len); + if(!read_buf){ + MCAL_FATAL("cann't malloc buf for flash write\r\n"); + ret = 1; + goto updata_exit; + } + + flash_handle = ddev_open(FLASH_DEV_NAME, &status, 0); + +write_again: + if(addr_offset) { + status = ddev_read(flash_handle, read_buf, write_len, write_addr); + if(status != FLASH_SUCCESS) { + MCAL_FATAL("cann't read flash before write\r\n"); + ret = 1; + goto updata_exit; + } + } + + os_memcpy(read_buf+addr_offset, buf, len); + + hal_flash_lock(); + #if CFG_SUPPORT_ALIOS + hal_flash_dis_secure(0, 0, 0); + #else + bk_flash_enable_security(FLASH_PROTECT_NONE); + #endif + + param = write_addr; + ddev_control(flash_handle, CMD_FLASH_ERASE_SECTOR, ¶m); + + status = ddev_write(flash_handle, (char *)read_buf, write_len, write_addr); + + if(status != FLASH_SUCCESS) { + MCAL_FATAL("save txpwr tab to flash failed\r\n"); + ret = 1; + hal_flash_unlock(); + goto updata_exit; + } + + #if CFG_SUPPORT_ALIOS + hal_flash_enable_secure(0, 0, 0); + #else + bk_flash_enable_security(FLASH_PROTECT_ALL); + #endif + hal_flash_unlock(); + + { + UINT8 *check_buf = read_buf, *org_buf = (UINT8 *)buf; + UINT32 check_addr = write_addr + addr_offset; + UINT8 check_result; + + os_memset(check_buf, 0, len); + + status = ddev_read(flash_handle, check_buf, len, check_addr); + if(status != FLASH_SUCCESS) { + MCAL_FATAL("cann't read flash in check\r\n"); + ret = 1; + goto updata_exit; + } + + check_result = 1; + for(int i=0; i (BK_FLASH_SECTOR_SIZE)){ + MCAL_FATAL("read flash addr error:%08x\r\n", addr_offset); + return 0; + } + + addr = pt->partition_start_addr+addr_offset;//TXPWR_TAB_FLASH_ADDR + addr_offset; + + flash_handle = ddev_open(FLASH_DEV_NAME, &status, 0); + status = ddev_read(flash_handle, buf, len, addr); + ddev_close(flash_handle); + + if(status != FLASH_SUCCESS) + ret = 0; + else + ret = len; + + return ret; +} + +UINT32 manual_cal_load_txpwr_tab_flash(void) +{ + UINT32 status, addr, addr_start; + DD_HANDLE flash_handle; + TXPWR_ELEM_ST head; + TXPWR_IS_RD is_ready_flash = 0; + #if CFG_SUPPORT_ALIOS + hal_logic_partition_t *pt = hal_flash_get_info(HAL_PARTITION_RF_FIRMWARE); + #else + bk_logic_partition_t *pt = bk_flash_get_info(BK_PARTITION_RF_FIRMWARE); + #endif + + addr_start = manual_cal_search_txpwr_tab(TXPWR_TAB_TAB, pt->partition_start_addr);//TXPWR_TAB_FLASH_ADDR); + if(!addr_start) { + MCAL_WARN("NO TXPWR_TAB_TAB found in flash\r\n"); + return TXPWR_NONE_RD; + } + + addr = manual_cal_search_txpwr_tab(TXPWR_ENABLE_ID, addr_start); + if(!addr) + { + MCAL_WARN("NO TXPWR_ENABLE_ID found in flash\r\n"); + return TXPWR_NONE_RD; + } + + flash_handle = ddev_open(FLASH_DEV_NAME, &status, 0); + ddev_read(flash_handle, (char *)&head, sizeof(TXPWR_ELEM_ST), addr); + ddev_read(flash_handle, (char *)&status, head.len, addr + sizeof(TXPWR_ELEM_ST)); + is_ready_flash = status; + MCAL_PRT("flash txpwr table:0x%x\r\n", is_ready_flash); + + // If txpwr tab in flash is unused, we should use auto calibration result + if(is_ready_flash == TXPWR_NONE_RD){ + MCAL_WARN("txpwr tabe in flash is unused\r\n"); + return TXPWR_NONE_RD; + } + + // for txpwr b + if(is_ready_flash & TXPWR_TAB_B_RD) { + addr = manual_cal_search_txpwr_tab(TXPWR_TAB_B_ID, addr_start); + if(addr) { + ddev_read(flash_handle, (char *)&head, sizeof(TXPWR_ELEM_ST), addr); + ddev_read(flash_handle, (char *)gtxpwr_tab_b, head.len, addr + sizeof(TXPWR_ELEM_ST)); + }else { + MCAL_WARN("txpwr tabe b in flash no found\r\n"); + } + } + + // for txpwr g and n20? + if(is_ready_flash & TXPWR_TAB_G_RD) { + //for g first + addr = manual_cal_search_txpwr_tab(TXPWR_TAB_G_ID, addr_start); + if(addr) { + ddev_read(flash_handle, (char *)&head, sizeof(TXPWR_ELEM_ST), addr); + ddev_read(flash_handle, (char *)gtxpwr_tab_g, head.len, addr + sizeof(TXPWR_ELEM_ST)); + } else { + MCAL_WARN("txpwr tabe g in flash no found\r\n"); + } + + // for n20 + addr = manual_cal_search_txpwr_tab(TXPWR_TAB_DIF_GN20_ID, addr_start); + if(addr) { + ddev_read(flash_handle, (char *)&head, sizeof(TXPWR_ELEM_ST), addr); + ddev_read(flash_handle, (char *)&g_dif_g_n20, head.len, addr + sizeof(TXPWR_ELEM_ST)); + MCAL_PRT("dif g and n20 ID in flash:%d\r\n", g_dif_g_n20); + } else { + MCAL_WARN("dif g and n20 ID in flash no found, use def:%d\r\n", g_dif_g_n20); + } + manual_cal_fit_txpwr_tab_n_20(g_dif_g_n20); + } + + // for txpwr N40 + if(is_ready_flash & TXPWR_TAB_N_RD) { + addr = manual_cal_search_txpwr_tab(TXPWR_TAB_N_ID, addr_start); + if(addr) { + ddev_read(flash_handle, (char *)&head, sizeof(TXPWR_ELEM_ST), addr); + ddev_read(flash_handle, (char *)gtxpwr_tab_n_40, head.len, addr + sizeof(TXPWR_ELEM_ST)); + }else { + MCAL_WARN("txpwr tabe n in flash no found\r\n"); + } + } + // only need load dist40 + addr = manual_cal_search_txpwr_tab(TXPWR_TAB_DIF_GN40_ID, addr_start); + if(addr) { + ddev_read(flash_handle, (char *)&head, sizeof(TXPWR_ELEM_ST), addr); + ddev_read(flash_handle, (char *)&g_dif_g_n40, head.len, addr + sizeof(TXPWR_ELEM_ST)); + MCAL_PRT("dif g and n40 ID in flash:%d\r\n", g_dif_g_n40); + } else { + MCAL_WARN("dif g and n40 ID in flash no found, use def:%d\r\n", g_dif_g_n40); + } + + ddev_close(flash_handle); + MCAL_PRT("read txpwr tab from flash success\r\n"); + + return is_ready_flash; +} + +UINT32 manual_cal_load_default_txpwr_tab(UINT32 is_ready_flash) +{ + #if TXPWR_DEFAULT_TAB + if(!(is_ready_flash & TXPWR_TAB_B_RD)) { + os_memcpy(gtxpwr_tab_b, gtxpwr_tab_def_b, sizeof(gtxpwr_tab_def_b)); + MCAL_WARN("Load default txpwr for b:%p\r\n", gtxpwr_tab_def_b); + } + + if(!(is_ready_flash & TXPWR_TAB_G_RD)) { + os_memcpy(gtxpwr_tab_g, gtxpwr_tab_def_g, sizeof(gtxpwr_tab_def_g)); + MCAL_WARN("Load default txpwr for g:%p\r\n", gtxpwr_tab_def_g); + + manual_cal_fit_txpwr_tab_n_20(g_dif_g_n20); + MCAL_WARN("fit n20 table with dist:%d\r\n", g_dif_g_n20); + } + + if(!(is_ready_flash & TXPWR_TAB_N_RD)) { + os_memcpy(gtxpwr_tab_n_40, gtxpwr_tab_def_n_40, sizeof(gtxpwr_tab_def_n_40)); + MCAL_WARN("Load default txpwr for n40:%p\r\n", gtxpwr_tab_def_n_40); + } + #endif + return 0; +} + +int manual_cal_save_txpwr_tab_to_flash(void) +{ + TXPWR_IS_RD is_ready, is_ready_flash; + UINT32 len = 0, txpwr_len = 0, flash_len = 0; + UINT8 *buf = NULL, *txpwr_buf = NULL;; + TAG_TXPWR_ST tag_txpwr; + TAG_TXPWR_PTR tag_txpwr_ptr = NULL; + TAG_ENABLE_ST tag_enable; + TAG_ENABLE_PTR tag_enable_ptr = NULL; + TAG_TXPWR_TAB_ST tag_tab; + TAG_TXPWR_TAB_PTR tag_tab_ptr = NULL; + TAG_DIF_ST tag_dif; + TAG_DIF_PTR tag_dif_ptr = NULL; + + UINT32 status, addr, addr_start; + DD_HANDLE flash_handle; + TXPWR_ELEM_ST head; + #if CFG_SUPPORT_ALIOS + hal_logic_partition_t *pt = hal_flash_get_info(HAL_PARTITION_RF_FIRMWARE); + #else + bk_logic_partition_t *pt = bk_flash_get_info(BK_PARTITION_RF_FIRMWARE); + #endif + + is_ready = manual_cal_txpwr_tab_is_fitted(); + MCAL_PRT("current txpwr table:0x%x\r\n", is_ready); + if(is_ready == TXPWR_NONE_RD) { + MCAL_WARN("TXPWR_NONE_RD, Cann't save txpwr tabe in flash\r\n"); + return 0; + } + + // alloc all memery at onece, so we no need to change the size of buf in combin function + txpwr_len = sizeof(TAG_TXPWR_ST) + sizeof(TAG_ENABLE_ST) + + 3*sizeof(TAG_TXPWR_TAB_ST) + 2*sizeof(TAG_DIF_ST); + + + // read flash, then combin the table in flash + flash_handle = ddev_open(FLASH_DEV_NAME, &status, 0); + status = manual_cal_search_opt_tab(&flash_len); + // Has TLV Header? + if(status) { + addr_start = manual_cal_search_txpwr_tab(TXPWR_TAB_TAB, pt->partition_start_addr);//TXPWR_TAB_FLASH_ADDR); + if(!addr_start) { + // not TXPWR_TAB_TAB, but has any other id, so attch TXPWR_TAB_TAB after the table + len = flash_len + txpwr_len; + buf = (UINT8*)os_malloc(len); + if(!buf) { + MCAL_FATAL("no memory for chipinfo save to flash\r\n"); + return 0; + } + // copy flash + ddev_read(flash_handle, (char *)buf, flash_len, pt->partition_start_addr);//TXPWR_TAB_FLASH_ADDR); + ddev_close(flash_handle); + + // updata new TLV header + tag_txpwr_ptr = (TAG_TXPWR_PTR)buf; + tag_txpwr.head.type= BK_FLASH_OPT_TLV_HEADER; + tag_txpwr.head.len = len - sizeof(TAG_TXPWR_ST);; + os_memcpy(tag_txpwr_ptr, &tag_txpwr, sizeof(TAG_TXPWR_ST)); + + txpwr_buf = (UINT8 *)(buf + flash_len); + addr_start = pt->partition_start_addr;//TXPWR_TAB_FLASH_ADDR; + }else { + // txpwr is exist, and found start addr. + len = txpwr_len; + txpwr_buf = buf = (UINT8*)os_malloc(txpwr_len); + if(!buf) { + MCAL_FATAL("no memory for txpwr tab save to flash\r\n"); + return 0; + } + } + } else { + // nothing in flash, write TLV with chipid + MCAL_WARN("NO BK_FLASH_OPT_TLV_HEADER found, save_txpwr_tab_to_flash failed\r\n"); + return 0; + } + + is_ready_flash = TXPWR_NONE_RD; + addr = manual_cal_search_txpwr_tab(TXPWR_ENABLE_ID, addr_start); + if(addr) { + ddev_read(flash_handle, (char *)&head, sizeof(TXPWR_ELEM_ST), addr); + ddev_read(flash_handle, (char *)&is_ready_flash, head.len, addr + sizeof(TXPWR_ELEM_ST)); + MCAL_PRT("flash txpwr table:0x%x\r\n", is_ready_flash); + } + + // for tag TXPW + tag_txpwr_ptr = (TAG_TXPWR_PTR)txpwr_buf; + tag_txpwr.head.type = TXPWR_TAB_TAB; + tag_txpwr.head.len = txpwr_len - sizeof(TAG_TXPWR_ST); + os_memcpy(tag_txpwr_ptr, &tag_txpwr, sizeof(TAG_TXPWR_ST)); + txpwr_buf = (UINT8*)(txpwr_buf + sizeof(TAG_TXPWR_ST)); + + // for tag TXPWR_ENABLE_ID + tag_enable_ptr = (TAG_ENABLE_PTR)(txpwr_buf); + tag_enable.head.type = TXPWR_ENABLE_ID; + tag_enable.head.len = sizeof(tag_enable.flag); + tag_enable.flag = (UINT32)is_ready; + os_memcpy(tag_enable_ptr, &tag_enable, sizeof(TAG_ENABLE_ST)); + txpwr_buf = (UINT8*)(txpwr_buf + sizeof(TAG_ENABLE_ST)); + + // for tag TXPWR_TAB_B_ID + tag_tab_ptr = (TAG_TXPWR_TAB_PTR)(txpwr_buf); + tag_tab.head.type = TXPWR_TAB_B_ID; + tag_tab.head.len = sizeof(TXPWR_ST)*WLAN_2_4_G_CHANNEL_NUM; + if(is_ready & TXPWR_TAB_B_RD) { + os_memcpy(&tag_tab.tab[0], gtxpwr_tab_b, tag_tab.head.len); + } else if(is_ready_flash & TXPWR_TAB_B_RD) { + addr = manual_cal_search_txpwr_tab(TXPWR_TAB_B_ID, addr_start); + if(addr) { + ddev_read(flash_handle, (char *)&head, sizeof(TXPWR_ELEM_ST), addr); + ddev_read(flash_handle, (char *)&tag_tab.tab[0], head.len, addr + sizeof(TXPWR_ELEM_ST)); + } else { + MCAL_PRT("txpwr tabe b in flash no found\r\n"); + } + } + os_memcpy(tag_tab_ptr, &tag_tab, sizeof(TAG_TXPWR_TAB_ST)); + txpwr_buf = (UINT8*)(txpwr_buf + sizeof(TAG_TXPWR_TAB_ST)); + + + // for tag TXPWR_TAB_G_ID + tag_tab_ptr = (TAG_TXPWR_TAB_PTR)(txpwr_buf); + tag_tab.head.type = TXPWR_TAB_G_ID; + tag_tab.head.len = sizeof(TXPWR_ST)*WLAN_2_4_G_CHANNEL_NUM; + if(is_ready & TXPWR_TAB_G_RD) { + os_memcpy(&tag_tab.tab[0], gtxpwr_tab_g, tag_tab.head.len); + } else if(is_ready_flash & TXPWR_TAB_G_RD) { + addr = manual_cal_search_txpwr_tab(TXPWR_TAB_G_ID, addr_start); + if(addr) { + ddev_read(flash_handle, (char *)&head, sizeof(TXPWR_ELEM_ST), addr); + ddev_read(flash_handle, (char *)&tag_tab.tab[0], head.len, addr + sizeof(TXPWR_ELEM_ST)); + } else { + MCAL_PRT("txpwr tabe g in flash no found\r\n"); + } + } + os_memcpy(tag_tab_ptr, &tag_tab, sizeof(TAG_TXPWR_TAB_ST)); + txpwr_buf = (UINT8*)(txpwr_buf + sizeof(TAG_TXPWR_TAB_ST)); + + // for tag TXPWR_TAB_N_ID + tag_tab_ptr = (TAG_TXPWR_TAB_PTR)(txpwr_buf); + tag_tab.head.type = TXPWR_TAB_N_ID; + tag_tab.head.len = sizeof(TXPWR_ST)*WLAN_2_4_G_CHANNEL_NUM; + if(is_ready & TXPWR_TAB_N_RD) { + os_memcpy(&tag_tab.tab[0], gtxpwr_tab_n_40, tag_tab.head.len); + } else if(is_ready_flash & TXPWR_TAB_N_RD) { + addr = manual_cal_search_txpwr_tab(TXPWR_TAB_N_ID, addr_start); + if(addr) { + ddev_read(flash_handle, (char *)&head, sizeof(TXPWR_ELEM_ST), addr); + ddev_read(flash_handle, (char *)&tag_tab.tab[0], head.len, addr + sizeof(TXPWR_ELEM_ST)); + } else { + MCAL_PRT("txpwr tabe N in flash no found\r\n"); + } + } + os_memcpy(tag_tab_ptr, &tag_tab, sizeof(TAG_TXPWR_TAB_ST)); + txpwr_buf = (UINT8*)(txpwr_buf + sizeof(TAG_TXPWR_TAB_ST)); + + // for tag TXPWR_TAB_DIF_GN20_ID + tag_dif_ptr = (TAG_DIF_PTR)(txpwr_buf); + tag_dif.head.type = TXPWR_TAB_DIF_GN20_ID; + tag_dif.head.len = sizeof(UINT32); + tag_dif.differ = g_dif_g_n20; + os_memcpy(tag_dif_ptr, &tag_dif, sizeof(TAG_DIF_ST)); + txpwr_buf = (UINT8*)(txpwr_buf + sizeof(TAG_DIF_ST)); + + // for tag TXPWR_TAB_DIF_GN40_ID + tag_dif_ptr = (TAG_DIF_PTR)(txpwr_buf); + tag_dif.head.type = TXPWR_TAB_DIF_GN40_ID; + tag_dif.head.len = sizeof(UINT32); + tag_dif.differ = g_dif_g_n40; + os_memcpy(tag_dif_ptr, &tag_dif, sizeof(TAG_DIF_ST)); + txpwr_buf = (UINT8*)(txpwr_buf + sizeof(TAG_DIF_ST)); + + ddev_close(flash_handle); + + addr_start -= pt->partition_start_addr;//TXPWR_TAB_FLASH_ADDR; + manual_cal_update_flash_area(addr_start, (char *)buf, len); + os_free(buf); + + return 1; +} + +int manual_cal_save_chipinfo_tab_to_flash(void) +{ + UINT32 len = 0, chipinfo_len = 0, flash_len = 0; + UINT8 *buf = NULL, *info_buf = NULL; + TAG_TXPWR_ST tag_txpwr; + TAG_TXPWR_PTR tag_txpwr_ptr = NULL; + TAG_COMM_ST tag_com; + TAG_COMM_PTR tag_com_ptr = NULL; + TAG_CHIPMAC_ST tag_mac; + TAG_CHIPMAC_PTR tag_mac_ptr = NULL; + UINT32 status, addr, addr_start; + DD_HANDLE flash_handle; + TXPWR_ELEM_ST head; + #if CFG_SUPPORT_ALIOS + hal_logic_partition_t *pt = hal_flash_get_info(HAL_PARTITION_RF_FIRMWARE); + #else + bk_logic_partition_t *pt = bk_flash_get_info(BK_PARTITION_RF_FIRMWARE); + #endif + + chipinfo_len = sizeof(TAG_TXPWR_ST) + sizeof(TAG_COMM_ST) + #if MCAL_SAVE_MAC_ADDR + + sizeof(TAG_CHIPMAC_ST) + #endif + + sizeof(TAG_COMM_ST) + sizeof(TAG_COMM_ST) + sizeof(TAG_COMM_ST) + + sizeof(TAG_COMM_ST); + + flash_handle = ddev_open(FLASH_DEV_NAME, &status, 0); + status = manual_cal_search_opt_tab(&flash_len); + // Has TLV Header? + if(status) { + addr_start = manual_cal_search_txpwr_tab(TXID, pt->partition_start_addr);//TXPWR_TAB_FLASH_ADDR); + if(!addr_start) { + // not txid, but has any other id, so attch txid after the table + len = flash_len + chipinfo_len; + buf = (UINT8*)os_malloc(len); + if(!buf) { + MCAL_FATAL("no memory for chipinfo save to flash\r\n"); + return 0; + } + // copy flash + ddev_read(flash_handle, (char *)buf, flash_len, pt->partition_start_addr);//TXPWR_TAB_FLASH_ADDR); + ddev_close(flash_handle); + + // updata new TLV header + tag_txpwr_ptr = (TAG_TXPWR_PTR)buf; + tag_txpwr.head.type= BK_FLASH_OPT_TLV_HEADER; + tag_txpwr.head.len = len - sizeof(TAG_TXPWR_ST); + os_memcpy(tag_txpwr_ptr, &tag_txpwr, sizeof(TAG_TXPWR_ST)); + + info_buf = (UINT8 *)(buf + flash_len); + } else { + #if 0 + // not need to write, return; + ddev_close(flash_handle); + return 0; + #else + // updata txid + len = flash_len; + buf = (UINT8*)os_malloc(len); + if(!buf) { + MCAL_FATAL("no memory for chipinfo save to flash\r\n"); + return 0; + } + // copy flash + ddev_read(flash_handle, (char *)buf, flash_len, pt->partition_start_addr);//TXPWR_TAB_FLASH_ADDR); + ddev_close(flash_handle); + + // point to txid + info_buf = (UINT8 *)(buf + sizeof(TAG_TXPWR_ST)); + #endif + } + } else { + // nothing in flash, write TLV with chipid + len = chipinfo_len + sizeof(TAG_TXPWR_ST); + + buf = (UINT8*)os_malloc(len); + if(!buf) { + MCAL_FATAL("no memory for chipinfo save to flash\r\n"); + return 0; + } + + // updata new TLV header + tag_txpwr_ptr = (TAG_TXPWR_PTR)buf; + tag_txpwr.head.type= BK_FLASH_OPT_TLV_HEADER; + tag_txpwr.head.len = len - sizeof(TAG_TXPWR_ST); + os_memcpy(tag_txpwr_ptr, &tag_txpwr, sizeof(TAG_TXPWR_ST)); + info_buf = (UINT8 *)(buf + sizeof(TAG_TXPWR_ST)); + } + + ////////////////////////////////////////////// + // for tag TXID + tag_txpwr_ptr = (TAG_TXPWR_PTR)(info_buf); + tag_txpwr.head.type = TXID; + tag_txpwr.head.len = chipinfo_len - sizeof(TAG_TXPWR_ST); + os_memcpy(tag_txpwr_ptr, &tag_txpwr, sizeof(TAG_TXPWR_ST)); + + // for tag TXID_ID + info_buf = (UINT8 *)(info_buf + sizeof(TAG_TXPWR_ST)); + tag_com_ptr = (TAG_COMM_PTR)(info_buf); + tag_com.head.type = TXID_ID; + tag_com.head.len = sizeof(tag_com.value); + tag_com.value = (UINT32)DEFAULT_TXID_ID; + os_memcpy(tag_com_ptr, &tag_com, sizeof(TAG_COMM_ST)); + +#if MCAL_SAVE_MAC_ADDR + // for tag TXID_MAC + info_buf = (UINT8 *)(info_buf + sizeof(TAG_COMM_ST)); + tag_mac_ptr = (TAG_CHIPMAC_PTR)(info_buf); + tag_mac.head.type = TXID_MAC; + tag_mac.head.len = 6; + os_memcpy(&tag_mac.arry[0], system_mac, 6); + os_memcpy(tag_mac_ptr, &tag_mac, sizeof(TAG_CHIPMAC_ST)); + info_buf = (UINT8 *)(info_buf + sizeof(TAG_CHIPMAC_ST)); +#else + info_buf = (UINT8 *)(info_buf + sizeof(TAG_COMM_ST)); +#endif + // for tag TXID_THERMAL + //manual_cal_get_current_temperature(); + os_printf("save sys temper:%d\r\n", g_cur_temp); + tag_com_ptr = (TAG_COMM_PTR)(info_buf ); + tag_com.head.type = TXID_THERMAL; + tag_com.head.len = sizeof(tag_com.value); + tag_com.value = (UINT32)g_cur_temp; + os_memcpy(tag_com_ptr, &tag_com, sizeof(TAG_COMM_ST)); + + // for tag TXID_CHANNEL + info_buf = (UINT8 *)(info_buf + sizeof(TAG_COMM_ST)); + tag_com_ptr = (TAG_COMM_PTR)(info_buf); + tag_com.head.type = TXID_CHANNEL; + tag_com.head.len = sizeof(tag_com.value); + tag_com.value = (UINT32)DEFAULT_TXID_CHANNEL; + os_memcpy(tag_com_ptr, &tag_com, sizeof(TAG_COMM_ST)); + + // for tag TXID_XTAL + info_buf = (UINT8 *)(info_buf + sizeof(TAG_COMM_ST)); + tag_com_ptr = (TAG_COMM_PTR)(info_buf); + tag_com.head.type = TXID_XTAL; + tag_com.head.len = sizeof(tag_com.value); + tag_com.value = (UINT32)DEFAULT_TXID_XTAL; + os_memcpy(tag_com_ptr, &tag_com, sizeof(TAG_COMM_ST)); + + // for tag TXID_ADC + info_buf = (UINT8 *)(info_buf + sizeof(TAG_COMM_ST)); + tag_com_ptr = (TAG_COMM_PTR)(info_buf); + tag_com.head.type = TXID_ADC; + tag_com.head.len = sizeof(tag_com.value); + tag_com.value = *((UINT32 *)&saradc_val); + os_memcpy(tag_com_ptr, &tag_com, sizeof(TAG_COMM_ST)); + manual_cal_update_flash_area(0, (char *)buf, len); + os_free(buf); + + return 1; +} + +int manual_cal_get_macaddr_from_flash(UINT8 *mac_ptr) +{ + #if MCAL_SAVE_MAC_ADDR + UINT32 flash_len = 0; + UINT32 status, addr, addr_start; + DD_HANDLE flash_handle; + TXPWR_ELEM_ST head; + #if CFG_SUPPORT_ALIOS + hal_logic_partition_t *pt = hal_flash_get_info(HAL_PARTITION_RF_FIRMWARE); + #else + bk_logic_partition_t *pt = bk_flash_get_info(BK_PARTITION_RF_FIRMWARE); + #endif + flash_handle = ddev_open(FLASH_DEV_NAME, &status, 0); + status = manual_cal_search_opt_tab(&flash_len); + // Has TLV Header? + if(status) { + addr_start = manual_cal_search_txpwr_tab(TXID, pt->partition_start_addr);//TXPWR_TAB_FLASH_ADDR); + if(!addr_start) { + // not txid, but has any other id, so attch txid after the table + MCAL_FATAL("No txid header found in flash\r\n"); + return 0; + } + } + else { + MCAL_FATAL("No TLV header found in flash\r\n"); + return 0; + } + + addr = manual_cal_search_txpwr_tab(TXID_MAC, addr_start); + if(addr) { + ddev_read(flash_handle, (char *)&head, sizeof(TXPWR_ELEM_ST), addr); + ddev_read(flash_handle, (char *)mac_ptr, head.len, addr + sizeof(TXPWR_ELEM_ST)); + //MCAL_PRT("read MAC ADDR from flash\r\n"); + }else { + MCAL_FATAL("No MAC id found in txid header \r\n"); + return 0; + } + + return 1; + #else + return 0; + #endif +} + +int manual_cal_write_macaddr_to_flash(UINT8 *mac_ptr) +{ + #if MCAL_SAVE_MAC_ADDR + UINT32 flash_len = 0; + UINT32 status, addr, addr_start; + DD_HANDLE flash_handle; + TXPWR_ELEM_ST head; + #if CFG_SUPPORT_ALIOS + hal_logic_partition_t *pt = hal_flash_get_info(HAL_PARTITION_RF_FIRMWARE); + #else + bk_logic_partition_t *pt = bk_flash_get_info(BK_PARTITION_RF_FIRMWARE); + #endif + + flash_handle = ddev_open(FLASH_DEV_NAME, &status, 0); + status = manual_cal_search_opt_tab(&flash_len); + // Has TLV Header? + if(status) { + addr_start = manual_cal_search_txpwr_tab(TXID, pt->partition_start_addr);//TXPWR_TAB_FLASH_ADDR); + if(!addr_start) { + // not txid, but has any other id, so attch txid after the table + MCAL_FATAL("No txid header found in flash\r\n"); + return 0; + } + } + else { + MCAL_FATAL("No TLV header found in flash\r\n"); + return 0; + } + + addr = manual_cal_search_txpwr_tab(TXID_MAC, addr_start); + if(addr) { + ddev_read(flash_handle, (char *)&head, sizeof(TXPWR_ELEM_ST), addr); + addr += sizeof(TXPWR_ELEM_ST); + addr -= pt->partition_start_addr;//TXPWR_TAB_FLASH_ADDR; + manual_cal_update_flash_area(addr, (char *)mac_ptr, 6); //0: sucess, 1 failed + }else { + MCAL_FATAL("No MAC id found in txid header \r\n"); + return 0; + } + + return 1; + #else + return 0; + #endif +} + +UINT8 manual_cal_wirte_otp_flash(UINT32 addr, UINT32 len, UINT8 *buf) +{ + UINT8 ret = 0; + #if CFG_SUPPORT_ALIOS + hal_logic_partition_t *pt = hal_flash_get_info(HAL_PARTITION_RF_FIRMWARE); + #else + bk_logic_partition_t *pt = bk_flash_get_info(BK_PARTITION_RF_FIRMWARE); + #endif + //MCAL_PRT("wirte_otp_flash:addr:%08x, len:%d, buf:%p\r\n", addr, len, buf); + addr -= pt->partition_start_addr;//TXPWR_TAB_FLASH_ADDR; + ret = manual_cal_update_flash_area(addr, (char *)buf, len); //0: sucess, 1 failed + return ret; +} + +UINT8 manual_cal_read_otp_flash(UINT32 addr, UINT32 len, UINT8 *buf) +{ + UINT8 ret = 0; + //MCAL_PRT("read_otp_flash:addr:%08x, len:%d, buf:%p\r\n",addr, len, buf); + ret = manual_cal_read_flash(addr, (char *)buf, len); //0:failed, others: len + return ret; +} + +void manual_cal_get_current_temperature(void) +{ + UINT32 temp_value; + + if(!temp_single_get_current_temperature(&temp_value)) + g_cur_temp = temp_value; + + MCAL_WARN("system temperature:%0d\r\n", g_cur_temp); +} + +void manual_cal_show_otp_flash(void) +{ + UINT32 status, flash_len, addr_start; + DD_HANDLE flash_handle; + TXPWR_ELEM_ST head; + #if CFG_SUPPORT_ALIOS + hal_logic_partition_t *pt = hal_flash_get_info(HAL_PARTITION_RF_FIRMWARE); + #else + bk_logic_partition_t *pt = bk_flash_get_info(BK_PARTITION_RF_FIRMWARE); + #endif + + flash_len = 0; + flash_handle = ddev_open(FLASH_DEV_NAME, &status, 0); + status = manual_cal_search_opt_tab(&flash_len); + + if(status) + { + UINT8 *buf = (UINT8*)os_malloc(flash_len); + if(!buf) + { + MCAL_FATAL("no memory for show_otp_flash\r\n"); + ddev_close(flash_handle); + return; + } + + os_memset(buf, 0, sizeof(flash_len)); + addr_start = pt->partition_start_addr; + // copy flash + ddev_read(flash_handle, (char *)buf, flash_len, addr_start);//TXPWR_TAB_FLASH_ADDR); + for(int i=0; ipartition_start_addr);//TXPWR_TAB_FLASH_ADDR); + if(!addr_start) { + MCAL_FATAL("NO TXID found in flash, use def temp:%d\r\n", DEFAULT_TXID_THERMAL); + goto init_temp; + } + + addr = manual_cal_search_txpwr_tab(TXID_THERMAL, addr_start); + if(!addr) + { + MCAL_FATAL("NO TXID_THERMAL found in flash, use def temp:%d\r\n", DEFAULT_TXID_THERMAL); + goto init_temp; + } + + flash_handle = ddev_open(FLASH_DEV_NAME, &status, 0); + ddev_read(flash_handle, (char *)&head, sizeof(TXPWR_ELEM_ST), addr); + ddev_read(flash_handle, (char *)&status, head.len, addr + sizeof(TXPWR_ELEM_ST)); + tem_in_flash = status; + +init_temp: + MCAL_FATAL("temp in flash is:%d\r\n", tem_in_flash); + return tem_in_flash; +} + +void manual_cal_load_differ_tag_from_flash(void) +{ + UINT32 status, addr, addr_start; + DD_HANDLE flash_handle; + TXPWR_ELEM_ST head; + #if CFG_SUPPORT_ALIOS + hal_logic_partition_t *pt = hal_flash_get_info(HAL_PARTITION_RF_FIRMWARE); + #else + bk_logic_partition_t *pt = bk_flash_get_info(BK_PARTITION_RF_FIRMWARE); + #endif + UINT32 dif_n20 = MOD_DIST_G_BW_N20; + UINT32 dif_n40 = MOD_DIST_G_BW_N40; + + addr_start = manual_cal_search_txpwr_tab(TXPWR_TAB_TAB, pt->partition_start_addr);//TXPWR_TAB_FLASH_ADDR); + if(!addr_start) { + MCAL_FATAL("NO TXPWR_TAB_TAB found in flash, use def:%d, %d\r\n", + MOD_DIST_G_BW_N20, MOD_DIST_G_BW_N40); + goto load_diff; + } + + addr = manual_cal_search_txpwr_tab(TXPWR_TAB_DIF_GN20_ID, addr_start); + if(!addr) { + MCAL_FATAL("NO TXPWR_TAB_DIF_GN20_ID found in flash, use def:%d\r\n", MOD_DIST_G_BW_N20); + } else { + flash_handle = ddev_open(FLASH_DEV_NAME, &status, 0); + ddev_read(flash_handle, (char *)&head, sizeof(TXPWR_ELEM_ST), addr); + ddev_read(flash_handle, (char *)&status, head.len, addr + sizeof(TXPWR_ELEM_ST)); + dif_n20 = status; + } + + addr = manual_cal_search_txpwr_tab(TXPWR_TAB_DIF_GN40_ID, addr_start); + if(!addr) { + MCAL_FATAL("NO TXPWR_TAB_DIF_GN40_ID found in flash, use def:%d\r\n", TXPWR_TAB_DIF_GN40_ID); + } else { + flash_handle = ddev_open(FLASH_DEV_NAME, &status, 0); + ddev_read(flash_handle, (char *)&head, sizeof(TXPWR_ELEM_ST), addr); + ddev_read(flash_handle, (char *)&status, head.len, addr + sizeof(TXPWR_ELEM_ST)); + dif_n40 = status; + } + +load_diff: + MCAL_FATAL("diff in flash:n20-%d, n40-%d\r\n", dif_n20, dif_n40); + return; +} + +#endif // CFG_SUPPORT_MANUAL_CALI + + +#if CFG_USE_TEMPERATURE_DETECT +#define TMP_PWR_TAB_LEN (16 + 2) + +typedef struct tmp_set_pwr_st { + UINT8 indx; + UINT8 flag; + UINT16 temp_tab[TMP_PWR_TAB_LEN]; + TMP_PWR_PTR pwr_ptr; + UINT16 init_mod; + UINT16 init_pa; +} TMP_SET_PWR_ST, *TMP_SET_PWR_PTR; + +const TMP_PWR_ST tmp_pwr_tab[TMP_PWR_TAB_LEN] = { + {0x01, 8, 0}, // 0 + {0x02, 8, 0}, // 1 + {0x03, 8, 0}, // 2 + {0x04, 8, 0}, // 3 + {0x05, 8, 0}, // 4 + {0x06, 8, 0}, // 5 + {0x07, 8, 0}, // 6 + {0x08, 8, 0}, // 7 + {0x0a, 8, 0}, // 8 + {0x0c, 8, 0}, // 9 + {0x0f, 8, 0}, // 10 + {0x0f, 8, 1}, // 11 + {0x0f, 8, 2}, // 12 + {0x0f, 8, 3}, // 13 + {0x0f, 8, 4}, // 14 + {0x0f, 8, 5}, // 15 + {0x0f, 8, 6}, + {0x0f, 8, 7} +}; + +TMP_SET_PWR_ST g_tmp_pwr; + +extern void sctrl_cali_dpll(UINT8 flag); +extern void sctrl_dpll_int_open(void); + +void manual_cal_set_tmp_pwr_flag(UINT8 flag) +{ + os_printf("set flag to %d\r\n", flag); + g_tmp_pwr.flag = flag; +} + +void manual_cal_tmp_pwr_init_reg(UINT16 reg_mod, UINT16 reg_pa) +{ + TMP_DETECT_WARN("manual_cal_tmp_pwr_init_reg: mod:%d, pa:%d\r\n", reg_mod, reg_pa); + g_tmp_pwr.init_mod = reg_mod; + g_tmp_pwr.init_pa = reg_pa; +} + +extern void rwnx_cal_set_txpwr_by_tmpdetect(UINT16 shift); +void manual_cal_temp_pwr_unint(void) +{ + os_printf("manual_cal_temp_pwr_unint: mod:%d, pa:%d\r\n", g_tmp_pwr.init_mod, + g_tmp_pwr.init_pa); + rwnx_cal_set_reg_mod_pa(g_tmp_pwr.init_mod, g_tmp_pwr.init_pa); + rwnx_cal_set_txpwr_by_tmpdetect(0); + + manual_cal_set_tmp_pwr_flag(0); + os_printf("set flag to disable, don't do pwr any more:%d\r\n", g_tmp_pwr.flag); + +} + +void manual_cal_tmp_pwr_init(UINT16 init_temp, UINT16 init_thre, UINT16 init_dist) +{ + INT32 idx = TMP_PWR_TAB_LEN-1, i; + TMP_PWR_PTR pwr_ptr_0, pwr_ptr_1; + UINT8 reg_mod, reg_pa; + INT16 temp = 0; + + reg_mod = g_tmp_pwr.init_mod; + reg_pa = g_tmp_pwr.init_pa; + + for(i=0; imod <= reg_mod) && (pwr_ptr_1->mod >= reg_mod)) + && ((pwr_ptr_0->pa <= reg_pa) && (pwr_ptr_1->pa >= reg_pa))) + { + if((pwr_ptr_1->pa == reg_pa) && (pwr_ptr_1->mod >= reg_mod)) + idx = i+1; + else + idx = i; + + break; + } + } + + os_printf("init temp pwr table: mod:%d, pa:%d, tmp:%d, idx:%d, dist:%d\r\n", + reg_mod, reg_pa, init_temp, idx, init_dist); + + if(init_temp >= ADC_TEMP_VAL_MAX) + { + os_printf("init temp too large %d, failed\r\n"); + return; + } + + init_temp += init_dist; + if(init_temp >= ADC_TEMP_VAL_MAX) + init_temp = ADC_TEMP_VAL_MAX; + + os_memset(&g_tmp_pwr.temp_tab[0], 0, sizeof(UINT16)*TMP_PWR_TAB_LEN); + g_tmp_pwr.indx = idx; + g_tmp_pwr.pwr_ptr = (TMP_PWR_PTR)&tmp_pwr_tab[idx]; + g_tmp_pwr.temp_tab[idx] = init_temp; + + for(i=idx+1; i ADC_TEMP_VAL_MAX)? ADC_TEMP_VAL_MAX : temp; + g_tmp_pwr.temp_tab[i] = temp; + } + + for(i=idx-1; i>=0; i--) { + //temp = g_tmp_pwr.temp_tab[i+1] - ADC_TMEP_LSB_PER_10DEGREE; + temp = g_tmp_pwr.temp_tab[i+1] - init_thre; + temp = (temp < ADC_TEMP_VAL_MIN)? ADC_TEMP_VAL_MIN : temp; + g_tmp_pwr.temp_tab[i] = temp; + } + + TMP_DETECT_WARN("\r\n"); + for(i=0; i>1) + 2, thre_2 = thre_1 + thre ; + UINT8 indx = g_tmp_pwr.indx, need_cal_dpll = 0; + UINT16 last_val = g_tmp_pwr.temp_tab[g_tmp_pwr.indx]; + + if(cur_val > last_val) + { + dist = cur_val - last_val; + if(dist >= thre_2) + { + indx = (indx+2= thre_1) + indx = (indx+1= thre_2) + { + indx = (indx>2)? indx-2:0; + need_cal_dpll = 1; + } + else if(dist >= thre_1) + indx = (indx>1)? indx-1:0; + } + + if(g_tmp_pwr.indx == indx) + return NULL; + + g_tmp_pwr.indx = indx; + g_tmp_pwr.pwr_ptr = (TMP_PWR_PTR)&tmp_pwr_tab[indx]; + *last = g_tmp_pwr.temp_tab[g_tmp_pwr.indx]; + + if(need_cal_dpll) + { + os_printf("cal dpll!\r\n"); + CHECK_OPERATE_RF_REG_IF_IN_SLEEP(); + sctrl_cali_dpll(0); + sctrl_dpll_int_open(); + CHECK_OPERATE_RF_REG_IF_IN_SLEEP_END(); + } + + bk7011_cal_bias(); + + if(g_tmp_pwr.flag) { + os_printf("set_tmp_pwr: indx:%d, mod:%d, pa:%d, tmp:%d, shift:%d\r\n", indx, + g_tmp_pwr.pwr_ptr->mod, g_tmp_pwr.pwr_ptr->pa, *last, g_tmp_pwr.pwr_ptr->pwr_idx_shift); + + return g_tmp_pwr.pwr_ptr; + } else + return NULL; +} + +UINT32 manual_cal_load_temp_tag_flash(void) +{ + g_cur_temp = g_cur_temp_flash= manual_cal_load_temp_tag_from_flash(); + // start temp dectect + manual_cal_tmp_pwr_init(g_cur_temp, ADC_TMEP_LSB_PER_10DEGREE * ADC_TMEP_10DEGREE_PER_DBPWR, + ADC_TMEP_DIST_INTIAL_VAL); + + return g_cur_temp; +} + +#endif // CFG_USE_TEMPERATURE_DETECT + +#if CFG_SARADC_CALIBRATE +UINT32 manual_cal_load_adc_cali_flash(void) +{ + UINT32 status, addr, addr_start; + DD_HANDLE flash_handle; + TXPWR_ELEM_ST head; + #if CFG_SUPPORT_ALIOS + hal_logic_partition_t *pt = hal_flash_get_info(HAL_PARTITION_RF_FIRMWARE); + #else + bk_logic_partition_t *pt = bk_flash_get_info(BK_PARTITION_RF_FIRMWARE); + #endif + + addr_start = manual_cal_search_txpwr_tab(TXID, pt->partition_start_addr);//TXPWR_TAB_FLASH_ADDR); + if(!addr_start) { + goto FAILURE; + } + + addr = manual_cal_search_txpwr_tab(TXID_ADC, addr_start); + if(!addr) + { + goto FAILURE; + } + + flash_handle = ddev_open(FLASH_DEV_NAME, &status, 0); + ddev_read(flash_handle, (char *)&head, sizeof(TXPWR_ELEM_ST), addr); + ddev_read(flash_handle, (char *)&saradc_val, head.len, addr + sizeof(TXPWR_ELEM_ST)); + + os_printf("calibrate low value:[%x]\r\n", saradc_val.low); + os_printf("calibrate high value:[%x]\r\n", saradc_val.high); + + return SARADC_SUCCESS; + +FAILURE: + return SARADC_FAILURE; +} +#endif + +#endif // (CFG_SOC_NAME != SOC_BK7231) + diff --git a/beken_os/beken378/func/bk7011_cal/manual_cal_bk7231U.c b/beken_os/beken378/func/bk7011_cal/manual_cal_bk7231U.c new file mode 100755 index 0000000..6d76c81 --- /dev/null +++ b/beken_os/beken378/func/bk7011_cal/manual_cal_bk7231U.c @@ -0,0 +1,3969 @@ +#include "include.h" + +#if (CFG_SOC_NAME != SOC_BK7231) +#include "arm_arch.h" +#if CFG_SUPPORT_MANUAL_CALI +#include "target_util_pub.h" +#include "mem_pub.h" + +#include "drv_model_pub.h" +#include "sys_ctrl_pub.h" +#include "phy.h" + +#include "bk7011_cal_pub.h" +#include "bk7011_cal.h" + +#include +#include "flash_pub.h" +#include "temp_detect_pub.h" +#include "saradc_pub.h" +#include "param_config.h" + +#include "rtos_pub.h" +#if CFG_SUPPORT_ALIOS +#include "hal/soc/soc.h" +#else +#include "BkDriverFlash.h" +#endif +#include "power_save_pub.h" +#include "cmd_evm.h" +#include "ate_app.h" +#include "sys_ctrl.h" + +#define TXPWR_DEFAULT_TAB 1 + +/* support max work cuurent<250mA@3.3V */ +#define CFG_SUPPORT_LOW_MAX_CURRENT 0 + +#define MCAL_SAVE_MAC_ADDR 1 + +#define WLAN_2_4_G_CHANNEL_NUM (14) +#define BLE_2_4_G_CHANNEL_NUM (40) +#define MAX_RATE_FOR_B_5M (5) // 5.5M +#define MAX_RATE_FOR_B (11) // 11M +#define MAX_RATE_FOR_G (54) // 54M +#define MIN_RATE_FOR_N (128) // MCS0 +#define MAX_RATE_FOR_N (135) // MCS7 + +#if (CFG_SOC_NAME == SOC_BK7231N) +#define MOD_DIST_G_BW_N20 (4) // bk7231 is 2 //wyg 20200330 2->4 +#define MOD_DIST_G_BW_N40 (4) //wyg 20200330 4->8 +#else +#define MOD_DIST_G_BW_N20 (2) // bk7231 is 2 +#define MOD_DIST_G_BW_N40 (3) +#endif + +#define TXPWR_ELEM_INUSED (0) +#define TXPWR_ELEM_UNUSED (1) + +#define BK_FLASH_SECTOR_SIZE (4*1024) +#define BK_FLASH_WRITE_CHECK_TIMES 3 + +#define MCAL_DEBUG 0 +#include "uart_pub.h" +#if MCAL_DEBUG +#define MCAL_PRT os_printf +#define MCAL_WARN os_printf +#define MCAL_FATAL fatal_prf +#else +#define MCAL_PRT null_prf +#define MCAL_WARN null_prf +#define MCAL_FATAL fatal_prf +#endif + +/* bit[7]: TXPWR flag + * 0: invalid + * 1: used + * bit[4:0]: 5bit TXPWR pwr_gain; + */ +#define FLAG_MASK (0x1u) +#define FLAG_POSI (7) +#if (CFG_SOC_NAME == SOC_BK7231N) +#define GAIN_MASK (0x7fu) +#else +#define GAIN_MASK (0x1fu) +#endif +#define GET_TXPWR_GAIN(p) ((p)->value & GAIN_MASK) +#define SET_TXPWR_GAIN(p, gain) {(p)->value &= (~GAIN_MASK); \ + (p)->value |= (gain&GAIN_MASK);} + +#define GET_TXPWR_FLAG(p) (((p)->value>>FLAG_POSI)&FLAG_MASK) +#define SET_TXPWR_FLAG(p, flag) {(p)->value &= (~(FLAG_MASK<value |= ((flag&FLAG_MASK)< BLE_2_4_G_CHANNEL_NUM) { + MCAL_WARN("ble wrong channel:%d\r\n", channel); + return; + } + + txpwr_tab_ptr = >xpwr_tab_ble[channel]; + + SET_TXPWR_GAIN(txpwr_tab_ptr, pwr_gain); + SET_TXPWR_FLAG(txpwr_tab_ptr, TXPWR_ELEM_INUSED); + + if (channel == 0) { + ble_cal_bit |= 0x1; + } else if (channel == 19) { + ble_cal_bit |= 0x2; + } else if (channel == 39) { + ble_cal_bit |= 0x4; + } + + MCAL_WARN("save c:%d, gain:%d\r\n", channel, pwr_gain); + + return; + } + + // for wlan wifi + if((channel == 0) || (channel > WLAN_2_4_G_CHANNEL_NUM)) { + MCAL_WARN("Manual cal wrong channel:%d\r\n", channel); + return; + } + + channel -= 1; + + if((rate <= MAX_RATE_FOR_B_5M) || (rate == MAX_RATE_FOR_B)) { + txpwr_tab_ptr = >xpwr_tab_b[channel]; + } else if(rate <= MAX_RATE_FOR_G) { + txpwr_tab_ptr = >xpwr_tab_g[channel]; + is_g_rate = 1; + } else if(rate <= MAX_RATE_FOR_N && rate >= MIN_RATE_FOR_N) { + txpwr_tab_ptr = >xpwr_tab_n_40[channel]; + } else { + MCAL_WARN("Manual cal wrong rate:%d\r\n", rate); + return; + } + + SET_TXPWR_GAIN(txpwr_tab_ptr, pwr_gain); + SET_TXPWR_FLAG(txpwr_tab_ptr, TXPWR_ELEM_INUSED); + + if(is_g_rate) { + // need save n20 + os_memcpy(>xpwr_tab_n[channel], >xpwr_tab_g[channel], sizeof(TXPWR_ST)); + manual_cal_adjust_fitting(>xpwr_tab_n[channel], g_dif_g_n20); + MCAL_PRT("fit n20 tab with dist:%d\r\n", g_dif_g_n20); + } +} + +#if CFG_SUPPORT_LOW_MAX_CURRENT//Max default work current<250mA@3.3V +const UINT16 shift_tab_b[4] = {0, 0, 0, 0}; // 11M base,5.5M,2M,1M +const UINT16 shift_tab_g[8] = {0, 2, 4, 4, 4, 4, 4, 4}; // 54M base - 6M +const UINT16 shift_tab_n[1] = {0}; // for MCS7 +#elif (CFG_SOC_NAME == SOC_BK7231N) +const UINT16 shift_tab_b[4] = {0, 0, 0, 0}; // 11M base,5.5M,2M,1M +// 54M base - 54M,48M,36M,24M,18M,12M,9M,6M +const UINT16 shift_tab_g[8] = {0, 2, 2, 2, 3, 3, 4, 4/*4*/}; // 54M base - 12M,9M,6M//do +const UINT16 shift_tab_n20[8] = {0, 2, 2, 2, 3, 3, 4, 4/*4*/};; // n20 mcs7base - mcs0 + +const UINT16 shift_tab_n40[8] = {0, 2, 2, 2, 3, 3, 4, 4/*4*/}; // n40 mcs7base - mcs0 +#else +const UINT16 shift_tab_b[4] = {0, 0, 0, 0}; // 11M base,5.5M,2M,1M +// 54M base - 54M,48M,36M,24M,18M,12M,9M,6M +const UINT16 shift_tab_g[8] = {0, 1, 1, 1, 2, 2, 4, 6/*4*/}; // 54M base - 12M,9M,6M +const UINT16 shift_tab_n20[8] = {0, 1, 1, 2, 2, 4, 4, 6/*4*/};; // n20 mcs7base - mcs0 + +const UINT16 shift_tab_n40[8] = {0, 1, 1, 2, 2, 4, 4, 6/*4*/}; // n40 mcs7base - mcs0 +#endif + +#define PWR_INIT_VAL 17 +const INT8 pwr_idx_2_dbm[] = { + PWR_INIT_VAL, // 00 1Mbps + 17, // 01 2Mbps + 17, // 02 5.5Mbps + 17, // 03 11Mbps + + 17, // 04 6Mbps + 17, // 05 9Mbps + 17, // 06 12Mbps + 17, // 07 18Mbps + 16, // 08 24Mbps + 15, // 09 36Mbps + 14, // 10 48Mbps + 14, // 11 54Mbps + + 17, // 12 mcs0 N20 + 17, // 13 mcs1 N20 + 17, // 14 mcs2 N20 + 16, // 15 mcs3 N20 + 15, // 16 mcs4 N20 + 14, // 17 mcs5 N20 + 13, // 18 mcs6 N20 + 13, // 19 mcs7 N20 + + 15, // 20 mcs0 N40 + 15, // 21 mcs1 N40 + 15, // 22 mcs2 N40 + 14, // 23 mcs3 N40 + 13, // 24 mcs4 N40 + 13, // 25 mcs5 N40 + 12, // 26 mcs6 N40 + 12 // 27 mcs7 N40 +}; + +INT8 g_cur_txpwr_dbm = PWR_INIT_VAL; + +INT8 manual_cal_get_dbm_by_rate(UINT32 rate, UINT32 bandwidth) +{ + const INT8 *dbm_ptr; + + if(bandwidth == PHY_CHNL_BW_20) + { + if(rate <= 3){ + dbm_ptr = &pwr_idx_2_dbm[rate]; + } + else if(rate <= 11 ){ // for g: 6-54M -- 4-11 + dbm_ptr = &pwr_idx_2_dbm[rate]; + }else if((rate >= 128) && (rate <= 135)){ // for n20 MCS0-7 + dbm_ptr = &pwr_idx_2_dbm[12 + rate - 128]; + }else{ + MCAL_FATAL("\r\n manual_cal_get_dbm_by_rate err %d\r\n", rate); + return 0; + } + } + else { + if((rate >= 128) && (rate <= 135)){ + dbm_ptr = &pwr_idx_2_dbm[20 + rate - 128]; + }else{ + MCAL_FATAL("\r\n manual_cal_get_dbm_by_rate err %d\r\n", rate); + return 0; + } + } + + g_cur_txpwr_dbm = *dbm_ptr; + + return *dbm_ptr; +} + +INT8 manual_cal_get_cur_txpwr_dbm(void) +{ + return g_cur_txpwr_dbm; +} + +UINT32 manual_cal_get_pwr_idx_shift(UINT32 rate, UINT32 bandwidth, UINT32 *pwr_gain) +{ + const UINT16 *shift; + UINT32 idex, ret = 2; + + if(bandwidth == PHY_CHNL_BW_20) + { + if(rate <= 3){ + shift = shift_tab_b; + idex = 3 - rate; + ret = 1; + } + else if(rate <= 11 ){ // for g: 6-54M -- 3-11 + shift = shift_tab_g; + idex = 11 - rate; + }else if((rate >= 128) && (rate <= 135)){ // for n20 MCS0-7 + shift = shift_tab_n20; + idex = 135 - rate; + }else{ + MCAL_FATAL("\r\nget_pwr_idx_shift wrong rate:%d\r\n", rate); + return 0; + } + } + else { + if((rate >= 128) && (rate <= 135)){ + shift = shift_tab_n40; + idex = 135 - rate; + }else{ + MCAL_FATAL("\r\nget_pwr_idx_shift wrong rate:%d\r\n", rate); + return 0; + } + } + + //MCAL_PRT("get_pwr_info: idx: %d, pwr:%d", shift[idex], *pwr_gain);remove for midea + + idex = shift[idex] + *pwr_gain; +#if (CFG_SOC_NAME == SOC_BK7231N) + *pwr_gain = (idex > 79)? 79: idex; +#else + *pwr_gain = (idex > 31)? 31: idex; +#endif + //MCAL_PRT("--pwr:%d\r\n", *pwr_gain);remove for midea + + return ret; +} + +int manual_cal_get_txpwr(UINT32 rate, UINT32 channel, UINT32 bandwidth, UINT32 *pwr_gain) +{ + TXPWR_PTR txpwr_tab_ptr = NULL; + + // for ble + if(rate == EVM_DEFUALT_BLE_RATE) + { + if(channel > BLE_2_4_G_CHANNEL_NUM) { + MCAL_WARN("ble wrong channel:%d\r\n", channel); + return 0; + } + + txpwr_tab_ptr = >xpwr_tab_ble[channel]; + + *pwr_gain = GET_TXPWR_GAIN(txpwr_tab_ptr); + return 1; + } + + // for wlan wifi + if((channel == 0) || (channel > WLAN_2_4_G_CHANNEL_NUM)) { + MCAL_WARN("Manual cal wrong channel:%d\r\n", channel); + return 0; + } + + if((bandwidth != PHY_CHNL_BW_20) && (bandwidth != PHY_CHNL_BW_40)) { + MCAL_WARN("Manual cal wrong bandwidth:%d\r\n", bandwidth); + return 0; + } + + channel -= 1; + + if(bandwidth == PHY_CHNL_BW_20) { + if((rate <= MAX_RATE_FOR_B_5M) || (rate == MAX_RATE_FOR_B)) { + txpwr_tab_ptr = >xpwr_tab_b[channel]; + }else if(rate <= MAX_RATE_FOR_G) { + txpwr_tab_ptr = >xpwr_tab_g[channel]; + }else if((rate <= MAX_RATE_FOR_N) && (rate >= MIN_RATE_FOR_N)) { + txpwr_tab_ptr = >xpwr_tab_n[channel]; + } else { + MCAL_FATAL("\r\nManual cal wrong rate:%d\r\n", rate); + return 0; + } + } else { + if((rate <= MAX_RATE_FOR_N) && (rate >= MIN_RATE_FOR_N)){ + txpwr_tab_ptr = >xpwr_tab_n_40[channel]; + } else { + MCAL_FATAL("\r\nManual cal wrong rate with BW40? %d:%d\r\n", bandwidth, rate); + txpwr_tab_ptr = >xpwr_tab_n[channel]; + } + } + + *pwr_gain = GET_TXPWR_GAIN(txpwr_tab_ptr); + //MCAL_PRT("get txpwrtab gain:%d,ch:%d\r\n", *pwr_gain, channel+1); ///remove for midea + + return 1; +} + +uint8_t manual_cal_get_ble_pwr_idx(uint8_t channel) +{ + TXPWR_PTR txpwr_tab_ptr = NULL; + + if (channel > 39) + channel = 39; + + txpwr_tab_ptr = >xpwr_tab_ble[channel]; + + return (GET_TXPWR_GAIN(txpwr_tab_ptr)); +} + +void manual_cal_show_txpwr_tab(void) +{ + TXPWR_PTR txpwr_tab_ptr = NULL; + UINT32 i; + + MCAL_FATAL("txpwr table for b:\r\n"); + for(i=0; ivalue, + GET_TXPWR_FLAG(txpwr_tab_ptr), GET_TXPWR_GAIN(txpwr_tab_ptr)); + } + + MCAL_FATAL("\r\ntxpwr table for g:\r\n"); + for(i=0; ivalue, + GET_TXPWR_FLAG(txpwr_tab_ptr), GET_TXPWR_GAIN(txpwr_tab_ptr)); + } + + MCAL_FATAL("\r\ntxpwr table for n20:\r\n"); + for(i=0; ivalue, + GET_TXPWR_FLAG(txpwr_tab_ptr), GET_TXPWR_GAIN(txpwr_tab_ptr)); + } + + MCAL_FATAL("\r\ntxpwr table for n40:\r\n"); + for(i=0; ivalue, + GET_TXPWR_FLAG(txpwr_tab_ptr), GET_TXPWR_GAIN(txpwr_tab_ptr)); + } + + MCAL_FATAL("\r\ntxpwr table for ble:\r\n"); + for(i=0; ivalue, + GET_TXPWR_FLAG(txpwr_tab_ptr), GET_TXPWR_GAIN(txpwr_tab_ptr)); + } + + MCAL_FATAL("\r\nsys temper:%d\r\n", g_cur_temp); + MCAL_FATAL("sys xtal:%d\r\n", g_xtal); + //MCAL_PRT("TSSI:%d\r\n", bk7011_get_txpwr_config_reg()); + + //bk7011_cal_dcormod_show(); +} + +TXPWR_IS_RD manual_cal_txpwr_tab_is_fitted(void) +{ + return (TXPWR_TAB_B_RD | TXPWR_TAB_G_RD | TXPWR_TAB_N_RD | TXPWR_TAB_BLE); +} + +static void manual_cal_adjust_fitting(TXPWR_PTR ptr, UINT16 dist) +{ + UINT16 gain; + //if(GET_TXPWR_FLAG(ptr) == TXPWR_ELEM_UNUSED) + // return; + + gain = GET_TXPWR_GAIN(ptr); + gain = (gain > dist)? gain - dist : 0; + + SET_TXPWR_GAIN(ptr, gain); +} + +static void manual_cal_do_fitting_base(TXPWR_PTR dst, TXPWR_PTR srclow, TXPWR_PTR srchigh) +{ + UINT16 gain = 0, dist; + + if((GET_TXPWR_FLAG(srclow) == TXPWR_ELEM_UNUSED) + || (GET_TXPWR_FLAG(srchigh) == TXPWR_ELEM_UNUSED)) + return; + + if(GET_TXPWR_GAIN(srclow) > GET_TXPWR_GAIN(srchigh)) { + dist = GET_TXPWR_GAIN(srclow) - GET_TXPWR_GAIN(srchigh); +#if (SOC_BK7231N == CFG_SOC_NAME) + gain = (UINT16)((float)(dist) / 3.0 + 0.5) + GET_TXPWR_GAIN(srchigh) + 1; +#else + gain = (UINT16)((float)(dist) / 2.0) + GET_TXPWR_GAIN(srchigh); +#endif + } + else { + dist = GET_TXPWR_GAIN(srchigh) - GET_TXPWR_GAIN(srclow); +#if (SOC_BK7231N == CFG_SOC_NAME) + gain = (UINT16)((float)(dist) / 3.0 + 0.5) + GET_TXPWR_GAIN(srclow) + 1; +#else + gain = (UINT16)((float)(dist) / 2.0) + GET_TXPWR_GAIN(srclow); +#endif + } + + SET_TXPWR_GAIN(dst, gain); + SET_TXPWR_FLAG(dst, TXPWR_ELEM_INUSED); +} + +static void manual_cal_do_fitting(TXPWR_PTR dst, TXPWR_PTR srclow, TXPWR_PTR srchigh) +{ + UINT16 gain = 0; + + if((GET_TXPWR_FLAG(srclow) == TXPWR_ELEM_UNUSED) + || (GET_TXPWR_FLAG(srchigh) == TXPWR_ELEM_UNUSED)) + return; + + gain = (UINT16)((float)(GET_TXPWR_GAIN(srclow) + GET_TXPWR_GAIN(srchigh)) / 2 + 0.5); + SET_TXPWR_GAIN(dst, gain); + SET_TXPWR_FLAG(dst, TXPWR_ELEM_INUSED); +} + +void manual_cal_11b_2_ble(void) +{ + TXPWR_PTR tab_ptr = NULL; + unsigned char gain; + +#if (CFG_SOC_NAME == SOC_BK7231N) + tab_ptr = gtxpwr_tab_g; + if (ble_cal_bit == 0) { + if (GET_TXPWR_FLAG(&tab_ptr[0]) == TXPWR_ELEM_INUSED) { + gain = GET_TXPWR_GAIN(&tab_ptr[0]); + + // think ble power need to be 7db + if ((gain + 12) > ble_diff_to_wifi) { + gain = gain + 12 - ble_diff_to_wifi; + } else { + gain = 1; + } + + SET_TXPWR_GAIN(>xpwr_tab_ble[0],gain); + SET_TXPWR_FLAG(>xpwr_tab_ble[0],TXPWR_ELEM_INUSED); + } + if (GET_TXPWR_FLAG(&tab_ptr[6]) == TXPWR_ELEM_INUSED) { + gain = GET_TXPWR_GAIN(&tab_ptr[6]); + + // think ble power need to be 7db + if ((gain + 12) > ble_diff_to_wifi) { + gain = gain + 12 - ble_diff_to_wifi; + } else { + gain = 1; + } + + SET_TXPWR_GAIN(>xpwr_tab_ble[19],gain); + SET_TXPWR_FLAG(>xpwr_tab_ble[19],TXPWR_ELEM_INUSED); + } else if ((GET_TXPWR_FLAG(&tab_ptr[12]) == TXPWR_ELEM_INUSED) + && (GET_TXPWR_FLAG(&tab_ptr[0]) == TXPWR_ELEM_INUSED)) { + gain = (GET_TXPWR_GAIN(&tab_ptr[0]) + GET_TXPWR_GAIN(&tab_ptr[12])) / 2; + + if ((gain + 12) > ble_diff_to_wifi) { + gain = gain + 12 - ble_diff_to_wifi; + } else { + gain = 1; + } + + SET_TXPWR_GAIN(>xpwr_tab_ble[19],gain); + SET_TXPWR_FLAG(>xpwr_tab_ble[19],TXPWR_ELEM_INUSED); + } + if (GET_TXPWR_FLAG(&tab_ptr[12]) == TXPWR_ELEM_INUSED) { + gain = GET_TXPWR_GAIN(&tab_ptr[12]); + + // think ble power need to be 7db + if ((gain + 12) > ble_diff_to_wifi) { + gain = gain + 12 - ble_diff_to_wifi; + } else { + gain = 1; + } + + SET_TXPWR_GAIN(>xpwr_tab_ble[39],gain); + SET_TXPWR_FLAG(>xpwr_tab_ble[39],TXPWR_ELEM_INUSED); + } + } else if ((ble_cal_bit & 0x2) == 0x2) { + if ((ble_cal_bit & 0x1) == 0) { + if ((GET_TXPWR_FLAG(&tab_ptr[0]) == TXPWR_ELEM_INUSED) + && (GET_TXPWR_FLAG(&tab_ptr[6]) == TXPWR_ELEM_INUSED)) { + gain = (char)GET_TXPWR_GAIN(>xpwr_tab_ble[19]) - ((char)GET_TXPWR_GAIN(&tab_ptr[6]) - (char)GET_TXPWR_GAIN(&tab_ptr[0])); + SET_TXPWR_GAIN(>xpwr_tab_ble[0],gain); + SET_TXPWR_FLAG(>xpwr_tab_ble[0],TXPWR_ELEM_INUSED); + } + } + if ((ble_cal_bit & 0x4) == 0) { + if ((GET_TXPWR_FLAG(&tab_ptr[6]) == TXPWR_ELEM_INUSED) + && (GET_TXPWR_FLAG(&tab_ptr[12]) == TXPWR_ELEM_INUSED)) { + gain = (char)GET_TXPWR_GAIN(>xpwr_tab_ble[19]) - ((char)GET_TXPWR_GAIN(&tab_ptr[6]) - (char)GET_TXPWR_GAIN(&tab_ptr[12])); + SET_TXPWR_GAIN(>xpwr_tab_ble[39],gain); + SET_TXPWR_FLAG(>xpwr_tab_ble[39],TXPWR_ELEM_INUSED); + } + } + } + +#else + if (ble_cal_bit == 0) { + tab_ptr = gtxpwr_tab_b; + if((GET_TXPWR_FLAG(&tab_ptr[0]) == TXPWR_ELEM_INUSED) + &&(GET_TXPWR_FLAG(&tab_ptr[12]) == TXPWR_ELEM_INUSED)) { + gain = (GET_TXPWR_GAIN(&tab_ptr[0]) + GET_TXPWR_GAIN(&tab_ptr[12]))/2; + if ((gain > 20) && (gain <= 31)) { + gain -= 9; + } else if((gain >= 15) && (gain <= 20)) { + gain -= 7; + } else { + gain -= 5; + } + SET_TXPWR_GAIN(>xpwr_tab_ble[19],gain); + SET_TXPWR_FLAG(>xpwr_tab_ble[19],TXPWR_ELEM_INUSED); + } + } +#endif +} + +UINT32 manual_cal_fitting_txpwr_tab(void) +{ + UINT32 ret = 0, i; + TXPWR_PTR tab_ptr = NULL; + + // for b, check ch1, ch7, ch13 is in used + tab_ptr = gtxpwr_tab_b; + if((GET_TXPWR_FLAG(&tab_ptr[0]) == TXPWR_ELEM_UNUSED) + ||(GET_TXPWR_FLAG(&tab_ptr[12]) == TXPWR_ELEM_UNUSED) ){ + MCAL_WARN("txpwr table for b fitting failed!, ch1 ch13 unused\r\n"); + } else { + if(GET_TXPWR_FLAG(&tab_ptr[6]) == TXPWR_ELEM_UNUSED) { + // fitting ch7, use ch1, ch13 + manual_cal_do_fitting_base(&tab_ptr[6], &tab_ptr[0], &tab_ptr[12]); + } + // fitting ch4, use ch1, ch7 + manual_cal_do_fitting(&tab_ptr[3], &tab_ptr[0], &tab_ptr[6]); + // fitting ch2, use ch1, ch4 + manual_cal_do_fitting(&tab_ptr[1], &tab_ptr[0], &tab_ptr[3]); + // fitting ch3, use ch2, ch4 + manual_cal_do_fitting(&tab_ptr[2], &tab_ptr[1], &tab_ptr[3]); + // fitting ch5, use ch4, ch7 + manual_cal_do_fitting(&tab_ptr[4], &tab_ptr[3], &tab_ptr[6]); + // fitting ch6, use ch5, ch7 + manual_cal_do_fitting(&tab_ptr[5], &tab_ptr[4], &tab_ptr[6]); + + // fitting ch10, use ch7, ch13 + manual_cal_do_fitting(&tab_ptr[9], &tab_ptr[6], &tab_ptr[12]); + // fitting ch8, use ch7, ch10 + manual_cal_do_fitting(&tab_ptr[7], &tab_ptr[6], &tab_ptr[9]); + // fitting ch9, use ch8, ch10 + manual_cal_do_fitting(&tab_ptr[8], &tab_ptr[7], &tab_ptr[9]); + // fitting ch11, use ch10, ch13 + manual_cal_do_fitting(&tab_ptr[10], &tab_ptr[9], &tab_ptr[12]); + // fitting ch12, use ch11, ch13 + manual_cal_do_fitting(&tab_ptr[11], &tab_ptr[10], &tab_ptr[12]); + + // fitting ch14, the same as ch13 + manual_cal_do_fitting(&tab_ptr[13], &tab_ptr[12], &tab_ptr[12]); + + // clear flag, only base change set used + for(i=0; i 31) + diff = 31; + + g_dif_g_n20 = (diff&GAIN_MASK); + manual_cal_fit_txpwr_tab_n_20(g_dif_g_n20); +} + +void manual_cal_set_dif_g_n40(UINT32 diff) +{ + if(diff == g_dif_g_n40) { + MCAL_PRT("no need to do, same with g_dif_g_n40:%d\r\n", g_dif_g_n40); + return; + } + + if(diff > 31) + diff = 31; + + g_dif_g_n40 = (diff&GAIN_MASK); + manual_cal_fit_txpwr_tab_n_40(g_dif_g_n40); +} + +void manual_cal_set_dif_ble(UINT32 diff) +{ + ble_diff_to_wifi = diff; +} + +//////////////////////////////////////////////////////////////////////////////// +static UINT32 manual_cal_search_opt_tab(UINT32 *len) +{ + UINT32 ret = 0, status; + DD_HANDLE flash_handle; + TXPWR_ELEM_ST head; + #if CFG_SUPPORT_ALIOS + hal_logic_partition_t *pt = hal_flash_get_info(HAL_PARTITION_RF_FIRMWARE); + #else + bk_logic_partition_t *pt = bk_flash_get_info(BK_PARTITION_RF_FIRMWARE); + #endif + + *len = 0; + flash_handle = ddev_open(FLASH_DEV_NAME, &status, 0); + ddev_read(flash_handle, (char *)&head, sizeof(TXPWR_ELEM_ST), pt->partition_start_addr);//TXPWR_TAB_FLASH_ADDR); + if(BK_FLASH_OPT_TLV_HEADER == head.type){ + *len = head.len + sizeof(TAG_TXPWR_ST); + ret = 1; + } + ddev_close(flash_handle); + + return ret; +} + +static UINT32 manual_cal_search_txpwr_tab(UINT32 type, UINT32 start_addr) +{ + UINT32 status, addr, end_addr; + DD_HANDLE flash_handle; + TXPWR_ELEM_ST head; + + status = manual_cal_search_opt_tab(&addr); + if(!status) { + return 0; + } + + flash_handle = ddev_open(FLASH_DEV_NAME, &status, 0); + ddev_read(flash_handle, (char *)&head, sizeof(TXPWR_ELEM_ST), start_addr); + addr = start_addr + sizeof(TXPWR_ELEM_ST); + end_addr = addr + head.len; + while(addr < end_addr) { + ddev_read(flash_handle, (char *)&head, sizeof(TXPWR_ELEM_ST), addr); + if(type == head.type){ + break; + } else { + addr += sizeof(TXPWR_ELEM_ST); + addr += head.len; + } + } + + if(addr >= end_addr) { + addr = 0; + } + ddev_close(flash_handle); + + return addr; +} + +static UINT8 manual_cal_update_flash_area(UINT32 addr_offset, char *buf, UINT32 len) +{ + DD_HANDLE flash_handle = DD_HANDLE_UNVALID; + UINT32 param, status, write_len, write_addr, flash_len; + UINT8 ret = 0; + UINT8 *read_buf = NULL; + UINT8 check_times = BK_FLASH_WRITE_CHECK_TIMES; + #if CFG_SUPPORT_ALIOS + hal_logic_partition_t *pt = hal_flash_get_info(HAL_PARTITION_RF_FIRMWARE); + #else + bk_logic_partition_t *pt = bk_flash_get_info(BK_PARTITION_RF_FIRMWARE); + #endif + + if(addr_offset > (BK_FLASH_SECTOR_SIZE)){ + MCAL_FATAL("write flash addroffset error:%08x\r\n", addr_offset); + return 1; + } + if(len == 0) + return 0; + + status = manual_cal_search_opt_tab(&flash_len); + if(status && (flash_len >= (addr_offset + len))) { + // read all flash otp + write_len = flash_len; + } else { + write_len = addr_offset + len; + } + + write_addr = pt->partition_start_addr;//TXPWR_TAB_FLASH_ADDR; + + read_buf = (UINT8*)os_malloc(write_len); + if(!read_buf){ + MCAL_FATAL("cann't malloc buf for flash write\r\n"); + ret = 1; + goto updata_exit; + } + + flash_handle = ddev_open(FLASH_DEV_NAME, &status, 0); + +write_again: + if(addr_offset) { + status = ddev_read(flash_handle, (char*)read_buf, write_len, write_addr); + if(status != FLASH_SUCCESS) { + MCAL_FATAL("cann't read flash before write\r\n"); + ret = 1; + goto updata_exit; + } + if (0 == os_memcmp(read_buf+addr_offset, buf, len)) + { + MCAL_WARN("same value ignore update\r\n"); + goto updata_exit; + } + } + + os_memcpy(read_buf+addr_offset, buf, len); + + hal_flash_lock(); + + #if CFG_SUPPORT_ALIOS + hal_flash_dis_secure(0, 0, 0); + #else + bk_flash_enable_security(FLASH_PROTECT_NONE); + #endif + + param = write_addr; + ddev_control(flash_handle, CMD_FLASH_ERASE_SECTOR, ¶m); + + status = ddev_write(flash_handle, (char *)read_buf, write_len, write_addr); + + if(status != FLASH_SUCCESS) { + MCAL_FATAL("save txpwr tab to flash failed\r\n"); + ret = 1; + hal_flash_unlock(); + goto updata_exit; + } + + #if CFG_SUPPORT_ALIOS + hal_flash_enable_secure(0, 0, 0); + #else + bk_flash_enable_security(FLASH_PROTECT_ALL); + #endif + hal_flash_unlock(); + + { + UINT8 *check_buf = read_buf, *org_buf = (UINT8 *)buf; + UINT32 check_addr = write_addr + addr_offset; + UINT8 check_result; + + os_memset(check_buf, 0, len); + + status = ddev_read(flash_handle, (char*)check_buf, len, check_addr); + if(status != FLASH_SUCCESS) { + MCAL_FATAL("cann't read flash in check\r\n"); + ret = 1; + goto updata_exit; + } + + check_result = 1; + for(int i=0; i (BK_FLASH_SECTOR_SIZE)){ + MCAL_FATAL("read flash addr error:%08x\r\n", addr_offset); + return 0; + } + + addr = pt->partition_start_addr+addr_offset;//TXPWR_TAB_FLASH_ADDR + addr_offset; + + flash_handle = ddev_open(FLASH_DEV_NAME, &status, 0); + status = ddev_read(flash_handle, buf, len, addr); + ddev_close(flash_handle); + + if(status != FLASH_SUCCESS) + ret = 0; + else + ret = len; + + return ret; +} + +UINT32 manual_cal_load_txpwr_tab_flash(void) +{ + UINT32 status, addr, addr_start; + DD_HANDLE flash_handle; + TXPWR_ELEM_ST head; + TXPWR_IS_RD is_ready_flash = 0; + #if CFG_SUPPORT_ALIOS + hal_logic_partition_t *pt = hal_flash_get_info(HAL_PARTITION_RF_FIRMWARE); + #else + bk_logic_partition_t *pt = bk_flash_get_info(BK_PARTITION_RF_FIRMWARE); + #endif + + if(bk7011_is_rfcali_mode_auto()) + { + return TXPWR_NONE_RD; + } + + addr_start = manual_cal_search_txpwr_tab(TXPWR_TAB_TAB, pt->partition_start_addr);//TXPWR_TAB_FLASH_ADDR); + if(!addr_start) { + MCAL_WARN("NO TXPWR_TAB_TAB found in flash\r\n"); + return TXPWR_NONE_RD; + } + + addr = manual_cal_search_txpwr_tab(TXPWR_ENABLE_ID, addr_start); + if(!addr) + { + MCAL_WARN("NO TXPWR_ENABLE_ID found in flash\r\n"); + return TXPWR_NONE_RD; + } + + flash_handle = ddev_open(FLASH_DEV_NAME, &status, 0); + ddev_read(flash_handle, (char *)&head, sizeof(TXPWR_ELEM_ST), addr); + ddev_read(flash_handle, (char *)&status, head.len, addr + sizeof(TXPWR_ELEM_ST)); + is_ready_flash = status; + MCAL_PRT("flash txpwr table:0x%x\r\n", is_ready_flash); + + // If txpwr tab in flash is unused, we should use auto calibration result + if(is_ready_flash == TXPWR_NONE_RD){ + MCAL_WARN("txpwr tabe in flash is unused\r\n"); + return TXPWR_NONE_RD; + } + + // for txpwr b + if(is_ready_flash & TXPWR_TAB_B_RD) { + addr = manual_cal_search_txpwr_tab(TXPWR_TAB_B_ID, addr_start); + if(addr) { + ddev_read(flash_handle, (char *)&head, sizeof(TXPWR_ELEM_ST), addr); + ddev_read(flash_handle, (char *)gtxpwr_tab_b, head.len, addr + sizeof(TXPWR_ELEM_ST)); + }else { + MCAL_WARN("txpwr tabe b in flash no found\r\n"); + } + } + + // for txpwr g and n20? + if(is_ready_flash & TXPWR_TAB_G_RD) { + //for g first + addr = manual_cal_search_txpwr_tab(TXPWR_TAB_G_ID, addr_start); + if(addr) { + ddev_read(flash_handle, (char *)&head, sizeof(TXPWR_ELEM_ST), addr); + ddev_read(flash_handle, (char *)gtxpwr_tab_g, head.len, addr + sizeof(TXPWR_ELEM_ST)); + } else { + MCAL_WARN("txpwr tabe g in flash no found\r\n"); + } + + // for n20 + addr = manual_cal_search_txpwr_tab(TXPWR_TAB_DIF_GN20_ID, addr_start); + if(addr) { + ddev_read(flash_handle, (char *)&head, sizeof(TXPWR_ELEM_ST), addr); + ddev_read(flash_handle, (char *)&g_dif_g_n20, head.len, addr + sizeof(TXPWR_ELEM_ST)); + MCAL_PRT("dif g and n20 ID in flash:%d\r\n", g_dif_g_n20); + } else { + MCAL_WARN("dif g and n20 ID in flash no found, use def:%d\r\n", g_dif_g_n20); + } + manual_cal_fit_txpwr_tab_n_20(g_dif_g_n20); + } + + // for txpwr N40 + if(is_ready_flash & TXPWR_TAB_N_RD) { + addr = manual_cal_search_txpwr_tab(TXPWR_TAB_N_ID, addr_start); + if(addr) { + ddev_read(flash_handle, (char *)&head, sizeof(TXPWR_ELEM_ST), addr); + ddev_read(flash_handle, (char *)gtxpwr_tab_n_40, head.len, addr + sizeof(TXPWR_ELEM_ST)); + }else { + MCAL_WARN("txpwr tabe n in flash no found\r\n"); + } + } + // only need load dist40 + addr = manual_cal_search_txpwr_tab(TXPWR_TAB_DIF_GN40_ID, addr_start); + if(addr) { + ddev_read(flash_handle, (char *)&head, sizeof(TXPWR_ELEM_ST), addr); + ddev_read(flash_handle, (char *)&g_dif_g_n40, head.len, addr + sizeof(TXPWR_ELEM_ST)); + MCAL_PRT("dif g and n40 ID in flash:%d\r\n", g_dif_g_n40); + } else { + MCAL_WARN("dif g and n40 ID in flash no found, use def:%d\r\n", g_dif_g_n40); + } + + // for ble tx pwr + if(is_ready_flash & TXPWR_TAB_BLE) { + addr = manual_cal_search_txpwr_tab(TXPWR_TAB_BLE_ID, addr_start); + if(addr) { + ddev_read(flash_handle, (char *)&head, sizeof(TXPWR_ELEM_ST), addr); + ddev_read(flash_handle, (char *)gtxpwr_tab_ble, head.len, addr + sizeof(TXPWR_ELEM_ST)); + }else { + MCAL_WARN("txpwr tabe ble in flash no found\r\n"); + } + } + + ddev_close(flash_handle); + MCAL_PRT("read txpwr tab from flash success\r\n"); + + return is_ready_flash; +} + +UINT32 manual_cal_load_default_txpwr_tab(UINT32 is_ready_flash) +{ + #if TXPWR_DEFAULT_TAB + if(bk7011_is_rfcali_mode_auto()) + { + return 0; + } + + if(!(is_ready_flash & TXPWR_TAB_B_RD)) { + os_memcpy(gtxpwr_tab_b, gtxpwr_tab_def_b, sizeof(gtxpwr_tab_def_b)); + MCAL_WARN("Load default txpwr for b:%p\r\n", gtxpwr_tab_def_b); + } + + if(!(is_ready_flash & TXPWR_TAB_G_RD)) { + os_memcpy(gtxpwr_tab_g, gtxpwr_tab_def_g, sizeof(gtxpwr_tab_def_g)); + MCAL_WARN("Load default txpwr for g:%p\r\n", gtxpwr_tab_def_g); + + manual_cal_fit_txpwr_tab_n_20(g_dif_g_n20); + MCAL_WARN("fit n20 table with dist:%d\r\n", g_dif_g_n20); + } + + if(!(is_ready_flash & TXPWR_TAB_N_RD)) { + os_memcpy(gtxpwr_tab_n_40, gtxpwr_tab_def_n_40, sizeof(gtxpwr_tab_def_n_40)); + MCAL_WARN("Load default txpwr for n40:%p\r\n", gtxpwr_tab_def_n_40); + } + + if(!(is_ready_flash & TXPWR_TAB_BLE)) { + os_memcpy(gtxpwr_tab_ble, gtxpwr_tab_def_ble, sizeof(gtxpwr_tab_def_ble)); + MCAL_WARN("Load default txpwr for ble:%p\r\n", gtxpwr_tab_def_ble); + } + #endif + return 0; +} + +int manual_cal_save_txpwr_tab_to_flash(void) +{ + TXPWR_IS_RD is_ready, is_ready_flash; + UINT32 len = 0, txpwr_len = 0, flash_len = 0; + UINT8 *buf = NULL, *txpwr_buf = NULL;; + TAG_TXPWR_ST tag_txpwr; + TAG_TXPWR_PTR tag_txpwr_ptr = NULL; + TAG_ENABLE_ST tag_enable; + TAG_ENABLE_PTR tag_enable_ptr = NULL; + TAG_TXPWR_TAB_ST tag_tab; + TAG_TXPWR_TAB_PTR tag_tab_ptr = NULL; + TAG_DIF_ST tag_dif; + TAG_DIF_PTR tag_dif_ptr = NULL; + + UINT32 status, addr, addr_start; + DD_HANDLE flash_handle; + TXPWR_ELEM_ST head; + #if CFG_SUPPORT_ALIOS + hal_logic_partition_t *pt = hal_flash_get_info(HAL_PARTITION_RF_FIRMWARE); + #else + bk_logic_partition_t *pt = bk_flash_get_info(BK_PARTITION_RF_FIRMWARE); + #endif + + is_ready = manual_cal_txpwr_tab_is_fitted(); + MCAL_PRT("current txpwr table:0x%x\r\n", is_ready); + if(is_ready == TXPWR_NONE_RD) { + MCAL_WARN("TXPWR_NONE_RD, Cann't save txpwr tabe in flash\r\n"); + return 0; + } + + // alloc all memery at onece, so we no need to change the size of buf in combin function + txpwr_len = sizeof(TAG_TXPWR_ST) + sizeof(TAG_ENABLE_ST) + + 3*sizeof(TAG_TXPWR_TAB_ST) + 2*sizeof(TAG_DIF_ST) + + sizeof(TAG_TXPWR_TAB_BLE_ST) + sizeof(TAG_ENABLE_ST) + + sizeof(TAG_TXPWR_TAB_ST); + + + // read flash, then combin the table in flash + flash_handle = ddev_open(FLASH_DEV_NAME, &status, 0); + status = manual_cal_search_opt_tab(&flash_len); + // Has TLV Header? + if(status) { + addr_start = manual_cal_search_txpwr_tab(TXPWR_TAB_TAB, pt->partition_start_addr);//TXPWR_TAB_FLASH_ADDR); + if(!addr_start) { + // not TXPWR_TAB_TAB, but has any other id, so attch TXPWR_TAB_TAB after the table + len = flash_len + txpwr_len; + buf = (UINT8*)os_malloc(len); + if(!buf) { + MCAL_FATAL("no memory for chipinfo save to flash\r\n"); + return 0; + } + // copy flash + ddev_read(flash_handle, (char *)buf, flash_len, pt->partition_start_addr);//TXPWR_TAB_FLASH_ADDR); + ddev_close(flash_handle); + + // updata new TLV header + tag_txpwr_ptr = (TAG_TXPWR_PTR)buf; + tag_txpwr.head.type= BK_FLASH_OPT_TLV_HEADER; + tag_txpwr.head.len = len - sizeof(TAG_TXPWR_ST);; + os_memcpy(tag_txpwr_ptr, &tag_txpwr, sizeof(TAG_TXPWR_ST)); + + txpwr_buf = (UINT8 *)(buf + flash_len); + addr_start = pt->partition_start_addr;//TXPWR_TAB_FLASH_ADDR; + }else { + // txpwr is exist, and found start addr. + len = txpwr_len; + txpwr_buf = buf = (UINT8*)os_malloc(txpwr_len); + if(!buf) { + MCAL_FATAL("no memory for txpwr tab save to flash\r\n"); + return 0; + } + } + } else { + // nothing in flash, write TLV with chipid + MCAL_WARN("NO BK_FLASH_OPT_TLV_HEADER found, save_txpwr_tab_to_flash failed\r\n"); + return 0; + } + + is_ready_flash = TXPWR_NONE_RD; + addr = manual_cal_search_txpwr_tab(TXPWR_ENABLE_ID, addr_start); + if(addr) { + ddev_read(flash_handle, (char *)&head, sizeof(TXPWR_ELEM_ST), addr); + ddev_read(flash_handle, (char *)&is_ready_flash, head.len, addr + sizeof(TXPWR_ELEM_ST)); + MCAL_PRT("flash txpwr table:0x%x\r\n", is_ready_flash); + } + + // for tag TXPW + tag_txpwr_ptr = (TAG_TXPWR_PTR)txpwr_buf; + tag_txpwr.head.type = TXPWR_TAB_TAB; + tag_txpwr.head.len = txpwr_len - sizeof(TAG_TXPWR_ST); + os_memcpy(tag_txpwr_ptr, &tag_txpwr, sizeof(TAG_TXPWR_ST)); + txpwr_buf = (UINT8*)(txpwr_buf + sizeof(TAG_TXPWR_ST)); + + // for tag TXPWR_ENABLE_ID + tag_enable_ptr = (TAG_ENABLE_PTR)(txpwr_buf); + tag_enable.head.type = TXPWR_ENABLE_ID; + tag_enable.head.len = sizeof(tag_enable.flag); + + tag_enable.flag = (UINT32)TXPWR_NONE_RD; + os_memcpy(tag_enable_ptr, &tag_enable, sizeof(TAG_ENABLE_ST)); + txpwr_buf = (UINT8*)(txpwr_buf + sizeof(TAG_ENABLE_ST)); + + // for tag TXPWR_TAB_B_ID + tag_tab_ptr = (TAG_TXPWR_TAB_PTR)(txpwr_buf); + tag_tab.head.type = TXPWR_TAB_B_ID; + tag_tab.head.len = sizeof(TXPWR_ST)*WLAN_2_4_G_CHANNEL_NUM; + if(is_ready & TXPWR_TAB_B_RD) { + os_memcpy(&tag_tab.tab[0], gtxpwr_tab_b, tag_tab.head.len); + } else if(is_ready_flash & TXPWR_TAB_B_RD) { + addr = manual_cal_search_txpwr_tab(TXPWR_TAB_B_ID, addr_start); + if(addr) { + ddev_read(flash_handle, (char *)&head, sizeof(TXPWR_ELEM_ST), addr); + ddev_read(flash_handle, (char *)&tag_tab.tab[0], head.len, addr + sizeof(TXPWR_ELEM_ST)); + } else { + MCAL_PRT("txpwr tabe b in flash no found\r\n"); + } + } + os_memcpy(tag_tab_ptr, &tag_tab, sizeof(TAG_TXPWR_TAB_ST)); + txpwr_buf = (UINT8*)(txpwr_buf + sizeof(TAG_TXPWR_TAB_ST)); + + + // for tag TXPWR_TAB_G_ID + tag_tab_ptr = (TAG_TXPWR_TAB_PTR)(txpwr_buf); + tag_tab.head.type = TXPWR_TAB_G_ID; + tag_tab.head.len = sizeof(TXPWR_ST)*WLAN_2_4_G_CHANNEL_NUM; + if(is_ready & TXPWR_TAB_G_RD) { + os_memcpy(&tag_tab.tab[0], gtxpwr_tab_g, tag_tab.head.len); + } else if(is_ready_flash & TXPWR_TAB_G_RD) { + addr = manual_cal_search_txpwr_tab(TXPWR_TAB_G_ID, addr_start); + if(addr) { + ddev_read(flash_handle, (char *)&head, sizeof(TXPWR_ELEM_ST), addr); + ddev_read(flash_handle, (char *)&tag_tab.tab[0], head.len, addr + sizeof(TXPWR_ELEM_ST)); + } else { + MCAL_PRT("txpwr tabe g in flash no found\r\n"); + } + } + os_memcpy(tag_tab_ptr, &tag_tab, sizeof(TAG_TXPWR_TAB_ST)); + txpwr_buf = (UINT8*)(txpwr_buf + sizeof(TAG_TXPWR_TAB_ST)); + + // for tag TXPWR_TAB_N_ID + tag_tab_ptr = (TAG_TXPWR_TAB_PTR)(txpwr_buf); + tag_tab.head.type = TXPWR_TAB_N_ID; + tag_tab.head.len = sizeof(TXPWR_ST)*WLAN_2_4_G_CHANNEL_NUM; + if(is_ready & TXPWR_TAB_N_RD) { + os_memcpy(&tag_tab.tab[0], gtxpwr_tab_n_40, tag_tab.head.len); + } else if(is_ready_flash & TXPWR_TAB_N_RD) { + addr = manual_cal_search_txpwr_tab(TXPWR_TAB_N_ID, addr_start); + if(addr) { + ddev_read(flash_handle, (char *)&head, sizeof(TXPWR_ELEM_ST), addr); + ddev_read(flash_handle, (char *)&tag_tab.tab[0], head.len, addr + sizeof(TXPWR_ELEM_ST)); + } else { + MCAL_PRT("txpwr tabe N in flash no found\r\n"); + } + } + os_memcpy(tag_tab_ptr, &tag_tab, sizeof(TAG_TXPWR_TAB_ST)); + txpwr_buf = (UINT8*)(txpwr_buf + sizeof(TAG_TXPWR_TAB_ST)); + + // for tag TXPWR_TAB_DIF_GN20_ID + tag_dif_ptr = (TAG_DIF_PTR)(txpwr_buf); + tag_dif.head.type = TXPWR_TAB_DIF_GN20_ID; + tag_dif.head.len = sizeof(UINT32); + tag_dif.differ = g_dif_g_n20; + os_memcpy(tag_dif_ptr, &tag_dif, sizeof(TAG_DIF_ST)); + txpwr_buf = (UINT8*)(txpwr_buf + sizeof(TAG_DIF_ST)); + + // for tag TXPWR_TAB_DIF_GN40_ID + tag_dif_ptr = (TAG_DIF_PTR)(txpwr_buf); + tag_dif.head.type = TXPWR_TAB_DIF_GN40_ID; + tag_dif.head.len = sizeof(UINT32); + tag_dif.differ = g_dif_g_n40; + os_memcpy(tag_dif_ptr, &tag_dif, sizeof(TAG_DIF_ST)); + txpwr_buf = (UINT8*)(txpwr_buf + sizeof(TAG_DIF_ST)); + + // for tag TXPWR_TAB_BLE_ID + TAG_TXPWR_TAB_BLE_PTR tag_tab_ble_ptr = (TAG_TXPWR_TAB_BLE_PTR)(txpwr_buf); + TAG_TXPWR_TAB_BLE_ST tag_tab_ble; + tag_tab_ble.head.type = TXPWR_TAB_BLE_ID; + tag_tab_ble.head.len = sizeof(TXPWR_ST)*BLE_2_4_G_CHANNEL_NUM; + if(is_ready & TXPWR_TAB_BLE) { + os_memcpy(&tag_tab_ble.tab[0], gtxpwr_tab_ble, tag_tab_ble.head.len); + } else if(is_ready_flash & TXPWR_TAB_BLE) { + addr = manual_cal_search_txpwr_tab(TXPWR_TAB_BLE_ID, addr_start); + if(addr) { + ddev_read(flash_handle, (char *)&head, sizeof(TXPWR_ELEM_ST), addr); + ddev_read(flash_handle, (char *)&tag_tab_ble.tab[0], head.len, addr + sizeof(TXPWR_ELEM_ST)); + } else { + MCAL_PRT("txpwr tabe ble in flash no found\r\n"); + } + } + os_memcpy(tag_tab_ble_ptr, &tag_tab_ble, sizeof(TAG_TXPWR_TAB_BLE_ST)); + txpwr_buf = (UINT8*)(txpwr_buf + sizeof(TAG_TXPWR_TAB_BLE_ST)); + + // for tag TXPWR_TAB_CALI_STATUTS + tag_enable_ptr = (TAG_ENABLE_PTR)(txpwr_buf); + tag_enable.head.type = TXPWR_TAB_CALI_STATUTS; + tag_enable.head.len = sizeof(tag_enable.flag); + // wlays write 0, only save position in flash,. + // txevm -e 4 0/1 can write it again + tag_enable.flag = CALI_STA_NOFOUND; //manual_cal_g_rfcali_status(); + os_memcpy(tag_enable_ptr, &tag_enable, sizeof(TAG_ENABLE_ST)); + txpwr_buf = (UINT8*)(txpwr_buf + sizeof(TAG_ENABLE_ST)); + + ddev_close(flash_handle); + + addr_start -= pt->partition_start_addr;//TXPWR_TAB_FLASH_ADDR; + manual_cal_update_flash_area(addr_start, (char *)buf, len); + os_free(buf); + + return 1; +} + +int manual_cal_save_chipinfo_tab_to_flash(void) +{ + UINT32 len = 0, chipinfo_len = 0, flash_len = 0; + UINT8 *buf = NULL, *info_buf = NULL; + TAG_TXPWR_ST tag_txpwr; + TAG_TXPWR_PTR tag_txpwr_ptr = NULL; + TAG_COMM_ST tag_com; + TAG_COMM_PTR tag_com_ptr = NULL; + TAG_CHIPMAC_ST tag_mac; + TAG_CHIPMAC_PTR tag_mac_ptr = NULL; + TAG_LPF_IQ_ST tag_lpf_iq; + TAG_LPF_IQ_PTR tag_lpf_iq_ptr = NULL; + UINT32 status, addr_start; + DD_HANDLE flash_handle; + #if CFG_SUPPORT_ALIOS + hal_logic_partition_t *pt = hal_flash_get_info(HAL_PARTITION_RF_FIRMWARE); + #else + bk_logic_partition_t *pt = bk_flash_get_info(BK_PARTITION_RF_FIRMWARE); + #endif + + chipinfo_len = sizeof(TAG_TXPWR_ST) + sizeof(TAG_COMM_ST) + #if MCAL_SAVE_MAC_ADDR + + sizeof(TAG_CHIPMAC_ST) + #endif + + sizeof(TAG_COMM_ST) + sizeof(TAG_COMM_ST) + sizeof(TAG_COMM_ST) + + sizeof(TAG_COMM_ST) + + sizeof(TAG_LPF_IQ_ST); + + flash_handle = ddev_open(FLASH_DEV_NAME, &status, 0); + status = manual_cal_search_opt_tab(&flash_len); + // Has TLV Header? + if(status) { + addr_start = manual_cal_search_txpwr_tab(TXID, pt->partition_start_addr);//TXPWR_TAB_FLASH_ADDR); + if(!addr_start) { + // not txid, but has any other id, so attch txid after the table + len = flash_len + chipinfo_len; + buf = (UINT8*)os_malloc(len); + if(!buf) { + MCAL_FATAL("no memory for chipinfo save to flash\r\n"); + return 0; + } + // copy flash + ddev_read(flash_handle, (char *)buf, flash_len, pt->partition_start_addr);//TXPWR_TAB_FLASH_ADDR); + ddev_close(flash_handle); + + // updata new TLV header + tag_txpwr_ptr = (TAG_TXPWR_PTR)buf; + tag_txpwr.head.type= BK_FLASH_OPT_TLV_HEADER; + tag_txpwr.head.len = len - sizeof(TAG_TXPWR_ST); + os_memcpy(tag_txpwr_ptr, &tag_txpwr, sizeof(TAG_TXPWR_ST)); + + info_buf = (UINT8 *)(buf + flash_len); + } else { + #if 0 + // not need to write, return; + ddev_close(flash_handle); + return 0; + #else + // updata txid + len = flash_len; + buf = (UINT8*)os_malloc(len); + if(!buf) { + MCAL_FATAL("no memory for chipinfo save to flash\r\n"); + return 0; + } + // copy flash + ddev_read(flash_handle, (char *)buf, flash_len, pt->partition_start_addr);//TXPWR_TAB_FLASH_ADDR); + ddev_close(flash_handle); + + // point to txid + info_buf = (UINT8 *)(buf + sizeof(TAG_TXPWR_ST)); + #endif + } + } else { + // nothing in flash, write TLV with chipid + len = chipinfo_len + sizeof(TAG_TXPWR_ST); + + buf = (UINT8*)os_malloc(len); + if(!buf) { + MCAL_FATAL("no memory for chipinfo save to flash\r\n"); + return 0; + } + + // updata new TLV header + tag_txpwr_ptr = (TAG_TXPWR_PTR)buf; + tag_txpwr.head.type= BK_FLASH_OPT_TLV_HEADER; + tag_txpwr.head.len = len - sizeof(TAG_TXPWR_ST); + os_memcpy(tag_txpwr_ptr, &tag_txpwr, sizeof(TAG_TXPWR_ST)); + info_buf = (UINT8 *)(buf + sizeof(TAG_TXPWR_ST)); + } + + ////////////////////////////////////////////// + // for tag TXID + tag_txpwr_ptr = (TAG_TXPWR_PTR)(info_buf); + tag_txpwr.head.type = TXID; + tag_txpwr.head.len = chipinfo_len - sizeof(TAG_TXPWR_ST); + os_memcpy(tag_txpwr_ptr, &tag_txpwr, sizeof(TAG_TXPWR_ST)); + + // for tag TXID_ID + info_buf = (UINT8 *)(info_buf + sizeof(TAG_TXPWR_ST)); + tag_com_ptr = (TAG_COMM_PTR)(info_buf); + tag_com.head.type = TXID_ID; + tag_com.head.len = sizeof(tag_com.value); + tag_com.value = (UINT32)DEFAULT_TXID_ID; + os_memcpy(tag_com_ptr, &tag_com, sizeof(TAG_COMM_ST)); + +#if MCAL_SAVE_MAC_ADDR + // for tag TXID_MAC + info_buf = (UINT8 *)(info_buf + sizeof(TAG_COMM_ST)); + tag_mac_ptr = (TAG_CHIPMAC_PTR)(info_buf); + tag_mac.head.type = TXID_MAC; + tag_mac.head.len = 6; + os_memcpy(&tag_mac.arry[0], system_mac, 6); + os_memcpy(tag_mac_ptr, &tag_mac, sizeof(TAG_CHIPMAC_ST)); + info_buf = (UINT8 *)(info_buf + sizeof(TAG_CHIPMAC_ST)); +#else + info_buf = (UINT8 *)(info_buf + sizeof(TAG_COMM_ST)); +#endif + // for tag TXID_THERMAL + //manual_cal_get_current_temperature(); + os_printf("save sys temper:%d\r\n", g_cur_temp); + tag_com_ptr = (TAG_COMM_PTR)(info_buf ); + tag_com.head.type = TXID_THERMAL; + tag_com.head.len = sizeof(tag_com.value); + tag_com.value = (UINT32)g_cur_temp; + os_memcpy(tag_com_ptr, &tag_com, sizeof(TAG_COMM_ST)); + + // for tag TXID_CHANNEL + info_buf = (UINT8 *)(info_buf + sizeof(TAG_COMM_ST)); + tag_com_ptr = (TAG_COMM_PTR)(info_buf); + tag_com.head.type = TXID_CHANNEL; + tag_com.head.len = sizeof(tag_com.value); + tag_com.value = (UINT32)DEFAULT_TXID_CHANNEL; + os_memcpy(tag_com_ptr, &tag_com, sizeof(TAG_COMM_ST)); + + // for tag TXID_XTAL + info_buf = (UINT8 *)(info_buf + sizeof(TAG_COMM_ST)); + tag_com_ptr = (TAG_COMM_PTR)(info_buf); + tag_com.head.type = TXID_XTAL; + tag_com.head.len = sizeof(tag_com.value); + tag_com.value = (UINT32)g_xtal; + os_memcpy(tag_com_ptr, &tag_com, sizeof(TAG_COMM_ST)); + + // for tag TXID_ADC + info_buf = (UINT8 *)(info_buf + sizeof(TAG_COMM_ST)); + tag_com_ptr = (TAG_COMM_PTR)(info_buf); + tag_com.head.type = TXID_ADC; + tag_com.head.len = sizeof(tag_com.value); + UINT32 *p_temp = (UINT32 *)&saradc_val; + tag_com.value = *p_temp; + ///tag_com.value = *((UINT32 *)&saradc_val); + os_memcpy(tag_com_ptr, &tag_com, sizeof(TAG_COMM_ST)); + + // for tag lpf i&q + info_buf = (UINT8 *)(info_buf + sizeof(TAG_COMM_ST)); + tag_lpf_iq_ptr = (TAG_LPF_IQ_PTR)(info_buf); + tag_lpf_iq.head.type = TXID_LPFCAP; + tag_lpf_iq.head.len = sizeof(TAG_LPF_IQ_ST) - sizeof(TXPWR_ELEM_ST); + + tag_lpf_iq.lpf_i = g_lpf_cal_i; + tag_lpf_iq.lpf_q = g_lpf_cal_q; + os_printf("%x, %d, %d, %d\r\n", TXID_LPFCAP, tag_lpf_iq.head.len, g_lpf_cal_i, g_lpf_cal_q); + os_memcpy(tag_lpf_iq_ptr, &tag_lpf_iq, sizeof(TAG_LPF_IQ_ST)); + + manual_cal_update_flash_area(0, (char *)buf, len); + os_free(buf); + + return 1; +} + +int manual_cal_get_macaddr_from_flash(UINT8 *mac_ptr) +{ + #if MCAL_SAVE_MAC_ADDR + UINT32 flash_len = 0; + UINT32 status, addr, addr_start; + DD_HANDLE flash_handle; + TXPWR_ELEM_ST head; + #if CFG_SUPPORT_ALIOS + hal_logic_partition_t *pt = hal_flash_get_info(HAL_PARTITION_RF_FIRMWARE); + #else + bk_logic_partition_t *pt = bk_flash_get_info(BK_PARTITION_RF_FIRMWARE); + #endif + flash_handle = ddev_open(FLASH_DEV_NAME, &status, 0); + status = manual_cal_search_opt_tab(&flash_len); + // Has TLV Header? + if(status) { + addr_start = manual_cal_search_txpwr_tab(TXID, pt->partition_start_addr);//TXPWR_TAB_FLASH_ADDR); + if(!addr_start) { + // not txid, but has any other id, so attch txid after the table + MCAL_FATAL("No txid header found in flash\r\n"); + return 0; + } + } + else { + MCAL_FATAL("No TLV header found in flash\r\n"); + return 0; + } + + addr = manual_cal_search_txpwr_tab(TXID_MAC, addr_start); + if(addr) { + ddev_read(flash_handle, (char *)&head, sizeof(TXPWR_ELEM_ST), addr); + ddev_read(flash_handle, (char *)mac_ptr, head.len, addr + sizeof(TXPWR_ELEM_ST)); + //MCAL_PRT("read MAC ADDR from flash\r\n"); + }else { + MCAL_FATAL("No MAC id found in txid header \r\n"); + return 0; + } + + return 1; + #else + return 0; + #endif +} + +int manual_cal_write_macaddr_to_flash(UINT8 *mac_ptr) +{ + #if MCAL_SAVE_MAC_ADDR + UINT32 flash_len = 0; + UINT32 status, addr, addr_start; + DD_HANDLE flash_handle; + TXPWR_ELEM_ST head; + #if CFG_SUPPORT_ALIOS + hal_logic_partition_t *pt = hal_flash_get_info(HAL_PARTITION_RF_FIRMWARE); + #else + bk_logic_partition_t *pt = bk_flash_get_info(BK_PARTITION_RF_FIRMWARE); + #endif + + flash_handle = ddev_open(FLASH_DEV_NAME, &status, 0); + status = manual_cal_search_opt_tab(&flash_len); + // Has TLV Header? + if(!status) { + if (g_xtal == DEFAULT_TXID_XTAL) { + g_xtal = manual_cal_load_xtal_tag_from_flash(); + } + if (!manual_cal_save_chipinfo_tab_to_flash()) + { + MCAL_FATAL("No TLV header found in flash, init partition failed\r\n"); + return 0; + } + else + { + MCAL_FATAL("No TLV header found in flash, init partition success\r\n"); + } + } + + addr_start = manual_cal_search_txpwr_tab(TXID, pt->partition_start_addr);//TXPWR_TAB_FLASH_ADDR); + if(!addr_start) { + // not txid, but has any other id, so attch txid after the table + MCAL_FATAL("No txid header found in flash\r\n"); + return 0; + } + + addr = manual_cal_search_txpwr_tab(TXID_MAC, addr_start); + if(addr) { + ddev_read(flash_handle, (char *)&head, sizeof(TXPWR_ELEM_ST), addr); + addr += sizeof(TXPWR_ELEM_ST); + addr -= pt->partition_start_addr;//TXPWR_TAB_FLASH_ADDR; + manual_cal_update_flash_area(addr, (char *)mac_ptr, 6); //0: sucess, 1 failed + }else { + MCAL_FATAL("No MAC id found in txid header \r\n"); + return 0; + } + + return 1; + #else + return 0; + #endif +} + +UINT8 manual_cal_wirte_otp_flash(UINT32 addr, UINT32 len, UINT8 *buf) +{ + UINT8 ret = 0; + #if CFG_SUPPORT_ALIOS + hal_logic_partition_t *pt = hal_flash_get_info(HAL_PARTITION_RF_FIRMWARE); + #else + bk_logic_partition_t *pt = bk_flash_get_info(BK_PARTITION_RF_FIRMWARE); + #endif + //MCAL_PRT("wirte_otp_flash:addr:%08x, len:%d, buf:%p\r\n", addr, len, buf); + addr -= pt->partition_start_addr;//TXPWR_TAB_FLASH_ADDR; + ret = manual_cal_update_flash_area(addr, (char *)buf, len); //0: sucess, 1 failed + return ret; +} + +UINT8 manual_cal_read_otp_flash(UINT32 addr, UINT32 len, UINT8 *buf) +{ + UINT8 ret = 0; + //MCAL_PRT("read_otp_flash:addr:%08x, len:%d, buf:%p\r\n",addr, len, buf); + ret = manual_cal_read_flash(addr, (char *)buf, len); //0:failed, others: len + return ret; +} + +void manual_cal_get_current_temperature(void) +{ + UINT32 temp_value; + + if(!temp_single_get_current_temperature(&temp_value)) + g_cur_temp = temp_value; + + MCAL_FATAL("system temperature:%0d\r\n", g_cur_temp); +} + +void manual_cal_show_otp_flash(void) +{ + UINT32 status, flash_len, addr_start; + DD_HANDLE flash_handle; + #if CFG_SUPPORT_ALIOS + hal_logic_partition_t *pt = hal_flash_get_info(HAL_PARTITION_RF_FIRMWARE); + #else + bk_logic_partition_t *pt = bk_flash_get_info(BK_PARTITION_RF_FIRMWARE); + #endif + + flash_len = 0; + flash_handle = ddev_open(FLASH_DEV_NAME, &status, 0); + status = manual_cal_search_opt_tab(&flash_len); + + if(!status) { + status = 1; + flash_len = 1024; + } + + if(status) + { + UINT8 *buf = (UINT8*)os_malloc(flash_len); + if(!buf) + { + MCAL_FATAL("no memory for show_otp_flash\r\n"); + ddev_close(flash_handle); + return; + } + + os_memset(buf, 0, sizeof(flash_len)); + addr_start = pt->partition_start_addr; + // copy flash + ddev_read(flash_handle, (char *)buf, flash_len, addr_start);//TXPWR_TAB_FLASH_ADDR); + for(int i=0; ipartition_start_addr);//TXPWR_TAB_FLASH_ADDR); + if(!addr_start) { + // not txid, but has any other id, so attch txid after the table + MCAL_FATAL("No txpwr header found in flash\r\n"); + return 0; + } + } + else { + MCAL_FATAL("No TLV header found in flash\r\n"); + return 0; + } + + addr = manual_cal_search_txpwr_tab(TXPWR_TAB_CALI_STATUTS, addr_start); + if(addr) { + ddev_read(flash_handle, (char *)&head, sizeof(TXPWR_ELEM_ST), addr); + ddev_read(flash_handle, (char *)&status_bak, head.len, addr + sizeof(TXPWR_ELEM_ST)); + }else { + MCAL_FATAL("No RFCALI STATUS found in txid header\r\n"); + return 0; + } + + if(rf_status) + *rf_status = status_bak; + + return 1; +} + +int manual_cal_set_rfcali_status_inflash(UINT32 rf_status) +{ + if(manual_cal_is_in_rfcali_mode() == 0) + { + MCAL_FATAL("not in rfcali mode\r\n"); + return 0; + } + + UINT32 flash_len = 0; + UINT32 status, addr, addr_start; + DD_HANDLE flash_handle; + TXPWR_ELEM_ST head; +#if CFG_SUPPORT_ALIOS + hal_logic_partition_t *pt = hal_flash_get_info(HAL_PARTITION_RF_FIRMWARE); +#else + bk_logic_partition_t *pt = bk_flash_get_info(BK_PARTITION_RF_FIRMWARE); +#endif + + flash_handle = ddev_open(FLASH_DEV_NAME, &status, 0); + status = manual_cal_search_opt_tab(&flash_len); + // Has TLV Header? + if(status) { + addr_start = manual_cal_search_txpwr_tab(TXPWR_TAB_TAB, pt->partition_start_addr);//TXPWR_TAB_FLASH_ADDR); + if(!addr_start) { + // not txid, but has any other id, so attch txid after the table + MCAL_FATAL("No txpwr header found in flash\r\n"); + return 0; + } + } + else { + MCAL_FATAL("No TLV header found in flash\r\n"); + return 0; + } + + addr = manual_cal_search_txpwr_tab(TXPWR_TAB_CALI_STATUTS, addr_start); + if(addr) { + ddev_read(flash_handle, (char *)&head, sizeof(TXPWR_ELEM_ST), addr); + addr += sizeof(TXPWR_ELEM_ST); + addr -= pt->partition_start_addr;//TXPWR_TAB_FLASH_ADDR; + manual_cal_update_flash_area(addr, (char *)&rf_status, sizeof(UINT32)); //0: sucess, 1 failed + }else { + MCAL_FATAL("No RFCALI STATUS found in txid header\r\n"); + return 0; + } + + addr = manual_cal_search_txpwr_tab(TXPWR_ENABLE_ID, addr_start); + if(addr) { + UINT32 is_ready; + ddev_read(flash_handle, (char *)&head, sizeof(TXPWR_ELEM_ST), addr); + addr += sizeof(TXPWR_ELEM_ST); + addr -= pt->partition_start_addr;//TXPWR_TAB_FLASH_ADDR; + if(rf_status == 0) + is_ready = TXPWR_NONE_RD; + else + is_ready = manual_cal_txpwr_tab_is_fitted(); + manual_cal_update_flash_area(addr, (char *)&is_ready, sizeof(UINT32)); //0: sucess, 1 failed + }else { + MCAL_FATAL("No TXPWR_ENABLE_ID found in txid header\r\n"); + return 0; + } + + return 1; +} + +void manual_cal_set_xtal(UINT32 xtal) +{ + UINT32 param = xtal; + if(xtal > PARAM_XTALH_CTUNE_MASK) + param = PARAM_XTALH_CTUNE_MASK; + + os_null_printf("xtal_cali:%d\r\n", xtal); + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_SET_XTALH_CTUNE, ¶m); + g_xtal = param; +} + +UINT32 manual_cal_get_xtal(void) +{ + return g_xcali.last_xtal; +} + +void manual_cal_set_lpf_iq(UINT32 lpf_i, UINT32 lpf_q) +{ +#if (CFG_SOC_NAME == SOC_BK7231N) + if(lpf_q > 0x7f) + lpf_q = 0x7f; + if(lpf_i > 0x7f) + lpf_i = 0x7f; +#else + if(lpf_q > 0x3f) + lpf_q = 0x3f; + if(lpf_i > 0x3f) + lpf_i = 0x3f; +#endif + + g_lpf_cal_i = lpf_i; + g_lpf_cal_q = lpf_q; + rwnx_cal_set_lpfcap_iq(lpf_i, lpf_q); +} + +void manual_cal_load_lpf_iq_tag_flash(void) +{ + bk7011_get_tx_filter_corner((INT32 *)&g_lpf_cal_i, (INT32 *)&g_lpf_cal_q); + +#if (CFG_SOC_NAME != SOC_BK7231N) + UINT32 status, addr, addr_start; + DD_HANDLE flash_handle; + #if CFG_SUPPORT_ALIOS + hal_logic_partition_t *pt = hal_flash_get_info(HAL_PARTITION_RF_FIRMWARE); + #else + bk_logic_partition_t *pt = bk_flash_get_info(BK_PARTITION_RF_FIRMWARE); + #endif + TAG_LPF_IQ_ST lpf; + + addr_start = manual_cal_search_txpwr_tab(TXID, pt->partition_start_addr);//TXPWR_TAB_FLASH_ADDR); + if(!addr_start) { + MCAL_WARN("NO TXID found in flash, use lpf i&q:%d, %d\r\n", + g_lpf_cal_i, g_lpf_cal_q); + goto init_lpf; + } + + addr = manual_cal_search_txpwr_tab(TXID_LPFCAP, addr_start); + if(!addr) + { + MCAL_WARN("NO TXID_LPFCAP found in flash, use def %d, %d\r\n", + g_lpf_cal_i, g_lpf_cal_q); + goto init_lpf; + } + + flash_handle = ddev_open(FLASH_DEV_NAME, &status, 0); + ddev_read(flash_handle, (char *)&lpf, sizeof(TXPWR_ELEM_ST), addr); + ddev_read(flash_handle, (char *)&lpf.lpf_i, lpf.head.len, addr + sizeof(TXPWR_ELEM_ST)); + MCAL_FATAL("lpf_i & q in flash is:%d, %d\r\n", lpf.lpf_i, lpf.lpf_q); + + if (DEFAULT_TXID_LPF_CAP_I != lpf.lpf_i) + { + g_lpf_cal_i = lpf.lpf_i; + } + if (DEFAULT_TXID_LPF_CAP_Q != lpf.lpf_q) + { + g_lpf_cal_q = lpf.lpf_q; + } +init_lpf: +#endif // (CFG_SOC_NAME != SOC_BK7231N) + + rwnx_cal_set_lpfcap_iq(g_lpf_cal_i, g_lpf_cal_q); +} + +void manual_cal_load_differ_tag_from_flash(void) +{ + UINT32 status, addr, addr_start; + DD_HANDLE flash_handle; + TXPWR_ELEM_ST head; + #if CFG_SUPPORT_ALIOS + hal_logic_partition_t *pt = hal_flash_get_info(HAL_PARTITION_RF_FIRMWARE); + #else + bk_logic_partition_t *pt = bk_flash_get_info(BK_PARTITION_RF_FIRMWARE); + #endif + UINT32 dif_n20 = MOD_DIST_G_BW_N20; + UINT32 dif_n40 = MOD_DIST_G_BW_N40; + + addr_start = manual_cal_search_txpwr_tab(TXPWR_TAB_TAB, pt->partition_start_addr);//TXPWR_TAB_FLASH_ADDR); + if(!addr_start) { + MCAL_WARN("NO TXPWR_TAB_TAB found in flash, use def:%d, %d\r\n", + MOD_DIST_G_BW_N20, MOD_DIST_G_BW_N40); + goto load_diff; + } + + addr = manual_cal_search_txpwr_tab(TXPWR_TAB_DIF_GN20_ID, addr_start); + if(!addr) { + MCAL_WARN("NO TXPWR_TAB_DIF_GN20_ID found in flash, use def:%d\r\n", MOD_DIST_G_BW_N20); + } else { + flash_handle = ddev_open(FLASH_DEV_NAME, &status, 0); + ddev_read(flash_handle, (char *)&head, sizeof(TXPWR_ELEM_ST), addr); + ddev_read(flash_handle, (char *)&status, head.len, addr + sizeof(TXPWR_ELEM_ST)); + dif_n20 = status; + } + + addr = manual_cal_search_txpwr_tab(TXPWR_TAB_DIF_GN40_ID, addr_start); + if(!addr) { + MCAL_WARN("NO TXPWR_TAB_DIF_GN40_ID found in flash, use def:%d\r\n", TXPWR_TAB_DIF_GN40_ID); + } else { + flash_handle = ddev_open(FLASH_DEV_NAME, &status, 0); + ddev_read(flash_handle, (char *)&head, sizeof(TXPWR_ELEM_ST), addr); + ddev_read(flash_handle, (char *)&status, head.len, addr + sizeof(TXPWR_ELEM_ST)); + dif_n40 = status; + } + +load_diff: + MCAL_FATAL("diff in flash:n20-%d, n40-%d\r\n", dif_n20, dif_n40); + return; +} + +int manual_cal_load_xtal_tag_from_flash(void) +{ + UINT32 status, addr, addr_start; + DD_HANDLE flash_handle; + TXPWR_ELEM_ST head; + bk_logic_partition_t *pt = bk_flash_get_info(BK_PARTITION_RF_FIRMWARE); + UINT32 xtal = DEFAULT_TXID_XTAL; +#if (CFG_SOC_NAME == SOC_BK7231N) + UINT32 device_id = sctrl_ctrl(CMD_GET_DEVICE_ID, NULL); + + if ((device_id == DEVICE_ID_BK7231N_B) + || (device_id == DEVICE_ID_BK7231N_C)) + { + xtal = DEFAULT_TXID_XTAL_C; + } +#endif + + addr_start = manual_cal_search_txpwr_tab(TXID, pt->partition_start_addr);//TXPWR_TAB_FLASH_ADDR); + if(!addr_start) { + MCAL_WARN("NO TXID found in flash, use def xtal:%d\r\n", DEFAULT_TXID_XTAL); + goto init_xtal; + } + + addr = manual_cal_search_txpwr_tab(TXID_XTAL, addr_start); + if(!addr) + { + MCAL_WARN("NO TXID_THERMAL found in flash, use def xtal:%d\r\n", DEFAULT_TXID_XTAL); + goto init_xtal; + } + + flash_handle = ddev_open(FLASH_DEV_NAME, &status, 0); + ddev_read(flash_handle, (char *)&head, sizeof(TXPWR_ELEM_ST), addr); + ddev_read(flash_handle, (char *)&status, head.len, addr + sizeof(TXPWR_ELEM_ST)); + xtal = status; + +init_xtal: + MCAL_FATAL("xtal in flash is:%d\r\n", xtal); + return xtal; +} + +void manual_cal_load_xtal_tag_flash(void) +{ + g_xtal = manual_cal_load_xtal_tag_from_flash(); + manual_cal_set_xtal(g_xtal); +#if CFG_USE_TEMPERATURE_DETECT + manual_cal_init_xtal_cali(g_cur_temp, g_xtal); +#endif +} + +#if CFG_TEMP_DETECT_VERSION == CFG_TEMP_DETECT_VERSION1 +void manual_cal_do_xtal_temp_delta_set(INT8 shift) +{ + g_xcali.xtal_c_delta = shift; +} +#endif + +int manual_cal_load_temp_tag_from_flash(void) +{ + UINT32 status, addr, addr_start; + DD_HANDLE flash_handle; + TXPWR_ELEM_ST head; + #if CFG_SUPPORT_ALIOS + hal_logic_partition_t *pt = hal_flash_get_info(HAL_PARTITION_RF_FIRMWARE); + #else + bk_logic_partition_t *pt = bk_flash_get_info(BK_PARTITION_RF_FIRMWARE); + #endif + UINT32 tem_in_flash = DEFAULT_TXID_THERMAL; + + addr_start = manual_cal_search_txpwr_tab(TXID, pt->partition_start_addr);//TXPWR_TAB_FLASH_ADDR); + if(!addr_start) { + MCAL_WARN("NO TXID found in flash, use def temp:%d\r\n", DEFAULT_TXID_THERMAL); + goto init_temp; + } + + addr = manual_cal_search_txpwr_tab(TXID_THERMAL, addr_start); + if(!addr) + { + MCAL_WARN("NO TXID_THERMAL found in flash, use def temp:%d\r\n", DEFAULT_TXID_THERMAL); + goto init_temp; + } + + flash_handle = ddev_open(FLASH_DEV_NAME, &status, 0); + ddev_read(flash_handle, (char *)&head, sizeof(TXPWR_ELEM_ST), addr); + ddev_read(flash_handle, (char *)&status, head.len, addr + sizeof(TXPWR_ELEM_ST)); + tem_in_flash = status; + +init_temp: + MCAL_FATAL("temp in flash is:%d\r\n", tem_in_flash); + return tem_in_flash; +} + +int manual_cal_save_cailmain_tx_tab_to_flash(void) +{ + extern INT32 gtx_dcorMod; + extern INT32 gtx_dcorPA; + extern INT32 gtx_pre_gain; + INT32 gtx_i_dc_comp; + INT32 gtx_q_dc_comp; + INT32 gtx_i_gain_comp; + INT32 gtx_q_gain_comp; + INT32 gtx_ifilter_corner; + INT32 gtx_qfilter_corner; + INT32 gtx_phase_comp; + INT32 gtx_phase_ty2; + + UINT32 len = 0, txpwr_len = 0, flash_len = 0; + UINT8 *buf = NULL, *txpwr_buf = NULL;; + TAG_TXPWR_ST tag_txpwr; + TAG_TXPWR_PTR tag_txpwr_ptr = NULL; + TAG_COMM_ST tag_comm; + TAG_COMM_PTR tag_comm_ptr = NULL; + + UINT32 status, addr_start; + DD_HANDLE flash_handle; + /// TXPWR_ELEM_ST head; + #if CFG_SUPPORT_ALIOS + hal_logic_partition_t *pt = hal_flash_get_info(HAL_PARTITION_RF_FIRMWARE); + #else + bk_logic_partition_t *pt = bk_flash_get_info(BK_PARTITION_RF_FIRMWARE); + #endif + + // alloc all memery at onece, so we no need to change the size of buf in combin function + txpwr_len = sizeof(TAG_TXPWR_ST) // head + + sizeof(TAG_COMM_ST) // gtx_dcorMod + + sizeof(TAG_COMM_ST) // gtx_dcorPA + + sizeof(TAG_COMM_ST) // gtx_pre_gain + + sizeof(TAG_COMM_ST) // gtx_i_dc_comp + + sizeof(TAG_COMM_ST) // gtx_q_dc_comp + + sizeof(TAG_COMM_ST) // gtx_i_gain_comp + + sizeof(TAG_COMM_ST) // gtx_q_gain_comp + + sizeof(TAG_COMM_ST) // gtx_ifilter_corner + + sizeof(TAG_COMM_ST) // gtx_qfilter_corner + + sizeof(TAG_COMM_ST) // gtx_phase_comp + + sizeof(TAG_COMM_ST); // gtx_phase_ty2 + + // read flash, then combin the table in flash + flash_handle = ddev_open(FLASH_DEV_NAME, &status, 0); + status = manual_cal_search_opt_tab(&flash_len); + // Has TLV Header? + if(status) { + addr_start = manual_cal_search_txpwr_tab(CALI_MAIN_TX, pt->partition_start_addr);//TXPWR_TAB_FLASH_ADDR); + if(!addr_start) { + // no CALI_MAIN_TX, but has any other id, so attch CALI_MAIN_TX after the table + len = flash_len + txpwr_len; + buf = (UINT8*)os_malloc(len); + if(!buf) { + MCAL_WARN("no memory for save_cailmain_tx_tab\r\n"); + ddev_close(flash_handle); + return 0; + } + // copy flash + ddev_read(flash_handle, (char *)buf, flash_len, pt->partition_start_addr);//TXPWR_TAB_FLASH_ADDR); + ddev_close(flash_handle); + + // updata new TLV header + tag_txpwr_ptr = (TAG_TXPWR_PTR)buf; + tag_txpwr.head.type= BK_FLASH_OPT_TLV_HEADER; + tag_txpwr.head.len = len - sizeof(TAG_TXPWR_ST);; + os_memcpy(tag_txpwr_ptr, &tag_txpwr, sizeof(TAG_TXPWR_ST)); + + txpwr_buf = (UINT8 *)(buf + flash_len); + addr_start = pt->partition_start_addr;//TXPWR_TAB_FLASH_ADDR; + }else { + // CALI_MAIN_TX is exist, and found start addr. + len = txpwr_len; + txpwr_buf = buf = (UINT8*)os_malloc(txpwr_len); + if(!buf) { + MCAL_WARN("no memory for txpwr tab save to flash\r\n"); + ddev_close(flash_handle); + return 0; + } + } + } else { + // nothing in flash, write TLV with chipid + MCAL_WARN("NO BK_FLASH_OPT_TLV_HEADER found, save_cailmain_tx_tab failed\r\n"); + ddev_close(flash_handle); + return 0; + } + + ddev_close(flash_handle); + + bk7011_get_tx_filter_corner(>x_ifilter_corner, >x_qfilter_corner); + bk7011_get_tx_dc_comp(>x_i_dc_comp, >x_q_dc_comp); + bk7011_get_tx_gain_comp(>x_i_gain_comp, >x_q_gain_comp); + bk7011_get_tx_phase(>x_phase_comp, >x_phase_ty2); + //bk7011_get_tx_tssi_thred(>x_tssi_thred_b, >x_tssi_thred_g); + + // for tag CALI_MAIN_TX + tag_txpwr_ptr = (TAG_TXPWR_PTR)txpwr_buf; + tag_txpwr.head.type = CALI_MAIN_TX; + tag_txpwr.head.len = txpwr_len - sizeof(TAG_TXPWR_ST); + os_memcpy(tag_txpwr_ptr, &tag_txpwr, sizeof(TAG_TXPWR_ST)); + txpwr_buf = (UINT8*)(txpwr_buf + sizeof(TAG_TXPWR_ST)); + + // for tag gtx_dcorMod + tag_comm_ptr = (TAG_COMM_PTR)(txpwr_buf); + tag_comm.head.type = CM_TX_DCOR_MOD; + tag_comm.head.len = sizeof(tag_comm.value); + tag_comm.value = (UINT32)gtx_dcorMod; + os_memcpy(tag_comm_ptr, &tag_comm, sizeof(TAG_COMM_ST)); + txpwr_buf = (UINT8*)(txpwr_buf + sizeof(TAG_COMM_ST)); + + // for tag gtx_dcorPA + tag_comm_ptr = (TAG_COMM_PTR)(txpwr_buf); + tag_comm.head.type = CM_TX_DCOR_PA; + tag_comm.head.len = sizeof(tag_comm.value); + tag_comm.value = (UINT32)gtx_dcorPA; + os_memcpy(tag_comm_ptr, &tag_comm, sizeof(TAG_COMM_ST)); + txpwr_buf = (UINT8*)(txpwr_buf + sizeof(TAG_COMM_ST)); + + // for tag gtx_pre_gain + tag_comm_ptr = (TAG_COMM_PTR)(txpwr_buf); + tag_comm.head.type = CM_TX_PREGAIN; + tag_comm.head.len = sizeof(tag_comm.value); + tag_comm.value = (UINT32)gtx_pre_gain; + os_memcpy(tag_comm_ptr, &tag_comm, sizeof(TAG_COMM_ST)); + txpwr_buf = (UINT8*)(txpwr_buf + sizeof(TAG_COMM_ST)); + + // for tag gtx_i_dc_comp + tag_comm_ptr = (TAG_COMM_PTR)(txpwr_buf); + tag_comm.head.type = CM_TX_I_DC_COMP; + tag_comm.head.len = sizeof(tag_comm.value); + tag_comm.value = (UINT32)gtx_i_dc_comp; + os_memcpy(tag_comm_ptr, &tag_comm, sizeof(TAG_COMM_ST)); + txpwr_buf = (UINT8*)(txpwr_buf + sizeof(TAG_COMM_ST)); + + // for tag gtx_q_dc_comp + tag_comm_ptr = (TAG_COMM_PTR)(txpwr_buf); + tag_comm.head.type = CM_TX_Q_DC_COMP; + tag_comm.head.len = sizeof(tag_comm.value); + tag_comm.value = (UINT32)gtx_q_dc_comp; + os_memcpy(tag_comm_ptr, &tag_comm, sizeof(TAG_COMM_ST)); + txpwr_buf = (UINT8*)(txpwr_buf + sizeof(TAG_COMM_ST)); + + // for tag gtx_i_gain_comp + tag_comm_ptr = (TAG_COMM_PTR)(txpwr_buf); + tag_comm.head.type = CM_TX_I_GAIN_COMP; + tag_comm.head.len = sizeof(tag_comm.value); + tag_comm.value = (UINT32)gtx_i_gain_comp; + os_memcpy(tag_comm_ptr, &tag_comm, sizeof(TAG_COMM_ST)); + txpwr_buf = (UINT8*)(txpwr_buf + sizeof(TAG_COMM_ST)); + + // for tag gtx_q_gain_comp + tag_comm_ptr = (TAG_COMM_PTR)(txpwr_buf); + tag_comm.head.type = CM_TX_Q_GAIN_COMP; + tag_comm.head.len = sizeof(tag_comm.value); + tag_comm.value = (UINT32)gtx_q_gain_comp; + os_memcpy(tag_comm_ptr, &tag_comm, sizeof(TAG_COMM_ST)); + txpwr_buf = (UINT8*)(txpwr_buf + sizeof(TAG_COMM_ST)); + + // for tag gtx_ifilter_corner + tag_comm_ptr = (TAG_COMM_PTR)(txpwr_buf); + tag_comm.head.type = CM_TX_I_FILTER_CORNER; + tag_comm.head.len = sizeof(tag_comm.value); + tag_comm.value = (UINT32)gtx_ifilter_corner; + os_memcpy(tag_comm_ptr, &tag_comm, sizeof(TAG_COMM_ST)); + txpwr_buf = (UINT8*)(txpwr_buf + sizeof(TAG_COMM_ST)); + + // for tag gtx_qfilter_corner + tag_comm_ptr = (TAG_COMM_PTR)(txpwr_buf); + tag_comm.head.type = CM_TX_Q_FILTER_CORNER; + tag_comm.head.len = sizeof(tag_comm.value); + tag_comm.value = (UINT32)gtx_qfilter_corner; + os_memcpy(tag_comm_ptr, &tag_comm, sizeof(TAG_COMM_ST)); + txpwr_buf = (UINT8*)(txpwr_buf + sizeof(TAG_COMM_ST)); + + // for tag gtx_phase_comp + tag_comm_ptr = (TAG_COMM_PTR)(txpwr_buf); + tag_comm.head.type = CM_TX_PHASE_COMP; + tag_comm.head.len = sizeof(tag_comm.value); + tag_comm.value = (UINT32)gtx_phase_comp; + os_memcpy(tag_comm_ptr, &tag_comm, sizeof(TAG_COMM_ST)); + txpwr_buf = (UINT8*)(txpwr_buf + sizeof(TAG_COMM_ST)); + + // for tag gtx_phase_ty2 + tag_comm_ptr = (TAG_COMM_PTR)(txpwr_buf); + tag_comm.head.type = CM_TX_PHASE_TY2; + tag_comm.head.len = sizeof(tag_comm.value); + tag_comm.value = (UINT32)gtx_phase_ty2; + os_memcpy(tag_comm_ptr, &tag_comm, sizeof(TAG_COMM_ST)); + txpwr_buf = (UINT8*)(txpwr_buf + sizeof(TAG_COMM_ST)); + + addr_start -= pt->partition_start_addr;//TXPWR_TAB_FLASH_ADDR; + manual_cal_update_flash_area(addr_start, (char *)buf, len); + os_free(buf); + + return 1; +} + +int manual_cal_save_cailmain_rx_tab_to_flash(void) +{ + INT32 rx_dc_gain_tab[8]; + INT32 rx_amp_err_wr; + INT32 rx_phase_err_wr; + + UINT32 len = 0, txpwr_len = 0, flash_len = 0; + UINT8 *buf = NULL, *txpwr_buf = NULL;; + TAG_TXPWR_ST tag_txpwr; + TAG_TXPWR_PTR tag_txpwr_ptr = NULL; + TAG_COMM_ST tag_comm; + TAG_COMM_PTR tag_comm_ptr = NULL; + TAG_RX_DC_ST tag_rx_dc; + TAG_RX_DC_PTR tag_rx_dc_ptr = NULL; + + UINT32 status, addr_start; + DD_HANDLE flash_handle; + /// TXPWR_ELEM_ST head; + #if CFG_SUPPORT_ALIOS + hal_logic_partition_t *pt = hal_flash_get_info(HAL_PARTITION_RF_FIRMWARE); + #else + bk_logic_partition_t *pt = bk_flash_get_info(BK_PARTITION_RF_FIRMWARE); + #endif + + // alloc all memery at onece, so we no need to change the size of buf in combin function + txpwr_len = sizeof(TAG_TXPWR_ST) // head + + sizeof(TAG_RX_DC_ST) // rx_dc_gain_tab 0 -7 + + sizeof(TAG_COMM_ST) // rx_amp_err_wr + + sizeof(TAG_COMM_ST); // rx_phase_err_wr + + // read flash, then combin the table in flash + flash_handle = ddev_open(FLASH_DEV_NAME, &status, 0); + status = manual_cal_search_opt_tab(&flash_len); + // Has TLV Header? + if(status) { + addr_start = manual_cal_search_txpwr_tab(CALI_MAIN_RX, pt->partition_start_addr);//TXPWR_TAB_FLASH_ADDR); + if(!addr_start) { + // no CALI_MAIN_RX, but has any other id, so attch CALI_MAIN_TX after the table + len = flash_len + txpwr_len; + buf = (UINT8*)os_malloc(len); + if(!buf) { + MCAL_WARN("no memory for save_cailmain_rx_tab\r\n"); + ddev_close(flash_handle); + return 0; + } + // copy flash + ddev_read(flash_handle, (char *)buf, flash_len, pt->partition_start_addr);//TXPWR_TAB_FLASH_ADDR); + ddev_close(flash_handle); + + // updata new TLV header + tag_txpwr_ptr = (TAG_TXPWR_PTR)buf; + tag_txpwr.head.type= BK_FLASH_OPT_TLV_HEADER; + tag_txpwr.head.len = len - sizeof(TAG_TXPWR_ST);; + os_memcpy(tag_txpwr_ptr, &tag_txpwr, sizeof(TAG_TXPWR_ST)); + + txpwr_buf = (UINT8 *)(buf + flash_len); + addr_start = pt->partition_start_addr;//TXPWR_TAB_FLASH_ADDR; + }else { + // CALI_MAIN_RX is exist, and found start addr. + len = txpwr_len; + txpwr_buf = buf = (UINT8*)os_malloc(txpwr_len); + if(!buf) { + MCAL_WARN("no memory for txpwr tab save to flash\r\n"); + ddev_close(flash_handle); + return 0; + } + } + } else { + // nothing in flash, write TLV with chipid + MCAL_WARN("NO BK_FLASH_OPT_TLV_HEADER found, save_cailmain_rx_tab failed\r\n"); + ddev_close(flash_handle); + return 0; + } + + ddev_close(flash_handle); + + // for tag CALI_MAIN_TX + tag_txpwr_ptr = (TAG_TXPWR_PTR)txpwr_buf; + tag_txpwr.head.type = CALI_MAIN_RX; + tag_txpwr.head.len = txpwr_len - sizeof(TAG_TXPWR_ST); + os_memcpy(tag_txpwr_ptr, &tag_txpwr, sizeof(TAG_TXPWR_ST)); + txpwr_buf = (UINT8*)(txpwr_buf + sizeof(TAG_TXPWR_ST)); + + bk7011_get_rx_err_wr(&rx_amp_err_wr, &rx_phase_err_wr, rx_dc_gain_tab); + // for tag rx_dc_gain_tab + tag_rx_dc_ptr = (TAG_RX_DC_PTR)(txpwr_buf); + tag_rx_dc.head.type = CM_RX_DC_GAIN_TAB; + tag_rx_dc.head.len = sizeof(tag_rx_dc.value); + tag_rx_dc.value[0] = rx_dc_gain_tab[0]; + tag_rx_dc.value[1] = rx_dc_gain_tab[1]; + tag_rx_dc.value[2] = rx_dc_gain_tab[2]; + tag_rx_dc.value[3] = rx_dc_gain_tab[3]; + tag_rx_dc.value[4] = rx_dc_gain_tab[4]; + tag_rx_dc.value[5] = rx_dc_gain_tab[5]; + tag_rx_dc.value[6] = rx_dc_gain_tab[6]; + tag_rx_dc.value[7] = rx_dc_gain_tab[7]; + os_memcpy(tag_rx_dc_ptr, &tag_rx_dc, sizeof(TAG_RX_DC_ST)); + txpwr_buf = (UINT8*)(txpwr_buf + sizeof(TAG_RX_DC_ST)); + + // for tag rx_amp_err_wr + tag_comm_ptr = (TAG_COMM_PTR)(txpwr_buf); + tag_comm.head.type = CM_RX_AMP_ERR_WR; + tag_comm.head.len = sizeof(tag_comm.value); + tag_comm.value = (UINT32)rx_amp_err_wr; + os_memcpy(tag_comm_ptr, &tag_comm, sizeof(TAG_COMM_ST)); + txpwr_buf = (UINT8*)(txpwr_buf + sizeof(TAG_COMM_ST)); + + // for tag rx_phase_err_wr + tag_comm_ptr = (TAG_COMM_PTR)(txpwr_buf); + tag_comm.head.type = CM_RX_PHASE_ERR_WR; + tag_comm.head.len = sizeof(tag_comm.value); + tag_comm.value = (UINT32)rx_phase_err_wr; + os_memcpy(tag_comm_ptr, &tag_comm, sizeof(TAG_COMM_ST)); + txpwr_buf = (UINT8*)(txpwr_buf + sizeof(TAG_COMM_ST)); + + addr_start -= pt->partition_start_addr;//TXPWR_TAB_FLASH_ADDR; + manual_cal_update_flash_area(addr_start, (char *)buf, len); + os_free(buf); + + return 1; +} + +int manual_cal_load_calimain_tag_from_flash(UINT32 tag, int *tag_addr, int tag_size) +{ + UINT32 status, addr, addr_start; + DD_HANDLE flash_handle; + TXPWR_ELEM_ST head; + #if CFG_SUPPORT_ALIOS + hal_logic_partition_t *pt = hal_flash_get_info(HAL_PARTITION_RF_FIRMWARE); + #else + bk_logic_partition_t *pt = bk_flash_get_info(BK_PARTITION_RF_FIRMWARE); + #endif + + status = manual_cal_search_opt_tab(&addr); + if(!status) { + // no tlv in flash + MCAL_FATAL("NO TLV tag in flash \r\n"); + return -1; + } + + if((tag >= CM_TX_DCOR_MOD) && (tag < CM_TX_END)) + { + addr_start = manual_cal_search_txpwr_tab(CALI_MAIN_TX, pt->partition_start_addr); + } + else if((tag >= CM_RX_DC_GAIN_TAB) && (tag < CM_RX_END)) + { + addr_start = manual_cal_search_txpwr_tab(CALI_MAIN_RX, pt->partition_start_addr); + } + else + { + MCAL_FATAL("not a CALI_MAIN_tag \r\n"); + return 0; + } + + if(!addr_start) { + MCAL_FATAL("NO CALI_MAIN_tag in flash \r\n"); + return -2; + } + + addr = manual_cal_search_txpwr_tab(tag, addr_start); + if(!addr) { + MCAL_FATAL("NO %x tag in flash\r\n", tag); + return -3; + } else { + flash_handle = ddev_open(FLASH_DEV_NAME, &status, 0); + ddev_read(flash_handle, (char *)&head, sizeof(TXPWR_ELEM_ST), addr); + if((tag_addr) && (tag_size >= head.len)) + { + ddev_read(flash_handle, (char *)tag_addr, head.len, addr + sizeof(TXPWR_ELEM_ST)); + } + return 1; + } +} + +UINT32 manual_cal_txpwr_tab_ready_in_flash(void) +{ + UINT32 status, addr, addr_start; + DD_HANDLE flash_handle; + TXPWR_ELEM_ST head; + TXPWR_IS_RD is_ready_flash = 0; + #if CFG_SUPPORT_ALIOS + hal_logic_partition_t *pt = hal_flash_get_info(HAL_PARTITION_RF_FIRMWARE); + #else + bk_logic_partition_t *pt = bk_flash_get_info(BK_PARTITION_RF_FIRMWARE); + #endif + + addr_start = manual_cal_search_txpwr_tab(TXPWR_TAB_TAB, pt->partition_start_addr);//TXPWR_TAB_FLASH_ADDR); + if(!addr_start) { + //MCAL_WARN("NO TXPWR_TAB_TAB found in flash\r\n"); + return TXPWR_NONE_RD; + } + + addr = manual_cal_search_txpwr_tab(TXPWR_ENABLE_ID, addr_start); + if(!addr) + { + //MCAL_WARN("NO TXPWR_ENABLE_ID found in flash\r\n"); + return TXPWR_NONE_RD; + } + + flash_handle = ddev_open(FLASH_DEV_NAME, &status, 0); + ddev_read(flash_handle, (char *)&head, sizeof(TXPWR_ELEM_ST), addr); + ddev_read(flash_handle, (char *)&status, head.len, addr + sizeof(TXPWR_ELEM_ST)); + is_ready_flash = status; + //MCAL_PRT("flash txpwr table:0x%x\r\n", is_ready_flash); + + return is_ready_flash; +} + +#endif // CFG_SUPPORT_MANUAL_CALI + + +#if CFG_USE_TEMPERATURE_DETECT + +#if CFG_TEMP_DETECT_VERSION == CFG_TEMP_DETECT_VERSION1 +#define TMP_PWR_TAB_LEN 39 + +typedef struct tmp_set_pwr_st { + UINT8 indx; + UINT8 indx_cali_bias; + UINT8 indx_cali_dpll; + UINT8 flag; + UINT16 temp_tab[TMP_PWR_TAB_LEN]; + TMP_PWR_PTR pwr_ptr; +} TMP_SET_PWR_ST, *TMP_SET_PWR_PTR; + +const TMP_PWR_ST tmp_pwr_tab[TMP_PWR_TAB_LEN] = { +//trx0x0c[12:15], shift_b, shift_g, shift_ble, xtal_c_delta +#if (CFG_SOC_NAME == SOC_BK7231N) + { 0x00, -2, -4, 0, 0}, // 0 ,-40 -35 + { 0x00, -2, -4, 0, 2}, // 1 ,-35 -30 + { 0x00, -2, -4, 0, 4}, // 2 ,-30 -25 + { 0x00, -1, -3, 0, 7}, // 3 ,-25 -20 + { 0x00, -1, -3, 0, 7}, // 4 ,-20 -15 + { 0x00, -1, -2, 0, 8}, // 5 ,-15 -10 + { 0x00, 0, -1, 0, 8}, // 6 ,-10 -5 + { 0x00, 0, -1, 0, 8}, // 7 ,-5 0 + { 0x00, 0, -1, 0, 7}, // 8 ,0 5 + { 0x00, 0, -1, 0, 7}, // 9 ,5 10 + { 0x00, 0, -1, 0, 6}, // 10 ,10 15 + { 0x00, 0, -1, 0, 6}, // 11 ,15 20 + { 0x00, 0, 0, 0, 1}, // 12 ,20 25 + { 0x00, 0, 0, 0, 0}, // 13 ,25 30 + { 0x00, 0, 0, 0, -1}, // 14 ,30 35 + { 0x00, 0, 0, 0, -4}, // 15 ,35 40 + { 0x00, 0, 0, 0, -4}, // 16 ,40 45 + { 0x00, 0, 0, 0, -4}, // 17 ,45 50 + { 0x00, 0, 1, 0, -6}, // 18 ,50 55 + { 0x00, 0, 1, 0, -8}, // 19 ,55 60 + { 0x00, 1, 2, 0, -8}, // 20 ,60 65 + { 0x00, 1, 2, 0, -8}, // 21 ,65 70 + { 0x00, 1, 3, 0, -7}, // 22 ,70 75 + { 0x00, 2, 4, 0, -6}, // 23 ,75 80 + { 0x00, 2, 4, 0, -3}, // 24 ,80 85 + { 0x00, 2, 4, 0, -1}, // 25 ,85 90 + { 0x00, 2, 4, 0, 0}, // 26 ,90 95 + { 0x00, 2, 4, 1, 5}, // 27 ,95 100 + { 0x00, 2, 4, 1, 10}, // 28 ,100 105 + { 0x00, 2, 4, 2, 20}, // 29 ,105 110 + { 0x00, 2, 4, 2, 30}, // 30 ,110 115 + { 0x00, 2, 4, 3, 40}, // 31 ,115 + { 0x00, 2, 4, 3, 60}, // 32 ,120 + { 0x00, 2, 4, 3, 80}, // 33 ,125 + { 0x00, 2, 4, 3, 100}, // 34 ,130 + { 0x00, 2, 4, 3, 127}, // 35 ,135 + { 0x00, 2, 4, 3, 127}, // 36 ,140 + { 0x00, 2, 4, 3, 127}, // 37 ,145 + { 0x00, 2, 4, 3, 127}, // 38 ,150 +#else + { 0x08, -4, -4, 0, 0}, // 0 ,-40 + { 0x08, -4, -4, 0, 0}, // 1 ,-35 + { 0x08, -4, -4, 0, 0}, // 2 ,-30 + { 0x08, -4, -4, 0, 0}, // 3 ,-25 + { 0x08, -4, -4, 0, 0}, // 4 ,-20 + { 0x08, -3, -3, 0, 0}, // 5 ,-15 + { 0x08, -3, -3, 0, 0}, // 6 ,-10 + { 0x08, -3, -3, 0, 0}, // 7 ,-5 + { 0x08, -2, -2, 0, 0}, // 8 ,0 + { 0x08, -2, -2, 0, 0}, // 9 ,5 + { 0x08, -2, -2, 0, 0}, // 10 ,10 + { 0x08, -1, -1, 0, 0}, // 11 ,15 + { 0x08, -1, -1, 0, 0}, // 12 ,20 + { 0x08, -1, -1, 0, 0}, // 13 ,25 + { 0x08, 0, 0, 0, 2}, // 14 ,30 + { 0x08, 0, 0, 0, 1}, // 15 ,35 + { 0x08, 0, 0, 0, 0}, // 16 ,40 + { 0x08, 0, 0, 0, 0}, // 17 ,45 + { 0x08, 0, 0, 0, 0}, // 18 ,50 + { 0x08, 0, 0, 0, 0}, // 19 ,55 + { 0x08, 0, 0, 0, 0}, // 20 ,60 + { 0x08, 0, 0, 0, 0}, // 21 ,65 + { 0x08, 0, 0, 0, 0}, // 22 ,70 + { 0x08, 0, 0, 0, 0}, // 23 ,75 + { 0x08, 0, 0, 0, 0}, // 24 ,80 + { 0x08, 0, 0, 0, 5}, // 25 ,85 + { 0x08, 0, 0, 0, 8}, // 26 ,90 + { 0x08, 1, 1, 1, 11}, // 27 ,95 + { 0x08, 1, 1, 1, 16}, // 28 ,100 + { 0x08, 2, 2, 2, 22}, // 29 ,105 + { 0x08, 2, 2, 2, 30}, // 30 ,110 + { 0x08, 3, 3, 3, 40}, // 31 ,115 + { 0x08, 3, 3, 3, 52}, // 32 ,120 + { 0x08, 3, 3, 3, 63}, // 33 ,125 + { 0x08, 3, 3, 3, 63}, // 34 ,130 + { 0x08, 3, 3, 3, 63}, // 35 ,135 + { 0x08, 3, 3, 3, 63}, // 36 ,140 + { 0x08, 3, 3, 3, 63}, // 37 ,145 + { 0x08, 3, 3, 3, 63}, // 38 ,150 +#endif +}; +#else + +#define TMP_PWR_TAB_LEN 13 + +typedef struct tmp_set_pwr_st { + UINT8 indx; + UINT8 flag; + UINT16 temp_tab[TMP_PWR_TAB_LEN]; + TMP_PWR_PTR pwr_ptr; + UINT16 init_mod; + UINT16 init_pa; +} TMP_SET_PWR_ST, *TMP_SET_PWR_PTR; +/* +const TMP_PWR_ST tmp_pwr_tab[TMP_PWR_TAB_LEN] = { + { 0, 6}, // pwr index 0 5dbm + { 0, 8}, // pwr index 1 6dbm + { 1, 8}, // pwr index 2 7dbm + { 2, 8}, // pwr index 3 8dbm + { 3, 8}, // pwr index 4 9dbm + { 4, 8}, // pwr index 5 10dbm + { 6, 8}, // pwr index 6 11bm + { 8, 8}, // pwr index 7 12dbm + {11, 8}, // pwr index 8 13dbm + {15, 8}, // pwr index 9 14dbm + {15, 10}, // pwr index 10 15dbm + {15, 12}, // pwr index 11 16dbm + {15, 15}, // pwr index 12 17dbm +}; +*/ + +const TMP_PWR_ST tmp_pwr_tab[TMP_PWR_TAB_LEN] = { + { 4, 8}, // pwr index 0 5dbm + { 4, 8}, // pwr index 1 6dbm + { 6, 8}, // pwr index 2 7dbm + { 6, 8}, // pwr index 3 8dbm + { 6, 8}, // pwr index 4 9dbm + { 8, 8}, // pwr index 5 10dbm + { 8, 8}, // pwr index 6 11bm + { 8, 8}, // pwr index 7 12dbm + { 8, 8}, // pwr index 8 13dbm + { 11, 8}, // pwr index 9 14dbm + { 11, 8}, // pwr index 10 15dbm + { 11, 8}, // pwr index 11 16dbm + { 11, 8}, // pwr index 12 17dbm +}; +#endif + +typedef struct xtal_st { + UINT8 low; + UINT8 high; + UINT16 value; +} XTAL_ST, *XTAL_PTR; + +const XTAL_ST xtal_tab[] = { + { 0, 20, 3}, + { 20, 30, 5}, + { 30, 40, 8}, + { 40, 50, 12}, + { 50, 60, 17}, + { 60, 70, 23}, + { 70, 80, 30}, + { 80, 90, 38}, + { 90, 100, 47}, + { 100, 110, 57}, + { 110, 0, 68}, +}; + +TMP_SET_PWR_ST g_tmp_pwr; + +extern void sctrl_cali_dpll(UINT8 flag); +extern void sctrl_dpll_int_open(void); + +void manual_cal_init_xtal_cali(UINT16 init_temp, UINT16 init_xtal) +{ +#if (CFG_TEMP_DETECT_VERSION == CFG_TEMP_DETECT_VERSION1) + g_xcali.init_xtal = init_xtal; + g_xcali.last_xtal = init_xtal; + os_null_printf("--init_xtal = %d\n",init_xtal); +#endif +} + + +void manual_cal_set_tmp_pwr_flag(UINT8 flag) +{ + os_null_printf("set flag to %d\r\n", flag); + g_tmp_pwr.flag = flag; +} + +void manual_cal_tmp_pwr_init_reg(UINT16 reg_mod, UINT16 reg_pa) +{ +#if CFG_TEMP_DETECT_VERSION == CFG_TEMP_DETECT_VERSION1 + +#else + TMP_DETECT_WARN("manual_cal_tmp_pwr_init_reg: mod:%d, pa:%d\r\n", reg_mod, reg_pa); + g_tmp_pwr.init_mod = reg_mod; + g_tmp_pwr.init_pa = reg_pa; +#endif +} + +extern struct temp_cal_pwr_st g_temp_pwr_current; +extern struct temp_cal_pwr_st g_temp_pwr_current_tpc; +extern INT16 g_ble_pwr_indx, g_ble_pwr_shift; +extern void rwnx_cal_set_txpwr_by_tmpdetect(INT16 shift_b, INT16 shift_g); +UINT16 g_tmp_pwr_indx_bak = 255; +void manual_cal_store_cur_temp(void) +{ + g_tmp_pwr_indx_bak = g_tmp_pwr.indx; + + os_printf("restore g_tmp_pwr.indx:%d\r\n", g_tmp_pwr_indx_bak); +} + +void manual_cal_recover_cur_temp(void) +{ + if(g_tmp_pwr_indx_bak == 255) + g_tmp_pwr.indx = g_tmp_pwr.indx; + else + g_tmp_pwr.indx = g_tmp_pwr_indx_bak; + + os_printf("recover g_tmp_pwr.indx:%d\r\n", g_tmp_pwr.indx); +} + +extern void rwnx_set_tpc_txpwr_by_tmpdetect(INT16 shift_b, INT16 shift_g); +extern void rwnx_cal_set_ble_txpwr_by_tmpdetect(INT16 shift_ble); +void manual_cal_temp_pwr_unint(void) +{ +#if CFG_TEMP_DETECT_VERSION == CFG_TEMP_DETECT_VERSION1 + rwnx_cal_set_txpwr_by_tmpdetect(0, 0); + rwnx_set_tpc_txpwr_by_tmpdetect(0, 0); + +#if (CFG_SOC_NAME != SOC_BK7231N) + rwnx_cal_set_ble_txpwr_by_tmpdetect(0); +#endif + + manual_cal_do_xtal_temp_delta_set(0); + manual_cal_do_xtal_cali(0, 0, 0, 0); + + os_printf("stop pwr info: pwridx:%d, shift_b:%d, shift_g:%d, rate:%d\r\n", + g_temp_pwr_current.idx, + g_temp_pwr_current.shift, + g_temp_pwr_current.shift_g, + g_temp_pwr_current.mode); + + os_printf("stop pwr tpc info: pwridx:%d, shift_b:%d, shift_g:%d, rate:%d\r\n", + g_temp_pwr_current_tpc.idx, + g_temp_pwr_current_tpc.shift, + g_temp_pwr_current_tpc.shift_g, + g_temp_pwr_current_tpc.mode); + +#if (CFG_SOC_NAME != SOC_BK7231N) + os_printf("stop pwr ble info: pwridx:%d, shift:%d\r\n", + g_ble_pwr_indx, g_ble_pwr_shift); +#endif + + bk_printf("stop td-indx:%d, tab:%d,", + g_tmp_pwr.indx, + g_tmp_pwr.temp_tab[g_tmp_pwr.indx]); + + os_printf("stop xtal info: init:%d, c_delta:%d\r\n", + g_xcali.init_xtal, g_xcali.xtal_c_delta); + + bk_printf("--0xc:%02x, pidx_b:%d, pidx_g:%d, X:%d\n", + g_tmp_pwr.pwr_ptr->trx0x0c_12_15, + g_tmp_pwr.pwr_ptr->p_index_delta, + g_tmp_pwr.pwr_ptr->p_index_delta_g, + g_tmp_pwr.pwr_ptr->xtal_c_dlta); + manual_cal_store_cur_temp(); +#else + os_printf("manual_cal_temp_pwr_unint: mod:%d, pa:%d\r\n", g_tmp_pwr.init_mod, + g_tmp_pwr.init_pa); + rwnx_cal_set_reg_mod_pa(g_tmp_pwr.init_mod, g_tmp_pwr.init_pa); +#endif + + manual_cal_set_tmp_pwr_flag(0); + os_printf("set flag to disable, don't do pwr any more:%d\r\n", g_tmp_pwr.flag); + +} + +#if CFG_TEMP_DETECT_VERSION == CFG_TEMP_DETECT_VERSION1 +void manual_cal_tmp_pwr_init(UINT16 init_temp, UINT16 init_thre, UINT16 init_dist) +{ + INT32 idx = 13, i; + INT16 temp = 0; + + os_null_printf("init temp pwr table:tmp:%d, idx:%d, dist:%d, init_thre:%d\r\n", + init_temp, idx, init_dist,init_thre); + + if(init_temp >= ADC_TEMP_VAL_MAX) + { + os_printf("init temp too large %d, failed\r\n"); + return; + } + + init_temp += init_dist; + if(init_temp > ADC_TEMP_VAL_MAX) + init_temp = ADC_TEMP_VAL_MAX; + + os_memset(&g_tmp_pwr.temp_tab[0], 0, sizeof(UINT16)*TMP_PWR_TAB_LEN); + g_tmp_pwr.indx = idx; + g_tmp_pwr.indx_cali_bias = idx; + g_tmp_pwr.indx_cali_dpll = idx; + g_tmp_pwr.pwr_ptr = (TMP_PWR_PTR)&tmp_pwr_tab[idx]; + g_tmp_pwr.temp_tab[idx] = init_temp; + + for(i=idx+1; i> 1); + temp = (temp < ADC_TEMP_VAL_MIN)? ADC_TEMP_VAL_MIN : temp; +#else + temp = g_tmp_pwr.temp_tab[i-1] + init_thre; + temp = (temp > ADC_TEMP_VAL_MAX)? ADC_TEMP_VAL_MAX : temp; +#endif + g_tmp_pwr.temp_tab[i] = temp; + } + + for(i=idx-1; i>=0; i--) { + //temp = g_tmp_pwr.temp_tab[i+1] - ADC_TMEP_LSB_PER_10DEGREE; +#if (CFG_SOC_NAME == SOC_BK7231N) + temp = g_tmp_pwr.temp_tab[i+1] + (init_thre >> 1); + temp = (temp > ADC_TEMP_VAL_MAX)? ADC_TEMP_VAL_MAX : temp; +#else + temp = g_tmp_pwr.temp_tab[i+1] - init_thre; + temp = (temp < ADC_TEMP_VAL_MIN)? ADC_TEMP_VAL_MIN : temp; +#endif + g_tmp_pwr.temp_tab[i] = temp; + } + + os_null_printf("Temp tab\r\n"); + for(i=0; imod <= reg_mod) && (pwr_ptr_1->mod >= reg_mod)) + && ((pwr_ptr_0->pa <= reg_pa) && (pwr_ptr_1->pa >= reg_pa))) + { + if((pwr_ptr_1->pa == reg_pa) && (pwr_ptr_1->mod >= reg_mod)) + idx = i+1; + else + idx = i; + + break; + } + } + + os_printf("init temp pwr table: mod:%d, pa:%d, tmp:%d, idx:%d, dist:%d\r\n", + reg_mod, reg_pa, init_temp, idx, init_dist); + + if(init_temp < init_dist) { + init_temp = ADC_TEMP_VAL_MIN; + } else { + init_temp -= init_dist; + } + + os_memset(&g_tmp_pwr.temp_tab[0], 0, sizeof(UINT16)*TMP_PWR_TAB_LEN); + g_tmp_pwr.indx = idx; + g_tmp_pwr.pwr_ptr = (TMP_PWR_PTR)&tmp_pwr_tab[idx]; + g_tmp_pwr.temp_tab[idx] = init_temp; + + for(i=idx+1; i ADC_TEMP_VAL_MAX)? ADC_TEMP_VAL_MAX : temp; + g_tmp_pwr.temp_tab[i] = temp; + } + + for(i=idx-1; i>=0; i--) { + //temp = g_tmp_pwr.temp_tab[i+1] - ADC_TMEP_LSB_PER_10DEGREE; + temp = g_tmp_pwr.temp_tab[i+1] - init_thre; + temp = (temp < ADC_TEMP_VAL_MIN)? ADC_TEMP_VAL_MIN : temp; + g_tmp_pwr.temp_tab[i] = temp; + } + + TMP_DETECT_WARN("\r\n"); + for(i=0; i> 2) + 2; /* -2.5 ~ +2.5 ===> 5, for tmp_pwr_tab */ + UINT32 thre_5_degree = (thre >> 1); + UINT32 thre_50_degree = DO_SETP * thre_5_degree; + UINT8 dist_cal_dpll = 0, dist_cal_bias = 0; + UINT16 last_val = g_tmp_pwr.temp_tab[g_tmp_pwr.indx]; + + UINT8 indx = g_tmp_pwr.indx; + + if(cur_val > last_val) + { + dist = cur_val - last_val; + if(dist >= thre_50_degree) + { + indx = ((indx-DO_SETP) > 0)? (indx - DO_SETP) : 0; + } + else if(dist >= thre_2_5_degree) + { + //round down to find step index + int i = (dist - thre_2_5_degree) / thre_5_degree; + indx = ((indx-(i+1)) > 0)? (indx-(i+1)) : 0; + } + } + else if(cur_val < last_val) + { + dist = last_val - cur_val; + if(dist >= thre_50_degree) + { + indx = (indx+DO_SETP= thre_2_5_degree) + { + //round down to find step index + int i = (dist - thre_2_5_degree) / thre_5_degree; + indx = ((indx +i+1) g_tmp_pwr.indx_cali_dpll) + { + dist_cal_dpll = indx - g_tmp_pwr.indx_cali_dpll; + } + else + { + dist_cal_dpll = g_tmp_pwr.indx_cali_dpll - indx; + } + + if (indx > g_tmp_pwr.indx_cali_bias) + { + dist_cal_bias = indx - g_tmp_pwr.indx_cali_bias; + } + else + { + dist_cal_bias = g_tmp_pwr.indx_cali_bias - indx; + } + + /* cali bias each 4*5degree */ + if (dist_cal_bias >= 4) + { +#ifdef ATE_PRINT_DEBUG + if (!get_ate_mode_state()) + { + os_null_printf("cal_bias!\r\n"); + } +#endif + g_tmp_pwr.indx_cali_bias = indx; + bk7011_cal_bias(); + } + + /* cali dpll each 4*5degree */ + if (dist_cal_dpll >= 4) + { +#ifdef ATE_PRINT_DEBUG + if (!get_ate_mode_state()) + { + os_printf("cal dpll!\r\n"); + } +#endif + + g_tmp_pwr.indx_cali_dpll = indx; + CHECK_OPERATE_RF_REG_IF_IN_SLEEP(); + sctrl_cali_dpll(0); + sctrl_dpll_int_open(); + CHECK_OPERATE_RF_REG_IF_IN_SLEEP_END(); + } + + // bk7231U need dist>60, then do tx pwr. + if(g_tmp_pwr.flag) + { + UINT8 last_idx = g_tmp_pwr.indx; + temperature_type new_temperature_type; + INT16 temp_code; + + if (g_cur_temp_flash >= 7 * thre + cur_val) + { + // normal_temp_25C + 7 * ADC_TMEP_LSB_PER_10DEGREE = normal_temp_25C + 70C = 95C + new_temperature_type = TEMPERATURE_TYPE_HIGH; + } + else if (cur_val >= 5 * thre_5_degree + g_cur_temp_flash) + { + // cur_temp >= normal_temp_25C - 5 * ADC_TMEP_LSB_PER_5DEGREE = normal_temp_25C - 25C = 0C + new_temperature_type = TEMPERATURE_TYPE_LOW; + } + else + { + new_temperature_type = TEMPERATURE_TYPE_NORMAL; + } + bk7011_cal_vdddig_by_temperature(new_temperature_type); + + g_tmp_pwr.indx = indx; + g_tmp_pwr.pwr_ptr = (TMP_PWR_PTR)&tmp_pwr_tab[indx]; + *last = g_tmp_pwr.temp_tab[g_tmp_pwr.indx]; + + ///os_printf("set_tmp_pwr: indx:%d, mod:%d, pa:%d, tmp:%d\r\n", indx, + // g_tmp_pwr.pwr_ptr->mod, g_tmp_pwr.pwr_ptr->pa, *last); +#ifdef ATE_PRINT_DEBUG + if (!get_ate_mode_state()) + { + if (g_cur_temp_flash >= cur_val) + { + temp_code = 25 + (g_cur_temp_flash - cur_val) * 10 / thre; + } + else + { + temp_code = 25 - (cur_val - g_cur_temp_flash) * 10 / thre; + } + MCAL_FATAL("temp_code:%d - adc_code:%d - adc_trend:[%d]:%d->[%d]:%d\r\n", + temp_code, cur_val, + last_idx, g_tmp_pwr.temp_tab[last_idx], + g_tmp_pwr.indx, g_tmp_pwr.temp_tab[g_tmp_pwr.indx]); + } +#endif + + return g_tmp_pwr.pwr_ptr; + (void)last_idx; + (void)temp_code; + } + else + { + g_tmp_pwr.indx = indx; + return NULL; + } +} +#else +TMP_PWR_PTR manual_cal_set_tmp_pwr(UINT16 cur_val, UINT16 thre, UINT16 *last) +{ + #define DO_SETP (10) + + UINT32 dist = 0, thre_1 = (thre>>1) + 2, thre_2 = thre_1 + (DO_SETP-1)*thre ; + UINT8 need_cal_dpll = 0, need_cal_bais = 0; + + UINT16 last_val = g_tmp_pwr.temp_tab[g_tmp_pwr.indx]; + UINT8 indx = g_tmp_pwr.indx; + + if(cur_val > last_val) + { + dist = cur_val - last_val; + if(dist >= thre_2) + { + indx = ((indx+DO_SETP) < TMP_PWR_TAB_LEN)? (indx + DO_SETP) : TMP_PWR_TAB_LEN-1; + need_cal_dpll = 1; + need_cal_bais = 1; + } + else if(dist >= thre_1) + { + int i; + for(i=DO_SETP-2; i>=0; i--) + { + thre_2 = thre_1 + i*thre; + if(dist >= thre_2) + { + indx = ((indx+(i+1)) < TMP_PWR_TAB_LEN)? (indx+(i+1)) : TMP_PWR_TAB_LEN-1; + break; + } + } + + need_cal_bais = 1; + + if(i >= 1) + { + need_cal_dpll = 1; + } + } + } + else if(cur_val < last_val) + { + dist = last_val - cur_val; + if(dist >= thre_2) + { + indx = (indx>DO_SETP)? indx-DO_SETP:0; + need_cal_dpll = 1; + need_cal_bais = 1; + } + else if(dist >= thre_1) + { + int i; + for(i=DO_SETP-2; i>=0; i--) + { + thre_2 = thre_1 + i*thre; + if(dist >= thre_2) + { + indx = (indx > (i+1))? (indx-(i+1)) : 0; + break; + } + } + + need_cal_bais = 1; + + if(i >= 1) + { + need_cal_dpll = 1; + } + } + } + + if(printf_is_allowed() +#if ATE_APP_FUN + && (get_ate_mode_state() == 0) +#endif + ) + { + os_printf("td cur:%d, last:%d, flag:%d\r\n", cur_val, last_val, g_tmp_pwr.flag); + } + + if(g_tmp_pwr.indx == indx) + return NULL; + + if(need_cal_dpll) + { + if(ble_in_dut_mode() == 0) + os_printf("cal dpll!\r\n"); + + CHECK_OPERATE_RF_REG_IF_IN_SLEEP(); + sctrl_cali_dpll(0); + sctrl_dpll_int_open(); + CHECK_OPERATE_RF_REG_IF_IN_SLEEP_END(); + } + + if(need_cal_bais) + { + if(ble_in_dut_mode() == 0) + os_printf("cal_bias!\r\n"); + bk7011_cal_bias(); + } + + // bk7231U need dist>60, then do tx pwr. + if(g_tmp_pwr.flag) + { + UINT8 last_idx = g_tmp_pwr.indx; + + g_tmp_pwr.indx = indx; + g_tmp_pwr.pwr_ptr = (TMP_PWR_PTR)&tmp_pwr_tab[indx]; + *last = g_tmp_pwr.temp_tab[g_tmp_pwr.indx]; + + ///os_printf("set_tmp_pwr: indx:%d, mod:%d, pa:%d, tmp:%d\r\n", indx, + // g_tmp_pwr.pwr_ptr->mod, g_tmp_pwr.pwr_ptr->pa, *last); + if(ble_in_dut_mode() == 0) + { + bk_printf("do td cur_t:%d--last:idx:%d,t:%d -- new:idx:%d,t:%d \r\n", + cur_val, + last_idx, g_tmp_pwr.temp_tab[last_idx], + g_tmp_pwr.indx, g_tmp_pwr.temp_tab[g_tmp_pwr.indx]); + + bk_printf("--0xc:%02x, shift_b:%d, shift_g:%d, X:%d\n", + g_tmp_pwr.pwr_ptr->trx0x0c_12_15, + g_tmp_pwr.pwr_ptr->p_index_delta, + g_tmp_pwr.pwr_ptr->p_index_delta_g, + g_tmp_pwr.pwr_ptr->xtal_c_dlta); + } + + return g_tmp_pwr.pwr_ptr; + } + else + { + g_tmp_pwr.indx = indx; + return NULL; + } +} +#endif + +void manual_cal_do_single_temperature(void) +{ + UINT32 temp_value; + + if(!temp_single_get_current_temperature(&temp_value)) + { + UINT32 last_value = g_cur_temp; + GLOBAL_INT_DECLARATION(); + + GLOBAL_INT_DISABLE(); + //manual_cal_tmp_pwr_init(g_cur_temp, ADC_TMEP_LSB_PER_10DEGREE * ADC_TMEP_10DEGREE_PER_DBPWR, ADC_TMEP_DIST_INTIAL_VAL); + manual_cal_recover_cur_temp(); + manual_cal_set_tmp_pwr_flag(1); + rwnx_cal_do_temp_detect(temp_value, ADC_TMEP_LSB_PER_10DEGREE * ADC_TMEP_10DEGREE_PER_DBPWR, (UINT16 *)&last_value); + manual_cal_set_tmp_pwr_flag(0); + + GLOBAL_INT_RESTORE(); + + os_printf("std set pwr: idx:%d, shift:%d, rate:%d\r\n", + g_temp_pwr_current.idx, g_temp_pwr_current.shift, + g_temp_pwr_current.mode); + + os_printf("std tpc set pwr: idx:%d, shift:%d, rate:%d\r\n", + g_temp_pwr_current_tpc.idx, g_temp_pwr_current_tpc.shift, + g_temp_pwr_current_tpc.mode); + + os_printf("std done:%0d\r\n", temp_value); + } + else + { + os_printf("std failed\r\n", temp_value); + } +} + +void manual_cal_do_xtal_cali(UINT16 cur_val, UINT16 *last, UINT16 thre, UINT16 init_val) +{ + if(g_tmp_pwr.flag == 0) + return; + +#if CFG_TEMP_DETECT_VERSION == CFG_TEMP_DETECT_VERSION1 + INT32 param; + + param = g_xcali.init_xtal + g_xcali.xtal_c_delta; + if(g_xcali.last_xtal != param) + { +#ifdef ATE_PRINT_DEBUG + os_null_printf("init_xtal:%d, delta:%d, last_xtal:%d\r\n", + g_xcali.init_xtal, + g_xcali.xtal_c_delta, + g_xcali.last_xtal); +#endif + + if (param > PARAM_XTALH_CTUNE_MASK) + { + param = PARAM_XTALH_CTUNE_MASK; + } + else if (param < 0) + { + param = 0; + } + + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_SET_XTALH_CTUNE, ¶m); + g_xcali.last_xtal = param; + + //os_printf("do_xtal_cali: c-d:%d-%d, l:%d, h:%d, v:%d\r\n", cur_val, dist, + // p_xtal->low, p_xtal->high, param); + } +#else + INT16 dist = 0; + XTAL_PTR p_xtal; + UINT32 param, foud = 0; + UINT32 i, tab_len = sizeof(xtal_tab)/sizeof(XTAL_ST); + + dist = cur_val - g_cur_temp_flash; + + p_xtal = (XTAL_PTR)&xtal_tab[tab_len-1]; + + if(dist <= thre) { + param = init_val; + foud = 1; + } else if(dist > p_xtal->low + thre) { + param = p_xtal->value + init_val; + foud = 1; + } else { + for(i=0; i p_xtal->low + thre ) && (dist <= p_xtal->high + thre)) { + param = p_xtal->value + init_val; + foud = 1; + break; + } + } + } + + if((*last != param) && (foud)) { + + if(param > PARAM_XTALH_CTUNE_MASK) + param = PARAM_XTALH_CTUNE_MASK; + + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_SET_XTALH_CTUNE, ¶m); + *last = param; + + os_null_printf("T0:%d,T1:%d,T:%d,X:%d, CT0:%d,CT:%d\r\n", g_cur_temp_flash, cur_val, thre, + dist, init_val, param); + + //os_printf("do_xtal_cali: c-d:%d-%d, l:%d, h:%d, v:%d\r\n", cur_val, dist, + // p_xtal->low, p_xtal->high, param); + } +#endif +} + +UINT32 manual_cal_load_temp_tag_flash(void) +{ + g_cur_temp = g_cur_temp_flash= manual_cal_load_temp_tag_from_flash(); + // start temp dectect + manual_cal_tmp_pwr_init(g_cur_temp, ADC_TMEP_LSB_PER_10DEGREE * ADC_TMEP_10DEGREE_PER_DBPWR, + ADC_TMEP_DIST_INTIAL_VAL); + + return g_cur_temp; +} + +#endif // CFG_USE_TEMPERATURE_DETECT + +#if CFG_SARADC_CALIBRATE +UINT32 manual_cal_load_adc_cali_flash(void) +{ +#if (CFG_SOC_NAME == SOC_BK7231N) + UINT8 values[3]; + values[0] = wifi_read_efuse(18); + values[1] = wifi_read_efuse(19); + values[2] = wifi_read_efuse(20); + if (((0xFF == values[0]) && (0xFF == values[1])) + || ((0x00 == values[0]) && (0x00 == values[1])) + || (0xFF == values[2]) || (0x00 == values[2])) + { + os_printf("uncali adc value:[%02x %02x %02x]\r\n", values[0], values[1], values[2]); + goto FAILURE; + } + saradc_val.low = values[2] & 0x0F; + saradc_val.low = (saradc_val.low << 8) | values[0]; + + saradc_val.high = values[2] & 0xF0; + saradc_val.high = (saradc_val.high << 4) | values[1]; +#else + UINT32 status, addr, addr_start; + DD_HANDLE flash_handle; + TXPWR_ELEM_ST head; + bk_logic_partition_t *pt = bk_flash_get_info(BK_PARTITION_RF_FIRMWARE); + + addr_start = manual_cal_search_txpwr_tab(TXID, pt->partition_start_addr);//TXPWR_TAB_FLASH_ADDR); + if(!addr_start) { + goto FAILURE; + } + + addr = manual_cal_search_txpwr_tab(TXID_ADC, addr_start); + if(!addr) + { + goto FAILURE; + } + + flash_handle = ddev_open(FLASH_DEV_NAME, &status, 0); + ddev_read(flash_handle, (char *)&head, sizeof(TXPWR_ELEM_ST), addr); + ddev_read(flash_handle, (char *)&saradc_val, head.len, addr + sizeof(TXPWR_ELEM_ST)); +#endif + + os_printf("calibrate low value:[%x]\r\n", saradc_val.low); + os_printf("calibrate high value:[%x]\r\n", saradc_val.high); + + return SARADC_SUCCESS; + +FAILURE: + return SARADC_FAILURE; +} +#endif + +#endif // (CFG_SOC_NAME != SOC_BK7231) + diff --git a/beken_os/beken378/func/bk_tuya_pwm/bk_tuya_pwm.c b/beken_os/beken378/func/bk_tuya_pwm/bk_tuya_pwm.c new file mode 100755 index 0000000..67bb89c --- /dev/null +++ b/beken_os/beken378/func/bk_tuya_pwm/bk_tuya_pwm.c @@ -0,0 +1,210 @@ +#include "include.h" +#include "icu_pub.h" +#include "pwm_pub.h" +#include "uart_pub.h" +#include "bk_tuya_pwm.h" +#include "drv_model_pub.h" +#if (CFG_SOC_NAME == SOC_BK7231N) +#include "BkDriverPwm.h" +#endif + +UINT32 bk_cw_pwm_init(uint8 channel_num, uint32 end_value, uint32 duty_cycle) +{ + UINT32 ret; +#if (CFG_SOC_NAME != SOC_BK7231N) + pwm_param_t param; + + TPWM_PRT("tuya_pwm_init: %d %ld %ld\r\n", channel_num, end_value, duty_cycle); + + *(volatile unsigned long *) (0x00802A0C) |= ( (1 << 1)); + + param.channel = channel_num; + param.cfg.bits.en = 0; + param.cfg.bits.int_en = 0; + param.cfg.bits.clk = 1; + param.cfg.bits.mode = 0; + param.end_value = end_value; + param.duty_cycle = duty_cycle; + param.p_Int_Handler = NULL; + ret = sddev_control(PWM_DEV_NAME, CMD_PWM_INIT_PARAM, ¶m); + ASSERT(PWM_SUCCESS == ret); +#else + OSStatus status; + status = bk_pwm_initialize(channel_num, end_value, duty_cycle, 0, 0); + ret = (kNoErr == status) ? PWM_SUCCESS : PWM_FAILURE; +#endif + + return ret; +} + +void bk_cw_pwm_set_duty_cycle(uint8 channel_num, uint32 duty_cycle) +{ + UINT32 ret; + pwm_param_t param; + + TPWM_PRT("tuya_pwm_set_duty_cycle: %d %ld\r\n", channel_num, duty_cycle); + + param.channel = channel_num; +#if (CFG_SOC_NAME != SOC_BK7231N) + param.duty_cycle = duty_cycle; +#else + param.duty_cycle1 = duty_cycle; +#endif + ret = sddev_control(PWM_DEV_NAME, CMD_PWM_SET_DUTY_CYCLE, ¶m); + if (PWM_SUCCESS != ret) + { + TPWM_FATAL("tuya_pwm_set_duty_cycle: error param!\r\n"); + } + ASSERT(PWM_SUCCESS == ret); +} + +void bk_cw_pwm_set_end_value(uint8 channel_num, uint32 end_value) +{ + UINT32 ret; + pwm_param_t param; + + TPWM_PRT("tuya_pwm_set_end_value: %d %ld\r\n", channel_num, end_value); + + param.channel = channel_num; + param.end_value = end_value; + ret = sddev_control(PWM_DEV_NAME, CMD_PWM_SET_END_VALUE, ¶m); + if (PWM_SUCCESS != ret) + { + TPWM_FATAL("tuya_pwm_set_end_value: error param!\r\n"); + } + ASSERT(PWM_SUCCESS == ret); +} + +void bk_cw_pwm_stop(uint8 channel_num_1, uint8 channel_num_2) +{ + UINT32 ret; + UINT32 PWM_channel; + + TPWM_PRT("tuya_pwm_stop: %d %d\r\n", channel_num_1, channel_num_2); + + PWM_channel = channel_num_1; + ret = sddev_control(PWM_DEV_NAME, CMD_PWM_UNIT_DISABLE, &PWM_channel); + ASSERT(PWM_SUCCESS == ret); + + PWM_channel = channel_num_2; + ret = sddev_control(PWM_DEV_NAME, CMD_PWM_UNIT_DISABLE, &PWM_channel); + ASSERT(PWM_SUCCESS == ret); +} + +void bk_cw_pwm_reset_duty_cycle(uint8 channel_num_1, uint8 channel_num_2, + uint32 duty_cycle_1, uint32 duty_cycle_2, + uint32 end_value, uint32 dead_band_1) +{ +#if (CFG_SOC_NAME != SOC_BK7231N) + GLOBAL_INT_DECLARATION(); + UINT32 i_time_out1, i_time_out2, status; + + TPWM_PRT("tuya_pwm_reset_duty_cycle: %d %d %ld %ld %ld %ld\r\n", + channel_num_1, channel_num_2, duty_cycle_1, duty_cycle_2, end_value, dead_band_1); + + if ((channel_num_1 >= PWM_COUNT) || (channel_num_2 >= PWM_COUNT)) + { + TPWM_FATAL("tuya_pwm_reset_duty_cycle param 1 error!\r\n"); + return; + } + + if (end_value < duty_cycle_1 + duty_cycle_2 + dead_band_1*2) + { + TPWM_FATAL("tuya_pwm_reset_duty_cycle param 2 error!\r\n"); + return; + } + + // set PWM 1/2 end value + *(volatile unsigned long *) (0x00802A80 + 0x08 + (channel_num_1 * 3 * 4)) = end_value; + *(volatile unsigned long *) (0x00802A80 + 0x08 + (channel_num_2 * 3 * 4)) = end_value; + + // set PWM 1/2 duty cycle + *(volatile unsigned long *) (0x00802A80 + 0x0C + (channel_num_1 * 3 * 4)) = duty_cycle_1; + *(volatile unsigned long *) (0x00802A80 + 0x0C + (channel_num_2 * 3 * 4)) = duty_cycle_2; + + + //enable pwm1 and pwm1 int + *(volatile unsigned long *) (0x00802040) |= (1 << 9); + *(volatile unsigned long *) (0x00802A80) |= (1 << (channel_num_1 * 4)); + *(volatile unsigned long *) (0x00802A80) |= (1 << (channel_num_1 * 4+1)); + + GLOBAL_INT_DISABLE(); + + while(1) + { + //wait pwm int + status = *(volatile unsigned long *) (0x0080204C); + if(status & (1 << 9)) + { + break; + } + } + + // disable PWM 2 channel + *(volatile unsigned long *) (0x00802A80) &= (~((1 << (channel_num_2 * 4)))); + + // cache tuya_pwm_set_duty_cycle function + do + { + char *text, temp; + int i; + + text = (char *)bk_cw_pwm_reset_duty_cycle; + for (i = 0; i < 0x400; i ++) + { + temp = text[i]; + } + } while(0); + + // delay + { + uint32 slot1, t; + volatile uint32 slot2; + + *(volatile unsigned long *) (0x00802A10) = (1 << 2) | (1 << 0); + i_time_out1 = 0; + while ((*(volatile unsigned long *) (0x00802A10)) & (1 << 0)) + { + i_time_out1 ++; + if (i_time_out1 > (120 * 1000)) + { + break; + } + } + slot1 = *(volatile unsigned long *) (0x00802A14); + + //pwm int time about 5us + t = duty_cycle_1 + dead_band_1 + slot1; + i_time_out1 = 0; + while (1) + { + *(volatile unsigned long *) (0x00802A10) = (1 << 2) | (1 << 0); + i_time_out2 = 0; + while ((*(volatile unsigned long *) (0x00802A10)) & (1 << 0)) + { + i_time_out2 ++; + if (i_time_out2 > (120 * 1000)) + { + break; + } + } + slot2 = *(volatile unsigned long *) (0x00802A14); + if (slot2 >= t) + { + break; + } + + i_time_out1 ++; + if (i_time_out1 > (120 * 1000)) + { + break; + } + } + } + + // enable PWM channel 1/2 + *(volatile unsigned long *) (0x00802A80) |= (1 << (channel_num_1 * 4)) + | (1 << (channel_num_2 * 4)); + GLOBAL_INT_RESTORE(); +#endif +} diff --git a/beken_os/beken378/func/bk_tuya_pwm/bk_tuya_pwm.h b/beken_os/beken378/func/bk_tuya_pwm/bk_tuya_pwm.h new file mode 100755 index 0000000..df16d1e --- /dev/null +++ b/beken_os/beken378/func/bk_tuya_pwm/bk_tuya_pwm.h @@ -0,0 +1,31 @@ +#ifndef _BK_TUYA_PWM_H_ +#define _BK_TUYA_PWM_H_ + +#define TPWM_DEBUG +#undef TPWM_DEBUG + +#ifdef TPWM_DEBUG +#define TPWM_PRT os_printf +#define TPWM_WARN warning_prf +#define TPWM_FATAL fatal_prf +#else +#define TPWM_PRT null_prf +#define TPWM_WARN null_prf +#define TPWM_FATAL null_prf +#endif + + +extern UINT32 bk_cw_pwm_init(uint8 channel_num, uint32 end_value, uint32 duty_cycle); + +extern void bk_cw_pwm_set_duty_cycle(uint8 channel_num, uint32 duty_cycle); +extern void bk_cw_pwm_set_end_value(uint8 channel_num, uint32 end_value); + +extern void bk_cw_pwm_stop(uint8 channel_num_1, uint8 channel_num_2); + +extern void bk_cw_pwm_reset_duty_cycle(uint8 channel_num_1, uint8 channel_num_2, + uint32 duty_cycle_1, uint32 duty_cycle_2, + uint32 end_value, uint32 dead_band_1); + +#endif + + diff --git a/beken_os/beken378/func/camera_intf/camera_inft.c b/beken_os/beken378/func/camera_intf/camera_inft.c new file mode 100755 index 0000000..770ce2f --- /dev/null +++ b/beken_os/beken378/func/camera_intf/camera_inft.c @@ -0,0 +1,278 @@ +#include "include.h" +#include "arm_arch.h" + +#if CFG_USE_CAMERA_INTF +//#include "process.h" +#include "llc.h" + +#include "video_transfer.h" + +#include "jpeg_encoder_pub.h" +#include "i2c_pub.h" + +#include "camera_intf.h" +#include "camera_intf_pub.h" + +#include "drv_model_pub.h" +#include "general_dma_pub.h" +#include "mem_pub.h" +#include "bk_timer_pub.h" + +#define CAMERA_INTF_DEBUG +#include "uart_pub.h" +#ifdef CAMERA_INTF_DEBUG +#define CAMERA_INTF_PRT os_printf +#define CAMERA_INTF_WPRT warning_prf +#define CAMERA_INTF_FATAL fatal_prf +#else +#define CAMERA_INTF_PRT null_prf +#define CAMERA_INTF_WPRT null_prf +#define CAMERA_INTF_FATAL null_prf +#endif + +#define EJPEG_DMA_CHNAL GDMA_CHANNEL_5 +#define EJPEG_DELAY_HTIMER_CHNAL 3 +#define EJPEG_DELAY_HTIMER_VAL (2) // 2ms +#define USE_JTAG_FOR_DEBUG 0 + +DJPEG_DESC_ST ejpeg_cfg; +DD_HANDLE i2c_hdl = DD_HANDLE_UNVALID, ejpeg_hdl = DD_HANDLE_UNVALID; +I2C_OP_ST i2c_operater; + +void camera_intf_delay_timer_hdl(UINT8 param) +{ + #if CFG_GENERAL_DMA + GDMA_CFG_ST en_cfg; + UINT16 already_len = ejpeg_cfg.rx_read_len; + UINT32 channel = ejpeg_cfg.dma_channel; + GLOBAL_INT_DECLARATION(); + + REG_WRITE((0x00802800+(16*4)), 0x02); + + int left_len = sddev_control(GDMA_DEV_NAME, CMD_GDMA_GET_LEFT_LEN, (void*)channel); + int rec_len = ejpeg_cfg.node_len - left_len; + UINT32 frame_len = 0; + frame_len = ddev_control(ejpeg_hdl, EJPEG_CMD_GET_FRAME_LEN, NULL); + + if((ejpeg_cfg.node_full_handler != NULL) && (rec_len > 0)) { + ejpeg_cfg.node_full_handler(ejpeg_cfg.rxbuf + already_len, rec_len, 1, frame_len); + } + + already_len += rec_len; + if(already_len >= ejpeg_cfg.rxbuf_len) { + already_len -= ejpeg_cfg.rxbuf_len; + } + + GLOBAL_INT_DISABLE(); + ejpeg_cfg.rx_read_len = already_len; + GLOBAL_INT_RESTORE(); + + // turn off dma, so dma can start from first configure. for easy handler + en_cfg.channel = ejpeg_cfg.dma_channel; + en_cfg.param = 0; + sddev_control(GDMA_DEV_NAME, CMD_GDMA_SET_DMA_ENABLE, &en_cfg); + + ejpeg_cfg.rx_read_len = 0; + en_cfg.param = 1; + sddev_control(GDMA_DEV_NAME, CMD_GDMA_SET_DMA_ENABLE, &en_cfg); + #endif + + if((ejpeg_cfg.data_end_handler)) { + ejpeg_cfg.data_end_handler(); + } + + channel = EJPEG_DELAY_HTIMER_CHNAL; + sddev_control(TIMER_DEV_NAME, CMD_TIMER_UNIT_DISABLE, &channel); + + REG_WRITE((0x00802800+(16*4)), 0x00); +} + +static void camera_intf_start_delay_timer(void) +{ + timer_param_t param; + + REG_WRITE((0x00802800+(16*4)), 0x02); + + param.channel = EJPEG_DELAY_HTIMER_CHNAL; + param.div = 1; + param.period = EJPEG_DELAY_HTIMER_VAL; + param.t_Int_Handler= camera_intf_delay_timer_hdl; + + sddev_control(TIMER_DEV_NAME, CMD_TIMER_INIT_PARAM, ¶m); + + REG_WRITE((0x00802800+(16*4)), 0x00); +} + +static void camera_intf_ejpeg_rx_handler(UINT32 dma) +{ + UINT16 already_len = ejpeg_cfg.rx_read_len; + UINT16 copy_len = ejpeg_cfg.node_len; + GLOBAL_INT_DECLARATION(); + + REG_WRITE((0x00802800+(17*4)), 0x02); + + if(ejpeg_cfg.node_full_handler != NULL) { + ejpeg_cfg.node_full_handler(ejpeg_cfg.rxbuf + already_len, copy_len, 0, 0); + } + + already_len += copy_len; + + if(already_len >= ejpeg_cfg.rxbuf_len) + already_len = 0; + + GLOBAL_INT_DISABLE(); + ejpeg_cfg.rx_read_len = already_len; + GLOBAL_INT_RESTORE(); + + REG_WRITE((0x00802800+(17*4)), 0x00); +} + +static void camera_intf_ejpeg_end_handler(void) +{ + camera_intf_start_delay_timer(); +} + +static void camera_intf_config_ejpeg(void* data) +{ + os_memset(&ejpeg_cfg, 0, sizeof(DJPEG_DESC_ST)); + os_memcpy(&ejpeg_cfg, data, sizeof(TVIDEO_DESC_ST)); + + ejpeg_cfg.x_pixel = X_PIXEL_640; + ejpeg_cfg.y_pixel = Y_PIXEL_480; + + ejpeg_cfg.start_frame_handler = NULL; + ejpeg_cfg.end_frame_handler = camera_intf_ejpeg_end_handler; + +#if CFG_GENERAL_DMA + ejpeg_cfg.dma_rx_handler = camera_intf_ejpeg_rx_handler; + ejpeg_cfg.dma_channel = GDMA_CHANNEL_4; +#endif +} + +static void camera_intf_sccb_write(UINT8 addr, UINT8 data) +{ + char buff = (char)data; + + i2c_operater.op_addr = addr; + ddev_write(i2c_hdl, &buff, 1, (UINT32)&i2c_operater); +} + +void camera_intf_sccb_read(UINT8 addr, UINT8 *data) +{ + i2c_operater.op_addr = addr; + ddev_read(i2c_hdl, (char*)data, 1, (UINT32)&i2c_operater); +} + +static void camera_intf_config_senser(void) +{ + UINT32 i, size; + UINT8 addr, data; + +#if (USE_CAMERA == PAS6329_DEV) + + i2c_operater.salve_id = PAS6329_DEV_ID; + + size = sizeof(pas6329_page0)/2; + PAS6329_SET_PAGE0; + + for(i=0; iJS//AE_HIST_LLUB[5:0]; AE Bias4 parameters + {0x07, 0x64}, // 64//A0//AE Indoor Y-Thd[7:0] + {0x08, 0x61}, + {0x09, 0x00}, + {0x0A, 0x64}, + {0x0C, 0x00}, + {0x0D, 0x00}, // AE_HIST_BiasUB[7:0] ; AE Bias1 parameters + {0x0E, 0x00}, // AE_HIST_BiasThd[7:0] ; AE Bias1 parameters + {0x0F, 0x9B}, // AWB_Windows_X[7:0] + {0x11, 0x6E}, // AWB_Windows_Y[7:0] + {0x13, 0x62}, // For 24MHz. 27M use 0xAE + {0x14, 0x22}, // For 24MHz. 27M use 0x22 + {0x15, 0x32}, // 00//55//45//32==>JS//AE_HIST_BrightBit[6:4]==>AE Bias 2;AE_HIST_DarkBit[2:0];AE Bias3 + {0x16, 0x57}, // 5f//58//AE_HIST_DarkBin[7:4];AE_HIST_PeakThd[3:0]; AE Bias3 parameters + {0x17, 0x02}, // AE_HIST_NullThd[3:0] ; AE Bias2 parameters + {0x19, 0x3E}, // AWB_Digital Gain_Low Bound for R + {0x1A, 0x67}, // AWB_Digital Gain_Upper Bound for B + {0x1B, 0x3C}, // 41//3C==>JS//AWB_Digital Gain_Low Bound for B + {0x1C, 0x6B}, // AWB_Digital Gain_Upper for R + {0x1D, 0x99}, + {0x1E, 0x98}, + {0x1F, 0x10}, // 10//Denoise_En[4] + {0x20, 0x16}, // 0x22);//22//DeNoise_Str_G[7:0] + {0x21, 0x00}, // 0x10);//0x12);//18//12//18//18//18//12==>JS//DeNoise_H_LB_G[7:0] + {0x22, 0x60}, // DeNoise_H_UB_G[7:0] + {0x23, 0x16}, // 0x24);//16//24//DeNoise_Str_RB[7:0] + {0x24, 0x00}, // 0x10);//0x12);//12//1a//1a//1A//12==>JS//DeNoise_H_LB_RB[7:0] + {0x25, 0x60}, // 60==>JS//DeNoise_H_UB_RB[7:0] + {0x26, 0x00}, // DeNoise_Gain_Offset_G[7:0] + {0x27, 0x00}, // DeNoise_Gain_Offset_RB[7:0] + {0x29, 0x01}, // G_40_ISP_Gamma_EnH[0] + {0x2A, 0x11}, // 11//0F//12//ISP_Gamma_Y0[7:0] + {0x2B, 0x20}, // 20//1D//22//ISP_Gamma_Y1[7:0] + {0x2C, 0x3A}, // 3A//36//3D//ISP_Gamma_Y2[7:0] + {0x2D, 0x64}, // 64//5D//67//ISP_Gamma_Y3[7:0] + {0x2E, 0x75}, // 75//6D//77//ISP_Gamma_Y4[7:0] + {0x2F, 0x84}, // 84//7B//85//ISP_Gamma_Y5[7:0] + {0x30, 0x92}, // 92//87//91//ISP_Gamma_Y6[7:0] + {0x31, 0x9F}, // 9F//92//9C//ISP_Gamma_Y7[7:0] + {0x32, 0xB5}, // B5//A5//AE//ISP_Gamma_Y8[7:0] + {0x33, 0xC7}, // C7//B4//BD//ISP_Gamma_Y9[7:0] + {0x34, 0xD5}, // D5//C1//C9//ISP_Gamma_Y10[7:0] + {0x35, 0xE0}, // E0//CC//D3//ISP_Gamma_Y11[7:0] + {0x36, 0xEF}, // EF//DE//E2//ISP_Gamma_Y12[7:0] + {0x37, 0xF8}, // F8//EC//EE//ISP_Gamma_Y13[7:0] + {0x38, 0xFD}, // FD//F6//F8//ISP_Gamma_Y14[7:0] + {0x39, 0x01}, + {0x3A, 0x28}, + {0x3B, 0x28}, + {0x3C, 0x24}, + {0x3D, 0x1E}, + {0x3E, 0x00}, // 02//01//02//02//AE_HIST_Backlight[2:0] + {0x3F, 0x0F}, // 0b//0F//AE_HIST_Step_V[4:0] + {0x40, 0x0A}, // 58//0A//AE_HIST_HStart[7:0] + {0x41, 0x19}, // 53//19//AE_HIST_VStart[7:0] + {0x42, 0x41}, + {0x43, 0x01}, + {0x44, 0x00}, + {0x45, 0x02}, + {0x46, 0x02}, + {0x47, 0x31}, // AWB_ShowActivePix[7];AWB_Speed[1:0] + {0x48, 0x5A}, // 0x50;//5A//50==>JS//AWB_CThdM[3:0];AWB_CThdStep[7:4] //50 + {0x49, 0x7F}, // 7F//AWB_SumRatio_B[7:0] + {0x4A, 0x86}, // AWB_SumRatio_R[7:0] + {0x4B, 0x42}, // AWB_CThdL[7:0] + {0x4C, 0x14}, // 0x05);//0x05);//05//05//10==>JS//AWB_CThdH[7:0] //10 + {0x4D, 0x64}, // AWB_CbThdL[7:0] + {0x4E, 0x87}, // AWB_CrThdL[7:0] + {0x4F, 0x6E}, // AWB_CbCrThdL[7:0] + {0x50, 0x75}, // AWB_CbThdH[7:0] + {0x51, 0x96}, // AWBCrThdH[7:0] + {0x52, 0x86}, // 0x8C);//8C//86//8C==>JS//AWB_CbCrThdH[7:0] // 20160308 davis for AWB + {0x53, 0x28}, // 0x14);//R_YLow_NL[7:0] + {0x54, 0xF5}, // R_YHigh7:0] + {0x55, 0x53}, // 0x33);//0x53);//53//33//53//33==>JS//AWB_CThdDn[3:0];AWB_CThdUp[7:4] //33 // 20160308 davis for AWB + {0x56, 0x0D}, // 0x18); //0x14);//16//18//16//AE_Stage_YLow_LL_Thd[4:0] // 20160308 davis for AWB + {0x57, 0x01}, // AWB_LockRange_In[3:0] + {0x58, 0x05}, // AWB_LockRange_Out[5:0] + {0x59, 0x03}, // AWB_LockRange_In_LL[5:0] + {0x5A, 0x08}, // AWB_LockRange_Out_LL[5:0] + {0x5B, 0x02}, // AWB_MinStep_th[2:0] + {0x5C, 0x10}, // 0c//10//AE_HIST_Step_H[4:0] + {0x5D, 0xFF}, + {0x5F, 0x05}, // 06//05==>JS//08//AE_LockRange_Out_LB[7:0] + {0x60, 0x01}, // 01//00//G_Balance_En[0] + {0x61, 0x04}, // G_Balance_Thd[3:0] + {0x62, 0x02}, // G_Balance_ThdLB[7:0] + {0x63, 0x30}, + {0x64, 0x05}, // 0A//05==>JS//0F/AE_LockRange_Out_UB[7:0] + {0x65, 0x40}, // 50//40==>JS//40//AE_LockRange_In[7:4] + {0x66, 0x12}, // 0x13);//12//13//AE_EnH[4] ; Freq_60[0]==>0/1 : 50/60Hz + {0x67, 0xC7}, // for 24M. 27M use 0x7F + {0x68, 0x2D}, // for 24M. 27M use 0x33 + {0x6B, 0x06}, // 0x03);//0x06//R_AE_minStage[4:0] + {0x6C, 0x0F}, // 0x0E);//0x0D);//0x14);//16//19//1A//R_AE_maxStage[4:0] + {0x6D, 0x58}, // 50//60//58==>JS//AG_Stage_UB[7:0] at Max AE Stage + {0x6E, 0x13}, + {0x6F, 0x50}, // 0x50);//0x55);// 0x55 //0x4B);//4b//50//50//4B==>JS//55//Ytarget[7:0] + {0x70, 0x00}, + {0x71, 0x00}, + {0x72, 0x03}, // 0x03 ;//01//AWB_EnH[0] ; AWB_RegionMode[1] //03 + {0x73, 0xC5}, // AWB_Bal_Gain_R[7:0] + {0x74, 0x9C}, // AWB_Bal_Gain_B[7:0] + {0x75, 0x0D}, // AWB_Weight_LL[1:0];AWB_Weight_LH[3:2];AWB_Weight_HL[5:4];AWB_Weight_HH[7:6] + {0x76, 0x96}, + {0x78, 0x01}, + {0x79, 0x16}, + {0x7B, 0x04}, + {0x7C, 0x03}, + {0x7D, 0x00}, + {0x7E, 0x00}, + {0x7F, 0xFF}, + {0x80, 0x86}, + {0x81, 0x00}, // 00//AE_Speed[5:4]==>0:1x ; 1:1/2x ; 2:1/4x ; 3:1/8x ;AE_MinStep_th[1:0] + {0x84, 0x1C}, + {0x86, 0x09}, + {0x87, 0xEA}, + {0x88, 0x01}, + {0x89, 0x00}, + {0x8A, 0x00}, + {0x8B, 0x00}, + {0x8C, 0x9E}, + {0x8E, 0x00}, + {0x8F, 0x00}, + {0x90, 0x00}, + {0x91, 0x00}, + {0x92, 0x00}, + {0x93, 0x00}, + {0x94, 0x00}, + {0x95, 0x0A}, + {0x97, 0x10}, // Shading_En[4] + {0x98, 0x00}, + {0x99, 0x46}, // Offset_X_R[6:0] + {0x9A, 0x52}, // Offset_Y_R[6:0] + {0x9B, 0x4C}, // Offset_X_G[6:0] + {0x9C, 0x52}, // Offset_Y_G[6:0] + {0x9D, 0x4A}, // Offset_X_B[6:0] + {0x9E, 0x52}, // Offset_Y_B[6:0] + {0x9F, 0x72}, // LSC_R1[6:0] + {0xA0, 0x46}, // 46//LSC_G1[6:0] + {0xA1, 0x34}, // LSC_B1[6:0] + {0xA2, 0x4C}, // 41//LSC_R2[6:0] + {0xA3, 0x54}, // 3D//LSC_G2[6:0] + {0xA4, 0x54}, // LSC_B2[6:0] + {0xA5, 0x05}, // LSFT_1[6:0] + {0xA6, 0x01}, // LSFT_2[1:0] + {0xA7, 0x01}, // LSFT_3[3:0] + {0xA9, 0x00}, // 0xD0 + {0xAA, 0x00}, + {0xC6, 0xB9}, // 0xA2 + {0xC7, 0x00}, + {0xC8, 0x80}, + {0xC9, 0x00}, + {0xCA, 0xA3}, // 0xB7 + {0xCB, 0x00}, + {0xDF, 0x20}, + {0xE0, 0x80}, + {0xE1, 0x02}, + {0xE2, 0xE0}, + {0xE3, 0x01}, + {0xE6, 0x00}, + {0xE9, 0x87}, + {0xEA, 0x00}, + {0xEB, 0x00}, + {0xED, 0x00}, + {0xEE, 0x3F}, + {0xED, 0x01}, +}; + +const UINT8 pas6329_page1[][2] = { + {0x02, 0x01}, + {0x03, 0x83}, + {0x04, 0x62}, // 0xFC);//0x78); + {0x05, 0x02}, // 0x01);//0x04); + {0x06, 0x10}, + {0x07, 0x0F}, // 0x13); // 20160308 davis for AWB + {0x08, 0x10}, + {0x09, 0x0F}, + {0x0C, 0x03}, + {0x0D, 0x20}, // 0x62); + {0x0E, 0xE5}, // 0x02); + {0x0F, 0x01}, // 0x00); + {0x11, 0x00}, + {0x12, 0x00}, + {0x17, 0x00}, + {0x18, 0x00}, + {0x19, 0x00}, + {0x1A, 0x00}, + {0x1B, 0x8F}, + {0x1C, 0x02}, + {0x1D, 0xEB}, + {0x1E, 0x01}, + {0x20, 0x14}, + {0x21, 0x00}, // 0x00//0x0C//Flip (bit3) & Mirror (bit2) + {0x22, 0x08}, + {0x23, 0x00}, + {0x24, 0x05}, + {0x27, 0x03}, + {0x28, 0x00}, + {0x2A, 0x00}, + {0x2B, 0x4A}, + {0x2C, 0x7D}, + {0x2D, 0x13}, + {0x2E, 0x49}, + {0x2F, 0x4A}, + {0x30, 0x68}, + {0x31, 0x96}, + {0x32, 0xAB}, + {0x33, 0x31}, + {0x34, 0x81}, + {0x35, 0x00}, // 06//DigDac_offset_Gb1 + {0x36, 0x00}, // 06//DigDac_offset_B1 + {0x37, 0x00}, // 06//DigDac_offset_Gr1 + {0x38, 0x00}, // 06//DigDac_offset_R1 + {0x39, 0x20}, + {0x3B, 0x04}, + {0x3C, 0x04}, + {0x3D, 0x04}, + {0x3E, 0x04}, + {0x40, 0x00}, + {0x41, 0x06}, + {0x42, 0x00}, + {0x43, 0x82}, + {0x44, 0x0E}, + {0x45, 0x23}, + {0x48, 0x21}, + {0x49, 0x11}, + {0x4A, 0x00}, + {0x4B, 0x08}, // 00//08//[3] T_cg_offset_EnL + {0x50, 0x03}, + {0x51, 0x44}, + {0x52, 0x79}, + {0x53, 0x80}, + {0x54, 0x00}, + {0x56, 0x00}, + {0x57, 0x00}, + {0x5D, 0x00}, + {0x5E, 0x14}, + {0x60, 0x00}, + {0x62, 0x35}, + {0x63, 0x7F}, + {0x64, 0x34}, + {0x66, 0x06}, + {0x67, 0x08}, + {0x68, 0x07}, + {0x6F, 0x00}, + {0x70, 0x00}, + {0x71, 0x00}, + {0x72, 0x00}, + {0x73, 0x00}, + {0x74, 0x00}, + {0x75, 0x00}, + {0x76, 0x00}, + {0x77, 0x20}, + {0x78, 0x07}, // 0x05); + {0x79, 0x0F}, + {0x7A, 0x0F}, + {0x7B, 0x8A}, + {0x7E, 0x00}, + {0x7F, 0x01}, + {0x80, 0x00}, + {0x82, 0x00}, + {0x87, 0x00}, + {0x88, 0x00}, + {0x89, 0x00}, + {0x8A, 0x00}, + {0x8B, 0x00}, + {0x8C, 0x00}, + {0x8D, 0x00}, + {0x8E, 0x00}, + {0x8F, 0x00}, + {0x90, 0x00}, + {0x91, 0x00}, + {0x9E, 0x02}, + {0x9F, 0x00}, + {0xA1, 0x04}, + {0xA2, 0xC0}, + {0xA4, 0x00}, + {0xA5, 0x00}, + {0xA6, 0x00}, + {0xA7, 0x06}, + {0xA8, 0x0F}, + {0xA9, 0x00}, + {0xAA, 0xAA}, + {0xAB, 0x55}, + {0xAC, 0x66}, + {0xB0, 0x05}, + {0xB1, 0x3F}, + {0xB2, 0xCA}, + {0xB4, 0x02}, + {0xB6, 0x0C}, + {0xBE, 0x4A}, + {0xBF, 0x80}, + {0xC0, 0x13}, + {0xC1, 0x49}, + {0xC2, 0x4A}, + {0xC3, 0x80}, + {0xC4, 0x13}, + {0xC5, 0x49}, + {0xC6, 0x4A}, + {0xC7, 0x80}, + {0xC8, 0x13}, + {0xC9, 0x49}, + {0xCA, 0x00}, + {0xCB, 0x00}, + {0xCC, 0x00}, + {0xCD, 0x00}, + {0xCE, 0x00}, + {0xCF, 0x00}, + {0xD0, 0x00}, + {0xD1, 0x00}, + {0xD2, 0x00}, + {0xD3, 0x00}, + {0xD4, 0x00}, + {0xD5, 0x00}, + {0x11, 0x01}, +}; + +const UINT8 pas6329_page2[][2] = { + {0x00, 0x00}, + {0x0B, 0x1A}, // 1a//0a//1a//0A//1A==>JS//AUTO_Contrast_EnH[4];AUTO_Contrast_Strength[3:0] + {0x0C, 0x4B}, // AUTO_Contrast_UB[7:0] + {0x0D, 0x44}, // 0x40);//44//40//AUTO_Contrast_LB[7:0] + {0x0E, 0x00}, + {0x0F, 0x96}, + {0x10, 0x32}, + {0x11, 0x0F}, // AE_HIST_Bias_Stage[4:0] + {0x12, 0x8C}, // AE_HIST_Bright_Thd[7:0] + {0x13, 0x28}, // AE_HIST_Dark_Thd[7:0] + {0x14, 0x2D}, // AE_HIST_BCountLmt[7:0] + {0x15, 0x1E}, // AE_HIST_DCountLmt[7:0] + {0x17, 0x00}, + {0x18, 0x40}, + {0x19, 0x80}, + {0x1A, 0x61}, // 0x71);//AWB_Skin_Mode[4] ; AWB_Skin_Mask[1] ; AWB_Mask[0] + {0x1B, 0x86}, // AWB_Weight_SH[7:4] ; AWB_Weight_SL[3:0] + {0x1C, 0x6E}, // AWB_SCbThdL[7:0] + {0x1D, 0x7D}, // AWB_SCbThdH[7:0] + {0x1E, 0x84}, // AWB_SCrThdL[7:0] + {0x1F, 0x96}, // AWB_SCrThdL[7:0] + {0x20, 0xF5}, // AWB_SThdY[7:0] + {0x21, 0x02}, // AWB_SThdR[4:0] + {0x22, 0x08}, // 08//Defect_En[3] + {0x26, 0x18}, // DefectThd_NL[4:0] + {0x27, 0x08}, // DefectThd_LL[4:0] + {0x2A, 0x80}, + {0x2B, 0x00}, // Edge_Test_Mode[3:0] + {0x2C, 0x1f}, // 0x14);//0x20); + {0x2D, 0x1f}, // 0x14);//0x20); + {0x2E, 0x00}, // 0x10);//10//Edge_Thd_LB[7:0] + {0x2F, 0x0D}, // 16//19//AE_Stage_LL[4:0] + {0x30, 0x0D}, // AE_Stage_NL[4:0] + {0x31, 0x01}, + {0x35, 0x0F}, // Gamma_Strengh_NL[4:0] + {0x36, 0x04}, // Manual_Gamma_Strengh[5];Gamma_Strengh_Delta[4:0] + {0x37, 0x08}, // 0A//Gamma_Strengh_LL[3:0] + {0x38, 0x8D}, // 0x8F);//8e//92//8f//8E//92==>JS//AE_Middle_Gain_En[7];AE_Middle_Stage[4:0] + {0x39, 0x01}, // 00//01//AE_Middle_Gain[5:0] + {0x3A, 0x8B}, + {0x3C, 0x00}, + {0x3E, 0x33}, // 33//33//32//33==>JS//32//32//CCM_Sign[5:0]==>Sign Bit + {0x3F, 0x1F}, // 25//1F//25//1F==>JS//32//CCM_0_0[7:0] + {0x40, 0x48}, // 4b//48//4b//4F//48==>JS//4B//CCM_0_1[7:0] + {0x41, 0x19}, // 10//19//10//0C//19==>JS//03//CCM_0_2[7:0] + {0x42, 0x20}, // 14//14//20//14//20==>JS//20//0B//32//32//CCM_1_0[7:0]==>Cb_CCM + {0x43, 0xa0}, // 7D//8C//7D==>JS//A0//42//9D//CCM_1_1[7:0]==>Cb_CCM + {0x44, 0xc0}, // a0//A0//9D//A0//A5//A5//9D==>JS//C0//4D//cF//CF//CCM_1_2[7:0]==>Cb_CCM + {0x45, 0x90}, // 90//80//78//90==>JS//70//90//46//98//CCM_2_0[7:0]==>Cr_CCM + {0x46, 0x90}, // 82//80//78//85//91//82==>JS//70//A0//48//A8//CCM_2_1[7:0]==>Cr_CCM + {0x47, 0x00}, // 06//08//08//00//0E//00//00//0E==>JS//06//10//02//10//CCM_2_2[7:0]==>Cr_CCM + {0x50, 0x20}, // Y_Thd_H[6:0] + {0x51, 0x02}, // Y_Thd_L[4:0] + {0x52, 0x10}, // C_Thd_H[4:0] + {0x53, 0x03}, // 02//02//03==>JS//C_Thd_L[4:0] + {0x54, 0x01}, // False_Color_Cancel[0] + {0x55, 0x00}, // Manual_EdgeRatio[4] + {0x56, 0x04}, // EdgeRatio_Delta[4:0] + {0x57, 0x0C}, // 0x04);//10//04//0c//02//04==>JS//EdgeRatio_LL[4:0] + {0x58, 0x16}, // 0x18);//range -> 0x10~0x1F + {0x59, 0x00}, // Manual_Edge_th[4] + {0x5A, 0x02}, // 0e//Edge_th_Delta[4:0] + {0x5B, 0x0f}, // 0x18);//01//18//14//14//Edge_Th_LL[7:0] + {0x5C, 0x0C}, // 0x08//0x0a,//0x0C);//0x08);//range -> 0x0A~0x00 + {0x5D, 0x00}, // Manual_Saturation[4];Saturation_2X[1];Saturation_Fast[0] + {0x5E, 0x06}, // Saturation_Delta[4:0] + {0x5F, 0x14}, // 0x16);//0d//10//0E//0D==>JS//18//0E//Saturation_LL[4:0] + {0x60, 0x10}, // 0x16);//0x10);//1f//10//Saturation_NL[4:0] + {0x61, 0x00}, // Manual_Shading_CP[4];Shading_Fast[0] + {0x62, 0x05}, // Shading_Delta[4:0] + {0x63, 0xFF}, // 0x4F);//4f//ff//EF//Shading_CP_LL[7:4] ; Shading_CP_NL[3:0] + {0x64, 0x03}, // Contrast_Yavg[4] ; Contrast_En[0] + {0x65, 0x40}, // 0x48);//43//48//46//48==>JS//46//Contrast_Str[7:0] + {0x66, 0x96}, // 96//FA//96==>JS//Contrast_CP[7:0] + {0x67, 0x07}, + {0x68, 0x08}, + {0x69, 0x00}, // 10//20//Brightness_LL[7:0] + {0x6A, 0x00}, // Brightness_NL[7:0] + {0x6C, 0x32}, + {0x6D, 0x12}, + {0x6E, 0x08}, + {0x6F, 0x0D}, + {0x70, 0x02}, + {0x71, 0x00}, + {0x72, 0x0E}, + {0x73, 0x08}, + {0x74, 0x31}, + {0x75, 0x01}, + {0x76, 0x14}, + {0x77, 0x0A}, + {0x78, 0x14}, + {0x79, 0x03}, + {0x7A, 0x00}, + {0x7B, 0x02}, + {0x7C, 0x15}, + {0x7D, 0x00}, + {0x9B, 0x02}, + {0x9C, 0x80}, + {0x9D, 0x01}, + {0x9E, 0xE0}, + {0x9F, 0x00}, + {0xA0, 0x00}, + {0xA1, 0x00}, + {0xA2, 0x00}, + {0xA4, 0x02}, + {0xAD, 0x00}, + {0xAE, 0x00}, + {0xB2, 0x00}, + {0xBC, 0x13}, + {0xBD, 0x01}, + {0xBE, 0x00}, + {0xBF, 0x00}, // 0x04); + {0xC0, 0x00}, + {0xC1, 0x03}, // 0x03);//03 //0x0f Hsync/Vsyncͬʱʹ + {0xC2, 0x00}, + {0xC8, 0x80}, + {0xC9, 0x00}, + {0xCA, 0x00}, + {0xCB, 0x02}, + {0xCC, 0xD0}, + {0xCD, 0x00}, + {0xE0, 0x04}, + {0xE3, 0x00}, + {0xE4, 0x00}, + {0xE5, 0x00}, + {0xE6, 0x00}, + {0xEB, 0x00}, + {0x00, 0x01}, + {0xEF, 0x00}, + {0x3E, 0x00}, + {0x56, 0x0D}, + {0x6B, 0x06}, + {0x6C, 0x0D}, + {0xEF, 0x02}, + {0x2F, 0x1F}, + {0x30, 0x0D}, + {0x38, 0x0D}, + {0x39, 0x01}, +}; + +#elif (USE_CAMERA == OV_7670_DEV) +const UINT8 ov_7670_init_talbe[][2] = { + {0x12,0x80}, + {0x11,0x80}, // 0x02 // 30fps + {0x6b,0x0a}, // 0x8a // pclk*6 + {0x3a,0x04}, // 0x0c // modify by jianghumaibg + {0x3d,0xc2}, + {0x12,0x00}, + {0x15,0x00}, + {0x17,0x13}, + {0x18,0x01}, + {0x32,0xbf}, + {0x19,0x02}, + {0x1a,0x7a}, + {0x03,0x0a}, + {0x0c,0x00}, + {0x3e,0x00}, + {0x70,0x3a}, + {0x71,0x35}, + {0x72,0x11}, + {0x73,0xf0}, + {0xa2,0x02}, + {0x7a,0x21}, + {0x7b,0x05}, + {0x7c,0x13}, + {0x7d,0x29}, + {0x7e,0x52}, + {0x7f,0x63}, + {0x80,0x71}, + {0x81,0x7c}, + {0x82,0x85}, + {0x83,0x8f}, + {0x84,0x95}, + {0x85,0xa3}, + {0x86,0xae}, + {0x87,0xc3}, + {0x88,0xd5}, + {0x89,0xe7}, + {0x13,0xe0}, + {0x01,0x80}, + {0x02,0x80}, + {0x00,0x00}, + {0x10,0x00}, + {0x0d,0x50}, + {0x42,0x40}, + {0x14,0x1a}, + {0xa5,0x05}, + {0xab,0x07}, + {0x24,0x45}, + {0x25,0x33}, + {0x26,0xe3}, + {0x55,0x00}, + {0x9f,0xa0}, + {0xa0,0x90}, + {0xa1,0x0b}, + {0xa6,0xd8}, + {0xa7,0xd8}, + {0xa8,0xf0}, + {0xa9,0x90}, + {0xaa,0x94}, + {0x13,0xe5}, + {0x0e,0x61}, + {0x0f,0x4b}, + {0x16,0x02}, + {0x1e,0x07}, + {0x21,0x02}, + {0x22,0x91}, + {0x29,0x07}, + {0x33,0x0b}, + {0x35,0x0b}, + {0x37,0x1d}, + {0x38,0x71}, + {0x39,0x2a}, + {0x3c,0x78}, + {0x4d,0x40}, + {0x4e,0x20}, + {0x69,0x00}, + {0x74,0x19}, + {0x8d,0x4f}, + {0x8e,0x00}, + {0x8f,0x00}, + {0x90,0x00}, + {0x91,0x00}, + {0x92,0x19}, + {0x96,0x00}, + {0x9a,0x80}, + {0xb0,0x84}, + {0xb1,0x0c}, + {0xb2,0x0e}, + {0xb3,0x7c}, + {0xb8,0x0a}, + {0x43,0x14}, + {0x44,0xf0}, + {0x45,0x34}, + {0x46,0x58}, + {0x47,0x28}, + {0x48,0x3a}, + {0x59,0x88}, + {0x5a,0x88}, + {0x5b,0x44}, + {0x5c,0x67}, + {0x5d,0x49}, + {0x5e,0x0e}, + {0x64,0x04}, + {0x65,0x20}, + {0x66,0x05}, + {0x94,0x04}, + {0x95,0x08}, + {0x6c,0x0a}, + {0x6d,0x55}, + {0x6e,0x11}, + {0x6f,0x9e}, + {0x6a,0x40}, + {0x13,0xc7}, + {0x4f,0x8b}, + {0x50,0x8b}, + {0x51,0x00}, + {0x52,0x22}, + {0x53,0x5e}, + {0x54,0x80}, + {0x58,0x9e}, + {0x41,0x08}, + {0x75,0x04}, + {0x76,0xe1}, + {0x4c,0x00}, + {0x77,0x01}, + {0x3d,0xc8}, // 0xc2. //modify by jianghuaming + {0x4b,0x09}, + {0xc9,0x60}, + {0x41,0x38}, + {0x56,0x40}, + {0x34,0x11}, + {0x3b,0xaa}, // 0x8a + {0xa4,0x88}, + {0x96,0x00}, + {0x97,0x30}, + {0x98,0x20}, + {0x99,0x30}, + {0x9a,0x84}, + {0x9b,0x29}, + {0x9c,0x03}, + {0x9d,0x4b}, + {0x9e,0x3f}, + {0x78,0x04}, + {0x79,0x01}, + {0xc8,0xf0}, + {0x79,0x0f}, + {0xc8,0x00}, + {0x79,0x10}, + {0xc8,0x7e}, + {0x79,0x0a}, + {0xc8,0x80}, + {0x79,0x0b}, + {0xc8,0x01}, + {0x79,0x0c}, + {0xc8,0x0f}, + {0x79,0x0d}, + {0xc8,0x20}, + {0x79,0x09}, + {0xc8,0x80}, + {0x79,0x02}, + {0xc8,0xc0}, + {0x79,0x03}, + {0xc8,0x40}, + {0x79,0x05}, + {0xc8,0x30}, + {0x79,0x26}, + {0x2d,0x00}, + {0x2e,0x00}, + {0x09,0x03}, // add by jianghuaming + {0x15,0x12}, // 0x02 //modify by jianghuaming + {0x13,0xe7}, +}; +#elif (USE_CAMERA == PAS6375_DEV) +const UINT8 pas6375_init_talbe[][2] = +{ + {0xEF,0x00}, + {0x04,0x00}, + {0x05,0x24}, + {0x06,0x00}, + {0x07,0x64}, + {0x08,0x5D}, + {0x09,0x00}, + {0x0A,0x3C}, + {0x0C,0x00}, + {0x0D,0x50}, + {0x0E,0x00}, + {0x0F,0x8C}, + {0x11,0x64}, + {0x12,0x30}, + {0x13,0xE9}, + {0x14,0x22}, + {0x15,0x23}, + {0x16,0x5F}, + {0x17,0x02}, + {0x18,0x0F}, + {0x19,0x40}, + {0x1A,0x71}, + {0x1B,0x40}, + {0x1C,0x64}, + {0x1D,0xF5}, + {0x1E,0x90}, + {0x1F,0x10}, + {0x20,0x10}, + {0x21,0x06}, + {0x22,0x78}, + {0x23,0x10}, + {0x24,0x06}, + {0x25,0x78}, + {0x26,0x0A}, + {0x27,0x0A}, + {0x28,0x3F}, + {0x29,0x01}, + {0x2A,0x06}, + {0x2B,0x0E}, + {0x2C,0x1E}, + {0x2D,0x3F}, + {0x2E,0x4F}, + {0x2F,0x5F}, + {0x30,0x6D}, + {0x31,0x7B}, + {0x32,0x94}, + {0x33,0xAA}, + {0x34,0xBC}, + {0x35,0xCB}, + {0x36,0xE1}, + {0x37,0xF0}, + {0x38,0xF9}, + {0x39,0xF1}, + {0x3A,0x32}, + {0x3B,0x07}, + {0x3C,0x19}, + {0x3D,0x08}, + {0x3E,0x01}, + {0x3F,0x0C}, + {0x40,0x1E}, + {0x41,0x44}, + {0x42,0x41}, + {0x43,0x01}, + {0x44,0x00}, + {0x45,0x02}, + {0x46,0x02}, + {0x47,0x31}, + {0x48,0x3C}, + {0x49,0x7F}, + {0x4A,0x80}, + {0x4B,0x42}, + {0x4C,0x08}, + {0x4D,0x64}, + {0x4E,0x87}, + {0x4F,0x79}, + {0x50,0x75}, + {0x51,0x96}, + {0x52,0x8C}, + {0x53,0x14}, + {0x54,0xF5}, + {0x55,0x43}, + {0x56,0x18}, + {0x57,0x01}, + {0x58,0x03}, + {0x59,0x03}, + {0x5A,0x08}, + {0x5B,0x03}, + {0x5C,0x0F}, + {0x5D,0xFF}, + {0x5E,0x1C}, + {0x5F,0x05}, + {0x60,0x01}, + {0x61,0x16}, + {0x62,0x0A}, + {0x63,0x30}, + {0x64,0x08}, + {0x65,0x30}, + {0x66,0x13}, + {0x67,0xC7}, + {0x68,0x2D}, + {0x6B,0x06}, + {0x6C,0x0F}, + {0x6D,0x3F}, + {0x6E,0x03}, + {0x6F,0x56}, + {0x70,0x00}, + {0x71,0x00}, + {0x72,0x03}, + {0x73,0xC2}, + {0x74,0xA4}, + {0x75,0x83}, + {0x76,0x60}, + {0x77,0x88}, + {0x78,0x01}, + {0x79,0x19}, + {0x7B,0x07}, + {0x7C,0x03}, + {0x7D,0x08}, + {0x7E,0x00}, + {0x7F,0xFF}, + {0x80,0x87}, + {0x81,0x12}, + {0x82,0x00}, + {0x84,0x16}, + {0x85,0x00}, + {0x86,0x08}, + {0x87,0xEA}, + {0x88,0x01}, + {0x89,0x00}, + {0x8A,0x02}, + {0x8B,0x00}, + {0x8C,0xB2}, + {0x8E,0x00}, + {0x8F,0x00}, + {0x90,0x00}, + {0x91,0x00}, + {0x93,0x00}, + {0x94,0x00}, + {0x95,0x05}, + {0x97,0x10}, + {0x98,0x00}, + {0x99,0x50}, + {0x9A,0x3C}, + {0x9B,0x64}, + {0x9C,0x3C}, + {0x9D,0x64}, + {0x9E,0x3C}, + {0x9F,0x00}, + {0xA0,0x00}, + {0xA1,0x00}, + {0xA2,0x34}, + {0xA3,0x34}, + {0xA4,0x34}, + {0xA5,0x07}, + {0xA6,0x01}, + {0xA7,0x03}, + {0xA8,0x03}, + {0xDF,0x20}, + {0xE0,0x80}, + {0xE1,0x02}, + {0xE2,0xE0}, + {0xE3,0x01}, + {0xE6,0x00}, + {0xE9,0x07}, + {0xEA,0x00}, + {0xEB,0x00}, + {0xED,0x00}, + {0xEE,0x3F}, + {0xED,0x01}, + {0xEF,0x01}, + {0x02,0x02}, + {0x03,0xAC}, + {0x04,0xF4}, + {0x05,0x01}, + {0x06,0x00}, + {0x07,0x00}, + {0x08,0x00}, + {0x0B,0x14}, + {0x0C,0x00}, + {0x0D,0x4A}, + {0x0E,0x02}, + {0x0F,0x00}, + {0x10,0x0F}, + {0x11,0x00}, + {0x17,0x00}, + {0x18,0x00}, + {0x19,0x00}, + {0x1A,0x00}, + {0x1B,0x87}, + {0x1C,0x02}, + {0x1D,0xE9}, + {0x1E,0x01}, + {0x1F,0x01}, + {0x20,0x14}, + {0x21,0x00}, + {0x22,0x08}, + {0x23,0x01}, + {0x24,0x0F}, + {0x25,0x20}, + {0x26,0x20}, + {0x27,0x0E}, + {0x28,0x20}, + {0x29,0x04}, + {0x2A,0x00}, + {0x2B,0x00}, + {0x2C,0x00}, + {0x2D,0x01}, + {0x2E,0xFF}, + {0x2F,0x65}, + {0x30,0x6C}, + {0x31,0x00}, + {0x32,0x00}, + {0x33,0x04}, + {0x34,0xA8}, + {0x35,0x00}, + {0x36,0x00}, + {0x37,0x00}, + {0x38,0x00}, + {0x39,0x20}, + {0x3A,0x10}, + {0x3B,0x00}, + {0x3C,0x00}, + {0x3D,0x00}, + {0x3E,0x00}, + {0x40,0x24}, + {0x41,0x06}, + {0x42,0x03}, + {0x43,0x92}, + {0x44,0x1E}, + {0x45,0x23}, + {0x48,0x64}, + {0x49,0x40}, + {0x4A,0x00}, + {0x4B,0x08}, + {0x4C,0x04}, + {0x4D,0x38}, + {0x4E,0x05}, + {0x50,0x0D}, + {0x51,0x00}, + {0x52,0x40}, + {0x53,0x00}, + {0x54,0x33}, + {0x55,0x44}, + {0x56,0x00}, + {0x57,0x00}, + {0x58,0x18}, + {0x59,0x00}, + {0x5C,0x00}, + {0x5D,0x00}, + {0x5E,0x44}, + {0x5F,0x40}, + {0x60,0x10}, + {0x61,0x04}, + {0x62,0x01}, + {0x63,0x78}, + {0x64,0x10}, + {0x66,0x08}, + {0x67,0x40}, + {0x68,0xC7}, + {0x69,0x4B}, + {0x6A,0x01}, + {0x6B,0x2A}, + {0x6C,0x00}, + {0x6D,0x70}, + {0x6E,0x07}, + {0x6F,0x00}, + {0x70,0xBA}, + {0x71,0x65}, + {0x72,0x6E}, + {0x73,0x00}, + {0x74,0x00}, + {0x75,0x00}, + {0x76,0x00}, + {0x77,0x30}, + {0x78,0x01}, + {0x79,0x05}, + {0x7A,0x0F}, + {0x7B,0x12}, + {0x7D,0x04}, + {0x7F,0x04}, + {0x80,0x00}, + {0x81,0x47}, + {0x82,0x10}, + {0x84,0x00}, + {0x85,0x00}, + {0x86,0x0A}, + {0x8B,0x00}, + {0x8C,0x00}, + {0x8F,0x00}, + {0x90,0x00}, + {0x91,0x01}, + {0x92,0x00}, + {0x93,0x14}, + {0x94,0x00}, + {0x99,0x40}, + {0x9A,0x00}, + {0x9B,0x00}, + {0x9C,0x02}, + {0x9D,0x43}, + {0x9E,0x02}, + {0x9F,0x10}, + {0xA0,0x89}, + {0xA1,0x00}, + {0xA2,0x05}, + {0xA3,0x00}, + {0xA4,0x00}, + {0xA5,0x00}, + {0xA6,0x00}, + {0xA7,0x06}, + {0xA8,0x0F}, + {0xA9,0x00}, + {0xAA,0xAA}, + {0xAB,0x55}, + {0xAC,0x97}, + {0xAD,0x71}, + {0xAE,0x71}, + {0xAF,0x00}, + {0xB0,0x05}, + {0xB1,0x3F}, + {0xB2,0xCA}, + {0xB3,0x01}, + {0xB4,0x00}, + {0xB5,0x29}, + {0xB6,0x02}, + {0xB7,0x00}, + {0xB8,0xF8}, + {0xB9,0x00}, + {0xBA,0x64}, + {0xBB,0x00}, + {0xBC,0x19}, + {0xBF,0x30}, + {0xC0,0x03}, + {0xC1,0x18}, + {0xC2,0x36}, + {0xC3,0x00}, + {0xC4,0x00}, + {0xC5,0x00}, + {0xC6,0x00}, + {0xC7,0x08}, + {0xC8,0x00}, + {0xC9,0x65}, + {0xCA,0xA6}, + {0xCD,0x00}, + {0xD3,0x80}, + {0xD4,0x00}, + {0xD5,0x00}, + {0xD6,0x03}, + {0xD7,0x77}, + {0xD8,0x00}, + {0xDB,0x00}, + {0xDE,0x0A}, + {0xDF,0x00}, + {0xE0,0x00}, + {0xE1,0x00}, + {0xE2,0x17}, + {0xE4,0x00}, + {0xE5,0x00}, + {0xE6,0x00}, + {0xE7,0x01}, + {0xE9,0x52}, + {0xEA,0x90}, + {0xEB,0x02}, + {0xEC,0x22}, + {0xED,0x0D}, + {0xEE,0x04}, + {0xF2,0x00}, + {0xF3,0x50}, + {0xF6,0x05}, + {0xF7,0x10}, + {0xF8,0x03}, + {0xF9,0x10}, + {0x11,0x01}, + {0xEF,0x02}, + {0x00,0x00}, + {0x01,0x31}, + {0x02,0xC7}, + {0x03,0x00}, + {0x04,0x3C}, + {0x05,0xA8}, + {0x06,0x20}, + {0x08,0x00}, + {0x09,0x00}, + {0x0A,0x00}, + {0x0B,0x00}, + {0x0C,0x0A}, + {0x0E,0x00}, + {0x0F,0x96}, + {0x10,0x32}, + {0x11,0x0E}, + {0x12,0xB0}, + {0x13,0x28}, + {0x14,0xFF}, + {0x15,0x1E}, + {0x1A,0xB1}, + {0x1B,0x86}, + {0x1C,0x69}, + {0x1D,0x7D}, + {0x1E,0x87}, + {0x1F,0x9B}, + {0x20,0xB4}, + {0x21,0x02}, + {0x22,0x08}, + {0x23,0x18}, + {0x2A,0x84}, + {0x2B,0x00}, + {0x2C,0x18}, + {0x2D,0x10}, + {0x2E,0x1E}, + {0x2F,0x0E}, + {0x30,0x0E}, + {0x31,0x01}, + {0x32,0x3F}, + {0x33,0x18}, + {0x34,0x01}, + {0x35,0x08}, + {0x36,0x04}, + {0x37,0x08}, + {0x38,0x0E}, + {0x39,0x20}, + {0x3A,0x8B}, + {0x3C,0x04}, + {0x49,0x0B}, + {0x4A,0x00}, + {0x4B,0x00}, + {0x4C,0x01}, + {0x4D,0x14}, + {0x4E,0x02}, + {0x4F,0x3C}, + {0x50,0x22}, + {0x51,0x01}, + {0x52,0x18}, + {0x53,0x01}, + {0x54,0x01}, + {0x55,0x00}, + {0x56,0x03}, + {0x57,0x02}, + {0x58,0x08}, + {0x59,0x00}, + {0x5A,0x08}, + {0x5B,0x08}, + {0x5C,0x05}, + {0x5D,0x02}, + {0x5E,0x06}, + {0x5F,0x0F}, + {0x60,0x14}, + {0x61,0x00}, + {0x62,0x04}, + {0x63,0x4F}, + {0x64,0x03}, + {0x65,0x44}, + {0x66,0x80}, + {0x68,0x00}, + {0x69,0x0F}, + {0x6A,0x00}, + {0x6B,0x00}, + {0x6C,0x00}, + {0x6D,0x00}, + {0x6E,0x00}, + {0x6F,0x00}, + {0x70,0x00}, + {0x71,0x84}, + {0x72,0x80}, + {0x73,0x01}, + {0x74,0xD4}, + {0x75,0xC4}, + {0x8D,0x12}, + {0x8E,0x10}, + {0x8F,0x10}, + {0x90,0x0F}, + {0x93,0x00}, + {0x94,0x0C}, + {0x95,0x04}, + {0x96,0x00}, + {0x97,0x08}, + {0x98,0x04}, + {0x9B,0x02}, + {0x9C,0x80}, + {0x9D,0x01}, + {0x9E,0xE0}, + {0x9F,0x00}, + {0xA0,0x00}, + {0xA1,0x00}, + {0xA2,0x00}, + {0xA4,0x02}, + {0xA5,0x0A}, + {0xA6,0x0C}, + {0xAD,0x00}, + {0xAE,0x00}, + {0xB2,0x00}, + {0xBC,0x10}, + {0xBD,0x01}, + {0xBE,0x00}, + {0xBF,0x00}, + {0xC0,0x00}, + {0xC1,0x13}, + {0xC2,0x10}, + {0xD7,0x02}, + {0xD8,0x04}, + {0xD9,0xC8}, + {0xDA,0x50}, + {0xDB,0x0E}, + {0xDC,0x08}, + {0xDD,0x14}, + {0xDE,0x32}, + {0xDF,0x00}, + {0xE0,0x04}, + {0xE1,0x00}, + {0xE3,0x00}, + {0xE4,0x00}, + {0xE5,0x00}, + {0xE6,0x00}, + {0xEB,0x00}, + {0x00,0x01}, + {0xEF,0x03}, + {0x01,0x01}, + {0x02,0x00}, + {0x03,0x33}, + {0x04,0x1A}, + {0x05,0x58}, + {0x06,0x0E}, + {0x07,0x0F}, + {0x08,0x39}, + {0x09,0x48}, + {0x0A,0x3D}, + {0x0B,0x3A}, + {0x0C,0x03}, + {0x0D,0x01}, + {0x0E,0x13}, + {0x0F,0x0D}, + {0x10,0x01}, + {0x11,0x0F}, + {0x12,0x02}, + {0x13,0x1A}, + {0x14,0x19}, + {0x15,0x0D}, + {0x16,0x0E}, + {0x17,0x01}, + {0x18,0x85}, + {0x19,0x54}, + {0x1A,0x10}, + {0x1B,0x40}, + {0x1C,0x40}, + {0x1D,0x21}, + {0x1E,0x40}, + {0x1F,0x54}, + {0x30,0xA0}, + {0x31,0x01}, + {0x32,0x50}, + {0x33,0x00}, + {0x34,0x60}, + {0x35,0x00}, + {0x36,0x00}, + {0x37,0xFF}, + {0x38,0x5A}, + {0x39,0x3C}, + {0x3A,0x28}, + {0x3B,0x14}, + {0x3C,0x02}, + {0x3D,0x34}, + {0x3E,0x05}, + {0x50,0xD0}, + {0x51,0x50}, + {0x52,0x40}, + {0x53,0x18}, + {0x54,0xA4}, + {0x55,0x01}, + {0x56,0x14}, + {0x57,0x60}, + {0x58,0x02}, + {0x59,0x32}, + {0x5A,0x33}, + {0x5B,0x24}, + {0x5C,0x7F}, + {0x5D,0x0F}, + {0x5E,0x0F}, + {0x5F,0x0F}, + {0x60,0x0F}, + {0x61,0x1C}, + {0x62,0x07}, + {0x63,0x00}, + {0x64,0x15}, + {0x65,0x01}, + {0x66,0x40}, + {0x68,0x00}, + {0x69,0xFF}, + {0x6A,0x00}, + {0x6B,0xFF}, + {0x78,0x01}, + {0x79,0x54}, + {0x7A,0x40}, + {0x7B,0x0F}, + {0x80,0x00}, + {0x81,0x01}, + {0x82,0x0F}, + {0x83,0x18}, + {0x84,0x02}, + {0x85,0x0C}, + {0x86,0x28}, + {0x87,0x02}, + {0x8A,0x03}, + {0x8B,0x96}, + {0x8C,0x40}, + {0x8D,0x04}, + {0x8E,0x00}, + {0x8F,0x10}, + {0x90,0x00}, + {0x9A,0x26}, + {0x9B,0x00}, + {0xF1,0x00}, + {0xF2,0x00}, + {0xF3,0x00}, + {0xF4,0x00}, + {0xF5,0x00}, + {0xF8,0x48}, + {0xF9,0x00}, + {0xFA,0x02}, + {0xFB,0x00}, + {0xFC,0x10}, + {0x00,0x01}, +}; + +#elif (USE_CAMERA == GC0328C_DEV) +const UINT8 gc0328c_init_talbe[][2] = { + {0xFE,0x80}, + {0xFE,0x80}, + {0xFC,0x16}, + {0xFC,0x16}, + {0xFC,0x16}, + {0xFC,0x16}, + {0xF1,0x00}, + {0xF2,0x00}, + {0xFE,0x00}, + {0x4F,0x00}, + {0x03,0x00}, + {0x04,0xC0}, + {0x42,0x00}, + {0x77,0x5A}, + {0x78,0x40}, + {0x79,0x56}, + {0xFE,0x00}, + {0x0D,0x01}, + {0x0E,0xE8}, + {0x0F,0x02}, + {0x10,0x88}, + {0x09,0x00}, + {0x0A,0x00}, + {0x0B,0x00}, + {0x0C,0x00}, + {0x16,0x00}, + {0x17,0x14}, + {0x18,0x0E}, + {0x19,0x06}, + {0x1B,0x48}, + {0x1F,0xC8}, + {0x20,0x01}, + {0x21,0x78}, + {0x22,0xB0}, + {0x23,0x04}, + {0x24,0x16}, + {0x26,0x00}, + {0x50,0x01}, + {0x70,0x45}, + {0x05,0x00}, + {0x06,0xDE}, + {0x07,0x00}, + {0x08,0xA7}, + {0xFE,0x01}, + {0x29,0x00}, + {0x2A,0x83}, + {0x2B,0x02}, + {0x2C,0x8F}, + {0x2D,0x02}, + {0x2E,0x8F}, + {0x2F,0x02}, + {0x30,0x8F}, + {0x31,0x02}, + {0x32,0x8F}, + {0xFE,0x00}, + {0xFE,0x01}, + {0x50,0x00}, + {0x4F,0x00}, + {0x4C,0x01}, + {0x4F,0x00}, + {0x4F,0x00}, + {0x4F,0x00}, + {0x4F,0x00}, + {0x4F,0x00}, + {0x4D,0x30}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4D,0x40}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4D,0x50}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4D,0x60}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4D,0x70}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4F,0x01}, + {0x50,0x88}, + {0xFE,0x00}, + {0xFE,0x00}, + {0x27,0xB7}, + {0x28,0x7F}, + {0x29,0x20}, + {0x33,0x20}, + {0x34,0x20}, + {0x35,0x20}, + {0x36,0x20}, + {0x32,0x08}, + {0x3B,0x00}, + {0x3C,0x00}, + {0x3D,0x00}, + {0x3E,0x00}, + {0x47,0x00}, + {0x48,0x00}, + {0x40,0x7F}, + {0x41,0x26}, + {0x42,0xFB}, + {0x44,0x02}, + {0x45,0x00}, + {0x46,0x03}, + {0x4F,0x01}, + {0x4B,0x01}, + {0x50,0x01}, + {0x7E,0x0A}, + {0x7F,0x03}, + {0x81,0x15}, + {0x82,0x90}, + {0x83,0x02}, + {0x84,0xE5}, + {0x90,0x2C}, + {0x92,0x02}, + {0x94,0x02}, + {0x95,0x35}, + {0xD1,0x24}, + {0xD2,0x24}, + {0xD3,0x40}, + {0xDD,0xD3}, + {0xDE,0x38}, + {0xE4,0x88}, + {0xE5,0x40}, + {0xD7,0x0E}, + {0xFE,0x00}, + {0xBF,0x0E}, + {0xC0,0x1C}, + {0xC1,0x34}, + {0xC2,0x48}, + {0xC3,0x5A}, + {0xC4,0x6E}, + {0xC5,0x80}, + {0xC6,0x9C}, + {0xC7,0xB4}, + {0xC8,0xC7}, + {0xC9,0xD7}, + {0xCA,0xE3}, + {0xCB,0xED}, + {0xCC,0xF2}, + {0xCD,0xF8}, + {0xCE,0xFD}, + {0xCF,0xFF}, + {0xFE,0x00}, + {0x63,0x00}, + {0x64,0x05}, + {0x65,0x0B}, + {0x66,0x19}, + {0x67,0x2E}, + {0x68,0x40}, + {0x69,0x54}, + {0x6A,0x66}, + {0x6B,0x86}, + {0x6C,0xA7}, + {0x6D,0xC6}, + {0x6E,0xE4}, + {0x6F,0xFF}, + {0xFE,0x01}, + {0x18,0x02}, + {0xFE,0x00}, + {0x97,0x30}, + {0x98,0x00}, + {0x9B,0x60}, + {0x9C,0x60}, + {0xA4,0x50}, + {0xA8,0x80}, + {0xAA,0x40}, + {0xA2,0x23}, + {0xAD,0x28}, + {0xFE,0x01}, + {0x9C,0x00}, + {0x9E,0xC0}, + {0x9F,0x40}, + {0xFE,0x01}, + {0x08,0xA0}, + {0x09,0xE8}, + {0x10,0x08}, + {0x11,0x21}, + {0x12,0x11}, + {0x13,0x45}, + {0x15,0xFC}, + {0x18,0x02}, + {0x21,0xF0}, + {0x22,0x60}, + {0x23,0x30}, + {0x25,0x00}, + {0x24,0x14}, + {0x3D,0x80}, + {0x3E,0x40}, + {0xFE,0x01}, + {0x51,0x88}, + {0x52,0x12}, + {0x53,0x80}, + {0x54,0x60}, + {0x55,0x01}, + {0x56,0x02}, + {0x58,0x00}, + {0x5B,0x02}, + {0x5E,0xA4}, + {0x5F,0x8A}, + {0x61,0xDC}, + {0x62,0xDC}, + {0x70,0xFC}, + {0x71,0x10}, + {0x72,0x10}, + {0x73,0x20}, + {0x74,0x20}, + {0x75,0x01}, + {0x76,0x00}, + {0x77,0x40}, + {0x78,0x70}, + {0x79,0x00}, + {0x7B,0x00}, + {0x7C,0x71}, + {0x7D,0x00}, + {0x80,0x70}, + {0x81,0x58}, + {0x82,0x98}, + {0x83,0x60}, + {0x84,0x58}, + {0x85,0x50}, + {0xFE,0x00}, + {0xFE,0x01}, + {0xC0,0x10}, + {0xC1,0x0C}, + {0xC2,0x0A}, + {0xC6,0x0E}, + {0xC7,0x0B}, + {0xC8,0x0A}, + {0xBA,0x26}, + {0xBB,0x1C}, + {0xBC,0x1D}, + {0xB4,0x23}, + {0xB5,0x1C}, + {0xB6,0x1A}, + {0xC3,0x00}, + {0xC4,0x00}, + {0xC5,0x00}, + {0xC9,0x00}, + {0xCA,0x00}, + {0xCB,0x00}, + {0xBD,0x00}, + {0xBE,0x00}, + {0xBF,0x00}, + {0xB7,0x07}, + {0xB8,0x05}, + {0xB9,0x05}, + {0xA8,0x07}, + {0xA9,0x06}, + {0xAA,0x00}, + {0xAB,0x04}, + {0xAC,0x00}, + {0xAD,0x02}, + {0xAE,0x0D}, + {0xAF,0x05}, + {0xB0,0x00}, + {0xB1,0x07}, + {0xB2,0x03}, + {0xB3,0x00}, + {0xA4,0x00}, + {0xA5,0x00}, + {0xA6,0x00}, + {0xA7,0x00}, + {0xA1,0x3C}, + {0xA2,0x50}, + {0xFE,0x00}, + {0xB1,0x12}, + {0xB2,0xF5}, + {0xB3,0xFE}, + {0xB4,0xE0}, + {0xB5,0x15}, + {0xB6,0xC8}, + {0xFE,0x01}, + {0x50,0x00}, + {0xFE,0x01}, + {0x4F,0x00}, + {0x4C,0x01}, + {0x4F,0x00}, + {0x4F,0x00}, + {0x4F,0x00}, + {0x4D,0x34}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x02}, + {0x4E,0x02}, + {0x4D,0x44}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4D,0x53}, + {0x4E,0x08}, + {0x4E,0x08}, + {0x4E,0x04}, + {0x4E,0x04}, + {0x4D,0x65}, + {0x4E,0x04}, + {0x4D,0x73}, + {0x4E,0x20}, + {0x4D,0x83}, + {0x4E,0x20}, + {0x4F,0x01}, + {0x50,0x88}, + {0xFE,0x00}, + {0xF1,0x07}, + {0xF2,0x01}, +}; +#endif // USE_CAMERA + +#endif diff --git a/beken_os/beken378/func/camera_intf/camera_intf_pub.h b/beken_os/beken378/func/camera_intf/camera_intf_pub.h new file mode 100755 index 0000000..482c76e --- /dev/null +++ b/beken_os/beken378/func/camera_intf/camera_intf_pub.h @@ -0,0 +1,7 @@ +#ifndef __CAMERA_INTF_PUB_H__ +#define __CAMERA_INTF_PUB_H__ + +void camera_intfer_init(void* data); +void camera_intfer_deinit(void); + +#endif // __CAMERA_INTF_PUB_H__ diff --git a/beken_os/beken378/func/ethernet_intf/ethernet_intf.h b/beken_os/beken378/func/ethernet_intf/ethernet_intf.h new file mode 100755 index 0000000..b1f38ab --- /dev/null +++ b/beken_os/beken378/func/ethernet_intf/ethernet_intf.h @@ -0,0 +1,12 @@ +#ifndef __ETHERNET_INTF_H__ +#define __ETHERNET_INTF_H__ + +#include "mac.h" + +extern char wireless_ip[4]; +extern char wireless_mask[4]; +extern char wireless_gw[4]; + +extern int hwaddr_aton(const char *txt, u8 *addr); + +#endif diff --git a/beken_os/beken378/func/fatfs/app_fs.h b/beken_os/beken378/func/fatfs/app_fs.h new file mode 100755 index 0000000..ed2ca7a --- /dev/null +++ b/beken_os/beken378/func/fatfs/app_fs.h @@ -0,0 +1,3 @@ +#include "ff.h" +uint16 get_musicfile_count(void); +FILE_INFO *get_file_info(void); \ No newline at end of file diff --git a/beken_os/beken378/func/fatfs/cc936.c b/beken_os/beken378/func/fatfs/cc936.c new file mode 100755 index 0000000..485f234 --- /dev/null +++ b/beken_os/beken378/func/fatfs/cc936.c @@ -0,0 +1,11079 @@ +/*------------------------------------------------------------------------*/ +/* Unicode - OEM code bidirectional converter (C)ChaN, 2015 */ +/* CP936 (Simplified Chinese GBK) */ +/*------------------------------------------------------------------------*/ + +#include "cc936.h" + + +#if !_USE_LFN || _CODE_PAGE != 936 +//#error This file is not needed in current configuration. Remove from the project.// old one +#endif +#if _CODE_PAGE == 936 +static +const WCHAR uni2oem[] = +{ + /* Unicode - OEM, Unicode - OEM, Unicode - OEM, Unicode - OEM */ + 0x00A4, 0xA1E8, 0x00A7, 0xA1EC, 0x00A8, 0xA1A7, 0x00B0, 0xA1E3, + 0x00B1, 0xA1C0, 0x00B7, 0xA1A4, 0x00D7, 0xA1C1, 0x00E0, 0xA8A4, + 0x00E1, 0xA8A2, 0x00E8, 0xA8A8, 0x00E9, 0xA8A6, 0x00EA, 0xA8BA, + 0x00EC, 0xA8AC, 0x00ED, 0xA8AA, 0x00F2, 0xA8B0, 0x00F3, 0xA8AE, + 0x00F7, 0xA1C2, 0x00F9, 0xA8B4, 0x00FA, 0xA8B2, 0x00FC, 0xA8B9, + 0x0101, 0xA8A1, 0x0113, 0xA8A5, 0x011B, 0xA8A7, 0x012B, 0xA8A9, + 0x0144, 0xA8BD, 0x0148, 0xA8BE, 0x014D, 0xA8AD, 0x016B, 0xA8B1, + 0x01CE, 0xA8A3, 0x01D0, 0xA8AB, 0x01D2, 0xA8AF, 0x01D4, 0xA8B3, + 0x01D6, 0xA8B5, 0x01D8, 0xA8B6, 0x01DA, 0xA8B7, 0x01DC, 0xA8B8, + 0x0251, 0xA8BB, 0x0261, 0xA8C0, 0x02C7, 0xA1A6, 0x02C9, 0xA1A5, + 0x02CA, 0xA840, 0x02CB, 0xA841, 0x02D9, 0xA842, 0x0391, 0xA6A1, + 0x0392, 0xA6A2, 0x0393, 0xA6A3, 0x0394, 0xA6A4, 0x0395, 0xA6A5, + 0x0396, 0xA6A6, 0x0397, 0xA6A7, 0x0398, 0xA6A8, 0x0399, 0xA6A9, + 0x039A, 0xA6AA, 0x039B, 0xA6AB, 0x039C, 0xA6AC, 0x039D, 0xA6AD, + 0x039E, 0xA6AE, 0x039F, 0xA6AF, 0x03A0, 0xA6B0, 0x03A1, 0xA6B1, + 0x03A3, 0xA6B2, 0x03A4, 0xA6B3, 0x03A5, 0xA6B4, 0x03A6, 0xA6B5, + 0x03A7, 0xA6B6, 0x03A8, 0xA6B7, 0x03A9, 0xA6B8, 0x03B1, 0xA6C1, + 0x03B2, 0xA6C2, 0x03B3, 0xA6C3, 0x03B4, 0xA6C4, 0x03B5, 0xA6C5, + 0x03B6, 0xA6C6, 0x03B7, 0xA6C7, 0x03B8, 0xA6C8, 0x03B9, 0xA6C9, + 0x03BA, 0xA6CA, 0x03BB, 0xA6CB, 0x03BC, 0xA6CC, 0x03BD, 0xA6CD, + 0x03BE, 0xA6CE, 0x03BF, 0xA6CF, 0x03C0, 0xA6D0, 0x03C1, 0xA6D1, + 0x03C3, 0xA6D2, 0x03C4, 0xA6D3, 0x03C5, 0xA6D4, 0x03C6, 0xA6D5, + 0x03C7, 0xA6D6, 0x03C8, 0xA6D7, 0x03C9, 0xA6D8, 0x0401, 0xA7A7, + 0x0410, 0xA7A1, 0x0411, 0xA7A2, 0x0412, 0xA7A3, 0x0413, 0xA7A4, + 0x0414, 0xA7A5, 0x0415, 0xA7A6, 0x0416, 0xA7A8, 0x0417, 0xA7A9, + 0x0418, 0xA7AA, 0x0419, 0xA7AB, 0x041A, 0xA7AC, 0x041B, 0xA7AD, + 0x041C, 0xA7AE, 0x041D, 0xA7AF, 0x041E, 0xA7B0, 0x041F, 0xA7B1, + 0x0420, 0xA7B2, 0x0421, 0xA7B3, 0x0422, 0xA7B4, 0x0423, 0xA7B5, + 0x0424, 0xA7B6, 0x0425, 0xA7B7, 0x0426, 0xA7B8, 0x0427, 0xA7B9, + 0x0428, 0xA7BA, 0x0429, 0xA7BB, 0x042A, 0xA7BC, 0x042B, 0xA7BD, + 0x042C, 0xA7BE, 0x042D, 0xA7BF, 0x042E, 0xA7C0, 0x042F, 0xA7C1, + 0x0430, 0xA7D1, 0x0431, 0xA7D2, 0x0432, 0xA7D3, 0x0433, 0xA7D4, + 0x0434, 0xA7D5, 0x0435, 0xA7D6, 0x0436, 0xA7D8, 0x0437, 0xA7D9, + 0x0438, 0xA7DA, 0x0439, 0xA7DB, 0x043A, 0xA7DC, 0x043B, 0xA7DD, + 0x043C, 0xA7DE, 0x043D, 0xA7DF, 0x043E, 0xA7E0, 0x043F, 0xA7E1, + 0x0440, 0xA7E2, 0x0441, 0xA7E3, 0x0442, 0xA7E4, 0x0443, 0xA7E5, + 0x0444, 0xA7E6, 0x0445, 0xA7E7, 0x0446, 0xA7E8, 0x0447, 0xA7E9, + 0x0448, 0xA7EA, 0x0449, 0xA7EB, 0x044A, 0xA7EC, 0x044B, 0xA7ED, + 0x044C, 0xA7EE, 0x044D, 0xA7EF, 0x044E, 0xA7F0, 0x044F, 0xA7F1, + 0x0451, 0xA7D7, 0x2010, 0xA95C, 0x2013, 0xA843, 0x2014, 0xA1AA, + 0x2015, 0xA844, 0x2016, 0xA1AC, 0x2018, 0xA1AE, 0x2019, 0xA1AF, + 0x201C, 0xA1B0, 0x201D, 0xA1B1, 0x2025, 0xA845, 0x2026, 0xA1AD, + 0x2030, 0xA1EB, 0x2032, 0xA1E4, 0x2033, 0xA1E5, 0x2035, 0xA846, + 0x203B, 0xA1F9, 0x20AC, 0x0080, 0x2103, 0xA1E6, 0x2105, 0xA847, + 0x2109, 0xA848, 0x2116, 0xA1ED, 0x2121, 0xA959, 0x2160, 0xA2F1, + 0x2161, 0xA2F2, 0x2162, 0xA2F3, 0x2163, 0xA2F4, 0x2164, 0xA2F5, + 0x2165, 0xA2F6, 0x2166, 0xA2F7, 0x2167, 0xA2F8, 0x2168, 0xA2F9, + 0x2169, 0xA2FA, 0x216A, 0xA2FB, 0x216B, 0xA2FC, 0x2170, 0xA2A1, + 0x2171, 0xA2A2, 0x2172, 0xA2A3, 0x2173, 0xA2A4, 0x2174, 0xA2A5, + 0x2175, 0xA2A6, 0x2176, 0xA2A7, 0x2177, 0xA2A8, 0x2178, 0xA2A9, + 0x2179, 0xA2AA, 0x2190, 0xA1FB, 0x2191, 0xA1FC, 0x2192, 0xA1FA, + 0x2193, 0xA1FD, 0x2196, 0xA849, 0x2197, 0xA84A, 0x2198, 0xA84B, + 0x2199, 0xA84C, 0x2208, 0xA1CA, 0x220F, 0xA1C7, 0x2211, 0xA1C6, + 0x2215, 0xA84D, 0x221A, 0xA1CC, 0x221D, 0xA1D8, 0x221E, 0xA1DE, + 0x221F, 0xA84E, 0x2220, 0xA1CF, 0x2223, 0xA84F, 0x2225, 0xA1CE, + 0x2227, 0xA1C4, 0x2228, 0xA1C5, 0x2229, 0xA1C9, 0x222A, 0xA1C8, + 0x222B, 0xA1D2, 0x222E, 0xA1D3, 0x2234, 0xA1E0, 0x2235, 0xA1DF, + 0x2236, 0xA1C3, 0x2237, 0xA1CB, 0x223D, 0xA1D7, 0x2248, 0xA1D6, + 0x224C, 0xA1D5, 0x2252, 0xA850, 0x2260, 0xA1D9, 0x2261, 0xA1D4, + 0x2264, 0xA1DC, 0x2265, 0xA1DD, 0x2266, 0xA851, 0x2267, 0xA852, + 0x226E, 0xA1DA, 0x226F, 0xA1DB, 0x2295, 0xA892, 0x2299, 0xA1D1, + 0x22A5, 0xA1CD, 0x22BF, 0xA853, 0x2312, 0xA1D0, 0x2460, 0xA2D9, + 0x2461, 0xA2DA, 0x2462, 0xA2DB, 0x2463, 0xA2DC, 0x2464, 0xA2DD, + 0x2465, 0xA2DE, 0x2466, 0xA2DF, 0x2467, 0xA2E0, 0x2468, 0xA2E1, + 0x2469, 0xA2E2, 0x2474, 0xA2C5, 0x2475, 0xA2C6, 0x2476, 0xA2C7, + 0x2477, 0xA2C8, 0x2478, 0xA2C9, 0x2479, 0xA2CA, 0x247A, 0xA2CB, + 0x247B, 0xA2CC, 0x247C, 0xA2CD, 0x247D, 0xA2CE, 0x247E, 0xA2CF, + 0x247F, 0xA2D0, 0x2480, 0xA2D1, 0x2481, 0xA2D2, 0x2482, 0xA2D3, + 0x2483, 0xA2D4, 0x2484, 0xA2D5, 0x2485, 0xA2D6, 0x2486, 0xA2D7, + 0x2487, 0xA2D8, 0x2488, 0xA2B1, 0x2489, 0xA2B2, 0x248A, 0xA2B3, + 0x248B, 0xA2B4, 0x248C, 0xA2B5, 0x248D, 0xA2B6, 0x248E, 0xA2B7, + 0x248F, 0xA2B8, 0x2490, 0xA2B9, 0x2491, 0xA2BA, 0x2492, 0xA2BB, + 0x2493, 0xA2BC, 0x2494, 0xA2BD, 0x2495, 0xA2BE, 0x2496, 0xA2BF, + 0x2497, 0xA2C0, 0x2498, 0xA2C1, 0x2499, 0xA2C2, 0x249A, 0xA2C3, + 0x249B, 0xA2C4, 0x2500, 0xA9A4, 0x2501, 0xA9A5, 0x2502, 0xA9A6, + 0x2503, 0xA9A7, 0x2504, 0xA9A8, 0x2505, 0xA9A9, 0x2506, 0xA9AA, + 0x2507, 0xA9AB, 0x2508, 0xA9AC, 0x2509, 0xA9AD, 0x250A, 0xA9AE, + 0x250B, 0xA9AF, 0x250C, 0xA9B0, 0x250D, 0xA9B1, 0x250E, 0xA9B2, + 0x250F, 0xA9B3, 0x2510, 0xA9B4, 0x2511, 0xA9B5, 0x2512, 0xA9B6, + 0x2513, 0xA9B7, 0x2514, 0xA9B8, 0x2515, 0xA9B9, 0x2516, 0xA9BA, + 0x2517, 0xA9BB, 0x2518, 0xA9BC, 0x2519, 0xA9BD, 0x251A, 0xA9BE, + 0x251B, 0xA9BF, 0x251C, 0xA9C0, 0x251D, 0xA9C1, 0x251E, 0xA9C2, + 0x251F, 0xA9C3, 0x2520, 0xA9C4, 0x2521, 0xA9C5, 0x2522, 0xA9C6, + 0x2523, 0xA9C7, 0x2524, 0xA9C8, 0x2525, 0xA9C9, 0x2526, 0xA9CA, + 0x2527, 0xA9CB, 0x2528, 0xA9CC, 0x2529, 0xA9CD, 0x252A, 0xA9CE, + 0x252B, 0xA9CF, 0x252C, 0xA9D0, 0x252D, 0xA9D1, 0x252E, 0xA9D2, + 0x252F, 0xA9D3, 0x2530, 0xA9D4, 0x2531, 0xA9D5, 0x2532, 0xA9D6, + 0x2533, 0xA9D7, 0x2534, 0xA9D8, 0x2535, 0xA9D9, 0x2536, 0xA9DA, + 0x2537, 0xA9DB, 0x2538, 0xA9DC, 0x2539, 0xA9DD, 0x253A, 0xA9DE, + 0x253B, 0xA9DF, 0x253C, 0xA9E0, 0x253D, 0xA9E1, 0x253E, 0xA9E2, + 0x253F, 0xA9E3, 0x2540, 0xA9E4, 0x2541, 0xA9E5, 0x2542, 0xA9E6, + 0x2543, 0xA9E7, 0x2544, 0xA9E8, 0x2545, 0xA9E9, 0x2546, 0xA9EA, + 0x2547, 0xA9EB, 0x2548, 0xA9EC, 0x2549, 0xA9ED, 0x254A, 0xA9EE, + 0x254B, 0xA9EF, 0x2550, 0xA854, 0x2551, 0xA855, 0x2552, 0xA856, + 0x2553, 0xA857, 0x2554, 0xA858, 0x2555, 0xA859, 0x2556, 0xA85A, + 0x2557, 0xA85B, 0x2558, 0xA85C, 0x2559, 0xA85D, 0x255A, 0xA85E, + 0x255B, 0xA85F, 0x255C, 0xA860, 0x255D, 0xA861, 0x255E, 0xA862, + 0x255F, 0xA863, 0x2560, 0xA864, 0x2561, 0xA865, 0x2562, 0xA866, + 0x2563, 0xA867, 0x2564, 0xA868, 0x2565, 0xA869, 0x2566, 0xA86A, + 0x2567, 0xA86B, 0x2568, 0xA86C, 0x2569, 0xA86D, 0x256A, 0xA86E, + 0x256B, 0xA86F, 0x256C, 0xA870, 0x256D, 0xA871, 0x256E, 0xA872, + 0x256F, 0xA873, 0x2570, 0xA874, 0x2571, 0xA875, 0x2572, 0xA876, + 0x2573, 0xA877, 0x2581, 0xA878, 0x2582, 0xA879, 0x2583, 0xA87A, + 0x2584, 0xA87B, 0x2585, 0xA87C, 0x2586, 0xA87D, 0x2587, 0xA87E, + 0x2588, 0xA880, 0x2589, 0xA881, 0x258A, 0xA882, 0x258B, 0xA883, + 0x258C, 0xA884, 0x258D, 0xA885, 0x258E, 0xA886, 0x258F, 0xA887, + 0x2593, 0xA888, 0x2594, 0xA889, 0x2595, 0xA88A, 0x25A0, 0xA1F6, + 0x25A1, 0xA1F5, 0x25B2, 0xA1F8, 0x25B3, 0xA1F7, 0x25BC, 0xA88B, + 0x25BD, 0xA88C, 0x25C6, 0xA1F4, 0x25C7, 0xA1F3, 0x25CB, 0xA1F0, + 0x25CE, 0xA1F2, 0x25CF, 0xA1F1, 0x25E2, 0xA88D, 0x25E3, 0xA88E, + 0x25E4, 0xA88F, 0x25E5, 0xA890, 0x2605, 0xA1EF, 0x2606, 0xA1EE, + 0x2609, 0xA891, 0x2640, 0xA1E2, 0x2642, 0xA1E1, 0x3000, 0xA1A1, + 0x3001, 0xA1A2, 0x3002, 0xA1A3, 0x3003, 0xA1A8, 0x3005, 0xA1A9, + 0x3006, 0xA965, 0x3007, 0xA996, 0x3008, 0xA1B4, 0x3009, 0xA1B5, + 0x300A, 0xA1B6, 0x300B, 0xA1B7, 0x300C, 0xA1B8, 0x300D, 0xA1B9, + 0x300E, 0xA1BA, 0x300F, 0xA1BB, 0x3010, 0xA1BE, 0x3011, 0xA1BF, + 0x3012, 0xA893, 0x3013, 0xA1FE, 0x3014, 0xA1B2, 0x3015, 0xA1B3, + 0x3016, 0xA1BC, 0x3017, 0xA1BD, 0x301D, 0xA894, 0x301E, 0xA895, + 0x3021, 0xA940, 0x3022, 0xA941, 0x3023, 0xA942, 0x3024, 0xA943, + 0x3025, 0xA944, 0x3026, 0xA945, 0x3027, 0xA946, 0x3028, 0xA947, + 0x3029, 0xA948, 0x3041, 0xA4A1, 0x3042, 0xA4A2, 0x3043, 0xA4A3, + 0x3044, 0xA4A4, 0x3045, 0xA4A5, 0x3046, 0xA4A6, 0x3047, 0xA4A7, + 0x3048, 0xA4A8, 0x3049, 0xA4A9, 0x304A, 0xA4AA, 0x304B, 0xA4AB, + 0x304C, 0xA4AC, 0x304D, 0xA4AD, 0x304E, 0xA4AE, 0x304F, 0xA4AF, + 0x3050, 0xA4B0, 0x3051, 0xA4B1, 0x3052, 0xA4B2, 0x3053, 0xA4B3, + 0x3054, 0xA4B4, 0x3055, 0xA4B5, 0x3056, 0xA4B6, 0x3057, 0xA4B7, + 0x3058, 0xA4B8, 0x3059, 0xA4B9, 0x305A, 0xA4BA, 0x305B, 0xA4BB, + 0x305C, 0xA4BC, 0x305D, 0xA4BD, 0x305E, 0xA4BE, 0x305F, 0xA4BF, + 0x3060, 0xA4C0, 0x3061, 0xA4C1, 0x3062, 0xA4C2, 0x3063, 0xA4C3, + 0x3064, 0xA4C4, 0x3065, 0xA4C5, 0x3066, 0xA4C6, 0x3067, 0xA4C7, + 0x3068, 0xA4C8, 0x3069, 0xA4C9, 0x306A, 0xA4CA, 0x306B, 0xA4CB, + 0x306C, 0xA4CC, 0x306D, 0xA4CD, 0x306E, 0xA4CE, 0x306F, 0xA4CF, + 0x3070, 0xA4D0, 0x3071, 0xA4D1, 0x3072, 0xA4D2, 0x3073, 0xA4D3, + 0x3074, 0xA4D4, 0x3075, 0xA4D5, 0x3076, 0xA4D6, 0x3077, 0xA4D7, + 0x3078, 0xA4D8, 0x3079, 0xA4D9, 0x307A, 0xA4DA, 0x307B, 0xA4DB, + 0x307C, 0xA4DC, 0x307D, 0xA4DD, 0x307E, 0xA4DE, 0x307F, 0xA4DF, + 0x3080, 0xA4E0, 0x3081, 0xA4E1, 0x3082, 0xA4E2, 0x3083, 0xA4E3, + 0x3084, 0xA4E4, 0x3085, 0xA4E5, 0x3086, 0xA4E6, 0x3087, 0xA4E7, + 0x3088, 0xA4E8, 0x3089, 0xA4E9, 0x308A, 0xA4EA, 0x308B, 0xA4EB, + 0x308C, 0xA4EC, 0x308D, 0xA4ED, 0x308E, 0xA4EE, 0x308F, 0xA4EF, + 0x3090, 0xA4F0, 0x3091, 0xA4F1, 0x3092, 0xA4F2, 0x3093, 0xA4F3, + 0x309B, 0xA961, 0x309C, 0xA962, 0x309D, 0xA966, 0x309E, 0xA967, + 0x30A1, 0xA5A1, 0x30A2, 0xA5A2, 0x30A3, 0xA5A3, 0x30A4, 0xA5A4, + 0x30A5, 0xA5A5, 0x30A6, 0xA5A6, 0x30A7, 0xA5A7, 0x30A8, 0xA5A8, + 0x30A9, 0xA5A9, 0x30AA, 0xA5AA, 0x30AB, 0xA5AB, 0x30AC, 0xA5AC, + 0x30AD, 0xA5AD, 0x30AE, 0xA5AE, 0x30AF, 0xA5AF, 0x30B0, 0xA5B0, + 0x30B1, 0xA5B1, 0x30B2, 0xA5B2, 0x30B3, 0xA5B3, 0x30B4, 0xA5B4, + 0x30B5, 0xA5B5, 0x30B6, 0xA5B6, 0x30B7, 0xA5B7, 0x30B8, 0xA5B8, + 0x30B9, 0xA5B9, 0x30BA, 0xA5BA, 0x30BB, 0xA5BB, 0x30BC, 0xA5BC, + 0x30BD, 0xA5BD, 0x30BE, 0xA5BE, 0x30BF, 0xA5BF, 0x30C0, 0xA5C0, + 0x30C1, 0xA5C1, 0x30C2, 0xA5C2, 0x30C3, 0xA5C3, 0x30C4, 0xA5C4, + 0x30C5, 0xA5C5, 0x30C6, 0xA5C6, 0x30C7, 0xA5C7, 0x30C8, 0xA5C8, + 0x30C9, 0xA5C9, 0x30CA, 0xA5CA, 0x30CB, 0xA5CB, 0x30CC, 0xA5CC, + 0x30CD, 0xA5CD, 0x30CE, 0xA5CE, 0x30CF, 0xA5CF, 0x30D0, 0xA5D0, + 0x30D1, 0xA5D1, 0x30D2, 0xA5D2, 0x30D3, 0xA5D3, 0x30D4, 0xA5D4, + 0x30D5, 0xA5D5, 0x30D6, 0xA5D6, 0x30D7, 0xA5D7, 0x30D8, 0xA5D8, + 0x30D9, 0xA5D9, 0x30DA, 0xA5DA, 0x30DB, 0xA5DB, 0x30DC, 0xA5DC, + 0x30DD, 0xA5DD, 0x30DE, 0xA5DE, 0x30DF, 0xA5DF, 0x30E0, 0xA5E0, + 0x30E1, 0xA5E1, 0x30E2, 0xA5E2, 0x30E3, 0xA5E3, 0x30E4, 0xA5E4, + 0x30E5, 0xA5E5, 0x30E6, 0xA5E6, 0x30E7, 0xA5E7, 0x30E8, 0xA5E8, + 0x30E9, 0xA5E9, 0x30EA, 0xA5EA, 0x30EB, 0xA5EB, 0x30EC, 0xA5EC, + 0x30ED, 0xA5ED, 0x30EE, 0xA5EE, 0x30EF, 0xA5EF, 0x30F0, 0xA5F0, + 0x30F1, 0xA5F1, 0x30F2, 0xA5F2, 0x30F3, 0xA5F3, 0x30F4, 0xA5F4, + 0x30F5, 0xA5F5, 0x30F6, 0xA5F6, 0x30FC, 0xA960, 0x30FD, 0xA963, + 0x30FE, 0xA964, 0x3105, 0xA8C5, 0x3106, 0xA8C6, 0x3107, 0xA8C7, + 0x3108, 0xA8C8, 0x3109, 0xA8C9, 0x310A, 0xA8CA, 0x310B, 0xA8CB, + 0x310C, 0xA8CC, 0x310D, 0xA8CD, 0x310E, 0xA8CE, 0x310F, 0xA8CF, + 0x3110, 0xA8D0, 0x3111, 0xA8D1, 0x3112, 0xA8D2, 0x3113, 0xA8D3, + 0x3114, 0xA8D4, 0x3115, 0xA8D5, 0x3116, 0xA8D6, 0x3117, 0xA8D7, + 0x3118, 0xA8D8, 0x3119, 0xA8D9, 0x311A, 0xA8DA, 0x311B, 0xA8DB, + 0x311C, 0xA8DC, 0x311D, 0xA8DD, 0x311E, 0xA8DE, 0x311F, 0xA8DF, + 0x3120, 0xA8E0, 0x3121, 0xA8E1, 0x3122, 0xA8E2, 0x3123, 0xA8E3, + 0x3124, 0xA8E4, 0x3125, 0xA8E5, 0x3126, 0xA8E6, 0x3127, 0xA8E7, + 0x3128, 0xA8E8, 0x3129, 0xA8E9, 0x3220, 0xA2E5, 0x3221, 0xA2E6, + 0x3222, 0xA2E7, 0x3223, 0xA2E8, 0x3224, 0xA2E9, 0x3225, 0xA2EA, + 0x3226, 0xA2EB, 0x3227, 0xA2EC, 0x3228, 0xA2ED, 0x3229, 0xA2EE, + 0x3231, 0xA95A, 0x32A3, 0xA949, 0x338E, 0xA94A, 0x338F, 0xA94B, + 0x339C, 0xA94C, 0x339D, 0xA94D, 0x339E, 0xA94E, 0x33A1, 0xA94F, + 0x33C4, 0xA950, 0x33CE, 0xA951, 0x33D1, 0xA952, 0x33D2, 0xA953, + 0x33D5, 0xA954, 0x4E00, 0xD2BB, 0x4E01, 0xB6A1, 0x4E02, 0x8140, + 0x4E03, 0xC6DF, 0x4E04, 0x8141, 0x4E05, 0x8142, 0x4E06, 0x8143, + 0x4E07, 0xCDF2, 0x4E08, 0xD5C9, 0x4E09, 0xC8FD, 0x4E0A, 0xC9CF, + 0x4E0B, 0xCFC2, 0x4E0C, 0xD8A2, 0x4E0D, 0xB2BB, 0x4E0E, 0xD3EB, + 0x4E0F, 0x8144, 0x4E10, 0xD8A4, 0x4E11, 0xB3F3, 0x4E12, 0x8145, + 0x4E13, 0xD7A8, 0x4E14, 0xC7D2, 0x4E15, 0xD8A7, 0x4E16, 0xCAC0, + 0x4E17, 0x8146, 0x4E18, 0xC7F0, 0x4E19, 0xB1FB, 0x4E1A, 0xD2B5, + 0x4E1B, 0xB4D4, 0x4E1C, 0xB6AB, 0x4E1D, 0xCBBF, 0x4E1E, 0xD8A9, + 0x4E1F, 0x8147, 0x4E20, 0x8148, 0x4E21, 0x8149, 0x4E22, 0xB6AA, + 0x4E23, 0x814A, 0x4E24, 0xC1BD, 0x4E25, 0xD1CF, 0x4E26, 0x814B, + 0x4E27, 0xC9A5, 0x4E28, 0xD8AD, 0x4E29, 0x814C, 0x4E2A, 0xB8F6, + 0x4E2B, 0xD1BE, 0x4E2C, 0xE3DC, 0x4E2D, 0xD6D0, 0x4E2E, 0x814D, + 0x4E2F, 0x814E, 0x4E30, 0xB7E1, 0x4E31, 0x814F, 0x4E32, 0xB4AE, + 0x4E33, 0x8150, 0x4E34, 0xC1D9, 0x4E35, 0x8151, 0x4E36, 0xD8BC, + 0x4E37, 0x8152, 0x4E38, 0xCDE8, 0x4E39, 0xB5A4, 0x4E3A, 0xCEAA, + 0x4E3B, 0xD6F7, 0x4E3C, 0x8153, 0x4E3D, 0xC0F6, 0x4E3E, 0xBED9, + 0x4E3F, 0xD8AF, 0x4E40, 0x8154, 0x4E41, 0x8155, 0x4E42, 0x8156, + 0x4E43, 0xC4CB, 0x4E44, 0x8157, 0x4E45, 0xBEC3, 0x4E46, 0x8158, + 0x4E47, 0xD8B1, 0x4E48, 0xC3B4, 0x4E49, 0xD2E5, 0x4E4A, 0x8159, + 0x4E4B, 0xD6AE, 0x4E4C, 0xCEDA, 0x4E4D, 0xD5A7, 0x4E4E, 0xBAF5, + 0x4E4F, 0xB7A6, 0x4E50, 0xC0D6, 0x4E51, 0x815A, 0x4E52, 0xC6B9, + 0x4E53, 0xC5D2, 0x4E54, 0xC7C7, 0x4E55, 0x815B, 0x4E56, 0xB9D4, + 0x4E57, 0x815C, 0x4E58, 0xB3CB, 0x4E59, 0xD2D2, 0x4E5A, 0x815D, + 0x4E5B, 0x815E, 0x4E5C, 0xD8BF, 0x4E5D, 0xBEC5, 0x4E5E, 0xC6F2, + 0x4E5F, 0xD2B2, 0x4E60, 0xCFB0, 0x4E61, 0xCFE7, 0x4E62, 0x815F, + 0x4E63, 0x8160, 0x4E64, 0x8161, 0x4E65, 0x8162, 0x4E66, 0xCAE9, + 0x4E67, 0x8163, 0x4E68, 0x8164, 0x4E69, 0xD8C0, 0x4E6A, 0x8165, + 0x4E6B, 0x8166, 0x4E6C, 0x8167, 0x4E6D, 0x8168, 0x4E6E, 0x8169, + 0x4E6F, 0x816A, 0x4E70, 0xC2F2, 0x4E71, 0xC2D2, 0x4E72, 0x816B, + 0x4E73, 0xC8E9, 0x4E74, 0x816C, 0x4E75, 0x816D, 0x4E76, 0x816E, + 0x4E77, 0x816F, 0x4E78, 0x8170, 0x4E79, 0x8171, 0x4E7A, 0x8172, + 0x4E7B, 0x8173, 0x4E7C, 0x8174, 0x4E7D, 0x8175, 0x4E7E, 0xC7AC, + 0x4E7F, 0x8176, 0x4E80, 0x8177, 0x4E81, 0x8178, 0x4E82, 0x8179, + 0x4E83, 0x817A, 0x4E84, 0x817B, 0x4E85, 0x817C, 0x4E86, 0xC1CB, + 0x4E87, 0x817D, 0x4E88, 0xD3E8, 0x4E89, 0xD5F9, 0x4E8A, 0x817E, + 0x4E8B, 0xCAC2, 0x4E8C, 0xB6FE, 0x4E8D, 0xD8A1, 0x4E8E, 0xD3DA, + 0x4E8F, 0xBFF7, 0x4E90, 0x8180, 0x4E91, 0xD4C6, 0x4E92, 0xBBA5, + 0x4E93, 0xD8C1, 0x4E94, 0xCEE5, 0x4E95, 0xBEAE, 0x4E96, 0x8181, + 0x4E97, 0x8182, 0x4E98, 0xD8A8, 0x4E99, 0x8183, 0x4E9A, 0xD1C7, + 0x4E9B, 0xD0A9, 0x4E9C, 0x8184, 0x4E9D, 0x8185, 0x4E9E, 0x8186, + 0x4E9F, 0xD8BD, 0x4EA0, 0xD9EF, 0x4EA1, 0xCDF6, 0x4EA2, 0xBFBA, + 0x4EA3, 0x8187, 0x4EA4, 0xBDBB, 0x4EA5, 0xBAA5, 0x4EA6, 0xD2E0, + 0x4EA7, 0xB2FA, 0x4EA8, 0xBAE0, 0x4EA9, 0xC4B6, 0x4EAA, 0x8188, + 0x4EAB, 0xCFED, 0x4EAC, 0xBEA9, 0x4EAD, 0xCDA4, 0x4EAE, 0xC1C1, + 0x4EAF, 0x8189, 0x4EB0, 0x818A, 0x4EB1, 0x818B, 0x4EB2, 0xC7D7, + 0x4EB3, 0xD9F1, 0x4EB4, 0x818C, 0x4EB5, 0xD9F4, 0x4EB6, 0x818D, + 0x4EB7, 0x818E, 0x4EB8, 0x818F, 0x4EB9, 0x8190, 0x4EBA, 0xC8CB, + 0x4EBB, 0xD8E9, 0x4EBC, 0x8191, 0x4EBD, 0x8192, 0x4EBE, 0x8193, + 0x4EBF, 0xD2DA, 0x4EC0, 0xCAB2, 0x4EC1, 0xC8CA, 0x4EC2, 0xD8EC, + 0x4EC3, 0xD8EA, 0x4EC4, 0xD8C6, 0x4EC5, 0xBDF6, 0x4EC6, 0xC6CD, + 0x4EC7, 0xB3F0, 0x4EC8, 0x8194, 0x4EC9, 0xD8EB, 0x4ECA, 0xBDF1, + 0x4ECB, 0xBDE9, 0x4ECC, 0x8195, 0x4ECD, 0xC8D4, 0x4ECE, 0xB4D3, + 0x4ECF, 0x8196, 0x4ED0, 0x8197, 0x4ED1, 0xC2D8, 0x4ED2, 0x8198, + 0x4ED3, 0xB2D6, 0x4ED4, 0xD7D0, 0x4ED5, 0xCACB, 0x4ED6, 0xCBFB, + 0x4ED7, 0xD5CC, 0x4ED8, 0xB8B6, 0x4ED9, 0xCFC9, 0x4EDA, 0x8199, + 0x4EDB, 0x819A, 0x4EDC, 0x819B, 0x4EDD, 0xD9DA, 0x4EDE, 0xD8F0, + 0x4EDF, 0xC7AA, 0x4EE0, 0x819C, 0x4EE1, 0xD8EE, 0x4EE2, 0x819D, + 0x4EE3, 0xB4FA, 0x4EE4, 0xC1EE, 0x4EE5, 0xD2D4, 0x4EE6, 0x819E, + 0x4EE7, 0x819F, 0x4EE8, 0xD8ED, 0x4EE9, 0x81A0, 0x4EEA, 0xD2C7, + 0x4EEB, 0xD8EF, 0x4EEC, 0xC3C7, 0x4EED, 0x81A1, 0x4EEE, 0x81A2, + 0x4EEF, 0x81A3, 0x4EF0, 0xD1F6, 0x4EF1, 0x81A4, 0x4EF2, 0xD6D9, + 0x4EF3, 0xD8F2, 0x4EF4, 0x81A5, 0x4EF5, 0xD8F5, 0x4EF6, 0xBCFE, + 0x4EF7, 0xBCDB, 0x4EF8, 0x81A6, 0x4EF9, 0x81A7, 0x4EFA, 0x81A8, + 0x4EFB, 0xC8CE, 0x4EFC, 0x81A9, 0x4EFD, 0xB7DD, 0x4EFE, 0x81AA, + 0x4EFF, 0xB7C2, 0x4F00, 0x81AB, 0x4F01, 0xC6F3, 0x4F02, 0x81AC, + 0x4F03, 0x81AD, 0x4F04, 0x81AE, 0x4F05, 0x81AF, 0x4F06, 0x81B0, + 0x4F07, 0x81B1, 0x4F08, 0x81B2, 0x4F09, 0xD8F8, 0x4F0A, 0xD2C1, + 0x4F0B, 0x81B3, 0x4F0C, 0x81B4, 0x4F0D, 0xCEE9, 0x4F0E, 0xBCBF, + 0x4F0F, 0xB7FC, 0x4F10, 0xB7A5, 0x4F11, 0xD0DD, 0x4F12, 0x81B5, + 0x4F13, 0x81B6, 0x4F14, 0x81B7, 0x4F15, 0x81B8, 0x4F16, 0x81B9, + 0x4F17, 0xD6DA, 0x4F18, 0xD3C5, 0x4F19, 0xBBEF, 0x4F1A, 0xBBE1, + 0x4F1B, 0xD8F1, 0x4F1C, 0x81BA, 0x4F1D, 0x81BB, 0x4F1E, 0xC9A1, + 0x4F1F, 0xCEB0, 0x4F20, 0xB4AB, 0x4F21, 0x81BC, 0x4F22, 0xD8F3, + 0x4F23, 0x81BD, 0x4F24, 0xC9CB, 0x4F25, 0xD8F6, 0x4F26, 0xC2D7, + 0x4F27, 0xD8F7, 0x4F28, 0x81BE, 0x4F29, 0x81BF, 0x4F2A, 0xCEB1, + 0x4F2B, 0xD8F9, 0x4F2C, 0x81C0, 0x4F2D, 0x81C1, 0x4F2E, 0x81C2, + 0x4F2F, 0xB2AE, 0x4F30, 0xB9C0, 0x4F31, 0x81C3, 0x4F32, 0xD9A3, + 0x4F33, 0x81C4, 0x4F34, 0xB0E9, 0x4F35, 0x81C5, 0x4F36, 0xC1E6, + 0x4F37, 0x81C6, 0x4F38, 0xC9EC, 0x4F39, 0x81C7, 0x4F3A, 0xCBC5, + 0x4F3B, 0x81C8, 0x4F3C, 0xCBC6, 0x4F3D, 0xD9A4, 0x4F3E, 0x81C9, + 0x4F3F, 0x81CA, 0x4F40, 0x81CB, 0x4F41, 0x81CC, 0x4F42, 0x81CD, + 0x4F43, 0xB5E8, 0x4F44, 0x81CE, 0x4F45, 0x81CF, 0x4F46, 0xB5AB, + 0x4F47, 0x81D0, 0x4F48, 0x81D1, 0x4F49, 0x81D2, 0x4F4A, 0x81D3, + 0x4F4B, 0x81D4, 0x4F4C, 0x81D5, 0x4F4D, 0xCEBB, 0x4F4E, 0xB5CD, + 0x4F4F, 0xD7A1, 0x4F50, 0xD7F4, 0x4F51, 0xD3D3, 0x4F52, 0x81D6, + 0x4F53, 0xCCE5, 0x4F54, 0x81D7, 0x4F55, 0xBACE, 0x4F56, 0x81D8, + 0x4F57, 0xD9A2, 0x4F58, 0xD9DC, 0x4F59, 0xD3E0, 0x4F5A, 0xD8FD, + 0x4F5B, 0xB7F0, 0x4F5C, 0xD7F7, 0x4F5D, 0xD8FE, 0x4F5E, 0xD8FA, + 0x4F5F, 0xD9A1, 0x4F60, 0xC4E3, 0x4F61, 0x81D9, 0x4F62, 0x81DA, + 0x4F63, 0xD3B6, 0x4F64, 0xD8F4, 0x4F65, 0xD9DD, 0x4F66, 0x81DB, + 0x4F67, 0xD8FB, 0x4F68, 0x81DC, 0x4F69, 0xC5E5, 0x4F6A, 0x81DD, + 0x4F6B, 0x81DE, 0x4F6C, 0xC0D0, 0x4F6D, 0x81DF, 0x4F6E, 0x81E0, + 0x4F6F, 0xD1F0, 0x4F70, 0xB0DB, 0x4F71, 0x81E1, 0x4F72, 0x81E2, + 0x4F73, 0xBCD1, 0x4F74, 0xD9A6, 0x4F75, 0x81E3, 0x4F76, 0xD9A5, + 0x4F77, 0x81E4, 0x4F78, 0x81E5, 0x4F79, 0x81E6, 0x4F7A, 0x81E7, + 0x4F7B, 0xD9AC, 0x4F7C, 0xD9AE, 0x4F7D, 0x81E8, 0x4F7E, 0xD9AB, + 0x4F7F, 0xCAB9, 0x4F80, 0x81E9, 0x4F81, 0x81EA, 0x4F82, 0x81EB, + 0x4F83, 0xD9A9, 0x4F84, 0xD6B6, 0x4F85, 0x81EC, 0x4F86, 0x81ED, + 0x4F87, 0x81EE, 0x4F88, 0xB3DE, 0x4F89, 0xD9A8, 0x4F8A, 0x81EF, + 0x4F8B, 0xC0FD, 0x4F8C, 0x81F0, 0x4F8D, 0xCACC, 0x4F8E, 0x81F1, + 0x4F8F, 0xD9AA, 0x4F90, 0x81F2, 0x4F91, 0xD9A7, 0x4F92, 0x81F3, + 0x4F93, 0x81F4, 0x4F94, 0xD9B0, 0x4F95, 0x81F5, 0x4F96, 0x81F6, + 0x4F97, 0xB6B1, 0x4F98, 0x81F7, 0x4F99, 0x81F8, 0x4F9A, 0x81F9, + 0x4F9B, 0xB9A9, 0x4F9C, 0x81FA, 0x4F9D, 0xD2C0, 0x4F9E, 0x81FB, + 0x4F9F, 0x81FC, 0x4FA0, 0xCFC0, 0x4FA1, 0x81FD, 0x4FA2, 0x81FE, + 0x4FA3, 0xC2C2, 0x4FA4, 0x8240, 0x4FA5, 0xBDC4, 0x4FA6, 0xD5EC, + 0x4FA7, 0xB2E0, 0x4FA8, 0xC7C8, 0x4FA9, 0xBFEB, 0x4FAA, 0xD9AD, + 0x4FAB, 0x8241, 0x4FAC, 0xD9AF, 0x4FAD, 0x8242, 0x4FAE, 0xCEEA, + 0x4FAF, 0xBAEE, 0x4FB0, 0x8243, 0x4FB1, 0x8244, 0x4FB2, 0x8245, + 0x4FB3, 0x8246, 0x4FB4, 0x8247, 0x4FB5, 0xC7D6, 0x4FB6, 0x8248, + 0x4FB7, 0x8249, 0x4FB8, 0x824A, 0x4FB9, 0x824B, 0x4FBA, 0x824C, + 0x4FBB, 0x824D, 0x4FBC, 0x824E, 0x4FBD, 0x824F, 0x4FBE, 0x8250, + 0x4FBF, 0xB1E3, 0x4FC0, 0x8251, 0x4FC1, 0x8252, 0x4FC2, 0x8253, + 0x4FC3, 0xB4D9, 0x4FC4, 0xB6ED, 0x4FC5, 0xD9B4, 0x4FC6, 0x8254, + 0x4FC7, 0x8255, 0x4FC8, 0x8256, 0x4FC9, 0x8257, 0x4FCA, 0xBFA1, + 0x4FCB, 0x8258, 0x4FCC, 0x8259, 0x4FCD, 0x825A, 0x4FCE, 0xD9DE, + 0x4FCF, 0xC7CE, 0x4FD0, 0xC0FE, 0x4FD1, 0xD9B8, 0x4FD2, 0x825B, + 0x4FD3, 0x825C, 0x4FD4, 0x825D, 0x4FD5, 0x825E, 0x4FD6, 0x825F, + 0x4FD7, 0xCBD7, 0x4FD8, 0xB7FD, 0x4FD9, 0x8260, 0x4FDA, 0xD9B5, + 0x4FDB, 0x8261, 0x4FDC, 0xD9B7, 0x4FDD, 0xB1A3, 0x4FDE, 0xD3E1, + 0x4FDF, 0xD9B9, 0x4FE0, 0x8262, 0x4FE1, 0xD0C5, 0x4FE2, 0x8263, + 0x4FE3, 0xD9B6, 0x4FE4, 0x8264, 0x4FE5, 0x8265, 0x4FE6, 0xD9B1, + 0x4FE7, 0x8266, 0x4FE8, 0xD9B2, 0x4FE9, 0xC1A9, 0x4FEA, 0xD9B3, + 0x4FEB, 0x8267, 0x4FEC, 0x8268, 0x4FED, 0xBCF3, 0x4FEE, 0xD0DE, + 0x4FEF, 0xB8A9, 0x4FF0, 0x8269, 0x4FF1, 0xBEE3, 0x4FF2, 0x826A, + 0x4FF3, 0xD9BD, 0x4FF4, 0x826B, 0x4FF5, 0x826C, 0x4FF6, 0x826D, + 0x4FF7, 0x826E, 0x4FF8, 0xD9BA, 0x4FF9, 0x826F, 0x4FFA, 0xB0B3, + 0x4FFB, 0x8270, 0x4FFC, 0x8271, 0x4FFD, 0x8272, 0x4FFE, 0xD9C2, + 0x4FFF, 0x8273, 0x5000, 0x8274, 0x5001, 0x8275, 0x5002, 0x8276, + 0x5003, 0x8277, 0x5004, 0x8278, 0x5005, 0x8279, 0x5006, 0x827A, + 0x5007, 0x827B, 0x5008, 0x827C, 0x5009, 0x827D, 0x500A, 0x827E, + 0x500B, 0x8280, 0x500C, 0xD9C4, 0x500D, 0xB1B6, 0x500E, 0x8281, + 0x500F, 0xD9BF, 0x5010, 0x8282, 0x5011, 0x8283, 0x5012, 0xB5B9, + 0x5013, 0x8284, 0x5014, 0xBEF3, 0x5015, 0x8285, 0x5016, 0x8286, + 0x5017, 0x8287, 0x5018, 0xCCC8, 0x5019, 0xBAF2, 0x501A, 0xD2D0, + 0x501B, 0x8288, 0x501C, 0xD9C3, 0x501D, 0x8289, 0x501E, 0x828A, + 0x501F, 0xBDE8, 0x5020, 0x828B, 0x5021, 0xB3AB, 0x5022, 0x828C, + 0x5023, 0x828D, 0x5024, 0x828E, 0x5025, 0xD9C5, 0x5026, 0xBEEB, + 0x5027, 0x828F, 0x5028, 0xD9C6, 0x5029, 0xD9BB, 0x502A, 0xC4DF, + 0x502B, 0x8290, 0x502C, 0xD9BE, 0x502D, 0xD9C1, 0x502E, 0xD9C0, + 0x502F, 0x8291, 0x5030, 0x8292, 0x5031, 0x8293, 0x5032, 0x8294, + 0x5033, 0x8295, 0x5034, 0x8296, 0x5035, 0x8297, 0x5036, 0x8298, + 0x5037, 0x8299, 0x5038, 0x829A, 0x5039, 0x829B, 0x503A, 0xD5AE, + 0x503B, 0x829C, 0x503C, 0xD6B5, 0x503D, 0x829D, 0x503E, 0xC7E3, + 0x503F, 0x829E, 0x5040, 0x829F, 0x5041, 0x82A0, 0x5042, 0x82A1, + 0x5043, 0xD9C8, 0x5044, 0x82A2, 0x5045, 0x82A3, 0x5046, 0x82A4, + 0x5047, 0xBCD9, 0x5048, 0xD9CA, 0x5049, 0x82A5, 0x504A, 0x82A6, + 0x504B, 0x82A7, 0x504C, 0xD9BC, 0x504D, 0x82A8, 0x504E, 0xD9CB, + 0x504F, 0xC6AB, 0x5050, 0x82A9, 0x5051, 0x82AA, 0x5052, 0x82AB, + 0x5053, 0x82AC, 0x5054, 0x82AD, 0x5055, 0xD9C9, 0x5056, 0x82AE, + 0x5057, 0x82AF, 0x5058, 0x82B0, 0x5059, 0x82B1, 0x505A, 0xD7F6, + 0x505B, 0x82B2, 0x505C, 0xCDA3, 0x505D, 0x82B3, 0x505E, 0x82B4, + 0x505F, 0x82B5, 0x5060, 0x82B6, 0x5061, 0x82B7, 0x5062, 0x82B8, + 0x5063, 0x82B9, 0x5064, 0x82BA, 0x5065, 0xBDA1, 0x5066, 0x82BB, + 0x5067, 0x82BC, 0x5068, 0x82BD, 0x5069, 0x82BE, 0x506A, 0x82BF, + 0x506B, 0x82C0, 0x506C, 0xD9CC, 0x506D, 0x82C1, 0x506E, 0x82C2, + 0x506F, 0x82C3, 0x5070, 0x82C4, 0x5071, 0x82C5, 0x5072, 0x82C6, + 0x5073, 0x82C7, 0x5074, 0x82C8, 0x5075, 0x82C9, 0x5076, 0xC5BC, + 0x5077, 0xCDB5, 0x5078, 0x82CA, 0x5079, 0x82CB, 0x507A, 0x82CC, + 0x507B, 0xD9CD, 0x507C, 0x82CD, 0x507D, 0x82CE, 0x507E, 0xD9C7, + 0x507F, 0xB3A5, 0x5080, 0xBFFE, 0x5081, 0x82CF, 0x5082, 0x82D0, + 0x5083, 0x82D1, 0x5084, 0x82D2, 0x5085, 0xB8B5, 0x5086, 0x82D3, + 0x5087, 0x82D4, 0x5088, 0xC0FC, 0x5089, 0x82D5, 0x508A, 0x82D6, + 0x508B, 0x82D7, 0x508C, 0x82D8, 0x508D, 0xB0F8, 0x508E, 0x82D9, + 0x508F, 0x82DA, 0x5090, 0x82DB, 0x5091, 0x82DC, 0x5092, 0x82DD, + 0x5093, 0x82DE, 0x5094, 0x82DF, 0x5095, 0x82E0, 0x5096, 0x82E1, + 0x5097, 0x82E2, 0x5098, 0x82E3, 0x5099, 0x82E4, 0x509A, 0x82E5, + 0x509B, 0x82E6, 0x509C, 0x82E7, 0x509D, 0x82E8, 0x509E, 0x82E9, + 0x509F, 0x82EA, 0x50A0, 0x82EB, 0x50A1, 0x82EC, 0x50A2, 0x82ED, + 0x50A3, 0xB4F6, 0x50A4, 0x82EE, 0x50A5, 0xD9CE, 0x50A6, 0x82EF, + 0x50A7, 0xD9CF, 0x50A8, 0xB4A2, 0x50A9, 0xD9D0, 0x50AA, 0x82F0, + 0x50AB, 0x82F1, 0x50AC, 0xB4DF, 0x50AD, 0x82F2, 0x50AE, 0x82F3, + 0x50AF, 0x82F4, 0x50B0, 0x82F5, 0x50B1, 0x82F6, 0x50B2, 0xB0C1, + 0x50B3, 0x82F7, 0x50B4, 0x82F8, 0x50B5, 0x82F9, 0x50B6, 0x82FA, + 0x50B7, 0x82FB, 0x50B8, 0x82FC, 0x50B9, 0x82FD, 0x50BA, 0xD9D1, + 0x50BB, 0xC9B5, 0x50BC, 0x82FE, 0x50BD, 0x8340, 0x50BE, 0x8341, + 0x50BF, 0x8342, 0x50C0, 0x8343, 0x50C1, 0x8344, 0x50C2, 0x8345, + 0x50C3, 0x8346, 0x50C4, 0x8347, 0x50C5, 0x8348, 0x50C6, 0x8349, + 0x50C7, 0x834A, 0x50C8, 0x834B, 0x50C9, 0x834C, 0x50CA, 0x834D, + 0x50CB, 0x834E, 0x50CC, 0x834F, 0x50CD, 0x8350, 0x50CE, 0x8351, + 0x50CF, 0xCFF1, 0x50D0, 0x8352, 0x50D1, 0x8353, 0x50D2, 0x8354, + 0x50D3, 0x8355, 0x50D4, 0x8356, 0x50D5, 0x8357, 0x50D6, 0xD9D2, + 0x50D7, 0x8358, 0x50D8, 0x8359, 0x50D9, 0x835A, 0x50DA, 0xC1C5, + 0x50DB, 0x835B, 0x50DC, 0x835C, 0x50DD, 0x835D, 0x50DE, 0x835E, + 0x50DF, 0x835F, 0x50E0, 0x8360, 0x50E1, 0x8361, 0x50E2, 0x8362, + 0x50E3, 0x8363, 0x50E4, 0x8364, 0x50E5, 0x8365, 0x50E6, 0xD9D6, + 0x50E7, 0xC9AE, 0x50E8, 0x8366, 0x50E9, 0x8367, 0x50EA, 0x8368, + 0x50EB, 0x8369, 0x50EC, 0xD9D5, 0x50ED, 0xD9D4, 0x50EE, 0xD9D7, + 0x50EF, 0x836A, 0x50F0, 0x836B, 0x50F1, 0x836C, 0x50F2, 0x836D, + 0x50F3, 0xCBDB, 0x50F4, 0x836E, 0x50F5, 0xBDA9, 0x50F6, 0x836F, + 0x50F7, 0x8370, 0x50F8, 0x8371, 0x50F9, 0x8372, 0x50FA, 0x8373, + 0x50FB, 0xC6A7, 0x50FC, 0x8374, 0x50FD, 0x8375, 0x50FE, 0x8376, + 0x50FF, 0x8377, 0x5100, 0x8378, 0x5101, 0x8379, 0x5102, 0x837A, + 0x5103, 0x837B, 0x5104, 0x837C, 0x5105, 0x837D, 0x5106, 0xD9D3, + 0x5107, 0xD9D8, 0x5108, 0x837E, 0x5109, 0x8380, 0x510A, 0x8381, + 0x510B, 0xD9D9, 0x510C, 0x8382, 0x510D, 0x8383, 0x510E, 0x8384, + 0x510F, 0x8385, 0x5110, 0x8386, 0x5111, 0x8387, 0x5112, 0xC8E5, + 0x5113, 0x8388, 0x5114, 0x8389, 0x5115, 0x838A, 0x5116, 0x838B, + 0x5117, 0x838C, 0x5118, 0x838D, 0x5119, 0x838E, 0x511A, 0x838F, + 0x511B, 0x8390, 0x511C, 0x8391, 0x511D, 0x8392, 0x511E, 0x8393, + 0x511F, 0x8394, 0x5120, 0x8395, 0x5121, 0xC0DC, 0x5122, 0x8396, + 0x5123, 0x8397, 0x5124, 0x8398, 0x5125, 0x8399, 0x5126, 0x839A, + 0x5127, 0x839B, 0x5128, 0x839C, 0x5129, 0x839D, 0x512A, 0x839E, + 0x512B, 0x839F, 0x512C, 0x83A0, 0x512D, 0x83A1, 0x512E, 0x83A2, + 0x512F, 0x83A3, 0x5130, 0x83A4, 0x5131, 0x83A5, 0x5132, 0x83A6, + 0x5133, 0x83A7, 0x5134, 0x83A8, 0x5135, 0x83A9, 0x5136, 0x83AA, + 0x5137, 0x83AB, 0x5138, 0x83AC, 0x5139, 0x83AD, 0x513A, 0x83AE, + 0x513B, 0x83AF, 0x513C, 0x83B0, 0x513D, 0x83B1, 0x513E, 0x83B2, + 0x513F, 0xB6F9, 0x5140, 0xD8A3, 0x5141, 0xD4CA, 0x5142, 0x83B3, + 0x5143, 0xD4AA, 0x5144, 0xD0D6, 0x5145, 0xB3E4, 0x5146, 0xD5D7, + 0x5147, 0x83B4, 0x5148, 0xCFC8, 0x5149, 0xB9E2, 0x514A, 0x83B5, + 0x514B, 0xBFCB, 0x514C, 0x83B6, 0x514D, 0xC3E2, 0x514E, 0x83B7, + 0x514F, 0x83B8, 0x5150, 0x83B9, 0x5151, 0xB6D2, 0x5152, 0x83BA, + 0x5153, 0x83BB, 0x5154, 0xCDC3, 0x5155, 0xD9EE, 0x5156, 0xD9F0, + 0x5157, 0x83BC, 0x5158, 0x83BD, 0x5159, 0x83BE, 0x515A, 0xB5B3, + 0x515B, 0x83BF, 0x515C, 0xB6B5, 0x515D, 0x83C0, 0x515E, 0x83C1, + 0x515F, 0x83C2, 0x5160, 0x83C3, 0x5161, 0x83C4, 0x5162, 0xBEA4, + 0x5163, 0x83C5, 0x5164, 0x83C6, 0x5165, 0xC8EB, 0x5166, 0x83C7, + 0x5167, 0x83C8, 0x5168, 0xC8AB, 0x5169, 0x83C9, 0x516A, 0x83CA, + 0x516B, 0xB0CB, 0x516C, 0xB9AB, 0x516D, 0xC1F9, 0x516E, 0xD9E2, + 0x516F, 0x83CB, 0x5170, 0xC0BC, 0x5171, 0xB9B2, 0x5172, 0x83CC, + 0x5173, 0xB9D8, 0x5174, 0xD0CB, 0x5175, 0xB1F8, 0x5176, 0xC6E4, + 0x5177, 0xBEDF, 0x5178, 0xB5E4, 0x5179, 0xD7C8, 0x517A, 0x83CD, + 0x517B, 0xD1F8, 0x517C, 0xBCE6, 0x517D, 0xCADE, 0x517E, 0x83CE, + 0x517F, 0x83CF, 0x5180, 0xBCBD, 0x5181, 0xD9E6, 0x5182, 0xD8E7, + 0x5183, 0x83D0, 0x5184, 0x83D1, 0x5185, 0xC4DA, 0x5186, 0x83D2, + 0x5187, 0x83D3, 0x5188, 0xB8D4, 0x5189, 0xC8BD, 0x518A, 0x83D4, + 0x518B, 0x83D5, 0x518C, 0xB2E1, 0x518D, 0xD4D9, 0x518E, 0x83D6, + 0x518F, 0x83D7, 0x5190, 0x83D8, 0x5191, 0x83D9, 0x5192, 0xC3B0, + 0x5193, 0x83DA, 0x5194, 0x83DB, 0x5195, 0xC3E1, 0x5196, 0xDAA2, + 0x5197, 0xC8DF, 0x5198, 0x83DC, 0x5199, 0xD0B4, 0x519A, 0x83DD, + 0x519B, 0xBEFC, 0x519C, 0xC5A9, 0x519D, 0x83DE, 0x519E, 0x83DF, + 0x519F, 0x83E0, 0x51A0, 0xB9DA, 0x51A1, 0x83E1, 0x51A2, 0xDAA3, + 0x51A3, 0x83E2, 0x51A4, 0xD4A9, 0x51A5, 0xDAA4, 0x51A6, 0x83E3, + 0x51A7, 0x83E4, 0x51A8, 0x83E5, 0x51A9, 0x83E6, 0x51AA, 0x83E7, + 0x51AB, 0xD9FB, 0x51AC, 0xB6AC, 0x51AD, 0x83E8, 0x51AE, 0x83E9, + 0x51AF, 0xB7EB, 0x51B0, 0xB1F9, 0x51B1, 0xD9FC, 0x51B2, 0xB3E5, + 0x51B3, 0xBEF6, 0x51B4, 0x83EA, 0x51B5, 0xBFF6, 0x51B6, 0xD2B1, + 0x51B7, 0xC0E4, 0x51B8, 0x83EB, 0x51B9, 0x83EC, 0x51BA, 0x83ED, + 0x51BB, 0xB6B3, 0x51BC, 0xD9FE, 0x51BD, 0xD9FD, 0x51BE, 0x83EE, + 0x51BF, 0x83EF, 0x51C0, 0xBEBB, 0x51C1, 0x83F0, 0x51C2, 0x83F1, + 0x51C3, 0x83F2, 0x51C4, 0xC6E0, 0x51C5, 0x83F3, 0x51C6, 0xD7BC, + 0x51C7, 0xDAA1, 0x51C8, 0x83F4, 0x51C9, 0xC1B9, 0x51CA, 0x83F5, + 0x51CB, 0xB5F2, 0x51CC, 0xC1E8, 0x51CD, 0x83F6, 0x51CE, 0x83F7, + 0x51CF, 0xBCF5, 0x51D0, 0x83F8, 0x51D1, 0xB4D5, 0x51D2, 0x83F9, + 0x51D3, 0x83FA, 0x51D4, 0x83FB, 0x51D5, 0x83FC, 0x51D6, 0x83FD, + 0x51D7, 0x83FE, 0x51D8, 0x8440, 0x51D9, 0x8441, 0x51DA, 0x8442, + 0x51DB, 0xC1DD, 0x51DC, 0x8443, 0x51DD, 0xC4FD, 0x51DE, 0x8444, + 0x51DF, 0x8445, 0x51E0, 0xBCB8, 0x51E1, 0xB7B2, 0x51E2, 0x8446, + 0x51E3, 0x8447, 0x51E4, 0xB7EF, 0x51E5, 0x8448, 0x51E6, 0x8449, + 0x51E7, 0x844A, 0x51E8, 0x844B, 0x51E9, 0x844C, 0x51EA, 0x844D, + 0x51EB, 0xD9EC, 0x51EC, 0x844E, 0x51ED, 0xC6BE, 0x51EE, 0x844F, + 0x51EF, 0xBFAD, 0x51F0, 0xBBCB, 0x51F1, 0x8450, 0x51F2, 0x8451, + 0x51F3, 0xB5CA, 0x51F4, 0x8452, 0x51F5, 0xDBC9, 0x51F6, 0xD0D7, + 0x51F7, 0x8453, 0x51F8, 0xCDB9, 0x51F9, 0xB0BC, 0x51FA, 0xB3F6, + 0x51FB, 0xBBF7, 0x51FC, 0xDBCA, 0x51FD, 0xBAAF, 0x51FE, 0x8454, + 0x51FF, 0xD4E4, 0x5200, 0xB5B6, 0x5201, 0xB5F3, 0x5202, 0xD8D6, + 0x5203, 0xC8D0, 0x5204, 0x8455, 0x5205, 0x8456, 0x5206, 0xB7D6, + 0x5207, 0xC7D0, 0x5208, 0xD8D7, 0x5209, 0x8457, 0x520A, 0xBFAF, + 0x520B, 0x8458, 0x520C, 0x8459, 0x520D, 0xDBBB, 0x520E, 0xD8D8, + 0x520F, 0x845A, 0x5210, 0x845B, 0x5211, 0xD0CC, 0x5212, 0xBBAE, + 0x5213, 0x845C, 0x5214, 0x845D, 0x5215, 0x845E, 0x5216, 0xEBBE, + 0x5217, 0xC1D0, 0x5218, 0xC1F5, 0x5219, 0xD4F2, 0x521A, 0xB8D5, + 0x521B, 0xB4B4, 0x521C, 0x845F, 0x521D, 0xB3F5, 0x521E, 0x8460, + 0x521F, 0x8461, 0x5220, 0xC9BE, 0x5221, 0x8462, 0x5222, 0x8463, + 0x5223, 0x8464, 0x5224, 0xC5D0, 0x5225, 0x8465, 0x5226, 0x8466, + 0x5227, 0x8467, 0x5228, 0xC5D9, 0x5229, 0xC0FB, 0x522A, 0x8468, + 0x522B, 0xB1F0, 0x522C, 0x8469, 0x522D, 0xD8D9, 0x522E, 0xB9CE, + 0x522F, 0x846A, 0x5230, 0xB5BD, 0x5231, 0x846B, 0x5232, 0x846C, + 0x5233, 0xD8DA, 0x5234, 0x846D, 0x5235, 0x846E, 0x5236, 0xD6C6, + 0x5237, 0xCBA2, 0x5238, 0xC8AF, 0x5239, 0xC9B2, 0x523A, 0xB4CC, + 0x523B, 0xBFCC, 0x523C, 0x846F, 0x523D, 0xB9F4, 0x523E, 0x8470, + 0x523F, 0xD8DB, 0x5240, 0xD8DC, 0x5241, 0xB6E7, 0x5242, 0xBCC1, + 0x5243, 0xCCEA, 0x5244, 0x8471, 0x5245, 0x8472, 0x5246, 0x8473, + 0x5247, 0x8474, 0x5248, 0x8475, 0x5249, 0x8476, 0x524A, 0xCFF7, + 0x524B, 0x8477, 0x524C, 0xD8DD, 0x524D, 0xC7B0, 0x524E, 0x8478, + 0x524F, 0x8479, 0x5250, 0xB9D0, 0x5251, 0xBDA3, 0x5252, 0x847A, + 0x5253, 0x847B, 0x5254, 0xCCDE, 0x5255, 0x847C, 0x5256, 0xC6CA, + 0x5257, 0x847D, 0x5258, 0x847E, 0x5259, 0x8480, 0x525A, 0x8481, + 0x525B, 0x8482, 0x525C, 0xD8E0, 0x525D, 0x8483, 0x525E, 0xD8DE, + 0x525F, 0x8484, 0x5260, 0x8485, 0x5261, 0xD8DF, 0x5262, 0x8486, + 0x5263, 0x8487, 0x5264, 0x8488, 0x5265, 0xB0FE, 0x5266, 0x8489, + 0x5267, 0xBEE7, 0x5268, 0x848A, 0x5269, 0xCAA3, 0x526A, 0xBCF4, + 0x526B, 0x848B, 0x526C, 0x848C, 0x526D, 0x848D, 0x526E, 0x848E, + 0x526F, 0xB8B1, 0x5270, 0x848F, 0x5271, 0x8490, 0x5272, 0xB8EE, + 0x5273, 0x8491, 0x5274, 0x8492, 0x5275, 0x8493, 0x5276, 0x8494, + 0x5277, 0x8495, 0x5278, 0x8496, 0x5279, 0x8497, 0x527A, 0x8498, + 0x527B, 0x8499, 0x527C, 0x849A, 0x527D, 0xD8E2, 0x527E, 0x849B, + 0x527F, 0xBDCB, 0x5280, 0x849C, 0x5281, 0xD8E4, 0x5282, 0xD8E3, + 0x5283, 0x849D, 0x5284, 0x849E, 0x5285, 0x849F, 0x5286, 0x84A0, + 0x5287, 0x84A1, 0x5288, 0xC5FC, 0x5289, 0x84A2, 0x528A, 0x84A3, + 0x528B, 0x84A4, 0x528C, 0x84A5, 0x528D, 0x84A6, 0x528E, 0x84A7, + 0x528F, 0x84A8, 0x5290, 0xD8E5, 0x5291, 0x84A9, 0x5292, 0x84AA, + 0x5293, 0xD8E6, 0x5294, 0x84AB, 0x5295, 0x84AC, 0x5296, 0x84AD, + 0x5297, 0x84AE, 0x5298, 0x84AF, 0x5299, 0x84B0, 0x529A, 0x84B1, + 0x529B, 0xC1A6, 0x529C, 0x84B2, 0x529D, 0xC8B0, 0x529E, 0xB0EC, + 0x529F, 0xB9A6, 0x52A0, 0xBCD3, 0x52A1, 0xCEF1, 0x52A2, 0xDBBD, + 0x52A3, 0xC1D3, 0x52A4, 0x84B3, 0x52A5, 0x84B4, 0x52A6, 0x84B5, + 0x52A7, 0x84B6, 0x52A8, 0xB6AF, 0x52A9, 0xD6FA, 0x52AA, 0xC5AC, + 0x52AB, 0xBDD9, 0x52AC, 0xDBBE, 0x52AD, 0xDBBF, 0x52AE, 0x84B7, + 0x52AF, 0x84B8, 0x52B0, 0x84B9, 0x52B1, 0xC0F8, 0x52B2, 0xBEA2, + 0x52B3, 0xC0CD, 0x52B4, 0x84BA, 0x52B5, 0x84BB, 0x52B6, 0x84BC, + 0x52B7, 0x84BD, 0x52B8, 0x84BE, 0x52B9, 0x84BF, 0x52BA, 0x84C0, + 0x52BB, 0x84C1, 0x52BC, 0x84C2, 0x52BD, 0x84C3, 0x52BE, 0xDBC0, + 0x52BF, 0xCAC6, 0x52C0, 0x84C4, 0x52C1, 0x84C5, 0x52C2, 0x84C6, + 0x52C3, 0xB2AA, 0x52C4, 0x84C7, 0x52C5, 0x84C8, 0x52C6, 0x84C9, + 0x52C7, 0xD3C2, 0x52C8, 0x84CA, 0x52C9, 0xC3E3, 0x52CA, 0x84CB, + 0x52CB, 0xD1AB, 0x52CC, 0x84CC, 0x52CD, 0x84CD, 0x52CE, 0x84CE, + 0x52CF, 0x84CF, 0x52D0, 0xDBC2, 0x52D1, 0x84D0, 0x52D2, 0xC0D5, + 0x52D3, 0x84D1, 0x52D4, 0x84D2, 0x52D5, 0x84D3, 0x52D6, 0xDBC3, + 0x52D7, 0x84D4, 0x52D8, 0xBFB1, 0x52D9, 0x84D5, 0x52DA, 0x84D6, + 0x52DB, 0x84D7, 0x52DC, 0x84D8, 0x52DD, 0x84D9, 0x52DE, 0x84DA, + 0x52DF, 0xC4BC, 0x52E0, 0x84DB, 0x52E1, 0x84DC, 0x52E2, 0x84DD, + 0x52E3, 0x84DE, 0x52E4, 0xC7DA, 0x52E5, 0x84DF, 0x52E6, 0x84E0, + 0x52E7, 0x84E1, 0x52E8, 0x84E2, 0x52E9, 0x84E3, 0x52EA, 0x84E4, + 0x52EB, 0x84E5, 0x52EC, 0x84E6, 0x52ED, 0x84E7, 0x52EE, 0x84E8, + 0x52EF, 0x84E9, 0x52F0, 0xDBC4, 0x52F1, 0x84EA, 0x52F2, 0x84EB, + 0x52F3, 0x84EC, 0x52F4, 0x84ED, 0x52F5, 0x84EE, 0x52F6, 0x84EF, + 0x52F7, 0x84F0, 0x52F8, 0x84F1, 0x52F9, 0xD9E8, 0x52FA, 0xC9D7, + 0x52FB, 0x84F2, 0x52FC, 0x84F3, 0x52FD, 0x84F4, 0x52FE, 0xB9B4, + 0x52FF, 0xCEF0, 0x5300, 0xD4C8, 0x5301, 0x84F5, 0x5302, 0x84F6, + 0x5303, 0x84F7, 0x5304, 0x84F8, 0x5305, 0xB0FC, 0x5306, 0xB4D2, + 0x5307, 0x84F9, 0x5308, 0xD0D9, 0x5309, 0x84FA, 0x530A, 0x84FB, + 0x530B, 0x84FC, 0x530C, 0x84FD, 0x530D, 0xD9E9, 0x530E, 0x84FE, + 0x530F, 0xDECB, 0x5310, 0xD9EB, 0x5311, 0x8540, 0x5312, 0x8541, + 0x5313, 0x8542, 0x5314, 0x8543, 0x5315, 0xD8B0, 0x5316, 0xBBAF, + 0x5317, 0xB1B1, 0x5318, 0x8544, 0x5319, 0xB3D7, 0x531A, 0xD8CE, + 0x531B, 0x8545, 0x531C, 0x8546, 0x531D, 0xD4D1, 0x531E, 0x8547, + 0x531F, 0x8548, 0x5320, 0xBDB3, 0x5321, 0xBFEF, 0x5322, 0x8549, + 0x5323, 0xCFBB, 0x5324, 0x854A, 0x5325, 0x854B, 0x5326, 0xD8D0, + 0x5327, 0x854C, 0x5328, 0x854D, 0x5329, 0x854E, 0x532A, 0xB7CB, + 0x532B, 0x854F, 0x532C, 0x8550, 0x532D, 0x8551, 0x532E, 0xD8D1, + 0x532F, 0x8552, 0x5330, 0x8553, 0x5331, 0x8554, 0x5332, 0x8555, + 0x5333, 0x8556, 0x5334, 0x8557, 0x5335, 0x8558, 0x5336, 0x8559, + 0x5337, 0x855A, 0x5338, 0x855B, 0x5339, 0xC6A5, 0x533A, 0xC7F8, + 0x533B, 0xD2BD, 0x533C, 0x855C, 0x533D, 0x855D, 0x533E, 0xD8D2, + 0x533F, 0xC4E4, 0x5340, 0x855E, 0x5341, 0xCAAE, 0x5342, 0x855F, + 0x5343, 0xC7A7, 0x5344, 0x8560, 0x5345, 0xD8A6, 0x5346, 0x8561, + 0x5347, 0xC9FD, 0x5348, 0xCEE7, 0x5349, 0xBBDC, 0x534A, 0xB0EB, + 0x534B, 0x8562, 0x534C, 0x8563, 0x534D, 0x8564, 0x534E, 0xBBAA, + 0x534F, 0xD0AD, 0x5350, 0x8565, 0x5351, 0xB1B0, 0x5352, 0xD7E4, + 0x5353, 0xD7BF, 0x5354, 0x8566, 0x5355, 0xB5A5, 0x5356, 0xC2F4, + 0x5357, 0xC4CF, 0x5358, 0x8567, 0x5359, 0x8568, 0x535A, 0xB2A9, + 0x535B, 0x8569, 0x535C, 0xB2B7, 0x535D, 0x856A, 0x535E, 0xB1E5, + 0x535F, 0xDFB2, 0x5360, 0xD5BC, 0x5361, 0xBFA8, 0x5362, 0xC2AC, + 0x5363, 0xD8D5, 0x5364, 0xC2B1, 0x5365, 0x856B, 0x5366, 0xD8D4, + 0x5367, 0xCED4, 0x5368, 0x856C, 0x5369, 0xDAE0, 0x536A, 0x856D, + 0x536B, 0xCEC0, 0x536C, 0x856E, 0x536D, 0x856F, 0x536E, 0xD8B4, + 0x536F, 0xC3AE, 0x5370, 0xD3A1, 0x5371, 0xCEA3, 0x5372, 0x8570, + 0x5373, 0xBCB4, 0x5374, 0xC8B4, 0x5375, 0xC2D1, 0x5376, 0x8571, + 0x5377, 0xBEED, 0x5378, 0xD0B6, 0x5379, 0x8572, 0x537A, 0xDAE1, + 0x537B, 0x8573, 0x537C, 0x8574, 0x537D, 0x8575, 0x537E, 0x8576, + 0x537F, 0xC7E4, 0x5380, 0x8577, 0x5381, 0x8578, 0x5382, 0xB3A7, + 0x5383, 0x8579, 0x5384, 0xB6F2, 0x5385, 0xCCFC, 0x5386, 0xC0FA, + 0x5387, 0x857A, 0x5388, 0x857B, 0x5389, 0xC0F7, 0x538A, 0x857C, + 0x538B, 0xD1B9, 0x538C, 0xD1E1, 0x538D, 0xD8C7, 0x538E, 0x857D, + 0x538F, 0x857E, 0x5390, 0x8580, 0x5391, 0x8581, 0x5392, 0x8582, + 0x5393, 0x8583, 0x5394, 0x8584, 0x5395, 0xB2DE, 0x5396, 0x8585, + 0x5397, 0x8586, 0x5398, 0xC0E5, 0x5399, 0x8587, 0x539A, 0xBAF1, + 0x539B, 0x8588, 0x539C, 0x8589, 0x539D, 0xD8C8, 0x539E, 0x858A, + 0x539F, 0xD4AD, 0x53A0, 0x858B, 0x53A1, 0x858C, 0x53A2, 0xCFE1, + 0x53A3, 0xD8C9, 0x53A4, 0x858D, 0x53A5, 0xD8CA, 0x53A6, 0xCFC3, + 0x53A7, 0x858E, 0x53A8, 0xB3F8, 0x53A9, 0xBEC7, 0x53AA, 0x858F, + 0x53AB, 0x8590, 0x53AC, 0x8591, 0x53AD, 0x8592, 0x53AE, 0xD8CB, + 0x53AF, 0x8593, 0x53B0, 0x8594, 0x53B1, 0x8595, 0x53B2, 0x8596, + 0x53B3, 0x8597, 0x53B4, 0x8598, 0x53B5, 0x8599, 0x53B6, 0xDBCC, + 0x53B7, 0x859A, 0x53B8, 0x859B, 0x53B9, 0x859C, 0x53BA, 0x859D, + 0x53BB, 0xC8A5, 0x53BC, 0x859E, 0x53BD, 0x859F, 0x53BE, 0x85A0, + 0x53BF, 0xCFD8, 0x53C0, 0x85A1, 0x53C1, 0xC8FE, 0x53C2, 0xB2CE, + 0x53C3, 0x85A2, 0x53C4, 0x85A3, 0x53C5, 0x85A4, 0x53C6, 0x85A5, + 0x53C7, 0x85A6, 0x53C8, 0xD3D6, 0x53C9, 0xB2E6, 0x53CA, 0xBCB0, + 0x53CB, 0xD3D1, 0x53CC, 0xCBAB, 0x53CD, 0xB7B4, 0x53CE, 0x85A7, + 0x53CF, 0x85A8, 0x53D0, 0x85A9, 0x53D1, 0xB7A2, 0x53D2, 0x85AA, + 0x53D3, 0x85AB, 0x53D4, 0xCAE5, 0x53D5, 0x85AC, 0x53D6, 0xC8A1, + 0x53D7, 0xCADC, 0x53D8, 0xB1E4, 0x53D9, 0xD0F0, 0x53DA, 0x85AD, + 0x53DB, 0xC5D1, 0x53DC, 0x85AE, 0x53DD, 0x85AF, 0x53DE, 0x85B0, + 0x53DF, 0xDBC5, 0x53E0, 0xB5FE, 0x53E1, 0x85B1, 0x53E2, 0x85B2, + 0x53E3, 0xBFDA, 0x53E4, 0xB9C5, 0x53E5, 0xBEE4, 0x53E6, 0xC1ED, + 0x53E7, 0x85B3, 0x53E8, 0xDFB6, 0x53E9, 0xDFB5, 0x53EA, 0xD6BB, + 0x53EB, 0xBDD0, 0x53EC, 0xD5D9, 0x53ED, 0xB0C8, 0x53EE, 0xB6A3, + 0x53EF, 0xBFC9, 0x53F0, 0xCCA8, 0x53F1, 0xDFB3, 0x53F2, 0xCAB7, + 0x53F3, 0xD3D2, 0x53F4, 0x85B4, 0x53F5, 0xD8CF, 0x53F6, 0xD2B6, + 0x53F7, 0xBAC5, 0x53F8, 0xCBBE, 0x53F9, 0xCCBE, 0x53FA, 0x85B5, + 0x53FB, 0xDFB7, 0x53FC, 0xB5F0, 0x53FD, 0xDFB4, 0x53FE, 0x85B6, + 0x53FF, 0x85B7, 0x5400, 0x85B8, 0x5401, 0xD3F5, 0x5402, 0x85B9, + 0x5403, 0xB3D4, 0x5404, 0xB8F7, 0x5405, 0x85BA, 0x5406, 0xDFBA, + 0x5407, 0x85BB, 0x5408, 0xBACF, 0x5409, 0xBCAA, 0x540A, 0xB5F5, + 0x540B, 0x85BC, 0x540C, 0xCDAC, 0x540D, 0xC3FB, 0x540E, 0xBAF3, + 0x540F, 0xC0F4, 0x5410, 0xCDC2, 0x5411, 0xCFF2, 0x5412, 0xDFB8, + 0x5413, 0xCFC5, 0x5414, 0x85BD, 0x5415, 0xC2C0, 0x5416, 0xDFB9, + 0x5417, 0xC2F0, 0x5418, 0x85BE, 0x5419, 0x85BF, 0x541A, 0x85C0, + 0x541B, 0xBEFD, 0x541C, 0x85C1, 0x541D, 0xC1DF, 0x541E, 0xCDCC, + 0x541F, 0xD2F7, 0x5420, 0xB7CD, 0x5421, 0xDFC1, 0x5422, 0x85C2, + 0x5423, 0xDFC4, 0x5424, 0x85C3, 0x5425, 0x85C4, 0x5426, 0xB7F1, + 0x5427, 0xB0C9, 0x5428, 0xB6D6, 0x5429, 0xB7D4, 0x542A, 0x85C5, + 0x542B, 0xBAAC, 0x542C, 0xCCFD, 0x542D, 0xBFD4, 0x542E, 0xCBB1, + 0x542F, 0xC6F4, 0x5430, 0x85C6, 0x5431, 0xD6A8, 0x5432, 0xDFC5, + 0x5433, 0x85C7, 0x5434, 0xCEE2, 0x5435, 0xB3B3, 0x5436, 0x85C8, + 0x5437, 0x85C9, 0x5438, 0xCEFC, 0x5439, 0xB4B5, 0x543A, 0x85CA, + 0x543B, 0xCEC7, 0x543C, 0xBAF0, 0x543D, 0x85CB, 0x543E, 0xCEE1, + 0x543F, 0x85CC, 0x5440, 0xD1BD, 0x5441, 0x85CD, 0x5442, 0x85CE, + 0x5443, 0xDFC0, 0x5444, 0x85CF, 0x5445, 0x85D0, 0x5446, 0xB4F4, + 0x5447, 0x85D1, 0x5448, 0xB3CA, 0x5449, 0x85D2, 0x544A, 0xB8E6, + 0x544B, 0xDFBB, 0x544C, 0x85D3, 0x544D, 0x85D4, 0x544E, 0x85D5, + 0x544F, 0x85D6, 0x5450, 0xC4C5, 0x5451, 0x85D7, 0x5452, 0xDFBC, + 0x5453, 0xDFBD, 0x5454, 0xDFBE, 0x5455, 0xC5BB, 0x5456, 0xDFBF, + 0x5457, 0xDFC2, 0x5458, 0xD4B1, 0x5459, 0xDFC3, 0x545A, 0x85D8, + 0x545B, 0xC7BA, 0x545C, 0xCED8, 0x545D, 0x85D9, 0x545E, 0x85DA, + 0x545F, 0x85DB, 0x5460, 0x85DC, 0x5461, 0x85DD, 0x5462, 0xC4D8, + 0x5463, 0x85DE, 0x5464, 0xDFCA, 0x5465, 0x85DF, 0x5466, 0xDFCF, + 0x5467, 0x85E0, 0x5468, 0xD6DC, 0x5469, 0x85E1, 0x546A, 0x85E2, + 0x546B, 0x85E3, 0x546C, 0x85E4, 0x546D, 0x85E5, 0x546E, 0x85E6, + 0x546F, 0x85E7, 0x5470, 0x85E8, 0x5471, 0xDFC9, 0x5472, 0xDFDA, + 0x5473, 0xCEB6, 0x5474, 0x85E9, 0x5475, 0xBAC7, 0x5476, 0xDFCE, + 0x5477, 0xDFC8, 0x5478, 0xC5DE, 0x5479, 0x85EA, 0x547A, 0x85EB, + 0x547B, 0xC9EB, 0x547C, 0xBAF4, 0x547D, 0xC3FC, 0x547E, 0x85EC, + 0x547F, 0x85ED, 0x5480, 0xBED7, 0x5481, 0x85EE, 0x5482, 0xDFC6, + 0x5483, 0x85EF, 0x5484, 0xDFCD, 0x5485, 0x85F0, 0x5486, 0xC5D8, + 0x5487, 0x85F1, 0x5488, 0x85F2, 0x5489, 0x85F3, 0x548A, 0x85F4, + 0x548B, 0xD5A6, 0x548C, 0xBACD, 0x548D, 0x85F5, 0x548E, 0xBECC, + 0x548F, 0xD3BD, 0x5490, 0xB8C0, 0x5491, 0x85F6, 0x5492, 0xD6E4, + 0x5493, 0x85F7, 0x5494, 0xDFC7, 0x5495, 0xB9BE, 0x5496, 0xBFA7, + 0x5497, 0x85F8, 0x5498, 0x85F9, 0x5499, 0xC1FC, 0x549A, 0xDFCB, + 0x549B, 0xDFCC, 0x549C, 0x85FA, 0x549D, 0xDFD0, 0x549E, 0x85FB, + 0x549F, 0x85FC, 0x54A0, 0x85FD, 0x54A1, 0x85FE, 0x54A2, 0x8640, + 0x54A3, 0xDFDB, 0x54A4, 0xDFE5, 0x54A5, 0x8641, 0x54A6, 0xDFD7, + 0x54A7, 0xDFD6, 0x54A8, 0xD7C9, 0x54A9, 0xDFE3, 0x54AA, 0xDFE4, + 0x54AB, 0xE5EB, 0x54AC, 0xD2A7, 0x54AD, 0xDFD2, 0x54AE, 0x8642, + 0x54AF, 0xBFA9, 0x54B0, 0x8643, 0x54B1, 0xD4DB, 0x54B2, 0x8644, + 0x54B3, 0xBFC8, 0x54B4, 0xDFD4, 0x54B5, 0x8645, 0x54B6, 0x8646, + 0x54B7, 0x8647, 0x54B8, 0xCFCC, 0x54B9, 0x8648, 0x54BA, 0x8649, + 0x54BB, 0xDFDD, 0x54BC, 0x864A, 0x54BD, 0xD1CA, 0x54BE, 0x864B, + 0x54BF, 0xDFDE, 0x54C0, 0xB0A7, 0x54C1, 0xC6B7, 0x54C2, 0xDFD3, + 0x54C3, 0x864C, 0x54C4, 0xBAE5, 0x54C5, 0x864D, 0x54C6, 0xB6DF, + 0x54C7, 0xCDDB, 0x54C8, 0xB9FE, 0x54C9, 0xD4D5, 0x54CA, 0x864E, + 0x54CB, 0x864F, 0x54CC, 0xDFDF, 0x54CD, 0xCFEC, 0x54CE, 0xB0A5, + 0x54CF, 0xDFE7, 0x54D0, 0xDFD1, 0x54D1, 0xD1C6, 0x54D2, 0xDFD5, + 0x54D3, 0xDFD8, 0x54D4, 0xDFD9, 0x54D5, 0xDFDC, 0x54D6, 0x8650, + 0x54D7, 0xBBA9, 0x54D8, 0x8651, 0x54D9, 0xDFE0, 0x54DA, 0xDFE1, + 0x54DB, 0x8652, 0x54DC, 0xDFE2, 0x54DD, 0xDFE6, 0x54DE, 0xDFE8, + 0x54DF, 0xD3B4, 0x54E0, 0x8653, 0x54E1, 0x8654, 0x54E2, 0x8655, + 0x54E3, 0x8656, 0x54E4, 0x8657, 0x54E5, 0xB8E7, 0x54E6, 0xC5B6, + 0x54E7, 0xDFEA, 0x54E8, 0xC9DA, 0x54E9, 0xC1A8, 0x54EA, 0xC4C4, + 0x54EB, 0x8658, 0x54EC, 0x8659, 0x54ED, 0xBFDE, 0x54EE, 0xCFF8, + 0x54EF, 0x865A, 0x54F0, 0x865B, 0x54F1, 0x865C, 0x54F2, 0xD5DC, + 0x54F3, 0xDFEE, 0x54F4, 0x865D, 0x54F5, 0x865E, 0x54F6, 0x865F, + 0x54F7, 0x8660, 0x54F8, 0x8661, 0x54F9, 0x8662, 0x54FA, 0xB2B8, + 0x54FB, 0x8663, 0x54FC, 0xBADF, 0x54FD, 0xDFEC, 0x54FE, 0x8664, + 0x54FF, 0xDBC1, 0x5500, 0x8665, 0x5501, 0xD1E4, 0x5502, 0x8666, + 0x5503, 0x8667, 0x5504, 0x8668, 0x5505, 0x8669, 0x5506, 0xCBF4, + 0x5507, 0xB4BD, 0x5508, 0x866A, 0x5509, 0xB0A6, 0x550A, 0x866B, + 0x550B, 0x866C, 0x550C, 0x866D, 0x550D, 0x866E, 0x550E, 0x866F, + 0x550F, 0xDFF1, 0x5510, 0xCCC6, 0x5511, 0xDFF2, 0x5512, 0x8670, + 0x5513, 0x8671, 0x5514, 0xDFED, 0x5515, 0x8672, 0x5516, 0x8673, + 0x5517, 0x8674, 0x5518, 0x8675, 0x5519, 0x8676, 0x551A, 0x8677, + 0x551B, 0xDFE9, 0x551C, 0x8678, 0x551D, 0x8679, 0x551E, 0x867A, + 0x551F, 0x867B, 0x5520, 0xDFEB, 0x5521, 0x867C, 0x5522, 0xDFEF, + 0x5523, 0xDFF0, 0x5524, 0xBBBD, 0x5525, 0x867D, 0x5526, 0x867E, + 0x5527, 0xDFF3, 0x5528, 0x8680, 0x5529, 0x8681, 0x552A, 0xDFF4, + 0x552B, 0x8682, 0x552C, 0xBBA3, 0x552D, 0x8683, 0x552E, 0xCADB, + 0x552F, 0xCEA8, 0x5530, 0xE0A7, 0x5531, 0xB3AA, 0x5532, 0x8684, + 0x5533, 0xE0A6, 0x5534, 0x8685, 0x5535, 0x8686, 0x5536, 0x8687, + 0x5537, 0xE0A1, 0x5538, 0x8688, 0x5539, 0x8689, 0x553A, 0x868A, + 0x553B, 0x868B, 0x553C, 0xDFFE, 0x553D, 0x868C, 0x553E, 0xCDD9, + 0x553F, 0xDFFC, 0x5540, 0x868D, 0x5541, 0xDFFA, 0x5542, 0x868E, + 0x5543, 0xBFD0, 0x5544, 0xD7C4, 0x5545, 0x868F, 0x5546, 0xC9CC, + 0x5547, 0x8690, 0x5548, 0x8691, 0x5549, 0xDFF8, 0x554A, 0xB0A1, + 0x554B, 0x8692, 0x554C, 0x8693, 0x554D, 0x8694, 0x554E, 0x8695, + 0x554F, 0x8696, 0x5550, 0xDFFD, 0x5551, 0x8697, 0x5552, 0x8698, + 0x5553, 0x8699, 0x5554, 0x869A, 0x5555, 0xDFFB, 0x5556, 0xE0A2, + 0x5557, 0x869B, 0x5558, 0x869C, 0x5559, 0x869D, 0x555A, 0x869E, + 0x555B, 0x869F, 0x555C, 0xE0A8, 0x555D, 0x86A0, 0x555E, 0x86A1, + 0x555F, 0x86A2, 0x5560, 0x86A3, 0x5561, 0xB7C8, 0x5562, 0x86A4, + 0x5563, 0x86A5, 0x5564, 0xC6A1, 0x5565, 0xC9B6, 0x5566, 0xC0B2, + 0x5567, 0xDFF5, 0x5568, 0x86A6, 0x5569, 0x86A7, 0x556A, 0xC5BE, + 0x556B, 0x86A8, 0x556C, 0xD8C4, 0x556D, 0xDFF9, 0x556E, 0xC4F6, + 0x556F, 0x86A9, 0x5570, 0x86AA, 0x5571, 0x86AB, 0x5572, 0x86AC, + 0x5573, 0x86AD, 0x5574, 0x86AE, 0x5575, 0xE0A3, 0x5576, 0xE0A4, + 0x5577, 0xE0A5, 0x5578, 0xD0A5, 0x5579, 0x86AF, 0x557A, 0x86B0, + 0x557B, 0xE0B4, 0x557C, 0xCCE4, 0x557D, 0x86B1, 0x557E, 0xE0B1, + 0x557F, 0x86B2, 0x5580, 0xBFA6, 0x5581, 0xE0AF, 0x5582, 0xCEB9, + 0x5583, 0xE0AB, 0x5584, 0xC9C6, 0x5585, 0x86B3, 0x5586, 0x86B4, + 0x5587, 0xC0AE, 0x5588, 0xE0AE, 0x5589, 0xBAED, 0x558A, 0xBAB0, + 0x558B, 0xE0A9, 0x558C, 0x86B5, 0x558D, 0x86B6, 0x558E, 0x86B7, + 0x558F, 0xDFF6, 0x5590, 0x86B8, 0x5591, 0xE0B3, 0x5592, 0x86B9, + 0x5593, 0x86BA, 0x5594, 0xE0B8, 0x5595, 0x86BB, 0x5596, 0x86BC, + 0x5597, 0x86BD, 0x5598, 0xB4AD, 0x5599, 0xE0B9, 0x559A, 0x86BE, + 0x559B, 0x86BF, 0x559C, 0xCFB2, 0x559D, 0xBAC8, 0x559E, 0x86C0, + 0x559F, 0xE0B0, 0x55A0, 0x86C1, 0x55A1, 0x86C2, 0x55A2, 0x86C3, + 0x55A3, 0x86C4, 0x55A4, 0x86C5, 0x55A5, 0x86C6, 0x55A6, 0x86C7, + 0x55A7, 0xD0FA, 0x55A8, 0x86C8, 0x55A9, 0x86C9, 0x55AA, 0x86CA, + 0x55AB, 0x86CB, 0x55AC, 0x86CC, 0x55AD, 0x86CD, 0x55AE, 0x86CE, + 0x55AF, 0x86CF, 0x55B0, 0x86D0, 0x55B1, 0xE0AC, 0x55B2, 0x86D1, + 0x55B3, 0xD4FB, 0x55B4, 0x86D2, 0x55B5, 0xDFF7, 0x55B6, 0x86D3, + 0x55B7, 0xC5E7, 0x55B8, 0x86D4, 0x55B9, 0xE0AD, 0x55BA, 0x86D5, + 0x55BB, 0xD3F7, 0x55BC, 0x86D6, 0x55BD, 0xE0B6, 0x55BE, 0xE0B7, + 0x55BF, 0x86D7, 0x55C0, 0x86D8, 0x55C1, 0x86D9, 0x55C2, 0x86DA, + 0x55C3, 0x86DB, 0x55C4, 0xE0C4, 0x55C5, 0xD0E1, 0x55C6, 0x86DC, + 0x55C7, 0x86DD, 0x55C8, 0x86DE, 0x55C9, 0xE0BC, 0x55CA, 0x86DF, + 0x55CB, 0x86E0, 0x55CC, 0xE0C9, 0x55CD, 0xE0CA, 0x55CE, 0x86E1, + 0x55CF, 0x86E2, 0x55D0, 0x86E3, 0x55D1, 0xE0BE, 0x55D2, 0xE0AA, + 0x55D3, 0xC9A4, 0x55D4, 0xE0C1, 0x55D5, 0x86E4, 0x55D6, 0xE0B2, + 0x55D7, 0x86E5, 0x55D8, 0x86E6, 0x55D9, 0x86E7, 0x55DA, 0x86E8, + 0x55DB, 0x86E9, 0x55DC, 0xCAC8, 0x55DD, 0xE0C3, 0x55DE, 0x86EA, + 0x55DF, 0xE0B5, 0x55E0, 0x86EB, 0x55E1, 0xCECB, 0x55E2, 0x86EC, + 0x55E3, 0xCBC3, 0x55E4, 0xE0CD, 0x55E5, 0xE0C6, 0x55E6, 0xE0C2, + 0x55E7, 0x86ED, 0x55E8, 0xE0CB, 0x55E9, 0x86EE, 0x55EA, 0xE0BA, + 0x55EB, 0xE0BF, 0x55EC, 0xE0C0, 0x55ED, 0x86EF, 0x55EE, 0x86F0, + 0x55EF, 0xE0C5, 0x55F0, 0x86F1, 0x55F1, 0x86F2, 0x55F2, 0xE0C7, + 0x55F3, 0xE0C8, 0x55F4, 0x86F3, 0x55F5, 0xE0CC, 0x55F6, 0x86F4, + 0x55F7, 0xE0BB, 0x55F8, 0x86F5, 0x55F9, 0x86F6, 0x55FA, 0x86F7, + 0x55FB, 0x86F8, 0x55FC, 0x86F9, 0x55FD, 0xCBD4, 0x55FE, 0xE0D5, + 0x55FF, 0x86FA, 0x5600, 0xE0D6, 0x5601, 0xE0D2, 0x5602, 0x86FB, + 0x5603, 0x86FC, 0x5604, 0x86FD, 0x5605, 0x86FE, 0x5606, 0x8740, + 0x5607, 0x8741, 0x5608, 0xE0D0, 0x5609, 0xBCCE, 0x560A, 0x8742, + 0x560B, 0x8743, 0x560C, 0xE0D1, 0x560D, 0x8744, 0x560E, 0xB8C2, + 0x560F, 0xD8C5, 0x5610, 0x8745, 0x5611, 0x8746, 0x5612, 0x8747, + 0x5613, 0x8748, 0x5614, 0x8749, 0x5615, 0x874A, 0x5616, 0x874B, + 0x5617, 0x874C, 0x5618, 0xD0EA, 0x5619, 0x874D, 0x561A, 0x874E, + 0x561B, 0xC2EF, 0x561C, 0x874F, 0x561D, 0x8750, 0x561E, 0xE0CF, + 0x561F, 0xE0BD, 0x5620, 0x8751, 0x5621, 0x8752, 0x5622, 0x8753, + 0x5623, 0xE0D4, 0x5624, 0xE0D3, 0x5625, 0x8754, 0x5626, 0x8755, + 0x5627, 0xE0D7, 0x5628, 0x8756, 0x5629, 0x8757, 0x562A, 0x8758, + 0x562B, 0x8759, 0x562C, 0xE0DC, 0x562D, 0xE0D8, 0x562E, 0x875A, + 0x562F, 0x875B, 0x5630, 0x875C, 0x5631, 0xD6F6, 0x5632, 0xB3B0, + 0x5633, 0x875D, 0x5634, 0xD7EC, 0x5635, 0x875E, 0x5636, 0xCBBB, + 0x5637, 0x875F, 0x5638, 0x8760, 0x5639, 0xE0DA, 0x563A, 0x8761, + 0x563B, 0xCEFB, 0x563C, 0x8762, 0x563D, 0x8763, 0x563E, 0x8764, + 0x563F, 0xBAD9, 0x5640, 0x8765, 0x5641, 0x8766, 0x5642, 0x8767, + 0x5643, 0x8768, 0x5644, 0x8769, 0x5645, 0x876A, 0x5646, 0x876B, + 0x5647, 0x876C, 0x5648, 0x876D, 0x5649, 0x876E, 0x564A, 0x876F, + 0x564B, 0x8770, 0x564C, 0xE0E1, 0x564D, 0xE0DD, 0x564E, 0xD2AD, + 0x564F, 0x8771, 0x5650, 0x8772, 0x5651, 0x8773, 0x5652, 0x8774, + 0x5653, 0x8775, 0x5654, 0xE0E2, 0x5655, 0x8776, 0x5656, 0x8777, + 0x5657, 0xE0DB, 0x5658, 0xE0D9, 0x5659, 0xE0DF, 0x565A, 0x8778, + 0x565B, 0x8779, 0x565C, 0xE0E0, 0x565D, 0x877A, 0x565E, 0x877B, + 0x565F, 0x877C, 0x5660, 0x877D, 0x5661, 0x877E, 0x5662, 0xE0DE, + 0x5663, 0x8780, 0x5664, 0xE0E4, 0x5665, 0x8781, 0x5666, 0x8782, + 0x5667, 0x8783, 0x5668, 0xC6F7, 0x5669, 0xD8AC, 0x566A, 0xD4EB, + 0x566B, 0xE0E6, 0x566C, 0xCAC9, 0x566D, 0x8784, 0x566E, 0x8785, + 0x566F, 0x8786, 0x5670, 0x8787, 0x5671, 0xE0E5, 0x5672, 0x8788, + 0x5673, 0x8789, 0x5674, 0x878A, 0x5675, 0x878B, 0x5676, 0xB8C1, + 0x5677, 0x878C, 0x5678, 0x878D, 0x5679, 0x878E, 0x567A, 0x878F, + 0x567B, 0xE0E7, 0x567C, 0xE0E8, 0x567D, 0x8790, 0x567E, 0x8791, + 0x567F, 0x8792, 0x5680, 0x8793, 0x5681, 0x8794, 0x5682, 0x8795, + 0x5683, 0x8796, 0x5684, 0x8797, 0x5685, 0xE0E9, 0x5686, 0xE0E3, + 0x5687, 0x8798, 0x5688, 0x8799, 0x5689, 0x879A, 0x568A, 0x879B, + 0x568B, 0x879C, 0x568C, 0x879D, 0x568D, 0x879E, 0x568E, 0xBABF, + 0x568F, 0xCCE7, 0x5690, 0x879F, 0x5691, 0x87A0, 0x5692, 0x87A1, + 0x5693, 0xE0EA, 0x5694, 0x87A2, 0x5695, 0x87A3, 0x5696, 0x87A4, + 0x5697, 0x87A5, 0x5698, 0x87A6, 0x5699, 0x87A7, 0x569A, 0x87A8, + 0x569B, 0x87A9, 0x569C, 0x87AA, 0x569D, 0x87AB, 0x569E, 0x87AC, + 0x569F, 0x87AD, 0x56A0, 0x87AE, 0x56A1, 0x87AF, 0x56A2, 0x87B0, + 0x56A3, 0xCFF9, 0x56A4, 0x87B1, 0x56A5, 0x87B2, 0x56A6, 0x87B3, + 0x56A7, 0x87B4, 0x56A8, 0x87B5, 0x56A9, 0x87B6, 0x56AA, 0x87B7, + 0x56AB, 0x87B8, 0x56AC, 0x87B9, 0x56AD, 0x87BA, 0x56AE, 0x87BB, + 0x56AF, 0xE0EB, 0x56B0, 0x87BC, 0x56B1, 0x87BD, 0x56B2, 0x87BE, + 0x56B3, 0x87BF, 0x56B4, 0x87C0, 0x56B5, 0x87C1, 0x56B6, 0x87C2, + 0x56B7, 0xC8C2, 0x56B8, 0x87C3, 0x56B9, 0x87C4, 0x56BA, 0x87C5, + 0x56BB, 0x87C6, 0x56BC, 0xBDC0, 0x56BD, 0x87C7, 0x56BE, 0x87C8, + 0x56BF, 0x87C9, 0x56C0, 0x87CA, 0x56C1, 0x87CB, 0x56C2, 0x87CC, + 0x56C3, 0x87CD, 0x56C4, 0x87CE, 0x56C5, 0x87CF, 0x56C6, 0x87D0, + 0x56C7, 0x87D1, 0x56C8, 0x87D2, 0x56C9, 0x87D3, 0x56CA, 0xC4D2, + 0x56CB, 0x87D4, 0x56CC, 0x87D5, 0x56CD, 0x87D6, 0x56CE, 0x87D7, + 0x56CF, 0x87D8, 0x56D0, 0x87D9, 0x56D1, 0x87DA, 0x56D2, 0x87DB, + 0x56D3, 0x87DC, 0x56D4, 0xE0EC, 0x56D5, 0x87DD, 0x56D6, 0x87DE, + 0x56D7, 0xE0ED, 0x56D8, 0x87DF, 0x56D9, 0x87E0, 0x56DA, 0xC7F4, + 0x56DB, 0xCBC4, 0x56DC, 0x87E1, 0x56DD, 0xE0EE, 0x56DE, 0xBBD8, + 0x56DF, 0xD8B6, 0x56E0, 0xD2F2, 0x56E1, 0xE0EF, 0x56E2, 0xCDC5, + 0x56E3, 0x87E2, 0x56E4, 0xB6DA, 0x56E5, 0x87E3, 0x56E6, 0x87E4, + 0x56E7, 0x87E5, 0x56E8, 0x87E6, 0x56E9, 0x87E7, 0x56EA, 0x87E8, + 0x56EB, 0xE0F1, 0x56EC, 0x87E9, 0x56ED, 0xD4B0, 0x56EE, 0x87EA, + 0x56EF, 0x87EB, 0x56F0, 0xC0A7, 0x56F1, 0xB4D1, 0x56F2, 0x87EC, + 0x56F3, 0x87ED, 0x56F4, 0xCEA7, 0x56F5, 0xE0F0, 0x56F6, 0x87EE, + 0x56F7, 0x87EF, 0x56F8, 0x87F0, 0x56F9, 0xE0F2, 0x56FA, 0xB9CC, + 0x56FB, 0x87F1, 0x56FC, 0x87F2, 0x56FD, 0xB9FA, 0x56FE, 0xCDBC, + 0x56FF, 0xE0F3, 0x5700, 0x87F3, 0x5701, 0x87F4, 0x5702, 0x87F5, + 0x5703, 0xC6D4, 0x5704, 0xE0F4, 0x5705, 0x87F6, 0x5706, 0xD4B2, + 0x5707, 0x87F7, 0x5708, 0xC8A6, 0x5709, 0xE0F6, 0x570A, 0xE0F5, + 0x570B, 0x87F8, 0x570C, 0x87F9, 0x570D, 0x87FA, 0x570E, 0x87FB, + 0x570F, 0x87FC, 0x5710, 0x87FD, 0x5711, 0x87FE, 0x5712, 0x8840, + 0x5713, 0x8841, 0x5714, 0x8842, 0x5715, 0x8843, 0x5716, 0x8844, + 0x5717, 0x8845, 0x5718, 0x8846, 0x5719, 0x8847, 0x571A, 0x8848, + 0x571B, 0x8849, 0x571C, 0xE0F7, 0x571D, 0x884A, 0x571E, 0x884B, + 0x571F, 0xCDC1, 0x5720, 0x884C, 0x5721, 0x884D, 0x5722, 0x884E, + 0x5723, 0xCAA5, 0x5724, 0x884F, 0x5725, 0x8850, 0x5726, 0x8851, + 0x5727, 0x8852, 0x5728, 0xD4DA, 0x5729, 0xDBD7, 0x572A, 0xDBD9, + 0x572B, 0x8853, 0x572C, 0xDBD8, 0x572D, 0xB9E7, 0x572E, 0xDBDC, + 0x572F, 0xDBDD, 0x5730, 0xB5D8, 0x5731, 0x8854, 0x5732, 0x8855, + 0x5733, 0xDBDA, 0x5734, 0x8856, 0x5735, 0x8857, 0x5736, 0x8858, + 0x5737, 0x8859, 0x5738, 0x885A, 0x5739, 0xDBDB, 0x573A, 0xB3A1, + 0x573B, 0xDBDF, 0x573C, 0x885B, 0x573D, 0x885C, 0x573E, 0xBBF8, + 0x573F, 0x885D, 0x5740, 0xD6B7, 0x5741, 0x885E, 0x5742, 0xDBE0, + 0x5743, 0x885F, 0x5744, 0x8860, 0x5745, 0x8861, 0x5746, 0x8862, + 0x5747, 0xBEF9, 0x5748, 0x8863, 0x5749, 0x8864, 0x574A, 0xB7BB, + 0x574B, 0x8865, 0x574C, 0xDBD0, 0x574D, 0xCCAE, 0x574E, 0xBFB2, + 0x574F, 0xBBB5, 0x5750, 0xD7F8, 0x5751, 0xBFD3, 0x5752, 0x8866, + 0x5753, 0x8867, 0x5754, 0x8868, 0x5755, 0x8869, 0x5756, 0x886A, + 0x5757, 0xBFE9, 0x5758, 0x886B, 0x5759, 0x886C, 0x575A, 0xBCE1, + 0x575B, 0xCCB3, 0x575C, 0xDBDE, 0x575D, 0xB0D3, 0x575E, 0xCEEB, + 0x575F, 0xB7D8, 0x5760, 0xD7B9, 0x5761, 0xC6C2, 0x5762, 0x886D, + 0x5763, 0x886E, 0x5764, 0xC0A4, 0x5765, 0x886F, 0x5766, 0xCCB9, + 0x5767, 0x8870, 0x5768, 0xDBE7, 0x5769, 0xDBE1, 0x576A, 0xC6BA, + 0x576B, 0xDBE3, 0x576C, 0x8871, 0x576D, 0xDBE8, 0x576E, 0x8872, + 0x576F, 0xC5F7, 0x5770, 0x8873, 0x5771, 0x8874, 0x5772, 0x8875, + 0x5773, 0xDBEA, 0x5774, 0x8876, 0x5775, 0x8877, 0x5776, 0xDBE9, + 0x5777, 0xBFC0, 0x5778, 0x8878, 0x5779, 0x8879, 0x577A, 0x887A, + 0x577B, 0xDBE6, 0x577C, 0xDBE5, 0x577D, 0x887B, 0x577E, 0x887C, + 0x577F, 0x887D, 0x5780, 0x887E, 0x5781, 0x8880, 0x5782, 0xB4B9, + 0x5783, 0xC0AC, 0x5784, 0xC2A2, 0x5785, 0xDBE2, 0x5786, 0xDBE4, + 0x5787, 0x8881, 0x5788, 0x8882, 0x5789, 0x8883, 0x578A, 0x8884, + 0x578B, 0xD0CD, 0x578C, 0xDBED, 0x578D, 0x8885, 0x578E, 0x8886, + 0x578F, 0x8887, 0x5790, 0x8888, 0x5791, 0x8889, 0x5792, 0xC0DD, + 0x5793, 0xDBF2, 0x5794, 0x888A, 0x5795, 0x888B, 0x5796, 0x888C, + 0x5797, 0x888D, 0x5798, 0x888E, 0x5799, 0x888F, 0x579A, 0x8890, + 0x579B, 0xB6E2, 0x579C, 0x8891, 0x579D, 0x8892, 0x579E, 0x8893, + 0x579F, 0x8894, 0x57A0, 0xDBF3, 0x57A1, 0xDBD2, 0x57A2, 0xB9B8, + 0x57A3, 0xD4AB, 0x57A4, 0xDBEC, 0x57A5, 0x8895, 0x57A6, 0xBFD1, + 0x57A7, 0xDBF0, 0x57A8, 0x8896, 0x57A9, 0xDBD1, 0x57AA, 0x8897, + 0x57AB, 0xB5E6, 0x57AC, 0x8898, 0x57AD, 0xDBEB, 0x57AE, 0xBFE5, + 0x57AF, 0x8899, 0x57B0, 0x889A, 0x57B1, 0x889B, 0x57B2, 0xDBEE, + 0x57B3, 0x889C, 0x57B4, 0xDBF1, 0x57B5, 0x889D, 0x57B6, 0x889E, + 0x57B7, 0x889F, 0x57B8, 0xDBF9, 0x57B9, 0x88A0, 0x57BA, 0x88A1, + 0x57BB, 0x88A2, 0x57BC, 0x88A3, 0x57BD, 0x88A4, 0x57BE, 0x88A5, + 0x57BF, 0x88A6, 0x57C0, 0x88A7, 0x57C1, 0x88A8, 0x57C2, 0xB9A1, + 0x57C3, 0xB0A3, 0x57C4, 0x88A9, 0x57C5, 0x88AA, 0x57C6, 0x88AB, + 0x57C7, 0x88AC, 0x57C8, 0x88AD, 0x57C9, 0x88AE, 0x57CA, 0x88AF, + 0x57CB, 0xC2F1, 0x57CC, 0x88B0, 0x57CD, 0x88B1, 0x57CE, 0xB3C7, + 0x57CF, 0xDBEF, 0x57D0, 0x88B2, 0x57D1, 0x88B3, 0x57D2, 0xDBF8, + 0x57D3, 0x88B4, 0x57D4, 0xC6D2, 0x57D5, 0xDBF4, 0x57D6, 0x88B5, + 0x57D7, 0x88B6, 0x57D8, 0xDBF5, 0x57D9, 0xDBF7, 0x57DA, 0xDBF6, + 0x57DB, 0x88B7, 0x57DC, 0x88B8, 0x57DD, 0xDBFE, 0x57DE, 0x88B9, + 0x57DF, 0xD3F2, 0x57E0, 0xB2BA, 0x57E1, 0x88BA, 0x57E2, 0x88BB, + 0x57E3, 0x88BC, 0x57E4, 0xDBFD, 0x57E5, 0x88BD, 0x57E6, 0x88BE, + 0x57E7, 0x88BF, 0x57E8, 0x88C0, 0x57E9, 0x88C1, 0x57EA, 0x88C2, + 0x57EB, 0x88C3, 0x57EC, 0x88C4, 0x57ED, 0xDCA4, 0x57EE, 0x88C5, + 0x57EF, 0xDBFB, 0x57F0, 0x88C6, 0x57F1, 0x88C7, 0x57F2, 0x88C8, + 0x57F3, 0x88C9, 0x57F4, 0xDBFA, 0x57F5, 0x88CA, 0x57F6, 0x88CB, + 0x57F7, 0x88CC, 0x57F8, 0xDBFC, 0x57F9, 0xC5E0, 0x57FA, 0xBBF9, + 0x57FB, 0x88CD, 0x57FC, 0x88CE, 0x57FD, 0xDCA3, 0x57FE, 0x88CF, + 0x57FF, 0x88D0, 0x5800, 0xDCA5, 0x5801, 0x88D1, 0x5802, 0xCCC3, + 0x5803, 0x88D2, 0x5804, 0x88D3, 0x5805, 0x88D4, 0x5806, 0xB6D1, + 0x5807, 0xDDC0, 0x5808, 0x88D5, 0x5809, 0x88D6, 0x580A, 0x88D7, + 0x580B, 0xDCA1, 0x580C, 0x88D8, 0x580D, 0xDCA2, 0x580E, 0x88D9, + 0x580F, 0x88DA, 0x5810, 0x88DB, 0x5811, 0xC7B5, 0x5812, 0x88DC, + 0x5813, 0x88DD, 0x5814, 0x88DE, 0x5815, 0xB6E9, 0x5816, 0x88DF, + 0x5817, 0x88E0, 0x5818, 0x88E1, 0x5819, 0xDCA7, 0x581A, 0x88E2, + 0x581B, 0x88E3, 0x581C, 0x88E4, 0x581D, 0x88E5, 0x581E, 0xDCA6, + 0x581F, 0x88E6, 0x5820, 0xDCA9, 0x5821, 0xB1A4, 0x5822, 0x88E7, + 0x5823, 0x88E8, 0x5824, 0xB5CC, 0x5825, 0x88E9, 0x5826, 0x88EA, + 0x5827, 0x88EB, 0x5828, 0x88EC, 0x5829, 0x88ED, 0x582A, 0xBFB0, + 0x582B, 0x88EE, 0x582C, 0x88EF, 0x582D, 0x88F0, 0x582E, 0x88F1, + 0x582F, 0x88F2, 0x5830, 0xD1DF, 0x5831, 0x88F3, 0x5832, 0x88F4, + 0x5833, 0x88F5, 0x5834, 0x88F6, 0x5835, 0xB6C2, 0x5836, 0x88F7, + 0x5837, 0x88F8, 0x5838, 0x88F9, 0x5839, 0x88FA, 0x583A, 0x88FB, + 0x583B, 0x88FC, 0x583C, 0x88FD, 0x583D, 0x88FE, 0x583E, 0x8940, + 0x583F, 0x8941, 0x5840, 0x8942, 0x5841, 0x8943, 0x5842, 0x8944, + 0x5843, 0x8945, 0x5844, 0xDCA8, 0x5845, 0x8946, 0x5846, 0x8947, + 0x5847, 0x8948, 0x5848, 0x8949, 0x5849, 0x894A, 0x584A, 0x894B, + 0x584B, 0x894C, 0x584C, 0xCBFA, 0x584D, 0xEBF3, 0x584E, 0x894D, + 0x584F, 0x894E, 0x5850, 0x894F, 0x5851, 0xCBDC, 0x5852, 0x8950, + 0x5853, 0x8951, 0x5854, 0xCBFE, 0x5855, 0x8952, 0x5856, 0x8953, + 0x5857, 0x8954, 0x5858, 0xCCC1, 0x5859, 0x8955, 0x585A, 0x8956, + 0x585B, 0x8957, 0x585C, 0x8958, 0x585D, 0x8959, 0x585E, 0xC8FB, + 0x585F, 0x895A, 0x5860, 0x895B, 0x5861, 0x895C, 0x5862, 0x895D, + 0x5863, 0x895E, 0x5864, 0x895F, 0x5865, 0xDCAA, 0x5866, 0x8960, + 0x5867, 0x8961, 0x5868, 0x8962, 0x5869, 0x8963, 0x586A, 0x8964, + 0x586B, 0xCCEE, 0x586C, 0xDCAB, 0x586D, 0x8965, 0x586E, 0x8966, + 0x586F, 0x8967, 0x5870, 0x8968, 0x5871, 0x8969, 0x5872, 0x896A, + 0x5873, 0x896B, 0x5874, 0x896C, 0x5875, 0x896D, 0x5876, 0x896E, + 0x5877, 0x896F, 0x5878, 0x8970, 0x5879, 0x8971, 0x587A, 0x8972, + 0x587B, 0x8973, 0x587C, 0x8974, 0x587D, 0x8975, 0x587E, 0xDBD3, + 0x587F, 0x8976, 0x5880, 0xDCAF, 0x5881, 0xDCAC, 0x5882, 0x8977, + 0x5883, 0xBEB3, 0x5884, 0x8978, 0x5885, 0xCAFB, 0x5886, 0x8979, + 0x5887, 0x897A, 0x5888, 0x897B, 0x5889, 0xDCAD, 0x588A, 0x897C, + 0x588B, 0x897D, 0x588C, 0x897E, 0x588D, 0x8980, 0x588E, 0x8981, + 0x588F, 0x8982, 0x5890, 0x8983, 0x5891, 0x8984, 0x5892, 0xC9CA, + 0x5893, 0xC4B9, 0x5894, 0x8985, 0x5895, 0x8986, 0x5896, 0x8987, + 0x5897, 0x8988, 0x5898, 0x8989, 0x5899, 0xC7BD, 0x589A, 0xDCAE, + 0x589B, 0x898A, 0x589C, 0x898B, 0x589D, 0x898C, 0x589E, 0xD4F6, + 0x589F, 0xD0E6, 0x58A0, 0x898D, 0x58A1, 0x898E, 0x58A2, 0x898F, + 0x58A3, 0x8990, 0x58A4, 0x8991, 0x58A5, 0x8992, 0x58A6, 0x8993, + 0x58A7, 0x8994, 0x58A8, 0xC4AB, 0x58A9, 0xB6D5, 0x58AA, 0x8995, + 0x58AB, 0x8996, 0x58AC, 0x8997, 0x58AD, 0x8998, 0x58AE, 0x8999, + 0x58AF, 0x899A, 0x58B0, 0x899B, 0x58B1, 0x899C, 0x58B2, 0x899D, + 0x58B3, 0x899E, 0x58B4, 0x899F, 0x58B5, 0x89A0, 0x58B6, 0x89A1, + 0x58B7, 0x89A2, 0x58B8, 0x89A3, 0x58B9, 0x89A4, 0x58BA, 0x89A5, + 0x58BB, 0x89A6, 0x58BC, 0xDBD4, 0x58BD, 0x89A7, 0x58BE, 0x89A8, + 0x58BF, 0x89A9, 0x58C0, 0x89AA, 0x58C1, 0xB1DA, 0x58C2, 0x89AB, + 0x58C3, 0x89AC, 0x58C4, 0x89AD, 0x58C5, 0xDBD5, 0x58C6, 0x89AE, + 0x58C7, 0x89AF, 0x58C8, 0x89B0, 0x58C9, 0x89B1, 0x58CA, 0x89B2, + 0x58CB, 0x89B3, 0x58CC, 0x89B4, 0x58CD, 0x89B5, 0x58CE, 0x89B6, + 0x58CF, 0x89B7, 0x58D0, 0x89B8, 0x58D1, 0xDBD6, 0x58D2, 0x89B9, + 0x58D3, 0x89BA, 0x58D4, 0x89BB, 0x58D5, 0xBABE, 0x58D6, 0x89BC, + 0x58D7, 0x89BD, 0x58D8, 0x89BE, 0x58D9, 0x89BF, 0x58DA, 0x89C0, + 0x58DB, 0x89C1, 0x58DC, 0x89C2, 0x58DD, 0x89C3, 0x58DE, 0x89C4, + 0x58DF, 0x89C5, 0x58E0, 0x89C6, 0x58E1, 0x89C7, 0x58E2, 0x89C8, + 0x58E3, 0x89C9, 0x58E4, 0xC8C0, 0x58E5, 0x89CA, 0x58E6, 0x89CB, + 0x58E7, 0x89CC, 0x58E8, 0x89CD, 0x58E9, 0x89CE, 0x58EA, 0x89CF, + 0x58EB, 0xCABF, 0x58EC, 0xC8C9, 0x58ED, 0x89D0, 0x58EE, 0xD7B3, + 0x58EF, 0x89D1, 0x58F0, 0xC9F9, 0x58F1, 0x89D2, 0x58F2, 0x89D3, + 0x58F3, 0xBFC7, 0x58F4, 0x89D4, 0x58F5, 0x89D5, 0x58F6, 0xBAF8, + 0x58F7, 0x89D6, 0x58F8, 0x89D7, 0x58F9, 0xD2BC, 0x58FA, 0x89D8, + 0x58FB, 0x89D9, 0x58FC, 0x89DA, 0x58FD, 0x89DB, 0x58FE, 0x89DC, + 0x58FF, 0x89DD, 0x5900, 0x89DE, 0x5901, 0x89DF, 0x5902, 0xE2BA, + 0x5903, 0x89E0, 0x5904, 0xB4A6, 0x5905, 0x89E1, 0x5906, 0x89E2, + 0x5907, 0xB1B8, 0x5908, 0x89E3, 0x5909, 0x89E4, 0x590A, 0x89E5, + 0x590B, 0x89E6, 0x590C, 0x89E7, 0x590D, 0xB8B4, 0x590E, 0x89E8, + 0x590F, 0xCFC4, 0x5910, 0x89E9, 0x5911, 0x89EA, 0x5912, 0x89EB, + 0x5913, 0x89EC, 0x5914, 0xD9E7, 0x5915, 0xCFA6, 0x5916, 0xCDE2, + 0x5917, 0x89ED, 0x5918, 0x89EE, 0x5919, 0xD9ED, 0x591A, 0xB6E0, + 0x591B, 0x89EF, 0x591C, 0xD2B9, 0x591D, 0x89F0, 0x591E, 0x89F1, + 0x591F, 0xB9BB, 0x5920, 0x89F2, 0x5921, 0x89F3, 0x5922, 0x89F4, + 0x5923, 0x89F5, 0x5924, 0xE2B9, 0x5925, 0xE2B7, 0x5926, 0x89F6, + 0x5927, 0xB4F3, 0x5928, 0x89F7, 0x5929, 0xCCEC, 0x592A, 0xCCAB, + 0x592B, 0xB7F2, 0x592C, 0x89F8, 0x592D, 0xD8B2, 0x592E, 0xD1EB, + 0x592F, 0xBABB, 0x5930, 0x89F9, 0x5931, 0xCAA7, 0x5932, 0x89FA, + 0x5933, 0x89FB, 0x5934, 0xCDB7, 0x5935, 0x89FC, 0x5936, 0x89FD, + 0x5937, 0xD2C4, 0x5938, 0xBFE4, 0x5939, 0xBCD0, 0x593A, 0xB6E1, + 0x593B, 0x89FE, 0x593C, 0xDEC5, 0x593D, 0x8A40, 0x593E, 0x8A41, + 0x593F, 0x8A42, 0x5940, 0x8A43, 0x5941, 0xDEC6, 0x5942, 0xDBBC, + 0x5943, 0x8A44, 0x5944, 0xD1D9, 0x5945, 0x8A45, 0x5946, 0x8A46, + 0x5947, 0xC6E6, 0x5948, 0xC4CE, 0x5949, 0xB7EE, 0x594A, 0x8A47, + 0x594B, 0xB7DC, 0x594C, 0x8A48, 0x594D, 0x8A49, 0x594E, 0xBFFC, + 0x594F, 0xD7E0, 0x5950, 0x8A4A, 0x5951, 0xC6F5, 0x5952, 0x8A4B, + 0x5953, 0x8A4C, 0x5954, 0xB1BC, 0x5955, 0xDEC8, 0x5956, 0xBDB1, + 0x5957, 0xCCD7, 0x5958, 0xDECA, 0x5959, 0x8A4D, 0x595A, 0xDEC9, + 0x595B, 0x8A4E, 0x595C, 0x8A4F, 0x595D, 0x8A50, 0x595E, 0x8A51, + 0x595F, 0x8A52, 0x5960, 0xB5EC, 0x5961, 0x8A53, 0x5962, 0xC9DD, + 0x5963, 0x8A54, 0x5964, 0x8A55, 0x5965, 0xB0C2, 0x5966, 0x8A56, + 0x5967, 0x8A57, 0x5968, 0x8A58, 0x5969, 0x8A59, 0x596A, 0x8A5A, + 0x596B, 0x8A5B, 0x596C, 0x8A5C, 0x596D, 0x8A5D, 0x596E, 0x8A5E, + 0x596F, 0x8A5F, 0x5970, 0x8A60, 0x5971, 0x8A61, 0x5972, 0x8A62, + 0x5973, 0xC5AE, 0x5974, 0xC5AB, 0x5975, 0x8A63, 0x5976, 0xC4CC, + 0x5977, 0x8A64, 0x5978, 0xBCE9, 0x5979, 0xCBFD, 0x597A, 0x8A65, + 0x597B, 0x8A66, 0x597C, 0x8A67, 0x597D, 0xBAC3, 0x597E, 0x8A68, + 0x597F, 0x8A69, 0x5980, 0x8A6A, 0x5981, 0xE5F9, 0x5982, 0xC8E7, + 0x5983, 0xE5FA, 0x5984, 0xCDFD, 0x5985, 0x8A6B, 0x5986, 0xD7B1, + 0x5987, 0xB8BE, 0x5988, 0xC2E8, 0x5989, 0x8A6C, 0x598A, 0xC8D1, + 0x598B, 0x8A6D, 0x598C, 0x8A6E, 0x598D, 0xE5FB, 0x598E, 0x8A6F, + 0x598F, 0x8A70, 0x5990, 0x8A71, 0x5991, 0x8A72, 0x5992, 0xB6CA, + 0x5993, 0xBCCB, 0x5994, 0x8A73, 0x5995, 0x8A74, 0x5996, 0xD1FD, + 0x5997, 0xE6A1, 0x5998, 0x8A75, 0x5999, 0xC3EE, 0x599A, 0x8A76, + 0x599B, 0x8A77, 0x599C, 0x8A78, 0x599D, 0x8A79, 0x599E, 0xE6A4, + 0x599F, 0x8A7A, 0x59A0, 0x8A7B, 0x59A1, 0x8A7C, 0x59A2, 0x8A7D, + 0x59A3, 0xE5FE, 0x59A4, 0xE6A5, 0x59A5, 0xCDD7, 0x59A6, 0x8A7E, + 0x59A7, 0x8A80, 0x59A8, 0xB7C1, 0x59A9, 0xE5FC, 0x59AA, 0xE5FD, + 0x59AB, 0xE6A3, 0x59AC, 0x8A81, 0x59AD, 0x8A82, 0x59AE, 0xC4DD, + 0x59AF, 0xE6A8, 0x59B0, 0x8A83, 0x59B1, 0x8A84, 0x59B2, 0xE6A7, + 0x59B3, 0x8A85, 0x59B4, 0x8A86, 0x59B5, 0x8A87, 0x59B6, 0x8A88, + 0x59B7, 0x8A89, 0x59B8, 0x8A8A, 0x59B9, 0xC3C3, 0x59BA, 0x8A8B, + 0x59BB, 0xC6DE, 0x59BC, 0x8A8C, 0x59BD, 0x8A8D, 0x59BE, 0xE6AA, + 0x59BF, 0x8A8E, 0x59C0, 0x8A8F, 0x59C1, 0x8A90, 0x59C2, 0x8A91, + 0x59C3, 0x8A92, 0x59C4, 0x8A93, 0x59C5, 0x8A94, 0x59C6, 0xC4B7, + 0x59C7, 0x8A95, 0x59C8, 0x8A96, 0x59C9, 0x8A97, 0x59CA, 0xE6A2, + 0x59CB, 0xCABC, 0x59CC, 0x8A98, 0x59CD, 0x8A99, 0x59CE, 0x8A9A, + 0x59CF, 0x8A9B, 0x59D0, 0xBDE3, 0x59D1, 0xB9C3, 0x59D2, 0xE6A6, + 0x59D3, 0xD0D5, 0x59D4, 0xCEAF, 0x59D5, 0x8A9C, 0x59D6, 0x8A9D, + 0x59D7, 0xE6A9, 0x59D8, 0xE6B0, 0x59D9, 0x8A9E, 0x59DA, 0xD2A6, + 0x59DB, 0x8A9F, 0x59DC, 0xBDAA, 0x59DD, 0xE6AD, 0x59DE, 0x8AA0, + 0x59DF, 0x8AA1, 0x59E0, 0x8AA2, 0x59E1, 0x8AA3, 0x59E2, 0x8AA4, + 0x59E3, 0xE6AF, 0x59E4, 0x8AA5, 0x59E5, 0xC0D1, 0x59E6, 0x8AA6, + 0x59E7, 0x8AA7, 0x59E8, 0xD2CC, 0x59E9, 0x8AA8, 0x59EA, 0x8AA9, + 0x59EB, 0x8AAA, 0x59EC, 0xBCA7, 0x59ED, 0x8AAB, 0x59EE, 0x8AAC, + 0x59EF, 0x8AAD, 0x59F0, 0x8AAE, 0x59F1, 0x8AAF, 0x59F2, 0x8AB0, + 0x59F3, 0x8AB1, 0x59F4, 0x8AB2, 0x59F5, 0x8AB3, 0x59F6, 0x8AB4, + 0x59F7, 0x8AB5, 0x59F8, 0x8AB6, 0x59F9, 0xE6B1, 0x59FA, 0x8AB7, + 0x59FB, 0xD2F6, 0x59FC, 0x8AB8, 0x59FD, 0x8AB9, 0x59FE, 0x8ABA, + 0x59FF, 0xD7CB, 0x5A00, 0x8ABB, 0x5A01, 0xCDFE, 0x5A02, 0x8ABC, + 0x5A03, 0xCDDE, 0x5A04, 0xC2A6, 0x5A05, 0xE6AB, 0x5A06, 0xE6AC, + 0x5A07, 0xBDBF, 0x5A08, 0xE6AE, 0x5A09, 0xE6B3, 0x5A0A, 0x8ABD, + 0x5A0B, 0x8ABE, 0x5A0C, 0xE6B2, 0x5A0D, 0x8ABF, 0x5A0E, 0x8AC0, + 0x5A0F, 0x8AC1, 0x5A10, 0x8AC2, 0x5A11, 0xE6B6, 0x5A12, 0x8AC3, + 0x5A13, 0xE6B8, 0x5A14, 0x8AC4, 0x5A15, 0x8AC5, 0x5A16, 0x8AC6, + 0x5A17, 0x8AC7, 0x5A18, 0xC4EF, 0x5A19, 0x8AC8, 0x5A1A, 0x8AC9, + 0x5A1B, 0x8ACA, 0x5A1C, 0xC4C8, 0x5A1D, 0x8ACB, 0x5A1E, 0x8ACC, + 0x5A1F, 0xBEEA, 0x5A20, 0xC9EF, 0x5A21, 0x8ACD, 0x5A22, 0x8ACE, + 0x5A23, 0xE6B7, 0x5A24, 0x8ACF, 0x5A25, 0xB6F0, 0x5A26, 0x8AD0, + 0x5A27, 0x8AD1, 0x5A28, 0x8AD2, 0x5A29, 0xC3E4, 0x5A2A, 0x8AD3, + 0x5A2B, 0x8AD4, 0x5A2C, 0x8AD5, 0x5A2D, 0x8AD6, 0x5A2E, 0x8AD7, + 0x5A2F, 0x8AD8, 0x5A30, 0x8AD9, 0x5A31, 0xD3E9, 0x5A32, 0xE6B4, + 0x5A33, 0x8ADA, 0x5A34, 0xE6B5, 0x5A35, 0x8ADB, 0x5A36, 0xC8A2, + 0x5A37, 0x8ADC, 0x5A38, 0x8ADD, 0x5A39, 0x8ADE, 0x5A3A, 0x8ADF, + 0x5A3B, 0x8AE0, 0x5A3C, 0xE6BD, 0x5A3D, 0x8AE1, 0x5A3E, 0x8AE2, + 0x5A3F, 0x8AE3, 0x5A40, 0xE6B9, 0x5A41, 0x8AE4, 0x5A42, 0x8AE5, + 0x5A43, 0x8AE6, 0x5A44, 0x8AE7, 0x5A45, 0x8AE8, 0x5A46, 0xC6C5, + 0x5A47, 0x8AE9, 0x5A48, 0x8AEA, 0x5A49, 0xCDF1, 0x5A4A, 0xE6BB, + 0x5A4B, 0x8AEB, 0x5A4C, 0x8AEC, 0x5A4D, 0x8AED, 0x5A4E, 0x8AEE, + 0x5A4F, 0x8AEF, 0x5A50, 0x8AF0, 0x5A51, 0x8AF1, 0x5A52, 0x8AF2, + 0x5A53, 0x8AF3, 0x5A54, 0x8AF4, 0x5A55, 0xE6BC, 0x5A56, 0x8AF5, + 0x5A57, 0x8AF6, 0x5A58, 0x8AF7, 0x5A59, 0x8AF8, 0x5A5A, 0xBBE9, + 0x5A5B, 0x8AF9, 0x5A5C, 0x8AFA, 0x5A5D, 0x8AFB, 0x5A5E, 0x8AFC, + 0x5A5F, 0x8AFD, 0x5A60, 0x8AFE, 0x5A61, 0x8B40, 0x5A62, 0xE6BE, + 0x5A63, 0x8B41, 0x5A64, 0x8B42, 0x5A65, 0x8B43, 0x5A66, 0x8B44, + 0x5A67, 0xE6BA, 0x5A68, 0x8B45, 0x5A69, 0x8B46, 0x5A6A, 0xC0B7, + 0x5A6B, 0x8B47, 0x5A6C, 0x8B48, 0x5A6D, 0x8B49, 0x5A6E, 0x8B4A, + 0x5A6F, 0x8B4B, 0x5A70, 0x8B4C, 0x5A71, 0x8B4D, 0x5A72, 0x8B4E, + 0x5A73, 0x8B4F, 0x5A74, 0xD3A4, 0x5A75, 0xE6BF, 0x5A76, 0xC9F4, + 0x5A77, 0xE6C3, 0x5A78, 0x8B50, 0x5A79, 0x8B51, 0x5A7A, 0xE6C4, + 0x5A7B, 0x8B52, 0x5A7C, 0x8B53, 0x5A7D, 0x8B54, 0x5A7E, 0x8B55, + 0x5A7F, 0xD0F6, 0x5A80, 0x8B56, 0x5A81, 0x8B57, 0x5A82, 0x8B58, + 0x5A83, 0x8B59, 0x5A84, 0x8B5A, 0x5A85, 0x8B5B, 0x5A86, 0x8B5C, + 0x5A87, 0x8B5D, 0x5A88, 0x8B5E, 0x5A89, 0x8B5F, 0x5A8A, 0x8B60, + 0x5A8B, 0x8B61, 0x5A8C, 0x8B62, 0x5A8D, 0x8B63, 0x5A8E, 0x8B64, + 0x5A8F, 0x8B65, 0x5A90, 0x8B66, 0x5A91, 0x8B67, 0x5A92, 0xC3BD, + 0x5A93, 0x8B68, 0x5A94, 0x8B69, 0x5A95, 0x8B6A, 0x5A96, 0x8B6B, + 0x5A97, 0x8B6C, 0x5A98, 0x8B6D, 0x5A99, 0x8B6E, 0x5A9A, 0xC3C4, + 0x5A9B, 0xE6C2, 0x5A9C, 0x8B6F, 0x5A9D, 0x8B70, 0x5A9E, 0x8B71, + 0x5A9F, 0x8B72, 0x5AA0, 0x8B73, 0x5AA1, 0x8B74, 0x5AA2, 0x8B75, + 0x5AA3, 0x8B76, 0x5AA4, 0x8B77, 0x5AA5, 0x8B78, 0x5AA6, 0x8B79, + 0x5AA7, 0x8B7A, 0x5AA8, 0x8B7B, 0x5AA9, 0x8B7C, 0x5AAA, 0xE6C1, + 0x5AAB, 0x8B7D, 0x5AAC, 0x8B7E, 0x5AAD, 0x8B80, 0x5AAE, 0x8B81, + 0x5AAF, 0x8B82, 0x5AB0, 0x8B83, 0x5AB1, 0x8B84, 0x5AB2, 0xE6C7, + 0x5AB3, 0xCFB1, 0x5AB4, 0x8B85, 0x5AB5, 0xEBF4, 0x5AB6, 0x8B86, + 0x5AB7, 0x8B87, 0x5AB8, 0xE6CA, 0x5AB9, 0x8B88, 0x5ABA, 0x8B89, + 0x5ABB, 0x8B8A, 0x5ABC, 0x8B8B, 0x5ABD, 0x8B8C, 0x5ABE, 0xE6C5, + 0x5ABF, 0x8B8D, 0x5AC0, 0x8B8E, 0x5AC1, 0xBCDE, 0x5AC2, 0xC9A9, + 0x5AC3, 0x8B8F, 0x5AC4, 0x8B90, 0x5AC5, 0x8B91, 0x5AC6, 0x8B92, + 0x5AC7, 0x8B93, 0x5AC8, 0x8B94, 0x5AC9, 0xBCB5, 0x5ACA, 0x8B95, + 0x5ACB, 0x8B96, 0x5ACC, 0xCFD3, 0x5ACD, 0x8B97, 0x5ACE, 0x8B98, + 0x5ACF, 0x8B99, 0x5AD0, 0x8B9A, 0x5AD1, 0x8B9B, 0x5AD2, 0xE6C8, + 0x5AD3, 0x8B9C, 0x5AD4, 0xE6C9, 0x5AD5, 0x8B9D, 0x5AD6, 0xE6CE, + 0x5AD7, 0x8B9E, 0x5AD8, 0xE6D0, 0x5AD9, 0x8B9F, 0x5ADA, 0x8BA0, + 0x5ADB, 0x8BA1, 0x5ADC, 0xE6D1, 0x5ADD, 0x8BA2, 0x5ADE, 0x8BA3, + 0x5ADF, 0x8BA4, 0x5AE0, 0xE6CB, 0x5AE1, 0xB5D5, 0x5AE2, 0x8BA5, + 0x5AE3, 0xE6CC, 0x5AE4, 0x8BA6, 0x5AE5, 0x8BA7, 0x5AE6, 0xE6CF, + 0x5AE7, 0x8BA8, 0x5AE8, 0x8BA9, 0x5AE9, 0xC4DB, 0x5AEA, 0x8BAA, + 0x5AEB, 0xE6C6, 0x5AEC, 0x8BAB, 0x5AED, 0x8BAC, 0x5AEE, 0x8BAD, + 0x5AEF, 0x8BAE, 0x5AF0, 0x8BAF, 0x5AF1, 0xE6CD, 0x5AF2, 0x8BB0, + 0x5AF3, 0x8BB1, 0x5AF4, 0x8BB2, 0x5AF5, 0x8BB3, 0x5AF6, 0x8BB4, + 0x5AF7, 0x8BB5, 0x5AF8, 0x8BB6, 0x5AF9, 0x8BB7, 0x5AFA, 0x8BB8, + 0x5AFB, 0x8BB9, 0x5AFC, 0x8BBA, 0x5AFD, 0x8BBB, 0x5AFE, 0x8BBC, + 0x5AFF, 0x8BBD, 0x5B00, 0x8BBE, 0x5B01, 0x8BBF, 0x5B02, 0x8BC0, + 0x5B03, 0x8BC1, 0x5B04, 0x8BC2, 0x5B05, 0x8BC3, 0x5B06, 0x8BC4, + 0x5B07, 0x8BC5, 0x5B08, 0x8BC6, 0x5B09, 0xE6D2, 0x5B0A, 0x8BC7, + 0x5B0B, 0x8BC8, 0x5B0C, 0x8BC9, 0x5B0D, 0x8BCA, 0x5B0E, 0x8BCB, + 0x5B0F, 0x8BCC, 0x5B10, 0x8BCD, 0x5B11, 0x8BCE, 0x5B12, 0x8BCF, + 0x5B13, 0x8BD0, 0x5B14, 0x8BD1, 0x5B15, 0x8BD2, 0x5B16, 0xE6D4, + 0x5B17, 0xE6D3, 0x5B18, 0x8BD3, 0x5B19, 0x8BD4, 0x5B1A, 0x8BD5, + 0x5B1B, 0x8BD6, 0x5B1C, 0x8BD7, 0x5B1D, 0x8BD8, 0x5B1E, 0x8BD9, + 0x5B1F, 0x8BDA, 0x5B20, 0x8BDB, 0x5B21, 0x8BDC, 0x5B22, 0x8BDD, + 0x5B23, 0x8BDE, 0x5B24, 0x8BDF, 0x5B25, 0x8BE0, 0x5B26, 0x8BE1, + 0x5B27, 0x8BE2, 0x5B28, 0x8BE3, 0x5B29, 0x8BE4, 0x5B2A, 0x8BE5, + 0x5B2B, 0x8BE6, 0x5B2C, 0x8BE7, 0x5B2D, 0x8BE8, 0x5B2E, 0x8BE9, + 0x5B2F, 0x8BEA, 0x5B30, 0x8BEB, 0x5B31, 0x8BEC, 0x5B32, 0xE6D5, + 0x5B33, 0x8BED, 0x5B34, 0xD9F8, 0x5B35, 0x8BEE, 0x5B36, 0x8BEF, + 0x5B37, 0xE6D6, 0x5B38, 0x8BF0, 0x5B39, 0x8BF1, 0x5B3A, 0x8BF2, + 0x5B3B, 0x8BF3, 0x5B3C, 0x8BF4, 0x5B3D, 0x8BF5, 0x5B3E, 0x8BF6, + 0x5B3F, 0x8BF7, 0x5B40, 0xE6D7, 0x5B41, 0x8BF8, 0x5B42, 0x8BF9, + 0x5B43, 0x8BFA, 0x5B44, 0x8BFB, 0x5B45, 0x8BFC, 0x5B46, 0x8BFD, + 0x5B47, 0x8BFE, 0x5B48, 0x8C40, 0x5B49, 0x8C41, 0x5B4A, 0x8C42, + 0x5B4B, 0x8C43, 0x5B4C, 0x8C44, 0x5B4D, 0x8C45, 0x5B4E, 0x8C46, + 0x5B4F, 0x8C47, 0x5B50, 0xD7D3, 0x5B51, 0xE6DD, 0x5B52, 0x8C48, + 0x5B53, 0xE6DE, 0x5B54, 0xBFD7, 0x5B55, 0xD4D0, 0x5B56, 0x8C49, + 0x5B57, 0xD7D6, 0x5B58, 0xB4E6, 0x5B59, 0xCBEF, 0x5B5A, 0xE6DA, + 0x5B5B, 0xD8C3, 0x5B5C, 0xD7CE, 0x5B5D, 0xD0A2, 0x5B5E, 0x8C4A, + 0x5B5F, 0xC3CF, 0x5B60, 0x8C4B, 0x5B61, 0x8C4C, 0x5B62, 0xE6DF, + 0x5B63, 0xBCBE, 0x5B64, 0xB9C2, 0x5B65, 0xE6DB, 0x5B66, 0xD1A7, + 0x5B67, 0x8C4D, 0x5B68, 0x8C4E, 0x5B69, 0xBAA2, 0x5B6A, 0xC2CF, + 0x5B6B, 0x8C4F, 0x5B6C, 0xD8AB, 0x5B6D, 0x8C50, 0x5B6E, 0x8C51, + 0x5B6F, 0x8C52, 0x5B70, 0xCAEB, 0x5B71, 0xE5EE, 0x5B72, 0x8C53, + 0x5B73, 0xE6DC, 0x5B74, 0x8C54, 0x5B75, 0xB7F5, 0x5B76, 0x8C55, + 0x5B77, 0x8C56, 0x5B78, 0x8C57, 0x5B79, 0x8C58, 0x5B7A, 0xC8E6, + 0x5B7B, 0x8C59, 0x5B7C, 0x8C5A, 0x5B7D, 0xC4F5, 0x5B7E, 0x8C5B, + 0x5B7F, 0x8C5C, 0x5B80, 0xE5B2, 0x5B81, 0xC4FE, 0x5B82, 0x8C5D, + 0x5B83, 0xCBFC, 0x5B84, 0xE5B3, 0x5B85, 0xD5AC, 0x5B86, 0x8C5E, + 0x5B87, 0xD3EE, 0x5B88, 0xCAD8, 0x5B89, 0xB0B2, 0x5B8A, 0x8C5F, + 0x5B8B, 0xCBCE, 0x5B8C, 0xCDEA, 0x5B8D, 0x8C60, 0x5B8E, 0x8C61, + 0x5B8F, 0xBAEA, 0x5B90, 0x8C62, 0x5B91, 0x8C63, 0x5B92, 0x8C64, + 0x5B93, 0xE5B5, 0x5B94, 0x8C65, 0x5B95, 0xE5B4, 0x5B96, 0x8C66, + 0x5B97, 0xD7DA, 0x5B98, 0xB9D9, 0x5B99, 0xD6E6, 0x5B9A, 0xB6A8, + 0x5B9B, 0xCDF0, 0x5B9C, 0xD2CB, 0x5B9D, 0xB1A6, 0x5B9E, 0xCAB5, + 0x5B9F, 0x8C67, 0x5BA0, 0xB3E8, 0x5BA1, 0xC9F3, 0x5BA2, 0xBFCD, + 0x5BA3, 0xD0FB, 0x5BA4, 0xCAD2, 0x5BA5, 0xE5B6, 0x5BA6, 0xBBC2, + 0x5BA7, 0x8C68, 0x5BA8, 0x8C69, 0x5BA9, 0x8C6A, 0x5BAA, 0xCFDC, + 0x5BAB, 0xB9AC, 0x5BAC, 0x8C6B, 0x5BAD, 0x8C6C, 0x5BAE, 0x8C6D, + 0x5BAF, 0x8C6E, 0x5BB0, 0xD4D7, 0x5BB1, 0x8C6F, 0x5BB2, 0x8C70, + 0x5BB3, 0xBAA6, 0x5BB4, 0xD1E7, 0x5BB5, 0xCFFC, 0x5BB6, 0xBCD2, + 0x5BB7, 0x8C71, 0x5BB8, 0xE5B7, 0x5BB9, 0xC8DD, 0x5BBA, 0x8C72, + 0x5BBB, 0x8C73, 0x5BBC, 0x8C74, 0x5BBD, 0xBFED, 0x5BBE, 0xB1F6, + 0x5BBF, 0xCBDE, 0x5BC0, 0x8C75, 0x5BC1, 0x8C76, 0x5BC2, 0xBCC5, + 0x5BC3, 0x8C77, 0x5BC4, 0xBCC4, 0x5BC5, 0xD2FA, 0x5BC6, 0xC3DC, + 0x5BC7, 0xBFDC, 0x5BC8, 0x8C78, 0x5BC9, 0x8C79, 0x5BCA, 0x8C7A, + 0x5BCB, 0x8C7B, 0x5BCC, 0xB8BB, 0x5BCD, 0x8C7C, 0x5BCE, 0x8C7D, + 0x5BCF, 0x8C7E, 0x5BD0, 0xC3C2, 0x5BD1, 0x8C80, 0x5BD2, 0xBAAE, + 0x5BD3, 0xD4A2, 0x5BD4, 0x8C81, 0x5BD5, 0x8C82, 0x5BD6, 0x8C83, + 0x5BD7, 0x8C84, 0x5BD8, 0x8C85, 0x5BD9, 0x8C86, 0x5BDA, 0x8C87, + 0x5BDB, 0x8C88, 0x5BDC, 0x8C89, 0x5BDD, 0xC7DE, 0x5BDE, 0xC4AF, + 0x5BDF, 0xB2EC, 0x5BE0, 0x8C8A, 0x5BE1, 0xB9D1, 0x5BE2, 0x8C8B, + 0x5BE3, 0x8C8C, 0x5BE4, 0xE5BB, 0x5BE5, 0xC1C8, 0x5BE6, 0x8C8D, + 0x5BE7, 0x8C8E, 0x5BE8, 0xD5AF, 0x5BE9, 0x8C8F, 0x5BEA, 0x8C90, + 0x5BEB, 0x8C91, 0x5BEC, 0x8C92, 0x5BED, 0x8C93, 0x5BEE, 0xE5BC, + 0x5BEF, 0x8C94, 0x5BF0, 0xE5BE, 0x5BF1, 0x8C95, 0x5BF2, 0x8C96, + 0x5BF3, 0x8C97, 0x5BF4, 0x8C98, 0x5BF5, 0x8C99, 0x5BF6, 0x8C9A, + 0x5BF7, 0x8C9B, 0x5BF8, 0xB4E7, 0x5BF9, 0xB6D4, 0x5BFA, 0xCBC2, + 0x5BFB, 0xD1B0, 0x5BFC, 0xB5BC, 0x5BFD, 0x8C9C, 0x5BFE, 0x8C9D, + 0x5BFF, 0xCAD9, 0x5C00, 0x8C9E, 0x5C01, 0xB7E2, 0x5C02, 0x8C9F, + 0x5C03, 0x8CA0, 0x5C04, 0xC9E4, 0x5C05, 0x8CA1, 0x5C06, 0xBDAB, + 0x5C07, 0x8CA2, 0x5C08, 0x8CA3, 0x5C09, 0xCEBE, 0x5C0A, 0xD7F0, + 0x5C0B, 0x8CA4, 0x5C0C, 0x8CA5, 0x5C0D, 0x8CA6, 0x5C0E, 0x8CA7, + 0x5C0F, 0xD0A1, 0x5C10, 0x8CA8, 0x5C11, 0xC9D9, 0x5C12, 0x8CA9, + 0x5C13, 0x8CAA, 0x5C14, 0xB6FB, 0x5C15, 0xE6D8, 0x5C16, 0xBCE2, + 0x5C17, 0x8CAB, 0x5C18, 0xB3BE, 0x5C19, 0x8CAC, 0x5C1A, 0xC9D0, + 0x5C1B, 0x8CAD, 0x5C1C, 0xE6D9, 0x5C1D, 0xB3A2, 0x5C1E, 0x8CAE, + 0x5C1F, 0x8CAF, 0x5C20, 0x8CB0, 0x5C21, 0x8CB1, 0x5C22, 0xDECC, + 0x5C23, 0x8CB2, 0x5C24, 0xD3C8, 0x5C25, 0xDECD, 0x5C26, 0x8CB3, + 0x5C27, 0xD2A2, 0x5C28, 0x8CB4, 0x5C29, 0x8CB5, 0x5C2A, 0x8CB6, + 0x5C2B, 0x8CB7, 0x5C2C, 0xDECE, 0x5C2D, 0x8CB8, 0x5C2E, 0x8CB9, + 0x5C2F, 0x8CBA, 0x5C30, 0x8CBB, 0x5C31, 0xBECD, 0x5C32, 0x8CBC, + 0x5C33, 0x8CBD, 0x5C34, 0xDECF, 0x5C35, 0x8CBE, 0x5C36, 0x8CBF, + 0x5C37, 0x8CC0, 0x5C38, 0xCAAC, 0x5C39, 0xD2FC, 0x5C3A, 0xB3DF, + 0x5C3B, 0xE5EA, 0x5C3C, 0xC4E1, 0x5C3D, 0xBEA1, 0x5C3E, 0xCEB2, + 0x5C3F, 0xC4F2, 0x5C40, 0xBED6, 0x5C41, 0xC6A8, 0x5C42, 0xB2E3, + 0x5C43, 0x8CC1, 0x5C44, 0x8CC2, 0x5C45, 0xBED3, 0x5C46, 0x8CC3, + 0x5C47, 0x8CC4, 0x5C48, 0xC7FC, 0x5C49, 0xCCEB, 0x5C4A, 0xBDEC, + 0x5C4B, 0xCEDD, 0x5C4C, 0x8CC5, 0x5C4D, 0x8CC6, 0x5C4E, 0xCABA, + 0x5C4F, 0xC6C1, 0x5C50, 0xE5EC, 0x5C51, 0xD0BC, 0x5C52, 0x8CC7, + 0x5C53, 0x8CC8, 0x5C54, 0x8CC9, 0x5C55, 0xD5B9, 0x5C56, 0x8CCA, + 0x5C57, 0x8CCB, 0x5C58, 0x8CCC, 0x5C59, 0xE5ED, 0x5C5A, 0x8CCD, + 0x5C5B, 0x8CCE, 0x5C5C, 0x8CCF, 0x5C5D, 0x8CD0, 0x5C5E, 0xCAF4, + 0x5C5F, 0x8CD1, 0x5C60, 0xCDC0, 0x5C61, 0xC2C5, 0x5C62, 0x8CD2, + 0x5C63, 0xE5EF, 0x5C64, 0x8CD3, 0x5C65, 0xC2C4, 0x5C66, 0xE5F0, + 0x5C67, 0x8CD4, 0x5C68, 0x8CD5, 0x5C69, 0x8CD6, 0x5C6A, 0x8CD7, + 0x5C6B, 0x8CD8, 0x5C6C, 0x8CD9, 0x5C6D, 0x8CDA, 0x5C6E, 0xE5F8, + 0x5C6F, 0xCDCD, 0x5C70, 0x8CDB, 0x5C71, 0xC9BD, 0x5C72, 0x8CDC, + 0x5C73, 0x8CDD, 0x5C74, 0x8CDE, 0x5C75, 0x8CDF, 0x5C76, 0x8CE0, + 0x5C77, 0x8CE1, 0x5C78, 0x8CE2, 0x5C79, 0xD2D9, 0x5C7A, 0xE1A8, + 0x5C7B, 0x8CE3, 0x5C7C, 0x8CE4, 0x5C7D, 0x8CE5, 0x5C7E, 0x8CE6, + 0x5C7F, 0xD3EC, 0x5C80, 0x8CE7, 0x5C81, 0xCBEA, 0x5C82, 0xC6F1, + 0x5C83, 0x8CE8, 0x5C84, 0x8CE9, 0x5C85, 0x8CEA, 0x5C86, 0x8CEB, + 0x5C87, 0x8CEC, 0x5C88, 0xE1AC, 0x5C89, 0x8CED, 0x5C8A, 0x8CEE, + 0x5C8B, 0x8CEF, 0x5C8C, 0xE1A7, 0x5C8D, 0xE1A9, 0x5C8E, 0x8CF0, + 0x5C8F, 0x8CF1, 0x5C90, 0xE1AA, 0x5C91, 0xE1AF, 0x5C92, 0x8CF2, + 0x5C93, 0x8CF3, 0x5C94, 0xB2ED, 0x5C95, 0x8CF4, 0x5C96, 0xE1AB, + 0x5C97, 0xB8DA, 0x5C98, 0xE1AD, 0x5C99, 0xE1AE, 0x5C9A, 0xE1B0, + 0x5C9B, 0xB5BA, 0x5C9C, 0xE1B1, 0x5C9D, 0x8CF5, 0x5C9E, 0x8CF6, + 0x5C9F, 0x8CF7, 0x5CA0, 0x8CF8, 0x5CA1, 0x8CF9, 0x5CA2, 0xE1B3, + 0x5CA3, 0xE1B8, 0x5CA4, 0x8CFA, 0x5CA5, 0x8CFB, 0x5CA6, 0x8CFC, + 0x5CA7, 0x8CFD, 0x5CA8, 0x8CFE, 0x5CA9, 0xD1D2, 0x5CAA, 0x8D40, + 0x5CAB, 0xE1B6, 0x5CAC, 0xE1B5, 0x5CAD, 0xC1EB, 0x5CAE, 0x8D41, + 0x5CAF, 0x8D42, 0x5CB0, 0x8D43, 0x5CB1, 0xE1B7, 0x5CB2, 0x8D44, + 0x5CB3, 0xD4C0, 0x5CB4, 0x8D45, 0x5CB5, 0xE1B2, 0x5CB6, 0x8D46, + 0x5CB7, 0xE1BA, 0x5CB8, 0xB0B6, 0x5CB9, 0x8D47, 0x5CBA, 0x8D48, + 0x5CBB, 0x8D49, 0x5CBC, 0x8D4A, 0x5CBD, 0xE1B4, 0x5CBE, 0x8D4B, + 0x5CBF, 0xBFF9, 0x5CC0, 0x8D4C, 0x5CC1, 0xE1B9, 0x5CC2, 0x8D4D, + 0x5CC3, 0x8D4E, 0x5CC4, 0xE1BB, 0x5CC5, 0x8D4F, 0x5CC6, 0x8D50, + 0x5CC7, 0x8D51, 0x5CC8, 0x8D52, 0x5CC9, 0x8D53, 0x5CCA, 0x8D54, + 0x5CCB, 0xE1BE, 0x5CCC, 0x8D55, 0x5CCD, 0x8D56, 0x5CCE, 0x8D57, + 0x5CCF, 0x8D58, 0x5CD0, 0x8D59, 0x5CD1, 0x8D5A, 0x5CD2, 0xE1BC, + 0x5CD3, 0x8D5B, 0x5CD4, 0x8D5C, 0x5CD5, 0x8D5D, 0x5CD6, 0x8D5E, + 0x5CD7, 0x8D5F, 0x5CD8, 0x8D60, 0x5CD9, 0xD6C5, 0x5CDA, 0x8D61, + 0x5CDB, 0x8D62, 0x5CDC, 0x8D63, 0x5CDD, 0x8D64, 0x5CDE, 0x8D65, + 0x5CDF, 0x8D66, 0x5CE0, 0x8D67, 0x5CE1, 0xCFBF, 0x5CE2, 0x8D68, + 0x5CE3, 0x8D69, 0x5CE4, 0xE1BD, 0x5CE5, 0xE1BF, 0x5CE6, 0xC2CD, + 0x5CE7, 0x8D6A, 0x5CE8, 0xB6EB, 0x5CE9, 0x8D6B, 0x5CEA, 0xD3F8, + 0x5CEB, 0x8D6C, 0x5CEC, 0x8D6D, 0x5CED, 0xC7CD, 0x5CEE, 0x8D6E, + 0x5CEF, 0x8D6F, 0x5CF0, 0xB7E5, 0x5CF1, 0x8D70, 0x5CF2, 0x8D71, + 0x5CF3, 0x8D72, 0x5CF4, 0x8D73, 0x5CF5, 0x8D74, 0x5CF6, 0x8D75, + 0x5CF7, 0x8D76, 0x5CF8, 0x8D77, 0x5CF9, 0x8D78, 0x5CFA, 0x8D79, + 0x5CFB, 0xBEFE, 0x5CFC, 0x8D7A, 0x5CFD, 0x8D7B, 0x5CFE, 0x8D7C, + 0x5CFF, 0x8D7D, 0x5D00, 0x8D7E, 0x5D01, 0x8D80, 0x5D02, 0xE1C0, + 0x5D03, 0xE1C1, 0x5D04, 0x8D81, 0x5D05, 0x8D82, 0x5D06, 0xE1C7, + 0x5D07, 0xB3E7, 0x5D08, 0x8D83, 0x5D09, 0x8D84, 0x5D0A, 0x8D85, + 0x5D0B, 0x8D86, 0x5D0C, 0x8D87, 0x5D0D, 0x8D88, 0x5D0E, 0xC6E9, + 0x5D0F, 0x8D89, 0x5D10, 0x8D8A, 0x5D11, 0x8D8B, 0x5D12, 0x8D8C, + 0x5D13, 0x8D8D, 0x5D14, 0xB4DE, 0x5D15, 0x8D8E, 0x5D16, 0xD1C2, + 0x5D17, 0x8D8F, 0x5D18, 0x8D90, 0x5D19, 0x8D91, 0x5D1A, 0x8D92, + 0x5D1B, 0xE1C8, 0x5D1C, 0x8D93, 0x5D1D, 0x8D94, 0x5D1E, 0xE1C6, + 0x5D1F, 0x8D95, 0x5D20, 0x8D96, 0x5D21, 0x8D97, 0x5D22, 0x8D98, + 0x5D23, 0x8D99, 0x5D24, 0xE1C5, 0x5D25, 0x8D9A, 0x5D26, 0xE1C3, + 0x5D27, 0xE1C2, 0x5D28, 0x8D9B, 0x5D29, 0xB1C0, 0x5D2A, 0x8D9C, + 0x5D2B, 0x8D9D, 0x5D2C, 0x8D9E, 0x5D2D, 0xD5B8, 0x5D2E, 0xE1C4, + 0x5D2F, 0x8D9F, 0x5D30, 0x8DA0, 0x5D31, 0x8DA1, 0x5D32, 0x8DA2, + 0x5D33, 0x8DA3, 0x5D34, 0xE1CB, 0x5D35, 0x8DA4, 0x5D36, 0x8DA5, + 0x5D37, 0x8DA6, 0x5D38, 0x8DA7, 0x5D39, 0x8DA8, 0x5D3A, 0x8DA9, + 0x5D3B, 0x8DAA, 0x5D3C, 0x8DAB, 0x5D3D, 0xE1CC, 0x5D3E, 0xE1CA, + 0x5D3F, 0x8DAC, 0x5D40, 0x8DAD, 0x5D41, 0x8DAE, 0x5D42, 0x8DAF, + 0x5D43, 0x8DB0, 0x5D44, 0x8DB1, 0x5D45, 0x8DB2, 0x5D46, 0x8DB3, + 0x5D47, 0xEFFA, 0x5D48, 0x8DB4, 0x5D49, 0x8DB5, 0x5D4A, 0xE1D3, + 0x5D4B, 0xE1D2, 0x5D4C, 0xC7B6, 0x5D4D, 0x8DB6, 0x5D4E, 0x8DB7, + 0x5D4F, 0x8DB8, 0x5D50, 0x8DB9, 0x5D51, 0x8DBA, 0x5D52, 0x8DBB, + 0x5D53, 0x8DBC, 0x5D54, 0x8DBD, 0x5D55, 0x8DBE, 0x5D56, 0x8DBF, + 0x5D57, 0x8DC0, 0x5D58, 0xE1C9, 0x5D59, 0x8DC1, 0x5D5A, 0x8DC2, + 0x5D5B, 0xE1CE, 0x5D5C, 0x8DC3, 0x5D5D, 0xE1D0, 0x5D5E, 0x8DC4, + 0x5D5F, 0x8DC5, 0x5D60, 0x8DC6, 0x5D61, 0x8DC7, 0x5D62, 0x8DC8, + 0x5D63, 0x8DC9, 0x5D64, 0x8DCA, 0x5D65, 0x8DCB, 0x5D66, 0x8DCC, + 0x5D67, 0x8DCD, 0x5D68, 0x8DCE, 0x5D69, 0xE1D4, 0x5D6A, 0x8DCF, + 0x5D6B, 0xE1D1, 0x5D6C, 0xE1CD, 0x5D6D, 0x8DD0, 0x5D6E, 0x8DD1, + 0x5D6F, 0xE1CF, 0x5D70, 0x8DD2, 0x5D71, 0x8DD3, 0x5D72, 0x8DD4, + 0x5D73, 0x8DD5, 0x5D74, 0xE1D5, 0x5D75, 0x8DD6, 0x5D76, 0x8DD7, + 0x5D77, 0x8DD8, 0x5D78, 0x8DD9, 0x5D79, 0x8DDA, 0x5D7A, 0x8DDB, + 0x5D7B, 0x8DDC, 0x5D7C, 0x8DDD, 0x5D7D, 0x8DDE, 0x5D7E, 0x8DDF, + 0x5D7F, 0x8DE0, 0x5D80, 0x8DE1, 0x5D81, 0x8DE2, 0x5D82, 0xE1D6, + 0x5D83, 0x8DE3, 0x5D84, 0x8DE4, 0x5D85, 0x8DE5, 0x5D86, 0x8DE6, + 0x5D87, 0x8DE7, 0x5D88, 0x8DE8, 0x5D89, 0x8DE9, 0x5D8A, 0x8DEA, + 0x5D8B, 0x8DEB, 0x5D8C, 0x8DEC, 0x5D8D, 0x8DED, 0x5D8E, 0x8DEE, + 0x5D8F, 0x8DEF, 0x5D90, 0x8DF0, 0x5D91, 0x8DF1, 0x5D92, 0x8DF2, + 0x5D93, 0x8DF3, 0x5D94, 0x8DF4, 0x5D95, 0x8DF5, 0x5D96, 0x8DF6, + 0x5D97, 0x8DF7, 0x5D98, 0x8DF8, 0x5D99, 0xE1D7, 0x5D9A, 0x8DF9, + 0x5D9B, 0x8DFA, 0x5D9C, 0x8DFB, 0x5D9D, 0xE1D8, 0x5D9E, 0x8DFC, + 0x5D9F, 0x8DFD, 0x5DA0, 0x8DFE, 0x5DA1, 0x8E40, 0x5DA2, 0x8E41, + 0x5DA3, 0x8E42, 0x5DA4, 0x8E43, 0x5DA5, 0x8E44, 0x5DA6, 0x8E45, + 0x5DA7, 0x8E46, 0x5DA8, 0x8E47, 0x5DA9, 0x8E48, 0x5DAA, 0x8E49, + 0x5DAB, 0x8E4A, 0x5DAC, 0x8E4B, 0x5DAD, 0x8E4C, 0x5DAE, 0x8E4D, + 0x5DAF, 0x8E4E, 0x5DB0, 0x8E4F, 0x5DB1, 0x8E50, 0x5DB2, 0x8E51, + 0x5DB3, 0x8E52, 0x5DB4, 0x8E53, 0x5DB5, 0x8E54, 0x5DB6, 0x8E55, + 0x5DB7, 0xE1DA, 0x5DB8, 0x8E56, 0x5DB9, 0x8E57, 0x5DBA, 0x8E58, + 0x5DBB, 0x8E59, 0x5DBC, 0x8E5A, 0x5DBD, 0x8E5B, 0x5DBE, 0x8E5C, + 0x5DBF, 0x8E5D, 0x5DC0, 0x8E5E, 0x5DC1, 0x8E5F, 0x5DC2, 0x8E60, + 0x5DC3, 0x8E61, 0x5DC4, 0x8E62, 0x5DC5, 0xE1DB, 0x5DC6, 0x8E63, + 0x5DC7, 0x8E64, 0x5DC8, 0x8E65, 0x5DC9, 0x8E66, 0x5DCA, 0x8E67, + 0x5DCB, 0x8E68, 0x5DCC, 0x8E69, 0x5DCD, 0xCEA1, 0x5DCE, 0x8E6A, + 0x5DCF, 0x8E6B, 0x5DD0, 0x8E6C, 0x5DD1, 0x8E6D, 0x5DD2, 0x8E6E, + 0x5DD3, 0x8E6F, 0x5DD4, 0x8E70, 0x5DD5, 0x8E71, 0x5DD6, 0x8E72, + 0x5DD7, 0x8E73, 0x5DD8, 0x8E74, 0x5DD9, 0x8E75, 0x5DDA, 0x8E76, + 0x5DDB, 0xE7DD, 0x5DDC, 0x8E77, 0x5DDD, 0xB4A8, 0x5DDE, 0xD6DD, + 0x5DDF, 0x8E78, 0x5DE0, 0x8E79, 0x5DE1, 0xD1B2, 0x5DE2, 0xB3B2, + 0x5DE3, 0x8E7A, 0x5DE4, 0x8E7B, 0x5DE5, 0xB9A4, 0x5DE6, 0xD7F3, + 0x5DE7, 0xC7C9, 0x5DE8, 0xBEDE, 0x5DE9, 0xB9AE, 0x5DEA, 0x8E7C, + 0x5DEB, 0xCED7, 0x5DEC, 0x8E7D, 0x5DED, 0x8E7E, 0x5DEE, 0xB2EE, + 0x5DEF, 0xDBCF, 0x5DF0, 0x8E80, 0x5DF1, 0xBCBA, 0x5DF2, 0xD2D1, + 0x5DF3, 0xCBC8, 0x5DF4, 0xB0CD, 0x5DF5, 0x8E81, 0x5DF6, 0x8E82, + 0x5DF7, 0xCFEF, 0x5DF8, 0x8E83, 0x5DF9, 0x8E84, 0x5DFA, 0x8E85, + 0x5DFB, 0x8E86, 0x5DFC, 0x8E87, 0x5DFD, 0xD9E3, 0x5DFE, 0xBDED, + 0x5DFF, 0x8E88, 0x5E00, 0x8E89, 0x5E01, 0xB1D2, 0x5E02, 0xCAD0, + 0x5E03, 0xB2BC, 0x5E04, 0x8E8A, 0x5E05, 0xCBA7, 0x5E06, 0xB7AB, + 0x5E07, 0x8E8B, 0x5E08, 0xCAA6, 0x5E09, 0x8E8C, 0x5E0A, 0x8E8D, + 0x5E0B, 0x8E8E, 0x5E0C, 0xCFA3, 0x5E0D, 0x8E8F, 0x5E0E, 0x8E90, + 0x5E0F, 0xE0F8, 0x5E10, 0xD5CA, 0x5E11, 0xE0FB, 0x5E12, 0x8E91, + 0x5E13, 0x8E92, 0x5E14, 0xE0FA, 0x5E15, 0xC5C1, 0x5E16, 0xCCFB, + 0x5E17, 0x8E93, 0x5E18, 0xC1B1, 0x5E19, 0xE0F9, 0x5E1A, 0xD6E3, + 0x5E1B, 0xB2AF, 0x5E1C, 0xD6C4, 0x5E1D, 0xB5DB, 0x5E1E, 0x8E94, + 0x5E1F, 0x8E95, 0x5E20, 0x8E96, 0x5E21, 0x8E97, 0x5E22, 0x8E98, + 0x5E23, 0x8E99, 0x5E24, 0x8E9A, 0x5E25, 0x8E9B, 0x5E26, 0xB4F8, + 0x5E27, 0xD6A1, 0x5E28, 0x8E9C, 0x5E29, 0x8E9D, 0x5E2A, 0x8E9E, + 0x5E2B, 0x8E9F, 0x5E2C, 0x8EA0, 0x5E2D, 0xCFAF, 0x5E2E, 0xB0EF, + 0x5E2F, 0x8EA1, 0x5E30, 0x8EA2, 0x5E31, 0xE0FC, 0x5E32, 0x8EA3, + 0x5E33, 0x8EA4, 0x5E34, 0x8EA5, 0x5E35, 0x8EA6, 0x5E36, 0x8EA7, + 0x5E37, 0xE1A1, 0x5E38, 0xB3A3, 0x5E39, 0x8EA8, 0x5E3A, 0x8EA9, + 0x5E3B, 0xE0FD, 0x5E3C, 0xE0FE, 0x5E3D, 0xC3B1, 0x5E3E, 0x8EAA, + 0x5E3F, 0x8EAB, 0x5E40, 0x8EAC, 0x5E41, 0x8EAD, 0x5E42, 0xC3DD, + 0x5E43, 0x8EAE, 0x5E44, 0xE1A2, 0x5E45, 0xB7F9, 0x5E46, 0x8EAF, + 0x5E47, 0x8EB0, 0x5E48, 0x8EB1, 0x5E49, 0x8EB2, 0x5E4A, 0x8EB3, + 0x5E4B, 0x8EB4, 0x5E4C, 0xBBCF, 0x5E4D, 0x8EB5, 0x5E4E, 0x8EB6, + 0x5E4F, 0x8EB7, 0x5E50, 0x8EB8, 0x5E51, 0x8EB9, 0x5E52, 0x8EBA, + 0x5E53, 0x8EBB, 0x5E54, 0xE1A3, 0x5E55, 0xC4BB, 0x5E56, 0x8EBC, + 0x5E57, 0x8EBD, 0x5E58, 0x8EBE, 0x5E59, 0x8EBF, 0x5E5A, 0x8EC0, + 0x5E5B, 0xE1A4, 0x5E5C, 0x8EC1, 0x5E5D, 0x8EC2, 0x5E5E, 0xE1A5, + 0x5E5F, 0x8EC3, 0x5E60, 0x8EC4, 0x5E61, 0xE1A6, 0x5E62, 0xB4B1, + 0x5E63, 0x8EC5, 0x5E64, 0x8EC6, 0x5E65, 0x8EC7, 0x5E66, 0x8EC8, + 0x5E67, 0x8EC9, 0x5E68, 0x8ECA, 0x5E69, 0x8ECB, 0x5E6A, 0x8ECC, + 0x5E6B, 0x8ECD, 0x5E6C, 0x8ECE, 0x5E6D, 0x8ECF, 0x5E6E, 0x8ED0, + 0x5E6F, 0x8ED1, 0x5E70, 0x8ED2, 0x5E71, 0x8ED3, 0x5E72, 0xB8C9, + 0x5E73, 0xC6BD, 0x5E74, 0xC4EA, 0x5E75, 0x8ED4, 0x5E76, 0xB2A2, + 0x5E77, 0x8ED5, 0x5E78, 0xD0D2, 0x5E79, 0x8ED6, 0x5E7A, 0xE7DB, + 0x5E7B, 0xBBC3, 0x5E7C, 0xD3D7, 0x5E7D, 0xD3C4, 0x5E7E, 0x8ED7, + 0x5E7F, 0xB9E3, 0x5E80, 0xE2CF, 0x5E81, 0x8ED8, 0x5E82, 0x8ED9, + 0x5E83, 0x8EDA, 0x5E84, 0xD7AF, 0x5E85, 0x8EDB, 0x5E86, 0xC7EC, + 0x5E87, 0xB1D3, 0x5E88, 0x8EDC, 0x5E89, 0x8EDD, 0x5E8A, 0xB4B2, + 0x5E8B, 0xE2D1, 0x5E8C, 0x8EDE, 0x5E8D, 0x8EDF, 0x5E8E, 0x8EE0, + 0x5E8F, 0xD0F2, 0x5E90, 0xC2AE, 0x5E91, 0xE2D0, 0x5E92, 0x8EE1, + 0x5E93, 0xBFE2, 0x5E94, 0xD3A6, 0x5E95, 0xB5D7, 0x5E96, 0xE2D2, + 0x5E97, 0xB5EA, 0x5E98, 0x8EE2, 0x5E99, 0xC3ED, 0x5E9A, 0xB8FD, + 0x5E9B, 0x8EE3, 0x5E9C, 0xB8AE, 0x5E9D, 0x8EE4, 0x5E9E, 0xC5D3, + 0x5E9F, 0xB7CF, 0x5EA0, 0xE2D4, 0x5EA1, 0x8EE5, 0x5EA2, 0x8EE6, + 0x5EA3, 0x8EE7, 0x5EA4, 0x8EE8, 0x5EA5, 0xE2D3, 0x5EA6, 0xB6C8, + 0x5EA7, 0xD7F9, 0x5EA8, 0x8EE9, 0x5EA9, 0x8EEA, 0x5EAA, 0x8EEB, + 0x5EAB, 0x8EEC, 0x5EAC, 0x8EED, 0x5EAD, 0xCDA5, 0x5EAE, 0x8EEE, + 0x5EAF, 0x8EEF, 0x5EB0, 0x8EF0, 0x5EB1, 0x8EF1, 0x5EB2, 0x8EF2, + 0x5EB3, 0xE2D8, 0x5EB4, 0x8EF3, 0x5EB5, 0xE2D6, 0x5EB6, 0xCAFC, + 0x5EB7, 0xBFB5, 0x5EB8, 0xD3B9, 0x5EB9, 0xE2D5, 0x5EBA, 0x8EF4, + 0x5EBB, 0x8EF5, 0x5EBC, 0x8EF6, 0x5EBD, 0x8EF7, 0x5EBE, 0xE2D7, + 0x5EBF, 0x8EF8, 0x5EC0, 0x8EF9, 0x5EC1, 0x8EFA, 0x5EC2, 0x8EFB, + 0x5EC3, 0x8EFC, 0x5EC4, 0x8EFD, 0x5EC5, 0x8EFE, 0x5EC6, 0x8F40, + 0x5EC7, 0x8F41, 0x5EC8, 0x8F42, 0x5EC9, 0xC1AE, 0x5ECA, 0xC0C8, + 0x5ECB, 0x8F43, 0x5ECC, 0x8F44, 0x5ECD, 0x8F45, 0x5ECE, 0x8F46, + 0x5ECF, 0x8F47, 0x5ED0, 0x8F48, 0x5ED1, 0xE2DB, 0x5ED2, 0xE2DA, + 0x5ED3, 0xC0AA, 0x5ED4, 0x8F49, 0x5ED5, 0x8F4A, 0x5ED6, 0xC1CE, + 0x5ED7, 0x8F4B, 0x5ED8, 0x8F4C, 0x5ED9, 0x8F4D, 0x5EDA, 0x8F4E, + 0x5EDB, 0xE2DC, 0x5EDC, 0x8F4F, 0x5EDD, 0x8F50, 0x5EDE, 0x8F51, + 0x5EDF, 0x8F52, 0x5EE0, 0x8F53, 0x5EE1, 0x8F54, 0x5EE2, 0x8F55, + 0x5EE3, 0x8F56, 0x5EE4, 0x8F57, 0x5EE5, 0x8F58, 0x5EE6, 0x8F59, + 0x5EE7, 0x8F5A, 0x5EE8, 0xE2DD, 0x5EE9, 0x8F5B, 0x5EEA, 0xE2DE, + 0x5EEB, 0x8F5C, 0x5EEC, 0x8F5D, 0x5EED, 0x8F5E, 0x5EEE, 0x8F5F, + 0x5EEF, 0x8F60, 0x5EF0, 0x8F61, 0x5EF1, 0x8F62, 0x5EF2, 0x8F63, + 0x5EF3, 0x8F64, 0x5EF4, 0xDBC8, 0x5EF5, 0x8F65, 0x5EF6, 0xD1D3, + 0x5EF7, 0xCDA2, 0x5EF8, 0x8F66, 0x5EF9, 0x8F67, 0x5EFA, 0xBDA8, + 0x5EFB, 0x8F68, 0x5EFC, 0x8F69, 0x5EFD, 0x8F6A, 0x5EFE, 0xDEC3, + 0x5EFF, 0xD8A5, 0x5F00, 0xBFAA, 0x5F01, 0xDBCD, 0x5F02, 0xD2EC, + 0x5F03, 0xC6FA, 0x5F04, 0xC5AA, 0x5F05, 0x8F6B, 0x5F06, 0x8F6C, + 0x5F07, 0x8F6D, 0x5F08, 0xDEC4, 0x5F09, 0x8F6E, 0x5F0A, 0xB1D7, + 0x5F0B, 0xDFAE, 0x5F0C, 0x8F6F, 0x5F0D, 0x8F70, 0x5F0E, 0x8F71, + 0x5F0F, 0xCABD, 0x5F10, 0x8F72, 0x5F11, 0xDFB1, 0x5F12, 0x8F73, + 0x5F13, 0xB9AD, 0x5F14, 0x8F74, 0x5F15, 0xD2FD, 0x5F16, 0x8F75, + 0x5F17, 0xB8A5, 0x5F18, 0xBAEB, 0x5F19, 0x8F76, 0x5F1A, 0x8F77, + 0x5F1B, 0xB3DA, 0x5F1C, 0x8F78, 0x5F1D, 0x8F79, 0x5F1E, 0x8F7A, + 0x5F1F, 0xB5DC, 0x5F20, 0xD5C5, 0x5F21, 0x8F7B, 0x5F22, 0x8F7C, + 0x5F23, 0x8F7D, 0x5F24, 0x8F7E, 0x5F25, 0xC3D6, 0x5F26, 0xCFD2, + 0x5F27, 0xBBA1, 0x5F28, 0x8F80, 0x5F29, 0xE5F3, 0x5F2A, 0xE5F2, + 0x5F2B, 0x8F81, 0x5F2C, 0x8F82, 0x5F2D, 0xE5F4, 0x5F2E, 0x8F83, + 0x5F2F, 0xCDE4, 0x5F30, 0x8F84, 0x5F31, 0xC8F5, 0x5F32, 0x8F85, + 0x5F33, 0x8F86, 0x5F34, 0x8F87, 0x5F35, 0x8F88, 0x5F36, 0x8F89, + 0x5F37, 0x8F8A, 0x5F38, 0x8F8B, 0x5F39, 0xB5AF, 0x5F3A, 0xC7BF, + 0x5F3B, 0x8F8C, 0x5F3C, 0xE5F6, 0x5F3D, 0x8F8D, 0x5F3E, 0x8F8E, + 0x5F3F, 0x8F8F, 0x5F40, 0xECB0, 0x5F41, 0x8F90, 0x5F42, 0x8F91, + 0x5F43, 0x8F92, 0x5F44, 0x8F93, 0x5F45, 0x8F94, 0x5F46, 0x8F95, + 0x5F47, 0x8F96, 0x5F48, 0x8F97, 0x5F49, 0x8F98, 0x5F4A, 0x8F99, + 0x5F4B, 0x8F9A, 0x5F4C, 0x8F9B, 0x5F4D, 0x8F9C, 0x5F4E, 0x8F9D, + 0x5F4F, 0x8F9E, 0x5F50, 0xE5E6, 0x5F51, 0x8F9F, 0x5F52, 0xB9E9, + 0x5F53, 0xB5B1, 0x5F54, 0x8FA0, 0x5F55, 0xC2BC, 0x5F56, 0xE5E8, + 0x5F57, 0xE5E7, 0x5F58, 0xE5E9, 0x5F59, 0x8FA1, 0x5F5A, 0x8FA2, + 0x5F5B, 0x8FA3, 0x5F5C, 0x8FA4, 0x5F5D, 0xD2CD, 0x5F5E, 0x8FA5, + 0x5F5F, 0x8FA6, 0x5F60, 0x8FA7, 0x5F61, 0xE1EA, 0x5F62, 0xD0CE, + 0x5F63, 0x8FA8, 0x5F64, 0xCDAE, 0x5F65, 0x8FA9, 0x5F66, 0xD1E5, + 0x5F67, 0x8FAA, 0x5F68, 0x8FAB, 0x5F69, 0xB2CA, 0x5F6A, 0xB1EB, + 0x5F6B, 0x8FAC, 0x5F6C, 0xB1F2, 0x5F6D, 0xC5ED, 0x5F6E, 0x8FAD, + 0x5F6F, 0x8FAE, 0x5F70, 0xD5C3, 0x5F71, 0xD3B0, 0x5F72, 0x8FAF, + 0x5F73, 0xE1DC, 0x5F74, 0x8FB0, 0x5F75, 0x8FB1, 0x5F76, 0x8FB2, + 0x5F77, 0xE1DD, 0x5F78, 0x8FB3, 0x5F79, 0xD2DB, 0x5F7A, 0x8FB4, + 0x5F7B, 0xB3B9, 0x5F7C, 0xB1CB, 0x5F7D, 0x8FB5, 0x5F7E, 0x8FB6, + 0x5F7F, 0x8FB7, 0x5F80, 0xCDF9, 0x5F81, 0xD5F7, 0x5F82, 0xE1DE, + 0x5F83, 0x8FB8, 0x5F84, 0xBEB6, 0x5F85, 0xB4FD, 0x5F86, 0x8FB9, + 0x5F87, 0xE1DF, 0x5F88, 0xBADC, 0x5F89, 0xE1E0, 0x5F8A, 0xBBB2, + 0x5F8B, 0xC2C9, 0x5F8C, 0xE1E1, 0x5F8D, 0x8FBA, 0x5F8E, 0x8FBB, + 0x5F8F, 0x8FBC, 0x5F90, 0xD0EC, 0x5F91, 0x8FBD, 0x5F92, 0xCDBD, + 0x5F93, 0x8FBE, 0x5F94, 0x8FBF, 0x5F95, 0xE1E2, 0x5F96, 0x8FC0, + 0x5F97, 0xB5C3, 0x5F98, 0xC5C7, 0x5F99, 0xE1E3, 0x5F9A, 0x8FC1, + 0x5F9B, 0x8FC2, 0x5F9C, 0xE1E4, 0x5F9D, 0x8FC3, 0x5F9E, 0x8FC4, + 0x5F9F, 0x8FC5, 0x5FA0, 0x8FC6, 0x5FA1, 0xD3F9, 0x5FA2, 0x8FC7, + 0x5FA3, 0x8FC8, 0x5FA4, 0x8FC9, 0x5FA5, 0x8FCA, 0x5FA6, 0x8FCB, + 0x5FA7, 0x8FCC, 0x5FA8, 0xE1E5, 0x5FA9, 0x8FCD, 0x5FAA, 0xD1AD, + 0x5FAB, 0x8FCE, 0x5FAC, 0x8FCF, 0x5FAD, 0xE1E6, 0x5FAE, 0xCEA2, + 0x5FAF, 0x8FD0, 0x5FB0, 0x8FD1, 0x5FB1, 0x8FD2, 0x5FB2, 0x8FD3, + 0x5FB3, 0x8FD4, 0x5FB4, 0x8FD5, 0x5FB5, 0xE1E7, 0x5FB6, 0x8FD6, + 0x5FB7, 0xB5C2, 0x5FB8, 0x8FD7, 0x5FB9, 0x8FD8, 0x5FBA, 0x8FD9, + 0x5FBB, 0x8FDA, 0x5FBC, 0xE1E8, 0x5FBD, 0xBBD5, 0x5FBE, 0x8FDB, + 0x5FBF, 0x8FDC, 0x5FC0, 0x8FDD, 0x5FC1, 0x8FDE, 0x5FC2, 0x8FDF, + 0x5FC3, 0xD0C4, 0x5FC4, 0xE2E0, 0x5FC5, 0xB1D8, 0x5FC6, 0xD2E4, + 0x5FC7, 0x8FE0, 0x5FC8, 0x8FE1, 0x5FC9, 0xE2E1, 0x5FCA, 0x8FE2, + 0x5FCB, 0x8FE3, 0x5FCC, 0xBCC9, 0x5FCD, 0xC8CC, 0x5FCE, 0x8FE4, + 0x5FCF, 0xE2E3, 0x5FD0, 0xECFE, 0x5FD1, 0xECFD, 0x5FD2, 0xDFAF, + 0x5FD3, 0x8FE5, 0x5FD4, 0x8FE6, 0x5FD5, 0x8FE7, 0x5FD6, 0xE2E2, + 0x5FD7, 0xD6BE, 0x5FD8, 0xCDFC, 0x5FD9, 0xC3A6, 0x5FDA, 0x8FE8, + 0x5FDB, 0x8FE9, 0x5FDC, 0x8FEA, 0x5FDD, 0xE3C3, 0x5FDE, 0x8FEB, + 0x5FDF, 0x8FEC, 0x5FE0, 0xD6D2, 0x5FE1, 0xE2E7, 0x5FE2, 0x8FED, + 0x5FE3, 0x8FEE, 0x5FE4, 0xE2E8, 0x5FE5, 0x8FEF, 0x5FE6, 0x8FF0, + 0x5FE7, 0xD3C7, 0x5FE8, 0x8FF1, 0x5FE9, 0x8FF2, 0x5FEA, 0xE2EC, + 0x5FEB, 0xBFEC, 0x5FEC, 0x8FF3, 0x5FED, 0xE2ED, 0x5FEE, 0xE2E5, + 0x5FEF, 0x8FF4, 0x5FF0, 0x8FF5, 0x5FF1, 0xB3C0, 0x5FF2, 0x8FF6, + 0x5FF3, 0x8FF7, 0x5FF4, 0x8FF8, 0x5FF5, 0xC4EE, 0x5FF6, 0x8FF9, + 0x5FF7, 0x8FFA, 0x5FF8, 0xE2EE, 0x5FF9, 0x8FFB, 0x5FFA, 0x8FFC, + 0x5FFB, 0xD0C3, 0x5FFC, 0x8FFD, 0x5FFD, 0xBAF6, 0x5FFE, 0xE2E9, + 0x5FFF, 0xB7DE, 0x6000, 0xBBB3, 0x6001, 0xCCAC, 0x6002, 0xCBCB, + 0x6003, 0xE2E4, 0x6004, 0xE2E6, 0x6005, 0xE2EA, 0x6006, 0xE2EB, + 0x6007, 0x8FFE, 0x6008, 0x9040, 0x6009, 0x9041, 0x600A, 0xE2F7, + 0x600B, 0x9042, 0x600C, 0x9043, 0x600D, 0xE2F4, 0x600E, 0xD4F5, + 0x600F, 0xE2F3, 0x6010, 0x9044, 0x6011, 0x9045, 0x6012, 0xC5AD, + 0x6013, 0x9046, 0x6014, 0xD5FA, 0x6015, 0xC5C2, 0x6016, 0xB2C0, + 0x6017, 0x9047, 0x6018, 0x9048, 0x6019, 0xE2EF, 0x601A, 0x9049, + 0x601B, 0xE2F2, 0x601C, 0xC1AF, 0x601D, 0xCBBC, 0x601E, 0x904A, + 0x601F, 0x904B, 0x6020, 0xB5A1, 0x6021, 0xE2F9, 0x6022, 0x904C, + 0x6023, 0x904D, 0x6024, 0x904E, 0x6025, 0xBCB1, 0x6026, 0xE2F1, + 0x6027, 0xD0D4, 0x6028, 0xD4B9, 0x6029, 0xE2F5, 0x602A, 0xB9D6, + 0x602B, 0xE2F6, 0x602C, 0x904F, 0x602D, 0x9050, 0x602E, 0x9051, + 0x602F, 0xC7D3, 0x6030, 0x9052, 0x6031, 0x9053, 0x6032, 0x9054, + 0x6033, 0x9055, 0x6034, 0x9056, 0x6035, 0xE2F0, 0x6036, 0x9057, + 0x6037, 0x9058, 0x6038, 0x9059, 0x6039, 0x905A, 0x603A, 0x905B, + 0x603B, 0xD7DC, 0x603C, 0xEDA1, 0x603D, 0x905C, 0x603E, 0x905D, + 0x603F, 0xE2F8, 0x6040, 0x905E, 0x6041, 0xEDA5, 0x6042, 0xE2FE, + 0x6043, 0xCAD1, 0x6044, 0x905F, 0x6045, 0x9060, 0x6046, 0x9061, + 0x6047, 0x9062, 0x6048, 0x9063, 0x6049, 0x9064, 0x604A, 0x9065, + 0x604B, 0xC1B5, 0x604C, 0x9066, 0x604D, 0xBBD0, 0x604E, 0x9067, + 0x604F, 0x9068, 0x6050, 0xBFD6, 0x6051, 0x9069, 0x6052, 0xBAE3, + 0x6053, 0x906A, 0x6054, 0x906B, 0x6055, 0xCBA1, 0x6056, 0x906C, + 0x6057, 0x906D, 0x6058, 0x906E, 0x6059, 0xEDA6, 0x605A, 0xEDA3, + 0x605B, 0x906F, 0x605C, 0x9070, 0x605D, 0xEDA2, 0x605E, 0x9071, + 0x605F, 0x9072, 0x6060, 0x9073, 0x6061, 0x9074, 0x6062, 0xBBD6, + 0x6063, 0xEDA7, 0x6064, 0xD0F4, 0x6065, 0x9075, 0x6066, 0x9076, + 0x6067, 0xEDA4, 0x6068, 0xBADE, 0x6069, 0xB6F7, 0x606A, 0xE3A1, + 0x606B, 0xB6B2, 0x606C, 0xCCF1, 0x606D, 0xB9A7, 0x606E, 0x9077, + 0x606F, 0xCFA2, 0x6070, 0xC7A1, 0x6071, 0x9078, 0x6072, 0x9079, + 0x6073, 0xBFD2, 0x6074, 0x907A, 0x6075, 0x907B, 0x6076, 0xB6F1, + 0x6077, 0x907C, 0x6078, 0xE2FA, 0x6079, 0xE2FB, 0x607A, 0xE2FD, + 0x607B, 0xE2FC, 0x607C, 0xC4D5, 0x607D, 0xE3A2, 0x607E, 0x907D, + 0x607F, 0xD3C1, 0x6080, 0x907E, 0x6081, 0x9080, 0x6082, 0x9081, + 0x6083, 0xE3A7, 0x6084, 0xC7C4, 0x6085, 0x9082, 0x6086, 0x9083, + 0x6087, 0x9084, 0x6088, 0x9085, 0x6089, 0xCFA4, 0x608A, 0x9086, + 0x608B, 0x9087, 0x608C, 0xE3A9, 0x608D, 0xBAB7, 0x608E, 0x9088, + 0x608F, 0x9089, 0x6090, 0x908A, 0x6091, 0x908B, 0x6092, 0xE3A8, + 0x6093, 0x908C, 0x6094, 0xBBDA, 0x6095, 0x908D, 0x6096, 0xE3A3, + 0x6097, 0x908E, 0x6098, 0x908F, 0x6099, 0x9090, 0x609A, 0xE3A4, + 0x609B, 0xE3AA, 0x609C, 0x9091, 0x609D, 0xE3A6, 0x609E, 0x9092, + 0x609F, 0xCEF2, 0x60A0, 0xD3C6, 0x60A1, 0x9093, 0x60A2, 0x9094, + 0x60A3, 0xBBBC, 0x60A4, 0x9095, 0x60A5, 0x9096, 0x60A6, 0xD4C3, + 0x60A7, 0x9097, 0x60A8, 0xC4FA, 0x60A9, 0x9098, 0x60AA, 0x9099, + 0x60AB, 0xEDA8, 0x60AC, 0xD0FC, 0x60AD, 0xE3A5, 0x60AE, 0x909A, + 0x60AF, 0xC3F5, 0x60B0, 0x909B, 0x60B1, 0xE3AD, 0x60B2, 0xB1AF, + 0x60B3, 0x909C, 0x60B4, 0xE3B2, 0x60B5, 0x909D, 0x60B6, 0x909E, + 0x60B7, 0x909F, 0x60B8, 0xBCC2, 0x60B9, 0x90A0, 0x60BA, 0x90A1, + 0x60BB, 0xE3AC, 0x60BC, 0xB5BF, 0x60BD, 0x90A2, 0x60BE, 0x90A3, + 0x60BF, 0x90A4, 0x60C0, 0x90A5, 0x60C1, 0x90A6, 0x60C2, 0x90A7, + 0x60C3, 0x90A8, 0x60C4, 0x90A9, 0x60C5, 0xC7E9, 0x60C6, 0xE3B0, + 0x60C7, 0x90AA, 0x60C8, 0x90AB, 0x60C9, 0x90AC, 0x60CA, 0xBEAA, + 0x60CB, 0xCDEF, 0x60CC, 0x90AD, 0x60CD, 0x90AE, 0x60CE, 0x90AF, + 0x60CF, 0x90B0, 0x60D0, 0x90B1, 0x60D1, 0xBBF3, 0x60D2, 0x90B2, + 0x60D3, 0x90B3, 0x60D4, 0x90B4, 0x60D5, 0xCCE8, 0x60D6, 0x90B5, + 0x60D7, 0x90B6, 0x60D8, 0xE3AF, 0x60D9, 0x90B7, 0x60DA, 0xE3B1, + 0x60DB, 0x90B8, 0x60DC, 0xCFA7, 0x60DD, 0xE3AE, 0x60DE, 0x90B9, + 0x60DF, 0xCEA9, 0x60E0, 0xBBDD, 0x60E1, 0x90BA, 0x60E2, 0x90BB, + 0x60E3, 0x90BC, 0x60E4, 0x90BD, 0x60E5, 0x90BE, 0x60E6, 0xB5EB, + 0x60E7, 0xBEE5, 0x60E8, 0xB2D2, 0x60E9, 0xB3CD, 0x60EA, 0x90BF, + 0x60EB, 0xB1B9, 0x60EC, 0xE3AB, 0x60ED, 0xB2D1, 0x60EE, 0xB5AC, + 0x60EF, 0xB9DF, 0x60F0, 0xB6E8, 0x60F1, 0x90C0, 0x60F2, 0x90C1, + 0x60F3, 0xCFEB, 0x60F4, 0xE3B7, 0x60F5, 0x90C2, 0x60F6, 0xBBCC, + 0x60F7, 0x90C3, 0x60F8, 0x90C4, 0x60F9, 0xC8C7, 0x60FA, 0xD0CA, + 0x60FB, 0x90C5, 0x60FC, 0x90C6, 0x60FD, 0x90C7, 0x60FE, 0x90C8, + 0x60FF, 0x90C9, 0x6100, 0xE3B8, 0x6101, 0xB3EE, 0x6102, 0x90CA, + 0x6103, 0x90CB, 0x6104, 0x90CC, 0x6105, 0x90CD, 0x6106, 0xEDA9, + 0x6107, 0x90CE, 0x6108, 0xD3FA, 0x6109, 0xD3E4, 0x610A, 0x90CF, + 0x610B, 0x90D0, 0x610C, 0x90D1, 0x610D, 0xEDAA, 0x610E, 0xE3B9, + 0x610F, 0xD2E2, 0x6110, 0x90D2, 0x6111, 0x90D3, 0x6112, 0x90D4, + 0x6113, 0x90D5, 0x6114, 0x90D6, 0x6115, 0xE3B5, 0x6116, 0x90D7, + 0x6117, 0x90D8, 0x6118, 0x90D9, 0x6119, 0x90DA, 0x611A, 0xD3DE, + 0x611B, 0x90DB, 0x611C, 0x90DC, 0x611D, 0x90DD, 0x611E, 0x90DE, + 0x611F, 0xB8D0, 0x6120, 0xE3B3, 0x6121, 0x90DF, 0x6122, 0x90E0, + 0x6123, 0xE3B6, 0x6124, 0xB7DF, 0x6125, 0x90E1, 0x6126, 0xE3B4, + 0x6127, 0xC0A2, 0x6128, 0x90E2, 0x6129, 0x90E3, 0x612A, 0x90E4, + 0x612B, 0xE3BA, 0x612C, 0x90E5, 0x612D, 0x90E6, 0x612E, 0x90E7, + 0x612F, 0x90E8, 0x6130, 0x90E9, 0x6131, 0x90EA, 0x6132, 0x90EB, + 0x6133, 0x90EC, 0x6134, 0x90ED, 0x6135, 0x90EE, 0x6136, 0x90EF, + 0x6137, 0x90F0, 0x6138, 0x90F1, 0x6139, 0x90F2, 0x613A, 0x90F3, + 0x613B, 0x90F4, 0x613C, 0x90F5, 0x613D, 0x90F6, 0x613E, 0x90F7, + 0x613F, 0xD4B8, 0x6140, 0x90F8, 0x6141, 0x90F9, 0x6142, 0x90FA, + 0x6143, 0x90FB, 0x6144, 0x90FC, 0x6145, 0x90FD, 0x6146, 0x90FE, + 0x6147, 0x9140, 0x6148, 0xB4C8, 0x6149, 0x9141, 0x614A, 0xE3BB, + 0x614B, 0x9142, 0x614C, 0xBBC5, 0x614D, 0x9143, 0x614E, 0xC9F7, + 0x614F, 0x9144, 0x6150, 0x9145, 0x6151, 0xC9E5, 0x6152, 0x9146, + 0x6153, 0x9147, 0x6154, 0x9148, 0x6155, 0xC4BD, 0x6156, 0x9149, + 0x6157, 0x914A, 0x6158, 0x914B, 0x6159, 0x914C, 0x615A, 0x914D, + 0x615B, 0x914E, 0x615C, 0x914F, 0x615D, 0xEDAB, 0x615E, 0x9150, + 0x615F, 0x9151, 0x6160, 0x9152, 0x6161, 0x9153, 0x6162, 0xC2FD, + 0x6163, 0x9154, 0x6164, 0x9155, 0x6165, 0x9156, 0x6166, 0x9157, + 0x6167, 0xBBDB, 0x6168, 0xBFAE, 0x6169, 0x9158, 0x616A, 0x9159, + 0x616B, 0x915A, 0x616C, 0x915B, 0x616D, 0x915C, 0x616E, 0x915D, + 0x616F, 0x915E, 0x6170, 0xCEBF, 0x6171, 0x915F, 0x6172, 0x9160, + 0x6173, 0x9161, 0x6174, 0x9162, 0x6175, 0xE3BC, 0x6176, 0x9163, + 0x6177, 0xBFB6, 0x6178, 0x9164, 0x6179, 0x9165, 0x617A, 0x9166, + 0x617B, 0x9167, 0x617C, 0x9168, 0x617D, 0x9169, 0x617E, 0x916A, + 0x617F, 0x916B, 0x6180, 0x916C, 0x6181, 0x916D, 0x6182, 0x916E, + 0x6183, 0x916F, 0x6184, 0x9170, 0x6185, 0x9171, 0x6186, 0x9172, + 0x6187, 0x9173, 0x6188, 0x9174, 0x6189, 0x9175, 0x618A, 0x9176, + 0x618B, 0xB1EF, 0x618C, 0x9177, 0x618D, 0x9178, 0x618E, 0xD4F7, + 0x618F, 0x9179, 0x6190, 0x917A, 0x6191, 0x917B, 0x6192, 0x917C, + 0x6193, 0x917D, 0x6194, 0xE3BE, 0x6195, 0x917E, 0x6196, 0x9180, + 0x6197, 0x9181, 0x6198, 0x9182, 0x6199, 0x9183, 0x619A, 0x9184, + 0x619B, 0x9185, 0x619C, 0x9186, 0x619D, 0xEDAD, 0x619E, 0x9187, + 0x619F, 0x9188, 0x61A0, 0x9189, 0x61A1, 0x918A, 0x61A2, 0x918B, + 0x61A3, 0x918C, 0x61A4, 0x918D, 0x61A5, 0x918E, 0x61A6, 0x918F, + 0x61A7, 0xE3BF, 0x61A8, 0xBAA9, 0x61A9, 0xEDAC, 0x61AA, 0x9190, + 0x61AB, 0x9191, 0x61AC, 0xE3BD, 0x61AD, 0x9192, 0x61AE, 0x9193, + 0x61AF, 0x9194, 0x61B0, 0x9195, 0x61B1, 0x9196, 0x61B2, 0x9197, + 0x61B3, 0x9198, 0x61B4, 0x9199, 0x61B5, 0x919A, 0x61B6, 0x919B, + 0x61B7, 0xE3C0, 0x61B8, 0x919C, 0x61B9, 0x919D, 0x61BA, 0x919E, + 0x61BB, 0x919F, 0x61BC, 0x91A0, 0x61BD, 0x91A1, 0x61BE, 0xBAB6, + 0x61BF, 0x91A2, 0x61C0, 0x91A3, 0x61C1, 0x91A4, 0x61C2, 0xB6AE, + 0x61C3, 0x91A5, 0x61C4, 0x91A6, 0x61C5, 0x91A7, 0x61C6, 0x91A8, + 0x61C7, 0x91A9, 0x61C8, 0xD0B8, 0x61C9, 0x91AA, 0x61CA, 0xB0C3, + 0x61CB, 0xEDAE, 0x61CC, 0x91AB, 0x61CD, 0x91AC, 0x61CE, 0x91AD, + 0x61CF, 0x91AE, 0x61D0, 0x91AF, 0x61D1, 0xEDAF, 0x61D2, 0xC0C1, + 0x61D3, 0x91B0, 0x61D4, 0xE3C1, 0x61D5, 0x91B1, 0x61D6, 0x91B2, + 0x61D7, 0x91B3, 0x61D8, 0x91B4, 0x61D9, 0x91B5, 0x61DA, 0x91B6, + 0x61DB, 0x91B7, 0x61DC, 0x91B8, 0x61DD, 0x91B9, 0x61DE, 0x91BA, + 0x61DF, 0x91BB, 0x61E0, 0x91BC, 0x61E1, 0x91BD, 0x61E2, 0x91BE, + 0x61E3, 0x91BF, 0x61E4, 0x91C0, 0x61E5, 0x91C1, 0x61E6, 0xC5B3, + 0x61E7, 0x91C2, 0x61E8, 0x91C3, 0x61E9, 0x91C4, 0x61EA, 0x91C5, + 0x61EB, 0x91C6, 0x61EC, 0x91C7, 0x61ED, 0x91C8, 0x61EE, 0x91C9, + 0x61EF, 0x91CA, 0x61F0, 0x91CB, 0x61F1, 0x91CC, 0x61F2, 0x91CD, + 0x61F3, 0x91CE, 0x61F4, 0x91CF, 0x61F5, 0xE3C2, 0x61F6, 0x91D0, + 0x61F7, 0x91D1, 0x61F8, 0x91D2, 0x61F9, 0x91D3, 0x61FA, 0x91D4, + 0x61FB, 0x91D5, 0x61FC, 0x91D6, 0x61FD, 0x91D7, 0x61FE, 0x91D8, + 0x61FF, 0xDCB2, 0x6200, 0x91D9, 0x6201, 0x91DA, 0x6202, 0x91DB, + 0x6203, 0x91DC, 0x6204, 0x91DD, 0x6205, 0x91DE, 0x6206, 0xEDB0, + 0x6207, 0x91DF, 0x6208, 0xB8EA, 0x6209, 0x91E0, 0x620A, 0xCEEC, + 0x620B, 0xEAA7, 0x620C, 0xD0E7, 0x620D, 0xCAF9, 0x620E, 0xC8D6, + 0x620F, 0xCFB7, 0x6210, 0xB3C9, 0x6211, 0xCED2, 0x6212, 0xBDE4, + 0x6213, 0x91E1, 0x6214, 0x91E2, 0x6215, 0xE3DE, 0x6216, 0xBBF2, + 0x6217, 0xEAA8, 0x6218, 0xD5BD, 0x6219, 0x91E3, 0x621A, 0xC6DD, + 0x621B, 0xEAA9, 0x621C, 0x91E4, 0x621D, 0x91E5, 0x621E, 0x91E6, + 0x621F, 0xEAAA, 0x6220, 0x91E7, 0x6221, 0xEAAC, 0x6222, 0xEAAB, + 0x6223, 0x91E8, 0x6224, 0xEAAE, 0x6225, 0xEAAD, 0x6226, 0x91E9, + 0x6227, 0x91EA, 0x6228, 0x91EB, 0x6229, 0x91EC, 0x622A, 0xBDD8, + 0x622B, 0x91ED, 0x622C, 0xEAAF, 0x622D, 0x91EE, 0x622E, 0xC2BE, + 0x622F, 0x91EF, 0x6230, 0x91F0, 0x6231, 0x91F1, 0x6232, 0x91F2, + 0x6233, 0xB4C1, 0x6234, 0xB4F7, 0x6235, 0x91F3, 0x6236, 0x91F4, + 0x6237, 0xBBA7, 0x6238, 0x91F5, 0x6239, 0x91F6, 0x623A, 0x91F7, + 0x623B, 0x91F8, 0x623C, 0x91F9, 0x623D, 0xECE6, 0x623E, 0xECE5, + 0x623F, 0xB7BF, 0x6240, 0xCBF9, 0x6241, 0xB1E2, 0x6242, 0x91FA, + 0x6243, 0xECE7, 0x6244, 0x91FB, 0x6245, 0x91FC, 0x6246, 0x91FD, + 0x6247, 0xC9C8, 0x6248, 0xECE8, 0x6249, 0xECE9, 0x624A, 0x91FE, + 0x624B, 0xCAD6, 0x624C, 0xDED0, 0x624D, 0xB2C5, 0x624E, 0xD4FA, + 0x624F, 0x9240, 0x6250, 0x9241, 0x6251, 0xC6CB, 0x6252, 0xB0C7, + 0x6253, 0xB4F2, 0x6254, 0xC8D3, 0x6255, 0x9242, 0x6256, 0x9243, + 0x6257, 0x9244, 0x6258, 0xCDD0, 0x6259, 0x9245, 0x625A, 0x9246, + 0x625B, 0xBFB8, 0x625C, 0x9247, 0x625D, 0x9248, 0x625E, 0x9249, + 0x625F, 0x924A, 0x6260, 0x924B, 0x6261, 0x924C, 0x6262, 0x924D, + 0x6263, 0xBFDB, 0x6264, 0x924E, 0x6265, 0x924F, 0x6266, 0xC7A4, + 0x6267, 0xD6B4, 0x6268, 0x9250, 0x6269, 0xC0A9, 0x626A, 0xDED1, + 0x626B, 0xC9A8, 0x626C, 0xD1EF, 0x626D, 0xC5A4, 0x626E, 0xB0E7, + 0x626F, 0xB3B6, 0x6270, 0xC8C5, 0x6271, 0x9251, 0x6272, 0x9252, + 0x6273, 0xB0E2, 0x6274, 0x9253, 0x6275, 0x9254, 0x6276, 0xB7F6, + 0x6277, 0x9255, 0x6278, 0x9256, 0x6279, 0xC5FA, 0x627A, 0x9257, + 0x627B, 0x9258, 0x627C, 0xB6F3, 0x627D, 0x9259, 0x627E, 0xD5D2, + 0x627F, 0xB3D0, 0x6280, 0xBCBC, 0x6281, 0x925A, 0x6282, 0x925B, + 0x6283, 0x925C, 0x6284, 0xB3AD, 0x6285, 0x925D, 0x6286, 0x925E, + 0x6287, 0x925F, 0x6288, 0x9260, 0x6289, 0xBEF1, 0x628A, 0xB0D1, + 0x628B, 0x9261, 0x628C, 0x9262, 0x628D, 0x9263, 0x628E, 0x9264, + 0x628F, 0x9265, 0x6290, 0x9266, 0x6291, 0xD2D6, 0x6292, 0xCAE3, + 0x6293, 0xD7A5, 0x6294, 0x9267, 0x6295, 0xCDB6, 0x6296, 0xB6B6, + 0x6297, 0xBFB9, 0x6298, 0xD5DB, 0x6299, 0x9268, 0x629A, 0xB8A7, + 0x629B, 0xC5D7, 0x629C, 0x9269, 0x629D, 0x926A, 0x629E, 0x926B, + 0x629F, 0xDED2, 0x62A0, 0xBFD9, 0x62A1, 0xC2D5, 0x62A2, 0xC7C0, + 0x62A3, 0x926C, 0x62A4, 0xBBA4, 0x62A5, 0xB1A8, 0x62A6, 0x926D, + 0x62A7, 0x926E, 0x62A8, 0xC5EA, 0x62A9, 0x926F, 0x62AA, 0x9270, + 0x62AB, 0xC5FB, 0x62AC, 0xCCA7, 0x62AD, 0x9271, 0x62AE, 0x9272, + 0x62AF, 0x9273, 0x62B0, 0x9274, 0x62B1, 0xB1A7, 0x62B2, 0x9275, + 0x62B3, 0x9276, 0x62B4, 0x9277, 0x62B5, 0xB5D6, 0x62B6, 0x9278, + 0x62B7, 0x9279, 0x62B8, 0x927A, 0x62B9, 0xC4A8, 0x62BA, 0x927B, + 0x62BB, 0xDED3, 0x62BC, 0xD1BA, 0x62BD, 0xB3E9, 0x62BE, 0x927C, + 0x62BF, 0xC3F2, 0x62C0, 0x927D, 0x62C1, 0x927E, 0x62C2, 0xB7F7, + 0x62C3, 0x9280, 0x62C4, 0xD6F4, 0x62C5, 0xB5A3, 0x62C6, 0xB2F0, + 0x62C7, 0xC4B4, 0x62C8, 0xC4E9, 0x62C9, 0xC0AD, 0x62CA, 0xDED4, + 0x62CB, 0x9281, 0x62CC, 0xB0E8, 0x62CD, 0xC5C4, 0x62CE, 0xC1E0, + 0x62CF, 0x9282, 0x62D0, 0xB9D5, 0x62D1, 0x9283, 0x62D2, 0xBEDC, + 0x62D3, 0xCDD8, 0x62D4, 0xB0CE, 0x62D5, 0x9284, 0x62D6, 0xCDCF, + 0x62D7, 0xDED6, 0x62D8, 0xBED0, 0x62D9, 0xD7BE, 0x62DA, 0xDED5, + 0x62DB, 0xD5D0, 0x62DC, 0xB0DD, 0x62DD, 0x9285, 0x62DE, 0x9286, + 0x62DF, 0xC4E2, 0x62E0, 0x9287, 0x62E1, 0x9288, 0x62E2, 0xC2A3, + 0x62E3, 0xBCF0, 0x62E4, 0x9289, 0x62E5, 0xD3B5, 0x62E6, 0xC0B9, + 0x62E7, 0xC5A1, 0x62E8, 0xB2A6, 0x62E9, 0xD4F1, 0x62EA, 0x928A, + 0x62EB, 0x928B, 0x62EC, 0xC0A8, 0x62ED, 0xCAC3, 0x62EE, 0xDED7, + 0x62EF, 0xD5FC, 0x62F0, 0x928C, 0x62F1, 0xB9B0, 0x62F2, 0x928D, + 0x62F3, 0xC8AD, 0x62F4, 0xCBA9, 0x62F5, 0x928E, 0x62F6, 0xDED9, + 0x62F7, 0xBFBD, 0x62F8, 0x928F, 0x62F9, 0x9290, 0x62FA, 0x9291, + 0x62FB, 0x9292, 0x62FC, 0xC6B4, 0x62FD, 0xD7A7, 0x62FE, 0xCAB0, + 0x62FF, 0xC4C3, 0x6300, 0x9293, 0x6301, 0xB3D6, 0x6302, 0xB9D2, + 0x6303, 0x9294, 0x6304, 0x9295, 0x6305, 0x9296, 0x6306, 0x9297, + 0x6307, 0xD6B8, 0x6308, 0xEAFC, 0x6309, 0xB0B4, 0x630A, 0x9298, + 0x630B, 0x9299, 0x630C, 0x929A, 0x630D, 0x929B, 0x630E, 0xBFE6, + 0x630F, 0x929C, 0x6310, 0x929D, 0x6311, 0xCCF4, 0x6312, 0x929E, + 0x6313, 0x929F, 0x6314, 0x92A0, 0x6315, 0x92A1, 0x6316, 0xCDDA, + 0x6317, 0x92A2, 0x6318, 0x92A3, 0x6319, 0x92A4, 0x631A, 0xD6BF, + 0x631B, 0xC2CE, 0x631C, 0x92A5, 0x631D, 0xCECE, 0x631E, 0xCCA2, + 0x631F, 0xD0AE, 0x6320, 0xC4D3, 0x6321, 0xB5B2, 0x6322, 0xDED8, + 0x6323, 0xD5F5, 0x6324, 0xBCB7, 0x6325, 0xBBD3, 0x6326, 0x92A6, + 0x6327, 0x92A7, 0x6328, 0xB0A4, 0x6329, 0x92A8, 0x632A, 0xC5B2, + 0x632B, 0xB4EC, 0x632C, 0x92A9, 0x632D, 0x92AA, 0x632E, 0x92AB, + 0x632F, 0xD5F1, 0x6330, 0x92AC, 0x6331, 0x92AD, 0x6332, 0xEAFD, + 0x6333, 0x92AE, 0x6334, 0x92AF, 0x6335, 0x92B0, 0x6336, 0x92B1, + 0x6337, 0x92B2, 0x6338, 0x92B3, 0x6339, 0xDEDA, 0x633A, 0xCDA6, + 0x633B, 0x92B4, 0x633C, 0x92B5, 0x633D, 0xCDEC, 0x633E, 0x92B6, + 0x633F, 0x92B7, 0x6340, 0x92B8, 0x6341, 0x92B9, 0x6342, 0xCEE6, + 0x6343, 0xDEDC, 0x6344, 0x92BA, 0x6345, 0xCDB1, 0x6346, 0xC0A6, + 0x6347, 0x92BB, 0x6348, 0x92BC, 0x6349, 0xD7BD, 0x634A, 0x92BD, + 0x634B, 0xDEDB, 0x634C, 0xB0C6, 0x634D, 0xBAB4, 0x634E, 0xC9D3, + 0x634F, 0xC4F3, 0x6350, 0xBEE8, 0x6351, 0x92BE, 0x6352, 0x92BF, + 0x6353, 0x92C0, 0x6354, 0x92C1, 0x6355, 0xB2B6, 0x6356, 0x92C2, + 0x6357, 0x92C3, 0x6358, 0x92C4, 0x6359, 0x92C5, 0x635A, 0x92C6, + 0x635B, 0x92C7, 0x635C, 0x92C8, 0x635D, 0x92C9, 0x635E, 0xC0CC, + 0x635F, 0xCBF0, 0x6360, 0x92CA, 0x6361, 0xBCF1, 0x6362, 0xBBBB, + 0x6363, 0xB5B7, 0x6364, 0x92CB, 0x6365, 0x92CC, 0x6366, 0x92CD, + 0x6367, 0xC5F5, 0x6368, 0x92CE, 0x6369, 0xDEE6, 0x636A, 0x92CF, + 0x636B, 0x92D0, 0x636C, 0x92D1, 0x636D, 0xDEE3, 0x636E, 0xBEDD, + 0x636F, 0x92D2, 0x6370, 0x92D3, 0x6371, 0xDEDF, 0x6372, 0x92D4, + 0x6373, 0x92D5, 0x6374, 0x92D6, 0x6375, 0x92D7, 0x6376, 0xB4B7, + 0x6377, 0xBDDD, 0x6378, 0x92D8, 0x6379, 0x92D9, 0x637A, 0xDEE0, + 0x637B, 0xC4ED, 0x637C, 0x92DA, 0x637D, 0x92DB, 0x637E, 0x92DC, + 0x637F, 0x92DD, 0x6380, 0xCFC6, 0x6381, 0x92DE, 0x6382, 0xB5E0, + 0x6383, 0x92DF, 0x6384, 0x92E0, 0x6385, 0x92E1, 0x6386, 0x92E2, + 0x6387, 0xB6DE, 0x6388, 0xCADA, 0x6389, 0xB5F4, 0x638A, 0xDEE5, + 0x638B, 0x92E3, 0x638C, 0xD5C6, 0x638D, 0x92E4, 0x638E, 0xDEE1, + 0x638F, 0xCCCD, 0x6390, 0xC6FE, 0x6391, 0x92E5, 0x6392, 0xC5C5, + 0x6393, 0x92E6, 0x6394, 0x92E7, 0x6395, 0x92E8, 0x6396, 0xD2B4, + 0x6397, 0x92E9, 0x6398, 0xBEF2, 0x6399, 0x92EA, 0x639A, 0x92EB, + 0x639B, 0x92EC, 0x639C, 0x92ED, 0x639D, 0x92EE, 0x639E, 0x92EF, + 0x639F, 0x92F0, 0x63A0, 0xC2D3, 0x63A1, 0x92F1, 0x63A2, 0xCCBD, + 0x63A3, 0xB3B8, 0x63A4, 0x92F2, 0x63A5, 0xBDD3, 0x63A6, 0x92F3, + 0x63A7, 0xBFD8, 0x63A8, 0xCDC6, 0x63A9, 0xD1DA, 0x63AA, 0xB4EB, + 0x63AB, 0x92F4, 0x63AC, 0xDEE4, 0x63AD, 0xDEDD, 0x63AE, 0xDEE7, + 0x63AF, 0x92F5, 0x63B0, 0xEAFE, 0x63B1, 0x92F6, 0x63B2, 0x92F7, + 0x63B3, 0xC2B0, 0x63B4, 0xDEE2, 0x63B5, 0x92F8, 0x63B6, 0x92F9, + 0x63B7, 0xD6C0, 0x63B8, 0xB5A7, 0x63B9, 0x92FA, 0x63BA, 0xB2F4, + 0x63BB, 0x92FB, 0x63BC, 0xDEE8, 0x63BD, 0x92FC, 0x63BE, 0xDEF2, + 0x63BF, 0x92FD, 0x63C0, 0x92FE, 0x63C1, 0x9340, 0x63C2, 0x9341, + 0x63C3, 0x9342, 0x63C4, 0xDEED, 0x63C5, 0x9343, 0x63C6, 0xDEF1, + 0x63C7, 0x9344, 0x63C8, 0x9345, 0x63C9, 0xC8E0, 0x63CA, 0x9346, + 0x63CB, 0x9347, 0x63CC, 0x9348, 0x63CD, 0xD7E1, 0x63CE, 0xDEEF, + 0x63CF, 0xC3E8, 0x63D0, 0xCCE1, 0x63D1, 0x9349, 0x63D2, 0xB2E5, + 0x63D3, 0x934A, 0x63D4, 0x934B, 0x63D5, 0x934C, 0x63D6, 0xD2BE, + 0x63D7, 0x934D, 0x63D8, 0x934E, 0x63D9, 0x934F, 0x63DA, 0x9350, + 0x63DB, 0x9351, 0x63DC, 0x9352, 0x63DD, 0x9353, 0x63DE, 0xDEEE, + 0x63DF, 0x9354, 0x63E0, 0xDEEB, 0x63E1, 0xCED5, 0x63E2, 0x9355, + 0x63E3, 0xB4A7, 0x63E4, 0x9356, 0x63E5, 0x9357, 0x63E6, 0x9358, + 0x63E7, 0x9359, 0x63E8, 0x935A, 0x63E9, 0xBFAB, 0x63EA, 0xBEBE, + 0x63EB, 0x935B, 0x63EC, 0x935C, 0x63ED, 0xBDD2, 0x63EE, 0x935D, + 0x63EF, 0x935E, 0x63F0, 0x935F, 0x63F1, 0x9360, 0x63F2, 0xDEE9, + 0x63F3, 0x9361, 0x63F4, 0xD4AE, 0x63F5, 0x9362, 0x63F6, 0xDEDE, + 0x63F7, 0x9363, 0x63F8, 0xDEEA, 0x63F9, 0x9364, 0x63FA, 0x9365, + 0x63FB, 0x9366, 0x63FC, 0x9367, 0x63FD, 0xC0BF, 0x63FE, 0x9368, + 0x63FF, 0xDEEC, 0x6400, 0xB2F3, 0x6401, 0xB8E9, 0x6402, 0xC2A7, + 0x6403, 0x9369, 0x6404, 0x936A, 0x6405, 0xBDC1, 0x6406, 0x936B, + 0x6407, 0x936C, 0x6408, 0x936D, 0x6409, 0x936E, 0x640A, 0x936F, + 0x640B, 0xDEF5, 0x640C, 0xDEF8, 0x640D, 0x9370, 0x640E, 0x9371, + 0x640F, 0xB2AB, 0x6410, 0xB4A4, 0x6411, 0x9372, 0x6412, 0x9373, + 0x6413, 0xB4EA, 0x6414, 0xC9A6, 0x6415, 0x9374, 0x6416, 0x9375, + 0x6417, 0x9376, 0x6418, 0x9377, 0x6419, 0x9378, 0x641A, 0x9379, + 0x641B, 0xDEF6, 0x641C, 0xCBD1, 0x641D, 0x937A, 0x641E, 0xB8E3, + 0x641F, 0x937B, 0x6420, 0xDEF7, 0x6421, 0xDEFA, 0x6422, 0x937C, + 0x6423, 0x937D, 0x6424, 0x937E, 0x6425, 0x9380, 0x6426, 0xDEF9, + 0x6427, 0x9381, 0x6428, 0x9382, 0x6429, 0x9383, 0x642A, 0xCCC2, + 0x642B, 0x9384, 0x642C, 0xB0E1, 0x642D, 0xB4EE, 0x642E, 0x9385, + 0x642F, 0x9386, 0x6430, 0x9387, 0x6431, 0x9388, 0x6432, 0x9389, + 0x6433, 0x938A, 0x6434, 0xE5BA, 0x6435, 0x938B, 0x6436, 0x938C, + 0x6437, 0x938D, 0x6438, 0x938E, 0x6439, 0x938F, 0x643A, 0xD0AF, + 0x643B, 0x9390, 0x643C, 0x9391, 0x643D, 0xB2EB, 0x643E, 0x9392, + 0x643F, 0xEBA1, 0x6440, 0x9393, 0x6441, 0xDEF4, 0x6442, 0x9394, + 0x6443, 0x9395, 0x6444, 0xC9E3, 0x6445, 0xDEF3, 0x6446, 0xB0DA, + 0x6447, 0xD2A1, 0x6448, 0xB1F7, 0x6449, 0x9396, 0x644A, 0xCCAF, + 0x644B, 0x9397, 0x644C, 0x9398, 0x644D, 0x9399, 0x644E, 0x939A, + 0x644F, 0x939B, 0x6450, 0x939C, 0x6451, 0x939D, 0x6452, 0xDEF0, + 0x6453, 0x939E, 0x6454, 0xCBA4, 0x6455, 0x939F, 0x6456, 0x93A0, + 0x6457, 0x93A1, 0x6458, 0xD5AA, 0x6459, 0x93A2, 0x645A, 0x93A3, + 0x645B, 0x93A4, 0x645C, 0x93A5, 0x645D, 0x93A6, 0x645E, 0xDEFB, + 0x645F, 0x93A7, 0x6460, 0x93A8, 0x6461, 0x93A9, 0x6462, 0x93AA, + 0x6463, 0x93AB, 0x6464, 0x93AC, 0x6465, 0x93AD, 0x6466, 0x93AE, + 0x6467, 0xB4DD, 0x6468, 0x93AF, 0x6469, 0xC4A6, 0x646A, 0x93B0, + 0x646B, 0x93B1, 0x646C, 0x93B2, 0x646D, 0xDEFD, 0x646E, 0x93B3, + 0x646F, 0x93B4, 0x6470, 0x93B5, 0x6471, 0x93B6, 0x6472, 0x93B7, + 0x6473, 0x93B8, 0x6474, 0x93B9, 0x6475, 0x93BA, 0x6476, 0x93BB, + 0x6477, 0x93BC, 0x6478, 0xC3FE, 0x6479, 0xC4A1, 0x647A, 0xDFA1, + 0x647B, 0x93BD, 0x647C, 0x93BE, 0x647D, 0x93BF, 0x647E, 0x93C0, + 0x647F, 0x93C1, 0x6480, 0x93C2, 0x6481, 0x93C3, 0x6482, 0xC1CC, + 0x6483, 0x93C4, 0x6484, 0xDEFC, 0x6485, 0xBEEF, 0x6486, 0x93C5, + 0x6487, 0xC6B2, 0x6488, 0x93C6, 0x6489, 0x93C7, 0x648A, 0x93C8, + 0x648B, 0x93C9, 0x648C, 0x93CA, 0x648D, 0x93CB, 0x648E, 0x93CC, + 0x648F, 0x93CD, 0x6490, 0x93CE, 0x6491, 0xB3C5, 0x6492, 0xC8F6, + 0x6493, 0x93CF, 0x6494, 0x93D0, 0x6495, 0xCBBA, 0x6496, 0xDEFE, + 0x6497, 0x93D1, 0x6498, 0x93D2, 0x6499, 0xDFA4, 0x649A, 0x93D3, + 0x649B, 0x93D4, 0x649C, 0x93D5, 0x649D, 0x93D6, 0x649E, 0xD7B2, + 0x649F, 0x93D7, 0x64A0, 0x93D8, 0x64A1, 0x93D9, 0x64A2, 0x93DA, + 0x64A3, 0x93DB, 0x64A4, 0xB3B7, 0x64A5, 0x93DC, 0x64A6, 0x93DD, + 0x64A7, 0x93DE, 0x64A8, 0x93DF, 0x64A9, 0xC1C3, 0x64AA, 0x93E0, + 0x64AB, 0x93E1, 0x64AC, 0xC7CB, 0x64AD, 0xB2A5, 0x64AE, 0xB4E9, + 0x64AF, 0x93E2, 0x64B0, 0xD7AB, 0x64B1, 0x93E3, 0x64B2, 0x93E4, + 0x64B3, 0x93E5, 0x64B4, 0x93E6, 0x64B5, 0xC4EC, 0x64B6, 0x93E7, + 0x64B7, 0xDFA2, 0x64B8, 0xDFA3, 0x64B9, 0x93E8, 0x64BA, 0xDFA5, + 0x64BB, 0x93E9, 0x64BC, 0xBAB3, 0x64BD, 0x93EA, 0x64BE, 0x93EB, + 0x64BF, 0x93EC, 0x64C0, 0xDFA6, 0x64C1, 0x93ED, 0x64C2, 0xC0DE, + 0x64C3, 0x93EE, 0x64C4, 0x93EF, 0x64C5, 0xC9C3, 0x64C6, 0x93F0, + 0x64C7, 0x93F1, 0x64C8, 0x93F2, 0x64C9, 0x93F3, 0x64CA, 0x93F4, + 0x64CB, 0x93F5, 0x64CC, 0x93F6, 0x64CD, 0xB2D9, 0x64CE, 0xC7E6, + 0x64CF, 0x93F7, 0x64D0, 0xDFA7, 0x64D1, 0x93F8, 0x64D2, 0xC7DC, + 0x64D3, 0x93F9, 0x64D4, 0x93FA, 0x64D5, 0x93FB, 0x64D6, 0x93FC, + 0x64D7, 0xDFA8, 0x64D8, 0xEBA2, 0x64D9, 0x93FD, 0x64DA, 0x93FE, + 0x64DB, 0x9440, 0x64DC, 0x9441, 0x64DD, 0x9442, 0x64DE, 0xCBD3, + 0x64DF, 0x9443, 0x64E0, 0x9444, 0x64E1, 0x9445, 0x64E2, 0xDFAA, + 0x64E3, 0x9446, 0x64E4, 0xDFA9, 0x64E5, 0x9447, 0x64E6, 0xB2C1, + 0x64E7, 0x9448, 0x64E8, 0x9449, 0x64E9, 0x944A, 0x64EA, 0x944B, + 0x64EB, 0x944C, 0x64EC, 0x944D, 0x64ED, 0x944E, 0x64EE, 0x944F, + 0x64EF, 0x9450, 0x64F0, 0x9451, 0x64F1, 0x9452, 0x64F2, 0x9453, + 0x64F3, 0x9454, 0x64F4, 0x9455, 0x64F5, 0x9456, 0x64F6, 0x9457, + 0x64F7, 0x9458, 0x64F8, 0x9459, 0x64F9, 0x945A, 0x64FA, 0x945B, + 0x64FB, 0x945C, 0x64FC, 0x945D, 0x64FD, 0x945E, 0x64FE, 0x945F, + 0x64FF, 0x9460, 0x6500, 0xC5CA, 0x6501, 0x9461, 0x6502, 0x9462, + 0x6503, 0x9463, 0x6504, 0x9464, 0x6505, 0x9465, 0x6506, 0x9466, + 0x6507, 0x9467, 0x6508, 0x9468, 0x6509, 0xDFAB, 0x650A, 0x9469, + 0x650B, 0x946A, 0x650C, 0x946B, 0x650D, 0x946C, 0x650E, 0x946D, + 0x650F, 0x946E, 0x6510, 0x946F, 0x6511, 0x9470, 0x6512, 0xD4DC, + 0x6513, 0x9471, 0x6514, 0x9472, 0x6515, 0x9473, 0x6516, 0x9474, + 0x6517, 0x9475, 0x6518, 0xC8C1, 0x6519, 0x9476, 0x651A, 0x9477, + 0x651B, 0x9478, 0x651C, 0x9479, 0x651D, 0x947A, 0x651E, 0x947B, + 0x651F, 0x947C, 0x6520, 0x947D, 0x6521, 0x947E, 0x6522, 0x9480, + 0x6523, 0x9481, 0x6524, 0x9482, 0x6525, 0xDFAC, 0x6526, 0x9483, + 0x6527, 0x9484, 0x6528, 0x9485, 0x6529, 0x9486, 0x652A, 0x9487, + 0x652B, 0xBEF0, 0x652C, 0x9488, 0x652D, 0x9489, 0x652E, 0xDFAD, + 0x652F, 0xD6A7, 0x6530, 0x948A, 0x6531, 0x948B, 0x6532, 0x948C, + 0x6533, 0x948D, 0x6534, 0xEAB7, 0x6535, 0xEBB6, 0x6536, 0xCAD5, + 0x6537, 0x948E, 0x6538, 0xD8FC, 0x6539, 0xB8C4, 0x653A, 0x948F, + 0x653B, 0xB9A5, 0x653C, 0x9490, 0x653D, 0x9491, 0x653E, 0xB7C5, + 0x653F, 0xD5FE, 0x6540, 0x9492, 0x6541, 0x9493, 0x6542, 0x9494, + 0x6543, 0x9495, 0x6544, 0x9496, 0x6545, 0xB9CA, 0x6546, 0x9497, + 0x6547, 0x9498, 0x6548, 0xD0A7, 0x6549, 0xF4CD, 0x654A, 0x9499, + 0x654B, 0x949A, 0x654C, 0xB5D0, 0x654D, 0x949B, 0x654E, 0x949C, + 0x654F, 0xC3F4, 0x6550, 0x949D, 0x6551, 0xBEC8, 0x6552, 0x949E, + 0x6553, 0x949F, 0x6554, 0x94A0, 0x6555, 0xEBB7, 0x6556, 0xB0BD, + 0x6557, 0x94A1, 0x6558, 0x94A2, 0x6559, 0xBDCC, 0x655A, 0x94A3, + 0x655B, 0xC1B2, 0x655C, 0x94A4, 0x655D, 0xB1D6, 0x655E, 0xB3A8, + 0x655F, 0x94A5, 0x6560, 0x94A6, 0x6561, 0x94A7, 0x6562, 0xB8D2, + 0x6563, 0xC9A2, 0x6564, 0x94A8, 0x6565, 0x94A9, 0x6566, 0xB6D8, + 0x6567, 0x94AA, 0x6568, 0x94AB, 0x6569, 0x94AC, 0x656A, 0x94AD, + 0x656B, 0xEBB8, 0x656C, 0xBEB4, 0x656D, 0x94AE, 0x656E, 0x94AF, + 0x656F, 0x94B0, 0x6570, 0xCAFD, 0x6571, 0x94B1, 0x6572, 0xC7C3, + 0x6573, 0x94B2, 0x6574, 0xD5FB, 0x6575, 0x94B3, 0x6576, 0x94B4, + 0x6577, 0xB7F3, 0x6578, 0x94B5, 0x6579, 0x94B6, 0x657A, 0x94B7, + 0x657B, 0x94B8, 0x657C, 0x94B9, 0x657D, 0x94BA, 0x657E, 0x94BB, + 0x657F, 0x94BC, 0x6580, 0x94BD, 0x6581, 0x94BE, 0x6582, 0x94BF, + 0x6583, 0x94C0, 0x6584, 0x94C1, 0x6585, 0x94C2, 0x6586, 0x94C3, + 0x6587, 0xCEC4, 0x6588, 0x94C4, 0x6589, 0x94C5, 0x658A, 0x94C6, + 0x658B, 0xD5AB, 0x658C, 0xB1F3, 0x658D, 0x94C7, 0x658E, 0x94C8, + 0x658F, 0x94C9, 0x6590, 0xECB3, 0x6591, 0xB0DF, 0x6592, 0x94CA, + 0x6593, 0xECB5, 0x6594, 0x94CB, 0x6595, 0x94CC, 0x6596, 0x94CD, + 0x6597, 0xB6B7, 0x6598, 0x94CE, 0x6599, 0xC1CF, 0x659A, 0x94CF, + 0x659B, 0xF5FA, 0x659C, 0xD0B1, 0x659D, 0x94D0, 0x659E, 0x94D1, + 0x659F, 0xD5E5, 0x65A0, 0x94D2, 0x65A1, 0xCED3, 0x65A2, 0x94D3, + 0x65A3, 0x94D4, 0x65A4, 0xBDEF, 0x65A5, 0xB3E2, 0x65A6, 0x94D5, + 0x65A7, 0xB8AB, 0x65A8, 0x94D6, 0x65A9, 0xD5B6, 0x65AA, 0x94D7, + 0x65AB, 0xEDBD, 0x65AC, 0x94D8, 0x65AD, 0xB6CF, 0x65AE, 0x94D9, + 0x65AF, 0xCBB9, 0x65B0, 0xD0C2, 0x65B1, 0x94DA, 0x65B2, 0x94DB, + 0x65B3, 0x94DC, 0x65B4, 0x94DD, 0x65B5, 0x94DE, 0x65B6, 0x94DF, + 0x65B7, 0x94E0, 0x65B8, 0x94E1, 0x65B9, 0xB7BD, 0x65BA, 0x94E2, + 0x65BB, 0x94E3, 0x65BC, 0xECB6, 0x65BD, 0xCAA9, 0x65BE, 0x94E4, + 0x65BF, 0x94E5, 0x65C0, 0x94E6, 0x65C1, 0xC5D4, 0x65C2, 0x94E7, + 0x65C3, 0xECB9, 0x65C4, 0xECB8, 0x65C5, 0xC2C3, 0x65C6, 0xECB7, + 0x65C7, 0x94E8, 0x65C8, 0x94E9, 0x65C9, 0x94EA, 0x65CA, 0x94EB, + 0x65CB, 0xD0FD, 0x65CC, 0xECBA, 0x65CD, 0x94EC, 0x65CE, 0xECBB, + 0x65CF, 0xD7E5, 0x65D0, 0x94ED, 0x65D1, 0x94EE, 0x65D2, 0xECBC, + 0x65D3, 0x94EF, 0x65D4, 0x94F0, 0x65D5, 0x94F1, 0x65D6, 0xECBD, + 0x65D7, 0xC6EC, 0x65D8, 0x94F2, 0x65D9, 0x94F3, 0x65DA, 0x94F4, + 0x65DB, 0x94F5, 0x65DC, 0x94F6, 0x65DD, 0x94F7, 0x65DE, 0x94F8, + 0x65DF, 0x94F9, 0x65E0, 0xCEDE, 0x65E1, 0x94FA, 0x65E2, 0xBCC8, + 0x65E3, 0x94FB, 0x65E4, 0x94FC, 0x65E5, 0xC8D5, 0x65E6, 0xB5A9, + 0x65E7, 0xBEC9, 0x65E8, 0xD6BC, 0x65E9, 0xD4E7, 0x65EA, 0x94FD, + 0x65EB, 0x94FE, 0x65EC, 0xD1AE, 0x65ED, 0xD0F1, 0x65EE, 0xEAB8, + 0x65EF, 0xEAB9, 0x65F0, 0xEABA, 0x65F1, 0xBAB5, 0x65F2, 0x9540, + 0x65F3, 0x9541, 0x65F4, 0x9542, 0x65F5, 0x9543, 0x65F6, 0xCAB1, + 0x65F7, 0xBFF5, 0x65F8, 0x9544, 0x65F9, 0x9545, 0x65FA, 0xCDFA, + 0x65FB, 0x9546, 0x65FC, 0x9547, 0x65FD, 0x9548, 0x65FE, 0x9549, + 0x65FF, 0x954A, 0x6600, 0xEAC0, 0x6601, 0x954B, 0x6602, 0xB0BA, + 0x6603, 0xEABE, 0x6604, 0x954C, 0x6605, 0x954D, 0x6606, 0xC0A5, + 0x6607, 0x954E, 0x6608, 0x954F, 0x6609, 0x9550, 0x660A, 0xEABB, + 0x660B, 0x9551, 0x660C, 0xB2FD, 0x660D, 0x9552, 0x660E, 0xC3F7, + 0x660F, 0xBBE8, 0x6610, 0x9553, 0x6611, 0x9554, 0x6612, 0x9555, + 0x6613, 0xD2D7, 0x6614, 0xCEF4, 0x6615, 0xEABF, 0x6616, 0x9556, + 0x6617, 0x9557, 0x6618, 0x9558, 0x6619, 0xEABC, 0x661A, 0x9559, + 0x661B, 0x955A, 0x661C, 0x955B, 0x661D, 0xEAC3, 0x661E, 0x955C, + 0x661F, 0xD0C7, 0x6620, 0xD3B3, 0x6621, 0x955D, 0x6622, 0x955E, + 0x6623, 0x955F, 0x6624, 0x9560, 0x6625, 0xB4BA, 0x6626, 0x9561, + 0x6627, 0xC3C1, 0x6628, 0xD7F2, 0x6629, 0x9562, 0x662A, 0x9563, + 0x662B, 0x9564, 0x662C, 0x9565, 0x662D, 0xD5D1, 0x662E, 0x9566, + 0x662F, 0xCAC7, 0x6630, 0x9567, 0x6631, 0xEAC5, 0x6632, 0x9568, + 0x6633, 0x9569, 0x6634, 0xEAC4, 0x6635, 0xEAC7, 0x6636, 0xEAC6, + 0x6637, 0x956A, 0x6638, 0x956B, 0x6639, 0x956C, 0x663A, 0x956D, + 0x663B, 0x956E, 0x663C, 0xD6E7, 0x663D, 0x956F, 0x663E, 0xCFD4, + 0x663F, 0x9570, 0x6640, 0x9571, 0x6641, 0xEACB, 0x6642, 0x9572, + 0x6643, 0xBBCE, 0x6644, 0x9573, 0x6645, 0x9574, 0x6646, 0x9575, + 0x6647, 0x9576, 0x6648, 0x9577, 0x6649, 0x9578, 0x664A, 0x9579, + 0x664B, 0xBDFA, 0x664C, 0xC9CE, 0x664D, 0x957A, 0x664E, 0x957B, + 0x664F, 0xEACC, 0x6650, 0x957C, 0x6651, 0x957D, 0x6652, 0xC9B9, + 0x6653, 0xCFFE, 0x6654, 0xEACA, 0x6655, 0xD4CE, 0x6656, 0xEACD, + 0x6657, 0xEACF, 0x6658, 0x957E, 0x6659, 0x9580, 0x665A, 0xCDED, + 0x665B, 0x9581, 0x665C, 0x9582, 0x665D, 0x9583, 0x665E, 0x9584, + 0x665F, 0xEAC9, 0x6660, 0x9585, 0x6661, 0xEACE, 0x6662, 0x9586, + 0x6663, 0x9587, 0x6664, 0xCEEE, 0x6665, 0x9588, 0x6666, 0xBBDE, + 0x6667, 0x9589, 0x6668, 0xB3BF, 0x6669, 0x958A, 0x666A, 0x958B, + 0x666B, 0x958C, 0x666C, 0x958D, 0x666D, 0x958E, 0x666E, 0xC6D5, + 0x666F, 0xBEB0, 0x6670, 0xCEFA, 0x6671, 0x958F, 0x6672, 0x9590, + 0x6673, 0x9591, 0x6674, 0xC7E7, 0x6675, 0x9592, 0x6676, 0xBEA7, + 0x6677, 0xEAD0, 0x6678, 0x9593, 0x6679, 0x9594, 0x667A, 0xD6C7, + 0x667B, 0x9595, 0x667C, 0x9596, 0x667D, 0x9597, 0x667E, 0xC1C0, + 0x667F, 0x9598, 0x6680, 0x9599, 0x6681, 0x959A, 0x6682, 0xD4DD, + 0x6683, 0x959B, 0x6684, 0xEAD1, 0x6685, 0x959C, 0x6686, 0x959D, + 0x6687, 0xCFBE, 0x6688, 0x959E, 0x6689, 0x959F, 0x668A, 0x95A0, + 0x668B, 0x95A1, 0x668C, 0xEAD2, 0x668D, 0x95A2, 0x668E, 0x95A3, + 0x668F, 0x95A4, 0x6690, 0x95A5, 0x6691, 0xCAEE, 0x6692, 0x95A6, + 0x6693, 0x95A7, 0x6694, 0x95A8, 0x6695, 0x95A9, 0x6696, 0xC5AF, + 0x6697, 0xB0B5, 0x6698, 0x95AA, 0x6699, 0x95AB, 0x669A, 0x95AC, + 0x669B, 0x95AD, 0x669C, 0x95AE, 0x669D, 0xEAD4, 0x669E, 0x95AF, + 0x669F, 0x95B0, 0x66A0, 0x95B1, 0x66A1, 0x95B2, 0x66A2, 0x95B3, + 0x66A3, 0x95B4, 0x66A4, 0x95B5, 0x66A5, 0x95B6, 0x66A6, 0x95B7, + 0x66A7, 0xEAD3, 0x66A8, 0xF4DF, 0x66A9, 0x95B8, 0x66AA, 0x95B9, + 0x66AB, 0x95BA, 0x66AC, 0x95BB, 0x66AD, 0x95BC, 0x66AE, 0xC4BA, + 0x66AF, 0x95BD, 0x66B0, 0x95BE, 0x66B1, 0x95BF, 0x66B2, 0x95C0, + 0x66B3, 0x95C1, 0x66B4, 0xB1A9, 0x66B5, 0x95C2, 0x66B6, 0x95C3, + 0x66B7, 0x95C4, 0x66B8, 0x95C5, 0x66B9, 0xE5DF, 0x66BA, 0x95C6, + 0x66BB, 0x95C7, 0x66BC, 0x95C8, 0x66BD, 0x95C9, 0x66BE, 0xEAD5, + 0x66BF, 0x95CA, 0x66C0, 0x95CB, 0x66C1, 0x95CC, 0x66C2, 0x95CD, + 0x66C3, 0x95CE, 0x66C4, 0x95CF, 0x66C5, 0x95D0, 0x66C6, 0x95D1, + 0x66C7, 0x95D2, 0x66C8, 0x95D3, 0x66C9, 0x95D4, 0x66CA, 0x95D5, + 0x66CB, 0x95D6, 0x66CC, 0x95D7, 0x66CD, 0x95D8, 0x66CE, 0x95D9, + 0x66CF, 0x95DA, 0x66D0, 0x95DB, 0x66D1, 0x95DC, 0x66D2, 0x95DD, + 0x66D3, 0x95DE, 0x66D4, 0x95DF, 0x66D5, 0x95E0, 0x66D6, 0x95E1, + 0x66D7, 0x95E2, 0x66D8, 0x95E3, 0x66D9, 0xCAEF, 0x66DA, 0x95E4, + 0x66DB, 0xEAD6, 0x66DC, 0xEAD7, 0x66DD, 0xC6D8, 0x66DE, 0x95E5, + 0x66DF, 0x95E6, 0x66E0, 0x95E7, 0x66E1, 0x95E8, 0x66E2, 0x95E9, + 0x66E3, 0x95EA, 0x66E4, 0x95EB, 0x66E5, 0x95EC, 0x66E6, 0xEAD8, + 0x66E7, 0x95ED, 0x66E8, 0x95EE, 0x66E9, 0xEAD9, 0x66EA, 0x95EF, + 0x66EB, 0x95F0, 0x66EC, 0x95F1, 0x66ED, 0x95F2, 0x66EE, 0x95F3, + 0x66EF, 0x95F4, 0x66F0, 0xD4BB, 0x66F1, 0x95F5, 0x66F2, 0xC7FA, + 0x66F3, 0xD2B7, 0x66F4, 0xB8FC, 0x66F5, 0x95F6, 0x66F6, 0x95F7, + 0x66F7, 0xEAC2, 0x66F8, 0x95F8, 0x66F9, 0xB2DC, 0x66FA, 0x95F9, + 0x66FB, 0x95FA, 0x66FC, 0xC2FC, 0x66FD, 0x95FB, 0x66FE, 0xD4F8, + 0x66FF, 0xCCE6, 0x6700, 0xD7EE, 0x6701, 0x95FC, 0x6702, 0x95FD, + 0x6703, 0x95FE, 0x6704, 0x9640, 0x6705, 0x9641, 0x6706, 0x9642, + 0x6707, 0x9643, 0x6708, 0xD4C2, 0x6709, 0xD3D0, 0x670A, 0xEBC3, + 0x670B, 0xC5F3, 0x670C, 0x9644, 0x670D, 0xB7FE, 0x670E, 0x9645, + 0x670F, 0x9646, 0x6710, 0xEBD4, 0x6711, 0x9647, 0x6712, 0x9648, + 0x6713, 0x9649, 0x6714, 0xCBB7, 0x6715, 0xEBDE, 0x6716, 0x964A, + 0x6717, 0xC0CA, 0x6718, 0x964B, 0x6719, 0x964C, 0x671A, 0x964D, + 0x671B, 0xCDFB, 0x671C, 0x964E, 0x671D, 0xB3AF, 0x671E, 0x964F, + 0x671F, 0xC6DA, 0x6720, 0x9650, 0x6721, 0x9651, 0x6722, 0x9652, + 0x6723, 0x9653, 0x6724, 0x9654, 0x6725, 0x9655, 0x6726, 0xEBFC, + 0x6727, 0x9656, 0x6728, 0xC4BE, 0x6729, 0x9657, 0x672A, 0xCEB4, + 0x672B, 0xC4A9, 0x672C, 0xB1BE, 0x672D, 0xD4FD, 0x672E, 0x9658, + 0x672F, 0xCAF5, 0x6730, 0x9659, 0x6731, 0xD6EC, 0x6732, 0x965A, + 0x6733, 0x965B, 0x6734, 0xC6D3, 0x6735, 0xB6E4, 0x6736, 0x965C, + 0x6737, 0x965D, 0x6738, 0x965E, 0x6739, 0x965F, 0x673A, 0xBBFA, + 0x673B, 0x9660, 0x673C, 0x9661, 0x673D, 0xD0E0, 0x673E, 0x9662, + 0x673F, 0x9663, 0x6740, 0xC9B1, 0x6741, 0x9664, 0x6742, 0xD4D3, + 0x6743, 0xC8A8, 0x6744, 0x9665, 0x6745, 0x9666, 0x6746, 0xB8CB, + 0x6747, 0x9667, 0x6748, 0xE8BE, 0x6749, 0xC9BC, 0x674A, 0x9668, + 0x674B, 0x9669, 0x674C, 0xE8BB, 0x674D, 0x966A, 0x674E, 0xC0EE, + 0x674F, 0xD0D3, 0x6750, 0xB2C4, 0x6751, 0xB4E5, 0x6752, 0x966B, + 0x6753, 0xE8BC, 0x6754, 0x966C, 0x6755, 0x966D, 0x6756, 0xD5C8, + 0x6757, 0x966E, 0x6758, 0x966F, 0x6759, 0x9670, 0x675A, 0x9671, + 0x675B, 0x9672, 0x675C, 0xB6C5, 0x675D, 0x9673, 0x675E, 0xE8BD, + 0x675F, 0xCAF8, 0x6760, 0xB8DC, 0x6761, 0xCCF5, 0x6762, 0x9674, + 0x6763, 0x9675, 0x6764, 0x9676, 0x6765, 0xC0B4, 0x6766, 0x9677, + 0x6767, 0x9678, 0x6768, 0xD1EE, 0x6769, 0xE8BF, 0x676A, 0xE8C2, + 0x676B, 0x9679, 0x676C, 0x967A, 0x676D, 0xBABC, 0x676E, 0x967B, + 0x676F, 0xB1AD, 0x6770, 0xBDDC, 0x6771, 0x967C, 0x6772, 0xEABD, + 0x6773, 0xE8C3, 0x6774, 0x967D, 0x6775, 0xE8C6, 0x6776, 0x967E, + 0x6777, 0xE8CB, 0x6778, 0x9680, 0x6779, 0x9681, 0x677A, 0x9682, + 0x677B, 0x9683, 0x677C, 0xE8CC, 0x677D, 0x9684, 0x677E, 0xCBC9, + 0x677F, 0xB0E5, 0x6780, 0x9685, 0x6781, 0xBCAB, 0x6782, 0x9686, + 0x6783, 0x9687, 0x6784, 0xB9B9, 0x6785, 0x9688, 0x6786, 0x9689, + 0x6787, 0xE8C1, 0x6788, 0x968A, 0x6789, 0xCDF7, 0x678A, 0x968B, + 0x678B, 0xE8CA, 0x678C, 0x968C, 0x678D, 0x968D, 0x678E, 0x968E, + 0x678F, 0x968F, 0x6790, 0xCEF6, 0x6791, 0x9690, 0x6792, 0x9691, + 0x6793, 0x9692, 0x6794, 0x9693, 0x6795, 0xD5ED, 0x6796, 0x9694, + 0x6797, 0xC1D6, 0x6798, 0xE8C4, 0x6799, 0x9695, 0x679A, 0xC3B6, + 0x679B, 0x9696, 0x679C, 0xB9FB, 0x679D, 0xD6A6, 0x679E, 0xE8C8, + 0x679F, 0x9697, 0x67A0, 0x9698, 0x67A1, 0x9699, 0x67A2, 0xCAE0, + 0x67A3, 0xD4E6, 0x67A4, 0x969A, 0x67A5, 0xE8C0, 0x67A6, 0x969B, + 0x67A7, 0xE8C5, 0x67A8, 0xE8C7, 0x67A9, 0x969C, 0x67AA, 0xC7B9, + 0x67AB, 0xB7E3, 0x67AC, 0x969D, 0x67AD, 0xE8C9, 0x67AE, 0x969E, + 0x67AF, 0xBFDD, 0x67B0, 0xE8D2, 0x67B1, 0x969F, 0x67B2, 0x96A0, + 0x67B3, 0xE8D7, 0x67B4, 0x96A1, 0x67B5, 0xE8D5, 0x67B6, 0xBCDC, + 0x67B7, 0xBCCF, 0x67B8, 0xE8DB, 0x67B9, 0x96A2, 0x67BA, 0x96A3, + 0x67BB, 0x96A4, 0x67BC, 0x96A5, 0x67BD, 0x96A6, 0x67BE, 0x96A7, + 0x67BF, 0x96A8, 0x67C0, 0x96A9, 0x67C1, 0xE8DE, 0x67C2, 0x96AA, + 0x67C3, 0xE8DA, 0x67C4, 0xB1FA, 0x67C5, 0x96AB, 0x67C6, 0x96AC, + 0x67C7, 0x96AD, 0x67C8, 0x96AE, 0x67C9, 0x96AF, 0x67CA, 0x96B0, + 0x67CB, 0x96B1, 0x67CC, 0x96B2, 0x67CD, 0x96B3, 0x67CE, 0x96B4, + 0x67CF, 0xB0D8, 0x67D0, 0xC4B3, 0x67D1, 0xB8CC, 0x67D2, 0xC6E2, + 0x67D3, 0xC8BE, 0x67D4, 0xC8E1, 0x67D5, 0x96B5, 0x67D6, 0x96B6, + 0x67D7, 0x96B7, 0x67D8, 0xE8CF, 0x67D9, 0xE8D4, 0x67DA, 0xE8D6, + 0x67DB, 0x96B8, 0x67DC, 0xB9F1, 0x67DD, 0xE8D8, 0x67DE, 0xD7F5, + 0x67DF, 0x96B9, 0x67E0, 0xC4FB, 0x67E1, 0x96BA, 0x67E2, 0xE8DC, + 0x67E3, 0x96BB, 0x67E4, 0x96BC, 0x67E5, 0xB2E9, 0x67E6, 0x96BD, + 0x67E7, 0x96BE, 0x67E8, 0x96BF, 0x67E9, 0xE8D1, 0x67EA, 0x96C0, + 0x67EB, 0x96C1, 0x67EC, 0xBCED, 0x67ED, 0x96C2, 0x67EE, 0x96C3, + 0x67EF, 0xBFC2, 0x67F0, 0xE8CD, 0x67F1, 0xD6F9, 0x67F2, 0x96C4, + 0x67F3, 0xC1F8, 0x67F4, 0xB2F1, 0x67F5, 0x96C5, 0x67F6, 0x96C6, + 0x67F7, 0x96C7, 0x67F8, 0x96C8, 0x67F9, 0x96C9, 0x67FA, 0x96CA, + 0x67FB, 0x96CB, 0x67FC, 0x96CC, 0x67FD, 0xE8DF, 0x67FE, 0x96CD, + 0x67FF, 0xCAC1, 0x6800, 0xE8D9, 0x6801, 0x96CE, 0x6802, 0x96CF, + 0x6803, 0x96D0, 0x6804, 0x96D1, 0x6805, 0xD5A4, 0x6806, 0x96D2, + 0x6807, 0xB1EA, 0x6808, 0xD5BB, 0x6809, 0xE8CE, 0x680A, 0xE8D0, + 0x680B, 0xB6B0, 0x680C, 0xE8D3, 0x680D, 0x96D3, 0x680E, 0xE8DD, + 0x680F, 0xC0B8, 0x6810, 0x96D4, 0x6811, 0xCAF7, 0x6812, 0x96D5, + 0x6813, 0xCBA8, 0x6814, 0x96D6, 0x6815, 0x96D7, 0x6816, 0xC6DC, + 0x6817, 0xC0F5, 0x6818, 0x96D8, 0x6819, 0x96D9, 0x681A, 0x96DA, + 0x681B, 0x96DB, 0x681C, 0x96DC, 0x681D, 0xE8E9, 0x681E, 0x96DD, + 0x681F, 0x96DE, 0x6820, 0x96DF, 0x6821, 0xD0A3, 0x6822, 0x96E0, + 0x6823, 0x96E1, 0x6824, 0x96E2, 0x6825, 0x96E3, 0x6826, 0x96E4, + 0x6827, 0x96E5, 0x6828, 0x96E6, 0x6829, 0xE8F2, 0x682A, 0xD6EA, + 0x682B, 0x96E7, 0x682C, 0x96E8, 0x682D, 0x96E9, 0x682E, 0x96EA, + 0x682F, 0x96EB, 0x6830, 0x96EC, 0x6831, 0x96ED, 0x6832, 0xE8E0, + 0x6833, 0xE8E1, 0x6834, 0x96EE, 0x6835, 0x96EF, 0x6836, 0x96F0, + 0x6837, 0xD1F9, 0x6838, 0xBACB, 0x6839, 0xB8F9, 0x683A, 0x96F1, + 0x683B, 0x96F2, 0x683C, 0xB8F1, 0x683D, 0xD4D4, 0x683E, 0xE8EF, + 0x683F, 0x96F3, 0x6840, 0xE8EE, 0x6841, 0xE8EC, 0x6842, 0xB9F0, + 0x6843, 0xCCD2, 0x6844, 0xE8E6, 0x6845, 0xCEA6, 0x6846, 0xBFF2, + 0x6847, 0x96F4, 0x6848, 0xB0B8, 0x6849, 0xE8F1, 0x684A, 0xE8F0, + 0x684B, 0x96F5, 0x684C, 0xD7C0, 0x684D, 0x96F6, 0x684E, 0xE8E4, + 0x684F, 0x96F7, 0x6850, 0xCDA9, 0x6851, 0xC9A3, 0x6852, 0x96F8, + 0x6853, 0xBBB8, 0x6854, 0xBDDB, 0x6855, 0xE8EA, 0x6856, 0x96F9, + 0x6857, 0x96FA, 0x6858, 0x96FB, 0x6859, 0x96FC, 0x685A, 0x96FD, + 0x685B, 0x96FE, 0x685C, 0x9740, 0x685D, 0x9741, 0x685E, 0x9742, + 0x685F, 0x9743, 0x6860, 0xE8E2, 0x6861, 0xE8E3, 0x6862, 0xE8E5, + 0x6863, 0xB5B5, 0x6864, 0xE8E7, 0x6865, 0xC7C5, 0x6866, 0xE8EB, + 0x6867, 0xE8ED, 0x6868, 0xBDB0, 0x6869, 0xD7AE, 0x686A, 0x9744, + 0x686B, 0xE8F8, 0x686C, 0x9745, 0x686D, 0x9746, 0x686E, 0x9747, + 0x686F, 0x9748, 0x6870, 0x9749, 0x6871, 0x974A, 0x6872, 0x974B, + 0x6873, 0x974C, 0x6874, 0xE8F5, 0x6875, 0x974D, 0x6876, 0xCDB0, + 0x6877, 0xE8F6, 0x6878, 0x974E, 0x6879, 0x974F, 0x687A, 0x9750, + 0x687B, 0x9751, 0x687C, 0x9752, 0x687D, 0x9753, 0x687E, 0x9754, + 0x687F, 0x9755, 0x6880, 0x9756, 0x6881, 0xC1BA, 0x6882, 0x9757, + 0x6883, 0xE8E8, 0x6884, 0x9758, 0x6885, 0xC3B7, 0x6886, 0xB0F0, + 0x6887, 0x9759, 0x6888, 0x975A, 0x6889, 0x975B, 0x688A, 0x975C, + 0x688B, 0x975D, 0x688C, 0x975E, 0x688D, 0x975F, 0x688E, 0x9760, + 0x688F, 0xE8F4, 0x6890, 0x9761, 0x6891, 0x9762, 0x6892, 0x9763, + 0x6893, 0xE8F7, 0x6894, 0x9764, 0x6895, 0x9765, 0x6896, 0x9766, + 0x6897, 0xB9A3, 0x6898, 0x9767, 0x6899, 0x9768, 0x689A, 0x9769, + 0x689B, 0x976A, 0x689C, 0x976B, 0x689D, 0x976C, 0x689E, 0x976D, + 0x689F, 0x976E, 0x68A0, 0x976F, 0x68A1, 0x9770, 0x68A2, 0xC9D2, + 0x68A3, 0x9771, 0x68A4, 0x9772, 0x68A5, 0x9773, 0x68A6, 0xC3CE, + 0x68A7, 0xCEE0, 0x68A8, 0xC0E6, 0x68A9, 0x9774, 0x68AA, 0x9775, + 0x68AB, 0x9776, 0x68AC, 0x9777, 0x68AD, 0xCBF3, 0x68AE, 0x9778, + 0x68AF, 0xCCDD, 0x68B0, 0xD0B5, 0x68B1, 0x9779, 0x68B2, 0x977A, + 0x68B3, 0xCAE1, 0x68B4, 0x977B, 0x68B5, 0xE8F3, 0x68B6, 0x977C, + 0x68B7, 0x977D, 0x68B8, 0x977E, 0x68B9, 0x9780, 0x68BA, 0x9781, + 0x68BB, 0x9782, 0x68BC, 0x9783, 0x68BD, 0x9784, 0x68BE, 0x9785, + 0x68BF, 0x9786, 0x68C0, 0xBCEC, 0x68C1, 0x9787, 0x68C2, 0xE8F9, + 0x68C3, 0x9788, 0x68C4, 0x9789, 0x68C5, 0x978A, 0x68C6, 0x978B, + 0x68C7, 0x978C, 0x68C8, 0x978D, 0x68C9, 0xC3DE, 0x68CA, 0x978E, + 0x68CB, 0xC6E5, 0x68CC, 0x978F, 0x68CD, 0xB9F7, 0x68CE, 0x9790, + 0x68CF, 0x9791, 0x68D0, 0x9792, 0x68D1, 0x9793, 0x68D2, 0xB0F4, + 0x68D3, 0x9794, 0x68D4, 0x9795, 0x68D5, 0xD7D8, 0x68D6, 0x9796, + 0x68D7, 0x9797, 0x68D8, 0xBCAC, 0x68D9, 0x9798, 0x68DA, 0xC5EF, + 0x68DB, 0x9799, 0x68DC, 0x979A, 0x68DD, 0x979B, 0x68DE, 0x979C, + 0x68DF, 0x979D, 0x68E0, 0xCCC4, 0x68E1, 0x979E, 0x68E2, 0x979F, + 0x68E3, 0xE9A6, 0x68E4, 0x97A0, 0x68E5, 0x97A1, 0x68E6, 0x97A2, + 0x68E7, 0x97A3, 0x68E8, 0x97A4, 0x68E9, 0x97A5, 0x68EA, 0x97A6, + 0x68EB, 0x97A7, 0x68EC, 0x97A8, 0x68ED, 0x97A9, 0x68EE, 0xC9AD, + 0x68EF, 0x97AA, 0x68F0, 0xE9A2, 0x68F1, 0xC0E2, 0x68F2, 0x97AB, + 0x68F3, 0x97AC, 0x68F4, 0x97AD, 0x68F5, 0xBFC3, 0x68F6, 0x97AE, + 0x68F7, 0x97AF, 0x68F8, 0x97B0, 0x68F9, 0xE8FE, 0x68FA, 0xB9D7, + 0x68FB, 0x97B1, 0x68FC, 0xE8FB, 0x68FD, 0x97B2, 0x68FE, 0x97B3, + 0x68FF, 0x97B4, 0x6900, 0x97B5, 0x6901, 0xE9A4, 0x6902, 0x97B6, + 0x6903, 0x97B7, 0x6904, 0x97B8, 0x6905, 0xD2CE, 0x6906, 0x97B9, + 0x6907, 0x97BA, 0x6908, 0x97BB, 0x6909, 0x97BC, 0x690A, 0x97BD, + 0x690B, 0xE9A3, 0x690C, 0x97BE, 0x690D, 0xD6B2, 0x690E, 0xD7B5, + 0x690F, 0x97BF, 0x6910, 0xE9A7, 0x6911, 0x97C0, 0x6912, 0xBDB7, + 0x6913, 0x97C1, 0x6914, 0x97C2, 0x6915, 0x97C3, 0x6916, 0x97C4, + 0x6917, 0x97C5, 0x6918, 0x97C6, 0x6919, 0x97C7, 0x691A, 0x97C8, + 0x691B, 0x97C9, 0x691C, 0x97CA, 0x691D, 0x97CB, 0x691E, 0x97CC, + 0x691F, 0xE8FC, 0x6920, 0xE8FD, 0x6921, 0x97CD, 0x6922, 0x97CE, + 0x6923, 0x97CF, 0x6924, 0xE9A1, 0x6925, 0x97D0, 0x6926, 0x97D1, + 0x6927, 0x97D2, 0x6928, 0x97D3, 0x6929, 0x97D4, 0x692A, 0x97D5, + 0x692B, 0x97D6, 0x692C, 0x97D7, 0x692D, 0xCDD6, 0x692E, 0x97D8, + 0x692F, 0x97D9, 0x6930, 0xD2AC, 0x6931, 0x97DA, 0x6932, 0x97DB, + 0x6933, 0x97DC, 0x6934, 0xE9B2, 0x6935, 0x97DD, 0x6936, 0x97DE, + 0x6937, 0x97DF, 0x6938, 0x97E0, 0x6939, 0xE9A9, 0x693A, 0x97E1, + 0x693B, 0x97E2, 0x693C, 0x97E3, 0x693D, 0xB4AA, 0x693E, 0x97E4, + 0x693F, 0xB4BB, 0x6940, 0x97E5, 0x6941, 0x97E6, 0x6942, 0xE9AB, + 0x6943, 0x97E7, 0x6944, 0x97E8, 0x6945, 0x97E9, 0x6946, 0x97EA, + 0x6947, 0x97EB, 0x6948, 0x97EC, 0x6949, 0x97ED, 0x694A, 0x97EE, + 0x694B, 0x97EF, 0x694C, 0x97F0, 0x694D, 0x97F1, 0x694E, 0x97F2, + 0x694F, 0x97F3, 0x6950, 0x97F4, 0x6951, 0x97F5, 0x6952, 0x97F6, + 0x6953, 0x97F7, 0x6954, 0xD0A8, 0x6955, 0x97F8, 0x6956, 0x97F9, + 0x6957, 0xE9A5, 0x6958, 0x97FA, 0x6959, 0x97FB, 0x695A, 0xB3FE, + 0x695B, 0x97FC, 0x695C, 0x97FD, 0x695D, 0xE9AC, 0x695E, 0xC0E3, + 0x695F, 0x97FE, 0x6960, 0xE9AA, 0x6961, 0x9840, 0x6962, 0x9841, + 0x6963, 0xE9B9, 0x6964, 0x9842, 0x6965, 0x9843, 0x6966, 0xE9B8, + 0x6967, 0x9844, 0x6968, 0x9845, 0x6969, 0x9846, 0x696A, 0x9847, + 0x696B, 0xE9AE, 0x696C, 0x9848, 0x696D, 0x9849, 0x696E, 0xE8FA, + 0x696F, 0x984A, 0x6970, 0x984B, 0x6971, 0xE9A8, 0x6972, 0x984C, + 0x6973, 0x984D, 0x6974, 0x984E, 0x6975, 0x984F, 0x6976, 0x9850, + 0x6977, 0xBFAC, 0x6978, 0xE9B1, 0x6979, 0xE9BA, 0x697A, 0x9851, + 0x697B, 0x9852, 0x697C, 0xC2A5, 0x697D, 0x9853, 0x697E, 0x9854, + 0x697F, 0x9855, 0x6980, 0xE9AF, 0x6981, 0x9856, 0x6982, 0xB8C5, + 0x6983, 0x9857, 0x6984, 0xE9AD, 0x6985, 0x9858, 0x6986, 0xD3DC, + 0x6987, 0xE9B4, 0x6988, 0xE9B5, 0x6989, 0xE9B7, 0x698A, 0x9859, + 0x698B, 0x985A, 0x698C, 0x985B, 0x698D, 0xE9C7, 0x698E, 0x985C, + 0x698F, 0x985D, 0x6990, 0x985E, 0x6991, 0x985F, 0x6992, 0x9860, + 0x6993, 0x9861, 0x6994, 0xC0C6, 0x6995, 0xE9C5, 0x6996, 0x9862, + 0x6997, 0x9863, 0x6998, 0xE9B0, 0x6999, 0x9864, 0x699A, 0x9865, + 0x699B, 0xE9BB, 0x699C, 0xB0F1, 0x699D, 0x9866, 0x699E, 0x9867, + 0x699F, 0x9868, 0x69A0, 0x9869, 0x69A1, 0x986A, 0x69A2, 0x986B, + 0x69A3, 0x986C, 0x69A4, 0x986D, 0x69A5, 0x986E, 0x69A6, 0x986F, + 0x69A7, 0xE9BC, 0x69A8, 0xD5A5, 0x69A9, 0x9870, 0x69AA, 0x9871, + 0x69AB, 0xE9BE, 0x69AC, 0x9872, 0x69AD, 0xE9BF, 0x69AE, 0x9873, + 0x69AF, 0x9874, 0x69B0, 0x9875, 0x69B1, 0xE9C1, 0x69B2, 0x9876, + 0x69B3, 0x9877, 0x69B4, 0xC1F1, 0x69B5, 0x9878, 0x69B6, 0x9879, + 0x69B7, 0xC8B6, 0x69B8, 0x987A, 0x69B9, 0x987B, 0x69BA, 0x987C, + 0x69BB, 0xE9BD, 0x69BC, 0x987D, 0x69BD, 0x987E, 0x69BE, 0x9880, + 0x69BF, 0x9881, 0x69C0, 0x9882, 0x69C1, 0xE9C2, 0x69C2, 0x9883, + 0x69C3, 0x9884, 0x69C4, 0x9885, 0x69C5, 0x9886, 0x69C6, 0x9887, + 0x69C7, 0x9888, 0x69C8, 0x9889, 0x69C9, 0x988A, 0x69CA, 0xE9C3, + 0x69CB, 0x988B, 0x69CC, 0xE9B3, 0x69CD, 0x988C, 0x69CE, 0xE9B6, + 0x69CF, 0x988D, 0x69D0, 0xBBB1, 0x69D1, 0x988E, 0x69D2, 0x988F, + 0x69D3, 0x9890, 0x69D4, 0xE9C0, 0x69D5, 0x9891, 0x69D6, 0x9892, + 0x69D7, 0x9893, 0x69D8, 0x9894, 0x69D9, 0x9895, 0x69DA, 0x9896, + 0x69DB, 0xBCF7, 0x69DC, 0x9897, 0x69DD, 0x9898, 0x69DE, 0x9899, + 0x69DF, 0xE9C4, 0x69E0, 0xE9C6, 0x69E1, 0x989A, 0x69E2, 0x989B, + 0x69E3, 0x989C, 0x69E4, 0x989D, 0x69E5, 0x989E, 0x69E6, 0x989F, + 0x69E7, 0x98A0, 0x69E8, 0x98A1, 0x69E9, 0x98A2, 0x69EA, 0x98A3, + 0x69EB, 0x98A4, 0x69EC, 0x98A5, 0x69ED, 0xE9CA, 0x69EE, 0x98A6, + 0x69EF, 0x98A7, 0x69F0, 0x98A8, 0x69F1, 0x98A9, 0x69F2, 0xE9CE, + 0x69F3, 0x98AA, 0x69F4, 0x98AB, 0x69F5, 0x98AC, 0x69F6, 0x98AD, + 0x69F7, 0x98AE, 0x69F8, 0x98AF, 0x69F9, 0x98B0, 0x69FA, 0x98B1, + 0x69FB, 0x98B2, 0x69FC, 0x98B3, 0x69FD, 0xB2DB, 0x69FE, 0x98B4, + 0x69FF, 0xE9C8, 0x6A00, 0x98B5, 0x6A01, 0x98B6, 0x6A02, 0x98B7, + 0x6A03, 0x98B8, 0x6A04, 0x98B9, 0x6A05, 0x98BA, 0x6A06, 0x98BB, + 0x6A07, 0x98BC, 0x6A08, 0x98BD, 0x6A09, 0x98BE, 0x6A0A, 0xB7AE, + 0x6A0B, 0x98BF, 0x6A0C, 0x98C0, 0x6A0D, 0x98C1, 0x6A0E, 0x98C2, + 0x6A0F, 0x98C3, 0x6A10, 0x98C4, 0x6A11, 0x98C5, 0x6A12, 0x98C6, + 0x6A13, 0x98C7, 0x6A14, 0x98C8, 0x6A15, 0x98C9, 0x6A16, 0x98CA, + 0x6A17, 0xE9CB, 0x6A18, 0xE9CC, 0x6A19, 0x98CB, 0x6A1A, 0x98CC, + 0x6A1B, 0x98CD, 0x6A1C, 0x98CE, 0x6A1D, 0x98CF, 0x6A1E, 0x98D0, + 0x6A1F, 0xD5C1, 0x6A20, 0x98D1, 0x6A21, 0xC4A3, 0x6A22, 0x98D2, + 0x6A23, 0x98D3, 0x6A24, 0x98D4, 0x6A25, 0x98D5, 0x6A26, 0x98D6, + 0x6A27, 0x98D7, 0x6A28, 0xE9D8, 0x6A29, 0x98D8, 0x6A2A, 0xBAE1, + 0x6A2B, 0x98D9, 0x6A2C, 0x98DA, 0x6A2D, 0x98DB, 0x6A2E, 0x98DC, + 0x6A2F, 0xE9C9, 0x6A30, 0x98DD, 0x6A31, 0xD3A3, 0x6A32, 0x98DE, + 0x6A33, 0x98DF, 0x6A34, 0x98E0, 0x6A35, 0xE9D4, 0x6A36, 0x98E1, + 0x6A37, 0x98E2, 0x6A38, 0x98E3, 0x6A39, 0x98E4, 0x6A3A, 0x98E5, + 0x6A3B, 0x98E6, 0x6A3C, 0x98E7, 0x6A3D, 0xE9D7, 0x6A3E, 0xE9D0, + 0x6A3F, 0x98E8, 0x6A40, 0x98E9, 0x6A41, 0x98EA, 0x6A42, 0x98EB, + 0x6A43, 0x98EC, 0x6A44, 0xE9CF, 0x6A45, 0x98ED, 0x6A46, 0x98EE, + 0x6A47, 0xC7C1, 0x6A48, 0x98EF, 0x6A49, 0x98F0, 0x6A4A, 0x98F1, + 0x6A4B, 0x98F2, 0x6A4C, 0x98F3, 0x6A4D, 0x98F4, 0x6A4E, 0x98F5, + 0x6A4F, 0x98F6, 0x6A50, 0xE9D2, 0x6A51, 0x98F7, 0x6A52, 0x98F8, + 0x6A53, 0x98F9, 0x6A54, 0x98FA, 0x6A55, 0x98FB, 0x6A56, 0x98FC, + 0x6A57, 0x98FD, 0x6A58, 0xE9D9, 0x6A59, 0xB3C8, 0x6A5A, 0x98FE, + 0x6A5B, 0xE9D3, 0x6A5C, 0x9940, 0x6A5D, 0x9941, 0x6A5E, 0x9942, + 0x6A5F, 0x9943, 0x6A60, 0x9944, 0x6A61, 0xCFF0, 0x6A62, 0x9945, + 0x6A63, 0x9946, 0x6A64, 0x9947, 0x6A65, 0xE9CD, 0x6A66, 0x9948, + 0x6A67, 0x9949, 0x6A68, 0x994A, 0x6A69, 0x994B, 0x6A6A, 0x994C, + 0x6A6B, 0x994D, 0x6A6C, 0x994E, 0x6A6D, 0x994F, 0x6A6E, 0x9950, + 0x6A6F, 0x9951, 0x6A70, 0x9952, 0x6A71, 0xB3F7, 0x6A72, 0x9953, + 0x6A73, 0x9954, 0x6A74, 0x9955, 0x6A75, 0x9956, 0x6A76, 0x9957, + 0x6A77, 0x9958, 0x6A78, 0x9959, 0x6A79, 0xE9D6, 0x6A7A, 0x995A, + 0x6A7B, 0x995B, 0x6A7C, 0xE9DA, 0x6A7D, 0x995C, 0x6A7E, 0x995D, + 0x6A7F, 0x995E, 0x6A80, 0xCCB4, 0x6A81, 0x995F, 0x6A82, 0x9960, + 0x6A83, 0x9961, 0x6A84, 0xCFAD, 0x6A85, 0x9962, 0x6A86, 0x9963, + 0x6A87, 0x9964, 0x6A88, 0x9965, 0x6A89, 0x9966, 0x6A8A, 0x9967, + 0x6A8B, 0x9968, 0x6A8C, 0x9969, 0x6A8D, 0x996A, 0x6A8E, 0xE9D5, + 0x6A8F, 0x996B, 0x6A90, 0xE9DC, 0x6A91, 0xE9DB, 0x6A92, 0x996C, + 0x6A93, 0x996D, 0x6A94, 0x996E, 0x6A95, 0x996F, 0x6A96, 0x9970, + 0x6A97, 0xE9DE, 0x6A98, 0x9971, 0x6A99, 0x9972, 0x6A9A, 0x9973, + 0x6A9B, 0x9974, 0x6A9C, 0x9975, 0x6A9D, 0x9976, 0x6A9E, 0x9977, + 0x6A9F, 0x9978, 0x6AA0, 0xE9D1, 0x6AA1, 0x9979, 0x6AA2, 0x997A, + 0x6AA3, 0x997B, 0x6AA4, 0x997C, 0x6AA5, 0x997D, 0x6AA6, 0x997E, + 0x6AA7, 0x9980, 0x6AA8, 0x9981, 0x6AA9, 0xE9DD, 0x6AAA, 0x9982, + 0x6AAB, 0xE9DF, 0x6AAC, 0xC3CA, 0x6AAD, 0x9983, 0x6AAE, 0x9984, + 0x6AAF, 0x9985, 0x6AB0, 0x9986, 0x6AB1, 0x9987, 0x6AB2, 0x9988, + 0x6AB3, 0x9989, 0x6AB4, 0x998A, 0x6AB5, 0x998B, 0x6AB6, 0x998C, + 0x6AB7, 0x998D, 0x6AB8, 0x998E, 0x6AB9, 0x998F, 0x6ABA, 0x9990, + 0x6ABB, 0x9991, 0x6ABC, 0x9992, 0x6ABD, 0x9993, 0x6ABE, 0x9994, + 0x6ABF, 0x9995, 0x6AC0, 0x9996, 0x6AC1, 0x9997, 0x6AC2, 0x9998, + 0x6AC3, 0x9999, 0x6AC4, 0x999A, 0x6AC5, 0x999B, 0x6AC6, 0x999C, + 0x6AC7, 0x999D, 0x6AC8, 0x999E, 0x6AC9, 0x999F, 0x6ACA, 0x99A0, + 0x6ACB, 0x99A1, 0x6ACC, 0x99A2, 0x6ACD, 0x99A3, 0x6ACE, 0x99A4, + 0x6ACF, 0x99A5, 0x6AD0, 0x99A6, 0x6AD1, 0x99A7, 0x6AD2, 0x99A8, + 0x6AD3, 0x99A9, 0x6AD4, 0x99AA, 0x6AD5, 0x99AB, 0x6AD6, 0x99AC, + 0x6AD7, 0x99AD, 0x6AD8, 0x99AE, 0x6AD9, 0x99AF, 0x6ADA, 0x99B0, + 0x6ADB, 0x99B1, 0x6ADC, 0x99B2, 0x6ADD, 0x99B3, 0x6ADE, 0x99B4, + 0x6ADF, 0x99B5, 0x6AE0, 0x99B6, 0x6AE1, 0x99B7, 0x6AE2, 0x99B8, + 0x6AE3, 0x99B9, 0x6AE4, 0x99BA, 0x6AE5, 0x99BB, 0x6AE6, 0x99BC, + 0x6AE7, 0x99BD, 0x6AE8, 0x99BE, 0x6AE9, 0x99BF, 0x6AEA, 0x99C0, + 0x6AEB, 0x99C1, 0x6AEC, 0x99C2, 0x6AED, 0x99C3, 0x6AEE, 0x99C4, + 0x6AEF, 0x99C5, 0x6AF0, 0x99C6, 0x6AF1, 0x99C7, 0x6AF2, 0x99C8, + 0x6AF3, 0x99C9, 0x6AF4, 0x99CA, 0x6AF5, 0x99CB, 0x6AF6, 0x99CC, + 0x6AF7, 0x99CD, 0x6AF8, 0x99CE, 0x6AF9, 0x99CF, 0x6AFA, 0x99D0, + 0x6AFB, 0x99D1, 0x6AFC, 0x99D2, 0x6AFD, 0x99D3, 0x6AFE, 0x99D4, + 0x6AFF, 0x99D5, 0x6B00, 0x99D6, 0x6B01, 0x99D7, 0x6B02, 0x99D8, + 0x6B03, 0x99D9, 0x6B04, 0x99DA, 0x6B05, 0x99DB, 0x6B06, 0x99DC, + 0x6B07, 0x99DD, 0x6B08, 0x99DE, 0x6B09, 0x99DF, 0x6B0A, 0x99E0, + 0x6B0B, 0x99E1, 0x6B0C, 0x99E2, 0x6B0D, 0x99E3, 0x6B0E, 0x99E4, + 0x6B0F, 0x99E5, 0x6B10, 0x99E6, 0x6B11, 0x99E7, 0x6B12, 0x99E8, + 0x6B13, 0x99E9, 0x6B14, 0x99EA, 0x6B15, 0x99EB, 0x6B16, 0x99EC, + 0x6B17, 0x99ED, 0x6B18, 0x99EE, 0x6B19, 0x99EF, 0x6B1A, 0x99F0, + 0x6B1B, 0x99F1, 0x6B1C, 0x99F2, 0x6B1D, 0x99F3, 0x6B1E, 0x99F4, + 0x6B1F, 0x99F5, 0x6B20, 0xC7B7, 0x6B21, 0xB4CE, 0x6B22, 0xBBB6, + 0x6B23, 0xD0C0, 0x6B24, 0xECA3, 0x6B25, 0x99F6, 0x6B26, 0x99F7, + 0x6B27, 0xC5B7, 0x6B28, 0x99F8, 0x6B29, 0x99F9, 0x6B2A, 0x99FA, + 0x6B2B, 0x99FB, 0x6B2C, 0x99FC, 0x6B2D, 0x99FD, 0x6B2E, 0x99FE, + 0x6B2F, 0x9A40, 0x6B30, 0x9A41, 0x6B31, 0x9A42, 0x6B32, 0xD3FB, + 0x6B33, 0x9A43, 0x6B34, 0x9A44, 0x6B35, 0x9A45, 0x6B36, 0x9A46, + 0x6B37, 0xECA4, 0x6B38, 0x9A47, 0x6B39, 0xECA5, 0x6B3A, 0xC6DB, + 0x6B3B, 0x9A48, 0x6B3C, 0x9A49, 0x6B3D, 0x9A4A, 0x6B3E, 0xBFEE, + 0x6B3F, 0x9A4B, 0x6B40, 0x9A4C, 0x6B41, 0x9A4D, 0x6B42, 0x9A4E, + 0x6B43, 0xECA6, 0x6B44, 0x9A4F, 0x6B45, 0x9A50, 0x6B46, 0xECA7, + 0x6B47, 0xD0AA, 0x6B48, 0x9A51, 0x6B49, 0xC7B8, 0x6B4A, 0x9A52, + 0x6B4B, 0x9A53, 0x6B4C, 0xB8E8, 0x6B4D, 0x9A54, 0x6B4E, 0x9A55, + 0x6B4F, 0x9A56, 0x6B50, 0x9A57, 0x6B51, 0x9A58, 0x6B52, 0x9A59, + 0x6B53, 0x9A5A, 0x6B54, 0x9A5B, 0x6B55, 0x9A5C, 0x6B56, 0x9A5D, + 0x6B57, 0x9A5E, 0x6B58, 0x9A5F, 0x6B59, 0xECA8, 0x6B5A, 0x9A60, + 0x6B5B, 0x9A61, 0x6B5C, 0x9A62, 0x6B5D, 0x9A63, 0x6B5E, 0x9A64, + 0x6B5F, 0x9A65, 0x6B60, 0x9A66, 0x6B61, 0x9A67, 0x6B62, 0xD6B9, + 0x6B63, 0xD5FD, 0x6B64, 0xB4CB, 0x6B65, 0xB2BD, 0x6B66, 0xCEE4, + 0x6B67, 0xC6E7, 0x6B68, 0x9A68, 0x6B69, 0x9A69, 0x6B6A, 0xCDE1, + 0x6B6B, 0x9A6A, 0x6B6C, 0x9A6B, 0x6B6D, 0x9A6C, 0x6B6E, 0x9A6D, + 0x6B6F, 0x9A6E, 0x6B70, 0x9A6F, 0x6B71, 0x9A70, 0x6B72, 0x9A71, + 0x6B73, 0x9A72, 0x6B74, 0x9A73, 0x6B75, 0x9A74, 0x6B76, 0x9A75, + 0x6B77, 0x9A76, 0x6B78, 0x9A77, 0x6B79, 0xB4F5, 0x6B7A, 0x9A78, + 0x6B7B, 0xCBC0, 0x6B7C, 0xBCDF, 0x6B7D, 0x9A79, 0x6B7E, 0x9A7A, + 0x6B7F, 0x9A7B, 0x6B80, 0x9A7C, 0x6B81, 0xE9E2, 0x6B82, 0xE9E3, + 0x6B83, 0xD1EA, 0x6B84, 0xE9E5, 0x6B85, 0x9A7D, 0x6B86, 0xB4F9, + 0x6B87, 0xE9E4, 0x6B88, 0x9A7E, 0x6B89, 0xD1B3, 0x6B8A, 0xCAE2, + 0x6B8B, 0xB2D0, 0x6B8C, 0x9A80, 0x6B8D, 0xE9E8, 0x6B8E, 0x9A81, + 0x6B8F, 0x9A82, 0x6B90, 0x9A83, 0x6B91, 0x9A84, 0x6B92, 0xE9E6, + 0x6B93, 0xE9E7, 0x6B94, 0x9A85, 0x6B95, 0x9A86, 0x6B96, 0xD6B3, + 0x6B97, 0x9A87, 0x6B98, 0x9A88, 0x6B99, 0x9A89, 0x6B9A, 0xE9E9, + 0x6B9B, 0xE9EA, 0x6B9C, 0x9A8A, 0x6B9D, 0x9A8B, 0x6B9E, 0x9A8C, + 0x6B9F, 0x9A8D, 0x6BA0, 0x9A8E, 0x6BA1, 0xE9EB, 0x6BA2, 0x9A8F, + 0x6BA3, 0x9A90, 0x6BA4, 0x9A91, 0x6BA5, 0x9A92, 0x6BA6, 0x9A93, + 0x6BA7, 0x9A94, 0x6BA8, 0x9A95, 0x6BA9, 0x9A96, 0x6BAA, 0xE9EC, + 0x6BAB, 0x9A97, 0x6BAC, 0x9A98, 0x6BAD, 0x9A99, 0x6BAE, 0x9A9A, + 0x6BAF, 0x9A9B, 0x6BB0, 0x9A9C, 0x6BB1, 0x9A9D, 0x6BB2, 0x9A9E, + 0x6BB3, 0xECAF, 0x6BB4, 0xC5B9, 0x6BB5, 0xB6CE, 0x6BB6, 0x9A9F, + 0x6BB7, 0xD2F3, 0x6BB8, 0x9AA0, 0x6BB9, 0x9AA1, 0x6BBA, 0x9AA2, + 0x6BBB, 0x9AA3, 0x6BBC, 0x9AA4, 0x6BBD, 0x9AA5, 0x6BBE, 0x9AA6, + 0x6BBF, 0xB5EE, 0x6BC0, 0x9AA7, 0x6BC1, 0xBBD9, 0x6BC2, 0xECB1, + 0x6BC3, 0x9AA8, 0x6BC4, 0x9AA9, 0x6BC5, 0xD2E3, 0x6BC6, 0x9AAA, + 0x6BC7, 0x9AAB, 0x6BC8, 0x9AAC, 0x6BC9, 0x9AAD, 0x6BCA, 0x9AAE, + 0x6BCB, 0xCEE3, 0x6BCC, 0x9AAF, 0x6BCD, 0xC4B8, 0x6BCE, 0x9AB0, + 0x6BCF, 0xC3BF, 0x6BD0, 0x9AB1, 0x6BD1, 0x9AB2, 0x6BD2, 0xB6BE, + 0x6BD3, 0xD8B9, 0x6BD4, 0xB1C8, 0x6BD5, 0xB1CF, 0x6BD6, 0xB1D1, + 0x6BD7, 0xC5FE, 0x6BD8, 0x9AB3, 0x6BD9, 0xB1D0, 0x6BDA, 0x9AB4, + 0x6BDB, 0xC3AB, 0x6BDC, 0x9AB5, 0x6BDD, 0x9AB6, 0x6BDE, 0x9AB7, + 0x6BDF, 0x9AB8, 0x6BE0, 0x9AB9, 0x6BE1, 0xD5B1, 0x6BE2, 0x9ABA, + 0x6BE3, 0x9ABB, 0x6BE4, 0x9ABC, 0x6BE5, 0x9ABD, 0x6BE6, 0x9ABE, + 0x6BE7, 0x9ABF, 0x6BE8, 0x9AC0, 0x6BE9, 0x9AC1, 0x6BEA, 0xEBA4, + 0x6BEB, 0xBAC1, 0x6BEC, 0x9AC2, 0x6BED, 0x9AC3, 0x6BEE, 0x9AC4, + 0x6BEF, 0xCCBA, 0x6BF0, 0x9AC5, 0x6BF1, 0x9AC6, 0x6BF2, 0x9AC7, + 0x6BF3, 0xEBA5, 0x6BF4, 0x9AC8, 0x6BF5, 0xEBA7, 0x6BF6, 0x9AC9, + 0x6BF7, 0x9ACA, 0x6BF8, 0x9ACB, 0x6BF9, 0xEBA8, 0x6BFA, 0x9ACC, + 0x6BFB, 0x9ACD, 0x6BFC, 0x9ACE, 0x6BFD, 0xEBA6, 0x6BFE, 0x9ACF, + 0x6BFF, 0x9AD0, 0x6C00, 0x9AD1, 0x6C01, 0x9AD2, 0x6C02, 0x9AD3, + 0x6C03, 0x9AD4, 0x6C04, 0x9AD5, 0x6C05, 0xEBA9, 0x6C06, 0xEBAB, + 0x6C07, 0xEBAA, 0x6C08, 0x9AD6, 0x6C09, 0x9AD7, 0x6C0A, 0x9AD8, + 0x6C0B, 0x9AD9, 0x6C0C, 0x9ADA, 0x6C0D, 0xEBAC, 0x6C0E, 0x9ADB, + 0x6C0F, 0xCACF, 0x6C10, 0xD8B5, 0x6C11, 0xC3F1, 0x6C12, 0x9ADC, + 0x6C13, 0xC3A5, 0x6C14, 0xC6F8, 0x6C15, 0xEBAD, 0x6C16, 0xC4CA, + 0x6C17, 0x9ADD, 0x6C18, 0xEBAE, 0x6C19, 0xEBAF, 0x6C1A, 0xEBB0, + 0x6C1B, 0xB7D5, 0x6C1C, 0x9ADE, 0x6C1D, 0x9ADF, 0x6C1E, 0x9AE0, + 0x6C1F, 0xB7FA, 0x6C20, 0x9AE1, 0x6C21, 0xEBB1, 0x6C22, 0xC7E2, + 0x6C23, 0x9AE2, 0x6C24, 0xEBB3, 0x6C25, 0x9AE3, 0x6C26, 0xBAA4, + 0x6C27, 0xD1F5, 0x6C28, 0xB0B1, 0x6C29, 0xEBB2, 0x6C2A, 0xEBB4, + 0x6C2B, 0x9AE4, 0x6C2C, 0x9AE5, 0x6C2D, 0x9AE6, 0x6C2E, 0xB5AA, + 0x6C2F, 0xC2C8, 0x6C30, 0xC7E8, 0x6C31, 0x9AE7, 0x6C32, 0xEBB5, + 0x6C33, 0x9AE8, 0x6C34, 0xCBAE, 0x6C35, 0xE3DF, 0x6C36, 0x9AE9, + 0x6C37, 0x9AEA, 0x6C38, 0xD3C0, 0x6C39, 0x9AEB, 0x6C3A, 0x9AEC, + 0x6C3B, 0x9AED, 0x6C3C, 0x9AEE, 0x6C3D, 0xD9DB, 0x6C3E, 0x9AEF, + 0x6C3F, 0x9AF0, 0x6C40, 0xCDA1, 0x6C41, 0xD6AD, 0x6C42, 0xC7F3, + 0x6C43, 0x9AF1, 0x6C44, 0x9AF2, 0x6C45, 0x9AF3, 0x6C46, 0xD9E0, + 0x6C47, 0xBBE3, 0x6C48, 0x9AF4, 0x6C49, 0xBABA, 0x6C4A, 0xE3E2, + 0x6C4B, 0x9AF5, 0x6C4C, 0x9AF6, 0x6C4D, 0x9AF7, 0x6C4E, 0x9AF8, + 0x6C4F, 0x9AF9, 0x6C50, 0xCFAB, 0x6C51, 0x9AFA, 0x6C52, 0x9AFB, + 0x6C53, 0x9AFC, 0x6C54, 0xE3E0, 0x6C55, 0xC9C7, 0x6C56, 0x9AFD, + 0x6C57, 0xBAB9, 0x6C58, 0x9AFE, 0x6C59, 0x9B40, 0x6C5A, 0x9B41, + 0x6C5B, 0xD1B4, 0x6C5C, 0xE3E1, 0x6C5D, 0xC8EA, 0x6C5E, 0xB9AF, + 0x6C5F, 0xBDAD, 0x6C60, 0xB3D8, 0x6C61, 0xCEDB, 0x6C62, 0x9B42, + 0x6C63, 0x9B43, 0x6C64, 0xCCC0, 0x6C65, 0x9B44, 0x6C66, 0x9B45, + 0x6C67, 0x9B46, 0x6C68, 0xE3E8, 0x6C69, 0xE3E9, 0x6C6A, 0xCDF4, + 0x6C6B, 0x9B47, 0x6C6C, 0x9B48, 0x6C6D, 0x9B49, 0x6C6E, 0x9B4A, + 0x6C6F, 0x9B4B, 0x6C70, 0xCCAD, 0x6C71, 0x9B4C, 0x6C72, 0xBCB3, + 0x6C73, 0x9B4D, 0x6C74, 0xE3EA, 0x6C75, 0x9B4E, 0x6C76, 0xE3EB, + 0x6C77, 0x9B4F, 0x6C78, 0x9B50, 0x6C79, 0xD0DA, 0x6C7A, 0x9B51, + 0x6C7B, 0x9B52, 0x6C7C, 0x9B53, 0x6C7D, 0xC6FB, 0x6C7E, 0xB7DA, + 0x6C7F, 0x9B54, 0x6C80, 0x9B55, 0x6C81, 0xC7DF, 0x6C82, 0xD2CA, + 0x6C83, 0xCED6, 0x6C84, 0x9B56, 0x6C85, 0xE3E4, 0x6C86, 0xE3EC, + 0x6C87, 0x9B57, 0x6C88, 0xC9F2, 0x6C89, 0xB3C1, 0x6C8A, 0x9B58, + 0x6C8B, 0x9B59, 0x6C8C, 0xE3E7, 0x6C8D, 0x9B5A, 0x6C8E, 0x9B5B, + 0x6C8F, 0xC6E3, 0x6C90, 0xE3E5, 0x6C91, 0x9B5C, 0x6C92, 0x9B5D, + 0x6C93, 0xEDB3, 0x6C94, 0xE3E6, 0x6C95, 0x9B5E, 0x6C96, 0x9B5F, + 0x6C97, 0x9B60, 0x6C98, 0x9B61, 0x6C99, 0xC9B3, 0x6C9A, 0x9B62, + 0x6C9B, 0xC5E6, 0x6C9C, 0x9B63, 0x6C9D, 0x9B64, 0x6C9E, 0x9B65, + 0x6C9F, 0xB9B5, 0x6CA0, 0x9B66, 0x6CA1, 0xC3BB, 0x6CA2, 0x9B67, + 0x6CA3, 0xE3E3, 0x6CA4, 0xC5BD, 0x6CA5, 0xC1A4, 0x6CA6, 0xC2D9, + 0x6CA7, 0xB2D7, 0x6CA8, 0x9B68, 0x6CA9, 0xE3ED, 0x6CAA, 0xBBA6, + 0x6CAB, 0xC4AD, 0x6CAC, 0x9B69, 0x6CAD, 0xE3F0, 0x6CAE, 0xBEDA, + 0x6CAF, 0x9B6A, 0x6CB0, 0x9B6B, 0x6CB1, 0xE3FB, 0x6CB2, 0xE3F5, + 0x6CB3, 0xBAD3, 0x6CB4, 0x9B6C, 0x6CB5, 0x9B6D, 0x6CB6, 0x9B6E, + 0x6CB7, 0x9B6F, 0x6CB8, 0xB7D0, 0x6CB9, 0xD3CD, 0x6CBA, 0x9B70, + 0x6CBB, 0xD6CE, 0x6CBC, 0xD5D3, 0x6CBD, 0xB9C1, 0x6CBE, 0xD5B4, + 0x6CBF, 0xD1D8, 0x6CC0, 0x9B71, 0x6CC1, 0x9B72, 0x6CC2, 0x9B73, + 0x6CC3, 0x9B74, 0x6CC4, 0xD0B9, 0x6CC5, 0xC7F6, 0x6CC6, 0x9B75, + 0x6CC7, 0x9B76, 0x6CC8, 0x9B77, 0x6CC9, 0xC8AA, 0x6CCA, 0xB2B4, + 0x6CCB, 0x9B78, 0x6CCC, 0xC3DA, 0x6CCD, 0x9B79, 0x6CCE, 0x9B7A, + 0x6CCF, 0x9B7B, 0x6CD0, 0xE3EE, 0x6CD1, 0x9B7C, 0x6CD2, 0x9B7D, + 0x6CD3, 0xE3FC, 0x6CD4, 0xE3EF, 0x6CD5, 0xB7A8, 0x6CD6, 0xE3F7, + 0x6CD7, 0xE3F4, 0x6CD8, 0x9B7E, 0x6CD9, 0x9B80, 0x6CDA, 0x9B81, + 0x6CDB, 0xB7BA, 0x6CDC, 0x9B82, 0x6CDD, 0x9B83, 0x6CDE, 0xC5A2, + 0x6CDF, 0x9B84, 0x6CE0, 0xE3F6, 0x6CE1, 0xC5DD, 0x6CE2, 0xB2A8, + 0x6CE3, 0xC6FC, 0x6CE4, 0x9B85, 0x6CE5, 0xC4E0, 0x6CE6, 0x9B86, + 0x6CE7, 0x9B87, 0x6CE8, 0xD7A2, 0x6CE9, 0x9B88, 0x6CEA, 0xC0E1, + 0x6CEB, 0xE3F9, 0x6CEC, 0x9B89, 0x6CED, 0x9B8A, 0x6CEE, 0xE3FA, + 0x6CEF, 0xE3FD, 0x6CF0, 0xCCA9, 0x6CF1, 0xE3F3, 0x6CF2, 0x9B8B, + 0x6CF3, 0xD3BE, 0x6CF4, 0x9B8C, 0x6CF5, 0xB1C3, 0x6CF6, 0xEDB4, + 0x6CF7, 0xE3F1, 0x6CF8, 0xE3F2, 0x6CF9, 0x9B8D, 0x6CFA, 0xE3F8, + 0x6CFB, 0xD0BA, 0x6CFC, 0xC6C3, 0x6CFD, 0xD4F3, 0x6CFE, 0xE3FE, + 0x6CFF, 0x9B8E, 0x6D00, 0x9B8F, 0x6D01, 0xBDE0, 0x6D02, 0x9B90, + 0x6D03, 0x9B91, 0x6D04, 0xE4A7, 0x6D05, 0x9B92, 0x6D06, 0x9B93, + 0x6D07, 0xE4A6, 0x6D08, 0x9B94, 0x6D09, 0x9B95, 0x6D0A, 0x9B96, + 0x6D0B, 0xD1F3, 0x6D0C, 0xE4A3, 0x6D0D, 0x9B97, 0x6D0E, 0xE4A9, + 0x6D0F, 0x9B98, 0x6D10, 0x9B99, 0x6D11, 0x9B9A, 0x6D12, 0xC8F7, + 0x6D13, 0x9B9B, 0x6D14, 0x9B9C, 0x6D15, 0x9B9D, 0x6D16, 0x9B9E, + 0x6D17, 0xCFB4, 0x6D18, 0x9B9F, 0x6D19, 0xE4A8, 0x6D1A, 0xE4AE, + 0x6D1B, 0xC2E5, 0x6D1C, 0x9BA0, 0x6D1D, 0x9BA1, 0x6D1E, 0xB6B4, + 0x6D1F, 0x9BA2, 0x6D20, 0x9BA3, 0x6D21, 0x9BA4, 0x6D22, 0x9BA5, + 0x6D23, 0x9BA6, 0x6D24, 0x9BA7, 0x6D25, 0xBDF2, 0x6D26, 0x9BA8, + 0x6D27, 0xE4A2, 0x6D28, 0x9BA9, 0x6D29, 0x9BAA, 0x6D2A, 0xBAE9, + 0x6D2B, 0xE4AA, 0x6D2C, 0x9BAB, 0x6D2D, 0x9BAC, 0x6D2E, 0xE4AC, + 0x6D2F, 0x9BAD, 0x6D30, 0x9BAE, 0x6D31, 0xB6FD, 0x6D32, 0xD6DE, + 0x6D33, 0xE4B2, 0x6D34, 0x9BAF, 0x6D35, 0xE4AD, 0x6D36, 0x9BB0, + 0x6D37, 0x9BB1, 0x6D38, 0x9BB2, 0x6D39, 0xE4A1, 0x6D3A, 0x9BB3, + 0x6D3B, 0xBBEE, 0x6D3C, 0xCDDD, 0x6D3D, 0xC7A2, 0x6D3E, 0xC5C9, + 0x6D3F, 0x9BB4, 0x6D40, 0x9BB5, 0x6D41, 0xC1F7, 0x6D42, 0x9BB6, + 0x6D43, 0xE4A4, 0x6D44, 0x9BB7, 0x6D45, 0xC7B3, 0x6D46, 0xBDAC, + 0x6D47, 0xBDBD, 0x6D48, 0xE4A5, 0x6D49, 0x9BB8, 0x6D4A, 0xD7C7, + 0x6D4B, 0xB2E2, 0x6D4C, 0x9BB9, 0x6D4D, 0xE4AB, 0x6D4E, 0xBCC3, + 0x6D4F, 0xE4AF, 0x6D50, 0x9BBA, 0x6D51, 0xBBEB, 0x6D52, 0xE4B0, + 0x6D53, 0xC5A8, 0x6D54, 0xE4B1, 0x6D55, 0x9BBB, 0x6D56, 0x9BBC, + 0x6D57, 0x9BBD, 0x6D58, 0x9BBE, 0x6D59, 0xD5E3, 0x6D5A, 0xBFA3, + 0x6D5B, 0x9BBF, 0x6D5C, 0xE4BA, 0x6D5D, 0x9BC0, 0x6D5E, 0xE4B7, + 0x6D5F, 0x9BC1, 0x6D60, 0xE4BB, 0x6D61, 0x9BC2, 0x6D62, 0x9BC3, + 0x6D63, 0xE4BD, 0x6D64, 0x9BC4, 0x6D65, 0x9BC5, 0x6D66, 0xC6D6, + 0x6D67, 0x9BC6, 0x6D68, 0x9BC7, 0x6D69, 0xBAC6, 0x6D6A, 0xC0CB, + 0x6D6B, 0x9BC8, 0x6D6C, 0x9BC9, 0x6D6D, 0x9BCA, 0x6D6E, 0xB8A1, + 0x6D6F, 0xE4B4, 0x6D70, 0x9BCB, 0x6D71, 0x9BCC, 0x6D72, 0x9BCD, + 0x6D73, 0x9BCE, 0x6D74, 0xD4A1, 0x6D75, 0x9BCF, 0x6D76, 0x9BD0, + 0x6D77, 0xBAA3, 0x6D78, 0xBDFE, 0x6D79, 0x9BD1, 0x6D7A, 0x9BD2, + 0x6D7B, 0x9BD3, 0x6D7C, 0xE4BC, 0x6D7D, 0x9BD4, 0x6D7E, 0x9BD5, + 0x6D7F, 0x9BD6, 0x6D80, 0x9BD7, 0x6D81, 0x9BD8, 0x6D82, 0xCDBF, + 0x6D83, 0x9BD9, 0x6D84, 0x9BDA, 0x6D85, 0xC4F9, 0x6D86, 0x9BDB, + 0x6D87, 0x9BDC, 0x6D88, 0xCFFB, 0x6D89, 0xC9E6, 0x6D8A, 0x9BDD, + 0x6D8B, 0x9BDE, 0x6D8C, 0xD3BF, 0x6D8D, 0x9BDF, 0x6D8E, 0xCFD1, + 0x6D8F, 0x9BE0, 0x6D90, 0x9BE1, 0x6D91, 0xE4B3, 0x6D92, 0x9BE2, + 0x6D93, 0xE4B8, 0x6D94, 0xE4B9, 0x6D95, 0xCCE9, 0x6D96, 0x9BE3, + 0x6D97, 0x9BE4, 0x6D98, 0x9BE5, 0x6D99, 0x9BE6, 0x6D9A, 0x9BE7, + 0x6D9B, 0xCCCE, 0x6D9C, 0x9BE8, 0x6D9D, 0xC0D4, 0x6D9E, 0xE4B5, + 0x6D9F, 0xC1B0, 0x6DA0, 0xE4B6, 0x6DA1, 0xCED0, 0x6DA2, 0x9BE9, + 0x6DA3, 0xBBC1, 0x6DA4, 0xB5D3, 0x6DA5, 0x9BEA, 0x6DA6, 0xC8F3, + 0x6DA7, 0xBDA7, 0x6DA8, 0xD5C7, 0x6DA9, 0xC9AC, 0x6DAA, 0xB8A2, + 0x6DAB, 0xE4CA, 0x6DAC, 0x9BEB, 0x6DAD, 0x9BEC, 0x6DAE, 0xE4CC, + 0x6DAF, 0xD1C4, 0x6DB0, 0x9BED, 0x6DB1, 0x9BEE, 0x6DB2, 0xD2BA, + 0x6DB3, 0x9BEF, 0x6DB4, 0x9BF0, 0x6DB5, 0xBAAD, 0x6DB6, 0x9BF1, + 0x6DB7, 0x9BF2, 0x6DB8, 0xBAD4, 0x6DB9, 0x9BF3, 0x6DBA, 0x9BF4, + 0x6DBB, 0x9BF5, 0x6DBC, 0x9BF6, 0x6DBD, 0x9BF7, 0x6DBE, 0x9BF8, + 0x6DBF, 0xE4C3, 0x6DC0, 0xB5ED, 0x6DC1, 0x9BF9, 0x6DC2, 0x9BFA, + 0x6DC3, 0x9BFB, 0x6DC4, 0xD7CD, 0x6DC5, 0xE4C0, 0x6DC6, 0xCFFD, + 0x6DC7, 0xE4BF, 0x6DC8, 0x9BFC, 0x6DC9, 0x9BFD, 0x6DCA, 0x9BFE, + 0x6DCB, 0xC1DC, 0x6DCC, 0xCCCA, 0x6DCD, 0x9C40, 0x6DCE, 0x9C41, + 0x6DCF, 0x9C42, 0x6DD0, 0x9C43, 0x6DD1, 0xCAE7, 0x6DD2, 0x9C44, + 0x6DD3, 0x9C45, 0x6DD4, 0x9C46, 0x6DD5, 0x9C47, 0x6DD6, 0xC4D7, + 0x6DD7, 0x9C48, 0x6DD8, 0xCCD4, 0x6DD9, 0xE4C8, 0x6DDA, 0x9C49, + 0x6DDB, 0x9C4A, 0x6DDC, 0x9C4B, 0x6DDD, 0xE4C7, 0x6DDE, 0xE4C1, + 0x6DDF, 0x9C4C, 0x6DE0, 0xE4C4, 0x6DE1, 0xB5AD, 0x6DE2, 0x9C4D, + 0x6DE3, 0x9C4E, 0x6DE4, 0xD3D9, 0x6DE5, 0x9C4F, 0x6DE6, 0xE4C6, + 0x6DE7, 0x9C50, 0x6DE8, 0x9C51, 0x6DE9, 0x9C52, 0x6DEA, 0x9C53, + 0x6DEB, 0xD2F9, 0x6DEC, 0xB4E3, 0x6DED, 0x9C54, 0x6DEE, 0xBBB4, + 0x6DEF, 0x9C55, 0x6DF0, 0x9C56, 0x6DF1, 0xC9EE, 0x6DF2, 0x9C57, + 0x6DF3, 0xB4BE, 0x6DF4, 0x9C58, 0x6DF5, 0x9C59, 0x6DF6, 0x9C5A, + 0x6DF7, 0xBBEC, 0x6DF8, 0x9C5B, 0x6DF9, 0xD1CD, 0x6DFA, 0x9C5C, + 0x6DFB, 0xCCED, 0x6DFC, 0xEDB5, 0x6DFD, 0x9C5D, 0x6DFE, 0x9C5E, + 0x6DFF, 0x9C5F, 0x6E00, 0x9C60, 0x6E01, 0x9C61, 0x6E02, 0x9C62, + 0x6E03, 0x9C63, 0x6E04, 0x9C64, 0x6E05, 0xC7E5, 0x6E06, 0x9C65, + 0x6E07, 0x9C66, 0x6E08, 0x9C67, 0x6E09, 0x9C68, 0x6E0A, 0xD4A8, + 0x6E0B, 0x9C69, 0x6E0C, 0xE4CB, 0x6E0D, 0xD7D5, 0x6E0E, 0xE4C2, + 0x6E0F, 0x9C6A, 0x6E10, 0xBDA5, 0x6E11, 0xE4C5, 0x6E12, 0x9C6B, + 0x6E13, 0x9C6C, 0x6E14, 0xD3E6, 0x6E15, 0x9C6D, 0x6E16, 0xE4C9, + 0x6E17, 0xC9F8, 0x6E18, 0x9C6E, 0x6E19, 0x9C6F, 0x6E1A, 0xE4BE, + 0x6E1B, 0x9C70, 0x6E1C, 0x9C71, 0x6E1D, 0xD3E5, 0x6E1E, 0x9C72, + 0x6E1F, 0x9C73, 0x6E20, 0xC7FE, 0x6E21, 0xB6C9, 0x6E22, 0x9C74, + 0x6E23, 0xD4FC, 0x6E24, 0xB2B3, 0x6E25, 0xE4D7, 0x6E26, 0x9C75, + 0x6E27, 0x9C76, 0x6E28, 0x9C77, 0x6E29, 0xCEC2, 0x6E2A, 0x9C78, + 0x6E2B, 0xE4CD, 0x6E2C, 0x9C79, 0x6E2D, 0xCEBC, 0x6E2E, 0x9C7A, + 0x6E2F, 0xB8DB, 0x6E30, 0x9C7B, 0x6E31, 0x9C7C, 0x6E32, 0xE4D6, + 0x6E33, 0x9C7D, 0x6E34, 0xBFCA, 0x6E35, 0x9C7E, 0x6E36, 0x9C80, + 0x6E37, 0x9C81, 0x6E38, 0xD3CE, 0x6E39, 0x9C82, 0x6E3A, 0xC3EC, + 0x6E3B, 0x9C83, 0x6E3C, 0x9C84, 0x6E3D, 0x9C85, 0x6E3E, 0x9C86, + 0x6E3F, 0x9C87, 0x6E40, 0x9C88, 0x6E41, 0x9C89, 0x6E42, 0x9C8A, + 0x6E43, 0xC5C8, 0x6E44, 0xE4D8, 0x6E45, 0x9C8B, 0x6E46, 0x9C8C, + 0x6E47, 0x9C8D, 0x6E48, 0x9C8E, 0x6E49, 0x9C8F, 0x6E4A, 0x9C90, + 0x6E4B, 0x9C91, 0x6E4C, 0x9C92, 0x6E4D, 0xCDC4, 0x6E4E, 0xE4CF, + 0x6E4F, 0x9C93, 0x6E50, 0x9C94, 0x6E51, 0x9C95, 0x6E52, 0x9C96, + 0x6E53, 0xE4D4, 0x6E54, 0xE4D5, 0x6E55, 0x9C97, 0x6E56, 0xBAFE, + 0x6E57, 0x9C98, 0x6E58, 0xCFE6, 0x6E59, 0x9C99, 0x6E5A, 0x9C9A, + 0x6E5B, 0xD5BF, 0x6E5C, 0x9C9B, 0x6E5D, 0x9C9C, 0x6E5E, 0x9C9D, + 0x6E5F, 0xE4D2, 0x6E60, 0x9C9E, 0x6E61, 0x9C9F, 0x6E62, 0x9CA0, + 0x6E63, 0x9CA1, 0x6E64, 0x9CA2, 0x6E65, 0x9CA3, 0x6E66, 0x9CA4, + 0x6E67, 0x9CA5, 0x6E68, 0x9CA6, 0x6E69, 0x9CA7, 0x6E6A, 0x9CA8, + 0x6E6B, 0xE4D0, 0x6E6C, 0x9CA9, 0x6E6D, 0x9CAA, 0x6E6E, 0xE4CE, + 0x6E6F, 0x9CAB, 0x6E70, 0x9CAC, 0x6E71, 0x9CAD, 0x6E72, 0x9CAE, + 0x6E73, 0x9CAF, 0x6E74, 0x9CB0, 0x6E75, 0x9CB1, 0x6E76, 0x9CB2, + 0x6E77, 0x9CB3, 0x6E78, 0x9CB4, 0x6E79, 0x9CB5, 0x6E7A, 0x9CB6, + 0x6E7B, 0x9CB7, 0x6E7C, 0x9CB8, 0x6E7D, 0x9CB9, 0x6E7E, 0xCDE5, + 0x6E7F, 0xCAAA, 0x6E80, 0x9CBA, 0x6E81, 0x9CBB, 0x6E82, 0x9CBC, + 0x6E83, 0xC0A3, 0x6E84, 0x9CBD, 0x6E85, 0xBDA6, 0x6E86, 0xE4D3, + 0x6E87, 0x9CBE, 0x6E88, 0x9CBF, 0x6E89, 0xB8C8, 0x6E8A, 0x9CC0, + 0x6E8B, 0x9CC1, 0x6E8C, 0x9CC2, 0x6E8D, 0x9CC3, 0x6E8E, 0x9CC4, + 0x6E8F, 0xE4E7, 0x6E90, 0xD4B4, 0x6E91, 0x9CC5, 0x6E92, 0x9CC6, + 0x6E93, 0x9CC7, 0x6E94, 0x9CC8, 0x6E95, 0x9CC9, 0x6E96, 0x9CCA, + 0x6E97, 0x9CCB, 0x6E98, 0xE4DB, 0x6E99, 0x9CCC, 0x6E9A, 0x9CCD, + 0x6E9B, 0x9CCE, 0x6E9C, 0xC1EF, 0x6E9D, 0x9CCF, 0x6E9E, 0x9CD0, + 0x6E9F, 0xE4E9, 0x6EA0, 0x9CD1, 0x6EA1, 0x9CD2, 0x6EA2, 0xD2E7, + 0x6EA3, 0x9CD3, 0x6EA4, 0x9CD4, 0x6EA5, 0xE4DF, 0x6EA6, 0x9CD5, + 0x6EA7, 0xE4E0, 0x6EA8, 0x9CD6, 0x6EA9, 0x9CD7, 0x6EAA, 0xCFAA, + 0x6EAB, 0x9CD8, 0x6EAC, 0x9CD9, 0x6EAD, 0x9CDA, 0x6EAE, 0x9CDB, + 0x6EAF, 0xCBDD, 0x6EB0, 0x9CDC, 0x6EB1, 0xE4DA, 0x6EB2, 0xE4D1, + 0x6EB3, 0x9CDD, 0x6EB4, 0xE4E5, 0x6EB5, 0x9CDE, 0x6EB6, 0xC8DC, + 0x6EB7, 0xE4E3, 0x6EB8, 0x9CDF, 0x6EB9, 0x9CE0, 0x6EBA, 0xC4E7, + 0x6EBB, 0xE4E2, 0x6EBC, 0x9CE1, 0x6EBD, 0xE4E1, 0x6EBE, 0x9CE2, + 0x6EBF, 0x9CE3, 0x6EC0, 0x9CE4, 0x6EC1, 0xB3FC, 0x6EC2, 0xE4E8, + 0x6EC3, 0x9CE5, 0x6EC4, 0x9CE6, 0x6EC5, 0x9CE7, 0x6EC6, 0x9CE8, + 0x6EC7, 0xB5E1, 0x6EC8, 0x9CE9, 0x6EC9, 0x9CEA, 0x6ECA, 0x9CEB, + 0x6ECB, 0xD7CC, 0x6ECC, 0x9CEC, 0x6ECD, 0x9CED, 0x6ECE, 0x9CEE, + 0x6ECF, 0xE4E6, 0x6ED0, 0x9CEF, 0x6ED1, 0xBBAC, 0x6ED2, 0x9CF0, + 0x6ED3, 0xD7D2, 0x6ED4, 0xCCCF, 0x6ED5, 0xEBF8, 0x6ED6, 0x9CF1, + 0x6ED7, 0xE4E4, 0x6ED8, 0x9CF2, 0x6ED9, 0x9CF3, 0x6EDA, 0xB9F6, + 0x6EDB, 0x9CF4, 0x6EDC, 0x9CF5, 0x6EDD, 0x9CF6, 0x6EDE, 0xD6CD, + 0x6EDF, 0xE4D9, 0x6EE0, 0xE4DC, 0x6EE1, 0xC2FA, 0x6EE2, 0xE4DE, + 0x6EE3, 0x9CF7, 0x6EE4, 0xC2CB, 0x6EE5, 0xC0C4, 0x6EE6, 0xC2D0, + 0x6EE7, 0x9CF8, 0x6EE8, 0xB1F5, 0x6EE9, 0xCCB2, 0x6EEA, 0x9CF9, + 0x6EEB, 0x9CFA, 0x6EEC, 0x9CFB, 0x6EED, 0x9CFC, 0x6EEE, 0x9CFD, + 0x6EEF, 0x9CFE, 0x6EF0, 0x9D40, 0x6EF1, 0x9D41, 0x6EF2, 0x9D42, + 0x6EF3, 0x9D43, 0x6EF4, 0xB5CE, 0x6EF5, 0x9D44, 0x6EF6, 0x9D45, + 0x6EF7, 0x9D46, 0x6EF8, 0x9D47, 0x6EF9, 0xE4EF, 0x6EFA, 0x9D48, + 0x6EFB, 0x9D49, 0x6EFC, 0x9D4A, 0x6EFD, 0x9D4B, 0x6EFE, 0x9D4C, + 0x6EFF, 0x9D4D, 0x6F00, 0x9D4E, 0x6F01, 0x9D4F, 0x6F02, 0xC6AF, + 0x6F03, 0x9D50, 0x6F04, 0x9D51, 0x6F05, 0x9D52, 0x6F06, 0xC6E1, + 0x6F07, 0x9D53, 0x6F08, 0x9D54, 0x6F09, 0xE4F5, 0x6F0A, 0x9D55, + 0x6F0B, 0x9D56, 0x6F0C, 0x9D57, 0x6F0D, 0x9D58, 0x6F0E, 0x9D59, + 0x6F0F, 0xC2A9, 0x6F10, 0x9D5A, 0x6F11, 0x9D5B, 0x6F12, 0x9D5C, + 0x6F13, 0xC0EC, 0x6F14, 0xD1DD, 0x6F15, 0xE4EE, 0x6F16, 0x9D5D, + 0x6F17, 0x9D5E, 0x6F18, 0x9D5F, 0x6F19, 0x9D60, 0x6F1A, 0x9D61, + 0x6F1B, 0x9D62, 0x6F1C, 0x9D63, 0x6F1D, 0x9D64, 0x6F1E, 0x9D65, + 0x6F1F, 0x9D66, 0x6F20, 0xC4AE, 0x6F21, 0x9D67, 0x6F22, 0x9D68, + 0x6F23, 0x9D69, 0x6F24, 0xE4ED, 0x6F25, 0x9D6A, 0x6F26, 0x9D6B, + 0x6F27, 0x9D6C, 0x6F28, 0x9D6D, 0x6F29, 0xE4F6, 0x6F2A, 0xE4F4, + 0x6F2B, 0xC2FE, 0x6F2C, 0x9D6E, 0x6F2D, 0xE4DD, 0x6F2E, 0x9D6F, + 0x6F2F, 0xE4F0, 0x6F30, 0x9D70, 0x6F31, 0xCAFE, 0x6F32, 0x9D71, + 0x6F33, 0xD5C4, 0x6F34, 0x9D72, 0x6F35, 0x9D73, 0x6F36, 0xE4F1, + 0x6F37, 0x9D74, 0x6F38, 0x9D75, 0x6F39, 0x9D76, 0x6F3A, 0x9D77, + 0x6F3B, 0x9D78, 0x6F3C, 0x9D79, 0x6F3D, 0x9D7A, 0x6F3E, 0xD1FA, + 0x6F3F, 0x9D7B, 0x6F40, 0x9D7C, 0x6F41, 0x9D7D, 0x6F42, 0x9D7E, + 0x6F43, 0x9D80, 0x6F44, 0x9D81, 0x6F45, 0x9D82, 0x6F46, 0xE4EB, + 0x6F47, 0xE4EC, 0x6F48, 0x9D83, 0x6F49, 0x9D84, 0x6F4A, 0x9D85, + 0x6F4B, 0xE4F2, 0x6F4C, 0x9D86, 0x6F4D, 0xCEAB, 0x6F4E, 0x9D87, + 0x6F4F, 0x9D88, 0x6F50, 0x9D89, 0x6F51, 0x9D8A, 0x6F52, 0x9D8B, + 0x6F53, 0x9D8C, 0x6F54, 0x9D8D, 0x6F55, 0x9D8E, 0x6F56, 0x9D8F, + 0x6F57, 0x9D90, 0x6F58, 0xC5CB, 0x6F59, 0x9D91, 0x6F5A, 0x9D92, + 0x6F5B, 0x9D93, 0x6F5C, 0xC7B1, 0x6F5D, 0x9D94, 0x6F5E, 0xC2BA, + 0x6F5F, 0x9D95, 0x6F60, 0x9D96, 0x6F61, 0x9D97, 0x6F62, 0xE4EA, + 0x6F63, 0x9D98, 0x6F64, 0x9D99, 0x6F65, 0x9D9A, 0x6F66, 0xC1CA, + 0x6F67, 0x9D9B, 0x6F68, 0x9D9C, 0x6F69, 0x9D9D, 0x6F6A, 0x9D9E, + 0x6F6B, 0x9D9F, 0x6F6C, 0x9DA0, 0x6F6D, 0xCCB6, 0x6F6E, 0xB3B1, + 0x6F6F, 0x9DA1, 0x6F70, 0x9DA2, 0x6F71, 0x9DA3, 0x6F72, 0xE4FB, + 0x6F73, 0x9DA4, 0x6F74, 0xE4F3, 0x6F75, 0x9DA5, 0x6F76, 0x9DA6, + 0x6F77, 0x9DA7, 0x6F78, 0xE4FA, 0x6F79, 0x9DA8, 0x6F7A, 0xE4FD, + 0x6F7B, 0x9DA9, 0x6F7C, 0xE4FC, 0x6F7D, 0x9DAA, 0x6F7E, 0x9DAB, + 0x6F7F, 0x9DAC, 0x6F80, 0x9DAD, 0x6F81, 0x9DAE, 0x6F82, 0x9DAF, + 0x6F83, 0x9DB0, 0x6F84, 0xB3CE, 0x6F85, 0x9DB1, 0x6F86, 0x9DB2, + 0x6F87, 0x9DB3, 0x6F88, 0xB3BA, 0x6F89, 0xE4F7, 0x6F8A, 0x9DB4, + 0x6F8B, 0x9DB5, 0x6F8C, 0xE4F9, 0x6F8D, 0xE4F8, 0x6F8E, 0xC5EC, + 0x6F8F, 0x9DB6, 0x6F90, 0x9DB7, 0x6F91, 0x9DB8, 0x6F92, 0x9DB9, + 0x6F93, 0x9DBA, 0x6F94, 0x9DBB, 0x6F95, 0x9DBC, 0x6F96, 0x9DBD, + 0x6F97, 0x9DBE, 0x6F98, 0x9DBF, 0x6F99, 0x9DC0, 0x6F9A, 0x9DC1, + 0x6F9B, 0x9DC2, 0x6F9C, 0xC0BD, 0x6F9D, 0x9DC3, 0x6F9E, 0x9DC4, + 0x6F9F, 0x9DC5, 0x6FA0, 0x9DC6, 0x6FA1, 0xD4E8, 0x6FA2, 0x9DC7, + 0x6FA3, 0x9DC8, 0x6FA4, 0x9DC9, 0x6FA5, 0x9DCA, 0x6FA6, 0x9DCB, + 0x6FA7, 0xE5A2, 0x6FA8, 0x9DCC, 0x6FA9, 0x9DCD, 0x6FAA, 0x9DCE, + 0x6FAB, 0x9DCF, 0x6FAC, 0x9DD0, 0x6FAD, 0x9DD1, 0x6FAE, 0x9DD2, + 0x6FAF, 0x9DD3, 0x6FB0, 0x9DD4, 0x6FB1, 0x9DD5, 0x6FB2, 0x9DD6, + 0x6FB3, 0xB0C4, 0x6FB4, 0x9DD7, 0x6FB5, 0x9DD8, 0x6FB6, 0xE5A4, + 0x6FB7, 0x9DD9, 0x6FB8, 0x9DDA, 0x6FB9, 0xE5A3, 0x6FBA, 0x9DDB, + 0x6FBB, 0x9DDC, 0x6FBC, 0x9DDD, 0x6FBD, 0x9DDE, 0x6FBE, 0x9DDF, + 0x6FBF, 0x9DE0, 0x6FC0, 0xBCA4, 0x6FC1, 0x9DE1, 0x6FC2, 0xE5A5, + 0x6FC3, 0x9DE2, 0x6FC4, 0x9DE3, 0x6FC5, 0x9DE4, 0x6FC6, 0x9DE5, + 0x6FC7, 0x9DE6, 0x6FC8, 0x9DE7, 0x6FC9, 0xE5A1, 0x6FCA, 0x9DE8, + 0x6FCB, 0x9DE9, 0x6FCC, 0x9DEA, 0x6FCD, 0x9DEB, 0x6FCE, 0x9DEC, + 0x6FCF, 0x9DED, 0x6FD0, 0x9DEE, 0x6FD1, 0xE4FE, 0x6FD2, 0xB1F4, + 0x6FD3, 0x9DEF, 0x6FD4, 0x9DF0, 0x6FD5, 0x9DF1, 0x6FD6, 0x9DF2, + 0x6FD7, 0x9DF3, 0x6FD8, 0x9DF4, 0x6FD9, 0x9DF5, 0x6FDA, 0x9DF6, + 0x6FDB, 0x9DF7, 0x6FDC, 0x9DF8, 0x6FDD, 0x9DF9, 0x6FDE, 0xE5A8, + 0x6FDF, 0x9DFA, 0x6FE0, 0xE5A9, 0x6FE1, 0xE5A6, 0x6FE2, 0x9DFB, + 0x6FE3, 0x9DFC, 0x6FE4, 0x9DFD, 0x6FE5, 0x9DFE, 0x6FE6, 0x9E40, + 0x6FE7, 0x9E41, 0x6FE8, 0x9E42, 0x6FE9, 0x9E43, 0x6FEA, 0x9E44, + 0x6FEB, 0x9E45, 0x6FEC, 0x9E46, 0x6FED, 0x9E47, 0x6FEE, 0xE5A7, + 0x6FEF, 0xE5AA, 0x6FF0, 0x9E48, 0x6FF1, 0x9E49, 0x6FF2, 0x9E4A, + 0x6FF3, 0x9E4B, 0x6FF4, 0x9E4C, 0x6FF5, 0x9E4D, 0x6FF6, 0x9E4E, + 0x6FF7, 0x9E4F, 0x6FF8, 0x9E50, 0x6FF9, 0x9E51, 0x6FFA, 0x9E52, + 0x6FFB, 0x9E53, 0x6FFC, 0x9E54, 0x6FFD, 0x9E55, 0x6FFE, 0x9E56, + 0x6FFF, 0x9E57, 0x7000, 0x9E58, 0x7001, 0x9E59, 0x7002, 0x9E5A, + 0x7003, 0x9E5B, 0x7004, 0x9E5C, 0x7005, 0x9E5D, 0x7006, 0x9E5E, + 0x7007, 0x9E5F, 0x7008, 0x9E60, 0x7009, 0x9E61, 0x700A, 0x9E62, + 0x700B, 0x9E63, 0x700C, 0x9E64, 0x700D, 0x9E65, 0x700E, 0x9E66, + 0x700F, 0x9E67, 0x7010, 0x9E68, 0x7011, 0xC6D9, 0x7012, 0x9E69, + 0x7013, 0x9E6A, 0x7014, 0x9E6B, 0x7015, 0x9E6C, 0x7016, 0x9E6D, + 0x7017, 0x9E6E, 0x7018, 0x9E6F, 0x7019, 0x9E70, 0x701A, 0xE5AB, + 0x701B, 0xE5AD, 0x701C, 0x9E71, 0x701D, 0x9E72, 0x701E, 0x9E73, + 0x701F, 0x9E74, 0x7020, 0x9E75, 0x7021, 0x9E76, 0x7022, 0x9E77, + 0x7023, 0xE5AC, 0x7024, 0x9E78, 0x7025, 0x9E79, 0x7026, 0x9E7A, + 0x7027, 0x9E7B, 0x7028, 0x9E7C, 0x7029, 0x9E7D, 0x702A, 0x9E7E, + 0x702B, 0x9E80, 0x702C, 0x9E81, 0x702D, 0x9E82, 0x702E, 0x9E83, + 0x702F, 0x9E84, 0x7030, 0x9E85, 0x7031, 0x9E86, 0x7032, 0x9E87, + 0x7033, 0x9E88, 0x7034, 0x9E89, 0x7035, 0xE5AF, 0x7036, 0x9E8A, + 0x7037, 0x9E8B, 0x7038, 0x9E8C, 0x7039, 0xE5AE, 0x703A, 0x9E8D, + 0x703B, 0x9E8E, 0x703C, 0x9E8F, 0x703D, 0x9E90, 0x703E, 0x9E91, + 0x703F, 0x9E92, 0x7040, 0x9E93, 0x7041, 0x9E94, 0x7042, 0x9E95, + 0x7043, 0x9E96, 0x7044, 0x9E97, 0x7045, 0x9E98, 0x7046, 0x9E99, + 0x7047, 0x9E9A, 0x7048, 0x9E9B, 0x7049, 0x9E9C, 0x704A, 0x9E9D, + 0x704B, 0x9E9E, 0x704C, 0xB9E0, 0x704D, 0x9E9F, 0x704E, 0x9EA0, + 0x704F, 0xE5B0, 0x7050, 0x9EA1, 0x7051, 0x9EA2, 0x7052, 0x9EA3, + 0x7053, 0x9EA4, 0x7054, 0x9EA5, 0x7055, 0x9EA6, 0x7056, 0x9EA7, + 0x7057, 0x9EA8, 0x7058, 0x9EA9, 0x7059, 0x9EAA, 0x705A, 0x9EAB, + 0x705B, 0x9EAC, 0x705C, 0x9EAD, 0x705D, 0x9EAE, 0x705E, 0xE5B1, + 0x705F, 0x9EAF, 0x7060, 0x9EB0, 0x7061, 0x9EB1, 0x7062, 0x9EB2, + 0x7063, 0x9EB3, 0x7064, 0x9EB4, 0x7065, 0x9EB5, 0x7066, 0x9EB6, + 0x7067, 0x9EB7, 0x7068, 0x9EB8, 0x7069, 0x9EB9, 0x706A, 0x9EBA, + 0x706B, 0xBBF0, 0x706C, 0xECE1, 0x706D, 0xC3F0, 0x706E, 0x9EBB, + 0x706F, 0xB5C6, 0x7070, 0xBBD2, 0x7071, 0x9EBC, 0x7072, 0x9EBD, + 0x7073, 0x9EBE, 0x7074, 0x9EBF, 0x7075, 0xC1E9, 0x7076, 0xD4EE, + 0x7077, 0x9EC0, 0x7078, 0xBEC4, 0x7079, 0x9EC1, 0x707A, 0x9EC2, + 0x707B, 0x9EC3, 0x707C, 0xD7C6, 0x707D, 0x9EC4, 0x707E, 0xD4D6, + 0x707F, 0xB2D3, 0x7080, 0xECBE, 0x7081, 0x9EC5, 0x7082, 0x9EC6, + 0x7083, 0x9EC7, 0x7084, 0x9EC8, 0x7085, 0xEAC1, 0x7086, 0x9EC9, + 0x7087, 0x9ECA, 0x7088, 0x9ECB, 0x7089, 0xC2AF, 0x708A, 0xB4B6, + 0x708B, 0x9ECC, 0x708C, 0x9ECD, 0x708D, 0x9ECE, 0x708E, 0xD1D7, + 0x708F, 0x9ECF, 0x7090, 0x9ED0, 0x7091, 0x9ED1, 0x7092, 0xB3B4, + 0x7093, 0x9ED2, 0x7094, 0xC8B2, 0x7095, 0xBFBB, 0x7096, 0xECC0, + 0x7097, 0x9ED3, 0x7098, 0x9ED4, 0x7099, 0xD6CB, 0x709A, 0x9ED5, + 0x709B, 0x9ED6, 0x709C, 0xECBF, 0x709D, 0xECC1, 0x709E, 0x9ED7, + 0x709F, 0x9ED8, 0x70A0, 0x9ED9, 0x70A1, 0x9EDA, 0x70A2, 0x9EDB, + 0x70A3, 0x9EDC, 0x70A4, 0x9EDD, 0x70A5, 0x9EDE, 0x70A6, 0x9EDF, + 0x70A7, 0x9EE0, 0x70A8, 0x9EE1, 0x70A9, 0x9EE2, 0x70AA, 0x9EE3, + 0x70AB, 0xECC5, 0x70AC, 0xBEE6, 0x70AD, 0xCCBF, 0x70AE, 0xC5DA, + 0x70AF, 0xBEBC, 0x70B0, 0x9EE4, 0x70B1, 0xECC6, 0x70B2, 0x9EE5, + 0x70B3, 0xB1FE, 0x70B4, 0x9EE6, 0x70B5, 0x9EE7, 0x70B6, 0x9EE8, + 0x70B7, 0xECC4, 0x70B8, 0xD5A8, 0x70B9, 0xB5E3, 0x70BA, 0x9EE9, + 0x70BB, 0xECC2, 0x70BC, 0xC1B6, 0x70BD, 0xB3E3, 0x70BE, 0x9EEA, + 0x70BF, 0x9EEB, 0x70C0, 0xECC3, 0x70C1, 0xCBB8, 0x70C2, 0xC0C3, + 0x70C3, 0xCCFE, 0x70C4, 0x9EEC, 0x70C5, 0x9EED, 0x70C6, 0x9EEE, + 0x70C7, 0x9EEF, 0x70C8, 0xC1D2, 0x70C9, 0x9EF0, 0x70CA, 0xECC8, + 0x70CB, 0x9EF1, 0x70CC, 0x9EF2, 0x70CD, 0x9EF3, 0x70CE, 0x9EF4, + 0x70CF, 0x9EF5, 0x70D0, 0x9EF6, 0x70D1, 0x9EF7, 0x70D2, 0x9EF8, + 0x70D3, 0x9EF9, 0x70D4, 0x9EFA, 0x70D5, 0x9EFB, 0x70D6, 0x9EFC, + 0x70D7, 0x9EFD, 0x70D8, 0xBAE6, 0x70D9, 0xC0D3, 0x70DA, 0x9EFE, + 0x70DB, 0xD6F2, 0x70DC, 0x9F40, 0x70DD, 0x9F41, 0x70DE, 0x9F42, + 0x70DF, 0xD1CC, 0x70E0, 0x9F43, 0x70E1, 0x9F44, 0x70E2, 0x9F45, + 0x70E3, 0x9F46, 0x70E4, 0xBFBE, 0x70E5, 0x9F47, 0x70E6, 0xB7B3, + 0x70E7, 0xC9D5, 0x70E8, 0xECC7, 0x70E9, 0xBBE2, 0x70EA, 0x9F48, + 0x70EB, 0xCCCC, 0x70EC, 0xBDFD, 0x70ED, 0xC8C8, 0x70EE, 0x9F49, + 0x70EF, 0xCFA9, 0x70F0, 0x9F4A, 0x70F1, 0x9F4B, 0x70F2, 0x9F4C, + 0x70F3, 0x9F4D, 0x70F4, 0x9F4E, 0x70F5, 0x9F4F, 0x70F6, 0x9F50, + 0x70F7, 0xCDE9, 0x70F8, 0x9F51, 0x70F9, 0xC5EB, 0x70FA, 0x9F52, + 0x70FB, 0x9F53, 0x70FC, 0x9F54, 0x70FD, 0xB7E9, 0x70FE, 0x9F55, + 0x70FF, 0x9F56, 0x7100, 0x9F57, 0x7101, 0x9F58, 0x7102, 0x9F59, + 0x7103, 0x9F5A, 0x7104, 0x9F5B, 0x7105, 0x9F5C, 0x7106, 0x9F5D, + 0x7107, 0x9F5E, 0x7108, 0x9F5F, 0x7109, 0xD1C9, 0x710A, 0xBAB8, + 0x710B, 0x9F60, 0x710C, 0x9F61, 0x710D, 0x9F62, 0x710E, 0x9F63, + 0x710F, 0x9F64, 0x7110, 0xECC9, 0x7111, 0x9F65, 0x7112, 0x9F66, + 0x7113, 0xECCA, 0x7114, 0x9F67, 0x7115, 0xBBC0, 0x7116, 0xECCB, + 0x7117, 0x9F68, 0x7118, 0xECE2, 0x7119, 0xB1BA, 0x711A, 0xB7D9, + 0x711B, 0x9F69, 0x711C, 0x9F6A, 0x711D, 0x9F6B, 0x711E, 0x9F6C, + 0x711F, 0x9F6D, 0x7120, 0x9F6E, 0x7121, 0x9F6F, 0x7122, 0x9F70, + 0x7123, 0x9F71, 0x7124, 0x9F72, 0x7125, 0x9F73, 0x7126, 0xBDB9, + 0x7127, 0x9F74, 0x7128, 0x9F75, 0x7129, 0x9F76, 0x712A, 0x9F77, + 0x712B, 0x9F78, 0x712C, 0x9F79, 0x712D, 0x9F7A, 0x712E, 0x9F7B, + 0x712F, 0xECCC, 0x7130, 0xD1E6, 0x7131, 0xECCD, 0x7132, 0x9F7C, + 0x7133, 0x9F7D, 0x7134, 0x9F7E, 0x7135, 0x9F80, 0x7136, 0xC8BB, + 0x7137, 0x9F81, 0x7138, 0x9F82, 0x7139, 0x9F83, 0x713A, 0x9F84, + 0x713B, 0x9F85, 0x713C, 0x9F86, 0x713D, 0x9F87, 0x713E, 0x9F88, + 0x713F, 0x9F89, 0x7140, 0x9F8A, 0x7141, 0x9F8B, 0x7142, 0x9F8C, + 0x7143, 0x9F8D, 0x7144, 0x9F8E, 0x7145, 0xECD1, 0x7146, 0x9F8F, + 0x7147, 0x9F90, 0x7148, 0x9F91, 0x7149, 0x9F92, 0x714A, 0xECD3, + 0x714B, 0x9F93, 0x714C, 0xBBCD, 0x714D, 0x9F94, 0x714E, 0xBCE5, + 0x714F, 0x9F95, 0x7150, 0x9F96, 0x7151, 0x9F97, 0x7152, 0x9F98, + 0x7153, 0x9F99, 0x7154, 0x9F9A, 0x7155, 0x9F9B, 0x7156, 0x9F9C, + 0x7157, 0x9F9D, 0x7158, 0x9F9E, 0x7159, 0x9F9F, 0x715A, 0x9FA0, + 0x715B, 0x9FA1, 0x715C, 0xECCF, 0x715D, 0x9FA2, 0x715E, 0xC9B7, + 0x715F, 0x9FA3, 0x7160, 0x9FA4, 0x7161, 0x9FA5, 0x7162, 0x9FA6, + 0x7163, 0x9FA7, 0x7164, 0xC3BA, 0x7165, 0x9FA8, 0x7166, 0xECE3, + 0x7167, 0xD5D5, 0x7168, 0xECD0, 0x7169, 0x9FA9, 0x716A, 0x9FAA, + 0x716B, 0x9FAB, 0x716C, 0x9FAC, 0x716D, 0x9FAD, 0x716E, 0xD6F3, + 0x716F, 0x9FAE, 0x7170, 0x9FAF, 0x7171, 0x9FB0, 0x7172, 0xECD2, + 0x7173, 0xECCE, 0x7174, 0x9FB1, 0x7175, 0x9FB2, 0x7176, 0x9FB3, + 0x7177, 0x9FB4, 0x7178, 0xECD4, 0x7179, 0x9FB5, 0x717A, 0xECD5, + 0x717B, 0x9FB6, 0x717C, 0x9FB7, 0x717D, 0xC9BF, 0x717E, 0x9FB8, + 0x717F, 0x9FB9, 0x7180, 0x9FBA, 0x7181, 0x9FBB, 0x7182, 0x9FBC, + 0x7183, 0x9FBD, 0x7184, 0xCFA8, 0x7185, 0x9FBE, 0x7186, 0x9FBF, + 0x7187, 0x9FC0, 0x7188, 0x9FC1, 0x7189, 0x9FC2, 0x718A, 0xD0DC, + 0x718B, 0x9FC3, 0x718C, 0x9FC4, 0x718D, 0x9FC5, 0x718E, 0x9FC6, + 0x718F, 0xD1AC, 0x7190, 0x9FC7, 0x7191, 0x9FC8, 0x7192, 0x9FC9, + 0x7193, 0x9FCA, 0x7194, 0xC8DB, 0x7195, 0x9FCB, 0x7196, 0x9FCC, + 0x7197, 0x9FCD, 0x7198, 0xECD6, 0x7199, 0xCEF5, 0x719A, 0x9FCE, + 0x719B, 0x9FCF, 0x719C, 0x9FD0, 0x719D, 0x9FD1, 0x719E, 0x9FD2, + 0x719F, 0xCAEC, 0x71A0, 0xECDA, 0x71A1, 0x9FD3, 0x71A2, 0x9FD4, + 0x71A3, 0x9FD5, 0x71A4, 0x9FD6, 0x71A5, 0x9FD7, 0x71A6, 0x9FD8, + 0x71A7, 0x9FD9, 0x71A8, 0xECD9, 0x71A9, 0x9FDA, 0x71AA, 0x9FDB, + 0x71AB, 0x9FDC, 0x71AC, 0xB0BE, 0x71AD, 0x9FDD, 0x71AE, 0x9FDE, + 0x71AF, 0x9FDF, 0x71B0, 0x9FE0, 0x71B1, 0x9FE1, 0x71B2, 0x9FE2, + 0x71B3, 0xECD7, 0x71B4, 0x9FE3, 0x71B5, 0xECD8, 0x71B6, 0x9FE4, + 0x71B7, 0x9FE5, 0x71B8, 0x9FE6, 0x71B9, 0xECE4, 0x71BA, 0x9FE7, + 0x71BB, 0x9FE8, 0x71BC, 0x9FE9, 0x71BD, 0x9FEA, 0x71BE, 0x9FEB, + 0x71BF, 0x9FEC, 0x71C0, 0x9FED, 0x71C1, 0x9FEE, 0x71C2, 0x9FEF, + 0x71C3, 0xC8BC, 0x71C4, 0x9FF0, 0x71C5, 0x9FF1, 0x71C6, 0x9FF2, + 0x71C7, 0x9FF3, 0x71C8, 0x9FF4, 0x71C9, 0x9FF5, 0x71CA, 0x9FF6, + 0x71CB, 0x9FF7, 0x71CC, 0x9FF8, 0x71CD, 0x9FF9, 0x71CE, 0xC1C7, + 0x71CF, 0x9FFA, 0x71D0, 0x9FFB, 0x71D1, 0x9FFC, 0x71D2, 0x9FFD, + 0x71D3, 0x9FFE, 0x71D4, 0xECDC, 0x71D5, 0xD1E0, 0x71D6, 0xA040, + 0x71D7, 0xA041, 0x71D8, 0xA042, 0x71D9, 0xA043, 0x71DA, 0xA044, + 0x71DB, 0xA045, 0x71DC, 0xA046, 0x71DD, 0xA047, 0x71DE, 0xA048, + 0x71DF, 0xA049, 0x71E0, 0xECDB, 0x71E1, 0xA04A, 0x71E2, 0xA04B, + 0x71E3, 0xA04C, 0x71E4, 0xA04D, 0x71E5, 0xD4EF, 0x71E6, 0xA04E, + 0x71E7, 0xECDD, 0x71E8, 0xA04F, 0x71E9, 0xA050, 0x71EA, 0xA051, + 0x71EB, 0xA052, 0x71EC, 0xA053, 0x71ED, 0xA054, 0x71EE, 0xDBC6, + 0x71EF, 0xA055, 0x71F0, 0xA056, 0x71F1, 0xA057, 0x71F2, 0xA058, + 0x71F3, 0xA059, 0x71F4, 0xA05A, 0x71F5, 0xA05B, 0x71F6, 0xA05C, + 0x71F7, 0xA05D, 0x71F8, 0xA05E, 0x71F9, 0xECDE, 0x71FA, 0xA05F, + 0x71FB, 0xA060, 0x71FC, 0xA061, 0x71FD, 0xA062, 0x71FE, 0xA063, + 0x71FF, 0xA064, 0x7200, 0xA065, 0x7201, 0xA066, 0x7202, 0xA067, + 0x7203, 0xA068, 0x7204, 0xA069, 0x7205, 0xA06A, 0x7206, 0xB1AC, + 0x7207, 0xA06B, 0x7208, 0xA06C, 0x7209, 0xA06D, 0x720A, 0xA06E, + 0x720B, 0xA06F, 0x720C, 0xA070, 0x720D, 0xA071, 0x720E, 0xA072, + 0x720F, 0xA073, 0x7210, 0xA074, 0x7211, 0xA075, 0x7212, 0xA076, + 0x7213, 0xA077, 0x7214, 0xA078, 0x7215, 0xA079, 0x7216, 0xA07A, + 0x7217, 0xA07B, 0x7218, 0xA07C, 0x7219, 0xA07D, 0x721A, 0xA07E, + 0x721B, 0xA080, 0x721C, 0xA081, 0x721D, 0xECDF, 0x721E, 0xA082, + 0x721F, 0xA083, 0x7220, 0xA084, 0x7221, 0xA085, 0x7222, 0xA086, + 0x7223, 0xA087, 0x7224, 0xA088, 0x7225, 0xA089, 0x7226, 0xA08A, + 0x7227, 0xA08B, 0x7228, 0xECE0, 0x7229, 0xA08C, 0x722A, 0xD7A6, + 0x722B, 0xA08D, 0x722C, 0xC5C0, 0x722D, 0xA08E, 0x722E, 0xA08F, + 0x722F, 0xA090, 0x7230, 0xEBBC, 0x7231, 0xB0AE, 0x7232, 0xA091, + 0x7233, 0xA092, 0x7234, 0xA093, 0x7235, 0xBEF4, 0x7236, 0xB8B8, + 0x7237, 0xD2AF, 0x7238, 0xB0D6, 0x7239, 0xB5F9, 0x723A, 0xA094, + 0x723B, 0xD8B3, 0x723C, 0xA095, 0x723D, 0xCBAC, 0x723E, 0xA096, + 0x723F, 0xE3DD, 0x7240, 0xA097, 0x7241, 0xA098, 0x7242, 0xA099, + 0x7243, 0xA09A, 0x7244, 0xA09B, 0x7245, 0xA09C, 0x7246, 0xA09D, + 0x7247, 0xC6AC, 0x7248, 0xB0E6, 0x7249, 0xA09E, 0x724A, 0xA09F, + 0x724B, 0xA0A0, 0x724C, 0xC5C6, 0x724D, 0xEBB9, 0x724E, 0xA0A1, + 0x724F, 0xA0A2, 0x7250, 0xA0A3, 0x7251, 0xA0A4, 0x7252, 0xEBBA, + 0x7253, 0xA0A5, 0x7254, 0xA0A6, 0x7255, 0xA0A7, 0x7256, 0xEBBB, + 0x7257, 0xA0A8, 0x7258, 0xA0A9, 0x7259, 0xD1C0, 0x725A, 0xA0AA, + 0x725B, 0xC5A3, 0x725C, 0xA0AB, 0x725D, 0xEAF2, 0x725E, 0xA0AC, + 0x725F, 0xC4B2, 0x7260, 0xA0AD, 0x7261, 0xC4B5, 0x7262, 0xC0CE, + 0x7263, 0xA0AE, 0x7264, 0xA0AF, 0x7265, 0xA0B0, 0x7266, 0xEAF3, + 0x7267, 0xC4C1, 0x7268, 0xA0B1, 0x7269, 0xCEEF, 0x726A, 0xA0B2, + 0x726B, 0xA0B3, 0x726C, 0xA0B4, 0x726D, 0xA0B5, 0x726E, 0xEAF0, + 0x726F, 0xEAF4, 0x7270, 0xA0B6, 0x7271, 0xA0B7, 0x7272, 0xC9FC, + 0x7273, 0xA0B8, 0x7274, 0xA0B9, 0x7275, 0xC7A3, 0x7276, 0xA0BA, + 0x7277, 0xA0BB, 0x7278, 0xA0BC, 0x7279, 0xCCD8, 0x727A, 0xCEFE, + 0x727B, 0xA0BD, 0x727C, 0xA0BE, 0x727D, 0xA0BF, 0x727E, 0xEAF5, + 0x727F, 0xEAF6, 0x7280, 0xCFAC, 0x7281, 0xC0E7, 0x7282, 0xA0C0, + 0x7283, 0xA0C1, 0x7284, 0xEAF7, 0x7285, 0xA0C2, 0x7286, 0xA0C3, + 0x7287, 0xA0C4, 0x7288, 0xA0C5, 0x7289, 0xA0C6, 0x728A, 0xB6BF, + 0x728B, 0xEAF8, 0x728C, 0xA0C7, 0x728D, 0xEAF9, 0x728E, 0xA0C8, + 0x728F, 0xEAFA, 0x7290, 0xA0C9, 0x7291, 0xA0CA, 0x7292, 0xEAFB, + 0x7293, 0xA0CB, 0x7294, 0xA0CC, 0x7295, 0xA0CD, 0x7296, 0xA0CE, + 0x7297, 0xA0CF, 0x7298, 0xA0D0, 0x7299, 0xA0D1, 0x729A, 0xA0D2, + 0x729B, 0xA0D3, 0x729C, 0xA0D4, 0x729D, 0xA0D5, 0x729E, 0xA0D6, + 0x729F, 0xEAF1, 0x72A0, 0xA0D7, 0x72A1, 0xA0D8, 0x72A2, 0xA0D9, + 0x72A3, 0xA0DA, 0x72A4, 0xA0DB, 0x72A5, 0xA0DC, 0x72A6, 0xA0DD, + 0x72A7, 0xA0DE, 0x72A8, 0xA0DF, 0x72A9, 0xA0E0, 0x72AA, 0xA0E1, + 0x72AB, 0xA0E2, 0x72AC, 0xC8AE, 0x72AD, 0xE1EB, 0x72AE, 0xA0E3, + 0x72AF, 0xB7B8, 0x72B0, 0xE1EC, 0x72B1, 0xA0E4, 0x72B2, 0xA0E5, + 0x72B3, 0xA0E6, 0x72B4, 0xE1ED, 0x72B5, 0xA0E7, 0x72B6, 0xD7B4, + 0x72B7, 0xE1EE, 0x72B8, 0xE1EF, 0x72B9, 0xD3CC, 0x72BA, 0xA0E8, + 0x72BB, 0xA0E9, 0x72BC, 0xA0EA, 0x72BD, 0xA0EB, 0x72BE, 0xA0EC, + 0x72BF, 0xA0ED, 0x72C0, 0xA0EE, 0x72C1, 0xE1F1, 0x72C2, 0xBFF1, + 0x72C3, 0xE1F0, 0x72C4, 0xB5D2, 0x72C5, 0xA0EF, 0x72C6, 0xA0F0, + 0x72C7, 0xA0F1, 0x72C8, 0xB1B7, 0x72C9, 0xA0F2, 0x72CA, 0xA0F3, + 0x72CB, 0xA0F4, 0x72CC, 0xA0F5, 0x72CD, 0xE1F3, 0x72CE, 0xE1F2, + 0x72CF, 0xA0F6, 0x72D0, 0xBAFC, 0x72D1, 0xA0F7, 0x72D2, 0xE1F4, + 0x72D3, 0xA0F8, 0x72D4, 0xA0F9, 0x72D5, 0xA0FA, 0x72D6, 0xA0FB, + 0x72D7, 0xB9B7, 0x72D8, 0xA0FC, 0x72D9, 0xBED1, 0x72DA, 0xA0FD, + 0x72DB, 0xA0FE, 0x72DC, 0xAA40, 0x72DD, 0xAA41, 0x72DE, 0xC4FC, + 0x72DF, 0xAA42, 0x72E0, 0xBADD, 0x72E1, 0xBDC6, 0x72E2, 0xAA43, + 0x72E3, 0xAA44, 0x72E4, 0xAA45, 0x72E5, 0xAA46, 0x72E6, 0xAA47, + 0x72E7, 0xAA48, 0x72E8, 0xE1F5, 0x72E9, 0xE1F7, 0x72EA, 0xAA49, + 0x72EB, 0xAA4A, 0x72EC, 0xB6C0, 0x72ED, 0xCFC1, 0x72EE, 0xCAA8, + 0x72EF, 0xE1F6, 0x72F0, 0xD5F8, 0x72F1, 0xD3FC, 0x72F2, 0xE1F8, + 0x72F3, 0xE1FC, 0x72F4, 0xE1F9, 0x72F5, 0xAA4B, 0x72F6, 0xAA4C, + 0x72F7, 0xE1FA, 0x72F8, 0xC0EA, 0x72F9, 0xAA4D, 0x72FA, 0xE1FE, + 0x72FB, 0xE2A1, 0x72FC, 0xC0C7, 0x72FD, 0xAA4E, 0x72FE, 0xAA4F, + 0x72FF, 0xAA50, 0x7300, 0xAA51, 0x7301, 0xE1FB, 0x7302, 0xAA52, + 0x7303, 0xE1FD, 0x7304, 0xAA53, 0x7305, 0xAA54, 0x7306, 0xAA55, + 0x7307, 0xAA56, 0x7308, 0xAA57, 0x7309, 0xAA58, 0x730A, 0xE2A5, + 0x730B, 0xAA59, 0x730C, 0xAA5A, 0x730D, 0xAA5B, 0x730E, 0xC1D4, + 0x730F, 0xAA5C, 0x7310, 0xAA5D, 0x7311, 0xAA5E, 0x7312, 0xAA5F, + 0x7313, 0xE2A3, 0x7314, 0xAA60, 0x7315, 0xE2A8, 0x7316, 0xB2FE, + 0x7317, 0xE2A2, 0x7318, 0xAA61, 0x7319, 0xAA62, 0x731A, 0xAA63, + 0x731B, 0xC3CD, 0x731C, 0xB2C2, 0x731D, 0xE2A7, 0x731E, 0xE2A6, + 0x731F, 0xAA64, 0x7320, 0xAA65, 0x7321, 0xE2A4, 0x7322, 0xE2A9, + 0x7323, 0xAA66, 0x7324, 0xAA67, 0x7325, 0xE2AB, 0x7326, 0xAA68, + 0x7327, 0xAA69, 0x7328, 0xAA6A, 0x7329, 0xD0C9, 0x732A, 0xD6ED, + 0x732B, 0xC3A8, 0x732C, 0xE2AC, 0x732D, 0xAA6B, 0x732E, 0xCFD7, + 0x732F, 0xAA6C, 0x7330, 0xAA6D, 0x7331, 0xE2AE, 0x7332, 0xAA6E, + 0x7333, 0xAA6F, 0x7334, 0xBAEF, 0x7335, 0xAA70, 0x7336, 0xAA71, + 0x7337, 0xE9E0, 0x7338, 0xE2AD, 0x7339, 0xE2AA, 0x733A, 0xAA72, + 0x733B, 0xAA73, 0x733C, 0xAA74, 0x733D, 0xAA75, 0x733E, 0xBBAB, + 0x733F, 0xD4B3, 0x7340, 0xAA76, 0x7341, 0xAA77, 0x7342, 0xAA78, + 0x7343, 0xAA79, 0x7344, 0xAA7A, 0x7345, 0xAA7B, 0x7346, 0xAA7C, + 0x7347, 0xAA7D, 0x7348, 0xAA7E, 0x7349, 0xAA80, 0x734A, 0xAA81, + 0x734B, 0xAA82, 0x734C, 0xAA83, 0x734D, 0xE2B0, 0x734E, 0xAA84, + 0x734F, 0xAA85, 0x7350, 0xE2AF, 0x7351, 0xAA86, 0x7352, 0xE9E1, + 0x7353, 0xAA87, 0x7354, 0xAA88, 0x7355, 0xAA89, 0x7356, 0xAA8A, + 0x7357, 0xE2B1, 0x7358, 0xAA8B, 0x7359, 0xAA8C, 0x735A, 0xAA8D, + 0x735B, 0xAA8E, 0x735C, 0xAA8F, 0x735D, 0xAA90, 0x735E, 0xAA91, + 0x735F, 0xAA92, 0x7360, 0xE2B2, 0x7361, 0xAA93, 0x7362, 0xAA94, + 0x7363, 0xAA95, 0x7364, 0xAA96, 0x7365, 0xAA97, 0x7366, 0xAA98, + 0x7367, 0xAA99, 0x7368, 0xAA9A, 0x7369, 0xAA9B, 0x736A, 0xAA9C, + 0x736B, 0xAA9D, 0x736C, 0xE2B3, 0x736D, 0xCCA1, 0x736E, 0xAA9E, + 0x736F, 0xE2B4, 0x7370, 0xAA9F, 0x7371, 0xAAA0, 0x7372, 0xAB40, + 0x7373, 0xAB41, 0x7374, 0xAB42, 0x7375, 0xAB43, 0x7376, 0xAB44, + 0x7377, 0xAB45, 0x7378, 0xAB46, 0x7379, 0xAB47, 0x737A, 0xAB48, + 0x737B, 0xAB49, 0x737C, 0xAB4A, 0x737D, 0xAB4B, 0x737E, 0xE2B5, + 0x737F, 0xAB4C, 0x7380, 0xAB4D, 0x7381, 0xAB4E, 0x7382, 0xAB4F, + 0x7383, 0xAB50, 0x7384, 0xD0FE, 0x7385, 0xAB51, 0x7386, 0xAB52, + 0x7387, 0xC2CA, 0x7388, 0xAB53, 0x7389, 0xD3F1, 0x738A, 0xAB54, + 0x738B, 0xCDF5, 0x738C, 0xAB55, 0x738D, 0xAB56, 0x738E, 0xE7E0, + 0x738F, 0xAB57, 0x7390, 0xAB58, 0x7391, 0xE7E1, 0x7392, 0xAB59, + 0x7393, 0xAB5A, 0x7394, 0xAB5B, 0x7395, 0xAB5C, 0x7396, 0xBEC1, + 0x7397, 0xAB5D, 0x7398, 0xAB5E, 0x7399, 0xAB5F, 0x739A, 0xAB60, + 0x739B, 0xC2EA, 0x739C, 0xAB61, 0x739D, 0xAB62, 0x739E, 0xAB63, + 0x739F, 0xE7E4, 0x73A0, 0xAB64, 0x73A1, 0xAB65, 0x73A2, 0xE7E3, + 0x73A3, 0xAB66, 0x73A4, 0xAB67, 0x73A5, 0xAB68, 0x73A6, 0xAB69, + 0x73A7, 0xAB6A, 0x73A8, 0xAB6B, 0x73A9, 0xCDE6, 0x73AA, 0xAB6C, + 0x73AB, 0xC3B5, 0x73AC, 0xAB6D, 0x73AD, 0xAB6E, 0x73AE, 0xE7E2, + 0x73AF, 0xBBB7, 0x73B0, 0xCFD6, 0x73B1, 0xAB6F, 0x73B2, 0xC1E1, + 0x73B3, 0xE7E9, 0x73B4, 0xAB70, 0x73B5, 0xAB71, 0x73B6, 0xAB72, + 0x73B7, 0xE7E8, 0x73B8, 0xAB73, 0x73B9, 0xAB74, 0x73BA, 0xE7F4, + 0x73BB, 0xB2A3, 0x73BC, 0xAB75, 0x73BD, 0xAB76, 0x73BE, 0xAB77, + 0x73BF, 0xAB78, 0x73C0, 0xE7EA, 0x73C1, 0xAB79, 0x73C2, 0xE7E6, + 0x73C3, 0xAB7A, 0x73C4, 0xAB7B, 0x73C5, 0xAB7C, 0x73C6, 0xAB7D, + 0x73C7, 0xAB7E, 0x73C8, 0xE7EC, 0x73C9, 0xE7EB, 0x73CA, 0xC9BA, + 0x73CB, 0xAB80, 0x73CC, 0xAB81, 0x73CD, 0xD5E4, 0x73CE, 0xAB82, + 0x73CF, 0xE7E5, 0x73D0, 0xB7A9, 0x73D1, 0xE7E7, 0x73D2, 0xAB83, + 0x73D3, 0xAB84, 0x73D4, 0xAB85, 0x73D5, 0xAB86, 0x73D6, 0xAB87, + 0x73D7, 0xAB88, 0x73D8, 0xAB89, 0x73D9, 0xE7EE, 0x73DA, 0xAB8A, + 0x73DB, 0xAB8B, 0x73DC, 0xAB8C, 0x73DD, 0xAB8D, 0x73DE, 0xE7F3, + 0x73DF, 0xAB8E, 0x73E0, 0xD6E9, 0x73E1, 0xAB8F, 0x73E2, 0xAB90, + 0x73E3, 0xAB91, 0x73E4, 0xAB92, 0x73E5, 0xE7ED, 0x73E6, 0xAB93, + 0x73E7, 0xE7F2, 0x73E8, 0xAB94, 0x73E9, 0xE7F1, 0x73EA, 0xAB95, + 0x73EB, 0xAB96, 0x73EC, 0xAB97, 0x73ED, 0xB0E0, 0x73EE, 0xAB98, + 0x73EF, 0xAB99, 0x73F0, 0xAB9A, 0x73F1, 0xAB9B, 0x73F2, 0xE7F5, + 0x73F3, 0xAB9C, 0x73F4, 0xAB9D, 0x73F5, 0xAB9E, 0x73F6, 0xAB9F, + 0x73F7, 0xABA0, 0x73F8, 0xAC40, 0x73F9, 0xAC41, 0x73FA, 0xAC42, + 0x73FB, 0xAC43, 0x73FC, 0xAC44, 0x73FD, 0xAC45, 0x73FE, 0xAC46, + 0x73FF, 0xAC47, 0x7400, 0xAC48, 0x7401, 0xAC49, 0x7402, 0xAC4A, + 0x7403, 0xC7F2, 0x7404, 0xAC4B, 0x7405, 0xC0C5, 0x7406, 0xC0ED, + 0x7407, 0xAC4C, 0x7408, 0xAC4D, 0x7409, 0xC1F0, 0x740A, 0xE7F0, + 0x740B, 0xAC4E, 0x740C, 0xAC4F, 0x740D, 0xAC50, 0x740E, 0xAC51, + 0x740F, 0xE7F6, 0x7410, 0xCBF6, 0x7411, 0xAC52, 0x7412, 0xAC53, + 0x7413, 0xAC54, 0x7414, 0xAC55, 0x7415, 0xAC56, 0x7416, 0xAC57, + 0x7417, 0xAC58, 0x7418, 0xAC59, 0x7419, 0xAC5A, 0x741A, 0xE8A2, + 0x741B, 0xE8A1, 0x741C, 0xAC5B, 0x741D, 0xAC5C, 0x741E, 0xAC5D, + 0x741F, 0xAC5E, 0x7420, 0xAC5F, 0x7421, 0xAC60, 0x7422, 0xD7C1, + 0x7423, 0xAC61, 0x7424, 0xAC62, 0x7425, 0xE7FA, 0x7426, 0xE7F9, + 0x7427, 0xAC63, 0x7428, 0xE7FB, 0x7429, 0xAC64, 0x742A, 0xE7F7, + 0x742B, 0xAC65, 0x742C, 0xE7FE, 0x742D, 0xAC66, 0x742E, 0xE7FD, + 0x742F, 0xAC67, 0x7430, 0xE7FC, 0x7431, 0xAC68, 0x7432, 0xAC69, + 0x7433, 0xC1D5, 0x7434, 0xC7D9, 0x7435, 0xC5FD, 0x7436, 0xC5C3, + 0x7437, 0xAC6A, 0x7438, 0xAC6B, 0x7439, 0xAC6C, 0x743A, 0xAC6D, + 0x743B, 0xAC6E, 0x743C, 0xC7ED, 0x743D, 0xAC6F, 0x743E, 0xAC70, + 0x743F, 0xAC71, 0x7440, 0xAC72, 0x7441, 0xE8A3, 0x7442, 0xAC73, + 0x7443, 0xAC74, 0x7444, 0xAC75, 0x7445, 0xAC76, 0x7446, 0xAC77, + 0x7447, 0xAC78, 0x7448, 0xAC79, 0x7449, 0xAC7A, 0x744A, 0xAC7B, + 0x744B, 0xAC7C, 0x744C, 0xAC7D, 0x744D, 0xAC7E, 0x744E, 0xAC80, + 0x744F, 0xAC81, 0x7450, 0xAC82, 0x7451, 0xAC83, 0x7452, 0xAC84, + 0x7453, 0xAC85, 0x7454, 0xAC86, 0x7455, 0xE8A6, 0x7456, 0xAC87, + 0x7457, 0xE8A5, 0x7458, 0xAC88, 0x7459, 0xE8A7, 0x745A, 0xBAF7, + 0x745B, 0xE7F8, 0x745C, 0xE8A4, 0x745D, 0xAC89, 0x745E, 0xC8F0, + 0x745F, 0xC9AA, 0x7460, 0xAC8A, 0x7461, 0xAC8B, 0x7462, 0xAC8C, + 0x7463, 0xAC8D, 0x7464, 0xAC8E, 0x7465, 0xAC8F, 0x7466, 0xAC90, + 0x7467, 0xAC91, 0x7468, 0xAC92, 0x7469, 0xAC93, 0x746A, 0xAC94, + 0x746B, 0xAC95, 0x746C, 0xAC96, 0x746D, 0xE8A9, 0x746E, 0xAC97, + 0x746F, 0xAC98, 0x7470, 0xB9E5, 0x7471, 0xAC99, 0x7472, 0xAC9A, + 0x7473, 0xAC9B, 0x7474, 0xAC9C, 0x7475, 0xAC9D, 0x7476, 0xD1FE, + 0x7477, 0xE8A8, 0x7478, 0xAC9E, 0x7479, 0xAC9F, 0x747A, 0xACA0, + 0x747B, 0xAD40, 0x747C, 0xAD41, 0x747D, 0xAD42, 0x747E, 0xE8AA, + 0x747F, 0xAD43, 0x7480, 0xE8AD, 0x7481, 0xE8AE, 0x7482, 0xAD44, + 0x7483, 0xC1A7, 0x7484, 0xAD45, 0x7485, 0xAD46, 0x7486, 0xAD47, + 0x7487, 0xE8AF, 0x7488, 0xAD48, 0x7489, 0xAD49, 0x748A, 0xAD4A, + 0x748B, 0xE8B0, 0x748C, 0xAD4B, 0x748D, 0xAD4C, 0x748E, 0xE8AC, + 0x748F, 0xAD4D, 0x7490, 0xE8B4, 0x7491, 0xAD4E, 0x7492, 0xAD4F, + 0x7493, 0xAD50, 0x7494, 0xAD51, 0x7495, 0xAD52, 0x7496, 0xAD53, + 0x7497, 0xAD54, 0x7498, 0xAD55, 0x7499, 0xAD56, 0x749A, 0xAD57, + 0x749B, 0xAD58, 0x749C, 0xE8AB, 0x749D, 0xAD59, 0x749E, 0xE8B1, + 0x749F, 0xAD5A, 0x74A0, 0xAD5B, 0x74A1, 0xAD5C, 0x74A2, 0xAD5D, + 0x74A3, 0xAD5E, 0x74A4, 0xAD5F, 0x74A5, 0xAD60, 0x74A6, 0xAD61, + 0x74A7, 0xE8B5, 0x74A8, 0xE8B2, 0x74A9, 0xE8B3, 0x74AA, 0xAD62, + 0x74AB, 0xAD63, 0x74AC, 0xAD64, 0x74AD, 0xAD65, 0x74AE, 0xAD66, + 0x74AF, 0xAD67, 0x74B0, 0xAD68, 0x74B1, 0xAD69, 0x74B2, 0xAD6A, + 0x74B3, 0xAD6B, 0x74B4, 0xAD6C, 0x74B5, 0xAD6D, 0x74B6, 0xAD6E, + 0x74B7, 0xAD6F, 0x74B8, 0xAD70, 0x74B9, 0xAD71, 0x74BA, 0xE8B7, + 0x74BB, 0xAD72, 0x74BC, 0xAD73, 0x74BD, 0xAD74, 0x74BE, 0xAD75, + 0x74BF, 0xAD76, 0x74C0, 0xAD77, 0x74C1, 0xAD78, 0x74C2, 0xAD79, + 0x74C3, 0xAD7A, 0x74C4, 0xAD7B, 0x74C5, 0xAD7C, 0x74C6, 0xAD7D, + 0x74C7, 0xAD7E, 0x74C8, 0xAD80, 0x74C9, 0xAD81, 0x74CA, 0xAD82, + 0x74CB, 0xAD83, 0x74CC, 0xAD84, 0x74CD, 0xAD85, 0x74CE, 0xAD86, + 0x74CF, 0xAD87, 0x74D0, 0xAD88, 0x74D1, 0xAD89, 0x74D2, 0xE8B6, + 0x74D3, 0xAD8A, 0x74D4, 0xAD8B, 0x74D5, 0xAD8C, 0x74D6, 0xAD8D, + 0x74D7, 0xAD8E, 0x74D8, 0xAD8F, 0x74D9, 0xAD90, 0x74DA, 0xAD91, + 0x74DB, 0xAD92, 0x74DC, 0xB9CF, 0x74DD, 0xAD93, 0x74DE, 0xF0AC, + 0x74DF, 0xAD94, 0x74E0, 0xF0AD, 0x74E1, 0xAD95, 0x74E2, 0xC6B0, + 0x74E3, 0xB0EA, 0x74E4, 0xC8BF, 0x74E5, 0xAD96, 0x74E6, 0xCDDF, + 0x74E7, 0xAD97, 0x74E8, 0xAD98, 0x74E9, 0xAD99, 0x74EA, 0xAD9A, + 0x74EB, 0xAD9B, 0x74EC, 0xAD9C, 0x74ED, 0xAD9D, 0x74EE, 0xCECD, + 0x74EF, 0xEAB1, 0x74F0, 0xAD9E, 0x74F1, 0xAD9F, 0x74F2, 0xADA0, + 0x74F3, 0xAE40, 0x74F4, 0xEAB2, 0x74F5, 0xAE41, 0x74F6, 0xC6BF, + 0x74F7, 0xB4C9, 0x74F8, 0xAE42, 0x74F9, 0xAE43, 0x74FA, 0xAE44, + 0x74FB, 0xAE45, 0x74FC, 0xAE46, 0x74FD, 0xAE47, 0x74FE, 0xAE48, + 0x74FF, 0xEAB3, 0x7500, 0xAE49, 0x7501, 0xAE4A, 0x7502, 0xAE4B, + 0x7503, 0xAE4C, 0x7504, 0xD5E7, 0x7505, 0xAE4D, 0x7506, 0xAE4E, + 0x7507, 0xAE4F, 0x7508, 0xAE50, 0x7509, 0xAE51, 0x750A, 0xAE52, + 0x750B, 0xAE53, 0x750C, 0xAE54, 0x750D, 0xDDF9, 0x750E, 0xAE55, + 0x750F, 0xEAB4, 0x7510, 0xAE56, 0x7511, 0xEAB5, 0x7512, 0xAE57, + 0x7513, 0xEAB6, 0x7514, 0xAE58, 0x7515, 0xAE59, 0x7516, 0xAE5A, + 0x7517, 0xAE5B, 0x7518, 0xB8CA, 0x7519, 0xDFB0, 0x751A, 0xC9F5, + 0x751B, 0xAE5C, 0x751C, 0xCCF0, 0x751D, 0xAE5D, 0x751E, 0xAE5E, + 0x751F, 0xC9FA, 0x7520, 0xAE5F, 0x7521, 0xAE60, 0x7522, 0xAE61, + 0x7523, 0xAE62, 0x7524, 0xAE63, 0x7525, 0xC9FB, 0x7526, 0xAE64, + 0x7527, 0xAE65, 0x7528, 0xD3C3, 0x7529, 0xCBA6, 0x752A, 0xAE66, + 0x752B, 0xB8A6, 0x752C, 0xF0AE, 0x752D, 0xB1C2, 0x752E, 0xAE67, + 0x752F, 0xE5B8, 0x7530, 0xCCEF, 0x7531, 0xD3C9, 0x7532, 0xBCD7, + 0x7533, 0xC9EA, 0x7534, 0xAE68, 0x7535, 0xB5E7, 0x7536, 0xAE69, + 0x7537, 0xC4D0, 0x7538, 0xB5E9, 0x7539, 0xAE6A, 0x753A, 0xEEAE, + 0x753B, 0xBBAD, 0x753C, 0xAE6B, 0x753D, 0xAE6C, 0x753E, 0xE7DE, + 0x753F, 0xAE6D, 0x7540, 0xEEAF, 0x7541, 0xAE6E, 0x7542, 0xAE6F, + 0x7543, 0xAE70, 0x7544, 0xAE71, 0x7545, 0xB3A9, 0x7546, 0xAE72, + 0x7547, 0xAE73, 0x7548, 0xEEB2, 0x7549, 0xAE74, 0x754A, 0xAE75, + 0x754B, 0xEEB1, 0x754C, 0xBDE7, 0x754D, 0xAE76, 0x754E, 0xEEB0, + 0x754F, 0xCEB7, 0x7550, 0xAE77, 0x7551, 0xAE78, 0x7552, 0xAE79, + 0x7553, 0xAE7A, 0x7554, 0xC5CF, 0x7555, 0xAE7B, 0x7556, 0xAE7C, + 0x7557, 0xAE7D, 0x7558, 0xAE7E, 0x7559, 0xC1F4, 0x755A, 0xDBCE, + 0x755B, 0xEEB3, 0x755C, 0xD0F3, 0x755D, 0xAE80, 0x755E, 0xAE81, + 0x755F, 0xAE82, 0x7560, 0xAE83, 0x7561, 0xAE84, 0x7562, 0xAE85, + 0x7563, 0xAE86, 0x7564, 0xAE87, 0x7565, 0xC2D4, 0x7566, 0xC6E8, + 0x7567, 0xAE88, 0x7568, 0xAE89, 0x7569, 0xAE8A, 0x756A, 0xB7AC, + 0x756B, 0xAE8B, 0x756C, 0xAE8C, 0x756D, 0xAE8D, 0x756E, 0xAE8E, + 0x756F, 0xAE8F, 0x7570, 0xAE90, 0x7571, 0xAE91, 0x7572, 0xEEB4, + 0x7573, 0xAE92, 0x7574, 0xB3EB, 0x7575, 0xAE93, 0x7576, 0xAE94, + 0x7577, 0xAE95, 0x7578, 0xBBFB, 0x7579, 0xEEB5, 0x757A, 0xAE96, + 0x757B, 0xAE97, 0x757C, 0xAE98, 0x757D, 0xAE99, 0x757E, 0xAE9A, + 0x757F, 0xE7DC, 0x7580, 0xAE9B, 0x7581, 0xAE9C, 0x7582, 0xAE9D, + 0x7583, 0xEEB6, 0x7584, 0xAE9E, 0x7585, 0xAE9F, 0x7586, 0xBDAE, + 0x7587, 0xAEA0, 0x7588, 0xAF40, 0x7589, 0xAF41, 0x758A, 0xAF42, + 0x758B, 0xF1E2, 0x758C, 0xAF43, 0x758D, 0xAF44, 0x758E, 0xAF45, + 0x758F, 0xCAE8, 0x7590, 0xAF46, 0x7591, 0xD2C9, 0x7592, 0xF0DA, + 0x7593, 0xAF47, 0x7594, 0xF0DB, 0x7595, 0xAF48, 0x7596, 0xF0DC, + 0x7597, 0xC1C6, 0x7598, 0xAF49, 0x7599, 0xB8ED, 0x759A, 0xBECE, + 0x759B, 0xAF4A, 0x759C, 0xAF4B, 0x759D, 0xF0DE, 0x759E, 0xAF4C, + 0x759F, 0xC5B1, 0x75A0, 0xF0DD, 0x75A1, 0xD1F1, 0x75A2, 0xAF4D, + 0x75A3, 0xF0E0, 0x75A4, 0xB0CC, 0x75A5, 0xBDEA, 0x75A6, 0xAF4E, + 0x75A7, 0xAF4F, 0x75A8, 0xAF50, 0x75A9, 0xAF51, 0x75AA, 0xAF52, + 0x75AB, 0xD2DF, 0x75AC, 0xF0DF, 0x75AD, 0xAF53, 0x75AE, 0xB4AF, + 0x75AF, 0xB7E8, 0x75B0, 0xF0E6, 0x75B1, 0xF0E5, 0x75B2, 0xC6A3, + 0x75B3, 0xF0E1, 0x75B4, 0xF0E2, 0x75B5, 0xB4C3, 0x75B6, 0xAF54, + 0x75B7, 0xAF55, 0x75B8, 0xF0E3, 0x75B9, 0xD5EE, 0x75BA, 0xAF56, + 0x75BB, 0xAF57, 0x75BC, 0xCCDB, 0x75BD, 0xBED2, 0x75BE, 0xBCB2, + 0x75BF, 0xAF58, 0x75C0, 0xAF59, 0x75C1, 0xAF5A, 0x75C2, 0xF0E8, + 0x75C3, 0xF0E7, 0x75C4, 0xF0E4, 0x75C5, 0xB2A1, 0x75C6, 0xAF5B, + 0x75C7, 0xD6A2, 0x75C8, 0xD3B8, 0x75C9, 0xBEB7, 0x75CA, 0xC8AC, + 0x75CB, 0xAF5C, 0x75CC, 0xAF5D, 0x75CD, 0xF0EA, 0x75CE, 0xAF5E, + 0x75CF, 0xAF5F, 0x75D0, 0xAF60, 0x75D1, 0xAF61, 0x75D2, 0xD1F7, + 0x75D3, 0xAF62, 0x75D4, 0xD6CC, 0x75D5, 0xBADB, 0x75D6, 0xF0E9, + 0x75D7, 0xAF63, 0x75D8, 0xB6BB, 0x75D9, 0xAF64, 0x75DA, 0xAF65, + 0x75DB, 0xCDB4, 0x75DC, 0xAF66, 0x75DD, 0xAF67, 0x75DE, 0xC6A6, + 0x75DF, 0xAF68, 0x75E0, 0xAF69, 0x75E1, 0xAF6A, 0x75E2, 0xC1A1, + 0x75E3, 0xF0EB, 0x75E4, 0xF0EE, 0x75E5, 0xAF6B, 0x75E6, 0xF0ED, + 0x75E7, 0xF0F0, 0x75E8, 0xF0EC, 0x75E9, 0xAF6C, 0x75EA, 0xBBBE, + 0x75EB, 0xF0EF, 0x75EC, 0xAF6D, 0x75ED, 0xAF6E, 0x75EE, 0xAF6F, + 0x75EF, 0xAF70, 0x75F0, 0xCCB5, 0x75F1, 0xF0F2, 0x75F2, 0xAF71, + 0x75F3, 0xAF72, 0x75F4, 0xB3D5, 0x75F5, 0xAF73, 0x75F6, 0xAF74, + 0x75F7, 0xAF75, 0x75F8, 0xAF76, 0x75F9, 0xB1D4, 0x75FA, 0xAF77, + 0x75FB, 0xAF78, 0x75FC, 0xF0F3, 0x75FD, 0xAF79, 0x75FE, 0xAF7A, + 0x75FF, 0xF0F4, 0x7600, 0xF0F6, 0x7601, 0xB4E1, 0x7602, 0xAF7B, + 0x7603, 0xF0F1, 0x7604, 0xAF7C, 0x7605, 0xF0F7, 0x7606, 0xAF7D, + 0x7607, 0xAF7E, 0x7608, 0xAF80, 0x7609, 0xAF81, 0x760A, 0xF0FA, + 0x760B, 0xAF82, 0x760C, 0xF0F8, 0x760D, 0xAF83, 0x760E, 0xAF84, + 0x760F, 0xAF85, 0x7610, 0xF0F5, 0x7611, 0xAF86, 0x7612, 0xAF87, + 0x7613, 0xAF88, 0x7614, 0xAF89, 0x7615, 0xF0FD, 0x7616, 0xAF8A, + 0x7617, 0xF0F9, 0x7618, 0xF0FC, 0x7619, 0xF0FE, 0x761A, 0xAF8B, + 0x761B, 0xF1A1, 0x761C, 0xAF8C, 0x761D, 0xAF8D, 0x761E, 0xAF8E, + 0x761F, 0xCEC1, 0x7620, 0xF1A4, 0x7621, 0xAF8F, 0x7622, 0xF1A3, + 0x7623, 0xAF90, 0x7624, 0xC1F6, 0x7625, 0xF0FB, 0x7626, 0xCADD, + 0x7627, 0xAF91, 0x7628, 0xAF92, 0x7629, 0xB4F1, 0x762A, 0xB1F1, + 0x762B, 0xCCB1, 0x762C, 0xAF93, 0x762D, 0xF1A6, 0x762E, 0xAF94, + 0x762F, 0xAF95, 0x7630, 0xF1A7, 0x7631, 0xAF96, 0x7632, 0xAF97, + 0x7633, 0xF1AC, 0x7634, 0xD5CE, 0x7635, 0xF1A9, 0x7636, 0xAF98, + 0x7637, 0xAF99, 0x7638, 0xC8B3, 0x7639, 0xAF9A, 0x763A, 0xAF9B, + 0x763B, 0xAF9C, 0x763C, 0xF1A2, 0x763D, 0xAF9D, 0x763E, 0xF1AB, + 0x763F, 0xF1A8, 0x7640, 0xF1A5, 0x7641, 0xAF9E, 0x7642, 0xAF9F, + 0x7643, 0xF1AA, 0x7644, 0xAFA0, 0x7645, 0xB040, 0x7646, 0xB041, + 0x7647, 0xB042, 0x7648, 0xB043, 0x7649, 0xB044, 0x764A, 0xB045, + 0x764B, 0xB046, 0x764C, 0xB0A9, 0x764D, 0xF1AD, 0x764E, 0xB047, + 0x764F, 0xB048, 0x7650, 0xB049, 0x7651, 0xB04A, 0x7652, 0xB04B, + 0x7653, 0xB04C, 0x7654, 0xF1AF, 0x7655, 0xB04D, 0x7656, 0xF1B1, + 0x7657, 0xB04E, 0x7658, 0xB04F, 0x7659, 0xB050, 0x765A, 0xB051, + 0x765B, 0xB052, 0x765C, 0xF1B0, 0x765D, 0xB053, 0x765E, 0xF1AE, + 0x765F, 0xB054, 0x7660, 0xB055, 0x7661, 0xB056, 0x7662, 0xB057, + 0x7663, 0xD1A2, 0x7664, 0xB058, 0x7665, 0xB059, 0x7666, 0xB05A, + 0x7667, 0xB05B, 0x7668, 0xB05C, 0x7669, 0xB05D, 0x766A, 0xB05E, + 0x766B, 0xF1B2, 0x766C, 0xB05F, 0x766D, 0xB060, 0x766E, 0xB061, + 0x766F, 0xF1B3, 0x7670, 0xB062, 0x7671, 0xB063, 0x7672, 0xB064, + 0x7673, 0xB065, 0x7674, 0xB066, 0x7675, 0xB067, 0x7676, 0xB068, + 0x7677, 0xB069, 0x7678, 0xB9EF, 0x7679, 0xB06A, 0x767A, 0xB06B, + 0x767B, 0xB5C7, 0x767C, 0xB06C, 0x767D, 0xB0D7, 0x767E, 0xB0D9, + 0x767F, 0xB06D, 0x7680, 0xB06E, 0x7681, 0xB06F, 0x7682, 0xD4ED, + 0x7683, 0xB070, 0x7684, 0xB5C4, 0x7685, 0xB071, 0x7686, 0xBDD4, + 0x7687, 0xBBCA, 0x7688, 0xF0A7, 0x7689, 0xB072, 0x768A, 0xB073, + 0x768B, 0xB8DE, 0x768C, 0xB074, 0x768D, 0xB075, 0x768E, 0xF0A8, + 0x768F, 0xB076, 0x7690, 0xB077, 0x7691, 0xB0A8, 0x7692, 0xB078, + 0x7693, 0xF0A9, 0x7694, 0xB079, 0x7695, 0xB07A, 0x7696, 0xCDEE, + 0x7697, 0xB07B, 0x7698, 0xB07C, 0x7699, 0xF0AA, 0x769A, 0xB07D, + 0x769B, 0xB07E, 0x769C, 0xB080, 0x769D, 0xB081, 0x769E, 0xB082, + 0x769F, 0xB083, 0x76A0, 0xB084, 0x76A1, 0xB085, 0x76A2, 0xB086, + 0x76A3, 0xB087, 0x76A4, 0xF0AB, 0x76A5, 0xB088, 0x76A6, 0xB089, + 0x76A7, 0xB08A, 0x76A8, 0xB08B, 0x76A9, 0xB08C, 0x76AA, 0xB08D, + 0x76AB, 0xB08E, 0x76AC, 0xB08F, 0x76AD, 0xB090, 0x76AE, 0xC6A4, + 0x76AF, 0xB091, 0x76B0, 0xB092, 0x76B1, 0xD6E5, 0x76B2, 0xF1E4, + 0x76B3, 0xB093, 0x76B4, 0xF1E5, 0x76B5, 0xB094, 0x76B6, 0xB095, + 0x76B7, 0xB096, 0x76B8, 0xB097, 0x76B9, 0xB098, 0x76BA, 0xB099, + 0x76BB, 0xB09A, 0x76BC, 0xB09B, 0x76BD, 0xB09C, 0x76BE, 0xB09D, + 0x76BF, 0xC3F3, 0x76C0, 0xB09E, 0x76C1, 0xB09F, 0x76C2, 0xD3DB, + 0x76C3, 0xB0A0, 0x76C4, 0xB140, 0x76C5, 0xD6D1, 0x76C6, 0xC5E8, + 0x76C7, 0xB141, 0x76C8, 0xD3AF, 0x76C9, 0xB142, 0x76CA, 0xD2E6, + 0x76CB, 0xB143, 0x76CC, 0xB144, 0x76CD, 0xEEC1, 0x76CE, 0xB0BB, + 0x76CF, 0xD5B5, 0x76D0, 0xD1CE, 0x76D1, 0xBCE0, 0x76D2, 0xBAD0, + 0x76D3, 0xB145, 0x76D4, 0xBFF8, 0x76D5, 0xB146, 0x76D6, 0xB8C7, + 0x76D7, 0xB5C1, 0x76D8, 0xC5CC, 0x76D9, 0xB147, 0x76DA, 0xB148, + 0x76DB, 0xCAA2, 0x76DC, 0xB149, 0x76DD, 0xB14A, 0x76DE, 0xB14B, + 0x76DF, 0xC3CB, 0x76E0, 0xB14C, 0x76E1, 0xB14D, 0x76E2, 0xB14E, + 0x76E3, 0xB14F, 0x76E4, 0xB150, 0x76E5, 0xEEC2, 0x76E6, 0xB151, + 0x76E7, 0xB152, 0x76E8, 0xB153, 0x76E9, 0xB154, 0x76EA, 0xB155, + 0x76EB, 0xB156, 0x76EC, 0xB157, 0x76ED, 0xB158, 0x76EE, 0xC4BF, + 0x76EF, 0xB6A2, 0x76F0, 0xB159, 0x76F1, 0xEDEC, 0x76F2, 0xC3A4, + 0x76F3, 0xB15A, 0x76F4, 0xD6B1, 0x76F5, 0xB15B, 0x76F6, 0xB15C, + 0x76F7, 0xB15D, 0x76F8, 0xCFE0, 0x76F9, 0xEDEF, 0x76FA, 0xB15E, + 0x76FB, 0xB15F, 0x76FC, 0xC5CE, 0x76FD, 0xB160, 0x76FE, 0xB6DC, + 0x76FF, 0xB161, 0x7700, 0xB162, 0x7701, 0xCAA1, 0x7702, 0xB163, + 0x7703, 0xB164, 0x7704, 0xEDED, 0x7705, 0xB165, 0x7706, 0xB166, + 0x7707, 0xEDF0, 0x7708, 0xEDF1, 0x7709, 0xC3BC, 0x770A, 0xB167, + 0x770B, 0xBFB4, 0x770C, 0xB168, 0x770D, 0xEDEE, 0x770E, 0xB169, + 0x770F, 0xB16A, 0x7710, 0xB16B, 0x7711, 0xB16C, 0x7712, 0xB16D, + 0x7713, 0xB16E, 0x7714, 0xB16F, 0x7715, 0xB170, 0x7716, 0xB171, + 0x7717, 0xB172, 0x7718, 0xB173, 0x7719, 0xEDF4, 0x771A, 0xEDF2, + 0x771B, 0xB174, 0x771C, 0xB175, 0x771D, 0xB176, 0x771E, 0xB177, + 0x771F, 0xD5E6, 0x7720, 0xC3DF, 0x7721, 0xB178, 0x7722, 0xEDF3, + 0x7723, 0xB179, 0x7724, 0xB17A, 0x7725, 0xB17B, 0x7726, 0xEDF6, + 0x7727, 0xB17C, 0x7728, 0xD5A3, 0x7729, 0xD1A3, 0x772A, 0xB17D, + 0x772B, 0xB17E, 0x772C, 0xB180, 0x772D, 0xEDF5, 0x772E, 0xB181, + 0x772F, 0xC3D0, 0x7730, 0xB182, 0x7731, 0xB183, 0x7732, 0xB184, + 0x7733, 0xB185, 0x7734, 0xB186, 0x7735, 0xEDF7, 0x7736, 0xBFF4, + 0x7737, 0xBEEC, 0x7738, 0xEDF8, 0x7739, 0xB187, 0x773A, 0xCCF7, + 0x773B, 0xB188, 0x773C, 0xD1DB, 0x773D, 0xB189, 0x773E, 0xB18A, + 0x773F, 0xB18B, 0x7740, 0xD7C5, 0x7741, 0xD5F6, 0x7742, 0xB18C, + 0x7743, 0xEDFC, 0x7744, 0xB18D, 0x7745, 0xB18E, 0x7746, 0xB18F, + 0x7747, 0xEDFB, 0x7748, 0xB190, 0x7749, 0xB191, 0x774A, 0xB192, + 0x774B, 0xB193, 0x774C, 0xB194, 0x774D, 0xB195, 0x774E, 0xB196, + 0x774F, 0xB197, 0x7750, 0xEDF9, 0x7751, 0xEDFA, 0x7752, 0xB198, + 0x7753, 0xB199, 0x7754, 0xB19A, 0x7755, 0xB19B, 0x7756, 0xB19C, + 0x7757, 0xB19D, 0x7758, 0xB19E, 0x7759, 0xB19F, 0x775A, 0xEDFD, + 0x775B, 0xBEA6, 0x775C, 0xB1A0, 0x775D, 0xB240, 0x775E, 0xB241, + 0x775F, 0xB242, 0x7760, 0xB243, 0x7761, 0xCBAF, 0x7762, 0xEEA1, + 0x7763, 0xB6BD, 0x7764, 0xB244, 0x7765, 0xEEA2, 0x7766, 0xC4C0, + 0x7767, 0xB245, 0x7768, 0xEDFE, 0x7769, 0xB246, 0x776A, 0xB247, + 0x776B, 0xBDDE, 0x776C, 0xB2C7, 0x776D, 0xB248, 0x776E, 0xB249, + 0x776F, 0xB24A, 0x7770, 0xB24B, 0x7771, 0xB24C, 0x7772, 0xB24D, + 0x7773, 0xB24E, 0x7774, 0xB24F, 0x7775, 0xB250, 0x7776, 0xB251, + 0x7777, 0xB252, 0x7778, 0xB253, 0x7779, 0xB6C3, 0x777A, 0xB254, + 0x777B, 0xB255, 0x777C, 0xB256, 0x777D, 0xEEA5, 0x777E, 0xD8BA, + 0x777F, 0xEEA3, 0x7780, 0xEEA6, 0x7781, 0xB257, 0x7782, 0xB258, + 0x7783, 0xB259, 0x7784, 0xC3E9, 0x7785, 0xB3F2, 0x7786, 0xB25A, + 0x7787, 0xB25B, 0x7788, 0xB25C, 0x7789, 0xB25D, 0x778A, 0xB25E, + 0x778B, 0xB25F, 0x778C, 0xEEA7, 0x778D, 0xEEA4, 0x778E, 0xCFB9, + 0x778F, 0xB260, 0x7790, 0xB261, 0x7791, 0xEEA8, 0x7792, 0xC2F7, + 0x7793, 0xB262, 0x7794, 0xB263, 0x7795, 0xB264, 0x7796, 0xB265, + 0x7797, 0xB266, 0x7798, 0xB267, 0x7799, 0xB268, 0x779A, 0xB269, + 0x779B, 0xB26A, 0x779C, 0xB26B, 0x779D, 0xB26C, 0x779E, 0xB26D, + 0x779F, 0xEEA9, 0x77A0, 0xEEAA, 0x77A1, 0xB26E, 0x77A2, 0xDEAB, + 0x77A3, 0xB26F, 0x77A4, 0xB270, 0x77A5, 0xC6B3, 0x77A6, 0xB271, + 0x77A7, 0xC7C6, 0x77A8, 0xB272, 0x77A9, 0xD6F5, 0x77AA, 0xB5C9, + 0x77AB, 0xB273, 0x77AC, 0xCBB2, 0x77AD, 0xB274, 0x77AE, 0xB275, + 0x77AF, 0xB276, 0x77B0, 0xEEAB, 0x77B1, 0xB277, 0x77B2, 0xB278, + 0x77B3, 0xCDAB, 0x77B4, 0xB279, 0x77B5, 0xEEAC, 0x77B6, 0xB27A, + 0x77B7, 0xB27B, 0x77B8, 0xB27C, 0x77B9, 0xB27D, 0x77BA, 0xB27E, + 0x77BB, 0xD5B0, 0x77BC, 0xB280, 0x77BD, 0xEEAD, 0x77BE, 0xB281, + 0x77BF, 0xF6C4, 0x77C0, 0xB282, 0x77C1, 0xB283, 0x77C2, 0xB284, + 0x77C3, 0xB285, 0x77C4, 0xB286, 0x77C5, 0xB287, 0x77C6, 0xB288, + 0x77C7, 0xB289, 0x77C8, 0xB28A, 0x77C9, 0xB28B, 0x77CA, 0xB28C, + 0x77CB, 0xB28D, 0x77CC, 0xB28E, 0x77CD, 0xDBC7, 0x77CE, 0xB28F, + 0x77CF, 0xB290, 0x77D0, 0xB291, 0x77D1, 0xB292, 0x77D2, 0xB293, + 0x77D3, 0xB294, 0x77D4, 0xB295, 0x77D5, 0xB296, 0x77D6, 0xB297, + 0x77D7, 0xB4A3, 0x77D8, 0xB298, 0x77D9, 0xB299, 0x77DA, 0xB29A, + 0x77DB, 0xC3AC, 0x77DC, 0xF1E6, 0x77DD, 0xB29B, 0x77DE, 0xB29C, + 0x77DF, 0xB29D, 0x77E0, 0xB29E, 0x77E1, 0xB29F, 0x77E2, 0xCAB8, + 0x77E3, 0xD2D3, 0x77E4, 0xB2A0, 0x77E5, 0xD6AA, 0x77E6, 0xB340, + 0x77E7, 0xEFF2, 0x77E8, 0xB341, 0x77E9, 0xBED8, 0x77EA, 0xB342, + 0x77EB, 0xBDC3, 0x77EC, 0xEFF3, 0x77ED, 0xB6CC, 0x77EE, 0xB0AB, + 0x77EF, 0xB343, 0x77F0, 0xB344, 0x77F1, 0xB345, 0x77F2, 0xB346, + 0x77F3, 0xCAAF, 0x77F4, 0xB347, 0x77F5, 0xB348, 0x77F6, 0xEDB6, + 0x77F7, 0xB349, 0x77F8, 0xEDB7, 0x77F9, 0xB34A, 0x77FA, 0xB34B, + 0x77FB, 0xB34C, 0x77FC, 0xB34D, 0x77FD, 0xCEF9, 0x77FE, 0xB7AF, + 0x77FF, 0xBFF3, 0x7800, 0xEDB8, 0x7801, 0xC2EB, 0x7802, 0xC9B0, + 0x7803, 0xB34E, 0x7804, 0xB34F, 0x7805, 0xB350, 0x7806, 0xB351, + 0x7807, 0xB352, 0x7808, 0xB353, 0x7809, 0xEDB9, 0x780A, 0xB354, + 0x780B, 0xB355, 0x780C, 0xC6F6, 0x780D, 0xBFB3, 0x780E, 0xB356, + 0x780F, 0xB357, 0x7810, 0xB358, 0x7811, 0xEDBC, 0x7812, 0xC5F8, + 0x7813, 0xB359, 0x7814, 0xD1D0, 0x7815, 0xB35A, 0x7816, 0xD7A9, + 0x7817, 0xEDBA, 0x7818, 0xEDBB, 0x7819, 0xB35B, 0x781A, 0xD1E2, + 0x781B, 0xB35C, 0x781C, 0xEDBF, 0x781D, 0xEDC0, 0x781E, 0xB35D, + 0x781F, 0xEDC4, 0x7820, 0xB35E, 0x7821, 0xB35F, 0x7822, 0xB360, + 0x7823, 0xEDC8, 0x7824, 0xB361, 0x7825, 0xEDC6, 0x7826, 0xEDCE, + 0x7827, 0xD5E8, 0x7828, 0xB362, 0x7829, 0xEDC9, 0x782A, 0xB363, + 0x782B, 0xB364, 0x782C, 0xEDC7, 0x782D, 0xEDBE, 0x782E, 0xB365, + 0x782F, 0xB366, 0x7830, 0xC5E9, 0x7831, 0xB367, 0x7832, 0xB368, + 0x7833, 0xB369, 0x7834, 0xC6C6, 0x7835, 0xB36A, 0x7836, 0xB36B, + 0x7837, 0xC9E9, 0x7838, 0xD4D2, 0x7839, 0xEDC1, 0x783A, 0xEDC2, + 0x783B, 0xEDC3, 0x783C, 0xEDC5, 0x783D, 0xB36C, 0x783E, 0xC0F9, + 0x783F, 0xB36D, 0x7840, 0xB4A1, 0x7841, 0xB36E, 0x7842, 0xB36F, + 0x7843, 0xB370, 0x7844, 0xB371, 0x7845, 0xB9E8, 0x7846, 0xB372, + 0x7847, 0xEDD0, 0x7848, 0xB373, 0x7849, 0xB374, 0x784A, 0xB375, + 0x784B, 0xB376, 0x784C, 0xEDD1, 0x784D, 0xB377, 0x784E, 0xEDCA, + 0x784F, 0xB378, 0x7850, 0xEDCF, 0x7851, 0xB379, 0x7852, 0xCEF8, + 0x7853, 0xB37A, 0x7854, 0xB37B, 0x7855, 0xCBB6, 0x7856, 0xEDCC, + 0x7857, 0xEDCD, 0x7858, 0xB37C, 0x7859, 0xB37D, 0x785A, 0xB37E, + 0x785B, 0xB380, 0x785C, 0xB381, 0x785D, 0xCFF5, 0x785E, 0xB382, + 0x785F, 0xB383, 0x7860, 0xB384, 0x7861, 0xB385, 0x7862, 0xB386, + 0x7863, 0xB387, 0x7864, 0xB388, 0x7865, 0xB389, 0x7866, 0xB38A, + 0x7867, 0xB38B, 0x7868, 0xB38C, 0x7869, 0xB38D, 0x786A, 0xEDD2, + 0x786B, 0xC1F2, 0x786C, 0xD3B2, 0x786D, 0xEDCB, 0x786E, 0xC8B7, + 0x786F, 0xB38E, 0x7870, 0xB38F, 0x7871, 0xB390, 0x7872, 0xB391, + 0x7873, 0xB392, 0x7874, 0xB393, 0x7875, 0xB394, 0x7876, 0xB395, + 0x7877, 0xBCEF, 0x7878, 0xB396, 0x7879, 0xB397, 0x787A, 0xB398, + 0x787B, 0xB399, 0x787C, 0xC5F0, 0x787D, 0xB39A, 0x787E, 0xB39B, + 0x787F, 0xB39C, 0x7880, 0xB39D, 0x7881, 0xB39E, 0x7882, 0xB39F, + 0x7883, 0xB3A0, 0x7884, 0xB440, 0x7885, 0xB441, 0x7886, 0xB442, + 0x7887, 0xEDD6, 0x7888, 0xB443, 0x7889, 0xB5EF, 0x788A, 0xB444, + 0x788B, 0xB445, 0x788C, 0xC2B5, 0x788D, 0xB0AD, 0x788E, 0xCBE9, + 0x788F, 0xB446, 0x7890, 0xB447, 0x7891, 0xB1AE, 0x7892, 0xB448, + 0x7893, 0xEDD4, 0x7894, 0xB449, 0x7895, 0xB44A, 0x7896, 0xB44B, + 0x7897, 0xCDEB, 0x7898, 0xB5E2, 0x7899, 0xB44C, 0x789A, 0xEDD5, + 0x789B, 0xEDD3, 0x789C, 0xEDD7, 0x789D, 0xB44D, 0x789E, 0xB44E, + 0x789F, 0xB5FA, 0x78A0, 0xB44F, 0x78A1, 0xEDD8, 0x78A2, 0xB450, + 0x78A3, 0xEDD9, 0x78A4, 0xB451, 0x78A5, 0xEDDC, 0x78A6, 0xB452, + 0x78A7, 0xB1CC, 0x78A8, 0xB453, 0x78A9, 0xB454, 0x78AA, 0xB455, + 0x78AB, 0xB456, 0x78AC, 0xB457, 0x78AD, 0xB458, 0x78AE, 0xB459, + 0x78AF, 0xB45A, 0x78B0, 0xC5F6, 0x78B1, 0xBCEE, 0x78B2, 0xEDDA, + 0x78B3, 0xCCBC, 0x78B4, 0xB2EA, 0x78B5, 0xB45B, 0x78B6, 0xB45C, + 0x78B7, 0xB45D, 0x78B8, 0xB45E, 0x78B9, 0xEDDB, 0x78BA, 0xB45F, + 0x78BB, 0xB460, 0x78BC, 0xB461, 0x78BD, 0xB462, 0x78BE, 0xC4EB, + 0x78BF, 0xB463, 0x78C0, 0xB464, 0x78C1, 0xB4C5, 0x78C2, 0xB465, + 0x78C3, 0xB466, 0x78C4, 0xB467, 0x78C5, 0xB0F5, 0x78C6, 0xB468, + 0x78C7, 0xB469, 0x78C8, 0xB46A, 0x78C9, 0xEDDF, 0x78CA, 0xC0DA, + 0x78CB, 0xB4E8, 0x78CC, 0xB46B, 0x78CD, 0xB46C, 0x78CE, 0xB46D, + 0x78CF, 0xB46E, 0x78D0, 0xC5CD, 0x78D1, 0xB46F, 0x78D2, 0xB470, + 0x78D3, 0xB471, 0x78D4, 0xEDDD, 0x78D5, 0xBFC4, 0x78D6, 0xB472, + 0x78D7, 0xB473, 0x78D8, 0xB474, 0x78D9, 0xEDDE, 0x78DA, 0xB475, + 0x78DB, 0xB476, 0x78DC, 0xB477, 0x78DD, 0xB478, 0x78DE, 0xB479, + 0x78DF, 0xB47A, 0x78E0, 0xB47B, 0x78E1, 0xB47C, 0x78E2, 0xB47D, + 0x78E3, 0xB47E, 0x78E4, 0xB480, 0x78E5, 0xB481, 0x78E6, 0xB482, + 0x78E7, 0xB483, 0x78E8, 0xC4A5, 0x78E9, 0xB484, 0x78EA, 0xB485, + 0x78EB, 0xB486, 0x78EC, 0xEDE0, 0x78ED, 0xB487, 0x78EE, 0xB488, + 0x78EF, 0xB489, 0x78F0, 0xB48A, 0x78F1, 0xB48B, 0x78F2, 0xEDE1, + 0x78F3, 0xB48C, 0x78F4, 0xEDE3, 0x78F5, 0xB48D, 0x78F6, 0xB48E, + 0x78F7, 0xC1D7, 0x78F8, 0xB48F, 0x78F9, 0xB490, 0x78FA, 0xBBC7, + 0x78FB, 0xB491, 0x78FC, 0xB492, 0x78FD, 0xB493, 0x78FE, 0xB494, + 0x78FF, 0xB495, 0x7900, 0xB496, 0x7901, 0xBDB8, 0x7902, 0xB497, + 0x7903, 0xB498, 0x7904, 0xB499, 0x7905, 0xEDE2, 0x7906, 0xB49A, + 0x7907, 0xB49B, 0x7908, 0xB49C, 0x7909, 0xB49D, 0x790A, 0xB49E, + 0x790B, 0xB49F, 0x790C, 0xB4A0, 0x790D, 0xB540, 0x790E, 0xB541, + 0x790F, 0xB542, 0x7910, 0xB543, 0x7911, 0xB544, 0x7912, 0xB545, + 0x7913, 0xEDE4, 0x7914, 0xB546, 0x7915, 0xB547, 0x7916, 0xB548, + 0x7917, 0xB549, 0x7918, 0xB54A, 0x7919, 0xB54B, 0x791A, 0xB54C, + 0x791B, 0xB54D, 0x791C, 0xB54E, 0x791D, 0xB54F, 0x791E, 0xEDE6, + 0x791F, 0xB550, 0x7920, 0xB551, 0x7921, 0xB552, 0x7922, 0xB553, + 0x7923, 0xB554, 0x7924, 0xEDE5, 0x7925, 0xB555, 0x7926, 0xB556, + 0x7927, 0xB557, 0x7928, 0xB558, 0x7929, 0xB559, 0x792A, 0xB55A, + 0x792B, 0xB55B, 0x792C, 0xB55C, 0x792D, 0xB55D, 0x792E, 0xB55E, + 0x792F, 0xB55F, 0x7930, 0xB560, 0x7931, 0xB561, 0x7932, 0xB562, + 0x7933, 0xB563, 0x7934, 0xEDE7, 0x7935, 0xB564, 0x7936, 0xB565, + 0x7937, 0xB566, 0x7938, 0xB567, 0x7939, 0xB568, 0x793A, 0xCABE, + 0x793B, 0xECEA, 0x793C, 0xC0F1, 0x793D, 0xB569, 0x793E, 0xC9E7, + 0x793F, 0xB56A, 0x7940, 0xECEB, 0x7941, 0xC6EE, 0x7942, 0xB56B, + 0x7943, 0xB56C, 0x7944, 0xB56D, 0x7945, 0xB56E, 0x7946, 0xECEC, + 0x7947, 0xB56F, 0x7948, 0xC6ED, 0x7949, 0xECED, 0x794A, 0xB570, + 0x794B, 0xB571, 0x794C, 0xB572, 0x794D, 0xB573, 0x794E, 0xB574, + 0x794F, 0xB575, 0x7950, 0xB576, 0x7951, 0xB577, 0x7952, 0xB578, + 0x7953, 0xECF0, 0x7954, 0xB579, 0x7955, 0xB57A, 0x7956, 0xD7E6, + 0x7957, 0xECF3, 0x7958, 0xB57B, 0x7959, 0xB57C, 0x795A, 0xECF1, + 0x795B, 0xECEE, 0x795C, 0xECEF, 0x795D, 0xD7A3, 0x795E, 0xC9F1, + 0x795F, 0xCBEE, 0x7960, 0xECF4, 0x7961, 0xB57D, 0x7962, 0xECF2, + 0x7963, 0xB57E, 0x7964, 0xB580, 0x7965, 0xCFE9, 0x7966, 0xB581, + 0x7967, 0xECF6, 0x7968, 0xC6B1, 0x7969, 0xB582, 0x796A, 0xB583, + 0x796B, 0xB584, 0x796C, 0xB585, 0x796D, 0xBCC0, 0x796E, 0xB586, + 0x796F, 0xECF5, 0x7970, 0xB587, 0x7971, 0xB588, 0x7972, 0xB589, + 0x7973, 0xB58A, 0x7974, 0xB58B, 0x7975, 0xB58C, 0x7976, 0xB58D, + 0x7977, 0xB5BB, 0x7978, 0xBBF6, 0x7979, 0xB58E, 0x797A, 0xECF7, + 0x797B, 0xB58F, 0x797C, 0xB590, 0x797D, 0xB591, 0x797E, 0xB592, + 0x797F, 0xB593, 0x7980, 0xD9F7, 0x7981, 0xBDFB, 0x7982, 0xB594, + 0x7983, 0xB595, 0x7984, 0xC2BB, 0x7985, 0xECF8, 0x7986, 0xB596, + 0x7987, 0xB597, 0x7988, 0xB598, 0x7989, 0xB599, 0x798A, 0xECF9, + 0x798B, 0xB59A, 0x798C, 0xB59B, 0x798D, 0xB59C, 0x798E, 0xB59D, + 0x798F, 0xB8A3, 0x7990, 0xB59E, 0x7991, 0xB59F, 0x7992, 0xB5A0, + 0x7993, 0xB640, 0x7994, 0xB641, 0x7995, 0xB642, 0x7996, 0xB643, + 0x7997, 0xB644, 0x7998, 0xB645, 0x7999, 0xB646, 0x799A, 0xECFA, + 0x799B, 0xB647, 0x799C, 0xB648, 0x799D, 0xB649, 0x799E, 0xB64A, + 0x799F, 0xB64B, 0x79A0, 0xB64C, 0x79A1, 0xB64D, 0x79A2, 0xB64E, + 0x79A3, 0xB64F, 0x79A4, 0xB650, 0x79A5, 0xB651, 0x79A6, 0xB652, + 0x79A7, 0xECFB, 0x79A8, 0xB653, 0x79A9, 0xB654, 0x79AA, 0xB655, + 0x79AB, 0xB656, 0x79AC, 0xB657, 0x79AD, 0xB658, 0x79AE, 0xB659, + 0x79AF, 0xB65A, 0x79B0, 0xB65B, 0x79B1, 0xB65C, 0x79B2, 0xB65D, + 0x79B3, 0xECFC, 0x79B4, 0xB65E, 0x79B5, 0xB65F, 0x79B6, 0xB660, + 0x79B7, 0xB661, 0x79B8, 0xB662, 0x79B9, 0xD3ED, 0x79BA, 0xD8AE, + 0x79BB, 0xC0EB, 0x79BC, 0xB663, 0x79BD, 0xC7DD, 0x79BE, 0xBACC, + 0x79BF, 0xB664, 0x79C0, 0xD0E3, 0x79C1, 0xCBBD, 0x79C2, 0xB665, + 0x79C3, 0xCDBA, 0x79C4, 0xB666, 0x79C5, 0xB667, 0x79C6, 0xB8D1, + 0x79C7, 0xB668, 0x79C8, 0xB669, 0x79C9, 0xB1FC, 0x79CA, 0xB66A, + 0x79CB, 0xC7EF, 0x79CC, 0xB66B, 0x79CD, 0xD6D6, 0x79CE, 0xB66C, + 0x79CF, 0xB66D, 0x79D0, 0xB66E, 0x79D1, 0xBFC6, 0x79D2, 0xC3EB, + 0x79D3, 0xB66F, 0x79D4, 0xB670, 0x79D5, 0xEFF5, 0x79D6, 0xB671, + 0x79D7, 0xB672, 0x79D8, 0xC3D8, 0x79D9, 0xB673, 0x79DA, 0xB674, + 0x79DB, 0xB675, 0x79DC, 0xB676, 0x79DD, 0xB677, 0x79DE, 0xB678, + 0x79DF, 0xD7E2, 0x79E0, 0xB679, 0x79E1, 0xB67A, 0x79E2, 0xB67B, + 0x79E3, 0xEFF7, 0x79E4, 0xB3D3, 0x79E5, 0xB67C, 0x79E6, 0xC7D8, + 0x79E7, 0xD1ED, 0x79E8, 0xB67D, 0x79E9, 0xD6C8, 0x79EA, 0xB67E, + 0x79EB, 0xEFF8, 0x79EC, 0xB680, 0x79ED, 0xEFF6, 0x79EE, 0xB681, + 0x79EF, 0xBBFD, 0x79F0, 0xB3C6, 0x79F1, 0xB682, 0x79F2, 0xB683, + 0x79F3, 0xB684, 0x79F4, 0xB685, 0x79F5, 0xB686, 0x79F6, 0xB687, + 0x79F7, 0xB688, 0x79F8, 0xBDD5, 0x79F9, 0xB689, 0x79FA, 0xB68A, + 0x79FB, 0xD2C6, 0x79FC, 0xB68B, 0x79FD, 0xBBE0, 0x79FE, 0xB68C, + 0x79FF, 0xB68D, 0x7A00, 0xCFA1, 0x7A01, 0xB68E, 0x7A02, 0xEFFC, + 0x7A03, 0xEFFB, 0x7A04, 0xB68F, 0x7A05, 0xB690, 0x7A06, 0xEFF9, + 0x7A07, 0xB691, 0x7A08, 0xB692, 0x7A09, 0xB693, 0x7A0A, 0xB694, + 0x7A0B, 0xB3CC, 0x7A0C, 0xB695, 0x7A0D, 0xC9D4, 0x7A0E, 0xCBB0, + 0x7A0F, 0xB696, 0x7A10, 0xB697, 0x7A11, 0xB698, 0x7A12, 0xB699, + 0x7A13, 0xB69A, 0x7A14, 0xEFFE, 0x7A15, 0xB69B, 0x7A16, 0xB69C, + 0x7A17, 0xB0DE, 0x7A18, 0xB69D, 0x7A19, 0xB69E, 0x7A1A, 0xD6C9, + 0x7A1B, 0xB69F, 0x7A1C, 0xB6A0, 0x7A1D, 0xB740, 0x7A1E, 0xEFFD, + 0x7A1F, 0xB741, 0x7A20, 0xB3ED, 0x7A21, 0xB742, 0x7A22, 0xB743, + 0x7A23, 0xF6D5, 0x7A24, 0xB744, 0x7A25, 0xB745, 0x7A26, 0xB746, + 0x7A27, 0xB747, 0x7A28, 0xB748, 0x7A29, 0xB749, 0x7A2A, 0xB74A, + 0x7A2B, 0xB74B, 0x7A2C, 0xB74C, 0x7A2D, 0xB74D, 0x7A2E, 0xB74E, + 0x7A2F, 0xB74F, 0x7A30, 0xB750, 0x7A31, 0xB751, 0x7A32, 0xB752, + 0x7A33, 0xCEC8, 0x7A34, 0xB753, 0x7A35, 0xB754, 0x7A36, 0xB755, + 0x7A37, 0xF0A2, 0x7A38, 0xB756, 0x7A39, 0xF0A1, 0x7A3A, 0xB757, + 0x7A3B, 0xB5BE, 0x7A3C, 0xBCDA, 0x7A3D, 0xBBFC, 0x7A3E, 0xB758, + 0x7A3F, 0xB8E5, 0x7A40, 0xB759, 0x7A41, 0xB75A, 0x7A42, 0xB75B, + 0x7A43, 0xB75C, 0x7A44, 0xB75D, 0x7A45, 0xB75E, 0x7A46, 0xC4C2, + 0x7A47, 0xB75F, 0x7A48, 0xB760, 0x7A49, 0xB761, 0x7A4A, 0xB762, + 0x7A4B, 0xB763, 0x7A4C, 0xB764, 0x7A4D, 0xB765, 0x7A4E, 0xB766, + 0x7A4F, 0xB767, 0x7A50, 0xB768, 0x7A51, 0xF0A3, 0x7A52, 0xB769, + 0x7A53, 0xB76A, 0x7A54, 0xB76B, 0x7A55, 0xB76C, 0x7A56, 0xB76D, + 0x7A57, 0xCBEB, 0x7A58, 0xB76E, 0x7A59, 0xB76F, 0x7A5A, 0xB770, + 0x7A5B, 0xB771, 0x7A5C, 0xB772, 0x7A5D, 0xB773, 0x7A5E, 0xB774, + 0x7A5F, 0xB775, 0x7A60, 0xB776, 0x7A61, 0xB777, 0x7A62, 0xB778, + 0x7A63, 0xB779, 0x7A64, 0xB77A, 0x7A65, 0xB77B, 0x7A66, 0xB77C, + 0x7A67, 0xB77D, 0x7A68, 0xB77E, 0x7A69, 0xB780, 0x7A6A, 0xB781, + 0x7A6B, 0xB782, 0x7A6C, 0xB783, 0x7A6D, 0xB784, 0x7A6E, 0xB785, + 0x7A6F, 0xB786, 0x7A70, 0xF0A6, 0x7A71, 0xB787, 0x7A72, 0xB788, + 0x7A73, 0xB789, 0x7A74, 0xD1A8, 0x7A75, 0xB78A, 0x7A76, 0xBEBF, + 0x7A77, 0xC7EE, 0x7A78, 0xF1B6, 0x7A79, 0xF1B7, 0x7A7A, 0xBFD5, + 0x7A7B, 0xB78B, 0x7A7C, 0xB78C, 0x7A7D, 0xB78D, 0x7A7E, 0xB78E, + 0x7A7F, 0xB4A9, 0x7A80, 0xF1B8, 0x7A81, 0xCDBB, 0x7A82, 0xB78F, + 0x7A83, 0xC7D4, 0x7A84, 0xD5AD, 0x7A85, 0xB790, 0x7A86, 0xF1B9, + 0x7A87, 0xB791, 0x7A88, 0xF1BA, 0x7A89, 0xB792, 0x7A8A, 0xB793, + 0x7A8B, 0xB794, 0x7A8C, 0xB795, 0x7A8D, 0xC7CF, 0x7A8E, 0xB796, + 0x7A8F, 0xB797, 0x7A90, 0xB798, 0x7A91, 0xD2A4, 0x7A92, 0xD6CF, + 0x7A93, 0xB799, 0x7A94, 0xB79A, 0x7A95, 0xF1BB, 0x7A96, 0xBDD1, + 0x7A97, 0xB4B0, 0x7A98, 0xBEBD, 0x7A99, 0xB79B, 0x7A9A, 0xB79C, + 0x7A9B, 0xB79D, 0x7A9C, 0xB4DC, 0x7A9D, 0xCED1, 0x7A9E, 0xB79E, + 0x7A9F, 0xBFDF, 0x7AA0, 0xF1BD, 0x7AA1, 0xB79F, 0x7AA2, 0xB7A0, + 0x7AA3, 0xB840, 0x7AA4, 0xB841, 0x7AA5, 0xBFFA, 0x7AA6, 0xF1BC, + 0x7AA7, 0xB842, 0x7AA8, 0xF1BF, 0x7AA9, 0xB843, 0x7AAA, 0xB844, + 0x7AAB, 0xB845, 0x7AAC, 0xF1BE, 0x7AAD, 0xF1C0, 0x7AAE, 0xB846, + 0x7AAF, 0xB847, 0x7AB0, 0xB848, 0x7AB1, 0xB849, 0x7AB2, 0xB84A, + 0x7AB3, 0xF1C1, 0x7AB4, 0xB84B, 0x7AB5, 0xB84C, 0x7AB6, 0xB84D, + 0x7AB7, 0xB84E, 0x7AB8, 0xB84F, 0x7AB9, 0xB850, 0x7ABA, 0xB851, + 0x7ABB, 0xB852, 0x7ABC, 0xB853, 0x7ABD, 0xB854, 0x7ABE, 0xB855, + 0x7ABF, 0xC1FE, 0x7AC0, 0xB856, 0x7AC1, 0xB857, 0x7AC2, 0xB858, + 0x7AC3, 0xB859, 0x7AC4, 0xB85A, 0x7AC5, 0xB85B, 0x7AC6, 0xB85C, + 0x7AC7, 0xB85D, 0x7AC8, 0xB85E, 0x7AC9, 0xB85F, 0x7ACA, 0xB860, + 0x7ACB, 0xC1A2, 0x7ACC, 0xB861, 0x7ACD, 0xB862, 0x7ACE, 0xB863, + 0x7ACF, 0xB864, 0x7AD0, 0xB865, 0x7AD1, 0xB866, 0x7AD2, 0xB867, + 0x7AD3, 0xB868, 0x7AD4, 0xB869, 0x7AD5, 0xB86A, 0x7AD6, 0xCAFA, + 0x7AD7, 0xB86B, 0x7AD8, 0xB86C, 0x7AD9, 0xD5BE, 0x7ADA, 0xB86D, + 0x7ADB, 0xB86E, 0x7ADC, 0xB86F, 0x7ADD, 0xB870, 0x7ADE, 0xBEBA, + 0x7ADF, 0xBEB9, 0x7AE0, 0xD5C2, 0x7AE1, 0xB871, 0x7AE2, 0xB872, + 0x7AE3, 0xBFA2, 0x7AE4, 0xB873, 0x7AE5, 0xCDAF, 0x7AE6, 0xF1B5, + 0x7AE7, 0xB874, 0x7AE8, 0xB875, 0x7AE9, 0xB876, 0x7AEA, 0xB877, + 0x7AEB, 0xB878, 0x7AEC, 0xB879, 0x7AED, 0xBDDF, 0x7AEE, 0xB87A, + 0x7AEF, 0xB6CB, 0x7AF0, 0xB87B, 0x7AF1, 0xB87C, 0x7AF2, 0xB87D, + 0x7AF3, 0xB87E, 0x7AF4, 0xB880, 0x7AF5, 0xB881, 0x7AF6, 0xB882, + 0x7AF7, 0xB883, 0x7AF8, 0xB884, 0x7AF9, 0xD6F1, 0x7AFA, 0xF3C3, + 0x7AFB, 0xB885, 0x7AFC, 0xB886, 0x7AFD, 0xF3C4, 0x7AFE, 0xB887, + 0x7AFF, 0xB8CD, 0x7B00, 0xB888, 0x7B01, 0xB889, 0x7B02, 0xB88A, + 0x7B03, 0xF3C6, 0x7B04, 0xF3C7, 0x7B05, 0xB88B, 0x7B06, 0xB0CA, + 0x7B07, 0xB88C, 0x7B08, 0xF3C5, 0x7B09, 0xB88D, 0x7B0A, 0xF3C9, + 0x7B0B, 0xCBF1, 0x7B0C, 0xB88E, 0x7B0D, 0xB88F, 0x7B0E, 0xB890, + 0x7B0F, 0xF3CB, 0x7B10, 0xB891, 0x7B11, 0xD0A6, 0x7B12, 0xB892, + 0x7B13, 0xB893, 0x7B14, 0xB1CA, 0x7B15, 0xF3C8, 0x7B16, 0xB894, + 0x7B17, 0xB895, 0x7B18, 0xB896, 0x7B19, 0xF3CF, 0x7B1A, 0xB897, + 0x7B1B, 0xB5D1, 0x7B1C, 0xB898, 0x7B1D, 0xB899, 0x7B1E, 0xF3D7, + 0x7B1F, 0xB89A, 0x7B20, 0xF3D2, 0x7B21, 0xB89B, 0x7B22, 0xB89C, + 0x7B23, 0xB89D, 0x7B24, 0xF3D4, 0x7B25, 0xF3D3, 0x7B26, 0xB7FB, + 0x7B27, 0xB89E, 0x7B28, 0xB1BF, 0x7B29, 0xB89F, 0x7B2A, 0xF3CE, + 0x7B2B, 0xF3CA, 0x7B2C, 0xB5DA, 0x7B2D, 0xB8A0, 0x7B2E, 0xF3D0, + 0x7B2F, 0xB940, 0x7B30, 0xB941, 0x7B31, 0xF3D1, 0x7B32, 0xB942, + 0x7B33, 0xF3D5, 0x7B34, 0xB943, 0x7B35, 0xB944, 0x7B36, 0xB945, + 0x7B37, 0xB946, 0x7B38, 0xF3CD, 0x7B39, 0xB947, 0x7B3A, 0xBCE3, + 0x7B3B, 0xB948, 0x7B3C, 0xC1FD, 0x7B3D, 0xB949, 0x7B3E, 0xF3D6, + 0x7B3F, 0xB94A, 0x7B40, 0xB94B, 0x7B41, 0xB94C, 0x7B42, 0xB94D, + 0x7B43, 0xB94E, 0x7B44, 0xB94F, 0x7B45, 0xF3DA, 0x7B46, 0xB950, + 0x7B47, 0xF3CC, 0x7B48, 0xB951, 0x7B49, 0xB5C8, 0x7B4A, 0xB952, + 0x7B4B, 0xBDEE, 0x7B4C, 0xF3DC, 0x7B4D, 0xB953, 0x7B4E, 0xB954, + 0x7B4F, 0xB7A4, 0x7B50, 0xBFF0, 0x7B51, 0xD6FE, 0x7B52, 0xCDB2, + 0x7B53, 0xB955, 0x7B54, 0xB4F0, 0x7B55, 0xB956, 0x7B56, 0xB2DF, + 0x7B57, 0xB957, 0x7B58, 0xF3D8, 0x7B59, 0xB958, 0x7B5A, 0xF3D9, + 0x7B5B, 0xC9B8, 0x7B5C, 0xB959, 0x7B5D, 0xF3DD, 0x7B5E, 0xB95A, + 0x7B5F, 0xB95B, 0x7B60, 0xF3DE, 0x7B61, 0xB95C, 0x7B62, 0xF3E1, + 0x7B63, 0xB95D, 0x7B64, 0xB95E, 0x7B65, 0xB95F, 0x7B66, 0xB960, + 0x7B67, 0xB961, 0x7B68, 0xB962, 0x7B69, 0xB963, 0x7B6A, 0xB964, + 0x7B6B, 0xB965, 0x7B6C, 0xB966, 0x7B6D, 0xB967, 0x7B6E, 0xF3DF, + 0x7B6F, 0xB968, 0x7B70, 0xB969, 0x7B71, 0xF3E3, 0x7B72, 0xF3E2, + 0x7B73, 0xB96A, 0x7B74, 0xB96B, 0x7B75, 0xF3DB, 0x7B76, 0xB96C, + 0x7B77, 0xBFEA, 0x7B78, 0xB96D, 0x7B79, 0xB3EF, 0x7B7A, 0xB96E, + 0x7B7B, 0xF3E0, 0x7B7C, 0xB96F, 0x7B7D, 0xB970, 0x7B7E, 0xC7A9, + 0x7B7F, 0xB971, 0x7B80, 0xBCF2, 0x7B81, 0xB972, 0x7B82, 0xB973, + 0x7B83, 0xB974, 0x7B84, 0xB975, 0x7B85, 0xF3EB, 0x7B86, 0xB976, + 0x7B87, 0xB977, 0x7B88, 0xB978, 0x7B89, 0xB979, 0x7B8A, 0xB97A, + 0x7B8B, 0xB97B, 0x7B8C, 0xB97C, 0x7B8D, 0xB9BF, 0x7B8E, 0xB97D, + 0x7B8F, 0xB97E, 0x7B90, 0xF3E4, 0x7B91, 0xB980, 0x7B92, 0xB981, + 0x7B93, 0xB982, 0x7B94, 0xB2AD, 0x7B95, 0xBBFE, 0x7B96, 0xB983, + 0x7B97, 0xCBE3, 0x7B98, 0xB984, 0x7B99, 0xB985, 0x7B9A, 0xB986, + 0x7B9B, 0xB987, 0x7B9C, 0xF3ED, 0x7B9D, 0xF3E9, 0x7B9E, 0xB988, + 0x7B9F, 0xB989, 0x7BA0, 0xB98A, 0x7BA1, 0xB9DC, 0x7BA2, 0xF3EE, + 0x7BA3, 0xB98B, 0x7BA4, 0xB98C, 0x7BA5, 0xB98D, 0x7BA6, 0xF3E5, + 0x7BA7, 0xF3E6, 0x7BA8, 0xF3EA, 0x7BA9, 0xC2E1, 0x7BAA, 0xF3EC, + 0x7BAB, 0xF3EF, 0x7BAC, 0xF3E8, 0x7BAD, 0xBCFD, 0x7BAE, 0xB98E, + 0x7BAF, 0xB98F, 0x7BB0, 0xB990, 0x7BB1, 0xCFE4, 0x7BB2, 0xB991, + 0x7BB3, 0xB992, 0x7BB4, 0xF3F0, 0x7BB5, 0xB993, 0x7BB6, 0xB994, + 0x7BB7, 0xB995, 0x7BB8, 0xF3E7, 0x7BB9, 0xB996, 0x7BBA, 0xB997, + 0x7BBB, 0xB998, 0x7BBC, 0xB999, 0x7BBD, 0xB99A, 0x7BBE, 0xB99B, + 0x7BBF, 0xB99C, 0x7BC0, 0xB99D, 0x7BC1, 0xF3F2, 0x7BC2, 0xB99E, + 0x7BC3, 0xB99F, 0x7BC4, 0xB9A0, 0x7BC5, 0xBA40, 0x7BC6, 0xD7AD, + 0x7BC7, 0xC6AA, 0x7BC8, 0xBA41, 0x7BC9, 0xBA42, 0x7BCA, 0xBA43, + 0x7BCB, 0xBA44, 0x7BCC, 0xF3F3, 0x7BCD, 0xBA45, 0x7BCE, 0xBA46, + 0x7BCF, 0xBA47, 0x7BD0, 0xBA48, 0x7BD1, 0xF3F1, 0x7BD2, 0xBA49, + 0x7BD3, 0xC2A8, 0x7BD4, 0xBA4A, 0x7BD5, 0xBA4B, 0x7BD6, 0xBA4C, + 0x7BD7, 0xBA4D, 0x7BD8, 0xBA4E, 0x7BD9, 0xB8DD, 0x7BDA, 0xF3F5, + 0x7BDB, 0xBA4F, 0x7BDC, 0xBA50, 0x7BDD, 0xF3F4, 0x7BDE, 0xBA51, + 0x7BDF, 0xBA52, 0x7BE0, 0xBA53, 0x7BE1, 0xB4DB, 0x7BE2, 0xBA54, + 0x7BE3, 0xBA55, 0x7BE4, 0xBA56, 0x7BE5, 0xF3F6, 0x7BE6, 0xF3F7, + 0x7BE7, 0xBA57, 0x7BE8, 0xBA58, 0x7BE9, 0xBA59, 0x7BEA, 0xF3F8, + 0x7BEB, 0xBA5A, 0x7BEC, 0xBA5B, 0x7BED, 0xBA5C, 0x7BEE, 0xC0BA, + 0x7BEF, 0xBA5D, 0x7BF0, 0xBA5E, 0x7BF1, 0xC0E9, 0x7BF2, 0xBA5F, + 0x7BF3, 0xBA60, 0x7BF4, 0xBA61, 0x7BF5, 0xBA62, 0x7BF6, 0xBA63, + 0x7BF7, 0xC5F1, 0x7BF8, 0xBA64, 0x7BF9, 0xBA65, 0x7BFA, 0xBA66, + 0x7BFB, 0xBA67, 0x7BFC, 0xF3FB, 0x7BFD, 0xBA68, 0x7BFE, 0xF3FA, + 0x7BFF, 0xBA69, 0x7C00, 0xBA6A, 0x7C01, 0xBA6B, 0x7C02, 0xBA6C, + 0x7C03, 0xBA6D, 0x7C04, 0xBA6E, 0x7C05, 0xBA6F, 0x7C06, 0xBA70, + 0x7C07, 0xB4D8, 0x7C08, 0xBA71, 0x7C09, 0xBA72, 0x7C0A, 0xBA73, + 0x7C0B, 0xF3FE, 0x7C0C, 0xF3F9, 0x7C0D, 0xBA74, 0x7C0E, 0xBA75, + 0x7C0F, 0xF3FC, 0x7C10, 0xBA76, 0x7C11, 0xBA77, 0x7C12, 0xBA78, + 0x7C13, 0xBA79, 0x7C14, 0xBA7A, 0x7C15, 0xBA7B, 0x7C16, 0xF3FD, + 0x7C17, 0xBA7C, 0x7C18, 0xBA7D, 0x7C19, 0xBA7E, 0x7C1A, 0xBA80, + 0x7C1B, 0xBA81, 0x7C1C, 0xBA82, 0x7C1D, 0xBA83, 0x7C1E, 0xBA84, + 0x7C1F, 0xF4A1, 0x7C20, 0xBA85, 0x7C21, 0xBA86, 0x7C22, 0xBA87, + 0x7C23, 0xBA88, 0x7C24, 0xBA89, 0x7C25, 0xBA8A, 0x7C26, 0xF4A3, + 0x7C27, 0xBBC9, 0x7C28, 0xBA8B, 0x7C29, 0xBA8C, 0x7C2A, 0xF4A2, + 0x7C2B, 0xBA8D, 0x7C2C, 0xBA8E, 0x7C2D, 0xBA8F, 0x7C2E, 0xBA90, + 0x7C2F, 0xBA91, 0x7C30, 0xBA92, 0x7C31, 0xBA93, 0x7C32, 0xBA94, + 0x7C33, 0xBA95, 0x7C34, 0xBA96, 0x7C35, 0xBA97, 0x7C36, 0xBA98, + 0x7C37, 0xBA99, 0x7C38, 0xF4A4, 0x7C39, 0xBA9A, 0x7C3A, 0xBA9B, + 0x7C3B, 0xBA9C, 0x7C3C, 0xBA9D, 0x7C3D, 0xBA9E, 0x7C3E, 0xBA9F, + 0x7C3F, 0xB2BE, 0x7C40, 0xF4A6, 0x7C41, 0xF4A5, 0x7C42, 0xBAA0, + 0x7C43, 0xBB40, 0x7C44, 0xBB41, 0x7C45, 0xBB42, 0x7C46, 0xBB43, + 0x7C47, 0xBB44, 0x7C48, 0xBB45, 0x7C49, 0xBB46, 0x7C4A, 0xBB47, + 0x7C4B, 0xBB48, 0x7C4C, 0xBB49, 0x7C4D, 0xBCAE, 0x7C4E, 0xBB4A, + 0x7C4F, 0xBB4B, 0x7C50, 0xBB4C, 0x7C51, 0xBB4D, 0x7C52, 0xBB4E, + 0x7C53, 0xBB4F, 0x7C54, 0xBB50, 0x7C55, 0xBB51, 0x7C56, 0xBB52, + 0x7C57, 0xBB53, 0x7C58, 0xBB54, 0x7C59, 0xBB55, 0x7C5A, 0xBB56, + 0x7C5B, 0xBB57, 0x7C5C, 0xBB58, 0x7C5D, 0xBB59, 0x7C5E, 0xBB5A, + 0x7C5F, 0xBB5B, 0x7C60, 0xBB5C, 0x7C61, 0xBB5D, 0x7C62, 0xBB5E, + 0x7C63, 0xBB5F, 0x7C64, 0xBB60, 0x7C65, 0xBB61, 0x7C66, 0xBB62, + 0x7C67, 0xBB63, 0x7C68, 0xBB64, 0x7C69, 0xBB65, 0x7C6A, 0xBB66, + 0x7C6B, 0xBB67, 0x7C6C, 0xBB68, 0x7C6D, 0xBB69, 0x7C6E, 0xBB6A, + 0x7C6F, 0xBB6B, 0x7C70, 0xBB6C, 0x7C71, 0xBB6D, 0x7C72, 0xBB6E, + 0x7C73, 0xC3D7, 0x7C74, 0xD9E1, 0x7C75, 0xBB6F, 0x7C76, 0xBB70, + 0x7C77, 0xBB71, 0x7C78, 0xBB72, 0x7C79, 0xBB73, 0x7C7A, 0xBB74, + 0x7C7B, 0xC0E0, 0x7C7C, 0xF4CC, 0x7C7D, 0xD7D1, 0x7C7E, 0xBB75, + 0x7C7F, 0xBB76, 0x7C80, 0xBB77, 0x7C81, 0xBB78, 0x7C82, 0xBB79, + 0x7C83, 0xBB7A, 0x7C84, 0xBB7B, 0x7C85, 0xBB7C, 0x7C86, 0xBB7D, + 0x7C87, 0xBB7E, 0x7C88, 0xBB80, 0x7C89, 0xB7DB, 0x7C8A, 0xBB81, + 0x7C8B, 0xBB82, 0x7C8C, 0xBB83, 0x7C8D, 0xBB84, 0x7C8E, 0xBB85, + 0x7C8F, 0xBB86, 0x7C90, 0xBB87, 0x7C91, 0xF4CE, 0x7C92, 0xC1A3, + 0x7C93, 0xBB88, 0x7C94, 0xBB89, 0x7C95, 0xC6C9, 0x7C96, 0xBB8A, + 0x7C97, 0xB4D6, 0x7C98, 0xD5B3, 0x7C99, 0xBB8B, 0x7C9A, 0xBB8C, + 0x7C9B, 0xBB8D, 0x7C9C, 0xF4D0, 0x7C9D, 0xF4CF, 0x7C9E, 0xF4D1, + 0x7C9F, 0xCBDA, 0x7CA0, 0xBB8E, 0x7CA1, 0xBB8F, 0x7CA2, 0xF4D2, + 0x7CA3, 0xBB90, 0x7CA4, 0xD4C1, 0x7CA5, 0xD6E0, 0x7CA6, 0xBB91, + 0x7CA7, 0xBB92, 0x7CA8, 0xBB93, 0x7CA9, 0xBB94, 0x7CAA, 0xB7E0, + 0x7CAB, 0xBB95, 0x7CAC, 0xBB96, 0x7CAD, 0xBB97, 0x7CAE, 0xC1B8, + 0x7CAF, 0xBB98, 0x7CB0, 0xBB99, 0x7CB1, 0xC1BB, 0x7CB2, 0xF4D3, + 0x7CB3, 0xBEAC, 0x7CB4, 0xBB9A, 0x7CB5, 0xBB9B, 0x7CB6, 0xBB9C, + 0x7CB7, 0xBB9D, 0x7CB8, 0xBB9E, 0x7CB9, 0xB4E2, 0x7CBA, 0xBB9F, + 0x7CBB, 0xBBA0, 0x7CBC, 0xF4D4, 0x7CBD, 0xF4D5, 0x7CBE, 0xBEAB, + 0x7CBF, 0xBC40, 0x7CC0, 0xBC41, 0x7CC1, 0xF4D6, 0x7CC2, 0xBC42, + 0x7CC3, 0xBC43, 0x7CC4, 0xBC44, 0x7CC5, 0xF4DB, 0x7CC6, 0xBC45, + 0x7CC7, 0xF4D7, 0x7CC8, 0xF4DA, 0x7CC9, 0xBC46, 0x7CCA, 0xBAFD, + 0x7CCB, 0xBC47, 0x7CCC, 0xF4D8, 0x7CCD, 0xF4D9, 0x7CCE, 0xBC48, + 0x7CCF, 0xBC49, 0x7CD0, 0xBC4A, 0x7CD1, 0xBC4B, 0x7CD2, 0xBC4C, + 0x7CD3, 0xBC4D, 0x7CD4, 0xBC4E, 0x7CD5, 0xB8E2, 0x7CD6, 0xCCC7, + 0x7CD7, 0xF4DC, 0x7CD8, 0xBC4F, 0x7CD9, 0xB2DA, 0x7CDA, 0xBC50, + 0x7CDB, 0xBC51, 0x7CDC, 0xC3D3, 0x7CDD, 0xBC52, 0x7CDE, 0xBC53, + 0x7CDF, 0xD4E3, 0x7CE0, 0xBFB7, 0x7CE1, 0xBC54, 0x7CE2, 0xBC55, + 0x7CE3, 0xBC56, 0x7CE4, 0xBC57, 0x7CE5, 0xBC58, 0x7CE6, 0xBC59, + 0x7CE7, 0xBC5A, 0x7CE8, 0xF4DD, 0x7CE9, 0xBC5B, 0x7CEA, 0xBC5C, + 0x7CEB, 0xBC5D, 0x7CEC, 0xBC5E, 0x7CED, 0xBC5F, 0x7CEE, 0xBC60, + 0x7CEF, 0xC5B4, 0x7CF0, 0xBC61, 0x7CF1, 0xBC62, 0x7CF2, 0xBC63, + 0x7CF3, 0xBC64, 0x7CF4, 0xBC65, 0x7CF5, 0xBC66, 0x7CF6, 0xBC67, + 0x7CF7, 0xBC68, 0x7CF8, 0xF4E9, 0x7CF9, 0xBC69, 0x7CFA, 0xBC6A, + 0x7CFB, 0xCFB5, 0x7CFC, 0xBC6B, 0x7CFD, 0xBC6C, 0x7CFE, 0xBC6D, + 0x7CFF, 0xBC6E, 0x7D00, 0xBC6F, 0x7D01, 0xBC70, 0x7D02, 0xBC71, + 0x7D03, 0xBC72, 0x7D04, 0xBC73, 0x7D05, 0xBC74, 0x7D06, 0xBC75, + 0x7D07, 0xBC76, 0x7D08, 0xBC77, 0x7D09, 0xBC78, 0x7D0A, 0xCEC9, + 0x7D0B, 0xBC79, 0x7D0C, 0xBC7A, 0x7D0D, 0xBC7B, 0x7D0E, 0xBC7C, + 0x7D0F, 0xBC7D, 0x7D10, 0xBC7E, 0x7D11, 0xBC80, 0x7D12, 0xBC81, + 0x7D13, 0xBC82, 0x7D14, 0xBC83, 0x7D15, 0xBC84, 0x7D16, 0xBC85, + 0x7D17, 0xBC86, 0x7D18, 0xBC87, 0x7D19, 0xBC88, 0x7D1A, 0xBC89, + 0x7D1B, 0xBC8A, 0x7D1C, 0xBC8B, 0x7D1D, 0xBC8C, 0x7D1E, 0xBC8D, + 0x7D1F, 0xBC8E, 0x7D20, 0xCBD8, 0x7D21, 0xBC8F, 0x7D22, 0xCBF7, + 0x7D23, 0xBC90, 0x7D24, 0xBC91, 0x7D25, 0xBC92, 0x7D26, 0xBC93, + 0x7D27, 0xBDF4, 0x7D28, 0xBC94, 0x7D29, 0xBC95, 0x7D2A, 0xBC96, + 0x7D2B, 0xD7CF, 0x7D2C, 0xBC97, 0x7D2D, 0xBC98, 0x7D2E, 0xBC99, + 0x7D2F, 0xC0DB, 0x7D30, 0xBC9A, 0x7D31, 0xBC9B, 0x7D32, 0xBC9C, + 0x7D33, 0xBC9D, 0x7D34, 0xBC9E, 0x7D35, 0xBC9F, 0x7D36, 0xBCA0, + 0x7D37, 0xBD40, 0x7D38, 0xBD41, 0x7D39, 0xBD42, 0x7D3A, 0xBD43, + 0x7D3B, 0xBD44, 0x7D3C, 0xBD45, 0x7D3D, 0xBD46, 0x7D3E, 0xBD47, + 0x7D3F, 0xBD48, 0x7D40, 0xBD49, 0x7D41, 0xBD4A, 0x7D42, 0xBD4B, + 0x7D43, 0xBD4C, 0x7D44, 0xBD4D, 0x7D45, 0xBD4E, 0x7D46, 0xBD4F, + 0x7D47, 0xBD50, 0x7D48, 0xBD51, 0x7D49, 0xBD52, 0x7D4A, 0xBD53, + 0x7D4B, 0xBD54, 0x7D4C, 0xBD55, 0x7D4D, 0xBD56, 0x7D4E, 0xBD57, + 0x7D4F, 0xBD58, 0x7D50, 0xBD59, 0x7D51, 0xBD5A, 0x7D52, 0xBD5B, + 0x7D53, 0xBD5C, 0x7D54, 0xBD5D, 0x7D55, 0xBD5E, 0x7D56, 0xBD5F, + 0x7D57, 0xBD60, 0x7D58, 0xBD61, 0x7D59, 0xBD62, 0x7D5A, 0xBD63, + 0x7D5B, 0xBD64, 0x7D5C, 0xBD65, 0x7D5D, 0xBD66, 0x7D5E, 0xBD67, + 0x7D5F, 0xBD68, 0x7D60, 0xBD69, 0x7D61, 0xBD6A, 0x7D62, 0xBD6B, + 0x7D63, 0xBD6C, 0x7D64, 0xBD6D, 0x7D65, 0xBD6E, 0x7D66, 0xBD6F, + 0x7D67, 0xBD70, 0x7D68, 0xBD71, 0x7D69, 0xBD72, 0x7D6A, 0xBD73, + 0x7D6B, 0xBD74, 0x7D6C, 0xBD75, 0x7D6D, 0xBD76, 0x7D6E, 0xD0F5, + 0x7D6F, 0xBD77, 0x7D70, 0xBD78, 0x7D71, 0xBD79, 0x7D72, 0xBD7A, + 0x7D73, 0xBD7B, 0x7D74, 0xBD7C, 0x7D75, 0xBD7D, 0x7D76, 0xBD7E, + 0x7D77, 0xF4EA, 0x7D78, 0xBD80, 0x7D79, 0xBD81, 0x7D7A, 0xBD82, + 0x7D7B, 0xBD83, 0x7D7C, 0xBD84, 0x7D7D, 0xBD85, 0x7D7E, 0xBD86, + 0x7D7F, 0xBD87, 0x7D80, 0xBD88, 0x7D81, 0xBD89, 0x7D82, 0xBD8A, + 0x7D83, 0xBD8B, 0x7D84, 0xBD8C, 0x7D85, 0xBD8D, 0x7D86, 0xBD8E, + 0x7D87, 0xBD8F, 0x7D88, 0xBD90, 0x7D89, 0xBD91, 0x7D8A, 0xBD92, + 0x7D8B, 0xBD93, 0x7D8C, 0xBD94, 0x7D8D, 0xBD95, 0x7D8E, 0xBD96, + 0x7D8F, 0xBD97, 0x7D90, 0xBD98, 0x7D91, 0xBD99, 0x7D92, 0xBD9A, + 0x7D93, 0xBD9B, 0x7D94, 0xBD9C, 0x7D95, 0xBD9D, 0x7D96, 0xBD9E, + 0x7D97, 0xBD9F, 0x7D98, 0xBDA0, 0x7D99, 0xBE40, 0x7D9A, 0xBE41, + 0x7D9B, 0xBE42, 0x7D9C, 0xBE43, 0x7D9D, 0xBE44, 0x7D9E, 0xBE45, + 0x7D9F, 0xBE46, 0x7DA0, 0xBE47, 0x7DA1, 0xBE48, 0x7DA2, 0xBE49, + 0x7DA3, 0xBE4A, 0x7DA4, 0xBE4B, 0x7DA5, 0xBE4C, 0x7DA6, 0xF4EB, + 0x7DA7, 0xBE4D, 0x7DA8, 0xBE4E, 0x7DA9, 0xBE4F, 0x7DAA, 0xBE50, + 0x7DAB, 0xBE51, 0x7DAC, 0xBE52, 0x7DAD, 0xBE53, 0x7DAE, 0xF4EC, + 0x7DAF, 0xBE54, 0x7DB0, 0xBE55, 0x7DB1, 0xBE56, 0x7DB2, 0xBE57, + 0x7DB3, 0xBE58, 0x7DB4, 0xBE59, 0x7DB5, 0xBE5A, 0x7DB6, 0xBE5B, + 0x7DB7, 0xBE5C, 0x7DB8, 0xBE5D, 0x7DB9, 0xBE5E, 0x7DBA, 0xBE5F, + 0x7DBB, 0xBE60, 0x7DBC, 0xBE61, 0x7DBD, 0xBE62, 0x7DBE, 0xBE63, + 0x7DBF, 0xBE64, 0x7DC0, 0xBE65, 0x7DC1, 0xBE66, 0x7DC2, 0xBE67, + 0x7DC3, 0xBE68, 0x7DC4, 0xBE69, 0x7DC5, 0xBE6A, 0x7DC6, 0xBE6B, + 0x7DC7, 0xBE6C, 0x7DC8, 0xBE6D, 0x7DC9, 0xBE6E, 0x7DCA, 0xBE6F, + 0x7DCB, 0xBE70, 0x7DCC, 0xBE71, 0x7DCD, 0xBE72, 0x7DCE, 0xBE73, + 0x7DCF, 0xBE74, 0x7DD0, 0xBE75, 0x7DD1, 0xBE76, 0x7DD2, 0xBE77, + 0x7DD3, 0xBE78, 0x7DD4, 0xBE79, 0x7DD5, 0xBE7A, 0x7DD6, 0xBE7B, + 0x7DD7, 0xBE7C, 0x7DD8, 0xBE7D, 0x7DD9, 0xBE7E, 0x7DDA, 0xBE80, + 0x7DDB, 0xBE81, 0x7DDC, 0xBE82, 0x7DDD, 0xBE83, 0x7DDE, 0xBE84, + 0x7DDF, 0xBE85, 0x7DE0, 0xBE86, 0x7DE1, 0xBE87, 0x7DE2, 0xBE88, + 0x7DE3, 0xBE89, 0x7DE4, 0xBE8A, 0x7DE5, 0xBE8B, 0x7DE6, 0xBE8C, + 0x7DE7, 0xBE8D, 0x7DE8, 0xBE8E, 0x7DE9, 0xBE8F, 0x7DEA, 0xBE90, + 0x7DEB, 0xBE91, 0x7DEC, 0xBE92, 0x7DED, 0xBE93, 0x7DEE, 0xBE94, + 0x7DEF, 0xBE95, 0x7DF0, 0xBE96, 0x7DF1, 0xBE97, 0x7DF2, 0xBE98, + 0x7DF3, 0xBE99, 0x7DF4, 0xBE9A, 0x7DF5, 0xBE9B, 0x7DF6, 0xBE9C, + 0x7DF7, 0xBE9D, 0x7DF8, 0xBE9E, 0x7DF9, 0xBE9F, 0x7DFA, 0xBEA0, + 0x7DFB, 0xBF40, 0x7DFC, 0xBF41, 0x7DFD, 0xBF42, 0x7DFE, 0xBF43, + 0x7DFF, 0xBF44, 0x7E00, 0xBF45, 0x7E01, 0xBF46, 0x7E02, 0xBF47, + 0x7E03, 0xBF48, 0x7E04, 0xBF49, 0x7E05, 0xBF4A, 0x7E06, 0xBF4B, + 0x7E07, 0xBF4C, 0x7E08, 0xBF4D, 0x7E09, 0xBF4E, 0x7E0A, 0xBF4F, + 0x7E0B, 0xBF50, 0x7E0C, 0xBF51, 0x7E0D, 0xBF52, 0x7E0E, 0xBF53, + 0x7E0F, 0xBF54, 0x7E10, 0xBF55, 0x7E11, 0xBF56, 0x7E12, 0xBF57, + 0x7E13, 0xBF58, 0x7E14, 0xBF59, 0x7E15, 0xBF5A, 0x7E16, 0xBF5B, + 0x7E17, 0xBF5C, 0x7E18, 0xBF5D, 0x7E19, 0xBF5E, 0x7E1A, 0xBF5F, + 0x7E1B, 0xBF60, 0x7E1C, 0xBF61, 0x7E1D, 0xBF62, 0x7E1E, 0xBF63, + 0x7E1F, 0xBF64, 0x7E20, 0xBF65, 0x7E21, 0xBF66, 0x7E22, 0xBF67, + 0x7E23, 0xBF68, 0x7E24, 0xBF69, 0x7E25, 0xBF6A, 0x7E26, 0xBF6B, + 0x7E27, 0xBF6C, 0x7E28, 0xBF6D, 0x7E29, 0xBF6E, 0x7E2A, 0xBF6F, + 0x7E2B, 0xBF70, 0x7E2C, 0xBF71, 0x7E2D, 0xBF72, 0x7E2E, 0xBF73, + 0x7E2F, 0xBF74, 0x7E30, 0xBF75, 0x7E31, 0xBF76, 0x7E32, 0xBF77, + 0x7E33, 0xBF78, 0x7E34, 0xBF79, 0x7E35, 0xBF7A, 0x7E36, 0xBF7B, + 0x7E37, 0xBF7C, 0x7E38, 0xBF7D, 0x7E39, 0xBF7E, 0x7E3A, 0xBF80, + 0x7E3B, 0xF7E3, 0x7E3C, 0xBF81, 0x7E3D, 0xBF82, 0x7E3E, 0xBF83, + 0x7E3F, 0xBF84, 0x7E40, 0xBF85, 0x7E41, 0xB7B1, 0x7E42, 0xBF86, + 0x7E43, 0xBF87, 0x7E44, 0xBF88, 0x7E45, 0xBF89, 0x7E46, 0xBF8A, + 0x7E47, 0xF4ED, 0x7E48, 0xBF8B, 0x7E49, 0xBF8C, 0x7E4A, 0xBF8D, + 0x7E4B, 0xBF8E, 0x7E4C, 0xBF8F, 0x7E4D, 0xBF90, 0x7E4E, 0xBF91, + 0x7E4F, 0xBF92, 0x7E50, 0xBF93, 0x7E51, 0xBF94, 0x7E52, 0xBF95, + 0x7E53, 0xBF96, 0x7E54, 0xBF97, 0x7E55, 0xBF98, 0x7E56, 0xBF99, + 0x7E57, 0xBF9A, 0x7E58, 0xBF9B, 0x7E59, 0xBF9C, 0x7E5A, 0xBF9D, + 0x7E5B, 0xBF9E, 0x7E5C, 0xBF9F, 0x7E5D, 0xBFA0, 0x7E5E, 0xC040, + 0x7E5F, 0xC041, 0x7E60, 0xC042, 0x7E61, 0xC043, 0x7E62, 0xC044, + 0x7E63, 0xC045, 0x7E64, 0xC046, 0x7E65, 0xC047, 0x7E66, 0xC048, + 0x7E67, 0xC049, 0x7E68, 0xC04A, 0x7E69, 0xC04B, 0x7E6A, 0xC04C, + 0x7E6B, 0xC04D, 0x7E6C, 0xC04E, 0x7E6D, 0xC04F, 0x7E6E, 0xC050, + 0x7E6F, 0xC051, 0x7E70, 0xC052, 0x7E71, 0xC053, 0x7E72, 0xC054, + 0x7E73, 0xC055, 0x7E74, 0xC056, 0x7E75, 0xC057, 0x7E76, 0xC058, + 0x7E77, 0xC059, 0x7E78, 0xC05A, 0x7E79, 0xC05B, 0x7E7A, 0xC05C, + 0x7E7B, 0xC05D, 0x7E7C, 0xC05E, 0x7E7D, 0xC05F, 0x7E7E, 0xC060, + 0x7E7F, 0xC061, 0x7E80, 0xC062, 0x7E81, 0xC063, 0x7E82, 0xD7EB, + 0x7E83, 0xC064, 0x7E84, 0xC065, 0x7E85, 0xC066, 0x7E86, 0xC067, + 0x7E87, 0xC068, 0x7E88, 0xC069, 0x7E89, 0xC06A, 0x7E8A, 0xC06B, + 0x7E8B, 0xC06C, 0x7E8C, 0xC06D, 0x7E8D, 0xC06E, 0x7E8E, 0xC06F, + 0x7E8F, 0xC070, 0x7E90, 0xC071, 0x7E91, 0xC072, 0x7E92, 0xC073, + 0x7E93, 0xC074, 0x7E94, 0xC075, 0x7E95, 0xC076, 0x7E96, 0xC077, + 0x7E97, 0xC078, 0x7E98, 0xC079, 0x7E99, 0xC07A, 0x7E9A, 0xC07B, + 0x7E9B, 0xF4EE, 0x7E9C, 0xC07C, 0x7E9D, 0xC07D, 0x7E9E, 0xC07E, + 0x7E9F, 0xE6F9, 0x7EA0, 0xBEC0, 0x7EA1, 0xE6FA, 0x7EA2, 0xBAEC, + 0x7EA3, 0xE6FB, 0x7EA4, 0xCFCB, 0x7EA5, 0xE6FC, 0x7EA6, 0xD4BC, + 0x7EA7, 0xBCB6, 0x7EA8, 0xE6FD, 0x7EA9, 0xE6FE, 0x7EAA, 0xBCCD, + 0x7EAB, 0xC8D2, 0x7EAC, 0xCEB3, 0x7EAD, 0xE7A1, 0x7EAE, 0xC080, + 0x7EAF, 0xB4BF, 0x7EB0, 0xE7A2, 0x7EB1, 0xC9B4, 0x7EB2, 0xB8D9, + 0x7EB3, 0xC4C9, 0x7EB4, 0xC081, 0x7EB5, 0xD7DD, 0x7EB6, 0xC2DA, + 0x7EB7, 0xB7D7, 0x7EB8, 0xD6BD, 0x7EB9, 0xCEC6, 0x7EBA, 0xB7C4, + 0x7EBB, 0xC082, 0x7EBC, 0xC083, 0x7EBD, 0xC5A6, 0x7EBE, 0xE7A3, + 0x7EBF, 0xCFDF, 0x7EC0, 0xE7A4, 0x7EC1, 0xE7A5, 0x7EC2, 0xE7A6, + 0x7EC3, 0xC1B7, 0x7EC4, 0xD7E9, 0x7EC5, 0xC9F0, 0x7EC6, 0xCFB8, + 0x7EC7, 0xD6AF, 0x7EC8, 0xD6D5, 0x7EC9, 0xE7A7, 0x7ECA, 0xB0ED, + 0x7ECB, 0xE7A8, 0x7ECC, 0xE7A9, 0x7ECD, 0xC9DC, 0x7ECE, 0xD2EF, + 0x7ECF, 0xBEAD, 0x7ED0, 0xE7AA, 0x7ED1, 0xB0F3, 0x7ED2, 0xC8DE, + 0x7ED3, 0xBDE1, 0x7ED4, 0xE7AB, 0x7ED5, 0xC8C6, 0x7ED6, 0xC084, + 0x7ED7, 0xE7AC, 0x7ED8, 0xBBE6, 0x7ED9, 0xB8F8, 0x7EDA, 0xD1A4, + 0x7EDB, 0xE7AD, 0x7EDC, 0xC2E7, 0x7EDD, 0xBEF8, 0x7EDE, 0xBDCA, + 0x7EDF, 0xCDB3, 0x7EE0, 0xE7AE, 0x7EE1, 0xE7AF, 0x7EE2, 0xBEEE, + 0x7EE3, 0xD0E5, 0x7EE4, 0xC085, 0x7EE5, 0xCBE7, 0x7EE6, 0xCCD0, + 0x7EE7, 0xBCCC, 0x7EE8, 0xE7B0, 0x7EE9, 0xBCA8, 0x7EEA, 0xD0F7, + 0x7EEB, 0xE7B1, 0x7EEC, 0xC086, 0x7EED, 0xD0F8, 0x7EEE, 0xE7B2, + 0x7EEF, 0xE7B3, 0x7EF0, 0xB4C2, 0x7EF1, 0xE7B4, 0x7EF2, 0xE7B5, + 0x7EF3, 0xC9FE, 0x7EF4, 0xCEAC, 0x7EF5, 0xC3E0, 0x7EF6, 0xE7B7, + 0x7EF7, 0xB1C1, 0x7EF8, 0xB3F1, 0x7EF9, 0xC087, 0x7EFA, 0xE7B8, + 0x7EFB, 0xE7B9, 0x7EFC, 0xD7DB, 0x7EFD, 0xD5C0, 0x7EFE, 0xE7BA, + 0x7EFF, 0xC2CC, 0x7F00, 0xD7BA, 0x7F01, 0xE7BB, 0x7F02, 0xE7BC, + 0x7F03, 0xE7BD, 0x7F04, 0xBCEA, 0x7F05, 0xC3E5, 0x7F06, 0xC0C2, + 0x7F07, 0xE7BE, 0x7F08, 0xE7BF, 0x7F09, 0xBCA9, 0x7F0A, 0xC088, + 0x7F0B, 0xE7C0, 0x7F0C, 0xE7C1, 0x7F0D, 0xE7B6, 0x7F0E, 0xB6D0, + 0x7F0F, 0xE7C2, 0x7F10, 0xC089, 0x7F11, 0xE7C3, 0x7F12, 0xE7C4, + 0x7F13, 0xBBBA, 0x7F14, 0xB5DE, 0x7F15, 0xC2C6, 0x7F16, 0xB1E0, + 0x7F17, 0xE7C5, 0x7F18, 0xD4B5, 0x7F19, 0xE7C6, 0x7F1A, 0xB8BF, + 0x7F1B, 0xE7C8, 0x7F1C, 0xE7C7, 0x7F1D, 0xB7EC, 0x7F1E, 0xC08A, + 0x7F1F, 0xE7C9, 0x7F20, 0xB2F8, 0x7F21, 0xE7CA, 0x7F22, 0xE7CB, + 0x7F23, 0xE7CC, 0x7F24, 0xE7CD, 0x7F25, 0xE7CE, 0x7F26, 0xE7CF, + 0x7F27, 0xE7D0, 0x7F28, 0xD3A7, 0x7F29, 0xCBF5, 0x7F2A, 0xE7D1, + 0x7F2B, 0xE7D2, 0x7F2C, 0xE7D3, 0x7F2D, 0xE7D4, 0x7F2E, 0xC9C9, + 0x7F2F, 0xE7D5, 0x7F30, 0xE7D6, 0x7F31, 0xE7D7, 0x7F32, 0xE7D8, + 0x7F33, 0xE7D9, 0x7F34, 0xBDC9, 0x7F35, 0xE7DA, 0x7F36, 0xF3BE, + 0x7F37, 0xC08B, 0x7F38, 0xB8D7, 0x7F39, 0xC08C, 0x7F3A, 0xC8B1, + 0x7F3B, 0xC08D, 0x7F3C, 0xC08E, 0x7F3D, 0xC08F, 0x7F3E, 0xC090, + 0x7F3F, 0xC091, 0x7F40, 0xC092, 0x7F41, 0xC093, 0x7F42, 0xF3BF, + 0x7F43, 0xC094, 0x7F44, 0xF3C0, 0x7F45, 0xF3C1, 0x7F46, 0xC095, + 0x7F47, 0xC096, 0x7F48, 0xC097, 0x7F49, 0xC098, 0x7F4A, 0xC099, + 0x7F4B, 0xC09A, 0x7F4C, 0xC09B, 0x7F4D, 0xC09C, 0x7F4E, 0xC09D, + 0x7F4F, 0xC09E, 0x7F50, 0xB9DE, 0x7F51, 0xCDF8, 0x7F52, 0xC09F, + 0x7F53, 0xC0A0, 0x7F54, 0xD8E8, 0x7F55, 0xBAB1, 0x7F56, 0xC140, + 0x7F57, 0xC2DE, 0x7F58, 0xEEB7, 0x7F59, 0xC141, 0x7F5A, 0xB7A3, + 0x7F5B, 0xC142, 0x7F5C, 0xC143, 0x7F5D, 0xC144, 0x7F5E, 0xC145, + 0x7F5F, 0xEEB9, 0x7F60, 0xC146, 0x7F61, 0xEEB8, 0x7F62, 0xB0D5, + 0x7F63, 0xC147, 0x7F64, 0xC148, 0x7F65, 0xC149, 0x7F66, 0xC14A, + 0x7F67, 0xC14B, 0x7F68, 0xEEBB, 0x7F69, 0xD5D6, 0x7F6A, 0xD7EF, + 0x7F6B, 0xC14C, 0x7F6C, 0xC14D, 0x7F6D, 0xC14E, 0x7F6E, 0xD6C3, + 0x7F6F, 0xC14F, 0x7F70, 0xC150, 0x7F71, 0xEEBD, 0x7F72, 0xCAF0, + 0x7F73, 0xC151, 0x7F74, 0xEEBC, 0x7F75, 0xC152, 0x7F76, 0xC153, + 0x7F77, 0xC154, 0x7F78, 0xC155, 0x7F79, 0xEEBE, 0x7F7A, 0xC156, + 0x7F7B, 0xC157, 0x7F7C, 0xC158, 0x7F7D, 0xC159, 0x7F7E, 0xEEC0, + 0x7F7F, 0xC15A, 0x7F80, 0xC15B, 0x7F81, 0xEEBF, 0x7F82, 0xC15C, + 0x7F83, 0xC15D, 0x7F84, 0xC15E, 0x7F85, 0xC15F, 0x7F86, 0xC160, + 0x7F87, 0xC161, 0x7F88, 0xC162, 0x7F89, 0xC163, 0x7F8A, 0xD1F2, + 0x7F8B, 0xC164, 0x7F8C, 0xC7BC, 0x7F8D, 0xC165, 0x7F8E, 0xC3C0, + 0x7F8F, 0xC166, 0x7F90, 0xC167, 0x7F91, 0xC168, 0x7F92, 0xC169, + 0x7F93, 0xC16A, 0x7F94, 0xB8E1, 0x7F95, 0xC16B, 0x7F96, 0xC16C, + 0x7F97, 0xC16D, 0x7F98, 0xC16E, 0x7F99, 0xC16F, 0x7F9A, 0xC1E7, + 0x7F9B, 0xC170, 0x7F9C, 0xC171, 0x7F9D, 0xF4C6, 0x7F9E, 0xD0DF, + 0x7F9F, 0xF4C7, 0x7FA0, 0xC172, 0x7FA1, 0xCFDB, 0x7FA2, 0xC173, + 0x7FA3, 0xC174, 0x7FA4, 0xC8BA, 0x7FA5, 0xC175, 0x7FA6, 0xC176, + 0x7FA7, 0xF4C8, 0x7FA8, 0xC177, 0x7FA9, 0xC178, 0x7FAA, 0xC179, + 0x7FAB, 0xC17A, 0x7FAC, 0xC17B, 0x7FAD, 0xC17C, 0x7FAE, 0xC17D, + 0x7FAF, 0xF4C9, 0x7FB0, 0xF4CA, 0x7FB1, 0xC17E, 0x7FB2, 0xF4CB, + 0x7FB3, 0xC180, 0x7FB4, 0xC181, 0x7FB5, 0xC182, 0x7FB6, 0xC183, + 0x7FB7, 0xC184, 0x7FB8, 0xD9FA, 0x7FB9, 0xB8FE, 0x7FBA, 0xC185, + 0x7FBB, 0xC186, 0x7FBC, 0xE5F1, 0x7FBD, 0xD3F0, 0x7FBE, 0xC187, + 0x7FBF, 0xF4E0, 0x7FC0, 0xC188, 0x7FC1, 0xCECC, 0x7FC2, 0xC189, + 0x7FC3, 0xC18A, 0x7FC4, 0xC18B, 0x7FC5, 0xB3E1, 0x7FC6, 0xC18C, + 0x7FC7, 0xC18D, 0x7FC8, 0xC18E, 0x7FC9, 0xC18F, 0x7FCA, 0xF1B4, + 0x7FCB, 0xC190, 0x7FCC, 0xD2EE, 0x7FCD, 0xC191, 0x7FCE, 0xF4E1, + 0x7FCF, 0xC192, 0x7FD0, 0xC193, 0x7FD1, 0xC194, 0x7FD2, 0xC195, + 0x7FD3, 0xC196, 0x7FD4, 0xCFE8, 0x7FD5, 0xF4E2, 0x7FD6, 0xC197, + 0x7FD7, 0xC198, 0x7FD8, 0xC7CC, 0x7FD9, 0xC199, 0x7FDA, 0xC19A, + 0x7FDB, 0xC19B, 0x7FDC, 0xC19C, 0x7FDD, 0xC19D, 0x7FDE, 0xC19E, + 0x7FDF, 0xB5D4, 0x7FE0, 0xB4E4, 0x7FE1, 0xF4E4, 0x7FE2, 0xC19F, + 0x7FE3, 0xC1A0, 0x7FE4, 0xC240, 0x7FE5, 0xF4E3, 0x7FE6, 0xF4E5, + 0x7FE7, 0xC241, 0x7FE8, 0xC242, 0x7FE9, 0xF4E6, 0x7FEA, 0xC243, + 0x7FEB, 0xC244, 0x7FEC, 0xC245, 0x7FED, 0xC246, 0x7FEE, 0xF4E7, + 0x7FEF, 0xC247, 0x7FF0, 0xBAB2, 0x7FF1, 0xB0BF, 0x7FF2, 0xC248, + 0x7FF3, 0xF4E8, 0x7FF4, 0xC249, 0x7FF5, 0xC24A, 0x7FF6, 0xC24B, + 0x7FF7, 0xC24C, 0x7FF8, 0xC24D, 0x7FF9, 0xC24E, 0x7FFA, 0xC24F, + 0x7FFB, 0xB7AD, 0x7FFC, 0xD2ED, 0x7FFD, 0xC250, 0x7FFE, 0xC251, + 0x7FFF, 0xC252, 0x8000, 0xD2AB, 0x8001, 0xC0CF, 0x8002, 0xC253, + 0x8003, 0xBFBC, 0x8004, 0xEBA3, 0x8005, 0xD5DF, 0x8006, 0xEAC8, + 0x8007, 0xC254, 0x8008, 0xC255, 0x8009, 0xC256, 0x800A, 0xC257, + 0x800B, 0xF1F3, 0x800C, 0xB6F8, 0x800D, 0xCBA3, 0x800E, 0xC258, + 0x800F, 0xC259, 0x8010, 0xC4CD, 0x8011, 0xC25A, 0x8012, 0xF1E7, + 0x8013, 0xC25B, 0x8014, 0xF1E8, 0x8015, 0xB8FB, 0x8016, 0xF1E9, + 0x8017, 0xBAC4, 0x8018, 0xD4C5, 0x8019, 0xB0D2, 0x801A, 0xC25C, + 0x801B, 0xC25D, 0x801C, 0xF1EA, 0x801D, 0xC25E, 0x801E, 0xC25F, + 0x801F, 0xC260, 0x8020, 0xF1EB, 0x8021, 0xC261, 0x8022, 0xF1EC, + 0x8023, 0xC262, 0x8024, 0xC263, 0x8025, 0xF1ED, 0x8026, 0xF1EE, + 0x8027, 0xF1EF, 0x8028, 0xF1F1, 0x8029, 0xF1F0, 0x802A, 0xC5D5, + 0x802B, 0xC264, 0x802C, 0xC265, 0x802D, 0xC266, 0x802E, 0xC267, + 0x802F, 0xC268, 0x8030, 0xC269, 0x8031, 0xF1F2, 0x8032, 0xC26A, + 0x8033, 0xB6FA, 0x8034, 0xC26B, 0x8035, 0xF1F4, 0x8036, 0xD2AE, + 0x8037, 0xDEC7, 0x8038, 0xCBCA, 0x8039, 0xC26C, 0x803A, 0xC26D, + 0x803B, 0xB3DC, 0x803C, 0xC26E, 0x803D, 0xB5A2, 0x803E, 0xC26F, + 0x803F, 0xB9A2, 0x8040, 0xC270, 0x8041, 0xC271, 0x8042, 0xC4F4, + 0x8043, 0xF1F5, 0x8044, 0xC272, 0x8045, 0xC273, 0x8046, 0xF1F6, + 0x8047, 0xC274, 0x8048, 0xC275, 0x8049, 0xC276, 0x804A, 0xC1C4, + 0x804B, 0xC1FB, 0x804C, 0xD6B0, 0x804D, 0xF1F7, 0x804E, 0xC277, + 0x804F, 0xC278, 0x8050, 0xC279, 0x8051, 0xC27A, 0x8052, 0xF1F8, + 0x8053, 0xC27B, 0x8054, 0xC1AA, 0x8055, 0xC27C, 0x8056, 0xC27D, + 0x8057, 0xC27E, 0x8058, 0xC6B8, 0x8059, 0xC280, 0x805A, 0xBEDB, + 0x805B, 0xC281, 0x805C, 0xC282, 0x805D, 0xC283, 0x805E, 0xC284, + 0x805F, 0xC285, 0x8060, 0xC286, 0x8061, 0xC287, 0x8062, 0xC288, + 0x8063, 0xC289, 0x8064, 0xC28A, 0x8065, 0xC28B, 0x8066, 0xC28C, + 0x8067, 0xC28D, 0x8068, 0xC28E, 0x8069, 0xF1F9, 0x806A, 0xB4CF, + 0x806B, 0xC28F, 0x806C, 0xC290, 0x806D, 0xC291, 0x806E, 0xC292, + 0x806F, 0xC293, 0x8070, 0xC294, 0x8071, 0xF1FA, 0x8072, 0xC295, + 0x8073, 0xC296, 0x8074, 0xC297, 0x8075, 0xC298, 0x8076, 0xC299, + 0x8077, 0xC29A, 0x8078, 0xC29B, 0x8079, 0xC29C, 0x807A, 0xC29D, + 0x807B, 0xC29E, 0x807C, 0xC29F, 0x807D, 0xC2A0, 0x807E, 0xC340, + 0x807F, 0xEDB2, 0x8080, 0xEDB1, 0x8081, 0xC341, 0x8082, 0xC342, + 0x8083, 0xCBE0, 0x8084, 0xD2DE, 0x8085, 0xC343, 0x8086, 0xCBC1, + 0x8087, 0xD5D8, 0x8088, 0xC344, 0x8089, 0xC8E2, 0x808A, 0xC345, + 0x808B, 0xC0DF, 0x808C, 0xBCA1, 0x808D, 0xC346, 0x808E, 0xC347, + 0x808F, 0xC348, 0x8090, 0xC349, 0x8091, 0xC34A, 0x8092, 0xC34B, + 0x8093, 0xEBC1, 0x8094, 0xC34C, 0x8095, 0xC34D, 0x8096, 0xD0A4, + 0x8097, 0xC34E, 0x8098, 0xD6E2, 0x8099, 0xC34F, 0x809A, 0xB6C7, + 0x809B, 0xB8D8, 0x809C, 0xEBC0, 0x809D, 0xB8CE, 0x809E, 0xC350, + 0x809F, 0xEBBF, 0x80A0, 0xB3A6, 0x80A1, 0xB9C9, 0x80A2, 0xD6AB, + 0x80A3, 0xC351, 0x80A4, 0xB7F4, 0x80A5, 0xB7CA, 0x80A6, 0xC352, + 0x80A7, 0xC353, 0x80A8, 0xC354, 0x80A9, 0xBCE7, 0x80AA, 0xB7BE, + 0x80AB, 0xEBC6, 0x80AC, 0xC355, 0x80AD, 0xEBC7, 0x80AE, 0xB0B9, + 0x80AF, 0xBFCF, 0x80B0, 0xC356, 0x80B1, 0xEBC5, 0x80B2, 0xD3FD, + 0x80B3, 0xC357, 0x80B4, 0xEBC8, 0x80B5, 0xC358, 0x80B6, 0xC359, + 0x80B7, 0xEBC9, 0x80B8, 0xC35A, 0x80B9, 0xC35B, 0x80BA, 0xB7CE, + 0x80BB, 0xC35C, 0x80BC, 0xEBC2, 0x80BD, 0xEBC4, 0x80BE, 0xC9F6, + 0x80BF, 0xD6D7, 0x80C0, 0xD5CD, 0x80C1, 0xD0B2, 0x80C2, 0xEBCF, + 0x80C3, 0xCEB8, 0x80C4, 0xEBD0, 0x80C5, 0xC35D, 0x80C6, 0xB5A8, + 0x80C7, 0xC35E, 0x80C8, 0xC35F, 0x80C9, 0xC360, 0x80CA, 0xC361, + 0x80CB, 0xC362, 0x80CC, 0xB1B3, 0x80CD, 0xEBD2, 0x80CE, 0xCCA5, + 0x80CF, 0xC363, 0x80D0, 0xC364, 0x80D1, 0xC365, 0x80D2, 0xC366, + 0x80D3, 0xC367, 0x80D4, 0xC368, 0x80D5, 0xC369, 0x80D6, 0xC5D6, + 0x80D7, 0xEBD3, 0x80D8, 0xC36A, 0x80D9, 0xEBD1, 0x80DA, 0xC5DF, + 0x80DB, 0xEBCE, 0x80DC, 0xCAA4, 0x80DD, 0xEBD5, 0x80DE, 0xB0FB, + 0x80DF, 0xC36B, 0x80E0, 0xC36C, 0x80E1, 0xBAFA, 0x80E2, 0xC36D, + 0x80E3, 0xC36E, 0x80E4, 0xD8B7, 0x80E5, 0xF1E3, 0x80E6, 0xC36F, + 0x80E7, 0xEBCA, 0x80E8, 0xEBCB, 0x80E9, 0xEBCC, 0x80EA, 0xEBCD, + 0x80EB, 0xEBD6, 0x80EC, 0xE6C0, 0x80ED, 0xEBD9, 0x80EE, 0xC370, + 0x80EF, 0xBFE8, 0x80F0, 0xD2C8, 0x80F1, 0xEBD7, 0x80F2, 0xEBDC, + 0x80F3, 0xB8EC, 0x80F4, 0xEBD8, 0x80F5, 0xC371, 0x80F6, 0xBDBA, + 0x80F7, 0xC372, 0x80F8, 0xD0D8, 0x80F9, 0xC373, 0x80FA, 0xB0B7, + 0x80FB, 0xC374, 0x80FC, 0xEBDD, 0x80FD, 0xC4DC, 0x80FE, 0xC375, + 0x80FF, 0xC376, 0x8100, 0xC377, 0x8101, 0xC378, 0x8102, 0xD6AC, + 0x8103, 0xC379, 0x8104, 0xC37A, 0x8105, 0xC37B, 0x8106, 0xB4E0, + 0x8107, 0xC37C, 0x8108, 0xC37D, 0x8109, 0xC2F6, 0x810A, 0xBCB9, + 0x810B, 0xC37E, 0x810C, 0xC380, 0x810D, 0xEBDA, 0x810E, 0xEBDB, + 0x810F, 0xD4E0, 0x8110, 0xC6EA, 0x8111, 0xC4D4, 0x8112, 0xEBDF, + 0x8113, 0xC5A7, 0x8114, 0xD9F5, 0x8115, 0xC381, 0x8116, 0xB2B1, + 0x8117, 0xC382, 0x8118, 0xEBE4, 0x8119, 0xC383, 0x811A, 0xBDC5, + 0x811B, 0xC384, 0x811C, 0xC385, 0x811D, 0xC386, 0x811E, 0xEBE2, + 0x811F, 0xC387, 0x8120, 0xC388, 0x8121, 0xC389, 0x8122, 0xC38A, + 0x8123, 0xC38B, 0x8124, 0xC38C, 0x8125, 0xC38D, 0x8126, 0xC38E, + 0x8127, 0xC38F, 0x8128, 0xC390, 0x8129, 0xC391, 0x812A, 0xC392, + 0x812B, 0xC393, 0x812C, 0xEBE3, 0x812D, 0xC394, 0x812E, 0xC395, + 0x812F, 0xB8AC, 0x8130, 0xC396, 0x8131, 0xCDD1, 0x8132, 0xEBE5, + 0x8133, 0xC397, 0x8134, 0xC398, 0x8135, 0xC399, 0x8136, 0xEBE1, + 0x8137, 0xC39A, 0x8138, 0xC1B3, 0x8139, 0xC39B, 0x813A, 0xC39C, + 0x813B, 0xC39D, 0x813C, 0xC39E, 0x813D, 0xC39F, 0x813E, 0xC6A2, + 0x813F, 0xC3A0, 0x8140, 0xC440, 0x8141, 0xC441, 0x8142, 0xC442, + 0x8143, 0xC443, 0x8144, 0xC444, 0x8145, 0xC445, 0x8146, 0xCCF3, + 0x8147, 0xC446, 0x8148, 0xEBE6, 0x8149, 0xC447, 0x814A, 0xC0B0, + 0x814B, 0xD2B8, 0x814C, 0xEBE7, 0x814D, 0xC448, 0x814E, 0xC449, + 0x814F, 0xC44A, 0x8150, 0xB8AF, 0x8151, 0xB8AD, 0x8152, 0xC44B, + 0x8153, 0xEBE8, 0x8154, 0xC7BB, 0x8155, 0xCDF3, 0x8156, 0xC44C, + 0x8157, 0xC44D, 0x8158, 0xC44E, 0x8159, 0xEBEA, 0x815A, 0xEBEB, + 0x815B, 0xC44F, 0x815C, 0xC450, 0x815D, 0xC451, 0x815E, 0xC452, + 0x815F, 0xC453, 0x8160, 0xEBED, 0x8161, 0xC454, 0x8162, 0xC455, + 0x8163, 0xC456, 0x8164, 0xC457, 0x8165, 0xD0C8, 0x8166, 0xC458, + 0x8167, 0xEBF2, 0x8168, 0xC459, 0x8169, 0xEBEE, 0x816A, 0xC45A, + 0x816B, 0xC45B, 0x816C, 0xC45C, 0x816D, 0xEBF1, 0x816E, 0xC8F9, + 0x816F, 0xC45D, 0x8170, 0xD1FC, 0x8171, 0xEBEC, 0x8172, 0xC45E, + 0x8173, 0xC45F, 0x8174, 0xEBE9, 0x8175, 0xC460, 0x8176, 0xC461, + 0x8177, 0xC462, 0x8178, 0xC463, 0x8179, 0xB8B9, 0x817A, 0xCFD9, + 0x817B, 0xC4E5, 0x817C, 0xEBEF, 0x817D, 0xEBF0, 0x817E, 0xCCDA, + 0x817F, 0xCDC8, 0x8180, 0xB0F2, 0x8181, 0xC464, 0x8182, 0xEBF6, + 0x8183, 0xC465, 0x8184, 0xC466, 0x8185, 0xC467, 0x8186, 0xC468, + 0x8187, 0xC469, 0x8188, 0xEBF5, 0x8189, 0xC46A, 0x818A, 0xB2B2, + 0x818B, 0xC46B, 0x818C, 0xC46C, 0x818D, 0xC46D, 0x818E, 0xC46E, + 0x818F, 0xB8E0, 0x8190, 0xC46F, 0x8191, 0xEBF7, 0x8192, 0xC470, + 0x8193, 0xC471, 0x8194, 0xC472, 0x8195, 0xC473, 0x8196, 0xC474, + 0x8197, 0xC475, 0x8198, 0xB1EC, 0x8199, 0xC476, 0x819A, 0xC477, + 0x819B, 0xCCC5, 0x819C, 0xC4A4, 0x819D, 0xCFA5, 0x819E, 0xC478, + 0x819F, 0xC479, 0x81A0, 0xC47A, 0x81A1, 0xC47B, 0x81A2, 0xC47C, + 0x81A3, 0xEBF9, 0x81A4, 0xC47D, 0x81A5, 0xC47E, 0x81A6, 0xECA2, + 0x81A7, 0xC480, 0x81A8, 0xC5F2, 0x81A9, 0xC481, 0x81AA, 0xEBFA, + 0x81AB, 0xC482, 0x81AC, 0xC483, 0x81AD, 0xC484, 0x81AE, 0xC485, + 0x81AF, 0xC486, 0x81B0, 0xC487, 0x81B1, 0xC488, 0x81B2, 0xC489, + 0x81B3, 0xC9C5, 0x81B4, 0xC48A, 0x81B5, 0xC48B, 0x81B6, 0xC48C, + 0x81B7, 0xC48D, 0x81B8, 0xC48E, 0x81B9, 0xC48F, 0x81BA, 0xE2DF, + 0x81BB, 0xEBFE, 0x81BC, 0xC490, 0x81BD, 0xC491, 0x81BE, 0xC492, + 0x81BF, 0xC493, 0x81C0, 0xCDCE, 0x81C1, 0xECA1, 0x81C2, 0xB1DB, + 0x81C3, 0xD3B7, 0x81C4, 0xC494, 0x81C5, 0xC495, 0x81C6, 0xD2DC, + 0x81C7, 0xC496, 0x81C8, 0xC497, 0x81C9, 0xC498, 0x81CA, 0xEBFD, + 0x81CB, 0xC499, 0x81CC, 0xEBFB, 0x81CD, 0xC49A, 0x81CE, 0xC49B, + 0x81CF, 0xC49C, 0x81D0, 0xC49D, 0x81D1, 0xC49E, 0x81D2, 0xC49F, + 0x81D3, 0xC4A0, 0x81D4, 0xC540, 0x81D5, 0xC541, 0x81D6, 0xC542, + 0x81D7, 0xC543, 0x81D8, 0xC544, 0x81D9, 0xC545, 0x81DA, 0xC546, + 0x81DB, 0xC547, 0x81DC, 0xC548, 0x81DD, 0xC549, 0x81DE, 0xC54A, + 0x81DF, 0xC54B, 0x81E0, 0xC54C, 0x81E1, 0xC54D, 0x81E2, 0xC54E, + 0x81E3, 0xB3BC, 0x81E4, 0xC54F, 0x81E5, 0xC550, 0x81E6, 0xC551, + 0x81E7, 0xEAB0, 0x81E8, 0xC552, 0x81E9, 0xC553, 0x81EA, 0xD7D4, + 0x81EB, 0xC554, 0x81EC, 0xF4AB, 0x81ED, 0xB3F4, 0x81EE, 0xC555, + 0x81EF, 0xC556, 0x81F0, 0xC557, 0x81F1, 0xC558, 0x81F2, 0xC559, + 0x81F3, 0xD6C1, 0x81F4, 0xD6C2, 0x81F5, 0xC55A, 0x81F6, 0xC55B, + 0x81F7, 0xC55C, 0x81F8, 0xC55D, 0x81F9, 0xC55E, 0x81FA, 0xC55F, + 0x81FB, 0xD5E9, 0x81FC, 0xBECA, 0x81FD, 0xC560, 0x81FE, 0xF4A7, + 0x81FF, 0xC561, 0x8200, 0xD2A8, 0x8201, 0xF4A8, 0x8202, 0xF4A9, + 0x8203, 0xC562, 0x8204, 0xF4AA, 0x8205, 0xBECB, 0x8206, 0xD3DF, + 0x8207, 0xC563, 0x8208, 0xC564, 0x8209, 0xC565, 0x820A, 0xC566, + 0x820B, 0xC567, 0x820C, 0xC9E0, 0x820D, 0xC9E1, 0x820E, 0xC568, + 0x820F, 0xC569, 0x8210, 0xF3C2, 0x8211, 0xC56A, 0x8212, 0xCAE6, + 0x8213, 0xC56B, 0x8214, 0xCCF2, 0x8215, 0xC56C, 0x8216, 0xC56D, + 0x8217, 0xC56E, 0x8218, 0xC56F, 0x8219, 0xC570, 0x821A, 0xC571, + 0x821B, 0xE2B6, 0x821C, 0xCBB4, 0x821D, 0xC572, 0x821E, 0xCEE8, + 0x821F, 0xD6DB, 0x8220, 0xC573, 0x8221, 0xF4AD, 0x8222, 0xF4AE, + 0x8223, 0xF4AF, 0x8224, 0xC574, 0x8225, 0xC575, 0x8226, 0xC576, + 0x8227, 0xC577, 0x8228, 0xF4B2, 0x8229, 0xC578, 0x822A, 0xBABD, + 0x822B, 0xF4B3, 0x822C, 0xB0E3, 0x822D, 0xF4B0, 0x822E, 0xC579, + 0x822F, 0xF4B1, 0x8230, 0xBDA2, 0x8231, 0xB2D5, 0x8232, 0xC57A, + 0x8233, 0xF4B6, 0x8234, 0xF4B7, 0x8235, 0xB6E6, 0x8236, 0xB2B0, + 0x8237, 0xCFCF, 0x8238, 0xF4B4, 0x8239, 0xB4AC, 0x823A, 0xC57B, + 0x823B, 0xF4B5, 0x823C, 0xC57C, 0x823D, 0xC57D, 0x823E, 0xF4B8, + 0x823F, 0xC57E, 0x8240, 0xC580, 0x8241, 0xC581, 0x8242, 0xC582, + 0x8243, 0xC583, 0x8244, 0xF4B9, 0x8245, 0xC584, 0x8246, 0xC585, + 0x8247, 0xCDA7, 0x8248, 0xC586, 0x8249, 0xF4BA, 0x824A, 0xC587, + 0x824B, 0xF4BB, 0x824C, 0xC588, 0x824D, 0xC589, 0x824E, 0xC58A, + 0x824F, 0xF4BC, 0x8250, 0xC58B, 0x8251, 0xC58C, 0x8252, 0xC58D, + 0x8253, 0xC58E, 0x8254, 0xC58F, 0x8255, 0xC590, 0x8256, 0xC591, + 0x8257, 0xC592, 0x8258, 0xCBD2, 0x8259, 0xC593, 0x825A, 0xF4BD, + 0x825B, 0xC594, 0x825C, 0xC595, 0x825D, 0xC596, 0x825E, 0xC597, + 0x825F, 0xF4BE, 0x8260, 0xC598, 0x8261, 0xC599, 0x8262, 0xC59A, + 0x8263, 0xC59B, 0x8264, 0xC59C, 0x8265, 0xC59D, 0x8266, 0xC59E, + 0x8267, 0xC59F, 0x8268, 0xF4BF, 0x8269, 0xC5A0, 0x826A, 0xC640, + 0x826B, 0xC641, 0x826C, 0xC642, 0x826D, 0xC643, 0x826E, 0xF4DE, + 0x826F, 0xC1BC, 0x8270, 0xBCE8, 0x8271, 0xC644, 0x8272, 0xC9AB, + 0x8273, 0xD1DE, 0x8274, 0xE5F5, 0x8275, 0xC645, 0x8276, 0xC646, + 0x8277, 0xC647, 0x8278, 0xC648, 0x8279, 0xDCB3, 0x827A, 0xD2D5, + 0x827B, 0xC649, 0x827C, 0xC64A, 0x827D, 0xDCB4, 0x827E, 0xB0AC, + 0x827F, 0xDCB5, 0x8280, 0xC64B, 0x8281, 0xC64C, 0x8282, 0xBDDA, + 0x8283, 0xC64D, 0x8284, 0xDCB9, 0x8285, 0xC64E, 0x8286, 0xC64F, + 0x8287, 0xC650, 0x8288, 0xD8C2, 0x8289, 0xC651, 0x828A, 0xDCB7, + 0x828B, 0xD3F3, 0x828C, 0xC652, 0x828D, 0xC9D6, 0x828E, 0xDCBA, + 0x828F, 0xDCB6, 0x8290, 0xC653, 0x8291, 0xDCBB, 0x8292, 0xC3A2, + 0x8293, 0xC654, 0x8294, 0xC655, 0x8295, 0xC656, 0x8296, 0xC657, + 0x8297, 0xDCBC, 0x8298, 0xDCC5, 0x8299, 0xDCBD, 0x829A, 0xC658, + 0x829B, 0xC659, 0x829C, 0xCEDF, 0x829D, 0xD6A5, 0x829E, 0xC65A, + 0x829F, 0xDCCF, 0x82A0, 0xC65B, 0x82A1, 0xDCCD, 0x82A2, 0xC65C, + 0x82A3, 0xC65D, 0x82A4, 0xDCD2, 0x82A5, 0xBDE6, 0x82A6, 0xC2AB, + 0x82A7, 0xC65E, 0x82A8, 0xDCB8, 0x82A9, 0xDCCB, 0x82AA, 0xDCCE, + 0x82AB, 0xDCBE, 0x82AC, 0xB7D2, 0x82AD, 0xB0C5, 0x82AE, 0xDCC7, + 0x82AF, 0xD0BE, 0x82B0, 0xDCC1, 0x82B1, 0xBBA8, 0x82B2, 0xC65F, + 0x82B3, 0xB7BC, 0x82B4, 0xDCCC, 0x82B5, 0xC660, 0x82B6, 0xC661, + 0x82B7, 0xDCC6, 0x82B8, 0xDCBF, 0x82B9, 0xC7DB, 0x82BA, 0xC662, + 0x82BB, 0xC663, 0x82BC, 0xC664, 0x82BD, 0xD1BF, 0x82BE, 0xDCC0, + 0x82BF, 0xC665, 0x82C0, 0xC666, 0x82C1, 0xDCCA, 0x82C2, 0xC667, + 0x82C3, 0xC668, 0x82C4, 0xDCD0, 0x82C5, 0xC669, 0x82C6, 0xC66A, + 0x82C7, 0xCEAD, 0x82C8, 0xDCC2, 0x82C9, 0xC66B, 0x82CA, 0xDCC3, + 0x82CB, 0xDCC8, 0x82CC, 0xDCC9, 0x82CD, 0xB2D4, 0x82CE, 0xDCD1, + 0x82CF, 0xCBD5, 0x82D0, 0xC66C, 0x82D1, 0xD4B7, 0x82D2, 0xDCDB, + 0x82D3, 0xDCDF, 0x82D4, 0xCCA6, 0x82D5, 0xDCE6, 0x82D6, 0xC66D, + 0x82D7, 0xC3E7, 0x82D8, 0xDCDC, 0x82D9, 0xC66E, 0x82DA, 0xC66F, + 0x82DB, 0xBFC1, 0x82DC, 0xDCD9, 0x82DD, 0xC670, 0x82DE, 0xB0FA, + 0x82DF, 0xB9B6, 0x82E0, 0xDCE5, 0x82E1, 0xDCD3, 0x82E2, 0xC671, + 0x82E3, 0xDCC4, 0x82E4, 0xDCD6, 0x82E5, 0xC8F4, 0x82E6, 0xBFE0, + 0x82E7, 0xC672, 0x82E8, 0xC673, 0x82E9, 0xC674, 0x82EA, 0xC675, + 0x82EB, 0xC9BB, 0x82EC, 0xC676, 0x82ED, 0xC677, 0x82EE, 0xC678, + 0x82EF, 0xB1BD, 0x82F0, 0xC679, 0x82F1, 0xD3A2, 0x82F2, 0xC67A, + 0x82F3, 0xC67B, 0x82F4, 0xDCDA, 0x82F5, 0xC67C, 0x82F6, 0xC67D, + 0x82F7, 0xDCD5, 0x82F8, 0xC67E, 0x82F9, 0xC6BB, 0x82FA, 0xC680, + 0x82FB, 0xDCDE, 0x82FC, 0xC681, 0x82FD, 0xC682, 0x82FE, 0xC683, + 0x82FF, 0xC684, 0x8300, 0xC685, 0x8301, 0xD7C2, 0x8302, 0xC3AF, + 0x8303, 0xB7B6, 0x8304, 0xC7D1, 0x8305, 0xC3A9, 0x8306, 0xDCE2, + 0x8307, 0xDCD8, 0x8308, 0xDCEB, 0x8309, 0xDCD4, 0x830A, 0xC686, + 0x830B, 0xC687, 0x830C, 0xDCDD, 0x830D, 0xC688, 0x830E, 0xBEA5, + 0x830F, 0xDCD7, 0x8310, 0xC689, 0x8311, 0xDCE0, 0x8312, 0xC68A, + 0x8313, 0xC68B, 0x8314, 0xDCE3, 0x8315, 0xDCE4, 0x8316, 0xC68C, + 0x8317, 0xDCF8, 0x8318, 0xC68D, 0x8319, 0xC68E, 0x831A, 0xDCE1, + 0x831B, 0xDDA2, 0x831C, 0xDCE7, 0x831D, 0xC68F, 0x831E, 0xC690, + 0x831F, 0xC691, 0x8320, 0xC692, 0x8321, 0xC693, 0x8322, 0xC694, + 0x8323, 0xC695, 0x8324, 0xC696, 0x8325, 0xC697, 0x8326, 0xC698, + 0x8327, 0xBCEB, 0x8328, 0xB4C4, 0x8329, 0xC699, 0x832A, 0xC69A, + 0x832B, 0xC3A3, 0x832C, 0xB2E7, 0x832D, 0xDCFA, 0x832E, 0xC69B, + 0x832F, 0xDCF2, 0x8330, 0xC69C, 0x8331, 0xDCEF, 0x8332, 0xC69D, + 0x8333, 0xDCFC, 0x8334, 0xDCEE, 0x8335, 0xD2F0, 0x8336, 0xB2E8, + 0x8337, 0xC69E, 0x8338, 0xC8D7, 0x8339, 0xC8E3, 0x833A, 0xDCFB, + 0x833B, 0xC69F, 0x833C, 0xDCED, 0x833D, 0xC6A0, 0x833E, 0xC740, + 0x833F, 0xC741, 0x8340, 0xDCF7, 0x8341, 0xC742, 0x8342, 0xC743, + 0x8343, 0xDCF5, 0x8344, 0xC744, 0x8345, 0xC745, 0x8346, 0xBEA3, + 0x8347, 0xDCF4, 0x8348, 0xC746, 0x8349, 0xB2DD, 0x834A, 0xC747, + 0x834B, 0xC748, 0x834C, 0xC749, 0x834D, 0xC74A, 0x834E, 0xC74B, + 0x834F, 0xDCF3, 0x8350, 0xBCF6, 0x8351, 0xDCE8, 0x8352, 0xBBC4, + 0x8353, 0xC74C, 0x8354, 0xC0F3, 0x8355, 0xC74D, 0x8356, 0xC74E, + 0x8357, 0xC74F, 0x8358, 0xC750, 0x8359, 0xC751, 0x835A, 0xBCD4, + 0x835B, 0xDCE9, 0x835C, 0xDCEA, 0x835D, 0xC752, 0x835E, 0xDCF1, + 0x835F, 0xDCF6, 0x8360, 0xDCF9, 0x8361, 0xB5B4, 0x8362, 0xC753, + 0x8363, 0xC8D9, 0x8364, 0xBBE7, 0x8365, 0xDCFE, 0x8366, 0xDCFD, + 0x8367, 0xD3AB, 0x8368, 0xDDA1, 0x8369, 0xDDA3, 0x836A, 0xDDA5, + 0x836B, 0xD2F1, 0x836C, 0xDDA4, 0x836D, 0xDDA6, 0x836E, 0xDDA7, + 0x836F, 0xD2A9, 0x8370, 0xC754, 0x8371, 0xC755, 0x8372, 0xC756, + 0x8373, 0xC757, 0x8374, 0xC758, 0x8375, 0xC759, 0x8376, 0xC75A, + 0x8377, 0xBAC9, 0x8378, 0xDDA9, 0x8379, 0xC75B, 0x837A, 0xC75C, + 0x837B, 0xDDB6, 0x837C, 0xDDB1, 0x837D, 0xDDB4, 0x837E, 0xC75D, + 0x837F, 0xC75E, 0x8380, 0xC75F, 0x8381, 0xC760, 0x8382, 0xC761, + 0x8383, 0xC762, 0x8384, 0xC763, 0x8385, 0xDDB0, 0x8386, 0xC6CE, + 0x8387, 0xC764, 0x8388, 0xC765, 0x8389, 0xC0F2, 0x838A, 0xC766, + 0x838B, 0xC767, 0x838C, 0xC768, 0x838D, 0xC769, 0x838E, 0xC9AF, + 0x838F, 0xC76A, 0x8390, 0xC76B, 0x8391, 0xC76C, 0x8392, 0xDCEC, + 0x8393, 0xDDAE, 0x8394, 0xC76D, 0x8395, 0xC76E, 0x8396, 0xC76F, + 0x8397, 0xC770, 0x8398, 0xDDB7, 0x8399, 0xC771, 0x839A, 0xC772, + 0x839B, 0xDCF0, 0x839C, 0xDDAF, 0x839D, 0xC773, 0x839E, 0xDDB8, + 0x839F, 0xC774, 0x83A0, 0xDDAC, 0x83A1, 0xC775, 0x83A2, 0xC776, + 0x83A3, 0xC777, 0x83A4, 0xC778, 0x83A5, 0xC779, 0x83A6, 0xC77A, + 0x83A7, 0xC77B, 0x83A8, 0xDDB9, 0x83A9, 0xDDB3, 0x83AA, 0xDDAD, + 0x83AB, 0xC4AA, 0x83AC, 0xC77C, 0x83AD, 0xC77D, 0x83AE, 0xC77E, + 0x83AF, 0xC780, 0x83B0, 0xDDA8, 0x83B1, 0xC0B3, 0x83B2, 0xC1AB, + 0x83B3, 0xDDAA, 0x83B4, 0xDDAB, 0x83B5, 0xC781, 0x83B6, 0xDDB2, + 0x83B7, 0xBBF1, 0x83B8, 0xDDB5, 0x83B9, 0xD3A8, 0x83BA, 0xDDBA, + 0x83BB, 0xC782, 0x83BC, 0xDDBB, 0x83BD, 0xC3A7, 0x83BE, 0xC783, + 0x83BF, 0xC784, 0x83C0, 0xDDD2, 0x83C1, 0xDDBC, 0x83C2, 0xC785, + 0x83C3, 0xC786, 0x83C4, 0xC787, 0x83C5, 0xDDD1, 0x83C6, 0xC788, + 0x83C7, 0xB9BD, 0x83C8, 0xC789, 0x83C9, 0xC78A, 0x83CA, 0xBED5, + 0x83CB, 0xC78B, 0x83CC, 0xBEFA, 0x83CD, 0xC78C, 0x83CE, 0xC78D, + 0x83CF, 0xBACA, 0x83D0, 0xC78E, 0x83D1, 0xC78F, 0x83D2, 0xC790, + 0x83D3, 0xC791, 0x83D4, 0xDDCA, 0x83D5, 0xC792, 0x83D6, 0xDDC5, + 0x83D7, 0xC793, 0x83D8, 0xDDBF, 0x83D9, 0xC794, 0x83DA, 0xC795, + 0x83DB, 0xC796, 0x83DC, 0xB2CB, 0x83DD, 0xDDC3, 0x83DE, 0xC797, + 0x83DF, 0xDDCB, 0x83E0, 0xB2A4, 0x83E1, 0xDDD5, 0x83E2, 0xC798, + 0x83E3, 0xC799, 0x83E4, 0xC79A, 0x83E5, 0xDDBE, 0x83E6, 0xC79B, + 0x83E7, 0xC79C, 0x83E8, 0xC79D, 0x83E9, 0xC6D0, 0x83EA, 0xDDD0, + 0x83EB, 0xC79E, 0x83EC, 0xC79F, 0x83ED, 0xC7A0, 0x83EE, 0xC840, + 0x83EF, 0xC841, 0x83F0, 0xDDD4, 0x83F1, 0xC1E2, 0x83F2, 0xB7C6, + 0x83F3, 0xC842, 0x83F4, 0xC843, 0x83F5, 0xC844, 0x83F6, 0xC845, + 0x83F7, 0xC846, 0x83F8, 0xDDCE, 0x83F9, 0xDDCF, 0x83FA, 0xC847, + 0x83FB, 0xC848, 0x83FC, 0xC849, 0x83FD, 0xDDC4, 0x83FE, 0xC84A, + 0x83FF, 0xC84B, 0x8400, 0xC84C, 0x8401, 0xDDBD, 0x8402, 0xC84D, + 0x8403, 0xDDCD, 0x8404, 0xCCD1, 0x8405, 0xC84E, 0x8406, 0xDDC9, + 0x8407, 0xC84F, 0x8408, 0xC850, 0x8409, 0xC851, 0x840A, 0xC852, + 0x840B, 0xDDC2, 0x840C, 0xC3C8, 0x840D, 0xC6BC, 0x840E, 0xCEAE, + 0x840F, 0xDDCC, 0x8410, 0xC853, 0x8411, 0xDDC8, 0x8412, 0xC854, + 0x8413, 0xC855, 0x8414, 0xC856, 0x8415, 0xC857, 0x8416, 0xC858, + 0x8417, 0xC859, 0x8418, 0xDDC1, 0x8419, 0xC85A, 0x841A, 0xC85B, + 0x841B, 0xC85C, 0x841C, 0xDDC6, 0x841D, 0xC2DC, 0x841E, 0xC85D, + 0x841F, 0xC85E, 0x8420, 0xC85F, 0x8421, 0xC860, 0x8422, 0xC861, + 0x8423, 0xC862, 0x8424, 0xD3A9, 0x8425, 0xD3AA, 0x8426, 0xDDD3, + 0x8427, 0xCFF4, 0x8428, 0xC8F8, 0x8429, 0xC863, 0x842A, 0xC864, + 0x842B, 0xC865, 0x842C, 0xC866, 0x842D, 0xC867, 0x842E, 0xC868, + 0x842F, 0xC869, 0x8430, 0xC86A, 0x8431, 0xDDE6, 0x8432, 0xC86B, + 0x8433, 0xC86C, 0x8434, 0xC86D, 0x8435, 0xC86E, 0x8436, 0xC86F, + 0x8437, 0xC870, 0x8438, 0xDDC7, 0x8439, 0xC871, 0x843A, 0xC872, + 0x843B, 0xC873, 0x843C, 0xDDE0, 0x843D, 0xC2E4, 0x843E, 0xC874, + 0x843F, 0xC875, 0x8440, 0xC876, 0x8441, 0xC877, 0x8442, 0xC878, + 0x8443, 0xC879, 0x8444, 0xC87A, 0x8445, 0xC87B, 0x8446, 0xDDE1, + 0x8447, 0xC87C, 0x8448, 0xC87D, 0x8449, 0xC87E, 0x844A, 0xC880, + 0x844B, 0xC881, 0x844C, 0xC882, 0x844D, 0xC883, 0x844E, 0xC884, + 0x844F, 0xC885, 0x8450, 0xC886, 0x8451, 0xDDD7, 0x8452, 0xC887, + 0x8453, 0xC888, 0x8454, 0xC889, 0x8455, 0xC88A, 0x8456, 0xC88B, + 0x8457, 0xD6F8, 0x8458, 0xC88C, 0x8459, 0xDDD9, 0x845A, 0xDDD8, + 0x845B, 0xB8F0, 0x845C, 0xDDD6, 0x845D, 0xC88D, 0x845E, 0xC88E, + 0x845F, 0xC88F, 0x8460, 0xC890, 0x8461, 0xC6CF, 0x8462, 0xC891, + 0x8463, 0xB6AD, 0x8464, 0xC892, 0x8465, 0xC893, 0x8466, 0xC894, + 0x8467, 0xC895, 0x8468, 0xC896, 0x8469, 0xDDE2, 0x846A, 0xC897, + 0x846B, 0xBAF9, 0x846C, 0xD4E1, 0x846D, 0xDDE7, 0x846E, 0xC898, + 0x846F, 0xC899, 0x8470, 0xC89A, 0x8471, 0xB4D0, 0x8472, 0xC89B, + 0x8473, 0xDDDA, 0x8474, 0xC89C, 0x8475, 0xBFFB, 0x8476, 0xDDE3, + 0x8477, 0xC89D, 0x8478, 0xDDDF, 0x8479, 0xC89E, 0x847A, 0xDDDD, + 0x847B, 0xC89F, 0x847C, 0xC8A0, 0x847D, 0xC940, 0x847E, 0xC941, + 0x847F, 0xC942, 0x8480, 0xC943, 0x8481, 0xC944, 0x8482, 0xB5D9, + 0x8483, 0xC945, 0x8484, 0xC946, 0x8485, 0xC947, 0x8486, 0xC948, + 0x8487, 0xDDDB, 0x8488, 0xDDDC, 0x8489, 0xDDDE, 0x848A, 0xC949, + 0x848B, 0xBDAF, 0x848C, 0xDDE4, 0x848D, 0xC94A, 0x848E, 0xDDE5, + 0x848F, 0xC94B, 0x8490, 0xC94C, 0x8491, 0xC94D, 0x8492, 0xC94E, + 0x8493, 0xC94F, 0x8494, 0xC950, 0x8495, 0xC951, 0x8496, 0xC952, + 0x8497, 0xDDF5, 0x8498, 0xC953, 0x8499, 0xC3C9, 0x849A, 0xC954, + 0x849B, 0xC955, 0x849C, 0xCBE2, 0x849D, 0xC956, 0x849E, 0xC957, + 0x849F, 0xC958, 0x84A0, 0xC959, 0x84A1, 0xDDF2, 0x84A2, 0xC95A, + 0x84A3, 0xC95B, 0x84A4, 0xC95C, 0x84A5, 0xC95D, 0x84A6, 0xC95E, + 0x84A7, 0xC95F, 0x84A8, 0xC960, 0x84A9, 0xC961, 0x84AA, 0xC962, + 0x84AB, 0xC963, 0x84AC, 0xC964, 0x84AD, 0xC965, 0x84AE, 0xC966, + 0x84AF, 0xD8E1, 0x84B0, 0xC967, 0x84B1, 0xC968, 0x84B2, 0xC6D1, + 0x84B3, 0xC969, 0x84B4, 0xDDF4, 0x84B5, 0xC96A, 0x84B6, 0xC96B, + 0x84B7, 0xC96C, 0x84B8, 0xD5F4, 0x84B9, 0xDDF3, 0x84BA, 0xDDF0, + 0x84BB, 0xC96D, 0x84BC, 0xC96E, 0x84BD, 0xDDEC, 0x84BE, 0xC96F, + 0x84BF, 0xDDEF, 0x84C0, 0xC970, 0x84C1, 0xDDE8, 0x84C2, 0xC971, + 0x84C3, 0xC972, 0x84C4, 0xD0EE, 0x84C5, 0xC973, 0x84C6, 0xC974, + 0x84C7, 0xC975, 0x84C8, 0xC976, 0x84C9, 0xC8D8, 0x84CA, 0xDDEE, + 0x84CB, 0xC977, 0x84CC, 0xC978, 0x84CD, 0xDDE9, 0x84CE, 0xC979, + 0x84CF, 0xC97A, 0x84D0, 0xDDEA, 0x84D1, 0xCBF2, 0x84D2, 0xC97B, + 0x84D3, 0xDDED, 0x84D4, 0xC97C, 0x84D5, 0xC97D, 0x84D6, 0xB1CD, + 0x84D7, 0xC97E, 0x84D8, 0xC980, 0x84D9, 0xC981, 0x84DA, 0xC982, + 0x84DB, 0xC983, 0x84DC, 0xC984, 0x84DD, 0xC0B6, 0x84DE, 0xC985, + 0x84DF, 0xBCBB, 0x84E0, 0xDDF1, 0x84E1, 0xC986, 0x84E2, 0xC987, + 0x84E3, 0xDDF7, 0x84E4, 0xC988, 0x84E5, 0xDDF6, 0x84E6, 0xDDEB, + 0x84E7, 0xC989, 0x84E8, 0xC98A, 0x84E9, 0xC98B, 0x84EA, 0xC98C, + 0x84EB, 0xC98D, 0x84EC, 0xC5EE, 0x84ED, 0xC98E, 0x84EE, 0xC98F, + 0x84EF, 0xC990, 0x84F0, 0xDDFB, 0x84F1, 0xC991, 0x84F2, 0xC992, + 0x84F3, 0xC993, 0x84F4, 0xC994, 0x84F5, 0xC995, 0x84F6, 0xC996, + 0x84F7, 0xC997, 0x84F8, 0xC998, 0x84F9, 0xC999, 0x84FA, 0xC99A, + 0x84FB, 0xC99B, 0x84FC, 0xDEA4, 0x84FD, 0xC99C, 0x84FE, 0xC99D, + 0x84FF, 0xDEA3, 0x8500, 0xC99E, 0x8501, 0xC99F, 0x8502, 0xC9A0, + 0x8503, 0xCA40, 0x8504, 0xCA41, 0x8505, 0xCA42, 0x8506, 0xCA43, + 0x8507, 0xCA44, 0x8508, 0xCA45, 0x8509, 0xCA46, 0x850A, 0xCA47, + 0x850B, 0xCA48, 0x850C, 0xDDF8, 0x850D, 0xCA49, 0x850E, 0xCA4A, + 0x850F, 0xCA4B, 0x8510, 0xCA4C, 0x8511, 0xC3EF, 0x8512, 0xCA4D, + 0x8513, 0xC2FB, 0x8514, 0xCA4E, 0x8515, 0xCA4F, 0x8516, 0xCA50, + 0x8517, 0xD5E1, 0x8518, 0xCA51, 0x8519, 0xCA52, 0x851A, 0xCEB5, + 0x851B, 0xCA53, 0x851C, 0xCA54, 0x851D, 0xCA55, 0x851E, 0xCA56, + 0x851F, 0xDDFD, 0x8520, 0xCA57, 0x8521, 0xB2CC, 0x8522, 0xCA58, + 0x8523, 0xCA59, 0x8524, 0xCA5A, 0x8525, 0xCA5B, 0x8526, 0xCA5C, + 0x8527, 0xCA5D, 0x8528, 0xCA5E, 0x8529, 0xCA5F, 0x852A, 0xCA60, + 0x852B, 0xC4E8, 0x852C, 0xCADF, 0x852D, 0xCA61, 0x852E, 0xCA62, + 0x852F, 0xCA63, 0x8530, 0xCA64, 0x8531, 0xCA65, 0x8532, 0xCA66, + 0x8533, 0xCA67, 0x8534, 0xCA68, 0x8535, 0xCA69, 0x8536, 0xCA6A, + 0x8537, 0xC7BE, 0x8538, 0xDDFA, 0x8539, 0xDDFC, 0x853A, 0xDDFE, + 0x853B, 0xDEA2, 0x853C, 0xB0AA, 0x853D, 0xB1CE, 0x853E, 0xCA6B, + 0x853F, 0xCA6C, 0x8540, 0xCA6D, 0x8541, 0xCA6E, 0x8542, 0xCA6F, + 0x8543, 0xDEAC, 0x8544, 0xCA70, 0x8545, 0xCA71, 0x8546, 0xCA72, + 0x8547, 0xCA73, 0x8548, 0xDEA6, 0x8549, 0xBDB6, 0x854A, 0xC8EF, + 0x854B, 0xCA74, 0x854C, 0xCA75, 0x854D, 0xCA76, 0x854E, 0xCA77, + 0x854F, 0xCA78, 0x8550, 0xCA79, 0x8551, 0xCA7A, 0x8552, 0xCA7B, + 0x8553, 0xCA7C, 0x8554, 0xCA7D, 0x8555, 0xCA7E, 0x8556, 0xDEA1, + 0x8557, 0xCA80, 0x8558, 0xCA81, 0x8559, 0xDEA5, 0x855A, 0xCA82, + 0x855B, 0xCA83, 0x855C, 0xCA84, 0x855D, 0xCA85, 0x855E, 0xDEA9, + 0x855F, 0xCA86, 0x8560, 0xCA87, 0x8561, 0xCA88, 0x8562, 0xCA89, + 0x8563, 0xCA8A, 0x8564, 0xDEA8, 0x8565, 0xCA8B, 0x8566, 0xCA8C, + 0x8567, 0xCA8D, 0x8568, 0xDEA7, 0x8569, 0xCA8E, 0x856A, 0xCA8F, + 0x856B, 0xCA90, 0x856C, 0xCA91, 0x856D, 0xCA92, 0x856E, 0xCA93, + 0x856F, 0xCA94, 0x8570, 0xCA95, 0x8571, 0xCA96, 0x8572, 0xDEAD, + 0x8573, 0xCA97, 0x8574, 0xD4CC, 0x8575, 0xCA98, 0x8576, 0xCA99, + 0x8577, 0xCA9A, 0x8578, 0xCA9B, 0x8579, 0xDEB3, 0x857A, 0xDEAA, + 0x857B, 0xDEAE, 0x857C, 0xCA9C, 0x857D, 0xCA9D, 0x857E, 0xC0D9, + 0x857F, 0xCA9E, 0x8580, 0xCA9F, 0x8581, 0xCAA0, 0x8582, 0xCB40, + 0x8583, 0xCB41, 0x8584, 0xB1A1, 0x8585, 0xDEB6, 0x8586, 0xCB42, + 0x8587, 0xDEB1, 0x8588, 0xCB43, 0x8589, 0xCB44, 0x858A, 0xCB45, + 0x858B, 0xCB46, 0x858C, 0xCB47, 0x858D, 0xCB48, 0x858E, 0xCB49, + 0x858F, 0xDEB2, 0x8590, 0xCB4A, 0x8591, 0xCB4B, 0x8592, 0xCB4C, + 0x8593, 0xCB4D, 0x8594, 0xCB4E, 0x8595, 0xCB4F, 0x8596, 0xCB50, + 0x8597, 0xCB51, 0x8598, 0xCB52, 0x8599, 0xCB53, 0x859A, 0xCB54, + 0x859B, 0xD1A6, 0x859C, 0xDEB5, 0x859D, 0xCB55, 0x859E, 0xCB56, + 0x859F, 0xCB57, 0x85A0, 0xCB58, 0x85A1, 0xCB59, 0x85A2, 0xCB5A, + 0x85A3, 0xCB5B, 0x85A4, 0xDEAF, 0x85A5, 0xCB5C, 0x85A6, 0xCB5D, + 0x85A7, 0xCB5E, 0x85A8, 0xDEB0, 0x85A9, 0xCB5F, 0x85AA, 0xD0BD, + 0x85AB, 0xCB60, 0x85AC, 0xCB61, 0x85AD, 0xCB62, 0x85AE, 0xDEB4, + 0x85AF, 0xCAED, 0x85B0, 0xDEB9, 0x85B1, 0xCB63, 0x85B2, 0xCB64, + 0x85B3, 0xCB65, 0x85B4, 0xCB66, 0x85B5, 0xCB67, 0x85B6, 0xCB68, + 0x85B7, 0xDEB8, 0x85B8, 0xCB69, 0x85B9, 0xDEB7, 0x85BA, 0xCB6A, + 0x85BB, 0xCB6B, 0x85BC, 0xCB6C, 0x85BD, 0xCB6D, 0x85BE, 0xCB6E, + 0x85BF, 0xCB6F, 0x85C0, 0xCB70, 0x85C1, 0xDEBB, 0x85C2, 0xCB71, + 0x85C3, 0xCB72, 0x85C4, 0xCB73, 0x85C5, 0xCB74, 0x85C6, 0xCB75, + 0x85C7, 0xCB76, 0x85C8, 0xCB77, 0x85C9, 0xBDE5, 0x85CA, 0xCB78, + 0x85CB, 0xCB79, 0x85CC, 0xCB7A, 0x85CD, 0xCB7B, 0x85CE, 0xCB7C, + 0x85CF, 0xB2D8, 0x85D0, 0xC3EA, 0x85D1, 0xCB7D, 0x85D2, 0xCB7E, + 0x85D3, 0xDEBA, 0x85D4, 0xCB80, 0x85D5, 0xC5BA, 0x85D6, 0xCB81, + 0x85D7, 0xCB82, 0x85D8, 0xCB83, 0x85D9, 0xCB84, 0x85DA, 0xCB85, + 0x85DB, 0xCB86, 0x85DC, 0xDEBC, 0x85DD, 0xCB87, 0x85DE, 0xCB88, + 0x85DF, 0xCB89, 0x85E0, 0xCB8A, 0x85E1, 0xCB8B, 0x85E2, 0xCB8C, + 0x85E3, 0xCB8D, 0x85E4, 0xCCD9, 0x85E5, 0xCB8E, 0x85E6, 0xCB8F, + 0x85E7, 0xCB90, 0x85E8, 0xCB91, 0x85E9, 0xB7AA, 0x85EA, 0xCB92, + 0x85EB, 0xCB93, 0x85EC, 0xCB94, 0x85ED, 0xCB95, 0x85EE, 0xCB96, + 0x85EF, 0xCB97, 0x85F0, 0xCB98, 0x85F1, 0xCB99, 0x85F2, 0xCB9A, + 0x85F3, 0xCB9B, 0x85F4, 0xCB9C, 0x85F5, 0xCB9D, 0x85F6, 0xCB9E, + 0x85F7, 0xCB9F, 0x85F8, 0xCBA0, 0x85F9, 0xCC40, 0x85FA, 0xCC41, + 0x85FB, 0xD4E5, 0x85FC, 0xCC42, 0x85FD, 0xCC43, 0x85FE, 0xCC44, + 0x85FF, 0xDEBD, 0x8600, 0xCC45, 0x8601, 0xCC46, 0x8602, 0xCC47, + 0x8603, 0xCC48, 0x8604, 0xCC49, 0x8605, 0xDEBF, 0x8606, 0xCC4A, + 0x8607, 0xCC4B, 0x8608, 0xCC4C, 0x8609, 0xCC4D, 0x860A, 0xCC4E, + 0x860B, 0xCC4F, 0x860C, 0xCC50, 0x860D, 0xCC51, 0x860E, 0xCC52, + 0x860F, 0xCC53, 0x8610, 0xCC54, 0x8611, 0xC4A2, 0x8612, 0xCC55, + 0x8613, 0xCC56, 0x8614, 0xCC57, 0x8615, 0xCC58, 0x8616, 0xDEC1, + 0x8617, 0xCC59, 0x8618, 0xCC5A, 0x8619, 0xCC5B, 0x861A, 0xCC5C, + 0x861B, 0xCC5D, 0x861C, 0xCC5E, 0x861D, 0xCC5F, 0x861E, 0xCC60, + 0x861F, 0xCC61, 0x8620, 0xCC62, 0x8621, 0xCC63, 0x8622, 0xCC64, + 0x8623, 0xCC65, 0x8624, 0xCC66, 0x8625, 0xCC67, 0x8626, 0xCC68, + 0x8627, 0xDEBE, 0x8628, 0xCC69, 0x8629, 0xDEC0, 0x862A, 0xCC6A, + 0x862B, 0xCC6B, 0x862C, 0xCC6C, 0x862D, 0xCC6D, 0x862E, 0xCC6E, + 0x862F, 0xCC6F, 0x8630, 0xCC70, 0x8631, 0xCC71, 0x8632, 0xCC72, + 0x8633, 0xCC73, 0x8634, 0xCC74, 0x8635, 0xCC75, 0x8636, 0xCC76, + 0x8637, 0xCC77, 0x8638, 0xD5BA, 0x8639, 0xCC78, 0x863A, 0xCC79, + 0x863B, 0xCC7A, 0x863C, 0xDEC2, 0x863D, 0xCC7B, 0x863E, 0xCC7C, + 0x863F, 0xCC7D, 0x8640, 0xCC7E, 0x8641, 0xCC80, 0x8642, 0xCC81, + 0x8643, 0xCC82, 0x8644, 0xCC83, 0x8645, 0xCC84, 0x8646, 0xCC85, + 0x8647, 0xCC86, 0x8648, 0xCC87, 0x8649, 0xCC88, 0x864A, 0xCC89, + 0x864B, 0xCC8A, 0x864C, 0xCC8B, 0x864D, 0xF2AE, 0x864E, 0xBBA2, + 0x864F, 0xC2B2, 0x8650, 0xC5B0, 0x8651, 0xC2C7, 0x8652, 0xCC8C, + 0x8653, 0xCC8D, 0x8654, 0xF2AF, 0x8655, 0xCC8E, 0x8656, 0xCC8F, + 0x8657, 0xCC90, 0x8658, 0xCC91, 0x8659, 0xCC92, 0x865A, 0xD0E9, + 0x865B, 0xCC93, 0x865C, 0xCC94, 0x865D, 0xCC95, 0x865E, 0xD3DD, + 0x865F, 0xCC96, 0x8660, 0xCC97, 0x8661, 0xCC98, 0x8662, 0xEBBD, + 0x8663, 0xCC99, 0x8664, 0xCC9A, 0x8665, 0xCC9B, 0x8666, 0xCC9C, + 0x8667, 0xCC9D, 0x8668, 0xCC9E, 0x8669, 0xCC9F, 0x866A, 0xCCA0, + 0x866B, 0xB3E6, 0x866C, 0xF2B0, 0x866D, 0xCD40, 0x866E, 0xF2B1, + 0x866F, 0xCD41, 0x8670, 0xCD42, 0x8671, 0xCAAD, 0x8672, 0xCD43, + 0x8673, 0xCD44, 0x8674, 0xCD45, 0x8675, 0xCD46, 0x8676, 0xCD47, + 0x8677, 0xCD48, 0x8678, 0xCD49, 0x8679, 0xBAE7, 0x867A, 0xF2B3, + 0x867B, 0xF2B5, 0x867C, 0xF2B4, 0x867D, 0xCBE4, 0x867E, 0xCFBA, + 0x867F, 0xF2B2, 0x8680, 0xCAB4, 0x8681, 0xD2CF, 0x8682, 0xC2EC, + 0x8683, 0xCD4A, 0x8684, 0xCD4B, 0x8685, 0xCD4C, 0x8686, 0xCD4D, + 0x8687, 0xCD4E, 0x8688, 0xCD4F, 0x8689, 0xCD50, 0x868A, 0xCEC3, + 0x868B, 0xF2B8, 0x868C, 0xB0F6, 0x868D, 0xF2B7, 0x868E, 0xCD51, + 0x868F, 0xCD52, 0x8690, 0xCD53, 0x8691, 0xCD54, 0x8692, 0xCD55, + 0x8693, 0xF2BE, 0x8694, 0xCD56, 0x8695, 0xB2CF, 0x8696, 0xCD57, + 0x8697, 0xCD58, 0x8698, 0xCD59, 0x8699, 0xCD5A, 0x869A, 0xCD5B, + 0x869B, 0xCD5C, 0x869C, 0xD1C1, 0x869D, 0xF2BA, 0x869E, 0xCD5D, + 0x869F, 0xCD5E, 0x86A0, 0xCD5F, 0x86A1, 0xCD60, 0x86A2, 0xCD61, + 0x86A3, 0xF2BC, 0x86A4, 0xD4E9, 0x86A5, 0xCD62, 0x86A6, 0xCD63, + 0x86A7, 0xF2BB, 0x86A8, 0xF2B6, 0x86A9, 0xF2BF, 0x86AA, 0xF2BD, + 0x86AB, 0xCD64, 0x86AC, 0xF2B9, 0x86AD, 0xCD65, 0x86AE, 0xCD66, + 0x86AF, 0xF2C7, 0x86B0, 0xF2C4, 0x86B1, 0xF2C6, 0x86B2, 0xCD67, + 0x86B3, 0xCD68, 0x86B4, 0xF2CA, 0x86B5, 0xF2C2, 0x86B6, 0xF2C0, + 0x86B7, 0xCD69, 0x86B8, 0xCD6A, 0x86B9, 0xCD6B, 0x86BA, 0xF2C5, + 0x86BB, 0xCD6C, 0x86BC, 0xCD6D, 0x86BD, 0xCD6E, 0x86BE, 0xCD6F, + 0x86BF, 0xCD70, 0x86C0, 0xD6FB, 0x86C1, 0xCD71, 0x86C2, 0xCD72, + 0x86C3, 0xCD73, 0x86C4, 0xF2C1, 0x86C5, 0xCD74, 0x86C6, 0xC7F9, + 0x86C7, 0xC9DF, 0x86C8, 0xCD75, 0x86C9, 0xF2C8, 0x86CA, 0xB9C6, + 0x86CB, 0xB5B0, 0x86CC, 0xCD76, 0x86CD, 0xCD77, 0x86CE, 0xF2C3, + 0x86CF, 0xF2C9, 0x86D0, 0xF2D0, 0x86D1, 0xF2D6, 0x86D2, 0xCD78, + 0x86D3, 0xCD79, 0x86D4, 0xBBD7, 0x86D5, 0xCD7A, 0x86D6, 0xCD7B, + 0x86D7, 0xCD7C, 0x86D8, 0xF2D5, 0x86D9, 0xCDDC, 0x86DA, 0xCD7D, + 0x86DB, 0xD6EB, 0x86DC, 0xCD7E, 0x86DD, 0xCD80, 0x86DE, 0xF2D2, + 0x86DF, 0xF2D4, 0x86E0, 0xCD81, 0x86E1, 0xCD82, 0x86E2, 0xCD83, + 0x86E3, 0xCD84, 0x86E4, 0xB8F2, 0x86E5, 0xCD85, 0x86E6, 0xCD86, + 0x86E7, 0xCD87, 0x86E8, 0xCD88, 0x86E9, 0xF2CB, 0x86EA, 0xCD89, + 0x86EB, 0xCD8A, 0x86EC, 0xCD8B, 0x86ED, 0xF2CE, 0x86EE, 0xC2F9, + 0x86EF, 0xCD8C, 0x86F0, 0xD5DD, 0x86F1, 0xF2CC, 0x86F2, 0xF2CD, + 0x86F3, 0xF2CF, 0x86F4, 0xF2D3, 0x86F5, 0xCD8D, 0x86F6, 0xCD8E, + 0x86F7, 0xCD8F, 0x86F8, 0xF2D9, 0x86F9, 0xD3BC, 0x86FA, 0xCD90, + 0x86FB, 0xCD91, 0x86FC, 0xCD92, 0x86FD, 0xCD93, 0x86FE, 0xB6EA, + 0x86FF, 0xCD94, 0x8700, 0xCAF1, 0x8701, 0xCD95, 0x8702, 0xB7E4, + 0x8703, 0xF2D7, 0x8704, 0xCD96, 0x8705, 0xCD97, 0x8706, 0xCD98, + 0x8707, 0xF2D8, 0x8708, 0xF2DA, 0x8709, 0xF2DD, 0x870A, 0xF2DB, + 0x870B, 0xCD99, 0x870C, 0xCD9A, 0x870D, 0xF2DC, 0x870E, 0xCD9B, + 0x870F, 0xCD9C, 0x8710, 0xCD9D, 0x8711, 0xCD9E, 0x8712, 0xD1D1, + 0x8713, 0xF2D1, 0x8714, 0xCD9F, 0x8715, 0xCDC9, 0x8716, 0xCDA0, + 0x8717, 0xCECF, 0x8718, 0xD6A9, 0x8719, 0xCE40, 0x871A, 0xF2E3, + 0x871B, 0xCE41, 0x871C, 0xC3DB, 0x871D, 0xCE42, 0x871E, 0xF2E0, + 0x871F, 0xCE43, 0x8720, 0xCE44, 0x8721, 0xC0AF, 0x8722, 0xF2EC, + 0x8723, 0xF2DE, 0x8724, 0xCE45, 0x8725, 0xF2E1, 0x8726, 0xCE46, + 0x8727, 0xCE47, 0x8728, 0xCE48, 0x8729, 0xF2E8, 0x872A, 0xCE49, + 0x872B, 0xCE4A, 0x872C, 0xCE4B, 0x872D, 0xCE4C, 0x872E, 0xF2E2, + 0x872F, 0xCE4D, 0x8730, 0xCE4E, 0x8731, 0xF2E7, 0x8732, 0xCE4F, + 0x8733, 0xCE50, 0x8734, 0xF2E6, 0x8735, 0xCE51, 0x8736, 0xCE52, + 0x8737, 0xF2E9, 0x8738, 0xCE53, 0x8739, 0xCE54, 0x873A, 0xCE55, + 0x873B, 0xF2DF, 0x873C, 0xCE56, 0x873D, 0xCE57, 0x873E, 0xF2E4, + 0x873F, 0xF2EA, 0x8740, 0xCE58, 0x8741, 0xCE59, 0x8742, 0xCE5A, + 0x8743, 0xCE5B, 0x8744, 0xCE5C, 0x8745, 0xCE5D, 0x8746, 0xCE5E, + 0x8747, 0xD3AC, 0x8748, 0xF2E5, 0x8749, 0xB2F5, 0x874A, 0xCE5F, + 0x874B, 0xCE60, 0x874C, 0xF2F2, 0x874D, 0xCE61, 0x874E, 0xD0AB, + 0x874F, 0xCE62, 0x8750, 0xCE63, 0x8751, 0xCE64, 0x8752, 0xCE65, + 0x8753, 0xF2F5, 0x8754, 0xCE66, 0x8755, 0xCE67, 0x8756, 0xCE68, + 0x8757, 0xBBC8, 0x8758, 0xCE69, 0x8759, 0xF2F9, 0x875A, 0xCE6A, + 0x875B, 0xCE6B, 0x875C, 0xCE6C, 0x875D, 0xCE6D, 0x875E, 0xCE6E, + 0x875F, 0xCE6F, 0x8760, 0xF2F0, 0x8761, 0xCE70, 0x8762, 0xCE71, + 0x8763, 0xF2F6, 0x8764, 0xF2F8, 0x8765, 0xF2FA, 0x8766, 0xCE72, + 0x8767, 0xCE73, 0x8768, 0xCE74, 0x8769, 0xCE75, 0x876A, 0xCE76, + 0x876B, 0xCE77, 0x876C, 0xCE78, 0x876D, 0xCE79, 0x876E, 0xF2F3, + 0x876F, 0xCE7A, 0x8770, 0xF2F1, 0x8771, 0xCE7B, 0x8772, 0xCE7C, + 0x8773, 0xCE7D, 0x8774, 0xBAFB, 0x8775, 0xCE7E, 0x8776, 0xB5FB, + 0x8777, 0xCE80, 0x8778, 0xCE81, 0x8779, 0xCE82, 0x877A, 0xCE83, + 0x877B, 0xF2EF, 0x877C, 0xF2F7, 0x877D, 0xF2ED, 0x877E, 0xF2EE, + 0x877F, 0xCE84, 0x8780, 0xCE85, 0x8781, 0xCE86, 0x8782, 0xF2EB, + 0x8783, 0xF3A6, 0x8784, 0xCE87, 0x8785, 0xF3A3, 0x8786, 0xCE88, + 0x8787, 0xCE89, 0x8788, 0xF3A2, 0x8789, 0xCE8A, 0x878A, 0xCE8B, + 0x878B, 0xF2F4, 0x878C, 0xCE8C, 0x878D, 0xC8DA, 0x878E, 0xCE8D, + 0x878F, 0xCE8E, 0x8790, 0xCE8F, 0x8791, 0xCE90, 0x8792, 0xCE91, + 0x8793, 0xF2FB, 0x8794, 0xCE92, 0x8795, 0xCE93, 0x8796, 0xCE94, + 0x8797, 0xF3A5, 0x8798, 0xCE95, 0x8799, 0xCE96, 0x879A, 0xCE97, + 0x879B, 0xCE98, 0x879C, 0xCE99, 0x879D, 0xCE9A, 0x879E, 0xCE9B, + 0x879F, 0xC3F8, 0x87A0, 0xCE9C, 0x87A1, 0xCE9D, 0x87A2, 0xCE9E, + 0x87A3, 0xCE9F, 0x87A4, 0xCEA0, 0x87A5, 0xCF40, 0x87A6, 0xCF41, + 0x87A7, 0xCF42, 0x87A8, 0xF2FD, 0x87A9, 0xCF43, 0x87AA, 0xCF44, + 0x87AB, 0xF3A7, 0x87AC, 0xF3A9, 0x87AD, 0xF3A4, 0x87AE, 0xCF45, + 0x87AF, 0xF2FC, 0x87B0, 0xCF46, 0x87B1, 0xCF47, 0x87B2, 0xCF48, + 0x87B3, 0xF3AB, 0x87B4, 0xCF49, 0x87B5, 0xF3AA, 0x87B6, 0xCF4A, + 0x87B7, 0xCF4B, 0x87B8, 0xCF4C, 0x87B9, 0xCF4D, 0x87BA, 0xC2DD, + 0x87BB, 0xCF4E, 0x87BC, 0xCF4F, 0x87BD, 0xF3AE, 0x87BE, 0xCF50, + 0x87BF, 0xCF51, 0x87C0, 0xF3B0, 0x87C1, 0xCF52, 0x87C2, 0xCF53, + 0x87C3, 0xCF54, 0x87C4, 0xCF55, 0x87C5, 0xCF56, 0x87C6, 0xF3A1, + 0x87C7, 0xCF57, 0x87C8, 0xCF58, 0x87C9, 0xCF59, 0x87CA, 0xF3B1, + 0x87CB, 0xF3AC, 0x87CC, 0xCF5A, 0x87CD, 0xCF5B, 0x87CE, 0xCF5C, + 0x87CF, 0xCF5D, 0x87D0, 0xCF5E, 0x87D1, 0xF3AF, 0x87D2, 0xF2FE, + 0x87D3, 0xF3AD, 0x87D4, 0xCF5F, 0x87D5, 0xCF60, 0x87D6, 0xCF61, + 0x87D7, 0xCF62, 0x87D8, 0xCF63, 0x87D9, 0xCF64, 0x87DA, 0xCF65, + 0x87DB, 0xF3B2, 0x87DC, 0xCF66, 0x87DD, 0xCF67, 0x87DE, 0xCF68, + 0x87DF, 0xCF69, 0x87E0, 0xF3B4, 0x87E1, 0xCF6A, 0x87E2, 0xCF6B, + 0x87E3, 0xCF6C, 0x87E4, 0xCF6D, 0x87E5, 0xF3A8, 0x87E6, 0xCF6E, + 0x87E7, 0xCF6F, 0x87E8, 0xCF70, 0x87E9, 0xCF71, 0x87EA, 0xF3B3, + 0x87EB, 0xCF72, 0x87EC, 0xCF73, 0x87ED, 0xCF74, 0x87EE, 0xF3B5, + 0x87EF, 0xCF75, 0x87F0, 0xCF76, 0x87F1, 0xCF77, 0x87F2, 0xCF78, + 0x87F3, 0xCF79, 0x87F4, 0xCF7A, 0x87F5, 0xCF7B, 0x87F6, 0xCF7C, + 0x87F7, 0xCF7D, 0x87F8, 0xCF7E, 0x87F9, 0xD0B7, 0x87FA, 0xCF80, + 0x87FB, 0xCF81, 0x87FC, 0xCF82, 0x87FD, 0xCF83, 0x87FE, 0xF3B8, + 0x87FF, 0xCF84, 0x8800, 0xCF85, 0x8801, 0xCF86, 0x8802, 0xCF87, + 0x8803, 0xD9F9, 0x8804, 0xCF88, 0x8805, 0xCF89, 0x8806, 0xCF8A, + 0x8807, 0xCF8B, 0x8808, 0xCF8C, 0x8809, 0xCF8D, 0x880A, 0xF3B9, + 0x880B, 0xCF8E, 0x880C, 0xCF8F, 0x880D, 0xCF90, 0x880E, 0xCF91, + 0x880F, 0xCF92, 0x8810, 0xCF93, 0x8811, 0xCF94, 0x8812, 0xCF95, + 0x8813, 0xF3B7, 0x8814, 0xCF96, 0x8815, 0xC8E4, 0x8816, 0xF3B6, + 0x8817, 0xCF97, 0x8818, 0xCF98, 0x8819, 0xCF99, 0x881A, 0xCF9A, + 0x881B, 0xF3BA, 0x881C, 0xCF9B, 0x881D, 0xCF9C, 0x881E, 0xCF9D, + 0x881F, 0xCF9E, 0x8820, 0xCF9F, 0x8821, 0xF3BB, 0x8822, 0xB4C0, + 0x8823, 0xCFA0, 0x8824, 0xD040, 0x8825, 0xD041, 0x8826, 0xD042, + 0x8827, 0xD043, 0x8828, 0xD044, 0x8829, 0xD045, 0x882A, 0xD046, + 0x882B, 0xD047, 0x882C, 0xD048, 0x882D, 0xD049, 0x882E, 0xD04A, + 0x882F, 0xD04B, 0x8830, 0xD04C, 0x8831, 0xD04D, 0x8832, 0xEEC3, + 0x8833, 0xD04E, 0x8834, 0xD04F, 0x8835, 0xD050, 0x8836, 0xD051, + 0x8837, 0xD052, 0x8838, 0xD053, 0x8839, 0xF3BC, 0x883A, 0xD054, + 0x883B, 0xD055, 0x883C, 0xF3BD, 0x883D, 0xD056, 0x883E, 0xD057, + 0x883F, 0xD058, 0x8840, 0xD1AA, 0x8841, 0xD059, 0x8842, 0xD05A, + 0x8843, 0xD05B, 0x8844, 0xF4AC, 0x8845, 0xD0C6, 0x8846, 0xD05C, + 0x8847, 0xD05D, 0x8848, 0xD05E, 0x8849, 0xD05F, 0x884A, 0xD060, + 0x884B, 0xD061, 0x884C, 0xD0D0, 0x884D, 0xD1DC, 0x884E, 0xD062, + 0x884F, 0xD063, 0x8850, 0xD064, 0x8851, 0xD065, 0x8852, 0xD066, + 0x8853, 0xD067, 0x8854, 0xCFCE, 0x8855, 0xD068, 0x8856, 0xD069, + 0x8857, 0xBDD6, 0x8858, 0xD06A, 0x8859, 0xD1C3, 0x885A, 0xD06B, + 0x885B, 0xD06C, 0x885C, 0xD06D, 0x885D, 0xD06E, 0x885E, 0xD06F, + 0x885F, 0xD070, 0x8860, 0xD071, 0x8861, 0xBAE2, 0x8862, 0xE1E9, + 0x8863, 0xD2C2, 0x8864, 0xF1C2, 0x8865, 0xB2B9, 0x8866, 0xD072, + 0x8867, 0xD073, 0x8868, 0xB1ED, 0x8869, 0xF1C3, 0x886A, 0xD074, + 0x886B, 0xC9C0, 0x886C, 0xB3C4, 0x886D, 0xD075, 0x886E, 0xD9F2, + 0x886F, 0xD076, 0x8870, 0xCBA5, 0x8871, 0xD077, 0x8872, 0xF1C4, + 0x8873, 0xD078, 0x8874, 0xD079, 0x8875, 0xD07A, 0x8876, 0xD07B, + 0x8877, 0xD6D4, 0x8878, 0xD07C, 0x8879, 0xD07D, 0x887A, 0xD07E, + 0x887B, 0xD080, 0x887C, 0xD081, 0x887D, 0xF1C5, 0x887E, 0xF4C0, + 0x887F, 0xF1C6, 0x8880, 0xD082, 0x8881, 0xD4AC, 0x8882, 0xF1C7, + 0x8883, 0xD083, 0x8884, 0xB0C0, 0x8885, 0xF4C1, 0x8886, 0xD084, + 0x8887, 0xD085, 0x8888, 0xF4C2, 0x8889, 0xD086, 0x888A, 0xD087, + 0x888B, 0xB4FC, 0x888C, 0xD088, 0x888D, 0xC5DB, 0x888E, 0xD089, + 0x888F, 0xD08A, 0x8890, 0xD08B, 0x8891, 0xD08C, 0x8892, 0xCCBB, + 0x8893, 0xD08D, 0x8894, 0xD08E, 0x8895, 0xD08F, 0x8896, 0xD0E4, + 0x8897, 0xD090, 0x8898, 0xD091, 0x8899, 0xD092, 0x889A, 0xD093, + 0x889B, 0xD094, 0x889C, 0xCDE0, 0x889D, 0xD095, 0x889E, 0xD096, + 0x889F, 0xD097, 0x88A0, 0xD098, 0x88A1, 0xD099, 0x88A2, 0xF1C8, + 0x88A3, 0xD09A, 0x88A4, 0xD9F3, 0x88A5, 0xD09B, 0x88A6, 0xD09C, + 0x88A7, 0xD09D, 0x88A8, 0xD09E, 0x88A9, 0xD09F, 0x88AA, 0xD0A0, + 0x88AB, 0xB1BB, 0x88AC, 0xD140, 0x88AD, 0xCFAE, 0x88AE, 0xD141, + 0x88AF, 0xD142, 0x88B0, 0xD143, 0x88B1, 0xB8A4, 0x88B2, 0xD144, + 0x88B3, 0xD145, 0x88B4, 0xD146, 0x88B5, 0xD147, 0x88B6, 0xD148, + 0x88B7, 0xF1CA, 0x88B8, 0xD149, 0x88B9, 0xD14A, 0x88BA, 0xD14B, + 0x88BB, 0xD14C, 0x88BC, 0xF1CB, 0x88BD, 0xD14D, 0x88BE, 0xD14E, + 0x88BF, 0xD14F, 0x88C0, 0xD150, 0x88C1, 0xB2C3, 0x88C2, 0xC1D1, + 0x88C3, 0xD151, 0x88C4, 0xD152, 0x88C5, 0xD7B0, 0x88C6, 0xF1C9, + 0x88C7, 0xD153, 0x88C8, 0xD154, 0x88C9, 0xF1CC, 0x88CA, 0xD155, + 0x88CB, 0xD156, 0x88CC, 0xD157, 0x88CD, 0xD158, 0x88CE, 0xF1CE, + 0x88CF, 0xD159, 0x88D0, 0xD15A, 0x88D1, 0xD15B, 0x88D2, 0xD9F6, + 0x88D3, 0xD15C, 0x88D4, 0xD2E1, 0x88D5, 0xD4A3, 0x88D6, 0xD15D, + 0x88D7, 0xD15E, 0x88D8, 0xF4C3, 0x88D9, 0xC8B9, 0x88DA, 0xD15F, + 0x88DB, 0xD160, 0x88DC, 0xD161, 0x88DD, 0xD162, 0x88DE, 0xD163, + 0x88DF, 0xF4C4, 0x88E0, 0xD164, 0x88E1, 0xD165, 0x88E2, 0xF1CD, + 0x88E3, 0xF1CF, 0x88E4, 0xBFE3, 0x88E5, 0xF1D0, 0x88E6, 0xD166, + 0x88E7, 0xD167, 0x88E8, 0xF1D4, 0x88E9, 0xD168, 0x88EA, 0xD169, + 0x88EB, 0xD16A, 0x88EC, 0xD16B, 0x88ED, 0xD16C, 0x88EE, 0xD16D, + 0x88EF, 0xD16E, 0x88F0, 0xF1D6, 0x88F1, 0xF1D1, 0x88F2, 0xD16F, + 0x88F3, 0xC9D1, 0x88F4, 0xC5E1, 0x88F5, 0xD170, 0x88F6, 0xD171, + 0x88F7, 0xD172, 0x88F8, 0xC2E3, 0x88F9, 0xB9FC, 0x88FA, 0xD173, + 0x88FB, 0xD174, 0x88FC, 0xF1D3, 0x88FD, 0xD175, 0x88FE, 0xF1D5, + 0x88FF, 0xD176, 0x8900, 0xD177, 0x8901, 0xD178, 0x8902, 0xB9D3, + 0x8903, 0xD179, 0x8904, 0xD17A, 0x8905, 0xD17B, 0x8906, 0xD17C, + 0x8907, 0xD17D, 0x8908, 0xD17E, 0x8909, 0xD180, 0x890A, 0xF1DB, + 0x890B, 0xD181, 0x890C, 0xD182, 0x890D, 0xD183, 0x890E, 0xD184, + 0x890F, 0xD185, 0x8910, 0xBAD6, 0x8911, 0xD186, 0x8912, 0xB0FD, + 0x8913, 0xF1D9, 0x8914, 0xD187, 0x8915, 0xD188, 0x8916, 0xD189, + 0x8917, 0xD18A, 0x8918, 0xD18B, 0x8919, 0xF1D8, 0x891A, 0xF1D2, + 0x891B, 0xF1DA, 0x891C, 0xD18C, 0x891D, 0xD18D, 0x891E, 0xD18E, + 0x891F, 0xD18F, 0x8920, 0xD190, 0x8921, 0xF1D7, 0x8922, 0xD191, + 0x8923, 0xD192, 0x8924, 0xD193, 0x8925, 0xC8EC, 0x8926, 0xD194, + 0x8927, 0xD195, 0x8928, 0xD196, 0x8929, 0xD197, 0x892A, 0xCDCA, + 0x892B, 0xF1DD, 0x892C, 0xD198, 0x892D, 0xD199, 0x892E, 0xD19A, + 0x892F, 0xD19B, 0x8930, 0xE5BD, 0x8931, 0xD19C, 0x8932, 0xD19D, + 0x8933, 0xD19E, 0x8934, 0xF1DC, 0x8935, 0xD19F, 0x8936, 0xF1DE, + 0x8937, 0xD1A0, 0x8938, 0xD240, 0x8939, 0xD241, 0x893A, 0xD242, + 0x893B, 0xD243, 0x893C, 0xD244, 0x893D, 0xD245, 0x893E, 0xD246, + 0x893F, 0xD247, 0x8940, 0xD248, 0x8941, 0xF1DF, 0x8942, 0xD249, + 0x8943, 0xD24A, 0x8944, 0xCFE5, 0x8945, 0xD24B, 0x8946, 0xD24C, + 0x8947, 0xD24D, 0x8948, 0xD24E, 0x8949, 0xD24F, 0x894A, 0xD250, + 0x894B, 0xD251, 0x894C, 0xD252, 0x894D, 0xD253, 0x894E, 0xD254, + 0x894F, 0xD255, 0x8950, 0xD256, 0x8951, 0xD257, 0x8952, 0xD258, + 0x8953, 0xD259, 0x8954, 0xD25A, 0x8955, 0xD25B, 0x8956, 0xD25C, + 0x8957, 0xD25D, 0x8958, 0xD25E, 0x8959, 0xD25F, 0x895A, 0xD260, + 0x895B, 0xD261, 0x895C, 0xD262, 0x895D, 0xD263, 0x895E, 0xF4C5, + 0x895F, 0xBDF3, 0x8960, 0xD264, 0x8961, 0xD265, 0x8962, 0xD266, + 0x8963, 0xD267, 0x8964, 0xD268, 0x8965, 0xD269, 0x8966, 0xF1E0, + 0x8967, 0xD26A, 0x8968, 0xD26B, 0x8969, 0xD26C, 0x896A, 0xD26D, + 0x896B, 0xD26E, 0x896C, 0xD26F, 0x896D, 0xD270, 0x896E, 0xD271, + 0x896F, 0xD272, 0x8970, 0xD273, 0x8971, 0xD274, 0x8972, 0xD275, + 0x8973, 0xD276, 0x8974, 0xD277, 0x8975, 0xD278, 0x8976, 0xD279, + 0x8977, 0xD27A, 0x8978, 0xD27B, 0x8979, 0xD27C, 0x897A, 0xD27D, + 0x897B, 0xF1E1, 0x897C, 0xD27E, 0x897D, 0xD280, 0x897E, 0xD281, + 0x897F, 0xCEF7, 0x8980, 0xD282, 0x8981, 0xD2AA, 0x8982, 0xD283, + 0x8983, 0xF1FB, 0x8984, 0xD284, 0x8985, 0xD285, 0x8986, 0xB8B2, + 0x8987, 0xD286, 0x8988, 0xD287, 0x8989, 0xD288, 0x898A, 0xD289, + 0x898B, 0xD28A, 0x898C, 0xD28B, 0x898D, 0xD28C, 0x898E, 0xD28D, + 0x898F, 0xD28E, 0x8990, 0xD28F, 0x8991, 0xD290, 0x8992, 0xD291, + 0x8993, 0xD292, 0x8994, 0xD293, 0x8995, 0xD294, 0x8996, 0xD295, + 0x8997, 0xD296, 0x8998, 0xD297, 0x8999, 0xD298, 0x899A, 0xD299, + 0x899B, 0xD29A, 0x899C, 0xD29B, 0x899D, 0xD29C, 0x899E, 0xD29D, + 0x899F, 0xD29E, 0x89A0, 0xD29F, 0x89A1, 0xD2A0, 0x89A2, 0xD340, + 0x89A3, 0xD341, 0x89A4, 0xD342, 0x89A5, 0xD343, 0x89A6, 0xD344, + 0x89A7, 0xD345, 0x89A8, 0xD346, 0x89A9, 0xD347, 0x89AA, 0xD348, + 0x89AB, 0xD349, 0x89AC, 0xD34A, 0x89AD, 0xD34B, 0x89AE, 0xD34C, + 0x89AF, 0xD34D, 0x89B0, 0xD34E, 0x89B1, 0xD34F, 0x89B2, 0xD350, + 0x89B3, 0xD351, 0x89B4, 0xD352, 0x89B5, 0xD353, 0x89B6, 0xD354, + 0x89B7, 0xD355, 0x89B8, 0xD356, 0x89B9, 0xD357, 0x89BA, 0xD358, + 0x89BB, 0xD359, 0x89BC, 0xD35A, 0x89BD, 0xD35B, 0x89BE, 0xD35C, + 0x89BF, 0xD35D, 0x89C0, 0xD35E, 0x89C1, 0xBCFB, 0x89C2, 0xB9DB, + 0x89C3, 0xD35F, 0x89C4, 0xB9E6, 0x89C5, 0xC3D9, 0x89C6, 0xCAD3, + 0x89C7, 0xEAE8, 0x89C8, 0xC0C0, 0x89C9, 0xBEF5, 0x89CA, 0xEAE9, + 0x89CB, 0xEAEA, 0x89CC, 0xEAEB, 0x89CD, 0xD360, 0x89CE, 0xEAEC, + 0x89CF, 0xEAED, 0x89D0, 0xEAEE, 0x89D1, 0xEAEF, 0x89D2, 0xBDC7, + 0x89D3, 0xD361, 0x89D4, 0xD362, 0x89D5, 0xD363, 0x89D6, 0xF5FB, + 0x89D7, 0xD364, 0x89D8, 0xD365, 0x89D9, 0xD366, 0x89DA, 0xF5FD, + 0x89DB, 0xD367, 0x89DC, 0xF5FE, 0x89DD, 0xD368, 0x89DE, 0xF5FC, + 0x89DF, 0xD369, 0x89E0, 0xD36A, 0x89E1, 0xD36B, 0x89E2, 0xD36C, + 0x89E3, 0xBDE2, 0x89E4, 0xD36D, 0x89E5, 0xF6A1, 0x89E6, 0xB4A5, + 0x89E7, 0xD36E, 0x89E8, 0xD36F, 0x89E9, 0xD370, 0x89EA, 0xD371, + 0x89EB, 0xF6A2, 0x89EC, 0xD372, 0x89ED, 0xD373, 0x89EE, 0xD374, + 0x89EF, 0xF6A3, 0x89F0, 0xD375, 0x89F1, 0xD376, 0x89F2, 0xD377, + 0x89F3, 0xECB2, 0x89F4, 0xD378, 0x89F5, 0xD379, 0x89F6, 0xD37A, + 0x89F7, 0xD37B, 0x89F8, 0xD37C, 0x89F9, 0xD37D, 0x89FA, 0xD37E, + 0x89FB, 0xD380, 0x89FC, 0xD381, 0x89FD, 0xD382, 0x89FE, 0xD383, + 0x89FF, 0xD384, 0x8A00, 0xD1D4, 0x8A01, 0xD385, 0x8A02, 0xD386, + 0x8A03, 0xD387, 0x8A04, 0xD388, 0x8A05, 0xD389, 0x8A06, 0xD38A, + 0x8A07, 0xD9EA, 0x8A08, 0xD38B, 0x8A09, 0xD38C, 0x8A0A, 0xD38D, + 0x8A0B, 0xD38E, 0x8A0C, 0xD38F, 0x8A0D, 0xD390, 0x8A0E, 0xD391, + 0x8A0F, 0xD392, 0x8A10, 0xD393, 0x8A11, 0xD394, 0x8A12, 0xD395, + 0x8A13, 0xD396, 0x8A14, 0xD397, 0x8A15, 0xD398, 0x8A16, 0xD399, + 0x8A17, 0xD39A, 0x8A18, 0xD39B, 0x8A19, 0xD39C, 0x8A1A, 0xD39D, + 0x8A1B, 0xD39E, 0x8A1C, 0xD39F, 0x8A1D, 0xD3A0, 0x8A1E, 0xD440, + 0x8A1F, 0xD441, 0x8A20, 0xD442, 0x8A21, 0xD443, 0x8A22, 0xD444, + 0x8A23, 0xD445, 0x8A24, 0xD446, 0x8A25, 0xD447, 0x8A26, 0xD448, + 0x8A27, 0xD449, 0x8A28, 0xD44A, 0x8A29, 0xD44B, 0x8A2A, 0xD44C, + 0x8A2B, 0xD44D, 0x8A2C, 0xD44E, 0x8A2D, 0xD44F, 0x8A2E, 0xD450, + 0x8A2F, 0xD451, 0x8A30, 0xD452, 0x8A31, 0xD453, 0x8A32, 0xD454, + 0x8A33, 0xD455, 0x8A34, 0xD456, 0x8A35, 0xD457, 0x8A36, 0xD458, + 0x8A37, 0xD459, 0x8A38, 0xD45A, 0x8A39, 0xD45B, 0x8A3A, 0xD45C, + 0x8A3B, 0xD45D, 0x8A3C, 0xD45E, 0x8A3D, 0xD45F, 0x8A3E, 0xF6A4, + 0x8A3F, 0xD460, 0x8A40, 0xD461, 0x8A41, 0xD462, 0x8A42, 0xD463, + 0x8A43, 0xD464, 0x8A44, 0xD465, 0x8A45, 0xD466, 0x8A46, 0xD467, + 0x8A47, 0xD468, 0x8A48, 0xEEBA, 0x8A49, 0xD469, 0x8A4A, 0xD46A, + 0x8A4B, 0xD46B, 0x8A4C, 0xD46C, 0x8A4D, 0xD46D, 0x8A4E, 0xD46E, + 0x8A4F, 0xD46F, 0x8A50, 0xD470, 0x8A51, 0xD471, 0x8A52, 0xD472, + 0x8A53, 0xD473, 0x8A54, 0xD474, 0x8A55, 0xD475, 0x8A56, 0xD476, + 0x8A57, 0xD477, 0x8A58, 0xD478, 0x8A59, 0xD479, 0x8A5A, 0xD47A, + 0x8A5B, 0xD47B, 0x8A5C, 0xD47C, 0x8A5D, 0xD47D, 0x8A5E, 0xD47E, + 0x8A5F, 0xD480, 0x8A60, 0xD481, 0x8A61, 0xD482, 0x8A62, 0xD483, + 0x8A63, 0xD484, 0x8A64, 0xD485, 0x8A65, 0xD486, 0x8A66, 0xD487, + 0x8A67, 0xD488, 0x8A68, 0xD489, 0x8A69, 0xD48A, 0x8A6A, 0xD48B, + 0x8A6B, 0xD48C, 0x8A6C, 0xD48D, 0x8A6D, 0xD48E, 0x8A6E, 0xD48F, + 0x8A6F, 0xD490, 0x8A70, 0xD491, 0x8A71, 0xD492, 0x8A72, 0xD493, + 0x8A73, 0xD494, 0x8A74, 0xD495, 0x8A75, 0xD496, 0x8A76, 0xD497, + 0x8A77, 0xD498, 0x8A78, 0xD499, 0x8A79, 0xD5B2, 0x8A7A, 0xD49A, + 0x8A7B, 0xD49B, 0x8A7C, 0xD49C, 0x8A7D, 0xD49D, 0x8A7E, 0xD49E, + 0x8A7F, 0xD49F, 0x8A80, 0xD4A0, 0x8A81, 0xD540, 0x8A82, 0xD541, + 0x8A83, 0xD542, 0x8A84, 0xD543, 0x8A85, 0xD544, 0x8A86, 0xD545, + 0x8A87, 0xD546, 0x8A88, 0xD547, 0x8A89, 0xD3FE, 0x8A8A, 0xCCDC, + 0x8A8B, 0xD548, 0x8A8C, 0xD549, 0x8A8D, 0xD54A, 0x8A8E, 0xD54B, + 0x8A8F, 0xD54C, 0x8A90, 0xD54D, 0x8A91, 0xD54E, 0x8A92, 0xD54F, + 0x8A93, 0xCAC4, 0x8A94, 0xD550, 0x8A95, 0xD551, 0x8A96, 0xD552, + 0x8A97, 0xD553, 0x8A98, 0xD554, 0x8A99, 0xD555, 0x8A9A, 0xD556, + 0x8A9B, 0xD557, 0x8A9C, 0xD558, 0x8A9D, 0xD559, 0x8A9E, 0xD55A, + 0x8A9F, 0xD55B, 0x8AA0, 0xD55C, 0x8AA1, 0xD55D, 0x8AA2, 0xD55E, + 0x8AA3, 0xD55F, 0x8AA4, 0xD560, 0x8AA5, 0xD561, 0x8AA6, 0xD562, + 0x8AA7, 0xD563, 0x8AA8, 0xD564, 0x8AA9, 0xD565, 0x8AAA, 0xD566, + 0x8AAB, 0xD567, 0x8AAC, 0xD568, 0x8AAD, 0xD569, 0x8AAE, 0xD56A, + 0x8AAF, 0xD56B, 0x8AB0, 0xD56C, 0x8AB1, 0xD56D, 0x8AB2, 0xD56E, + 0x8AB3, 0xD56F, 0x8AB4, 0xD570, 0x8AB5, 0xD571, 0x8AB6, 0xD572, + 0x8AB7, 0xD573, 0x8AB8, 0xD574, 0x8AB9, 0xD575, 0x8ABA, 0xD576, + 0x8ABB, 0xD577, 0x8ABC, 0xD578, 0x8ABD, 0xD579, 0x8ABE, 0xD57A, + 0x8ABF, 0xD57B, 0x8AC0, 0xD57C, 0x8AC1, 0xD57D, 0x8AC2, 0xD57E, + 0x8AC3, 0xD580, 0x8AC4, 0xD581, 0x8AC5, 0xD582, 0x8AC6, 0xD583, + 0x8AC7, 0xD584, 0x8AC8, 0xD585, 0x8AC9, 0xD586, 0x8ACA, 0xD587, + 0x8ACB, 0xD588, 0x8ACC, 0xD589, 0x8ACD, 0xD58A, 0x8ACE, 0xD58B, + 0x8ACF, 0xD58C, 0x8AD0, 0xD58D, 0x8AD1, 0xD58E, 0x8AD2, 0xD58F, + 0x8AD3, 0xD590, 0x8AD4, 0xD591, 0x8AD5, 0xD592, 0x8AD6, 0xD593, + 0x8AD7, 0xD594, 0x8AD8, 0xD595, 0x8AD9, 0xD596, 0x8ADA, 0xD597, + 0x8ADB, 0xD598, 0x8ADC, 0xD599, 0x8ADD, 0xD59A, 0x8ADE, 0xD59B, + 0x8ADF, 0xD59C, 0x8AE0, 0xD59D, 0x8AE1, 0xD59E, 0x8AE2, 0xD59F, + 0x8AE3, 0xD5A0, 0x8AE4, 0xD640, 0x8AE5, 0xD641, 0x8AE6, 0xD642, + 0x8AE7, 0xD643, 0x8AE8, 0xD644, 0x8AE9, 0xD645, 0x8AEA, 0xD646, + 0x8AEB, 0xD647, 0x8AEC, 0xD648, 0x8AED, 0xD649, 0x8AEE, 0xD64A, + 0x8AEF, 0xD64B, 0x8AF0, 0xD64C, 0x8AF1, 0xD64D, 0x8AF2, 0xD64E, + 0x8AF3, 0xD64F, 0x8AF4, 0xD650, 0x8AF5, 0xD651, 0x8AF6, 0xD652, + 0x8AF7, 0xD653, 0x8AF8, 0xD654, 0x8AF9, 0xD655, 0x8AFA, 0xD656, + 0x8AFB, 0xD657, 0x8AFC, 0xD658, 0x8AFD, 0xD659, 0x8AFE, 0xD65A, + 0x8AFF, 0xD65B, 0x8B00, 0xD65C, 0x8B01, 0xD65D, 0x8B02, 0xD65E, + 0x8B03, 0xD65F, 0x8B04, 0xD660, 0x8B05, 0xD661, 0x8B06, 0xD662, + 0x8B07, 0xE5C0, 0x8B08, 0xD663, 0x8B09, 0xD664, 0x8B0A, 0xD665, + 0x8B0B, 0xD666, 0x8B0C, 0xD667, 0x8B0D, 0xD668, 0x8B0E, 0xD669, + 0x8B0F, 0xD66A, 0x8B10, 0xD66B, 0x8B11, 0xD66C, 0x8B12, 0xD66D, + 0x8B13, 0xD66E, 0x8B14, 0xD66F, 0x8B15, 0xD670, 0x8B16, 0xD671, + 0x8B17, 0xD672, 0x8B18, 0xD673, 0x8B19, 0xD674, 0x8B1A, 0xD675, + 0x8B1B, 0xD676, 0x8B1C, 0xD677, 0x8B1D, 0xD678, 0x8B1E, 0xD679, + 0x8B1F, 0xD67A, 0x8B20, 0xD67B, 0x8B21, 0xD67C, 0x8B22, 0xD67D, + 0x8B23, 0xD67E, 0x8B24, 0xD680, 0x8B25, 0xD681, 0x8B26, 0xF6A5, + 0x8B27, 0xD682, 0x8B28, 0xD683, 0x8B29, 0xD684, 0x8B2A, 0xD685, + 0x8B2B, 0xD686, 0x8B2C, 0xD687, 0x8B2D, 0xD688, 0x8B2E, 0xD689, + 0x8B2F, 0xD68A, 0x8B30, 0xD68B, 0x8B31, 0xD68C, 0x8B32, 0xD68D, + 0x8B33, 0xD68E, 0x8B34, 0xD68F, 0x8B35, 0xD690, 0x8B36, 0xD691, + 0x8B37, 0xD692, 0x8B38, 0xD693, 0x8B39, 0xD694, 0x8B3A, 0xD695, + 0x8B3B, 0xD696, 0x8B3C, 0xD697, 0x8B3D, 0xD698, 0x8B3E, 0xD699, + 0x8B3F, 0xD69A, 0x8B40, 0xD69B, 0x8B41, 0xD69C, 0x8B42, 0xD69D, + 0x8B43, 0xD69E, 0x8B44, 0xD69F, 0x8B45, 0xD6A0, 0x8B46, 0xD740, + 0x8B47, 0xD741, 0x8B48, 0xD742, 0x8B49, 0xD743, 0x8B4A, 0xD744, + 0x8B4B, 0xD745, 0x8B4C, 0xD746, 0x8B4D, 0xD747, 0x8B4E, 0xD748, + 0x8B4F, 0xD749, 0x8B50, 0xD74A, 0x8B51, 0xD74B, 0x8B52, 0xD74C, + 0x8B53, 0xD74D, 0x8B54, 0xD74E, 0x8B55, 0xD74F, 0x8B56, 0xD750, + 0x8B57, 0xD751, 0x8B58, 0xD752, 0x8B59, 0xD753, 0x8B5A, 0xD754, + 0x8B5B, 0xD755, 0x8B5C, 0xD756, 0x8B5D, 0xD757, 0x8B5E, 0xD758, + 0x8B5F, 0xD759, 0x8B60, 0xD75A, 0x8B61, 0xD75B, 0x8B62, 0xD75C, + 0x8B63, 0xD75D, 0x8B64, 0xD75E, 0x8B65, 0xD75F, 0x8B66, 0xBEAF, + 0x8B67, 0xD760, 0x8B68, 0xD761, 0x8B69, 0xD762, 0x8B6A, 0xD763, + 0x8B6B, 0xD764, 0x8B6C, 0xC6A9, 0x8B6D, 0xD765, 0x8B6E, 0xD766, + 0x8B6F, 0xD767, 0x8B70, 0xD768, 0x8B71, 0xD769, 0x8B72, 0xD76A, + 0x8B73, 0xD76B, 0x8B74, 0xD76C, 0x8B75, 0xD76D, 0x8B76, 0xD76E, + 0x8B77, 0xD76F, 0x8B78, 0xD770, 0x8B79, 0xD771, 0x8B7A, 0xD772, + 0x8B7B, 0xD773, 0x8B7C, 0xD774, 0x8B7D, 0xD775, 0x8B7E, 0xD776, + 0x8B7F, 0xD777, 0x8B80, 0xD778, 0x8B81, 0xD779, 0x8B82, 0xD77A, + 0x8B83, 0xD77B, 0x8B84, 0xD77C, 0x8B85, 0xD77D, 0x8B86, 0xD77E, + 0x8B87, 0xD780, 0x8B88, 0xD781, 0x8B89, 0xD782, 0x8B8A, 0xD783, + 0x8B8B, 0xD784, 0x8B8C, 0xD785, 0x8B8D, 0xD786, 0x8B8E, 0xD787, + 0x8B8F, 0xD788, 0x8B90, 0xD789, 0x8B91, 0xD78A, 0x8B92, 0xD78B, + 0x8B93, 0xD78C, 0x8B94, 0xD78D, 0x8B95, 0xD78E, 0x8B96, 0xD78F, + 0x8B97, 0xD790, 0x8B98, 0xD791, 0x8B99, 0xD792, 0x8B9A, 0xD793, + 0x8B9B, 0xD794, 0x8B9C, 0xD795, 0x8B9D, 0xD796, 0x8B9E, 0xD797, + 0x8B9F, 0xD798, 0x8BA0, 0xDAA5, 0x8BA1, 0xBCC6, 0x8BA2, 0xB6A9, + 0x8BA3, 0xB8BC, 0x8BA4, 0xC8CF, 0x8BA5, 0xBCA5, 0x8BA6, 0xDAA6, + 0x8BA7, 0xDAA7, 0x8BA8, 0xCCD6, 0x8BA9, 0xC8C3, 0x8BAA, 0xDAA8, + 0x8BAB, 0xC6FD, 0x8BAC, 0xD799, 0x8BAD, 0xD1B5, 0x8BAE, 0xD2E9, + 0x8BAF, 0xD1B6, 0x8BB0, 0xBCC7, 0x8BB1, 0xD79A, 0x8BB2, 0xBDB2, + 0x8BB3, 0xBBE4, 0x8BB4, 0xDAA9, 0x8BB5, 0xDAAA, 0x8BB6, 0xD1C8, + 0x8BB7, 0xDAAB, 0x8BB8, 0xD0ED, 0x8BB9, 0xB6EF, 0x8BBA, 0xC2DB, + 0x8BBB, 0xD79B, 0x8BBC, 0xCBCF, 0x8BBD, 0xB7ED, 0x8BBE, 0xC9E8, + 0x8BBF, 0xB7C3, 0x8BC0, 0xBEF7, 0x8BC1, 0xD6A4, 0x8BC2, 0xDAAC, + 0x8BC3, 0xDAAD, 0x8BC4, 0xC6C0, 0x8BC5, 0xD7E7, 0x8BC6, 0xCAB6, + 0x8BC7, 0xD79C, 0x8BC8, 0xD5A9, 0x8BC9, 0xCBDF, 0x8BCA, 0xD5EF, + 0x8BCB, 0xDAAE, 0x8BCC, 0xD6DF, 0x8BCD, 0xB4CA, 0x8BCE, 0xDAB0, + 0x8BCF, 0xDAAF, 0x8BD0, 0xD79D, 0x8BD1, 0xD2EB, 0x8BD2, 0xDAB1, + 0x8BD3, 0xDAB2, 0x8BD4, 0xDAB3, 0x8BD5, 0xCAD4, 0x8BD6, 0xDAB4, + 0x8BD7, 0xCAAB, 0x8BD8, 0xDAB5, 0x8BD9, 0xDAB6, 0x8BDA, 0xB3CF, + 0x8BDB, 0xD6EF, 0x8BDC, 0xDAB7, 0x8BDD, 0xBBB0, 0x8BDE, 0xB5AE, + 0x8BDF, 0xDAB8, 0x8BE0, 0xDAB9, 0x8BE1, 0xB9EE, 0x8BE2, 0xD1AF, + 0x8BE3, 0xD2E8, 0x8BE4, 0xDABA, 0x8BE5, 0xB8C3, 0x8BE6, 0xCFEA, + 0x8BE7, 0xB2EF, 0x8BE8, 0xDABB, 0x8BE9, 0xDABC, 0x8BEA, 0xD79E, + 0x8BEB, 0xBDEB, 0x8BEC, 0xCEDC, 0x8BED, 0xD3EF, 0x8BEE, 0xDABD, + 0x8BEF, 0xCEF3, 0x8BF0, 0xDABE, 0x8BF1, 0xD3D5, 0x8BF2, 0xBBE5, + 0x8BF3, 0xDABF, 0x8BF4, 0xCBB5, 0x8BF5, 0xCBD0, 0x8BF6, 0xDAC0, + 0x8BF7, 0xC7EB, 0x8BF8, 0xD6EE, 0x8BF9, 0xDAC1, 0x8BFA, 0xC5B5, + 0x8BFB, 0xB6C1, 0x8BFC, 0xDAC2, 0x8BFD, 0xB7CC, 0x8BFE, 0xBFCE, + 0x8BFF, 0xDAC3, 0x8C00, 0xDAC4, 0x8C01, 0xCBAD, 0x8C02, 0xDAC5, + 0x8C03, 0xB5F7, 0x8C04, 0xDAC6, 0x8C05, 0xC1C2, 0x8C06, 0xD7BB, + 0x8C07, 0xDAC7, 0x8C08, 0xCCB8, 0x8C09, 0xD79F, 0x8C0A, 0xD2EA, + 0x8C0B, 0xC4B1, 0x8C0C, 0xDAC8, 0x8C0D, 0xB5FD, 0x8C0E, 0xBBD1, + 0x8C0F, 0xDAC9, 0x8C10, 0xD0B3, 0x8C11, 0xDACA, 0x8C12, 0xDACB, + 0x8C13, 0xCEBD, 0x8C14, 0xDACC, 0x8C15, 0xDACD, 0x8C16, 0xDACE, + 0x8C17, 0xB2F7, 0x8C18, 0xDAD1, 0x8C19, 0xDACF, 0x8C1A, 0xD1E8, + 0x8C1B, 0xDAD0, 0x8C1C, 0xC3D5, 0x8C1D, 0xDAD2, 0x8C1E, 0xD7A0, + 0x8C1F, 0xDAD3, 0x8C20, 0xDAD4, 0x8C21, 0xDAD5, 0x8C22, 0xD0BB, + 0x8C23, 0xD2A5, 0x8C24, 0xB0F9, 0x8C25, 0xDAD6, 0x8C26, 0xC7AB, + 0x8C27, 0xDAD7, 0x8C28, 0xBDF7, 0x8C29, 0xC3A1, 0x8C2A, 0xDAD8, + 0x8C2B, 0xDAD9, 0x8C2C, 0xC3FD, 0x8C2D, 0xCCB7, 0x8C2E, 0xDADA, + 0x8C2F, 0xDADB, 0x8C30, 0xC0BE, 0x8C31, 0xC6D7, 0x8C32, 0xDADC, + 0x8C33, 0xDADD, 0x8C34, 0xC7B4, 0x8C35, 0xDADE, 0x8C36, 0xDADF, + 0x8C37, 0xB9C8, 0x8C38, 0xD840, 0x8C39, 0xD841, 0x8C3A, 0xD842, + 0x8C3B, 0xD843, 0x8C3C, 0xD844, 0x8C3D, 0xD845, 0x8C3E, 0xD846, + 0x8C3F, 0xD847, 0x8C40, 0xD848, 0x8C41, 0xBBED, 0x8C42, 0xD849, + 0x8C43, 0xD84A, 0x8C44, 0xD84B, 0x8C45, 0xD84C, 0x8C46, 0xB6B9, + 0x8C47, 0xF4F8, 0x8C48, 0xD84D, 0x8C49, 0xF4F9, 0x8C4A, 0xD84E, + 0x8C4B, 0xD84F, 0x8C4C, 0xCDE3, 0x8C4D, 0xD850, 0x8C4E, 0xD851, + 0x8C4F, 0xD852, 0x8C50, 0xD853, 0x8C51, 0xD854, 0x8C52, 0xD855, + 0x8C53, 0xD856, 0x8C54, 0xD857, 0x8C55, 0xF5B9, 0x8C56, 0xD858, + 0x8C57, 0xD859, 0x8C58, 0xD85A, 0x8C59, 0xD85B, 0x8C5A, 0xEBE0, + 0x8C5B, 0xD85C, 0x8C5C, 0xD85D, 0x8C5D, 0xD85E, 0x8C5E, 0xD85F, + 0x8C5F, 0xD860, 0x8C60, 0xD861, 0x8C61, 0xCFF3, 0x8C62, 0xBBBF, + 0x8C63, 0xD862, 0x8C64, 0xD863, 0x8C65, 0xD864, 0x8C66, 0xD865, + 0x8C67, 0xD866, 0x8C68, 0xD867, 0x8C69, 0xD868, 0x8C6A, 0xBAC0, + 0x8C6B, 0xD4A5, 0x8C6C, 0xD869, 0x8C6D, 0xD86A, 0x8C6E, 0xD86B, + 0x8C6F, 0xD86C, 0x8C70, 0xD86D, 0x8C71, 0xD86E, 0x8C72, 0xD86F, + 0x8C73, 0xE1D9, 0x8C74, 0xD870, 0x8C75, 0xD871, 0x8C76, 0xD872, + 0x8C77, 0xD873, 0x8C78, 0xF5F4, 0x8C79, 0xB1AA, 0x8C7A, 0xB2F2, + 0x8C7B, 0xD874, 0x8C7C, 0xD875, 0x8C7D, 0xD876, 0x8C7E, 0xD877, + 0x8C7F, 0xD878, 0x8C80, 0xD879, 0x8C81, 0xD87A, 0x8C82, 0xF5F5, + 0x8C83, 0xD87B, 0x8C84, 0xD87C, 0x8C85, 0xF5F7, 0x8C86, 0xD87D, + 0x8C87, 0xD87E, 0x8C88, 0xD880, 0x8C89, 0xBAD1, 0x8C8A, 0xF5F6, + 0x8C8B, 0xD881, 0x8C8C, 0xC3B2, 0x8C8D, 0xD882, 0x8C8E, 0xD883, + 0x8C8F, 0xD884, 0x8C90, 0xD885, 0x8C91, 0xD886, 0x8C92, 0xD887, + 0x8C93, 0xD888, 0x8C94, 0xF5F9, 0x8C95, 0xD889, 0x8C96, 0xD88A, + 0x8C97, 0xD88B, 0x8C98, 0xF5F8, 0x8C99, 0xD88C, 0x8C9A, 0xD88D, + 0x8C9B, 0xD88E, 0x8C9C, 0xD88F, 0x8C9D, 0xD890, 0x8C9E, 0xD891, + 0x8C9F, 0xD892, 0x8CA0, 0xD893, 0x8CA1, 0xD894, 0x8CA2, 0xD895, + 0x8CA3, 0xD896, 0x8CA4, 0xD897, 0x8CA5, 0xD898, 0x8CA6, 0xD899, + 0x8CA7, 0xD89A, 0x8CA8, 0xD89B, 0x8CA9, 0xD89C, 0x8CAA, 0xD89D, + 0x8CAB, 0xD89E, 0x8CAC, 0xD89F, 0x8CAD, 0xD8A0, 0x8CAE, 0xD940, + 0x8CAF, 0xD941, 0x8CB0, 0xD942, 0x8CB1, 0xD943, 0x8CB2, 0xD944, + 0x8CB3, 0xD945, 0x8CB4, 0xD946, 0x8CB5, 0xD947, 0x8CB6, 0xD948, + 0x8CB7, 0xD949, 0x8CB8, 0xD94A, 0x8CB9, 0xD94B, 0x8CBA, 0xD94C, + 0x8CBB, 0xD94D, 0x8CBC, 0xD94E, 0x8CBD, 0xD94F, 0x8CBE, 0xD950, + 0x8CBF, 0xD951, 0x8CC0, 0xD952, 0x8CC1, 0xD953, 0x8CC2, 0xD954, + 0x8CC3, 0xD955, 0x8CC4, 0xD956, 0x8CC5, 0xD957, 0x8CC6, 0xD958, + 0x8CC7, 0xD959, 0x8CC8, 0xD95A, 0x8CC9, 0xD95B, 0x8CCA, 0xD95C, + 0x8CCB, 0xD95D, 0x8CCC, 0xD95E, 0x8CCD, 0xD95F, 0x8CCE, 0xD960, + 0x8CCF, 0xD961, 0x8CD0, 0xD962, 0x8CD1, 0xD963, 0x8CD2, 0xD964, + 0x8CD3, 0xD965, 0x8CD4, 0xD966, 0x8CD5, 0xD967, 0x8CD6, 0xD968, + 0x8CD7, 0xD969, 0x8CD8, 0xD96A, 0x8CD9, 0xD96B, 0x8CDA, 0xD96C, + 0x8CDB, 0xD96D, 0x8CDC, 0xD96E, 0x8CDD, 0xD96F, 0x8CDE, 0xD970, + 0x8CDF, 0xD971, 0x8CE0, 0xD972, 0x8CE1, 0xD973, 0x8CE2, 0xD974, + 0x8CE3, 0xD975, 0x8CE4, 0xD976, 0x8CE5, 0xD977, 0x8CE6, 0xD978, + 0x8CE7, 0xD979, 0x8CE8, 0xD97A, 0x8CE9, 0xD97B, 0x8CEA, 0xD97C, + 0x8CEB, 0xD97D, 0x8CEC, 0xD97E, 0x8CED, 0xD980, 0x8CEE, 0xD981, + 0x8CEF, 0xD982, 0x8CF0, 0xD983, 0x8CF1, 0xD984, 0x8CF2, 0xD985, + 0x8CF3, 0xD986, 0x8CF4, 0xD987, 0x8CF5, 0xD988, 0x8CF6, 0xD989, + 0x8CF7, 0xD98A, 0x8CF8, 0xD98B, 0x8CF9, 0xD98C, 0x8CFA, 0xD98D, + 0x8CFB, 0xD98E, 0x8CFC, 0xD98F, 0x8CFD, 0xD990, 0x8CFE, 0xD991, + 0x8CFF, 0xD992, 0x8D00, 0xD993, 0x8D01, 0xD994, 0x8D02, 0xD995, + 0x8D03, 0xD996, 0x8D04, 0xD997, 0x8D05, 0xD998, 0x8D06, 0xD999, + 0x8D07, 0xD99A, 0x8D08, 0xD99B, 0x8D09, 0xD99C, 0x8D0A, 0xD99D, + 0x8D0B, 0xD99E, 0x8D0C, 0xD99F, 0x8D0D, 0xD9A0, 0x8D0E, 0xDA40, + 0x8D0F, 0xDA41, 0x8D10, 0xDA42, 0x8D11, 0xDA43, 0x8D12, 0xDA44, + 0x8D13, 0xDA45, 0x8D14, 0xDA46, 0x8D15, 0xDA47, 0x8D16, 0xDA48, + 0x8D17, 0xDA49, 0x8D18, 0xDA4A, 0x8D19, 0xDA4B, 0x8D1A, 0xDA4C, + 0x8D1B, 0xDA4D, 0x8D1C, 0xDA4E, 0x8D1D, 0xB1B4, 0x8D1E, 0xD5EA, + 0x8D1F, 0xB8BA, 0x8D20, 0xDA4F, 0x8D21, 0xB9B1, 0x8D22, 0xB2C6, + 0x8D23, 0xD4F0, 0x8D24, 0xCFCD, 0x8D25, 0xB0DC, 0x8D26, 0xD5CB, + 0x8D27, 0xBBF5, 0x8D28, 0xD6CA, 0x8D29, 0xB7B7, 0x8D2A, 0xCCB0, + 0x8D2B, 0xC6B6, 0x8D2C, 0xB1E1, 0x8D2D, 0xB9BA, 0x8D2E, 0xD6FC, + 0x8D2F, 0xB9E1, 0x8D30, 0xB7A1, 0x8D31, 0xBCFA, 0x8D32, 0xEADA, + 0x8D33, 0xEADB, 0x8D34, 0xCCF9, 0x8D35, 0xB9F3, 0x8D36, 0xEADC, + 0x8D37, 0xB4FB, 0x8D38, 0xC3B3, 0x8D39, 0xB7D1, 0x8D3A, 0xBAD8, + 0x8D3B, 0xEADD, 0x8D3C, 0xD4F4, 0x8D3D, 0xEADE, 0x8D3E, 0xBCD6, + 0x8D3F, 0xBBDF, 0x8D40, 0xEADF, 0x8D41, 0xC1DE, 0x8D42, 0xC2B8, + 0x8D43, 0xD4DF, 0x8D44, 0xD7CA, 0x8D45, 0xEAE0, 0x8D46, 0xEAE1, + 0x8D47, 0xEAE4, 0x8D48, 0xEAE2, 0x8D49, 0xEAE3, 0x8D4A, 0xC9DE, + 0x8D4B, 0xB8B3, 0x8D4C, 0xB6C4, 0x8D4D, 0xEAE5, 0x8D4E, 0xCAEA, + 0x8D4F, 0xC9CD, 0x8D50, 0xB4CD, 0x8D51, 0xDA50, 0x8D52, 0xDA51, + 0x8D53, 0xE2D9, 0x8D54, 0xC5E2, 0x8D55, 0xEAE6, 0x8D56, 0xC0B5, + 0x8D57, 0xDA52, 0x8D58, 0xD7B8, 0x8D59, 0xEAE7, 0x8D5A, 0xD7AC, + 0x8D5B, 0xC8FC, 0x8D5C, 0xD8D3, 0x8D5D, 0xD8CD, 0x8D5E, 0xD4DE, + 0x8D5F, 0xDA53, 0x8D60, 0xD4F9, 0x8D61, 0xC9C4, 0x8D62, 0xD3AE, + 0x8D63, 0xB8D3, 0x8D64, 0xB3E0, 0x8D65, 0xDA54, 0x8D66, 0xC9E2, + 0x8D67, 0xF4F6, 0x8D68, 0xDA55, 0x8D69, 0xDA56, 0x8D6A, 0xDA57, + 0x8D6B, 0xBAD5, 0x8D6C, 0xDA58, 0x8D6D, 0xF4F7, 0x8D6E, 0xDA59, + 0x8D6F, 0xDA5A, 0x8D70, 0xD7DF, 0x8D71, 0xDA5B, 0x8D72, 0xDA5C, + 0x8D73, 0xF4F1, 0x8D74, 0xB8B0, 0x8D75, 0xD5D4, 0x8D76, 0xB8CF, + 0x8D77, 0xC6F0, 0x8D78, 0xDA5D, 0x8D79, 0xDA5E, 0x8D7A, 0xDA5F, + 0x8D7B, 0xDA60, 0x8D7C, 0xDA61, 0x8D7D, 0xDA62, 0x8D7E, 0xDA63, + 0x8D7F, 0xDA64, 0x8D80, 0xDA65, 0x8D81, 0xB3C3, 0x8D82, 0xDA66, + 0x8D83, 0xDA67, 0x8D84, 0xF4F2, 0x8D85, 0xB3AC, 0x8D86, 0xDA68, + 0x8D87, 0xDA69, 0x8D88, 0xDA6A, 0x8D89, 0xDA6B, 0x8D8A, 0xD4BD, + 0x8D8B, 0xC7F7, 0x8D8C, 0xDA6C, 0x8D8D, 0xDA6D, 0x8D8E, 0xDA6E, + 0x8D8F, 0xDA6F, 0x8D90, 0xDA70, 0x8D91, 0xF4F4, 0x8D92, 0xDA71, + 0x8D93, 0xDA72, 0x8D94, 0xF4F3, 0x8D95, 0xDA73, 0x8D96, 0xDA74, + 0x8D97, 0xDA75, 0x8D98, 0xDA76, 0x8D99, 0xDA77, 0x8D9A, 0xDA78, + 0x8D9B, 0xDA79, 0x8D9C, 0xDA7A, 0x8D9D, 0xDA7B, 0x8D9E, 0xDA7C, + 0x8D9F, 0xCCCB, 0x8DA0, 0xDA7D, 0x8DA1, 0xDA7E, 0x8DA2, 0xDA80, + 0x8DA3, 0xC8A4, 0x8DA4, 0xDA81, 0x8DA5, 0xDA82, 0x8DA6, 0xDA83, + 0x8DA7, 0xDA84, 0x8DA8, 0xDA85, 0x8DA9, 0xDA86, 0x8DAA, 0xDA87, + 0x8DAB, 0xDA88, 0x8DAC, 0xDA89, 0x8DAD, 0xDA8A, 0x8DAE, 0xDA8B, + 0x8DAF, 0xDA8C, 0x8DB0, 0xDA8D, 0x8DB1, 0xF4F5, 0x8DB2, 0xDA8E, + 0x8DB3, 0xD7E3, 0x8DB4, 0xC5BF, 0x8DB5, 0xF5C0, 0x8DB6, 0xDA8F, + 0x8DB7, 0xDA90, 0x8DB8, 0xF5BB, 0x8DB9, 0xDA91, 0x8DBA, 0xF5C3, + 0x8DBB, 0xDA92, 0x8DBC, 0xF5C2, 0x8DBD, 0xDA93, 0x8DBE, 0xD6BA, + 0x8DBF, 0xF5C1, 0x8DC0, 0xDA94, 0x8DC1, 0xDA95, 0x8DC2, 0xDA96, + 0x8DC3, 0xD4BE, 0x8DC4, 0xF5C4, 0x8DC5, 0xDA97, 0x8DC6, 0xF5CC, + 0x8DC7, 0xDA98, 0x8DC8, 0xDA99, 0x8DC9, 0xDA9A, 0x8DCA, 0xDA9B, + 0x8DCB, 0xB0CF, 0x8DCC, 0xB5F8, 0x8DCD, 0xDA9C, 0x8DCE, 0xF5C9, + 0x8DCF, 0xF5CA, 0x8DD0, 0xDA9D, 0x8DD1, 0xC5DC, 0x8DD2, 0xDA9E, + 0x8DD3, 0xDA9F, 0x8DD4, 0xDAA0, 0x8DD5, 0xDB40, 0x8DD6, 0xF5C5, + 0x8DD7, 0xF5C6, 0x8DD8, 0xDB41, 0x8DD9, 0xDB42, 0x8DDA, 0xF5C7, + 0x8DDB, 0xF5CB, 0x8DDC, 0xDB43, 0x8DDD, 0xBEE0, 0x8DDE, 0xF5C8, + 0x8DDF, 0xB8FA, 0x8DE0, 0xDB44, 0x8DE1, 0xDB45, 0x8DE2, 0xDB46, + 0x8DE3, 0xF5D0, 0x8DE4, 0xF5D3, 0x8DE5, 0xDB47, 0x8DE6, 0xDB48, + 0x8DE7, 0xDB49, 0x8DE8, 0xBFE7, 0x8DE9, 0xDB4A, 0x8DEA, 0xB9F2, + 0x8DEB, 0xF5BC, 0x8DEC, 0xF5CD, 0x8DED, 0xDB4B, 0x8DEE, 0xDB4C, + 0x8DEF, 0xC2B7, 0x8DF0, 0xDB4D, 0x8DF1, 0xDB4E, 0x8DF2, 0xDB4F, + 0x8DF3, 0xCCF8, 0x8DF4, 0xDB50, 0x8DF5, 0xBCF9, 0x8DF6, 0xDB51, + 0x8DF7, 0xF5CE, 0x8DF8, 0xF5CF, 0x8DF9, 0xF5D1, 0x8DFA, 0xB6E5, + 0x8DFB, 0xF5D2, 0x8DFC, 0xDB52, 0x8DFD, 0xF5D5, 0x8DFE, 0xDB53, + 0x8DFF, 0xDB54, 0x8E00, 0xDB55, 0x8E01, 0xDB56, 0x8E02, 0xDB57, + 0x8E03, 0xDB58, 0x8E04, 0xDB59, 0x8E05, 0xF5BD, 0x8E06, 0xDB5A, + 0x8E07, 0xDB5B, 0x8E08, 0xDB5C, 0x8E09, 0xF5D4, 0x8E0A, 0xD3BB, + 0x8E0B, 0xDB5D, 0x8E0C, 0xB3EC, 0x8E0D, 0xDB5E, 0x8E0E, 0xDB5F, + 0x8E0F, 0xCCA4, 0x8E10, 0xDB60, 0x8E11, 0xDB61, 0x8E12, 0xDB62, + 0x8E13, 0xDB63, 0x8E14, 0xF5D6, 0x8E15, 0xDB64, 0x8E16, 0xDB65, + 0x8E17, 0xDB66, 0x8E18, 0xDB67, 0x8E19, 0xDB68, 0x8E1A, 0xDB69, + 0x8E1B, 0xDB6A, 0x8E1C, 0xDB6B, 0x8E1D, 0xF5D7, 0x8E1E, 0xBEE1, + 0x8E1F, 0xF5D8, 0x8E20, 0xDB6C, 0x8E21, 0xDB6D, 0x8E22, 0xCCDF, + 0x8E23, 0xF5DB, 0x8E24, 0xDB6E, 0x8E25, 0xDB6F, 0x8E26, 0xDB70, + 0x8E27, 0xDB71, 0x8E28, 0xDB72, 0x8E29, 0xB2C8, 0x8E2A, 0xD7D9, + 0x8E2B, 0xDB73, 0x8E2C, 0xF5D9, 0x8E2D, 0xDB74, 0x8E2E, 0xF5DA, + 0x8E2F, 0xF5DC, 0x8E30, 0xDB75, 0x8E31, 0xF5E2, 0x8E32, 0xDB76, + 0x8E33, 0xDB77, 0x8E34, 0xDB78, 0x8E35, 0xF5E0, 0x8E36, 0xDB79, + 0x8E37, 0xDB7A, 0x8E38, 0xDB7B, 0x8E39, 0xF5DF, 0x8E3A, 0xF5DD, + 0x8E3B, 0xDB7C, 0x8E3C, 0xDB7D, 0x8E3D, 0xF5E1, 0x8E3E, 0xDB7E, + 0x8E3F, 0xDB80, 0x8E40, 0xF5DE, 0x8E41, 0xF5E4, 0x8E42, 0xF5E5, + 0x8E43, 0xDB81, 0x8E44, 0xCCE3, 0x8E45, 0xDB82, 0x8E46, 0xDB83, + 0x8E47, 0xE5BF, 0x8E48, 0xB5B8, 0x8E49, 0xF5E3, 0x8E4A, 0xF5E8, + 0x8E4B, 0xCCA3, 0x8E4C, 0xDB84, 0x8E4D, 0xDB85, 0x8E4E, 0xDB86, + 0x8E4F, 0xDB87, 0x8E50, 0xDB88, 0x8E51, 0xF5E6, 0x8E52, 0xF5E7, + 0x8E53, 0xDB89, 0x8E54, 0xDB8A, 0x8E55, 0xDB8B, 0x8E56, 0xDB8C, + 0x8E57, 0xDB8D, 0x8E58, 0xDB8E, 0x8E59, 0xF5BE, 0x8E5A, 0xDB8F, + 0x8E5B, 0xDB90, 0x8E5C, 0xDB91, 0x8E5D, 0xDB92, 0x8E5E, 0xDB93, + 0x8E5F, 0xDB94, 0x8E60, 0xDB95, 0x8E61, 0xDB96, 0x8E62, 0xDB97, + 0x8E63, 0xDB98, 0x8E64, 0xDB99, 0x8E65, 0xDB9A, 0x8E66, 0xB1C4, + 0x8E67, 0xDB9B, 0x8E68, 0xDB9C, 0x8E69, 0xF5BF, 0x8E6A, 0xDB9D, + 0x8E6B, 0xDB9E, 0x8E6C, 0xB5C5, 0x8E6D, 0xB2E4, 0x8E6E, 0xDB9F, + 0x8E6F, 0xF5EC, 0x8E70, 0xF5E9, 0x8E71, 0xDBA0, 0x8E72, 0xB6D7, + 0x8E73, 0xDC40, 0x8E74, 0xF5ED, 0x8E75, 0xDC41, 0x8E76, 0xF5EA, + 0x8E77, 0xDC42, 0x8E78, 0xDC43, 0x8E79, 0xDC44, 0x8E7A, 0xDC45, + 0x8E7B, 0xDC46, 0x8E7C, 0xF5EB, 0x8E7D, 0xDC47, 0x8E7E, 0xDC48, + 0x8E7F, 0xB4DA, 0x8E80, 0xDC49, 0x8E81, 0xD4EA, 0x8E82, 0xDC4A, + 0x8E83, 0xDC4B, 0x8E84, 0xDC4C, 0x8E85, 0xF5EE, 0x8E86, 0xDC4D, + 0x8E87, 0xB3F9, 0x8E88, 0xDC4E, 0x8E89, 0xDC4F, 0x8E8A, 0xDC50, + 0x8E8B, 0xDC51, 0x8E8C, 0xDC52, 0x8E8D, 0xDC53, 0x8E8E, 0xDC54, + 0x8E8F, 0xF5EF, 0x8E90, 0xF5F1, 0x8E91, 0xDC55, 0x8E92, 0xDC56, + 0x8E93, 0xDC57, 0x8E94, 0xF5F0, 0x8E95, 0xDC58, 0x8E96, 0xDC59, + 0x8E97, 0xDC5A, 0x8E98, 0xDC5B, 0x8E99, 0xDC5C, 0x8E9A, 0xDC5D, + 0x8E9B, 0xDC5E, 0x8E9C, 0xF5F2, 0x8E9D, 0xDC5F, 0x8E9E, 0xF5F3, + 0x8E9F, 0xDC60, 0x8EA0, 0xDC61, 0x8EA1, 0xDC62, 0x8EA2, 0xDC63, + 0x8EA3, 0xDC64, 0x8EA4, 0xDC65, 0x8EA5, 0xDC66, 0x8EA6, 0xDC67, + 0x8EA7, 0xDC68, 0x8EA8, 0xDC69, 0x8EA9, 0xDC6A, 0x8EAA, 0xDC6B, + 0x8EAB, 0xC9ED, 0x8EAC, 0xB9AA, 0x8EAD, 0xDC6C, 0x8EAE, 0xDC6D, + 0x8EAF, 0xC7FB, 0x8EB0, 0xDC6E, 0x8EB1, 0xDC6F, 0x8EB2, 0xB6E3, + 0x8EB3, 0xDC70, 0x8EB4, 0xDC71, 0x8EB5, 0xDC72, 0x8EB6, 0xDC73, + 0x8EB7, 0xDC74, 0x8EB8, 0xDC75, 0x8EB9, 0xDC76, 0x8EBA, 0xCCC9, + 0x8EBB, 0xDC77, 0x8EBC, 0xDC78, 0x8EBD, 0xDC79, 0x8EBE, 0xDC7A, + 0x8EBF, 0xDC7B, 0x8EC0, 0xDC7C, 0x8EC1, 0xDC7D, 0x8EC2, 0xDC7E, + 0x8EC3, 0xDC80, 0x8EC4, 0xDC81, 0x8EC5, 0xDC82, 0x8EC6, 0xDC83, + 0x8EC7, 0xDC84, 0x8EC8, 0xDC85, 0x8EC9, 0xDC86, 0x8ECA, 0xDC87, + 0x8ECB, 0xDC88, 0x8ECC, 0xDC89, 0x8ECD, 0xDC8A, 0x8ECE, 0xEAA6, + 0x8ECF, 0xDC8B, 0x8ED0, 0xDC8C, 0x8ED1, 0xDC8D, 0x8ED2, 0xDC8E, + 0x8ED3, 0xDC8F, 0x8ED4, 0xDC90, 0x8ED5, 0xDC91, 0x8ED6, 0xDC92, + 0x8ED7, 0xDC93, 0x8ED8, 0xDC94, 0x8ED9, 0xDC95, 0x8EDA, 0xDC96, + 0x8EDB, 0xDC97, 0x8EDC, 0xDC98, 0x8EDD, 0xDC99, 0x8EDE, 0xDC9A, + 0x8EDF, 0xDC9B, 0x8EE0, 0xDC9C, 0x8EE1, 0xDC9D, 0x8EE2, 0xDC9E, + 0x8EE3, 0xDC9F, 0x8EE4, 0xDCA0, 0x8EE5, 0xDD40, 0x8EE6, 0xDD41, + 0x8EE7, 0xDD42, 0x8EE8, 0xDD43, 0x8EE9, 0xDD44, 0x8EEA, 0xDD45, + 0x8EEB, 0xDD46, 0x8EEC, 0xDD47, 0x8EED, 0xDD48, 0x8EEE, 0xDD49, + 0x8EEF, 0xDD4A, 0x8EF0, 0xDD4B, 0x8EF1, 0xDD4C, 0x8EF2, 0xDD4D, + 0x8EF3, 0xDD4E, 0x8EF4, 0xDD4F, 0x8EF5, 0xDD50, 0x8EF6, 0xDD51, + 0x8EF7, 0xDD52, 0x8EF8, 0xDD53, 0x8EF9, 0xDD54, 0x8EFA, 0xDD55, + 0x8EFB, 0xDD56, 0x8EFC, 0xDD57, 0x8EFD, 0xDD58, 0x8EFE, 0xDD59, + 0x8EFF, 0xDD5A, 0x8F00, 0xDD5B, 0x8F01, 0xDD5C, 0x8F02, 0xDD5D, + 0x8F03, 0xDD5E, 0x8F04, 0xDD5F, 0x8F05, 0xDD60, 0x8F06, 0xDD61, + 0x8F07, 0xDD62, 0x8F08, 0xDD63, 0x8F09, 0xDD64, 0x8F0A, 0xDD65, + 0x8F0B, 0xDD66, 0x8F0C, 0xDD67, 0x8F0D, 0xDD68, 0x8F0E, 0xDD69, + 0x8F0F, 0xDD6A, 0x8F10, 0xDD6B, 0x8F11, 0xDD6C, 0x8F12, 0xDD6D, + 0x8F13, 0xDD6E, 0x8F14, 0xDD6F, 0x8F15, 0xDD70, 0x8F16, 0xDD71, + 0x8F17, 0xDD72, 0x8F18, 0xDD73, 0x8F19, 0xDD74, 0x8F1A, 0xDD75, + 0x8F1B, 0xDD76, 0x8F1C, 0xDD77, 0x8F1D, 0xDD78, 0x8F1E, 0xDD79, + 0x8F1F, 0xDD7A, 0x8F20, 0xDD7B, 0x8F21, 0xDD7C, 0x8F22, 0xDD7D, + 0x8F23, 0xDD7E, 0x8F24, 0xDD80, 0x8F25, 0xDD81, 0x8F26, 0xDD82, + 0x8F27, 0xDD83, 0x8F28, 0xDD84, 0x8F29, 0xDD85, 0x8F2A, 0xDD86, + 0x8F2B, 0xDD87, 0x8F2C, 0xDD88, 0x8F2D, 0xDD89, 0x8F2E, 0xDD8A, + 0x8F2F, 0xDD8B, 0x8F30, 0xDD8C, 0x8F31, 0xDD8D, 0x8F32, 0xDD8E, + 0x8F33, 0xDD8F, 0x8F34, 0xDD90, 0x8F35, 0xDD91, 0x8F36, 0xDD92, + 0x8F37, 0xDD93, 0x8F38, 0xDD94, 0x8F39, 0xDD95, 0x8F3A, 0xDD96, + 0x8F3B, 0xDD97, 0x8F3C, 0xDD98, 0x8F3D, 0xDD99, 0x8F3E, 0xDD9A, + 0x8F3F, 0xDD9B, 0x8F40, 0xDD9C, 0x8F41, 0xDD9D, 0x8F42, 0xDD9E, + 0x8F43, 0xDD9F, 0x8F44, 0xDDA0, 0x8F45, 0xDE40, 0x8F46, 0xDE41, + 0x8F47, 0xDE42, 0x8F48, 0xDE43, 0x8F49, 0xDE44, 0x8F4A, 0xDE45, + 0x8F4B, 0xDE46, 0x8F4C, 0xDE47, 0x8F4D, 0xDE48, 0x8F4E, 0xDE49, + 0x8F4F, 0xDE4A, 0x8F50, 0xDE4B, 0x8F51, 0xDE4C, 0x8F52, 0xDE4D, + 0x8F53, 0xDE4E, 0x8F54, 0xDE4F, 0x8F55, 0xDE50, 0x8F56, 0xDE51, + 0x8F57, 0xDE52, 0x8F58, 0xDE53, 0x8F59, 0xDE54, 0x8F5A, 0xDE55, + 0x8F5B, 0xDE56, 0x8F5C, 0xDE57, 0x8F5D, 0xDE58, 0x8F5E, 0xDE59, + 0x8F5F, 0xDE5A, 0x8F60, 0xDE5B, 0x8F61, 0xDE5C, 0x8F62, 0xDE5D, + 0x8F63, 0xDE5E, 0x8F64, 0xDE5F, 0x8F65, 0xDE60, 0x8F66, 0xB3B5, + 0x8F67, 0xD4FE, 0x8F68, 0xB9EC, 0x8F69, 0xD0F9, 0x8F6A, 0xDE61, + 0x8F6B, 0xE9ED, 0x8F6C, 0xD7AA, 0x8F6D, 0xE9EE, 0x8F6E, 0xC2D6, + 0x8F6F, 0xC8ED, 0x8F70, 0xBAE4, 0x8F71, 0xE9EF, 0x8F72, 0xE9F0, + 0x8F73, 0xE9F1, 0x8F74, 0xD6E1, 0x8F75, 0xE9F2, 0x8F76, 0xE9F3, + 0x8F77, 0xE9F5, 0x8F78, 0xE9F4, 0x8F79, 0xE9F6, 0x8F7A, 0xE9F7, + 0x8F7B, 0xC7E1, 0x8F7C, 0xE9F8, 0x8F7D, 0xD4D8, 0x8F7E, 0xE9F9, + 0x8F7F, 0xBDCE, 0x8F80, 0xDE62, 0x8F81, 0xE9FA, 0x8F82, 0xE9FB, + 0x8F83, 0xBDCF, 0x8F84, 0xE9FC, 0x8F85, 0xB8A8, 0x8F86, 0xC1BE, + 0x8F87, 0xE9FD, 0x8F88, 0xB1B2, 0x8F89, 0xBBD4, 0x8F8A, 0xB9F5, + 0x8F8B, 0xE9FE, 0x8F8C, 0xDE63, 0x8F8D, 0xEAA1, 0x8F8E, 0xEAA2, + 0x8F8F, 0xEAA3, 0x8F90, 0xB7F8, 0x8F91, 0xBCAD, 0x8F92, 0xDE64, + 0x8F93, 0xCAE4, 0x8F94, 0xE0CE, 0x8F95, 0xD4AF, 0x8F96, 0xCFBD, + 0x8F97, 0xD5B7, 0x8F98, 0xEAA4, 0x8F99, 0xD5DE, 0x8F9A, 0xEAA5, + 0x8F9B, 0xD0C1, 0x8F9C, 0xB9BC, 0x8F9D, 0xDE65, 0x8F9E, 0xB4C7, + 0x8F9F, 0xB1D9, 0x8FA0, 0xDE66, 0x8FA1, 0xDE67, 0x8FA2, 0xDE68, + 0x8FA3, 0xC0B1, 0x8FA4, 0xDE69, 0x8FA5, 0xDE6A, 0x8FA6, 0xDE6B, + 0x8FA7, 0xDE6C, 0x8FA8, 0xB1E6, 0x8FA9, 0xB1E7, 0x8FAA, 0xDE6D, + 0x8FAB, 0xB1E8, 0x8FAC, 0xDE6E, 0x8FAD, 0xDE6F, 0x8FAE, 0xDE70, + 0x8FAF, 0xDE71, 0x8FB0, 0xB3BD, 0x8FB1, 0xC8E8, 0x8FB2, 0xDE72, + 0x8FB3, 0xDE73, 0x8FB4, 0xDE74, 0x8FB5, 0xDE75, 0x8FB6, 0xE5C1, + 0x8FB7, 0xDE76, 0x8FB8, 0xDE77, 0x8FB9, 0xB1DF, 0x8FBA, 0xDE78, + 0x8FBB, 0xDE79, 0x8FBC, 0xDE7A, 0x8FBD, 0xC1C9, 0x8FBE, 0xB4EF, + 0x8FBF, 0xDE7B, 0x8FC0, 0xDE7C, 0x8FC1, 0xC7A8, 0x8FC2, 0xD3D8, + 0x8FC3, 0xDE7D, 0x8FC4, 0xC6F9, 0x8FC5, 0xD1B8, 0x8FC6, 0xDE7E, + 0x8FC7, 0xB9FD, 0x8FC8, 0xC2F5, 0x8FC9, 0xDE80, 0x8FCA, 0xDE81, + 0x8FCB, 0xDE82, 0x8FCC, 0xDE83, 0x8FCD, 0xDE84, 0x8FCE, 0xD3AD, + 0x8FCF, 0xDE85, 0x8FD0, 0xD4CB, 0x8FD1, 0xBDFC, 0x8FD2, 0xDE86, + 0x8FD3, 0xE5C2, 0x8FD4, 0xB7B5, 0x8FD5, 0xE5C3, 0x8FD6, 0xDE87, + 0x8FD7, 0xDE88, 0x8FD8, 0xBBB9, 0x8FD9, 0xD5E2, 0x8FDA, 0xDE89, + 0x8FDB, 0xBDF8, 0x8FDC, 0xD4B6, 0x8FDD, 0xCEA5, 0x8FDE, 0xC1AC, + 0x8FDF, 0xB3D9, 0x8FE0, 0xDE8A, 0x8FE1, 0xDE8B, 0x8FE2, 0xCCF6, + 0x8FE3, 0xDE8C, 0x8FE4, 0xE5C6, 0x8FE5, 0xE5C4, 0x8FE6, 0xE5C8, + 0x8FE7, 0xDE8D, 0x8FE8, 0xE5CA, 0x8FE9, 0xE5C7, 0x8FEA, 0xB5CF, + 0x8FEB, 0xC6C8, 0x8FEC, 0xDE8E, 0x8FED, 0xB5FC, 0x8FEE, 0xE5C5, + 0x8FEF, 0xDE8F, 0x8FF0, 0xCAF6, 0x8FF1, 0xDE90, 0x8FF2, 0xDE91, + 0x8FF3, 0xE5C9, 0x8FF4, 0xDE92, 0x8FF5, 0xDE93, 0x8FF6, 0xDE94, + 0x8FF7, 0xC3D4, 0x8FF8, 0xB1C5, 0x8FF9, 0xBCA3, 0x8FFA, 0xDE95, + 0x8FFB, 0xDE96, 0x8FFC, 0xDE97, 0x8FFD, 0xD7B7, 0x8FFE, 0xDE98, + 0x8FFF, 0xDE99, 0x9000, 0xCDCB, 0x9001, 0xCBCD, 0x9002, 0xCACA, + 0x9003, 0xCCD3, 0x9004, 0xE5CC, 0x9005, 0xE5CB, 0x9006, 0xC4E6, + 0x9007, 0xDE9A, 0x9008, 0xDE9B, 0x9009, 0xD1A1, 0x900A, 0xD1B7, + 0x900B, 0xE5CD, 0x900C, 0xDE9C, 0x900D, 0xE5D0, 0x900E, 0xDE9D, + 0x900F, 0xCDB8, 0x9010, 0xD6F0, 0x9011, 0xE5CF, 0x9012, 0xB5DD, + 0x9013, 0xDE9E, 0x9014, 0xCDBE, 0x9015, 0xDE9F, 0x9016, 0xE5D1, + 0x9017, 0xB6BA, 0x9018, 0xDEA0, 0x9019, 0xDF40, 0x901A, 0xCDA8, + 0x901B, 0xB9E4, 0x901C, 0xDF41, 0x901D, 0xCAC5, 0x901E, 0xB3D1, + 0x901F, 0xCBD9, 0x9020, 0xD4EC, 0x9021, 0xE5D2, 0x9022, 0xB7EA, + 0x9023, 0xDF42, 0x9024, 0xDF43, 0x9025, 0xDF44, 0x9026, 0xE5CE, + 0x9027, 0xDF45, 0x9028, 0xDF46, 0x9029, 0xDF47, 0x902A, 0xDF48, + 0x902B, 0xDF49, 0x902C, 0xDF4A, 0x902D, 0xE5D5, 0x902E, 0xB4FE, + 0x902F, 0xE5D6, 0x9030, 0xDF4B, 0x9031, 0xDF4C, 0x9032, 0xDF4D, + 0x9033, 0xDF4E, 0x9034, 0xDF4F, 0x9035, 0xE5D3, 0x9036, 0xE5D4, + 0x9037, 0xDF50, 0x9038, 0xD2DD, 0x9039, 0xDF51, 0x903A, 0xDF52, + 0x903B, 0xC2DF, 0x903C, 0xB1C6, 0x903D, 0xDF53, 0x903E, 0xD3E2, + 0x903F, 0xDF54, 0x9040, 0xDF55, 0x9041, 0xB6DD, 0x9042, 0xCBEC, + 0x9043, 0xDF56, 0x9044, 0xE5D7, 0x9045, 0xDF57, 0x9046, 0xDF58, + 0x9047, 0xD3F6, 0x9048, 0xDF59, 0x9049, 0xDF5A, 0x904A, 0xDF5B, + 0x904B, 0xDF5C, 0x904C, 0xDF5D, 0x904D, 0xB1E9, 0x904E, 0xDF5E, + 0x904F, 0xB6F4, 0x9050, 0xE5DA, 0x9051, 0xE5D8, 0x9052, 0xE5D9, + 0x9053, 0xB5C0, 0x9054, 0xDF5F, 0x9055, 0xDF60, 0x9056, 0xDF61, + 0x9057, 0xD2C5, 0x9058, 0xE5DC, 0x9059, 0xDF62, 0x905A, 0xDF63, + 0x905B, 0xE5DE, 0x905C, 0xDF64, 0x905D, 0xDF65, 0x905E, 0xDF66, + 0x905F, 0xDF67, 0x9060, 0xDF68, 0x9061, 0xDF69, 0x9062, 0xE5DD, + 0x9063, 0xC7B2, 0x9064, 0xDF6A, 0x9065, 0xD2A3, 0x9066, 0xDF6B, + 0x9067, 0xDF6C, 0x9068, 0xE5DB, 0x9069, 0xDF6D, 0x906A, 0xDF6E, + 0x906B, 0xDF6F, 0x906C, 0xDF70, 0x906D, 0xD4E2, 0x906E, 0xD5DA, + 0x906F, 0xDF71, 0x9070, 0xDF72, 0x9071, 0xDF73, 0x9072, 0xDF74, + 0x9073, 0xDF75, 0x9074, 0xE5E0, 0x9075, 0xD7F1, 0x9076, 0xDF76, + 0x9077, 0xDF77, 0x9078, 0xDF78, 0x9079, 0xDF79, 0x907A, 0xDF7A, + 0x907B, 0xDF7B, 0x907C, 0xDF7C, 0x907D, 0xE5E1, 0x907E, 0xDF7D, + 0x907F, 0xB1DC, 0x9080, 0xD1FB, 0x9081, 0xDF7E, 0x9082, 0xE5E2, + 0x9083, 0xE5E4, 0x9084, 0xDF80, 0x9085, 0xDF81, 0x9086, 0xDF82, + 0x9087, 0xDF83, 0x9088, 0xE5E3, 0x9089, 0xDF84, 0x908A, 0xDF85, + 0x908B, 0xE5E5, 0x908C, 0xDF86, 0x908D, 0xDF87, 0x908E, 0xDF88, + 0x908F, 0xDF89, 0x9090, 0xDF8A, 0x9091, 0xD2D8, 0x9092, 0xDF8B, + 0x9093, 0xB5CB, 0x9094, 0xDF8C, 0x9095, 0xE7DF, 0x9096, 0xDF8D, + 0x9097, 0xDAF5, 0x9098, 0xDF8E, 0x9099, 0xDAF8, 0x909A, 0xDF8F, + 0x909B, 0xDAF6, 0x909C, 0xDF90, 0x909D, 0xDAF7, 0x909E, 0xDF91, + 0x909F, 0xDF92, 0x90A0, 0xDF93, 0x90A1, 0xDAFA, 0x90A2, 0xD0CF, + 0x90A3, 0xC4C7, 0x90A4, 0xDF94, 0x90A5, 0xDF95, 0x90A6, 0xB0EE, + 0x90A7, 0xDF96, 0x90A8, 0xDF97, 0x90A9, 0xDF98, 0x90AA, 0xD0B0, + 0x90AB, 0xDF99, 0x90AC, 0xDAF9, 0x90AD, 0xDF9A, 0x90AE, 0xD3CA, + 0x90AF, 0xBAAA, 0x90B0, 0xDBA2, 0x90B1, 0xC7F1, 0x90B2, 0xDF9B, + 0x90B3, 0xDAFC, 0x90B4, 0xDAFB, 0x90B5, 0xC9DB, 0x90B6, 0xDAFD, + 0x90B7, 0xDF9C, 0x90B8, 0xDBA1, 0x90B9, 0xD7DE, 0x90BA, 0xDAFE, + 0x90BB, 0xC1DA, 0x90BC, 0xDF9D, 0x90BD, 0xDF9E, 0x90BE, 0xDBA5, + 0x90BF, 0xDF9F, 0x90C0, 0xDFA0, 0x90C1, 0xD3F4, 0x90C2, 0xE040, + 0x90C3, 0xE041, 0x90C4, 0xDBA7, 0x90C5, 0xDBA4, 0x90C6, 0xE042, + 0x90C7, 0xDBA8, 0x90C8, 0xE043, 0x90C9, 0xE044, 0x90CA, 0xBDBC, + 0x90CB, 0xE045, 0x90CC, 0xE046, 0x90CD, 0xE047, 0x90CE, 0xC0C9, + 0x90CF, 0xDBA3, 0x90D0, 0xDBA6, 0x90D1, 0xD6A3, 0x90D2, 0xE048, + 0x90D3, 0xDBA9, 0x90D4, 0xE049, 0x90D5, 0xE04A, 0x90D6, 0xE04B, + 0x90D7, 0xDBAD, 0x90D8, 0xE04C, 0x90D9, 0xE04D, 0x90DA, 0xE04E, + 0x90DB, 0xDBAE, 0x90DC, 0xDBAC, 0x90DD, 0xBAC2, 0x90DE, 0xE04F, + 0x90DF, 0xE050, 0x90E0, 0xE051, 0x90E1, 0xBFA4, 0x90E2, 0xDBAB, + 0x90E3, 0xE052, 0x90E4, 0xE053, 0x90E5, 0xE054, 0x90E6, 0xDBAA, + 0x90E7, 0xD4C7, 0x90E8, 0xB2BF, 0x90E9, 0xE055, 0x90EA, 0xE056, + 0x90EB, 0xDBAF, 0x90EC, 0xE057, 0x90ED, 0xB9F9, 0x90EE, 0xE058, + 0x90EF, 0xDBB0, 0x90F0, 0xE059, 0x90F1, 0xE05A, 0x90F2, 0xE05B, + 0x90F3, 0xE05C, 0x90F4, 0xB3BB, 0x90F5, 0xE05D, 0x90F6, 0xE05E, + 0x90F7, 0xE05F, 0x90F8, 0xB5A6, 0x90F9, 0xE060, 0x90FA, 0xE061, + 0x90FB, 0xE062, 0x90FC, 0xE063, 0x90FD, 0xB6BC, 0x90FE, 0xDBB1, + 0x90FF, 0xE064, 0x9100, 0xE065, 0x9101, 0xE066, 0x9102, 0xB6F5, + 0x9103, 0xE067, 0x9104, 0xDBB2, 0x9105, 0xE068, 0x9106, 0xE069, + 0x9107, 0xE06A, 0x9108, 0xE06B, 0x9109, 0xE06C, 0x910A, 0xE06D, + 0x910B, 0xE06E, 0x910C, 0xE06F, 0x910D, 0xE070, 0x910E, 0xE071, + 0x910F, 0xE072, 0x9110, 0xE073, 0x9111, 0xE074, 0x9112, 0xE075, + 0x9113, 0xE076, 0x9114, 0xE077, 0x9115, 0xE078, 0x9116, 0xE079, + 0x9117, 0xE07A, 0x9118, 0xE07B, 0x9119, 0xB1C9, 0x911A, 0xE07C, + 0x911B, 0xE07D, 0x911C, 0xE07E, 0x911D, 0xE080, 0x911E, 0xDBB4, + 0x911F, 0xE081, 0x9120, 0xE082, 0x9121, 0xE083, 0x9122, 0xDBB3, + 0x9123, 0xDBB5, 0x9124, 0xE084, 0x9125, 0xE085, 0x9126, 0xE086, + 0x9127, 0xE087, 0x9128, 0xE088, 0x9129, 0xE089, 0x912A, 0xE08A, + 0x912B, 0xE08B, 0x912C, 0xE08C, 0x912D, 0xE08D, 0x912E, 0xE08E, + 0x912F, 0xDBB7, 0x9130, 0xE08F, 0x9131, 0xDBB6, 0x9132, 0xE090, + 0x9133, 0xE091, 0x9134, 0xE092, 0x9135, 0xE093, 0x9136, 0xE094, + 0x9137, 0xE095, 0x9138, 0xE096, 0x9139, 0xDBB8, 0x913A, 0xE097, + 0x913B, 0xE098, 0x913C, 0xE099, 0x913D, 0xE09A, 0x913E, 0xE09B, + 0x913F, 0xE09C, 0x9140, 0xE09D, 0x9141, 0xE09E, 0x9142, 0xE09F, + 0x9143, 0xDBB9, 0x9144, 0xE0A0, 0x9145, 0xE140, 0x9146, 0xDBBA, + 0x9147, 0xE141, 0x9148, 0xE142, 0x9149, 0xD3CF, 0x914A, 0xF4FA, + 0x914B, 0xC7F5, 0x914C, 0xD7C3, 0x914D, 0xC5E4, 0x914E, 0xF4FC, + 0x914F, 0xF4FD, 0x9150, 0xF4FB, 0x9151, 0xE143, 0x9152, 0xBEC6, + 0x9153, 0xE144, 0x9154, 0xE145, 0x9155, 0xE146, 0x9156, 0xE147, + 0x9157, 0xD0EF, 0x9158, 0xE148, 0x9159, 0xE149, 0x915A, 0xB7D3, + 0x915B, 0xE14A, 0x915C, 0xE14B, 0x915D, 0xD4CD, 0x915E, 0xCCAA, + 0x915F, 0xE14C, 0x9160, 0xE14D, 0x9161, 0xF5A2, 0x9162, 0xF5A1, + 0x9163, 0xBAA8, 0x9164, 0xF4FE, 0x9165, 0xCBD6, 0x9166, 0xE14E, + 0x9167, 0xE14F, 0x9168, 0xE150, 0x9169, 0xF5A4, 0x916A, 0xC0D2, + 0x916B, 0xE151, 0x916C, 0xB3EA, 0x916D, 0xE152, 0x916E, 0xCDAA, + 0x916F, 0xF5A5, 0x9170, 0xF5A3, 0x9171, 0xBDB4, 0x9172, 0xF5A8, + 0x9173, 0xE153, 0x9174, 0xF5A9, 0x9175, 0xBDCD, 0x9176, 0xC3B8, + 0x9177, 0xBFE1, 0x9178, 0xCBE1, 0x9179, 0xF5AA, 0x917A, 0xE154, + 0x917B, 0xE155, 0x917C, 0xE156, 0x917D, 0xF5A6, 0x917E, 0xF5A7, + 0x917F, 0xC4F0, 0x9180, 0xE157, 0x9181, 0xE158, 0x9182, 0xE159, + 0x9183, 0xE15A, 0x9184, 0xE15B, 0x9185, 0xF5AC, 0x9186, 0xE15C, + 0x9187, 0xB4BC, 0x9188, 0xE15D, 0x9189, 0xD7ED, 0x918A, 0xE15E, + 0x918B, 0xB4D7, 0x918C, 0xF5AB, 0x918D, 0xF5AE, 0x918E, 0xE15F, + 0x918F, 0xE160, 0x9190, 0xF5AD, 0x9191, 0xF5AF, 0x9192, 0xD0D1, + 0x9193, 0xE161, 0x9194, 0xE162, 0x9195, 0xE163, 0x9196, 0xE164, + 0x9197, 0xE165, 0x9198, 0xE166, 0x9199, 0xE167, 0x919A, 0xC3D1, + 0x919B, 0xC8A9, 0x919C, 0xE168, 0x919D, 0xE169, 0x919E, 0xE16A, + 0x919F, 0xE16B, 0x91A0, 0xE16C, 0x91A1, 0xE16D, 0x91A2, 0xF5B0, + 0x91A3, 0xF5B1, 0x91A4, 0xE16E, 0x91A5, 0xE16F, 0x91A6, 0xE170, + 0x91A7, 0xE171, 0x91A8, 0xE172, 0x91A9, 0xE173, 0x91AA, 0xF5B2, + 0x91AB, 0xE174, 0x91AC, 0xE175, 0x91AD, 0xF5B3, 0x91AE, 0xF5B4, + 0x91AF, 0xF5B5, 0x91B0, 0xE176, 0x91B1, 0xE177, 0x91B2, 0xE178, + 0x91B3, 0xE179, 0x91B4, 0xF5B7, 0x91B5, 0xF5B6, 0x91B6, 0xE17A, + 0x91B7, 0xE17B, 0x91B8, 0xE17C, 0x91B9, 0xE17D, 0x91BA, 0xF5B8, + 0x91BB, 0xE17E, 0x91BC, 0xE180, 0x91BD, 0xE181, 0x91BE, 0xE182, + 0x91BF, 0xE183, 0x91C0, 0xE184, 0x91C1, 0xE185, 0x91C2, 0xE186, + 0x91C3, 0xE187, 0x91C4, 0xE188, 0x91C5, 0xE189, 0x91C6, 0xE18A, + 0x91C7, 0xB2C9, 0x91C8, 0xE18B, 0x91C9, 0xD3D4, 0x91CA, 0xCACD, + 0x91CB, 0xE18C, 0x91CC, 0xC0EF, 0x91CD, 0xD6D8, 0x91CE, 0xD2B0, + 0x91CF, 0xC1BF, 0x91D0, 0xE18D, 0x91D1, 0xBDF0, 0x91D2, 0xE18E, + 0x91D3, 0xE18F, 0x91D4, 0xE190, 0x91D5, 0xE191, 0x91D6, 0xE192, + 0x91D7, 0xE193, 0x91D8, 0xE194, 0x91D9, 0xE195, 0x91DA, 0xE196, + 0x91DB, 0xE197, 0x91DC, 0xB8AA, 0x91DD, 0xE198, 0x91DE, 0xE199, + 0x91DF, 0xE19A, 0x91E0, 0xE19B, 0x91E1, 0xE19C, 0x91E2, 0xE19D, + 0x91E3, 0xE19E, 0x91E4, 0xE19F, 0x91E5, 0xE1A0, 0x91E6, 0xE240, + 0x91E7, 0xE241, 0x91E8, 0xE242, 0x91E9, 0xE243, 0x91EA, 0xE244, + 0x91EB, 0xE245, 0x91EC, 0xE246, 0x91ED, 0xE247, 0x91EE, 0xE248, + 0x91EF, 0xE249, 0x91F0, 0xE24A, 0x91F1, 0xE24B, 0x91F2, 0xE24C, + 0x91F3, 0xE24D, 0x91F4, 0xE24E, 0x91F5, 0xE24F, 0x91F6, 0xE250, + 0x91F7, 0xE251, 0x91F8, 0xE252, 0x91F9, 0xE253, 0x91FA, 0xE254, + 0x91FB, 0xE255, 0x91FC, 0xE256, 0x91FD, 0xE257, 0x91FE, 0xE258, + 0x91FF, 0xE259, 0x9200, 0xE25A, 0x9201, 0xE25B, 0x9202, 0xE25C, + 0x9203, 0xE25D, 0x9204, 0xE25E, 0x9205, 0xE25F, 0x9206, 0xE260, + 0x9207, 0xE261, 0x9208, 0xE262, 0x9209, 0xE263, 0x920A, 0xE264, + 0x920B, 0xE265, 0x920C, 0xE266, 0x920D, 0xE267, 0x920E, 0xE268, + 0x920F, 0xE269, 0x9210, 0xE26A, 0x9211, 0xE26B, 0x9212, 0xE26C, + 0x9213, 0xE26D, 0x9214, 0xE26E, 0x9215, 0xE26F, 0x9216, 0xE270, + 0x9217, 0xE271, 0x9218, 0xE272, 0x9219, 0xE273, 0x921A, 0xE274, + 0x921B, 0xE275, 0x921C, 0xE276, 0x921D, 0xE277, 0x921E, 0xE278, + 0x921F, 0xE279, 0x9220, 0xE27A, 0x9221, 0xE27B, 0x9222, 0xE27C, + 0x9223, 0xE27D, 0x9224, 0xE27E, 0x9225, 0xE280, 0x9226, 0xE281, + 0x9227, 0xE282, 0x9228, 0xE283, 0x9229, 0xE284, 0x922A, 0xE285, + 0x922B, 0xE286, 0x922C, 0xE287, 0x922D, 0xE288, 0x922E, 0xE289, + 0x922F, 0xE28A, 0x9230, 0xE28B, 0x9231, 0xE28C, 0x9232, 0xE28D, + 0x9233, 0xE28E, 0x9234, 0xE28F, 0x9235, 0xE290, 0x9236, 0xE291, + 0x9237, 0xE292, 0x9238, 0xE293, 0x9239, 0xE294, 0x923A, 0xE295, + 0x923B, 0xE296, 0x923C, 0xE297, 0x923D, 0xE298, 0x923E, 0xE299, + 0x923F, 0xE29A, 0x9240, 0xE29B, 0x9241, 0xE29C, 0x9242, 0xE29D, + 0x9243, 0xE29E, 0x9244, 0xE29F, 0x9245, 0xE2A0, 0x9246, 0xE340, + 0x9247, 0xE341, 0x9248, 0xE342, 0x9249, 0xE343, 0x924A, 0xE344, + 0x924B, 0xE345, 0x924C, 0xE346, 0x924D, 0xE347, 0x924E, 0xE348, + 0x924F, 0xE349, 0x9250, 0xE34A, 0x9251, 0xE34B, 0x9252, 0xE34C, + 0x9253, 0xE34D, 0x9254, 0xE34E, 0x9255, 0xE34F, 0x9256, 0xE350, + 0x9257, 0xE351, 0x9258, 0xE352, 0x9259, 0xE353, 0x925A, 0xE354, + 0x925B, 0xE355, 0x925C, 0xE356, 0x925D, 0xE357, 0x925E, 0xE358, + 0x925F, 0xE359, 0x9260, 0xE35A, 0x9261, 0xE35B, 0x9262, 0xE35C, + 0x9263, 0xE35D, 0x9264, 0xE35E, 0x9265, 0xE35F, 0x9266, 0xE360, + 0x9267, 0xE361, 0x9268, 0xE362, 0x9269, 0xE363, 0x926A, 0xE364, + 0x926B, 0xE365, 0x926C, 0xE366, 0x926D, 0xE367, 0x926E, 0xE368, + 0x926F, 0xE369, 0x9270, 0xE36A, 0x9271, 0xE36B, 0x9272, 0xE36C, + 0x9273, 0xE36D, 0x9274, 0xBCF8, 0x9275, 0xE36E, 0x9276, 0xE36F, + 0x9277, 0xE370, 0x9278, 0xE371, 0x9279, 0xE372, 0x927A, 0xE373, + 0x927B, 0xE374, 0x927C, 0xE375, 0x927D, 0xE376, 0x927E, 0xE377, + 0x927F, 0xE378, 0x9280, 0xE379, 0x9281, 0xE37A, 0x9282, 0xE37B, + 0x9283, 0xE37C, 0x9284, 0xE37D, 0x9285, 0xE37E, 0x9286, 0xE380, + 0x9287, 0xE381, 0x9288, 0xE382, 0x9289, 0xE383, 0x928A, 0xE384, + 0x928B, 0xE385, 0x928C, 0xE386, 0x928D, 0xE387, 0x928E, 0xF6C6, + 0x928F, 0xE388, 0x9290, 0xE389, 0x9291, 0xE38A, 0x9292, 0xE38B, + 0x9293, 0xE38C, 0x9294, 0xE38D, 0x9295, 0xE38E, 0x9296, 0xE38F, + 0x9297, 0xE390, 0x9298, 0xE391, 0x9299, 0xE392, 0x929A, 0xE393, + 0x929B, 0xE394, 0x929C, 0xE395, 0x929D, 0xE396, 0x929E, 0xE397, + 0x929F, 0xE398, 0x92A0, 0xE399, 0x92A1, 0xE39A, 0x92A2, 0xE39B, + 0x92A3, 0xE39C, 0x92A4, 0xE39D, 0x92A5, 0xE39E, 0x92A6, 0xE39F, + 0x92A7, 0xE3A0, 0x92A8, 0xE440, 0x92A9, 0xE441, 0x92AA, 0xE442, + 0x92AB, 0xE443, 0x92AC, 0xE444, 0x92AD, 0xE445, 0x92AE, 0xF6C7, + 0x92AF, 0xE446, 0x92B0, 0xE447, 0x92B1, 0xE448, 0x92B2, 0xE449, + 0x92B3, 0xE44A, 0x92B4, 0xE44B, 0x92B5, 0xE44C, 0x92B6, 0xE44D, + 0x92B7, 0xE44E, 0x92B8, 0xE44F, 0x92B9, 0xE450, 0x92BA, 0xE451, + 0x92BB, 0xE452, 0x92BC, 0xE453, 0x92BD, 0xE454, 0x92BE, 0xE455, + 0x92BF, 0xE456, 0x92C0, 0xE457, 0x92C1, 0xE458, 0x92C2, 0xE459, + 0x92C3, 0xE45A, 0x92C4, 0xE45B, 0x92C5, 0xE45C, 0x92C6, 0xE45D, + 0x92C7, 0xE45E, 0x92C8, 0xF6C8, 0x92C9, 0xE45F, 0x92CA, 0xE460, + 0x92CB, 0xE461, 0x92CC, 0xE462, 0x92CD, 0xE463, 0x92CE, 0xE464, + 0x92CF, 0xE465, 0x92D0, 0xE466, 0x92D1, 0xE467, 0x92D2, 0xE468, + 0x92D3, 0xE469, 0x92D4, 0xE46A, 0x92D5, 0xE46B, 0x92D6, 0xE46C, + 0x92D7, 0xE46D, 0x92D8, 0xE46E, 0x92D9, 0xE46F, 0x92DA, 0xE470, + 0x92DB, 0xE471, 0x92DC, 0xE472, 0x92DD, 0xE473, 0x92DE, 0xE474, + 0x92DF, 0xE475, 0x92E0, 0xE476, 0x92E1, 0xE477, 0x92E2, 0xE478, + 0x92E3, 0xE479, 0x92E4, 0xE47A, 0x92E5, 0xE47B, 0x92E6, 0xE47C, + 0x92E7, 0xE47D, 0x92E8, 0xE47E, 0x92E9, 0xE480, 0x92EA, 0xE481, + 0x92EB, 0xE482, 0x92EC, 0xE483, 0x92ED, 0xE484, 0x92EE, 0xE485, + 0x92EF, 0xE486, 0x92F0, 0xE487, 0x92F1, 0xE488, 0x92F2, 0xE489, + 0x92F3, 0xE48A, 0x92F4, 0xE48B, 0x92F5, 0xE48C, 0x92F6, 0xE48D, + 0x92F7, 0xE48E, 0x92F8, 0xE48F, 0x92F9, 0xE490, 0x92FA, 0xE491, + 0x92FB, 0xE492, 0x92FC, 0xE493, 0x92FD, 0xE494, 0x92FE, 0xE495, + 0x92FF, 0xE496, 0x9300, 0xE497, 0x9301, 0xE498, 0x9302, 0xE499, + 0x9303, 0xE49A, 0x9304, 0xE49B, 0x9305, 0xE49C, 0x9306, 0xE49D, + 0x9307, 0xE49E, 0x9308, 0xE49F, 0x9309, 0xE4A0, 0x930A, 0xE540, + 0x930B, 0xE541, 0x930C, 0xE542, 0x930D, 0xE543, 0x930E, 0xE544, + 0x930F, 0xE545, 0x9310, 0xE546, 0x9311, 0xE547, 0x9312, 0xE548, + 0x9313, 0xE549, 0x9314, 0xE54A, 0x9315, 0xE54B, 0x9316, 0xE54C, + 0x9317, 0xE54D, 0x9318, 0xE54E, 0x9319, 0xE54F, 0x931A, 0xE550, + 0x931B, 0xE551, 0x931C, 0xE552, 0x931D, 0xE553, 0x931E, 0xE554, + 0x931F, 0xE555, 0x9320, 0xE556, 0x9321, 0xE557, 0x9322, 0xE558, + 0x9323, 0xE559, 0x9324, 0xE55A, 0x9325, 0xE55B, 0x9326, 0xE55C, + 0x9327, 0xE55D, 0x9328, 0xE55E, 0x9329, 0xE55F, 0x932A, 0xE560, + 0x932B, 0xE561, 0x932C, 0xE562, 0x932D, 0xE563, 0x932E, 0xE564, + 0x932F, 0xE565, 0x9330, 0xE566, 0x9331, 0xE567, 0x9332, 0xE568, + 0x9333, 0xE569, 0x9334, 0xE56A, 0x9335, 0xE56B, 0x9336, 0xE56C, + 0x9337, 0xE56D, 0x9338, 0xE56E, 0x9339, 0xE56F, 0x933A, 0xE570, + 0x933B, 0xE571, 0x933C, 0xE572, 0x933D, 0xE573, 0x933E, 0xF6C9, + 0x933F, 0xE574, 0x9340, 0xE575, 0x9341, 0xE576, 0x9342, 0xE577, + 0x9343, 0xE578, 0x9344, 0xE579, 0x9345, 0xE57A, 0x9346, 0xE57B, + 0x9347, 0xE57C, 0x9348, 0xE57D, 0x9349, 0xE57E, 0x934A, 0xE580, + 0x934B, 0xE581, 0x934C, 0xE582, 0x934D, 0xE583, 0x934E, 0xE584, + 0x934F, 0xE585, 0x9350, 0xE586, 0x9351, 0xE587, 0x9352, 0xE588, + 0x9353, 0xE589, 0x9354, 0xE58A, 0x9355, 0xE58B, 0x9356, 0xE58C, + 0x9357, 0xE58D, 0x9358, 0xE58E, 0x9359, 0xE58F, 0x935A, 0xE590, + 0x935B, 0xE591, 0x935C, 0xE592, 0x935D, 0xE593, 0x935E, 0xE594, + 0x935F, 0xE595, 0x9360, 0xE596, 0x9361, 0xE597, 0x9362, 0xE598, + 0x9363, 0xE599, 0x9364, 0xE59A, 0x9365, 0xE59B, 0x9366, 0xE59C, + 0x9367, 0xE59D, 0x9368, 0xE59E, 0x9369, 0xE59F, 0x936A, 0xF6CA, + 0x936B, 0xE5A0, 0x936C, 0xE640, 0x936D, 0xE641, 0x936E, 0xE642, + 0x936F, 0xE643, 0x9370, 0xE644, 0x9371, 0xE645, 0x9372, 0xE646, + 0x9373, 0xE647, 0x9374, 0xE648, 0x9375, 0xE649, 0x9376, 0xE64A, + 0x9377, 0xE64B, 0x9378, 0xE64C, 0x9379, 0xE64D, 0x937A, 0xE64E, + 0x937B, 0xE64F, 0x937C, 0xE650, 0x937D, 0xE651, 0x937E, 0xE652, + 0x937F, 0xE653, 0x9380, 0xE654, 0x9381, 0xE655, 0x9382, 0xE656, + 0x9383, 0xE657, 0x9384, 0xE658, 0x9385, 0xE659, 0x9386, 0xE65A, + 0x9387, 0xE65B, 0x9388, 0xE65C, 0x9389, 0xE65D, 0x938A, 0xE65E, + 0x938B, 0xE65F, 0x938C, 0xE660, 0x938D, 0xE661, 0x938E, 0xE662, + 0x938F, 0xF6CC, 0x9390, 0xE663, 0x9391, 0xE664, 0x9392, 0xE665, + 0x9393, 0xE666, 0x9394, 0xE667, 0x9395, 0xE668, 0x9396, 0xE669, + 0x9397, 0xE66A, 0x9398, 0xE66B, 0x9399, 0xE66C, 0x939A, 0xE66D, + 0x939B, 0xE66E, 0x939C, 0xE66F, 0x939D, 0xE670, 0x939E, 0xE671, + 0x939F, 0xE672, 0x93A0, 0xE673, 0x93A1, 0xE674, 0x93A2, 0xE675, + 0x93A3, 0xE676, 0x93A4, 0xE677, 0x93A5, 0xE678, 0x93A6, 0xE679, + 0x93A7, 0xE67A, 0x93A8, 0xE67B, 0x93A9, 0xE67C, 0x93AA, 0xE67D, + 0x93AB, 0xE67E, 0x93AC, 0xE680, 0x93AD, 0xE681, 0x93AE, 0xE682, + 0x93AF, 0xE683, 0x93B0, 0xE684, 0x93B1, 0xE685, 0x93B2, 0xE686, + 0x93B3, 0xE687, 0x93B4, 0xE688, 0x93B5, 0xE689, 0x93B6, 0xE68A, + 0x93B7, 0xE68B, 0x93B8, 0xE68C, 0x93B9, 0xE68D, 0x93BA, 0xE68E, + 0x93BB, 0xE68F, 0x93BC, 0xE690, 0x93BD, 0xE691, 0x93BE, 0xE692, + 0x93BF, 0xE693, 0x93C0, 0xE694, 0x93C1, 0xE695, 0x93C2, 0xE696, + 0x93C3, 0xE697, 0x93C4, 0xE698, 0x93C5, 0xE699, 0x93C6, 0xE69A, + 0x93C7, 0xE69B, 0x93C8, 0xE69C, 0x93C9, 0xE69D, 0x93CA, 0xF6CB, + 0x93CB, 0xE69E, 0x93CC, 0xE69F, 0x93CD, 0xE6A0, 0x93CE, 0xE740, + 0x93CF, 0xE741, 0x93D0, 0xE742, 0x93D1, 0xE743, 0x93D2, 0xE744, + 0x93D3, 0xE745, 0x93D4, 0xE746, 0x93D5, 0xE747, 0x93D6, 0xF7E9, + 0x93D7, 0xE748, 0x93D8, 0xE749, 0x93D9, 0xE74A, 0x93DA, 0xE74B, + 0x93DB, 0xE74C, 0x93DC, 0xE74D, 0x93DD, 0xE74E, 0x93DE, 0xE74F, + 0x93DF, 0xE750, 0x93E0, 0xE751, 0x93E1, 0xE752, 0x93E2, 0xE753, + 0x93E3, 0xE754, 0x93E4, 0xE755, 0x93E5, 0xE756, 0x93E6, 0xE757, + 0x93E7, 0xE758, 0x93E8, 0xE759, 0x93E9, 0xE75A, 0x93EA, 0xE75B, + 0x93EB, 0xE75C, 0x93EC, 0xE75D, 0x93ED, 0xE75E, 0x93EE, 0xE75F, + 0x93EF, 0xE760, 0x93F0, 0xE761, 0x93F1, 0xE762, 0x93F2, 0xE763, + 0x93F3, 0xE764, 0x93F4, 0xE765, 0x93F5, 0xE766, 0x93F6, 0xE767, + 0x93F7, 0xE768, 0x93F8, 0xE769, 0x93F9, 0xE76A, 0x93FA, 0xE76B, + 0x93FB, 0xE76C, 0x93FC, 0xE76D, 0x93FD, 0xE76E, 0x93FE, 0xE76F, + 0x93FF, 0xE770, 0x9400, 0xE771, 0x9401, 0xE772, 0x9402, 0xE773, + 0x9403, 0xE774, 0x9404, 0xE775, 0x9405, 0xE776, 0x9406, 0xE777, + 0x9407, 0xE778, 0x9408, 0xE779, 0x9409, 0xE77A, 0x940A, 0xE77B, + 0x940B, 0xE77C, 0x940C, 0xE77D, 0x940D, 0xE77E, 0x940E, 0xE780, + 0x940F, 0xE781, 0x9410, 0xE782, 0x9411, 0xE783, 0x9412, 0xE784, + 0x9413, 0xE785, 0x9414, 0xE786, 0x9415, 0xE787, 0x9416, 0xE788, + 0x9417, 0xE789, 0x9418, 0xE78A, 0x9419, 0xE78B, 0x941A, 0xE78C, + 0x941B, 0xE78D, 0x941C, 0xE78E, 0x941D, 0xE78F, 0x941E, 0xE790, + 0x941F, 0xE791, 0x9420, 0xE792, 0x9421, 0xE793, 0x9422, 0xE794, + 0x9423, 0xE795, 0x9424, 0xE796, 0x9425, 0xE797, 0x9426, 0xE798, + 0x9427, 0xE799, 0x9428, 0xE79A, 0x9429, 0xE79B, 0x942A, 0xE79C, + 0x942B, 0xE79D, 0x942C, 0xE79E, 0x942D, 0xE79F, 0x942E, 0xE7A0, + 0x942F, 0xE840, 0x9430, 0xE841, 0x9431, 0xE842, 0x9432, 0xE843, + 0x9433, 0xE844, 0x9434, 0xE845, 0x9435, 0xE846, 0x9436, 0xE847, + 0x9437, 0xE848, 0x9438, 0xE849, 0x9439, 0xE84A, 0x943A, 0xE84B, + 0x943B, 0xE84C, 0x943C, 0xE84D, 0x943D, 0xE84E, 0x943E, 0xF6CD, + 0x943F, 0xE84F, 0x9440, 0xE850, 0x9441, 0xE851, 0x9442, 0xE852, + 0x9443, 0xE853, 0x9444, 0xE854, 0x9445, 0xE855, 0x9446, 0xE856, + 0x9447, 0xE857, 0x9448, 0xE858, 0x9449, 0xE859, 0x944A, 0xE85A, + 0x944B, 0xE85B, 0x944C, 0xE85C, 0x944D, 0xE85D, 0x944E, 0xE85E, + 0x944F, 0xE85F, 0x9450, 0xE860, 0x9451, 0xE861, 0x9452, 0xE862, + 0x9453, 0xE863, 0x9454, 0xE864, 0x9455, 0xE865, 0x9456, 0xE866, + 0x9457, 0xE867, 0x9458, 0xE868, 0x9459, 0xE869, 0x945A, 0xE86A, + 0x945B, 0xE86B, 0x945C, 0xE86C, 0x945D, 0xE86D, 0x945E, 0xE86E, + 0x945F, 0xE86F, 0x9460, 0xE870, 0x9461, 0xE871, 0x9462, 0xE872, + 0x9463, 0xE873, 0x9464, 0xE874, 0x9465, 0xE875, 0x9466, 0xE876, + 0x9467, 0xE877, 0x9468, 0xE878, 0x9469, 0xE879, 0x946A, 0xE87A, + 0x946B, 0xF6CE, 0x946C, 0xE87B, 0x946D, 0xE87C, 0x946E, 0xE87D, + 0x946F, 0xE87E, 0x9470, 0xE880, 0x9471, 0xE881, 0x9472, 0xE882, + 0x9473, 0xE883, 0x9474, 0xE884, 0x9475, 0xE885, 0x9476, 0xE886, + 0x9477, 0xE887, 0x9478, 0xE888, 0x9479, 0xE889, 0x947A, 0xE88A, + 0x947B, 0xE88B, 0x947C, 0xE88C, 0x947D, 0xE88D, 0x947E, 0xE88E, + 0x947F, 0xE88F, 0x9480, 0xE890, 0x9481, 0xE891, 0x9482, 0xE892, + 0x9483, 0xE893, 0x9484, 0xE894, 0x9485, 0xEEC4, 0x9486, 0xEEC5, + 0x9487, 0xEEC6, 0x9488, 0xD5EB, 0x9489, 0xB6A4, 0x948A, 0xEEC8, + 0x948B, 0xEEC7, 0x948C, 0xEEC9, 0x948D, 0xEECA, 0x948E, 0xC7A5, + 0x948F, 0xEECB, 0x9490, 0xEECC, 0x9491, 0xE895, 0x9492, 0xB7B0, + 0x9493, 0xB5F6, 0x9494, 0xEECD, 0x9495, 0xEECF, 0x9496, 0xE896, + 0x9497, 0xEECE, 0x9498, 0xE897, 0x9499, 0xB8C6, 0x949A, 0xEED0, + 0x949B, 0xEED1, 0x949C, 0xEED2, 0x949D, 0xB6DB, 0x949E, 0xB3AE, + 0x949F, 0xD6D3, 0x94A0, 0xC4C6, 0x94A1, 0xB1B5, 0x94A2, 0xB8D6, + 0x94A3, 0xEED3, 0x94A4, 0xEED4, 0x94A5, 0xD4BF, 0x94A6, 0xC7D5, + 0x94A7, 0xBEFB, 0x94A8, 0xCED9, 0x94A9, 0xB9B3, 0x94AA, 0xEED6, + 0x94AB, 0xEED5, 0x94AC, 0xEED8, 0x94AD, 0xEED7, 0x94AE, 0xC5A5, + 0x94AF, 0xEED9, 0x94B0, 0xEEDA, 0x94B1, 0xC7AE, 0x94B2, 0xEEDB, + 0x94B3, 0xC7AF, 0x94B4, 0xEEDC, 0x94B5, 0xB2A7, 0x94B6, 0xEEDD, + 0x94B7, 0xEEDE, 0x94B8, 0xEEDF, 0x94B9, 0xEEE0, 0x94BA, 0xEEE1, + 0x94BB, 0xD7EA, 0x94BC, 0xEEE2, 0x94BD, 0xEEE3, 0x94BE, 0xBCD8, + 0x94BF, 0xEEE4, 0x94C0, 0xD3CB, 0x94C1, 0xCCFA, 0x94C2, 0xB2AC, + 0x94C3, 0xC1E5, 0x94C4, 0xEEE5, 0x94C5, 0xC7A6, 0x94C6, 0xC3AD, + 0x94C7, 0xE898, 0x94C8, 0xEEE6, 0x94C9, 0xEEE7, 0x94CA, 0xEEE8, + 0x94CB, 0xEEE9, 0x94CC, 0xEEEA, 0x94CD, 0xEEEB, 0x94CE, 0xEEEC, + 0x94CF, 0xE899, 0x94D0, 0xEEED, 0x94D1, 0xEEEE, 0x94D2, 0xEEEF, + 0x94D3, 0xE89A, 0x94D4, 0xE89B, 0x94D5, 0xEEF0, 0x94D6, 0xEEF1, + 0x94D7, 0xEEF2, 0x94D8, 0xEEF4, 0x94D9, 0xEEF3, 0x94DA, 0xE89C, + 0x94DB, 0xEEF5, 0x94DC, 0xCDAD, 0x94DD, 0xC2C1, 0x94DE, 0xEEF6, + 0x94DF, 0xEEF7, 0x94E0, 0xEEF8, 0x94E1, 0xD5A1, 0x94E2, 0xEEF9, + 0x94E3, 0xCFB3, 0x94E4, 0xEEFA, 0x94E5, 0xEEFB, 0x94E6, 0xE89D, + 0x94E7, 0xEEFC, 0x94E8, 0xEEFD, 0x94E9, 0xEFA1, 0x94EA, 0xEEFE, + 0x94EB, 0xEFA2, 0x94EC, 0xB8F5, 0x94ED, 0xC3FA, 0x94EE, 0xEFA3, + 0x94EF, 0xEFA4, 0x94F0, 0xBDC2, 0x94F1, 0xD2BF, 0x94F2, 0xB2F9, + 0x94F3, 0xEFA5, 0x94F4, 0xEFA6, 0x94F5, 0xEFA7, 0x94F6, 0xD2F8, + 0x94F7, 0xEFA8, 0x94F8, 0xD6FD, 0x94F9, 0xEFA9, 0x94FA, 0xC6CC, + 0x94FB, 0xE89E, 0x94FC, 0xEFAA, 0x94FD, 0xEFAB, 0x94FE, 0xC1B4, + 0x94FF, 0xEFAC, 0x9500, 0xCFFA, 0x9501, 0xCBF8, 0x9502, 0xEFAE, + 0x9503, 0xEFAD, 0x9504, 0xB3FA, 0x9505, 0xB9F8, 0x9506, 0xEFAF, + 0x9507, 0xEFB0, 0x9508, 0xD0E2, 0x9509, 0xEFB1, 0x950A, 0xEFB2, + 0x950B, 0xB7E6, 0x950C, 0xD0BF, 0x950D, 0xEFB3, 0x950E, 0xEFB4, + 0x950F, 0xEFB5, 0x9510, 0xC8F1, 0x9511, 0xCCE0, 0x9512, 0xEFB6, + 0x9513, 0xEFB7, 0x9514, 0xEFB8, 0x9515, 0xEFB9, 0x9516, 0xEFBA, + 0x9517, 0xD5E0, 0x9518, 0xEFBB, 0x9519, 0xB4ED, 0x951A, 0xC3AA, + 0x951B, 0xEFBC, 0x951C, 0xE89F, 0x951D, 0xEFBD, 0x951E, 0xEFBE, + 0x951F, 0xEFBF, 0x9520, 0xE8A0, 0x9521, 0xCEFD, 0x9522, 0xEFC0, + 0x9523, 0xC2E0, 0x9524, 0xB4B8, 0x9525, 0xD7B6, 0x9526, 0xBDF5, + 0x9527, 0xE940, 0x9528, 0xCFC7, 0x9529, 0xEFC3, 0x952A, 0xEFC1, + 0x952B, 0xEFC2, 0x952C, 0xEFC4, 0x952D, 0xB6A7, 0x952E, 0xBCFC, + 0x952F, 0xBEE2, 0x9530, 0xC3CC, 0x9531, 0xEFC5, 0x9532, 0xEFC6, + 0x9533, 0xE941, 0x9534, 0xEFC7, 0x9535, 0xEFCF, 0x9536, 0xEFC8, + 0x9537, 0xEFC9, 0x9538, 0xEFCA, 0x9539, 0xC7C2, 0x953A, 0xEFF1, + 0x953B, 0xB6CD, 0x953C, 0xEFCB, 0x953D, 0xE942, 0x953E, 0xEFCC, + 0x953F, 0xEFCD, 0x9540, 0xB6C6, 0x9541, 0xC3BE, 0x9542, 0xEFCE, + 0x9543, 0xE943, 0x9544, 0xEFD0, 0x9545, 0xEFD1, 0x9546, 0xEFD2, + 0x9547, 0xD5F2, 0x9548, 0xE944, 0x9549, 0xEFD3, 0x954A, 0xC4F7, + 0x954B, 0xE945, 0x954C, 0xEFD4, 0x954D, 0xC4F8, 0x954E, 0xEFD5, + 0x954F, 0xEFD6, 0x9550, 0xB8E4, 0x9551, 0xB0F7, 0x9552, 0xEFD7, + 0x9553, 0xEFD8, 0x9554, 0xEFD9, 0x9555, 0xE946, 0x9556, 0xEFDA, + 0x9557, 0xEFDB, 0x9558, 0xEFDC, 0x9559, 0xEFDD, 0x955A, 0xE947, + 0x955B, 0xEFDE, 0x955C, 0xBEB5, 0x955D, 0xEFE1, 0x955E, 0xEFDF, + 0x955F, 0xEFE0, 0x9560, 0xE948, 0x9561, 0xEFE2, 0x9562, 0xEFE3, + 0x9563, 0xC1CD, 0x9564, 0xEFE4, 0x9565, 0xEFE5, 0x9566, 0xEFE6, + 0x9567, 0xEFE7, 0x9568, 0xEFE8, 0x9569, 0xEFE9, 0x956A, 0xEFEA, + 0x956B, 0xEFEB, 0x956C, 0xEFEC, 0x956D, 0xC0D8, 0x956E, 0xE949, + 0x956F, 0xEFED, 0x9570, 0xC1AD, 0x9571, 0xEFEE, 0x9572, 0xEFEF, + 0x9573, 0xEFF0, 0x9574, 0xE94A, 0x9575, 0xE94B, 0x9576, 0xCFE2, + 0x9577, 0xE94C, 0x9578, 0xE94D, 0x9579, 0xE94E, 0x957A, 0xE94F, + 0x957B, 0xE950, 0x957C, 0xE951, 0x957D, 0xE952, 0x957E, 0xE953, + 0x957F, 0xB3A4, 0x9580, 0xE954, 0x9581, 0xE955, 0x9582, 0xE956, + 0x9583, 0xE957, 0x9584, 0xE958, 0x9585, 0xE959, 0x9586, 0xE95A, + 0x9587, 0xE95B, 0x9588, 0xE95C, 0x9589, 0xE95D, 0x958A, 0xE95E, + 0x958B, 0xE95F, 0x958C, 0xE960, 0x958D, 0xE961, 0x958E, 0xE962, + 0x958F, 0xE963, 0x9590, 0xE964, 0x9591, 0xE965, 0x9592, 0xE966, + 0x9593, 0xE967, 0x9594, 0xE968, 0x9595, 0xE969, 0x9596, 0xE96A, + 0x9597, 0xE96B, 0x9598, 0xE96C, 0x9599, 0xE96D, 0x959A, 0xE96E, + 0x959B, 0xE96F, 0x959C, 0xE970, 0x959D, 0xE971, 0x959E, 0xE972, + 0x959F, 0xE973, 0x95A0, 0xE974, 0x95A1, 0xE975, 0x95A2, 0xE976, + 0x95A3, 0xE977, 0x95A4, 0xE978, 0x95A5, 0xE979, 0x95A6, 0xE97A, + 0x95A7, 0xE97B, 0x95A8, 0xE97C, 0x95A9, 0xE97D, 0x95AA, 0xE97E, + 0x95AB, 0xE980, 0x95AC, 0xE981, 0x95AD, 0xE982, 0x95AE, 0xE983, + 0x95AF, 0xE984, 0x95B0, 0xE985, 0x95B1, 0xE986, 0x95B2, 0xE987, + 0x95B3, 0xE988, 0x95B4, 0xE989, 0x95B5, 0xE98A, 0x95B6, 0xE98B, + 0x95B7, 0xE98C, 0x95B8, 0xE98D, 0x95B9, 0xE98E, 0x95BA, 0xE98F, + 0x95BB, 0xE990, 0x95BC, 0xE991, 0x95BD, 0xE992, 0x95BE, 0xE993, + 0x95BF, 0xE994, 0x95C0, 0xE995, 0x95C1, 0xE996, 0x95C2, 0xE997, + 0x95C3, 0xE998, 0x95C4, 0xE999, 0x95C5, 0xE99A, 0x95C6, 0xE99B, + 0x95C7, 0xE99C, 0x95C8, 0xE99D, 0x95C9, 0xE99E, 0x95CA, 0xE99F, + 0x95CB, 0xE9A0, 0x95CC, 0xEA40, 0x95CD, 0xEA41, 0x95CE, 0xEA42, + 0x95CF, 0xEA43, 0x95D0, 0xEA44, 0x95D1, 0xEA45, 0x95D2, 0xEA46, + 0x95D3, 0xEA47, 0x95D4, 0xEA48, 0x95D5, 0xEA49, 0x95D6, 0xEA4A, + 0x95D7, 0xEA4B, 0x95D8, 0xEA4C, 0x95D9, 0xEA4D, 0x95DA, 0xEA4E, + 0x95DB, 0xEA4F, 0x95DC, 0xEA50, 0x95DD, 0xEA51, 0x95DE, 0xEA52, + 0x95DF, 0xEA53, 0x95E0, 0xEA54, 0x95E1, 0xEA55, 0x95E2, 0xEA56, + 0x95E3, 0xEA57, 0x95E4, 0xEA58, 0x95E5, 0xEA59, 0x95E6, 0xEA5A, + 0x95E7, 0xEA5B, 0x95E8, 0xC3C5, 0x95E9, 0xE3C5, 0x95EA, 0xC9C1, + 0x95EB, 0xE3C6, 0x95EC, 0xEA5C, 0x95ED, 0xB1D5, 0x95EE, 0xCECA, + 0x95EF, 0xB4B3, 0x95F0, 0xC8F2, 0x95F1, 0xE3C7, 0x95F2, 0xCFD0, + 0x95F3, 0xE3C8, 0x95F4, 0xBCE4, 0x95F5, 0xE3C9, 0x95F6, 0xE3CA, + 0x95F7, 0xC3C6, 0x95F8, 0xD5A2, 0x95F9, 0xC4D6, 0x95FA, 0xB9EB, + 0x95FB, 0xCEC5, 0x95FC, 0xE3CB, 0x95FD, 0xC3F6, 0x95FE, 0xE3CC, + 0x95FF, 0xEA5D, 0x9600, 0xB7A7, 0x9601, 0xB8F3, 0x9602, 0xBAD2, + 0x9603, 0xE3CD, 0x9604, 0xE3CE, 0x9605, 0xD4C4, 0x9606, 0xE3CF, + 0x9607, 0xEA5E, 0x9608, 0xE3D0, 0x9609, 0xD1CB, 0x960A, 0xE3D1, + 0x960B, 0xE3D2, 0x960C, 0xE3D3, 0x960D, 0xE3D4, 0x960E, 0xD1D6, + 0x960F, 0xE3D5, 0x9610, 0xB2FB, 0x9611, 0xC0BB, 0x9612, 0xE3D6, + 0x9613, 0xEA5F, 0x9614, 0xC0AB, 0x9615, 0xE3D7, 0x9616, 0xE3D8, + 0x9617, 0xE3D9, 0x9618, 0xEA60, 0x9619, 0xE3DA, 0x961A, 0xE3DB, + 0x961B, 0xEA61, 0x961C, 0xB8B7, 0x961D, 0xDAE2, 0x961E, 0xEA62, + 0x961F, 0xB6D3, 0x9620, 0xEA63, 0x9621, 0xDAE4, 0x9622, 0xDAE3, + 0x9623, 0xEA64, 0x9624, 0xEA65, 0x9625, 0xEA66, 0x9626, 0xEA67, + 0x9627, 0xEA68, 0x9628, 0xEA69, 0x9629, 0xEA6A, 0x962A, 0xDAE6, + 0x962B, 0xEA6B, 0x962C, 0xEA6C, 0x962D, 0xEA6D, 0x962E, 0xC8EE, + 0x962F, 0xEA6E, 0x9630, 0xEA6F, 0x9631, 0xDAE5, 0x9632, 0xB7C0, + 0x9633, 0xD1F4, 0x9634, 0xD2F5, 0x9635, 0xD5F3, 0x9636, 0xBDD7, + 0x9637, 0xEA70, 0x9638, 0xEA71, 0x9639, 0xEA72, 0x963A, 0xEA73, + 0x963B, 0xD7E8, 0x963C, 0xDAE8, 0x963D, 0xDAE7, 0x963E, 0xEA74, + 0x963F, 0xB0A2, 0x9640, 0xCDD3, 0x9641, 0xEA75, 0x9642, 0xDAE9, + 0x9643, 0xEA76, 0x9644, 0xB8BD, 0x9645, 0xBCCA, 0x9646, 0xC2BD, + 0x9647, 0xC2A4, 0x9648, 0xB3C2, 0x9649, 0xDAEA, 0x964A, 0xEA77, + 0x964B, 0xC2AA, 0x964C, 0xC4B0, 0x964D, 0xBDB5, 0x964E, 0xEA78, + 0x964F, 0xEA79, 0x9650, 0xCFDE, 0x9651, 0xEA7A, 0x9652, 0xEA7B, + 0x9653, 0xEA7C, 0x9654, 0xDAEB, 0x9655, 0xC9C2, 0x9656, 0xEA7D, + 0x9657, 0xEA7E, 0x9658, 0xEA80, 0x9659, 0xEA81, 0x965A, 0xEA82, + 0x965B, 0xB1DD, 0x965C, 0xEA83, 0x965D, 0xEA84, 0x965E, 0xEA85, + 0x965F, 0xDAEC, 0x9660, 0xEA86, 0x9661, 0xB6B8, 0x9662, 0xD4BA, + 0x9663, 0xEA87, 0x9664, 0xB3FD, 0x9665, 0xEA88, 0x9666, 0xEA89, + 0x9667, 0xDAED, 0x9668, 0xD4C9, 0x9669, 0xCFD5, 0x966A, 0xC5E3, + 0x966B, 0xEA8A, 0x966C, 0xDAEE, 0x966D, 0xEA8B, 0x966E, 0xEA8C, + 0x966F, 0xEA8D, 0x9670, 0xEA8E, 0x9671, 0xEA8F, 0x9672, 0xDAEF, + 0x9673, 0xEA90, 0x9674, 0xDAF0, 0x9675, 0xC1EA, 0x9676, 0xCCD5, + 0x9677, 0xCFDD, 0x9678, 0xEA91, 0x9679, 0xEA92, 0x967A, 0xEA93, + 0x967B, 0xEA94, 0x967C, 0xEA95, 0x967D, 0xEA96, 0x967E, 0xEA97, + 0x967F, 0xEA98, 0x9680, 0xEA99, 0x9681, 0xEA9A, 0x9682, 0xEA9B, + 0x9683, 0xEA9C, 0x9684, 0xEA9D, 0x9685, 0xD3E7, 0x9686, 0xC2A1, + 0x9687, 0xEA9E, 0x9688, 0xDAF1, 0x9689, 0xEA9F, 0x968A, 0xEAA0, + 0x968B, 0xCBE5, 0x968C, 0xEB40, 0x968D, 0xDAF2, 0x968E, 0xEB41, + 0x968F, 0xCBE6, 0x9690, 0xD2FE, 0x9691, 0xEB42, 0x9692, 0xEB43, + 0x9693, 0xEB44, 0x9694, 0xB8F4, 0x9695, 0xEB45, 0x9696, 0xEB46, + 0x9697, 0xDAF3, 0x9698, 0xB0AF, 0x9699, 0xCFB6, 0x969A, 0xEB47, + 0x969B, 0xEB48, 0x969C, 0xD5CF, 0x969D, 0xEB49, 0x969E, 0xEB4A, + 0x969F, 0xEB4B, 0x96A0, 0xEB4C, 0x96A1, 0xEB4D, 0x96A2, 0xEB4E, + 0x96A3, 0xEB4F, 0x96A4, 0xEB50, 0x96A5, 0xEB51, 0x96A6, 0xEB52, + 0x96A7, 0xCBED, 0x96A8, 0xEB53, 0x96A9, 0xEB54, 0x96AA, 0xEB55, + 0x96AB, 0xEB56, 0x96AC, 0xEB57, 0x96AD, 0xEB58, 0x96AE, 0xEB59, + 0x96AF, 0xEB5A, 0x96B0, 0xDAF4, 0x96B1, 0xEB5B, 0x96B2, 0xEB5C, + 0x96B3, 0xE3C4, 0x96B4, 0xEB5D, 0x96B5, 0xEB5E, 0x96B6, 0xC1A5, + 0x96B7, 0xEB5F, 0x96B8, 0xEB60, 0x96B9, 0xF6BF, 0x96BA, 0xEB61, + 0x96BB, 0xEB62, 0x96BC, 0xF6C0, 0x96BD, 0xF6C1, 0x96BE, 0xC4D1, + 0x96BF, 0xEB63, 0x96C0, 0xC8B8, 0x96C1, 0xD1E3, 0x96C2, 0xEB64, + 0x96C3, 0xEB65, 0x96C4, 0xD0DB, 0x96C5, 0xD1C5, 0x96C6, 0xBCAF, + 0x96C7, 0xB9CD, 0x96C8, 0xEB66, 0x96C9, 0xEFF4, 0x96CA, 0xEB67, + 0x96CB, 0xEB68, 0x96CC, 0xB4C6, 0x96CD, 0xD3BA, 0x96CE, 0xF6C2, + 0x96CF, 0xB3FB, 0x96D0, 0xEB69, 0x96D1, 0xEB6A, 0x96D2, 0xF6C3, + 0x96D3, 0xEB6B, 0x96D4, 0xEB6C, 0x96D5, 0xB5F1, 0x96D6, 0xEB6D, + 0x96D7, 0xEB6E, 0x96D8, 0xEB6F, 0x96D9, 0xEB70, 0x96DA, 0xEB71, + 0x96DB, 0xEB72, 0x96DC, 0xEB73, 0x96DD, 0xEB74, 0x96DE, 0xEB75, + 0x96DF, 0xEB76, 0x96E0, 0xF6C5, 0x96E1, 0xEB77, 0x96E2, 0xEB78, + 0x96E3, 0xEB79, 0x96E4, 0xEB7A, 0x96E5, 0xEB7B, 0x96E6, 0xEB7C, + 0x96E7, 0xEB7D, 0x96E8, 0xD3EA, 0x96E9, 0xF6A7, 0x96EA, 0xD1A9, + 0x96EB, 0xEB7E, 0x96EC, 0xEB80, 0x96ED, 0xEB81, 0x96EE, 0xEB82, + 0x96EF, 0xF6A9, 0x96F0, 0xEB83, 0x96F1, 0xEB84, 0x96F2, 0xEB85, + 0x96F3, 0xF6A8, 0x96F4, 0xEB86, 0x96F5, 0xEB87, 0x96F6, 0xC1E3, + 0x96F7, 0xC0D7, 0x96F8, 0xEB88, 0x96F9, 0xB1A2, 0x96FA, 0xEB89, + 0x96FB, 0xEB8A, 0x96FC, 0xEB8B, 0x96FD, 0xEB8C, 0x96FE, 0xCEED, + 0x96FF, 0xEB8D, 0x9700, 0xD0E8, 0x9701, 0xF6AB, 0x9702, 0xEB8E, + 0x9703, 0xEB8F, 0x9704, 0xCFF6, 0x9705, 0xEB90, 0x9706, 0xF6AA, + 0x9707, 0xD5F0, 0x9708, 0xF6AC, 0x9709, 0xC3B9, 0x970A, 0xEB91, + 0x970B, 0xEB92, 0x970C, 0xEB93, 0x970D, 0xBBF4, 0x970E, 0xF6AE, + 0x970F, 0xF6AD, 0x9710, 0xEB94, 0x9711, 0xEB95, 0x9712, 0xEB96, + 0x9713, 0xC4DE, 0x9714, 0xEB97, 0x9715, 0xEB98, 0x9716, 0xC1D8, + 0x9717, 0xEB99, 0x9718, 0xEB9A, 0x9719, 0xEB9B, 0x971A, 0xEB9C, + 0x971B, 0xEB9D, 0x971C, 0xCBAA, 0x971D, 0xEB9E, 0x971E, 0xCFBC, + 0x971F, 0xEB9F, 0x9720, 0xEBA0, 0x9721, 0xEC40, 0x9722, 0xEC41, + 0x9723, 0xEC42, 0x9724, 0xEC43, 0x9725, 0xEC44, 0x9726, 0xEC45, + 0x9727, 0xEC46, 0x9728, 0xEC47, 0x9729, 0xEC48, 0x972A, 0xF6AF, + 0x972B, 0xEC49, 0x972C, 0xEC4A, 0x972D, 0xF6B0, 0x972E, 0xEC4B, + 0x972F, 0xEC4C, 0x9730, 0xF6B1, 0x9731, 0xEC4D, 0x9732, 0xC2B6, + 0x9733, 0xEC4E, 0x9734, 0xEC4F, 0x9735, 0xEC50, 0x9736, 0xEC51, + 0x9737, 0xEC52, 0x9738, 0xB0D4, 0x9739, 0xC5F9, 0x973A, 0xEC53, + 0x973B, 0xEC54, 0x973C, 0xEC55, 0x973D, 0xEC56, 0x973E, 0xF6B2, + 0x973F, 0xEC57, 0x9740, 0xEC58, 0x9741, 0xEC59, 0x9742, 0xEC5A, + 0x9743, 0xEC5B, 0x9744, 0xEC5C, 0x9745, 0xEC5D, 0x9746, 0xEC5E, + 0x9747, 0xEC5F, 0x9748, 0xEC60, 0x9749, 0xEC61, 0x974A, 0xEC62, + 0x974B, 0xEC63, 0x974C, 0xEC64, 0x974D, 0xEC65, 0x974E, 0xEC66, + 0x974F, 0xEC67, 0x9750, 0xEC68, 0x9751, 0xEC69, 0x9752, 0xC7E0, + 0x9753, 0xF6A6, 0x9754, 0xEC6A, 0x9755, 0xEC6B, 0x9756, 0xBEB8, + 0x9757, 0xEC6C, 0x9758, 0xEC6D, 0x9759, 0xBEB2, 0x975A, 0xEC6E, + 0x975B, 0xB5E5, 0x975C, 0xEC6F, 0x975D, 0xEC70, 0x975E, 0xB7C7, + 0x975F, 0xEC71, 0x9760, 0xBFBF, 0x9761, 0xC3D2, 0x9762, 0xC3E6, + 0x9763, 0xEC72, 0x9764, 0xEC73, 0x9765, 0xD8CC, 0x9766, 0xEC74, + 0x9767, 0xEC75, 0x9768, 0xEC76, 0x9769, 0xB8EF, 0x976A, 0xEC77, + 0x976B, 0xEC78, 0x976C, 0xEC79, 0x976D, 0xEC7A, 0x976E, 0xEC7B, + 0x976F, 0xEC7C, 0x9770, 0xEC7D, 0x9771, 0xEC7E, 0x9772, 0xEC80, + 0x9773, 0xBDF9, 0x9774, 0xD1A5, 0x9775, 0xEC81, 0x9776, 0xB0D0, + 0x9777, 0xEC82, 0x9778, 0xEC83, 0x9779, 0xEC84, 0x977A, 0xEC85, + 0x977B, 0xEC86, 0x977C, 0xF7B0, 0x977D, 0xEC87, 0x977E, 0xEC88, + 0x977F, 0xEC89, 0x9780, 0xEC8A, 0x9781, 0xEC8B, 0x9782, 0xEC8C, + 0x9783, 0xEC8D, 0x9784, 0xEC8E, 0x9785, 0xF7B1, 0x9786, 0xEC8F, + 0x9787, 0xEC90, 0x9788, 0xEC91, 0x9789, 0xEC92, 0x978A, 0xEC93, + 0x978B, 0xD0AC, 0x978C, 0xEC94, 0x978D, 0xB0B0, 0x978E, 0xEC95, + 0x978F, 0xEC96, 0x9790, 0xEC97, 0x9791, 0xF7B2, 0x9792, 0xF7B3, + 0x9793, 0xEC98, 0x9794, 0xF7B4, 0x9795, 0xEC99, 0x9796, 0xEC9A, + 0x9797, 0xEC9B, 0x9798, 0xC7CA, 0x9799, 0xEC9C, 0x979A, 0xEC9D, + 0x979B, 0xEC9E, 0x979C, 0xEC9F, 0x979D, 0xECA0, 0x979E, 0xED40, + 0x979F, 0xED41, 0x97A0, 0xBECF, 0x97A1, 0xED42, 0x97A2, 0xED43, + 0x97A3, 0xF7B7, 0x97A4, 0xED44, 0x97A5, 0xED45, 0x97A6, 0xED46, + 0x97A7, 0xED47, 0x97A8, 0xED48, 0x97A9, 0xED49, 0x97AA, 0xED4A, + 0x97AB, 0xF7B6, 0x97AC, 0xED4B, 0x97AD, 0xB1DE, 0x97AE, 0xED4C, + 0x97AF, 0xF7B5, 0x97B0, 0xED4D, 0x97B1, 0xED4E, 0x97B2, 0xF7B8, + 0x97B3, 0xED4F, 0x97B4, 0xF7B9, 0x97B5, 0xED50, 0x97B6, 0xED51, + 0x97B7, 0xED52, 0x97B8, 0xED53, 0x97B9, 0xED54, 0x97BA, 0xED55, + 0x97BB, 0xED56, 0x97BC, 0xED57, 0x97BD, 0xED58, 0x97BE, 0xED59, + 0x97BF, 0xED5A, 0x97C0, 0xED5B, 0x97C1, 0xED5C, 0x97C2, 0xED5D, + 0x97C3, 0xED5E, 0x97C4, 0xED5F, 0x97C5, 0xED60, 0x97C6, 0xED61, + 0x97C7, 0xED62, 0x97C8, 0xED63, 0x97C9, 0xED64, 0x97CA, 0xED65, + 0x97CB, 0xED66, 0x97CC, 0xED67, 0x97CD, 0xED68, 0x97CE, 0xED69, + 0x97CF, 0xED6A, 0x97D0, 0xED6B, 0x97D1, 0xED6C, 0x97D2, 0xED6D, + 0x97D3, 0xED6E, 0x97D4, 0xED6F, 0x97D5, 0xED70, 0x97D6, 0xED71, + 0x97D7, 0xED72, 0x97D8, 0xED73, 0x97D9, 0xED74, 0x97DA, 0xED75, + 0x97DB, 0xED76, 0x97DC, 0xED77, 0x97DD, 0xED78, 0x97DE, 0xED79, + 0x97DF, 0xED7A, 0x97E0, 0xED7B, 0x97E1, 0xED7C, 0x97E2, 0xED7D, + 0x97E3, 0xED7E, 0x97E4, 0xED80, 0x97E5, 0xED81, 0x97E6, 0xCEA4, + 0x97E7, 0xC8CD, 0x97E8, 0xED82, 0x97E9, 0xBAAB, 0x97EA, 0xE8B8, + 0x97EB, 0xE8B9, 0x97EC, 0xE8BA, 0x97ED, 0xBEC2, 0x97EE, 0xED83, + 0x97EF, 0xED84, 0x97F0, 0xED85, 0x97F1, 0xED86, 0x97F2, 0xED87, + 0x97F3, 0xD2F4, 0x97F4, 0xED88, 0x97F5, 0xD4CF, 0x97F6, 0xC9D8, + 0x97F7, 0xED89, 0x97F8, 0xED8A, 0x97F9, 0xED8B, 0x97FA, 0xED8C, + 0x97FB, 0xED8D, 0x97FC, 0xED8E, 0x97FD, 0xED8F, 0x97FE, 0xED90, + 0x97FF, 0xED91, 0x9800, 0xED92, 0x9801, 0xED93, 0x9802, 0xED94, + 0x9803, 0xED95, 0x9804, 0xED96, 0x9805, 0xED97, 0x9806, 0xED98, + 0x9807, 0xED99, 0x9808, 0xED9A, 0x9809, 0xED9B, 0x980A, 0xED9C, + 0x980B, 0xED9D, 0x980C, 0xED9E, 0x980D, 0xED9F, 0x980E, 0xEDA0, + 0x980F, 0xEE40, 0x9810, 0xEE41, 0x9811, 0xEE42, 0x9812, 0xEE43, + 0x9813, 0xEE44, 0x9814, 0xEE45, 0x9815, 0xEE46, 0x9816, 0xEE47, + 0x9817, 0xEE48, 0x9818, 0xEE49, 0x9819, 0xEE4A, 0x981A, 0xEE4B, + 0x981B, 0xEE4C, 0x981C, 0xEE4D, 0x981D, 0xEE4E, 0x981E, 0xEE4F, + 0x981F, 0xEE50, 0x9820, 0xEE51, 0x9821, 0xEE52, 0x9822, 0xEE53, + 0x9823, 0xEE54, 0x9824, 0xEE55, 0x9825, 0xEE56, 0x9826, 0xEE57, + 0x9827, 0xEE58, 0x9828, 0xEE59, 0x9829, 0xEE5A, 0x982A, 0xEE5B, + 0x982B, 0xEE5C, 0x982C, 0xEE5D, 0x982D, 0xEE5E, 0x982E, 0xEE5F, + 0x982F, 0xEE60, 0x9830, 0xEE61, 0x9831, 0xEE62, 0x9832, 0xEE63, + 0x9833, 0xEE64, 0x9834, 0xEE65, 0x9835, 0xEE66, 0x9836, 0xEE67, + 0x9837, 0xEE68, 0x9838, 0xEE69, 0x9839, 0xEE6A, 0x983A, 0xEE6B, + 0x983B, 0xEE6C, 0x983C, 0xEE6D, 0x983D, 0xEE6E, 0x983E, 0xEE6F, + 0x983F, 0xEE70, 0x9840, 0xEE71, 0x9841, 0xEE72, 0x9842, 0xEE73, + 0x9843, 0xEE74, 0x9844, 0xEE75, 0x9845, 0xEE76, 0x9846, 0xEE77, + 0x9847, 0xEE78, 0x9848, 0xEE79, 0x9849, 0xEE7A, 0x984A, 0xEE7B, + 0x984B, 0xEE7C, 0x984C, 0xEE7D, 0x984D, 0xEE7E, 0x984E, 0xEE80, + 0x984F, 0xEE81, 0x9850, 0xEE82, 0x9851, 0xEE83, 0x9852, 0xEE84, + 0x9853, 0xEE85, 0x9854, 0xEE86, 0x9855, 0xEE87, 0x9856, 0xEE88, + 0x9857, 0xEE89, 0x9858, 0xEE8A, 0x9859, 0xEE8B, 0x985A, 0xEE8C, + 0x985B, 0xEE8D, 0x985C, 0xEE8E, 0x985D, 0xEE8F, 0x985E, 0xEE90, + 0x985F, 0xEE91, 0x9860, 0xEE92, 0x9861, 0xEE93, 0x9862, 0xEE94, + 0x9863, 0xEE95, 0x9864, 0xEE96, 0x9865, 0xEE97, 0x9866, 0xEE98, + 0x9867, 0xEE99, 0x9868, 0xEE9A, 0x9869, 0xEE9B, 0x986A, 0xEE9C, + 0x986B, 0xEE9D, 0x986C, 0xEE9E, 0x986D, 0xEE9F, 0x986E, 0xEEA0, + 0x986F, 0xEF40, 0x9870, 0xEF41, 0x9871, 0xEF42, 0x9872, 0xEF43, + 0x9873, 0xEF44, 0x9874, 0xEF45, 0x9875, 0xD2B3, 0x9876, 0xB6A5, + 0x9877, 0xC7EA, 0x9878, 0xF1FC, 0x9879, 0xCFEE, 0x987A, 0xCBB3, + 0x987B, 0xD0EB, 0x987C, 0xE7EF, 0x987D, 0xCDE7, 0x987E, 0xB9CB, + 0x987F, 0xB6D9, 0x9880, 0xF1FD, 0x9881, 0xB0E4, 0x9882, 0xCBCC, + 0x9883, 0xF1FE, 0x9884, 0xD4A4, 0x9885, 0xC2AD, 0x9886, 0xC1EC, + 0x9887, 0xC6C4, 0x9888, 0xBEB1, 0x9889, 0xF2A1, 0x988A, 0xBCD5, + 0x988B, 0xEF46, 0x988C, 0xF2A2, 0x988D, 0xF2A3, 0x988E, 0xEF47, + 0x988F, 0xF2A4, 0x9890, 0xD2C3, 0x9891, 0xC6B5, 0x9892, 0xEF48, + 0x9893, 0xCDC7, 0x9894, 0xF2A5, 0x9895, 0xEF49, 0x9896, 0xD3B1, + 0x9897, 0xBFC5, 0x9898, 0xCCE2, 0x9899, 0xEF4A, 0x989A, 0xF2A6, + 0x989B, 0xF2A7, 0x989C, 0xD1D5, 0x989D, 0xB6EE, 0x989E, 0xF2A8, + 0x989F, 0xF2A9, 0x98A0, 0xB5DF, 0x98A1, 0xF2AA, 0x98A2, 0xF2AB, + 0x98A3, 0xEF4B, 0x98A4, 0xB2FC, 0x98A5, 0xF2AC, 0x98A6, 0xF2AD, + 0x98A7, 0xC8A7, 0x98A8, 0xEF4C, 0x98A9, 0xEF4D, 0x98AA, 0xEF4E, + 0x98AB, 0xEF4F, 0x98AC, 0xEF50, 0x98AD, 0xEF51, 0x98AE, 0xEF52, + 0x98AF, 0xEF53, 0x98B0, 0xEF54, 0x98B1, 0xEF55, 0x98B2, 0xEF56, + 0x98B3, 0xEF57, 0x98B4, 0xEF58, 0x98B5, 0xEF59, 0x98B6, 0xEF5A, + 0x98B7, 0xEF5B, 0x98B8, 0xEF5C, 0x98B9, 0xEF5D, 0x98BA, 0xEF5E, + 0x98BB, 0xEF5F, 0x98BC, 0xEF60, 0x98BD, 0xEF61, 0x98BE, 0xEF62, + 0x98BF, 0xEF63, 0x98C0, 0xEF64, 0x98C1, 0xEF65, 0x98C2, 0xEF66, + 0x98C3, 0xEF67, 0x98C4, 0xEF68, 0x98C5, 0xEF69, 0x98C6, 0xEF6A, + 0x98C7, 0xEF6B, 0x98C8, 0xEF6C, 0x98C9, 0xEF6D, 0x98CA, 0xEF6E, + 0x98CB, 0xEF6F, 0x98CC, 0xEF70, 0x98CD, 0xEF71, 0x98CE, 0xB7E7, + 0x98CF, 0xEF72, 0x98D0, 0xEF73, 0x98D1, 0xECA9, 0x98D2, 0xECAA, + 0x98D3, 0xECAB, 0x98D4, 0xEF74, 0x98D5, 0xECAC, 0x98D6, 0xEF75, + 0x98D7, 0xEF76, 0x98D8, 0xC6AE, 0x98D9, 0xECAD, 0x98DA, 0xECAE, + 0x98DB, 0xEF77, 0x98DC, 0xEF78, 0x98DD, 0xEF79, 0x98DE, 0xB7C9, + 0x98DF, 0xCAB3, 0x98E0, 0xEF7A, 0x98E1, 0xEF7B, 0x98E2, 0xEF7C, + 0x98E3, 0xEF7D, 0x98E4, 0xEF7E, 0x98E5, 0xEF80, 0x98E6, 0xEF81, + 0x98E7, 0xE2B8, 0x98E8, 0xF7CF, 0x98E9, 0xEF82, 0x98EA, 0xEF83, + 0x98EB, 0xEF84, 0x98EC, 0xEF85, 0x98ED, 0xEF86, 0x98EE, 0xEF87, + 0x98EF, 0xEF88, 0x98F0, 0xEF89, 0x98F1, 0xEF8A, 0x98F2, 0xEF8B, + 0x98F3, 0xEF8C, 0x98F4, 0xEF8D, 0x98F5, 0xEF8E, 0x98F6, 0xEF8F, + 0x98F7, 0xEF90, 0x98F8, 0xEF91, 0x98F9, 0xEF92, 0x98FA, 0xEF93, + 0x98FB, 0xEF94, 0x98FC, 0xEF95, 0x98FD, 0xEF96, 0x98FE, 0xEF97, + 0x98FF, 0xEF98, 0x9900, 0xEF99, 0x9901, 0xEF9A, 0x9902, 0xEF9B, + 0x9903, 0xEF9C, 0x9904, 0xEF9D, 0x9905, 0xEF9E, 0x9906, 0xEF9F, + 0x9907, 0xEFA0, 0x9908, 0xF040, 0x9909, 0xF041, 0x990A, 0xF042, + 0x990B, 0xF043, 0x990C, 0xF044, 0x990D, 0xF7D0, 0x990E, 0xF045, + 0x990F, 0xF046, 0x9910, 0xB2CD, 0x9911, 0xF047, 0x9912, 0xF048, + 0x9913, 0xF049, 0x9914, 0xF04A, 0x9915, 0xF04B, 0x9916, 0xF04C, + 0x9917, 0xF04D, 0x9918, 0xF04E, 0x9919, 0xF04F, 0x991A, 0xF050, + 0x991B, 0xF051, 0x991C, 0xF052, 0x991D, 0xF053, 0x991E, 0xF054, + 0x991F, 0xF055, 0x9920, 0xF056, 0x9921, 0xF057, 0x9922, 0xF058, + 0x9923, 0xF059, 0x9924, 0xF05A, 0x9925, 0xF05B, 0x9926, 0xF05C, + 0x9927, 0xF05D, 0x9928, 0xF05E, 0x9929, 0xF05F, 0x992A, 0xF060, + 0x992B, 0xF061, 0x992C, 0xF062, 0x992D, 0xF063, 0x992E, 0xF7D1, + 0x992F, 0xF064, 0x9930, 0xF065, 0x9931, 0xF066, 0x9932, 0xF067, + 0x9933, 0xF068, 0x9934, 0xF069, 0x9935, 0xF06A, 0x9936, 0xF06B, + 0x9937, 0xF06C, 0x9938, 0xF06D, 0x9939, 0xF06E, 0x993A, 0xF06F, + 0x993B, 0xF070, 0x993C, 0xF071, 0x993D, 0xF072, 0x993E, 0xF073, + 0x993F, 0xF074, 0x9940, 0xF075, 0x9941, 0xF076, 0x9942, 0xF077, + 0x9943, 0xF078, 0x9944, 0xF079, 0x9945, 0xF07A, 0x9946, 0xF07B, + 0x9947, 0xF07C, 0x9948, 0xF07D, 0x9949, 0xF07E, 0x994A, 0xF080, + 0x994B, 0xF081, 0x994C, 0xF082, 0x994D, 0xF083, 0x994E, 0xF084, + 0x994F, 0xF085, 0x9950, 0xF086, 0x9951, 0xF087, 0x9952, 0xF088, + 0x9953, 0xF089, 0x9954, 0xF7D3, 0x9955, 0xF7D2, 0x9956, 0xF08A, + 0x9957, 0xF08B, 0x9958, 0xF08C, 0x9959, 0xF08D, 0x995A, 0xF08E, + 0x995B, 0xF08F, 0x995C, 0xF090, 0x995D, 0xF091, 0x995E, 0xF092, + 0x995F, 0xF093, 0x9960, 0xF094, 0x9961, 0xF095, 0x9962, 0xF096, + 0x9963, 0xE2BB, 0x9964, 0xF097, 0x9965, 0xBCA2, 0x9966, 0xF098, + 0x9967, 0xE2BC, 0x9968, 0xE2BD, 0x9969, 0xE2BE, 0x996A, 0xE2BF, + 0x996B, 0xE2C0, 0x996C, 0xE2C1, 0x996D, 0xB7B9, 0x996E, 0xD2FB, + 0x996F, 0xBDA4, 0x9970, 0xCACE, 0x9971, 0xB1A5, 0x9972, 0xCBC7, + 0x9973, 0xF099, 0x9974, 0xE2C2, 0x9975, 0xB6FC, 0x9976, 0xC8C4, + 0x9977, 0xE2C3, 0x9978, 0xF09A, 0x9979, 0xF09B, 0x997A, 0xBDC8, + 0x997B, 0xF09C, 0x997C, 0xB1FD, 0x997D, 0xE2C4, 0x997E, 0xF09D, + 0x997F, 0xB6F6, 0x9980, 0xE2C5, 0x9981, 0xC4D9, 0x9982, 0xF09E, + 0x9983, 0xF09F, 0x9984, 0xE2C6, 0x9985, 0xCFDA, 0x9986, 0xB9DD, + 0x9987, 0xE2C7, 0x9988, 0xC0A1, 0x9989, 0xF0A0, 0x998A, 0xE2C8, + 0x998B, 0xB2F6, 0x998C, 0xF140, 0x998D, 0xE2C9, 0x998E, 0xF141, + 0x998F, 0xC1F3, 0x9990, 0xE2CA, 0x9991, 0xE2CB, 0x9992, 0xC2F8, + 0x9993, 0xE2CC, 0x9994, 0xE2CD, 0x9995, 0xE2CE, 0x9996, 0xCAD7, + 0x9997, 0xD8B8, 0x9998, 0xD9E5, 0x9999, 0xCFE3, 0x999A, 0xF142, + 0x999B, 0xF143, 0x999C, 0xF144, 0x999D, 0xF145, 0x999E, 0xF146, + 0x999F, 0xF147, 0x99A0, 0xF148, 0x99A1, 0xF149, 0x99A2, 0xF14A, + 0x99A3, 0xF14B, 0x99A4, 0xF14C, 0x99A5, 0xF0A5, 0x99A6, 0xF14D, + 0x99A7, 0xF14E, 0x99A8, 0xDCB0, 0x99A9, 0xF14F, 0x99AA, 0xF150, + 0x99AB, 0xF151, 0x99AC, 0xF152, 0x99AD, 0xF153, 0x99AE, 0xF154, + 0x99AF, 0xF155, 0x99B0, 0xF156, 0x99B1, 0xF157, 0x99B2, 0xF158, + 0x99B3, 0xF159, 0x99B4, 0xF15A, 0x99B5, 0xF15B, 0x99B6, 0xF15C, + 0x99B7, 0xF15D, 0x99B8, 0xF15E, 0x99B9, 0xF15F, 0x99BA, 0xF160, + 0x99BB, 0xF161, 0x99BC, 0xF162, 0x99BD, 0xF163, 0x99BE, 0xF164, + 0x99BF, 0xF165, 0x99C0, 0xF166, 0x99C1, 0xF167, 0x99C2, 0xF168, + 0x99C3, 0xF169, 0x99C4, 0xF16A, 0x99C5, 0xF16B, 0x99C6, 0xF16C, + 0x99C7, 0xF16D, 0x99C8, 0xF16E, 0x99C9, 0xF16F, 0x99CA, 0xF170, + 0x99CB, 0xF171, 0x99CC, 0xF172, 0x99CD, 0xF173, 0x99CE, 0xF174, + 0x99CF, 0xF175, 0x99D0, 0xF176, 0x99D1, 0xF177, 0x99D2, 0xF178, + 0x99D3, 0xF179, 0x99D4, 0xF17A, 0x99D5, 0xF17B, 0x99D6, 0xF17C, + 0x99D7, 0xF17D, 0x99D8, 0xF17E, 0x99D9, 0xF180, 0x99DA, 0xF181, + 0x99DB, 0xF182, 0x99DC, 0xF183, 0x99DD, 0xF184, 0x99DE, 0xF185, + 0x99DF, 0xF186, 0x99E0, 0xF187, 0x99E1, 0xF188, 0x99E2, 0xF189, + 0x99E3, 0xF18A, 0x99E4, 0xF18B, 0x99E5, 0xF18C, 0x99E6, 0xF18D, + 0x99E7, 0xF18E, 0x99E8, 0xF18F, 0x99E9, 0xF190, 0x99EA, 0xF191, + 0x99EB, 0xF192, 0x99EC, 0xF193, 0x99ED, 0xF194, 0x99EE, 0xF195, + 0x99EF, 0xF196, 0x99F0, 0xF197, 0x99F1, 0xF198, 0x99F2, 0xF199, + 0x99F3, 0xF19A, 0x99F4, 0xF19B, 0x99F5, 0xF19C, 0x99F6, 0xF19D, + 0x99F7, 0xF19E, 0x99F8, 0xF19F, 0x99F9, 0xF1A0, 0x99FA, 0xF240, + 0x99FB, 0xF241, 0x99FC, 0xF242, 0x99FD, 0xF243, 0x99FE, 0xF244, + 0x99FF, 0xF245, 0x9A00, 0xF246, 0x9A01, 0xF247, 0x9A02, 0xF248, + 0x9A03, 0xF249, 0x9A04, 0xF24A, 0x9A05, 0xF24B, 0x9A06, 0xF24C, + 0x9A07, 0xF24D, 0x9A08, 0xF24E, 0x9A09, 0xF24F, 0x9A0A, 0xF250, + 0x9A0B, 0xF251, 0x9A0C, 0xF252, 0x9A0D, 0xF253, 0x9A0E, 0xF254, + 0x9A0F, 0xF255, 0x9A10, 0xF256, 0x9A11, 0xF257, 0x9A12, 0xF258, + 0x9A13, 0xF259, 0x9A14, 0xF25A, 0x9A15, 0xF25B, 0x9A16, 0xF25C, + 0x9A17, 0xF25D, 0x9A18, 0xF25E, 0x9A19, 0xF25F, 0x9A1A, 0xF260, + 0x9A1B, 0xF261, 0x9A1C, 0xF262, 0x9A1D, 0xF263, 0x9A1E, 0xF264, + 0x9A1F, 0xF265, 0x9A20, 0xF266, 0x9A21, 0xF267, 0x9A22, 0xF268, + 0x9A23, 0xF269, 0x9A24, 0xF26A, 0x9A25, 0xF26B, 0x9A26, 0xF26C, + 0x9A27, 0xF26D, 0x9A28, 0xF26E, 0x9A29, 0xF26F, 0x9A2A, 0xF270, + 0x9A2B, 0xF271, 0x9A2C, 0xF272, 0x9A2D, 0xF273, 0x9A2E, 0xF274, + 0x9A2F, 0xF275, 0x9A30, 0xF276, 0x9A31, 0xF277, 0x9A32, 0xF278, + 0x9A33, 0xF279, 0x9A34, 0xF27A, 0x9A35, 0xF27B, 0x9A36, 0xF27C, + 0x9A37, 0xF27D, 0x9A38, 0xF27E, 0x9A39, 0xF280, 0x9A3A, 0xF281, + 0x9A3B, 0xF282, 0x9A3C, 0xF283, 0x9A3D, 0xF284, 0x9A3E, 0xF285, + 0x9A3F, 0xF286, 0x9A40, 0xF287, 0x9A41, 0xF288, 0x9A42, 0xF289, + 0x9A43, 0xF28A, 0x9A44, 0xF28B, 0x9A45, 0xF28C, 0x9A46, 0xF28D, + 0x9A47, 0xF28E, 0x9A48, 0xF28F, 0x9A49, 0xF290, 0x9A4A, 0xF291, + 0x9A4B, 0xF292, 0x9A4C, 0xF293, 0x9A4D, 0xF294, 0x9A4E, 0xF295, + 0x9A4F, 0xF296, 0x9A50, 0xF297, 0x9A51, 0xF298, 0x9A52, 0xF299, + 0x9A53, 0xF29A, 0x9A54, 0xF29B, 0x9A55, 0xF29C, 0x9A56, 0xF29D, + 0x9A57, 0xF29E, 0x9A58, 0xF29F, 0x9A59, 0xF2A0, 0x9A5A, 0xF340, + 0x9A5B, 0xF341, 0x9A5C, 0xF342, 0x9A5D, 0xF343, 0x9A5E, 0xF344, + 0x9A5F, 0xF345, 0x9A60, 0xF346, 0x9A61, 0xF347, 0x9A62, 0xF348, + 0x9A63, 0xF349, 0x9A64, 0xF34A, 0x9A65, 0xF34B, 0x9A66, 0xF34C, + 0x9A67, 0xF34D, 0x9A68, 0xF34E, 0x9A69, 0xF34F, 0x9A6A, 0xF350, + 0x9A6B, 0xF351, 0x9A6C, 0xC2ED, 0x9A6D, 0xD4A6, 0x9A6E, 0xCDD4, + 0x9A6F, 0xD1B1, 0x9A70, 0xB3DB, 0x9A71, 0xC7FD, 0x9A72, 0xF352, + 0x9A73, 0xB2B5, 0x9A74, 0xC2BF, 0x9A75, 0xE6E0, 0x9A76, 0xCABB, + 0x9A77, 0xE6E1, 0x9A78, 0xE6E2, 0x9A79, 0xBED4, 0x9A7A, 0xE6E3, + 0x9A7B, 0xD7A4, 0x9A7C, 0xCDD5, 0x9A7D, 0xE6E5, 0x9A7E, 0xBCDD, + 0x9A7F, 0xE6E4, 0x9A80, 0xE6E6, 0x9A81, 0xE6E7, 0x9A82, 0xC2EE, + 0x9A83, 0xF353, 0x9A84, 0xBDBE, 0x9A85, 0xE6E8, 0x9A86, 0xC2E6, + 0x9A87, 0xBAA7, 0x9A88, 0xE6E9, 0x9A89, 0xF354, 0x9A8A, 0xE6EA, + 0x9A8B, 0xB3D2, 0x9A8C, 0xD1E9, 0x9A8D, 0xF355, 0x9A8E, 0xF356, + 0x9A8F, 0xBFA5, 0x9A90, 0xE6EB, 0x9A91, 0xC6EF, 0x9A92, 0xE6EC, + 0x9A93, 0xE6ED, 0x9A94, 0xF357, 0x9A95, 0xF358, 0x9A96, 0xE6EE, + 0x9A97, 0xC6AD, 0x9A98, 0xE6EF, 0x9A99, 0xF359, 0x9A9A, 0xC9A7, + 0x9A9B, 0xE6F0, 0x9A9C, 0xE6F1, 0x9A9D, 0xE6F2, 0x9A9E, 0xE5B9, + 0x9A9F, 0xE6F3, 0x9AA0, 0xE6F4, 0x9AA1, 0xC2E2, 0x9AA2, 0xE6F5, + 0x9AA3, 0xE6F6, 0x9AA4, 0xD6E8, 0x9AA5, 0xE6F7, 0x9AA6, 0xF35A, + 0x9AA7, 0xE6F8, 0x9AA8, 0xB9C7, 0x9AA9, 0xF35B, 0x9AAA, 0xF35C, + 0x9AAB, 0xF35D, 0x9AAC, 0xF35E, 0x9AAD, 0xF35F, 0x9AAE, 0xF360, + 0x9AAF, 0xF361, 0x9AB0, 0xF7BB, 0x9AB1, 0xF7BA, 0x9AB2, 0xF362, + 0x9AB3, 0xF363, 0x9AB4, 0xF364, 0x9AB5, 0xF365, 0x9AB6, 0xF7BE, + 0x9AB7, 0xF7BC, 0x9AB8, 0xBAA1, 0x9AB9, 0xF366, 0x9ABA, 0xF7BF, + 0x9ABB, 0xF367, 0x9ABC, 0xF7C0, 0x9ABD, 0xF368, 0x9ABE, 0xF369, + 0x9ABF, 0xF36A, 0x9AC0, 0xF7C2, 0x9AC1, 0xF7C1, 0x9AC2, 0xF7C4, + 0x9AC3, 0xF36B, 0x9AC4, 0xF36C, 0x9AC5, 0xF7C3, 0x9AC6, 0xF36D, + 0x9AC7, 0xF36E, 0x9AC8, 0xF36F, 0x9AC9, 0xF370, 0x9ACA, 0xF371, + 0x9ACB, 0xF7C5, 0x9ACC, 0xF7C6, 0x9ACD, 0xF372, 0x9ACE, 0xF373, + 0x9ACF, 0xF374, 0x9AD0, 0xF375, 0x9AD1, 0xF7C7, 0x9AD2, 0xF376, + 0x9AD3, 0xCBE8, 0x9AD4, 0xF377, 0x9AD5, 0xF378, 0x9AD6, 0xF379, + 0x9AD7, 0xF37A, 0x9AD8, 0xB8DF, 0x9AD9, 0xF37B, 0x9ADA, 0xF37C, + 0x9ADB, 0xF37D, 0x9ADC, 0xF37E, 0x9ADD, 0xF380, 0x9ADE, 0xF381, + 0x9ADF, 0xF7D4, 0x9AE0, 0xF382, 0x9AE1, 0xF7D5, 0x9AE2, 0xF383, + 0x9AE3, 0xF384, 0x9AE4, 0xF385, 0x9AE5, 0xF386, 0x9AE6, 0xF7D6, + 0x9AE7, 0xF387, 0x9AE8, 0xF388, 0x9AE9, 0xF389, 0x9AEA, 0xF38A, + 0x9AEB, 0xF7D8, 0x9AEC, 0xF38B, 0x9AED, 0xF7DA, 0x9AEE, 0xF38C, + 0x9AEF, 0xF7D7, 0x9AF0, 0xF38D, 0x9AF1, 0xF38E, 0x9AF2, 0xF38F, + 0x9AF3, 0xF390, 0x9AF4, 0xF391, 0x9AF5, 0xF392, 0x9AF6, 0xF393, + 0x9AF7, 0xF394, 0x9AF8, 0xF395, 0x9AF9, 0xF7DB, 0x9AFA, 0xF396, + 0x9AFB, 0xF7D9, 0x9AFC, 0xF397, 0x9AFD, 0xF398, 0x9AFE, 0xF399, + 0x9AFF, 0xF39A, 0x9B00, 0xF39B, 0x9B01, 0xF39C, 0x9B02, 0xF39D, + 0x9B03, 0xD7D7, 0x9B04, 0xF39E, 0x9B05, 0xF39F, 0x9B06, 0xF3A0, + 0x9B07, 0xF440, 0x9B08, 0xF7DC, 0x9B09, 0xF441, 0x9B0A, 0xF442, + 0x9B0B, 0xF443, 0x9B0C, 0xF444, 0x9B0D, 0xF445, 0x9B0E, 0xF446, + 0x9B0F, 0xF7DD, 0x9B10, 0xF447, 0x9B11, 0xF448, 0x9B12, 0xF449, + 0x9B13, 0xF7DE, 0x9B14, 0xF44A, 0x9B15, 0xF44B, 0x9B16, 0xF44C, + 0x9B17, 0xF44D, 0x9B18, 0xF44E, 0x9B19, 0xF44F, 0x9B1A, 0xF450, + 0x9B1B, 0xF451, 0x9B1C, 0xF452, 0x9B1D, 0xF453, 0x9B1E, 0xF454, + 0x9B1F, 0xF7DF, 0x9B20, 0xF455, 0x9B21, 0xF456, 0x9B22, 0xF457, + 0x9B23, 0xF7E0, 0x9B24, 0xF458, 0x9B25, 0xF459, 0x9B26, 0xF45A, + 0x9B27, 0xF45B, 0x9B28, 0xF45C, 0x9B29, 0xF45D, 0x9B2A, 0xF45E, + 0x9B2B, 0xF45F, 0x9B2C, 0xF460, 0x9B2D, 0xF461, 0x9B2E, 0xF462, + 0x9B2F, 0xDBCB, 0x9B30, 0xF463, 0x9B31, 0xF464, 0x9B32, 0xD8AA, + 0x9B33, 0xF465, 0x9B34, 0xF466, 0x9B35, 0xF467, 0x9B36, 0xF468, + 0x9B37, 0xF469, 0x9B38, 0xF46A, 0x9B39, 0xF46B, 0x9B3A, 0xF46C, + 0x9B3B, 0xE5F7, 0x9B3C, 0xB9ED, 0x9B3D, 0xF46D, 0x9B3E, 0xF46E, + 0x9B3F, 0xF46F, 0x9B40, 0xF470, 0x9B41, 0xBFFD, 0x9B42, 0xBBEA, + 0x9B43, 0xF7C9, 0x9B44, 0xC6C7, 0x9B45, 0xF7C8, 0x9B46, 0xF471, + 0x9B47, 0xF7CA, 0x9B48, 0xF7CC, 0x9B49, 0xF7CB, 0x9B4A, 0xF472, + 0x9B4B, 0xF473, 0x9B4C, 0xF474, 0x9B4D, 0xF7CD, 0x9B4E, 0xF475, + 0x9B4F, 0xCEBA, 0x9B50, 0xF476, 0x9B51, 0xF7CE, 0x9B52, 0xF477, + 0x9B53, 0xF478, 0x9B54, 0xC4A7, 0x9B55, 0xF479, 0x9B56, 0xF47A, + 0x9B57, 0xF47B, 0x9B58, 0xF47C, 0x9B59, 0xF47D, 0x9B5A, 0xF47E, + 0x9B5B, 0xF480, 0x9B5C, 0xF481, 0x9B5D, 0xF482, 0x9B5E, 0xF483, + 0x9B5F, 0xF484, 0x9B60, 0xF485, 0x9B61, 0xF486, 0x9B62, 0xF487, + 0x9B63, 0xF488, 0x9B64, 0xF489, 0x9B65, 0xF48A, 0x9B66, 0xF48B, + 0x9B67, 0xF48C, 0x9B68, 0xF48D, 0x9B69, 0xF48E, 0x9B6A, 0xF48F, + 0x9B6B, 0xF490, 0x9B6C, 0xF491, 0x9B6D, 0xF492, 0x9B6E, 0xF493, + 0x9B6F, 0xF494, 0x9B70, 0xF495, 0x9B71, 0xF496, 0x9B72, 0xF497, + 0x9B73, 0xF498, 0x9B74, 0xF499, 0x9B75, 0xF49A, 0x9B76, 0xF49B, + 0x9B77, 0xF49C, 0x9B78, 0xF49D, 0x9B79, 0xF49E, 0x9B7A, 0xF49F, + 0x9B7B, 0xF4A0, 0x9B7C, 0xF540, 0x9B7D, 0xF541, 0x9B7E, 0xF542, + 0x9B7F, 0xF543, 0x9B80, 0xF544, 0x9B81, 0xF545, 0x9B82, 0xF546, + 0x9B83, 0xF547, 0x9B84, 0xF548, 0x9B85, 0xF549, 0x9B86, 0xF54A, + 0x9B87, 0xF54B, 0x9B88, 0xF54C, 0x9B89, 0xF54D, 0x9B8A, 0xF54E, + 0x9B8B, 0xF54F, 0x9B8C, 0xF550, 0x9B8D, 0xF551, 0x9B8E, 0xF552, + 0x9B8F, 0xF553, 0x9B90, 0xF554, 0x9B91, 0xF555, 0x9B92, 0xF556, + 0x9B93, 0xF557, 0x9B94, 0xF558, 0x9B95, 0xF559, 0x9B96, 0xF55A, + 0x9B97, 0xF55B, 0x9B98, 0xF55C, 0x9B99, 0xF55D, 0x9B9A, 0xF55E, + 0x9B9B, 0xF55F, 0x9B9C, 0xF560, 0x9B9D, 0xF561, 0x9B9E, 0xF562, + 0x9B9F, 0xF563, 0x9BA0, 0xF564, 0x9BA1, 0xF565, 0x9BA2, 0xF566, + 0x9BA3, 0xF567, 0x9BA4, 0xF568, 0x9BA5, 0xF569, 0x9BA6, 0xF56A, + 0x9BA7, 0xF56B, 0x9BA8, 0xF56C, 0x9BA9, 0xF56D, 0x9BAA, 0xF56E, + 0x9BAB, 0xF56F, 0x9BAC, 0xF570, 0x9BAD, 0xF571, 0x9BAE, 0xF572, + 0x9BAF, 0xF573, 0x9BB0, 0xF574, 0x9BB1, 0xF575, 0x9BB2, 0xF576, + 0x9BB3, 0xF577, 0x9BB4, 0xF578, 0x9BB5, 0xF579, 0x9BB6, 0xF57A, + 0x9BB7, 0xF57B, 0x9BB8, 0xF57C, 0x9BB9, 0xF57D, 0x9BBA, 0xF57E, + 0x9BBB, 0xF580, 0x9BBC, 0xF581, 0x9BBD, 0xF582, 0x9BBE, 0xF583, + 0x9BBF, 0xF584, 0x9BC0, 0xF585, 0x9BC1, 0xF586, 0x9BC2, 0xF587, + 0x9BC3, 0xF588, 0x9BC4, 0xF589, 0x9BC5, 0xF58A, 0x9BC6, 0xF58B, + 0x9BC7, 0xF58C, 0x9BC8, 0xF58D, 0x9BC9, 0xF58E, 0x9BCA, 0xF58F, + 0x9BCB, 0xF590, 0x9BCC, 0xF591, 0x9BCD, 0xF592, 0x9BCE, 0xF593, + 0x9BCF, 0xF594, 0x9BD0, 0xF595, 0x9BD1, 0xF596, 0x9BD2, 0xF597, + 0x9BD3, 0xF598, 0x9BD4, 0xF599, 0x9BD5, 0xF59A, 0x9BD6, 0xF59B, + 0x9BD7, 0xF59C, 0x9BD8, 0xF59D, 0x9BD9, 0xF59E, 0x9BDA, 0xF59F, + 0x9BDB, 0xF5A0, 0x9BDC, 0xF640, 0x9BDD, 0xF641, 0x9BDE, 0xF642, + 0x9BDF, 0xF643, 0x9BE0, 0xF644, 0x9BE1, 0xF645, 0x9BE2, 0xF646, + 0x9BE3, 0xF647, 0x9BE4, 0xF648, 0x9BE5, 0xF649, 0x9BE6, 0xF64A, + 0x9BE7, 0xF64B, 0x9BE8, 0xF64C, 0x9BE9, 0xF64D, 0x9BEA, 0xF64E, + 0x9BEB, 0xF64F, 0x9BEC, 0xF650, 0x9BED, 0xF651, 0x9BEE, 0xF652, + 0x9BEF, 0xF653, 0x9BF0, 0xF654, 0x9BF1, 0xF655, 0x9BF2, 0xF656, + 0x9BF3, 0xF657, 0x9BF4, 0xF658, 0x9BF5, 0xF659, 0x9BF6, 0xF65A, + 0x9BF7, 0xF65B, 0x9BF8, 0xF65C, 0x9BF9, 0xF65D, 0x9BFA, 0xF65E, + 0x9BFB, 0xF65F, 0x9BFC, 0xF660, 0x9BFD, 0xF661, 0x9BFE, 0xF662, + 0x9BFF, 0xF663, 0x9C00, 0xF664, 0x9C01, 0xF665, 0x9C02, 0xF666, + 0x9C03, 0xF667, 0x9C04, 0xF668, 0x9C05, 0xF669, 0x9C06, 0xF66A, + 0x9C07, 0xF66B, 0x9C08, 0xF66C, 0x9C09, 0xF66D, 0x9C0A, 0xF66E, + 0x9C0B, 0xF66F, 0x9C0C, 0xF670, 0x9C0D, 0xF671, 0x9C0E, 0xF672, + 0x9C0F, 0xF673, 0x9C10, 0xF674, 0x9C11, 0xF675, 0x9C12, 0xF676, + 0x9C13, 0xF677, 0x9C14, 0xF678, 0x9C15, 0xF679, 0x9C16, 0xF67A, + 0x9C17, 0xF67B, 0x9C18, 0xF67C, 0x9C19, 0xF67D, 0x9C1A, 0xF67E, + 0x9C1B, 0xF680, 0x9C1C, 0xF681, 0x9C1D, 0xF682, 0x9C1E, 0xF683, + 0x9C1F, 0xF684, 0x9C20, 0xF685, 0x9C21, 0xF686, 0x9C22, 0xF687, + 0x9C23, 0xF688, 0x9C24, 0xF689, 0x9C25, 0xF68A, 0x9C26, 0xF68B, + 0x9C27, 0xF68C, 0x9C28, 0xF68D, 0x9C29, 0xF68E, 0x9C2A, 0xF68F, + 0x9C2B, 0xF690, 0x9C2C, 0xF691, 0x9C2D, 0xF692, 0x9C2E, 0xF693, + 0x9C2F, 0xF694, 0x9C30, 0xF695, 0x9C31, 0xF696, 0x9C32, 0xF697, + 0x9C33, 0xF698, 0x9C34, 0xF699, 0x9C35, 0xF69A, 0x9C36, 0xF69B, + 0x9C37, 0xF69C, 0x9C38, 0xF69D, 0x9C39, 0xF69E, 0x9C3A, 0xF69F, + 0x9C3B, 0xF6A0, 0x9C3C, 0xF740, 0x9C3D, 0xF741, 0x9C3E, 0xF742, + 0x9C3F, 0xF743, 0x9C40, 0xF744, 0x9C41, 0xF745, 0x9C42, 0xF746, + 0x9C43, 0xF747, 0x9C44, 0xF748, 0x9C45, 0xF749, 0x9C46, 0xF74A, + 0x9C47, 0xF74B, 0x9C48, 0xF74C, 0x9C49, 0xF74D, 0x9C4A, 0xF74E, + 0x9C4B, 0xF74F, 0x9C4C, 0xF750, 0x9C4D, 0xF751, 0x9C4E, 0xF752, + 0x9C4F, 0xF753, 0x9C50, 0xF754, 0x9C51, 0xF755, 0x9C52, 0xF756, + 0x9C53, 0xF757, 0x9C54, 0xF758, 0x9C55, 0xF759, 0x9C56, 0xF75A, + 0x9C57, 0xF75B, 0x9C58, 0xF75C, 0x9C59, 0xF75D, 0x9C5A, 0xF75E, + 0x9C5B, 0xF75F, 0x9C5C, 0xF760, 0x9C5D, 0xF761, 0x9C5E, 0xF762, + 0x9C5F, 0xF763, 0x9C60, 0xF764, 0x9C61, 0xF765, 0x9C62, 0xF766, + 0x9C63, 0xF767, 0x9C64, 0xF768, 0x9C65, 0xF769, 0x9C66, 0xF76A, + 0x9C67, 0xF76B, 0x9C68, 0xF76C, 0x9C69, 0xF76D, 0x9C6A, 0xF76E, + 0x9C6B, 0xF76F, 0x9C6C, 0xF770, 0x9C6D, 0xF771, 0x9C6E, 0xF772, + 0x9C6F, 0xF773, 0x9C70, 0xF774, 0x9C71, 0xF775, 0x9C72, 0xF776, + 0x9C73, 0xF777, 0x9C74, 0xF778, 0x9C75, 0xF779, 0x9C76, 0xF77A, + 0x9C77, 0xF77B, 0x9C78, 0xF77C, 0x9C79, 0xF77D, 0x9C7A, 0xF77E, + 0x9C7B, 0xF780, 0x9C7C, 0xD3E3, 0x9C7D, 0xF781, 0x9C7E, 0xF782, + 0x9C7F, 0xF6CF, 0x9C80, 0xF783, 0x9C81, 0xC2B3, 0x9C82, 0xF6D0, + 0x9C83, 0xF784, 0x9C84, 0xF785, 0x9C85, 0xF6D1, 0x9C86, 0xF6D2, + 0x9C87, 0xF6D3, 0x9C88, 0xF6D4, 0x9C89, 0xF786, 0x9C8A, 0xF787, + 0x9C8B, 0xF6D6, 0x9C8C, 0xF788, 0x9C8D, 0xB1AB, 0x9C8E, 0xF6D7, + 0x9C8F, 0xF789, 0x9C90, 0xF6D8, 0x9C91, 0xF6D9, 0x9C92, 0xF6DA, + 0x9C93, 0xF78A, 0x9C94, 0xF6DB, 0x9C95, 0xF6DC, 0x9C96, 0xF78B, + 0x9C97, 0xF78C, 0x9C98, 0xF78D, 0x9C99, 0xF78E, 0x9C9A, 0xF6DD, + 0x9C9B, 0xF6DE, 0x9C9C, 0xCFCA, 0x9C9D, 0xF78F, 0x9C9E, 0xF6DF, + 0x9C9F, 0xF6E0, 0x9CA0, 0xF6E1, 0x9CA1, 0xF6E2, 0x9CA2, 0xF6E3, + 0x9CA3, 0xF6E4, 0x9CA4, 0xC0F0, 0x9CA5, 0xF6E5, 0x9CA6, 0xF6E6, + 0x9CA7, 0xF6E7, 0x9CA8, 0xF6E8, 0x9CA9, 0xF6E9, 0x9CAA, 0xF790, + 0x9CAB, 0xF6EA, 0x9CAC, 0xF791, 0x9CAD, 0xF6EB, 0x9CAE, 0xF6EC, + 0x9CAF, 0xF792, 0x9CB0, 0xF6ED, 0x9CB1, 0xF6EE, 0x9CB2, 0xF6EF, + 0x9CB3, 0xF6F0, 0x9CB4, 0xF6F1, 0x9CB5, 0xF6F2, 0x9CB6, 0xF6F3, + 0x9CB7, 0xF6F4, 0x9CB8, 0xBEA8, 0x9CB9, 0xF793, 0x9CBA, 0xF6F5, + 0x9CBB, 0xF6F6, 0x9CBC, 0xF6F7, 0x9CBD, 0xF6F8, 0x9CBE, 0xF794, + 0x9CBF, 0xF795, 0x9CC0, 0xF796, 0x9CC1, 0xF797, 0x9CC2, 0xF798, + 0x9CC3, 0xC8FA, 0x9CC4, 0xF6F9, 0x9CC5, 0xF6FA, 0x9CC6, 0xF6FB, + 0x9CC7, 0xF6FC, 0x9CC8, 0xF799, 0x9CC9, 0xF79A, 0x9CCA, 0xF6FD, + 0x9CCB, 0xF6FE, 0x9CCC, 0xF7A1, 0x9CCD, 0xF7A2, 0x9CCE, 0xF7A3, + 0x9CCF, 0xF7A4, 0x9CD0, 0xF7A5, 0x9CD1, 0xF79B, 0x9CD2, 0xF79C, + 0x9CD3, 0xF7A6, 0x9CD4, 0xF7A7, 0x9CD5, 0xF7A8, 0x9CD6, 0xB1EE, + 0x9CD7, 0xF7A9, 0x9CD8, 0xF7AA, 0x9CD9, 0xF7AB, 0x9CDA, 0xF79D, + 0x9CDB, 0xF79E, 0x9CDC, 0xF7AC, 0x9CDD, 0xF7AD, 0x9CDE, 0xC1DB, + 0x9CDF, 0xF7AE, 0x9CE0, 0xF79F, 0x9CE1, 0xF7A0, 0x9CE2, 0xF7AF, + 0x9CE3, 0xF840, 0x9CE4, 0xF841, 0x9CE5, 0xF842, 0x9CE6, 0xF843, + 0x9CE7, 0xF844, 0x9CE8, 0xF845, 0x9CE9, 0xF846, 0x9CEA, 0xF847, + 0x9CEB, 0xF848, 0x9CEC, 0xF849, 0x9CED, 0xF84A, 0x9CEE, 0xF84B, + 0x9CEF, 0xF84C, 0x9CF0, 0xF84D, 0x9CF1, 0xF84E, 0x9CF2, 0xF84F, + 0x9CF3, 0xF850, 0x9CF4, 0xF851, 0x9CF5, 0xF852, 0x9CF6, 0xF853, + 0x9CF7, 0xF854, 0x9CF8, 0xF855, 0x9CF9, 0xF856, 0x9CFA, 0xF857, + 0x9CFB, 0xF858, 0x9CFC, 0xF859, 0x9CFD, 0xF85A, 0x9CFE, 0xF85B, + 0x9CFF, 0xF85C, 0x9D00, 0xF85D, 0x9D01, 0xF85E, 0x9D02, 0xF85F, + 0x9D03, 0xF860, 0x9D04, 0xF861, 0x9D05, 0xF862, 0x9D06, 0xF863, + 0x9D07, 0xF864, 0x9D08, 0xF865, 0x9D09, 0xF866, 0x9D0A, 0xF867, + 0x9D0B, 0xF868, 0x9D0C, 0xF869, 0x9D0D, 0xF86A, 0x9D0E, 0xF86B, + 0x9D0F, 0xF86C, 0x9D10, 0xF86D, 0x9D11, 0xF86E, 0x9D12, 0xF86F, + 0x9D13, 0xF870, 0x9D14, 0xF871, 0x9D15, 0xF872, 0x9D16, 0xF873, + 0x9D17, 0xF874, 0x9D18, 0xF875, 0x9D19, 0xF876, 0x9D1A, 0xF877, + 0x9D1B, 0xF878, 0x9D1C, 0xF879, 0x9D1D, 0xF87A, 0x9D1E, 0xF87B, + 0x9D1F, 0xF87C, 0x9D20, 0xF87D, 0x9D21, 0xF87E, 0x9D22, 0xF880, + 0x9D23, 0xF881, 0x9D24, 0xF882, 0x9D25, 0xF883, 0x9D26, 0xF884, + 0x9D27, 0xF885, 0x9D28, 0xF886, 0x9D29, 0xF887, 0x9D2A, 0xF888, + 0x9D2B, 0xF889, 0x9D2C, 0xF88A, 0x9D2D, 0xF88B, 0x9D2E, 0xF88C, + 0x9D2F, 0xF88D, 0x9D30, 0xF88E, 0x9D31, 0xF88F, 0x9D32, 0xF890, + 0x9D33, 0xF891, 0x9D34, 0xF892, 0x9D35, 0xF893, 0x9D36, 0xF894, + 0x9D37, 0xF895, 0x9D38, 0xF896, 0x9D39, 0xF897, 0x9D3A, 0xF898, + 0x9D3B, 0xF899, 0x9D3C, 0xF89A, 0x9D3D, 0xF89B, 0x9D3E, 0xF89C, + 0x9D3F, 0xF89D, 0x9D40, 0xF89E, 0x9D41, 0xF89F, 0x9D42, 0xF8A0, + 0x9D43, 0xF940, 0x9D44, 0xF941, 0x9D45, 0xF942, 0x9D46, 0xF943, + 0x9D47, 0xF944, 0x9D48, 0xF945, 0x9D49, 0xF946, 0x9D4A, 0xF947, + 0x9D4B, 0xF948, 0x9D4C, 0xF949, 0x9D4D, 0xF94A, 0x9D4E, 0xF94B, + 0x9D4F, 0xF94C, 0x9D50, 0xF94D, 0x9D51, 0xF94E, 0x9D52, 0xF94F, + 0x9D53, 0xF950, 0x9D54, 0xF951, 0x9D55, 0xF952, 0x9D56, 0xF953, + 0x9D57, 0xF954, 0x9D58, 0xF955, 0x9D59, 0xF956, 0x9D5A, 0xF957, + 0x9D5B, 0xF958, 0x9D5C, 0xF959, 0x9D5D, 0xF95A, 0x9D5E, 0xF95B, + 0x9D5F, 0xF95C, 0x9D60, 0xF95D, 0x9D61, 0xF95E, 0x9D62, 0xF95F, + 0x9D63, 0xF960, 0x9D64, 0xF961, 0x9D65, 0xF962, 0x9D66, 0xF963, + 0x9D67, 0xF964, 0x9D68, 0xF965, 0x9D69, 0xF966, 0x9D6A, 0xF967, + 0x9D6B, 0xF968, 0x9D6C, 0xF969, 0x9D6D, 0xF96A, 0x9D6E, 0xF96B, + 0x9D6F, 0xF96C, 0x9D70, 0xF96D, 0x9D71, 0xF96E, 0x9D72, 0xF96F, + 0x9D73, 0xF970, 0x9D74, 0xF971, 0x9D75, 0xF972, 0x9D76, 0xF973, + 0x9D77, 0xF974, 0x9D78, 0xF975, 0x9D79, 0xF976, 0x9D7A, 0xF977, + 0x9D7B, 0xF978, 0x9D7C, 0xF979, 0x9D7D, 0xF97A, 0x9D7E, 0xF97B, + 0x9D7F, 0xF97C, 0x9D80, 0xF97D, 0x9D81, 0xF97E, 0x9D82, 0xF980, + 0x9D83, 0xF981, 0x9D84, 0xF982, 0x9D85, 0xF983, 0x9D86, 0xF984, + 0x9D87, 0xF985, 0x9D88, 0xF986, 0x9D89, 0xF987, 0x9D8A, 0xF988, + 0x9D8B, 0xF989, 0x9D8C, 0xF98A, 0x9D8D, 0xF98B, 0x9D8E, 0xF98C, + 0x9D8F, 0xF98D, 0x9D90, 0xF98E, 0x9D91, 0xF98F, 0x9D92, 0xF990, + 0x9D93, 0xF991, 0x9D94, 0xF992, 0x9D95, 0xF993, 0x9D96, 0xF994, + 0x9D97, 0xF995, 0x9D98, 0xF996, 0x9D99, 0xF997, 0x9D9A, 0xF998, + 0x9D9B, 0xF999, 0x9D9C, 0xF99A, 0x9D9D, 0xF99B, 0x9D9E, 0xF99C, + 0x9D9F, 0xF99D, 0x9DA0, 0xF99E, 0x9DA1, 0xF99F, 0x9DA2, 0xF9A0, + 0x9DA3, 0xFA40, 0x9DA4, 0xFA41, 0x9DA5, 0xFA42, 0x9DA6, 0xFA43, + 0x9DA7, 0xFA44, 0x9DA8, 0xFA45, 0x9DA9, 0xFA46, 0x9DAA, 0xFA47, + 0x9DAB, 0xFA48, 0x9DAC, 0xFA49, 0x9DAD, 0xFA4A, 0x9DAE, 0xFA4B, + 0x9DAF, 0xFA4C, 0x9DB0, 0xFA4D, 0x9DB1, 0xFA4E, 0x9DB2, 0xFA4F, + 0x9DB3, 0xFA50, 0x9DB4, 0xFA51, 0x9DB5, 0xFA52, 0x9DB6, 0xFA53, + 0x9DB7, 0xFA54, 0x9DB8, 0xFA55, 0x9DB9, 0xFA56, 0x9DBA, 0xFA57, + 0x9DBB, 0xFA58, 0x9DBC, 0xFA59, 0x9DBD, 0xFA5A, 0x9DBE, 0xFA5B, + 0x9DBF, 0xFA5C, 0x9DC0, 0xFA5D, 0x9DC1, 0xFA5E, 0x9DC2, 0xFA5F, + 0x9DC3, 0xFA60, 0x9DC4, 0xFA61, 0x9DC5, 0xFA62, 0x9DC6, 0xFA63, + 0x9DC7, 0xFA64, 0x9DC8, 0xFA65, 0x9DC9, 0xFA66, 0x9DCA, 0xFA67, + 0x9DCB, 0xFA68, 0x9DCC, 0xFA69, 0x9DCD, 0xFA6A, 0x9DCE, 0xFA6B, + 0x9DCF, 0xFA6C, 0x9DD0, 0xFA6D, 0x9DD1, 0xFA6E, 0x9DD2, 0xFA6F, + 0x9DD3, 0xFA70, 0x9DD4, 0xFA71, 0x9DD5, 0xFA72, 0x9DD6, 0xFA73, + 0x9DD7, 0xFA74, 0x9DD8, 0xFA75, 0x9DD9, 0xFA76, 0x9DDA, 0xFA77, + 0x9DDB, 0xFA78, 0x9DDC, 0xFA79, 0x9DDD, 0xFA7A, 0x9DDE, 0xFA7B, + 0x9DDF, 0xFA7C, 0x9DE0, 0xFA7D, 0x9DE1, 0xFA7E, 0x9DE2, 0xFA80, + 0x9DE3, 0xFA81, 0x9DE4, 0xFA82, 0x9DE5, 0xFA83, 0x9DE6, 0xFA84, + 0x9DE7, 0xFA85, 0x9DE8, 0xFA86, 0x9DE9, 0xFA87, 0x9DEA, 0xFA88, + 0x9DEB, 0xFA89, 0x9DEC, 0xFA8A, 0x9DED, 0xFA8B, 0x9DEE, 0xFA8C, + 0x9DEF, 0xFA8D, 0x9DF0, 0xFA8E, 0x9DF1, 0xFA8F, 0x9DF2, 0xFA90, + 0x9DF3, 0xFA91, 0x9DF4, 0xFA92, 0x9DF5, 0xFA93, 0x9DF6, 0xFA94, + 0x9DF7, 0xFA95, 0x9DF8, 0xFA96, 0x9DF9, 0xFA97, 0x9DFA, 0xFA98, + 0x9DFB, 0xFA99, 0x9DFC, 0xFA9A, 0x9DFD, 0xFA9B, 0x9DFE, 0xFA9C, + 0x9DFF, 0xFA9D, 0x9E00, 0xFA9E, 0x9E01, 0xFA9F, 0x9E02, 0xFAA0, + 0x9E03, 0xFB40, 0x9E04, 0xFB41, 0x9E05, 0xFB42, 0x9E06, 0xFB43, + 0x9E07, 0xFB44, 0x9E08, 0xFB45, 0x9E09, 0xFB46, 0x9E0A, 0xFB47, + 0x9E0B, 0xFB48, 0x9E0C, 0xFB49, 0x9E0D, 0xFB4A, 0x9E0E, 0xFB4B, + 0x9E0F, 0xFB4C, 0x9E10, 0xFB4D, 0x9E11, 0xFB4E, 0x9E12, 0xFB4F, + 0x9E13, 0xFB50, 0x9E14, 0xFB51, 0x9E15, 0xFB52, 0x9E16, 0xFB53, + 0x9E17, 0xFB54, 0x9E18, 0xFB55, 0x9E19, 0xFB56, 0x9E1A, 0xFB57, + 0x9E1B, 0xFB58, 0x9E1C, 0xFB59, 0x9E1D, 0xFB5A, 0x9E1E, 0xFB5B, + 0x9E1F, 0xC4F1, 0x9E20, 0xF0AF, 0x9E21, 0xBCA6, 0x9E22, 0xF0B0, + 0x9E23, 0xC3F9, 0x9E24, 0xFB5C, 0x9E25, 0xC5B8, 0x9E26, 0xD1BB, + 0x9E27, 0xFB5D, 0x9E28, 0xF0B1, 0x9E29, 0xF0B2, 0x9E2A, 0xF0B3, + 0x9E2B, 0xF0B4, 0x9E2C, 0xF0B5, 0x9E2D, 0xD1BC, 0x9E2E, 0xFB5E, + 0x9E2F, 0xD1EC, 0x9E30, 0xFB5F, 0x9E31, 0xF0B7, 0x9E32, 0xF0B6, + 0x9E33, 0xD4A7, 0x9E34, 0xFB60, 0x9E35, 0xCDD2, 0x9E36, 0xF0B8, + 0x9E37, 0xF0BA, 0x9E38, 0xF0B9, 0x9E39, 0xF0BB, 0x9E3A, 0xF0BC, + 0x9E3B, 0xFB61, 0x9E3C, 0xFB62, 0x9E3D, 0xB8EB, 0x9E3E, 0xF0BD, + 0x9E3F, 0xBAE8, 0x9E40, 0xFB63, 0x9E41, 0xF0BE, 0x9E42, 0xF0BF, + 0x9E43, 0xBEE9, 0x9E44, 0xF0C0, 0x9E45, 0xB6EC, 0x9E46, 0xF0C1, + 0x9E47, 0xF0C2, 0x9E48, 0xF0C3, 0x9E49, 0xF0C4, 0x9E4A, 0xC8B5, + 0x9E4B, 0xF0C5, 0x9E4C, 0xF0C6, 0x9E4D, 0xFB64, 0x9E4E, 0xF0C7, + 0x9E4F, 0xC5F4, 0x9E50, 0xFB65, 0x9E51, 0xF0C8, 0x9E52, 0xFB66, + 0x9E53, 0xFB67, 0x9E54, 0xFB68, 0x9E55, 0xF0C9, 0x9E56, 0xFB69, + 0x9E57, 0xF0CA, 0x9E58, 0xF7BD, 0x9E59, 0xFB6A, 0x9E5A, 0xF0CB, + 0x9E5B, 0xF0CC, 0x9E5C, 0xF0CD, 0x9E5D, 0xFB6B, 0x9E5E, 0xF0CE, + 0x9E5F, 0xFB6C, 0x9E60, 0xFB6D, 0x9E61, 0xFB6E, 0x9E62, 0xFB6F, + 0x9E63, 0xF0CF, 0x9E64, 0xBAD7, 0x9E65, 0xFB70, 0x9E66, 0xF0D0, + 0x9E67, 0xF0D1, 0x9E68, 0xF0D2, 0x9E69, 0xF0D3, 0x9E6A, 0xF0D4, + 0x9E6B, 0xF0D5, 0x9E6C, 0xF0D6, 0x9E6D, 0xF0D8, 0x9E6E, 0xFB71, + 0x9E6F, 0xFB72, 0x9E70, 0xD3A5, 0x9E71, 0xF0D7, 0x9E72, 0xFB73, + 0x9E73, 0xF0D9, 0x9E74, 0xFB74, 0x9E75, 0xFB75, 0x9E76, 0xFB76, + 0x9E77, 0xFB77, 0x9E78, 0xFB78, 0x9E79, 0xFB79, 0x9E7A, 0xFB7A, + 0x9E7B, 0xFB7B, 0x9E7C, 0xFB7C, 0x9E7D, 0xFB7D, 0x9E7E, 0xF5BA, + 0x9E7F, 0xC2B9, 0x9E80, 0xFB7E, 0x9E81, 0xFB80, 0x9E82, 0xF7E4, + 0x9E83, 0xFB81, 0x9E84, 0xFB82, 0x9E85, 0xFB83, 0x9E86, 0xFB84, + 0x9E87, 0xF7E5, 0x9E88, 0xF7E6, 0x9E89, 0xFB85, 0x9E8A, 0xFB86, + 0x9E8B, 0xF7E7, 0x9E8C, 0xFB87, 0x9E8D, 0xFB88, 0x9E8E, 0xFB89, + 0x9E8F, 0xFB8A, 0x9E90, 0xFB8B, 0x9E91, 0xFB8C, 0x9E92, 0xF7E8, + 0x9E93, 0xC2B4, 0x9E94, 0xFB8D, 0x9E95, 0xFB8E, 0x9E96, 0xFB8F, + 0x9E97, 0xFB90, 0x9E98, 0xFB91, 0x9E99, 0xFB92, 0x9E9A, 0xFB93, + 0x9E9B, 0xFB94, 0x9E9C, 0xFB95, 0x9E9D, 0xF7EA, 0x9E9E, 0xFB96, + 0x9E9F, 0xF7EB, 0x9EA0, 0xFB97, 0x9EA1, 0xFB98, 0x9EA2, 0xFB99, + 0x9EA3, 0xFB9A, 0x9EA4, 0xFB9B, 0x9EA5, 0xFB9C, 0x9EA6, 0xC2F3, + 0x9EA7, 0xFB9D, 0x9EA8, 0xFB9E, 0x9EA9, 0xFB9F, 0x9EAA, 0xFBA0, + 0x9EAB, 0xFC40, 0x9EAC, 0xFC41, 0x9EAD, 0xFC42, 0x9EAE, 0xFC43, + 0x9EAF, 0xFC44, 0x9EB0, 0xFC45, 0x9EB1, 0xFC46, 0x9EB2, 0xFC47, + 0x9EB3, 0xFC48, 0x9EB4, 0xF4F0, 0x9EB5, 0xFC49, 0x9EB6, 0xFC4A, + 0x9EB7, 0xFC4B, 0x9EB8, 0xF4EF, 0x9EB9, 0xFC4C, 0x9EBA, 0xFC4D, + 0x9EBB, 0xC2E9, 0x9EBC, 0xFC4E, 0x9EBD, 0xF7E1, 0x9EBE, 0xF7E2, + 0x9EBF, 0xFC4F, 0x9EC0, 0xFC50, 0x9EC1, 0xFC51, 0x9EC2, 0xFC52, + 0x9EC3, 0xFC53, 0x9EC4, 0xBBC6, 0x9EC5, 0xFC54, 0x9EC6, 0xFC55, + 0x9EC7, 0xFC56, 0x9EC8, 0xFC57, 0x9EC9, 0xD9E4, 0x9ECA, 0xFC58, + 0x9ECB, 0xFC59, 0x9ECC, 0xFC5A, 0x9ECD, 0xCAF2, 0x9ECE, 0xC0E8, + 0x9ECF, 0xF0A4, 0x9ED0, 0xFC5B, 0x9ED1, 0xBADA, 0x9ED2, 0xFC5C, + 0x9ED3, 0xFC5D, 0x9ED4, 0xC7AD, 0x9ED5, 0xFC5E, 0x9ED6, 0xFC5F, + 0x9ED7, 0xFC60, 0x9ED8, 0xC4AC, 0x9ED9, 0xFC61, 0x9EDA, 0xFC62, + 0x9EDB, 0xF7EC, 0x9EDC, 0xF7ED, 0x9EDD, 0xF7EE, 0x9EDE, 0xFC63, + 0x9EDF, 0xF7F0, 0x9EE0, 0xF7EF, 0x9EE1, 0xFC64, 0x9EE2, 0xF7F1, + 0x9EE3, 0xFC65, 0x9EE4, 0xFC66, 0x9EE5, 0xF7F4, 0x9EE6, 0xFC67, + 0x9EE7, 0xF7F3, 0x9EE8, 0xFC68, 0x9EE9, 0xF7F2, 0x9EEA, 0xF7F5, + 0x9EEB, 0xFC69, 0x9EEC, 0xFC6A, 0x9EED, 0xFC6B, 0x9EEE, 0xFC6C, + 0x9EEF, 0xF7F6, 0x9EF0, 0xFC6D, 0x9EF1, 0xFC6E, 0x9EF2, 0xFC6F, + 0x9EF3, 0xFC70, 0x9EF4, 0xFC71, 0x9EF5, 0xFC72, 0x9EF6, 0xFC73, + 0x9EF7, 0xFC74, 0x9EF8, 0xFC75, 0x9EF9, 0xEDE9, 0x9EFA, 0xFC76, + 0x9EFB, 0xEDEA, 0x9EFC, 0xEDEB, 0x9EFD, 0xFC77, 0x9EFE, 0xF6BC, + 0x9EFF, 0xFC78, 0x9F00, 0xFC79, 0x9F01, 0xFC7A, 0x9F02, 0xFC7B, + 0x9F03, 0xFC7C, 0x9F04, 0xFC7D, 0x9F05, 0xFC7E, 0x9F06, 0xFC80, + 0x9F07, 0xFC81, 0x9F08, 0xFC82, 0x9F09, 0xFC83, 0x9F0A, 0xFC84, + 0x9F0B, 0xF6BD, 0x9F0C, 0xFC85, 0x9F0D, 0xF6BE, 0x9F0E, 0xB6A6, + 0x9F0F, 0xFC86, 0x9F10, 0xD8BE, 0x9F11, 0xFC87, 0x9F12, 0xFC88, + 0x9F13, 0xB9C4, 0x9F14, 0xFC89, 0x9F15, 0xFC8A, 0x9F16, 0xFC8B, + 0x9F17, 0xD8BB, 0x9F18, 0xFC8C, 0x9F19, 0xDCB1, 0x9F1A, 0xFC8D, + 0x9F1B, 0xFC8E, 0x9F1C, 0xFC8F, 0x9F1D, 0xFC90, 0x9F1E, 0xFC91, + 0x9F1F, 0xFC92, 0x9F20, 0xCAF3, 0x9F21, 0xFC93, 0x9F22, 0xF7F7, + 0x9F23, 0xFC94, 0x9F24, 0xFC95, 0x9F25, 0xFC96, 0x9F26, 0xFC97, + 0x9F27, 0xFC98, 0x9F28, 0xFC99, 0x9F29, 0xFC9A, 0x9F2A, 0xFC9B, + 0x9F2B, 0xFC9C, 0x9F2C, 0xF7F8, 0x9F2D, 0xFC9D, 0x9F2E, 0xFC9E, + 0x9F2F, 0xF7F9, 0x9F30, 0xFC9F, 0x9F31, 0xFCA0, 0x9F32, 0xFD40, + 0x9F33, 0xFD41, 0x9F34, 0xFD42, 0x9F35, 0xFD43, 0x9F36, 0xFD44, + 0x9F37, 0xF7FB, 0x9F38, 0xFD45, 0x9F39, 0xF7FA, 0x9F3A, 0xFD46, + 0x9F3B, 0xB1C7, 0x9F3C, 0xFD47, 0x9F3D, 0xF7FC, 0x9F3E, 0xF7FD, + 0x9F3F, 0xFD48, 0x9F40, 0xFD49, 0x9F41, 0xFD4A, 0x9F42, 0xFD4B, + 0x9F43, 0xFD4C, 0x9F44, 0xF7FE, 0x9F45, 0xFD4D, 0x9F46, 0xFD4E, + 0x9F47, 0xFD4F, 0x9F48, 0xFD50, 0x9F49, 0xFD51, 0x9F4A, 0xFD52, + 0x9F4B, 0xFD53, 0x9F4C, 0xFD54, 0x9F4D, 0xFD55, 0x9F4E, 0xFD56, + 0x9F4F, 0xFD57, 0x9F50, 0xC6EB, 0x9F51, 0xECB4, 0x9F52, 0xFD58, + 0x9F53, 0xFD59, 0x9F54, 0xFD5A, 0x9F55, 0xFD5B, 0x9F56, 0xFD5C, + 0x9F57, 0xFD5D, 0x9F58, 0xFD5E, 0x9F59, 0xFD5F, 0x9F5A, 0xFD60, + 0x9F5B, 0xFD61, 0x9F5C, 0xFD62, 0x9F5D, 0xFD63, 0x9F5E, 0xFD64, + 0x9F5F, 0xFD65, 0x9F60, 0xFD66, 0x9F61, 0xFD67, 0x9F62, 0xFD68, + 0x9F63, 0xFD69, 0x9F64, 0xFD6A, 0x9F65, 0xFD6B, 0x9F66, 0xFD6C, + 0x9F67, 0xFD6D, 0x9F68, 0xFD6E, 0x9F69, 0xFD6F, 0x9F6A, 0xFD70, + 0x9F6B, 0xFD71, 0x9F6C, 0xFD72, 0x9F6D, 0xFD73, 0x9F6E, 0xFD74, + 0x9F6F, 0xFD75, 0x9F70, 0xFD76, 0x9F71, 0xFD77, 0x9F72, 0xFD78, + 0x9F73, 0xFD79, 0x9F74, 0xFD7A, 0x9F75, 0xFD7B, 0x9F76, 0xFD7C, + 0x9F77, 0xFD7D, 0x9F78, 0xFD7E, 0x9F79, 0xFD80, 0x9F7A, 0xFD81, + 0x9F7B, 0xFD82, 0x9F7C, 0xFD83, 0x9F7D, 0xFD84, 0x9F7E, 0xFD85, + 0x9F7F, 0xB3DD, 0x9F80, 0xF6B3, 0x9F81, 0xFD86, 0x9F82, 0xFD87, + 0x9F83, 0xF6B4, 0x9F84, 0xC1E4, 0x9F85, 0xF6B5, 0x9F86, 0xF6B6, + 0x9F87, 0xF6B7, 0x9F88, 0xF6B8, 0x9F89, 0xF6B9, 0x9F8A, 0xF6BA, + 0x9F8B, 0xC8A3, 0x9F8C, 0xF6BB, 0x9F8D, 0xFD88, 0x9F8E, 0xFD89, + 0x9F8F, 0xFD8A, 0x9F90, 0xFD8B, 0x9F91, 0xFD8C, 0x9F92, 0xFD8D, + 0x9F93, 0xFD8E, 0x9F94, 0xFD8F, 0x9F95, 0xFD90, 0x9F96, 0xFD91, + 0x9F97, 0xFD92, 0x9F98, 0xFD93, 0x9F99, 0xC1FA, 0x9F9A, 0xB9A8, + 0x9F9B, 0xEDE8, 0x9F9C, 0xFD94, 0x9F9D, 0xFD95, 0x9F9E, 0xFD96, + 0x9F9F, 0xB9EA, 0x9FA0, 0xD9DF, 0x9FA1, 0xFD97, 0x9FA2, 0xFD98, + 0x9FA3, 0xFD99, 0x9FA4, 0xFD9A, 0x9FA5, 0xFD9B, 0xF92C, 0xFD9C, + 0xF979, 0xFD9D, 0xF995, 0xFD9E, 0xF9E7, 0xFD9F, 0xF9F1, 0xFDA0, + 0xFA0C, 0xFE40, 0xFA0D, 0xFE41, 0xFA0E, 0xFE42, 0xFA0F, 0xFE43, + 0xFA11, 0xFE44, 0xFA13, 0xFE45, 0xFA14, 0xFE46, 0xFA18, 0xFE47, + 0xFA1F, 0xFE48, 0xFA20, 0xFE49, 0xFA21, 0xFE4A, 0xFA23, 0xFE4B, + 0xFA24, 0xFE4C, 0xFA27, 0xFE4D, 0xFA28, 0xFE4E, 0xFA29, 0xFE4F, + 0xFE30, 0xA955, 0xFE31, 0xA6F2, 0xFE33, 0xA6F4, 0xFE34, 0xA6F5, + 0xFE35, 0xA6E0, 0xFE36, 0xA6E1, 0xFE37, 0xA6F0, 0xFE38, 0xA6F1, + 0xFE39, 0xA6E2, 0xFE3A, 0xA6E3, 0xFE3B, 0xA6EE, 0xFE3C, 0xA6EF, + 0xFE3D, 0xA6E6, 0xFE3E, 0xA6E7, 0xFE3F, 0xA6E4, 0xFE40, 0xA6E5, + 0xFE41, 0xA6E8, 0xFE42, 0xA6E9, 0xFE43, 0xA6EA, 0xFE44, 0xA6EB, + 0xFE49, 0xA968, 0xFE4A, 0xA969, 0xFE4B, 0xA96A, 0xFE4C, 0xA96B, + 0xFE4D, 0xA96C, 0xFE4E, 0xA96D, 0xFE4F, 0xA96E, 0xFE50, 0xA96F, + 0xFE51, 0xA970, 0xFE52, 0xA971, 0xFE54, 0xA972, 0xFE55, 0xA973, + 0xFE56, 0xA974, 0xFE57, 0xA975, 0xFE59, 0xA976, 0xFE5A, 0xA977, + 0xFE5B, 0xA978, 0xFE5C, 0xA979, 0xFE5D, 0xA97A, 0xFE5E, 0xA97B, + 0xFE5F, 0xA97C, 0xFE60, 0xA97D, 0xFE61, 0xA97E, 0xFE62, 0xA980, + 0xFE63, 0xA981, 0xFE64, 0xA982, 0xFE65, 0xA983, 0xFE66, 0xA984, + 0xFE68, 0xA985, 0xFE69, 0xA986, 0xFE6A, 0xA987, 0xFE6B, 0xA988, + 0xFF01, 0xA3A1, 0xFF02, 0xA3A2, 0xFF03, 0xA3A3, 0xFF04, 0xA1E7, + 0xFF05, 0xA3A5, 0xFF06, 0xA3A6, 0xFF07, 0xA3A7, 0xFF08, 0xA3A8, + 0xFF09, 0xA3A9, 0xFF0A, 0xA3AA, 0xFF0B, 0xA3AB, 0xFF0C, 0xA3AC, + 0xFF0D, 0xA3AD, 0xFF0E, 0xA3AE, 0xFF0F, 0xA3AF, 0xFF10, 0xA3B0, + 0xFF11, 0xA3B1, 0xFF12, 0xA3B2, 0xFF13, 0xA3B3, 0xFF14, 0xA3B4, + 0xFF15, 0xA3B5, 0xFF16, 0xA3B6, 0xFF17, 0xA3B7, 0xFF18, 0xA3B8, + 0xFF19, 0xA3B9, 0xFF1A, 0xA3BA, 0xFF1B, 0xA3BB, 0xFF1C, 0xA3BC, + 0xFF1D, 0xA3BD, 0xFF1E, 0xA3BE, 0xFF1F, 0xA3BF, 0xFF20, 0xA3C0, + 0xFF21, 0xA3C1, 0xFF22, 0xA3C2, 0xFF23, 0xA3C3, 0xFF24, 0xA3C4, + 0xFF25, 0xA3C5, 0xFF26, 0xA3C6, 0xFF27, 0xA3C7, 0xFF28, 0xA3C8, + 0xFF29, 0xA3C9, 0xFF2A, 0xA3CA, 0xFF2B, 0xA3CB, 0xFF2C, 0xA3CC, + 0xFF2D, 0xA3CD, 0xFF2E, 0xA3CE, 0xFF2F, 0xA3CF, 0xFF30, 0xA3D0, + 0xFF31, 0xA3D1, 0xFF32, 0xA3D2, 0xFF33, 0xA3D3, 0xFF34, 0xA3D4, + 0xFF35, 0xA3D5, 0xFF36, 0xA3D6, 0xFF37, 0xA3D7, 0xFF38, 0xA3D8, + 0xFF39, 0xA3D9, 0xFF3A, 0xA3DA, 0xFF3B, 0xA3DB, 0xFF3C, 0xA3DC, + 0xFF3D, 0xA3DD, 0xFF3E, 0xA3DE, 0xFF3F, 0xA3DF, 0xFF40, 0xA3E0, + 0xFF41, 0xA3E1, 0xFF42, 0xA3E2, 0xFF43, 0xA3E3, 0xFF44, 0xA3E4, + 0xFF45, 0xA3E5, 0xFF46, 0xA3E6, 0xFF47, 0xA3E7, 0xFF48, 0xA3E8, + 0xFF49, 0xA3E9, 0xFF4A, 0xA3EA, 0xFF4B, 0xA3EB, 0xFF4C, 0xA3EC, + 0xFF4D, 0xA3ED, 0xFF4E, 0xA3EE, 0xFF4F, 0xA3EF, 0xFF50, 0xA3F0, + 0xFF51, 0xA3F1, 0xFF52, 0xA3F2, 0xFF53, 0xA3F3, 0xFF54, 0xA3F4, + 0xFF55, 0xA3F5, 0xFF56, 0xA3F6, 0xFF57, 0xA3F7, 0xFF58, 0xA3F8, + 0xFF59, 0xA3F9, 0xFF5A, 0xA3FA, 0xFF5B, 0xA3FB, 0xFF5C, 0xA3FC, + 0xFF5D, 0xA3FD, 0xFF5E, 0xA1AB, 0xFFE0, 0xA1E9, 0xFFE1, 0xA1EA, + 0xFFE2, 0xA956, 0xFFE3, 0xA3FE, 0xFFE4, 0xA957, 0xFFE5, 0xA3A4, + 0, 0 +}; + +static +const WCHAR oem2uni[] = +{ + /* OEM - Unicode, OEM - Unicode, OEM - Unicode, OEM - Unicode */ + 0x0080, 0x20AC, 0x8140, 0x4E02, 0x8141, 0x4E04, 0x8142, 0x4E05, + 0x8143, 0x4E06, 0x8144, 0x4E0F, 0x8145, 0x4E12, 0x8146, 0x4E17, + 0x8147, 0x4E1F, 0x8148, 0x4E20, 0x8149, 0x4E21, 0x814A, 0x4E23, + 0x814B, 0x4E26, 0x814C, 0x4E29, 0x814D, 0x4E2E, 0x814E, 0x4E2F, + 0x814F, 0x4E31, 0x8150, 0x4E33, 0x8151, 0x4E35, 0x8152, 0x4E37, + 0x8153, 0x4E3C, 0x8154, 0x4E40, 0x8155, 0x4E41, 0x8156, 0x4E42, + 0x8157, 0x4E44, 0x8158, 0x4E46, 0x8159, 0x4E4A, 0x815A, 0x4E51, + 0x815B, 0x4E55, 0x815C, 0x4E57, 0x815D, 0x4E5A, 0x815E, 0x4E5B, + 0x815F, 0x4E62, 0x8160, 0x4E63, 0x8161, 0x4E64, 0x8162, 0x4E65, + 0x8163, 0x4E67, 0x8164, 0x4E68, 0x8165, 0x4E6A, 0x8166, 0x4E6B, + 0x8167, 0x4E6C, 0x8168, 0x4E6D, 0x8169, 0x4E6E, 0x816A, 0x4E6F, + 0x816B, 0x4E72, 0x816C, 0x4E74, 0x816D, 0x4E75, 0x816E, 0x4E76, + 0x816F, 0x4E77, 0x8170, 0x4E78, 0x8171, 0x4E79, 0x8172, 0x4E7A, + 0x8173, 0x4E7B, 0x8174, 0x4E7C, 0x8175, 0x4E7D, 0x8176, 0x4E7F, + 0x8177, 0x4E80, 0x8178, 0x4E81, 0x8179, 0x4E82, 0x817A, 0x4E83, + 0x817B, 0x4E84, 0x817C, 0x4E85, 0x817D, 0x4E87, 0x817E, 0x4E8A, + 0x8180, 0x4E90, 0x8181, 0x4E96, 0x8182, 0x4E97, 0x8183, 0x4E99, + 0x8184, 0x4E9C, 0x8185, 0x4E9D, 0x8186, 0x4E9E, 0x8187, 0x4EA3, + 0x8188, 0x4EAA, 0x8189, 0x4EAF, 0x818A, 0x4EB0, 0x818B, 0x4EB1, + 0x818C, 0x4EB4, 0x818D, 0x4EB6, 0x818E, 0x4EB7, 0x818F, 0x4EB8, + 0x8190, 0x4EB9, 0x8191, 0x4EBC, 0x8192, 0x4EBD, 0x8193, 0x4EBE, + 0x8194, 0x4EC8, 0x8195, 0x4ECC, 0x8196, 0x4ECF, 0x8197, 0x4ED0, + 0x8198, 0x4ED2, 0x8199, 0x4EDA, 0x819A, 0x4EDB, 0x819B, 0x4EDC, + 0x819C, 0x4EE0, 0x819D, 0x4EE2, 0x819E, 0x4EE6, 0x819F, 0x4EE7, + 0x81A0, 0x4EE9, 0x81A1, 0x4EED, 0x81A2, 0x4EEE, 0x81A3, 0x4EEF, + 0x81A4, 0x4EF1, 0x81A5, 0x4EF4, 0x81A6, 0x4EF8, 0x81A7, 0x4EF9, + 0x81A8, 0x4EFA, 0x81A9, 0x4EFC, 0x81AA, 0x4EFE, 0x81AB, 0x4F00, + 0x81AC, 0x4F02, 0x81AD, 0x4F03, 0x81AE, 0x4F04, 0x81AF, 0x4F05, + 0x81B0, 0x4F06, 0x81B1, 0x4F07, 0x81B2, 0x4F08, 0x81B3, 0x4F0B, + 0x81B4, 0x4F0C, 0x81B5, 0x4F12, 0x81B6, 0x4F13, 0x81B7, 0x4F14, + 0x81B8, 0x4F15, 0x81B9, 0x4F16, 0x81BA, 0x4F1C, 0x81BB, 0x4F1D, + 0x81BC, 0x4F21, 0x81BD, 0x4F23, 0x81BE, 0x4F28, 0x81BF, 0x4F29, + 0x81C0, 0x4F2C, 0x81C1, 0x4F2D, 0x81C2, 0x4F2E, 0x81C3, 0x4F31, + 0x81C4, 0x4F33, 0x81C5, 0x4F35, 0x81C6, 0x4F37, 0x81C7, 0x4F39, + 0x81C8, 0x4F3B, 0x81C9, 0x4F3E, 0x81CA, 0x4F3F, 0x81CB, 0x4F40, + 0x81CC, 0x4F41, 0x81CD, 0x4F42, 0x81CE, 0x4F44, 0x81CF, 0x4F45, + 0x81D0, 0x4F47, 0x81D1, 0x4F48, 0x81D2, 0x4F49, 0x81D3, 0x4F4A, + 0x81D4, 0x4F4B, 0x81D5, 0x4F4C, 0x81D6, 0x4F52, 0x81D7, 0x4F54, + 0x81D8, 0x4F56, 0x81D9, 0x4F61, 0x81DA, 0x4F62, 0x81DB, 0x4F66, + 0x81DC, 0x4F68, 0x81DD, 0x4F6A, 0x81DE, 0x4F6B, 0x81DF, 0x4F6D, + 0x81E0, 0x4F6E, 0x81E1, 0x4F71, 0x81E2, 0x4F72, 0x81E3, 0x4F75, + 0x81E4, 0x4F77, 0x81E5, 0x4F78, 0x81E6, 0x4F79, 0x81E7, 0x4F7A, + 0x81E8, 0x4F7D, 0x81E9, 0x4F80, 0x81EA, 0x4F81, 0x81EB, 0x4F82, + 0x81EC, 0x4F85, 0x81ED, 0x4F86, 0x81EE, 0x4F87, 0x81EF, 0x4F8A, + 0x81F0, 0x4F8C, 0x81F1, 0x4F8E, 0x81F2, 0x4F90, 0x81F3, 0x4F92, + 0x81F4, 0x4F93, 0x81F5, 0x4F95, 0x81F6, 0x4F96, 0x81F7, 0x4F98, + 0x81F8, 0x4F99, 0x81F9, 0x4F9A, 0x81FA, 0x4F9C, 0x81FB, 0x4F9E, + 0x81FC, 0x4F9F, 0x81FD, 0x4FA1, 0x81FE, 0x4FA2, 0x8240, 0x4FA4, + 0x8241, 0x4FAB, 0x8242, 0x4FAD, 0x8243, 0x4FB0, 0x8244, 0x4FB1, + 0x8245, 0x4FB2, 0x8246, 0x4FB3, 0x8247, 0x4FB4, 0x8248, 0x4FB6, + 0x8249, 0x4FB7, 0x824A, 0x4FB8, 0x824B, 0x4FB9, 0x824C, 0x4FBA, + 0x824D, 0x4FBB, 0x824E, 0x4FBC, 0x824F, 0x4FBD, 0x8250, 0x4FBE, + 0x8251, 0x4FC0, 0x8252, 0x4FC1, 0x8253, 0x4FC2, 0x8254, 0x4FC6, + 0x8255, 0x4FC7, 0x8256, 0x4FC8, 0x8257, 0x4FC9, 0x8258, 0x4FCB, + 0x8259, 0x4FCC, 0x825A, 0x4FCD, 0x825B, 0x4FD2, 0x825C, 0x4FD3, + 0x825D, 0x4FD4, 0x825E, 0x4FD5, 0x825F, 0x4FD6, 0x8260, 0x4FD9, + 0x8261, 0x4FDB, 0x8262, 0x4FE0, 0x8263, 0x4FE2, 0x8264, 0x4FE4, + 0x8265, 0x4FE5, 0x8266, 0x4FE7, 0x8267, 0x4FEB, 0x8268, 0x4FEC, + 0x8269, 0x4FF0, 0x826A, 0x4FF2, 0x826B, 0x4FF4, 0x826C, 0x4FF5, + 0x826D, 0x4FF6, 0x826E, 0x4FF7, 0x826F, 0x4FF9, 0x8270, 0x4FFB, + 0x8271, 0x4FFC, 0x8272, 0x4FFD, 0x8273, 0x4FFF, 0x8274, 0x5000, + 0x8275, 0x5001, 0x8276, 0x5002, 0x8277, 0x5003, 0x8278, 0x5004, + 0x8279, 0x5005, 0x827A, 0x5006, 0x827B, 0x5007, 0x827C, 0x5008, + 0x827D, 0x5009, 0x827E, 0x500A, 0x8280, 0x500B, 0x8281, 0x500E, + 0x8282, 0x5010, 0x8283, 0x5011, 0x8284, 0x5013, 0x8285, 0x5015, + 0x8286, 0x5016, 0x8287, 0x5017, 0x8288, 0x501B, 0x8289, 0x501D, + 0x828A, 0x501E, 0x828B, 0x5020, 0x828C, 0x5022, 0x828D, 0x5023, + 0x828E, 0x5024, 0x828F, 0x5027, 0x8290, 0x502B, 0x8291, 0x502F, + 0x8292, 0x5030, 0x8293, 0x5031, 0x8294, 0x5032, 0x8295, 0x5033, + 0x8296, 0x5034, 0x8297, 0x5035, 0x8298, 0x5036, 0x8299, 0x5037, + 0x829A, 0x5038, 0x829B, 0x5039, 0x829C, 0x503B, 0x829D, 0x503D, + 0x829E, 0x503F, 0x829F, 0x5040, 0x82A0, 0x5041, 0x82A1, 0x5042, + 0x82A2, 0x5044, 0x82A3, 0x5045, 0x82A4, 0x5046, 0x82A5, 0x5049, + 0x82A6, 0x504A, 0x82A7, 0x504B, 0x82A8, 0x504D, 0x82A9, 0x5050, + 0x82AA, 0x5051, 0x82AB, 0x5052, 0x82AC, 0x5053, 0x82AD, 0x5054, + 0x82AE, 0x5056, 0x82AF, 0x5057, 0x82B0, 0x5058, 0x82B1, 0x5059, + 0x82B2, 0x505B, 0x82B3, 0x505D, 0x82B4, 0x505E, 0x82B5, 0x505F, + 0x82B6, 0x5060, 0x82B7, 0x5061, 0x82B8, 0x5062, 0x82B9, 0x5063, + 0x82BA, 0x5064, 0x82BB, 0x5066, 0x82BC, 0x5067, 0x82BD, 0x5068, + 0x82BE, 0x5069, 0x82BF, 0x506A, 0x82C0, 0x506B, 0x82C1, 0x506D, + 0x82C2, 0x506E, 0x82C3, 0x506F, 0x82C4, 0x5070, 0x82C5, 0x5071, + 0x82C6, 0x5072, 0x82C7, 0x5073, 0x82C8, 0x5074, 0x82C9, 0x5075, + 0x82CA, 0x5078, 0x82CB, 0x5079, 0x82CC, 0x507A, 0x82CD, 0x507C, + 0x82CE, 0x507D, 0x82CF, 0x5081, 0x82D0, 0x5082, 0x82D1, 0x5083, + 0x82D2, 0x5084, 0x82D3, 0x5086, 0x82D4, 0x5087, 0x82D5, 0x5089, + 0x82D6, 0x508A, 0x82D7, 0x508B, 0x82D8, 0x508C, 0x82D9, 0x508E, + 0x82DA, 0x508F, 0x82DB, 0x5090, 0x82DC, 0x5091, 0x82DD, 0x5092, + 0x82DE, 0x5093, 0x82DF, 0x5094, 0x82E0, 0x5095, 0x82E1, 0x5096, + 0x82E2, 0x5097, 0x82E3, 0x5098, 0x82E4, 0x5099, 0x82E5, 0x509A, + 0x82E6, 0x509B, 0x82E7, 0x509C, 0x82E8, 0x509D, 0x82E9, 0x509E, + 0x82EA, 0x509F, 0x82EB, 0x50A0, 0x82EC, 0x50A1, 0x82ED, 0x50A2, + 0x82EE, 0x50A4, 0x82EF, 0x50A6, 0x82F0, 0x50AA, 0x82F1, 0x50AB, + 0x82F2, 0x50AD, 0x82F3, 0x50AE, 0x82F4, 0x50AF, 0x82F5, 0x50B0, + 0x82F6, 0x50B1, 0x82F7, 0x50B3, 0x82F8, 0x50B4, 0x82F9, 0x50B5, + 0x82FA, 0x50B6, 0x82FB, 0x50B7, 0x82FC, 0x50B8, 0x82FD, 0x50B9, + 0x82FE, 0x50BC, 0x8340, 0x50BD, 0x8341, 0x50BE, 0x8342, 0x50BF, + 0x8343, 0x50C0, 0x8344, 0x50C1, 0x8345, 0x50C2, 0x8346, 0x50C3, + 0x8347, 0x50C4, 0x8348, 0x50C5, 0x8349, 0x50C6, 0x834A, 0x50C7, + 0x834B, 0x50C8, 0x834C, 0x50C9, 0x834D, 0x50CA, 0x834E, 0x50CB, + 0x834F, 0x50CC, 0x8350, 0x50CD, 0x8351, 0x50CE, 0x8352, 0x50D0, + 0x8353, 0x50D1, 0x8354, 0x50D2, 0x8355, 0x50D3, 0x8356, 0x50D4, + 0x8357, 0x50D5, 0x8358, 0x50D7, 0x8359, 0x50D8, 0x835A, 0x50D9, + 0x835B, 0x50DB, 0x835C, 0x50DC, 0x835D, 0x50DD, 0x835E, 0x50DE, + 0x835F, 0x50DF, 0x8360, 0x50E0, 0x8361, 0x50E1, 0x8362, 0x50E2, + 0x8363, 0x50E3, 0x8364, 0x50E4, 0x8365, 0x50E5, 0x8366, 0x50E8, + 0x8367, 0x50E9, 0x8368, 0x50EA, 0x8369, 0x50EB, 0x836A, 0x50EF, + 0x836B, 0x50F0, 0x836C, 0x50F1, 0x836D, 0x50F2, 0x836E, 0x50F4, + 0x836F, 0x50F6, 0x8370, 0x50F7, 0x8371, 0x50F8, 0x8372, 0x50F9, + 0x8373, 0x50FA, 0x8374, 0x50FC, 0x8375, 0x50FD, 0x8376, 0x50FE, + 0x8377, 0x50FF, 0x8378, 0x5100, 0x8379, 0x5101, 0x837A, 0x5102, + 0x837B, 0x5103, 0x837C, 0x5104, 0x837D, 0x5105, 0x837E, 0x5108, + 0x8380, 0x5109, 0x8381, 0x510A, 0x8382, 0x510C, 0x8383, 0x510D, + 0x8384, 0x510E, 0x8385, 0x510F, 0x8386, 0x5110, 0x8387, 0x5111, + 0x8388, 0x5113, 0x8389, 0x5114, 0x838A, 0x5115, 0x838B, 0x5116, + 0x838C, 0x5117, 0x838D, 0x5118, 0x838E, 0x5119, 0x838F, 0x511A, + 0x8390, 0x511B, 0x8391, 0x511C, 0x8392, 0x511D, 0x8393, 0x511E, + 0x8394, 0x511F, 0x8395, 0x5120, 0x8396, 0x5122, 0x8397, 0x5123, + 0x8398, 0x5124, 0x8399, 0x5125, 0x839A, 0x5126, 0x839B, 0x5127, + 0x839C, 0x5128, 0x839D, 0x5129, 0x839E, 0x512A, 0x839F, 0x512B, + 0x83A0, 0x512C, 0x83A1, 0x512D, 0x83A2, 0x512E, 0x83A3, 0x512F, + 0x83A4, 0x5130, 0x83A5, 0x5131, 0x83A6, 0x5132, 0x83A7, 0x5133, + 0x83A8, 0x5134, 0x83A9, 0x5135, 0x83AA, 0x5136, 0x83AB, 0x5137, + 0x83AC, 0x5138, 0x83AD, 0x5139, 0x83AE, 0x513A, 0x83AF, 0x513B, + 0x83B0, 0x513C, 0x83B1, 0x513D, 0x83B2, 0x513E, 0x83B3, 0x5142, + 0x83B4, 0x5147, 0x83B5, 0x514A, 0x83B6, 0x514C, 0x83B7, 0x514E, + 0x83B8, 0x514F, 0x83B9, 0x5150, 0x83BA, 0x5152, 0x83BB, 0x5153, + 0x83BC, 0x5157, 0x83BD, 0x5158, 0x83BE, 0x5159, 0x83BF, 0x515B, + 0x83C0, 0x515D, 0x83C1, 0x515E, 0x83C2, 0x515F, 0x83C3, 0x5160, + 0x83C4, 0x5161, 0x83C5, 0x5163, 0x83C6, 0x5164, 0x83C7, 0x5166, + 0x83C8, 0x5167, 0x83C9, 0x5169, 0x83CA, 0x516A, 0x83CB, 0x516F, + 0x83CC, 0x5172, 0x83CD, 0x517A, 0x83CE, 0x517E, 0x83CF, 0x517F, + 0x83D0, 0x5183, 0x83D1, 0x5184, 0x83D2, 0x5186, 0x83D3, 0x5187, + 0x83D4, 0x518A, 0x83D5, 0x518B, 0x83D6, 0x518E, 0x83D7, 0x518F, + 0x83D8, 0x5190, 0x83D9, 0x5191, 0x83DA, 0x5193, 0x83DB, 0x5194, + 0x83DC, 0x5198, 0x83DD, 0x519A, 0x83DE, 0x519D, 0x83DF, 0x519E, + 0x83E0, 0x519F, 0x83E1, 0x51A1, 0x83E2, 0x51A3, 0x83E3, 0x51A6, + 0x83E4, 0x51A7, 0x83E5, 0x51A8, 0x83E6, 0x51A9, 0x83E7, 0x51AA, + 0x83E8, 0x51AD, 0x83E9, 0x51AE, 0x83EA, 0x51B4, 0x83EB, 0x51B8, + 0x83EC, 0x51B9, 0x83ED, 0x51BA, 0x83EE, 0x51BE, 0x83EF, 0x51BF, + 0x83F0, 0x51C1, 0x83F1, 0x51C2, 0x83F2, 0x51C3, 0x83F3, 0x51C5, + 0x83F4, 0x51C8, 0x83F5, 0x51CA, 0x83F6, 0x51CD, 0x83F7, 0x51CE, + 0x83F8, 0x51D0, 0x83F9, 0x51D2, 0x83FA, 0x51D3, 0x83FB, 0x51D4, + 0x83FC, 0x51D5, 0x83FD, 0x51D6, 0x83FE, 0x51D7, 0x8440, 0x51D8, + 0x8441, 0x51D9, 0x8442, 0x51DA, 0x8443, 0x51DC, 0x8444, 0x51DE, + 0x8445, 0x51DF, 0x8446, 0x51E2, 0x8447, 0x51E3, 0x8448, 0x51E5, + 0x8449, 0x51E6, 0x844A, 0x51E7, 0x844B, 0x51E8, 0x844C, 0x51E9, + 0x844D, 0x51EA, 0x844E, 0x51EC, 0x844F, 0x51EE, 0x8450, 0x51F1, + 0x8451, 0x51F2, 0x8452, 0x51F4, 0x8453, 0x51F7, 0x8454, 0x51FE, + 0x8455, 0x5204, 0x8456, 0x5205, 0x8457, 0x5209, 0x8458, 0x520B, + 0x8459, 0x520C, 0x845A, 0x520F, 0x845B, 0x5210, 0x845C, 0x5213, + 0x845D, 0x5214, 0x845E, 0x5215, 0x845F, 0x521C, 0x8460, 0x521E, + 0x8461, 0x521F, 0x8462, 0x5221, 0x8463, 0x5222, 0x8464, 0x5223, + 0x8465, 0x5225, 0x8466, 0x5226, 0x8467, 0x5227, 0x8468, 0x522A, + 0x8469, 0x522C, 0x846A, 0x522F, 0x846B, 0x5231, 0x846C, 0x5232, + 0x846D, 0x5234, 0x846E, 0x5235, 0x846F, 0x523C, 0x8470, 0x523E, + 0x8471, 0x5244, 0x8472, 0x5245, 0x8473, 0x5246, 0x8474, 0x5247, + 0x8475, 0x5248, 0x8476, 0x5249, 0x8477, 0x524B, 0x8478, 0x524E, + 0x8479, 0x524F, 0x847A, 0x5252, 0x847B, 0x5253, 0x847C, 0x5255, + 0x847D, 0x5257, 0x847E, 0x5258, 0x8480, 0x5259, 0x8481, 0x525A, + 0x8482, 0x525B, 0x8483, 0x525D, 0x8484, 0x525F, 0x8485, 0x5260, + 0x8486, 0x5262, 0x8487, 0x5263, 0x8488, 0x5264, 0x8489, 0x5266, + 0x848A, 0x5268, 0x848B, 0x526B, 0x848C, 0x526C, 0x848D, 0x526D, + 0x848E, 0x526E, 0x848F, 0x5270, 0x8490, 0x5271, 0x8491, 0x5273, + 0x8492, 0x5274, 0x8493, 0x5275, 0x8494, 0x5276, 0x8495, 0x5277, + 0x8496, 0x5278, 0x8497, 0x5279, 0x8498, 0x527A, 0x8499, 0x527B, + 0x849A, 0x527C, 0x849B, 0x527E, 0x849C, 0x5280, 0x849D, 0x5283, + 0x849E, 0x5284, 0x849F, 0x5285, 0x84A0, 0x5286, 0x84A1, 0x5287, + 0x84A2, 0x5289, 0x84A3, 0x528A, 0x84A4, 0x528B, 0x84A5, 0x528C, + 0x84A6, 0x528D, 0x84A7, 0x528E, 0x84A8, 0x528F, 0x84A9, 0x5291, + 0x84AA, 0x5292, 0x84AB, 0x5294, 0x84AC, 0x5295, 0x84AD, 0x5296, + 0x84AE, 0x5297, 0x84AF, 0x5298, 0x84B0, 0x5299, 0x84B1, 0x529A, + 0x84B2, 0x529C, 0x84B3, 0x52A4, 0x84B4, 0x52A5, 0x84B5, 0x52A6, + 0x84B6, 0x52A7, 0x84B7, 0x52AE, 0x84B8, 0x52AF, 0x84B9, 0x52B0, + 0x84BA, 0x52B4, 0x84BB, 0x52B5, 0x84BC, 0x52B6, 0x84BD, 0x52B7, + 0x84BE, 0x52B8, 0x84BF, 0x52B9, 0x84C0, 0x52BA, 0x84C1, 0x52BB, + 0x84C2, 0x52BC, 0x84C3, 0x52BD, 0x84C4, 0x52C0, 0x84C5, 0x52C1, + 0x84C6, 0x52C2, 0x84C7, 0x52C4, 0x84C8, 0x52C5, 0x84C9, 0x52C6, + 0x84CA, 0x52C8, 0x84CB, 0x52CA, 0x84CC, 0x52CC, 0x84CD, 0x52CD, + 0x84CE, 0x52CE, 0x84CF, 0x52CF, 0x84D0, 0x52D1, 0x84D1, 0x52D3, + 0x84D2, 0x52D4, 0x84D3, 0x52D5, 0x84D4, 0x52D7, 0x84D5, 0x52D9, + 0x84D6, 0x52DA, 0x84D7, 0x52DB, 0x84D8, 0x52DC, 0x84D9, 0x52DD, + 0x84DA, 0x52DE, 0x84DB, 0x52E0, 0x84DC, 0x52E1, 0x84DD, 0x52E2, + 0x84DE, 0x52E3, 0x84DF, 0x52E5, 0x84E0, 0x52E6, 0x84E1, 0x52E7, + 0x84E2, 0x52E8, 0x84E3, 0x52E9, 0x84E4, 0x52EA, 0x84E5, 0x52EB, + 0x84E6, 0x52EC, 0x84E7, 0x52ED, 0x84E8, 0x52EE, 0x84E9, 0x52EF, + 0x84EA, 0x52F1, 0x84EB, 0x52F2, 0x84EC, 0x52F3, 0x84ED, 0x52F4, + 0x84EE, 0x52F5, 0x84EF, 0x52F6, 0x84F0, 0x52F7, 0x84F1, 0x52F8, + 0x84F2, 0x52FB, 0x84F3, 0x52FC, 0x84F4, 0x52FD, 0x84F5, 0x5301, + 0x84F6, 0x5302, 0x84F7, 0x5303, 0x84F8, 0x5304, 0x84F9, 0x5307, + 0x84FA, 0x5309, 0x84FB, 0x530A, 0x84FC, 0x530B, 0x84FD, 0x530C, + 0x84FE, 0x530E, 0x8540, 0x5311, 0x8541, 0x5312, 0x8542, 0x5313, + 0x8543, 0x5314, 0x8544, 0x5318, 0x8545, 0x531B, 0x8546, 0x531C, + 0x8547, 0x531E, 0x8548, 0x531F, 0x8549, 0x5322, 0x854A, 0x5324, + 0x854B, 0x5325, 0x854C, 0x5327, 0x854D, 0x5328, 0x854E, 0x5329, + 0x854F, 0x532B, 0x8550, 0x532C, 0x8551, 0x532D, 0x8552, 0x532F, + 0x8553, 0x5330, 0x8554, 0x5331, 0x8555, 0x5332, 0x8556, 0x5333, + 0x8557, 0x5334, 0x8558, 0x5335, 0x8559, 0x5336, 0x855A, 0x5337, + 0x855B, 0x5338, 0x855C, 0x533C, 0x855D, 0x533D, 0x855E, 0x5340, + 0x855F, 0x5342, 0x8560, 0x5344, 0x8561, 0x5346, 0x8562, 0x534B, + 0x8563, 0x534C, 0x8564, 0x534D, 0x8565, 0x5350, 0x8566, 0x5354, + 0x8567, 0x5358, 0x8568, 0x5359, 0x8569, 0x535B, 0x856A, 0x535D, + 0x856B, 0x5365, 0x856C, 0x5368, 0x856D, 0x536A, 0x856E, 0x536C, + 0x856F, 0x536D, 0x8570, 0x5372, 0x8571, 0x5376, 0x8572, 0x5379, + 0x8573, 0x537B, 0x8574, 0x537C, 0x8575, 0x537D, 0x8576, 0x537E, + 0x8577, 0x5380, 0x8578, 0x5381, 0x8579, 0x5383, 0x857A, 0x5387, + 0x857B, 0x5388, 0x857C, 0x538A, 0x857D, 0x538E, 0x857E, 0x538F, + 0x8580, 0x5390, 0x8581, 0x5391, 0x8582, 0x5392, 0x8583, 0x5393, + 0x8584, 0x5394, 0x8585, 0x5396, 0x8586, 0x5397, 0x8587, 0x5399, + 0x8588, 0x539B, 0x8589, 0x539C, 0x858A, 0x539E, 0x858B, 0x53A0, + 0x858C, 0x53A1, 0x858D, 0x53A4, 0x858E, 0x53A7, 0x858F, 0x53AA, + 0x8590, 0x53AB, 0x8591, 0x53AC, 0x8592, 0x53AD, 0x8593, 0x53AF, + 0x8594, 0x53B0, 0x8595, 0x53B1, 0x8596, 0x53B2, 0x8597, 0x53B3, + 0x8598, 0x53B4, 0x8599, 0x53B5, 0x859A, 0x53B7, 0x859B, 0x53B8, + 0x859C, 0x53B9, 0x859D, 0x53BA, 0x859E, 0x53BC, 0x859F, 0x53BD, + 0x85A0, 0x53BE, 0x85A1, 0x53C0, 0x85A2, 0x53C3, 0x85A3, 0x53C4, + 0x85A4, 0x53C5, 0x85A5, 0x53C6, 0x85A6, 0x53C7, 0x85A7, 0x53CE, + 0x85A8, 0x53CF, 0x85A9, 0x53D0, 0x85AA, 0x53D2, 0x85AB, 0x53D3, + 0x85AC, 0x53D5, 0x85AD, 0x53DA, 0x85AE, 0x53DC, 0x85AF, 0x53DD, + 0x85B0, 0x53DE, 0x85B1, 0x53E1, 0x85B2, 0x53E2, 0x85B3, 0x53E7, + 0x85B4, 0x53F4, 0x85B5, 0x53FA, 0x85B6, 0x53FE, 0x85B7, 0x53FF, + 0x85B8, 0x5400, 0x85B9, 0x5402, 0x85BA, 0x5405, 0x85BB, 0x5407, + 0x85BC, 0x540B, 0x85BD, 0x5414, 0x85BE, 0x5418, 0x85BF, 0x5419, + 0x85C0, 0x541A, 0x85C1, 0x541C, 0x85C2, 0x5422, 0x85C3, 0x5424, + 0x85C4, 0x5425, 0x85C5, 0x542A, 0x85C6, 0x5430, 0x85C7, 0x5433, + 0x85C8, 0x5436, 0x85C9, 0x5437, 0x85CA, 0x543A, 0x85CB, 0x543D, + 0x85CC, 0x543F, 0x85CD, 0x5441, 0x85CE, 0x5442, 0x85CF, 0x5444, + 0x85D0, 0x5445, 0x85D1, 0x5447, 0x85D2, 0x5449, 0x85D3, 0x544C, + 0x85D4, 0x544D, 0x85D5, 0x544E, 0x85D6, 0x544F, 0x85D7, 0x5451, + 0x85D8, 0x545A, 0x85D9, 0x545D, 0x85DA, 0x545E, 0x85DB, 0x545F, + 0x85DC, 0x5460, 0x85DD, 0x5461, 0x85DE, 0x5463, 0x85DF, 0x5465, + 0x85E0, 0x5467, 0x85E1, 0x5469, 0x85E2, 0x546A, 0x85E3, 0x546B, + 0x85E4, 0x546C, 0x85E5, 0x546D, 0x85E6, 0x546E, 0x85E7, 0x546F, + 0x85E8, 0x5470, 0x85E9, 0x5474, 0x85EA, 0x5479, 0x85EB, 0x547A, + 0x85EC, 0x547E, 0x85ED, 0x547F, 0x85EE, 0x5481, 0x85EF, 0x5483, + 0x85F0, 0x5485, 0x85F1, 0x5487, 0x85F2, 0x5488, 0x85F3, 0x5489, + 0x85F4, 0x548A, 0x85F5, 0x548D, 0x85F6, 0x5491, 0x85F7, 0x5493, + 0x85F8, 0x5497, 0x85F9, 0x5498, 0x85FA, 0x549C, 0x85FB, 0x549E, + 0x85FC, 0x549F, 0x85FD, 0x54A0, 0x85FE, 0x54A1, 0x8640, 0x54A2, + 0x8641, 0x54A5, 0x8642, 0x54AE, 0x8643, 0x54B0, 0x8644, 0x54B2, + 0x8645, 0x54B5, 0x8646, 0x54B6, 0x8647, 0x54B7, 0x8648, 0x54B9, + 0x8649, 0x54BA, 0x864A, 0x54BC, 0x864B, 0x54BE, 0x864C, 0x54C3, + 0x864D, 0x54C5, 0x864E, 0x54CA, 0x864F, 0x54CB, 0x8650, 0x54D6, + 0x8651, 0x54D8, 0x8652, 0x54DB, 0x8653, 0x54E0, 0x8654, 0x54E1, + 0x8655, 0x54E2, 0x8656, 0x54E3, 0x8657, 0x54E4, 0x8658, 0x54EB, + 0x8659, 0x54EC, 0x865A, 0x54EF, 0x865B, 0x54F0, 0x865C, 0x54F1, + 0x865D, 0x54F4, 0x865E, 0x54F5, 0x865F, 0x54F6, 0x8660, 0x54F7, + 0x8661, 0x54F8, 0x8662, 0x54F9, 0x8663, 0x54FB, 0x8664, 0x54FE, + 0x8665, 0x5500, 0x8666, 0x5502, 0x8667, 0x5503, 0x8668, 0x5504, + 0x8669, 0x5505, 0x866A, 0x5508, 0x866B, 0x550A, 0x866C, 0x550B, + 0x866D, 0x550C, 0x866E, 0x550D, 0x866F, 0x550E, 0x8670, 0x5512, + 0x8671, 0x5513, 0x8672, 0x5515, 0x8673, 0x5516, 0x8674, 0x5517, + 0x8675, 0x5518, 0x8676, 0x5519, 0x8677, 0x551A, 0x8678, 0x551C, + 0x8679, 0x551D, 0x867A, 0x551E, 0x867B, 0x551F, 0x867C, 0x5521, + 0x867D, 0x5525, 0x867E, 0x5526, 0x8680, 0x5528, 0x8681, 0x5529, + 0x8682, 0x552B, 0x8683, 0x552D, 0x8684, 0x5532, 0x8685, 0x5534, + 0x8686, 0x5535, 0x8687, 0x5536, 0x8688, 0x5538, 0x8689, 0x5539, + 0x868A, 0x553A, 0x868B, 0x553B, 0x868C, 0x553D, 0x868D, 0x5540, + 0x868E, 0x5542, 0x868F, 0x5545, 0x8690, 0x5547, 0x8691, 0x5548, + 0x8692, 0x554B, 0x8693, 0x554C, 0x8694, 0x554D, 0x8695, 0x554E, + 0x8696, 0x554F, 0x8697, 0x5551, 0x8698, 0x5552, 0x8699, 0x5553, + 0x869A, 0x5554, 0x869B, 0x5557, 0x869C, 0x5558, 0x869D, 0x5559, + 0x869E, 0x555A, 0x869F, 0x555B, 0x86A0, 0x555D, 0x86A1, 0x555E, + 0x86A2, 0x555F, 0x86A3, 0x5560, 0x86A4, 0x5562, 0x86A5, 0x5563, + 0x86A6, 0x5568, 0x86A7, 0x5569, 0x86A8, 0x556B, 0x86A9, 0x556F, + 0x86AA, 0x5570, 0x86AB, 0x5571, 0x86AC, 0x5572, 0x86AD, 0x5573, + 0x86AE, 0x5574, 0x86AF, 0x5579, 0x86B0, 0x557A, 0x86B1, 0x557D, + 0x86B2, 0x557F, 0x86B3, 0x5585, 0x86B4, 0x5586, 0x86B5, 0x558C, + 0x86B6, 0x558D, 0x86B7, 0x558E, 0x86B8, 0x5590, 0x86B9, 0x5592, + 0x86BA, 0x5593, 0x86BB, 0x5595, 0x86BC, 0x5596, 0x86BD, 0x5597, + 0x86BE, 0x559A, 0x86BF, 0x559B, 0x86C0, 0x559E, 0x86C1, 0x55A0, + 0x86C2, 0x55A1, 0x86C3, 0x55A2, 0x86C4, 0x55A3, 0x86C5, 0x55A4, + 0x86C6, 0x55A5, 0x86C7, 0x55A6, 0x86C8, 0x55A8, 0x86C9, 0x55A9, + 0x86CA, 0x55AA, 0x86CB, 0x55AB, 0x86CC, 0x55AC, 0x86CD, 0x55AD, + 0x86CE, 0x55AE, 0x86CF, 0x55AF, 0x86D0, 0x55B0, 0x86D1, 0x55B2, + 0x86D2, 0x55B4, 0x86D3, 0x55B6, 0x86D4, 0x55B8, 0x86D5, 0x55BA, + 0x86D6, 0x55BC, 0x86D7, 0x55BF, 0x86D8, 0x55C0, 0x86D9, 0x55C1, + 0x86DA, 0x55C2, 0x86DB, 0x55C3, 0x86DC, 0x55C6, 0x86DD, 0x55C7, + 0x86DE, 0x55C8, 0x86DF, 0x55CA, 0x86E0, 0x55CB, 0x86E1, 0x55CE, + 0x86E2, 0x55CF, 0x86E3, 0x55D0, 0x86E4, 0x55D5, 0x86E5, 0x55D7, + 0x86E6, 0x55D8, 0x86E7, 0x55D9, 0x86E8, 0x55DA, 0x86E9, 0x55DB, + 0x86EA, 0x55DE, 0x86EB, 0x55E0, 0x86EC, 0x55E2, 0x86ED, 0x55E7, + 0x86EE, 0x55E9, 0x86EF, 0x55ED, 0x86F0, 0x55EE, 0x86F1, 0x55F0, + 0x86F2, 0x55F1, 0x86F3, 0x55F4, 0x86F4, 0x55F6, 0x86F5, 0x55F8, + 0x86F6, 0x55F9, 0x86F7, 0x55FA, 0x86F8, 0x55FB, 0x86F9, 0x55FC, + 0x86FA, 0x55FF, 0x86FB, 0x5602, 0x86FC, 0x5603, 0x86FD, 0x5604, + 0x86FE, 0x5605, 0x8740, 0x5606, 0x8741, 0x5607, 0x8742, 0x560A, + 0x8743, 0x560B, 0x8744, 0x560D, 0x8745, 0x5610, 0x8746, 0x5611, + 0x8747, 0x5612, 0x8748, 0x5613, 0x8749, 0x5614, 0x874A, 0x5615, + 0x874B, 0x5616, 0x874C, 0x5617, 0x874D, 0x5619, 0x874E, 0x561A, + 0x874F, 0x561C, 0x8750, 0x561D, 0x8751, 0x5620, 0x8752, 0x5621, + 0x8753, 0x5622, 0x8754, 0x5625, 0x8755, 0x5626, 0x8756, 0x5628, + 0x8757, 0x5629, 0x8758, 0x562A, 0x8759, 0x562B, 0x875A, 0x562E, + 0x875B, 0x562F, 0x875C, 0x5630, 0x875D, 0x5633, 0x875E, 0x5635, + 0x875F, 0x5637, 0x8760, 0x5638, 0x8761, 0x563A, 0x8762, 0x563C, + 0x8763, 0x563D, 0x8764, 0x563E, 0x8765, 0x5640, 0x8766, 0x5641, + 0x8767, 0x5642, 0x8768, 0x5643, 0x8769, 0x5644, 0x876A, 0x5645, + 0x876B, 0x5646, 0x876C, 0x5647, 0x876D, 0x5648, 0x876E, 0x5649, + 0x876F, 0x564A, 0x8770, 0x564B, 0x8771, 0x564F, 0x8772, 0x5650, + 0x8773, 0x5651, 0x8774, 0x5652, 0x8775, 0x5653, 0x8776, 0x5655, + 0x8777, 0x5656, 0x8778, 0x565A, 0x8779, 0x565B, 0x877A, 0x565D, + 0x877B, 0x565E, 0x877C, 0x565F, 0x877D, 0x5660, 0x877E, 0x5661, + 0x8780, 0x5663, 0x8781, 0x5665, 0x8782, 0x5666, 0x8783, 0x5667, + 0x8784, 0x566D, 0x8785, 0x566E, 0x8786, 0x566F, 0x8787, 0x5670, + 0x8788, 0x5672, 0x8789, 0x5673, 0x878A, 0x5674, 0x878B, 0x5675, + 0x878C, 0x5677, 0x878D, 0x5678, 0x878E, 0x5679, 0x878F, 0x567A, + 0x8790, 0x567D, 0x8791, 0x567E, 0x8792, 0x567F, 0x8793, 0x5680, + 0x8794, 0x5681, 0x8795, 0x5682, 0x8796, 0x5683, 0x8797, 0x5684, + 0x8798, 0x5687, 0x8799, 0x5688, 0x879A, 0x5689, 0x879B, 0x568A, + 0x879C, 0x568B, 0x879D, 0x568C, 0x879E, 0x568D, 0x879F, 0x5690, + 0x87A0, 0x5691, 0x87A1, 0x5692, 0x87A2, 0x5694, 0x87A3, 0x5695, + 0x87A4, 0x5696, 0x87A5, 0x5697, 0x87A6, 0x5698, 0x87A7, 0x5699, + 0x87A8, 0x569A, 0x87A9, 0x569B, 0x87AA, 0x569C, 0x87AB, 0x569D, + 0x87AC, 0x569E, 0x87AD, 0x569F, 0x87AE, 0x56A0, 0x87AF, 0x56A1, + 0x87B0, 0x56A2, 0x87B1, 0x56A4, 0x87B2, 0x56A5, 0x87B3, 0x56A6, + 0x87B4, 0x56A7, 0x87B5, 0x56A8, 0x87B6, 0x56A9, 0x87B7, 0x56AA, + 0x87B8, 0x56AB, 0x87B9, 0x56AC, 0x87BA, 0x56AD, 0x87BB, 0x56AE, + 0x87BC, 0x56B0, 0x87BD, 0x56B1, 0x87BE, 0x56B2, 0x87BF, 0x56B3, + 0x87C0, 0x56B4, 0x87C1, 0x56B5, 0x87C2, 0x56B6, 0x87C3, 0x56B8, + 0x87C4, 0x56B9, 0x87C5, 0x56BA, 0x87C6, 0x56BB, 0x87C7, 0x56BD, + 0x87C8, 0x56BE, 0x87C9, 0x56BF, 0x87CA, 0x56C0, 0x87CB, 0x56C1, + 0x87CC, 0x56C2, 0x87CD, 0x56C3, 0x87CE, 0x56C4, 0x87CF, 0x56C5, + 0x87D0, 0x56C6, 0x87D1, 0x56C7, 0x87D2, 0x56C8, 0x87D3, 0x56C9, + 0x87D4, 0x56CB, 0x87D5, 0x56CC, 0x87D6, 0x56CD, 0x87D7, 0x56CE, + 0x87D8, 0x56CF, 0x87D9, 0x56D0, 0x87DA, 0x56D1, 0x87DB, 0x56D2, + 0x87DC, 0x56D3, 0x87DD, 0x56D5, 0x87DE, 0x56D6, 0x87DF, 0x56D8, + 0x87E0, 0x56D9, 0x87E1, 0x56DC, 0x87E2, 0x56E3, 0x87E3, 0x56E5, + 0x87E4, 0x56E6, 0x87E5, 0x56E7, 0x87E6, 0x56E8, 0x87E7, 0x56E9, + 0x87E8, 0x56EA, 0x87E9, 0x56EC, 0x87EA, 0x56EE, 0x87EB, 0x56EF, + 0x87EC, 0x56F2, 0x87ED, 0x56F3, 0x87EE, 0x56F6, 0x87EF, 0x56F7, + 0x87F0, 0x56F8, 0x87F1, 0x56FB, 0x87F2, 0x56FC, 0x87F3, 0x5700, + 0x87F4, 0x5701, 0x87F5, 0x5702, 0x87F6, 0x5705, 0x87F7, 0x5707, + 0x87F8, 0x570B, 0x87F9, 0x570C, 0x87FA, 0x570D, 0x87FB, 0x570E, + 0x87FC, 0x570F, 0x87FD, 0x5710, 0x87FE, 0x5711, 0x8840, 0x5712, + 0x8841, 0x5713, 0x8842, 0x5714, 0x8843, 0x5715, 0x8844, 0x5716, + 0x8845, 0x5717, 0x8846, 0x5718, 0x8847, 0x5719, 0x8848, 0x571A, + 0x8849, 0x571B, 0x884A, 0x571D, 0x884B, 0x571E, 0x884C, 0x5720, + 0x884D, 0x5721, 0x884E, 0x5722, 0x884F, 0x5724, 0x8850, 0x5725, + 0x8851, 0x5726, 0x8852, 0x5727, 0x8853, 0x572B, 0x8854, 0x5731, + 0x8855, 0x5732, 0x8856, 0x5734, 0x8857, 0x5735, 0x8858, 0x5736, + 0x8859, 0x5737, 0x885A, 0x5738, 0x885B, 0x573C, 0x885C, 0x573D, + 0x885D, 0x573F, 0x885E, 0x5741, 0x885F, 0x5743, 0x8860, 0x5744, + 0x8861, 0x5745, 0x8862, 0x5746, 0x8863, 0x5748, 0x8864, 0x5749, + 0x8865, 0x574B, 0x8866, 0x5752, 0x8867, 0x5753, 0x8868, 0x5754, + 0x8869, 0x5755, 0x886A, 0x5756, 0x886B, 0x5758, 0x886C, 0x5759, + 0x886D, 0x5762, 0x886E, 0x5763, 0x886F, 0x5765, 0x8870, 0x5767, + 0x8871, 0x576C, 0x8872, 0x576E, 0x8873, 0x5770, 0x8874, 0x5771, + 0x8875, 0x5772, 0x8876, 0x5774, 0x8877, 0x5775, 0x8878, 0x5778, + 0x8879, 0x5779, 0x887A, 0x577A, 0x887B, 0x577D, 0x887C, 0x577E, + 0x887D, 0x577F, 0x887E, 0x5780, 0x8880, 0x5781, 0x8881, 0x5787, + 0x8882, 0x5788, 0x8883, 0x5789, 0x8884, 0x578A, 0x8885, 0x578D, + 0x8886, 0x578E, 0x8887, 0x578F, 0x8888, 0x5790, 0x8889, 0x5791, + 0x888A, 0x5794, 0x888B, 0x5795, 0x888C, 0x5796, 0x888D, 0x5797, + 0x888E, 0x5798, 0x888F, 0x5799, 0x8890, 0x579A, 0x8891, 0x579C, + 0x8892, 0x579D, 0x8893, 0x579E, 0x8894, 0x579F, 0x8895, 0x57A5, + 0x8896, 0x57A8, 0x8897, 0x57AA, 0x8898, 0x57AC, 0x8899, 0x57AF, + 0x889A, 0x57B0, 0x889B, 0x57B1, 0x889C, 0x57B3, 0x889D, 0x57B5, + 0x889E, 0x57B6, 0x889F, 0x57B7, 0x88A0, 0x57B9, 0x88A1, 0x57BA, + 0x88A2, 0x57BB, 0x88A3, 0x57BC, 0x88A4, 0x57BD, 0x88A5, 0x57BE, + 0x88A6, 0x57BF, 0x88A7, 0x57C0, 0x88A8, 0x57C1, 0x88A9, 0x57C4, + 0x88AA, 0x57C5, 0x88AB, 0x57C6, 0x88AC, 0x57C7, 0x88AD, 0x57C8, + 0x88AE, 0x57C9, 0x88AF, 0x57CA, 0x88B0, 0x57CC, 0x88B1, 0x57CD, + 0x88B2, 0x57D0, 0x88B3, 0x57D1, 0x88B4, 0x57D3, 0x88B5, 0x57D6, + 0x88B6, 0x57D7, 0x88B7, 0x57DB, 0x88B8, 0x57DC, 0x88B9, 0x57DE, + 0x88BA, 0x57E1, 0x88BB, 0x57E2, 0x88BC, 0x57E3, 0x88BD, 0x57E5, + 0x88BE, 0x57E6, 0x88BF, 0x57E7, 0x88C0, 0x57E8, 0x88C1, 0x57E9, + 0x88C2, 0x57EA, 0x88C3, 0x57EB, 0x88C4, 0x57EC, 0x88C5, 0x57EE, + 0x88C6, 0x57F0, 0x88C7, 0x57F1, 0x88C8, 0x57F2, 0x88C9, 0x57F3, + 0x88CA, 0x57F5, 0x88CB, 0x57F6, 0x88CC, 0x57F7, 0x88CD, 0x57FB, + 0x88CE, 0x57FC, 0x88CF, 0x57FE, 0x88D0, 0x57FF, 0x88D1, 0x5801, + 0x88D2, 0x5803, 0x88D3, 0x5804, 0x88D4, 0x5805, 0x88D5, 0x5808, + 0x88D6, 0x5809, 0x88D7, 0x580A, 0x88D8, 0x580C, 0x88D9, 0x580E, + 0x88DA, 0x580F, 0x88DB, 0x5810, 0x88DC, 0x5812, 0x88DD, 0x5813, + 0x88DE, 0x5814, 0x88DF, 0x5816, 0x88E0, 0x5817, 0x88E1, 0x5818, + 0x88E2, 0x581A, 0x88E3, 0x581B, 0x88E4, 0x581C, 0x88E5, 0x581D, + 0x88E6, 0x581F, 0x88E7, 0x5822, 0x88E8, 0x5823, 0x88E9, 0x5825, + 0x88EA, 0x5826, 0x88EB, 0x5827, 0x88EC, 0x5828, 0x88ED, 0x5829, + 0x88EE, 0x582B, 0x88EF, 0x582C, 0x88F0, 0x582D, 0x88F1, 0x582E, + 0x88F2, 0x582F, 0x88F3, 0x5831, 0x88F4, 0x5832, 0x88F5, 0x5833, + 0x88F6, 0x5834, 0x88F7, 0x5836, 0x88F8, 0x5837, 0x88F9, 0x5838, + 0x88FA, 0x5839, 0x88FB, 0x583A, 0x88FC, 0x583B, 0x88FD, 0x583C, + 0x88FE, 0x583D, 0x8940, 0x583E, 0x8941, 0x583F, 0x8942, 0x5840, + 0x8943, 0x5841, 0x8944, 0x5842, 0x8945, 0x5843, 0x8946, 0x5845, + 0x8947, 0x5846, 0x8948, 0x5847, 0x8949, 0x5848, 0x894A, 0x5849, + 0x894B, 0x584A, 0x894C, 0x584B, 0x894D, 0x584E, 0x894E, 0x584F, + 0x894F, 0x5850, 0x8950, 0x5852, 0x8951, 0x5853, 0x8952, 0x5855, + 0x8953, 0x5856, 0x8954, 0x5857, 0x8955, 0x5859, 0x8956, 0x585A, + 0x8957, 0x585B, 0x8958, 0x585C, 0x8959, 0x585D, 0x895A, 0x585F, + 0x895B, 0x5860, 0x895C, 0x5861, 0x895D, 0x5862, 0x895E, 0x5863, + 0x895F, 0x5864, 0x8960, 0x5866, 0x8961, 0x5867, 0x8962, 0x5868, + 0x8963, 0x5869, 0x8964, 0x586A, 0x8965, 0x586D, 0x8966, 0x586E, + 0x8967, 0x586F, 0x8968, 0x5870, 0x8969, 0x5871, 0x896A, 0x5872, + 0x896B, 0x5873, 0x896C, 0x5874, 0x896D, 0x5875, 0x896E, 0x5876, + 0x896F, 0x5877, 0x8970, 0x5878, 0x8971, 0x5879, 0x8972, 0x587A, + 0x8973, 0x587B, 0x8974, 0x587C, 0x8975, 0x587D, 0x8976, 0x587F, + 0x8977, 0x5882, 0x8978, 0x5884, 0x8979, 0x5886, 0x897A, 0x5887, + 0x897B, 0x5888, 0x897C, 0x588A, 0x897D, 0x588B, 0x897E, 0x588C, + 0x8980, 0x588D, 0x8981, 0x588E, 0x8982, 0x588F, 0x8983, 0x5890, + 0x8984, 0x5891, 0x8985, 0x5894, 0x8986, 0x5895, 0x8987, 0x5896, + 0x8988, 0x5897, 0x8989, 0x5898, 0x898A, 0x589B, 0x898B, 0x589C, + 0x898C, 0x589D, 0x898D, 0x58A0, 0x898E, 0x58A1, 0x898F, 0x58A2, + 0x8990, 0x58A3, 0x8991, 0x58A4, 0x8992, 0x58A5, 0x8993, 0x58A6, + 0x8994, 0x58A7, 0x8995, 0x58AA, 0x8996, 0x58AB, 0x8997, 0x58AC, + 0x8998, 0x58AD, 0x8999, 0x58AE, 0x899A, 0x58AF, 0x899B, 0x58B0, + 0x899C, 0x58B1, 0x899D, 0x58B2, 0x899E, 0x58B3, 0x899F, 0x58B4, + 0x89A0, 0x58B5, 0x89A1, 0x58B6, 0x89A2, 0x58B7, 0x89A3, 0x58B8, + 0x89A4, 0x58B9, 0x89A5, 0x58BA, 0x89A6, 0x58BB, 0x89A7, 0x58BD, + 0x89A8, 0x58BE, 0x89A9, 0x58BF, 0x89AA, 0x58C0, 0x89AB, 0x58C2, + 0x89AC, 0x58C3, 0x89AD, 0x58C4, 0x89AE, 0x58C6, 0x89AF, 0x58C7, + 0x89B0, 0x58C8, 0x89B1, 0x58C9, 0x89B2, 0x58CA, 0x89B3, 0x58CB, + 0x89B4, 0x58CC, 0x89B5, 0x58CD, 0x89B6, 0x58CE, 0x89B7, 0x58CF, + 0x89B8, 0x58D0, 0x89B9, 0x58D2, 0x89BA, 0x58D3, 0x89BB, 0x58D4, + 0x89BC, 0x58D6, 0x89BD, 0x58D7, 0x89BE, 0x58D8, 0x89BF, 0x58D9, + 0x89C0, 0x58DA, 0x89C1, 0x58DB, 0x89C2, 0x58DC, 0x89C3, 0x58DD, + 0x89C4, 0x58DE, 0x89C5, 0x58DF, 0x89C6, 0x58E0, 0x89C7, 0x58E1, + 0x89C8, 0x58E2, 0x89C9, 0x58E3, 0x89CA, 0x58E5, 0x89CB, 0x58E6, + 0x89CC, 0x58E7, 0x89CD, 0x58E8, 0x89CE, 0x58E9, 0x89CF, 0x58EA, + 0x89D0, 0x58ED, 0x89D1, 0x58EF, 0x89D2, 0x58F1, 0x89D3, 0x58F2, + 0x89D4, 0x58F4, 0x89D5, 0x58F5, 0x89D6, 0x58F7, 0x89D7, 0x58F8, + 0x89D8, 0x58FA, 0x89D9, 0x58FB, 0x89DA, 0x58FC, 0x89DB, 0x58FD, + 0x89DC, 0x58FE, 0x89DD, 0x58FF, 0x89DE, 0x5900, 0x89DF, 0x5901, + 0x89E0, 0x5903, 0x89E1, 0x5905, 0x89E2, 0x5906, 0x89E3, 0x5908, + 0x89E4, 0x5909, 0x89E5, 0x590A, 0x89E6, 0x590B, 0x89E7, 0x590C, + 0x89E8, 0x590E, 0x89E9, 0x5910, 0x89EA, 0x5911, 0x89EB, 0x5912, + 0x89EC, 0x5913, 0x89ED, 0x5917, 0x89EE, 0x5918, 0x89EF, 0x591B, + 0x89F0, 0x591D, 0x89F1, 0x591E, 0x89F2, 0x5920, 0x89F3, 0x5921, + 0x89F4, 0x5922, 0x89F5, 0x5923, 0x89F6, 0x5926, 0x89F7, 0x5928, + 0x89F8, 0x592C, 0x89F9, 0x5930, 0x89FA, 0x5932, 0x89FB, 0x5933, + 0x89FC, 0x5935, 0x89FD, 0x5936, 0x89FE, 0x593B, 0x8A40, 0x593D, + 0x8A41, 0x593E, 0x8A42, 0x593F, 0x8A43, 0x5940, 0x8A44, 0x5943, + 0x8A45, 0x5945, 0x8A46, 0x5946, 0x8A47, 0x594A, 0x8A48, 0x594C, + 0x8A49, 0x594D, 0x8A4A, 0x5950, 0x8A4B, 0x5952, 0x8A4C, 0x5953, + 0x8A4D, 0x5959, 0x8A4E, 0x595B, 0x8A4F, 0x595C, 0x8A50, 0x595D, + 0x8A51, 0x595E, 0x8A52, 0x595F, 0x8A53, 0x5961, 0x8A54, 0x5963, + 0x8A55, 0x5964, 0x8A56, 0x5966, 0x8A57, 0x5967, 0x8A58, 0x5968, + 0x8A59, 0x5969, 0x8A5A, 0x596A, 0x8A5B, 0x596B, 0x8A5C, 0x596C, + 0x8A5D, 0x596D, 0x8A5E, 0x596E, 0x8A5F, 0x596F, 0x8A60, 0x5970, + 0x8A61, 0x5971, 0x8A62, 0x5972, 0x8A63, 0x5975, 0x8A64, 0x5977, + 0x8A65, 0x597A, 0x8A66, 0x597B, 0x8A67, 0x597C, 0x8A68, 0x597E, + 0x8A69, 0x597F, 0x8A6A, 0x5980, 0x8A6B, 0x5985, 0x8A6C, 0x5989, + 0x8A6D, 0x598B, 0x8A6E, 0x598C, 0x8A6F, 0x598E, 0x8A70, 0x598F, + 0x8A71, 0x5990, 0x8A72, 0x5991, 0x8A73, 0x5994, 0x8A74, 0x5995, + 0x8A75, 0x5998, 0x8A76, 0x599A, 0x8A77, 0x599B, 0x8A78, 0x599C, + 0x8A79, 0x599D, 0x8A7A, 0x599F, 0x8A7B, 0x59A0, 0x8A7C, 0x59A1, + 0x8A7D, 0x59A2, 0x8A7E, 0x59A6, 0x8A80, 0x59A7, 0x8A81, 0x59AC, + 0x8A82, 0x59AD, 0x8A83, 0x59B0, 0x8A84, 0x59B1, 0x8A85, 0x59B3, + 0x8A86, 0x59B4, 0x8A87, 0x59B5, 0x8A88, 0x59B6, 0x8A89, 0x59B7, + 0x8A8A, 0x59B8, 0x8A8B, 0x59BA, 0x8A8C, 0x59BC, 0x8A8D, 0x59BD, + 0x8A8E, 0x59BF, 0x8A8F, 0x59C0, 0x8A90, 0x59C1, 0x8A91, 0x59C2, + 0x8A92, 0x59C3, 0x8A93, 0x59C4, 0x8A94, 0x59C5, 0x8A95, 0x59C7, + 0x8A96, 0x59C8, 0x8A97, 0x59C9, 0x8A98, 0x59CC, 0x8A99, 0x59CD, + 0x8A9A, 0x59CE, 0x8A9B, 0x59CF, 0x8A9C, 0x59D5, 0x8A9D, 0x59D6, + 0x8A9E, 0x59D9, 0x8A9F, 0x59DB, 0x8AA0, 0x59DE, 0x8AA1, 0x59DF, + 0x8AA2, 0x59E0, 0x8AA3, 0x59E1, 0x8AA4, 0x59E2, 0x8AA5, 0x59E4, + 0x8AA6, 0x59E6, 0x8AA7, 0x59E7, 0x8AA8, 0x59E9, 0x8AA9, 0x59EA, + 0x8AAA, 0x59EB, 0x8AAB, 0x59ED, 0x8AAC, 0x59EE, 0x8AAD, 0x59EF, + 0x8AAE, 0x59F0, 0x8AAF, 0x59F1, 0x8AB0, 0x59F2, 0x8AB1, 0x59F3, + 0x8AB2, 0x59F4, 0x8AB3, 0x59F5, 0x8AB4, 0x59F6, 0x8AB5, 0x59F7, + 0x8AB6, 0x59F8, 0x8AB7, 0x59FA, 0x8AB8, 0x59FC, 0x8AB9, 0x59FD, + 0x8ABA, 0x59FE, 0x8ABB, 0x5A00, 0x8ABC, 0x5A02, 0x8ABD, 0x5A0A, + 0x8ABE, 0x5A0B, 0x8ABF, 0x5A0D, 0x8AC0, 0x5A0E, 0x8AC1, 0x5A0F, + 0x8AC2, 0x5A10, 0x8AC3, 0x5A12, 0x8AC4, 0x5A14, 0x8AC5, 0x5A15, + 0x8AC6, 0x5A16, 0x8AC7, 0x5A17, 0x8AC8, 0x5A19, 0x8AC9, 0x5A1A, + 0x8ACA, 0x5A1B, 0x8ACB, 0x5A1D, 0x8ACC, 0x5A1E, 0x8ACD, 0x5A21, + 0x8ACE, 0x5A22, 0x8ACF, 0x5A24, 0x8AD0, 0x5A26, 0x8AD1, 0x5A27, + 0x8AD2, 0x5A28, 0x8AD3, 0x5A2A, 0x8AD4, 0x5A2B, 0x8AD5, 0x5A2C, + 0x8AD6, 0x5A2D, 0x8AD7, 0x5A2E, 0x8AD8, 0x5A2F, 0x8AD9, 0x5A30, + 0x8ADA, 0x5A33, 0x8ADB, 0x5A35, 0x8ADC, 0x5A37, 0x8ADD, 0x5A38, + 0x8ADE, 0x5A39, 0x8ADF, 0x5A3A, 0x8AE0, 0x5A3B, 0x8AE1, 0x5A3D, + 0x8AE2, 0x5A3E, 0x8AE3, 0x5A3F, 0x8AE4, 0x5A41, 0x8AE5, 0x5A42, + 0x8AE6, 0x5A43, 0x8AE7, 0x5A44, 0x8AE8, 0x5A45, 0x8AE9, 0x5A47, + 0x8AEA, 0x5A48, 0x8AEB, 0x5A4B, 0x8AEC, 0x5A4C, 0x8AED, 0x5A4D, + 0x8AEE, 0x5A4E, 0x8AEF, 0x5A4F, 0x8AF0, 0x5A50, 0x8AF1, 0x5A51, + 0x8AF2, 0x5A52, 0x8AF3, 0x5A53, 0x8AF4, 0x5A54, 0x8AF5, 0x5A56, + 0x8AF6, 0x5A57, 0x8AF7, 0x5A58, 0x8AF8, 0x5A59, 0x8AF9, 0x5A5B, + 0x8AFA, 0x5A5C, 0x8AFB, 0x5A5D, 0x8AFC, 0x5A5E, 0x8AFD, 0x5A5F, + 0x8AFE, 0x5A60, 0x8B40, 0x5A61, 0x8B41, 0x5A63, 0x8B42, 0x5A64, + 0x8B43, 0x5A65, 0x8B44, 0x5A66, 0x8B45, 0x5A68, 0x8B46, 0x5A69, + 0x8B47, 0x5A6B, 0x8B48, 0x5A6C, 0x8B49, 0x5A6D, 0x8B4A, 0x5A6E, + 0x8B4B, 0x5A6F, 0x8B4C, 0x5A70, 0x8B4D, 0x5A71, 0x8B4E, 0x5A72, + 0x8B4F, 0x5A73, 0x8B50, 0x5A78, 0x8B51, 0x5A79, 0x8B52, 0x5A7B, + 0x8B53, 0x5A7C, 0x8B54, 0x5A7D, 0x8B55, 0x5A7E, 0x8B56, 0x5A80, + 0x8B57, 0x5A81, 0x8B58, 0x5A82, 0x8B59, 0x5A83, 0x8B5A, 0x5A84, + 0x8B5B, 0x5A85, 0x8B5C, 0x5A86, 0x8B5D, 0x5A87, 0x8B5E, 0x5A88, + 0x8B5F, 0x5A89, 0x8B60, 0x5A8A, 0x8B61, 0x5A8B, 0x8B62, 0x5A8C, + 0x8B63, 0x5A8D, 0x8B64, 0x5A8E, 0x8B65, 0x5A8F, 0x8B66, 0x5A90, + 0x8B67, 0x5A91, 0x8B68, 0x5A93, 0x8B69, 0x5A94, 0x8B6A, 0x5A95, + 0x8B6B, 0x5A96, 0x8B6C, 0x5A97, 0x8B6D, 0x5A98, 0x8B6E, 0x5A99, + 0x8B6F, 0x5A9C, 0x8B70, 0x5A9D, 0x8B71, 0x5A9E, 0x8B72, 0x5A9F, + 0x8B73, 0x5AA0, 0x8B74, 0x5AA1, 0x8B75, 0x5AA2, 0x8B76, 0x5AA3, + 0x8B77, 0x5AA4, 0x8B78, 0x5AA5, 0x8B79, 0x5AA6, 0x8B7A, 0x5AA7, + 0x8B7B, 0x5AA8, 0x8B7C, 0x5AA9, 0x8B7D, 0x5AAB, 0x8B7E, 0x5AAC, + 0x8B80, 0x5AAD, 0x8B81, 0x5AAE, 0x8B82, 0x5AAF, 0x8B83, 0x5AB0, + 0x8B84, 0x5AB1, 0x8B85, 0x5AB4, 0x8B86, 0x5AB6, 0x8B87, 0x5AB7, + 0x8B88, 0x5AB9, 0x8B89, 0x5ABA, 0x8B8A, 0x5ABB, 0x8B8B, 0x5ABC, + 0x8B8C, 0x5ABD, 0x8B8D, 0x5ABF, 0x8B8E, 0x5AC0, 0x8B8F, 0x5AC3, + 0x8B90, 0x5AC4, 0x8B91, 0x5AC5, 0x8B92, 0x5AC6, 0x8B93, 0x5AC7, + 0x8B94, 0x5AC8, 0x8B95, 0x5ACA, 0x8B96, 0x5ACB, 0x8B97, 0x5ACD, + 0x8B98, 0x5ACE, 0x8B99, 0x5ACF, 0x8B9A, 0x5AD0, 0x8B9B, 0x5AD1, + 0x8B9C, 0x5AD3, 0x8B9D, 0x5AD5, 0x8B9E, 0x5AD7, 0x8B9F, 0x5AD9, + 0x8BA0, 0x5ADA, 0x8BA1, 0x5ADB, 0x8BA2, 0x5ADD, 0x8BA3, 0x5ADE, + 0x8BA4, 0x5ADF, 0x8BA5, 0x5AE2, 0x8BA6, 0x5AE4, 0x8BA7, 0x5AE5, + 0x8BA8, 0x5AE7, 0x8BA9, 0x5AE8, 0x8BAA, 0x5AEA, 0x8BAB, 0x5AEC, + 0x8BAC, 0x5AED, 0x8BAD, 0x5AEE, 0x8BAE, 0x5AEF, 0x8BAF, 0x5AF0, + 0x8BB0, 0x5AF2, 0x8BB1, 0x5AF3, 0x8BB2, 0x5AF4, 0x8BB3, 0x5AF5, + 0x8BB4, 0x5AF6, 0x8BB5, 0x5AF7, 0x8BB6, 0x5AF8, 0x8BB7, 0x5AF9, + 0x8BB8, 0x5AFA, 0x8BB9, 0x5AFB, 0x8BBA, 0x5AFC, 0x8BBB, 0x5AFD, + 0x8BBC, 0x5AFE, 0x8BBD, 0x5AFF, 0x8BBE, 0x5B00, 0x8BBF, 0x5B01, + 0x8BC0, 0x5B02, 0x8BC1, 0x5B03, 0x8BC2, 0x5B04, 0x8BC3, 0x5B05, + 0x8BC4, 0x5B06, 0x8BC5, 0x5B07, 0x8BC6, 0x5B08, 0x8BC7, 0x5B0A, + 0x8BC8, 0x5B0B, 0x8BC9, 0x5B0C, 0x8BCA, 0x5B0D, 0x8BCB, 0x5B0E, + 0x8BCC, 0x5B0F, 0x8BCD, 0x5B10, 0x8BCE, 0x5B11, 0x8BCF, 0x5B12, + 0x8BD0, 0x5B13, 0x8BD1, 0x5B14, 0x8BD2, 0x5B15, 0x8BD3, 0x5B18, + 0x8BD4, 0x5B19, 0x8BD5, 0x5B1A, 0x8BD6, 0x5B1B, 0x8BD7, 0x5B1C, + 0x8BD8, 0x5B1D, 0x8BD9, 0x5B1E, 0x8BDA, 0x5B1F, 0x8BDB, 0x5B20, + 0x8BDC, 0x5B21, 0x8BDD, 0x5B22, 0x8BDE, 0x5B23, 0x8BDF, 0x5B24, + 0x8BE0, 0x5B25, 0x8BE1, 0x5B26, 0x8BE2, 0x5B27, 0x8BE3, 0x5B28, + 0x8BE4, 0x5B29, 0x8BE5, 0x5B2A, 0x8BE6, 0x5B2B, 0x8BE7, 0x5B2C, + 0x8BE8, 0x5B2D, 0x8BE9, 0x5B2E, 0x8BEA, 0x5B2F, 0x8BEB, 0x5B30, + 0x8BEC, 0x5B31, 0x8BED, 0x5B33, 0x8BEE, 0x5B35, 0x8BEF, 0x5B36, + 0x8BF0, 0x5B38, 0x8BF1, 0x5B39, 0x8BF2, 0x5B3A, 0x8BF3, 0x5B3B, + 0x8BF4, 0x5B3C, 0x8BF5, 0x5B3D, 0x8BF6, 0x5B3E, 0x8BF7, 0x5B3F, + 0x8BF8, 0x5B41, 0x8BF9, 0x5B42, 0x8BFA, 0x5B43, 0x8BFB, 0x5B44, + 0x8BFC, 0x5B45, 0x8BFD, 0x5B46, 0x8BFE, 0x5B47, 0x8C40, 0x5B48, + 0x8C41, 0x5B49, 0x8C42, 0x5B4A, 0x8C43, 0x5B4B, 0x8C44, 0x5B4C, + 0x8C45, 0x5B4D, 0x8C46, 0x5B4E, 0x8C47, 0x5B4F, 0x8C48, 0x5B52, + 0x8C49, 0x5B56, 0x8C4A, 0x5B5E, 0x8C4B, 0x5B60, 0x8C4C, 0x5B61, + 0x8C4D, 0x5B67, 0x8C4E, 0x5B68, 0x8C4F, 0x5B6B, 0x8C50, 0x5B6D, + 0x8C51, 0x5B6E, 0x8C52, 0x5B6F, 0x8C53, 0x5B72, 0x8C54, 0x5B74, + 0x8C55, 0x5B76, 0x8C56, 0x5B77, 0x8C57, 0x5B78, 0x8C58, 0x5B79, + 0x8C59, 0x5B7B, 0x8C5A, 0x5B7C, 0x8C5B, 0x5B7E, 0x8C5C, 0x5B7F, + 0x8C5D, 0x5B82, 0x8C5E, 0x5B86, 0x8C5F, 0x5B8A, 0x8C60, 0x5B8D, + 0x8C61, 0x5B8E, 0x8C62, 0x5B90, 0x8C63, 0x5B91, 0x8C64, 0x5B92, + 0x8C65, 0x5B94, 0x8C66, 0x5B96, 0x8C67, 0x5B9F, 0x8C68, 0x5BA7, + 0x8C69, 0x5BA8, 0x8C6A, 0x5BA9, 0x8C6B, 0x5BAC, 0x8C6C, 0x5BAD, + 0x8C6D, 0x5BAE, 0x8C6E, 0x5BAF, 0x8C6F, 0x5BB1, 0x8C70, 0x5BB2, + 0x8C71, 0x5BB7, 0x8C72, 0x5BBA, 0x8C73, 0x5BBB, 0x8C74, 0x5BBC, + 0x8C75, 0x5BC0, 0x8C76, 0x5BC1, 0x8C77, 0x5BC3, 0x8C78, 0x5BC8, + 0x8C79, 0x5BC9, 0x8C7A, 0x5BCA, 0x8C7B, 0x5BCB, 0x8C7C, 0x5BCD, + 0x8C7D, 0x5BCE, 0x8C7E, 0x5BCF, 0x8C80, 0x5BD1, 0x8C81, 0x5BD4, + 0x8C82, 0x5BD5, 0x8C83, 0x5BD6, 0x8C84, 0x5BD7, 0x8C85, 0x5BD8, + 0x8C86, 0x5BD9, 0x8C87, 0x5BDA, 0x8C88, 0x5BDB, 0x8C89, 0x5BDC, + 0x8C8A, 0x5BE0, 0x8C8B, 0x5BE2, 0x8C8C, 0x5BE3, 0x8C8D, 0x5BE6, + 0x8C8E, 0x5BE7, 0x8C8F, 0x5BE9, 0x8C90, 0x5BEA, 0x8C91, 0x5BEB, + 0x8C92, 0x5BEC, 0x8C93, 0x5BED, 0x8C94, 0x5BEF, 0x8C95, 0x5BF1, + 0x8C96, 0x5BF2, 0x8C97, 0x5BF3, 0x8C98, 0x5BF4, 0x8C99, 0x5BF5, + 0x8C9A, 0x5BF6, 0x8C9B, 0x5BF7, 0x8C9C, 0x5BFD, 0x8C9D, 0x5BFE, + 0x8C9E, 0x5C00, 0x8C9F, 0x5C02, 0x8CA0, 0x5C03, 0x8CA1, 0x5C05, + 0x8CA2, 0x5C07, 0x8CA3, 0x5C08, 0x8CA4, 0x5C0B, 0x8CA5, 0x5C0C, + 0x8CA6, 0x5C0D, 0x8CA7, 0x5C0E, 0x8CA8, 0x5C10, 0x8CA9, 0x5C12, + 0x8CAA, 0x5C13, 0x8CAB, 0x5C17, 0x8CAC, 0x5C19, 0x8CAD, 0x5C1B, + 0x8CAE, 0x5C1E, 0x8CAF, 0x5C1F, 0x8CB0, 0x5C20, 0x8CB1, 0x5C21, + 0x8CB2, 0x5C23, 0x8CB3, 0x5C26, 0x8CB4, 0x5C28, 0x8CB5, 0x5C29, + 0x8CB6, 0x5C2A, 0x8CB7, 0x5C2B, 0x8CB8, 0x5C2D, 0x8CB9, 0x5C2E, + 0x8CBA, 0x5C2F, 0x8CBB, 0x5C30, 0x8CBC, 0x5C32, 0x8CBD, 0x5C33, + 0x8CBE, 0x5C35, 0x8CBF, 0x5C36, 0x8CC0, 0x5C37, 0x8CC1, 0x5C43, + 0x8CC2, 0x5C44, 0x8CC3, 0x5C46, 0x8CC4, 0x5C47, 0x8CC5, 0x5C4C, + 0x8CC6, 0x5C4D, 0x8CC7, 0x5C52, 0x8CC8, 0x5C53, 0x8CC9, 0x5C54, + 0x8CCA, 0x5C56, 0x8CCB, 0x5C57, 0x8CCC, 0x5C58, 0x8CCD, 0x5C5A, + 0x8CCE, 0x5C5B, 0x8CCF, 0x5C5C, 0x8CD0, 0x5C5D, 0x8CD1, 0x5C5F, + 0x8CD2, 0x5C62, 0x8CD3, 0x5C64, 0x8CD4, 0x5C67, 0x8CD5, 0x5C68, + 0x8CD6, 0x5C69, 0x8CD7, 0x5C6A, 0x8CD8, 0x5C6B, 0x8CD9, 0x5C6C, + 0x8CDA, 0x5C6D, 0x8CDB, 0x5C70, 0x8CDC, 0x5C72, 0x8CDD, 0x5C73, + 0x8CDE, 0x5C74, 0x8CDF, 0x5C75, 0x8CE0, 0x5C76, 0x8CE1, 0x5C77, + 0x8CE2, 0x5C78, 0x8CE3, 0x5C7B, 0x8CE4, 0x5C7C, 0x8CE5, 0x5C7D, + 0x8CE6, 0x5C7E, 0x8CE7, 0x5C80, 0x8CE8, 0x5C83, 0x8CE9, 0x5C84, + 0x8CEA, 0x5C85, 0x8CEB, 0x5C86, 0x8CEC, 0x5C87, 0x8CED, 0x5C89, + 0x8CEE, 0x5C8A, 0x8CEF, 0x5C8B, 0x8CF0, 0x5C8E, 0x8CF1, 0x5C8F, + 0x8CF2, 0x5C92, 0x8CF3, 0x5C93, 0x8CF4, 0x5C95, 0x8CF5, 0x5C9D, + 0x8CF6, 0x5C9E, 0x8CF7, 0x5C9F, 0x8CF8, 0x5CA0, 0x8CF9, 0x5CA1, + 0x8CFA, 0x5CA4, 0x8CFB, 0x5CA5, 0x8CFC, 0x5CA6, 0x8CFD, 0x5CA7, + 0x8CFE, 0x5CA8, 0x8D40, 0x5CAA, 0x8D41, 0x5CAE, 0x8D42, 0x5CAF, + 0x8D43, 0x5CB0, 0x8D44, 0x5CB2, 0x8D45, 0x5CB4, 0x8D46, 0x5CB6, + 0x8D47, 0x5CB9, 0x8D48, 0x5CBA, 0x8D49, 0x5CBB, 0x8D4A, 0x5CBC, + 0x8D4B, 0x5CBE, 0x8D4C, 0x5CC0, 0x8D4D, 0x5CC2, 0x8D4E, 0x5CC3, + 0x8D4F, 0x5CC5, 0x8D50, 0x5CC6, 0x8D51, 0x5CC7, 0x8D52, 0x5CC8, + 0x8D53, 0x5CC9, 0x8D54, 0x5CCA, 0x8D55, 0x5CCC, 0x8D56, 0x5CCD, + 0x8D57, 0x5CCE, 0x8D58, 0x5CCF, 0x8D59, 0x5CD0, 0x8D5A, 0x5CD1, + 0x8D5B, 0x5CD3, 0x8D5C, 0x5CD4, 0x8D5D, 0x5CD5, 0x8D5E, 0x5CD6, + 0x8D5F, 0x5CD7, 0x8D60, 0x5CD8, 0x8D61, 0x5CDA, 0x8D62, 0x5CDB, + 0x8D63, 0x5CDC, 0x8D64, 0x5CDD, 0x8D65, 0x5CDE, 0x8D66, 0x5CDF, + 0x8D67, 0x5CE0, 0x8D68, 0x5CE2, 0x8D69, 0x5CE3, 0x8D6A, 0x5CE7, + 0x8D6B, 0x5CE9, 0x8D6C, 0x5CEB, 0x8D6D, 0x5CEC, 0x8D6E, 0x5CEE, + 0x8D6F, 0x5CEF, 0x8D70, 0x5CF1, 0x8D71, 0x5CF2, 0x8D72, 0x5CF3, + 0x8D73, 0x5CF4, 0x8D74, 0x5CF5, 0x8D75, 0x5CF6, 0x8D76, 0x5CF7, + 0x8D77, 0x5CF8, 0x8D78, 0x5CF9, 0x8D79, 0x5CFA, 0x8D7A, 0x5CFC, + 0x8D7B, 0x5CFD, 0x8D7C, 0x5CFE, 0x8D7D, 0x5CFF, 0x8D7E, 0x5D00, + 0x8D80, 0x5D01, 0x8D81, 0x5D04, 0x8D82, 0x5D05, 0x8D83, 0x5D08, + 0x8D84, 0x5D09, 0x8D85, 0x5D0A, 0x8D86, 0x5D0B, 0x8D87, 0x5D0C, + 0x8D88, 0x5D0D, 0x8D89, 0x5D0F, 0x8D8A, 0x5D10, 0x8D8B, 0x5D11, + 0x8D8C, 0x5D12, 0x8D8D, 0x5D13, 0x8D8E, 0x5D15, 0x8D8F, 0x5D17, + 0x8D90, 0x5D18, 0x8D91, 0x5D19, 0x8D92, 0x5D1A, 0x8D93, 0x5D1C, + 0x8D94, 0x5D1D, 0x8D95, 0x5D1F, 0x8D96, 0x5D20, 0x8D97, 0x5D21, + 0x8D98, 0x5D22, 0x8D99, 0x5D23, 0x8D9A, 0x5D25, 0x8D9B, 0x5D28, + 0x8D9C, 0x5D2A, 0x8D9D, 0x5D2B, 0x8D9E, 0x5D2C, 0x8D9F, 0x5D2F, + 0x8DA0, 0x5D30, 0x8DA1, 0x5D31, 0x8DA2, 0x5D32, 0x8DA3, 0x5D33, + 0x8DA4, 0x5D35, 0x8DA5, 0x5D36, 0x8DA6, 0x5D37, 0x8DA7, 0x5D38, + 0x8DA8, 0x5D39, 0x8DA9, 0x5D3A, 0x8DAA, 0x5D3B, 0x8DAB, 0x5D3C, + 0x8DAC, 0x5D3F, 0x8DAD, 0x5D40, 0x8DAE, 0x5D41, 0x8DAF, 0x5D42, + 0x8DB0, 0x5D43, 0x8DB1, 0x5D44, 0x8DB2, 0x5D45, 0x8DB3, 0x5D46, + 0x8DB4, 0x5D48, 0x8DB5, 0x5D49, 0x8DB6, 0x5D4D, 0x8DB7, 0x5D4E, + 0x8DB8, 0x5D4F, 0x8DB9, 0x5D50, 0x8DBA, 0x5D51, 0x8DBB, 0x5D52, + 0x8DBC, 0x5D53, 0x8DBD, 0x5D54, 0x8DBE, 0x5D55, 0x8DBF, 0x5D56, + 0x8DC0, 0x5D57, 0x8DC1, 0x5D59, 0x8DC2, 0x5D5A, 0x8DC3, 0x5D5C, + 0x8DC4, 0x5D5E, 0x8DC5, 0x5D5F, 0x8DC6, 0x5D60, 0x8DC7, 0x5D61, + 0x8DC8, 0x5D62, 0x8DC9, 0x5D63, 0x8DCA, 0x5D64, 0x8DCB, 0x5D65, + 0x8DCC, 0x5D66, 0x8DCD, 0x5D67, 0x8DCE, 0x5D68, 0x8DCF, 0x5D6A, + 0x8DD0, 0x5D6D, 0x8DD1, 0x5D6E, 0x8DD2, 0x5D70, 0x8DD3, 0x5D71, + 0x8DD4, 0x5D72, 0x8DD5, 0x5D73, 0x8DD6, 0x5D75, 0x8DD7, 0x5D76, + 0x8DD8, 0x5D77, 0x8DD9, 0x5D78, 0x8DDA, 0x5D79, 0x8DDB, 0x5D7A, + 0x8DDC, 0x5D7B, 0x8DDD, 0x5D7C, 0x8DDE, 0x5D7D, 0x8DDF, 0x5D7E, + 0x8DE0, 0x5D7F, 0x8DE1, 0x5D80, 0x8DE2, 0x5D81, 0x8DE3, 0x5D83, + 0x8DE4, 0x5D84, 0x8DE5, 0x5D85, 0x8DE6, 0x5D86, 0x8DE7, 0x5D87, + 0x8DE8, 0x5D88, 0x8DE9, 0x5D89, 0x8DEA, 0x5D8A, 0x8DEB, 0x5D8B, + 0x8DEC, 0x5D8C, 0x8DED, 0x5D8D, 0x8DEE, 0x5D8E, 0x8DEF, 0x5D8F, + 0x8DF0, 0x5D90, 0x8DF1, 0x5D91, 0x8DF2, 0x5D92, 0x8DF3, 0x5D93, + 0x8DF4, 0x5D94, 0x8DF5, 0x5D95, 0x8DF6, 0x5D96, 0x8DF7, 0x5D97, + 0x8DF8, 0x5D98, 0x8DF9, 0x5D9A, 0x8DFA, 0x5D9B, 0x8DFB, 0x5D9C, + 0x8DFC, 0x5D9E, 0x8DFD, 0x5D9F, 0x8DFE, 0x5DA0, 0x8E40, 0x5DA1, + 0x8E41, 0x5DA2, 0x8E42, 0x5DA3, 0x8E43, 0x5DA4, 0x8E44, 0x5DA5, + 0x8E45, 0x5DA6, 0x8E46, 0x5DA7, 0x8E47, 0x5DA8, 0x8E48, 0x5DA9, + 0x8E49, 0x5DAA, 0x8E4A, 0x5DAB, 0x8E4B, 0x5DAC, 0x8E4C, 0x5DAD, + 0x8E4D, 0x5DAE, 0x8E4E, 0x5DAF, 0x8E4F, 0x5DB0, 0x8E50, 0x5DB1, + 0x8E51, 0x5DB2, 0x8E52, 0x5DB3, 0x8E53, 0x5DB4, 0x8E54, 0x5DB5, + 0x8E55, 0x5DB6, 0x8E56, 0x5DB8, 0x8E57, 0x5DB9, 0x8E58, 0x5DBA, + 0x8E59, 0x5DBB, 0x8E5A, 0x5DBC, 0x8E5B, 0x5DBD, 0x8E5C, 0x5DBE, + 0x8E5D, 0x5DBF, 0x8E5E, 0x5DC0, 0x8E5F, 0x5DC1, 0x8E60, 0x5DC2, + 0x8E61, 0x5DC3, 0x8E62, 0x5DC4, 0x8E63, 0x5DC6, 0x8E64, 0x5DC7, + 0x8E65, 0x5DC8, 0x8E66, 0x5DC9, 0x8E67, 0x5DCA, 0x8E68, 0x5DCB, + 0x8E69, 0x5DCC, 0x8E6A, 0x5DCE, 0x8E6B, 0x5DCF, 0x8E6C, 0x5DD0, + 0x8E6D, 0x5DD1, 0x8E6E, 0x5DD2, 0x8E6F, 0x5DD3, 0x8E70, 0x5DD4, + 0x8E71, 0x5DD5, 0x8E72, 0x5DD6, 0x8E73, 0x5DD7, 0x8E74, 0x5DD8, + 0x8E75, 0x5DD9, 0x8E76, 0x5DDA, 0x8E77, 0x5DDC, 0x8E78, 0x5DDF, + 0x8E79, 0x5DE0, 0x8E7A, 0x5DE3, 0x8E7B, 0x5DE4, 0x8E7C, 0x5DEA, + 0x8E7D, 0x5DEC, 0x8E7E, 0x5DED, 0x8E80, 0x5DF0, 0x8E81, 0x5DF5, + 0x8E82, 0x5DF6, 0x8E83, 0x5DF8, 0x8E84, 0x5DF9, 0x8E85, 0x5DFA, + 0x8E86, 0x5DFB, 0x8E87, 0x5DFC, 0x8E88, 0x5DFF, 0x8E89, 0x5E00, + 0x8E8A, 0x5E04, 0x8E8B, 0x5E07, 0x8E8C, 0x5E09, 0x8E8D, 0x5E0A, + 0x8E8E, 0x5E0B, 0x8E8F, 0x5E0D, 0x8E90, 0x5E0E, 0x8E91, 0x5E12, + 0x8E92, 0x5E13, 0x8E93, 0x5E17, 0x8E94, 0x5E1E, 0x8E95, 0x5E1F, + 0x8E96, 0x5E20, 0x8E97, 0x5E21, 0x8E98, 0x5E22, 0x8E99, 0x5E23, + 0x8E9A, 0x5E24, 0x8E9B, 0x5E25, 0x8E9C, 0x5E28, 0x8E9D, 0x5E29, + 0x8E9E, 0x5E2A, 0x8E9F, 0x5E2B, 0x8EA0, 0x5E2C, 0x8EA1, 0x5E2F, + 0x8EA2, 0x5E30, 0x8EA3, 0x5E32, 0x8EA4, 0x5E33, 0x8EA5, 0x5E34, + 0x8EA6, 0x5E35, 0x8EA7, 0x5E36, 0x8EA8, 0x5E39, 0x8EA9, 0x5E3A, + 0x8EAA, 0x5E3E, 0x8EAB, 0x5E3F, 0x8EAC, 0x5E40, 0x8EAD, 0x5E41, + 0x8EAE, 0x5E43, 0x8EAF, 0x5E46, 0x8EB0, 0x5E47, 0x8EB1, 0x5E48, + 0x8EB2, 0x5E49, 0x8EB3, 0x5E4A, 0x8EB4, 0x5E4B, 0x8EB5, 0x5E4D, + 0x8EB6, 0x5E4E, 0x8EB7, 0x5E4F, 0x8EB8, 0x5E50, 0x8EB9, 0x5E51, + 0x8EBA, 0x5E52, 0x8EBB, 0x5E53, 0x8EBC, 0x5E56, 0x8EBD, 0x5E57, + 0x8EBE, 0x5E58, 0x8EBF, 0x5E59, 0x8EC0, 0x5E5A, 0x8EC1, 0x5E5C, + 0x8EC2, 0x5E5D, 0x8EC3, 0x5E5F, 0x8EC4, 0x5E60, 0x8EC5, 0x5E63, + 0x8EC6, 0x5E64, 0x8EC7, 0x5E65, 0x8EC8, 0x5E66, 0x8EC9, 0x5E67, + 0x8ECA, 0x5E68, 0x8ECB, 0x5E69, 0x8ECC, 0x5E6A, 0x8ECD, 0x5E6B, + 0x8ECE, 0x5E6C, 0x8ECF, 0x5E6D, 0x8ED0, 0x5E6E, 0x8ED1, 0x5E6F, + 0x8ED2, 0x5E70, 0x8ED3, 0x5E71, 0x8ED4, 0x5E75, 0x8ED5, 0x5E77, + 0x8ED6, 0x5E79, 0x8ED7, 0x5E7E, 0x8ED8, 0x5E81, 0x8ED9, 0x5E82, + 0x8EDA, 0x5E83, 0x8EDB, 0x5E85, 0x8EDC, 0x5E88, 0x8EDD, 0x5E89, + 0x8EDE, 0x5E8C, 0x8EDF, 0x5E8D, 0x8EE0, 0x5E8E, 0x8EE1, 0x5E92, + 0x8EE2, 0x5E98, 0x8EE3, 0x5E9B, 0x8EE4, 0x5E9D, 0x8EE5, 0x5EA1, + 0x8EE6, 0x5EA2, 0x8EE7, 0x5EA3, 0x8EE8, 0x5EA4, 0x8EE9, 0x5EA8, + 0x8EEA, 0x5EA9, 0x8EEB, 0x5EAA, 0x8EEC, 0x5EAB, 0x8EED, 0x5EAC, + 0x8EEE, 0x5EAE, 0x8EEF, 0x5EAF, 0x8EF0, 0x5EB0, 0x8EF1, 0x5EB1, + 0x8EF2, 0x5EB2, 0x8EF3, 0x5EB4, 0x8EF4, 0x5EBA, 0x8EF5, 0x5EBB, + 0x8EF6, 0x5EBC, 0x8EF7, 0x5EBD, 0x8EF8, 0x5EBF, 0x8EF9, 0x5EC0, + 0x8EFA, 0x5EC1, 0x8EFB, 0x5EC2, 0x8EFC, 0x5EC3, 0x8EFD, 0x5EC4, + 0x8EFE, 0x5EC5, 0x8F40, 0x5EC6, 0x8F41, 0x5EC7, 0x8F42, 0x5EC8, + 0x8F43, 0x5ECB, 0x8F44, 0x5ECC, 0x8F45, 0x5ECD, 0x8F46, 0x5ECE, + 0x8F47, 0x5ECF, 0x8F48, 0x5ED0, 0x8F49, 0x5ED4, 0x8F4A, 0x5ED5, + 0x8F4B, 0x5ED7, 0x8F4C, 0x5ED8, 0x8F4D, 0x5ED9, 0x8F4E, 0x5EDA, + 0x8F4F, 0x5EDC, 0x8F50, 0x5EDD, 0x8F51, 0x5EDE, 0x8F52, 0x5EDF, + 0x8F53, 0x5EE0, 0x8F54, 0x5EE1, 0x8F55, 0x5EE2, 0x8F56, 0x5EE3, + 0x8F57, 0x5EE4, 0x8F58, 0x5EE5, 0x8F59, 0x5EE6, 0x8F5A, 0x5EE7, + 0x8F5B, 0x5EE9, 0x8F5C, 0x5EEB, 0x8F5D, 0x5EEC, 0x8F5E, 0x5EED, + 0x8F5F, 0x5EEE, 0x8F60, 0x5EEF, 0x8F61, 0x5EF0, 0x8F62, 0x5EF1, + 0x8F63, 0x5EF2, 0x8F64, 0x5EF3, 0x8F65, 0x5EF5, 0x8F66, 0x5EF8, + 0x8F67, 0x5EF9, 0x8F68, 0x5EFB, 0x8F69, 0x5EFC, 0x8F6A, 0x5EFD, + 0x8F6B, 0x5F05, 0x8F6C, 0x5F06, 0x8F6D, 0x5F07, 0x8F6E, 0x5F09, + 0x8F6F, 0x5F0C, 0x8F70, 0x5F0D, 0x8F71, 0x5F0E, 0x8F72, 0x5F10, + 0x8F73, 0x5F12, 0x8F74, 0x5F14, 0x8F75, 0x5F16, 0x8F76, 0x5F19, + 0x8F77, 0x5F1A, 0x8F78, 0x5F1C, 0x8F79, 0x5F1D, 0x8F7A, 0x5F1E, + 0x8F7B, 0x5F21, 0x8F7C, 0x5F22, 0x8F7D, 0x5F23, 0x8F7E, 0x5F24, + 0x8F80, 0x5F28, 0x8F81, 0x5F2B, 0x8F82, 0x5F2C, 0x8F83, 0x5F2E, + 0x8F84, 0x5F30, 0x8F85, 0x5F32, 0x8F86, 0x5F33, 0x8F87, 0x5F34, + 0x8F88, 0x5F35, 0x8F89, 0x5F36, 0x8F8A, 0x5F37, 0x8F8B, 0x5F38, + 0x8F8C, 0x5F3B, 0x8F8D, 0x5F3D, 0x8F8E, 0x5F3E, 0x8F8F, 0x5F3F, + 0x8F90, 0x5F41, 0x8F91, 0x5F42, 0x8F92, 0x5F43, 0x8F93, 0x5F44, + 0x8F94, 0x5F45, 0x8F95, 0x5F46, 0x8F96, 0x5F47, 0x8F97, 0x5F48, + 0x8F98, 0x5F49, 0x8F99, 0x5F4A, 0x8F9A, 0x5F4B, 0x8F9B, 0x5F4C, + 0x8F9C, 0x5F4D, 0x8F9D, 0x5F4E, 0x8F9E, 0x5F4F, 0x8F9F, 0x5F51, + 0x8FA0, 0x5F54, 0x8FA1, 0x5F59, 0x8FA2, 0x5F5A, 0x8FA3, 0x5F5B, + 0x8FA4, 0x5F5C, 0x8FA5, 0x5F5E, 0x8FA6, 0x5F5F, 0x8FA7, 0x5F60, + 0x8FA8, 0x5F63, 0x8FA9, 0x5F65, 0x8FAA, 0x5F67, 0x8FAB, 0x5F68, + 0x8FAC, 0x5F6B, 0x8FAD, 0x5F6E, 0x8FAE, 0x5F6F, 0x8FAF, 0x5F72, + 0x8FB0, 0x5F74, 0x8FB1, 0x5F75, 0x8FB2, 0x5F76, 0x8FB3, 0x5F78, + 0x8FB4, 0x5F7A, 0x8FB5, 0x5F7D, 0x8FB6, 0x5F7E, 0x8FB7, 0x5F7F, + 0x8FB8, 0x5F83, 0x8FB9, 0x5F86, 0x8FBA, 0x5F8D, 0x8FBB, 0x5F8E, + 0x8FBC, 0x5F8F, 0x8FBD, 0x5F91, 0x8FBE, 0x5F93, 0x8FBF, 0x5F94, + 0x8FC0, 0x5F96, 0x8FC1, 0x5F9A, 0x8FC2, 0x5F9B, 0x8FC3, 0x5F9D, + 0x8FC4, 0x5F9E, 0x8FC5, 0x5F9F, 0x8FC6, 0x5FA0, 0x8FC7, 0x5FA2, + 0x8FC8, 0x5FA3, 0x8FC9, 0x5FA4, 0x8FCA, 0x5FA5, 0x8FCB, 0x5FA6, + 0x8FCC, 0x5FA7, 0x8FCD, 0x5FA9, 0x8FCE, 0x5FAB, 0x8FCF, 0x5FAC, + 0x8FD0, 0x5FAF, 0x8FD1, 0x5FB0, 0x8FD2, 0x5FB1, 0x8FD3, 0x5FB2, + 0x8FD4, 0x5FB3, 0x8FD5, 0x5FB4, 0x8FD6, 0x5FB6, 0x8FD7, 0x5FB8, + 0x8FD8, 0x5FB9, 0x8FD9, 0x5FBA, 0x8FDA, 0x5FBB, 0x8FDB, 0x5FBE, + 0x8FDC, 0x5FBF, 0x8FDD, 0x5FC0, 0x8FDE, 0x5FC1, 0x8FDF, 0x5FC2, + 0x8FE0, 0x5FC7, 0x8FE1, 0x5FC8, 0x8FE2, 0x5FCA, 0x8FE3, 0x5FCB, + 0x8FE4, 0x5FCE, 0x8FE5, 0x5FD3, 0x8FE6, 0x5FD4, 0x8FE7, 0x5FD5, + 0x8FE8, 0x5FDA, 0x8FE9, 0x5FDB, 0x8FEA, 0x5FDC, 0x8FEB, 0x5FDE, + 0x8FEC, 0x5FDF, 0x8FED, 0x5FE2, 0x8FEE, 0x5FE3, 0x8FEF, 0x5FE5, + 0x8FF0, 0x5FE6, 0x8FF1, 0x5FE8, 0x8FF2, 0x5FE9, 0x8FF3, 0x5FEC, + 0x8FF4, 0x5FEF, 0x8FF5, 0x5FF0, 0x8FF6, 0x5FF2, 0x8FF7, 0x5FF3, + 0x8FF8, 0x5FF4, 0x8FF9, 0x5FF6, 0x8FFA, 0x5FF7, 0x8FFB, 0x5FF9, + 0x8FFC, 0x5FFA, 0x8FFD, 0x5FFC, 0x8FFE, 0x6007, 0x9040, 0x6008, + 0x9041, 0x6009, 0x9042, 0x600B, 0x9043, 0x600C, 0x9044, 0x6010, + 0x9045, 0x6011, 0x9046, 0x6013, 0x9047, 0x6017, 0x9048, 0x6018, + 0x9049, 0x601A, 0x904A, 0x601E, 0x904B, 0x601F, 0x904C, 0x6022, + 0x904D, 0x6023, 0x904E, 0x6024, 0x904F, 0x602C, 0x9050, 0x602D, + 0x9051, 0x602E, 0x9052, 0x6030, 0x9053, 0x6031, 0x9054, 0x6032, + 0x9055, 0x6033, 0x9056, 0x6034, 0x9057, 0x6036, 0x9058, 0x6037, + 0x9059, 0x6038, 0x905A, 0x6039, 0x905B, 0x603A, 0x905C, 0x603D, + 0x905D, 0x603E, 0x905E, 0x6040, 0x905F, 0x6044, 0x9060, 0x6045, + 0x9061, 0x6046, 0x9062, 0x6047, 0x9063, 0x6048, 0x9064, 0x6049, + 0x9065, 0x604A, 0x9066, 0x604C, 0x9067, 0x604E, 0x9068, 0x604F, + 0x9069, 0x6051, 0x906A, 0x6053, 0x906B, 0x6054, 0x906C, 0x6056, + 0x906D, 0x6057, 0x906E, 0x6058, 0x906F, 0x605B, 0x9070, 0x605C, + 0x9071, 0x605E, 0x9072, 0x605F, 0x9073, 0x6060, 0x9074, 0x6061, + 0x9075, 0x6065, 0x9076, 0x6066, 0x9077, 0x606E, 0x9078, 0x6071, + 0x9079, 0x6072, 0x907A, 0x6074, 0x907B, 0x6075, 0x907C, 0x6077, + 0x907D, 0x607E, 0x907E, 0x6080, 0x9080, 0x6081, 0x9081, 0x6082, + 0x9082, 0x6085, 0x9083, 0x6086, 0x9084, 0x6087, 0x9085, 0x6088, + 0x9086, 0x608A, 0x9087, 0x608B, 0x9088, 0x608E, 0x9089, 0x608F, + 0x908A, 0x6090, 0x908B, 0x6091, 0x908C, 0x6093, 0x908D, 0x6095, + 0x908E, 0x6097, 0x908F, 0x6098, 0x9090, 0x6099, 0x9091, 0x609C, + 0x9092, 0x609E, 0x9093, 0x60A1, 0x9094, 0x60A2, 0x9095, 0x60A4, + 0x9096, 0x60A5, 0x9097, 0x60A7, 0x9098, 0x60A9, 0x9099, 0x60AA, + 0x909A, 0x60AE, 0x909B, 0x60B0, 0x909C, 0x60B3, 0x909D, 0x60B5, + 0x909E, 0x60B6, 0x909F, 0x60B7, 0x90A0, 0x60B9, 0x90A1, 0x60BA, + 0x90A2, 0x60BD, 0x90A3, 0x60BE, 0x90A4, 0x60BF, 0x90A5, 0x60C0, + 0x90A6, 0x60C1, 0x90A7, 0x60C2, 0x90A8, 0x60C3, 0x90A9, 0x60C4, + 0x90AA, 0x60C7, 0x90AB, 0x60C8, 0x90AC, 0x60C9, 0x90AD, 0x60CC, + 0x90AE, 0x60CD, 0x90AF, 0x60CE, 0x90B0, 0x60CF, 0x90B1, 0x60D0, + 0x90B2, 0x60D2, 0x90B3, 0x60D3, 0x90B4, 0x60D4, 0x90B5, 0x60D6, + 0x90B6, 0x60D7, 0x90B7, 0x60D9, 0x90B8, 0x60DB, 0x90B9, 0x60DE, + 0x90BA, 0x60E1, 0x90BB, 0x60E2, 0x90BC, 0x60E3, 0x90BD, 0x60E4, + 0x90BE, 0x60E5, 0x90BF, 0x60EA, 0x90C0, 0x60F1, 0x90C1, 0x60F2, + 0x90C2, 0x60F5, 0x90C3, 0x60F7, 0x90C4, 0x60F8, 0x90C5, 0x60FB, + 0x90C6, 0x60FC, 0x90C7, 0x60FD, 0x90C8, 0x60FE, 0x90C9, 0x60FF, + 0x90CA, 0x6102, 0x90CB, 0x6103, 0x90CC, 0x6104, 0x90CD, 0x6105, + 0x90CE, 0x6107, 0x90CF, 0x610A, 0x90D0, 0x610B, 0x90D1, 0x610C, + 0x90D2, 0x6110, 0x90D3, 0x6111, 0x90D4, 0x6112, 0x90D5, 0x6113, + 0x90D6, 0x6114, 0x90D7, 0x6116, 0x90D8, 0x6117, 0x90D9, 0x6118, + 0x90DA, 0x6119, 0x90DB, 0x611B, 0x90DC, 0x611C, 0x90DD, 0x611D, + 0x90DE, 0x611E, 0x90DF, 0x6121, 0x90E0, 0x6122, 0x90E1, 0x6125, + 0x90E2, 0x6128, 0x90E3, 0x6129, 0x90E4, 0x612A, 0x90E5, 0x612C, + 0x90E6, 0x612D, 0x90E7, 0x612E, 0x90E8, 0x612F, 0x90E9, 0x6130, + 0x90EA, 0x6131, 0x90EB, 0x6132, 0x90EC, 0x6133, 0x90ED, 0x6134, + 0x90EE, 0x6135, 0x90EF, 0x6136, 0x90F0, 0x6137, 0x90F1, 0x6138, + 0x90F2, 0x6139, 0x90F3, 0x613A, 0x90F4, 0x613B, 0x90F5, 0x613C, + 0x90F6, 0x613D, 0x90F7, 0x613E, 0x90F8, 0x6140, 0x90F9, 0x6141, + 0x90FA, 0x6142, 0x90FB, 0x6143, 0x90FC, 0x6144, 0x90FD, 0x6145, + 0x90FE, 0x6146, 0x9140, 0x6147, 0x9141, 0x6149, 0x9142, 0x614B, + 0x9143, 0x614D, 0x9144, 0x614F, 0x9145, 0x6150, 0x9146, 0x6152, + 0x9147, 0x6153, 0x9148, 0x6154, 0x9149, 0x6156, 0x914A, 0x6157, + 0x914B, 0x6158, 0x914C, 0x6159, 0x914D, 0x615A, 0x914E, 0x615B, + 0x914F, 0x615C, 0x9150, 0x615E, 0x9151, 0x615F, 0x9152, 0x6160, + 0x9153, 0x6161, 0x9154, 0x6163, 0x9155, 0x6164, 0x9156, 0x6165, + 0x9157, 0x6166, 0x9158, 0x6169, 0x9159, 0x616A, 0x915A, 0x616B, + 0x915B, 0x616C, 0x915C, 0x616D, 0x915D, 0x616E, 0x915E, 0x616F, + 0x915F, 0x6171, 0x9160, 0x6172, 0x9161, 0x6173, 0x9162, 0x6174, + 0x9163, 0x6176, 0x9164, 0x6178, 0x9165, 0x6179, 0x9166, 0x617A, + 0x9167, 0x617B, 0x9168, 0x617C, 0x9169, 0x617D, 0x916A, 0x617E, + 0x916B, 0x617F, 0x916C, 0x6180, 0x916D, 0x6181, 0x916E, 0x6182, + 0x916F, 0x6183, 0x9170, 0x6184, 0x9171, 0x6185, 0x9172, 0x6186, + 0x9173, 0x6187, 0x9174, 0x6188, 0x9175, 0x6189, 0x9176, 0x618A, + 0x9177, 0x618C, 0x9178, 0x618D, 0x9179, 0x618F, 0x917A, 0x6190, + 0x917B, 0x6191, 0x917C, 0x6192, 0x917D, 0x6193, 0x917E, 0x6195, + 0x9180, 0x6196, 0x9181, 0x6197, 0x9182, 0x6198, 0x9183, 0x6199, + 0x9184, 0x619A, 0x9185, 0x619B, 0x9186, 0x619C, 0x9187, 0x619E, + 0x9188, 0x619F, 0x9189, 0x61A0, 0x918A, 0x61A1, 0x918B, 0x61A2, + 0x918C, 0x61A3, 0x918D, 0x61A4, 0x918E, 0x61A5, 0x918F, 0x61A6, + 0x9190, 0x61AA, 0x9191, 0x61AB, 0x9192, 0x61AD, 0x9193, 0x61AE, + 0x9194, 0x61AF, 0x9195, 0x61B0, 0x9196, 0x61B1, 0x9197, 0x61B2, + 0x9198, 0x61B3, 0x9199, 0x61B4, 0x919A, 0x61B5, 0x919B, 0x61B6, + 0x919C, 0x61B8, 0x919D, 0x61B9, 0x919E, 0x61BA, 0x919F, 0x61BB, + 0x91A0, 0x61BC, 0x91A1, 0x61BD, 0x91A2, 0x61BF, 0x91A3, 0x61C0, + 0x91A4, 0x61C1, 0x91A5, 0x61C3, 0x91A6, 0x61C4, 0x91A7, 0x61C5, + 0x91A8, 0x61C6, 0x91A9, 0x61C7, 0x91AA, 0x61C9, 0x91AB, 0x61CC, + 0x91AC, 0x61CD, 0x91AD, 0x61CE, 0x91AE, 0x61CF, 0x91AF, 0x61D0, + 0x91B0, 0x61D3, 0x91B1, 0x61D5, 0x91B2, 0x61D6, 0x91B3, 0x61D7, + 0x91B4, 0x61D8, 0x91B5, 0x61D9, 0x91B6, 0x61DA, 0x91B7, 0x61DB, + 0x91B8, 0x61DC, 0x91B9, 0x61DD, 0x91BA, 0x61DE, 0x91BB, 0x61DF, + 0x91BC, 0x61E0, 0x91BD, 0x61E1, 0x91BE, 0x61E2, 0x91BF, 0x61E3, + 0x91C0, 0x61E4, 0x91C1, 0x61E5, 0x91C2, 0x61E7, 0x91C3, 0x61E8, + 0x91C4, 0x61E9, 0x91C5, 0x61EA, 0x91C6, 0x61EB, 0x91C7, 0x61EC, + 0x91C8, 0x61ED, 0x91C9, 0x61EE, 0x91CA, 0x61EF, 0x91CB, 0x61F0, + 0x91CC, 0x61F1, 0x91CD, 0x61F2, 0x91CE, 0x61F3, 0x91CF, 0x61F4, + 0x91D0, 0x61F6, 0x91D1, 0x61F7, 0x91D2, 0x61F8, 0x91D3, 0x61F9, + 0x91D4, 0x61FA, 0x91D5, 0x61FB, 0x91D6, 0x61FC, 0x91D7, 0x61FD, + 0x91D8, 0x61FE, 0x91D9, 0x6200, 0x91DA, 0x6201, 0x91DB, 0x6202, + 0x91DC, 0x6203, 0x91DD, 0x6204, 0x91DE, 0x6205, 0x91DF, 0x6207, + 0x91E0, 0x6209, 0x91E1, 0x6213, 0x91E2, 0x6214, 0x91E3, 0x6219, + 0x91E4, 0x621C, 0x91E5, 0x621D, 0x91E6, 0x621E, 0x91E7, 0x6220, + 0x91E8, 0x6223, 0x91E9, 0x6226, 0x91EA, 0x6227, 0x91EB, 0x6228, + 0x91EC, 0x6229, 0x91ED, 0x622B, 0x91EE, 0x622D, 0x91EF, 0x622F, + 0x91F0, 0x6230, 0x91F1, 0x6231, 0x91F2, 0x6232, 0x91F3, 0x6235, + 0x91F4, 0x6236, 0x91F5, 0x6238, 0x91F6, 0x6239, 0x91F7, 0x623A, + 0x91F8, 0x623B, 0x91F9, 0x623C, 0x91FA, 0x6242, 0x91FB, 0x6244, + 0x91FC, 0x6245, 0x91FD, 0x6246, 0x91FE, 0x624A, 0x9240, 0x624F, + 0x9241, 0x6250, 0x9242, 0x6255, 0x9243, 0x6256, 0x9244, 0x6257, + 0x9245, 0x6259, 0x9246, 0x625A, 0x9247, 0x625C, 0x9248, 0x625D, + 0x9249, 0x625E, 0x924A, 0x625F, 0x924B, 0x6260, 0x924C, 0x6261, + 0x924D, 0x6262, 0x924E, 0x6264, 0x924F, 0x6265, 0x9250, 0x6268, + 0x9251, 0x6271, 0x9252, 0x6272, 0x9253, 0x6274, 0x9254, 0x6275, + 0x9255, 0x6277, 0x9256, 0x6278, 0x9257, 0x627A, 0x9258, 0x627B, + 0x9259, 0x627D, 0x925A, 0x6281, 0x925B, 0x6282, 0x925C, 0x6283, + 0x925D, 0x6285, 0x925E, 0x6286, 0x925F, 0x6287, 0x9260, 0x6288, + 0x9261, 0x628B, 0x9262, 0x628C, 0x9263, 0x628D, 0x9264, 0x628E, + 0x9265, 0x628F, 0x9266, 0x6290, 0x9267, 0x6294, 0x9268, 0x6299, + 0x9269, 0x629C, 0x926A, 0x629D, 0x926B, 0x629E, 0x926C, 0x62A3, + 0x926D, 0x62A6, 0x926E, 0x62A7, 0x926F, 0x62A9, 0x9270, 0x62AA, + 0x9271, 0x62AD, 0x9272, 0x62AE, 0x9273, 0x62AF, 0x9274, 0x62B0, + 0x9275, 0x62B2, 0x9276, 0x62B3, 0x9277, 0x62B4, 0x9278, 0x62B6, + 0x9279, 0x62B7, 0x927A, 0x62B8, 0x927B, 0x62BA, 0x927C, 0x62BE, + 0x927D, 0x62C0, 0x927E, 0x62C1, 0x9280, 0x62C3, 0x9281, 0x62CB, + 0x9282, 0x62CF, 0x9283, 0x62D1, 0x9284, 0x62D5, 0x9285, 0x62DD, + 0x9286, 0x62DE, 0x9287, 0x62E0, 0x9288, 0x62E1, 0x9289, 0x62E4, + 0x928A, 0x62EA, 0x928B, 0x62EB, 0x928C, 0x62F0, 0x928D, 0x62F2, + 0x928E, 0x62F5, 0x928F, 0x62F8, 0x9290, 0x62F9, 0x9291, 0x62FA, + 0x9292, 0x62FB, 0x9293, 0x6300, 0x9294, 0x6303, 0x9295, 0x6304, + 0x9296, 0x6305, 0x9297, 0x6306, 0x9298, 0x630A, 0x9299, 0x630B, + 0x929A, 0x630C, 0x929B, 0x630D, 0x929C, 0x630F, 0x929D, 0x6310, + 0x929E, 0x6312, 0x929F, 0x6313, 0x92A0, 0x6314, 0x92A1, 0x6315, + 0x92A2, 0x6317, 0x92A3, 0x6318, 0x92A4, 0x6319, 0x92A5, 0x631C, + 0x92A6, 0x6326, 0x92A7, 0x6327, 0x92A8, 0x6329, 0x92A9, 0x632C, + 0x92AA, 0x632D, 0x92AB, 0x632E, 0x92AC, 0x6330, 0x92AD, 0x6331, + 0x92AE, 0x6333, 0x92AF, 0x6334, 0x92B0, 0x6335, 0x92B1, 0x6336, + 0x92B2, 0x6337, 0x92B3, 0x6338, 0x92B4, 0x633B, 0x92B5, 0x633C, + 0x92B6, 0x633E, 0x92B7, 0x633F, 0x92B8, 0x6340, 0x92B9, 0x6341, + 0x92BA, 0x6344, 0x92BB, 0x6347, 0x92BC, 0x6348, 0x92BD, 0x634A, + 0x92BE, 0x6351, 0x92BF, 0x6352, 0x92C0, 0x6353, 0x92C1, 0x6354, + 0x92C2, 0x6356, 0x92C3, 0x6357, 0x92C4, 0x6358, 0x92C5, 0x6359, + 0x92C6, 0x635A, 0x92C7, 0x635B, 0x92C8, 0x635C, 0x92C9, 0x635D, + 0x92CA, 0x6360, 0x92CB, 0x6364, 0x92CC, 0x6365, 0x92CD, 0x6366, + 0x92CE, 0x6368, 0x92CF, 0x636A, 0x92D0, 0x636B, 0x92D1, 0x636C, + 0x92D2, 0x636F, 0x92D3, 0x6370, 0x92D4, 0x6372, 0x92D5, 0x6373, + 0x92D6, 0x6374, 0x92D7, 0x6375, 0x92D8, 0x6378, 0x92D9, 0x6379, + 0x92DA, 0x637C, 0x92DB, 0x637D, 0x92DC, 0x637E, 0x92DD, 0x637F, + 0x92DE, 0x6381, 0x92DF, 0x6383, 0x92E0, 0x6384, 0x92E1, 0x6385, + 0x92E2, 0x6386, 0x92E3, 0x638B, 0x92E4, 0x638D, 0x92E5, 0x6391, + 0x92E6, 0x6393, 0x92E7, 0x6394, 0x92E8, 0x6395, 0x92E9, 0x6397, + 0x92EA, 0x6399, 0x92EB, 0x639A, 0x92EC, 0x639B, 0x92ED, 0x639C, + 0x92EE, 0x639D, 0x92EF, 0x639E, 0x92F0, 0x639F, 0x92F1, 0x63A1, + 0x92F2, 0x63A4, 0x92F3, 0x63A6, 0x92F4, 0x63AB, 0x92F5, 0x63AF, + 0x92F6, 0x63B1, 0x92F7, 0x63B2, 0x92F8, 0x63B5, 0x92F9, 0x63B6, + 0x92FA, 0x63B9, 0x92FB, 0x63BB, 0x92FC, 0x63BD, 0x92FD, 0x63BF, + 0x92FE, 0x63C0, 0x9340, 0x63C1, 0x9341, 0x63C2, 0x9342, 0x63C3, + 0x9343, 0x63C5, 0x9344, 0x63C7, 0x9345, 0x63C8, 0x9346, 0x63CA, + 0x9347, 0x63CB, 0x9348, 0x63CC, 0x9349, 0x63D1, 0x934A, 0x63D3, + 0x934B, 0x63D4, 0x934C, 0x63D5, 0x934D, 0x63D7, 0x934E, 0x63D8, + 0x934F, 0x63D9, 0x9350, 0x63DA, 0x9351, 0x63DB, 0x9352, 0x63DC, + 0x9353, 0x63DD, 0x9354, 0x63DF, 0x9355, 0x63E2, 0x9356, 0x63E4, + 0x9357, 0x63E5, 0x9358, 0x63E6, 0x9359, 0x63E7, 0x935A, 0x63E8, + 0x935B, 0x63EB, 0x935C, 0x63EC, 0x935D, 0x63EE, 0x935E, 0x63EF, + 0x935F, 0x63F0, 0x9360, 0x63F1, 0x9361, 0x63F3, 0x9362, 0x63F5, + 0x9363, 0x63F7, 0x9364, 0x63F9, 0x9365, 0x63FA, 0x9366, 0x63FB, + 0x9367, 0x63FC, 0x9368, 0x63FE, 0x9369, 0x6403, 0x936A, 0x6404, + 0x936B, 0x6406, 0x936C, 0x6407, 0x936D, 0x6408, 0x936E, 0x6409, + 0x936F, 0x640A, 0x9370, 0x640D, 0x9371, 0x640E, 0x9372, 0x6411, + 0x9373, 0x6412, 0x9374, 0x6415, 0x9375, 0x6416, 0x9376, 0x6417, + 0x9377, 0x6418, 0x9378, 0x6419, 0x9379, 0x641A, 0x937A, 0x641D, + 0x937B, 0x641F, 0x937C, 0x6422, 0x937D, 0x6423, 0x937E, 0x6424, + 0x9380, 0x6425, 0x9381, 0x6427, 0x9382, 0x6428, 0x9383, 0x6429, + 0x9384, 0x642B, 0x9385, 0x642E, 0x9386, 0x642F, 0x9387, 0x6430, + 0x9388, 0x6431, 0x9389, 0x6432, 0x938A, 0x6433, 0x938B, 0x6435, + 0x938C, 0x6436, 0x938D, 0x6437, 0x938E, 0x6438, 0x938F, 0x6439, + 0x9390, 0x643B, 0x9391, 0x643C, 0x9392, 0x643E, 0x9393, 0x6440, + 0x9394, 0x6442, 0x9395, 0x6443, 0x9396, 0x6449, 0x9397, 0x644B, + 0x9398, 0x644C, 0x9399, 0x644D, 0x939A, 0x644E, 0x939B, 0x644F, + 0x939C, 0x6450, 0x939D, 0x6451, 0x939E, 0x6453, 0x939F, 0x6455, + 0x93A0, 0x6456, 0x93A1, 0x6457, 0x93A2, 0x6459, 0x93A3, 0x645A, + 0x93A4, 0x645B, 0x93A5, 0x645C, 0x93A6, 0x645D, 0x93A7, 0x645F, + 0x93A8, 0x6460, 0x93A9, 0x6461, 0x93AA, 0x6462, 0x93AB, 0x6463, + 0x93AC, 0x6464, 0x93AD, 0x6465, 0x93AE, 0x6466, 0x93AF, 0x6468, + 0x93B0, 0x646A, 0x93B1, 0x646B, 0x93B2, 0x646C, 0x93B3, 0x646E, + 0x93B4, 0x646F, 0x93B5, 0x6470, 0x93B6, 0x6471, 0x93B7, 0x6472, + 0x93B8, 0x6473, 0x93B9, 0x6474, 0x93BA, 0x6475, 0x93BB, 0x6476, + 0x93BC, 0x6477, 0x93BD, 0x647B, 0x93BE, 0x647C, 0x93BF, 0x647D, + 0x93C0, 0x647E, 0x93C1, 0x647F, 0x93C2, 0x6480, 0x93C3, 0x6481, + 0x93C4, 0x6483, 0x93C5, 0x6486, 0x93C6, 0x6488, 0x93C7, 0x6489, + 0x93C8, 0x648A, 0x93C9, 0x648B, 0x93CA, 0x648C, 0x93CB, 0x648D, + 0x93CC, 0x648E, 0x93CD, 0x648F, 0x93CE, 0x6490, 0x93CF, 0x6493, + 0x93D0, 0x6494, 0x93D1, 0x6497, 0x93D2, 0x6498, 0x93D3, 0x649A, + 0x93D4, 0x649B, 0x93D5, 0x649C, 0x93D6, 0x649D, 0x93D7, 0x649F, + 0x93D8, 0x64A0, 0x93D9, 0x64A1, 0x93DA, 0x64A2, 0x93DB, 0x64A3, + 0x93DC, 0x64A5, 0x93DD, 0x64A6, 0x93DE, 0x64A7, 0x93DF, 0x64A8, + 0x93E0, 0x64AA, 0x93E1, 0x64AB, 0x93E2, 0x64AF, 0x93E3, 0x64B1, + 0x93E4, 0x64B2, 0x93E5, 0x64B3, 0x93E6, 0x64B4, 0x93E7, 0x64B6, + 0x93E8, 0x64B9, 0x93E9, 0x64BB, 0x93EA, 0x64BD, 0x93EB, 0x64BE, + 0x93EC, 0x64BF, 0x93ED, 0x64C1, 0x93EE, 0x64C3, 0x93EF, 0x64C4, + 0x93F0, 0x64C6, 0x93F1, 0x64C7, 0x93F2, 0x64C8, 0x93F3, 0x64C9, + 0x93F4, 0x64CA, 0x93F5, 0x64CB, 0x93F6, 0x64CC, 0x93F7, 0x64CF, + 0x93F8, 0x64D1, 0x93F9, 0x64D3, 0x93FA, 0x64D4, 0x93FB, 0x64D5, + 0x93FC, 0x64D6, 0x93FD, 0x64D9, 0x93FE, 0x64DA, 0x9440, 0x64DB, + 0x9441, 0x64DC, 0x9442, 0x64DD, 0x9443, 0x64DF, 0x9444, 0x64E0, + 0x9445, 0x64E1, 0x9446, 0x64E3, 0x9447, 0x64E5, 0x9448, 0x64E7, + 0x9449, 0x64E8, 0x944A, 0x64E9, 0x944B, 0x64EA, 0x944C, 0x64EB, + 0x944D, 0x64EC, 0x944E, 0x64ED, 0x944F, 0x64EE, 0x9450, 0x64EF, + 0x9451, 0x64F0, 0x9452, 0x64F1, 0x9453, 0x64F2, 0x9454, 0x64F3, + 0x9455, 0x64F4, 0x9456, 0x64F5, 0x9457, 0x64F6, 0x9458, 0x64F7, + 0x9459, 0x64F8, 0x945A, 0x64F9, 0x945B, 0x64FA, 0x945C, 0x64FB, + 0x945D, 0x64FC, 0x945E, 0x64FD, 0x945F, 0x64FE, 0x9460, 0x64FF, + 0x9461, 0x6501, 0x9462, 0x6502, 0x9463, 0x6503, 0x9464, 0x6504, + 0x9465, 0x6505, 0x9466, 0x6506, 0x9467, 0x6507, 0x9468, 0x6508, + 0x9469, 0x650A, 0x946A, 0x650B, 0x946B, 0x650C, 0x946C, 0x650D, + 0x946D, 0x650E, 0x946E, 0x650F, 0x946F, 0x6510, 0x9470, 0x6511, + 0x9471, 0x6513, 0x9472, 0x6514, 0x9473, 0x6515, 0x9474, 0x6516, + 0x9475, 0x6517, 0x9476, 0x6519, 0x9477, 0x651A, 0x9478, 0x651B, + 0x9479, 0x651C, 0x947A, 0x651D, 0x947B, 0x651E, 0x947C, 0x651F, + 0x947D, 0x6520, 0x947E, 0x6521, 0x9480, 0x6522, 0x9481, 0x6523, + 0x9482, 0x6524, 0x9483, 0x6526, 0x9484, 0x6527, 0x9485, 0x6528, + 0x9486, 0x6529, 0x9487, 0x652A, 0x9488, 0x652C, 0x9489, 0x652D, + 0x948A, 0x6530, 0x948B, 0x6531, 0x948C, 0x6532, 0x948D, 0x6533, + 0x948E, 0x6537, 0x948F, 0x653A, 0x9490, 0x653C, 0x9491, 0x653D, + 0x9492, 0x6540, 0x9493, 0x6541, 0x9494, 0x6542, 0x9495, 0x6543, + 0x9496, 0x6544, 0x9497, 0x6546, 0x9498, 0x6547, 0x9499, 0x654A, + 0x949A, 0x654B, 0x949B, 0x654D, 0x949C, 0x654E, 0x949D, 0x6550, + 0x949E, 0x6552, 0x949F, 0x6553, 0x94A0, 0x6554, 0x94A1, 0x6557, + 0x94A2, 0x6558, 0x94A3, 0x655A, 0x94A4, 0x655C, 0x94A5, 0x655F, + 0x94A6, 0x6560, 0x94A7, 0x6561, 0x94A8, 0x6564, 0x94A9, 0x6565, + 0x94AA, 0x6567, 0x94AB, 0x6568, 0x94AC, 0x6569, 0x94AD, 0x656A, + 0x94AE, 0x656D, 0x94AF, 0x656E, 0x94B0, 0x656F, 0x94B1, 0x6571, + 0x94B2, 0x6573, 0x94B3, 0x6575, 0x94B4, 0x6576, 0x94B5, 0x6578, + 0x94B6, 0x6579, 0x94B7, 0x657A, 0x94B8, 0x657B, 0x94B9, 0x657C, + 0x94BA, 0x657D, 0x94BB, 0x657E, 0x94BC, 0x657F, 0x94BD, 0x6580, + 0x94BE, 0x6581, 0x94BF, 0x6582, 0x94C0, 0x6583, 0x94C1, 0x6584, + 0x94C2, 0x6585, 0x94C3, 0x6586, 0x94C4, 0x6588, 0x94C5, 0x6589, + 0x94C6, 0x658A, 0x94C7, 0x658D, 0x94C8, 0x658E, 0x94C9, 0x658F, + 0x94CA, 0x6592, 0x94CB, 0x6594, 0x94CC, 0x6595, 0x94CD, 0x6596, + 0x94CE, 0x6598, 0x94CF, 0x659A, 0x94D0, 0x659D, 0x94D1, 0x659E, + 0x94D2, 0x65A0, 0x94D3, 0x65A2, 0x94D4, 0x65A3, 0x94D5, 0x65A6, + 0x94D6, 0x65A8, 0x94D7, 0x65AA, 0x94D8, 0x65AC, 0x94D9, 0x65AE, + 0x94DA, 0x65B1, 0x94DB, 0x65B2, 0x94DC, 0x65B3, 0x94DD, 0x65B4, + 0x94DE, 0x65B5, 0x94DF, 0x65B6, 0x94E0, 0x65B7, 0x94E1, 0x65B8, + 0x94E2, 0x65BA, 0x94E3, 0x65BB, 0x94E4, 0x65BE, 0x94E5, 0x65BF, + 0x94E6, 0x65C0, 0x94E7, 0x65C2, 0x94E8, 0x65C7, 0x94E9, 0x65C8, + 0x94EA, 0x65C9, 0x94EB, 0x65CA, 0x94EC, 0x65CD, 0x94ED, 0x65D0, + 0x94EE, 0x65D1, 0x94EF, 0x65D3, 0x94F0, 0x65D4, 0x94F1, 0x65D5, + 0x94F2, 0x65D8, 0x94F3, 0x65D9, 0x94F4, 0x65DA, 0x94F5, 0x65DB, + 0x94F6, 0x65DC, 0x94F7, 0x65DD, 0x94F8, 0x65DE, 0x94F9, 0x65DF, + 0x94FA, 0x65E1, 0x94FB, 0x65E3, 0x94FC, 0x65E4, 0x94FD, 0x65EA, + 0x94FE, 0x65EB, 0x9540, 0x65F2, 0x9541, 0x65F3, 0x9542, 0x65F4, + 0x9543, 0x65F5, 0x9544, 0x65F8, 0x9545, 0x65F9, 0x9546, 0x65FB, + 0x9547, 0x65FC, 0x9548, 0x65FD, 0x9549, 0x65FE, 0x954A, 0x65FF, + 0x954B, 0x6601, 0x954C, 0x6604, 0x954D, 0x6605, 0x954E, 0x6607, + 0x954F, 0x6608, 0x9550, 0x6609, 0x9551, 0x660B, 0x9552, 0x660D, + 0x9553, 0x6610, 0x9554, 0x6611, 0x9555, 0x6612, 0x9556, 0x6616, + 0x9557, 0x6617, 0x9558, 0x6618, 0x9559, 0x661A, 0x955A, 0x661B, + 0x955B, 0x661C, 0x955C, 0x661E, 0x955D, 0x6621, 0x955E, 0x6622, + 0x955F, 0x6623, 0x9560, 0x6624, 0x9561, 0x6626, 0x9562, 0x6629, + 0x9563, 0x662A, 0x9564, 0x662B, 0x9565, 0x662C, 0x9566, 0x662E, + 0x9567, 0x6630, 0x9568, 0x6632, 0x9569, 0x6633, 0x956A, 0x6637, + 0x956B, 0x6638, 0x956C, 0x6639, 0x956D, 0x663A, 0x956E, 0x663B, + 0x956F, 0x663D, 0x9570, 0x663F, 0x9571, 0x6640, 0x9572, 0x6642, + 0x9573, 0x6644, 0x9574, 0x6645, 0x9575, 0x6646, 0x9576, 0x6647, + 0x9577, 0x6648, 0x9578, 0x6649, 0x9579, 0x664A, 0x957A, 0x664D, + 0x957B, 0x664E, 0x957C, 0x6650, 0x957D, 0x6651, 0x957E, 0x6658, + 0x9580, 0x6659, 0x9581, 0x665B, 0x9582, 0x665C, 0x9583, 0x665D, + 0x9584, 0x665E, 0x9585, 0x6660, 0x9586, 0x6662, 0x9587, 0x6663, + 0x9588, 0x6665, 0x9589, 0x6667, 0x958A, 0x6669, 0x958B, 0x666A, + 0x958C, 0x666B, 0x958D, 0x666C, 0x958E, 0x666D, 0x958F, 0x6671, + 0x9590, 0x6672, 0x9591, 0x6673, 0x9592, 0x6675, 0x9593, 0x6678, + 0x9594, 0x6679, 0x9595, 0x667B, 0x9596, 0x667C, 0x9597, 0x667D, + 0x9598, 0x667F, 0x9599, 0x6680, 0x959A, 0x6681, 0x959B, 0x6683, + 0x959C, 0x6685, 0x959D, 0x6686, 0x959E, 0x6688, 0x959F, 0x6689, + 0x95A0, 0x668A, 0x95A1, 0x668B, 0x95A2, 0x668D, 0x95A3, 0x668E, + 0x95A4, 0x668F, 0x95A5, 0x6690, 0x95A6, 0x6692, 0x95A7, 0x6693, + 0x95A8, 0x6694, 0x95A9, 0x6695, 0x95AA, 0x6698, 0x95AB, 0x6699, + 0x95AC, 0x669A, 0x95AD, 0x669B, 0x95AE, 0x669C, 0x95AF, 0x669E, + 0x95B0, 0x669F, 0x95B1, 0x66A0, 0x95B2, 0x66A1, 0x95B3, 0x66A2, + 0x95B4, 0x66A3, 0x95B5, 0x66A4, 0x95B6, 0x66A5, 0x95B7, 0x66A6, + 0x95B8, 0x66A9, 0x95B9, 0x66AA, 0x95BA, 0x66AB, 0x95BB, 0x66AC, + 0x95BC, 0x66AD, 0x95BD, 0x66AF, 0x95BE, 0x66B0, 0x95BF, 0x66B1, + 0x95C0, 0x66B2, 0x95C1, 0x66B3, 0x95C2, 0x66B5, 0x95C3, 0x66B6, + 0x95C4, 0x66B7, 0x95C5, 0x66B8, 0x95C6, 0x66BA, 0x95C7, 0x66BB, + 0x95C8, 0x66BC, 0x95C9, 0x66BD, 0x95CA, 0x66BF, 0x95CB, 0x66C0, + 0x95CC, 0x66C1, 0x95CD, 0x66C2, 0x95CE, 0x66C3, 0x95CF, 0x66C4, + 0x95D0, 0x66C5, 0x95D1, 0x66C6, 0x95D2, 0x66C7, 0x95D3, 0x66C8, + 0x95D4, 0x66C9, 0x95D5, 0x66CA, 0x95D6, 0x66CB, 0x95D7, 0x66CC, + 0x95D8, 0x66CD, 0x95D9, 0x66CE, 0x95DA, 0x66CF, 0x95DB, 0x66D0, + 0x95DC, 0x66D1, 0x95DD, 0x66D2, 0x95DE, 0x66D3, 0x95DF, 0x66D4, + 0x95E0, 0x66D5, 0x95E1, 0x66D6, 0x95E2, 0x66D7, 0x95E3, 0x66D8, + 0x95E4, 0x66DA, 0x95E5, 0x66DE, 0x95E6, 0x66DF, 0x95E7, 0x66E0, + 0x95E8, 0x66E1, 0x95E9, 0x66E2, 0x95EA, 0x66E3, 0x95EB, 0x66E4, + 0x95EC, 0x66E5, 0x95ED, 0x66E7, 0x95EE, 0x66E8, 0x95EF, 0x66EA, + 0x95F0, 0x66EB, 0x95F1, 0x66EC, 0x95F2, 0x66ED, 0x95F3, 0x66EE, + 0x95F4, 0x66EF, 0x95F5, 0x66F1, 0x95F6, 0x66F5, 0x95F7, 0x66F6, + 0x95F8, 0x66F8, 0x95F9, 0x66FA, 0x95FA, 0x66FB, 0x95FB, 0x66FD, + 0x95FC, 0x6701, 0x95FD, 0x6702, 0x95FE, 0x6703, 0x9640, 0x6704, + 0x9641, 0x6705, 0x9642, 0x6706, 0x9643, 0x6707, 0x9644, 0x670C, + 0x9645, 0x670E, 0x9646, 0x670F, 0x9647, 0x6711, 0x9648, 0x6712, + 0x9649, 0x6713, 0x964A, 0x6716, 0x964B, 0x6718, 0x964C, 0x6719, + 0x964D, 0x671A, 0x964E, 0x671C, 0x964F, 0x671E, 0x9650, 0x6720, + 0x9651, 0x6721, 0x9652, 0x6722, 0x9653, 0x6723, 0x9654, 0x6724, + 0x9655, 0x6725, 0x9656, 0x6727, 0x9657, 0x6729, 0x9658, 0x672E, + 0x9659, 0x6730, 0x965A, 0x6732, 0x965B, 0x6733, 0x965C, 0x6736, + 0x965D, 0x6737, 0x965E, 0x6738, 0x965F, 0x6739, 0x9660, 0x673B, + 0x9661, 0x673C, 0x9662, 0x673E, 0x9663, 0x673F, 0x9664, 0x6741, + 0x9665, 0x6744, 0x9666, 0x6745, 0x9667, 0x6747, 0x9668, 0x674A, + 0x9669, 0x674B, 0x966A, 0x674D, 0x966B, 0x6752, 0x966C, 0x6754, + 0x966D, 0x6755, 0x966E, 0x6757, 0x966F, 0x6758, 0x9670, 0x6759, + 0x9671, 0x675A, 0x9672, 0x675B, 0x9673, 0x675D, 0x9674, 0x6762, + 0x9675, 0x6763, 0x9676, 0x6764, 0x9677, 0x6766, 0x9678, 0x6767, + 0x9679, 0x676B, 0x967A, 0x676C, 0x967B, 0x676E, 0x967C, 0x6771, + 0x967D, 0x6774, 0x967E, 0x6776, 0x9680, 0x6778, 0x9681, 0x6779, + 0x9682, 0x677A, 0x9683, 0x677B, 0x9684, 0x677D, 0x9685, 0x6780, + 0x9686, 0x6782, 0x9687, 0x6783, 0x9688, 0x6785, 0x9689, 0x6786, + 0x968A, 0x6788, 0x968B, 0x678A, 0x968C, 0x678C, 0x968D, 0x678D, + 0x968E, 0x678E, 0x968F, 0x678F, 0x9690, 0x6791, 0x9691, 0x6792, + 0x9692, 0x6793, 0x9693, 0x6794, 0x9694, 0x6796, 0x9695, 0x6799, + 0x9696, 0x679B, 0x9697, 0x679F, 0x9698, 0x67A0, 0x9699, 0x67A1, + 0x969A, 0x67A4, 0x969B, 0x67A6, 0x969C, 0x67A9, 0x969D, 0x67AC, + 0x969E, 0x67AE, 0x969F, 0x67B1, 0x96A0, 0x67B2, 0x96A1, 0x67B4, + 0x96A2, 0x67B9, 0x96A3, 0x67BA, 0x96A4, 0x67BB, 0x96A5, 0x67BC, + 0x96A6, 0x67BD, 0x96A7, 0x67BE, 0x96A8, 0x67BF, 0x96A9, 0x67C0, + 0x96AA, 0x67C2, 0x96AB, 0x67C5, 0x96AC, 0x67C6, 0x96AD, 0x67C7, + 0x96AE, 0x67C8, 0x96AF, 0x67C9, 0x96B0, 0x67CA, 0x96B1, 0x67CB, + 0x96B2, 0x67CC, 0x96B3, 0x67CD, 0x96B4, 0x67CE, 0x96B5, 0x67D5, + 0x96B6, 0x67D6, 0x96B7, 0x67D7, 0x96B8, 0x67DB, 0x96B9, 0x67DF, + 0x96BA, 0x67E1, 0x96BB, 0x67E3, 0x96BC, 0x67E4, 0x96BD, 0x67E6, + 0x96BE, 0x67E7, 0x96BF, 0x67E8, 0x96C0, 0x67EA, 0x96C1, 0x67EB, + 0x96C2, 0x67ED, 0x96C3, 0x67EE, 0x96C4, 0x67F2, 0x96C5, 0x67F5, + 0x96C6, 0x67F6, 0x96C7, 0x67F7, 0x96C8, 0x67F8, 0x96C9, 0x67F9, + 0x96CA, 0x67FA, 0x96CB, 0x67FB, 0x96CC, 0x67FC, 0x96CD, 0x67FE, + 0x96CE, 0x6801, 0x96CF, 0x6802, 0x96D0, 0x6803, 0x96D1, 0x6804, + 0x96D2, 0x6806, 0x96D3, 0x680D, 0x96D4, 0x6810, 0x96D5, 0x6812, + 0x96D6, 0x6814, 0x96D7, 0x6815, 0x96D8, 0x6818, 0x96D9, 0x6819, + 0x96DA, 0x681A, 0x96DB, 0x681B, 0x96DC, 0x681C, 0x96DD, 0x681E, + 0x96DE, 0x681F, 0x96DF, 0x6820, 0x96E0, 0x6822, 0x96E1, 0x6823, + 0x96E2, 0x6824, 0x96E3, 0x6825, 0x96E4, 0x6826, 0x96E5, 0x6827, + 0x96E6, 0x6828, 0x96E7, 0x682B, 0x96E8, 0x682C, 0x96E9, 0x682D, + 0x96EA, 0x682E, 0x96EB, 0x682F, 0x96EC, 0x6830, 0x96ED, 0x6831, + 0x96EE, 0x6834, 0x96EF, 0x6835, 0x96F0, 0x6836, 0x96F1, 0x683A, + 0x96F2, 0x683B, 0x96F3, 0x683F, 0x96F4, 0x6847, 0x96F5, 0x684B, + 0x96F6, 0x684D, 0x96F7, 0x684F, 0x96F8, 0x6852, 0x96F9, 0x6856, + 0x96FA, 0x6857, 0x96FB, 0x6858, 0x96FC, 0x6859, 0x96FD, 0x685A, + 0x96FE, 0x685B, 0x9740, 0x685C, 0x9741, 0x685D, 0x9742, 0x685E, + 0x9743, 0x685F, 0x9744, 0x686A, 0x9745, 0x686C, 0x9746, 0x686D, + 0x9747, 0x686E, 0x9748, 0x686F, 0x9749, 0x6870, 0x974A, 0x6871, + 0x974B, 0x6872, 0x974C, 0x6873, 0x974D, 0x6875, 0x974E, 0x6878, + 0x974F, 0x6879, 0x9750, 0x687A, 0x9751, 0x687B, 0x9752, 0x687C, + 0x9753, 0x687D, 0x9754, 0x687E, 0x9755, 0x687F, 0x9756, 0x6880, + 0x9757, 0x6882, 0x9758, 0x6884, 0x9759, 0x6887, 0x975A, 0x6888, + 0x975B, 0x6889, 0x975C, 0x688A, 0x975D, 0x688B, 0x975E, 0x688C, + 0x975F, 0x688D, 0x9760, 0x688E, 0x9761, 0x6890, 0x9762, 0x6891, + 0x9763, 0x6892, 0x9764, 0x6894, 0x9765, 0x6895, 0x9766, 0x6896, + 0x9767, 0x6898, 0x9768, 0x6899, 0x9769, 0x689A, 0x976A, 0x689B, + 0x976B, 0x689C, 0x976C, 0x689D, 0x976D, 0x689E, 0x976E, 0x689F, + 0x976F, 0x68A0, 0x9770, 0x68A1, 0x9771, 0x68A3, 0x9772, 0x68A4, + 0x9773, 0x68A5, 0x9774, 0x68A9, 0x9775, 0x68AA, 0x9776, 0x68AB, + 0x9777, 0x68AC, 0x9778, 0x68AE, 0x9779, 0x68B1, 0x977A, 0x68B2, + 0x977B, 0x68B4, 0x977C, 0x68B6, 0x977D, 0x68B7, 0x977E, 0x68B8, + 0x9780, 0x68B9, 0x9781, 0x68BA, 0x9782, 0x68BB, 0x9783, 0x68BC, + 0x9784, 0x68BD, 0x9785, 0x68BE, 0x9786, 0x68BF, 0x9787, 0x68C1, + 0x9788, 0x68C3, 0x9789, 0x68C4, 0x978A, 0x68C5, 0x978B, 0x68C6, + 0x978C, 0x68C7, 0x978D, 0x68C8, 0x978E, 0x68CA, 0x978F, 0x68CC, + 0x9790, 0x68CE, 0x9791, 0x68CF, 0x9792, 0x68D0, 0x9793, 0x68D1, + 0x9794, 0x68D3, 0x9795, 0x68D4, 0x9796, 0x68D6, 0x9797, 0x68D7, + 0x9798, 0x68D9, 0x9799, 0x68DB, 0x979A, 0x68DC, 0x979B, 0x68DD, + 0x979C, 0x68DE, 0x979D, 0x68DF, 0x979E, 0x68E1, 0x979F, 0x68E2, + 0x97A0, 0x68E4, 0x97A1, 0x68E5, 0x97A2, 0x68E6, 0x97A3, 0x68E7, + 0x97A4, 0x68E8, 0x97A5, 0x68E9, 0x97A6, 0x68EA, 0x97A7, 0x68EB, + 0x97A8, 0x68EC, 0x97A9, 0x68ED, 0x97AA, 0x68EF, 0x97AB, 0x68F2, + 0x97AC, 0x68F3, 0x97AD, 0x68F4, 0x97AE, 0x68F6, 0x97AF, 0x68F7, + 0x97B0, 0x68F8, 0x97B1, 0x68FB, 0x97B2, 0x68FD, 0x97B3, 0x68FE, + 0x97B4, 0x68FF, 0x97B5, 0x6900, 0x97B6, 0x6902, 0x97B7, 0x6903, + 0x97B8, 0x6904, 0x97B9, 0x6906, 0x97BA, 0x6907, 0x97BB, 0x6908, + 0x97BC, 0x6909, 0x97BD, 0x690A, 0x97BE, 0x690C, 0x97BF, 0x690F, + 0x97C0, 0x6911, 0x97C1, 0x6913, 0x97C2, 0x6914, 0x97C3, 0x6915, + 0x97C4, 0x6916, 0x97C5, 0x6917, 0x97C6, 0x6918, 0x97C7, 0x6919, + 0x97C8, 0x691A, 0x97C9, 0x691B, 0x97CA, 0x691C, 0x97CB, 0x691D, + 0x97CC, 0x691E, 0x97CD, 0x6921, 0x97CE, 0x6922, 0x97CF, 0x6923, + 0x97D0, 0x6925, 0x97D1, 0x6926, 0x97D2, 0x6927, 0x97D3, 0x6928, + 0x97D4, 0x6929, 0x97D5, 0x692A, 0x97D6, 0x692B, 0x97D7, 0x692C, + 0x97D8, 0x692E, 0x97D9, 0x692F, 0x97DA, 0x6931, 0x97DB, 0x6932, + 0x97DC, 0x6933, 0x97DD, 0x6935, 0x97DE, 0x6936, 0x97DF, 0x6937, + 0x97E0, 0x6938, 0x97E1, 0x693A, 0x97E2, 0x693B, 0x97E3, 0x693C, + 0x97E4, 0x693E, 0x97E5, 0x6940, 0x97E6, 0x6941, 0x97E7, 0x6943, + 0x97E8, 0x6944, 0x97E9, 0x6945, 0x97EA, 0x6946, 0x97EB, 0x6947, + 0x97EC, 0x6948, 0x97ED, 0x6949, 0x97EE, 0x694A, 0x97EF, 0x694B, + 0x97F0, 0x694C, 0x97F1, 0x694D, 0x97F2, 0x694E, 0x97F3, 0x694F, + 0x97F4, 0x6950, 0x97F5, 0x6951, 0x97F6, 0x6952, 0x97F7, 0x6953, + 0x97F8, 0x6955, 0x97F9, 0x6956, 0x97FA, 0x6958, 0x97FB, 0x6959, + 0x97FC, 0x695B, 0x97FD, 0x695C, 0x97FE, 0x695F, 0x9840, 0x6961, + 0x9841, 0x6962, 0x9842, 0x6964, 0x9843, 0x6965, 0x9844, 0x6967, + 0x9845, 0x6968, 0x9846, 0x6969, 0x9847, 0x696A, 0x9848, 0x696C, + 0x9849, 0x696D, 0x984A, 0x696F, 0x984B, 0x6970, 0x984C, 0x6972, + 0x984D, 0x6973, 0x984E, 0x6974, 0x984F, 0x6975, 0x9850, 0x6976, + 0x9851, 0x697A, 0x9852, 0x697B, 0x9853, 0x697D, 0x9854, 0x697E, + 0x9855, 0x697F, 0x9856, 0x6981, 0x9857, 0x6983, 0x9858, 0x6985, + 0x9859, 0x698A, 0x985A, 0x698B, 0x985B, 0x698C, 0x985C, 0x698E, + 0x985D, 0x698F, 0x985E, 0x6990, 0x985F, 0x6991, 0x9860, 0x6992, + 0x9861, 0x6993, 0x9862, 0x6996, 0x9863, 0x6997, 0x9864, 0x6999, + 0x9865, 0x699A, 0x9866, 0x699D, 0x9867, 0x699E, 0x9868, 0x699F, + 0x9869, 0x69A0, 0x986A, 0x69A1, 0x986B, 0x69A2, 0x986C, 0x69A3, + 0x986D, 0x69A4, 0x986E, 0x69A5, 0x986F, 0x69A6, 0x9870, 0x69A9, + 0x9871, 0x69AA, 0x9872, 0x69AC, 0x9873, 0x69AE, 0x9874, 0x69AF, + 0x9875, 0x69B0, 0x9876, 0x69B2, 0x9877, 0x69B3, 0x9878, 0x69B5, + 0x9879, 0x69B6, 0x987A, 0x69B8, 0x987B, 0x69B9, 0x987C, 0x69BA, + 0x987D, 0x69BC, 0x987E, 0x69BD, 0x9880, 0x69BE, 0x9881, 0x69BF, + 0x9882, 0x69C0, 0x9883, 0x69C2, 0x9884, 0x69C3, 0x9885, 0x69C4, + 0x9886, 0x69C5, 0x9887, 0x69C6, 0x9888, 0x69C7, 0x9889, 0x69C8, + 0x988A, 0x69C9, 0x988B, 0x69CB, 0x988C, 0x69CD, 0x988D, 0x69CF, + 0x988E, 0x69D1, 0x988F, 0x69D2, 0x9890, 0x69D3, 0x9891, 0x69D5, + 0x9892, 0x69D6, 0x9893, 0x69D7, 0x9894, 0x69D8, 0x9895, 0x69D9, + 0x9896, 0x69DA, 0x9897, 0x69DC, 0x9898, 0x69DD, 0x9899, 0x69DE, + 0x989A, 0x69E1, 0x989B, 0x69E2, 0x989C, 0x69E3, 0x989D, 0x69E4, + 0x989E, 0x69E5, 0x989F, 0x69E6, 0x98A0, 0x69E7, 0x98A1, 0x69E8, + 0x98A2, 0x69E9, 0x98A3, 0x69EA, 0x98A4, 0x69EB, 0x98A5, 0x69EC, + 0x98A6, 0x69EE, 0x98A7, 0x69EF, 0x98A8, 0x69F0, 0x98A9, 0x69F1, + 0x98AA, 0x69F3, 0x98AB, 0x69F4, 0x98AC, 0x69F5, 0x98AD, 0x69F6, + 0x98AE, 0x69F7, 0x98AF, 0x69F8, 0x98B0, 0x69F9, 0x98B1, 0x69FA, + 0x98B2, 0x69FB, 0x98B3, 0x69FC, 0x98B4, 0x69FE, 0x98B5, 0x6A00, + 0x98B6, 0x6A01, 0x98B7, 0x6A02, 0x98B8, 0x6A03, 0x98B9, 0x6A04, + 0x98BA, 0x6A05, 0x98BB, 0x6A06, 0x98BC, 0x6A07, 0x98BD, 0x6A08, + 0x98BE, 0x6A09, 0x98BF, 0x6A0B, 0x98C0, 0x6A0C, 0x98C1, 0x6A0D, + 0x98C2, 0x6A0E, 0x98C3, 0x6A0F, 0x98C4, 0x6A10, 0x98C5, 0x6A11, + 0x98C6, 0x6A12, 0x98C7, 0x6A13, 0x98C8, 0x6A14, 0x98C9, 0x6A15, + 0x98CA, 0x6A16, 0x98CB, 0x6A19, 0x98CC, 0x6A1A, 0x98CD, 0x6A1B, + 0x98CE, 0x6A1C, 0x98CF, 0x6A1D, 0x98D0, 0x6A1E, 0x98D1, 0x6A20, + 0x98D2, 0x6A22, 0x98D3, 0x6A23, 0x98D4, 0x6A24, 0x98D5, 0x6A25, + 0x98D6, 0x6A26, 0x98D7, 0x6A27, 0x98D8, 0x6A29, 0x98D9, 0x6A2B, + 0x98DA, 0x6A2C, 0x98DB, 0x6A2D, 0x98DC, 0x6A2E, 0x98DD, 0x6A30, + 0x98DE, 0x6A32, 0x98DF, 0x6A33, 0x98E0, 0x6A34, 0x98E1, 0x6A36, + 0x98E2, 0x6A37, 0x98E3, 0x6A38, 0x98E4, 0x6A39, 0x98E5, 0x6A3A, + 0x98E6, 0x6A3B, 0x98E7, 0x6A3C, 0x98E8, 0x6A3F, 0x98E9, 0x6A40, + 0x98EA, 0x6A41, 0x98EB, 0x6A42, 0x98EC, 0x6A43, 0x98ED, 0x6A45, + 0x98EE, 0x6A46, 0x98EF, 0x6A48, 0x98F0, 0x6A49, 0x98F1, 0x6A4A, + 0x98F2, 0x6A4B, 0x98F3, 0x6A4C, 0x98F4, 0x6A4D, 0x98F5, 0x6A4E, + 0x98F6, 0x6A4F, 0x98F7, 0x6A51, 0x98F8, 0x6A52, 0x98F9, 0x6A53, + 0x98FA, 0x6A54, 0x98FB, 0x6A55, 0x98FC, 0x6A56, 0x98FD, 0x6A57, + 0x98FE, 0x6A5A, 0x9940, 0x6A5C, 0x9941, 0x6A5D, 0x9942, 0x6A5E, + 0x9943, 0x6A5F, 0x9944, 0x6A60, 0x9945, 0x6A62, 0x9946, 0x6A63, + 0x9947, 0x6A64, 0x9948, 0x6A66, 0x9949, 0x6A67, 0x994A, 0x6A68, + 0x994B, 0x6A69, 0x994C, 0x6A6A, 0x994D, 0x6A6B, 0x994E, 0x6A6C, + 0x994F, 0x6A6D, 0x9950, 0x6A6E, 0x9951, 0x6A6F, 0x9952, 0x6A70, + 0x9953, 0x6A72, 0x9954, 0x6A73, 0x9955, 0x6A74, 0x9956, 0x6A75, + 0x9957, 0x6A76, 0x9958, 0x6A77, 0x9959, 0x6A78, 0x995A, 0x6A7A, + 0x995B, 0x6A7B, 0x995C, 0x6A7D, 0x995D, 0x6A7E, 0x995E, 0x6A7F, + 0x995F, 0x6A81, 0x9960, 0x6A82, 0x9961, 0x6A83, 0x9962, 0x6A85, + 0x9963, 0x6A86, 0x9964, 0x6A87, 0x9965, 0x6A88, 0x9966, 0x6A89, + 0x9967, 0x6A8A, 0x9968, 0x6A8B, 0x9969, 0x6A8C, 0x996A, 0x6A8D, + 0x996B, 0x6A8F, 0x996C, 0x6A92, 0x996D, 0x6A93, 0x996E, 0x6A94, + 0x996F, 0x6A95, 0x9970, 0x6A96, 0x9971, 0x6A98, 0x9972, 0x6A99, + 0x9973, 0x6A9A, 0x9974, 0x6A9B, 0x9975, 0x6A9C, 0x9976, 0x6A9D, + 0x9977, 0x6A9E, 0x9978, 0x6A9F, 0x9979, 0x6AA1, 0x997A, 0x6AA2, + 0x997B, 0x6AA3, 0x997C, 0x6AA4, 0x997D, 0x6AA5, 0x997E, 0x6AA6, + 0x9980, 0x6AA7, 0x9981, 0x6AA8, 0x9982, 0x6AAA, 0x9983, 0x6AAD, + 0x9984, 0x6AAE, 0x9985, 0x6AAF, 0x9986, 0x6AB0, 0x9987, 0x6AB1, + 0x9988, 0x6AB2, 0x9989, 0x6AB3, 0x998A, 0x6AB4, 0x998B, 0x6AB5, + 0x998C, 0x6AB6, 0x998D, 0x6AB7, 0x998E, 0x6AB8, 0x998F, 0x6AB9, + 0x9990, 0x6ABA, 0x9991, 0x6ABB, 0x9992, 0x6ABC, 0x9993, 0x6ABD, + 0x9994, 0x6ABE, 0x9995, 0x6ABF, 0x9996, 0x6AC0, 0x9997, 0x6AC1, + 0x9998, 0x6AC2, 0x9999, 0x6AC3, 0x999A, 0x6AC4, 0x999B, 0x6AC5, + 0x999C, 0x6AC6, 0x999D, 0x6AC7, 0x999E, 0x6AC8, 0x999F, 0x6AC9, + 0x99A0, 0x6ACA, 0x99A1, 0x6ACB, 0x99A2, 0x6ACC, 0x99A3, 0x6ACD, + 0x99A4, 0x6ACE, 0x99A5, 0x6ACF, 0x99A6, 0x6AD0, 0x99A7, 0x6AD1, + 0x99A8, 0x6AD2, 0x99A9, 0x6AD3, 0x99AA, 0x6AD4, 0x99AB, 0x6AD5, + 0x99AC, 0x6AD6, 0x99AD, 0x6AD7, 0x99AE, 0x6AD8, 0x99AF, 0x6AD9, + 0x99B0, 0x6ADA, 0x99B1, 0x6ADB, 0x99B2, 0x6ADC, 0x99B3, 0x6ADD, + 0x99B4, 0x6ADE, 0x99B5, 0x6ADF, 0x99B6, 0x6AE0, 0x99B7, 0x6AE1, + 0x99B8, 0x6AE2, 0x99B9, 0x6AE3, 0x99BA, 0x6AE4, 0x99BB, 0x6AE5, + 0x99BC, 0x6AE6, 0x99BD, 0x6AE7, 0x99BE, 0x6AE8, 0x99BF, 0x6AE9, + 0x99C0, 0x6AEA, 0x99C1, 0x6AEB, 0x99C2, 0x6AEC, 0x99C3, 0x6AED, + 0x99C4, 0x6AEE, 0x99C5, 0x6AEF, 0x99C6, 0x6AF0, 0x99C7, 0x6AF1, + 0x99C8, 0x6AF2, 0x99C9, 0x6AF3, 0x99CA, 0x6AF4, 0x99CB, 0x6AF5, + 0x99CC, 0x6AF6, 0x99CD, 0x6AF7, 0x99CE, 0x6AF8, 0x99CF, 0x6AF9, + 0x99D0, 0x6AFA, 0x99D1, 0x6AFB, 0x99D2, 0x6AFC, 0x99D3, 0x6AFD, + 0x99D4, 0x6AFE, 0x99D5, 0x6AFF, 0x99D6, 0x6B00, 0x99D7, 0x6B01, + 0x99D8, 0x6B02, 0x99D9, 0x6B03, 0x99DA, 0x6B04, 0x99DB, 0x6B05, + 0x99DC, 0x6B06, 0x99DD, 0x6B07, 0x99DE, 0x6B08, 0x99DF, 0x6B09, + 0x99E0, 0x6B0A, 0x99E1, 0x6B0B, 0x99E2, 0x6B0C, 0x99E3, 0x6B0D, + 0x99E4, 0x6B0E, 0x99E5, 0x6B0F, 0x99E6, 0x6B10, 0x99E7, 0x6B11, + 0x99E8, 0x6B12, 0x99E9, 0x6B13, 0x99EA, 0x6B14, 0x99EB, 0x6B15, + 0x99EC, 0x6B16, 0x99ED, 0x6B17, 0x99EE, 0x6B18, 0x99EF, 0x6B19, + 0x99F0, 0x6B1A, 0x99F1, 0x6B1B, 0x99F2, 0x6B1C, 0x99F3, 0x6B1D, + 0x99F4, 0x6B1E, 0x99F5, 0x6B1F, 0x99F6, 0x6B25, 0x99F7, 0x6B26, + 0x99F8, 0x6B28, 0x99F9, 0x6B29, 0x99FA, 0x6B2A, 0x99FB, 0x6B2B, + 0x99FC, 0x6B2C, 0x99FD, 0x6B2D, 0x99FE, 0x6B2E, 0x9A40, 0x6B2F, + 0x9A41, 0x6B30, 0x9A42, 0x6B31, 0x9A43, 0x6B33, 0x9A44, 0x6B34, + 0x9A45, 0x6B35, 0x9A46, 0x6B36, 0x9A47, 0x6B38, 0x9A48, 0x6B3B, + 0x9A49, 0x6B3C, 0x9A4A, 0x6B3D, 0x9A4B, 0x6B3F, 0x9A4C, 0x6B40, + 0x9A4D, 0x6B41, 0x9A4E, 0x6B42, 0x9A4F, 0x6B44, 0x9A50, 0x6B45, + 0x9A51, 0x6B48, 0x9A52, 0x6B4A, 0x9A53, 0x6B4B, 0x9A54, 0x6B4D, + 0x9A55, 0x6B4E, 0x9A56, 0x6B4F, 0x9A57, 0x6B50, 0x9A58, 0x6B51, + 0x9A59, 0x6B52, 0x9A5A, 0x6B53, 0x9A5B, 0x6B54, 0x9A5C, 0x6B55, + 0x9A5D, 0x6B56, 0x9A5E, 0x6B57, 0x9A5F, 0x6B58, 0x9A60, 0x6B5A, + 0x9A61, 0x6B5B, 0x9A62, 0x6B5C, 0x9A63, 0x6B5D, 0x9A64, 0x6B5E, + 0x9A65, 0x6B5F, 0x9A66, 0x6B60, 0x9A67, 0x6B61, 0x9A68, 0x6B68, + 0x9A69, 0x6B69, 0x9A6A, 0x6B6B, 0x9A6B, 0x6B6C, 0x9A6C, 0x6B6D, + 0x9A6D, 0x6B6E, 0x9A6E, 0x6B6F, 0x9A6F, 0x6B70, 0x9A70, 0x6B71, + 0x9A71, 0x6B72, 0x9A72, 0x6B73, 0x9A73, 0x6B74, 0x9A74, 0x6B75, + 0x9A75, 0x6B76, 0x9A76, 0x6B77, 0x9A77, 0x6B78, 0x9A78, 0x6B7A, + 0x9A79, 0x6B7D, 0x9A7A, 0x6B7E, 0x9A7B, 0x6B7F, 0x9A7C, 0x6B80, + 0x9A7D, 0x6B85, 0x9A7E, 0x6B88, 0x9A80, 0x6B8C, 0x9A81, 0x6B8E, + 0x9A82, 0x6B8F, 0x9A83, 0x6B90, 0x9A84, 0x6B91, 0x9A85, 0x6B94, + 0x9A86, 0x6B95, 0x9A87, 0x6B97, 0x9A88, 0x6B98, 0x9A89, 0x6B99, + 0x9A8A, 0x6B9C, 0x9A8B, 0x6B9D, 0x9A8C, 0x6B9E, 0x9A8D, 0x6B9F, + 0x9A8E, 0x6BA0, 0x9A8F, 0x6BA2, 0x9A90, 0x6BA3, 0x9A91, 0x6BA4, + 0x9A92, 0x6BA5, 0x9A93, 0x6BA6, 0x9A94, 0x6BA7, 0x9A95, 0x6BA8, + 0x9A96, 0x6BA9, 0x9A97, 0x6BAB, 0x9A98, 0x6BAC, 0x9A99, 0x6BAD, + 0x9A9A, 0x6BAE, 0x9A9B, 0x6BAF, 0x9A9C, 0x6BB0, 0x9A9D, 0x6BB1, + 0x9A9E, 0x6BB2, 0x9A9F, 0x6BB6, 0x9AA0, 0x6BB8, 0x9AA1, 0x6BB9, + 0x9AA2, 0x6BBA, 0x9AA3, 0x6BBB, 0x9AA4, 0x6BBC, 0x9AA5, 0x6BBD, + 0x9AA6, 0x6BBE, 0x9AA7, 0x6BC0, 0x9AA8, 0x6BC3, 0x9AA9, 0x6BC4, + 0x9AAA, 0x6BC6, 0x9AAB, 0x6BC7, 0x9AAC, 0x6BC8, 0x9AAD, 0x6BC9, + 0x9AAE, 0x6BCA, 0x9AAF, 0x6BCC, 0x9AB0, 0x6BCE, 0x9AB1, 0x6BD0, + 0x9AB2, 0x6BD1, 0x9AB3, 0x6BD8, 0x9AB4, 0x6BDA, 0x9AB5, 0x6BDC, + 0x9AB6, 0x6BDD, 0x9AB7, 0x6BDE, 0x9AB8, 0x6BDF, 0x9AB9, 0x6BE0, + 0x9ABA, 0x6BE2, 0x9ABB, 0x6BE3, 0x9ABC, 0x6BE4, 0x9ABD, 0x6BE5, + 0x9ABE, 0x6BE6, 0x9ABF, 0x6BE7, 0x9AC0, 0x6BE8, 0x9AC1, 0x6BE9, + 0x9AC2, 0x6BEC, 0x9AC3, 0x6BED, 0x9AC4, 0x6BEE, 0x9AC5, 0x6BF0, + 0x9AC6, 0x6BF1, 0x9AC7, 0x6BF2, 0x9AC8, 0x6BF4, 0x9AC9, 0x6BF6, + 0x9ACA, 0x6BF7, 0x9ACB, 0x6BF8, 0x9ACC, 0x6BFA, 0x9ACD, 0x6BFB, + 0x9ACE, 0x6BFC, 0x9ACF, 0x6BFE, 0x9AD0, 0x6BFF, 0x9AD1, 0x6C00, + 0x9AD2, 0x6C01, 0x9AD3, 0x6C02, 0x9AD4, 0x6C03, 0x9AD5, 0x6C04, + 0x9AD6, 0x6C08, 0x9AD7, 0x6C09, 0x9AD8, 0x6C0A, 0x9AD9, 0x6C0B, + 0x9ADA, 0x6C0C, 0x9ADB, 0x6C0E, 0x9ADC, 0x6C12, 0x9ADD, 0x6C17, + 0x9ADE, 0x6C1C, 0x9ADF, 0x6C1D, 0x9AE0, 0x6C1E, 0x9AE1, 0x6C20, + 0x9AE2, 0x6C23, 0x9AE3, 0x6C25, 0x9AE4, 0x6C2B, 0x9AE5, 0x6C2C, + 0x9AE6, 0x6C2D, 0x9AE7, 0x6C31, 0x9AE8, 0x6C33, 0x9AE9, 0x6C36, + 0x9AEA, 0x6C37, 0x9AEB, 0x6C39, 0x9AEC, 0x6C3A, 0x9AED, 0x6C3B, + 0x9AEE, 0x6C3C, 0x9AEF, 0x6C3E, 0x9AF0, 0x6C3F, 0x9AF1, 0x6C43, + 0x9AF2, 0x6C44, 0x9AF3, 0x6C45, 0x9AF4, 0x6C48, 0x9AF5, 0x6C4B, + 0x9AF6, 0x6C4C, 0x9AF7, 0x6C4D, 0x9AF8, 0x6C4E, 0x9AF9, 0x6C4F, + 0x9AFA, 0x6C51, 0x9AFB, 0x6C52, 0x9AFC, 0x6C53, 0x9AFD, 0x6C56, + 0x9AFE, 0x6C58, 0x9B40, 0x6C59, 0x9B41, 0x6C5A, 0x9B42, 0x6C62, + 0x9B43, 0x6C63, 0x9B44, 0x6C65, 0x9B45, 0x6C66, 0x9B46, 0x6C67, + 0x9B47, 0x6C6B, 0x9B48, 0x6C6C, 0x9B49, 0x6C6D, 0x9B4A, 0x6C6E, + 0x9B4B, 0x6C6F, 0x9B4C, 0x6C71, 0x9B4D, 0x6C73, 0x9B4E, 0x6C75, + 0x9B4F, 0x6C77, 0x9B50, 0x6C78, 0x9B51, 0x6C7A, 0x9B52, 0x6C7B, + 0x9B53, 0x6C7C, 0x9B54, 0x6C7F, 0x9B55, 0x6C80, 0x9B56, 0x6C84, + 0x9B57, 0x6C87, 0x9B58, 0x6C8A, 0x9B59, 0x6C8B, 0x9B5A, 0x6C8D, + 0x9B5B, 0x6C8E, 0x9B5C, 0x6C91, 0x9B5D, 0x6C92, 0x9B5E, 0x6C95, + 0x9B5F, 0x6C96, 0x9B60, 0x6C97, 0x9B61, 0x6C98, 0x9B62, 0x6C9A, + 0x9B63, 0x6C9C, 0x9B64, 0x6C9D, 0x9B65, 0x6C9E, 0x9B66, 0x6CA0, + 0x9B67, 0x6CA2, 0x9B68, 0x6CA8, 0x9B69, 0x6CAC, 0x9B6A, 0x6CAF, + 0x9B6B, 0x6CB0, 0x9B6C, 0x6CB4, 0x9B6D, 0x6CB5, 0x9B6E, 0x6CB6, + 0x9B6F, 0x6CB7, 0x9B70, 0x6CBA, 0x9B71, 0x6CC0, 0x9B72, 0x6CC1, + 0x9B73, 0x6CC2, 0x9B74, 0x6CC3, 0x9B75, 0x6CC6, 0x9B76, 0x6CC7, + 0x9B77, 0x6CC8, 0x9B78, 0x6CCB, 0x9B79, 0x6CCD, 0x9B7A, 0x6CCE, + 0x9B7B, 0x6CCF, 0x9B7C, 0x6CD1, 0x9B7D, 0x6CD2, 0x9B7E, 0x6CD8, + 0x9B80, 0x6CD9, 0x9B81, 0x6CDA, 0x9B82, 0x6CDC, 0x9B83, 0x6CDD, + 0x9B84, 0x6CDF, 0x9B85, 0x6CE4, 0x9B86, 0x6CE6, 0x9B87, 0x6CE7, + 0x9B88, 0x6CE9, 0x9B89, 0x6CEC, 0x9B8A, 0x6CED, 0x9B8B, 0x6CF2, + 0x9B8C, 0x6CF4, 0x9B8D, 0x6CF9, 0x9B8E, 0x6CFF, 0x9B8F, 0x6D00, + 0x9B90, 0x6D02, 0x9B91, 0x6D03, 0x9B92, 0x6D05, 0x9B93, 0x6D06, + 0x9B94, 0x6D08, 0x9B95, 0x6D09, 0x9B96, 0x6D0A, 0x9B97, 0x6D0D, + 0x9B98, 0x6D0F, 0x9B99, 0x6D10, 0x9B9A, 0x6D11, 0x9B9B, 0x6D13, + 0x9B9C, 0x6D14, 0x9B9D, 0x6D15, 0x9B9E, 0x6D16, 0x9B9F, 0x6D18, + 0x9BA0, 0x6D1C, 0x9BA1, 0x6D1D, 0x9BA2, 0x6D1F, 0x9BA3, 0x6D20, + 0x9BA4, 0x6D21, 0x9BA5, 0x6D22, 0x9BA6, 0x6D23, 0x9BA7, 0x6D24, + 0x9BA8, 0x6D26, 0x9BA9, 0x6D28, 0x9BAA, 0x6D29, 0x9BAB, 0x6D2C, + 0x9BAC, 0x6D2D, 0x9BAD, 0x6D2F, 0x9BAE, 0x6D30, 0x9BAF, 0x6D34, + 0x9BB0, 0x6D36, 0x9BB1, 0x6D37, 0x9BB2, 0x6D38, 0x9BB3, 0x6D3A, + 0x9BB4, 0x6D3F, 0x9BB5, 0x6D40, 0x9BB6, 0x6D42, 0x9BB7, 0x6D44, + 0x9BB8, 0x6D49, 0x9BB9, 0x6D4C, 0x9BBA, 0x6D50, 0x9BBB, 0x6D55, + 0x9BBC, 0x6D56, 0x9BBD, 0x6D57, 0x9BBE, 0x6D58, 0x9BBF, 0x6D5B, + 0x9BC0, 0x6D5D, 0x9BC1, 0x6D5F, 0x9BC2, 0x6D61, 0x9BC3, 0x6D62, + 0x9BC4, 0x6D64, 0x9BC5, 0x6D65, 0x9BC6, 0x6D67, 0x9BC7, 0x6D68, + 0x9BC8, 0x6D6B, 0x9BC9, 0x6D6C, 0x9BCA, 0x6D6D, 0x9BCB, 0x6D70, + 0x9BCC, 0x6D71, 0x9BCD, 0x6D72, 0x9BCE, 0x6D73, 0x9BCF, 0x6D75, + 0x9BD0, 0x6D76, 0x9BD1, 0x6D79, 0x9BD2, 0x6D7A, 0x9BD3, 0x6D7B, + 0x9BD4, 0x6D7D, 0x9BD5, 0x6D7E, 0x9BD6, 0x6D7F, 0x9BD7, 0x6D80, + 0x9BD8, 0x6D81, 0x9BD9, 0x6D83, 0x9BDA, 0x6D84, 0x9BDB, 0x6D86, + 0x9BDC, 0x6D87, 0x9BDD, 0x6D8A, 0x9BDE, 0x6D8B, 0x9BDF, 0x6D8D, + 0x9BE0, 0x6D8F, 0x9BE1, 0x6D90, 0x9BE2, 0x6D92, 0x9BE3, 0x6D96, + 0x9BE4, 0x6D97, 0x9BE5, 0x6D98, 0x9BE6, 0x6D99, 0x9BE7, 0x6D9A, + 0x9BE8, 0x6D9C, 0x9BE9, 0x6DA2, 0x9BEA, 0x6DA5, 0x9BEB, 0x6DAC, + 0x9BEC, 0x6DAD, 0x9BED, 0x6DB0, 0x9BEE, 0x6DB1, 0x9BEF, 0x6DB3, + 0x9BF0, 0x6DB4, 0x9BF1, 0x6DB6, 0x9BF2, 0x6DB7, 0x9BF3, 0x6DB9, + 0x9BF4, 0x6DBA, 0x9BF5, 0x6DBB, 0x9BF6, 0x6DBC, 0x9BF7, 0x6DBD, + 0x9BF8, 0x6DBE, 0x9BF9, 0x6DC1, 0x9BFA, 0x6DC2, 0x9BFB, 0x6DC3, + 0x9BFC, 0x6DC8, 0x9BFD, 0x6DC9, 0x9BFE, 0x6DCA, 0x9C40, 0x6DCD, + 0x9C41, 0x6DCE, 0x9C42, 0x6DCF, 0x9C43, 0x6DD0, 0x9C44, 0x6DD2, + 0x9C45, 0x6DD3, 0x9C46, 0x6DD4, 0x9C47, 0x6DD5, 0x9C48, 0x6DD7, + 0x9C49, 0x6DDA, 0x9C4A, 0x6DDB, 0x9C4B, 0x6DDC, 0x9C4C, 0x6DDF, + 0x9C4D, 0x6DE2, 0x9C4E, 0x6DE3, 0x9C4F, 0x6DE5, 0x9C50, 0x6DE7, + 0x9C51, 0x6DE8, 0x9C52, 0x6DE9, 0x9C53, 0x6DEA, 0x9C54, 0x6DED, + 0x9C55, 0x6DEF, 0x9C56, 0x6DF0, 0x9C57, 0x6DF2, 0x9C58, 0x6DF4, + 0x9C59, 0x6DF5, 0x9C5A, 0x6DF6, 0x9C5B, 0x6DF8, 0x9C5C, 0x6DFA, + 0x9C5D, 0x6DFD, 0x9C5E, 0x6DFE, 0x9C5F, 0x6DFF, 0x9C60, 0x6E00, + 0x9C61, 0x6E01, 0x9C62, 0x6E02, 0x9C63, 0x6E03, 0x9C64, 0x6E04, + 0x9C65, 0x6E06, 0x9C66, 0x6E07, 0x9C67, 0x6E08, 0x9C68, 0x6E09, + 0x9C69, 0x6E0B, 0x9C6A, 0x6E0F, 0x9C6B, 0x6E12, 0x9C6C, 0x6E13, + 0x9C6D, 0x6E15, 0x9C6E, 0x6E18, 0x9C6F, 0x6E19, 0x9C70, 0x6E1B, + 0x9C71, 0x6E1C, 0x9C72, 0x6E1E, 0x9C73, 0x6E1F, 0x9C74, 0x6E22, + 0x9C75, 0x6E26, 0x9C76, 0x6E27, 0x9C77, 0x6E28, 0x9C78, 0x6E2A, + 0x9C79, 0x6E2C, 0x9C7A, 0x6E2E, 0x9C7B, 0x6E30, 0x9C7C, 0x6E31, + 0x9C7D, 0x6E33, 0x9C7E, 0x6E35, 0x9C80, 0x6E36, 0x9C81, 0x6E37, + 0x9C82, 0x6E39, 0x9C83, 0x6E3B, 0x9C84, 0x6E3C, 0x9C85, 0x6E3D, + 0x9C86, 0x6E3E, 0x9C87, 0x6E3F, 0x9C88, 0x6E40, 0x9C89, 0x6E41, + 0x9C8A, 0x6E42, 0x9C8B, 0x6E45, 0x9C8C, 0x6E46, 0x9C8D, 0x6E47, + 0x9C8E, 0x6E48, 0x9C8F, 0x6E49, 0x9C90, 0x6E4A, 0x9C91, 0x6E4B, + 0x9C92, 0x6E4C, 0x9C93, 0x6E4F, 0x9C94, 0x6E50, 0x9C95, 0x6E51, + 0x9C96, 0x6E52, 0x9C97, 0x6E55, 0x9C98, 0x6E57, 0x9C99, 0x6E59, + 0x9C9A, 0x6E5A, 0x9C9B, 0x6E5C, 0x9C9C, 0x6E5D, 0x9C9D, 0x6E5E, + 0x9C9E, 0x6E60, 0x9C9F, 0x6E61, 0x9CA0, 0x6E62, 0x9CA1, 0x6E63, + 0x9CA2, 0x6E64, 0x9CA3, 0x6E65, 0x9CA4, 0x6E66, 0x9CA5, 0x6E67, + 0x9CA6, 0x6E68, 0x9CA7, 0x6E69, 0x9CA8, 0x6E6A, 0x9CA9, 0x6E6C, + 0x9CAA, 0x6E6D, 0x9CAB, 0x6E6F, 0x9CAC, 0x6E70, 0x9CAD, 0x6E71, + 0x9CAE, 0x6E72, 0x9CAF, 0x6E73, 0x9CB0, 0x6E74, 0x9CB1, 0x6E75, + 0x9CB2, 0x6E76, 0x9CB3, 0x6E77, 0x9CB4, 0x6E78, 0x9CB5, 0x6E79, + 0x9CB6, 0x6E7A, 0x9CB7, 0x6E7B, 0x9CB8, 0x6E7C, 0x9CB9, 0x6E7D, + 0x9CBA, 0x6E80, 0x9CBB, 0x6E81, 0x9CBC, 0x6E82, 0x9CBD, 0x6E84, + 0x9CBE, 0x6E87, 0x9CBF, 0x6E88, 0x9CC0, 0x6E8A, 0x9CC1, 0x6E8B, + 0x9CC2, 0x6E8C, 0x9CC3, 0x6E8D, 0x9CC4, 0x6E8E, 0x9CC5, 0x6E91, + 0x9CC6, 0x6E92, 0x9CC7, 0x6E93, 0x9CC8, 0x6E94, 0x9CC9, 0x6E95, + 0x9CCA, 0x6E96, 0x9CCB, 0x6E97, 0x9CCC, 0x6E99, 0x9CCD, 0x6E9A, + 0x9CCE, 0x6E9B, 0x9CCF, 0x6E9D, 0x9CD0, 0x6E9E, 0x9CD1, 0x6EA0, + 0x9CD2, 0x6EA1, 0x9CD3, 0x6EA3, 0x9CD4, 0x6EA4, 0x9CD5, 0x6EA6, + 0x9CD6, 0x6EA8, 0x9CD7, 0x6EA9, 0x9CD8, 0x6EAB, 0x9CD9, 0x6EAC, + 0x9CDA, 0x6EAD, 0x9CDB, 0x6EAE, 0x9CDC, 0x6EB0, 0x9CDD, 0x6EB3, + 0x9CDE, 0x6EB5, 0x9CDF, 0x6EB8, 0x9CE0, 0x6EB9, 0x9CE1, 0x6EBC, + 0x9CE2, 0x6EBE, 0x9CE3, 0x6EBF, 0x9CE4, 0x6EC0, 0x9CE5, 0x6EC3, + 0x9CE6, 0x6EC4, 0x9CE7, 0x6EC5, 0x9CE8, 0x6EC6, 0x9CE9, 0x6EC8, + 0x9CEA, 0x6EC9, 0x9CEB, 0x6ECA, 0x9CEC, 0x6ECC, 0x9CED, 0x6ECD, + 0x9CEE, 0x6ECE, 0x9CEF, 0x6ED0, 0x9CF0, 0x6ED2, 0x9CF1, 0x6ED6, + 0x9CF2, 0x6ED8, 0x9CF3, 0x6ED9, 0x9CF4, 0x6EDB, 0x9CF5, 0x6EDC, + 0x9CF6, 0x6EDD, 0x9CF7, 0x6EE3, 0x9CF8, 0x6EE7, 0x9CF9, 0x6EEA, + 0x9CFA, 0x6EEB, 0x9CFB, 0x6EEC, 0x9CFC, 0x6EED, 0x9CFD, 0x6EEE, + 0x9CFE, 0x6EEF, 0x9D40, 0x6EF0, 0x9D41, 0x6EF1, 0x9D42, 0x6EF2, + 0x9D43, 0x6EF3, 0x9D44, 0x6EF5, 0x9D45, 0x6EF6, 0x9D46, 0x6EF7, + 0x9D47, 0x6EF8, 0x9D48, 0x6EFA, 0x9D49, 0x6EFB, 0x9D4A, 0x6EFC, + 0x9D4B, 0x6EFD, 0x9D4C, 0x6EFE, 0x9D4D, 0x6EFF, 0x9D4E, 0x6F00, + 0x9D4F, 0x6F01, 0x9D50, 0x6F03, 0x9D51, 0x6F04, 0x9D52, 0x6F05, + 0x9D53, 0x6F07, 0x9D54, 0x6F08, 0x9D55, 0x6F0A, 0x9D56, 0x6F0B, + 0x9D57, 0x6F0C, 0x9D58, 0x6F0D, 0x9D59, 0x6F0E, 0x9D5A, 0x6F10, + 0x9D5B, 0x6F11, 0x9D5C, 0x6F12, 0x9D5D, 0x6F16, 0x9D5E, 0x6F17, + 0x9D5F, 0x6F18, 0x9D60, 0x6F19, 0x9D61, 0x6F1A, 0x9D62, 0x6F1B, + 0x9D63, 0x6F1C, 0x9D64, 0x6F1D, 0x9D65, 0x6F1E, 0x9D66, 0x6F1F, + 0x9D67, 0x6F21, 0x9D68, 0x6F22, 0x9D69, 0x6F23, 0x9D6A, 0x6F25, + 0x9D6B, 0x6F26, 0x9D6C, 0x6F27, 0x9D6D, 0x6F28, 0x9D6E, 0x6F2C, + 0x9D6F, 0x6F2E, 0x9D70, 0x6F30, 0x9D71, 0x6F32, 0x9D72, 0x6F34, + 0x9D73, 0x6F35, 0x9D74, 0x6F37, 0x9D75, 0x6F38, 0x9D76, 0x6F39, + 0x9D77, 0x6F3A, 0x9D78, 0x6F3B, 0x9D79, 0x6F3C, 0x9D7A, 0x6F3D, + 0x9D7B, 0x6F3F, 0x9D7C, 0x6F40, 0x9D7D, 0x6F41, 0x9D7E, 0x6F42, + 0x9D80, 0x6F43, 0x9D81, 0x6F44, 0x9D82, 0x6F45, 0x9D83, 0x6F48, + 0x9D84, 0x6F49, 0x9D85, 0x6F4A, 0x9D86, 0x6F4C, 0x9D87, 0x6F4E, + 0x9D88, 0x6F4F, 0x9D89, 0x6F50, 0x9D8A, 0x6F51, 0x9D8B, 0x6F52, + 0x9D8C, 0x6F53, 0x9D8D, 0x6F54, 0x9D8E, 0x6F55, 0x9D8F, 0x6F56, + 0x9D90, 0x6F57, 0x9D91, 0x6F59, 0x9D92, 0x6F5A, 0x9D93, 0x6F5B, + 0x9D94, 0x6F5D, 0x9D95, 0x6F5F, 0x9D96, 0x6F60, 0x9D97, 0x6F61, + 0x9D98, 0x6F63, 0x9D99, 0x6F64, 0x9D9A, 0x6F65, 0x9D9B, 0x6F67, + 0x9D9C, 0x6F68, 0x9D9D, 0x6F69, 0x9D9E, 0x6F6A, 0x9D9F, 0x6F6B, + 0x9DA0, 0x6F6C, 0x9DA1, 0x6F6F, 0x9DA2, 0x6F70, 0x9DA3, 0x6F71, + 0x9DA4, 0x6F73, 0x9DA5, 0x6F75, 0x9DA6, 0x6F76, 0x9DA7, 0x6F77, + 0x9DA8, 0x6F79, 0x9DA9, 0x6F7B, 0x9DAA, 0x6F7D, 0x9DAB, 0x6F7E, + 0x9DAC, 0x6F7F, 0x9DAD, 0x6F80, 0x9DAE, 0x6F81, 0x9DAF, 0x6F82, + 0x9DB0, 0x6F83, 0x9DB1, 0x6F85, 0x9DB2, 0x6F86, 0x9DB3, 0x6F87, + 0x9DB4, 0x6F8A, 0x9DB5, 0x6F8B, 0x9DB6, 0x6F8F, 0x9DB7, 0x6F90, + 0x9DB8, 0x6F91, 0x9DB9, 0x6F92, 0x9DBA, 0x6F93, 0x9DBB, 0x6F94, + 0x9DBC, 0x6F95, 0x9DBD, 0x6F96, 0x9DBE, 0x6F97, 0x9DBF, 0x6F98, + 0x9DC0, 0x6F99, 0x9DC1, 0x6F9A, 0x9DC2, 0x6F9B, 0x9DC3, 0x6F9D, + 0x9DC4, 0x6F9E, 0x9DC5, 0x6F9F, 0x9DC6, 0x6FA0, 0x9DC7, 0x6FA2, + 0x9DC8, 0x6FA3, 0x9DC9, 0x6FA4, 0x9DCA, 0x6FA5, 0x9DCB, 0x6FA6, + 0x9DCC, 0x6FA8, 0x9DCD, 0x6FA9, 0x9DCE, 0x6FAA, 0x9DCF, 0x6FAB, + 0x9DD0, 0x6FAC, 0x9DD1, 0x6FAD, 0x9DD2, 0x6FAE, 0x9DD3, 0x6FAF, + 0x9DD4, 0x6FB0, 0x9DD5, 0x6FB1, 0x9DD6, 0x6FB2, 0x9DD7, 0x6FB4, + 0x9DD8, 0x6FB5, 0x9DD9, 0x6FB7, 0x9DDA, 0x6FB8, 0x9DDB, 0x6FBA, + 0x9DDC, 0x6FBB, 0x9DDD, 0x6FBC, 0x9DDE, 0x6FBD, 0x9DDF, 0x6FBE, + 0x9DE0, 0x6FBF, 0x9DE1, 0x6FC1, 0x9DE2, 0x6FC3, 0x9DE3, 0x6FC4, + 0x9DE4, 0x6FC5, 0x9DE5, 0x6FC6, 0x9DE6, 0x6FC7, 0x9DE7, 0x6FC8, + 0x9DE8, 0x6FCA, 0x9DE9, 0x6FCB, 0x9DEA, 0x6FCC, 0x9DEB, 0x6FCD, + 0x9DEC, 0x6FCE, 0x9DED, 0x6FCF, 0x9DEE, 0x6FD0, 0x9DEF, 0x6FD3, + 0x9DF0, 0x6FD4, 0x9DF1, 0x6FD5, 0x9DF2, 0x6FD6, 0x9DF3, 0x6FD7, + 0x9DF4, 0x6FD8, 0x9DF5, 0x6FD9, 0x9DF6, 0x6FDA, 0x9DF7, 0x6FDB, + 0x9DF8, 0x6FDC, 0x9DF9, 0x6FDD, 0x9DFA, 0x6FDF, 0x9DFB, 0x6FE2, + 0x9DFC, 0x6FE3, 0x9DFD, 0x6FE4, 0x9DFE, 0x6FE5, 0x9E40, 0x6FE6, + 0x9E41, 0x6FE7, 0x9E42, 0x6FE8, 0x9E43, 0x6FE9, 0x9E44, 0x6FEA, + 0x9E45, 0x6FEB, 0x9E46, 0x6FEC, 0x9E47, 0x6FED, 0x9E48, 0x6FF0, + 0x9E49, 0x6FF1, 0x9E4A, 0x6FF2, 0x9E4B, 0x6FF3, 0x9E4C, 0x6FF4, + 0x9E4D, 0x6FF5, 0x9E4E, 0x6FF6, 0x9E4F, 0x6FF7, 0x9E50, 0x6FF8, + 0x9E51, 0x6FF9, 0x9E52, 0x6FFA, 0x9E53, 0x6FFB, 0x9E54, 0x6FFC, + 0x9E55, 0x6FFD, 0x9E56, 0x6FFE, 0x9E57, 0x6FFF, 0x9E58, 0x7000, + 0x9E59, 0x7001, 0x9E5A, 0x7002, 0x9E5B, 0x7003, 0x9E5C, 0x7004, + 0x9E5D, 0x7005, 0x9E5E, 0x7006, 0x9E5F, 0x7007, 0x9E60, 0x7008, + 0x9E61, 0x7009, 0x9E62, 0x700A, 0x9E63, 0x700B, 0x9E64, 0x700C, + 0x9E65, 0x700D, 0x9E66, 0x700E, 0x9E67, 0x700F, 0x9E68, 0x7010, + 0x9E69, 0x7012, 0x9E6A, 0x7013, 0x9E6B, 0x7014, 0x9E6C, 0x7015, + 0x9E6D, 0x7016, 0x9E6E, 0x7017, 0x9E6F, 0x7018, 0x9E70, 0x7019, + 0x9E71, 0x701C, 0x9E72, 0x701D, 0x9E73, 0x701E, 0x9E74, 0x701F, + 0x9E75, 0x7020, 0x9E76, 0x7021, 0x9E77, 0x7022, 0x9E78, 0x7024, + 0x9E79, 0x7025, 0x9E7A, 0x7026, 0x9E7B, 0x7027, 0x9E7C, 0x7028, + 0x9E7D, 0x7029, 0x9E7E, 0x702A, 0x9E80, 0x702B, 0x9E81, 0x702C, + 0x9E82, 0x702D, 0x9E83, 0x702E, 0x9E84, 0x702F, 0x9E85, 0x7030, + 0x9E86, 0x7031, 0x9E87, 0x7032, 0x9E88, 0x7033, 0x9E89, 0x7034, + 0x9E8A, 0x7036, 0x9E8B, 0x7037, 0x9E8C, 0x7038, 0x9E8D, 0x703A, + 0x9E8E, 0x703B, 0x9E8F, 0x703C, 0x9E90, 0x703D, 0x9E91, 0x703E, + 0x9E92, 0x703F, 0x9E93, 0x7040, 0x9E94, 0x7041, 0x9E95, 0x7042, + 0x9E96, 0x7043, 0x9E97, 0x7044, 0x9E98, 0x7045, 0x9E99, 0x7046, + 0x9E9A, 0x7047, 0x9E9B, 0x7048, 0x9E9C, 0x7049, 0x9E9D, 0x704A, + 0x9E9E, 0x704B, 0x9E9F, 0x704D, 0x9EA0, 0x704E, 0x9EA1, 0x7050, + 0x9EA2, 0x7051, 0x9EA3, 0x7052, 0x9EA4, 0x7053, 0x9EA5, 0x7054, + 0x9EA6, 0x7055, 0x9EA7, 0x7056, 0x9EA8, 0x7057, 0x9EA9, 0x7058, + 0x9EAA, 0x7059, 0x9EAB, 0x705A, 0x9EAC, 0x705B, 0x9EAD, 0x705C, + 0x9EAE, 0x705D, 0x9EAF, 0x705F, 0x9EB0, 0x7060, 0x9EB1, 0x7061, + 0x9EB2, 0x7062, 0x9EB3, 0x7063, 0x9EB4, 0x7064, 0x9EB5, 0x7065, + 0x9EB6, 0x7066, 0x9EB7, 0x7067, 0x9EB8, 0x7068, 0x9EB9, 0x7069, + 0x9EBA, 0x706A, 0x9EBB, 0x706E, 0x9EBC, 0x7071, 0x9EBD, 0x7072, + 0x9EBE, 0x7073, 0x9EBF, 0x7074, 0x9EC0, 0x7077, 0x9EC1, 0x7079, + 0x9EC2, 0x707A, 0x9EC3, 0x707B, 0x9EC4, 0x707D, 0x9EC5, 0x7081, + 0x9EC6, 0x7082, 0x9EC7, 0x7083, 0x9EC8, 0x7084, 0x9EC9, 0x7086, + 0x9ECA, 0x7087, 0x9ECB, 0x7088, 0x9ECC, 0x708B, 0x9ECD, 0x708C, + 0x9ECE, 0x708D, 0x9ECF, 0x708F, 0x9ED0, 0x7090, 0x9ED1, 0x7091, + 0x9ED2, 0x7093, 0x9ED3, 0x7097, 0x9ED4, 0x7098, 0x9ED5, 0x709A, + 0x9ED6, 0x709B, 0x9ED7, 0x709E, 0x9ED8, 0x709F, 0x9ED9, 0x70A0, + 0x9EDA, 0x70A1, 0x9EDB, 0x70A2, 0x9EDC, 0x70A3, 0x9EDD, 0x70A4, + 0x9EDE, 0x70A5, 0x9EDF, 0x70A6, 0x9EE0, 0x70A7, 0x9EE1, 0x70A8, + 0x9EE2, 0x70A9, 0x9EE3, 0x70AA, 0x9EE4, 0x70B0, 0x9EE5, 0x70B2, + 0x9EE6, 0x70B4, 0x9EE7, 0x70B5, 0x9EE8, 0x70B6, 0x9EE9, 0x70BA, + 0x9EEA, 0x70BE, 0x9EEB, 0x70BF, 0x9EEC, 0x70C4, 0x9EED, 0x70C5, + 0x9EEE, 0x70C6, 0x9EEF, 0x70C7, 0x9EF0, 0x70C9, 0x9EF1, 0x70CB, + 0x9EF2, 0x70CC, 0x9EF3, 0x70CD, 0x9EF4, 0x70CE, 0x9EF5, 0x70CF, + 0x9EF6, 0x70D0, 0x9EF7, 0x70D1, 0x9EF8, 0x70D2, 0x9EF9, 0x70D3, + 0x9EFA, 0x70D4, 0x9EFB, 0x70D5, 0x9EFC, 0x70D6, 0x9EFD, 0x70D7, + 0x9EFE, 0x70DA, 0x9F40, 0x70DC, 0x9F41, 0x70DD, 0x9F42, 0x70DE, + 0x9F43, 0x70E0, 0x9F44, 0x70E1, 0x9F45, 0x70E2, 0x9F46, 0x70E3, + 0x9F47, 0x70E5, 0x9F48, 0x70EA, 0x9F49, 0x70EE, 0x9F4A, 0x70F0, + 0x9F4B, 0x70F1, 0x9F4C, 0x70F2, 0x9F4D, 0x70F3, 0x9F4E, 0x70F4, + 0x9F4F, 0x70F5, 0x9F50, 0x70F6, 0x9F51, 0x70F8, 0x9F52, 0x70FA, + 0x9F53, 0x70FB, 0x9F54, 0x70FC, 0x9F55, 0x70FE, 0x9F56, 0x70FF, + 0x9F57, 0x7100, 0x9F58, 0x7101, 0x9F59, 0x7102, 0x9F5A, 0x7103, + 0x9F5B, 0x7104, 0x9F5C, 0x7105, 0x9F5D, 0x7106, 0x9F5E, 0x7107, + 0x9F5F, 0x7108, 0x9F60, 0x710B, 0x9F61, 0x710C, 0x9F62, 0x710D, + 0x9F63, 0x710E, 0x9F64, 0x710F, 0x9F65, 0x7111, 0x9F66, 0x7112, + 0x9F67, 0x7114, 0x9F68, 0x7117, 0x9F69, 0x711B, 0x9F6A, 0x711C, + 0x9F6B, 0x711D, 0x9F6C, 0x711E, 0x9F6D, 0x711F, 0x9F6E, 0x7120, + 0x9F6F, 0x7121, 0x9F70, 0x7122, 0x9F71, 0x7123, 0x9F72, 0x7124, + 0x9F73, 0x7125, 0x9F74, 0x7127, 0x9F75, 0x7128, 0x9F76, 0x7129, + 0x9F77, 0x712A, 0x9F78, 0x712B, 0x9F79, 0x712C, 0x9F7A, 0x712D, + 0x9F7B, 0x712E, 0x9F7C, 0x7132, 0x9F7D, 0x7133, 0x9F7E, 0x7134, + 0x9F80, 0x7135, 0x9F81, 0x7137, 0x9F82, 0x7138, 0x9F83, 0x7139, + 0x9F84, 0x713A, 0x9F85, 0x713B, 0x9F86, 0x713C, 0x9F87, 0x713D, + 0x9F88, 0x713E, 0x9F89, 0x713F, 0x9F8A, 0x7140, 0x9F8B, 0x7141, + 0x9F8C, 0x7142, 0x9F8D, 0x7143, 0x9F8E, 0x7144, 0x9F8F, 0x7146, + 0x9F90, 0x7147, 0x9F91, 0x7148, 0x9F92, 0x7149, 0x9F93, 0x714B, + 0x9F94, 0x714D, 0x9F95, 0x714F, 0x9F96, 0x7150, 0x9F97, 0x7151, + 0x9F98, 0x7152, 0x9F99, 0x7153, 0x9F9A, 0x7154, 0x9F9B, 0x7155, + 0x9F9C, 0x7156, 0x9F9D, 0x7157, 0x9F9E, 0x7158, 0x9F9F, 0x7159, + 0x9FA0, 0x715A, 0x9FA1, 0x715B, 0x9FA2, 0x715D, 0x9FA3, 0x715F, + 0x9FA4, 0x7160, 0x9FA5, 0x7161, 0x9FA6, 0x7162, 0x9FA7, 0x7163, + 0x9FA8, 0x7165, 0x9FA9, 0x7169, 0x9FAA, 0x716A, 0x9FAB, 0x716B, + 0x9FAC, 0x716C, 0x9FAD, 0x716D, 0x9FAE, 0x716F, 0x9FAF, 0x7170, + 0x9FB0, 0x7171, 0x9FB1, 0x7174, 0x9FB2, 0x7175, 0x9FB3, 0x7176, + 0x9FB4, 0x7177, 0x9FB5, 0x7179, 0x9FB6, 0x717B, 0x9FB7, 0x717C, + 0x9FB8, 0x717E, 0x9FB9, 0x717F, 0x9FBA, 0x7180, 0x9FBB, 0x7181, + 0x9FBC, 0x7182, 0x9FBD, 0x7183, 0x9FBE, 0x7185, 0x9FBF, 0x7186, + 0x9FC0, 0x7187, 0x9FC1, 0x7188, 0x9FC2, 0x7189, 0x9FC3, 0x718B, + 0x9FC4, 0x718C, 0x9FC5, 0x718D, 0x9FC6, 0x718E, 0x9FC7, 0x7190, + 0x9FC8, 0x7191, 0x9FC9, 0x7192, 0x9FCA, 0x7193, 0x9FCB, 0x7195, + 0x9FCC, 0x7196, 0x9FCD, 0x7197, 0x9FCE, 0x719A, 0x9FCF, 0x719B, + 0x9FD0, 0x719C, 0x9FD1, 0x719D, 0x9FD2, 0x719E, 0x9FD3, 0x71A1, + 0x9FD4, 0x71A2, 0x9FD5, 0x71A3, 0x9FD6, 0x71A4, 0x9FD7, 0x71A5, + 0x9FD8, 0x71A6, 0x9FD9, 0x71A7, 0x9FDA, 0x71A9, 0x9FDB, 0x71AA, + 0x9FDC, 0x71AB, 0x9FDD, 0x71AD, 0x9FDE, 0x71AE, 0x9FDF, 0x71AF, + 0x9FE0, 0x71B0, 0x9FE1, 0x71B1, 0x9FE2, 0x71B2, 0x9FE3, 0x71B4, + 0x9FE4, 0x71B6, 0x9FE5, 0x71B7, 0x9FE6, 0x71B8, 0x9FE7, 0x71BA, + 0x9FE8, 0x71BB, 0x9FE9, 0x71BC, 0x9FEA, 0x71BD, 0x9FEB, 0x71BE, + 0x9FEC, 0x71BF, 0x9FED, 0x71C0, 0x9FEE, 0x71C1, 0x9FEF, 0x71C2, + 0x9FF0, 0x71C4, 0x9FF1, 0x71C5, 0x9FF2, 0x71C6, 0x9FF3, 0x71C7, + 0x9FF4, 0x71C8, 0x9FF5, 0x71C9, 0x9FF6, 0x71CA, 0x9FF7, 0x71CB, + 0x9FF8, 0x71CC, 0x9FF9, 0x71CD, 0x9FFA, 0x71CF, 0x9FFB, 0x71D0, + 0x9FFC, 0x71D1, 0x9FFD, 0x71D2, 0x9FFE, 0x71D3, 0xA040, 0x71D6, + 0xA041, 0x71D7, 0xA042, 0x71D8, 0xA043, 0x71D9, 0xA044, 0x71DA, + 0xA045, 0x71DB, 0xA046, 0x71DC, 0xA047, 0x71DD, 0xA048, 0x71DE, + 0xA049, 0x71DF, 0xA04A, 0x71E1, 0xA04B, 0x71E2, 0xA04C, 0x71E3, + 0xA04D, 0x71E4, 0xA04E, 0x71E6, 0xA04F, 0x71E8, 0xA050, 0x71E9, + 0xA051, 0x71EA, 0xA052, 0x71EB, 0xA053, 0x71EC, 0xA054, 0x71ED, + 0xA055, 0x71EF, 0xA056, 0x71F0, 0xA057, 0x71F1, 0xA058, 0x71F2, + 0xA059, 0x71F3, 0xA05A, 0x71F4, 0xA05B, 0x71F5, 0xA05C, 0x71F6, + 0xA05D, 0x71F7, 0xA05E, 0x71F8, 0xA05F, 0x71FA, 0xA060, 0x71FB, + 0xA061, 0x71FC, 0xA062, 0x71FD, 0xA063, 0x71FE, 0xA064, 0x71FF, + 0xA065, 0x7200, 0xA066, 0x7201, 0xA067, 0x7202, 0xA068, 0x7203, + 0xA069, 0x7204, 0xA06A, 0x7205, 0xA06B, 0x7207, 0xA06C, 0x7208, + 0xA06D, 0x7209, 0xA06E, 0x720A, 0xA06F, 0x720B, 0xA070, 0x720C, + 0xA071, 0x720D, 0xA072, 0x720E, 0xA073, 0x720F, 0xA074, 0x7210, + 0xA075, 0x7211, 0xA076, 0x7212, 0xA077, 0x7213, 0xA078, 0x7214, + 0xA079, 0x7215, 0xA07A, 0x7216, 0xA07B, 0x7217, 0xA07C, 0x7218, + 0xA07D, 0x7219, 0xA07E, 0x721A, 0xA080, 0x721B, 0xA081, 0x721C, + 0xA082, 0x721E, 0xA083, 0x721F, 0xA084, 0x7220, 0xA085, 0x7221, + 0xA086, 0x7222, 0xA087, 0x7223, 0xA088, 0x7224, 0xA089, 0x7225, + 0xA08A, 0x7226, 0xA08B, 0x7227, 0xA08C, 0x7229, 0xA08D, 0x722B, + 0xA08E, 0x722D, 0xA08F, 0x722E, 0xA090, 0x722F, 0xA091, 0x7232, + 0xA092, 0x7233, 0xA093, 0x7234, 0xA094, 0x723A, 0xA095, 0x723C, + 0xA096, 0x723E, 0xA097, 0x7240, 0xA098, 0x7241, 0xA099, 0x7242, + 0xA09A, 0x7243, 0xA09B, 0x7244, 0xA09C, 0x7245, 0xA09D, 0x7246, + 0xA09E, 0x7249, 0xA09F, 0x724A, 0xA0A0, 0x724B, 0xA0A1, 0x724E, + 0xA0A2, 0x724F, 0xA0A3, 0x7250, 0xA0A4, 0x7251, 0xA0A5, 0x7253, + 0xA0A6, 0x7254, 0xA0A7, 0x7255, 0xA0A8, 0x7257, 0xA0A9, 0x7258, + 0xA0AA, 0x725A, 0xA0AB, 0x725C, 0xA0AC, 0x725E, 0xA0AD, 0x7260, + 0xA0AE, 0x7263, 0xA0AF, 0x7264, 0xA0B0, 0x7265, 0xA0B1, 0x7268, + 0xA0B2, 0x726A, 0xA0B3, 0x726B, 0xA0B4, 0x726C, 0xA0B5, 0x726D, + 0xA0B6, 0x7270, 0xA0B7, 0x7271, 0xA0B8, 0x7273, 0xA0B9, 0x7274, + 0xA0BA, 0x7276, 0xA0BB, 0x7277, 0xA0BC, 0x7278, 0xA0BD, 0x727B, + 0xA0BE, 0x727C, 0xA0BF, 0x727D, 0xA0C0, 0x7282, 0xA0C1, 0x7283, + 0xA0C2, 0x7285, 0xA0C3, 0x7286, 0xA0C4, 0x7287, 0xA0C5, 0x7288, + 0xA0C6, 0x7289, 0xA0C7, 0x728C, 0xA0C8, 0x728E, 0xA0C9, 0x7290, + 0xA0CA, 0x7291, 0xA0CB, 0x7293, 0xA0CC, 0x7294, 0xA0CD, 0x7295, + 0xA0CE, 0x7296, 0xA0CF, 0x7297, 0xA0D0, 0x7298, 0xA0D1, 0x7299, + 0xA0D2, 0x729A, 0xA0D3, 0x729B, 0xA0D4, 0x729C, 0xA0D5, 0x729D, + 0xA0D6, 0x729E, 0xA0D7, 0x72A0, 0xA0D8, 0x72A1, 0xA0D9, 0x72A2, + 0xA0DA, 0x72A3, 0xA0DB, 0x72A4, 0xA0DC, 0x72A5, 0xA0DD, 0x72A6, + 0xA0DE, 0x72A7, 0xA0DF, 0x72A8, 0xA0E0, 0x72A9, 0xA0E1, 0x72AA, + 0xA0E2, 0x72AB, 0xA0E3, 0x72AE, 0xA0E4, 0x72B1, 0xA0E5, 0x72B2, + 0xA0E6, 0x72B3, 0xA0E7, 0x72B5, 0xA0E8, 0x72BA, 0xA0E9, 0x72BB, + 0xA0EA, 0x72BC, 0xA0EB, 0x72BD, 0xA0EC, 0x72BE, 0xA0ED, 0x72BF, + 0xA0EE, 0x72C0, 0xA0EF, 0x72C5, 0xA0F0, 0x72C6, 0xA0F1, 0x72C7, + 0xA0F2, 0x72C9, 0xA0F3, 0x72CA, 0xA0F4, 0x72CB, 0xA0F5, 0x72CC, + 0xA0F6, 0x72CF, 0xA0F7, 0x72D1, 0xA0F8, 0x72D3, 0xA0F9, 0x72D4, + 0xA0FA, 0x72D5, 0xA0FB, 0x72D6, 0xA0FC, 0x72D8, 0xA0FD, 0x72DA, + 0xA0FE, 0x72DB, 0xA1A1, 0x3000, 0xA1A2, 0x3001, 0xA1A3, 0x3002, + 0xA1A4, 0x00B7, 0xA1A5, 0x02C9, 0xA1A6, 0x02C7, 0xA1A7, 0x00A8, + 0xA1A8, 0x3003, 0xA1A9, 0x3005, 0xA1AA, 0x2014, 0xA1AB, 0xFF5E, + 0xA1AC, 0x2016, 0xA1AD, 0x2026, 0xA1AE, 0x2018, 0xA1AF, 0x2019, + 0xA1B0, 0x201C, 0xA1B1, 0x201D, 0xA1B2, 0x3014, 0xA1B3, 0x3015, + 0xA1B4, 0x3008, 0xA1B5, 0x3009, 0xA1B6, 0x300A, 0xA1B7, 0x300B, + 0xA1B8, 0x300C, 0xA1B9, 0x300D, 0xA1BA, 0x300E, 0xA1BB, 0x300F, + 0xA1BC, 0x3016, 0xA1BD, 0x3017, 0xA1BE, 0x3010, 0xA1BF, 0x3011, + 0xA1C0, 0x00B1, 0xA1C1, 0x00D7, 0xA1C2, 0x00F7, 0xA1C3, 0x2236, + 0xA1C4, 0x2227, 0xA1C5, 0x2228, 0xA1C6, 0x2211, 0xA1C7, 0x220F, + 0xA1C8, 0x222A, 0xA1C9, 0x2229, 0xA1CA, 0x2208, 0xA1CB, 0x2237, + 0xA1CC, 0x221A, 0xA1CD, 0x22A5, 0xA1CE, 0x2225, 0xA1CF, 0x2220, + 0xA1D0, 0x2312, 0xA1D1, 0x2299, 0xA1D2, 0x222B, 0xA1D3, 0x222E, + 0xA1D4, 0x2261, 0xA1D5, 0x224C, 0xA1D6, 0x2248, 0xA1D7, 0x223D, + 0xA1D8, 0x221D, 0xA1D9, 0x2260, 0xA1DA, 0x226E, 0xA1DB, 0x226F, + 0xA1DC, 0x2264, 0xA1DD, 0x2265, 0xA1DE, 0x221E, 0xA1DF, 0x2235, + 0xA1E0, 0x2234, 0xA1E1, 0x2642, 0xA1E2, 0x2640, 0xA1E3, 0x00B0, + 0xA1E4, 0x2032, 0xA1E5, 0x2033, 0xA1E6, 0x2103, 0xA1E7, 0xFF04, + 0xA1E8, 0x00A4, 0xA1E9, 0xFFE0, 0xA1EA, 0xFFE1, 0xA1EB, 0x2030, + 0xA1EC, 0x00A7, 0xA1ED, 0x2116, 0xA1EE, 0x2606, 0xA1EF, 0x2605, + 0xA1F0, 0x25CB, 0xA1F1, 0x25CF, 0xA1F2, 0x25CE, 0xA1F3, 0x25C7, + 0xA1F4, 0x25C6, 0xA1F5, 0x25A1, 0xA1F6, 0x25A0, 0xA1F7, 0x25B3, + 0xA1F8, 0x25B2, 0xA1F9, 0x203B, 0xA1FA, 0x2192, 0xA1FB, 0x2190, + 0xA1FC, 0x2191, 0xA1FD, 0x2193, 0xA1FE, 0x3013, 0xA2A1, 0x2170, + 0xA2A2, 0x2171, 0xA2A3, 0x2172, 0xA2A4, 0x2173, 0xA2A5, 0x2174, + 0xA2A6, 0x2175, 0xA2A7, 0x2176, 0xA2A8, 0x2177, 0xA2A9, 0x2178, + 0xA2AA, 0x2179, 0xA2B1, 0x2488, 0xA2B2, 0x2489, 0xA2B3, 0x248A, + 0xA2B4, 0x248B, 0xA2B5, 0x248C, 0xA2B6, 0x248D, 0xA2B7, 0x248E, + 0xA2B8, 0x248F, 0xA2B9, 0x2490, 0xA2BA, 0x2491, 0xA2BB, 0x2492, + 0xA2BC, 0x2493, 0xA2BD, 0x2494, 0xA2BE, 0x2495, 0xA2BF, 0x2496, + 0xA2C0, 0x2497, 0xA2C1, 0x2498, 0xA2C2, 0x2499, 0xA2C3, 0x249A, + 0xA2C4, 0x249B, 0xA2C5, 0x2474, 0xA2C6, 0x2475, 0xA2C7, 0x2476, + 0xA2C8, 0x2477, 0xA2C9, 0x2478, 0xA2CA, 0x2479, 0xA2CB, 0x247A, + 0xA2CC, 0x247B, 0xA2CD, 0x247C, 0xA2CE, 0x247D, 0xA2CF, 0x247E, + 0xA2D0, 0x247F, 0xA2D1, 0x2480, 0xA2D2, 0x2481, 0xA2D3, 0x2482, + 0xA2D4, 0x2483, 0xA2D5, 0x2484, 0xA2D6, 0x2485, 0xA2D7, 0x2486, + 0xA2D8, 0x2487, 0xA2D9, 0x2460, 0xA2DA, 0x2461, 0xA2DB, 0x2462, + 0xA2DC, 0x2463, 0xA2DD, 0x2464, 0xA2DE, 0x2465, 0xA2DF, 0x2466, + 0xA2E0, 0x2467, 0xA2E1, 0x2468, 0xA2E2, 0x2469, 0xA2E5, 0x3220, + 0xA2E6, 0x3221, 0xA2E7, 0x3222, 0xA2E8, 0x3223, 0xA2E9, 0x3224, + 0xA2EA, 0x3225, 0xA2EB, 0x3226, 0xA2EC, 0x3227, 0xA2ED, 0x3228, + 0xA2EE, 0x3229, 0xA2F1, 0x2160, 0xA2F2, 0x2161, 0xA2F3, 0x2162, + 0xA2F4, 0x2163, 0xA2F5, 0x2164, 0xA2F6, 0x2165, 0xA2F7, 0x2166, + 0xA2F8, 0x2167, 0xA2F9, 0x2168, 0xA2FA, 0x2169, 0xA2FB, 0x216A, + 0xA2FC, 0x216B, 0xA3A1, 0xFF01, 0xA3A2, 0xFF02, 0xA3A3, 0xFF03, + 0xA3A4, 0xFFE5, 0xA3A5, 0xFF05, 0xA3A6, 0xFF06, 0xA3A7, 0xFF07, + 0xA3A8, 0xFF08, 0xA3A9, 0xFF09, 0xA3AA, 0xFF0A, 0xA3AB, 0xFF0B, + 0xA3AC, 0xFF0C, 0xA3AD, 0xFF0D, 0xA3AE, 0xFF0E, 0xA3AF, 0xFF0F, + 0xA3B0, 0xFF10, 0xA3B1, 0xFF11, 0xA3B2, 0xFF12, 0xA3B3, 0xFF13, + 0xA3B4, 0xFF14, 0xA3B5, 0xFF15, 0xA3B6, 0xFF16, 0xA3B7, 0xFF17, + 0xA3B8, 0xFF18, 0xA3B9, 0xFF19, 0xA3BA, 0xFF1A, 0xA3BB, 0xFF1B, + 0xA3BC, 0xFF1C, 0xA3BD, 0xFF1D, 0xA3BE, 0xFF1E, 0xA3BF, 0xFF1F, + 0xA3C0, 0xFF20, 0xA3C1, 0xFF21, 0xA3C2, 0xFF22, 0xA3C3, 0xFF23, + 0xA3C4, 0xFF24, 0xA3C5, 0xFF25, 0xA3C6, 0xFF26, 0xA3C7, 0xFF27, + 0xA3C8, 0xFF28, 0xA3C9, 0xFF29, 0xA3CA, 0xFF2A, 0xA3CB, 0xFF2B, + 0xA3CC, 0xFF2C, 0xA3CD, 0xFF2D, 0xA3CE, 0xFF2E, 0xA3CF, 0xFF2F, + 0xA3D0, 0xFF30, 0xA3D1, 0xFF31, 0xA3D2, 0xFF32, 0xA3D3, 0xFF33, + 0xA3D4, 0xFF34, 0xA3D5, 0xFF35, 0xA3D6, 0xFF36, 0xA3D7, 0xFF37, + 0xA3D8, 0xFF38, 0xA3D9, 0xFF39, 0xA3DA, 0xFF3A, 0xA3DB, 0xFF3B, + 0xA3DC, 0xFF3C, 0xA3DD, 0xFF3D, 0xA3DE, 0xFF3E, 0xA3DF, 0xFF3F, + 0xA3E0, 0xFF40, 0xA3E1, 0xFF41, 0xA3E2, 0xFF42, 0xA3E3, 0xFF43, + 0xA3E4, 0xFF44, 0xA3E5, 0xFF45, 0xA3E6, 0xFF46, 0xA3E7, 0xFF47, + 0xA3E8, 0xFF48, 0xA3E9, 0xFF49, 0xA3EA, 0xFF4A, 0xA3EB, 0xFF4B, + 0xA3EC, 0xFF4C, 0xA3ED, 0xFF4D, 0xA3EE, 0xFF4E, 0xA3EF, 0xFF4F, + 0xA3F0, 0xFF50, 0xA3F1, 0xFF51, 0xA3F2, 0xFF52, 0xA3F3, 0xFF53, + 0xA3F4, 0xFF54, 0xA3F5, 0xFF55, 0xA3F6, 0xFF56, 0xA3F7, 0xFF57, + 0xA3F8, 0xFF58, 0xA3F9, 0xFF59, 0xA3FA, 0xFF5A, 0xA3FB, 0xFF5B, + 0xA3FC, 0xFF5C, 0xA3FD, 0xFF5D, 0xA3FE, 0xFFE3, 0xA4A1, 0x3041, + 0xA4A2, 0x3042, 0xA4A3, 0x3043, 0xA4A4, 0x3044, 0xA4A5, 0x3045, + 0xA4A6, 0x3046, 0xA4A7, 0x3047, 0xA4A8, 0x3048, 0xA4A9, 0x3049, + 0xA4AA, 0x304A, 0xA4AB, 0x304B, 0xA4AC, 0x304C, 0xA4AD, 0x304D, + 0xA4AE, 0x304E, 0xA4AF, 0x304F, 0xA4B0, 0x3050, 0xA4B1, 0x3051, + 0xA4B2, 0x3052, 0xA4B3, 0x3053, 0xA4B4, 0x3054, 0xA4B5, 0x3055, + 0xA4B6, 0x3056, 0xA4B7, 0x3057, 0xA4B8, 0x3058, 0xA4B9, 0x3059, + 0xA4BA, 0x305A, 0xA4BB, 0x305B, 0xA4BC, 0x305C, 0xA4BD, 0x305D, + 0xA4BE, 0x305E, 0xA4BF, 0x305F, 0xA4C0, 0x3060, 0xA4C1, 0x3061, + 0xA4C2, 0x3062, 0xA4C3, 0x3063, 0xA4C4, 0x3064, 0xA4C5, 0x3065, + 0xA4C6, 0x3066, 0xA4C7, 0x3067, 0xA4C8, 0x3068, 0xA4C9, 0x3069, + 0xA4CA, 0x306A, 0xA4CB, 0x306B, 0xA4CC, 0x306C, 0xA4CD, 0x306D, + 0xA4CE, 0x306E, 0xA4CF, 0x306F, 0xA4D0, 0x3070, 0xA4D1, 0x3071, + 0xA4D2, 0x3072, 0xA4D3, 0x3073, 0xA4D4, 0x3074, 0xA4D5, 0x3075, + 0xA4D6, 0x3076, 0xA4D7, 0x3077, 0xA4D8, 0x3078, 0xA4D9, 0x3079, + 0xA4DA, 0x307A, 0xA4DB, 0x307B, 0xA4DC, 0x307C, 0xA4DD, 0x307D, + 0xA4DE, 0x307E, 0xA4DF, 0x307F, 0xA4E0, 0x3080, 0xA4E1, 0x3081, + 0xA4E2, 0x3082, 0xA4E3, 0x3083, 0xA4E4, 0x3084, 0xA4E5, 0x3085, + 0xA4E6, 0x3086, 0xA4E7, 0x3087, 0xA4E8, 0x3088, 0xA4E9, 0x3089, + 0xA4EA, 0x308A, 0xA4EB, 0x308B, 0xA4EC, 0x308C, 0xA4ED, 0x308D, + 0xA4EE, 0x308E, 0xA4EF, 0x308F, 0xA4F0, 0x3090, 0xA4F1, 0x3091, + 0xA4F2, 0x3092, 0xA4F3, 0x3093, 0xA5A1, 0x30A1, 0xA5A2, 0x30A2, + 0xA5A3, 0x30A3, 0xA5A4, 0x30A4, 0xA5A5, 0x30A5, 0xA5A6, 0x30A6, + 0xA5A7, 0x30A7, 0xA5A8, 0x30A8, 0xA5A9, 0x30A9, 0xA5AA, 0x30AA, + 0xA5AB, 0x30AB, 0xA5AC, 0x30AC, 0xA5AD, 0x30AD, 0xA5AE, 0x30AE, + 0xA5AF, 0x30AF, 0xA5B0, 0x30B0, 0xA5B1, 0x30B1, 0xA5B2, 0x30B2, + 0xA5B3, 0x30B3, 0xA5B4, 0x30B4, 0xA5B5, 0x30B5, 0xA5B6, 0x30B6, + 0xA5B7, 0x30B7, 0xA5B8, 0x30B8, 0xA5B9, 0x30B9, 0xA5BA, 0x30BA, + 0xA5BB, 0x30BB, 0xA5BC, 0x30BC, 0xA5BD, 0x30BD, 0xA5BE, 0x30BE, + 0xA5BF, 0x30BF, 0xA5C0, 0x30C0, 0xA5C1, 0x30C1, 0xA5C2, 0x30C2, + 0xA5C3, 0x30C3, 0xA5C4, 0x30C4, 0xA5C5, 0x30C5, 0xA5C6, 0x30C6, + 0xA5C7, 0x30C7, 0xA5C8, 0x30C8, 0xA5C9, 0x30C9, 0xA5CA, 0x30CA, + 0xA5CB, 0x30CB, 0xA5CC, 0x30CC, 0xA5CD, 0x30CD, 0xA5CE, 0x30CE, + 0xA5CF, 0x30CF, 0xA5D0, 0x30D0, 0xA5D1, 0x30D1, 0xA5D2, 0x30D2, + 0xA5D3, 0x30D3, 0xA5D4, 0x30D4, 0xA5D5, 0x30D5, 0xA5D6, 0x30D6, + 0xA5D7, 0x30D7, 0xA5D8, 0x30D8, 0xA5D9, 0x30D9, 0xA5DA, 0x30DA, + 0xA5DB, 0x30DB, 0xA5DC, 0x30DC, 0xA5DD, 0x30DD, 0xA5DE, 0x30DE, + 0xA5DF, 0x30DF, 0xA5E0, 0x30E0, 0xA5E1, 0x30E1, 0xA5E2, 0x30E2, + 0xA5E3, 0x30E3, 0xA5E4, 0x30E4, 0xA5E5, 0x30E5, 0xA5E6, 0x30E6, + 0xA5E7, 0x30E7, 0xA5E8, 0x30E8, 0xA5E9, 0x30E9, 0xA5EA, 0x30EA, + 0xA5EB, 0x30EB, 0xA5EC, 0x30EC, 0xA5ED, 0x30ED, 0xA5EE, 0x30EE, + 0xA5EF, 0x30EF, 0xA5F0, 0x30F0, 0xA5F1, 0x30F1, 0xA5F2, 0x30F2, + 0xA5F3, 0x30F3, 0xA5F4, 0x30F4, 0xA5F5, 0x30F5, 0xA5F6, 0x30F6, + 0xA6A1, 0x0391, 0xA6A2, 0x0392, 0xA6A3, 0x0393, 0xA6A4, 0x0394, + 0xA6A5, 0x0395, 0xA6A6, 0x0396, 0xA6A7, 0x0397, 0xA6A8, 0x0398, + 0xA6A9, 0x0399, 0xA6AA, 0x039A, 0xA6AB, 0x039B, 0xA6AC, 0x039C, + 0xA6AD, 0x039D, 0xA6AE, 0x039E, 0xA6AF, 0x039F, 0xA6B0, 0x03A0, + 0xA6B1, 0x03A1, 0xA6B2, 0x03A3, 0xA6B3, 0x03A4, 0xA6B4, 0x03A5, + 0xA6B5, 0x03A6, 0xA6B6, 0x03A7, 0xA6B7, 0x03A8, 0xA6B8, 0x03A9, + 0xA6C1, 0x03B1, 0xA6C2, 0x03B2, 0xA6C3, 0x03B3, 0xA6C4, 0x03B4, + 0xA6C5, 0x03B5, 0xA6C6, 0x03B6, 0xA6C7, 0x03B7, 0xA6C8, 0x03B8, + 0xA6C9, 0x03B9, 0xA6CA, 0x03BA, 0xA6CB, 0x03BB, 0xA6CC, 0x03BC, + 0xA6CD, 0x03BD, 0xA6CE, 0x03BE, 0xA6CF, 0x03BF, 0xA6D0, 0x03C0, + 0xA6D1, 0x03C1, 0xA6D2, 0x03C3, 0xA6D3, 0x03C4, 0xA6D4, 0x03C5, + 0xA6D5, 0x03C6, 0xA6D6, 0x03C7, 0xA6D7, 0x03C8, 0xA6D8, 0x03C9, + 0xA6E0, 0xFE35, 0xA6E1, 0xFE36, 0xA6E2, 0xFE39, 0xA6E3, 0xFE3A, + 0xA6E4, 0xFE3F, 0xA6E5, 0xFE40, 0xA6E6, 0xFE3D, 0xA6E7, 0xFE3E, + 0xA6E8, 0xFE41, 0xA6E9, 0xFE42, 0xA6EA, 0xFE43, 0xA6EB, 0xFE44, + 0xA6EE, 0xFE3B, 0xA6EF, 0xFE3C, 0xA6F0, 0xFE37, 0xA6F1, 0xFE38, + 0xA6F2, 0xFE31, 0xA6F4, 0xFE33, 0xA6F5, 0xFE34, 0xA7A1, 0x0410, + 0xA7A2, 0x0411, 0xA7A3, 0x0412, 0xA7A4, 0x0413, 0xA7A5, 0x0414, + 0xA7A6, 0x0415, 0xA7A7, 0x0401, 0xA7A8, 0x0416, 0xA7A9, 0x0417, + 0xA7AA, 0x0418, 0xA7AB, 0x0419, 0xA7AC, 0x041A, 0xA7AD, 0x041B, + 0xA7AE, 0x041C, 0xA7AF, 0x041D, 0xA7B0, 0x041E, 0xA7B1, 0x041F, + 0xA7B2, 0x0420, 0xA7B3, 0x0421, 0xA7B4, 0x0422, 0xA7B5, 0x0423, + 0xA7B6, 0x0424, 0xA7B7, 0x0425, 0xA7B8, 0x0426, 0xA7B9, 0x0427, + 0xA7BA, 0x0428, 0xA7BB, 0x0429, 0xA7BC, 0x042A, 0xA7BD, 0x042B, + 0xA7BE, 0x042C, 0xA7BF, 0x042D, 0xA7C0, 0x042E, 0xA7C1, 0x042F, + 0xA7D1, 0x0430, 0xA7D2, 0x0431, 0xA7D3, 0x0432, 0xA7D4, 0x0433, + 0xA7D5, 0x0434, 0xA7D6, 0x0435, 0xA7D7, 0x0451, 0xA7D8, 0x0436, + 0xA7D9, 0x0437, 0xA7DA, 0x0438, 0xA7DB, 0x0439, 0xA7DC, 0x043A, + 0xA7DD, 0x043B, 0xA7DE, 0x043C, 0xA7DF, 0x043D, 0xA7E0, 0x043E, + 0xA7E1, 0x043F, 0xA7E2, 0x0440, 0xA7E3, 0x0441, 0xA7E4, 0x0442, + 0xA7E5, 0x0443, 0xA7E6, 0x0444, 0xA7E7, 0x0445, 0xA7E8, 0x0446, + 0xA7E9, 0x0447, 0xA7EA, 0x0448, 0xA7EB, 0x0449, 0xA7EC, 0x044A, + 0xA7ED, 0x044B, 0xA7EE, 0x044C, 0xA7EF, 0x044D, 0xA7F0, 0x044E, + 0xA7F1, 0x044F, 0xA840, 0x02CA, 0xA841, 0x02CB, 0xA842, 0x02D9, + 0xA843, 0x2013, 0xA844, 0x2015, 0xA845, 0x2025, 0xA846, 0x2035, + 0xA847, 0x2105, 0xA848, 0x2109, 0xA849, 0x2196, 0xA84A, 0x2197, + 0xA84B, 0x2198, 0xA84C, 0x2199, 0xA84D, 0x2215, 0xA84E, 0x221F, + 0xA84F, 0x2223, 0xA850, 0x2252, 0xA851, 0x2266, 0xA852, 0x2267, + 0xA853, 0x22BF, 0xA854, 0x2550, 0xA855, 0x2551, 0xA856, 0x2552, + 0xA857, 0x2553, 0xA858, 0x2554, 0xA859, 0x2555, 0xA85A, 0x2556, + 0xA85B, 0x2557, 0xA85C, 0x2558, 0xA85D, 0x2559, 0xA85E, 0x255A, + 0xA85F, 0x255B, 0xA860, 0x255C, 0xA861, 0x255D, 0xA862, 0x255E, + 0xA863, 0x255F, 0xA864, 0x2560, 0xA865, 0x2561, 0xA866, 0x2562, + 0xA867, 0x2563, 0xA868, 0x2564, 0xA869, 0x2565, 0xA86A, 0x2566, + 0xA86B, 0x2567, 0xA86C, 0x2568, 0xA86D, 0x2569, 0xA86E, 0x256A, + 0xA86F, 0x256B, 0xA870, 0x256C, 0xA871, 0x256D, 0xA872, 0x256E, + 0xA873, 0x256F, 0xA874, 0x2570, 0xA875, 0x2571, 0xA876, 0x2572, + 0xA877, 0x2573, 0xA878, 0x2581, 0xA879, 0x2582, 0xA87A, 0x2583, + 0xA87B, 0x2584, 0xA87C, 0x2585, 0xA87D, 0x2586, 0xA87E, 0x2587, + 0xA880, 0x2588, 0xA881, 0x2589, 0xA882, 0x258A, 0xA883, 0x258B, + 0xA884, 0x258C, 0xA885, 0x258D, 0xA886, 0x258E, 0xA887, 0x258F, + 0xA888, 0x2593, 0xA889, 0x2594, 0xA88A, 0x2595, 0xA88B, 0x25BC, + 0xA88C, 0x25BD, 0xA88D, 0x25E2, 0xA88E, 0x25E3, 0xA88F, 0x25E4, + 0xA890, 0x25E5, 0xA891, 0x2609, 0xA892, 0x2295, 0xA893, 0x3012, + 0xA894, 0x301D, 0xA895, 0x301E, 0xA8A1, 0x0101, 0xA8A2, 0x00E1, + 0xA8A3, 0x01CE, 0xA8A4, 0x00E0, 0xA8A5, 0x0113, 0xA8A6, 0x00E9, + 0xA8A7, 0x011B, 0xA8A8, 0x00E8, 0xA8A9, 0x012B, 0xA8AA, 0x00ED, + 0xA8AB, 0x01D0, 0xA8AC, 0x00EC, 0xA8AD, 0x014D, 0xA8AE, 0x00F3, + 0xA8AF, 0x01D2, 0xA8B0, 0x00F2, 0xA8B1, 0x016B, 0xA8B2, 0x00FA, + 0xA8B3, 0x01D4, 0xA8B4, 0x00F9, 0xA8B5, 0x01D6, 0xA8B6, 0x01D8, + 0xA8B7, 0x01DA, 0xA8B8, 0x01DC, 0xA8B9, 0x00FC, 0xA8BA, 0x00EA, + 0xA8BB, 0x0251, 0xA8BD, 0x0144, 0xA8BE, 0x0148, 0xA8C0, 0x0261, + 0xA8C5, 0x3105, 0xA8C6, 0x3106, 0xA8C7, 0x3107, 0xA8C8, 0x3108, + 0xA8C9, 0x3109, 0xA8CA, 0x310A, 0xA8CB, 0x310B, 0xA8CC, 0x310C, + 0xA8CD, 0x310D, 0xA8CE, 0x310E, 0xA8CF, 0x310F, 0xA8D0, 0x3110, + 0xA8D1, 0x3111, 0xA8D2, 0x3112, 0xA8D3, 0x3113, 0xA8D4, 0x3114, + 0xA8D5, 0x3115, 0xA8D6, 0x3116, 0xA8D7, 0x3117, 0xA8D8, 0x3118, + 0xA8D9, 0x3119, 0xA8DA, 0x311A, 0xA8DB, 0x311B, 0xA8DC, 0x311C, + 0xA8DD, 0x311D, 0xA8DE, 0x311E, 0xA8DF, 0x311F, 0xA8E0, 0x3120, + 0xA8E1, 0x3121, 0xA8E2, 0x3122, 0xA8E3, 0x3123, 0xA8E4, 0x3124, + 0xA8E5, 0x3125, 0xA8E6, 0x3126, 0xA8E7, 0x3127, 0xA8E8, 0x3128, + 0xA8E9, 0x3129, 0xA940, 0x3021, 0xA941, 0x3022, 0xA942, 0x3023, + 0xA943, 0x3024, 0xA944, 0x3025, 0xA945, 0x3026, 0xA946, 0x3027, + 0xA947, 0x3028, 0xA948, 0x3029, 0xA949, 0x32A3, 0xA94A, 0x338E, + 0xA94B, 0x338F, 0xA94C, 0x339C, 0xA94D, 0x339D, 0xA94E, 0x339E, + 0xA94F, 0x33A1, 0xA950, 0x33C4, 0xA951, 0x33CE, 0xA952, 0x33D1, + 0xA953, 0x33D2, 0xA954, 0x33D5, 0xA955, 0xFE30, 0xA956, 0xFFE2, + 0xA957, 0xFFE4, 0xA959, 0x2121, 0xA95A, 0x3231, 0xA95C, 0x2010, + 0xA960, 0x30FC, 0xA961, 0x309B, 0xA962, 0x309C, 0xA963, 0x30FD, + 0xA964, 0x30FE, 0xA965, 0x3006, 0xA966, 0x309D, 0xA967, 0x309E, + 0xA968, 0xFE49, 0xA969, 0xFE4A, 0xA96A, 0xFE4B, 0xA96B, 0xFE4C, + 0xA96C, 0xFE4D, 0xA96D, 0xFE4E, 0xA96E, 0xFE4F, 0xA96F, 0xFE50, + 0xA970, 0xFE51, 0xA971, 0xFE52, 0xA972, 0xFE54, 0xA973, 0xFE55, + 0xA974, 0xFE56, 0xA975, 0xFE57, 0xA976, 0xFE59, 0xA977, 0xFE5A, + 0xA978, 0xFE5B, 0xA979, 0xFE5C, 0xA97A, 0xFE5D, 0xA97B, 0xFE5E, + 0xA97C, 0xFE5F, 0xA97D, 0xFE60, 0xA97E, 0xFE61, 0xA980, 0xFE62, + 0xA981, 0xFE63, 0xA982, 0xFE64, 0xA983, 0xFE65, 0xA984, 0xFE66, + 0xA985, 0xFE68, 0xA986, 0xFE69, 0xA987, 0xFE6A, 0xA988, 0xFE6B, + 0xA996, 0x3007, 0xA9A4, 0x2500, 0xA9A5, 0x2501, 0xA9A6, 0x2502, + 0xA9A7, 0x2503, 0xA9A8, 0x2504, 0xA9A9, 0x2505, 0xA9AA, 0x2506, + 0xA9AB, 0x2507, 0xA9AC, 0x2508, 0xA9AD, 0x2509, 0xA9AE, 0x250A, + 0xA9AF, 0x250B, 0xA9B0, 0x250C, 0xA9B1, 0x250D, 0xA9B2, 0x250E, + 0xA9B3, 0x250F, 0xA9B4, 0x2510, 0xA9B5, 0x2511, 0xA9B6, 0x2512, + 0xA9B7, 0x2513, 0xA9B8, 0x2514, 0xA9B9, 0x2515, 0xA9BA, 0x2516, + 0xA9BB, 0x2517, 0xA9BC, 0x2518, 0xA9BD, 0x2519, 0xA9BE, 0x251A, + 0xA9BF, 0x251B, 0xA9C0, 0x251C, 0xA9C1, 0x251D, 0xA9C2, 0x251E, + 0xA9C3, 0x251F, 0xA9C4, 0x2520, 0xA9C5, 0x2521, 0xA9C6, 0x2522, + 0xA9C7, 0x2523, 0xA9C8, 0x2524, 0xA9C9, 0x2525, 0xA9CA, 0x2526, + 0xA9CB, 0x2527, 0xA9CC, 0x2528, 0xA9CD, 0x2529, 0xA9CE, 0x252A, + 0xA9CF, 0x252B, 0xA9D0, 0x252C, 0xA9D1, 0x252D, 0xA9D2, 0x252E, + 0xA9D3, 0x252F, 0xA9D4, 0x2530, 0xA9D5, 0x2531, 0xA9D6, 0x2532, + 0xA9D7, 0x2533, 0xA9D8, 0x2534, 0xA9D9, 0x2535, 0xA9DA, 0x2536, + 0xA9DB, 0x2537, 0xA9DC, 0x2538, 0xA9DD, 0x2539, 0xA9DE, 0x253A, + 0xA9DF, 0x253B, 0xA9E0, 0x253C, 0xA9E1, 0x253D, 0xA9E2, 0x253E, + 0xA9E3, 0x253F, 0xA9E4, 0x2540, 0xA9E5, 0x2541, 0xA9E6, 0x2542, + 0xA9E7, 0x2543, 0xA9E8, 0x2544, 0xA9E9, 0x2545, 0xA9EA, 0x2546, + 0xA9EB, 0x2547, 0xA9EC, 0x2548, 0xA9ED, 0x2549, 0xA9EE, 0x254A, + 0xA9EF, 0x254B, 0xAA40, 0x72DC, 0xAA41, 0x72DD, 0xAA42, 0x72DF, + 0xAA43, 0x72E2, 0xAA44, 0x72E3, 0xAA45, 0x72E4, 0xAA46, 0x72E5, + 0xAA47, 0x72E6, 0xAA48, 0x72E7, 0xAA49, 0x72EA, 0xAA4A, 0x72EB, + 0xAA4B, 0x72F5, 0xAA4C, 0x72F6, 0xAA4D, 0x72F9, 0xAA4E, 0x72FD, + 0xAA4F, 0x72FE, 0xAA50, 0x72FF, 0xAA51, 0x7300, 0xAA52, 0x7302, + 0xAA53, 0x7304, 0xAA54, 0x7305, 0xAA55, 0x7306, 0xAA56, 0x7307, + 0xAA57, 0x7308, 0xAA58, 0x7309, 0xAA59, 0x730B, 0xAA5A, 0x730C, + 0xAA5B, 0x730D, 0xAA5C, 0x730F, 0xAA5D, 0x7310, 0xAA5E, 0x7311, + 0xAA5F, 0x7312, 0xAA60, 0x7314, 0xAA61, 0x7318, 0xAA62, 0x7319, + 0xAA63, 0x731A, 0xAA64, 0x731F, 0xAA65, 0x7320, 0xAA66, 0x7323, + 0xAA67, 0x7324, 0xAA68, 0x7326, 0xAA69, 0x7327, 0xAA6A, 0x7328, + 0xAA6B, 0x732D, 0xAA6C, 0x732F, 0xAA6D, 0x7330, 0xAA6E, 0x7332, + 0xAA6F, 0x7333, 0xAA70, 0x7335, 0xAA71, 0x7336, 0xAA72, 0x733A, + 0xAA73, 0x733B, 0xAA74, 0x733C, 0xAA75, 0x733D, 0xAA76, 0x7340, + 0xAA77, 0x7341, 0xAA78, 0x7342, 0xAA79, 0x7343, 0xAA7A, 0x7344, + 0xAA7B, 0x7345, 0xAA7C, 0x7346, 0xAA7D, 0x7347, 0xAA7E, 0x7348, + 0xAA80, 0x7349, 0xAA81, 0x734A, 0xAA82, 0x734B, 0xAA83, 0x734C, + 0xAA84, 0x734E, 0xAA85, 0x734F, 0xAA86, 0x7351, 0xAA87, 0x7353, + 0xAA88, 0x7354, 0xAA89, 0x7355, 0xAA8A, 0x7356, 0xAA8B, 0x7358, + 0xAA8C, 0x7359, 0xAA8D, 0x735A, 0xAA8E, 0x735B, 0xAA8F, 0x735C, + 0xAA90, 0x735D, 0xAA91, 0x735E, 0xAA92, 0x735F, 0xAA93, 0x7361, + 0xAA94, 0x7362, 0xAA95, 0x7363, 0xAA96, 0x7364, 0xAA97, 0x7365, + 0xAA98, 0x7366, 0xAA99, 0x7367, 0xAA9A, 0x7368, 0xAA9B, 0x7369, + 0xAA9C, 0x736A, 0xAA9D, 0x736B, 0xAA9E, 0x736E, 0xAA9F, 0x7370, + 0xAAA0, 0x7371, 0xAB40, 0x7372, 0xAB41, 0x7373, 0xAB42, 0x7374, + 0xAB43, 0x7375, 0xAB44, 0x7376, 0xAB45, 0x7377, 0xAB46, 0x7378, + 0xAB47, 0x7379, 0xAB48, 0x737A, 0xAB49, 0x737B, 0xAB4A, 0x737C, + 0xAB4B, 0x737D, 0xAB4C, 0x737F, 0xAB4D, 0x7380, 0xAB4E, 0x7381, + 0xAB4F, 0x7382, 0xAB50, 0x7383, 0xAB51, 0x7385, 0xAB52, 0x7386, + 0xAB53, 0x7388, 0xAB54, 0x738A, 0xAB55, 0x738C, 0xAB56, 0x738D, + 0xAB57, 0x738F, 0xAB58, 0x7390, 0xAB59, 0x7392, 0xAB5A, 0x7393, + 0xAB5B, 0x7394, 0xAB5C, 0x7395, 0xAB5D, 0x7397, 0xAB5E, 0x7398, + 0xAB5F, 0x7399, 0xAB60, 0x739A, 0xAB61, 0x739C, 0xAB62, 0x739D, + 0xAB63, 0x739E, 0xAB64, 0x73A0, 0xAB65, 0x73A1, 0xAB66, 0x73A3, + 0xAB67, 0x73A4, 0xAB68, 0x73A5, 0xAB69, 0x73A6, 0xAB6A, 0x73A7, + 0xAB6B, 0x73A8, 0xAB6C, 0x73AA, 0xAB6D, 0x73AC, 0xAB6E, 0x73AD, + 0xAB6F, 0x73B1, 0xAB70, 0x73B4, 0xAB71, 0x73B5, 0xAB72, 0x73B6, + 0xAB73, 0x73B8, 0xAB74, 0x73B9, 0xAB75, 0x73BC, 0xAB76, 0x73BD, + 0xAB77, 0x73BE, 0xAB78, 0x73BF, 0xAB79, 0x73C1, 0xAB7A, 0x73C3, + 0xAB7B, 0x73C4, 0xAB7C, 0x73C5, 0xAB7D, 0x73C6, 0xAB7E, 0x73C7, + 0xAB80, 0x73CB, 0xAB81, 0x73CC, 0xAB82, 0x73CE, 0xAB83, 0x73D2, + 0xAB84, 0x73D3, 0xAB85, 0x73D4, 0xAB86, 0x73D5, 0xAB87, 0x73D6, + 0xAB88, 0x73D7, 0xAB89, 0x73D8, 0xAB8A, 0x73DA, 0xAB8B, 0x73DB, + 0xAB8C, 0x73DC, 0xAB8D, 0x73DD, 0xAB8E, 0x73DF, 0xAB8F, 0x73E1, + 0xAB90, 0x73E2, 0xAB91, 0x73E3, 0xAB92, 0x73E4, 0xAB93, 0x73E6, + 0xAB94, 0x73E8, 0xAB95, 0x73EA, 0xAB96, 0x73EB, 0xAB97, 0x73EC, + 0xAB98, 0x73EE, 0xAB99, 0x73EF, 0xAB9A, 0x73F0, 0xAB9B, 0x73F1, + 0xAB9C, 0x73F3, 0xAB9D, 0x73F4, 0xAB9E, 0x73F5, 0xAB9F, 0x73F6, + 0xABA0, 0x73F7, 0xAC40, 0x73F8, 0xAC41, 0x73F9, 0xAC42, 0x73FA, + 0xAC43, 0x73FB, 0xAC44, 0x73FC, 0xAC45, 0x73FD, 0xAC46, 0x73FE, + 0xAC47, 0x73FF, 0xAC48, 0x7400, 0xAC49, 0x7401, 0xAC4A, 0x7402, + 0xAC4B, 0x7404, 0xAC4C, 0x7407, 0xAC4D, 0x7408, 0xAC4E, 0x740B, + 0xAC4F, 0x740C, 0xAC50, 0x740D, 0xAC51, 0x740E, 0xAC52, 0x7411, + 0xAC53, 0x7412, 0xAC54, 0x7413, 0xAC55, 0x7414, 0xAC56, 0x7415, + 0xAC57, 0x7416, 0xAC58, 0x7417, 0xAC59, 0x7418, 0xAC5A, 0x7419, + 0xAC5B, 0x741C, 0xAC5C, 0x741D, 0xAC5D, 0x741E, 0xAC5E, 0x741F, + 0xAC5F, 0x7420, 0xAC60, 0x7421, 0xAC61, 0x7423, 0xAC62, 0x7424, + 0xAC63, 0x7427, 0xAC64, 0x7429, 0xAC65, 0x742B, 0xAC66, 0x742D, + 0xAC67, 0x742F, 0xAC68, 0x7431, 0xAC69, 0x7432, 0xAC6A, 0x7437, + 0xAC6B, 0x7438, 0xAC6C, 0x7439, 0xAC6D, 0x743A, 0xAC6E, 0x743B, + 0xAC6F, 0x743D, 0xAC70, 0x743E, 0xAC71, 0x743F, 0xAC72, 0x7440, + 0xAC73, 0x7442, 0xAC74, 0x7443, 0xAC75, 0x7444, 0xAC76, 0x7445, + 0xAC77, 0x7446, 0xAC78, 0x7447, 0xAC79, 0x7448, 0xAC7A, 0x7449, + 0xAC7B, 0x744A, 0xAC7C, 0x744B, 0xAC7D, 0x744C, 0xAC7E, 0x744D, + 0xAC80, 0x744E, 0xAC81, 0x744F, 0xAC82, 0x7450, 0xAC83, 0x7451, + 0xAC84, 0x7452, 0xAC85, 0x7453, 0xAC86, 0x7454, 0xAC87, 0x7456, + 0xAC88, 0x7458, 0xAC89, 0x745D, 0xAC8A, 0x7460, 0xAC8B, 0x7461, + 0xAC8C, 0x7462, 0xAC8D, 0x7463, 0xAC8E, 0x7464, 0xAC8F, 0x7465, + 0xAC90, 0x7466, 0xAC91, 0x7467, 0xAC92, 0x7468, 0xAC93, 0x7469, + 0xAC94, 0x746A, 0xAC95, 0x746B, 0xAC96, 0x746C, 0xAC97, 0x746E, + 0xAC98, 0x746F, 0xAC99, 0x7471, 0xAC9A, 0x7472, 0xAC9B, 0x7473, + 0xAC9C, 0x7474, 0xAC9D, 0x7475, 0xAC9E, 0x7478, 0xAC9F, 0x7479, + 0xACA0, 0x747A, 0xAD40, 0x747B, 0xAD41, 0x747C, 0xAD42, 0x747D, + 0xAD43, 0x747F, 0xAD44, 0x7482, 0xAD45, 0x7484, 0xAD46, 0x7485, + 0xAD47, 0x7486, 0xAD48, 0x7488, 0xAD49, 0x7489, 0xAD4A, 0x748A, + 0xAD4B, 0x748C, 0xAD4C, 0x748D, 0xAD4D, 0x748F, 0xAD4E, 0x7491, + 0xAD4F, 0x7492, 0xAD50, 0x7493, 0xAD51, 0x7494, 0xAD52, 0x7495, + 0xAD53, 0x7496, 0xAD54, 0x7497, 0xAD55, 0x7498, 0xAD56, 0x7499, + 0xAD57, 0x749A, 0xAD58, 0x749B, 0xAD59, 0x749D, 0xAD5A, 0x749F, + 0xAD5B, 0x74A0, 0xAD5C, 0x74A1, 0xAD5D, 0x74A2, 0xAD5E, 0x74A3, + 0xAD5F, 0x74A4, 0xAD60, 0x74A5, 0xAD61, 0x74A6, 0xAD62, 0x74AA, + 0xAD63, 0x74AB, 0xAD64, 0x74AC, 0xAD65, 0x74AD, 0xAD66, 0x74AE, + 0xAD67, 0x74AF, 0xAD68, 0x74B0, 0xAD69, 0x74B1, 0xAD6A, 0x74B2, + 0xAD6B, 0x74B3, 0xAD6C, 0x74B4, 0xAD6D, 0x74B5, 0xAD6E, 0x74B6, + 0xAD6F, 0x74B7, 0xAD70, 0x74B8, 0xAD71, 0x74B9, 0xAD72, 0x74BB, + 0xAD73, 0x74BC, 0xAD74, 0x74BD, 0xAD75, 0x74BE, 0xAD76, 0x74BF, + 0xAD77, 0x74C0, 0xAD78, 0x74C1, 0xAD79, 0x74C2, 0xAD7A, 0x74C3, + 0xAD7B, 0x74C4, 0xAD7C, 0x74C5, 0xAD7D, 0x74C6, 0xAD7E, 0x74C7, + 0xAD80, 0x74C8, 0xAD81, 0x74C9, 0xAD82, 0x74CA, 0xAD83, 0x74CB, + 0xAD84, 0x74CC, 0xAD85, 0x74CD, 0xAD86, 0x74CE, 0xAD87, 0x74CF, + 0xAD88, 0x74D0, 0xAD89, 0x74D1, 0xAD8A, 0x74D3, 0xAD8B, 0x74D4, + 0xAD8C, 0x74D5, 0xAD8D, 0x74D6, 0xAD8E, 0x74D7, 0xAD8F, 0x74D8, + 0xAD90, 0x74D9, 0xAD91, 0x74DA, 0xAD92, 0x74DB, 0xAD93, 0x74DD, + 0xAD94, 0x74DF, 0xAD95, 0x74E1, 0xAD96, 0x74E5, 0xAD97, 0x74E7, + 0xAD98, 0x74E8, 0xAD99, 0x74E9, 0xAD9A, 0x74EA, 0xAD9B, 0x74EB, + 0xAD9C, 0x74EC, 0xAD9D, 0x74ED, 0xAD9E, 0x74F0, 0xAD9F, 0x74F1, + 0xADA0, 0x74F2, 0xAE40, 0x74F3, 0xAE41, 0x74F5, 0xAE42, 0x74F8, + 0xAE43, 0x74F9, 0xAE44, 0x74FA, 0xAE45, 0x74FB, 0xAE46, 0x74FC, + 0xAE47, 0x74FD, 0xAE48, 0x74FE, 0xAE49, 0x7500, 0xAE4A, 0x7501, + 0xAE4B, 0x7502, 0xAE4C, 0x7503, 0xAE4D, 0x7505, 0xAE4E, 0x7506, + 0xAE4F, 0x7507, 0xAE50, 0x7508, 0xAE51, 0x7509, 0xAE52, 0x750A, + 0xAE53, 0x750B, 0xAE54, 0x750C, 0xAE55, 0x750E, 0xAE56, 0x7510, + 0xAE57, 0x7512, 0xAE58, 0x7514, 0xAE59, 0x7515, 0xAE5A, 0x7516, + 0xAE5B, 0x7517, 0xAE5C, 0x751B, 0xAE5D, 0x751D, 0xAE5E, 0x751E, + 0xAE5F, 0x7520, 0xAE60, 0x7521, 0xAE61, 0x7522, 0xAE62, 0x7523, + 0xAE63, 0x7524, 0xAE64, 0x7526, 0xAE65, 0x7527, 0xAE66, 0x752A, + 0xAE67, 0x752E, 0xAE68, 0x7534, 0xAE69, 0x7536, 0xAE6A, 0x7539, + 0xAE6B, 0x753C, 0xAE6C, 0x753D, 0xAE6D, 0x753F, 0xAE6E, 0x7541, + 0xAE6F, 0x7542, 0xAE70, 0x7543, 0xAE71, 0x7544, 0xAE72, 0x7546, + 0xAE73, 0x7547, 0xAE74, 0x7549, 0xAE75, 0x754A, 0xAE76, 0x754D, + 0xAE77, 0x7550, 0xAE78, 0x7551, 0xAE79, 0x7552, 0xAE7A, 0x7553, + 0xAE7B, 0x7555, 0xAE7C, 0x7556, 0xAE7D, 0x7557, 0xAE7E, 0x7558, + 0xAE80, 0x755D, 0xAE81, 0x755E, 0xAE82, 0x755F, 0xAE83, 0x7560, + 0xAE84, 0x7561, 0xAE85, 0x7562, 0xAE86, 0x7563, 0xAE87, 0x7564, + 0xAE88, 0x7567, 0xAE89, 0x7568, 0xAE8A, 0x7569, 0xAE8B, 0x756B, + 0xAE8C, 0x756C, 0xAE8D, 0x756D, 0xAE8E, 0x756E, 0xAE8F, 0x756F, + 0xAE90, 0x7570, 0xAE91, 0x7571, 0xAE92, 0x7573, 0xAE93, 0x7575, + 0xAE94, 0x7576, 0xAE95, 0x7577, 0xAE96, 0x757A, 0xAE97, 0x757B, + 0xAE98, 0x757C, 0xAE99, 0x757D, 0xAE9A, 0x757E, 0xAE9B, 0x7580, + 0xAE9C, 0x7581, 0xAE9D, 0x7582, 0xAE9E, 0x7584, 0xAE9F, 0x7585, + 0xAEA0, 0x7587, 0xAF40, 0x7588, 0xAF41, 0x7589, 0xAF42, 0x758A, + 0xAF43, 0x758C, 0xAF44, 0x758D, 0xAF45, 0x758E, 0xAF46, 0x7590, + 0xAF47, 0x7593, 0xAF48, 0x7595, 0xAF49, 0x7598, 0xAF4A, 0x759B, + 0xAF4B, 0x759C, 0xAF4C, 0x759E, 0xAF4D, 0x75A2, 0xAF4E, 0x75A6, + 0xAF4F, 0x75A7, 0xAF50, 0x75A8, 0xAF51, 0x75A9, 0xAF52, 0x75AA, + 0xAF53, 0x75AD, 0xAF54, 0x75B6, 0xAF55, 0x75B7, 0xAF56, 0x75BA, + 0xAF57, 0x75BB, 0xAF58, 0x75BF, 0xAF59, 0x75C0, 0xAF5A, 0x75C1, + 0xAF5B, 0x75C6, 0xAF5C, 0x75CB, 0xAF5D, 0x75CC, 0xAF5E, 0x75CE, + 0xAF5F, 0x75CF, 0xAF60, 0x75D0, 0xAF61, 0x75D1, 0xAF62, 0x75D3, + 0xAF63, 0x75D7, 0xAF64, 0x75D9, 0xAF65, 0x75DA, 0xAF66, 0x75DC, + 0xAF67, 0x75DD, 0xAF68, 0x75DF, 0xAF69, 0x75E0, 0xAF6A, 0x75E1, + 0xAF6B, 0x75E5, 0xAF6C, 0x75E9, 0xAF6D, 0x75EC, 0xAF6E, 0x75ED, + 0xAF6F, 0x75EE, 0xAF70, 0x75EF, 0xAF71, 0x75F2, 0xAF72, 0x75F3, + 0xAF73, 0x75F5, 0xAF74, 0x75F6, 0xAF75, 0x75F7, 0xAF76, 0x75F8, + 0xAF77, 0x75FA, 0xAF78, 0x75FB, 0xAF79, 0x75FD, 0xAF7A, 0x75FE, + 0xAF7B, 0x7602, 0xAF7C, 0x7604, 0xAF7D, 0x7606, 0xAF7E, 0x7607, + 0xAF80, 0x7608, 0xAF81, 0x7609, 0xAF82, 0x760B, 0xAF83, 0x760D, + 0xAF84, 0x760E, 0xAF85, 0x760F, 0xAF86, 0x7611, 0xAF87, 0x7612, + 0xAF88, 0x7613, 0xAF89, 0x7614, 0xAF8A, 0x7616, 0xAF8B, 0x761A, + 0xAF8C, 0x761C, 0xAF8D, 0x761D, 0xAF8E, 0x761E, 0xAF8F, 0x7621, + 0xAF90, 0x7623, 0xAF91, 0x7627, 0xAF92, 0x7628, 0xAF93, 0x762C, + 0xAF94, 0x762E, 0xAF95, 0x762F, 0xAF96, 0x7631, 0xAF97, 0x7632, + 0xAF98, 0x7636, 0xAF99, 0x7637, 0xAF9A, 0x7639, 0xAF9B, 0x763A, + 0xAF9C, 0x763B, 0xAF9D, 0x763D, 0xAF9E, 0x7641, 0xAF9F, 0x7642, + 0xAFA0, 0x7644, 0xB040, 0x7645, 0xB041, 0x7646, 0xB042, 0x7647, + 0xB043, 0x7648, 0xB044, 0x7649, 0xB045, 0x764A, 0xB046, 0x764B, + 0xB047, 0x764E, 0xB048, 0x764F, 0xB049, 0x7650, 0xB04A, 0x7651, + 0xB04B, 0x7652, 0xB04C, 0x7653, 0xB04D, 0x7655, 0xB04E, 0x7657, + 0xB04F, 0x7658, 0xB050, 0x7659, 0xB051, 0x765A, 0xB052, 0x765B, + 0xB053, 0x765D, 0xB054, 0x765F, 0xB055, 0x7660, 0xB056, 0x7661, + 0xB057, 0x7662, 0xB058, 0x7664, 0xB059, 0x7665, 0xB05A, 0x7666, + 0xB05B, 0x7667, 0xB05C, 0x7668, 0xB05D, 0x7669, 0xB05E, 0x766A, + 0xB05F, 0x766C, 0xB060, 0x766D, 0xB061, 0x766E, 0xB062, 0x7670, + 0xB063, 0x7671, 0xB064, 0x7672, 0xB065, 0x7673, 0xB066, 0x7674, + 0xB067, 0x7675, 0xB068, 0x7676, 0xB069, 0x7677, 0xB06A, 0x7679, + 0xB06B, 0x767A, 0xB06C, 0x767C, 0xB06D, 0x767F, 0xB06E, 0x7680, + 0xB06F, 0x7681, 0xB070, 0x7683, 0xB071, 0x7685, 0xB072, 0x7689, + 0xB073, 0x768A, 0xB074, 0x768C, 0xB075, 0x768D, 0xB076, 0x768F, + 0xB077, 0x7690, 0xB078, 0x7692, 0xB079, 0x7694, 0xB07A, 0x7695, + 0xB07B, 0x7697, 0xB07C, 0x7698, 0xB07D, 0x769A, 0xB07E, 0x769B, + 0xB080, 0x769C, 0xB081, 0x769D, 0xB082, 0x769E, 0xB083, 0x769F, + 0xB084, 0x76A0, 0xB085, 0x76A1, 0xB086, 0x76A2, 0xB087, 0x76A3, + 0xB088, 0x76A5, 0xB089, 0x76A6, 0xB08A, 0x76A7, 0xB08B, 0x76A8, + 0xB08C, 0x76A9, 0xB08D, 0x76AA, 0xB08E, 0x76AB, 0xB08F, 0x76AC, + 0xB090, 0x76AD, 0xB091, 0x76AF, 0xB092, 0x76B0, 0xB093, 0x76B3, + 0xB094, 0x76B5, 0xB095, 0x76B6, 0xB096, 0x76B7, 0xB097, 0x76B8, + 0xB098, 0x76B9, 0xB099, 0x76BA, 0xB09A, 0x76BB, 0xB09B, 0x76BC, + 0xB09C, 0x76BD, 0xB09D, 0x76BE, 0xB09E, 0x76C0, 0xB09F, 0x76C1, + 0xB0A0, 0x76C3, 0xB0A1, 0x554A, 0xB0A2, 0x963F, 0xB0A3, 0x57C3, + 0xB0A4, 0x6328, 0xB0A5, 0x54CE, 0xB0A6, 0x5509, 0xB0A7, 0x54C0, + 0xB0A8, 0x7691, 0xB0A9, 0x764C, 0xB0AA, 0x853C, 0xB0AB, 0x77EE, + 0xB0AC, 0x827E, 0xB0AD, 0x788D, 0xB0AE, 0x7231, 0xB0AF, 0x9698, + 0xB0B0, 0x978D, 0xB0B1, 0x6C28, 0xB0B2, 0x5B89, 0xB0B3, 0x4FFA, + 0xB0B4, 0x6309, 0xB0B5, 0x6697, 0xB0B6, 0x5CB8, 0xB0B7, 0x80FA, + 0xB0B8, 0x6848, 0xB0B9, 0x80AE, 0xB0BA, 0x6602, 0xB0BB, 0x76CE, + 0xB0BC, 0x51F9, 0xB0BD, 0x6556, 0xB0BE, 0x71AC, 0xB0BF, 0x7FF1, + 0xB0C0, 0x8884, 0xB0C1, 0x50B2, 0xB0C2, 0x5965, 0xB0C3, 0x61CA, + 0xB0C4, 0x6FB3, 0xB0C5, 0x82AD, 0xB0C6, 0x634C, 0xB0C7, 0x6252, + 0xB0C8, 0x53ED, 0xB0C9, 0x5427, 0xB0CA, 0x7B06, 0xB0CB, 0x516B, + 0xB0CC, 0x75A4, 0xB0CD, 0x5DF4, 0xB0CE, 0x62D4, 0xB0CF, 0x8DCB, + 0xB0D0, 0x9776, 0xB0D1, 0x628A, 0xB0D2, 0x8019, 0xB0D3, 0x575D, + 0xB0D4, 0x9738, 0xB0D5, 0x7F62, 0xB0D6, 0x7238, 0xB0D7, 0x767D, + 0xB0D8, 0x67CF, 0xB0D9, 0x767E, 0xB0DA, 0x6446, 0xB0DB, 0x4F70, + 0xB0DC, 0x8D25, 0xB0DD, 0x62DC, 0xB0DE, 0x7A17, 0xB0DF, 0x6591, + 0xB0E0, 0x73ED, 0xB0E1, 0x642C, 0xB0E2, 0x6273, 0xB0E3, 0x822C, + 0xB0E4, 0x9881, 0xB0E5, 0x677F, 0xB0E6, 0x7248, 0xB0E7, 0x626E, + 0xB0E8, 0x62CC, 0xB0E9, 0x4F34, 0xB0EA, 0x74E3, 0xB0EB, 0x534A, + 0xB0EC, 0x529E, 0xB0ED, 0x7ECA, 0xB0EE, 0x90A6, 0xB0EF, 0x5E2E, + 0xB0F0, 0x6886, 0xB0F1, 0x699C, 0xB0F2, 0x8180, 0xB0F3, 0x7ED1, + 0xB0F4, 0x68D2, 0xB0F5, 0x78C5, 0xB0F6, 0x868C, 0xB0F7, 0x9551, + 0xB0F8, 0x508D, 0xB0F9, 0x8C24, 0xB0FA, 0x82DE, 0xB0FB, 0x80DE, + 0xB0FC, 0x5305, 0xB0FD, 0x8912, 0xB0FE, 0x5265, 0xB140, 0x76C4, + 0xB141, 0x76C7, 0xB142, 0x76C9, 0xB143, 0x76CB, 0xB144, 0x76CC, + 0xB145, 0x76D3, 0xB146, 0x76D5, 0xB147, 0x76D9, 0xB148, 0x76DA, + 0xB149, 0x76DC, 0xB14A, 0x76DD, 0xB14B, 0x76DE, 0xB14C, 0x76E0, + 0xB14D, 0x76E1, 0xB14E, 0x76E2, 0xB14F, 0x76E3, 0xB150, 0x76E4, + 0xB151, 0x76E6, 0xB152, 0x76E7, 0xB153, 0x76E8, 0xB154, 0x76E9, + 0xB155, 0x76EA, 0xB156, 0x76EB, 0xB157, 0x76EC, 0xB158, 0x76ED, + 0xB159, 0x76F0, 0xB15A, 0x76F3, 0xB15B, 0x76F5, 0xB15C, 0x76F6, + 0xB15D, 0x76F7, 0xB15E, 0x76FA, 0xB15F, 0x76FB, 0xB160, 0x76FD, + 0xB161, 0x76FF, 0xB162, 0x7700, 0xB163, 0x7702, 0xB164, 0x7703, + 0xB165, 0x7705, 0xB166, 0x7706, 0xB167, 0x770A, 0xB168, 0x770C, + 0xB169, 0x770E, 0xB16A, 0x770F, 0xB16B, 0x7710, 0xB16C, 0x7711, + 0xB16D, 0x7712, 0xB16E, 0x7713, 0xB16F, 0x7714, 0xB170, 0x7715, + 0xB171, 0x7716, 0xB172, 0x7717, 0xB173, 0x7718, 0xB174, 0x771B, + 0xB175, 0x771C, 0xB176, 0x771D, 0xB177, 0x771E, 0xB178, 0x7721, + 0xB179, 0x7723, 0xB17A, 0x7724, 0xB17B, 0x7725, 0xB17C, 0x7727, + 0xB17D, 0x772A, 0xB17E, 0x772B, 0xB180, 0x772C, 0xB181, 0x772E, + 0xB182, 0x7730, 0xB183, 0x7731, 0xB184, 0x7732, 0xB185, 0x7733, + 0xB186, 0x7734, 0xB187, 0x7739, 0xB188, 0x773B, 0xB189, 0x773D, + 0xB18A, 0x773E, 0xB18B, 0x773F, 0xB18C, 0x7742, 0xB18D, 0x7744, + 0xB18E, 0x7745, 0xB18F, 0x7746, 0xB190, 0x7748, 0xB191, 0x7749, + 0xB192, 0x774A, 0xB193, 0x774B, 0xB194, 0x774C, 0xB195, 0x774D, + 0xB196, 0x774E, 0xB197, 0x774F, 0xB198, 0x7752, 0xB199, 0x7753, + 0xB19A, 0x7754, 0xB19B, 0x7755, 0xB19C, 0x7756, 0xB19D, 0x7757, + 0xB19E, 0x7758, 0xB19F, 0x7759, 0xB1A0, 0x775C, 0xB1A1, 0x8584, + 0xB1A2, 0x96F9, 0xB1A3, 0x4FDD, 0xB1A4, 0x5821, 0xB1A5, 0x9971, + 0xB1A6, 0x5B9D, 0xB1A7, 0x62B1, 0xB1A8, 0x62A5, 0xB1A9, 0x66B4, + 0xB1AA, 0x8C79, 0xB1AB, 0x9C8D, 0xB1AC, 0x7206, 0xB1AD, 0x676F, + 0xB1AE, 0x7891, 0xB1AF, 0x60B2, 0xB1B0, 0x5351, 0xB1B1, 0x5317, + 0xB1B2, 0x8F88, 0xB1B3, 0x80CC, 0xB1B4, 0x8D1D, 0xB1B5, 0x94A1, + 0xB1B6, 0x500D, 0xB1B7, 0x72C8, 0xB1B8, 0x5907, 0xB1B9, 0x60EB, + 0xB1BA, 0x7119, 0xB1BB, 0x88AB, 0xB1BC, 0x5954, 0xB1BD, 0x82EF, + 0xB1BE, 0x672C, 0xB1BF, 0x7B28, 0xB1C0, 0x5D29, 0xB1C1, 0x7EF7, + 0xB1C2, 0x752D, 0xB1C3, 0x6CF5, 0xB1C4, 0x8E66, 0xB1C5, 0x8FF8, + 0xB1C6, 0x903C, 0xB1C7, 0x9F3B, 0xB1C8, 0x6BD4, 0xB1C9, 0x9119, + 0xB1CA, 0x7B14, 0xB1CB, 0x5F7C, 0xB1CC, 0x78A7, 0xB1CD, 0x84D6, + 0xB1CE, 0x853D, 0xB1CF, 0x6BD5, 0xB1D0, 0x6BD9, 0xB1D1, 0x6BD6, + 0xB1D2, 0x5E01, 0xB1D3, 0x5E87, 0xB1D4, 0x75F9, 0xB1D5, 0x95ED, + 0xB1D6, 0x655D, 0xB1D7, 0x5F0A, 0xB1D8, 0x5FC5, 0xB1D9, 0x8F9F, + 0xB1DA, 0x58C1, 0xB1DB, 0x81C2, 0xB1DC, 0x907F, 0xB1DD, 0x965B, + 0xB1DE, 0x97AD, 0xB1DF, 0x8FB9, 0xB1E0, 0x7F16, 0xB1E1, 0x8D2C, + 0xB1E2, 0x6241, 0xB1E3, 0x4FBF, 0xB1E4, 0x53D8, 0xB1E5, 0x535E, + 0xB1E6, 0x8FA8, 0xB1E7, 0x8FA9, 0xB1E8, 0x8FAB, 0xB1E9, 0x904D, + 0xB1EA, 0x6807, 0xB1EB, 0x5F6A, 0xB1EC, 0x8198, 0xB1ED, 0x8868, + 0xB1EE, 0x9CD6, 0xB1EF, 0x618B, 0xB1F0, 0x522B, 0xB1F1, 0x762A, + 0xB1F2, 0x5F6C, 0xB1F3, 0x658C, 0xB1F4, 0x6FD2, 0xB1F5, 0x6EE8, + 0xB1F6, 0x5BBE, 0xB1F7, 0x6448, 0xB1F8, 0x5175, 0xB1F9, 0x51B0, + 0xB1FA, 0x67C4, 0xB1FB, 0x4E19, 0xB1FC, 0x79C9, 0xB1FD, 0x997C, + 0xB1FE, 0x70B3, 0xB240, 0x775D, 0xB241, 0x775E, 0xB242, 0x775F, + 0xB243, 0x7760, 0xB244, 0x7764, 0xB245, 0x7767, 0xB246, 0x7769, + 0xB247, 0x776A, 0xB248, 0x776D, 0xB249, 0x776E, 0xB24A, 0x776F, + 0xB24B, 0x7770, 0xB24C, 0x7771, 0xB24D, 0x7772, 0xB24E, 0x7773, + 0xB24F, 0x7774, 0xB250, 0x7775, 0xB251, 0x7776, 0xB252, 0x7777, + 0xB253, 0x7778, 0xB254, 0x777A, 0xB255, 0x777B, 0xB256, 0x777C, + 0xB257, 0x7781, 0xB258, 0x7782, 0xB259, 0x7783, 0xB25A, 0x7786, + 0xB25B, 0x7787, 0xB25C, 0x7788, 0xB25D, 0x7789, 0xB25E, 0x778A, + 0xB25F, 0x778B, 0xB260, 0x778F, 0xB261, 0x7790, 0xB262, 0x7793, + 0xB263, 0x7794, 0xB264, 0x7795, 0xB265, 0x7796, 0xB266, 0x7797, + 0xB267, 0x7798, 0xB268, 0x7799, 0xB269, 0x779A, 0xB26A, 0x779B, + 0xB26B, 0x779C, 0xB26C, 0x779D, 0xB26D, 0x779E, 0xB26E, 0x77A1, + 0xB26F, 0x77A3, 0xB270, 0x77A4, 0xB271, 0x77A6, 0xB272, 0x77A8, + 0xB273, 0x77AB, 0xB274, 0x77AD, 0xB275, 0x77AE, 0xB276, 0x77AF, + 0xB277, 0x77B1, 0xB278, 0x77B2, 0xB279, 0x77B4, 0xB27A, 0x77B6, + 0xB27B, 0x77B7, 0xB27C, 0x77B8, 0xB27D, 0x77B9, 0xB27E, 0x77BA, + 0xB280, 0x77BC, 0xB281, 0x77BE, 0xB282, 0x77C0, 0xB283, 0x77C1, + 0xB284, 0x77C2, 0xB285, 0x77C3, 0xB286, 0x77C4, 0xB287, 0x77C5, + 0xB288, 0x77C6, 0xB289, 0x77C7, 0xB28A, 0x77C8, 0xB28B, 0x77C9, + 0xB28C, 0x77CA, 0xB28D, 0x77CB, 0xB28E, 0x77CC, 0xB28F, 0x77CE, + 0xB290, 0x77CF, 0xB291, 0x77D0, 0xB292, 0x77D1, 0xB293, 0x77D2, + 0xB294, 0x77D3, 0xB295, 0x77D4, 0xB296, 0x77D5, 0xB297, 0x77D6, + 0xB298, 0x77D8, 0xB299, 0x77D9, 0xB29A, 0x77DA, 0xB29B, 0x77DD, + 0xB29C, 0x77DE, 0xB29D, 0x77DF, 0xB29E, 0x77E0, 0xB29F, 0x77E1, + 0xB2A0, 0x77E4, 0xB2A1, 0x75C5, 0xB2A2, 0x5E76, 0xB2A3, 0x73BB, + 0xB2A4, 0x83E0, 0xB2A5, 0x64AD, 0xB2A6, 0x62E8, 0xB2A7, 0x94B5, + 0xB2A8, 0x6CE2, 0xB2A9, 0x535A, 0xB2AA, 0x52C3, 0xB2AB, 0x640F, + 0xB2AC, 0x94C2, 0xB2AD, 0x7B94, 0xB2AE, 0x4F2F, 0xB2AF, 0x5E1B, + 0xB2B0, 0x8236, 0xB2B1, 0x8116, 0xB2B2, 0x818A, 0xB2B3, 0x6E24, + 0xB2B4, 0x6CCA, 0xB2B5, 0x9A73, 0xB2B6, 0x6355, 0xB2B7, 0x535C, + 0xB2B8, 0x54FA, 0xB2B9, 0x8865, 0xB2BA, 0x57E0, 0xB2BB, 0x4E0D, + 0xB2BC, 0x5E03, 0xB2BD, 0x6B65, 0xB2BE, 0x7C3F, 0xB2BF, 0x90E8, + 0xB2C0, 0x6016, 0xB2C1, 0x64E6, 0xB2C2, 0x731C, 0xB2C3, 0x88C1, + 0xB2C4, 0x6750, 0xB2C5, 0x624D, 0xB2C6, 0x8D22, 0xB2C7, 0x776C, + 0xB2C8, 0x8E29, 0xB2C9, 0x91C7, 0xB2CA, 0x5F69, 0xB2CB, 0x83DC, + 0xB2CC, 0x8521, 0xB2CD, 0x9910, 0xB2CE, 0x53C2, 0xB2CF, 0x8695, + 0xB2D0, 0x6B8B, 0xB2D1, 0x60ED, 0xB2D2, 0x60E8, 0xB2D3, 0x707F, + 0xB2D4, 0x82CD, 0xB2D5, 0x8231, 0xB2D6, 0x4ED3, 0xB2D7, 0x6CA7, + 0xB2D8, 0x85CF, 0xB2D9, 0x64CD, 0xB2DA, 0x7CD9, 0xB2DB, 0x69FD, + 0xB2DC, 0x66F9, 0xB2DD, 0x8349, 0xB2DE, 0x5395, 0xB2DF, 0x7B56, + 0xB2E0, 0x4FA7, 0xB2E1, 0x518C, 0xB2E2, 0x6D4B, 0xB2E3, 0x5C42, + 0xB2E4, 0x8E6D, 0xB2E5, 0x63D2, 0xB2E6, 0x53C9, 0xB2E7, 0x832C, + 0xB2E8, 0x8336, 0xB2E9, 0x67E5, 0xB2EA, 0x78B4, 0xB2EB, 0x643D, + 0xB2EC, 0x5BDF, 0xB2ED, 0x5C94, 0xB2EE, 0x5DEE, 0xB2EF, 0x8BE7, + 0xB2F0, 0x62C6, 0xB2F1, 0x67F4, 0xB2F2, 0x8C7A, 0xB2F3, 0x6400, + 0xB2F4, 0x63BA, 0xB2F5, 0x8749, 0xB2F6, 0x998B, 0xB2F7, 0x8C17, + 0xB2F8, 0x7F20, 0xB2F9, 0x94F2, 0xB2FA, 0x4EA7, 0xB2FB, 0x9610, + 0xB2FC, 0x98A4, 0xB2FD, 0x660C, 0xB2FE, 0x7316, 0xB340, 0x77E6, + 0xB341, 0x77E8, 0xB342, 0x77EA, 0xB343, 0x77EF, 0xB344, 0x77F0, + 0xB345, 0x77F1, 0xB346, 0x77F2, 0xB347, 0x77F4, 0xB348, 0x77F5, + 0xB349, 0x77F7, 0xB34A, 0x77F9, 0xB34B, 0x77FA, 0xB34C, 0x77FB, + 0xB34D, 0x77FC, 0xB34E, 0x7803, 0xB34F, 0x7804, 0xB350, 0x7805, + 0xB351, 0x7806, 0xB352, 0x7807, 0xB353, 0x7808, 0xB354, 0x780A, + 0xB355, 0x780B, 0xB356, 0x780E, 0xB357, 0x780F, 0xB358, 0x7810, + 0xB359, 0x7813, 0xB35A, 0x7815, 0xB35B, 0x7819, 0xB35C, 0x781B, + 0xB35D, 0x781E, 0xB35E, 0x7820, 0xB35F, 0x7821, 0xB360, 0x7822, + 0xB361, 0x7824, 0xB362, 0x7828, 0xB363, 0x782A, 0xB364, 0x782B, + 0xB365, 0x782E, 0xB366, 0x782F, 0xB367, 0x7831, 0xB368, 0x7832, + 0xB369, 0x7833, 0xB36A, 0x7835, 0xB36B, 0x7836, 0xB36C, 0x783D, + 0xB36D, 0x783F, 0xB36E, 0x7841, 0xB36F, 0x7842, 0xB370, 0x7843, + 0xB371, 0x7844, 0xB372, 0x7846, 0xB373, 0x7848, 0xB374, 0x7849, + 0xB375, 0x784A, 0xB376, 0x784B, 0xB377, 0x784D, 0xB378, 0x784F, + 0xB379, 0x7851, 0xB37A, 0x7853, 0xB37B, 0x7854, 0xB37C, 0x7858, + 0xB37D, 0x7859, 0xB37E, 0x785A, 0xB380, 0x785B, 0xB381, 0x785C, + 0xB382, 0x785E, 0xB383, 0x785F, 0xB384, 0x7860, 0xB385, 0x7861, + 0xB386, 0x7862, 0xB387, 0x7863, 0xB388, 0x7864, 0xB389, 0x7865, + 0xB38A, 0x7866, 0xB38B, 0x7867, 0xB38C, 0x7868, 0xB38D, 0x7869, + 0xB38E, 0x786F, 0xB38F, 0x7870, 0xB390, 0x7871, 0xB391, 0x7872, + 0xB392, 0x7873, 0xB393, 0x7874, 0xB394, 0x7875, 0xB395, 0x7876, + 0xB396, 0x7878, 0xB397, 0x7879, 0xB398, 0x787A, 0xB399, 0x787B, + 0xB39A, 0x787D, 0xB39B, 0x787E, 0xB39C, 0x787F, 0xB39D, 0x7880, + 0xB39E, 0x7881, 0xB39F, 0x7882, 0xB3A0, 0x7883, 0xB3A1, 0x573A, + 0xB3A2, 0x5C1D, 0xB3A3, 0x5E38, 0xB3A4, 0x957F, 0xB3A5, 0x507F, + 0xB3A6, 0x80A0, 0xB3A7, 0x5382, 0xB3A8, 0x655E, 0xB3A9, 0x7545, + 0xB3AA, 0x5531, 0xB3AB, 0x5021, 0xB3AC, 0x8D85, 0xB3AD, 0x6284, + 0xB3AE, 0x949E, 0xB3AF, 0x671D, 0xB3B0, 0x5632, 0xB3B1, 0x6F6E, + 0xB3B2, 0x5DE2, 0xB3B3, 0x5435, 0xB3B4, 0x7092, 0xB3B5, 0x8F66, + 0xB3B6, 0x626F, 0xB3B7, 0x64A4, 0xB3B8, 0x63A3, 0xB3B9, 0x5F7B, + 0xB3BA, 0x6F88, 0xB3BB, 0x90F4, 0xB3BC, 0x81E3, 0xB3BD, 0x8FB0, + 0xB3BE, 0x5C18, 0xB3BF, 0x6668, 0xB3C0, 0x5FF1, 0xB3C1, 0x6C89, + 0xB3C2, 0x9648, 0xB3C3, 0x8D81, 0xB3C4, 0x886C, 0xB3C5, 0x6491, + 0xB3C6, 0x79F0, 0xB3C7, 0x57CE, 0xB3C8, 0x6A59, 0xB3C9, 0x6210, + 0xB3CA, 0x5448, 0xB3CB, 0x4E58, 0xB3CC, 0x7A0B, 0xB3CD, 0x60E9, + 0xB3CE, 0x6F84, 0xB3CF, 0x8BDA, 0xB3D0, 0x627F, 0xB3D1, 0x901E, + 0xB3D2, 0x9A8B, 0xB3D3, 0x79E4, 0xB3D4, 0x5403, 0xB3D5, 0x75F4, + 0xB3D6, 0x6301, 0xB3D7, 0x5319, 0xB3D8, 0x6C60, 0xB3D9, 0x8FDF, + 0xB3DA, 0x5F1B, 0xB3DB, 0x9A70, 0xB3DC, 0x803B, 0xB3DD, 0x9F7F, + 0xB3DE, 0x4F88, 0xB3DF, 0x5C3A, 0xB3E0, 0x8D64, 0xB3E1, 0x7FC5, + 0xB3E2, 0x65A5, 0xB3E3, 0x70BD, 0xB3E4, 0x5145, 0xB3E5, 0x51B2, + 0xB3E6, 0x866B, 0xB3E7, 0x5D07, 0xB3E8, 0x5BA0, 0xB3E9, 0x62BD, + 0xB3EA, 0x916C, 0xB3EB, 0x7574, 0xB3EC, 0x8E0C, 0xB3ED, 0x7A20, + 0xB3EE, 0x6101, 0xB3EF, 0x7B79, 0xB3F0, 0x4EC7, 0xB3F1, 0x7EF8, + 0xB3F2, 0x7785, 0xB3F3, 0x4E11, 0xB3F4, 0x81ED, 0xB3F5, 0x521D, + 0xB3F6, 0x51FA, 0xB3F7, 0x6A71, 0xB3F8, 0x53A8, 0xB3F9, 0x8E87, + 0xB3FA, 0x9504, 0xB3FB, 0x96CF, 0xB3FC, 0x6EC1, 0xB3FD, 0x9664, + 0xB3FE, 0x695A, 0xB440, 0x7884, 0xB441, 0x7885, 0xB442, 0x7886, + 0xB443, 0x7888, 0xB444, 0x788A, 0xB445, 0x788B, 0xB446, 0x788F, + 0xB447, 0x7890, 0xB448, 0x7892, 0xB449, 0x7894, 0xB44A, 0x7895, + 0xB44B, 0x7896, 0xB44C, 0x7899, 0xB44D, 0x789D, 0xB44E, 0x789E, + 0xB44F, 0x78A0, 0xB450, 0x78A2, 0xB451, 0x78A4, 0xB452, 0x78A6, + 0xB453, 0x78A8, 0xB454, 0x78A9, 0xB455, 0x78AA, 0xB456, 0x78AB, + 0xB457, 0x78AC, 0xB458, 0x78AD, 0xB459, 0x78AE, 0xB45A, 0x78AF, + 0xB45B, 0x78B5, 0xB45C, 0x78B6, 0xB45D, 0x78B7, 0xB45E, 0x78B8, + 0xB45F, 0x78BA, 0xB460, 0x78BB, 0xB461, 0x78BC, 0xB462, 0x78BD, + 0xB463, 0x78BF, 0xB464, 0x78C0, 0xB465, 0x78C2, 0xB466, 0x78C3, + 0xB467, 0x78C4, 0xB468, 0x78C6, 0xB469, 0x78C7, 0xB46A, 0x78C8, + 0xB46B, 0x78CC, 0xB46C, 0x78CD, 0xB46D, 0x78CE, 0xB46E, 0x78CF, + 0xB46F, 0x78D1, 0xB470, 0x78D2, 0xB471, 0x78D3, 0xB472, 0x78D6, + 0xB473, 0x78D7, 0xB474, 0x78D8, 0xB475, 0x78DA, 0xB476, 0x78DB, + 0xB477, 0x78DC, 0xB478, 0x78DD, 0xB479, 0x78DE, 0xB47A, 0x78DF, + 0xB47B, 0x78E0, 0xB47C, 0x78E1, 0xB47D, 0x78E2, 0xB47E, 0x78E3, + 0xB480, 0x78E4, 0xB481, 0x78E5, 0xB482, 0x78E6, 0xB483, 0x78E7, + 0xB484, 0x78E9, 0xB485, 0x78EA, 0xB486, 0x78EB, 0xB487, 0x78ED, + 0xB488, 0x78EE, 0xB489, 0x78EF, 0xB48A, 0x78F0, 0xB48B, 0x78F1, + 0xB48C, 0x78F3, 0xB48D, 0x78F5, 0xB48E, 0x78F6, 0xB48F, 0x78F8, + 0xB490, 0x78F9, 0xB491, 0x78FB, 0xB492, 0x78FC, 0xB493, 0x78FD, + 0xB494, 0x78FE, 0xB495, 0x78FF, 0xB496, 0x7900, 0xB497, 0x7902, + 0xB498, 0x7903, 0xB499, 0x7904, 0xB49A, 0x7906, 0xB49B, 0x7907, + 0xB49C, 0x7908, 0xB49D, 0x7909, 0xB49E, 0x790A, 0xB49F, 0x790B, + 0xB4A0, 0x790C, 0xB4A1, 0x7840, 0xB4A2, 0x50A8, 0xB4A3, 0x77D7, + 0xB4A4, 0x6410, 0xB4A5, 0x89E6, 0xB4A6, 0x5904, 0xB4A7, 0x63E3, + 0xB4A8, 0x5DDD, 0xB4A9, 0x7A7F, 0xB4AA, 0x693D, 0xB4AB, 0x4F20, + 0xB4AC, 0x8239, 0xB4AD, 0x5598, 0xB4AE, 0x4E32, 0xB4AF, 0x75AE, + 0xB4B0, 0x7A97, 0xB4B1, 0x5E62, 0xB4B2, 0x5E8A, 0xB4B3, 0x95EF, + 0xB4B4, 0x521B, 0xB4B5, 0x5439, 0xB4B6, 0x708A, 0xB4B7, 0x6376, + 0xB4B8, 0x9524, 0xB4B9, 0x5782, 0xB4BA, 0x6625, 0xB4BB, 0x693F, + 0xB4BC, 0x9187, 0xB4BD, 0x5507, 0xB4BE, 0x6DF3, 0xB4BF, 0x7EAF, + 0xB4C0, 0x8822, 0xB4C1, 0x6233, 0xB4C2, 0x7EF0, 0xB4C3, 0x75B5, + 0xB4C4, 0x8328, 0xB4C5, 0x78C1, 0xB4C6, 0x96CC, 0xB4C7, 0x8F9E, + 0xB4C8, 0x6148, 0xB4C9, 0x74F7, 0xB4CA, 0x8BCD, 0xB4CB, 0x6B64, + 0xB4CC, 0x523A, 0xB4CD, 0x8D50, 0xB4CE, 0x6B21, 0xB4CF, 0x806A, + 0xB4D0, 0x8471, 0xB4D1, 0x56F1, 0xB4D2, 0x5306, 0xB4D3, 0x4ECE, + 0xB4D4, 0x4E1B, 0xB4D5, 0x51D1, 0xB4D6, 0x7C97, 0xB4D7, 0x918B, + 0xB4D8, 0x7C07, 0xB4D9, 0x4FC3, 0xB4DA, 0x8E7F, 0xB4DB, 0x7BE1, + 0xB4DC, 0x7A9C, 0xB4DD, 0x6467, 0xB4DE, 0x5D14, 0xB4DF, 0x50AC, + 0xB4E0, 0x8106, 0xB4E1, 0x7601, 0xB4E2, 0x7CB9, 0xB4E3, 0x6DEC, + 0xB4E4, 0x7FE0, 0xB4E5, 0x6751, 0xB4E6, 0x5B58, 0xB4E7, 0x5BF8, + 0xB4E8, 0x78CB, 0xB4E9, 0x64AE, 0xB4EA, 0x6413, 0xB4EB, 0x63AA, + 0xB4EC, 0x632B, 0xB4ED, 0x9519, 0xB4EE, 0x642D, 0xB4EF, 0x8FBE, + 0xB4F0, 0x7B54, 0xB4F1, 0x7629, 0xB4F2, 0x6253, 0xB4F3, 0x5927, + 0xB4F4, 0x5446, 0xB4F5, 0x6B79, 0xB4F6, 0x50A3, 0xB4F7, 0x6234, + 0xB4F8, 0x5E26, 0xB4F9, 0x6B86, 0xB4FA, 0x4EE3, 0xB4FB, 0x8D37, + 0xB4FC, 0x888B, 0xB4FD, 0x5F85, 0xB4FE, 0x902E, 0xB540, 0x790D, + 0xB541, 0x790E, 0xB542, 0x790F, 0xB543, 0x7910, 0xB544, 0x7911, + 0xB545, 0x7912, 0xB546, 0x7914, 0xB547, 0x7915, 0xB548, 0x7916, + 0xB549, 0x7917, 0xB54A, 0x7918, 0xB54B, 0x7919, 0xB54C, 0x791A, + 0xB54D, 0x791B, 0xB54E, 0x791C, 0xB54F, 0x791D, 0xB550, 0x791F, + 0xB551, 0x7920, 0xB552, 0x7921, 0xB553, 0x7922, 0xB554, 0x7923, + 0xB555, 0x7925, 0xB556, 0x7926, 0xB557, 0x7927, 0xB558, 0x7928, + 0xB559, 0x7929, 0xB55A, 0x792A, 0xB55B, 0x792B, 0xB55C, 0x792C, + 0xB55D, 0x792D, 0xB55E, 0x792E, 0xB55F, 0x792F, 0xB560, 0x7930, + 0xB561, 0x7931, 0xB562, 0x7932, 0xB563, 0x7933, 0xB564, 0x7935, + 0xB565, 0x7936, 0xB566, 0x7937, 0xB567, 0x7938, 0xB568, 0x7939, + 0xB569, 0x793D, 0xB56A, 0x793F, 0xB56B, 0x7942, 0xB56C, 0x7943, + 0xB56D, 0x7944, 0xB56E, 0x7945, 0xB56F, 0x7947, 0xB570, 0x794A, + 0xB571, 0x794B, 0xB572, 0x794C, 0xB573, 0x794D, 0xB574, 0x794E, + 0xB575, 0x794F, 0xB576, 0x7950, 0xB577, 0x7951, 0xB578, 0x7952, + 0xB579, 0x7954, 0xB57A, 0x7955, 0xB57B, 0x7958, 0xB57C, 0x7959, + 0xB57D, 0x7961, 0xB57E, 0x7963, 0xB580, 0x7964, 0xB581, 0x7966, + 0xB582, 0x7969, 0xB583, 0x796A, 0xB584, 0x796B, 0xB585, 0x796C, + 0xB586, 0x796E, 0xB587, 0x7970, 0xB588, 0x7971, 0xB589, 0x7972, + 0xB58A, 0x7973, 0xB58B, 0x7974, 0xB58C, 0x7975, 0xB58D, 0x7976, + 0xB58E, 0x7979, 0xB58F, 0x797B, 0xB590, 0x797C, 0xB591, 0x797D, + 0xB592, 0x797E, 0xB593, 0x797F, 0xB594, 0x7982, 0xB595, 0x7983, + 0xB596, 0x7986, 0xB597, 0x7987, 0xB598, 0x7988, 0xB599, 0x7989, + 0xB59A, 0x798B, 0xB59B, 0x798C, 0xB59C, 0x798D, 0xB59D, 0x798E, + 0xB59E, 0x7990, 0xB59F, 0x7991, 0xB5A0, 0x7992, 0xB5A1, 0x6020, + 0xB5A2, 0x803D, 0xB5A3, 0x62C5, 0xB5A4, 0x4E39, 0xB5A5, 0x5355, + 0xB5A6, 0x90F8, 0xB5A7, 0x63B8, 0xB5A8, 0x80C6, 0xB5A9, 0x65E6, + 0xB5AA, 0x6C2E, 0xB5AB, 0x4F46, 0xB5AC, 0x60EE, 0xB5AD, 0x6DE1, + 0xB5AE, 0x8BDE, 0xB5AF, 0x5F39, 0xB5B0, 0x86CB, 0xB5B1, 0x5F53, + 0xB5B2, 0x6321, 0xB5B3, 0x515A, 0xB5B4, 0x8361, 0xB5B5, 0x6863, + 0xB5B6, 0x5200, 0xB5B7, 0x6363, 0xB5B8, 0x8E48, 0xB5B9, 0x5012, + 0xB5BA, 0x5C9B, 0xB5BB, 0x7977, 0xB5BC, 0x5BFC, 0xB5BD, 0x5230, + 0xB5BE, 0x7A3B, 0xB5BF, 0x60BC, 0xB5C0, 0x9053, 0xB5C1, 0x76D7, + 0xB5C2, 0x5FB7, 0xB5C3, 0x5F97, 0xB5C4, 0x7684, 0xB5C5, 0x8E6C, + 0xB5C6, 0x706F, 0xB5C7, 0x767B, 0xB5C8, 0x7B49, 0xB5C9, 0x77AA, + 0xB5CA, 0x51F3, 0xB5CB, 0x9093, 0xB5CC, 0x5824, 0xB5CD, 0x4F4E, + 0xB5CE, 0x6EF4, 0xB5CF, 0x8FEA, 0xB5D0, 0x654C, 0xB5D1, 0x7B1B, + 0xB5D2, 0x72C4, 0xB5D3, 0x6DA4, 0xB5D4, 0x7FDF, 0xB5D5, 0x5AE1, + 0xB5D6, 0x62B5, 0xB5D7, 0x5E95, 0xB5D8, 0x5730, 0xB5D9, 0x8482, + 0xB5DA, 0x7B2C, 0xB5DB, 0x5E1D, 0xB5DC, 0x5F1F, 0xB5DD, 0x9012, + 0xB5DE, 0x7F14, 0xB5DF, 0x98A0, 0xB5E0, 0x6382, 0xB5E1, 0x6EC7, + 0xB5E2, 0x7898, 0xB5E3, 0x70B9, 0xB5E4, 0x5178, 0xB5E5, 0x975B, + 0xB5E6, 0x57AB, 0xB5E7, 0x7535, 0xB5E8, 0x4F43, 0xB5E9, 0x7538, + 0xB5EA, 0x5E97, 0xB5EB, 0x60E6, 0xB5EC, 0x5960, 0xB5ED, 0x6DC0, + 0xB5EE, 0x6BBF, 0xB5EF, 0x7889, 0xB5F0, 0x53FC, 0xB5F1, 0x96D5, + 0xB5F2, 0x51CB, 0xB5F3, 0x5201, 0xB5F4, 0x6389, 0xB5F5, 0x540A, + 0xB5F6, 0x9493, 0xB5F7, 0x8C03, 0xB5F8, 0x8DCC, 0xB5F9, 0x7239, + 0xB5FA, 0x789F, 0xB5FB, 0x8776, 0xB5FC, 0x8FED, 0xB5FD, 0x8C0D, + 0xB5FE, 0x53E0, 0xB640, 0x7993, 0xB641, 0x7994, 0xB642, 0x7995, + 0xB643, 0x7996, 0xB644, 0x7997, 0xB645, 0x7998, 0xB646, 0x7999, + 0xB647, 0x799B, 0xB648, 0x799C, 0xB649, 0x799D, 0xB64A, 0x799E, + 0xB64B, 0x799F, 0xB64C, 0x79A0, 0xB64D, 0x79A1, 0xB64E, 0x79A2, + 0xB64F, 0x79A3, 0xB650, 0x79A4, 0xB651, 0x79A5, 0xB652, 0x79A6, + 0xB653, 0x79A8, 0xB654, 0x79A9, 0xB655, 0x79AA, 0xB656, 0x79AB, + 0xB657, 0x79AC, 0xB658, 0x79AD, 0xB659, 0x79AE, 0xB65A, 0x79AF, + 0xB65B, 0x79B0, 0xB65C, 0x79B1, 0xB65D, 0x79B2, 0xB65E, 0x79B4, + 0xB65F, 0x79B5, 0xB660, 0x79B6, 0xB661, 0x79B7, 0xB662, 0x79B8, + 0xB663, 0x79BC, 0xB664, 0x79BF, 0xB665, 0x79C2, 0xB666, 0x79C4, + 0xB667, 0x79C5, 0xB668, 0x79C7, 0xB669, 0x79C8, 0xB66A, 0x79CA, + 0xB66B, 0x79CC, 0xB66C, 0x79CE, 0xB66D, 0x79CF, 0xB66E, 0x79D0, + 0xB66F, 0x79D3, 0xB670, 0x79D4, 0xB671, 0x79D6, 0xB672, 0x79D7, + 0xB673, 0x79D9, 0xB674, 0x79DA, 0xB675, 0x79DB, 0xB676, 0x79DC, + 0xB677, 0x79DD, 0xB678, 0x79DE, 0xB679, 0x79E0, 0xB67A, 0x79E1, + 0xB67B, 0x79E2, 0xB67C, 0x79E5, 0xB67D, 0x79E8, 0xB67E, 0x79EA, + 0xB680, 0x79EC, 0xB681, 0x79EE, 0xB682, 0x79F1, 0xB683, 0x79F2, + 0xB684, 0x79F3, 0xB685, 0x79F4, 0xB686, 0x79F5, 0xB687, 0x79F6, + 0xB688, 0x79F7, 0xB689, 0x79F9, 0xB68A, 0x79FA, 0xB68B, 0x79FC, + 0xB68C, 0x79FE, 0xB68D, 0x79FF, 0xB68E, 0x7A01, 0xB68F, 0x7A04, + 0xB690, 0x7A05, 0xB691, 0x7A07, 0xB692, 0x7A08, 0xB693, 0x7A09, + 0xB694, 0x7A0A, 0xB695, 0x7A0C, 0xB696, 0x7A0F, 0xB697, 0x7A10, + 0xB698, 0x7A11, 0xB699, 0x7A12, 0xB69A, 0x7A13, 0xB69B, 0x7A15, + 0xB69C, 0x7A16, 0xB69D, 0x7A18, 0xB69E, 0x7A19, 0xB69F, 0x7A1B, + 0xB6A0, 0x7A1C, 0xB6A1, 0x4E01, 0xB6A2, 0x76EF, 0xB6A3, 0x53EE, + 0xB6A4, 0x9489, 0xB6A5, 0x9876, 0xB6A6, 0x9F0E, 0xB6A7, 0x952D, + 0xB6A8, 0x5B9A, 0xB6A9, 0x8BA2, 0xB6AA, 0x4E22, 0xB6AB, 0x4E1C, + 0xB6AC, 0x51AC, 0xB6AD, 0x8463, 0xB6AE, 0x61C2, 0xB6AF, 0x52A8, + 0xB6B0, 0x680B, 0xB6B1, 0x4F97, 0xB6B2, 0x606B, 0xB6B3, 0x51BB, + 0xB6B4, 0x6D1E, 0xB6B5, 0x515C, 0xB6B6, 0x6296, 0xB6B7, 0x6597, + 0xB6B8, 0x9661, 0xB6B9, 0x8C46, 0xB6BA, 0x9017, 0xB6BB, 0x75D8, + 0xB6BC, 0x90FD, 0xB6BD, 0x7763, 0xB6BE, 0x6BD2, 0xB6BF, 0x728A, + 0xB6C0, 0x72EC, 0xB6C1, 0x8BFB, 0xB6C2, 0x5835, 0xB6C3, 0x7779, + 0xB6C4, 0x8D4C, 0xB6C5, 0x675C, 0xB6C6, 0x9540, 0xB6C7, 0x809A, + 0xB6C8, 0x5EA6, 0xB6C9, 0x6E21, 0xB6CA, 0x5992, 0xB6CB, 0x7AEF, + 0xB6CC, 0x77ED, 0xB6CD, 0x953B, 0xB6CE, 0x6BB5, 0xB6CF, 0x65AD, + 0xB6D0, 0x7F0E, 0xB6D1, 0x5806, 0xB6D2, 0x5151, 0xB6D3, 0x961F, + 0xB6D4, 0x5BF9, 0xB6D5, 0x58A9, 0xB6D6, 0x5428, 0xB6D7, 0x8E72, + 0xB6D8, 0x6566, 0xB6D9, 0x987F, 0xB6DA, 0x56E4, 0xB6DB, 0x949D, + 0xB6DC, 0x76FE, 0xB6DD, 0x9041, 0xB6DE, 0x6387, 0xB6DF, 0x54C6, + 0xB6E0, 0x591A, 0xB6E1, 0x593A, 0xB6E2, 0x579B, 0xB6E3, 0x8EB2, + 0xB6E4, 0x6735, 0xB6E5, 0x8DFA, 0xB6E6, 0x8235, 0xB6E7, 0x5241, + 0xB6E8, 0x60F0, 0xB6E9, 0x5815, 0xB6EA, 0x86FE, 0xB6EB, 0x5CE8, + 0xB6EC, 0x9E45, 0xB6ED, 0x4FC4, 0xB6EE, 0x989D, 0xB6EF, 0x8BB9, + 0xB6F0, 0x5A25, 0xB6F1, 0x6076, 0xB6F2, 0x5384, 0xB6F3, 0x627C, + 0xB6F4, 0x904F, 0xB6F5, 0x9102, 0xB6F6, 0x997F, 0xB6F7, 0x6069, + 0xB6F8, 0x800C, 0xB6F9, 0x513F, 0xB6FA, 0x8033, 0xB6FB, 0x5C14, + 0xB6FC, 0x9975, 0xB6FD, 0x6D31, 0xB6FE, 0x4E8C, 0xB740, 0x7A1D, + 0xB741, 0x7A1F, 0xB742, 0x7A21, 0xB743, 0x7A22, 0xB744, 0x7A24, + 0xB745, 0x7A25, 0xB746, 0x7A26, 0xB747, 0x7A27, 0xB748, 0x7A28, + 0xB749, 0x7A29, 0xB74A, 0x7A2A, 0xB74B, 0x7A2B, 0xB74C, 0x7A2C, + 0xB74D, 0x7A2D, 0xB74E, 0x7A2E, 0xB74F, 0x7A2F, 0xB750, 0x7A30, + 0xB751, 0x7A31, 0xB752, 0x7A32, 0xB753, 0x7A34, 0xB754, 0x7A35, + 0xB755, 0x7A36, 0xB756, 0x7A38, 0xB757, 0x7A3A, 0xB758, 0x7A3E, + 0xB759, 0x7A40, 0xB75A, 0x7A41, 0xB75B, 0x7A42, 0xB75C, 0x7A43, + 0xB75D, 0x7A44, 0xB75E, 0x7A45, 0xB75F, 0x7A47, 0xB760, 0x7A48, + 0xB761, 0x7A49, 0xB762, 0x7A4A, 0xB763, 0x7A4B, 0xB764, 0x7A4C, + 0xB765, 0x7A4D, 0xB766, 0x7A4E, 0xB767, 0x7A4F, 0xB768, 0x7A50, + 0xB769, 0x7A52, 0xB76A, 0x7A53, 0xB76B, 0x7A54, 0xB76C, 0x7A55, + 0xB76D, 0x7A56, 0xB76E, 0x7A58, 0xB76F, 0x7A59, 0xB770, 0x7A5A, + 0xB771, 0x7A5B, 0xB772, 0x7A5C, 0xB773, 0x7A5D, 0xB774, 0x7A5E, + 0xB775, 0x7A5F, 0xB776, 0x7A60, 0xB777, 0x7A61, 0xB778, 0x7A62, + 0xB779, 0x7A63, 0xB77A, 0x7A64, 0xB77B, 0x7A65, 0xB77C, 0x7A66, + 0xB77D, 0x7A67, 0xB77E, 0x7A68, 0xB780, 0x7A69, 0xB781, 0x7A6A, + 0xB782, 0x7A6B, 0xB783, 0x7A6C, 0xB784, 0x7A6D, 0xB785, 0x7A6E, + 0xB786, 0x7A6F, 0xB787, 0x7A71, 0xB788, 0x7A72, 0xB789, 0x7A73, + 0xB78A, 0x7A75, 0xB78B, 0x7A7B, 0xB78C, 0x7A7C, 0xB78D, 0x7A7D, + 0xB78E, 0x7A7E, 0xB78F, 0x7A82, 0xB790, 0x7A85, 0xB791, 0x7A87, + 0xB792, 0x7A89, 0xB793, 0x7A8A, 0xB794, 0x7A8B, 0xB795, 0x7A8C, + 0xB796, 0x7A8E, 0xB797, 0x7A8F, 0xB798, 0x7A90, 0xB799, 0x7A93, + 0xB79A, 0x7A94, 0xB79B, 0x7A99, 0xB79C, 0x7A9A, 0xB79D, 0x7A9B, + 0xB79E, 0x7A9E, 0xB79F, 0x7AA1, 0xB7A0, 0x7AA2, 0xB7A1, 0x8D30, + 0xB7A2, 0x53D1, 0xB7A3, 0x7F5A, 0xB7A4, 0x7B4F, 0xB7A5, 0x4F10, + 0xB7A6, 0x4E4F, 0xB7A7, 0x9600, 0xB7A8, 0x6CD5, 0xB7A9, 0x73D0, + 0xB7AA, 0x85E9, 0xB7AB, 0x5E06, 0xB7AC, 0x756A, 0xB7AD, 0x7FFB, + 0xB7AE, 0x6A0A, 0xB7AF, 0x77FE, 0xB7B0, 0x9492, 0xB7B1, 0x7E41, + 0xB7B2, 0x51E1, 0xB7B3, 0x70E6, 0xB7B4, 0x53CD, 0xB7B5, 0x8FD4, + 0xB7B6, 0x8303, 0xB7B7, 0x8D29, 0xB7B8, 0x72AF, 0xB7B9, 0x996D, + 0xB7BA, 0x6CDB, 0xB7BB, 0x574A, 0xB7BC, 0x82B3, 0xB7BD, 0x65B9, + 0xB7BE, 0x80AA, 0xB7BF, 0x623F, 0xB7C0, 0x9632, 0xB7C1, 0x59A8, + 0xB7C2, 0x4EFF, 0xB7C3, 0x8BBF, 0xB7C4, 0x7EBA, 0xB7C5, 0x653E, + 0xB7C6, 0x83F2, 0xB7C7, 0x975E, 0xB7C8, 0x5561, 0xB7C9, 0x98DE, + 0xB7CA, 0x80A5, 0xB7CB, 0x532A, 0xB7CC, 0x8BFD, 0xB7CD, 0x5420, + 0xB7CE, 0x80BA, 0xB7CF, 0x5E9F, 0xB7D0, 0x6CB8, 0xB7D1, 0x8D39, + 0xB7D2, 0x82AC, 0xB7D3, 0x915A, 0xB7D4, 0x5429, 0xB7D5, 0x6C1B, + 0xB7D6, 0x5206, 0xB7D7, 0x7EB7, 0xB7D8, 0x575F, 0xB7D9, 0x711A, + 0xB7DA, 0x6C7E, 0xB7DB, 0x7C89, 0xB7DC, 0x594B, 0xB7DD, 0x4EFD, + 0xB7DE, 0x5FFF, 0xB7DF, 0x6124, 0xB7E0, 0x7CAA, 0xB7E1, 0x4E30, + 0xB7E2, 0x5C01, 0xB7E3, 0x67AB, 0xB7E4, 0x8702, 0xB7E5, 0x5CF0, + 0xB7E6, 0x950B, 0xB7E7, 0x98CE, 0xB7E8, 0x75AF, 0xB7E9, 0x70FD, + 0xB7EA, 0x9022, 0xB7EB, 0x51AF, 0xB7EC, 0x7F1D, 0xB7ED, 0x8BBD, + 0xB7EE, 0x5949, 0xB7EF, 0x51E4, 0xB7F0, 0x4F5B, 0xB7F1, 0x5426, + 0xB7F2, 0x592B, 0xB7F3, 0x6577, 0xB7F4, 0x80A4, 0xB7F5, 0x5B75, + 0xB7F6, 0x6276, 0xB7F7, 0x62C2, 0xB7F8, 0x8F90, 0xB7F9, 0x5E45, + 0xB7FA, 0x6C1F, 0xB7FB, 0x7B26, 0xB7FC, 0x4F0F, 0xB7FD, 0x4FD8, + 0xB7FE, 0x670D, 0xB840, 0x7AA3, 0xB841, 0x7AA4, 0xB842, 0x7AA7, + 0xB843, 0x7AA9, 0xB844, 0x7AAA, 0xB845, 0x7AAB, 0xB846, 0x7AAE, + 0xB847, 0x7AAF, 0xB848, 0x7AB0, 0xB849, 0x7AB1, 0xB84A, 0x7AB2, + 0xB84B, 0x7AB4, 0xB84C, 0x7AB5, 0xB84D, 0x7AB6, 0xB84E, 0x7AB7, + 0xB84F, 0x7AB8, 0xB850, 0x7AB9, 0xB851, 0x7ABA, 0xB852, 0x7ABB, + 0xB853, 0x7ABC, 0xB854, 0x7ABD, 0xB855, 0x7ABE, 0xB856, 0x7AC0, + 0xB857, 0x7AC1, 0xB858, 0x7AC2, 0xB859, 0x7AC3, 0xB85A, 0x7AC4, + 0xB85B, 0x7AC5, 0xB85C, 0x7AC6, 0xB85D, 0x7AC7, 0xB85E, 0x7AC8, + 0xB85F, 0x7AC9, 0xB860, 0x7ACA, 0xB861, 0x7ACC, 0xB862, 0x7ACD, + 0xB863, 0x7ACE, 0xB864, 0x7ACF, 0xB865, 0x7AD0, 0xB866, 0x7AD1, + 0xB867, 0x7AD2, 0xB868, 0x7AD3, 0xB869, 0x7AD4, 0xB86A, 0x7AD5, + 0xB86B, 0x7AD7, 0xB86C, 0x7AD8, 0xB86D, 0x7ADA, 0xB86E, 0x7ADB, + 0xB86F, 0x7ADC, 0xB870, 0x7ADD, 0xB871, 0x7AE1, 0xB872, 0x7AE2, + 0xB873, 0x7AE4, 0xB874, 0x7AE7, 0xB875, 0x7AE8, 0xB876, 0x7AE9, + 0xB877, 0x7AEA, 0xB878, 0x7AEB, 0xB879, 0x7AEC, 0xB87A, 0x7AEE, + 0xB87B, 0x7AF0, 0xB87C, 0x7AF1, 0xB87D, 0x7AF2, 0xB87E, 0x7AF3, + 0xB880, 0x7AF4, 0xB881, 0x7AF5, 0xB882, 0x7AF6, 0xB883, 0x7AF7, + 0xB884, 0x7AF8, 0xB885, 0x7AFB, 0xB886, 0x7AFC, 0xB887, 0x7AFE, + 0xB888, 0x7B00, 0xB889, 0x7B01, 0xB88A, 0x7B02, 0xB88B, 0x7B05, + 0xB88C, 0x7B07, 0xB88D, 0x7B09, 0xB88E, 0x7B0C, 0xB88F, 0x7B0D, + 0xB890, 0x7B0E, 0xB891, 0x7B10, 0xB892, 0x7B12, 0xB893, 0x7B13, + 0xB894, 0x7B16, 0xB895, 0x7B17, 0xB896, 0x7B18, 0xB897, 0x7B1A, + 0xB898, 0x7B1C, 0xB899, 0x7B1D, 0xB89A, 0x7B1F, 0xB89B, 0x7B21, + 0xB89C, 0x7B22, 0xB89D, 0x7B23, 0xB89E, 0x7B27, 0xB89F, 0x7B29, + 0xB8A0, 0x7B2D, 0xB8A1, 0x6D6E, 0xB8A2, 0x6DAA, 0xB8A3, 0x798F, + 0xB8A4, 0x88B1, 0xB8A5, 0x5F17, 0xB8A6, 0x752B, 0xB8A7, 0x629A, + 0xB8A8, 0x8F85, 0xB8A9, 0x4FEF, 0xB8AA, 0x91DC, 0xB8AB, 0x65A7, + 0xB8AC, 0x812F, 0xB8AD, 0x8151, 0xB8AE, 0x5E9C, 0xB8AF, 0x8150, + 0xB8B0, 0x8D74, 0xB8B1, 0x526F, 0xB8B2, 0x8986, 0xB8B3, 0x8D4B, + 0xB8B4, 0x590D, 0xB8B5, 0x5085, 0xB8B6, 0x4ED8, 0xB8B7, 0x961C, + 0xB8B8, 0x7236, 0xB8B9, 0x8179, 0xB8BA, 0x8D1F, 0xB8BB, 0x5BCC, + 0xB8BC, 0x8BA3, 0xB8BD, 0x9644, 0xB8BE, 0x5987, 0xB8BF, 0x7F1A, + 0xB8C0, 0x5490, 0xB8C1, 0x5676, 0xB8C2, 0x560E, 0xB8C3, 0x8BE5, + 0xB8C4, 0x6539, 0xB8C5, 0x6982, 0xB8C6, 0x9499, 0xB8C7, 0x76D6, + 0xB8C8, 0x6E89, 0xB8C9, 0x5E72, 0xB8CA, 0x7518, 0xB8CB, 0x6746, + 0xB8CC, 0x67D1, 0xB8CD, 0x7AFF, 0xB8CE, 0x809D, 0xB8CF, 0x8D76, + 0xB8D0, 0x611F, 0xB8D1, 0x79C6, 0xB8D2, 0x6562, 0xB8D3, 0x8D63, + 0xB8D4, 0x5188, 0xB8D5, 0x521A, 0xB8D6, 0x94A2, 0xB8D7, 0x7F38, + 0xB8D8, 0x809B, 0xB8D9, 0x7EB2, 0xB8DA, 0x5C97, 0xB8DB, 0x6E2F, + 0xB8DC, 0x6760, 0xB8DD, 0x7BD9, 0xB8DE, 0x768B, 0xB8DF, 0x9AD8, + 0xB8E0, 0x818F, 0xB8E1, 0x7F94, 0xB8E2, 0x7CD5, 0xB8E3, 0x641E, + 0xB8E4, 0x9550, 0xB8E5, 0x7A3F, 0xB8E6, 0x544A, 0xB8E7, 0x54E5, + 0xB8E8, 0x6B4C, 0xB8E9, 0x6401, 0xB8EA, 0x6208, 0xB8EB, 0x9E3D, + 0xB8EC, 0x80F3, 0xB8ED, 0x7599, 0xB8EE, 0x5272, 0xB8EF, 0x9769, + 0xB8F0, 0x845B, 0xB8F1, 0x683C, 0xB8F2, 0x86E4, 0xB8F3, 0x9601, + 0xB8F4, 0x9694, 0xB8F5, 0x94EC, 0xB8F6, 0x4E2A, 0xB8F7, 0x5404, + 0xB8F8, 0x7ED9, 0xB8F9, 0x6839, 0xB8FA, 0x8DDF, 0xB8FB, 0x8015, + 0xB8FC, 0x66F4, 0xB8FD, 0x5E9A, 0xB8FE, 0x7FB9, 0xB940, 0x7B2F, + 0xB941, 0x7B30, 0xB942, 0x7B32, 0xB943, 0x7B34, 0xB944, 0x7B35, + 0xB945, 0x7B36, 0xB946, 0x7B37, 0xB947, 0x7B39, 0xB948, 0x7B3B, + 0xB949, 0x7B3D, 0xB94A, 0x7B3F, 0xB94B, 0x7B40, 0xB94C, 0x7B41, + 0xB94D, 0x7B42, 0xB94E, 0x7B43, 0xB94F, 0x7B44, 0xB950, 0x7B46, + 0xB951, 0x7B48, 0xB952, 0x7B4A, 0xB953, 0x7B4D, 0xB954, 0x7B4E, + 0xB955, 0x7B53, 0xB956, 0x7B55, 0xB957, 0x7B57, 0xB958, 0x7B59, + 0xB959, 0x7B5C, 0xB95A, 0x7B5E, 0xB95B, 0x7B5F, 0xB95C, 0x7B61, + 0xB95D, 0x7B63, 0xB95E, 0x7B64, 0xB95F, 0x7B65, 0xB960, 0x7B66, + 0xB961, 0x7B67, 0xB962, 0x7B68, 0xB963, 0x7B69, 0xB964, 0x7B6A, + 0xB965, 0x7B6B, 0xB966, 0x7B6C, 0xB967, 0x7B6D, 0xB968, 0x7B6F, + 0xB969, 0x7B70, 0xB96A, 0x7B73, 0xB96B, 0x7B74, 0xB96C, 0x7B76, + 0xB96D, 0x7B78, 0xB96E, 0x7B7A, 0xB96F, 0x7B7C, 0xB970, 0x7B7D, + 0xB971, 0x7B7F, 0xB972, 0x7B81, 0xB973, 0x7B82, 0xB974, 0x7B83, + 0xB975, 0x7B84, 0xB976, 0x7B86, 0xB977, 0x7B87, 0xB978, 0x7B88, + 0xB979, 0x7B89, 0xB97A, 0x7B8A, 0xB97B, 0x7B8B, 0xB97C, 0x7B8C, + 0xB97D, 0x7B8E, 0xB97E, 0x7B8F, 0xB980, 0x7B91, 0xB981, 0x7B92, + 0xB982, 0x7B93, 0xB983, 0x7B96, 0xB984, 0x7B98, 0xB985, 0x7B99, + 0xB986, 0x7B9A, 0xB987, 0x7B9B, 0xB988, 0x7B9E, 0xB989, 0x7B9F, + 0xB98A, 0x7BA0, 0xB98B, 0x7BA3, 0xB98C, 0x7BA4, 0xB98D, 0x7BA5, + 0xB98E, 0x7BAE, 0xB98F, 0x7BAF, 0xB990, 0x7BB0, 0xB991, 0x7BB2, + 0xB992, 0x7BB3, 0xB993, 0x7BB5, 0xB994, 0x7BB6, 0xB995, 0x7BB7, + 0xB996, 0x7BB9, 0xB997, 0x7BBA, 0xB998, 0x7BBB, 0xB999, 0x7BBC, + 0xB99A, 0x7BBD, 0xB99B, 0x7BBE, 0xB99C, 0x7BBF, 0xB99D, 0x7BC0, + 0xB99E, 0x7BC2, 0xB99F, 0x7BC3, 0xB9A0, 0x7BC4, 0xB9A1, 0x57C2, + 0xB9A2, 0x803F, 0xB9A3, 0x6897, 0xB9A4, 0x5DE5, 0xB9A5, 0x653B, + 0xB9A6, 0x529F, 0xB9A7, 0x606D, 0xB9A8, 0x9F9A, 0xB9A9, 0x4F9B, + 0xB9AA, 0x8EAC, 0xB9AB, 0x516C, 0xB9AC, 0x5BAB, 0xB9AD, 0x5F13, + 0xB9AE, 0x5DE9, 0xB9AF, 0x6C5E, 0xB9B0, 0x62F1, 0xB9B1, 0x8D21, + 0xB9B2, 0x5171, 0xB9B3, 0x94A9, 0xB9B4, 0x52FE, 0xB9B5, 0x6C9F, + 0xB9B6, 0x82DF, 0xB9B7, 0x72D7, 0xB9B8, 0x57A2, 0xB9B9, 0x6784, + 0xB9BA, 0x8D2D, 0xB9BB, 0x591F, 0xB9BC, 0x8F9C, 0xB9BD, 0x83C7, + 0xB9BE, 0x5495, 0xB9BF, 0x7B8D, 0xB9C0, 0x4F30, 0xB9C1, 0x6CBD, + 0xB9C2, 0x5B64, 0xB9C3, 0x59D1, 0xB9C4, 0x9F13, 0xB9C5, 0x53E4, + 0xB9C6, 0x86CA, 0xB9C7, 0x9AA8, 0xB9C8, 0x8C37, 0xB9C9, 0x80A1, + 0xB9CA, 0x6545, 0xB9CB, 0x987E, 0xB9CC, 0x56FA, 0xB9CD, 0x96C7, + 0xB9CE, 0x522E, 0xB9CF, 0x74DC, 0xB9D0, 0x5250, 0xB9D1, 0x5BE1, + 0xB9D2, 0x6302, 0xB9D3, 0x8902, 0xB9D4, 0x4E56, 0xB9D5, 0x62D0, + 0xB9D6, 0x602A, 0xB9D7, 0x68FA, 0xB9D8, 0x5173, 0xB9D9, 0x5B98, + 0xB9DA, 0x51A0, 0xB9DB, 0x89C2, 0xB9DC, 0x7BA1, 0xB9DD, 0x9986, + 0xB9DE, 0x7F50, 0xB9DF, 0x60EF, 0xB9E0, 0x704C, 0xB9E1, 0x8D2F, + 0xB9E2, 0x5149, 0xB9E3, 0x5E7F, 0xB9E4, 0x901B, 0xB9E5, 0x7470, + 0xB9E6, 0x89C4, 0xB9E7, 0x572D, 0xB9E8, 0x7845, 0xB9E9, 0x5F52, + 0xB9EA, 0x9F9F, 0xB9EB, 0x95FA, 0xB9EC, 0x8F68, 0xB9ED, 0x9B3C, + 0xB9EE, 0x8BE1, 0xB9EF, 0x7678, 0xB9F0, 0x6842, 0xB9F1, 0x67DC, + 0xB9F2, 0x8DEA, 0xB9F3, 0x8D35, 0xB9F4, 0x523D, 0xB9F5, 0x8F8A, + 0xB9F6, 0x6EDA, 0xB9F7, 0x68CD, 0xB9F8, 0x9505, 0xB9F9, 0x90ED, + 0xB9FA, 0x56FD, 0xB9FB, 0x679C, 0xB9FC, 0x88F9, 0xB9FD, 0x8FC7, + 0xB9FE, 0x54C8, 0xBA40, 0x7BC5, 0xBA41, 0x7BC8, 0xBA42, 0x7BC9, + 0xBA43, 0x7BCA, 0xBA44, 0x7BCB, 0xBA45, 0x7BCD, 0xBA46, 0x7BCE, + 0xBA47, 0x7BCF, 0xBA48, 0x7BD0, 0xBA49, 0x7BD2, 0xBA4A, 0x7BD4, + 0xBA4B, 0x7BD5, 0xBA4C, 0x7BD6, 0xBA4D, 0x7BD7, 0xBA4E, 0x7BD8, + 0xBA4F, 0x7BDB, 0xBA50, 0x7BDC, 0xBA51, 0x7BDE, 0xBA52, 0x7BDF, + 0xBA53, 0x7BE0, 0xBA54, 0x7BE2, 0xBA55, 0x7BE3, 0xBA56, 0x7BE4, + 0xBA57, 0x7BE7, 0xBA58, 0x7BE8, 0xBA59, 0x7BE9, 0xBA5A, 0x7BEB, + 0xBA5B, 0x7BEC, 0xBA5C, 0x7BED, 0xBA5D, 0x7BEF, 0xBA5E, 0x7BF0, + 0xBA5F, 0x7BF2, 0xBA60, 0x7BF3, 0xBA61, 0x7BF4, 0xBA62, 0x7BF5, + 0xBA63, 0x7BF6, 0xBA64, 0x7BF8, 0xBA65, 0x7BF9, 0xBA66, 0x7BFA, + 0xBA67, 0x7BFB, 0xBA68, 0x7BFD, 0xBA69, 0x7BFF, 0xBA6A, 0x7C00, + 0xBA6B, 0x7C01, 0xBA6C, 0x7C02, 0xBA6D, 0x7C03, 0xBA6E, 0x7C04, + 0xBA6F, 0x7C05, 0xBA70, 0x7C06, 0xBA71, 0x7C08, 0xBA72, 0x7C09, + 0xBA73, 0x7C0A, 0xBA74, 0x7C0D, 0xBA75, 0x7C0E, 0xBA76, 0x7C10, + 0xBA77, 0x7C11, 0xBA78, 0x7C12, 0xBA79, 0x7C13, 0xBA7A, 0x7C14, + 0xBA7B, 0x7C15, 0xBA7C, 0x7C17, 0xBA7D, 0x7C18, 0xBA7E, 0x7C19, + 0xBA80, 0x7C1A, 0xBA81, 0x7C1B, 0xBA82, 0x7C1C, 0xBA83, 0x7C1D, + 0xBA84, 0x7C1E, 0xBA85, 0x7C20, 0xBA86, 0x7C21, 0xBA87, 0x7C22, + 0xBA88, 0x7C23, 0xBA89, 0x7C24, 0xBA8A, 0x7C25, 0xBA8B, 0x7C28, + 0xBA8C, 0x7C29, 0xBA8D, 0x7C2B, 0xBA8E, 0x7C2C, 0xBA8F, 0x7C2D, + 0xBA90, 0x7C2E, 0xBA91, 0x7C2F, 0xBA92, 0x7C30, 0xBA93, 0x7C31, + 0xBA94, 0x7C32, 0xBA95, 0x7C33, 0xBA96, 0x7C34, 0xBA97, 0x7C35, + 0xBA98, 0x7C36, 0xBA99, 0x7C37, 0xBA9A, 0x7C39, 0xBA9B, 0x7C3A, + 0xBA9C, 0x7C3B, 0xBA9D, 0x7C3C, 0xBA9E, 0x7C3D, 0xBA9F, 0x7C3E, + 0xBAA0, 0x7C42, 0xBAA1, 0x9AB8, 0xBAA2, 0x5B69, 0xBAA3, 0x6D77, + 0xBAA4, 0x6C26, 0xBAA5, 0x4EA5, 0xBAA6, 0x5BB3, 0xBAA7, 0x9A87, + 0xBAA8, 0x9163, 0xBAA9, 0x61A8, 0xBAAA, 0x90AF, 0xBAAB, 0x97E9, + 0xBAAC, 0x542B, 0xBAAD, 0x6DB5, 0xBAAE, 0x5BD2, 0xBAAF, 0x51FD, + 0xBAB0, 0x558A, 0xBAB1, 0x7F55, 0xBAB2, 0x7FF0, 0xBAB3, 0x64BC, + 0xBAB4, 0x634D, 0xBAB5, 0x65F1, 0xBAB6, 0x61BE, 0xBAB7, 0x608D, + 0xBAB8, 0x710A, 0xBAB9, 0x6C57, 0xBABA, 0x6C49, 0xBABB, 0x592F, + 0xBABC, 0x676D, 0xBABD, 0x822A, 0xBABE, 0x58D5, 0xBABF, 0x568E, + 0xBAC0, 0x8C6A, 0xBAC1, 0x6BEB, 0xBAC2, 0x90DD, 0xBAC3, 0x597D, + 0xBAC4, 0x8017, 0xBAC5, 0x53F7, 0xBAC6, 0x6D69, 0xBAC7, 0x5475, + 0xBAC8, 0x559D, 0xBAC9, 0x8377, 0xBACA, 0x83CF, 0xBACB, 0x6838, + 0xBACC, 0x79BE, 0xBACD, 0x548C, 0xBACE, 0x4F55, 0xBACF, 0x5408, + 0xBAD0, 0x76D2, 0xBAD1, 0x8C89, 0xBAD2, 0x9602, 0xBAD3, 0x6CB3, + 0xBAD4, 0x6DB8, 0xBAD5, 0x8D6B, 0xBAD6, 0x8910, 0xBAD7, 0x9E64, + 0xBAD8, 0x8D3A, 0xBAD9, 0x563F, 0xBADA, 0x9ED1, 0xBADB, 0x75D5, + 0xBADC, 0x5F88, 0xBADD, 0x72E0, 0xBADE, 0x6068, 0xBADF, 0x54FC, + 0xBAE0, 0x4EA8, 0xBAE1, 0x6A2A, 0xBAE2, 0x8861, 0xBAE3, 0x6052, + 0xBAE4, 0x8F70, 0xBAE5, 0x54C4, 0xBAE6, 0x70D8, 0xBAE7, 0x8679, + 0xBAE8, 0x9E3F, 0xBAE9, 0x6D2A, 0xBAEA, 0x5B8F, 0xBAEB, 0x5F18, + 0xBAEC, 0x7EA2, 0xBAED, 0x5589, 0xBAEE, 0x4FAF, 0xBAEF, 0x7334, + 0xBAF0, 0x543C, 0xBAF1, 0x539A, 0xBAF2, 0x5019, 0xBAF3, 0x540E, + 0xBAF4, 0x547C, 0xBAF5, 0x4E4E, 0xBAF6, 0x5FFD, 0xBAF7, 0x745A, + 0xBAF8, 0x58F6, 0xBAF9, 0x846B, 0xBAFA, 0x80E1, 0xBAFB, 0x8774, + 0xBAFC, 0x72D0, 0xBAFD, 0x7CCA, 0xBAFE, 0x6E56, 0xBB40, 0x7C43, + 0xBB41, 0x7C44, 0xBB42, 0x7C45, 0xBB43, 0x7C46, 0xBB44, 0x7C47, + 0xBB45, 0x7C48, 0xBB46, 0x7C49, 0xBB47, 0x7C4A, 0xBB48, 0x7C4B, + 0xBB49, 0x7C4C, 0xBB4A, 0x7C4E, 0xBB4B, 0x7C4F, 0xBB4C, 0x7C50, + 0xBB4D, 0x7C51, 0xBB4E, 0x7C52, 0xBB4F, 0x7C53, 0xBB50, 0x7C54, + 0xBB51, 0x7C55, 0xBB52, 0x7C56, 0xBB53, 0x7C57, 0xBB54, 0x7C58, + 0xBB55, 0x7C59, 0xBB56, 0x7C5A, 0xBB57, 0x7C5B, 0xBB58, 0x7C5C, + 0xBB59, 0x7C5D, 0xBB5A, 0x7C5E, 0xBB5B, 0x7C5F, 0xBB5C, 0x7C60, + 0xBB5D, 0x7C61, 0xBB5E, 0x7C62, 0xBB5F, 0x7C63, 0xBB60, 0x7C64, + 0xBB61, 0x7C65, 0xBB62, 0x7C66, 0xBB63, 0x7C67, 0xBB64, 0x7C68, + 0xBB65, 0x7C69, 0xBB66, 0x7C6A, 0xBB67, 0x7C6B, 0xBB68, 0x7C6C, + 0xBB69, 0x7C6D, 0xBB6A, 0x7C6E, 0xBB6B, 0x7C6F, 0xBB6C, 0x7C70, + 0xBB6D, 0x7C71, 0xBB6E, 0x7C72, 0xBB6F, 0x7C75, 0xBB70, 0x7C76, + 0xBB71, 0x7C77, 0xBB72, 0x7C78, 0xBB73, 0x7C79, 0xBB74, 0x7C7A, + 0xBB75, 0x7C7E, 0xBB76, 0x7C7F, 0xBB77, 0x7C80, 0xBB78, 0x7C81, + 0xBB79, 0x7C82, 0xBB7A, 0x7C83, 0xBB7B, 0x7C84, 0xBB7C, 0x7C85, + 0xBB7D, 0x7C86, 0xBB7E, 0x7C87, 0xBB80, 0x7C88, 0xBB81, 0x7C8A, + 0xBB82, 0x7C8B, 0xBB83, 0x7C8C, 0xBB84, 0x7C8D, 0xBB85, 0x7C8E, + 0xBB86, 0x7C8F, 0xBB87, 0x7C90, 0xBB88, 0x7C93, 0xBB89, 0x7C94, + 0xBB8A, 0x7C96, 0xBB8B, 0x7C99, 0xBB8C, 0x7C9A, 0xBB8D, 0x7C9B, + 0xBB8E, 0x7CA0, 0xBB8F, 0x7CA1, 0xBB90, 0x7CA3, 0xBB91, 0x7CA6, + 0xBB92, 0x7CA7, 0xBB93, 0x7CA8, 0xBB94, 0x7CA9, 0xBB95, 0x7CAB, + 0xBB96, 0x7CAC, 0xBB97, 0x7CAD, 0xBB98, 0x7CAF, 0xBB99, 0x7CB0, + 0xBB9A, 0x7CB4, 0xBB9B, 0x7CB5, 0xBB9C, 0x7CB6, 0xBB9D, 0x7CB7, + 0xBB9E, 0x7CB8, 0xBB9F, 0x7CBA, 0xBBA0, 0x7CBB, 0xBBA1, 0x5F27, + 0xBBA2, 0x864E, 0xBBA3, 0x552C, 0xBBA4, 0x62A4, 0xBBA5, 0x4E92, + 0xBBA6, 0x6CAA, 0xBBA7, 0x6237, 0xBBA8, 0x82B1, 0xBBA9, 0x54D7, + 0xBBAA, 0x534E, 0xBBAB, 0x733E, 0xBBAC, 0x6ED1, 0xBBAD, 0x753B, + 0xBBAE, 0x5212, 0xBBAF, 0x5316, 0xBBB0, 0x8BDD, 0xBBB1, 0x69D0, + 0xBBB2, 0x5F8A, 0xBBB3, 0x6000, 0xBBB4, 0x6DEE, 0xBBB5, 0x574F, + 0xBBB6, 0x6B22, 0xBBB7, 0x73AF, 0xBBB8, 0x6853, 0xBBB9, 0x8FD8, + 0xBBBA, 0x7F13, 0xBBBB, 0x6362, 0xBBBC, 0x60A3, 0xBBBD, 0x5524, + 0xBBBE, 0x75EA, 0xBBBF, 0x8C62, 0xBBC0, 0x7115, 0xBBC1, 0x6DA3, + 0xBBC2, 0x5BA6, 0xBBC3, 0x5E7B, 0xBBC4, 0x8352, 0xBBC5, 0x614C, + 0xBBC6, 0x9EC4, 0xBBC7, 0x78FA, 0xBBC8, 0x8757, 0xBBC9, 0x7C27, + 0xBBCA, 0x7687, 0xBBCB, 0x51F0, 0xBBCC, 0x60F6, 0xBBCD, 0x714C, + 0xBBCE, 0x6643, 0xBBCF, 0x5E4C, 0xBBD0, 0x604D, 0xBBD1, 0x8C0E, + 0xBBD2, 0x7070, 0xBBD3, 0x6325, 0xBBD4, 0x8F89, 0xBBD5, 0x5FBD, + 0xBBD6, 0x6062, 0xBBD7, 0x86D4, 0xBBD8, 0x56DE, 0xBBD9, 0x6BC1, + 0xBBDA, 0x6094, 0xBBDB, 0x6167, 0xBBDC, 0x5349, 0xBBDD, 0x60E0, + 0xBBDE, 0x6666, 0xBBDF, 0x8D3F, 0xBBE0, 0x79FD, 0xBBE1, 0x4F1A, + 0xBBE2, 0x70E9, 0xBBE3, 0x6C47, 0xBBE4, 0x8BB3, 0xBBE5, 0x8BF2, + 0xBBE6, 0x7ED8, 0xBBE7, 0x8364, 0xBBE8, 0x660F, 0xBBE9, 0x5A5A, + 0xBBEA, 0x9B42, 0xBBEB, 0x6D51, 0xBBEC, 0x6DF7, 0xBBED, 0x8C41, + 0xBBEE, 0x6D3B, 0xBBEF, 0x4F19, 0xBBF0, 0x706B, 0xBBF1, 0x83B7, + 0xBBF2, 0x6216, 0xBBF3, 0x60D1, 0xBBF4, 0x970D, 0xBBF5, 0x8D27, + 0xBBF6, 0x7978, 0xBBF7, 0x51FB, 0xBBF8, 0x573E, 0xBBF9, 0x57FA, + 0xBBFA, 0x673A, 0xBBFB, 0x7578, 0xBBFC, 0x7A3D, 0xBBFD, 0x79EF, + 0xBBFE, 0x7B95, 0xBC40, 0x7CBF, 0xBC41, 0x7CC0, 0xBC42, 0x7CC2, + 0xBC43, 0x7CC3, 0xBC44, 0x7CC4, 0xBC45, 0x7CC6, 0xBC46, 0x7CC9, + 0xBC47, 0x7CCB, 0xBC48, 0x7CCE, 0xBC49, 0x7CCF, 0xBC4A, 0x7CD0, + 0xBC4B, 0x7CD1, 0xBC4C, 0x7CD2, 0xBC4D, 0x7CD3, 0xBC4E, 0x7CD4, + 0xBC4F, 0x7CD8, 0xBC50, 0x7CDA, 0xBC51, 0x7CDB, 0xBC52, 0x7CDD, + 0xBC53, 0x7CDE, 0xBC54, 0x7CE1, 0xBC55, 0x7CE2, 0xBC56, 0x7CE3, + 0xBC57, 0x7CE4, 0xBC58, 0x7CE5, 0xBC59, 0x7CE6, 0xBC5A, 0x7CE7, + 0xBC5B, 0x7CE9, 0xBC5C, 0x7CEA, 0xBC5D, 0x7CEB, 0xBC5E, 0x7CEC, + 0xBC5F, 0x7CED, 0xBC60, 0x7CEE, 0xBC61, 0x7CF0, 0xBC62, 0x7CF1, + 0xBC63, 0x7CF2, 0xBC64, 0x7CF3, 0xBC65, 0x7CF4, 0xBC66, 0x7CF5, + 0xBC67, 0x7CF6, 0xBC68, 0x7CF7, 0xBC69, 0x7CF9, 0xBC6A, 0x7CFA, + 0xBC6B, 0x7CFC, 0xBC6C, 0x7CFD, 0xBC6D, 0x7CFE, 0xBC6E, 0x7CFF, + 0xBC6F, 0x7D00, 0xBC70, 0x7D01, 0xBC71, 0x7D02, 0xBC72, 0x7D03, + 0xBC73, 0x7D04, 0xBC74, 0x7D05, 0xBC75, 0x7D06, 0xBC76, 0x7D07, + 0xBC77, 0x7D08, 0xBC78, 0x7D09, 0xBC79, 0x7D0B, 0xBC7A, 0x7D0C, + 0xBC7B, 0x7D0D, 0xBC7C, 0x7D0E, 0xBC7D, 0x7D0F, 0xBC7E, 0x7D10, + 0xBC80, 0x7D11, 0xBC81, 0x7D12, 0xBC82, 0x7D13, 0xBC83, 0x7D14, + 0xBC84, 0x7D15, 0xBC85, 0x7D16, 0xBC86, 0x7D17, 0xBC87, 0x7D18, + 0xBC88, 0x7D19, 0xBC89, 0x7D1A, 0xBC8A, 0x7D1B, 0xBC8B, 0x7D1C, + 0xBC8C, 0x7D1D, 0xBC8D, 0x7D1E, 0xBC8E, 0x7D1F, 0xBC8F, 0x7D21, + 0xBC90, 0x7D23, 0xBC91, 0x7D24, 0xBC92, 0x7D25, 0xBC93, 0x7D26, + 0xBC94, 0x7D28, 0xBC95, 0x7D29, 0xBC96, 0x7D2A, 0xBC97, 0x7D2C, + 0xBC98, 0x7D2D, 0xBC99, 0x7D2E, 0xBC9A, 0x7D30, 0xBC9B, 0x7D31, + 0xBC9C, 0x7D32, 0xBC9D, 0x7D33, 0xBC9E, 0x7D34, 0xBC9F, 0x7D35, + 0xBCA0, 0x7D36, 0xBCA1, 0x808C, 0xBCA2, 0x9965, 0xBCA3, 0x8FF9, + 0xBCA4, 0x6FC0, 0xBCA5, 0x8BA5, 0xBCA6, 0x9E21, 0xBCA7, 0x59EC, + 0xBCA8, 0x7EE9, 0xBCA9, 0x7F09, 0xBCAA, 0x5409, 0xBCAB, 0x6781, + 0xBCAC, 0x68D8, 0xBCAD, 0x8F91, 0xBCAE, 0x7C4D, 0xBCAF, 0x96C6, + 0xBCB0, 0x53CA, 0xBCB1, 0x6025, 0xBCB2, 0x75BE, 0xBCB3, 0x6C72, + 0xBCB4, 0x5373, 0xBCB5, 0x5AC9, 0xBCB6, 0x7EA7, 0xBCB7, 0x6324, + 0xBCB8, 0x51E0, 0xBCB9, 0x810A, 0xBCBA, 0x5DF1, 0xBCBB, 0x84DF, + 0xBCBC, 0x6280, 0xBCBD, 0x5180, 0xBCBE, 0x5B63, 0xBCBF, 0x4F0E, + 0xBCC0, 0x796D, 0xBCC1, 0x5242, 0xBCC2, 0x60B8, 0xBCC3, 0x6D4E, + 0xBCC4, 0x5BC4, 0xBCC5, 0x5BC2, 0xBCC6, 0x8BA1, 0xBCC7, 0x8BB0, + 0xBCC8, 0x65E2, 0xBCC9, 0x5FCC, 0xBCCA, 0x9645, 0xBCCB, 0x5993, + 0xBCCC, 0x7EE7, 0xBCCD, 0x7EAA, 0xBCCE, 0x5609, 0xBCCF, 0x67B7, + 0xBCD0, 0x5939, 0xBCD1, 0x4F73, 0xBCD2, 0x5BB6, 0xBCD3, 0x52A0, + 0xBCD4, 0x835A, 0xBCD5, 0x988A, 0xBCD6, 0x8D3E, 0xBCD7, 0x7532, + 0xBCD8, 0x94BE, 0xBCD9, 0x5047, 0xBCDA, 0x7A3C, 0xBCDB, 0x4EF7, + 0xBCDC, 0x67B6, 0xBCDD, 0x9A7E, 0xBCDE, 0x5AC1, 0xBCDF, 0x6B7C, + 0xBCE0, 0x76D1, 0xBCE1, 0x575A, 0xBCE2, 0x5C16, 0xBCE3, 0x7B3A, + 0xBCE4, 0x95F4, 0xBCE5, 0x714E, 0xBCE6, 0x517C, 0xBCE7, 0x80A9, + 0xBCE8, 0x8270, 0xBCE9, 0x5978, 0xBCEA, 0x7F04, 0xBCEB, 0x8327, + 0xBCEC, 0x68C0, 0xBCED, 0x67EC, 0xBCEE, 0x78B1, 0xBCEF, 0x7877, + 0xBCF0, 0x62E3, 0xBCF1, 0x6361, 0xBCF2, 0x7B80, 0xBCF3, 0x4FED, + 0xBCF4, 0x526A, 0xBCF5, 0x51CF, 0xBCF6, 0x8350, 0xBCF7, 0x69DB, + 0xBCF8, 0x9274, 0xBCF9, 0x8DF5, 0xBCFA, 0x8D31, 0xBCFB, 0x89C1, + 0xBCFC, 0x952E, 0xBCFD, 0x7BAD, 0xBCFE, 0x4EF6, 0xBD40, 0x7D37, + 0xBD41, 0x7D38, 0xBD42, 0x7D39, 0xBD43, 0x7D3A, 0xBD44, 0x7D3B, + 0xBD45, 0x7D3C, 0xBD46, 0x7D3D, 0xBD47, 0x7D3E, 0xBD48, 0x7D3F, + 0xBD49, 0x7D40, 0xBD4A, 0x7D41, 0xBD4B, 0x7D42, 0xBD4C, 0x7D43, + 0xBD4D, 0x7D44, 0xBD4E, 0x7D45, 0xBD4F, 0x7D46, 0xBD50, 0x7D47, + 0xBD51, 0x7D48, 0xBD52, 0x7D49, 0xBD53, 0x7D4A, 0xBD54, 0x7D4B, + 0xBD55, 0x7D4C, 0xBD56, 0x7D4D, 0xBD57, 0x7D4E, 0xBD58, 0x7D4F, + 0xBD59, 0x7D50, 0xBD5A, 0x7D51, 0xBD5B, 0x7D52, 0xBD5C, 0x7D53, + 0xBD5D, 0x7D54, 0xBD5E, 0x7D55, 0xBD5F, 0x7D56, 0xBD60, 0x7D57, + 0xBD61, 0x7D58, 0xBD62, 0x7D59, 0xBD63, 0x7D5A, 0xBD64, 0x7D5B, + 0xBD65, 0x7D5C, 0xBD66, 0x7D5D, 0xBD67, 0x7D5E, 0xBD68, 0x7D5F, + 0xBD69, 0x7D60, 0xBD6A, 0x7D61, 0xBD6B, 0x7D62, 0xBD6C, 0x7D63, + 0xBD6D, 0x7D64, 0xBD6E, 0x7D65, 0xBD6F, 0x7D66, 0xBD70, 0x7D67, + 0xBD71, 0x7D68, 0xBD72, 0x7D69, 0xBD73, 0x7D6A, 0xBD74, 0x7D6B, + 0xBD75, 0x7D6C, 0xBD76, 0x7D6D, 0xBD77, 0x7D6F, 0xBD78, 0x7D70, + 0xBD79, 0x7D71, 0xBD7A, 0x7D72, 0xBD7B, 0x7D73, 0xBD7C, 0x7D74, + 0xBD7D, 0x7D75, 0xBD7E, 0x7D76, 0xBD80, 0x7D78, 0xBD81, 0x7D79, + 0xBD82, 0x7D7A, 0xBD83, 0x7D7B, 0xBD84, 0x7D7C, 0xBD85, 0x7D7D, + 0xBD86, 0x7D7E, 0xBD87, 0x7D7F, 0xBD88, 0x7D80, 0xBD89, 0x7D81, + 0xBD8A, 0x7D82, 0xBD8B, 0x7D83, 0xBD8C, 0x7D84, 0xBD8D, 0x7D85, + 0xBD8E, 0x7D86, 0xBD8F, 0x7D87, 0xBD90, 0x7D88, 0xBD91, 0x7D89, + 0xBD92, 0x7D8A, 0xBD93, 0x7D8B, 0xBD94, 0x7D8C, 0xBD95, 0x7D8D, + 0xBD96, 0x7D8E, 0xBD97, 0x7D8F, 0xBD98, 0x7D90, 0xBD99, 0x7D91, + 0xBD9A, 0x7D92, 0xBD9B, 0x7D93, 0xBD9C, 0x7D94, 0xBD9D, 0x7D95, + 0xBD9E, 0x7D96, 0xBD9F, 0x7D97, 0xBDA0, 0x7D98, 0xBDA1, 0x5065, + 0xBDA2, 0x8230, 0xBDA3, 0x5251, 0xBDA4, 0x996F, 0xBDA5, 0x6E10, + 0xBDA6, 0x6E85, 0xBDA7, 0x6DA7, 0xBDA8, 0x5EFA, 0xBDA9, 0x50F5, + 0xBDAA, 0x59DC, 0xBDAB, 0x5C06, 0xBDAC, 0x6D46, 0xBDAD, 0x6C5F, + 0xBDAE, 0x7586, 0xBDAF, 0x848B, 0xBDB0, 0x6868, 0xBDB1, 0x5956, + 0xBDB2, 0x8BB2, 0xBDB3, 0x5320, 0xBDB4, 0x9171, 0xBDB5, 0x964D, + 0xBDB6, 0x8549, 0xBDB7, 0x6912, 0xBDB8, 0x7901, 0xBDB9, 0x7126, + 0xBDBA, 0x80F6, 0xBDBB, 0x4EA4, 0xBDBC, 0x90CA, 0xBDBD, 0x6D47, + 0xBDBE, 0x9A84, 0xBDBF, 0x5A07, 0xBDC0, 0x56BC, 0xBDC1, 0x6405, + 0xBDC2, 0x94F0, 0xBDC3, 0x77EB, 0xBDC4, 0x4FA5, 0xBDC5, 0x811A, + 0xBDC6, 0x72E1, 0xBDC7, 0x89D2, 0xBDC8, 0x997A, 0xBDC9, 0x7F34, + 0xBDCA, 0x7EDE, 0xBDCB, 0x527F, 0xBDCC, 0x6559, 0xBDCD, 0x9175, + 0xBDCE, 0x8F7F, 0xBDCF, 0x8F83, 0xBDD0, 0x53EB, 0xBDD1, 0x7A96, + 0xBDD2, 0x63ED, 0xBDD3, 0x63A5, 0xBDD4, 0x7686, 0xBDD5, 0x79F8, + 0xBDD6, 0x8857, 0xBDD7, 0x9636, 0xBDD8, 0x622A, 0xBDD9, 0x52AB, + 0xBDDA, 0x8282, 0xBDDB, 0x6854, 0xBDDC, 0x6770, 0xBDDD, 0x6377, + 0xBDDE, 0x776B, 0xBDDF, 0x7AED, 0xBDE0, 0x6D01, 0xBDE1, 0x7ED3, + 0xBDE2, 0x89E3, 0xBDE3, 0x59D0, 0xBDE4, 0x6212, 0xBDE5, 0x85C9, + 0xBDE6, 0x82A5, 0xBDE7, 0x754C, 0xBDE8, 0x501F, 0xBDE9, 0x4ECB, + 0xBDEA, 0x75A5, 0xBDEB, 0x8BEB, 0xBDEC, 0x5C4A, 0xBDED, 0x5DFE, + 0xBDEE, 0x7B4B, 0xBDEF, 0x65A4, 0xBDF0, 0x91D1, 0xBDF1, 0x4ECA, + 0xBDF2, 0x6D25, 0xBDF3, 0x895F, 0xBDF4, 0x7D27, 0xBDF5, 0x9526, + 0xBDF6, 0x4EC5, 0xBDF7, 0x8C28, 0xBDF8, 0x8FDB, 0xBDF9, 0x9773, + 0xBDFA, 0x664B, 0xBDFB, 0x7981, 0xBDFC, 0x8FD1, 0xBDFD, 0x70EC, + 0xBDFE, 0x6D78, 0xBE40, 0x7D99, 0xBE41, 0x7D9A, 0xBE42, 0x7D9B, + 0xBE43, 0x7D9C, 0xBE44, 0x7D9D, 0xBE45, 0x7D9E, 0xBE46, 0x7D9F, + 0xBE47, 0x7DA0, 0xBE48, 0x7DA1, 0xBE49, 0x7DA2, 0xBE4A, 0x7DA3, + 0xBE4B, 0x7DA4, 0xBE4C, 0x7DA5, 0xBE4D, 0x7DA7, 0xBE4E, 0x7DA8, + 0xBE4F, 0x7DA9, 0xBE50, 0x7DAA, 0xBE51, 0x7DAB, 0xBE52, 0x7DAC, + 0xBE53, 0x7DAD, 0xBE54, 0x7DAF, 0xBE55, 0x7DB0, 0xBE56, 0x7DB1, + 0xBE57, 0x7DB2, 0xBE58, 0x7DB3, 0xBE59, 0x7DB4, 0xBE5A, 0x7DB5, + 0xBE5B, 0x7DB6, 0xBE5C, 0x7DB7, 0xBE5D, 0x7DB8, 0xBE5E, 0x7DB9, + 0xBE5F, 0x7DBA, 0xBE60, 0x7DBB, 0xBE61, 0x7DBC, 0xBE62, 0x7DBD, + 0xBE63, 0x7DBE, 0xBE64, 0x7DBF, 0xBE65, 0x7DC0, 0xBE66, 0x7DC1, + 0xBE67, 0x7DC2, 0xBE68, 0x7DC3, 0xBE69, 0x7DC4, 0xBE6A, 0x7DC5, + 0xBE6B, 0x7DC6, 0xBE6C, 0x7DC7, 0xBE6D, 0x7DC8, 0xBE6E, 0x7DC9, + 0xBE6F, 0x7DCA, 0xBE70, 0x7DCB, 0xBE71, 0x7DCC, 0xBE72, 0x7DCD, + 0xBE73, 0x7DCE, 0xBE74, 0x7DCF, 0xBE75, 0x7DD0, 0xBE76, 0x7DD1, + 0xBE77, 0x7DD2, 0xBE78, 0x7DD3, 0xBE79, 0x7DD4, 0xBE7A, 0x7DD5, + 0xBE7B, 0x7DD6, 0xBE7C, 0x7DD7, 0xBE7D, 0x7DD8, 0xBE7E, 0x7DD9, + 0xBE80, 0x7DDA, 0xBE81, 0x7DDB, 0xBE82, 0x7DDC, 0xBE83, 0x7DDD, + 0xBE84, 0x7DDE, 0xBE85, 0x7DDF, 0xBE86, 0x7DE0, 0xBE87, 0x7DE1, + 0xBE88, 0x7DE2, 0xBE89, 0x7DE3, 0xBE8A, 0x7DE4, 0xBE8B, 0x7DE5, + 0xBE8C, 0x7DE6, 0xBE8D, 0x7DE7, 0xBE8E, 0x7DE8, 0xBE8F, 0x7DE9, + 0xBE90, 0x7DEA, 0xBE91, 0x7DEB, 0xBE92, 0x7DEC, 0xBE93, 0x7DED, + 0xBE94, 0x7DEE, 0xBE95, 0x7DEF, 0xBE96, 0x7DF0, 0xBE97, 0x7DF1, + 0xBE98, 0x7DF2, 0xBE99, 0x7DF3, 0xBE9A, 0x7DF4, 0xBE9B, 0x7DF5, + 0xBE9C, 0x7DF6, 0xBE9D, 0x7DF7, 0xBE9E, 0x7DF8, 0xBE9F, 0x7DF9, + 0xBEA0, 0x7DFA, 0xBEA1, 0x5C3D, 0xBEA2, 0x52B2, 0xBEA3, 0x8346, + 0xBEA4, 0x5162, 0xBEA5, 0x830E, 0xBEA6, 0x775B, 0xBEA7, 0x6676, + 0xBEA8, 0x9CB8, 0xBEA9, 0x4EAC, 0xBEAA, 0x60CA, 0xBEAB, 0x7CBE, + 0xBEAC, 0x7CB3, 0xBEAD, 0x7ECF, 0xBEAE, 0x4E95, 0xBEAF, 0x8B66, + 0xBEB0, 0x666F, 0xBEB1, 0x9888, 0xBEB2, 0x9759, 0xBEB3, 0x5883, + 0xBEB4, 0x656C, 0xBEB5, 0x955C, 0xBEB6, 0x5F84, 0xBEB7, 0x75C9, + 0xBEB8, 0x9756, 0xBEB9, 0x7ADF, 0xBEBA, 0x7ADE, 0xBEBB, 0x51C0, + 0xBEBC, 0x70AF, 0xBEBD, 0x7A98, 0xBEBE, 0x63EA, 0xBEBF, 0x7A76, + 0xBEC0, 0x7EA0, 0xBEC1, 0x7396, 0xBEC2, 0x97ED, 0xBEC3, 0x4E45, + 0xBEC4, 0x7078, 0xBEC5, 0x4E5D, 0xBEC6, 0x9152, 0xBEC7, 0x53A9, + 0xBEC8, 0x6551, 0xBEC9, 0x65E7, 0xBECA, 0x81FC, 0xBECB, 0x8205, + 0xBECC, 0x548E, 0xBECD, 0x5C31, 0xBECE, 0x759A, 0xBECF, 0x97A0, + 0xBED0, 0x62D8, 0xBED1, 0x72D9, 0xBED2, 0x75BD, 0xBED3, 0x5C45, + 0xBED4, 0x9A79, 0xBED5, 0x83CA, 0xBED6, 0x5C40, 0xBED7, 0x5480, + 0xBED8, 0x77E9, 0xBED9, 0x4E3E, 0xBEDA, 0x6CAE, 0xBEDB, 0x805A, + 0xBEDC, 0x62D2, 0xBEDD, 0x636E, 0xBEDE, 0x5DE8, 0xBEDF, 0x5177, + 0xBEE0, 0x8DDD, 0xBEE1, 0x8E1E, 0xBEE2, 0x952F, 0xBEE3, 0x4FF1, + 0xBEE4, 0x53E5, 0xBEE5, 0x60E7, 0xBEE6, 0x70AC, 0xBEE7, 0x5267, + 0xBEE8, 0x6350, 0xBEE9, 0x9E43, 0xBEEA, 0x5A1F, 0xBEEB, 0x5026, + 0xBEEC, 0x7737, 0xBEED, 0x5377, 0xBEEE, 0x7EE2, 0xBEEF, 0x6485, + 0xBEF0, 0x652B, 0xBEF1, 0x6289, 0xBEF2, 0x6398, 0xBEF3, 0x5014, + 0xBEF4, 0x7235, 0xBEF5, 0x89C9, 0xBEF6, 0x51B3, 0xBEF7, 0x8BC0, + 0xBEF8, 0x7EDD, 0xBEF9, 0x5747, 0xBEFA, 0x83CC, 0xBEFB, 0x94A7, + 0xBEFC, 0x519B, 0xBEFD, 0x541B, 0xBEFE, 0x5CFB, 0xBF40, 0x7DFB, + 0xBF41, 0x7DFC, 0xBF42, 0x7DFD, 0xBF43, 0x7DFE, 0xBF44, 0x7DFF, + 0xBF45, 0x7E00, 0xBF46, 0x7E01, 0xBF47, 0x7E02, 0xBF48, 0x7E03, + 0xBF49, 0x7E04, 0xBF4A, 0x7E05, 0xBF4B, 0x7E06, 0xBF4C, 0x7E07, + 0xBF4D, 0x7E08, 0xBF4E, 0x7E09, 0xBF4F, 0x7E0A, 0xBF50, 0x7E0B, + 0xBF51, 0x7E0C, 0xBF52, 0x7E0D, 0xBF53, 0x7E0E, 0xBF54, 0x7E0F, + 0xBF55, 0x7E10, 0xBF56, 0x7E11, 0xBF57, 0x7E12, 0xBF58, 0x7E13, + 0xBF59, 0x7E14, 0xBF5A, 0x7E15, 0xBF5B, 0x7E16, 0xBF5C, 0x7E17, + 0xBF5D, 0x7E18, 0xBF5E, 0x7E19, 0xBF5F, 0x7E1A, 0xBF60, 0x7E1B, + 0xBF61, 0x7E1C, 0xBF62, 0x7E1D, 0xBF63, 0x7E1E, 0xBF64, 0x7E1F, + 0xBF65, 0x7E20, 0xBF66, 0x7E21, 0xBF67, 0x7E22, 0xBF68, 0x7E23, + 0xBF69, 0x7E24, 0xBF6A, 0x7E25, 0xBF6B, 0x7E26, 0xBF6C, 0x7E27, + 0xBF6D, 0x7E28, 0xBF6E, 0x7E29, 0xBF6F, 0x7E2A, 0xBF70, 0x7E2B, + 0xBF71, 0x7E2C, 0xBF72, 0x7E2D, 0xBF73, 0x7E2E, 0xBF74, 0x7E2F, + 0xBF75, 0x7E30, 0xBF76, 0x7E31, 0xBF77, 0x7E32, 0xBF78, 0x7E33, + 0xBF79, 0x7E34, 0xBF7A, 0x7E35, 0xBF7B, 0x7E36, 0xBF7C, 0x7E37, + 0xBF7D, 0x7E38, 0xBF7E, 0x7E39, 0xBF80, 0x7E3A, 0xBF81, 0x7E3C, + 0xBF82, 0x7E3D, 0xBF83, 0x7E3E, 0xBF84, 0x7E3F, 0xBF85, 0x7E40, + 0xBF86, 0x7E42, 0xBF87, 0x7E43, 0xBF88, 0x7E44, 0xBF89, 0x7E45, + 0xBF8A, 0x7E46, 0xBF8B, 0x7E48, 0xBF8C, 0x7E49, 0xBF8D, 0x7E4A, + 0xBF8E, 0x7E4B, 0xBF8F, 0x7E4C, 0xBF90, 0x7E4D, 0xBF91, 0x7E4E, + 0xBF92, 0x7E4F, 0xBF93, 0x7E50, 0xBF94, 0x7E51, 0xBF95, 0x7E52, + 0xBF96, 0x7E53, 0xBF97, 0x7E54, 0xBF98, 0x7E55, 0xBF99, 0x7E56, + 0xBF9A, 0x7E57, 0xBF9B, 0x7E58, 0xBF9C, 0x7E59, 0xBF9D, 0x7E5A, + 0xBF9E, 0x7E5B, 0xBF9F, 0x7E5C, 0xBFA0, 0x7E5D, 0xBFA1, 0x4FCA, + 0xBFA2, 0x7AE3, 0xBFA3, 0x6D5A, 0xBFA4, 0x90E1, 0xBFA5, 0x9A8F, + 0xBFA6, 0x5580, 0xBFA7, 0x5496, 0xBFA8, 0x5361, 0xBFA9, 0x54AF, + 0xBFAA, 0x5F00, 0xBFAB, 0x63E9, 0xBFAC, 0x6977, 0xBFAD, 0x51EF, + 0xBFAE, 0x6168, 0xBFAF, 0x520A, 0xBFB0, 0x582A, 0xBFB1, 0x52D8, + 0xBFB2, 0x574E, 0xBFB3, 0x780D, 0xBFB4, 0x770B, 0xBFB5, 0x5EB7, + 0xBFB6, 0x6177, 0xBFB7, 0x7CE0, 0xBFB8, 0x625B, 0xBFB9, 0x6297, + 0xBFBA, 0x4EA2, 0xBFBB, 0x7095, 0xBFBC, 0x8003, 0xBFBD, 0x62F7, + 0xBFBE, 0x70E4, 0xBFBF, 0x9760, 0xBFC0, 0x5777, 0xBFC1, 0x82DB, + 0xBFC2, 0x67EF, 0xBFC3, 0x68F5, 0xBFC4, 0x78D5, 0xBFC5, 0x9897, + 0xBFC6, 0x79D1, 0xBFC7, 0x58F3, 0xBFC8, 0x54B3, 0xBFC9, 0x53EF, + 0xBFCA, 0x6E34, 0xBFCB, 0x514B, 0xBFCC, 0x523B, 0xBFCD, 0x5BA2, + 0xBFCE, 0x8BFE, 0xBFCF, 0x80AF, 0xBFD0, 0x5543, 0xBFD1, 0x57A6, + 0xBFD2, 0x6073, 0xBFD3, 0x5751, 0xBFD4, 0x542D, 0xBFD5, 0x7A7A, + 0xBFD6, 0x6050, 0xBFD7, 0x5B54, 0xBFD8, 0x63A7, 0xBFD9, 0x62A0, + 0xBFDA, 0x53E3, 0xBFDB, 0x6263, 0xBFDC, 0x5BC7, 0xBFDD, 0x67AF, + 0xBFDE, 0x54ED, 0xBFDF, 0x7A9F, 0xBFE0, 0x82E6, 0xBFE1, 0x9177, + 0xBFE2, 0x5E93, 0xBFE3, 0x88E4, 0xBFE4, 0x5938, 0xBFE5, 0x57AE, + 0xBFE6, 0x630E, 0xBFE7, 0x8DE8, 0xBFE8, 0x80EF, 0xBFE9, 0x5757, + 0xBFEA, 0x7B77, 0xBFEB, 0x4FA9, 0xBFEC, 0x5FEB, 0xBFED, 0x5BBD, + 0xBFEE, 0x6B3E, 0xBFEF, 0x5321, 0xBFF0, 0x7B50, 0xBFF1, 0x72C2, + 0xBFF2, 0x6846, 0xBFF3, 0x77FF, 0xBFF4, 0x7736, 0xBFF5, 0x65F7, + 0xBFF6, 0x51B5, 0xBFF7, 0x4E8F, 0xBFF8, 0x76D4, 0xBFF9, 0x5CBF, + 0xBFFA, 0x7AA5, 0xBFFB, 0x8475, 0xBFFC, 0x594E, 0xBFFD, 0x9B41, + 0xBFFE, 0x5080, 0xC040, 0x7E5E, 0xC041, 0x7E5F, 0xC042, 0x7E60, + 0xC043, 0x7E61, 0xC044, 0x7E62, 0xC045, 0x7E63, 0xC046, 0x7E64, + 0xC047, 0x7E65, 0xC048, 0x7E66, 0xC049, 0x7E67, 0xC04A, 0x7E68, + 0xC04B, 0x7E69, 0xC04C, 0x7E6A, 0xC04D, 0x7E6B, 0xC04E, 0x7E6C, + 0xC04F, 0x7E6D, 0xC050, 0x7E6E, 0xC051, 0x7E6F, 0xC052, 0x7E70, + 0xC053, 0x7E71, 0xC054, 0x7E72, 0xC055, 0x7E73, 0xC056, 0x7E74, + 0xC057, 0x7E75, 0xC058, 0x7E76, 0xC059, 0x7E77, 0xC05A, 0x7E78, + 0xC05B, 0x7E79, 0xC05C, 0x7E7A, 0xC05D, 0x7E7B, 0xC05E, 0x7E7C, + 0xC05F, 0x7E7D, 0xC060, 0x7E7E, 0xC061, 0x7E7F, 0xC062, 0x7E80, + 0xC063, 0x7E81, 0xC064, 0x7E83, 0xC065, 0x7E84, 0xC066, 0x7E85, + 0xC067, 0x7E86, 0xC068, 0x7E87, 0xC069, 0x7E88, 0xC06A, 0x7E89, + 0xC06B, 0x7E8A, 0xC06C, 0x7E8B, 0xC06D, 0x7E8C, 0xC06E, 0x7E8D, + 0xC06F, 0x7E8E, 0xC070, 0x7E8F, 0xC071, 0x7E90, 0xC072, 0x7E91, + 0xC073, 0x7E92, 0xC074, 0x7E93, 0xC075, 0x7E94, 0xC076, 0x7E95, + 0xC077, 0x7E96, 0xC078, 0x7E97, 0xC079, 0x7E98, 0xC07A, 0x7E99, + 0xC07B, 0x7E9A, 0xC07C, 0x7E9C, 0xC07D, 0x7E9D, 0xC07E, 0x7E9E, + 0xC080, 0x7EAE, 0xC081, 0x7EB4, 0xC082, 0x7EBB, 0xC083, 0x7EBC, + 0xC084, 0x7ED6, 0xC085, 0x7EE4, 0xC086, 0x7EEC, 0xC087, 0x7EF9, + 0xC088, 0x7F0A, 0xC089, 0x7F10, 0xC08A, 0x7F1E, 0xC08B, 0x7F37, + 0xC08C, 0x7F39, 0xC08D, 0x7F3B, 0xC08E, 0x7F3C, 0xC08F, 0x7F3D, + 0xC090, 0x7F3E, 0xC091, 0x7F3F, 0xC092, 0x7F40, 0xC093, 0x7F41, + 0xC094, 0x7F43, 0xC095, 0x7F46, 0xC096, 0x7F47, 0xC097, 0x7F48, + 0xC098, 0x7F49, 0xC099, 0x7F4A, 0xC09A, 0x7F4B, 0xC09B, 0x7F4C, + 0xC09C, 0x7F4D, 0xC09D, 0x7F4E, 0xC09E, 0x7F4F, 0xC09F, 0x7F52, + 0xC0A0, 0x7F53, 0xC0A1, 0x9988, 0xC0A2, 0x6127, 0xC0A3, 0x6E83, + 0xC0A4, 0x5764, 0xC0A5, 0x6606, 0xC0A6, 0x6346, 0xC0A7, 0x56F0, + 0xC0A8, 0x62EC, 0xC0A9, 0x6269, 0xC0AA, 0x5ED3, 0xC0AB, 0x9614, + 0xC0AC, 0x5783, 0xC0AD, 0x62C9, 0xC0AE, 0x5587, 0xC0AF, 0x8721, + 0xC0B0, 0x814A, 0xC0B1, 0x8FA3, 0xC0B2, 0x5566, 0xC0B3, 0x83B1, + 0xC0B4, 0x6765, 0xC0B5, 0x8D56, 0xC0B6, 0x84DD, 0xC0B7, 0x5A6A, + 0xC0B8, 0x680F, 0xC0B9, 0x62E6, 0xC0BA, 0x7BEE, 0xC0BB, 0x9611, + 0xC0BC, 0x5170, 0xC0BD, 0x6F9C, 0xC0BE, 0x8C30, 0xC0BF, 0x63FD, + 0xC0C0, 0x89C8, 0xC0C1, 0x61D2, 0xC0C2, 0x7F06, 0xC0C3, 0x70C2, + 0xC0C4, 0x6EE5, 0xC0C5, 0x7405, 0xC0C6, 0x6994, 0xC0C7, 0x72FC, + 0xC0C8, 0x5ECA, 0xC0C9, 0x90CE, 0xC0CA, 0x6717, 0xC0CB, 0x6D6A, + 0xC0CC, 0x635E, 0xC0CD, 0x52B3, 0xC0CE, 0x7262, 0xC0CF, 0x8001, + 0xC0D0, 0x4F6C, 0xC0D1, 0x59E5, 0xC0D2, 0x916A, 0xC0D3, 0x70D9, + 0xC0D4, 0x6D9D, 0xC0D5, 0x52D2, 0xC0D6, 0x4E50, 0xC0D7, 0x96F7, + 0xC0D8, 0x956D, 0xC0D9, 0x857E, 0xC0DA, 0x78CA, 0xC0DB, 0x7D2F, + 0xC0DC, 0x5121, 0xC0DD, 0x5792, 0xC0DE, 0x64C2, 0xC0DF, 0x808B, + 0xC0E0, 0x7C7B, 0xC0E1, 0x6CEA, 0xC0E2, 0x68F1, 0xC0E3, 0x695E, + 0xC0E4, 0x51B7, 0xC0E5, 0x5398, 0xC0E6, 0x68A8, 0xC0E7, 0x7281, + 0xC0E8, 0x9ECE, 0xC0E9, 0x7BF1, 0xC0EA, 0x72F8, 0xC0EB, 0x79BB, + 0xC0EC, 0x6F13, 0xC0ED, 0x7406, 0xC0EE, 0x674E, 0xC0EF, 0x91CC, + 0xC0F0, 0x9CA4, 0xC0F1, 0x793C, 0xC0F2, 0x8389, 0xC0F3, 0x8354, + 0xC0F4, 0x540F, 0xC0F5, 0x6817, 0xC0F6, 0x4E3D, 0xC0F7, 0x5389, + 0xC0F8, 0x52B1, 0xC0F9, 0x783E, 0xC0FA, 0x5386, 0xC0FB, 0x5229, + 0xC0FC, 0x5088, 0xC0FD, 0x4F8B, 0xC0FE, 0x4FD0, 0xC140, 0x7F56, + 0xC141, 0x7F59, 0xC142, 0x7F5B, 0xC143, 0x7F5C, 0xC144, 0x7F5D, + 0xC145, 0x7F5E, 0xC146, 0x7F60, 0xC147, 0x7F63, 0xC148, 0x7F64, + 0xC149, 0x7F65, 0xC14A, 0x7F66, 0xC14B, 0x7F67, 0xC14C, 0x7F6B, + 0xC14D, 0x7F6C, 0xC14E, 0x7F6D, 0xC14F, 0x7F6F, 0xC150, 0x7F70, + 0xC151, 0x7F73, 0xC152, 0x7F75, 0xC153, 0x7F76, 0xC154, 0x7F77, + 0xC155, 0x7F78, 0xC156, 0x7F7A, 0xC157, 0x7F7B, 0xC158, 0x7F7C, + 0xC159, 0x7F7D, 0xC15A, 0x7F7F, 0xC15B, 0x7F80, 0xC15C, 0x7F82, + 0xC15D, 0x7F83, 0xC15E, 0x7F84, 0xC15F, 0x7F85, 0xC160, 0x7F86, + 0xC161, 0x7F87, 0xC162, 0x7F88, 0xC163, 0x7F89, 0xC164, 0x7F8B, + 0xC165, 0x7F8D, 0xC166, 0x7F8F, 0xC167, 0x7F90, 0xC168, 0x7F91, + 0xC169, 0x7F92, 0xC16A, 0x7F93, 0xC16B, 0x7F95, 0xC16C, 0x7F96, + 0xC16D, 0x7F97, 0xC16E, 0x7F98, 0xC16F, 0x7F99, 0xC170, 0x7F9B, + 0xC171, 0x7F9C, 0xC172, 0x7FA0, 0xC173, 0x7FA2, 0xC174, 0x7FA3, + 0xC175, 0x7FA5, 0xC176, 0x7FA6, 0xC177, 0x7FA8, 0xC178, 0x7FA9, + 0xC179, 0x7FAA, 0xC17A, 0x7FAB, 0xC17B, 0x7FAC, 0xC17C, 0x7FAD, + 0xC17D, 0x7FAE, 0xC17E, 0x7FB1, 0xC180, 0x7FB3, 0xC181, 0x7FB4, + 0xC182, 0x7FB5, 0xC183, 0x7FB6, 0xC184, 0x7FB7, 0xC185, 0x7FBA, + 0xC186, 0x7FBB, 0xC187, 0x7FBE, 0xC188, 0x7FC0, 0xC189, 0x7FC2, + 0xC18A, 0x7FC3, 0xC18B, 0x7FC4, 0xC18C, 0x7FC6, 0xC18D, 0x7FC7, + 0xC18E, 0x7FC8, 0xC18F, 0x7FC9, 0xC190, 0x7FCB, 0xC191, 0x7FCD, + 0xC192, 0x7FCF, 0xC193, 0x7FD0, 0xC194, 0x7FD1, 0xC195, 0x7FD2, + 0xC196, 0x7FD3, 0xC197, 0x7FD6, 0xC198, 0x7FD7, 0xC199, 0x7FD9, + 0xC19A, 0x7FDA, 0xC19B, 0x7FDB, 0xC19C, 0x7FDC, 0xC19D, 0x7FDD, + 0xC19E, 0x7FDE, 0xC19F, 0x7FE2, 0xC1A0, 0x7FE3, 0xC1A1, 0x75E2, + 0xC1A2, 0x7ACB, 0xC1A3, 0x7C92, 0xC1A4, 0x6CA5, 0xC1A5, 0x96B6, + 0xC1A6, 0x529B, 0xC1A7, 0x7483, 0xC1A8, 0x54E9, 0xC1A9, 0x4FE9, + 0xC1AA, 0x8054, 0xC1AB, 0x83B2, 0xC1AC, 0x8FDE, 0xC1AD, 0x9570, + 0xC1AE, 0x5EC9, 0xC1AF, 0x601C, 0xC1B0, 0x6D9F, 0xC1B1, 0x5E18, + 0xC1B2, 0x655B, 0xC1B3, 0x8138, 0xC1B4, 0x94FE, 0xC1B5, 0x604B, + 0xC1B6, 0x70BC, 0xC1B7, 0x7EC3, 0xC1B8, 0x7CAE, 0xC1B9, 0x51C9, + 0xC1BA, 0x6881, 0xC1BB, 0x7CB1, 0xC1BC, 0x826F, 0xC1BD, 0x4E24, + 0xC1BE, 0x8F86, 0xC1BF, 0x91CF, 0xC1C0, 0x667E, 0xC1C1, 0x4EAE, + 0xC1C2, 0x8C05, 0xC1C3, 0x64A9, 0xC1C4, 0x804A, 0xC1C5, 0x50DA, + 0xC1C6, 0x7597, 0xC1C7, 0x71CE, 0xC1C8, 0x5BE5, 0xC1C9, 0x8FBD, + 0xC1CA, 0x6F66, 0xC1CB, 0x4E86, 0xC1CC, 0x6482, 0xC1CD, 0x9563, + 0xC1CE, 0x5ED6, 0xC1CF, 0x6599, 0xC1D0, 0x5217, 0xC1D1, 0x88C2, + 0xC1D2, 0x70C8, 0xC1D3, 0x52A3, 0xC1D4, 0x730E, 0xC1D5, 0x7433, + 0xC1D6, 0x6797, 0xC1D7, 0x78F7, 0xC1D8, 0x9716, 0xC1D9, 0x4E34, + 0xC1DA, 0x90BB, 0xC1DB, 0x9CDE, 0xC1DC, 0x6DCB, 0xC1DD, 0x51DB, + 0xC1DE, 0x8D41, 0xC1DF, 0x541D, 0xC1E0, 0x62CE, 0xC1E1, 0x73B2, + 0xC1E2, 0x83F1, 0xC1E3, 0x96F6, 0xC1E4, 0x9F84, 0xC1E5, 0x94C3, + 0xC1E6, 0x4F36, 0xC1E7, 0x7F9A, 0xC1E8, 0x51CC, 0xC1E9, 0x7075, + 0xC1EA, 0x9675, 0xC1EB, 0x5CAD, 0xC1EC, 0x9886, 0xC1ED, 0x53E6, + 0xC1EE, 0x4EE4, 0xC1EF, 0x6E9C, 0xC1F0, 0x7409, 0xC1F1, 0x69B4, + 0xC1F2, 0x786B, 0xC1F3, 0x998F, 0xC1F4, 0x7559, 0xC1F5, 0x5218, + 0xC1F6, 0x7624, 0xC1F7, 0x6D41, 0xC1F8, 0x67F3, 0xC1F9, 0x516D, + 0xC1FA, 0x9F99, 0xC1FB, 0x804B, 0xC1FC, 0x5499, 0xC1FD, 0x7B3C, + 0xC1FE, 0x7ABF, 0xC240, 0x7FE4, 0xC241, 0x7FE7, 0xC242, 0x7FE8, + 0xC243, 0x7FEA, 0xC244, 0x7FEB, 0xC245, 0x7FEC, 0xC246, 0x7FED, + 0xC247, 0x7FEF, 0xC248, 0x7FF2, 0xC249, 0x7FF4, 0xC24A, 0x7FF5, + 0xC24B, 0x7FF6, 0xC24C, 0x7FF7, 0xC24D, 0x7FF8, 0xC24E, 0x7FF9, + 0xC24F, 0x7FFA, 0xC250, 0x7FFD, 0xC251, 0x7FFE, 0xC252, 0x7FFF, + 0xC253, 0x8002, 0xC254, 0x8007, 0xC255, 0x8008, 0xC256, 0x8009, + 0xC257, 0x800A, 0xC258, 0x800E, 0xC259, 0x800F, 0xC25A, 0x8011, + 0xC25B, 0x8013, 0xC25C, 0x801A, 0xC25D, 0x801B, 0xC25E, 0x801D, + 0xC25F, 0x801E, 0xC260, 0x801F, 0xC261, 0x8021, 0xC262, 0x8023, + 0xC263, 0x8024, 0xC264, 0x802B, 0xC265, 0x802C, 0xC266, 0x802D, + 0xC267, 0x802E, 0xC268, 0x802F, 0xC269, 0x8030, 0xC26A, 0x8032, + 0xC26B, 0x8034, 0xC26C, 0x8039, 0xC26D, 0x803A, 0xC26E, 0x803C, + 0xC26F, 0x803E, 0xC270, 0x8040, 0xC271, 0x8041, 0xC272, 0x8044, + 0xC273, 0x8045, 0xC274, 0x8047, 0xC275, 0x8048, 0xC276, 0x8049, + 0xC277, 0x804E, 0xC278, 0x804F, 0xC279, 0x8050, 0xC27A, 0x8051, + 0xC27B, 0x8053, 0xC27C, 0x8055, 0xC27D, 0x8056, 0xC27E, 0x8057, + 0xC280, 0x8059, 0xC281, 0x805B, 0xC282, 0x805C, 0xC283, 0x805D, + 0xC284, 0x805E, 0xC285, 0x805F, 0xC286, 0x8060, 0xC287, 0x8061, + 0xC288, 0x8062, 0xC289, 0x8063, 0xC28A, 0x8064, 0xC28B, 0x8065, + 0xC28C, 0x8066, 0xC28D, 0x8067, 0xC28E, 0x8068, 0xC28F, 0x806B, + 0xC290, 0x806C, 0xC291, 0x806D, 0xC292, 0x806E, 0xC293, 0x806F, + 0xC294, 0x8070, 0xC295, 0x8072, 0xC296, 0x8073, 0xC297, 0x8074, + 0xC298, 0x8075, 0xC299, 0x8076, 0xC29A, 0x8077, 0xC29B, 0x8078, + 0xC29C, 0x8079, 0xC29D, 0x807A, 0xC29E, 0x807B, 0xC29F, 0x807C, + 0xC2A0, 0x807D, 0xC2A1, 0x9686, 0xC2A2, 0x5784, 0xC2A3, 0x62E2, + 0xC2A4, 0x9647, 0xC2A5, 0x697C, 0xC2A6, 0x5A04, 0xC2A7, 0x6402, + 0xC2A8, 0x7BD3, 0xC2A9, 0x6F0F, 0xC2AA, 0x964B, 0xC2AB, 0x82A6, + 0xC2AC, 0x5362, 0xC2AD, 0x9885, 0xC2AE, 0x5E90, 0xC2AF, 0x7089, + 0xC2B0, 0x63B3, 0xC2B1, 0x5364, 0xC2B2, 0x864F, 0xC2B3, 0x9C81, + 0xC2B4, 0x9E93, 0xC2B5, 0x788C, 0xC2B6, 0x9732, 0xC2B7, 0x8DEF, + 0xC2B8, 0x8D42, 0xC2B9, 0x9E7F, 0xC2BA, 0x6F5E, 0xC2BB, 0x7984, + 0xC2BC, 0x5F55, 0xC2BD, 0x9646, 0xC2BE, 0x622E, 0xC2BF, 0x9A74, + 0xC2C0, 0x5415, 0xC2C1, 0x94DD, 0xC2C2, 0x4FA3, 0xC2C3, 0x65C5, + 0xC2C4, 0x5C65, 0xC2C5, 0x5C61, 0xC2C6, 0x7F15, 0xC2C7, 0x8651, + 0xC2C8, 0x6C2F, 0xC2C9, 0x5F8B, 0xC2CA, 0x7387, 0xC2CB, 0x6EE4, + 0xC2CC, 0x7EFF, 0xC2CD, 0x5CE6, 0xC2CE, 0x631B, 0xC2CF, 0x5B6A, + 0xC2D0, 0x6EE6, 0xC2D1, 0x5375, 0xC2D2, 0x4E71, 0xC2D3, 0x63A0, + 0xC2D4, 0x7565, 0xC2D5, 0x62A1, 0xC2D6, 0x8F6E, 0xC2D7, 0x4F26, + 0xC2D8, 0x4ED1, 0xC2D9, 0x6CA6, 0xC2DA, 0x7EB6, 0xC2DB, 0x8BBA, + 0xC2DC, 0x841D, 0xC2DD, 0x87BA, 0xC2DE, 0x7F57, 0xC2DF, 0x903B, + 0xC2E0, 0x9523, 0xC2E1, 0x7BA9, 0xC2E2, 0x9AA1, 0xC2E3, 0x88F8, + 0xC2E4, 0x843D, 0xC2E5, 0x6D1B, 0xC2E6, 0x9A86, 0xC2E7, 0x7EDC, + 0xC2E8, 0x5988, 0xC2E9, 0x9EBB, 0xC2EA, 0x739B, 0xC2EB, 0x7801, + 0xC2EC, 0x8682, 0xC2ED, 0x9A6C, 0xC2EE, 0x9A82, 0xC2EF, 0x561B, + 0xC2F0, 0x5417, 0xC2F1, 0x57CB, 0xC2F2, 0x4E70, 0xC2F3, 0x9EA6, + 0xC2F4, 0x5356, 0xC2F5, 0x8FC8, 0xC2F6, 0x8109, 0xC2F7, 0x7792, + 0xC2F8, 0x9992, 0xC2F9, 0x86EE, 0xC2FA, 0x6EE1, 0xC2FB, 0x8513, + 0xC2FC, 0x66FC, 0xC2FD, 0x6162, 0xC2FE, 0x6F2B, 0xC340, 0x807E, + 0xC341, 0x8081, 0xC342, 0x8082, 0xC343, 0x8085, 0xC344, 0x8088, + 0xC345, 0x808A, 0xC346, 0x808D, 0xC347, 0x808E, 0xC348, 0x808F, + 0xC349, 0x8090, 0xC34A, 0x8091, 0xC34B, 0x8092, 0xC34C, 0x8094, + 0xC34D, 0x8095, 0xC34E, 0x8097, 0xC34F, 0x8099, 0xC350, 0x809E, + 0xC351, 0x80A3, 0xC352, 0x80A6, 0xC353, 0x80A7, 0xC354, 0x80A8, + 0xC355, 0x80AC, 0xC356, 0x80B0, 0xC357, 0x80B3, 0xC358, 0x80B5, + 0xC359, 0x80B6, 0xC35A, 0x80B8, 0xC35B, 0x80B9, 0xC35C, 0x80BB, + 0xC35D, 0x80C5, 0xC35E, 0x80C7, 0xC35F, 0x80C8, 0xC360, 0x80C9, + 0xC361, 0x80CA, 0xC362, 0x80CB, 0xC363, 0x80CF, 0xC364, 0x80D0, + 0xC365, 0x80D1, 0xC366, 0x80D2, 0xC367, 0x80D3, 0xC368, 0x80D4, + 0xC369, 0x80D5, 0xC36A, 0x80D8, 0xC36B, 0x80DF, 0xC36C, 0x80E0, + 0xC36D, 0x80E2, 0xC36E, 0x80E3, 0xC36F, 0x80E6, 0xC370, 0x80EE, + 0xC371, 0x80F5, 0xC372, 0x80F7, 0xC373, 0x80F9, 0xC374, 0x80FB, + 0xC375, 0x80FE, 0xC376, 0x80FF, 0xC377, 0x8100, 0xC378, 0x8101, + 0xC379, 0x8103, 0xC37A, 0x8104, 0xC37B, 0x8105, 0xC37C, 0x8107, + 0xC37D, 0x8108, 0xC37E, 0x810B, 0xC380, 0x810C, 0xC381, 0x8115, + 0xC382, 0x8117, 0xC383, 0x8119, 0xC384, 0x811B, 0xC385, 0x811C, + 0xC386, 0x811D, 0xC387, 0x811F, 0xC388, 0x8120, 0xC389, 0x8121, + 0xC38A, 0x8122, 0xC38B, 0x8123, 0xC38C, 0x8124, 0xC38D, 0x8125, + 0xC38E, 0x8126, 0xC38F, 0x8127, 0xC390, 0x8128, 0xC391, 0x8129, + 0xC392, 0x812A, 0xC393, 0x812B, 0xC394, 0x812D, 0xC395, 0x812E, + 0xC396, 0x8130, 0xC397, 0x8133, 0xC398, 0x8134, 0xC399, 0x8135, + 0xC39A, 0x8137, 0xC39B, 0x8139, 0xC39C, 0x813A, 0xC39D, 0x813B, + 0xC39E, 0x813C, 0xC39F, 0x813D, 0xC3A0, 0x813F, 0xC3A1, 0x8C29, + 0xC3A2, 0x8292, 0xC3A3, 0x832B, 0xC3A4, 0x76F2, 0xC3A5, 0x6C13, + 0xC3A6, 0x5FD9, 0xC3A7, 0x83BD, 0xC3A8, 0x732B, 0xC3A9, 0x8305, + 0xC3AA, 0x951A, 0xC3AB, 0x6BDB, 0xC3AC, 0x77DB, 0xC3AD, 0x94C6, + 0xC3AE, 0x536F, 0xC3AF, 0x8302, 0xC3B0, 0x5192, 0xC3B1, 0x5E3D, + 0xC3B2, 0x8C8C, 0xC3B3, 0x8D38, 0xC3B4, 0x4E48, 0xC3B5, 0x73AB, + 0xC3B6, 0x679A, 0xC3B7, 0x6885, 0xC3B8, 0x9176, 0xC3B9, 0x9709, + 0xC3BA, 0x7164, 0xC3BB, 0x6CA1, 0xC3BC, 0x7709, 0xC3BD, 0x5A92, + 0xC3BE, 0x9541, 0xC3BF, 0x6BCF, 0xC3C0, 0x7F8E, 0xC3C1, 0x6627, + 0xC3C2, 0x5BD0, 0xC3C3, 0x59B9, 0xC3C4, 0x5A9A, 0xC3C5, 0x95E8, + 0xC3C6, 0x95F7, 0xC3C7, 0x4EEC, 0xC3C8, 0x840C, 0xC3C9, 0x8499, + 0xC3CA, 0x6AAC, 0xC3CB, 0x76DF, 0xC3CC, 0x9530, 0xC3CD, 0x731B, + 0xC3CE, 0x68A6, 0xC3CF, 0x5B5F, 0xC3D0, 0x772F, 0xC3D1, 0x919A, + 0xC3D2, 0x9761, 0xC3D3, 0x7CDC, 0xC3D4, 0x8FF7, 0xC3D5, 0x8C1C, + 0xC3D6, 0x5F25, 0xC3D7, 0x7C73, 0xC3D8, 0x79D8, 0xC3D9, 0x89C5, + 0xC3DA, 0x6CCC, 0xC3DB, 0x871C, 0xC3DC, 0x5BC6, 0xC3DD, 0x5E42, + 0xC3DE, 0x68C9, 0xC3DF, 0x7720, 0xC3E0, 0x7EF5, 0xC3E1, 0x5195, + 0xC3E2, 0x514D, 0xC3E3, 0x52C9, 0xC3E4, 0x5A29, 0xC3E5, 0x7F05, + 0xC3E6, 0x9762, 0xC3E7, 0x82D7, 0xC3E8, 0x63CF, 0xC3E9, 0x7784, + 0xC3EA, 0x85D0, 0xC3EB, 0x79D2, 0xC3EC, 0x6E3A, 0xC3ED, 0x5E99, + 0xC3EE, 0x5999, 0xC3EF, 0x8511, 0xC3F0, 0x706D, 0xC3F1, 0x6C11, + 0xC3F2, 0x62BF, 0xC3F3, 0x76BF, 0xC3F4, 0x654F, 0xC3F5, 0x60AF, + 0xC3F6, 0x95FD, 0xC3F7, 0x660E, 0xC3F8, 0x879F, 0xC3F9, 0x9E23, + 0xC3FA, 0x94ED, 0xC3FB, 0x540D, 0xC3FC, 0x547D, 0xC3FD, 0x8C2C, + 0xC3FE, 0x6478, 0xC440, 0x8140, 0xC441, 0x8141, 0xC442, 0x8142, + 0xC443, 0x8143, 0xC444, 0x8144, 0xC445, 0x8145, 0xC446, 0x8147, + 0xC447, 0x8149, 0xC448, 0x814D, 0xC449, 0x814E, 0xC44A, 0x814F, + 0xC44B, 0x8152, 0xC44C, 0x8156, 0xC44D, 0x8157, 0xC44E, 0x8158, + 0xC44F, 0x815B, 0xC450, 0x815C, 0xC451, 0x815D, 0xC452, 0x815E, + 0xC453, 0x815F, 0xC454, 0x8161, 0xC455, 0x8162, 0xC456, 0x8163, + 0xC457, 0x8164, 0xC458, 0x8166, 0xC459, 0x8168, 0xC45A, 0x816A, + 0xC45B, 0x816B, 0xC45C, 0x816C, 0xC45D, 0x816F, 0xC45E, 0x8172, + 0xC45F, 0x8173, 0xC460, 0x8175, 0xC461, 0x8176, 0xC462, 0x8177, + 0xC463, 0x8178, 0xC464, 0x8181, 0xC465, 0x8183, 0xC466, 0x8184, + 0xC467, 0x8185, 0xC468, 0x8186, 0xC469, 0x8187, 0xC46A, 0x8189, + 0xC46B, 0x818B, 0xC46C, 0x818C, 0xC46D, 0x818D, 0xC46E, 0x818E, + 0xC46F, 0x8190, 0xC470, 0x8192, 0xC471, 0x8193, 0xC472, 0x8194, + 0xC473, 0x8195, 0xC474, 0x8196, 0xC475, 0x8197, 0xC476, 0x8199, + 0xC477, 0x819A, 0xC478, 0x819E, 0xC479, 0x819F, 0xC47A, 0x81A0, + 0xC47B, 0x81A1, 0xC47C, 0x81A2, 0xC47D, 0x81A4, 0xC47E, 0x81A5, + 0xC480, 0x81A7, 0xC481, 0x81A9, 0xC482, 0x81AB, 0xC483, 0x81AC, + 0xC484, 0x81AD, 0xC485, 0x81AE, 0xC486, 0x81AF, 0xC487, 0x81B0, + 0xC488, 0x81B1, 0xC489, 0x81B2, 0xC48A, 0x81B4, 0xC48B, 0x81B5, + 0xC48C, 0x81B6, 0xC48D, 0x81B7, 0xC48E, 0x81B8, 0xC48F, 0x81B9, + 0xC490, 0x81BC, 0xC491, 0x81BD, 0xC492, 0x81BE, 0xC493, 0x81BF, + 0xC494, 0x81C4, 0xC495, 0x81C5, 0xC496, 0x81C7, 0xC497, 0x81C8, + 0xC498, 0x81C9, 0xC499, 0x81CB, 0xC49A, 0x81CD, 0xC49B, 0x81CE, + 0xC49C, 0x81CF, 0xC49D, 0x81D0, 0xC49E, 0x81D1, 0xC49F, 0x81D2, + 0xC4A0, 0x81D3, 0xC4A1, 0x6479, 0xC4A2, 0x8611, 0xC4A3, 0x6A21, + 0xC4A4, 0x819C, 0xC4A5, 0x78E8, 0xC4A6, 0x6469, 0xC4A7, 0x9B54, + 0xC4A8, 0x62B9, 0xC4A9, 0x672B, 0xC4AA, 0x83AB, 0xC4AB, 0x58A8, + 0xC4AC, 0x9ED8, 0xC4AD, 0x6CAB, 0xC4AE, 0x6F20, 0xC4AF, 0x5BDE, + 0xC4B0, 0x964C, 0xC4B1, 0x8C0B, 0xC4B2, 0x725F, 0xC4B3, 0x67D0, + 0xC4B4, 0x62C7, 0xC4B5, 0x7261, 0xC4B6, 0x4EA9, 0xC4B7, 0x59C6, + 0xC4B8, 0x6BCD, 0xC4B9, 0x5893, 0xC4BA, 0x66AE, 0xC4BB, 0x5E55, + 0xC4BC, 0x52DF, 0xC4BD, 0x6155, 0xC4BE, 0x6728, 0xC4BF, 0x76EE, + 0xC4C0, 0x7766, 0xC4C1, 0x7267, 0xC4C2, 0x7A46, 0xC4C3, 0x62FF, + 0xC4C4, 0x54EA, 0xC4C5, 0x5450, 0xC4C6, 0x94A0, 0xC4C7, 0x90A3, + 0xC4C8, 0x5A1C, 0xC4C9, 0x7EB3, 0xC4CA, 0x6C16, 0xC4CB, 0x4E43, + 0xC4CC, 0x5976, 0xC4CD, 0x8010, 0xC4CE, 0x5948, 0xC4CF, 0x5357, + 0xC4D0, 0x7537, 0xC4D1, 0x96BE, 0xC4D2, 0x56CA, 0xC4D3, 0x6320, + 0xC4D4, 0x8111, 0xC4D5, 0x607C, 0xC4D6, 0x95F9, 0xC4D7, 0x6DD6, + 0xC4D8, 0x5462, 0xC4D9, 0x9981, 0xC4DA, 0x5185, 0xC4DB, 0x5AE9, + 0xC4DC, 0x80FD, 0xC4DD, 0x59AE, 0xC4DE, 0x9713, 0xC4DF, 0x502A, + 0xC4E0, 0x6CE5, 0xC4E1, 0x5C3C, 0xC4E2, 0x62DF, 0xC4E3, 0x4F60, + 0xC4E4, 0x533F, 0xC4E5, 0x817B, 0xC4E6, 0x9006, 0xC4E7, 0x6EBA, + 0xC4E8, 0x852B, 0xC4E9, 0x62C8, 0xC4EA, 0x5E74, 0xC4EB, 0x78BE, + 0xC4EC, 0x64B5, 0xC4ED, 0x637B, 0xC4EE, 0x5FF5, 0xC4EF, 0x5A18, + 0xC4F0, 0x917F, 0xC4F1, 0x9E1F, 0xC4F2, 0x5C3F, 0xC4F3, 0x634F, + 0xC4F4, 0x8042, 0xC4F5, 0x5B7D, 0xC4F6, 0x556E, 0xC4F7, 0x954A, + 0xC4F8, 0x954D, 0xC4F9, 0x6D85, 0xC4FA, 0x60A8, 0xC4FB, 0x67E0, + 0xC4FC, 0x72DE, 0xC4FD, 0x51DD, 0xC4FE, 0x5B81, 0xC540, 0x81D4, + 0xC541, 0x81D5, 0xC542, 0x81D6, 0xC543, 0x81D7, 0xC544, 0x81D8, + 0xC545, 0x81D9, 0xC546, 0x81DA, 0xC547, 0x81DB, 0xC548, 0x81DC, + 0xC549, 0x81DD, 0xC54A, 0x81DE, 0xC54B, 0x81DF, 0xC54C, 0x81E0, + 0xC54D, 0x81E1, 0xC54E, 0x81E2, 0xC54F, 0x81E4, 0xC550, 0x81E5, + 0xC551, 0x81E6, 0xC552, 0x81E8, 0xC553, 0x81E9, 0xC554, 0x81EB, + 0xC555, 0x81EE, 0xC556, 0x81EF, 0xC557, 0x81F0, 0xC558, 0x81F1, + 0xC559, 0x81F2, 0xC55A, 0x81F5, 0xC55B, 0x81F6, 0xC55C, 0x81F7, + 0xC55D, 0x81F8, 0xC55E, 0x81F9, 0xC55F, 0x81FA, 0xC560, 0x81FD, + 0xC561, 0x81FF, 0xC562, 0x8203, 0xC563, 0x8207, 0xC564, 0x8208, + 0xC565, 0x8209, 0xC566, 0x820A, 0xC567, 0x820B, 0xC568, 0x820E, + 0xC569, 0x820F, 0xC56A, 0x8211, 0xC56B, 0x8213, 0xC56C, 0x8215, + 0xC56D, 0x8216, 0xC56E, 0x8217, 0xC56F, 0x8218, 0xC570, 0x8219, + 0xC571, 0x821A, 0xC572, 0x821D, 0xC573, 0x8220, 0xC574, 0x8224, + 0xC575, 0x8225, 0xC576, 0x8226, 0xC577, 0x8227, 0xC578, 0x8229, + 0xC579, 0x822E, 0xC57A, 0x8232, 0xC57B, 0x823A, 0xC57C, 0x823C, + 0xC57D, 0x823D, 0xC57E, 0x823F, 0xC580, 0x8240, 0xC581, 0x8241, + 0xC582, 0x8242, 0xC583, 0x8243, 0xC584, 0x8245, 0xC585, 0x8246, + 0xC586, 0x8248, 0xC587, 0x824A, 0xC588, 0x824C, 0xC589, 0x824D, + 0xC58A, 0x824E, 0xC58B, 0x8250, 0xC58C, 0x8251, 0xC58D, 0x8252, + 0xC58E, 0x8253, 0xC58F, 0x8254, 0xC590, 0x8255, 0xC591, 0x8256, + 0xC592, 0x8257, 0xC593, 0x8259, 0xC594, 0x825B, 0xC595, 0x825C, + 0xC596, 0x825D, 0xC597, 0x825E, 0xC598, 0x8260, 0xC599, 0x8261, + 0xC59A, 0x8262, 0xC59B, 0x8263, 0xC59C, 0x8264, 0xC59D, 0x8265, + 0xC59E, 0x8266, 0xC59F, 0x8267, 0xC5A0, 0x8269, 0xC5A1, 0x62E7, + 0xC5A2, 0x6CDE, 0xC5A3, 0x725B, 0xC5A4, 0x626D, 0xC5A5, 0x94AE, + 0xC5A6, 0x7EBD, 0xC5A7, 0x8113, 0xC5A8, 0x6D53, 0xC5A9, 0x519C, + 0xC5AA, 0x5F04, 0xC5AB, 0x5974, 0xC5AC, 0x52AA, 0xC5AD, 0x6012, + 0xC5AE, 0x5973, 0xC5AF, 0x6696, 0xC5B0, 0x8650, 0xC5B1, 0x759F, + 0xC5B2, 0x632A, 0xC5B3, 0x61E6, 0xC5B4, 0x7CEF, 0xC5B5, 0x8BFA, + 0xC5B6, 0x54E6, 0xC5B7, 0x6B27, 0xC5B8, 0x9E25, 0xC5B9, 0x6BB4, + 0xC5BA, 0x85D5, 0xC5BB, 0x5455, 0xC5BC, 0x5076, 0xC5BD, 0x6CA4, + 0xC5BE, 0x556A, 0xC5BF, 0x8DB4, 0xC5C0, 0x722C, 0xC5C1, 0x5E15, + 0xC5C2, 0x6015, 0xC5C3, 0x7436, 0xC5C4, 0x62CD, 0xC5C5, 0x6392, + 0xC5C6, 0x724C, 0xC5C7, 0x5F98, 0xC5C8, 0x6E43, 0xC5C9, 0x6D3E, + 0xC5CA, 0x6500, 0xC5CB, 0x6F58, 0xC5CC, 0x76D8, 0xC5CD, 0x78D0, + 0xC5CE, 0x76FC, 0xC5CF, 0x7554, 0xC5D0, 0x5224, 0xC5D1, 0x53DB, + 0xC5D2, 0x4E53, 0xC5D3, 0x5E9E, 0xC5D4, 0x65C1, 0xC5D5, 0x802A, + 0xC5D6, 0x80D6, 0xC5D7, 0x629B, 0xC5D8, 0x5486, 0xC5D9, 0x5228, + 0xC5DA, 0x70AE, 0xC5DB, 0x888D, 0xC5DC, 0x8DD1, 0xC5DD, 0x6CE1, + 0xC5DE, 0x5478, 0xC5DF, 0x80DA, 0xC5E0, 0x57F9, 0xC5E1, 0x88F4, + 0xC5E2, 0x8D54, 0xC5E3, 0x966A, 0xC5E4, 0x914D, 0xC5E5, 0x4F69, + 0xC5E6, 0x6C9B, 0xC5E7, 0x55B7, 0xC5E8, 0x76C6, 0xC5E9, 0x7830, + 0xC5EA, 0x62A8, 0xC5EB, 0x70F9, 0xC5EC, 0x6F8E, 0xC5ED, 0x5F6D, + 0xC5EE, 0x84EC, 0xC5EF, 0x68DA, 0xC5F0, 0x787C, 0xC5F1, 0x7BF7, + 0xC5F2, 0x81A8, 0xC5F3, 0x670B, 0xC5F4, 0x9E4F, 0xC5F5, 0x6367, + 0xC5F6, 0x78B0, 0xC5F7, 0x576F, 0xC5F8, 0x7812, 0xC5F9, 0x9739, + 0xC5FA, 0x6279, 0xC5FB, 0x62AB, 0xC5FC, 0x5288, 0xC5FD, 0x7435, + 0xC5FE, 0x6BD7, 0xC640, 0x826A, 0xC641, 0x826B, 0xC642, 0x826C, + 0xC643, 0x826D, 0xC644, 0x8271, 0xC645, 0x8275, 0xC646, 0x8276, + 0xC647, 0x8277, 0xC648, 0x8278, 0xC649, 0x827B, 0xC64A, 0x827C, + 0xC64B, 0x8280, 0xC64C, 0x8281, 0xC64D, 0x8283, 0xC64E, 0x8285, + 0xC64F, 0x8286, 0xC650, 0x8287, 0xC651, 0x8289, 0xC652, 0x828C, + 0xC653, 0x8290, 0xC654, 0x8293, 0xC655, 0x8294, 0xC656, 0x8295, + 0xC657, 0x8296, 0xC658, 0x829A, 0xC659, 0x829B, 0xC65A, 0x829E, + 0xC65B, 0x82A0, 0xC65C, 0x82A2, 0xC65D, 0x82A3, 0xC65E, 0x82A7, + 0xC65F, 0x82B2, 0xC660, 0x82B5, 0xC661, 0x82B6, 0xC662, 0x82BA, + 0xC663, 0x82BB, 0xC664, 0x82BC, 0xC665, 0x82BF, 0xC666, 0x82C0, + 0xC667, 0x82C2, 0xC668, 0x82C3, 0xC669, 0x82C5, 0xC66A, 0x82C6, + 0xC66B, 0x82C9, 0xC66C, 0x82D0, 0xC66D, 0x82D6, 0xC66E, 0x82D9, + 0xC66F, 0x82DA, 0xC670, 0x82DD, 0xC671, 0x82E2, 0xC672, 0x82E7, + 0xC673, 0x82E8, 0xC674, 0x82E9, 0xC675, 0x82EA, 0xC676, 0x82EC, + 0xC677, 0x82ED, 0xC678, 0x82EE, 0xC679, 0x82F0, 0xC67A, 0x82F2, + 0xC67B, 0x82F3, 0xC67C, 0x82F5, 0xC67D, 0x82F6, 0xC67E, 0x82F8, + 0xC680, 0x82FA, 0xC681, 0x82FC, 0xC682, 0x82FD, 0xC683, 0x82FE, + 0xC684, 0x82FF, 0xC685, 0x8300, 0xC686, 0x830A, 0xC687, 0x830B, + 0xC688, 0x830D, 0xC689, 0x8310, 0xC68A, 0x8312, 0xC68B, 0x8313, + 0xC68C, 0x8316, 0xC68D, 0x8318, 0xC68E, 0x8319, 0xC68F, 0x831D, + 0xC690, 0x831E, 0xC691, 0x831F, 0xC692, 0x8320, 0xC693, 0x8321, + 0xC694, 0x8322, 0xC695, 0x8323, 0xC696, 0x8324, 0xC697, 0x8325, + 0xC698, 0x8326, 0xC699, 0x8329, 0xC69A, 0x832A, 0xC69B, 0x832E, + 0xC69C, 0x8330, 0xC69D, 0x8332, 0xC69E, 0x8337, 0xC69F, 0x833B, + 0xC6A0, 0x833D, 0xC6A1, 0x5564, 0xC6A2, 0x813E, 0xC6A3, 0x75B2, + 0xC6A4, 0x76AE, 0xC6A5, 0x5339, 0xC6A6, 0x75DE, 0xC6A7, 0x50FB, + 0xC6A8, 0x5C41, 0xC6A9, 0x8B6C, 0xC6AA, 0x7BC7, 0xC6AB, 0x504F, + 0xC6AC, 0x7247, 0xC6AD, 0x9A97, 0xC6AE, 0x98D8, 0xC6AF, 0x6F02, + 0xC6B0, 0x74E2, 0xC6B1, 0x7968, 0xC6B2, 0x6487, 0xC6B3, 0x77A5, + 0xC6B4, 0x62FC, 0xC6B5, 0x9891, 0xC6B6, 0x8D2B, 0xC6B7, 0x54C1, + 0xC6B8, 0x8058, 0xC6B9, 0x4E52, 0xC6BA, 0x576A, 0xC6BB, 0x82F9, + 0xC6BC, 0x840D, 0xC6BD, 0x5E73, 0xC6BE, 0x51ED, 0xC6BF, 0x74F6, + 0xC6C0, 0x8BC4, 0xC6C1, 0x5C4F, 0xC6C2, 0x5761, 0xC6C3, 0x6CFC, + 0xC6C4, 0x9887, 0xC6C5, 0x5A46, 0xC6C6, 0x7834, 0xC6C7, 0x9B44, + 0xC6C8, 0x8FEB, 0xC6C9, 0x7C95, 0xC6CA, 0x5256, 0xC6CB, 0x6251, + 0xC6CC, 0x94FA, 0xC6CD, 0x4EC6, 0xC6CE, 0x8386, 0xC6CF, 0x8461, + 0xC6D0, 0x83E9, 0xC6D1, 0x84B2, 0xC6D2, 0x57D4, 0xC6D3, 0x6734, + 0xC6D4, 0x5703, 0xC6D5, 0x666E, 0xC6D6, 0x6D66, 0xC6D7, 0x8C31, + 0xC6D8, 0x66DD, 0xC6D9, 0x7011, 0xC6DA, 0x671F, 0xC6DB, 0x6B3A, + 0xC6DC, 0x6816, 0xC6DD, 0x621A, 0xC6DE, 0x59BB, 0xC6DF, 0x4E03, + 0xC6E0, 0x51C4, 0xC6E1, 0x6F06, 0xC6E2, 0x67D2, 0xC6E3, 0x6C8F, + 0xC6E4, 0x5176, 0xC6E5, 0x68CB, 0xC6E6, 0x5947, 0xC6E7, 0x6B67, + 0xC6E8, 0x7566, 0xC6E9, 0x5D0E, 0xC6EA, 0x8110, 0xC6EB, 0x9F50, + 0xC6EC, 0x65D7, 0xC6ED, 0x7948, 0xC6EE, 0x7941, 0xC6EF, 0x9A91, + 0xC6F0, 0x8D77, 0xC6F1, 0x5C82, 0xC6F2, 0x4E5E, 0xC6F3, 0x4F01, + 0xC6F4, 0x542F, 0xC6F5, 0x5951, 0xC6F6, 0x780C, 0xC6F7, 0x5668, + 0xC6F8, 0x6C14, 0xC6F9, 0x8FC4, 0xC6FA, 0x5F03, 0xC6FB, 0x6C7D, + 0xC6FC, 0x6CE3, 0xC6FD, 0x8BAB, 0xC6FE, 0x6390, 0xC740, 0x833E, + 0xC741, 0x833F, 0xC742, 0x8341, 0xC743, 0x8342, 0xC744, 0x8344, + 0xC745, 0x8345, 0xC746, 0x8348, 0xC747, 0x834A, 0xC748, 0x834B, + 0xC749, 0x834C, 0xC74A, 0x834D, 0xC74B, 0x834E, 0xC74C, 0x8353, + 0xC74D, 0x8355, 0xC74E, 0x8356, 0xC74F, 0x8357, 0xC750, 0x8358, + 0xC751, 0x8359, 0xC752, 0x835D, 0xC753, 0x8362, 0xC754, 0x8370, + 0xC755, 0x8371, 0xC756, 0x8372, 0xC757, 0x8373, 0xC758, 0x8374, + 0xC759, 0x8375, 0xC75A, 0x8376, 0xC75B, 0x8379, 0xC75C, 0x837A, + 0xC75D, 0x837E, 0xC75E, 0x837F, 0xC75F, 0x8380, 0xC760, 0x8381, + 0xC761, 0x8382, 0xC762, 0x8383, 0xC763, 0x8384, 0xC764, 0x8387, + 0xC765, 0x8388, 0xC766, 0x838A, 0xC767, 0x838B, 0xC768, 0x838C, + 0xC769, 0x838D, 0xC76A, 0x838F, 0xC76B, 0x8390, 0xC76C, 0x8391, + 0xC76D, 0x8394, 0xC76E, 0x8395, 0xC76F, 0x8396, 0xC770, 0x8397, + 0xC771, 0x8399, 0xC772, 0x839A, 0xC773, 0x839D, 0xC774, 0x839F, + 0xC775, 0x83A1, 0xC776, 0x83A2, 0xC777, 0x83A3, 0xC778, 0x83A4, + 0xC779, 0x83A5, 0xC77A, 0x83A6, 0xC77B, 0x83A7, 0xC77C, 0x83AC, + 0xC77D, 0x83AD, 0xC77E, 0x83AE, 0xC780, 0x83AF, 0xC781, 0x83B5, + 0xC782, 0x83BB, 0xC783, 0x83BE, 0xC784, 0x83BF, 0xC785, 0x83C2, + 0xC786, 0x83C3, 0xC787, 0x83C4, 0xC788, 0x83C6, 0xC789, 0x83C8, + 0xC78A, 0x83C9, 0xC78B, 0x83CB, 0xC78C, 0x83CD, 0xC78D, 0x83CE, + 0xC78E, 0x83D0, 0xC78F, 0x83D1, 0xC790, 0x83D2, 0xC791, 0x83D3, + 0xC792, 0x83D5, 0xC793, 0x83D7, 0xC794, 0x83D9, 0xC795, 0x83DA, + 0xC796, 0x83DB, 0xC797, 0x83DE, 0xC798, 0x83E2, 0xC799, 0x83E3, + 0xC79A, 0x83E4, 0xC79B, 0x83E6, 0xC79C, 0x83E7, 0xC79D, 0x83E8, + 0xC79E, 0x83EB, 0xC79F, 0x83EC, 0xC7A0, 0x83ED, 0xC7A1, 0x6070, + 0xC7A2, 0x6D3D, 0xC7A3, 0x7275, 0xC7A4, 0x6266, 0xC7A5, 0x948E, + 0xC7A6, 0x94C5, 0xC7A7, 0x5343, 0xC7A8, 0x8FC1, 0xC7A9, 0x7B7E, + 0xC7AA, 0x4EDF, 0xC7AB, 0x8C26, 0xC7AC, 0x4E7E, 0xC7AD, 0x9ED4, + 0xC7AE, 0x94B1, 0xC7AF, 0x94B3, 0xC7B0, 0x524D, 0xC7B1, 0x6F5C, + 0xC7B2, 0x9063, 0xC7B3, 0x6D45, 0xC7B4, 0x8C34, 0xC7B5, 0x5811, + 0xC7B6, 0x5D4C, 0xC7B7, 0x6B20, 0xC7B8, 0x6B49, 0xC7B9, 0x67AA, + 0xC7BA, 0x545B, 0xC7BB, 0x8154, 0xC7BC, 0x7F8C, 0xC7BD, 0x5899, + 0xC7BE, 0x8537, 0xC7BF, 0x5F3A, 0xC7C0, 0x62A2, 0xC7C1, 0x6A47, + 0xC7C2, 0x9539, 0xC7C3, 0x6572, 0xC7C4, 0x6084, 0xC7C5, 0x6865, + 0xC7C6, 0x77A7, 0xC7C7, 0x4E54, 0xC7C8, 0x4FA8, 0xC7C9, 0x5DE7, + 0xC7CA, 0x9798, 0xC7CB, 0x64AC, 0xC7CC, 0x7FD8, 0xC7CD, 0x5CED, + 0xC7CE, 0x4FCF, 0xC7CF, 0x7A8D, 0xC7D0, 0x5207, 0xC7D1, 0x8304, + 0xC7D2, 0x4E14, 0xC7D3, 0x602F, 0xC7D4, 0x7A83, 0xC7D5, 0x94A6, + 0xC7D6, 0x4FB5, 0xC7D7, 0x4EB2, 0xC7D8, 0x79E6, 0xC7D9, 0x7434, + 0xC7DA, 0x52E4, 0xC7DB, 0x82B9, 0xC7DC, 0x64D2, 0xC7DD, 0x79BD, + 0xC7DE, 0x5BDD, 0xC7DF, 0x6C81, 0xC7E0, 0x9752, 0xC7E1, 0x8F7B, + 0xC7E2, 0x6C22, 0xC7E3, 0x503E, 0xC7E4, 0x537F, 0xC7E5, 0x6E05, + 0xC7E6, 0x64CE, 0xC7E7, 0x6674, 0xC7E8, 0x6C30, 0xC7E9, 0x60C5, + 0xC7EA, 0x9877, 0xC7EB, 0x8BF7, 0xC7EC, 0x5E86, 0xC7ED, 0x743C, + 0xC7EE, 0x7A77, 0xC7EF, 0x79CB, 0xC7F0, 0x4E18, 0xC7F1, 0x90B1, + 0xC7F2, 0x7403, 0xC7F3, 0x6C42, 0xC7F4, 0x56DA, 0xC7F5, 0x914B, + 0xC7F6, 0x6CC5, 0xC7F7, 0x8D8B, 0xC7F8, 0x533A, 0xC7F9, 0x86C6, + 0xC7FA, 0x66F2, 0xC7FB, 0x8EAF, 0xC7FC, 0x5C48, 0xC7FD, 0x9A71, + 0xC7FE, 0x6E20, 0xC840, 0x83EE, 0xC841, 0x83EF, 0xC842, 0x83F3, + 0xC843, 0x83F4, 0xC844, 0x83F5, 0xC845, 0x83F6, 0xC846, 0x83F7, + 0xC847, 0x83FA, 0xC848, 0x83FB, 0xC849, 0x83FC, 0xC84A, 0x83FE, + 0xC84B, 0x83FF, 0xC84C, 0x8400, 0xC84D, 0x8402, 0xC84E, 0x8405, + 0xC84F, 0x8407, 0xC850, 0x8408, 0xC851, 0x8409, 0xC852, 0x840A, + 0xC853, 0x8410, 0xC854, 0x8412, 0xC855, 0x8413, 0xC856, 0x8414, + 0xC857, 0x8415, 0xC858, 0x8416, 0xC859, 0x8417, 0xC85A, 0x8419, + 0xC85B, 0x841A, 0xC85C, 0x841B, 0xC85D, 0x841E, 0xC85E, 0x841F, + 0xC85F, 0x8420, 0xC860, 0x8421, 0xC861, 0x8422, 0xC862, 0x8423, + 0xC863, 0x8429, 0xC864, 0x842A, 0xC865, 0x842B, 0xC866, 0x842C, + 0xC867, 0x842D, 0xC868, 0x842E, 0xC869, 0x842F, 0xC86A, 0x8430, + 0xC86B, 0x8432, 0xC86C, 0x8433, 0xC86D, 0x8434, 0xC86E, 0x8435, + 0xC86F, 0x8436, 0xC870, 0x8437, 0xC871, 0x8439, 0xC872, 0x843A, + 0xC873, 0x843B, 0xC874, 0x843E, 0xC875, 0x843F, 0xC876, 0x8440, + 0xC877, 0x8441, 0xC878, 0x8442, 0xC879, 0x8443, 0xC87A, 0x8444, + 0xC87B, 0x8445, 0xC87C, 0x8447, 0xC87D, 0x8448, 0xC87E, 0x8449, + 0xC880, 0x844A, 0xC881, 0x844B, 0xC882, 0x844C, 0xC883, 0x844D, + 0xC884, 0x844E, 0xC885, 0x844F, 0xC886, 0x8450, 0xC887, 0x8452, + 0xC888, 0x8453, 0xC889, 0x8454, 0xC88A, 0x8455, 0xC88B, 0x8456, + 0xC88C, 0x8458, 0xC88D, 0x845D, 0xC88E, 0x845E, 0xC88F, 0x845F, + 0xC890, 0x8460, 0xC891, 0x8462, 0xC892, 0x8464, 0xC893, 0x8465, + 0xC894, 0x8466, 0xC895, 0x8467, 0xC896, 0x8468, 0xC897, 0x846A, + 0xC898, 0x846E, 0xC899, 0x846F, 0xC89A, 0x8470, 0xC89B, 0x8472, + 0xC89C, 0x8474, 0xC89D, 0x8477, 0xC89E, 0x8479, 0xC89F, 0x847B, + 0xC8A0, 0x847C, 0xC8A1, 0x53D6, 0xC8A2, 0x5A36, 0xC8A3, 0x9F8B, + 0xC8A4, 0x8DA3, 0xC8A5, 0x53BB, 0xC8A6, 0x5708, 0xC8A7, 0x98A7, + 0xC8A8, 0x6743, 0xC8A9, 0x919B, 0xC8AA, 0x6CC9, 0xC8AB, 0x5168, + 0xC8AC, 0x75CA, 0xC8AD, 0x62F3, 0xC8AE, 0x72AC, 0xC8AF, 0x5238, + 0xC8B0, 0x529D, 0xC8B1, 0x7F3A, 0xC8B2, 0x7094, 0xC8B3, 0x7638, + 0xC8B4, 0x5374, 0xC8B5, 0x9E4A, 0xC8B6, 0x69B7, 0xC8B7, 0x786E, + 0xC8B8, 0x96C0, 0xC8B9, 0x88D9, 0xC8BA, 0x7FA4, 0xC8BB, 0x7136, + 0xC8BC, 0x71C3, 0xC8BD, 0x5189, 0xC8BE, 0x67D3, 0xC8BF, 0x74E4, + 0xC8C0, 0x58E4, 0xC8C1, 0x6518, 0xC8C2, 0x56B7, 0xC8C3, 0x8BA9, + 0xC8C4, 0x9976, 0xC8C5, 0x6270, 0xC8C6, 0x7ED5, 0xC8C7, 0x60F9, + 0xC8C8, 0x70ED, 0xC8C9, 0x58EC, 0xC8CA, 0x4EC1, 0xC8CB, 0x4EBA, + 0xC8CC, 0x5FCD, 0xC8CD, 0x97E7, 0xC8CE, 0x4EFB, 0xC8CF, 0x8BA4, + 0xC8D0, 0x5203, 0xC8D1, 0x598A, 0xC8D2, 0x7EAB, 0xC8D3, 0x6254, + 0xC8D4, 0x4ECD, 0xC8D5, 0x65E5, 0xC8D6, 0x620E, 0xC8D7, 0x8338, + 0xC8D8, 0x84C9, 0xC8D9, 0x8363, 0xC8DA, 0x878D, 0xC8DB, 0x7194, + 0xC8DC, 0x6EB6, 0xC8DD, 0x5BB9, 0xC8DE, 0x7ED2, 0xC8DF, 0x5197, + 0xC8E0, 0x63C9, 0xC8E1, 0x67D4, 0xC8E2, 0x8089, 0xC8E3, 0x8339, + 0xC8E4, 0x8815, 0xC8E5, 0x5112, 0xC8E6, 0x5B7A, 0xC8E7, 0x5982, + 0xC8E8, 0x8FB1, 0xC8E9, 0x4E73, 0xC8EA, 0x6C5D, 0xC8EB, 0x5165, + 0xC8EC, 0x8925, 0xC8ED, 0x8F6F, 0xC8EE, 0x962E, 0xC8EF, 0x854A, + 0xC8F0, 0x745E, 0xC8F1, 0x9510, 0xC8F2, 0x95F0, 0xC8F3, 0x6DA6, + 0xC8F4, 0x82E5, 0xC8F5, 0x5F31, 0xC8F6, 0x6492, 0xC8F7, 0x6D12, + 0xC8F8, 0x8428, 0xC8F9, 0x816E, 0xC8FA, 0x9CC3, 0xC8FB, 0x585E, + 0xC8FC, 0x8D5B, 0xC8FD, 0x4E09, 0xC8FE, 0x53C1, 0xC940, 0x847D, + 0xC941, 0x847E, 0xC942, 0x847F, 0xC943, 0x8480, 0xC944, 0x8481, + 0xC945, 0x8483, 0xC946, 0x8484, 0xC947, 0x8485, 0xC948, 0x8486, + 0xC949, 0x848A, 0xC94A, 0x848D, 0xC94B, 0x848F, 0xC94C, 0x8490, + 0xC94D, 0x8491, 0xC94E, 0x8492, 0xC94F, 0x8493, 0xC950, 0x8494, + 0xC951, 0x8495, 0xC952, 0x8496, 0xC953, 0x8498, 0xC954, 0x849A, + 0xC955, 0x849B, 0xC956, 0x849D, 0xC957, 0x849E, 0xC958, 0x849F, + 0xC959, 0x84A0, 0xC95A, 0x84A2, 0xC95B, 0x84A3, 0xC95C, 0x84A4, + 0xC95D, 0x84A5, 0xC95E, 0x84A6, 0xC95F, 0x84A7, 0xC960, 0x84A8, + 0xC961, 0x84A9, 0xC962, 0x84AA, 0xC963, 0x84AB, 0xC964, 0x84AC, + 0xC965, 0x84AD, 0xC966, 0x84AE, 0xC967, 0x84B0, 0xC968, 0x84B1, + 0xC969, 0x84B3, 0xC96A, 0x84B5, 0xC96B, 0x84B6, 0xC96C, 0x84B7, + 0xC96D, 0x84BB, 0xC96E, 0x84BC, 0xC96F, 0x84BE, 0xC970, 0x84C0, + 0xC971, 0x84C2, 0xC972, 0x84C3, 0xC973, 0x84C5, 0xC974, 0x84C6, + 0xC975, 0x84C7, 0xC976, 0x84C8, 0xC977, 0x84CB, 0xC978, 0x84CC, + 0xC979, 0x84CE, 0xC97A, 0x84CF, 0xC97B, 0x84D2, 0xC97C, 0x84D4, + 0xC97D, 0x84D5, 0xC97E, 0x84D7, 0xC980, 0x84D8, 0xC981, 0x84D9, + 0xC982, 0x84DA, 0xC983, 0x84DB, 0xC984, 0x84DC, 0xC985, 0x84DE, + 0xC986, 0x84E1, 0xC987, 0x84E2, 0xC988, 0x84E4, 0xC989, 0x84E7, + 0xC98A, 0x84E8, 0xC98B, 0x84E9, 0xC98C, 0x84EA, 0xC98D, 0x84EB, + 0xC98E, 0x84ED, 0xC98F, 0x84EE, 0xC990, 0x84EF, 0xC991, 0x84F1, + 0xC992, 0x84F2, 0xC993, 0x84F3, 0xC994, 0x84F4, 0xC995, 0x84F5, + 0xC996, 0x84F6, 0xC997, 0x84F7, 0xC998, 0x84F8, 0xC999, 0x84F9, + 0xC99A, 0x84FA, 0xC99B, 0x84FB, 0xC99C, 0x84FD, 0xC99D, 0x84FE, + 0xC99E, 0x8500, 0xC99F, 0x8501, 0xC9A0, 0x8502, 0xC9A1, 0x4F1E, + 0xC9A2, 0x6563, 0xC9A3, 0x6851, 0xC9A4, 0x55D3, 0xC9A5, 0x4E27, + 0xC9A6, 0x6414, 0xC9A7, 0x9A9A, 0xC9A8, 0x626B, 0xC9A9, 0x5AC2, + 0xC9AA, 0x745F, 0xC9AB, 0x8272, 0xC9AC, 0x6DA9, 0xC9AD, 0x68EE, + 0xC9AE, 0x50E7, 0xC9AF, 0x838E, 0xC9B0, 0x7802, 0xC9B1, 0x6740, + 0xC9B2, 0x5239, 0xC9B3, 0x6C99, 0xC9B4, 0x7EB1, 0xC9B5, 0x50BB, + 0xC9B6, 0x5565, 0xC9B7, 0x715E, 0xC9B8, 0x7B5B, 0xC9B9, 0x6652, + 0xC9BA, 0x73CA, 0xC9BB, 0x82EB, 0xC9BC, 0x6749, 0xC9BD, 0x5C71, + 0xC9BE, 0x5220, 0xC9BF, 0x717D, 0xC9C0, 0x886B, 0xC9C1, 0x95EA, + 0xC9C2, 0x9655, 0xC9C3, 0x64C5, 0xC9C4, 0x8D61, 0xC9C5, 0x81B3, + 0xC9C6, 0x5584, 0xC9C7, 0x6C55, 0xC9C8, 0x6247, 0xC9C9, 0x7F2E, + 0xC9CA, 0x5892, 0xC9CB, 0x4F24, 0xC9CC, 0x5546, 0xC9CD, 0x8D4F, + 0xC9CE, 0x664C, 0xC9CF, 0x4E0A, 0xC9D0, 0x5C1A, 0xC9D1, 0x88F3, + 0xC9D2, 0x68A2, 0xC9D3, 0x634E, 0xC9D4, 0x7A0D, 0xC9D5, 0x70E7, + 0xC9D6, 0x828D, 0xC9D7, 0x52FA, 0xC9D8, 0x97F6, 0xC9D9, 0x5C11, + 0xC9DA, 0x54E8, 0xC9DB, 0x90B5, 0xC9DC, 0x7ECD, 0xC9DD, 0x5962, + 0xC9DE, 0x8D4A, 0xC9DF, 0x86C7, 0xC9E0, 0x820C, 0xC9E1, 0x820D, + 0xC9E2, 0x8D66, 0xC9E3, 0x6444, 0xC9E4, 0x5C04, 0xC9E5, 0x6151, + 0xC9E6, 0x6D89, 0xC9E7, 0x793E, 0xC9E8, 0x8BBE, 0xC9E9, 0x7837, + 0xC9EA, 0x7533, 0xC9EB, 0x547B, 0xC9EC, 0x4F38, 0xC9ED, 0x8EAB, + 0xC9EE, 0x6DF1, 0xC9EF, 0x5A20, 0xC9F0, 0x7EC5, 0xC9F1, 0x795E, + 0xC9F2, 0x6C88, 0xC9F3, 0x5BA1, 0xC9F4, 0x5A76, 0xC9F5, 0x751A, + 0xC9F6, 0x80BE, 0xC9F7, 0x614E, 0xC9F8, 0x6E17, 0xC9F9, 0x58F0, + 0xC9FA, 0x751F, 0xC9FB, 0x7525, 0xC9FC, 0x7272, 0xC9FD, 0x5347, + 0xC9FE, 0x7EF3, 0xCA40, 0x8503, 0xCA41, 0x8504, 0xCA42, 0x8505, + 0xCA43, 0x8506, 0xCA44, 0x8507, 0xCA45, 0x8508, 0xCA46, 0x8509, + 0xCA47, 0x850A, 0xCA48, 0x850B, 0xCA49, 0x850D, 0xCA4A, 0x850E, + 0xCA4B, 0x850F, 0xCA4C, 0x8510, 0xCA4D, 0x8512, 0xCA4E, 0x8514, + 0xCA4F, 0x8515, 0xCA50, 0x8516, 0xCA51, 0x8518, 0xCA52, 0x8519, + 0xCA53, 0x851B, 0xCA54, 0x851C, 0xCA55, 0x851D, 0xCA56, 0x851E, + 0xCA57, 0x8520, 0xCA58, 0x8522, 0xCA59, 0x8523, 0xCA5A, 0x8524, + 0xCA5B, 0x8525, 0xCA5C, 0x8526, 0xCA5D, 0x8527, 0xCA5E, 0x8528, + 0xCA5F, 0x8529, 0xCA60, 0x852A, 0xCA61, 0x852D, 0xCA62, 0x852E, + 0xCA63, 0x852F, 0xCA64, 0x8530, 0xCA65, 0x8531, 0xCA66, 0x8532, + 0xCA67, 0x8533, 0xCA68, 0x8534, 0xCA69, 0x8535, 0xCA6A, 0x8536, + 0xCA6B, 0x853E, 0xCA6C, 0x853F, 0xCA6D, 0x8540, 0xCA6E, 0x8541, + 0xCA6F, 0x8542, 0xCA70, 0x8544, 0xCA71, 0x8545, 0xCA72, 0x8546, + 0xCA73, 0x8547, 0xCA74, 0x854B, 0xCA75, 0x854C, 0xCA76, 0x854D, + 0xCA77, 0x854E, 0xCA78, 0x854F, 0xCA79, 0x8550, 0xCA7A, 0x8551, + 0xCA7B, 0x8552, 0xCA7C, 0x8553, 0xCA7D, 0x8554, 0xCA7E, 0x8555, + 0xCA80, 0x8557, 0xCA81, 0x8558, 0xCA82, 0x855A, 0xCA83, 0x855B, + 0xCA84, 0x855C, 0xCA85, 0x855D, 0xCA86, 0x855F, 0xCA87, 0x8560, + 0xCA88, 0x8561, 0xCA89, 0x8562, 0xCA8A, 0x8563, 0xCA8B, 0x8565, + 0xCA8C, 0x8566, 0xCA8D, 0x8567, 0xCA8E, 0x8569, 0xCA8F, 0x856A, + 0xCA90, 0x856B, 0xCA91, 0x856C, 0xCA92, 0x856D, 0xCA93, 0x856E, + 0xCA94, 0x856F, 0xCA95, 0x8570, 0xCA96, 0x8571, 0xCA97, 0x8573, + 0xCA98, 0x8575, 0xCA99, 0x8576, 0xCA9A, 0x8577, 0xCA9B, 0x8578, + 0xCA9C, 0x857C, 0xCA9D, 0x857D, 0xCA9E, 0x857F, 0xCA9F, 0x8580, + 0xCAA0, 0x8581, 0xCAA1, 0x7701, 0xCAA2, 0x76DB, 0xCAA3, 0x5269, + 0xCAA4, 0x80DC, 0xCAA5, 0x5723, 0xCAA6, 0x5E08, 0xCAA7, 0x5931, + 0xCAA8, 0x72EE, 0xCAA9, 0x65BD, 0xCAAA, 0x6E7F, 0xCAAB, 0x8BD7, + 0xCAAC, 0x5C38, 0xCAAD, 0x8671, 0xCAAE, 0x5341, 0xCAAF, 0x77F3, + 0xCAB0, 0x62FE, 0xCAB1, 0x65F6, 0xCAB2, 0x4EC0, 0xCAB3, 0x98DF, + 0xCAB4, 0x8680, 0xCAB5, 0x5B9E, 0xCAB6, 0x8BC6, 0xCAB7, 0x53F2, + 0xCAB8, 0x77E2, 0xCAB9, 0x4F7F, 0xCABA, 0x5C4E, 0xCABB, 0x9A76, + 0xCABC, 0x59CB, 0xCABD, 0x5F0F, 0xCABE, 0x793A, 0xCABF, 0x58EB, + 0xCAC0, 0x4E16, 0xCAC1, 0x67FF, 0xCAC2, 0x4E8B, 0xCAC3, 0x62ED, + 0xCAC4, 0x8A93, 0xCAC5, 0x901D, 0xCAC6, 0x52BF, 0xCAC7, 0x662F, + 0xCAC8, 0x55DC, 0xCAC9, 0x566C, 0xCACA, 0x9002, 0xCACB, 0x4ED5, + 0xCACC, 0x4F8D, 0xCACD, 0x91CA, 0xCACE, 0x9970, 0xCACF, 0x6C0F, + 0xCAD0, 0x5E02, 0xCAD1, 0x6043, 0xCAD2, 0x5BA4, 0xCAD3, 0x89C6, + 0xCAD4, 0x8BD5, 0xCAD5, 0x6536, 0xCAD6, 0x624B, 0xCAD7, 0x9996, + 0xCAD8, 0x5B88, 0xCAD9, 0x5BFF, 0xCADA, 0x6388, 0xCADB, 0x552E, + 0xCADC, 0x53D7, 0xCADD, 0x7626, 0xCADE, 0x517D, 0xCADF, 0x852C, + 0xCAE0, 0x67A2, 0xCAE1, 0x68B3, 0xCAE2, 0x6B8A, 0xCAE3, 0x6292, + 0xCAE4, 0x8F93, 0xCAE5, 0x53D4, 0xCAE6, 0x8212, 0xCAE7, 0x6DD1, + 0xCAE8, 0x758F, 0xCAE9, 0x4E66, 0xCAEA, 0x8D4E, 0xCAEB, 0x5B70, + 0xCAEC, 0x719F, 0xCAED, 0x85AF, 0xCAEE, 0x6691, 0xCAEF, 0x66D9, + 0xCAF0, 0x7F72, 0xCAF1, 0x8700, 0xCAF2, 0x9ECD, 0xCAF3, 0x9F20, + 0xCAF4, 0x5C5E, 0xCAF5, 0x672F, 0xCAF6, 0x8FF0, 0xCAF7, 0x6811, + 0xCAF8, 0x675F, 0xCAF9, 0x620D, 0xCAFA, 0x7AD6, 0xCAFB, 0x5885, + 0xCAFC, 0x5EB6, 0xCAFD, 0x6570, 0xCAFE, 0x6F31, 0xCB40, 0x8582, + 0xCB41, 0x8583, 0xCB42, 0x8586, 0xCB43, 0x8588, 0xCB44, 0x8589, + 0xCB45, 0x858A, 0xCB46, 0x858B, 0xCB47, 0x858C, 0xCB48, 0x858D, + 0xCB49, 0x858E, 0xCB4A, 0x8590, 0xCB4B, 0x8591, 0xCB4C, 0x8592, + 0xCB4D, 0x8593, 0xCB4E, 0x8594, 0xCB4F, 0x8595, 0xCB50, 0x8596, + 0xCB51, 0x8597, 0xCB52, 0x8598, 0xCB53, 0x8599, 0xCB54, 0x859A, + 0xCB55, 0x859D, 0xCB56, 0x859E, 0xCB57, 0x859F, 0xCB58, 0x85A0, + 0xCB59, 0x85A1, 0xCB5A, 0x85A2, 0xCB5B, 0x85A3, 0xCB5C, 0x85A5, + 0xCB5D, 0x85A6, 0xCB5E, 0x85A7, 0xCB5F, 0x85A9, 0xCB60, 0x85AB, + 0xCB61, 0x85AC, 0xCB62, 0x85AD, 0xCB63, 0x85B1, 0xCB64, 0x85B2, + 0xCB65, 0x85B3, 0xCB66, 0x85B4, 0xCB67, 0x85B5, 0xCB68, 0x85B6, + 0xCB69, 0x85B8, 0xCB6A, 0x85BA, 0xCB6B, 0x85BB, 0xCB6C, 0x85BC, + 0xCB6D, 0x85BD, 0xCB6E, 0x85BE, 0xCB6F, 0x85BF, 0xCB70, 0x85C0, + 0xCB71, 0x85C2, 0xCB72, 0x85C3, 0xCB73, 0x85C4, 0xCB74, 0x85C5, + 0xCB75, 0x85C6, 0xCB76, 0x85C7, 0xCB77, 0x85C8, 0xCB78, 0x85CA, + 0xCB79, 0x85CB, 0xCB7A, 0x85CC, 0xCB7B, 0x85CD, 0xCB7C, 0x85CE, + 0xCB7D, 0x85D1, 0xCB7E, 0x85D2, 0xCB80, 0x85D4, 0xCB81, 0x85D6, + 0xCB82, 0x85D7, 0xCB83, 0x85D8, 0xCB84, 0x85D9, 0xCB85, 0x85DA, + 0xCB86, 0x85DB, 0xCB87, 0x85DD, 0xCB88, 0x85DE, 0xCB89, 0x85DF, + 0xCB8A, 0x85E0, 0xCB8B, 0x85E1, 0xCB8C, 0x85E2, 0xCB8D, 0x85E3, + 0xCB8E, 0x85E5, 0xCB8F, 0x85E6, 0xCB90, 0x85E7, 0xCB91, 0x85E8, + 0xCB92, 0x85EA, 0xCB93, 0x85EB, 0xCB94, 0x85EC, 0xCB95, 0x85ED, + 0xCB96, 0x85EE, 0xCB97, 0x85EF, 0xCB98, 0x85F0, 0xCB99, 0x85F1, + 0xCB9A, 0x85F2, 0xCB9B, 0x85F3, 0xCB9C, 0x85F4, 0xCB9D, 0x85F5, + 0xCB9E, 0x85F6, 0xCB9F, 0x85F7, 0xCBA0, 0x85F8, 0xCBA1, 0x6055, + 0xCBA2, 0x5237, 0xCBA3, 0x800D, 0xCBA4, 0x6454, 0xCBA5, 0x8870, + 0xCBA6, 0x7529, 0xCBA7, 0x5E05, 0xCBA8, 0x6813, 0xCBA9, 0x62F4, + 0xCBAA, 0x971C, 0xCBAB, 0x53CC, 0xCBAC, 0x723D, 0xCBAD, 0x8C01, + 0xCBAE, 0x6C34, 0xCBAF, 0x7761, 0xCBB0, 0x7A0E, 0xCBB1, 0x542E, + 0xCBB2, 0x77AC, 0xCBB3, 0x987A, 0xCBB4, 0x821C, 0xCBB5, 0x8BF4, + 0xCBB6, 0x7855, 0xCBB7, 0x6714, 0xCBB8, 0x70C1, 0xCBB9, 0x65AF, + 0xCBBA, 0x6495, 0xCBBB, 0x5636, 0xCBBC, 0x601D, 0xCBBD, 0x79C1, + 0xCBBE, 0x53F8, 0xCBBF, 0x4E1D, 0xCBC0, 0x6B7B, 0xCBC1, 0x8086, + 0xCBC2, 0x5BFA, 0xCBC3, 0x55E3, 0xCBC4, 0x56DB, 0xCBC5, 0x4F3A, + 0xCBC6, 0x4F3C, 0xCBC7, 0x9972, 0xCBC8, 0x5DF3, 0xCBC9, 0x677E, + 0xCBCA, 0x8038, 0xCBCB, 0x6002, 0xCBCC, 0x9882, 0xCBCD, 0x9001, + 0xCBCE, 0x5B8B, 0xCBCF, 0x8BBC, 0xCBD0, 0x8BF5, 0xCBD1, 0x641C, + 0xCBD2, 0x8258, 0xCBD3, 0x64DE, 0xCBD4, 0x55FD, 0xCBD5, 0x82CF, + 0xCBD6, 0x9165, 0xCBD7, 0x4FD7, 0xCBD8, 0x7D20, 0xCBD9, 0x901F, + 0xCBDA, 0x7C9F, 0xCBDB, 0x50F3, 0xCBDC, 0x5851, 0xCBDD, 0x6EAF, + 0xCBDE, 0x5BBF, 0xCBDF, 0x8BC9, 0xCBE0, 0x8083, 0xCBE1, 0x9178, + 0xCBE2, 0x849C, 0xCBE3, 0x7B97, 0xCBE4, 0x867D, 0xCBE5, 0x968B, + 0xCBE6, 0x968F, 0xCBE7, 0x7EE5, 0xCBE8, 0x9AD3, 0xCBE9, 0x788E, + 0xCBEA, 0x5C81, 0xCBEB, 0x7A57, 0xCBEC, 0x9042, 0xCBED, 0x96A7, + 0xCBEE, 0x795F, 0xCBEF, 0x5B59, 0xCBF0, 0x635F, 0xCBF1, 0x7B0B, + 0xCBF2, 0x84D1, 0xCBF3, 0x68AD, 0xCBF4, 0x5506, 0xCBF5, 0x7F29, + 0xCBF6, 0x7410, 0xCBF7, 0x7D22, 0xCBF8, 0x9501, 0xCBF9, 0x6240, + 0xCBFA, 0x584C, 0xCBFB, 0x4ED6, 0xCBFC, 0x5B83, 0xCBFD, 0x5979, + 0xCBFE, 0x5854, 0xCC40, 0x85F9, 0xCC41, 0x85FA, 0xCC42, 0x85FC, + 0xCC43, 0x85FD, 0xCC44, 0x85FE, 0xCC45, 0x8600, 0xCC46, 0x8601, + 0xCC47, 0x8602, 0xCC48, 0x8603, 0xCC49, 0x8604, 0xCC4A, 0x8606, + 0xCC4B, 0x8607, 0xCC4C, 0x8608, 0xCC4D, 0x8609, 0xCC4E, 0x860A, + 0xCC4F, 0x860B, 0xCC50, 0x860C, 0xCC51, 0x860D, 0xCC52, 0x860E, + 0xCC53, 0x860F, 0xCC54, 0x8610, 0xCC55, 0x8612, 0xCC56, 0x8613, + 0xCC57, 0x8614, 0xCC58, 0x8615, 0xCC59, 0x8617, 0xCC5A, 0x8618, + 0xCC5B, 0x8619, 0xCC5C, 0x861A, 0xCC5D, 0x861B, 0xCC5E, 0x861C, + 0xCC5F, 0x861D, 0xCC60, 0x861E, 0xCC61, 0x861F, 0xCC62, 0x8620, + 0xCC63, 0x8621, 0xCC64, 0x8622, 0xCC65, 0x8623, 0xCC66, 0x8624, + 0xCC67, 0x8625, 0xCC68, 0x8626, 0xCC69, 0x8628, 0xCC6A, 0x862A, + 0xCC6B, 0x862B, 0xCC6C, 0x862C, 0xCC6D, 0x862D, 0xCC6E, 0x862E, + 0xCC6F, 0x862F, 0xCC70, 0x8630, 0xCC71, 0x8631, 0xCC72, 0x8632, + 0xCC73, 0x8633, 0xCC74, 0x8634, 0xCC75, 0x8635, 0xCC76, 0x8636, + 0xCC77, 0x8637, 0xCC78, 0x8639, 0xCC79, 0x863A, 0xCC7A, 0x863B, + 0xCC7B, 0x863D, 0xCC7C, 0x863E, 0xCC7D, 0x863F, 0xCC7E, 0x8640, + 0xCC80, 0x8641, 0xCC81, 0x8642, 0xCC82, 0x8643, 0xCC83, 0x8644, + 0xCC84, 0x8645, 0xCC85, 0x8646, 0xCC86, 0x8647, 0xCC87, 0x8648, + 0xCC88, 0x8649, 0xCC89, 0x864A, 0xCC8A, 0x864B, 0xCC8B, 0x864C, + 0xCC8C, 0x8652, 0xCC8D, 0x8653, 0xCC8E, 0x8655, 0xCC8F, 0x8656, + 0xCC90, 0x8657, 0xCC91, 0x8658, 0xCC92, 0x8659, 0xCC93, 0x865B, + 0xCC94, 0x865C, 0xCC95, 0x865D, 0xCC96, 0x865F, 0xCC97, 0x8660, + 0xCC98, 0x8661, 0xCC99, 0x8663, 0xCC9A, 0x8664, 0xCC9B, 0x8665, + 0xCC9C, 0x8666, 0xCC9D, 0x8667, 0xCC9E, 0x8668, 0xCC9F, 0x8669, + 0xCCA0, 0x866A, 0xCCA1, 0x736D, 0xCCA2, 0x631E, 0xCCA3, 0x8E4B, + 0xCCA4, 0x8E0F, 0xCCA5, 0x80CE, 0xCCA6, 0x82D4, 0xCCA7, 0x62AC, + 0xCCA8, 0x53F0, 0xCCA9, 0x6CF0, 0xCCAA, 0x915E, 0xCCAB, 0x592A, + 0xCCAC, 0x6001, 0xCCAD, 0x6C70, 0xCCAE, 0x574D, 0xCCAF, 0x644A, + 0xCCB0, 0x8D2A, 0xCCB1, 0x762B, 0xCCB2, 0x6EE9, 0xCCB3, 0x575B, + 0xCCB4, 0x6A80, 0xCCB5, 0x75F0, 0xCCB6, 0x6F6D, 0xCCB7, 0x8C2D, + 0xCCB8, 0x8C08, 0xCCB9, 0x5766, 0xCCBA, 0x6BEF, 0xCCBB, 0x8892, + 0xCCBC, 0x78B3, 0xCCBD, 0x63A2, 0xCCBE, 0x53F9, 0xCCBF, 0x70AD, + 0xCCC0, 0x6C64, 0xCCC1, 0x5858, 0xCCC2, 0x642A, 0xCCC3, 0x5802, + 0xCCC4, 0x68E0, 0xCCC5, 0x819B, 0xCCC6, 0x5510, 0xCCC7, 0x7CD6, + 0xCCC8, 0x5018, 0xCCC9, 0x8EBA, 0xCCCA, 0x6DCC, 0xCCCB, 0x8D9F, + 0xCCCC, 0x70EB, 0xCCCD, 0x638F, 0xCCCE, 0x6D9B, 0xCCCF, 0x6ED4, + 0xCCD0, 0x7EE6, 0xCCD1, 0x8404, 0xCCD2, 0x6843, 0xCCD3, 0x9003, + 0xCCD4, 0x6DD8, 0xCCD5, 0x9676, 0xCCD6, 0x8BA8, 0xCCD7, 0x5957, + 0xCCD8, 0x7279, 0xCCD9, 0x85E4, 0xCCDA, 0x817E, 0xCCDB, 0x75BC, + 0xCCDC, 0x8A8A, 0xCCDD, 0x68AF, 0xCCDE, 0x5254, 0xCCDF, 0x8E22, + 0xCCE0, 0x9511, 0xCCE1, 0x63D0, 0xCCE2, 0x9898, 0xCCE3, 0x8E44, + 0xCCE4, 0x557C, 0xCCE5, 0x4F53, 0xCCE6, 0x66FF, 0xCCE7, 0x568F, + 0xCCE8, 0x60D5, 0xCCE9, 0x6D95, 0xCCEA, 0x5243, 0xCCEB, 0x5C49, + 0xCCEC, 0x5929, 0xCCED, 0x6DFB, 0xCCEE, 0x586B, 0xCCEF, 0x7530, + 0xCCF0, 0x751C, 0xCCF1, 0x606C, 0xCCF2, 0x8214, 0xCCF3, 0x8146, + 0xCCF4, 0x6311, 0xCCF5, 0x6761, 0xCCF6, 0x8FE2, 0xCCF7, 0x773A, + 0xCCF8, 0x8DF3, 0xCCF9, 0x8D34, 0xCCFA, 0x94C1, 0xCCFB, 0x5E16, + 0xCCFC, 0x5385, 0xCCFD, 0x542C, 0xCCFE, 0x70C3, 0xCD40, 0x866D, + 0xCD41, 0x866F, 0xCD42, 0x8670, 0xCD43, 0x8672, 0xCD44, 0x8673, + 0xCD45, 0x8674, 0xCD46, 0x8675, 0xCD47, 0x8676, 0xCD48, 0x8677, + 0xCD49, 0x8678, 0xCD4A, 0x8683, 0xCD4B, 0x8684, 0xCD4C, 0x8685, + 0xCD4D, 0x8686, 0xCD4E, 0x8687, 0xCD4F, 0x8688, 0xCD50, 0x8689, + 0xCD51, 0x868E, 0xCD52, 0x868F, 0xCD53, 0x8690, 0xCD54, 0x8691, + 0xCD55, 0x8692, 0xCD56, 0x8694, 0xCD57, 0x8696, 0xCD58, 0x8697, + 0xCD59, 0x8698, 0xCD5A, 0x8699, 0xCD5B, 0x869A, 0xCD5C, 0x869B, + 0xCD5D, 0x869E, 0xCD5E, 0x869F, 0xCD5F, 0x86A0, 0xCD60, 0x86A1, + 0xCD61, 0x86A2, 0xCD62, 0x86A5, 0xCD63, 0x86A6, 0xCD64, 0x86AB, + 0xCD65, 0x86AD, 0xCD66, 0x86AE, 0xCD67, 0x86B2, 0xCD68, 0x86B3, + 0xCD69, 0x86B7, 0xCD6A, 0x86B8, 0xCD6B, 0x86B9, 0xCD6C, 0x86BB, + 0xCD6D, 0x86BC, 0xCD6E, 0x86BD, 0xCD6F, 0x86BE, 0xCD70, 0x86BF, + 0xCD71, 0x86C1, 0xCD72, 0x86C2, 0xCD73, 0x86C3, 0xCD74, 0x86C5, + 0xCD75, 0x86C8, 0xCD76, 0x86CC, 0xCD77, 0x86CD, 0xCD78, 0x86D2, + 0xCD79, 0x86D3, 0xCD7A, 0x86D5, 0xCD7B, 0x86D6, 0xCD7C, 0x86D7, + 0xCD7D, 0x86DA, 0xCD7E, 0x86DC, 0xCD80, 0x86DD, 0xCD81, 0x86E0, + 0xCD82, 0x86E1, 0xCD83, 0x86E2, 0xCD84, 0x86E3, 0xCD85, 0x86E5, + 0xCD86, 0x86E6, 0xCD87, 0x86E7, 0xCD88, 0x86E8, 0xCD89, 0x86EA, + 0xCD8A, 0x86EB, 0xCD8B, 0x86EC, 0xCD8C, 0x86EF, 0xCD8D, 0x86F5, + 0xCD8E, 0x86F6, 0xCD8F, 0x86F7, 0xCD90, 0x86FA, 0xCD91, 0x86FB, + 0xCD92, 0x86FC, 0xCD93, 0x86FD, 0xCD94, 0x86FF, 0xCD95, 0x8701, + 0xCD96, 0x8704, 0xCD97, 0x8705, 0xCD98, 0x8706, 0xCD99, 0x870B, + 0xCD9A, 0x870C, 0xCD9B, 0x870E, 0xCD9C, 0x870F, 0xCD9D, 0x8710, + 0xCD9E, 0x8711, 0xCD9F, 0x8714, 0xCDA0, 0x8716, 0xCDA1, 0x6C40, + 0xCDA2, 0x5EF7, 0xCDA3, 0x505C, 0xCDA4, 0x4EAD, 0xCDA5, 0x5EAD, + 0xCDA6, 0x633A, 0xCDA7, 0x8247, 0xCDA8, 0x901A, 0xCDA9, 0x6850, + 0xCDAA, 0x916E, 0xCDAB, 0x77B3, 0xCDAC, 0x540C, 0xCDAD, 0x94DC, + 0xCDAE, 0x5F64, 0xCDAF, 0x7AE5, 0xCDB0, 0x6876, 0xCDB1, 0x6345, + 0xCDB2, 0x7B52, 0xCDB3, 0x7EDF, 0xCDB4, 0x75DB, 0xCDB5, 0x5077, + 0xCDB6, 0x6295, 0xCDB7, 0x5934, 0xCDB8, 0x900F, 0xCDB9, 0x51F8, + 0xCDBA, 0x79C3, 0xCDBB, 0x7A81, 0xCDBC, 0x56FE, 0xCDBD, 0x5F92, + 0xCDBE, 0x9014, 0xCDBF, 0x6D82, 0xCDC0, 0x5C60, 0xCDC1, 0x571F, + 0xCDC2, 0x5410, 0xCDC3, 0x5154, 0xCDC4, 0x6E4D, 0xCDC5, 0x56E2, + 0xCDC6, 0x63A8, 0xCDC7, 0x9893, 0xCDC8, 0x817F, 0xCDC9, 0x8715, + 0xCDCA, 0x892A, 0xCDCB, 0x9000, 0xCDCC, 0x541E, 0xCDCD, 0x5C6F, + 0xCDCE, 0x81C0, 0xCDCF, 0x62D6, 0xCDD0, 0x6258, 0xCDD1, 0x8131, + 0xCDD2, 0x9E35, 0xCDD3, 0x9640, 0xCDD4, 0x9A6E, 0xCDD5, 0x9A7C, + 0xCDD6, 0x692D, 0xCDD7, 0x59A5, 0xCDD8, 0x62D3, 0xCDD9, 0x553E, + 0xCDDA, 0x6316, 0xCDDB, 0x54C7, 0xCDDC, 0x86D9, 0xCDDD, 0x6D3C, + 0xCDDE, 0x5A03, 0xCDDF, 0x74E6, 0xCDE0, 0x889C, 0xCDE1, 0x6B6A, + 0xCDE2, 0x5916, 0xCDE3, 0x8C4C, 0xCDE4, 0x5F2F, 0xCDE5, 0x6E7E, + 0xCDE6, 0x73A9, 0xCDE7, 0x987D, 0xCDE8, 0x4E38, 0xCDE9, 0x70F7, + 0xCDEA, 0x5B8C, 0xCDEB, 0x7897, 0xCDEC, 0x633D, 0xCDED, 0x665A, + 0xCDEE, 0x7696, 0xCDEF, 0x60CB, 0xCDF0, 0x5B9B, 0xCDF1, 0x5A49, + 0xCDF2, 0x4E07, 0xCDF3, 0x8155, 0xCDF4, 0x6C6A, 0xCDF5, 0x738B, + 0xCDF6, 0x4EA1, 0xCDF7, 0x6789, 0xCDF8, 0x7F51, 0xCDF9, 0x5F80, + 0xCDFA, 0x65FA, 0xCDFB, 0x671B, 0xCDFC, 0x5FD8, 0xCDFD, 0x5984, + 0xCDFE, 0x5A01, 0xCE40, 0x8719, 0xCE41, 0x871B, 0xCE42, 0x871D, + 0xCE43, 0x871F, 0xCE44, 0x8720, 0xCE45, 0x8724, 0xCE46, 0x8726, + 0xCE47, 0x8727, 0xCE48, 0x8728, 0xCE49, 0x872A, 0xCE4A, 0x872B, + 0xCE4B, 0x872C, 0xCE4C, 0x872D, 0xCE4D, 0x872F, 0xCE4E, 0x8730, + 0xCE4F, 0x8732, 0xCE50, 0x8733, 0xCE51, 0x8735, 0xCE52, 0x8736, + 0xCE53, 0x8738, 0xCE54, 0x8739, 0xCE55, 0x873A, 0xCE56, 0x873C, + 0xCE57, 0x873D, 0xCE58, 0x8740, 0xCE59, 0x8741, 0xCE5A, 0x8742, + 0xCE5B, 0x8743, 0xCE5C, 0x8744, 0xCE5D, 0x8745, 0xCE5E, 0x8746, + 0xCE5F, 0x874A, 0xCE60, 0x874B, 0xCE61, 0x874D, 0xCE62, 0x874F, + 0xCE63, 0x8750, 0xCE64, 0x8751, 0xCE65, 0x8752, 0xCE66, 0x8754, + 0xCE67, 0x8755, 0xCE68, 0x8756, 0xCE69, 0x8758, 0xCE6A, 0x875A, + 0xCE6B, 0x875B, 0xCE6C, 0x875C, 0xCE6D, 0x875D, 0xCE6E, 0x875E, + 0xCE6F, 0x875F, 0xCE70, 0x8761, 0xCE71, 0x8762, 0xCE72, 0x8766, + 0xCE73, 0x8767, 0xCE74, 0x8768, 0xCE75, 0x8769, 0xCE76, 0x876A, + 0xCE77, 0x876B, 0xCE78, 0x876C, 0xCE79, 0x876D, 0xCE7A, 0x876F, + 0xCE7B, 0x8771, 0xCE7C, 0x8772, 0xCE7D, 0x8773, 0xCE7E, 0x8775, + 0xCE80, 0x8777, 0xCE81, 0x8778, 0xCE82, 0x8779, 0xCE83, 0x877A, + 0xCE84, 0x877F, 0xCE85, 0x8780, 0xCE86, 0x8781, 0xCE87, 0x8784, + 0xCE88, 0x8786, 0xCE89, 0x8787, 0xCE8A, 0x8789, 0xCE8B, 0x878A, + 0xCE8C, 0x878C, 0xCE8D, 0x878E, 0xCE8E, 0x878F, 0xCE8F, 0x8790, + 0xCE90, 0x8791, 0xCE91, 0x8792, 0xCE92, 0x8794, 0xCE93, 0x8795, + 0xCE94, 0x8796, 0xCE95, 0x8798, 0xCE96, 0x8799, 0xCE97, 0x879A, + 0xCE98, 0x879B, 0xCE99, 0x879C, 0xCE9A, 0x879D, 0xCE9B, 0x879E, + 0xCE9C, 0x87A0, 0xCE9D, 0x87A1, 0xCE9E, 0x87A2, 0xCE9F, 0x87A3, + 0xCEA0, 0x87A4, 0xCEA1, 0x5DCD, 0xCEA2, 0x5FAE, 0xCEA3, 0x5371, + 0xCEA4, 0x97E6, 0xCEA5, 0x8FDD, 0xCEA6, 0x6845, 0xCEA7, 0x56F4, + 0xCEA8, 0x552F, 0xCEA9, 0x60DF, 0xCEAA, 0x4E3A, 0xCEAB, 0x6F4D, + 0xCEAC, 0x7EF4, 0xCEAD, 0x82C7, 0xCEAE, 0x840E, 0xCEAF, 0x59D4, + 0xCEB0, 0x4F1F, 0xCEB1, 0x4F2A, 0xCEB2, 0x5C3E, 0xCEB3, 0x7EAC, + 0xCEB4, 0x672A, 0xCEB5, 0x851A, 0xCEB6, 0x5473, 0xCEB7, 0x754F, + 0xCEB8, 0x80C3, 0xCEB9, 0x5582, 0xCEBA, 0x9B4F, 0xCEBB, 0x4F4D, + 0xCEBC, 0x6E2D, 0xCEBD, 0x8C13, 0xCEBE, 0x5C09, 0xCEBF, 0x6170, + 0xCEC0, 0x536B, 0xCEC1, 0x761F, 0xCEC2, 0x6E29, 0xCEC3, 0x868A, + 0xCEC4, 0x6587, 0xCEC5, 0x95FB, 0xCEC6, 0x7EB9, 0xCEC7, 0x543B, + 0xCEC8, 0x7A33, 0xCEC9, 0x7D0A, 0xCECA, 0x95EE, 0xCECB, 0x55E1, + 0xCECC, 0x7FC1, 0xCECD, 0x74EE, 0xCECE, 0x631D, 0xCECF, 0x8717, + 0xCED0, 0x6DA1, 0xCED1, 0x7A9D, 0xCED2, 0x6211, 0xCED3, 0x65A1, + 0xCED4, 0x5367, 0xCED5, 0x63E1, 0xCED6, 0x6C83, 0xCED7, 0x5DEB, + 0xCED8, 0x545C, 0xCED9, 0x94A8, 0xCEDA, 0x4E4C, 0xCEDB, 0x6C61, + 0xCEDC, 0x8BEC, 0xCEDD, 0x5C4B, 0xCEDE, 0x65E0, 0xCEDF, 0x829C, + 0xCEE0, 0x68A7, 0xCEE1, 0x543E, 0xCEE2, 0x5434, 0xCEE3, 0x6BCB, + 0xCEE4, 0x6B66, 0xCEE5, 0x4E94, 0xCEE6, 0x6342, 0xCEE7, 0x5348, + 0xCEE8, 0x821E, 0xCEE9, 0x4F0D, 0xCEEA, 0x4FAE, 0xCEEB, 0x575E, + 0xCEEC, 0x620A, 0xCEED, 0x96FE, 0xCEEE, 0x6664, 0xCEEF, 0x7269, + 0xCEF0, 0x52FF, 0xCEF1, 0x52A1, 0xCEF2, 0x609F, 0xCEF3, 0x8BEF, + 0xCEF4, 0x6614, 0xCEF5, 0x7199, 0xCEF6, 0x6790, 0xCEF7, 0x897F, + 0xCEF8, 0x7852, 0xCEF9, 0x77FD, 0xCEFA, 0x6670, 0xCEFB, 0x563B, + 0xCEFC, 0x5438, 0xCEFD, 0x9521, 0xCEFE, 0x727A, 0xCF40, 0x87A5, + 0xCF41, 0x87A6, 0xCF42, 0x87A7, 0xCF43, 0x87A9, 0xCF44, 0x87AA, + 0xCF45, 0x87AE, 0xCF46, 0x87B0, 0xCF47, 0x87B1, 0xCF48, 0x87B2, + 0xCF49, 0x87B4, 0xCF4A, 0x87B6, 0xCF4B, 0x87B7, 0xCF4C, 0x87B8, + 0xCF4D, 0x87B9, 0xCF4E, 0x87BB, 0xCF4F, 0x87BC, 0xCF50, 0x87BE, + 0xCF51, 0x87BF, 0xCF52, 0x87C1, 0xCF53, 0x87C2, 0xCF54, 0x87C3, + 0xCF55, 0x87C4, 0xCF56, 0x87C5, 0xCF57, 0x87C7, 0xCF58, 0x87C8, + 0xCF59, 0x87C9, 0xCF5A, 0x87CC, 0xCF5B, 0x87CD, 0xCF5C, 0x87CE, + 0xCF5D, 0x87CF, 0xCF5E, 0x87D0, 0xCF5F, 0x87D4, 0xCF60, 0x87D5, + 0xCF61, 0x87D6, 0xCF62, 0x87D7, 0xCF63, 0x87D8, 0xCF64, 0x87D9, + 0xCF65, 0x87DA, 0xCF66, 0x87DC, 0xCF67, 0x87DD, 0xCF68, 0x87DE, + 0xCF69, 0x87DF, 0xCF6A, 0x87E1, 0xCF6B, 0x87E2, 0xCF6C, 0x87E3, + 0xCF6D, 0x87E4, 0xCF6E, 0x87E6, 0xCF6F, 0x87E7, 0xCF70, 0x87E8, + 0xCF71, 0x87E9, 0xCF72, 0x87EB, 0xCF73, 0x87EC, 0xCF74, 0x87ED, + 0xCF75, 0x87EF, 0xCF76, 0x87F0, 0xCF77, 0x87F1, 0xCF78, 0x87F2, + 0xCF79, 0x87F3, 0xCF7A, 0x87F4, 0xCF7B, 0x87F5, 0xCF7C, 0x87F6, + 0xCF7D, 0x87F7, 0xCF7E, 0x87F8, 0xCF80, 0x87FA, 0xCF81, 0x87FB, + 0xCF82, 0x87FC, 0xCF83, 0x87FD, 0xCF84, 0x87FF, 0xCF85, 0x8800, + 0xCF86, 0x8801, 0xCF87, 0x8802, 0xCF88, 0x8804, 0xCF89, 0x8805, + 0xCF8A, 0x8806, 0xCF8B, 0x8807, 0xCF8C, 0x8808, 0xCF8D, 0x8809, + 0xCF8E, 0x880B, 0xCF8F, 0x880C, 0xCF90, 0x880D, 0xCF91, 0x880E, + 0xCF92, 0x880F, 0xCF93, 0x8810, 0xCF94, 0x8811, 0xCF95, 0x8812, + 0xCF96, 0x8814, 0xCF97, 0x8817, 0xCF98, 0x8818, 0xCF99, 0x8819, + 0xCF9A, 0x881A, 0xCF9B, 0x881C, 0xCF9C, 0x881D, 0xCF9D, 0x881E, + 0xCF9E, 0x881F, 0xCF9F, 0x8820, 0xCFA0, 0x8823, 0xCFA1, 0x7A00, + 0xCFA2, 0x606F, 0xCFA3, 0x5E0C, 0xCFA4, 0x6089, 0xCFA5, 0x819D, + 0xCFA6, 0x5915, 0xCFA7, 0x60DC, 0xCFA8, 0x7184, 0xCFA9, 0x70EF, + 0xCFAA, 0x6EAA, 0xCFAB, 0x6C50, 0xCFAC, 0x7280, 0xCFAD, 0x6A84, + 0xCFAE, 0x88AD, 0xCFAF, 0x5E2D, 0xCFB0, 0x4E60, 0xCFB1, 0x5AB3, + 0xCFB2, 0x559C, 0xCFB3, 0x94E3, 0xCFB4, 0x6D17, 0xCFB5, 0x7CFB, + 0xCFB6, 0x9699, 0xCFB7, 0x620F, 0xCFB8, 0x7EC6, 0xCFB9, 0x778E, + 0xCFBA, 0x867E, 0xCFBB, 0x5323, 0xCFBC, 0x971E, 0xCFBD, 0x8F96, + 0xCFBE, 0x6687, 0xCFBF, 0x5CE1, 0xCFC0, 0x4FA0, 0xCFC1, 0x72ED, + 0xCFC2, 0x4E0B, 0xCFC3, 0x53A6, 0xCFC4, 0x590F, 0xCFC5, 0x5413, + 0xCFC6, 0x6380, 0xCFC7, 0x9528, 0xCFC8, 0x5148, 0xCFC9, 0x4ED9, + 0xCFCA, 0x9C9C, 0xCFCB, 0x7EA4, 0xCFCC, 0x54B8, 0xCFCD, 0x8D24, + 0xCFCE, 0x8854, 0xCFCF, 0x8237, 0xCFD0, 0x95F2, 0xCFD1, 0x6D8E, + 0xCFD2, 0x5F26, 0xCFD3, 0x5ACC, 0xCFD4, 0x663E, 0xCFD5, 0x9669, + 0xCFD6, 0x73B0, 0xCFD7, 0x732E, 0xCFD8, 0x53BF, 0xCFD9, 0x817A, + 0xCFDA, 0x9985, 0xCFDB, 0x7FA1, 0xCFDC, 0x5BAA, 0xCFDD, 0x9677, + 0xCFDE, 0x9650, 0xCFDF, 0x7EBF, 0xCFE0, 0x76F8, 0xCFE1, 0x53A2, + 0xCFE2, 0x9576, 0xCFE3, 0x9999, 0xCFE4, 0x7BB1, 0xCFE5, 0x8944, + 0xCFE6, 0x6E58, 0xCFE7, 0x4E61, 0xCFE8, 0x7FD4, 0xCFE9, 0x7965, + 0xCFEA, 0x8BE6, 0xCFEB, 0x60F3, 0xCFEC, 0x54CD, 0xCFED, 0x4EAB, + 0xCFEE, 0x9879, 0xCFEF, 0x5DF7, 0xCFF0, 0x6A61, 0xCFF1, 0x50CF, + 0xCFF2, 0x5411, 0xCFF3, 0x8C61, 0xCFF4, 0x8427, 0xCFF5, 0x785D, + 0xCFF6, 0x9704, 0xCFF7, 0x524A, 0xCFF8, 0x54EE, 0xCFF9, 0x56A3, + 0xCFFA, 0x9500, 0xCFFB, 0x6D88, 0xCFFC, 0x5BB5, 0xCFFD, 0x6DC6, + 0xCFFE, 0x6653, 0xD040, 0x8824, 0xD041, 0x8825, 0xD042, 0x8826, + 0xD043, 0x8827, 0xD044, 0x8828, 0xD045, 0x8829, 0xD046, 0x882A, + 0xD047, 0x882B, 0xD048, 0x882C, 0xD049, 0x882D, 0xD04A, 0x882E, + 0xD04B, 0x882F, 0xD04C, 0x8830, 0xD04D, 0x8831, 0xD04E, 0x8833, + 0xD04F, 0x8834, 0xD050, 0x8835, 0xD051, 0x8836, 0xD052, 0x8837, + 0xD053, 0x8838, 0xD054, 0x883A, 0xD055, 0x883B, 0xD056, 0x883D, + 0xD057, 0x883E, 0xD058, 0x883F, 0xD059, 0x8841, 0xD05A, 0x8842, + 0xD05B, 0x8843, 0xD05C, 0x8846, 0xD05D, 0x8847, 0xD05E, 0x8848, + 0xD05F, 0x8849, 0xD060, 0x884A, 0xD061, 0x884B, 0xD062, 0x884E, + 0xD063, 0x884F, 0xD064, 0x8850, 0xD065, 0x8851, 0xD066, 0x8852, + 0xD067, 0x8853, 0xD068, 0x8855, 0xD069, 0x8856, 0xD06A, 0x8858, + 0xD06B, 0x885A, 0xD06C, 0x885B, 0xD06D, 0x885C, 0xD06E, 0x885D, + 0xD06F, 0x885E, 0xD070, 0x885F, 0xD071, 0x8860, 0xD072, 0x8866, + 0xD073, 0x8867, 0xD074, 0x886A, 0xD075, 0x886D, 0xD076, 0x886F, + 0xD077, 0x8871, 0xD078, 0x8873, 0xD079, 0x8874, 0xD07A, 0x8875, + 0xD07B, 0x8876, 0xD07C, 0x8878, 0xD07D, 0x8879, 0xD07E, 0x887A, + 0xD080, 0x887B, 0xD081, 0x887C, 0xD082, 0x8880, 0xD083, 0x8883, + 0xD084, 0x8886, 0xD085, 0x8887, 0xD086, 0x8889, 0xD087, 0x888A, + 0xD088, 0x888C, 0xD089, 0x888E, 0xD08A, 0x888F, 0xD08B, 0x8890, + 0xD08C, 0x8891, 0xD08D, 0x8893, 0xD08E, 0x8894, 0xD08F, 0x8895, + 0xD090, 0x8897, 0xD091, 0x8898, 0xD092, 0x8899, 0xD093, 0x889A, + 0xD094, 0x889B, 0xD095, 0x889D, 0xD096, 0x889E, 0xD097, 0x889F, + 0xD098, 0x88A0, 0xD099, 0x88A1, 0xD09A, 0x88A3, 0xD09B, 0x88A5, + 0xD09C, 0x88A6, 0xD09D, 0x88A7, 0xD09E, 0x88A8, 0xD09F, 0x88A9, + 0xD0A0, 0x88AA, 0xD0A1, 0x5C0F, 0xD0A2, 0x5B5D, 0xD0A3, 0x6821, + 0xD0A4, 0x8096, 0xD0A5, 0x5578, 0xD0A6, 0x7B11, 0xD0A7, 0x6548, + 0xD0A8, 0x6954, 0xD0A9, 0x4E9B, 0xD0AA, 0x6B47, 0xD0AB, 0x874E, + 0xD0AC, 0x978B, 0xD0AD, 0x534F, 0xD0AE, 0x631F, 0xD0AF, 0x643A, + 0xD0B0, 0x90AA, 0xD0B1, 0x659C, 0xD0B2, 0x80C1, 0xD0B3, 0x8C10, + 0xD0B4, 0x5199, 0xD0B5, 0x68B0, 0xD0B6, 0x5378, 0xD0B7, 0x87F9, + 0xD0B8, 0x61C8, 0xD0B9, 0x6CC4, 0xD0BA, 0x6CFB, 0xD0BB, 0x8C22, + 0xD0BC, 0x5C51, 0xD0BD, 0x85AA, 0xD0BE, 0x82AF, 0xD0BF, 0x950C, + 0xD0C0, 0x6B23, 0xD0C1, 0x8F9B, 0xD0C2, 0x65B0, 0xD0C3, 0x5FFB, + 0xD0C4, 0x5FC3, 0xD0C5, 0x4FE1, 0xD0C6, 0x8845, 0xD0C7, 0x661F, + 0xD0C8, 0x8165, 0xD0C9, 0x7329, 0xD0CA, 0x60FA, 0xD0CB, 0x5174, + 0xD0CC, 0x5211, 0xD0CD, 0x578B, 0xD0CE, 0x5F62, 0xD0CF, 0x90A2, + 0xD0D0, 0x884C, 0xD0D1, 0x9192, 0xD0D2, 0x5E78, 0xD0D3, 0x674F, + 0xD0D4, 0x6027, 0xD0D5, 0x59D3, 0xD0D6, 0x5144, 0xD0D7, 0x51F6, + 0xD0D8, 0x80F8, 0xD0D9, 0x5308, 0xD0DA, 0x6C79, 0xD0DB, 0x96C4, + 0xD0DC, 0x718A, 0xD0DD, 0x4F11, 0xD0DE, 0x4FEE, 0xD0DF, 0x7F9E, + 0xD0E0, 0x673D, 0xD0E1, 0x55C5, 0xD0E2, 0x9508, 0xD0E3, 0x79C0, + 0xD0E4, 0x8896, 0xD0E5, 0x7EE3, 0xD0E6, 0x589F, 0xD0E7, 0x620C, + 0xD0E8, 0x9700, 0xD0E9, 0x865A, 0xD0EA, 0x5618, 0xD0EB, 0x987B, + 0xD0EC, 0x5F90, 0xD0ED, 0x8BB8, 0xD0EE, 0x84C4, 0xD0EF, 0x9157, + 0xD0F0, 0x53D9, 0xD0F1, 0x65ED, 0xD0F2, 0x5E8F, 0xD0F3, 0x755C, + 0xD0F4, 0x6064, 0xD0F5, 0x7D6E, 0xD0F6, 0x5A7F, 0xD0F7, 0x7EEA, + 0xD0F8, 0x7EED, 0xD0F9, 0x8F69, 0xD0FA, 0x55A7, 0xD0FB, 0x5BA3, + 0xD0FC, 0x60AC, 0xD0FD, 0x65CB, 0xD0FE, 0x7384, 0xD140, 0x88AC, + 0xD141, 0x88AE, 0xD142, 0x88AF, 0xD143, 0x88B0, 0xD144, 0x88B2, + 0xD145, 0x88B3, 0xD146, 0x88B4, 0xD147, 0x88B5, 0xD148, 0x88B6, + 0xD149, 0x88B8, 0xD14A, 0x88B9, 0xD14B, 0x88BA, 0xD14C, 0x88BB, + 0xD14D, 0x88BD, 0xD14E, 0x88BE, 0xD14F, 0x88BF, 0xD150, 0x88C0, + 0xD151, 0x88C3, 0xD152, 0x88C4, 0xD153, 0x88C7, 0xD154, 0x88C8, + 0xD155, 0x88CA, 0xD156, 0x88CB, 0xD157, 0x88CC, 0xD158, 0x88CD, + 0xD159, 0x88CF, 0xD15A, 0x88D0, 0xD15B, 0x88D1, 0xD15C, 0x88D3, + 0xD15D, 0x88D6, 0xD15E, 0x88D7, 0xD15F, 0x88DA, 0xD160, 0x88DB, + 0xD161, 0x88DC, 0xD162, 0x88DD, 0xD163, 0x88DE, 0xD164, 0x88E0, + 0xD165, 0x88E1, 0xD166, 0x88E6, 0xD167, 0x88E7, 0xD168, 0x88E9, + 0xD169, 0x88EA, 0xD16A, 0x88EB, 0xD16B, 0x88EC, 0xD16C, 0x88ED, + 0xD16D, 0x88EE, 0xD16E, 0x88EF, 0xD16F, 0x88F2, 0xD170, 0x88F5, + 0xD171, 0x88F6, 0xD172, 0x88F7, 0xD173, 0x88FA, 0xD174, 0x88FB, + 0xD175, 0x88FD, 0xD176, 0x88FF, 0xD177, 0x8900, 0xD178, 0x8901, + 0xD179, 0x8903, 0xD17A, 0x8904, 0xD17B, 0x8905, 0xD17C, 0x8906, + 0xD17D, 0x8907, 0xD17E, 0x8908, 0xD180, 0x8909, 0xD181, 0x890B, + 0xD182, 0x890C, 0xD183, 0x890D, 0xD184, 0x890E, 0xD185, 0x890F, + 0xD186, 0x8911, 0xD187, 0x8914, 0xD188, 0x8915, 0xD189, 0x8916, + 0xD18A, 0x8917, 0xD18B, 0x8918, 0xD18C, 0x891C, 0xD18D, 0x891D, + 0xD18E, 0x891E, 0xD18F, 0x891F, 0xD190, 0x8920, 0xD191, 0x8922, + 0xD192, 0x8923, 0xD193, 0x8924, 0xD194, 0x8926, 0xD195, 0x8927, + 0xD196, 0x8928, 0xD197, 0x8929, 0xD198, 0x892C, 0xD199, 0x892D, + 0xD19A, 0x892E, 0xD19B, 0x892F, 0xD19C, 0x8931, 0xD19D, 0x8932, + 0xD19E, 0x8933, 0xD19F, 0x8935, 0xD1A0, 0x8937, 0xD1A1, 0x9009, + 0xD1A2, 0x7663, 0xD1A3, 0x7729, 0xD1A4, 0x7EDA, 0xD1A5, 0x9774, + 0xD1A6, 0x859B, 0xD1A7, 0x5B66, 0xD1A8, 0x7A74, 0xD1A9, 0x96EA, + 0xD1AA, 0x8840, 0xD1AB, 0x52CB, 0xD1AC, 0x718F, 0xD1AD, 0x5FAA, + 0xD1AE, 0x65EC, 0xD1AF, 0x8BE2, 0xD1B0, 0x5BFB, 0xD1B1, 0x9A6F, + 0xD1B2, 0x5DE1, 0xD1B3, 0x6B89, 0xD1B4, 0x6C5B, 0xD1B5, 0x8BAD, + 0xD1B6, 0x8BAF, 0xD1B7, 0x900A, 0xD1B8, 0x8FC5, 0xD1B9, 0x538B, + 0xD1BA, 0x62BC, 0xD1BB, 0x9E26, 0xD1BC, 0x9E2D, 0xD1BD, 0x5440, + 0xD1BE, 0x4E2B, 0xD1BF, 0x82BD, 0xD1C0, 0x7259, 0xD1C1, 0x869C, + 0xD1C2, 0x5D16, 0xD1C3, 0x8859, 0xD1C4, 0x6DAF, 0xD1C5, 0x96C5, + 0xD1C6, 0x54D1, 0xD1C7, 0x4E9A, 0xD1C8, 0x8BB6, 0xD1C9, 0x7109, + 0xD1CA, 0x54BD, 0xD1CB, 0x9609, 0xD1CC, 0x70DF, 0xD1CD, 0x6DF9, + 0xD1CE, 0x76D0, 0xD1CF, 0x4E25, 0xD1D0, 0x7814, 0xD1D1, 0x8712, + 0xD1D2, 0x5CA9, 0xD1D3, 0x5EF6, 0xD1D4, 0x8A00, 0xD1D5, 0x989C, + 0xD1D6, 0x960E, 0xD1D7, 0x708E, 0xD1D8, 0x6CBF, 0xD1D9, 0x5944, + 0xD1DA, 0x63A9, 0xD1DB, 0x773C, 0xD1DC, 0x884D, 0xD1DD, 0x6F14, + 0xD1DE, 0x8273, 0xD1DF, 0x5830, 0xD1E0, 0x71D5, 0xD1E1, 0x538C, + 0xD1E2, 0x781A, 0xD1E3, 0x96C1, 0xD1E4, 0x5501, 0xD1E5, 0x5F66, + 0xD1E6, 0x7130, 0xD1E7, 0x5BB4, 0xD1E8, 0x8C1A, 0xD1E9, 0x9A8C, + 0xD1EA, 0x6B83, 0xD1EB, 0x592E, 0xD1EC, 0x9E2F, 0xD1ED, 0x79E7, + 0xD1EE, 0x6768, 0xD1EF, 0x626C, 0xD1F0, 0x4F6F, 0xD1F1, 0x75A1, + 0xD1F2, 0x7F8A, 0xD1F3, 0x6D0B, 0xD1F4, 0x9633, 0xD1F5, 0x6C27, + 0xD1F6, 0x4EF0, 0xD1F7, 0x75D2, 0xD1F8, 0x517B, 0xD1F9, 0x6837, + 0xD1FA, 0x6F3E, 0xD1FB, 0x9080, 0xD1FC, 0x8170, 0xD1FD, 0x5996, + 0xD1FE, 0x7476, 0xD240, 0x8938, 0xD241, 0x8939, 0xD242, 0x893A, + 0xD243, 0x893B, 0xD244, 0x893C, 0xD245, 0x893D, 0xD246, 0x893E, + 0xD247, 0x893F, 0xD248, 0x8940, 0xD249, 0x8942, 0xD24A, 0x8943, + 0xD24B, 0x8945, 0xD24C, 0x8946, 0xD24D, 0x8947, 0xD24E, 0x8948, + 0xD24F, 0x8949, 0xD250, 0x894A, 0xD251, 0x894B, 0xD252, 0x894C, + 0xD253, 0x894D, 0xD254, 0x894E, 0xD255, 0x894F, 0xD256, 0x8950, + 0xD257, 0x8951, 0xD258, 0x8952, 0xD259, 0x8953, 0xD25A, 0x8954, + 0xD25B, 0x8955, 0xD25C, 0x8956, 0xD25D, 0x8957, 0xD25E, 0x8958, + 0xD25F, 0x8959, 0xD260, 0x895A, 0xD261, 0x895B, 0xD262, 0x895C, + 0xD263, 0x895D, 0xD264, 0x8960, 0xD265, 0x8961, 0xD266, 0x8962, + 0xD267, 0x8963, 0xD268, 0x8964, 0xD269, 0x8965, 0xD26A, 0x8967, + 0xD26B, 0x8968, 0xD26C, 0x8969, 0xD26D, 0x896A, 0xD26E, 0x896B, + 0xD26F, 0x896C, 0xD270, 0x896D, 0xD271, 0x896E, 0xD272, 0x896F, + 0xD273, 0x8970, 0xD274, 0x8971, 0xD275, 0x8972, 0xD276, 0x8973, + 0xD277, 0x8974, 0xD278, 0x8975, 0xD279, 0x8976, 0xD27A, 0x8977, + 0xD27B, 0x8978, 0xD27C, 0x8979, 0xD27D, 0x897A, 0xD27E, 0x897C, + 0xD280, 0x897D, 0xD281, 0x897E, 0xD282, 0x8980, 0xD283, 0x8982, + 0xD284, 0x8984, 0xD285, 0x8985, 0xD286, 0x8987, 0xD287, 0x8988, + 0xD288, 0x8989, 0xD289, 0x898A, 0xD28A, 0x898B, 0xD28B, 0x898C, + 0xD28C, 0x898D, 0xD28D, 0x898E, 0xD28E, 0x898F, 0xD28F, 0x8990, + 0xD290, 0x8991, 0xD291, 0x8992, 0xD292, 0x8993, 0xD293, 0x8994, + 0xD294, 0x8995, 0xD295, 0x8996, 0xD296, 0x8997, 0xD297, 0x8998, + 0xD298, 0x8999, 0xD299, 0x899A, 0xD29A, 0x899B, 0xD29B, 0x899C, + 0xD29C, 0x899D, 0xD29D, 0x899E, 0xD29E, 0x899F, 0xD29F, 0x89A0, + 0xD2A0, 0x89A1, 0xD2A1, 0x6447, 0xD2A2, 0x5C27, 0xD2A3, 0x9065, + 0xD2A4, 0x7A91, 0xD2A5, 0x8C23, 0xD2A6, 0x59DA, 0xD2A7, 0x54AC, + 0xD2A8, 0x8200, 0xD2A9, 0x836F, 0xD2AA, 0x8981, 0xD2AB, 0x8000, + 0xD2AC, 0x6930, 0xD2AD, 0x564E, 0xD2AE, 0x8036, 0xD2AF, 0x7237, + 0xD2B0, 0x91CE, 0xD2B1, 0x51B6, 0xD2B2, 0x4E5F, 0xD2B3, 0x9875, + 0xD2B4, 0x6396, 0xD2B5, 0x4E1A, 0xD2B6, 0x53F6, 0xD2B7, 0x66F3, + 0xD2B8, 0x814B, 0xD2B9, 0x591C, 0xD2BA, 0x6DB2, 0xD2BB, 0x4E00, + 0xD2BC, 0x58F9, 0xD2BD, 0x533B, 0xD2BE, 0x63D6, 0xD2BF, 0x94F1, + 0xD2C0, 0x4F9D, 0xD2C1, 0x4F0A, 0xD2C2, 0x8863, 0xD2C3, 0x9890, + 0xD2C4, 0x5937, 0xD2C5, 0x9057, 0xD2C6, 0x79FB, 0xD2C7, 0x4EEA, + 0xD2C8, 0x80F0, 0xD2C9, 0x7591, 0xD2CA, 0x6C82, 0xD2CB, 0x5B9C, + 0xD2CC, 0x59E8, 0xD2CD, 0x5F5D, 0xD2CE, 0x6905, 0xD2CF, 0x8681, + 0xD2D0, 0x501A, 0xD2D1, 0x5DF2, 0xD2D2, 0x4E59, 0xD2D3, 0x77E3, + 0xD2D4, 0x4EE5, 0xD2D5, 0x827A, 0xD2D6, 0x6291, 0xD2D7, 0x6613, + 0xD2D8, 0x9091, 0xD2D9, 0x5C79, 0xD2DA, 0x4EBF, 0xD2DB, 0x5F79, + 0xD2DC, 0x81C6, 0xD2DD, 0x9038, 0xD2DE, 0x8084, 0xD2DF, 0x75AB, + 0xD2E0, 0x4EA6, 0xD2E1, 0x88D4, 0xD2E2, 0x610F, 0xD2E3, 0x6BC5, + 0xD2E4, 0x5FC6, 0xD2E5, 0x4E49, 0xD2E6, 0x76CA, 0xD2E7, 0x6EA2, + 0xD2E8, 0x8BE3, 0xD2E9, 0x8BAE, 0xD2EA, 0x8C0A, 0xD2EB, 0x8BD1, + 0xD2EC, 0x5F02, 0xD2ED, 0x7FFC, 0xD2EE, 0x7FCC, 0xD2EF, 0x7ECE, + 0xD2F0, 0x8335, 0xD2F1, 0x836B, 0xD2F2, 0x56E0, 0xD2F3, 0x6BB7, + 0xD2F4, 0x97F3, 0xD2F5, 0x9634, 0xD2F6, 0x59FB, 0xD2F7, 0x541F, + 0xD2F8, 0x94F6, 0xD2F9, 0x6DEB, 0xD2FA, 0x5BC5, 0xD2FB, 0x996E, + 0xD2FC, 0x5C39, 0xD2FD, 0x5F15, 0xD2FE, 0x9690, 0xD340, 0x89A2, + 0xD341, 0x89A3, 0xD342, 0x89A4, 0xD343, 0x89A5, 0xD344, 0x89A6, + 0xD345, 0x89A7, 0xD346, 0x89A8, 0xD347, 0x89A9, 0xD348, 0x89AA, + 0xD349, 0x89AB, 0xD34A, 0x89AC, 0xD34B, 0x89AD, 0xD34C, 0x89AE, + 0xD34D, 0x89AF, 0xD34E, 0x89B0, 0xD34F, 0x89B1, 0xD350, 0x89B2, + 0xD351, 0x89B3, 0xD352, 0x89B4, 0xD353, 0x89B5, 0xD354, 0x89B6, + 0xD355, 0x89B7, 0xD356, 0x89B8, 0xD357, 0x89B9, 0xD358, 0x89BA, + 0xD359, 0x89BB, 0xD35A, 0x89BC, 0xD35B, 0x89BD, 0xD35C, 0x89BE, + 0xD35D, 0x89BF, 0xD35E, 0x89C0, 0xD35F, 0x89C3, 0xD360, 0x89CD, + 0xD361, 0x89D3, 0xD362, 0x89D4, 0xD363, 0x89D5, 0xD364, 0x89D7, + 0xD365, 0x89D8, 0xD366, 0x89D9, 0xD367, 0x89DB, 0xD368, 0x89DD, + 0xD369, 0x89DF, 0xD36A, 0x89E0, 0xD36B, 0x89E1, 0xD36C, 0x89E2, + 0xD36D, 0x89E4, 0xD36E, 0x89E7, 0xD36F, 0x89E8, 0xD370, 0x89E9, + 0xD371, 0x89EA, 0xD372, 0x89EC, 0xD373, 0x89ED, 0xD374, 0x89EE, + 0xD375, 0x89F0, 0xD376, 0x89F1, 0xD377, 0x89F2, 0xD378, 0x89F4, + 0xD379, 0x89F5, 0xD37A, 0x89F6, 0xD37B, 0x89F7, 0xD37C, 0x89F8, + 0xD37D, 0x89F9, 0xD37E, 0x89FA, 0xD380, 0x89FB, 0xD381, 0x89FC, + 0xD382, 0x89FD, 0xD383, 0x89FE, 0xD384, 0x89FF, 0xD385, 0x8A01, + 0xD386, 0x8A02, 0xD387, 0x8A03, 0xD388, 0x8A04, 0xD389, 0x8A05, + 0xD38A, 0x8A06, 0xD38B, 0x8A08, 0xD38C, 0x8A09, 0xD38D, 0x8A0A, + 0xD38E, 0x8A0B, 0xD38F, 0x8A0C, 0xD390, 0x8A0D, 0xD391, 0x8A0E, + 0xD392, 0x8A0F, 0xD393, 0x8A10, 0xD394, 0x8A11, 0xD395, 0x8A12, + 0xD396, 0x8A13, 0xD397, 0x8A14, 0xD398, 0x8A15, 0xD399, 0x8A16, + 0xD39A, 0x8A17, 0xD39B, 0x8A18, 0xD39C, 0x8A19, 0xD39D, 0x8A1A, + 0xD39E, 0x8A1B, 0xD39F, 0x8A1C, 0xD3A0, 0x8A1D, 0xD3A1, 0x5370, + 0xD3A2, 0x82F1, 0xD3A3, 0x6A31, 0xD3A4, 0x5A74, 0xD3A5, 0x9E70, + 0xD3A6, 0x5E94, 0xD3A7, 0x7F28, 0xD3A8, 0x83B9, 0xD3A9, 0x8424, + 0xD3AA, 0x8425, 0xD3AB, 0x8367, 0xD3AC, 0x8747, 0xD3AD, 0x8FCE, + 0xD3AE, 0x8D62, 0xD3AF, 0x76C8, 0xD3B0, 0x5F71, 0xD3B1, 0x9896, + 0xD3B2, 0x786C, 0xD3B3, 0x6620, 0xD3B4, 0x54DF, 0xD3B5, 0x62E5, + 0xD3B6, 0x4F63, 0xD3B7, 0x81C3, 0xD3B8, 0x75C8, 0xD3B9, 0x5EB8, + 0xD3BA, 0x96CD, 0xD3BB, 0x8E0A, 0xD3BC, 0x86F9, 0xD3BD, 0x548F, + 0xD3BE, 0x6CF3, 0xD3BF, 0x6D8C, 0xD3C0, 0x6C38, 0xD3C1, 0x607F, + 0xD3C2, 0x52C7, 0xD3C3, 0x7528, 0xD3C4, 0x5E7D, 0xD3C5, 0x4F18, + 0xD3C6, 0x60A0, 0xD3C7, 0x5FE7, 0xD3C8, 0x5C24, 0xD3C9, 0x7531, + 0xD3CA, 0x90AE, 0xD3CB, 0x94C0, 0xD3CC, 0x72B9, 0xD3CD, 0x6CB9, + 0xD3CE, 0x6E38, 0xD3CF, 0x9149, 0xD3D0, 0x6709, 0xD3D1, 0x53CB, + 0xD3D2, 0x53F3, 0xD3D3, 0x4F51, 0xD3D4, 0x91C9, 0xD3D5, 0x8BF1, + 0xD3D6, 0x53C8, 0xD3D7, 0x5E7C, 0xD3D8, 0x8FC2, 0xD3D9, 0x6DE4, + 0xD3DA, 0x4E8E, 0xD3DB, 0x76C2, 0xD3DC, 0x6986, 0xD3DD, 0x865E, + 0xD3DE, 0x611A, 0xD3DF, 0x8206, 0xD3E0, 0x4F59, 0xD3E1, 0x4FDE, + 0xD3E2, 0x903E, 0xD3E3, 0x9C7C, 0xD3E4, 0x6109, 0xD3E5, 0x6E1D, + 0xD3E6, 0x6E14, 0xD3E7, 0x9685, 0xD3E8, 0x4E88, 0xD3E9, 0x5A31, + 0xD3EA, 0x96E8, 0xD3EB, 0x4E0E, 0xD3EC, 0x5C7F, 0xD3ED, 0x79B9, + 0xD3EE, 0x5B87, 0xD3EF, 0x8BED, 0xD3F0, 0x7FBD, 0xD3F1, 0x7389, + 0xD3F2, 0x57DF, 0xD3F3, 0x828B, 0xD3F4, 0x90C1, 0xD3F5, 0x5401, + 0xD3F6, 0x9047, 0xD3F7, 0x55BB, 0xD3F8, 0x5CEA, 0xD3F9, 0x5FA1, + 0xD3FA, 0x6108, 0xD3FB, 0x6B32, 0xD3FC, 0x72F1, 0xD3FD, 0x80B2, + 0xD3FE, 0x8A89, 0xD440, 0x8A1E, 0xD441, 0x8A1F, 0xD442, 0x8A20, + 0xD443, 0x8A21, 0xD444, 0x8A22, 0xD445, 0x8A23, 0xD446, 0x8A24, + 0xD447, 0x8A25, 0xD448, 0x8A26, 0xD449, 0x8A27, 0xD44A, 0x8A28, + 0xD44B, 0x8A29, 0xD44C, 0x8A2A, 0xD44D, 0x8A2B, 0xD44E, 0x8A2C, + 0xD44F, 0x8A2D, 0xD450, 0x8A2E, 0xD451, 0x8A2F, 0xD452, 0x8A30, + 0xD453, 0x8A31, 0xD454, 0x8A32, 0xD455, 0x8A33, 0xD456, 0x8A34, + 0xD457, 0x8A35, 0xD458, 0x8A36, 0xD459, 0x8A37, 0xD45A, 0x8A38, + 0xD45B, 0x8A39, 0xD45C, 0x8A3A, 0xD45D, 0x8A3B, 0xD45E, 0x8A3C, + 0xD45F, 0x8A3D, 0xD460, 0x8A3F, 0xD461, 0x8A40, 0xD462, 0x8A41, + 0xD463, 0x8A42, 0xD464, 0x8A43, 0xD465, 0x8A44, 0xD466, 0x8A45, + 0xD467, 0x8A46, 0xD468, 0x8A47, 0xD469, 0x8A49, 0xD46A, 0x8A4A, + 0xD46B, 0x8A4B, 0xD46C, 0x8A4C, 0xD46D, 0x8A4D, 0xD46E, 0x8A4E, + 0xD46F, 0x8A4F, 0xD470, 0x8A50, 0xD471, 0x8A51, 0xD472, 0x8A52, + 0xD473, 0x8A53, 0xD474, 0x8A54, 0xD475, 0x8A55, 0xD476, 0x8A56, + 0xD477, 0x8A57, 0xD478, 0x8A58, 0xD479, 0x8A59, 0xD47A, 0x8A5A, + 0xD47B, 0x8A5B, 0xD47C, 0x8A5C, 0xD47D, 0x8A5D, 0xD47E, 0x8A5E, + 0xD480, 0x8A5F, 0xD481, 0x8A60, 0xD482, 0x8A61, 0xD483, 0x8A62, + 0xD484, 0x8A63, 0xD485, 0x8A64, 0xD486, 0x8A65, 0xD487, 0x8A66, + 0xD488, 0x8A67, 0xD489, 0x8A68, 0xD48A, 0x8A69, 0xD48B, 0x8A6A, + 0xD48C, 0x8A6B, 0xD48D, 0x8A6C, 0xD48E, 0x8A6D, 0xD48F, 0x8A6E, + 0xD490, 0x8A6F, 0xD491, 0x8A70, 0xD492, 0x8A71, 0xD493, 0x8A72, + 0xD494, 0x8A73, 0xD495, 0x8A74, 0xD496, 0x8A75, 0xD497, 0x8A76, + 0xD498, 0x8A77, 0xD499, 0x8A78, 0xD49A, 0x8A7A, 0xD49B, 0x8A7B, + 0xD49C, 0x8A7C, 0xD49D, 0x8A7D, 0xD49E, 0x8A7E, 0xD49F, 0x8A7F, + 0xD4A0, 0x8A80, 0xD4A1, 0x6D74, 0xD4A2, 0x5BD3, 0xD4A3, 0x88D5, + 0xD4A4, 0x9884, 0xD4A5, 0x8C6B, 0xD4A6, 0x9A6D, 0xD4A7, 0x9E33, + 0xD4A8, 0x6E0A, 0xD4A9, 0x51A4, 0xD4AA, 0x5143, 0xD4AB, 0x57A3, + 0xD4AC, 0x8881, 0xD4AD, 0x539F, 0xD4AE, 0x63F4, 0xD4AF, 0x8F95, + 0xD4B0, 0x56ED, 0xD4B1, 0x5458, 0xD4B2, 0x5706, 0xD4B3, 0x733F, + 0xD4B4, 0x6E90, 0xD4B5, 0x7F18, 0xD4B6, 0x8FDC, 0xD4B7, 0x82D1, + 0xD4B8, 0x613F, 0xD4B9, 0x6028, 0xD4BA, 0x9662, 0xD4BB, 0x66F0, + 0xD4BC, 0x7EA6, 0xD4BD, 0x8D8A, 0xD4BE, 0x8DC3, 0xD4BF, 0x94A5, + 0xD4C0, 0x5CB3, 0xD4C1, 0x7CA4, 0xD4C2, 0x6708, 0xD4C3, 0x60A6, + 0xD4C4, 0x9605, 0xD4C5, 0x8018, 0xD4C6, 0x4E91, 0xD4C7, 0x90E7, + 0xD4C8, 0x5300, 0xD4C9, 0x9668, 0xD4CA, 0x5141, 0xD4CB, 0x8FD0, + 0xD4CC, 0x8574, 0xD4CD, 0x915D, 0xD4CE, 0x6655, 0xD4CF, 0x97F5, + 0xD4D0, 0x5B55, 0xD4D1, 0x531D, 0xD4D2, 0x7838, 0xD4D3, 0x6742, + 0xD4D4, 0x683D, 0xD4D5, 0x54C9, 0xD4D6, 0x707E, 0xD4D7, 0x5BB0, + 0xD4D8, 0x8F7D, 0xD4D9, 0x518D, 0xD4DA, 0x5728, 0xD4DB, 0x54B1, + 0xD4DC, 0x6512, 0xD4DD, 0x6682, 0xD4DE, 0x8D5E, 0xD4DF, 0x8D43, + 0xD4E0, 0x810F, 0xD4E1, 0x846C, 0xD4E2, 0x906D, 0xD4E3, 0x7CDF, + 0xD4E4, 0x51FF, 0xD4E5, 0x85FB, 0xD4E6, 0x67A3, 0xD4E7, 0x65E9, + 0xD4E8, 0x6FA1, 0xD4E9, 0x86A4, 0xD4EA, 0x8E81, 0xD4EB, 0x566A, + 0xD4EC, 0x9020, 0xD4ED, 0x7682, 0xD4EE, 0x7076, 0xD4EF, 0x71E5, + 0xD4F0, 0x8D23, 0xD4F1, 0x62E9, 0xD4F2, 0x5219, 0xD4F3, 0x6CFD, + 0xD4F4, 0x8D3C, 0xD4F5, 0x600E, 0xD4F6, 0x589E, 0xD4F7, 0x618E, + 0xD4F8, 0x66FE, 0xD4F9, 0x8D60, 0xD4FA, 0x624E, 0xD4FB, 0x55B3, + 0xD4FC, 0x6E23, 0xD4FD, 0x672D, 0xD4FE, 0x8F67, 0xD540, 0x8A81, + 0xD541, 0x8A82, 0xD542, 0x8A83, 0xD543, 0x8A84, 0xD544, 0x8A85, + 0xD545, 0x8A86, 0xD546, 0x8A87, 0xD547, 0x8A88, 0xD548, 0x8A8B, + 0xD549, 0x8A8C, 0xD54A, 0x8A8D, 0xD54B, 0x8A8E, 0xD54C, 0x8A8F, + 0xD54D, 0x8A90, 0xD54E, 0x8A91, 0xD54F, 0x8A92, 0xD550, 0x8A94, + 0xD551, 0x8A95, 0xD552, 0x8A96, 0xD553, 0x8A97, 0xD554, 0x8A98, + 0xD555, 0x8A99, 0xD556, 0x8A9A, 0xD557, 0x8A9B, 0xD558, 0x8A9C, + 0xD559, 0x8A9D, 0xD55A, 0x8A9E, 0xD55B, 0x8A9F, 0xD55C, 0x8AA0, + 0xD55D, 0x8AA1, 0xD55E, 0x8AA2, 0xD55F, 0x8AA3, 0xD560, 0x8AA4, + 0xD561, 0x8AA5, 0xD562, 0x8AA6, 0xD563, 0x8AA7, 0xD564, 0x8AA8, + 0xD565, 0x8AA9, 0xD566, 0x8AAA, 0xD567, 0x8AAB, 0xD568, 0x8AAC, + 0xD569, 0x8AAD, 0xD56A, 0x8AAE, 0xD56B, 0x8AAF, 0xD56C, 0x8AB0, + 0xD56D, 0x8AB1, 0xD56E, 0x8AB2, 0xD56F, 0x8AB3, 0xD570, 0x8AB4, + 0xD571, 0x8AB5, 0xD572, 0x8AB6, 0xD573, 0x8AB7, 0xD574, 0x8AB8, + 0xD575, 0x8AB9, 0xD576, 0x8ABA, 0xD577, 0x8ABB, 0xD578, 0x8ABC, + 0xD579, 0x8ABD, 0xD57A, 0x8ABE, 0xD57B, 0x8ABF, 0xD57C, 0x8AC0, + 0xD57D, 0x8AC1, 0xD57E, 0x8AC2, 0xD580, 0x8AC3, 0xD581, 0x8AC4, + 0xD582, 0x8AC5, 0xD583, 0x8AC6, 0xD584, 0x8AC7, 0xD585, 0x8AC8, + 0xD586, 0x8AC9, 0xD587, 0x8ACA, 0xD588, 0x8ACB, 0xD589, 0x8ACC, + 0xD58A, 0x8ACD, 0xD58B, 0x8ACE, 0xD58C, 0x8ACF, 0xD58D, 0x8AD0, + 0xD58E, 0x8AD1, 0xD58F, 0x8AD2, 0xD590, 0x8AD3, 0xD591, 0x8AD4, + 0xD592, 0x8AD5, 0xD593, 0x8AD6, 0xD594, 0x8AD7, 0xD595, 0x8AD8, + 0xD596, 0x8AD9, 0xD597, 0x8ADA, 0xD598, 0x8ADB, 0xD599, 0x8ADC, + 0xD59A, 0x8ADD, 0xD59B, 0x8ADE, 0xD59C, 0x8ADF, 0xD59D, 0x8AE0, + 0xD59E, 0x8AE1, 0xD59F, 0x8AE2, 0xD5A0, 0x8AE3, 0xD5A1, 0x94E1, + 0xD5A2, 0x95F8, 0xD5A3, 0x7728, 0xD5A4, 0x6805, 0xD5A5, 0x69A8, + 0xD5A6, 0x548B, 0xD5A7, 0x4E4D, 0xD5A8, 0x70B8, 0xD5A9, 0x8BC8, + 0xD5AA, 0x6458, 0xD5AB, 0x658B, 0xD5AC, 0x5B85, 0xD5AD, 0x7A84, + 0xD5AE, 0x503A, 0xD5AF, 0x5BE8, 0xD5B0, 0x77BB, 0xD5B1, 0x6BE1, + 0xD5B2, 0x8A79, 0xD5B3, 0x7C98, 0xD5B4, 0x6CBE, 0xD5B5, 0x76CF, + 0xD5B6, 0x65A9, 0xD5B7, 0x8F97, 0xD5B8, 0x5D2D, 0xD5B9, 0x5C55, + 0xD5BA, 0x8638, 0xD5BB, 0x6808, 0xD5BC, 0x5360, 0xD5BD, 0x6218, + 0xD5BE, 0x7AD9, 0xD5BF, 0x6E5B, 0xD5C0, 0x7EFD, 0xD5C1, 0x6A1F, + 0xD5C2, 0x7AE0, 0xD5C3, 0x5F70, 0xD5C4, 0x6F33, 0xD5C5, 0x5F20, + 0xD5C6, 0x638C, 0xD5C7, 0x6DA8, 0xD5C8, 0x6756, 0xD5C9, 0x4E08, + 0xD5CA, 0x5E10, 0xD5CB, 0x8D26, 0xD5CC, 0x4ED7, 0xD5CD, 0x80C0, + 0xD5CE, 0x7634, 0xD5CF, 0x969C, 0xD5D0, 0x62DB, 0xD5D1, 0x662D, + 0xD5D2, 0x627E, 0xD5D3, 0x6CBC, 0xD5D4, 0x8D75, 0xD5D5, 0x7167, + 0xD5D6, 0x7F69, 0xD5D7, 0x5146, 0xD5D8, 0x8087, 0xD5D9, 0x53EC, + 0xD5DA, 0x906E, 0xD5DB, 0x6298, 0xD5DC, 0x54F2, 0xD5DD, 0x86F0, + 0xD5DE, 0x8F99, 0xD5DF, 0x8005, 0xD5E0, 0x9517, 0xD5E1, 0x8517, + 0xD5E2, 0x8FD9, 0xD5E3, 0x6D59, 0xD5E4, 0x73CD, 0xD5E5, 0x659F, + 0xD5E6, 0x771F, 0xD5E7, 0x7504, 0xD5E8, 0x7827, 0xD5E9, 0x81FB, + 0xD5EA, 0x8D1E, 0xD5EB, 0x9488, 0xD5EC, 0x4FA6, 0xD5ED, 0x6795, + 0xD5EE, 0x75B9, 0xD5EF, 0x8BCA, 0xD5F0, 0x9707, 0xD5F1, 0x632F, + 0xD5F2, 0x9547, 0xD5F3, 0x9635, 0xD5F4, 0x84B8, 0xD5F5, 0x6323, + 0xD5F6, 0x7741, 0xD5F7, 0x5F81, 0xD5F8, 0x72F0, 0xD5F9, 0x4E89, + 0xD5FA, 0x6014, 0xD5FB, 0x6574, 0xD5FC, 0x62EF, 0xD5FD, 0x6B63, + 0xD5FE, 0x653F, 0xD640, 0x8AE4, 0xD641, 0x8AE5, 0xD642, 0x8AE6, + 0xD643, 0x8AE7, 0xD644, 0x8AE8, 0xD645, 0x8AE9, 0xD646, 0x8AEA, + 0xD647, 0x8AEB, 0xD648, 0x8AEC, 0xD649, 0x8AED, 0xD64A, 0x8AEE, + 0xD64B, 0x8AEF, 0xD64C, 0x8AF0, 0xD64D, 0x8AF1, 0xD64E, 0x8AF2, + 0xD64F, 0x8AF3, 0xD650, 0x8AF4, 0xD651, 0x8AF5, 0xD652, 0x8AF6, + 0xD653, 0x8AF7, 0xD654, 0x8AF8, 0xD655, 0x8AF9, 0xD656, 0x8AFA, + 0xD657, 0x8AFB, 0xD658, 0x8AFC, 0xD659, 0x8AFD, 0xD65A, 0x8AFE, + 0xD65B, 0x8AFF, 0xD65C, 0x8B00, 0xD65D, 0x8B01, 0xD65E, 0x8B02, + 0xD65F, 0x8B03, 0xD660, 0x8B04, 0xD661, 0x8B05, 0xD662, 0x8B06, + 0xD663, 0x8B08, 0xD664, 0x8B09, 0xD665, 0x8B0A, 0xD666, 0x8B0B, + 0xD667, 0x8B0C, 0xD668, 0x8B0D, 0xD669, 0x8B0E, 0xD66A, 0x8B0F, + 0xD66B, 0x8B10, 0xD66C, 0x8B11, 0xD66D, 0x8B12, 0xD66E, 0x8B13, + 0xD66F, 0x8B14, 0xD670, 0x8B15, 0xD671, 0x8B16, 0xD672, 0x8B17, + 0xD673, 0x8B18, 0xD674, 0x8B19, 0xD675, 0x8B1A, 0xD676, 0x8B1B, + 0xD677, 0x8B1C, 0xD678, 0x8B1D, 0xD679, 0x8B1E, 0xD67A, 0x8B1F, + 0xD67B, 0x8B20, 0xD67C, 0x8B21, 0xD67D, 0x8B22, 0xD67E, 0x8B23, + 0xD680, 0x8B24, 0xD681, 0x8B25, 0xD682, 0x8B27, 0xD683, 0x8B28, + 0xD684, 0x8B29, 0xD685, 0x8B2A, 0xD686, 0x8B2B, 0xD687, 0x8B2C, + 0xD688, 0x8B2D, 0xD689, 0x8B2E, 0xD68A, 0x8B2F, 0xD68B, 0x8B30, + 0xD68C, 0x8B31, 0xD68D, 0x8B32, 0xD68E, 0x8B33, 0xD68F, 0x8B34, + 0xD690, 0x8B35, 0xD691, 0x8B36, 0xD692, 0x8B37, 0xD693, 0x8B38, + 0xD694, 0x8B39, 0xD695, 0x8B3A, 0xD696, 0x8B3B, 0xD697, 0x8B3C, + 0xD698, 0x8B3D, 0xD699, 0x8B3E, 0xD69A, 0x8B3F, 0xD69B, 0x8B40, + 0xD69C, 0x8B41, 0xD69D, 0x8B42, 0xD69E, 0x8B43, 0xD69F, 0x8B44, + 0xD6A0, 0x8B45, 0xD6A1, 0x5E27, 0xD6A2, 0x75C7, 0xD6A3, 0x90D1, + 0xD6A4, 0x8BC1, 0xD6A5, 0x829D, 0xD6A6, 0x679D, 0xD6A7, 0x652F, + 0xD6A8, 0x5431, 0xD6A9, 0x8718, 0xD6AA, 0x77E5, 0xD6AB, 0x80A2, + 0xD6AC, 0x8102, 0xD6AD, 0x6C41, 0xD6AE, 0x4E4B, 0xD6AF, 0x7EC7, + 0xD6B0, 0x804C, 0xD6B1, 0x76F4, 0xD6B2, 0x690D, 0xD6B3, 0x6B96, + 0xD6B4, 0x6267, 0xD6B5, 0x503C, 0xD6B6, 0x4F84, 0xD6B7, 0x5740, + 0xD6B8, 0x6307, 0xD6B9, 0x6B62, 0xD6BA, 0x8DBE, 0xD6BB, 0x53EA, + 0xD6BC, 0x65E8, 0xD6BD, 0x7EB8, 0xD6BE, 0x5FD7, 0xD6BF, 0x631A, + 0xD6C0, 0x63B7, 0xD6C1, 0x81F3, 0xD6C2, 0x81F4, 0xD6C3, 0x7F6E, + 0xD6C4, 0x5E1C, 0xD6C5, 0x5CD9, 0xD6C6, 0x5236, 0xD6C7, 0x667A, + 0xD6C8, 0x79E9, 0xD6C9, 0x7A1A, 0xD6CA, 0x8D28, 0xD6CB, 0x7099, + 0xD6CC, 0x75D4, 0xD6CD, 0x6EDE, 0xD6CE, 0x6CBB, 0xD6CF, 0x7A92, + 0xD6D0, 0x4E2D, 0xD6D1, 0x76C5, 0xD6D2, 0x5FE0, 0xD6D3, 0x949F, + 0xD6D4, 0x8877, 0xD6D5, 0x7EC8, 0xD6D6, 0x79CD, 0xD6D7, 0x80BF, + 0xD6D8, 0x91CD, 0xD6D9, 0x4EF2, 0xD6DA, 0x4F17, 0xD6DB, 0x821F, + 0xD6DC, 0x5468, 0xD6DD, 0x5DDE, 0xD6DE, 0x6D32, 0xD6DF, 0x8BCC, + 0xD6E0, 0x7CA5, 0xD6E1, 0x8F74, 0xD6E2, 0x8098, 0xD6E3, 0x5E1A, + 0xD6E4, 0x5492, 0xD6E5, 0x76B1, 0xD6E6, 0x5B99, 0xD6E7, 0x663C, + 0xD6E8, 0x9AA4, 0xD6E9, 0x73E0, 0xD6EA, 0x682A, 0xD6EB, 0x86DB, + 0xD6EC, 0x6731, 0xD6ED, 0x732A, 0xD6EE, 0x8BF8, 0xD6EF, 0x8BDB, + 0xD6F0, 0x9010, 0xD6F1, 0x7AF9, 0xD6F2, 0x70DB, 0xD6F3, 0x716E, + 0xD6F4, 0x62C4, 0xD6F5, 0x77A9, 0xD6F6, 0x5631, 0xD6F7, 0x4E3B, + 0xD6F8, 0x8457, 0xD6F9, 0x67F1, 0xD6FA, 0x52A9, 0xD6FB, 0x86C0, + 0xD6FC, 0x8D2E, 0xD6FD, 0x94F8, 0xD6FE, 0x7B51, 0xD740, 0x8B46, + 0xD741, 0x8B47, 0xD742, 0x8B48, 0xD743, 0x8B49, 0xD744, 0x8B4A, + 0xD745, 0x8B4B, 0xD746, 0x8B4C, 0xD747, 0x8B4D, 0xD748, 0x8B4E, + 0xD749, 0x8B4F, 0xD74A, 0x8B50, 0xD74B, 0x8B51, 0xD74C, 0x8B52, + 0xD74D, 0x8B53, 0xD74E, 0x8B54, 0xD74F, 0x8B55, 0xD750, 0x8B56, + 0xD751, 0x8B57, 0xD752, 0x8B58, 0xD753, 0x8B59, 0xD754, 0x8B5A, + 0xD755, 0x8B5B, 0xD756, 0x8B5C, 0xD757, 0x8B5D, 0xD758, 0x8B5E, + 0xD759, 0x8B5F, 0xD75A, 0x8B60, 0xD75B, 0x8B61, 0xD75C, 0x8B62, + 0xD75D, 0x8B63, 0xD75E, 0x8B64, 0xD75F, 0x8B65, 0xD760, 0x8B67, + 0xD761, 0x8B68, 0xD762, 0x8B69, 0xD763, 0x8B6A, 0xD764, 0x8B6B, + 0xD765, 0x8B6D, 0xD766, 0x8B6E, 0xD767, 0x8B6F, 0xD768, 0x8B70, + 0xD769, 0x8B71, 0xD76A, 0x8B72, 0xD76B, 0x8B73, 0xD76C, 0x8B74, + 0xD76D, 0x8B75, 0xD76E, 0x8B76, 0xD76F, 0x8B77, 0xD770, 0x8B78, + 0xD771, 0x8B79, 0xD772, 0x8B7A, 0xD773, 0x8B7B, 0xD774, 0x8B7C, + 0xD775, 0x8B7D, 0xD776, 0x8B7E, 0xD777, 0x8B7F, 0xD778, 0x8B80, + 0xD779, 0x8B81, 0xD77A, 0x8B82, 0xD77B, 0x8B83, 0xD77C, 0x8B84, + 0xD77D, 0x8B85, 0xD77E, 0x8B86, 0xD780, 0x8B87, 0xD781, 0x8B88, + 0xD782, 0x8B89, 0xD783, 0x8B8A, 0xD784, 0x8B8B, 0xD785, 0x8B8C, + 0xD786, 0x8B8D, 0xD787, 0x8B8E, 0xD788, 0x8B8F, 0xD789, 0x8B90, + 0xD78A, 0x8B91, 0xD78B, 0x8B92, 0xD78C, 0x8B93, 0xD78D, 0x8B94, + 0xD78E, 0x8B95, 0xD78F, 0x8B96, 0xD790, 0x8B97, 0xD791, 0x8B98, + 0xD792, 0x8B99, 0xD793, 0x8B9A, 0xD794, 0x8B9B, 0xD795, 0x8B9C, + 0xD796, 0x8B9D, 0xD797, 0x8B9E, 0xD798, 0x8B9F, 0xD799, 0x8BAC, + 0xD79A, 0x8BB1, 0xD79B, 0x8BBB, 0xD79C, 0x8BC7, 0xD79D, 0x8BD0, + 0xD79E, 0x8BEA, 0xD79F, 0x8C09, 0xD7A0, 0x8C1E, 0xD7A1, 0x4F4F, + 0xD7A2, 0x6CE8, 0xD7A3, 0x795D, 0xD7A4, 0x9A7B, 0xD7A5, 0x6293, + 0xD7A6, 0x722A, 0xD7A7, 0x62FD, 0xD7A8, 0x4E13, 0xD7A9, 0x7816, + 0xD7AA, 0x8F6C, 0xD7AB, 0x64B0, 0xD7AC, 0x8D5A, 0xD7AD, 0x7BC6, + 0xD7AE, 0x6869, 0xD7AF, 0x5E84, 0xD7B0, 0x88C5, 0xD7B1, 0x5986, + 0xD7B2, 0x649E, 0xD7B3, 0x58EE, 0xD7B4, 0x72B6, 0xD7B5, 0x690E, + 0xD7B6, 0x9525, 0xD7B7, 0x8FFD, 0xD7B8, 0x8D58, 0xD7B9, 0x5760, + 0xD7BA, 0x7F00, 0xD7BB, 0x8C06, 0xD7BC, 0x51C6, 0xD7BD, 0x6349, + 0xD7BE, 0x62D9, 0xD7BF, 0x5353, 0xD7C0, 0x684C, 0xD7C1, 0x7422, + 0xD7C2, 0x8301, 0xD7C3, 0x914C, 0xD7C4, 0x5544, 0xD7C5, 0x7740, + 0xD7C6, 0x707C, 0xD7C7, 0x6D4A, 0xD7C8, 0x5179, 0xD7C9, 0x54A8, + 0xD7CA, 0x8D44, 0xD7CB, 0x59FF, 0xD7CC, 0x6ECB, 0xD7CD, 0x6DC4, + 0xD7CE, 0x5B5C, 0xD7CF, 0x7D2B, 0xD7D0, 0x4ED4, 0xD7D1, 0x7C7D, + 0xD7D2, 0x6ED3, 0xD7D3, 0x5B50, 0xD7D4, 0x81EA, 0xD7D5, 0x6E0D, + 0xD7D6, 0x5B57, 0xD7D7, 0x9B03, 0xD7D8, 0x68D5, 0xD7D9, 0x8E2A, + 0xD7DA, 0x5B97, 0xD7DB, 0x7EFC, 0xD7DC, 0x603B, 0xD7DD, 0x7EB5, + 0xD7DE, 0x90B9, 0xD7DF, 0x8D70, 0xD7E0, 0x594F, 0xD7E1, 0x63CD, + 0xD7E2, 0x79DF, 0xD7E3, 0x8DB3, 0xD7E4, 0x5352, 0xD7E5, 0x65CF, + 0xD7E6, 0x7956, 0xD7E7, 0x8BC5, 0xD7E8, 0x963B, 0xD7E9, 0x7EC4, + 0xD7EA, 0x94BB, 0xD7EB, 0x7E82, 0xD7EC, 0x5634, 0xD7ED, 0x9189, + 0xD7EE, 0x6700, 0xD7EF, 0x7F6A, 0xD7F0, 0x5C0A, 0xD7F1, 0x9075, + 0xD7F2, 0x6628, 0xD7F3, 0x5DE6, 0xD7F4, 0x4F50, 0xD7F5, 0x67DE, + 0xD7F6, 0x505A, 0xD7F7, 0x4F5C, 0xD7F8, 0x5750, 0xD7F9, 0x5EA7, + 0xD840, 0x8C38, 0xD841, 0x8C39, 0xD842, 0x8C3A, 0xD843, 0x8C3B, + 0xD844, 0x8C3C, 0xD845, 0x8C3D, 0xD846, 0x8C3E, 0xD847, 0x8C3F, + 0xD848, 0x8C40, 0xD849, 0x8C42, 0xD84A, 0x8C43, 0xD84B, 0x8C44, + 0xD84C, 0x8C45, 0xD84D, 0x8C48, 0xD84E, 0x8C4A, 0xD84F, 0x8C4B, + 0xD850, 0x8C4D, 0xD851, 0x8C4E, 0xD852, 0x8C4F, 0xD853, 0x8C50, + 0xD854, 0x8C51, 0xD855, 0x8C52, 0xD856, 0x8C53, 0xD857, 0x8C54, + 0xD858, 0x8C56, 0xD859, 0x8C57, 0xD85A, 0x8C58, 0xD85B, 0x8C59, + 0xD85C, 0x8C5B, 0xD85D, 0x8C5C, 0xD85E, 0x8C5D, 0xD85F, 0x8C5E, + 0xD860, 0x8C5F, 0xD861, 0x8C60, 0xD862, 0x8C63, 0xD863, 0x8C64, + 0xD864, 0x8C65, 0xD865, 0x8C66, 0xD866, 0x8C67, 0xD867, 0x8C68, + 0xD868, 0x8C69, 0xD869, 0x8C6C, 0xD86A, 0x8C6D, 0xD86B, 0x8C6E, + 0xD86C, 0x8C6F, 0xD86D, 0x8C70, 0xD86E, 0x8C71, 0xD86F, 0x8C72, + 0xD870, 0x8C74, 0xD871, 0x8C75, 0xD872, 0x8C76, 0xD873, 0x8C77, + 0xD874, 0x8C7B, 0xD875, 0x8C7C, 0xD876, 0x8C7D, 0xD877, 0x8C7E, + 0xD878, 0x8C7F, 0xD879, 0x8C80, 0xD87A, 0x8C81, 0xD87B, 0x8C83, + 0xD87C, 0x8C84, 0xD87D, 0x8C86, 0xD87E, 0x8C87, 0xD880, 0x8C88, + 0xD881, 0x8C8B, 0xD882, 0x8C8D, 0xD883, 0x8C8E, 0xD884, 0x8C8F, + 0xD885, 0x8C90, 0xD886, 0x8C91, 0xD887, 0x8C92, 0xD888, 0x8C93, + 0xD889, 0x8C95, 0xD88A, 0x8C96, 0xD88B, 0x8C97, 0xD88C, 0x8C99, + 0xD88D, 0x8C9A, 0xD88E, 0x8C9B, 0xD88F, 0x8C9C, 0xD890, 0x8C9D, + 0xD891, 0x8C9E, 0xD892, 0x8C9F, 0xD893, 0x8CA0, 0xD894, 0x8CA1, + 0xD895, 0x8CA2, 0xD896, 0x8CA3, 0xD897, 0x8CA4, 0xD898, 0x8CA5, + 0xD899, 0x8CA6, 0xD89A, 0x8CA7, 0xD89B, 0x8CA8, 0xD89C, 0x8CA9, + 0xD89D, 0x8CAA, 0xD89E, 0x8CAB, 0xD89F, 0x8CAC, 0xD8A0, 0x8CAD, + 0xD8A1, 0x4E8D, 0xD8A2, 0x4E0C, 0xD8A3, 0x5140, 0xD8A4, 0x4E10, + 0xD8A5, 0x5EFF, 0xD8A6, 0x5345, 0xD8A7, 0x4E15, 0xD8A8, 0x4E98, + 0xD8A9, 0x4E1E, 0xD8AA, 0x9B32, 0xD8AB, 0x5B6C, 0xD8AC, 0x5669, + 0xD8AD, 0x4E28, 0xD8AE, 0x79BA, 0xD8AF, 0x4E3F, 0xD8B0, 0x5315, + 0xD8B1, 0x4E47, 0xD8B2, 0x592D, 0xD8B3, 0x723B, 0xD8B4, 0x536E, + 0xD8B5, 0x6C10, 0xD8B6, 0x56DF, 0xD8B7, 0x80E4, 0xD8B8, 0x9997, + 0xD8B9, 0x6BD3, 0xD8BA, 0x777E, 0xD8BB, 0x9F17, 0xD8BC, 0x4E36, + 0xD8BD, 0x4E9F, 0xD8BE, 0x9F10, 0xD8BF, 0x4E5C, 0xD8C0, 0x4E69, + 0xD8C1, 0x4E93, 0xD8C2, 0x8288, 0xD8C3, 0x5B5B, 0xD8C4, 0x556C, + 0xD8C5, 0x560F, 0xD8C6, 0x4EC4, 0xD8C7, 0x538D, 0xD8C8, 0x539D, + 0xD8C9, 0x53A3, 0xD8CA, 0x53A5, 0xD8CB, 0x53AE, 0xD8CC, 0x9765, + 0xD8CD, 0x8D5D, 0xD8CE, 0x531A, 0xD8CF, 0x53F5, 0xD8D0, 0x5326, + 0xD8D1, 0x532E, 0xD8D2, 0x533E, 0xD8D3, 0x8D5C, 0xD8D4, 0x5366, + 0xD8D5, 0x5363, 0xD8D6, 0x5202, 0xD8D7, 0x5208, 0xD8D8, 0x520E, + 0xD8D9, 0x522D, 0xD8DA, 0x5233, 0xD8DB, 0x523F, 0xD8DC, 0x5240, + 0xD8DD, 0x524C, 0xD8DE, 0x525E, 0xD8DF, 0x5261, 0xD8E0, 0x525C, + 0xD8E1, 0x84AF, 0xD8E2, 0x527D, 0xD8E3, 0x5282, 0xD8E4, 0x5281, + 0xD8E5, 0x5290, 0xD8E6, 0x5293, 0xD8E7, 0x5182, 0xD8E8, 0x7F54, + 0xD8E9, 0x4EBB, 0xD8EA, 0x4EC3, 0xD8EB, 0x4EC9, 0xD8EC, 0x4EC2, + 0xD8ED, 0x4EE8, 0xD8EE, 0x4EE1, 0xD8EF, 0x4EEB, 0xD8F0, 0x4EDE, + 0xD8F1, 0x4F1B, 0xD8F2, 0x4EF3, 0xD8F3, 0x4F22, 0xD8F4, 0x4F64, + 0xD8F5, 0x4EF5, 0xD8F6, 0x4F25, 0xD8F7, 0x4F27, 0xD8F8, 0x4F09, + 0xD8F9, 0x4F2B, 0xD8FA, 0x4F5E, 0xD8FB, 0x4F67, 0xD8FC, 0x6538, + 0xD8FD, 0x4F5A, 0xD8FE, 0x4F5D, 0xD940, 0x8CAE, 0xD941, 0x8CAF, + 0xD942, 0x8CB0, 0xD943, 0x8CB1, 0xD944, 0x8CB2, 0xD945, 0x8CB3, + 0xD946, 0x8CB4, 0xD947, 0x8CB5, 0xD948, 0x8CB6, 0xD949, 0x8CB7, + 0xD94A, 0x8CB8, 0xD94B, 0x8CB9, 0xD94C, 0x8CBA, 0xD94D, 0x8CBB, + 0xD94E, 0x8CBC, 0xD94F, 0x8CBD, 0xD950, 0x8CBE, 0xD951, 0x8CBF, + 0xD952, 0x8CC0, 0xD953, 0x8CC1, 0xD954, 0x8CC2, 0xD955, 0x8CC3, + 0xD956, 0x8CC4, 0xD957, 0x8CC5, 0xD958, 0x8CC6, 0xD959, 0x8CC7, + 0xD95A, 0x8CC8, 0xD95B, 0x8CC9, 0xD95C, 0x8CCA, 0xD95D, 0x8CCB, + 0xD95E, 0x8CCC, 0xD95F, 0x8CCD, 0xD960, 0x8CCE, 0xD961, 0x8CCF, + 0xD962, 0x8CD0, 0xD963, 0x8CD1, 0xD964, 0x8CD2, 0xD965, 0x8CD3, + 0xD966, 0x8CD4, 0xD967, 0x8CD5, 0xD968, 0x8CD6, 0xD969, 0x8CD7, + 0xD96A, 0x8CD8, 0xD96B, 0x8CD9, 0xD96C, 0x8CDA, 0xD96D, 0x8CDB, + 0xD96E, 0x8CDC, 0xD96F, 0x8CDD, 0xD970, 0x8CDE, 0xD971, 0x8CDF, + 0xD972, 0x8CE0, 0xD973, 0x8CE1, 0xD974, 0x8CE2, 0xD975, 0x8CE3, + 0xD976, 0x8CE4, 0xD977, 0x8CE5, 0xD978, 0x8CE6, 0xD979, 0x8CE7, + 0xD97A, 0x8CE8, 0xD97B, 0x8CE9, 0xD97C, 0x8CEA, 0xD97D, 0x8CEB, + 0xD97E, 0x8CEC, 0xD980, 0x8CED, 0xD981, 0x8CEE, 0xD982, 0x8CEF, + 0xD983, 0x8CF0, 0xD984, 0x8CF1, 0xD985, 0x8CF2, 0xD986, 0x8CF3, + 0xD987, 0x8CF4, 0xD988, 0x8CF5, 0xD989, 0x8CF6, 0xD98A, 0x8CF7, + 0xD98B, 0x8CF8, 0xD98C, 0x8CF9, 0xD98D, 0x8CFA, 0xD98E, 0x8CFB, + 0xD98F, 0x8CFC, 0xD990, 0x8CFD, 0xD991, 0x8CFE, 0xD992, 0x8CFF, + 0xD993, 0x8D00, 0xD994, 0x8D01, 0xD995, 0x8D02, 0xD996, 0x8D03, + 0xD997, 0x8D04, 0xD998, 0x8D05, 0xD999, 0x8D06, 0xD99A, 0x8D07, + 0xD99B, 0x8D08, 0xD99C, 0x8D09, 0xD99D, 0x8D0A, 0xD99E, 0x8D0B, + 0xD99F, 0x8D0C, 0xD9A0, 0x8D0D, 0xD9A1, 0x4F5F, 0xD9A2, 0x4F57, + 0xD9A3, 0x4F32, 0xD9A4, 0x4F3D, 0xD9A5, 0x4F76, 0xD9A6, 0x4F74, + 0xD9A7, 0x4F91, 0xD9A8, 0x4F89, 0xD9A9, 0x4F83, 0xD9AA, 0x4F8F, + 0xD9AB, 0x4F7E, 0xD9AC, 0x4F7B, 0xD9AD, 0x4FAA, 0xD9AE, 0x4F7C, + 0xD9AF, 0x4FAC, 0xD9B0, 0x4F94, 0xD9B1, 0x4FE6, 0xD9B2, 0x4FE8, + 0xD9B3, 0x4FEA, 0xD9B4, 0x4FC5, 0xD9B5, 0x4FDA, 0xD9B6, 0x4FE3, + 0xD9B7, 0x4FDC, 0xD9B8, 0x4FD1, 0xD9B9, 0x4FDF, 0xD9BA, 0x4FF8, + 0xD9BB, 0x5029, 0xD9BC, 0x504C, 0xD9BD, 0x4FF3, 0xD9BE, 0x502C, + 0xD9BF, 0x500F, 0xD9C0, 0x502E, 0xD9C1, 0x502D, 0xD9C2, 0x4FFE, + 0xD9C3, 0x501C, 0xD9C4, 0x500C, 0xD9C5, 0x5025, 0xD9C6, 0x5028, + 0xD9C7, 0x507E, 0xD9C8, 0x5043, 0xD9C9, 0x5055, 0xD9CA, 0x5048, + 0xD9CB, 0x504E, 0xD9CC, 0x506C, 0xD9CD, 0x507B, 0xD9CE, 0x50A5, + 0xD9CF, 0x50A7, 0xD9D0, 0x50A9, 0xD9D1, 0x50BA, 0xD9D2, 0x50D6, + 0xD9D3, 0x5106, 0xD9D4, 0x50ED, 0xD9D5, 0x50EC, 0xD9D6, 0x50E6, + 0xD9D7, 0x50EE, 0xD9D8, 0x5107, 0xD9D9, 0x510B, 0xD9DA, 0x4EDD, + 0xD9DB, 0x6C3D, 0xD9DC, 0x4F58, 0xD9DD, 0x4F65, 0xD9DE, 0x4FCE, + 0xD9DF, 0x9FA0, 0xD9E0, 0x6C46, 0xD9E1, 0x7C74, 0xD9E2, 0x516E, + 0xD9E3, 0x5DFD, 0xD9E4, 0x9EC9, 0xD9E5, 0x9998, 0xD9E6, 0x5181, + 0xD9E7, 0x5914, 0xD9E8, 0x52F9, 0xD9E9, 0x530D, 0xD9EA, 0x8A07, + 0xD9EB, 0x5310, 0xD9EC, 0x51EB, 0xD9ED, 0x5919, 0xD9EE, 0x5155, + 0xD9EF, 0x4EA0, 0xD9F0, 0x5156, 0xD9F1, 0x4EB3, 0xD9F2, 0x886E, + 0xD9F3, 0x88A4, 0xD9F4, 0x4EB5, 0xD9F5, 0x8114, 0xD9F6, 0x88D2, + 0xD9F7, 0x7980, 0xD9F8, 0x5B34, 0xD9F9, 0x8803, 0xD9FA, 0x7FB8, + 0xD9FB, 0x51AB, 0xD9FC, 0x51B1, 0xD9FD, 0x51BD, 0xD9FE, 0x51BC, + 0xDA40, 0x8D0E, 0xDA41, 0x8D0F, 0xDA42, 0x8D10, 0xDA43, 0x8D11, + 0xDA44, 0x8D12, 0xDA45, 0x8D13, 0xDA46, 0x8D14, 0xDA47, 0x8D15, + 0xDA48, 0x8D16, 0xDA49, 0x8D17, 0xDA4A, 0x8D18, 0xDA4B, 0x8D19, + 0xDA4C, 0x8D1A, 0xDA4D, 0x8D1B, 0xDA4E, 0x8D1C, 0xDA4F, 0x8D20, + 0xDA50, 0x8D51, 0xDA51, 0x8D52, 0xDA52, 0x8D57, 0xDA53, 0x8D5F, + 0xDA54, 0x8D65, 0xDA55, 0x8D68, 0xDA56, 0x8D69, 0xDA57, 0x8D6A, + 0xDA58, 0x8D6C, 0xDA59, 0x8D6E, 0xDA5A, 0x8D6F, 0xDA5B, 0x8D71, + 0xDA5C, 0x8D72, 0xDA5D, 0x8D78, 0xDA5E, 0x8D79, 0xDA5F, 0x8D7A, + 0xDA60, 0x8D7B, 0xDA61, 0x8D7C, 0xDA62, 0x8D7D, 0xDA63, 0x8D7E, + 0xDA64, 0x8D7F, 0xDA65, 0x8D80, 0xDA66, 0x8D82, 0xDA67, 0x8D83, + 0xDA68, 0x8D86, 0xDA69, 0x8D87, 0xDA6A, 0x8D88, 0xDA6B, 0x8D89, + 0xDA6C, 0x8D8C, 0xDA6D, 0x8D8D, 0xDA6E, 0x8D8E, 0xDA6F, 0x8D8F, + 0xDA70, 0x8D90, 0xDA71, 0x8D92, 0xDA72, 0x8D93, 0xDA73, 0x8D95, + 0xDA74, 0x8D96, 0xDA75, 0x8D97, 0xDA76, 0x8D98, 0xDA77, 0x8D99, + 0xDA78, 0x8D9A, 0xDA79, 0x8D9B, 0xDA7A, 0x8D9C, 0xDA7B, 0x8D9D, + 0xDA7C, 0x8D9E, 0xDA7D, 0x8DA0, 0xDA7E, 0x8DA1, 0xDA80, 0x8DA2, + 0xDA81, 0x8DA4, 0xDA82, 0x8DA5, 0xDA83, 0x8DA6, 0xDA84, 0x8DA7, + 0xDA85, 0x8DA8, 0xDA86, 0x8DA9, 0xDA87, 0x8DAA, 0xDA88, 0x8DAB, + 0xDA89, 0x8DAC, 0xDA8A, 0x8DAD, 0xDA8B, 0x8DAE, 0xDA8C, 0x8DAF, + 0xDA8D, 0x8DB0, 0xDA8E, 0x8DB2, 0xDA8F, 0x8DB6, 0xDA90, 0x8DB7, + 0xDA91, 0x8DB9, 0xDA92, 0x8DBB, 0xDA93, 0x8DBD, 0xDA94, 0x8DC0, + 0xDA95, 0x8DC1, 0xDA96, 0x8DC2, 0xDA97, 0x8DC5, 0xDA98, 0x8DC7, + 0xDA99, 0x8DC8, 0xDA9A, 0x8DC9, 0xDA9B, 0x8DCA, 0xDA9C, 0x8DCD, + 0xDA9D, 0x8DD0, 0xDA9E, 0x8DD2, 0xDA9F, 0x8DD3, 0xDAA0, 0x8DD4, + 0xDAA1, 0x51C7, 0xDAA2, 0x5196, 0xDAA3, 0x51A2, 0xDAA4, 0x51A5, + 0xDAA5, 0x8BA0, 0xDAA6, 0x8BA6, 0xDAA7, 0x8BA7, 0xDAA8, 0x8BAA, + 0xDAA9, 0x8BB4, 0xDAAA, 0x8BB5, 0xDAAB, 0x8BB7, 0xDAAC, 0x8BC2, + 0xDAAD, 0x8BC3, 0xDAAE, 0x8BCB, 0xDAAF, 0x8BCF, 0xDAB0, 0x8BCE, + 0xDAB1, 0x8BD2, 0xDAB2, 0x8BD3, 0xDAB3, 0x8BD4, 0xDAB4, 0x8BD6, + 0xDAB5, 0x8BD8, 0xDAB6, 0x8BD9, 0xDAB7, 0x8BDC, 0xDAB8, 0x8BDF, + 0xDAB9, 0x8BE0, 0xDABA, 0x8BE4, 0xDABB, 0x8BE8, 0xDABC, 0x8BE9, + 0xDABD, 0x8BEE, 0xDABE, 0x8BF0, 0xDABF, 0x8BF3, 0xDAC0, 0x8BF6, + 0xDAC1, 0x8BF9, 0xDAC2, 0x8BFC, 0xDAC3, 0x8BFF, 0xDAC4, 0x8C00, + 0xDAC5, 0x8C02, 0xDAC6, 0x8C04, 0xDAC7, 0x8C07, 0xDAC8, 0x8C0C, + 0xDAC9, 0x8C0F, 0xDACA, 0x8C11, 0xDACB, 0x8C12, 0xDACC, 0x8C14, + 0xDACD, 0x8C15, 0xDACE, 0x8C16, 0xDACF, 0x8C19, 0xDAD0, 0x8C1B, + 0xDAD1, 0x8C18, 0xDAD2, 0x8C1D, 0xDAD3, 0x8C1F, 0xDAD4, 0x8C20, + 0xDAD5, 0x8C21, 0xDAD6, 0x8C25, 0xDAD7, 0x8C27, 0xDAD8, 0x8C2A, + 0xDAD9, 0x8C2B, 0xDADA, 0x8C2E, 0xDADB, 0x8C2F, 0xDADC, 0x8C32, + 0xDADD, 0x8C33, 0xDADE, 0x8C35, 0xDADF, 0x8C36, 0xDAE0, 0x5369, + 0xDAE1, 0x537A, 0xDAE2, 0x961D, 0xDAE3, 0x9622, 0xDAE4, 0x9621, + 0xDAE5, 0x9631, 0xDAE6, 0x962A, 0xDAE7, 0x963D, 0xDAE8, 0x963C, + 0xDAE9, 0x9642, 0xDAEA, 0x9649, 0xDAEB, 0x9654, 0xDAEC, 0x965F, + 0xDAED, 0x9667, 0xDAEE, 0x966C, 0xDAEF, 0x9672, 0xDAF0, 0x9674, + 0xDAF1, 0x9688, 0xDAF2, 0x968D, 0xDAF3, 0x9697, 0xDAF4, 0x96B0, + 0xDAF5, 0x9097, 0xDAF6, 0x909B, 0xDAF7, 0x909D, 0xDAF8, 0x9099, + 0xDAF9, 0x90AC, 0xDAFA, 0x90A1, 0xDAFB, 0x90B4, 0xDAFC, 0x90B3, + 0xDAFD, 0x90B6, 0xDAFE, 0x90BA, 0xDB40, 0x8DD5, 0xDB41, 0x8DD8, + 0xDB42, 0x8DD9, 0xDB43, 0x8DDC, 0xDB44, 0x8DE0, 0xDB45, 0x8DE1, + 0xDB46, 0x8DE2, 0xDB47, 0x8DE5, 0xDB48, 0x8DE6, 0xDB49, 0x8DE7, + 0xDB4A, 0x8DE9, 0xDB4B, 0x8DED, 0xDB4C, 0x8DEE, 0xDB4D, 0x8DF0, + 0xDB4E, 0x8DF1, 0xDB4F, 0x8DF2, 0xDB50, 0x8DF4, 0xDB51, 0x8DF6, + 0xDB52, 0x8DFC, 0xDB53, 0x8DFE, 0xDB54, 0x8DFF, 0xDB55, 0x8E00, + 0xDB56, 0x8E01, 0xDB57, 0x8E02, 0xDB58, 0x8E03, 0xDB59, 0x8E04, + 0xDB5A, 0x8E06, 0xDB5B, 0x8E07, 0xDB5C, 0x8E08, 0xDB5D, 0x8E0B, + 0xDB5E, 0x8E0D, 0xDB5F, 0x8E0E, 0xDB60, 0x8E10, 0xDB61, 0x8E11, + 0xDB62, 0x8E12, 0xDB63, 0x8E13, 0xDB64, 0x8E15, 0xDB65, 0x8E16, + 0xDB66, 0x8E17, 0xDB67, 0x8E18, 0xDB68, 0x8E19, 0xDB69, 0x8E1A, + 0xDB6A, 0x8E1B, 0xDB6B, 0x8E1C, 0xDB6C, 0x8E20, 0xDB6D, 0x8E21, + 0xDB6E, 0x8E24, 0xDB6F, 0x8E25, 0xDB70, 0x8E26, 0xDB71, 0x8E27, + 0xDB72, 0x8E28, 0xDB73, 0x8E2B, 0xDB74, 0x8E2D, 0xDB75, 0x8E30, + 0xDB76, 0x8E32, 0xDB77, 0x8E33, 0xDB78, 0x8E34, 0xDB79, 0x8E36, + 0xDB7A, 0x8E37, 0xDB7B, 0x8E38, 0xDB7C, 0x8E3B, 0xDB7D, 0x8E3C, + 0xDB7E, 0x8E3E, 0xDB80, 0x8E3F, 0xDB81, 0x8E43, 0xDB82, 0x8E45, + 0xDB83, 0x8E46, 0xDB84, 0x8E4C, 0xDB85, 0x8E4D, 0xDB86, 0x8E4E, + 0xDB87, 0x8E4F, 0xDB88, 0x8E50, 0xDB89, 0x8E53, 0xDB8A, 0x8E54, + 0xDB8B, 0x8E55, 0xDB8C, 0x8E56, 0xDB8D, 0x8E57, 0xDB8E, 0x8E58, + 0xDB8F, 0x8E5A, 0xDB90, 0x8E5B, 0xDB91, 0x8E5C, 0xDB92, 0x8E5D, + 0xDB93, 0x8E5E, 0xDB94, 0x8E5F, 0xDB95, 0x8E60, 0xDB96, 0x8E61, + 0xDB97, 0x8E62, 0xDB98, 0x8E63, 0xDB99, 0x8E64, 0xDB9A, 0x8E65, + 0xDB9B, 0x8E67, 0xDB9C, 0x8E68, 0xDB9D, 0x8E6A, 0xDB9E, 0x8E6B, + 0xDB9F, 0x8E6E, 0xDBA0, 0x8E71, 0xDBA1, 0x90B8, 0xDBA2, 0x90B0, + 0xDBA3, 0x90CF, 0xDBA4, 0x90C5, 0xDBA5, 0x90BE, 0xDBA6, 0x90D0, + 0xDBA7, 0x90C4, 0xDBA8, 0x90C7, 0xDBA9, 0x90D3, 0xDBAA, 0x90E6, + 0xDBAB, 0x90E2, 0xDBAC, 0x90DC, 0xDBAD, 0x90D7, 0xDBAE, 0x90DB, + 0xDBAF, 0x90EB, 0xDBB0, 0x90EF, 0xDBB1, 0x90FE, 0xDBB2, 0x9104, + 0xDBB3, 0x9122, 0xDBB4, 0x911E, 0xDBB5, 0x9123, 0xDBB6, 0x9131, + 0xDBB7, 0x912F, 0xDBB8, 0x9139, 0xDBB9, 0x9143, 0xDBBA, 0x9146, + 0xDBBB, 0x520D, 0xDBBC, 0x5942, 0xDBBD, 0x52A2, 0xDBBE, 0x52AC, + 0xDBBF, 0x52AD, 0xDBC0, 0x52BE, 0xDBC1, 0x54FF, 0xDBC2, 0x52D0, + 0xDBC3, 0x52D6, 0xDBC4, 0x52F0, 0xDBC5, 0x53DF, 0xDBC6, 0x71EE, + 0xDBC7, 0x77CD, 0xDBC8, 0x5EF4, 0xDBC9, 0x51F5, 0xDBCA, 0x51FC, + 0xDBCB, 0x9B2F, 0xDBCC, 0x53B6, 0xDBCD, 0x5F01, 0xDBCE, 0x755A, + 0xDBCF, 0x5DEF, 0xDBD0, 0x574C, 0xDBD1, 0x57A9, 0xDBD2, 0x57A1, + 0xDBD3, 0x587E, 0xDBD4, 0x58BC, 0xDBD5, 0x58C5, 0xDBD6, 0x58D1, + 0xDBD7, 0x5729, 0xDBD8, 0x572C, 0xDBD9, 0x572A, 0xDBDA, 0x5733, + 0xDBDB, 0x5739, 0xDBDC, 0x572E, 0xDBDD, 0x572F, 0xDBDE, 0x575C, + 0xDBDF, 0x573B, 0xDBE0, 0x5742, 0xDBE1, 0x5769, 0xDBE2, 0x5785, + 0xDBE3, 0x576B, 0xDBE4, 0x5786, 0xDBE5, 0x577C, 0xDBE6, 0x577B, + 0xDBE7, 0x5768, 0xDBE8, 0x576D, 0xDBE9, 0x5776, 0xDBEA, 0x5773, + 0xDBEB, 0x57AD, 0xDBEC, 0x57A4, 0xDBED, 0x578C, 0xDBEE, 0x57B2, + 0xDBEF, 0x57CF, 0xDBF0, 0x57A7, 0xDBF1, 0x57B4, 0xDBF2, 0x5793, + 0xDBF3, 0x57A0, 0xDBF4, 0x57D5, 0xDBF5, 0x57D8, 0xDBF6, 0x57DA, + 0xDBF7, 0x57D9, 0xDBF8, 0x57D2, 0xDBF9, 0x57B8, 0xDBFA, 0x57F4, + 0xDBFB, 0x57EF, 0xDBFC, 0x57F8, 0xDBFD, 0x57E4, 0xDBFE, 0x57DD, + 0xDC40, 0x8E73, 0xDC41, 0x8E75, 0xDC42, 0x8E77, 0xDC43, 0x8E78, + 0xDC44, 0x8E79, 0xDC45, 0x8E7A, 0xDC46, 0x8E7B, 0xDC47, 0x8E7D, + 0xDC48, 0x8E7E, 0xDC49, 0x8E80, 0xDC4A, 0x8E82, 0xDC4B, 0x8E83, + 0xDC4C, 0x8E84, 0xDC4D, 0x8E86, 0xDC4E, 0x8E88, 0xDC4F, 0x8E89, + 0xDC50, 0x8E8A, 0xDC51, 0x8E8B, 0xDC52, 0x8E8C, 0xDC53, 0x8E8D, + 0xDC54, 0x8E8E, 0xDC55, 0x8E91, 0xDC56, 0x8E92, 0xDC57, 0x8E93, + 0xDC58, 0x8E95, 0xDC59, 0x8E96, 0xDC5A, 0x8E97, 0xDC5B, 0x8E98, + 0xDC5C, 0x8E99, 0xDC5D, 0x8E9A, 0xDC5E, 0x8E9B, 0xDC5F, 0x8E9D, + 0xDC60, 0x8E9F, 0xDC61, 0x8EA0, 0xDC62, 0x8EA1, 0xDC63, 0x8EA2, + 0xDC64, 0x8EA3, 0xDC65, 0x8EA4, 0xDC66, 0x8EA5, 0xDC67, 0x8EA6, + 0xDC68, 0x8EA7, 0xDC69, 0x8EA8, 0xDC6A, 0x8EA9, 0xDC6B, 0x8EAA, + 0xDC6C, 0x8EAD, 0xDC6D, 0x8EAE, 0xDC6E, 0x8EB0, 0xDC6F, 0x8EB1, + 0xDC70, 0x8EB3, 0xDC71, 0x8EB4, 0xDC72, 0x8EB5, 0xDC73, 0x8EB6, + 0xDC74, 0x8EB7, 0xDC75, 0x8EB8, 0xDC76, 0x8EB9, 0xDC77, 0x8EBB, + 0xDC78, 0x8EBC, 0xDC79, 0x8EBD, 0xDC7A, 0x8EBE, 0xDC7B, 0x8EBF, + 0xDC7C, 0x8EC0, 0xDC7D, 0x8EC1, 0xDC7E, 0x8EC2, 0xDC80, 0x8EC3, + 0xDC81, 0x8EC4, 0xDC82, 0x8EC5, 0xDC83, 0x8EC6, 0xDC84, 0x8EC7, + 0xDC85, 0x8EC8, 0xDC86, 0x8EC9, 0xDC87, 0x8ECA, 0xDC88, 0x8ECB, + 0xDC89, 0x8ECC, 0xDC8A, 0x8ECD, 0xDC8B, 0x8ECF, 0xDC8C, 0x8ED0, + 0xDC8D, 0x8ED1, 0xDC8E, 0x8ED2, 0xDC8F, 0x8ED3, 0xDC90, 0x8ED4, + 0xDC91, 0x8ED5, 0xDC92, 0x8ED6, 0xDC93, 0x8ED7, 0xDC94, 0x8ED8, + 0xDC95, 0x8ED9, 0xDC96, 0x8EDA, 0xDC97, 0x8EDB, 0xDC98, 0x8EDC, + 0xDC99, 0x8EDD, 0xDC9A, 0x8EDE, 0xDC9B, 0x8EDF, 0xDC9C, 0x8EE0, + 0xDC9D, 0x8EE1, 0xDC9E, 0x8EE2, 0xDC9F, 0x8EE3, 0xDCA0, 0x8EE4, + 0xDCA1, 0x580B, 0xDCA2, 0x580D, 0xDCA3, 0x57FD, 0xDCA4, 0x57ED, + 0xDCA5, 0x5800, 0xDCA6, 0x581E, 0xDCA7, 0x5819, 0xDCA8, 0x5844, + 0xDCA9, 0x5820, 0xDCAA, 0x5865, 0xDCAB, 0x586C, 0xDCAC, 0x5881, + 0xDCAD, 0x5889, 0xDCAE, 0x589A, 0xDCAF, 0x5880, 0xDCB0, 0x99A8, + 0xDCB1, 0x9F19, 0xDCB2, 0x61FF, 0xDCB3, 0x8279, 0xDCB4, 0x827D, + 0xDCB5, 0x827F, 0xDCB6, 0x828F, 0xDCB7, 0x828A, 0xDCB8, 0x82A8, + 0xDCB9, 0x8284, 0xDCBA, 0x828E, 0xDCBB, 0x8291, 0xDCBC, 0x8297, + 0xDCBD, 0x8299, 0xDCBE, 0x82AB, 0xDCBF, 0x82B8, 0xDCC0, 0x82BE, + 0xDCC1, 0x82B0, 0xDCC2, 0x82C8, 0xDCC3, 0x82CA, 0xDCC4, 0x82E3, + 0xDCC5, 0x8298, 0xDCC6, 0x82B7, 0xDCC7, 0x82AE, 0xDCC8, 0x82CB, + 0xDCC9, 0x82CC, 0xDCCA, 0x82C1, 0xDCCB, 0x82A9, 0xDCCC, 0x82B4, + 0xDCCD, 0x82A1, 0xDCCE, 0x82AA, 0xDCCF, 0x829F, 0xDCD0, 0x82C4, + 0xDCD1, 0x82CE, 0xDCD2, 0x82A4, 0xDCD3, 0x82E1, 0xDCD4, 0x8309, + 0xDCD5, 0x82F7, 0xDCD6, 0x82E4, 0xDCD7, 0x830F, 0xDCD8, 0x8307, + 0xDCD9, 0x82DC, 0xDCDA, 0x82F4, 0xDCDB, 0x82D2, 0xDCDC, 0x82D8, + 0xDCDD, 0x830C, 0xDCDE, 0x82FB, 0xDCDF, 0x82D3, 0xDCE0, 0x8311, + 0xDCE1, 0x831A, 0xDCE2, 0x8306, 0xDCE3, 0x8314, 0xDCE4, 0x8315, + 0xDCE5, 0x82E0, 0xDCE6, 0x82D5, 0xDCE7, 0x831C, 0xDCE8, 0x8351, + 0xDCE9, 0x835B, 0xDCEA, 0x835C, 0xDCEB, 0x8308, 0xDCEC, 0x8392, + 0xDCED, 0x833C, 0xDCEE, 0x8334, 0xDCEF, 0x8331, 0xDCF0, 0x839B, + 0xDCF1, 0x835E, 0xDCF2, 0x832F, 0xDCF3, 0x834F, 0xDCF4, 0x8347, + 0xDCF5, 0x8343, 0xDCF6, 0x835F, 0xDCF7, 0x8340, 0xDCF8, 0x8317, + 0xDCF9, 0x8360, 0xDCFA, 0x832D, 0xDCFB, 0x833A, 0xDCFC, 0x8333, + 0xDCFD, 0x8366, 0xDCFE, 0x8365, 0xDD40, 0x8EE5, 0xDD41, 0x8EE6, + 0xDD42, 0x8EE7, 0xDD43, 0x8EE8, 0xDD44, 0x8EE9, 0xDD45, 0x8EEA, + 0xDD46, 0x8EEB, 0xDD47, 0x8EEC, 0xDD48, 0x8EED, 0xDD49, 0x8EEE, + 0xDD4A, 0x8EEF, 0xDD4B, 0x8EF0, 0xDD4C, 0x8EF1, 0xDD4D, 0x8EF2, + 0xDD4E, 0x8EF3, 0xDD4F, 0x8EF4, 0xDD50, 0x8EF5, 0xDD51, 0x8EF6, + 0xDD52, 0x8EF7, 0xDD53, 0x8EF8, 0xDD54, 0x8EF9, 0xDD55, 0x8EFA, + 0xDD56, 0x8EFB, 0xDD57, 0x8EFC, 0xDD58, 0x8EFD, 0xDD59, 0x8EFE, + 0xDD5A, 0x8EFF, 0xDD5B, 0x8F00, 0xDD5C, 0x8F01, 0xDD5D, 0x8F02, + 0xDD5E, 0x8F03, 0xDD5F, 0x8F04, 0xDD60, 0x8F05, 0xDD61, 0x8F06, + 0xDD62, 0x8F07, 0xDD63, 0x8F08, 0xDD64, 0x8F09, 0xDD65, 0x8F0A, + 0xDD66, 0x8F0B, 0xDD67, 0x8F0C, 0xDD68, 0x8F0D, 0xDD69, 0x8F0E, + 0xDD6A, 0x8F0F, 0xDD6B, 0x8F10, 0xDD6C, 0x8F11, 0xDD6D, 0x8F12, + 0xDD6E, 0x8F13, 0xDD6F, 0x8F14, 0xDD70, 0x8F15, 0xDD71, 0x8F16, + 0xDD72, 0x8F17, 0xDD73, 0x8F18, 0xDD74, 0x8F19, 0xDD75, 0x8F1A, + 0xDD76, 0x8F1B, 0xDD77, 0x8F1C, 0xDD78, 0x8F1D, 0xDD79, 0x8F1E, + 0xDD7A, 0x8F1F, 0xDD7B, 0x8F20, 0xDD7C, 0x8F21, 0xDD7D, 0x8F22, + 0xDD7E, 0x8F23, 0xDD80, 0x8F24, 0xDD81, 0x8F25, 0xDD82, 0x8F26, + 0xDD83, 0x8F27, 0xDD84, 0x8F28, 0xDD85, 0x8F29, 0xDD86, 0x8F2A, + 0xDD87, 0x8F2B, 0xDD88, 0x8F2C, 0xDD89, 0x8F2D, 0xDD8A, 0x8F2E, + 0xDD8B, 0x8F2F, 0xDD8C, 0x8F30, 0xDD8D, 0x8F31, 0xDD8E, 0x8F32, + 0xDD8F, 0x8F33, 0xDD90, 0x8F34, 0xDD91, 0x8F35, 0xDD92, 0x8F36, + 0xDD93, 0x8F37, 0xDD94, 0x8F38, 0xDD95, 0x8F39, 0xDD96, 0x8F3A, + 0xDD97, 0x8F3B, 0xDD98, 0x8F3C, 0xDD99, 0x8F3D, 0xDD9A, 0x8F3E, + 0xDD9B, 0x8F3F, 0xDD9C, 0x8F40, 0xDD9D, 0x8F41, 0xDD9E, 0x8F42, + 0xDD9F, 0x8F43, 0xDDA0, 0x8F44, 0xDDA1, 0x8368, 0xDDA2, 0x831B, + 0xDDA3, 0x8369, 0xDDA4, 0x836C, 0xDDA5, 0x836A, 0xDDA6, 0x836D, + 0xDDA7, 0x836E, 0xDDA8, 0x83B0, 0xDDA9, 0x8378, 0xDDAA, 0x83B3, + 0xDDAB, 0x83B4, 0xDDAC, 0x83A0, 0xDDAD, 0x83AA, 0xDDAE, 0x8393, + 0xDDAF, 0x839C, 0xDDB0, 0x8385, 0xDDB1, 0x837C, 0xDDB2, 0x83B6, + 0xDDB3, 0x83A9, 0xDDB4, 0x837D, 0xDDB5, 0x83B8, 0xDDB6, 0x837B, + 0xDDB7, 0x8398, 0xDDB8, 0x839E, 0xDDB9, 0x83A8, 0xDDBA, 0x83BA, + 0xDDBB, 0x83BC, 0xDDBC, 0x83C1, 0xDDBD, 0x8401, 0xDDBE, 0x83E5, + 0xDDBF, 0x83D8, 0xDDC0, 0x5807, 0xDDC1, 0x8418, 0xDDC2, 0x840B, + 0xDDC3, 0x83DD, 0xDDC4, 0x83FD, 0xDDC5, 0x83D6, 0xDDC6, 0x841C, + 0xDDC7, 0x8438, 0xDDC8, 0x8411, 0xDDC9, 0x8406, 0xDDCA, 0x83D4, + 0xDDCB, 0x83DF, 0xDDCC, 0x840F, 0xDDCD, 0x8403, 0xDDCE, 0x83F8, + 0xDDCF, 0x83F9, 0xDDD0, 0x83EA, 0xDDD1, 0x83C5, 0xDDD2, 0x83C0, + 0xDDD3, 0x8426, 0xDDD4, 0x83F0, 0xDDD5, 0x83E1, 0xDDD6, 0x845C, + 0xDDD7, 0x8451, 0xDDD8, 0x845A, 0xDDD9, 0x8459, 0xDDDA, 0x8473, + 0xDDDB, 0x8487, 0xDDDC, 0x8488, 0xDDDD, 0x847A, 0xDDDE, 0x8489, + 0xDDDF, 0x8478, 0xDDE0, 0x843C, 0xDDE1, 0x8446, 0xDDE2, 0x8469, + 0xDDE3, 0x8476, 0xDDE4, 0x848C, 0xDDE5, 0x848E, 0xDDE6, 0x8431, + 0xDDE7, 0x846D, 0xDDE8, 0x84C1, 0xDDE9, 0x84CD, 0xDDEA, 0x84D0, + 0xDDEB, 0x84E6, 0xDDEC, 0x84BD, 0xDDED, 0x84D3, 0xDDEE, 0x84CA, + 0xDDEF, 0x84BF, 0xDDF0, 0x84BA, 0xDDF1, 0x84E0, 0xDDF2, 0x84A1, + 0xDDF3, 0x84B9, 0xDDF4, 0x84B4, 0xDDF5, 0x8497, 0xDDF6, 0x84E5, + 0xDDF7, 0x84E3, 0xDDF8, 0x850C, 0xDDF9, 0x750D, 0xDDFA, 0x8538, + 0xDDFB, 0x84F0, 0xDDFC, 0x8539, 0xDDFD, 0x851F, 0xDDFE, 0x853A, + 0xDE40, 0x8F45, 0xDE41, 0x8F46, 0xDE42, 0x8F47, 0xDE43, 0x8F48, + 0xDE44, 0x8F49, 0xDE45, 0x8F4A, 0xDE46, 0x8F4B, 0xDE47, 0x8F4C, + 0xDE48, 0x8F4D, 0xDE49, 0x8F4E, 0xDE4A, 0x8F4F, 0xDE4B, 0x8F50, + 0xDE4C, 0x8F51, 0xDE4D, 0x8F52, 0xDE4E, 0x8F53, 0xDE4F, 0x8F54, + 0xDE50, 0x8F55, 0xDE51, 0x8F56, 0xDE52, 0x8F57, 0xDE53, 0x8F58, + 0xDE54, 0x8F59, 0xDE55, 0x8F5A, 0xDE56, 0x8F5B, 0xDE57, 0x8F5C, + 0xDE58, 0x8F5D, 0xDE59, 0x8F5E, 0xDE5A, 0x8F5F, 0xDE5B, 0x8F60, + 0xDE5C, 0x8F61, 0xDE5D, 0x8F62, 0xDE5E, 0x8F63, 0xDE5F, 0x8F64, + 0xDE60, 0x8F65, 0xDE61, 0x8F6A, 0xDE62, 0x8F80, 0xDE63, 0x8F8C, + 0xDE64, 0x8F92, 0xDE65, 0x8F9D, 0xDE66, 0x8FA0, 0xDE67, 0x8FA1, + 0xDE68, 0x8FA2, 0xDE69, 0x8FA4, 0xDE6A, 0x8FA5, 0xDE6B, 0x8FA6, + 0xDE6C, 0x8FA7, 0xDE6D, 0x8FAA, 0xDE6E, 0x8FAC, 0xDE6F, 0x8FAD, + 0xDE70, 0x8FAE, 0xDE71, 0x8FAF, 0xDE72, 0x8FB2, 0xDE73, 0x8FB3, + 0xDE74, 0x8FB4, 0xDE75, 0x8FB5, 0xDE76, 0x8FB7, 0xDE77, 0x8FB8, + 0xDE78, 0x8FBA, 0xDE79, 0x8FBB, 0xDE7A, 0x8FBC, 0xDE7B, 0x8FBF, + 0xDE7C, 0x8FC0, 0xDE7D, 0x8FC3, 0xDE7E, 0x8FC6, 0xDE80, 0x8FC9, + 0xDE81, 0x8FCA, 0xDE82, 0x8FCB, 0xDE83, 0x8FCC, 0xDE84, 0x8FCD, + 0xDE85, 0x8FCF, 0xDE86, 0x8FD2, 0xDE87, 0x8FD6, 0xDE88, 0x8FD7, + 0xDE89, 0x8FDA, 0xDE8A, 0x8FE0, 0xDE8B, 0x8FE1, 0xDE8C, 0x8FE3, + 0xDE8D, 0x8FE7, 0xDE8E, 0x8FEC, 0xDE8F, 0x8FEF, 0xDE90, 0x8FF1, + 0xDE91, 0x8FF2, 0xDE92, 0x8FF4, 0xDE93, 0x8FF5, 0xDE94, 0x8FF6, + 0xDE95, 0x8FFA, 0xDE96, 0x8FFB, 0xDE97, 0x8FFC, 0xDE98, 0x8FFE, + 0xDE99, 0x8FFF, 0xDE9A, 0x9007, 0xDE9B, 0x9008, 0xDE9C, 0x900C, + 0xDE9D, 0x900E, 0xDE9E, 0x9013, 0xDE9F, 0x9015, 0xDEA0, 0x9018, + 0xDEA1, 0x8556, 0xDEA2, 0x853B, 0xDEA3, 0x84FF, 0xDEA4, 0x84FC, + 0xDEA5, 0x8559, 0xDEA6, 0x8548, 0xDEA7, 0x8568, 0xDEA8, 0x8564, + 0xDEA9, 0x855E, 0xDEAA, 0x857A, 0xDEAB, 0x77A2, 0xDEAC, 0x8543, + 0xDEAD, 0x8572, 0xDEAE, 0x857B, 0xDEAF, 0x85A4, 0xDEB0, 0x85A8, + 0xDEB1, 0x8587, 0xDEB2, 0x858F, 0xDEB3, 0x8579, 0xDEB4, 0x85AE, + 0xDEB5, 0x859C, 0xDEB6, 0x8585, 0xDEB7, 0x85B9, 0xDEB8, 0x85B7, + 0xDEB9, 0x85B0, 0xDEBA, 0x85D3, 0xDEBB, 0x85C1, 0xDEBC, 0x85DC, + 0xDEBD, 0x85FF, 0xDEBE, 0x8627, 0xDEBF, 0x8605, 0xDEC0, 0x8629, + 0xDEC1, 0x8616, 0xDEC2, 0x863C, 0xDEC3, 0x5EFE, 0xDEC4, 0x5F08, + 0xDEC5, 0x593C, 0xDEC6, 0x5941, 0xDEC7, 0x8037, 0xDEC8, 0x5955, + 0xDEC9, 0x595A, 0xDECA, 0x5958, 0xDECB, 0x530F, 0xDECC, 0x5C22, + 0xDECD, 0x5C25, 0xDECE, 0x5C2C, 0xDECF, 0x5C34, 0xDED0, 0x624C, + 0xDED1, 0x626A, 0xDED2, 0x629F, 0xDED3, 0x62BB, 0xDED4, 0x62CA, + 0xDED5, 0x62DA, 0xDED6, 0x62D7, 0xDED7, 0x62EE, 0xDED8, 0x6322, + 0xDED9, 0x62F6, 0xDEDA, 0x6339, 0xDEDB, 0x634B, 0xDEDC, 0x6343, + 0xDEDD, 0x63AD, 0xDEDE, 0x63F6, 0xDEDF, 0x6371, 0xDEE0, 0x637A, + 0xDEE1, 0x638E, 0xDEE2, 0x63B4, 0xDEE3, 0x636D, 0xDEE4, 0x63AC, + 0xDEE5, 0x638A, 0xDEE6, 0x6369, 0xDEE7, 0x63AE, 0xDEE8, 0x63BC, + 0xDEE9, 0x63F2, 0xDEEA, 0x63F8, 0xDEEB, 0x63E0, 0xDEEC, 0x63FF, + 0xDEED, 0x63C4, 0xDEEE, 0x63DE, 0xDEEF, 0x63CE, 0xDEF0, 0x6452, + 0xDEF1, 0x63C6, 0xDEF2, 0x63BE, 0xDEF3, 0x6445, 0xDEF4, 0x6441, + 0xDEF5, 0x640B, 0xDEF6, 0x641B, 0xDEF7, 0x6420, 0xDEF8, 0x640C, + 0xDEF9, 0x6426, 0xDEFA, 0x6421, 0xDEFB, 0x645E, 0xDEFC, 0x6484, + 0xDEFD, 0x646D, 0xDEFE, 0x6496, 0xDF40, 0x9019, 0xDF41, 0x901C, + 0xDF42, 0x9023, 0xDF43, 0x9024, 0xDF44, 0x9025, 0xDF45, 0x9027, + 0xDF46, 0x9028, 0xDF47, 0x9029, 0xDF48, 0x902A, 0xDF49, 0x902B, + 0xDF4A, 0x902C, 0xDF4B, 0x9030, 0xDF4C, 0x9031, 0xDF4D, 0x9032, + 0xDF4E, 0x9033, 0xDF4F, 0x9034, 0xDF50, 0x9037, 0xDF51, 0x9039, + 0xDF52, 0x903A, 0xDF53, 0x903D, 0xDF54, 0x903F, 0xDF55, 0x9040, + 0xDF56, 0x9043, 0xDF57, 0x9045, 0xDF58, 0x9046, 0xDF59, 0x9048, + 0xDF5A, 0x9049, 0xDF5B, 0x904A, 0xDF5C, 0x904B, 0xDF5D, 0x904C, + 0xDF5E, 0x904E, 0xDF5F, 0x9054, 0xDF60, 0x9055, 0xDF61, 0x9056, + 0xDF62, 0x9059, 0xDF63, 0x905A, 0xDF64, 0x905C, 0xDF65, 0x905D, + 0xDF66, 0x905E, 0xDF67, 0x905F, 0xDF68, 0x9060, 0xDF69, 0x9061, + 0xDF6A, 0x9064, 0xDF6B, 0x9066, 0xDF6C, 0x9067, 0xDF6D, 0x9069, + 0xDF6E, 0x906A, 0xDF6F, 0x906B, 0xDF70, 0x906C, 0xDF71, 0x906F, + 0xDF72, 0x9070, 0xDF73, 0x9071, 0xDF74, 0x9072, 0xDF75, 0x9073, + 0xDF76, 0x9076, 0xDF77, 0x9077, 0xDF78, 0x9078, 0xDF79, 0x9079, + 0xDF7A, 0x907A, 0xDF7B, 0x907B, 0xDF7C, 0x907C, 0xDF7D, 0x907E, + 0xDF7E, 0x9081, 0xDF80, 0x9084, 0xDF81, 0x9085, 0xDF82, 0x9086, + 0xDF83, 0x9087, 0xDF84, 0x9089, 0xDF85, 0x908A, 0xDF86, 0x908C, + 0xDF87, 0x908D, 0xDF88, 0x908E, 0xDF89, 0x908F, 0xDF8A, 0x9090, + 0xDF8B, 0x9092, 0xDF8C, 0x9094, 0xDF8D, 0x9096, 0xDF8E, 0x9098, + 0xDF8F, 0x909A, 0xDF90, 0x909C, 0xDF91, 0x909E, 0xDF92, 0x909F, + 0xDF93, 0x90A0, 0xDF94, 0x90A4, 0xDF95, 0x90A5, 0xDF96, 0x90A7, + 0xDF97, 0x90A8, 0xDF98, 0x90A9, 0xDF99, 0x90AB, 0xDF9A, 0x90AD, + 0xDF9B, 0x90B2, 0xDF9C, 0x90B7, 0xDF9D, 0x90BC, 0xDF9E, 0x90BD, + 0xDF9F, 0x90BF, 0xDFA0, 0x90C0, 0xDFA1, 0x647A, 0xDFA2, 0x64B7, + 0xDFA3, 0x64B8, 0xDFA4, 0x6499, 0xDFA5, 0x64BA, 0xDFA6, 0x64C0, + 0xDFA7, 0x64D0, 0xDFA8, 0x64D7, 0xDFA9, 0x64E4, 0xDFAA, 0x64E2, + 0xDFAB, 0x6509, 0xDFAC, 0x6525, 0xDFAD, 0x652E, 0xDFAE, 0x5F0B, + 0xDFAF, 0x5FD2, 0xDFB0, 0x7519, 0xDFB1, 0x5F11, 0xDFB2, 0x535F, + 0xDFB3, 0x53F1, 0xDFB4, 0x53FD, 0xDFB5, 0x53E9, 0xDFB6, 0x53E8, + 0xDFB7, 0x53FB, 0xDFB8, 0x5412, 0xDFB9, 0x5416, 0xDFBA, 0x5406, + 0xDFBB, 0x544B, 0xDFBC, 0x5452, 0xDFBD, 0x5453, 0xDFBE, 0x5454, + 0xDFBF, 0x5456, 0xDFC0, 0x5443, 0xDFC1, 0x5421, 0xDFC2, 0x5457, + 0xDFC3, 0x5459, 0xDFC4, 0x5423, 0xDFC5, 0x5432, 0xDFC6, 0x5482, + 0xDFC7, 0x5494, 0xDFC8, 0x5477, 0xDFC9, 0x5471, 0xDFCA, 0x5464, + 0xDFCB, 0x549A, 0xDFCC, 0x549B, 0xDFCD, 0x5484, 0xDFCE, 0x5476, + 0xDFCF, 0x5466, 0xDFD0, 0x549D, 0xDFD1, 0x54D0, 0xDFD2, 0x54AD, + 0xDFD3, 0x54C2, 0xDFD4, 0x54B4, 0xDFD5, 0x54D2, 0xDFD6, 0x54A7, + 0xDFD7, 0x54A6, 0xDFD8, 0x54D3, 0xDFD9, 0x54D4, 0xDFDA, 0x5472, + 0xDFDB, 0x54A3, 0xDFDC, 0x54D5, 0xDFDD, 0x54BB, 0xDFDE, 0x54BF, + 0xDFDF, 0x54CC, 0xDFE0, 0x54D9, 0xDFE1, 0x54DA, 0xDFE2, 0x54DC, + 0xDFE3, 0x54A9, 0xDFE4, 0x54AA, 0xDFE5, 0x54A4, 0xDFE6, 0x54DD, + 0xDFE7, 0x54CF, 0xDFE8, 0x54DE, 0xDFE9, 0x551B, 0xDFEA, 0x54E7, + 0xDFEB, 0x5520, 0xDFEC, 0x54FD, 0xDFED, 0x5514, 0xDFEE, 0x54F3, + 0xDFEF, 0x5522, 0xDFF0, 0x5523, 0xDFF1, 0x550F, 0xDFF2, 0x5511, + 0xDFF3, 0x5527, 0xDFF4, 0x552A, 0xDFF5, 0x5567, 0xDFF6, 0x558F, + 0xDFF7, 0x55B5, 0xDFF8, 0x5549, 0xDFF9, 0x556D, 0xDFFA, 0x5541, + 0xDFFB, 0x5555, 0xDFFC, 0x553F, 0xDFFD, 0x5550, 0xDFFE, 0x553C, + 0xE040, 0x90C2, 0xE041, 0x90C3, 0xE042, 0x90C6, 0xE043, 0x90C8, + 0xE044, 0x90C9, 0xE045, 0x90CB, 0xE046, 0x90CC, 0xE047, 0x90CD, + 0xE048, 0x90D2, 0xE049, 0x90D4, 0xE04A, 0x90D5, 0xE04B, 0x90D6, + 0xE04C, 0x90D8, 0xE04D, 0x90D9, 0xE04E, 0x90DA, 0xE04F, 0x90DE, + 0xE050, 0x90DF, 0xE051, 0x90E0, 0xE052, 0x90E3, 0xE053, 0x90E4, + 0xE054, 0x90E5, 0xE055, 0x90E9, 0xE056, 0x90EA, 0xE057, 0x90EC, + 0xE058, 0x90EE, 0xE059, 0x90F0, 0xE05A, 0x90F1, 0xE05B, 0x90F2, + 0xE05C, 0x90F3, 0xE05D, 0x90F5, 0xE05E, 0x90F6, 0xE05F, 0x90F7, + 0xE060, 0x90F9, 0xE061, 0x90FA, 0xE062, 0x90FB, 0xE063, 0x90FC, + 0xE064, 0x90FF, 0xE065, 0x9100, 0xE066, 0x9101, 0xE067, 0x9103, + 0xE068, 0x9105, 0xE069, 0x9106, 0xE06A, 0x9107, 0xE06B, 0x9108, + 0xE06C, 0x9109, 0xE06D, 0x910A, 0xE06E, 0x910B, 0xE06F, 0x910C, + 0xE070, 0x910D, 0xE071, 0x910E, 0xE072, 0x910F, 0xE073, 0x9110, + 0xE074, 0x9111, 0xE075, 0x9112, 0xE076, 0x9113, 0xE077, 0x9114, + 0xE078, 0x9115, 0xE079, 0x9116, 0xE07A, 0x9117, 0xE07B, 0x9118, + 0xE07C, 0x911A, 0xE07D, 0x911B, 0xE07E, 0x911C, 0xE080, 0x911D, + 0xE081, 0x911F, 0xE082, 0x9120, 0xE083, 0x9121, 0xE084, 0x9124, + 0xE085, 0x9125, 0xE086, 0x9126, 0xE087, 0x9127, 0xE088, 0x9128, + 0xE089, 0x9129, 0xE08A, 0x912A, 0xE08B, 0x912B, 0xE08C, 0x912C, + 0xE08D, 0x912D, 0xE08E, 0x912E, 0xE08F, 0x9130, 0xE090, 0x9132, + 0xE091, 0x9133, 0xE092, 0x9134, 0xE093, 0x9135, 0xE094, 0x9136, + 0xE095, 0x9137, 0xE096, 0x9138, 0xE097, 0x913A, 0xE098, 0x913B, + 0xE099, 0x913C, 0xE09A, 0x913D, 0xE09B, 0x913E, 0xE09C, 0x913F, + 0xE09D, 0x9140, 0xE09E, 0x9141, 0xE09F, 0x9142, 0xE0A0, 0x9144, + 0xE0A1, 0x5537, 0xE0A2, 0x5556, 0xE0A3, 0x5575, 0xE0A4, 0x5576, + 0xE0A5, 0x5577, 0xE0A6, 0x5533, 0xE0A7, 0x5530, 0xE0A8, 0x555C, + 0xE0A9, 0x558B, 0xE0AA, 0x55D2, 0xE0AB, 0x5583, 0xE0AC, 0x55B1, + 0xE0AD, 0x55B9, 0xE0AE, 0x5588, 0xE0AF, 0x5581, 0xE0B0, 0x559F, + 0xE0B1, 0x557E, 0xE0B2, 0x55D6, 0xE0B3, 0x5591, 0xE0B4, 0x557B, + 0xE0B5, 0x55DF, 0xE0B6, 0x55BD, 0xE0B7, 0x55BE, 0xE0B8, 0x5594, + 0xE0B9, 0x5599, 0xE0BA, 0x55EA, 0xE0BB, 0x55F7, 0xE0BC, 0x55C9, + 0xE0BD, 0x561F, 0xE0BE, 0x55D1, 0xE0BF, 0x55EB, 0xE0C0, 0x55EC, + 0xE0C1, 0x55D4, 0xE0C2, 0x55E6, 0xE0C3, 0x55DD, 0xE0C4, 0x55C4, + 0xE0C5, 0x55EF, 0xE0C6, 0x55E5, 0xE0C7, 0x55F2, 0xE0C8, 0x55F3, + 0xE0C9, 0x55CC, 0xE0CA, 0x55CD, 0xE0CB, 0x55E8, 0xE0CC, 0x55F5, + 0xE0CD, 0x55E4, 0xE0CE, 0x8F94, 0xE0CF, 0x561E, 0xE0D0, 0x5608, + 0xE0D1, 0x560C, 0xE0D2, 0x5601, 0xE0D3, 0x5624, 0xE0D4, 0x5623, + 0xE0D5, 0x55FE, 0xE0D6, 0x5600, 0xE0D7, 0x5627, 0xE0D8, 0x562D, + 0xE0D9, 0x5658, 0xE0DA, 0x5639, 0xE0DB, 0x5657, 0xE0DC, 0x562C, + 0xE0DD, 0x564D, 0xE0DE, 0x5662, 0xE0DF, 0x5659, 0xE0E0, 0x565C, + 0xE0E1, 0x564C, 0xE0E2, 0x5654, 0xE0E3, 0x5686, 0xE0E4, 0x5664, + 0xE0E5, 0x5671, 0xE0E6, 0x566B, 0xE0E7, 0x567B, 0xE0E8, 0x567C, + 0xE0E9, 0x5685, 0xE0EA, 0x5693, 0xE0EB, 0x56AF, 0xE0EC, 0x56D4, + 0xE0ED, 0x56D7, 0xE0EE, 0x56DD, 0xE0EF, 0x56E1, 0xE0F0, 0x56F5, + 0xE0F1, 0x56EB, 0xE0F2, 0x56F9, 0xE0F3, 0x56FF, 0xE0F4, 0x5704, + 0xE0F5, 0x570A, 0xE0F6, 0x5709, 0xE0F7, 0x571C, 0xE0F8, 0x5E0F, + 0xE0F9, 0x5E19, 0xE0FA, 0x5E14, 0xE0FB, 0x5E11, 0xE0FC, 0x5E31, + 0xE0FD, 0x5E3B, 0xE0FE, 0x5E3C, 0xE140, 0x9145, 0xE141, 0x9147, + 0xE142, 0x9148, 0xE143, 0x9151, 0xE144, 0x9153, 0xE145, 0x9154, + 0xE146, 0x9155, 0xE147, 0x9156, 0xE148, 0x9158, 0xE149, 0x9159, + 0xE14A, 0x915B, 0xE14B, 0x915C, 0xE14C, 0x915F, 0xE14D, 0x9160, + 0xE14E, 0x9166, 0xE14F, 0x9167, 0xE150, 0x9168, 0xE151, 0x916B, + 0xE152, 0x916D, 0xE153, 0x9173, 0xE154, 0x917A, 0xE155, 0x917B, + 0xE156, 0x917C, 0xE157, 0x9180, 0xE158, 0x9181, 0xE159, 0x9182, + 0xE15A, 0x9183, 0xE15B, 0x9184, 0xE15C, 0x9186, 0xE15D, 0x9188, + 0xE15E, 0x918A, 0xE15F, 0x918E, 0xE160, 0x918F, 0xE161, 0x9193, + 0xE162, 0x9194, 0xE163, 0x9195, 0xE164, 0x9196, 0xE165, 0x9197, + 0xE166, 0x9198, 0xE167, 0x9199, 0xE168, 0x919C, 0xE169, 0x919D, + 0xE16A, 0x919E, 0xE16B, 0x919F, 0xE16C, 0x91A0, 0xE16D, 0x91A1, + 0xE16E, 0x91A4, 0xE16F, 0x91A5, 0xE170, 0x91A6, 0xE171, 0x91A7, + 0xE172, 0x91A8, 0xE173, 0x91A9, 0xE174, 0x91AB, 0xE175, 0x91AC, + 0xE176, 0x91B0, 0xE177, 0x91B1, 0xE178, 0x91B2, 0xE179, 0x91B3, + 0xE17A, 0x91B6, 0xE17B, 0x91B7, 0xE17C, 0x91B8, 0xE17D, 0x91B9, + 0xE17E, 0x91BB, 0xE180, 0x91BC, 0xE181, 0x91BD, 0xE182, 0x91BE, + 0xE183, 0x91BF, 0xE184, 0x91C0, 0xE185, 0x91C1, 0xE186, 0x91C2, + 0xE187, 0x91C3, 0xE188, 0x91C4, 0xE189, 0x91C5, 0xE18A, 0x91C6, + 0xE18B, 0x91C8, 0xE18C, 0x91CB, 0xE18D, 0x91D0, 0xE18E, 0x91D2, + 0xE18F, 0x91D3, 0xE190, 0x91D4, 0xE191, 0x91D5, 0xE192, 0x91D6, + 0xE193, 0x91D7, 0xE194, 0x91D8, 0xE195, 0x91D9, 0xE196, 0x91DA, + 0xE197, 0x91DB, 0xE198, 0x91DD, 0xE199, 0x91DE, 0xE19A, 0x91DF, + 0xE19B, 0x91E0, 0xE19C, 0x91E1, 0xE19D, 0x91E2, 0xE19E, 0x91E3, + 0xE19F, 0x91E4, 0xE1A0, 0x91E5, 0xE1A1, 0x5E37, 0xE1A2, 0x5E44, + 0xE1A3, 0x5E54, 0xE1A4, 0x5E5B, 0xE1A5, 0x5E5E, 0xE1A6, 0x5E61, + 0xE1A7, 0x5C8C, 0xE1A8, 0x5C7A, 0xE1A9, 0x5C8D, 0xE1AA, 0x5C90, + 0xE1AB, 0x5C96, 0xE1AC, 0x5C88, 0xE1AD, 0x5C98, 0xE1AE, 0x5C99, + 0xE1AF, 0x5C91, 0xE1B0, 0x5C9A, 0xE1B1, 0x5C9C, 0xE1B2, 0x5CB5, + 0xE1B3, 0x5CA2, 0xE1B4, 0x5CBD, 0xE1B5, 0x5CAC, 0xE1B6, 0x5CAB, + 0xE1B7, 0x5CB1, 0xE1B8, 0x5CA3, 0xE1B9, 0x5CC1, 0xE1BA, 0x5CB7, + 0xE1BB, 0x5CC4, 0xE1BC, 0x5CD2, 0xE1BD, 0x5CE4, 0xE1BE, 0x5CCB, + 0xE1BF, 0x5CE5, 0xE1C0, 0x5D02, 0xE1C1, 0x5D03, 0xE1C2, 0x5D27, + 0xE1C3, 0x5D26, 0xE1C4, 0x5D2E, 0xE1C5, 0x5D24, 0xE1C6, 0x5D1E, + 0xE1C7, 0x5D06, 0xE1C8, 0x5D1B, 0xE1C9, 0x5D58, 0xE1CA, 0x5D3E, + 0xE1CB, 0x5D34, 0xE1CC, 0x5D3D, 0xE1CD, 0x5D6C, 0xE1CE, 0x5D5B, + 0xE1CF, 0x5D6F, 0xE1D0, 0x5D5D, 0xE1D1, 0x5D6B, 0xE1D2, 0x5D4B, + 0xE1D3, 0x5D4A, 0xE1D4, 0x5D69, 0xE1D5, 0x5D74, 0xE1D6, 0x5D82, + 0xE1D7, 0x5D99, 0xE1D8, 0x5D9D, 0xE1D9, 0x8C73, 0xE1DA, 0x5DB7, + 0xE1DB, 0x5DC5, 0xE1DC, 0x5F73, 0xE1DD, 0x5F77, 0xE1DE, 0x5F82, + 0xE1DF, 0x5F87, 0xE1E0, 0x5F89, 0xE1E1, 0x5F8C, 0xE1E2, 0x5F95, + 0xE1E3, 0x5F99, 0xE1E4, 0x5F9C, 0xE1E5, 0x5FA8, 0xE1E6, 0x5FAD, + 0xE1E7, 0x5FB5, 0xE1E8, 0x5FBC, 0xE1E9, 0x8862, 0xE1EA, 0x5F61, + 0xE1EB, 0x72AD, 0xE1EC, 0x72B0, 0xE1ED, 0x72B4, 0xE1EE, 0x72B7, + 0xE1EF, 0x72B8, 0xE1F0, 0x72C3, 0xE1F1, 0x72C1, 0xE1F2, 0x72CE, + 0xE1F3, 0x72CD, 0xE1F4, 0x72D2, 0xE1F5, 0x72E8, 0xE1F6, 0x72EF, + 0xE1F7, 0x72E9, 0xE1F8, 0x72F2, 0xE1F9, 0x72F4, 0xE1FA, 0x72F7, + 0xE1FB, 0x7301, 0xE1FC, 0x72F3, 0xE1FD, 0x7303, 0xE1FE, 0x72FA, + 0xE240, 0x91E6, 0xE241, 0x91E7, 0xE242, 0x91E8, 0xE243, 0x91E9, + 0xE244, 0x91EA, 0xE245, 0x91EB, 0xE246, 0x91EC, 0xE247, 0x91ED, + 0xE248, 0x91EE, 0xE249, 0x91EF, 0xE24A, 0x91F0, 0xE24B, 0x91F1, + 0xE24C, 0x91F2, 0xE24D, 0x91F3, 0xE24E, 0x91F4, 0xE24F, 0x91F5, + 0xE250, 0x91F6, 0xE251, 0x91F7, 0xE252, 0x91F8, 0xE253, 0x91F9, + 0xE254, 0x91FA, 0xE255, 0x91FB, 0xE256, 0x91FC, 0xE257, 0x91FD, + 0xE258, 0x91FE, 0xE259, 0x91FF, 0xE25A, 0x9200, 0xE25B, 0x9201, + 0xE25C, 0x9202, 0xE25D, 0x9203, 0xE25E, 0x9204, 0xE25F, 0x9205, + 0xE260, 0x9206, 0xE261, 0x9207, 0xE262, 0x9208, 0xE263, 0x9209, + 0xE264, 0x920A, 0xE265, 0x920B, 0xE266, 0x920C, 0xE267, 0x920D, + 0xE268, 0x920E, 0xE269, 0x920F, 0xE26A, 0x9210, 0xE26B, 0x9211, + 0xE26C, 0x9212, 0xE26D, 0x9213, 0xE26E, 0x9214, 0xE26F, 0x9215, + 0xE270, 0x9216, 0xE271, 0x9217, 0xE272, 0x9218, 0xE273, 0x9219, + 0xE274, 0x921A, 0xE275, 0x921B, 0xE276, 0x921C, 0xE277, 0x921D, + 0xE278, 0x921E, 0xE279, 0x921F, 0xE27A, 0x9220, 0xE27B, 0x9221, + 0xE27C, 0x9222, 0xE27D, 0x9223, 0xE27E, 0x9224, 0xE280, 0x9225, + 0xE281, 0x9226, 0xE282, 0x9227, 0xE283, 0x9228, 0xE284, 0x9229, + 0xE285, 0x922A, 0xE286, 0x922B, 0xE287, 0x922C, 0xE288, 0x922D, + 0xE289, 0x922E, 0xE28A, 0x922F, 0xE28B, 0x9230, 0xE28C, 0x9231, + 0xE28D, 0x9232, 0xE28E, 0x9233, 0xE28F, 0x9234, 0xE290, 0x9235, + 0xE291, 0x9236, 0xE292, 0x9237, 0xE293, 0x9238, 0xE294, 0x9239, + 0xE295, 0x923A, 0xE296, 0x923B, 0xE297, 0x923C, 0xE298, 0x923D, + 0xE299, 0x923E, 0xE29A, 0x923F, 0xE29B, 0x9240, 0xE29C, 0x9241, + 0xE29D, 0x9242, 0xE29E, 0x9243, 0xE29F, 0x9244, 0xE2A0, 0x9245, + 0xE2A1, 0x72FB, 0xE2A2, 0x7317, 0xE2A3, 0x7313, 0xE2A4, 0x7321, + 0xE2A5, 0x730A, 0xE2A6, 0x731E, 0xE2A7, 0x731D, 0xE2A8, 0x7315, + 0xE2A9, 0x7322, 0xE2AA, 0x7339, 0xE2AB, 0x7325, 0xE2AC, 0x732C, + 0xE2AD, 0x7338, 0xE2AE, 0x7331, 0xE2AF, 0x7350, 0xE2B0, 0x734D, + 0xE2B1, 0x7357, 0xE2B2, 0x7360, 0xE2B3, 0x736C, 0xE2B4, 0x736F, + 0xE2B5, 0x737E, 0xE2B6, 0x821B, 0xE2B7, 0x5925, 0xE2B8, 0x98E7, + 0xE2B9, 0x5924, 0xE2BA, 0x5902, 0xE2BB, 0x9963, 0xE2BC, 0x9967, + 0xE2BD, 0x9968, 0xE2BE, 0x9969, 0xE2BF, 0x996A, 0xE2C0, 0x996B, + 0xE2C1, 0x996C, 0xE2C2, 0x9974, 0xE2C3, 0x9977, 0xE2C4, 0x997D, + 0xE2C5, 0x9980, 0xE2C6, 0x9984, 0xE2C7, 0x9987, 0xE2C8, 0x998A, + 0xE2C9, 0x998D, 0xE2CA, 0x9990, 0xE2CB, 0x9991, 0xE2CC, 0x9993, + 0xE2CD, 0x9994, 0xE2CE, 0x9995, 0xE2CF, 0x5E80, 0xE2D0, 0x5E91, + 0xE2D1, 0x5E8B, 0xE2D2, 0x5E96, 0xE2D3, 0x5EA5, 0xE2D4, 0x5EA0, + 0xE2D5, 0x5EB9, 0xE2D6, 0x5EB5, 0xE2D7, 0x5EBE, 0xE2D8, 0x5EB3, + 0xE2D9, 0x8D53, 0xE2DA, 0x5ED2, 0xE2DB, 0x5ED1, 0xE2DC, 0x5EDB, + 0xE2DD, 0x5EE8, 0xE2DE, 0x5EEA, 0xE2DF, 0x81BA, 0xE2E0, 0x5FC4, + 0xE2E1, 0x5FC9, 0xE2E2, 0x5FD6, 0xE2E3, 0x5FCF, 0xE2E4, 0x6003, + 0xE2E5, 0x5FEE, 0xE2E6, 0x6004, 0xE2E7, 0x5FE1, 0xE2E8, 0x5FE4, + 0xE2E9, 0x5FFE, 0xE2EA, 0x6005, 0xE2EB, 0x6006, 0xE2EC, 0x5FEA, + 0xE2ED, 0x5FED, 0xE2EE, 0x5FF8, 0xE2EF, 0x6019, 0xE2F0, 0x6035, + 0xE2F1, 0x6026, 0xE2F2, 0x601B, 0xE2F3, 0x600F, 0xE2F4, 0x600D, + 0xE2F5, 0x6029, 0xE2F6, 0x602B, 0xE2F7, 0x600A, 0xE2F8, 0x603F, + 0xE2F9, 0x6021, 0xE2FA, 0x6078, 0xE2FB, 0x6079, 0xE2FC, 0x607B, + 0xE2FD, 0x607A, 0xE2FE, 0x6042, 0xE340, 0x9246, 0xE341, 0x9247, + 0xE342, 0x9248, 0xE343, 0x9249, 0xE344, 0x924A, 0xE345, 0x924B, + 0xE346, 0x924C, 0xE347, 0x924D, 0xE348, 0x924E, 0xE349, 0x924F, + 0xE34A, 0x9250, 0xE34B, 0x9251, 0xE34C, 0x9252, 0xE34D, 0x9253, + 0xE34E, 0x9254, 0xE34F, 0x9255, 0xE350, 0x9256, 0xE351, 0x9257, + 0xE352, 0x9258, 0xE353, 0x9259, 0xE354, 0x925A, 0xE355, 0x925B, + 0xE356, 0x925C, 0xE357, 0x925D, 0xE358, 0x925E, 0xE359, 0x925F, + 0xE35A, 0x9260, 0xE35B, 0x9261, 0xE35C, 0x9262, 0xE35D, 0x9263, + 0xE35E, 0x9264, 0xE35F, 0x9265, 0xE360, 0x9266, 0xE361, 0x9267, + 0xE362, 0x9268, 0xE363, 0x9269, 0xE364, 0x926A, 0xE365, 0x926B, + 0xE366, 0x926C, 0xE367, 0x926D, 0xE368, 0x926E, 0xE369, 0x926F, + 0xE36A, 0x9270, 0xE36B, 0x9271, 0xE36C, 0x9272, 0xE36D, 0x9273, + 0xE36E, 0x9275, 0xE36F, 0x9276, 0xE370, 0x9277, 0xE371, 0x9278, + 0xE372, 0x9279, 0xE373, 0x927A, 0xE374, 0x927B, 0xE375, 0x927C, + 0xE376, 0x927D, 0xE377, 0x927E, 0xE378, 0x927F, 0xE379, 0x9280, + 0xE37A, 0x9281, 0xE37B, 0x9282, 0xE37C, 0x9283, 0xE37D, 0x9284, + 0xE37E, 0x9285, 0xE380, 0x9286, 0xE381, 0x9287, 0xE382, 0x9288, + 0xE383, 0x9289, 0xE384, 0x928A, 0xE385, 0x928B, 0xE386, 0x928C, + 0xE387, 0x928D, 0xE388, 0x928F, 0xE389, 0x9290, 0xE38A, 0x9291, + 0xE38B, 0x9292, 0xE38C, 0x9293, 0xE38D, 0x9294, 0xE38E, 0x9295, + 0xE38F, 0x9296, 0xE390, 0x9297, 0xE391, 0x9298, 0xE392, 0x9299, + 0xE393, 0x929A, 0xE394, 0x929B, 0xE395, 0x929C, 0xE396, 0x929D, + 0xE397, 0x929E, 0xE398, 0x929F, 0xE399, 0x92A0, 0xE39A, 0x92A1, + 0xE39B, 0x92A2, 0xE39C, 0x92A3, 0xE39D, 0x92A4, 0xE39E, 0x92A5, + 0xE39F, 0x92A6, 0xE3A0, 0x92A7, 0xE3A1, 0x606A, 0xE3A2, 0x607D, + 0xE3A3, 0x6096, 0xE3A4, 0x609A, 0xE3A5, 0x60AD, 0xE3A6, 0x609D, + 0xE3A7, 0x6083, 0xE3A8, 0x6092, 0xE3A9, 0x608C, 0xE3AA, 0x609B, + 0xE3AB, 0x60EC, 0xE3AC, 0x60BB, 0xE3AD, 0x60B1, 0xE3AE, 0x60DD, + 0xE3AF, 0x60D8, 0xE3B0, 0x60C6, 0xE3B1, 0x60DA, 0xE3B2, 0x60B4, + 0xE3B3, 0x6120, 0xE3B4, 0x6126, 0xE3B5, 0x6115, 0xE3B6, 0x6123, + 0xE3B7, 0x60F4, 0xE3B8, 0x6100, 0xE3B9, 0x610E, 0xE3BA, 0x612B, + 0xE3BB, 0x614A, 0xE3BC, 0x6175, 0xE3BD, 0x61AC, 0xE3BE, 0x6194, + 0xE3BF, 0x61A7, 0xE3C0, 0x61B7, 0xE3C1, 0x61D4, 0xE3C2, 0x61F5, + 0xE3C3, 0x5FDD, 0xE3C4, 0x96B3, 0xE3C5, 0x95E9, 0xE3C6, 0x95EB, + 0xE3C7, 0x95F1, 0xE3C8, 0x95F3, 0xE3C9, 0x95F5, 0xE3CA, 0x95F6, + 0xE3CB, 0x95FC, 0xE3CC, 0x95FE, 0xE3CD, 0x9603, 0xE3CE, 0x9604, + 0xE3CF, 0x9606, 0xE3D0, 0x9608, 0xE3D1, 0x960A, 0xE3D2, 0x960B, + 0xE3D3, 0x960C, 0xE3D4, 0x960D, 0xE3D5, 0x960F, 0xE3D6, 0x9612, + 0xE3D7, 0x9615, 0xE3D8, 0x9616, 0xE3D9, 0x9617, 0xE3DA, 0x9619, + 0xE3DB, 0x961A, 0xE3DC, 0x4E2C, 0xE3DD, 0x723F, 0xE3DE, 0x6215, + 0xE3DF, 0x6C35, 0xE3E0, 0x6C54, 0xE3E1, 0x6C5C, 0xE3E2, 0x6C4A, + 0xE3E3, 0x6CA3, 0xE3E4, 0x6C85, 0xE3E5, 0x6C90, 0xE3E6, 0x6C94, + 0xE3E7, 0x6C8C, 0xE3E8, 0x6C68, 0xE3E9, 0x6C69, 0xE3EA, 0x6C74, + 0xE3EB, 0x6C76, 0xE3EC, 0x6C86, 0xE3ED, 0x6CA9, 0xE3EE, 0x6CD0, + 0xE3EF, 0x6CD4, 0xE3F0, 0x6CAD, 0xE3F1, 0x6CF7, 0xE3F2, 0x6CF8, + 0xE3F3, 0x6CF1, 0xE3F4, 0x6CD7, 0xE3F5, 0x6CB2, 0xE3F6, 0x6CE0, + 0xE3F7, 0x6CD6, 0xE3F8, 0x6CFA, 0xE3F9, 0x6CEB, 0xE3FA, 0x6CEE, + 0xE3FB, 0x6CB1, 0xE3FC, 0x6CD3, 0xE3FD, 0x6CEF, 0xE3FE, 0x6CFE, + 0xE440, 0x92A8, 0xE441, 0x92A9, 0xE442, 0x92AA, 0xE443, 0x92AB, + 0xE444, 0x92AC, 0xE445, 0x92AD, 0xE446, 0x92AF, 0xE447, 0x92B0, + 0xE448, 0x92B1, 0xE449, 0x92B2, 0xE44A, 0x92B3, 0xE44B, 0x92B4, + 0xE44C, 0x92B5, 0xE44D, 0x92B6, 0xE44E, 0x92B7, 0xE44F, 0x92B8, + 0xE450, 0x92B9, 0xE451, 0x92BA, 0xE452, 0x92BB, 0xE453, 0x92BC, + 0xE454, 0x92BD, 0xE455, 0x92BE, 0xE456, 0x92BF, 0xE457, 0x92C0, + 0xE458, 0x92C1, 0xE459, 0x92C2, 0xE45A, 0x92C3, 0xE45B, 0x92C4, + 0xE45C, 0x92C5, 0xE45D, 0x92C6, 0xE45E, 0x92C7, 0xE45F, 0x92C9, + 0xE460, 0x92CA, 0xE461, 0x92CB, 0xE462, 0x92CC, 0xE463, 0x92CD, + 0xE464, 0x92CE, 0xE465, 0x92CF, 0xE466, 0x92D0, 0xE467, 0x92D1, + 0xE468, 0x92D2, 0xE469, 0x92D3, 0xE46A, 0x92D4, 0xE46B, 0x92D5, + 0xE46C, 0x92D6, 0xE46D, 0x92D7, 0xE46E, 0x92D8, 0xE46F, 0x92D9, + 0xE470, 0x92DA, 0xE471, 0x92DB, 0xE472, 0x92DC, 0xE473, 0x92DD, + 0xE474, 0x92DE, 0xE475, 0x92DF, 0xE476, 0x92E0, 0xE477, 0x92E1, + 0xE478, 0x92E2, 0xE479, 0x92E3, 0xE47A, 0x92E4, 0xE47B, 0x92E5, + 0xE47C, 0x92E6, 0xE47D, 0x92E7, 0xE47E, 0x92E8, 0xE480, 0x92E9, + 0xE481, 0x92EA, 0xE482, 0x92EB, 0xE483, 0x92EC, 0xE484, 0x92ED, + 0xE485, 0x92EE, 0xE486, 0x92EF, 0xE487, 0x92F0, 0xE488, 0x92F1, + 0xE489, 0x92F2, 0xE48A, 0x92F3, 0xE48B, 0x92F4, 0xE48C, 0x92F5, + 0xE48D, 0x92F6, 0xE48E, 0x92F7, 0xE48F, 0x92F8, 0xE490, 0x92F9, + 0xE491, 0x92FA, 0xE492, 0x92FB, 0xE493, 0x92FC, 0xE494, 0x92FD, + 0xE495, 0x92FE, 0xE496, 0x92FF, 0xE497, 0x9300, 0xE498, 0x9301, + 0xE499, 0x9302, 0xE49A, 0x9303, 0xE49B, 0x9304, 0xE49C, 0x9305, + 0xE49D, 0x9306, 0xE49E, 0x9307, 0xE49F, 0x9308, 0xE4A0, 0x9309, + 0xE4A1, 0x6D39, 0xE4A2, 0x6D27, 0xE4A3, 0x6D0C, 0xE4A4, 0x6D43, + 0xE4A5, 0x6D48, 0xE4A6, 0x6D07, 0xE4A7, 0x6D04, 0xE4A8, 0x6D19, + 0xE4A9, 0x6D0E, 0xE4AA, 0x6D2B, 0xE4AB, 0x6D4D, 0xE4AC, 0x6D2E, + 0xE4AD, 0x6D35, 0xE4AE, 0x6D1A, 0xE4AF, 0x6D4F, 0xE4B0, 0x6D52, + 0xE4B1, 0x6D54, 0xE4B2, 0x6D33, 0xE4B3, 0x6D91, 0xE4B4, 0x6D6F, + 0xE4B5, 0x6D9E, 0xE4B6, 0x6DA0, 0xE4B7, 0x6D5E, 0xE4B8, 0x6D93, + 0xE4B9, 0x6D94, 0xE4BA, 0x6D5C, 0xE4BB, 0x6D60, 0xE4BC, 0x6D7C, + 0xE4BD, 0x6D63, 0xE4BE, 0x6E1A, 0xE4BF, 0x6DC7, 0xE4C0, 0x6DC5, + 0xE4C1, 0x6DDE, 0xE4C2, 0x6E0E, 0xE4C3, 0x6DBF, 0xE4C4, 0x6DE0, + 0xE4C5, 0x6E11, 0xE4C6, 0x6DE6, 0xE4C7, 0x6DDD, 0xE4C8, 0x6DD9, + 0xE4C9, 0x6E16, 0xE4CA, 0x6DAB, 0xE4CB, 0x6E0C, 0xE4CC, 0x6DAE, + 0xE4CD, 0x6E2B, 0xE4CE, 0x6E6E, 0xE4CF, 0x6E4E, 0xE4D0, 0x6E6B, + 0xE4D1, 0x6EB2, 0xE4D2, 0x6E5F, 0xE4D3, 0x6E86, 0xE4D4, 0x6E53, + 0xE4D5, 0x6E54, 0xE4D6, 0x6E32, 0xE4D7, 0x6E25, 0xE4D8, 0x6E44, + 0xE4D9, 0x6EDF, 0xE4DA, 0x6EB1, 0xE4DB, 0x6E98, 0xE4DC, 0x6EE0, + 0xE4DD, 0x6F2D, 0xE4DE, 0x6EE2, 0xE4DF, 0x6EA5, 0xE4E0, 0x6EA7, + 0xE4E1, 0x6EBD, 0xE4E2, 0x6EBB, 0xE4E3, 0x6EB7, 0xE4E4, 0x6ED7, + 0xE4E5, 0x6EB4, 0xE4E6, 0x6ECF, 0xE4E7, 0x6E8F, 0xE4E8, 0x6EC2, + 0xE4E9, 0x6E9F, 0xE4EA, 0x6F62, 0xE4EB, 0x6F46, 0xE4EC, 0x6F47, + 0xE4ED, 0x6F24, 0xE4EE, 0x6F15, 0xE4EF, 0x6EF9, 0xE4F0, 0x6F2F, + 0xE4F1, 0x6F36, 0xE4F2, 0x6F4B, 0xE4F3, 0x6F74, 0xE4F4, 0x6F2A, + 0xE4F5, 0x6F09, 0xE4F6, 0x6F29, 0xE4F7, 0x6F89, 0xE4F8, 0x6F8D, + 0xE4F9, 0x6F8C, 0xE4FA, 0x6F78, 0xE4FB, 0x6F72, 0xE4FC, 0x6F7C, + 0xE4FD, 0x6F7A, 0xE4FE, 0x6FD1, 0xE540, 0x930A, 0xE541, 0x930B, + 0xE542, 0x930C, 0xE543, 0x930D, 0xE544, 0x930E, 0xE545, 0x930F, + 0xE546, 0x9310, 0xE547, 0x9311, 0xE548, 0x9312, 0xE549, 0x9313, + 0xE54A, 0x9314, 0xE54B, 0x9315, 0xE54C, 0x9316, 0xE54D, 0x9317, + 0xE54E, 0x9318, 0xE54F, 0x9319, 0xE550, 0x931A, 0xE551, 0x931B, + 0xE552, 0x931C, 0xE553, 0x931D, 0xE554, 0x931E, 0xE555, 0x931F, + 0xE556, 0x9320, 0xE557, 0x9321, 0xE558, 0x9322, 0xE559, 0x9323, + 0xE55A, 0x9324, 0xE55B, 0x9325, 0xE55C, 0x9326, 0xE55D, 0x9327, + 0xE55E, 0x9328, 0xE55F, 0x9329, 0xE560, 0x932A, 0xE561, 0x932B, + 0xE562, 0x932C, 0xE563, 0x932D, 0xE564, 0x932E, 0xE565, 0x932F, + 0xE566, 0x9330, 0xE567, 0x9331, 0xE568, 0x9332, 0xE569, 0x9333, + 0xE56A, 0x9334, 0xE56B, 0x9335, 0xE56C, 0x9336, 0xE56D, 0x9337, + 0xE56E, 0x9338, 0xE56F, 0x9339, 0xE570, 0x933A, 0xE571, 0x933B, + 0xE572, 0x933C, 0xE573, 0x933D, 0xE574, 0x933F, 0xE575, 0x9340, + 0xE576, 0x9341, 0xE577, 0x9342, 0xE578, 0x9343, 0xE579, 0x9344, + 0xE57A, 0x9345, 0xE57B, 0x9346, 0xE57C, 0x9347, 0xE57D, 0x9348, + 0xE57E, 0x9349, 0xE580, 0x934A, 0xE581, 0x934B, 0xE582, 0x934C, + 0xE583, 0x934D, 0xE584, 0x934E, 0xE585, 0x934F, 0xE586, 0x9350, + 0xE587, 0x9351, 0xE588, 0x9352, 0xE589, 0x9353, 0xE58A, 0x9354, + 0xE58B, 0x9355, 0xE58C, 0x9356, 0xE58D, 0x9357, 0xE58E, 0x9358, + 0xE58F, 0x9359, 0xE590, 0x935A, 0xE591, 0x935B, 0xE592, 0x935C, + 0xE593, 0x935D, 0xE594, 0x935E, 0xE595, 0x935F, 0xE596, 0x9360, + 0xE597, 0x9361, 0xE598, 0x9362, 0xE599, 0x9363, 0xE59A, 0x9364, + 0xE59B, 0x9365, 0xE59C, 0x9366, 0xE59D, 0x9367, 0xE59E, 0x9368, + 0xE59F, 0x9369, 0xE5A0, 0x936B, 0xE5A1, 0x6FC9, 0xE5A2, 0x6FA7, + 0xE5A3, 0x6FB9, 0xE5A4, 0x6FB6, 0xE5A5, 0x6FC2, 0xE5A6, 0x6FE1, + 0xE5A7, 0x6FEE, 0xE5A8, 0x6FDE, 0xE5A9, 0x6FE0, 0xE5AA, 0x6FEF, + 0xE5AB, 0x701A, 0xE5AC, 0x7023, 0xE5AD, 0x701B, 0xE5AE, 0x7039, + 0xE5AF, 0x7035, 0xE5B0, 0x704F, 0xE5B1, 0x705E, 0xE5B2, 0x5B80, + 0xE5B3, 0x5B84, 0xE5B4, 0x5B95, 0xE5B5, 0x5B93, 0xE5B6, 0x5BA5, + 0xE5B7, 0x5BB8, 0xE5B8, 0x752F, 0xE5B9, 0x9A9E, 0xE5BA, 0x6434, + 0xE5BB, 0x5BE4, 0xE5BC, 0x5BEE, 0xE5BD, 0x8930, 0xE5BE, 0x5BF0, + 0xE5BF, 0x8E47, 0xE5C0, 0x8B07, 0xE5C1, 0x8FB6, 0xE5C2, 0x8FD3, + 0xE5C3, 0x8FD5, 0xE5C4, 0x8FE5, 0xE5C5, 0x8FEE, 0xE5C6, 0x8FE4, + 0xE5C7, 0x8FE9, 0xE5C8, 0x8FE6, 0xE5C9, 0x8FF3, 0xE5CA, 0x8FE8, + 0xE5CB, 0x9005, 0xE5CC, 0x9004, 0xE5CD, 0x900B, 0xE5CE, 0x9026, + 0xE5CF, 0x9011, 0xE5D0, 0x900D, 0xE5D1, 0x9016, 0xE5D2, 0x9021, + 0xE5D3, 0x9035, 0xE5D4, 0x9036, 0xE5D5, 0x902D, 0xE5D6, 0x902F, + 0xE5D7, 0x9044, 0xE5D8, 0x9051, 0xE5D9, 0x9052, 0xE5DA, 0x9050, + 0xE5DB, 0x9068, 0xE5DC, 0x9058, 0xE5DD, 0x9062, 0xE5DE, 0x905B, + 0xE5DF, 0x66B9, 0xE5E0, 0x9074, 0xE5E1, 0x907D, 0xE5E2, 0x9082, + 0xE5E3, 0x9088, 0xE5E4, 0x9083, 0xE5E5, 0x908B, 0xE5E6, 0x5F50, + 0xE5E7, 0x5F57, 0xE5E8, 0x5F56, 0xE5E9, 0x5F58, 0xE5EA, 0x5C3B, + 0xE5EB, 0x54AB, 0xE5EC, 0x5C50, 0xE5ED, 0x5C59, 0xE5EE, 0x5B71, + 0xE5EF, 0x5C63, 0xE5F0, 0x5C66, 0xE5F1, 0x7FBC, 0xE5F2, 0x5F2A, + 0xE5F3, 0x5F29, 0xE5F4, 0x5F2D, 0xE5F5, 0x8274, 0xE5F6, 0x5F3C, + 0xE5F7, 0x9B3B, 0xE5F8, 0x5C6E, 0xE5F9, 0x5981, 0xE5FA, 0x5983, + 0xE5FB, 0x598D, 0xE5FC, 0x59A9, 0xE5FD, 0x59AA, 0xE5FE, 0x59A3, + 0xE640, 0x936C, 0xE641, 0x936D, 0xE642, 0x936E, 0xE643, 0x936F, + 0xE644, 0x9370, 0xE645, 0x9371, 0xE646, 0x9372, 0xE647, 0x9373, + 0xE648, 0x9374, 0xE649, 0x9375, 0xE64A, 0x9376, 0xE64B, 0x9377, + 0xE64C, 0x9378, 0xE64D, 0x9379, 0xE64E, 0x937A, 0xE64F, 0x937B, + 0xE650, 0x937C, 0xE651, 0x937D, 0xE652, 0x937E, 0xE653, 0x937F, + 0xE654, 0x9380, 0xE655, 0x9381, 0xE656, 0x9382, 0xE657, 0x9383, + 0xE658, 0x9384, 0xE659, 0x9385, 0xE65A, 0x9386, 0xE65B, 0x9387, + 0xE65C, 0x9388, 0xE65D, 0x9389, 0xE65E, 0x938A, 0xE65F, 0x938B, + 0xE660, 0x938C, 0xE661, 0x938D, 0xE662, 0x938E, 0xE663, 0x9390, + 0xE664, 0x9391, 0xE665, 0x9392, 0xE666, 0x9393, 0xE667, 0x9394, + 0xE668, 0x9395, 0xE669, 0x9396, 0xE66A, 0x9397, 0xE66B, 0x9398, + 0xE66C, 0x9399, 0xE66D, 0x939A, 0xE66E, 0x939B, 0xE66F, 0x939C, + 0xE670, 0x939D, 0xE671, 0x939E, 0xE672, 0x939F, 0xE673, 0x93A0, + 0xE674, 0x93A1, 0xE675, 0x93A2, 0xE676, 0x93A3, 0xE677, 0x93A4, + 0xE678, 0x93A5, 0xE679, 0x93A6, 0xE67A, 0x93A7, 0xE67B, 0x93A8, + 0xE67C, 0x93A9, 0xE67D, 0x93AA, 0xE67E, 0x93AB, 0xE680, 0x93AC, + 0xE681, 0x93AD, 0xE682, 0x93AE, 0xE683, 0x93AF, 0xE684, 0x93B0, + 0xE685, 0x93B1, 0xE686, 0x93B2, 0xE687, 0x93B3, 0xE688, 0x93B4, + 0xE689, 0x93B5, 0xE68A, 0x93B6, 0xE68B, 0x93B7, 0xE68C, 0x93B8, + 0xE68D, 0x93B9, 0xE68E, 0x93BA, 0xE68F, 0x93BB, 0xE690, 0x93BC, + 0xE691, 0x93BD, 0xE692, 0x93BE, 0xE693, 0x93BF, 0xE694, 0x93C0, + 0xE695, 0x93C1, 0xE696, 0x93C2, 0xE697, 0x93C3, 0xE698, 0x93C4, + 0xE699, 0x93C5, 0xE69A, 0x93C6, 0xE69B, 0x93C7, 0xE69C, 0x93C8, + 0xE69D, 0x93C9, 0xE69E, 0x93CB, 0xE69F, 0x93CC, 0xE6A0, 0x93CD, + 0xE6A1, 0x5997, 0xE6A2, 0x59CA, 0xE6A3, 0x59AB, 0xE6A4, 0x599E, + 0xE6A5, 0x59A4, 0xE6A6, 0x59D2, 0xE6A7, 0x59B2, 0xE6A8, 0x59AF, + 0xE6A9, 0x59D7, 0xE6AA, 0x59BE, 0xE6AB, 0x5A05, 0xE6AC, 0x5A06, + 0xE6AD, 0x59DD, 0xE6AE, 0x5A08, 0xE6AF, 0x59E3, 0xE6B0, 0x59D8, + 0xE6B1, 0x59F9, 0xE6B2, 0x5A0C, 0xE6B3, 0x5A09, 0xE6B4, 0x5A32, + 0xE6B5, 0x5A34, 0xE6B6, 0x5A11, 0xE6B7, 0x5A23, 0xE6B8, 0x5A13, + 0xE6B9, 0x5A40, 0xE6BA, 0x5A67, 0xE6BB, 0x5A4A, 0xE6BC, 0x5A55, + 0xE6BD, 0x5A3C, 0xE6BE, 0x5A62, 0xE6BF, 0x5A75, 0xE6C0, 0x80EC, + 0xE6C1, 0x5AAA, 0xE6C2, 0x5A9B, 0xE6C3, 0x5A77, 0xE6C4, 0x5A7A, + 0xE6C5, 0x5ABE, 0xE6C6, 0x5AEB, 0xE6C7, 0x5AB2, 0xE6C8, 0x5AD2, + 0xE6C9, 0x5AD4, 0xE6CA, 0x5AB8, 0xE6CB, 0x5AE0, 0xE6CC, 0x5AE3, + 0xE6CD, 0x5AF1, 0xE6CE, 0x5AD6, 0xE6CF, 0x5AE6, 0xE6D0, 0x5AD8, + 0xE6D1, 0x5ADC, 0xE6D2, 0x5B09, 0xE6D3, 0x5B17, 0xE6D4, 0x5B16, + 0xE6D5, 0x5B32, 0xE6D6, 0x5B37, 0xE6D7, 0x5B40, 0xE6D8, 0x5C15, + 0xE6D9, 0x5C1C, 0xE6DA, 0x5B5A, 0xE6DB, 0x5B65, 0xE6DC, 0x5B73, + 0xE6DD, 0x5B51, 0xE6DE, 0x5B53, 0xE6DF, 0x5B62, 0xE6E0, 0x9A75, + 0xE6E1, 0x9A77, 0xE6E2, 0x9A78, 0xE6E3, 0x9A7A, 0xE6E4, 0x9A7F, + 0xE6E5, 0x9A7D, 0xE6E6, 0x9A80, 0xE6E7, 0x9A81, 0xE6E8, 0x9A85, + 0xE6E9, 0x9A88, 0xE6EA, 0x9A8A, 0xE6EB, 0x9A90, 0xE6EC, 0x9A92, + 0xE6ED, 0x9A93, 0xE6EE, 0x9A96, 0xE6EF, 0x9A98, 0xE6F0, 0x9A9B, + 0xE6F1, 0x9A9C, 0xE6F2, 0x9A9D, 0xE6F3, 0x9A9F, 0xE6F4, 0x9AA0, + 0xE6F5, 0x9AA2, 0xE6F6, 0x9AA3, 0xE6F7, 0x9AA5, 0xE6F8, 0x9AA7, + 0xE6F9, 0x7E9F, 0xE6FA, 0x7EA1, 0xE6FB, 0x7EA3, 0xE6FC, 0x7EA5, + 0xE6FD, 0x7EA8, 0xE6FE, 0x7EA9, 0xE740, 0x93CE, 0xE741, 0x93CF, + 0xE742, 0x93D0, 0xE743, 0x93D1, 0xE744, 0x93D2, 0xE745, 0x93D3, + 0xE746, 0x93D4, 0xE747, 0x93D5, 0xE748, 0x93D7, 0xE749, 0x93D8, + 0xE74A, 0x93D9, 0xE74B, 0x93DA, 0xE74C, 0x93DB, 0xE74D, 0x93DC, + 0xE74E, 0x93DD, 0xE74F, 0x93DE, 0xE750, 0x93DF, 0xE751, 0x93E0, + 0xE752, 0x93E1, 0xE753, 0x93E2, 0xE754, 0x93E3, 0xE755, 0x93E4, + 0xE756, 0x93E5, 0xE757, 0x93E6, 0xE758, 0x93E7, 0xE759, 0x93E8, + 0xE75A, 0x93E9, 0xE75B, 0x93EA, 0xE75C, 0x93EB, 0xE75D, 0x93EC, + 0xE75E, 0x93ED, 0xE75F, 0x93EE, 0xE760, 0x93EF, 0xE761, 0x93F0, + 0xE762, 0x93F1, 0xE763, 0x93F2, 0xE764, 0x93F3, 0xE765, 0x93F4, + 0xE766, 0x93F5, 0xE767, 0x93F6, 0xE768, 0x93F7, 0xE769, 0x93F8, + 0xE76A, 0x93F9, 0xE76B, 0x93FA, 0xE76C, 0x93FB, 0xE76D, 0x93FC, + 0xE76E, 0x93FD, 0xE76F, 0x93FE, 0xE770, 0x93FF, 0xE771, 0x9400, + 0xE772, 0x9401, 0xE773, 0x9402, 0xE774, 0x9403, 0xE775, 0x9404, + 0xE776, 0x9405, 0xE777, 0x9406, 0xE778, 0x9407, 0xE779, 0x9408, + 0xE77A, 0x9409, 0xE77B, 0x940A, 0xE77C, 0x940B, 0xE77D, 0x940C, + 0xE77E, 0x940D, 0xE780, 0x940E, 0xE781, 0x940F, 0xE782, 0x9410, + 0xE783, 0x9411, 0xE784, 0x9412, 0xE785, 0x9413, 0xE786, 0x9414, + 0xE787, 0x9415, 0xE788, 0x9416, 0xE789, 0x9417, 0xE78A, 0x9418, + 0xE78B, 0x9419, 0xE78C, 0x941A, 0xE78D, 0x941B, 0xE78E, 0x941C, + 0xE78F, 0x941D, 0xE790, 0x941E, 0xE791, 0x941F, 0xE792, 0x9420, + 0xE793, 0x9421, 0xE794, 0x9422, 0xE795, 0x9423, 0xE796, 0x9424, + 0xE797, 0x9425, 0xE798, 0x9426, 0xE799, 0x9427, 0xE79A, 0x9428, + 0xE79B, 0x9429, 0xE79C, 0x942A, 0xE79D, 0x942B, 0xE79E, 0x942C, + 0xE79F, 0x942D, 0xE7A0, 0x942E, 0xE7A1, 0x7EAD, 0xE7A2, 0x7EB0, + 0xE7A3, 0x7EBE, 0xE7A4, 0x7EC0, 0xE7A5, 0x7EC1, 0xE7A6, 0x7EC2, + 0xE7A7, 0x7EC9, 0xE7A8, 0x7ECB, 0xE7A9, 0x7ECC, 0xE7AA, 0x7ED0, + 0xE7AB, 0x7ED4, 0xE7AC, 0x7ED7, 0xE7AD, 0x7EDB, 0xE7AE, 0x7EE0, + 0xE7AF, 0x7EE1, 0xE7B0, 0x7EE8, 0xE7B1, 0x7EEB, 0xE7B2, 0x7EEE, + 0xE7B3, 0x7EEF, 0xE7B4, 0x7EF1, 0xE7B5, 0x7EF2, 0xE7B6, 0x7F0D, + 0xE7B7, 0x7EF6, 0xE7B8, 0x7EFA, 0xE7B9, 0x7EFB, 0xE7BA, 0x7EFE, + 0xE7BB, 0x7F01, 0xE7BC, 0x7F02, 0xE7BD, 0x7F03, 0xE7BE, 0x7F07, + 0xE7BF, 0x7F08, 0xE7C0, 0x7F0B, 0xE7C1, 0x7F0C, 0xE7C2, 0x7F0F, + 0xE7C3, 0x7F11, 0xE7C4, 0x7F12, 0xE7C5, 0x7F17, 0xE7C6, 0x7F19, + 0xE7C7, 0x7F1C, 0xE7C8, 0x7F1B, 0xE7C9, 0x7F1F, 0xE7CA, 0x7F21, + 0xE7CB, 0x7F22, 0xE7CC, 0x7F23, 0xE7CD, 0x7F24, 0xE7CE, 0x7F25, + 0xE7CF, 0x7F26, 0xE7D0, 0x7F27, 0xE7D1, 0x7F2A, 0xE7D2, 0x7F2B, + 0xE7D3, 0x7F2C, 0xE7D4, 0x7F2D, 0xE7D5, 0x7F2F, 0xE7D6, 0x7F30, + 0xE7D7, 0x7F31, 0xE7D8, 0x7F32, 0xE7D9, 0x7F33, 0xE7DA, 0x7F35, + 0xE7DB, 0x5E7A, 0xE7DC, 0x757F, 0xE7DD, 0x5DDB, 0xE7DE, 0x753E, + 0xE7DF, 0x9095, 0xE7E0, 0x738E, 0xE7E1, 0x7391, 0xE7E2, 0x73AE, + 0xE7E3, 0x73A2, 0xE7E4, 0x739F, 0xE7E5, 0x73CF, 0xE7E6, 0x73C2, + 0xE7E7, 0x73D1, 0xE7E8, 0x73B7, 0xE7E9, 0x73B3, 0xE7EA, 0x73C0, + 0xE7EB, 0x73C9, 0xE7EC, 0x73C8, 0xE7ED, 0x73E5, 0xE7EE, 0x73D9, + 0xE7EF, 0x987C, 0xE7F0, 0x740A, 0xE7F1, 0x73E9, 0xE7F2, 0x73E7, + 0xE7F3, 0x73DE, 0xE7F4, 0x73BA, 0xE7F5, 0x73F2, 0xE7F6, 0x740F, + 0xE7F7, 0x742A, 0xE7F8, 0x745B, 0xE7F9, 0x7426, 0xE7FA, 0x7425, + 0xE7FB, 0x7428, 0xE7FC, 0x7430, 0xE7FD, 0x742E, 0xE7FE, 0x742C, + 0xE840, 0x942F, 0xE841, 0x9430, 0xE842, 0x9431, 0xE843, 0x9432, + 0xE844, 0x9433, 0xE845, 0x9434, 0xE846, 0x9435, 0xE847, 0x9436, + 0xE848, 0x9437, 0xE849, 0x9438, 0xE84A, 0x9439, 0xE84B, 0x943A, + 0xE84C, 0x943B, 0xE84D, 0x943C, 0xE84E, 0x943D, 0xE84F, 0x943F, + 0xE850, 0x9440, 0xE851, 0x9441, 0xE852, 0x9442, 0xE853, 0x9443, + 0xE854, 0x9444, 0xE855, 0x9445, 0xE856, 0x9446, 0xE857, 0x9447, + 0xE858, 0x9448, 0xE859, 0x9449, 0xE85A, 0x944A, 0xE85B, 0x944B, + 0xE85C, 0x944C, 0xE85D, 0x944D, 0xE85E, 0x944E, 0xE85F, 0x944F, + 0xE860, 0x9450, 0xE861, 0x9451, 0xE862, 0x9452, 0xE863, 0x9453, + 0xE864, 0x9454, 0xE865, 0x9455, 0xE866, 0x9456, 0xE867, 0x9457, + 0xE868, 0x9458, 0xE869, 0x9459, 0xE86A, 0x945A, 0xE86B, 0x945B, + 0xE86C, 0x945C, 0xE86D, 0x945D, 0xE86E, 0x945E, 0xE86F, 0x945F, + 0xE870, 0x9460, 0xE871, 0x9461, 0xE872, 0x9462, 0xE873, 0x9463, + 0xE874, 0x9464, 0xE875, 0x9465, 0xE876, 0x9466, 0xE877, 0x9467, + 0xE878, 0x9468, 0xE879, 0x9469, 0xE87A, 0x946A, 0xE87B, 0x946C, + 0xE87C, 0x946D, 0xE87D, 0x946E, 0xE87E, 0x946F, 0xE880, 0x9470, + 0xE881, 0x9471, 0xE882, 0x9472, 0xE883, 0x9473, 0xE884, 0x9474, + 0xE885, 0x9475, 0xE886, 0x9476, 0xE887, 0x9477, 0xE888, 0x9478, + 0xE889, 0x9479, 0xE88A, 0x947A, 0xE88B, 0x947B, 0xE88C, 0x947C, + 0xE88D, 0x947D, 0xE88E, 0x947E, 0xE88F, 0x947F, 0xE890, 0x9480, + 0xE891, 0x9481, 0xE892, 0x9482, 0xE893, 0x9483, 0xE894, 0x9484, + 0xE895, 0x9491, 0xE896, 0x9496, 0xE897, 0x9498, 0xE898, 0x94C7, + 0xE899, 0x94CF, 0xE89A, 0x94D3, 0xE89B, 0x94D4, 0xE89C, 0x94DA, + 0xE89D, 0x94E6, 0xE89E, 0x94FB, 0xE89F, 0x951C, 0xE8A0, 0x9520, + 0xE8A1, 0x741B, 0xE8A2, 0x741A, 0xE8A3, 0x7441, 0xE8A4, 0x745C, + 0xE8A5, 0x7457, 0xE8A6, 0x7455, 0xE8A7, 0x7459, 0xE8A8, 0x7477, + 0xE8A9, 0x746D, 0xE8AA, 0x747E, 0xE8AB, 0x749C, 0xE8AC, 0x748E, + 0xE8AD, 0x7480, 0xE8AE, 0x7481, 0xE8AF, 0x7487, 0xE8B0, 0x748B, + 0xE8B1, 0x749E, 0xE8B2, 0x74A8, 0xE8B3, 0x74A9, 0xE8B4, 0x7490, + 0xE8B5, 0x74A7, 0xE8B6, 0x74D2, 0xE8B7, 0x74BA, 0xE8B8, 0x97EA, + 0xE8B9, 0x97EB, 0xE8BA, 0x97EC, 0xE8BB, 0x674C, 0xE8BC, 0x6753, + 0xE8BD, 0x675E, 0xE8BE, 0x6748, 0xE8BF, 0x6769, 0xE8C0, 0x67A5, + 0xE8C1, 0x6787, 0xE8C2, 0x676A, 0xE8C3, 0x6773, 0xE8C4, 0x6798, + 0xE8C5, 0x67A7, 0xE8C6, 0x6775, 0xE8C7, 0x67A8, 0xE8C8, 0x679E, + 0xE8C9, 0x67AD, 0xE8CA, 0x678B, 0xE8CB, 0x6777, 0xE8CC, 0x677C, + 0xE8CD, 0x67F0, 0xE8CE, 0x6809, 0xE8CF, 0x67D8, 0xE8D0, 0x680A, + 0xE8D1, 0x67E9, 0xE8D2, 0x67B0, 0xE8D3, 0x680C, 0xE8D4, 0x67D9, + 0xE8D5, 0x67B5, 0xE8D6, 0x67DA, 0xE8D7, 0x67B3, 0xE8D8, 0x67DD, + 0xE8D9, 0x6800, 0xE8DA, 0x67C3, 0xE8DB, 0x67B8, 0xE8DC, 0x67E2, + 0xE8DD, 0x680E, 0xE8DE, 0x67C1, 0xE8DF, 0x67FD, 0xE8E0, 0x6832, + 0xE8E1, 0x6833, 0xE8E2, 0x6860, 0xE8E3, 0x6861, 0xE8E4, 0x684E, + 0xE8E5, 0x6862, 0xE8E6, 0x6844, 0xE8E7, 0x6864, 0xE8E8, 0x6883, + 0xE8E9, 0x681D, 0xE8EA, 0x6855, 0xE8EB, 0x6866, 0xE8EC, 0x6841, + 0xE8ED, 0x6867, 0xE8EE, 0x6840, 0xE8EF, 0x683E, 0xE8F0, 0x684A, + 0xE8F1, 0x6849, 0xE8F2, 0x6829, 0xE8F3, 0x68B5, 0xE8F4, 0x688F, + 0xE8F5, 0x6874, 0xE8F6, 0x6877, 0xE8F7, 0x6893, 0xE8F8, 0x686B, + 0xE8F9, 0x68C2, 0xE8FA, 0x696E, 0xE8FB, 0x68FC, 0xE8FC, 0x691F, + 0xE8FD, 0x6920, 0xE8FE, 0x68F9, 0xE940, 0x9527, 0xE941, 0x9533, + 0xE942, 0x953D, 0xE943, 0x9543, 0xE944, 0x9548, 0xE945, 0x954B, + 0xE946, 0x9555, 0xE947, 0x955A, 0xE948, 0x9560, 0xE949, 0x956E, + 0xE94A, 0x9574, 0xE94B, 0x9575, 0xE94C, 0x9577, 0xE94D, 0x9578, + 0xE94E, 0x9579, 0xE94F, 0x957A, 0xE950, 0x957B, 0xE951, 0x957C, + 0xE952, 0x957D, 0xE953, 0x957E, 0xE954, 0x9580, 0xE955, 0x9581, + 0xE956, 0x9582, 0xE957, 0x9583, 0xE958, 0x9584, 0xE959, 0x9585, + 0xE95A, 0x9586, 0xE95B, 0x9587, 0xE95C, 0x9588, 0xE95D, 0x9589, + 0xE95E, 0x958A, 0xE95F, 0x958B, 0xE960, 0x958C, 0xE961, 0x958D, + 0xE962, 0x958E, 0xE963, 0x958F, 0xE964, 0x9590, 0xE965, 0x9591, + 0xE966, 0x9592, 0xE967, 0x9593, 0xE968, 0x9594, 0xE969, 0x9595, + 0xE96A, 0x9596, 0xE96B, 0x9597, 0xE96C, 0x9598, 0xE96D, 0x9599, + 0xE96E, 0x959A, 0xE96F, 0x959B, 0xE970, 0x959C, 0xE971, 0x959D, + 0xE972, 0x959E, 0xE973, 0x959F, 0xE974, 0x95A0, 0xE975, 0x95A1, + 0xE976, 0x95A2, 0xE977, 0x95A3, 0xE978, 0x95A4, 0xE979, 0x95A5, + 0xE97A, 0x95A6, 0xE97B, 0x95A7, 0xE97C, 0x95A8, 0xE97D, 0x95A9, + 0xE97E, 0x95AA, 0xE980, 0x95AB, 0xE981, 0x95AC, 0xE982, 0x95AD, + 0xE983, 0x95AE, 0xE984, 0x95AF, 0xE985, 0x95B0, 0xE986, 0x95B1, + 0xE987, 0x95B2, 0xE988, 0x95B3, 0xE989, 0x95B4, 0xE98A, 0x95B5, + 0xE98B, 0x95B6, 0xE98C, 0x95B7, 0xE98D, 0x95B8, 0xE98E, 0x95B9, + 0xE98F, 0x95BA, 0xE990, 0x95BB, 0xE991, 0x95BC, 0xE992, 0x95BD, + 0xE993, 0x95BE, 0xE994, 0x95BF, 0xE995, 0x95C0, 0xE996, 0x95C1, + 0xE997, 0x95C2, 0xE998, 0x95C3, 0xE999, 0x95C4, 0xE99A, 0x95C5, + 0xE99B, 0x95C6, 0xE99C, 0x95C7, 0xE99D, 0x95C8, 0xE99E, 0x95C9, + 0xE99F, 0x95CA, 0xE9A0, 0x95CB, 0xE9A1, 0x6924, 0xE9A2, 0x68F0, + 0xE9A3, 0x690B, 0xE9A4, 0x6901, 0xE9A5, 0x6957, 0xE9A6, 0x68E3, + 0xE9A7, 0x6910, 0xE9A8, 0x6971, 0xE9A9, 0x6939, 0xE9AA, 0x6960, + 0xE9AB, 0x6942, 0xE9AC, 0x695D, 0xE9AD, 0x6984, 0xE9AE, 0x696B, + 0xE9AF, 0x6980, 0xE9B0, 0x6998, 0xE9B1, 0x6978, 0xE9B2, 0x6934, + 0xE9B3, 0x69CC, 0xE9B4, 0x6987, 0xE9B5, 0x6988, 0xE9B6, 0x69CE, + 0xE9B7, 0x6989, 0xE9B8, 0x6966, 0xE9B9, 0x6963, 0xE9BA, 0x6979, + 0xE9BB, 0x699B, 0xE9BC, 0x69A7, 0xE9BD, 0x69BB, 0xE9BE, 0x69AB, + 0xE9BF, 0x69AD, 0xE9C0, 0x69D4, 0xE9C1, 0x69B1, 0xE9C2, 0x69C1, + 0xE9C3, 0x69CA, 0xE9C4, 0x69DF, 0xE9C5, 0x6995, 0xE9C6, 0x69E0, + 0xE9C7, 0x698D, 0xE9C8, 0x69FF, 0xE9C9, 0x6A2F, 0xE9CA, 0x69ED, + 0xE9CB, 0x6A17, 0xE9CC, 0x6A18, 0xE9CD, 0x6A65, 0xE9CE, 0x69F2, + 0xE9CF, 0x6A44, 0xE9D0, 0x6A3E, 0xE9D1, 0x6AA0, 0xE9D2, 0x6A50, + 0xE9D3, 0x6A5B, 0xE9D4, 0x6A35, 0xE9D5, 0x6A8E, 0xE9D6, 0x6A79, + 0xE9D7, 0x6A3D, 0xE9D8, 0x6A28, 0xE9D9, 0x6A58, 0xE9DA, 0x6A7C, + 0xE9DB, 0x6A91, 0xE9DC, 0x6A90, 0xE9DD, 0x6AA9, 0xE9DE, 0x6A97, + 0xE9DF, 0x6AAB, 0xE9E0, 0x7337, 0xE9E1, 0x7352, 0xE9E2, 0x6B81, + 0xE9E3, 0x6B82, 0xE9E4, 0x6B87, 0xE9E5, 0x6B84, 0xE9E6, 0x6B92, + 0xE9E7, 0x6B93, 0xE9E8, 0x6B8D, 0xE9E9, 0x6B9A, 0xE9EA, 0x6B9B, + 0xE9EB, 0x6BA1, 0xE9EC, 0x6BAA, 0xE9ED, 0x8F6B, 0xE9EE, 0x8F6D, + 0xE9EF, 0x8F71, 0xE9F0, 0x8F72, 0xE9F1, 0x8F73, 0xE9F2, 0x8F75, + 0xE9F3, 0x8F76, 0xE9F4, 0x8F78, 0xE9F5, 0x8F77, 0xE9F6, 0x8F79, + 0xE9F7, 0x8F7A, 0xE9F8, 0x8F7C, 0xE9F9, 0x8F7E, 0xE9FA, 0x8F81, + 0xE9FB, 0x8F82, 0xE9FC, 0x8F84, 0xE9FD, 0x8F87, 0xE9FE, 0x8F8B, + 0xEA40, 0x95CC, 0xEA41, 0x95CD, 0xEA42, 0x95CE, 0xEA43, 0x95CF, + 0xEA44, 0x95D0, 0xEA45, 0x95D1, 0xEA46, 0x95D2, 0xEA47, 0x95D3, + 0xEA48, 0x95D4, 0xEA49, 0x95D5, 0xEA4A, 0x95D6, 0xEA4B, 0x95D7, + 0xEA4C, 0x95D8, 0xEA4D, 0x95D9, 0xEA4E, 0x95DA, 0xEA4F, 0x95DB, + 0xEA50, 0x95DC, 0xEA51, 0x95DD, 0xEA52, 0x95DE, 0xEA53, 0x95DF, + 0xEA54, 0x95E0, 0xEA55, 0x95E1, 0xEA56, 0x95E2, 0xEA57, 0x95E3, + 0xEA58, 0x95E4, 0xEA59, 0x95E5, 0xEA5A, 0x95E6, 0xEA5B, 0x95E7, + 0xEA5C, 0x95EC, 0xEA5D, 0x95FF, 0xEA5E, 0x9607, 0xEA5F, 0x9613, + 0xEA60, 0x9618, 0xEA61, 0x961B, 0xEA62, 0x961E, 0xEA63, 0x9620, + 0xEA64, 0x9623, 0xEA65, 0x9624, 0xEA66, 0x9625, 0xEA67, 0x9626, + 0xEA68, 0x9627, 0xEA69, 0x9628, 0xEA6A, 0x9629, 0xEA6B, 0x962B, + 0xEA6C, 0x962C, 0xEA6D, 0x962D, 0xEA6E, 0x962F, 0xEA6F, 0x9630, + 0xEA70, 0x9637, 0xEA71, 0x9638, 0xEA72, 0x9639, 0xEA73, 0x963A, + 0xEA74, 0x963E, 0xEA75, 0x9641, 0xEA76, 0x9643, 0xEA77, 0x964A, + 0xEA78, 0x964E, 0xEA79, 0x964F, 0xEA7A, 0x9651, 0xEA7B, 0x9652, + 0xEA7C, 0x9653, 0xEA7D, 0x9656, 0xEA7E, 0x9657, 0xEA80, 0x9658, + 0xEA81, 0x9659, 0xEA82, 0x965A, 0xEA83, 0x965C, 0xEA84, 0x965D, + 0xEA85, 0x965E, 0xEA86, 0x9660, 0xEA87, 0x9663, 0xEA88, 0x9665, + 0xEA89, 0x9666, 0xEA8A, 0x966B, 0xEA8B, 0x966D, 0xEA8C, 0x966E, + 0xEA8D, 0x966F, 0xEA8E, 0x9670, 0xEA8F, 0x9671, 0xEA90, 0x9673, + 0xEA91, 0x9678, 0xEA92, 0x9679, 0xEA93, 0x967A, 0xEA94, 0x967B, + 0xEA95, 0x967C, 0xEA96, 0x967D, 0xEA97, 0x967E, 0xEA98, 0x967F, + 0xEA99, 0x9680, 0xEA9A, 0x9681, 0xEA9B, 0x9682, 0xEA9C, 0x9683, + 0xEA9D, 0x9684, 0xEA9E, 0x9687, 0xEA9F, 0x9689, 0xEAA0, 0x968A, + 0xEAA1, 0x8F8D, 0xEAA2, 0x8F8E, 0xEAA3, 0x8F8F, 0xEAA4, 0x8F98, + 0xEAA5, 0x8F9A, 0xEAA6, 0x8ECE, 0xEAA7, 0x620B, 0xEAA8, 0x6217, + 0xEAA9, 0x621B, 0xEAAA, 0x621F, 0xEAAB, 0x6222, 0xEAAC, 0x6221, + 0xEAAD, 0x6225, 0xEAAE, 0x6224, 0xEAAF, 0x622C, 0xEAB0, 0x81E7, + 0xEAB1, 0x74EF, 0xEAB2, 0x74F4, 0xEAB3, 0x74FF, 0xEAB4, 0x750F, + 0xEAB5, 0x7511, 0xEAB6, 0x7513, 0xEAB7, 0x6534, 0xEAB8, 0x65EE, + 0xEAB9, 0x65EF, 0xEABA, 0x65F0, 0xEABB, 0x660A, 0xEABC, 0x6619, + 0xEABD, 0x6772, 0xEABE, 0x6603, 0xEABF, 0x6615, 0xEAC0, 0x6600, + 0xEAC1, 0x7085, 0xEAC2, 0x66F7, 0xEAC3, 0x661D, 0xEAC4, 0x6634, + 0xEAC5, 0x6631, 0xEAC6, 0x6636, 0xEAC7, 0x6635, 0xEAC8, 0x8006, + 0xEAC9, 0x665F, 0xEACA, 0x6654, 0xEACB, 0x6641, 0xEACC, 0x664F, + 0xEACD, 0x6656, 0xEACE, 0x6661, 0xEACF, 0x6657, 0xEAD0, 0x6677, + 0xEAD1, 0x6684, 0xEAD2, 0x668C, 0xEAD3, 0x66A7, 0xEAD4, 0x669D, + 0xEAD5, 0x66BE, 0xEAD6, 0x66DB, 0xEAD7, 0x66DC, 0xEAD8, 0x66E6, + 0xEAD9, 0x66E9, 0xEADA, 0x8D32, 0xEADB, 0x8D33, 0xEADC, 0x8D36, + 0xEADD, 0x8D3B, 0xEADE, 0x8D3D, 0xEADF, 0x8D40, 0xEAE0, 0x8D45, + 0xEAE1, 0x8D46, 0xEAE2, 0x8D48, 0xEAE3, 0x8D49, 0xEAE4, 0x8D47, + 0xEAE5, 0x8D4D, 0xEAE6, 0x8D55, 0xEAE7, 0x8D59, 0xEAE8, 0x89C7, + 0xEAE9, 0x89CA, 0xEAEA, 0x89CB, 0xEAEB, 0x89CC, 0xEAEC, 0x89CE, + 0xEAED, 0x89CF, 0xEAEE, 0x89D0, 0xEAEF, 0x89D1, 0xEAF0, 0x726E, + 0xEAF1, 0x729F, 0xEAF2, 0x725D, 0xEAF3, 0x7266, 0xEAF4, 0x726F, + 0xEAF5, 0x727E, 0xEAF6, 0x727F, 0xEAF7, 0x7284, 0xEAF8, 0x728B, + 0xEAF9, 0x728D, 0xEAFA, 0x728F, 0xEAFB, 0x7292, 0xEAFC, 0x6308, + 0xEAFD, 0x6332, 0xEAFE, 0x63B0, 0xEB40, 0x968C, 0xEB41, 0x968E, + 0xEB42, 0x9691, 0xEB43, 0x9692, 0xEB44, 0x9693, 0xEB45, 0x9695, + 0xEB46, 0x9696, 0xEB47, 0x969A, 0xEB48, 0x969B, 0xEB49, 0x969D, + 0xEB4A, 0x969E, 0xEB4B, 0x969F, 0xEB4C, 0x96A0, 0xEB4D, 0x96A1, + 0xEB4E, 0x96A2, 0xEB4F, 0x96A3, 0xEB50, 0x96A4, 0xEB51, 0x96A5, + 0xEB52, 0x96A6, 0xEB53, 0x96A8, 0xEB54, 0x96A9, 0xEB55, 0x96AA, + 0xEB56, 0x96AB, 0xEB57, 0x96AC, 0xEB58, 0x96AD, 0xEB59, 0x96AE, + 0xEB5A, 0x96AF, 0xEB5B, 0x96B1, 0xEB5C, 0x96B2, 0xEB5D, 0x96B4, + 0xEB5E, 0x96B5, 0xEB5F, 0x96B7, 0xEB60, 0x96B8, 0xEB61, 0x96BA, + 0xEB62, 0x96BB, 0xEB63, 0x96BF, 0xEB64, 0x96C2, 0xEB65, 0x96C3, + 0xEB66, 0x96C8, 0xEB67, 0x96CA, 0xEB68, 0x96CB, 0xEB69, 0x96D0, + 0xEB6A, 0x96D1, 0xEB6B, 0x96D3, 0xEB6C, 0x96D4, 0xEB6D, 0x96D6, + 0xEB6E, 0x96D7, 0xEB6F, 0x96D8, 0xEB70, 0x96D9, 0xEB71, 0x96DA, + 0xEB72, 0x96DB, 0xEB73, 0x96DC, 0xEB74, 0x96DD, 0xEB75, 0x96DE, + 0xEB76, 0x96DF, 0xEB77, 0x96E1, 0xEB78, 0x96E2, 0xEB79, 0x96E3, + 0xEB7A, 0x96E4, 0xEB7B, 0x96E5, 0xEB7C, 0x96E6, 0xEB7D, 0x96E7, + 0xEB7E, 0x96EB, 0xEB80, 0x96EC, 0xEB81, 0x96ED, 0xEB82, 0x96EE, + 0xEB83, 0x96F0, 0xEB84, 0x96F1, 0xEB85, 0x96F2, 0xEB86, 0x96F4, + 0xEB87, 0x96F5, 0xEB88, 0x96F8, 0xEB89, 0x96FA, 0xEB8A, 0x96FB, + 0xEB8B, 0x96FC, 0xEB8C, 0x96FD, 0xEB8D, 0x96FF, 0xEB8E, 0x9702, + 0xEB8F, 0x9703, 0xEB90, 0x9705, 0xEB91, 0x970A, 0xEB92, 0x970B, + 0xEB93, 0x970C, 0xEB94, 0x9710, 0xEB95, 0x9711, 0xEB96, 0x9712, + 0xEB97, 0x9714, 0xEB98, 0x9715, 0xEB99, 0x9717, 0xEB9A, 0x9718, + 0xEB9B, 0x9719, 0xEB9C, 0x971A, 0xEB9D, 0x971B, 0xEB9E, 0x971D, + 0xEB9F, 0x971F, 0xEBA0, 0x9720, 0xEBA1, 0x643F, 0xEBA2, 0x64D8, + 0xEBA3, 0x8004, 0xEBA4, 0x6BEA, 0xEBA5, 0x6BF3, 0xEBA6, 0x6BFD, + 0xEBA7, 0x6BF5, 0xEBA8, 0x6BF9, 0xEBA9, 0x6C05, 0xEBAA, 0x6C07, + 0xEBAB, 0x6C06, 0xEBAC, 0x6C0D, 0xEBAD, 0x6C15, 0xEBAE, 0x6C18, + 0xEBAF, 0x6C19, 0xEBB0, 0x6C1A, 0xEBB1, 0x6C21, 0xEBB2, 0x6C29, + 0xEBB3, 0x6C24, 0xEBB4, 0x6C2A, 0xEBB5, 0x6C32, 0xEBB6, 0x6535, + 0xEBB7, 0x6555, 0xEBB8, 0x656B, 0xEBB9, 0x724D, 0xEBBA, 0x7252, + 0xEBBB, 0x7256, 0xEBBC, 0x7230, 0xEBBD, 0x8662, 0xEBBE, 0x5216, + 0xEBBF, 0x809F, 0xEBC0, 0x809C, 0xEBC1, 0x8093, 0xEBC2, 0x80BC, + 0xEBC3, 0x670A, 0xEBC4, 0x80BD, 0xEBC5, 0x80B1, 0xEBC6, 0x80AB, + 0xEBC7, 0x80AD, 0xEBC8, 0x80B4, 0xEBC9, 0x80B7, 0xEBCA, 0x80E7, + 0xEBCB, 0x80E8, 0xEBCC, 0x80E9, 0xEBCD, 0x80EA, 0xEBCE, 0x80DB, + 0xEBCF, 0x80C2, 0xEBD0, 0x80C4, 0xEBD1, 0x80D9, 0xEBD2, 0x80CD, + 0xEBD3, 0x80D7, 0xEBD4, 0x6710, 0xEBD5, 0x80DD, 0xEBD6, 0x80EB, + 0xEBD7, 0x80F1, 0xEBD8, 0x80F4, 0xEBD9, 0x80ED, 0xEBDA, 0x810D, + 0xEBDB, 0x810E, 0xEBDC, 0x80F2, 0xEBDD, 0x80FC, 0xEBDE, 0x6715, + 0xEBDF, 0x8112, 0xEBE0, 0x8C5A, 0xEBE1, 0x8136, 0xEBE2, 0x811E, + 0xEBE3, 0x812C, 0xEBE4, 0x8118, 0xEBE5, 0x8132, 0xEBE6, 0x8148, + 0xEBE7, 0x814C, 0xEBE8, 0x8153, 0xEBE9, 0x8174, 0xEBEA, 0x8159, + 0xEBEB, 0x815A, 0xEBEC, 0x8171, 0xEBED, 0x8160, 0xEBEE, 0x8169, + 0xEBEF, 0x817C, 0xEBF0, 0x817D, 0xEBF1, 0x816D, 0xEBF2, 0x8167, + 0xEBF3, 0x584D, 0xEBF4, 0x5AB5, 0xEBF5, 0x8188, 0xEBF6, 0x8182, + 0xEBF7, 0x8191, 0xEBF8, 0x6ED5, 0xEBF9, 0x81A3, 0xEBFA, 0x81AA, + 0xEBFB, 0x81CC, 0xEBFC, 0x6726, 0xEBFD, 0x81CA, 0xEBFE, 0x81BB, + 0xEC40, 0x9721, 0xEC41, 0x9722, 0xEC42, 0x9723, 0xEC43, 0x9724, + 0xEC44, 0x9725, 0xEC45, 0x9726, 0xEC46, 0x9727, 0xEC47, 0x9728, + 0xEC48, 0x9729, 0xEC49, 0x972B, 0xEC4A, 0x972C, 0xEC4B, 0x972E, + 0xEC4C, 0x972F, 0xEC4D, 0x9731, 0xEC4E, 0x9733, 0xEC4F, 0x9734, + 0xEC50, 0x9735, 0xEC51, 0x9736, 0xEC52, 0x9737, 0xEC53, 0x973A, + 0xEC54, 0x973B, 0xEC55, 0x973C, 0xEC56, 0x973D, 0xEC57, 0x973F, + 0xEC58, 0x9740, 0xEC59, 0x9741, 0xEC5A, 0x9742, 0xEC5B, 0x9743, + 0xEC5C, 0x9744, 0xEC5D, 0x9745, 0xEC5E, 0x9746, 0xEC5F, 0x9747, + 0xEC60, 0x9748, 0xEC61, 0x9749, 0xEC62, 0x974A, 0xEC63, 0x974B, + 0xEC64, 0x974C, 0xEC65, 0x974D, 0xEC66, 0x974E, 0xEC67, 0x974F, + 0xEC68, 0x9750, 0xEC69, 0x9751, 0xEC6A, 0x9754, 0xEC6B, 0x9755, + 0xEC6C, 0x9757, 0xEC6D, 0x9758, 0xEC6E, 0x975A, 0xEC6F, 0x975C, + 0xEC70, 0x975D, 0xEC71, 0x975F, 0xEC72, 0x9763, 0xEC73, 0x9764, + 0xEC74, 0x9766, 0xEC75, 0x9767, 0xEC76, 0x9768, 0xEC77, 0x976A, + 0xEC78, 0x976B, 0xEC79, 0x976C, 0xEC7A, 0x976D, 0xEC7B, 0x976E, + 0xEC7C, 0x976F, 0xEC7D, 0x9770, 0xEC7E, 0x9771, 0xEC80, 0x9772, + 0xEC81, 0x9775, 0xEC82, 0x9777, 0xEC83, 0x9778, 0xEC84, 0x9779, + 0xEC85, 0x977A, 0xEC86, 0x977B, 0xEC87, 0x977D, 0xEC88, 0x977E, + 0xEC89, 0x977F, 0xEC8A, 0x9780, 0xEC8B, 0x9781, 0xEC8C, 0x9782, + 0xEC8D, 0x9783, 0xEC8E, 0x9784, 0xEC8F, 0x9786, 0xEC90, 0x9787, + 0xEC91, 0x9788, 0xEC92, 0x9789, 0xEC93, 0x978A, 0xEC94, 0x978C, + 0xEC95, 0x978E, 0xEC96, 0x978F, 0xEC97, 0x9790, 0xEC98, 0x9793, + 0xEC99, 0x9795, 0xEC9A, 0x9796, 0xEC9B, 0x9797, 0xEC9C, 0x9799, + 0xEC9D, 0x979A, 0xEC9E, 0x979B, 0xEC9F, 0x979C, 0xECA0, 0x979D, + 0xECA1, 0x81C1, 0xECA2, 0x81A6, 0xECA3, 0x6B24, 0xECA4, 0x6B37, + 0xECA5, 0x6B39, 0xECA6, 0x6B43, 0xECA7, 0x6B46, 0xECA8, 0x6B59, + 0xECA9, 0x98D1, 0xECAA, 0x98D2, 0xECAB, 0x98D3, 0xECAC, 0x98D5, + 0xECAD, 0x98D9, 0xECAE, 0x98DA, 0xECAF, 0x6BB3, 0xECB0, 0x5F40, + 0xECB1, 0x6BC2, 0xECB2, 0x89F3, 0xECB3, 0x6590, 0xECB4, 0x9F51, + 0xECB5, 0x6593, 0xECB6, 0x65BC, 0xECB7, 0x65C6, 0xECB8, 0x65C4, + 0xECB9, 0x65C3, 0xECBA, 0x65CC, 0xECBB, 0x65CE, 0xECBC, 0x65D2, + 0xECBD, 0x65D6, 0xECBE, 0x7080, 0xECBF, 0x709C, 0xECC0, 0x7096, + 0xECC1, 0x709D, 0xECC2, 0x70BB, 0xECC3, 0x70C0, 0xECC4, 0x70B7, + 0xECC5, 0x70AB, 0xECC6, 0x70B1, 0xECC7, 0x70E8, 0xECC8, 0x70CA, + 0xECC9, 0x7110, 0xECCA, 0x7113, 0xECCB, 0x7116, 0xECCC, 0x712F, + 0xECCD, 0x7131, 0xECCE, 0x7173, 0xECCF, 0x715C, 0xECD0, 0x7168, + 0xECD1, 0x7145, 0xECD2, 0x7172, 0xECD3, 0x714A, 0xECD4, 0x7178, + 0xECD5, 0x717A, 0xECD6, 0x7198, 0xECD7, 0x71B3, 0xECD8, 0x71B5, + 0xECD9, 0x71A8, 0xECDA, 0x71A0, 0xECDB, 0x71E0, 0xECDC, 0x71D4, + 0xECDD, 0x71E7, 0xECDE, 0x71F9, 0xECDF, 0x721D, 0xECE0, 0x7228, + 0xECE1, 0x706C, 0xECE2, 0x7118, 0xECE3, 0x7166, 0xECE4, 0x71B9, + 0xECE5, 0x623E, 0xECE6, 0x623D, 0xECE7, 0x6243, 0xECE8, 0x6248, + 0xECE9, 0x6249, 0xECEA, 0x793B, 0xECEB, 0x7940, 0xECEC, 0x7946, + 0xECED, 0x7949, 0xECEE, 0x795B, 0xECEF, 0x795C, 0xECF0, 0x7953, + 0xECF1, 0x795A, 0xECF2, 0x7962, 0xECF3, 0x7957, 0xECF4, 0x7960, + 0xECF5, 0x796F, 0xECF6, 0x7967, 0xECF7, 0x797A, 0xECF8, 0x7985, + 0xECF9, 0x798A, 0xECFA, 0x799A, 0xECFB, 0x79A7, 0xECFC, 0x79B3, + 0xECFD, 0x5FD1, 0xECFE, 0x5FD0, 0xED40, 0x979E, 0xED41, 0x979F, + 0xED42, 0x97A1, 0xED43, 0x97A2, 0xED44, 0x97A4, 0xED45, 0x97A5, + 0xED46, 0x97A6, 0xED47, 0x97A7, 0xED48, 0x97A8, 0xED49, 0x97A9, + 0xED4A, 0x97AA, 0xED4B, 0x97AC, 0xED4C, 0x97AE, 0xED4D, 0x97B0, + 0xED4E, 0x97B1, 0xED4F, 0x97B3, 0xED50, 0x97B5, 0xED51, 0x97B6, + 0xED52, 0x97B7, 0xED53, 0x97B8, 0xED54, 0x97B9, 0xED55, 0x97BA, + 0xED56, 0x97BB, 0xED57, 0x97BC, 0xED58, 0x97BD, 0xED59, 0x97BE, + 0xED5A, 0x97BF, 0xED5B, 0x97C0, 0xED5C, 0x97C1, 0xED5D, 0x97C2, + 0xED5E, 0x97C3, 0xED5F, 0x97C4, 0xED60, 0x97C5, 0xED61, 0x97C6, + 0xED62, 0x97C7, 0xED63, 0x97C8, 0xED64, 0x97C9, 0xED65, 0x97CA, + 0xED66, 0x97CB, 0xED67, 0x97CC, 0xED68, 0x97CD, 0xED69, 0x97CE, + 0xED6A, 0x97CF, 0xED6B, 0x97D0, 0xED6C, 0x97D1, 0xED6D, 0x97D2, + 0xED6E, 0x97D3, 0xED6F, 0x97D4, 0xED70, 0x97D5, 0xED71, 0x97D6, + 0xED72, 0x97D7, 0xED73, 0x97D8, 0xED74, 0x97D9, 0xED75, 0x97DA, + 0xED76, 0x97DB, 0xED77, 0x97DC, 0xED78, 0x97DD, 0xED79, 0x97DE, + 0xED7A, 0x97DF, 0xED7B, 0x97E0, 0xED7C, 0x97E1, 0xED7D, 0x97E2, + 0xED7E, 0x97E3, 0xED80, 0x97E4, 0xED81, 0x97E5, 0xED82, 0x97E8, + 0xED83, 0x97EE, 0xED84, 0x97EF, 0xED85, 0x97F0, 0xED86, 0x97F1, + 0xED87, 0x97F2, 0xED88, 0x97F4, 0xED89, 0x97F7, 0xED8A, 0x97F8, + 0xED8B, 0x97F9, 0xED8C, 0x97FA, 0xED8D, 0x97FB, 0xED8E, 0x97FC, + 0xED8F, 0x97FD, 0xED90, 0x97FE, 0xED91, 0x97FF, 0xED92, 0x9800, + 0xED93, 0x9801, 0xED94, 0x9802, 0xED95, 0x9803, 0xED96, 0x9804, + 0xED97, 0x9805, 0xED98, 0x9806, 0xED99, 0x9807, 0xED9A, 0x9808, + 0xED9B, 0x9809, 0xED9C, 0x980A, 0xED9D, 0x980B, 0xED9E, 0x980C, + 0xED9F, 0x980D, 0xEDA0, 0x980E, 0xEDA1, 0x603C, 0xEDA2, 0x605D, + 0xEDA3, 0x605A, 0xEDA4, 0x6067, 0xEDA5, 0x6041, 0xEDA6, 0x6059, + 0xEDA7, 0x6063, 0xEDA8, 0x60AB, 0xEDA9, 0x6106, 0xEDAA, 0x610D, + 0xEDAB, 0x615D, 0xEDAC, 0x61A9, 0xEDAD, 0x619D, 0xEDAE, 0x61CB, + 0xEDAF, 0x61D1, 0xEDB0, 0x6206, 0xEDB1, 0x8080, 0xEDB2, 0x807F, + 0xEDB3, 0x6C93, 0xEDB4, 0x6CF6, 0xEDB5, 0x6DFC, 0xEDB6, 0x77F6, + 0xEDB7, 0x77F8, 0xEDB8, 0x7800, 0xEDB9, 0x7809, 0xEDBA, 0x7817, + 0xEDBB, 0x7818, 0xEDBC, 0x7811, 0xEDBD, 0x65AB, 0xEDBE, 0x782D, + 0xEDBF, 0x781C, 0xEDC0, 0x781D, 0xEDC1, 0x7839, 0xEDC2, 0x783A, + 0xEDC3, 0x783B, 0xEDC4, 0x781F, 0xEDC5, 0x783C, 0xEDC6, 0x7825, + 0xEDC7, 0x782C, 0xEDC8, 0x7823, 0xEDC9, 0x7829, 0xEDCA, 0x784E, + 0xEDCB, 0x786D, 0xEDCC, 0x7856, 0xEDCD, 0x7857, 0xEDCE, 0x7826, + 0xEDCF, 0x7850, 0xEDD0, 0x7847, 0xEDD1, 0x784C, 0xEDD2, 0x786A, + 0xEDD3, 0x789B, 0xEDD4, 0x7893, 0xEDD5, 0x789A, 0xEDD6, 0x7887, + 0xEDD7, 0x789C, 0xEDD8, 0x78A1, 0xEDD9, 0x78A3, 0xEDDA, 0x78B2, + 0xEDDB, 0x78B9, 0xEDDC, 0x78A5, 0xEDDD, 0x78D4, 0xEDDE, 0x78D9, + 0xEDDF, 0x78C9, 0xEDE0, 0x78EC, 0xEDE1, 0x78F2, 0xEDE2, 0x7905, + 0xEDE3, 0x78F4, 0xEDE4, 0x7913, 0xEDE5, 0x7924, 0xEDE6, 0x791E, + 0xEDE7, 0x7934, 0xEDE8, 0x9F9B, 0xEDE9, 0x9EF9, 0xEDEA, 0x9EFB, + 0xEDEB, 0x9EFC, 0xEDEC, 0x76F1, 0xEDED, 0x7704, 0xEDEE, 0x770D, + 0xEDEF, 0x76F9, 0xEDF0, 0x7707, 0xEDF1, 0x7708, 0xEDF2, 0x771A, + 0xEDF3, 0x7722, 0xEDF4, 0x7719, 0xEDF5, 0x772D, 0xEDF6, 0x7726, + 0xEDF7, 0x7735, 0xEDF8, 0x7738, 0xEDF9, 0x7750, 0xEDFA, 0x7751, + 0xEDFB, 0x7747, 0xEDFC, 0x7743, 0xEDFD, 0x775A, 0xEDFE, 0x7768, + 0xEE40, 0x980F, 0xEE41, 0x9810, 0xEE42, 0x9811, 0xEE43, 0x9812, + 0xEE44, 0x9813, 0xEE45, 0x9814, 0xEE46, 0x9815, 0xEE47, 0x9816, + 0xEE48, 0x9817, 0xEE49, 0x9818, 0xEE4A, 0x9819, 0xEE4B, 0x981A, + 0xEE4C, 0x981B, 0xEE4D, 0x981C, 0xEE4E, 0x981D, 0xEE4F, 0x981E, + 0xEE50, 0x981F, 0xEE51, 0x9820, 0xEE52, 0x9821, 0xEE53, 0x9822, + 0xEE54, 0x9823, 0xEE55, 0x9824, 0xEE56, 0x9825, 0xEE57, 0x9826, + 0xEE58, 0x9827, 0xEE59, 0x9828, 0xEE5A, 0x9829, 0xEE5B, 0x982A, + 0xEE5C, 0x982B, 0xEE5D, 0x982C, 0xEE5E, 0x982D, 0xEE5F, 0x982E, + 0xEE60, 0x982F, 0xEE61, 0x9830, 0xEE62, 0x9831, 0xEE63, 0x9832, + 0xEE64, 0x9833, 0xEE65, 0x9834, 0xEE66, 0x9835, 0xEE67, 0x9836, + 0xEE68, 0x9837, 0xEE69, 0x9838, 0xEE6A, 0x9839, 0xEE6B, 0x983A, + 0xEE6C, 0x983B, 0xEE6D, 0x983C, 0xEE6E, 0x983D, 0xEE6F, 0x983E, + 0xEE70, 0x983F, 0xEE71, 0x9840, 0xEE72, 0x9841, 0xEE73, 0x9842, + 0xEE74, 0x9843, 0xEE75, 0x9844, 0xEE76, 0x9845, 0xEE77, 0x9846, + 0xEE78, 0x9847, 0xEE79, 0x9848, 0xEE7A, 0x9849, 0xEE7B, 0x984A, + 0xEE7C, 0x984B, 0xEE7D, 0x984C, 0xEE7E, 0x984D, 0xEE80, 0x984E, + 0xEE81, 0x984F, 0xEE82, 0x9850, 0xEE83, 0x9851, 0xEE84, 0x9852, + 0xEE85, 0x9853, 0xEE86, 0x9854, 0xEE87, 0x9855, 0xEE88, 0x9856, + 0xEE89, 0x9857, 0xEE8A, 0x9858, 0xEE8B, 0x9859, 0xEE8C, 0x985A, + 0xEE8D, 0x985B, 0xEE8E, 0x985C, 0xEE8F, 0x985D, 0xEE90, 0x985E, + 0xEE91, 0x985F, 0xEE92, 0x9860, 0xEE93, 0x9861, 0xEE94, 0x9862, + 0xEE95, 0x9863, 0xEE96, 0x9864, 0xEE97, 0x9865, 0xEE98, 0x9866, + 0xEE99, 0x9867, 0xEE9A, 0x9868, 0xEE9B, 0x9869, 0xEE9C, 0x986A, + 0xEE9D, 0x986B, 0xEE9E, 0x986C, 0xEE9F, 0x986D, 0xEEA0, 0x986E, + 0xEEA1, 0x7762, 0xEEA2, 0x7765, 0xEEA3, 0x777F, 0xEEA4, 0x778D, + 0xEEA5, 0x777D, 0xEEA6, 0x7780, 0xEEA7, 0x778C, 0xEEA8, 0x7791, + 0xEEA9, 0x779F, 0xEEAA, 0x77A0, 0xEEAB, 0x77B0, 0xEEAC, 0x77B5, + 0xEEAD, 0x77BD, 0xEEAE, 0x753A, 0xEEAF, 0x7540, 0xEEB0, 0x754E, + 0xEEB1, 0x754B, 0xEEB2, 0x7548, 0xEEB3, 0x755B, 0xEEB4, 0x7572, + 0xEEB5, 0x7579, 0xEEB6, 0x7583, 0xEEB7, 0x7F58, 0xEEB8, 0x7F61, + 0xEEB9, 0x7F5F, 0xEEBA, 0x8A48, 0xEEBB, 0x7F68, 0xEEBC, 0x7F74, + 0xEEBD, 0x7F71, 0xEEBE, 0x7F79, 0xEEBF, 0x7F81, 0xEEC0, 0x7F7E, + 0xEEC1, 0x76CD, 0xEEC2, 0x76E5, 0xEEC3, 0x8832, 0xEEC4, 0x9485, + 0xEEC5, 0x9486, 0xEEC6, 0x9487, 0xEEC7, 0x948B, 0xEEC8, 0x948A, + 0xEEC9, 0x948C, 0xEECA, 0x948D, 0xEECB, 0x948F, 0xEECC, 0x9490, + 0xEECD, 0x9494, 0xEECE, 0x9497, 0xEECF, 0x9495, 0xEED0, 0x949A, + 0xEED1, 0x949B, 0xEED2, 0x949C, 0xEED3, 0x94A3, 0xEED4, 0x94A4, + 0xEED5, 0x94AB, 0xEED6, 0x94AA, 0xEED7, 0x94AD, 0xEED8, 0x94AC, + 0xEED9, 0x94AF, 0xEEDA, 0x94B0, 0xEEDB, 0x94B2, 0xEEDC, 0x94B4, + 0xEEDD, 0x94B6, 0xEEDE, 0x94B7, 0xEEDF, 0x94B8, 0xEEE0, 0x94B9, + 0xEEE1, 0x94BA, 0xEEE2, 0x94BC, 0xEEE3, 0x94BD, 0xEEE4, 0x94BF, + 0xEEE5, 0x94C4, 0xEEE6, 0x94C8, 0xEEE7, 0x94C9, 0xEEE8, 0x94CA, + 0xEEE9, 0x94CB, 0xEEEA, 0x94CC, 0xEEEB, 0x94CD, 0xEEEC, 0x94CE, + 0xEEED, 0x94D0, 0xEEEE, 0x94D1, 0xEEEF, 0x94D2, 0xEEF0, 0x94D5, + 0xEEF1, 0x94D6, 0xEEF2, 0x94D7, 0xEEF3, 0x94D9, 0xEEF4, 0x94D8, + 0xEEF5, 0x94DB, 0xEEF6, 0x94DE, 0xEEF7, 0x94DF, 0xEEF8, 0x94E0, + 0xEEF9, 0x94E2, 0xEEFA, 0x94E4, 0xEEFB, 0x94E5, 0xEEFC, 0x94E7, + 0xEEFD, 0x94E8, 0xEEFE, 0x94EA, 0xEF40, 0x986F, 0xEF41, 0x9870, + 0xEF42, 0x9871, 0xEF43, 0x9872, 0xEF44, 0x9873, 0xEF45, 0x9874, + 0xEF46, 0x988B, 0xEF47, 0x988E, 0xEF48, 0x9892, 0xEF49, 0x9895, + 0xEF4A, 0x9899, 0xEF4B, 0x98A3, 0xEF4C, 0x98A8, 0xEF4D, 0x98A9, + 0xEF4E, 0x98AA, 0xEF4F, 0x98AB, 0xEF50, 0x98AC, 0xEF51, 0x98AD, + 0xEF52, 0x98AE, 0xEF53, 0x98AF, 0xEF54, 0x98B0, 0xEF55, 0x98B1, + 0xEF56, 0x98B2, 0xEF57, 0x98B3, 0xEF58, 0x98B4, 0xEF59, 0x98B5, + 0xEF5A, 0x98B6, 0xEF5B, 0x98B7, 0xEF5C, 0x98B8, 0xEF5D, 0x98B9, + 0xEF5E, 0x98BA, 0xEF5F, 0x98BB, 0xEF60, 0x98BC, 0xEF61, 0x98BD, + 0xEF62, 0x98BE, 0xEF63, 0x98BF, 0xEF64, 0x98C0, 0xEF65, 0x98C1, + 0xEF66, 0x98C2, 0xEF67, 0x98C3, 0xEF68, 0x98C4, 0xEF69, 0x98C5, + 0xEF6A, 0x98C6, 0xEF6B, 0x98C7, 0xEF6C, 0x98C8, 0xEF6D, 0x98C9, + 0xEF6E, 0x98CA, 0xEF6F, 0x98CB, 0xEF70, 0x98CC, 0xEF71, 0x98CD, + 0xEF72, 0x98CF, 0xEF73, 0x98D0, 0xEF74, 0x98D4, 0xEF75, 0x98D6, + 0xEF76, 0x98D7, 0xEF77, 0x98DB, 0xEF78, 0x98DC, 0xEF79, 0x98DD, + 0xEF7A, 0x98E0, 0xEF7B, 0x98E1, 0xEF7C, 0x98E2, 0xEF7D, 0x98E3, + 0xEF7E, 0x98E4, 0xEF80, 0x98E5, 0xEF81, 0x98E6, 0xEF82, 0x98E9, + 0xEF83, 0x98EA, 0xEF84, 0x98EB, 0xEF85, 0x98EC, 0xEF86, 0x98ED, + 0xEF87, 0x98EE, 0xEF88, 0x98EF, 0xEF89, 0x98F0, 0xEF8A, 0x98F1, + 0xEF8B, 0x98F2, 0xEF8C, 0x98F3, 0xEF8D, 0x98F4, 0xEF8E, 0x98F5, + 0xEF8F, 0x98F6, 0xEF90, 0x98F7, 0xEF91, 0x98F8, 0xEF92, 0x98F9, + 0xEF93, 0x98FA, 0xEF94, 0x98FB, 0xEF95, 0x98FC, 0xEF96, 0x98FD, + 0xEF97, 0x98FE, 0xEF98, 0x98FF, 0xEF99, 0x9900, 0xEF9A, 0x9901, + 0xEF9B, 0x9902, 0xEF9C, 0x9903, 0xEF9D, 0x9904, 0xEF9E, 0x9905, + 0xEF9F, 0x9906, 0xEFA0, 0x9907, 0xEFA1, 0x94E9, 0xEFA2, 0x94EB, + 0xEFA3, 0x94EE, 0xEFA4, 0x94EF, 0xEFA5, 0x94F3, 0xEFA6, 0x94F4, + 0xEFA7, 0x94F5, 0xEFA8, 0x94F7, 0xEFA9, 0x94F9, 0xEFAA, 0x94FC, + 0xEFAB, 0x94FD, 0xEFAC, 0x94FF, 0xEFAD, 0x9503, 0xEFAE, 0x9502, + 0xEFAF, 0x9506, 0xEFB0, 0x9507, 0xEFB1, 0x9509, 0xEFB2, 0x950A, + 0xEFB3, 0x950D, 0xEFB4, 0x950E, 0xEFB5, 0x950F, 0xEFB6, 0x9512, + 0xEFB7, 0x9513, 0xEFB8, 0x9514, 0xEFB9, 0x9515, 0xEFBA, 0x9516, + 0xEFBB, 0x9518, 0xEFBC, 0x951B, 0xEFBD, 0x951D, 0xEFBE, 0x951E, + 0xEFBF, 0x951F, 0xEFC0, 0x9522, 0xEFC1, 0x952A, 0xEFC2, 0x952B, + 0xEFC3, 0x9529, 0xEFC4, 0x952C, 0xEFC5, 0x9531, 0xEFC6, 0x9532, + 0xEFC7, 0x9534, 0xEFC8, 0x9536, 0xEFC9, 0x9537, 0xEFCA, 0x9538, + 0xEFCB, 0x953C, 0xEFCC, 0x953E, 0xEFCD, 0x953F, 0xEFCE, 0x9542, + 0xEFCF, 0x9535, 0xEFD0, 0x9544, 0xEFD1, 0x9545, 0xEFD2, 0x9546, + 0xEFD3, 0x9549, 0xEFD4, 0x954C, 0xEFD5, 0x954E, 0xEFD6, 0x954F, + 0xEFD7, 0x9552, 0xEFD8, 0x9553, 0xEFD9, 0x9554, 0xEFDA, 0x9556, + 0xEFDB, 0x9557, 0xEFDC, 0x9558, 0xEFDD, 0x9559, 0xEFDE, 0x955B, + 0xEFDF, 0x955E, 0xEFE0, 0x955F, 0xEFE1, 0x955D, 0xEFE2, 0x9561, + 0xEFE3, 0x9562, 0xEFE4, 0x9564, 0xEFE5, 0x9565, 0xEFE6, 0x9566, + 0xEFE7, 0x9567, 0xEFE8, 0x9568, 0xEFE9, 0x9569, 0xEFEA, 0x956A, + 0xEFEB, 0x956B, 0xEFEC, 0x956C, 0xEFED, 0x956F, 0xEFEE, 0x9571, + 0xEFEF, 0x9572, 0xEFF0, 0x9573, 0xEFF1, 0x953A, 0xEFF2, 0x77E7, + 0xEFF3, 0x77EC, 0xEFF4, 0x96C9, 0xEFF5, 0x79D5, 0xEFF6, 0x79ED, + 0xEFF7, 0x79E3, 0xEFF8, 0x79EB, 0xEFF9, 0x7A06, 0xEFFA, 0x5D47, + 0xEFFB, 0x7A03, 0xEFFC, 0x7A02, 0xEFFD, 0x7A1E, 0xEFFE, 0x7A14, + 0xF040, 0x9908, 0xF041, 0x9909, 0xF042, 0x990A, 0xF043, 0x990B, + 0xF044, 0x990C, 0xF045, 0x990E, 0xF046, 0x990F, 0xF047, 0x9911, + 0xF048, 0x9912, 0xF049, 0x9913, 0xF04A, 0x9914, 0xF04B, 0x9915, + 0xF04C, 0x9916, 0xF04D, 0x9917, 0xF04E, 0x9918, 0xF04F, 0x9919, + 0xF050, 0x991A, 0xF051, 0x991B, 0xF052, 0x991C, 0xF053, 0x991D, + 0xF054, 0x991E, 0xF055, 0x991F, 0xF056, 0x9920, 0xF057, 0x9921, + 0xF058, 0x9922, 0xF059, 0x9923, 0xF05A, 0x9924, 0xF05B, 0x9925, + 0xF05C, 0x9926, 0xF05D, 0x9927, 0xF05E, 0x9928, 0xF05F, 0x9929, + 0xF060, 0x992A, 0xF061, 0x992B, 0xF062, 0x992C, 0xF063, 0x992D, + 0xF064, 0x992F, 0xF065, 0x9930, 0xF066, 0x9931, 0xF067, 0x9932, + 0xF068, 0x9933, 0xF069, 0x9934, 0xF06A, 0x9935, 0xF06B, 0x9936, + 0xF06C, 0x9937, 0xF06D, 0x9938, 0xF06E, 0x9939, 0xF06F, 0x993A, + 0xF070, 0x993B, 0xF071, 0x993C, 0xF072, 0x993D, 0xF073, 0x993E, + 0xF074, 0x993F, 0xF075, 0x9940, 0xF076, 0x9941, 0xF077, 0x9942, + 0xF078, 0x9943, 0xF079, 0x9944, 0xF07A, 0x9945, 0xF07B, 0x9946, + 0xF07C, 0x9947, 0xF07D, 0x9948, 0xF07E, 0x9949, 0xF080, 0x994A, + 0xF081, 0x994B, 0xF082, 0x994C, 0xF083, 0x994D, 0xF084, 0x994E, + 0xF085, 0x994F, 0xF086, 0x9950, 0xF087, 0x9951, 0xF088, 0x9952, + 0xF089, 0x9953, 0xF08A, 0x9956, 0xF08B, 0x9957, 0xF08C, 0x9958, + 0xF08D, 0x9959, 0xF08E, 0x995A, 0xF08F, 0x995B, 0xF090, 0x995C, + 0xF091, 0x995D, 0xF092, 0x995E, 0xF093, 0x995F, 0xF094, 0x9960, + 0xF095, 0x9961, 0xF096, 0x9962, 0xF097, 0x9964, 0xF098, 0x9966, + 0xF099, 0x9973, 0xF09A, 0x9978, 0xF09B, 0x9979, 0xF09C, 0x997B, + 0xF09D, 0x997E, 0xF09E, 0x9982, 0xF09F, 0x9983, 0xF0A0, 0x9989, + 0xF0A1, 0x7A39, 0xF0A2, 0x7A37, 0xF0A3, 0x7A51, 0xF0A4, 0x9ECF, + 0xF0A5, 0x99A5, 0xF0A6, 0x7A70, 0xF0A7, 0x7688, 0xF0A8, 0x768E, + 0xF0A9, 0x7693, 0xF0AA, 0x7699, 0xF0AB, 0x76A4, 0xF0AC, 0x74DE, + 0xF0AD, 0x74E0, 0xF0AE, 0x752C, 0xF0AF, 0x9E20, 0xF0B0, 0x9E22, + 0xF0B1, 0x9E28, 0xF0B2, 0x9E29, 0xF0B3, 0x9E2A, 0xF0B4, 0x9E2B, + 0xF0B5, 0x9E2C, 0xF0B6, 0x9E32, 0xF0B7, 0x9E31, 0xF0B8, 0x9E36, + 0xF0B9, 0x9E38, 0xF0BA, 0x9E37, 0xF0BB, 0x9E39, 0xF0BC, 0x9E3A, + 0xF0BD, 0x9E3E, 0xF0BE, 0x9E41, 0xF0BF, 0x9E42, 0xF0C0, 0x9E44, + 0xF0C1, 0x9E46, 0xF0C2, 0x9E47, 0xF0C3, 0x9E48, 0xF0C4, 0x9E49, + 0xF0C5, 0x9E4B, 0xF0C6, 0x9E4C, 0xF0C7, 0x9E4E, 0xF0C8, 0x9E51, + 0xF0C9, 0x9E55, 0xF0CA, 0x9E57, 0xF0CB, 0x9E5A, 0xF0CC, 0x9E5B, + 0xF0CD, 0x9E5C, 0xF0CE, 0x9E5E, 0xF0CF, 0x9E63, 0xF0D0, 0x9E66, + 0xF0D1, 0x9E67, 0xF0D2, 0x9E68, 0xF0D3, 0x9E69, 0xF0D4, 0x9E6A, + 0xF0D5, 0x9E6B, 0xF0D6, 0x9E6C, 0xF0D7, 0x9E71, 0xF0D8, 0x9E6D, + 0xF0D9, 0x9E73, 0xF0DA, 0x7592, 0xF0DB, 0x7594, 0xF0DC, 0x7596, + 0xF0DD, 0x75A0, 0xF0DE, 0x759D, 0xF0DF, 0x75AC, 0xF0E0, 0x75A3, + 0xF0E1, 0x75B3, 0xF0E2, 0x75B4, 0xF0E3, 0x75B8, 0xF0E4, 0x75C4, + 0xF0E5, 0x75B1, 0xF0E6, 0x75B0, 0xF0E7, 0x75C3, 0xF0E8, 0x75C2, + 0xF0E9, 0x75D6, 0xF0EA, 0x75CD, 0xF0EB, 0x75E3, 0xF0EC, 0x75E8, + 0xF0ED, 0x75E6, 0xF0EE, 0x75E4, 0xF0EF, 0x75EB, 0xF0F0, 0x75E7, + 0xF0F1, 0x7603, 0xF0F2, 0x75F1, 0xF0F3, 0x75FC, 0xF0F4, 0x75FF, + 0xF0F5, 0x7610, 0xF0F6, 0x7600, 0xF0F7, 0x7605, 0xF0F8, 0x760C, + 0xF0F9, 0x7617, 0xF0FA, 0x760A, 0xF0FB, 0x7625, 0xF0FC, 0x7618, + 0xF0FD, 0x7615, 0xF0FE, 0x7619, 0xF140, 0x998C, 0xF141, 0x998E, + 0xF142, 0x999A, 0xF143, 0x999B, 0xF144, 0x999C, 0xF145, 0x999D, + 0xF146, 0x999E, 0xF147, 0x999F, 0xF148, 0x99A0, 0xF149, 0x99A1, + 0xF14A, 0x99A2, 0xF14B, 0x99A3, 0xF14C, 0x99A4, 0xF14D, 0x99A6, + 0xF14E, 0x99A7, 0xF14F, 0x99A9, 0xF150, 0x99AA, 0xF151, 0x99AB, + 0xF152, 0x99AC, 0xF153, 0x99AD, 0xF154, 0x99AE, 0xF155, 0x99AF, + 0xF156, 0x99B0, 0xF157, 0x99B1, 0xF158, 0x99B2, 0xF159, 0x99B3, + 0xF15A, 0x99B4, 0xF15B, 0x99B5, 0xF15C, 0x99B6, 0xF15D, 0x99B7, + 0xF15E, 0x99B8, 0xF15F, 0x99B9, 0xF160, 0x99BA, 0xF161, 0x99BB, + 0xF162, 0x99BC, 0xF163, 0x99BD, 0xF164, 0x99BE, 0xF165, 0x99BF, + 0xF166, 0x99C0, 0xF167, 0x99C1, 0xF168, 0x99C2, 0xF169, 0x99C3, + 0xF16A, 0x99C4, 0xF16B, 0x99C5, 0xF16C, 0x99C6, 0xF16D, 0x99C7, + 0xF16E, 0x99C8, 0xF16F, 0x99C9, 0xF170, 0x99CA, 0xF171, 0x99CB, + 0xF172, 0x99CC, 0xF173, 0x99CD, 0xF174, 0x99CE, 0xF175, 0x99CF, + 0xF176, 0x99D0, 0xF177, 0x99D1, 0xF178, 0x99D2, 0xF179, 0x99D3, + 0xF17A, 0x99D4, 0xF17B, 0x99D5, 0xF17C, 0x99D6, 0xF17D, 0x99D7, + 0xF17E, 0x99D8, 0xF180, 0x99D9, 0xF181, 0x99DA, 0xF182, 0x99DB, + 0xF183, 0x99DC, 0xF184, 0x99DD, 0xF185, 0x99DE, 0xF186, 0x99DF, + 0xF187, 0x99E0, 0xF188, 0x99E1, 0xF189, 0x99E2, 0xF18A, 0x99E3, + 0xF18B, 0x99E4, 0xF18C, 0x99E5, 0xF18D, 0x99E6, 0xF18E, 0x99E7, + 0xF18F, 0x99E8, 0xF190, 0x99E9, 0xF191, 0x99EA, 0xF192, 0x99EB, + 0xF193, 0x99EC, 0xF194, 0x99ED, 0xF195, 0x99EE, 0xF196, 0x99EF, + 0xF197, 0x99F0, 0xF198, 0x99F1, 0xF199, 0x99F2, 0xF19A, 0x99F3, + 0xF19B, 0x99F4, 0xF19C, 0x99F5, 0xF19D, 0x99F6, 0xF19E, 0x99F7, + 0xF19F, 0x99F8, 0xF1A0, 0x99F9, 0xF1A1, 0x761B, 0xF1A2, 0x763C, + 0xF1A3, 0x7622, 0xF1A4, 0x7620, 0xF1A5, 0x7640, 0xF1A6, 0x762D, + 0xF1A7, 0x7630, 0xF1A8, 0x763F, 0xF1A9, 0x7635, 0xF1AA, 0x7643, + 0xF1AB, 0x763E, 0xF1AC, 0x7633, 0xF1AD, 0x764D, 0xF1AE, 0x765E, + 0xF1AF, 0x7654, 0xF1B0, 0x765C, 0xF1B1, 0x7656, 0xF1B2, 0x766B, + 0xF1B3, 0x766F, 0xF1B4, 0x7FCA, 0xF1B5, 0x7AE6, 0xF1B6, 0x7A78, + 0xF1B7, 0x7A79, 0xF1B8, 0x7A80, 0xF1B9, 0x7A86, 0xF1BA, 0x7A88, + 0xF1BB, 0x7A95, 0xF1BC, 0x7AA6, 0xF1BD, 0x7AA0, 0xF1BE, 0x7AAC, + 0xF1BF, 0x7AA8, 0xF1C0, 0x7AAD, 0xF1C1, 0x7AB3, 0xF1C2, 0x8864, + 0xF1C3, 0x8869, 0xF1C4, 0x8872, 0xF1C5, 0x887D, 0xF1C6, 0x887F, + 0xF1C7, 0x8882, 0xF1C8, 0x88A2, 0xF1C9, 0x88C6, 0xF1CA, 0x88B7, + 0xF1CB, 0x88BC, 0xF1CC, 0x88C9, 0xF1CD, 0x88E2, 0xF1CE, 0x88CE, + 0xF1CF, 0x88E3, 0xF1D0, 0x88E5, 0xF1D1, 0x88F1, 0xF1D2, 0x891A, + 0xF1D3, 0x88FC, 0xF1D4, 0x88E8, 0xF1D5, 0x88FE, 0xF1D6, 0x88F0, + 0xF1D7, 0x8921, 0xF1D8, 0x8919, 0xF1D9, 0x8913, 0xF1DA, 0x891B, + 0xF1DB, 0x890A, 0xF1DC, 0x8934, 0xF1DD, 0x892B, 0xF1DE, 0x8936, + 0xF1DF, 0x8941, 0xF1E0, 0x8966, 0xF1E1, 0x897B, 0xF1E2, 0x758B, + 0xF1E3, 0x80E5, 0xF1E4, 0x76B2, 0xF1E5, 0x76B4, 0xF1E6, 0x77DC, + 0xF1E7, 0x8012, 0xF1E8, 0x8014, 0xF1E9, 0x8016, 0xF1EA, 0x801C, + 0xF1EB, 0x8020, 0xF1EC, 0x8022, 0xF1ED, 0x8025, 0xF1EE, 0x8026, + 0xF1EF, 0x8027, 0xF1F0, 0x8029, 0xF1F1, 0x8028, 0xF1F2, 0x8031, + 0xF1F3, 0x800B, 0xF1F4, 0x8035, 0xF1F5, 0x8043, 0xF1F6, 0x8046, + 0xF1F7, 0x804D, 0xF1F8, 0x8052, 0xF1F9, 0x8069, 0xF1FA, 0x8071, + 0xF1FB, 0x8983, 0xF1FC, 0x9878, 0xF1FD, 0x9880, 0xF1FE, 0x9883, + 0xF240, 0x99FA, 0xF241, 0x99FB, 0xF242, 0x99FC, 0xF243, 0x99FD, + 0xF244, 0x99FE, 0xF245, 0x99FF, 0xF246, 0x9A00, 0xF247, 0x9A01, + 0xF248, 0x9A02, 0xF249, 0x9A03, 0xF24A, 0x9A04, 0xF24B, 0x9A05, + 0xF24C, 0x9A06, 0xF24D, 0x9A07, 0xF24E, 0x9A08, 0xF24F, 0x9A09, + 0xF250, 0x9A0A, 0xF251, 0x9A0B, 0xF252, 0x9A0C, 0xF253, 0x9A0D, + 0xF254, 0x9A0E, 0xF255, 0x9A0F, 0xF256, 0x9A10, 0xF257, 0x9A11, + 0xF258, 0x9A12, 0xF259, 0x9A13, 0xF25A, 0x9A14, 0xF25B, 0x9A15, + 0xF25C, 0x9A16, 0xF25D, 0x9A17, 0xF25E, 0x9A18, 0xF25F, 0x9A19, + 0xF260, 0x9A1A, 0xF261, 0x9A1B, 0xF262, 0x9A1C, 0xF263, 0x9A1D, + 0xF264, 0x9A1E, 0xF265, 0x9A1F, 0xF266, 0x9A20, 0xF267, 0x9A21, + 0xF268, 0x9A22, 0xF269, 0x9A23, 0xF26A, 0x9A24, 0xF26B, 0x9A25, + 0xF26C, 0x9A26, 0xF26D, 0x9A27, 0xF26E, 0x9A28, 0xF26F, 0x9A29, + 0xF270, 0x9A2A, 0xF271, 0x9A2B, 0xF272, 0x9A2C, 0xF273, 0x9A2D, + 0xF274, 0x9A2E, 0xF275, 0x9A2F, 0xF276, 0x9A30, 0xF277, 0x9A31, + 0xF278, 0x9A32, 0xF279, 0x9A33, 0xF27A, 0x9A34, 0xF27B, 0x9A35, + 0xF27C, 0x9A36, 0xF27D, 0x9A37, 0xF27E, 0x9A38, 0xF280, 0x9A39, + 0xF281, 0x9A3A, 0xF282, 0x9A3B, 0xF283, 0x9A3C, 0xF284, 0x9A3D, + 0xF285, 0x9A3E, 0xF286, 0x9A3F, 0xF287, 0x9A40, 0xF288, 0x9A41, + 0xF289, 0x9A42, 0xF28A, 0x9A43, 0xF28B, 0x9A44, 0xF28C, 0x9A45, + 0xF28D, 0x9A46, 0xF28E, 0x9A47, 0xF28F, 0x9A48, 0xF290, 0x9A49, + 0xF291, 0x9A4A, 0xF292, 0x9A4B, 0xF293, 0x9A4C, 0xF294, 0x9A4D, + 0xF295, 0x9A4E, 0xF296, 0x9A4F, 0xF297, 0x9A50, 0xF298, 0x9A51, + 0xF299, 0x9A52, 0xF29A, 0x9A53, 0xF29B, 0x9A54, 0xF29C, 0x9A55, + 0xF29D, 0x9A56, 0xF29E, 0x9A57, 0xF29F, 0x9A58, 0xF2A0, 0x9A59, + 0xF2A1, 0x9889, 0xF2A2, 0x988C, 0xF2A3, 0x988D, 0xF2A4, 0x988F, + 0xF2A5, 0x9894, 0xF2A6, 0x989A, 0xF2A7, 0x989B, 0xF2A8, 0x989E, + 0xF2A9, 0x989F, 0xF2AA, 0x98A1, 0xF2AB, 0x98A2, 0xF2AC, 0x98A5, + 0xF2AD, 0x98A6, 0xF2AE, 0x864D, 0xF2AF, 0x8654, 0xF2B0, 0x866C, + 0xF2B1, 0x866E, 0xF2B2, 0x867F, 0xF2B3, 0x867A, 0xF2B4, 0x867C, + 0xF2B5, 0x867B, 0xF2B6, 0x86A8, 0xF2B7, 0x868D, 0xF2B8, 0x868B, + 0xF2B9, 0x86AC, 0xF2BA, 0x869D, 0xF2BB, 0x86A7, 0xF2BC, 0x86A3, + 0xF2BD, 0x86AA, 0xF2BE, 0x8693, 0xF2BF, 0x86A9, 0xF2C0, 0x86B6, + 0xF2C1, 0x86C4, 0xF2C2, 0x86B5, 0xF2C3, 0x86CE, 0xF2C4, 0x86B0, + 0xF2C5, 0x86BA, 0xF2C6, 0x86B1, 0xF2C7, 0x86AF, 0xF2C8, 0x86C9, + 0xF2C9, 0x86CF, 0xF2CA, 0x86B4, 0xF2CB, 0x86E9, 0xF2CC, 0x86F1, + 0xF2CD, 0x86F2, 0xF2CE, 0x86ED, 0xF2CF, 0x86F3, 0xF2D0, 0x86D0, + 0xF2D1, 0x8713, 0xF2D2, 0x86DE, 0xF2D3, 0x86F4, 0xF2D4, 0x86DF, + 0xF2D5, 0x86D8, 0xF2D6, 0x86D1, 0xF2D7, 0x8703, 0xF2D8, 0x8707, + 0xF2D9, 0x86F8, 0xF2DA, 0x8708, 0xF2DB, 0x870A, 0xF2DC, 0x870D, + 0xF2DD, 0x8709, 0xF2DE, 0x8723, 0xF2DF, 0x873B, 0xF2E0, 0x871E, + 0xF2E1, 0x8725, 0xF2E2, 0x872E, 0xF2E3, 0x871A, 0xF2E4, 0x873E, + 0xF2E5, 0x8748, 0xF2E6, 0x8734, 0xF2E7, 0x8731, 0xF2E8, 0x8729, + 0xF2E9, 0x8737, 0xF2EA, 0x873F, 0xF2EB, 0x8782, 0xF2EC, 0x8722, + 0xF2ED, 0x877D, 0xF2EE, 0x877E, 0xF2EF, 0x877B, 0xF2F0, 0x8760, + 0xF2F1, 0x8770, 0xF2F2, 0x874C, 0xF2F3, 0x876E, 0xF2F4, 0x878B, + 0xF2F5, 0x8753, 0xF2F6, 0x8763, 0xF2F7, 0x877C, 0xF2F8, 0x8764, + 0xF2F9, 0x8759, 0xF2FA, 0x8765, 0xF2FB, 0x8793, 0xF2FC, 0x87AF, + 0xF2FD, 0x87A8, 0xF2FE, 0x87D2, 0xF340, 0x9A5A, 0xF341, 0x9A5B, + 0xF342, 0x9A5C, 0xF343, 0x9A5D, 0xF344, 0x9A5E, 0xF345, 0x9A5F, + 0xF346, 0x9A60, 0xF347, 0x9A61, 0xF348, 0x9A62, 0xF349, 0x9A63, + 0xF34A, 0x9A64, 0xF34B, 0x9A65, 0xF34C, 0x9A66, 0xF34D, 0x9A67, + 0xF34E, 0x9A68, 0xF34F, 0x9A69, 0xF350, 0x9A6A, 0xF351, 0x9A6B, + 0xF352, 0x9A72, 0xF353, 0x9A83, 0xF354, 0x9A89, 0xF355, 0x9A8D, + 0xF356, 0x9A8E, 0xF357, 0x9A94, 0xF358, 0x9A95, 0xF359, 0x9A99, + 0xF35A, 0x9AA6, 0xF35B, 0x9AA9, 0xF35C, 0x9AAA, 0xF35D, 0x9AAB, + 0xF35E, 0x9AAC, 0xF35F, 0x9AAD, 0xF360, 0x9AAE, 0xF361, 0x9AAF, + 0xF362, 0x9AB2, 0xF363, 0x9AB3, 0xF364, 0x9AB4, 0xF365, 0x9AB5, + 0xF366, 0x9AB9, 0xF367, 0x9ABB, 0xF368, 0x9ABD, 0xF369, 0x9ABE, + 0xF36A, 0x9ABF, 0xF36B, 0x9AC3, 0xF36C, 0x9AC4, 0xF36D, 0x9AC6, + 0xF36E, 0x9AC7, 0xF36F, 0x9AC8, 0xF370, 0x9AC9, 0xF371, 0x9ACA, + 0xF372, 0x9ACD, 0xF373, 0x9ACE, 0xF374, 0x9ACF, 0xF375, 0x9AD0, + 0xF376, 0x9AD2, 0xF377, 0x9AD4, 0xF378, 0x9AD5, 0xF379, 0x9AD6, + 0xF37A, 0x9AD7, 0xF37B, 0x9AD9, 0xF37C, 0x9ADA, 0xF37D, 0x9ADB, + 0xF37E, 0x9ADC, 0xF380, 0x9ADD, 0xF381, 0x9ADE, 0xF382, 0x9AE0, + 0xF383, 0x9AE2, 0xF384, 0x9AE3, 0xF385, 0x9AE4, 0xF386, 0x9AE5, + 0xF387, 0x9AE7, 0xF388, 0x9AE8, 0xF389, 0x9AE9, 0xF38A, 0x9AEA, + 0xF38B, 0x9AEC, 0xF38C, 0x9AEE, 0xF38D, 0x9AF0, 0xF38E, 0x9AF1, + 0xF38F, 0x9AF2, 0xF390, 0x9AF3, 0xF391, 0x9AF4, 0xF392, 0x9AF5, + 0xF393, 0x9AF6, 0xF394, 0x9AF7, 0xF395, 0x9AF8, 0xF396, 0x9AFA, + 0xF397, 0x9AFC, 0xF398, 0x9AFD, 0xF399, 0x9AFE, 0xF39A, 0x9AFF, + 0xF39B, 0x9B00, 0xF39C, 0x9B01, 0xF39D, 0x9B02, 0xF39E, 0x9B04, + 0xF39F, 0x9B05, 0xF3A0, 0x9B06, 0xF3A1, 0x87C6, 0xF3A2, 0x8788, + 0xF3A3, 0x8785, 0xF3A4, 0x87AD, 0xF3A5, 0x8797, 0xF3A6, 0x8783, + 0xF3A7, 0x87AB, 0xF3A8, 0x87E5, 0xF3A9, 0x87AC, 0xF3AA, 0x87B5, + 0xF3AB, 0x87B3, 0xF3AC, 0x87CB, 0xF3AD, 0x87D3, 0xF3AE, 0x87BD, + 0xF3AF, 0x87D1, 0xF3B0, 0x87C0, 0xF3B1, 0x87CA, 0xF3B2, 0x87DB, + 0xF3B3, 0x87EA, 0xF3B4, 0x87E0, 0xF3B5, 0x87EE, 0xF3B6, 0x8816, + 0xF3B7, 0x8813, 0xF3B8, 0x87FE, 0xF3B9, 0x880A, 0xF3BA, 0x881B, + 0xF3BB, 0x8821, 0xF3BC, 0x8839, 0xF3BD, 0x883C, 0xF3BE, 0x7F36, + 0xF3BF, 0x7F42, 0xF3C0, 0x7F44, 0xF3C1, 0x7F45, 0xF3C2, 0x8210, + 0xF3C3, 0x7AFA, 0xF3C4, 0x7AFD, 0xF3C5, 0x7B08, 0xF3C6, 0x7B03, + 0xF3C7, 0x7B04, 0xF3C8, 0x7B15, 0xF3C9, 0x7B0A, 0xF3CA, 0x7B2B, + 0xF3CB, 0x7B0F, 0xF3CC, 0x7B47, 0xF3CD, 0x7B38, 0xF3CE, 0x7B2A, + 0xF3CF, 0x7B19, 0xF3D0, 0x7B2E, 0xF3D1, 0x7B31, 0xF3D2, 0x7B20, + 0xF3D3, 0x7B25, 0xF3D4, 0x7B24, 0xF3D5, 0x7B33, 0xF3D6, 0x7B3E, + 0xF3D7, 0x7B1E, 0xF3D8, 0x7B58, 0xF3D9, 0x7B5A, 0xF3DA, 0x7B45, + 0xF3DB, 0x7B75, 0xF3DC, 0x7B4C, 0xF3DD, 0x7B5D, 0xF3DE, 0x7B60, + 0xF3DF, 0x7B6E, 0xF3E0, 0x7B7B, 0xF3E1, 0x7B62, 0xF3E2, 0x7B72, + 0xF3E3, 0x7B71, 0xF3E4, 0x7B90, 0xF3E5, 0x7BA6, 0xF3E6, 0x7BA7, + 0xF3E7, 0x7BB8, 0xF3E8, 0x7BAC, 0xF3E9, 0x7B9D, 0xF3EA, 0x7BA8, + 0xF3EB, 0x7B85, 0xF3EC, 0x7BAA, 0xF3ED, 0x7B9C, 0xF3EE, 0x7BA2, + 0xF3EF, 0x7BAB, 0xF3F0, 0x7BB4, 0xF3F1, 0x7BD1, 0xF3F2, 0x7BC1, + 0xF3F3, 0x7BCC, 0xF3F4, 0x7BDD, 0xF3F5, 0x7BDA, 0xF3F6, 0x7BE5, + 0xF3F7, 0x7BE6, 0xF3F8, 0x7BEA, 0xF3F9, 0x7C0C, 0xF3FA, 0x7BFE, + 0xF3FB, 0x7BFC, 0xF3FC, 0x7C0F, 0xF3FD, 0x7C16, 0xF3FE, 0x7C0B, + 0xF440, 0x9B07, 0xF441, 0x9B09, 0xF442, 0x9B0A, 0xF443, 0x9B0B, + 0xF444, 0x9B0C, 0xF445, 0x9B0D, 0xF446, 0x9B0E, 0xF447, 0x9B10, + 0xF448, 0x9B11, 0xF449, 0x9B12, 0xF44A, 0x9B14, 0xF44B, 0x9B15, + 0xF44C, 0x9B16, 0xF44D, 0x9B17, 0xF44E, 0x9B18, 0xF44F, 0x9B19, + 0xF450, 0x9B1A, 0xF451, 0x9B1B, 0xF452, 0x9B1C, 0xF453, 0x9B1D, + 0xF454, 0x9B1E, 0xF455, 0x9B20, 0xF456, 0x9B21, 0xF457, 0x9B22, + 0xF458, 0x9B24, 0xF459, 0x9B25, 0xF45A, 0x9B26, 0xF45B, 0x9B27, + 0xF45C, 0x9B28, 0xF45D, 0x9B29, 0xF45E, 0x9B2A, 0xF45F, 0x9B2B, + 0xF460, 0x9B2C, 0xF461, 0x9B2D, 0xF462, 0x9B2E, 0xF463, 0x9B30, + 0xF464, 0x9B31, 0xF465, 0x9B33, 0xF466, 0x9B34, 0xF467, 0x9B35, + 0xF468, 0x9B36, 0xF469, 0x9B37, 0xF46A, 0x9B38, 0xF46B, 0x9B39, + 0xF46C, 0x9B3A, 0xF46D, 0x9B3D, 0xF46E, 0x9B3E, 0xF46F, 0x9B3F, + 0xF470, 0x9B40, 0xF471, 0x9B46, 0xF472, 0x9B4A, 0xF473, 0x9B4B, + 0xF474, 0x9B4C, 0xF475, 0x9B4E, 0xF476, 0x9B50, 0xF477, 0x9B52, + 0xF478, 0x9B53, 0xF479, 0x9B55, 0xF47A, 0x9B56, 0xF47B, 0x9B57, + 0xF47C, 0x9B58, 0xF47D, 0x9B59, 0xF47E, 0x9B5A, 0xF480, 0x9B5B, + 0xF481, 0x9B5C, 0xF482, 0x9B5D, 0xF483, 0x9B5E, 0xF484, 0x9B5F, + 0xF485, 0x9B60, 0xF486, 0x9B61, 0xF487, 0x9B62, 0xF488, 0x9B63, + 0xF489, 0x9B64, 0xF48A, 0x9B65, 0xF48B, 0x9B66, 0xF48C, 0x9B67, + 0xF48D, 0x9B68, 0xF48E, 0x9B69, 0xF48F, 0x9B6A, 0xF490, 0x9B6B, + 0xF491, 0x9B6C, 0xF492, 0x9B6D, 0xF493, 0x9B6E, 0xF494, 0x9B6F, + 0xF495, 0x9B70, 0xF496, 0x9B71, 0xF497, 0x9B72, 0xF498, 0x9B73, + 0xF499, 0x9B74, 0xF49A, 0x9B75, 0xF49B, 0x9B76, 0xF49C, 0x9B77, + 0xF49D, 0x9B78, 0xF49E, 0x9B79, 0xF49F, 0x9B7A, 0xF4A0, 0x9B7B, + 0xF4A1, 0x7C1F, 0xF4A2, 0x7C2A, 0xF4A3, 0x7C26, 0xF4A4, 0x7C38, + 0xF4A5, 0x7C41, 0xF4A6, 0x7C40, 0xF4A7, 0x81FE, 0xF4A8, 0x8201, + 0xF4A9, 0x8202, 0xF4AA, 0x8204, 0xF4AB, 0x81EC, 0xF4AC, 0x8844, + 0xF4AD, 0x8221, 0xF4AE, 0x8222, 0xF4AF, 0x8223, 0xF4B0, 0x822D, + 0xF4B1, 0x822F, 0xF4B2, 0x8228, 0xF4B3, 0x822B, 0xF4B4, 0x8238, + 0xF4B5, 0x823B, 0xF4B6, 0x8233, 0xF4B7, 0x8234, 0xF4B8, 0x823E, + 0xF4B9, 0x8244, 0xF4BA, 0x8249, 0xF4BB, 0x824B, 0xF4BC, 0x824F, + 0xF4BD, 0x825A, 0xF4BE, 0x825F, 0xF4BF, 0x8268, 0xF4C0, 0x887E, + 0xF4C1, 0x8885, 0xF4C2, 0x8888, 0xF4C3, 0x88D8, 0xF4C4, 0x88DF, + 0xF4C5, 0x895E, 0xF4C6, 0x7F9D, 0xF4C7, 0x7F9F, 0xF4C8, 0x7FA7, + 0xF4C9, 0x7FAF, 0xF4CA, 0x7FB0, 0xF4CB, 0x7FB2, 0xF4CC, 0x7C7C, + 0xF4CD, 0x6549, 0xF4CE, 0x7C91, 0xF4CF, 0x7C9D, 0xF4D0, 0x7C9C, + 0xF4D1, 0x7C9E, 0xF4D2, 0x7CA2, 0xF4D3, 0x7CB2, 0xF4D4, 0x7CBC, + 0xF4D5, 0x7CBD, 0xF4D6, 0x7CC1, 0xF4D7, 0x7CC7, 0xF4D8, 0x7CCC, + 0xF4D9, 0x7CCD, 0xF4DA, 0x7CC8, 0xF4DB, 0x7CC5, 0xF4DC, 0x7CD7, + 0xF4DD, 0x7CE8, 0xF4DE, 0x826E, 0xF4DF, 0x66A8, 0xF4E0, 0x7FBF, + 0xF4E1, 0x7FCE, 0xF4E2, 0x7FD5, 0xF4E3, 0x7FE5, 0xF4E4, 0x7FE1, + 0xF4E5, 0x7FE6, 0xF4E6, 0x7FE9, 0xF4E7, 0x7FEE, 0xF4E8, 0x7FF3, + 0xF4E9, 0x7CF8, 0xF4EA, 0x7D77, 0xF4EB, 0x7DA6, 0xF4EC, 0x7DAE, + 0xF4ED, 0x7E47, 0xF4EE, 0x7E9B, 0xF4EF, 0x9EB8, 0xF4F0, 0x9EB4, + 0xF4F1, 0x8D73, 0xF4F2, 0x8D84, 0xF4F3, 0x8D94, 0xF4F4, 0x8D91, + 0xF4F5, 0x8DB1, 0xF4F6, 0x8D67, 0xF4F7, 0x8D6D, 0xF4F8, 0x8C47, + 0xF4F9, 0x8C49, 0xF4FA, 0x914A, 0xF4FB, 0x9150, 0xF4FC, 0x914E, + 0xF4FD, 0x914F, 0xF4FE, 0x9164, 0xF540, 0x9B7C, 0xF541, 0x9B7D, + 0xF542, 0x9B7E, 0xF543, 0x9B7F, 0xF544, 0x9B80, 0xF545, 0x9B81, + 0xF546, 0x9B82, 0xF547, 0x9B83, 0xF548, 0x9B84, 0xF549, 0x9B85, + 0xF54A, 0x9B86, 0xF54B, 0x9B87, 0xF54C, 0x9B88, 0xF54D, 0x9B89, + 0xF54E, 0x9B8A, 0xF54F, 0x9B8B, 0xF550, 0x9B8C, 0xF551, 0x9B8D, + 0xF552, 0x9B8E, 0xF553, 0x9B8F, 0xF554, 0x9B90, 0xF555, 0x9B91, + 0xF556, 0x9B92, 0xF557, 0x9B93, 0xF558, 0x9B94, 0xF559, 0x9B95, + 0xF55A, 0x9B96, 0xF55B, 0x9B97, 0xF55C, 0x9B98, 0xF55D, 0x9B99, + 0xF55E, 0x9B9A, 0xF55F, 0x9B9B, 0xF560, 0x9B9C, 0xF561, 0x9B9D, + 0xF562, 0x9B9E, 0xF563, 0x9B9F, 0xF564, 0x9BA0, 0xF565, 0x9BA1, + 0xF566, 0x9BA2, 0xF567, 0x9BA3, 0xF568, 0x9BA4, 0xF569, 0x9BA5, + 0xF56A, 0x9BA6, 0xF56B, 0x9BA7, 0xF56C, 0x9BA8, 0xF56D, 0x9BA9, + 0xF56E, 0x9BAA, 0xF56F, 0x9BAB, 0xF570, 0x9BAC, 0xF571, 0x9BAD, + 0xF572, 0x9BAE, 0xF573, 0x9BAF, 0xF574, 0x9BB0, 0xF575, 0x9BB1, + 0xF576, 0x9BB2, 0xF577, 0x9BB3, 0xF578, 0x9BB4, 0xF579, 0x9BB5, + 0xF57A, 0x9BB6, 0xF57B, 0x9BB7, 0xF57C, 0x9BB8, 0xF57D, 0x9BB9, + 0xF57E, 0x9BBA, 0xF580, 0x9BBB, 0xF581, 0x9BBC, 0xF582, 0x9BBD, + 0xF583, 0x9BBE, 0xF584, 0x9BBF, 0xF585, 0x9BC0, 0xF586, 0x9BC1, + 0xF587, 0x9BC2, 0xF588, 0x9BC3, 0xF589, 0x9BC4, 0xF58A, 0x9BC5, + 0xF58B, 0x9BC6, 0xF58C, 0x9BC7, 0xF58D, 0x9BC8, 0xF58E, 0x9BC9, + 0xF58F, 0x9BCA, 0xF590, 0x9BCB, 0xF591, 0x9BCC, 0xF592, 0x9BCD, + 0xF593, 0x9BCE, 0xF594, 0x9BCF, 0xF595, 0x9BD0, 0xF596, 0x9BD1, + 0xF597, 0x9BD2, 0xF598, 0x9BD3, 0xF599, 0x9BD4, 0xF59A, 0x9BD5, + 0xF59B, 0x9BD6, 0xF59C, 0x9BD7, 0xF59D, 0x9BD8, 0xF59E, 0x9BD9, + 0xF59F, 0x9BDA, 0xF5A0, 0x9BDB, 0xF5A1, 0x9162, 0xF5A2, 0x9161, + 0xF5A3, 0x9170, 0xF5A4, 0x9169, 0xF5A5, 0x916F, 0xF5A6, 0x917D, + 0xF5A7, 0x917E, 0xF5A8, 0x9172, 0xF5A9, 0x9174, 0xF5AA, 0x9179, + 0xF5AB, 0x918C, 0xF5AC, 0x9185, 0xF5AD, 0x9190, 0xF5AE, 0x918D, + 0xF5AF, 0x9191, 0xF5B0, 0x91A2, 0xF5B1, 0x91A3, 0xF5B2, 0x91AA, + 0xF5B3, 0x91AD, 0xF5B4, 0x91AE, 0xF5B5, 0x91AF, 0xF5B6, 0x91B5, + 0xF5B7, 0x91B4, 0xF5B8, 0x91BA, 0xF5B9, 0x8C55, 0xF5BA, 0x9E7E, + 0xF5BB, 0x8DB8, 0xF5BC, 0x8DEB, 0xF5BD, 0x8E05, 0xF5BE, 0x8E59, + 0xF5BF, 0x8E69, 0xF5C0, 0x8DB5, 0xF5C1, 0x8DBF, 0xF5C2, 0x8DBC, + 0xF5C3, 0x8DBA, 0xF5C4, 0x8DC4, 0xF5C5, 0x8DD6, 0xF5C6, 0x8DD7, + 0xF5C7, 0x8DDA, 0xF5C8, 0x8DDE, 0xF5C9, 0x8DCE, 0xF5CA, 0x8DCF, + 0xF5CB, 0x8DDB, 0xF5CC, 0x8DC6, 0xF5CD, 0x8DEC, 0xF5CE, 0x8DF7, + 0xF5CF, 0x8DF8, 0xF5D0, 0x8DE3, 0xF5D1, 0x8DF9, 0xF5D2, 0x8DFB, + 0xF5D3, 0x8DE4, 0xF5D4, 0x8E09, 0xF5D5, 0x8DFD, 0xF5D6, 0x8E14, + 0xF5D7, 0x8E1D, 0xF5D8, 0x8E1F, 0xF5D9, 0x8E2C, 0xF5DA, 0x8E2E, + 0xF5DB, 0x8E23, 0xF5DC, 0x8E2F, 0xF5DD, 0x8E3A, 0xF5DE, 0x8E40, + 0xF5DF, 0x8E39, 0xF5E0, 0x8E35, 0xF5E1, 0x8E3D, 0xF5E2, 0x8E31, + 0xF5E3, 0x8E49, 0xF5E4, 0x8E41, 0xF5E5, 0x8E42, 0xF5E6, 0x8E51, + 0xF5E7, 0x8E52, 0xF5E8, 0x8E4A, 0xF5E9, 0x8E70, 0xF5EA, 0x8E76, + 0xF5EB, 0x8E7C, 0xF5EC, 0x8E6F, 0xF5ED, 0x8E74, 0xF5EE, 0x8E85, + 0xF5EF, 0x8E8F, 0xF5F0, 0x8E94, 0xF5F1, 0x8E90, 0xF5F2, 0x8E9C, + 0xF5F3, 0x8E9E, 0xF5F4, 0x8C78, 0xF5F5, 0x8C82, 0xF5F6, 0x8C8A, + 0xF5F7, 0x8C85, 0xF5F8, 0x8C98, 0xF5F9, 0x8C94, 0xF5FA, 0x659B, + 0xF5FB, 0x89D6, 0xF5FC, 0x89DE, 0xF5FD, 0x89DA, 0xF5FE, 0x89DC, + 0xF640, 0x9BDC, 0xF641, 0x9BDD, 0xF642, 0x9BDE, 0xF643, 0x9BDF, + 0xF644, 0x9BE0, 0xF645, 0x9BE1, 0xF646, 0x9BE2, 0xF647, 0x9BE3, + 0xF648, 0x9BE4, 0xF649, 0x9BE5, 0xF64A, 0x9BE6, 0xF64B, 0x9BE7, + 0xF64C, 0x9BE8, 0xF64D, 0x9BE9, 0xF64E, 0x9BEA, 0xF64F, 0x9BEB, + 0xF650, 0x9BEC, 0xF651, 0x9BED, 0xF652, 0x9BEE, 0xF653, 0x9BEF, + 0xF654, 0x9BF0, 0xF655, 0x9BF1, 0xF656, 0x9BF2, 0xF657, 0x9BF3, + 0xF658, 0x9BF4, 0xF659, 0x9BF5, 0xF65A, 0x9BF6, 0xF65B, 0x9BF7, + 0xF65C, 0x9BF8, 0xF65D, 0x9BF9, 0xF65E, 0x9BFA, 0xF65F, 0x9BFB, + 0xF660, 0x9BFC, 0xF661, 0x9BFD, 0xF662, 0x9BFE, 0xF663, 0x9BFF, + 0xF664, 0x9C00, 0xF665, 0x9C01, 0xF666, 0x9C02, 0xF667, 0x9C03, + 0xF668, 0x9C04, 0xF669, 0x9C05, 0xF66A, 0x9C06, 0xF66B, 0x9C07, + 0xF66C, 0x9C08, 0xF66D, 0x9C09, 0xF66E, 0x9C0A, 0xF66F, 0x9C0B, + 0xF670, 0x9C0C, 0xF671, 0x9C0D, 0xF672, 0x9C0E, 0xF673, 0x9C0F, + 0xF674, 0x9C10, 0xF675, 0x9C11, 0xF676, 0x9C12, 0xF677, 0x9C13, + 0xF678, 0x9C14, 0xF679, 0x9C15, 0xF67A, 0x9C16, 0xF67B, 0x9C17, + 0xF67C, 0x9C18, 0xF67D, 0x9C19, 0xF67E, 0x9C1A, 0xF680, 0x9C1B, + 0xF681, 0x9C1C, 0xF682, 0x9C1D, 0xF683, 0x9C1E, 0xF684, 0x9C1F, + 0xF685, 0x9C20, 0xF686, 0x9C21, 0xF687, 0x9C22, 0xF688, 0x9C23, + 0xF689, 0x9C24, 0xF68A, 0x9C25, 0xF68B, 0x9C26, 0xF68C, 0x9C27, + 0xF68D, 0x9C28, 0xF68E, 0x9C29, 0xF68F, 0x9C2A, 0xF690, 0x9C2B, + 0xF691, 0x9C2C, 0xF692, 0x9C2D, 0xF693, 0x9C2E, 0xF694, 0x9C2F, + 0xF695, 0x9C30, 0xF696, 0x9C31, 0xF697, 0x9C32, 0xF698, 0x9C33, + 0xF699, 0x9C34, 0xF69A, 0x9C35, 0xF69B, 0x9C36, 0xF69C, 0x9C37, + 0xF69D, 0x9C38, 0xF69E, 0x9C39, 0xF69F, 0x9C3A, 0xF6A0, 0x9C3B, + 0xF6A1, 0x89E5, 0xF6A2, 0x89EB, 0xF6A3, 0x89EF, 0xF6A4, 0x8A3E, + 0xF6A5, 0x8B26, 0xF6A6, 0x9753, 0xF6A7, 0x96E9, 0xF6A8, 0x96F3, + 0xF6A9, 0x96EF, 0xF6AA, 0x9706, 0xF6AB, 0x9701, 0xF6AC, 0x9708, + 0xF6AD, 0x970F, 0xF6AE, 0x970E, 0xF6AF, 0x972A, 0xF6B0, 0x972D, + 0xF6B1, 0x9730, 0xF6B2, 0x973E, 0xF6B3, 0x9F80, 0xF6B4, 0x9F83, + 0xF6B5, 0x9F85, 0xF6B6, 0x9F86, 0xF6B7, 0x9F87, 0xF6B8, 0x9F88, + 0xF6B9, 0x9F89, 0xF6BA, 0x9F8A, 0xF6BB, 0x9F8C, 0xF6BC, 0x9EFE, + 0xF6BD, 0x9F0B, 0xF6BE, 0x9F0D, 0xF6BF, 0x96B9, 0xF6C0, 0x96BC, + 0xF6C1, 0x96BD, 0xF6C2, 0x96CE, 0xF6C3, 0x96D2, 0xF6C4, 0x77BF, + 0xF6C5, 0x96E0, 0xF6C6, 0x928E, 0xF6C7, 0x92AE, 0xF6C8, 0x92C8, + 0xF6C9, 0x933E, 0xF6CA, 0x936A, 0xF6CB, 0x93CA, 0xF6CC, 0x938F, + 0xF6CD, 0x943E, 0xF6CE, 0x946B, 0xF6CF, 0x9C7F, 0xF6D0, 0x9C82, + 0xF6D1, 0x9C85, 0xF6D2, 0x9C86, 0xF6D3, 0x9C87, 0xF6D4, 0x9C88, + 0xF6D5, 0x7A23, 0xF6D6, 0x9C8B, 0xF6D7, 0x9C8E, 0xF6D8, 0x9C90, + 0xF6D9, 0x9C91, 0xF6DA, 0x9C92, 0xF6DB, 0x9C94, 0xF6DC, 0x9C95, + 0xF6DD, 0x9C9A, 0xF6DE, 0x9C9B, 0xF6DF, 0x9C9E, 0xF6E0, 0x9C9F, + 0xF6E1, 0x9CA0, 0xF6E2, 0x9CA1, 0xF6E3, 0x9CA2, 0xF6E4, 0x9CA3, + 0xF6E5, 0x9CA5, 0xF6E6, 0x9CA6, 0xF6E7, 0x9CA7, 0xF6E8, 0x9CA8, + 0xF6E9, 0x9CA9, 0xF6EA, 0x9CAB, 0xF6EB, 0x9CAD, 0xF6EC, 0x9CAE, + 0xF6ED, 0x9CB0, 0xF6EE, 0x9CB1, 0xF6EF, 0x9CB2, 0xF6F0, 0x9CB3, + 0xF6F1, 0x9CB4, 0xF6F2, 0x9CB5, 0xF6F3, 0x9CB6, 0xF6F4, 0x9CB7, + 0xF6F5, 0x9CBA, 0xF6F6, 0x9CBB, 0xF6F7, 0x9CBC, 0xF6F8, 0x9CBD, + 0xF6F9, 0x9CC4, 0xF6FA, 0x9CC5, 0xF6FB, 0x9CC6, 0xF6FC, 0x9CC7, + 0xF6FD, 0x9CCA, 0xF6FE, 0x9CCB, 0xF740, 0x9C3C, 0xF741, 0x9C3D, + 0xF742, 0x9C3E, 0xF743, 0x9C3F, 0xF744, 0x9C40, 0xF745, 0x9C41, + 0xF746, 0x9C42, 0xF747, 0x9C43, 0xF748, 0x9C44, 0xF749, 0x9C45, + 0xF74A, 0x9C46, 0xF74B, 0x9C47, 0xF74C, 0x9C48, 0xF74D, 0x9C49, + 0xF74E, 0x9C4A, 0xF74F, 0x9C4B, 0xF750, 0x9C4C, 0xF751, 0x9C4D, + 0xF752, 0x9C4E, 0xF753, 0x9C4F, 0xF754, 0x9C50, 0xF755, 0x9C51, + 0xF756, 0x9C52, 0xF757, 0x9C53, 0xF758, 0x9C54, 0xF759, 0x9C55, + 0xF75A, 0x9C56, 0xF75B, 0x9C57, 0xF75C, 0x9C58, 0xF75D, 0x9C59, + 0xF75E, 0x9C5A, 0xF75F, 0x9C5B, 0xF760, 0x9C5C, 0xF761, 0x9C5D, + 0xF762, 0x9C5E, 0xF763, 0x9C5F, 0xF764, 0x9C60, 0xF765, 0x9C61, + 0xF766, 0x9C62, 0xF767, 0x9C63, 0xF768, 0x9C64, 0xF769, 0x9C65, + 0xF76A, 0x9C66, 0xF76B, 0x9C67, 0xF76C, 0x9C68, 0xF76D, 0x9C69, + 0xF76E, 0x9C6A, 0xF76F, 0x9C6B, 0xF770, 0x9C6C, 0xF771, 0x9C6D, + 0xF772, 0x9C6E, 0xF773, 0x9C6F, 0xF774, 0x9C70, 0xF775, 0x9C71, + 0xF776, 0x9C72, 0xF777, 0x9C73, 0xF778, 0x9C74, 0xF779, 0x9C75, + 0xF77A, 0x9C76, 0xF77B, 0x9C77, 0xF77C, 0x9C78, 0xF77D, 0x9C79, + 0xF77E, 0x9C7A, 0xF780, 0x9C7B, 0xF781, 0x9C7D, 0xF782, 0x9C7E, + 0xF783, 0x9C80, 0xF784, 0x9C83, 0xF785, 0x9C84, 0xF786, 0x9C89, + 0xF787, 0x9C8A, 0xF788, 0x9C8C, 0xF789, 0x9C8F, 0xF78A, 0x9C93, + 0xF78B, 0x9C96, 0xF78C, 0x9C97, 0xF78D, 0x9C98, 0xF78E, 0x9C99, + 0xF78F, 0x9C9D, 0xF790, 0x9CAA, 0xF791, 0x9CAC, 0xF792, 0x9CAF, + 0xF793, 0x9CB9, 0xF794, 0x9CBE, 0xF795, 0x9CBF, 0xF796, 0x9CC0, + 0xF797, 0x9CC1, 0xF798, 0x9CC2, 0xF799, 0x9CC8, 0xF79A, 0x9CC9, + 0xF79B, 0x9CD1, 0xF79C, 0x9CD2, 0xF79D, 0x9CDA, 0xF79E, 0x9CDB, + 0xF79F, 0x9CE0, 0xF7A0, 0x9CE1, 0xF7A1, 0x9CCC, 0xF7A2, 0x9CCD, + 0xF7A3, 0x9CCE, 0xF7A4, 0x9CCF, 0xF7A5, 0x9CD0, 0xF7A6, 0x9CD3, + 0xF7A7, 0x9CD4, 0xF7A8, 0x9CD5, 0xF7A9, 0x9CD7, 0xF7AA, 0x9CD8, + 0xF7AB, 0x9CD9, 0xF7AC, 0x9CDC, 0xF7AD, 0x9CDD, 0xF7AE, 0x9CDF, + 0xF7AF, 0x9CE2, 0xF7B0, 0x977C, 0xF7B1, 0x9785, 0xF7B2, 0x9791, + 0xF7B3, 0x9792, 0xF7B4, 0x9794, 0xF7B5, 0x97AF, 0xF7B6, 0x97AB, + 0xF7B7, 0x97A3, 0xF7B8, 0x97B2, 0xF7B9, 0x97B4, 0xF7BA, 0x9AB1, + 0xF7BB, 0x9AB0, 0xF7BC, 0x9AB7, 0xF7BD, 0x9E58, 0xF7BE, 0x9AB6, + 0xF7BF, 0x9ABA, 0xF7C0, 0x9ABC, 0xF7C1, 0x9AC1, 0xF7C2, 0x9AC0, + 0xF7C3, 0x9AC5, 0xF7C4, 0x9AC2, 0xF7C5, 0x9ACB, 0xF7C6, 0x9ACC, + 0xF7C7, 0x9AD1, 0xF7C8, 0x9B45, 0xF7C9, 0x9B43, 0xF7CA, 0x9B47, + 0xF7CB, 0x9B49, 0xF7CC, 0x9B48, 0xF7CD, 0x9B4D, 0xF7CE, 0x9B51, + 0xF7CF, 0x98E8, 0xF7D0, 0x990D, 0xF7D1, 0x992E, 0xF7D2, 0x9955, + 0xF7D3, 0x9954, 0xF7D4, 0x9ADF, 0xF7D5, 0x9AE1, 0xF7D6, 0x9AE6, + 0xF7D7, 0x9AEF, 0xF7D8, 0x9AEB, 0xF7D9, 0x9AFB, 0xF7DA, 0x9AED, + 0xF7DB, 0x9AF9, 0xF7DC, 0x9B08, 0xF7DD, 0x9B0F, 0xF7DE, 0x9B13, + 0xF7DF, 0x9B1F, 0xF7E0, 0x9B23, 0xF7E1, 0x9EBD, 0xF7E2, 0x9EBE, + 0xF7E3, 0x7E3B, 0xF7E4, 0x9E82, 0xF7E5, 0x9E87, 0xF7E6, 0x9E88, + 0xF7E7, 0x9E8B, 0xF7E8, 0x9E92, 0xF7E9, 0x93D6, 0xF7EA, 0x9E9D, + 0xF7EB, 0x9E9F, 0xF7EC, 0x9EDB, 0xF7ED, 0x9EDC, 0xF7EE, 0x9EDD, + 0xF7EF, 0x9EE0, 0xF7F0, 0x9EDF, 0xF7F1, 0x9EE2, 0xF7F2, 0x9EE9, + 0xF7F3, 0x9EE7, 0xF7F4, 0x9EE5, 0xF7F5, 0x9EEA, 0xF7F6, 0x9EEF, + 0xF7F7, 0x9F22, 0xF7F8, 0x9F2C, 0xF7F9, 0x9F2F, 0xF7FA, 0x9F39, + 0xF7FB, 0x9F37, 0xF7FC, 0x9F3D, 0xF7FD, 0x9F3E, 0xF7FE, 0x9F44, + 0xF840, 0x9CE3, 0xF841, 0x9CE4, 0xF842, 0x9CE5, 0xF843, 0x9CE6, + 0xF844, 0x9CE7, 0xF845, 0x9CE8, 0xF846, 0x9CE9, 0xF847, 0x9CEA, + 0xF848, 0x9CEB, 0xF849, 0x9CEC, 0xF84A, 0x9CED, 0xF84B, 0x9CEE, + 0xF84C, 0x9CEF, 0xF84D, 0x9CF0, 0xF84E, 0x9CF1, 0xF84F, 0x9CF2, + 0xF850, 0x9CF3, 0xF851, 0x9CF4, 0xF852, 0x9CF5, 0xF853, 0x9CF6, + 0xF854, 0x9CF7, 0xF855, 0x9CF8, 0xF856, 0x9CF9, 0xF857, 0x9CFA, + 0xF858, 0x9CFB, 0xF859, 0x9CFC, 0xF85A, 0x9CFD, 0xF85B, 0x9CFE, + 0xF85C, 0x9CFF, 0xF85D, 0x9D00, 0xF85E, 0x9D01, 0xF85F, 0x9D02, + 0xF860, 0x9D03, 0xF861, 0x9D04, 0xF862, 0x9D05, 0xF863, 0x9D06, + 0xF864, 0x9D07, 0xF865, 0x9D08, 0xF866, 0x9D09, 0xF867, 0x9D0A, + 0xF868, 0x9D0B, 0xF869, 0x9D0C, 0xF86A, 0x9D0D, 0xF86B, 0x9D0E, + 0xF86C, 0x9D0F, 0xF86D, 0x9D10, 0xF86E, 0x9D11, 0xF86F, 0x9D12, + 0xF870, 0x9D13, 0xF871, 0x9D14, 0xF872, 0x9D15, 0xF873, 0x9D16, + 0xF874, 0x9D17, 0xF875, 0x9D18, 0xF876, 0x9D19, 0xF877, 0x9D1A, + 0xF878, 0x9D1B, 0xF879, 0x9D1C, 0xF87A, 0x9D1D, 0xF87B, 0x9D1E, + 0xF87C, 0x9D1F, 0xF87D, 0x9D20, 0xF87E, 0x9D21, 0xF880, 0x9D22, + 0xF881, 0x9D23, 0xF882, 0x9D24, 0xF883, 0x9D25, 0xF884, 0x9D26, + 0xF885, 0x9D27, 0xF886, 0x9D28, 0xF887, 0x9D29, 0xF888, 0x9D2A, + 0xF889, 0x9D2B, 0xF88A, 0x9D2C, 0xF88B, 0x9D2D, 0xF88C, 0x9D2E, + 0xF88D, 0x9D2F, 0xF88E, 0x9D30, 0xF88F, 0x9D31, 0xF890, 0x9D32, + 0xF891, 0x9D33, 0xF892, 0x9D34, 0xF893, 0x9D35, 0xF894, 0x9D36, + 0xF895, 0x9D37, 0xF896, 0x9D38, 0xF897, 0x9D39, 0xF898, 0x9D3A, + 0xF899, 0x9D3B, 0xF89A, 0x9D3C, 0xF89B, 0x9D3D, 0xF89C, 0x9D3E, + 0xF89D, 0x9D3F, 0xF89E, 0x9D40, 0xF89F, 0x9D41, 0xF8A0, 0x9D42, + 0xF940, 0x9D43, 0xF941, 0x9D44, 0xF942, 0x9D45, 0xF943, 0x9D46, + 0xF944, 0x9D47, 0xF945, 0x9D48, 0xF946, 0x9D49, 0xF947, 0x9D4A, + 0xF948, 0x9D4B, 0xF949, 0x9D4C, 0xF94A, 0x9D4D, 0xF94B, 0x9D4E, + 0xF94C, 0x9D4F, 0xF94D, 0x9D50, 0xF94E, 0x9D51, 0xF94F, 0x9D52, + 0xF950, 0x9D53, 0xF951, 0x9D54, 0xF952, 0x9D55, 0xF953, 0x9D56, + 0xF954, 0x9D57, 0xF955, 0x9D58, 0xF956, 0x9D59, 0xF957, 0x9D5A, + 0xF958, 0x9D5B, 0xF959, 0x9D5C, 0xF95A, 0x9D5D, 0xF95B, 0x9D5E, + 0xF95C, 0x9D5F, 0xF95D, 0x9D60, 0xF95E, 0x9D61, 0xF95F, 0x9D62, + 0xF960, 0x9D63, 0xF961, 0x9D64, 0xF962, 0x9D65, 0xF963, 0x9D66, + 0xF964, 0x9D67, 0xF965, 0x9D68, 0xF966, 0x9D69, 0xF967, 0x9D6A, + 0xF968, 0x9D6B, 0xF969, 0x9D6C, 0xF96A, 0x9D6D, 0xF96B, 0x9D6E, + 0xF96C, 0x9D6F, 0xF96D, 0x9D70, 0xF96E, 0x9D71, 0xF96F, 0x9D72, + 0xF970, 0x9D73, 0xF971, 0x9D74, 0xF972, 0x9D75, 0xF973, 0x9D76, + 0xF974, 0x9D77, 0xF975, 0x9D78, 0xF976, 0x9D79, 0xF977, 0x9D7A, + 0xF978, 0x9D7B, 0xF979, 0x9D7C, 0xF97A, 0x9D7D, 0xF97B, 0x9D7E, + 0xF97C, 0x9D7F, 0xF97D, 0x9D80, 0xF97E, 0x9D81, 0xF980, 0x9D82, + 0xF981, 0x9D83, 0xF982, 0x9D84, 0xF983, 0x9D85, 0xF984, 0x9D86, + 0xF985, 0x9D87, 0xF986, 0x9D88, 0xF987, 0x9D89, 0xF988, 0x9D8A, + 0xF989, 0x9D8B, 0xF98A, 0x9D8C, 0xF98B, 0x9D8D, 0xF98C, 0x9D8E, + 0xF98D, 0x9D8F, 0xF98E, 0x9D90, 0xF98F, 0x9D91, 0xF990, 0x9D92, + 0xF991, 0x9D93, 0xF992, 0x9D94, 0xF993, 0x9D95, 0xF994, 0x9D96, + 0xF995, 0x9D97, 0xF996, 0x9D98, 0xF997, 0x9D99, 0xF998, 0x9D9A, + 0xF999, 0x9D9B, 0xF99A, 0x9D9C, 0xF99B, 0x9D9D, 0xF99C, 0x9D9E, + 0xF99D, 0x9D9F, 0xF99E, 0x9DA0, 0xF99F, 0x9DA1, 0xF9A0, 0x9DA2, + 0xFA40, 0x9DA3, 0xFA41, 0x9DA4, 0xFA42, 0x9DA5, 0xFA43, 0x9DA6, + 0xFA44, 0x9DA7, 0xFA45, 0x9DA8, 0xFA46, 0x9DA9, 0xFA47, 0x9DAA, + 0xFA48, 0x9DAB, 0xFA49, 0x9DAC, 0xFA4A, 0x9DAD, 0xFA4B, 0x9DAE, + 0xFA4C, 0x9DAF, 0xFA4D, 0x9DB0, 0xFA4E, 0x9DB1, 0xFA4F, 0x9DB2, + 0xFA50, 0x9DB3, 0xFA51, 0x9DB4, 0xFA52, 0x9DB5, 0xFA53, 0x9DB6, + 0xFA54, 0x9DB7, 0xFA55, 0x9DB8, 0xFA56, 0x9DB9, 0xFA57, 0x9DBA, + 0xFA58, 0x9DBB, 0xFA59, 0x9DBC, 0xFA5A, 0x9DBD, 0xFA5B, 0x9DBE, + 0xFA5C, 0x9DBF, 0xFA5D, 0x9DC0, 0xFA5E, 0x9DC1, 0xFA5F, 0x9DC2, + 0xFA60, 0x9DC3, 0xFA61, 0x9DC4, 0xFA62, 0x9DC5, 0xFA63, 0x9DC6, + 0xFA64, 0x9DC7, 0xFA65, 0x9DC8, 0xFA66, 0x9DC9, 0xFA67, 0x9DCA, + 0xFA68, 0x9DCB, 0xFA69, 0x9DCC, 0xFA6A, 0x9DCD, 0xFA6B, 0x9DCE, + 0xFA6C, 0x9DCF, 0xFA6D, 0x9DD0, 0xFA6E, 0x9DD1, 0xFA6F, 0x9DD2, + 0xFA70, 0x9DD3, 0xFA71, 0x9DD4, 0xFA72, 0x9DD5, 0xFA73, 0x9DD6, + 0xFA74, 0x9DD7, 0xFA75, 0x9DD8, 0xFA76, 0x9DD9, 0xFA77, 0x9DDA, + 0xFA78, 0x9DDB, 0xFA79, 0x9DDC, 0xFA7A, 0x9DDD, 0xFA7B, 0x9DDE, + 0xFA7C, 0x9DDF, 0xFA7D, 0x9DE0, 0xFA7E, 0x9DE1, 0xFA80, 0x9DE2, + 0xFA81, 0x9DE3, 0xFA82, 0x9DE4, 0xFA83, 0x9DE5, 0xFA84, 0x9DE6, + 0xFA85, 0x9DE7, 0xFA86, 0x9DE8, 0xFA87, 0x9DE9, 0xFA88, 0x9DEA, + 0xFA89, 0x9DEB, 0xFA8A, 0x9DEC, 0xFA8B, 0x9DED, 0xFA8C, 0x9DEE, + 0xFA8D, 0x9DEF, 0xFA8E, 0x9DF0, 0xFA8F, 0x9DF1, 0xFA90, 0x9DF2, + 0xFA91, 0x9DF3, 0xFA92, 0x9DF4, 0xFA93, 0x9DF5, 0xFA94, 0x9DF6, + 0xFA95, 0x9DF7, 0xFA96, 0x9DF8, 0xFA97, 0x9DF9, 0xFA98, 0x9DFA, + 0xFA99, 0x9DFB, 0xFA9A, 0x9DFC, 0xFA9B, 0x9DFD, 0xFA9C, 0x9DFE, + 0xFA9D, 0x9DFF, 0xFA9E, 0x9E00, 0xFA9F, 0x9E01, 0xFAA0, 0x9E02, + 0xFB40, 0x9E03, 0xFB41, 0x9E04, 0xFB42, 0x9E05, 0xFB43, 0x9E06, + 0xFB44, 0x9E07, 0xFB45, 0x9E08, 0xFB46, 0x9E09, 0xFB47, 0x9E0A, + 0xFB48, 0x9E0B, 0xFB49, 0x9E0C, 0xFB4A, 0x9E0D, 0xFB4B, 0x9E0E, + 0xFB4C, 0x9E0F, 0xFB4D, 0x9E10, 0xFB4E, 0x9E11, 0xFB4F, 0x9E12, + 0xFB50, 0x9E13, 0xFB51, 0x9E14, 0xFB52, 0x9E15, 0xFB53, 0x9E16, + 0xFB54, 0x9E17, 0xFB55, 0x9E18, 0xFB56, 0x9E19, 0xFB57, 0x9E1A, + 0xFB58, 0x9E1B, 0xFB59, 0x9E1C, 0xFB5A, 0x9E1D, 0xFB5B, 0x9E1E, + 0xFB5C, 0x9E24, 0xFB5D, 0x9E27, 0xFB5E, 0x9E2E, 0xFB5F, 0x9E30, + 0xFB60, 0x9E34, 0xFB61, 0x9E3B, 0xFB62, 0x9E3C, 0xFB63, 0x9E40, + 0xFB64, 0x9E4D, 0xFB65, 0x9E50, 0xFB66, 0x9E52, 0xFB67, 0x9E53, + 0xFB68, 0x9E54, 0xFB69, 0x9E56, 0xFB6A, 0x9E59, 0xFB6B, 0x9E5D, + 0xFB6C, 0x9E5F, 0xFB6D, 0x9E60, 0xFB6E, 0x9E61, 0xFB6F, 0x9E62, + 0xFB70, 0x9E65, 0xFB71, 0x9E6E, 0xFB72, 0x9E6F, 0xFB73, 0x9E72, + 0xFB74, 0x9E74, 0xFB75, 0x9E75, 0xFB76, 0x9E76, 0xFB77, 0x9E77, + 0xFB78, 0x9E78, 0xFB79, 0x9E79, 0xFB7A, 0x9E7A, 0xFB7B, 0x9E7B, + 0xFB7C, 0x9E7C, 0xFB7D, 0x9E7D, 0xFB7E, 0x9E80, 0xFB80, 0x9E81, + 0xFB81, 0x9E83, 0xFB82, 0x9E84, 0xFB83, 0x9E85, 0xFB84, 0x9E86, + 0xFB85, 0x9E89, 0xFB86, 0x9E8A, 0xFB87, 0x9E8C, 0xFB88, 0x9E8D, + 0xFB89, 0x9E8E, 0xFB8A, 0x9E8F, 0xFB8B, 0x9E90, 0xFB8C, 0x9E91, + 0xFB8D, 0x9E94, 0xFB8E, 0x9E95, 0xFB8F, 0x9E96, 0xFB90, 0x9E97, + 0xFB91, 0x9E98, 0xFB92, 0x9E99, 0xFB93, 0x9E9A, 0xFB94, 0x9E9B, + 0xFB95, 0x9E9C, 0xFB96, 0x9E9E, 0xFB97, 0x9EA0, 0xFB98, 0x9EA1, + 0xFB99, 0x9EA2, 0xFB9A, 0x9EA3, 0xFB9B, 0x9EA4, 0xFB9C, 0x9EA5, + 0xFB9D, 0x9EA7, 0xFB9E, 0x9EA8, 0xFB9F, 0x9EA9, 0xFBA0, 0x9EAA, + 0xFC40, 0x9EAB, 0xFC41, 0x9EAC, 0xFC42, 0x9EAD, 0xFC43, 0x9EAE, + 0xFC44, 0x9EAF, 0xFC45, 0x9EB0, 0xFC46, 0x9EB1, 0xFC47, 0x9EB2, + 0xFC48, 0x9EB3, 0xFC49, 0x9EB5, 0xFC4A, 0x9EB6, 0xFC4B, 0x9EB7, + 0xFC4C, 0x9EB9, 0xFC4D, 0x9EBA, 0xFC4E, 0x9EBC, 0xFC4F, 0x9EBF, + 0xFC50, 0x9EC0, 0xFC51, 0x9EC1, 0xFC52, 0x9EC2, 0xFC53, 0x9EC3, + 0xFC54, 0x9EC5, 0xFC55, 0x9EC6, 0xFC56, 0x9EC7, 0xFC57, 0x9EC8, + 0xFC58, 0x9ECA, 0xFC59, 0x9ECB, 0xFC5A, 0x9ECC, 0xFC5B, 0x9ED0, + 0xFC5C, 0x9ED2, 0xFC5D, 0x9ED3, 0xFC5E, 0x9ED5, 0xFC5F, 0x9ED6, + 0xFC60, 0x9ED7, 0xFC61, 0x9ED9, 0xFC62, 0x9EDA, 0xFC63, 0x9EDE, + 0xFC64, 0x9EE1, 0xFC65, 0x9EE3, 0xFC66, 0x9EE4, 0xFC67, 0x9EE6, + 0xFC68, 0x9EE8, 0xFC69, 0x9EEB, 0xFC6A, 0x9EEC, 0xFC6B, 0x9EED, + 0xFC6C, 0x9EEE, 0xFC6D, 0x9EF0, 0xFC6E, 0x9EF1, 0xFC6F, 0x9EF2, + 0xFC70, 0x9EF3, 0xFC71, 0x9EF4, 0xFC72, 0x9EF5, 0xFC73, 0x9EF6, + 0xFC74, 0x9EF7, 0xFC75, 0x9EF8, 0xFC76, 0x9EFA, 0xFC77, 0x9EFD, + 0xFC78, 0x9EFF, 0xFC79, 0x9F00, 0xFC7A, 0x9F01, 0xFC7B, 0x9F02, + 0xFC7C, 0x9F03, 0xFC7D, 0x9F04, 0xFC7E, 0x9F05, 0xFC80, 0x9F06, + 0xFC81, 0x9F07, 0xFC82, 0x9F08, 0xFC83, 0x9F09, 0xFC84, 0x9F0A, + 0xFC85, 0x9F0C, 0xFC86, 0x9F0F, 0xFC87, 0x9F11, 0xFC88, 0x9F12, + 0xFC89, 0x9F14, 0xFC8A, 0x9F15, 0xFC8B, 0x9F16, 0xFC8C, 0x9F18, + 0xFC8D, 0x9F1A, 0xFC8E, 0x9F1B, 0xFC8F, 0x9F1C, 0xFC90, 0x9F1D, + 0xFC91, 0x9F1E, 0xFC92, 0x9F1F, 0xFC93, 0x9F21, 0xFC94, 0x9F23, + 0xFC95, 0x9F24, 0xFC96, 0x9F25, 0xFC97, 0x9F26, 0xFC98, 0x9F27, + 0xFC99, 0x9F28, 0xFC9A, 0x9F29, 0xFC9B, 0x9F2A, 0xFC9C, 0x9F2B, + 0xFC9D, 0x9F2D, 0xFC9E, 0x9F2E, 0xFC9F, 0x9F30, 0xFCA0, 0x9F31, + 0xFD40, 0x9F32, 0xFD41, 0x9F33, 0xFD42, 0x9F34, 0xFD43, 0x9F35, + 0xFD44, 0x9F36, 0xFD45, 0x9F38, 0xFD46, 0x9F3A, 0xFD47, 0x9F3C, + 0xFD48, 0x9F3F, 0xFD49, 0x9F40, 0xFD4A, 0x9F41, 0xFD4B, 0x9F42, + 0xFD4C, 0x9F43, 0xFD4D, 0x9F45, 0xFD4E, 0x9F46, 0xFD4F, 0x9F47, + 0xFD50, 0x9F48, 0xFD51, 0x9F49, 0xFD52, 0x9F4A, 0xFD53, 0x9F4B, + 0xFD54, 0x9F4C, 0xFD55, 0x9F4D, 0xFD56, 0x9F4E, 0xFD57, 0x9F4F, + 0xFD58, 0x9F52, 0xFD59, 0x9F53, 0xFD5A, 0x9F54, 0xFD5B, 0x9F55, + 0xFD5C, 0x9F56, 0xFD5D, 0x9F57, 0xFD5E, 0x9F58, 0xFD5F, 0x9F59, + 0xFD60, 0x9F5A, 0xFD61, 0x9F5B, 0xFD62, 0x9F5C, 0xFD63, 0x9F5D, + 0xFD64, 0x9F5E, 0xFD65, 0x9F5F, 0xFD66, 0x9F60, 0xFD67, 0x9F61, + 0xFD68, 0x9F62, 0xFD69, 0x9F63, 0xFD6A, 0x9F64, 0xFD6B, 0x9F65, + 0xFD6C, 0x9F66, 0xFD6D, 0x9F67, 0xFD6E, 0x9F68, 0xFD6F, 0x9F69, + 0xFD70, 0x9F6A, 0xFD71, 0x9F6B, 0xFD72, 0x9F6C, 0xFD73, 0x9F6D, + 0xFD74, 0x9F6E, 0xFD75, 0x9F6F, 0xFD76, 0x9F70, 0xFD77, 0x9F71, + 0xFD78, 0x9F72, 0xFD79, 0x9F73, 0xFD7A, 0x9F74, 0xFD7B, 0x9F75, + 0xFD7C, 0x9F76, 0xFD7D, 0x9F77, 0xFD7E, 0x9F78, 0xFD80, 0x9F79, + 0xFD81, 0x9F7A, 0xFD82, 0x9F7B, 0xFD83, 0x9F7C, 0xFD84, 0x9F7D, + 0xFD85, 0x9F7E, 0xFD86, 0x9F81, 0xFD87, 0x9F82, 0xFD88, 0x9F8D, + 0xFD89, 0x9F8E, 0xFD8A, 0x9F8F, 0xFD8B, 0x9F90, 0xFD8C, 0x9F91, + 0xFD8D, 0x9F92, 0xFD8E, 0x9F93, 0xFD8F, 0x9F94, 0xFD90, 0x9F95, + 0xFD91, 0x9F96, 0xFD92, 0x9F97, 0xFD93, 0x9F98, 0xFD94, 0x9F9C, + 0xFD95, 0x9F9D, 0xFD96, 0x9F9E, 0xFD97, 0x9FA1, 0xFD98, 0x9FA2, + 0xFD99, 0x9FA3, 0xFD9A, 0x9FA4, 0xFD9B, 0x9FA5, 0xFD9C, 0xF92C, + 0xFD9D, 0xF979, 0xFD9E, 0xF995, 0xFD9F, 0xF9E7, 0xFDA0, 0xF9F1, + 0xFE40, 0xFA0C, 0xFE41, 0xFA0D, 0xFE42, 0xFA0E, 0xFE43, 0xFA0F, + 0xFE44, 0xFA11, 0xFE45, 0xFA13, 0xFE46, 0xFA14, 0xFE47, 0xFA18, + 0xFE48, 0xFA1F, 0xFE49, 0xFA20, 0xFE4A, 0xFA21, 0xFE4B, 0xFA23, + 0xFE4C, 0xFA24, 0xFE4D, 0xFA27, 0xFE4E, 0xFA28, 0xFE4F, 0xFA29, + 0, 0 +}; + + + +WCHAR ff_convert ( /* Converted code, 0 means conversion error */ + WCHAR chr, /* Character code to be converted */ + UINT dir /* 0: Unicode to OEM code, 1: OEM code to Unicode */ +) +{ + const WCHAR *p; + WCHAR c; + int i, n, li, hi; + + + if (chr < 0x80) /* ASCII */ + { + c = chr; + } + else + { + if (dir) /* OEM code to unicode */ + { + p = oem2uni; + hi = sizeof oem2uni / 4 - 1; + } + else /* Unicode to OEM code */ + { + p = uni2oem; + hi = sizeof uni2oem / 4 - 1; + } + li = 0; + for (n = 16; n; n--) + { + i = li + (hi - li) / 2; + if (chr == p[i * 2]) break; + if (chr > p[i * 2]) + li = i; + else + hi = i; + } + c = n ? p[i * 2 + 1] : 0; + } + + return c; +} + + + +WCHAR ff_wtoupper ( /* Returns upper converted character */ + WCHAR chr /* Unicode character to be upper converted (BMP only) */ +) +{ + /* Compressed upper conversion table */ + static const WCHAR cvt1[] = /* U+0000 - U+0FFF */ + { + /* Basic Latin */ + 0x0061, 0x031A, + /* Latin-1 Supplement */ + 0x00E0, 0x0317, 0x00F8, 0x0307, 0x00FF, 0x0001, 0x0178, + /* Latin Extended-A */ + 0x0100, 0x0130, 0x0132, 0x0106, 0x0139, 0x0110, 0x014A, 0x012E, 0x0179, 0x0106, + /* Latin Extended-B */ + 0x0180, 0x004D, 0x0243, 0x0181, 0x0182, 0x0182, 0x0184, 0x0184, 0x0186, 0x0187, 0x0187, 0x0189, 0x018A, 0x018B, 0x018B, 0x018D, 0x018E, 0x018F, 0x0190, 0x0191, 0x0191, 0x0193, 0x0194, 0x01F6, 0x0196, 0x0197, 0x0198, 0x0198, 0x023D, 0x019B, 0x019C, 0x019D, 0x0220, 0x019F, 0x01A0, 0x01A0, 0x01A2, 0x01A2, 0x01A4, 0x01A4, 0x01A6, 0x01A7, 0x01A7, 0x01A9, 0x01AA, 0x01AB, 0x01AC, 0x01AC, 0x01AE, 0x01AF, 0x01AF, 0x01B1, 0x01B2, 0x01B3, 0x01B3, 0x01B5, 0x01B5, 0x01B7, 0x01B8, 0x01B8, 0x01BA, 0x01BB, 0x01BC, 0x01BC, 0x01BE, 0x01F7, 0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x01C4, 0x01C5, 0x01C4, 0x01C7, 0x01C8, 0x01C7, 0x01CA, 0x01CB, 0x01CA, + 0x01CD, 0x0110, 0x01DD, 0x0001, 0x018E, 0x01DE, 0x0112, 0x01F3, 0x0003, 0x01F1, 0x01F4, 0x01F4, 0x01F8, 0x0128, + 0x0222, 0x0112, 0x023A, 0x0009, 0x2C65, 0x023B, 0x023B, 0x023D, 0x2C66, 0x023F, 0x0240, 0x0241, 0x0241, 0x0246, 0x010A, + /* IPA Extensions */ + 0x0253, 0x0040, 0x0181, 0x0186, 0x0255, 0x0189, 0x018A, 0x0258, 0x018F, 0x025A, 0x0190, 0x025C, 0x025D, 0x025E, 0x025F, 0x0193, 0x0261, 0x0262, 0x0194, 0x0264, 0x0265, 0x0266, 0x0267, 0x0197, 0x0196, 0x026A, 0x2C62, 0x026C, 0x026D, 0x026E, 0x019C, 0x0270, 0x0271, 0x019D, 0x0273, 0x0274, 0x019F, 0x0276, 0x0277, 0x0278, 0x0279, 0x027A, 0x027B, 0x027C, 0x2C64, 0x027E, 0x027F, 0x01A6, 0x0281, 0x0282, 0x01A9, 0x0284, 0x0285, 0x0286, 0x0287, 0x01AE, 0x0244, 0x01B1, 0x01B2, 0x0245, 0x028D, 0x028E, 0x028F, 0x0290, 0x0291, 0x01B7, + /* Greek, Coptic */ + 0x037B, 0x0003, 0x03FD, 0x03FE, 0x03FF, 0x03AC, 0x0004, 0x0386, 0x0388, 0x0389, 0x038A, 0x03B1, 0x0311, + 0x03C2, 0x0002, 0x03A3, 0x03A3, 0x03C4, 0x0308, 0x03CC, 0x0003, 0x038C, 0x038E, 0x038F, 0x03D8, 0x0118, + 0x03F2, 0x000A, 0x03F9, 0x03F3, 0x03F4, 0x03F5, 0x03F6, 0x03F7, 0x03F7, 0x03F9, 0x03FA, 0x03FA, + /* Cyrillic */ + 0x0430, 0x0320, 0x0450, 0x0710, 0x0460, 0x0122, 0x048A, 0x0136, 0x04C1, 0x010E, 0x04CF, 0x0001, 0x04C0, 0x04D0, 0x0144, + /* Armenian */ + 0x0561, 0x0426, + + 0x0000 + }; + static const WCHAR cvt2[] = /* U+1000 - U+FFFF */ + { + /* Phonetic Extensions */ + 0x1D7D, 0x0001, 0x2C63, + /* Latin Extended Additional */ + 0x1E00, 0x0196, 0x1EA0, 0x015A, + /* Greek Extended */ + 0x1F00, 0x0608, 0x1F10, 0x0606, 0x1F20, 0x0608, 0x1F30, 0x0608, 0x1F40, 0x0606, + 0x1F51, 0x0007, 0x1F59, 0x1F52, 0x1F5B, 0x1F54, 0x1F5D, 0x1F56, 0x1F5F, 0x1F60, 0x0608, + 0x1F70, 0x000E, 0x1FBA, 0x1FBB, 0x1FC8, 0x1FC9, 0x1FCA, 0x1FCB, 0x1FDA, 0x1FDB, 0x1FF8, 0x1FF9, 0x1FEA, 0x1FEB, 0x1FFA, 0x1FFB, + 0x1F80, 0x0608, 0x1F90, 0x0608, 0x1FA0, 0x0608, 0x1FB0, 0x0004, 0x1FB8, 0x1FB9, 0x1FB2, 0x1FBC, + 0x1FCC, 0x0001, 0x1FC3, 0x1FD0, 0x0602, 0x1FE0, 0x0602, 0x1FE5, 0x0001, 0x1FEC, 0x1FF2, 0x0001, 0x1FFC, + /* Letterlike Symbols */ + 0x214E, 0x0001, 0x2132, + /* Number forms */ + 0x2170, 0x0210, 0x2184, 0x0001, 0x2183, + /* Enclosed Alphanumerics */ + 0x24D0, 0x051A, 0x2C30, 0x042F, + /* Latin Extended-C */ + 0x2C60, 0x0102, 0x2C67, 0x0106, 0x2C75, 0x0102, + /* Coptic */ + 0x2C80, 0x0164, + /* Georgian Supplement */ + 0x2D00, 0x0826, + /* Full-width */ + 0xFF41, 0x031A, + + 0x0000 + }; + const WCHAR *p; + WCHAR bc, nc, cmd; + + + p = chr < 0x1000 ? cvt1 : cvt2; + for (;;) + { + bc = *p++; /* Get block base */ + if (!bc || chr < bc) break; + nc = *p++; + cmd = nc >> 8; + nc &= 0xFF; /* Get processing command and block size */ + if (chr < bc + nc) /* In the block? */ + { + switch (cmd) + { + case 0: + chr = p[chr - bc]; + break; /* Table conversion */ + case 1: + chr -= (chr - bc) & 1; + break; /* Case pairs */ + case 2: + chr -= 16; + break; /* Shift -16 */ + case 3: + chr -= 32; + break; /* Shift -32 */ + case 4: + chr -= 48; + break; /* Shift -48 */ + case 5: + chr -= 26; + break; /* Shift -26 */ + case 6: + chr += 8; + break; /* Shift +8 */ + case 7: + chr -= 80; + break; /* Shift -80 */ + case 8: + chr -= 0x1C60; + break; /* Shift -0x1C60 */ + } + break; + } + if (!cmd) p += nc; + } + + return chr; +} +#endif diff --git a/beken_os/beken378/func/fatfs/cc936.h b/beken_os/beken378/func/fatfs/cc936.h new file mode 100755 index 0000000..7b5ceb4 --- /dev/null +++ b/beken_os/beken378/func/fatfs/cc936.h @@ -0,0 +1,23 @@ +/* + * cc936.h + * + * Created on: 2017-5-24 + * Author: bo.wang + */ + +#ifndef CC936_H_ +#define CC936_H_ +#include "integer.h" +#include "ffconf.h" + +#if _CODE_PAGE == 936 +WCHAR ff_convert ( /* Converted code, 0 means conversion error */ + WCHAR chr, /* Character code to be converted */ + UINT dir /* 0: Unicode to OEM code, 1: OEM code to Unicode */ +); + +WCHAR ff_wtoupper ( /* Returns upper converted character */ + WCHAR chr /* Unicode character to be upper converted (BMP only) */ +); +#endif +#endif /* CC936_H_ */ diff --git a/beken_os/beken378/func/fatfs/ccsbcs.c b/beken_os/beken378/func/fatfs/ccsbcs.c new file mode 100755 index 0000000..e982ace --- /dev/null +++ b/beken_os/beken378/func/fatfs/ccsbcs.c @@ -0,0 +1,438 @@ +/*------------------------------------------------------------------------*/ +/* Unicode - Local code bidirectional converter (C)ChaN, 2015 */ +/* (SBCS code pages) */ +/*------------------------------------------------------------------------*/ +/* 437 U.S. +/ 720 Arabic +/ 737 Greek +/ 771 KBL +/ 775 Baltic +/ 850 Latin 1 +/ 852 Latin 2 +/ 855 Cyrillic +/ 857 Turkish +/ 860 Portuguese +/ 861 Icelandic +/ 862 Hebrew +/ 863 Canadian French +/ 864 Arabic +/ 865 Nordic +/ 866 Russian +/ 869 Greek 2 +*/ + +//#include "ff.h" + +#include"ccsbcs.h" + +#if _CODE_PAGE == 437 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = /* CP437(0x80-0xFF) to Unicode conversion table */ +{ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, + 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, + 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +}; + +#elif _CODE_PAGE == 720 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = /* CP720(0x80-0xFF) to Unicode conversion table */ +{ + 0x0000, 0x0000, 0x00E9, 0x00E2, 0x0000, 0x00E0, 0x0000, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0651, 0x0652, 0x00F4, 0x00A4, 0x0640, 0x00FB, 0x00F9, 0x0621, 0x0622, 0x0623, 0x0624, 0x00A3, 0x0625, 0x0626, 0x0627, + 0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x0636, 0x0637, 0x0638, 0x0639, 0x063A, 0x0641, 0x00B5, 0x0642, 0x0643, 0x0644, 0x0645, 0x0646, 0x0647, 0x0648, 0x0649, 0x064A, + 0x2261, 0x064B, 0x064C, 0x064D, 0x064E, 0x064F, 0x0650, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +}; + +#elif _CODE_PAGE == 737 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = /* CP737(0x80-0xFF) to Unicode conversion table */ +{ + 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, 0x03A0, + 0x03A1, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8, + 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0, 0x03C1, 0x03C3, 0x03C2, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x03C9, 0x03AC, 0x03AD, 0x03AE, 0x03CA, 0x03AF, 0x03CC, 0x03CD, 0x03CB, 0x03CE, 0x0386, 0x0388, 0x0389, 0x038A, 0x038C, 0x038E, + 0x038F, 0x00B1, 0x2265, 0x2264, 0x03AA, 0x03AB, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +}; + +#elif _CODE_PAGE == 771 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = /* CP771(0x80-0xFF) to Unicode conversion table */ +{ + 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, + 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, + 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x2558, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x0104, 0x0105, 0x010C, 0x010D, + 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F, + 0x0118, 0x0119, 0x0116, 0x0117, 0x012E, 0x012F, 0x0160, 0x0161, 0x0172, 0x0173, 0x016A, 0x016B, 0x017D, 0x017E, 0x25A0, 0x00A0 +}; + +#elif _CODE_PAGE == 775 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = /* CP775(0x80-0xFF) to Unicode conversion table */ +{ + 0x0106, 0x00FC, 0x00E9, 0x0101, 0x00E4, 0x0123, 0x00E5, 0x0107, 0x0142, 0x0113, 0x0156, 0x0157, 0x012B, 0x0179, 0x00C4, 0x00C5, + 0x00C9, 0x00E6, 0x00C6, 0x014D, 0x00F6, 0x0122, 0x00A2, 0x015A, 0x015B, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x00A4, + 0x0100, 0x012A, 0x00F3, 0x017B, 0x017C, 0x017A, 0x201D, 0x00A6, 0x00A9, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x0141, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x0104, 0x010C, 0x0118, 0x0116, 0x2563, 0x2551, 0x2557, 0x255D, 0x012E, 0x0160, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0172, 0x016A, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x017D, + 0x0105, 0x010D, 0x0119, 0x0117, 0x012F, 0x0161, 0x0173, 0x016B, 0x017E, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x00D3, 0x00DF, 0x014C, 0x0143, 0x00F5, 0x00D5, 0x00B5, 0x0144, 0x0136, 0x0137, 0x013B, 0x013C, 0x0146, 0x0112, 0x0145, 0x2019, + 0x00AD, 0x00B1, 0x201C, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x201E, 0x00B0, 0x2219, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0 +}; + +#elif _CODE_PAGE == 850 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = /* CP850(0x80-0xFF) to Unicode conversion table */ +{ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, + 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0, 0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, + 0x00F0, 0x00D0, 0x00CA, 0x00CB, 0x00C8, 0x0131, 0x00CD, 0x00CE, 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580, + 0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x00FE, 0x00DE, 0x00DA, 0x00DB, 0x00D9, 0x00FD, 0x00DD, 0x00AF, 0x00B4, + 0x00AD, 0x00B1, 0x2017, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0 +}; + +#elif _CODE_PAGE == 852 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = /* CP852(0x80-0xFF) to Unicode conversion table */ +{ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x016F, 0x0107, 0x00E7, 0x0142, 0x00EB, 0x0150, 0x0151, 0x00EE, 0x0179, 0x00C4, 0x0106, + 0x00C9, 0x0139, 0x013A, 0x00F4, 0x00F6, 0x013D, 0x013E, 0x015A, 0x015B, 0x00D6, 0x00DC, 0x0164, 0x0165, 0x0141, 0x00D7, 0x010D, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x0104, 0x0105, 0x017D, 0x017E, 0x0118, 0x0119, 0x00AC, 0x017A, 0x010C, 0x015F, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x011A, 0x015E, 0x2563, 0x2551, 0x2557, 0x255D, 0x017B, 0x017C, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0102, 0x0103, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, + 0x0111, 0x0110, 0x010E, 0x00CB, 0x010F, 0x0147, 0x00CD, 0x00CE, 0x011B, 0x2518, 0x250C, 0x2588, 0x2584, 0x0162, 0x016E, 0x2580, + 0x00D3, 0x00DF, 0x00D4, 0x0143, 0x0144, 0x0148, 0x0160, 0x0161, 0x0154, 0x00DA, 0x0155, 0x0170, 0x00FD, 0x00DD, 0x0163, 0x00B4, + 0x00AD, 0x02DD, 0x02DB, 0x02C7, 0x02D8, 0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x02D9, 0x0171, 0x0158, 0x0159, 0x25A0, 0x00A0 +}; + +#elif _CODE_PAGE == 855 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = /* CP855(0x80-0xFF) to Unicode conversion table */ +{ + 0x0452, 0x0402, 0x0453, 0x0403, 0x0451, 0x0401, 0x0454, 0x0404, 0x0455, 0x0405, 0x0456, 0x0406, 0x0457, 0x0407, 0x0458, 0x0408, + 0x0459, 0x0409, 0x045A, 0x040A, 0x045B, 0x040B, 0x045C, 0x040C, 0x045E, 0x040E, 0x045F, 0x040F, 0x044E, 0x042E, 0x044A, 0x042A, + 0x0430, 0x0410, 0x0431, 0x0411, 0x0446, 0x0426, 0x0434, 0x0414, 0x0435, 0x0415, 0x0444, 0x0424, 0x0433, 0x0413, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x0445, 0x0425, 0x0438, 0x0418, 0x2563, 0x2551, 0x2557, 0x255D, 0x0439, 0x0419, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x043A, 0x041A, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, + 0x043B, 0x041B, 0x043C, 0x041C, 0x043D, 0x041D, 0x043E, 0x041E, 0x043F, 0x2518, 0x250C, 0x2588, 0x2584, 0x041F, 0x044F, 0x2580, + 0x042F, 0x0440, 0x0420, 0x0441, 0x0421, 0x0442, 0x0422, 0x0443, 0x0423, 0x0436, 0x0416, 0x0432, 0x0412, 0x044C, 0x042C, 0x2116, + 0x00AD, 0x044B, 0x042B, 0x0437, 0x0417, 0x0448, 0x0428, 0x044D, 0x042D, 0x0449, 0x0429, 0x0447, 0x0427, 0x00A7, 0x25A0, 0x00A0 +}; + +#elif _CODE_PAGE == 857 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = /* CP857(0x80-0xFF) to Unicode conversion table */ +{ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0131, 0x00C4, 0x00C5, + 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x0130, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x015E, 0x015F, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x011E, 0x011F, 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0, 0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, + 0x00BA, 0x00AA, 0x00CA, 0x00CB, 0x00C8, 0x0000, 0x00CD, 0x00CE, 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580, + 0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x0000, 0x00D7, 0x00DA, 0x00DB, 0x00D9, 0x00EC, 0x00FF, 0x00AF, 0x00B4, + 0x00AD, 0x00B1, 0x0000, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0 +}; + +#elif _CODE_PAGE == 860 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = /* CP860(0x80-0xFF) to Unicode conversion table */ +{ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E3, 0x00E0, 0x00C1, 0x00E7, 0x00EA, 0x00CA, 0x00E8, 0x00CD, 0x00D4, 0x00EC, 0x00C3, 0x00C2, + 0x00C9, 0x00C0, 0x00C8, 0x00F4, 0x00F5, 0x00F2, 0x00DA, 0x00F9, 0x00CC, 0x00D5, 0x00DC, 0x00A2, 0x00A3, 0x00D9, 0x20A7, 0x00D3, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x00D2, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x2558, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, + 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +}; + +#elif _CODE_PAGE == 861 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = /* CP861(0x80-0xFF) to Unicode conversion table */ +{ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E6, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00D0, 0x00F0, 0x00DE, 0x00C4, 0x00C5, + 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00FE, 0x00FB, 0x00DD, 0x00FD, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x20A7, 0x0192, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00C1, 0x00CD, 0x00D3, 0x00DA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, + 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +}; + +#elif _CODE_PAGE == 862 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = /* CP862(0x80-0xFF) to Unicode conversion table */ +{ + 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, + 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, 0x05E8, 0x05E9, 0x05EA, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, + 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +}; + +#elif _CODE_PAGE == 863 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = /* CP863(0x80-0xFF) to Unicode conversion table */ +{ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00C2, 0x00E0, 0x00B6, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x2017, 0x00C0, + 0x00C9, 0x00C8, 0x00CA, 0x00F4, 0x00CB, 0x00CF, 0x00FB, 0x00F9, 0x00A4, 0x00D4, 0x00DC, 0x00A2, 0x00A3, 0x00D9, 0x00DB, 0x0192, + 0x00A6, 0x00B4, 0x00F3, 0x00FA, 0x00A8, 0x00BB, 0x00B3, 0x00AF, 0x00CE, 0x3210, 0x00AC, 0x00BD, 0x00BC, 0x00BE, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2219, + 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +}; + +#elif _CODE_PAGE == 864 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = /* CP864(0x80-0xFF) to Unicode conversion table */ +{ + 0x00B0, 0x00B7, 0x2219, 0x221A, 0x2592, 0x2500, 0x2502, 0x253C, 0x2524, 0x252C, 0x251C, 0x2534, 0x2510, 0x250C, 0x2514, 0x2518, + 0x03B2, 0x221E, 0x03C6, 0x00B1, 0x00BD, 0x00BC, 0x2248, 0x00AB, 0x00BB, 0xFEF7, 0xFEF8, 0x0000, 0x0000, 0xFEFB, 0xFEFC, 0x0000, + 0x00A0, 0x00AD, 0xFE82, 0x00A3, 0x00A4, 0xFE84, 0x0000, 0x20AC, 0xFE8E, 0xFE8F, 0xFE95, 0xFE99, 0x060C, 0xFE9D, 0xFEA1, 0xFEA5, + 0x0660, 0x0661, 0x0662, 0x0663, 0x0664, 0x0665, 0x0666, 0x0667, 0x0668, 0x0669, 0xFED1, 0x061B, 0xFEB1, 0xFEB5, 0xFEB9, 0x061F, + 0x00A2, 0xFE80, 0xFE81, 0xFE83, 0xFE85, 0xFECA, 0xFE8B, 0xFE8D, 0xFE91, 0xFE93, 0xFE97, 0xFE9B, 0xFE9F, 0xFEA3, 0xFEA7, 0xFEA9, + 0xFEAB, 0xFEAD, 0xFEAF, 0xFEB3, 0xFEB7, 0xFEBB, 0xFEBF, 0xFEC1, 0xFEC5, 0xFECB, 0xFECF, 0x00A6, 0x00AC, 0x00F7, 0x00D7, 0xFEC9, + 0x0640, 0xFED3, 0xFED7, 0xFEDB, 0xFEDF, 0xFEE3, 0xFEE7, 0xFEEB, 0xFEED, 0xFEEF, 0xFEF3, 0xFEBD, 0xFECC, 0xFECE, 0xFECD, 0xFEE1, + 0xFE7D, 0x0651, 0xFEE5, 0xFEE9, 0xFEEC, 0xFEF0, 0xFEF2, 0xFED0, 0xFED5, 0xFEF5, 0xFEF6, 0xFEDD, 0xFED9, 0xFEF1, 0x25A0, 0x0000 +}; + +#elif _CODE_PAGE == 865 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = /* CP865(0x80-0xFF) to Unicode conversion table */ +{ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, + 0x00C5, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x20A7, 0x0192, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00A4, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x2558, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, + 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +}; + +#elif _CODE_PAGE == 866 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = /* CP866(0x80-0xFF) to Unicode conversion table */ +{ + 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, + 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, + 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F, + 0x0401, 0x0451, 0x0404, 0x0454, 0x0407, 0x0457, 0x040E, 0x045E, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x2116, 0x00A4, 0x25A0, 0x00A0 +}; + +#elif _CODE_PAGE == 869 +#define _TBLDEF 1 +static +const WCHAR Tbl[] = /* CP869(0x80-0xFF) to Unicode conversion table */ +{ + 0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x0386, 0x00B7, 0x00B7, 0x00AC, 0x00A6, 0x2018, 0x2019, 0x0388, 0x2015, 0x0389, + 0x038A, 0x03AA, 0x038C, 0x00B7, 0x00B7, 0x038E, 0x03AB, 0x00A9, 0x038F, 0x00B2, 0x00B3, 0x03AC, 0x00A3, 0x03AD, 0x03AE, 0x03AF, + 0x03CA, 0x0390, 0x03CC, 0x03CD, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x00BD, 0x0398, 0x0399, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x039A, 0x039B, 0x039C, 0x039D, 0x2563, 0x2551, 0x2557, 0x255D, 0x039E, 0x039F, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0A30, 0x03A1, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x03A3, + 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, 0x03B1, 0x03B2, 0x03B3, 0x2518, 0x250C, 0x2588, 0x2584, 0x03B4, 0x03B5, 0x2580, + 0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0, 0x03C1, 0x03C3, 0x03C2, 0x03C4, 0x0384, + 0x00AD, 0x00B1, 0x03C5, 0x03C6, 0x03C7, 0x00A7, 0x03C8, 0x0385, 0x00B0, 0x00A8, 0x03C9, 0x03CB, 0x03B0, 0x03CE, 0x25A0, 0x00A0 +}; + +#endif + + +#if !_TBLDEF || !_USE_LFN +//#error This file is not needed at current configuration. Remove from the project. +#endif + + +#if _TBLDEF&&_CODE_PAGE != 936 + +WCHAR ff_convert ( /* Converted character, Returns zero on error */ + WCHAR chr, /* Character code to be converted */ + UINT dir /* 0: Unicode to OEM code, 1: OEM code to Unicode */ +) +{ + WCHAR c; + + + if (chr < 0x80) /* ASCII */ + { + c = chr; + + } + else + { + if (dir) /* OEM code to Unicode */ + { + c = (chr >= 0x100) ? 0 : Tbl[chr - 0x80]; + + } + else /* Unicode to OEM code */ + { + for (c = 0; c < 0x80; c++) + { + if (chr == Tbl[c]) break; + } + c = (c + 0x80) & 0xFF; + } + } + + return c; +} + + + +WCHAR ff_wtoupper ( /* Returns upper converted character */ + WCHAR chr /* Unicode character to be upper converted (BMP only) */ +) +{ + /* Compressed upper conversion table */ + static const WCHAR cvt1[] = /* U+0000 - U+0FFF */ + { + /* Basic Latin */ + 0x0061, 0x031A, + /* Latin-1 Supplement */ + 0x00E0, 0x0317, 0x00F8, 0x0307, 0x00FF, 0x0001, 0x0178, + /* Latin Extended-A */ + 0x0100, 0x0130, 0x0132, 0x0106, 0x0139, 0x0110, 0x014A, 0x012E, 0x0179, 0x0106, + /* Latin Extended-B */ + 0x0180, 0x004D, 0x0243, 0x0181, 0x0182, 0x0182, 0x0184, 0x0184, 0x0186, 0x0187, 0x0187, 0x0189, 0x018A, 0x018B, 0x018B, 0x018D, 0x018E, 0x018F, 0x0190, 0x0191, 0x0191, 0x0193, 0x0194, 0x01F6, 0x0196, 0x0197, 0x0198, 0x0198, 0x023D, 0x019B, 0x019C, 0x019D, 0x0220, 0x019F, 0x01A0, 0x01A0, 0x01A2, 0x01A2, 0x01A4, 0x01A4, 0x01A6, 0x01A7, 0x01A7, 0x01A9, 0x01AA, 0x01AB, 0x01AC, 0x01AC, 0x01AE, 0x01AF, 0x01AF, 0x01B1, 0x01B2, 0x01B3, 0x01B3, 0x01B5, 0x01B5, 0x01B7, 0x01B8, 0x01B8, 0x01BA, 0x01BB, 0x01BC, 0x01BC, 0x01BE, 0x01F7, 0x01C0, 0x01C1, 0x01C2, 0x01C3, 0x01C4, 0x01C5, 0x01C4, 0x01C7, 0x01C8, 0x01C7, 0x01CA, 0x01CB, 0x01CA, + 0x01CD, 0x0110, 0x01DD, 0x0001, 0x018E, 0x01DE, 0x0112, 0x01F3, 0x0003, 0x01F1, 0x01F4, 0x01F4, 0x01F8, 0x0128, + 0x0222, 0x0112, 0x023A, 0x0009, 0x2C65, 0x023B, 0x023B, 0x023D, 0x2C66, 0x023F, 0x0240, 0x0241, 0x0241, 0x0246, 0x010A, + /* IPA Extensions */ + 0x0253, 0x0040, 0x0181, 0x0186, 0x0255, 0x0189, 0x018A, 0x0258, 0x018F, 0x025A, 0x0190, 0x025C, 0x025D, 0x025E, 0x025F, 0x0193, 0x0261, 0x0262, 0x0194, 0x0264, 0x0265, 0x0266, 0x0267, 0x0197, 0x0196, 0x026A, 0x2C62, 0x026C, 0x026D, 0x026E, 0x019C, 0x0270, 0x0271, 0x019D, 0x0273, 0x0274, 0x019F, 0x0276, 0x0277, 0x0278, 0x0279, 0x027A, 0x027B, 0x027C, 0x2C64, 0x027E, 0x027F, 0x01A6, 0x0281, 0x0282, 0x01A9, 0x0284, 0x0285, 0x0286, 0x0287, 0x01AE, 0x0244, 0x01B1, 0x01B2, 0x0245, 0x028D, 0x028E, 0x028F, 0x0290, 0x0291, 0x01B7, + /* Greek, Coptic */ + 0x037B, 0x0003, 0x03FD, 0x03FE, 0x03FF, 0x03AC, 0x0004, 0x0386, 0x0388, 0x0389, 0x038A, 0x03B1, 0x0311, + 0x03C2, 0x0002, 0x03A3, 0x03A3, 0x03C4, 0x0308, 0x03CC, 0x0003, 0x038C, 0x038E, 0x038F, 0x03D8, 0x0118, + 0x03F2, 0x000A, 0x03F9, 0x03F3, 0x03F4, 0x03F5, 0x03F6, 0x03F7, 0x03F7, 0x03F9, 0x03FA, 0x03FA, + /* Cyrillic */ + 0x0430, 0x0320, 0x0450, 0x0710, 0x0460, 0x0122, 0x048A, 0x0136, 0x04C1, 0x010E, 0x04CF, 0x0001, 0x04C0, 0x04D0, 0x0144, + /* Armenian */ + 0x0561, 0x0426, + + 0x0000 + }; + static const WCHAR cvt2[] = /* U+1000 - U+FFFF */ + { + /* Phonetic Extensions */ + 0x1D7D, 0x0001, 0x2C63, + /* Latin Extended Additional */ + 0x1E00, 0x0196, 0x1EA0, 0x015A, + /* Greek Extended */ + 0x1F00, 0x0608, 0x1F10, 0x0606, 0x1F20, 0x0608, 0x1F30, 0x0608, 0x1F40, 0x0606, + 0x1F51, 0x0007, 0x1F59, 0x1F52, 0x1F5B, 0x1F54, 0x1F5D, 0x1F56, 0x1F5F, 0x1F60, 0x0608, + 0x1F70, 0x000E, 0x1FBA, 0x1FBB, 0x1FC8, 0x1FC9, 0x1FCA, 0x1FCB, 0x1FDA, 0x1FDB, 0x1FF8, 0x1FF9, 0x1FEA, 0x1FEB, 0x1FFA, 0x1FFB, + 0x1F80, 0x0608, 0x1F90, 0x0608, 0x1FA0, 0x0608, 0x1FB0, 0x0004, 0x1FB8, 0x1FB9, 0x1FB2, 0x1FBC, + 0x1FCC, 0x0001, 0x1FC3, 0x1FD0, 0x0602, 0x1FE0, 0x0602, 0x1FE5, 0x0001, 0x1FEC, 0x1FF2, 0x0001, 0x1FFC, + /* Letterlike Symbols */ + 0x214E, 0x0001, 0x2132, + /* Number forms */ + 0x2170, 0x0210, 0x2184, 0x0001, 0x2183, + /* Enclosed Alphanumerics */ + 0x24D0, 0x051A, 0x2C30, 0x042F, + /* Latin Extended-C */ + 0x2C60, 0x0102, 0x2C67, 0x0106, 0x2C75, 0x0102, + /* Coptic */ + 0x2C80, 0x0164, + /* Georgian Supplement */ + 0x2D00, 0x0826, + /* Full-width */ + 0xFF41, 0x031A, + + 0x0000 + }; + const WCHAR *p; + WCHAR bc, nc, cmd; + + + p = chr < 0x1000 ? cvt1 : cvt2; + for (;;) + { + bc = *p++; /* Get block base */ + if (!bc || chr < bc) break; + nc = *p++; + cmd = nc >> 8; + nc &= 0xFF; /* Get processing command and block size */ + if (chr < bc + nc) /* In the block? */ + { + switch (cmd) + { + case 0: + chr = p[chr - bc]; + break; /* Table conversion */ + case 1: + chr -= (chr - bc) & 1; + break; /* Case pairs */ + case 2: + chr -= 16; + break; /* Shift -16 */ + case 3: + chr -= 32; + break; /* Shift -32 */ + case 4: + chr -= 48; + break; /* Shift -48 */ + case 5: + chr -= 26; + break; /* Shift -26 */ + case 6: + chr += 8; + break; /* Shift +8 */ + case 7: + chr -= 80; + break; /* Shift -80 */ + case 8: + chr -= 0x1C60; + break; /* Shift -0x1C60 */ + } + break; + } + if (!cmd) p += nc; + } + + return chr; +} +#endif diff --git a/beken_os/beken378/func/fatfs/ccsbcs.h b/beken_os/beken378/func/fatfs/ccsbcs.h new file mode 100755 index 0000000..69b0e26 --- /dev/null +++ b/beken_os/beken378/func/fatfs/ccsbcs.h @@ -0,0 +1,25 @@ +/* + * ccsbcs.h + * + * Created on: 2017-5-24 + * Author: bo.wang + */ + +#ifndef CCSBCS_H_ +#define CCSBCS_H_ +#include "integer.h" +#include "ffconf.h" + +#if _CODE_PAGE != 936 +WCHAR ff_convert ( /* Converted character, Returns zero on error */ + WCHAR chr, /* Character code to be converted */ + UINT dir /* 0: Unicode to OEM code, 1: OEM code to Unicode */ +); + +WCHAR ff_wtoupper ( /* Returns upper converted character */ + WCHAR chr /* Unicode character to be upper converted (BMP only) */ +); + +#endif + +#endif /* CCSBCS_H_ */ diff --git a/beken_os/beken378/func/fatfs/disk_io.c b/beken_os/beken378/func/fatfs/disk_io.c new file mode 100755 index 0000000..d855e85 --- /dev/null +++ b/beken_os/beken378/func/fatfs/disk_io.c @@ -0,0 +1,306 @@ +#include "include.h" +#include "arm_arch.h" +#include "diskio.h" + +#if CFG_USE_SDCARD_HOST +#include "sdio_driver.h" +#include "sdcard.h" +#include "sdcard_pub.h" +#include "drv_model_pub.h" +#include "sys_ctrl_pub.h" +#include "mem_pub.h" +#include "icu_pub.h" +#include "target_util_pub.h" +#include "ff.h" +#include "usb_pub.h" + +#define USB_RET_OK 0 +#define USB_RET_ERROR 1 +#define USB_RET_CONNECT 2 +#define USB_RET_DISCONNECT 3 +#define USB_RET_READ_OK 4 +#define USB_RET_WRITE_OK 5 + +extern void MUSB_Host_init(void); +extern uint8_t MGC_MsdGetMediumstatus(void); +extern uint32_t MUSB_NoneRunBackground(void); + +uint8 udisk_init(void) +{ + uint32 ret = USB_RET_ERROR; + + if (MGC_MsdGetMediumstatus()) + { + ret = USB_RET_OK; + } + else + { + MUSB_Host_init(); + + while (1) + { + ret = MUSB_NoneRunBackground(); + printf("udisk_init: ret = 0x%lx\r\n", ret); + if (MGC_MsdGetMediumstatus()) + { + printf("get_HfiMedium_size = 0x%lx\r\n", get_HfiMedium_size()); + printf("get_HfiMedium_blksize = 0x%lx\r\n", get_HfiMedium_blksize()); + ret = USB_RET_OK; + break; + } + else + { + if((USB_RET_DISCONNECT == ret) || (USB_RET_ERROR == ret)) + { + break; + } + } + } + } + + return ret; +} + +static DD_HANDLE sdcard_hdl; +DSTATUS disk_initialize (uint8 pdrv) +{ + int cnt = 5; + UINT32 status; + + os_printf("disk_initialize\r\n"); + if(pdrv == DISK_TYPE_SD) + { + while(cnt--) + { + sdcard_hdl = ddev_open(SDCARD_DEV_NAME, &status, 0); + if(DD_HANDLE_UNVALID != sdcard_hdl) + { + return RES_OK; + } + FAT_WARN("SD init retry cnt = %d\r\n", cnt); + } + } + else if(pdrv == DISK_TYPE_UDISK) + { + if(udisk_init() == USB_RET_OK) + return RES_OK; + return RES_OK; + } + return STA_NOINIT; +} + + +DSTATUS disk_status (uint8 pdrv) +{ + return RES_OK; +} + +DRESULT disk_read ( + uint8 pdrv, + uint8 *buff, + uint32 start_sector, + uint32 sector_cnt +) +{ + uint32 err; + + os_printf("disk_read: pdrv=%d, buff=0x%p, start_sector=0x%x, sector_cnt=0x%x\r\n", pdrv, buff, start_sector, sector_cnt); + if( pdrv == DISK_TYPE_SD) + { + err = ddev_read(sdcard_hdl, (char *)buff, sector_cnt, start_sector); + if(err != SD_OK ) + return RES_ERROR; + } + else if(pdrv == DISK_TYPE_UDISK) + { + err = MUSB_HfiRead(start_sector, sector_cnt, buff); + os_printf("err = 0x%x\r\n", err); + if(err != USB_RET_OK) + { + os_printf("disk_read: RES_ERROR\r\n"); + return RES_ERROR; + } + os_printf("disk_read: RES_OK\r\n"); + return RES_OK; + } + return RES_OK; +} + + +DSTATUS disk_close(void) +{ + os_printf("disk_close\r\n"); + ddev_close(sdcard_hdl); + + sdcard_hdl = DD_HANDLE_UNVALID; + return RES_OK; +} + +#endif + + +#if CFG_USE_USB_HOST +#include +#include +#include "driver_udisk.h" + +enum +{ + DISK_TYPE_SD = 0, + DISK_TYPE_UDISK +}; + +static uint8 cur_disk_type = DISK_TYPE_SD; + +DSTATUS disk_initialize(uint8 pdrv) +{ + cur_disk_type = pdrv; + + os_printf("DISK_INITIALIZE\r\n"); + + if (pdrv == DISK_TYPE_SD) + { + return RES_ERROR; + } + else if (udisk_init() == USB_RET_OK) + { + return RES_OK; + } + + return STA_NOINIT; +} + +DSTATUS disk_status(BYTE drv) +{ + return RES_OK; +} + +DRESULT disk_read ( + BYTE drv, + BYTE *buff, /* Data buffer to store read data */ + DWORD sector, /* Sector address (LBA) */ + BYTE count /* Number of sectors to read (1..255) */ +) +{ + volatile int try_num = 0; + cur_disk_type = drv; + DRESULT ret; + + ret = RES_OK; + if (drv == DISK_TYPE_SD) + { + ret = RES_ERROR; + } + else + { + if (udisk_rd_blk_sync(sector, count, buff) != USB_RET_OK) + { + os_printf("disk_read_error\r\n"); + ret = RES_ERROR; + } + } + + return ret; +} + +#if (_READONLY == 0) +DRESULT disk_write ( + BYTE drv, + const BYTE *buff, /* Data to be written */ + DWORD sector, /* Sector address (LBA) */ + BYTE count /* Number of sectors to write (1..255) */ +) +{ + uint8 res = 0; + cur_disk_type = drv; + + if (!count) return RES_PARERR; // count2??̨0?????2?y䨪? + + if ( cur_disk_type == DISK_TYPE_SD) + { + return RES_ERROR; + } + else + { + res = udisk_wr_blk_sync((int)sector, (int)count, (uint8 *)buff); + } + + if (res == 0x00)return RES_OK; + else return RES_ERROR; +} +#endif + +DRESULT disk_ioctl ( + BYTE drv, + BYTE ctrl, /* Control code */ + void *buff /* Buffer to send/receive control data */ +) +{ + DRESULT res = RES_OK; + cur_disk_type = drv; + if (cur_disk_type == DISK_TYPE_SD) + { + return RES_ERROR; + } + else + { + switch(ctrl) + { + case CTRL_SYNC: + // if (SD_WaitReady()==0)res = RES_OK; + // else res = RES_ERROR; + // Delay(10000); + // printf("CTRL_SYNC \r\n"); + res = RES_OK; + break; + case GET_SECTOR_SIZE: + *(WORD *)buff = 512; + res = RES_OK; + break; + case GET_BLOCK_SIZE: + *(WORD *)buff = 8; + res = RES_OK; + break; + case GET_SECTOR_COUNT: + *(DWORD *)buff = udisk_get_size(); + res = RES_OK; + break; + default: + res = RES_PARERR; + break; + } + } + return res; +} + +DWORD get_fattime (void) +{ + return 0; +} + +uint8 Media_is_online(void) +{ + if (cur_disk_type == DISK_TYPE_SD) + // return SD_is_attached(); + return RES_ERROR; + else + return udisk_is_attached(); +} + +uint8 get_cur_media_type(void) +{ + return cur_disk_type; +} + +DRESULT disk_unmount(uint8 pdrv) +{ + if (pdrv == DISK_TYPE_SD) + // SD_SPI_Uninit(); + return RES_ERROR; + else + // udisk_uninit(); + return RES_OK; +} + +#endif + diff --git a/beken_os/beken378/func/fatfs/diskio.h b/beken_os/beken378/func/fatfs/diskio.h new file mode 100755 index 0000000..a0321de --- /dev/null +++ b/beken_os/beken378/func/fatfs/diskio.h @@ -0,0 +1,153 @@ +/*----------------------------------------------------------------------- +/ Low level disk interface modlue include file +/-----------------------------------------------------------------------*/ +#ifndef _DISKIO_H_ +#define _DISKIO_H_ + +#include "include.h" +#include "arm_arch.h" +#include "uart_pub.h" +#include "ffconf.h" +#include "integer.h" + +#define FAT_INTF_DEBUG + +#ifdef FAT_INTF_DEBUG +#define FAT_PRT os_printf +#define FAT_WARN warning_prf +#define FAT_FATAL fatal_prf +#else +#define FAT_PRT null_prf +#define FAT_WARN null_prf +#define FAT_FATAL null_prf +#endif + +/* Disk Status Bits (DSTATUS) */ +#define STA_NOINIT 0x01 /* Drive not initialized */ +#define STA_NODISK 0x02 /* No medium in the drive */ +#define STA_PROTECT 0x04 /* Write protected */ + +#if CFG_USE_SDCARD_HOST +#ifndef _DISKIO_DEFINED +#define _DISKIO_DEFINED + +#ifdef __cplusplus +extern "C" { +#endif + + typedef uint8 DSTATUS; + + typedef enum + { + RES_OK = 0, /* 0: Successful */ + RES_ERROR, /* 1: R/W Error */ + RES_WRPRT, /* 2: Write Protected */ + RES_NOTRDY, /* 3: Not Ready */ + RES_PARERR /* 4: Invalid Parameter */ + } DRESULT; + + typedef enum + { + DISK_TYPE_SD = 0, + DISK_TYPE_UDISK + } DISKTPYE; + + DSTATUS disk_initialize (uint8 pdrv); + DSTATUS disk_status (uint8 pdrv); + DRESULT disk_read (uint8 pdrv, uint8 *buff, uint32 start_sector, uint32 sector_cnt); + +#ifdef __cplusplus +} +#endif + +#endif // _DISKIO_DEFINED +#endif // CFG_USE_SDCARD_HOST + + +#if CFG_USE_USB_HOST +/*----------------------------------------------------------------------- +/ Low level disk interface modlue include file +/-----------------------------------------------------------------------*/ + +#ifndef _DISKIO +#define _DISKIO + +#define _READONLY 0 /* 1: Remove write functions */ +#define _USE_IOCTL 1 /* 1: Use disk_ioctl fucntion */ +#include "ff.h" + +/* Status of Disk Functions */ +typedef BYTE DSTATUS; + +typedef enum +{ + DISK_NUMBER_SPI_SD = 0, + DISK_NUMBER_SDIO_SD = 1, + DISK_NUMBER_UDISK = 2 +} DISK_NUMBER; + +/* Results of Disk Functions */ +typedef enum +{ + RES_OK = 0, /* 0: Successful */ + RES_ERROR, /* 1: R/W Error */ + RES_WRPRT, /* 2: Write Protected */ + RES_NOTRDY, /* 3: Not Ready */ + RES_PARERR /* 4: Invalid Parameter */ +} DRESULT; + + +/*---------------------------------------*/ +/* Prototypes for disk control functions */ +int assign_drives (int, int); +DSTATUS disk_initialize (BYTE); +DSTATUS disk_initialize1 (BYTE); +DSTATUS disk_status (BYTE); +DRESULT disk_read (BYTE, BYTE *, DWORD, BYTE); +#if _READONLY == 0 +DRESULT disk_write (BYTE, const BYTE *, DWORD, BYTE); +#endif +DRESULT disk_ioctl (BYTE, BYTE, void *); +DRESULT disk_unmount(uint8 drv); +uint8 Media_is_online(void); +uint8 get_cur_media_type(void); +/* Disk Status Bits (DSTATUS) */ + +#define STA_NOINIT 0x01 /* Drive not initialized */ +#define STA_NODISK 0x02 /* No medium in the drive */ +#define STA_PROTECT 0x04 /* Write protected */ + + +/* Command code for disk_ioctrl fucntion */ +/* Generic command (defined for FatFs) */ +#define CTRL_SYNC 0 /* Flush disk cache (for write functions) */ +#define GET_SECTOR_COUNT 1 /* Get media size (for only f_mkfs()) */ +#define GET_SECTOR_SIZE 2 /* Get sector size (for multiple sector size (_MAX_SS >= 1024)) */ +#define GET_BLOCK_SIZE 3 /* Get erase block size (for only f_mkfs()) */ +#define CTRL_ERASE_SECTOR 4 /* Force erased a block of sectors (for only _USE_ERASE) */ + +/* Generic command */ +#define CTRL_POWER 5 /* Get/Set power status */ +#define CTRL_LOCK 6 /* Lock/Unlock media removal */ +#define CTRL_EJECT 7 /* Eject media */ + +/* MMC/SDC specific ioctl command */ +#define MMC_GET_TYPE 10 /* Get card type */ +#define MMC_GET_CSD 11 /* Get CSD */ +#define MMC_GET_CID 12 /* Get CID */ +#define MMC_GET_OCR 13 /* Get OCR */ +#define MMC_GET_SDSTAT 14 /* Get SD status */ + +/* ATA/CF specific ioctl command */ +#define ATA_GET_REV 20 /* Get F/W revision */ +#define ATA_GET_MODEL 21 /* Get model name */ +#define ATA_GET_SN 22 /* Get serial number */ + +/* NAND specific ioctl command */ +#define NAND_FORMAT 30 /* Create physical format */ +#endif +#endif // CFG_USE_USB_HOST + +#endif // _DISKIO_H_ +//eof + diff --git a/beken_os/beken378/func/fatfs/driver_udisk.c b/beken_os/beken378/func/fatfs/driver_udisk.c new file mode 100755 index 0000000..f25b44e --- /dev/null +++ b/beken_os/beken378/func/fatfs/driver_udisk.c @@ -0,0 +1,83 @@ +#include +#include +#include "include.h" +#include "driver_udisk.h" +#include "rtos_pub.h" +#include "uart_pub.h" +#include "usb_msd.h" + +#if CFG_USE_USB_HOST +extern uint8_t MUSB_GetConnect_Flag(void); +extern uint8_t MGC_MsdGetMediumstatus(void); + +uint8 udisk_is_attached(void) +{ + return MUSB_GetConnect_Flag(); +} + +uint8 udisk_init(void) +{ + uint32 ret = USB_RET_ERROR; + int ret_val; + + os_printf("udisk_init_wzl\r\n"); + + while(1) + { + if (MGC_MsdGetMediumstatus()) + { + ret = USB_RET_OK; + break; + } + else + { + rtos_delay_milliseconds(100); + } + } + + return ret; +} + +int udisk_rd_blk_sync(uint32 first_block, uint32 block_num, uint8 *dest ) +{ + int ret = USB_RET_ERROR; + + os_printf("disk_rd:%d:%d\r\n", first_block, block_num); + if (!MGC_MsdGetMediumstatus()) + { + os_printf("disk_rd_failed\r\n"); + return ret; + } + + #ifdef CFG_ENABLE_SYC_OP + ret = MUSB_HfiRead_sync(first_block, block_num, dest); + #endif + + return ret; +} + +int udisk_wr_blk_sync(uint32 first_block, uint32 block_num, uint8 *dest) +{ + int ret = USB_RET_ERROR; + + os_printf("disk_wr:%d:%d\r\n", first_block, block_num); + if (!MGC_MsdGetMediumstatus()) + { + os_printf("disk_wr_failed\r\n"); + return ret; + } + + #ifdef CFG_ENABLE_SYC_OP + ret = MUSB_HfiWrite_sync(first_block, block_num, dest); + #endif + + return ret; +} + +uint32 udisk_get_size(void) +{ + return 0;//driver_udisk.total_block; +} + +#endif + diff --git a/beken_os/beken378/func/fatfs/driver_udisk.h b/beken_os/beken378/func/fatfs/driver_udisk.h new file mode 100755 index 0000000..8b8ed55 --- /dev/null +++ b/beken_os/beken378/func/fatfs/driver_udisk.h @@ -0,0 +1,41 @@ +#ifndef __DRIVER_USB_H__ +#define __DRIVER_USB_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include "include.h" +#include "ffconf.h" + + +#if CFG_USE_USB_HOST +#define USB_RET_OK 0 +#define USB_RET_ERROR 1 +#define USB_RET_CONNECT 2 +#define USB_RET_DISCONNECT 3 +#define USB_RET_READ_OK 4 +#define USB_RET_WRITE_OK 5 + +typedef struct __driver_udisk_s +{ + uint32 total_block; + uint16 block_size; + uint16 InitFlag; +} driver_udisk_t; + +extern uint8 udisk_init(void); +extern void udisk_uninit(void); +extern uint32 udisk_get_size(void); +extern uint8 udisk_is_attached(void); +extern int udisk_rd_blk_sync(uint32 first_block, uint32 block_num, uint8 *dest ); +extern int udisk_wr_blk_sync(uint32 first_block, uint32 block_num, uint8 *dest); +#endif + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __DRIVER_USB_H__ */ diff --git a/beken_os/beken378/func/fatfs/ff.c b/beken_os/beken378/func/fatfs/ff.c new file mode 100755 index 0000000..f5a4ee9 --- /dev/null +++ b/beken_os/beken378/func/fatfs/ff.c @@ -0,0 +1,8026 @@ + +#include "diskio.h" /* Declarations of disk I/O functions */ +#include "ff.h" /* Declarations of API */ +#if CFG_USE_SDCARD_HOST + +#if _FATFS != 7231 /* Revision ID */ +#error Wrong include file (ff.h). +#endif + +#if _VOLUMES >= 1 || _VOLUMES <= 10 +static +FATFS *FatFs[_VOLUMES]; /* Pointer to the file system objects (logical drives) */ +#else +#error Number of volumes must be 1 to 10. +#endif + +static +uint16 Fsid; /* File system mount ID */ + +#define ExFatContiguousClus 0x03 +/*-----------------------------------------------------------------------*/ +/* String functions */ +/*-----------------------------------------------------------------------*/ + +/* Copy memory to memory */ +//static +void mem_cpy (void *dst, const void *src, uint32 cnt) +{ + uint8 *d = (uint8 *)dst; + const uint8 *s = (const uint8 *)src; + while (cnt--) + *d++ = *s++; +} + +/* Fill memory */ +void mem_set (void *dst, int val, uint32 cnt) +{ + uint8 *d = (uint8 *)dst; + while (cnt--) + *d++ = (uint8)val; +} + +/*-----------------------------------------------------------------------*/ +/* Change window offset */ +/*-----------------------------------------------------------------------*/ +FRESULT move_window ( + FATFS *fs, /* File system object */ + uint32 sector /* Sector number to make apperance in the fs->win[] */ +) /* Move to zero only writes back dirty window */ +{ + uint32 wsect; + wsect = fs->winsect; + if (wsect != sector) /* Changed current window */ + { + if (sector) + { + if (disk_read(fs->drive, fs->win, sector, 1) != RES_OK) + return FR_DISK_ERR; + fs->winsect = sector; + } + } + return FR_OK; +} + + +/*-----------------------------------------------------------------------*/ +/* Get sector# from cluster# */ +/*-----------------------------------------------------------------------*/ +static uint32 clust2sect ( FATFS *fs, uint32 clst) +{ + clst -= 2; + if (clst >= (fs->max_clust - 2)) + return 0; + return (clst * fs->csize + fs->database); +} + + +/*-----------------------------------------------------------------------*/ +/* FAT access - Read value of a FAT entry */ +/*-----------------------------------------------------------------------*/ +uint32 get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, Else:Cluster status */ + FATFS *fs, /* File system object */ + uint32 clst /* Cluster# to get the link information */ +) +{ + uint32 wc, bc; + uint8 *p; + + if (clst < 2 || clst >= fs->max_clust) /* Check range */ + return 1; + + switch (fs->fs_type) + { + case FS_FAT12 : + bc = (uint32)clst; + bc += bc / 2; + if (move_window(fs, fs->fatbase + (bc / SS(fs)))) break; + wc = fs->win[bc % SS(fs)]; + bc++; + if (move_window(fs, fs->fatbase + (bc / SS(fs)))) break; + wc |= fs->win[bc % SS(fs)] << 8; + return clst & 1 ? wc >> 4 : (wc & 0xFFF); + + case FS_FAT16 : + if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 2)))) break; + p = &fs->win[clst * 2 % SS(fs)]; + return LD_WORD(p); + case FS_ExFAT : + case FS_FAT32 : + if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 4)))) break; + p = &fs->win[clst * 4 % SS(fs)]; + return LD_DWORD(p) & 0x0FFFFFFF; + + default: + return 1; + } + + return 0xFFFFFFFF; /* An error occurred at the disk I/O layer */ +} + +/*-----------------------------------------------------------------------*/ +/* Check if the file/directory object is valid or not */ +/*-----------------------------------------------------------------------*/ +static +FRESULT validate (FATFS *fs) +{ + if(!fs || !fs->fs_type) + return FR_INVALID_OBJECT; + + return FR_OK; +} + +/*-----------------------------------------------------------------------*/ +/* Seek File R/W Pointer */ +/*-----------------------------------------------------------------------*/ +FRESULT f_lseek ( + FIL *fp, /* Pointer to the file object */ + uint32 ofs /* File pointer from top of file */ +) +{ + FRESULT res; + uint32 clst, bcs, nsect, ifptr; + + + res = validate(fp->fs); /* Check validity of the object */ + if (res != FR_OK) + return res; + + if (ofs > fp->fsize ) + ofs = fp->fsize; + + ifptr = fp->fptr; + fp->fptr = nsect = 0; + fp->csect = 255; + + if (ofs > 0) + { + bcs = (uint32)fp->fs->csize * SS(fp->fs); /* Cluster size (byte) */ + if (ifptr > 0 && (ofs - 1) / bcs >= (ifptr - 1) / bcs) + { + /* When seek to same or following cluster, */ + fp->fptr = (ifptr - 1) & ~(bcs - 1); /* start from the current cluster */ + ofs -= fp->fptr; + clst = fp->curr_clust; + } + else + { + /* When seek to back cluster, */ + clst = fp->org_clust;/* start from the first cluster */ + fp->curr_clust = clst; + } + if (clst != 0) + { + while (ofs > bcs) + { + /* Cluster following loop */ + if((fp->fs->fs_type == FS_ExFAT) && (fp->ExNoChainFlag == ExFatContiguousClus)) + clst++; + else + clst = get_fat(fp->fs, clst); + + if (clst == 0xFFFFFFFF) + return FR_DISK_ERR; + if (clst <= 1 || clst >= fp->fs->max_clust) + return FR_INT_ERR; + fp->curr_clust = clst; + fp->fptr += bcs; + ofs -= bcs; + } + fp->fptr += ofs; + fp->csect = (uint8)(ofs / SS(fp->fs)); /* Sector offset in the cluster */ + if (ofs % SS(fp->fs)) + { + nsect = clust2sect(fp->fs, clst); /* Current sector */ + if (!nsect) + return FR_INT_ERR; + nsect += fp->csect; + fp->csect++; + } + } + } + + if (fp->fptr % SS(fp->fs) && nsect != fp->dsect) + { + if (disk_read(fp->fs->drive, fp->buf, nsect, 1) != RES_OK) + return FR_DISK_ERR; + fp->dsect = nsect; + } + return res; +} + +/*-----------------------------------------------------------------------*/ +/* Directory handling - Seek directory index */ +/*-----------------------------------------------------------------------*/ +//static +FRESULT dir_seek ( + DIR *dj, /* Pointer to directory object */ + uint16 idx /* Directory index number */ +) +{ + uint32 clst; + uint16 ic; + + dj->index = idx; + + if((dj->fs->fs_type == FS_ExFAT) && (dj->ExNoChainFlag == ExFatContiguousClus)) + { + ic = SS(dj->fs) / 32 * dj->fs->csize; /* Entries per cluster */ + clst = dj->sclust; + if (clst >= dj->fs->max_clust) + return FR_INT_ERR; + while(idx >= ic) + { + clst++; + idx -= ic; + } + dj->clust = clst; + dj->sect = clust2sect(dj->fs, dj->clust) + idx / (SS(dj->fs) / 32); + } + else + { + clst = dj->sclust; + if (clst == 1 || clst >= dj->fs->max_clust) + return FR_INT_ERR; + if (!clst && ((dj->fs->fs_type == FS_FAT32) || (dj->fs->fs_type == FS_ExFAT))) + clst = dj->fs->dirbase; + if (clst == 0) + { + dj->clust = clst; + if (idx >= dj->fs->n_rootdir) + return FR_INT_ERR; + dj->sect = dj->fs->dirbase + idx / (SS(dj->fs) / 32); + } + else + { + ic = SS(dj->fs) / 32 * dj->fs->csize; /* Entries per cluster */ + while (idx >= ic) + { + clst = get_fat(dj->fs, clst); /* Get next cluster */ + if (clst == 0xFFFFFFFF) return FR_DISK_ERR; + if (clst < 2 || clst >= dj->fs->max_clust) /* Reached to end of table or int error */ + return FR_INT_ERR; + idx -= ic; + } + dj->clust = clst; + dj->sect = clust2sect(dj->fs, clst) + idx / (SS(dj->fs) / 32); + } + } + + dj->dir = dj->fs->win + (idx % (SS(dj->fs) / 32)) * 32; /* Ptr to the entry in the sector */ + return FR_OK; +} + +/*-----------------------------------------------------------------------*/ +/* Load a sector and check if it is an (Ex)FAT boot sector */ +/* output: 0-FAT boot sector,(foud fat16 or fat32) + 1-Exfat, + 2-Not boot sector, + 3-Valid boot record but not fat/exfat, + 4-Disk error */ +/*-----------------------------------------------------------------------*/ +static +uint8 check_fs (FATFS *fs, uint32 sect) +{ + if (disk_read(fs->drive, fs->win, sect, 1) != RES_OK) + return 4; + + if (LD_WORD(&fs->win[BS_55AA]) != 0xAA55) + return 2; + if(LD_DWORD(&fs->win[BPB_ExFatName]) == 0x54414658 )/*check "XFAT" string*/ + return 1; + if ((LD_DWORD(&fs->win[BS_FilSysType]) & 0xFFFFFF) == 0x544146) /* Check "FAT" string */ + return 0; + if ((LD_DWORD(&fs->win[BS_FilSysType32]) & 0xFFFFFF) == 0x544146)/* Check "FAT" string */ + return 0; + return 3; +} + +/*-----------------------------------------------------------------------*/ +/* Read File */ +/*-----------------------------------------------------------------------*/ +FRESULT f_read ( + FIL *fp, /* Pointer to the file object */ + void *buff, /* Pointer to data buffer */ + uint32 btr, /* Number of bytes to read */ + uint32 *br /* Pointer to number of bytes read */ +) +{ + FRESULT res; + uint32 clst, sect, remain; + uint32 rcnt = 0, cc; + uint8 *rbuff = buff; + + *br = 0; /* Initialize bytes read */ + res = validate(fp->fs); /* Check validity of the object */ + if (res != FR_OK) + return res; + if (!(fp->flag & FA_READ)) /* Check access mode */ + return FR_DENIED; + + remain = fp->fsize - fp->fptr; + if (btr > remain) + btr = (uint32)remain;/* Truncate btr by remaining bytes */ + + for ( ; btr; rbuff += rcnt, fp->fptr += rcnt, *br += rcnt, btr -= rcnt) + { + if ((fp->fptr % SS(fp->fs)) == 0) + { + /* On the sector boundary? */ + if (fp->csect >= fp->fs->csize) + { + /* On the cluster boundary? */ + if((fp->fs->fs_type == FS_ExFAT) && (fp->ExNoChainFlag == ExFatContiguousClus)) + { + clst = fp->org_clust + ((fp->fptr + _MAX_SS - 1) / _MAX_SS + fp->fs->csize - 1) / (fp->fs->csize); + } + else + clst = (fp->fptr == 0) ? fp->org_clust : get_fat(fp->fs, fp->curr_clust); + if (clst <= 1) + return FR_INT_ERR; + if (clst == 0xFFFFFFFF) + return FR_DISK_ERR; + fp->curr_clust = clst; /* Update current cluster */ + fp->csect = 0; /* Reset sector offset in the cluster */ + } + sect = clust2sect(fp->fs, fp->curr_clust); /* Get current sector */ + if (!sect) + return FR_INT_ERR; + sect += fp->csect; + cc = btr / SS(fp->fs); /* When remaining bytes >= sector size, */ + if (cc) + { + /* Read maximum contiguous sectors directly */ + if (fp->csect + cc > fp->fs->csize) /* Clip at cluster boundary */ + cc = fp->fs->csize - fp->csect; + if (disk_read(fp->fs->drive, rbuff, sect, (uint8)cc) != RES_OK) + return FR_DISK_ERR; + fp->csect += (uint8)cc; /* Next sector address in the cluster */ + rcnt = SS(fp->fs) * cc; /* Number of bytes transferred */ + continue; + } + if (fp->dsect != sect) + { + /* Fill sector buffer with file data */ + if (disk_read(fp->fs->drive, fp->buf, sect, 1) != RES_OK) + return FR_DISK_ERR; + } + fp->dsect = sect; + fp->csect++;/* Next sector address in the cluster */ + } + rcnt = SS(fp->fs) - (fp->fptr % SS(fp->fs));/* Get partial sector data from sector buffer */ + if (rcnt > btr) + rcnt = btr; + mem_cpy(rbuff, &fp->buf[fp->fptr % SS(fp->fs)], rcnt); /* Pick partial sector */ + } + return FR_OK; +} + +/*----------------------------------------------------------------------- +Close File. +input: fp -- Pointer to the file object to be closed +------------------------------------------------------------------------*/ +FRESULT f_close ( FIL *fp) +{ + FRESULT res; + res = validate(fp->fs); + if (res == FR_OK) + fp->fs = NULL; + return res; +} + +/* FR_OK(0): successful, !=0: any error occured */ +FRESULT chk_mounted_con (FATFS *rfs, uint8 type) +{ + uint8 fmt, *tbl; + DSTATUS stat; + uint32 bsect, fsize, tsect, mclst; + FATFS *fs; + + FAT_PRT("chk_mounted_con\r\n"); + fs = rfs; + if (!fs) + return FR_NOT_ENABLED; /* Is the file system object available? */ + if (fs->fs_type) + { + stat = disk_status(fs->drive); + if (!(stat & STA_NOINIT)) + return FR_OK; /* The file system object is valid */ + } + + fs->fs_type = 0; + fs->drive = type; + stat = disk_initialize(fs->drive); /* Initialize low level disk I/O layer */ + FAT_PRT("newfat 1:%d\r\n", stat); + if (stat & STA_NOINIT) + return FR_NOT_READY; + + fmt = check_fs(fs, bsect = 0); + FAT_PRT("newfat 2:%d\r\n", fmt); + + if (fmt == 3) + { + /* Not an FAT boot record, it may be patitioned */ + tbl = &fs->win[MBR_Table + LD2PT(vol) * 16]; + + FAT_PRT("tbl[4] = 0x%x\r\n", tbl[4]); + if (tbl[4]) + { + bsect = LD_DWORD(&tbl[8]); + fmt = check_fs(fs, bsect); + } + } + FAT_PRT("fmt = 0x%x\r\n", fmt); + fmt = 0; + FAT_PRT("fmt = 0x%x\r\n", fmt); + + if (fmt == 4) + return FR_NO_FILESYSTEM; + if((fmt == 2) || (fmt == 3)) + return FR_DISK_ERR; + + if(fmt == 1) /*exfat*/ + { + if((1 << (fs->win[BPB_ExBytePerSecSft])) != SS(fs)) + return FR_NO_FILESYSTEM; + /* Initialize the file system object */ + fs->sects_fat = LD_DWORD(fs->win + BPB_ExFatLength); + fs->n_fats = fs->win[BPB_ExNumofFATs]; + fs->fatbase = bsect + LD_DWORD(fs->win + BPB_ExFatOffset); //// + fs->csize = 1 << (fs->win[BPB_ExSecPerClusSft]); + fs->max_clust = LD_DWORD(fs->win + BPB_ExClusterCnt); + fs->dirbase = LD_DWORD(fs->win + BPB_ExRootDirBase); + fs->database = bsect + LD_DWORD(fs->win + BPB_ExClusHPOffset); + fs->n_rootdir = 0; + fs->fs_type = FS_ExFAT; + fs->winsect = 0; + } + else + { + /* BPSεĴ BIOS Parameter Block */ + // ֽ 512byte + FAT_PRT("LD_WORD(fs->win+BPB_BytsPerSec) = 0x%x\r\n", LD_WORD(fs->win + BPB_BytsPerSec)); + FAT_PRT("SS(fs) = 0x%x\r\n", SS(fs)); + if (fmt || LD_WORD(fs->win + BPB_BytsPerSec) != SS(fs)) + return FR_NO_FILESYSTEM; + /* Initialize the file system object */ + fsize = LD_WORD(fs->win + BPB_FATSz16); + if (!fsize) // ÿFATռ ֻFAT12/16ʹãFAT32Ϊ0 + fsize = LD_DWORD(fs->win + BPB_FATSz32); + fs->sects_fat = fsize; + fs->n_fats = fs->win[BPB_NumFATs];// FATFATĸһΪ2 + fsize *= fs->n_fats; + + // + fs->fatbase = bsect + LD_WORD(fs->win + BPB_RsvdSecCnt); + fs->csize = fs->win[BPB_SecPerClus]; // ÿ + // Ŀ¼ɵĿ¼ֻFAT12/16ʹãFAT32Ϊ0 + fs->n_rootdir = LD_WORD(fs->win + BPB_RootEntCnt); + // С(С32MBڴˣ32MBĴ0x20-23) + // ֻFAT12/16ʹãFAT32Ϊ0 + tsect = LD_WORD(fs->win + BPB_TotSec16); + if (!tsect) // FAT32ܵ + tsect = LD_DWORD(fs->win + BPB_TotSec32); + fs->max_clust = mclst = (tsect + - LD_WORD(fs->win + BPB_RsvdSecCnt) - fsize - fs->n_rootdir / (SS(fs) / 32) + ) / fs->csize + 2; + + fmt = FS_FAT12; + if (mclst >= 0xFF7) + fmt = FS_FAT16; + if (mclst >= 0xFFF7) + fmt = FS_FAT32; + + // Ŀ¼غ FAT32 һ 2 + if (fmt == FS_FAT32) + fs->dirbase = LD_DWORD(fs->win + BPB_RootClus); + else + fs->dirbase = fs->fatbase + fsize; + fs->database = fs->fatbase + fsize + fs->n_rootdir / (SS(fs) / 32); + fs->fs_type = fmt; + fs->winsect = 0; + } + + fs->id = ++Fsid; + FAT_PRT("FAT INIT OK!!!\r\n"); + return FR_OK; +} + +FRESULT f_EOF(FIL *fp ) +{ + if(fp->fsize <= fp->fptr) + return FR_FILE_END; + else + return FR_OK; + +} + +/*-----------------------------------------------------------------------*/ +/* Mount/Unmount a Logical Drive */ +/*-----------------------------------------------------------------------*/ +FRESULT f_mount ( + uint8 vol, /* Logical drive number to be mounted/unmounted */ + FATFS *fs /* Pointer to the file system object (NULL:unmount)*/ +) +{ + FATFS *cfs; + + if (vol >= _VOLUMES) + return FR_INVALID_DRIVE; + + cfs = FatFs[vol]; /* Pointer to fs object */ + + if (cfs) + cfs->fs_type = 0; /* Clear old fs object */ + + if (fs) + fs->fs_type = 0; /* Clear new fs object */ + + FatFs[vol] = fs; /* Register new fs object */ + + return FR_OK; +} + +/* Pointer to new file system object (NULL for unmount)*/ +FRESULT f_unmount (FATFS *fs) +{ + mem_set(fs, 0, sizeof(FATFS)); + return FR_OK; +} + +#endif + +#if CFG_USE_FTPD_UPGRADE + +FRESULT f_close ( + FIL *fp /* Pointer to the file object to be closed */ +) +{ + return FR_OK; +} + +FRESULT f_getcwd ( + TCHAR *buff, /* Pointer to the directory path */ + uint32 len /* Size of path */ +) +{ + return FR_OK; +} + +FRESULT f_open ( + FIL *fp, /* Pointer to the blank file object */ + const TCHAR *path, /* Pointer to the file name */ + uint8 mode /* Access mode and file open mode flags */ +) +{ + return FR_OK; +} + +FRESULT f_opendir ( + DIR *dp, /* Pointer to directory object to create */ + const TCHAR *path /* Pointer to the directory path */ +) +{ + return FR_OK; +} + +FRESULT f_read ( + FIL *fp, /* Pointer to the file object */ + void *buff, /* Pointer to data buffer */ + uint32 btr, /* Number of bytes to read */ + uint32 *br /* Pointer to number of bytes read */ +) +{ + return FR_OK; +} + +FRESULT f_readdir ( + DIR *dp, /* Pointer to the open directory object */ + FILINFO *fno /* Pointer to file information to return */ +) +{ + return FR_OK; +} + +FRESULT f_stat ( + const TCHAR *path, /* Pointer to the file path */ + FILINFO *fno /* Pointer to file information to return */ +) +{ + return FR_OK; +} + +FRESULT f_write ( + FIL *fp, /* Pointer to the file object */ + const void *buff, /* Pointer to the data to be written */ + uint32 btw, /* Number of bytes to write */ + uint32 *bw /* Pointer to number of bytes written */ +) +{ + return FR_OK; +} + +FRESULT f_chdir ( + const TCHAR *path /* Pointer to the directory path */ +) +{ + return FR_OK; +} + +FRESULT f_mkdir ( + const TCHAR *path /* Pointer to the directory path */ +) +{ + return FR_OK; +} + +FRESULT f_rename ( + const TCHAR *path_old, /* Pointer to the object name to be renamed */ + const TCHAR *path_new /* Pointer to the new name */ +) +{ + return FR_OK; +} + +FRESULT f_unlink ( + const TCHAR *path /* Pointer to the file or directory path */ +) +{ + return FR_OK; +} + +FRESULT f_eof(FIL *fp ) +{ + if(fp->fsize <= fp->fptr) + return FR_FILE_END; + else + return FR_OK; + +} +#endif + +#if CFG_USE_USB_HOST +/*----------------------------------------------------------------------------/ +/ FatFs - Generic FAT file system module R0.12c / +/-----------------------------------------------------------------------------/ +/ +/ Copyright (C) 2017, ChaN, all right reserved. +/ +/ FatFs module is an open source software. Redistribution and use of FatFs in +/ source and binary forms, with or without modification, are permitted provided +/ that the following condition is met: +/ +/ 1. Redistributions of source code must retain the above copyright notice, +/ this condition and the following disclaimer. +/ +/ This software is provided by the copyright holder and contributors "AS IS" +/ and any warranties related to this software are DISCLAIMED. +/ The copyright owner or contributors be NOT LIABLE for any damages caused +/ by use of this software. +/----------------------------------------------------------------------------*/ + +#include +//#include +#include + +#include "ff.h" /* Declarations of FatFs API */ +#include "diskio.h" /* Declarations of device I/O functions */ +//#include"syscall.h" +//#include "unicode.c" + +/*-------------------------------------------------------------------------- + + Module Private Definitions + +---------------------------------------------------------------------------*/ + +#if _FATFS != 68300 /* Revision ID */ +#error Wrong include file (ff.h). +#endif + + +#define DEBUG_FF +#undef DEBUG_FF + + +/* DBCS code ranges and SBCS upper conversion tables */ + +#if _CODE_PAGE == 932 /* Japanese Shift-JIS */ +#define _DF1S 0x81 /* DBC 1st byte range 1 start */ +#define _DF1E 0x9F /* DBC 1st byte range 1 end */ +#define _DF2S 0xE0 /* DBC 1st byte range 2 start */ +#define _DF2E 0xFC /* DBC 1st byte range 2 end */ +#define _DS1S 0x40 /* DBC 2nd byte range 1 start */ +#define _DS1E 0x7E /* DBC 2nd byte range 1 end */ +#define _DS2S 0x80 /* DBC 2nd byte range 2 start */ +#define _DS2E 0xFC /* DBC 2nd byte range 2 end */ + +#elif _CODE_PAGE == 936 /* Simplified Chinese GBK */ +#define _DF1S 0x81 +#define _DF1E 0xFE +#define _DS1S 0x40 +#define _DS1E 0x7E +#define _DS2S 0x80 +#define _DS2E 0xFE + +#elif _CODE_PAGE == 949 /* Korean */ +#define _DF1S 0x81 +#define _DF1E 0xFE +#define _DS1S 0x41 +#define _DS1E 0x5A +#define _DS2S 0x61 +#define _DS2E 0x7A +#define _DS3S 0x81 +#define _DS3E 0xFE + +#elif _CODE_PAGE == 950 /* Traditional Chinese Big5 */ +#define _DF1S 0x81 +#define _DF1E 0xFE +#define _DS1S 0x40 +#define _DS1E 0x7E +#define _DS2S 0xA1 +#define _DS2E 0xFE + +#elif _CODE_PAGE == 437 /* U.S. */ +#define _DF1S 0 +#define _EXCVT {0x80,0x9A,0x45,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F, \ + 0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,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, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 720 /* Arabic */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ + 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,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, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 737 /* Greek */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ + 0x90,0x92,0x92,0x93,0x94,0x95,0x96,0x97,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87, \ + 0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0xAA,0x92,0x93,0x94,0x95,0x96, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,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, \ + 0x97,0xEA,0xEB,0xEC,0xE4,0xED,0xEE,0xEF,0xF5,0xF0,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 771 /* KBL */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ + 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,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,0xDC,0xDE,0xDE, \ + 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0xF0,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF8,0xFA,0xFA,0xFC,0xFC,0xFE,0xFF} + +#elif _CODE_PAGE == 775 /* Baltic */ +#define _DF1S 0 +#define _EXCVT {0x80,0x9A,0x91,0xA0,0x8E,0x95,0x8F,0x80,0xAD,0xED,0x8A,0x8A,0xA1,0x8D,0x8E,0x8F, \ + 0x90,0x92,0x92,0xE2,0x99,0x95,0x96,0x97,0x97,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ + 0xA0,0xA1,0xE0,0xA3,0xA3,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xB5,0xB6,0xB7,0xB8,0xBD,0xBE,0xC6,0xC7,0xA5,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE3,0xE8,0xE8,0xEA,0xEA,0xEE,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 850 /* Latin 1 */ +#define _DF1S 0 +#define _EXCVT {0x43,0x55,0x45,0x41,0x41,0x41,0x41,0x43,0x45,0x45,0x45,0x49,0x49,0x49,0x41,0x41, \ + 0x45,0x92,0x92,0x4F,0x4F,0x4F,0x55,0x55,0x59,0x4F,0x55,0x4F,0x9C,0x4F,0x9E,0x9F, \ + 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0x41,0x41,0x41,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0x41,0x41,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD1,0xD1,0x45,0x45,0x45,0x49,0x49,0x49,0x49,0xD9,0xDA,0xDB,0xDC,0xDD,0x49,0xDF, \ + 0x4F,0xE1,0x4F,0x4F,0x4F,0x4F,0xE6,0xE8,0xE8,0x55,0x55,0x55,0x59,0x59,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 852 /* Latin 2 */ +#define _DF1S 0 +#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xDE,0x8F,0x80,0x9D,0xD3,0x8A,0x8A,0xD7,0x8D,0x8E,0x8F, \ + 0x90,0x91,0x91,0xE2,0x99,0x95,0x95,0x97,0x97,0x99,0x9A,0x9B,0x9B,0x9D,0x9E,0xAC, \ + 0xB5,0xD6,0xE0,0xE9,0xA4,0xA4,0xA6,0xA6,0xA8,0xA8,0xAA,0x8D,0xAC,0xB8,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBD,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC6,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD1,0xD1,0xD2,0xD3,0xD2,0xD5,0xD6,0xD7,0xB7,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE3,0xD5,0xE6,0xE6,0xE8,0xE9,0xE8,0xEB,0xED,0xED,0xDD,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xEB,0xFC,0xFC,0xFE,0xFF} + +#elif _CODE_PAGE == 855 /* Cyrillic */ +#define _DF1S 0 +#define _EXCVT {0x81,0x81,0x83,0x83,0x85,0x85,0x87,0x87,0x89,0x89,0x8B,0x8B,0x8D,0x8D,0x8F,0x8F, \ + 0x91,0x91,0x93,0x93,0x95,0x95,0x97,0x97,0x99,0x99,0x9B,0x9B,0x9D,0x9D,0x9F,0x9F, \ + 0xA1,0xA1,0xA3,0xA3,0xA5,0xA5,0xA7,0xA7,0xA9,0xA9,0xAB,0xAB,0xAD,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB6,0xB6,0xB8,0xB8,0xB9,0xBA,0xBB,0xBC,0xBE,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD1,0xD1,0xD3,0xD3,0xD5,0xD5,0xD7,0xD7,0xDD,0xD9,0xDA,0xDB,0xDC,0xDD,0xE0,0xDF, \ + 0xE0,0xE2,0xE2,0xE4,0xE4,0xE6,0xE6,0xE8,0xE8,0xEA,0xEA,0xEC,0xEC,0xEE,0xEE,0xEF, \ + 0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF8,0xFA,0xFA,0xFC,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 857 /* Turkish */ +#define _DF1S 0 +#define _EXCVT {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0x49,0x8E,0x8F, \ + 0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x98,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9E, \ + 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA6,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD0,0xD1,0xD2,0xD3,0xD4,0x49,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xDE,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 860 /* Portuguese */ +#define _DF1S 0 +#define _EXCVT {0x80,0x9A,0x90,0x8F,0x8E,0x91,0x86,0x80,0x89,0x89,0x92,0x8B,0x8C,0x98,0x8E,0x8F, \ + 0x90,0x91,0x92,0x8C,0x99,0xA9,0x96,0x9D,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x86,0x8B,0x9F,0x96,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,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, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 861 /* Icelandic */ +#define _DF1S 0 +#define _EXCVT {0x80,0x9A,0x90,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x8B,0x8B,0x8D,0x8E,0x8F, \ + 0x90,0x92,0x92,0x4F,0x99,0x8D,0x55,0x97,0x97,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ + 0xA4,0xA5,0xA6,0xA7,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,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, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 862 /* Hebrew */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ + 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,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, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 863 /* Canadian-French */ +#define _DF1S 0 +#define _EXCVT {0x43,0x55,0x45,0x41,0x41,0x41,0x86,0x43,0x45,0x45,0x45,0x49,0x49,0x8D,0x41,0x8F, \ + 0x45,0x45,0x45,0x4F,0x45,0x49,0x55,0x55,0x98,0x4F,0x55,0x9B,0x9C,0x55,0x55,0x9F, \ + 0xA0,0xA1,0x4F,0x55,0xA4,0xA5,0xA6,0xA7,0x49,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,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, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 864 /* Arabic */ +#define _DF1S 0 +#define _EXCVT {0x80,0x9A,0x45,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F, \ + 0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,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, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 865 /* Nordic */ +#define _DF1S 0 +#define _EXCVT {0x80,0x9A,0x90,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F, \ + 0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,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, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 866 /* Russian */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ + 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,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, \ + 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0xF0,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} + +#elif _CODE_PAGE == 869 /* Greek 2 */ +#define _DF1S 0 +#define _EXCVT {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ + 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x86,0x9C,0x8D,0x8F,0x90, \ + 0x91,0x90,0x92,0x95,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xA4,0xA5,0xA6,0xD9,0xDA,0xDB,0xDC,0xA7,0xA8,0xDF, \ + 0xA9,0xAA,0xAC,0xAD,0xB5,0xB6,0xB7,0xB8,0xBD,0xBE,0xC6,0xC7,0xCF,0xCF,0xD0,0xEF, \ + 0xF0,0xF1,0xD1,0xD2,0xD3,0xF5,0xD4,0xF7,0xF8,0xF9,0xD5,0x96,0x95,0x98,0xFE,0xFF} + +#elif _CODE_PAGE == 1 /* ASCII (for only non-LFN cfg) */ +#if _USE_LFN != 0 +#error Cannot enable LFN without valid code page. +#endif +#define _DF1S 0 + +#else +#error Unknown code page + +#endif + + +/* Character code support macros */ +#define IsUpper(c) (((c)>='A')&&((c)<='Z')) +#define IsLower(c) (((c)>='a')&&((c)<='z')) +#define IsDigit(c) (((c)>='0')&&((c)<='9')) + +#if _DF1S != 0 /* Code page is DBCS */ + +#ifdef _DF2S /* Two 1st byte areas */ +#define IsDBCS1(c) (((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E) || ((BYTE)(c) >= _DF2S && (BYTE)(c) <= _DF2E)) +#else /* One 1st byte area */ +#define IsDBCS1(c) ((BYTE)(c) >= _DF1S && (BYTE)(c) <= _DF1E) +#endif + +#ifdef _DS3S /* Three 2nd byte areas */ +#define IsDBCS2(c) (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E) || ((BYTE)(c) >= _DS3S && (BYTE)(c) <= _DS3E)) +#else /* Two 2nd byte areas */ +#define IsDBCS2(c) (((BYTE)(c) >= _DS1S && (BYTE)(c) <= _DS1E) || ((BYTE)(c) >= _DS2S && (BYTE)(c) <= _DS2E)) +#endif + +#else /* Code page is SBCS */ + +#define IsDBCS1(c) 0 +#define IsDBCS2(c) 0 + +#endif /* _DF1S */ + + +/* Additional file attribute bits for internal use */ +#define AM_VOL 0x08 /* Volume label */ +#define AM_LFN 0x0F /* LFN entry */ +#define AM_MASK 0x3F /* Mask of defined bits */ + + +/* Additional file access control and file status flags for internal use */ +#define FA_SEEKEND 0x20 /* Seek to end of the file on file open */ +#define FA_MODIFIED 0x40 /* File has been modified */ +#define FA_DIRTY 0x80 /* FIL.buf[] needs to be written-back */ + + +/* Name status flags in fn[] */ +#define NSFLAG 11 /* Index of the name status byte */ +#define NS_LOSS 0x01 /* Out of 8.3 format */ +#define NS_LFN 0x02 /* Force to create LFN entry */ +#define NS_LAST 0x04 /* Last segment */ +#define NS_BODY 0x08 /* Lower case flag (body) */ +#define NS_EXT 0x10 /* Lower case flag (ext) */ +#define NS_DOT 0x20 /* Dot entry */ +#define NS_NOLFN 0x40 /* Do not find LFN */ +#define NS_NONAME 0x80 /* Not followed */ + + +/* Limits and boundaries */ +#define MAX_DIR 0x200000 /* Max size of FAT directory */ +#define MAX_DIR_EX 0x10000000 /* Max size of exFAT directory */ +#define MAX_FAT12 0xFF5 /* Max FAT12 clusters (differs from specs, but correct for real DOS/Windows behavior) */ +#define MAX_FAT16 0xFFF5 /* Max FAT16 clusters (differs from specs, but correct for real DOS/Windows behavior) */ +#define MAX_FAT32 0x0FFFFFF5 /* Max FAT32 clusters (not specified, practical limit) */ +#define MAX_EXFAT 0x7FFFFFFD /* Max exFAT clusters (differs from specs, implementation limit) */ + + +/* FatFs refers the FAT structure as simple byte array instead of structure member +/ because the C structure is not binary compatible between different platforms */ + +#define BS_JmpBoot 0 /* x86 jump instruction (3-byte) */ +#define BS_OEMName 3 /* OEM name (8-byte) */ +#define BPB_BytsPerSec 11 /* Sector size [byte] (WORD) */ +#define BPB_SecPerClus 13 /* Cluster size [sector] (BYTE) */ +#define BPB_RsvdSecCnt 14 /* Size of reserved area [sector] (WORD) */ +#define BPB_NumFATs 16 /* Number of FATs (BYTE) */ +#define BPB_RootEntCnt 17 /* Size of root directory area for FAT12/16 [entry] (WORD) */ +#define BPB_TotSec16 19 /* Volume size (16-bit) [sector] (WORD) */ +#define BPB_Media 21 /* Media descriptor byte (BYTE) */ +#define BPB_FATSz16 22 /* FAT size (16-bit) [sector] (WORD) */ +#define BPB_SecPerTrk 24 /* Track size for int13h [sector] (WORD) */ +#define BPB_NumHeads 26 /* Number of heads for int13h (WORD) */ +#define BPB_HiddSec 28 /* Volume offset from top of the drive (DWORD) */ +#define BPB_TotSec32 32 /* Volume size (32-bit) [sector] (DWORD) */ +#define BS_DrvNum 36 /* Physical drive number for int13h (BYTE) */ +#define BS_NTres 37 /* Error flag (BYTE) */ +#define BS_BootSig 38 /* Extended boot signature (BYTE) */ +#define BS_VolID 39 /* Volume serial number (DWORD) */ +#define BS_VolLab 43 /* Volume label string (8-byte) */ +#define BS_FilSysType 54 /* File system type string (8-byte) */ +#define BS_BootCode 62 /* Boot code (448-byte) */ +#define BS_55AA 510 /* Signature word (WORD) */ + +#define BPB_FATSz32 36 /* FAT32: FAT size [sector] (DWORD) */ +#define BPB_ExtFlags32 40 /* FAT32: Extended flags (WORD) */ +#define BPB_FSVer32 42 /* FAT32: File system version (WORD) */ +#define BPB_RootClus32 44 /* FAT32: Root directory cluster (DWORD) */ +#define BPB_FSInfo32 48 /* FAT32: Offset of FSINFO sector (WORD) */ +#define BPB_BkBootSec32 50 /* FAT32: Offset of backup boot sector (WORD) */ +#define BS_DrvNum32 64 /* FAT32: Physical drive number for int13h (BYTE) */ +#define BS_NTres32 65 /* FAT32: Error flag (BYTE) */ +#define BS_BootSig32 66 /* FAT32: Extended boot signature (BYTE) */ +#define BS_VolID32 67 /* FAT32: Volume serial number (DWORD) */ +#define BS_VolLab32 71 /* FAT32: Volume label string (8-byte) */ +#define BS_FilSysType32 82 /* FAT32: File system type string (8-byte) */ +#define BS_BootCode32 90 /* FAT32: Boot code (420-byte) */ + +#define BPB_ZeroedEx 11 /* exFAT: MBZ field (53-byte) */ +#define BPB_VolOfsEx 64 /* exFAT: Volume offset from top of the drive [sector] (QWORD) */ +#define BPB_TotSecEx 72 /* exFAT: Volume size [sector] (QWORD) */ +#define BPB_FatOfsEx 80 /* exFAT: FAT offset from top of the volume [sector] (DWORD) */ +#define BPB_FatSzEx 84 /* exFAT: FAT size [sector] (DWORD) */ +#define BPB_DataOfsEx 88 /* exFAT: Data offset from top of the volume [sector] (DWORD) */ +#define BPB_NumClusEx 92 /* exFAT: Number of clusters (DWORD) */ +#define BPB_RootClusEx 96 /* exFAT: Root directory start cluster (DWORD) */ +#define BPB_VolIDEx 100 /* exFAT: Volume serial number (DWORD) */ +#define BPB_FSVerEx 104 /* exFAT: File system version (WORD) */ +#define BPB_VolFlagEx 106 /* exFAT: Volume flags (BYTE) */ +#define BPB_ActFatEx 107 /* exFAT: Active FAT flags (BYTE) */ +#define BPB_BytsPerSecEx 108 /* exFAT: Log2 of sector size in unit of byte (BYTE) */ +#define BPB_SecPerClusEx 109 /* exFAT: Log2 of cluster size in unit of sector (BYTE) */ +#define BPB_NumFATsEx 110 /* exFAT: Number of FATs (BYTE) */ +#define BPB_DrvNumEx 111 /* exFAT: Physical drive number for int13h (BYTE) */ +#define BPB_PercInUseEx 112 /* exFAT: Percent in use (BYTE) */ +#define BPB_RsvdEx 113 /* exFAT: Reserved (7-byte) */ +#define BS_BootCodeEx 120 /* exFAT: Boot code (390-byte) */ + +#define DIR_Name 0 /* Short file name (11-byte) */ +#define DIR_Attr 11 /* Attribute (BYTE) */ +#define DIR_NTres 12 /* Lower case flag (BYTE) */ +#define DIR_CrtTime10 13 /* Created time sub-second (BYTE) */ +#define DIR_CrtTime 14 /* Created time (DWORD) */ +#define DIR_LstAccDate 18 /* Last accessed date (WORD) */ +#define DIR_FstClusHI 20 /* Higher 16-bit of first cluster (WORD) */ +#define DIR_ModTime 22 /* Modified time (DWORD) */ +#define DIR_FstClusLO 26 /* Lower 16-bit of first cluster (WORD) */ +#define DIR_FileSize 28 /* File size (DWORD) */ +#define LDIR_Ord 0 /* LFN: LFN order and LLE flag (BYTE) */ +#define LDIR_Attr 11 /* LFN: LFN attribute (BYTE) */ +#define LDIR_Type 12 /* LFN: Entry type (BYTE) */ +#define LDIR_Chksum 13 /* LFN: Checksum of the SFN (BYTE) */ +#define LDIR_FstClusLO 26 /* LFN: MBZ field (WORD) */ +#define XDIR_Type 0 /* exFAT: Type of exFAT directory entry (BYTE) */ +#define XDIR_NumLabel 1 /* exFAT: Number of volume label characters (BYTE) */ +#define XDIR_Label 2 /* exFAT: Volume label (11-WORD) */ +#define XDIR_CaseSum 4 /* exFAT: Sum of case conversion table (DWORD) */ +#define XDIR_NumSec 1 /* exFAT: Number of secondary entries (BYTE) */ +#define XDIR_SetSum 2 /* exFAT: Sum of the set of directory entries (WORD) */ +#define XDIR_Attr 4 /* exFAT: File attribute (WORD) */ +#define XDIR_CrtTime 8 /* exFAT: Created time (DWORD) */ +#define XDIR_ModTime 12 /* exFAT: Modified time (DWORD) */ +#define XDIR_AccTime 16 /* exFAT: Last accessed time (DWORD) */ +#define XDIR_CrtTime10 20 /* exFAT: Created time subsecond (BYTE) */ +#define XDIR_ModTime10 21 /* exFAT: Modified time subsecond (BYTE) */ +#define XDIR_CrtTZ 22 /* exFAT: Created timezone (BYTE) */ +#define XDIR_ModTZ 23 /* exFAT: Modified timezone (BYTE) */ +#define XDIR_AccTZ 24 /* exFAT: Last accessed timezone (BYTE) */ +#define XDIR_GenFlags 33 /* exFAT: General secondary flags (WORD) */ +#define XDIR_NumName 35 /* exFAT: Number of file name characters (BYTE) */ +#define XDIR_NameHash 36 /* exFAT: Hash of file name (WORD) */ +#define XDIR_ValidFileSize 40 /* exFAT: Valid file size (QWORD) */ +#define XDIR_FstClus 52 /* exFAT: First cluster of the file data (DWORD) */ +#define XDIR_FileSize 56 /* exFAT: File/Directory size (QWORD) */ + +#define SZDIRE 32 /* Size of a directory entry */ +#define DDEM 0xE5 /* Deleted directory entry mark set to DIR_Name[0] */ +#define RDDEM 0x05 /* Replacement of the character collides with DDEM */ +#define LLEF 0x40 /* Last long entry flag in LDIR_Ord */ + +#define FSI_LeadSig 0 /* FAT32 FSI: Leading signature (DWORD) */ +#define FSI_StrucSig 484 /* FAT32 FSI: Structure signature (DWORD) */ +#define FSI_Free_Count 488 /* FAT32 FSI: Number of free clusters (DWORD) */ +#define FSI_Nxt_Free 492 /* FAT32 FSI: Last allocated cluster (DWORD) */ + +#define MBR_Table 446 /* MBR: Offset of partition table in the MBR */ +#define SZ_PTE 16 /* MBR: Size of a partition table entry */ +#define PTE_Boot 0 /* MBR PTE: Boot indicator */ +#define PTE_StHead 1 /* MBR PTE: Start head */ +#define PTE_StSec 2 /* MBR PTE: Start sector */ +#define PTE_StCyl 3 /* MBR PTE: Start cylinder */ +#define PTE_System 4 /* MBR PTE: System ID */ +#define PTE_EdHead 5 /* MBR PTE: End head */ +#define PTE_EdSec 6 /* MBR PTE: End sector */ +#define PTE_EdCyl 7 /* MBR PTE: End cylinder */ +#define PTE_StLba 8 /* MBR PTE: Start in LBA */ +#define PTE_SizLba 12 /* MBR PTE: Size in LBA */ + + +/* Post process after fatal error on file operation */ +#define ABORT(fs, res) { fp->err = (BYTE)(res); LEAVE_FF(fs, res); } + + +/* Reentrancy related */ +#if _FS_REENTRANT +#if _USE_LFN == 1 +#error Static LFN work area cannot be used at thread-safe configuration +#endif +#define ENTER_FF(fs) { if (!lock_fs(fs)) return FR_TIMEOUT; } +#define LEAVE_FF(fs, res) { unlock_fs(fs, res); return res; } +#else +#define ENTER_FF(fs) +#define LEAVE_FF(fs, res) return res +#endif + + +/* Definitions of volume - partition conversion */ +#if _MULTI_PARTITION +#define LD2PD(vol) VolToPart[vol].pd /* Get physical drive number */ +#define LD2PT(vol) VolToPart[vol].pt /* Get partition index */ +#else +#define LD2PD(vol) (BYTE)(vol) /* Each logical drive is bound to the same physical drive number */ +#define LD2PT(vol) 0 /* Find first valid partition or in SFD */ +#endif + + +/* Definitions of sector size */ +#if (_MAX_SS < _MIN_SS) || (_MAX_SS != 512 && _MAX_SS != 1024 && _MAX_SS != 2048 && _MAX_SS != 4096) || (_MIN_SS != 512 && _MIN_SS != 1024 && _MIN_SS != 2048 && _MIN_SS != 4096) +#error Wrong sector size configuration +#endif +#if _MAX_SS == _MIN_SS +#define SS(fs) ((UINT)_MAX_SS) /* Fixed sector size */ +#else +#define SS(fs) ((fs)->ssize) /* Variable sector size */ +#endif + + +/* Timestamp */ +#if _FS_NORTC == 1 +#if _NORTC_YEAR < 1980 || _NORTC_YEAR > 2107 || _NORTC_MON < 1 || _NORTC_MON > 12 || _NORTC_MDAY < 1 || _NORTC_MDAY > 31 +#error Invalid _FS_NORTC settings +#endif +#define GET_FATTIME() ((DWORD)(_NORTC_YEAR - 1980) << 25 | (DWORD)_NORTC_MON << 21 | (DWORD)_NORTC_MDAY << 16) +#else +#define GET_FATTIME() get_fattime() +#endif + + +/* File lock controls */ +#if _FS_LOCK != 0 +#if _FS_READONLY +#error _FS_LOCK must be 0 at read-only configuration +#endif +typedef struct +{ + FATFS *fs; /* Object ID 1, volume (NULL:blank entry) */ + DWORD clu; /* Object ID 2, containing directory (0:root) */ + DWORD ofs; /* Object ID 3, offset in the directory */ + WORD ctr; /* Object open counter, 0:none, 0x01..0xFF:read mode open count, 0x100:write mode */ +} FILESEM; +#endif + + + + + +/*-------------------------------------------------------------------------- + + Module Private Work Area + +---------------------------------------------------------------------------*/ + +/* Remark: Variables defined here without initial value shall be guaranteed +/ zero/null at start-up. If not, the linker option or start-up routine is +/ not compliance with C standard. */ + +#if _VOLUMES < 1 || _VOLUMES > 10 +#error Wrong _VOLUMES setting +#endif +static FATFS *FatFs[_VOLUMES]; /* Pointer to the file system objects (logical drives) */ +static WORD Fsid; /* File system mount ID */ + +#if _FS_RPATH != 0 && _VOLUMES >= 2 +static BYTE CurrVol; /* Current drive */ +#endif + +#if _FS_LOCK != 0 +static FILESEM Files[_FS_LOCK]; /* Open object lock semaphores */ +#endif + +#if _USE_LFN == 0 /* Non-LFN configuration */ +#define DEF_NAMBUF +#define INIT_NAMBUF(fs) +#define FREE_NAMBUF() + +#else /* LFN configuration */ +#if _MAX_LFN < 12 || _MAX_LFN > 255 +#error Wrong _MAX_LFN value +#endif +#define MAXDIRB(nc) ((nc + 44U) / 15 * SZDIRE) + +#if _USE_LFN == 1 /* LFN enabled with static working buffer */ +#if _FS_EXFAT +static BYTE DirBuf[MAXDIRB(_MAX_LFN)]; /* Directory entry block scratchpad buffer */ +#endif +static WCHAR LfnBuf[_MAX_LFN + 1]; /* LFN enabled with static working buffer */ +#define DEF_NAMBUF +#define INIT_NAMBUF(fs) +#define FREE_NAMBUF() + +#elif _USE_LFN == 2 /* LFN enabled with dynamic working buffer on the stack */ +#if _FS_EXFAT +#define DEF_NAMBUF WCHAR lbuf[_MAX_LFN+1]; BYTE dbuf[MAXDIRB(_MAX_LFN)]; +#define INIT_NAMBUF(fs) { (fs)->lfnbuf = lbuf; (fs)->dirbuf = dbuf; } +#define FREE_NAMBUF() +#else +#define DEF_NAMBUF WCHAR lbuf[_MAX_LFN+1]; +#define INIT_NAMBUF(fs) { (fs)->lfnbuf = lbuf; } +#define FREE_NAMBUF() +#endif + +#elif _USE_LFN == 3 /* LFN enabled with dynamic working buffer on the heap */ +//#if _FS_EXFAT +//#define DEF_NAMBUF WCHAR *lfn; +//#define INIT_NAMBUF(fs) { lfn = ff_memalloc((_MAX_LFN+1)*2 + MAXDIRB(_MAX_LFN)); if (!lfn) LEAVE_FF(fs, FR_NOT_ENOUGH_CORE); (fs)->lfnbuf = lfn; (fs)->dirbuf = (BYTE*)(lfn+_MAX_LFN+1); } +//#define FREE_NAMBUF() ff_memfree(lfn) +//#else +//#define DEF_NAMBUF WCHAR *lfn; +//#define INIT_NAMBUF(fs) { lfn = ff_memalloc((_MAX_LFN+1)*2); if (!lfn) LEAVE_FF(fs, FR_NOT_ENOUGH_CORE); (fs)->lfnbuf = lfn; } +//#define FREE_NAMBUF() ff_memfree(lfn) +//#endif + +#else +#error Wrong _USE_LFN setting + +#endif +#endif /* else _USE_LFN == 0 */ + +#ifdef _EXCVT +static const BYTE ExCvt[] = _EXCVT; /* Upper conversion table for SBCS extended characters */ +#endif + + + + + + +/*-------------------------------------------------------------------------- + + Module Private Functions + +---------------------------------------------------------------------------*/ + + +/*-----------------------------------------------------------------------*/ +/* Load/Store multi-byte word in the FAT structure */ +/*-----------------------------------------------------------------------*/ + +static +WORD ld_word (const BYTE *ptr) /* Load a 2-byte little-endian word */ +{ + WORD rv; + + rv = ptr[1]; + rv = rv << 8 | ptr[0]; + return rv; +} + +static +DWORD ld_dword (const BYTE *ptr) /* Load a 4-byte little-endian word */ +{ + DWORD rv; + + rv = ptr[3]; + rv = rv << 8 | ptr[2]; + rv = rv << 8 | ptr[1]; + rv = rv << 8 | ptr[0]; + return rv; +} + +#if _FS_EXFAT +static +QWORD ld_qword (const BYTE *ptr) /* Load an 8-byte little-endian word */ +{ + QWORD rv; + + rv = ptr[7]; + rv = rv << 8 | ptr[6]; + rv = rv << 8 | ptr[5]; + rv = rv << 8 | ptr[4]; + rv = rv << 8 | ptr[3]; + rv = rv << 8 | ptr[2]; + rv = rv << 8 | ptr[1]; + rv = rv << 8 | ptr[0]; + return rv; +} +#endif + +#if !_FS_READONLY +static +void st_word (BYTE *ptr, WORD val) /* Store a 2-byte word in little-endian */ +{ + *ptr++ = (BYTE)val; + val >>= 8; + *ptr++ = (BYTE)val; +} + +static +void st_dword (BYTE *ptr, DWORD val) /* Store a 4-byte word in little-endian */ +{ + *ptr++ = (BYTE)val; + val >>= 8; + *ptr++ = (BYTE)val; + val >>= 8; + *ptr++ = (BYTE)val; + val >>= 8; + *ptr++ = (BYTE)val; +} + +#if _FS_EXFAT +static +void st_qword (BYTE *ptr, QWORD val) /* Store an 8-byte word in little-endian */ +{ + *ptr++ = (BYTE)val; + val >>= 8; + *ptr++ = (BYTE)val; + val >>= 8; + *ptr++ = (BYTE)val; + val >>= 8; + *ptr++ = (BYTE)val; + val >>= 8; + *ptr++ = (BYTE)val; + val >>= 8; + *ptr++ = (BYTE)val; + val >>= 8; + *ptr++ = (BYTE)val; + val >>= 8; + *ptr++ = (BYTE)val; +} +#endif +#endif /* !_FS_READONLY */ + + + +/*-----------------------------------------------------------------------*/ +/* String functions */ +/*-----------------------------------------------------------------------*/ + +/* Copy memory to memory */ +//static +//void memcpy (void* dst, const void* src, UINT cnt) { +// BYTE *d = (BYTE*)dst; +// const BYTE *s = (const BYTE*)src; + +// if (cnt) { +// do { +// *d++ = *s++; +// } while (--cnt); +// } +//} + +/* Fill memory block */ +//static +//void memset (void* dst, int val, UINT cnt) { +// BYTE *d = (BYTE*)dst; + +// do { +// *d++ = (BYTE)val; +// } while (--cnt); +//} + +/* Compare memory block */ +//static +//int memcmp (const void* dst, const void* src, UINT cnt) { /* ZR:same, NZ:different */ +// const BYTE *d = (const BYTE *)dst, *s = (const BYTE *)src; +// int r = 0; + +// do { +// r = *d++ - *s++; +// } while (--cnt && r == 0); + +// return r; +//} + +/* Check if chr is contained in the string */ +static +int chk_chr (const char *str, int chr) /* NZ:contained, ZR:not contained */ +{ + while (*str && *str != chr) str++; + return *str; +} + + + + +#if _FS_REENTRANT +/*-----------------------------------------------------------------------*/ +/* Request/Release grant to access the volume */ +/*-----------------------------------------------------------------------*/ +static +int lock_fs ( + FATFS *fs /* File system object */ +) +{ + return (fs && ff_req_grant(fs->sobj)) ? 1 : 0; +} + + +static +void unlock_fs ( + FATFS *fs, /* File system object */ + FRESULT res /* Result code to be returned */ +) +{ + if (fs && res != FR_NOT_ENABLED && res != FR_INVALID_DRIVE && res != FR_TIMEOUT) + { + ff_rel_grant(fs->sobj); + } +} + +#endif + + + +#if _FS_LOCK != 0 +/*-----------------------------------------------------------------------*/ +/* File lock control functions */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT chk_lock ( /* Check if the file can be accessed */ + DIR *dp, /* Directory object pointing the file to be checked */ + int acc /* Desired access type (0:Read, 1:Write, 2:Delete/Rename) */ +) +{ + UINT i, be; + + /* Search file semaphore table */ + for (i = be = 0; i < _FS_LOCK; i++) + { + if (Files[i].fs) /* Existing entry */ + { + if (Files[i].fs == dp->obj.fs && /* Check if the object matched with an open object */ + Files[i].clu == dp->obj.sclust && + Files[i].ofs == dp->dptr) break; + } + else /* Blank entry */ + { + be = 1; + } + } + if (i == _FS_LOCK) /* The object is not opened */ + { + return (be || acc == 2) ? FR_OK : FR_TOO_MANY_OPEN_FILES; /* Is there a blank entry for new object? */ + } + + /* The object has been opened. Reject any open against writing file and all write mode open */ + return (acc || Files[i].ctr == 0x100) ? FR_LOCKED : FR_OK; +} + + +static +int enq_lock (void) /* Check if an entry is available for a new object */ +{ + UINT i; + + for (i = 0; i < _FS_LOCK && Files[i].fs; i++) ; + return (i == _FS_LOCK) ? 0 : 1; +} + + +static +UINT inc_lock ( /* Increment object open counter and returns its index (0:Internal error) */ + DIR *dp, /* Directory object pointing the file to register or increment */ + int acc /* Desired access (0:Read, 1:Write, 2:Delete/Rename) */ +) +{ + UINT i; + + + for (i = 0; i < _FS_LOCK; i++) /* Find the object */ + { + if (Files[i].fs == dp->obj.fs && + Files[i].clu == dp->obj.sclust && + Files[i].ofs == dp->dptr) break; + } + + if (i == _FS_LOCK) /* Not opened. Register it as new. */ + { + for (i = 0; i < _FS_LOCK && Files[i].fs; i++) ; + if (i == _FS_LOCK) return 0; /* No free entry to register (int err) */ + Files[i].fs = dp->obj.fs; + Files[i].clu = dp->obj.sclust; + Files[i].ofs = dp->dptr; + Files[i].ctr = 0; + } + + if (acc && Files[i].ctr) return 0; /* Access violation (int err) */ + + Files[i].ctr = acc ? 0x100 : Files[i].ctr + 1; /* Set semaphore value */ + + return i + 1; +} + + +static +FRESULT dec_lock ( /* Decrement object open counter */ + UINT i /* Semaphore index (1..) */ +) +{ + WORD n; + FRESULT res; + + + if (--i < _FS_LOCK) /* Shift index number origin from 0 */ + { + n = Files[i].ctr; + if (n == 0x100) n = 0; /* If write mode open, delete the entry */ + if (n > 0) n--; /* Decrement read mode open count */ + Files[i].ctr = n; + if (n == 0) Files[i].fs = 0; /* Delete the entry if open count gets zero */ + res = FR_OK; + } + else + { + res = FR_INT_ERR; /* Invalid index nunber */ + } + return res; +} + + +static +void clear_lock ( /* Clear lock entries of the volume */ + FATFS *fs +) +{ + UINT i; + + for (i = 0; i < _FS_LOCK; i++) + { + if (Files[i].fs == fs) Files[i].fs = 0; + } +} + +#endif /* _FS_LOCK != 0 */ + + + +/*-----------------------------------------------------------------------*/ +/* Move/Flush disk access window in the file system object */ +/*-----------------------------------------------------------------------*/ +#if !_FS_READONLY +static +FRESULT sync_window ( /* Returns FR_OK or FR_DISK_ERROR */ + FATFS *fs /* File system object */ +) +{ + DWORD wsect; + UINT nf; + FRESULT res = FR_OK; + + + if (fs->wflag) /* Write back the sector if it is dirty */ + { + wsect = fs->winsect; /* Current sector number */ + if (disk_write(fs->drv, fs->win, wsect, 1) != RES_OK) + { + res = FR_DISK_ERR; + } + else + { + fs->wflag = 0; + if (wsect - fs->fatbase < fs->fsize) /* Is it in the FAT area? */ + { + for (nf = fs->n_fats; nf >= 2; nf--) /* Reflect the change to all FAT copies */ + { + wsect += fs->fsize; + disk_write(fs->drv, fs->win, wsect, 1); + } + } + } + } + return res; +} +#endif + + +//static +FRESULT move_window ( /* Returns FR_OK or FR_DISK_ERROR */ + FATFS *fs, /* File system object */ + DWORD sector /* Sector number to make appearance in the fs->win[] */ +) +{ + FRESULT res = FR_OK; + + + if (sector != fs->winsect) /* Window offset changed? */ + { +#if !_FS_READONLY + res = sync_window(fs); /* Write-back changes */ +#endif + if (res == FR_OK) /* Fill sector window with new data */ + { + if (disk_read(fs->drv, fs->win, sector, 1) != RES_OK) + { + sector = 0xFFFFFFFF; /* Invalidate window if data is not reliable */ + res = FR_DISK_ERR; + } + fs->winsect = sector; + } + } + return res; +} + + + + +#if !_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Synchronize file system and strage device */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT sync_fs ( /* FR_OK:succeeded, !=0:error */ + FATFS *fs /* File system object */ +) +{ + FRESULT res; + + + res = sync_window(fs); + if (res == FR_OK) + { + /* Update FSInfo sector if needed */ + if (fs->fs_type == FS_FAT32 && fs->fsi_flag == 1) + { + /* Create FSInfo structure */ + memset(fs->win, 0, SS(fs)); + st_word(fs->win + BS_55AA, 0xAA55); + st_dword(fs->win + FSI_LeadSig, 0x41615252); + st_dword(fs->win + FSI_StrucSig, 0x61417272); + st_dword(fs->win + FSI_Free_Count, fs->free_clst); + st_dword(fs->win + FSI_Nxt_Free, fs->last_clst); + /* Write it into the FSInfo sector */ + fs->winsect = fs->volbase + 1; + disk_write(fs->drv, fs->win, fs->winsect, 1); + fs->fsi_flag = 0; + } + /* Make sure that no pending write process in the physical drive */ + if (disk_ioctl(fs->drv, CTRL_SYNC, 0) != RES_OK) res = FR_DISK_ERR; + } + + return res; +} + +#endif + + + +/*-----------------------------------------------------------------------*/ +/* Get sector# from cluster# */ +/*-----------------------------------------------------------------------*/ + +static +DWORD clust2sect ( /* !=0:Sector number, 0:Failed (invalid cluster#) */ + FATFS *fs, /* File system object */ + DWORD clst /* Cluster# to be converted */ +) +{ + clst -= 2; + if (clst >= fs->n_fatent - 2) return 0; /* Invalid cluster# */ + return clst * fs->csize + fs->database; +} + + + + +/*-----------------------------------------------------------------------*/ +/* FAT access - Read value of a FAT entry */ +/*-----------------------------------------------------------------------*/ + +static +DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, 2..0x7FFFFFFF:Cluster status */ + _FDID *obj, /* Corresponding object */ + DWORD clst /* Cluster number to get the value */ +) +{ + UINT wc, bc; + DWORD val; + FATFS *fs = obj->fs; + + + if (clst < 2 || clst >= fs->n_fatent) /* Check if in valid range */ + { + val = 1; /* Internal error */ + + } + else + { + val = 0xFFFFFFFF; /* Default value falls on disk error */ + + switch (fs->fs_type) + { + case FS_FAT12 : + bc = (UINT)clst; + bc += bc / 2; + if (move_window(fs, fs->fatbase + (bc / SS(fs))) != FR_OK) break; + wc = fs->win[bc++ % SS(fs)]; + if (move_window(fs, fs->fatbase + (bc / SS(fs))) != FR_OK) break; + wc |= fs->win[bc % SS(fs)] << 8; + val = (clst & 1) ? (wc >> 4) : (wc & 0xFFF); + break; + + case FS_FAT16 : + if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 2))) != FR_OK) break; + val = ld_word(fs->win + clst * 2 % SS(fs)); + break; + + case FS_FAT32 : + if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))) != FR_OK) break; + val = ld_dword(fs->win + clst * 4 % SS(fs)) & 0x0FFFFFFF; + break; +#if _FS_EXFAT + case FS_EXFAT : + if (obj->objsize) + { + DWORD cofs = clst - obj->sclust; /* Offset from start cluster */ + DWORD clen = (DWORD)((obj->objsize - 1) / SS(fs)) / fs->csize; /* Number of clusters - 1 */ + + if (obj->stat == 2) /* Is there no valid chain on the FAT? */ + { + if (cofs <= clen) + { + val = (cofs == clen) ? 0x7FFFFFFF : clst + 1; /* Generate the value */ + break; + } + } + if (obj->stat == 3 && cofs < obj->n_cont) /* Is it in the 1st fragment? */ + { + val = clst + 1; /* Generate the value */ + break; + } + if (obj->stat != 2) /* Get value from FAT if FAT chain is valid */ + { + if (obj->n_frag != 0) /* Is it on the growing edge? */ + { + val = 0x7FFFFFFF; /* Generate EOC */ + } + else + { + if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))) != FR_OK) break; + val = ld_dword(fs->win + clst * 4 % SS(fs)) & 0x7FFFFFFF; + } + break; + } + } + /* go to default */ + + default: + val = 1; /* Internal error */ +#endif + } + } + + return val; +} + + + + +#if !_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* FAT access - Change value of a FAT entry */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT put_fat ( /* FR_OK(0):succeeded, !=0:error */ + FATFS *fs, /* Corresponding file system object */ + DWORD clst, /* FAT index number (cluster number) to be changed */ + DWORD val /* New value to be set to the entry */ +) +{ + UINT bc; + BYTE *p; + FRESULT res = FR_INT_ERR; + + if (clst >= 2 && clst < fs->n_fatent) /* Check if in valid range */ + { + switch (fs->fs_type) + { + case FS_FAT12 : /* Bitfield items */ + bc = (UINT)clst; + bc += bc / 2; + res = move_window(fs, fs->fatbase + (bc / SS(fs))); + if (res != FR_OK) break; + p = fs->win + bc++ % SS(fs); + *p = (clst & 1) ? ((*p & 0x0F) | ((BYTE)val << 4)) : (BYTE)val; + fs->wflag = 1; + res = move_window(fs, fs->fatbase + (bc / SS(fs))); + if (res != FR_OK) break; + p = fs->win + bc % SS(fs); + *p = (clst & 1) ? (BYTE)(val >> 4) : ((*p & 0xF0) | ((BYTE)(val >> 8) & 0x0F)); + fs->wflag = 1; + break; + + case FS_FAT16 : /* WORD aligned items */ + res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 2))); + if (res != FR_OK) break; + st_word(fs->win + clst * 2 % SS(fs), (WORD)val); + fs->wflag = 1; + break; + + case FS_FAT32 : /* DWORD aligned items */ +#if _FS_EXFAT + case FS_EXFAT : +#endif + res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))); + if (res != FR_OK) break; + if (!_FS_EXFAT || fs->fs_type != FS_EXFAT) + { + val = (val & 0x0FFFFFFF) | (ld_dword(fs->win + clst * 4 % SS(fs)) & 0xF0000000); + } + st_dword(fs->win + clst * 4 % SS(fs), val); + fs->wflag = 1; + break; + } + } + return res; +} + +#endif /* !_FS_READONLY */ + + + + +#if _FS_EXFAT && !_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* exFAT: Accessing FAT and Allocation Bitmap */ +/*-----------------------------------------------------------------------*/ + +/*--------------------------------------*/ +/* Find a contiguous free cluster block */ +/*--------------------------------------*/ + +static +DWORD find_bitmap ( /* 0:Not found, 2..:Cluster block found, 0xFFFFFFFF:Disk error */ + FATFS *fs, /* File system object */ + DWORD clst, /* Cluster number to scan from */ + DWORD ncl /* Number of contiguous clusters to find (1..) */ +) +{ + BYTE bm, bv; + UINT i; + DWORD val, scl, ctr; + + + clst -= 2; /* The first bit in the bitmap corresponds to cluster #2 */ + if (clst >= fs->n_fatent - 2) clst = 0; + scl = val = clst; + ctr = 0; + for (;;) + { + if (move_window(fs, fs->database + val / 8 / SS(fs)) != FR_OK) return 0xFFFFFFFF; /* (assuming bitmap is located top of the cluster heap) */ + i = val / 8 % SS(fs); + bm = 1 << (val % 8); + do + { + do + { + bv = fs->win[i] & bm; + bm <<= 1; /* Get bit value */ + if (++val >= fs->n_fatent - 2) /* Next cluster (with wrap-around) */ + { + val = 0; + bm = 0; + i = SS(fs); + } + if (!bv) /* Is it a free cluster? */ + { + if (++ctr == ncl) return scl + 2; /* Check if run length is sufficient for required */ + } + else + { + scl = val; + ctr = 0; /* Encountered a cluster in-use, restart to scan */ + } + if (val == clst) return 0; /* All cluster scanned? */ + } + while (bm); + bm = 1; + } + while (++i < SS(fs)); + } +} + + +/*----------------------------------------*/ +/* Set/Clear a block of allocation bitmap */ +/*----------------------------------------*/ + +static +FRESULT change_bitmap ( + FATFS *fs, /* File system object */ + DWORD clst, /* Cluster number to change from */ + DWORD ncl, /* Number of clusters to be changed */ + int bv /* bit value to be set (0 or 1) */ +) +{ + BYTE bm; + UINT i; + DWORD sect; + + clst -= 2; /* The first bit corresponds to cluster #2 */ + sect = fs->database + clst / 8 / SS(fs); /* Sector address (assuming bitmap is located top of the cluster heap) */ + i = clst / 8 % SS(fs); /* Byte offset in the sector */ + bm = 1 << (clst % 8); /* Bit mask in the byte */ + for (;;) + { + if (move_window(fs, sect++) != FR_OK) return FR_DISK_ERR; + do + { + do + { + if (bv == (int)((fs->win[i] & bm) != 0)) return FR_INT_ERR; /* Is the bit expected value? */ + fs->win[i] ^= bm; /* Flip the bit */ + fs->wflag = 1; + if (--ncl == 0) return FR_OK; /* All bits processed? */ + } + while (bm <<= 1); /* Next bit */ + bm = 1; + } + while (++i < SS(fs)); /* Next byte */ + i = 0; + } +} + + +/*---------------------------------------------*/ +/* Fill the first fragment of the FAT chain */ +/*---------------------------------------------*/ + +static +FRESULT fill_first_frag ( + _FDID *obj /* Pointer to the corresponding object */ +) +{ + FRESULT res; + DWORD cl, n; + + if (obj->stat == 3) /* Has the object been changed 'fragmented'? */ + { + for (cl = obj->sclust, n = obj->n_cont; n; cl++, n--) /* Create cluster chain on the FAT */ + { + res = put_fat(obj->fs, cl, cl + 1); + if (res != FR_OK) return res; + } + obj->stat = 0; /* Change status 'FAT chain is valid' */ + } + return FR_OK; +} + + +/*---------------------------------------------*/ +/* Fill the last fragment of the FAT chain */ +/*---------------------------------------------*/ + +static +FRESULT fill_last_frag ( + _FDID *obj, /* Pointer to the corresponding object */ + DWORD lcl, /* Last cluster of the fragment */ + DWORD term /* Value to set the last FAT entry */ +) +{ + FRESULT res; + + while (obj->n_frag > 0) /* Create the last chain on the FAT */ + { + res = put_fat(obj->fs, lcl - obj->n_frag + 1, (obj->n_frag > 1) ? lcl - obj->n_frag + 2 : term); + if (res != FR_OK) return res; + obj->n_frag--; + } + return FR_OK; +} + +#endif /* _FS_EXFAT && !_FS_READONLY */ + + + +#if !_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* FAT handling - Remove a cluster chain */ +/*-----------------------------------------------------------------------*/ +static +FRESULT remove_chain ( /* FR_OK(0):succeeded, !=0:error */ + _FDID *obj, /* Corresponding object */ + DWORD clst, /* Cluster to remove a chain from */ + DWORD pclst /* Previous cluster of clst (0:an entire chain) */ +) +{ + FRESULT res = FR_OK; + DWORD nxt; + FATFS *fs = obj->fs; +#if _FS_EXFAT || _USE_TRIM + DWORD scl = clst, ecl = clst; +#endif +#if _USE_TRIM + DWORD rt[2]; +#endif + + if (clst < 2 || clst >= fs->n_fatent) return FR_INT_ERR; /* Check if in valid range */ + + /* Mark the previous cluster 'EOC' on the FAT if it exists */ + if (pclst && (!_FS_EXFAT || fs->fs_type != FS_EXFAT || obj->stat != 2)) + { + res = put_fat(fs, pclst, 0xFFFFFFFF); + if (res != FR_OK) return res; + } + + /* Remove the chain */ + do + { + nxt = get_fat(obj, clst); /* Get cluster status */ + if (nxt == 0) break; /* Empty cluster? */ + if (nxt == 1) return FR_INT_ERR; /* Internal error? */ + if (nxt == 0xFFFFFFFF) return FR_DISK_ERR; /* Disk error? */ + if (!_FS_EXFAT || fs->fs_type != FS_EXFAT) + { + res = put_fat(fs, clst, 0); /* Mark the cluster 'free' on the FAT */ + if (res != FR_OK) return res; + } + if (fs->free_clst < fs->n_fatent - 2) /* Update FSINFO */ + { + fs->free_clst++; + fs->fsi_flag |= 1; + } +#if _FS_EXFAT || _USE_TRIM + if (ecl + 1 == nxt) /* Is next cluster contiguous? */ + { + ecl = nxt; + } + else /* End of contiguous cluster block */ + { +#if _FS_EXFAT + if (fs->fs_type == FS_EXFAT) + { + res = change_bitmap(fs, scl, ecl - scl + 1, 0); /* Mark the cluster block 'free' on the bitmap */ + if (res != FR_OK) return res; + } +#endif +#if _USE_TRIM + rt[0] = clust2sect(fs, scl); /* Start sector */ + rt[1] = clust2sect(fs, ecl) + fs->csize - 1; /* End sector */ + disk_ioctl(fs->drv, CTRL_TRIM, rt); /* Inform device the block can be erased */ +#endif + scl = ecl = nxt; + } +#endif + clst = nxt; /* Next cluster */ + } + while (clst < fs->n_fatent); /* Repeat while not the last link */ + +#if _FS_EXFAT + if (fs->fs_type == FS_EXFAT) + { + if (pclst == 0) /* Does the object have no chain? */ + { + obj->stat = 0; /* Change the object status 'initial' */ + } + else + { + if (obj->stat == 3 && pclst >= obj->sclust && pclst <= obj->sclust + obj->n_cont) /* Did the chain get contiguous? */ + { + obj->stat = 2; /* Change the object status 'contiguous' */ + } + } + } +#endif + return FR_OK; +} + + + + +/*-----------------------------------------------------------------------*/ +/* FAT handling - Stretch a chain or Create a new chain */ +/*-----------------------------------------------------------------------*/ +static +DWORD create_chain ( /* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk error, >=2:New cluster# */ + _FDID *obj, /* Corresponding object */ + DWORD clst /* Cluster# to stretch, 0:Create a new chain */ +) +{ + DWORD cs, ncl, scl; + FRESULT res; + FATFS *fs = obj->fs; + + + if (clst == 0) /* Create a new chain */ + { + scl = fs->last_clst; /* Get suggested cluster to start from */ + if (scl == 0 || scl >= fs->n_fatent) scl = 1; + } + else /* Stretch current chain */ + { + cs = get_fat(obj, clst); /* Check the cluster status */ + if (cs < 2) return 1; /* Invalid FAT value */ + if (cs == 0xFFFFFFFF) return cs; /* A disk error occurred */ + if (cs < fs->n_fatent) return cs; /* It is already followed by next cluster */ + scl = clst; + } + +#if _FS_EXFAT + if (fs->fs_type == FS_EXFAT) /* On the exFAT volume */ + { + ncl = find_bitmap(fs, scl, 1); /* Find a free cluster */ + if (ncl == 0 || ncl == 0xFFFFFFFF) return ncl; /* No free cluster or hard error? */ + res = change_bitmap(fs, ncl, 1, 1); /* Mark the cluster 'in use' */ + if (res == FR_INT_ERR) return 1; + if (res == FR_DISK_ERR) return 0xFFFFFFFF; + if (clst == 0) /* Is it a new chain? */ + { + obj->stat = 2; /* Set status 'contiguous' */ + } + else /* It is a stretched chain */ + { + if (obj->stat == 2 && ncl != scl + 1) /* Is the chain got fragmented? */ + { + obj->n_cont = scl - obj->sclust; /* Set size of the contiguous part */ + obj->stat = 3; /* Change status 'just fragmented' */ + } + } + if (obj->stat != 2) /* Is the file non-contiguous? */ + { + if (ncl == clst + 1) /* Is the cluster next to previous one? */ + { + obj->n_frag = obj->n_frag ? obj->n_frag + 1 : 2; /* Increment size of last framgent */ + } + else /* New fragment */ + { + if (obj->n_frag == 0) obj->n_frag = 1; + res = fill_last_frag(obj, clst, ncl); /* Fill last fragment on the FAT and link it to new one */ + if (res == FR_OK) obj->n_frag = 1; + } + } + } + else +#endif + { + /* On the FAT12/16/32 volume */ + ncl = scl; /* Start cluster */ + for (;;) + { + ncl++; /* Next cluster */ + if (ncl >= fs->n_fatent) /* Check wrap-around */ + { + ncl = 2; + if (ncl > scl) return 0; /* No free cluster */ + } + cs = get_fat(obj, ncl); /* Get the cluster status */ + if (cs == 0) break; /* Found a free cluster */ + if (cs == 1 || cs == 0xFFFFFFFF) return cs; /* An error occurred */ + if (ncl == scl) return 0; /* No free cluster */ + } + res = put_fat(fs, ncl, 0xFFFFFFFF); /* Mark the new cluster 'EOC' */ + if (res == FR_OK && clst != 0) + { + res = put_fat(fs, clst, ncl); /* Link it from the previous one if needed */ + } + } + + if (res == FR_OK) /* Update FSINFO if function succeeded. */ + { + fs->last_clst = ncl; + if (fs->free_clst <= fs->n_fatent - 2) fs->free_clst--; + fs->fsi_flag |= 1; + } + else + { + ncl = (res == FR_DISK_ERR) ? 0xFFFFFFFF : 1; /* Failed. Generate error status */ + } + + return ncl; /* Return new cluster number or error status */ +} + +#endif /* !_FS_READONLY */ + + + + +#if _USE_FASTSEEK +/*-----------------------------------------------------------------------*/ +/* FAT handling - Convert offset into cluster with link map table */ +/*-----------------------------------------------------------------------*/ + +static +DWORD clmt_clust ( /* <2:Error, >=2:Cluster number */ + FIL *fp, /* Pointer to the file object */ + FSIZE_t ofs /* File offset to be converted to cluster# */ +) +{ + DWORD cl, ncl, *tbl; + FATFS *fs = fp->obj.fs; + + + tbl = fp->cltbl + 1; /* Top of CLMT */ + cl = (DWORD)(ofs / SS(fs) / fs->csize); /* Cluster order from top of the file */ + for (;;) + { + ncl = *tbl++; /* Number of cluters in the fragment */ + if (ncl == 0) return 0; /* End of table? (error) */ + if (cl < ncl) break; /* In this fragment? */ + cl -= ncl; + tbl++; /* Next fragment */ + } + return cl + *tbl; /* Return the cluster number */ +} + +#endif /* _USE_FASTSEEK */ + + + + +/*-----------------------------------------------------------------------*/ +/* Directory handling - Set directory index */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT dir_sdi ( /* FR_OK(0):succeeded, !=0:error */ + DIR *dp, /* Pointer to directory object */ + DWORD ofs /* Offset of directory table */ +) +{ + DWORD csz, clst; + FATFS *fs = dp->obj.fs; + + + if (ofs >= (DWORD)((_FS_EXFAT && fs->fs_type == FS_EXFAT) ? MAX_DIR_EX : MAX_DIR) || ofs % SZDIRE) /* Check range of offset and alignment */ + { + return FR_INT_ERR; + } + dp->dptr = ofs; /* Set current offset */ + clst = dp->obj.sclust; /* Table start cluster (0:root) */ + if (clst == 0 && fs->fs_type >= FS_FAT32) /* Replace cluster# 0 with root cluster# */ + { + clst = fs->dirbase; + if (_FS_EXFAT) dp->obj.stat = 0; /* exFAT: Root dir has an FAT chain */ + } + + if (clst == 0) /* Static table (root-directory in FAT12/16) */ + { + if (ofs / SZDIRE >= fs->n_rootdir) return FR_INT_ERR; /* Is index out of range? */ + dp->sect = fs->dirbase; + + } + else /* Dynamic table (sub-directory or root-directory in FAT32+) */ + { + csz = (DWORD)fs->csize * SS(fs); /* Bytes per cluster */ + while (ofs >= csz) /* Follow cluster chain */ + { + clst = get_fat(&dp->obj, clst); /* Get next cluster */ + if (clst == 0xFFFFFFFF) return FR_DISK_ERR; /* Disk error */ + if (clst < 2 || clst >= fs->n_fatent) return FR_INT_ERR; /* Reached to end of table or internal error */ + ofs -= csz; + } + dp->sect = clust2sect(fs, clst); + } + dp->clust = clst; /* Current cluster# */ + if (!dp->sect) return FR_INT_ERR; + dp->sect += ofs / SS(fs); /* Sector# of the directory entry */ + dp->dir = fs->win + (ofs % SS(fs)); /* Pointer to the entry in the win[] */ + + return FR_OK; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Directory handling - Move directory table index next */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT dir_next ( /* FR_OK(0):succeeded, FR_NO_FILE:End of table, FR_DENIED:Could not stretch */ + DIR *dp, /* Pointer to the directory object */ + int stretch /* 0: Do not stretch table, 1: Stretch table if needed */ +) +{ + DWORD ofs, clst; + FATFS *fs = dp->obj.fs; +#if !_FS_READONLY + UINT n; +#endif + + ofs = dp->dptr + SZDIRE; /* Next entry */ + if (!dp->sect || ofs >= (DWORD)((_FS_EXFAT && fs->fs_type == FS_EXFAT) ? MAX_DIR_EX : MAX_DIR)) return FR_NO_FILE; /* Report EOT when offset has reached max value */ + + if (ofs % SS(fs) == 0) /* Sector changed? */ + { + dp->sect++; /* Next sector */ + + if (!dp->clust) /* Static table */ + { + if (ofs / SZDIRE >= fs->n_rootdir) /* Report EOT if it reached end of static table */ + { + dp->sect = 0; + return FR_NO_FILE; + } + } + else /* Dynamic table */ + { + if ((ofs / SS(fs) & (fs->csize - 1)) == 0) /* Cluster changed? */ + { + clst = get_fat(&dp->obj, dp->clust); /* Get next cluster */ + if (clst <= 1) return FR_INT_ERR; /* Internal error */ + if (clst == 0xFFFFFFFF) return FR_DISK_ERR; /* Disk error */ + if (clst >= fs->n_fatent) /* Reached end of dynamic table */ + { +#if !_FS_READONLY + if (!stretch) /* If no stretch, report EOT */ + { + dp->sect = 0; + return FR_NO_FILE; + } + clst = create_chain(&dp->obj, dp->clust); /* Allocate a cluster */ + if (clst == 0) return FR_DENIED; /* No free cluster */ + if (clst == 1) return FR_INT_ERR; /* Internal error */ + if (clst == 0xFFFFFFFF) return FR_DISK_ERR; /* Disk error */ + /* Clean-up the stretched table */ + if (_FS_EXFAT) dp->obj.stat |= 4; /* The directory needs to be updated */ + if (sync_window(fs) != FR_OK) return FR_DISK_ERR; /* Flush disk access window */ + memset(fs->win, 0, SS(fs)); /* Clear window buffer */ + for (n = 0, fs->winsect = clust2sect(fs, clst); n < fs->csize; n++, fs->winsect++) /* Fill the new cluster with 0 */ + { + fs->wflag = 1; + if (sync_window(fs) != FR_OK) return FR_DISK_ERR; + } + fs->winsect -= n; /* Restore window offset */ +#else + if (!stretch) dp->sect = 0; /* (this line is to suppress compiler warning) */ + dp->sect = 0; + return FR_NO_FILE; /* Report EOT */ +#endif + } + dp->clust = clst; /* Initialize data for new cluster */ + dp->sect = clust2sect(fs, clst); + } + } + } + dp->dptr = ofs; /* Current entry */ + dp->dir = fs->win + ofs % SS(fs); /* Pointer to the entry in the win[] */ + + return FR_OK; +} + + + + +#if !_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Directory handling - Reserve a block of directory entries */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT dir_alloc ( /* FR_OK(0):succeeded, !=0:error */ + DIR *dp, /* Pointer to the directory object */ + UINT nent /* Number of contiguous entries to allocate */ +) +{ + FRESULT res; + UINT n; + FATFS *fs = dp->obj.fs; + + + res = dir_sdi(dp, 0); + if (res == FR_OK) + { + n = 0; + do + { + res = move_window(fs, dp->sect); + if (res != FR_OK) break; +#if _FS_EXFAT + if ((fs->fs_type == FS_EXFAT) ? (int)((dp->dir[XDIR_Type] & 0x80) == 0) : (int)(dp->dir[DIR_Name] == DDEM || dp->dir[DIR_Name] == 0)) + { +#else + if (dp->dir[DIR_Name] == DDEM || dp->dir[DIR_Name] == 0) + { +#endif + if (++n == nent) break; /* A block of contiguous free entries is found */ + } + else + { + n = 0; /* Not a blank entry. Restart to search */ + } + res = dir_next(dp, 1); + } + while (res == FR_OK); /* Next entry with table stretch enabled */ + } + + if (res == FR_NO_FILE) res = FR_DENIED; /* No directory entry to allocate */ + return res; +} + +#endif /* !_FS_READONLY */ + + + + +/*-----------------------------------------------------------------------*/ +/* FAT: Directory handling - Load/Store start cluster number */ +/*-----------------------------------------------------------------------*/ + +static +DWORD ld_clust ( /* Returns the top cluster value of the SFN entry */ + FATFS *fs, /* Pointer to the fs object */ + const BYTE *dir /* Pointer to the key entry */ +) +{ + DWORD cl; + + cl = ld_word(dir + DIR_FstClusLO); + if (fs->fs_type == FS_FAT32) + { + cl |= (DWORD)ld_word(dir + DIR_FstClusHI) << 16; + } + + return cl; +} + + +#if !_FS_READONLY +static +void st_clust ( + FATFS *fs, /* Pointer to the fs object */ + BYTE *dir, /* Pointer to the key entry */ + DWORD cl /* Value to be set */ +) +{ + st_word(dir + DIR_FstClusLO, (WORD)cl); + if (fs->fs_type == FS_FAT32) + { + st_word(dir + DIR_FstClusHI, (WORD)(cl >> 16)); + } +} +#endif + + + +#if _USE_LFN != 0 +/*------------------------------------------------------------------------*/ +/* FAT-LFN: LFN handling */ +/*------------------------------------------------------------------------*/ +static +const BYTE LfnOfs[] = {1, 3, 5, 7, 9, 14, 16, 18, 20, 22, 24, 28, 30}; /* Offset of LFN characters in the directory entry */ + + +/*--------------------------------------------------------*/ +/* FAT-LFN: Compare a part of file name with an LFN entry */ +/*--------------------------------------------------------*/ +static +int cmp_lfn ( /* 1:matched, 0:not matched */ + const WCHAR *lfnbuf, /* Pointer to the LFN working buffer to be compared */ + BYTE *dir /* Pointer to the directory entry containing the part of LFN */ +) +{ + UINT i, s; + WCHAR wc, uc; + + + if (ld_word(dir + LDIR_FstClusLO) != 0) return 0; /* Check LDIR_FstClusLO */ + + i = ((dir[LDIR_Ord] & 0x3F) - 1) * 13; /* Offset in the LFN buffer */ + + for (wc = 1, s = 0; s < 13; s++) /* Process all characters in the entry */ + { + uc = ld_word(dir + LfnOfs[s]); /* Pick an LFN character */ + if (wc) + { + if (i >= _MAX_LFN || ff_wtoupper(uc) != ff_wtoupper(lfnbuf[i++])) /* Compare it */ + { + return 0; /* Not matched */ + } + wc = uc; + } + else + { + if (uc != 0xFFFF) return 0; /* Check filler */ + } + } + + if ((dir[LDIR_Ord] & LLEF) && wc && lfnbuf[i]) return 0; /* Last segment matched but different length */ + + return 1; /* The part of LFN matched */ +} + + +#if _FS_MINIMIZE <= 1 || _FS_RPATH >= 2 || _USE_LABEL || _FS_EXFAT +/*-----------------------------------------------------*/ +/* FAT-LFN: Pick a part of file name from an LFN entry */ +/*-----------------------------------------------------*/ +static +int pick_lfn ( /* 1:succeeded, 0:buffer overflow or invalid LFN entry */ + WCHAR *lfnbuf, /* Pointer to the LFN working buffer */ + BYTE *dir /* Pointer to the LFN entry */ +) +{ + UINT i, s; + WCHAR wc, uc; + + + if (ld_word(dir + LDIR_FstClusLO) != 0) return 0; /* Check LDIR_FstClusLO is 0 */ + + i = ((dir[LDIR_Ord] & ~LLEF) - 1) * 13; /* Offset in the LFN buffer */ + + for (wc = 1, s = 0; s < 13; s++) /* Process all characters in the entry */ + { + uc = ld_word(dir + LfnOfs[s]); /* Pick an LFN character */ + if (wc) + { + if (i >= _MAX_LFN) return 0; /* Buffer overflow? */ + lfnbuf[i++] = wc = uc; /* Store it */ + } + else + { + if (uc != 0xFFFF) return 0; /* Check filler */ + } + } + + if (dir[LDIR_Ord] & LLEF) /* Put terminator if it is the last LFN part */ + { + if (i >= _MAX_LFN) return 0; /* Buffer overflow? */ + lfnbuf[i] = 0; + } + + return 1; /* The part of LFN is valid */ +} +#endif + + +#if !_FS_READONLY +/*-----------------------------------------*/ +/* FAT-LFN: Create an entry of LFN entries */ +/*-----------------------------------------*/ +static +void put_lfn ( + const WCHAR *lfn, /* Pointer to the LFN */ + BYTE *dir, /* Pointer to the LFN entry to be created */ + BYTE ord, /* LFN order (1-20) */ + BYTE sum /* Checksum of the corresponding SFN */ +) +{ + UINT i, s; + WCHAR wc; + + + dir[LDIR_Chksum] = sum; /* Set checksum */ + dir[LDIR_Attr] = AM_LFN; /* Set attribute. LFN entry */ + dir[LDIR_Type] = 0; + st_word(dir + LDIR_FstClusLO, 0); + + i = (ord - 1) * 13; /* Get offset in the LFN working buffer */ + s = wc = 0; + do + { + if (wc != 0xFFFF) wc = lfn[i++]; /* Get an effective character */ + st_word(dir + LfnOfs[s], wc); /* Put it */ + if (wc == 0) wc = 0xFFFF; /* Padding characters for left locations */ + } + while (++s < 13); + if (wc == 0xFFFF || !lfn[i]) ord |= LLEF; /* Last LFN part is the start of LFN sequence */ + dir[LDIR_Ord] = ord; /* Set the LFN order */ +} + +#endif /* !_FS_READONLY */ +#endif /* _USE_LFN != 0 */ + + + +#if _USE_LFN != 0 && !_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* FAT-LFN: Create a Numbered SFN */ +/*-----------------------------------------------------------------------*/ + +static +void gen_numname ( + BYTE *dst, /* Pointer to the buffer to store numbered SFN */ + const BYTE *src, /* Pointer to SFN */ + const WCHAR *lfn, /* Pointer to LFN */ + UINT seq /* Sequence number */ +) +{ + BYTE ns[8], c; + UINT i, j; + WCHAR wc; + DWORD sr; + + + memcpy(dst, src, 11); + + if (seq > 5) /* In case of many collisions, generate a hash number instead of sequential number */ + { + sr = seq; + while (*lfn) /* Create a CRC */ + { + wc = *lfn++; + for (i = 0; i < 16; i++) + { + sr = (sr << 1) + (wc & 1); + wc >>= 1; + if (sr & 0x10000) sr ^= 0x11021; + } + } + seq = (UINT)sr; + } + + /* itoa (hexdecimal) */ + i = 7; + do + { + c = (BYTE)((seq % 16) + '0'); + if (c > '9') c += 7; + ns[i--] = c; + seq /= 16; + } + while (seq); + ns[i] = '~'; + + /* Append the number */ + for (j = 0; j < i && dst[j] != ' '; j++) + { + if (IsDBCS1(dst[j])) + { + if (j == i - 1) break; + j++; + } + } + do + { + dst[j++] = (i < 8) ? ns[i++] : ' '; + } + while (j < 8); +} +#endif /* _USE_LFN != 0 && !_FS_READONLY */ + + + +#if _USE_LFN != 0 +/*-----------------------------------------------------------------------*/ +/* FAT-LFN: Calculate checksum of an SFN entry */ +/*-----------------------------------------------------------------------*/ + +static +BYTE sum_sfn ( + const BYTE *dir /* Pointer to the SFN entry */ +) +{ + BYTE sum = 0; + UINT n = 11; + + do + { + sum = (sum >> 1) + (sum << 7) + *dir++; + } + while (--n); + return sum; +} + +#endif /* _USE_LFN != 0 */ + + + +#if _FS_EXFAT +/*-----------------------------------------------------------------------*/ +/* exFAT: Checksum */ +/*-----------------------------------------------------------------------*/ + +static +WORD xdir_sum ( /* Get checksum of the directoly block */ + const BYTE *dir /* Directory entry block to be calculated */ +) +{ + UINT i, szblk; + WORD sum; + + + szblk = (dir[XDIR_NumSec] + 1) * SZDIRE; + for (i = sum = 0; i < szblk; i++) + { + if (i == XDIR_SetSum) /* Skip sum field */ + { + i++; + } + else + { + sum = ((sum & 1) ? 0x8000 : 0) + (sum >> 1) + dir[i]; + } + } + return sum; +} + + + +static +WORD xname_sum ( /* Get check sum (to be used as hash) of the name */ + const WCHAR *name /* File name to be calculated */ +) +{ + WCHAR chr; + WORD sum = 0; + + + while ((chr = *name++) != 0) + { + chr = ff_wtoupper(chr); /* File name needs to be ignored case */ + sum = ((sum & 1) ? 0x8000 : 0) + (sum >> 1) + (chr & 0xFF); + sum = ((sum & 1) ? 0x8000 : 0) + (sum >> 1) + (chr >> 8); + } + return sum; +} + + +#if !_FS_READONLY && _USE_MKFS +static +DWORD xsum32 ( + BYTE dat, /* Data to be sumed */ + DWORD sum /* Previous value */ +) +{ + sum = ((sum & 1) ? 0x80000000 : 0) + (sum >> 1) + dat; + return sum; +} +#endif + + +#if _FS_MINIMIZE <= 1 || _FS_RPATH >= 2 +/*------------------------------------------------------*/ +/* exFAT: Get object information from a directory block */ +/*------------------------------------------------------*/ + +static +void get_xdir_info ( + BYTE *dirb, /* Pointer to the direcotry entry block 85+C0+C1s */ + FILINFO *fno /* Buffer to store the extracted file information */ +) +{ + UINT di, si; + WCHAR w; +#if !_LFN_UNICODE + UINT nc; +#endif + + /* Get file name */ + di = 0; +#if _LFN_UNICODE + for (si = SZDIRE * 2; di < dirb[XDIR_NumName]; si += 2, di++) + { + if ((si % SZDIRE) == 0) si += 2; /* Skip entry type field */ + w = ld_word(dirb + si); /* Get a character */ + if (di >= _MAX_LFN) + { + di = 0; /* Buffer overflow --> inaccessible object name */ + break; + } + fno->fname[di] = w; /* Store it */ + } +#else + for (si = SZDIRE * 2, nc = 0; nc < dirb[XDIR_NumName]; si += 2, nc++) + { + if ((si % SZDIRE) == 0) si += 2; /* Skip entry type field */ + w = ff_convert(ld_word(dirb + si), 0); /* Get a character and Unicode -> OEM */ + if (_DF1S && w >= 0x100) /* Is it a double byte char? (always false at SBCS cfg) */ + { + fno->fname[di++] = (char)(w >> 8); /* Put 1st byte of the DBC */ + } + if (w == 0 || di >= _MAX_LFN) + { + di = 0; /* Invalid char or buffer overflow --> inaccessible object name */ + break; + } + fno->fname[di++] = (char)w; + } +#endif + if (di == 0) fno->fname[di++] = '?'; /* Inaccessible object name? */ + fno->fname[di] = 0; /* Terminate file name */ + + fno->altname[0] = 0; /* No SFN */ + fno->fattrib = dirb[XDIR_Attr]; /* Attribute */ + fno->fsize = (fno->fattrib & AM_DIR) ? 0 : ld_qword(dirb + XDIR_FileSize); /* Size */ + fno->ftime = ld_word(dirb + XDIR_ModTime + 0); /* Time */ + fno->fdate = ld_word(dirb + XDIR_ModTime + 2); /* Date */ +} + +#endif /* _FS_MINIMIZE <= 1 || _FS_RPATH >= 2 */ + + +/*-----------------------------------*/ +/* exFAT: Get a directry entry block */ +/*-----------------------------------*/ + +static +FRESULT load_xdir ( /* FR_INT_ERR: invalid entry block */ + DIR *dp /* Pointer to the reading direcotry object pointing the 85 entry */ +) +{ + FRESULT res; + UINT i, sz_ent; + BYTE *dirb = dp->obj.fs->dirbuf; /* Pointer to the on-memory direcotry entry block 85+C0+C1s */ + + + /* Load 85 entry */ + res = move_window(dp->obj.fs, dp->sect); + if (res != FR_OK) return res; + if (dp->dir[XDIR_Type] != 0x85) return FR_INT_ERR; + memcpy(dirb + 0, dp->dir, SZDIRE); + sz_ent = (dirb[XDIR_NumSec] + 1) * SZDIRE; + if (sz_ent < 3 * SZDIRE || sz_ent > 19 * SZDIRE) return FR_INT_ERR; + + /* Load C0 entry */ + res = dir_next(dp, 0); + if (res != FR_OK) return res; + res = move_window(dp->obj.fs, dp->sect); + if (res != FR_OK) return res; + if (dp->dir[XDIR_Type] != 0xC0) return FR_INT_ERR; + memcpy(dirb + SZDIRE, dp->dir, SZDIRE); + if (MAXDIRB(dirb[XDIR_NumName]) > sz_ent) return FR_INT_ERR; + + /* Load C1 entries */ + i = SZDIRE * 2; /* C1 offset */ + do + { + res = dir_next(dp, 0); + if (res != FR_OK) return res; + res = move_window(dp->obj.fs, dp->sect); + if (res != FR_OK) return res; + if (dp->dir[XDIR_Type] != 0xC1) return FR_INT_ERR; + if (i < MAXDIRB(_MAX_LFN)) memcpy(dirb + i, dp->dir, SZDIRE); + } + while ((i += SZDIRE) < sz_ent); + + /* Sanity check (do it when accessible object name) */ + if (i <= MAXDIRB(_MAX_LFN)) + { + if (xdir_sum(dirb) != ld_word(dirb + XDIR_SetSum)) return FR_INT_ERR; + } + return FR_OK; +} + + +#if !_FS_READONLY || _FS_RPATH != 0 +/*------------------------------------------------*/ +/* exFAT: Load the object's directory entry block */ +/*------------------------------------------------*/ +static +FRESULT load_obj_dir ( + DIR *dp, /* Blank directory object to be used to access containing direcotry */ + const _FDID *obj /* Object with its containing directory information */ +) +{ + FRESULT res; + + /* Open object containing directory */ + dp->obj.fs = obj->fs; + dp->obj.sclust = obj->c_scl; + dp->obj.stat = (BYTE)obj->c_size; + dp->obj.objsize = obj->c_size & 0xFFFFFF00; + dp->blk_ofs = obj->c_ofs; + + res = dir_sdi(dp, dp->blk_ofs); /* Goto object's entry block */ + if (res == FR_OK) + { + res = load_xdir(dp); /* Load the object's entry block */ + } + return res; +} +#endif + + +#if !_FS_READONLY +/*-----------------------------------------------*/ +/* exFAT: Store the directory block to the media */ +/*-----------------------------------------------*/ +static +FRESULT store_xdir ( + DIR *dp /* Pointer to the direcotry object */ +) +{ + FRESULT res; + UINT nent; + BYTE *dirb = dp->obj.fs->dirbuf; /* Pointer to the direcotry entry block 85+C0+C1s */ + + /* Create set sum */ + st_word(dirb + XDIR_SetSum, xdir_sum(dirb)); + nent = dirb[XDIR_NumSec] + 1; + + /* Store the set of directory to the volume */ + res = dir_sdi(dp, dp->blk_ofs); + while (res == FR_OK) + { + res = move_window(dp->obj.fs, dp->sect); + if (res != FR_OK) break; + memcpy(dp->dir, dirb, SZDIRE); + dp->obj.fs->wflag = 1; + if (--nent == 0) break; + dirb += SZDIRE; + res = dir_next(dp, 0); + } + return (res == FR_OK || res == FR_DISK_ERR) ? res : FR_INT_ERR; +} + + + +/*-------------------------------------------*/ +/* exFAT: Create a new directory enrty block */ +/*-------------------------------------------*/ + +static +void create_xdir ( + BYTE *dirb, /* Pointer to the direcotry entry block buffer */ + const WCHAR *lfn /* Pointer to the nul terminated file name */ +) +{ + UINT i; + BYTE nb, nc; + WCHAR chr; + + + /* Create 85+C0 entry */ + memset(dirb, 0, 2 * SZDIRE); + dirb[XDIR_Type] = 0x85; + dirb[XDIR_Type + SZDIRE] = 0xC0; + + /* Create C1 entries */ + nc = 0; + nb = 1; + chr = 1; + i = SZDIRE * 2; + do + { + dirb[i++] = 0xC1; + dirb[i++] = 0; /* Entry type C1 */ + do /* Fill name field */ + { + if (chr && (chr = lfn[nc]) != 0) nc++; /* Get a character if exist */ + st_word(dirb + i, chr); /* Store it */ + } + while ((i += 2) % SZDIRE != 0); + nb++; + } + while (lfn[nc]); /* Fill next entry if any char follows */ + + dirb[XDIR_NumName] = nc; /* Set name length */ + dirb[XDIR_NumSec] = nb; /* Set block length */ + st_word(dirb + XDIR_NameHash, xname_sum(lfn)); /* Set name hash */ +} + +#endif /* !_FS_READONLY */ +#endif /* _FS_EXFAT */ + + + +#if _FS_MINIMIZE <= 1 || _FS_RPATH >= 2 || _USE_LABEL || _FS_EXFAT +/*-----------------------------------------------------------------------*/ +/* Read an object from the directory */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT dir_read ( + DIR *dp, /* Pointer to the directory object */ + int vol /* Filtered by 0:file/directory or 1:volume label */ +) +{ + FRESULT res = FR_NO_FILE; + FATFS *fs = dp->obj.fs; + BYTE a, c; +#if _USE_LFN != 0 + BYTE ord = 0xFF, sum = 0xFF; +#endif + + while (dp->sect) + { + res = move_window(fs, dp->sect); + if (res != FR_OK) break; + c = dp->dir[DIR_Name]; /* Test for the entry type */ + if (c == 0) + { + res = FR_NO_FILE; + break; /* Reached to end of the directory */ + } +#if _FS_EXFAT + if (fs->fs_type == FS_EXFAT) /* On the exFAT volume */ + { + if (_USE_LABEL && vol) + { + if (c == 0x83) break; /* Volume label entry? */ + } + else + { + if (c == 0x85) /* Start of the file entry block? */ + { + dp->blk_ofs = dp->dptr; /* Get location of the block */ + res = load_xdir(dp); /* Load the entry block */ + if (res == FR_OK) + { + dp->obj.attr = fs->dirbuf[XDIR_Attr] & AM_MASK; /* Get attribute */ + } + break; + } + } + } + else +#endif + { + /* On the FAT12/16/32 volume */ + dp->obj.attr = a = dp->dir[DIR_Attr] & AM_MASK; /* Get attribute */ +#if _USE_LFN != 0 /* LFN configuration */ + if (c == DDEM || c == '.' || (int)((a & ~AM_ARC) == AM_VOL) != vol) /* An entry without valid data */ + { + ord = 0xFF; + } + else + { + if (a == AM_LFN) /* An LFN entry is found */ + { + if (c & LLEF) /* Is it start of an LFN sequence? */ + { + sum = dp->dir[LDIR_Chksum]; + c &= (BYTE)~LLEF; + ord = c; + dp->blk_ofs = dp->dptr; + } + /* Check LFN validity and capture it */ + ord = (c == ord && sum == dp->dir[LDIR_Chksum] && pick_lfn(fs->lfnbuf, dp->dir)) ? ord - 1 : 0xFF; + } + else /* An SFN entry is found */ + { + if (ord || sum != sum_sfn(dp->dir)) /* Is there a valid LFN? */ + { + dp->blk_ofs = 0xFFFFFFFF; /* It has no LFN. */ + } + break; + } + } +#else /* Non LFN configuration */ + if (c != DDEM && c != '.' && a != AM_LFN && (int)((a & ~AM_ARC) == AM_VOL) == vol) /* Is it a valid entry? */ + { + break; + } +#endif + } + res = dir_next(dp, 0); /* Next entry */ + if (res != FR_OK) break; + } + + if (res != FR_OK) dp->sect = 0; /* Terminate the read operation on error or EOT */ + return res; +} + +#endif /* _FS_MINIMIZE <= 1 || _USE_LABEL || _FS_RPATH >= 2 */ + + + +/*-----------------------------------------------------------------------*/ +/* Directory handling - Find an object in the directory */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT dir_find ( /* FR_OK(0):succeeded, !=0:error */ + DIR *dp /* Pointer to the directory object with the file name */ +) +{ + FRESULT res; + FATFS *fs = dp->obj.fs; + BYTE c; +#if _USE_LFN != 0 + BYTE a, ord, sum; +#endif + + res = dir_sdi(dp, 0); /* Rewind directory object */ + if (res != FR_OK) return res; +#if _FS_EXFAT + if (fs->fs_type == FS_EXFAT) /* On the exFAT volume */ + { + BYTE nc; + UINT di, ni; + WORD hash = xname_sum(fs->lfnbuf); /* Hash value of the name to find */ + + while ((res = dir_read(dp, 0)) == FR_OK) /* Read an item */ + { +#if _MAX_LFN < 255 + if (fs->dirbuf[XDIR_NumName] > _MAX_LFN) continue; /* Skip comparison if inaccessible object name */ +#endif + if (ld_word(fs->dirbuf + XDIR_NameHash) != hash) continue; /* Skip comparison if hash mismatched */ + for (nc = fs->dirbuf[XDIR_NumName], di = SZDIRE * 2, ni = 0; nc; nc--, di += 2, ni++) /* Compare the name */ + { + if ((di % SZDIRE) == 0) di += 2; + if (ff_wtoupper(ld_word(fs->dirbuf + di)) != ff_wtoupper(fs->lfnbuf[ni])) break; + } + if (nc == 0 && !fs->lfnbuf[ni]) break; /* Name matched? */ + } + return res; + } +#endif + /* On the FAT12/16/32 volume */ +#if _USE_LFN != 0 + ord = sum = 0xFF; + dp->blk_ofs = 0xFFFFFFFF; /* Reset LFN sequence */ +#endif + do + { + res = move_window(fs, dp->sect); + if (res != FR_OK) break; + c = dp->dir[DIR_Name]; + if (c == 0) + { + res = FR_NO_FILE; /* Reached to end of table */ + break; + } +#if _USE_LFN != 0 /* LFN configuration */ + dp->obj.attr = a = dp->dir[DIR_Attr] & AM_MASK; + if (c == DDEM || ((a & AM_VOL) && a != AM_LFN)) /* An entry without valid data */ + { + ord = 0xFF; + dp->blk_ofs = 0xFFFFFFFF; /* Reset LFN sequence */ + } + else + { + if (a == AM_LFN) /* An LFN entry is found */ + { + if (!(dp->fn[NSFLAG] & NS_NOLFN)) + { + if (c & LLEF) /* Is it start of LFN sequence? */ + { + sum = dp->dir[LDIR_Chksum]; + c &= (BYTE)~LLEF; + ord = c; /* LFN start order */ + dp->blk_ofs = dp->dptr; /* Start offset of LFN */ + } + /* Check validity of the LFN entry and compare it with given name */ + ord = (c == ord && sum == dp->dir[LDIR_Chksum] && cmp_lfn(fs->lfnbuf, dp->dir)) ? ord - 1 : 0xFF; + } + } + else /* An SFN entry is found */ + { + if (!ord && sum == sum_sfn(dp->dir)) break; /* LFN matched? */ + if (!(dp->fn[NSFLAG] & NS_LOSS) && !memcmp(dp->dir, dp->fn, 11)) break; /* SFN matched? */ + ord = 0xFF; + dp->blk_ofs = 0xFFFFFFFF; /* Reset LFN sequence */ + } + } +#else /* Non LFN configuration */ + dp->obj.attr = dp->dir[DIR_Attr] & AM_MASK; + if (!(dp->dir[DIR_Attr] & AM_VOL) && !memcmp(dp->dir, dp->fn, 11)) break; /* Is it a valid entry? */ +#endif + res = dir_next(dp, 0); /* Next entry */ + } + while (res == FR_OK); + + return res; +} + + + + +#if !_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Register an object to the directory */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT dir_register ( /* FR_OK:succeeded, FR_DENIED:no free entry or too many SFN collision, FR_DISK_ERR:disk error */ + DIR *dp /* Target directory with object name to be created */ +) +{ + FRESULT res; + FATFS *fs = dp->obj.fs; +#if _USE_LFN != 0 /* LFN configuration */ + UINT n, nlen, nent; + BYTE sn[12], sum; + + + if (dp->fn[NSFLAG] & (NS_DOT | NS_NONAME)) return FR_INVALID_NAME; /* Check name validity */ + for (nlen = 0; fs->lfnbuf[nlen]; nlen++) ; /* Get lfn length */ + +#if _FS_EXFAT + if (fs->fs_type == FS_EXFAT) /* On the exFAT volume */ + { + DIR dj; + + nent = (nlen + 14) / 15 + 2; /* Number of entries to allocate (85+C0+C1s) */ + res = dir_alloc(dp, nent); /* Allocate entries */ + if (res != FR_OK) return res; + dp->blk_ofs = dp->dptr - SZDIRE * (nent - 1); /* Set the allocated entry block offset */ + + if (dp->obj.sclust != 0 && (dp->obj.stat & 4)) /* Has the sub-directory been stretched? */ + { + dp->obj.objsize += (DWORD)fs->csize * SS(fs); /* Increase the directory size by cluster size */ + res = fill_first_frag(&dp->obj); /* Fill first fragment on the FAT if needed */ + if (res != FR_OK) return res; + res = fill_last_frag(&dp->obj, dp->clust, 0xFFFFFFFF); /* Fill last fragment on the FAT if needed */ + if (res != FR_OK) return res; + res = load_obj_dir(&dj, &dp->obj); /* Load the object status */ + if (res != FR_OK) return res; + st_qword(fs->dirbuf + XDIR_FileSize, dp->obj.objsize); /* Update the allocation status */ + st_qword(fs->dirbuf + XDIR_ValidFileSize, dp->obj.objsize); + fs->dirbuf[XDIR_GenFlags] = dp->obj.stat | 1; + res = store_xdir(&dj); /* Store the object status */ + if (res != FR_OK) return res; + } + + create_xdir(fs->dirbuf, fs->lfnbuf); /* Create on-memory directory block to be written later */ + return FR_OK; + } +#endif + /* On the FAT12/16/32 volume */ + memcpy(sn, dp->fn, 12); + if (sn[NSFLAG] & NS_LOSS) /* When LFN is out of 8.3 format, generate a numbered name */ + { + dp->fn[NSFLAG] = NS_NOLFN; /* Find only SFN */ + for (n = 1; n < 100; n++) + { + gen_numname(dp->fn, sn, fs->lfnbuf, n); /* Generate a numbered name */ + res = dir_find(dp); /* Check if the name collides with existing SFN */ + if (res != FR_OK) break; + } + if (n == 100) return FR_DENIED; /* Abort if too many collisions */ + if (res != FR_NO_FILE) return res; /* Abort if the result is other than 'not collided' */ + dp->fn[NSFLAG] = sn[NSFLAG]; + } + + /* Create an SFN with/without LFNs. */ + nent = (sn[NSFLAG] & NS_LFN) ? (nlen + 12) / 13 + 1 : 1; /* Number of entries to allocate */ + res = dir_alloc(dp, nent); /* Allocate entries */ + if (res == FR_OK && --nent) /* Set LFN entry if needed */ + { + res = dir_sdi(dp, dp->dptr - nent * SZDIRE); + if (res == FR_OK) + { + sum = sum_sfn(dp->fn); /* Checksum value of the SFN tied to the LFN */ + do /* Store LFN entries in bottom first */ + { + res = move_window(fs, dp->sect); + if (res != FR_OK) break; + put_lfn(fs->lfnbuf, dp->dir, (BYTE)nent, sum); + fs->wflag = 1; + res = dir_next(dp, 0); /* Next entry */ + } + while (res == FR_OK && --nent); + } + } + +#else /* Non LFN configuration */ + res = dir_alloc(dp, 1); /* Allocate an entry for SFN */ + +#endif + + /* Set SFN entry */ + if (res == FR_OK) + { + res = move_window(fs, dp->sect); + if (res == FR_OK) + { + memset(dp->dir, 0, SZDIRE); /* Clean the entry */ + memcpy(dp->dir + DIR_Name, dp->fn, 11); /* Put SFN */ +#if _USE_LFN != 0 + dp->dir[DIR_NTres] = dp->fn[NSFLAG] & (NS_BODY | NS_EXT); /* Put NT flag */ +#endif + fs->wflag = 1; + } + } + + return res; +} + +#endif /* !_FS_READONLY */ + + + +#if !_FS_READONLY && _FS_MINIMIZE == 0 +/*-----------------------------------------------------------------------*/ +/* Remove an object from the directory */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT dir_remove ( /* FR_OK:Succeeded, FR_DISK_ERR:A disk error */ + DIR *dp /* Directory object pointing the entry to be removed */ +) +{ + FRESULT res; + FATFS *fs = dp->obj.fs; +#if _USE_LFN != 0 /* LFN configuration */ + DWORD last = dp->dptr; + + res = (dp->blk_ofs == 0xFFFFFFFF) ? FR_OK : dir_sdi(dp, dp->blk_ofs); /* Goto top of the entry block if LFN is exist */ + if (res == FR_OK) + { + do + { + res = move_window(fs, dp->sect); + if (res != FR_OK) break; + /* Mark an entry 'deleted' */ + if (_FS_EXFAT && fs->fs_type == FS_EXFAT) /* On the exFAT volume */ + { + dp->dir[XDIR_Type] &= 0x7F; + } + else /* On the FAT12/16/32 volume */ + { + dp->dir[DIR_Name] = DDEM; + } + fs->wflag = 1; + if (dp->dptr >= last) break; /* If reached last entry then all entries of the object has been deleted. */ + res = dir_next(dp, 0); /* Next entry */ + } + while (res == FR_OK); + if (res == FR_NO_FILE) res = FR_INT_ERR; + } +#else /* Non LFN configuration */ + + res = move_window(fs, dp->sect); + if (res == FR_OK) + { + dp->dir[DIR_Name] = DDEM; + fs->wflag = 1; + } +#endif + + return res; +} + +#endif /* !_FS_READONLY && _FS_MINIMIZE == 0 */ + + + +#if _FS_MINIMIZE <= 1 || _FS_RPATH >= 2 +/*-----------------------------------------------------------------------*/ +/* Get file information from directory entry */ +/*-----------------------------------------------------------------------*/ + +static +void get_fileinfo ( /* No return code */ + DIR *dp, /* Pointer to the directory object */ + FILINFO *fno /* Pointer to the file information to be filled */ +) +{ + UINT i, j; + TCHAR c; + DWORD tm; +#if _USE_LFN != 0 + WCHAR w, lfv; + FATFS *fs = dp->obj.fs; +#endif + + + fno->fname[0] = 0; /* Invaidate file info */ + if (!dp->sect) return; /* Exit if read pointer has reached end of directory */ + +#if _USE_LFN != 0 /* LFN configuration */ +#if _FS_EXFAT + if (fs->fs_type == FS_EXFAT) /* On the exFAT volume */ + { + get_xdir_info(fs->dirbuf, fno); + return; + } + else +#endif + { + /* On the FAT12/16/32 volume */ + if (dp->blk_ofs != 0xFFFFFFFF) /* Get LFN if available */ + { + i = j = 0; + while ((w = fs->lfnbuf[j++]) != 0) /* Get an LFN character */ + { +#if !_LFN_UNICODE + w = ff_convert(w, 0); /* Unicode -> OEM */ + if (w == 0) + { + i = 0; /* No LFN if it could not be converted */ + break; + } + if (_DF1S && w >= 0x100) /* Put 1st byte if it is a DBC (always false at SBCS cfg) */ + { + fno->fname[i++] = (char)(w >> 8); + } +#endif + if (i >= _MAX_LFN) + { + i = 0; /* No LFN if buffer overflow */ + break; + } + fno->fname[i++] = (TCHAR)w; + } + fno->fname[i] = 0; /* Terminate the LFN */ + } + } + + i = j = 0; + lfv = fno->fname[i]; /* LFN is exist if non-zero */ + while (i < 11) /* Copy name body and extension */ + { + c = (TCHAR)dp->dir[i++]; + if (c == ' ') continue; /* Skip padding spaces */ + if (c == RDDEM) c = (TCHAR)DDEM; /* Restore replaced DDEM character */ + if (i == 9) /* Insert a . if extension is exist */ + { + if (!lfv) fno->fname[j] = '.'; + fno->altname[j++] = '.'; + } +#if _LFN_UNICODE + if (IsDBCS1(c) && i != 8 && i != 11 && IsDBCS2(dp->dir[i])) + { + c = c << 8 | dp->dir[i++]; + } + c = ff_convert(c, 1); /* OEM -> Unicode */ + if (!c) c = '?'; +#endif + fno->altname[j] = c; + if (!lfv) + { + if (IsUpper(c) && (dp->dir[DIR_NTres] & ((i >= 9) ? NS_EXT : NS_BODY))) + { + c += 0x20; /* To lower */ + } + fno->fname[j] = c; + } + j++; + } + if (!lfv) + { + fno->fname[j] = 0; + if (!dp->dir[DIR_NTres]) j = 0; /* Altname is no longer needed if neither LFN nor case info is exist. */ + } + fno->altname[j] = 0; /* Terminate the SFN */ + +#else /* Non-LFN configuration */ + i = j = 0; + while (i < 11) /* Copy name body and extension */ + { + c = (TCHAR)dp->dir[i++]; + if (c == ' ') continue; /* Skip padding spaces */ + if (c == RDDEM) c = (TCHAR)DDEM; /* Restore replaced DDEM character */ + if (i == 9) fno->fname[j++] = '.'; /* Insert a . if extension is exist */ + fno->fname[j++] = c; + } + fno->fname[j] = 0; +#endif + + fno->fattrib = dp->dir[DIR_Attr]; /* Attribute */ + fno->fsize = ld_dword(dp->dir + DIR_FileSize); /* Size */ + tm = ld_dword(dp->dir + DIR_ModTime); /* Timestamp */ + fno->ftime = (WORD)tm; + fno->fdate = (WORD)(tm >> 16); +} + +#endif /* _FS_MINIMIZE <= 1 || _FS_RPATH >= 2 */ + + + +#if _USE_FIND && _FS_MINIMIZE <= 1 +/*-----------------------------------------------------------------------*/ +/* Pattern matching */ +/*-----------------------------------------------------------------------*/ + +static +WCHAR get_achar ( /* Get a character and advances ptr 1 or 2 */ + const TCHAR **ptr /* Pointer to pointer to the SBCS/DBCS/Unicode string */ +) +{ +#if !_LFN_UNICODE + WCHAR chr; + + chr = (BYTE) * (*ptr)++; /* Get a byte */ + if (IsLower(chr)) chr -= 0x20; /* To upper ASCII char */ +#ifdef _EXCVT + if (chr >= 0x80) chr = ExCvt[chr - 0x80]; /* To upper SBCS extended char */ +#else + if (IsDBCS1(chr) && IsDBCS2(**ptr)) /* Get DBC 2nd byte if needed */ + { + chr = chr << 8 | (BYTE) * (*ptr)++; + } +#endif + return chr; +#else + return ff_wtoupper(*(*ptr)++); /* Get a word and to upper */ +#endif +} + + +static +int pattern_matching ( /* 0:not matched, 1:matched */ + const TCHAR *pat, /* Matching pattern */ + const TCHAR *nam, /* String to be tested */ + int skip, /* Number of pre-skip chars (number of ?s) */ + int inf /* Infinite search (* specified) */ +) +{ + const TCHAR *pp, *np; + WCHAR pc, nc; + int nm, nx; + + + while (skip--) /* Pre-skip name chars */ + { + if (!get_achar(&nam)) return 0; /* Branch mismatched if less name chars */ + } + if (!*pat && inf) return 1; /* (short circuit) */ + + do + { + pp = pat; + np = nam; /* Top of pattern and name to match */ + for (;;) + { + if (*pp == '?' || *pp == '*') /* Wildcard? */ + { + nm = nx = 0; + do /* Analyze the wildcard chars */ + { + if (*pp++ == '?') nm++; + else nx = 1; + } + while (*pp == '?' || *pp == '*'); + if (pattern_matching(pp, np, nm, nx)) return 1; /* Test new branch (recurs upto number of wildcard blocks in the pattern) */ + nc = *np; + break; /* Branch mismatched */ + } + pc = get_achar(&pp); /* Get a pattern char */ + nc = get_achar(&np); /* Get a name char */ + if (pc != nc) break; /* Branch mismatched? */ + if (pc == 0) return 1; /* Branch matched? (matched at end of both strings) */ + } + get_achar(&nam); /* nam++ */ + } + while (inf && nc); /* Retry until end of name if infinite search is specified */ + + return 0; +} + +#endif /* _USE_FIND && _FS_MINIMIZE <= 1 */ + + + +/*-----------------------------------------------------------------------*/ +/* Pick a top segment and create the object name in directory form */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT create_name ( /* FR_OK: successful, FR_INVALID_NAME: could not create */ + DIR *dp, /* Pointer to the directory object */ + const TCHAR **path /* Pointer to pointer to the segment in the path string */ +) +{ +#if _USE_LFN != 0 /* LFN configuration */ + BYTE b, cf; + WCHAR w, *lfn; + UINT i, ni, si, di; + const TCHAR *p; + + /* Create LFN in Unicode */ + p = *path; + lfn = dp->obj.fs->lfnbuf; + si = di = 0; + for (;;) + { + w = p[si++]; /* Get a character */ + if (w < ' ') break; /* Break if end of the path name */ + if (w == '/' || w == '\\') /* Break if a separator is found */ + { + while (p[si] == '/' || p[si] == '\\') si++; /* Skip duplicated separator if exist */ + break; + } + if (di >= _MAX_LFN) return FR_INVALID_NAME; /* Reject too long name */ +#if !_LFN_UNICODE + w &= 0xFF; + if (IsDBCS1(w)) /* Check if it is a DBC 1st byte (always false on SBCS cfg) */ + { + b = (BYTE)p[si++]; /* Get 2nd byte */ + w = (w << 8) + b; /* Create a DBC */ + if (!IsDBCS2(b)) return FR_INVALID_NAME; /* Reject invalid sequence */ + } + w = ff_convert(w, 1); /* Convert ANSI/OEM to Unicode */ + if (!w) return FR_INVALID_NAME; /* Reject invalid code */ +#endif + if (w < 0x80 && chk_chr("\"*:<>\?|\x7F", w)) return FR_INVALID_NAME; /* Reject illegal characters for LFN */ + lfn[di++] = w; /* Store the Unicode character */ + } + *path = &p[si]; /* Return pointer to the next segment */ + cf = (w < ' ') ? NS_LAST : 0; /* Set last segment flag if end of the path */ +#if _FS_RPATH != 0 + if ((di == 1 && lfn[di - 1] == '.') || + (di == 2 && lfn[di - 1] == '.' && lfn[di - 2] == '.')) /* Is this segment a dot name? */ + { + lfn[di] = 0; + for (i = 0; i < 11; i++) /* Create dot name for SFN entry */ + dp->fn[i] = (i < di) ? '.' : ' '; + dp->fn[i] = cf | NS_DOT; /* This is a dot entry */ + return FR_OK; + } +#endif + while (di) /* Snip off trailing spaces and dots if exist */ + { + w = lfn[di - 1]; + if (w != ' ' && w != '.') break; + di--; + } + lfn[di] = 0; /* LFN is created */ + if (di == 0) return FR_INVALID_NAME; /* Reject nul name */ + + /* Create SFN in directory form */ + memset(dp->fn, ' ', 11); + for (si = 0; lfn[si] == ' ' || lfn[si] == '.'; si++) ; /* Strip leading spaces and dots */ + if (si) cf |= NS_LOSS | NS_LFN; + while (di && lfn[di - 1] != '.') di--; /* Find extension (di<=si: no extension) */ + + i = b = 0; + ni = 8; + for (;;) + { + w = lfn[si++]; /* Get an LFN character */ + if (!w) break; /* Break on end of the LFN */ + if (w == ' ' || (w == '.' && si != di)) /* Remove spaces and dots */ + { + cf |= NS_LOSS | NS_LFN; + continue; + } + + if (i >= ni || si == di) /* Extension or end of SFN */ + { + if (ni == 11) /* Long extension */ + { + cf |= NS_LOSS | NS_LFN; + break; + } + if (si != di) cf |= NS_LOSS | NS_LFN; /* Out of 8.3 format */ + if (si > di) break; /* No extension */ + si = di; + i = 8; + ni = 11; /* Enter extension section */ + b <<= 2; + continue; + } + + if (w >= 0x80) /* Non ASCII character */ + { +#ifdef _EXCVT + w = ff_convert(w, 0); /* Unicode -> OEM code */ + if (w) w = ExCvt[w - 0x80]; /* Convert extended character to upper (SBCS) */ +#else + w = ff_convert(ff_wtoupper(w), 0); /* Upper converted Unicode -> OEM code */ +#endif + cf |= NS_LFN; /* Force create LFN entry */ + } + + if (_DF1S && w >= 0x100) /* Is this DBC? (always false at SBCS cfg) */ + { + if (i >= ni - 1) + { + cf |= NS_LOSS | NS_LFN; + i = ni; + continue; + } + dp->fn[i++] = (BYTE)(w >> 8); + } + else /* SBC */ + { + if (!w || chk_chr("+,;=[]", w)) /* Replace illegal characters for SFN */ + { + w = '_'; + cf |= NS_LOSS | NS_LFN;/* Lossy conversion */ + } + else + { + if (IsUpper(w)) /* ASCII large capital */ + { + b |= 2; + } + else + { + if (IsLower(w)) /* ASCII small capital */ + { + b |= 1; + w -= 0x20; + } + } + } + } + dp->fn[i++] = (BYTE)w; + } + + if (dp->fn[0] == DDEM) dp->fn[0] = RDDEM; /* If the first character collides with DDEM, replace it with RDDEM */ + + if (ni == 8) b <<= 2; + if ((b & 0x0C) == 0x0C || (b & 0x03) == 0x03) cf |= NS_LFN; /* Create LFN entry when there are composite capitals */ + if (!(cf & NS_LFN)) /* When LFN is in 8.3 format without extended character, NT flags are created */ + { + if ((b & 0x03) == 0x01) cf |= NS_EXT; /* NT flag (Extension has only small capital) */ + if ((b & 0x0C) == 0x04) cf |= NS_BODY; /* NT flag (Filename has only small capital) */ + } + + dp->fn[NSFLAG] = cf; /* SFN is created */ + + return FR_OK; + + +#else /* _USE_LFN != 0 : Non-LFN configuration */ + BYTE c, d, *sfn; + UINT ni, si, i; + const char *p; + + /* Create file name in directory form */ + p = *path; + sfn = dp->fn; + memset(sfn, ' ', 11); + si = i = 0; + ni = 8; +#if _FS_RPATH != 0 + if (p[si] == '.') /* Is this a dot entry? */ + { + for (;;) + { + c = (BYTE)p[si++]; + if (c != '.' || si >= 3) break; + sfn[i++] = c; + } + if (c != '/' && c != '\\' && c > ' ') return FR_INVALID_NAME; + *path = p + si; /* Return pointer to the next segment */ + sfn[NSFLAG] = (c <= ' ') ? NS_LAST | NS_DOT : NS_DOT; /* Set last segment flag if end of the path */ + return FR_OK; + } +#endif + for (;;) + { + c = (BYTE)p[si++]; + if (c <= ' ') break; /* Break if end of the path name */ + if (c == '/' || c == '\\') /* Break if a separator is found */ + { + while (p[si] == '/' || p[si] == '\\') si++; /* Skip duplicated separator if exist */ + break; + } + if (c == '.' || i >= ni) /* End of body or over size? */ + { + if (ni == 11 || c != '.') return FR_INVALID_NAME; /* Over size or invalid dot */ + i = 8; + ni = 11; /* Goto extension */ + continue; + } + if (c >= 0x80) /* Extended character? */ + { +#ifdef _EXCVT + c = ExCvt[c - 0x80]; /* To upper extended characters (SBCS cfg) */ +#else +#if !_DF1S + return FR_INVALID_NAME; /* Reject extended characters (ASCII only cfg) */ +#endif +#endif + } + if (IsDBCS1(c)) /* Check if it is a DBC 1st byte (always false at SBCS cfg.) */ + { + d = (BYTE)p[si++]; /* Get 2nd byte */ + if (!IsDBCS2(d) || i >= ni - 1) return FR_INVALID_NAME; /* Reject invalid DBC */ + sfn[i++] = c; + sfn[i++] = d; + } + else /* SBC */ + { + if (chk_chr("\"*+,:;<=>\?[]|\x7F", c)) return FR_INVALID_NAME; /* Reject illegal chrs for SFN */ + if (IsLower(c)) c -= 0x20; /* To upper */ + sfn[i++] = c; + } + } + *path = p + si; /* Return pointer to the next segment */ + if (i == 0) return FR_INVALID_NAME; /* Reject nul string */ + + if (sfn[0] == DDEM) sfn[0] = RDDEM; /* If the first character collides with DDEM, replace it with RDDEM */ + sfn[NSFLAG] = (c <= ' ') ? NS_LAST : 0; /* Set last segment flag if end of the path */ + + return FR_OK; +#endif /* _USE_LFN != 0 */ +} + + + + +/*-----------------------------------------------------------------------*/ +/* Follow a file path */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */ + DIR *dp, /* Directory object to return last directory and found object */ + const TCHAR *path /* Full-path string to find a file or directory */ +) +{ + FRESULT res; + BYTE ns; + _FDID *obj = &dp->obj; + FATFS *fs = obj->fs; + + +#if _FS_RPATH != 0 + if (*path != '/' && *path != '\\') /* Without heading separator */ + { + obj->sclust = fs->cdir; /* Start from current directory */ + } + else +#endif + { + /* With heading separator */ + while (*path == '/' || *path == '\\') path++; /* Strip heading separator */ + obj->sclust = 0; /* Start from root directory */ + } +#if _FS_EXFAT + obj->n_frag = 0; /* Invalidate last fragment counter of the object */ +#if _FS_RPATH != 0 + if (fs->fs_type == FS_EXFAT && obj->sclust) /* Retrieve the sub-directory status if needed */ + { + DIR dj; + + obj->c_scl = fs->cdc_scl; + obj->c_size = fs->cdc_size; + obj->c_ofs = fs->cdc_ofs; + res = load_obj_dir(&dj, obj); + if (res != FR_OK) return res; + obj->objsize = ld_dword(fs->dirbuf + XDIR_FileSize); + obj->stat = fs->dirbuf[XDIR_GenFlags] & 2; + } +#endif +#endif + + if ((UINT)*path < ' ') /* Null path name is the origin directory itself */ + { + dp->fn[NSFLAG] = NS_NONAME; + res = dir_sdi(dp, 0); + + } + else /* Follow path */ + { + for (;;) + { + res = create_name(dp, &path); /* Get a segment name of the path */ + if (res != FR_OK) break; + res = dir_find(dp); /* Find an object with the segment name */ + ns = dp->fn[NSFLAG]; + if (res != FR_OK) /* Failed to find the object */ + { + if (res == FR_NO_FILE) /* Object is not found */ + { + if (_FS_RPATH && (ns & NS_DOT)) /* If dot entry is not exist, stay there */ + { + if (!(ns & NS_LAST)) continue; /* Continue to follow if not last segment */ + dp->fn[NSFLAG] = NS_NONAME; + res = FR_OK; + } + else /* Could not find the object */ + { + if (!(ns & NS_LAST)) res = FR_NO_PATH; /* Adjust error code if not last segment */ + } + } + break; + } + if (ns & NS_LAST) break; /* Last segment matched. Function completed. */ + /* Get into the sub-directory */ + if (!(obj->attr & AM_DIR)) /* It is not a sub-directory and cannot follow */ + { + res = FR_NO_PATH; + break; + } +#if _FS_EXFAT + if (fs->fs_type == FS_EXFAT) /* Save containing directory information for next dir */ + { + obj->c_scl = obj->sclust; + obj->c_size = ((DWORD)obj->objsize & 0xFFFFFF00) | obj->stat; + obj->c_ofs = dp->blk_ofs; + obj->sclust = ld_dword(fs->dirbuf + XDIR_FstClus); /* Open next directory */ + obj->stat = fs->dirbuf[XDIR_GenFlags] & 2; + obj->objsize = ld_qword(fs->dirbuf + XDIR_FileSize); + } + else +#endif + { + obj->sclust = ld_clust(fs, fs->win + dp->dptr % SS(fs)); /* Open next directory */ + } + } + } + + return res; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Get logical drive number from path name */ +/*-----------------------------------------------------------------------*/ + +static +int get_ldnumber ( /* Returns logical drive number (-1:invalid drive) */ + const TCHAR **path /* Pointer to pointer to the path name */ +) +{ + const TCHAR *tp, *tt; + UINT i; + int vol = -1; +#if _STR_VOLUME_ID /* Find string drive id */ + static const char *const volid[] = {_VOLUME_STRS}; + const char *sp; + char c; + TCHAR tc; +#endif + + + if (*path) /* If the pointer is not a null */ + { + for (tt = *path; ((UINT)*tt >= (_USE_LFN ? ' ' : '!')) && (*tt != ':'); tt++) ; /* Find ':' in the path */ + if (*tt == ':') /* If a ':' is exist in the path name */ + { + tp = *path; + i = *tp++ - '0'; + if (i < 10 && tp == tt) /* Is there a numeric drive id? */ + { + if (i < _VOLUMES) /* If a drive id is found, get the value and strip it */ + { + vol = (int)i; + *path = ++tt; + } + } +#if _STR_VOLUME_ID + else /* No numeric drive number, find string drive id */ + { + i = 0; + tt++; + do + { + sp = volid[i]; + tp = *path; + do /* Compare a string drive id with path name */ + { + c = *sp++; + tc = *tp++; + if (IsLower(tc)) tc -= 0x20; + } + while (c && (TCHAR)c == tc); + } + while ((c || tp != tt) && ++i < _VOLUMES); /* Repeat for each id until pattern match */ + if (i < _VOLUMES) /* If a drive id is found, get the value and strip it */ + { + vol = (int)i; + *path = tt; + } + } +#endif + return vol; + } +#if _FS_RPATH != 0 && _VOLUMES >= 2 + vol = CurrVol; /* Current drive */ +#else + vol = 0; /* Drive 0 */ +#endif + } + return vol; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Load a sector and check if it is an FAT boot sector */ +/*-----------------------------------------------------------------------*/ + +static +BYTE check_fs ( /* 0:FAT, 1:exFAT, 2:Valid BS but not FAT, 3:Not a BS, 4:Disk error */ + FATFS *fs, /* File system object */ + DWORD sect /* Sector# (lba) to load and check if it is an FAT-VBR or not */ +) +{ + fs->wflag = 0; + fs->winsect = 0xFFFFFFFF; /* Invaidate window */ + if (move_window(fs, sect) != FR_OK) return 4; /* Load boot record */ + + if (ld_word(fs->win + BS_55AA) != 0xAA55) return 3; /* Check boot record signature (always placed here even if the sector size is >512) */ + + if (fs->win[BS_JmpBoot] == 0xE9 || (fs->win[BS_JmpBoot] == 0xEB && fs->win[BS_JmpBoot + 2] == 0x90)) + { + if ((ld_dword(fs->win + BS_FilSysType) & 0xFFFFFF) == 0x544146) return 0; /* Check "FAT" string */ + if (ld_dword(fs->win + BS_FilSysType32) == 0x33544146) return 0; /* Check "FAT3" string */ + } +#if _FS_EXFAT + if (!memcmp(fs->win + BS_JmpBoot, "\xEB\x76\x90" "EXFAT ", 11)) return 1; +#endif + return 2; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Find logical drive and check if the volume is mounted */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT find_volume ( /* FR_OK(0): successful, !=0: any error occurred */ + const TCHAR **path, /* Pointer to pointer to the path name (drive number) */ + FATFS **rfs, /* Pointer to pointer to the found file system object */ + BYTE mode /* !=0: Check write protection for write access */ +) +{ + BYTE fmt, *pt; + int vol; + DSTATUS stat; + DWORD bsect, fasize, tsect, sysect, nclst, szbfat, br[4]; + WORD nrsv; + FATFS *fs; + UINT i; + + FAT_PRT("find_volume\r\n"); + + /* Get logical drive number */ + *rfs = 0; + vol = get_ldnumber(path); + if (vol < 0) return FR_INVALID_DRIVE; + + /* Check if the file system object is valid or not */ + fs = FatFs[vol]; /* Get pointer to the file system object */ + if (!fs) return FR_NOT_ENABLED; /* Is the file system object available? */ + + ENTER_FF(fs); /* Lock the volume */ + *rfs = fs; /* Return pointer to the file system object */ + + mode &= (BYTE)~FA_READ; /* Desired access mode, write access or not */ + if (fs->fs_type) /* If the volume has been mounted */ + { + stat = disk_status(fs->drv); + if (!(stat & STA_NOINIT)) /* and the physical drive is kept initialized */ + { + if (!_FS_READONLY && mode && (stat & STA_PROTECT)) /* Check write protection if needed */ + { + return FR_WRITE_PROTECTED; + } + return FR_OK; /* The file system object is valid */ + } + } + + /* The file system object is not valid. */ + /* Following code attempts to mount the volume. (analyze BPB and initialize the fs object) */ + + fs->fs_type = 0; /* Clear the file system object */ + fs->drv = LD2PD(vol); /* Bind the logical drive and a physical drive */ + stat = disk_initialize(fs->drv); /* Initialize the physical drive */ + if (stat & STA_NOINIT) /* Check if the initialization succeeded */ + { + return FR_NOT_READY; /* Failed to initialize due to no medium or hard error */ + } + if (!_FS_READONLY && mode && (stat & STA_PROTECT)) /* Check disk write protection if needed */ + { + return FR_WRITE_PROTECTED; + } +#if _MAX_SS != _MIN_SS /* Get sector size (multiple sector size cfg only) */ + if (disk_ioctl(fs->drv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK) return FR_DISK_ERR; + if (SS(fs) > _MAX_SS || SS(fs) < _MIN_SS || (SS(fs) & (SS(fs) - 1))) return FR_DISK_ERR; +#endif + + /* Find an FAT partition on the drive. Supports only generic partitioning rules, FDISK and SFD. */ + bsect = 0; + fmt = check_fs(fs, bsect); /* Load sector 0 and check if it is an FAT-VBR as SFD */ + if (fmt == 2 || (fmt < 2 && LD2PT(vol) != 0)) /* Not an FAT-VBR or forced partition number */ + { + for (i = 0; i < 4; i++) /* Get partition offset */ + { + pt = fs->win + (MBR_Table + i * SZ_PTE); + br[i] = pt[PTE_System] ? ld_dword(pt + PTE_StLba) : 0; + } + i = LD2PT(vol); /* Partition number: 0:auto, 1-4:forced */ + if (i) i--; + do /* Find an FAT volume */ + { + bsect = br[i]; + fmt = bsect ? check_fs(fs, bsect) : 3; /* Check the partition */ + } + while (LD2PT(vol) == 0 && fmt >= 2 && ++i < 4); + } + if (fmt == 4) return FR_DISK_ERR; /* An error occured in the disk I/O layer */ + if (fmt >= 2) return FR_NO_FILESYSTEM; /* No FAT volume is found */ + + /* An FAT volume is found (bsect). Following code initializes the file system object */ + +#if _FS_EXFAT + if (fmt == 1) + { + QWORD maxlba; + + for (i = BPB_ZeroedEx; i < BPB_ZeroedEx + 53 && fs->win[i] == 0; i++) ; /* Check zero filler */ + if (i < BPB_ZeroedEx + 53) return FR_NO_FILESYSTEM; + + if (ld_word(fs->win + BPB_FSVerEx) != 0x100) return FR_NO_FILESYSTEM; /* Check exFAT revision (Must be 1.0) */ + + if (1 << fs->win[BPB_BytsPerSecEx] != SS(fs)) /* (BPB_BytsPerSecEx must be equal to the physical sector size) */ + { + return FR_NO_FILESYSTEM; + } + + maxlba = ld_qword(fs->win + BPB_TotSecEx) + bsect; /* Last LBA + 1 of the volume */ + if (maxlba >= 0x100000000) return FR_NO_FILESYSTEM; /* (It cannot be handled in 32-bit LBA) */ + + fs->fsize = ld_dword(fs->win + BPB_FatSzEx); /* Number of sectors per FAT */ + + fs->n_fats = fs->win[BPB_NumFATsEx]; /* Number of FATs */ + if (fs->n_fats != 1) return FR_NO_FILESYSTEM; /* (Supports only 1 FAT) */ + + fs->csize = 1 << fs->win[BPB_SecPerClusEx]; /* Cluster size */ + if (fs->csize == 0) return FR_NO_FILESYSTEM; /* (Must be 1..32768) */ + + nclst = ld_dword(fs->win + BPB_NumClusEx); /* Number of clusters */ + if (nclst > MAX_EXFAT) return FR_NO_FILESYSTEM; /* (Too many clusters) */ + fs->n_fatent = nclst + 2; + + /* Boundaries and Limits */ + fs->volbase = bsect; + fs->database = bsect + ld_dword(fs->win + BPB_DataOfsEx); + fs->fatbase = bsect + ld_dword(fs->win + BPB_FatOfsEx); + if (maxlba < (QWORD)fs->database + nclst * fs->csize) return FR_NO_FILESYSTEM; /* (Volume size must not be smaller than the size requiered) */ + fs->dirbase = ld_dword(fs->win + BPB_RootClusEx); + + /* Check if bitmap location is in assumption (at the first cluster) */ + if (move_window(fs, clust2sect(fs, fs->dirbase)) != FR_OK) return FR_DISK_ERR; + for (i = 0; i < SS(fs); i += SZDIRE) + { + if (fs->win[i] == 0x81 && ld_dword(fs->win + i + 20) == 2) break; /* 81 entry with cluster #2? */ + } + if (i == SS(fs)) return FR_NO_FILESYSTEM; +#if !_FS_READONLY + fs->last_clst = fs->free_clst = 0xFFFFFFFF; /* Initialize cluster allocation information */ +#endif + fmt = FS_EXFAT; /* FAT sub-type */ + } + else +#endif /* _FS_EXFAT */ + { + if (ld_word(fs->win + BPB_BytsPerSec) != SS(fs)) return FR_NO_FILESYSTEM; /* (BPB_BytsPerSec must be equal to the physical sector size) */ + + fasize = ld_word(fs->win + BPB_FATSz16); /* Number of sectors per FAT */ + if (fasize == 0) fasize = ld_dword(fs->win + BPB_FATSz32); + fs->fsize = fasize; + + fs->n_fats = fs->win[BPB_NumFATs]; /* Number of FATs */ + if (fs->n_fats != 1 && fs->n_fats != 2) return FR_NO_FILESYSTEM; /* (Must be 1 or 2) */ + fasize *= fs->n_fats; /* Number of sectors for FAT area */ + + fs->csize = fs->win[BPB_SecPerClus]; /* Cluster size */ + if (fs->csize == 0 || (fs->csize & (fs->csize - 1))) return FR_NO_FILESYSTEM; /* (Must be power of 2) */ + + fs->n_rootdir = ld_word(fs->win + BPB_RootEntCnt); /* Number of root directory entries */ + if (fs->n_rootdir % (SS(fs) / SZDIRE)) return FR_NO_FILESYSTEM; /* (Must be sector aligned) */ + + tsect = ld_word(fs->win + BPB_TotSec16); /* Number of sectors on the volume */ + if (tsect == 0) tsect = ld_dword(fs->win + BPB_TotSec32); + + nrsv = ld_word(fs->win + BPB_RsvdSecCnt); /* Number of reserved sectors */ + if (nrsv == 0) return FR_NO_FILESYSTEM; /* (Must not be 0) */ + + /* Determine the FAT sub type */ + sysect = nrsv + fasize + fs->n_rootdir / (SS(fs) / SZDIRE); /* RSV + FAT + DIR */ + if (tsect < sysect) return FR_NO_FILESYSTEM; /* (Invalid volume size) */ + nclst = (tsect - sysect) / fs->csize; /* Number of clusters */ + if (nclst == 0) return FR_NO_FILESYSTEM; /* (Invalid volume size) */ + fmt = FS_FAT32; + if (nclst <= MAX_FAT16) fmt = FS_FAT16; + if (nclst <= MAX_FAT12) fmt = FS_FAT12; + + /* Boundaries and Limits */ + fs->n_fatent = nclst + 2; /* Number of FAT entries */ + fs->volbase = bsect; /* Volume start sector */ + fs->fatbase = bsect + nrsv; /* FAT start sector */ + fs->database = bsect + sysect; /* Data start sector */ + if (fmt == FS_FAT32) + { + if (ld_word(fs->win + BPB_FSVer32) != 0) return FR_NO_FILESYSTEM; /* (Must be FAT32 revision 0.0) */ + if (fs->n_rootdir) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must be 0) */ + fs->dirbase = ld_dword(fs->win + BPB_RootClus32); /* Root directory start cluster */ + szbfat = fs->n_fatent * 4; /* (Needed FAT size) */ + } + else + { + if (fs->n_rootdir == 0) return FR_NO_FILESYSTEM;/* (BPB_RootEntCnt must not be 0) */ + fs->dirbase = fs->fatbase + fasize; /* Root directory start sector */ + szbfat = (fmt == FS_FAT16) ? /* (Needed FAT size) */ + fs->n_fatent * 2 : fs->n_fatent * 3 / 2 + (fs->n_fatent & 1); + } + if (fs->fsize < (szbfat + (SS(fs) - 1)) / SS(fs)) return FR_NO_FILESYSTEM; /* (BPB_FATSz must not be less than the size needed) */ + +#if !_FS_READONLY + /* Get FSINFO if available */ + fs->last_clst = fs->free_clst = 0xFFFFFFFF; /* Initialize cluster allocation information */ + fs->fsi_flag = 0x80; +#if (_FS_NOFSINFO & 3) != 3 + if (fmt == FS_FAT32 /* Enable FSINFO only if FAT32 and BPB_FSInfo32 == 1 */ + && ld_word(fs->win + BPB_FSInfo32) == 1 + && move_window(fs, bsect + 1) == FR_OK) + { + fs->fsi_flag = 0; + if (ld_word(fs->win + BS_55AA) == 0xAA55 /* Load FSINFO data if available */ + && ld_dword(fs->win + FSI_LeadSig) == 0x41615252 + && ld_dword(fs->win + FSI_StrucSig) == 0x61417272) + { +#if (_FS_NOFSINFO & 1) == 0 + fs->free_clst = ld_dword(fs->win + FSI_Free_Count); +#endif +#if (_FS_NOFSINFO & 2) == 0 + fs->last_clst = ld_dword(fs->win + FSI_Nxt_Free); +#endif + } + } +#endif /* (_FS_NOFSINFO & 3) != 3 */ +#endif /* !_FS_READONLY */ + } + + fs->fs_type = fmt; /* FAT sub-type */ + fs->id = ++Fsid; /* File system mount ID */ +#if _USE_LFN == 1 + fs->lfnbuf = LfnBuf; /* Static LFN working buffer */ +#if _FS_EXFAT + fs->dirbuf = DirBuf; /* Static directory block scratchpad buuffer */ +#endif +#endif +#if _FS_RPATH != 0 + fs->cdir = 0; /* Initialize current directory */ +#endif +#if _FS_LOCK != 0 /* Clear file lock semaphores */ + clear_lock(fs); +#endif + return FR_OK; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Check if the file/directory object is valid or not */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT validate ( /* Returns FR_OK or FR_INVALID_OBJECT */ + _FDID *obj, /* Pointer to the _OBJ, the 1st member in the FIL/DIR object, to check validity */ + FATFS **fs /* Pointer to pointer to the owner file system object to return */ +) +{ + FRESULT res; + + if (!obj || !obj->fs || !obj->fs->fs_type || obj->fs->id != obj->id || (disk_status(obj->fs->drv) & STA_NOINIT)) + { + *fs = 0; + res = FR_INVALID_OBJECT; /* The object is invalid */ + } + else + { + *fs = obj->fs; /* Owner file sytem object */ + ENTER_FF(obj->fs); /* Lock file system */ + res = FR_OK; /* Valid object */ + } + return res; +} + + + + +/*--------------------------------------------------------------------------- + + Public Functions (FatFs API) + +----------------------------------------------------------------------------*/ + + + +/*-----------------------------------------------------------------------*/ +/* Mount/Unmount a Logical Drive */ +/*-----------------------------------------------------------------------*/ +FRESULT f_mount ( + FATFS *fs, /* Pointer to the file system object (NULL:unmount)*/ + const TCHAR *path, /* Logical drive number to be mounted/unmounted */ + BYTE opt /* Mode option 0:Do not mount (delayed mount), 1:Mount immediately */ +) +{ + FATFS *cfs; + int vol; + FRESULT res; + const TCHAR *rp = path; + + FAT_PRT("f_mount1\r\n"); + + /* Get logical drive number */ + vol = get_ldnumber(&rp); + if (vol < 0) + return FR_INVALID_DRIVE; + + cfs = FatFs[vol]; /* Pointer to fs object */ + + if (cfs) + { +#if _FS_LOCK != 0 + clear_lock(cfs); +#endif +#if _FS_REENTRANT /* Discard sync object of the current volume */ + if (!ff_del_syncobj(cfs->sobj)) + return FR_INT_ERR; +#endif + cfs->fs_type = 0; /* Clear old fs object */ + } + + if (fs) + { + fs->fs_type = 0; /* Clear new fs object */ +#if _FS_REENTRANT /* Create sync object for the new volume */ + if (!ff_cre_syncobj((BYTE)vol, &fs->sobj)) + return FR_INT_ERR; +#endif + } + FatFs[vol] = fs; /* Register new fs object */ + + if (!fs || opt != 1) + return FR_OK; /* Do not mount now, it will be mounted later */ + + res = find_volume(&path, &fs, 0); /* Force mounted the volume */ + LEAVE_FF(fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Open or Create a File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_open ( + FIL *fp, /* Pointer to the blank file object */ + const TCHAR *path, /* Pointer to the file name */ + BYTE mode /* Access mode and file open mode flags */ +) +{ + FRESULT res; + DIR dj; + FATFS *fs; +#if !_FS_READONLY + DWORD dw, cl, bcs, clst, sc; + FSIZE_t ofs; +#endif + DEF_NAMBUF + + if (!fp) return FR_INVALID_OBJECT; + + /* Get logical drive */ + mode &= _FS_READONLY ? FA_READ : FA_READ | FA_WRITE | FA_CREATE_ALWAYS | FA_CREATE_NEW | FA_OPEN_ALWAYS | FA_OPEN_APPEND | FA_SEEKEND; + res = find_volume(&path, &fs, mode); + if (res == FR_OK) + { + dj.obj.fs = fs; + INIT_NAMBUF(fs); + res = follow_path(&dj, path); /* Follow the file path */ +#if !_FS_READONLY /* R/W configuration */ + if (res == FR_OK) + { + if (dj.fn[NSFLAG] & NS_NONAME) /* Origin directory itself? */ + { + res = FR_INVALID_NAME; + } +#if _FS_LOCK != 0 + else + { + res = chk_lock(&dj, (mode & ~FA_READ) ? 1 : 0); + } +#endif + } + /* Create or Open a file */ + if (mode & (FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)) + { + if (res != FR_OK) /* No file, create new */ + { + if (res == FR_NO_FILE) /* There is no file to open, create a new entry */ + { +#if _FS_LOCK != 0 + res = enq_lock() ? dir_register(&dj) : FR_TOO_MANY_OPEN_FILES; +#else + res = dir_register(&dj); +#endif + } + mode |= FA_CREATE_ALWAYS; /* File is created */ + } + else /* Any object is already existing */ + { + if (dj.obj.attr & (AM_RDO | AM_DIR)) /* Cannot overwrite it (R/O or DIR) */ + { + res = FR_DENIED; + } + else + { + if (mode & FA_CREATE_NEW) res = FR_EXIST; /* Cannot create as new file */ + } + } + if (res == FR_OK && (mode & FA_CREATE_ALWAYS)) /* Truncate it if overwrite mode */ + { + dw = GET_FATTIME(); +#if _FS_EXFAT + if (fs->fs_type == FS_EXFAT) + { + /* Get current allocation info */ + fp->obj.fs = fs; + fp->obj.sclust = ld_dword(fs->dirbuf + XDIR_FstClus); + fp->obj.objsize = ld_qword(fs->dirbuf + XDIR_FileSize); + fp->obj.stat = fs->dirbuf[XDIR_GenFlags] & 2; + fp->obj.n_frag = 0; + /* Initialize directory entry block */ + st_dword(fs->dirbuf + XDIR_CrtTime, dw); /* Set created time */ + fs->dirbuf[XDIR_CrtTime10] = 0; + st_dword(fs->dirbuf + XDIR_ModTime, dw); /* Set modified time */ + fs->dirbuf[XDIR_ModTime10] = 0; + fs->dirbuf[XDIR_Attr] = AM_ARC; /* Reset attribute */ + st_dword(fs->dirbuf + XDIR_FstClus, 0); /* Reset file allocation info */ + st_qword(fs->dirbuf + XDIR_FileSize, 0); + st_qword(fs->dirbuf + XDIR_ValidFileSize, 0); + fs->dirbuf[XDIR_GenFlags] = 1; + res = store_xdir(&dj); + if (res == FR_OK && fp->obj.sclust) /* Remove the cluster chain if exist */ + { + res = remove_chain(&fp->obj, fp->obj.sclust, 0); + fs->last_clst = fp->obj.sclust - 1; /* Reuse the cluster hole */ + } + } + else +#endif + { + /* Clean directory info */ + st_dword(dj.dir + DIR_CrtTime, dw); /* Set created time */ + st_dword(dj.dir + DIR_ModTime, dw); /* Set modified time */ + dj.dir[DIR_Attr] = AM_ARC; /* Reset attribute */ + cl = ld_clust(fs, dj.dir); /* Get cluster chain */ + st_clust(fs, dj.dir, 0); /* Reset file allocation info */ + st_dword(dj.dir + DIR_FileSize, 0); + fs->wflag = 1; + + if (cl) /* Remove the cluster chain if exist */ + { + dw = fs->winsect; + res = remove_chain(&dj.obj, cl, 0); + if (res == FR_OK) + { + res = move_window(fs, dw); + fs->last_clst = cl - 1; /* Reuse the cluster hole */ + } + } + } + } + } + else /* Open an existing file */ + { + if (res == FR_OK) /* Following succeeded */ + { + if (dj.obj.attr & AM_DIR) /* It is a directory */ + { + res = FR_NO_FILE; + } + else + { + if ((mode & FA_WRITE) && (dj.obj.attr & AM_RDO)) /* R/O violation */ + { + res = FR_DENIED; + } + } + } + } + if (res == FR_OK) + { + if (mode & FA_CREATE_ALWAYS) /* Set file change flag if created or overwritten */ + mode |= FA_MODIFIED; + fp->dir_sect = fs->winsect; /* Pointer to the directory entry */ + fp->dir_ptr = dj.dir; +#if _FS_LOCK != 0 + fp->obj.lockid = inc_lock(&dj, (mode & ~FA_READ) ? 1 : 0); + if (!fp->obj.lockid) res = FR_INT_ERR; +#endif + } +#else /* R/O configuration */ + if (res == FR_OK) + { + if (dj.fn[NSFLAG] & NS_NONAME) /* Origin directory itself? */ + { + res = FR_INVALID_NAME; + } + else + { + if (dj.obj.attr & AM_DIR) /* It is a directory */ + { + res = FR_NO_FILE; + } + } + } +#endif + + if (res == FR_OK) + { +#if _FS_EXFAT + if (fs->fs_type == FS_EXFAT) + { + fp->obj.c_scl = dj.obj.sclust; /* Get containing directory info */ + fp->obj.c_size = ((DWORD)dj.obj.objsize & 0xFFFFFF00) | dj.obj.stat; + fp->obj.c_ofs = dj.blk_ofs; + fp->obj.sclust = ld_dword(fs->dirbuf + XDIR_FstClus); /* Get object allocation info */ + fp->obj.objsize = ld_qword(fs->dirbuf + XDIR_FileSize); + fp->obj.stat = fs->dirbuf[XDIR_GenFlags] & 2; + } + else +#endif + { + fp->obj.sclust = ld_clust(fs, dj.dir); /* Get object allocation info */ + fp->obj.objsize = ld_dword(dj.dir + DIR_FileSize); + } +#if _USE_FASTSEEK + fp->cltbl = 0; /* Disable fast seek mode */ +#endif + fp->obj.fs = fs; /* Validate the file object */ + fp->obj.id = fs->id; + fp->flag = mode; /* Set file access mode */ + fp->err = 0; /* Clear error flag */ + fp->sect = 0; /* Invalidate current data sector */ + fp->fptr = 0; /* Set file pointer top of the file */ +#if !_FS_READONLY +#if !_FS_TINY + memset(fp->buf, 0, _MAX_SS); /* Clear sector buffer */ +#endif + if ((mode & FA_SEEKEND) && fp->obj.objsize > 0) /* Seek to end of file if FA_OPEN_APPEND is specified */ + { + fp->fptr = fp->obj.objsize; /* Offset to seek */ + bcs = (DWORD)fs->csize * SS(fs); /* Cluster size in byte */ + clst = fp->obj.sclust; /* Follow the cluster chain */ + for (ofs = fp->obj.objsize; res == FR_OK && ofs > bcs; ofs -= bcs) + { + clst = get_fat(&fp->obj, clst); + if (clst <= 1) res = FR_INT_ERR; + if (clst == 0xFFFFFFFF) res = FR_DISK_ERR; + } + fp->clust = clst; + if (res == FR_OK && ofs % SS(fs)) /* Fill sector buffer if not on the sector boundary */ + { + if ((sc = clust2sect(fs, clst)) == 0) + { + res = FR_INT_ERR; + } + else + { + fp->sect = sc + (DWORD)(ofs / SS(fs)); +#if !_FS_TINY + if (disk_read(fs->drv, fp->buf, fp->sect, 1) != RES_OK) res = FR_DISK_ERR; +#endif + } + } + } +#endif + } + + FREE_NAMBUF(); + } + + if (res != FR_OK) fp->obj.fs = 0; /* Invalidate file object on error */ + + LEAVE_FF(fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Read File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_read ( + FIL *fp, /* Pointer to the file object */ + void *buff, /* Pointer to data buffer */ + UINT btr, /* Number of bytes to read */ + UINT *br /* Pointer to number of bytes read */ +) +{ + FRESULT res; + FATFS *fs; + DWORD clst, sect; + FSIZE_t remain; + UINT rcnt, cc, csect; + BYTE *rbuff = (BYTE *)buff; + + + *br = 0; /* Clear read byte counter */ + res = validate(&fp->obj, &fs); /* Check validity of the file object */ + if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); /* Check validity */ + if (!(fp->flag & FA_READ)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */ + remain = fp->obj.objsize - fp->fptr; + if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */ + + for ( ; btr; /* Repeat until all data read */ + rbuff += rcnt, fp->fptr += rcnt, *br += rcnt, btr -= rcnt) + { + if (fp->fptr % SS(fs) == 0) /* On the sector boundary? */ + { + csect = (UINT)(fp->fptr / SS(fs) & (fs->csize - 1)); /* Sector offset in the cluster */ + if (csect == 0) /* On the cluster boundary? */ + { + if (fp->fptr == 0) /* On the top of the file? */ + { + clst = fp->obj.sclust; /* Follow cluster chain from the origin */ + } + else /* Middle or end of the file */ + { +#if _USE_FASTSEEK + if (fp->cltbl) + { + clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */ + } + else +#endif + { + clst = get_fat(&fp->obj, fp->clust); /* Follow cluster chain on the FAT */ + } + } + if (clst < 2) ABORT(fs, FR_INT_ERR); + if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR); + fp->clust = clst; /* Update current cluster */ + } + sect = clust2sect(fs, fp->clust); /* Get current sector */ + if (!sect) ABORT(fs, FR_INT_ERR); + sect += csect; + cc = btr / SS(fs); /* When remaining bytes >= sector size, */ + if (cc) /* Read maximum contiguous sectors directly */ + { + if (csect + cc > fs->csize) /* Clip at cluster boundary */ + { + cc = fs->csize - csect; + } + if (disk_read(fs->drv, rbuff, sect, cc) != RES_OK) ABORT(fs, FR_DISK_ERR); +#if !_FS_READONLY && _FS_MINIMIZE <= 2 /* Replace one of the read sectors with cached data if it contains a dirty sector */ +#if _FS_TINY + if (fs->wflag && fs->winsect - sect < cc) + { + memcpy(rbuff + ((fs->winsect - sect) * SS(fs)), fs->win, SS(fs)); + } +#else + if ((fp->flag & FA_DIRTY) && fp->sect - sect < cc) + { + memcpy(rbuff + ((fp->sect - sect) * SS(fs)), fp->buf, SS(fs)); + } +#endif +#endif + rcnt = SS(fs) * cc; /* Number of bytes transferred */ + continue; + } +#if !_FS_TINY + if (fp->sect != sect) /* Load data sector if not in cache */ + { +#if !_FS_READONLY + if (fp->flag & FA_DIRTY) /* Write-back dirty sector cache */ + { + if (disk_write(fs->drv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); + fp->flag &= (BYTE)~FA_DIRTY; + } +#endif + if (disk_read(fs->drv, fp->buf, sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); /* Fill sector cache */ + } +#endif + fp->sect = sect; + } + rcnt = SS(fs) - (UINT)fp->fptr % SS(fs); /* Number of bytes left in the sector */ + if (rcnt > btr) rcnt = btr; /* Clip it by btr if needed */ +#if _FS_TINY + if (move_window(fs, fp->sect) != FR_OK) ABORT(fs, FR_DISK_ERR); /* Move sector window */ + memcpy(rbuff, fs->win + fp->fptr % SS(fs), rcnt); /* Extract partial sector */ +#else + memcpy(rbuff, fp->buf + fp->fptr % SS(fs), rcnt); /* Extract partial sector */ +#endif + } + + LEAVE_FF(fs, FR_OK); +} + + + + +#if !_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Write File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_write ( + FIL *fp, /* Pointer to the file object */ + const void *buff, /* Pointer to the data to be written */ + UINT btw, /* Number of bytes to write */ + UINT *bw /* Pointer to number of bytes written */ +) +{ + FRESULT res; + FATFS *fs; + DWORD clst, sect; + UINT wcnt, cc, csect; + const BYTE *wbuff = (const BYTE *)buff; + + + *bw = 0; /* Clear write byte counter */ + res = validate(&fp->obj, &fs); /* Check validity of the file object */ + if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); /* Check validity */ + if (!(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */ + + /* Check fptr wrap-around (file size cannot reach 4GiB on FATxx) */ + if ((!_FS_EXFAT || fs->fs_type != FS_EXFAT) && (DWORD)(fp->fptr + btw) < (DWORD)fp->fptr) + { + btw = (UINT)(0xFFFFFFFF - (DWORD)fp->fptr); + } + + for ( ; btw; /* Repeat until all data written */ + wbuff += wcnt, fp->fptr += wcnt, fp->obj.objsize = (fp->fptr > fp->obj.objsize) ? fp->fptr : fp->obj.objsize, *bw += wcnt, btw -= wcnt) + { + if (fp->fptr % SS(fs) == 0) /* On the sector boundary? */ + { + csect = (UINT)(fp->fptr / SS(fs)) & (fs->csize - 1); /* Sector offset in the cluster */ + if (csect == 0) /* On the cluster boundary? */ + { + if (fp->fptr == 0) /* On the top of the file? */ + { + clst = fp->obj.sclust; /* Follow from the origin */ + if (clst == 0) /* If no cluster is allocated, */ + { + clst = create_chain(&fp->obj, 0); /* create a new cluster chain */ + } + } + else /* On the middle or end of the file */ + { +#if _USE_FASTSEEK + if (fp->cltbl) + { + clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */ + } + else +#endif + { + clst = create_chain(&fp->obj, fp->clust); /* Follow or stretch cluster chain on the FAT */ + } + } + if (clst == 0) break; /* Could not allocate a new cluster (disk full) */ + if (clst == 1) ABORT(fs, FR_INT_ERR); + if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR); + fp->clust = clst; /* Update current cluster */ + if (fp->obj.sclust == 0) fp->obj.sclust = clst; /* Set start cluster if the first write */ + } +#if _FS_TINY + if (fs->winsect == fp->sect && sync_window(fs) != FR_OK) ABORT(fs, FR_DISK_ERR); /* Write-back sector cache */ +#else + if (fp->flag & FA_DIRTY) /* Write-back sector cache */ + { + if (disk_write(fs->drv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); + fp->flag &= (BYTE)~FA_DIRTY; + } +#endif + sect = clust2sect(fs, fp->clust); /* Get current sector */ + if (!sect) ABORT(fs, FR_INT_ERR); + sect += csect; + cc = btw / SS(fs); /* When remaining bytes >= sector size, */ + if (cc) /* Write maximum contiguous sectors directly */ + { + if (csect + cc > fs->csize) /* Clip at cluster boundary */ + { + cc = fs->csize - csect; + } + if (disk_write(fs->drv, wbuff, sect, cc) != RES_OK) ABORT(fs, FR_DISK_ERR); +#if _FS_MINIMIZE <= 2 +#if _FS_TINY + if (fs->winsect - sect < cc) /* Refill sector cache if it gets invalidated by the direct write */ + { + memcpy(fs->win, wbuff + ((fs->winsect - sect) * SS(fs)), SS(fs)); + fs->wflag = 0; + } +#else + if (fp->sect - sect < cc) /* Refill sector cache if it gets invalidated by the direct write */ + { + memcpy(fp->buf, wbuff + ((fp->sect - sect) * SS(fs)), SS(fs)); + fp->flag &= (BYTE)~FA_DIRTY; + } +#endif +#endif + wcnt = SS(fs) * cc; /* Number of bytes transferred */ + continue; + } +#if _FS_TINY + if (fp->fptr >= fp->obj.objsize) /* Avoid silly cache filling on the growing edge */ + { + if (sync_window(fs) != FR_OK) ABORT(fs, FR_DISK_ERR); + fs->winsect = sect; + } +#else + if (fp->sect != sect && /* Fill sector cache with file data */ + fp->fptr < fp->obj.objsize && + disk_read(fs->drv, fp->buf, sect, 1) != RES_OK) + { + ABORT(fs, FR_DISK_ERR); + } +#endif + fp->sect = sect; + } + wcnt = SS(fs) - (UINT)fp->fptr % SS(fs); /* Number of bytes left in the sector */ + if (wcnt > btw) wcnt = btw; /* Clip it by btw if needed */ +#if _FS_TINY + if (move_window(fs, fp->sect) != FR_OK) ABORT(fs, FR_DISK_ERR); /* Move sector window */ + memcpy(fs->win + fp->fptr % SS(fs), wbuff, wcnt); /* Fit data to the sector */ + fs->wflag = 1; +#else + memcpy(fp->buf + fp->fptr % SS(fs), wbuff, wcnt); /* Fit data to the sector */ + fp->flag |= FA_DIRTY; +#endif + } + + fp->flag |= FA_MODIFIED; /* Set file change flag */ + + LEAVE_FF(fs, FR_OK); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Synchronize the File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_sync ( + FIL *fp /* Pointer to the file object */ +) +{ + FRESULT res; + FATFS *fs; + DWORD tm; + BYTE *dir; +#if _FS_EXFAT + DIR dj; + DEF_NAMBUF +#endif + + res = validate(&fp->obj, &fs); /* Check validity of the file object */ + if (res == FR_OK) + { + if (fp->flag & FA_MODIFIED) /* Is there any change to the file? */ + { +#if !_FS_TINY + if (fp->flag & FA_DIRTY) /* Write-back cached data if needed */ + { + if (disk_write(fs->drv, fp->buf, fp->sect, 1) != RES_OK) LEAVE_FF(fs, FR_DISK_ERR); + fp->flag &= (BYTE)~FA_DIRTY; + } +#endif + /* Update the directory entry */ + tm = GET_FATTIME(); /* Modified time */ +#if _FS_EXFAT + if (fs->fs_type == FS_EXFAT) + { + res = fill_first_frag(&fp->obj); /* Fill first fragment on the FAT if needed */ + if (res == FR_OK) + { + res = fill_last_frag(&fp->obj, fp->clust, 0xFFFFFFFF); /* Fill last fragment on the FAT if needed */ + } + if (res == FR_OK) + { + INIT_NAMBUF(fs); + res = load_obj_dir(&dj, &fp->obj); /* Load directory entry block */ + if (res == FR_OK) + { + fs->dirbuf[XDIR_Attr] |= AM_ARC; /* Set archive bit */ + fs->dirbuf[XDIR_GenFlags] = fp->obj.stat | 1; /* Update file allocation info */ + st_dword(fs->dirbuf + XDIR_FstClus, fp->obj.sclust); + st_qword(fs->dirbuf + XDIR_FileSize, fp->obj.objsize); + st_qword(fs->dirbuf + XDIR_ValidFileSize, fp->obj.objsize); + st_dword(fs->dirbuf + XDIR_ModTime, tm); /* Update modified time */ + fs->dirbuf[XDIR_ModTime10] = 0; + st_dword(fs->dirbuf + XDIR_AccTime, 0); + res = store_xdir(&dj); /* Restore it to the directory */ + if (res == FR_OK) + { + res = sync_fs(fs); + fp->flag &= (BYTE)~FA_MODIFIED; + } + } + FREE_NAMBUF(); + } + } + else +#endif + { + res = move_window(fs, fp->dir_sect); + if (res == FR_OK) + { + dir = fp->dir_ptr; + dir[DIR_Attr] |= AM_ARC; /* Set archive bit */ + st_clust(fp->obj.fs, dir, fp->obj.sclust); /* Update file allocation info */ + st_dword(dir + DIR_FileSize, (DWORD)fp->obj.objsize); /* Update file size */ + st_dword(dir + DIR_ModTime, tm); /* Update modified time */ + st_word(dir + DIR_LstAccDate, 0); + fs->wflag = 1; + res = sync_fs(fs); /* Restore it to the directory */ + fp->flag &= (BYTE)~FA_MODIFIED; + } + } + } + } + + LEAVE_FF(fs, res); +} + +#endif /* !_FS_READONLY */ + + + + +/*-----------------------------------------------------------------------*/ +/* Close File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_close ( + FIL *fp /* Pointer to the file object to be closed */ +) +{ + FRESULT res; + FATFS *fs; + +#if !_FS_READONLY + res = f_sync(fp); /* Flush cached data */ + if (res == FR_OK) +#endif + { + res = validate(&fp->obj, &fs); /* Lock volume */ + if (res == FR_OK) + { +#if _FS_LOCK != 0 + res = dec_lock(fp->obj.lockid); /* Decrement file open counter */ + if (res == FR_OK) +#endif + { + fp->obj.fs = 0; /* Invalidate file object */ + } +#if _FS_REENTRANT + unlock_fs(fs, FR_OK); /* Unlock volume */ +#endif + } + } + return res; +} + + + + +#if _FS_RPATH >= 1 +/*-----------------------------------------------------------------------*/ +/* Change Current Directory or Current Drive, Get Current Directory */ +/*-----------------------------------------------------------------------*/ + +#if _VOLUMES >= 2 +FRESULT f_chdrive ( + const TCHAR *path /* Drive number */ +) +{ + int vol; + + + /* Get logical drive number */ + vol = get_ldnumber(&path); + if (vol < 0) return FR_INVALID_DRIVE; + + CurrVol = (BYTE)vol; /* Set it as current volume */ + + return FR_OK; +} +#endif + + +FRESULT f_chdir ( + const TCHAR *path /* Pointer to the directory path */ +) +{ + FRESULT res; + DIR dj; + FATFS *fs; + DEF_NAMBUF + + /* Get logical drive */ + res = find_volume(&path, &fs, 0); + if (res == FR_OK) + { + dj.obj.fs = fs; + INIT_NAMBUF(fs); + res = follow_path(&dj, path); /* Follow the path */ + if (res == FR_OK) /* Follow completed */ + { + if (dj.fn[NSFLAG] & NS_NONAME) + { + fs->cdir = dj.obj.sclust; /* It is the start directory itself */ +#if _FS_EXFAT + if (fs->fs_type == FS_EXFAT) + { + fs->cdc_scl = dj.obj.c_scl; + fs->cdc_size = dj.obj.c_size; + fs->cdc_ofs = dj.obj.c_ofs; + } +#endif + } + else + { + if (dj.obj.attr & AM_DIR) /* It is a sub-directory */ + { +#if _FS_EXFAT + if (fs->fs_type == FS_EXFAT) + { + fs->cdir = ld_dword(fs->dirbuf + XDIR_FstClus); /* Sub-directory cluster */ + fs->cdc_scl = dj.obj.sclust; /* Save containing directory information */ + fs->cdc_size = ((DWORD)dj.obj.objsize & 0xFFFFFF00) | dj.obj.stat; + fs->cdc_ofs = dj.blk_ofs; + } + else +#endif + { + fs->cdir = ld_clust(fs, dj.dir); /* Sub-directory cluster */ + } + } + else + { + res = FR_NO_PATH; /* Reached but a file */ + } + } + } + FREE_NAMBUF(); + if (res == FR_NO_FILE) res = FR_NO_PATH; + } + + LEAVE_FF(fs, res); +} + + +#if _FS_RPATH >= 2 +FRESULT f_getcwd ( + TCHAR *buff, /* Pointer to the directory path */ + UINT len /* Size of path */ +) +{ + FRESULT res; + DIR dj; + FATFS *fs; + UINT i, n; + DWORD ccl; + TCHAR *tp; + FILINFO fno; + DEF_NAMBUF + + + *buff = 0; + /* Get logical drive */ + res = find_volume((const TCHAR **)&buff, &fs, 0); /* Get current volume */ + if (res == FR_OK) + { + dj.obj.fs = fs; + INIT_NAMBUF(fs); + i = len; /* Bottom of buffer (directory stack base) */ + if (!_FS_EXFAT || fs->fs_type != FS_EXFAT) /* (Cannot do getcwd on exFAT and returns root path) */ + { + dj.obj.sclust = fs->cdir; /* Start to follow upper directory from current directory */ + while ((ccl = dj.obj.sclust) != 0) /* Repeat while current directory is a sub-directory */ + { + res = dir_sdi(&dj, 1 * SZDIRE); /* Get parent directory */ + if (res != FR_OK) break; + res = move_window(fs, dj.sect); + if (res != FR_OK) break; + dj.obj.sclust = ld_clust(fs, dj.dir); /* Goto parent directory */ + res = dir_sdi(&dj, 0); + if (res != FR_OK) break; + do /* Find the entry links to the child directory */ + { + res = dir_read(&dj, 0); + if (res != FR_OK) break; + if (ccl == ld_clust(fs, dj.dir)) break; /* Found the entry */ + res = dir_next(&dj, 0); + } + while (res == FR_OK); + if (res == FR_NO_FILE) res = FR_INT_ERR;/* It cannot be 'not found'. */ + if (res != FR_OK) break; + get_fileinfo(&dj, &fno); /* Get the directory name and push it to the buffer */ + for (n = 0; fno.fname[n]; n++) ; + if (i < n + 3) + { + res = FR_NOT_ENOUGH_CORE; + break; + } + while (n) buff[--i] = fno.fname[--n]; + buff[--i] = '/'; + } + } + tp = buff; + if (res == FR_OK) + { +#if _VOLUMES >= 2 + *tp++ = '0' + CurrVol; /* Put drive number */ + *tp++ = ':'; +#endif + if (i == len) /* Root-directory */ + { + *tp++ = '/'; + } + else /* Sub-directroy */ + { + do /* Add stacked path str */ + *tp++ = buff[i++]; + while (i < len); + } + } + *tp = 0; + FREE_NAMBUF(); + } + + LEAVE_FF(fs, res); +} + +#endif /* _FS_RPATH >= 2 */ +#endif /* _FS_RPATH >= 1 */ + + + +#if _FS_MINIMIZE <= 2 +/*-----------------------------------------------------------------------*/ +/* Seek File R/W Pointer */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_lseek ( + FIL *fp, /* Pointer to the file object */ + FSIZE_t ofs /* File pointer from top of file */ +) +{ + FRESULT res; + FATFS *fs; + DWORD clst, bcs, nsect; + FSIZE_t ifptr; +#if _USE_FASTSEEK + DWORD cl, pcl, ncl, tcl, dsc, tlen, ulen, *tbl; +#endif + + res = validate(&fp->obj, &fs); /* Check validity of the file object */ + if (res == FR_OK) res = (FRESULT)fp->err; +#if _FS_EXFAT && !_FS_READONLY + if (res == FR_OK && fs->fs_type == FS_EXFAT) + { + res = fill_last_frag(&fp->obj, fp->clust, 0xFFFFFFFF); /* Fill last fragment on the FAT if needed */ + } +#endif + if (res != FR_OK) LEAVE_FF(fs, res); + +#if _USE_FASTSEEK + if (fp->cltbl) /* Fast seek */ + { + if (ofs == CREATE_LINKMAP) /* Create CLMT */ + { + tbl = fp->cltbl; + tlen = *tbl++; + ulen = 2; /* Given table size and required table size */ + cl = fp->obj.sclust; /* Origin of the chain */ + if (cl) + { + do + { + /* Get a fragment */ + tcl = cl; + ncl = 0; + ulen += 2; /* Top, length and used items */ + do + { + pcl = cl; + ncl++; + cl = get_fat(&fp->obj, cl); + if (cl <= 1) ABORT(fs, FR_INT_ERR); + if (cl == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR); + } + while (cl == pcl + 1); + if (ulen <= tlen) /* Store the length and top of the fragment */ + { + *tbl++ = ncl; + *tbl++ = tcl; + } + } + while (cl < fs->n_fatent); /* Repeat until end of chain */ + } + *fp->cltbl = ulen; /* Number of items used */ + if (ulen <= tlen) + { + *tbl = 0; /* Terminate table */ + } + else + { + res = FR_NOT_ENOUGH_CORE; /* Given table size is smaller than required */ + } + } + else /* Fast seek */ + { + if (ofs > fp->obj.objsize) ofs = fp->obj.objsize; /* Clip offset at the file size */ + fp->fptr = ofs; /* Set file pointer */ + if (ofs) + { + fp->clust = clmt_clust(fp, ofs - 1); + dsc = clust2sect(fs, fp->clust); + if (!dsc) ABORT(fs, FR_INT_ERR); + dsc += (DWORD)((ofs - 1) / SS(fs)) & (fs->csize - 1); + if (fp->fptr % SS(fs) && dsc != fp->sect) /* Refill sector cache if needed */ + { +#if !_FS_TINY +#if !_FS_READONLY + if (fp->flag & FA_DIRTY) /* Write-back dirty sector cache */ + { + if (disk_write(fs->drv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); + fp->flag &= (BYTE)~FA_DIRTY; + } +#endif + if (disk_read(fs->drv, fp->buf, dsc, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); /* Load current sector */ +#endif + fp->sect = dsc; + } + } + } + } + else +#endif + + /* Normal Seek */ + { +#if _FS_EXFAT + if (fs->fs_type != FS_EXFAT && ofs >= 0x100000000) ofs = 0xFFFFFFFF; /* Clip at 4GiB-1 if at FATxx */ +#endif + if (ofs > fp->obj.objsize && (_FS_READONLY || !(fp->flag & FA_WRITE))) /* In read-only mode, clip offset with the file size */ + { + ofs = fp->obj.objsize; + } + ifptr = fp->fptr; + fp->fptr = nsect = 0; + if (ofs) + { + bcs = (DWORD)fs->csize * SS(fs); /* Cluster size (byte) */ + if (ifptr > 0 && + (ofs - 1) / bcs >= (ifptr - 1) / bcs) /* When seek to same or following cluster, */ + { + fp->fptr = (ifptr - 1) & ~(FSIZE_t)(bcs - 1); /* start from the current cluster */ + ofs -= fp->fptr; + clst = fp->clust; + } + else /* When seek to back cluster, */ + { + clst = fp->obj.sclust; /* start from the first cluster */ +#if !_FS_READONLY + if (clst == 0) /* If no cluster chain, create a new chain */ + { + clst = create_chain(&fp->obj, 0); + if (clst == 1) ABORT(fs, FR_INT_ERR); + if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR); + fp->obj.sclust = clst; + } +#endif + fp->clust = clst; + } + if (clst != 0) + { + while (ofs > bcs) /* Cluster following loop */ + { + ofs -= bcs; + fp->fptr += bcs; +#if !_FS_READONLY + if (fp->flag & FA_WRITE) /* Check if in write mode or not */ + { + if (_FS_EXFAT && fp->fptr > fp->obj.objsize) /* No FAT chain object needs correct objsize to generate FAT value */ + { + fp->obj.objsize = fp->fptr; + fp->flag |= FA_MODIFIED; + } + clst = create_chain(&fp->obj, clst); /* Follow chain with forceed stretch */ + if (clst == 0) /* Clip file size in case of disk full */ + { + ofs = 0; + break; + } + } + else +#endif + { + clst = get_fat(&fp->obj, clst); /* Follow cluster chain if not in write mode */ + } + if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR); + if (clst <= 1 || clst >= fs->n_fatent) ABORT(fs, FR_INT_ERR); + fp->clust = clst; + } + fp->fptr += ofs; + if (ofs % SS(fs)) + { + nsect = clust2sect(fs, clst); /* Current sector */ + if (!nsect) ABORT(fs, FR_INT_ERR); + nsect += (DWORD)(ofs / SS(fs)); + } + } + } + if (!_FS_READONLY && fp->fptr > fp->obj.objsize) /* Set file change flag if the file size is extended */ + { + fp->obj.objsize = fp->fptr; + fp->flag |= FA_MODIFIED; + } + if (fp->fptr % SS(fs) && nsect != fp->sect) /* Fill sector cache if needed */ + { +#if !_FS_TINY +#if !_FS_READONLY + if (fp->flag & FA_DIRTY) /* Write-back dirty sector cache */ + { + if (disk_write(fs->drv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); + fp->flag &= (BYTE)~FA_DIRTY; + } +#endif + if (disk_read(fs->drv, fp->buf, nsect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); /* Fill sector cache */ +#endif + fp->sect = nsect; + } + } + + LEAVE_FF(fs, res); +} + + + +#if _FS_MINIMIZE <= 1 +/*-----------------------------------------------------------------------*/ +/* Create a Directory Object */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_opendir ( + DIR *dp, /* Pointer to directory object to create */ + const TCHAR *path /* Pointer to the directory path */ +) +{ + FRESULT res; + FATFS *fs; + _FDID *obj; + DEF_NAMBUF + +#ifdef DEBUG_FF + printf("f_opendir\r\n"); + uart1_wait_tx_finish(); +#endif + if (!dp) return FR_INVALID_OBJECT; + + /* Get logical drive */ + obj = &dp->obj; +#ifdef DEBUG_FF + printf("f_opendir ---1\r\n"); + uart1_wait_tx_finish(); +#endif + res = find_volume(&path, &fs, 0); +#ifdef DEBUG_FF + printf("f_opendir ---2\r\n"); + uart1_wait_tx_finish(); +#endif + if (res == FR_OK) + { + obj->fs = fs; + INIT_NAMBUF(fs); +#ifdef DEBUG_FF + printf("f_opendir ---3\r\n"); + uart1_wait_tx_finish(); +#endif + res = follow_path(dp, path); /* Follow the path to the directory */ +#ifdef DEBUG_FF + printf("f_opendir ---4\r\n"); + uart1_wait_tx_finish(); +#endif + if (res == FR_OK) /* Follow completed */ + { + if (!(dp->fn[NSFLAG] & NS_NONAME)) /* It is not the origin directory itself */ + { + if (obj->attr & AM_DIR) /* This object is a sub-directory */ + { +#if _FS_EXFAT +#ifdef DEBUG_FF + printf("f_opendir ---5\r\n"); + uart1_wait_tx_finish(); +#endif + if (fs->fs_type == FS_EXFAT) + { + obj->c_scl = obj->sclust; /* Get containing directory inforamation */ + obj->c_size = ((DWORD)obj->objsize & 0xFFFFFF00) | obj->stat; + obj->c_ofs = dp->blk_ofs; + obj->sclust = ld_dword(fs->dirbuf + XDIR_FstClus); /* Get object allocation info */ + obj->objsize = ld_qword(fs->dirbuf + XDIR_FileSize); + obj->stat = fs->dirbuf[XDIR_GenFlags] & 2; +#ifdef DEBUG_FF + printf("f_opendir ---6\r\n"); + uart1_wait_tx_finish(); +#endif + } + else +#endif + { +#ifdef DEBUG_FF + printf("f_opendir ---7\r\n"); + uart1_wait_tx_finish(); +#endif + obj->sclust = ld_clust(fs, dp->dir); /* Get object allocation info */ + } + } + else /* This object is a file */ + { + res = FR_NO_PATH; +#ifdef DEBUG_FF + printf("f_opendir ---8\r\n"); + uart1_wait_tx_finish(); +#endif + } + } +#ifdef DEBUG_FF + printf("f_opendir ---9\r\n"); + uart1_wait_tx_finish(); +#endif + if (res == FR_OK) + { +#ifdef DEBUG_FF + printf("f_opendir ---10\r\n"); + uart1_wait_tx_finish(); +#endif + obj->id = fs->id; + res = dir_sdi(dp, 0); /* Rewind directory */ +#if _FS_LOCK != 0 +#ifdef DEBUG_FF + printf("f_opendir ---11\r\n"); + uart1_wait_tx_finish(); +#endif + if (res == FR_OK) + { +#ifdef DEBUG_FF + printf("f_opendir ---12\r\n"); + uart1_wait_tx_finish(); +#endif + if (obj->sclust) + { +#ifdef DEBUG_FF + printf("f_opendir ---13\r\n"); + uart1_wait_tx_finish(); +#endif + obj->lockid = inc_lock(dp, 0); /* Lock the sub directory */ + if (!obj->lockid) res = FR_TOO_MANY_OPEN_FILES; + } + else + { +#ifdef DEBUG_FF + printf("f_opendir ---14\r\n"); + uart1_wait_tx_finish(); +#endif + obj->lockid = 0; /* Root directory need not to be locked */ + } + } +#endif + } + } +#ifdef DEBUG_FF + printf("f_opendir ---15\r\n"); + uart1_wait_tx_finish(); +#endif + FREE_NAMBUF(); + if (res == FR_NO_FILE) res = FR_NO_PATH; + } +#ifdef DEBUG_FF + printf("f_opendir ---16\r\n"); + uart1_wait_tx_finish(); +#endif + if (res != FR_OK) obj->fs = 0; /* Invalidate the directory object if function faild */ + +#ifdef DEBUG_FF + printf("f_opendir ---17\r\n"); + uart1_wait_tx_finish(); +#endif + LEAVE_FF(fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Close Directory */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_closedir ( + DIR *dp /* Pointer to the directory object to be closed */ +) +{ + FRESULT res; + FATFS *fs; + + + res = validate(&dp->obj, &fs); /* Check validity of the file object */ + if (res == FR_OK) + { +#if _FS_LOCK != 0 + if (dp->obj.lockid) /* Decrement sub-directory open counter */ + { + res = dec_lock(dp->obj.lockid); + } + if (res == FR_OK) +#endif + { + dp->obj.fs = 0; /* Invalidate directory object */ + } +#if _FS_REENTRANT + unlock_fs(fs, FR_OK); /* Unlock volume */ +#endif + } + return res; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Read Directory Entries in Sequence */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_readdir ( + DIR *dp, /* Pointer to the open directory object */ + FILINFO *fno /* Pointer to file information to return */ +) +{ + FRESULT res; + FATFS *fs; + DEF_NAMBUF + + + res = validate(&dp->obj, &fs); /* Check validity of the directory object */ + if (res == FR_OK) + { + if (!fno) + { + res = dir_sdi(dp, 0); /* Rewind the directory object */ + } + else + { + INIT_NAMBUF(fs); + res = dir_read(dp, 0); /* Read an item */ + if (res == FR_NO_FILE) res = FR_OK; /* Ignore end of directory */ + if (res == FR_OK) /* A valid entry is found */ + { + get_fileinfo(dp, fno); /* Get the object information */ + res = dir_next(dp, 0); /* Increment index for next */ + if (res == FR_NO_FILE) res = FR_OK; /* Ignore end of directory now */ + } + FREE_NAMBUF(); + } + } + LEAVE_FF(fs, res); +} + + + +#if _USE_FIND +/*-----------------------------------------------------------------------*/ +/* Find Next File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_findnext ( + DIR *dp, /* Pointer to the open directory object */ + FILINFO *fno /* Pointer to the file information structure */ +) +{ + FRESULT res; + + + for (;;) + { + res = f_readdir(dp, fno); /* Get a directory item */ + if (res != FR_OK || !fno || !fno->fname[0]) break; /* Terminate if any error or end of directory */ + if (pattern_matching(dp->pat, fno->fname, 0, 0)) break; /* Test for the file name */ +#if _USE_LFN != 0 && _USE_FIND == 2 + if (pattern_matching(dp->pat, fno->altname, 0, 0)) break; /* Test for alternative name if exist */ +#endif + } + return res; +} + + + +/*-----------------------------------------------------------------------*/ +/* Find First File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_findfirst ( + DIR *dp, /* Pointer to the blank directory object */ + FILINFO *fno, /* Pointer to the file information structure */ + const TCHAR *path, /* Pointer to the directory to open */ + const TCHAR *pattern /* Pointer to the matching pattern */ +) +{ + FRESULT res; + + + dp->pat = pattern; /* Save pointer to pattern string */ + res = f_opendir(dp, path); /* Open the target directory */ + if (res == FR_OK) + { + res = f_findnext(dp, fno); /* Find the first item */ + } + return res; +} + +#endif /* _USE_FIND */ + + + +#if _FS_MINIMIZE == 0 +/*-----------------------------------------------------------------------*/ +/* Get File Status */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_stat ( + const TCHAR *path, /* Pointer to the file path */ + FILINFO *fno /* Pointer to file information to return */ +) +{ + FRESULT res; + DIR dj; + DEF_NAMBUF + + + /* Get logical drive */ + res = find_volume(&path, &dj.obj.fs, 0); + if (res == FR_OK) + { + INIT_NAMBUF(dj.obj.fs); + res = follow_path(&dj, path); /* Follow the file path */ + if (res == FR_OK) /* Follow completed */ + { + if (dj.fn[NSFLAG] & NS_NONAME) /* It is origin directory */ + { + res = FR_INVALID_NAME; + } + else /* Found an object */ + { + if (fno) get_fileinfo(&dj, fno); + } + } + FREE_NAMBUF(); + } + + LEAVE_FF(dj.obj.fs, res); +} + + + +#if !_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Get Number of Free Clusters */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_getfree ( + const TCHAR *path, /* Path name of the logical drive number */ + DWORD *nclst, /* Pointer to a variable to return number of free clusters */ + FATFS **fatfs /* Pointer to return pointer to corresponding file system object */ +) +{ + FRESULT res; + FATFS *fs; + DWORD nfree, clst, sect, stat; + UINT i; + BYTE *p; + _FDID obj; + + + /* Get logical drive */ + res = find_volume(&path, &fs, 0); + if (res == FR_OK) + { + *fatfs = fs; /* Return ptr to the fs object */ + /* If free_clst is valid, return it without full cluster scan */ + if (fs->free_clst <= fs->n_fatent - 2) + { + *nclst = fs->free_clst; + } + else + { + /* Get number of free clusters */ + nfree = 0; + if (fs->fs_type == FS_FAT12) /* FAT12: Sector unalighed FAT entries */ + { + clst = 2; + obj.fs = fs; + do + { + stat = get_fat(&obj, clst); + if (stat == 0xFFFFFFFF) + { + res = FR_DISK_ERR; + break; + } + if (stat == 1) + { + res = FR_INT_ERR; + break; + } + if (stat == 0) nfree++; + } + while (++clst < fs->n_fatent); + } + else + { +#if _FS_EXFAT + if (fs->fs_type == FS_EXFAT) /* exFAT: Scan bitmap table */ + { + BYTE bm; + UINT b; + + clst = fs->n_fatent - 2; + sect = fs->database; + i = 0; + do + { + if (i == 0 && (res = move_window(fs, sect++)) != FR_OK) break; + for (b = 8, bm = fs->win[i]; b && clst; b--, clst--) + { + if (!(bm & 1)) nfree++; + bm >>= 1; + } + i = (i + 1) % SS(fs); + } + while (clst); + } + else +#endif + { + /* FAT16/32: Sector alighed FAT entries */ + clst = fs->n_fatent; + sect = fs->fatbase; + i = 0; + p = 0; + do + { + if (i == 0) + { + res = move_window(fs, sect++); + if (res != FR_OK) break; + p = fs->win; + i = SS(fs); + } + if (fs->fs_type == FS_FAT16) + { + if (ld_word(p) == 0) nfree++; + p += 2; + i -= 2; + } + else + { + if ((ld_dword(p) & 0x0FFFFFFF) == 0) nfree++; + p += 4; + i -= 4; + } + } + while (--clst); + } + } + *nclst = nfree; /* Return the free clusters */ + fs->free_clst = nfree; /* Now free_clst is valid */ + fs->fsi_flag |= 1; /* FSInfo is to be updated */ + } + } + + LEAVE_FF(fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Truncate File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_truncate ( + FIL *fp /* Pointer to the file object */ +) +{ + FRESULT res; + FATFS *fs; + DWORD ncl; + + + res = validate(&fp->obj, &fs); /* Check validity of the file object */ + if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); + if (!(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */ + + if (fp->fptr < fp->obj.objsize) /* Process when fptr is not on the eof */ + { + if (fp->fptr == 0) /* When set file size to zero, remove entire cluster chain */ + { + res = remove_chain(&fp->obj, fp->obj.sclust, 0); + fp->obj.sclust = 0; + } + else /* When truncate a part of the file, remove remaining clusters */ + { + ncl = get_fat(&fp->obj, fp->clust); + res = FR_OK; + if (ncl == 0xFFFFFFFF) res = FR_DISK_ERR; + if (ncl == 1) res = FR_INT_ERR; + if (res == FR_OK && ncl < fs->n_fatent) + { + res = remove_chain(&fp->obj, ncl, fp->clust); + } + } + fp->obj.objsize = fp->fptr; /* Set file size to current R/W point */ + fp->flag |= FA_MODIFIED; +#if !_FS_TINY + if (res == FR_OK && (fp->flag & FA_DIRTY)) + { + if (disk_write(fs->drv, fp->buf, fp->sect, 1) != RES_OK) + { + res = FR_DISK_ERR; + } + else + { + fp->flag &= (BYTE)~FA_DIRTY; + } + } +#endif + if (res != FR_OK) ABORT(fs, res); + } + + LEAVE_FF(fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Delete a File/Directory */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_unlink ( + const TCHAR *path /* Pointer to the file or directory path */ +) +{ + FRESULT res; + DIR dj, sdj; + DWORD dclst = 0; + FATFS *fs; +#if _FS_EXFAT + _FDID obj; +#endif + DEF_NAMBUF + + + /* Get logical drive */ + res = find_volume(&path, &fs, FA_WRITE); + dj.obj.fs = fs; + if (res == FR_OK) + { + INIT_NAMBUF(fs); + res = follow_path(&dj, path); /* Follow the file path */ + if (_FS_RPATH && res == FR_OK && (dj.fn[NSFLAG] & NS_DOT)) + { + res = FR_INVALID_NAME; /* Cannot remove dot entry */ + } +#if _FS_LOCK != 0 + if (res == FR_OK) res = chk_lock(&dj, 2); /* Check if it is an open object */ +#endif + if (res == FR_OK) /* The object is accessible */ + { + if (dj.fn[NSFLAG] & NS_NONAME) + { + res = FR_INVALID_NAME; /* Cannot remove the origin directory */ + } + else + { + if (dj.obj.attr & AM_RDO) + { + res = FR_DENIED; /* Cannot remove R/O object */ + } + } + if (res == FR_OK) + { +#if _FS_EXFAT + obj.fs = fs; + if (fs->fs_type == FS_EXFAT) + { + obj.sclust = dclst = ld_dword(fs->dirbuf + XDIR_FstClus); + obj.objsize = ld_qword(fs->dirbuf + XDIR_FileSize); + obj.stat = fs->dirbuf[XDIR_GenFlags] & 2; + } + else +#endif + { + dclst = ld_clust(fs, dj.dir); + } + if (dj.obj.attr & AM_DIR) /* Is it a sub-directory? */ + { +#if _FS_RPATH != 0 + if (dclst == fs->cdir) /* Is it the current directory? */ + { + res = FR_DENIED; + } + else +#endif + { + sdj.obj.fs = fs; /* Open the sub-directory */ + sdj.obj.sclust = dclst; +#if _FS_EXFAT + if (fs->fs_type == FS_EXFAT) + { + sdj.obj.objsize = obj.objsize; + sdj.obj.stat = obj.stat; + } +#endif + res = dir_sdi(&sdj, 0); + if (res == FR_OK) + { + res = dir_read(&sdj, 0); /* Read an item */ + if (res == FR_OK) res = FR_DENIED; /* Not empty? */ + if (res == FR_NO_FILE) res = FR_OK; /* Empty? */ + } + } + } + } + if (res == FR_OK) + { + res = dir_remove(&dj); /* Remove the directory entry */ + if (res == FR_OK && dclst) /* Remove the cluster chain if exist */ + { +#if _FS_EXFAT + res = remove_chain(&obj, dclst, 0); +#else + res = remove_chain(&dj.obj, dclst, 0); +#endif + } + if (res == FR_OK) res = sync_fs(fs); + } + } + FREE_NAMBUF(); + } + + LEAVE_FF(fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Create a Directory */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_mkdir ( + const TCHAR *path /* Pointer to the directory path */ +) +{ + FRESULT res; + DIR dj; + FATFS *fs; + BYTE *dir; + UINT n; + DWORD dsc, dcl, pcl, tm; + DEF_NAMBUF + + + /* Get logical drive */ + res = find_volume(&path, &fs, FA_WRITE); + dj.obj.fs = fs; + if (res == FR_OK) + { + INIT_NAMBUF(fs); + res = follow_path(&dj, path); /* Follow the file path */ + if (res == FR_OK) res = FR_EXIST; /* Any object with same name is already existing */ + if (_FS_RPATH && res == FR_NO_FILE && (dj.fn[NSFLAG] & NS_DOT)) + { + res = FR_INVALID_NAME; + } + if (res == FR_NO_FILE) /* Can create a new directory */ + { + dcl = create_chain(&dj.obj, 0); /* Allocate a cluster for the new directory table */ + dj.obj.objsize = (DWORD)fs->csize * SS(fs); + res = FR_OK; + if (dcl == 0) res = FR_DENIED; /* No space to allocate a new cluster */ + if (dcl == 1) res = FR_INT_ERR; + if (dcl == 0xFFFFFFFF) res = FR_DISK_ERR; + if (res == FR_OK) res = sync_window(fs); /* Flush FAT */ + tm = GET_FATTIME(); + if (res == FR_OK) /* Initialize the new directory table */ + { + dsc = clust2sect(fs, dcl); + dir = fs->win; + memset(dir, 0, SS(fs)); + if (!_FS_EXFAT || fs->fs_type != FS_EXFAT) + { + memset(dir + DIR_Name, ' ', 11); /* Create "." entry */ + dir[DIR_Name] = '.'; + dir[DIR_Attr] = AM_DIR; + st_dword(dir + DIR_ModTime, tm); + st_clust(fs, dir, dcl); + memcpy(dir + SZDIRE, dir, SZDIRE); /* Create ".." entry */ + dir[SZDIRE + 1] = '.'; + pcl = dj.obj.sclust; + if (fs->fs_type == FS_FAT32 && pcl == fs->dirbase) pcl = 0; + st_clust(fs, dir + SZDIRE, pcl); + } + for (n = fs->csize; n; n--) /* Write dot entries and clear following sectors */ + { + fs->winsect = dsc++; + fs->wflag = 1; + res = sync_window(fs); + if (res != FR_OK) break; + memset(dir, 0, SS(fs)); + } + } + if (res == FR_OK) + { + res = dir_register(&dj); /* Register the object to the directoy */ + } + if (res == FR_OK) + { +#if _FS_EXFAT + if (fs->fs_type == FS_EXFAT) /* Initialize directory entry block */ + { + st_dword(fs->dirbuf + XDIR_ModTime, tm); /* Created time */ + st_dword(fs->dirbuf + XDIR_FstClus, dcl); /* Table start cluster */ + st_dword(fs->dirbuf + XDIR_FileSize, (DWORD)dj.obj.objsize); /* File size needs to be valid */ + st_dword(fs->dirbuf + XDIR_ValidFileSize, (DWORD)dj.obj.objsize); + fs->dirbuf[XDIR_GenFlags] = 3; /* Initialize the object flag (contiguous) */ + fs->dirbuf[XDIR_Attr] = AM_DIR; /* Attribute */ + res = store_xdir(&dj); + } + else +#endif + { + dir = dj.dir; + st_dword(dir + DIR_ModTime, tm); /* Created time */ + st_clust(fs, dir, dcl); /* Table start cluster */ + dir[DIR_Attr] = AM_DIR; /* Attribute */ + fs->wflag = 1; + } + if (res == FR_OK) + { + res = sync_fs(fs); + } + } + else + { + remove_chain(&dj.obj, dcl, 0); /* Could not register, remove cluster chain */ + } + } + FREE_NAMBUF(); + } + + LEAVE_FF(fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Rename a File/Directory */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_rename ( + const TCHAR *path_old, /* Pointer to the object name to be renamed */ + const TCHAR *path_new /* Pointer to the new name */ +) +{ + FRESULT res; + DIR djo, djn; + FATFS *fs; + BYTE buf[_FS_EXFAT ? SZDIRE * 2 : 24], *dir; + DWORD dw; + DEF_NAMBUF + + + get_ldnumber(&path_new); /* Snip drive number of new name off */ + res = find_volume(&path_old, &fs, FA_WRITE); /* Get logical drive of the old object */ + if (res == FR_OK) + { + djo.obj.fs = fs; + INIT_NAMBUF(fs); + res = follow_path(&djo, path_old); /* Check old object */ + if (res == FR_OK && (djo.fn[NSFLAG] & (NS_DOT | NS_NONAME))) res = FR_INVALID_NAME; /* Check validity of name */ +#if _FS_LOCK != 0 + if (res == FR_OK) + { + res = chk_lock(&djo, 2); + } +#endif + if (res == FR_OK) /* Object to be renamed is found */ + { +#if _FS_EXFAT + if (fs->fs_type == FS_EXFAT) /* At exFAT */ + { + BYTE nf, nn; + WORD nh; + + memcpy(buf, fs->dirbuf, SZDIRE * 2); /* Save 85+C0 entry of old object */ + memcpy(&djn, &djo, sizeof djo); + res = follow_path(&djn, path_new); /* Make sure if new object name is not in use */ + if (res == FR_OK) /* Is new name already in use by any other object? */ + { + res = (djn.obj.sclust == djo.obj.sclust && djn.dptr == djo.dptr) ? FR_NO_FILE : FR_EXIST; + } + if (res == FR_NO_FILE) /* It is a valid path and no name collision */ + { + res = dir_register(&djn); /* Register the new entry */ + if (res == FR_OK) + { + nf = fs->dirbuf[XDIR_NumSec]; + nn = fs->dirbuf[XDIR_NumName]; + nh = ld_word(fs->dirbuf + XDIR_NameHash); + memcpy(fs->dirbuf, buf, SZDIRE * 2); + fs->dirbuf[XDIR_NumSec] = nf; + fs->dirbuf[XDIR_NumName] = nn; + st_word(fs->dirbuf + XDIR_NameHash, nh); + /* Start of critical section where an interruption can cause a cross-link */ + res = store_xdir(&djn); + } + } + } + else +#endif + { + /* At FAT12/FAT16/FAT32 */ + memcpy(buf, djo.dir + DIR_Attr, 21); /* Save information about the object except name */ + memcpy(&djn, &djo, sizeof (DIR)); /* Duplicate the directory object */ + res = follow_path(&djn, path_new); /* Make sure if new object name is not in use */ + if (res == FR_OK) /* Is new name already in use by any other object? */ + { + res = (djn.obj.sclust == djo.obj.sclust && djn.dptr == djo.dptr) ? FR_NO_FILE : FR_EXIST; + } + if (res == FR_NO_FILE) /* It is a valid path and no name collision */ + { + res = dir_register(&djn); /* Register the new entry */ + if (res == FR_OK) + { + dir = djn.dir; /* Copy information about object except name */ + memcpy(dir + 13, buf + 2, 19); + dir[DIR_Attr] = buf[0] | AM_ARC; + fs->wflag = 1; + if ((dir[DIR_Attr] & AM_DIR) && djo.obj.sclust != djn.obj.sclust) /* Update .. entry in the sub-directory if needed */ + { + dw = clust2sect(fs, ld_clust(fs, dir)); + if (!dw) + { + res = FR_INT_ERR; + } + else + { + /* Start of critical section where an interruption can cause a cross-link */ + res = move_window(fs, dw); + dir = fs->win + SZDIRE * 1; /* Ptr to .. entry */ + if (res == FR_OK && dir[1] == '.') + { + st_clust(fs, dir, djn.obj.sclust); + fs->wflag = 1; + } + } + } + } + } + } + if (res == FR_OK) + { + res = dir_remove(&djo); /* Remove old entry */ + if (res == FR_OK) + { + res = sync_fs(fs); + } + } + /* End of the critical section */ + } + FREE_NAMBUF(); + } + + LEAVE_FF(fs, res); +} + +#endif /* !_FS_READONLY */ +#endif /* _FS_MINIMIZE == 0 */ +#endif /* _FS_MINIMIZE <= 1 */ +#endif /* _FS_MINIMIZE <= 2 */ + + + +#if _USE_CHMOD && !_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Change Attribute */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_chmod ( + const TCHAR *path, /* Pointer to the file path */ + BYTE attr, /* Attribute bits */ + BYTE mask /* Attribute mask to change */ +) +{ + FRESULT res; + DIR dj; + FATFS *fs; + DEF_NAMBUF + + + res = find_volume(&path, &fs, FA_WRITE); /* Get logical drive */ + dj.obj.fs = fs; + if (res == FR_OK) + { + INIT_NAMBUF(fs); + res = follow_path(&dj, path); /* Follow the file path */ + if (res == FR_OK && (dj.fn[NSFLAG] & (NS_DOT | NS_NONAME))) res = FR_INVALID_NAME; /* Check object validity */ + if (res == FR_OK) + { + mask &= AM_RDO | AM_HID | AM_SYS | AM_ARC; /* Valid attribute mask */ +#if _FS_EXFAT + if (fs->fs_type == FS_EXFAT) + { + fs->dirbuf[XDIR_Attr] = (attr & mask) | (fs->dirbuf[XDIR_Attr] & (BYTE)~mask); /* Apply attribute change */ + res = store_xdir(&dj); + } + else +#endif + { + dj.dir[DIR_Attr] = (attr & mask) | (dj.dir[DIR_Attr] & (BYTE)~mask); /* Apply attribute change */ + fs->wflag = 1; + } + if (res == FR_OK) + { + res = sync_fs(fs); + } + } + FREE_NAMBUF(); + } + + LEAVE_FF(fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Change Timestamp */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_utime ( + const TCHAR *path, /* Pointer to the file/directory name */ + const FILINFO *fno /* Pointer to the time stamp to be set */ +) +{ + FRESULT res; + DIR dj; + FATFS *fs; + DEF_NAMBUF + + + res = find_volume(&path, &fs, FA_WRITE); /* Get logical drive */ + dj.obj.fs = fs; + if (res == FR_OK) + { + INIT_NAMBUF(fs); + res = follow_path(&dj, path); /* Follow the file path */ + if (res == FR_OK && (dj.fn[NSFLAG] & (NS_DOT | NS_NONAME))) res = FR_INVALID_NAME; /* Check object validity */ + if (res == FR_OK) + { +#if _FS_EXFAT + if (fs->fs_type == FS_EXFAT) + { + st_dword(fs->dirbuf + XDIR_ModTime, (DWORD)fno->fdate << 16 | fno->ftime); + res = store_xdir(&dj); + } + else +#endif + { + st_dword(dj.dir + DIR_ModTime, (DWORD)fno->fdate << 16 | fno->ftime); + fs->wflag = 1; + } + if (res == FR_OK) + { + res = sync_fs(fs); + } + } + FREE_NAMBUF(); + } + + LEAVE_FF(fs, res); +} + +#endif /* _USE_CHMOD && !_FS_READONLY */ + + + +#if _USE_LABEL +/*-----------------------------------------------------------------------*/ +/* Get Volume Label */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_getlabel ( + const TCHAR *path, /* Path name of the logical drive number */ + TCHAR *label, /* Pointer to a buffer to return the volume label */ + DWORD *vsn /* Pointer to a variable to return the volume serial number */ +) +{ + FRESULT res; + DIR dj; + FATFS *fs; + UINT si, di; +#if _LFN_UNICODE || _FS_EXFAT + WCHAR w; +#endif + + /* Get logical drive */ + res = find_volume(&path, &fs, 0); + + /* Get volume label */ + if (res == FR_OK && label) + { + dj.obj.fs = fs; + dj.obj.sclust = 0; /* Open root directory */ + res = dir_sdi(&dj, 0); + if (res == FR_OK) + { + res = dir_read(&dj, 1); /* Find a volume label entry */ + if (res == FR_OK) + { +#if _FS_EXFAT + if (fs->fs_type == FS_EXFAT) + { + for (si = di = 0; si < dj.dir[XDIR_NumLabel]; si++) /* Extract volume label from 83 entry */ + { + w = ld_word(dj.dir + XDIR_Label + si * 2); +#if _LFN_UNICODE + label[di++] = w; +#else + w = ff_convert(w, 0); /* Unicode -> OEM */ + if (w == 0) w = '?'; /* Replace wrong character */ + if (_DF1S && w >= 0x100) label[di++] = (char)(w >> 8); + label[di++] = (char)w; +#endif + } + label[di] = 0; + } + else +#endif + { + si = di = 0; /* Extract volume label from AM_VOL entry with code comversion */ + do + { +#if _LFN_UNICODE + w = (si < 11) ? dj.dir[si++] : ' '; + if (IsDBCS1(w) && si < 11 && IsDBCS2(dj.dir[si])) + { + w = w << 8 | dj.dir[si++]; + } + label[di++] = ff_convert(w, 1); /* OEM -> Unicode */ +#else + label[di++] = dj.dir[si++]; +#endif + } + while (di < 11); + do /* Truncate trailing spaces */ + { + label[di] = 0; + if (di == 0) break; + } + while (label[--di] == ' '); + } + } + } + if (res == FR_NO_FILE) /* No label entry and return nul string */ + { + label[0] = 0; + res = FR_OK; + } + } + + /* Get volume serial number */ + if (res == FR_OK && vsn) + { + res = move_window(fs, fs->volbase); + if (res == FR_OK) + { + switch (fs->fs_type) + { + case FS_EXFAT: + di = BPB_VolIDEx; + break; + + case FS_FAT32: + di = BS_VolID32; + break; + + default: + di = BS_VolID; + } + *vsn = ld_dword(fs->win + di); + } + } + + LEAVE_FF(fs, res); +} + + + +#if !_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Set Volume Label */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_setlabel ( + const TCHAR *label /* Pointer to the volume label to set */ +) +{ + FRESULT res; + DIR dj; + FATFS *fs; + BYTE dirvn[22]; + UINT i, j, slen; + WCHAR w; + static const char badchr[] = "\"*+,.:;<=>\?[]|\x7F"; + + + /* Get logical drive */ + res = find_volume(&label, &fs, FA_WRITE); + if (res != FR_OK) LEAVE_FF(fs, res); + dj.obj.fs = fs; + + /* Get length of given volume label */ + for (slen = 0; (UINT)label[slen] >= ' '; slen++) ; /* Get name length */ + +#if _FS_EXFAT + if (fs->fs_type == FS_EXFAT) /* On the exFAT volume */ + { + for (i = j = 0; i < slen; ) /* Create volume label in directory form */ + { + w = label[i++]; +#if !_LFN_UNICODE + if (IsDBCS1(w)) + { + w = (i < slen && IsDBCS2(label[i])) ? w << 8 | (BYTE)label[i++] : 0; + } + w = ff_convert(w, 1); +#endif + if (w == 0 || chk_chr(badchr, w) || j == 22) /* Check validity check validity of the volume label */ + { + LEAVE_FF(fs, FR_INVALID_NAME); + } + st_word(dirvn + j, w); + j += 2; + } + slen = j; + } + else +#endif + { + /* On the FAT12/16/32 volume */ + for ( ; slen && label[slen - 1] == ' '; slen--) ; /* Remove trailing spaces */ + if (slen) /* Is there a volume label to be set? */ + { + dirvn[0] = 0; + i = j = 0; /* Create volume label in directory form */ + do + { +#if _LFN_UNICODE + w = ff_convert(ff_wtoupper(label[i++]), 0); +#else + w = (BYTE)label[i++]; + if (IsDBCS1(w)) + { + w = (j < 10 && i < slen && IsDBCS2(label[i])) ? w << 8 | (BYTE)label[i++] : 0; + } +#if _USE_LFN != 0 + w = ff_convert(ff_wtoupper(ff_convert(w, 1)), 0); +#else + if (IsLower(w)) w -= 0x20; /* To upper ASCII characters */ +#ifdef _EXCVT + if (w >= 0x80) w = ExCvt[w - 0x80]; /* To upper extended characters (SBCS cfg) */ +#else + if (!_DF1S && w >= 0x80) w = 0; /* Reject extended characters (ASCII cfg) */ +#endif +#endif +#endif + if (w == 0 || chk_chr(badchr, w) || j >= (UINT)((w >= 0x100) ? 10 : 11)) /* Reject invalid characters for volume label */ + { + LEAVE_FF(fs, FR_INVALID_NAME); + } + if (w >= 0x100) dirvn[j++] = (BYTE)(w >> 8); + dirvn[j++] = (BYTE)w; + } + while (i < slen); + while (j < 11) dirvn[j++] = ' '; /* Fill remaining name field */ + if (dirvn[0] == DDEM) LEAVE_FF(fs, FR_INVALID_NAME); /* Reject illegal name (heading DDEM) */ + } + } + + /* Set volume label */ + dj.obj.sclust = 0; /* Open root directory */ + res = dir_sdi(&dj, 0); + if (res == FR_OK) + { + res = dir_read(&dj, 1); /* Get volume label entry */ + if (res == FR_OK) + { + if (_FS_EXFAT && fs->fs_type == FS_EXFAT) + { + dj.dir[XDIR_NumLabel] = (BYTE)(slen / 2); /* Change the volume label */ + memcpy(dj.dir + XDIR_Label, dirvn, slen); + } + else + { + if (slen) + { + memcpy(dj.dir, dirvn, 11); /* Change the volume label */ + } + else + { + dj.dir[DIR_Name] = DDEM; /* Remove the volume label */ + } + } + fs->wflag = 1; + res = sync_fs(fs); + } + else /* No volume label entry is found or error */ + { + if (res == FR_NO_FILE) + { + res = FR_OK; + if (slen) /* Create a volume label entry */ + { + res = dir_alloc(&dj, 1); /* Allocate an entry */ + if (res == FR_OK) + { + memset(dj.dir, 0, SZDIRE); /* Clear the entry */ + if (_FS_EXFAT && fs->fs_type == FS_EXFAT) + { + dj.dir[XDIR_Type] = 0x83; /* Create 83 entry */ + dj.dir[XDIR_NumLabel] = (BYTE)(slen / 2); + memcpy(dj.dir + XDIR_Label, dirvn, slen); + } + else + { + dj.dir[DIR_Attr] = AM_VOL; /* Create volume label entry */ + memcpy(dj.dir, dirvn, 11); + } + fs->wflag = 1; + res = sync_fs(fs); + } + } + } + } + } + + LEAVE_FF(fs, res); +} + +#endif /* !_FS_READONLY */ +#endif /* _USE_LABEL */ + + + +#if _USE_EXPAND && !_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Allocate a Contiguous Blocks to the File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_expand ( + FIL *fp, /* Pointer to the file object */ + FSIZE_t fsz, /* File size to be expanded to */ + BYTE opt /* Operation mode 0:Find and prepare or 1:Find and allocate */ +) +{ + FRESULT res; + FATFS *fs; + DWORD n, clst, stcl, scl, ncl, tcl, lclst; + + + res = validate(&fp->obj, &fs); /* Check validity of the file object */ + if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); + if (fsz == 0 || fp->obj.objsize != 0 || !(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED); +#if _FS_EXFAT + if (fs->fs_type != FS_EXFAT && fsz >= 0x100000000) LEAVE_FF(fs, FR_DENIED); /* Check if in size limit */ +#endif + n = (DWORD)fs->csize * SS(fs); /* Cluster size */ + tcl = (DWORD)(fsz / n) + ((fsz & (n - 1)) ? 1 : 0); /* Number of clusters required */ + stcl = fs->last_clst; + lclst = 0; + if (stcl < 2 || stcl >= fs->n_fatent) stcl = 2; + +#if _FS_EXFAT + if (fs->fs_type == FS_EXFAT) + { + scl = find_bitmap(fs, stcl, tcl); /* Find a contiguous cluster block */ + if (scl == 0) res = FR_DENIED; /* No contiguous cluster block was found */ + if (scl == 0xFFFFFFFF) res = FR_DISK_ERR; + if (res == FR_OK) /* A contiguous free area is found */ + { + if (opt) /* Allocate it now */ + { + res = change_bitmap(fs, scl, tcl, 1); /* Mark the cluster block 'in use' */ + lclst = scl + tcl - 1; + } + else /* Set it as suggested point for next allocation */ + { + lclst = scl - 1; + } + } + } + else +#endif + { + scl = clst = stcl; + ncl = 0; + for (;;) /* Find a contiguous cluster block */ + { + n = get_fat(&fp->obj, clst); + if (++clst >= fs->n_fatent) clst = 2; + if (n == 1) + { + res = FR_INT_ERR; + break; + } + if (n == 0xFFFFFFFF) + { + res = FR_DISK_ERR; + break; + } + if (n == 0) /* Is it a free cluster? */ + { + if (++ncl == tcl) break; /* Break if a contiguous cluster block is found */ + } + else + { + scl = clst; + ncl = 0; /* Not a free cluster */ + } + if (clst == stcl) + { + res = FR_DENIED; /* No contiguous cluster? */ + break; + } + } + if (res == FR_OK) /* A contiguous free area is found */ + { + if (opt) /* Allocate it now */ + { + for (clst = scl, n = tcl; n; clst++, n--) /* Create a cluster chain on the FAT */ + { + res = put_fat(fs, clst, (n == 1) ? 0xFFFFFFFF : clst + 1); + if (res != FR_OK) break; + lclst = clst; + } + } + else /* Set it as suggested point for next allocation */ + { + lclst = scl - 1; + } + } + } + + if (res == FR_OK) + { + fs->last_clst = lclst; /* Set suggested start cluster to start next */ + if (opt) /* Is it allocated now? */ + { + fp->obj.sclust = scl; /* Update object allocation information */ + fp->obj.objsize = fsz; + if (_FS_EXFAT) fp->obj.stat = 2; /* Set status 'contiguous chain' */ + fp->flag |= FA_MODIFIED; + if (fs->free_clst <= fs->n_fatent - 2) /* Update FSINFO */ + { + fs->free_clst -= tcl; + fs->fsi_flag |= 1; + } + } + } + + LEAVE_FF(fs, res); +} + +#endif /* _USE_EXPAND && !_FS_READONLY */ + + + +#if _USE_FORWARD +/*-----------------------------------------------------------------------*/ +/* Forward data to the stream directly */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_forward ( + FIL *fp, /* Pointer to the file object */ + UINT (*func)(const BYTE *, UINT), /* Pointer to the streaming function */ + UINT btf, /* Number of bytes to forward */ + UINT *bf /* Pointer to number of bytes forwarded */ +) +{ + FRESULT res; + FATFS *fs; + DWORD clst, sect; + FSIZE_t remain; + UINT rcnt, csect; + BYTE *dbuf; + + + *bf = 0; /* Clear transfer byte counter */ + res = validate(&fp->obj, &fs); /* Check validity of the file object */ + if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); + if (!(fp->flag & FA_READ)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */ + + remain = fp->obj.objsize - fp->fptr; + if (btf > remain) btf = (UINT)remain; /* Truncate btf by remaining bytes */ + + for ( ; btf && (*func)(0, 0); /* Repeat until all data transferred or stream goes busy */ + fp->fptr += rcnt, *bf += rcnt, btf -= rcnt) + { + csect = (UINT)(fp->fptr / SS(fs) & (fs->csize - 1)); /* Sector offset in the cluster */ + if (fp->fptr % SS(fs) == 0) /* On the sector boundary? */ + { + if (csect == 0) /* On the cluster boundary? */ + { + clst = (fp->fptr == 0) ? /* On the top of the file? */ + fp->obj.sclust : get_fat(&fp->obj, fp->clust); + if (clst <= 1) ABORT(fs, FR_INT_ERR); + if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR); + fp->clust = clst; /* Update current cluster */ + } + } + sect = clust2sect(fs, fp->clust); /* Get current data sector */ + if (!sect) ABORT(fs, FR_INT_ERR); + sect += csect; +#if _FS_TINY + if (move_window(fs, sect) != FR_OK) ABORT(fs, FR_DISK_ERR); /* Move sector window to the file data */ + dbuf = fs->win; +#else + if (fp->sect != sect) /* Fill sector cache with file data */ + { +#if !_FS_READONLY + if (fp->flag & FA_DIRTY) /* Write-back dirty sector cache */ + { + if (disk_write(fs->drv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); + fp->flag &= (BYTE)~FA_DIRTY; + } +#endif + if (disk_read(fs->drv, fp->buf, sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); + } + dbuf = fp->buf; +#endif + fp->sect = sect; + rcnt = SS(fs) - (UINT)fp->fptr % SS(fs); /* Number of bytes left in the sector */ + if (rcnt > btf) rcnt = btf; /* Clip it by btr if needed */ + rcnt = (*func)(dbuf + ((UINT)fp->fptr % SS(fs)), rcnt); /* Forward the file data */ + if (!rcnt) ABORT(fs, FR_INT_ERR); + } + + LEAVE_FF(fs, FR_OK); +} +#endif /* _USE_FORWARD */ + + + +#if _USE_MKFS && !_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Create an FAT/exFAT volume */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_mkfs ( + const TCHAR *path, /* Logical drive number */ + BYTE opt, /* Format option */ + DWORD au, /* Size of allocation unit (cluster) [byte] */ + void *work, /* Pointer to working buffer */ + UINT len /* Size of working buffer */ +) +{ + const UINT n_fats = 1; /* Number of FATs for FAT12/16/32 volume (1 or 2) */ + const UINT n_rootdir = 512; /* Number of root directory entries for FAT12/16 volume */ + static const WORD cst[] = {1, 4, 16, 64, 256, 512, 0}; /* Cluster size boundary for FAT12/16 volume (4Ks unit) */ + static const WORD cst32[] = {1, 2, 4, 8, 16, 32, 0}; /* Cluster size boundary for FAT32 volume (128Ks unit) */ + BYTE fmt, sys, *buf, *pte, pdrv, part; + WORD ss; + DWORD szb_buf, sz_buf, sz_blk, n_clst, pau, sect, nsect, n; + DWORD b_vol, b_fat, b_data; /* Base LBA for volume, fat, data */ + DWORD sz_vol, sz_rsv, sz_fat, sz_dir; /* Size for volume, fat, dir, data */ + UINT i; + int vol; + DSTATUS stat; +#if _USE_TRIM || _FS_EXFAT + DWORD tbl[3]; +#endif + FAT_PRT("f_mkfs\r\n"); + + /* Check mounted drive and clear work area */ + vol = get_ldnumber(&path); /* Get target logical drive */ + if (vol < 0) return FR_INVALID_DRIVE; + if (FatFs[vol]) FatFs[vol]->fs_type = 0; /* Clear the volume */ + pdrv = LD2PD(vol); /* Physical drive */ + part = LD2PT(vol); /* Partition (0:create as new, 1-4:get from partition table) */ + + /* Check physical drive status */ + stat = disk_initialize(pdrv); + if (stat & STA_NOINIT) return FR_NOT_READY; + if (stat & STA_PROTECT) return FR_WRITE_PROTECTED; + if (disk_ioctl(pdrv, GET_BLOCK_SIZE, &sz_blk) != RES_OK || !sz_blk || sz_blk > 32768 || (sz_blk & (sz_blk - 1))) sz_blk = 1; /* Erase block to align data area */ +#if _MAX_SS != _MIN_SS /* Get sector size of the medium if variable sector size cfg. */ + if (disk_ioctl(pdrv, GET_SECTOR_SIZE, &ss) != RES_OK) return FR_DISK_ERR; + if (ss > _MAX_SS || ss < _MIN_SS || (ss & (ss - 1))) return FR_DISK_ERR; +#else + ss = _MAX_SS; +#endif + if ((au != 0 && au < ss) || au > 0x1000000 || (au & (au - 1))) return FR_INVALID_PARAMETER; /* Check if au is valid */ + au /= ss; /* Cluster size in unit of sector */ + + /* Get working buffer */ + buf = (BYTE *)work; /* Working buffer */ + sz_buf = len / ss; /* Size of working buffer (sector) */ + szb_buf = sz_buf * ss; /* Size of working buffer (byte) */ + if (!szb_buf) return FR_MKFS_ABORTED; + + /* Determine where the volume to be located (b_vol, sz_vol) */ + if (_MULTI_PARTITION && part != 0) + { + /* Get partition information from partition table in the MBR */ + if (disk_read(pdrv, buf, 0, 1) != RES_OK) return FR_DISK_ERR; /* Load MBR */ + if (ld_word(buf + BS_55AA) != 0xAA55) return FR_MKFS_ABORTED; /* Check if MBR is valid */ + pte = buf + (MBR_Table + (part - 1) * SZ_PTE); + if (!pte[PTE_System]) return FR_MKFS_ABORTED; /* No partition? */ + b_vol = ld_dword(pte + PTE_StLba); /* Get volume start sector */ + sz_vol = ld_dword(pte + PTE_SizLba); /* Get volume size */ + } + else + { + /* Create a single-partition in this function */ + if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_vol) != RES_OK) return FR_DISK_ERR; + b_vol = (opt & FM_SFD) ? 0 : 63; /* Volume start sector */ + if (sz_vol < b_vol) return FR_MKFS_ABORTED; + sz_vol -= b_vol; /* Volume size */ + } + if (sz_vol < 128) return FR_MKFS_ABORTED; /* Check if volume size is >=128s */ + + /* Pre-determine the FAT type */ + do + { + if (_FS_EXFAT && (opt & FM_EXFAT)) /* exFAT possible? */ + { + if ((opt & FM_ANY) == FM_EXFAT || sz_vol >= 0x4000000 || au > 128) /* exFAT only, vol >= 64Ms or au > 128s ? */ + { + fmt = FS_EXFAT; + break; + } + } + if (au > 128) return FR_INVALID_PARAMETER; /* Too large au for FAT/FAT32 */ + if (opt & FM_FAT32) /* FAT32 possible? */ + { + if ((opt & FM_ANY) == FM_FAT32 || !(opt & FM_FAT)) /* FAT32 only or no-FAT? */ + { + fmt = FS_FAT32; + break; + } + } + if (!(opt & FM_FAT)) return FR_INVALID_PARAMETER; /* no-FAT? */ + fmt = FS_FAT16; + } + while (0); + +#if _FS_EXFAT + if (fmt == FS_EXFAT) /* Create an exFAT volume */ + { + DWORD szb_bit, szb_case, sum, nb, cl; + WCHAR ch, si; + UINT j, st; + BYTE b; + + if (sz_vol < 0x1000) return FR_MKFS_ABORTED; /* Too small volume? */ +#if _USE_TRIM + tbl[0] = b_vol; + tbl[1] = b_vol + sz_vol - 1; /* Inform the device the volume area may be erased */ + disk_ioctl(pdrv, CTRL_TRIM, tbl); +#endif + /* Determine FAT location, data location and number of clusters */ + if (!au) /* au auto-selection */ + { + au = 8; + if (sz_vol >= 0x80000) au = 64; /* >= 512Ks */ + if (sz_vol >= 0x4000000) au = 256; /* >= 64Ms */ + } + b_fat = b_vol + 32; /* FAT start at offset 32 */ + sz_fat = ((sz_vol / au + 2) * 4 + ss - 1) / ss; /* Number of FAT sectors */ + b_data = (b_fat + sz_fat + sz_blk - 1) & ~(sz_blk - 1); /* Align data area to the erase block boundary */ + if (b_data >= sz_vol / 2) return FR_MKFS_ABORTED; /* Too small volume? */ + n_clst = (sz_vol - (b_data - b_vol)) / au; /* Number of clusters */ + if (n_clst < 16) return FR_MKFS_ABORTED; /* Too few clusters? */ + if (n_clst > MAX_EXFAT) return FR_MKFS_ABORTED; /* Too many clusters? */ + + szb_bit = (n_clst + 7) / 8; /* Size of allocation bitmap */ + tbl[0] = (szb_bit + au * ss - 1) / (au * ss); /* Number of allocation bitmap clusters */ + + /* Create a compressed up-case table */ + sect = b_data + au * tbl[0]; /* Table start sector */ + sum = 0; /* Table checksum to be stored in the 82 entry */ + st = si = i = j = szb_case = 0; + do + { + switch (st) + { + case 0: + ch = ff_wtoupper(si); /* Get an up-case char */ + if (ch != si) + { + si++; + break; /* Store the up-case char if exist */ + } + for (j = 1; (WCHAR)(si + j) && (WCHAR)(si + j) == ff_wtoupper((WCHAR)(si + j)); j++) ; /* Get run length of no-case block */ + if (j >= 128) + { + ch = 0xFFFF; + st = 2; + break; /* Compress the no-case block if run is >= 128 */ + } + st = 1; /* Do not compress short run */ + /* go to next case */ + case 1: + ch = si++; /* Fill the short run */ + if (--j == 0) st = 0; + break; + + default: + ch = (WCHAR)j; + si += j; /* Number of chars to skip */ + st = 0; + } + sum = xsum32(buf[i + 0] = (BYTE)ch, sum); /* Put it into the write buffer */ + sum = xsum32(buf[i + 1] = (BYTE)(ch >> 8), sum); + i += 2; + szb_case += 2; + if (!si || i == szb_buf) /* Write buffered data when buffer full or end of process */ + { + n = (i + ss - 1) / ss; + if (disk_write(pdrv, buf, sect, n) != RES_OK) return FR_DISK_ERR; + sect += n; + i = 0; + } + } + while (si); + tbl[1] = (szb_case + au * ss - 1) / (au * ss); /* Number of up-case table clusters */ + tbl[2] = 1; /* Number of root dir clusters */ + + /* Initialize the allocation bitmap */ + sect = b_data; + nsect = (szb_bit + ss - 1) / ss; /* Start of bitmap and number of sectors */ + nb = tbl[0] + tbl[1] + tbl[2]; /* Number of clusters in-use by system */ + do + { + memset(buf, 0, szb_buf); + for (i = 0; nb >= 8 && i < szb_buf; buf[i++] = 0xFF, nb -= 8) ; + for (b = 1; nb && i < szb_buf; buf[i] |= b, b <<= 1, nb--) ; + n = (nsect > sz_buf) ? sz_buf : nsect; /* Write the buffered data */ + if (disk_write(pdrv, buf, sect, n) != RES_OK) return FR_DISK_ERR; + sect += n; + nsect -= n; + } + while (nsect); + + /* Initialize the FAT */ + sect = b_fat; + nsect = sz_fat; /* Start of FAT and number of FAT sectors */ + j = nb = cl = 0; + do + { + memset(buf, 0, szb_buf); + i = 0; /* Clear work area and reset write index */ + if (cl == 0) /* Set entry 0 and 1 */ + { + st_dword(buf + i, 0xFFFFFFF8); + i += 4; + cl++; + st_dword(buf + i, 0xFFFFFFFF); + i += 4; + cl++; + } + do /* Create chains of bitmap, up-case and root dir */ + { + while (nb && i < szb_buf) /* Create a chain */ + { + st_dword(buf + i, (nb > 1) ? cl + 1 : 0xFFFFFFFF); + i += 4; + cl++; + nb--; + } + if (!nb && j < 3) nb = tbl[j++]; /* Next chain */ + } + while (nb && i < szb_buf); + n = (nsect > sz_buf) ? sz_buf : nsect; /* Write the buffered data */ + if (disk_write(pdrv, buf, sect, n) != RES_OK) return FR_DISK_ERR; + sect += n; + nsect -= n; + } + while (nsect); + + /* Initialize the root directory */ + memset(buf, 0, szb_buf); + buf[SZDIRE * 0 + 0] = 0x83; /* 83 entry (volume label) */ + buf[SZDIRE * 1 + 0] = 0x81; /* 81 entry (allocation bitmap) */ + st_dword(buf + SZDIRE * 1 + 20, 2); + st_dword(buf + SZDIRE * 1 + 24, szb_bit); + buf[SZDIRE * 2 + 0] = 0x82; /* 82 entry (up-case table) */ + st_dword(buf + SZDIRE * 2 + 4, sum); + st_dword(buf + SZDIRE * 2 + 20, 2 + tbl[0]); + st_dword(buf + SZDIRE * 2 + 24, szb_case); + sect = b_data + au * (tbl[0] + tbl[1]); + nsect = au; /* Start of the root directory and number of sectors */ + do /* Fill root directory sectors */ + { + n = (nsect > sz_buf) ? sz_buf : nsect; + if (disk_write(pdrv, buf, sect, n) != RES_OK) return FR_DISK_ERR; + memset(buf, 0, ss); + sect += n; + nsect -= n; + } + while (nsect); + + /* Create two set of the exFAT VBR blocks */ + sect = b_vol; + for (n = 0; n < 2; n++) + { + /* Main record (+0) */ + memset(buf, 0, ss); + memcpy(buf + BS_JmpBoot, "\xEB\x76\x90" "EXFAT ", 11); /* Boot jump code (x86), OEM name */ + st_dword(buf + BPB_VolOfsEx, b_vol); /* Volume offset in the physical drive [sector] */ + st_dword(buf + BPB_TotSecEx, sz_vol); /* Volume size [sector] */ + st_dword(buf + BPB_FatOfsEx, b_fat - b_vol); /* FAT offset [sector] */ + st_dword(buf + BPB_FatSzEx, sz_fat); /* FAT size [sector] */ + st_dword(buf + BPB_DataOfsEx, b_data - b_vol); /* Data offset [sector] */ + st_dword(buf + BPB_NumClusEx, n_clst); /* Number of clusters */ + st_dword(buf + BPB_RootClusEx, 2 + tbl[0] + tbl[1]); /* Root dir cluster # */ + st_dword(buf + BPB_VolIDEx, GET_FATTIME()); /* VSN */ + st_word(buf + BPB_FSVerEx, 0x100); /* File system version (1.00) */ + for (buf[BPB_BytsPerSecEx] = 0, i = ss; i >>= 1; buf[BPB_BytsPerSecEx]++) ; /* Log2 of sector size [byte] */ + for (buf[BPB_SecPerClusEx] = 0, i = au; i >>= 1; buf[BPB_SecPerClusEx]++) ; /* Log2 of cluster size [sector] */ + buf[BPB_NumFATsEx] = 1; /* Number of FATs */ + buf[BPB_DrvNumEx] = 0x80; /* Drive number (for int13) */ + st_word(buf + BS_BootCodeEx, 0xFEEB); /* Boot code (x86) */ + st_word(buf + BS_55AA, 0xAA55); /* Signature (placed here regardless of sector size) */ + for (i = sum = 0; i < ss; i++) /* VBR checksum */ + { + if (i != BPB_VolFlagEx && i != BPB_VolFlagEx + 1 && i != BPB_PercInUseEx) sum = xsum32(buf[i], sum); + } + if (disk_write(pdrv, buf, sect++, 1) != RES_OK) return FR_DISK_ERR; + /* Extended bootstrap record (+1..+8) */ + memset(buf, 0, ss); + st_word(buf + ss - 2, 0xAA55); /* Signature (placed at end of sector) */ + for (j = 1; j < 9; j++) + { + for (i = 0; i < ss; sum = xsum32(buf[i++], sum)) ; /* VBR checksum */ + if (disk_write(pdrv, buf, sect++, 1) != RES_OK) return FR_DISK_ERR; + } + /* OEM/Reserved record (+9..+10) */ + memset(buf, 0, ss); + for ( ; j < 11; j++) + { + for (i = 0; i < ss; sum = xsum32(buf[i++], sum)) ; /* VBR checksum */ + if (disk_write(pdrv, buf, sect++, 1) != RES_OK) return FR_DISK_ERR; + } + /* Sum record (+11) */ + for (i = 0; i < ss; i += 4) st_dword(buf + i, sum); /* Fill with checksum value */ + if (disk_write(pdrv, buf, sect++, 1) != RES_OK) return FR_DISK_ERR; + } + + } + else +#endif /* _FS_EXFAT */ + { + /* Create an FAT12/16/32 volume */ + do + { + pau = au; + /* Pre-determine number of clusters and FAT sub-type */ + if (fmt == FS_FAT32) /* FAT32 volume */ + { + if (!pau) /* au auto-selection */ + { + n = sz_vol / 0x20000; /* Volume size in unit of 128KS */ + for (i = 0, pau = 1; cst32[i] && cst32[i] <= n; i++, pau <<= 1) ; /* Get from table */ + } + n_clst = sz_vol / pau; /* Number of clusters */ + sz_fat = (n_clst * 4 + 8 + ss - 1) / ss; /* FAT size [sector] */ + sz_rsv = 32; /* Number of reserved sectors */ + sz_dir = 0; /* No static directory */ + if (n_clst <= MAX_FAT16 || n_clst > MAX_FAT32) return FR_MKFS_ABORTED; + } + else /* FAT12/16 volume */ + { + if (!pau) /* au auto-selection */ + { + n = sz_vol / 0x1000; /* Volume size in unit of 4KS */ + for (i = 0, pau = 1; cst[i] && cst[i] <= n; i++, pau <<= 1) ; /* Get from table */ + } + n_clst = sz_vol / pau; + if (n_clst > MAX_FAT12) + { + n = n_clst * 2 + 4; /* FAT size [byte] */ + } + else + { + fmt = FS_FAT12; + n = (n_clst * 3 + 1) / 2 + 3; /* FAT size [byte] */ + } + sz_fat = (n + ss - 1) / ss; /* FAT size [sector] */ + sz_rsv = 1; /* Number of reserved sectors */ + sz_dir = (DWORD)n_rootdir * SZDIRE / ss; /* Rootdir size [sector] */ + } + b_fat = b_vol + sz_rsv; /* FAT base */ + b_data = b_fat + sz_fat * n_fats + sz_dir; /* Data base */ + + /* Align data base to erase block boundary (for flash memory media) */ + n = ((b_data + sz_blk - 1) & ~(sz_blk - 1)) - b_data; /* Next nearest erase block from current data base */ + if (fmt == FS_FAT32) /* FAT32: Move FAT base */ + { + sz_rsv += n; + b_fat += n; + } + else /* FAT12/16: Expand FAT size */ + { + sz_fat += n / n_fats; + } + + /* Determine number of clusters and final check of validity of the FAT sub-type */ + if (sz_vol < b_data + pau * 16 - b_vol) return FR_MKFS_ABORTED; /* Too small volume */ + n_clst = (sz_vol - sz_rsv - sz_fat * n_fats - sz_dir) / pau; + if (fmt == FS_FAT32) + { + if (n_clst <= MAX_FAT16) /* Too few clusters for FAT32 */ + { + if (!au && (au = pau / 2) != 0) continue; /* Adjust cluster size and retry */ + return FR_MKFS_ABORTED; + } + } + if (fmt == FS_FAT16) + { + if (n_clst > MAX_FAT16) /* Too many clusters for FAT16 */ + { + if (!au && (pau * 2) <= 64) + { + au = pau * 2; + continue; /* Adjust cluster size and retry */ + } + if ((opt & FM_FAT32)) + { + fmt = FS_FAT32; + continue; /* Switch type to FAT32 and retry */ + } + if (!au && (au = pau * 2) <= 128) continue; /* Adjust cluster size and retry */ + return FR_MKFS_ABORTED; + } + if (n_clst <= MAX_FAT12) /* Too few clusters for FAT16 */ + { + if (!au && (au = pau * 2) <= 128) continue; /* Adjust cluster size and retry */ + return FR_MKFS_ABORTED; + } + } + if (fmt == FS_FAT12 && n_clst > MAX_FAT12) return FR_MKFS_ABORTED; /* Too many clusters for FAT12 */ + + /* Ok, it is the valid cluster configuration */ + break; + } + while (1); + +#if _USE_TRIM + tbl[0] = b_vol; + tbl[1] = b_vol + sz_vol - 1; /* Inform the device the volume area can be erased */ + disk_ioctl(pdrv, CTRL_TRIM, tbl); +#endif + /* Create FAT VBR */ + memset(buf, 0, ss); + memcpy(buf + BS_JmpBoot, "\xEB\xFE\x90" "MSDOS5.0", 11);/* Boot jump code (x86), OEM name */ + st_word(buf + BPB_BytsPerSec, ss); /* Sector size [byte] */ + buf[BPB_SecPerClus] = (BYTE)pau; /* Cluster size [sector] */ + st_word(buf + BPB_RsvdSecCnt, (WORD)sz_rsv); /* Size of reserved area */ + buf[BPB_NumFATs] = (BYTE)n_fats; /* Number of FATs */ + st_word(buf + BPB_RootEntCnt, (WORD)((fmt == FS_FAT32) ? 0 : n_rootdir)); /* Number of root directory entries */ + if (sz_vol < 0x10000) + { + st_word(buf + BPB_TotSec16, (WORD)sz_vol); /* Volume size in 16-bit LBA */ + } + else + { + st_dword(buf + BPB_TotSec32, sz_vol); /* Volume size in 32-bit LBA */ + } + buf[BPB_Media] = 0xF8; /* Media descriptor byte */ + st_word(buf + BPB_SecPerTrk, 63); /* Number of sectors per track (for int13) */ + st_word(buf + BPB_NumHeads, 255); /* Number of heads (for int13) */ + st_dword(buf + BPB_HiddSec, b_vol); /* Volume offset in the physical drive [sector] */ + if (fmt == FS_FAT32) + { + st_dword(buf + BS_VolID32, GET_FATTIME()); /* VSN */ + st_dword(buf + BPB_FATSz32, sz_fat); /* FAT size [sector] */ + st_dword(buf + BPB_RootClus32, 2); /* Root directory cluster # (2) */ + st_word(buf + BPB_FSInfo32, 1); /* Offset of FSINFO sector (VBR + 1) */ + st_word(buf + BPB_BkBootSec32, 6); /* Offset of backup VBR (VBR + 6) */ + buf[BS_DrvNum32] = 0x80; /* Drive number (for int13) */ + buf[BS_BootSig32] = 0x29; /* Extended boot signature */ + memcpy(buf + BS_VolLab32, "NO NAME " "FAT32 ", 19); /* Volume label, FAT signature */ + } + else + { + st_dword(buf + BS_VolID, GET_FATTIME()); /* VSN */ + st_word(buf + BPB_FATSz16, (WORD)sz_fat); /* FAT size [sector] */ + buf[BS_DrvNum] = 0x80; /* Drive number (for int13) */ + buf[BS_BootSig] = 0x29; /* Extended boot signature */ + memcpy(buf + BS_VolLab, "NO NAME " "FAT ", 19); /* Volume label, FAT signature */ + } + st_word(buf + BS_55AA, 0xAA55); /* Signature (offset is fixed here regardless of sector size) */ + if (disk_write(pdrv, buf, b_vol, 1) != RES_OK) return FR_DISK_ERR; /* Write it to the VBR sector */ + + /* Create FSINFO record if needed */ + if (fmt == FS_FAT32) + { + disk_write(pdrv, buf, b_vol + 6, 1); /* Write backup VBR (VBR + 6) */ + memset(buf, 0, ss); + st_dword(buf + FSI_LeadSig, 0x41615252); + st_dword(buf + FSI_StrucSig, 0x61417272); + st_dword(buf + FSI_Free_Count, n_clst - 1); /* Number of free clusters */ + st_dword(buf + FSI_Nxt_Free, 2); /* Last allocated cluster# */ + st_word(buf + BS_55AA, 0xAA55); + disk_write(pdrv, buf, b_vol + 7, 1); /* Write backup FSINFO (VBR + 7) */ + disk_write(pdrv, buf, b_vol + 1, 1); /* Write original FSINFO (VBR + 1) */ + } + + /* Initialize FAT area */ + memset(buf, 0, (UINT)szb_buf); + sect = b_fat; /* FAT start sector */ + for (i = 0; i < n_fats; i++) /* Initialize FATs each */ + { + if (fmt == FS_FAT32) + { + st_dword(buf + 0, 0xFFFFFFF8); /* Entry 0 */ + st_dword(buf + 4, 0xFFFFFFFF); /* Entry 1 */ + st_dword(buf + 8, 0x0FFFFFFF); /* Entry 2 (root directory) */ + } + else + { + st_dword(buf + 0, (fmt == FS_FAT12) ? 0xFFFFF8 : 0xFFFFFFF8); /* Entry 0 and 1 */ + } + nsect = sz_fat; /* Number of FAT sectors */ + do /* Fill FAT sectors */ + { + n = (nsect > sz_buf) ? sz_buf : nsect; + if (disk_write(pdrv, buf, sect, (UINT)n) != RES_OK) return FR_DISK_ERR; + memset(buf, 0, ss); + sect += n; + nsect -= n; + } + while (nsect); + } + + /* Initialize root directory (fill with zero) */ + nsect = (fmt == FS_FAT32) ? pau : sz_dir; /* Number of root directory sectors */ + do + { + n = (nsect > sz_buf) ? sz_buf : nsect; + if (disk_write(pdrv, buf, sect, (UINT)n) != RES_OK) return FR_DISK_ERR; + sect += n; + nsect -= n; + } + while (nsect); + } + + /* Determine system ID in the partition table */ + if (_FS_EXFAT && fmt == FS_EXFAT) + { + sys = 0x07; /* HPFS/NTFS/exFAT */ + } + else + { + if (fmt == FS_FAT32) + { + sys = 0x0C; /* FAT32X */ + } + else + { + if (sz_vol >= 0x10000) + { + sys = 0x06; /* FAT12/16 (>=64KS) */ + } + else + { + sys = (fmt == FS_FAT16) ? 0x04 : 0x01; /* FAT16 (<64KS) : FAT12 (<64KS) */ + } + } + } + + /* Update partition information */ + if (_MULTI_PARTITION && part != 0) /* Created in the existing partition */ + { + /* Update system ID in the partition table */ + if (disk_read(pdrv, buf, 0, 1) != RES_OK) return FR_DISK_ERR; /* Read the MBR */ + buf[MBR_Table + (part - 1) * SZ_PTE + PTE_System] = sys; /* Set system ID */ + if (disk_write(pdrv, buf, 0, 1) != RES_OK) return FR_DISK_ERR; /* Write it back to the MBR */ + } + else /* Created as a new single partition */ + { + if (!(opt & FM_SFD)) /* Create partition table if in FDISK format */ + { + memset(buf, 0, ss); + st_word(buf + BS_55AA, 0xAA55); /* MBR signature */ + pte = buf + MBR_Table; /* Create partition table for single partition in the drive */ + pte[PTE_Boot] = 0; /* Boot indicator */ + pte[PTE_StHead] = 1; /* Start head */ + pte[PTE_StSec] = 1; /* Start sector */ + pte[PTE_StCyl] = 0; /* Start cylinder */ + pte[PTE_System] = sys; /* System type */ + n = (b_vol + sz_vol) / (63 * 255); /* (End CHS may be invalid) */ + pte[PTE_EdHead] = 254; /* End head */ + pte[PTE_EdSec] = (BYTE)(n >> 2 | 63); /* End sector */ + pte[PTE_EdCyl] = (BYTE)n; /* End cylinder */ + st_dword(pte + PTE_StLba, b_vol); /* Start offset in LBA */ + st_dword(pte + PTE_SizLba, sz_vol); /* Size in sectors */ + if (disk_write(pdrv, buf, 0, 1) != RES_OK) return FR_DISK_ERR; /* Write it to the MBR */ + } + } + + if (disk_ioctl(pdrv, CTRL_SYNC, 0) != RES_OK) return FR_DISK_ERR; + + return FR_OK; +} + + + +#if _MULTI_PARTITION +/*-----------------------------------------------------------------------*/ +/* Create partition table on the physical drive */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_fdisk ( + BYTE pdrv, /* Physical drive number */ + const DWORD *szt, /* Pointer to the size table for each partitions */ + void *work /* Pointer to the working buffer */ +) +{ + UINT i, n, sz_cyl, tot_cyl, b_cyl, e_cyl, p_cyl; + BYTE s_hd, e_hd, *p, *buf = (BYTE *)work; + DSTATUS stat; + DWORD sz_disk, sz_part, s_part; + + FAT_PRT("f_fdisk\r\n"); + + stat = disk_initialize(pdrv); + if (stat & STA_NOINIT) return FR_NOT_READY; + if (stat & STA_PROTECT) return FR_WRITE_PROTECTED; + if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_disk)) return FR_DISK_ERR; + + /* Determine the CHS without any consideration of the drive geometry */ + for (n = 16; n < 256 && sz_disk / n / 63 > 1024; n *= 2) ; + if (n == 256) n--; + e_hd = n - 1; + sz_cyl = 63 * n; + tot_cyl = sz_disk / sz_cyl; + + /* Create partition table */ + memset(buf, 0, _MAX_SS); + p = buf + MBR_Table; + b_cyl = 0; + for (i = 0; i < 4; i++, p += SZ_PTE) + { + p_cyl = (szt[i] <= 100U) ? (DWORD)tot_cyl * szt[i] / 100 : szt[i] / sz_cyl; /* Number of cylinders */ + if (!p_cyl) continue; + s_part = (DWORD)sz_cyl * b_cyl; + sz_part = (DWORD)sz_cyl * p_cyl; + if (i == 0) /* Exclude first track of cylinder 0 */ + { + s_hd = 1; + s_part += 63; + sz_part -= 63; + } + else + { + s_hd = 0; + } + e_cyl = b_cyl + p_cyl - 1; /* End cylinder */ + if (e_cyl >= tot_cyl) return FR_INVALID_PARAMETER; + + /* Set partition table */ + p[1] = s_hd; /* Start head */ + p[2] = (BYTE)((b_cyl >> 2) + 1); /* Start sector */ + p[3] = (BYTE)b_cyl; /* Start cylinder */ + p[4] = 0x07; /* System type (temporary setting) */ + p[5] = e_hd; /* End head */ + p[6] = (BYTE)((e_cyl >> 2) + 63); /* End sector */ + p[7] = (BYTE)e_cyl; /* End cylinder */ + st_dword(p + 8, s_part); /* Start sector in LBA */ + st_dword(p + 12, sz_part); /* Number of sectors */ + + /* Next partition */ + b_cyl += p_cyl; + } + st_word(p, 0xAA55); + + /* Write it to the MBR */ + return (disk_write(pdrv, buf, 0, 1) != RES_OK || disk_ioctl(pdrv, CTRL_SYNC, 0) != RES_OK) ? FR_DISK_ERR : FR_OK; +} + +#endif /* _MULTI_PARTITION */ +#endif /* _USE_MKFS && !_FS_READONLY */ + + + + +#if _USE_STRFUNC +/*-----------------------------------------------------------------------*/ +/* Get a string from the file */ +/*-----------------------------------------------------------------------*/ + +TCHAR *f_gets ( + TCHAR *buff, /* Pointer to the string buffer to read */ + int len, /* Size of string buffer (characters) */ + FIL *fp /* Pointer to the file object */ +) +{ + int n = 0; + TCHAR c, *p = buff; + BYTE s[2]; + UINT rc; + + + while (n < len - 1) /* Read characters until buffer gets filled */ + { +#if _LFN_UNICODE +#if _STRF_ENCODE == 3 /* Read a character in UTF-8 */ + f_read(fp, s, 1, &rc); + if (rc != 1) break; + c = s[0]; + if (c >= 0x80) + { + if (c < 0xC0) continue; /* Skip stray trailer */ + if (c < 0xE0) /* Two-byte sequence (0x80-0x7FF) */ + { + f_read(fp, s, 1, &rc); + if (rc != 1) break; + c = (c & 0x1F) << 6 | (s[0] & 0x3F); + if (c < 0x80) c = '?'; /* Reject invalid code range */ + } + else + { + if (c < 0xF0) /* Three-byte sequence (0x800-0xFFFF) */ + { + f_read(fp, s, 2, &rc); + if (rc != 2) break; + c = c << 12 | (s[0] & 0x3F) << 6 | (s[1] & 0x3F); + if (c < 0x800) c = '?'; /* Reject invalid code range */ + } + else /* Reject four-byte sequence */ + { + c = '?'; + } + } + } +#elif _STRF_ENCODE == 2 /* Read a character in UTF-16BE */ + f_read(fp, s, 2, &rc); + if (rc != 2) break; + c = s[1] + (s[0] << 8); +#elif _STRF_ENCODE == 1 /* Read a character in UTF-16LE */ + f_read(fp, s, 2, &rc); + if (rc != 2) break; + c = s[0] + (s[1] << 8); +#else /* Read a character in ANSI/OEM */ + f_read(fp, s, 1, &rc); + if (rc != 1) break; + c = s[0]; + if (IsDBCS1(c)) + { + f_read(fp, s, 1, &rc); + if (rc != 1) break; + c = (c << 8) + s[0]; + } + c = ff_convert(c, 1); /* OEM -> Unicode */ + if (!c) c = '?'; +#endif +#else /* Read a character without conversion */ + f_read(fp, s, 1, &rc); + if (rc != 1) break; + c = s[0]; +#endif + if (_USE_STRFUNC == 2 && c == '\r') continue; /* Strip '\r' */ + *p++ = c; + n++; + if (c == '\n') break; /* Break on EOL */ + } + *p = 0; + return n ? buff : 0; /* When no data read (eof or error), return with error. */ +} + + + + +#if !_FS_READONLY +#include +/*-----------------------------------------------------------------------*/ +/* Put a character to the file */ +/*-----------------------------------------------------------------------*/ + +typedef struct +{ + FIL *fp; /* Ptr to the writing file */ + int idx, nchr; /* Write index of buf[] (-1:error), number of chars written */ + BYTE buf[64]; /* Write buffer */ +} putbuff; + + +static +void putc_bfd ( /* Buffered write with code conversion */ + putbuff *pb, + TCHAR c +) +{ + UINT bw; + int i; + + + if (_USE_STRFUNC == 2 && c == '\n') /* LF -> CRLF conversion */ + { + putc_bfd(pb, '\r'); + } + + i = pb->idx; /* Write index of pb->buf[] */ + if (i < 0) return; + +#if _LFN_UNICODE +#if _STRF_ENCODE == 3 /* Write a character in UTF-8 */ + if (c < 0x80) /* 7-bit */ + { + pb->buf[i++] = (BYTE)c; + } + else + { + if (c < 0x800) /* 11-bit */ + { + pb->buf[i++] = (BYTE)(0xC0 | c >> 6); + } + else /* 16-bit */ + { + pb->buf[i++] = (BYTE)(0xE0 | c >> 12); + pb->buf[i++] = (BYTE)(0x80 | (c >> 6 & 0x3F)); + } + pb->buf[i++] = (BYTE)(0x80 | (c & 0x3F)); + } +#elif _STRF_ENCODE == 2 /* Write a character in UTF-16BE */ + pb->buf[i++] = (BYTE)(c >> 8); + pb->buf[i++] = (BYTE)c; +#elif _STRF_ENCODE == 1 /* Write a character in UTF-16LE */ + pb->buf[i++] = (BYTE)c; + pb->buf[i++] = (BYTE)(c >> 8); +#else /* Write a character in ANSI/OEM */ + c = ff_convert(c, 0); /* Unicode -> OEM */ + if (!c) c = '?'; + if (c >= 0x100) + pb->buf[i++] = (BYTE)(c >> 8); + pb->buf[i++] = (BYTE)c; +#endif +#else /* Write a character without conversion */ + pb->buf[i++] = (BYTE)c; +#endif + + if (i >= (int)(sizeof pb->buf) - 3) /* Write buffered characters to the file */ + { + f_write(pb->fp, pb->buf, (UINT)i, &bw); + i = (bw == (UINT)i) ? 0 : -1; + } + pb->idx = i; + pb->nchr++; +} + + +static +int putc_flush ( /* Flush left characters in the buffer */ + putbuff *pb +) +{ + UINT nw; + + if ( pb->idx >= 0 /* Flush buffered characters to the file */ + && f_write(pb->fp, pb->buf, (UINT)pb->idx, &nw) == FR_OK + && (UINT)pb->idx == nw) return pb->nchr; + return EOF; +} + + +static +void putc_init ( /* Initialize write buffer */ + putbuff *pb, + FIL *fp +) +{ + pb->fp = fp; + pb->nchr = pb->idx = 0; +} + + + +int f_putc ( + TCHAR c, /* A character to be output */ + FIL *fp /* Pointer to the file object */ +) +{ + putbuff pb; + + + putc_init(&pb, fp); + putc_bfd(&pb, c); /* Put the character */ + return putc_flush(&pb); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Put a string to the file */ +/*-----------------------------------------------------------------------*/ + +int f_puts ( + const TCHAR *str, /* Pointer to the string to be output */ + FIL *fp /* Pointer to the file object */ +) +{ + putbuff pb; + + + putc_init(&pb, fp); + while (*str) putc_bfd(&pb, *str++); /* Put the string */ + return putc_flush(&pb); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Put a formatted string to the file */ +/*-----------------------------------------------------------------------*/ + +int f_printf ( + FIL *fp, /* Pointer to the file object */ + const TCHAR *fmt, /* Pointer to the format string */ + ... /* Optional arguments... */ +) +{ + va_list arp; + putbuff pb; + BYTE f, r; + UINT i, j, w; + DWORD v; + TCHAR c, d, str[32], *p; + + + putc_init(&pb, fp); + + va_start(arp, fmt); + + for (;;) + { + c = *fmt++; + if (c == 0) break; /* End of string */ + if (c != '%') /* Non escape character */ + { + putc_bfd(&pb, c); + continue; + } + w = f = 0; + c = *fmt++; + if (c == '0') /* Flag: '0' padding */ + { + f = 1; + c = *fmt++; + } + else + { + if (c == '-') /* Flag: left justified */ + { + f = 2; + c = *fmt++; + } + } + while (IsDigit(c)) /* Precision */ + { + w = w * 10 + c - '0'; + c = *fmt++; + } + if (c == 'l' || c == 'L') /* Prefix: Size is long int */ + { + f |= 4; + c = *fmt++; + } + if (!c) break; + d = c; + if (IsLower(d)) d -= 0x20; + switch (d) /* Type is... */ + { + case 'S' : /* String */ + p = va_arg(arp, TCHAR *); + for (j = 0; p[j]; j++) ; + if (!(f & 2)) + { + while (j++ < w) putc_bfd(&pb, ' '); + } + while (*p) putc_bfd(&pb, *p++); + while (j++ < w) putc_bfd(&pb, ' '); + continue; + + case 'C' : /* Character */ + putc_bfd(&pb, (TCHAR)va_arg(arp, int)); + continue; + + case 'B' : /* Binary */ + r = 2; + break; + + case 'O' : /* Octal */ + r = 8; + break; + + case 'D' : /* Signed decimal */ + case 'U' : /* Unsigned decimal */ + r = 10; + break; + + case 'X' : /* Hexdecimal */ + r = 16; + break; + + default: /* Unknown type (pass-through) */ + putc_bfd(&pb, c); + continue; + } + + /* Get an argument and put it in numeral */ + v = (f & 4) ? (DWORD)va_arg(arp, long) : ((d == 'D') ? (DWORD)(long)va_arg(arp, int) : (DWORD)va_arg(arp, unsigned int)); + if (d == 'D' && (v & 0x80000000)) + { + v = 0 - v; + f |= 8; + } + i = 0; + do + { + d = (TCHAR)(v % r); + v /= r; + if (d > 9) d += (c == 'x') ? 0x27 : 0x07; + str[i++] = d + '0'; + } + while (v && i < sizeof str / sizeof str[0]); + if (f & 8) str[i++] = '-'; + j = i; + d = (f & 1) ? '0' : ' '; + while (!(f & 2) && j++ < w) putc_bfd(&pb, d); + do + { + putc_bfd(&pb, str[--i]); + } + while (i); + while (j++ < w) putc_bfd(&pb, d); + } + + va_end(arp); + + return putc_flush(&pb); +} + +#endif /* !_FS_READONLY */ +#endif /* _USE_STRFUNC */ + +/*Exfat*/ +#define BPB_ExFatName 0x04 /*xfat string*/ +#define BPB_ExFatOffset 0x50 /*fat offset*/ +#define BPB_ExFatLength 0x54 /*fat length*/ +#define BPB_ExClusHPOffset 0x58 /*cluster Heap Offset*/ +#define BPB_ExClusterCnt 0x5c /*cluster count*/ +#define BPB_ExRootDirBase 0x60 /*root dir cluster*/ +#define BPB_ExBytePerSecSft 0x6c /*bytes per sector shift */ +#define BPB_ExSecPerClusSft 0x6d /*sectors per cluster shift */ +#define BPB_ExNumofFATs 0x6e /*number of fat*/ + +#define FILE_DIR_ENTRY 0x85 +#define STREAM_EXT_DIR_ENT 0xc0 +#define FILE_NAME_DIR_ENTRY 0xc1 + +#define ExFat_Dir_Attr 0x04//1byte + +#define ExFat_NoChainFlag 0x01//1 byte +#define ExFat_DataLength 0x08//4bytes +#define ExFat_FirstCluster 0x14//4bytes +#define ExFat_NameLength 0x03//1byte, unicode uint + +#define BPB_RootClus 44 /* Root directory first cluster (4) */ + +#define FS_EXFAT 4 + +/* Multi-byte word access macros */ /* Use byte-by-byte access to the FAT structure */ +#define LD_WORD(ptr) (uint16)(((uint16)*((uint8*)(ptr)+1)<<8)|(uint16)*(uint8*)(ptr)) +#define LD_DWORD(ptr) (uint32)(((uint32)*((uint8*)(ptr)+3)<<24)|((uint32)*((uint8*)(ptr)+2)<<16)|((uint16)*((uint8*)(ptr)+1)<<8)|*(uint8*)(ptr)) +#define ST_WORD(ptr,val) *(uint8*)(ptr)=(uint8)(val); *((uint8*)(ptr)+1)=(uint8)((uint16)(val)>>8) +#define ST_DWORD(ptr,val) *(uint8*)(ptr)=(uint8)(val); *((uint8*)(ptr)+1)=(uint8)((uint16)(val)>>8); *((uint8*)(ptr)+2)=(uint8)((uint32)(val)>>16); *((uint8*)(ptr)+3)=(uint8)((uint32)(val)>>24) + + + + +FRESULT chk_mounted_con (FATFS *rfs, uint8 type) +{ + uint8 fmt, *tbl, drv; + DSTATUS stat; + uint32 bsect, fsize, tsect, mclst; + FATFS *fs; + uint8 vol = 0; + fs = rfs; + drv = 0; + if (!fs) + return FR_NOT_ENABLED; /* Is the file system object available? */ + if (fs->fs_type) + { + stat = disk_status(drv); + if (!(stat & STA_NOINIT)) + return FR_OK; /* The file system object is valid */ + } + + fs->fs_type = 0; + fs->drv = type; + stat = disk_initialize(fs->drv); /* Initialize low level disk I/O layer */ + if (stat & STA_NOINIT) + return FR_NOT_READY; + + fmt = check_fs(fs, bsect = 0); + + if (fmt == 3) + { + /* Not an FAT boot record, it may be patitioned */ + while(vol < 4) + { + tbl = &fs->win[MBR_Table + vol * 16]; + + if (tbl[4]) + { + bsect = LD_DWORD(&tbl[8]); + fmt = check_fs(fs, bsect); + break; + } + else + { + vol++; + } + } + } + + if (fmt == 4) + return FR_NO_FILESYSTEM; + if((fmt == 2) || (fmt == 3)) + return FR_DISK_ERR; + + if(fmt == 1) /*exfat*/ + { + if((1 << (fs->win[BPB_ExBytePerSecSft])) != SS(fs)) + return FR_NO_FILESYSTEM; + /* Initialize the file system object */ + fs->fsize = LD_DWORD(fs->win + BPB_ExFatLength); + fs->n_fats = fs->win[BPB_ExNumofFATs]; + fs->fatbase = bsect + LD_DWORD(fs->win + BPB_ExFatOffset); //// + fs->csize = 1 << (fs->win[BPB_ExSecPerClusSft]); + fs->n_fatent = LD_DWORD(fs->win + BPB_ExClusterCnt); + fs->dirbase = LD_DWORD(fs->win + BPB_ExRootDirBase); + fs->database = bsect + LD_DWORD(fs->win + BPB_ExClusHPOffset); + fs->n_rootdir = 0; + fs->fs_type = FS_EXFAT; + fs->winsect = 0; + } + else + { + if (fmt || LD_WORD(fs->win + BPB_BytsPerSec) != SS(fs)) + return FR_NO_FILESYSTEM; + /* Initialize the file system object */ + fsize = LD_WORD(fs->win + BPB_FATSz16); + if (!fsize) fsize = LD_DWORD(fs->win + BPB_FATSz32); + fs->fsize = fsize; + fs->n_fats = fs->win[BPB_NumFATs]; + fsize *= fs->n_fats; + fs->fatbase = bsect + LD_WORD(fs->win + BPB_RsvdSecCnt); + fs->csize = fs->win[BPB_SecPerClus]; + fs->n_rootdir = LD_WORD(fs->win + BPB_RootEntCnt); + tsect = LD_WORD(fs->win + BPB_TotSec16); + if (!tsect) tsect = LD_DWORD(fs->win + BPB_TotSec32); + fs->n_fatent = mclst = (tsect + - LD_WORD(fs->win + BPB_RsvdSecCnt) - fsize - fs->n_rootdir / (SS(fs) / 32) + ) / fs->csize + 2; + + fmt = FS_FAT12; + if (mclst >= 0xFF7) fmt = FS_FAT16; + if (mclst >= 0xFFF7) fmt = FS_FAT32; + + if (fmt == FS_FAT32) + fs->dirbase = LD_DWORD(fs->win + BPB_RootClus); + else + fs->dirbase = fs->fatbase + fsize; + fs->database = fs->fatbase + fsize + fs->n_rootdir / (SS(fs) / 32); + fs->fs_type = fmt; + fs->winsect = 0; + } + + fs->id = ++Fsid; + // os_printf("FAT INIT OK!!!\r\n"); + return FR_OK; + + + +} + +/*-----------------------------------------------------------------------*/ +/* Directory handling - Seek directory index */ +/*-----------------------------------------------------------------------*/ +#define EXFatContiguousClus 0x03 +//static +FRESULT dir_seek ( + DIR *dj, /* Pointer to directory object */ + uint16 idx /* Directory index number */ +) +{ + uint32 clst; + uint16 ic; + + dj->dptr = idx; + + if((dj->obj.fs->fs_type == FS_EXFAT) && (dj->obj.stat == EXFatContiguousClus)) + { + ic = SS(dj->fs) / 32 * dj->obj.fs->csize; /* Entries per cluster */ + clst = dj->obj.sclust; + if (clst >= dj->obj.fs->n_fatent) + return FR_INT_ERR; + while(idx >= ic) + { + clst++; + idx -= ic; + } + dj->clust = clst; + dj->sect = clust2sect(dj->obj.fs, dj->clust) + idx / (SS(dj->obj.fs) / 32); + } + else + { + clst = dj->obj.sclust; + if (clst == 1 || clst >= dj->obj.fs->n_fatent) + return FR_INT_ERR; + if (!clst && ((dj->obj.fs->fs_type == FS_FAT32) || (dj->obj.fs->fs_type == FS_EXFAT))) + clst = dj->obj.fs->dirbase; + if (clst == 0) + { + dj->clust = clst; + if (idx >= dj->obj.fs->n_rootdir) + return FR_INT_ERR; + dj->sect = dj->obj.fs->dirbase + idx / (SS(dj->obj.fs) / 32); + } + else + { + ic = SS(dj->obj.fs) / 32 * dj->obj.fs->csize; /* Entries per cluster */ + while (idx >= ic) + { + clst = get_fat(&(dj->obj), clst); /* Get next cluster */ + if (clst == 0xFFFFFFFF) return FR_DISK_ERR; + if (clst < 2 || clst >= dj->obj.fs->n_fatent) /* Reached to end of table or int error */ + return FR_INT_ERR; + idx -= ic; + } + dj->clust = clst; + dj->sect = clust2sect(dj->obj.fs, clst) + idx / (SS(dj->obj.fs) / 32); + } + } + + dj->dir = dj->obj.fs->win + (idx % (SS(dj->obj.fs) / 32)) * 32; /* Ptr to the entry in the sector */ + return FR_OK; +} + + +FRESULT f_EOF(FIL *fp ) +{ + // os_printf("size=%d,ptr=%d\r\n",fp->fsize,fp->fptr); + if(fp->obj.objsize <= fp->fptr) + return (FRESULT)20 /*FR_FILE_END*/; //paul + else + return FR_OK; +} + + +/* +UINT out_stream ( + const BYTE *p, + UINT btf +) +{ + UINT cnt = 0; + + + FR_INT_ERR. + if (FIFO_READY) cnt = 1; + } + else { + do { + FIFO_PORT = *p++; + cnt++; + } while (cnt < btf && FIFO_READY); + } + + return cnt; +} + +*/ + +/*-----------------------------------------------------------------------*/ +/* Read wav File */ +/*-----------------------------------------------------------------------*/ + + + + + +#endif diff --git a/beken_os/beken378/func/fatfs/ff.h b/beken_os/beken378/func/fatfs/ff.h new file mode 100755 index 0000000..dec4194 --- /dev/null +++ b/beken_os/beken378/func/fatfs/ff.h @@ -0,0 +1,912 @@ +#ifndef _FF_HEADER_FILE_ +#define _FF_HEADER_FILE_ + +#include "include.h" +#include "ffconf.h" + +#if CFG_USE_SDCARD_HOST +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef _FATFS +#define _FATFS 7231 /* Revision ID */ + + /* Definitions of volume management */ + /* Each logical drive is bound to the same physical drive number */ +#define LD2PD(vol) (uint8)(vol) + /* Find first valid partition or in SFD */ +#define LD2PT(vol) 0 + typedef unsigned short WCHAR; + + /* Type of path name strings on FatFs API */ +#if _LFN_UNICODE /* Unicode string */ +#if !_USE_LFN +#error _LFN_UNICODE must be 0 at non-LFN cfg. +#endif +#ifndef _INC_TCHAR + typedef WCHAR TCHAR; +#define _T(x) L ## x +#define _TEXT(x) L ## x +#endif + +#else /* ANSI/OEM string */ +#ifndef _INC_TCHAR + typedef char TCHAR; +#define _T(x) x +#define _TEXT(x) x +#endif + +#endif + +#define SD_DATA_CRC_ERR (-255) + +typedef struct _fat_file_info_s +{ + char filename[13]; + char ext_name[3]; + uint32 file_start_cluster; + uint32 file_blks; +} fat_file_info_t; + +typedef struct _FATFS_ +{ + uint8 fs_type; /* FAT sub type */ + uint8 drive; /* Physical drive number */ + uint8 csize; /* Number of sectors per cluster */ + uint8 n_fats; /* Number of FAT copies */ + uint8 wflag; /* win[] dirty flag (1:must be written back) */ + uint8 fsi_flag; /* fsinfo dirty flag (1:must be written back) */ + uint16 id; /* File system mount ID */ + uint16 n_rootdir; /* Number of root directory entries (0 on FAT32) */ + uint32 sects_fat; /* Sectors per fat */ + uint32 max_clust; /* Maximum cluster# + 1. Number of clusters is max_clust - 2 */ + uint32 fatbase; /* FAT start sector */ + uint32 dirbase; /* Root directory start sector (Cluster# on FAT32) */ + uint8 win[_MAX_SS];/* Disk access window for Directory/FAT */ //make sure win is allign(4) + uint32 database; /* Data start sector */ + uint32 winsect; /* Current sector appearing in the win[] */ +} FATFS; + +/* File object structure */ +typedef struct _FIL_ +{ + FATFS *fs; /* Pointer to the owner file system object */ + uint16 id; /* Owner file system mount ID */ + uint8 flag; /* File status flags */ + uint8 csect; /* Sector address in the cluster */ + uint32 fptr; /* File R/W pointer */ + uint32 fsize; /* File size */ + uint32 org_clust; /* File start cluster */ + uint8 buf[_MAX_SS];/* File R/W buffer *///make sure buf is allign(4) + uint32 curr_clust; /* Current cluster */ + uint32 dsect; /* Current data sector */ + uint32 ExNoChainFlag; +} FIL; + + +/* Directory object structure (DIR) */ +typedef struct +{ + FATFS *fs; /* Pointer to the owner file system object (**do not change order**) */ + uint16 id; /* Owner file system mount ID (**do not change order**) */ + uint16 index; /* Current read/write index number */ + uint32 sclust; /* Table start cluster (0:Root dir) */ + uint32 clust; /* Current cluster */ + uint32 sect; /* Current sector */ + uint8 *dir; /* Pointer to the current SFN entry in the win[] */ + uint8 *fn; /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */ + uint32 ExNoChainFlag; /* if the value equals to 0x03,then all cluster are contiguous*/ +#if _USE_LFN + WCHAR *lfn; /* Pointer to the LFN working buffer */ + uint16 lfn_idx; /* Last matched LFN index number (0xFFFF:No LFN) */ +#endif +} DIR; + +/* File status structure (FILINFO) */ +typedef struct +{ + uint32 fsize; /* File size */ + uint16 fdate; /* Last modified date */ + uint16 ftime; /* Last modified time */ + uint8 fattrib; /* Attribute */ + TCHAR fname[13]; /* Short file name (8.3 format) */ + + uint8 ExNoChainFlag; // + uint8 reserved; + uint32 fcluster; +#if _USE_LFN + TCHAR *lfname; /* Pointer to the LFN buffer */ + uint32 lfsize; /* Size of LFN buffer in TCHAR */ +#endif +} FILINFO, FILINFOADD, *PFILINFOADD;; + +typedef struct +{ + uint32 fcluster; /* ļĴغ */ + char fname[13]; /* Short file name (8.3 format) */ + char extname[3]; + // uint8 ExNoChainFlag;//exfat flag + uint8 fat_ok_flag; + uint16 Reserved1; +} FILE_INFO; + +/*app struct*/ +//add by wangxuejun +typedef struct +{ + uint32 first_cluster; + uint16 music_total; + uint8 broot_dir; + uint8 ExNoChainFlag; +} FAT_DIR_INFO; +//add by wangxuejun +typedef struct +{ + uint32 cluster_number; + uint16 dirlevel; + uint8 broot_dir; + uint8 ExNoChainFlag; +} DIR_QUEUE; + + +/* File function return code (FRESULT) */ +typedef enum +{ + FR_OK = 0, /* (0) Succeeded */ + FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */ + FR_INT_ERR, /* (2) Assertion failed */ + FR_NOT_READY, /* (3) The physical drive cannot work */ + FR_NO_FILE, /* (4) Could not find the file */ + FR_NO_PATH, /* (5) Could not find the path */ + FR_INVALID_NAME, /* (6) The path name format is invalid */ + FR_DENIED, /* (7) Access denied due to prohibited access or directory full */ + FR_EXIST, /* (8) Access denied due to prohibited access */ + FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */ + FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */ + FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */ + FR_NOT_ENABLED, /* (12) The volume has no work area */ + FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */ + FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any parameter error */ + FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */ + FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */ + FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */ + FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > _FS_SHARE */ + FR_INVALID_PARAMETER, /* (19) Given parameter is invalid */ + FR_FILE_END /* (20) File end */ +} FRESULT; + + + +/*--------------------------------------------------------------*/ +/* FatFs module application interface */ +FRESULT dir_seek ( + DIR *dj, /* Pointer to directory object */ + uint16 idx /* Directory index number */ +); + +FRESULT move_window ( + FATFS *fs, /* File system object */ + uint32 sector /* Sector number to make apperance in the fs->win[] */ +); /* Move to zero only writes back dirty window */ + +FRESULT f_lseek ( + FIL *fp, /* Pointer to the file object */ + uint32 ofs /* File pointer from top of file */ +); + +/* Close an open file object */ +FRESULT f_close (FIL *fp); +/* Read data from a file */ +FRESULT f_read (FIL *fp, void *buff, uint32 btr, uint32 *br); +/* Read data from a file */ +FRESULT f_wav_read(FIL *fp, void *buff, uint32 btr, uint32 *br); +/* Mount/Unmount a logical drive */ +FRESULT f_mount (uint8 vol, FATFS *fs); +/* Unmount a logical drive */ +FRESULT f_unmount (FATFS *fs); +/*decide the end of an file*/ +FRESULT f_EOF(FIL *fp); + +/* Get current directory */ +FRESULT f_getcwd (TCHAR *buff, uint32 len); +/* Open or create a file */ +FRESULT f_open (FIL *fp, const TCHAR *path, uint8 mode); +/* Open a directory */ +FRESULT f_opendir (DIR *dp, const TCHAR *path); +/* Read a directory item */ +FRESULT f_readdir (DIR *dp, FILINFO *fno); +/* Get file status */ +FRESULT f_stat (const TCHAR *path, FILINFO *fno); +/* Write data to the file */ +FRESULT f_write (FIL *fp, const void *buff, uint32 btw, uint32 *bw); +/* Change current directory */ +FRESULT f_chdir (const TCHAR *path); +/* Create a sub directory */ +FRESULT f_mkdir (const TCHAR *path); +/* Rename/Move a file or directory */ +FRESULT f_rename (const TCHAR *path_old, const TCHAR *path_new); +/* Delete an existing file or directory */ +FRESULT f_unlink (const TCHAR *path); +/* check whether get to the end of file */ +FRESULT f_eof(FIL *fp ); + +//uint32 SD_Fs_Init(void); +uint32 Media_Fs_Init(uint8 type); +uint16 get_musicfile_count(void); +FILE_INFO *get_file_info(void); +FIL *Get_File_From_Number(uint16 number); + +#ifndef EOF +#define EOF (-1) +#endif + + /*--------------------------------------------------------------*/ + /* Additional user defined functions */ + void mem_cpy (void *dst, const void *src, uint32 cnt); + + /* Unicode support functions */ +#if _USE_LFN + /* Unicode - OEM code conversion */ + /* OEM-Unicode bidirectional conversion */ + WCHAR ff_convert (WCHAR chr, uint32 dir); + /* Unicode upper-case conversion */ + WCHAR ff_wtoupper (WCHAR chr); +#endif + + + /* Definitions of sector size */ +#if (_MAX_SS < _MIN_SS) + || (_MAX_SS != 512 && _MAX_SS != 1024 && _MAX_SS != 2048 && _MAX_SS != 4096) + || (_MIN_SS != 512 && _MIN_SS != 1024 && _MIN_SS != 2048 && _MIN_SS != 4096) +#error Wrong sector size configuration. +#endif +#if _MAX_SS == _MIN_SS +#define SS(fs) ((uint32)_MAX_SS) /* Fixed sector size */ +#else +#define SS(fs) ((fs)->ssize) /* Variable sector size */ +#endif + + /*--------------------------------------------------------------*/ + /* Flags and offset address */ + /* File access control and file status flags (FIL.flag) */ +#define FA_READ 0x01 +#define FA_WRITE 0x02 +#define FA_OPEN_EXISTING 0x00 +#define FA_CREATE_NEW 0x04 +#define FA_CREATE_ALWAYS 0x08 +#define FA_OPEN_ALWAYS 0x10 +#define FA_OPEN_APPEND 0x30 + + /* FAT sub type (FATFS.fs_type) */ +#define FS_FAT12 1 +#define FS_FAT16 2 +#define FS_FAT32 3 +#define FS_ExFAT 4 + + /* File attribute bits for directory entry */ +#define AM_RDO 0x01 /* Read only */ +#define AM_HID 0x02 /* Hidden */ +#define AM_SYS 0x04 /* System */ +#define AM_VOL 0x08 /* Volume label */ +#define AM_LFN 0x0F /* LFN entry */ +#define AM_DIR 0x10 /* Directory */ +#define AM_ARC 0x20 /* Archive */ +#define AM_MASK 0x3F /* Mask of defined bits */ + + /* Fast seek feature */ +#define CREATE_LINKMAP 0xFFFFFFFF + + /* Name status flags */ +#define NS 11 /* Index of name status byte in fn[] */ +#define NS_LOSS 0x01 /* Out of 8.3 format */ +#define NS_LFN 0x02 /* Force to create LFN entry */ +#define NS_LAST 0x04 /* Last segment */ +#define NS_BODY 0x08 /* Lower case flag (body) */ +#define NS_EXT 0x10 /* Lower case flag (ext) */ +#define NS_DOT 0x20 /* Dot entry */ + + + /*FAT32/16 */ +#define BS_jmpBoot 0 /* Jump instruction (3) */ +#define BS_OEMName 3 /* OEM name (8) */ +#define BPB_BytsPerSec 11 /* Sector size [byte] (2) */ +#define BPB_SecPerClus 13 /* Cluster size [sector] (1) */ +#define BPB_RsvdSecCnt 14 /* Size of reserved area [sector] (2) */ +#define BPB_NumFATs 16 /* Number of FAT copies (1) */ +#define BPB_RootEntCnt 17 /* Number of root directory entries for FAT12/16 (2) */ +#define BPB_TotSec16 19 /* Volume size [sector] (2) */ +#define BPB_Media 21 /* Media descriptor (1) */ +#define BPB_FATSz16 22 /* FAT size [sector] (2) */ +#define BPB_SecPerTrk 24 /* Track size [sector] (2) */ +#define BPB_NumHeads 26 /* Number of heads (2) */ +#define BPB_HiddSec 28 /* Number of special hidden sectors (4) */ +#define BPB_TotSec32 32 /* Volume size [sector] (4) */ +#define BS_DrvNum 36 /* Physical drive number (2) */ +#define BS_BootSig 38 /* Extended boot signature (1) */ +#define BS_VolID 39 /* Volume serial number (4) */ +#define BS_VolLab 43 /* Volume label (8) */ +#define BS_FilSysType 54 /* File system type (1) */ +#define BPB_FATSz32 36 /* FAT size [sector] (4) */ +#define BPB_ExtFlags 40 /* Extended flags (2) */ +#define BPB_FSVer 42 /* File system version (2) */ +#define BPB_RootClus 44 /* Root directory first cluster (4) */ +#define BPB_FSInfo 48 /* Offset of FSINFO sector (2) */ +#define BPB_BkBootSec 50 /* Offset of backup boot sector (2) */ +#define BS_DrvNum32 64 /* Physical drive number (2) */ +#define BS_BootSig32 66 /* Extended boot signature (1) */ +#define BS_VolID32 67 /* Volume serial number (4) */ +#define BS_VolLab32 71 /* Volume label (8) */ +#define BS_FilSysType32 82 /* File system type (1) */ +#define FSI_LeadSig 0 /* FSI: Leading signature (4) */ +#define FSI_StrucSig 484 /* FSI: Structure signature (4) */ +#define FSI_Free_Count 488 /* FSI: Number of free clusters (4) */ +#define FSI_Nxt_Free 492 /* FSI: Last allocated cluster (4) */ +#define MBR_Table 446 /* MBR: Partition table offset (2) */ +#define SZ_PTE 16 /* MBR: Size of a partition table entry */ +#define BS_55AA 510 /* Signature word (2) */ + +#define DIR_Name 0 /* Short file name (11) */ +#define DIR_Attr 11 /* Attribute (1) */ +#define DIR_NTres 12 /* NT flag (1) */ +#define DIR_CrtTimeTenth 13 /* Created time sub-second (1) */ +#define DIR_CrtTime 14 /* Created time (2) */ +#define DIR_CrtDate 16 /* Created date (2) */ +#define DIR_LstAccDate 18 /* Last accessed date (2) */ +#define DIR_FstClusHI 20 /* Higher 16-bit of first cluster (2) */ +#define DIR_WrtTime 22 /* Modified time (2) */ +#define DIR_WrtDate 24 /* Modified date (2) */ +#define DIR_FstClusLO 26 /* Lower 16-bit of first cluster (2) */ +#define DIR_FileSize 28 /* File size (4) */ +#define LDIR_Ord 0 /* LFN entry order and LLE flag (1) */ +#define LDIR_Attr 11 /* LFN attribute (1) */ +#define LDIR_Type 12 /* LFN type (1) */ +#define LDIR_Chksum 13 /* Sum of corresponding SFN entry */ +#define LDIR_FstClusLO 26 /* Filled by zero (0) */ +#define SZ_DIR 32 /* Size of a directory entry */ +#define LLE 0x40 /* Last long entry flag in LDIR_Ord */ +#define DDE 0xE5 /* Deleted directory entry mark in DIR_Name[0] */ +#define NDDE 0x05 /* Replacement of the character collides with DDE */ + + + /*Exfat*/ +#define BPB_ExFatName 0x04 /*xfat string*/ +#define BPB_ExFatOffset 0x50 /*fat offset*/ +#define BPB_ExFatLength 0x54 /*fat length*/ +#define BPB_ExClusHPOffset 0x58 /*cluster Heap Offset*/ +#define BPB_ExClusterCnt 0x5c /*cluster count*/ +#define BPB_ExRootDirBase 0x60 /*root dir cluster*/ +#define BPB_ExBytePerSecSft 0x6c /*bytes per sector shift */ +#define BPB_ExSecPerClusSft 0x6d /*sectors per cluster shift */ +#define BPB_ExNumofFATs 0x6e /*number of fat*/ + +#define FILE_DIR_ENTRY 0x85 +#define STREAM_EXT_DIR_ENT 0xc0 +#define FILE_NAME_DIR_ENTRY 0xc1 + +#define ExFat_Dir_Attr 0x04 // byte + +#define ExFat_NoChainFlag 0x01 +#define ExFat_DataLength 0x08 +#define ExFat_FirstCluster 0x14 +#define ExFat_NameLength 0x03 // 1byte, unicode uint + + /*--------------------------------*/ + /* Multi-byte word access macros */ + /* Use byte-by-byte access to the FAT structure */ +#define LD_WORD(ptr) (uint16) \ + (((uint16)*((uint8*)(ptr)+1)<<8) \ + |(uint16)*(uint8*)(ptr)) + +#define LD_DWORD(ptr) (uint32) \ + (((uint32)*((uint8*)(ptr)+3)<<24) \ + |((uint32)*((uint8*)(ptr)+2)<<16) \ + |((uint16)*((uint8*)(ptr)+1)<<8) \ + |*(uint8*)(ptr)) + +#define ST_WORD(ptr,val) \ + *(uint8*)(ptr)=(uint8)(val); \ + *((uint8*)(ptr)+1)=(uint8)((uint16)(val)>>8) + +#define ST_DWORD(ptr,val) \ + *(uint8*)(ptr)=(uint8)(val); \ + *((uint8*)(ptr)+1)=(uint8)((uint16)(val)>>8); \ + *((uint8*)(ptr)+2)=(uint8)((uint32)(val)>>16); \ + *((uint8*)(ptr)+3)=(uint8)((uint32)(val)>>24) + +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* _FATFS */ + + +#if CFG_USE_USB_HOST +/*----------------------------------------------------------------------------/ +/ FatFs - Generic FAT file system module R0.12c / +/-----------------------------------------------------------------------------/ +/ +/ Copyright (C) 2017, ChaN, all right reserved. +/ +/ FatFs module is an open source software. Redistribution and use of FatFs in +/ source and binary forms, with or without modification, are permitted provided +/ that the following condition is met: + +/ 1. Redistributions of source code must retain the above copyright notice, +/ this condition and the following disclaimer. +/ +/ This software is provided by the copyright holder and contributors "AS IS" +/ and any warranties related to this software are DISCLAIMED. +/ The copyright owner or contributors be NOT LIABLE for any damages caused +/ by use of this software. +/----------------------------------------------------------------------------*/ + + +#ifndef _FATFS +#define _FATFS 68300 /* Revision ID */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "integer.h" /* Basic integer types */ + //#include "types.h" +#include "ffconf.h" /* FatFs configuration options */ + //#include"syscall.h" + //#include"ccsbcs.h" + +#if _FATFS != _FFCONF +#error Wrong configuration file (ffconf.h). +#endif + + + + /* Definitions of volume management */ + +#if _MULTI_PARTITION /* Multiple partition configuration */ + typedef struct + { + BYTE pd; /* Physical drive number */ + BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */ + } PARTITION; + extern PARTITION VolToPart[]; /* Volume - Partition resolution table */ +#endif + + + + /* Type of path name strings on FatFs API */ + +#if _LFN_UNICODE /* Unicode (UTF-16) string */ +#if _USE_LFN == 0 +#error _LFN_UNICODE must be 0 at non-LFN cfg. +#endif +#ifndef _INC_TCHAR + typedef WCHAR TCHAR; +#define _T(x) L ## x +#define _TEXT(x) L ## x +#endif +#else /* ANSI/OEM string */ +#ifndef _INC_TCHAR + typedef char TCHAR; +#define _T(x) x +#define _TEXT(x) x +#endif +#endif + + + + /* Type of file size variables */ + +#if _FS_EXFAT +#if _USE_LFN == 0 +#error LFN must be enabled when enable exFAT +#endif + typedef QWORD FSIZE_t; +#else + typedef DWORD FSIZE_t; +#endif + + typedef struct _fat_file_info_s + { + char filename[13]; + char ext_name[3]; + uint32 file_start_cluster; + uint32 file_blks; + } fat_file_info_t; + + + + typedef struct + { + uint32 fcluster; + char fname[13]; /* Short file name (8.3 format) */ + char extname[3]; + // uint8 ExNoChainFlag;//exfat flag + uint8 fat_ok_flag; + uint16 Reserved1; + } FILE_INFO; + + //*app struct*/ + //add by wangxuejun + + typedef struct + { + uint32 first_cluster; + uint16 music_total; + uint8 broot_dir; + uint8 ExNoChainFlag; + } FAT_DIR_INFO; + + + //add by wangxuejun + typedef struct + { + uint32 cluster_number; + uint16 dirlevel; + uint8 broot_dir; + uint8 ExNoChainFlag; + } DIR_QUEUE; + //add by wangxuejun + + + + + + + /* File system object structure (FATFS) */ + + typedef struct + { + BYTE fs_type; /* File system type (0:N/A) */ + BYTE drv; /* Physical drive number */ + BYTE n_fats; /* Number of FATs (1 or 2) */ + BYTE wflag; /* win[] flag (b0:dirty) */ + BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */ + WORD id; /* File system mount ID */ + WORD n_rootdir; /* Number of root directory entries (FAT12/16) */ + WORD csize; /* Cluster size [sectors] */ +#if _MAX_SS != _MIN_SS + WORD ssize; /* Sector size (512, 1024, 2048 or 4096) */ +#endif +#if _USE_LFN != 0 + WCHAR *lfnbuf; /* LFN working buffer */ +#endif +#if _FS_EXFAT + BYTE *dirbuf; /* Directory entry block scratchpad buffer */ +#endif +#if _FS_REENTRANT + _SYNC_t sobj; /* Identifier of sync object */ +#endif +#if !_FS_READONLY + DWORD last_clst; /* Last allocated cluster */ + DWORD free_clst; /* Number of free clusters */ +#endif +#if _FS_RPATH != 0 + DWORD cdir; /* Current directory start cluster (0:root) */ +#if _FS_EXFAT + DWORD cdc_scl; /* Containing directory start cluster (invalid when cdir is 0) */ + DWORD cdc_size; /* b31-b8:Size of containing directory, b7-b0: Chain status */ + DWORD cdc_ofs; /* Offset in the containing directory (invalid when cdir is 0) */ +#endif +#endif + DWORD n_fatent; /* Number of FAT entries (number of clusters + 2) */ + DWORD fsize; /* Size of an FAT [sectors] */ + DWORD volbase; /* Volume base sector */ + DWORD fatbase; /* FAT base sector */ + DWORD dirbase; /* Root directory base sector/cluster */ + DWORD database; /* Data base sector */ + DWORD winsect; /* Current sector appearing in the win[] */ + BYTE win[_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */ + } FATFS; + + + + /* Object ID and allocation information (_FDID) */ + + typedef struct + { + FATFS *fs; /* Pointer to the owner file system object */ + WORD id; /* Owner file system mount ID */ + BYTE attr; /* Object attribute */ + BYTE stat; /* Object chain status (b1-0: =0:not contiguous, =2:contiguous (no data on FAT), =3:flagmented in this session, b2:sub-directory stretched) */ + DWORD sclust; /* Object start cluster (0:no cluster or root directory) */ + FSIZE_t objsize; /* Object size (valid when sclust != 0) */ +#if _FS_EXFAT + DWORD n_cont; /* Size of first fragment, clusters - 1 (valid when stat == 3) */ + DWORD n_frag; /* Size of last fragment needs to be written (valid when not zero) */ + DWORD c_scl; /* Containing directory start cluster (valid when sclust != 0) */ + DWORD c_size; /* b31-b8:Size of containing directory, b7-b0: Chain status (valid when c_scl != 0) */ + DWORD c_ofs; /* Offset in the containing directory (valid when sclust != 0 and non-directory object) */ +#endif +#if _FS_LOCK != 0 + UINT lockid; /* File lock ID origin from 1 (index of file semaphore table Files[]) */ +#endif + } _FDID; + + + + /* File object structure (FIL) */ + + typedef struct + { + _FDID obj; /* Object identifier (must be the 1st member to detect invalid object pointer) */ + BYTE flag; /* File status flags */ + BYTE err; /* Abort flag (error code) */ + FSIZE_t fptr; /* File read/write pointer (Zeroed on file open) */ + DWORD clust; /* Current cluster of fpter (invalid when fptr is 0) */ + DWORD sect; /* Sector number appearing in buf[] (0:invalid) */ +#if !_FS_READONLY + DWORD dir_sect; /* Sector number containing the directory entry */ + BYTE *dir_ptr; /* Pointer to the directory entry in the win[] */ +#endif +#if _USE_FASTSEEK + DWORD *cltbl; /* Pointer to the cluster link map table (nulled on open, set by application) */ +#endif +#if !_FS_TINY + BYTE buf[_MAX_SS]; /* File private data read/write window */ +#endif + } FIL; + + + + /* Directory object structure (DIR) */ + + typedef struct + { + _FDID obj; /* Object identifier */ + DWORD dptr; /* Current read/write offset */ + DWORD clust; /* Current cluster */ + DWORD sect; /* Current sector (0:Read operation has terminated) */ + BYTE *dir; /* Pointer to the directory item in the win[] */ + BYTE fn[12]; /* SFN (in/out) {body[8],ext[3],status[1]} */ +#if _USE_LFN != 0 + DWORD blk_ofs; /* Offset of current entry block being processed (0xFFFFFFFF:Invalid) */ +#endif +#if _USE_FIND + const TCHAR *pat; /* Pointer to the name matching pattern */ +#endif + } DIR; + + + + /* File information structure (FILINFO) */ + + typedef struct + { + FSIZE_t fsize; /* File size */ + WORD fdate; /* Modified date */ + WORD ftime; /* Modified time */ + BYTE fattrib; /* File attribute */ +#if _USE_LFN != 0 + TCHAR altname[13]; /* Altenative file name */ + TCHAR fname[_MAX_LFN + 1]; /* Primary file name */ +#else + TCHAR fname[13]; /* File name */ +#endif + } FILINFO; + + + /* File status structure (FILINFO) */ + typedef struct + { + uint32 fsize; /* File size */ + uint16 fdate; /* Last modified date */ + uint16 ftime; /* Last modified time */ + uint8 fattrib; /* Attribute */ + TCHAR fname[13]; /* Short file name (8.3 format) */ + + uint8 ExNoChainFlag; // + uint8 reserved; + uint32 fcluster; +#if _USE_LFN + TCHAR *lfname; /* Pointer to the LFN buffer */ + uint32 lfsize; /* Size of LFN buffer in TCHAR */ +#endif + } FILINFOADD, *PFILINFOADD; + + + + /* File function return code (FRESULT) */ + + typedef enum + { + FR_OK = 0, /* (0) Succeeded */ + FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */ + FR_INT_ERR, /* (2) Assertion failed */ + FR_NOT_READY, /* (3) The physical drive cannot work */ + FR_NO_FILE, /* (4) Could not find the file */ + FR_NO_PATH, /* (5) Could not find the path */ + FR_INVALID_NAME, /* (6) The path name format is invalid */ + FR_DENIED, /* (7) Access denied due to prohibited access or directory full */ + FR_EXIST, /* (8) Access denied due to prohibited access */ + FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */ + FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */ + FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */ + FR_NOT_ENABLED, /* (12) The volume has no work area */ + FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */ + FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any problem */ + FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */ + FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */ + FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */ + FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > _FS_LOCK */ + FR_INVALID_PARAMETER /* (19) Given parameter is invalid */ + } FRESULT; + + + + /*--------------------------------------------------------------*/ + /* FatFs module application interface */ + + FRESULT f_open (FIL *fp, const TCHAR *path, BYTE mode); /* Open or create a file */ + FRESULT f_close (FIL *fp); /* Close an open file object */ + FRESULT f_read (FIL *fp, void *buff, UINT btr, UINT *br); /* Read data from the file */ + FRESULT f_write (FIL *fp, const void *buff, UINT btw, UINT *bw); /* Write data to the file */ + FRESULT f_lseek (FIL *fp, FSIZE_t ofs); /* Move file pointer of the file object */ + FRESULT f_truncate (FIL *fp); /* Truncate the file */ + FRESULT f_sync (FIL *fp); /* Flush cached data of the writing file */ + FRESULT f_opendir (DIR *dp, const TCHAR *path); /* Open a directory */ + FRESULT f_closedir (DIR *dp); /* Close an open directory */ + FRESULT f_readdir (DIR *dp, FILINFO *fno); /* Read a directory item */ + FRESULT f_findfirst (DIR *dp, FILINFO *fno, const TCHAR *path, const TCHAR *pattern); /* Find first file */ + FRESULT f_findnext (DIR *dp, FILINFO *fno); /* Find next file */ + FRESULT f_mkdir (const TCHAR *path); /* Create a sub directory */ + FRESULT f_unlink (const TCHAR *path); /* Delete an existing file or directory */ + FRESULT f_rename (const TCHAR *path_old, const TCHAR *path_new); /* Rename/Move a file or directory */ + FRESULT f_stat (const TCHAR *path, FILINFO *fno); /* Get file status */ + FRESULT f_chmod (const TCHAR *path, BYTE attr, BYTE mask); /* Change attribute of a file/dir */ + FRESULT f_utime (const TCHAR *path, const FILINFO *fno); /* Change timestamp of a file/dir */ + FRESULT f_chdir (const TCHAR *path); /* Change current directory */ + FRESULT f_chdrive (const TCHAR *path); /* Change current drive */ + FRESULT f_getcwd (TCHAR *buff, UINT len); /* Get current directory */ + FRESULT f_getfree (const TCHAR *path, DWORD *nclst, FATFS **fatfs); /* Get number of free clusters on the drive */ + FRESULT f_getlabel (const TCHAR *path, TCHAR *label, DWORD *vsn); /* Get volume label */ + FRESULT f_setlabel (const TCHAR *label); /* Set volume label */ + FRESULT f_forward (FIL *fp, UINT(*func)(const BYTE *, UINT), UINT btf, UINT *bf); /* Forward data to the stream */ + FRESULT f_expand (FIL *fp, FSIZE_t szf, BYTE opt); /* Allocate a contiguous block to the file */ + FRESULT f_mount (FATFS *fs, const TCHAR *path, BYTE opt); /* Mount/Unmount a logical drive */ + FRESULT f_mkfs (const TCHAR *path, BYTE opt, DWORD au, void *work, UINT len); /* Create a FAT volume */ + FRESULT f_fdisk (BYTE pdrv, const DWORD *szt, void *work); /* Divide a physical drive into some partitions */ + int f_putc (TCHAR c, FIL *fp); /* Put a character to the file */ + int f_puts (const TCHAR *str, FIL *cp); /* Put a string to the file */ + int f_printf (FIL *fp, const TCHAR *str, ...); /* Put a formatted string to the file */ + TCHAR *f_gets (TCHAR *buff, int len, FIL *fp); /* Get a string from the file */ + + + + + +#define f_eof(fp) ((int)((fp)->fptr == (fp)->obj.objsize)) +#define f_error(fp) ((fp)->err) +#define f_tell(fp) ((fp)->fptr) +#define f_size(fp) ((fp)->obj.objsize) +#define f_rewind(fp) f_lseek((fp), 0) +#define f_rewinddir(dp) f_readdir((dp), 0) +#define f_rmdir(path) f_unlink(path) + +#ifndef EOF +#define EOF (-1) +#endif + + + + + /*--------------------------------------------------------------*/ + /* Additional user defined functions */ + + /* RTC function */ +#if !_FS_READONLY && !_FS_NORTC + DWORD get_fattime (void); +#endif + + /* Unicode support functions */ +#if _USE_LFN != 0 /* Unicode - OEM code conversion */ + //WCHAR ff_convert (WCHAR chr, UINT dir); /* OEM-Unicode bidirectional conversion */ + //WCHAR ff_wtoupper (WCHAR chr); /* Unicode upper-case conversion */ +#if _CODE_PAGE < 900 +#include"ccsbcs.h" +#elif (_CODE_PAGE == 936) +#include"cc936.h" +#endif + //#include"ccsbcs.c" +#if _USE_LFN == 3 /* Memory functions */ + //void* ff_memalloc (UINT msize); /* Allocate memory block */ + //void ff_memfree (void* mblock); /* Free memory block */ +#include"syscall.h" +#endif + +#endif + + + + + /* Sync functions */ +#if _FS_REENTRANT + int ff_cre_syncobj (BYTE vol, _SYNC_t *sobj); /* Create a sync object */ + int ff_req_grant (_SYNC_t sobj); /* Lock sync object */ + void ff_rel_grant (_SYNC_t sobj); /* Unlock sync object */ + int ff_del_syncobj (_SYNC_t sobj); /* Delete a sync object */ +#endif + + + + + /*--------------------------------------------------------------*/ + /* Flags and offset address */ + + + /* File access mode and open method flags (3rd argument of f_open) */ +#define FA_READ 0x01 +#define FA_WRITE 0x02 +#define FA_OPEN_EXISTING 0x00 +#define FA_CREATE_NEW 0x04 +#define FA_CREATE_ALWAYS 0x08 +#define FA_OPEN_ALWAYS 0x10 +#define FA_OPEN_APPEND 0x30 + + /* Fast seek controls (2nd argument of f_lseek) */ +#define CREATE_LINKMAP ((FSIZE_t)0 - 1) + + /* Format options (2nd argument of f_mkfs) */ +#define FM_FAT 0x01 +#define FM_FAT32 0x02 +#define FM_EXFAT 0x04 +#define FM_ANY 0x07 +#define FM_SFD 0x08 + + /* Filesystem type (FATFS.fs_type) */ +#define FS_FAT12 1 +#define FS_FAT16 2 +#define FS_FAT32 3 +#define FS_EXFAT 4 + + /* File attribute bits for directory entry (FILINFO.fattrib) */ +#define AM_RDO 0x01 /* Read only */ +#define AM_HID 0x02 /* Hidden */ +#define AM_SYS 0x04 /* System */ +#define AM_DIR 0x10 /* Directory */ +#define AM_ARC 0x20 /* Archive */ + + +#if 1 + + // void mem_set (void* dst, int val, UINT cnt); + + //void mem_cpy (void* dst, const void* src, UINT cnt); + + /* Move to zero only writes back dirty window */ + + + FRESULT f_lseek ( + FIL *fp, /* Pointer to the file object */ + FSIZE_t ofs /* File pointer from top of file */ + ); + //*/ + + FRESULT move_window ( + FATFS *fs, /* File system object */ + DWORD sector /* Sector number to make apperance in the fs->win[] */ + ); /* Move to zero only writes back dirty window */ + + FRESULT f_EOF(FIL *fp); /*decide the end of an file*/ + + FRESULT dir_seek ( + DIR *dj, /* Pointer to directory object */ + uint16 idx /* Directory index number */ + ); + + FRESULT chk_mounted_con (FATFS *rfs, uint8 type); + +#endif + + +#ifdef __cplusplus +} +#endif + +#endif /* _FATFS */ + +#endif +#endif // _FF_HEADER_FILE_ +// eof \ No newline at end of file diff --git a/beken_os/beken378/func/fatfs/ffconf.h b/beken_os/beken378/func/fatfs/ffconf.h new file mode 100755 index 0000000..b4a6fb2 --- /dev/null +++ b/beken_os/beken378/func/fatfs/ffconf.h @@ -0,0 +1,323 @@ + +#include "include.h" + +#if CFG_USE_SDCARD_HOST +#ifndef _FFCONF +#define _FFCONF 7211 /* Revision ID */ + +#define _USE_LFN 0 /* 0 to 3 */ +#define _MAX_LFN 255 /* Maximum LFN length to handle (12 to 255) */ +#define _LFN_UNICODE 0 /* 0:ANSI/OEM or 1:Unicode */ +#define _VOLUMES 2 +#define _MIN_SS 512 +#define _MAX_SS 512 +#define _FS_REENTRANT 0 /* 0:Disable or 1:Enable */ + +typedef unsigned char uint8; /* ޷8λͱ */ +typedef signed char int8; /* з8λͱ */ +typedef unsigned short uint16; /* ޷16λͱ */ +typedef signed short int16; /* з16λͱ */ +typedef unsigned int uint32; /* ޷32λͱ */ +typedef signed int int32; /* з32λͱ */ +typedef float fp32; /* ȸ32λȣ */ +typedef double fp64; /* ˫ȸ64λȣ */ +typedef unsigned long long uint64; +typedef long long int64; + +typedef unsigned char u_int8; /* ޷8λͱ */ +typedef unsigned short u_int16; /* ޷16λͱ */ +typedef unsigned int u_int32; /* ޷32λͱ */ + +#endif + +#endif + + +#if CFG_USE_USB_HOST +/*---------------------------------------------------------------------------/ +/ FatFs - FAT file system module configuration file +/---------------------------------------------------------------------------*/ + +#include "integer.h" /* Basic integer types */ + +#define _FFCONF 68300 /* Revision ID */ + +/*---------------------------------------------------------------------------/ +/ Function Configurations +/---------------------------------------------------------------------------*/ + +#define _FS_READONLY 0 +/* This option switches read-only configuration. (0:Read/Write or 1:Read-only) +/ Read-only configuration removes writing API functions, f_write(), f_sync(), +/ f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree() +/ and optional writing functions as well. */ + + +#define _FS_MINIMIZE 0 +/* This option defines minimization level to remove some basic API functions. +/ +/ 0: All basic functions are enabled. +/ 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename() +/ are removed. +/ 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1. +/ 3: f_lseek() function is removed in addition to 2. */ + + +#define _USE_STRFUNC 0 +/* This option switches string functions, f_gets(), f_putc(), f_puts() and +/ f_printf(). +/ +/ 0: Disable string functions. +/ 1: Enable without LF-CRLF conversion. +/ 2: Enable with LF-CRLF conversion. */ + + +#define _USE_FIND 1 +/* This option switches filtered directory read functions, f_findfirst() and +/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */ + + +#define _USE_MKFS 1 +/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */ + + +#define _USE_FASTSEEK 0 +/* This option switches fast seek function. (0:Disable or 1:Enable) */ + + +#define _USE_EXPAND 0 +/* This option switches f_expand function. (0:Disable or 1:Enable) */ + + +#define _USE_CHMOD 0 +/* This option switches attribute manipulation functions, f_chmod() and f_utime(). +/ (0:Disable or 1:Enable) Also _FS_READONLY needs to be 0 to enable this option. */ + + +#define _USE_LABEL 0 +/* This option switches volume label functions, f_getlabel() and f_setlabel(). +/ (0:Disable or 1:Enable) */ + + +#define _USE_FORWARD 1 +/* This option switches f_forward() function. (0:Disable or 1:Enable) */ + + +/*---------------------------------------------------------------------------/ +/ Locale and Namespace Configurations +/---------------------------------------------------------------------------*/ + +#define _CODE_PAGE 437 //old one is 932 +/* This option specifies the OEM code page to be used on the target system. +/ Incorrect setting of the code page can cause a file open failure. +/ +/ 1 - ASCII (No support of extended character. Non-LFN cfg. only) +/ 437 - U.S. +/ 720 - Arabic +/ 737 - Greek +/ 771 - KBL +/ 775 - Baltic +/ 850 - Latin 1 +/ 852 - Latin 2 +/ 855 - Cyrillic +/ 857 - Turkish +/ 860 - Portuguese +/ 861 - Icelandic +/ 862 - Hebrew +/ 863 - Canadian French +/ 864 - Arabic +/ 865 - Nordic +/ 866 - Russian +/ 869 - Greek 2 +/ 932 - Japanese (DBCS) +/ 936 - Simplified Chinese (DBCS) +/ 949 - Korean (DBCS) +/ 950 - Traditional Chinese (DBCS) +*/ + + +#define _USE_LFN 2 +#define _MAX_LFN 127 // old 255 +/* The _USE_LFN switches the support of long file name (LFN). +/ +/ 0: Disable support of LFN. _MAX_LFN has no effect. +/ 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe. +/ 2: Enable LFN with dynamic working buffer on the STACK. +/ 3: Enable LFN with dynamic working buffer on the HEAP. +/ +/ To enable the LFN, Unicode handling functions (option/unicode.c) must be added +/ to the project. The working buffer occupies (_MAX_LFN + 1) * 2 bytes and +/ additional 608 bytes at exFAT enabled. _MAX_LFN can be in range from 12 to 255. +/ It should be set 255 to support full featured LFN operations. +/ When use stack for the working buffer, take care on stack overflow. When use heap +/ memory for the working buffer, memory management functions, ff_memalloc() and +/ ff_memfree(), must be added to the project. */ + + +#define _LFN_UNICODE 0 +/* This option switches character encoding on the API. (0:ANSI/OEM or 1:UTF-16) +/ To use Unicode string for the path name, enable LFN and set _LFN_UNICODE = 1. +/ This option also affects behavior of string I/O functions. */ + + +#define _STRF_ENCODE 3 +/* When _LFN_UNICODE == 1, this option selects the character encoding ON THE FILE to +/ be read/written via string I/O functions, f_gets(), f_putc(), f_puts and f_printf(). +/ +/ 0: ANSI/OEM +/ 1: UTF-16LE +/ 2: UTF-16BE +/ 3: UTF-8 +/ +/ This option has no effect when _LFN_UNICODE == 0. */ + + +#define _FS_RPATH 0 +/* This option configures support of relative path. +/ +/ 0: Disable relative path and remove related functions. +/ 1: Enable relative path. f_chdir() and f_chdrive() are available. +/ 2: f_getcwd() function is available in addition to 1. +*/ + + +/*---------------------------------------------------------------------------/ +/ Drive/Volume Configurations +/---------------------------------------------------------------------------*/ + +#define _VOLUMES 3 +/* Number of volumes (logical drives) to be used. (1-10) */ + + +#define _STR_VOLUME_ID 0 +#define _VOLUME_STRS "RAM","NAND","CF","SD","SD2","USB","USB2","USB3" +/* _STR_VOLUME_ID switches string support of volume ID. +/ When _STR_VOLUME_ID is set to 1, also pre-defined strings can be used as drive +/ number in the path name. _VOLUME_STRS defines the drive ID strings for each +/ logical drives. Number of items must be equal to _VOLUMES. Valid characters for +/ the drive ID strings are: A-Z and 0-9. */ + + +#define _MULTI_PARTITION 0 +/* This option switches support of multi-partition on a physical drive. +/ By default (0), each logical drive number is bound to the same physical drive +/ number and only an FAT volume found on the physical drive will be mounted. +/ When multi-partition is enabled (1), each logical drive number can be bound to +/ arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk() +/ funciton will be available. */ + + +#define _MIN_SS 512 +#define _MAX_SS 512 +/* These options configure the range of sector size to be supported. (512, 1024, +/ 2048 or 4096) Always set both 512 for most systems, generic memory card and +/ harddisk. But a larger value may be required for on-board flash memory and some +/ type of optical media. When _MAX_SS is larger than _MIN_SS, FatFs is configured +/ to variable sector size and GET_SECTOR_SIZE command needs to be implemented to +/ the disk_ioctl() function. */ + + +#define _USE_TRIM 0 +/* This option switches support of ATA-TRIM. (0:Disable or 1:Enable) +/ To enable Trim function, also CTRL_TRIM command should be implemented to the +/ disk_ioctl() function. */ + + +#define _FS_NOFSINFO 0 +/* If you need to know correct free space on the FAT32 volume, set bit 0 of this +/ option, and f_getfree() function at first time after volume mount will force +/ a full FAT scan. Bit 1 controls the use of last allocated cluster number. +/ +/ bit0=0: Use free cluster count in the FSINFO if available. +/ bit0=1: Do not trust free cluster count in the FSINFO. +/ bit1=0: Use last allocated cluster number in the FSINFO if available. +/ bit1=1: Do not trust last allocated cluster number in the FSINFO. +*/ + + + +/*---------------------------------------------------------------------------/ +/ System Configurations +/---------------------------------------------------------------------------*/ + +#define _FS_TINY 0 +/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny) +/ At the tiny configuration, size of file object (FIL) is shrinked _MAX_SS bytes. +/ Instead of private sector buffer eliminated from the file object, common sector +/ buffer in the file system object (FATFS) is used for the file data transfer. */ + + +#define _FS_EXFAT 1 +/* This option switches support of exFAT file system. (0:Disable or 1:Enable) +/ When enable exFAT, also LFN needs to be enabled. (_USE_LFN >= 1) +/ Note that enabling exFAT discards ANSI C (C89) compatibility. */ + + +#define _FS_NORTC 0 +#define _NORTC_MON 1 +#define _NORTC_MDAY 1 +#define _NORTC_YEAR 2016 +/* The option _FS_NORTC switches timestamp functiton. If the system does not have +/ any RTC function or valid timestamp is not needed, set _FS_NORTC = 1 to disable +/ the timestamp function. All objects modified by FatFs will have a fixed timestamp +/ defined by _NORTC_MON, _NORTC_MDAY and _NORTC_YEAR in local time. +/ To enable timestamp function (_FS_NORTC = 0), get_fattime() function need to be +/ added to the project to get current time form real-time clock. _NORTC_MON, +/ _NORTC_MDAY and _NORTC_YEAR have no effect. +/ These options have no effect at read-only configuration (_FS_READONLY = 1). */ + + +#define _FS_LOCK 0 +/* The option _FS_LOCK switches file lock function to control duplicated file open +/ and illegal operation to open objects. This option must be 0 when _FS_READONLY +/ is 1. +/ +/ 0: Disable file lock function. To avoid volume corruption, application program +/ should avoid illegal open, remove and rename to the open objects. +/ >0: Enable file lock function. The value defines how many files/sub-directories +/ can be opened simultaneously under file lock control. Note that the file +/ lock control is independent of re-entrancy. */ + + +#define _FS_REENTRANT 0 +#define _FS_TIMEOUT 1000 +#define _SYNC_t HANDLE +/* The option _FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs +/ module itself. Note that regardless of this option, file access to different +/ volume is always re-entrant and volume control functions, f_mount(), f_mkfs() +/ and f_fdisk() function, are always not re-entrant. Only file/directory access +/ to the same volume is under control of this function. +/ +/ 0: Disable re-entrancy. _FS_TIMEOUT and _SYNC_t have no effect. +/ 1: Enable re-entrancy. Also user provided synchronization handlers, +/ ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj() +/ function, must be added to the project. Samples are available in +/ option/syscall.c. +/ +/ The _FS_TIMEOUT defines timeout period in unit of time tick. +/ The _SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*, +/ SemaphoreHandle_t and etc. A header file for O/S definitions needs to be +/ included somewhere in the scope of ff.h. */ + +/* #include // O/S definitions */ + + +typedef unsigned char uint8; /* ޷8λͱ */ +typedef signed char int8; /* з8λͱ */ +typedef unsigned short uint16; /* ޷16λͱ */ +typedef signed short int16; /* з16λͱ */ +typedef unsigned int uint32; /* ޷32λͱ */ +typedef signed int int32; /* з32λͱ */ +typedef float fp32; /* ȸ32λȣ */ +typedef double fp64; /* ˫ȸ64λȣ */ +typedef unsigned long long uint64; +typedef long long int64; + +typedef unsigned char u_int8; /* ޷8λͱ */ +typedef unsigned short u_int16; /* ޷16λͱ */ +typedef unsigned int u_int32; /* ޷32λͱ */ + + +/*--- End of configuration options ---*/ + +#endif diff --git a/beken_os/beken378/func/fatfs/integer.h b/beken_os/beken378/func/fatfs/integer.h new file mode 100755 index 0000000..d882d21 --- /dev/null +++ b/beken_os/beken378/func/fatfs/integer.h @@ -0,0 +1,28 @@ +/*-------------------------------------------*/ +/* Integer type definitions for FatFs module */ +/*-------------------------------------------*/ + +#ifndef _FF_INTEGER_ +#define _FF_INTEGER_ + +/* These types MUST be 16-bit or 32-bit */ +typedef int INT; +typedef unsigned int UINT; + +/* This type MUST be 8-bit */ +typedef unsigned char BYTE; + +/* These types MUST be 16-bit */ +typedef short SHORT; +typedef unsigned short WORD; +typedef unsigned short WCHAR; + +/* These types MUST be 32-bit */ +typedef long LONG; +typedef unsigned long DWORD; + +/* This type MUST be 64-bit (Remove this for ANSI C (C89) compatibility) */ +typedef unsigned long long QWORD; + +#endif // _FF_INTEGER_ +// eof diff --git a/beken_os/beken378/func/fatfs/playmode.c b/beken_os/beken378/func/fatfs/playmode.c new file mode 100755 index 0000000..34ff3d8 --- /dev/null +++ b/beken_os/beken378/func/fatfs/playmode.c @@ -0,0 +1,519 @@ +#include "diskio.h" /* Declarations of low level disk I/O functions */ +#if CFG_USE_SDCARD_HOST +#include "ff.h" + +#define MAX_DIR_SUPPORT 1024 +#define MAX_SONG_DIR 64 // 128 +#define MAX_DIR_LEVEL 6 + +FILE_INFO FileInfo; +char *MP3_Ext = ".MP3"; +char *WAV_Ext = ".WAV"; +FAT_DIR_INFO file_queue[MAX_SONG_DIR]; +uint16 mp3queuecount = 0; //MP3ļļĿ +uint16 mp3filecount = 0;// MP3ܵĿ +FATFS Fatfs_buf; +FIL fsFD; +DIR_QUEUE *point_front;//ͷָ +DIR_QUEUE *point_rear;//βָ +static uint16 rear_cnt = 0; + +DIR_QUEUE g_dirbuf[MAX_DIR_SUPPORT]; + +extern void mem_set (void *dst, int val, uint32 cnt); +extern FRESULT chk_mounted_con (FATFS *rfs, uint8 chk_wp); + +int strcmpi (const void *dst, const void *src, int cnt) +{ + const char *d = (const char *)dst, *s = (const char *)src; + int r = 0; + while (cnt-- && (r = *d++ - *s++) == 0) ; + return r; +} + +char *strrchr_con(char *str, char ch) +{ + char *p = (char *)str; + while (*str) str++; + while ((str-- != p) && (*str != ch)); + if (*str == ch) + return( (char *)str ); + return NULL; +} +static void Convert2UpperCase(char *str, uint32 len) +{ + uint32 i; + for(i = 0; i < len; i++) + ((str[i] <= 'z') && (str[i] >= 'a')) ? (str[i] -= 0x20) : str[i]; +} + + +FRESULT f_open_con ( + FIL *fp, /* Pointer to the blank file object */ + PFILINFOADD finfo, + uint8 mode /* Access mode and file open mode flags */ +) +{ + fp->flag = mode; /* File access mode */ + fp->org_clust = finfo->fcluster;/* File start cluster */ + fp->fsize = finfo->fsize; /* File size */ + fp->fptr = 0; + fp->csect = 255; /* File pointer */ + fp->dsect = 0; + fp->fs = &Fatfs_buf; + fp->id = Fatfs_buf.id; /* Owner file system object of the file */ + fp->ExNoChainFlag = finfo->ExNoChainFlag; + return FR_OK; +} + +//// +FRESULT fl_listatdir(DIR *dj_con, PFILINFOADD fi_con, uint16 idx) +{ + int i; + uint8 c, *dir; + char *p; + FRESULT ret = FR_NO_FILE; + /*for exfat use*/ + static uint8 DirEntryAttr = 0; + static uint8 no_fat_chain_Flag = 0; + static uint8 ExtNameStartFlag = 0; + static uint8 exfat_name_length = 0; + static uint8 extname_idx = 0; + static char ext_name[3]; + static uint32 exfat_first_cluster = 0; + static uint32 exfat_file_size = 0; + static uint16 exfat_entry_phase = 0; + uint32 tmp = 0; + + dj_con->dir = dj_con->fs->win + (idx % (SS(dj_con->fs) / 32)) * 32; + dir = dj_con->dir; + + if(dj_con->fs->fs_type == FS_ExFAT) + { + switch (dir[0]) + { + case FILE_DIR_ENTRY: + if(exfat_entry_phase == 0) + { + DirEntryAttr = dir[ExFat_Dir_Attr] & 0x3f; //get file attribute + exfat_entry_phase++; + } + ret = FR_NO_FILE; + break; + + case STREAM_EXT_DIR_ENT: + if(exfat_entry_phase == 1) + { + exfat_first_cluster = LD_DWORD(dir + ExFat_FirstCluster); + exfat_file_size = LD_DWORD(dir + ExFat_DataLength); //Byte unit + exfat_name_length = dir[ExFat_NameLength]; + no_fat_chain_Flag = dir[ExFat_NoChainFlag]; + extname_idx = 0; + ExtNameStartFlag = 0; + exfat_entry_phase++; + } + ret = FR_NO_FILE; + break; + + case FILE_NAME_DIR_ENTRY: + if(exfat_entry_phase == 2 ) + { + if(exfat_name_length < 19) + { + tmp = (exfat_name_length > 15) ? 15 : exfat_name_length; + for(i = 0; i < tmp; i++) + { + if(ExtNameStartFlag) + { + ext_name[extname_idx] = (char)dir[(i + 1) << 1]; + extname_idx++; + + } + else + { + + if((dir[(i + 1) << 1] == '.') && (dir[((i + 1) << 1) + 1] == 0)) + ExtNameStartFlag = 1; + } + } + exfat_name_length -= tmp; + } + else + exfat_name_length -= 15; + + if(exfat_name_length == 0) + { + /*all file name directory entries have been handled*/ + mem_set(fi_con->fname, ' ', 13); + Convert2UpperCase(ext_name, 3); + mem_cpy(&fi_con->fname[9], ext_name, 3); + fi_con->fname[0] = '*'; + fi_con->fname[8] = '.';//for our usage , ignore the name + fi_con->fname[12] = '\0'; + + fi_con->fattrib = DirEntryAttr; /* Attribute */ + fi_con->fsize = exfat_file_size; /* Size */ + fi_con->fcluster = exfat_first_cluster;/*file start cluster*/ + fi_con->ExNoChainFlag = no_fat_chain_Flag; + exfat_entry_phase = 0; + ret = FR_OK; + } + else + ret = FR_NO_FILE; + } + break; + case 0: + ret = FR_EXIST; + break; + default: + exfat_entry_phase = 0; + ret = FR_NO_FILE; + break; + } + } + else + { + p = fi_con->fname; + + if ((dir[0] == 0xE5) || (dir[0] == 0x05) || (dir[0] == 0x20) || (dir[0] == '.') + || (dir[DIR_Attr] == 0x0f)) + return FR_NO_FILE; + + if (dir[0] == 0x00) + return FR_EXIST; + + for (i = 0; i < 8; i++) + { + /* Copy name body */ + c = dir[i]; + *p++ = c; + } + fi_con->fname[8] = ' '; + fi_con->fname[9] = ' '; + fi_con->fname[10] = ' '; + fi_con->fname[11] = ' '; + if (dir[8] != ' ') + { + /* Copy name extension */ + *p++ = '.'; + for (i = 8; i < 11; i++) + { + c = dir[i]; + if (c == ' ') + break; + *p++ = c; + } + } + fi_con->fname[12] = '\0'; + fi_con->fattrib = dir[DIR_Attr]; /* Attribute */ + fi_con->fsize = LD_DWORD(dir + DIR_FileSize); /* Size */ + fi_con->fdate = LD_WORD(dir + DIR_WrtDate); /* Date */ + fi_con->ftime = LD_WORD(dir + DIR_WrtTime); /* Time */ + fi_con->fcluster = ((uint32)LD_WORD(dir + DIR_FstClusHI) << 16) | LD_WORD(dir + DIR_FstClusLO); + ret = FR_OK; + } + return ret; +} + +static FRESULT get_curdir_info(DIR_QUEUE *p_front) +{ + uint16 idx = 0; + uint16 cur_musicfile = 0; + uint16 ic, dc; + FRESULT ret; + DIR dj; + FILINFOADD fl_curnode; + char *Ext = NULL; + char *Ext1 = NULL; + + dj.fs = &Fatfs_buf; + dj.ExNoChainFlag = p_front->ExNoChainFlag; + + dc = SS(dj.fs) / 32;//entry count per sector + ic = SS(dj.fs) / 32 * dj.fs->csize;//entry count per cluster + if(p_front->broot_dir) + dj.sclust = 0;//for Fat16 + else + dj.sclust = p_front ->cluster_number; + + os_printf("get_curdir_info\r\n"); + while(1) + { + if((idx % ic) == 0) //new cluster + { + ret = dir_seek(&dj, idx); + if (ret != FR_OK) + break; + } + + if((idx % dc) == 0) //new sector + { + if((idx % ic) != 0) //not cluster boundary + dj.sect++; + ret = move_window(dj.fs, dj.sect); + if (ret != FR_OK) + break; + + } + + ret = fl_listatdir(&dj, &fl_curnode, idx); + idx++; + + if(ret == FR_OK) + { + if((fl_curnode.fattrib & 0x10) != 0) + { + point_rear->cluster_number = fl_curnode.fcluster; + point_rear->dirlevel = p_front->dirlevel + 1; + point_rear->broot_dir = 0; + point_rear->ExNoChainFlag = fl_curnode.ExNoChainFlag; + rear_cnt++; + if(rear_cnt > MAX_DIR_SUPPORT - 1) + break; + point_rear++; + + } + if((fl_curnode.fattrib & 0x20) != 0) /*ֻءϵͳļ֧*/ + { + Ext = fl_curnode.fname; + os_printf("get_curdir_info: fl_curnode.fname = \"%s\"\r\n", Ext); + Ext1 = strrchr_con(Ext, '.'); + if (!strcmpi(Ext1, MP3_Ext, 4)) + cur_musicfile++; + else + { + if(!strcmpi(Ext1, WAV_Ext, 4)) + cur_musicfile++; + } + + } + } + + if(ret == FR_NO_FILE) + continue; + + if(ret == FR_EXIST) + break; + }//while(1) + if (cur_musicfile) + { + file_queue[mp3queuecount].first_cluster = p_front->cluster_number; + file_queue[mp3queuecount].music_total = cur_musicfile; + file_queue[mp3queuecount].broot_dir = p_front->broot_dir; + file_queue[mp3queuecount].ExNoChainFlag = p_front->ExNoChainFlag; + mp3queuecount++; + mp3filecount += cur_musicfile; + } + return FR_OK; +} + +/*input: +i -- directory index +number -- music file idx in directory i */ +static FIL *GetFile_From_NumInDir(uint16 i, uint16 number) +{ + uint16 idx = 0; + uint16 ic, dc, brootdir, music_count; + FRESULT ret; + FILINFOADD fl_curnode; + char *Ext = NULL; + char *Ext1 = NULL; + DIR dj_con; + + FIL *fio = &fsFD; + + dj_con.fs = &Fatfs_buf; + brootdir = file_queue[i].broot_dir; + if(brootdir) + dj_con.sclust = 0; + else + dj_con.sclust = file_queue[i].first_cluster; + + dc = SS(dj_con.fs) / 32; + ic = SS(dj_con.fs) / 32 * dj_con.fs->csize; + music_count = 0; + number += 1; + + while(1) + { + if((idx % ic) == 0) + { + ret = dir_seek(&dj_con, idx); + if (ret != FR_OK) + return NULL; + } + if((idx % dc) == 0) + { + if((idx % ic) != 0) + dj_con.sect++; + ret = move_window(dj_con.fs, dj_con.sect); + if (ret != FR_OK) + return NULL; + } + + ret = fl_listatdir(&dj_con, &fl_curnode, idx); + idx++; + + if(ret == FR_OK) + { + if((fl_curnode.fattrib & 0x20) != 0) /*ֻءϵͳļ֧*/ + { + Ext = fl_curnode.fname; + Ext1 = strrchr_con(Ext, '.'); + if (!strcmpi(Ext1, MP3_Ext, 4)) + music_count++; + else + { + if (!strcmpi(Ext1, WAV_Ext, 4)) + music_count++; + } + } + } + + if (music_count == number) + break; + + if(ret == FR_NO_FILE) + continue; + + if(ret == FR_EXIST) + return NULL; + } + FileInfo.fcluster = fl_curnode.fcluster; + mem_cpy(FileInfo.fname, fl_curnode.fname, 12); + mem_cpy(FileInfo.extname, FileInfo.fname + 9, 3); + f_open_con(fio, &fl_curnode, FA_READ); + + return fio; +} + + +/*input:number -- 0~mp3filecount-1 */ +//Playlist_GetSongFileInfo +FIL *Get_File_From_Number(uint16 number) +{ + uint16 i; + FIL *fhFile; + + for(i = 0; i < MAX_SONG_DIR; i++) + { + if(number >= file_queue[i].music_total) + { + number = number - file_queue[i].music_total; + continue; + } + else + break; + } + if(i == MAX_SONG_DIR) + return NULL; + fhFile = GetFile_From_NumInDir(i, number); + return fhFile; +} + +/*scan whole disk, get total music file number and store the DIRs info +which have music files +*/ +static uint32 initfatsystem(uint8 type) +{ + int count = 0, ret; + DIR_QUEUE *dir_buf; + rear_cnt = 0; + if((ret = chk_mounted_con(&Fatfs_buf, type)) != FR_OK) + { + FAT_PRT("Fat Init Err:%d!!!\r\n", ret); + return 1; + } +#if 1 + //if(driver_sdcard_get_init_status()) + { + //dir_buf=(DIR_QUEUE*)jmalloc(MAX_DIR_SUPPORT*sizeof(DIR_QUEUE),0);//ֵ֧ļ + //if(!dir_buf) + // return -1; + dir_buf = &g_dirbuf[0]; + + mem_set(file_queue, 0, MAX_SONG_DIR * sizeof(FAT_DIR_INFO)); + mp3filecount = 0; + mp3queuecount = 0; + point_front = point_rear = dir_buf; + + point_front ->cluster_number = Fatfs_buf.dirbase; + point_front ->dirlevel = 0; + point_front ->ExNoChainFlag = 0; + + if (Fatfs_buf.fs_type == FS_FAT16) + point_front ->broot_dir = 1; + else + point_front ->broot_dir = 0; + + point_rear++; + rear_cnt++; + while(1) + { + if ((mp3queuecount < MAX_SONG_DIR) + && (point_front ->dirlevel < MAX_DIR_LEVEL) + && (point_front != point_rear) + && (count < MAX_DIR_SUPPORT)) + { + if(rear_cnt > MAX_DIR_SUPPORT - 1) + break; + + get_curdir_info(point_front); + count++; + point_front++; + } + else + break; + } + + FAT_PRT("count=%d mp3queuecount=%d mp3filecount=%d,rear_cnt =%d\r\n", count, mp3queuecount, mp3filecount, rear_cnt); + //driver_sdcard_set_init_status(0); + //jfree(dir_buf); + // dir_buf = NULL; + } +#endif + return 0; +} + +/*Sd card & filesystem initialization*/ +//uint32 SD_Fs_Init(void) +uint32 Media_Fs_Init(uint8 type) +{ + uint32 ret = 1; + FileInfo.fat_ok_flag = 0; + if(f_mount(1, &Fatfs_buf) == FR_OK) + { + if(initfatsystem(type) == FR_OK) + { + FileInfo.fat_ok_flag = 1; + ret = 0; + } + } + return ret; +} + +uint8 get_fat_ok_flag(void) +{ + return FileInfo.fat_ok_flag; +} + +uint16 get_musicfile_count(void) +{ + return mp3filecount; +} +FILE_INFO *get_file_info(void) +{ + return (&FileInfo); +} + +uint8 get_disk_type(void) +{ + return Fatfs_buf.drive; +} + +#endif + + +#if CFG_USE_USB_HOST +#endif + diff --git a/beken_os/beken378/func/fatfs/test_fatfs.c b/beken_os/beken378/func/fatfs/test_fatfs.c new file mode 100755 index 0000000..b46601a --- /dev/null +++ b/beken_os/beken378/func/fatfs/test_fatfs.c @@ -0,0 +1,201 @@ +#include +#include +#include "include.h" +#include "diskio.h" +#include "test_fatfs.h" +#include "mem_pub.h" +#include "ff.h" + +#define WR_RD_BUF_SIZE 1024 +#define TEST_MP3_FILE_NAME "/Panama_Matteo.mp3" +#define TEST_TXT_FILE_NAME "/test1.txt" +#define TEST_TXT_FILE_NAME1 "/ֿж೤೤Ͷ೤ҧңҳԷ.txt" + +#if CFG_USE_USB_HOST +FATFS *pfs = NULL; + +FRESULT scan_files +( + char *path /* Start node to be scanned (***also used as work area***) */ +) +{ + FRESULT fr; + DIR dir; + FILINFO fno; + + fr = f_opendir(&dir, path); /* Open the directory */ + if (fr == FR_OK) + { + os_printf("%s/\r\n", path); + while (1) + { + fr = f_readdir(&dir, &fno); /* Read a directory item */ + if (fr != FR_OK) + { + break; /* Break on error */ + } + if (fno.fname[0] == 0) + { + break; /* Break on end of dir */ + } + if (fno.fattrib & AM_DIR) + { + /* It is a directory */ + char pathTemp[255]; + sprintf(pathTemp, "%s/%s", path, fno.fname); + fr = scan_files(pathTemp); /* Enter the directory */ + if (fr != FR_OK) break; + } + else + { + /* It is a file. */ + os_printf("%s/%s\r\n", path, fno.fname); + } + } + f_closedir(&dir); + } + else + { + os_printf("f_opendir failed\r\n"); + } + + return fr; +} + +void test_mount(DISK_NUMBER number) +{ + FRESULT fr; + char cFileName[_MAX_LFN]; + + if (pfs != NULL) + { + os_free(pfs); + } + + pfs = os_malloc(sizeof(FATFS)); + if(NULL == pfs) + { + os_printf("f_mount malloc failed!\r\n"); + goto failed_mount; + } + + sprintf(cFileName, "%d:", number); + fr = f_mount(pfs, cFileName, 1); + if (fr != FR_OK) + { + os_printf("f_mount failed:%d\r\n", fr); + } + else + { + os_printf("f_mount OK!\r\n"); + } + +failed_mount: + os_printf("----- test_mount %d over -----\r\n\r\n", number); +} + +void scan_file_system(DISK_NUMBER number) +{ + FRESULT fr; + char cFileName[_MAX_LFN]; + + os_printf("\r\n----- scan_file_system %d start -----\r\n", number); + + sprintf(cFileName, "%d:", number); + fr = scan_files(cFileName); + if (fr != FR_OK) + { + os_printf("scan_files failed!\r\n"); + } + else + { + os_printf("scan_files OK!\r\n"); + } + + os_printf("----- scan_file_system %d over -----\r\n\r\n", number); +} + +void test_fatfs(DISK_NUMBER number) +{ + char cFileName[_MAX_LFN]; + FIL file; + FRESULT fr; + + os_printf("\r\n----- test_fatfs %d start -----\r\n", number); + sprintf(cFileName, "%d:%s", number, TEST_MP3_FILE_NAME); + os_printf("f_open \"%s\"\r\n", cFileName); + fr = f_open(&file, cFileName, FA_OPEN_EXISTING | FA_READ); + if (fr == FR_OK) + { + unsigned int uiTemp = 0; + unsigned int uiRdTotalLength = 0; + unsigned char ucRdTemp[WR_RD_BUF_SIZE]; + + do + { + os_printf("."); + fr = f_read(&file, ucRdTemp, WR_RD_BUF_SIZE, &uiTemp); + if (fr == FR_OK) + { + } + else + { + os_printf("f_read failed 1 fr = %d\r\n", fr); + goto error1; + } + uiRdTotalLength += uiTemp; + } + while (uiTemp == WR_RD_BUF_SIZE); + os_printf("\r\n"); + os_printf("f_read: read total byte = %d\r\n", uiRdTotalLength); + + fr = f_close(&file); + if (fr != FR_OK) + { + os_printf("f_close failed 1 fr = %d\r\n", fr); + goto error1; + } + else + { + os_printf("f_close OK\r\n"); + } + } + else + { + os_printf("f_open failed 1 fr = %d\r\n", fr); + } + + os_printf("----- test_fatfs %d over -----\r\n\r\n", number); + return; + +error1: + f_close(&file); +error0: + os_printf("----- test_fatfs %d failed -----\r\n\r\n", number); +} + +void test_fatfs_format(DISK_NUMBER number) +{ + FRESULT fr; + char cFileName[_MAX_LFN]; + unsigned char ucRdTemp[WR_RD_BUF_SIZE]; + + os_printf("----- test_fatfs_format %d start -----\r\n", number); + + sprintf(cFileName, "%d:", number); + fr = f_mkfs(cFileName, FM_FAT, 65536, ucRdTemp, WR_RD_BUF_SIZE); + if (fr != FR_OK) + { + os_printf("f_mkfs failed!\r\n"); + } + else + { + os_printf("f_mkfs OK!\r\n"); + } + + os_printf("----- test_fatfs_format %d over -----\r\n", number); +} +#endif + +// eof + diff --git a/beken_os/beken378/func/fatfs/test_fatfs.h b/beken_os/beken378/func/fatfs/test_fatfs.h new file mode 100755 index 0000000..b7283fa --- /dev/null +++ b/beken_os/beken378/func/fatfs/test_fatfs.h @@ -0,0 +1,39 @@ +/************************************************************* + * @file test_fatfs.h + * @brief Header file of test_fatfs.c + * @author GuWenFu + * @version V1.0 + * @date 2016-09-29 + * @par + * @attention + * + * @history 2016-09-29 gwf create this file + */ + +#ifndef __TEST_FATFS_H__ + +#define __TEST_FATFS_H__ + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +#include "diskio.h" + + +#if CFG_USE_USB_HOST + extern void test_mount(DISK_NUMBER number); + extern void scan_file_system(DISK_NUMBER number); + extern void test_fatfs(DISK_NUMBER number); + extern void test_fatfs_format(DISK_NUMBER number); +#endif + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __TEST_FATFS_H__ */ diff --git a/beken_os/beken378/func/func.c b/beken_os/beken378/func/func.c new file mode 100755 index 0000000..5ecff44 --- /dev/null +++ b/beken_os/beken378/func/func.c @@ -0,0 +1,136 @@ +#include "include.h" +#include "func_pub.h" +#include "intc.h" +#include "rwnx.h" +#include "uart_pub.h" +#include "param_config.h" +#include "saradc_pub.h" + +#if CFG_ROLE_LAUNCH +#include "role_launch.h" +#endif + +#if CFG_SUPPORT_CALIBRATION +#include "bk7011_cal_pub.h" +#endif + +#if CFG_UART_DEBUG +#include "uart_debug_pub.h" +#endif + +#if CFG_SDIO +#include "sdio_intf_pub.h" +#endif + +#if CFG_USB +#include "fusb_pub.h" +#endif +#include "start_type_pub.h" +#include "BkDriverFlash.h" + +UINT32 func_init_extended(void) +{ + char temp_mac[6]; + + cfg_param_init(); + // load mac, init mac first + wifi_get_mac_address(temp_mac, CONFIG_ROLE_NULL); + + manual_cal_load_bandgap_calm(); + //FUNC_PRT("[FUNC]rwnxl_init\r\n"); + rwnxl_init(); + +#if CFG_UART_DEBUG + #ifndef KEIL_SIMULATOR + FUNC_PRT("[FUNC]uart_debug_init\r\n"); + uart_debug_init(); + #endif +#endif + +#if (!CFG_SUPPORT_RTT) + FUNC_PRT("[FUNC]intc_init\r\n"); + intc_init(); +#endif + +#if CFG_SUPPORT_CALIBRATION + UINT32 is_tab_inflash = 0; + FUNC_PRT("[FUNC]calibration_main\r\n"); + calibration_main(); + #if CFG_SUPPORT_MANUAL_CALI + is_tab_inflash = manual_cal_load_txpwr_tab_flash(); + manual_cal_load_default_txpwr_tab(is_tab_inflash); + #endif + #if CFG_SARADC_CALIBRATE + manual_cal_load_adc_cali_flash(); + #endif + #if CFG_USE_TEMPERATURE_DETECT + manual_cal_load_temp_tag_flash(); + #endif + + #if (CFG_SOC_NAME != SOC_BK7231) + manual_cal_load_lpf_iq_tag_flash(); + manual_cal_load_xtal_tag_flash(); + #endif // (CFG_SOC_NAME != SOC_BK7231) + + rwnx_cal_initial_calibration(); + + #if CFG_SUPPORT_MANUAL_CALI + if (0)//(is_tab_inflash == 0) + { + manual_cal_fitting_txpwr_tab(); + manual_cal_save_chipinfo_tab_to_flash(); + manual_cal_save_txpwr_tab_to_flash(); + } + #endif // CFG_SUPPORT_MANUAL_CALI +#if (CFG_SUPPORT_BLE && (CFG_SOC_NAME == SOC_BK7231N)) + extern void ble_update_tx_pwr(void); + ble_update_tx_pwr(); +#endif +#endif + +#if CFG_SDIO + FUNC_PRT("[FUNC]sdio_intf_init\r\n"); + sdio_intf_init(); +#endif + +#if CFG_SDIO_TRANS + FUNC_PRT("[FUNC]sdio_intf_trans_init\r\n"); + sdio_trans_init(); +#endif + + +#if CFG_USB + FUNC_PRT("[FUNC]fusb_init\r\n"); + fusb_init(); +#endif + +#if CFG_USE_STA_PS + //FUNC_PRT("[FUNC]ps_init\r\n"); +#endif + +#if CFG_ROLE_LAUNCH + rl_init(); +#endif + + #if CFG_ENABLE_BUTTON + key_initialization(); + #endif + +#ifdef BEKEN_START_WDT + bk_wdg_initialize(10000); +#endif + + FUNC_PRT("[FUNC]func_init_extended OVER\r\n"); + os_null_printf("start_type:%d\r\n",bk_misc_get_start_type()); + return 0; +} + +UINT32 func_init_basic(void) +{ + intc_init(); + hal_flash_init(); + + return 0; +} + +// eof diff --git a/beken_os/beken378/func/hostapd-2.5/bk_patch/ddrv.c b/beken_os/beken378/func/hostapd-2.5/bk_patch/ddrv.c new file mode 100755 index 0000000..aa72328 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/bk_patch/ddrv.c @@ -0,0 +1,50 @@ +#include "include.h" +#include "ddrv.h" + +#include "sk_intf.h" +#include "ieee802_11_defs.h" +#include "driver_beken.h" +#include "hostapd_intf_pub.h" + +int ioctl_host_ap(unsigned int cmd, unsigned long arg) +{ + int ret = 0; + switch(cmd) + { + case PRISM2_IOCTL_HOSTAPD: + ret = hapd_intf_ioctl(arg); + break; + + case PRISM2_IOCTL_PRISM2_PARAM: + break; + + case SIOCSIWESSID: + break; + + case SIOCGIWRANGE: + break; + + case SIOCSIWFREQ: + break; + + default: + break; + } + + return ret; +} + +int ioctl_inet(int dev, u8 vif_index, unsigned int cmd, unsigned long arg) +{ + int ret = 0; + + if(ioctl_get_socket_num(vif_index) == dev) + { + ret = ioctl_host_ap(cmd, arg); + } + + return ret; +} + +// eof + diff --git a/beken_os/beken378/func/hostapd-2.5/bk_patch/ddrv.h b/beken_os/beken378/func/hostapd-2.5/bk_patch/ddrv.h new file mode 100755 index 0000000..5dbc05b --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/bk_patch/ddrv.h @@ -0,0 +1,19 @@ +#ifndef _DDRV_H_ +#define _DDRV_H_ + +/* These 32 ioctl are wireless device private, for 16 commands. + * Each driver is free to use them for whatever purpose it chooses, + * however the driver *must* export the description of those ioctls + * with SIOCGIWPRIV and *must* use arguments as defined below. + * If you don't follow those rules, DaveM is going to hate you (reason : + * it make mixed 32/64bit operation impossible). + */ +#define SIOCIWFIRSTPRIV 0x8BE0 +#define SIOCIWLASTPRIV 0x8BFF + +extern int ioctl_inet(int dev, u8 vif_index, unsigned int cmd, unsigned long arg); +extern void exit(int seconds); + +#endif +// eof + diff --git a/beken_os/beken378/func/hostapd-2.5/bk_patch/errno-base.h b/beken_os/beken378/func/hostapd-2.5/bk_patch/errno-base.h new file mode 100755 index 0000000..6e851d3 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/bk_patch/errno-base.h @@ -0,0 +1,160 @@ +#ifndef _ASM_GENERIC_ERRNO_BASE_H +#define _ASM_GENERIC_ERRNO_BASE_H + +#define ERRPERM 1 /* Operation not permitted */ +#define ERRNOENT 2 /* No such file or directory */ +#define ERRSRCH 3 /* No such process */ +#define ERRINTR 4 /* Interrupted system call */ +#define EERIO 5 /* I/O error */ +#define ERRNXIO 6 /* No such device or address */ +#define ERR2BIG 7 /* Argument list too long */ +#define ERRNOEXEC 8 /* Exec format error */ +#define ERRBADF 9 /* Bad file number */ +#define ERRCHILD 10 /* No child processes */ +#define ERRAGAIN 11 /* Try again */ +#define ERRNOMEM 12 /* Out of memory */ +#define ERRACCES 13 /* Permission denied */ +#define ERRFAULT 14 /* Bad address */ +#define ERRNOTBLK 15 /* Block device required */ +#define ERRBUSY 16 /* Device or resource busy */ +#define ERREXIST 17 /* File exists */ +#define ERRXDEV 18 /* Cross-device link */ +#define ERRNODEV 19 /* No such device */ +#define ERRNOTDIR 20 /* Not a directory */ +#define ERRISDIR 21 /* Is a directory */ +#define ERRINVAL 22 /* Invalid argument */ +#define ERRNFILE 23 /* File table overflow */ +#define ERRMFILE 24 /* Too many open files */ +#define ERRNOTTY 25 /* Not a typewriter */ +#define ERRTXTBSY 26 /* Text file busy */ +#define ERRFBIG 27 /* File too large */ +#define ERRNOSPC 28 /* No space left on device */ +#define ERRSPIPE 29 /* Illegal seek */ +#define ERRROFS 30 /* Read-only file system */ +#define ERRMLINK 31 /* Too many links */ +#define ERRPIPE 32 /* Broken pipe */ +#define ERRDOM 33 /* Math argument out of domain of func */ +#define ERRRANGE 34 /* Math result not representable */ + + +#define ERRNOMSG 35 /* No message of desired type */ +#define ERRIDRM 36 /* Identifier removed */ +#define ERRCHRNG 37 /* Channel number out of range */ +#define ERRL2NSYNC 38 /* Level 2 not synchronized */ +#define ERRL3HLT 39 /* Level 3 halted */ +#define ERRL3RST 40 /* Level 3 reset */ +#define ERRLNRNG 41 /* Link number out of range */ +#define ERRUNATCH 42 /* Protocol driver not attached */ +#define ERRNOCSI 43 /* No CSI structure available */ +#define ERRL2HLT 44 /* Level 2 halted */ +#define ERRDEADLK 45 /* Resource deadlock would occur */ +#define ERRDEADLOCK ERRDEADLK +#define ERRNOLCK 46 /* No record locks available */ +#define ERRILSEQ 47 /* Illegal byte sequence */ + +#define ERRNONET 50 /* Machine is not on the network */ +#define ERRNODATA 51 /* No data available */ +#define ERRTIME 52 /* Timer expired */ +#define ERRNOSR 53 /* Out of streams resources */ +#define ERRNOSTR 54 /* Device not a stream */ +#define ERRNOPKG 55 /* Package not installed */ + +#define ERRNOLINK 57 /* Link has been severed */ +#define ERRADV 58 /* Advertise error */ +#define ERRSRMNT 59 /* Srmount error */ +#define ERRCOMM 60 /* Communication error on send */ +#define ERRPROTO 61 /* Protocol error */ + +#define ERRMULTIHOP 64 /* Multihop attempted */ + +#define ERRDOTDOT 66 /* RFS specific error */ +#define ERRBADMSG 67 /* Not a data message */ +#define ERRUSERS 68 /* Too many users */ +#define ERRDQUOT 69 /* Quota exceeded */ +#define ERRSTALE 70 /* Stale NFS file handle */ +#define ERRREMOTE 71 /* Object is remote */ +#define ERROVERFLOW 72 /* Value too large for defined data type */ + +/* these errnos are defined by Linux but not HPUX. */ +#define ERRBADE 160 /* Invalid exchange */ +#define ERRBADR 161 /* Invalid request descriptor */ +#define ERRXFULL 162 /* Exchange full */ +#define ERRNOANO 163 /* No anode */ +#define ERRBADRQC 164 /* Invalid request code */ +#define ERRBADSLT 165 /* Invalid slot */ +#define ERRBFONT 166 /* Bad font file format */ +#define ERRNOTUNIQ 167 /* Name not unique on network */ +#define ERRBADFD 168 /* File descriptor in bad state */ +#define ERRREMCHG 169 /* Remote address changed */ +#define ERRLIBACC 170 /* Can not access a needed shared library */ +#define ERRLIBBAD 171 /* Accessing a corrupted shared library */ +#define ERRLIBSCN 172 /* .lib section in a.out corrupted */ +#define ERRLIBMAX 173 /* Attempting to link in too many shared libraries */ +#define ERRLIBEXEC 174 /* Cannot exec a shared library directly */ +#define ERRRESTART 175 /* Interrupted system call should be restarted */ +#define ERRSTRPIPE 176 /* Streams pipe error */ +#define ERRUCLEAN 177 /* Structure needs cleaning */ +#define ERRNOTNAM 178 /* Not a XENIX named type file */ +#define ERRNAVAIL 179 /* No XENIX semaphores available */ +#define ERRISNAM 180 /* Is a named type file */ +#define ERRREMOTEIO 181 /* Remote I/O error */ +#define ERRNOMEDIUM 182 /* No medium found */ +#define ERRMEDIUMTYPE 183 /*Wrong medium type */ +#define ERRNOKEY 184 /* Required key not available */ +#define ERRKEYEXPIRED 185 /* Key has expired */ +#define ERRKEYREVOKED 186 /* Key has been revoked */ +#define ERRKEYREJECTED 187 /* Key was rejected by service */ + +/* We now return you to your regularly scheduled HPUX. */ +#define ERRNOSYM 215 /* symbol does not exist in executable */ +#define ERRNOTSOCK 216 /* Socket operation on non-socket */ +#define ERRDESTADDRREQ 217 /* Destination address required */ +#define ERRMSGSIZE 218 /* Message too long */ +#define ERRPROTOTYPE 219 /* Protocol wrong type for socket */ +#define ERRNOPROTOOPT 220 /* Protocol not available */ +#define ERRPROTONOSUPPORT 221 /* Protocol not supported */ +#define ERRSOCKTNOSUPPORT 222 /* Socket type not supported */ +#define ERROPNOTSUPP 223 /* Operation not supported on transport endpoint */ +#define ERRPFNOSUPPORT 224 /* Protocol family not supported */ +#define ERRAFNOSUPPORT 225 /* Address family not supported by protocol */ +#define ERRADDRINUSE 226 /* Address already in use */ +#define ERRADDRNOTAVAIL 227 /* Cannot assign requested address */ +#define ERRNETDOWN 228 /* Network is down */ +#define ERRNETUNREACH 229 /* Network is unreachable */ +#define ERRNETRESET 230 /* Network dropped connection because of reset */ +#define ERRCONNABORTED 231 /* Software caused connection abort */ +#define ERRCONNRESET 232 /* Connection reset by peer */ +#define ERRNOBUFS 233 /*No buffer space available */ +#define ERRISCONN 234 /*Transport endpoint is already connected */ +#define ERRNOTCONN 235 /* Transport endpoint is not connected */ +#define ERRSHUTDOWN 236 /* Cannot send after transport endpoint shutdown */ +#define ERRTOOMANYREFS 237 /* Too many references: cannot splice */ +#define ERRREFUSED ERRCONNREFUSED /* for HP's NFS apparently */ +#define ERRTIMEDOUT 238 /* Connection timed out */ +#define ERRCONNREFUSED 239 /* Connection refused */ +#define ERRREMOTERELEASE 240 /* Remote peer released connection */ +#define ERRHOSTDOWN 241 /* Host is down */ +#define ERRHOSTUNREACH 242 /* No route to host */ + +#define ERRALREADY 244 /* Operation already in progress */ +#define ERRINPROGRESS 245 /* Operation now in progress */ +#define ERRWOULDBLOCK 246 /* Operation would block (Linux returns EAGAIN) */ +#define ERRNOTEMPTY 247 /* Directory not empty */ +#define ERRNAMETOOLONG 248 /* File name too long */ +#define ERRLOOP 249 /* Too many symbolic links encountered */ +#define ERRNOSYS 251 /* Function not implemented */ + +#define ERRNOTSUP 252 /* Function not implemented (POSIX.4 / HPUX) */ +#define ERRCANCELLED 253 /* aio request was canceled before complete (POSIX.4 / HPUX) */ +#define ERRCANCELED ERRCANCELLED /* SuSv3 and Solaris wants one 'L' */ + +/* for robust mutexes */ +#define ERROWNERDEAD 254 /* Owner died */ +#define ERRNOTRECOVERABLE 255 /* State not recoverable */ + +#define ERRRFKILL 256 /* Operation not possible due to RF-kill */ + +#define ERRHWPOISON 257 /* Memory page has hardware error */ +#endif +// eof + diff --git a/beken_os/beken378/func/hostapd-2.5/bk_patch/fake_socket.c b/beken_os/beken378/func/hostapd-2.5/bk_patch/fake_socket.c new file mode 100755 index 0000000..75736c7 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/bk_patch/fake_socket.c @@ -0,0 +1,438 @@ +#include "include.h" +#include "fake_socket.h" +#include "mem_pub.h" +#include "uart_pub.h" +#include "hostapd_intf_pub.h" +#if CFG_SUPPORT_ALIOS +#include "ll.h" +#endif + +static SOCKET_ENTITY socket_entity = { + DL_LIST_HEAD_INIT(socket_entity.sk_head) +}; + +extern void bmsg_skt_tx_sender(void *arg); + +#if 1 +int ke_sk_send(SOCKET sk, const unsigned char *buf, int len, int flag) +{ + int ret = 0; + unsigned char *data_buf; + BK_SOCKET *element; + SOCKET_MSG *sk_msg; + GLOBAL_INT_DECLARATION(); + + SK_PRT("ke_tx:%d,buf:0x%x, len:%d\r\n", sk, buf, len); + element = sk_get_sk_element(sk); + if(0 == element) + { + goto tx_exit; + } + + sk_msg = (SOCKET_MSG *)os_malloc(sizeof(SOCKET_MSG)); + if(0 == sk_msg) + { + goto tx_exit; + } + data_buf = (unsigned char *)os_malloc(len); + if(0 == data_buf) + { + goto malloc_buf_exit; + } + ret = len; + sk_msg->len = len; + sk_msg->msg = data_buf; + + os_memcpy(sk_msg->msg, buf, len); + + GLOBAL_INT_DISABLE(); + dl_list_add_tail(&element->sk_rx_msg, &sk_msg->data); + GLOBAL_INT_RESTORE(); + + return ret; + +malloc_buf_exit: + os_free(sk_msg); + +tx_exit: + return ret; +} + +int ke_sk_recv(SOCKET sk, const unsigned char *buf, int len, int flag) +{ + int count; + int ret = 0; + BK_SOCKET *element; + SOCKET_MSG *sk_msg, *tmp; + GLOBAL_INT_DECLARATION(); + + SK_PRT("ke_rx:%d,buf:0x%x, len:%d\r\n", sk, buf, len); + element = sk_get_sk_element(sk); + if(0 == element) + { + goto rx_exit; + } + + GLOBAL_INT_DISABLE(); + dl_list_for_each_safe(sk_msg, tmp, &element->sk_tx_msg, SOCKET_MSG, data) + { + count = MIN(sk_msg->len, len); + + ASSERT(count); + ASSERT(sk_msg); + SK_PRT("r1:%d,buf:0x%x, len:%d\r\n", sk, buf, count); + os_memcpy((void *)buf, (void *)sk_msg->msg, count); + + ret = count; + + os_free(sk_msg->msg); + sk_msg->msg = 0; + sk_msg->len = 0; + + dl_list_del(&sk_msg->data); + os_free(sk_msg); + sk_msg = 0; + + break; + } + + GLOBAL_INT_RESTORE(); + return ret; + +rx_exit: + return 0; +} + +int ke_sk_recv_peek_next_payload_size(SOCKET sk) +{ + int ret = 0; + BK_SOCKET *element; + SOCKET_MSG *sk_msg, *tmp; + GLOBAL_INT_DECLARATION(); + + element = sk_get_sk_element(sk); + if(0 == element) + { + goto rx_exit; + } + + GLOBAL_INT_DISABLE(); + dl_list_for_each_safe(sk_msg, tmp, &element->sk_tx_msg, SOCKET_MSG, data) + { + ret = sk_msg->len; + break; + } + + GLOBAL_INT_RESTORE(); + +rx_exit: + return ret; +} + +int ke_sk_send_peek_next_payload_size(SOCKET sk) +{ + int ret = 0; + BK_SOCKET *element; + SOCKET_MSG *sk_msg, *tmp; + GLOBAL_INT_DECLARATION(); + + element = sk_get_sk_element(sk); + if(0 == element) + { + goto rx_exit; + } + + GLOBAL_INT_DISABLE(); + dl_list_for_each_safe(sk_msg, tmp, &element->sk_rx_msg, SOCKET_MSG, data) + { + ret = sk_msg->len; + break; + } + + GLOBAL_INT_RESTORE(); + +rx_exit: + return ret; +} +#endif + +#if 2 +BK_SOCKET *sk_get_sk_element(SOCKET sk) +{ + BK_SOCKET *tmp; + BK_SOCKET *bk_sk_ptr; + GLOBAL_INT_DECLARATION(); + + GLOBAL_INT_DISABLE(); + + dl_list_for_each_safe(bk_sk_ptr, tmp, &socket_entity.sk_head, BK_SOCKET, sk_element) + { + if(sk == bk_sk_ptr->sk) + { + GLOBAL_INT_RESTORE(); + return bk_sk_ptr; + } + } + + GLOBAL_INT_RESTORE(); + return 0; +} + +SOCKET fsocket_init(int af, int type, int protocol) +{ + SOCKET sk; + BK_SOCKET *sk_ptr; + GLOBAL_INT_DECLARATION(); + + sk = af + type + protocol; + //ASSERT(0 == sk_get_sk_element(sk)); + if (0 != sk_get_sk_element(sk)) + { + os_printf("%s sk=%d exist\n", __FUNCTION__, sk); + return sk; + } + + sk_ptr = (BK_SOCKET *)os_malloc(sizeof(BK_SOCKET)); + if(0 == sk_ptr) + { + SK_PRT("create fsocket_init unexceptionally\r\n"); + return 0; + } + + sk_ptr->sk = sk; + + GLOBAL_INT_DISABLE(); + dl_list_init(&sk_ptr->sk_rx_msg); + dl_list_init(&sk_ptr->sk_tx_msg); + + dl_list_add(&socket_entity.sk_head, &sk_ptr->sk_element); + GLOBAL_INT_RESTORE(); + + SK_PRT("create fsocket_init:%d\r\n", sk); + return sk; +} + +int fsocket_send(SOCKET sk, const unsigned char *buf, int len, S_TYPE_PTR type) +{ + int ret = 0; + BK_SOCKET *element; + SOCKET_MSG *sk_msg; + unsigned char *data_buf; + GLOBAL_INT_DECLARATION(); + + SK_PRT("hapd_tx:%d,buf:0x%x, len:%d\r\n", sk, buf, len); + element = sk_get_sk_element(sk); + if(0 == element) + { + goto tx_exit; + } + + sk_msg = (SOCKET_MSG *)os_malloc(sizeof(SOCKET_MSG)); + if(0 == sk_msg) + { + goto tx_exit; + } + + data_buf = (unsigned char *)os_malloc(len); + if(0 == data_buf) + { + goto malloc_buf_exit; + } + ret = len; + sk_msg->len = len; + sk_msg->msg = data_buf; + + os_memcpy(sk_msg->msg, buf, len); + + GLOBAL_INT_DISABLE(); + dl_list_add_tail(&element->sk_tx_msg, &sk_msg->data); + GLOBAL_INT_RESTORE(); + + bmsg_skt_tx_sender(type); + + return ret; + +malloc_buf_exit: + os_free(sk_msg); + +tx_exit: + return ret; +} + +#if FSOCKET_TX_SYNC +int fsocket_send_sync(SOCKET sk, const unsigned char *buf, int len, S_TYPE_PTR type) +{ + int ret = 0; + BK_SOCKET *element; + SOCKET_MSG *sk_msg; + unsigned char *data_buf; + GLOBAL_INT_DECLARATION(); + + SK_PRT("hapd_tx:%d,buf:0x%x, len:%d\r\n", sk, buf, len); + element = sk_get_sk_element(sk); + if(0 == element) + { + goto tx_exit; + } + + sk_msg = (SOCKET_MSG *)os_malloc(sizeof(SOCKET_MSG)); + if(0 == sk_msg) + { + goto tx_exit; + } + + data_buf = (unsigned char *)os_malloc(len); + if(0 == data_buf) + { + goto malloc_buf_exit; + } + ret = len; + sk_msg->len = len; + sk_msg->msg = data_buf; + + os_memcpy(sk_msg->msg, buf, len); + + GLOBAL_INT_DISABLE(); + dl_list_add_tail(&element->sk_tx_msg, &sk_msg->data); + GLOBAL_INT_RESTORE(); + + bmsg_skt_tx_sender(type); + + return ret; + +malloc_buf_exit: + os_free(sk_msg); + +tx_exit: + return ret; +} +#endif + +int fsocket_recv(SOCKET sk, const unsigned char *buf, int len, int flag) +{ + int count; + int ret = 0; + BK_SOCKET *element; + SOCKET_MSG *sk_msg, *tmp; + GLOBAL_INT_DECLARATION(); + + SK_PRT("hapd_rx:%d,buf:0x%x, len:%d\r\n", sk, buf, len); + element = sk_get_sk_element(sk); + if(0 == element) + { + goto rx_exit; + } + + GLOBAL_INT_DISABLE(); + dl_list_for_each_safe(sk_msg, tmp, &element->sk_rx_msg, SOCKET_MSG, data) + { + if(sk_msg->len > len) + { + SK_WPRT("recv_buf_small:%d:%d\r\n", sk_msg->len, len); + } + + count = MIN(sk_msg->len, len); + + ASSERT(count); + ASSERT(sk_msg); + + os_memcpy((void *)buf, (void *)sk_msg->msg, count); + ret = count; + + os_free(sk_msg->msg); + sk_msg->msg = 0; + sk_msg->len = 0; + + dl_list_del(&sk_msg->data); + os_free(sk_msg); + sk_msg = 0; + + break; + } + GLOBAL_INT_RESTORE(); + + return ret; + +rx_exit: + return 0; +} + +void fsocket_close(SOCKET sk) +{ + BK_SOCKET *element; + SOCKET_MSG *sk_msg, *tmp; + GLOBAL_INT_DECLARATION(); + + SK_PRT("close_sk:%d\r\n", sk); + element = sk_get_sk_element(sk); + if(0 == element) + { + return; + } + + GLOBAL_INT_DISABLE(); + dl_list_for_each_safe(sk_msg, tmp, &element->sk_tx_msg, SOCKET_MSG, data) + { + dl_list_del(&sk_msg->data); + + if(sk_msg->msg) + { + os_free(sk_msg->msg); + sk_msg->msg = 0; + sk_msg->len = 0; + } + + os_free(sk_msg); + } + + dl_list_for_each_safe(sk_msg, tmp, &element->sk_rx_msg, SOCKET_MSG, data) + { + dl_list_del(&sk_msg->data); + + if(sk_msg->msg) + { + os_free(sk_msg->msg); + sk_msg->msg = 0; + sk_msg->len = 0; + } + + os_free(sk_msg); + } + + dl_list_del(&element->sk_element); + + os_free(element); + element = 0; + + GLOBAL_INT_RESTORE(); +} + +int fsocket_peek_recv_next_payload_size(SOCKET sk) +{ + int ret = 0; + BK_SOCKET *element; + SOCKET_MSG *sk_msg, *tmp; + GLOBAL_INT_DECLARATION(); + + element = sk_get_sk_element(sk); + if(0 == element) + { + goto rx_exit; + } + + GLOBAL_INT_DISABLE(); + dl_list_for_each_safe(sk_msg, tmp, &element->sk_rx_msg, SOCKET_MSG, data) + { + ret = sk_msg->len; + break; + } + + GLOBAL_INT_RESTORE(); + return ret; + +rx_exit: + return 0; +} +#endif +// eof + diff --git a/beken_os/beken378/func/hostapd-2.5/bk_patch/fake_socket.h b/beken_os/beken378/func/hostapd-2.5/bk_patch/fake_socket.h new file mode 100755 index 0000000..59b024a --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/bk_patch/fake_socket.h @@ -0,0 +1,256 @@ +#ifndef _FAKE_SOCKET_H_ +#define _FAKE_SOCKET_H_ + +#include "list.h" + +//#define SK_DEBUG + +#ifdef SK_DEBUG + #define SK_PRT os_printf + #define SK_WPRT warning_prf +#else + #define SK_PRT os_null_printf + #define SK_WPRT warning_prf +#endif + +typedef int SOCKET; + +typedef struct +{ + struct dl_list data; + + unsigned char *msg; + int len; + +}SOCKET_MSG; + +typedef struct +{ + struct dl_list sk_tx_msg; + struct dl_list sk_rx_msg; + struct dl_list sk_element; + + SOCKET sk; +}BK_SOCKET; + +typedef struct +{ + struct dl_list sk_head; +}SOCKET_ENTITY; + +/** sock_type - Socket types + * + * Please notice that for binary compat reasons MIPS has to + * override the enum sock_type in include/linux/net.h, so + * we define ARCH_HAS_SOCKET_TYPES here. + * + * @SOCK_DGRAM - datagram (conn.less) socket + * @SOCK_STREAM - stream (connection) socket + * @SOCK_RAW - raw socket + * @SOCK_RDM - reliably-delivered message + * @SOCK_SEQPACKET - sequential packet socket + * @SOCK_PACKET - linux specific way of getting packets at the dev level. + * For writing rarp and other similar things on the user level. + */ +enum sock_type { + SOCK_DGRAM = 1, + SOCK_STREAM = 2, + SOCK_RAW = 3, + SOCK_RDM = 4, + SOCK_SEQPACKET = 5, + SOCK_DCCP = 6, + SOCK_PACKET = 10, +}; + +/* + * These 16 ioctls are available to devices via the do_ioctl() device + * vector. Each device should include this file and redefine these names + * as their own. Because these are device dependent it is a good idea + * _NOT_ to issue them to random objects and hope. + * + * THESE IOCTLS ARE _DEPRECATED_ AND WILL DISAPPEAR IN 2.5.X -DaveM + */ + +#define SIOCDEVPRIVATE 0x89F0 /* to 89FF */ + +/* + * These 16 ioctl calls are protocol private + */ + +#define SIOCPROTOPRIVATE 0x89E0 /* to 89EF */ + +typedef unsigned short sa_family_t; + +/* + * 1003.1g requires sa_family_t and that sa_data is char. + */ + +struct sockaddr { + sa_family_t sa_family; /* address family, AF_xxx */ + char sa_data[14]; /* 14 bytes of protocol address */ +}; + + +/* Supported address families. */ +#define AF_UNSPEC 0 +#define AF_UNIX 1 /* Unix domain sockets */ +#define AF_LOCAL 1 /* POSIX name for AF_UNIX */ +#define AF_INET 2 /* Internet IP Protocol */ +#define AF_AX25 3 /* Amateur Radio AX.25 */ +#define AF_IPX 4 /* Novell IPX */ +#define AF_APPLETALK 5 /* AppleTalk DDP */ +#define AF_NETROM 6 /* Amateur Radio NET/ROM */ +#define AF_BRIDGE 7 /* Multiprotocol bridge */ +#define AF_ATMPVC 8 /* ATM PVCs */ +#define AF_X25 9 /* Reserved for X.25 project */ +#define AF_INET6 10 /* IP version 6 */ +#define AF_ROSE 11 /* Amateur Radio X.25 PLP */ +#define AF_DECnet 12 /* Reserved for DECnet project */ +#define AF_NETBEUI 13 /* Reserved for 802.2LLC project*/ +#define AF_SECURITY 14 /* Security callback pseudo AF */ +#define AF_KEY 15 /* PF_KEY key management API */ +#define AF_NETLINK 16 +#define AF_ROUTE AF_NETLINK /* Alias to emulate 4.4BSD */ +#define AF_PACKET 17 /* Packet family */ +#define AF_ASH 18 /* Ash */ +#define AF_ECONET 19 /* Acorn Econet */ +#define AF_ATMSVC 20 /* ATM SVCs */ +#define AF_RDS 21 /* RDS sockets */ +#define AF_SNA 22 /* Linux SNA Project (nutters!) */ +#define AF_IRDA 23 /* IRDA sockets */ +#define AF_PPPOX 24 /* PPPoX sockets */ +#define AF_WANPIPE 25 /* Wanpipe API Sockets */ +#define AF_LLC 26 /* Linux LLC */ +#define AF_CAN 29 /* Controller Area Network */ +#define AF_TIPC 30 /* TIPC sockets */ +#define AF_BLUETOOTH 31 /* Bluetooth sockets */ +#define AF_IUCV 32 /* IUCV sockets */ +#define AF_RXRPC 33 /* RxRPC sockets */ +#define AF_ISDN 34 /* mISDN sockets */ +#define AF_PHONET 35 /* Phonet sockets */ +#define AF_IEEE802154 36 /* IEEE802154 sockets */ +#define AF_CAIF 37 /* CAIF sockets */ +#define AF_ALG 38 /* Algorithm sockets */ +#define AF_MAX 39 /* For now.. */ + +/* Protocol families, same as address families. */ +#define PF_UNSPEC AF_UNSPEC +#define PF_UNIX AF_UNIX +#define PF_LOCAL AF_LOCAL +#define PF_INET AF_INET +#define PF_AX25 AF_AX25 +#define PF_IPX AF_IPX +#define PF_APPLETALK AF_APPLETALK +#define PF_NETROM AF_NETROM +#define PF_BRIDGE AF_BRIDGE +#define PF_ATMPVC AF_ATMPVC +#define PF_X25 AF_X25 +#define PF_INET6 AF_INET6 +#define PF_ROSE AF_ROSE +#define PF_DECnet AF_DECnet +#define PF_NETBEUI AF_NETBEUI +#define PF_SECURITY AF_SECURITY +#define PF_KEY AF_KEY +#define PF_NETLINK AF_NETLINK +#define PF_ROUTE AF_ROUTE +#define PF_PACKET AF_PACKET +#define PF_ASH AF_ASH +#define PF_ECONET AF_ECONET +#define PF_ATMSVC AF_ATMSVC +#define PF_RDS AF_RDS +#define PF_SNA AF_SNA +#define PF_IRDA AF_IRDA +#define PF_PPPOX AF_PPPOX +#define PF_WANPIPE AF_WANPIPE +#define PF_LLC AF_LLC +#define PF_CAN AF_CAN +#define PF_TIPC AF_TIPC +#define PF_BLUETOOTH AF_BLUETOOTH +#define PF_IUCV AF_IUCV +#define PF_RXRPC AF_RXRPC +#define PF_ISDN AF_ISDN +#define PF_PHONET AF_PHONET +#define PF_IEEE802154 AF_IEEE802154 +#define PF_CAIF AF_CAIF +#define PF_ALG AF_ALG +#define PF_MAX AF_MAX + +#define SOL_SOCKET 1 + +#define SO_DEBUG 1 +#define SO_REUSEADDR 2 +#define SO_TYPE 3 +#define SO_ERROR 4 +#define SO_DONTROUTE 5 +#define SO_BROADCAST 6 +#define SO_SNDBUF 7 +#define SO_RCVBUF 8 +#define SO_SNDBUFFORCE 32 +#define SO_RCVBUFFORCE 33 +#define SO_KEEPALIVE 9 +#define SO_OOBINLINE 10 +#define SO_NO_CHECK 11 +#define SO_PRIORITY 12 +#define SO_LINGER 13 +#define SO_BSDCOMPAT 14 +/* To add :#define SO_REUSEPORT 15 */ +#define SO_PASSCRED 16 +#define SO_PEERCRED 17 +#define SO_RCVLOWAT 18 +#define SO_SNDLOWAT 19 +#define SO_RCVTIMEO 20 +#define SO_SNDTIMEO 21 + +/* Security levels - as per NRL IPv6 - don't actually do anything */ +#define SO_SECURITY_AUTHENTICATION 22 +#define SO_SECURITY_ENCRYPTION_TRANSPORT 23 +#define SO_SECURITY_ENCRYPTION_NETWORK 24 + +#define SO_BINDTODEVICE 25 + +/* Socket filtering */ +#define SO_ATTACH_FILTER 26 +#define SO_DETACH_FILTER 27 + +#define SO_PEERNAME 28 +#define SO_TIMESTAMP 29 +#define SCM_TIMESTAMP SO_TIMESTAMP + +#define SO_ACCEPTCONN 30 + +#define SO_PEERSEC 31 +#define SO_PASSSEC 34 +#define SO_TIMESTAMPNS 35 +#define SCM_TIMESTAMPNS SO_TIMESTAMPNS + +#define SO_MARK 36 + +#define SO_TIMESTAMPING 37 +#define SCM_TIMESTAMPING SO_TIMESTAMPING + +#define SO_PROTOCOL 38 +#define SO_DOMAIN 39 + +#define SO_RXQ_OVFL 40 + +typedef struct socket_type_st { + unsigned char type; + unsigned char vif_index; + void *args; + int sync; +}S_TYPE_ST,*S_TYPE_PTR; + +extern SOCKET fsocket_init(int af, int type, int protocol); +extern int fsocket_send(SOCKET sk, const unsigned char *buf, int len, S_TYPE_PTR type); +extern int fsocket_recv(SOCKET sk, const unsigned char *buf, int len, int flag); +extern void fsocket_close(SOCKET sk); +extern int ke_sk_send(SOCKET sk, const unsigned char *buf, int len, int flag); +extern int ke_sk_recv(SOCKET sk, const unsigned char *buf, int len, int flag); +extern BK_SOCKET *sk_get_sk_element(SOCKET sk); +extern int ke_sk_recv_peek_next_payload_size(SOCKET sk); +extern int fsocket_peek_recv_next_payload_size(SOCKET sk); +extern int ke_sk_send_peek_next_payload_size(SOCKET sk); + +#endif // _FAKE_SOCKET_H_ +// eof + diff --git a/beken_os/beken378/func/hostapd-2.5/bk_patch/signal.c b/beken_os/beken378/func/hostapd-2.5/bk_patch/signal.c new file mode 100755 index 0000000..4ba81ca --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/bk_patch/signal.c @@ -0,0 +1,14 @@ +#include "include.h" +#include "signal.h" + +void bk_signal(int sig_num, SIG_FUNC func) +{ +} + +extern unsigned int bk_alarm(unsigned int seconds) +{ + return 0; +} + +// eof + diff --git a/beken_os/beken378/func/hostapd-2.5/bk_patch/signal.h b/beken_os/beken378/func/hostapd-2.5/bk_patch/signal.h new file mode 100755 index 0000000..caf77c7 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/bk_patch/signal.h @@ -0,0 +1,53 @@ +#ifndef _SIGNAL_H_ +#define _SIGNAL_H_ + +typedef void (*SIG_FUNC)(int); + +#define SIGHUP 1 +#define SIGINT 2 +#define SIGQUIT 3 +#define SIGILL 4 +#define SIGTRAP 5 +#define SIGABRT 6 +#define SIGEMT 7 +#define SIGFPE 8 +#define SIGKILL 9 +#define SIGBUS 10 +#define SIGSEGV 11 +#define SIGSYS 12 +#define SIGPIPE 13 +#define SIGALRM 14 +#define SIGTERM 15 +#define SIGURG 16 +#define SIGSTOP 17 +#define SIGTSTP 18 +#define SIGCONT 19 +#define SIGCHLD 20 +#define SIGTTIN 21 +#define SIGTTOU 22 +#define SIGIO 23 +#define SIGXCPU 24 +#define SIGXFSZ 25 +#define SIGVTALRM 26 +#define SIGPROF 27 +#define SIGWINCH 28 +#define SIGINFO 29 +#define SIGUSR1 30 +#define SIGUSR2 31 + +#define SIGSCAN 32 +#define SIGASSOC 33 +#define SIGDISASSOC 34 +#define SIGDEAUTH 35 +#define SIGCSA 36 + +#define SIGPOLL SIGIO +#define SIGPWR SIGINFO +#define SIGIOT SIGABRT + +extern void bk_signal(int sig_num, SIG_FUNC func); +unsigned int bk_alarm(unsigned int seconds); + +#endif +// eof + diff --git a/beken_os/beken378/func/hostapd-2.5/bk_patch/sk_intf.c b/beken_os/beken378/func/hostapd-2.5/bk_patch/sk_intf.c new file mode 100755 index 0000000..b943659 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/bk_patch/sk_intf.c @@ -0,0 +1,126 @@ +#include "include.h" +#include "sk_intf.h" +#include "main_none.h" +#include "eloop.h" + +#include "param_config.h" +#include "uart_pub.h" +#include "rw_pub.h" + +extern uint32_t wpa_hostapd_queue_poll(uint32_t param); + +SOCKET mgmt_get_socket_num(u8 vif_idx) +{ + return (SK_INTF_MGMT_SOCKET_NUM + vif_idx); +} + +SOCKET ioctl_get_socket_num(u8 vif_idx) +{ + return (SK_INTF_IOCTL_SOCKET_NUM + vif_idx); +} + +SOCKET data_get_socket_num(u8 vif_idx) +{ + return (SK_INTF_DATA_SOCKET_NUM + vif_idx); +} + +int ke_mgmt_packet_tx(unsigned char *buf, int len, int flag) +{ + int ret; + SOCKET sk = mgmt_get_socket_num(flag); + + ret = ke_sk_send(sk, buf, len, flag); + + wpa_hostapd_queue_poll((uint32_t)flag); + + return ret; +} + +int ke_mgmt_packet_rx(unsigned char *buf, int len, int flag) +{ + SOCKET sk = mgmt_get_socket_num(flag); + + return ke_sk_recv(sk, buf, len, flag); +} + +int ke_mgmt_peek_txed_next_payload_size(int flag) +{ + SOCKET sk = mgmt_get_socket_num(flag); + + return ke_sk_send_peek_next_payload_size(sk); +} + +int ke_mgmt_peek_rxed_next_payload_size(int flag) +{ + SOCKET sk = mgmt_get_socket_num(flag); + + return ke_sk_recv_peek_next_payload_size(sk); +} + +int ke_l2_packet_tx(unsigned char *buf, int len, int flag) +{ + int ret; + SOCKET sk = data_get_socket_num(flag); + + ret = ke_sk_send(sk, buf, len, flag); + + wpa_hostapd_queue_poll((uint32_t)flag); + + return ret; +} + +int ke_l2_packet_rx(unsigned char *buf, int len, int flag) +{ + SOCKET sk = data_get_socket_num(flag); + + return ke_sk_recv(sk, buf, len, flag); +} + +int ke_data_peek_txed_next_payload_size(int flag) +{ + SOCKET sk = data_get_socket_num(flag); + + return ke_sk_send_peek_next_payload_size(sk); +} + +int ke_data_peek_rxed_next_payload_size(int flag) +{ + SOCKET sk = data_get_socket_num(flag); + + return ke_sk_recv_peek_next_payload_size(sk); +} + +int ws_mgmt_peek_rxed_next_payload_size(int flag) +{ + SOCKET sk = mgmt_get_socket_num(flag); + + return fsocket_peek_recv_next_payload_size(sk); +} + +int ws_get_mgmt_packet(unsigned char *buf, int len, int flag) +{ + SOCKET sk; + + sk = mgmt_get_socket_num(flag); + + return fsocket_recv(sk, buf, len, flag); +} + +int ws_data_peek_rxed_next_payload_size(int flag) +{ + SOCKET sk = data_get_socket_num(flag); + + return fsocket_peek_recv_next_payload_size(sk); +} + +int ws_get_data_packet(unsigned char *buf, int len, int flag) +{ + SOCKET sk; + + sk = data_get_socket_num(flag); + + return fsocket_recv(sk, buf, len, flag); +} + +// eof + diff --git a/beken_os/beken378/func/hostapd-2.5/bk_patch/sk_intf.h b/beken_os/beken378/func/hostapd-2.5/bk_patch/sk_intf.h new file mode 100755 index 0000000..9c6687a --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/bk_patch/sk_intf.h @@ -0,0 +1,27 @@ +#ifndef _SK_INTF_H_ +#define _SK_INTF_H_ + +#include "common.h" +#include "fake_socket.h" + +#define SK_INTF_MGMT_SOCKET_NUM (PF_PACKET + SOCK_RAW + ETH_P_ALL) +#define SK_INTF_IOCTL_SOCKET_NUM (PF_INET + SOCK_DGRAM + 0) +#define SK_INTF_DATA_SOCKET_NUM (PF_PACKET + SOCK_RAW + ETH_P_PAE) + +extern int ke_mgmt_peek_rxed_next_payload_size(int flag); +extern int ke_mgmt_packet_rx(unsigned char *buf, int len, int flag); +extern int ke_mgmt_packet_tx(unsigned char *buf, int len, int flag); +extern int ke_l2_packet_tx(unsigned char *buf, int len, int flag); +extern int ke_l2_packet_rx(unsigned char *buf, int len, int flag); +extern int ke_data_peek_txed_next_payload_size(int flag); +extern int ke_data_peek_rxed_next_payload_size(int flag); +extern int ws_mgmt_peek_rxed_next_payload_size(int flag); +extern int ws_get_mgmt_packet(unsigned char *buf, int len, int flag); +extern int ws_data_peek_rxed_next_payload_size(int flag); +extern int ws_get_data_packet(unsigned char *buf, int len, int flag); +extern SOCKET mgmt_get_socket_num(u8 vif_idx); +extern SOCKET data_get_socket_num(u8 vif_idx); +extern SOCKET ioctl_get_socket_num(u8 vif_idx); +#endif +// eof + diff --git a/beken_os/beken378/func/hostapd-2.5/hostapd/hostapd_cfg.h b/beken_os/beken378/func/hostapd-2.5/hostapd/hostapd_cfg.h new file mode 100755 index 0000000..21f03cc --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/hostapd/hostapd_cfg.h @@ -0,0 +1,15 @@ +#ifndef _HOSTAPD_CONFIG_H_ +#define _HOSTAPD_CONFIG_H_ + +#include "include.h" +#include "defs.h" +#include "rwnx_config.h" + +#define CFG_AUTH_ALG WPA_AUTH_ALG_OPEN + +#define CFG_SUPPORTED_MAX_STA_NUM CFG_STA_MAX// 2 +#define CFG_SUPPORT_80211G 1 + +#endif // _HOSTAPD_CONFIG_H_ + + diff --git a/beken_os/beken378/func/hostapd-2.5/hostapd/main_none.c b/beken_os/beken378/func/hostapd-2.5/hostapd/main_none.c new file mode 100755 index 0000000..b159c2a --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/hostapd/main_none.c @@ -0,0 +1,777 @@ +/* + * WPA Supplicant / Example program entrypoint + * Copyright (c) 2003-2005, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ +#include "include.h" +#include "uart_pub.h" +#include "includes.h" +#include "hostapd_cfg.h" +#include "common.h" +#include "ap/hostapd.h" +#include "eloop.h" +#include "main_none.h" +#include "ap/sta_info.h" +#include "ps.h" +#include "param_config.h" +#include "wlan_ui_pub.h" +#include "rtos_pub.h" +#include "rtos_error.h" +#include "wlan_ui_pub.h" + +#if (CFG_SUPPORT_ALIOS || CFG_SUPPORT_RTT) +beken_thread_t hostapd_thread_handle = NULL; +extern beken_thread_t wpas_thread_handle; +#else +xTaskHandle hostapd_thread_handle = NULL; +extern xTaskHandle wpas_thread_handle; +#endif + +#define HOSTAPD_STACK_SIZE 4000 +beken_semaphore_t hostapd_sema = NULL; +beken_semaphore_t wpa_hostapd_sema = NULL; +void *wpa_hostapd_param = NULL; +beken_queue_t wpah_queue = NULL; +static struct hapd_global s_hapd_global; +struct hapd_interfaces g_hapd_interfaces; +uint32_t hostapd_exit_flag = 0; + +const char *bss_iface = "wlan0"; + +extern int ap_channel_switch(struct hostapd_iface *ap_iface, int new_freq); +extern uint32_t wpa_hostapd_queue_poll(uint32_t param); + +void hostapd_cfg_defaults_bss(struct hostapd_bss_config *bss) +{ + bss->logger_syslog_level = HOSTAPD_LEVEL_INFO; + bss->logger_stdout_level = HOSTAPD_LEVEL_INFO; + bss->logger_syslog = (unsigned int) -1; + bss->logger_stdout = (unsigned int) -1; + + bss->auth_algs = CFG_AUTH_ALG; + + bss->wep_rekeying_period = 300; + /* use key0 in individual key and key1 in broadcast key */ + bss->broadcast_key_idx_min = 1; + bss->broadcast_key_idx_max = 2; + bss->eap_reauth_period = 3600; + + bss->wpa_group_rekey = 600; + bss->wpa_gmk_rekey = 86400; + bss->wpa_key_mgmt = WPA_KEY_MGMT_PSK; + bss->wpa_pairwise = WPA_CIPHER_TKIP; + bss->wpa_group = WPA_CIPHER_TKIP; + bss->rsn_pairwise = 0; + + bss->max_num_sta = CFG_SUPPORTED_MAX_STA_NUM; + + bss->dtim_period = 2; + + bss->radius_server_auth_port = 1812; + bss->ap_max_inactivity = AP_MAX_INACTIVITY; + bss->eapol_version = 2; + bss->max_listen_interval = 65535; + bss->pwd_group = 19; /* ECC: GF(p=256) */ + +#ifdef CONFIG_IEEE80211W + bss->assoc_sa_query_max_timeout = 1000; + bss->assoc_sa_query_retry_timeout = 201; + bss->group_mgmt_cipher = WPA_CIPHER_AES_128_CMAC; +#endif /* CONFIG_IEEE80211W */ +#ifdef EAP_SERVER_FAST + /* both anonymous and authenticated provisioning */ + bss->eap_fast_prov = 3; + bss->pac_key_lifetime = 7 * 24 * 60 * 60; + bss->pac_key_refresh_time = 1 * 24 * 60 * 60; +#endif /* EAP_SERVER_FAST */ + + /* Set to -1 as defaults depends on HT in setup */ + bss->wmm_enabled = -1; + +#ifdef CONFIG_IEEE80211R + bss->ft_over_ds = 1; +#endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_SAE + bss->sae_anti_clogging_threshold = 5; +#endif +} + +struct hostapd_config * hostapd_cfg_defaults(void) +{ +#define ecw2cw(ecw) ((1 << (ecw)) - 1) + + struct hostapd_config *conf; + struct hostapd_bss_config *bss; + const int aCWmin = 4, aCWmax = 10; + const struct hostapd_wmm_ac_params ac_bk = + { aCWmin, aCWmax, 7, 0, 0 }; /* background traffic */ + const struct hostapd_wmm_ac_params ac_be = + { aCWmin, aCWmax, 3, 0, 0 }; /* best effort traffic */ + const struct hostapd_wmm_ac_params ac_vi = /* video traffic */ + { aCWmin - 1, aCWmin, 2, 3008 / 32, 0 }; + const struct hostapd_wmm_ac_params ac_vo = /* voice traffic */ + { aCWmin - 2, aCWmin - 1, 2, 1504 / 32, 0 }; + const struct hostapd_tx_queue_params txq_bk = + { 7, ecw2cw(aCWmin), ecw2cw(aCWmax), 0 }; + const struct hostapd_tx_queue_params txq_be = + { 3, ecw2cw(aCWmin), 4 * (ecw2cw(aCWmin) + 1) - 1, 0}; + const struct hostapd_tx_queue_params txq_vi = + { 1, (ecw2cw(aCWmin) + 1) / 2 - 1, ecw2cw(aCWmin), 30}; + const struct hostapd_tx_queue_params txq_vo = + { 1, (ecw2cw(aCWmin) + 1) / 4 - 1, + (ecw2cw(aCWmin) + 1) / 2 - 1, 15}; + +#undef ecw2cw + + conf = os_zalloc(sizeof(*conf)); + bss = os_zalloc(sizeof(*bss)); + if (conf == NULL || bss == NULL) { + wpa_printf(MSG_ERROR, "Failed to allocate memory for " + "configuration data."); + os_free(conf); + os_free(bss); + return NULL; + } + conf->bss = os_calloc(1, sizeof(struct hostapd_bss_config *)); + if (conf->bss == NULL) { + os_free(conf); + os_free(bss); + return NULL; + } + conf->bss[0] = bss; + + hostapd_cfg_defaults_bss(bss); + + conf->num_bss = 1; + + #if CFG_SUPPORT_80211G + conf->hw_mode = HOSTAPD_MODE_IEEE80211G; + #endif + + conf->beacon_int = 100; + conf->rts_threshold = -1; /* use driver default: 2347 */ + conf->fragm_threshold = -1; /* user driver default: 2346 */ + conf->send_probe_response = 1; + /* Set to invalid value means do not add Power Constraint IE */ + conf->local_pwr_constraint = -1; + + conf->wmm_ac_params[0] = ac_be; + conf->wmm_ac_params[1] = ac_bk; + conf->wmm_ac_params[2] = ac_vi; + conf->wmm_ac_params[3] = ac_vo; + + conf->tx_queue[0] = txq_vo; + conf->tx_queue[1] = txq_vi; + conf->tx_queue[2] = txq_be; + conf->tx_queue[3] = txq_bk; + + conf->ht_capab = HT_CAP_INFO_SMPS_DISABLED; + + conf->ap_table_max_size = 255; + conf->ap_table_expiration_time = 60; + conf->track_sta_max_age = 0;//180; + + conf->acs = 0; + conf->acs_ch_list.num = 0; +#ifdef CONFIG_ACS + conf->acs_num_scans = 5; +#endif /* CONFIG_ACS */ + + return conf; +} + +struct hostapd_config * hostapd_config_read(const char *fname) +{ + struct hostapd_config *conf = 0; + int i; + int errors = 0; + struct hostapd_bss_config *bss; + + conf = hostapd_cfg_defaults(); + if (NULL == conf) { + return NULL; + } + + conf->last_bss = conf->bss[0]; + bss = conf->last_bss; + + os_strcpy(bss->iface, bss_iface); + wifi_get_mac_address((char*)&bss->bssid, CONFIG_ROLE_AP); + /* set default driver based on configuration */ + conf->driver = wpa_drivers[0]; + conf->last_bss = conf->bss[0]; + + bss->ssid.ssid_len = g_ap_param_ptr->ssid.length; + os_memcpy(bss->ssid.ssid, g_ap_param_ptr->ssid.array, bss->ssid.ssid_len); + bss->max_listen_interval = 65535; + bss->ieee802_1x = 0; + bss->ssid.ssid_set = 1; + + if(g_ap_param_ptr->cipher_suite == SECURITY_TYPE_WEP){ + bss->default_wep_key_len = 0; + bss->ssid.wep.keys_set = 1; + bss->ssid.wep.default_len = 10; + bss->ssid.wep.idx = 0; + bss->ssid.wep.len[0] = 5; + bss->ssid.wep.key[0] = (u8 *)os_malloc(bss->ssid.wep.len[0]); + if(bss->ssid.wep.key[0]){ + int wkey; + const char *wep_key = (char *)g_ap_param_ptr->key; + if(g_ap_param_ptr->key_len == 5){ + os_memcpy(bss->ssid.wep.key[0], wep_key, g_ap_param_ptr->key_len); + }else if(g_ap_param_ptr->key_len == 10){ + for(i = 0; i < bss->ssid.wep.len[0]; i ++){ + wkey = hex2byte(&wep_key[2 * i]); + ASSERT(-1 != wkey); + + bss->ssid.wep.key[0][i] = wkey; + } + }else{ + os_printf("WEP_KEY_len_exception\r\n"); + } + } + }else if(g_ap_param_ptr->cipher_suite == SECURITY_TYPE_WPA_TKIP){ + bss->wpa = 1; + bss->wpa_pairwise = WPA_CIPHER_TKIP; + }else if(g_ap_param_ptr->cipher_suite == SECURITY_TYPE_WPA2_AES){ + bss->wpa = 2; + bss->wpa_pairwise = WPA_CIPHER_CCMP; + }else if(g_ap_param_ptr->cipher_suite == SECURITY_TYPE_WPA2_MIXED){ + bss->wpa = 2; + bss->wpa_pairwise = WPA_CIPHER_TKIP|WPA_CIPHER_CCMP; + } + if(g_ap_param_ptr->cipher_suite > SECURITY_TYPE_WEP){ + const char *wpa_key = (char *)g_ap_param_ptr->key; + os_free(bss->ssid.wpa_passphrase); + bss->ssid.wpa_passphrase = os_strdup(wpa_key); + if (bss->ssid.wpa_passphrase) { + hostapd_config_clear_wpa_psk(&bss->ssid.wpa_psk); + bss->ssid.wpa_passphrase_set = 1; + } + bss->wpa_key_mgmt = WPA_KEY_MGMT_PSK; + } + + for (i = 0; i < conf->num_bss; i++) + hostapd_set_security_params(conf->bss[i], 1); + + if (hostapd_config_check(conf, 1)) + errors++; + + return conf; +} + +/** + * hostapd_driver_init - Preparate driver interface + */ +static int hostapd_driver_init(struct hostapd_iface *iface) +{ + size_t i; + struct wpa_init_params params; + struct hostapd_data *hapd = iface->bss[0]; + struct hostapd_bss_config *conf = hapd->conf; + u8 *b = conf->bssid; + struct wpa_driver_capa capa; + + if (hapd->driver == NULL || hapd->driver->hapd_init == NULL) { + wpa_printf(MSG_ERROR, "No hostapd driver wrapper available"); + return -1; + } + + /* Initialize the driver interface */ + if (!(b[0] | b[1] | b[2] | b[3] | b[4] | b[5])) { + b = NULL; + os_printf("hostapd_driver_init bssid is null\r\n"); + return -1; + } + + os_memset(¶ms, 0, sizeof(params)); + for (i = 0; wpa_drivers[i]; i++) { + if (wpa_drivers[i] != hapd->driver) + continue; + + if (s_hapd_global.drv_priv[i] == NULL && + wpa_drivers[i]->global_init) { + s_hapd_global.drv_priv[i] = wpa_drivers[i]->global_init(); + if (s_hapd_global.drv_priv[i] == NULL) { + wpa_printf(MSG_ERROR, "Failed to initialize " + "driver '%s'", + wpa_drivers[i]->name); + return -1; + } + } + + params.global_priv = s_hapd_global.drv_priv[i]; + break; + } + params.bssid = b; + params.ifname = hapd->conf->iface; + params.driver_params = hapd->iconf->driver_params; + params.use_pae_group_addr = hapd->conf->use_pae_group_addr; + + params.num_bridge = hapd->iface->num_bss; + params.bridge = os_calloc(hapd->iface->num_bss, sizeof(char *)); + if (params.bridge == NULL) + return -1; + for (i = 0; i < hapd->iface->num_bss; i++) { + struct hostapd_data *bss = hapd->iface->bss[i]; +#ifdef CONFIG_FULL_HOSTAPD + if (bss->conf->bridge[0]) { + params.bridge[i] = bss->conf->bridge; + } +#else + bss = bss; +#endif + } + + os_memcpy(hapd->own_addr, b, ETH_ALEN); + params.own_addr = hapd->own_addr; + + hapd->drv_priv = hapd->driver->hapd_init(hapd, ¶ms); + os_free(params.bridge); + if (hapd->drv_priv == NULL) { + wpa_printf(MSG_ERROR, "%s driver initialization failed.", + hapd->driver->name); + hapd->driver = NULL; + return -1; + } + + if (hapd->driver->get_capa && + hapd->driver->get_capa(hapd->drv_priv, &capa) == 0) { + struct wowlan_triggers *triggs; + + iface->drv_flags = capa.flags; + iface->smps_modes = capa.smps_modes; + iface->probe_resp_offloads = capa.probe_resp_offloads; + iface->extended_capa = capa.extended_capa; + iface->extended_capa_mask = capa.extended_capa_mask; + iface->extended_capa_len = capa.extended_capa_len; + iface->drv_max_acl_mac_addrs = capa.max_acl_mac_addrs; +#ifdef CONFIG_FULL_HOSTAPD + triggs = wpa_get_wowlan_triggers(conf->wowlan_triggers, &capa); + if (triggs && hapd->driver->set_wowlan) { + if (hapd->driver->set_wowlan(hapd->drv_priv, triggs)) + wpa_printf(MSG_ERROR, "set_wowlan failed"); + } + os_free(triggs); +#else + triggs = triggs; +#endif + } + + return 0; +} + + +/** + * hostapd_interface_init - Read configuration file and init BSS data + * + * This function is used to parse configuration file for a full interface (one + * or more BSSes sharing the same radio) and allocate memory for the BSS + * g_hapd_interfaces. No actiual driver operations are started. + */ +static struct hostapd_iface * +hostapd_interface_init(struct hapd_interfaces *interfaces, + const char *config_fname, int debug) +{ + struct hostapd_iface *iface; + int k; + + wpa_printf(MSG_ERROR, "Configuration file: %s", config_fname); + iface = hostapd_init(interfaces, config_fname); + if (!iface) + return NULL; + iface->interfaces = interfaces; + + for (k = 0; k < debug; k++) { + if (iface->bss[0]->conf->logger_stdout_level > 0) + iface->bss[0]->conf->logger_stdout_level--; + } + + if (iface->conf->bss[0]->iface[0] == '\0') { + wpa_printf(MSG_ERROR, "Interface name not specified in %s", + config_fname); + hostapd_interface_deinit_free(iface); + return NULL; + } + + return iface; +} + +static int hostapd_global_init(struct hapd_interfaces *interfaces, + const char *entropy_file) +{ + int i; + + os_memset(&s_hapd_global, 0, sizeof(s_hapd_global)); + + for (i = 0; wpa_drivers[i]; i++) + s_hapd_global.drv_count++; + if (s_hapd_global.drv_count == 0) { + wpa_printf(MSG_ERROR, "No drivers enabled"); + return -1; + } + s_hapd_global.drv_priv = os_calloc(s_hapd_global.drv_count, sizeof(void *)); + if (s_hapd_global.drv_priv == NULL) + return -1; + + return 0; +} + + +static void hostapd_global_deinit(const char *pid_file) +{ + int i; + + for (i = 0; wpa_drivers[i] && s_hapd_global.drv_priv; i++) { + if (!s_hapd_global.drv_priv[i]) + continue; + wpa_drivers[i]->global_deinit(s_hapd_global.drv_priv[i]); + } + os_free(s_hapd_global.drv_priv); + s_hapd_global.drv_priv = NULL; + + eloop_free_resource(); + + os_daemonize_terminate(pid_file); +} + +static int hostapd_global_run(struct hapd_interfaces *ifaces, int daemonize, + const char *pid_file) +{ + if (daemonize && os_daemonize(pid_file)) { + wpa_printf(MSG_ERROR, "daemon: %s", strerror(errno)); + return -1; + } + + eloop_run(); + + return 0; +} + + +const char * hostapd_msg_ifname_cb(void *ctx) +{ + struct hostapd_data *hapd = ctx; + if (hapd && hapd->iconf && hapd->iconf->bss && + hapd->iconf->num_bss > 0 && hapd->iconf->bss[0]) + return hapd->iconf->bss[0]->iface; + return NULL; +} + +/* Periodic cleanup tasks */ +static void hostapd_periodic(void *eloop_ctx, void *timeout_ctx) +{ +} + +int hostapd_main_exit(void) +{ + uint32_t ret; + + hostapd_exit_flag = 1; + + ret = wpa_hostapd_queue_poll(0xff); + while((0 == ret) && hostapd_exit_flag) + { + os_printf("hostapd_main_exiting\r\n"); + rtos_delay_milliseconds(10); + } + + return 0; +} + +int hostapd_exit_done(void) +{ + hostapd_exit_flag = 0; + os_printf("hostapd_exit_done\r\n"); + + return 0; +} + +int hostapd_is_exiting(void) +{ + return hostapd_exit_flag; +} + +int hostapd_exit_handler(void) +{ + size_t i; + + os_printf("hostapd_exit_handler\r\n"); + + if(g_hapd_interfaces.count == 0) + { + return 0; + } + + for ( i = 0; i < g_hapd_interfaces.count; i++ ) + { + if (!g_hapd_interfaces.iface[i]) + continue; + + g_hapd_interfaces.iface[i]->driver_ap_teardown = + !!(g_hapd_interfaces.iface[i]->drv_flags & + WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT); + + hostapd_interface_deinit_free(g_hapd_interfaces.iface[i]); + g_hapd_interfaces.iface[i] = NULL; + } + os_free(g_hapd_interfaces.iface); + g_hapd_interfaces.iface = NULL; + g_hapd_interfaces.count = 0; + + eloop_cancel_timeout(hostapd_periodic, &g_hapd_interfaces, NULL); + hostapd_global_deinit(NULL); + + return 0; +} + +int hostapd_main_entry(int argc, char *argv[]) +{ + int ret = 1; + size_t i, j; + int debug = 0; + char *pid_file = NULL; + size_t num_bss_configs = 0; + const char *log_file = NULL; + const char *entropy_file = NULL; + char *bss_config[1] = {CFG_BSS_CONFIG}; + char *ap_iface_buf = CFG_AP_IFACE_CONFIG; + + ap_iface_buf = os_malloc(strlen(CFG_AP_IFACE_CONFIG) + 1); + if (0 == ap_iface_buf) + return -1; + + os_memcpy(ap_iface_buf, CFG_AP_IFACE_CONFIG,(strlen(CFG_AP_IFACE_CONFIG) + 1)); + if (os_program_init()) + { + os_free(ap_iface_buf); + return -1; + } + + os_memset(&g_hapd_interfaces, 0, sizeof(g_hapd_interfaces)); + g_hapd_interfaces.config_read_cb = hostapd_config_read; + g_hapd_interfaces.for_each_interface = hostapd_for_each_interface; + g_hapd_interfaces.ctrl_iface_init = 0; + g_hapd_interfaces.ctrl_iface_deinit = 0; + g_hapd_interfaces.driver_init = hostapd_driver_init; + g_hapd_interfaces.global_iface_path = NULL; + g_hapd_interfaces.global_iface_name = NULL; + g_hapd_interfaces.global_ctrl_sock = -1; + g_hapd_interfaces.global_ctrl_dst = NULL; + + wpa_msg_register_ifname_cb(hostapd_msg_ifname_cb); + + g_hapd_interfaces.count = argc - 1; + if (g_hapd_interfaces.count || num_bss_configs) { + g_hapd_interfaces.iface = os_calloc(g_hapd_interfaces.count + num_bss_configs, + sizeof(struct hostapd_iface *)); + if (g_hapd_interfaces.iface == NULL) { + os_free(ap_iface_buf); + fatal_prf("malloc failed\r\n"); + return -1; + } + } + + if (hostapd_global_init(&g_hapd_interfaces, entropy_file)) { + os_free(ap_iface_buf); + fatal_prf("Failed to initialize global context\r\n"); + return -1; + } + + /* Allocate and parse configuration for full interface files */ + for (i = 0; i < g_hapd_interfaces.count; i++) { + char *config_fname = CFG_CONFIG_FNAME; + g_hapd_interfaces.iface[i] = hostapd_interface_init(&g_hapd_interfaces, + config_fname, + debug); + if (!g_hapd_interfaces.iface[i]) { + fatal_prf("Failed to initialize interface\r\n"); + goto out; + } + } + + /* Allocate and parse configuration for per-BSS files */ + for (i = 0; i < num_bss_configs; i++) { + struct hostapd_iface *iface; + char *fname; + + wpa_printf(MSG_INFO, "BSS config: %s", bss_config[i]); + fname = os_strchr(bss_config[i], ':'); + if (fname == NULL) { + wpa_printf(MSG_ERROR, + "Invalid BSS config identifier '%s'", + bss_config[i]); + goto out; + } + *fname++ = '\0'; + iface = hostapd_interface_init_bss(&g_hapd_interfaces, bss_config[i], + fname, debug); + if (iface == NULL) + goto out; + for (j = 0; j < g_hapd_interfaces.count; j++) { + if (g_hapd_interfaces.iface[j] == iface) + break; + } + if (j == g_hapd_interfaces.count) { + struct hostapd_iface **tmp; + tmp = os_realloc_array(g_hapd_interfaces.iface, + g_hapd_interfaces.count + 1, + sizeof(struct hostapd_iface *)); + if (tmp == NULL) { + hostapd_interface_deinit_free(iface); + goto out; + } + g_hapd_interfaces.iface = tmp; + g_hapd_interfaces.iface[g_hapd_interfaces.count++] = iface; + } + } + + /* + * Enable configured g_hapd_interfaces. Depending on channel configuration, + * this may complete full initialization before returning or use a + * callback mechanism to complete setup in case of operations like HT + * co-ex scans, ACS, or DFS are needed to determine channel parameters. + * In such case, the interface will be enabled from eloop context within + * hostapd_global_run(). + */ + g_hapd_interfaces.terminate_on_error = g_hapd_interfaces.count; + for (i = 0; i < g_hapd_interfaces.count; i++) { + if (hostapd_driver_init(g_hapd_interfaces.iface[i]) || + hostapd_setup_interface(g_hapd_interfaces.iface[i])) + goto out; + } + + hostapd_add_iface(&g_hapd_interfaces, ap_iface_buf); + + ret = 0; + + os_free(ap_iface_buf); + + return ret; + + out: + /* Deinitialize all g_hapd_interfaces */ + fatal_prf("hostapd_main_init_failed\r\n"); + for (i = 0; i < g_hapd_interfaces.count; i++) { + if (!g_hapd_interfaces.iface[i]) + continue; + + g_hapd_interfaces.iface[i]->driver_ap_teardown = + !!(g_hapd_interfaces.iface[i]->drv_flags & + WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT); + + hostapd_interface_deinit_free(g_hapd_interfaces.iface[i]); + g_hapd_interfaces.iface[i] = NULL; + } + os_free(g_hapd_interfaces.iface); + g_hapd_interfaces.iface = NULL; + g_hapd_interfaces.count = 0; + + eloop_cancel_timeout(hostapd_periodic, &g_hapd_interfaces, NULL); + hostapd_global_deinit(pid_file); + os_free(pid_file); + os_free(ap_iface_buf); + + if (log_file) + wpa_debug_close_file(); + wpa_debug_close_linux_tracing(); + + os_program_deinit(); + + return ret; +} + +static void hostapd_thread_main( void *arg ) +{ + int daemonize = 0; + char *pid_file = NULL; + + if (hostapd_global_run(&g_hapd_interfaces, daemonize, pid_file)) { + wpa_printf(MSG_ERROR, "Failed to start eloop"); + } +} + +void hostapd_thread_start(void) +{ + OSStatus ret; + + if(wpah_queue == NULL) { + ret = rtos_init_queue(&wpah_queue, + "wpah_queue", + sizeof(WPAH_MSG_ST), + 40); + ASSERT(kNoErr == ret); + } + + if((hostapd_thread_handle== NULL) && (NULL == wpas_thread_handle)) { + ret = rtos_create_thread(&hostapd_thread_handle, + THD_HOSTAPD_PRIORITY, + "hostapd_thread", + (beken_thread_function_t)hostapd_thread_main, + (unsigned short)HOSTAPD_STACK_SIZE, + (beken_thread_arg_t)NULLPTR); + ASSERT(kNoErr == ret); + } +} + +void hostapd_thread_stop(void) +{ + OSStatus ret; + + ret = rtos_delete_thread(&hostapd_thread_handle); + ASSERT(kNoErr == ret); + + ret = rtos_deinit_semaphore(&hostapd_sema); + ASSERT(kNoErr == ret); +} + +int hostapd_sem_wait(uint32_t ms) +{ + if(NULL == hostapd_sema) + { + return kTimeoutErr; + } + + return rtos_get_semaphore(&hostapd_sema, ms); +} + +void hostapd_poll(void *param) +{ + OSStatus ret; + + if(hostapd_sema) + { + ret = rtos_set_semaphore(&hostapd_sema); + } + + (void)ret; +} + +int hostapd_channel_switch(int new_freq) +{ + return ap_channel_switch(g_hapd_interfaces.iface[0], new_freq); +} + +uint32_t wpa_hostapd_queue_poll(uint32_t param) +{ + OSStatus ret; + uint32_t value = 0; + WPAH_MSG_ST msg; + + if(wpah_queue) { + msg.argu = (u32)param; + ret = rtos_push_to_queue(&wpah_queue, &msg, BEKEN_NO_WAIT); + if(kNoErr != ret) + { + os_printf("wpa_hostapd_queue_poll failed\r\n"); + value = 1; + } + } + + return value; +} + +// eof + diff --git a/beken_os/beken378/func/hostapd-2.5/hostapd/main_none.h b/beken_os/beken378/func/hostapd-2.5/hostapd/main_none.h new file mode 100755 index 0000000..38a28b2 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/hostapd/main_none.h @@ -0,0 +1,28 @@ +#ifndef _MAIN_NONE_H_ +#define _MAIN_NONE_H_ + +#define CFG_CONFIG_FNAME "beken_cfg_fname" +#define CFG_BSS_CONFIG "wangzhilei_config:bss_fname" +#define CFG_AP_IFACE_CONFIG "bss_config= wlan0" +#define WEP40_KEY_LENGTH 10 + +struct hapd_global { + void **drv_priv; + size_t drv_count; +}; + +extern const char *bss_iface; + +void hostapd_thread_start(void); +void hostapd_thread_stop(void); +extern int hostapd_main_entry(int argc, char *argv[]); +extern void hostapd_poll(void *param); +extern int hostapd_channel_switch(int new_freq); +extern int supplicant_main_entry(char *oob_ssid); +extern void wpa_supplicant_poll(void *param); +struct wpa_supplicant *wpa_suppliant_ctrl_get_wpas(); +struct hapd_interfaces *hostapd_ctrl_get_interfaces(); + +#endif // _MAIN_NONE_H_ +// eof + diff --git a/beken_os/beken378/func/hostapd-2.5/hs20/client/osu_client.h b/beken_os/beken378/func/hostapd-2.5/hs20/client/osu_client.h new file mode 100755 index 0000000..9a7059e --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/hs20/client/osu_client.h @@ -0,0 +1,118 @@ +/* + * Hotspot 2.0 - OSU client + * Copyright (c) 2013-2014, Qualcomm Atheros, Inc. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef OSU_CLIENT_H +#define OSU_CLIENT_H + +#define SPP_NS_URI "http://www.wi-fi.org/specifications/hotspot2dot0/v1.0/spp" + +#define URN_OMA_DM_DEVINFO "urn:oma:mo:oma-dm-devinfo:1.0" +#define URN_OMA_DM_DEVDETAIL "urn:oma:mo:oma-dm-devdetail:1.0" +#define URN_HS20_DEVDETAIL_EXT "urn:wfa:mo-ext:hotspot2dot0-devdetail-ext:1.0" +#define URN_HS20_PPS "urn:wfa:mo:hotspot2dot0-perprovidersubscription:1.0" + + +#define MAX_OSU_VALS 10 + +struct osu_lang_text { + char lang[4]; + char text[253]; +}; + +struct hs20_osu_client { + struct xml_node_ctx *xml; + struct http_ctx *http; + int no_reconnect; + char pps_fname[300]; + char *devid; + const char *result_file; + const char *summary_file; + const char *ifname; + const char *ca_fname; + int no_osu_cert_validation; /* for EST operations */ + char *fqdn; + char *server_url; + struct osu_lang_text friendly_name[MAX_OSU_VALS]; + size_t friendly_name_count; + size_t icon_count; + char icon_filename[MAX_OSU_VALS][256]; + u8 icon_hash[MAX_OSU_VALS][32]; + int pps_cred_set; + int pps_updated; + int client_cert_present; + char **server_dnsname; + size_t server_dnsname_count; +#define WORKAROUND_OCSP_OPTIONAL 0x00000001 + unsigned long int workarounds; +}; + + +/* osu_client.c */ + +void write_result(struct hs20_osu_client *ctx, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); +void write_summary(struct hs20_osu_client *ctx, const char *fmt, ...) + __attribute__ ((format (printf, 2, 3))); + +void debug_dump_node(struct hs20_osu_client *ctx, const char *title, + xml_node_t *node); +int osu_get_certificate(struct hs20_osu_client *ctx, xml_node_t *getcert); +int hs20_add_pps_mo(struct hs20_osu_client *ctx, const char *uri, + xml_node_t *add_mo, char *fname, size_t fname_len); +void get_user_pw(struct hs20_osu_client *ctx, xml_node_t *pps, + const char *alt_loc, char **user, char **pw); +int update_pps_file(struct hs20_osu_client *ctx, const char *pps_fname, + xml_node_t *pps); +void cmd_set_pps(struct hs20_osu_client *ctx, const char *pps_fname); + + +/* spp_client.c */ + +void spp_sub_rem(struct hs20_osu_client *ctx, const char *address, + const char *pps_fname, + const char *client_cert, const char *client_key, + const char *cred_username, const char *cred_password, + xml_node_t *pps); +void spp_pol_upd(struct hs20_osu_client *ctx, const char *address, + const char *pps_fname, + const char *client_cert, const char *client_key, + const char *cred_username, const char *cred_password, + xml_node_t *pps); +int cmd_prov(struct hs20_osu_client *ctx, const char *url); +int cmd_sim_prov(struct hs20_osu_client *ctx, const char *url); + + +/* oma_dm_client.c */ + +int cmd_oma_dm_prov(struct hs20_osu_client *ctx, const char *url); +int cmd_oma_dm_sim_prov(struct hs20_osu_client *ctx, const char *url); +void oma_dm_sub_rem(struct hs20_osu_client *ctx, const char *address, + const char *pps_fname, + const char *client_cert, const char *client_key, + const char *cred_username, const char *cred_password, + xml_node_t *pps); +void oma_dm_pol_upd(struct hs20_osu_client *ctx, const char *address, + const char *pps_fname, + const char *client_cert, const char *client_key, + const char *cred_username, const char *cred_password, + xml_node_t *pps); +void cmd_oma_dm_sub_rem(struct hs20_osu_client *ctx, const char *address, + const char *pps_fname); +void cmd_oma_dm_add(struct hs20_osu_client *ctx, const char *pps_fname, + const char *add_fname); +void cmd_oma_dm_replace(struct hs20_osu_client *ctx, const char *pps_fname, + const char *replace_fname); + +/* est.c */ + +int est_load_cacerts(struct hs20_osu_client *ctx, const char *url); +int est_build_csr(struct hs20_osu_client *ctx, const char *url); +int est_simple_enroll(struct hs20_osu_client *ctx, const char *url, + const char *user, const char *pw); + +#endif /* OSU_CLIENT_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/ap/accounting.h b/beken_os/beken378/func/hostapd-2.5/src/ap/accounting.h new file mode 100755 index 0000000..dcc54ee --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/ap/accounting.h @@ -0,0 +1,44 @@ +/* + * hostapd / RADIUS Accounting + * Copyright (c) 2002-2005, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef ACCOUNTING_H +#define ACCOUNTING_H + +#ifdef CONFIG_NO_ACCOUNTING +static inline void accounting_sta_get_id(struct hostapd_data *hapd, + struct sta_info *sta) +{ +} + +static inline void accounting_sta_start(struct hostapd_data *hapd, + struct sta_info *sta) +{ +} + +static inline void accounting_sta_stop(struct hostapd_data *hapd, + struct sta_info *sta) +{ +} + +static inline int accounting_init(struct hostapd_data *hapd) +{ + return 0; +} + +static inline void accounting_deinit(struct hostapd_data *hapd) +{ +} +#else /* CONFIG_NO_ACCOUNTING */ +void accounting_sta_get_id(struct hostapd_data *hapd, struct sta_info *sta); +void accounting_sta_start(struct hostapd_data *hapd, struct sta_info *sta); +void accounting_sta_stop(struct hostapd_data *hapd, struct sta_info *sta); +int accounting_init(struct hostapd_data *hapd); +void accounting_deinit(struct hostapd_data *hapd); +#endif /* CONFIG_NO_ACCOUNTING */ + +#endif /* ACCOUNTING_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/ap/acs.h b/beken_os/beken378/func/hostapd-2.5/src/ap/acs.h new file mode 100755 index 0000000..fc85259 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/ap/acs.h @@ -0,0 +1,27 @@ +/* + * ACS - Automatic Channel Selection module + * Copyright (c) 2011, Atheros Communications + * Copyright (c) 2013, Qualcomm Atheros, Inc. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef ACS_H +#define ACS_H + +#ifdef CONFIG_ACS + +enum hostapd_chan_status acs_init(struct hostapd_iface *iface); + +#else /* CONFIG_ACS */ + +static inline enum hostapd_chan_status acs_init(struct hostapd_iface *iface) +{ + wpa_printf(MSG_ERROR, "ACS was disabled on your build, rebuild hostapd with CONFIG_ACS=y or set channel"); + return HOSTAPD_CHAN_INVALID; +} + +#endif /* CONFIG_ACS */ + +#endif /* ACS_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/ap/ap_config.c b/beken_os/beken378/func/hostapd-2.5/src/ap/ap_config.c new file mode 100755 index 0000000..f02492f --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/ap/ap_config.c @@ -0,0 +1,645 @@ +/* + * hostapd / Configuration helper functions + * Copyright (c) 2003-2014, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "crypto/sha1.h" +#include "common/ieee802_11_defs.h" +#include "common/eapol_common.h" +#include "wpa_auth.h" +#include "ap/sta_info.h" +#include "ap_config.h" + +void hostapd_config_free_vlan(struct hostapd_bss_config *bss) +{ + struct hostapd_vlan *vlan, *prev; + + vlan = bss->vlan; + prev = NULL; + while (vlan) { + prev = vlan; + vlan = vlan->next; + os_free(prev); + } + + bss->vlan = NULL; +} + +void hostapd_config_defaults_bss(struct hostapd_bss_config *bss) +{ + bss->logger_syslog_level = HOSTAPD_LEVEL_INFO; + bss->logger_stdout_level = HOSTAPD_LEVEL_INFO; + bss->logger_syslog = (unsigned int) -1; + bss->logger_stdout = (unsigned int) -1; + + bss->auth_algs = WPA_AUTH_ALG_OPEN | WPA_AUTH_ALG_SHARED; + + bss->wep_rekeying_period = 300; + /* use key0 in individual key and key1 in broadcast key */ + bss->broadcast_key_idx_min = 1; + bss->broadcast_key_idx_max = 2; + bss->eap_reauth_period = 3600; + + bss->wpa_group_rekey = 600; + bss->wpa_gmk_rekey = 86400; + bss->wpa_key_mgmt = WPA_KEY_MGMT_PSK; + bss->wpa_pairwise = WPA_CIPHER_TKIP; + bss->wpa_group = WPA_CIPHER_TKIP; + bss->rsn_pairwise = 0; + + bss->max_num_sta = MAX_STA_COUNT; + + bss->dtim_period = 2; + + bss->radius_server_auth_port = 1812; + bss->ap_max_inactivity = AP_MAX_INACTIVITY; + bss->eapol_version = EAPOL_VERSION; + + bss->max_listen_interval = 65535; + + bss->pwd_group = 19; /* ECC: GF(p=256) */ + +#ifdef CONFIG_IEEE80211W + bss->assoc_sa_query_max_timeout = 1000; + bss->assoc_sa_query_retry_timeout = 201; + bss->group_mgmt_cipher = WPA_CIPHER_AES_128_CMAC; +#endif /* CONFIG_IEEE80211W */ +#ifdef EAP_SERVER_FAST + /* both anonymous and authenticated provisioning */ + bss->eap_fast_prov = 3; + bss->pac_key_lifetime = 7 * 24 * 60 * 60; + bss->pac_key_refresh_time = 1 * 24 * 60 * 60; +#endif /* EAP_SERVER_FAST */ + + /* Set to -1 as defaults depends on HT in setup */ + bss->wmm_enabled = -1; + +#ifdef CONFIG_IEEE80211R + bss->ft_over_ds = 1; +#endif /* CONFIG_IEEE80211R */ + +#ifdef CONFIG_SAE + bss->sae_anti_clogging_threshold = 5; +#endif +} + + +struct hostapd_config * hostapd_config_defaults(void) +{ +#define ecw2cw(ecw) ((1 << (ecw)) - 1) + + struct hostapd_config *conf; + struct hostapd_bss_config *bss; + const int aCWmin = 4, aCWmax = 10; + const struct hostapd_wmm_ac_params ac_bk = + { aCWmin, aCWmax, 7, 0, 0 }; /* background traffic */ + const struct hostapd_wmm_ac_params ac_be = + { aCWmin, aCWmax, 3, 0, 0 }; /* best effort traffic */ + const struct hostapd_wmm_ac_params ac_vi = /* video traffic */ + { aCWmin - 1, aCWmin, 2, 3008 / 32, 0 }; + const struct hostapd_wmm_ac_params ac_vo = /* voice traffic */ + { aCWmin - 2, aCWmin - 1, 2, 1504 / 32, 0 }; + const struct hostapd_tx_queue_params txq_bk = + { 7, ecw2cw(aCWmin), ecw2cw(aCWmax), 0 }; + const struct hostapd_tx_queue_params txq_be = + { 3, ecw2cw(aCWmin), 4 * (ecw2cw(aCWmin) + 1) - 1, 0}; + const struct hostapd_tx_queue_params txq_vi = + { 1, (ecw2cw(aCWmin) + 1) / 2 - 1, ecw2cw(aCWmin), 30}; + const struct hostapd_tx_queue_params txq_vo = + { 1, (ecw2cw(aCWmin) + 1) / 4 - 1, + (ecw2cw(aCWmin) + 1) / 2 - 1, 15}; + +#undef ecw2cw + + conf = os_zalloc(sizeof(*conf)); + bss = os_zalloc(sizeof(*bss)); + if (conf == NULL || bss == NULL) { + wpa_printf(MSG_ERROR, "Failed to allocate memory for " + "configuration data."); + os_free(conf); + os_free(bss); + return NULL; + } + conf->bss = os_calloc(1, sizeof(struct hostapd_bss_config *)); + if (conf->bss == NULL) { + os_free(conf); + os_free(bss); + return NULL; + } + conf->bss[0] = bss; + + hostapd_config_defaults_bss(bss); + + conf->num_bss = 1; + + conf->beacon_int = 100; + conf->rts_threshold = -1; /* use driver default: 2347 */ + conf->fragm_threshold = -1; /* user driver default: 2346 */ + conf->send_probe_response = 1; + /* Set to invalid value means do not add Power Constraint IE */ + conf->local_pwr_constraint = -1; + + conf->wmm_ac_params[0] = ac_be; + conf->wmm_ac_params[1] = ac_bk; + conf->wmm_ac_params[2] = ac_vi; + conf->wmm_ac_params[3] = ac_vo; + + conf->tx_queue[0] = txq_vo; + conf->tx_queue[1] = txq_vi; + conf->tx_queue[2] = txq_be; + conf->tx_queue[3] = txq_bk; + + conf->ht_capab = HT_CAP_INFO_SMPS_DISABLED; + + conf->ap_table_max_size = 255; + conf->ap_table_expiration_time = 60; + conf->track_sta_max_age = 180; + + conf->acs = 0; + conf->acs_ch_list.num = 0; +#ifdef CONFIG_ACS + conf->acs_num_scans = 5; +#endif /* CONFIG_ACS */ + + return conf; +} + + +int hostapd_mac_comp(const void *a, const void *b) +{ + return os_memcmp(a, b, sizeof(macaddr)); +} + + +int hostapd_mac_comp_empty(const void *a) +{ + macaddr empty = { 0 }; + return os_memcmp(a, empty, sizeof(macaddr)); +} + +static int hostapd_derive_psk(struct hostapd_ssid *ssid) +{ + ssid->wpa_psk = os_zalloc(sizeof(struct hostapd_wpa_psk)); + if (ssid->wpa_psk == NULL) { + wpa_printf(MSG_ERROR, "Unable to alloc space for PSK"); + return -1; + } + wpa_hexdump_ascii(MSG_DEBUG, "SSID", + (u8 *) ssid->ssid, ssid->ssid_len); + wpa_hexdump_ascii_key(MSG_DEBUG, "PSK (ASCII passphrase)", + (u8 *) ssid->wpa_passphrase, + os_strlen(ssid->wpa_passphrase)); + pbkdf2_sha1(ssid->wpa_passphrase, + ssid->ssid, ssid->ssid_len, + 4096, ssid->wpa_psk->psk, PMK_LEN); + wpa_hexdump_key(MSG_DEBUG, "PSK (from passphrase)", + ssid->wpa_psk->psk, PMK_LEN); + return 0; +} + + +int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf) +{ + struct hostapd_ssid *ssid = &conf->ssid; + + if (ssid->wpa_passphrase != NULL) { + if (ssid->wpa_psk != NULL) { + wpa_printf(MSG_DEBUG, "Using pre-configured WPA PSK " + "instead of passphrase"); + } else { + wpa_printf(MSG_DEBUG, "Deriving WPA PSK based on " + "passphrase"); + if (hostapd_derive_psk(ssid) < 0) + return -1; + } + ssid->wpa_psk->group = 1; + } + + return 0; +} + +static void hostapd_config_free_wep(struct hostapd_wep_keys *keys) +{ + int i; + for (i = 0; i < NUM_WEP_KEYS; i++) { + bin_clear_free(keys->key[i], keys->len[i]); + keys->key[i] = NULL; + } +} + + +void hostapd_config_clear_wpa_psk(struct hostapd_wpa_psk **l) +{ + struct hostapd_wpa_psk *psk, *tmp; + + for (psk = *l; psk;) { + tmp = psk; + psk = psk->next; + bin_clear_free(tmp, sizeof(*tmp)); + } + *l = NULL; +} + + +void hostapd_config_free_bss(struct hostapd_bss_config *conf) +{ + struct hostapd_eap_user *user, *prev_user; + + if (conf == NULL) + return; + + hostapd_config_clear_wpa_psk(&conf->ssid.wpa_psk); + + str_clear_free(conf->ssid.wpa_passphrase); + hostapd_config_free_wep(&conf->ssid.wep); +#ifdef CONFIG_FULL_DYNAMIC_VLAN + os_free(conf->ssid.vlan_tagged_interface); +#endif /* CONFIG_FULL_DYNAMIC_VLAN */ + + os_free(conf->rsn_preauth_interfaces); + os_free(conf->ctrl_interface); + os_free(conf->ca_cert); + os_free(conf->server_cert); + os_free(conf->private_key); + os_free(conf->private_key_passwd); + os_free(conf->ocsp_stapling_response); + os_free(conf->dh_file); + os_free(conf->openssl_ciphers); + os_free(conf->pac_opaque_encr_key); + os_free(conf->eap_fast_a_id); + os_free(conf->eap_fast_a_id_info); + os_free(conf->time_zone); + +#ifdef CONFIG_IEEE80211R + { + struct ft_remote_r0kh *r0kh, *r0kh_prev; + struct ft_remote_r1kh *r1kh, *r1kh_prev; + + r0kh = conf->r0kh_list; + conf->r0kh_list = NULL; + while (r0kh) { + r0kh_prev = r0kh; + r0kh = r0kh->next; + os_free(r0kh_prev); + } + + r1kh = conf->r1kh_list; + conf->r1kh_list = NULL; + while (r1kh) { + r1kh_prev = r1kh; + r1kh = r1kh->next; + os_free(r1kh_prev); + } + } +#endif /* CONFIG_IEEE80211R */ + + os_free(conf->roaming_consortium); + os_free(conf->venue_name); + os_free(conf->nai_realm_data); + os_free(conf->network_auth_type); + os_free(conf->anqp_3gpp_cell_net); + os_free(conf->domain_name); + + wpabuf_free(conf->vendor_elements); + + os_free(conf->sae_groups); + + os_free(conf->wowlan_triggers); + + os_free(conf->server_id); + + os_free(conf->no_probe_resp_if_seen_on); + os_free(conf->no_auth_if_seen_on); + + os_free(conf); + + user = user; + prev_user = prev_user; +} + + +/** + * hostapd_config_free - Free hostapd configuration + * @conf: Configuration data from hostapd_config_read(). + */ +void hostapd_config_free(struct hostapd_config *conf) +{ + size_t i; + + if (conf == NULL) + return; + + for (i = 0; i < conf->num_bss; i++) + hostapd_config_free_bss(conf->bss[i]); + os_free(conf->bss); + os_free(conf->supported_rates); + os_free(conf->basic_rates); + os_free(conf->acs_ch_list.range); + os_free(conf->driver_params); +#ifdef CONFIG_ACS + os_free(conf->acs_chan_bias); +#endif /* CONFIG_ACS */ + + os_free(conf); +} + + +/** + * hostapd_maclist_found - Find a MAC address from a list + * @list: MAC address list + * @num_entries: Number of addresses in the list + * @addr: Address to search for + * @vlan_id: Buffer for returning VLAN ID or %NULL if not needed + * Returns: 1 if address is in the list or 0 if not. + * + * Perform a binary search for given MAC address from a pre-sorted list. + */ +int hostapd_maclist_found(struct mac_acl_entry *list, int num_entries, + const u8 *addr, int *vlan_id) +{ + int start, end, middle, res; + + start = 0; + end = num_entries - 1; + + while (start <= end) { + middle = (start + end) / 2; + res = os_memcmp(list[middle].addr, addr, ETH_ALEN); + if (res == 0) { + if (vlan_id) + *vlan_id = list[middle].vlan_id; + return 1; + } + if (res < 0) + start = middle + 1; + else + end = middle - 1; + } + + return 0; +} + + +int hostapd_rate_found(int *list, int rate) +{ + int i; + + if (list == NULL) + return 0; + + for (i = 0; list[i] >= 0; i++) + if (list[i] == rate) + return 1; + + return 0; +} + +const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf, + const u8 *addr, const u8 *p2p_dev_addr, + const u8 *prev_psk) +{ + struct hostapd_wpa_psk *psk; + int next_ok = prev_psk == NULL; + + if (p2p_dev_addr && !is_zero_ether_addr(p2p_dev_addr)) { + wpa_printf(MSG_DEBUG, "Searching a PSK for " MACSTR + " p2p_dev_addr=" MACSTR " prev_psk=%p", + MAC2STR(addr), MAC2STR(p2p_dev_addr), prev_psk); + addr = NULL; /* Use P2P Device Address for matching */ + } else { + wpa_printf(MSG_DEBUG, "Searching a PSK for " MACSTR + " prev_psk=%p", + MAC2STR(addr), prev_psk); + } + + for (psk = conf->ssid.wpa_psk; psk != NULL; psk = psk->next) { + if (next_ok && + (psk->group || + (addr && os_memcmp(psk->addr, addr, ETH_ALEN) == 0) || + (!addr && p2p_dev_addr && + os_memcmp(psk->p2p_dev_addr, p2p_dev_addr, ETH_ALEN) == + 0))) + return psk->psk; + + if (psk->psk == prev_psk) + next_ok = 1; + } + + return NULL; +} + + +static int hostapd_config_check_bss(struct hostapd_bss_config *bss, + struct hostapd_config *conf, + int full_config) +{ + if (bss->wpa) { + int wep, i; + + wep = bss->default_wep_key_len > 0 || + bss->individual_wep_key_len > 0; + for (i = 0; i < NUM_WEP_KEYS; i++) { + if (bss->ssid.wep.keys_set) { + wep = 1; + break; + } + } + + if (wep) { + wpa_printf(MSG_ERROR, "WEP configuration in a WPA network is not supported"); + return -1; + } + } + + if (full_config && hostapd_mac_comp_empty(bss->bssid) != 0) { + size_t i; + + for (i = 0; i < conf->num_bss; i++) { + if (conf->bss[i] != bss && + (hostapd_mac_comp(conf->bss[i]->bssid, + bss->bssid) == 0)) { + wpa_printf(MSG_ERROR, "Duplicate BSSID " MACSTR + " on interface '%s' and '%s'.", + MAC2STR(bss->bssid), + conf->bss[i]->iface, bss->iface); + return -1; + } + } + } + +#ifdef CONFIG_IEEE80211R + if (full_config && wpa_key_mgmt_ft(bss->wpa_key_mgmt) && + (bss->nas_identifier == NULL || + os_strlen(bss->nas_identifier) < 1 || + os_strlen(bss->nas_identifier) > FT_R0KH_ID_MAX_LEN)) { + wpa_printf(MSG_ERROR, "FT (IEEE 802.11r) requires " + "nas_identifier to be configured as a 1..48 octet " + "string"); + return -1; + } +#endif /* CONFIG_IEEE80211R */ + +#ifdef CONFIG_IEEE80211N + if (full_config && conf->ieee80211n && + conf->hw_mode == HOSTAPD_MODE_IEEE80211B) { + bss->disable_11n = 1; + wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) in 11b mode is not " + "allowed, disabling HT capabilities"); + } + + if (full_config && conf->ieee80211n && + bss->ssid.security_policy == SECURITY_STATIC_WEP) { + bss->disable_11n = 1; + wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WEP is not " + "allowed, disabling HT capabilities"); + } + + if (full_config && conf->ieee80211n && bss->wpa && + !(bss->wpa_pairwise & WPA_CIPHER_CCMP) && + !(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP | + WPA_CIPHER_CCMP_256 | WPA_CIPHER_GCMP_256))) + { + bss->disable_11n = 1; + wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WPA/WPA2 " + "requires CCMP/GCMP to be enabled, disabling HT " + "capabilities"); + } +#endif /* CONFIG_IEEE80211N */ + + return 0; +} + + +static int hostapd_config_check_cw(struct hostapd_config *conf, int queue) +{ + int tx_cwmin = conf->tx_queue[queue].cwmin; + int tx_cwmax = conf->tx_queue[queue].cwmax; + int ac_cwmin = conf->wmm_ac_params[queue].cwmin; + int ac_cwmax = conf->wmm_ac_params[queue].cwmax; + + if (tx_cwmin > tx_cwmax) { + wpa_printf(MSG_ERROR, + "Invalid TX queue cwMin/cwMax values. cwMin(%d) greater than cwMax(%d)", + tx_cwmin, tx_cwmax); + return -1; + } + if (ac_cwmin > ac_cwmax) { + wpa_printf(MSG_ERROR, + "Invalid WMM AC cwMin/cwMax values. cwMin(%d) greater than cwMax(%d)", + ac_cwmin, ac_cwmax); + return -1; + } + return 0; +} + + +int hostapd_config_check(struct hostapd_config *conf, int full_config) +{ + size_t i; + + if (full_config && conf->ieee80211d && + (!conf->country[0] || !conf->country[1])) { + wpa_printf(MSG_ERROR, "Cannot enable IEEE 802.11d without " + "setting the country_code"); + return -1; + } + + if (full_config && conf->ieee80211h && !conf->ieee80211d) { + wpa_printf(MSG_ERROR, "Cannot enable IEEE 802.11h without " + "IEEE 802.11d enabled"); + return -1; + } + + if (full_config && conf->local_pwr_constraint != -1 && + !conf->ieee80211d) { + wpa_printf(MSG_ERROR, "Cannot add Power Constraint element without Country element"); + return -1; + } + + if (full_config && conf->spectrum_mgmt_required && + conf->local_pwr_constraint == -1) { + wpa_printf(MSG_ERROR, "Cannot set Spectrum Management bit without Country and Power Constraint elements"); + return -1; + } + + for (i = 0; i < NUM_TX_QUEUES; i++) { + if (hostapd_config_check_cw(conf, i)) + return -1; + } + + for (i = 0; i < conf->num_bss; i++) { + if (hostapd_config_check_bss(conf->bss[i], conf, full_config)) + return -1; + } + + return 0; +} + + +void hostapd_set_security_params(struct hostapd_bss_config *bss, + int full_config) +{ + if (bss->individual_wep_key_len == 0) { + /* individual keys are not use; can use key idx0 for + * broadcast keys */ + bss->broadcast_key_idx_min = 0; + } + + if ((bss->wpa & 2) && bss->rsn_pairwise == 0) + bss->rsn_pairwise = bss->wpa_pairwise; + bss->wpa_group = wpa_select_ap_group_cipher(bss->wpa, bss->wpa_pairwise, + bss->rsn_pairwise); + + if (bss->wpa && bss->ieee802_1x) { + bss->ssid.security_policy = SECURITY_WPA; + } else if (bss->wpa) { + bss->ssid.security_policy = SECURITY_WPA_PSK; + } else if (bss->ieee802_1x) { + int cipher = WPA_CIPHER_NONE; + bss->ssid.security_policy = SECURITY_IEEE_802_1X; + bss->ssid.wep.default_len = bss->default_wep_key_len; + if (full_config && bss->default_wep_key_len) { + cipher = bss->default_wep_key_len >= 13 ? + WPA_CIPHER_WEP104 : WPA_CIPHER_WEP40; + } else if (full_config && bss->ssid.wep.keys_set) { + if (bss->ssid.wep.len[0] >= 13) + cipher = WPA_CIPHER_WEP104; + else + cipher = WPA_CIPHER_WEP40; + } + bss->wpa_group = cipher; + bss->wpa_pairwise = cipher; + bss->rsn_pairwise = cipher; + if (full_config) + bss->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA; + } else if (bss->ssid.wep.keys_set) { + int cipher = WPA_CIPHER_WEP40; + if (bss->ssid.wep.len[0] >= 13) + cipher = WPA_CIPHER_WEP104; + bss->ssid.security_policy = SECURITY_STATIC_WEP; + bss->wpa_group = cipher; + bss->wpa_pairwise = cipher; + bss->rsn_pairwise = cipher; + if (full_config) + bss->wpa_key_mgmt = WPA_KEY_MGMT_NONE; + } else if (bss->osen) { + bss->ssid.security_policy = SECURITY_OSEN; + bss->wpa_group = WPA_CIPHER_CCMP; + bss->wpa_pairwise = 0; + bss->rsn_pairwise = WPA_CIPHER_CCMP; + } else { + bss->ssid.security_policy = SECURITY_PLAINTEXT; + if (full_config) { + bss->wpa_group = WPA_CIPHER_NONE; + bss->wpa_pairwise = WPA_CIPHER_NONE; + bss->rsn_pairwise = WPA_CIPHER_NONE; + bss->wpa_key_mgmt = WPA_KEY_MGMT_NONE; + } + } +} diff --git a/beken_os/beken378/func/hostapd-2.5/src/ap/ap_config.h b/beken_os/beken378/func/hostapd-2.5/src/ap/ap_config.h new file mode 100755 index 0000000..eca58ae --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/ap/ap_config.h @@ -0,0 +1,701 @@ +/* + * hostapd / Configuration definitions and helpers functions + * Copyright (c) 2003-2015, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef HOSTAPD_CONFIG_H +#define HOSTAPD_CONFIG_H + +#include "common/defs.h" +#include "ip_addr.h" +#include "common/wpa_common.h" +#include "common/ieee802_11_defs.h" +#include "common/ieee802_11_common.h" +#include "wps/wps.h" + +/** + * mesh_conf - local MBSS state and settings + */ +struct mesh_conf { + u8 meshid[32]; + u8 meshid_len; + /* Active Path Selection Protocol Identifier */ + u8 mesh_pp_id; + /* Active Path Selection Metric Identifier */ + u8 mesh_pm_id; + /* Congestion Control Mode Identifier */ + u8 mesh_cc_id; + /* Synchronization Protocol Identifier */ + u8 mesh_sp_id; + /* Authentication Protocol Identifier */ + u8 mesh_auth_id; + u8 *rsn_ie; + int rsn_ie_len; +#define MESH_CONF_SEC_NONE BIT(0) +#define MESH_CONF_SEC_AUTH BIT(1) +#define MESH_CONF_SEC_AMPE BIT(2) + unsigned int security; + int dot11MeshMaxRetries; + int dot11MeshRetryTimeout; /* msec */ + int dot11MeshConfirmTimeout; /* msec */ + int dot11MeshHoldingTimeout; /* msec */ +}; + +#define MAX_STA_COUNT 2007 +#define MAX_VLAN_ID 4094 + +typedef u8 macaddr[ETH_ALEN]; + +struct mac_acl_entry { + macaddr addr; + int vlan_id; +}; + +struct hostapd_radius_servers; +struct ft_remote_r0kh; +struct ft_remote_r1kh; + +#define NUM_WEP_KEYS 4 +struct hostapd_wep_keys { + u8 idx; + u8 *key[NUM_WEP_KEYS]; + size_t len[NUM_WEP_KEYS]; + int keys_set; + size_t default_len; /* key length used for dynamic key generation */ +}; + +typedef enum hostap_security_policy { + SECURITY_PLAINTEXT = 0, + SECURITY_STATIC_WEP = 1, + SECURITY_IEEE_802_1X = 2, + SECURITY_WPA_PSK = 3, + SECURITY_WPA = 4, + SECURITY_OSEN = 5 +} secpolicy; + +struct hostapd_ssid { + u8 ssid[SSID_MAX_LEN]; + size_t ssid_len; + unsigned int ssid_set:1; + unsigned int utf8_ssid:1; + unsigned int wpa_passphrase_set:1; + unsigned int wpa_psk_set:1; + +#ifndef CONFIG_NO_VLAN + char vlan[IFNAMSIZ + 1]; +#endif + secpolicy security_policy; + + struct hostapd_wpa_psk *wpa_psk; + char *wpa_passphrase; + + struct hostapd_wep_keys wep; + +#define DYNAMIC_VLAN_DISABLED 0 +#define DYNAMIC_VLAN_OPTIONAL 1 +#define DYNAMIC_VLAN_REQUIRED 2 + int dynamic_vlan; +#define DYNAMIC_VLAN_NAMING_WITHOUT_DEVICE 0 +#define DYNAMIC_VLAN_NAMING_WITH_DEVICE 1 +#define DYNAMIC_VLAN_NAMING_END 2 + int vlan_naming; +#ifdef CONFIG_FULL_DYNAMIC_VLAN + char *vlan_tagged_interface; +#endif /* CONFIG_FULL_DYNAMIC_VLAN */ +}; + + +#define VLAN_ID_WILDCARD -1 + +struct hostapd_vlan { + struct hostapd_vlan *next; + int vlan_id; /* VLAN ID or -1 (VLAN_ID_WILDCARD) for wildcard entry */ + char ifname[IFNAMSIZ + 1]; + int configured; + int dynamic_vlan; +#ifdef CONFIG_FULL_DYNAMIC_VLAN + +#define DVLAN_CLEAN_WLAN_PORT 0x8 + int clean; +#endif /* CONFIG_FULL_DYNAMIC_VLAN */ +}; + +#define PMK_LEN 32 +struct hostapd_sta_wpa_psk_short { + struct hostapd_sta_wpa_psk_short *next; + u8 psk[PMK_LEN]; +}; + +struct hostapd_wpa_psk { + struct hostapd_wpa_psk *next; + int group; + u8 psk[PMK_LEN]; + u8 addr[ETH_ALEN]; + u8 p2p_dev_addr[ETH_ALEN]; +}; + +struct hostapd_eap_user { + struct hostapd_eap_user *next; + u8 *identity; + size_t identity_len; + struct { + int vendor; + u32 method; + } methods[EAP_MAX_METHODS]; + u8 *password; + size_t password_len; + int phase2; + int force_version; + unsigned int wildcard_prefix:1; + unsigned int password_hash:1; /* whether password is hashed with + * nt_password_hash() */ + unsigned int remediation:1; + unsigned int macacl:1; + int ttls_auth; /* EAP_TTLS_AUTH_* bitfield */ + struct hostapd_radius_attr *accept_attr; +}; + +struct hostapd_radius_attr { + u8 type; + struct wpabuf *val; + struct hostapd_radius_attr *next; +}; + + +#define NUM_TX_QUEUES 4 + +struct hostapd_tx_queue_params { + int aifs; + int cwmin; + int cwmax; + int burst; /* maximum burst time in 0.1 ms, i.e., 10 = 1 ms */ +}; + + +#define MAX_ROAMING_CONSORTIUM_LEN 15 + +struct hostapd_roaming_consortium { + u8 len; + u8 oi[MAX_ROAMING_CONSORTIUM_LEN]; +}; + +struct hostapd_lang_string { + u8 lang[3]; + u8 name_len; + u8 name[252]; +}; + +#define MAX_NAI_REALMS 10 +#define MAX_NAI_REALMLEN 255 +#define MAX_NAI_EAP_METHODS 5 +#define MAX_NAI_AUTH_TYPES 4 +struct hostapd_nai_realm_data { + u8 encoding; + char realm_buf[MAX_NAI_REALMLEN + 1]; + char *realm[MAX_NAI_REALMS]; + u8 eap_method_count; + struct hostapd_nai_realm_eap { + u8 eap_method; + u8 num_auths; + u8 auth_id[MAX_NAI_AUTH_TYPES]; + u8 auth_val[MAX_NAI_AUTH_TYPES]; + } eap_method[MAX_NAI_EAP_METHODS]; +}; + +/** + * struct hostapd_bss_config - Per-BSS configuration + */ +struct hostapd_bss_config { + char iface[IFNAMSIZ + 1]; +#ifdef CONFIG_FULL_HOSTAPD + char bridge[IFNAMSIZ + 1]; + char vlan_bridge[IFNAMSIZ + 1]; + char wds_bridge[IFNAMSIZ + 1]; +#endif + enum hostapd_logger_level logger_syslog_level, logger_stdout_level; + + unsigned int logger_syslog; /* module bitfield */ + unsigned int logger_stdout; /* module bitfield */ + + int max_num_sta; /* maximum number of STAs in station table */ + + int dtim_period; +#ifdef CONFIG_FULL_HOSTAPD + int bss_load_update_period; +#endif + + int ieee802_1x; /* use IEEE 802.1X */ + int eapol_version; +#ifdef CONFIG_FULL_HOSTAPD + int eap_server; /* Use internal EAP server instead of external + * RADIUS server */ + struct hostapd_eap_user *eap_user; + char *eap_user_sqlite; + char *eap_sim_db; + int eap_server_erp; /* Whether ERP is enabled on internal EAP server */ + struct hostapd_ip_addr own_ip_addr; + char *nas_identifier; + struct hostapd_radius_servers *radius; + int acct_interim_interval; + int radius_request_cui; + struct hostapd_radius_attr *radius_auth_req_attr; + struct hostapd_radius_attr *radius_acct_req_attr; + int radius_das_port; + unsigned int radius_das_time_window; + int radius_das_require_event_timestamp; + struct hostapd_ip_addr radius_das_client_addr; + u8 *radius_das_shared_secret; + size_t radius_das_shared_secret_len; +#endif + + struct hostapd_ssid ssid; + + char *eap_req_id_text; /* optional displayable message sent with + * EAP Request-Identity */ + size_t eap_req_id_text_len; + int eapol_key_index_workaround; + + size_t default_wep_key_len; + int individual_wep_key_len; + int wep_rekeying_period; + int broadcast_key_idx_min, broadcast_key_idx_max; + int eap_reauth_period; + int erp_send_reauth_start; + char *erp_domain; + +#ifdef CONFIG_FULL_HOSTAPD + int ieee802_11f; /* use IEEE 802.11f (IAPP) */ + char iapp_iface[IFNAMSIZ + 1]; /* interface used with IAPP broadcast + * frames */ + enum { + ACCEPT_UNLESS_DENIED = 0, + DENY_UNLESS_ACCEPTED = 1, + USE_EXTERNAL_RADIUS_AUTH = 2 + } macaddr_acl; + struct mac_acl_entry *accept_mac; + int num_accept_mac; + struct mac_acl_entry *deny_mac; + int num_deny_mac; + int wds_sta; +#endif + int isolate; + int start_disabled; + + int auth_algs; /* bitfield of allowed IEEE 802.11 authentication + * algorithms, WPA_AUTH_ALG_{OPEN,SHARED,LEAP} */ + + int wpa; /* bitfield of WPA_PROTO_WPA, WPA_PROTO_RSN */ + int wpa_key_mgmt; +#ifdef CONFIG_IEEE80211W + enum mfp_options ieee80211w; + int group_mgmt_cipher; + /* dot11AssociationSAQueryMaximumTimeout (in TUs) */ + unsigned int assoc_sa_query_max_timeout; + /* dot11AssociationSAQueryRetryTimeout (in TUs) */ + int assoc_sa_query_retry_timeout; +#endif /* CONFIG_IEEE80211W */ + enum { + PSK_RADIUS_IGNORED = 0, + PSK_RADIUS_ACCEPTED = 1, + PSK_RADIUS_REQUIRED = 2 + } wpa_psk_radius; + int wpa_pairwise; + int wpa_group; + int wpa_group_rekey; + int wpa_strict_rekey; + int wpa_gmk_rekey; + int wpa_ptk_rekey; + int rsn_pairwise; + int rsn_preauth; + char *rsn_preauth_interfaces; + int peerkey; + +#ifdef CONFIG_IEEE80211R + /* IEEE 802.11r - Fast BSS Transition */ + u8 mobility_domain[MOBILITY_DOMAIN_ID_LEN]; + u8 r1_key_holder[FT_R1KH_ID_LEN]; + u32 r0_key_lifetime; + u32 reassociation_deadline; + struct ft_remote_r0kh *r0kh_list; + struct ft_remote_r1kh *r1kh_list; + int pmk_r1_push; + int ft_over_ds; +#endif /* CONFIG_IEEE80211R */ + + char *ctrl_interface; /* directory for UNIX domain sockets */ +#ifndef CONFIG_NATIVE_WINDOWS + int ctrl_interface_gid; +#endif /* CONFIG_NATIVE_WINDOWS */ + int ctrl_interface_gid_set; + + char *ca_cert; + char *server_cert; + char *private_key; + char *private_key_passwd; + int check_crl; + unsigned int tls_session_lifetime; + char *ocsp_stapling_response; + char *dh_file; + char *openssl_ciphers; + u8 *pac_opaque_encr_key; + u8 *eap_fast_a_id; + size_t eap_fast_a_id_len; + char *eap_fast_a_id_info; + int eap_fast_prov; + int pac_key_lifetime; + int pac_key_refresh_time; + int eap_sim_aka_result_ind; + int tnc; + int fragment_size; + u16 pwd_group; + + char *radius_server_clients; + int radius_server_auth_port; + int radius_server_acct_port; + int radius_server_ipv6; + + int use_pae_group_addr; /* Whether to send EAPOL frames to PAE group + * address instead of individual address + * (for driver_wired.c). + */ + + int ap_max_inactivity; + int ignore_broadcast_ssid; + + int wmm_enabled; + int wmm_uapsd; + + struct hostapd_vlan *vlan; + + macaddr bssid; + + /* + * Maximum listen interval that STAs can use when associating with this + * BSS. If a STA tries to use larger value, the association will be + * denied with status code 51. + */ + u16 max_listen_interval; + + int disable_pmksa_caching; + int okc; /* Opportunistic Key Caching */ + + int wps_state; +#ifdef CONFIG_WPS + int wps_independent; + int ap_setup_locked; + u8 uuid[16]; + char *wps_pin_requests; + char *device_name; + char *manufacturer; + char *model_name; + char *model_number; + char *serial_number; + u8 device_type[WPS_DEV_TYPE_LEN]; + char *config_methods; + u8 os_version[4]; + char *ap_pin; + int skip_cred_build; + u8 *extra_cred; + size_t extra_cred_len; + int wps_cred_processing; + int force_per_enrollee_psk; + u8 *ap_settings; + size_t ap_settings_len; + char *upnp_iface; + char *friendly_name; + char *manufacturer_url; + char *model_description; + char *model_url; + char *upc; + struct wpabuf *wps_vendor_ext[MAX_WPS_VENDOR_EXTENSIONS]; + int wps_nfc_pw_from_config; + int wps_nfc_dev_pw_id; + struct wpabuf *wps_nfc_dh_pubkey; + struct wpabuf *wps_nfc_dh_privkey; + struct wpabuf *wps_nfc_dev_pw; +#endif /* CONFIG_WPS */ + int pbc_in_m1; + char *server_id; + +#define P2P_ENABLED BIT(0) +#define P2P_GROUP_OWNER BIT(1) +#define P2P_GROUP_FORMATION BIT(2) +#define P2P_MANAGE BIT(3) +#define P2P_ALLOW_CROSS_CONNECTION BIT(4) + int p2p; +#ifdef CONFIG_P2P + u8 ip_addr_go[4]; + u8 ip_addr_mask[4]; + u8 ip_addr_start[4]; + u8 ip_addr_end[4]; +#endif /* CONFIG_P2P */ + + int disassoc_low_ack; + int skip_inactivity_poll; + +#define TDLS_PROHIBIT BIT(0) +#define TDLS_PROHIBIT_CHAN_SWITCH BIT(1) + int tdls; + int disable_11n; + int disable_11ac; + + /* IEEE 802.11v */ + int time_advertisement; + char *time_zone; + int wnm_sleep_mode; + int bss_transition; + + /* IEEE 802.11u - Interworking */ + int interworking; + int access_network_type; + int internet; + int asra; + int esr; + int uesa; + int venue_info_set; + u8 venue_group; + u8 venue_type; + u8 hessid[ETH_ALEN]; + + /* IEEE 802.11u - Roaming Consortium list */ + unsigned int roaming_consortium_count; + struct hostapd_roaming_consortium *roaming_consortium; + + /* IEEE 802.11u - Venue Name duples */ + unsigned int venue_name_count; + struct hostapd_lang_string *venue_name; + + /* IEEE 802.11u - Network Authentication Type */ + u8 *network_auth_type; + size_t network_auth_type_len; + + /* IEEE 802.11u - IP Address Type Availability */ + u8 ipaddr_type_availability; + u8 ipaddr_type_configured; + + /* IEEE 802.11u - 3GPP Cellular Network */ + u8 *anqp_3gpp_cell_net; + size_t anqp_3gpp_cell_net_len; + + /* IEEE 802.11u - Domain Name */ + u8 *domain_name; + size_t domain_name_len; + + unsigned int nai_realm_count; + struct hostapd_nai_realm_data *nai_realm_data; + + u16 gas_comeback_delay; + int gas_frag_limit; + + u8 qos_map_set[16 + 2 * 21]; + unsigned int qos_map_set_len; + + int osen; + int proxy_arp; + int na_mcast_to_ucast; +#ifdef CONFIG_HS20 + int hs20; + int disable_dgaf; + u16 anqp_domain_id; + unsigned int hs20_oper_friendly_name_count; + struct hostapd_lang_string *hs20_oper_friendly_name; + u8 *hs20_wan_metrics; + u8 *hs20_connection_capability; + size_t hs20_connection_capability_len; + u8 *hs20_operating_class; + u8 hs20_operating_class_len; + struct hs20_icon { + u16 width; + u16 height; + char language[3]; + char type[256]; + char name[256]; + char file[256]; + } *hs20_icons; + size_t hs20_icons_count; + u8 osu_ssid[SSID_MAX_LEN]; + size_t osu_ssid_len; + struct hs20_osu_provider { + unsigned int friendly_name_count; + struct hostapd_lang_string *friendly_name; + char *server_uri; + int *method_list; + char **icons; + size_t icons_count; + char *osu_nai; + unsigned int service_desc_count; + struct hostapd_lang_string *service_desc; + } *hs20_osu_providers, *last_osu; + size_t hs20_osu_providers_count; + unsigned int hs20_deauth_req_timeout; + char *subscr_remediation_url; + u8 subscr_remediation_method; +#endif /* CONFIG_HS20 */ + + u8 wps_rf_bands; /* RF bands for WPS (WPS_RF_*) */ + +#ifdef CONFIG_RADIUS_TEST + char *dump_msk_file; +#endif /* CONFIG_RADIUS_TEST */ + + struct wpabuf *vendor_elements; + + unsigned int sae_anti_clogging_threshold; + int *sae_groups; + + char *wowlan_triggers; /* Wake-on-WLAN triggers */ + +#ifdef CONFIG_TESTING_OPTIONS + u8 bss_load_test[5]; + u8 bss_load_test_set; + struct wpabuf *own_ie_override; +#endif /* CONFIG_TESTING_OPTIONS */ + +#define MESH_ENABLED BIT(0) + int mesh; + + int radio_measurements; + + int vendor_vht; + + char *no_probe_resp_if_seen_on; + char *no_auth_if_seen_on; +}; + + +/** + * struct hostapd_config - Per-radio interface configuration + */ + +struct hostapd_config { + struct hostapd_bss_config **bss, *last_bss; + size_t num_bss; + + u16 beacon_int; + int rts_threshold; + int fragm_threshold; + u8 send_probe_response; + u8 channel; + u8 acs; + struct wpa_freq_range_list acs_ch_list; + enum hostapd_hw_mode hw_mode; /* HOSTAPD_MODE_IEEE80211A, .. */ + + enum { + LONG_PREAMBLE = 0, + SHORT_PREAMBLE = 1 + } preamble; + + int *supported_rates; + int *basic_rates; + + const struct wpa_driver_ops *driver; + char *driver_params; + + int ap_table_max_size; + int ap_table_expiration_time; + + unsigned int track_sta_max_num; + unsigned int track_sta_max_age; + + char country[3]; /* first two octets: country code as described in + * ISO/IEC 3166-1. Third octet: + * ' ' (ascii 32): all environments + * 'O': Outdoor environemnt only + * 'I': Indoor environment only + */ + + int ieee80211d; + + int ieee80211h; /* DFS */ + + /* + * Local power constraint is an octet encoded as an unsigned integer in + * units of decibels. Invalid value -1 indicates that Power Constraint + * element will not be added. + */ + int local_pwr_constraint; + + /* Control Spectrum Management bit */ + int spectrum_mgmt_required; + + struct hostapd_tx_queue_params tx_queue[NUM_TX_QUEUES]; + + /* + * WMM AC parameters, in same order as 802.1D, i.e. + * 0 = BE (best effort) + * 1 = BK (background) + * 2 = VI (video) + * 3 = VO (voice) + */ + struct hostapd_wmm_ac_params wmm_ac_params[4]; + + int ht_op_mode_fixed; + u16 ht_capab; + int ht_no_overlap_check; + int ieee80211n; + int secondary_channel; + int no_pri_sec_switch; + int require_ht; + int obss_interval; + u32 vht_capab; + int ieee80211ac; + int require_vht; + u8 vht_oper_chwidth; + u8 vht_oper_centr_freq_seg0_idx; + u8 vht_oper_centr_freq_seg1_idx; + +#ifdef CONFIG_FST + struct fst_iface_cfg fst_cfg; +#endif /* CONFIG_FST */ + +#ifdef CONFIG_P2P + u8 p2p_go_ctwindow; +#endif /* CONFIG_P2P */ + +#ifdef CONFIG_TESTING_OPTIONS + double ignore_probe_probability; + double ignore_auth_probability; + double ignore_assoc_probability; + double ignore_reassoc_probability; + double corrupt_gtk_rekey_mic_probability; +#endif /* CONFIG_TESTING_OPTIONS */ + +#ifdef CONFIG_ACS + unsigned int acs_num_scans; + struct acs_bias { + int channel; + double bias; + } *acs_chan_bias; + unsigned int num_acs_chan_bias; +#endif /* CONFIG_ACS */ +}; + + +int hostapd_mac_comp(const void *a, const void *b); +int hostapd_mac_comp_empty(const void *a); +struct hostapd_config * hostapd_config_defaults(void); +void hostapd_config_defaults_bss(struct hostapd_bss_config *bss); +void hostapd_config_free_eap_user(struct hostapd_eap_user *user); +void hostapd_config_clear_wpa_psk(struct hostapd_wpa_psk **p); +void hostapd_config_free_bss(struct hostapd_bss_config *conf); +void hostapd_config_free(struct hostapd_config *conf); +int hostapd_maclist_found(struct mac_acl_entry *list, int num_entries, + const u8 *addr, int *vlan_id); +int hostapd_rate_found(int *list, int rate); +const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf, + const u8 *addr, const u8 *p2p_dev_addr, + const u8 *prev_psk); +int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf); +int hostapd_vlan_id_valid(struct hostapd_vlan *vlan, int vlan_id); +const char * hostapd_get_vlan_id_ifname(struct hostapd_vlan *vlan, + int vlan_id); +struct hostapd_radius_attr * +hostapd_config_get_radius_attr(struct hostapd_radius_attr *attr, u8 type); +int hostapd_config_check(struct hostapd_config *conf, int full_config); +void hostapd_set_security_params(struct hostapd_bss_config *bss, + int full_config); + +#endif /* HOSTAPD_CONFIG_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/ap/ap_drv_ops.c b/beken_os/beken378/func/hostapd-2.5/src/ap/ap_drv_ops.c new file mode 100755 index 0000000..72104fd --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/ap/ap_drv_ops.c @@ -0,0 +1,809 @@ +/* + * hostapd - Driver operations + * Copyright (c) 2009-2010, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "common/ieee802_11_defs.h" +#include "common/hw_features_common.h" +#include "wps/wps.h" +#include "ap/hostapd.h" +#include "ieee802_11.h" +#include "ap/sta_info.h" +#include "ap_config.h" +#include "p2p_hostapd.h" +#include "ap_drv_ops.h" + + +u32 hostapd_sta_flags_to_drv(u32 flags) +{ + int res = 0; + if (flags & WLAN_STA_AUTHORIZED) + res |= WPA_STA_AUTHORIZED; + if (flags & WLAN_STA_WMM) + res |= WPA_STA_WMM; + if (flags & WLAN_STA_SHORT_PREAMBLE) + res |= WPA_STA_SHORT_PREAMBLE; + if (flags & WLAN_STA_MFP) + res |= WPA_STA_MFP; + return res; +} + + +int hostapd_build_ap_extra_ies(struct hostapd_data *hapd, + struct wpabuf **beacon_ret, + struct wpabuf **proberesp_ret, + struct wpabuf **assocresp_ret) +{ + struct wpabuf *beacon = NULL, *proberesp = NULL, *assocresp = NULL; + u8 buf[200], *pos; + + *beacon_ret = *proberesp_ret = *assocresp_ret = NULL; + + pos = buf; + pos = hostapd_eid_time_adv(hapd, pos); + if (pos != buf) { + if (wpabuf_resize(&beacon, pos - buf) != 0) + goto fail; + wpabuf_put_data(beacon, buf, pos - buf); + } + pos = hostapd_eid_time_zone(hapd, pos); + if (pos != buf) { + if (wpabuf_resize(&proberesp, pos - buf) != 0) + goto fail; + wpabuf_put_data(proberesp, buf, pos - buf); + } + + pos = buf; + pos = hostapd_eid_ext_capab(hapd, pos); + if (pos != buf) { + if (wpabuf_resize(&assocresp, pos - buf) != 0) + goto fail; + wpabuf_put_data(assocresp, buf, pos - buf); + } + pos = hostapd_eid_interworking(hapd, pos); + pos = hostapd_eid_adv_proto(hapd, pos); + pos = hostapd_eid_roaming_consortium(hapd, pos); + if (pos != buf) { + if (wpabuf_resize(&beacon, pos - buf) != 0) + goto fail; + wpabuf_put_data(beacon, buf, pos - buf); + + if (wpabuf_resize(&proberesp, pos - buf) != 0) + goto fail; + wpabuf_put_data(proberesp, buf, pos - buf); + } + +#ifdef CONFIG_P2P + if (hapd->p2p_beacon_ie) { + if (wpabuf_resize(&beacon, wpabuf_len(hapd->p2p_beacon_ie)) < + 0) + goto fail; + wpabuf_put_buf(beacon, hapd->p2p_beacon_ie); + } + + if (hapd->p2p_probe_resp_ie) { + if (wpabuf_resize(&proberesp, + wpabuf_len(hapd->p2p_probe_resp_ie)) < 0) + goto fail; + wpabuf_put_buf(proberesp, hapd->p2p_probe_resp_ie); + } +#endif /* CONFIG_P2P */ + +#ifdef CONFIG_P2P_MANAGER + if (hapd->conf->p2p & P2P_MANAGE) { + if (wpabuf_resize(&beacon, 100) == 0) { + u8 *start, *p; + start = wpabuf_put(beacon, 0); + p = hostapd_eid_p2p_manage(hapd, start); + wpabuf_put(beacon, p - start); + } + + if (wpabuf_resize(&proberesp, 100) == 0) { + u8 *start, *p; + start = wpabuf_put(proberesp, 0); + p = hostapd_eid_p2p_manage(hapd, start); + wpabuf_put(proberesp, p - start); + } + } +#endif /* CONFIG_P2P_MANAGER */ + +#ifdef CONFIG_WPS + if (hapd->conf->wps_state) { + struct wpabuf *a = wps_build_assoc_resp_ie(); + if (a && wpabuf_resize(&assocresp, wpabuf_len(a)) == 0) + wpabuf_put_buf(assocresp, a); + wpabuf_free(a); + } +#endif /* CONFIG_WPS */ + +#ifdef CONFIG_P2P_MANAGER + if (hapd->conf->p2p & P2P_MANAGE) { + if (wpabuf_resize(&assocresp, 100) == 0) { + u8 *start, *p; + start = wpabuf_put(assocresp, 0); + p = hostapd_eid_p2p_manage(hapd, start); + wpabuf_put(assocresp, p - start); + } + } +#endif /* CONFIG_P2P_MANAGER */ + +#ifdef CONFIG_WIFI_DISPLAY + if (hapd->p2p_group) { + struct wpabuf *a; + a = p2p_group_assoc_resp_ie(hapd->p2p_group, P2P_SC_SUCCESS); + if (a && wpabuf_resize(&assocresp, wpabuf_len(a)) == 0) + wpabuf_put_buf(assocresp, a); + wpabuf_free(a); + } +#endif /* CONFIG_WIFI_DISPLAY */ + +#ifdef CONFIG_HS20 + pos = buf; + pos = hostapd_eid_hs20_indication(hapd, pos); + if (pos != buf) { + if (wpabuf_resize(&beacon, pos - buf) != 0) + goto fail; + wpabuf_put_data(beacon, buf, pos - buf); + + if (wpabuf_resize(&proberesp, pos - buf) != 0) + goto fail; + wpabuf_put_data(proberesp, buf, pos - buf); + } + + pos = hostapd_eid_osen(hapd, buf); + if (pos != buf) { + if (wpabuf_resize(&beacon, pos - buf) != 0) + goto fail; + wpabuf_put_data(beacon, buf, pos - buf); + + if (wpabuf_resize(&proberesp, pos - buf) != 0) + goto fail; + wpabuf_put_data(proberesp, buf, pos - buf); + } +#endif /* CONFIG_HS20 */ + + if (hapd->conf->vendor_elements) { + size_t add = wpabuf_len(hapd->conf->vendor_elements); + if (wpabuf_resize(&beacon, add) == 0) + wpabuf_put_buf(beacon, hapd->conf->vendor_elements); + if (wpabuf_resize(&proberesp, add) == 0) + wpabuf_put_buf(proberesp, hapd->conf->vendor_elements); + } + + *beacon_ret = beacon; + *proberesp_ret = proberesp; + *assocresp_ret = assocresp; + + return 0; + +fail: + wpabuf_free(beacon); + wpabuf_free(proberesp); + wpabuf_free(assocresp); + return -1; +} + + +void hostapd_free_ap_extra_ies(struct hostapd_data *hapd, + struct wpabuf *beacon, + struct wpabuf *proberesp, + struct wpabuf *assocresp) +{ + wpabuf_free(beacon); + wpabuf_free(proberesp); + wpabuf_free(assocresp); +} + + +int hostapd_reset_ap_wps_ie(struct hostapd_data *hapd) +{ + if (hapd->driver == NULL || hapd->driver->set_ap_wps_ie == NULL) + return 0; + + return hapd->driver->set_ap_wps_ie(hapd->drv_priv, NULL, NULL, NULL); +} + + +int hostapd_set_ap_wps_ie(struct hostapd_data *hapd) +{ + struct wpabuf *beacon = 0, *proberesp = 0, *assocresp = 0; + int ret; + + if (hapd->driver == NULL || hapd->driver->set_ap_wps_ie == NULL) + return 0; + + if (hostapd_build_ap_extra_ies(hapd, &beacon, &proberesp, &assocresp) < 0) + return -1; + + ret = hapd->driver->set_ap_wps_ie(hapd->drv_priv, beacon, proberesp, + assocresp); + + hostapd_free_ap_extra_ies(hapd, beacon, proberesp, assocresp); + + return ret; +} + + +int hostapd_set_authorized(struct hostapd_data *hapd, + struct sta_info *sta, int authorized) +{ + if (authorized) { + return hostapd_sta_set_flags(hapd, sta->addr, + hostapd_sta_flags_to_drv( + sta->flags), + WPA_STA_AUTHORIZED, ~0); + } + + return hostapd_sta_set_flags(hapd, sta->addr, + hostapd_sta_flags_to_drv(sta->flags), + 0, ~WPA_STA_AUTHORIZED); +} + + +int hostapd_set_sta_flags(struct hostapd_data *hapd, struct sta_info *sta) +{ + int set_flags, total_flags, flags_and, flags_or; + total_flags = hostapd_sta_flags_to_drv(sta->flags); + set_flags = WPA_STA_SHORT_PREAMBLE | WPA_STA_WMM | WPA_STA_MFP; + if (((!hapd->conf->ieee802_1x && !hapd->conf->wpa) || + sta->auth_alg == WLAN_AUTH_FT) && + sta->flags & WLAN_STA_AUTHORIZED) + set_flags |= WPA_STA_AUTHORIZED; + flags_or = total_flags & set_flags; + flags_and = total_flags | ~set_flags; + return hostapd_sta_set_flags(hapd, sta->addr, total_flags, + flags_or, flags_and); +} + + +int hostapd_set_drv_ieee8021x(struct hostapd_data *hapd, const char *ifname, + int enabled) +{ + struct wpa_bss_params params; + os_memset(¶ms, 0, sizeof(params)); + params.ifname = ifname; + params.enabled = enabled; + if (enabled) { + params.wpa = hapd->conf->wpa; + params.ieee802_1x = hapd->conf->ieee802_1x; + params.wpa_group = hapd->conf->wpa_group; + if ((hapd->conf->wpa & (WPA_PROTO_WPA | WPA_PROTO_RSN)) == + (WPA_PROTO_WPA | WPA_PROTO_RSN)) + params.wpa_pairwise = hapd->conf->wpa_pairwise | + hapd->conf->rsn_pairwise; + else if (hapd->conf->wpa & WPA_PROTO_RSN) + params.wpa_pairwise = hapd->conf->rsn_pairwise; + else if (hapd->conf->wpa & WPA_PROTO_WPA) + params.wpa_pairwise = hapd->conf->wpa_pairwise; + params.wpa_key_mgmt = hapd->conf->wpa_key_mgmt; + params.rsn_preauth = hapd->conf->rsn_preauth; +#ifdef CONFIG_IEEE80211W + params.ieee80211w = hapd->conf->ieee80211w; +#endif /* CONFIG_IEEE80211W */ + } + return hostapd_set_ieee8021x(hapd, ¶ms); +} + +#ifdef CONFIG_FULL_HOSTAPD +int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname) +{ + char force_ifname[IFNAMSIZ]; + u8 if_addr[ETH_ALEN]; + return hostapd_if_add(hapd, WPA_IF_AP_VLAN, ifname, hapd->own_addr, + NULL, NULL, force_ifname, if_addr, NULL, 0); +} + + +int hostapd_vlan_if_remove(struct hostapd_data *hapd, const char *ifname) +{ + return hostapd_if_remove(hapd, WPA_IF_AP_VLAN, ifname); +} + + +int hostapd_set_wds_sta(struct hostapd_data *hapd, char *ifname_wds, + const u8 *addr, int aid, int val) +{ + const char *bridge = NULL; + + if (hapd->driver == NULL || hapd->driver->set_wds_sta == NULL) + return -1; + if (hapd->conf->wds_bridge[0]) + bridge = hapd->conf->wds_bridge; + else if (hapd->conf->bridge[0]) + bridge = hapd->conf->bridge; + return hapd->driver->set_wds_sta(hapd->drv_priv, addr, aid, val, + bridge, ifname_wds); +} +#endif + +int hostapd_add_sta_node(struct hostapd_data *hapd, const u8 *addr, + u16 auth_alg) +{ + if (hapd->driver == NULL || hapd->driver->add_sta_node == NULL) + return 0; + return hapd->driver->add_sta_node(hapd->drv_priv, addr, auth_alg); +} + + +int hostapd_sta_auth(struct hostapd_data *hapd, const u8 *addr, + u16 seq, u16 status, const u8 *ie, size_t len) +{ + if (hapd->driver == NULL || hapd->driver->sta_auth == NULL) + return 0; + return hapd->driver->sta_auth(hapd->drv_priv, hapd->own_addr, addr, + seq, status, ie, len); +} + + +int hostapd_sta_assoc(struct hostapd_data *hapd, const u8 *addr, + int reassoc, u16 status, const u8 *ie, size_t len) +{ + if (hapd->driver == NULL || hapd->driver->sta_assoc == NULL) + return 0; + return hapd->driver->sta_assoc(hapd->drv_priv, hapd->own_addr, addr, + reassoc, status, ie, len); +} + + +int hostapd_sta_add(struct hostapd_data *hapd, + const u8 *addr, u16 aid, u16 capability, + const u8 *supp_rates, size_t supp_rates_len, + u16 listen_interval, + const struct ieee80211_ht_capabilities *ht_capab, + const struct ieee80211_vht_capabilities *vht_capab, + u32 flags, u8 qosinfo, u8 vht_opmode) +{ + struct hostapd_sta_add_params params; + + if (hapd->driver == NULL) + return 0; + if (hapd->driver->sta_add == NULL) + return 0; + + os_memset(¶ms, 0, sizeof(params)); + params.addr = addr; + params.aid = aid; + params.capability = capability; + params.supp_rates = supp_rates; + params.supp_rates_len = supp_rates_len; + params.listen_interval = listen_interval; + params.ht_capabilities = ht_capab; + params.vht_capabilities = vht_capab; + params.vht_opmode_enabled = !!(flags & WLAN_STA_VHT_OPMODE_ENABLED); + params.vht_opmode = vht_opmode; + params.flags = hostapd_sta_flags_to_drv(flags); + params.qosinfo = qosinfo; + return hapd->driver->sta_add(hapd->drv_priv, ¶ms); +} + + +int hostapd_add_tspec(struct hostapd_data *hapd, const u8 *addr, + u8 *tspec_ie, size_t tspec_ielen) +{ + if (hapd->driver == NULL || hapd->driver->add_tspec == NULL) + return 0; + return hapd->driver->add_tspec(hapd->drv_priv, addr, tspec_ie, + tspec_ielen); +} + + +int hostapd_set_privacy(struct hostapd_data *hapd, int enabled) +{ + if (hapd->driver == NULL || hapd->driver->set_privacy == NULL) + return 0; + return hapd->driver->set_privacy(hapd->drv_priv, enabled); +} + + +int hostapd_set_generic_elem(struct hostapd_data *hapd, const u8 *elem, + size_t elem_len) +{ + if (hapd->driver == NULL || hapd->driver->set_generic_elem == NULL) + return 0; + return hapd->driver->set_generic_elem(hapd->drv_priv, elem, elem_len); +} + + +int hostapd_get_ssid(struct hostapd_data *hapd, u8 *buf, size_t len) +{ + if (hapd->driver == NULL || hapd->driver->hapd_get_ssid == NULL) + return 0; + return hapd->driver->hapd_get_ssid(hapd->drv_priv, buf, len); +} + + +int hostapd_set_ssid(struct hostapd_data *hapd, const u8 *buf, size_t len) +{ + if (hapd->driver == NULL || hapd->driver->hapd_set_ssid == NULL) + return 0; + return hapd->driver->hapd_set_ssid(hapd->drv_priv, buf, len); +} + + +int hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type, + const char *ifname, const u8 *addr, void *bss_ctx, + void **drv_priv, char *force_ifname, u8 *if_addr, + const char *bridge, int use_existing) +{ + if (hapd->driver == NULL || hapd->driver->if_add == NULL) + return -1; + return hapd->driver->if_add(hapd->drv_priv, type, ifname, addr, + bss_ctx, drv_priv, force_ifname, if_addr, + bridge, use_existing); +} + + +int hostapd_if_remove(struct hostapd_data *hapd, enum wpa_driver_if_type type, + const char *ifname) +{ + if (hapd->driver == NULL || hapd->drv_priv == NULL || + hapd->driver->if_remove == NULL) + return -1; + return hapd->driver->if_remove(hapd->drv_priv, type, ifname); +} + + +int hostapd_set_ieee8021x(struct hostapd_data *hapd, + struct wpa_bss_params *params) +{ + if (hapd->driver == NULL || hapd->driver->set_ieee8021x == NULL) + return 0; + return hapd->driver->set_ieee8021x(hapd->drv_priv, params); +} + + +int hostapd_get_seqnum(const char *ifname, struct hostapd_data *hapd, + const u8 *addr, int idx, u8 *seq) +{ + if (hapd->driver == NULL || hapd->driver->get_seqnum == NULL) + return 0; + return hapd->driver->get_seqnum(ifname, hapd->drv_priv, addr, idx, + seq); +} + + +int hostapd_flush(struct hostapd_data *hapd) +{ + if (hapd->driver == NULL || hapd->driver->flush == NULL) + return 0; + return hapd->driver->flush(hapd->drv_priv); +} + + +int hostapd_set_freq(struct hostapd_data *hapd, enum hostapd_hw_mode mode, + int freq, int channel, int ht_enabled, int vht_enabled, + int sec_channel_offset, int vht_oper_chwidth, + int center_segment0, int center_segment1) +{ + struct hostapd_freq_params data; + + if (hostapd_set_freq_params(&data, mode, freq, channel, ht_enabled, + vht_enabled, sec_channel_offset, + vht_oper_chwidth, + center_segment0, center_segment1, + hapd->iface->current_mode ? + hapd->iface->current_mode->vht_capab : 0)) + return -1; + + if (hapd->driver == NULL) + return 0; + if (hapd->driver->set_freq == NULL) + return 0; + return hapd->driver->set_freq(hapd->drv_priv, &data); +} + +int hostapd_set_rts(struct hostapd_data *hapd, int rts) +{ + if (hapd->driver == NULL || hapd->driver->set_rts == NULL) + return 0; + return hapd->driver->set_rts(hapd->drv_priv, rts); +} + + +int hostapd_set_frag(struct hostapd_data *hapd, int frag) +{ + if (hapd->driver == NULL || hapd->driver->set_frag == NULL) + return 0; + return hapd->driver->set_frag(hapd->drv_priv, frag); +} + + +int hostapd_sta_set_flags(struct hostapd_data *hapd, u8 *addr, + int total_flags, int flags_or, int flags_and) +{ + if (hapd->driver == NULL || hapd->driver->sta_set_flags == NULL) + return 0; + return hapd->driver->sta_set_flags(hapd->drv_priv, addr, total_flags, + flags_or, flags_and); +} + + +int hostapd_set_country(struct hostapd_data *hapd, const char *country) +{ + if (hapd->driver == NULL || + hapd->driver->set_country == NULL) + return 0; + return hapd->driver->set_country(hapd->drv_priv, country); +} + + +int hostapd_set_tx_queue_params(struct hostapd_data *hapd, int queue, int aifs, + int cw_min, int cw_max, int burst_time) +{ + if (hapd->driver == NULL || hapd->driver->set_tx_queue_params == NULL) + return 0; + return hapd->driver->set_tx_queue_params(hapd->drv_priv, queue, aifs, + cw_min, cw_max, burst_time); +} + + +struct hostapd_hw_modes * +hostapd_get_hw_feature_data(struct hostapd_data *hapd, u16 *num_modes, + u16 *flags) +{ + if (hapd->driver == NULL || + hapd->driver->get_hw_feature_data == NULL) + return NULL; + return hapd->driver->get_hw_feature_data(hapd->drv_priv, num_modes, + flags); +} + + +int hostapd_driver_commit(struct hostapd_data *hapd) +{ + if (hapd->driver == NULL || hapd->driver->commit == NULL) + return 0; + return hapd->driver->commit(hapd->drv_priv); +} + + +int hostapd_drv_none(struct hostapd_data *hapd) +{ + return hapd->driver && os_strcmp(hapd->driver->name, "none") == 0; +} + + +int hostapd_driver_scan(struct hostapd_data *hapd, + struct wpa_driver_scan_params *params) +{ + if (hapd->driver && hapd->driver->scan2) + return hapd->driver->scan2(hapd->drv_priv, params); + return -1; +} + + +struct wpa_scan_results * hostapd_driver_get_scan_results( + struct hostapd_data *hapd) +{ + if (hapd->driver && hapd->driver->get_scan_results2) + return hapd->driver->get_scan_results2(hapd->drv_priv); + return NULL; +} + + +int hostapd_driver_set_noa(struct hostapd_data *hapd, u8 count, int start, + int duration) +{ + if (hapd->driver && hapd->driver->set_noa) + return hapd->driver->set_noa(hapd->drv_priv, count, start, + duration); + return -1; +} + + +int hostapd_drv_set_key(const char *ifname, struct hostapd_data *hapd, + enum wpa_alg alg, const u8 *addr, + int key_idx, int set_tx, + const u8 *seq, size_t seq_len, + const u8 *key, size_t key_len) +{ + if (hapd->driver == NULL || hapd->driver->set_key == NULL) + return 0; + return hapd->driver->set_key(ifname, hapd->drv_priv, alg, addr, + key_idx, set_tx, seq, seq_len, key, + key_len); +} + + +int hostapd_drv_send_mlme(struct hostapd_data *hapd, + const void *msg, size_t len, int noack) +{ + if (hapd->driver == NULL || hapd->driver->send_mlme == NULL) + return 0; + return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack, 0); +} + + +int hostapd_drv_sta_deauth(struct hostapd_data *hapd, + const u8 *addr, int reason) +{ + if (hapd->driver == NULL || hapd->driver->sta_deauth == NULL) + return 0; + return hapd->driver->sta_deauth(hapd->drv_priv, hapd->own_addr, addr, + reason); +} + + +int hostapd_drv_sta_disassoc(struct hostapd_data *hapd, + const u8 *addr, int reason) +{ + if (hapd->driver == NULL || hapd->driver->sta_disassoc == NULL) + return 0; + return hapd->driver->sta_disassoc(hapd->drv_priv, hapd->own_addr, addr, + reason); +} + + +int hostapd_drv_wnm_oper(struct hostapd_data *hapd, enum wnm_oper oper, + const u8 *peer, u8 *buf, u16 *buf_len) +{ + if (hapd->driver == NULL || hapd->driver->wnm_oper == NULL) + return -1; + return hapd->driver->wnm_oper(hapd->drv_priv, oper, peer, buf, + buf_len); +} + + +int hostapd_drv_send_action(struct hostapd_data *hapd, unsigned int freq, + unsigned int wait, const u8 *dst, const u8 *data, + size_t len) +{ + if (hapd->driver == NULL || hapd->driver->send_action == NULL) + return 0; + return hapd->driver->send_action(hapd->drv_priv, freq, wait, dst, + hapd->own_addr, hapd->own_addr, data, + len, 0); +} + + +int hostapd_start_dfs_cac(struct hostapd_iface *iface, + enum hostapd_hw_mode mode, int freq, + int channel, int ht_enabled, int vht_enabled, + int sec_channel_offset, int vht_oper_chwidth, + int center_segment0, int center_segment1) +{ + struct hostapd_data *hapd = iface->bss[0]; + struct hostapd_freq_params data; + int res; + + if (!hapd->driver || !hapd->driver->start_dfs_cac) + return 0; + + if (!iface->conf->ieee80211h) { + wpa_printf(MSG_ERROR, "Can't start DFS CAC, DFS functionality " + "is not enabled"); + return -1; + } + + if (hostapd_set_freq_params(&data, mode, freq, channel, ht_enabled, + vht_enabled, sec_channel_offset, + vht_oper_chwidth, center_segment0, + center_segment1, + iface->current_mode->vht_capab)) { + wpa_printf(MSG_ERROR, "Can't set freq params"); + return -1; + } + + res = hapd->driver->start_dfs_cac(hapd->drv_priv, &data); + if (!res) { + iface->cac_started = 1; + os_get_reltime(&iface->dfs_cac_start); + } + + return res; +} + + +int hostapd_drv_set_qos_map(struct hostapd_data *hapd, + const u8 *qos_map_set, u8 qos_map_set_len) +{ + if (hapd->driver == NULL || hapd->driver->set_qos_map == NULL) + return 0; + return hapd->driver->set_qos_map(hapd->drv_priv, qos_map_set, + qos_map_set_len); +} + + +static void hostapd_get_hw_mode_any_channels(struct hostapd_data *hapd, + struct hostapd_hw_modes *mode, + int acs_ch_list_all, + int **freq_list) +{ + int i; + + for (i = 0; i < mode->num_channels; i++) { + struct hostapd_channel_data *chan = &mode->channels[i]; + + if ((acs_ch_list_all || + freq_range_list_includes(&hapd->iface->conf->acs_ch_list, + chan->chan)) && + !(chan->flag & HOSTAPD_CHAN_DISABLED)) + int_array_add_unique(freq_list, chan->freq); + } +} + + +int hostapd_drv_do_acs(struct hostapd_data *hapd) +{ + struct drv_acs_params params; + int ret, i, acs_ch_list_all = 0; + u8 *channels = NULL; + unsigned int num_channels = 0; + struct hostapd_hw_modes *mode; + int *freq_list = NULL; + + if (hapd->driver == NULL || hapd->driver->do_acs == NULL) + return 0; + + os_memset(¶ms, 0, sizeof(params)); + params.hw_mode = hapd->iface->conf->hw_mode; + + /* + * If no chanlist config parameter is provided, include all enabled + * channels of the selected hw_mode. + */ + if (!hapd->iface->conf->acs_ch_list.num) + acs_ch_list_all = 1; + + mode = hapd->iface->current_mode; + if (mode) { + channels = os_malloc(mode->num_channels); + if (channels == NULL) + return -1; + + for (i = 0; i < mode->num_channels; i++) { + struct hostapd_channel_data *chan = &mode->channels[i]; + if (!acs_ch_list_all && + !freq_range_list_includes( + &hapd->iface->conf->acs_ch_list, + chan->chan)) + continue; + if (!(chan->flag & HOSTAPD_CHAN_DISABLED)) { + channels[num_channels++] = chan->chan; + int_array_add_unique(&freq_list, chan->freq); + } + } + } else { + for (i = 0; i < hapd->iface->num_hw_features; i++) { + mode = &hapd->iface->hw_features[i]; + hostapd_get_hw_mode_any_channels(hapd, mode, + acs_ch_list_all, + &freq_list); + } + } + + params.ch_list = channels; + params.ch_list_len = num_channels; + params.freq_list = freq_list; + + params.ht_enabled = !!(hapd->iface->conf->ieee80211n); + params.ht40_enabled = !!(hapd->iface->conf->ht_capab & + HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET); + params.vht_enabled = !!(hapd->iface->conf->ieee80211ac); + params.ch_width = 20; + if (hapd->iface->conf->ieee80211n && params.ht40_enabled) + params.ch_width = 40; + + /* Note: VHT20 is defined by combination of ht_capab & vht_oper_chwidth + */ + if (hapd->iface->conf->ieee80211ac && params.ht40_enabled) { + if (hapd->iface->conf->vht_oper_chwidth == VHT_CHANWIDTH_80MHZ) + params.ch_width = 80; + else if (hapd->iface->conf->vht_oper_chwidth == + VHT_CHANWIDTH_160MHZ || + hapd->iface->conf->vht_oper_chwidth == + VHT_CHANWIDTH_80P80MHZ) + params.ch_width = 160; + } + + ret = hapd->driver->do_acs(hapd->drv_priv, ¶ms); + os_free(channels); + + return ret; +} diff --git a/beken_os/beken378/func/hostapd-2.5/src/ap/ap_drv_ops.h b/beken_os/beken378/func/hostapd-2.5/src/ap/ap_drv_ops.h new file mode 100755 index 0000000..27d2958 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/ap/ap_drv_ops.h @@ -0,0 +1,342 @@ +/* + * hostapd - Driver operations + * Copyright (c) 2009-2014, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef AP_DRV_OPS +#define AP_DRV_OPS + +#include "errno-base.h" + +enum wpa_driver_if_type; +struct wpa_bss_params; +struct wpa_driver_scan_params; +struct ieee80211_ht_capabilities; +struct ieee80211_vht_capabilities; +struct hostapd_freq_params; + +u32 hostapd_sta_flags_to_drv(u32 flags); +int hostapd_build_ap_extra_ies(struct hostapd_data *hapd, + struct wpabuf **beacon, + struct wpabuf **proberesp, + struct wpabuf **assocresp); +void hostapd_free_ap_extra_ies(struct hostapd_data *hapd, struct wpabuf *beacon, + struct wpabuf *proberesp, + struct wpabuf *assocresp); +int hostapd_reset_ap_wps_ie(struct hostapd_data *hapd); +int hostapd_set_ap_wps_ie(struct hostapd_data *hapd); +int hostapd_set_authorized(struct hostapd_data *hapd, + struct sta_info *sta, int authorized); +int hostapd_set_sta_flags(struct hostapd_data *hapd, struct sta_info *sta); +int hostapd_set_drv_ieee8021x(struct hostapd_data *hapd, const char *ifname, + int enabled); +int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname); +int hostapd_vlan_if_remove(struct hostapd_data *hapd, const char *ifname); +int hostapd_set_wds_sta(struct hostapd_data *hapd, char *ifname_wds, + const u8 *addr, int aid, int val); +int hostapd_sta_add(struct hostapd_data *hapd, + const u8 *addr, u16 aid, u16 capability, + const u8 *supp_rates, size_t supp_rates_len, + u16 listen_interval, + const struct ieee80211_ht_capabilities *ht_capab, + const struct ieee80211_vht_capabilities *vht_capab, + u32 flags, u8 qosinfo, u8 vht_opmode); +int hostapd_set_privacy(struct hostapd_data *hapd, int enabled); +int hostapd_set_generic_elem(struct hostapd_data *hapd, const u8 *elem, + size_t elem_len); +int hostapd_get_ssid(struct hostapd_data *hapd, u8 *buf, size_t len); +int hostapd_set_ssid(struct hostapd_data *hapd, const u8 *buf, size_t len); +int hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type, + const char *ifname, const u8 *addr, void *bss_ctx, + void **drv_priv, char *force_ifname, u8 *if_addr, + const char *bridge, int use_existing); +int hostapd_if_remove(struct hostapd_data *hapd, enum wpa_driver_if_type type, + const char *ifname); +int hostapd_set_ieee8021x(struct hostapd_data *hapd, + struct wpa_bss_params *params); +int hostapd_get_seqnum(const char *ifname, struct hostapd_data *hapd, + const u8 *addr, int idx, u8 *seq); +int hostapd_flush(struct hostapd_data *hapd); +int hostapd_set_freq(struct hostapd_data *hapd, enum hostapd_hw_mode mode, + int freq, int channel, int ht_enabled, int vht_enabled, + int sec_channel_offset, int vht_oper_chwidth, + int center_segment0, int center_segment1); +int hostapd_set_rts(struct hostapd_data *hapd, int rts); +int hostapd_set_frag(struct hostapd_data *hapd, int frag); +int hostapd_sta_set_flags(struct hostapd_data *hapd, u8 *addr, + int total_flags, int flags_or, int flags_and); +int hostapd_set_country(struct hostapd_data *hapd, const char *country); +int hostapd_set_tx_queue_params(struct hostapd_data *hapd, int queue, int aifs, + int cw_min, int cw_max, int burst_time); +struct hostapd_hw_modes * +hostapd_get_hw_feature_data(struct hostapd_data *hapd, u16 *num_modes, + u16 *flags); +int hostapd_driver_commit(struct hostapd_data *hapd); +int hostapd_drv_none(struct hostapd_data *hapd); +int hostapd_driver_scan(struct hostapd_data *hapd, + struct wpa_driver_scan_params *params); +struct wpa_scan_results * hostapd_driver_get_scan_results( + struct hostapd_data *hapd); +int hostapd_driver_set_noa(struct hostapd_data *hapd, u8 count, int start, + int duration); +int hostapd_drv_set_key(const char *ifname, + struct hostapd_data *hapd, + enum wpa_alg alg, const u8 *addr, + int key_idx, int set_tx, + const u8 *seq, size_t seq_len, + const u8 *key, size_t key_len); +int hostapd_drv_send_mlme(struct hostapd_data *hapd, + const void *msg, size_t len, int noack); +int hostapd_drv_sta_deauth(struct hostapd_data *hapd, + const u8 *addr, int reason); +int hostapd_drv_sta_disassoc(struct hostapd_data *hapd, + const u8 *addr, int reason); +int hostapd_drv_send_action(struct hostapd_data *hapd, unsigned int freq, + unsigned int wait, const u8 *dst, const u8 *data, + size_t len); +int hostapd_add_sta_node(struct hostapd_data *hapd, const u8 *addr, + u16 auth_alg); +int hostapd_sta_auth(struct hostapd_data *hapd, const u8 *addr, + u16 seq, u16 status, const u8 *ie, size_t len); +int hostapd_sta_assoc(struct hostapd_data *hapd, const u8 *addr, + int reassoc, u16 status, const u8 *ie, size_t len); +int hostapd_add_tspec(struct hostapd_data *hapd, const u8 *addr, + u8 *tspec_ie, size_t tspec_ielen); +int hostapd_start_dfs_cac(struct hostapd_iface *iface, + enum hostapd_hw_mode mode, int freq, + int channel, int ht_enabled, int vht_enabled, + int sec_channel_offset, int vht_oper_chwidth, + int center_segment0, int center_segment1); +int hostapd_drv_do_acs(struct hostapd_data *hapd); + + +#include "drivers/driver.h" + +int hostapd_drv_wnm_oper(struct hostapd_data *hapd, + enum wnm_oper oper, const u8 *peer, + u8 *buf, u16 *buf_len); + +int hostapd_drv_set_qos_map(struct hostapd_data *hapd, const u8 *qos_map_set, + u8 qos_map_set_len); + +static inline int hostapd_drv_set_countermeasures(struct hostapd_data *hapd, + int enabled) +{ + if (hapd->driver == NULL || + hapd->driver->hapd_set_countermeasures == NULL) + return 0; + return hapd->driver->hapd_set_countermeasures(hapd->drv_priv, enabled); +} + +static inline int hostapd_drv_set_sta_vlan(const char *ifname, + struct hostapd_data *hapd, + const u8 *addr, int vlan_id) +{ + if (hapd->driver == NULL || hapd->driver->set_sta_vlan == NULL) + return 0; + return hapd->driver->set_sta_vlan(hapd->drv_priv, addr, ifname, + vlan_id); +} + +static inline int hostapd_drv_get_inact_sec(struct hostapd_data *hapd, + const u8 *addr) +{ + if (hapd->driver == NULL || hapd->driver->get_inact_sec == NULL) + return 0; + return hapd->driver->get_inact_sec(hapd->drv_priv, addr); +} + +static inline int hostapd_drv_sta_remove(struct hostapd_data *hapd, + const u8 *addr) +{ + if (hapd->driver == NULL || hapd->driver->sta_remove == NULL) + return 0; + return hapd->driver->sta_remove(hapd->drv_priv, addr); +} + +static inline int hostapd_drv_hapd_send_eapol(struct hostapd_data *hapd, + const u8 *addr, const u8 *data, + size_t data_len, int encrypt, + u32 flags) +{ + if (hapd->driver == NULL || hapd->driver->hapd_send_eapol == NULL) + return 0; + return hapd->driver->hapd_send_eapol(hapd->drv_priv, addr, data, + data_len, encrypt, + hapd->own_addr, flags); +} + +static inline int hostapd_drv_read_sta_data( + struct hostapd_data *hapd, struct hostap_sta_driver_data *data, + const u8 *addr) +{ + if (hapd->driver == NULL || hapd->driver->read_sta_data == NULL) + return -1; + return hapd->driver->read_sta_data(hapd->drv_priv, data, addr); +} + +static inline int hostapd_drv_sta_clear_stats(struct hostapd_data *hapd, + const u8 *addr) +{ + if (hapd->driver == NULL || hapd->driver->sta_clear_stats == NULL) + return 0; + return hapd->driver->sta_clear_stats(hapd->drv_priv, addr); +} + +static inline int hostapd_drv_set_acl(struct hostapd_data *hapd, + struct hostapd_acl_params *params) +{ + if (hapd->driver == NULL || hapd->driver->set_acl == NULL) + return 0; + return hapd->driver->set_acl(hapd->drv_priv, params); +} + +static inline int hostapd_drv_set_ap(struct hostapd_data *hapd, + struct wpa_driver_ap_params *params) +{ + if (hapd->driver == NULL || hapd->driver->set_ap == NULL) + return 0; + return hapd->driver->set_ap(hapd->drv_priv, params); +} + +static inline int hostapd_drv_set_radius_acl_auth(struct hostapd_data *hapd, + const u8 *mac, int accepted, + u32 session_timeout) +{ + if (hapd->driver == NULL || hapd->driver->set_radius_acl_auth == NULL) + return 0; + return hapd->driver->set_radius_acl_auth(hapd->drv_priv, mac, accepted, + session_timeout); +} + +static inline int hostapd_drv_set_radius_acl_expire(struct hostapd_data *hapd, + const u8 *mac) +{ + if (hapd->driver == NULL || + hapd->driver->set_radius_acl_expire == NULL) + return 0; + return hapd->driver->set_radius_acl_expire(hapd->drv_priv, mac); +} + +static inline int hostapd_drv_set_authmode(struct hostapd_data *hapd, + int auth_algs) +{ + if (hapd->driver == NULL || hapd->driver->set_authmode == NULL) + return 0; + return hapd->driver->set_authmode(hapd->drv_priv, auth_algs); +} + +static inline void hostapd_drv_poll_client(struct hostapd_data *hapd, + const u8 *own_addr, const u8 *addr, + int qos) +{ + if (hapd->driver == NULL || hapd->driver->poll_client == NULL) + return; + hapd->driver->poll_client(hapd->drv_priv, own_addr, addr, qos); +} + +static inline int hostapd_drv_get_survey(struct hostapd_data *hapd, + unsigned int freq) +{ + if (hapd->driver == NULL) + return -1; + if (!hapd->driver->get_survey) + return -1; + return hapd->driver->get_survey(hapd->drv_priv, freq); +} + +static inline int hostapd_get_country(struct hostapd_data *hapd, char *alpha2) +{ + if (hapd->driver == NULL || hapd->driver->get_country == NULL) + return -1; + return hapd->driver->get_country(hapd->drv_priv, alpha2); +} + +static inline const char * hostapd_drv_get_radio_name(struct hostapd_data *hapd) +{ + if (hapd->driver == NULL || hapd->drv_priv == NULL || + hapd->driver->get_radio_name == NULL) + return NULL; + return hapd->driver->get_radio_name(hapd->drv_priv); +} + +static inline int hostapd_drv_switch_channel(struct hostapd_data *hapd, + struct csa_settings *settings) +{ + if (hapd->driver == NULL || hapd->driver->switch_channel == NULL) + return -ERRNOTSUP; + + return hapd->driver->switch_channel(hapd->drv_priv, settings); +} + +static inline int hostapd_drv_status(struct hostapd_data *hapd, char *buf, + size_t buflen) +{ + if (hapd->driver == NULL || hapd->driver->status == NULL) + return -1; + return hapd->driver->status(hapd->drv_priv, buf, buflen); +} + +static inline int hostapd_drv_br_add_ip_neigh(struct hostapd_data *hapd, + int version, const u8 *ipaddr, + int prefixlen, const u8 *addr) +{ + if (hapd->driver == NULL || hapd->drv_priv == NULL || + hapd->driver->br_add_ip_neigh == NULL) + return -1; + return hapd->driver->br_add_ip_neigh(hapd->drv_priv, version, ipaddr, + prefixlen, addr); +} + +static inline int hostapd_drv_br_delete_ip_neigh(struct hostapd_data *hapd, + u8 version, const u8 *ipaddr) +{ + if (hapd->driver == NULL || hapd->drv_priv == NULL || + hapd->driver->br_delete_ip_neigh == NULL) + return -1; + return hapd->driver->br_delete_ip_neigh(hapd->drv_priv, version, + ipaddr); +} + +static inline int hostapd_drv_br_port_set_attr(struct hostapd_data *hapd, + enum drv_br_port_attr attr, + unsigned int val) +{ + if (hapd->driver == NULL || hapd->drv_priv == NULL || + hapd->driver->br_port_set_attr == NULL) + return -1; + return hapd->driver->br_port_set_attr(hapd->drv_priv, attr, val); +} + +static inline int hostapd_drv_br_set_net_param(struct hostapd_data *hapd, + enum drv_br_net_param param, + unsigned int val) +{ + if (hapd->driver == NULL || hapd->drv_priv == NULL || + hapd->driver->br_set_net_param == NULL) + return -1; + return hapd->driver->br_set_net_param(hapd->drv_priv, param, val); +} + +static inline int hostapd_drv_vendor_cmd(struct hostapd_data *hapd, + int vendor_id, int subcmd, + const u8 *data, size_t data_len, + struct wpabuf *buf) +{ + if (hapd->driver == NULL || hapd->driver->vendor_cmd == NULL) + return -1; + return hapd->driver->vendor_cmd(hapd->drv_priv, vendor_id, subcmd, data, + data_len, buf); +} + +static inline int hostapd_drv_stop_ap(struct hostapd_data *hapd) +{ + if (hapd->driver == NULL || hapd->driver->stop_ap == NULL) + return 0; + return hapd->driver->stop_ap(hapd->drv_priv); +} + +#endif /* AP_DRV_OPS */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/ap/ap_list.c b/beken_os/beken378/func/hostapd-2.5/src/ap/ap_list.c new file mode 100755 index 0000000..1930231 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/ap/ap_list.c @@ -0,0 +1,312 @@ +/* + * hostapd / AP table + * Copyright (c) 2002-2009, Jouni Malinen + * Copyright (c) 2003-2004, Instant802 Networks, Inc. + * Copyright (c) 2006, Devicescape Software, Inc. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "utils/eloop.h" +#include "common/ieee802_11_defs.h" +#include "common/ieee802_11_common.h" +#include "ap/hostapd.h" +#include "ap_config.h" +#include "ieee802_11.h" +#include "ap/sta_info.h" +#include "beacon.h" +#include "ap_list.h" + + +/* AP list is a double linked list with head->prev pointing to the end of the + * list and tail->next = NULL. Entries are moved to the head of the list + * whenever a beacon has been received from the AP in question. The tail entry + * in this link will thus be the least recently used entry. */ + + +static int ap_list_beacon_olbc(struct hostapd_iface *iface, struct ap_info *ap) +{ + int i; + + if (iface->current_mode == NULL || + iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G || + iface->conf->channel != ap->channel) + return 0; + + if (ap->erp != -1 && (ap->erp & ERP_INFO_NON_ERP_PRESENT)) + return 1; + + for (i = 0; i < WLAN_SUPP_RATES_MAX; i++) { + int rate = (ap->supported_rates[i] & 0x7f) * 5; + if (rate == 60 || rate == 90 || rate > 110) + return 0; + } + + return 1; +} + + +static struct ap_info * ap_get_ap(struct hostapd_iface *iface, const u8 *ap) +{ + struct ap_info *s; + + s = iface->ap_hash[STA_HASH(ap)]; + while (s != NULL && os_memcmp(s->addr, ap, ETH_ALEN) != 0) + s = s->hnext; + return s; +} + + +static void ap_ap_list_add(struct hostapd_iface *iface, struct ap_info *ap) +{ + if (iface->ap_list) { + ap->prev = iface->ap_list->prev; + iface->ap_list->prev = ap; + } else + ap->prev = ap; + ap->next = iface->ap_list; + iface->ap_list = ap; +} + + +static void ap_ap_list_del(struct hostapd_iface *iface, struct ap_info *ap) +{ + if (iface->ap_list == ap) + iface->ap_list = ap->next; + else + ap->prev->next = ap->next; + + if (ap->next) + ap->next->prev = ap->prev; + else if (iface->ap_list) + iface->ap_list->prev = ap->prev; +} + + +static void ap_ap_hash_add(struct hostapd_iface *iface, struct ap_info *ap) +{ + ap->hnext = iface->ap_hash[STA_HASH(ap->addr)]; + iface->ap_hash[STA_HASH(ap->addr)] = ap; +} + + +static void ap_ap_hash_del(struct hostapd_iface *iface, struct ap_info *ap) +{ + struct ap_info *s; + + s = iface->ap_hash[STA_HASH(ap->addr)]; + if (s == NULL) return; + if (os_memcmp(s->addr, ap->addr, ETH_ALEN) == 0) { + iface->ap_hash[STA_HASH(ap->addr)] = s->hnext; + return; + } + + while (s->hnext != NULL && + os_memcmp(s->hnext->addr, ap->addr, ETH_ALEN) != 0) + s = s->hnext; + if (s->hnext != NULL) + s->hnext = s->hnext->hnext; + else + wpa_printf(MSG_INFO, "AP: could not remove AP " MACSTR + " from hash table", MAC2STR(ap->addr)); +} + + +static void ap_free_ap(struct hostapd_iface *iface, struct ap_info *ap) +{ + ap_ap_hash_del(iface, ap); + ap_ap_list_del(iface, ap); + + iface->num_ap--; + os_free(ap); +} + + +static void hostapd_free_aps(struct hostapd_iface *iface) +{ + struct ap_info *ap, *prev; + + ap = iface->ap_list; + + while (ap) { + prev = ap; + ap = ap->next; + ap_free_ap(iface, prev); + } + + iface->ap_list = NULL; +} + + +static struct ap_info * ap_ap_add(struct hostapd_iface *iface, const u8 *addr) +{ + struct ap_info *ap; + + ap = os_zalloc(sizeof(struct ap_info)); + if (ap == NULL) + return NULL; + + /* initialize AP info data */ + os_memcpy(ap->addr, addr, ETH_ALEN); + ap_ap_list_add(iface, ap); + iface->num_ap++; + ap_ap_hash_add(iface, ap); + + if (iface->num_ap > iface->conf->ap_table_max_size && ap != ap->prev) { + wpa_printf(MSG_DEBUG, "Removing the least recently used AP " + MACSTR " from AP table", MAC2STR(ap->prev->addr)); + ap_free_ap(iface, ap->prev); + } + + return ap; +} + + +void ap_list_process_beacon(struct hostapd_iface *iface, + const struct ieee80211_mgmt *mgmt, + struct ieee802_11_elems *elems, + struct hostapd_frame_info *fi) +{ + struct ap_info *ap; + int new_ap = 0; + int set_beacon = 0; + + if (iface->conf->ap_table_max_size < 1) + return; + + ap = ap_get_ap(iface, mgmt->bssid); + if (!ap) { + ap = ap_ap_add(iface, mgmt->bssid); + if (!ap) { + wpa_printf(MSG_INFO, + "Failed to allocate AP information entry"); + return; + } + new_ap = 1; + } + + merge_byte_arrays(ap->supported_rates, WLAN_SUPP_RATES_MAX, + elems->supp_rates, elems->supp_rates_len, + elems->ext_supp_rates, elems->ext_supp_rates_len); + + if (elems->erp_info) + ap->erp = elems->erp_info[0]; + else + ap->erp = -1; + + if (elems->ds_params) + ap->channel = elems->ds_params[0]; + else if (elems->ht_operation) + ap->channel = elems->ht_operation[0]; + else if (fi) + ap->channel = fi->channel; + + if (elems->ht_capabilities) + ap->ht_support = 1; + else + ap->ht_support = 0; + + os_get_reltime(&ap->last_beacon); + + if (!new_ap && ap != iface->ap_list) { + /* move AP entry into the beginning of the list so that the + * oldest entry is always in the end of the list */ + ap_ap_list_del(iface, ap); + ap_ap_list_add(iface, ap); + } + + if (!iface->olbc && + ap_list_beacon_olbc(iface, ap)) { + iface->olbc = 1; + wpa_printf(MSG_DEBUG, "OLBC AP detected: " MACSTR + " (channel %d) - enable protection", + MAC2STR(ap->addr), ap->channel); + set_beacon++; + } + +#ifdef CONFIG_IEEE80211N + if (!iface->olbc_ht && !ap->ht_support && + (ap->channel == 0 || + ap->channel == iface->conf->channel || + ap->channel == iface->conf->channel + + iface->conf->secondary_channel * 4)) { + iface->olbc_ht = 1; + hostapd_ht_operation_update(iface); + wpa_printf(MSG_DEBUG, "OLBC HT AP detected: " MACSTR + " (channel %d) - enable protection", + MAC2STR(ap->addr), ap->channel); + set_beacon++; + } +#endif /* CONFIG_IEEE80211N */ + + if (set_beacon) + ieee802_11_update_beacons(iface); +} + + +void ap_list_timer(struct hostapd_iface *iface) +{ + struct os_reltime now; + struct ap_info *ap; + int set_beacon = 0; + + if (!iface->ap_list) + return; + + os_get_reltime(&now); + + while (iface->ap_list) { + ap = iface->ap_list->prev; + if (!os_reltime_expired(&now, &ap->last_beacon, + iface->conf->ap_table_expiration_time)) + break; + + ap_free_ap(iface, ap); + } + + if (iface->olbc || iface->olbc_ht) { + int olbc = 0; + int olbc_ht = 0; + + ap = iface->ap_list; + while (ap && (olbc == 0 || olbc_ht == 0)) { + if (ap_list_beacon_olbc(iface, ap)) + olbc = 1; + if (!ap->ht_support) + olbc_ht = 1; + ap = ap->next; + } + if (!olbc && iface->olbc) { + wpa_printf(MSG_DEBUG, "OLBC not detected anymore"); + iface->olbc = 0; + set_beacon++; + } +#ifdef CONFIG_IEEE80211N + if (!olbc_ht && iface->olbc_ht) { + wpa_printf(MSG_DEBUG, "OLBC HT not detected anymore"); + iface->olbc_ht = 0; + hostapd_ht_operation_update(iface); + set_beacon++; + } +#endif /* CONFIG_IEEE80211N */ + } + + if (set_beacon) + ieee802_11_update_beacons(iface); +} + + +int ap_list_init(struct hostapd_iface *iface) +{ + return 0; +} + + +void ap_list_deinit(struct hostapd_iface *iface) +{ + hostapd_free_aps(iface); +} diff --git a/beken_os/beken378/func/hostapd-2.5/src/ap/ap_list.h b/beken_os/beken378/func/hostapd-2.5/src/ap/ap_list.h new file mode 100755 index 0000000..9e0353c --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/ap/ap_list.h @@ -0,0 +1,58 @@ +/* + * hostapd / AP table + * Copyright (c) 2002-2003, Jouni Malinen + * Copyright (c) 2003-2004, Instant802 Networks, Inc. + * Copyright (c) 2006, Devicescape Software, Inc. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef AP_LIST_H +#define AP_LIST_H + +struct ap_info { + /* Note: next/prev pointers are updated whenever a new beacon is + * received because these are used to find the least recently used + * entries. */ + struct ap_info *next; /* next entry in AP list */ + struct ap_info *prev; /* previous entry in AP list */ + struct ap_info *hnext; /* next entry in hash table list */ + u8 addr[6]; + u8 supported_rates[WLAN_SUPP_RATES_MAX]; + int erp; /* ERP Info or -1 if ERP info element not present */ + + int channel; + + int ht_support; + + struct os_reltime last_beacon; +}; + +struct ieee802_11_elems; +struct hostapd_frame_info; + +void ap_list_process_beacon(struct hostapd_iface *iface, + const struct ieee80211_mgmt *mgmt, + struct ieee802_11_elems *elems, + struct hostapd_frame_info *fi); +#ifdef NEED_AP_MLME +int ap_list_init(struct hostapd_iface *iface); +void ap_list_deinit(struct hostapd_iface *iface); +void ap_list_timer(struct hostapd_iface *iface); +#else /* NEED_AP_MLME */ +static inline int ap_list_init(struct hostapd_iface *iface) +{ + return 0; +} + +static inline void ap_list_deinit(struct hostapd_iface *iface) +{ +} + +static inline void ap_list_timer(struct hostapd_iface *iface) +{ +} +#endif /* NEED_AP_MLME */ + +#endif /* AP_LIST_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/ap/ap_mlme.c b/beken_os/beken378/func/hostapd-2.5/src/ap/ap_mlme.c new file mode 100755 index 0000000..45b2ac7 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/ap/ap_mlme.c @@ -0,0 +1,178 @@ +/* + * hostapd / IEEE 802.11 MLME + * Copyright 2003-2006, Jouni Malinen + * Copyright 2003-2004, Instant802 Networks, Inc. + * Copyright 2005-2006, Devicescape Software, Inc. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "common/ieee802_11_defs.h" +#include "ieee802_11.h" +#include "wpa_auth.h" +#include "ap/sta_info.h" +#include "ap_mlme.h" +#include "ap/hostapd.h" + + +#if !defined(CONFIG_NO_HOSTAPD_LOGGER) || CFG_ENABLE_WPA_LOG +static const char * mlme_auth_alg_str(int alg) +{ + switch (alg) { + case WLAN_AUTH_OPEN: + return "OPEN_SYSTEM"; + case WLAN_AUTH_SHARED_KEY: + return "SHARED_KEY"; + case WLAN_AUTH_FT: + return "FT"; + } + + return "unknown"; +} +#endif /* CONFIG_NO_HOSTAPD_LOGGER */ + + +/** + * mlme_authenticate_indication - Report the establishment of an authentication + * relationship with a specific peer MAC entity + * @hapd: BSS data + * @sta: peer STA data + * + * MLME calls this function as a result of the establishment of an + * authentication relationship with a specific peer MAC entity that + * resulted from an authentication procedure that was initiated by + * that specific peer MAC entity. + * + * PeerSTAAddress = sta->addr + * AuthenticationType = sta->auth_alg (WLAN_AUTH_OPEN / WLAN_AUTH_SHARED_KEY) + */ +void mlme_authenticate_indication(struct hostapd_data *hapd, + struct sta_info *sta) +{ + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_MLME, + HOSTAPD_LEVEL_DEBUG, + "MLME-AUTHENTICATE.indication(" MACSTR ", %s)", + MAC2STR(sta->addr), mlme_auth_alg_str(sta->auth_alg)); + if (sta->auth_alg != WLAN_AUTH_FT && !(sta->flags & WLAN_STA_MFP)) + mlme_deletekeys_request(hapd, sta); +} + + +/** + * mlme_deauthenticate_indication - Report the invalidation of an + * authentication relationship with a specific peer MAC entity + * @hapd: BSS data + * @sta: Peer STA data + * @reason_code: ReasonCode from Deauthentication frame + * + * MLME calls this function as a result of the invalidation of an + * authentication relationship with a specific peer MAC entity. + * + * PeerSTAAddress = sta->addr + */ +void mlme_deauthenticate_indication(struct hostapd_data *hapd, + struct sta_info *sta, u16 reason_code) +{ + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_MLME, + HOSTAPD_LEVEL_DEBUG, + "MLME-DEAUTHENTICATE.indication(" MACSTR ", %d)", + MAC2STR(sta->addr), reason_code); + if (!hapd->iface->driver_ap_teardown) + mlme_deletekeys_request(hapd, sta); +} + + +/** + * mlme_associate_indication - Report the establishment of an association with + * a specific peer MAC entity + * @hapd: BSS data + * @sta: peer STA data + * + * MLME calls this function as a result of the establishment of an + * association with a specific peer MAC entity that resulted from an + * association procedure that was initiated by that specific peer MAC entity. + * + * PeerSTAAddress = sta->addr + */ +void mlme_associate_indication(struct hostapd_data *hapd, struct sta_info *sta) +{ + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_MLME, + HOSTAPD_LEVEL_DEBUG, + "MLME-ASSOCIATE.indication(" MACSTR ")", + MAC2STR(sta->addr)); + if (sta->auth_alg != WLAN_AUTH_FT) + mlme_deletekeys_request(hapd, sta); +} + + +/** + * mlme_reassociate_indication - Report the establishment of an reassociation + * with a specific peer MAC entity + * @hapd: BSS data + * @sta: peer STA data + * + * MLME calls this function as a result of the establishment of an + * reassociation with a specific peer MAC entity that resulted from a + * reassociation procedure that was initiated by that specific peer MAC entity. + * + * PeerSTAAddress = sta->addr + */ +void mlme_reassociate_indication(struct hostapd_data *hapd, + struct sta_info *sta) +{ + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_MLME, + HOSTAPD_LEVEL_DEBUG, + "MLME-REASSOCIATE.indication(" MACSTR ")", + MAC2STR(sta->addr)); + if (sta->auth_alg != WLAN_AUTH_FT) + mlme_deletekeys_request(hapd, sta); +} + + +/** + * mlme_disassociate_indication - Report disassociation with a specific peer + * MAC entity + * @hapd: BSS data + * @sta: Peer STA data + * @reason_code: ReasonCode from Disassociation frame + * + * MLME calls this function as a result of the invalidation of an association + * relationship with a specific peer MAC entity. + * + * PeerSTAAddress = sta->addr + */ +void mlme_disassociate_indication(struct hostapd_data *hapd, + struct sta_info *sta, u16 reason_code) +{ + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_MLME, + HOSTAPD_LEVEL_DEBUG, + "MLME-DISASSOCIATE.indication(" MACSTR ", %d)", + MAC2STR(sta->addr), reason_code); + mlme_deletekeys_request(hapd, sta); +} + + +void mlme_michaelmicfailure_indication(struct hostapd_data *hapd, + const u8 *addr) +{ + hostapd_logger(hapd, addr, HOSTAPD_MODULE_MLME, + HOSTAPD_LEVEL_DEBUG, + "MLME-MichaelMICFailure.indication(" MACSTR ")", + MAC2STR(addr)); +} + + +void mlme_deletekeys_request(struct hostapd_data *hapd, struct sta_info *sta) +{ + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_MLME, + HOSTAPD_LEVEL_DEBUG, + "MLME-DELETEKEYS.request(" MACSTR ")", + MAC2STR(sta->addr)); + + if (sta->wpa_sm) + wpa_remove_ptk(sta->wpa_sm); +} diff --git a/beken_os/beken378/func/hostapd-2.5/src/ap/ap_mlme.h b/beken_os/beken378/func/hostapd-2.5/src/ap/ap_mlme.h new file mode 100755 index 0000000..e7fd69d --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/ap/ap_mlme.h @@ -0,0 +1,34 @@ +/* + * hostapd / IEEE 802.11 MLME + * Copyright 2003, Jouni Malinen + * Copyright 2003-2004, Instant802 Networks, Inc. + * Copyright 2005-2006, Devicescape Software, Inc. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef MLME_H +#define MLME_H + +void mlme_authenticate_indication(struct hostapd_data *hapd, + struct sta_info *sta); + +void mlme_deauthenticate_indication(struct hostapd_data *hapd, + struct sta_info *sta, u16 reason_code); + +void mlme_associate_indication(struct hostapd_data *hapd, + struct sta_info *sta); + +void mlme_reassociate_indication(struct hostapd_data *hapd, + struct sta_info *sta); + +void mlme_disassociate_indication(struct hostapd_data *hapd, + struct sta_info *sta, u16 reason_code); + +void mlme_michaelmicfailure_indication(struct hostapd_data *hapd, + const u8 *addr); + +void mlme_deletekeys_request(struct hostapd_data *hapd, struct sta_info *sta); + +#endif /* MLME_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/ap/beacon.c b/beken_os/beken378/func/hostapd-2.5/src/ap/beacon.c new file mode 100755 index 0000000..024a704 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/ap/beacon.c @@ -0,0 +1,1160 @@ +/* + * hostapd / IEEE 802.11 Management: Beacon and Probe Request/Response + * Copyright (c) 2002-2004, Instant802 Networks, Inc. + * Copyright (c) 2005-2006, Devicescape Software, Inc. + * Copyright (c) 2008-2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#ifndef CONFIG_NATIVE_WINDOWS + +#include "utils/common.h" +#include "common/ieee802_11_defs.h" +#include "common/ieee802_11_common.h" +#include "common/hw_features_common.h" +#include "wps/wps_defs.h" +#include "ap/hostapd.h" +#include "ieee802_11.h" +#include "wpa_auth.h" +#include "wmm.h" +#include "ap_config.h" +#include "ap/sta_info.h" +#include "p2p_hostapd.h" +#include "ap_drv_ops.h" +#include "beacon.h" +#include "ap/dfs.h" + +#include "include.h" +#include "uart_pub.h" + +#ifdef NEED_AP_MLME +#ifdef CONFIG_FULL_HOSTAPD +static u8 * hostapd_eid_rm_enabled_capab(struct hostapd_data *hapd, u8 *eid, + size_t len) +{ + if (!hapd->conf->radio_measurements || len < 2 + 4) + return eid; + + *eid++ = WLAN_EID_RRM_ENABLED_CAPABILITIES; + *eid++ = 5; + *eid++ = (hapd->conf->radio_measurements & BIT(0)) ? + WLAN_RRM_CAPS_NEIGHBOR_REPORT : 0x00; + *eid++ = 0x00; + *eid++ = 0x00; + *eid++ = 0x00; + *eid++ = 0x00; + return eid; +} +static u8 * hostapd_eid_bss_load(struct hostapd_data *hapd, u8 *eid, size_t len) +{ + if (len < 2 + 5) + return eid; + +#ifdef CONFIG_TESTING_OPTIONS + if (hapd->conf->bss_load_test_set) { + *eid++ = WLAN_EID_BSS_LOAD; + *eid++ = 5; + os_memcpy(eid, hapd->conf->bss_load_test, 5); + eid += 5; + return eid; + } +#endif /* CONFIG_TESTING_OPTIONS */ + if (hapd->conf->bss_load_update_period) { + *eid++ = WLAN_EID_BSS_LOAD; + *eid++ = 5; + WPA_PUT_LE16(eid, hapd->num_sta); + eid += 2; + *eid++ = hapd->iface->channel_utilization; + WPA_PUT_LE16(eid, 0); /* no available admission capabity */ + eid += 2; + } + return eid; +} +#endif + +static u8 ieee802_11_erp_info(struct hostapd_data *hapd) +{ + u8 erp = 0; + + if (hapd->iface->current_mode == NULL || + hapd->iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G) + return 0; + + if (hapd->iface->olbc) + erp |= ERP_INFO_USE_PROTECTION; + if (hapd->iface->num_sta_non_erp > 0) { + erp |= ERP_INFO_NON_ERP_PRESENT | + ERP_INFO_USE_PROTECTION; + } + if (hapd->iface->num_sta_no_short_preamble > 0 || + hapd->iconf->preamble == LONG_PREAMBLE) + erp |= ERP_INFO_BARKER_PREAMBLE_MODE; + + return erp; +} + + +static u8 * hostapd_eid_ds_params(struct hostapd_data *hapd, u8 *eid) +{ + *eid++ = WLAN_EID_DS_PARAMS; + *eid++ = 1; + *eid++ = hapd->iconf->channel; + return eid; +} + + +static u8 * hostapd_eid_erp_info(struct hostapd_data *hapd, u8 *eid) +{ + if (hapd->iface->current_mode == NULL || + hapd->iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G) + return eid; + + /* Set NonERP_present and use_protection bits if there + * are any associated NonERP stations. */ + /* TODO: use_protection bit can be set to zero even if + * there are NonERP stations present. This optimization + * might be useful if NonERP stations are "quiet". + * See 802.11g/D6 E-1 for recommended practice. + * In addition, Non ERP present might be set, if AP detects Non ERP + * operation on other APs. */ + + /* Add ERP Information element */ + *eid++ = WLAN_EID_ERP_INFO; + *eid++ = 1; + *eid++ = ieee802_11_erp_info(hapd); + + return eid; +} + +#ifdef CONFIG_FULL_HOSTAPD +static u8 * hostapd_eid_pwr_constraint(struct hostapd_data *hapd, u8 *eid) +{ + u8 *pos = eid; + u8 local_pwr_constraint = 0; + int dfs = 0; + + if (hapd->iface->current_mode == NULL || + hapd->iface->current_mode->mode != HOSTAPD_MODE_IEEE80211A) + return eid; + + /* Let host drivers add this IE if DFS support is offloaded */ + if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) + return eid; + + /* + * There is no DFS support and power constraint was not directly + * requested by config option. + */ + if (!hapd->iconf->ieee80211h && + hapd->iconf->local_pwr_constraint == -1) + return eid; + +#ifdef CONFIG_DFS + /* Check if DFS is required by regulatory. */ + dfs = hostapd_is_dfs_required(hapd->iface); + if (dfs < 0) { + wpa_printf(MSG_WARNING, "Failed to check if DFS is required; ret=%d", + dfs); + dfs = 0; + } +#endif + + if (dfs == 0 && hapd->iconf->local_pwr_constraint == -1) + return eid; + + /* + * ieee80211h (DFS) is enabled so Power Constraint element shall + * be added when running on DFS channel whenever local_pwr_constraint + * is configured or not. In order to meet regulations when TPC is not + * implemented using a transmit power that is below the legal maximum + * (including any mitigation factor) should help. In this case, + * indicate 3 dB below maximum allowed transmit power. + */ + if (hapd->iconf->local_pwr_constraint == -1) + local_pwr_constraint = 3; + + /* + * A STA that is not an AP shall use a transmit power less than or + * equal to the local maximum transmit power level for the channel. + * The local maximum transmit power can be calculated from the formula: + * local max TX pwr = max TX pwr - local pwr constraint + * Where max TX pwr is maximum transmit power level specified for + * channel in Country element and local pwr constraint is specified + * for channel in this Power Constraint element. + */ + + /* Element ID */ + *pos++ = WLAN_EID_PWR_CONSTRAINT; + /* Length */ + *pos++ = 1; + /* Local Power Constraint */ + if (local_pwr_constraint) + *pos++ = local_pwr_constraint; + else + *pos++ = hapd->iconf->local_pwr_constraint; + + return pos; +} +#endif + +static u8 * hostapd_eid_country_add(u8 *pos, u8 *end, int chan_spacing, + struct hostapd_channel_data *start, + struct hostapd_channel_data *prev) +{ + if (end - pos < 3) + return pos; + + /* first channel number */ + *pos++ = start->chan; + /* number of channels */ + *pos++ = (prev->chan - start->chan) / chan_spacing + 1; + /* maximum transmit power level */ + *pos++ = start->max_tx_power; + + return pos; +} + + +static u8 * hostapd_eid_country(struct hostapd_data *hapd, u8 *eid, + int max_len) +{ + u8 *pos = eid; + u8 *end = eid + max_len; + int i; + struct hostapd_hw_modes *mode; + struct hostapd_channel_data *start, *prev; + int chan_spacing = 1; + + if (!hapd->iconf->ieee80211d || max_len < 6 || + hapd->iface->current_mode == NULL) + return eid; + + *pos++ = WLAN_EID_COUNTRY; + pos++; /* length will be set later */ + os_memcpy(pos, hapd->iconf->country, 3); /* e.g., 'US ' */ + pos += 3; + + mode = hapd->iface->current_mode; + if (mode->mode == HOSTAPD_MODE_IEEE80211A) + chan_spacing = 4; + + start = prev = NULL; + for (i = 0; i < mode->num_channels; i++) { + struct hostapd_channel_data *chan = &mode->channels[i]; + if (chan->flag & HOSTAPD_CHAN_DISABLED) + continue; + if (start && prev && + prev->chan + chan_spacing == chan->chan && + start->max_tx_power == chan->max_tx_power) { + prev = chan; + continue; /* can use same entry */ + } + + if (start && prev) { + pos = hostapd_eid_country_add(pos, end, chan_spacing, + start, prev); + start = NULL; + } + + /* Start new group */ + start = prev = chan; + } + + if (start) { + pos = hostapd_eid_country_add(pos, end, chan_spacing, + start, prev); + } + + if ((pos - eid) & 1) { + if (end - pos < 1) + return eid; + *pos++ = 0; /* pad for 16-bit alignment */ + } + + eid[1] = (pos - eid) - 2; + + return pos; +} + + +static u8 * hostapd_eid_wpa(struct hostapd_data *hapd, u8 *eid, size_t len) +{ + const u8 *ie; + size_t ielen; + + ie = wpa_auth_get_wpa_ie(hapd->wpa_auth, &ielen); + if (ie == NULL || ielen > len) + return eid; + + os_memcpy(eid, ie, ielen); + return eid + ielen; +} + + +static u8 * hostapd_eid_csa(struct hostapd_data *hapd, u8 *eid) +{ + u8 chan; + + if (!hapd->cs_freq_params.freq) + return eid; + + if (ieee80211_freq_to_chan(hapd->cs_freq_params.freq, &chan) == + NUM_HOSTAPD_MODES) + return eid; + + *eid++ = WLAN_EID_CHANNEL_SWITCH; + *eid++ = 3; + *eid++ = hapd->cs_block_tx; + *eid++ = chan; + *eid++ = hapd->cs_count; + + return eid; +} + + +static u8 * hostapd_eid_secondary_channel(struct hostapd_data *hapd, u8 *eid) +{ + u8 sec_ch; + + if (!hapd->cs_freq_params.sec_channel_offset) + return eid; + + if (hapd->cs_freq_params.sec_channel_offset == -1) + sec_ch = HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW; + else if (hapd->cs_freq_params.sec_channel_offset == 1) + sec_ch = HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE; + else + return eid; + + *eid++ = WLAN_EID_SECONDARY_CHANNEL_OFFSET; + *eid++ = 1; + *eid++ = sec_ch; + + return eid; +} + + +static u8 * hostapd_add_csa_elems(struct hostapd_data *hapd, u8 *pos, + u8 *start, unsigned int *csa_counter_off) +{ + u8 *old_pos = pos; + + if (!csa_counter_off) + return pos; + + *csa_counter_off = 0; + pos = hostapd_eid_csa(hapd, pos); + + if (pos != old_pos) { + /* save an offset to the counter - should be last byte */ + *csa_counter_off = pos - start - 1; + pos = hostapd_eid_secondary_channel(hapd, pos); + } + + return pos; +} + + +static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd, + const struct ieee80211_mgmt *req, + int is_p2p, size_t *resp_len) +{ + struct ieee80211_mgmt *resp; + u8 *pos, *epos; + size_t buflen; + +#define MAX_PROBERESP_LEN 768 + buflen = MAX_PROBERESP_LEN; +#ifdef CONFIG_WPS + if (hapd->wps_probe_resp_ie) + buflen += wpabuf_len(hapd->wps_probe_resp_ie); +#endif /* CONFIG_WPS */ +#ifdef CONFIG_P2P + if (hapd->p2p_probe_resp_ie) + buflen += wpabuf_len(hapd->p2p_probe_resp_ie); +#endif /* CONFIG_P2P */ +#ifdef CONFIG_FST + if (hapd->iface->fst_ies) + buflen += wpabuf_len(hapd->iface->fst_ies); +#endif /* CONFIG_FST */ + if (hapd->conf->vendor_elements) + buflen += wpabuf_len(hapd->conf->vendor_elements); + if (hapd->conf->vendor_vht) { + buflen += 5 + 2 + sizeof(struct ieee80211_vht_capabilities) + + 2 + sizeof(struct ieee80211_vht_operation); + } + resp = os_zalloc(buflen); + if (resp == NULL) + return NULL; + + epos = ((u8 *) resp) + MAX_PROBERESP_LEN; + + resp->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, + WLAN_FC_STYPE_PROBE_RESP); + if (req) + os_memcpy(resp->da, req->sa, ETH_ALEN); + os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN); + + os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN); + resp->u.probe_resp.beacon_int = + host_to_le16(hapd->iconf->beacon_int); + + /* hardware or low-level driver will setup seq_ctrl and timestamp */ + resp->u.probe_resp.capab_info = + host_to_le16(hostapd_own_capab_info(hapd)); + + pos = resp->u.probe_resp.variable; + *pos++ = WLAN_EID_SSID; + *pos++ = hapd->conf->ssid.ssid_len; + os_memcpy(pos, hapd->conf->ssid.ssid, hapd->conf->ssid.ssid_len); + pos += hapd->conf->ssid.ssid_len; + + /* Supported rates */ + pos = hostapd_eid_supp_rates(hapd, pos); + + /* DS Params */ + pos = hostapd_eid_ds_params(hapd, pos); + + pos = hostapd_eid_country(hapd, pos, epos - pos); + +#ifdef CONFIG_FULL_HOSTAPD + /* Power Constraint element */ + pos = hostapd_eid_pwr_constraint(hapd, pos); +#endif + + /* ERP Information element */ + pos = hostapd_eid_erp_info(hapd, pos); + + /* Extended supported rates */ + pos = hostapd_eid_ext_supp_rates(hapd, pos); + + /* RSN, MDIE, WPA */ + pos = hostapd_eid_wpa(hapd, pos, epos - pos); + +#ifdef CONFIG_FULL_HOSTAPD + pos = hostapd_eid_bss_load(hapd, pos, epos - pos); + pos = hostapd_eid_rm_enabled_capab(hapd, pos, epos - pos); +#endif + +#ifdef CONFIG_IEEE80211N + pos = hostapd_eid_ht_capabilities(hapd, pos); + pos = hostapd_eid_ht_operation(hapd, pos); +#endif /* CONFIG_IEEE80211N */ + + pos = hostapd_eid_ext_capab(hapd, pos); + +#ifdef CONFIG_FULL_HOSTAPD + pos = hostapd_eid_time_adv(hapd, pos); + pos = hostapd_eid_time_zone(hapd, pos); + + pos = hostapd_eid_interworking(hapd, pos); + pos = hostapd_eid_adv_proto(hapd, pos); + pos = hostapd_eid_roaming_consortium(hapd, pos); +#endif + + pos = hostapd_add_csa_elems(hapd, pos, (u8 *)resp, + &hapd->cs_c_off_proberesp); + +#ifdef CONFIG_FST + if (hapd->iface->fst_ies) { + os_memcpy(pos, wpabuf_head(hapd->iface->fst_ies), + wpabuf_len(hapd->iface->fst_ies)); + pos += wpabuf_len(hapd->iface->fst_ies); + } +#endif /* CONFIG_FST */ + +#ifdef CONFIG_IEEE80211AC + if (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) { + pos = hostapd_eid_vht_capabilities(hapd, pos); + pos = hostapd_eid_vht_operation(hapd, pos); + } + if (hapd->conf->vendor_vht) + pos = hostapd_eid_vendor_vht(hapd, pos); +#endif /* CONFIG_IEEE80211AC */ + + /* Wi-Fi Alliance WMM */ + pos = hostapd_eid_wmm(hapd, pos); + +#ifdef CONFIG_WPS + if (hapd->conf->wps_state && hapd->wps_probe_resp_ie) { + os_memcpy(pos, wpabuf_head(hapd->wps_probe_resp_ie), + wpabuf_len(hapd->wps_probe_resp_ie)); + pos += wpabuf_len(hapd->wps_probe_resp_ie); + } +#endif /* CONFIG_WPS */ + +#ifdef CONFIG_P2P + if ((hapd->conf->p2p & P2P_ENABLED) && is_p2p && + hapd->p2p_probe_resp_ie) { + os_memcpy(pos, wpabuf_head(hapd->p2p_probe_resp_ie), + wpabuf_len(hapd->p2p_probe_resp_ie)); + pos += wpabuf_len(hapd->p2p_probe_resp_ie); + } +#endif /* CONFIG_P2P */ +#ifdef CONFIG_P2P_MANAGER + if ((hapd->conf->p2p & (P2P_MANAGE | P2P_ENABLED | P2P_GROUP_OWNER)) == + P2P_MANAGE) + pos = hostapd_eid_p2p_manage(hapd, pos); +#endif /* CONFIG_P2P_MANAGER */ + +#ifdef CONFIG_HS20 + pos = hostapd_eid_hs20_indication(hapd, pos); + pos = hostapd_eid_osen(hapd, pos); +#endif /* CONFIG_HS20 */ + + if (hapd->conf->vendor_elements) { + os_memcpy(pos, wpabuf_head(hapd->conf->vendor_elements), + wpabuf_len(hapd->conf->vendor_elements)); + pos += wpabuf_len(hapd->conf->vendor_elements); + } + + *resp_len = pos - (u8 *) resp; + return (u8 *) resp; +} + + +enum ssid_match_result { + NO_SSID_MATCH, + EXACT_SSID_MATCH, + WILDCARD_SSID_MATCH +}; + +static enum ssid_match_result ssid_match(struct hostapd_data *hapd, + const u8 *ssid, size_t ssid_len, + const u8 *ssid_list, + size_t ssid_list_len) +{ + const u8 *pos, *end; + int wildcard = 0; + + if (ssid_len == 0) + wildcard = 1; + if (ssid_len == hapd->conf->ssid.ssid_len && + os_memcmp(ssid, hapd->conf->ssid.ssid, ssid_len) == 0) + return EXACT_SSID_MATCH; + + if (ssid_list == NULL) + return wildcard ? WILDCARD_SSID_MATCH : NO_SSID_MATCH; + + pos = ssid_list; + end = ssid_list + ssid_list_len; + while (pos + 1 <= end) { + if (pos + 2 + pos[1] > end) + break; + if (pos[1] == 0) + wildcard = 1; + if (pos[1] == hapd->conf->ssid.ssid_len && + os_memcmp(pos + 2, hapd->conf->ssid.ssid, pos[1]) == 0) + return EXACT_SSID_MATCH; + pos += 2 + pos[1]; + } + + return wildcard ? WILDCARD_SSID_MATCH : NO_SSID_MATCH; +} + + +void sta_track_expire(struct hostapd_iface *iface, int force) +{ + struct os_reltime now; + struct hostapd_sta_info *info; + + if (!iface->num_sta_seen) + return; + + os_get_reltime(&now); + while (0 != (info = dl_list_first(&iface->sta_seen, struct hostapd_sta_info, + list))) { + if (!force && + !os_reltime_expired(&now, &info->last_seen, + iface->conf->track_sta_max_age)) + break; + force = 0; + + wpa_printf(MSG_MSGDUMP, "%s: Expire STA tracking entry for " + MACSTR, iface->bss[0]->conf->iface, + MAC2STR(info->addr)); + dl_list_del(&info->list); + iface->num_sta_seen--; + os_free(info); + } +} + + +static struct hostapd_sta_info * sta_track_get(struct hostapd_iface *iface, + const u8 *addr) +{ + struct hostapd_sta_info *info; + + dl_list_for_each(info, &iface->sta_seen, struct hostapd_sta_info, list) + if (os_memcmp(addr, info->addr, ETH_ALEN) == 0) + return info; + + return NULL; +} + + +void sta_track_add(struct hostapd_iface *iface, const u8 *addr) +{ + struct hostapd_sta_info *info; + + info = sta_track_get(iface, addr); + if (info) { + /* Move the most recent entry to the end of the list */ + dl_list_del(&info->list); + dl_list_add_tail(&iface->sta_seen, &info->list); + os_get_reltime(&info->last_seen); + return; + } + + /* Add a new entry */ + info = os_zalloc(sizeof(*info)); + os_memcpy(info->addr, addr, ETH_ALEN); + os_get_reltime(&info->last_seen); + + if (iface->num_sta_seen >= iface->conf->track_sta_max_num) { + /* Expire oldest entry to make room for a new one */ + sta_track_expire(iface, 1); + } + + wpa_printf(MSG_MSGDUMP, "%s: Add STA tracking entry for " + MACSTR, iface->bss[0]->conf->iface, MAC2STR(addr)); + dl_list_add_tail(&iface->sta_seen, &info->list); + iface->num_sta_seen++; +} + + +struct hostapd_data * +sta_track_seen_on(struct hostapd_iface *iface, const u8 *addr, + const char *ifname) +{ + struct hapd_interfaces *interfaces = iface->interfaces; + size_t i, j; + + for (i = 0; i < interfaces->count; i++) { + struct hostapd_data *hapd = NULL; + + iface = interfaces->iface[i]; + for (j = 0; j < iface->num_bss; j++) { + hapd = iface->bss[j]; + if (os_strcmp(ifname, hapd->conf->iface) == 0) + break; + hapd = NULL; + } + + if (hapd && sta_track_get(iface, addr)) + return hapd; + } + + return NULL; +} + + +void handle_probe_req(struct hostapd_data *hapd, + const struct ieee80211_mgmt *mgmt, size_t len, + int ssi_signal) +{ + u8 *resp; + struct ieee802_11_elems elems; + const u8 *ie; + size_t ie_len; + size_t i, resp_len; + int noack; + enum ssid_match_result res; + + ie = mgmt->u.probe_req.variable; + if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req) - VARIABLE_ARRAY_SPARE) + return; + if (hapd->iconf->track_sta_max_num) + sta_track_add(hapd->iface, mgmt->sa); + ie_len = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.probe_req) - VARIABLE_ARRAY_SPARE); + + for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++) + if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx, + mgmt->sa, mgmt->da, mgmt->bssid, + ie, ie_len, ssi_signal) > 0) + return; + + if (!hapd->iconf->send_probe_response) + return; + + if (ieee802_11_parse_elems(ie, ie_len, &elems, 0) == ParseFailed) { + wpa_printf(MSG_DEBUG, "Could not parse ProbeReq from " MACSTR, + MAC2STR(mgmt->sa)); + return; + } + + if ((!elems.ssid || !elems.supp_rates)) { + wpa_printf(MSG_DEBUG, "STA " MACSTR " sent probe request " + "without SSID or supported rates element", + MAC2STR(mgmt->sa)); + return; + } + + if (hapd->conf->ignore_broadcast_ssid && elems.ssid_len == 0 && + elems.ssid_list_len == 0) { + wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR " for " + "broadcast SSID ignored", MAC2STR(mgmt->sa)); + return; + } + +#ifdef CONFIG_P2P + if ((hapd->conf->p2p & P2P_GROUP_OWNER) && + elems.ssid_len == P2P_WILDCARD_SSID_LEN && + os_memcmp(elems.ssid, P2P_WILDCARD_SSID, + P2P_WILDCARD_SSID_LEN) == 0) { + /* Process P2P Wildcard SSID like Wildcard SSID */ + elems.ssid_len = 0; + } +#endif /* CONFIG_P2P */ + + res = ssid_match(hapd, elems.ssid, elems.ssid_len, + elems.ssid_list, elems.ssid_list_len); + if (res == NO_SSID_MATCH) { + if (!(mgmt->da[0] & 0x01)) { + wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR + " for foreign SSID '%s' (DA " MACSTR ")%s", + MAC2STR(mgmt->sa), + wpa_ssid_txt(elems.ssid, elems.ssid_len), + MAC2STR(mgmt->da), + elems.ssid_list ? " (SSID list)" : ""); + } + return; + } + +#ifdef CONFIG_INTERWORKING + if (hapd->conf->interworking && + elems.interworking && elems.interworking_len >= 1) { + u8 ant = elems.interworking[0] & 0x0f; + if (ant != INTERWORKING_ANT_WILDCARD && + ant != hapd->conf->access_network_type) { + wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR + " for mismatching ANT %u ignored", + MAC2STR(mgmt->sa), ant); + return; + } + } + + if (hapd->conf->interworking && elems.interworking && + (elems.interworking_len == 7 || elems.interworking_len == 9)) { + const u8 *hessid; + if (elems.interworking_len == 7) + hessid = elems.interworking + 1; + else + hessid = elems.interworking + 1 + 2; + if (!is_broadcast_ether_addr(hessid) && + os_memcmp(hessid, hapd->conf->hessid, ETH_ALEN) != 0) { + wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR + " for mismatching HESSID " MACSTR + " ignored", + MAC2STR(mgmt->sa), MAC2STR(hessid)); + return; + } + } +#endif /* CONFIG_INTERWORKING */ + +#ifdef CONFIG_P2P + if ((hapd->conf->p2p & P2P_GROUP_OWNER) && + supp_rates_11b_only(&elems)) { + /* Indicates support for 11b rates only */ + wpa_printf(MSG_EXCESSIVE, "P2P: Ignore Probe Request from " + MACSTR " with only 802.11b rates", + MAC2STR(mgmt->sa)); + return; + } +#endif /* CONFIG_P2P */ + + /* TODO: verify that supp_rates contains at least one matching rate + * with AP configuration */ + + if (hapd->conf->no_probe_resp_if_seen_on && + is_multicast_ether_addr(mgmt->da) && + is_multicast_ether_addr(mgmt->bssid) && + sta_track_seen_on(hapd->iface, mgmt->sa, + hapd->conf->no_probe_resp_if_seen_on)) { + wpa_printf(MSG_MSGDUMP, "%s: Ignore Probe Request from " MACSTR + " since STA has been seen on %s", + hapd->conf->iface, MAC2STR(mgmt->sa), + hapd->conf->no_probe_resp_if_seen_on); + return; + } + +#ifdef CONFIG_TESTING_OPTIONS + if (hapd->iconf->ignore_probe_probability > 0.0 && + drand48() < hapd->iconf->ignore_probe_probability) { + wpa_printf(MSG_INFO, + "TESTING: ignoring probe request from " MACSTR, + MAC2STR(mgmt->sa)); + return; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + resp = hostapd_gen_probe_resp(hapd, mgmt, elems.p2p != NULL, + &resp_len); + if (resp == NULL) + return; + + /* + * If this is a broadcast probe request, apply no ack policy to avoid + * excessive retries. + */ + noack = !!(res == WILDCARD_SSID_MATCH && + is_broadcast_ether_addr(mgmt->da)); + + if (hostapd_drv_send_mlme(hapd, resp, resp_len, noack) < 0) + wpa_printf(MSG_INFO, "handle_probe_req: send failed"); + + os_free(resp); + + wpa_printf(MSG_EXCESSIVE, "STA " MACSTR " sent probe request for %s " + "SSID", MAC2STR(mgmt->sa), + elems.ssid_len == 0 ? "broadcast" : "our"); +} + + +static u8 * hostapd_probe_resp_offloads(struct hostapd_data *hapd, + size_t *resp_len) +{ + /* check probe response offloading caps and print warnings */ + if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_PROBE_RESP_OFFLOAD)) + return NULL; + +#ifdef CONFIG_WPS + if (hapd->conf->wps_state && hapd->wps_probe_resp_ie && + (!(hapd->iface->probe_resp_offloads & + (WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS | + WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS2)))) + wpa_printf(MSG_WARNING, "Device is trying to offload WPS " + "Probe Response while not supporting this"); +#endif /* CONFIG_WPS */ + +#ifdef CONFIG_P2P + if ((hapd->conf->p2p & P2P_ENABLED) && hapd->p2p_probe_resp_ie && + !(hapd->iface->probe_resp_offloads & + WPA_DRIVER_PROBE_RESP_OFFLOAD_P2P)) + wpa_printf(MSG_WARNING, "Device is trying to offload P2P " + "Probe Response while not supporting this"); +#endif /* CONFIG_P2P */ + + if (hapd->conf->interworking && + !(hapd->iface->probe_resp_offloads & + WPA_DRIVER_PROBE_RESP_OFFLOAD_INTERWORKING)) + wpa_printf(MSG_WARNING, "Device is trying to offload " + "Interworking Probe Response while not supporting " + "this"); + + /* Generate a Probe Response template for the non-P2P case */ + return hostapd_gen_probe_resp(hapd, NULL, 0, resp_len); +} + +#endif /* NEED_AP_MLME */ + + +int ieee802_11_build_ap_params(struct hostapd_data *hapd, + struct wpa_driver_ap_params *params) +{ + struct ieee80211_mgmt *head = NULL; + u8 *tail = NULL; + size_t head_len = 0, tail_len = 0; + u8 *resp = NULL; + size_t resp_len = 0; +#ifdef NEED_AP_MLME + u16 capab_info; + u8 *pos, *tailpos; + +#define BEACON_HEAD_BUF_SIZE 256 +#define BEACON_TAIL_BUF_SIZE 512 + head = os_zalloc(BEACON_HEAD_BUF_SIZE); + tail_len = BEACON_TAIL_BUF_SIZE; + + if (hapd->conf->vendor_elements) + tail_len += wpabuf_len(hapd->conf->vendor_elements); + +#ifdef CONFIG_IEEE80211AC + if (hapd->conf->vendor_vht) { + tail_len += 5 + 2 + sizeof(struct ieee80211_vht_capabilities) + + 2 + sizeof(struct ieee80211_vht_operation); + } +#endif /* CONFIG_IEEE80211AC */ + + tailpos = tail = os_malloc(tail_len); + if (head == NULL || tail == NULL) { + wpa_printf(MSG_ERROR, "Failed to set beacon data"); + os_free(head); + os_free(tail); + return -1; + } + + head->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, + WLAN_FC_STYPE_BEACON); + head->duration = host_to_le16(0); + os_memset(head->da, 0xff, ETH_ALEN); + + os_memcpy(head->sa, hapd->own_addr, ETH_ALEN); + os_memcpy(head->bssid, hapd->own_addr, ETH_ALEN); + head->u.beacon.beacon_int = + host_to_le16(hapd->iconf->beacon_int); + + /* hardware or low-level driver will setup seq_ctrl and timestamp */ + capab_info = hostapd_own_capab_info(hapd); + head->u.beacon.capab_info = host_to_le16(capab_info); + pos = &head->u.beacon.variable[0]; + + /* SSID */ + *pos++ = WLAN_EID_SSID; + if (hapd->conf->ignore_broadcast_ssid == 2) { + /* clear the data, but keep the correct length of the SSID */ + *pos++ = hapd->conf->ssid.ssid_len; + os_memset(pos, 0, hapd->conf->ssid.ssid_len); + pos += hapd->conf->ssid.ssid_len; + } else if (hapd->conf->ignore_broadcast_ssid) { + *pos++ = 0; /* empty SSID */ + } else { + *pos++ = hapd->conf->ssid.ssid_len; + os_memcpy(pos, hapd->conf->ssid.ssid, hapd->conf->ssid.ssid_len); + pos += hapd->conf->ssid.ssid_len; + } + + /* Supported rates */ + pos = hostapd_eid_supp_rates(hapd, pos); + + /* DS Params */ + pos = hostapd_eid_ds_params(hapd, pos); + + head_len = pos - (u8 *) head; + + tailpos = hostapd_eid_country(hapd, tailpos, + tail + BEACON_TAIL_BUF_SIZE - tailpos); + +#ifdef CONFIG_FULL_HOSTAPD + /* Power Constraint element */ + tailpos = hostapd_eid_pwr_constraint(hapd, tailpos); +#endif + + /* ERP Information element */ + tailpos = hostapd_eid_erp_info(hapd, tailpos); + + /* Extended supported rates */ + tailpos = hostapd_eid_ext_supp_rates(hapd, tailpos); + + /* RSN, MDIE, WPA */ + tailpos = hostapd_eid_wpa(hapd, tailpos, tail + BEACON_TAIL_BUF_SIZE - + tailpos); + +#ifdef CONFIG_FULL_HOSTAPD + tailpos = hostapd_eid_rm_enabled_capab(hapd, tailpos, + tail + BEACON_TAIL_BUF_SIZE - + tailpos); + + tailpos = hostapd_eid_bss_load(hapd, tailpos, + tail + BEACON_TAIL_BUF_SIZE - tailpos); +#endif +#ifdef CONFIG_IEEE80211N + tailpos = hostapd_eid_ht_capabilities(hapd, tailpos); + tailpos = hostapd_eid_ht_operation(hapd, tailpos); +#endif /* CONFIG_IEEE80211N */ + + tailpos = hostapd_eid_ext_capab(hapd, tailpos); + +#ifdef CONFIG_FULL_HOSTAPD + /* + * TODO: Time Advertisement element should only be included in some + * DTIM Beacon frames. + */ + tailpos = hostapd_eid_time_adv(hapd, tailpos); + + tailpos = hostapd_eid_interworking(hapd, tailpos); + tailpos = hostapd_eid_adv_proto(hapd, tailpos); + tailpos = hostapd_eid_roaming_consortium(hapd, tailpos); +#endif + tailpos = hostapd_add_csa_elems(hapd, tailpos, tail, + &hapd->cs_c_off_beacon); + + /* Wi-Fi Alliance WMM */ + tailpos = hostapd_eid_wmm(hapd, tailpos); + + if (hapd->conf->vendor_elements) { + os_memcpy(tailpos, wpabuf_head(hapd->conf->vendor_elements), + wpabuf_len(hapd->conf->vendor_elements)); + tailpos += wpabuf_len(hapd->conf->vendor_elements); + } + + tail_len = tailpos > tail ? tailpos - tail : 0; + + resp = hostapd_probe_resp_offloads(hapd, &resp_len); +#endif /* NEED_AP_MLME */ + + os_memset(params, 0, sizeof(*params)); + params->head = (u8 *) head; + params->head_len = head_len; + params->tail = tail; + params->tail_len = tail_len; + params->proberesp = resp; + params->proberesp_len = resp_len; + params->dtim_period = hapd->conf->dtim_period; + params->beacon_int = hapd->iconf->beacon_int; + params->basic_rates = hapd->iface->basic_rates; + params->ssid = hapd->conf->ssid.ssid; + params->ssid_len = hapd->conf->ssid.ssid_len; + if ((hapd->conf->wpa & (WPA_PROTO_WPA | WPA_PROTO_RSN)) == + (WPA_PROTO_WPA | WPA_PROTO_RSN)) + params->pairwise_ciphers = hapd->conf->wpa_pairwise | + hapd->conf->rsn_pairwise; + else if (hapd->conf->wpa & WPA_PROTO_RSN) + params->pairwise_ciphers = hapd->conf->rsn_pairwise; + else if (hapd->conf->wpa & WPA_PROTO_WPA) + params->pairwise_ciphers = hapd->conf->wpa_pairwise; + params->group_cipher = hapd->conf->wpa_group; + params->key_mgmt_suites = hapd->conf->wpa_key_mgmt; + params->auth_algs = hapd->conf->auth_algs; + params->wpa_version = hapd->conf->wpa; + params->privacy = hapd->conf->ssid.wep.keys_set || hapd->conf->wpa || + (hapd->conf->ieee802_1x && + (hapd->conf->default_wep_key_len || + hapd->conf->individual_wep_key_len)); + switch (hapd->conf->ignore_broadcast_ssid) { + case 0: + params->hide_ssid = NO_SSID_HIDING; + break; + case 1: + params->hide_ssid = HIDDEN_SSID_ZERO_LEN; + break; + case 2: + params->hide_ssid = HIDDEN_SSID_ZERO_CONTENTS; + break; + } + params->isolate = hapd->conf->isolate; + params->smps_mode = hapd->iconf->ht_capab & HT_CAP_INFO_SMPS_MASK; +#ifdef NEED_AP_MLME + params->cts_protect = !!(ieee802_11_erp_info(hapd) & + ERP_INFO_USE_PROTECTION); + params->preamble = hapd->iface->num_sta_no_short_preamble == 0 && + hapd->iconf->preamble == SHORT_PREAMBLE; + if (hapd->iface->current_mode && + hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G) + params->short_slot_time = + hapd->iface->num_sta_no_short_slot_time > 0 ? 0 : 1; + else + params->short_slot_time = -1; + if (!hapd->iconf->ieee80211n || hapd->conf->disable_11n) + params->ht_opmode = -1; + else + params->ht_opmode = hapd->iface->ht_op_mode; +#endif /* NEED_AP_MLME */ + params->interworking = hapd->conf->interworking; + if (hapd->conf->interworking && + !is_zero_ether_addr(hapd->conf->hessid)) + params->hessid = hapd->conf->hessid; + params->access_network_type = hapd->conf->access_network_type; + params->ap_max_inactivity = hapd->conf->ap_max_inactivity; +#ifdef CONFIG_P2P + params->p2p_go_ctwindow = hapd->iconf->p2p_go_ctwindow; +#endif /* CONFIG_P2P */ +#ifdef CONFIG_HS20 + params->disable_dgaf = hapd->conf->disable_dgaf; + if (hapd->conf->osen) { + params->privacy = 1; + params->osen = 1; + } +#endif /* CONFIG_HS20 */ + return 0; +} + + +void ieee802_11_free_ap_params(struct wpa_driver_ap_params *params) +{ + os_free(params->tail); + params->tail = NULL; + os_free(params->head); + params->head = NULL; + os_free(params->proberesp); + params->proberesp = NULL; +} + + +int ieee802_11_set_beacon(struct hostapd_data *hapd) +{ + struct wpa_driver_ap_params params; + struct hostapd_freq_params freq; + struct hostapd_iface *iface = hapd->iface; + struct hostapd_config *iconf = iface->conf; + struct wpabuf *beacon, *proberesp, *assocresp; + int res, ret = -1; + + if (hapd->csa_in_progress) { + wpa_printf(MSG_ERROR, "Cannot set beacons during CSA period"); + return -1; + } + + hapd->beacon_set_done = 1; + + if (ieee802_11_build_ap_params(hapd, ¶ms) < 0) + return -1; + + if (hostapd_build_ap_extra_ies(hapd, &beacon, &proberesp, &assocresp) < + 0) + goto fail; + + params.beacon_ies = beacon; + params.proberesp_ies = proberesp; + params.assocresp_ies = assocresp; + params.reenable = hapd->reenable_beacon; + hapd->reenable_beacon = 0; + + if (iface->current_mode && + hostapd_set_freq_params(&freq, iconf->hw_mode, iface->freq, + iconf->channel, iconf->ieee80211n, + iconf->ieee80211ac, + iconf->secondary_channel, + iconf->vht_oper_chwidth, + iconf->vht_oper_centr_freq_seg0_idx, + iconf->vht_oper_centr_freq_seg1_idx, + iface->current_mode->vht_capab) == 0) + params.freq = &freq; + + res = hostapd_drv_set_ap(hapd, ¶ms); + hostapd_free_ap_extra_ies(hapd, beacon, proberesp, assocresp); + if (res) + wpa_printf(MSG_ERROR, "Failed to set beacon parameters"); + else + ret = 0; +fail: + ieee802_11_free_ap_params(¶ms); + return ret; +} + + +int ieee802_11_set_beacons(struct hostapd_iface *iface) +{ + size_t i; + int ret = 0; + + for (i = 0; i < iface->num_bss; i++) { + if (iface->bss[i]->started && + ieee802_11_set_beacon(iface->bss[i]) < 0) + ret = -1; + } + + return ret; +} + + +/* only update beacons if started */ +int ieee802_11_update_beacons(struct hostapd_iface *iface) +{ + size_t i; + int ret = 0; + + for (i = 0; i < iface->num_bss; i++) { + if (iface->bss[i]->beacon_set_done && iface->bss[i]->started && + ieee802_11_set_beacon(iface->bss[i]) < 0) + ret = -1; + } + + return ret; +} + +#endif /* CONFIG_NATIVE_WINDOWS */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/ap/beacon.h b/beken_os/beken378/func/hostapd-2.5/src/ap/beacon.h new file mode 100755 index 0000000..d98f42e --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/ap/beacon.h @@ -0,0 +1,30 @@ +/* + * hostapd / IEEE 802.11 Management: Beacon and Probe Request/Response + * Copyright (c) 2002-2004, Instant802 Networks, Inc. + * Copyright (c) 2005-2006, Devicescape Software, Inc. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef BEACON_H +#define BEACON_H + +struct ieee80211_mgmt; + +void handle_probe_req(struct hostapd_data *hapd, + const struct ieee80211_mgmt *mgmt, size_t len, + int ssi_signal); +int ieee802_11_set_beacon(struct hostapd_data *hapd); +int ieee802_11_set_beacons(struct hostapd_iface *iface); +int ieee802_11_update_beacons(struct hostapd_iface *iface); +int ieee802_11_build_ap_params(struct hostapd_data *hapd, + struct wpa_driver_ap_params *params); +void ieee802_11_free_ap_params(struct wpa_driver_ap_params *params); +void sta_track_add(struct hostapd_iface *iface, const u8 *addr); +void sta_track_expire(struct hostapd_iface *iface, int force); +struct hostapd_data * +sta_track_seen_on(struct hostapd_iface *iface, const u8 *addr, + const char *ifname); + +#endif /* BEACON_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/ap/bss_load.h b/beken_os/beken378/func/hostapd-2.5/src/ap/bss_load.h new file mode 100755 index 0000000..ac3c793 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/ap/bss_load.h @@ -0,0 +1,17 @@ +/* + * BSS load update + * Copyright (c) 2014, Qualcomm Atheros, Inc. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef BSS_LOAD_UPDATE_H +#define BSS_LOAD_UPDATE_H + + +int bss_load_update_init(struct hostapd_data *hapd); +void bss_load_update_deinit(struct hostapd_data *hapd); + + +#endif /* BSS_LOAD_UPDATE_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/ap/dfs.h b/beken_os/beken378/func/hostapd-2.5/src/ap/dfs.h new file mode 100755 index 0000000..42a25b1 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/ap/dfs.h @@ -0,0 +1,31 @@ +/* + * DFS - Dynamic Frequency Selection + * Copyright (c) 2002-2013, Jouni Malinen + * Copyright (c) 2013, Qualcomm Atheros, Inc. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ +#ifndef DFS_H +#define DFS_H + +int hostapd_handle_dfs(struct hostapd_iface *iface); + +int hostapd_dfs_complete_cac(struct hostapd_iface *iface, int success, int freq, + int ht_enabled, int chan_offset, int chan_width, + int cf1, int cf2); +int hostapd_dfs_radar_detected(struct hostapd_iface *iface, int freq, + int ht_enabled, + int chan_offset, int chan_width, + int cf1, int cf2); +int hostapd_dfs_nop_finished(struct hostapd_iface *iface, int freq, + int ht_enabled, + int chan_offset, int chan_width, int cf1, int cf2); +int hostapd_is_dfs_required(struct hostapd_iface *iface); +int hostapd_dfs_start_cac(struct hostapd_iface *iface, int freq, + int ht_enabled, int chan_offset, int chan_width, + int cf1, int cf2); +int hostapd_handle_dfs_offload(struct hostapd_iface *iface); + +#endif /* DFS_H */ + diff --git a/beken_os/beken378/func/hostapd-2.5/src/ap/drv_callbacks.c b/beken_os/beken378/func/hostapd-2.5/src/ap/drv_callbacks.c new file mode 100755 index 0000000..a67e9f8 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/ap/drv_callbacks.c @@ -0,0 +1,1308 @@ +/* + * hostapd / Callback functions for driver wrappers + * Copyright (c) 2002-2013, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "utils/eloop.h" +#include "drivers/driver.h" +#include "common/ieee802_11_defs.h" +#include "common/ieee802_11_common.h" +#include "common/wpa_ctrl.h" +#include "crypto/random.h" +#include "wps/wps.h" +#include "ap/hostapd.h" +#include "ieee802_11.h" +#include "ap/sta_info.h" +#include "accounting.h" +#include "tkip_countermeasures.h" +#include "ieee802_1x.h" +#include "wpa_auth.h" +#include "wps_hostapd.h" +#include "ap_drv_ops.h" +#include "ap_config.h" +#include "hw_features.h" +#include "ap/dfs.h" +#include "beacon.h" +#include "hostapd_cfg.h" +#include "include.h" + +int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr, + const u8 *req_ies, size_t req_ies_len, int reassoc) +{ + struct sta_info *sta; + int new_assoc, res; + struct ieee802_11_elems elems; + const u8 *ie; + size_t ielen; +#if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211W) + u8 buf[sizeof(struct ieee80211_mgmt) + 1024]; + u8 *p = buf; +#endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W */ + u16 reason = WLAN_REASON_UNSPECIFIED; + u16 status = WLAN_STATUS_SUCCESS; + const u8 *p2p_dev_addr = NULL; + + if (addr == NULL) { + /* + * This could potentially happen with unexpected event from the + * driver wrapper. This was seen at least in one case where the + * driver ended up being set to station mode while hostapd was + * running, so better make sure we stop processing such an + * event here. + */ + wpa_printf(MSG_DEBUG, + "hostapd_notif_assoc: Skip event with no address"); + return -1; + } + random_add_randomness(addr, ETH_ALEN); + + hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, "associated"); + + ieee802_11_parse_elems(req_ies, req_ies_len, &elems, 0); + if (elems.wps_ie) { + ie = elems.wps_ie - 2; + ielen = elems.wps_ie_len + 2; + wpa_printf(MSG_DEBUG, "STA included WPS IE in (Re)AssocReq"); + } else if (elems.rsn_ie) { + ie = elems.rsn_ie - 2; + ielen = elems.rsn_ie_len + 2; + wpa_printf(MSG_DEBUG, "STA included RSN IE in (Re)AssocReq"); + } else if (elems.wpa_ie) { + ie = elems.wpa_ie - 2; + ielen = elems.wpa_ie_len + 2; + wpa_printf(MSG_DEBUG, "STA included WPA IE in (Re)AssocReq"); +#ifdef CONFIG_HS20 + } else if (elems.osen) { + ie = elems.osen - 2; + ielen = elems.osen_len + 2; + wpa_printf(MSG_DEBUG, "STA included OSEN IE in (Re)AssocReq"); +#endif /* CONFIG_HS20 */ + } else { + ie = NULL; + ielen = 0; + wpa_printf(MSG_DEBUG, + "STA did not include WPS/RSN/WPA IE in (Re)AssocReq"); + } + + sta = ap_get_sta(hapd, addr); + if (sta) { + ap_sta_no_session_timeout(hapd, sta); + accounting_sta_stop(hapd, sta); + + /* + * Make sure that the previously registered inactivity timer + * will not remove the STA immediately. + */ + sta->timeout_next = STA_NULLFUNC; + } else { + sta = ap_sta_add(hapd, addr); + if (sta == NULL) { + hostapd_drv_sta_disassoc(hapd, addr, + WLAN_REASON_DISASSOC_AP_BUSY); + return -1; + } + } + sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS | WLAN_STA_WPS2); + +#ifdef CONFIG_P2P + if (elems.p2p) { + wpabuf_free(sta->p2p_ie); + sta->p2p_ie = ieee802_11_vendor_ie_concat(req_ies, req_ies_len, + P2P_IE_VENDOR_TYPE); + if (sta->p2p_ie) + p2p_dev_addr = p2p_get_go_dev_addr(sta->p2p_ie); + } +#endif /* CONFIG_P2P */ + +#ifdef CONFIG_IEEE80211N +#ifdef NEED_AP_MLME + if (elems.ht_capabilities && + (hapd->iface->conf->ht_capab & + HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) { + struct ieee80211_ht_capabilities *ht_cap = + (struct ieee80211_ht_capabilities *) + elems.ht_capabilities; + + if (le_to_host16(ht_cap->ht_capabilities_info) & + HT_CAP_INFO_40MHZ_INTOLERANT) + ht40_intolerant_add(hapd->iface, sta); + } +#endif /* NEED_AP_MLME */ +#endif /* CONFIG_IEEE80211N */ + + if (hapd->conf->wpa) { + if (ie == NULL || ielen == 0) { +#ifdef CONFIG_WPS + if (hapd->conf->wps_state) { + wpa_printf(MSG_DEBUG, + "STA did not include WPA/RSN IE in (Re)Association Request - possible WPS use"); + sta->flags |= WLAN_STA_MAYBE_WPS; + goto skip_wpa_check; + } +#endif /* CONFIG_WPS */ + + wpa_printf(MSG_DEBUG, "No WPA/RSN IE from STA"); + return -1; + } +#ifdef CONFIG_WPS + if (hapd->conf->wps_state && ie[0] == 0xdd && ie[1] >= 4 && + os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) { + struct wpabuf *wps; + + sta->flags |= WLAN_STA_WPS; + wps = ieee802_11_vendor_ie_concat(ie, ielen, + WPS_IE_VENDOR_TYPE); + if (wps) { + if (wps_is_20(wps)) { + wpa_printf(MSG_DEBUG, + "WPS: STA supports WPS 2.0"); + sta->flags |= WLAN_STA_WPS2; + } + wpabuf_free(wps); + } + goto skip_wpa_check; + } +#endif /* CONFIG_WPS */ + + if (sta->wpa_sm == NULL) + sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, + sta->addr, + p2p_dev_addr); + if (sta->wpa_sm == NULL) { + wpa_printf(MSG_ERROR, + "Failed to initialize WPA state machine"); + return -1; + } + res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm, + ie, ielen, + elems.mdie, elems.mdie_len); + if (res != WPA_IE_OK) { + wpa_printf(MSG_DEBUG, + "WPA/RSN information element rejected? (res %u)", + res); + wpa_hexdump(MSG_DEBUG, "IE", ie, ielen); + if (res == WPA_INVALID_GROUP) { + reason = WLAN_REASON_GROUP_CIPHER_NOT_VALID; + status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID; + } else if (res == WPA_INVALID_PAIRWISE) { + reason = WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID; + status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID; + } else if (res == WPA_INVALID_AKMP) { + reason = WLAN_REASON_AKMP_NOT_VALID; + status = WLAN_STATUS_AKMP_NOT_VALID; + } +#ifdef CONFIG_IEEE80211W + else if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION) { + reason = WLAN_REASON_INVALID_IE; + status = WLAN_STATUS_INVALID_IE; + } else if (res == WPA_INVALID_MGMT_GROUP_CIPHER) { + reason = WLAN_REASON_GROUP_CIPHER_NOT_VALID; + status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID; + } +#endif /* CONFIG_IEEE80211W */ + else { + reason = WLAN_REASON_INVALID_IE; + status = WLAN_STATUS_INVALID_IE; + } + goto fail; + } +#ifdef CONFIG_IEEE80211W + if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out && + sta->sa_query_count > 0) + ap_check_sa_query_timeout(hapd, sta); + if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out && + (sta->auth_alg != WLAN_AUTH_FT)) { + /* + * STA has already been associated with MFP and SA + * Query timeout has not been reached. Reject the + * association attempt temporarily and start SA Query, + * if one is not pending. + */ + + if (sta->sa_query_count == 0) + ap_sta_start_sa_query(hapd, sta); + + status = WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY; + + p = hostapd_eid_assoc_comeback_time(hapd, sta, p); + + hostapd_sta_assoc(hapd, addr, reassoc, status, buf, + p - buf); + return 0; + } + + if (wpa_auth_uses_mfp(sta->wpa_sm)) + sta->flags |= WLAN_STA_MFP; + else + sta->flags &= ~WLAN_STA_MFP; +#endif /* CONFIG_IEEE80211W */ + +#ifdef CONFIG_IEEE80211R + if (sta->auth_alg == WLAN_AUTH_FT) { + status = wpa_ft_validate_reassoc(sta->wpa_sm, req_ies, + req_ies_len); + if (status != WLAN_STATUS_SUCCESS) { + if (status == WLAN_STATUS_INVALID_PMKID) + reason = WLAN_REASON_INVALID_IE; + if (status == WLAN_STATUS_INVALID_MDIE) + reason = WLAN_REASON_INVALID_IE; + if (status == WLAN_STATUS_INVALID_FTIE) + reason = WLAN_REASON_INVALID_IE; + goto fail; + } + } +#endif /* CONFIG_IEEE80211R */ + } else if (hapd->conf->wps_state) { +#ifdef CONFIG_WPS + struct wpabuf *wps; + + if (req_ies) + wps = ieee802_11_vendor_ie_concat(req_ies, req_ies_len, + WPS_IE_VENDOR_TYPE); + else + wps = NULL; +#ifdef CONFIG_WPS_STRICT + if (wps && wps_validate_assoc_req(wps) < 0) { + reason = WLAN_REASON_INVALID_IE; + status = WLAN_STATUS_INVALID_IE; + wpabuf_free(wps); + goto fail; + } +#endif /* CONFIG_WPS_STRICT */ + if (wps) { + sta->flags |= WLAN_STA_WPS; + if (wps_is_20(wps)) { + wpa_printf(MSG_DEBUG, + "WPS: STA supports WPS 2.0"); + sta->flags |= WLAN_STA_WPS2; + } + } else + sta->flags |= WLAN_STA_MAYBE_WPS; + wpabuf_free(wps); +#endif /* CONFIG_WPS */ +#ifdef CONFIG_HS20 + } else if (hapd->conf->osen) { + if (elems.osen == NULL) { + hostapd_logger( + hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, + "No HS 2.0 OSEN element in association request"); + return WLAN_STATUS_INVALID_IE; + } + + wpa_printf(MSG_DEBUG, "HS 2.0: OSEN association"); + if (sta->wpa_sm == NULL) + sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, + sta->addr, NULL); + if (sta->wpa_sm == NULL) { + wpa_printf(MSG_WARNING, + "Failed to initialize WPA state machine"); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + if (wpa_validate_osen(hapd->wpa_auth, sta->wpa_sm, + elems.osen - 2, elems.osen_len + 2) < 0) + return WLAN_STATUS_INVALID_IE; +#endif /* CONFIG_HS20 */ + } +#ifdef CONFIG_WPS +skip_wpa_check: +#endif /* CONFIG_WPS */ + +#ifdef CONFIG_IEEE80211R + p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, buf, sizeof(buf), + sta->auth_alg, req_ies, req_ies_len); + + hostapd_sta_assoc(hapd, addr, reassoc, status, buf, p - buf); + + if (sta->auth_alg == WLAN_AUTH_FT) + ap_sta_set_authorized(hapd, sta, 1); +#else /* CONFIG_IEEE80211R */ + /* Keep compiler silent about unused variables */ + if (status) { + } +#endif /* CONFIG_IEEE80211R */ + + new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0; + sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC; + sta->flags &= ~WLAN_STA_WNM_SLEEP_MODE; + + hostapd_set_sta_flags(hapd, sta); + + if (reassoc && (sta->auth_alg == WLAN_AUTH_FT)) + wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC_FT); + else + wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC); + + hostapd_new_assoc_sta(hapd, sta, !new_assoc); + + ieee802_1x_notify_port_enabled(sta->eapol_sm, 1); + +#ifdef CONFIG_P2P + if (req_ies) { + p2p_group_notif_assoc(hapd->p2p_group, sta->addr, + req_ies, req_ies_len); + } +#endif /* CONFIG_P2P */ + + return 0; + +fail: +#ifdef CONFIG_IEEE80211R + hostapd_sta_assoc(hapd, addr, reassoc, status, buf, p - buf); +#endif /* CONFIG_IEEE80211R */ + hostapd_drv_sta_disassoc(hapd, sta->addr, reason); + ap_free_sta(hapd, sta); + return -1; +} + + +void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr) +{ + struct sta_info *sta; + + if (addr == NULL) { + /* + * This could potentially happen with unexpected event from the + * driver wrapper. This was seen at least in one case where the + * driver ended up reporting a station mode event while hostapd + * was running, so better make sure we stop processing such an + * event here. + */ + wpa_printf(MSG_DEBUG, + "hostapd_notif_disassoc: Skip event with no address"); + return; + } + + hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, "disassociated"); + + sta = ap_get_sta(hapd, addr); + if (sta == NULL) { + wpa_printf(MSG_DEBUG, + "Disassociation notification for unknown STA " + MACSTR, MAC2STR(addr)); + return; + } + + ap_sta_set_authorized(hapd, sta, 0); + sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC); + wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC); + ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); + ap_free_sta(hapd, sta); +} + + +void hostapd_event_sta_low_ack(struct hostapd_data *hapd, const u8 *addr) +{ + struct sta_info *sta = ap_get_sta(hapd, addr); + + if (!sta || !hapd->conf->disassoc_low_ack) + return; + + hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, + "disconnected due to excessive missing ACKs"); + hostapd_drv_sta_disassoc(hapd, addr, WLAN_REASON_DISASSOC_LOW_ACK); + if (sta) + ap_sta_disassociate(hapd, sta, WLAN_REASON_DISASSOC_LOW_ACK); +} + + +void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht, + int offset, int width, int cf1, int cf2) +{ +#ifdef NEED_AP_MLME + int channel, chwidth, seg0_idx = 0, seg1_idx = 0, is_dfs; + + hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, + "driver had channel switch: freq=%d, ht=%d, offset=%d, width=%d (%s), cf1=%d, cf2=%d", + freq, ht, offset, width, channel_width_to_string(width), + cf1, cf2); + + hapd->iface->freq = freq; + + channel = hostapd_hw_get_channel(hapd, freq); + if (!channel) { + hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_WARNING, + "driver switched to bad channel!"); + return; + } + + switch (width) { + case CHAN_WIDTH_80: + chwidth = VHT_CHANWIDTH_80MHZ; + break; + case CHAN_WIDTH_80P80: + chwidth = VHT_CHANWIDTH_80P80MHZ; + break; + case CHAN_WIDTH_160: + chwidth = VHT_CHANWIDTH_160MHZ; + break; + case CHAN_WIDTH_20_NOHT: + case CHAN_WIDTH_20: + case CHAN_WIDTH_40: + default: + chwidth = VHT_CHANWIDTH_USE_HT; + break; + } + + switch (hapd->iface->current_mode->mode) { + case HOSTAPD_MODE_IEEE80211A: + if (cf1 > 5000) + seg0_idx = (cf1 - 5000) / 5; + if (cf2 > 5000) + seg1_idx = (cf2 - 5000) / 5; + break; + default: + seg0_idx = hostapd_hw_get_channel(hapd, cf1); + seg1_idx = hostapd_hw_get_channel(hapd, cf2); + break; + } + + hapd->iconf->channel = channel; + hapd->iconf->ieee80211n = ht; + if (!ht) + hapd->iconf->ieee80211ac = 0; + hapd->iconf->secondary_channel = offset; + hapd->iconf->vht_oper_chwidth = chwidth; + hapd->iconf->vht_oper_centr_freq_seg0_idx = seg0_idx; + hapd->iconf->vht_oper_centr_freq_seg1_idx = seg1_idx; + + is_dfs = ieee80211_is_dfs(freq); + + if (hapd->csa_in_progress && + freq == hapd->cs_freq_params.freq) { + hostapd_cleanup_cs_params(hapd); + ieee802_11_set_beacon(hapd); + + wpa_msg(hapd->msg_ctx, MSG_INFO, AP_CSA_FINISHED + "freq=%d dfs=%d", freq, is_dfs); + } else if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) { + wpa_msg(hapd->msg_ctx, MSG_INFO, AP_CSA_FINISHED + "freq=%d dfs=%d", freq, is_dfs); + } + (void)is_dfs; +#endif /* NEED_AP_MLME */ +} + + +void hostapd_event_connect_failed_reason(struct hostapd_data *hapd, + const u8 *addr, int reason_code) +{ + switch (reason_code) { + case MAX_CLIENT_REACHED: + wpa_msg(hapd->msg_ctx, MSG_INFO, AP_REJECTED_MAX_STA MACSTR, + MAC2STR(addr)); + break; + case BLOCKED_CLIENT: + wpa_msg(hapd->msg_ctx, MSG_INFO, AP_REJECTED_BLOCKED_STA MACSTR, + MAC2STR(addr)); + break; + } +} + + +#ifdef CONFIG_ACS +static void hostapd_acs_channel_selected(struct hostapd_data *hapd, + struct acs_selected_channels *acs_res) +{ + int ret, i; + + if (hapd->iconf->channel) { + wpa_printf(MSG_INFO, "ACS: Channel was already set to %d", + hapd->iconf->channel); + return; + } + + if (!hapd->iface->current_mode) { + for (i = 0; i < hapd->iface->num_hw_features; i++) { + struct hostapd_hw_modes *mode = + &hapd->iface->hw_features[i]; + + if (mode->mode == acs_res->hw_mode) { + hapd->iface->current_mode = mode; + break; + } + } + if (!hapd->iface->current_mode) { + hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_WARNING, + "driver selected to bad hw_mode"); + return; + } + } + + hapd->iface->freq = hostapd_hw_get_freq(hapd, acs_res->pri_channel); + + if (!acs_res->pri_channel) { + hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_WARNING, + "driver switched to bad channel"); + return; + } + + hapd->iconf->channel = acs_res->pri_channel; + hapd->iconf->acs = 1; + + if (acs_res->sec_channel == 0) + hapd->iconf->secondary_channel = 0; + else if (acs_res->sec_channel < acs_res->pri_channel) + hapd->iconf->secondary_channel = -1; + else if (acs_res->sec_channel > acs_res->pri_channel) + hapd->iconf->secondary_channel = 1; + else { + wpa_printf(MSG_ERROR, "Invalid secondary channel!"); + return; + } + + if (hapd->iface->conf->ieee80211ac) { + /* set defaults for backwards compatibility */ + hapd->iconf->vht_oper_centr_freq_seg1_idx = 0; + hapd->iconf->vht_oper_centr_freq_seg0_idx = 0; + hapd->iconf->vht_oper_chwidth = VHT_CHANWIDTH_USE_HT; + if (acs_res->ch_width == 80) { + hapd->iconf->vht_oper_centr_freq_seg0_idx = + acs_res->vht_seg0_center_ch; + hapd->iconf->vht_oper_chwidth = VHT_CHANWIDTH_80MHZ; + } else if (acs_res->ch_width == 160) { + if (acs_res->vht_seg1_center_ch == 0) { + hapd->iconf->vht_oper_centr_freq_seg0_idx = + acs_res->vht_seg0_center_ch; + hapd->iconf->vht_oper_chwidth = + VHT_CHANWIDTH_160MHZ; + } else { + hapd->iconf->vht_oper_centr_freq_seg0_idx = + acs_res->vht_seg0_center_ch; + hapd->iconf->vht_oper_centr_freq_seg1_idx = + acs_res->vht_seg1_center_ch; + hapd->iconf->vht_oper_chwidth = + VHT_CHANWIDTH_80P80MHZ; + } + } + } + + ret = hostapd_acs_completed(hapd->iface, 0); + if (ret) { + wpa_printf(MSG_ERROR, + "ACS: Possibly channel configuration is invalid"); + } +} +#endif /* CONFIG_ACS */ + + +int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa, const u8 *da, + const u8 *bssid, const u8 *ie, size_t ie_len, + int ssi_signal) +{ + size_t i; + int ret = 0; + + if (sa == NULL || ie == NULL) + return -1; + + random_add_randomness(sa, ETH_ALEN); + for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++) { + if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx, + sa, da, bssid, ie, ie_len, + ssi_signal) > 0) { + ret = 1; + break; + } + } + return ret; +} + + +#ifdef HOSTAPD + +#ifdef CONFIG_IEEE80211R +static void hostapd_notify_auth_ft_finish(void *ctx, const u8 *dst, + const u8 *bssid, + u16 auth_transaction, u16 status, + const u8 *ies, size_t ies_len) +{ + struct hostapd_data *hapd = ctx; + struct sta_info *sta; + + sta = ap_get_sta(hapd, dst); + if (sta == NULL) + return; + + hostapd_logger(hapd, dst, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, "authentication OK (FT)"); + sta->flags |= WLAN_STA_AUTH; + + hostapd_sta_auth(hapd, dst, auth_transaction, status, ies, ies_len); +} +#endif /* CONFIG_IEEE80211R */ + +#ifdef CONFIG_FULL_HOSTAPD +static void hostapd_notif_auth(struct hostapd_data *hapd, + struct auth_info *rx_auth) +{ + struct sta_info *sta; + u16 status = WLAN_STATUS_SUCCESS; + u8 resp_ies[2 + WLAN_AUTH_CHALLENGE_LEN]; + size_t resp_ies_len = 0; + + sta = ap_get_sta(hapd, rx_auth->peer); + if (!sta) { + sta = ap_sta_add(hapd, rx_auth->peer); + if (sta == NULL) { + status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; + goto fail; + } + } + sta->flags &= ~WLAN_STA_PREAUTH; + ieee802_1x_notify_pre_auth(sta->eapol_sm, 0); +#ifdef CONFIG_IEEE80211R + if (rx_auth->auth_type == WLAN_AUTH_FT && hapd->wpa_auth) { + sta->auth_alg = WLAN_AUTH_FT; + if (sta->wpa_sm == NULL) + sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, + sta->addr, NULL); + if (sta->wpa_sm == NULL) { + wpa_printf(MSG_DEBUG, + "FT: Failed to initialize WPA state machine"); + status = WLAN_STATUS_UNSPECIFIED_FAILURE; + goto fail; + } + wpa_ft_process_auth(sta->wpa_sm, rx_auth->bssid, + rx_auth->auth_transaction, rx_auth->ies, + rx_auth->ies_len, + hostapd_notify_auth_ft_finish, hapd); + return; + } +#endif /* CONFIG_IEEE80211R */ +fail: + hostapd_sta_auth(hapd, rx_auth->peer, rx_auth->auth_transaction + 1, + status, resp_ies, resp_ies_len); +} +#endif + +static void hostapd_action_rx(struct hostapd_data *hapd, + struct rx_mgmt *drv_mgmt) +{ + struct ieee80211_mgmt *mgmt; + struct sta_info *sta; + u16 fc; + + if (drv_mgmt->frame_len < 24 + 1) + return; + + mgmt = (struct ieee80211_mgmt *) drv_mgmt->frame; + fc = le_to_host16(mgmt->frame_control); + if (WLAN_FC_GET_STYPE(fc) != WLAN_FC_STYPE_ACTION) + return; /* handled by the driver */ + + sta = ap_get_sta(hapd, mgmt->sa); + if (sta == NULL) { + wpa_printf(MSG_DEBUG, "%s: station not found", __func__); + return; + } +#ifdef CONFIG_IEEE80211R + if (mgmt->u.action.category == WLAN_ACTION_FT) { + const u8 *payload = drv_mgmt->frame + 24 + 1; + + wpa_ft_action_rx(sta->wpa_sm, payload, plen); + } +#endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_IEEE80211W + if (mgmt->u.action.category == WLAN_ACTION_SA_QUERY && plen >= 4) { + ieee802_11_sa_query_action( + hapd, mgmt->sa, + mgmt->u.action.u.sa_query_resp.action, + mgmt->u.action.u.sa_query_resp.trans_id); + } +#endif /* CONFIG_IEEE80211W */ +#ifdef CONFIG_WNM + if (mgmt->u.action.category == WLAN_ACTION_WNM) { + ieee802_11_rx_wnm_action_ap(hapd, mgmt, drv_mgmt->frame_len); + } +#endif /* CONFIG_WNM */ +#ifdef CONFIG_FST + if (mgmt->u.action.category == WLAN_ACTION_FST && hapd->iface->fst) { + fst_rx_action(hapd->iface->fst, mgmt, drv_mgmt->frame_len); + return; + } +#endif /* CONFIG_FST */ + +} + + +#ifdef NEED_AP_MLME + +#define HAPD_BROADCAST ((struct hostapd_data *) -1) + +static struct hostapd_data * get_hapd_bssid(struct hostapd_iface *iface, + const u8 *bssid) +{ + size_t i; + u8 *b = (u8*)iface->bss[0]->own_addr; + + if (bssid == NULL) + return NULL; + if (bssid[0] == 0xff && bssid[1] == 0xff && bssid[2] == 0xff && + bssid[3] == 0xff && bssid[4] == 0xff && bssid[5] == 0xff) + return HAPD_BROADCAST; + + if (!(b[0] | b[1] | b[2] | b[3] | b[4] | b[5])) { + return NULL; + } + + for (i = 0; i < iface->num_bss; i++) { + if (os_memcmp(bssid, iface->bss[i]->own_addr, ETH_ALEN) == 0) + return iface->bss[i]; + } + + return NULL; +} + + +static void hostapd_rx_from_unknown_sta(struct hostapd_data *hapd, + const u8 *bssid, const u8 *addr, + int wds) +{ + hapd = get_hapd_bssid(hapd->iface, bssid); + if (hapd == NULL || hapd == HAPD_BROADCAST) + return; + + ieee802_11_rx_from_unknown(hapd, addr, wds); +} + + +static int hostapd_mgmt_rx(struct hostapd_data *hapd, struct rx_mgmt *rx_mgmt) +{ + struct hostapd_iface *iface = hapd->iface; + const struct ieee80211_hdr *hdr; + const u8 *bssid; + struct hostapd_frame_info fi; + int ret; + +#ifdef CONFIG_TESTING_OPTIONS + if (hapd->ext_mgmt_frame_handling) { + size_t hex_len = 2 * rx_mgmt->frame_len + 1; + char *hex = os_malloc(hex_len); + + if (hex) { + wpa_snprintf_hex(hex, hex_len, rx_mgmt->frame, + rx_mgmt->frame_len); + wpa_msg(hapd->msg_ctx, MSG_INFO, "MGMT-RX %s", hex); + os_free(hex); + } + return 1; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + hdr = (const struct ieee80211_hdr *) rx_mgmt->frame; + bssid = get_hdr_bssid(hdr, rx_mgmt->frame_len); + if (bssid == NULL) + return 0; + + hapd = get_hapd_bssid(iface, bssid); + if (hapd == NULL) { + u16 fc = le_to_host16(hdr->frame_control); + + /* + * Drop frames to unknown BSSIDs except for Beacon frames which + * could be used to update neighbor information. + */ + if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && + WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON) + hapd = iface->bss[0]; + else + return 0; + } + + os_memset(&fi, 0, sizeof(fi)); + fi.datarate = rx_mgmt->datarate; + fi.ssi_signal = rx_mgmt->ssi_signal; + + if (hapd == HAPD_BROADCAST) { + size_t i; + + ret = 0; + for (i = 0; i < iface->num_bss; i++) { + /* if bss is set, driver will call this function for + * each bss individually. */ + if (rx_mgmt->drv_priv && + (iface->bss[i]->drv_priv != rx_mgmt->drv_priv)) + continue; + + if (ieee802_11_mgmt(iface->bss[i], rx_mgmt->frame, + rx_mgmt->frame_len, &fi) > 0) + ret = 1; + } + } else + ret = ieee802_11_mgmt(hapd, rx_mgmt->frame, rx_mgmt->frame_len, + &fi); + + random_add_randomness(&fi, sizeof(fi)); + + return ret; +} + + +static void hostapd_mgmt_tx_cb(struct hostapd_data *hapd, const u8 *buf, + size_t len, u16 stype, int ok) +{ + struct ieee80211_hdr *hdr; + + hdr = (struct ieee80211_hdr *) buf; + hapd = get_hapd_bssid(hapd->iface, get_hdr_bssid(hdr, len)); + if (hapd == NULL || hapd == HAPD_BROADCAST) + return; + ieee802_11_mgmt_cb(hapd, buf, len, stype, ok); +} + +#endif /* NEED_AP_MLME */ + +#ifdef CONFIG_FULL_HOSTAPD +static int hostapd_event_new_sta(struct hostapd_data *hapd, const u8 *addr) +{ + struct sta_info *sta = ap_get_sta(hapd, addr); + + if (sta) + return 0; + + wpa_printf(MSG_DEBUG, "Data frame from unknown STA " MACSTR + " - adding a new STA", MAC2STR(addr)); + sta = ap_sta_add(hapd, addr); + if (sta) { + hostapd_new_assoc_sta(hapd, sta, 0); + } else { + wpa_printf(MSG_DEBUG, "Failed to add STA entry for " MACSTR, + MAC2STR(addr)); + return -1; + } + + return 0; +} +#endif + +static void hostapd_event_eapol_rx(struct hostapd_data *hapd, const u8 *src, + const u8 *data, size_t data_len) +{ + struct hostapd_iface *iface = hapd->iface; + struct sta_info *sta; + size_t j; + + for (j = 0; j < iface->num_bss; j++) { + sta = ap_get_sta(iface->bss[j], src); + if (sta && sta->flags & WLAN_STA_ASSOC) { + hapd = iface->bss[j]; + break; + } + } + + ieee802_1x_receive(hapd, src, data, data_len); +} + +#ifdef CONFIG_FULL_HOSTAPD +static struct hostapd_channel_data * hostapd_get_mode_channel( + struct hostapd_iface *iface, unsigned int freq) +{ + int i; + struct hostapd_channel_data *chan; + + for (i = 0; i < iface->current_mode->num_channels; i++) { + chan = &iface->current_mode->channels[i]; + if (!chan) + return NULL; + if ((unsigned int) chan->freq == freq) + return chan; + } + + return NULL; +} + +static void hostapd_update_nf(struct hostapd_iface *iface, + struct hostapd_channel_data *chan, + struct freq_survey *survey) +{ + if (!iface->chans_surveyed) { + chan->min_nf = survey->nf; + iface->lowest_nf = survey->nf; + } else { + if (dl_list_empty(&chan->survey_list)) + chan->min_nf = survey->nf; + else if (survey->nf < chan->min_nf) + chan->min_nf = survey->nf; + if (survey->nf < iface->lowest_nf) + iface->lowest_nf = survey->nf; + } +} + +static void hostapd_single_channel_get_survey(struct hostapd_iface *iface, + struct survey_results *survey_res) +{ + struct hostapd_channel_data *chan; + struct freq_survey *survey; + u64 divisor, dividend; + + survey = dl_list_first(&survey_res->survey_list, struct freq_survey, + list); + if (!survey || !survey->freq) + return; + + chan = hostapd_get_mode_channel(iface, survey->freq); + if (!chan || chan->flag & HOSTAPD_CHAN_DISABLED) + return; + + wpa_printf(MSG_DEBUG, + "Single Channel Survey: (freq=%d channel_time=%ld channel_time_busy=%ld)", + survey->freq, + (unsigned long int) survey->channel_time, + (unsigned long int) survey->channel_time_busy); + + if (survey->channel_time > iface->last_channel_time && + survey->channel_time > survey->channel_time_busy) { + dividend = survey->channel_time_busy - + iface->last_channel_time_busy; + divisor = survey->channel_time - iface->last_channel_time; + + iface->channel_utilization = dividend * 255 / divisor; + wpa_printf(MSG_DEBUG, "Channel Utilization: %d", + iface->channel_utilization); + } + iface->last_channel_time = survey->channel_time; + iface->last_channel_time_busy = survey->channel_time_busy; +} + +static void hostapd_event_get_survey(struct hostapd_data *hapd, + struct survey_results *survey_results) +{ + struct hostapd_iface *iface = hapd->iface; + struct freq_survey *survey, *tmp; + struct hostapd_channel_data *chan; + + if (dl_list_empty(&survey_results->survey_list)) { + wpa_printf(MSG_DEBUG, "No survey data received"); + return; + } + + if (survey_results->freq_filter) { + hostapd_single_channel_get_survey(iface, survey_results); + return; + } + + dl_list_for_each_safe(survey, tmp, &survey_results->survey_list, + struct freq_survey, list) { + chan = hostapd_get_mode_channel(iface, survey->freq); + if (!chan) + continue; + if (chan->flag & HOSTAPD_CHAN_DISABLED) + continue; + + dl_list_del(&survey->list); + dl_list_add_tail(&chan->survey_list, &survey->list); + + hostapd_update_nf(iface, chan, survey); + + iface->chans_surveyed++; + } +} +#endif + +#ifdef NEED_AP_MLME +#ifdef CONFIG_FULL_HOSTAPD +static void hostapd_event_iface_unavailable(struct hostapd_data *hapd) +{ + wpa_printf(MSG_DEBUG, "Interface %s is unavailable -- stopped", + hapd->conf->iface); + + if (hapd->csa_in_progress) { + wpa_printf(MSG_INFO, "CSA failed (%s was stopped)", + hapd->conf->iface); + hostapd_switch_channel_fallback(hapd->iface, + &hapd->cs_freq_params); + } +} +#endif + +#ifdef CONFIG_DFS +static void hostapd_event_dfs_radar_detected(struct hostapd_data *hapd, + struct dfs_event *radar) +{ + wpa_printf(MSG_DEBUG, "DFS radar detected on %d MHz", radar->freq); + hostapd_dfs_radar_detected(hapd->iface, radar->freq, radar->ht_enabled, + radar->chan_offset, radar->chan_width, + radar->cf1, radar->cf2); +} + + +static void hostapd_event_dfs_cac_finished(struct hostapd_data *hapd, + struct dfs_event *radar) +{ + wpa_printf(MSG_DEBUG, "DFS CAC finished on %d MHz", radar->freq); + hostapd_dfs_complete_cac(hapd->iface, 1, radar->freq, radar->ht_enabled, + radar->chan_offset, radar->chan_width, + radar->cf1, radar->cf2); +} + + +static void hostapd_event_dfs_cac_aborted(struct hostapd_data *hapd, + struct dfs_event *radar) +{ + wpa_printf(MSG_DEBUG, "DFS CAC aborted on %d MHz", radar->freq); + hostapd_dfs_complete_cac(hapd->iface, 0, radar->freq, radar->ht_enabled, + radar->chan_offset, radar->chan_width, + radar->cf1, radar->cf2); +} + + +static void hostapd_event_dfs_nop_finished(struct hostapd_data *hapd, + struct dfs_event *radar) +{ + wpa_printf(MSG_DEBUG, "DFS NOP finished on %d MHz", radar->freq); + hostapd_dfs_nop_finished(hapd->iface, radar->freq, radar->ht_enabled, + radar->chan_offset, radar->chan_width, + radar->cf1, radar->cf2); +} + + +static void hostapd_event_dfs_cac_started(struct hostapd_data *hapd, + struct dfs_event *radar) +{ + wpa_printf(MSG_DEBUG, "DFS offload CAC started on %d MHz", radar->freq); + hostapd_dfs_start_cac(hapd->iface, radar->freq, radar->ht_enabled, + radar->chan_offset, radar->chan_width, + radar->cf1, radar->cf2); +} +#endif +#endif /* NEED_AP_MLME */ + + +void wpa_supplicant_event(void *ctx, enum wpa_event_type event, + union wpa_event_data *data) +{ + struct hostapd_data *hapd = ctx; +#ifndef CONFIG_NO_STDOUT_DEBUG + int level = MSG_DEBUG; + + if (event == EVENT_RX_MGMT && data->rx_mgmt.frame && + data->rx_mgmt.frame_len >= 24) { + const struct ieee80211_hdr *hdr; + u16 fc; + + hdr = (const struct ieee80211_hdr *) data->rx_mgmt.frame; + fc = le_to_host16(hdr->frame_control); + if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && + WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON) + level = MSG_EXCESSIVE; + if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && + WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_REQ) + level = MSG_EXCESSIVE; + } + + wpa_dbg(hapd->msg_ctx, level, "Event %s (%d) received", + event_to_string(event), event); +#endif /* CONFIG_NO_STDOUT_DEBUG */ + + switch (event) { + case EVENT_MICHAEL_MIC_FAILURE: + michael_mic_failure(hapd, data->michael_mic_failure.src, 1); + break; +#ifdef CONFIG_FULL_HOSTAPD + case EVENT_SCAN_RESULTS: + if (hapd->iface->scan_cb) + hapd->iface->scan_cb(hapd->iface); + break; + case EVENT_WPS_BUTTON_PUSHED: + hostapd_wps_button_pushed(hapd, NULL); + break; +#endif +#ifdef NEED_AP_MLME + case EVENT_TX_STATUS: + switch (data->tx_status.type) { + case WLAN_FC_TYPE_MGMT: + hostapd_mgmt_tx_cb(hapd, data->tx_status.data, + data->tx_status.data_len, + data->tx_status.stype, + data->tx_status.ack); + break; + case WLAN_FC_TYPE_DATA: + hostapd_tx_status(hapd, data->tx_status.dst, + data->tx_status.data, + data->tx_status.data_len, + data->tx_status.ack); + break; + } + break; + case EVENT_EAPOL_TX_STATUS: + hostapd_eapol_tx_status(hapd, data->eapol_tx_status.dst, + data->eapol_tx_status.data, + data->eapol_tx_status.data_len, + data->eapol_tx_status.ack); + break; + case EVENT_DRIVER_CLIENT_POLL_OK: + hostapd_client_poll_ok(hapd, data->client_poll.addr); + break; + case EVENT_RX_FROM_UNKNOWN: + hostapd_rx_from_unknown_sta(hapd, data->rx_from_unknown.bssid, + data->rx_from_unknown.addr, + data->rx_from_unknown.wds); + break; +#endif /* NEED_AP_MLME */ + case EVENT_RX_MGMT: + if (!data->rx_mgmt.frame) + break; +#ifdef NEED_AP_MLME + if (hostapd_mgmt_rx(hapd, &data->rx_mgmt) > 0) + break; +#endif /* NEED_AP_MLME */ + hostapd_action_rx(hapd, &data->rx_mgmt); + break; +#ifdef CONFIG_FULL_HOSTAPD + case EVENT_RX_PROBE_REQ: + if (data->rx_probe_req.sa == NULL || + data->rx_probe_req.ie == NULL) + break; + hostapd_probe_req_rx(hapd, data->rx_probe_req.sa, + data->rx_probe_req.da, + data->rx_probe_req.bssid, + data->rx_probe_req.ie, + data->rx_probe_req.ie_len, + data->rx_probe_req.ssi_signal); + break; + case EVENT_NEW_STA: + hostapd_event_new_sta(hapd, data->new_sta.addr); + break; +#endif + case EVENT_EAPOL_RX: + hostapd_event_eapol_rx(hapd, data->eapol_rx.src, + data->eapol_rx.data, + data->eapol_rx.data_len); + break; + case EVENT_ASSOC: + if (!data) + return; + hostapd_notif_assoc(hapd, data->assoc_info.addr, + data->assoc_info.req_ies, + data->assoc_info.req_ies_len, + data->assoc_info.reassoc); + break; + case EVENT_DISASSOC: + if (data) + hostapd_notif_disassoc(hapd, data->disassoc_info.addr); + break; +#ifdef CONFIG_FULL_HOSTAPD + case EVENT_DEAUTH: + if (data) + hostapd_notif_disassoc(hapd, data->deauth_info.addr); + break; + case EVENT_STATION_LOW_ACK: + if (!data) + break; + hostapd_event_sta_low_ack(hapd, data->low_ack.addr); + break; + case EVENT_AUTH: + hostapd_notif_auth(hapd, &data->auth); + break; +#endif + case EVENT_CH_SWITCH: + if (!data) + break; + hostapd_event_ch_switch(hapd, data->ch_switch.freq, + data->ch_switch.ht_enabled, + data->ch_switch.ch_offset, + data->ch_switch.ch_width, + data->ch_switch.cf1, + data->ch_switch.cf2); + break; +#ifdef CONFIG_FULL_HOSTAPD + case EVENT_CONNECT_FAILED_REASON: + if (!data) + break; + hostapd_event_connect_failed_reason( + hapd, data->connect_failed_reason.addr, + data->connect_failed_reason.code); + break; + case EVENT_SURVEY: + hostapd_event_get_survey(hapd, &data->survey_results); + break; +#endif +#ifdef NEED_AP_MLME +#ifdef CONFIG_DFS + case EVENT_DFS_RADAR_DETECTED: + if (!data) + break; + hostapd_event_dfs_radar_detected(hapd, &data->dfs_event); + break; + case EVENT_DFS_CAC_FINISHED: + if (!data) + break; + hostapd_event_dfs_cac_finished(hapd, &data->dfs_event); + break; + case EVENT_DFS_CAC_ABORTED: + if (!data) + break; + hostapd_event_dfs_cac_aborted(hapd, &data->dfs_event); + break; + case EVENT_DFS_NOP_FINISHED: + if (!data) + break; + hostapd_event_dfs_nop_finished(hapd, &data->dfs_event); + break; + case EVENT_DFS_CAC_STARTED: + if (!data) + break; + hostapd_event_dfs_cac_started(hapd, &data->dfs_event); + break; +#endif +#ifdef CONFIG_FULL_HOSTAPD + case EVENT_INTERFACE_UNAVAILABLE: + hostapd_event_iface_unavailable(hapd); + break; + case EVENT_CHANNEL_LIST_CHANGED: + /* channel list changed (regulatory?), update channel list */ + /* TODO: check this. hostapd_get_hw_features() initializes + * too much stuff. */ + /* hostapd_get_hw_features(hapd->iface); */ + hostapd_channel_list_updated( + hapd->iface, data->channel_list_changed.initiator); + break; +#endif /* CONFIG_FULL_SUPPLICANT */ +#endif /* NEED_AP_MLME */ +#ifdef CONFIG_FULL_HOSTAPD + case EVENT_INTERFACE_ENABLED: + wpa_msg(hapd->msg_ctx, MSG_INFO, INTERFACE_ENABLED); + if (hapd->disabled && hapd->started) { + hapd->disabled = 0; + /* + * Try to re-enable interface if the driver stopped it + * when the interface got disabled. + */ + wpa_auth_reconfig_group_keys(hapd->wpa_auth); + hapd->reenable_beacon = 1; + ieee802_11_set_beacon(hapd); + } + break; + case EVENT_INTERFACE_DISABLED: + hostapd_free_stas(hapd); + wpa_msg(hapd->msg_ctx, MSG_INFO, INTERFACE_DISABLED); + hapd->disabled = 1; + break; +#endif +#ifdef CONFIG_ACS + case EVENT_ACS_CHANNEL_SELECTED: + hostapd_acs_channel_selected(hapd, + &data->acs_selected_channels); + break; +#endif /* CONFIG_ACS */ + default: + wpa_printf(MSG_DEBUG, "Unknown event %d", event); + break; + } +} + +#endif /* HOSTAPD */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/ap/hostapd.c b/beken_os/beken378/func/hostapd-2.5/src/ap/hostapd.c new file mode 100755 index 0000000..2df7080 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/ap/hostapd.c @@ -0,0 +1,2596 @@ +/* + * hostapd / Initialization and configuration + * Copyright (c) 2002-2014, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ +#include "utils/includes.h" +#include "utils/common.h" +#include "utils/eloop.h" +#include "common/ieee802_11_defs.h" +#include "common/wpa_ctrl.h" +#include "ap/hostapd.h" +#include "ap/sta_info.h" +#include "accounting.h" +#include "ap_list.h" +#include "beacon.h" +#include "ieee802_1x.h" +#include "ieee802_11_auth.h" +#include "vlan_init.h" +#include "wpa_auth.h" +#include "wps_hostapd.h" +#include "hw_features.h" +#include "wpa_auth_glue.h" +#include "ap_drv_ops.h" +#include "ap_config.h" +#include "p2p_hostapd.h" +#include "ap/dfs.h" +#include "ieee802_11.h" +#include "bss_load.h" +#include "errno-base.h" + +#include "include.h" +#include "uart_pub.h" + + +static int hostapd_flush_old_stations(struct hostapd_data *hapd, u16 reason); +static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd); +static int hostapd_broadcast_wep_clear(struct hostapd_data *hapd); +static int setup_interface2(struct hostapd_iface *iface); +static void channel_list_update_timeout(void *eloop_ctx, void *timeout_ctx); + + +int hostapd_for_each_interface(struct hapd_interfaces *interfaces, + int (*cb)(struct hostapd_iface *iface, + void *ctx), void *ctx) +{ + size_t i; + int ret; + + for (i = 0; i < interfaces->count; i++) { + ret = cb(interfaces->iface[i], ctx); + if (ret) + return ret; + } + + return 0; +} + + +static void hostapd_reload_bss(struct hostapd_data *hapd) +{ + struct hostapd_ssid *ssid; + +#ifndef CONFIG_NO_RADIUS + radius_client_reconfig(hapd->radius, hapd->conf->radius); +#endif /* CONFIG_NO_RADIUS */ + + ssid = &hapd->conf->ssid; + if (!ssid->wpa_psk_set && ssid->wpa_psk && !ssid->wpa_psk->next && + ssid->wpa_passphrase_set && ssid->wpa_passphrase) { + /* + * Force PSK to be derived again since SSID or passphrase may + * have changed. + */ + hostapd_config_clear_wpa_psk(&hapd->conf->ssid.wpa_psk); + } + if (hostapd_setup_wpa_psk(hapd->conf)) { + wpa_printf(MSG_ERROR, "Failed to re-configure WPA PSK " + "after reloading configuration"); + } + + if (hapd->conf->ieee802_1x || hapd->conf->wpa) + hostapd_set_drv_ieee8021x(hapd, hapd->conf->iface, 1); + else + hostapd_set_drv_ieee8021x(hapd, hapd->conf->iface, 0); + + if ((hapd->conf->wpa || hapd->conf->osen) && hapd->wpa_auth == NULL) { + hostapd_setup_wpa(hapd); + if (hapd->wpa_auth) + wpa_init_keys(hapd->wpa_auth); + } else if (hapd->conf->wpa) { + const u8 *wpa_ie; + size_t wpa_ie_len = 0; + hostapd_reconfig_wpa(hapd); + wpa_ie = wpa_auth_get_wpa_ie(hapd->wpa_auth, &wpa_ie_len); + if (hostapd_set_generic_elem(hapd, wpa_ie, wpa_ie_len)) + wpa_printf(MSG_ERROR, "Failed to configure WPA IE for " + "the kernel driver."); + } else if (hapd->wpa_auth) { + wpa_deinit(hapd->wpa_auth); + hapd->wpa_auth = NULL; + hostapd_set_privacy(hapd, 0); + hostapd_setup_encryption(hapd->conf->iface, hapd); + hostapd_set_generic_elem(hapd, (u8 *) "", 0); + } + + ieee802_11_set_beacon(hapd); + hostapd_update_wps(hapd); + + if (hapd->conf->ssid.ssid_set && + hostapd_set_ssid(hapd, hapd->conf->ssid.ssid, + hapd->conf->ssid.ssid_len)) { + wpa_printf(MSG_ERROR, "Could not set SSID for kernel driver"); + /* try to continue */ + } + wpa_printf(MSG_DEBUG, "Reconfigured interface %s", hapd->conf->iface); +} + + +static void hostapd_clear_old(struct hostapd_iface *iface) +{ + size_t j; + + /* + * Deauthenticate all stations since the new configuration may not + * allow them to use the BSS anymore. + */ + for (j = 0; j < iface->num_bss; j++) { + hostapd_flush_old_stations(iface->bss[j], + WLAN_REASON_PREV_AUTH_NOT_VALID); + hostapd_broadcast_wep_clear(iface->bss[j]); + +#ifndef CONFIG_NO_RADIUS + /* TODO: update dynamic data based on changed configuration + * items (e.g., open/close sockets, etc.) */ + radius_client_flush(iface->bss[j]->radius, 0); +#endif /* CONFIG_NO_RADIUS */ + } +} + + +int hostapd_reload_config(struct hostapd_iface *iface) +{ + struct hostapd_data *hapd = iface->bss[0]; + struct hostapd_config *newconf, *oldconf; + size_t j; + + if (iface->config_fname == NULL) { + /* Only in-memory config in use - assume it has been updated */ + hostapd_clear_old(iface); + for (j = 0; j < iface->num_bss; j++) + hostapd_reload_bss(iface->bss[j]); + return 0; + } + + if (iface->interfaces == NULL || + iface->interfaces->config_read_cb == NULL) + return -1; + newconf = iface->interfaces->config_read_cb(iface->config_fname); + if (newconf == NULL) + return -1; + + hostapd_clear_old(iface); + + oldconf = hapd->iconf; + iface->conf = newconf; + + for (j = 0; j < iface->num_bss; j++) { + hapd = iface->bss[j]; + hapd->iconf = newconf; + hapd->iconf->channel = oldconf->channel; + hapd->iconf->acs = oldconf->acs; + hapd->iconf->secondary_channel = oldconf->secondary_channel; + hapd->iconf->ieee80211n = oldconf->ieee80211n; + hapd->iconf->ieee80211ac = oldconf->ieee80211ac; + hapd->iconf->ht_capab = oldconf->ht_capab; + hapd->iconf->vht_capab = oldconf->vht_capab; + hapd->iconf->vht_oper_chwidth = oldconf->vht_oper_chwidth; + hapd->iconf->vht_oper_centr_freq_seg0_idx = + oldconf->vht_oper_centr_freq_seg0_idx; + hapd->iconf->vht_oper_centr_freq_seg1_idx = + oldconf->vht_oper_centr_freq_seg1_idx; + hapd->conf = newconf->bss[j]; + hostapd_reload_bss(hapd); + } + + hostapd_config_free(oldconf); + + + return 0; +} + + +static void hostapd_broadcast_key_clear_iface(struct hostapd_data *hapd, + char *ifname) +{ + int i; + + for (i = 0; i < NUM_WEP_KEYS; i++) { + if (hostapd_drv_set_key(ifname, hapd, WPA_ALG_NONE, NULL, i, + 0, NULL, 0, NULL, 0)) { + wpa_printf(MSG_DEBUG, "Failed to clear default " + "encryption keys (ifname=%s keyidx=%d)", + ifname, i); + } + } +#ifdef CONFIG_IEEE80211W + if (hapd->conf->ieee80211w) { + for (i = NUM_WEP_KEYS; i < NUM_WEP_KEYS + 2; i++) { + if (hostapd_drv_set_key(ifname, hapd, WPA_ALG_NONE, + NULL, i, 0, NULL, + 0, NULL, 0)) { + wpa_printf(MSG_DEBUG, "Failed to clear " + "default mgmt encryption keys " + "(ifname=%s keyidx=%d)", ifname, i); + } + } + } +#endif /* CONFIG_IEEE80211W */ +} + + +static int hostapd_broadcast_wep_clear(struct hostapd_data *hapd) +{ + hostapd_broadcast_key_clear_iface(hapd, hapd->conf->iface); + return 0; +} + + +static int hostapd_broadcast_wep_set(struct hostapd_data *hapd) +{ + int errors = 0, idx; + struct hostapd_ssid *ssid = &hapd->conf->ssid; + + idx = ssid->wep.idx; + if (ssid->wep.default_len && + hostapd_drv_set_key(hapd->conf->iface, + hapd, WPA_ALG_WEP, broadcast_ether_addr, idx, + 1, NULL, 0, ssid->wep.key[idx], + ssid->wep.len[idx])) { + wpa_printf(MSG_WARNING, "Could not set WEP encryption."); + errors++; + } + + return errors; +} + + +static void hostapd_free_hapd_data(struct hostapd_data *hapd) +{ + os_free(hapd->probereq_cb); + hapd->probereq_cb = NULL; + hapd->num_probereq_cb = 0; + +#ifdef CONFIG_P2P + wpabuf_free(hapd->p2p_beacon_ie); + hapd->p2p_beacon_ie = NULL; + wpabuf_free(hapd->p2p_probe_resp_ie); + hapd->p2p_probe_resp_ie = NULL; +#endif /* CONFIG_P2P */ + + if (!hapd->started) { + wpa_printf(MSG_ERROR, "%s: Interface %s wasn't started", + __func__, hapd->conf->iface); + return; + } + hapd->started = 0; + + wpa_printf(MSG_DEBUG, "%s(%s)", __func__, hapd->conf->iface); +#ifdef CONFIG_FULL_HOSTAPD + iapp_deinit(hapd->iapp); + hapd->iapp = NULL; + accounting_deinit(hapd); +#endif + hostapd_deinit_wpa(hapd); +#ifdef CONFIG_FULL_HOSTAPD + vlan_deinit(hapd); + hostapd_acl_deinit(hapd); +#endif +#ifndef CONFIG_NO_RADIUS + radius_client_deinit(hapd->radius); + hapd->radius = NULL; + radius_das_deinit(hapd->radius_das); + hapd->radius_das = NULL; +#endif /* CONFIG_NO_RADIUS */ + + hostapd_deinit_wps(hapd); + + if (hapd->interface_added) { + hapd->interface_added = 0; + if (hostapd_if_remove(hapd, WPA_IF_AP_BSS, hapd->conf->iface)) { + wpa_printf(MSG_WARNING, + "Failed to remove BSS interface %s", + hapd->conf->iface); + hapd->interface_added = 1; + } else { + /* + * Since this was a dynamically added interface, the + * driver wrapper may have removed its internal instance + * and hapd->drv_priv is not valid anymore. + */ + hapd->drv_priv = NULL; + } + } + + wpabuf_free(hapd->time_adv); + +#ifdef CONFIG_INTERWORKING + gas_serv_deinit(hapd); +#endif /* CONFIG_INTERWORKING */ + +#ifdef CONFIG_FULL_HOSTAPD + bss_load_update_deinit(hapd); + ndisc_snoop_deinit(hapd); + dhcp_snoop_deinit(hapd); + x_snoop_deinit(hapd); +#endif +#ifdef CONFIG_SQLITE + bin_clear_free(hapd->tmp_eap_user.identity, + hapd->tmp_eap_user.identity_len); + bin_clear_free(hapd->tmp_eap_user.password, + hapd->tmp_eap_user.password_len); +#endif /* CONFIG_SQLITE */ + +#ifdef CONFIG_MESH + wpabuf_free(hapd->mesh_pending_auth); + hapd->mesh_pending_auth = NULL; +#endif /* CONFIG_MESH */ +} + + +/** + * hostapd_cleanup - Per-BSS cleanup (deinitialization) + * @hapd: Pointer to BSS data + * + * This function is used to free all per-BSS data structures and resources. + * Most of the modules that are initialized in hostapd_setup_bss() are + * deinitialized here. + */ +static void hostapd_cleanup(struct hostapd_data *hapd) +{ + wpa_printf(MSG_DEBUG, "%s(hapd=%p (%s))", __func__, hapd, + hapd->conf->iface); + if (hapd->iface->interfaces && + hapd->iface->interfaces->ctrl_iface_deinit) + hapd->iface->interfaces->ctrl_iface_deinit(hapd); + hostapd_free_hapd_data(hapd); +} + + +static void sta_track_deinit(struct hostapd_iface *iface) +{ + struct hostapd_sta_info *info; + + if (!iface->num_sta_seen) + return; + + while (0 != (info = dl_list_first(&iface->sta_seen, struct hostapd_sta_info, + list))) { + dl_list_del(&info->list); + iface->num_sta_seen--; + os_free(info); + } +} + + +static void hostapd_cleanup_iface_partial(struct hostapd_iface *iface) +{ + wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface); +#ifdef CONFIG_IEEE80211N +#ifdef NEED_AP_MLME + hostapd_stop_setup_timers(iface); +#endif /* NEED_AP_MLME */ +#endif /* CONFIG_IEEE80211N */ + + hostapd_free_hw_features(iface->hw_features, iface->num_hw_features); + iface->hw_features = NULL; + + os_free(iface->current_rates); + iface->current_rates = NULL; + + os_free(iface->basic_rates); + iface->basic_rates = NULL; + + ap_list_deinit(iface); + sta_track_deinit(iface); +} + + +/** + * hostapd_cleanup_iface - Complete per-interface cleanup + * @iface: Pointer to interface data + * + * This function is called after per-BSS data structures are deinitialized + * with hostapd_cleanup(). + */ +static void hostapd_cleanup_iface(struct hostapd_iface *iface) +{ + wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface); + eloop_cancel_timeout(channel_list_update_timeout, iface, NULL); + + hostapd_cleanup_iface_partial(iface); + hostapd_config_free(iface->conf); + iface->conf = NULL; + + os_free(iface->config_fname); + os_free(iface->bss); + wpa_printf(MSG_DEBUG, "%s: free iface=%p", __func__, iface); + os_free(iface); +} + + +static void hostapd_clear_wep(struct hostapd_data *hapd) +{ + if (hapd->drv_priv && !hapd->iface->driver_ap_teardown) { + hostapd_set_privacy(hapd, 0); + hostapd_broadcast_wep_clear(hapd); + } +} + + +static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd) +{ + int i; + + hostapd_broadcast_wep_set(hapd); + + if (hapd->conf->ssid.wep.default_len) { + hostapd_set_privacy(hapd, 1); + return 0; + } + + /* + * When IEEE 802.1X is not enabled, the driver may need to know how to + * set authentication algorithms for static WEP. + */ + hostapd_drv_set_authmode(hapd, hapd->conf->auth_algs); + + for (i = 0; i < 4; i++) { + if (hapd->conf->ssid.wep.key[i] && + hostapd_drv_set_key(iface, hapd, WPA_ALG_WEP, NULL, i, + i == hapd->conf->ssid.wep.idx, NULL, 0, + hapd->conf->ssid.wep.key[i], + hapd->conf->ssid.wep.len[i])) { + wpa_printf(MSG_WARNING, "Could not set WEP " + "encryption."); + return -1; + } + if (hapd->conf->ssid.wep.key[i] && + i == hapd->conf->ssid.wep.idx) + hostapd_set_privacy(hapd, 1); + } + + return 0; +} + + +static int hostapd_flush_old_stations(struct hostapd_data *hapd, u16 reason) +{ + int ret = 0; + u8 addr[ETH_ALEN]; + + if (hostapd_drv_none(hapd) || hapd->drv_priv == NULL) + return 0; + + if (!hapd->iface->driver_ap_teardown) { + wpa_dbg(hapd->msg_ctx, MSG_DEBUG, + "Flushing old station entries"); + + if (hostapd_flush(hapd)) { + wpa_msg(hapd->msg_ctx, MSG_WARNING, + "Could not connect to kernel driver"); + ret = -1; + } + } + wpa_dbg(hapd->msg_ctx, MSG_DEBUG, "Deauthenticate all stations"); + os_memset(addr, 0xff, ETH_ALEN); + hostapd_drv_sta_deauth(hapd, addr, reason); + hostapd_free_stas(hapd); + + return ret; +} + + +static void hostapd_bss_deinit_no_free(struct hostapd_data *hapd) +{ + hostapd_free_stas(hapd); + hostapd_flush_old_stations(hapd, WLAN_REASON_DEAUTH_LEAVING); + hostapd_clear_wep(hapd); +} + + +/** + * hostapd_validate_bssid_configuration - Validate BSSID configuration + * @iface: Pointer to interface data + * Returns: 0 on success, -1 on failure + * + * This function is used to validate that the configured BSSIDs are valid. + */ +static int hostapd_validate_bssid_configuration(struct hostapd_iface *iface) +{ + u8 mask[ETH_ALEN] = { 0 }; + struct hostapd_data *hapd = iface->bss[0]; + unsigned int i = iface->conf->num_bss, bits = 0, j; + int auto_addr = 0; + + if (hostapd_drv_none(hapd)) + return 0; + + /* Generate BSSID mask that is large enough to cover the BSSIDs. */ + + /* Determine the bits necessary to cover the number of BSSIDs. */ + for (i--; i; i >>= 1) + bits++; + + /* Determine the bits necessary to any configured BSSIDs, + if they are higher than the number of BSSIDs. */ + for (j = 0; j < iface->conf->num_bss; j++) { + if (hostapd_mac_comp_empty(iface->conf->bss[j]->bssid) == 0) { + if (j) + auto_addr++; + continue; + } + + for (i = 0; i < ETH_ALEN; i++) { + mask[i] |= + iface->conf->bss[j]->bssid[i] ^ + hapd->own_addr[i]; + } + } + + if (!auto_addr) + goto skip_mask_ext; + + for (i = 0; i < ETH_ALEN && mask[i] == 0; i++) + ; + j = 0; + if (i < ETH_ALEN) { + j = (5 - i) * 8; + + while (mask[i] != 0) { + mask[i] >>= 1; + j++; + } + } + + if (bits < j) + bits = j; + + if (bits > 40) { + wpa_printf(MSG_ERROR, "Too many bits in the BSSID mask (%u)", + bits); + return -1; + } + + os_memset(mask, 0xff, ETH_ALEN); + j = bits / 8; + for (i = 5; i > 5 - j; i--) + mask[i] = 0; + j = bits % 8; + while (j--) + mask[i] <<= 1; + +skip_mask_ext: + wpa_printf(MSG_DEBUG, "BSS count %lu, BSSID mask " MACSTR " (%d bits)", + (unsigned long) iface->conf->num_bss, MAC2STR(mask), bits); + + if (!auto_addr) + return 0; + + for (i = 0; i < ETH_ALEN; i++) { + if ((hapd->own_addr[i] & mask[i]) != hapd->own_addr[i]) { + wpa_printf(MSG_ERROR, "Invalid BSSID mask " MACSTR + " for start address " MACSTR ".", + MAC2STR(mask), MAC2STR(hapd->own_addr)); + wpa_printf(MSG_ERROR, "Start address must be the " + "first address in the block (i.e., addr " + "AND mask == addr)."); + return -1; + } + } + + return 0; +} + + +static int mac_in_conf(struct hostapd_config *conf, const void *a) +{ + size_t i; + + for (i = 0; i < conf->num_bss; i++) { + if (hostapd_mac_comp(conf->bss[i]->bssid, a) == 0) { + return 1; + } + } + + return 0; +} + + +/** + * hostapd_setup_bss - Per-BSS setup (initialization) + * @hapd: Pointer to BSS data + * @first: Whether this BSS is the first BSS of an interface; -1 = not first, + * but interface may exist + * + * This function is used to initialize all per-BSS data structures and + * resources. This gets called in a loop for each BSS when an interface is + * initialized. Most of the modules that are initialized here will be + * deinitialized in hostapd_cleanup(). + */ +static int hostapd_setup_bss(struct hostapd_data *hapd, int first) +{ + struct hostapd_bss_config *conf = hapd->conf; + u8 ssid[SSID_MAX_LEN + 1]; + int ssid_len, set_ssid; + char force_ifname[IFNAMSIZ]; + u8 if_addr[ETH_ALEN]; + int flush_old_stations = 1; + + wpa_printf(MSG_DEBUG, "%s(hapd=%p (%s), first=%d)", + __func__, hapd, conf->iface, first); + +#ifdef EAP_SERVER_TNC + if (conf->tnc && tncs_global_init() < 0) { + wpa_printf(MSG_ERROR, "Failed to initialize TNCS"); + return -1; + } +#endif /* EAP_SERVER_TNC */ + + if (hapd->started) { + wpa_printf(MSG_ERROR, "%s: Interface %s was already started", + __func__, conf->iface); + return -1; + } + hapd->started = 1; + + if (!first || first == -1) { + if (hostapd_mac_comp_empty(conf->bssid) == 0) { + /* Allocate the next available BSSID. */ + do { + inc_byte_array(hapd->own_addr, ETH_ALEN); + } while (mac_in_conf(hapd->iconf, hapd->own_addr)); + } else { + /* Allocate the configured BSSID. */ + os_memcpy(hapd->own_addr, conf->bssid, ETH_ALEN); + + if (hostapd_mac_comp(hapd->own_addr, + hapd->iface->bss[0]->own_addr) == + 0) { + wpa_printf(MSG_ERROR, "BSS '%s' may not have " + "BSSID set to the MAC address of " + "the radio", conf->iface); + return -1; + } + } + + hapd->interface_added = 1; + if (hostapd_if_add(hapd->iface->bss[0], WPA_IF_AP_BSS, + conf->iface, hapd->own_addr, hapd, + &hapd->drv_priv, force_ifname, if_addr, +#ifdef CONFIG_FULL_HOSTAPD + conf->bridge[0] ? conf->bridge : NULL, +#else + NULL, +#endif + first == -1)) { + wpa_printf(MSG_ERROR, "Failed to add BSS (BSSID=" + MACSTR ")", MAC2STR(hapd->own_addr)); + hapd->interface_added = 0; + return -1; + } + } + + if (conf->wmm_enabled < 0) + conf->wmm_enabled = hapd->iconf->ieee80211n; + +#ifdef CONFIG_MESH + if (hapd->iface->mconf == NULL) + flush_old_stations = 0; +#endif /* CONFIG_MESH */ + + if (flush_old_stations) + hostapd_flush_old_stations(hapd, + WLAN_REASON_PREV_AUTH_NOT_VALID); + hostapd_set_privacy(hapd, 0); + + hostapd_broadcast_wep_clear(hapd); + if (hostapd_setup_encryption(conf->iface, hapd)) + return -1; + + /* + * Fetch the SSID from the system and use it or, + * if one was specified in the config file, verify they + * match. + */ + ssid_len = hostapd_get_ssid(hapd, ssid, sizeof(ssid)); + if (ssid_len < 0) { + wpa_printf(MSG_ERROR, "Could not read SSID from system"); + return -1; + } + if (conf->ssid.ssid_set) { + /* + * If SSID is specified in the config file and it differs + * from what is being used then force installation of the + * new SSID. + */ + set_ssid = (conf->ssid.ssid_len != (size_t) ssid_len || + os_memcmp(conf->ssid.ssid, ssid, ssid_len) != 0); + } else { + /* + * No SSID in the config file; just use the one we got + * from the system. + */ + set_ssid = 0; + conf->ssid.ssid_len = ssid_len; + os_memcpy(conf->ssid.ssid, ssid, conf->ssid.ssid_len); + } + + if (!hostapd_drv_none(hapd)) { + wpa_printf(MSG_ERROR, "Using interface %s with hwaddr " MACSTR + " and ssid \"%s\"", + conf->iface, MAC2STR(hapd->own_addr), + wpa_ssid_txt(conf->ssid.ssid, conf->ssid.ssid_len)); + } + + if (hostapd_setup_wpa_psk(conf)) { + wpa_printf(MSG_ERROR, "WPA-PSK setup failed."); + return -1; + } + + /* Set SSID for the kernel driver (to be used in beacon and probe + * response frames) */ + if (set_ssid && hostapd_set_ssid(hapd, conf->ssid.ssid, + conf->ssid.ssid_len)) { + wpa_printf(MSG_ERROR, "Could not set SSID for kernel driver"); + return -1; + } + +#ifndef CONFIG_NO_RADIUS + hapd->radius = radius_client_init(hapd, conf->radius); + if (hapd->radius == NULL) { + wpa_printf(MSG_ERROR, "RADIUS client initialization failed."); + return -1; + } + + if (conf->radius_das_port) { + struct radius_das_conf das_conf; + os_memset(&das_conf, 0, sizeof(das_conf)); + das_conf.port = conf->radius_das_port; + das_conf.shared_secret = conf->radius_das_shared_secret; + das_conf.shared_secret_len = + conf->radius_das_shared_secret_len; + das_conf.client_addr = &conf->radius_das_client_addr; + das_conf.time_window = conf->radius_das_time_window; + das_conf.require_event_timestamp = + conf->radius_das_require_event_timestamp; + das_conf.ctx = hapd; + das_conf.disconnect = hostapd_das_disconnect; + hapd->radius_das = radius_das_init(&das_conf); + if (hapd->radius_das == NULL) { + wpa_printf(MSG_ERROR, "RADIUS DAS initialization " + "failed."); + return -1; + } + } +#endif /* CONFIG_NO_RADIUS */ + + if (hostapd_acl_init(hapd)) { + wpa_printf(MSG_ERROR, "ACL initialization failed."); + return -1; + } + if (hostapd_init_wps(hapd, conf)) + return -1; + +#ifdef CONFIG_FULL_HOSTAPD + if (authsrv_init(hapd) < 0) + return -1; + + if (ieee802_1x_init(hapd)) { + wpa_printf(MSG_ERROR, "IEEE 802.1X initialization failed."); + return -1; + } +#endif + + if ((conf->wpa || conf->osen) && hostapd_setup_wpa(hapd)) + return -1; + + if (accounting_init(hapd)) { + wpa_printf(MSG_ERROR, "Accounting initialization failed."); + return -1; + } + +#ifdef CONFIG_FULL_HOSTAPD + if (conf->ieee802_11f && + (hapd->iapp = iapp_init(hapd, conf->iapp_iface)) == NULL) { + wpa_printf(MSG_ERROR, "IEEE 802.11F (IAPP) initialization " + "failed."); + return -1; + } +#endif +#ifdef CONFIG_INTERWORKING + if (gas_serv_init(hapd)) { + wpa_printf(MSG_ERROR, "GAS server initialization failed"); + return -1; + } + + if (conf->qos_map_set_len && + hostapd_drv_set_qos_map(hapd, conf->qos_map_set, + conf->qos_map_set_len)) { + wpa_printf(MSG_ERROR, "Failed to initialize QoS Map"); + return -1; + } +#endif /* CONFIG_INTERWORKING */ + +#ifdef CONFIG_FULL_HOSTAPD + if (conf->bss_load_update_period && bss_load_update_init(hapd)) { + wpa_printf(MSG_ERROR, "BSS Load initialization failed"); + return -1; + } + + if (conf->proxy_arp) { + if (x_snoop_init(hapd)) { + wpa_printf(MSG_ERROR, + "Generic snooping infrastructure initialization failed"); + return -1; + } + + if (dhcp_snoop_init(hapd)) { + wpa_printf(MSG_ERROR, + "DHCP snooping initialization failed"); + return -1; + } + + if (ndisc_snoop_init(hapd)) { + wpa_printf(MSG_ERROR, + "Neighbor Discovery snooping initialization failed"); + return -1; + } + } + + if (!hostapd_drv_none(hapd) && vlan_init(hapd)) { + wpa_printf(MSG_ERROR, "VLAN initialization failed."); + return -1; + } +#endif + + if (!conf->start_disabled && ieee802_11_set_beacon(hapd) < 0) + return -1; + + if (hapd->wpa_auth && wpa_init_keys(hapd->wpa_auth) < 0) + return -1; + + if (hapd->driver && hapd->driver->set_operstate) + hapd->driver->set_operstate(hapd->drv_priv, 1); + + return 0; +} + + +static void hostapd_tx_queue_params(struct hostapd_iface *iface) +{ + struct hostapd_data *hapd = iface->bss[0]; + int i; + struct hostapd_tx_queue_params *p; + +#ifdef CONFIG_MESH + if (iface->mconf == NULL) + return; +#endif /* CONFIG_MESH */ + + for (i = 0; i < NUM_TX_QUEUES; i++) { + p = &iface->conf->tx_queue[i]; + + if (hostapd_set_tx_queue_params(hapd, i, p->aifs, p->cwmin, + p->cwmax, p->burst)) { + wpa_printf(MSG_DEBUG, "Failed to set TX queue " + "parameters for queue %d.", i); + /* Continue anyway */ + } + } +} + +#ifdef CONFIG_FULL_HOSTAPD + +static int hostapd_set_acl_list(struct hostapd_data *hapd, + struct mac_acl_entry *mac_acl, + int n_entries, u8 accept_acl) +{ + struct hostapd_acl_params *acl_params; + int i, err; + + acl_params = os_zalloc(sizeof(*acl_params) + + (n_entries * sizeof(acl_params->mac_acl[0]))); + if (!acl_params) + return -ERRNOMEM; + + for (i = 0; i < n_entries; i++) + os_memcpy(acl_params->mac_acl[i].addr, mac_acl[i].addr, + ETH_ALEN); + + acl_params->acl_policy = accept_acl; + acl_params->num_mac_acl = n_entries; + + err = hostapd_drv_set_acl(hapd, acl_params); + + os_free(acl_params); + + return err; +} + + +static void hostapd_set_acl(struct hostapd_data *hapd) +{ + struct hostapd_config *conf = hapd->iconf; + int err; + u8 accept_acl; + + if (hapd->iface->drv_max_acl_mac_addrs == 0) + return; + + if (conf->bss[0]->macaddr_acl == DENY_UNLESS_ACCEPTED) { + accept_acl = 1; + err = hostapd_set_acl_list(hapd, conf->bss[0]->accept_mac, + conf->bss[0]->num_accept_mac, + accept_acl); + if (err) { + wpa_printf(MSG_DEBUG, "Failed to set accept acl"); + return; + } + } else if (conf->bss[0]->macaddr_acl == ACCEPT_UNLESS_DENIED) { + accept_acl = 0; + err = hostapd_set_acl_list(hapd, conf->bss[0]->deny_mac, + conf->bss[0]->num_deny_mac, + accept_acl); + if (err) { + wpa_printf(MSG_DEBUG, "Failed to set deny acl"); + return; + } + } +} +#endif + +static int start_ctrl_iface_bss(struct hostapd_data *hapd) +{ + if (!hapd->iface->interfaces || + !hapd->iface->interfaces->ctrl_iface_init) + return 0; + + if (hapd->iface->interfaces->ctrl_iface_init(hapd)) { + wpa_printf(MSG_ERROR, + "Failed to setup control interface for %s", + hapd->conf->iface); + return -1; + } + + return 0; +} + + +static int start_ctrl_iface(struct hostapd_iface *iface) +{ + size_t i; + + if (!iface->interfaces || !iface->interfaces->ctrl_iface_init) + return 0; + + for (i = 0; i < iface->num_bss; i++) { + struct hostapd_data *hapd = iface->bss[i]; + if (iface->interfaces->ctrl_iface_init(hapd)) { + wpa_printf(MSG_ERROR, + "Failed to setup control interface for %s", + hapd->conf->iface); + return -1; + } + } + + return 0; +} + + +static void channel_list_update_timeout(void *eloop_ctx, void *timeout_ctx) +{ + struct hostapd_iface *iface = eloop_ctx; + + if (!iface->wait_channel_update) { + wpa_printf(MSG_INFO, "Channel list update timeout, but interface was not waiting for it"); + return; + } + + /* + * It is possible that the existing channel list is acceptable, so try + * to proceed. + */ + wpa_printf(MSG_DEBUG, "Channel list update timeout - try to continue anyway"); + setup_interface2(iface); +} + + +void hostapd_channel_list_updated(struct hostapd_iface *iface, int initiator) +{ + if (!iface->wait_channel_update || initiator != REGDOM_SET_BY_USER) + return; + + wpa_printf(MSG_DEBUG, "Channel list updated - continue setup"); + eloop_cancel_timeout(channel_list_update_timeout, iface, NULL); + setup_interface2(iface); +} + + +static int setup_interface(struct hostapd_iface *iface) +{ + struct hostapd_data *hapd = iface->bss[0]; + size_t i; + + /* + * It is possible that setup_interface() is called after the interface + * was disabled etc., in which case driver_ap_teardown is possibly set + * to 1. Clear it here so any other key/station deletion, which is not + * part of a teardown flow, would also call the relevant driver + * callbacks. + */ + iface->driver_ap_teardown = 0; + + if (!iface->phy[0]) { + const char *phy = hostapd_drv_get_radio_name(hapd); + if (phy) { + wpa_printf(MSG_DEBUG, "phy: %s", phy); + os_strlcpy(iface->phy, phy, sizeof(iface->phy)); + } + } + + if (iface->num_bss != iface->conf->num_bss) { + os_printf("%s num_bss=%d vs %d\n", __FUNCTION__, iface->num_bss, iface->conf->num_bss); + return -1; + } + + /* + * Make sure that all BSSes get configured with a pointer to the same + * driver interface. + */ + for (i = 1; i < iface->num_bss; i++) { + iface->bss[i]->driver = hapd->driver; + iface->bss[i]->drv_priv = hapd->drv_priv; + } + + if (hostapd_validate_bssid_configuration(iface)) + return -1; + + /* + * Initialize control interfaces early to allow external monitoring of + * channel setup operations that may take considerable amount of time + * especially for DFS cases. + */ + if (start_ctrl_iface(iface)) + return -1; + + if (hapd->iconf->country[0] && hapd->iconf->country[1]) { + char country[4], previous_country[4]; + + hostapd_set_state(iface, HAPD_IFACE_COUNTRY_UPDATE); + if (hostapd_get_country(hapd, previous_country) < 0) + previous_country[0] = '\0'; + + os_memcpy(country, hapd->iconf->country, 3); + country[3] = '\0'; + if (hostapd_set_country(hapd, country) < 0) { + wpa_printf(MSG_ERROR, "Failed to set country code"); + return -1; + } + + wpa_printf(MSG_DEBUG, "Previous country code %s, new country code %s", + previous_country, country); + + if (os_strncmp(previous_country, country, 2) != 0) { + wpa_printf(MSG_DEBUG, "Continue interface setup after channel list update"); + iface->wait_channel_update = 1; + eloop_register_timeout(5, 0, + channel_list_update_timeout, + iface, NULL); + return 0; + } + } + + return setup_interface2(iface); +} + + +static int setup_interface2(struct hostapd_iface *iface) +{ + iface->wait_channel_update = 0; + + if (hostapd_get_hw_features(iface)) { + /* Not all drivers support this yet, so continue without hw + * feature data. */ + } else { + int ret = hostapd_select_hw_mode(iface); + if (ret < 0) { + wpa_printf(MSG_ERROR, "Could not select hw_mode and " + "channel. (%d)", ret); + goto fail; + } + if (ret == 1) { + wpa_printf(MSG_DEBUG, "Interface initialization will be completed in a callback (ACS)"); + return 0; + } + ret = hostapd_check_ht_capab(iface); + if (ret < 0) + goto fail; + if (ret == 1) { + wpa_printf(MSG_DEBUG, "Interface initialization will " + "be completed in a callback"); + return 0; + } + + if (iface->conf->ieee80211h) + wpa_printf(MSG_DEBUG, "DFS support is enabled"); + } + return hostapd_setup_interface_complete(iface, 0); + +fail: + hostapd_set_state(iface, HAPD_IFACE_DISABLED); + wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, AP_EVENT_DISABLED); + if (iface->interfaces && iface->interfaces->terminate_on_error) + eloop_terminate(); + return -1; +} + + +/** + * hostapd_setup_interface_complete - Complete interface setup + * + * This function is called when previous steps in the interface setup has been + * completed. This can also start operations, e.g., DFS, that will require + * additional processing before interface is ready to be enabled. Such + * operations will call this function from eloop callbacks when finished. + */ +int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err) +{ + struct hostapd_data *hapd = iface->bss[0]; + size_t j; + u8 *prev_addr; + int delay_apply_cfg = 0; + int res_dfs_offload = 0; + + if (err) + goto fail; + + wpa_printf(MSG_DEBUG, "Completing interface initialization"); + if (iface->conf->channel) { +#ifdef NEED_AP_MLME + int res; + (void)res; +#endif /* NEED_AP_MLME */ + + iface->freq = hostapd_hw_get_freq(hapd, iface->conf->channel); + wpa_printf(MSG_DEBUG, "Mode: %s Channel: %d " + "Frequency: %d MHz", + hostapd_hw_mode_txt(iface->conf->hw_mode), + iface->conf->channel, iface->freq); + +#ifdef NEED_AP_MLME + /* Handle DFS only if it is not offloaded to the driver */ + #if 1 // wangzhilei0 + iface->drv_flags |= WPA_DRIVER_FLAGS_DFS_OFFLOAD; + #endif +#ifdef CONFIG_DFS + if (!(iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD)) { + /* Check DFS */ + res = hostapd_handle_dfs(iface); + if (res <= 0) { + if (res < 0) + goto fail; + return res; + } + } else { + /* If DFS is offloaded to the driver */ + res_dfs_offload = hostapd_handle_dfs_offload(iface); + if (res_dfs_offload <= 0) { + if (res_dfs_offload < 0) + goto fail; + } else { + wpa_printf(MSG_DEBUG, + "Proceed with AP/channel setup"); + /* + * If this is a DFS channel, move to completing + * AP setup. + */ + if (res_dfs_offload == 1) + goto dfs_offload; + /* Otherwise fall through. */ + } + } +#endif +#endif /* NEED_AP_MLME */ + +#ifdef CONFIG_MESH + if (iface->mconf != NULL) { + wpa_printf(MSG_DEBUG, + "%s: Mesh configuration will be applied while joining the mesh network", + iface->bss[0]->conf->iface); + delay_apply_cfg = 1; + } +#endif /* CONFIG_MESH */ + + if (!delay_apply_cfg && + hostapd_set_freq(hapd, hapd->iconf->hw_mode, iface->freq, + hapd->iconf->channel, + hapd->iconf->ieee80211n, + hapd->iconf->ieee80211ac, + hapd->iconf->secondary_channel, + hapd->iconf->vht_oper_chwidth, + hapd->iconf->vht_oper_centr_freq_seg0_idx, + hapd->iconf->vht_oper_centr_freq_seg1_idx)) { + wpa_printf(MSG_ERROR, "Could not set channel for " + "kernel driver"); + goto fail; + } + } + + if (iface->current_mode) { + if (hostapd_prepare_rates(iface, iface->current_mode)) { + wpa_printf(MSG_ERROR, "Failed to prepare rates " + "table."); + goto fail; + } + } + + if (hapd->iconf->rts_threshold > -1 && + hostapd_set_rts(hapd, hapd->iconf->rts_threshold)) { + wpa_printf(MSG_ERROR, "Could not set RTS threshold for " + "kernel driver"); + goto fail; + } + + if (hapd->iconf->fragm_threshold > -1 && + hostapd_set_frag(hapd, hapd->iconf->fragm_threshold)) { + wpa_printf(MSG_ERROR, "Could not set fragmentation threshold " + "for kernel driver"); + goto fail; + } + + prev_addr = hapd->own_addr; + + for (j = 0; j < iface->num_bss; j++) { + hapd = iface->bss[j]; + if (j) + os_memcpy(hapd->own_addr, prev_addr, ETH_ALEN); + if (hostapd_setup_bss(hapd, j == 0)) { + do { + hapd = iface->bss[j]; + hostapd_bss_deinit_no_free(hapd); + hostapd_free_hapd_data(hapd); + } while (j-- > 0); + goto fail; + } + if (hostapd_mac_comp_empty(hapd->conf->bssid) == 0) + prev_addr = hapd->own_addr; + } + hapd = iface->bss[0]; + + hostapd_tx_queue_params(iface); + + ap_list_init(iface); + dl_list_init(&iface->sta_seen); + +#ifdef CONFIG_FULL_HOSTAPD + hostapd_set_acl(hapd); +#endif + if (hostapd_driver_commit(hapd) < 0) { + wpa_printf(MSG_ERROR, "%s: Failed to commit driver " + "configuration", __func__); + goto fail; + } + + /* + * WPS UPnP module can be initialized only when the "upnp_iface" is up. + * If "interface" and "upnp_iface" are the same (e.g., non-bridge + * mode), the interface is up only after driver_commit, so initialize + * WPS after driver_commit. + */ + for (j = 0; j < iface->num_bss; j++) { + if (hostapd_init_wps_complete(iface->bss[j])) + goto fail; + } + + if ((iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) && + !res_dfs_offload) { + /* + * If freq is DFS, and DFS is offloaded to the driver, then wait + * for CAC to complete. + */ + wpa_printf(MSG_DEBUG, "%s: Wait for CAC to complete", __func__); + return res_dfs_offload; + } + +#ifdef NEED_AP_MLME +#ifdef CONFIG_DFS +dfs_offload: +#endif +#endif /* NEED_AP_MLME */ + +#ifdef CONFIG_FST + if (hapd->iconf->fst_cfg.group_id[0]) { + struct fst_wpa_obj iface_obj; + + fst_hostapd_fill_iface_obj(hapd, &iface_obj); + iface->fst = fst_attach(hapd->conf->iface, hapd->own_addr, + &iface_obj, &hapd->iconf->fst_cfg); + if (!iface->fst) { + wpa_printf(MSG_ERROR, "Could not attach to FST %s", + hapd->iconf->fst_cfg.group_id); + goto fail; + } + } +#endif /* CONFIG_FST */ + + hostapd_set_state(iface, HAPD_IFACE_ENABLED); + wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, AP_EVENT_ENABLED); + if (hapd->setup_complete_cb) + hapd->setup_complete_cb(hapd->setup_complete_cb_ctx); + + wpa_printf(MSG_DEBUG, "Setup of interface done."); + if (iface->interfaces && iface->interfaces->terminate_on_error > 0) + iface->interfaces->terminate_on_error--; + + return 0; + +fail: + wpa_printf(MSG_ERROR, "Interface initialization failed"); + hostapd_set_state(iface, HAPD_IFACE_DISABLED); + wpa_msg(hapd->msg_ctx, MSG_INFO, AP_EVENT_DISABLED); +#ifdef CONFIG_FST + if (iface->fst) { + fst_detach(iface->fst); + iface->fst = NULL; + } +#endif /* CONFIG_FST */ + if (iface->interfaces && iface->interfaces->terminate_on_error) + eloop_terminate(); + return -1; +} + + +/** + * hostapd_setup_interface - Setup of an interface + * @iface: Pointer to interface data. + * Returns: 0 on success, -1 on failure + * + * Initializes the driver interface, validates the configuration, + * and sets driver parameters based on the configuration. + * Flushes old stations, sets the channel, encryption, + * beacons, and WDS links based on the configuration. + * + * If interface setup requires more time, e.g., to perform HT co-ex scans, ACS, + * or DFS operations, this function returns 0 before such operations have been + * completed. The pending operations are registered into eloop and will be + * completed from eloop callbacks. Those callbacks end up calling + * hostapd_setup_interface_complete() once setup has been completed. + */ +int hostapd_setup_interface(struct hostapd_iface *iface) +{ + int ret; + + ret = setup_interface(iface); + if (ret) { + wpa_printf(MSG_ERROR, "%s: Unable to setup interface.", + iface->bss[0]->conf->iface); + return -1; + } + + return 0; +} + +/** + * hostapd_alloc_bss_data - Allocate and initialize per-BSS data + * @hapd_iface: Pointer to interface data + * @conf: Pointer to per-interface configuration + * @bss: Pointer to per-BSS configuration for this BSS + * Returns: Pointer to allocated BSS data + * + * This function is used to allocate per-BSS data structure. This data will be + * freed after hostapd_cleanup() is called for it during interface + * deinitialization. + */ +struct hostapd_data * +hostapd_alloc_bss_data(struct hostapd_iface *hapd_iface, + struct hostapd_config *conf, + struct hostapd_bss_config *bss) +{ + struct hostapd_data *hapd; + + hapd = os_zalloc(sizeof(*hapd)); + if (hapd == NULL) + return NULL; + + hapd->new_assoc_sta_cb = hostapd_new_assoc_sta; + hapd->iconf = conf; + hapd->conf = bss; + hapd->iface = hapd_iface; + hapd->driver = hapd->iconf->driver; + + return hapd; +} + + +static void hostapd_bss_deinit(struct hostapd_data *hapd) +{ + wpa_printf(MSG_DEBUG, "%s: deinit bss %s", __func__, + hapd->conf->iface); + hostapd_bss_deinit_no_free(hapd); + wpa_msg(hapd->msg_ctx, MSG_INFO, AP_EVENT_DISABLED); + hostapd_cleanup(hapd); +} + + +void hostapd_interface_deinit(struct hostapd_iface *iface) +{ + int j; + + wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface); + if (iface == NULL) + return; + + hostapd_set_state(iface, HAPD_IFACE_DISABLED); + +#ifdef CONFIG_IEEE80211N +#ifdef NEED_AP_MLME + hostapd_stop_setup_timers(iface); + eloop_cancel_timeout(ap_ht2040_timeout, iface, NULL); +#endif /* NEED_AP_MLME */ +#endif /* CONFIG_IEEE80211N */ + eloop_cancel_timeout(channel_list_update_timeout, iface, NULL); + iface->wait_channel_update = 0; + +#ifdef CONFIG_FST + if (iface->fst) { + fst_detach(iface->fst); + iface->fst = NULL; + } +#endif /* CONFIG_FST */ + + for (j = iface->num_bss - 1; j >= 0; j--) + hostapd_bss_deinit(iface->bss[j]); +} + + +void hostapd_interface_free(struct hostapd_iface *iface) +{ + size_t j; + wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface); + for (j = 0; j < iface->num_bss; j++) { + wpa_printf(MSG_DEBUG, "%s: free hapd %p", + __func__, iface->bss[j]); + os_free(iface->bss[j]); + } + hostapd_cleanup_iface(iface); +} + + +/** + * hostapd_init - Allocate and initialize per-interface data + * @config_file: Path to the configuration file + * Returns: Pointer to the allocated interface data or %NULL on failure + * + * This function is used to allocate main data structures for per-interface + * data. The allocated data buffer will be freed by calling + * hostapd_cleanup_iface(). + */ +struct hostapd_iface * hostapd_init(struct hapd_interfaces *interfaces, + const char *config_file) +{ + struct hostapd_iface *hapd_iface = NULL; + struct hostapd_config *conf = NULL; + struct hostapd_data *hapd; + size_t i; + + hapd_iface = os_zalloc(sizeof(*hapd_iface)); + if (hapd_iface == NULL) + goto fail; + + hapd_iface->config_fname = os_strdup(config_file); + if (hapd_iface->config_fname == NULL) + goto fail; + + conf = interfaces->config_read_cb(hapd_iface->config_fname); + if (conf == NULL) + goto fail; + hapd_iface->conf = conf; + + hapd_iface->num_bss = conf->num_bss; + hapd_iface->bss = os_calloc(conf->num_bss, + sizeof(struct hostapd_data *)); + if (hapd_iface->bss == NULL) + goto fail; + + for (i = 0; i < conf->num_bss; i++) { + hapd = hapd_iface->bss[i] = + hostapd_alloc_bss_data(hapd_iface, conf, + conf->bss[i]); + if (hapd == NULL) + goto fail; + hapd->msg_ctx = hapd; + } + + return hapd_iface; + +fail: + wpa_printf(MSG_ERROR, "Failed to set up interface with %s", + config_file); + if (conf) + hostapd_config_free(conf); + if (hapd_iface) { + os_free(hapd_iface->config_fname); + os_free(hapd_iface->bss); + wpa_printf(MSG_DEBUG, "%s: free iface %p", + __func__, hapd_iface); + os_free(hapd_iface); + } + return NULL; +} + + +static int ifname_in_use(struct hapd_interfaces *interfaces, const char *ifname) +{ + size_t i, j; + + for (i = 0; i < interfaces->count; i++) { + struct hostapd_iface *iface = interfaces->iface[i]; + for (j = 0; j < iface->num_bss; j++) { + struct hostapd_data *hapd = iface->bss[j]; + if (os_strcmp(ifname, hapd->conf->iface) == 0) + return 1; + } + } + + return 0; +} + + +/** + * hostapd_interface_init_bss - Read configuration file and init BSS data + * + * This function is used to parse configuration file for a BSS. This BSS is + * added to an existing interface sharing the same radio (if any) or a new + * interface is created if this is the first interface on a radio. This + * allocate memory for the BSS. No actual driver operations are started. + * + * This is similar to hostapd_interface_init(), but for a case where the + * configuration is used to add a single BSS instead of all BSSes for a radio. + */ +struct hostapd_iface * +hostapd_interface_init_bss(struct hapd_interfaces *interfaces, const char *phy, + const char *config_fname, int debug) +{ + struct hostapd_iface *new_iface = NULL, *iface = NULL; + struct hostapd_data *hapd; + int k; + size_t i, bss_idx; + + if (!phy || !*phy) + return NULL; + + for (i = 0; i < interfaces->count; i++) { + if (os_strcmp(interfaces->iface[i]->phy, phy) == 0) { + iface = interfaces->iface[i]; + break; + } + } + + wpa_printf(MSG_INFO, "Configuration file: %s (phy %s)%s", + config_fname, phy, iface ? "" : " --> new PHY"); + if (iface) { + struct hostapd_config *conf; + struct hostapd_bss_config **tmp_conf; + struct hostapd_data **tmp_bss; + struct hostapd_bss_config *bss; + const char *ifname; + + /* Add new BSS to existing iface */ + conf = interfaces->config_read_cb(config_fname); + if (conf == NULL) + return NULL; + if (conf->num_bss > 1) { + wpa_printf(MSG_ERROR, "Multiple BSSes specified in BSS-config"); + hostapd_config_free(conf); + return NULL; + } + + ifname = conf->bss[0]->iface; + if (ifname[0] != '\0' && ifname_in_use(interfaces, ifname)) { + wpa_printf(MSG_ERROR, + "Interface name %s already in use", ifname); + hostapd_config_free(conf); + return NULL; + } + + tmp_conf = os_realloc_array( + iface->conf->bss, iface->conf->num_bss + 1, + sizeof(struct hostapd_bss_config *)); + tmp_bss = os_realloc_array(iface->bss, iface->num_bss + 1, + sizeof(struct hostapd_data *)); + if (tmp_bss) + iface->bss = tmp_bss; + if (tmp_conf) { + iface->conf->bss = tmp_conf; + iface->conf->last_bss = tmp_conf[0]; + } + if (tmp_bss == NULL || tmp_conf == NULL) { + hostapd_config_free(conf); + return NULL; + } + bss = iface->conf->bss[iface->conf->num_bss] = conf->bss[0]; + iface->conf->num_bss++; + + hapd = hostapd_alloc_bss_data(iface, iface->conf, bss); + if (hapd == NULL) { + iface->conf->num_bss--; + hostapd_config_free(conf); + return NULL; + } + iface->conf->last_bss = bss; + iface->bss[iface->num_bss] = hapd; + hapd->msg_ctx = hapd; + + bss_idx = iface->num_bss++; + conf->num_bss--; + conf->bss[0] = NULL; + hostapd_config_free(conf); + } else { + /* Add a new iface with the first BSS */ + new_iface = iface = hostapd_init(interfaces, config_fname); + if (!iface) + return NULL; + os_strlcpy(iface->phy, phy, sizeof(iface->phy)); + iface->interfaces = interfaces; + bss_idx = 0; + } + + for (k = 0; k < debug; k++) { + if (iface->bss[bss_idx]->conf->logger_stdout_level > 0) + iface->bss[bss_idx]->conf->logger_stdout_level--; + } + + if (iface->conf->bss[bss_idx]->iface[0] == '\0' && + !hostapd_drv_none(iface->bss[bss_idx])) { + wpa_printf(MSG_ERROR, "Interface name not specified in %s", + config_fname); + if (new_iface) + hostapd_interface_deinit_free(new_iface); + return NULL; + } + + return iface; +} + + +void hostapd_interface_deinit_free(struct hostapd_iface *iface) +{ + const struct wpa_driver_ops *driver; + void *drv_priv; + + wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface); + if (iface == NULL) + return; + wpa_printf(MSG_DEBUG, "%s: num_bss=%u conf->num_bss=%u", + __func__, (unsigned int) iface->num_bss, + (unsigned int) iface->conf->num_bss); + driver = iface->bss[0]->driver; + drv_priv = iface->bss[0]->drv_priv; + hostapd_interface_deinit(iface); + wpa_printf(MSG_DEBUG, "%s: driver=%p drv_priv=%p -> hapd_deinit", + __func__, driver, drv_priv); + if (driver && driver->hapd_deinit && drv_priv) { + driver->hapd_deinit(drv_priv); + iface->bss[0]->drv_priv = NULL; + } + hostapd_interface_free(iface); +} + + +static void hostapd_deinit_driver(const struct wpa_driver_ops *driver, + void *drv_priv, + struct hostapd_iface *hapd_iface) +{ + size_t j; + + wpa_printf(MSG_DEBUG, "%s: driver=%p drv_priv=%p -> hapd_deinit", + __func__, driver, drv_priv); + if (driver && driver->hapd_deinit && drv_priv) { + driver->hapd_deinit(drv_priv); + for (j = 0; j < hapd_iface->num_bss; j++) { + wpa_printf(MSG_DEBUG, "%s:bss[%d]->drv_priv=%p", + __func__, (int) j, + hapd_iface->bss[j]->drv_priv); + if (hapd_iface->bss[j]->drv_priv == drv_priv) + hapd_iface->bss[j]->drv_priv = NULL; + } + } +} + + +int hostapd_enable_iface(struct hostapd_iface *hapd_iface) +{ + size_t j; + + if (hapd_iface->bss[0]->drv_priv != NULL) { + wpa_printf(MSG_ERROR, "Interface %s already enabled", + hapd_iface->conf->bss[0]->iface); + return -1; + } + + wpa_printf(MSG_DEBUG, "Enable interface %s", + hapd_iface->conf->bss[0]->iface); + + for (j = 0; j < hapd_iface->num_bss; j++) + hostapd_set_security_params(hapd_iface->conf->bss[j], 1); + if (hostapd_config_check(hapd_iface->conf, 1) < 0) { + wpa_printf(MSG_INFO, "Invalid configuration - cannot enable"); + return -1; + } + + if (hapd_iface->interfaces == NULL || + hapd_iface->interfaces->driver_init == NULL || + hapd_iface->interfaces->driver_init(hapd_iface)) + return -1; + + if (hostapd_setup_interface(hapd_iface)) { + hostapd_deinit_driver(hapd_iface->bss[0]->driver, + hapd_iface->bss[0]->drv_priv, + hapd_iface); + return -1; + } + + return 0; +} + + +int hostapd_reload_iface(struct hostapd_iface *hapd_iface) +{ + size_t j; + + wpa_printf(MSG_DEBUG, "Reload interface %s", + hapd_iface->conf->bss[0]->iface); + for (j = 0; j < hapd_iface->num_bss; j++) + hostapd_set_security_params(hapd_iface->conf->bss[j], 1); + if (hostapd_config_check(hapd_iface->conf, 1) < 0) { + wpa_printf(MSG_ERROR, "Updated configuration is invalid"); + return -1; + } + hostapd_clear_old(hapd_iface); + for (j = 0; j < hapd_iface->num_bss; j++) + hostapd_reload_bss(hapd_iface->bss[j]); + + return 0; +} + + +int hostapd_disable_iface(struct hostapd_iface *hapd_iface) +{ + size_t j; + const struct wpa_driver_ops *driver; + void *drv_priv; + + if (hapd_iface == NULL) + return -1; + + if (hapd_iface->bss[0]->drv_priv == NULL) { + wpa_printf(MSG_INFO, "Interface %s already disabled", + hapd_iface->conf->bss[0]->iface); + return -1; + } + + wpa_msg(hapd_iface->bss[0]->msg_ctx, MSG_INFO, AP_EVENT_DISABLED); + driver = hapd_iface->bss[0]->driver; + drv_priv = hapd_iface->bss[0]->drv_priv; + + hapd_iface->driver_ap_teardown = + !!(hapd_iface->drv_flags & + WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT); + + /* same as hostapd_interface_deinit without deinitializing ctrl-iface */ + for (j = 0; j < hapd_iface->num_bss; j++) { + struct hostapd_data *hapd = hapd_iface->bss[j]; + hostapd_bss_deinit_no_free(hapd); + hostapd_free_hapd_data(hapd); + } + + hostapd_deinit_driver(driver, drv_priv, hapd_iface); + + /* From hostapd_cleanup_iface: These were initialized in + * hostapd_setup_interface and hostapd_setup_interface_complete + */ + hostapd_cleanup_iface_partial(hapd_iface); + + wpa_printf(MSG_DEBUG, "Interface %s disabled", + hapd_iface->bss[0]->conf->iface); + hostapd_set_state(hapd_iface, HAPD_IFACE_DISABLED); + return 0; +} + + +static struct hostapd_iface * +hostapd_iface_alloc(struct hapd_interfaces *interfaces) +{ + struct hostapd_iface **iface, *hapd_iface; + + iface = os_realloc_array(interfaces->iface, interfaces->count + 1, + sizeof(struct hostapd_iface *)); + if (iface == NULL) + return NULL; + interfaces->iface = iface; + hapd_iface = interfaces->iface[interfaces->count] = + os_zalloc(sizeof(*hapd_iface)); + if (hapd_iface == NULL) { + wpa_printf(MSG_ERROR, "%s: Failed to allocate memory for " + "the interface", __func__); + return NULL; + } + interfaces->count++; + hapd_iface->interfaces = interfaces; + + return hapd_iface; +} + + +static struct hostapd_config * +hostapd_config_alloc(struct hapd_interfaces *interfaces, const char *ifname, + const char *ctrl_iface, const char *driver) +{ + struct hostapd_bss_config *bss; + struct hostapd_config *conf; + + /* Allocates memory for bss and conf */ + conf = hostapd_config_defaults(); + if (conf == NULL) { + wpa_printf(MSG_ERROR, "%s: Failed to allocate memory for " + "configuration", __func__); + return NULL; + } + + if (driver) { + int j; + + for (j = 0; wpa_drivers[j]; j++) { + if (os_strcmp(driver, wpa_drivers[j]->name) == 0) { + conf->driver = wpa_drivers[j]; + goto skip; + } + } + + wpa_printf(MSG_ERROR, + "Invalid/unknown driver '%s' - registering the default driver", + driver); + } + + conf->driver = wpa_drivers[0]; + if (conf->driver == NULL) { + wpa_printf(MSG_ERROR, "No driver wrappers registered!"); + hostapd_config_free(conf); + return NULL; + } + +skip: + bss = conf->last_bss = conf->bss[0]; + + os_strlcpy(bss->iface, ifname, sizeof(bss->iface)); + bss->ctrl_interface = os_strdup(ctrl_iface); + if (bss->ctrl_interface == NULL) { + hostapd_config_free(conf); + return NULL; + } + + /* Reading configuration file skipped, will be done in SET! + * From reading the configuration till the end has to be done in + * SET + */ + return conf; +} + + +static int hostapd_data_alloc(struct hostapd_iface *hapd_iface, + struct hostapd_config *conf) +{ + size_t i; + struct hostapd_data *hapd; + + hapd_iface->bss = os_calloc(conf->num_bss, + sizeof(struct hostapd_data *)); + if (hapd_iface->bss == NULL) + return -1; + + for (i = 0; i < conf->num_bss; i++) { + hapd = hapd_iface->bss[i] = + hostapd_alloc_bss_data(hapd_iface, conf, conf->bss[i]); + if (hapd == NULL) { + while (i > 0) { + i--; + os_free(hapd_iface->bss[i]); + hapd_iface->bss[i] = NULL; + } + os_free(hapd_iface->bss); + hapd_iface->bss = NULL; + return -1; + } + hapd->msg_ctx = hapd; + } + + hapd_iface->conf = conf; + hapd_iface->num_bss = conf->num_bss; + + return 0; +} + + +int hostapd_add_iface(struct hapd_interfaces *interfaces, char *buf) +{ + struct hostapd_config *conf = NULL; + struct hostapd_iface *hapd_iface = NULL, *new_iface = NULL; + struct hostapd_data *hapd; + char *ptr; + size_t i, j; + const char *conf_file = NULL, *phy_name = NULL; + + if (os_strncmp(buf, "bss_config=", 11) == 0) { + char *pos; + phy_name = buf + 11; + pos = os_strchr(phy_name, ':'); + if (!pos) + return -1; + *pos++ = '\0'; + conf_file = pos; + if (!os_strlen(conf_file)) + return -1; + + hapd_iface = hostapd_interface_init_bss(interfaces, phy_name, + conf_file, 0); + if (!hapd_iface) + return -1; + for (j = 0; j < interfaces->count; j++) { + if (interfaces->iface[j] == hapd_iface) + break; + } + if (j == interfaces->count) { + struct hostapd_iface **tmp; + tmp = os_realloc_array(interfaces->iface, + interfaces->count + 1, + sizeof(struct hostapd_iface *)); + if (!tmp) { + hostapd_interface_deinit_free(hapd_iface); + return -1; + } + interfaces->iface = tmp; + interfaces->iface[interfaces->count++] = hapd_iface; + new_iface = hapd_iface; + } + + if (new_iface) { + if (interfaces->driver_init(hapd_iface)) + goto fail; + + if (hostapd_setup_interface(hapd_iface)) { + hostapd_deinit_driver( + hapd_iface->bss[0]->driver, + hapd_iface->bss[0]->drv_priv, + hapd_iface); + goto fail; + } + } else { + /* Assign new BSS with bss[0]'s driver info */ + hapd = hapd_iface->bss[hapd_iface->num_bss - 1]; + hapd->driver = hapd_iface->bss[0]->driver; + hapd->drv_priv = hapd_iface->bss[0]->drv_priv; + os_memcpy(hapd->own_addr, hapd_iface->bss[0]->own_addr, + ETH_ALEN); + + if (start_ctrl_iface_bss(hapd) < 0 || + (hapd_iface->state == HAPD_IFACE_ENABLED && + hostapd_setup_bss(hapd, -1))) { + hostapd_cleanup(hapd); + hapd_iface->bss[hapd_iface->num_bss - 1] = NULL; + hapd_iface->conf->num_bss--; + hapd_iface->num_bss--; + wpa_printf(MSG_DEBUG, "%s: free hapd %p %s", + __func__, hapd, hapd->conf->iface); + hostapd_config_free_bss(hapd->conf); + hapd->conf = NULL; + os_free(hapd); + return -1; + } + } + return 0; + } + + ptr = os_strchr(buf, ' '); + if (ptr == NULL) + return -1; + *ptr++ = '\0'; + + if (os_strncmp(ptr, "config=", 7) == 0) + conf_file = ptr + 7; + + for (i = 0; i < interfaces->count; i++) { + if (!os_strcmp(interfaces->iface[i]->conf->bss[0]->iface, + buf)) { + wpa_printf(MSG_INFO, "Cannot add interface - it " + "already exists"); + return -1; + } + } + + hapd_iface = hostapd_iface_alloc(interfaces); + if (hapd_iface == NULL) { + wpa_printf(MSG_ERROR, "%s: Failed to allocate memory " + "for interface", __func__); + goto fail; + } + new_iface = hapd_iface; + + if (conf_file && interfaces->config_read_cb) { + conf = interfaces->config_read_cb(conf_file); + if (conf && conf->bss) + os_strlcpy(conf->bss[0]->iface, buf, + sizeof(conf->bss[0]->iface)); + } else { + char *driver = os_strchr(ptr, ' '); + + if (driver) + *driver++ = '\0'; + conf = hostapd_config_alloc(interfaces, buf, ptr, driver); + } + + if (conf == NULL || conf->bss == NULL) { + wpa_printf(MSG_ERROR, "%s: Failed to allocate memory " + "for configuration", __func__); + goto fail; + } + + if (hostapd_data_alloc(hapd_iface, conf) < 0) { + wpa_printf(MSG_ERROR, "%s: Failed to allocate memory " + "for hostapd", __func__); + goto fail; + } + conf = NULL; + + if (start_ctrl_iface(hapd_iface) < 0) + goto fail; + + wpa_printf(MSG_INFO, "Add interface '%s'", + hapd_iface->conf->bss[0]->iface); + + return 0; + +fail: + if (conf) + hostapd_config_free(conf); + if (hapd_iface) { + if (hapd_iface->bss) { + for (i = 0; i < hapd_iface->num_bss; i++) { + hapd = hapd_iface->bss[i]; + if (!hapd) + continue; + if (hapd_iface->interfaces && + hapd_iface->interfaces->ctrl_iface_deinit) + hapd_iface->interfaces-> + ctrl_iface_deinit(hapd); + wpa_printf(MSG_DEBUG, "%s: free hapd %p (%s)", + __func__, hapd_iface->bss[i], + hapd->conf->iface); + hostapd_cleanup(hapd); + os_free(hapd); + hapd_iface->bss[i] = NULL; + } + os_free(hapd_iface->bss); + hapd_iface->bss = NULL; + } + if (new_iface) { + interfaces->count--; + interfaces->iface[interfaces->count] = NULL; + } + hostapd_cleanup_iface(hapd_iface); + } + return -1; +} + + +static int hostapd_remove_bss(struct hostapd_iface *iface, unsigned int idx) +{ + size_t i; + + wpa_printf(MSG_INFO, "Remove BSS '%s'", iface->conf->bss[idx]->iface); + + /* Remove hostapd_data only if it has already been initialized */ + if (idx < iface->num_bss) { + struct hostapd_data *hapd = iface->bss[idx]; + + hostapd_bss_deinit(hapd); + wpa_printf(MSG_DEBUG, "%s: free hapd %p (%s)", + __func__, hapd, hapd->conf->iface); + hostapd_config_free_bss(hapd->conf); + hapd->conf = NULL; + os_free(hapd); + + iface->num_bss--; + + for (i = idx; i < iface->num_bss; i++) + iface->bss[i] = iface->bss[i + 1]; + } else { + hostapd_config_free_bss(iface->conf->bss[idx]); + iface->conf->bss[idx] = NULL; + } + + iface->conf->num_bss--; + for (i = idx; i < iface->conf->num_bss; i++) + iface->conf->bss[i] = iface->conf->bss[i + 1]; + + return 0; +} + + +int hostapd_remove_iface(struct hapd_interfaces *interfaces, char *buf) +{ + struct hostapd_iface *hapd_iface; + size_t i, j, k = 0; + + for (i = 0; i < interfaces->count; i++) { + hapd_iface = interfaces->iface[i]; + if (hapd_iface == NULL) + return -1; + if (!os_strcmp(hapd_iface->conf->bss[0]->iface, buf)) { + wpa_printf(MSG_INFO, "Remove interface '%s'", buf); + hapd_iface->driver_ap_teardown = + !!(hapd_iface->drv_flags & + WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT); + + hostapd_interface_deinit_free(hapd_iface); + k = i; + while (k < (interfaces->count - 1)) { + interfaces->iface[k] = + interfaces->iface[k + 1]; + k++; + } + interfaces->count--; + return 0; + } + + for (j = 0; j < hapd_iface->conf->num_bss; j++) { + if (!os_strcmp(hapd_iface->conf->bss[j]->iface, buf)) { + hapd_iface->driver_ap_teardown = + !(hapd_iface->drv_flags & + WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT); + return hostapd_remove_bss(hapd_iface, j); + } + } + } + return -1; +} + + +/** + * hostapd_new_assoc_sta - Notify that a new station associated with the AP + * @hapd: Pointer to BSS data + * @sta: Pointer to the associated STA data + * @reassoc: 1 to indicate this was a re-association; 0 = first association + * + * This function will be called whenever a station associates with the AP. It + * can be called from ieee802_11.c for drivers that export MLME to hostapd and + * from drv_callbacks.c based on driver events for drivers that take care of + * management frames (IEEE 802.11 authentication and association) internally. + */ +void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta, + int reassoc) +{ + if (hapd->tkip_countermeasures) { + hostapd_drv_sta_deauth(hapd, sta->addr, + WLAN_REASON_MICHAEL_MIC_FAILURE); + return; + } + + hostapd_prune_associations(hapd, sta->addr); + +#ifdef CONFIG_FULL_HOSTAPD + /* IEEE 802.11F (IAPP) */ + if (hapd->conf->ieee802_11f) + iapp_new_station(hapd->iapp, sta); +#endif +#ifdef CONFIG_P2P + if (sta->p2p_ie == NULL && !sta->no_p2p_set) { + sta->no_p2p_set = 1; + hapd->num_sta_no_p2p++; + if (hapd->num_sta_no_p2p == 1) + hostapd_p2p_non_p2p_sta_connected(hapd); + } +#endif /* CONFIG_P2P */ + + /* Start accounting here, if IEEE 802.1X and WPA are not used. + * IEEE 802.1X/WPA code will start accounting after the station has + * been authorized. */ + if (!hapd->conf->ieee802_1x && !hapd->conf->wpa && !hapd->conf->osen) { + ap_sta_set_authorized(hapd, sta, 1); + os_get_reltime(&sta->connected_time); + accounting_sta_start(hapd, sta); + } + + if (reassoc) { + if (sta->auth_alg != WLAN_AUTH_FT && + !(sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS))) + wpa_auth_sm_event(sta->wpa_sm, WPA_REAUTH); + } else + wpa_auth_sta_associated(hapd->wpa_auth, sta->wpa_sm); + + if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_INACTIVITY_TIMER)) { + wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout " + "for " MACSTR " (%d seconds - ap_max_inactivity)", + __func__, MAC2STR(sta->addr), + hapd->conf->ap_max_inactivity); + eloop_cancel_timeout(ap_handle_timer, hapd, sta); + eloop_register_timeout(hapd->conf->ap_max_inactivity, 0, + ap_handle_timer, hapd, sta); + } +} + + +const char * hostapd_state_text(enum hostapd_iface_state s) +{ + switch (s) { + case HAPD_IFACE_UNINITIALIZED: + return "UNINITIALIZED"; + case HAPD_IFACE_DISABLED: + return "DISABLED"; + case HAPD_IFACE_COUNTRY_UPDATE: + return "COUNTRY_UPDATE"; + case HAPD_IFACE_ACS: + return "ACS"; + case HAPD_IFACE_HT_SCAN: + return "HT_SCAN"; + case HAPD_IFACE_DFS: + return "DFS"; + case HAPD_IFACE_ENABLED: + return "ENABLED"; + } + + return "UNKNOWN"; +} + + +void hostapd_set_state(struct hostapd_iface *iface, enum hostapd_iface_state s) +{ + wpa_printf(MSG_INFO, "%s: interface state %s->%s", + iface->conf->bss[0]->iface, hostapd_state_text(iface->state), + hostapd_state_text(s)); + iface->state = s; +} + + +#ifdef NEED_AP_MLME +static void free_beacon_data(struct beacon_data *beacon) +{ + os_free(beacon->head); + beacon->head = NULL; + os_free(beacon->tail); + beacon->tail = NULL; + os_free(beacon->probe_resp); + beacon->probe_resp = NULL; + os_free(beacon->beacon_ies); + beacon->beacon_ies = NULL; + os_free(beacon->proberesp_ies); + beacon->proberesp_ies = NULL; + os_free(beacon->assocresp_ies); + beacon->assocresp_ies = NULL; +} + + +static int hostapd_build_beacon_data(struct hostapd_data *hapd, + struct beacon_data *beacon) +{ + struct wpabuf *beacon_extra, *proberesp_extra, *assocresp_extra; + struct wpa_driver_ap_params params; + int ret; + + os_memset(beacon, 0, sizeof(*beacon)); + ret = ieee802_11_build_ap_params(hapd, ¶ms); + if (ret < 0) + return ret; + + ret = hostapd_build_ap_extra_ies(hapd, &beacon_extra, + &proberesp_extra, + &assocresp_extra); + if (ret) + goto free_ap_params; + + ret = -1; + beacon->head = os_malloc(params.head_len); + if (!beacon->head) + goto free_ap_extra_ies; + + os_memcpy(beacon->head, params.head, params.head_len); + beacon->head_len = params.head_len; + + beacon->tail = os_malloc(params.tail_len); + if (!beacon->tail) + goto free_beacon; + + os_memcpy(beacon->tail, params.tail, params.tail_len); + beacon->tail_len = params.tail_len; + + if (params.proberesp != NULL) { + beacon->probe_resp = os_malloc(params.proberesp_len); + if (!beacon->probe_resp) + goto free_beacon; + + os_memcpy(beacon->probe_resp, params.proberesp, + params.proberesp_len); + beacon->probe_resp_len = params.proberesp_len; + } + + /* copy the extra ies */ + if (beacon_extra) { + beacon->beacon_ies = os_malloc(wpabuf_len(beacon_extra)); + if (!beacon->beacon_ies) + goto free_beacon; + + os_memcpy(beacon->beacon_ies, + beacon_extra->buf, wpabuf_len(beacon_extra)); + beacon->beacon_ies_len = wpabuf_len(beacon_extra); + } + + if (proberesp_extra) { + beacon->proberesp_ies = + os_malloc(wpabuf_len(proberesp_extra)); + if (!beacon->proberesp_ies) + goto free_beacon; + + os_memcpy(beacon->proberesp_ies, proberesp_extra->buf, + wpabuf_len(proberesp_extra)); + beacon->proberesp_ies_len = wpabuf_len(proberesp_extra); + } + + if (assocresp_extra) { + beacon->assocresp_ies = + os_malloc(wpabuf_len(assocresp_extra)); + if (!beacon->assocresp_ies) + goto free_beacon; + + os_memcpy(beacon->assocresp_ies, assocresp_extra->buf, + wpabuf_len(assocresp_extra)); + beacon->assocresp_ies_len = wpabuf_len(assocresp_extra); + } + + ret = 0; +free_beacon: + /* if the function fails, the caller should not free beacon data */ + if (ret) + free_beacon_data(beacon); + +free_ap_extra_ies: + hostapd_free_ap_extra_ies(hapd, beacon_extra, proberesp_extra, + assocresp_extra); +free_ap_params: + ieee802_11_free_ap_params(¶ms); + return ret; +} + + +/* + * TODO: This flow currently supports only changing frequency within the + * same hw_mode. Any other changes to MAC parameters or provided settings (even + * width) are not supported. + */ +static int hostapd_change_config_freq(struct hostapd_data *hapd, + struct hostapd_config *conf, + struct hostapd_freq_params *params, + struct hostapd_freq_params *old_params) +{ + int channel; + + if (!params->channel) { + /* check if the new channel is supported by hw */ + params->channel = hostapd_hw_get_channel(hapd, params->freq); + } + + channel = params->channel; + if (!channel) + return -1; + + /* if a pointer to old_params is provided we save previous state */ + if (old_params) { + old_params->channel = conf->channel; + old_params->ht_enabled = conf->ieee80211n; + old_params->sec_channel_offset = conf->secondary_channel; + } + + conf->channel = channel; + conf->ieee80211n = params->ht_enabled; + conf->secondary_channel = params->sec_channel_offset; + + /* TODO: maybe call here hostapd_config_check here? */ + + return 0; +} + + +static int hostapd_fill_csa_settings(struct hostapd_data *hapd, + struct csa_settings *settings) +{ + struct hostapd_iface *iface = hapd->iface; + struct hostapd_freq_params old_freq; + int ret; + + os_memset(&old_freq, 0, sizeof(old_freq)); + if (!iface || !iface->freq || hapd->csa_in_progress) + return -1; + + ret = hostapd_change_config_freq(iface->bss[0], iface->conf, + &settings->freq_params, + &old_freq); + if (ret) + return ret; + + ret = hostapd_build_beacon_data(hapd, &settings->beacon_after); + + /* change back the configuration */ + hostapd_change_config_freq(iface->bss[0], iface->conf, + &old_freq, NULL); + + if (ret) + return ret; + + /* set channel switch parameters for csa ie */ + hapd->cs_freq_params = settings->freq_params; + hapd->cs_count = settings->cs_count; + hapd->cs_block_tx = settings->block_tx; + + ret = hostapd_build_beacon_data(hapd, &settings->beacon_csa); + if (ret) { + free_beacon_data(&settings->beacon_after); + return ret; + } + + settings->counter_offset_beacon = hapd->cs_c_off_beacon; + settings->counter_offset_presp = hapd->cs_c_off_proberesp; + + return 0; +} + + +void hostapd_cleanup_cs_params(struct hostapd_data *hapd) +{ + os_memset(&hapd->cs_freq_params, 0, sizeof(hapd->cs_freq_params)); + hapd->cs_count = 0; + hapd->cs_block_tx = 0; + hapd->cs_c_off_beacon = 0; + hapd->cs_c_off_proberesp = 0; + hapd->csa_in_progress = 0; +} + + +int hostapd_switch_channel(struct hostapd_data *hapd, + struct csa_settings *settings) +{ + int ret; + + if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_CSA)) { + wpa_printf(MSG_INFO, "CSA is not supported"); + return -1; + } + + ret = hostapd_fill_csa_settings(hapd, settings); + if (ret) + return ret; + + ret = hostapd_drv_switch_channel(hapd, settings); + free_beacon_data(&settings->beacon_csa); + free_beacon_data(&settings->beacon_after); + + if (ret) { + /* if we failed, clean cs parameters */ + hostapd_cleanup_cs_params(hapd); + return ret; + } + + hapd->csa_in_progress = 1; + return 0; +} + +void hostapd_switch_channel_fallback(struct hostapd_iface *iface, + const struct hostapd_freq_params *freq_params) +{ + int vht_seg0_idx = 0, vht_seg1_idx = 0, vht_bw = VHT_CHANWIDTH_USE_HT; + unsigned int i; + + wpa_printf(MSG_DEBUG, "Restarting all CSA-related BSSes"); + + if (freq_params->center_freq1) + vht_seg0_idx = 36 + (freq_params->center_freq1 - 5180) / 5; + if (freq_params->center_freq2) + vht_seg1_idx = 36 + (freq_params->center_freq2 - 5180) / 5; + + switch (freq_params->bandwidth) { + case 0: + case 20: + case 40: + vht_bw = VHT_CHANWIDTH_USE_HT; + break; + case 80: + if (freq_params->center_freq2) + vht_bw = VHT_CHANWIDTH_80P80MHZ; + else + vht_bw = VHT_CHANWIDTH_80MHZ; + break; + case 160: + vht_bw = VHT_CHANWIDTH_160MHZ; + break; + default: + wpa_printf(MSG_WARNING, "Unknown CSA bandwidth: %d", + freq_params->bandwidth); + break; + } + + iface->freq = freq_params->freq; + iface->conf->channel = freq_params->channel; + iface->conf->secondary_channel = freq_params->sec_channel_offset; + iface->conf->vht_oper_centr_freq_seg0_idx = vht_seg0_idx; + iface->conf->vht_oper_centr_freq_seg1_idx = vht_seg1_idx; + iface->conf->vht_oper_chwidth = vht_bw; + iface->conf->ieee80211n = freq_params->ht_enabled; + iface->conf->ieee80211ac = freq_params->vht_enabled; + + /* + * cs_params must not be cleared earlier because the freq_params + * argument may actually point to one of these. + */ + for (i = 0; i < iface->num_bss; i++) + hostapd_cleanup_cs_params(iface->bss[i]); + + hostapd_disable_iface(iface); + hostapd_enable_iface(iface); +} + + +struct hostapd_data * hostapd_get_iface(struct hapd_interfaces *interfaces, + const char *ifname) +{ + size_t i, j; + + for (i = 0; i < interfaces->count; i++) { + struct hostapd_iface *iface = interfaces->iface[i]; + + for (j = 0; j < iface->num_bss; j++) { + struct hostapd_data *hapd = iface->bss[j]; + + if (os_strcmp(ifname, hapd->conf->iface) == 0) + return hapd; + } + } + + return NULL; +} + +#endif /* NEED_AP_MLME */ + + +void hostapd_periodic_iface(struct hostapd_iface *iface) +{ + size_t i; + + ap_list_timer(iface); + + for (i = 0; i < iface->num_bss; i++) { + struct hostapd_data *hapd = iface->bss[i]; + + if (!hapd->started) + continue; + +#ifndef CONFIG_NO_RADIUS + hostapd_acl_expire(hapd); +#endif /* CONFIG_NO_RADIUS */ + } +} + +int ap_channel_switch(struct hostapd_iface *ap_iface, int new_freq) +{ + struct csa_settings settings = {6}; + + settings.cs_count = 8; + settings.freq_params.freq = new_freq; + settings.freq_params.ht_enabled = 1; + settings.freq_params.ht_enabled = 0; + + if (!ap_iface || !ap_iface->bss[0]) + return -1; + + return hostapd_switch_channel(ap_iface->bss[0], &settings); +} + diff --git a/beken_os/beken378/func/hostapd-2.5/src/ap/hostapd.h b/beken_os/beken378/func/hostapd-2.5/src/ap/hostapd.h new file mode 100755 index 0000000..a8f6f16 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/ap/hostapd.h @@ -0,0 +1,437 @@ +/* + * hostapd / Initialization and configuration + * Copyright (c) 2002-2014, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef HOSTAPD_H +#define HOSTAPD_H + +#include "common/defs.h" +#include "utils/list.h" +#include "ap_config.h" +#include "drivers/driver.h" + +struct wpa_ctrl_dst; +struct radius_server_data; +struct upnp_wps_device_sm; +struct hostapd_data; +struct sta_info; +struct ieee80211_ht_capabilities; +struct full_dynamic_vlan; +enum wps_event; +union wps_event_data; +#ifdef CONFIG_MESH +struct mesh_conf; +#endif /* CONFIG_MESH */ + +struct hostapd_iface; + +struct hapd_interfaces { + int (*reload_config)(struct hostapd_iface *iface); + struct hostapd_config * (*config_read_cb)(const char *config_fname); + int (*ctrl_iface_init)(struct hostapd_data *hapd); + void (*ctrl_iface_deinit)(struct hostapd_data *hapd); + int (*for_each_interface)(struct hapd_interfaces *interfaces, + int (*cb)(struct hostapd_iface *iface, + void *ctx), void *ctx); + int (*driver_init)(struct hostapd_iface *iface); + + size_t count; + int global_ctrl_sock; + struct wpa_ctrl_dst *global_ctrl_dst; + char *global_iface_path; + char *global_iface_name; + + struct hostapd_iface **iface; + + size_t terminate_on_error; + }; + +enum hostapd_chan_status { + HOSTAPD_CHAN_VALID = 0, /* channel is ready */ + HOSTAPD_CHAN_INVALID = 1, /* no usable channel found */ + HOSTAPD_CHAN_ACS = 2, /* ACS work being performed */ +}; + +struct hostapd_probereq_cb { + int (*cb)(void *ctx, const u8 *sa, const u8 *da, const u8 *bssid, + const u8 *ie, size_t ie_len, int ssi_signal); + void *ctx; +}; + +#define HOSTAPD_RATE_BASIC 0x00000001 + +struct hostapd_rate_data { + int rate; /* rate in 100 kbps */ + int flags; /* HOSTAPD_RATE_ flags */ +}; + +struct hostapd_frame_info { + u32 channel; + u32 datarate; + int ssi_signal; /* dBm */ +}; + +enum wps_status { + WPS_STATUS_SUCCESS = 1, + WPS_STATUS_FAILURE +}; + +enum pbc_status { + WPS_PBC_STATUS_DISABLE, + WPS_PBC_STATUS_ACTIVE, + WPS_PBC_STATUS_TIMEOUT, + WPS_PBC_STATUS_OVERLAP +}; + +struct wps_stat { + enum wps_status status; + enum wps_error_indication failure_reason; + enum pbc_status pbc_status; + u8 peer_addr[ETH_ALEN]; +}; + + +/** + * struct hostapd_data - hostapd per-BSS data structure + */ +struct hostapd_data { + struct hostapd_iface *iface; + struct hostapd_config *iconf; + struct hostapd_bss_config *conf; + int interface_added; /* virtual interface added for this BSS */ + unsigned int started:1; + unsigned int disabled:1; + unsigned int reenable_beacon:1; + + u8 own_addr[ETH_ALEN]; + + int num_sta; /* number of entries in sta_list */ + struct sta_info *sta_list; /* STA info list head */ +#define STA_HASH_SIZE 256 +#define STA_HASH(sta) (sta[5]) + struct sta_info *sta_hash[STA_HASH_SIZE]; + + /* + * Bitfield for indicating which AIDs are allocated. Only AID values + * 1-2007 are used and as such, the bit at index 0 corresponds to AID + * 1. + */ +#define AID_WORDS ((CFG_STA_MAX + 31) / 32) + u32 sta_aid[AID_WORDS]; + + const struct wpa_driver_ops *driver; + void *drv_priv; + + void (*new_assoc_sta_cb)(struct hostapd_data *hapd, + struct sta_info *sta, int reassoc); + + void *msg_ctx; /* ctx for wpa_msg() calls */ + void *msg_ctx_parent; /* parent interface ctx for wpa_msg() calls */ + + struct wpa_authenticator *wpa_auth; + struct eapol_authenticator *eapol_auth; + + struct os_reltime michael_mic_failure; + int michael_mic_failures; + int tkip_countermeasures; + + /* Time Advertisement */ + u8 time_update_counter; + struct wpabuf *time_adv; + +#ifdef CONFIG_FULL_DYNAMIC_VLAN + struct full_dynamic_vlan *full_dynamic_vlan; +#endif /* CONFIG_FULL_DYNAMIC_VLAN */ + + struct l2_packet_data *l2; + + int beacon_set_done; + + struct hostapd_probereq_cb *probereq_cb; + size_t num_probereq_cb; + + void (*public_action_cb)(void *ctx, const u8 *buf, size_t len, + int freq); + void *public_action_cb_ctx; + void (*public_action_cb2)(void *ctx, const u8 *buf, size_t len, + int freq); + void *public_action_cb2_ctx; + + int (*vendor_action_cb)(void *ctx, const u8 *buf, size_t len, + int freq); + void *vendor_action_cb_ctx; + + void (*wps_reg_success_cb)(void *ctx, const u8 *mac_addr, + const u8 *uuid_e); + void *wps_reg_success_cb_ctx; + + void (*wps_event_cb)(void *ctx, enum wps_event event, + union wps_event_data *data); + void *wps_event_cb_ctx; + + void (*sta_authorized_cb)(void *ctx, const u8 *mac_addr, + int authorized, const u8 *p2p_dev_addr); + void *sta_authorized_cb_ctx; + + void (*setup_complete_cb)(void *ctx); + void *setup_complete_cb_ctx; + + void (*new_psk_cb)(void *ctx, const u8 *mac_addr, + const u8 *p2p_dev_addr, const u8 *psk, + size_t psk_len); + void *new_psk_cb_ctx; + + /* channel switch parameters */ + struct hostapd_freq_params cs_freq_params; + u8 cs_count; + int cs_block_tx; + unsigned int cs_c_off_beacon; + unsigned int cs_c_off_proberesp; + int csa_in_progress; + +#ifdef CONFIG_P2P + struct p2p_data *p2p; + struct p2p_group *p2p_group; + struct wpabuf *p2p_beacon_ie; + struct wpabuf *p2p_probe_resp_ie; + + /* Number of non-P2P association stations */ + int num_sta_no_p2p; + + /* Periodic NoA (used only when no non-P2P clients in the group) */ + int noa_enabled; + int noa_start; + int noa_duration; +#endif /* CONFIG_P2P */ +#ifdef CONFIG_MESH + int num_plinks; + int max_plinks; + void (*mesh_sta_free_cb)(struct sta_info *sta); + struct wpabuf *mesh_pending_auth; + struct os_reltime mesh_pending_auth_time; +#endif /* CONFIG_MESH */ + +#ifdef CONFIG_SAE + /** Key used for generating SAE anti-clogging tokens */ + u8 sae_token_key[8]; + struct os_reltime last_sae_token_key_update; + int dot11RSNASAERetransPeriod; /* msec */ +#endif /* CONFIG_SAE */ +}; + + +struct hostapd_sta_info { + struct dl_list list; + u8 addr[ETH_ALEN]; + struct os_reltime last_seen; +}; + +/** + * struct hostapd_iface - hostapd per-interface data structure + */ +struct hostapd_iface { + struct hapd_interfaces *interfaces; + void *owner; + char *config_fname; + struct hostapd_config *conf; + char phy[16]; /* Name of the PHY (radio) */ + + enum hostapd_iface_state { + HAPD_IFACE_UNINITIALIZED, + HAPD_IFACE_DISABLED, + HAPD_IFACE_COUNTRY_UPDATE, + HAPD_IFACE_ACS, + HAPD_IFACE_HT_SCAN, + HAPD_IFACE_DFS, + HAPD_IFACE_ENABLED + } state; + +#ifdef CONFIG_MESH + struct mesh_conf *mconf; +#endif /* CONFIG_MESH */ + + size_t num_bss; + struct hostapd_data **bss; + + unsigned int wait_channel_update:1; + unsigned int cac_started:1; +#ifdef CONFIG_FST + struct fst_iface *fst; + const struct wpabuf *fst_ies; +#endif /* CONFIG_FST */ + + /* + * When set, indicates that the driver will handle the AP + * teardown: delete global keys, station keys, and stations. + */ + unsigned int driver_ap_teardown:1; + + int num_ap; /* number of entries in ap_list */ + struct ap_info *ap_list; /* AP info list head */ + struct ap_info *ap_hash[STA_HASH_SIZE]; + + u64 drv_flags; + + /* SMPS modes supported by the driver (WPA_DRIVER_SMPS_MODE_*) */ + unsigned int smps_modes; + + /* + * A bitmap of supported protocols for probe response offload. See + * struct wpa_driver_capa in driver.h + */ + unsigned int probe_resp_offloads; + + /* extended capabilities supported by the driver */ + const u8 *extended_capa, *extended_capa_mask; + unsigned int extended_capa_len; + + unsigned int drv_max_acl_mac_addrs; + + struct hostapd_hw_modes *hw_features; + int num_hw_features; + struct hostapd_hw_modes *current_mode; + /* Rates that are currently used (i.e., filtered copy of + * current_mode->channels */ + int num_rates; + struct hostapd_rate_data *current_rates; + int *basic_rates; + int freq; + + u16 hw_flags; + + /* Number of associated Non-ERP stations (i.e., stations using 802.11b + * in 802.11g BSS) */ + int num_sta_non_erp; + + /* Number of associated stations that do not support Short Slot Time */ + int num_sta_no_short_slot_time; + + /* Number of associated stations that do not support Short Preamble */ + int num_sta_no_short_preamble; + + int olbc; /* Overlapping Legacy BSS Condition */ + + /* Number of HT associated stations that do not support greenfield */ + int num_sta_ht_no_gf; + + /* Number of associated non-HT stations */ + int num_sta_no_ht; + + /* Number of HT associated stations 20 MHz */ + int num_sta_ht_20mhz; + + /* Number of HT40 intolerant stations */ + int num_sta_ht40_intolerant; + + /* Overlapping BSS information */ + int olbc_ht; + + u16 ht_op_mode; + + /* surveying helpers */ + + /* number of channels surveyed */ + unsigned int chans_surveyed; + + /* lowest observed noise floor in dBm */ + s8 lowest_nf; + + /* channel utilization calculation */ + u64 last_channel_time; + u64 last_channel_time_busy; + u8 channel_utilization; + + unsigned int dfs_cac_ms; + struct os_reltime dfs_cac_start; + + /* Latched with the actual secondary channel information and will be + * used while juggling between HT20 and HT40 modes. */ + int secondary_ch; + +#ifdef CONFIG_ACS + unsigned int acs_num_completed_scans; +#endif /* CONFIG_ACS */ + + void (*scan_cb)(struct hostapd_iface *iface); + int num_ht40_scan_tries; + + struct dl_list sta_seen; /* struct hostapd_sta_info */ + unsigned int num_sta_seen; +}; + +/* hostapd.c */ +int hostapd_for_each_interface(struct hapd_interfaces *interfaces, + int (*cb)(struct hostapd_iface *iface, + void *ctx), void *ctx); +int hostapd_reload_config(struct hostapd_iface *iface); +struct hostapd_data * +hostapd_alloc_bss_data(struct hostapd_iface *hapd_iface, + struct hostapd_config *conf, + struct hostapd_bss_config *bss); +int hostapd_setup_interface(struct hostapd_iface *iface); +int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err); +void hostapd_interface_deinit(struct hostapd_iface *iface); +void hostapd_interface_free(struct hostapd_iface *iface); +struct hostapd_iface * hostapd_init(struct hapd_interfaces *interfaces, + const char *config_file); +struct hostapd_iface * +hostapd_interface_init_bss(struct hapd_interfaces *interfaces, const char *phy, + const char *config_fname, int debug); +void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta, + int reassoc); +void hostapd_interface_deinit_free(struct hostapd_iface *iface); +int hostapd_enable_iface(struct hostapd_iface *hapd_iface); +int hostapd_reload_iface(struct hostapd_iface *hapd_iface); +int hostapd_disable_iface(struct hostapd_iface *hapd_iface); +int hostapd_add_iface(struct hapd_interfaces *ifaces, char *buf); +int hostapd_remove_iface(struct hapd_interfaces *ifaces, char *buf); +void hostapd_channel_list_updated(struct hostapd_iface *iface, int initiator); +void hostapd_set_state(struct hostapd_iface *iface, enum hostapd_iface_state s); +const char * hostapd_state_text(enum hostapd_iface_state s); +int hostapd_switch_channel(struct hostapd_data *hapd, + struct csa_settings *settings); +void +hostapd_switch_channel_fallback(struct hostapd_iface *iface, + const struct hostapd_freq_params *freq_params); +void hostapd_cleanup_cs_params(struct hostapd_data *hapd); +void hostapd_periodic_iface(struct hostapd_iface *iface); + +/* utils.c */ +int hostapd_register_probereq_cb(struct hostapd_data *hapd, + int (*cb)(void *ctx, const u8 *sa, + const u8 *da, const u8 *bssid, + const u8 *ie, size_t ie_len, + int ssi_signal), + void *ctx); +void hostapd_prune_associations(struct hostapd_data *hapd, const u8 *addr); + +/* drv_callbacks.c (TODO: move to somewhere else?) */ +int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr, + const u8 *ie, size_t ielen, int reassoc); +void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr); +void hostapd_event_sta_low_ack(struct hostapd_data *hapd, const u8 *addr); +void hostapd_event_connect_failed_reason(struct hostapd_data *hapd, + const u8 *addr, int reason_code); +int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa, const u8 *da, + const u8 *bssid, const u8 *ie, size_t ie_len, + int ssi_signal); +void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht, + int offset, int width, int cf1, int cf2); + +const struct hostapd_eap_user * +hostapd_get_eap_user(struct hostapd_data *hapd, const u8 *identity, + size_t identity_len, int phase2); + +struct hostapd_data * hostapd_get_iface(struct hapd_interfaces *interfaces, + const char *ifname); + +#ifdef CONFIG_FST +void fst_hostapd_fill_iface_obj(struct hostapd_data *hapd, + struct fst_wpa_obj *iface_obj); +#endif /* CONFIG_FST */ + +#endif /* HOSTAPD_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/ap/hw_features.c b/beken_os/beken378/func/hostapd-2.5/src/ap/hw_features.c new file mode 100755 index 0000000..a825c7f --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/ap/hw_features.c @@ -0,0 +1,992 @@ +/* + * hostapd / Hardware feature query and different modes + * Copyright 2002-2003, Instant802 Networks, Inc. + * Copyright 2005-2006, Devicescape Software, Inc. + * Copyright (c) 2008-2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "utils/eloop.h" +#include "common/ieee802_11_defs.h" +#include "common/ieee802_11_common.h" +#include "common/wpa_ctrl.h" +#include "common/hw_features_common.h" +#include "ap/hostapd.h" +#include "ap_config.h" +#include "ap_drv_ops.h" +#include "acs.h" +#include "ieee802_11.h" +#include "beacon.h" +#include "hw_features.h" +#include "hostapd_cfg.h" + +#include "include.h" +#include "param_config.h" + +void hostapd_free_hw_features(struct hostapd_hw_modes *hw_features, + size_t num_hw_features) +{ + size_t i; + + if (hw_features == NULL) + return; + + for (i = 0; i < num_hw_features; i++) { + os_free(hw_features[i].channels); + os_free(hw_features[i].rates); + } + + os_free(hw_features); +} + + +#ifndef CONFIG_NO_STDOUT_DEBUG +static char * dfs_info(struct hostapd_channel_data *chan) +{ + static char info[256]; + char *state; + + switch (chan->flag & HOSTAPD_CHAN_DFS_MASK) { + case HOSTAPD_CHAN_DFS_UNKNOWN: + state = "unknown"; + break; + case HOSTAPD_CHAN_DFS_USABLE: + state = "usable"; + break; + case HOSTAPD_CHAN_DFS_UNAVAILABLE: + state = "unavailable"; + break; + case HOSTAPD_CHAN_DFS_AVAILABLE: + state = "available"; + break; + default: + return ""; + } + os_snprintf(info, sizeof(info), " (DFS state = %s)", state); + info[sizeof(info) - 1] = '\0'; + + return info; +} +#endif /* CONFIG_NO_STDOUT_DEBUG */ + + +int hostapd_get_hw_features(struct hostapd_iface *iface) +{ + struct hostapd_data *hapd = iface->bss[0]; + int i, j; + u16 num_modes, flags; + struct hostapd_hw_modes *modes; + + if (hostapd_drv_none(hapd)) + return -1; + modes = hostapd_get_hw_feature_data(hapd, &num_modes, &flags); + if (modes == NULL) { + hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "Fetching hardware channel/rate support not " + "supported."); + return -1; + } + + iface->hw_flags = flags; + + hostapd_free_hw_features(iface->hw_features, iface->num_hw_features); + iface->hw_features = modes; + iface->num_hw_features = num_modes; + + for (i = 0; i < num_modes; i++) { + struct hostapd_hw_modes *feature = &modes[i]; + int dfs_enabled = hapd->iconf->ieee80211h && + (iface->drv_flags & WPA_DRIVER_FLAGS_RADAR); + + /* set flag for channels we can use in current regulatory + * domain */ + for (j = 0; j < feature->num_channels; j++) { + /* + * Disable all channels that are marked not to allow + * to initiate radiation (a.k.a. passive scan and no + * IBSS). + * Use radar channels only if the driver supports DFS. + */ + if ((feature->channels[j].flag & + HOSTAPD_CHAN_RADAR) && dfs_enabled) { + } else if (((feature->channels[j].flag & + HOSTAPD_CHAN_RADAR) && + !(iface->drv_flags & + WPA_DRIVER_FLAGS_DFS_OFFLOAD)) || + (feature->channels[j].flag & + HOSTAPD_CHAN_NO_IR)) { + feature->channels[j].flag |= + HOSTAPD_CHAN_DISABLED; + } + + if (feature->channels[j].flag & HOSTAPD_CHAN_DISABLED) + continue; + +#ifndef CONFIG_NO_STDOUT_DEBUG + wpa_printf(MSG_MSGDUMP, "Allowed channel: mode=%d " + "chan=%d freq=%d MHz max_tx_power=%d dBm%s", + feature->mode, + feature->channels[j].chan, + feature->channels[j].freq, + feature->channels[j].max_tx_power, + dfs_enabled ? dfs_info(&feature->channels[j]) : ""); +#endif /* CONFIG_NO_STDOUT_DEBUG */ + } + } + + return 0; +} + + +int hostapd_prepare_rates(struct hostapd_iface *iface, + struct hostapd_hw_modes *mode) +{ + int i, num_basic_rates = 0; + int basic_rates_a[] = { 60, 120, 240, -1 }; + int basic_rates_b[] = { 10, 20, -1 }; + int basic_rates_g[] = { 10, 20, 55, 110, -1 }; + int *basic_rates; + + if (iface->conf->basic_rates) + basic_rates = iface->conf->basic_rates; + else switch (mode->mode) { + case HOSTAPD_MODE_IEEE80211A: + basic_rates = basic_rates_a; + break; + case HOSTAPD_MODE_IEEE80211B: + basic_rates = basic_rates_b; + break; + case HOSTAPD_MODE_IEEE80211G: + basic_rates = basic_rates_g; + break; + case HOSTAPD_MODE_IEEE80211AD: + return 0; /* No basic rates for 11ad */ + default: + return -1; + } + + i = 0; + while (basic_rates[i] >= 0) + i++; + if (i) + i++; /* -1 termination */ + os_free(iface->basic_rates); + iface->basic_rates = os_malloc(i * sizeof(int)); + if (iface->basic_rates) + os_memcpy(iface->basic_rates, basic_rates, i * sizeof(int)); + + if(iface->current_rates) + { + os_free(iface->current_rates); + } + iface->num_rates = 0; + + iface->current_rates = + os_calloc(mode->num_rates, sizeof(struct hostapd_rate_data)); + if (!iface->current_rates) { + wpa_printf(MSG_ERROR, "Failed to allocate memory for rate " + "table."); + return -1; + } + + for (i = 0; i < mode->num_rates; i++) { + struct hostapd_rate_data *rate; + + if (iface->conf->supported_rates && + !hostapd_rate_found(iface->conf->supported_rates, + mode->rates[i])) + continue; + + rate = &iface->current_rates[iface->num_rates]; + rate->rate = mode->rates[i]; + if (hostapd_rate_found(basic_rates, rate->rate)) { + rate->flags |= HOSTAPD_RATE_BASIC; + num_basic_rates++; + } + wpa_printf(MSG_DEBUG, "RATE[%d] rate=%d flags=0x%x", + iface->num_rates, rate->rate, rate->flags); + iface->num_rates++; + } + + if ((iface->num_rates == 0 || num_basic_rates == 0) && + (!iface->conf->ieee80211n || !iface->conf->require_ht)) { + wpa_printf(MSG_ERROR, "No rates remaining in supported/basic " + "rate sets (%d,%d).", + iface->num_rates, num_basic_rates); + return -1; + } + + return 0; +} + + +#ifdef CONFIG_IEEE80211N +static int ieee80211n_allowed_ht40_channel_pair(struct hostapd_iface *iface) +{ + int pri_chan, sec_chan; + + if (!iface->conf->secondary_channel) + return 1; /* HT40 not used */ + + pri_chan = iface->conf->channel; + sec_chan = pri_chan + iface->conf->secondary_channel * 4; + + return allowed_ht40_channel_pair(iface->current_mode, pri_chan, + sec_chan); +} + + +static void ieee80211n_switch_pri_sec(struct hostapd_iface *iface) +{ + if (iface->conf->secondary_channel > 0) { + iface->conf->channel += 4; + iface->conf->secondary_channel = -1; + } else { + iface->conf->channel -= 4; + iface->conf->secondary_channel = 1; + } +} + + +static int ieee80211n_check_40mhz_5g(struct hostapd_iface *iface, + struct wpa_scan_results *scan_res) +{ + int pri_chan, sec_chan; + int res; + + pri_chan = iface->conf->channel; + sec_chan = pri_chan + iface->conf->secondary_channel * 4; + + res = check_40mhz_5g(iface->current_mode, scan_res, pri_chan, sec_chan); + + if (res == 2) { + if (iface->conf->no_pri_sec_switch) { + wpa_printf(MSG_DEBUG, + "Cannot switch PRI/SEC channels due to local constraint"); + } else { + ieee80211n_switch_pri_sec(iface); + } + } + + return !!res; +} + + +static int ieee80211n_check_40mhz_2g4(struct hostapd_iface *iface, + struct wpa_scan_results *scan_res) +{ + int pri_chan, sec_chan; + + pri_chan = iface->conf->channel; + sec_chan = pri_chan + iface->conf->secondary_channel * 4; + + return check_40mhz_2g4(iface->current_mode, scan_res, pri_chan, + sec_chan); +} + + +static void ieee80211n_check_scan(struct hostapd_iface *iface) +{ + struct wpa_scan_results *scan_res; + int oper40; + int res; + + /* Check list of neighboring BSSes (from scan) to see whether 40 MHz is + * allowed per IEEE Std 802.11-2012, 10.15.3.2 */ + + iface->scan_cb = NULL; + + scan_res = hostapd_driver_get_scan_results(iface->bss[0]); + if (scan_res == NULL) { + hostapd_setup_interface_complete(iface, 1); + return; + } + + if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A) + oper40 = ieee80211n_check_40mhz_5g(iface, scan_res); + else + oper40 = ieee80211n_check_40mhz_2g4(iface, scan_res); + wpa_scan_results_free(scan_res); + + if (!oper40 && iface->conf->ht_no_overlap_check) { + wpa_printf(MSG_INFO, "Ignore overlapping BSSes"); + oper40 = 1; + } + + iface->secondary_ch = iface->conf->secondary_channel; + if (!oper40) { + wpa_printf(MSG_INFO, "20/40 MHz operation not permitted on " + "channel pri=%d sec=%d based on overlapping BSSes", + iface->conf->channel, + iface->conf->channel + + iface->conf->secondary_channel * 4); + iface->conf->secondary_channel = 0; + if (iface->drv_flags & WPA_DRIVER_FLAGS_HT_2040_COEX) { + /* + * TODO: Could consider scheduling another scan to check + * if channel width can be changed if no coex reports + * are received from associating stations. + */ + } + } + + res = ieee80211n_allowed_ht40_channel_pair(iface); + if (!res) { + iface->conf->secondary_channel = 0; + wpa_printf(MSG_INFO, "Fallback to 20 MHz"); + } + + hostapd_setup_interface_complete(iface, !res); +} + + +static void ieee80211n_scan_channels_2g4(struct hostapd_iface *iface, + struct wpa_driver_scan_params *params) +{ + /* Scan only the affected frequency range */ + int pri_freq, sec_freq; + int affected_start, affected_end; + int i, pos; + struct hostapd_hw_modes *mode; + + if (iface->current_mode == NULL) + return; + + pri_freq = hostapd_hw_get_freq(iface->bss[0], iface->conf->channel); + if (iface->conf->secondary_channel > 0) + sec_freq = pri_freq + 20; + else + sec_freq = pri_freq - 20; + /* + * Note: Need to find the PRI channel also in cases where the affected + * channel is the SEC channel of a 40 MHz BSS, so need to include the + * scanning coverage here to be 40 MHz from the center frequency. + */ + affected_start = (pri_freq + sec_freq) / 2 - 40; + affected_end = (pri_freq + sec_freq) / 2 + 40; + wpa_printf(MSG_DEBUG, "40 MHz affected channel range: [%d,%d] MHz", + affected_start, affected_end); + + mode = iface->current_mode; + params->freqs = os_calloc(mode->num_channels + 1, sizeof(int)); + if (params->freqs == NULL) + return; + pos = 0; + + for (i = 0; i < mode->num_channels; i++) { + struct hostapd_channel_data *chan = &mode->channels[i]; + if (chan->flag & HOSTAPD_CHAN_DISABLED) + continue; + if (chan->freq < affected_start || + chan->freq > affected_end) + continue; + params->freqs[pos++] = chan->freq; + } +} + + +static void ieee80211n_scan_channels_5g(struct hostapd_iface *iface, + struct wpa_driver_scan_params *params) +{ + /* Scan only the affected frequency range */ + int pri_freq; + int affected_start, affected_end; + int i, pos; + struct hostapd_hw_modes *mode; + + if (iface->current_mode == NULL) + return; + + pri_freq = hostapd_hw_get_freq(iface->bss[0], iface->conf->channel); + if (iface->conf->secondary_channel > 0) { + affected_start = pri_freq - 10; + affected_end = pri_freq + 30; + } else { + affected_start = pri_freq - 30; + affected_end = pri_freq + 10; + } + wpa_printf(MSG_DEBUG, "40 MHz affected channel range: [%d,%d] MHz", + affected_start, affected_end); + + mode = iface->current_mode; + params->freqs = os_calloc(mode->num_channels + 1, sizeof(int)); + if (params->freqs == NULL) + return; + pos = 0; + + for (i = 0; i < mode->num_channels; i++) { + struct hostapd_channel_data *chan = &mode->channels[i]; + if (chan->flag & HOSTAPD_CHAN_DISABLED) + continue; + if (chan->freq < affected_start || + chan->freq > affected_end) + continue; + params->freqs[pos++] = chan->freq; + } +} + + +static void ap_ht40_scan_retry(void *eloop_data, void *user_data) +{ +#define HT2040_COEX_SCAN_RETRY 15 + struct hostapd_iface *iface = eloop_data; + struct wpa_driver_scan_params params; + int ret; + + os_memset(¶ms, 0, sizeof(params)); + if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G) + ieee80211n_scan_channels_2g4(iface, ¶ms); + else + ieee80211n_scan_channels_5g(iface, ¶ms); + + ret = hostapd_driver_scan(iface->bss[0], ¶ms); + iface->num_ht40_scan_tries++; + os_free(params.freqs); + + if (ret == -ERRBUSY && + iface->num_ht40_scan_tries < HT2040_COEX_SCAN_RETRY) { + wpa_printf(MSG_ERROR, + "Failed to request a scan of neighboring BSSes ret=%d (%s) - try to scan again (attempt %d)", + ret, strerror(-ret), iface->num_ht40_scan_tries); + eloop_register_timeout(1, 0, ap_ht40_scan_retry, iface, NULL); + return; + } + + if (ret == 0) { + iface->scan_cb = ieee80211n_check_scan; + return; + } + + wpa_printf(MSG_DEBUG, + "Failed to request a scan in device, bringing up in HT20 mode"); + iface->conf->secondary_channel = 0; + iface->conf->ht_capab &= ~HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET; + hostapd_setup_interface_complete(iface, 0); +} + + +void hostapd_stop_setup_timers(struct hostapd_iface *iface) +{ + eloop_cancel_timeout(ap_ht40_scan_retry, iface, NULL); +} + + +static int ieee80211n_check_40mhz(struct hostapd_iface *iface) +{ + struct wpa_driver_scan_params params; + int ret; + + if (!iface->conf->secondary_channel) + return 0; /* HT40 not used */ + + hostapd_set_state(iface, HAPD_IFACE_HT_SCAN); + wpa_printf(MSG_DEBUG, "Scan for neighboring BSSes prior to enabling " + "40 MHz channel"); + os_memset(¶ms, 0, sizeof(params)); + if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G) + ieee80211n_scan_channels_2g4(iface, ¶ms); + else + ieee80211n_scan_channels_5g(iface, ¶ms); + + ret = hostapd_driver_scan(iface->bss[0], ¶ms); + os_free(params.freqs); + + if (ret == -ERRBUSY) { + wpa_printf(MSG_ERROR, + "Failed to request a scan of neighboring BSSes ret=%d (%s) - try to scan again", + ret, strerror(-ret)); + iface->num_ht40_scan_tries = 1; + eloop_cancel_timeout(ap_ht40_scan_retry, iface, NULL); + eloop_register_timeout(1, 0, ap_ht40_scan_retry, iface, NULL); + return 1; + } + + if (ret < 0) { + wpa_printf(MSG_ERROR, + "Failed to request a scan of neighboring BSSes ret=%d (%s)", + ret, strerror(-ret)); + return -1; + } + + iface->scan_cb = ieee80211n_check_scan; + return 1; +} + + +static int ieee80211n_supported_ht_capab(struct hostapd_iface *iface) +{ + u16 hw = iface->current_mode->ht_capab; + u16 conf = iface->conf->ht_capab; + + if ((conf & HT_CAP_INFO_LDPC_CODING_CAP) && + !(hw & HT_CAP_INFO_LDPC_CODING_CAP)) { + wpa_printf(MSG_ERROR, "Driver does not support configured " + "HT capability [LDPC]"); + return 0; + } + + /* + * Driver ACS chosen channel may not be HT40 due to internal driver + * restrictions. + */ + if (!iface->conf->acs && (conf & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) && + !(hw & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) { + wpa_printf(MSG_ERROR, "Driver does not support configured " + "HT capability [HT40*]"); + return 0; + } + + switch (conf & HT_CAP_INFO_SMPS_MASK) { + case HT_CAP_INFO_SMPS_STATIC: + if (!(iface->smps_modes & WPA_DRIVER_SMPS_MODE_STATIC)) { + wpa_printf(MSG_ERROR, + "Driver does not support configured HT capability [SMPS-STATIC]"); + return 0; + } + break; + case HT_CAP_INFO_SMPS_DYNAMIC: + if (!(iface->smps_modes & WPA_DRIVER_SMPS_MODE_DYNAMIC)) { + wpa_printf(MSG_ERROR, + "Driver does not support configured HT capability [SMPS-DYNAMIC]"); + return 0; + } + break; + case HT_CAP_INFO_SMPS_DISABLED: + default: + break; + } + + if ((conf & HT_CAP_INFO_GREEN_FIELD) && + !(hw & HT_CAP_INFO_GREEN_FIELD)) { + wpa_printf(MSG_ERROR, "Driver does not support configured " + "HT capability [GF]"); + return 0; + } + + if ((conf & HT_CAP_INFO_SHORT_GI20MHZ) && + !(hw & HT_CAP_INFO_SHORT_GI20MHZ)) { + wpa_printf(MSG_ERROR, "Driver does not support configured " + "HT capability [SHORT-GI-20]"); + return 0; + } + + if ((conf & HT_CAP_INFO_SHORT_GI40MHZ) && + !(hw & HT_CAP_INFO_SHORT_GI40MHZ)) { + wpa_printf(MSG_ERROR, "Driver does not support configured " + "HT capability [SHORT-GI-40]"); + return 0; + } + + if ((conf & HT_CAP_INFO_TX_STBC) && !(hw & HT_CAP_INFO_TX_STBC)) { + wpa_printf(MSG_ERROR, "Driver does not support configured " + "HT capability [TX-STBC]"); + return 0; + } + + if ((conf & HT_CAP_INFO_RX_STBC_MASK) > + (hw & HT_CAP_INFO_RX_STBC_MASK)) { + wpa_printf(MSG_ERROR, "Driver does not support configured " + "HT capability [RX-STBC*]"); + return 0; + } + + if ((conf & HT_CAP_INFO_DELAYED_BA) && + !(hw & HT_CAP_INFO_DELAYED_BA)) { + wpa_printf(MSG_ERROR, "Driver does not support configured " + "HT capability [DELAYED-BA]"); + return 0; + } + + if ((conf & HT_CAP_INFO_MAX_AMSDU_SIZE) && + !(hw & HT_CAP_INFO_MAX_AMSDU_SIZE)) { + wpa_printf(MSG_ERROR, "Driver does not support configured " + "HT capability [MAX-AMSDU-7935]"); + return 0; + } + + if ((conf & HT_CAP_INFO_DSSS_CCK40MHZ) && + !(hw & HT_CAP_INFO_DSSS_CCK40MHZ)) { + wpa_printf(MSG_ERROR, "Driver does not support configured " + "HT capability [DSSS_CCK-40]"); + return 0; + } + + if ((conf & HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT) && + !(hw & HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT)) { + wpa_printf(MSG_ERROR, "Driver does not support configured " + "HT capability [LSIG-TXOP-PROT]"); + return 0; + } + + return 1; +} + + +#ifdef CONFIG_IEEE80211AC + +static int ieee80211ac_cap_check(u32 hw, u32 conf, u32 cap, const char *name) +{ + u32 req_cap = conf & cap; + + /* + * Make sure we support all requested capabilities. + * NOTE: We assume that 'cap' represents a capability mask, + * not a discrete value. + */ + if ((hw & req_cap) != req_cap) { + wpa_printf(MSG_ERROR, "Driver does not support configured VHT capability [%s]", + name); + return 0; + } + return 1; +} + + +static int ieee80211ac_cap_check_max(u32 hw, u32 conf, u32 mask, + unsigned int shift, + const char *name) +{ + u32 hw_max = hw & mask; + u32 conf_val = conf & mask; + + if (conf_val > hw_max) { + wpa_printf(MSG_ERROR, "Configured VHT capability [%s] exceeds max value supported by the driver (%d > %d)", + name, conf_val >> shift, hw_max >> shift); + return 0; + } + return 1; +} + + +static int ieee80211ac_supported_vht_capab(struct hostapd_iface *iface) +{ + struct hostapd_hw_modes *mode = iface->current_mode; + u32 hw = mode->vht_capab; + u32 conf = iface->conf->vht_capab; + + wpa_printf(MSG_DEBUG, "hw vht capab: 0x%x, conf vht capab: 0x%x", + hw, conf); + + if (mode->mode == HOSTAPD_MODE_IEEE80211G && + iface->conf->bss[0]->vendor_vht && + mode->vht_capab == 0 && iface->hw_features) { + int i; + + for (i = 0; i < iface->num_hw_features; i++) { + if (iface->hw_features[i].mode == + HOSTAPD_MODE_IEEE80211A) { + mode = &iface->hw_features[i]; + hw = mode->vht_capab; + wpa_printf(MSG_DEBUG, + "update hw vht capab based on 5 GHz band: 0x%x", + hw); + break; + } + } + } + +#define VHT_CAP_CHECK(cap) \ + do { \ + if (!ieee80211ac_cap_check(hw, conf, cap, #cap)) \ + return 0; \ + } while (0) + +#define VHT_CAP_CHECK_MAX(cap) \ + do { \ + if (!ieee80211ac_cap_check_max(hw, conf, cap, cap ## _SHIFT, \ + #cap)) \ + return 0; \ + } while (0) + + VHT_CAP_CHECK_MAX(VHT_CAP_MAX_MPDU_LENGTH_MASK); + VHT_CAP_CHECK(VHT_CAP_SUPP_CHAN_WIDTH_160MHZ); + VHT_CAP_CHECK(VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ); + VHT_CAP_CHECK(VHT_CAP_RXLDPC); + VHT_CAP_CHECK(VHT_CAP_SHORT_GI_80); + VHT_CAP_CHECK(VHT_CAP_SHORT_GI_160); + VHT_CAP_CHECK(VHT_CAP_TXSTBC); + VHT_CAP_CHECK_MAX(VHT_CAP_RXSTBC_MASK); + VHT_CAP_CHECK(VHT_CAP_SU_BEAMFORMER_CAPABLE); + VHT_CAP_CHECK(VHT_CAP_SU_BEAMFORMEE_CAPABLE); + VHT_CAP_CHECK_MAX(VHT_CAP_BEAMFORMEE_STS_MAX); + VHT_CAP_CHECK_MAX(VHT_CAP_SOUNDING_DIMENSION_MAX); + VHT_CAP_CHECK(VHT_CAP_MU_BEAMFORMER_CAPABLE); + VHT_CAP_CHECK(VHT_CAP_MU_BEAMFORMEE_CAPABLE); + VHT_CAP_CHECK(VHT_CAP_VHT_TXOP_PS); + VHT_CAP_CHECK(VHT_CAP_HTC_VHT); + VHT_CAP_CHECK_MAX(VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX); + VHT_CAP_CHECK(VHT_CAP_VHT_LINK_ADAPTATION_VHT_UNSOL_MFB); + VHT_CAP_CHECK(VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB); + VHT_CAP_CHECK(VHT_CAP_RX_ANTENNA_PATTERN); + VHT_CAP_CHECK(VHT_CAP_TX_ANTENNA_PATTERN); + +#undef VHT_CAP_CHECK +#undef VHT_CAP_CHECK_MAX + + return 1; +} +#endif /* CONFIG_IEEE80211AC */ + +#endif /* CONFIG_IEEE80211N */ + + +int hostapd_check_ht_capab(struct hostapd_iface *iface) +{ +#ifdef CONFIG_IEEE80211N + int ret; + if (!iface->conf->ieee80211n) + return 0; + + if (iface->current_mode->mode != HOSTAPD_MODE_IEEE80211B && + iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G && + (iface->conf->ht_capab & HT_CAP_INFO_DSSS_CCK40MHZ)) { + wpa_printf(MSG_DEBUG, + "Disable HT capability [DSSS_CCK-40] on 5 GHz band"); + iface->conf->ht_capab &= ~HT_CAP_INFO_DSSS_CCK40MHZ; + } + + if (!ieee80211n_supported_ht_capab(iface)) + return -1; +#ifdef CONFIG_IEEE80211AC + if (!ieee80211ac_supported_vht_capab(iface)) + return -1; +#endif /* CONFIG_IEEE80211AC */ + ret = ieee80211n_check_40mhz(iface); + if (ret) + return ret; + if (!ieee80211n_allowed_ht40_channel_pair(iface)) + return -1; +#endif /* CONFIG_IEEE80211N */ + + return 0; +} + + +static int hostapd_is_usable_chan(struct hostapd_iface *iface, + int channel, int primary) +{ + int i; + struct hostapd_channel_data *chan; + + if (!iface->current_mode) + return 0; + + for (i = 0; i < iface->current_mode->num_channels; i++) { + chan = &iface->current_mode->channels[i]; + if (chan->chan != channel) + continue; + + if (!(chan->flag & HOSTAPD_CHAN_DISABLED)) + return 1; + + wpa_printf(MSG_DEBUG, + "%schannel [%i] (%i) is disabled for use in AP mode, flags: 0x%x%s%s", + primary ? "" : "Configured HT40 secondary ", + i, chan->chan, chan->flag, + chan->flag & HOSTAPD_CHAN_NO_IR ? " NO-IR" : "", + chan->flag & HOSTAPD_CHAN_RADAR ? " RADAR" : ""); + } + + return 0; +} + + +static int hostapd_is_usable_chans(struct hostapd_iface *iface) +{ + if (!hostapd_is_usable_chan(iface, iface->conf->channel, 1)) + return 0; + + if (!iface->conf->secondary_channel) + return 1; + + return hostapd_is_usable_chan(iface, iface->conf->channel + + iface->conf->secondary_channel * 4, 0); +} + + +static enum hostapd_chan_status +hostapd_check_chans(struct hostapd_iface *iface) +{ + iface->conf->channel = g_ap_param_ptr->chann; + + if (iface->conf->channel) { + if (hostapd_is_usable_chans(iface)) + return HOSTAPD_CHAN_VALID; + else + return HOSTAPD_CHAN_INVALID; + } + + /* + * The user set channel=0 or channel=acs_survey + * which is used to trigger ACS. + */ + + switch (acs_init(iface)) { + case HOSTAPD_CHAN_ACS: + return HOSTAPD_CHAN_ACS; + case HOSTAPD_CHAN_VALID: + case HOSTAPD_CHAN_INVALID: + default: + return HOSTAPD_CHAN_INVALID; + } +} + + +static void hostapd_notify_bad_chans(struct hostapd_iface *iface) +{ + if (!iface->current_mode) { + hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_WARNING, + "Hardware does not support configured mode"); + return; + } + hostapd_logger(iface->bss[0], NULL, + HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_WARNING, + "Configured channel (%d) not found from the " + "channel list of current mode (%d) %s", + iface->conf->channel, + iface->current_mode->mode, + hostapd_hw_mode_txt(iface->current_mode->mode)); + hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_WARNING, + "Hardware does not support configured channel"); +} + + +int hostapd_acs_completed(struct hostapd_iface *iface, int err) +{ + int ret = -1; + + if (err) + goto out; + + switch (hostapd_check_chans(iface)) { + case HOSTAPD_CHAN_VALID: + wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, + ACS_EVENT_COMPLETED "freq=%d channel=%d", + hostapd_hw_get_freq(iface->bss[0], + iface->conf->channel), + iface->conf->channel); + break; + case HOSTAPD_CHAN_ACS: + wpa_printf(MSG_ERROR, "ACS error - reported complete, but no result available"); + wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, ACS_EVENT_FAILED); + hostapd_notify_bad_chans(iface); + goto out; + case HOSTAPD_CHAN_INVALID: + default: + wpa_printf(MSG_ERROR, "ACS picked unusable channels"); + wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, ACS_EVENT_FAILED); + hostapd_notify_bad_chans(iface); + goto out; + } + + ret = hostapd_check_ht_capab(iface); + if (ret < 0) + goto out; + if (ret == 1) { + wpa_printf(MSG_DEBUG, "Interface initialization will be completed in a callback"); + return 0; + } + + ret = 0; +out: + return hostapd_setup_interface_complete(iface, ret); +} + + +/** + * hostapd_select_hw_mode - Select the hardware mode + * @iface: Pointer to interface data. + * Returns: 0 on success, < 0 on failure + * + * Sets up the hardware mode, channel, rates, and passive scanning + * based on the configuration. + */ +int hostapd_select_hw_mode(struct hostapd_iface *iface) +{ + int i; + + if (iface->num_hw_features < 1) + return -1; + + if ((iface->conf->hw_mode == HOSTAPD_MODE_IEEE80211G || + iface->conf->ieee80211n || iface->conf->ieee80211ac) && + iface->conf->channel == 14) { + wpa_printf(MSG_INFO, "Disable OFDM/HT/VHT on channel 14"); + iface->conf->hw_mode = HOSTAPD_MODE_IEEE80211B; + iface->conf->ieee80211n = 0; + iface->conf->ieee80211ac = 0; + } + + iface->current_mode = NULL; + for (i = 0; i < iface->num_hw_features; i++) { + struct hostapd_hw_modes *mode = &iface->hw_features[i]; + if (mode->mode == iface->conf->hw_mode) { + iface->current_mode = mode; + break; + } + } + + if (iface->current_mode == NULL) { + if (!(iface->drv_flags & WPA_DRIVER_FLAGS_ACS_OFFLOAD) || + !(iface->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_HW_MODE_ANY)) + { + wpa_printf(MSG_ERROR, + "Hardware does not support configured mode"); + hostapd_logger(iface->bss[0], NULL, + HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_WARNING, + "Hardware does not support configured mode (%d) (hw_mode in hostapd.conf)", + (int) iface->conf->hw_mode); + return -2; + } + } + + switch (hostapd_check_chans(iface)) { + case HOSTAPD_CHAN_VALID: + return 0; + case HOSTAPD_CHAN_ACS: /* ACS will run and later complete */ + return 1; + case HOSTAPD_CHAN_INVALID: + default: + hostapd_notify_bad_chans(iface); + return -3; + } +} + + +const char * hostapd_hw_mode_txt(int mode) +{ + switch (mode) { + case HOSTAPD_MODE_IEEE80211A: + return "IEEE 802.11a"; + case HOSTAPD_MODE_IEEE80211B: + return "IEEE 802.11b"; + case HOSTAPD_MODE_IEEE80211G: + return "IEEE 802.11g"; + case HOSTAPD_MODE_IEEE80211AD: + return "IEEE 802.11ad"; + default: + return "UNKNOWN"; + } +} + +int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan) +{ + return hw_get_freq(hapd->iface->current_mode, chan); +} + +int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq) +{ + return hw_get_chan(hapd->iface->current_mode, freq); +} +// eof + diff --git a/beken_os/beken378/func/hostapd-2.5/src/ap/hw_features.h b/beken_os/beken378/func/hostapd-2.5/src/ap/hw_features.h new file mode 100755 index 0000000..ca7f22b --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/ap/hw_features.h @@ -0,0 +1,76 @@ +/* + * hostapd / Hardware feature query and different modes + * Copyright 2002-2003, Instant802 Networks, Inc. + * Copyright 2005-2006, Devicescape Software, Inc. + * Copyright (c) 2008-2011, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef HW_FEATURES_H +#define HW_FEATURES_H + +#ifdef NEED_AP_MLME +void hostapd_free_hw_features(struct hostapd_hw_modes *hw_features, + size_t num_hw_features); +int hostapd_get_hw_features(struct hostapd_iface *iface); +int hostapd_acs_completed(struct hostapd_iface *iface, int err); +int hostapd_select_hw_mode(struct hostapd_iface *iface); +const char * hostapd_hw_mode_txt(int mode); +int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan); +int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq); +int hostapd_check_ht_capab(struct hostapd_iface *iface); +int hostapd_prepare_rates(struct hostapd_iface *iface, + struct hostapd_hw_modes *mode); +void hostapd_stop_setup_timers(struct hostapd_iface *iface); +#else /* NEED_AP_MLME */ +static inline void +hostapd_free_hw_features(struct hostapd_hw_modes *hw_features, + size_t num_hw_features) +{ +} + +static inline int hostapd_get_hw_features(struct hostapd_iface *iface) +{ + return -1; +} + +static inline int hostapd_acs_completed(struct hostapd_iface *iface, int err) +{ + return -1; +} + +static inline int hostapd_select_hw_mode(struct hostapd_iface *iface) +{ + return -100; +} + +static inline const char * hostapd_hw_mode_txt(int mode) +{ + return NULL; +} + +static inline int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan) +{ + return -1; +} + +static inline int hostapd_check_ht_capab(struct hostapd_iface *iface) +{ + return 0; +} + +static inline int hostapd_prepare_rates(struct hostapd_iface *iface, + struct hostapd_hw_modes *mode) +{ + return 0; +} + +static inline void hostapd_stop_setup_timers(struct hostapd_iface *iface) +{ +} + +#endif /* NEED_AP_MLME */ + +#endif /* HW_FEATURES_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/ap/ieee802_11.c b/beken_os/beken378/func/hostapd-2.5/src/ap/ieee802_11.c new file mode 100755 index 0000000..7943c1a --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/ap/ieee802_11.c @@ -0,0 +1,2790 @@ +/* + * hostapd / IEEE 802.11 Management + * Copyright (c) 2002-2014, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "include.h" +#include "uart_pub.h" + +#include "includes.h" + + #include "utils/common.h" +#include "utils/eloop.h" +#include "crypto/crypto.h" +#include "crypto/sha256.h" +#include "crypto/random.h" +#include "common/ieee802_11_defs.h" +#include "common/ieee802_11_common.h" +#include "common/wpa_ctrl.h" +#include "common/sae.h" +#include "wps/wps.h" +#include "ap/hostapd.h" +#include "beacon.h" +#include "ieee802_11_auth.h" +#include "ap/sta_info.h" +#include "ieee802_1x.h" +#include "wpa_auth.h" +#include "wmm.h" +#include "ap_list.h" +#include "accounting.h" +#include "ap_config.h" +#include "ap_mlme.h" +#include "p2p_hostapd.h" +#include "ap_drv_ops.h" +#include "hw_features.h" +#include "ieee802_11.h" +#include "ap/dfs.h" + + +u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid) +{ + u8 *pos = eid; + int i, num, count; + + if (hapd->iface->current_rates == NULL) + return eid; + + *pos++ = WLAN_EID_SUPP_RATES; + num = hapd->iface->num_rates; + if (hapd->iconf->ieee80211n && hapd->iconf->require_ht) + num++; + if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht) + num++; + if (num > 8) { + /* rest of the rates are encoded in Extended supported + * rates element */ + num = 8; + } + + *pos++ = num; + for (i = 0, count = 0; i < hapd->iface->num_rates && count < num; + i++) { + count++; + *pos = hapd->iface->current_rates[i].rate / 5; + if (hapd->iface->current_rates[i].flags & HOSTAPD_RATE_BASIC) + *pos |= 0x80; + pos++; + } + + if (hapd->iconf->ieee80211n && hapd->iconf->require_ht && count < 8) { + count++; + *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_HT_PHY; + } + + if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht && count < 8) { + count++; + *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_VHT_PHY; + } + + return pos; +} + + +u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid) +{ + u8 *pos = eid; + int i, num, count; + + if (hapd->iface->current_rates == NULL) + return eid; + + num = hapd->iface->num_rates; + if (hapd->iconf->ieee80211n && hapd->iconf->require_ht) + num++; + if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht) + num++; + if (num <= 8) + return eid; + num -= 8; + + *pos++ = WLAN_EID_EXT_SUPP_RATES; + *pos++ = num; + for (i = 0, count = 0; i < hapd->iface->num_rates && count < num + 8; + i++) { + count++; + if (count <= 8) + continue; /* already in SuppRates IE */ + *pos = hapd->iface->current_rates[i].rate / 5; + if (hapd->iface->current_rates[i].flags & HOSTAPD_RATE_BASIC) + *pos |= 0x80; + pos++; + } + + if (hapd->iconf->ieee80211n && hapd->iconf->require_ht) { + count++; + if (count > 8) + *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_HT_PHY; + } + + if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht) { + count++; + if (count > 8) + *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_VHT_PHY; + } + + return pos; +} + + +u16 hostapd_own_capab_info(struct hostapd_data *hapd) +{ + int capab = WLAN_CAPABILITY_ESS; + int privacy; + int dfs = 0; + +#ifdef CONFIG_DFS + /* Check if any of configured channels require DFS */ + dfs = hostapd_is_dfs_required(hapd->iface); + if (dfs < 0) { + wpa_printf(MSG_WARNING, "Failed to check if DFS is required; ret=%d", + dfs); + dfs = 0; + } +#endif +#if 1 //wangzhilei + hapd->iface->num_sta_no_short_preamble = 0; + hapd->iconf->preamble = SHORT_PREAMBLE; +#endif + + if (hapd->iface->num_sta_no_short_preamble == 0 && + hapd->iconf->preamble == SHORT_PREAMBLE) + capab |= WLAN_CAPABILITY_SHORT_PREAMBLE; + + privacy = hapd->conf->ssid.wep.keys_set; + + if (hapd->conf->ieee802_1x && + (hapd->conf->default_wep_key_len || + hapd->conf->individual_wep_key_len)) + privacy = 1; + + if (hapd->conf->wpa) + privacy = 1; + +#ifdef CONFIG_HS20 + if (hapd->conf->osen) + privacy = 1; +#endif /* CONFIG_HS20 */ + + if (privacy) + capab |= WLAN_CAPABILITY_PRIVACY; + +#if 0 //wangzhilei + if (hapd->iface->current_mode && + hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G && + hapd->iface->num_sta_no_short_slot_time == 0) +#endif + capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME; + + /* + * Currently, Spectrum Management capability bit is set when directly + * requested in configuration by spectrum_mgmt_required or when AP is + * running on DFS channel. + * TODO: Also consider driver support for TPC to set Spectrum Mgmt bit + */ + if (hapd->iface->current_mode && + hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A && + (hapd->iconf->spectrum_mgmt_required || dfs)) + capab |= WLAN_CAPABILITY_SPECTRUM_MGMT; + + if (hapd->conf->radio_measurements) + capab |= IEEE80211_CAP_RRM; + + return capab; +} + + +#ifndef CONFIG_NO_RC4 +static u16 auth_shared_key(struct hostapd_data *hapd, struct sta_info *sta, + u16 auth_transaction, const u8 *challenge, + int iswep) +{ + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "authentication (shared key, transaction %d)", + auth_transaction); + + if (auth_transaction == 1) { + if (!sta->challenge) { + /* Generate a pseudo-random challenge */ + u8 key[8]; + struct os_time now; + int r; + sta->challenge = os_zalloc(WLAN_AUTH_CHALLENGE_LEN); + if (sta->challenge == NULL) + return WLAN_STATUS_UNSPECIFIED_FAILURE; + + os_get_time(&now); + r = os_random(); + os_memcpy(key, &now.sec, 4); + os_memcpy(key + 4, &r, 4); + rc4_skip(key, sizeof(key), 0, sta->challenge, WLAN_AUTH_CHALLENGE_LEN); + } + return 0; + } + + if (auth_transaction != 3) + return WLAN_STATUS_UNSPECIFIED_FAILURE; + + /* Transaction 3 */ + if (!iswep || !sta->challenge || !challenge || + os_memcmp_const(sta->challenge, challenge, + WLAN_AUTH_CHALLENGE_LEN)) { + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, + "shared key authentication - invalid " + "challenge-response"); + return WLAN_STATUS_CHALLENGE_FAIL; + } + + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "authentication OK (shared key)"); + sta->flags |= WLAN_STA_AUTH; + wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH); + os_free(sta->challenge); + sta->challenge = NULL; + + return 0; +} +#endif /* CONFIG_NO_RC4 */ + + +static void send_auth_reply(struct hostapd_data *hapd, + const u8 *dst, const u8 *bssid, + u16 auth_alg, u16 auth_transaction, u16 resp, + const u8 *ies, size_t ies_len) +{ + struct ieee80211_mgmt *reply; + u8 *buf; + size_t rlen; + + rlen = IEEE80211_HDRLEN + sizeof(reply->u.auth) - VARIABLE_ARRAY_SPARE + ies_len; + buf = os_zalloc(rlen); + if (buf == NULL) + return; + + reply = (struct ieee80211_mgmt *) buf; + reply->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, + WLAN_FC_STYPE_AUTH); + os_memcpy(reply->da, dst, ETH_ALEN); + os_memcpy(reply->sa, hapd->own_addr, ETH_ALEN); + os_memcpy(reply->bssid, bssid, ETH_ALEN); + + reply->u.auth.auth_alg = host_to_le16(auth_alg); + reply->u.auth.auth_transaction = host_to_le16(auth_transaction); + reply->u.auth.status_code = host_to_le16(resp); + + if (ies && ies_len) + os_memcpy(reply->u.auth.variable, ies, ies_len); + + wpa_printf(MSG_DEBUG, "authentication reply: STA=" MACSTR + " auth_alg=%d auth_transaction=%d resp=%d (IE len=%lu)", + MAC2STR(dst), auth_alg, auth_transaction, + resp, (unsigned long) ies_len); + if (hostapd_drv_send_mlme(hapd, reply, rlen, 0) < 0) + wpa_printf(MSG_INFO, "send_auth_reply: send"); + + os_free(buf); +} + + +#ifdef CONFIG_IEEE80211R +static void handle_auth_ft_finish(void *ctx, const u8 *dst, const u8 *bssid, + u16 auth_transaction, u16 status, + const u8 *ies, size_t ies_len) +{ + struct hostapd_data *hapd = ctx; + struct sta_info *sta; + + send_auth_reply(hapd, dst, bssid, WLAN_AUTH_FT, auth_transaction, + status, ies, ies_len); + + if (status != WLAN_STATUS_SUCCESS) + return; + + sta = ap_get_sta(hapd, dst); + if (sta == NULL) + return; + + hostapd_logger(hapd, dst, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, "authentication OK (FT)"); + sta->flags |= WLAN_STA_AUTH; + mlme_authenticate_indication(hapd, sta); +} +#endif /* CONFIG_IEEE80211R */ + + +#ifdef CONFIG_SAE + +#define dot11RSNASAESync 5 /* attempts */ + + +static struct wpabuf * auth_build_sae_commit(struct hostapd_data *hapd, + struct sta_info *sta, int update) +{ + struct wpabuf *buf; + + if (hapd->conf->ssid.wpa_passphrase == NULL) { + wpa_printf(MSG_DEBUG, "SAE: No password available"); + return NULL; + } + + if (update && + sae_prepare_commit(hapd->own_addr, sta->addr, + (u8 *) hapd->conf->ssid.wpa_passphrase, + os_strlen(hapd->conf->ssid.wpa_passphrase), + sta->sae) < 0) { + wpa_printf(MSG_DEBUG, "SAE: Could not pick PWE"); + return NULL; + } + + buf = wpabuf_alloc(SAE_COMMIT_MAX_LEN); + if (buf == NULL) + return NULL; + sae_write_commit(sta->sae, buf, sta->sae->tmp ? + sta->sae->tmp->anti_clogging_token : NULL); + + return buf; +} + + +static struct wpabuf * auth_build_sae_confirm(struct hostapd_data *hapd, + struct sta_info *sta) +{ + struct wpabuf *buf; + + buf = wpabuf_alloc(SAE_CONFIRM_MAX_LEN); + if (buf == NULL) + return NULL; + + sae_write_confirm(sta->sae, buf); + + return buf; +} + + +static int auth_sae_send_commit(struct hostapd_data *hapd, + struct sta_info *sta, + const u8 *bssid, int update) +{ + struct wpabuf *data; + + data = auth_build_sae_commit(hapd, sta, update); + if (data == NULL) + return WLAN_STATUS_UNSPECIFIED_FAILURE; + + send_auth_reply(hapd, sta->addr, bssid, + WLAN_AUTH_SAE, 1, WLAN_STATUS_SUCCESS, + wpabuf_head(data), wpabuf_len(data)); + + wpabuf_free(data); + + return WLAN_STATUS_SUCCESS; +} + + +static int auth_sae_send_confirm(struct hostapd_data *hapd, + struct sta_info *sta, + const u8 *bssid) +{ + struct wpabuf *data; + + data = auth_build_sae_confirm(hapd, sta); + if (data == NULL) + return WLAN_STATUS_UNSPECIFIED_FAILURE; + + send_auth_reply(hapd, sta->addr, bssid, + WLAN_AUTH_SAE, 2, WLAN_STATUS_SUCCESS, + wpabuf_head(data), wpabuf_len(data)); + + wpabuf_free(data); + + return WLAN_STATUS_SUCCESS; +} + + +static int use_sae_anti_clogging(struct hostapd_data *hapd) +{ + struct sta_info *sta; + unsigned int open = 0; + + if (hapd->conf->sae_anti_clogging_threshold == 0) + return 1; + + for (sta = hapd->sta_list; sta; sta = sta->next) { + if (!sta->sae) + continue; + if (sta->sae->state != SAE_COMMITTED && + sta->sae->state != SAE_CONFIRMED) + continue; + open++; + if (open >= hapd->conf->sae_anti_clogging_threshold) + return 1; + } + + return 0; +} + + +static int check_sae_token(struct hostapd_data *hapd, const u8 *addr, + const u8 *token, size_t token_len) +{ + u8 mac[SHA256_MAC_LEN]; + + if (token_len != SHA256_MAC_LEN) + return -1; + if (hmac_sha256(hapd->sae_token_key, sizeof(hapd->sae_token_key), + addr, ETH_ALEN, mac) < 0 || + os_memcmp_const(token, mac, SHA256_MAC_LEN) != 0) + return -1; + + return 0; +} + + +static struct wpabuf * auth_build_token_req(struct hostapd_data *hapd, + int group, const u8 *addr) +{ + struct wpabuf *buf; + u8 *token; + struct os_reltime now; + + os_get_reltime(&now); + if (!os_reltime_initialized(&hapd->last_sae_token_key_update) || + os_reltime_expired(&now, &hapd->last_sae_token_key_update, 60)) { + if (random_get_bytes(hapd->sae_token_key, + sizeof(hapd->sae_token_key)) < 0) + return NULL; + wpa_hexdump(MSG_DEBUG, "SAE: Updated token key", + hapd->sae_token_key, sizeof(hapd->sae_token_key)); + hapd->last_sae_token_key_update = now; + } + + buf = wpabuf_alloc(sizeof(le16) + SHA256_MAC_LEN); + if (buf == NULL) + return NULL; + + wpabuf_put_le16(buf, group); /* Finite Cyclic Group */ + + token = wpabuf_put(buf, SHA256_MAC_LEN); + hmac_sha256(hapd->sae_token_key, sizeof(hapd->sae_token_key), + addr, ETH_ALEN, token); + + return buf; +} + + +static int sae_check_big_sync(struct sta_info *sta) +{ + if (sta->sae->sync > dot11RSNASAESync) { + sta->sae->state = SAE_NOTHING; + sta->sae->sync = 0; + return -1; + } + return 0; +} + + +static void auth_sae_retransmit_timer(void *eloop_ctx, void *eloop_data) +{ + struct hostapd_data *hapd = eloop_ctx; + struct sta_info *sta = eloop_data; + int ret; + + if (sae_check_big_sync(sta)) + return; + sta->sae->sync++; + + switch (sta->sae->state) { + case SAE_COMMITTED: + ret = auth_sae_send_commit(hapd, sta, hapd->own_addr, 0); + eloop_register_timeout(0, + hapd->dot11RSNASAERetransPeriod * 1000, + auth_sae_retransmit_timer, hapd, sta); + break; + case SAE_CONFIRMED: + ret = auth_sae_send_confirm(hapd, sta, hapd->own_addr); + eloop_register_timeout(0, + hapd->dot11RSNASAERetransPeriod * 1000, + auth_sae_retransmit_timer, hapd, sta); + break; + default: + ret = -1; + break; + } + + if (ret != WLAN_STATUS_SUCCESS) + wpa_printf(MSG_INFO, "SAE: Failed to retransmit: ret=%d", ret); +} + + +void sae_clear_retransmit_timer(struct hostapd_data *hapd, struct sta_info *sta) +{ + eloop_cancel_timeout(auth_sae_retransmit_timer, hapd, sta); +} + + +static void sae_set_retransmit_timer(struct hostapd_data *hapd, + struct sta_info *sta) +{ + if (!(hapd->conf->mesh & MESH_ENABLED)) + return; + + eloop_cancel_timeout(auth_sae_retransmit_timer, hapd, sta); + eloop_register_timeout(0, hapd->dot11RSNASAERetransPeriod * 1000, + auth_sae_retransmit_timer, hapd, sta); +} + + +static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *bssid, u8 auth_transaction) +{ + int ret; + + if (auth_transaction != 1 && auth_transaction != 2) + return WLAN_STATUS_UNSPECIFIED_FAILURE; + + switch (sta->sae->state) { + case SAE_NOTHING: + if (auth_transaction == 1) { + ret = auth_sae_send_commit(hapd, sta, bssid, 1); + if (ret) + return ret; + sta->sae->state = SAE_COMMITTED; + + if (sae_process_commit(sta->sae) < 0) + return WLAN_STATUS_UNSPECIFIED_FAILURE; + + /* + * In mesh case, both Commit and Confirm can be sent + * immediately. In infrastructure BSS, only a single + * Authentication frame (Commit) is expected from the AP + * here and the second one (Confirm) will be sent once + * the STA has sent its second Authentication frame + * (Confirm). + */ + if (hapd->conf->mesh & MESH_ENABLED) { + /* + * Send both Commit and Confirm immediately + * based on SAE finite state machine + * Nothing -> Confirm transition. + */ + ret = auth_sae_send_confirm(hapd, sta, bssid); + if (ret) + return ret; + sta->sae->state = SAE_CONFIRMED; + } else { + /* + * For infrastructure BSS, send only the Commit + * message now to get alternating sequence of + * Authentication frames between the AP and STA. + * Confirm will be sent in + * Commited -> Confirmed/Accepted transition + * when receiving Confirm from STA. + */ + } + sta->sae->sync = 0; + sae_set_retransmit_timer(hapd, sta); + } else { + hostapd_logger(hapd, sta->addr, + HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "SAE confirm before commit"); + } + break; + case SAE_COMMITTED: + sae_clear_retransmit_timer(hapd, sta); + if (auth_transaction == 1) { + if (sae_process_commit(sta->sae) < 0) + return WLAN_STATUS_UNSPECIFIED_FAILURE; + + ret = auth_sae_send_confirm(hapd, sta, bssid); + if (ret) + return ret; + sta->sae->state = SAE_CONFIRMED; + sta->sae->sync = 0; + sae_set_retransmit_timer(hapd, sta); + } else if (hapd->conf->mesh & MESH_ENABLED) { + /* + * In mesh case, follow SAE finite state machine and + * send Commit now, if sync count allows. + */ + if (sae_check_big_sync(sta)) + return WLAN_STATUS_SUCCESS; + sta->sae->sync++; + + ret = auth_sae_send_commit(hapd, sta, bssid, 0); + if (ret) + return ret; + + sae_set_retransmit_timer(hapd, sta); + } else { + /* + * For instructure BSS, send the postponed Confirm from + * Nothing -> Confirmed transition that was reduced to + * Nothing -> Committed above. + */ + ret = auth_sae_send_confirm(hapd, sta, bssid); + if (ret) + return ret; + + sta->sae->state = SAE_CONFIRMED; + + /* + * Since this was triggered on Confirm RX, run another + * step to get to Accepted without waiting for + * additional events. + */ + return sae_sm_step(hapd, sta, bssid, auth_transaction); + } + break; + case SAE_CONFIRMED: + sae_clear_retransmit_timer(hapd, sta); + if (auth_transaction == 1) { + if (sae_check_big_sync(sta)) + return WLAN_STATUS_SUCCESS; + sta->sae->sync++; + + ret = auth_sae_send_commit(hapd, sta, bssid, 1); + if (ret) + return ret; + + if (sae_process_commit(sta->sae) < 0) + return WLAN_STATUS_UNSPECIFIED_FAILURE; + + ret = auth_sae_send_confirm(hapd, sta, bssid); + if (ret) + return ret; + + sae_set_retransmit_timer(hapd, sta); + } else { + sta->flags |= WLAN_STA_AUTH; + sta->auth_alg = WLAN_AUTH_SAE; + mlme_authenticate_indication(hapd, sta); + wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH); + sta->sae->state = SAE_ACCEPTED; + wpa_auth_pmksa_add_sae(hapd->wpa_auth, sta->addr, + sta->sae->pmk); + } + break; + case SAE_ACCEPTED: + if (auth_transaction == 1) { + wpa_printf(MSG_DEBUG, "SAE: remove the STA (" MACSTR + ") doing reauthentication", + MAC2STR(sta->addr)); + ap_free_sta(hapd, sta); + } else { + if (sae_check_big_sync(sta)) + return WLAN_STATUS_SUCCESS; + sta->sae->sync++; + + ret = auth_sae_send_confirm(hapd, sta, bssid); + sae_clear_temp_data(sta->sae); + if (ret) + return ret; + } + break; + default: + wpa_printf(MSG_ERROR, "SAE: invalid state %d", + sta->sae->state); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + return WLAN_STATUS_SUCCESS; +} + + +static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta, + const struct ieee80211_mgmt *mgmt, size_t len, + u16 auth_transaction, u16 status_code) +{ + u16 resp = WLAN_STATUS_SUCCESS; + struct wpabuf *data = NULL; + + if (!sta->sae) { + if (auth_transaction != 1 || status_code != WLAN_STATUS_SUCCESS) + return; + sta->sae = os_zalloc(sizeof(*sta->sae)); + if (sta->sae == NULL) + return; + sta->sae->state = SAE_NOTHING; + sta->sae->sync = 0; + } + + if (auth_transaction == 1) { + const u8 *token = NULL, *pos, *end; + size_t token_len = 0; + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "start SAE authentication (RX commit, status=%u)", + status_code); + + if ((hapd->conf->mesh & MESH_ENABLED) && + status_code == WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ && + sta->sae->tmp) { + pos = mgmt->u.auth.variable; + end = ((const u8 *) mgmt) + len; + if (pos + sizeof(le16) > end) { + wpa_printf(MSG_ERROR, + "SAE: Too short anti-clogging token request"); + resp = WLAN_STATUS_UNSPECIFIED_FAILURE; + goto reply; + } + resp = sae_group_allowed(sta->sae, + hapd->conf->sae_groups, + WPA_GET_LE16(pos)); + if (resp != WLAN_STATUS_SUCCESS) { + wpa_printf(MSG_ERROR, + "SAE: Invalid group in anti-clogging token request"); + goto reply; + } + pos += sizeof(le16); + + wpabuf_free(sta->sae->tmp->anti_clogging_token); + sta->sae->tmp->anti_clogging_token = + wpabuf_alloc_copy(pos, end - pos); + if (sta->sae->tmp->anti_clogging_token == NULL) { + wpa_printf(MSG_ERROR, + "SAE: Failed to alloc for anti-clogging token"); + return; + } + + /* + * IEEE Std 802.11-2012, 11.3.8.6.4: If the Status code + * is 76, a new Commit Message shall be constructed + * with the Anti-Clogging Token from the received + * Authentication frame, and the commit-scalar and + * COMMIT-ELEMENT previously sent. + */ + if (auth_sae_send_commit(hapd, sta, mgmt->bssid, 0)) { + wpa_printf(MSG_ERROR, + "SAE: Failed to send commit message"); + return; + } + sta->sae->state = SAE_COMMITTED; + sta->sae->sync = 0; + sae_set_retransmit_timer(hapd, sta); + return; + } + + if (status_code != WLAN_STATUS_SUCCESS) + return; + + resp = sae_parse_commit(sta->sae, mgmt->u.auth.variable, + ((const u8 *) mgmt) + len - + mgmt->u.auth.variable, &token, + &token_len, hapd->conf->sae_groups); + if (resp == SAE_SILENTLY_DISCARD) { + wpa_printf(MSG_DEBUG, + "SAE: Drop commit message from " MACSTR " due to reflection attack", + MAC2STR(sta->addr)); + return; + } + if (token && check_sae_token(hapd, sta->addr, token, token_len) + < 0) { + wpa_printf(MSG_DEBUG, "SAE: Drop commit message with " + "incorrect token from " MACSTR, + MAC2STR(sta->addr)); + return; + } + + if (resp != WLAN_STATUS_SUCCESS) + goto reply; + + if (!token && use_sae_anti_clogging(hapd)) { + wpa_printf(MSG_DEBUG, + "SAE: Request anti-clogging token from " + MACSTR, MAC2STR(sta->addr)); + data = auth_build_token_req(hapd, sta->sae->group, + sta->addr); + resp = WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ; + if (hapd->conf->mesh & MESH_ENABLED) + sta->sae->state = SAE_NOTHING; + goto reply; + } + + resp = sae_sm_step(hapd, sta, mgmt->bssid, auth_transaction); + } else if (auth_transaction == 2) { + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "SAE authentication (RX confirm, status=%u)", + status_code); + if (status_code != WLAN_STATUS_SUCCESS) + return; + if (sta->sae->state >= SAE_CONFIRMED || + !(hapd->conf->mesh & MESH_ENABLED)) { + if (sae_check_confirm(sta->sae, mgmt->u.auth.variable, + ((u8 *) mgmt) + len - + mgmt->u.auth.variable) < 0) { + resp = WLAN_STATUS_UNSPECIFIED_FAILURE; + goto reply; + } + } + resp = sae_sm_step(hapd, sta, mgmt->bssid, auth_transaction); + } else { + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "unexpected SAE authentication transaction %u (status=%u)", + auth_transaction, status_code); + if (status_code != WLAN_STATUS_SUCCESS) + return; + resp = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION; + } + +reply: + if (resp != WLAN_STATUS_SUCCESS) { + send_auth_reply(hapd, mgmt->sa, mgmt->bssid, WLAN_AUTH_SAE, + auth_transaction, resp, + data ? wpabuf_head(data) : (u8 *) "", + data ? wpabuf_len(data) : 0); + } + wpabuf_free(data); +} + + +/** + * auth_sae_init_committed - Send COMMIT and start SAE in committed state + * @hapd: BSS data for the device initiating the authentication + * @sta: the peer to which commit authentication frame is sent + * + * This function implements Init event handling (IEEE Std 802.11-2012, + * 11.3.8.6.3) in which initial COMMIT message is sent. Prior to calling, the + * sta->sae structure should be initialized appropriately via a call to + * sae_prepare_commit(). + */ +int auth_sae_init_committed(struct hostapd_data *hapd, struct sta_info *sta) +{ + int ret; + + if (!sta->sae || !sta->sae->tmp) + return -1; + + if (sta->sae->state != SAE_NOTHING) + return -1; + + ret = auth_sae_send_commit(hapd, sta, hapd->own_addr, 0); + if (ret) + return -1; + + sta->sae->state = SAE_COMMITTED; + sta->sae->sync = 0; + sae_set_retransmit_timer(hapd, sta); + + return 0; +} +#endif /* CONFIG_SAE */ +static void handle_auth(struct hostapd_data *hapd, + const struct ieee80211_mgmt *mgmt, size_t len) +{ + u16 auth_alg, auth_transaction; + u16 resp = WLAN_STATUS_SUCCESS; + struct sta_info *sta = NULL; + int res; + u16 fc; + const u8 *challenge = NULL; + u32 session_timeout, acct_interim_interval; + int vlan_id = 0; + struct hostapd_sta_wpa_psk_short *psk = NULL; + u8 resp_ies[2 + WLAN_AUTH_CHALLENGE_LEN]; + size_t resp_ies_len = 0; + char *identity = NULL; + char *radius_cui = NULL; + u16 seq_ctrl; + + if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth) - VARIABLE_ARRAY_SPARE) { + wpa_printf(MSG_INFO, "handle_auth - too short payload (len=%lu)", + (unsigned long) len); + return; + } + +#ifdef CONFIG_TESTING_OPTIONS + if (hapd->iconf->ignore_auth_probability > 0.0 && + drand48() < hapd->iconf->ignore_auth_probability) { + wpa_printf(MSG_INFO, + "TESTING: ignoring auth frame from " MACSTR, + MAC2STR(mgmt->sa)); + return; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + auth_alg = le_to_host16(mgmt->u.auth.auth_alg); + auth_transaction = le_to_host16(mgmt->u.auth.auth_transaction); + fc = le_to_host16(mgmt->frame_control); + seq_ctrl = le_to_host16(mgmt->seq_ctrl); + + if (len >= IEEE80211_HDRLEN + sizeof(mgmt->u.auth) - VARIABLE_ARRAY_SPARE + 2 + WLAN_AUTH_CHALLENGE_LEN + && mgmt->u.auth.variable[0] == WLAN_EID_CHALLENGE + && mgmt->u.auth.variable[1] == WLAN_AUTH_CHALLENGE_LEN) + challenge = &mgmt->u.auth.variable[2]; + +#ifdef CONFIG_NO_RC4 + if (auth_alg == WLAN_AUTH_SHARED_KEY) { + wpa_printf(MSG_INFO, + "Unsupported authentication algorithm (%d)", + auth_alg); + resp = WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG; + goto fail; + } +#endif /* CONFIG_NO_RC4 */ + + if (hapd->tkip_countermeasures) { + resp = WLAN_REASON_MICHAEL_MIC_FAILURE; + goto fail; + } + if (!(((hapd->conf->auth_algs & WPA_AUTH_ALG_OPEN) && + auth_alg == WLAN_AUTH_OPEN) || +#ifdef CONFIG_IEEE80211R + (hapd->conf->wpa && wpa_key_mgmt_ft(hapd->conf->wpa_key_mgmt) && + auth_alg == WLAN_AUTH_FT) || +#endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_SAE + (hapd->conf->wpa && wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) && + auth_alg == WLAN_AUTH_SAE) || +#endif /* CONFIG_SAE */ + ((hapd->conf->auth_algs & WPA_AUTH_ALG_SHARED) && + auth_alg == WLAN_AUTH_SHARED_KEY))) { + wpa_printf(MSG_INFO, "Unsupported authentication algorithm (%d)", + auth_alg); + resp = WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG; + goto fail; + } + + if (!(auth_transaction == 1 || auth_alg == WLAN_AUTH_SAE || + (auth_alg == WLAN_AUTH_SHARED_KEY && auth_transaction == 3))) { + wpa_printf(MSG_INFO, "Unknown authentication transaction number (%d)", + auth_transaction); + resp = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION; + goto fail; + } + + if (os_memcmp(mgmt->sa, hapd->own_addr, ETH_ALEN) == 0) { + wpa_printf(MSG_INFO, "Station " MACSTR " not allowed to authenticate", + MAC2STR(mgmt->sa)); + resp = WLAN_STATUS_UNSPECIFIED_FAILURE; + goto fail; + } + + if (hapd->conf->no_auth_if_seen_on) { + struct hostapd_data *other; + + other = sta_track_seen_on(hapd->iface, mgmt->sa, + hapd->conf->no_auth_if_seen_on); + if (other) { + u8 *pos; + u32 info; + u8 op_class, channel, phytype; + + wpa_printf(MSG_DEBUG, "%s: Reject authentication from " + MACSTR " since STA has been seen on %s", + hapd->conf->iface, MAC2STR(mgmt->sa), + hapd->conf->no_auth_if_seen_on); + + resp = WLAN_STATUS_REJECTED_WITH_SUGGESTED_BSS_TRANSITION; + pos = &resp_ies[0]; + *pos++ = WLAN_EID_NEIGHBOR_REPORT; + *pos++ = 13; + os_memcpy(pos, other->own_addr, ETH_ALEN); + pos += ETH_ALEN; + info = 0; /* TODO: BSSID Information */ + WPA_PUT_LE32(pos, info); + pos += 4; + if (other->iconf->hw_mode == HOSTAPD_MODE_IEEE80211AD) + phytype = 8; /* dmg */ + else if (other->iconf->ieee80211ac) + phytype = 9; /* vht */ + else if (other->iconf->ieee80211n) + phytype = 7; /* ht */ + else if (other->iconf->hw_mode == + HOSTAPD_MODE_IEEE80211A) + phytype = 4; /* ofdm */ + else if (other->iconf->hw_mode == + HOSTAPD_MODE_IEEE80211G) + phytype = 6; /* erp */ + else + phytype = 5; /* hrdsss */ + if (ieee80211_freq_to_channel_ext( + hostapd_hw_get_freq(other, + other->iconf->channel), + other->iconf->secondary_channel, + other->iconf->ieee80211ac, + &op_class, &channel) == NUM_HOSTAPD_MODES) { + op_class = 0; + channel = other->iconf->channel; + } + *pos++ = op_class; + *pos++ = channel; + *pos++ = phytype; + resp_ies_len = pos - &resp_ies[0]; + goto fail; + } + } + +#ifdef CONFIG_FULL_HOSTAPD + res = hostapd_allowed_address(hapd, mgmt->sa, (u8 *) mgmt, len, + &session_timeout, + &acct_interim_interval, &vlan_id, + &psk, &identity, &radius_cui); + + if (res == HOSTAPD_ACL_REJECT) { + wpa_printf(MSG_INFO, "Station " MACSTR " not allowed to authenticate", + MAC2STR(mgmt->sa)); + resp = WLAN_STATUS_UNSPECIFIED_FAILURE; + goto fail; + } + if (res == HOSTAPD_ACL_PENDING) { + wpa_printf(MSG_DEBUG, "Authentication frame from " MACSTR + " waiting for an external authentication", + MAC2STR(mgmt->sa)); + /* Authentication code will re-send the authentication frame + * after it has received (and cached) information from the + * external source. */ + return; + } +#else + res = HOSTAPD_ACL_ACCEPT; +#endif + sta = ap_get_sta(hapd, mgmt->sa); + if (sta) { + if ((fc & WLAN_FC_RETRY) && + sta->last_seq_ctrl != WLAN_INVALID_MGMT_SEQ && + sta->last_seq_ctrl == seq_ctrl && + sta->last_subtype == WLAN_FC_STYPE_AUTH) { + hostapd_logger(hapd, sta->addr, + HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "Drop repeated authentication frame seq_ctrl=0x%x", + seq_ctrl); + return; + } + } else { +#ifdef CONFIG_MESH + if (hapd->conf->mesh & MESH_ENABLED) { + /* if the mesh peer is not available, we don't do auth. + */ + wpa_printf(MSG_DEBUG, "Mesh peer " MACSTR + " not yet known - drop Authentiation frame", + MAC2STR(mgmt->sa)); + /* + * Save a copy of the frame so that it can be processed + * if a new peer entry is added shortly after this. + */ + wpabuf_free(hapd->mesh_pending_auth); + hapd->mesh_pending_auth = wpabuf_alloc_copy(mgmt, len); + os_get_reltime(&hapd->mesh_pending_auth_time); + return; + } +#endif /* CONFIG_MESH */ + + sta = ap_sta_add(hapd, mgmt->sa); + if (!sta) { + resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; + goto fail; + } + } + sta->last_seq_ctrl = seq_ctrl; + sta->last_subtype = WLAN_FC_STYPE_AUTH; + +#ifdef CONFIG_FULL_HOSTAPD + if (vlan_id > 0) { + if (!hostapd_vlan_id_valid(hapd->conf->vlan, vlan_id)) { + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS, + HOSTAPD_LEVEL_INFO, "Invalid VLAN ID " + "%d received from RADIUS server", + vlan_id); + resp = WLAN_STATUS_UNSPECIFIED_FAILURE; + goto fail; + } + sta->vlan_id = vlan_id; + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_RADIUS, + HOSTAPD_LEVEL_INFO, "VLAN ID %d", sta->vlan_id); + } +#endif + + hostapd_free_psk_list(sta->psk); + if (hapd->conf->wpa_psk_radius != PSK_RADIUS_IGNORED) { + sta->psk = psk; + psk = NULL; + } else { + sta->psk = NULL; + } + + sta->flags &= ~WLAN_STA_PREAUTH; + //ieee802_1x_notify_pre_auth(sta->eapol_sm, 0); + + if (res == HOSTAPD_ACL_ACCEPT_TIMEOUT) + ap_sta_session_timeout(hapd, sta, session_timeout); + else + ap_sta_no_session_timeout(hapd, sta); + + switch (auth_alg) { + case WLAN_AUTH_OPEN: + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "authentication OK (open system)"); + sta->flags |= WLAN_STA_AUTH; + wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH); + sta->auth_alg = WLAN_AUTH_OPEN; + mlme_authenticate_indication(hapd, sta); + break; +#ifndef CONFIG_NO_RC4 + case WLAN_AUTH_SHARED_KEY: + resp = auth_shared_key(hapd, sta, auth_transaction, challenge, + fc & WLAN_FC_ISWEP); + sta->auth_alg = WLAN_AUTH_SHARED_KEY; + mlme_authenticate_indication(hapd, sta); + if (sta->challenge && auth_transaction == 1) { + resp_ies[0] = WLAN_EID_CHALLENGE; + resp_ies[1] = WLAN_AUTH_CHALLENGE_LEN; + os_memcpy(resp_ies + 2, sta->challenge, + WLAN_AUTH_CHALLENGE_LEN); + resp_ies_len = 2 + WLAN_AUTH_CHALLENGE_LEN; + } + break; +#endif /* CONFIG_NO_RC4 */ +#ifdef CONFIG_IEEE80211R + case WLAN_AUTH_FT: + sta->auth_alg = WLAN_AUTH_FT; + if (sta->wpa_sm == NULL) + sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, + sta->addr, NULL); + if (sta->wpa_sm == NULL) { + wpa_printf(MSG_DEBUG, "FT: Failed to initialize WPA " + "state machine"); + resp = WLAN_STATUS_UNSPECIFIED_FAILURE; + goto fail; + } + wpa_ft_process_auth(sta->wpa_sm, mgmt->bssid, + auth_transaction, mgmt->u.auth.variable, + len - IEEE80211_HDRLEN - + sizeof(mgmt->u.auth) + VARIABLE_ARRAY_SPARE, + handle_auth_ft_finish, hapd); + /* handle_auth_ft_finish() callback will complete auth. */ + return; +#endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_SAE + case WLAN_AUTH_SAE: +#ifdef CONFIG_MESH + if (status_code == WLAN_STATUS_SUCCESS && + hapd->conf->mesh & MESH_ENABLED) { + if (sta->wpa_sm == NULL) + sta->wpa_sm = + wpa_auth_sta_init(hapd->wpa_auth, + sta->addr, NULL); + if (sta->wpa_sm == NULL) { + wpa_printf(MSG_DEBUG, + "SAE: Failed to initialize WPA state machine"); + resp = WLAN_STATUS_UNSPECIFIED_FAILURE; + goto fail; + } + } +#endif /* CONFIG_MESH */ + handle_auth_sae(hapd, sta, mgmt, len, auth_transaction, + status_code); + return; +#endif /* CONFIG_SAE */ + } + + fail: + os_free(identity); + os_free(radius_cui); + hostapd_free_psk_list(psk); + + send_auth_reply(hapd, mgmt->sa, mgmt->bssid, auth_alg, + auth_transaction + 1, resp, resp_ies, resp_ies_len); + (void)acct_interim_interval; + (void)vlan_id; +} + + +static int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta) +{ + int i, j = 32, aid; + + /* get a unique AID */ + if (sta->aid > 0) { + wpa_printf(MSG_DEBUG, " old AID %d", sta->aid); + return 0; + } + + for (i = 0; i < AID_WORDS; i++) { + if (hapd->sta_aid[i] == (u32) -1) + continue; + for (j = 0; j < 32; j++) { + if (!(hapd->sta_aid[i] & BIT(j))) + break; + } + if (j < 32) + break; + } + if (j == 32) + return -1; + aid = i * 32 + j + 1; + if (aid > 2007) + return -1; + + sta->aid = aid; + hapd->sta_aid[i] |= BIT(j); + wpa_printf(MSG_DEBUG, " new AID %d", sta->aid); + return 0; +} + + +static u16 check_ssid(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *ssid_ie, size_t ssid_ie_len) +{ + if (ssid_ie == NULL) + return WLAN_STATUS_UNSPECIFIED_FAILURE; + + if (ssid_ie_len != hapd->conf->ssid.ssid_len || + os_memcmp(ssid_ie, hapd->conf->ssid.ssid, ssid_ie_len) != 0) { + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, + "Station tried to associate with unknown SSID " + "'%s'", wpa_ssid_txt(ssid_ie, ssid_ie_len)); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + + return WLAN_STATUS_SUCCESS; +} + + +static u16 check_wmm(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *wmm_ie, size_t wmm_ie_len) +{ + sta->flags &= ~WLAN_STA_WMM; + sta->qosinfo = 0; + if (wmm_ie && hapd->conf->wmm_enabled) { + struct wmm_information_element *wmm; + + if (!hostapd_eid_wmm_valid(hapd, wmm_ie, wmm_ie_len)) { + hostapd_logger(hapd, sta->addr, + HOSTAPD_MODULE_WPA, + HOSTAPD_LEVEL_DEBUG, + "invalid WMM element in association " + "request"); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + + sta->flags |= WLAN_STA_WMM; + wmm = (struct wmm_information_element *) wmm_ie; + sta->qosinfo = wmm->qos_info; + } + return WLAN_STATUS_SUCCESS; +} + + +static u16 copy_supp_rates(struct hostapd_data *hapd, struct sta_info *sta, + struct ieee802_11_elems *elems) +{ + if (!elems->supp_rates) { + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "No supported rates element in AssocReq"); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + + if (elems->supp_rates_len + elems->ext_supp_rates_len > + sizeof(sta->supported_rates)) { + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "Invalid supported rates element length %d+%d", + elems->supp_rates_len, + elems->ext_supp_rates_len); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + + sta->supported_rates_len = merge_byte_arrays( + sta->supported_rates, sizeof(sta->supported_rates), + elems->supp_rates, elems->supp_rates_len, + elems->ext_supp_rates, elems->ext_supp_rates_len); + + return WLAN_STATUS_SUCCESS; +} + + +static u16 check_ext_capab(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *ext_capab_ie, size_t ext_capab_ie_len) +{ +#ifdef CONFIG_INTERWORKING + /* check for QoS Map support */ + if (ext_capab_ie_len >= 5) { + if (ext_capab_ie[4] & 0x01) + sta->qos_map_enabled = 1; + } +#endif /* CONFIG_INTERWORKING */ + + return WLAN_STATUS_SUCCESS; +} + + +static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *ies, size_t ies_len, int reassoc) +{ + struct ieee802_11_elems elems; + u16 resp; + const u8 *wpa_ie; + size_t wpa_ie_len; + const u8 *p2p_dev_addr = NULL; + + if (ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed) { + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, "Station sent an invalid " + "association request"); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + + resp = check_ssid(hapd, sta, elems.ssid, elems.ssid_len); + if (resp != WLAN_STATUS_SUCCESS) + return resp; + resp = check_wmm(hapd, sta, elems.wmm, elems.wmm_len); + if (resp != WLAN_STATUS_SUCCESS) + return resp; + resp = check_ext_capab(hapd, sta, elems.ext_capab, elems.ext_capab_len); + if (resp != WLAN_STATUS_SUCCESS) + return resp; + resp = copy_supp_rates(hapd, sta, &elems); + if (resp != WLAN_STATUS_SUCCESS) + return resp; +#ifdef CONFIG_IEEE80211N + resp = copy_sta_ht_capab(hapd, sta, elems.ht_capabilities); + if (resp != WLAN_STATUS_SUCCESS) + return resp; + if (hapd->iconf->ieee80211n && hapd->iconf->require_ht && + !(sta->flags & WLAN_STA_HT)) { + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, "Station does not support " + "mandatory HT PHY - reject association"); + return WLAN_STATUS_ASSOC_DENIED_NO_HT; + } +#endif /* CONFIG_IEEE80211N */ + +#ifdef CONFIG_IEEE80211AC + if (hapd->iconf->ieee80211ac) { + resp = copy_sta_vht_capab(hapd, sta, elems.vht_capabilities); + if (resp != WLAN_STATUS_SUCCESS) + return resp; + + resp = set_sta_vht_opmode(hapd, sta, elems.vht_opmode_notif); + if (resp != WLAN_STATUS_SUCCESS) + return resp; + } + + if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht && + !(sta->flags & WLAN_STA_VHT)) { + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, "Station does not support " + "mandatory VHT PHY - reject association"); + return WLAN_STATUS_ASSOC_DENIED_NO_VHT; + } + + if (hapd->conf->vendor_vht && !elems.vht_capabilities) { + resp = copy_sta_vendor_vht(hapd, sta, elems.vendor_vht, + elems.vendor_vht_len); + if (resp != WLAN_STATUS_SUCCESS) + return resp; + } +#endif /* CONFIG_IEEE80211AC */ + +#ifdef CONFIG_P2P + if (elems.p2p) { + wpabuf_free(sta->p2p_ie); + sta->p2p_ie = ieee802_11_vendor_ie_concat(ies, ies_len, + P2P_IE_VENDOR_TYPE); + if (sta->p2p_ie) + p2p_dev_addr = p2p_get_go_dev_addr(sta->p2p_ie); + } else { + wpabuf_free(sta->p2p_ie); + sta->p2p_ie = NULL; + } +#endif /* CONFIG_P2P */ + + if ((hapd->conf->wpa & WPA_PROTO_RSN) && elems.rsn_ie) { + wpa_ie = elems.rsn_ie; + wpa_ie_len = elems.rsn_ie_len; + } else if ((hapd->conf->wpa & WPA_PROTO_WPA) && + elems.wpa_ie) { + wpa_ie = elems.wpa_ie; + wpa_ie_len = elems.wpa_ie_len; + } else { + wpa_ie = NULL; + wpa_ie_len = 0; + } + +#ifdef CONFIG_WPS + sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS | WLAN_STA_WPS2); + if (hapd->conf->wps_state && elems.wps_ie) { + wpa_printf(MSG_DEBUG, "STA included WPS IE in (Re)Association " + "Request - assume WPS is used"); + sta->flags |= WLAN_STA_WPS; + wpabuf_free(sta->wps_ie); + sta->wps_ie = ieee802_11_vendor_ie_concat(ies, ies_len, + WPS_IE_VENDOR_TYPE); + if (sta->wps_ie && wps_is_20(sta->wps_ie)) { + wpa_printf(MSG_DEBUG, "WPS: STA supports WPS 2.0"); + sta->flags |= WLAN_STA_WPS2; + } + wpa_ie = NULL; + wpa_ie_len = 0; + if (sta->wps_ie && wps_validate_assoc_req(sta->wps_ie) < 0) { + wpa_printf(MSG_DEBUG, "WPS: Invalid WPS IE in " + "(Re)Association Request - reject"); + return WLAN_STATUS_INVALID_IE; + } + } else if (hapd->conf->wps_state && wpa_ie == NULL) { + wpa_printf(MSG_DEBUG, "STA did not include WPA/RSN IE in " + "(Re)Association Request - possible WPS use"); + sta->flags |= WLAN_STA_MAYBE_WPS; + } else +#endif /* CONFIG_WPS */ + if (hapd->conf->wpa && wpa_ie == NULL) { + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, + "No WPA/RSN IE in association request"); + return WLAN_STATUS_INVALID_IE; + } + + if (hapd->conf->wpa && wpa_ie) { + int res; + wpa_ie -= 2; + wpa_ie_len += 2; + if (sta->wpa_sm == NULL) + sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, + sta->addr, + p2p_dev_addr); + if (sta->wpa_sm == NULL) { + wpa_printf(MSG_WARNING, "Failed to initialize WPA " + "state machine"); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm, + wpa_ie, wpa_ie_len, + elems.mdie, elems.mdie_len); + if (res == WPA_INVALID_GROUP) + resp = WLAN_STATUS_GROUP_CIPHER_NOT_VALID; + else if (res == WPA_INVALID_PAIRWISE) + resp = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID; + else if (res == WPA_INVALID_AKMP) + resp = WLAN_STATUS_AKMP_NOT_VALID; + else if (res == WPA_ALLOC_FAIL) + resp = WLAN_STATUS_UNSPECIFIED_FAILURE; +#ifdef CONFIG_IEEE80211W + else if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION) + resp = WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION; + else if (res == WPA_INVALID_MGMT_GROUP_CIPHER) + resp = WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION; +#endif /* CONFIG_IEEE80211W */ + else if (res == WPA_INVALID_MDIE) + resp = WLAN_STATUS_INVALID_MDIE; + else if (res != WPA_IE_OK) + resp = WLAN_STATUS_INVALID_IE; + if (resp != WLAN_STATUS_SUCCESS) + return resp; +#ifdef CONFIG_IEEE80211W + if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out && + sta->sa_query_count > 0) + ap_check_sa_query_timeout(hapd, sta); + if ((sta->flags & WLAN_STA_MFP) && !sta->sa_query_timed_out && + (!reassoc || sta->auth_alg != WLAN_AUTH_FT)) { + /* + * STA has already been associated with MFP and SA + * Query timeout has not been reached. Reject the + * association attempt temporarily and start SA Query, + * if one is not pending. + */ + + if (sta->sa_query_count == 0) + ap_sta_start_sa_query(hapd, sta); + + return WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY; + } + + if (wpa_auth_uses_mfp(sta->wpa_sm)) + sta->flags |= WLAN_STA_MFP; + else + sta->flags &= ~WLAN_STA_MFP; +#endif /* CONFIG_IEEE80211W */ + +#ifdef CONFIG_IEEE80211R + if (sta->auth_alg == WLAN_AUTH_FT) { + if (!reassoc) { + wpa_printf(MSG_DEBUG, "FT: " MACSTR " tried " + "to use association (not " + "re-association) with FT auth_alg", + MAC2STR(sta->addr)); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + + resp = wpa_ft_validate_reassoc(sta->wpa_sm, ies, + ies_len); + if (resp != WLAN_STATUS_SUCCESS) + return resp; + } +#endif /* CONFIG_IEEE80211R */ + +#ifdef CONFIG_SAE + if (wpa_auth_uses_sae(sta->wpa_sm) && + sta->auth_alg == WLAN_AUTH_OPEN) { + struct rsn_pmksa_cache_entry *sa; + sa = wpa_auth_sta_get_pmksa(sta->wpa_sm); + if (!sa || sa->akmp != WPA_KEY_MGMT_SAE) { + wpa_printf(MSG_DEBUG, + "SAE: No PMKSA cache entry found for " + MACSTR, MAC2STR(sta->addr)); + return WLAN_STATUS_INVALID_PMKID; + } + wpa_printf(MSG_DEBUG, "SAE: " MACSTR + " using PMKSA caching", MAC2STR(sta->addr)); + } else if (wpa_auth_uses_sae(sta->wpa_sm) && + sta->auth_alg != WLAN_AUTH_SAE && + !(sta->auth_alg == WLAN_AUTH_FT && + wpa_auth_uses_ft_sae(sta->wpa_sm))) { + wpa_printf(MSG_DEBUG, "SAE: " MACSTR " tried to use " + "SAE AKM after non-SAE auth_alg %u", + MAC2STR(sta->addr), sta->auth_alg); + return WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG; + } +#endif /* CONFIG_SAE */ + +#ifdef CONFIG_IEEE80211N + if ((sta->flags & (WLAN_STA_HT | WLAN_STA_VHT)) && + wpa_auth_get_pairwise(sta->wpa_sm) == WPA_CIPHER_TKIP) { + hostapd_logger(hapd, sta->addr, + HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, + "Station tried to use TKIP with HT " + "association"); + return WLAN_STATUS_CIPHER_REJECTED_PER_POLICY; + } +#endif /* CONFIG_IEEE80211N */ + } else + wpa_auth_sta_no_wpa(sta->wpa_sm); + +#ifdef CONFIG_P2P + p2p_group_notif_assoc(hapd->p2p_group, sta->addr, ies, ies_len); +#endif /* CONFIG_P2P */ + + return WLAN_STATUS_SUCCESS; +} + + +static void send_deauth(struct hostapd_data *hapd, const u8 *addr, + u16 reason_code) +{ + int send_len; + struct ieee80211_mgmt reply; + + os_memset(&reply, 0, sizeof(reply)); + reply.frame_control = + IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_DEAUTH); + os_memcpy(reply.da, addr, ETH_ALEN); + os_memcpy(reply.sa, hapd->own_addr, ETH_ALEN); + os_memcpy(reply.bssid, hapd->own_addr, ETH_ALEN); + + send_len = IEEE80211_HDRLEN + sizeof(reply.u.deauth) - VARIABLE_ARRAY_SPARE; + reply.u.deauth.reason_code = host_to_le16(reason_code); + + if (hostapd_drv_send_mlme(hapd, &reply, send_len, 0) < 0) + wpa_printf(MSG_INFO, "Failed to send deauth failed"); +} + + +static void send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta, + u16 status_code, int reassoc, const u8 *ies, + size_t ies_len) +{ + int send_len; + u8 buf[sizeof(struct ieee80211_mgmt) + 1024]; + struct ieee80211_mgmt *reply; + u8 *p; + + os_memset(buf, 0, sizeof(buf)); + reply = (struct ieee80211_mgmt *) buf; + reply->frame_control = + IEEE80211_FC(WLAN_FC_TYPE_MGMT, + (reassoc ? WLAN_FC_STYPE_REASSOC_RESP : + WLAN_FC_STYPE_ASSOC_RESP)); + os_memcpy(reply->da, sta->addr, ETH_ALEN); + os_memcpy(reply->sa, hapd->own_addr, ETH_ALEN); + os_memcpy(reply->bssid, hapd->own_addr, ETH_ALEN); + + send_len = IEEE80211_HDRLEN; + send_len += sizeof(reply->u.assoc_resp) - VARIABLE_ARRAY_SPARE; + reply->u.assoc_resp.capab_info = + host_to_le16(hostapd_own_capab_info(hapd)); + reply->u.assoc_resp.status_code = host_to_le16(status_code); + reply->u.assoc_resp.aid = host_to_le16(sta->aid | BIT(14) | BIT(15)); + /* Supported rates */ + p = hostapd_eid_supp_rates(hapd, reply->u.assoc_resp.variable); + /* Extended supported rates */ + p = hostapd_eid_ext_supp_rates(hapd, p); + +#ifdef CONFIG_IEEE80211R + if (status_code == WLAN_STATUS_SUCCESS) { + /* IEEE 802.11r: Mobility Domain Information, Fast BSS + * Transition Information, RSN, [RIC Response] */ + p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, p, + buf + sizeof(buf) - p, + sta->auth_alg, ies, ies_len); + } +#endif /* CONFIG_IEEE80211R */ + +#ifdef CONFIG_IEEE80211W + if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY) + p = hostapd_eid_assoc_comeback_time(hapd, sta, p); +#endif /* CONFIG_IEEE80211W */ + +#ifdef CONFIG_IEEE80211N + p = hostapd_eid_ht_capabilities(hapd, p); + p = hostapd_eid_ht_operation(hapd, p); +#endif /* CONFIG_IEEE80211N */ + +#ifdef CONFIG_IEEE80211AC + if (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) { + p = hostapd_eid_vht_capabilities(hapd, p); + p = hostapd_eid_vht_operation(hapd, p); + } +#endif /* CONFIG_IEEE80211AC */ + + p = hostapd_eid_ext_capab(hapd, p); + p = hostapd_eid_bss_max_idle_period(hapd, p); + if (sta->qos_map_enabled) + p = hostapd_eid_qos_map_set(hapd, p); + +#ifdef CONFIG_FST + if (hapd->iface->fst_ies) { + os_memcpy(p, wpabuf_head(hapd->iface->fst_ies), + wpabuf_len(hapd->iface->fst_ies)); + p += wpabuf_len(hapd->iface->fst_ies); + } +#endif /* CONFIG_FST */ + +#ifdef CONFIG_IEEE80211AC + if (hapd->conf->vendor_vht && (sta->flags & WLAN_STA_VENDOR_VHT)) + p = hostapd_eid_vendor_vht(hapd, p); +#endif /* CONFIG_IEEE80211AC */ + + if (sta->flags & WLAN_STA_WMM) + p = hostapd_eid_wmm(hapd, p); + +#ifdef CONFIG_WPS + if ((sta->flags & WLAN_STA_WPS) || + ((sta->flags & WLAN_STA_MAYBE_WPS) && hapd->conf->wpa)) { + struct wpabuf *wps = wps_build_assoc_resp_ie(); + if (wps) { + os_memcpy(p, wpabuf_head(wps), wpabuf_len(wps)); + p += wpabuf_len(wps); + wpabuf_free(wps); + } + } +#endif /* CONFIG_WPS */ + +#ifdef CONFIG_P2P + if (sta->p2p_ie) { + struct wpabuf *p2p_resp_ie; + enum p2p_status_code status; + switch (status_code) { + case WLAN_STATUS_SUCCESS: + status = P2P_SC_SUCCESS; + break; + case WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA: + status = P2P_SC_FAIL_LIMIT_REACHED; + break; + default: + status = P2P_SC_FAIL_INVALID_PARAMS; + break; + } + p2p_resp_ie = p2p_group_assoc_resp_ie(hapd->p2p_group, status); + if (p2p_resp_ie) { + os_memcpy(p, wpabuf_head(p2p_resp_ie), + wpabuf_len(p2p_resp_ie)); + p += wpabuf_len(p2p_resp_ie); + wpabuf_free(p2p_resp_ie); + } + } +#endif /* CONFIG_P2P */ + +#ifdef CONFIG_P2P_MANAGER + if (hapd->conf->p2p & P2P_MANAGE) + p = hostapd_eid_p2p_manage(hapd, p); +#endif /* CONFIG_P2P_MANAGER */ + + send_len += p - reply->u.assoc_resp.variable; + + if (hostapd_drv_send_mlme(hapd, reply, send_len, 0) < 0) + wpa_printf(MSG_INFO, "Failed to send assoc resp failed"); +} + + +static void handle_assoc(struct hostapd_data *hapd, + const struct ieee80211_mgmt *mgmt, size_t len, + int reassoc) +{ + u16 capab_info, listen_interval, seq_ctrl, fc; + u16 resp = WLAN_STATUS_SUCCESS; + const u8 *pos; + int left, i; + struct sta_info *sta; + + if (len < IEEE80211_HDRLEN + (reassoc ? (sizeof(mgmt->u.reassoc_req) - VARIABLE_ARRAY_SPARE) : + (sizeof(mgmt->u.assoc_req) - VARIABLE_ARRAY_SPARE))) { + wpa_printf(MSG_INFO, "handle_assoc(reassoc=%d) - too short payload (len=%lu)", + reassoc, (unsigned long) len); + return; + } + +#ifdef CONFIG_TESTING_OPTIONS + if (reassoc) { + if (hapd->iconf->ignore_reassoc_probability > 0.0 && + drand48() < hapd->iconf->ignore_reassoc_probability) { + wpa_printf(MSG_INFO, + "TESTING: ignoring reassoc request from " + MACSTR, MAC2STR(mgmt->sa)); + return; + } + } else { + if (hapd->iconf->ignore_assoc_probability > 0.0 && + drand48() < hapd->iconf->ignore_assoc_probability) { + wpa_printf(MSG_INFO, + "TESTING: ignoring assoc request from " + MACSTR, MAC2STR(mgmt->sa)); + return; + } + } +#endif /* CONFIG_TESTING_OPTIONS */ + + fc = le_to_host16(mgmt->frame_control); + seq_ctrl = le_to_host16(mgmt->seq_ctrl); + + if (reassoc) { + capab_info = le_to_host16(mgmt->u.reassoc_req.capab_info); + listen_interval = le_to_host16( + mgmt->u.reassoc_req.listen_interval); + wpa_printf(MSG_DEBUG, "reassociation request: STA=" MACSTR + " capab_info=0x%02x listen_interval=%d current_ap=" + MACSTR " seq_ctrl=0x%x%s", + MAC2STR(mgmt->sa), capab_info, listen_interval, + MAC2STR(mgmt->u.reassoc_req.current_ap), + seq_ctrl, (fc & WLAN_FC_RETRY) ? " retry" : ""); + left = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.reassoc_req) - VARIABLE_ARRAY_SPARE); + pos = mgmt->u.reassoc_req.variable; + } else { + capab_info = le_to_host16(mgmt->u.assoc_req.capab_info); + listen_interval = le_to_host16( + mgmt->u.assoc_req.listen_interval); + wpa_printf(MSG_DEBUG, "association request: STA=" MACSTR + " capab_info=0x%02x listen_interval=%d " + "seq_ctrl=0x%x%s", + MAC2STR(mgmt->sa), capab_info, listen_interval, + seq_ctrl, (fc & WLAN_FC_RETRY) ? " retry" : ""); + left = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.assoc_req) - VARIABLE_ARRAY_SPARE); + pos = mgmt->u.assoc_req.variable; + } + + sta = ap_get_sta(hapd, mgmt->sa); +#ifdef CONFIG_IEEE80211R + if (sta && sta->auth_alg == WLAN_AUTH_FT && + (sta->flags & WLAN_STA_AUTH) == 0) { + wpa_printf(MSG_DEBUG, "FT: Allow STA " MACSTR " to associate " + "prior to authentication since it is using " + "over-the-DS FT", MAC2STR(mgmt->sa)); + } else +#endif /* CONFIG_IEEE80211R */ + if (sta == NULL || (sta->flags & WLAN_STA_AUTH) == 0) { + hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, "Station tried to " + "associate before authentication " + "(aid=%d flags=0x%x)", + sta ? sta->aid : -1, + sta ? sta->flags : 0); + send_deauth(hapd, mgmt->sa, + WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA); + return; + } + + if ((fc & WLAN_FC_RETRY) && + sta->last_seq_ctrl != WLAN_INVALID_MGMT_SEQ && + sta->last_seq_ctrl == seq_ctrl && + sta->last_subtype == reassoc ? WLAN_FC_STYPE_REASSOC_REQ : + WLAN_FC_STYPE_ASSOC_REQ) { + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "Drop repeated association frame seq_ctrl=0x%x", + seq_ctrl); + return; + } + sta->last_seq_ctrl = seq_ctrl; + sta->last_subtype = reassoc ? WLAN_FC_STYPE_REASSOC_REQ : + WLAN_FC_STYPE_ASSOC_REQ; + + if (hapd->tkip_countermeasures) { + resp = WLAN_REASON_MICHAEL_MIC_FAILURE; + goto fail; + } + + if (listen_interval > hapd->conf->max_listen_interval) { + hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "Too large Listen Interval (%d)", + listen_interval); + resp = WLAN_STATUS_ASSOC_DENIED_LISTEN_INT_TOO_LARGE; + goto fail; + } + + /* followed by SSID and Supported rates; and HT capabilities if 802.11n + * is used */ + resp = check_assoc_ies(hapd, sta, pos, left, reassoc); + if (resp != WLAN_STATUS_SUCCESS) + goto fail; + + if (hostapd_get_aid(hapd, sta) < 0) { + hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, "No room for more AIDs"); + resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; + goto fail; + } + + sta->capability = capab_info; + sta->listen_interval = listen_interval; + + if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G) + sta->flags |= WLAN_STA_NONERP; + for (i = 0; i < sta->supported_rates_len; i++) { + if ((sta->supported_rates[i] & 0x7f) > 22) { + sta->flags &= ~WLAN_STA_NONERP; + break; + } + } + if (sta->flags & WLAN_STA_NONERP && !sta->nonerp_set) { + sta->nonerp_set = 1; + hapd->iface->num_sta_non_erp++; + if (hapd->iface->num_sta_non_erp == 1) + ieee802_11_set_beacons(hapd->iface); + } + + if (!(sta->capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) && + !sta->no_short_slot_time_set) { + sta->no_short_slot_time_set = 1; + hapd->iface->num_sta_no_short_slot_time++; + if (hapd->iface->current_mode->mode == + HOSTAPD_MODE_IEEE80211G && + hapd->iface->num_sta_no_short_slot_time == 1) + ieee802_11_set_beacons(hapd->iface); + } + + if (sta->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) + sta->flags |= WLAN_STA_SHORT_PREAMBLE; + else + sta->flags &= ~WLAN_STA_SHORT_PREAMBLE; + + if (!(sta->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) && + !sta->no_short_preamble_set) { + sta->no_short_preamble_set = 1; + hapd->iface->num_sta_no_short_preamble++; + if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G + && hapd->iface->num_sta_no_short_preamble == 1) + ieee802_11_set_beacons(hapd->iface); + } + +#ifdef CONFIG_IEEE80211N + update_ht_state(hapd, sta); +#endif /* CONFIG_IEEE80211N */ + + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "association OK (aid %d)", sta->aid); + /* Station will be marked associated, after it acknowledges AssocResp + */ + sta->flags |= WLAN_STA_ASSOC_REQ_OK; + +#ifdef CONFIG_IEEE80211W + if ((sta->flags & WLAN_STA_MFP) && sta->sa_query_timed_out) { + wpa_printf(MSG_DEBUG, "Allowing %sassociation after timed out " + "SA Query procedure", reassoc ? "re" : ""); + /* TODO: Send a protected Disassociate frame to the STA using + * the old key and Reason Code "Previous Authentication no + * longer valid". Make sure this is only sent protected since + * unprotected frame would be received by the STA that is now + * trying to associate. + */ + } +#endif /* CONFIG_IEEE80211W */ + + /* Make sure that the previously registered inactivity timer will not + * remove the STA immediately. */ + sta->timeout_next = STA_NULLFUNC; + + fail: + send_assoc_resp(hapd, sta, resp, reassoc, pos, left); +} + + +static void handle_disassoc(struct hostapd_data *hapd, + const struct ieee80211_mgmt *mgmt, size_t len) +{ + struct sta_info *sta; + + if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.disassoc) - VARIABLE_ARRAY_SPARE) { + wpa_printf(MSG_INFO, "handle_disassoc - too short payload (len=%lu)", + (unsigned long) len); + return; + } + + wpa_printf(MSG_DEBUG, "disassocation: STA=" MACSTR " reason_code=%d", + MAC2STR(mgmt->sa), + le_to_host16(mgmt->u.disassoc.reason_code)); + + sta = ap_get_sta(hapd, mgmt->sa); + if (sta == NULL) { + wpa_printf(MSG_INFO, "Station " MACSTR " trying to disassociate, but it is not associated", + MAC2STR(mgmt->sa)); + return; + } + + ap_sta_set_authorized(hapd, sta, 0); + sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ; + sta->flags &= ~(WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK); + wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC); + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, "disassociated"); + ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); + /* Stop Accounting and IEEE 802.1X sessions, but leave the STA + * authenticated. */ + if (sta->ipaddr) + hostapd_drv_br_delete_ip_neigh(hapd, 4, (u8 *) &sta->ipaddr); + ap_sta_ip6addr_del(hapd, sta); + hostapd_drv_sta_remove(hapd, sta->addr); + + if (sta->timeout_next == STA_NULLFUNC || + sta->timeout_next == STA_DISASSOC) { + sta->timeout_next = STA_DEAUTH; + eloop_cancel_timeout(ap_handle_timer, hapd, sta); + eloop_register_timeout(AP_DEAUTH_DELAY, 0, ap_handle_timer, + hapd, sta); + } + + mlme_disassociate_indication( + hapd, sta, le_to_host16(mgmt->u.disassoc.reason_code)); +} + + +static void handle_deauth(struct hostapd_data *hapd, + const struct ieee80211_mgmt *mgmt, size_t len) +{ + struct sta_info *sta; + + if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.deauth) - VARIABLE_ARRAY_SPARE) { + wpa_msg(hapd->msg_ctx, MSG_DEBUG, "handle_deauth - too short " + "payload (len=%lu)", (unsigned long) len); + return; + } + + wpa_msg(hapd->msg_ctx, MSG_DEBUG, "deauthentication: STA=" MACSTR + " reason_code=%d", + MAC2STR(mgmt->sa), le_to_host16(mgmt->u.deauth.reason_code)); + + sta = ap_get_sta(hapd, mgmt->sa); + if (sta == NULL) { + wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Station " MACSTR " trying " + "to deauthenticate, but it is not authenticated", + MAC2STR(mgmt->sa)); + return; + } + + ap_sta_set_authorized(hapd, sta, 0); + sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ; + sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC | + WLAN_STA_ASSOC_REQ_OK); + wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH); + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, "deauthenticated"); + mlme_deauthenticate_indication( + hapd, sta, le_to_host16(mgmt->u.deauth.reason_code)); + ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); + ap_free_sta(hapd, sta); +} + + +static void handle_beacon(struct hostapd_data *hapd, + const struct ieee80211_mgmt *mgmt, size_t len, + struct hostapd_frame_info *fi) +{ + struct ieee802_11_elems elems; + + if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.beacon) - VARIABLE_ARRAY_SPARE) { + wpa_printf(MSG_INFO, "handle_beacon - too short payload (len=%lu)", + (unsigned long) len); + return; + } + + (void) ieee802_11_parse_elems(mgmt->u.beacon.variable, + len - (IEEE80211_HDRLEN + + sizeof(mgmt->u.beacon) - VARIABLE_ARRAY_SPARE), &elems, + 0); + + ap_list_process_beacon(hapd->iface, mgmt, &elems, fi); +} + + +#ifdef CONFIG_IEEE80211W + +static int hostapd_sa_query_action(struct hostapd_data *hapd, + const struct ieee80211_mgmt *mgmt, + size_t len) +{ + const u8 *end; + + end = mgmt->u.action.u.sa_query_resp.trans_id + + WLAN_SA_QUERY_TR_ID_LEN; + if (((u8 *) mgmt) + len < end) { + wpa_printf(MSG_DEBUG, "IEEE 802.11: Too short SA Query Action " + "frame (len=%lu)", (unsigned long) len); + return 0; + } + + ieee802_11_sa_query_action(hapd, mgmt->sa, + mgmt->u.action.u.sa_query_resp.action, + mgmt->u.action.u.sa_query_resp.trans_id); + return 1; +} + + +static int robust_action_frame(u8 category) +{ + return category != WLAN_ACTION_PUBLIC && + category != WLAN_ACTION_HT; +} +#endif /* CONFIG_IEEE80211W */ + + +static int handle_action(struct hostapd_data *hapd, + const struct ieee80211_mgmt *mgmt, size_t len) +{ + struct sta_info *sta; + sta = ap_get_sta(hapd, mgmt->sa); + + if (len < IEEE80211_HDRLEN + 1) { + hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "handle_action - too short payload (len=%lu)", + (unsigned long) len); + return 0; + } + + if (mgmt->u.action.category != WLAN_ACTION_PUBLIC && + (sta == NULL || !(sta->flags & WLAN_STA_ASSOC))) { + wpa_printf(MSG_DEBUG, "IEEE 802.11: Ignored Action " + "frame (category=%u) from unassociated STA " MACSTR, + MAC2STR(mgmt->sa), mgmt->u.action.category); + return 0; + } + +#ifdef CONFIG_IEEE80211W + if (sta && (sta->flags & WLAN_STA_MFP) && + !(mgmt->frame_control & host_to_le16(WLAN_FC_ISWEP)) && + robust_action_frame(mgmt->u.action.category)) { + hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "Dropped unprotected Robust Action frame from " + "an MFP STA"); + return 0; + } +#endif /* CONFIG_IEEE80211W */ + + if (sta) { + u16 fc = le_to_host16(mgmt->frame_control); + u16 seq_ctrl = le_to_host16(mgmt->seq_ctrl); + + if ((fc & WLAN_FC_RETRY) && + sta->last_seq_ctrl != WLAN_INVALID_MGMT_SEQ && + sta->last_seq_ctrl == seq_ctrl && + sta->last_subtype == WLAN_FC_STYPE_ACTION) { + hostapd_logger(hapd, sta->addr, + HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "Drop repeated action frame seq_ctrl=0x%x", + seq_ctrl); + return 1; + } + + sta->last_seq_ctrl = seq_ctrl; + sta->last_subtype = WLAN_FC_STYPE_ACTION; + } + + switch (mgmt->u.action.category) { +#ifdef CONFIG_IEEE80211R + case WLAN_ACTION_FT: + if (!sta || + wpa_ft_action_rx(sta->wpa_sm, (u8 *) &mgmt->u.action, + len - IEEE80211_HDRLEN)) + break; + return 1; +#endif /* CONFIG_IEEE80211R */ + case WLAN_ACTION_WMM: + hostapd_wmm_action(hapd, mgmt, len); + return 1; +#ifdef CONFIG_IEEE80211W + case WLAN_ACTION_SA_QUERY: + return hostapd_sa_query_action(hapd, mgmt, len); +#endif /* CONFIG_IEEE80211W */ +#ifdef CONFIG_WNM + case WLAN_ACTION_WNM: + ieee802_11_rx_wnm_action_ap(hapd, mgmt, len); + return 1; +#endif /* CONFIG_WNM */ +#ifdef CONFIG_FST + case WLAN_ACTION_FST: + if (hapd->iface->fst) + fst_rx_action(hapd->iface->fst, mgmt, len); + else + wpa_printf(MSG_DEBUG, + "FST: Ignore FST Action frame - no FST attached"); + return 1; +#endif /* CONFIG_FST */ + case WLAN_ACTION_PUBLIC: + case WLAN_ACTION_PROTECTED_DUAL: +#ifdef CONFIG_IEEE80211N + if (len >= IEEE80211_HDRLEN + 2 && + mgmt->u.action.u.public_action.action == + WLAN_PA_20_40_BSS_COEX) { + wpa_printf(MSG_DEBUG, + "HT20/40 coex mgmt frame received from STA " + MACSTR, MAC2STR(mgmt->sa)); + hostapd_2040_coex_action(hapd, mgmt, len); + } +#endif /* CONFIG_IEEE80211N */ + if (hapd->public_action_cb) { + hapd->public_action_cb(hapd->public_action_cb_ctx, + (u8 *) mgmt, len, + hapd->iface->freq); + } + if (hapd->public_action_cb2) { + hapd->public_action_cb2(hapd->public_action_cb2_ctx, + (u8 *) mgmt, len, + hapd->iface->freq); + } + if (hapd->public_action_cb || hapd->public_action_cb2) + return 1; + break; + case WLAN_ACTION_VENDOR_SPECIFIC: + if (hapd->vendor_action_cb) { + if (hapd->vendor_action_cb(hapd->vendor_action_cb_ctx, + (u8 *) mgmt, len, + hapd->iface->freq) == 0) + return 1; + } + break; + } + + hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "handle_action - unknown action category %d or invalid " + "frame", + mgmt->u.action.category); + if (!(mgmt->da[0] & 0x01) && !(mgmt->u.action.category & 0x80) && + !(mgmt->sa[0] & 0x01)) { + struct ieee80211_mgmt *resp; + + /* + * IEEE 802.11-REVma/D9.0 - 7.3.1.11 + * Return the Action frame to the source without change + * except that MSB of the Category set to 1. + */ + wpa_printf(MSG_DEBUG, "IEEE 802.11: Return unknown Action " + "frame back to sender"); + resp = os_malloc(len); + if (resp == NULL) + return 0; + os_memcpy(resp, mgmt, len); + os_memcpy(resp->da, resp->sa, ETH_ALEN); + os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN); + os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN); + resp->u.action.category |= 0x80; + + if (hostapd_drv_send_mlme(hapd, resp, len, 0) < 0) { + wpa_printf(MSG_ERROR, "IEEE 802.11: Failed to send " + "Action frame"); + } + os_free(resp); + } + + return 1; +} + + +/** + * ieee802_11_mgmt - process incoming IEEE 802.11 management frames + * @hapd: hostapd BSS data structure (the BSS to which the management frame was + * sent to) + * @buf: management frame data (starting from IEEE 802.11 header) + * @len: length of frame data in octets + * @fi: meta data about received frame (signal level, etc.) + * + * Process all incoming IEEE 802.11 management frames. This will be called for + * each frame received from the kernel driver through wlan#ap interface. In + * addition, it can be called to re-inserted pending frames (e.g., when using + * external RADIUS server as an MAC ACL). + */ +int ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len, + struct hostapd_frame_info *fi) +{ + struct ieee80211_mgmt *mgmt; + int broadcast; + u16 fc, stype; + int ret = 0; + + if (len < 24) + return 0; + + mgmt = (struct ieee80211_mgmt *) buf; + fc = le_to_host16(mgmt->frame_control); + stype = WLAN_FC_GET_STYPE(fc); + + if (stype == WLAN_FC_STYPE_BEACON) { + handle_beacon(hapd, mgmt, len, fi); + return 1; + } + + broadcast = (mgmt->bssid[0] == 0xff) + && (mgmt->bssid[1] == 0xff) + && (mgmt->bssid[2] == 0xff) + && (mgmt->bssid[3] == 0xff) + && (mgmt->bssid[4] == 0xff) + && (mgmt->bssid[5] == 0xff); + + if (!broadcast && +#ifdef CONFIG_P2P + /* Invitation responses can be sent with the peer MAC as BSSID */ + !((hapd->conf->p2p & P2P_GROUP_OWNER) && + stype == WLAN_FC_STYPE_ACTION) && +#endif /* CONFIG_P2P */ +#ifdef CONFIG_MESH + !(hapd->conf->mesh & MESH_ENABLED) && +#endif /* CONFIG_MESH */ + os_memcmp(mgmt->bssid, hapd->own_addr, ETH_ALEN) != 0) { + wpa_printf(MSG_INFO, "MGMT: BSSID=" MACSTR " not our address", + MAC2STR(mgmt->bssid)); + return 0; + } + + + if (stype == WLAN_FC_STYPE_PROBE_REQ) { + handle_probe_req(hapd, mgmt, len, fi->ssi_signal); + return 1; + } + + if (os_memcmp(mgmt->da, hapd->own_addr, ETH_ALEN) != 0) { + hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "MGMT: DA=" MACSTR " not our address", + MAC2STR(mgmt->da)); + return 0; + } + + if (hapd->iconf->track_sta_max_num) + sta_track_add(hapd->iface, mgmt->sa); + + switch (stype) { + case WLAN_FC_STYPE_AUTH: + wpa_printf(MSG_DEBUG, "mgmt::auth"); + handle_auth(hapd, mgmt, len); + ret = 1; + break; + case WLAN_FC_STYPE_ASSOC_REQ: + wpa_printf(MSG_DEBUG, "mgmt::assoc_req"); + handle_assoc(hapd, mgmt, len, 0); + ret = 1; + break; + case WLAN_FC_STYPE_REASSOC_REQ: + wpa_printf(MSG_DEBUG, "mgmt::reassoc_req"); + handle_assoc(hapd, mgmt, len, 1); + ret = 1; + break; + case WLAN_FC_STYPE_DISASSOC: + wpa_printf(MSG_DEBUG, "mgmt::disassoc"); + handle_disassoc(hapd, mgmt, len); + ret = 1; + break; + case WLAN_FC_STYPE_DEAUTH: + wpa_msg(hapd->msg_ctx, MSG_DEBUG, "mgmt::deauth"); + handle_deauth(hapd, mgmt, len); + ret = 1; + break; + case WLAN_FC_STYPE_ACTION: + wpa_printf(MSG_DEBUG, "mgmt::action"); + ret = handle_action(hapd, mgmt, len); + break; + default: + hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "unknown mgmt frame subtype %d", stype); + break; + } + + return ret; +} + + +static void handle_auth_cb(struct hostapd_data *hapd, + const struct ieee80211_mgmt *mgmt, + size_t len, int ok) +{ + u16 auth_alg, auth_transaction, status_code; + struct sta_info *sta; + + if (!ok) { + hostapd_logger(hapd, mgmt->da, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_NOTICE, + "did not acknowledge authentication response"); + return; + } + + if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth) - VARIABLE_ARRAY_SPARE) { + wpa_printf(MSG_INFO, "handle_auth_cb - too short payload (len=%lu)", + (unsigned long) len); + return; + } + + auth_alg = le_to_host16(mgmt->u.auth.auth_alg); + auth_transaction = le_to_host16(mgmt->u.auth.auth_transaction); + status_code = le_to_host16(mgmt->u.auth.status_code); + + sta = ap_get_sta(hapd, mgmt->da); + if (!sta) { + wpa_printf(MSG_INFO, "handle_auth_cb: STA " MACSTR " not found", + MAC2STR(mgmt->da)); + return; + } + + if (status_code == WLAN_STATUS_SUCCESS && + ((auth_alg == WLAN_AUTH_OPEN && auth_transaction == 2) || + (auth_alg == WLAN_AUTH_SHARED_KEY && auth_transaction == 4))) { + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, "authenticated"); + sta->flags |= WLAN_STA_AUTH; + } +} + +#ifdef CONFIG_FULL_HOSTAPD +static void hostapd_set_wds_encryption(struct hostapd_data *hapd, + struct sta_info *sta, + char *ifname_wds) +{ + int i; + struct hostapd_ssid *ssid = &hapd->conf->ssid; + + if (hapd->conf->ieee802_1x || hapd->conf->wpa) + return; + + for (i = 0; i < 4; i++) { + if (ssid->wep.key[i] && + hostapd_drv_set_key(ifname_wds, hapd, WPA_ALG_WEP, NULL, i, + i == ssid->wep.idx, NULL, 0, + ssid->wep.key[i], ssid->wep.len[i])) { + wpa_printf(MSG_WARNING, + "Could not set WEP keys for WDS interface; %s", + ifname_wds); + break; + } + } +} +#endif + +static void handle_assoc_cb(struct hostapd_data *hapd, + const struct ieee80211_mgmt *mgmt, + size_t len, int reassoc, int ok) +{ + u16 status; + struct sta_info *sta; + int new_assoc = 1; + struct ieee80211_ht_capabilities ht_cap; + struct ieee80211_vht_capabilities vht_cap; + + if (len < IEEE80211_HDRLEN + (reassoc ? (sizeof(mgmt->u.reassoc_resp) - VARIABLE_ARRAY_SPARE) : + (sizeof(mgmt->u.assoc_resp) - VARIABLE_ARRAY_SPARE))) { + wpa_printf(MSG_INFO, "handle_assoc_cb(reassoc=%d) - too short payload (len=%lu)", + reassoc, (unsigned long) len); + return; + } + + sta = ap_get_sta(hapd, mgmt->da); + if (!sta) { + wpa_printf(MSG_INFO, "handle_assoc_cb: STA " MACSTR " not found", + MAC2STR(mgmt->da)); + return; + } + + if (!ok) { + hostapd_logger(hapd, mgmt->da, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "did not acknowledge association response"); + sta->flags &= ~WLAN_STA_ASSOC_REQ_OK; + return; + } + + if (reassoc) + status = le_to_host16(mgmt->u.reassoc_resp.status_code); + else + status = le_to_host16(mgmt->u.assoc_resp.status_code); + + if (status != WLAN_STATUS_SUCCESS) + return; + + /* Stop previous accounting session, if one is started, and allocate + * new session id for the new session. */ + accounting_sta_stop(hapd, sta); + + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, + "associated (aid %d)", + sta->aid); + + if (sta->flags & WLAN_STA_ASSOC) + new_assoc = 0; + sta->flags |= WLAN_STA_ASSOC; + sta->flags &= ~WLAN_STA_WNM_SLEEP_MODE; + if ((!hapd->conf->ieee802_1x && !hapd->conf->wpa && !hapd->conf->osen) || + sta->auth_alg == WLAN_AUTH_FT) { + /* + * Open, static WEP, or FT protocol; no separate authorization + * step. + */ + ap_sta_set_authorized(hapd, sta, 1); + } + + if (reassoc) + mlme_reassociate_indication(hapd, sta); + else + mlme_associate_indication(hapd, sta); + +#ifdef CONFIG_IEEE80211W + sta->sa_query_timed_out = 0; +#endif /* CONFIG_IEEE80211W */ + + /* + * Remove the STA entry in order to make sure the STA PS state gets + * cleared and configuration gets updated in case of reassociation back + * to the same AP. + */ + hostapd_drv_sta_remove(hapd, sta->addr); + +#ifdef CONFIG_IEEE80211N + if (sta->flags & WLAN_STA_HT) + hostapd_get_ht_capab(hapd, sta->ht_capabilities, &ht_cap); +#endif /* CONFIG_IEEE80211N */ +#ifdef CONFIG_IEEE80211AC + if (sta->flags & WLAN_STA_VHT) + hostapd_get_vht_capab(hapd, sta->vht_capabilities, &vht_cap); +#endif /* CONFIG_IEEE80211AC */ + + if (hostapd_sta_add(hapd, sta->addr, sta->aid, sta->capability, + sta->supported_rates, sta->supported_rates_len, + sta->listen_interval, + sta->flags & WLAN_STA_HT ? &ht_cap : NULL, + sta->flags & WLAN_STA_VHT ? &vht_cap : NULL, + sta->flags, sta->qosinfo, sta->vht_opmode)) { + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_NOTICE, + "Could not add STA to kernel driver"); + + ap_sta_disconnect(hapd, sta, sta->addr, + WLAN_REASON_DISASSOC_AP_BUSY); + + return; + } + +#ifdef CONFIG_FULL_HOSTAPD + if (sta->flags & WLAN_STA_WDS) { + int ret; + char ifname_wds[IFNAMSIZ + 1]; + + ret = hostapd_set_wds_sta(hapd, ifname_wds, sta->addr, + sta->aid, 1); + if (!ret) + hostapd_set_wds_encryption(hapd, sta, ifname_wds); + } +#endif + + if (sta->eapol_sm == NULL) { + /* + * This STA does not use RADIUS server for EAP authentication, + * so bind it to the selected VLAN interface now, since the + * interface selection is not going to change anymore. + */ + if (ap_sta_bind_vlan(hapd, sta) < 0) + return; + } else if (sta->vlan_id) { + /* VLAN ID already set (e.g., by PMKSA caching), so bind STA */ + if (ap_sta_bind_vlan(hapd, sta) < 0) + return; + } + + hostapd_set_sta_flags(hapd, sta); + + if (sta->auth_alg == WLAN_AUTH_FT) + wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC_FT); + else + wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC); + hapd->new_assoc_sta_cb(hapd, sta, !new_assoc); // hostapd_new_assoc_sta + + ieee802_1x_notify_port_enabled(sta->eapol_sm, 1); +} + + +static void handle_deauth_cb(struct hostapd_data *hapd, + const struct ieee80211_mgmt *mgmt, + size_t len, int ok) +{ + struct sta_info *sta; + if (mgmt->da[0] & 0x01) + return; + sta = ap_get_sta(hapd, mgmt->da); + if (!sta) { + wpa_printf(MSG_DEBUG, "handle_deauth_cb: STA " MACSTR + " not found", MAC2STR(mgmt->da)); + return; + } + if (ok) + wpa_printf(MSG_DEBUG, "STA " MACSTR " acknowledged deauth", + MAC2STR(sta->addr)); + else + wpa_printf(MSG_DEBUG, "STA " MACSTR " did not acknowledge " + "deauth", MAC2STR(sta->addr)); + + ap_sta_deauth_cb(hapd, sta); +} + + +static void handle_disassoc_cb(struct hostapd_data *hapd, + const struct ieee80211_mgmt *mgmt, + size_t len, int ok) +{ + struct sta_info *sta; + if (mgmt->da[0] & 0x01) + return; + sta = ap_get_sta(hapd, mgmt->da); + if (!sta) { + wpa_printf(MSG_DEBUG, "handle_disassoc_cb: STA " MACSTR + " not found", MAC2STR(mgmt->da)); + return; + } + if (ok) + wpa_printf(MSG_DEBUG, "STA " MACSTR " acknowledged disassoc", + MAC2STR(sta->addr)); + else + wpa_printf(MSG_DEBUG, "STA " MACSTR " did not acknowledge " + "disassoc", MAC2STR(sta->addr)); + + ap_sta_disassoc_cb(hapd, sta); +} + + +/** + * ieee802_11_mgmt_cb - Process management frame TX status callback + * @hapd: hostapd BSS data structure (the BSS from which the management frame + * was sent from) + * @buf: management frame data (starting from IEEE 802.11 header) + * @len: length of frame data in octets + * @stype: management frame subtype from frame control field + * @ok: Whether the frame was ACK'ed + */ +void ieee802_11_mgmt_cb(struct hostapd_data *hapd, const u8 *buf, size_t len, + u16 stype, int ok) +{ + const struct ieee80211_mgmt *mgmt; + mgmt = (const struct ieee80211_mgmt *) buf; + +#ifdef CONFIG_TESTING_OPTIONS + if (hapd->ext_mgmt_frame_handling) { + wpa_msg(hapd->msg_ctx, MSG_INFO, "MGMT-TX-STATUS stype=%u ok=%d", + stype, ok); + return; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + switch (stype) { + case WLAN_FC_STYPE_AUTH: + wpa_printf(MSG_DEBUG, "mgmt::auth cb"); + handle_auth_cb(hapd, mgmt, len, ok); + break; + case WLAN_FC_STYPE_ASSOC_RESP: + wpa_printf(MSG_DEBUG, "mgmt::assoc_resp cb"); + handle_assoc_cb(hapd, mgmt, len, 0, ok); + break; + case WLAN_FC_STYPE_REASSOC_RESP: + wpa_printf(MSG_DEBUG, "mgmt::reassoc_resp cb"); + handle_assoc_cb(hapd, mgmt, len, 1, ok); + break; + case WLAN_FC_STYPE_PROBE_RESP: + wpa_printf(MSG_EXCESSIVE, "mgmt::proberesp cb"); + break; + case WLAN_FC_STYPE_DEAUTH: + wpa_printf(MSG_DEBUG, "mgmt::deauth cb"); + handle_deauth_cb(hapd, mgmt, len, ok); + break; + case WLAN_FC_STYPE_DISASSOC: + wpa_printf(MSG_DEBUG, "mgmt::disassoc cb"); + handle_disassoc_cb(hapd, mgmt, len, ok); + break; + case WLAN_FC_STYPE_ACTION: + wpa_printf(MSG_DEBUG, "mgmt::action cb"); + break; + default: + wpa_printf(MSG_INFO, "unknown mgmt cb frame subtype %d", stype); + break; + } +} + + +int ieee802_11_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen) +{ + /* TODO */ + return 0; +} + + +int ieee802_11_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta, + char *buf, size_t buflen) +{ + /* TODO */ + return 0; +} + + +void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr, + const u8 *buf, size_t len, int ack) +{ + struct sta_info *sta; + struct hostapd_iface *iface = hapd->iface; + + sta = ap_get_sta(hapd, addr); + if (sta == NULL && iface->num_bss > 1) { + size_t j; + for (j = 0; j < iface->num_bss; j++) { + hapd = iface->bss[j]; + sta = ap_get_sta(hapd, addr); + if (sta) + break; + } + } + if (sta == NULL || !(sta->flags & WLAN_STA_ASSOC)) + return; + if (sta->flags & WLAN_STA_PENDING_POLL) { + wpa_printf(MSG_DEBUG, "STA " MACSTR " %s pending " + "activity poll", MAC2STR(sta->addr), + ack ? "ACKed" : "did not ACK"); + if (ack) + sta->flags &= ~WLAN_STA_PENDING_POLL; + } + + ieee802_1x_tx_status(hapd, sta, buf, len, ack); +} + + +void hostapd_eapol_tx_status(struct hostapd_data *hapd, const u8 *dst, + const u8 *data, size_t len, int ack) +{ + struct sta_info *sta; + struct hostapd_iface *iface = hapd->iface; + + sta = ap_get_sta(hapd, dst); + if (sta == NULL && iface->num_bss > 1) { + size_t j; + for (j = 0; j < iface->num_bss; j++) { + hapd = iface->bss[j]; + sta = ap_get_sta(hapd, dst); + if (sta) + break; + } + } + if (sta == NULL || !(sta->flags & WLAN_STA_ASSOC)) { + wpa_printf(MSG_DEBUG, "Ignore TX status for Data frame to STA " + MACSTR " that is not currently associated", + MAC2STR(dst)); + return; + } + + ieee802_1x_eapol_tx_status(hapd, sta, data, len, ack); +} + + +void hostapd_client_poll_ok(struct hostapd_data *hapd, const u8 *addr) +{ + struct sta_info *sta; + struct hostapd_iface *iface = hapd->iface; + + sta = ap_get_sta(hapd, addr); + if (sta == NULL && iface->num_bss > 1) { + size_t j; + for (j = 0; j < iface->num_bss; j++) { + hapd = iface->bss[j]; + sta = ap_get_sta(hapd, addr); + if (sta) + break; + } + } + if (sta == NULL) + return; + if (!(sta->flags & WLAN_STA_PENDING_POLL)) + return; + + wpa_printf(MSG_DEBUG, "STA " MACSTR " ACKed pending " + "activity poll", MAC2STR(sta->addr)); + sta->flags &= ~WLAN_STA_PENDING_POLL; +} + + +void ieee802_11_rx_from_unknown(struct hostapd_data *hapd, const u8 *src, + int wds) +{ + struct sta_info *sta; + + sta = ap_get_sta(hapd, src); +#ifdef CONFIG_FULL_HOSTAPD + if (sta && (sta->flags & WLAN_STA_ASSOC)) { + if (!hapd->conf->wds_sta) + return; + + if (wds && !(sta->flags & WLAN_STA_WDS)) { + int ret; + char ifname_wds[IFNAMSIZ + 1]; + + wpa_printf(MSG_DEBUG, "Enable 4-address WDS mode for " + "STA " MACSTR " (aid %u)", + MAC2STR(sta->addr), sta->aid); + sta->flags |= WLAN_STA_WDS; + ret = hostapd_set_wds_sta(hapd, ifname_wds, + sta->addr, sta->aid, 1); + if (!ret) + hostapd_set_wds_encryption(hapd, sta, + ifname_wds); + } + return; + } +#endif + + wpa_printf(MSG_DEBUG, "Data/PS-poll frame from not associated STA " + MACSTR, MAC2STR(src)); + if (src[0] & 0x01) { + /* Broadcast bit set in SA?! Ignore the frame silently. */ + return; + } + + if (sta && (sta->flags & WLAN_STA_ASSOC_REQ_OK)) { + wpa_printf(MSG_DEBUG, "Association Response to the STA has " + "already been sent, but no TX status yet known - " + "ignore Class 3 frame issue with " MACSTR, + MAC2STR(src)); + return; + } + + if (sta && (sta->flags & WLAN_STA_AUTH)) + hostapd_drv_sta_disassoc( + hapd, src, + WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); + else + hostapd_drv_sta_deauth( + hapd, src, + WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); +} diff --git a/beken_os/beken378/func/hostapd-2.5/src/ap/ieee802_11.h b/beken_os/beken378/func/hostapd-2.5/src/ap/ieee802_11.h new file mode 100755 index 0000000..44c1bff --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/ap/ieee802_11.h @@ -0,0 +1,107 @@ +/* + * hostapd / IEEE 802.11 Management + * Copyright (c) 2002-2009, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef IEEE802_11_H +#define IEEE802_11_H + +struct hostapd_iface; +struct hostapd_data; +struct sta_info; +struct hostapd_frame_info; +struct ieee80211_ht_capabilities; +struct ieee80211_vht_capabilities; +struct ieee80211_mgmt; + +int ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len, + struct hostapd_frame_info *fi); +void ieee802_11_mgmt_cb(struct hostapd_data *hapd, const u8 *buf, size_t len, + u16 stype, int ok); +void hostapd_2040_coex_action(struct hostapd_data *hapd, + const struct ieee80211_mgmt *mgmt, size_t len); +#ifdef NEED_AP_MLME +int ieee802_11_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen); +int ieee802_11_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta, + char *buf, size_t buflen); +#else /* NEED_AP_MLME */ +static inline int ieee802_11_get_mib(struct hostapd_data *hapd, char *buf, + size_t buflen) +{ + return 0; +} + +static inline int ieee802_11_get_mib_sta(struct hostapd_data *hapd, + struct sta_info *sta, + char *buf, size_t buflen) +{ + return 0; +} +#endif /* NEED_AP_MLME */ +u16 hostapd_own_capab_info(struct hostapd_data *hapd); +void ap_ht2040_timeout(void *eloop_data, void *user_data); +u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid); +u8 * hostapd_eid_qos_map_set(struct hostapd_data *hapd, u8 *eid); +u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid); +u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid); +u8 * hostapd_eid_ht_capabilities(struct hostapd_data *hapd, u8 *eid); +u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid); +u8 * hostapd_eid_vht_capabilities(struct hostapd_data *hapd, u8 *eid); +u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid); +u8 * hostapd_eid_vendor_vht(struct hostapd_data *hapd, u8 *eid); +int hostapd_ht_operation_update(struct hostapd_iface *iface); +void ieee802_11_send_sa_query_req(struct hostapd_data *hapd, + const u8 *addr, const u8 *trans_id); +void hostapd_get_ht_capab(struct hostapd_data *hapd, + struct ieee80211_ht_capabilities *ht_cap, + struct ieee80211_ht_capabilities *neg_ht_cap); +void hostapd_get_vht_capab(struct hostapd_data *hapd, + struct ieee80211_vht_capabilities *vht_cap, + struct ieee80211_vht_capabilities *neg_vht_cap); +u16 copy_sta_ht_capab(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *ht_capab); +u16 copy_sta_vendor_vht(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *ie, size_t len); + +void update_ht_state(struct hostapd_data *hapd, struct sta_info *sta); +void ht40_intolerant_add(struct hostapd_iface *iface, struct sta_info *sta); +void ht40_intolerant_remove(struct hostapd_iface *iface, struct sta_info *sta); +u16 copy_sta_vht_capab(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *vht_capab); +u16 set_sta_vht_opmode(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *vht_opmode); +void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr, + const u8 *buf, size_t len, int ack); +void hostapd_eapol_tx_status(struct hostapd_data *hapd, const u8 *dst, + const u8 *data, size_t len, int ack); +void ieee802_11_rx_from_unknown(struct hostapd_data *hapd, const u8 *src, + int wds); +u8 * hostapd_eid_assoc_comeback_time(struct hostapd_data *hapd, + struct sta_info *sta, u8 *eid); +void ieee802_11_sa_query_action(struct hostapd_data *hapd, + const u8 *sa, const u8 action_type, + const u8 *trans_id); +u8 * hostapd_eid_interworking(struct hostapd_data *hapd, u8 *eid); +u8 * hostapd_eid_adv_proto(struct hostapd_data *hapd, u8 *eid); +u8 * hostapd_eid_roaming_consortium(struct hostapd_data *hapd, u8 *eid); +u8 * hostapd_eid_time_adv(struct hostapd_data *hapd, u8 *eid); +u8 * hostapd_eid_time_zone(struct hostapd_data *hapd, u8 *eid); +int hostapd_update_time_adv(struct hostapd_data *hapd); +void hostapd_client_poll_ok(struct hostapd_data *hapd, const u8 *addr); +u8 * hostapd_eid_bss_max_idle_period(struct hostapd_data *hapd, u8 *eid); + +int auth_sae_init_committed(struct hostapd_data *hapd, struct sta_info *sta); +#ifdef CONFIG_SAE +void sae_clear_retransmit_timer(struct hostapd_data *hapd, + struct sta_info *sta); +#else /* CONFIG_SAE */ +static inline void sae_clear_retransmit_timer(struct hostapd_data *hapd, + struct sta_info *sta) +{ +} +#endif /* CONFIG_SAE */ + +#endif /* IEEE802_11_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/ap/ieee802_11_auth.c b/beken_os/beken378/func/hostapd-2.5/src/ap/ieee802_11_auth.c new file mode 100755 index 0000000..a76690a --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/ap/ieee802_11_auth.c @@ -0,0 +1,648 @@ +/* + * hostapd / IEEE 802.11 authentication (ACL) + * Copyright (c) 2003-2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + * + * Access control list for IEEE 802.11 authentication can uses statically + * configured ACL from configuration files or an external RADIUS server. + * Results from external RADIUS queries are cached to allow faster + * authentication frame processing. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "utils/eloop.h" +#include "crypto/sha1.h" +#include "ap/hostapd.h" +#include "ap_config.h" +#include "ap_drv_ops.h" +#include "ieee802_11.h" +#include "ieee802_1x.h" +#include "ieee802_11_auth.h" + +#define RADIUS_ACL_TIMEOUT 30 + + +struct hostapd_cached_radius_acl { + struct os_reltime timestamp; + macaddr addr; + int accepted; /* HOSTAPD_ACL_* */ + struct hostapd_cached_radius_acl *next; + u32 session_timeout; + u32 acct_interim_interval; + int vlan_id; + struct hostapd_sta_wpa_psk_short *psk; + char *identity; + char *radius_cui; +}; + + +struct hostapd_acl_query_data { + struct os_reltime timestamp; + u8 radius_id; + macaddr addr; + u8 *auth_msg; /* IEEE 802.11 authentication frame from station */ + size_t auth_msg_len; + struct hostapd_acl_query_data *next; +}; + + +#ifndef CONFIG_NO_RADIUS +static void hostapd_acl_cache_free_entry(struct hostapd_cached_radius_acl *e) +{ + os_free(e->identity); + os_free(e->radius_cui); + hostapd_free_psk_list(e->psk); + os_free(e); +} + + +static void hostapd_acl_cache_free(struct hostapd_cached_radius_acl *acl_cache) +{ + struct hostapd_cached_radius_acl *prev; + + while (acl_cache) { + prev = acl_cache; + acl_cache = acl_cache->next; + hostapd_acl_cache_free_entry(prev); + } +} + + +static void copy_psk_list(struct hostapd_sta_wpa_psk_short **psk, + struct hostapd_sta_wpa_psk_short *src) +{ + struct hostapd_sta_wpa_psk_short **copy_to; + struct hostapd_sta_wpa_psk_short *copy_from; + + /* Copy PSK linked list */ + copy_to = psk; + copy_from = src; + while (copy_from && copy_to) { + *copy_to = os_zalloc(sizeof(struct hostapd_sta_wpa_psk_short)); + if (*copy_to == NULL) + break; + os_memcpy(*copy_to, copy_from, + sizeof(struct hostapd_sta_wpa_psk_short)); + copy_from = copy_from->next; + copy_to = &((*copy_to)->next); + } + if (copy_to) + *copy_to = NULL; +} + + +static int hostapd_acl_cache_get(struct hostapd_data *hapd, const u8 *addr, + u32 *session_timeout, + u32 *acct_interim_interval, int *vlan_id, + struct hostapd_sta_wpa_psk_short **psk, + char **identity, char **radius_cui) +{ + struct hostapd_cached_radius_acl *entry; + struct os_reltime now; + + os_get_reltime(&now); + + for (entry = hapd->acl_cache; entry; entry = entry->next) { + if (os_memcmp(entry->addr, addr, ETH_ALEN) != 0) + continue; + + if (os_reltime_expired(&now, &entry->timestamp, + RADIUS_ACL_TIMEOUT)) + return -1; /* entry has expired */ + if (entry->accepted == HOSTAPD_ACL_ACCEPT_TIMEOUT) + if (session_timeout) + *session_timeout = entry->session_timeout; + if (acct_interim_interval) + *acct_interim_interval = + entry->acct_interim_interval; + if (vlan_id) + *vlan_id = entry->vlan_id; + copy_psk_list(psk, entry->psk); + if (identity) { + if (entry->identity) + *identity = os_strdup(entry->identity); + else + *identity = NULL; + } + if (radius_cui) { + if (entry->radius_cui) + *radius_cui = os_strdup(entry->radius_cui); + else + *radius_cui = NULL; + } + return entry->accepted; + } + + return -1; +} +#endif /* CONFIG_NO_RADIUS */ + +#ifdef CONFIG_FULL_HOSTAPD +static void hostapd_acl_query_free(struct hostapd_acl_query_data *query) +{ + if (query == NULL) + return; + os_free(query->auth_msg); + os_free(query); +} +#endif + +#ifndef CONFIG_NO_RADIUS +static int hostapd_radius_acl_query(struct hostapd_data *hapd, const u8 *addr, + struct hostapd_acl_query_data *query) +{ + struct radius_msg *msg; + char buf[128]; + + query->radius_id = radius_client_get_id(hapd->radius); + msg = radius_msg_new(RADIUS_CODE_ACCESS_REQUEST, query->radius_id); + if (msg == NULL) + return -1; + + radius_msg_make_authenticator(msg, addr, ETH_ALEN); + + os_snprintf(buf, sizeof(buf), RADIUS_ADDR_FORMAT, MAC2STR(addr)); + if (!radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME, (u8 *) buf, + os_strlen(buf))) { + wpa_printf(MSG_DEBUG, "Could not add User-Name"); + goto fail; + } + + if (!radius_msg_add_attr_user_password( + msg, (u8 *) buf, os_strlen(buf), + hapd->conf->radius->auth_server->shared_secret, + hapd->conf->radius->auth_server->shared_secret_len)) { + wpa_printf(MSG_DEBUG, "Could not add User-Password"); + goto fail; + } + + if (add_common_radius_attr(hapd, hapd->conf->radius_auth_req_attr, + NULL, msg) < 0) + goto fail; + + os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT, + MAC2STR(addr)); + if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID, + (u8 *) buf, os_strlen(buf))) { + wpa_printf(MSG_DEBUG, "Could not add Calling-Station-Id"); + goto fail; + } + + os_snprintf(buf, sizeof(buf), "CONNECT 11Mbps 802.11b"); + if (!radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO, + (u8 *) buf, os_strlen(buf))) { + wpa_printf(MSG_DEBUG, "Could not add Connect-Info"); + goto fail; + } + + if (radius_client_send(hapd->radius, msg, RADIUS_AUTH, addr) < 0) + goto fail; + return 0; + + fail: + radius_msg_free(msg); + return -1; +} +#endif /* CONFIG_NO_RADIUS */ + + +#ifdef CONFIG_FULL_HOSTAPD +/** + * hostapd_allowed_address - Check whether a specified STA can be authenticated + * @hapd: hostapd BSS data + * @addr: MAC address of the STA + * @msg: Authentication message + * @len: Length of msg in octets + * @session_timeout: Buffer for returning session timeout (from RADIUS) + * @acct_interim_interval: Buffer for returning account interval (from RADIUS) + * @vlan_id: Buffer for returning VLAN ID + * @psk: Linked list buffer for returning WPA PSK + * @identity: Buffer for returning identity (from RADIUS) + * @radius_cui: Buffer for returning CUI (from RADIUS) + * Returns: HOSTAPD_ACL_ACCEPT, HOSTAPD_ACL_REJECT, or HOSTAPD_ACL_PENDING + * + * The caller is responsible for freeing the returned *identity and *radius_cui + * values with os_free(). + */ +int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr, + const u8 *msg, size_t len, u32 *session_timeout, + u32 *acct_interim_interval, int *vlan_id, + struct hostapd_sta_wpa_psk_short **psk, + char **identity, char **radius_cui) +{ + if (session_timeout) + *session_timeout = 0; + if (acct_interim_interval) + *acct_interim_interval = 0; + if (vlan_id) + *vlan_id = 0; + if (psk) + *psk = NULL; + if (identity) + *identity = NULL; + if (radius_cui) + *radius_cui = NULL; + + if (hostapd_maclist_found(hapd->conf->accept_mac, + hapd->conf->num_accept_mac, addr, vlan_id)) + return HOSTAPD_ACL_ACCEPT; + + if (hostapd_maclist_found(hapd->conf->deny_mac, + hapd->conf->num_deny_mac, addr, vlan_id)) + return HOSTAPD_ACL_REJECT; + + if (hapd->conf->macaddr_acl == ACCEPT_UNLESS_DENIED) + return HOSTAPD_ACL_ACCEPT; + if (hapd->conf->macaddr_acl == DENY_UNLESS_ACCEPTED) + return HOSTAPD_ACL_REJECT; + + if (hapd->conf->macaddr_acl == USE_EXTERNAL_RADIUS_AUTH) { +#ifdef CONFIG_NO_RADIUS + return HOSTAPD_ACL_REJECT; +#else /* CONFIG_NO_RADIUS */ + struct hostapd_acl_query_data *query; + + /* Check whether ACL cache has an entry for this station */ + int res = hostapd_acl_cache_get(hapd, addr, session_timeout, + acct_interim_interval, + vlan_id, psk, + identity, radius_cui); + if (res == HOSTAPD_ACL_ACCEPT || + res == HOSTAPD_ACL_ACCEPT_TIMEOUT) + return res; + if (res == HOSTAPD_ACL_REJECT) + return HOSTAPD_ACL_REJECT; + + query = hapd->acl_queries; + while (query) { + if (os_memcmp(query->addr, addr, ETH_ALEN) == 0) { + /* pending query in RADIUS retransmit queue; + * do not generate a new one */ + if (identity) { + os_free(*identity); + *identity = NULL; + } + if (radius_cui) { + os_free(*radius_cui); + *radius_cui = NULL; + } + return HOSTAPD_ACL_PENDING; + } + query = query->next; + } + + if (!hapd->conf->radius->auth_server) + return HOSTAPD_ACL_REJECT; + + /* No entry in the cache - query external RADIUS server */ + query = os_zalloc(sizeof(*query)); + if (query == NULL) { + wpa_printf(MSG_ERROR, "malloc for query data failed"); + return HOSTAPD_ACL_REJECT; + } + os_get_reltime(&query->timestamp); + os_memcpy(query->addr, addr, ETH_ALEN); + if (hostapd_radius_acl_query(hapd, addr, query)) { + wpa_printf(MSG_DEBUG, "Failed to send Access-Request " + "for ACL query."); + hostapd_acl_query_free(query); + return HOSTAPD_ACL_REJECT; + } + + query->auth_msg = os_malloc(len); + if (query->auth_msg == NULL) { + wpa_printf(MSG_ERROR, "Failed to allocate memory for " + "auth frame."); + hostapd_acl_query_free(query); + return HOSTAPD_ACL_REJECT; + } + os_memcpy(query->auth_msg, msg, len); + query->auth_msg_len = len; + query->next = hapd->acl_queries; + hapd->acl_queries = query; + + /* Queued data will be processed in hostapd_acl_recv_radius() + * when RADIUS server replies to the sent Access-Request. */ + return HOSTAPD_ACL_PENDING; +#endif /* CONFIG_NO_RADIUS */ + } + + return HOSTAPD_ACL_REJECT; +} +#endif + +#ifndef CONFIG_NO_RADIUS +static void hostapd_acl_expire_cache(struct hostapd_data *hapd, + struct os_reltime *now) +{ + struct hostapd_cached_radius_acl *prev, *entry, *tmp; + + prev = NULL; + entry = hapd->acl_cache; + + while (entry) { + if (os_reltime_expired(now, &entry->timestamp, + RADIUS_ACL_TIMEOUT)) { + wpa_printf(MSG_DEBUG, "Cached ACL entry for " MACSTR + " has expired.", MAC2STR(entry->addr)); + if (prev) + prev->next = entry->next; + else + hapd->acl_cache = entry->next; + hostapd_drv_set_radius_acl_expire(hapd, entry->addr); + tmp = entry; + entry = entry->next; + hostapd_acl_cache_free_entry(tmp); + continue; + } + + prev = entry; + entry = entry->next; + } +} + + +static void hostapd_acl_expire_queries(struct hostapd_data *hapd, + struct os_reltime *now) +{ + struct hostapd_acl_query_data *prev, *entry, *tmp; + + prev = NULL; + entry = hapd->acl_queries; + + while (entry) { + if (os_reltime_expired(now, &entry->timestamp, + RADIUS_ACL_TIMEOUT)) { + wpa_printf(MSG_DEBUG, "ACL query for " MACSTR + " has expired.", MAC2STR(entry->addr)); + if (prev) + prev->next = entry->next; + else + hapd->acl_queries = entry->next; + + tmp = entry; + entry = entry->next; + hostapd_acl_query_free(tmp); + continue; + } + + prev = entry; + entry = entry->next; + } +} + + +/** + * hostapd_acl_expire - ACL cache expiration callback + * @hapd: struct hostapd_data * + */ +void hostapd_acl_expire(struct hostapd_data *hapd) +{ + struct os_reltime now; + + os_get_reltime(&now); + hostapd_acl_expire_cache(hapd, &now); + hostapd_acl_expire_queries(hapd, &now); +} + + +static void decode_tunnel_passwords(struct hostapd_data *hapd, + const u8 *shared_secret, + size_t shared_secret_len, + struct radius_msg *msg, + struct radius_msg *req, + struct hostapd_cached_radius_acl *cache) +{ + int passphraselen; + char *passphrase, *strpassphrase; + size_t i; + struct hostapd_sta_wpa_psk_short *psk; + + /* + * Decode all tunnel passwords as PSK and save them into a linked list. + */ + for (i = 0; ; i++) { + passphrase = radius_msg_get_tunnel_password( + msg, &passphraselen, shared_secret, shared_secret_len, + req, i); + /* + * Passphrase is NULL iff there is no i-th Tunnel-Password + * attribute in msg. + */ + if (passphrase == NULL) + break; + /* + * passphrase does not contain the NULL termination. + * Add it here as pbkdf2_sha1() requires it. + */ + strpassphrase = os_zalloc(passphraselen + 1); + psk = os_zalloc(sizeof(struct hostapd_sta_wpa_psk_short)); + if (strpassphrase && psk) { + os_memcpy(strpassphrase, passphrase, passphraselen); + pbkdf2_sha1(strpassphrase, + hapd->conf->ssid.ssid, + hapd->conf->ssid.ssid_len, 4096, + psk->psk, PMK_LEN); + psk->next = cache->psk; + cache->psk = psk; + psk = NULL; + } + os_free(strpassphrase); + os_free(psk); + os_free(passphrase); + } +} + + +/** + * hostapd_acl_recv_radius - Process incoming RADIUS Authentication messages + * @msg: RADIUS response message + * @req: RADIUS request message + * @shared_secret: RADIUS shared secret + * @shared_secret_len: Length of shared_secret in octets + * @data: Context data (struct hostapd_data *) + * Returns: RADIUS_RX_PROCESSED if RADIUS message was a reply to ACL query (and + * was processed here) or RADIUS_RX_UNKNOWN if not. + */ +static RadiusRxResult +hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req, + const u8 *shared_secret, size_t shared_secret_len, + void *data) +{ + struct hostapd_data *hapd = data; + struct hostapd_acl_query_data *query, *prev; + struct hostapd_cached_radius_acl *cache; + struct radius_hdr *hdr = radius_msg_get_hdr(msg); + + query = hapd->acl_queries; + prev = NULL; + while (query) { + if (query->radius_id == hdr->identifier) + break; + prev = query; + query = query->next; + } + if (query == NULL) + return RADIUS_RX_UNKNOWN; + + wpa_printf(MSG_DEBUG, "Found matching Access-Request for RADIUS " + "message (id=%d)", query->radius_id); + + if (radius_msg_verify(msg, shared_secret, shared_secret_len, req, 0)) { + wpa_printf(MSG_INFO, "Incoming RADIUS packet did not have " + "correct authenticator - dropped\n"); + return RADIUS_RX_INVALID_AUTHENTICATOR; + } + + if (hdr->code != RADIUS_CODE_ACCESS_ACCEPT && + hdr->code != RADIUS_CODE_ACCESS_REJECT) { + wpa_printf(MSG_DEBUG, "Unknown RADIUS message code %d to ACL " + "query", hdr->code); + return RADIUS_RX_UNKNOWN; + } + + /* Insert Accept/Reject info into ACL cache */ + cache = os_zalloc(sizeof(*cache)); + if (cache == NULL) { + wpa_printf(MSG_DEBUG, "Failed to add ACL cache entry"); + goto done; + } + os_get_reltime(&cache->timestamp); + os_memcpy(cache->addr, query->addr, sizeof(cache->addr)); + if (hdr->code == RADIUS_CODE_ACCESS_ACCEPT) { + u8 *buf; + size_t len; + + if (radius_msg_get_attr_int32(msg, RADIUS_ATTR_SESSION_TIMEOUT, + &cache->session_timeout) == 0) + cache->accepted = HOSTAPD_ACL_ACCEPT_TIMEOUT; + else + cache->accepted = HOSTAPD_ACL_ACCEPT; + + if (radius_msg_get_attr_int32( + msg, RADIUS_ATTR_ACCT_INTERIM_INTERVAL, + &cache->acct_interim_interval) == 0 && + cache->acct_interim_interval < 60) { + wpa_printf(MSG_DEBUG, "Ignored too small " + "Acct-Interim-Interval %d for STA " MACSTR, + cache->acct_interim_interval, + MAC2STR(query->addr)); + cache->acct_interim_interval = 0; + } + + cache->vlan_id = radius_msg_get_vlanid(msg); + + decode_tunnel_passwords(hapd, shared_secret, shared_secret_len, + msg, req, cache); + + if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_USER_NAME, + &buf, &len, NULL) == 0) { + cache->identity = os_zalloc(len + 1); + if (cache->identity) + os_memcpy(cache->identity, buf, len); + } + if (radius_msg_get_attr_ptr( + msg, RADIUS_ATTR_CHARGEABLE_USER_IDENTITY, + &buf, &len, NULL) == 0) { + cache->radius_cui = os_zalloc(len + 1); + if (cache->radius_cui) + os_memcpy(cache->radius_cui, buf, len); + } + + if (hapd->conf->wpa_psk_radius == PSK_RADIUS_REQUIRED && + !cache->psk) + cache->accepted = HOSTAPD_ACL_REJECT; + + if (cache->vlan_id && + !hostapd_vlan_id_valid(hapd->conf->vlan, cache->vlan_id)) { + hostapd_logger(hapd, query->addr, + HOSTAPD_MODULE_RADIUS, + HOSTAPD_LEVEL_INFO, + "Invalid VLAN ID %d received from RADIUS server", + cache->vlan_id); + cache->vlan_id = 0; + } + if (hapd->conf->ssid.dynamic_vlan == DYNAMIC_VLAN_REQUIRED && + !cache->vlan_id) + cache->accepted = HOSTAPD_ACL_REJECT; + } else + cache->accepted = HOSTAPD_ACL_REJECT; + cache->next = hapd->acl_cache; + hapd->acl_cache = cache; + +#ifdef CONFIG_DRIVER_RADIUS_ACL + hostapd_drv_set_radius_acl_auth(hapd, query->addr, cache->accepted, + cache->session_timeout); +#else /* CONFIG_DRIVER_RADIUS_ACL */ +#ifdef NEED_AP_MLME + /* Re-send original authentication frame for 802.11 processing */ + wpa_printf(MSG_DEBUG, "Re-sending authentication frame after " + "successful RADIUS ACL query"); + ieee802_11_mgmt(hapd, query->auth_msg, query->auth_msg_len, NULL); +#endif /* NEED_AP_MLME */ +#endif /* CONFIG_DRIVER_RADIUS_ACL */ + + done: + if (prev == NULL) + hapd->acl_queries = query->next; + else + prev->next = query->next; + + hostapd_acl_query_free(query); + + return RADIUS_RX_PROCESSED; +} +#endif /* CONFIG_NO_RADIUS */ + + +/** + * hostapd_acl_init: Initialize IEEE 802.11 ACL + * @hapd: hostapd BSS data + * Returns: 0 on success, -1 on failure + */ +int hostapd_acl_init(struct hostapd_data *hapd) +{ +#ifndef CONFIG_NO_RADIUS + if (radius_client_register(hapd->radius, RADIUS_AUTH, + hostapd_acl_recv_radius, hapd)) + return -1; +#endif /* CONFIG_NO_RADIUS */ + + return 0; +} + + +#ifdef CONFIG_FULL_HOSTAPD +/** + * hostapd_acl_deinit - Deinitialize IEEE 802.11 ACL + * @hapd: hostapd BSS data + */ +void hostapd_acl_deinit(struct hostapd_data *hapd) +{ + struct hostapd_acl_query_data *query, *prev; + +#ifndef CONFIG_NO_RADIUS + hostapd_acl_cache_free(hapd->acl_cache); +#endif /* CONFIG_NO_RADIUS */ + + query = hapd->acl_queries; + while (query) { + prev = query; + query = query->next; + hostapd_acl_query_free(prev); + } +} +#endif + +void hostapd_free_psk_list(struct hostapd_sta_wpa_psk_short *psk) +{ + while (psk) { + struct hostapd_sta_wpa_psk_short *prev = psk; + psk = psk->next; + os_free(prev); + } +} diff --git a/beken_os/beken378/func/hostapd-2.5/src/ap/ieee802_11_auth.h b/beken_os/beken378/func/hostapd-2.5/src/ap/ieee802_11_auth.h new file mode 100755 index 0000000..b66f244 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/ap/ieee802_11_auth.h @@ -0,0 +1,29 @@ +/* + * hostapd / IEEE 802.11 authentication (ACL) + * Copyright (c) 2003-2005, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef IEEE802_11_AUTH_H +#define IEEE802_11_AUTH_H + +enum { + HOSTAPD_ACL_REJECT = 0, + HOSTAPD_ACL_ACCEPT = 1, + HOSTAPD_ACL_PENDING = 2, + HOSTAPD_ACL_ACCEPT_TIMEOUT = 3 +}; + +int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr, + const u8 *msg, size_t len, u32 *session_timeout, + u32 *acct_interim_interval, int *vlan_id, + struct hostapd_sta_wpa_psk_short **psk, + char **identity, char **radius_cui); +int hostapd_acl_init(struct hostapd_data *hapd); +void hostapd_acl_deinit(struct hostapd_data *hapd); +void hostapd_free_psk_list(struct hostapd_sta_wpa_psk_short *psk); +void hostapd_acl_expire(struct hostapd_data *hapd); + +#endif /* IEEE802_11_AUTH_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/ap/ieee802_11_ht.c b/beken_os/beken378/func/hostapd-2.5/src/ap/ieee802_11_ht.c new file mode 100755 index 0000000..105846d --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/ap/ieee802_11_ht.c @@ -0,0 +1,490 @@ +/* + * hostapd / IEEE 802.11n HT + * Copyright (c) 2002-2009, Jouni Malinen + * Copyright (c) 2007-2008, Intel Corporation + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "utils/eloop.h" +#include "common/ieee802_11_defs.h" +#include "ap/hostapd.h" +#include "ap_config.h" +#include "ap/sta_info.h" +#include "beacon.h" +#include "ieee802_11.h" +#include "hw_features.h" +#include "ap_drv_ops.h" + + +u8 * hostapd_eid_ht_capabilities(struct hostapd_data *hapd, u8 *eid) +{ + struct ieee80211_ht_capabilities *cap; + u8 *pos = eid; + + if (!hapd->iconf->ieee80211n || !hapd->iface->current_mode || + hapd->conf->disable_11n) + return eid; + + *pos++ = WLAN_EID_HT_CAP; + *pos++ = sizeof(*cap); + + cap = (struct ieee80211_ht_capabilities *) pos; + os_memset(cap, 0, sizeof(*cap)); + cap->ht_capabilities_info = host_to_le16(hapd->iconf->ht_capab); + cap->a_mpdu_params = hapd->iface->current_mode->a_mpdu_params; + os_memcpy(cap->supported_mcs_set, hapd->iface->current_mode->mcs_set, + 16); + + /* TODO: ht_extended_capabilities (now fully disabled) */ + /* TODO: tx_bf_capability_info (now fully disabled) */ + /* TODO: asel_capabilities (now fully disabled) */ + + pos += sizeof(*cap); + + if (hapd->iconf->obss_interval) { + struct ieee80211_obss_scan_parameters *scan_params; + + *pos++ = WLAN_EID_OVERLAPPING_BSS_SCAN_PARAMS; + *pos++ = sizeof(*scan_params); + + scan_params = (struct ieee80211_obss_scan_parameters *) pos; + os_memset(scan_params, 0, sizeof(*scan_params)); + scan_params->width_trigger_scan_interval = + host_to_le16(hapd->iconf->obss_interval); + + /* Fill in default values for remaining parameters + * (IEEE Std 802.11-2012, 8.4.2.61 and MIB defval) */ + scan_params->scan_passive_dwell = + host_to_le16(20); + scan_params->scan_active_dwell = + host_to_le16(10); + scan_params->scan_passive_total_per_channel = + host_to_le16(200); + scan_params->scan_active_total_per_channel = + host_to_le16(20); + scan_params->channel_transition_delay_factor = + host_to_le16(5); + scan_params->scan_activity_threshold = + host_to_le16(25); + + pos += sizeof(*scan_params); + } + + return pos; +} + + +u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid) +{ + struct ieee80211_ht_operation *oper; + u8 *pos = eid; + + if (!hapd->iconf->ieee80211n || hapd->conf->disable_11n) + return eid; + + *pos++ = WLAN_EID_HT_OPERATION; + *pos++ = sizeof(*oper); + + oper = (struct ieee80211_ht_operation *) pos; + os_memset(oper, 0, sizeof(*oper)); + + oper->primary_chan = hapd->iconf->channel; + oper->operation_mode = host_to_le16(hapd->iface->ht_op_mode); + if (hapd->iconf->secondary_channel == 1) + oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE | + HT_INFO_HT_PARAM_STA_CHNL_WIDTH; + if (hapd->iconf->secondary_channel == -1) + oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW | + HT_INFO_HT_PARAM_STA_CHNL_WIDTH; + + pos += sizeof(*oper); + + return pos; +} + + +/* +op_mode +Set to 0 (HT pure) under the followign conditions + - all STAs in the BSS are 20/40 MHz HT in 20/40 MHz BSS or + - all STAs in the BSS are 20 MHz HT in 20 MHz BSS +Set to 1 (HT non-member protection) if there may be non-HT STAs + in both the primary and the secondary channel +Set to 2 if only HT STAs are associated in BSS, + however and at least one 20 MHz HT STA is associated +Set to 3 (HT mixed mode) when one or more non-HT STAs are associated +*/ +int hostapd_ht_operation_update(struct hostapd_iface *iface) +{ + u16 cur_op_mode, new_op_mode; + int op_mode_changes = 0; + + if (!iface->conf->ieee80211n || iface->conf->ht_op_mode_fixed) + return 0; + + wpa_printf(MSG_DEBUG, "%s current operation mode=0x%X", + __func__, iface->ht_op_mode); + + if (!(iface->ht_op_mode & HT_OPER_OP_MODE_NON_GF_HT_STAS_PRESENT) + && iface->num_sta_ht_no_gf) { + iface->ht_op_mode |= HT_OPER_OP_MODE_NON_GF_HT_STAS_PRESENT; + op_mode_changes++; + } else if ((iface->ht_op_mode & + HT_OPER_OP_MODE_NON_GF_HT_STAS_PRESENT) && + iface->num_sta_ht_no_gf == 0) { + iface->ht_op_mode &= ~HT_OPER_OP_MODE_NON_GF_HT_STAS_PRESENT; + op_mode_changes++; + } + + if (!(iface->ht_op_mode & HT_OPER_OP_MODE_OBSS_NON_HT_STAS_PRESENT) && + (iface->num_sta_no_ht || iface->olbc_ht)) { + iface->ht_op_mode |= HT_OPER_OP_MODE_OBSS_NON_HT_STAS_PRESENT; + op_mode_changes++; + } else if ((iface->ht_op_mode & + HT_OPER_OP_MODE_OBSS_NON_HT_STAS_PRESENT) && + (iface->num_sta_no_ht == 0 && !iface->olbc_ht)) { + iface->ht_op_mode &= ~HT_OPER_OP_MODE_OBSS_NON_HT_STAS_PRESENT; + op_mode_changes++; + } + + if (iface->num_sta_no_ht) + new_op_mode = HT_PROT_NON_HT_MIXED; + else if (iface->conf->secondary_channel && iface->num_sta_ht_20mhz) + new_op_mode = HT_PROT_20MHZ_PROTECTION; + else if (iface->olbc_ht) + new_op_mode = HT_PROT_NONMEMBER_PROTECTION; + else + new_op_mode = HT_PROT_NO_PROTECTION; + + cur_op_mode = iface->ht_op_mode & HT_OPER_OP_MODE_HT_PROT_MASK; + if (cur_op_mode != new_op_mode) { + iface->ht_op_mode &= ~HT_OPER_OP_MODE_HT_PROT_MASK; + iface->ht_op_mode |= new_op_mode; + op_mode_changes++; + } + + wpa_printf(MSG_DEBUG, "%s new operation mode=0x%X changes=%d", + __func__, iface->ht_op_mode, op_mode_changes); + + return op_mode_changes; +} + + +static int is_40_allowed(struct hostapd_iface *iface, int channel) +{ + int pri_freq, sec_freq; + int affected_start, affected_end; + int pri = 2407 + 5 * channel; + + if (iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G) + return 1; + + pri_freq = hostapd_hw_get_freq(iface->bss[0], iface->conf->channel); + + if (iface->conf->secondary_channel > 0) + sec_freq = pri_freq + 20; + else + sec_freq = pri_freq - 20; + + affected_start = (pri_freq + sec_freq) / 2 - 25; + affected_end = (pri_freq + sec_freq) / 2 + 25; + if ((pri < affected_start || pri > affected_end)) + return 1; /* not within affected channel range */ + + wpa_printf(MSG_ERROR, "40 MHz affected channel range: [%d,%d] MHz", + affected_start, affected_end); + wpa_printf(MSG_ERROR, "Neighboring BSS: freq=%d", pri); + return 0; +} + + +void hostapd_2040_coex_action(struct hostapd_data *hapd, + const struct ieee80211_mgmt *mgmt, size_t len) +{ + struct hostapd_iface *iface = hapd->iface; + struct ieee80211_2040_bss_coex_ie *bc_ie; + struct ieee80211_2040_intol_chan_report *ic_report; + int is_ht40_allowed = 1; + int i; + const u8 *start = (const u8 *) mgmt; + const u8 *data = start + IEEE80211_HDRLEN + 2; + + hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, "hostapd_public_action - action=%d", + mgmt->u.action.u.public_action.action); + + if (!(iface->conf->ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) + return; + + if (len < IEEE80211_HDRLEN + 2 + sizeof(*bc_ie)) + return; + + bc_ie = (struct ieee80211_2040_bss_coex_ie *) data; + if (bc_ie->element_id != WLAN_EID_20_40_BSS_COEXISTENCE || + bc_ie->length < 1) { + wpa_printf(MSG_DEBUG, "Unexpected IE (%u,%u) in coex report", + bc_ie->element_id, bc_ie->length); + return; + } + if (len < IEEE80211_HDRLEN + 2 + 2 + bc_ie->length) + return; + data += 2 + bc_ie->length; + + wpa_printf(MSG_DEBUG, "20/40 BSS Coexistence Information field: 0x%x", + bc_ie->coex_param); + if (bc_ie->coex_param & WLAN_20_40_BSS_COEX_20MHZ_WIDTH_REQ) { + hostapd_logger(hapd, mgmt->sa, + HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "20 MHz BSS width request bit is set in BSS coexistence information field"); + is_ht40_allowed = 0; + } + + if (bc_ie->coex_param & WLAN_20_40_BSS_COEX_40MHZ_INTOL) { + hostapd_logger(hapd, mgmt->sa, + HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "40 MHz intolerant bit is set in BSS coexistence information field"); + is_ht40_allowed = 0; + } + + if (start + len - data >= 3 && + data[0] == WLAN_EID_20_40_BSS_INTOLERANT && data[1] >= 1) { + u8 ielen = data[1]; + + if (ielen > start + len - data - 2) + return; + ic_report = (struct ieee80211_2040_intol_chan_report *) data; + wpa_printf(MSG_DEBUG, + "20/40 BSS Intolerant Channel Report: Operating Class %u", + ic_report->op_class); + + /* Go through the channel report to find any BSS there in the + * affected channel range */ + for (i = 0; i < ielen - 1; i++) { + u8 chan = ic_report->variable[i]; + + if (is_40_allowed(iface, chan)) + continue; + hostapd_logger(hapd, mgmt->sa, + HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "20_40_INTOLERANT channel %d reported", + chan); + is_ht40_allowed = 0; + } + } + wpa_printf(MSG_DEBUG, "is_ht40_allowed=%d num_sta_ht40_intolerant=%d", + is_ht40_allowed, iface->num_sta_ht40_intolerant); + + if (!is_ht40_allowed && + (iface->drv_flags & WPA_DRIVER_FLAGS_HT_2040_COEX)) { + if (iface->conf->secondary_channel) { + hostapd_logger(hapd, mgmt->sa, + HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, + "Switching to 20 MHz operation"); + iface->conf->secondary_channel = 0; + ieee802_11_set_beacons(iface); + } + if (!iface->num_sta_ht40_intolerant && + iface->conf->obss_interval) { + unsigned int delay_time; + delay_time = OVERLAPPING_BSS_TRANS_DELAY_FACTOR * + iface->conf->obss_interval; + eloop_cancel_timeout(ap_ht2040_timeout, hapd->iface, + NULL); + eloop_register_timeout(delay_time, 0, ap_ht2040_timeout, + hapd->iface, NULL); + wpa_printf(MSG_DEBUG, + "Reschedule HT 20/40 timeout to occur in %u seconds", + delay_time); + } + } +} + + +u16 copy_sta_ht_capab(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *ht_capab) +{ + /* + * Disable HT caps for STAs associated to no-HT BSSes, or for stations + * that did not specify a valid WMM IE in the (Re)Association Request + * frame. + */ + if (!ht_capab || + !(sta->flags & WLAN_STA_WMM) || hapd->conf->disable_11n) { + sta->flags &= ~WLAN_STA_HT; + os_free(sta->ht_capabilities); + sta->ht_capabilities = NULL; + return WLAN_STATUS_SUCCESS; + } + + if (sta->ht_capabilities == NULL) { + sta->ht_capabilities = + os_zalloc(sizeof(struct ieee80211_ht_capabilities)); + if (sta->ht_capabilities == NULL) + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + + sta->flags |= WLAN_STA_HT; + os_memcpy(sta->ht_capabilities, ht_capab, + sizeof(struct ieee80211_ht_capabilities)); + + return WLAN_STATUS_SUCCESS; +} + + +void ht40_intolerant_add(struct hostapd_iface *iface, struct sta_info *sta) +{ + if (iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G) + return; + + wpa_printf(MSG_INFO, "HT: Forty MHz Intolerant is set by STA " MACSTR + " in Association Request", MAC2STR(sta->addr)); + + if (sta->ht40_intolerant_set) + return; + + sta->ht40_intolerant_set = 1; + iface->num_sta_ht40_intolerant++; + eloop_cancel_timeout(ap_ht2040_timeout, iface, NULL); + + if (iface->conf->secondary_channel && + (iface->drv_flags & WPA_DRIVER_FLAGS_HT_2040_COEX)) { + iface->conf->secondary_channel = 0; + ieee802_11_set_beacons(iface); + } +} + + +void ht40_intolerant_remove(struct hostapd_iface *iface, struct sta_info *sta) +{ + if (!sta->ht40_intolerant_set) + return; + + sta->ht40_intolerant_set = 0; + iface->num_sta_ht40_intolerant--; + + if (iface->num_sta_ht40_intolerant == 0 && + (iface->conf->ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) && + (iface->drv_flags & WPA_DRIVER_FLAGS_HT_2040_COEX)) { + unsigned int delay_time = OVERLAPPING_BSS_TRANS_DELAY_FACTOR * + iface->conf->obss_interval; + wpa_printf(MSG_DEBUG, + "HT: Start 20->40 MHz transition timer (%d seconds)", + delay_time); + eloop_cancel_timeout(ap_ht2040_timeout, iface, NULL); + eloop_register_timeout(delay_time, 0, ap_ht2040_timeout, + iface, NULL); + } +} + + +static void update_sta_ht(struct hostapd_data *hapd, struct sta_info *sta) +{ + u16 ht_capab; + + ht_capab = le_to_host16(sta->ht_capabilities->ht_capabilities_info); + wpa_printf(MSG_DEBUG, "HT: STA " MACSTR " HT Capabilities Info: " + "0x%04x", MAC2STR(sta->addr), ht_capab); + if ((ht_capab & HT_CAP_INFO_GREEN_FIELD) == 0) { + if (!sta->no_ht_gf_set) { + sta->no_ht_gf_set = 1; + hapd->iface->num_sta_ht_no_gf++; + } + wpa_printf(MSG_DEBUG, "%s STA " MACSTR " - no greenfield, num " + "of non-gf stations %d", + __func__, MAC2STR(sta->addr), + hapd->iface->num_sta_ht_no_gf); + } + if ((ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) == 0) { + if (!sta->ht_20mhz_set) { + sta->ht_20mhz_set = 1; + hapd->iface->num_sta_ht_20mhz++; + } + wpa_printf(MSG_DEBUG, "%s STA " MACSTR " - 20 MHz HT, num of " + "20MHz HT STAs %d", + __func__, MAC2STR(sta->addr), + hapd->iface->num_sta_ht_20mhz); + } + + if (ht_capab & HT_CAP_INFO_40MHZ_INTOLERANT) + ht40_intolerant_add(hapd->iface, sta); +} + + +static void update_sta_no_ht(struct hostapd_data *hapd, struct sta_info *sta) +{ + if (!sta->no_ht_set) { + sta->no_ht_set = 1; + hapd->iface->num_sta_no_ht++; + } + if (hapd->iconf->ieee80211n) { + wpa_printf(MSG_DEBUG, "%s STA " MACSTR " - no HT, num of " + "non-HT stations %d", + __func__, MAC2STR(sta->addr), + hapd->iface->num_sta_no_ht); + } +} + + +void update_ht_state(struct hostapd_data *hapd, struct sta_info *sta) +{ + if ((sta->flags & WLAN_STA_HT) && sta->ht_capabilities) + update_sta_ht(hapd, sta); + else + update_sta_no_ht(hapd, sta); + + if (hostapd_ht_operation_update(hapd->iface) > 0) + ieee802_11_set_beacons(hapd->iface); +} + + +void hostapd_get_ht_capab(struct hostapd_data *hapd, + struct ieee80211_ht_capabilities *ht_cap, + struct ieee80211_ht_capabilities *neg_ht_cap) +{ + u16 cap; + + if (ht_cap == NULL) + return; + os_memcpy(neg_ht_cap, ht_cap, sizeof(*neg_ht_cap)); + cap = le_to_host16(neg_ht_cap->ht_capabilities_info); + + /* + * Mask out HT features we don't support, but don't overwrite + * non-symmetric features like STBC and SMPS. Just because + * we're not in dynamic SMPS mode the STA might still be. + */ + cap &= (hapd->iconf->ht_capab | HT_CAP_INFO_RX_STBC_MASK | + HT_CAP_INFO_TX_STBC | HT_CAP_INFO_SMPS_MASK); + + /* + * STBC needs to be handled specially + * if we don't support RX STBC, mask out TX STBC in the STA's HT caps + * if we don't support TX STBC, mask out RX STBC in the STA's HT caps + */ + if (!(hapd->iconf->ht_capab & HT_CAP_INFO_RX_STBC_MASK)) + cap &= ~HT_CAP_INFO_TX_STBC; + if (!(hapd->iconf->ht_capab & HT_CAP_INFO_TX_STBC)) + cap &= ~HT_CAP_INFO_RX_STBC_MASK; + + neg_ht_cap->ht_capabilities_info = host_to_le16(cap); +} + + +void ap_ht2040_timeout(void *eloop_data, void *user_data) +{ + struct hostapd_iface *iface = eloop_data; + + wpa_printf(MSG_INFO, "Switching to 40 MHz operation"); + + iface->conf->secondary_channel = iface->secondary_ch; + ieee802_11_set_beacons(iface); +} diff --git a/beken_os/beken378/func/hostapd-2.5/src/ap/ieee802_11_shared.c b/beken_os/beken378/func/hostapd-2.5/src/ap/ieee802_11_shared.c new file mode 100755 index 0000000..7d6130d --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/ap/ieee802_11_shared.c @@ -0,0 +1,508 @@ +/* + * hostapd / IEEE 802.11 Management + * Copyright (c) 2002-2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "common/ieee802_11_defs.h" +#include "ap/hostapd.h" +#include "ap/sta_info.h" +#include "ap_config.h" +#include "ap_drv_ops.h" +#include "ieee802_11.h" + + +#ifdef CONFIG_IEEE80211W + +u8 * hostapd_eid_assoc_comeback_time(struct hostapd_data *hapd, + struct sta_info *sta, u8 *eid) +{ + u8 *pos = eid; + u32 timeout, tu; + struct os_reltime now, passed; + + *pos++ = WLAN_EID_TIMEOUT_INTERVAL; + *pos++ = 5; + *pos++ = WLAN_TIMEOUT_ASSOC_COMEBACK; + os_get_reltime(&now); + os_reltime_sub(&now, &sta->sa_query_start, &passed); + tu = (passed.sec * 1000000 + passed.usec) / 1024; + if (hapd->conf->assoc_sa_query_max_timeout > tu) + timeout = hapd->conf->assoc_sa_query_max_timeout - tu; + else + timeout = 0; + if (timeout < hapd->conf->assoc_sa_query_max_timeout) + timeout++; /* add some extra time for local timers */ + WPA_PUT_LE32(pos, timeout); + pos += 4; + + return pos; +} + + +/* MLME-SAQuery.request */ +void ieee802_11_send_sa_query_req(struct hostapd_data *hapd, + const u8 *addr, const u8 *trans_id) +{ + struct ieee80211_mgmt mgmt; + u8 *end; + + wpa_printf(MSG_DEBUG, "IEEE 802.11: Sending SA Query Request to " + MACSTR, MAC2STR(addr)); + wpa_hexdump(MSG_DEBUG, "IEEE 802.11: SA Query Transaction ID", + trans_id, WLAN_SA_QUERY_TR_ID_LEN); + + os_memset(&mgmt, 0, sizeof(mgmt)); + mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, + WLAN_FC_STYPE_ACTION); + os_memcpy(mgmt.da, addr, ETH_ALEN); + os_memcpy(mgmt.sa, hapd->own_addr, ETH_ALEN); + os_memcpy(mgmt.bssid, hapd->own_addr, ETH_ALEN); + mgmt.u.action.category = WLAN_ACTION_SA_QUERY; + mgmt.u.action.u.sa_query_req.action = WLAN_SA_QUERY_REQUEST; + os_memcpy(mgmt.u.action.u.sa_query_req.trans_id, trans_id, + WLAN_SA_QUERY_TR_ID_LEN); + end = mgmt.u.action.u.sa_query_req.trans_id + WLAN_SA_QUERY_TR_ID_LEN; + if (hostapd_drv_send_mlme(hapd, &mgmt, end - (u8 *) &mgmt, 0) < 0) + wpa_printf(MSG_INFO, "ieee802_11_send_sa_query_req: send failed"); +} + + +static void ieee802_11_send_sa_query_resp(struct hostapd_data *hapd, + const u8 *sa, const u8 *trans_id) +{ + struct sta_info *sta; + struct ieee80211_mgmt resp; + u8 *end; + + wpa_printf(MSG_DEBUG, "IEEE 802.11: Received SA Query Request from " + MACSTR, MAC2STR(sa)); + wpa_hexdump(MSG_DEBUG, "IEEE 802.11: SA Query Transaction ID", + trans_id, WLAN_SA_QUERY_TR_ID_LEN); + + sta = ap_get_sta(hapd, sa); + if (sta == NULL || !(sta->flags & WLAN_STA_ASSOC)) { + wpa_printf(MSG_DEBUG, "IEEE 802.11: Ignore SA Query Request " + "from unassociated STA " MACSTR, MAC2STR(sa)); + return; + } + + wpa_printf(MSG_DEBUG, "IEEE 802.11: Sending SA Query Response to " + MACSTR, MAC2STR(sa)); + + os_memset(&resp, 0, sizeof(resp)); + resp.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, + WLAN_FC_STYPE_ACTION); + os_memcpy(resp.da, sa, ETH_ALEN); + os_memcpy(resp.sa, hapd->own_addr, ETH_ALEN); + os_memcpy(resp.bssid, hapd->own_addr, ETH_ALEN); + resp.u.action.category = WLAN_ACTION_SA_QUERY; + resp.u.action.u.sa_query_req.action = WLAN_SA_QUERY_RESPONSE; + os_memcpy(resp.u.action.u.sa_query_req.trans_id, trans_id, + WLAN_SA_QUERY_TR_ID_LEN); + end = resp.u.action.u.sa_query_req.trans_id + WLAN_SA_QUERY_TR_ID_LEN; + if (hostapd_drv_send_mlme(hapd, &resp, end - (u8 *) &resp, 0) < 0) + wpa_printf(MSG_INFO, "ieee80211_mgmt_sa_query_request: send failed"); +} + + +void ieee802_11_sa_query_action(struct hostapd_data *hapd, const u8 *sa, + const u8 action_type, const u8 *trans_id) +{ + struct sta_info *sta; + int i; + + if (action_type == WLAN_SA_QUERY_REQUEST) { + ieee802_11_send_sa_query_resp(hapd, sa, trans_id); + return; + } + + if (action_type != WLAN_SA_QUERY_RESPONSE) { + wpa_printf(MSG_DEBUG, "IEEE 802.11: Unexpected SA Query " + "Action %d", action_type); + return; + } + + wpa_printf(MSG_DEBUG, "IEEE 802.11: Received SA Query Response from " + MACSTR, MAC2STR(sa)); + wpa_hexdump(MSG_DEBUG, "IEEE 802.11: SA Query Transaction ID", + trans_id, WLAN_SA_QUERY_TR_ID_LEN); + + /* MLME-SAQuery.confirm */ + + sta = ap_get_sta(hapd, sa); + if (sta == NULL || sta->sa_query_trans_id == NULL) { + wpa_printf(MSG_DEBUG, "IEEE 802.11: No matching STA with " + "pending SA Query request found"); + return; + } + + for (i = 0; i < sta->sa_query_count; i++) { + if (os_memcmp(sta->sa_query_trans_id + + i * WLAN_SA_QUERY_TR_ID_LEN, + trans_id, WLAN_SA_QUERY_TR_ID_LEN) == 0) + break; + } + + if (i >= sta->sa_query_count) { + wpa_printf(MSG_DEBUG, "IEEE 802.11: No matching SA Query " + "transaction identifier found"); + return; + } + + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "Reply to pending SA Query received"); + ap_sta_stop_sa_query(hapd, sta); +} + +#endif /* CONFIG_IEEE80211W */ + + +static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx) +{ + *pos = 0x00; + + switch (idx) { + case 0: /* Bits 0-7 */ + if (hapd->iconf->obss_interval) + *pos |= 0x01; /* Bit 0 - Coexistence management */ + break; + case 1: /* Bits 8-15 */ + if (hapd->conf->proxy_arp) + *pos |= 0x10; /* Bit 12 - Proxy ARP */ + break; + case 2: /* Bits 16-23 */ + if (hapd->conf->wnm_sleep_mode) + *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */ + if (hapd->conf->bss_transition) + *pos |= 0x08; /* Bit 19 - BSS Transition */ + break; + case 3: /* Bits 24-31 */ +#ifdef CONFIG_WNM + *pos |= 0x02; /* Bit 25 - SSID List */ +#endif /* CONFIG_WNM */ + if (hapd->conf->time_advertisement == 2) + *pos |= 0x08; /* Bit 27 - UTC TSF Offset */ + if (hapd->conf->interworking) + *pos |= 0x80; /* Bit 31 - Interworking */ + break; + case 4: /* Bits 32-39 */ + if (hapd->conf->qos_map_set_len) + *pos |= 0x01; /* Bit 32 - QoS Map */ + if (hapd->conf->tdls & TDLS_PROHIBIT) + *pos |= 0x40; /* Bit 38 - TDLS Prohibited */ + if (hapd->conf->tdls & TDLS_PROHIBIT_CHAN_SWITCH) { + /* Bit 39 - TDLS Channel Switching Prohibited */ + *pos |= 0x80; + } + break; + case 5: /* Bits 40-47 */ +#ifdef CONFIG_HS20 + if (hapd->conf->hs20) + *pos |= 0x40; /* Bit 46 - WNM-Notification */ +#endif /* CONFIG_HS20 */ + break; + case 6: /* Bits 48-55 */ + if (hapd->conf->ssid.utf8_ssid) + *pos |= 0x01; /* Bit 48 - UTF-8 SSID */ + break; + } +} + + +u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid) +{ + u8 *pos = eid; + u8 len = 0, i; + + if (hapd->conf->tdls & (TDLS_PROHIBIT | TDLS_PROHIBIT_CHAN_SWITCH)) + len = 5; + if (len < 4 && hapd->conf->interworking) + len = 4; + if (len < 3 && hapd->conf->wnm_sleep_mode) + len = 3; + if (len < 1 && hapd->iconf->obss_interval) + len = 1; + if (len < 7 && hapd->conf->ssid.utf8_ssid) + len = 7; +#ifdef CONFIG_WNM + if (len < 4) + len = 4; +#endif /* CONFIG_WNM */ +#ifdef CONFIG_HS20 + if (hapd->conf->hs20 && len < 6) + len = 6; +#endif /* CONFIG_HS20 */ + if (len < hapd->iface->extended_capa_len) + len = hapd->iface->extended_capa_len; + if (len == 0) + return eid; + + *pos++ = WLAN_EID_EXT_CAPAB; + *pos++ = len; + for (i = 0; i < len; i++, pos++) { + hostapd_ext_capab_byte(hapd, pos, i); + + if (i < hapd->iface->extended_capa_len) { + *pos &= ~hapd->iface->extended_capa_mask[i]; + *pos |= hapd->iface->extended_capa[i]; + } + } + + while (len > 0 && eid[1 + len] == 0) { + len--; + eid[1] = len; + } + if (len == 0) + return eid; + + return eid + 2 + len; +} + + +u8 * hostapd_eid_qos_map_set(struct hostapd_data *hapd, u8 *eid) +{ + u8 *pos = eid; + u8 len = hapd->conf->qos_map_set_len; + + if (!len) + return eid; + + *pos++ = WLAN_EID_QOS_MAP_SET; + *pos++ = len; + os_memcpy(pos, hapd->conf->qos_map_set, len); + pos += len; + + return pos; +} + + +u8 * hostapd_eid_interworking(struct hostapd_data *hapd, u8 *eid) +{ + u8 *pos = eid; +#ifdef CONFIG_INTERWORKING + u8 *len; + + if (!hapd->conf->interworking) + return eid; + + *pos++ = WLAN_EID_INTERWORKING; + len = pos++; + + *pos = hapd->conf->access_network_type; + if (hapd->conf->internet) + *pos |= INTERWORKING_ANO_INTERNET; + if (hapd->conf->asra) + *pos |= INTERWORKING_ANO_ASRA; + if (hapd->conf->esr) + *pos |= INTERWORKING_ANO_ESR; + if (hapd->conf->uesa) + *pos |= INTERWORKING_ANO_UESA; + pos++; + + if (hapd->conf->venue_info_set) { + *pos++ = hapd->conf->venue_group; + *pos++ = hapd->conf->venue_type; + } + + if (!is_zero_ether_addr(hapd->conf->hessid)) { + os_memcpy(pos, hapd->conf->hessid, ETH_ALEN); + pos += ETH_ALEN; + } + + *len = pos - len - 1; +#endif /* CONFIG_INTERWORKING */ + + return pos; +} + + +u8 * hostapd_eid_adv_proto(struct hostapd_data *hapd, u8 *eid) +{ + u8 *pos = eid; +#ifdef CONFIG_INTERWORKING + + /* TODO: Separate configuration for ANQP? */ + if (!hapd->conf->interworking) + return eid; + + *pos++ = WLAN_EID_ADV_PROTO; + *pos++ = 2; + *pos++ = 0x7F; /* Query Response Length Limit | PAME-BI */ + *pos++ = ACCESS_NETWORK_QUERY_PROTOCOL; +#endif /* CONFIG_INTERWORKING */ + + return pos; +} + + +u8 * hostapd_eid_roaming_consortium(struct hostapd_data *hapd, u8 *eid) +{ + u8 *pos = eid; +#ifdef CONFIG_INTERWORKING + u8 *len; + unsigned int i, count; + + if (!hapd->conf->interworking || + hapd->conf->roaming_consortium == NULL || + hapd->conf->roaming_consortium_count == 0) + return eid; + + *pos++ = WLAN_EID_ROAMING_CONSORTIUM; + len = pos++; + + /* Number of ANQP OIs (in addition to the max 3 listed here) */ + if (hapd->conf->roaming_consortium_count > 3 + 255) + *pos++ = 255; + else if (hapd->conf->roaming_consortium_count > 3) + *pos++ = hapd->conf->roaming_consortium_count - 3; + else + *pos++ = 0; + + /* OU #1 and #2 Lengths */ + *pos = hapd->conf->roaming_consortium[0].len; + if (hapd->conf->roaming_consortium_count > 1) + *pos |= hapd->conf->roaming_consortium[1].len << 4; + pos++; + + if (hapd->conf->roaming_consortium_count > 3) + count = 3; + else + count = hapd->conf->roaming_consortium_count; + + for (i = 0; i < count; i++) { + os_memcpy(pos, hapd->conf->roaming_consortium[i].oi, + hapd->conf->roaming_consortium[i].len); + pos += hapd->conf->roaming_consortium[i].len; + } + + *len = pos - len - 1; +#endif /* CONFIG_INTERWORKING */ + + return pos; +} + + +u8 * hostapd_eid_time_adv(struct hostapd_data *hapd, u8 *eid) +{ + if (hapd->conf->time_advertisement != 2) + return eid; + + if (hapd->time_adv == NULL && + hostapd_update_time_adv(hapd) < 0) + return eid; + + if (hapd->time_adv == NULL) + return eid; + + os_memcpy(eid, wpabuf_head(hapd->time_adv), + wpabuf_len(hapd->time_adv)); + eid += wpabuf_len(hapd->time_adv); + + return eid; +} + + +u8 * hostapd_eid_time_zone(struct hostapd_data *hapd, u8 *eid) +{ + size_t len; + + if (hapd->conf->time_advertisement != 2) + return eid; + + len = os_strlen(hapd->conf->time_zone); + + *eid++ = WLAN_EID_TIME_ZONE; + *eid++ = len; + os_memcpy(eid, hapd->conf->time_zone, len); + eid += len; + + return eid; +} + + +int hostapd_update_time_adv(struct hostapd_data *hapd) +{ + const int elen = 2 + 1 + 10 + 5 + 1; + struct os_time t; + struct os_tm tm; + u8 *pos; + + if (hapd->conf->time_advertisement != 2) + return 0; + + if (os_get_time(&t) < 0 || os_gmtime(t.sec, &tm) < 0) + return -1; + + if (!hapd->time_adv) { + hapd->time_adv = wpabuf_alloc(elen); + if (hapd->time_adv == NULL) + return -1; + pos = wpabuf_put(hapd->time_adv, elen); + } else + pos = wpabuf_mhead_u8(hapd->time_adv); + + *pos++ = WLAN_EID_TIME_ADVERTISEMENT; + *pos++ = 1 + 10 + 5 + 1; + + *pos++ = 2; /* UTC time at which the TSF timer is 0 */ + + /* Time Value at TSF 0 */ + /* FIX: need to calculate this based on the current TSF value */ + WPA_PUT_LE16(pos, tm.year); /* Year */ + pos += 2; + *pos++ = tm.month; /* Month */ + *pos++ = tm.day; /* Day of month */ + *pos++ = tm.hour; /* Hours */ + *pos++ = tm.min; /* Minutes */ + *pos++ = tm.sec; /* Seconds */ + WPA_PUT_LE16(pos, 0); /* Milliseconds (not used) */ + pos += 2; + *pos++ = 0; /* Reserved */ + + /* Time Error */ + /* TODO: fill in an estimate on the error */ + *pos++ = 0; + *pos++ = 0; + *pos++ = 0; + *pos++ = 0; + *pos++ = 0; + + *pos++ = hapd->time_update_counter++; + + return 0; +} + + +u8 * hostapd_eid_bss_max_idle_period(struct hostapd_data *hapd, u8 *eid) +{ + u8 *pos = eid; + +#ifdef CONFIG_WNM + if (hapd->conf->ap_max_inactivity > 0) { + unsigned int val; + *pos++ = WLAN_EID_BSS_MAX_IDLE_PERIOD; + *pos++ = 3; + val = hapd->conf->ap_max_inactivity; + if (val > 68000) + val = 68000; + val *= 1000; + val /= 1024; + if (val == 0) + val = 1; + if (val > 65535) + val = 65535; + WPA_PUT_LE16(pos, val); + pos += 2; + *pos++ = 0x00; /* TODO: Protected Keep-Alive Required */ + } +#endif /* CONFIG_WNM */ + + return pos; +} diff --git a/beken_os/beken378/func/hostapd-2.5/src/ap/ieee802_1x.c b/beken_os/beken378/func/hostapd-2.5/src/ap/ieee802_1x.c new file mode 100755 index 0000000..3801e40 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/ap/ieee802_1x.c @@ -0,0 +1,238 @@ +/* + * hostapd / IEEE 802.1X-2004 Authenticator + * Copyright (c) 2002-2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "utils/eloop.h" +#include "crypto/md5.h" +#include "crypto/crypto.h" +#include "crypto/random.h" +#include "common/ieee802_11_defs.h" +#include "ap/hostapd.h" +#include "accounting.h" +#include "ap/sta_info.h" +#include "wpa_auth.h" +#include "preauth_auth.h" +#include "ap_config.h" +#include "ap_drv_ops.h" +#include "wps_hostapd.h" +#include "ieee802_1x.h" + + +void ieee802_1x_finished(struct hostapd_data *hapd, + struct sta_info *sta, int success, + int remediation); + + +void ieee802_1x_set_sta_authorized(struct hostapd_data *hapd, + struct sta_info *sta, int authorized) +{ + int res; + + if (sta->flags & WLAN_STA_PREAUTH) + return; + + if (authorized) { + ap_sta_set_authorized(hapd, sta, 1); + res = hostapd_set_authorized(hapd, sta, 1); + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, + HOSTAPD_LEVEL_DEBUG, "authorizing port"); + } else { + ap_sta_set_authorized(hapd, sta, 0); + res = hostapd_set_authorized(hapd, sta, 0); + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, + HOSTAPD_LEVEL_DEBUG, "unauthorizing port"); + } +#ifdef CONFIG_NO_ACCOUNTING + (void)res; + if (authorized) { + os_get_reltime(&sta->connected_time); + accounting_sta_start(hapd, sta); + } +#endif +} + +/** + * ieee802_1x_receive - Process the EAPOL frames from the Supplicant + * @hapd: hostapd BSS data + * @sa: Source address (sender of the EAPOL frame) + * @buf: EAPOL frame + * @len: Length of buf in octets + * + * This function is called for each incoming EAPOL frame from the interface + */ +void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf, + size_t len) +{ + struct sta_info *sta; + struct ieee802_1x_hdr *hdr; + struct ieee802_1x_eapol_key *key; + u16 datalen; + struct rsn_pmksa_cache_entry *pmksa; + int key_mgmt; + + if (!hapd->conf->ieee802_1x && !hapd->conf->wpa && !hapd->conf->osen && + !hapd->conf->wps_state) + return; + + wpa_printf(MSG_DEBUG, "IEEE 802.1X: %lu bytes from " MACSTR, + (unsigned long) len, MAC2STR(sa)); + sta = ap_get_sta(hapd, sa); + if (!sta || (!(sta->flags & (WLAN_STA_ASSOC | WLAN_STA_PREAUTH)) && + !(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_WIRED))) { + wpa_printf(MSG_DEBUG, "IEEE 802.1X data frame from not " + "associated/Pre-authenticating STA"); + return; + } + + if (len < sizeof(*hdr)) { + wpa_printf(MSG_INFO, " too short IEEE 802.1X packet"); + return; + } + + hdr = (struct ieee802_1x_hdr *) buf; + datalen = be_to_host16(hdr->length); + wpa_printf(MSG_DEBUG, " IEEE 802.1X: version=%d type=%d length=%d", + hdr->version, hdr->type, datalen); + + if (len - sizeof(*hdr) < datalen) { + wpa_printf(MSG_INFO, " frame too short for this IEEE 802.1X packet"); + return; + } + if (len - sizeof(*hdr) > datalen) { + wpa_printf(MSG_DEBUG, " ignoring %lu extra octets after " + "IEEE 802.1X packet", + (unsigned long) len - sizeof(*hdr) - datalen); + } + + + key = (struct ieee802_1x_eapol_key *) (hdr + 1); + if (datalen >= sizeof(struct ieee802_1x_eapol_key) && + hdr->type == IEEE802_1X_TYPE_EAPOL_KEY && + (key->type == EAPOL_KEY_TYPE_WPA || + key->type == EAPOL_KEY_TYPE_RSN)) { + wpa_receive(hapd->wpa_auth, sta->wpa_sm, (u8 *) hdr, + sizeof(*hdr) + datalen); + return; + } + (void)key_mgmt; + (void)pmksa; +} + +void ieee802_1x_set_port_authorized(void *ctx, void *sta_ctx, + int authorized) +{ + struct hostapd_data *hapd = ctx; + struct sta_info *sta = sta_ctx; + ieee802_1x_set_sta_authorized(hapd, sta, authorized); +} + +int ieee802_1x_tx_status(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *buf, size_t len, int ack) +{ + struct ieee80211_hdr *hdr; + u8 *pos; + const unsigned char rfc1042_hdr[ETH_ALEN] = + { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; + + if (sta == NULL) + return -1; + if (len < sizeof(*hdr) + sizeof(rfc1042_hdr) + 2) + return 0; + + hdr = (struct ieee80211_hdr *) buf; + pos = (u8 *) (hdr + 1); + if (os_memcmp(pos, rfc1042_hdr, sizeof(rfc1042_hdr)) != 0) + return 0; + pos += sizeof(rfc1042_hdr); + if (WPA_GET_BE16(pos) != ETH_P_PAE) + return 0; + pos += 2; + + return ieee802_1x_eapol_tx_status(hapd, sta, pos, buf + len - pos, + ack); +} + + +int ieee802_1x_eapol_tx_status(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *buf, int len, int ack) +{ + const struct ieee802_1x_hdr *xhdr = + (const struct ieee802_1x_hdr *) buf; + const u8 *pos = buf + sizeof(*xhdr); + struct ieee802_1x_eapol_key *key; + + if (len < (int) sizeof(*xhdr)) + return 0; + wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR " TX status - version=%d " + "type=%d length=%d - ack=%d", + MAC2STR(sta->addr), xhdr->version, xhdr->type, + be_to_host16(xhdr->length), ack); + + if (xhdr->type != IEEE802_1X_TYPE_EAPOL_KEY) + return 0; + + if (pos + sizeof(struct wpa_eapol_key) <= buf + len) { + const struct wpa_eapol_key *wpa; + wpa = (const struct wpa_eapol_key *) pos; + if (wpa->type == EAPOL_KEY_TYPE_RSN || + wpa->type == EAPOL_KEY_TYPE_WPA) + wpa_auth_eapol_key_tx_status(hapd->wpa_auth, + sta->wpa_sm, ack); + } + + /* EAPOL EAP-Packet packets are eventually re-sent by either Supplicant + * or Authenticator state machines, but EAPOL-Key packets are not + * retransmitted in case of failure. Try to re-send failed EAPOL-Key + * packets couple of times because otherwise STA keys become + * unsynchronized with AP. */ + if (!ack && pos + sizeof(*key) <= buf + len) { + key = (struct ieee802_1x_eapol_key *) pos; + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, + HOSTAPD_LEVEL_DEBUG, "did not Ack EAPOL-Key " + "frame (%scast index=%d)", + key->key_index & BIT(7) ? "uni" : "broad", + key->key_index & ~BIT(7)); + /* TODO: re-send EAPOL-Key couple of times (with short delay + * between them?). If all attempt fail, report error and + * deauthenticate STA so that it will get new keys when + * authenticating again (e.g., after returning in range). + * Separate limit/transmit state needed both for unicast and + * broadcast keys(?) */ + } + /* TODO: could move unicast key configuration from ieee802_1x_tx_key() + * to here and change the key only if the EAPOL-Key packet was Acked. + */ + (void)key; + + return 1; +} + +void ieee802_1x_notify_port_enabled(struct eapol_state_machine *sm, + int enabled) +{ + if (sm == NULL) + return; +} + + +void ieee802_1x_notify_port_valid(struct eapol_state_machine *sm, + int valid) +{ + if (sm == NULL) + return; +} + + +void ieee802_1x_notify_pre_auth(struct eapol_state_machine *sm, int pre_auth) +{ + if (sm == NULL) + return; +} + diff --git a/beken_os/beken378/func/hostapd-2.5/src/ap/ieee802_1x.h b/beken_os/beken378/func/hostapd-2.5/src/ap/ieee802_1x.h new file mode 100755 index 0000000..b8d2194 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/ap/ieee802_1x.h @@ -0,0 +1,58 @@ +/* + * hostapd / IEEE 802.1X-2004 Authenticator + * Copyright (c) 2002-2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef IEEE802_1X_H +#define IEEE802_1X_H + +struct hostapd_data; +struct sta_info; +struct eapol_state_machine; +struct hostapd_config; +struct hostapd_bss_config; +struct hostapd_radius_attr; +struct radius_msg; + + +void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf, + size_t len); +void ieee802_1x_abort_auth(struct hostapd_data *hapd, struct sta_info *sta); +void ieee802_1x_set_sta_authorized(struct hostapd_data *hapd, + struct sta_info *sta, int authorized); +void ieee802_1x_dump_state(FILE *f, const char *prefix, struct sta_info *sta); +int ieee802_1x_init(struct hostapd_data *hapd); +void ieee802_1x_erp_flush(struct hostapd_data *hapd); +void ieee802_1x_deinit(struct hostapd_data *hapd); +int ieee802_1x_tx_status(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *buf, size_t len, int ack); +int ieee802_1x_eapol_tx_status(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *data, int len, int ack); +u8 * ieee802_1x_get_identity(struct eapol_state_machine *sm, size_t *len); +u8 * ieee802_1x_get_radius_class(struct eapol_state_machine *sm, size_t *len, + int idx); +struct wpabuf * ieee802_1x_get_radius_cui(struct eapol_state_machine *sm); +const u8 * ieee802_1x_get_key(struct eapol_state_machine *sm, size_t *len); +void ieee802_1x_notify_port_enabled(struct eapol_state_machine *sm, + int enabled); +void ieee802_1x_notify_port_valid(struct eapol_state_machine *sm, + int valid); +void ieee802_1x_notify_pre_auth(struct eapol_state_machine *sm, int pre_auth); +int ieee802_1x_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen); +int ieee802_1x_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta, + char *buf, size_t buflen); +void hostapd_get_ntp_timestamp(u8 *buf); +char *eap_type_text(u8 type); + +const char *radius_mode_txt(struct hostapd_data *hapd); +int radius_sta_rate(struct hostapd_data *hapd, struct sta_info *sta); + +int add_common_radius_attr(struct hostapd_data *hapd, + struct hostapd_radius_attr *req_attr, + struct sta_info *sta, + struct radius_msg *msg); + +#endif /* IEEE802_1X_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/ap/p2p_hostapd.h b/beken_os/beken378/func/hostapd-2.5/src/ap/p2p_hostapd.h new file mode 100755 index 0000000..0e3921c --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/ap/p2p_hostapd.h @@ -0,0 +1,35 @@ +/* + * hostapd / P2P integration + * Copyright (c) 2009-2010, Atheros Communications + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef P2P_HOSTAPD_H +#define P2P_HOSTAPD_H + +#ifdef CONFIG_P2P + +int hostapd_p2p_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta, + char *buf, size_t buflen); +int hostapd_p2p_set_noa(struct hostapd_data *hapd, u8 count, int start, + int duration); +void hostapd_p2p_non_p2p_sta_connected(struct hostapd_data *hapd); +void hostapd_p2p_non_p2p_sta_disconnected(struct hostapd_data *hapd); + + +#else /* CONFIG_P2P */ + +static inline int hostapd_p2p_get_mib_sta(struct hostapd_data *hapd, + struct sta_info *sta, + char *buf, size_t buflen) +{ + return 0; +} + +#endif /* CONFIG_P2P */ + +u8 * hostapd_eid_p2p_manage(struct hostapd_data *hapd, u8 *eid); + +#endif /* P2P_HOSTAPD_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/ap/preauth_auth.h b/beken_os/beken378/func/hostapd-2.5/src/ap/preauth_auth.h new file mode 100755 index 0000000..69fb356 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/ap/preauth_auth.h @@ -0,0 +1,52 @@ +/* + * hostapd - Authenticator for IEEE 802.11i RSN pre-authentication + * Copyright (c) 2004-2005, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef PREAUTH_H +#define PREAUTH_H + +#ifdef CONFIG_RSN_PREAUTH + +int rsn_preauth_iface_init(struct hostapd_data *hapd); +void rsn_preauth_iface_deinit(struct hostapd_data *hapd); +void rsn_preauth_finished(struct hostapd_data *hapd, struct sta_info *sta, + int success); +void rsn_preauth_send(struct hostapd_data *hapd, struct sta_info *sta, + u8 *buf, size_t len); +void rsn_preauth_free_station(struct hostapd_data *hapd, struct sta_info *sta); + +#else /* CONFIG_RSN_PREAUTH */ + +static inline int rsn_preauth_iface_init(struct hostapd_data *hapd) +{ + return 0; +} + +static inline void rsn_preauth_iface_deinit(struct hostapd_data *hapd) +{ +} + +static inline void rsn_preauth_finished(struct hostapd_data *hapd, + struct sta_info *sta, + int success) +{ +} + +static inline void rsn_preauth_send(struct hostapd_data *hapd, + struct sta_info *sta, + u8 *buf, size_t len) +{ +} + +static inline void rsn_preauth_free_station(struct hostapd_data *hapd, + struct sta_info *sta) +{ +} + +#endif /* CONFIG_RSN_PREAUTH */ + +#endif /* PREAUTH_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/ap/sta_info.c b/beken_os/beken378/func/hostapd-2.5/src/ap/sta_info.c new file mode 100755 index 0000000..6bab497 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/ap/sta_info.c @@ -0,0 +1,1113 @@ +/* + * hostapd / Station table + * Copyright (c) 2002-2013, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ +#include "utils/includes.h" +#include "utils/common.h" +#include "utils/eloop.h" +#include "common/ieee802_11_defs.h" +#include "common/wpa_ctrl.h" +#include "common/sae.h" +#include "ap/hostapd.h" +#include "accounting.h" +#include "ieee802_1x.h" +#include "ieee802_11.h" +#include "ieee802_11_auth.h" +#include "wpa_auth.h" +#include "preauth_auth.h" +#include "ap_config.h" +#include "beacon.h" +#include "ap_mlme.h" +#include "vlan_init.h" +#include "p2p_hostapd.h" +#include "ap_drv_ops.h" +#include "ap/sta_info.h" + +#include "include.h" +#include "uart_pub.h" + +#include "fake_clock_pub.h" + +static void ap_sta_remove_in_other_bss(struct hostapd_data *hapd, + struct sta_info *sta); +static void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx); +static void ap_handle_session_warning_timer(void *eloop_ctx, void *timeout_ctx); +static void ap_sta_deauth_cb_timeout(void *eloop_ctx, void *timeout_ctx); +static void ap_sta_disassoc_cb_timeout(void *eloop_ctx, void *timeout_ctx); +#ifdef CONFIG_IEEE80211W +static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx); +#endif /* CONFIG_IEEE80211W */ +static int ap_sta_remove(struct hostapd_data *hapd, struct sta_info *sta); + +int ap_for_each_sta(struct hostapd_data *hapd, + int (*cb)(struct hostapd_data *hapd, struct sta_info *sta, + void *ctx), + void *ctx) +{ + struct sta_info *sta; + + for (sta = hapd->sta_list; sta; sta = sta->next) { + if (cb(hapd, sta, ctx)) + return 1; + } + + return 0; +} + + +struct sta_info * ap_get_sta(struct hostapd_data *hapd, const u8 *sta) +{ + struct sta_info *s; + + s = hapd->sta_hash[STA_HASH(sta)]; + while (s != NULL && os_memcmp(s->addr, sta, 6) != 0) + s = s->hnext; + return s; +} + + +#ifdef CONFIG_P2P +struct sta_info * ap_get_sta_p2p(struct hostapd_data *hapd, const u8 *addr) +{ + struct sta_info *sta; + + for (sta = hapd->sta_list; sta; sta = sta->next) { + const u8 *p2p_dev_addr; + + if (sta->p2p_ie == NULL) + continue; + + p2p_dev_addr = p2p_get_go_dev_addr(sta->p2p_ie); + if (p2p_dev_addr == NULL) + continue; + + if (os_memcmp(p2p_dev_addr, addr, ETH_ALEN) == 0) + return sta; + } + + return NULL; +} +#endif /* CONFIG_P2P */ + + +static void ap_sta_list_del(struct hostapd_data *hapd, struct sta_info *sta) +{ + struct sta_info *tmp; + + if (hapd->sta_list == sta) { + hapd->sta_list = sta->next; + return; + } + + tmp = hapd->sta_list; + while (tmp != NULL && tmp->next != sta) + tmp = tmp->next; + if (tmp == NULL) { + wpa_printf(MSG_DEBUG, "Could not remove STA " MACSTR " from " + "list.", MAC2STR(sta->addr)); + } else + tmp->next = sta->next; +} + + +void ap_sta_hash_add(struct hostapd_data *hapd, struct sta_info *sta) +{ + sta->hnext = hapd->sta_hash[STA_HASH(sta->addr)]; + hapd->sta_hash[STA_HASH(sta->addr)] = sta; +} + + +static void ap_sta_hash_del(struct hostapd_data *hapd, struct sta_info *sta) +{ + struct sta_info *s; + + s = hapd->sta_hash[STA_HASH(sta->addr)]; + if (s == NULL) return; + if (os_memcmp(s->addr, sta->addr, 6) == 0) { + hapd->sta_hash[STA_HASH(sta->addr)] = s->hnext; + return; + } + + while (s->hnext != NULL && + os_memcmp(s->hnext->addr, sta->addr, ETH_ALEN) != 0) + s = s->hnext; + if (s->hnext != NULL) + s->hnext = s->hnext->hnext; + else + wpa_printf(MSG_DEBUG, "AP: could not remove STA " MACSTR + " from hash table", MAC2STR(sta->addr)); +} + + +void ap_sta_ip6addr_del(struct hostapd_data *hapd, struct sta_info *sta) +{ + //sta_ip6addr_del(hapd, sta); +} + + +void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta) +{ + int set_beacon = 0; + + accounting_sta_stop(hapd, sta); + + /* just in case */ + ap_sta_set_authorized(hapd, sta, 0); + +#ifdef CONFIG_FULL_HOSTAPD + if (sta->flags & WLAN_STA_WDS) + hostapd_set_wds_sta(hapd, NULL, sta->addr, sta->aid, 0); +#endif + + if (sta->ipaddr) + hostapd_drv_br_delete_ip_neigh(hapd, 4, (u8 *) &sta->ipaddr); + ap_sta_ip6addr_del(hapd, sta); + + if (!hapd->iface->driver_ap_teardown && + !(sta->flags & WLAN_STA_PREAUTH)) + hostapd_drv_sta_remove(hapd, sta->addr); + +#ifndef CONFIG_NO_VLAN + if (sta->vlan_id_bound) { + /* + * Need to remove the STA entry before potentially removing the + * VLAN. + */ + if (hapd->iface->driver_ap_teardown && + !(sta->flags & WLAN_STA_PREAUTH)) + hostapd_drv_sta_remove(hapd, sta->addr); + vlan_remove_dynamic(hapd, sta->vlan_id_bound); + } +#endif /* CONFIG_NO_VLAN */ + + ap_sta_hash_del(hapd, sta); + ap_sta_list_del(hapd, sta); + + if (sta->aid > 0) + hapd->sta_aid[(sta->aid - 1) / 32] &= + ~BIT((sta->aid - 1) % 32); + + hapd->num_sta--; + if (sta->nonerp_set) { + sta->nonerp_set = 0; + hapd->iface->num_sta_non_erp--; + if (hapd->iface->num_sta_non_erp == 0) + set_beacon++; + } + + if (sta->no_short_slot_time_set) { + sta->no_short_slot_time_set = 0; + hapd->iface->num_sta_no_short_slot_time--; + if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G + && hapd->iface->num_sta_no_short_slot_time == 0) + set_beacon++; + } + + if (sta->no_short_preamble_set) { + sta->no_short_preamble_set = 0; + hapd->iface->num_sta_no_short_preamble--; + if (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G + && hapd->iface->num_sta_no_short_preamble == 0) + set_beacon++; + } + + if (sta->no_ht_gf_set) { + sta->no_ht_gf_set = 0; + hapd->iface->num_sta_ht_no_gf--; + } + + if (sta->no_ht_set) { + sta->no_ht_set = 0; + hapd->iface->num_sta_no_ht--; + } + + if (sta->ht_20mhz_set) { + sta->ht_20mhz_set = 0; + hapd->iface->num_sta_ht_20mhz--; + } + +#ifdef CONFIG_IEEE80211N + ht40_intolerant_remove(hapd->iface, sta); +#endif /* CONFIG_IEEE80211N */ + +#ifdef CONFIG_P2P + if (sta->no_p2p_set) { + sta->no_p2p_set = 0; + hapd->num_sta_no_p2p--; + if (hapd->num_sta_no_p2p == 0) + hostapd_p2p_non_p2p_sta_disconnected(hapd); + } +#endif /* CONFIG_P2P */ + +#if defined(NEED_AP_MLME) && defined(CONFIG_IEEE80211N) + if (hostapd_ht_operation_update(hapd->iface) > 0) + set_beacon++; +#endif /* NEED_AP_MLME && CONFIG_IEEE80211N */ + +#ifdef CONFIG_MESH + if (hapd->mesh_sta_free_cb) + hapd->mesh_sta_free_cb(sta); +#endif /* CONFIG_MESH */ + + if (set_beacon) + ieee802_11_set_beacons(hapd->iface); + + wpa_printf(MSG_DEBUG, "%s: cancel ap_handle_timer for " MACSTR, + __func__, MAC2STR(sta->addr)); + eloop_cancel_timeout(ap_handle_timer, hapd, sta); + eloop_cancel_timeout(ap_handle_session_timer, hapd, sta); + eloop_cancel_timeout(ap_handle_session_warning_timer, hapd, sta); + eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta); + eloop_cancel_timeout(ap_sta_disassoc_cb_timeout, hapd, sta); + sae_clear_retransmit_timer(hapd, sta); + + wpa_auth_sta_deinit(sta->wpa_sm); + rsn_preauth_free_station(hapd, sta); +#ifndef CONFIG_NO_RADIUS + if (hapd->radius) + radius_client_flush_auth(hapd->radius, sta->addr); +#endif /* CONFIG_NO_RADIUS */ + + os_free(sta->challenge); + +#ifdef CONFIG_IEEE80211W + os_free(sta->sa_query_trans_id); + eloop_cancel_timeout(ap_sa_query_timer, hapd, sta); +#endif /* CONFIG_IEEE80211W */ + +#ifdef CONFIG_P2P + p2p_group_notif_disassoc(hapd->p2p_group, sta->addr); +#endif /* CONFIG_P2P */ + + wpabuf_free(sta->wps_ie); + wpabuf_free(sta->p2p_ie); + + os_free(sta->ht_capabilities); + os_free(sta->vht_capabilities); + hostapd_free_psk_list(sta->psk); + +#ifdef CONFIG_SAE + sae_clear_data(sta->sae); + os_free(sta->sae); +#endif /* CONFIG_SAE */ + + os_free(sta); +} + + +void hostapd_free_stas(struct hostapd_data *hapd) +{ + struct sta_info *sta, *prev; + + sta = hapd->sta_list; + + while (sta) { + prev = sta; + if (sta->flags & WLAN_STA_AUTH) { + mlme_deauthenticate_indication( + hapd, sta, WLAN_REASON_UNSPECIFIED); + } + sta = sta->next; + wpa_printf(MSG_DEBUG, "Removing station " MACSTR, + MAC2STR(prev->addr)); + ap_free_sta(hapd, prev); + } +} + + +/** + * ap_handle_timer - Per STA timer handler + * @eloop_ctx: struct hostapd_data * + * @timeout_ctx: struct sta_info * + * + * This function is called to check station activity and to remove inactive + * stations. + */ +void ap_handle_timer(void *eloop_ctx, void *timeout_ctx) +{ + struct hostapd_data *hapd = eloop_ctx; + struct sta_info *sta = timeout_ctx; + unsigned long next_time = 0; + int reason; + + os_null_printf("ap_handle_timer:%d,%ds\r\n", fclk_get_tick(), fclk_get_second()); + if (sta->timeout_next == STA_REMOVE) { + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, "deauthenticated due to " + "local deauth request"); + ap_free_sta(hapd, sta); + return; + } + + if ((sta->flags & WLAN_STA_ASSOC) && + (sta->timeout_next == STA_NULLFUNC || + sta->timeout_next == STA_DISASSOC)) { + int inactive_sec; + /* + * Add random value to timeout so that we don't end up bouncing + * all stations at the same time if we have lots of associated + * stations that are idle (but keep re-associating). + */ + int fuzz = 0; /*os_random() % 20;*/ + inactive_sec = hostapd_drv_get_inact_sec(hapd, sta->addr); + os_printf("inactive_sec:%d fuzz:%d\r\n", inactive_sec, fuzz); + if (inactive_sec == -1) { + os_null_printf("Check inactivity: Could not " + "get station info from kernel driver for " + MACSTR, MAC2STR(sta->addr)); + /* + * The driver may not support this functionality. + * Anyway, try again after the next inactivity timeout, + * but do not disconnect the station now. + */ + next_time = hapd->conf->ap_max_inactivity + fuzz; + } else if (inactive_sec == -ERRNOENT) { + os_null_printf("Station " MACSTR " has lost its driver entry", + MAC2STR(sta->addr)); + + /* Avoid sending client probe on removed client */ + sta->timeout_next = STA_DISASSOC; + goto skip_poll; + } else if (inactive_sec < hapd->conf->ap_max_inactivity) { + /* station activity detected; reset timeout state */ + wpa_msg(hapd->msg_ctx, MSG_DEBUG, + "Station " MACSTR " has been active %is ago", + MAC2STR(sta->addr), inactive_sec); + sta->timeout_next = STA_NULLFUNC; + next_time = hapd->conf->ap_max_inactivity + fuzz - + inactive_sec; + }else if(STA_DISASSOC == sta->timeout_next){ + sta->timeout_next = STA_REMOVE; + os_printf("STA_REMOVE\r\n"); + } else { + wpa_msg(hapd->msg_ctx, MSG_DEBUG, + "Station " MACSTR " has been " + "inactive too long: %d sec, max allowed: %d", + MAC2STR(sta->addr), inactive_sec, + hapd->conf->ap_max_inactivity); + + if (hapd->conf->skip_inactivity_poll) + sta->timeout_next = STA_DISASSOC; + } + } + + if ((sta->flags & WLAN_STA_ASSOC) && + sta->timeout_next == STA_DISASSOC && + !(sta->flags & WLAN_STA_PENDING_POLL) && + !hapd->conf->skip_inactivity_poll) { + wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Station " MACSTR + " has ACKed data poll", MAC2STR(sta->addr)); + /* data nullfunc frame poll did not produce TX errors; assume + * station ACKed it */ + sta->timeout_next = STA_NULLFUNC; + next_time = hapd->conf->ap_max_inactivity; + } + +skip_poll: + if (next_time) { + wpa_printf(MSG_DEBUG, "%s: register ap_handle_timer timeout " + "for " MACSTR " (%lu seconds)", + __func__, MAC2STR(sta->addr), next_time); + eloop_register_timeout(next_time, 0, ap_handle_timer, hapd, + sta); + return; + } + + if (sta->timeout_next == STA_NULLFUNC && + (sta->flags & WLAN_STA_ASSOC)) { + wpa_printf(MSG_DEBUG, " Polling STA"); + sta->flags |= WLAN_STA_PENDING_POLL; + hostapd_drv_poll_client(hapd, hapd->own_addr, sta->addr, + sta->flags & WLAN_STA_WMM); + } else if (sta->timeout_next != STA_REMOVE) { + int deauth = sta->timeout_next == STA_DEAUTH; + + wpa_dbg(hapd->msg_ctx, MSG_DEBUG, + "Timeout, sending %s info to STA " MACSTR, + deauth ? "deauthentication" : "disassociation", + MAC2STR(sta->addr)); + + if (deauth) { + hostapd_drv_sta_deauth( + hapd, sta->addr, + WLAN_REASON_PREV_AUTH_NOT_VALID); + } else { + reason = (sta->timeout_next == STA_DISASSOC) ? + WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY : + WLAN_REASON_PREV_AUTH_NOT_VALID; + os_printf("hostapd_drv_sta_disassoc\r\n"); + hostapd_drv_sta_disassoc(hapd, sta->addr, reason); + } + } + + switch (sta->timeout_next) { + case STA_NULLFUNC: + sta->timeout_next = STA_DISASSOC; + wpa_printf(MSG_DEBUG, "%s: register ap_handle_timer timeout " + "for " MACSTR " (%d seconds - AP_DISASSOC_DELAY)", + __func__, MAC2STR(sta->addr), AP_DISASSOC_DELAY); + eloop_register_timeout(AP_DISASSOC_DELAY, 0, ap_handle_timer, + hapd, sta); + break; + case STA_DISASSOC: + case STA_DISASSOC_FROM_CLI: + ap_sta_set_authorized(hapd, sta, 0); + sta->flags &= ~WLAN_STA_ASSOC; + ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); +#if 0 + if (!sta->acct_terminate_cause) + sta->acct_terminate_cause = + RADIUS_ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT; +#endif + accounting_sta_stop(hapd, sta); + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, "disassociated due to " + "inactivity"); + reason = (sta->timeout_next == STA_DISASSOC) ? + WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY : + WLAN_REASON_PREV_AUTH_NOT_VALID; + sta->timeout_next = STA_DEAUTH; + wpa_printf(MSG_DEBUG, "%s: register ap_handle_timer timeout " + "for " MACSTR " (%d seconds - AP_DEAUTH_DELAY)", + __func__, MAC2STR(sta->addr), AP_DEAUTH_DELAY); + eloop_register_timeout(AP_DEAUTH_DELAY, 0, ap_handle_timer, + hapd, sta); + mlme_disassociate_indication(hapd, sta, reason); + break; + case STA_DEAUTH: + case STA_REMOVE: + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, "deauthenticated due to " + "inactivity (timer DEAUTH/REMOVE)"); +#if 0 + if (!sta->acct_terminate_cause) + sta->acct_terminate_cause = + RADIUS_ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT; +#endif + os_null_printf("ap_free_sta\r\n"); + mlme_deauthenticate_indication( + hapd, sta, + WLAN_REASON_PREV_AUTH_NOT_VALID); + ap_free_sta(hapd, sta); + break; + } +} + + +static void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx) +{ + struct hostapd_data *hapd = eloop_ctx; + struct sta_info *sta = timeout_ctx; + + if (!(sta->flags & WLAN_STA_AUTH)) { + if (sta->flags & WLAN_STA_GAS) { + wpa_printf(MSG_DEBUG, "GAS: Remove temporary STA " + "entry " MACSTR, MAC2STR(sta->addr)); + ap_free_sta(hapd, sta); + } + return; + } + + hostapd_drv_sta_deauth(hapd, sta->addr, + WLAN_REASON_PREV_AUTH_NOT_VALID); + mlme_deauthenticate_indication(hapd, sta, + WLAN_REASON_PREV_AUTH_NOT_VALID); + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, "deauthenticated due to " + "session timeout"); +#if 0 + sta->acct_terminate_cause = + RADIUS_ACCT_TERMINATE_CAUSE_SESSION_TIMEOUT; +#endif + ap_free_sta(hapd, sta); +} + + +void ap_sta_replenish_timeout(struct hostapd_data *hapd, struct sta_info *sta, + u32 session_timeout) +{ + if (eloop_replenish_timeout(session_timeout, 0, + ap_handle_session_timer, hapd, sta) == 1) { + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, "setting session timeout " + "to %d seconds", session_timeout); + } +} + + +void ap_sta_session_timeout(struct hostapd_data *hapd, struct sta_info *sta, + u32 session_timeout) +{ + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, "setting session timeout to %d " + "seconds", session_timeout); + eloop_cancel_timeout(ap_handle_session_timer, hapd, sta); + eloop_register_timeout(session_timeout, 0, ap_handle_session_timer, + hapd, sta); +} + + +void ap_sta_no_session_timeout(struct hostapd_data *hapd, struct sta_info *sta) +{ + eloop_cancel_timeout(ap_handle_session_timer, hapd, sta); +} + + +static void ap_handle_session_warning_timer(void *eloop_ctx, void *timeout_ctx) +{ +} + + +void ap_sta_session_warning_timeout(struct hostapd_data *hapd, + struct sta_info *sta, int warning_time) +{ + eloop_cancel_timeout(ap_handle_session_warning_timer, hapd, sta); + eloop_register_timeout(warning_time, 0, ap_handle_session_warning_timer, + hapd, sta); +} + +struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr) +{ + struct sta_info *sta; + + sta = ap_get_sta(hapd, addr); + if (sta) + return sta; + + wpa_printf(MSG_DEBUG, " New STA"); + + if (hapd->num_sta >= hapd->conf->max_num_sta) { + /* FIX: might try to remove some old STAs first? */ + wpa_printf(MSG_DEBUG, "no more room for new STAs (%d/%d)", + hapd->num_sta, hapd->conf->max_num_sta); + return NULL; + } + + sta = os_zalloc(sizeof(struct sta_info)); + if (sta == NULL) { + os_printf("ap_sta_add malloc failed\r\n"); + return NULL; + } +#ifdef CONFIG_FULL_HOSTAPD + sta->acct_interim_interval = hapd->conf->acct_interim_interval; +#endif + accounting_sta_get_id(hapd, sta); + + if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_INACTIVITY_TIMER)) { + wpa_printf(MSG_DEBUG, "%s: register ap_handle_timer timeout " + "for " MACSTR " (%d seconds - ap_max_inactivity)", + __func__, MAC2STR(addr), + hapd->conf->ap_max_inactivity); + eloop_register_timeout(hapd->conf->ap_max_inactivity, 0, + ap_handle_timer, hapd, sta); + } + + /* initialize STA info data */ + os_memcpy(sta->addr, addr, ETH_ALEN); + sta->next = hapd->sta_list; + hapd->sta_list = sta; + hapd->num_sta++; + ap_sta_hash_add(hapd, sta); + ap_sta_remove_in_other_bss(hapd, sta); + sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ; + dl_list_init(&sta->ip6addr); + + return sta; +} + + +static int ap_sta_remove(struct hostapd_data *hapd, struct sta_info *sta) +{ + ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); + + if (sta->ipaddr) + hostapd_drv_br_delete_ip_neigh(hapd, 4, (u8 *) &sta->ipaddr); + ap_sta_ip6addr_del(hapd, sta); + + wpa_printf(MSG_DEBUG, "Removing STA " MACSTR " from kernel driver", + MAC2STR(sta->addr)); + if (hostapd_drv_sta_remove(hapd, sta->addr) && + (sta->flags & WLAN_STA_ASSOC)) { + wpa_printf(MSG_DEBUG, "Could not remove station " MACSTR + " from kernel driver.", MAC2STR(sta->addr)); + return -1; + } + return 0; +} + + +static void ap_sta_remove_in_other_bss(struct hostapd_data *hapd, + struct sta_info *sta) +{ + struct hostapd_iface *iface = hapd->iface; + size_t i; + + for (i = 0; i < iface->num_bss; i++) { + struct hostapd_data *bss = iface->bss[i]; + struct sta_info *sta2; + /* bss should always be set during operation, but it may be + * NULL during reconfiguration. Assume the STA is not + * associated to another BSS in that case to avoid NULL pointer + * dereferences. */ + if (bss == hapd || bss == NULL) + continue; + sta2 = ap_get_sta(bss, sta->addr); + if (!sta2) + continue; + + ap_sta_disconnect(bss, sta2, sta2->addr, + WLAN_REASON_PREV_AUTH_NOT_VALID); + } +} + + +static void ap_sta_disassoc_cb_timeout(void *eloop_ctx, void *timeout_ctx) +{ + struct hostapd_data *hapd = eloop_ctx; + struct sta_info *sta = timeout_ctx; + + ap_sta_remove(hapd, sta); + mlme_disassociate_indication(hapd, sta, sta->disassoc_reason); +} + + +void ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta, + u16 reason) +{ + wpa_printf(MSG_DEBUG, "%s: disassociate STA " MACSTR, + hapd->conf->iface, MAC2STR(sta->addr)); + sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ; + sta->flags &= ~(WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK); + ap_sta_set_authorized(hapd, sta, 0); + sta->timeout_next = STA_DEAUTH; + wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout " + "for " MACSTR " (%d seconds - " + "AP_MAX_INACTIVITY_AFTER_DISASSOC)", + __func__, MAC2STR(sta->addr), + AP_MAX_INACTIVITY_AFTER_DISASSOC); + eloop_cancel_timeout(ap_handle_timer, hapd, sta); + eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DISASSOC, 0, + ap_handle_timer, hapd, sta); + + sta->disassoc_reason = reason; + sta->flags |= WLAN_STA_PENDING_DISASSOC_CB; + eloop_cancel_timeout(ap_sta_disassoc_cb_timeout, hapd, sta); + eloop_register_timeout(hapd->iface->drv_flags & + WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS ? 2 : 0, 0, + ap_sta_disassoc_cb_timeout, hapd, sta); +} + + +static void ap_sta_deauth_cb_timeout(void *eloop_ctx, void *timeout_ctx) +{ + struct hostapd_data *hapd = eloop_ctx; + struct sta_info *sta = timeout_ctx; + + ap_sta_remove(hapd, sta); + mlme_deauthenticate_indication(hapd, sta, sta->deauth_reason); +} + + +void ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta, + u16 reason) +{ + wpa_printf(MSG_DEBUG, "%s: deauthenticate STA " MACSTR, + hapd->conf->iface, MAC2STR(sta->addr)); + sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ; + sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK); + ap_sta_set_authorized(hapd, sta, 0); + sta->timeout_next = STA_REMOVE; + wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout " + "for " MACSTR " (%d seconds - " + "AP_MAX_INACTIVITY_AFTER_DEAUTH)", + __func__, MAC2STR(sta->addr), + AP_MAX_INACTIVITY_AFTER_DEAUTH); + eloop_cancel_timeout(ap_handle_timer, hapd, sta); + eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DEAUTH, 0, + ap_handle_timer, hapd, sta); + + sta->deauth_reason = reason; + sta->flags |= WLAN_STA_PENDING_DEAUTH_CB; + eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta); + eloop_register_timeout(hapd->iface->drv_flags & + WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS ? 2 : 0, 0, + ap_sta_deauth_cb_timeout, hapd, sta); +} + +int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta) +{ +#ifndef CONFIG_NO_VLAN + const char *iface; + struct hostapd_vlan *vlan = NULL; + int ret; + int old_vlanid = sta->vlan_id_bound; + + iface = hapd->conf->iface; + if (hapd->conf->ssid.vlan[0]) + iface = hapd->conf->ssid.vlan; + + if (hapd->conf->ssid.dynamic_vlan == DYNAMIC_VLAN_DISABLED) + sta->vlan_id = 0; + else if (sta->vlan_id > 0) { + struct hostapd_vlan *wildcard_vlan = NULL; + vlan = hapd->conf->vlan; + while (vlan) { + if (vlan->vlan_id == sta->vlan_id) + break; + if (vlan->vlan_id == VLAN_ID_WILDCARD) + wildcard_vlan = vlan; + vlan = vlan->next; + } + if (!vlan) + vlan = wildcard_vlan; + if (vlan) + iface = vlan->ifname; + } + + /* + * Do not increment ref counters if the VLAN ID remains same, but do + * not skip hostapd_drv_set_sta_vlan() as hostapd_drv_sta_remove() might + * have been called before. + */ + if (sta->vlan_id == old_vlanid) + goto skip_counting; + + if (sta->vlan_id > 0 && vlan == NULL) { + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, "could not find VLAN for " + "binding station to (vlan_id=%d)", + sta->vlan_id); + ret = -1; + goto done; + } else if (sta->vlan_id > 0 && vlan->vlan_id == VLAN_ID_WILDCARD) { + vlan = vlan_add_dynamic(hapd, vlan, sta->vlan_id); + if (vlan == NULL) { + hostapd_logger(hapd, sta->addr, + HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, "could not add " + "dynamic VLAN interface for vlan_id=%d", + sta->vlan_id); + ret = -1; + goto done; + } + + iface = vlan->ifname; + if (vlan_setup_encryption_dyn(hapd, iface) != 0) { + hostapd_logger(hapd, sta->addr, + HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, "could not " + "configure encryption for dynamic VLAN " + "interface for vlan_id=%d", + sta->vlan_id); + } + + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, "added new dynamic VLAN " + "interface '%s'", iface); + } else if (vlan && vlan->vlan_id == sta->vlan_id) { + if (vlan->dynamic_vlan > 0) { + vlan->dynamic_vlan++; + hostapd_logger(hapd, sta->addr, + HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, "updated existing " + "dynamic VLAN interface '%s'", iface); + } + + /* + * Update encryption configuration for statically generated + * VLAN interface. This is only used for static WEP + * configuration for the case where hostapd did not yet know + * which keys are to be used when the interface was added. + */ + if (vlan_setup_encryption_dyn(hapd, iface) != 0) { + hostapd_logger(hapd, sta->addr, + HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, "could not " + "configure encryption for VLAN " + "interface for vlan_id=%d", + sta->vlan_id); + } + } + + /* ref counters have been increased, so mark the station */ + sta->vlan_id_bound = sta->vlan_id; + +skip_counting: + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, "binding station to interface " + "'%s'", iface); + + if (wpa_auth_sta_set_vlan(sta->wpa_sm, sta->vlan_id) < 0) + wpa_printf(MSG_INFO, "Failed to update VLAN-ID for WPA"); + + ret = hostapd_drv_set_sta_vlan(iface, hapd, sta->addr, sta->vlan_id); + if (ret < 0) { + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, "could not bind the STA " + "entry to vlan_id=%d", sta->vlan_id); + } + + /* During 1x reauth, if the vlan id changes, then remove the old id. */ + if (old_vlanid > 0 && old_vlanid != sta->vlan_id) + vlan_remove_dynamic(hapd, old_vlanid); +done: + + return ret; +#else /* CONFIG_NO_VLAN */ + return 0; +#endif /* CONFIG_NO_VLAN */ +} + + +#ifdef CONFIG_IEEE80211W + +int ap_check_sa_query_timeout(struct hostapd_data *hapd, struct sta_info *sta) +{ + u32 tu; + struct os_reltime now, passed; + os_get_reltime(&now); + os_reltime_sub(&now, &sta->sa_query_start, &passed); + tu = (passed.sec * 1000000 + passed.usec) / 1024; + if (hapd->conf->assoc_sa_query_max_timeout < tu) { + hostapd_logger(hapd, sta->addr, + HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "association SA Query timed out"); + sta->sa_query_timed_out = 1; + os_free(sta->sa_query_trans_id); + sta->sa_query_trans_id = NULL; + sta->sa_query_count = 0; + eloop_cancel_timeout(ap_sa_query_timer, hapd, sta); + return 1; + } + + return 0; +} + + +static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx) +{ + struct hostapd_data *hapd = eloop_ctx; + struct sta_info *sta = timeout_ctx; + unsigned int timeout, sec, usec; + u8 *trans_id, *nbuf; + + if (sta->sa_query_count > 0 && + ap_check_sa_query_timeout(hapd, sta)) + return; + + nbuf = os_realloc_array(sta->sa_query_trans_id, + sta->sa_query_count + 1, + WLAN_SA_QUERY_TR_ID_LEN); + if (nbuf == NULL) + return; + if (sta->sa_query_count == 0) { + /* Starting a new SA Query procedure */ + os_get_reltime(&sta->sa_query_start); + } + trans_id = nbuf + sta->sa_query_count * WLAN_SA_QUERY_TR_ID_LEN; + sta->sa_query_trans_id = nbuf; + sta->sa_query_count++; + + if (os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN) < 0) { + /* + * We don't really care which ID is used here, so simply + * hardcode this if the mostly theoretical os_get_random() + * failure happens. + */ + trans_id[0] = 0x12; + trans_id[1] = 0x34; + } + + timeout = hapd->conf->assoc_sa_query_retry_timeout; + sec = ((timeout / 1000) * 1024) / 1000; + usec = (timeout % 1000) * 1024; + eloop_register_timeout(sec, usec, ap_sa_query_timer, hapd, sta); + + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "association SA Query attempt %d", sta->sa_query_count); + + ieee802_11_send_sa_query_req(hapd, sta->addr, trans_id); +} + + +void ap_sta_start_sa_query(struct hostapd_data *hapd, struct sta_info *sta) +{ + ap_sa_query_timer(hapd, sta); +} + + +void ap_sta_stop_sa_query(struct hostapd_data *hapd, struct sta_info *sta) +{ + eloop_cancel_timeout(ap_sa_query_timer, hapd, sta); + os_free(sta->sa_query_trans_id); + sta->sa_query_trans_id = NULL; + sta->sa_query_count = 0; +} + +#endif /* CONFIG_IEEE80211W */ + + +void ap_sta_set_authorized(struct hostapd_data *hapd, struct sta_info *sta, + int authorized) +{ + const u8 *dev_addr = NULL; + char buf[100]; +#ifdef CONFIG_P2P + u8 addr[ETH_ALEN]; + u8 ip_addr_buf[4]; +#endif /* CONFIG_P2P */ + + if (!!authorized == !!(sta->flags & WLAN_STA_AUTHORIZED)) + return; + + if (authorized) + sta->flags |= WLAN_STA_AUTHORIZED; + else + sta->flags &= ~WLAN_STA_AUTHORIZED; + +#ifdef CONFIG_P2P + if (hapd->p2p_group == NULL) { + if (sta->p2p_ie != NULL && + p2p_parse_dev_addr_in_p2p_ie(sta->p2p_ie, addr) == 0) + dev_addr = addr; + } else + dev_addr = p2p_group_get_dev_addr(hapd->p2p_group, sta->addr); + + if (dev_addr) + os_snprintf(buf, sizeof(buf), MACSTR " p2p_dev_addr=" MACSTR, + MAC2STR(sta->addr), MAC2STR(dev_addr)); + else +#endif /* CONFIG_P2P */ + os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(sta->addr)); + + if (hapd->sta_authorized_cb) + hapd->sta_authorized_cb(hapd->sta_authorized_cb_ctx, + sta->addr, authorized, dev_addr); + + if (authorized) { + char ip_addr[100]; + ip_addr[0] = '\0'; +#ifdef CONFIG_P2P + if (wpa_auth_get_ip_addr(sta->wpa_sm, ip_addr_buf) == 0) { + os_snprintf(ip_addr, sizeof(ip_addr), + " ip_addr=%u.%u.%u.%u", + ip_addr_buf[0], ip_addr_buf[1], + ip_addr_buf[2], ip_addr_buf[3]); + } +#endif /* CONFIG_P2P */ + + wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED "%s%s", + buf, ip_addr); + + (void)ip_addr; + if (hapd->msg_ctx_parent && + hapd->msg_ctx_parent != hapd->msg_ctx) + wpa_msg_no_global(hapd->msg_ctx_parent, MSG_INFO, + AP_STA_CONNECTED "%s%s", + buf, ip_addr); + } else { + wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED "%s", buf); + + if (hapd->msg_ctx_parent && + hapd->msg_ctx_parent != hapd->msg_ctx) + wpa_msg_no_global(hapd->msg_ctx_parent, MSG_INFO, + AP_STA_DISCONNECTED "%s", buf); + } +} + + +void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *addr, u16 reason) +{ + + if (sta == NULL && addr) + sta = ap_get_sta(hapd, addr); + + if (addr) + hostapd_drv_sta_deauth(hapd, addr, reason); + + if (sta == NULL) + return; + ap_sta_set_authorized(hapd, sta, 0); + wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH); + ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); + sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC); + wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout " + "for " MACSTR " (%d seconds - " + "AP_MAX_INACTIVITY_AFTER_DEAUTH)", + __func__, MAC2STR(sta->addr), + AP_MAX_INACTIVITY_AFTER_DEAUTH); + eloop_cancel_timeout(ap_handle_timer, hapd, sta); + eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DEAUTH, 0, + ap_handle_timer, hapd, sta); + sta->timeout_next = STA_REMOVE; + + sta->deauth_reason = reason; + sta->flags |= WLAN_STA_PENDING_DEAUTH_CB; + eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta); + eloop_register_timeout(hapd->iface->drv_flags & + WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS ? 2 : 0, 0, + ap_sta_deauth_cb_timeout, hapd, sta); +} + + +void ap_sta_deauth_cb(struct hostapd_data *hapd, struct sta_info *sta) +{ + if (!(sta->flags & WLAN_STA_PENDING_DEAUTH_CB)) { + wpa_printf(MSG_DEBUG, "Ignore deauth cb for test frame"); + return; + } + sta->flags &= ~WLAN_STA_PENDING_DEAUTH_CB; + eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta); + ap_sta_deauth_cb_timeout(hapd, sta); +} + + +void ap_sta_disassoc_cb(struct hostapd_data *hapd, struct sta_info *sta) +{ + if (!(sta->flags & WLAN_STA_PENDING_DISASSOC_CB)) { + wpa_printf(MSG_DEBUG, "Ignore disassoc cb for test frame"); + return; + } + sta->flags &= ~WLAN_STA_PENDING_DISASSOC_CB; + eloop_cancel_timeout(ap_sta_disassoc_cb_timeout, hapd, sta); + ap_sta_disassoc_cb_timeout(hapd, sta); +} + + +int ap_sta_flags_txt(u32 flags, char *buf, size_t buflen) +{ + int res; + + buf[0] = '\0'; + res = os_snprintf(buf, buflen, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", + (flags & WLAN_STA_AUTH ? "[AUTH]" : ""), + (flags & WLAN_STA_ASSOC ? "[ASSOC]" : ""), + (flags & WLAN_STA_AUTHORIZED ? "[AUTHORIZED]" : ""), + (flags & WLAN_STA_PENDING_POLL ? "[PENDING_POLL" : + ""), + (flags & WLAN_STA_SHORT_PREAMBLE ? + "[SHORT_PREAMBLE]" : ""), + (flags & WLAN_STA_PREAUTH ? "[PREAUTH]" : ""), + (flags & WLAN_STA_WMM ? "[WMM]" : ""), + (flags & WLAN_STA_MFP ? "[MFP]" : ""), + (flags & WLAN_STA_WPS ? "[WPS]" : ""), + (flags & WLAN_STA_MAYBE_WPS ? "[MAYBE_WPS]" : ""), + (flags & WLAN_STA_WDS ? "[WDS]" : ""), + (flags & WLAN_STA_NONERP ? "[NonERP]" : ""), + (flags & WLAN_STA_WPS2 ? "[WPS2]" : ""), + (flags & WLAN_STA_GAS ? "[GAS]" : ""), + (flags & WLAN_STA_VHT ? "[VHT]" : ""), + (flags & WLAN_STA_VENDOR_VHT ? "[VENDOR_VHT]" : ""), + (flags & WLAN_STA_WNM_SLEEP_MODE ? + "[WNM_SLEEP_MODE]" : "")); + if (os_snprintf_error(buflen, res)) + res = -1; + + return res; +} diff --git a/beken_os/beken378/func/hostapd-2.5/src/ap/sta_info.h b/beken_os/beken378/func/hostapd-2.5/src/ap/sta_info.h new file mode 100755 index 0000000..bf9ad5b --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/ap/sta_info.h @@ -0,0 +1,206 @@ +/* + * hostapd / Station table + * Copyright (c) 2002-2011, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ +#ifndef STA_INFO_H +#define STA_INFO_H + +#ifdef CONFIG_MESH +/* needed for mesh_plink_state enum */ +#include "common/defs.h" +#endif /* CONFIG_MESH */ + +#include "list.h" + +/* STA flags */ +#define WLAN_STA_AUTH BIT(0) +#define WLAN_STA_ASSOC BIT(1) +#define WLAN_STA_AUTHORIZED BIT(5) +#define WLAN_STA_PENDING_POLL BIT(6) /* pending activity poll not ACKed */ +#define WLAN_STA_SHORT_PREAMBLE BIT(7) +#define WLAN_STA_PREAUTH BIT(8) +#define WLAN_STA_WMM BIT(9) +#define WLAN_STA_MFP BIT(10) +#define WLAN_STA_HT BIT(11) +#define WLAN_STA_WPS BIT(12) +#define WLAN_STA_MAYBE_WPS BIT(13) +#define WLAN_STA_WDS BIT(14) +#define WLAN_STA_ASSOC_REQ_OK BIT(15) +#define WLAN_STA_WPS2 BIT(16) +#define WLAN_STA_GAS BIT(17) +#define WLAN_STA_VHT BIT(18) +#define WLAN_STA_WNM_SLEEP_MODE BIT(19) +#define WLAN_STA_VHT_OPMODE_ENABLED BIT(20) +#define WLAN_STA_VENDOR_VHT BIT(21) +#define WLAN_STA_PENDING_DISASSOC_CB BIT(29) +#define WLAN_STA_PENDING_DEAUTH_CB BIT(30) +#define WLAN_STA_NONERP BIT(31) + +/* Maximum number of supported rates (from both Supported Rates and Extended + * Supported Rates IEs). */ +#define WLAN_SUPP_RATES_MAX 32 + + +struct sta_info { + struct sta_info *next; /* next entry in sta list */ + struct sta_info *hnext; /* next entry in hash table list */ + u8 addr[6]; + be32 ipaddr; + struct dl_list ip6addr; /* list head for struct ip6addr */ + u16 aid; /* STA's unique AID (1 .. 2007) or 0 if not yet assigned */ + u32 flags; /* Bitfield of WLAN_STA_* */ + u16 capability; + u16 listen_interval; /* or beacon_int for APs */ + u8 supported_rates[WLAN_SUPP_RATES_MAX]; + int supported_rates_len; + u8 qosinfo; /* Valid when WLAN_STA_WMM is set */ + +#ifdef CONFIG_MESH + enum mesh_plink_state plink_state; + u16 peer_lid; + u16 my_lid; + u16 mpm_close_reason; + int mpm_retries; + u8 my_nonce[32]; + u8 peer_nonce[32]; + u8 aek[32]; /* SHA256 digest length */ + u8 mtk[16]; + u8 mgtk[16]; + u8 sae_auth_retry; +#endif /* CONFIG_MESH */ + + unsigned int nonerp_set:1; + unsigned int no_short_slot_time_set:1; + unsigned int no_short_preamble_set:1; + unsigned int no_ht_gf_set:1; + unsigned int no_ht_set:1; + unsigned int ht40_intolerant_set:1; + unsigned int ht_20mhz_set:1; + unsigned int no_p2p_set:1; + unsigned int qos_map_enabled:1; + unsigned int remediation:1; + unsigned int hs20_deauth_requested:1; + unsigned int session_timeout_set:1; + unsigned int radius_das_match:1; + + u16 auth_alg; + + enum { + STA_NULLFUNC = 0, STA_DISASSOC, STA_DEAUTH, STA_REMOVE, + STA_DISASSOC_FROM_CLI + } timeout_next; + + u16 deauth_reason; + u16 disassoc_reason; + + /* IEEE 802.1X related data */ + struct eapol_state_machine *eapol_sm; + u8 *challenge; /* IEEE 802.11 Shared Key Authentication Challenge */ + + struct wpa_state_machine *wpa_sm; + + int vlan_id; /* 0: none, >0: VID */ + int vlan_id_bound; /* updated by ap_sta_bind_vlan() */ + /* PSKs from RADIUS authentication server */ + struct hostapd_sta_wpa_psk_short *psk; + + struct ieee80211_ht_capabilities *ht_capabilities; + struct ieee80211_vht_capabilities *vht_capabilities; + u8 vht_opmode; + +#ifdef CONFIG_IEEE80211W + int sa_query_count; /* number of pending SA Query requests; + * 0 = no SA Query in progress */ + int sa_query_timed_out; + u8 *sa_query_trans_id; /* buffer of WLAN_SA_QUERY_TR_ID_LEN * + * sa_query_count octets of pending SA Query + * transaction identifiers */ + struct os_reltime sa_query_start; +#endif /* CONFIG_IEEE80211W */ + + struct wpabuf *wps_ie; /* WPS IE from (Re)Association Request */ + struct wpabuf *p2p_ie; /* P2P IE from (Re)Association Request */ + + struct os_reltime connected_time; /* accouting */ + +#ifdef CONFIG_SAE + struct sae_data *sae; +#endif /* CONFIG_SAE */ + + /* Last Authentication/(Re)Association Request/Action frame sequence + * control */ + u16 last_seq_ctrl; + /* Last Authentication/(Re)Association Request/Action frame subtype */ + u8 last_subtype; +}; + + +/* Default value for maximum station inactivity. After AP_MAX_INACTIVITY has + * passed since last received frame from the station, a nullfunc data frame is + * sent to the station. If this frame is not acknowledged and no other frames + * have been received, the station will be disassociated after + * AP_DISASSOC_DELAY seconds. Similarly, the station will be deauthenticated + * after AP_DEAUTH_DELAY seconds has passed after disassociation. */ +#define AP_MAX_INACTIVITY (15) +#define AP_DISASSOC_DELAY (1) +#define AP_DEAUTH_DELAY (1) +/* Number of seconds to keep STA entry with Authenticated flag after it has + * been disassociated. */ +#define AP_MAX_INACTIVITY_AFTER_DISASSOC (1 * 30) +/* Number of seconds to keep STA entry after it has been deauthenticated. */ +#define AP_MAX_INACTIVITY_AFTER_DEAUTH (1 * 5) + + +struct hostapd_data; + +int ap_for_each_sta(struct hostapd_data *hapd, + int (*cb)(struct hostapd_data *hapd, struct sta_info *sta, + void *ctx), + void *ctx); +struct sta_info * ap_get_sta(struct hostapd_data *hapd, const u8 *sta); +struct sta_info * ap_get_sta_p2p(struct hostapd_data *hapd, const u8 *addr); +void ap_sta_hash_add(struct hostapd_data *hapd, struct sta_info *sta); +void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta); +void ap_sta_ip6addr_del(struct hostapd_data *hapd, struct sta_info *sta); +void hostapd_free_stas(struct hostapd_data *hapd); +void ap_handle_timer(void *eloop_ctx, void *timeout_ctx); +void ap_sta_replenish_timeout(struct hostapd_data *hapd, struct sta_info *sta, + u32 session_timeout); +void ap_sta_session_timeout(struct hostapd_data *hapd, struct sta_info *sta, + u32 session_timeout); +void ap_sta_no_session_timeout(struct hostapd_data *hapd, + struct sta_info *sta); +void ap_sta_session_warning_timeout(struct hostapd_data *hapd, + struct sta_info *sta, int warning_time); +struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr); +void ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta, + u16 reason); +void ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta, + u16 reason); +#ifdef CONFIG_WPS +int ap_sta_wps_cancel(struct hostapd_data *hapd, + struct sta_info *sta, void *ctx); +#endif /* CONFIG_WPS */ +int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta); +void ap_sta_start_sa_query(struct hostapd_data *hapd, struct sta_info *sta); +void ap_sta_stop_sa_query(struct hostapd_data *hapd, struct sta_info *sta); +int ap_check_sa_query_timeout(struct hostapd_data *hapd, struct sta_info *sta); +void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *addr, u16 reason); + +void ap_sta_set_authorized(struct hostapd_data *hapd, + struct sta_info *sta, int authorized); +static inline int ap_sta_is_authorized(struct sta_info *sta) +{ + return sta->flags & WLAN_STA_AUTHORIZED; +} + +void ap_sta_deauth_cb(struct hostapd_data *hapd, struct sta_info *sta); +void ap_sta_disassoc_cb(struct hostapd_data *hapd, struct sta_info *sta); + +int ap_sta_flags_txt(u32 flags, char *buf, size_t buflen); + +#endif /* STA_INFO_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/ap/tkip_countermeasures.c b/beken_os/beken378/func/hostapd-2.5/src/ap/tkip_countermeasures.c new file mode 100755 index 0000000..a0120b2 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/ap/tkip_countermeasures.c @@ -0,0 +1,106 @@ +/* + * hostapd / TKIP countermeasures + * Copyright (c) 2002-2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "utils/eloop.h" +#include "common/ieee802_11_defs.h" +#include "ap/hostapd.h" +#include "ap/sta_info.h" +#include "ap_mlme.h" +#include "wpa_auth.h" +#include "ap_drv_ops.h" +#include "tkip_countermeasures.h" + + +static void ieee80211_tkip_countermeasures_stop(void *eloop_ctx, + void *timeout_ctx) +{ + struct hostapd_data *hapd = eloop_ctx; + hapd->tkip_countermeasures = 0; + hostapd_drv_set_countermeasures(hapd, 0); + hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, "TKIP countermeasures ended"); +} + + +static void ieee80211_tkip_countermeasures_start(struct hostapd_data *hapd) +{ + struct sta_info *sta; + + hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, "TKIP countermeasures initiated"); + + wpa_auth_countermeasures_start(hapd->wpa_auth); + hapd->tkip_countermeasures = 1; + hostapd_drv_set_countermeasures(hapd, 1); + wpa_gtk_rekey(hapd->wpa_auth); + eloop_cancel_timeout(ieee80211_tkip_countermeasures_stop, hapd, NULL); + eloop_register_timeout(60, 0, ieee80211_tkip_countermeasures_stop, + hapd, NULL); + while ((sta = hapd->sta_list) != NULL) { +#if 0 + sta->acct_terminate_cause = + RADIUS_ACCT_TERMINATE_CAUSE_ADMIN_RESET; +#endif + if (sta->flags & WLAN_STA_AUTH) { + mlme_deauthenticate_indication( + hapd, sta, + WLAN_REASON_MICHAEL_MIC_FAILURE); + } + hostapd_drv_sta_deauth(hapd, sta->addr, + WLAN_REASON_MICHAEL_MIC_FAILURE); + ap_free_sta(hapd, sta); + } +} + + +void ieee80211_tkip_countermeasures_deinit(struct hostapd_data *hapd) +{ + eloop_cancel_timeout(ieee80211_tkip_countermeasures_stop, hapd, NULL); +} + + +int michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, int local) +{ + struct os_reltime now; + int ret = 0; + + if (addr && local) { + struct sta_info *sta = ap_get_sta(hapd, addr); + if (sta != NULL) { + wpa_auth_sta_local_mic_failure_report(sta->wpa_sm); + hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, + "Michael MIC failure detected in " + "received frame"); + mlme_michaelmicfailure_indication(hapd, addr); + } else { + wpa_printf(MSG_DEBUG, + "MLME-MICHAELMICFAILURE.indication " + "for not associated STA (" MACSTR + ") ignored", MAC2STR(addr)); + return ret; + } + } + + os_get_reltime(&now); + if (os_reltime_expired(&now, &hapd->michael_mic_failure, 60)) { + hapd->michael_mic_failures = 1; + } else { + hapd->michael_mic_failures++; + if (hapd->michael_mic_failures > 1) { + ieee80211_tkip_countermeasures_start(hapd); + ret = 1; + } + } + hapd->michael_mic_failure = now; + + return ret; +} diff --git a/beken_os/beken378/func/hostapd-2.5/src/ap/tkip_countermeasures.h b/beken_os/beken378/func/hostapd-2.5/src/ap/tkip_countermeasures.h new file mode 100755 index 0000000..d3eaed3 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/ap/tkip_countermeasures.h @@ -0,0 +1,15 @@ +/* + * hostapd / TKIP countermeasures + * Copyright (c) 2002-2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef TKIP_COUNTERMEASURES_H +#define TKIP_COUNTERMEASURES_H + +int michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, int local); +void ieee80211_tkip_countermeasures_deinit(struct hostapd_data *hapd); + +#endif /* TKIP_COUNTERMEASURES_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/ap/utils.c b/beken_os/beken378/func/hostapd-2.5/src/ap/utils.c new file mode 100755 index 0000000..0bab135 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/ap/utils.c @@ -0,0 +1,95 @@ +/* + * AP mode helper functions + * Copyright (c) 2009, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "common/ieee802_11_defs.h" +#include "ap/sta_info.h" +#include "ap/hostapd.h" + + +int hostapd_register_probereq_cb(struct hostapd_data *hapd, + int (*cb)(void *ctx, const u8 *sa, + const u8 *da, const u8 *bssid, + const u8 *ie, size_t ie_len, + int ssi_signal), + void *ctx) +{ + struct hostapd_probereq_cb *n; + + n = os_realloc_array(hapd->probereq_cb, hapd->num_probereq_cb + 1, + sizeof(struct hostapd_probereq_cb)); + if (n == NULL) + return -1; + + hapd->probereq_cb = n; + n = &hapd->probereq_cb[hapd->num_probereq_cb]; + hapd->num_probereq_cb++; + + n->cb = cb; + n->ctx = ctx; + + return 0; +} + + +struct prune_data { + struct hostapd_data *hapd; + const u8 *addr; +}; + +static int prune_associations(struct hostapd_iface *iface, void *ctx) +{ + struct prune_data *data = ctx; + struct sta_info *osta; + struct hostapd_data *ohapd; + size_t j; + + for (j = 0; j < iface->num_bss; j++) { + ohapd = iface->bss[j]; + if (ohapd == data->hapd) + continue; +#ifdef CONFIG_FST + /* Don't prune STAs belong to same FST */ + if (ohapd->iface->fst && + data->hapd->iface->fst && + fst_are_ifaces_aggregated(ohapd->iface->fst, + data->hapd->iface->fst)) + continue; +#endif /* CONFIG_FST */ + osta = ap_get_sta(ohapd, data->addr); + if (!osta) + continue; + + wpa_printf(MSG_INFO, "%s: Prune association for " MACSTR, + ohapd->conf->iface, MAC2STR(osta->addr)); + ap_sta_disassociate(ohapd, osta, WLAN_REASON_UNSPECIFIED); + } + + return 0; +} + +/** + * hostapd_prune_associations - Remove extraneous associations + * @hapd: Pointer to BSS data for the most recent association + * @addr: Associated STA address + * + * This function looks through all radios and BSS's for previous + * (stale) associations of STA. If any are found they are removed. + */ +void hostapd_prune_associations(struct hostapd_data *hapd, const u8 *addr) +{ + struct prune_data data; + data.hapd = hapd; + data.addr = addr; + if (hapd->iface->interfaces && + hapd->iface->interfaces->for_each_interface) + hapd->iface->interfaces->for_each_interface( + hapd->iface->interfaces, prune_associations, &data); +} diff --git a/beken_os/beken378/func/hostapd-2.5/src/ap/vlan_init.h b/beken_os/beken378/func/hostapd-2.5/src/ap/vlan_init.h new file mode 100755 index 0000000..fc39443 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/ap/vlan_init.h @@ -0,0 +1,51 @@ +/* + * hostapd / VLAN initialization + * Copyright 2003, Instant802 Networks, Inc. + * Copyright 2005, Devicescape Software, Inc. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef VLAN_INIT_H +#define VLAN_INIT_H + +#ifndef CONFIG_NO_VLAN +int vlan_init(struct hostapd_data *hapd); +void vlan_deinit(struct hostapd_data *hapd); +struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd, + struct hostapd_vlan *vlan, + int vlan_id); +int vlan_remove_dynamic(struct hostapd_data *hapd, int vlan_id); +int vlan_setup_encryption_dyn(struct hostapd_data *hapd, + const char *dyn_vlan); +#else /* CONFIG_NO_VLAN */ +static inline int vlan_init(struct hostapd_data *hapd) +{ + return 0; +} + +static inline void vlan_deinit(struct hostapd_data *hapd) +{ +} + +static inline struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd, + struct hostapd_vlan *vlan, + int vlan_id) +{ + return NULL; +} + +static inline int vlan_remove_dynamic(struct hostapd_data *hapd, int vlan_id) +{ + return -1; +} + +static inline int vlan_setup_encryption_dyn(struct hostapd_data *hapd, + const char *dyn_vlan) +{ + return -1; +} +#endif /* CONFIG_NO_VLAN */ + +#endif /* VLAN_INIT_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/ap/wmm.c b/beken_os/beken378/func/hostapd-2.5/src/ap/wmm.c new file mode 100755 index 0000000..020e142 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/ap/wmm.c @@ -0,0 +1,357 @@ +/* + * hostapd / WMM (Wi-Fi Multimedia) + * Copyright 2002-2003, Instant802 Networks, Inc. + * Copyright 2005-2006, Devicescape Software, Inc. + * Copyright (c) 2009, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "common/ieee802_11_defs.h" +#include "common/ieee802_11_common.h" +#include "ap/hostapd.h" +#include "ieee802_11.h" +#include "ap/sta_info.h" +#include "ap_config.h" +#include "ap_drv_ops.h" +#include "wmm.h" + + +/* TODO: maintain separate sequence and fragment numbers for each AC + * TODO: IGMP snooping to track which multicasts to forward - and use QOS-DATA + * if only WMM stations are receiving a certain group */ + + +u8 wmm_aci_aifsn(int aifsn, int acm, int aci) +{ + u8 ret; + ret = (aifsn << WMM_AC_AIFNS_SHIFT) & WMM_AC_AIFSN_MASK; + if (acm) + ret |= WMM_AC_ACM; + ret |= (aci << WMM_AC_ACI_SHIFT) & WMM_AC_ACI_MASK; + return ret; +} + + +/* + * Add WMM Parameter Element to Beacon, Probe Response, and (Re)Association + * Response frames. + */ +u8 * hostapd_eid_wmm(struct hostapd_data *hapd, u8 *eid) +{ +#if 1 + u8 *rivieraWaveVendorIE = eid; + + rivieraWaveVendorIE[0] = WLAN_EID_VENDOR_SPECIFIC; + rivieraWaveVendorIE[1] = 0x18; + rivieraWaveVendorIE[2] = 0x00; + rivieraWaveVendorIE[3] = 0x50; + rivieraWaveVendorIE[4] = 0xf2; + rivieraWaveVendorIE[5] = 0x02; + rivieraWaveVendorIE[6] = 0x01; + rivieraWaveVendorIE[7] = 0x01; + rivieraWaveVendorIE[8] = 0x00; + rivieraWaveVendorIE[9] = 0x00; + rivieraWaveVendorIE[10] = 0x03; + rivieraWaveVendorIE[11] = 0xa4; + rivieraWaveVendorIE[12] = 0x00; + rivieraWaveVendorIE[13] = 0x00; + rivieraWaveVendorIE[14] = 0x27; + rivieraWaveVendorIE[15] = 0xa4; + rivieraWaveVendorIE[16] = 0x00; + rivieraWaveVendorIE[17] = 0x00; + rivieraWaveVendorIE[18] = 0x42; + rivieraWaveVendorIE[19] = 0x43; + rivieraWaveVendorIE[20] = 0x5e; + rivieraWaveVendorIE[21] = 0x00; + rivieraWaveVendorIE[22] = 0x62; + rivieraWaveVendorIE[23] = 0x32; + rivieraWaveVendorIE[24] = 0x2f; + rivieraWaveVendorIE[25] = 0x00; + + return (u8*)((u32)eid + rivieraWaveVendorIE[1] + 2); +#else + u8 *pos = eid; + struct wmm_parameter_element *wmm = + (struct wmm_parameter_element *) (pos + 2); + int e; + + if (!hapd->conf->wmm_enabled) + return eid; + eid[0] = WLAN_EID_VENDOR_SPECIFIC; + wmm->oui[0] = 0x00; + wmm->oui[1] = 0x50; + wmm->oui[2] = 0xf2; + wmm->oui_type = WMM_OUI_TYPE; + wmm->oui_subtype = WMM_OUI_SUBTYPE_PARAMETER_ELEMENT; + wmm->version = WMM_VERSION; + wmm->qos_info = hapd->parameter_set_count & 0xf; + + if (hapd->conf->wmm_uapsd && + (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_UAPSD)) + wmm->qos_info |= 0x80; + + wmm->reserved = 0; + + /* fill in a parameter set record for each AC */ + for (e = 0; e < 4; e++) { + struct wmm_ac_parameter *ac = &wmm->ac[e]; + struct hostapd_wmm_ac_params *acp = + &hapd->iconf->wmm_ac_params[e]; + + ac->aci_aifsn = wmm_aci_aifsn(acp->aifs, + acp->admission_control_mandatory, + e); + ac->cw = wmm_ecw(acp->cwmin, acp->cwmax); + ac->txop_limit = host_to_le16(acp->txop_limit); + } + + pos = (u8 *) (wmm + 1); + eid[1] = pos - eid - 2; /* element length */ + + return pos; +#endif +} + + +/* + * This function is called when a station sends an association request with + * WMM info element. The function returns 1 on success or 0 on any error in WMM + * element. eid does not include Element ID and Length octets. + */ +int hostapd_eid_wmm_valid(struct hostapd_data *hapd, const u8 *eid, size_t len) +{ + struct wmm_information_element *wmm; + + wpa_hexdump(MSG_MSGDUMP, "WMM IE", eid, len); + + if (len < sizeof(struct wmm_information_element)) { + wpa_printf(MSG_DEBUG, "Too short WMM IE (len=%lu)", + (unsigned long) len); + return 0; + } + + wmm = (struct wmm_information_element *) eid; + wpa_printf(MSG_DEBUG, "Validating WMM IE: OUI %02x:%02x:%02x " + "OUI type %d OUI sub-type %d version %d QoS info 0x%x", + wmm->oui[0], wmm->oui[1], wmm->oui[2], wmm->oui_type, + wmm->oui_subtype, wmm->version, wmm->qos_info); + if (wmm->oui_subtype != WMM_OUI_SUBTYPE_INFORMATION_ELEMENT || + wmm->version != WMM_VERSION) { + wpa_printf(MSG_DEBUG, "Unsupported WMM IE Subtype/Version"); + return 0; + } + + return 1; +} + + +static void wmm_send_action(struct hostapd_data *hapd, const u8 *addr, + const struct wmm_tspec_element *tspec, + u8 action_code, u8 dialogue_token, u8 status_code) +{ + u8 buf[256]; + struct ieee80211_mgmt *m = (struct ieee80211_mgmt *) buf; + struct wmm_tspec_element *t = (struct wmm_tspec_element *) + m->u.action.u.wmm_action.variable; + int len; + + hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "action response - reason %d", status_code); + os_memset(buf, 0, sizeof(buf)); + m->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, + WLAN_FC_STYPE_ACTION); + os_memcpy(m->da, addr, ETH_ALEN); + os_memcpy(m->sa, hapd->own_addr, ETH_ALEN); + os_memcpy(m->bssid, hapd->own_addr, ETH_ALEN); + m->u.action.category = WLAN_ACTION_WMM; + m->u.action.u.wmm_action.action_code = action_code; + m->u.action.u.wmm_action.dialog_token = dialogue_token; + m->u.action.u.wmm_action.status_code = status_code; + os_memcpy(t, tspec, sizeof(struct wmm_tspec_element)); + len = ((u8 *) (t + 1)) - buf; + + if (hostapd_drv_send_mlme(hapd, m, len, 0) < 0) + wpa_printf(MSG_INFO, "wmm_send_action: send failed"); +} + + +int wmm_process_tspec(struct wmm_tspec_element *tspec) +{ + int medium_time, pps, duration; + int up, psb, dir, tid; + u16 val, surplus; + + up = (tspec->ts_info[1] >> 3) & 0x07; + psb = (tspec->ts_info[1] >> 2) & 0x01; + dir = (tspec->ts_info[0] >> 5) & 0x03; + tid = (tspec->ts_info[0] >> 1) & 0x0f; + wpa_printf(MSG_DEBUG, "WMM: TS Info: UP=%d PSB=%d Direction=%d TID=%d", + up, psb, dir, tid); + val = le_to_host16(tspec->nominal_msdu_size); + wpa_printf(MSG_DEBUG, "WMM: Nominal MSDU Size: %d%s", + val & 0x7fff, val & 0x8000 ? " (fixed)" : ""); + wpa_printf(MSG_DEBUG, "WMM: Mean Data Rate: %u bps", + le_to_host32(tspec->mean_data_rate)); + wpa_printf(MSG_DEBUG, "WMM: Minimum PHY Rate: %u bps", + le_to_host32(tspec->minimum_phy_rate)); + val = le_to_host16(tspec->surplus_bandwidth_allowance); + wpa_printf(MSG_DEBUG, "WMM: Surplus Bandwidth Allowance: %u.%04u", + val >> 13, 10000 * (val & 0x1fff) / 0x2000); + + val = le_to_host16(tspec->nominal_msdu_size); + if (val == 0) { + wpa_printf(MSG_DEBUG, "WMM: Invalid Nominal MSDU Size (0)"); + return WMM_ADDTS_STATUS_INVALID_PARAMETERS; + } + /* pps = Ceiling((Mean Data Rate / 8) / Nominal MSDU Size) */ + pps = ((le_to_host32(tspec->mean_data_rate) / 8) + val - 1) / val; + wpa_printf(MSG_DEBUG, "WMM: Packets-per-second estimate for TSPEC: %d", + pps); + + if (le_to_host32(tspec->minimum_phy_rate) < 1000000) { + wpa_printf(MSG_DEBUG, "WMM: Too small Minimum PHY Rate"); + return WMM_ADDTS_STATUS_INVALID_PARAMETERS; + } + + duration = (le_to_host16(tspec->nominal_msdu_size) & 0x7fff) * 8 / + (le_to_host32(tspec->minimum_phy_rate) / 1000000) + + 50 /* FIX: proper SIFS + ACK duration */; + + /* unsigned binary number with an implicit binary point after the + * leftmost 3 bits, i.e., 0x2000 = 1.0 */ + surplus = le_to_host16(tspec->surplus_bandwidth_allowance); + if (surplus <= 0x2000) { + wpa_printf(MSG_DEBUG, "WMM: Surplus Bandwidth Allowance not " + "greater than unity"); + return WMM_ADDTS_STATUS_INVALID_PARAMETERS; + } + + medium_time = surplus * pps * duration / 0x2000; + wpa_printf(MSG_DEBUG, "WMM: Estimated medium time: %u", medium_time); + + /* + * TODO: store list of granted (and still active) TSPECs and check + * whether there is available medium time for this request. For now, + * just refuse requests that would by themselves take very large + * portion of the available bandwidth. + */ + if (medium_time > 750000) { + wpa_printf(MSG_DEBUG, "WMM: Refuse TSPEC request for over " + "75%% of available bandwidth"); + return WMM_ADDTS_STATUS_REFUSED; + } + + /* Convert to 32 microseconds per second unit */ + tspec->medium_time = host_to_le16(medium_time / 32); + + (void)up; + (void)psb; + (void)dir; + (void)tid; + return WMM_ADDTS_STATUS_ADMISSION_ACCEPTED; +} + + +static void wmm_addts_req(struct hostapd_data *hapd, + const struct ieee80211_mgmt *mgmt, + struct wmm_tspec_element *tspec, size_t len) +{ + const u8 *end = ((const u8 *) mgmt) + len; + int res; + + if ((const u8 *) (tspec + 1) > end) { + wpa_printf(MSG_DEBUG, "WMM: TSPEC overflow in ADDTS Request"); + return; + } + + wpa_printf(MSG_DEBUG, "WMM: ADDTS Request (Dialog Token %d) for TSPEC " + "from " MACSTR, + mgmt->u.action.u.wmm_action.dialog_token, + MAC2STR(mgmt->sa)); + + res = wmm_process_tspec(tspec); + wpa_printf(MSG_DEBUG, "WMM: ADDTS processing result: %d", res); + + wmm_send_action(hapd, mgmt->sa, tspec, WMM_ACTION_CODE_ADDTS_RESP, + mgmt->u.action.u.wmm_action.dialog_token, res); +} + + +void hostapd_wmm_action(struct hostapd_data *hapd, + const struct ieee80211_mgmt *mgmt, size_t len) +{ + int action_code; + int left = len - IEEE80211_HDRLEN - 4; + const u8 *pos = ((const u8 *) mgmt) + IEEE80211_HDRLEN + 4; + struct ieee802_11_elems elems; + struct sta_info *sta = ap_get_sta(hapd, mgmt->sa); + + /* check that the request comes from a valid station */ + if (!sta || + (sta->flags & (WLAN_STA_ASSOC | WLAN_STA_WMM)) != + (WLAN_STA_ASSOC | WLAN_STA_WMM)) { + hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "wmm action received is not from associated wmm" + " station"); + /* TODO: respond with action frame refused status code */ + return; + } + + if (left < 0) + return; /* not a valid WMM Action frame */ + + /* extract the tspec info element */ + if (ieee802_11_parse_elems(pos, left, &elems, 1) == ParseFailed) { + hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "hostapd_wmm_action - could not parse wmm " + "action"); + /* TODO: respond with action frame invalid parameters status + * code */ + return; + } + + if (!elems.wmm_tspec || + elems.wmm_tspec_len != (sizeof(struct wmm_tspec_element) - 2)) { + hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "hostapd_wmm_action - missing or wrong length " + "tspec"); + /* TODO: respond with action frame invalid parameters status + * code */ + return; + } + + /* TODO: check the request is for an AC with ACM set, if not, refuse + * request */ + + action_code = mgmt->u.action.u.wmm_action.action_code; + switch (action_code) { + case WMM_ACTION_CODE_ADDTS_REQ: + wmm_addts_req(hapd, mgmt, (struct wmm_tspec_element *) + (elems.wmm_tspec - 2), len); + return; +#if 0 + /* TODO: needed for client implementation */ + case WMM_ACTION_CODE_ADDTS_RESP: + wmm_setup_request(hapd, mgmt, len); + return; + /* TODO: handle station teardown requests */ + case WMM_ACTION_CODE_DELTS: + wmm_teardown(hapd, mgmt, len); + return; +#endif + } + + hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "hostapd_wmm_action - unknown action code %d", + action_code); +} diff --git a/beken_os/beken378/func/hostapd-2.5/src/ap/wmm.h b/beken_os/beken378/func/hostapd-2.5/src/ap/wmm.h new file mode 100755 index 0000000..b70b863 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/ap/wmm.h @@ -0,0 +1,23 @@ +/* + * hostapd / WMM (Wi-Fi Multimedia) + * Copyright 2002-2003, Instant802 Networks, Inc. + * Copyright 2005-2006, Devicescape Software, Inc. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef WME_H +#define WME_H + +struct ieee80211_mgmt; +struct wmm_tspec_element; + +u8 * hostapd_eid_wmm(struct hostapd_data *hapd, u8 *eid); +int hostapd_eid_wmm_valid(struct hostapd_data *hapd, const u8 *eid, + size_t len); +void hostapd_wmm_action(struct hostapd_data *hapd, + const struct ieee80211_mgmt *mgmt, size_t len); +int wmm_process_tspec(struct wmm_tspec_element *tspec); + +#endif /* WME_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/ap/wpa_auth.c b/beken_os/beken378/func/hostapd-2.5/src/ap/wpa_auth.c new file mode 100755 index 0000000..f515889 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/ap/wpa_auth.c @@ -0,0 +1,3259 @@ +/* + * IEEE 802.11 RSN / WPA Authenticator + * Copyright (c) 2004-2015, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "utils/eloop.h" +#include "utils/state_machine.h" +#include "common/ieee802_11_defs.h" +#include "crypto/aes_wrap.h" +#include "crypto/crypto.h" +#include "crypto/sha1.h" +#include "crypto/sha256.h" +#include "crypto/random.h" +#include "ap_config.h" +#include "ieee802_11.h" +#include "wpa_auth.h" +#include "wpa_auth_i.h" +#include "wpa_auth_ie.h" + +#define STATE_MACHINE_DATA struct wpa_state_machine +#define STATE_MACHINE_DEBUG_PREFIX "WPA" +#define STATE_MACHINE_ADDR sm->addr + + +static void wpa_send_eapol_timeout(void *eloop_ctx, void *timeout_ctx); +static int wpa_sm_step(struct wpa_state_machine *sm); +static int wpa_verify_key_mic(int akmp, struct wpa_ptk *PTK, u8 *data, + size_t data_len); +static void wpa_sm_call_step(void *eloop_ctx, void *timeout_ctx); +static void wpa_group_sm_step(struct wpa_authenticator *wpa_auth, + struct wpa_group *group); +static void wpa_request_new_ptk(struct wpa_state_machine *sm); +static int wpa_gtk_update(struct wpa_authenticator *wpa_auth, + struct wpa_group *group); +static int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth, + struct wpa_group *group); +static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce, + const u8 *pmk, struct wpa_ptk *ptk); +static void wpa_group_free(struct wpa_authenticator *wpa_auth, + struct wpa_group *group); +static void wpa_group_get(struct wpa_authenticator *wpa_auth, + struct wpa_group *group); +static void wpa_group_put(struct wpa_authenticator *wpa_auth, + struct wpa_group *group); + +static const u32 dot11RSNAConfigGroupUpdateCount = 4; +static const u32 dot11RSNAConfigPairwiseUpdateCount = 4; +static const u32 eapol_key_timeout_first = 100; /* ms */ +static const u32 eapol_key_timeout_subseq = 1000; /* ms */ +static const u32 eapol_key_timeout_first_group = 500; /* ms */ + +/* TODO: make these configurable */ +static const int dot11RSNAConfigPMKLifetime = 43200; +static const int dot11RSNAConfigPMKReauthThreshold = 70; +static const int dot11RSNAConfigSATimeout = 60; + + +static inline int wpa_auth_mic_failure_report( + struct wpa_authenticator *wpa_auth, const u8 *addr) +{ + if (wpa_auth->cb.mic_failure_report) + return wpa_auth->cb.mic_failure_report(wpa_auth->cb.ctx, addr); + return 0; +} + + +static inline void wpa_auth_psk_failure_report( + struct wpa_authenticator *wpa_auth, const u8 *addr) +{ + if (wpa_auth->cb.psk_failure_report) + wpa_auth->cb.psk_failure_report(wpa_auth->cb.ctx, addr); +} + + +static inline void wpa_auth_set_eapol(struct wpa_authenticator *wpa_auth, + const u8 *addr, wpa_eapol_variable var, + int value) +{ + if (wpa_auth->cb.set_eapol) + wpa_auth->cb.set_eapol(wpa_auth->cb.ctx, addr, var, value); +} + + +static inline int wpa_auth_get_eapol(struct wpa_authenticator *wpa_auth, + const u8 *addr, wpa_eapol_variable var) +{ + if (wpa_auth->cb.get_eapol == NULL) + return -1; + return wpa_auth->cb.get_eapol(wpa_auth->cb.ctx, addr, var); +} + + +static inline const u8 * wpa_auth_get_psk(struct wpa_authenticator *wpa_auth, + const u8 *addr, + const u8 *p2p_dev_addr, + const u8 *prev_psk) +{ + if (wpa_auth->cb.get_psk == NULL) + return NULL; + return wpa_auth->cb.get_psk(wpa_auth->cb.ctx, addr, p2p_dev_addr, + prev_psk); +} + + +static inline int wpa_auth_get_msk(struct wpa_authenticator *wpa_auth, + const u8 *addr, u8 *msk, size_t *len) +{ + if (wpa_auth->cb.get_msk == NULL) + return -1; + return wpa_auth->cb.get_msk(wpa_auth->cb.ctx, addr, msk, len); +} + + +static inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth, + int vlan_id, + enum wpa_alg alg, const u8 *addr, int idx, + u8 *key, size_t key_len) +{ + if (wpa_auth->cb.set_key == NULL) + return -1; + return wpa_auth->cb.set_key(wpa_auth->cb.ctx, vlan_id, alg, addr, idx, + key, key_len); +} + + +static inline int wpa_auth_get_seqnum(struct wpa_authenticator *wpa_auth, + const u8 *addr, int idx, u8 *seq) +{ + if (wpa_auth->cb.get_seqnum == NULL) + return -1; + return wpa_auth->cb.get_seqnum(wpa_auth->cb.ctx, addr, idx, seq); +} + + +static inline int +wpa_auth_send_eapol(struct wpa_authenticator *wpa_auth, const u8 *addr, + const u8 *data, size_t data_len, int encrypt) +{ + if (wpa_auth->cb.send_eapol == NULL) + return -1; + return wpa_auth->cb.send_eapol(wpa_auth->cb.ctx, addr, data, data_len, + encrypt); +} + + +#ifdef CONFIG_MESH +static inline int wpa_auth_start_ampe(struct wpa_authenticator *wpa_auth, + const u8 *addr) +{ + if (wpa_auth->cb.start_ampe == NULL) + return -1; + return wpa_auth->cb.start_ampe(wpa_auth->cb.ctx, addr); +} +#endif /* CONFIG_MESH */ + + +int wpa_auth_for_each_sta(struct wpa_authenticator *wpa_auth, + int (*cb)(struct wpa_state_machine *sm, void *ctx), + void *cb_ctx) +{ + if (wpa_auth->cb.for_each_sta == NULL) + return 0; + return wpa_auth->cb.for_each_sta(wpa_auth->cb.ctx, cb, cb_ctx); +} + + +int wpa_auth_for_each_auth(struct wpa_authenticator *wpa_auth, + int (*cb)(struct wpa_authenticator *a, void *ctx), + void *cb_ctx) +{ + if (wpa_auth->cb.for_each_auth == NULL) + return 0; + return wpa_auth->cb.for_each_auth(wpa_auth->cb.ctx, cb, cb_ctx); +} + +#if CFG_ENABLE_WPA_LOG +void wpa_auth_logger(struct wpa_authenticator *wpa_auth, const u8 *addr, + logger_level level, const char *txt) +{ + if (wpa_auth->cb.logger == NULL) + return; + wpa_auth->cb.logger(wpa_auth->cb.ctx, addr, level, txt); +} + + +void wpa_auth_vlogger(struct wpa_authenticator *wpa_auth, const u8 *addr, + logger_level level, const char *fmt, ...) +{ + char *format; + int maxlen; + va_list ap; + + if (wpa_auth->cb.logger == NULL) + return; + + maxlen = os_strlen(fmt) + 100; + format = os_malloc(maxlen); + if (!format) + return; + + va_start(ap, fmt); + vsnprintf(format, maxlen, fmt, ap); + va_end(ap); + + wpa_auth_logger(wpa_auth, addr, level, format); + + os_free(format); +} +#endif + +static void wpa_sta_disconnect(struct wpa_authenticator *wpa_auth, + const u8 *addr) +{ + if (wpa_auth->cb.disconnect == NULL) + return; + wpa_printf(MSG_DEBUG, "wpa_sta_disconnect STA " MACSTR, MAC2STR(addr)); + wpa_auth->cb.disconnect(wpa_auth->cb.ctx, addr, + WLAN_REASON_PREV_AUTH_NOT_VALID); +} + + +static int wpa_use_aes_cmac(struct wpa_state_machine *sm) +{ + int ret = 0; +#ifdef CONFIG_IEEE80211R + if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) + ret = 1; +#endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_IEEE80211W + if (wpa_key_mgmt_sha256(sm->wpa_key_mgmt)) + ret = 1; +#endif /* CONFIG_IEEE80211W */ + if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) + ret = 1; + return ret; +} + + +static void wpa_rekey_gmk(void *eloop_ctx, void *timeout_ctx) +{ + struct wpa_authenticator *wpa_auth = eloop_ctx; + + if (random_get_bytes(wpa_auth->group->GMK, WPA_GMK_LEN)) { + wpa_printf(MSG_ERROR, "Failed to get random data for WPA " + "initialization."); + } else { + wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG, "GMK rekeyd"); + wpa_hexdump_key(MSG_DEBUG, "GMK", + wpa_auth->group->GMK, WPA_GMK_LEN); + } + + if (wpa_auth->conf.wpa_gmk_rekey) { + eloop_register_timeout(wpa_auth->conf.wpa_gmk_rekey, 0, + wpa_rekey_gmk, wpa_auth, NULL); + } +} + + +static void wpa_rekey_gtk(void *eloop_ctx, void *timeout_ctx) +{ + struct wpa_authenticator *wpa_auth = eloop_ctx; + struct wpa_group *group, *next; + + wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG, "rekeying GTK"); + group = wpa_auth->group; + while (group) { + wpa_group_get(wpa_auth, group); + + group->GTKReKey = TRUE; + do { + group->changed = FALSE; + wpa_group_sm_step(wpa_auth, group); + } while (group->changed); + + next = group->next; + wpa_group_put(wpa_auth, group); + group = next; + } + + if (wpa_auth->conf.wpa_group_rekey) { + eloop_register_timeout(wpa_auth->conf.wpa_group_rekey, + 0, wpa_rekey_gtk, wpa_auth, NULL); + } +} + + +static void wpa_rekey_ptk(void *eloop_ctx, void *timeout_ctx) +{ + struct wpa_authenticator *wpa_auth = eloop_ctx; + struct wpa_state_machine *sm = timeout_ctx; + + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "rekeying PTK"); + wpa_request_new_ptk(sm); + wpa_sm_step(sm); + (void)wpa_auth; +} + +static int wpa_group_init_gmk_and_counter(struct wpa_authenticator *wpa_auth, + struct wpa_group *group) +{ + u8 buf[ETH_ALEN + 8 + sizeof(unsigned long)]; + u8 rkey[32]; + unsigned long ptr; + + if (random_get_bytes(group->GMK, WPA_GMK_LEN) < 0) + return -1; + wpa_hexdump_key(MSG_DEBUG, "GMK", group->GMK, WPA_GMK_LEN); + + /* + * Counter = PRF-256(Random number, "Init Counter", + * Local MAC Address || Time) + */ + os_memcpy(buf, wpa_auth->addr, ETH_ALEN); + wpa_get_ntp_timestamp(buf + ETH_ALEN); + ptr = (unsigned long) group; + os_memcpy(buf + ETH_ALEN + 8, &ptr, sizeof(ptr)); + if (random_get_bytes(rkey, sizeof(rkey)) < 0) + return -1; + + if (sha1_prf(rkey, sizeof(rkey), "Init Counter", buf, sizeof(buf), + group->Counter, WPA_NONCE_LEN) < 0) + return -1; + wpa_hexdump_key(MSG_DEBUG, "Key Counter", + group->Counter, WPA_NONCE_LEN); + + return 0; +} + + +static struct wpa_group * wpa_group_init(struct wpa_authenticator *wpa_auth, + int vlan_id, int delay_init) +{ + struct wpa_group *group; + + group = os_zalloc(sizeof(struct wpa_group)); + if (group == NULL) + return NULL; + + group->GTKAuthenticator = TRUE; + group->vlan_id = vlan_id; + group->GTK_len = wpa_cipher_key_len(wpa_auth->conf.wpa_group); + + if (random_pool_ready() != 1) { + wpa_printf(MSG_INFO, "WPA: Not enough entropy in random pool " + "for secure operations - update keys later when " + "the first station connects"); + } + + /* + * Set initial GMK/Counter value here. The actual values that will be + * used in negotiations will be set once the first station tries to + * connect. This allows more time for collecting additional randomness + * on embedded devices. + */ + if (wpa_group_init_gmk_and_counter(wpa_auth, group) < 0) { + wpa_printf(MSG_ERROR, "Failed to get random data for WPA " + "initialization."); + os_free(group); + return NULL; + } + + group->GInit = TRUE; + if (delay_init) { + wpa_printf(MSG_DEBUG, "WPA: Delay group state machine start " + "until Beacon frames have been configured"); + /* Initialization is completed in wpa_init_keys(). */ + } else { + wpa_group_sm_step(wpa_auth, group); + group->GInit = FALSE; + wpa_group_sm_step(wpa_auth, group); + } + + return group; +} + + +/** + * wpa_init - Initialize WPA authenticator + * @addr: Authenticator address + * @conf: Configuration for WPA authenticator + * @cb: Callback functions for WPA authenticator + * Returns: Pointer to WPA authenticator data or %NULL on failure + */ +struct wpa_authenticator * wpa_init(const u8 *addr, + struct wpa_auth_config *conf, + struct wpa_auth_callbacks *cb) +{ + struct wpa_authenticator *wpa_auth; + + wpa_auth = os_zalloc(sizeof(struct wpa_authenticator)); + if (wpa_auth == NULL) + return NULL; + os_memcpy(wpa_auth->addr, addr, ETH_ALEN); + os_memcpy(&wpa_auth->conf, conf, sizeof(*conf)); + os_memcpy(&wpa_auth->cb, cb, sizeof(*cb)); + + if (wpa_auth_gen_wpa_ie(wpa_auth)) { + wpa_printf(MSG_ERROR, "Could not generate WPA IE."); + os_free(wpa_auth); + return NULL; + } + + wpa_auth->group = wpa_group_init(wpa_auth, 0, 1); + if (wpa_auth->group == NULL) { + os_free(wpa_auth->wpa_ie); + os_free(wpa_auth); + return NULL; + } + +#ifdef CONFIG_IEEE80211R + wpa_auth->ft_pmk_cache = wpa_ft_pmk_cache_init(); + if (wpa_auth->ft_pmk_cache == NULL) { + wpa_printf(MSG_ERROR, "FT PMK cache initialization failed."); + os_free(wpa_auth->group); + os_free(wpa_auth->wpa_ie); + pmksa_cache_auth_deinit(wpa_auth->pmksa); + os_free(wpa_auth); + return NULL; + } +#endif /* CONFIG_IEEE80211R */ + + if (wpa_auth->conf.wpa_gmk_rekey) { + eloop_register_timeout(wpa_auth->conf.wpa_gmk_rekey, 0, + wpa_rekey_gmk, wpa_auth, NULL); + } + + if (wpa_auth->conf.wpa_group_rekey) { + eloop_register_timeout(wpa_auth->conf.wpa_group_rekey, 0, + wpa_rekey_gtk, wpa_auth, NULL); + } + +#ifdef CONFIG_P2P + if (WPA_GET_BE32(conf->ip_addr_start)) { + int count = WPA_GET_BE32(conf->ip_addr_end) - + WPA_GET_BE32(conf->ip_addr_start) + 1; + if (count > 1000) + count = 1000; + if (count > 0) + wpa_auth->ip_pool = bitfield_alloc(count); + } +#endif /* CONFIG_P2P */ + + return wpa_auth; +} + + +int wpa_init_keys(struct wpa_authenticator *wpa_auth) +{ + struct wpa_group *group = wpa_auth->group; + + wpa_printf(MSG_DEBUG, "WPA: Start group state machine to set initial " + "keys"); + wpa_group_sm_step(wpa_auth, group); + group->GInit = FALSE; + wpa_group_sm_step(wpa_auth, group); + if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE) + return -1; + return 0; +} + + +/** + * wpa_deinit - Deinitialize WPA authenticator + * @wpa_auth: Pointer to WPA authenticator data from wpa_init() + */ +void wpa_deinit(struct wpa_authenticator *wpa_auth) +{ + struct wpa_group *group, *prev; + + eloop_cancel_timeout(wpa_rekey_gmk, wpa_auth, NULL); + eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL); + +#ifdef CONFIG_PEERKEY + while (wpa_auth->stsl_negotiations) + wpa_stsl_remove(wpa_auth, wpa_auth->stsl_negotiations); +#endif /* CONFIG_PEERKEY */ + +#ifdef CONFIG_IEEE80211R + wpa_ft_pmk_cache_deinit(wpa_auth->ft_pmk_cache); + wpa_auth->ft_pmk_cache = NULL; +#endif /* CONFIG_IEEE80211R */ + +#ifdef CONFIG_P2P + bitfield_free(wpa_auth->ip_pool); +#endif /* CONFIG_P2P */ + + + os_free(wpa_auth->wpa_ie); + + group = wpa_auth->group; + while (group) { + prev = group; + group = group->next; + os_free(prev); + } + + os_free(wpa_auth); +} + + +/** + * wpa_reconfig - Update WPA authenticator configuration + * @wpa_auth: Pointer to WPA authenticator data from wpa_init() + * @conf: Configuration for WPA authenticator + */ +int wpa_reconfig(struct wpa_authenticator *wpa_auth, + struct wpa_auth_config *conf) +{ + struct wpa_group *group; + if (wpa_auth == NULL) + return 0; + + os_memcpy(&wpa_auth->conf, conf, sizeof(*conf)); + if (wpa_auth_gen_wpa_ie(wpa_auth)) { + wpa_printf(MSG_ERROR, "Could not generate WPA IE."); + return -1; + } + + /* + * Reinitialize GTK to make sure it is suitable for the new + * configuration. + */ + group = wpa_auth->group; + group->GTK_len = wpa_cipher_key_len(wpa_auth->conf.wpa_group); + group->GInit = TRUE; + wpa_group_sm_step(wpa_auth, group); + group->GInit = FALSE; + wpa_group_sm_step(wpa_auth, group); + + return 0; +} + + +struct wpa_state_machine * +wpa_auth_sta_init(struct wpa_authenticator *wpa_auth, const u8 *addr, + const u8 *p2p_dev_addr) +{ + struct wpa_state_machine *sm; + + if (wpa_auth->group->wpa_group_state == WPA_GROUP_FATAL_FAILURE) + return NULL; + + sm = os_zalloc(sizeof(struct wpa_state_machine)); + if (sm == NULL) + return NULL; + os_memcpy(sm->addr, addr, ETH_ALEN); + if (p2p_dev_addr) + os_memcpy(sm->p2p_dev_addr, p2p_dev_addr, ETH_ALEN); + + sm->wpa_auth = wpa_auth; + sm->group = wpa_auth->group; + wpa_group_get(sm->wpa_auth, sm->group); + + return sm; +} + + +int wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth, + struct wpa_state_machine *sm) +{ + if (wpa_auth == NULL || !wpa_auth->conf.wpa || sm == NULL) + return -1; + +#ifdef CONFIG_IEEE80211R + if (sm->ft_completed) { + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, + "FT authentication already completed - do not " + "start 4-way handshake"); + /* Go to PTKINITDONE state to allow GTK rekeying */ + sm->wpa_ptk_state = WPA_PTK_PTKINITDONE; + return 0; + } +#endif /* CONFIG_IEEE80211R */ + + if (sm->started) { + os_memset(&sm->key_replay, 0, sizeof(sm->key_replay)); + sm->ReAuthenticationRequest = TRUE; + return wpa_sm_step(sm); + } + + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, + "start authentication"); + sm->started = 1; + + sm->Init = TRUE; + if (wpa_sm_step(sm) == 1) + return 1; /* should not really happen */ + sm->Init = FALSE; + sm->AuthenticationRequest = TRUE; + return wpa_sm_step(sm); +} + + +void wpa_auth_sta_no_wpa(struct wpa_state_machine *sm) +{ + /* WPA/RSN was not used - clear WPA state. This is needed if the STA + * reassociates back to the same AP while the previous entry for the + * STA has not yet been removed. */ + if (sm == NULL) + return; + + sm->wpa_key_mgmt = 0; +} + + +static void wpa_free_sta_sm(struct wpa_state_machine *sm) +{ +#ifdef CONFIG_P2P + if (WPA_GET_BE32(sm->ip_addr)) { + u32 start; + wpa_printf(MSG_DEBUG, "P2P: Free assigned IP " + "address %u.%u.%u.%u from " MACSTR, + sm->ip_addr[0], sm->ip_addr[1], + sm->ip_addr[2], sm->ip_addr[3], + MAC2STR(sm->addr)); + start = WPA_GET_BE32(sm->wpa_auth->conf.ip_addr_start); + bitfield_clear(sm->wpa_auth->ip_pool, + WPA_GET_BE32(sm->ip_addr) - start); + } +#endif /* CONFIG_P2P */ + if (sm->GUpdateStationKeys) { + sm->group->GKeyDoneStations--; + sm->GUpdateStationKeys = FALSE; + } +#ifdef CONFIG_IEEE80211R + os_free(sm->assoc_resp_ftie); + wpabuf_free(sm->ft_pending_req_ies); +#endif /* CONFIG_IEEE80211R */ + os_free(sm->last_rx_eapol_key); + os_free(sm->wpa_ie); + wpa_group_put(sm->wpa_auth, sm->group); + os_free(sm); +} + + +void wpa_auth_sta_deinit(struct wpa_state_machine *sm) +{ + if (sm == NULL) + return; + + if (sm->wpa_auth->conf.wpa_strict_rekey && sm->has_GTK) { + wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, + "strict rekeying - force GTK rekey since STA " + "is leaving"); + eloop_cancel_timeout(wpa_rekey_gtk, sm->wpa_auth, NULL); + eloop_register_timeout(0, 500000, wpa_rekey_gtk, sm->wpa_auth, + NULL); + } + + eloop_cancel_timeout(wpa_send_eapol_timeout, sm->wpa_auth, sm); + sm->pending_1_of_4_timeout = 0; + eloop_cancel_timeout(wpa_sm_call_step, sm, NULL); + eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm); + if (sm->in_step_loop) { + /* Must not free state machine while wpa_sm_step() is running. + * Freeing will be completed in the end of wpa_sm_step(). */ + wpa_printf(MSG_DEBUG, "WPA: Registering pending STA state " + "machine deinit for " MACSTR, MAC2STR(sm->addr)); + sm->pending_deinit = 1; + } else + wpa_free_sta_sm(sm); +} + + +static void wpa_request_new_ptk(struct wpa_state_machine *sm) +{ + if (sm == NULL) + return; + + sm->PTKRequest = TRUE; + sm->PTK_valid = FALSE; +} + + +static int wpa_replay_counter_valid(struct wpa_key_replay_counter *ctr, + const u8 *replay_counter) +{ + int i; + for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) { + if (!ctr[i].valid) + break; + if (os_memcmp(replay_counter, ctr[i].counter, + WPA_REPLAY_COUNTER_LEN) == 0) + return 1; + } + return 0; +} + + +static void wpa_replay_counter_mark_invalid(struct wpa_key_replay_counter *ctr, + const u8 *replay_counter) +{ + int i; + for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) { + if (ctr[i].valid && + (replay_counter == NULL || + os_memcmp(replay_counter, ctr[i].counter, + WPA_REPLAY_COUNTER_LEN) == 0)) + ctr[i].valid = FALSE; + } +} + + +#ifdef CONFIG_IEEE80211R +static int ft_check_msg_2_of_4(struct wpa_authenticator *wpa_auth, + struct wpa_state_machine *sm, + struct wpa_eapol_ie_parse *kde) +{ + struct wpa_ie_data ie; + struct rsn_mdie *mdie; + + if (wpa_parse_wpa_ie_rsn(kde->rsn_ie, kde->rsn_ie_len, &ie) < 0 || + ie.num_pmkid != 1 || ie.pmkid == NULL) { + wpa_printf(MSG_DEBUG, "FT: No PMKR1Name in " + "FT 4-way handshake message 2/4"); + return -1; + } + + os_memcpy(sm->sup_pmk_r1_name, ie.pmkid, PMKID_LEN); + wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name from Supplicant", + sm->sup_pmk_r1_name, PMKID_LEN); + + if (!kde->mdie || !kde->ftie) { + wpa_printf(MSG_DEBUG, "FT: No %s in FT 4-way handshake " + "message 2/4", kde->mdie ? "FTIE" : "MDIE"); + return -1; + } + + mdie = (struct rsn_mdie *) (kde->mdie + 2); + if (kde->mdie[1] < sizeof(struct rsn_mdie) || + os_memcmp(wpa_auth->conf.mobility_domain, mdie->mobility_domain, + MOBILITY_DOMAIN_ID_LEN) != 0) { + wpa_printf(MSG_DEBUG, "FT: MDIE mismatch"); + return -1; + } + + if (sm->assoc_resp_ftie && + (kde->ftie[1] != sm->assoc_resp_ftie[1] || + os_memcmp(kde->ftie, sm->assoc_resp_ftie, + 2 + sm->assoc_resp_ftie[1]) != 0)) { + wpa_printf(MSG_DEBUG, "FT: FTIE mismatch"); + wpa_hexdump(MSG_DEBUG, "FT: FTIE in EAPOL-Key msg 2/4", + kde->ftie, kde->ftie_len); + wpa_hexdump(MSG_DEBUG, "FT: FTIE in (Re)AssocResp", + sm->assoc_resp_ftie, 2 + sm->assoc_resp_ftie[1]); + return -1; + } + + return 0; +} +#endif /* CONFIG_IEEE80211R */ + + +static int wpa_receive_error_report(struct wpa_authenticator *wpa_auth, + struct wpa_state_machine *sm, int group) +{ + /* Supplicant reported a Michael MIC error */ + wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, + "received EAPOL-Key Error Request " + "(STA detected Michael MIC failure (group=%d))", + group); + + if (group && wpa_auth->conf.wpa_group != WPA_CIPHER_TKIP) { + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, + "ignore Michael MIC failure report since " + "group cipher is not TKIP"); + } else if (!group && sm->pairwise != WPA_CIPHER_TKIP) { + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, + "ignore Michael MIC failure report since " + "pairwise cipher is not TKIP"); + } else { + if (wpa_auth_mic_failure_report(wpa_auth, sm->addr) > 0) + return 1; /* STA entry was removed */ + sm->dot11RSNAStatsTKIPRemoteMICFailures++; + wpa_auth->dot11RSNAStatsTKIPRemoteMICFailures++; + } + + /* + * Error report is not a request for a new key handshake, but since + * Authenticator may do it, let's change the keys now anyway. + */ + wpa_request_new_ptk(sm); + return 0; +} + + +static int wpa_try_alt_snonce(struct wpa_state_machine *sm, u8 *data, + size_t data_len) +{ + struct wpa_ptk PTK; + int ok = 0; + const u8 *pmk = NULL; + + for (;;) { + if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) { + pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, + sm->p2p_dev_addr, pmk); + if (pmk == NULL) + break; + } else + pmk = sm->PMK; + + wpa_derive_ptk(sm, sm->alt_SNonce, pmk, &PTK); + + if (wpa_verify_key_mic(sm->wpa_key_mgmt, &PTK, data, data_len) + == 0) { + ok = 1; + break; + } + + if (!wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) + break; + } + + if (!ok) { + wpa_printf(MSG_DEBUG, + "WPA: Earlier SNonce did not result in matching MIC"); + return -1; + } + + wpa_printf(MSG_DEBUG, + "WPA: Earlier SNonce resulted in matching MIC"); + sm->alt_snonce_valid = 0; + os_memcpy(sm->SNonce, sm->alt_SNonce, WPA_NONCE_LEN); + os_memcpy(&sm->PTK, &PTK, sizeof(PTK)); + sm->PTK_valid = TRUE; + + return 0; +} + + +void wpa_receive(struct wpa_authenticator *wpa_auth, + struct wpa_state_machine *sm, + u8 *data, size_t data_len) +{ + struct ieee802_1x_hdr *hdr; + struct wpa_eapol_key *key; + struct wpa_eapol_key_192 *key192; + u16 key_info, key_data_length; + enum { PAIRWISE_2, PAIRWISE_4, GROUP_2, REQUEST, + SMK_M1, SMK_M3, SMK_ERROR } msg; + char *msgtxt; + struct wpa_eapol_ie_parse kde; + int ft; + const u8 *eapol_key_ie, *key_data; + size_t eapol_key_ie_len, keyhdrlen, mic_len; + + if (wpa_auth == NULL || !wpa_auth->conf.wpa || sm == NULL) + return; + + mic_len = wpa_mic_len(sm->wpa_key_mgmt); + keyhdrlen = mic_len == 24 ? sizeof(*key192) : sizeof(*key); + + if (data_len < sizeof(*hdr) + keyhdrlen) + return; + + hdr = (struct ieee802_1x_hdr *) data; + key = (struct wpa_eapol_key *) (hdr + 1); + key192 = (struct wpa_eapol_key_192 *) (hdr + 1); + key_info = WPA_GET_BE16(key->key_info); + if (mic_len == 24) { + key_data = (const u8 *) (key192 + 1); + key_data_length = WPA_GET_BE16(key192->key_data_length); + } else { + key_data = (const u8 *) (key + 1); + key_data_length = WPA_GET_BE16(key->key_data_length); + } + wpa_printf(MSG_DEBUG, "WPA: Received EAPOL-Key from " MACSTR + " key_info=0x%x type=%u key_data_length=%u", + MAC2STR(sm->addr), key_info, key->type, key_data_length); + if (key_data_length > data_len - sizeof(*hdr) - keyhdrlen) { + wpa_printf(MSG_INFO, "WPA: Invalid EAPOL-Key frame - " + "key_data overflow (%d > %lu)", + key_data_length, + (unsigned long) (data_len - sizeof(*hdr) - + keyhdrlen)); + return; + } + + if (sm->wpa == WPA_VERSION_WPA2) { + if (key->type == EAPOL_KEY_TYPE_WPA) { + /* + * Some deployed station implementations seem to send + * msg 4/4 with incorrect type value in WPA2 mode. + */ + wpa_printf(MSG_DEBUG, "Workaround: Allow EAPOL-Key " + "with unexpected WPA type in RSN mode"); + } else if (key->type != EAPOL_KEY_TYPE_RSN) { + wpa_printf(MSG_DEBUG, "Ignore EAPOL-Key with " + "unexpected type %d in RSN mode", + key->type); + return; + } + } else { + if (key->type != EAPOL_KEY_TYPE_WPA) { + wpa_printf(MSG_DEBUG, "Ignore EAPOL-Key with " + "unexpected type %d in WPA mode", + key->type); + return; + } + } + + wpa_hexdump(MSG_DEBUG, "WPA: Received Key Nonce", key->key_nonce, + WPA_NONCE_LEN); + wpa_hexdump(MSG_DEBUG, "WPA: Received Replay Counter", + key->replay_counter, WPA_REPLAY_COUNTER_LEN); + + /* FIX: verify that the EAPOL-Key frame was encrypted if pairwise keys + * are set */ + + if ((key_info & (WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_REQUEST)) == + (WPA_KEY_INFO_SMK_MESSAGE | WPA_KEY_INFO_REQUEST)) { + if (key_info & WPA_KEY_INFO_ERROR) { + msg = SMK_ERROR; + msgtxt = "SMK Error"; + } else { + msg = SMK_M1; + msgtxt = "SMK M1"; + } + } else if (key_info & WPA_KEY_INFO_SMK_MESSAGE) { + msg = SMK_M3; + msgtxt = "SMK M3"; + } else if (key_info & WPA_KEY_INFO_REQUEST) { + msg = REQUEST; + msgtxt = "Request"; + } else if (!(key_info & WPA_KEY_INFO_KEY_TYPE)) { + msg = GROUP_2; + msgtxt = "2/2 Group"; + } else if (key_data_length == 0) { + msg = PAIRWISE_4; + msgtxt = "4/4 Pairwise"; + } else { + msg = PAIRWISE_2; + msgtxt = "2/4 Pairwise"; + } + + /* TODO: key_info type validation for PeerKey */ + if (msg == REQUEST || msg == PAIRWISE_2 || msg == PAIRWISE_4 || + msg == GROUP_2) { + u16 ver = key_info & WPA_KEY_INFO_TYPE_MASK; + if (sm->pairwise == WPA_CIPHER_CCMP || + sm->pairwise == WPA_CIPHER_GCMP) { + if (wpa_use_aes_cmac(sm) && + sm->wpa_key_mgmt != WPA_KEY_MGMT_OSEN && + !wpa_key_mgmt_suite_b(sm->wpa_key_mgmt) && + ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) { + wpa_auth_logger(wpa_auth, sm->addr, + LOGGER_WARNING, + "advertised support for " + "AES-128-CMAC, but did not " + "use it"); + return; + } + + if (!wpa_use_aes_cmac(sm) && + ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { + wpa_auth_logger(wpa_auth, sm->addr, + LOGGER_WARNING, + "did not use HMAC-SHA1-AES " + "with CCMP/GCMP"); + return; + } + } + + if (wpa_key_mgmt_suite_b(sm->wpa_key_mgmt) && + ver != WPA_KEY_INFO_TYPE_AKM_DEFINED) { + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_WARNING, + "did not use EAPOL-Key descriptor version 0 as required for AKM-defined cases"); + return; + } + } + + if (key_info & WPA_KEY_INFO_REQUEST) { + if (sm->req_replay_counter_used && + os_memcmp(key->replay_counter, sm->req_replay_counter, + WPA_REPLAY_COUNTER_LEN) <= 0) { + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_WARNING, + "received EAPOL-Key request with " + "replayed counter"); + return; + } + } + + if (!(key_info & WPA_KEY_INFO_REQUEST) && + !wpa_replay_counter_valid(sm->key_replay, key->replay_counter)) { + int i; + + if (msg == PAIRWISE_2 && + wpa_replay_counter_valid(sm->prev_key_replay, + key->replay_counter) && + sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING && + os_memcmp(sm->SNonce, key->key_nonce, WPA_NONCE_LEN) != 0) + { + /* + * Some supplicant implementations (e.g., Windows XP + * WZC) update SNonce for each EAPOL-Key 2/4. This + * breaks the workaround on accepting any of the + * pending requests, so allow the SNonce to be updated + * even if we have already sent out EAPOL-Key 3/4. + */ + wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, + "Process SNonce update from STA " + "based on retransmitted EAPOL-Key " + "1/4"); + sm->update_snonce = 1; + os_memcpy(sm->alt_SNonce, sm->SNonce, WPA_NONCE_LEN); + sm->alt_snonce_valid = TRUE; + os_memcpy(sm->alt_replay_counter, + sm->key_replay[0].counter, + WPA_REPLAY_COUNTER_LEN); + goto continue_processing; + } + + if (msg == PAIRWISE_4 && sm->alt_snonce_valid && + sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING && + os_memcmp(key->replay_counter, sm->alt_replay_counter, + WPA_REPLAY_COUNTER_LEN) == 0) { + /* + * Supplicant may still be using the old SNonce since + * there was two EAPOL-Key 2/4 messages and they had + * different SNonce values. + */ + wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, + "Try to process received EAPOL-Key 4/4 based on old Replay Counter and SNonce from an earlier EAPOL-Key 1/4"); + goto continue_processing; + } + + if (msg == PAIRWISE_2 && + wpa_replay_counter_valid(sm->prev_key_replay, + key->replay_counter) && + sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING) { + wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, + "ignore retransmitted EAPOL-Key %s - " + "SNonce did not change", msgtxt); + } else { + wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, + "received EAPOL-Key %s with " + "unexpected replay counter", msgtxt); + } + for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) { + if (!sm->key_replay[i].valid) + break; + wpa_hexdump(MSG_DEBUG, "pending replay counter", + sm->key_replay[i].counter, + WPA_REPLAY_COUNTER_LEN); + } + wpa_hexdump(MSG_DEBUG, "received replay counter", + key->replay_counter, WPA_REPLAY_COUNTER_LEN); + return; + } + +continue_processing: + switch (msg) { + case PAIRWISE_2: + if (sm->wpa_ptk_state != WPA_PTK_PTKSTART && + sm->wpa_ptk_state != WPA_PTK_PTKCALCNEGOTIATING && + (!sm->update_snonce || + sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING)) { + wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, + "received EAPOL-Key msg 2/4 in " + "invalid state (%d) - dropped", + sm->wpa_ptk_state); + return; + } + random_add_randomness(key->key_nonce, WPA_NONCE_LEN); + if (sm->group->reject_4way_hs_for_entropy) { + /* + * The system did not have enough entropy to generate + * strong random numbers. Reject the first 4-way + * handshake(s) and collect some entropy based on the + * information from it. Once enough entropy is + * available, the next atempt will trigger GMK/Key + * Counter update and the station will be allowed to + * continue. + */ + wpa_printf(MSG_DEBUG, "WPA: Reject 4-way handshake to " + "collect more entropy for random number " + "generation"); + random_mark_pool_ready(); + wpa_sta_disconnect(wpa_auth, sm->addr); + return; + } + if (wpa_parse_kde_ies(key_data, key_data_length, &kde) < 0) { + wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, + "received EAPOL-Key msg 2/4 with " + "invalid Key Data contents"); + return; + } + if (kde.rsn_ie) { + eapol_key_ie = kde.rsn_ie; + eapol_key_ie_len = kde.rsn_ie_len; + } else { + eapol_key_ie = kde.wpa_ie; + eapol_key_ie_len = kde.wpa_ie_len; + } + ft = sm->wpa == WPA_VERSION_WPA2 && + wpa_key_mgmt_ft(sm->wpa_key_mgmt); + if (sm->wpa_ie == NULL || + wpa_compare_rsn_ie(ft, + sm->wpa_ie, sm->wpa_ie_len, + eapol_key_ie, eapol_key_ie_len)) { + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, + "WPA IE from (Re)AssocReq did not " + "match with msg 2/4"); + if (sm->wpa_ie) { + wpa_hexdump(MSG_DEBUG, "WPA IE in AssocReq", + sm->wpa_ie, sm->wpa_ie_len); + } + wpa_hexdump(MSG_DEBUG, "WPA IE in msg 2/4", + eapol_key_ie, eapol_key_ie_len); + /* MLME-DEAUTHENTICATE.request */ + wpa_sta_disconnect(wpa_auth, sm->addr); + return; + } +#ifdef CONFIG_IEEE80211R + if (ft && ft_check_msg_2_of_4(wpa_auth, sm, &kde) < 0) { + wpa_sta_disconnect(wpa_auth, sm->addr); + return; + } +#endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_P2P + if (kde.ip_addr_req && kde.ip_addr_req[0] && + wpa_auth->ip_pool && WPA_GET_BE32(sm->ip_addr) == 0) { + int idx; + wpa_printf(MSG_DEBUG, "P2P: IP address requested in " + "EAPOL-Key exchange"); + idx = bitfield_get_first_zero(wpa_auth->ip_pool); + if (idx >= 0) { + u32 start = WPA_GET_BE32(wpa_auth->conf. + ip_addr_start); + bitfield_set(wpa_auth->ip_pool, idx); + WPA_PUT_BE32(sm->ip_addr, start + idx); + wpa_printf(MSG_DEBUG, "P2P: Assigned IP " + "address %u.%u.%u.%u to " MACSTR, + sm->ip_addr[0], sm->ip_addr[1], + sm->ip_addr[2], sm->ip_addr[3], + MAC2STR(sm->addr)); + } + } +#endif /* CONFIG_P2P */ + break; + case PAIRWISE_4: + if (sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING || + !sm->PTK_valid) { + wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, + "received EAPOL-Key msg 4/4 in " + "invalid state (%d) - dropped", + sm->wpa_ptk_state); + return; + } + break; + case GROUP_2: + if (sm->wpa_ptk_group_state != WPA_PTK_GROUP_REKEYNEGOTIATING + || !sm->PTK_valid) { + wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, + "received EAPOL-Key msg 2/2 in " + "invalid state (%d) - dropped", + sm->wpa_ptk_group_state); + return; + } + break; +#ifdef CONFIG_PEERKEY + case SMK_M1: + case SMK_M3: + case SMK_ERROR: + if (!wpa_auth->conf.peerkey) { + wpa_printf(MSG_DEBUG, "RSN: SMK M1/M3/Error, but " + "PeerKey use disabled - ignoring message"); + return; + } + if (!sm->PTK_valid) { + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, + "received EAPOL-Key msg SMK in " + "invalid state - dropped"); + return; + } + break; +#else /* CONFIG_PEERKEY */ + case SMK_M1: + case SMK_M3: + case SMK_ERROR: + return; /* STSL disabled - ignore SMK messages */ +#endif /* CONFIG_PEERKEY */ + case REQUEST: + break; + } + + wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, + "received EAPOL-Key frame (%s)", msgtxt); + + if (key_info & WPA_KEY_INFO_ACK) { + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, + "received invalid EAPOL-Key: Key Ack set"); + return; + } + + if (!(key_info & WPA_KEY_INFO_MIC)) { + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, + "received invalid EAPOL-Key: Key MIC not set"); + return; + } + + sm->MICVerified = FALSE; + if (sm->PTK_valid && !sm->update_snonce) { + if (wpa_verify_key_mic(sm->wpa_key_mgmt, &sm->PTK, data, + data_len) && + (msg != PAIRWISE_4 || !sm->alt_snonce_valid || + wpa_try_alt_snonce(sm, data, data_len))) { + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, + "received EAPOL-Key with invalid MIC"); + return; + } + sm->MICVerified = TRUE; + eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm); + sm->pending_1_of_4_timeout = 0; + } + + if (key_info & WPA_KEY_INFO_REQUEST) { + if (sm->MICVerified) { + sm->req_replay_counter_used = 1; + os_memcpy(sm->req_replay_counter, key->replay_counter, + WPA_REPLAY_COUNTER_LEN); + } else { + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, + "received EAPOL-Key request with " + "invalid MIC"); + return; + } + + /* + * TODO: should decrypt key data field if encryption was used; + * even though MAC address KDE is not normally encrypted, + * supplicant is allowed to encrypt it. + */ + if (msg == SMK_ERROR) { +#ifdef CONFIG_PEERKEY + wpa_smk_error(wpa_auth, sm, key_data, key_data_length); +#endif /* CONFIG_PEERKEY */ + return; + } else if (key_info & WPA_KEY_INFO_ERROR) { + if (wpa_receive_error_report( + wpa_auth, sm, + !(key_info & WPA_KEY_INFO_KEY_TYPE)) > 0) + return; /* STA entry was removed */ + } else if (key_info & WPA_KEY_INFO_KEY_TYPE) { + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, + "received EAPOL-Key Request for new " + "4-Way Handshake"); + wpa_request_new_ptk(sm); +#ifdef CONFIG_PEERKEY + } else if (msg == SMK_M1) { + wpa_smk_m1(wpa_auth, sm, key, key_data, + key_data_length); +#endif /* CONFIG_PEERKEY */ + } else if (key_data_length > 0 && + wpa_parse_kde_ies(key_data, key_data_length, + &kde) == 0 && + kde.mac_addr) { + } else { + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, + "received EAPOL-Key Request for GTK " + "rekeying"); + eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL); + wpa_rekey_gtk(wpa_auth, NULL); + } + } else { + /* Do not allow the same key replay counter to be reused. */ + wpa_replay_counter_mark_invalid(sm->key_replay, + key->replay_counter); + + if (msg == PAIRWISE_2) { + /* + * Maintain a copy of the pending EAPOL-Key frames in + * case the EAPOL-Key frame was retransmitted. This is + * needed to allow EAPOL-Key msg 2/4 reply to another + * pending msg 1/4 to update the SNonce to work around + * unexpected supplicant behavior. + */ + os_memcpy(sm->prev_key_replay, sm->key_replay, + sizeof(sm->key_replay)); + } else { + os_memset(sm->prev_key_replay, 0, + sizeof(sm->prev_key_replay)); + } + + /* + * Make sure old valid counters are not accepted anymore and + * do not get copied again. + */ + wpa_replay_counter_mark_invalid(sm->key_replay, NULL); + } + +#ifdef CONFIG_PEERKEY + if (msg == SMK_M3) { + wpa_smk_m3(wpa_auth, sm, key, key_data, key_data_length); + return; + } +#endif /* CONFIG_PEERKEY */ + + os_free(sm->last_rx_eapol_key); + sm->last_rx_eapol_key = os_malloc(data_len); + if (sm->last_rx_eapol_key == NULL) + return; + os_memcpy(sm->last_rx_eapol_key, data, data_len); + sm->last_rx_eapol_key_len = data_len; + + sm->rx_eapol_key_secure = !!(key_info & WPA_KEY_INFO_SECURE); + sm->EAPOLKeyReceived = TRUE; + sm->EAPOLKeyPairwise = (Boolean)!!(key_info & WPA_KEY_INFO_KEY_TYPE); + sm->EAPOLKeyRequest = (Boolean)!!(key_info & WPA_KEY_INFO_REQUEST); + + os_memcpy(sm->SNonce, key->key_nonce, WPA_NONCE_LEN); + wpa_sm_step(sm); + + #if 0 == CFG_ENABLE_WPA_LOG + (void)msgtxt; + #endif +} + +static int wpa_gmk_to_gtk(const u8 *gmk, const char *label, const u8 *addr, + const u8 *gnonce, u8 *gtk, size_t gtk_len) +{ + u8 data[ETH_ALEN + WPA_NONCE_LEN + 8 + 16]; + u8 *pos; + int ret = 0; + + /* GTK = PRF-X(GMK, "Group key expansion", + * AA || GNonce || Time || random data) + * The example described in the IEEE 802.11 standard uses only AA and + * GNonce as inputs here. Add some more entropy since this derivation + * is done only at the Authenticator and as such, does not need to be + * exactly same. + */ + os_memcpy(data, addr, ETH_ALEN); + os_memcpy(data + ETH_ALEN, gnonce, WPA_NONCE_LEN); + pos = data + ETH_ALEN + WPA_NONCE_LEN; + wpa_get_ntp_timestamp(pos); + pos += 8; + if (random_get_bytes(pos, 16) < 0) + ret = -1; + +#ifdef CONFIG_IEEE80211W + sha256_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data), gtk, gtk_len); +#else /* CONFIG_IEEE80211W */ + if (sha1_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data), gtk, gtk_len) + < 0) + ret = -1; +#endif /* CONFIG_IEEE80211W */ + + return ret; +} + + +static void wpa_send_eapol_timeout(void *eloop_ctx, void *timeout_ctx) +{ + struct wpa_authenticator *wpa_auth = eloop_ctx; + struct wpa_state_machine *sm = timeout_ctx; + + sm->pending_1_of_4_timeout = 0; + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "EAPOL-Key timeout"); + sm->TimeoutEvt = TRUE; + wpa_sm_step(sm); + (void)wpa_auth; +} + + +void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, + struct wpa_state_machine *sm, int key_info, + const u8 *key_rsc, const u8 *nonce, + const u8 *kde, size_t kde_len, + int keyidx, int encr, int force_version) +{ + struct ieee802_1x_hdr *hdr; + struct wpa_eapol_key *key; + struct wpa_eapol_key_192 *key192; + size_t len, mic_len, keyhdrlen; + int alg; + int key_data_len, pad_len = 0; + u8 *buf, *pos; + int version, pairwise; + int i; + u8 *key_data; + + mic_len = wpa_mic_len(sm->wpa_key_mgmt); + keyhdrlen = mic_len == 24 ? sizeof(*key192) : sizeof(*key); + + len = sizeof(struct ieee802_1x_hdr) + keyhdrlen; + + if (force_version) + version = force_version; + else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN || + wpa_key_mgmt_suite_b(sm->wpa_key_mgmt)) + version = WPA_KEY_INFO_TYPE_AKM_DEFINED; + else if (wpa_use_aes_cmac(sm)) + version = WPA_KEY_INFO_TYPE_AES_128_CMAC; + else if (sm->pairwise != WPA_CIPHER_TKIP) + version = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES; + else + version = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4; + + pairwise = !!(key_info & WPA_KEY_INFO_KEY_TYPE); + + wpa_printf(MSG_DEBUG, "WPA: Send EAPOL(version=%d secure=%d mic=%d " + "ack=%d install=%d pairwise=%d kde_len=%lu keyidx=%d " + "encr=%d)\r\n", + version, + (key_info & WPA_KEY_INFO_SECURE) ? 1 : 0, + (key_info & WPA_KEY_INFO_MIC) ? 1 : 0, + (key_info & WPA_KEY_INFO_ACK) ? 1 : 0, + (key_info & WPA_KEY_INFO_INSTALL) ? 1 : 0, + pairwise, (unsigned long) kde_len, keyidx, encr); + + key_data_len = kde_len; + + if ((version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES || + sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN || + wpa_key_mgmt_suite_b(sm->wpa_key_mgmt) || + version == WPA_KEY_INFO_TYPE_AES_128_CMAC) && encr) { + pad_len = key_data_len % 8; + if (pad_len) + pad_len = 8 - pad_len; + key_data_len += pad_len + 8; + } + + len += key_data_len; + + hdr = os_zalloc(len); + if (hdr == NULL) + return; + hdr->version = wpa_auth->conf.eapol_version; + hdr->type = IEEE802_1X_TYPE_EAPOL_KEY; + hdr->length = host_to_be16(len - sizeof(*hdr)); + key = (struct wpa_eapol_key *) (hdr + 1); + key192 = (struct wpa_eapol_key_192 *) (hdr + 1); + key_data = ((u8 *) (hdr + 1)) + keyhdrlen; + + key->type = sm->wpa == WPA_VERSION_WPA2 ? + EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA; + key_info |= version; + if (encr && sm->wpa == WPA_VERSION_WPA2) + key_info |= WPA_KEY_INFO_ENCR_KEY_DATA; + if (sm->wpa != WPA_VERSION_WPA2) + key_info |= keyidx << WPA_KEY_INFO_KEY_INDEX_SHIFT; + WPA_PUT_BE16(key->key_info, key_info); + + alg = pairwise ? sm->pairwise : wpa_auth->conf.wpa_group; + WPA_PUT_BE16(key->key_length, wpa_cipher_key_len(alg)); + if (key_info & WPA_KEY_INFO_SMK_MESSAGE) + WPA_PUT_BE16(key->key_length, 0); + + /* FIX: STSL: what to use as key_replay_counter? */ + for (i = RSNA_MAX_EAPOL_RETRIES - 1; i > 0; i--) { + sm->key_replay[i].valid = sm->key_replay[i - 1].valid; + os_memcpy(sm->key_replay[i].counter, + sm->key_replay[i - 1].counter, + WPA_REPLAY_COUNTER_LEN); + } + inc_byte_array(sm->key_replay[0].counter, WPA_REPLAY_COUNTER_LEN); + os_memcpy(key->replay_counter, sm->key_replay[0].counter, + WPA_REPLAY_COUNTER_LEN); + wpa_hexdump(MSG_DEBUG, "WPA: Replay Counter", + key->replay_counter, WPA_REPLAY_COUNTER_LEN); + sm->key_replay[0].valid = TRUE; + + if (nonce) + os_memcpy(key->key_nonce, nonce, WPA_NONCE_LEN); + + if (key_rsc) + os_memcpy(key->key_rsc, key_rsc, WPA_KEY_RSC_LEN); + + if (kde && !encr) { + os_memcpy(key_data, kde, kde_len); + if (mic_len == 24) + WPA_PUT_BE16(key192->key_data_length, kde_len); + else + WPA_PUT_BE16(key->key_data_length, kde_len); + } else if (encr && kde) { + buf = os_zalloc(key_data_len); + if (buf == NULL) { + os_free(hdr); + return; + } + pos = buf; + os_memcpy(pos, kde, kde_len); + pos += kde_len; + + if (pad_len) + *pos++ = 0xdd; + + wpa_hexdump_key(MSG_DEBUG, "Plaintext EAPOL-Key Key Data", + buf, key_data_len); + if (version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES || + sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN || + wpa_key_mgmt_suite_b(sm->wpa_key_mgmt) || + version == WPA_KEY_INFO_TYPE_AES_128_CMAC) { + if (aes_wrap(sm->PTK.kek, sm->PTK.kek_len, + (key_data_len - 8) / 8, buf, key_data)) { + os_free(hdr); + os_free(buf); + return; + } + if (mic_len == 24) + WPA_PUT_BE16(key192->key_data_length, + key_data_len); + else + WPA_PUT_BE16(key->key_data_length, + key_data_len); +#ifndef CONFIG_NO_RC4 + } else if (sm->PTK.kek_len == 16) { + u8 ek[32]; + os_memcpy(key->key_iv, + sm->group->Counter + WPA_NONCE_LEN - 16, 16); + inc_byte_array(sm->group->Counter, WPA_NONCE_LEN); + os_memcpy(ek, key->key_iv, 16); + os_memcpy(ek + 16, sm->PTK.kek, sm->PTK.kek_len); + os_memcpy(key_data, buf, key_data_len); + rc4_skip(ek, 32, 256, key_data, key_data_len); + if (mic_len == 24) + WPA_PUT_BE16(key192->key_data_length, + key_data_len); + else + WPA_PUT_BE16(key->key_data_length, + key_data_len); +#endif /* CONFIG_NO_RC4 */ + } else { + os_free(hdr); + os_free(buf); + return; + } + os_free(buf); + } + + if (key_info & WPA_KEY_INFO_MIC) { + u8 *key_mic; + + if (!sm->PTK_valid) { + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, + "PTK not valid when sending EAPOL-Key " + "frame"); + os_free(hdr); + return; + } + + key_mic = key192->key_mic; /* same offset for key and key192 */ + wpa_eapol_key_mic(sm->PTK.kck, sm->PTK.kck_len, + sm->wpa_key_mgmt, version, + (u8 *) hdr, len, key_mic); + } + + wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_inc_EapolFramesTx, + 1); + wpa_auth_send_eapol(wpa_auth, sm->addr, (u8 *) hdr, len, + sm->pairwise_set); + os_free(hdr); +} + + +static void wpa_send_eapol(struct wpa_authenticator *wpa_auth, + struct wpa_state_machine *sm, int key_info, + const u8 *key_rsc, const u8 *nonce, + const u8 *kde, size_t kde_len, + int keyidx, int encr) +{ + int timeout_ms; + int pairwise = key_info & WPA_KEY_INFO_KEY_TYPE; + int ctr; + + if (sm == NULL) + return; + + __wpa_send_eapol(wpa_auth, sm, key_info, key_rsc, nonce, kde, kde_len, + keyidx, encr, 0); + + ctr = pairwise ? sm->TimeoutCtr : sm->GTimeoutCtr; + if (ctr == 1 && wpa_auth->conf.tx_status) + timeout_ms = pairwise ? eapol_key_timeout_first : + eapol_key_timeout_first_group; + else + timeout_ms = eapol_key_timeout_subseq; + if (pairwise && ctr == 1 && !(key_info & WPA_KEY_INFO_MIC)) + sm->pending_1_of_4_timeout = 1; + wpa_printf(MSG_DEBUG, "WPA: Use EAPOL-Key timeout of %u ms (retry " + "counter %d)", timeout_ms, ctr); + eloop_register_timeout(timeout_ms / 1000, (timeout_ms % 1000) * 1000, + wpa_send_eapol_timeout, wpa_auth, sm); +} + + +static int wpa_verify_key_mic(int akmp, struct wpa_ptk *PTK, u8 *data, + size_t data_len) +{ + struct ieee802_1x_hdr *hdr; + struct wpa_eapol_key *key; + struct wpa_eapol_key_192 *key192; + u16 key_info; + int ret = 0; + u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN]; + size_t mic_len = wpa_mic_len(akmp); + + if (data_len < sizeof(*hdr) + sizeof(*key)) + return -1; + + hdr = (struct ieee802_1x_hdr *) data; + key = (struct wpa_eapol_key *) (hdr + 1); + key192 = (struct wpa_eapol_key_192 *) (hdr + 1); + key_info = WPA_GET_BE16(key->key_info); + os_memcpy(mic, key192->key_mic, mic_len); + os_memset(key192->key_mic, 0, mic_len); + if (wpa_eapol_key_mic(PTK->kck, PTK->kck_len, akmp, + key_info & WPA_KEY_INFO_TYPE_MASK, + data, data_len, key192->key_mic) || + os_memcmp_const(mic, key192->key_mic, mic_len) != 0) + ret = -1; + os_memcpy(key192->key_mic, mic, mic_len); + return ret; +} + + +void wpa_remove_ptk(struct wpa_state_machine *sm) +{ + sm->PTK_valid = FALSE; + os_memset(&sm->PTK, 0, sizeof(sm->PTK)); + wpa_auth_set_key(sm->wpa_auth, 0, WPA_ALG_NONE, sm->addr, 0, NULL, 0); + sm->pairwise_set = FALSE; + eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm); +} + + +int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event) +{ + int remove_ptk = 1; + + if (sm == NULL) + return -1; + + wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, + "event %d notification", event); + + switch (event) { + case WPA_AUTH: +#ifdef CONFIG_MESH + /* PTKs are derived through AMPE */ + if (wpa_auth_start_ampe(sm->wpa_auth, sm->addr)) { + /* not mesh */ + break; + } + return 0; +#endif /* CONFIG_MESH */ + case WPA_ASSOC: + break; + case WPA_DEAUTH: + case WPA_DISASSOC: + sm->DeauthenticationRequest = TRUE; + break; + case WPA_REAUTH: + case WPA_REAUTH_EAPOL: + if (!sm->started) { + /* + * When using WPS, we may end up here if the STA + * manages to re-associate without the previous STA + * entry getting removed. Consequently, we need to make + * sure that the WPA state machines gets initialized + * properly at this point. + */ + wpa_printf(MSG_DEBUG, "WPA state machine had not been " + "started - initialize now"); + sm->started = 1; + sm->Init = TRUE; + if (wpa_sm_step(sm) == 1) + return 1; /* should not really happen */ + sm->Init = FALSE; + sm->AuthenticationRequest = TRUE; + break; + } + if (sm->GUpdateStationKeys) { + /* + * Reauthentication cancels the pending group key + * update for this STA. + */ + sm->group->GKeyDoneStations--; + sm->GUpdateStationKeys = FALSE; + sm->PtkGroupInit = TRUE; + } + sm->ReAuthenticationRequest = TRUE; + break; + case WPA_ASSOC_FT: +#ifdef CONFIG_IEEE80211R + wpa_printf(MSG_DEBUG, "FT: Retry PTK configuration " + "after association"); + wpa_ft_install_ptk(sm); + + /* Using FT protocol, not WPA auth state machine */ + sm->ft_completed = 1; + return 0; +#else /* CONFIG_IEEE80211R */ + break; +#endif /* CONFIG_IEEE80211R */ + case WPA_DRV_STA_REMOVED: + sm->tk_already_set = FALSE; + return 0; + } + +#ifdef CONFIG_IEEE80211R + sm->ft_completed = 0; +#endif /* CONFIG_IEEE80211R */ + +#ifdef CONFIG_IEEE80211W + if (sm->mgmt_frame_prot && event == WPA_AUTH) + remove_ptk = 0; +#endif /* CONFIG_IEEE80211W */ + + if (remove_ptk) { + sm->PTK_valid = FALSE; + os_memset(&sm->PTK, 0, sizeof(sm->PTK)); + + if (event != WPA_REAUTH_EAPOL) + wpa_remove_ptk(sm); + } + + if (sm->in_step_loop) { + /* + * wpa_sm_step() is already running - avoid recursive call to + * it by making the existing loop process the new update. + */ + sm->changed = TRUE; + return 0; + } + return wpa_sm_step(sm); +} + + +SM_STATE(WPA_PTK, INITIALIZE) +{ + SM_ENTRY_MA(WPA_PTK, INITIALIZE, wpa_ptk); + if (sm->Init) { + /* Init flag is not cleared here, so avoid busy + * loop by claiming nothing changed. */ + sm->changed = FALSE; + } + + sm->keycount = 0; + if (sm->GUpdateStationKeys) + sm->group->GKeyDoneStations--; + sm->GUpdateStationKeys = FALSE; + if (sm->wpa == WPA_VERSION_WPA) + sm->PInitAKeys = FALSE; + if (1 /* Unicast cipher supported AND (ESS OR ((IBSS or WDS) and + * Local AA > Remote AA)) */) { + sm->Pair = TRUE; + } + wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portEnabled, 0); + wpa_remove_ptk(sm); + wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portValid, 0); + sm->TimeoutCtr = 0; + if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) { + wpa_auth_set_eapol(sm->wpa_auth, sm->addr, + WPA_EAPOL_authorized, 0); + } +} + + +SM_STATE(WPA_PTK, DISCONNECT) +{ + SM_ENTRY_MA(WPA_PTK, DISCONNECT, wpa_ptk); + sm->Disconnect = FALSE; + wpa_sta_disconnect(sm->wpa_auth, sm->addr); +} + + +SM_STATE(WPA_PTK, DISCONNECTED) +{ + SM_ENTRY_MA(WPA_PTK, DISCONNECTED, wpa_ptk); + sm->DeauthenticationRequest = FALSE; +} + + +SM_STATE(WPA_PTK, AUTHENTICATION) +{ + SM_ENTRY_MA(WPA_PTK, AUTHENTICATION, wpa_ptk); + os_memset(&sm->PTK, 0, sizeof(sm->PTK)); + sm->PTK_valid = FALSE; + wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portControl_Auto, + 1); + wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portEnabled, 1); + sm->AuthenticationRequest = FALSE; +} + + +static void wpa_group_ensure_init(struct wpa_authenticator *wpa_auth, + struct wpa_group *group) +{ + if (group->first_sta_seen) + return; + /* + * System has run bit further than at the time hostapd was started + * potentially very early during boot up. This provides better chances + * of collecting more randomness on embedded systems. Re-initialize the + * GMK and Counter here to improve their strength if there was not + * enough entropy available immediately after system startup. + */ + wpa_printf(MSG_DEBUG, "WPA: Re-initialize GMK/Counter on first " + "station"); + if (random_pool_ready() != 1) { + wpa_printf(MSG_INFO, "WPA: Not enough entropy in random pool " + "to proceed - reject first 4-way handshake"); + group->reject_4way_hs_for_entropy = TRUE; + } else { + group->first_sta_seen = TRUE; + group->reject_4way_hs_for_entropy = FALSE; + } + + if (wpa_group_init_gmk_and_counter(wpa_auth, group) < 0 || + wpa_gtk_update(wpa_auth, group) < 0 || + wpa_group_config_group_keys(wpa_auth, group) < 0) { + wpa_printf(MSG_INFO, "WPA: GMK/GTK setup failed"); + group->first_sta_seen = FALSE; + group->reject_4way_hs_for_entropy = TRUE; + } +} + + +SM_STATE(WPA_PTK, AUTHENTICATION2) +{ + SM_ENTRY_MA(WPA_PTK, AUTHENTICATION2, wpa_ptk); + + wpa_group_ensure_init(sm->wpa_auth, sm->group); + sm->ReAuthenticationRequest = FALSE; + + /* + * Definition of ANonce selection in IEEE Std 802.11i-2004 is somewhat + * ambiguous. The Authenticator state machine uses a counter that is + * incremented by one for each 4-way handshake. However, the security + * analysis of 4-way handshake points out that unpredictable nonces + * help in preventing precomputation attacks. Instead of the state + * machine definition, use an unpredictable nonce value here to provide + * stronger protection against potential precomputation attacks. + */ + if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) { + wpa_printf(MSG_ERROR, "WPA: Failed to get random data for " + "ANonce."); + sm->Disconnect = TRUE; + return; + } + wpa_hexdump(MSG_DEBUG, "WPA: Assign ANonce", sm->ANonce, + WPA_NONCE_LEN); + /* IEEE 802.11i does not clear TimeoutCtr here, but this is more + * logical place than INITIALIZE since AUTHENTICATION2 can be + * re-entered on ReAuthenticationRequest without going through + * INITIALIZE. */ + sm->TimeoutCtr = 0; +} + +static int wpa_auth_sm_ptk_update(struct wpa_state_machine *sm) +{ + if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) { + wpa_printf(MSG_ERROR, + "WPA: Failed to get random data for ANonce"); + sm->Disconnect = TRUE; + return -1; + } + wpa_hexdump(MSG_DEBUG, "WPA: Assign new ANonce", sm->ANonce, + WPA_NONCE_LEN); + sm->TimeoutCtr = 0; + return 0; +} + +SM_STATE(WPA_PTK, INITPMK) +{ + u8 msk[2 * PMK_LEN]; + size_t len = 2 * PMK_LEN; + + SM_ENTRY_MA(WPA_PTK, INITPMK, wpa_ptk); +#ifdef CONFIG_IEEE80211R + sm->xxkey_len = 0; +#endif /* CONFIG_IEEE80211R */ + if (wpa_auth_get_msk(sm->wpa_auth, sm->addr, msk, &len) == 0) { + wpa_printf(MSG_DEBUG, "WPA: PMK from EAPOL state machine " + "(len=%lu)", (unsigned long) len); + os_memcpy(sm->PMK, msk, PMK_LEN); +#ifdef CONFIG_IEEE80211R + if (len >= 2 * PMK_LEN) { + os_memcpy(sm->xxkey, msk + PMK_LEN, PMK_LEN); + sm->xxkey_len = PMK_LEN; + } +#endif /* CONFIG_IEEE80211R */ + } else { + wpa_printf(MSG_DEBUG, "WPA: Could not get PMK, get_msk: %p", + sm->wpa_auth->cb.get_msk); + sm->Disconnect = TRUE; + return; + } + os_memset(msk, 0, sizeof(msk)); + + sm->req_replay_counter_used = 0; + /* IEEE 802.11i does not set keyRun to FALSE, but not doing this + * will break reauthentication since EAPOL state machines may not be + * get into AUTHENTICATING state that clears keyRun before WPA state + * machine enters AUTHENTICATION2 state and goes immediately to INITPMK + * state and takes PMK from the previously used AAA Key. This will + * eventually fail in 4-Way Handshake because Supplicant uses PMK + * derived from the new AAA Key. Setting keyRun = FALSE here seems to + * be good workaround for this issue. */ + wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyRun, 0); +} + + +SM_STATE(WPA_PTK, INITPSK) +{ + const u8 *psk; + SM_ENTRY_MA(WPA_PTK, INITPSK, wpa_ptk); + psk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, sm->p2p_dev_addr, NULL); + if (psk) { + os_memcpy(sm->PMK, psk, PMK_LEN); +#ifdef CONFIG_IEEE80211R + os_memcpy(sm->xxkey, psk, PMK_LEN); + sm->xxkey_len = PMK_LEN; +#endif /* CONFIG_IEEE80211R */ + } + sm->req_replay_counter_used = 0; +} + + +SM_STATE(WPA_PTK, PTKSTART) +{ + u8 buf[2 + RSN_SELECTOR_LEN + PMKID_LEN], *pmkid = NULL; + size_t pmkid_len = 0; + + SM_ENTRY_MA(WPA_PTK, PTKSTART, wpa_ptk); + sm->PTKRequest = FALSE; + sm->TimeoutEvt = FALSE; + sm->alt_snonce_valid = FALSE; + + sm->TimeoutCtr++; + if (sm->TimeoutCtr > (int) dot11RSNAConfigPairwiseUpdateCount) { + /* No point in sending the EAPOL-Key - we will disconnect + * immediately following this. */ + return; + } + + wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, + "sending 1/4 msg of 4-Way Handshake"); + /* + * TODO: Could add PMKID even with WPA2-PSK, but only if there is only + * one possible PSK for this STA. + */ + if (sm->wpa == WPA_VERSION_WPA2 && + wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) && + sm->wpa_key_mgmt != WPA_KEY_MGMT_OSEN) { + pmkid = buf; + pmkid_len = 2 + RSN_SELECTOR_LEN + PMKID_LEN; + pmkid[0] = WLAN_EID_VENDOR_SPECIFIC; + pmkid[1] = RSN_SELECTOR_LEN + PMKID_LEN; + RSN_SELECTOR_PUT(&pmkid[2], RSN_KEY_DATA_PMKID); + { + /* + * Calculate PMKID since no PMKSA cache entry was + * available with pre-calculated PMKID. + */ + rsn_pmkid(sm->PMK, PMK_LEN, sm->wpa_auth->addr, + sm->addr, &pmkid[2 + RSN_SELECTOR_LEN], + wpa_key_mgmt_sha256(sm->wpa_key_mgmt)); + } + } + wpa_send_eapol(sm->wpa_auth, sm, + WPA_KEY_INFO_ACK | WPA_KEY_INFO_KEY_TYPE, NULL, + sm->ANonce, pmkid, pmkid_len, 0, 0); +} + + +static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce, + const u8 *pmk, struct wpa_ptk *ptk) +{ +#ifdef CONFIG_IEEE80211R + if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) + return wpa_auth_derive_ptk_ft(sm, pmk, ptk); +#endif /* CONFIG_IEEE80211R */ + + return wpa_pmk_to_ptk(pmk, PMK_LEN, "Pairwise key expansion", + sm->wpa_auth->addr, sm->addr, sm->ANonce, snonce, + ptk, sm->wpa_key_mgmt, sm->pairwise); +} + + +SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) +{ + struct wpa_ptk PTK; + int ok = 0, psk_found = 0; + const u8 *pmk = NULL; + + SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING, wpa_ptk); + sm->EAPOLKeyReceived = FALSE; + sm->update_snonce = FALSE; + + /* WPA with IEEE 802.1X: use the derived PMK from EAP + * WPA-PSK: iterate through possible PSKs and select the one matching + * the packet */ + for (;;) { + if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) { + pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, + sm->p2p_dev_addr, pmk); + if (pmk == NULL) + break; + psk_found = 1; + } else + pmk = sm->PMK; + + wpa_derive_ptk(sm, sm->SNonce, pmk, &PTK); + + if (wpa_verify_key_mic(sm->wpa_key_mgmt, &PTK, + sm->last_rx_eapol_key, + sm->last_rx_eapol_key_len) == 0) { + ok = 1; + break; + } + + if (!wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) + break; + } + + if (!ok) { + wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, + "invalid MIC in msg 2/4 of 4-Way Handshake"); + if (psk_found) + wpa_auth_psk_failure_report(sm->wpa_auth, sm->addr); + return; + } + +#ifdef CONFIG_IEEE80211R + if (sm->wpa == WPA_VERSION_WPA2 && wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { + /* + * Verify that PMKR1Name from EAPOL-Key message 2/4 matches + * with the value we derived. + */ + if (os_memcmp_const(sm->sup_pmk_r1_name, sm->pmk_r1_name, + WPA_PMK_NAME_LEN) != 0) { + wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, + "PMKR1Name mismatch in FT 4-way " + "handshake"); + wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name from " + "Supplicant", + sm->sup_pmk_r1_name, WPA_PMK_NAME_LEN); + wpa_hexdump(MSG_DEBUG, "FT: Derived PMKR1Name", + sm->pmk_r1_name, WPA_PMK_NAME_LEN); + return; + } + } +#endif /* CONFIG_IEEE80211R */ + + sm->pending_1_of_4_timeout = 0; + eloop_cancel_timeout(wpa_send_eapol_timeout, sm->wpa_auth, sm); + + if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) { + /* PSK may have changed from the previous choice, so update + * state machine data based on whatever PSK was selected here. + */ + os_memcpy(sm->PMK, pmk, PMK_LEN); + } + + sm->MICVerified = TRUE; + + os_memcpy(&sm->PTK, &PTK, sizeof(PTK)); + sm->PTK_valid = TRUE; +} + + +SM_STATE(WPA_PTK, PTKCALCNEGOTIATING2) +{ + SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING2, wpa_ptk); + sm->TimeoutCtr = 0; +} + + +#ifdef CONFIG_IEEE80211W + +static int ieee80211w_kde_len(struct wpa_state_machine *sm) +{ + if (sm->mgmt_frame_prot) { + size_t len; + len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher); + return 2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN + len; + } + + return 0; +} + + +static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos) +{ + struct wpa_igtk_kde igtk; + struct wpa_group *gsm = sm->group; + u8 rsc[WPA_KEY_RSC_LEN]; + size_t len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher); + + if (!sm->mgmt_frame_prot) + return pos; + + igtk.keyid[0] = gsm->GN_igtk; + igtk.keyid[1] = 0; + if (gsm->wpa_group_state != WPA_GROUP_SETKEYSDONE || + wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, rsc) < 0) + os_memset(igtk.pn, 0, sizeof(igtk.pn)); + else + os_memcpy(igtk.pn, rsc, sizeof(igtk.pn)); + os_memcpy(igtk.igtk, gsm->IGTK[gsm->GN_igtk - 4], len); + if (sm->wpa_auth->conf.disable_gtk) { + /* + * Provide unique random IGTK to each STA to prevent use of + * IGTK in the BSS. + */ + if (random_get_bytes(igtk.igtk, len) < 0) + return pos; + } + pos = wpa_add_kde(pos, RSN_KEY_DATA_IGTK, + (const u8 *) &igtk, WPA_IGTK_KDE_PREFIX_LEN + len, + NULL, 0); + + return pos; +} + +#else /* CONFIG_IEEE80211W */ + +static int ieee80211w_kde_len(struct wpa_state_machine *sm) +{ + return 0; +} + + +static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos) +{ + return pos; +} + +#endif /* CONFIG_IEEE80211W */ + + +SM_STATE(WPA_PTK, PTKINITNEGOTIATING) +{ + u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde, *pos, dummy_gtk[32]; + size_t gtk_len, kde_len; + struct wpa_group *gsm = sm->group; + u8 *wpa_ie; + int wpa_ie_len, secure, keyidx, encr = 0; + + SM_ENTRY_MA(WPA_PTK, PTKINITNEGOTIATING, wpa_ptk); + sm->TimeoutEvt = FALSE; + + sm->TimeoutCtr++; + if (sm->TimeoutCtr > (int) dot11RSNAConfigPairwiseUpdateCount) { + /* No point in sending the EAPOL-Key - we will disconnect + * immediately following this. */ + return; + } + + /* Send EAPOL(1, 1, 1, Pair, P, RSC, ANonce, MIC(PTK), RSNIE, [MDIE], + GTK[GN], IGTK, [FTIE], [TIE * 2]) + */ + os_memset(rsc, 0, WPA_KEY_RSC_LEN); + wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, rsc); + /* If FT is used, wpa_auth->wpa_ie includes both RSNIE and MDIE */ + wpa_ie = sm->wpa_auth->wpa_ie; + wpa_ie_len = sm->wpa_auth->wpa_ie_len; + if (sm->wpa == WPA_VERSION_WPA && + (sm->wpa_auth->conf.wpa & WPA_PROTO_RSN) && + wpa_ie_len > wpa_ie[1] + 2 && wpa_ie[0] == WLAN_EID_RSN) { + /* WPA-only STA, remove RSN IE and possible MDIE */ + wpa_ie = wpa_ie + wpa_ie[1] + 2; + if (wpa_ie[0] == WLAN_EID_MOBILITY_DOMAIN) + wpa_ie = wpa_ie + wpa_ie[1] + 2; + wpa_ie_len = wpa_ie[1] + 2; + } + wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, + "sending 3/4 msg of 4-Way Handshake"); + if (sm->wpa == WPA_VERSION_WPA2) { + /* WPA2 send GTK in the 4-way handshake */ + secure = 1; + gtk = gsm->GTK[gsm->GN - 1]; + gtk_len = gsm->GTK_len; + if (sm->wpa_auth->conf.disable_gtk) { + /* + * Provide unique random GTK to each STA to prevent use + * of GTK in the BSS. + */ + if (random_get_bytes(dummy_gtk, gtk_len) < 0) + return; + gtk = dummy_gtk; + } + keyidx = gsm->GN; + _rsc = rsc; + encr = 1; + } else { + /* WPA does not include GTK in msg 3/4 */ + secure = 0; + gtk = NULL; + gtk_len = 0; + keyidx = 0; + _rsc = NULL; + if (sm->rx_eapol_key_secure) { + /* + * It looks like Windows 7 supplicant tries to use + * Secure bit in msg 2/4 after having reported Michael + * MIC failure and it then rejects the 4-way handshake + * if msg 3/4 does not set Secure bit. Work around this + * by setting the Secure bit here even in the case of + * WPA if the supplicant used it first. + */ + wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, + "STA used Secure bit in WPA msg 2/4 - " + "set Secure for 3/4 as workaround"); + secure = 1; + } + } + + kde_len = wpa_ie_len + ieee80211w_kde_len(sm); + if (gtk) + kde_len += 2 + RSN_SELECTOR_LEN + 2 + gtk_len; +#ifdef CONFIG_IEEE80211R + if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { + kde_len += 2 + PMKID_LEN; /* PMKR1Name into RSN IE */ + kde_len += 300; /* FTIE + 2 * TIE */ + } +#endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_P2P + if (WPA_GET_BE32(sm->ip_addr) > 0) + kde_len += 2 + RSN_SELECTOR_LEN + 3 * 4; +#endif /* CONFIG_P2P */ + kde = os_malloc(kde_len); + if (kde == NULL) + return; + + pos = kde; + os_memcpy(pos, wpa_ie, wpa_ie_len); + pos += wpa_ie_len; +#ifdef CONFIG_IEEE80211R + if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { + int res = wpa_insert_pmkid(kde, pos - kde, sm->pmk_r1_name); + if (res < 0) { + wpa_printf(MSG_ERROR, "FT: Failed to insert " + "PMKR1Name into RSN IE in EAPOL-Key data"); + os_free(kde); + return; + } + pos += res; + } +#endif /* CONFIG_IEEE80211R */ + if (gtk) { + u8 hdr[2]; + hdr[0] = keyidx & 0x03; + hdr[1] = 0; + pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2, + gtk, gtk_len); + } + pos = ieee80211w_kde_add(sm, pos); + +#ifdef CONFIG_IEEE80211R + if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { + int res; + struct wpa_auth_config *conf; + + conf = &sm->wpa_auth->conf; + res = wpa_write_ftie(conf, conf->r0_key_holder, + conf->r0_key_holder_len, + NULL, NULL, pos, kde + kde_len - pos, + NULL, 0); + if (res < 0) { + wpa_printf(MSG_ERROR, "FT: Failed to insert FTIE " + "into EAPOL-Key Key Data"); + os_free(kde); + return; + } + pos += res; + + /* TIE[ReassociationDeadline] (TU) */ + *pos++ = WLAN_EID_TIMEOUT_INTERVAL; + *pos++ = 5; + *pos++ = WLAN_TIMEOUT_REASSOC_DEADLINE; + WPA_PUT_LE32(pos, conf->reassociation_deadline); + pos += 4; + + /* TIE[KeyLifetime] (seconds) */ + *pos++ = WLAN_EID_TIMEOUT_INTERVAL; + *pos++ = 5; + *pos++ = WLAN_TIMEOUT_KEY_LIFETIME; + WPA_PUT_LE32(pos, conf->r0_key_lifetime * 60); + pos += 4; + } +#endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_P2P + if (WPA_GET_BE32(sm->ip_addr) > 0) { + u8 addr[3 * 4]; + os_memcpy(addr, sm->ip_addr, 4); + os_memcpy(addr + 4, sm->wpa_auth->conf.ip_addr_mask, 4); + os_memcpy(addr + 8, sm->wpa_auth->conf.ip_addr_go, 4); + pos = wpa_add_kde(pos, WFA_KEY_DATA_IP_ADDR_ALLOC, + addr, sizeof(addr), NULL, 0); + } +#endif /* CONFIG_P2P */ + + wpa_send_eapol(sm->wpa_auth, sm, + (secure ? WPA_KEY_INFO_SECURE : 0) | WPA_KEY_INFO_MIC | + WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL | + WPA_KEY_INFO_KEY_TYPE, + _rsc, sm->ANonce, kde, pos - kde, keyidx, encr); + os_free(kde); +} + + +SM_STATE(WPA_PTK, PTKINITDONE) +{ + SM_ENTRY_MA(WPA_PTK, PTKINITDONE, wpa_ptk); + sm->EAPOLKeyReceived = FALSE; + if (sm->Pair) { + enum wpa_alg alg = (enum wpa_alg)wpa_cipher_to_alg(sm->pairwise); + int klen = wpa_cipher_key_len(sm->pairwise); + if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0, + sm->PTK.tk, klen)) { + wpa_sta_disconnect(sm->wpa_auth, sm->addr); + return; + } + /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */ + sm->pairwise_set = TRUE; + + if (sm->wpa_auth->conf.wpa_ptk_rekey) { + eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm); + eloop_register_timeout(sm->wpa_auth->conf. + wpa_ptk_rekey, 0, wpa_rekey_ptk, + sm->wpa_auth, sm); + } + + if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) { + wpa_auth_set_eapol(sm->wpa_auth, sm->addr, + WPA_EAPOL_authorized, 1); + } + } + + if (0 /* IBSS == TRUE */) { + sm->keycount++; + if (sm->keycount == 2) { + wpa_auth_set_eapol(sm->wpa_auth, sm->addr, + WPA_EAPOL_portValid, 1); + } + } else { + wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portValid, + 1); + } + wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyAvailable, 0); + wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyDone, 1); + if (sm->wpa == WPA_VERSION_WPA) + sm->PInitAKeys = TRUE; + else + sm->has_GTK = TRUE; + wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO, + "pairwise key handshake completed (%s)", + sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN"); + +#ifdef CONFIG_IEEE80211R + wpa_ft_push_pmk_r1(sm->wpa_auth, sm->addr); +#endif /* CONFIG_IEEE80211R */ +} + + +SM_STEP(WPA_PTK) +{ + struct wpa_authenticator *wpa_auth = sm->wpa_auth; + + if (sm->Init) + SM_ENTER(WPA_PTK, INITIALIZE); + else if (sm->Disconnect + /* || FIX: dot11RSNAConfigSALifetime timeout */) { + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, + "WPA_PTK: sm->Disconnect"); + SM_ENTER(WPA_PTK, DISCONNECT); + } + else if (sm->DeauthenticationRequest) + SM_ENTER(WPA_PTK, DISCONNECTED); + else if (sm->AuthenticationRequest) + SM_ENTER(WPA_PTK, AUTHENTICATION); + else if (sm->ReAuthenticationRequest) + SM_ENTER(WPA_PTK, AUTHENTICATION2); + else if (sm->PTKRequest) { + if (wpa_auth_sm_ptk_update(sm) < 0) + SM_ENTER(WPA_PTK, DISCONNECTED); + else + SM_ENTER(WPA_PTK, PTKSTART); + } else switch (sm->wpa_ptk_state) { + case WPA_PTK_INITIALIZE: + break; + case WPA_PTK_DISCONNECT: + SM_ENTER(WPA_PTK, DISCONNECTED); + break; + case WPA_PTK_DISCONNECTED: + SM_ENTER(WPA_PTK, INITIALIZE); + break; + case WPA_PTK_AUTHENTICATION: + SM_ENTER(WPA_PTK, AUTHENTICATION2); + break; + case WPA_PTK_AUTHENTICATION2: + if (wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) && + wpa_auth_get_eapol(sm->wpa_auth, sm->addr, + WPA_EAPOL_keyRun) > 0) + SM_ENTER(WPA_PTK, INITPMK); + else if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) + /* FIX: && 802.1X::keyRun */) + SM_ENTER(WPA_PTK, INITPSK); + break; + case WPA_PTK_INITPMK: + if (wpa_auth_get_eapol(sm->wpa_auth, sm->addr, + WPA_EAPOL_keyAvailable) > 0) + SM_ENTER(WPA_PTK, PTKSTART); + else { + wpa_auth->dot11RSNA4WayHandshakeFailures++; + wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO, + "INITPMK - keyAvailable = false"); + SM_ENTER(WPA_PTK, DISCONNECT); + } + break; + case WPA_PTK_INITPSK: + if (wpa_auth_get_psk(sm->wpa_auth, sm->addr, sm->p2p_dev_addr, + NULL)) + SM_ENTER(WPA_PTK, PTKSTART); + else { + wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO, + "no PSK configured for the STA"); + wpa_auth->dot11RSNA4WayHandshakeFailures++; + SM_ENTER(WPA_PTK, DISCONNECT); + } + break; + case WPA_PTK_PTKSTART: + if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest && + sm->EAPOLKeyPairwise) + SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING); + else if (sm->TimeoutCtr > + (int) dot11RSNAConfigPairwiseUpdateCount) { + wpa_auth->dot11RSNA4WayHandshakeFailures++; + wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, + "PTKSTART: Retry limit %d reached", + dot11RSNAConfigPairwiseUpdateCount); + SM_ENTER(WPA_PTK, DISCONNECT); + } else if (sm->TimeoutEvt) + SM_ENTER(WPA_PTK, PTKSTART); + break; + case WPA_PTK_PTKCALCNEGOTIATING: + if (sm->MICVerified) + SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING2); + else if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest && + sm->EAPOLKeyPairwise) + SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING); + else if (sm->TimeoutEvt) + SM_ENTER(WPA_PTK, PTKSTART); + break; + case WPA_PTK_PTKCALCNEGOTIATING2: + SM_ENTER(WPA_PTK, PTKINITNEGOTIATING); + break; + case WPA_PTK_PTKINITNEGOTIATING: + if (sm->update_snonce) + SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING); + else if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest && + sm->EAPOLKeyPairwise && sm->MICVerified) + SM_ENTER(WPA_PTK, PTKINITDONE); + else if (sm->TimeoutCtr > + (int) dot11RSNAConfigPairwiseUpdateCount) { + wpa_auth->dot11RSNA4WayHandshakeFailures++; + wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, + "PTKINITNEGOTIATING: Retry limit %d " + "reached", + dot11RSNAConfigPairwiseUpdateCount); + SM_ENTER(WPA_PTK, DISCONNECT); + } else if (sm->TimeoutEvt) + SM_ENTER(WPA_PTK, PTKINITNEGOTIATING); + break; + case WPA_PTK_PTKINITDONE: + break; + } +} + + +SM_STATE(WPA_PTK_GROUP, IDLE) +{ + SM_ENTRY_MA(WPA_PTK_GROUP, IDLE, wpa_ptk_group); + if (sm->Init) { + /* Init flag is not cleared here, so avoid busy + * loop by claiming nothing changed. */ + sm->changed = FALSE; + } + sm->GTimeoutCtr = 0; +} + + +SM_STATE(WPA_PTK_GROUP, REKEYNEGOTIATING) +{ + u8 rsc[WPA_KEY_RSC_LEN]; + struct wpa_group *gsm = sm->group; + const u8 *kde; + u8 *kde_buf = NULL, *pos, hdr[2]; + size_t kde_len; + u8 *gtk, dummy_gtk[32]; + + SM_ENTRY_MA(WPA_PTK_GROUP, REKEYNEGOTIATING, wpa_ptk_group); + + sm->GTimeoutCtr++; + if (sm->GTimeoutCtr > (int) dot11RSNAConfigGroupUpdateCount) { + /* No point in sending the EAPOL-Key - we will disconnect + * immediately following this. */ + return; + } + + if (sm->wpa == WPA_VERSION_WPA) + sm->PInitAKeys = FALSE; + sm->TimeoutEvt = FALSE; + /* Send EAPOL(1, 1, 1, !Pair, G, RSC, GNonce, MIC(PTK), GTK[GN]) */ + os_memset(rsc, 0, WPA_KEY_RSC_LEN); + if (gsm->wpa_group_state == WPA_GROUP_SETKEYSDONE) + wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, rsc); + wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, + "sending 1/2 msg of Group Key Handshake"); + + gtk = gsm->GTK[gsm->GN - 1]; + if (sm->wpa_auth->conf.disable_gtk) { + /* + * Provide unique random GTK to each STA to prevent use + * of GTK in the BSS. + */ + if (random_get_bytes(dummy_gtk, gsm->GTK_len) < 0) + return; + gtk = dummy_gtk; + } + if (sm->wpa == WPA_VERSION_WPA2) { + kde_len = 2 + RSN_SELECTOR_LEN + 2 + gsm->GTK_len + + ieee80211w_kde_len(sm); + kde_buf = os_malloc(kde_len); + if (kde_buf == NULL) + return; + + kde = pos = kde_buf; + hdr[0] = gsm->GN & 0x03; + hdr[1] = 0; + pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2, + gtk, gsm->GTK_len); + pos = ieee80211w_kde_add(sm, pos); + kde_len = pos - kde; + } else { + kde = gtk; + kde_len = gsm->GTK_len; + } + + wpa_send_eapol(sm->wpa_auth, sm, + WPA_KEY_INFO_SECURE | WPA_KEY_INFO_MIC | + WPA_KEY_INFO_ACK | + (!sm->Pair ? WPA_KEY_INFO_INSTALL : 0), + rsc, gsm->GNonce, kde, kde_len, gsm->GN, 1); + + os_free(kde_buf); +} + + +SM_STATE(WPA_PTK_GROUP, REKEYESTABLISHED) +{ + SM_ENTRY_MA(WPA_PTK_GROUP, REKEYESTABLISHED, wpa_ptk_group); + sm->EAPOLKeyReceived = FALSE; + if (sm->GUpdateStationKeys) + sm->group->GKeyDoneStations--; + sm->GUpdateStationKeys = FALSE; + sm->GTimeoutCtr = 0; + /* FIX: MLME.SetProtection.Request(TA, Tx_Rx) */ + wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO, + "group key handshake completed (%s)", + sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN"); + sm->has_GTK = TRUE; +} + + +SM_STATE(WPA_PTK_GROUP, KEYERROR) +{ + SM_ENTRY_MA(WPA_PTK_GROUP, KEYERROR, wpa_ptk_group); + if (sm->GUpdateStationKeys) + sm->group->GKeyDoneStations--; + sm->GUpdateStationKeys = FALSE; + sm->Disconnect = TRUE; +} + + +SM_STEP(WPA_PTK_GROUP) +{ + if (sm->Init || sm->PtkGroupInit) { + SM_ENTER(WPA_PTK_GROUP, IDLE); + sm->PtkGroupInit = FALSE; + } else switch (sm->wpa_ptk_group_state) { + case WPA_PTK_GROUP_IDLE: + if (sm->GUpdateStationKeys || + (sm->wpa == WPA_VERSION_WPA && sm->PInitAKeys)) + SM_ENTER(WPA_PTK_GROUP, REKEYNEGOTIATING); + break; + case WPA_PTK_GROUP_REKEYNEGOTIATING: + if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest && + !sm->EAPOLKeyPairwise && sm->MICVerified) + SM_ENTER(WPA_PTK_GROUP, REKEYESTABLISHED); + else if (sm->GTimeoutCtr > + (int) dot11RSNAConfigGroupUpdateCount) + SM_ENTER(WPA_PTK_GROUP, KEYERROR); + else if (sm->TimeoutEvt) + SM_ENTER(WPA_PTK_GROUP, REKEYNEGOTIATING); + break; + case WPA_PTK_GROUP_KEYERROR: + SM_ENTER(WPA_PTK_GROUP, IDLE); + break; + case WPA_PTK_GROUP_REKEYESTABLISHED: + SM_ENTER(WPA_PTK_GROUP, IDLE); + break; + } +} + + +static int wpa_gtk_update(struct wpa_authenticator *wpa_auth, + struct wpa_group *group) +{ + int ret = 0; + + os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN); + inc_byte_array(group->Counter, WPA_NONCE_LEN); + if (wpa_gmk_to_gtk(group->GMK, "Group key expansion", + wpa_auth->addr, group->GNonce, + group->GTK[group->GN - 1], group->GTK_len) < 0) + ret = -1; + wpa_hexdump_key(MSG_DEBUG, "GTK", + group->GTK[group->GN - 1], group->GTK_len); + +#ifdef CONFIG_IEEE80211W + if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION) { + size_t len; + len = wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher); + os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN); + inc_byte_array(group->Counter, WPA_NONCE_LEN); + if (wpa_gmk_to_gtk(group->GMK, "IGTK key expansion", + wpa_auth->addr, group->GNonce, + group->IGTK[group->GN_igtk - 4], len) < 0) + ret = -1; + wpa_hexdump_key(MSG_DEBUG, "IGTK", + group->IGTK[group->GN_igtk - 4], len); + } +#endif /* CONFIG_IEEE80211W */ + + return ret; +} + + +static void wpa_group_gtk_init(struct wpa_authenticator *wpa_auth, + struct wpa_group *group) +{ + wpa_printf(MSG_DEBUG, "WPA: group state machine entering state " + "GTK_INIT (VLAN-ID %d)", group->vlan_id); + group->changed = FALSE; /* GInit is not cleared here; avoid loop */ + group->wpa_group_state = WPA_GROUP_GTK_INIT; + + /* GTK[0..N] = 0 */ + os_memset(group->GTK, 0, sizeof(group->GTK)); + group->GN = 1; + group->GM = 2; +#ifdef CONFIG_IEEE80211W + group->GN_igtk = 4; + group->GM_igtk = 5; +#endif /* CONFIG_IEEE80211W */ + /* GTK[GN] = CalcGTK() */ + wpa_gtk_update(wpa_auth, group); +} + + +static int wpa_group_update_sta(struct wpa_state_machine *sm, void *ctx) +{ + if (ctx != NULL && ctx != sm->group) + return 0; + + if (sm->wpa_ptk_state != WPA_PTK_PTKINITDONE) { + wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, + "Not in PTKINITDONE; skip Group Key update"); + sm->GUpdateStationKeys = FALSE; + return 0; + } + if (sm->GUpdateStationKeys) { + /* + * This should not really happen, so add a debug log entry. + * Since we clear the GKeyDoneStations before the loop, the + * station needs to be counted here anyway. + */ + wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, + "GUpdateStationKeys was already set when " + "marking station for GTK rekeying"); + } + + /* Do not rekey GTK/IGTK when STA is in WNM-Sleep Mode */ + if (sm->is_wnmsleep) + return 0; + + sm->group->GKeyDoneStations++; + sm->GUpdateStationKeys = TRUE; + + wpa_sm_step(sm); + return 0; +} + + +#ifdef CONFIG_WNM +/* update GTK when exiting WNM-Sleep Mode */ +void wpa_wnmsleep_rekey_gtk(struct wpa_state_machine *sm) +{ + if (sm == NULL || sm->is_wnmsleep) + return; + + wpa_group_update_sta(sm, NULL); +} + + +void wpa_set_wnmsleep(struct wpa_state_machine *sm, int flag) +{ + if (sm) + sm->is_wnmsleep = !!flag; +} + + +int wpa_wnmsleep_gtk_subelem(struct wpa_state_machine *sm, u8 *pos) +{ + struct wpa_group *gsm = sm->group; + u8 *start = pos; + + /* + * GTK subelement: + * Sub-elem ID[1] | Length[1] | Key Info[2] | Key Length[1] | RSC[8] | + * Key[5..32] + */ + *pos++ = WNM_SLEEP_SUBELEM_GTK; + *pos++ = 11 + gsm->GTK_len; + /* Key ID in B0-B1 of Key Info */ + WPA_PUT_LE16(pos, gsm->GN & 0x03); + pos += 2; + *pos++ = gsm->GTK_len; + if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, pos) != 0) + return 0; + pos += 8; + os_memcpy(pos, gsm->GTK[gsm->GN - 1], gsm->GTK_len); + pos += gsm->GTK_len; + + wpa_printf(MSG_DEBUG, "WNM: GTK Key ID %u in WNM-Sleep Mode exit", + gsm->GN); + wpa_hexdump_key(MSG_DEBUG, "WNM: GTK in WNM-Sleep Mode exit", + gsm->GTK[gsm->GN - 1], gsm->GTK_len); + + return pos - start; +} + + +#ifdef CONFIG_IEEE80211W +int wpa_wnmsleep_igtk_subelem(struct wpa_state_machine *sm, u8 *pos) +{ + struct wpa_group *gsm = sm->group; + u8 *start = pos; + size_t len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher); + + /* + * IGTK subelement: + * Sub-elem ID[1] | Length[1] | KeyID[2] | PN[6] | Key[16] + */ + *pos++ = WNM_SLEEP_SUBELEM_IGTK; + *pos++ = 2 + 6 + len; + WPA_PUT_LE16(pos, gsm->GN_igtk); + pos += 2; + if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, pos) != 0) + return 0; + pos += 6; + + os_memcpy(pos, gsm->IGTK[gsm->GN_igtk - 4], len); + pos += len; + + wpa_printf(MSG_DEBUG, "WNM: IGTK Key ID %u in WNM-Sleep Mode exit", + gsm->GN_igtk); + wpa_hexdump_key(MSG_DEBUG, "WNM: IGTK in WNM-Sleep Mode exit", + gsm->IGTK[gsm->GN_igtk - 4], len); + + return pos - start; +} +#endif /* CONFIG_IEEE80211W */ +#endif /* CONFIG_WNM */ + + +static void wpa_group_setkeys(struct wpa_authenticator *wpa_auth, + struct wpa_group *group) +{ + int tmp; + + wpa_printf(MSG_DEBUG, "WPA: group state machine entering state " + "SETKEYS (VLAN-ID %d)", group->vlan_id); + group->changed = TRUE; + group->wpa_group_state = WPA_GROUP_SETKEYS; + group->GTKReKey = FALSE; + tmp = group->GM; + group->GM = group->GN; + group->GN = tmp; +#ifdef CONFIG_IEEE80211W + tmp = group->GM_igtk; + group->GM_igtk = group->GN_igtk; + group->GN_igtk = tmp; +#endif /* CONFIG_IEEE80211W */ + /* "GKeyDoneStations = GNoStations" is done in more robust way by + * counting the STAs that are marked with GUpdateStationKeys instead of + * including all STAs that could be in not-yet-completed state. */ + wpa_gtk_update(wpa_auth, group); + + if (group->GKeyDoneStations) { + wpa_printf(MSG_DEBUG, "wpa_group_setkeys: Unexpected " + "GKeyDoneStations=%d when starting new GTK rekey", + group->GKeyDoneStations); + group->GKeyDoneStations = 0; + } + wpa_auth_for_each_sta(wpa_auth, wpa_group_update_sta, group); + wpa_printf(MSG_DEBUG, "wpa_group_setkeys: GKeyDoneStations=%d", + group->GKeyDoneStations); +} + + +static int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth, + struct wpa_group *group) +{ + int ret = 0; + + if (wpa_auth_set_key(wpa_auth, group->vlan_id, + (enum wpa_alg)wpa_cipher_to_alg(wpa_auth->conf.wpa_group), + broadcast_ether_addr, group->GN, + group->GTK[group->GN - 1], group->GTK_len) < 0) + ret = -1; + +#ifdef CONFIG_IEEE80211W + if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION) { + enum wpa_alg alg; + size_t len; + + alg = wpa_cipher_to_alg(wpa_auth->conf.group_mgmt_cipher); + len = wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher); + + if (ret == 0 && + wpa_auth_set_key(wpa_auth, group->vlan_id, alg, + broadcast_ether_addr, group->GN_igtk, + group->IGTK[group->GN_igtk - 4], len) < 0) + ret = -1; + } +#endif /* CONFIG_IEEE80211W */ + + return ret; +} + + +static int wpa_group_disconnect_cb(struct wpa_state_machine *sm, void *ctx) +{ + if (sm->group == ctx) { + wpa_printf(MSG_DEBUG, "WPA: Mark STA " MACSTR + " for discconnection due to fatal failure", + MAC2STR(sm->addr)); + sm->Disconnect = TRUE; + } + + return 0; +} + + +static void wpa_group_fatal_failure(struct wpa_authenticator *wpa_auth, + struct wpa_group *group) +{ + wpa_printf(MSG_DEBUG, "WPA: group state machine entering state FATAL_FAILURE"); + group->changed = TRUE; + group->wpa_group_state = WPA_GROUP_FATAL_FAILURE; + wpa_auth_for_each_sta(wpa_auth, wpa_group_disconnect_cb, group); +} + + +static int wpa_group_setkeysdone(struct wpa_authenticator *wpa_auth, + struct wpa_group *group) +{ + wpa_printf(MSG_DEBUG, "WPA: group state machine entering state " + "SETKEYSDONE (VLAN-ID %d)", group->vlan_id); + group->changed = TRUE; + group->wpa_group_state = WPA_GROUP_SETKEYSDONE; + + if (wpa_group_config_group_keys(wpa_auth, group) < 0) { + wpa_group_fatal_failure(wpa_auth, group); + return -1; + } + + return 0; +} + + +static void wpa_group_sm_step(struct wpa_authenticator *wpa_auth, + struct wpa_group *group) +{ + if (group->GInit) { + wpa_group_gtk_init(wpa_auth, group); + } else if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE) { + /* Do not allow group operations */ + } else if (group->wpa_group_state == WPA_GROUP_GTK_INIT && + group->GTKAuthenticator) { + wpa_group_setkeysdone(wpa_auth, group); + } else if (group->wpa_group_state == WPA_GROUP_SETKEYSDONE && + group->GTKReKey) { + wpa_group_setkeys(wpa_auth, group); + } else if (group->wpa_group_state == WPA_GROUP_SETKEYS) { + if (group->GKeyDoneStations == 0) + wpa_group_setkeysdone(wpa_auth, group); + else if (group->GTKReKey) + wpa_group_setkeys(wpa_auth, group); + } +} + + +static int wpa_sm_step(struct wpa_state_machine *sm) +{ + if (sm == NULL) + return 0; + + if (sm->in_step_loop) { + /* This should not happen, but if it does, make sure we do not + * end up freeing the state machine too early by exiting the + * recursive call. */ + wpa_printf(MSG_ERROR, "WPA: wpa_sm_step() called recursively"); + return 0; + } + + sm->in_step_loop = 1; + do { + if (sm->pending_deinit) + break; + + sm->changed = FALSE; + sm->wpa_auth->group->changed = FALSE; + + SM_STEP_RUN(WPA_PTK); + if (sm->pending_deinit) + break; + SM_STEP_RUN(WPA_PTK_GROUP); + if (sm->pending_deinit) + break; + wpa_group_sm_step(sm->wpa_auth, sm->group); + } while (sm->changed || sm->wpa_auth->group->changed); + sm->in_step_loop = 0; + + if (sm->pending_deinit) { + wpa_printf(MSG_DEBUG, "WPA: Completing pending STA state " + "machine deinit for " MACSTR, MAC2STR(sm->addr)); + wpa_free_sta_sm(sm); + return 1; + } + return 0; +} + + +static void wpa_sm_call_step(void *eloop_ctx, void *timeout_ctx) +{ + struct wpa_state_machine *sm = eloop_ctx; + wpa_sm_step(sm); +} + + +void wpa_auth_sm_notify(struct wpa_state_machine *sm) +{ + if (sm == NULL) + return; + eloop_register_timeout(0, 0, wpa_sm_call_step, sm, NULL); +} + + +void wpa_gtk_rekey(struct wpa_authenticator *wpa_auth) +{ + int tmp, i; + struct wpa_group *group; + + if (wpa_auth == NULL) + return; + + group = wpa_auth->group; + + for (i = 0; i < 2; i++) { + tmp = group->GM; + group->GM = group->GN; + group->GN = tmp; +#ifdef CONFIG_IEEE80211W + tmp = group->GM_igtk; + group->GM_igtk = group->GN_igtk; + group->GN_igtk = tmp; +#endif /* CONFIG_IEEE80211W */ + wpa_gtk_update(wpa_auth, group); + wpa_group_config_group_keys(wpa_auth, group); + } +} + + +const char * wpa_bool_txt(int val) +{ + return val ? "TRUE" : "FALSE"; +} + + +#define RSN_SUITE "%02x-%02x-%02x-%d" +#define RSN_SUITE_ARG(s) \ +((s) >> 24) & 0xff, ((s) >> 16) & 0xff, ((s) >> 8) & 0xff, (s) & 0xff + +void wpa_auth_countermeasures_start(struct wpa_authenticator *wpa_auth) +{ + if (wpa_auth) + wpa_auth->dot11RSNATKIPCounterMeasuresInvoked++; +} + + +int wpa_auth_pairwise_set(struct wpa_state_machine *sm) +{ + return sm && sm->pairwise_set; +} + + +int wpa_auth_get_pairwise(struct wpa_state_machine *sm) +{ + return sm->pairwise; +} + + +int wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm) +{ + if (sm == NULL) + return -1; + return sm->wpa_key_mgmt; +} + + +int wpa_auth_sta_wpa_version(struct wpa_state_machine *sm) +{ + if (sm == NULL) + return 0; + return sm->wpa; +} + +int wpa_auth_sta_ft_tk_already_set(struct wpa_state_machine *sm) +{ + if (!sm || !wpa_key_mgmt_ft(sm->wpa_key_mgmt)) + return 0; + return sm->tk_already_set; +} + +int wpa_auth_sta_clear_pmksa(struct wpa_state_machine *sm, + struct rsn_pmksa_cache_entry *entry) +{ + if (sm == NULL || sm->pmksa != entry) + return -1; + sm->pmksa = NULL; + return 0; +} + + +struct rsn_pmksa_cache_entry * +wpa_auth_sta_get_pmksa(struct wpa_state_machine *sm) +{ + return sm ? sm->pmksa : NULL; +} + + +void wpa_auth_sta_local_mic_failure_report(struct wpa_state_machine *sm) +{ + if (sm) + sm->dot11RSNAStatsTKIPLocalMICFailures++; +} + + +const u8 * wpa_auth_get_wpa_ie(struct wpa_authenticator *wpa_auth, size_t *len) +{ + if (wpa_auth == NULL) + return NULL; + *len = wpa_auth->wpa_ie_len; + return wpa_auth->wpa_ie; +} + +/* + * Remove and free the group from wpa_authenticator. This is triggered by a + * callback to make sure nobody is currently iterating the group list while it + * gets modified. + */ +static void wpa_group_free(struct wpa_authenticator *wpa_auth, + struct wpa_group *group) +{ + struct wpa_group *prev = wpa_auth->group; + + wpa_printf(MSG_DEBUG, "WPA: Remove group state machine for VLAN-ID %d", + group->vlan_id); + + while (prev) { + if (prev->next == group) { + /* This never frees the special first group as needed */ + prev->next = group->next; + os_free(group); + break; + } + prev = prev->next; + } + +} + + +/* Increase the reference counter for group */ +static void wpa_group_get(struct wpa_authenticator *wpa_auth, + struct wpa_group *group) +{ + /* Skip the special first group */ + if (wpa_auth->group == group) + return; + + group->references++; +} + + +/* Decrease the reference counter and maybe free the group */ +static void wpa_group_put(struct wpa_authenticator *wpa_auth, + struct wpa_group *group) +{ + /* Skip the special first group */ + if (wpa_auth->group == group) + return; + + group->references--; + if (group->references) + return; + wpa_group_free(wpa_auth, group); +} + + +/* + * Add a group that has its references counter set to zero. Caller needs to + * call wpa_group_get() on the return value to mark the entry in use. + */ +static struct wpa_group * +wpa_auth_add_group(struct wpa_authenticator *wpa_auth, int vlan_id) +{ + struct wpa_group *group; + + if (wpa_auth == NULL || wpa_auth->group == NULL) + return NULL; + + wpa_printf(MSG_DEBUG, "WPA: Add group state machine for VLAN-ID %d", + vlan_id); + group = wpa_group_init(wpa_auth, vlan_id, 0); + if (group == NULL) + return NULL; + + group->next = wpa_auth->group->next; + wpa_auth->group->next = group; + + return group; +} + + +int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id) +{ + struct wpa_group *group; + + if (sm == NULL || sm->wpa_auth == NULL) + return 0; + + group = sm->wpa_auth->group; + while (group) { + if (group->vlan_id == vlan_id) + break; + group = group->next; + } + + if (group == NULL) { + group = wpa_auth_add_group(sm->wpa_auth, vlan_id); + if (group == NULL) + return -1; + } + + if (sm->group == group) + return 0; + + if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE) + return -1; + + wpa_printf(MSG_DEBUG, "WPA: Moving STA " MACSTR " to use group state " + "machine for VLAN ID %d", MAC2STR(sm->addr), vlan_id); + + wpa_group_get(sm->wpa_auth, group); + wpa_group_put(sm->wpa_auth, sm->group); + sm->group = group; + + return 0; +} + + +void wpa_auth_eapol_key_tx_status(struct wpa_authenticator *wpa_auth, + struct wpa_state_machine *sm, int ack) +{ + if (wpa_auth == NULL || sm == NULL) + return; + wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key TX status for STA " MACSTR + " ack=%d", MAC2STR(sm->addr), ack); + if (sm->pending_1_of_4_timeout && ack) { + /* + * Some deployed supplicant implementations update their SNonce + * for each EAPOL-Key 2/4 message even within the same 4-way + * handshake and then fail to use the first SNonce when + * deriving the PTK. This results in unsuccessful 4-way + * handshake whenever the relatively short initial timeout is + * reached and EAPOL-Key 1/4 is retransmitted. Try to work + * around this by increasing the timeout now that we know that + * the station has received the frame. + */ + int timeout_ms = eapol_key_timeout_subseq; + wpa_printf(MSG_DEBUG, "WPA: Increase initial EAPOL-Key 1/4 " + "timeout by %u ms because of acknowledged frame", + timeout_ms); + eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm); + eloop_register_timeout(timeout_ms / 1000, + (timeout_ms % 1000) * 1000, + wpa_send_eapol_timeout, wpa_auth, sm); + } +} + + +int wpa_auth_uses_sae(struct wpa_state_machine *sm) +{ + if (sm == NULL) + return 0; + return wpa_key_mgmt_sae(sm->wpa_key_mgmt); +} + + +int wpa_auth_uses_ft_sae(struct wpa_state_machine *sm) +{ + if (sm == NULL) + return 0; + return sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_SAE; +} + + +#ifdef CONFIG_P2P +int wpa_auth_get_ip_addr(struct wpa_state_machine *sm, u8 *addr) +{ + if (sm == NULL || WPA_GET_BE32(sm->ip_addr) == 0) + return -1; + os_memcpy(addr, sm->ip_addr, 4); + return 0; +} +#endif /* CONFIG_P2P */ + +void wpa_auth_reconfig_group_keys(struct wpa_authenticator *wpa_auth) +{ + struct wpa_group *group; + + if (!wpa_auth) + return; + for (group = wpa_auth->group; group; group = group->next) + wpa_group_config_group_keys(wpa_auth, group); +} diff --git a/beken_os/beken378/func/hostapd-2.5/src/ap/wpa_auth.h b/beken_os/beken378/func/hostapd-2.5/src/ap/wpa_auth.h new file mode 100755 index 0000000..b4ff4e2 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/ap/wpa_auth.h @@ -0,0 +1,329 @@ +/* + * hostapd - IEEE 802.11i-2004 / WPA Authenticator + * Copyright (c) 2004-2015, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef WPA_AUTH_H +#define WPA_AUTH_H + +#include "common/defs.h" +#include "common/eapol_common.h" +#include "common/wpa_common.h" +#include "common/ieee802_11_defs.h" + +#define MAX_OWN_IE_OVERRIDE 256 + +#ifdef _MSC_VER +#pragma pack(push, 1) +#endif /* _MSC_VER */ + +/* IEEE Std 802.11r-2008, 11A.10.3 - Remote request/response frame definition + */ +STRUCT_PACKED struct ft_rrb_frame { + u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */ + u8 packet_type; /* FT_PACKET_REQUEST/FT_PACKET_RESPONSE */ + le16 action_length; /* little endian length of action_frame */ + u8 ap_address[ETH_ALEN]; + /* + * Followed by action_length bytes of FT Action frame (from Category + * field to the end of Action Frame body. + */ +}GCC_PACKED; + +#define RSN_REMOTE_FRAME_TYPE_FT_RRB 1 + +#define FT_PACKET_REQUEST 0 +#define FT_PACKET_RESPONSE 1 +/* Vendor-specific types for R0KH-R1KH protocol; not defined in 802.11r */ +#define FT_PACKET_R0KH_R1KH_PULL 200 +#define FT_PACKET_R0KH_R1KH_RESP 201 +#define FT_PACKET_R0KH_R1KH_PUSH 202 + +#define FT_R0KH_R1KH_PULL_DATA_LEN 44 +#define FT_R0KH_R1KH_RESP_DATA_LEN 76 +#define FT_R0KH_R1KH_PUSH_DATA_LEN 88 +#define FT_R0KH_R1KH_PULL_NONCE_LEN 16 + +STRUCT_PACKED struct ft_r0kh_r1kh_pull_frame { + u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */ + u8 packet_type; /* FT_PACKET_R0KH_R1KH_PULL */ + le16 data_length; /* little endian length of data (44) */ + u8 ap_address[ETH_ALEN]; + + u8 nonce[FT_R0KH_R1KH_PULL_NONCE_LEN]; + u8 pmk_r0_name[WPA_PMK_NAME_LEN]; + u8 r1kh_id[FT_R1KH_ID_LEN]; + u8 s1kh_id[ETH_ALEN]; + u8 pad[4]; /* 8-octet boundary for AES key wrap */ + u8 key_wrap_extra[8]; +}GCC_PACKED; + +STRUCT_PACKED struct ft_r0kh_r1kh_resp_frame { + u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */ + u8 packet_type; /* FT_PACKET_R0KH_R1KH_RESP */ + le16 data_length; /* little endian length of data (76) */ + u8 ap_address[ETH_ALEN]; + + u8 nonce[FT_R0KH_R1KH_PULL_NONCE_LEN]; /* copied from pull */ + u8 r1kh_id[FT_R1KH_ID_LEN]; /* copied from pull */ + u8 s1kh_id[ETH_ALEN]; /* copied from pull */ + u8 pmk_r1[PMK_LEN]; + u8 pmk_r1_name[WPA_PMK_NAME_LEN]; + le16 pairwise; + u8 pad[2]; /* 8-octet boundary for AES key wrap */ + u8 key_wrap_extra[8]; +}GCC_PACKED; + +STRUCT_PACKED struct ft_r0kh_r1kh_push_frame { + u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */ + u8 packet_type; /* FT_PACKET_R0KH_R1KH_PUSH */ + le16 data_length; /* little endian length of data (88) */ + u8 ap_address[ETH_ALEN]; + + /* Encrypted with AES key-wrap */ + u8 timestamp[4]; /* current time in seconds since unix epoch, little + * endian */ + u8 r1kh_id[FT_R1KH_ID_LEN]; + u8 s1kh_id[ETH_ALEN]; + u8 pmk_r0_name[WPA_PMK_NAME_LEN]; + u8 pmk_r1[PMK_LEN]; + u8 pmk_r1_name[WPA_PMK_NAME_LEN]; + le16 pairwise; + u8 pad[6]; /* 8-octet boundary for AES key wrap */ + u8 key_wrap_extra[8]; +}GCC_PACKED; + +#ifdef _MSC_VER +#pragma pack(pop) +#endif /* _MSC_VER */ + + +/* per STA state machine data */ + +struct wpa_authenticator; +struct wpa_state_machine; +struct rsn_pmksa_cache_entry; +struct eapol_state_machine; + + +struct ft_remote_r0kh { + struct ft_remote_r0kh *next; + u8 addr[ETH_ALEN]; + u8 id[FT_R0KH_ID_MAX_LEN]; + size_t id_len; + u8 key[16]; +}; + + +struct ft_remote_r1kh { + struct ft_remote_r1kh *next; + u8 addr[ETH_ALEN]; + u8 id[FT_R1KH_ID_LEN]; + u8 key[16]; +}; + + +struct wpa_auth_config { + int wpa; + int wpa_key_mgmt; + int wpa_pairwise; + int wpa_group; + int wpa_group_rekey; + int wpa_strict_rekey; + int wpa_gmk_rekey; + int wpa_ptk_rekey; + int rsn_pairwise; + int rsn_preauth; + int eapol_version; + int peerkey; + int wmm_enabled; + int wmm_uapsd; + int disable_pmksa_caching; + int okc; + int tx_status; +#ifdef CONFIG_IEEE80211W + enum mfp_options ieee80211w; + int group_mgmt_cipher; +#endif /* CONFIG_IEEE80211W */ +#ifdef CONFIG_IEEE80211R + u8 ssid[SSID_MAX_LEN]; + size_t ssid_len; + u8 mobility_domain[MOBILITY_DOMAIN_ID_LEN]; + u8 r0_key_holder[FT_R0KH_ID_MAX_LEN]; + size_t r0_key_holder_len; + u8 r1_key_holder[FT_R1KH_ID_LEN]; + u32 r0_key_lifetime; + u32 reassociation_deadline; + struct ft_remote_r0kh *r0kh_list; + struct ft_remote_r1kh *r1kh_list; + int pmk_r1_push; + int ft_over_ds; +#endif /* CONFIG_IEEE80211R */ + int disable_gtk; + int ap_mlme; +#ifdef CONFIG_TESTING_OPTIONS + double corrupt_gtk_rekey_mic_probability; + u8 own_ie_override[MAX_OWN_IE_OVERRIDE]; + size_t own_ie_override_len; +#endif /* CONFIG_TESTING_OPTIONS */ +#ifdef CONFIG_P2P + u8 ip_addr_go[4]; + u8 ip_addr_mask[4]; + u8 ip_addr_start[4]; + u8 ip_addr_end[4]; +#endif /* CONFIG_P2P */ +}; + +typedef enum { + LOGGER_DEBUG, LOGGER_INFO, LOGGER_WARNING +} logger_level; + +typedef enum { + WPA_EAPOL_portEnabled, WPA_EAPOL_portValid, WPA_EAPOL_authorized, + WPA_EAPOL_portControl_Auto, WPA_EAPOL_keyRun, WPA_EAPOL_keyAvailable, + WPA_EAPOL_keyDone, WPA_EAPOL_inc_EapolFramesTx +} wpa_eapol_variable; + +struct wpa_auth_callbacks { + void *ctx; + void (*logger)(void *ctx, const u8 *addr, logger_level level, + const char *txt); + void (*disconnect)(void *ctx, const u8 *addr, u16 reason); + int (*mic_failure_report)(void *ctx, const u8 *addr); + void (*psk_failure_report)(void *ctx, const u8 *addr); + void (*set_eapol)(void *ctx, const u8 *addr, wpa_eapol_variable var, + int value); + int (*get_eapol)(void *ctx, const u8 *addr, wpa_eapol_variable var); + const u8 * (*get_psk)(void *ctx, const u8 *addr, const u8 *p2p_dev_addr, + const u8 *prev_psk); + int (*get_msk)(void *ctx, const u8 *addr, u8 *msk, size_t *len); + int (*set_key)(void *ctx, int vlan_id, enum wpa_alg alg, + const u8 *addr, int idx, u8 *key, size_t key_len); + int (*get_seqnum)(void *ctx, const u8 *addr, int idx, u8 *seq); + int (*send_eapol)(void *ctx, const u8 *addr, const u8 *data, + size_t data_len, int encrypt); + int (*for_each_sta)(void *ctx, int (*cb)(struct wpa_state_machine *sm, + void *ctx), void *cb_ctx); + int (*for_each_auth)(void *ctx, int (*cb)(struct wpa_authenticator *a, + void *ctx), void *cb_ctx); + int (*send_ether)(void *ctx, const u8 *dst, u16 proto, const u8 *data, + size_t data_len); +#ifdef CONFIG_IEEE80211R + struct wpa_state_machine * (*add_sta)(void *ctx, const u8 *sta_addr); + int (*send_ft_action)(void *ctx, const u8 *dst, + const u8 *data, size_t data_len); + int (*add_tspec)(void *ctx, const u8 *sta_addr, u8 *tspec_ie, + size_t tspec_ielen); +#endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_MESH + int (*start_ampe)(void *ctx, const u8 *sta_addr); +#endif /* CONFIG_MESH */ +}; + +struct wpa_authenticator * wpa_init(const u8 *addr, + struct wpa_auth_config *conf, + struct wpa_auth_callbacks *cb); +int wpa_init_keys(struct wpa_authenticator *wpa_auth); +void wpa_deinit(struct wpa_authenticator *wpa_auth); +int wpa_reconfig(struct wpa_authenticator *wpa_auth, + struct wpa_auth_config *conf); + +enum { + WPA_IE_OK, WPA_INVALID_IE, WPA_INVALID_GROUP, WPA_INVALID_PAIRWISE, + WPA_INVALID_AKMP, WPA_NOT_ENABLED, WPA_ALLOC_FAIL, + WPA_MGMT_FRAME_PROTECTION_VIOLATION, WPA_INVALID_MGMT_GROUP_CIPHER, + WPA_INVALID_MDIE, WPA_INVALID_PROTO +}; + +int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, + struct wpa_state_machine *sm, + const u8 *wpa_ie, size_t wpa_ie_len, + const u8 *mdie, size_t mdie_len); +int wpa_validate_osen(struct wpa_authenticator *wpa_auth, + struct wpa_state_machine *sm, + const u8 *osen_ie, size_t osen_ie_len); +int wpa_auth_uses_mfp(struct wpa_state_machine *sm); +struct wpa_state_machine * +wpa_auth_sta_init(struct wpa_authenticator *wpa_auth, const u8 *addr, + const u8 *p2p_dev_addr); +int wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth, + struct wpa_state_machine *sm); +void wpa_auth_sta_no_wpa(struct wpa_state_machine *sm); +void wpa_auth_sta_deinit(struct wpa_state_machine *sm); +void wpa_receive(struct wpa_authenticator *wpa_auth, + struct wpa_state_machine *sm, + u8 *data, size_t data_len); +enum wpa_event { + WPA_AUTH, WPA_ASSOC, WPA_DISASSOC, WPA_DEAUTH, WPA_REAUTH, + WPA_REAUTH_EAPOL, WPA_ASSOC_FT, WPA_DRV_STA_REMOVED +}; +void wpa_remove_ptk(struct wpa_state_machine *sm); +int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event); +void wpa_auth_sm_notify(struct wpa_state_machine *sm); +void wpa_gtk_rekey(struct wpa_authenticator *wpa_auth); +int wpa_get_mib(struct wpa_authenticator *wpa_auth, char *buf, size_t buflen); +int wpa_get_mib_sta(struct wpa_state_machine *sm, char *buf, size_t buflen); +void wpa_auth_countermeasures_start(struct wpa_authenticator *wpa_auth); +int wpa_auth_pairwise_set(struct wpa_state_machine *sm); +int wpa_auth_get_pairwise(struct wpa_state_machine *sm); +int wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm); +int wpa_auth_sta_wpa_version(struct wpa_state_machine *sm); +int wpa_auth_sta_ft_tk_already_set(struct wpa_state_machine *sm); +int wpa_auth_sta_clear_pmksa(struct wpa_state_machine *sm, + struct rsn_pmksa_cache_entry *entry); +struct rsn_pmksa_cache_entry * +wpa_auth_sta_get_pmksa(struct wpa_state_machine *sm); +void wpa_auth_sta_local_mic_failure_report(struct wpa_state_machine *sm); +const u8 * wpa_auth_get_wpa_ie(struct wpa_authenticator *wpa_auth, + size_t *len); +int wpa_auth_pmksa_add(struct wpa_state_machine *sm, const u8 *pmk, + int session_timeout, struct eapol_state_machine *eapol); +int wpa_auth_pmksa_add_preauth(struct wpa_authenticator *wpa_auth, + const u8 *pmk, size_t len, const u8 *sta_addr, + int session_timeout, + struct eapol_state_machine *eapol); +int wpa_auth_pmksa_add_sae(struct wpa_authenticator *wpa_auth, const u8 *addr, + const u8 *pmk); +void wpa_auth_pmksa_remove(struct wpa_authenticator *wpa_auth, + const u8 *sta_addr); +int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id); +void wpa_auth_eapol_key_tx_status(struct wpa_authenticator *wpa_auth, + struct wpa_state_machine *sm, int ack); + +#ifdef CONFIG_IEEE80211R +u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, + size_t max_len, int auth_alg, + const u8 *req_ies, size_t req_ies_len); +void wpa_ft_process_auth(struct wpa_state_machine *sm, const u8 *bssid, + u16 auth_transaction, const u8 *ies, size_t ies_len, + void (*cb)(void *ctx, const u8 *dst, const u8 *bssid, + u16 auth_transaction, u16 resp, + const u8 *ies, size_t ies_len), + void *ctx); +u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, + size_t ies_len); +int wpa_ft_action_rx(struct wpa_state_machine *sm, const u8 *data, size_t len); +int wpa_ft_rrb_rx(struct wpa_authenticator *wpa_auth, const u8 *src_addr, + const u8 *data, size_t data_len); +void wpa_ft_push_pmk_r1(struct wpa_authenticator *wpa_auth, const u8 *addr); +#endif /* CONFIG_IEEE80211R */ + +void wpa_wnmsleep_rekey_gtk(struct wpa_state_machine *sm); +void wpa_set_wnmsleep(struct wpa_state_machine *sm, int flag); +int wpa_wnmsleep_gtk_subelem(struct wpa_state_machine *sm, u8 *pos); +int wpa_wnmsleep_igtk_subelem(struct wpa_state_machine *sm, u8 *pos); + +int wpa_auth_uses_sae(struct wpa_state_machine *sm); +int wpa_auth_uses_ft_sae(struct wpa_state_machine *sm); + +int wpa_auth_get_ip_addr(struct wpa_state_machine *sm, u8 *addr); + +struct radius_das_attrs; +int wpa_auth_radius_das_disconnect_pmksa(struct wpa_authenticator *wpa_auth, + struct radius_das_attrs *attr); +void wpa_auth_reconfig_group_keys(struct wpa_authenticator *wpa_auth); + +#endif /* WPA_AUTH_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/ap/wpa_auth_glue.c b/beken_os/beken378/func/hostapd-2.5/src/ap/wpa_auth_glue.c new file mode 100755 index 0000000..7b0c841 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/ap/wpa_auth_glue.c @@ -0,0 +1,677 @@ +/* + * hostapd / WPA authenticator glue code + * Copyright (c) 2002-2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "common/ieee802_11_defs.h" +#include "common/sae.h" +#include "common/wpa_ctrl.h" +#include "l2_packet/l2_packet.h" +#include "ap/hostapd.h" +#include "ieee802_1x.h" +#include "preauth_auth.h" +#include "ap/sta_info.h" +#include "tkip_countermeasures.h" +#include "ap_drv_ops.h" +#include "ap_config.h" +#include "wpa_auth.h" +#include "wpa_auth_glue.h" + + +static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf, + struct hostapd_config *iconf, + struct wpa_auth_config *wconf) +{ + os_memset(wconf, 0, sizeof(*wconf)); + wconf->wpa = conf->wpa; + wconf->wpa_key_mgmt = conf->wpa_key_mgmt; + wconf->wpa_pairwise = conf->wpa_pairwise; + wconf->wpa_group = conf->wpa_group; + wconf->wpa_group_rekey = conf->wpa_group_rekey; + wconf->wpa_strict_rekey = conf->wpa_strict_rekey; + wconf->wpa_gmk_rekey = conf->wpa_gmk_rekey; + wconf->wpa_ptk_rekey = conf->wpa_ptk_rekey; + wconf->rsn_pairwise = conf->rsn_pairwise; + wconf->rsn_preauth = conf->rsn_preauth; + wconf->eapol_version = conf->eapol_version; + wconf->peerkey = conf->peerkey; + wconf->wmm_enabled = conf->wmm_enabled; + wconf->wmm_uapsd = conf->wmm_uapsd; + wconf->disable_pmksa_caching = conf->disable_pmksa_caching; + wconf->okc = conf->okc; +#ifdef CONFIG_IEEE80211W + wconf->ieee80211w = conf->ieee80211w; + wconf->group_mgmt_cipher = conf->group_mgmt_cipher; +#endif /* CONFIG_IEEE80211W */ +#ifdef CONFIG_IEEE80211R + wconf->ssid_len = conf->ssid.ssid_len; + if (wconf->ssid_len > SSID_MAX_LEN) + wconf->ssid_len = SSID_MAX_LEN; + os_memcpy(wconf->ssid, conf->ssid.ssid, wconf->ssid_len); + os_memcpy(wconf->mobility_domain, conf->mobility_domain, + MOBILITY_DOMAIN_ID_LEN); + if (conf->nas_identifier && + os_strlen(conf->nas_identifier) <= FT_R0KH_ID_MAX_LEN) { + wconf->r0_key_holder_len = os_strlen(conf->nas_identifier); + os_memcpy(wconf->r0_key_holder, conf->nas_identifier, + wconf->r0_key_holder_len); + } + os_memcpy(wconf->r1_key_holder, conf->r1_key_holder, FT_R1KH_ID_LEN); + wconf->r0_key_lifetime = conf->r0_key_lifetime; + wconf->reassociation_deadline = conf->reassociation_deadline; + wconf->r0kh_list = conf->r0kh_list; + wconf->r1kh_list = conf->r1kh_list; + wconf->pmk_r1_push = conf->pmk_r1_push; + wconf->ft_over_ds = conf->ft_over_ds; +#endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_HS20 + wconf->disable_gtk = conf->disable_dgaf; + if (conf->osen) { + wconf->disable_gtk = 1; + wconf->wpa = WPA_PROTO_OSEN; + wconf->wpa_key_mgmt = WPA_KEY_MGMT_OSEN; + wconf->wpa_pairwise = 0; + wconf->wpa_group = WPA_CIPHER_CCMP; + wconf->rsn_pairwise = WPA_CIPHER_CCMP; + wconf->rsn_preauth = 0; + wconf->disable_pmksa_caching = 1; +#ifdef CONFIG_IEEE80211W + wconf->ieee80211w = 1; +#endif /* CONFIG_IEEE80211W */ + } +#endif /* CONFIG_HS20 */ +#ifdef CONFIG_TESTING_OPTIONS + wconf->corrupt_gtk_rekey_mic_probability = + iconf->corrupt_gtk_rekey_mic_probability; + if (conf->own_ie_override && + wpabuf_len(conf->own_ie_override) <= MAX_OWN_IE_OVERRIDE) { + wconf->own_ie_override_len = wpabuf_len(conf->own_ie_override); + os_memcpy(wconf->own_ie_override, + wpabuf_head(conf->own_ie_override), + wconf->own_ie_override_len); + } +#endif /* CONFIG_TESTING_OPTIONS */ +#ifdef CONFIG_P2P + os_memcpy(wconf->ip_addr_go, conf->ip_addr_go, 4); + os_memcpy(wconf->ip_addr_mask, conf->ip_addr_mask, 4); + os_memcpy(wconf->ip_addr_start, conf->ip_addr_start, 4); + os_memcpy(wconf->ip_addr_end, conf->ip_addr_end, 4); +#endif /* CONFIG_P2P */ +} + + +void hostapd_wpa_auth_logger(void *ctx, const u8 *addr, + logger_level level, const char *txt) +{ +#ifndef CONFIG_NO_HOSTAPD_LOGGER + struct hostapd_data *hapd = ctx; + int hlevel; + + switch (level) { + case LOGGER_WARNING: + hlevel = HOSTAPD_LEVEL_WARNING; + break; + case LOGGER_INFO: + hlevel = HOSTAPD_LEVEL_INFO; + break; + case LOGGER_DEBUG: + default: + hlevel = HOSTAPD_LEVEL_DEBUG; + break; + } + + hostapd_logger(hapd, addr, HOSTAPD_MODULE_WPA, hlevel, "%s", txt); +#endif /* CONFIG_NO_HOSTAPD_LOGGER */ +} + + +static void hostapd_wpa_auth_disconnect(void *ctx, const u8 *addr, + u16 reason) +{ + struct hostapd_data *hapd = ctx; + wpa_printf(MSG_DEBUG, "%s: WPA authenticator requests disconnect: " + "STA " MACSTR " reason %d", + __func__, MAC2STR(addr), reason); + ap_sta_disconnect(hapd, NULL, addr, reason); +} + + +static int hostapd_wpa_auth_mic_failure_report(void *ctx, const u8 *addr) +{ + struct hostapd_data *hapd = ctx; + return michael_mic_failure(hapd, addr, 0); +} + + +static void hostapd_wpa_auth_psk_failure_report(void *ctx, const u8 *addr) +{ + struct hostapd_data *hapd = ctx; + wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_POSSIBLE_PSK_MISMATCH MACSTR, + MAC2STR(addr)); + + (void)hapd; +} + + +static void hostapd_wpa_auth_set_eapol(void *ctx, const u8 *addr, + wpa_eapol_variable var, int value) +{ + struct hostapd_data *hapd = ctx; + struct sta_info *sta = ap_get_sta(hapd, addr); + if (sta == NULL) + return; + switch (var) { + case WPA_EAPOL_portEnabled: + ieee802_1x_notify_port_enabled(sta->eapol_sm, value); + break; + case WPA_EAPOL_portValid: + ieee802_1x_notify_port_valid(sta->eapol_sm, value); + break; + case WPA_EAPOL_authorized: + ieee802_1x_set_sta_authorized(hapd, sta, value); + break; +#ifdef CONFIG_FULL_HOSTAPD + case WPA_EAPOL_portControl_Auto: + if (sta->eapol_sm) + sta->eapol_sm->portControl = Auto; + break; + case WPA_EAPOL_keyRun: + if (sta->eapol_sm) + sta->eapol_sm->keyRun = value ? TRUE : FALSE; + break; + case WPA_EAPOL_keyAvailable: + if (sta->eapol_sm) + sta->eapol_sm->eap_if->eapKeyAvailable = + value ? TRUE : FALSE; + break; + case WPA_EAPOL_keyDone: + if (sta->eapol_sm) + sta->eapol_sm->keyDone = value ? TRUE : FALSE; + break; + case WPA_EAPOL_inc_EapolFramesTx: + if (sta->eapol_sm) + sta->eapol_sm->dot1xAuthEapolFramesTx++; + break; +#endif + default: + break; + } +} + + +static int hostapd_wpa_auth_get_eapol(void *ctx, const u8 *addr, + wpa_eapol_variable var) +{ + struct hostapd_data *hapd = ctx; + struct sta_info *sta = ap_get_sta(hapd, addr); + if (sta == NULL || sta->eapol_sm == NULL) + return -1; +#ifdef CONFIG_FULL_HOSTAPD + switch (var) { + case WPA_EAPOL_keyRun: + return sta->eapol_sm->keyRun; + case WPA_EAPOL_keyAvailable: + return sta->eapol_sm->eap_if->eapKeyAvailable; + default: + return -1; + } +#endif + return -1; +} + + +static const u8 * hostapd_wpa_auth_get_psk(void *ctx, const u8 *addr, + const u8 *p2p_dev_addr, + const u8 *prev_psk) +{ + struct hostapd_data *hapd = ctx; + struct sta_info *sta = ap_get_sta(hapd, addr); + const u8 *psk; + +#ifdef CONFIG_SAE + if (sta && sta->auth_alg == WLAN_AUTH_SAE) { + if (!sta->sae || prev_psk) + return NULL; + return sta->sae->pmk; + } +#endif /* CONFIG_SAE */ + + psk = hostapd_get_psk(hapd->conf, addr, p2p_dev_addr, prev_psk); + /* + * This is about to iterate over all psks, prev_psk gives the last + * returned psk which should not be returned again. + * logic list (all hostapd_get_psk; all sta->psk) + */ + if (sta && sta->psk && !psk) { + struct hostapd_sta_wpa_psk_short *pos; + psk = sta->psk->psk; + for (pos = sta->psk; pos; pos = pos->next) { + if (pos->psk == prev_psk) { + psk = pos->next ? pos->next->psk : NULL; + break; + } + } + } + return psk; +} + + +static int hostapd_wpa_auth_get_msk(void *ctx, const u8 *addr, u8 *msk, + size_t *len) +{ + return -1; +} + + +static int hostapd_wpa_auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg, + const u8 *addr, int idx, u8 *key, + size_t key_len) +{ + struct hostapd_data *hapd = ctx; + const char *ifname = hapd->conf->iface; + +#ifdef CONFIG_FULL_HOSTAPD + if (vlan_id > 0) { + ifname = hostapd_get_vlan_id_ifname(hapd->conf->vlan, vlan_id); + if (ifname == NULL) + return -1; + } +#endif + return hostapd_drv_set_key(ifname, hapd, alg, addr, idx, 1, NULL, 0, + key, key_len); +} + + +static int hostapd_wpa_auth_get_seqnum(void *ctx, const u8 *addr, int idx, + u8 *seq) +{ + struct hostapd_data *hapd = ctx; + return hostapd_get_seqnum(hapd->conf->iface, hapd, addr, idx, seq); +} + + +static int hostapd_wpa_auth_send_eapol(void *ctx, const u8 *addr, + const u8 *data, size_t data_len, + int encrypt) +{ + struct hostapd_data *hapd = ctx; + struct sta_info *sta; + u32 flags = 0; + +#ifdef CONFIG_TESTING_OPTIONS + if (hapd->ext_eapol_frame_io) { + size_t hex_len = 2 * data_len + 1; + char *hex = os_malloc(hex_len); + + if (hex == NULL) + return -1; + wpa_snprintf_hex(hex, hex_len, data, data_len); + wpa_msg(hapd->msg_ctx, MSG_INFO, "EAPOL-TX " MACSTR " %s", + MAC2STR(addr), hex); + os_free(hex); + return 0; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + sta = ap_get_sta(hapd, addr); + if (sta) + flags = hostapd_sta_flags_to_drv(sta->flags); + + return hostapd_drv_hapd_send_eapol(hapd, addr, data, data_len, + encrypt, flags); +} + + +static int hostapd_wpa_auth_for_each_sta( + void *ctx, int (*cb)(struct wpa_state_machine *sm, void *ctx), + void *cb_ctx) +{ + struct hostapd_data *hapd = ctx; + struct sta_info *sta; + + for (sta = hapd->sta_list; sta; sta = sta->next) { + if (sta->wpa_sm && cb(sta->wpa_sm, cb_ctx)) + return 1; + } + return 0; +} + + +struct wpa_auth_iface_iter_data { + int (*cb)(struct wpa_authenticator *sm, void *ctx); + void *cb_ctx; +}; + +static int wpa_auth_iface_iter(struct hostapd_iface *iface, void *ctx) +{ + struct wpa_auth_iface_iter_data *data = ctx; + size_t i; + for (i = 0; i < iface->num_bss; i++) { + if (iface->bss[i]->wpa_auth && + data->cb(iface->bss[i]->wpa_auth, data->cb_ctx)) + return 1; + } + return 0; +} + + +static int hostapd_wpa_auth_for_each_auth( + void *ctx, int (*cb)(struct wpa_authenticator *sm, void *ctx), + void *cb_ctx) +{ + struct hostapd_data *hapd = ctx; + struct wpa_auth_iface_iter_data data; + if (hapd->iface->interfaces == NULL || + hapd->iface->interfaces->for_each_interface == NULL) + return -1; + data.cb = cb; + data.cb_ctx = cb_ctx; + return hapd->iface->interfaces->for_each_interface( + hapd->iface->interfaces, wpa_auth_iface_iter, &data); +} + + +#ifdef CONFIG_IEEE80211R + +struct wpa_auth_ft_iface_iter_data { + struct hostapd_data *src_hapd; + const u8 *dst; + const u8 *data; + size_t data_len; +}; + + +static int hostapd_wpa_auth_ft_iter(struct hostapd_iface *iface, void *ctx) +{ + struct wpa_auth_ft_iface_iter_data *idata = ctx; + struct hostapd_data *hapd; + size_t j; + + for (j = 0; j < iface->num_bss; j++) { + hapd = iface->bss[j]; + if (hapd == idata->src_hapd) + continue; + if (os_memcmp(hapd->own_addr, idata->dst, ETH_ALEN) == 0) { + wpa_printf(MSG_DEBUG, "FT: Send RRB data directly to " + "locally managed BSS " MACSTR "@%s -> " + MACSTR "@%s", + MAC2STR(idata->src_hapd->own_addr), + idata->src_hapd->conf->iface, + MAC2STR(hapd->own_addr), hapd->conf->iface); + wpa_ft_rrb_rx(hapd->wpa_auth, + idata->src_hapd->own_addr, + idata->data, idata->data_len); + return 1; + } + } + + return 0; +} + +#endif /* CONFIG_IEEE80211R */ + + +static int hostapd_wpa_auth_send_ether(void *ctx, const u8 *dst, u16 proto, + const u8 *data, size_t data_len) +{ + struct hostapd_data *hapd = ctx; + struct l2_ethhdr *buf; + int ret; + +#ifdef CONFIG_TESTING_OPTIONS + if (hapd->ext_eapol_frame_io && proto == ETH_P_EAPOL) { + size_t hex_len = 2 * data_len + 1; + char *hex = os_malloc(hex_len); + + if (hex == NULL) + return -1; + wpa_snprintf_hex(hex, hex_len, data, data_len); + wpa_msg(hapd->msg_ctx, MSG_INFO, "EAPOL-TX " MACSTR " %s", + MAC2STR(dst), hex); + os_free(hex); + return 0; + } +#endif /* CONFIG_TESTING_OPTIONS */ + +#ifdef CONFIG_IEEE80211R + if (proto == ETH_P_RRB && hapd->iface->interfaces && + hapd->iface->interfaces->for_each_interface) { + int res; + struct wpa_auth_ft_iface_iter_data idata; + idata.src_hapd = hapd; + idata.dst = dst; + idata.data = data; + idata.data_len = data_len; + res = hapd->iface->interfaces->for_each_interface( + hapd->iface->interfaces, hostapd_wpa_auth_ft_iter, + &idata); + if (res == 1) + return data_len; + } +#endif /* CONFIG_IEEE80211R */ + + if (hapd->driver && hapd->driver->send_ether) + return hapd->driver->send_ether(hapd->drv_priv, dst, + hapd->own_addr, proto, + data, data_len); + if (hapd->l2 == NULL) + return -1; + + buf = os_malloc(sizeof(*buf) + data_len); + if (buf == NULL) + return -1; + os_memcpy(buf->h_dest, dst, ETH_ALEN); + os_memcpy(buf->h_source, hapd->own_addr, ETH_ALEN); + buf->h_proto = host_to_be16(proto); + os_memcpy(buf + 1, data, data_len); + ret = l2_packet_send(hapd->l2, dst, proto, (u8 *) buf, + sizeof(*buf) + data_len); + os_free(buf); + return ret; +} + + +#ifdef CONFIG_IEEE80211R + +static int hostapd_wpa_auth_send_ft_action(void *ctx, const u8 *dst, + const u8 *data, size_t data_len) +{ + struct hostapd_data *hapd = ctx; + int res; + struct ieee80211_mgmt *m; + size_t mlen; + struct sta_info *sta; + + sta = ap_get_sta(hapd, dst); + if (sta == NULL || sta->wpa_sm == NULL) + return -1; + + m = os_zalloc(sizeof(*m) + data_len); + if (m == NULL) + return -1; + mlen = ((u8 *) &m->u - (u8 *) m) + data_len; + m->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, + WLAN_FC_STYPE_ACTION); + os_memcpy(m->da, dst, ETH_ALEN); + os_memcpy(m->sa, hapd->own_addr, ETH_ALEN); + os_memcpy(m->bssid, hapd->own_addr, ETH_ALEN); + os_memcpy(&m->u, data, data_len); + + res = hostapd_drv_send_mlme(hapd, (u8 *) m, mlen, 0); + os_free(m); + return res; +} + + +static struct wpa_state_machine * +hostapd_wpa_auth_add_sta(void *ctx, const u8 *sta_addr) +{ + struct hostapd_data *hapd = ctx; + struct sta_info *sta; + + if (hostapd_add_sta_node(hapd, sta_addr, WLAN_AUTH_FT) < 0) + return NULL; + + sta = ap_sta_add(hapd, sta_addr); + if (sta == NULL) + return NULL; + if (sta->wpa_sm) { + sta->auth_alg = WLAN_AUTH_FT; + return sta->wpa_sm; + } + + sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, sta->addr, NULL); + if (sta->wpa_sm == NULL) { + ap_free_sta(hapd, sta); + return NULL; + } + sta->auth_alg = WLAN_AUTH_FT; + + return sta->wpa_sm; +} + + +static void hostapd_rrb_receive(void *ctx, const u8 *src_addr, const u8 *buf, + size_t len) +{ + struct hostapd_data *hapd = ctx; + struct l2_ethhdr *ethhdr; + if (len < sizeof(*ethhdr)) + return; + ethhdr = (struct l2_ethhdr *) buf; + wpa_printf(MSG_DEBUG, "FT: RRB received packet " MACSTR " -> " + MACSTR, MAC2STR(ethhdr->h_source), MAC2STR(ethhdr->h_dest)); + wpa_ft_rrb_rx(hapd->wpa_auth, ethhdr->h_source, buf + sizeof(*ethhdr), + len - sizeof(*ethhdr)); +} + + +static int hostapd_wpa_auth_add_tspec(void *ctx, const u8 *sta_addr, + u8 *tspec_ie, size_t tspec_ielen) +{ + struct hostapd_data *hapd = ctx; + return hostapd_add_tspec(hapd, sta_addr, tspec_ie, tspec_ielen); +} + +#endif /* CONFIG_IEEE80211R */ + + +int hostapd_setup_wpa(struct hostapd_data *hapd) +{ + struct wpa_auth_config _conf; + struct wpa_auth_callbacks cb; + const u8 *wpa_ie; + size_t wpa_ie_len; + + hostapd_wpa_auth_conf(hapd->conf, hapd->iconf, &_conf); + if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_EAPOL_TX_STATUS) + _conf.tx_status = 1; + if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_MLME) + _conf.ap_mlme = 1; + os_memset(&cb, 0, sizeof(cb)); + cb.ctx = hapd; + //cb.logger = hostapd_wpa_auth_logger; + cb.disconnect = hostapd_wpa_auth_disconnect; + cb.mic_failure_report = hostapd_wpa_auth_mic_failure_report; + cb.psk_failure_report = hostapd_wpa_auth_psk_failure_report; + cb.set_eapol = hostapd_wpa_auth_set_eapol; + cb.get_eapol = hostapd_wpa_auth_get_eapol; + cb.get_psk = hostapd_wpa_auth_get_psk; + cb.get_msk = hostapd_wpa_auth_get_msk; + cb.set_key = hostapd_wpa_auth_set_key; + cb.get_seqnum = hostapd_wpa_auth_get_seqnum; + cb.send_eapol = hostapd_wpa_auth_send_eapol; + cb.for_each_sta = hostapd_wpa_auth_for_each_sta; + cb.for_each_auth = hostapd_wpa_auth_for_each_auth; + cb.send_ether = hostapd_wpa_auth_send_ether; +#ifdef CONFIG_IEEE80211R + cb.send_ft_action = hostapd_wpa_auth_send_ft_action; + cb.add_sta = hostapd_wpa_auth_add_sta; + cb.add_tspec = hostapd_wpa_auth_add_tspec; +#endif /* CONFIG_IEEE80211R */ + hapd->wpa_auth = wpa_init(hapd->own_addr, &_conf, &cb); + if (hapd->wpa_auth == NULL) { + wpa_printf(MSG_ERROR, "WPA initialization failed."); + return -1; + } + + if (hostapd_set_privacy(hapd, 1)) { + wpa_printf(MSG_ERROR, "Could not set PrivacyInvoked " + "for interface %s", hapd->conf->iface); + return -1; + } + + wpa_ie = wpa_auth_get_wpa_ie(hapd->wpa_auth, &wpa_ie_len); + if (hostapd_set_generic_elem(hapd, wpa_ie, wpa_ie_len)) { + wpa_printf(MSG_ERROR, "Failed to configure WPA IE for " + "the kernel driver."); + return -1; + } + + if (rsn_preauth_iface_init(hapd)) { + wpa_printf(MSG_ERROR, "Initialization of RSN " + "pre-authentication failed."); + return -1; + } + +#ifdef CONFIG_IEEE80211R + if (!hostapd_drv_none(hapd) && hapd->conf->ft_over_ds && + wpa_key_mgmt_ft(hapd->conf->wpa_key_mgmt)) { + hapd->l2 = l2_packet_init(hapd->conf->bridge[0] ? + hapd->conf->bridge : + hapd->conf->iface, NULL, ETH_P_RRB, + hostapd_rrb_receive, hapd, 1); + if (hapd->l2 == NULL && + (hapd->driver == NULL || + hapd->driver->send_ether == NULL)) { + wpa_printf(MSG_ERROR, "Failed to open l2_packet " + "interface"); + return -1; + } + } +#endif /* CONFIG_IEEE80211R */ + + return 0; + +} + + +void hostapd_reconfig_wpa(struct hostapd_data *hapd) +{ + struct wpa_auth_config wpa_auth_conf; + hostapd_wpa_auth_conf(hapd->conf, hapd->iconf, &wpa_auth_conf); + wpa_reconfig(hapd->wpa_auth, &wpa_auth_conf); +} + + +void hostapd_deinit_wpa(struct hostapd_data *hapd) +{ + ieee80211_tkip_countermeasures_deinit(hapd); + rsn_preauth_iface_deinit(hapd); + if (hapd->wpa_auth) { + wpa_deinit(hapd->wpa_auth); + hapd->wpa_auth = NULL; + + if (hostapd_set_privacy(hapd, 0)) { + wpa_printf(MSG_DEBUG, "Could not disable " + "PrivacyInvoked for interface %s", + hapd->conf->iface); + } + + if (hostapd_set_generic_elem(hapd, (u8 *) "", 0)) { + wpa_printf(MSG_DEBUG, "Could not remove generic " + "information element from interface %s", + hapd->conf->iface); + } + } +#ifdef CONFIG_IEEE80211R + l2_packet_deinit(hapd->l2); + hapd->l2 = NULL; +#endif /* CONFIG_IEEE80211R */ +} diff --git a/beken_os/beken378/func/hostapd-2.5/src/ap/wpa_auth_glue.h b/beken_os/beken378/func/hostapd-2.5/src/ap/wpa_auth_glue.h new file mode 100755 index 0000000..1b13ae7 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/ap/wpa_auth_glue.h @@ -0,0 +1,16 @@ +/* + * hostapd / WPA authenticator glue code + * Copyright (c) 2002-2009, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef WPA_AUTH_GLUE_H +#define WPA_AUTH_GLUE_H + +int hostapd_setup_wpa(struct hostapd_data *hapd); +void hostapd_reconfig_wpa(struct hostapd_data *hapd); +void hostapd_deinit_wpa(struct hostapd_data *hapd); + +#endif /* WPA_AUTH_GLUE_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/ap/wpa_auth_i.h b/beken_os/beken378/func/hostapd-2.5/src/ap/wpa_auth_i.h new file mode 100755 index 0000000..9544eab --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/ap/wpa_auth_i.h @@ -0,0 +1,265 @@ +/* + * hostapd - IEEE 802.11i-2004 / WPA Authenticator: Internal definitions + * Copyright (c) 2004-2015, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef WPA_AUTH_I_H +#define WPA_AUTH_I_H + +/* max(dot11RSNAConfigGroupUpdateCount,dot11RSNAConfigPairwiseUpdateCount) */ +#define RSNA_MAX_EAPOL_RETRIES 4 + +struct wpa_group; + +struct wpa_stsl_negotiation { + struct wpa_stsl_negotiation *next; + u8 initiator[ETH_ALEN]; + u8 peer[ETH_ALEN]; +}; + + +struct wpa_state_machine { + struct wpa_authenticator *wpa_auth; + struct wpa_group *group; + + u8 addr[ETH_ALEN]; + u8 p2p_dev_addr[ETH_ALEN]; + + enum { + WPA_PTK_INITIALIZE, WPA_PTK_DISCONNECT, WPA_PTK_DISCONNECTED, + WPA_PTK_AUTHENTICATION, WPA_PTK_AUTHENTICATION2, + WPA_PTK_INITPMK, WPA_PTK_INITPSK, WPA_PTK_PTKSTART, + WPA_PTK_PTKCALCNEGOTIATING, WPA_PTK_PTKCALCNEGOTIATING2, + WPA_PTK_PTKINITNEGOTIATING, WPA_PTK_PTKINITDONE + } wpa_ptk_state; + + enum { + WPA_PTK_GROUP_IDLE = 0, + WPA_PTK_GROUP_REKEYNEGOTIATING, + WPA_PTK_GROUP_REKEYESTABLISHED, + WPA_PTK_GROUP_KEYERROR + } wpa_ptk_group_state; + + Boolean Init; + Boolean DeauthenticationRequest; + Boolean AuthenticationRequest; + Boolean ReAuthenticationRequest; + Boolean Disconnect; + int TimeoutCtr; + int GTimeoutCtr; + Boolean TimeoutEvt; + Boolean EAPOLKeyReceived; + Boolean EAPOLKeyPairwise; + Boolean EAPOLKeyRequest; + Boolean MICVerified; + Boolean GUpdateStationKeys; + u8 ANonce[WPA_NONCE_LEN]; + u8 SNonce[WPA_NONCE_LEN]; + u8 alt_SNonce[WPA_NONCE_LEN]; + u8 alt_replay_counter[WPA_REPLAY_COUNTER_LEN]; + u8 PMK[PMK_LEN]; + struct wpa_ptk PTK; + Boolean PTK_valid; + Boolean pairwise_set; + Boolean tk_already_set; + int keycount; + Boolean Pair; + struct wpa_key_replay_counter { + u8 counter[WPA_REPLAY_COUNTER_LEN]; + Boolean valid; + } key_replay[RSNA_MAX_EAPOL_RETRIES], + prev_key_replay[RSNA_MAX_EAPOL_RETRIES]; + Boolean PInitAKeys; /* WPA only, not in IEEE 802.11i */ + Boolean PTKRequest; /* not in IEEE 802.11i state machine */ + Boolean has_GTK; + Boolean PtkGroupInit; /* init request for PTK Group state machine */ + + u8 *last_rx_eapol_key; /* starting from IEEE 802.1X header */ + size_t last_rx_eapol_key_len; + + unsigned int changed:1; + unsigned int in_step_loop:1; + unsigned int pending_deinit:1; + unsigned int started:1; + unsigned int mgmt_frame_prot:1; + unsigned int rx_eapol_key_secure:1; + unsigned int update_snonce:1; + unsigned int alt_snonce_valid:1; +#ifdef CONFIG_IEEE80211R + unsigned int ft_completed:1; + unsigned int pmk_r1_name_valid:1; +#endif /* CONFIG_IEEE80211R */ + unsigned int is_wnmsleep:1; + + u8 req_replay_counter[WPA_REPLAY_COUNTER_LEN]; + int req_replay_counter_used; + + u8 *wpa_ie; + size_t wpa_ie_len; + + enum { + WPA_VERSION_NO_WPA = 0 /* WPA not used */, + WPA_VERSION_WPA = 1 /* WPA / IEEE 802.11i/D3.0 */, + WPA_VERSION_WPA2 = 2 /* WPA2 / IEEE 802.11i */ + } wpa; + int pairwise; /* Pairwise cipher suite, WPA_CIPHER_* */ + int wpa_key_mgmt; /* the selected WPA_KEY_MGMT_* */ + struct rsn_pmksa_cache_entry *pmksa; + + u32 dot11RSNAStatsTKIPLocalMICFailures; + u32 dot11RSNAStatsTKIPRemoteMICFailures; + +#ifdef CONFIG_IEEE80211R + u8 xxkey[PMK_LEN]; /* PSK or the second 256 bits of MSK */ + size_t xxkey_len; + u8 pmk_r1_name[WPA_PMK_NAME_LEN]; /* PMKR1Name derived from FT Auth + * Request */ + u8 r0kh_id[FT_R0KH_ID_MAX_LEN]; /* R0KH-ID from FT Auth Request */ + size_t r0kh_id_len; + u8 sup_pmk_r1_name[WPA_PMK_NAME_LEN]; /* PMKR1Name from EAPOL-Key + * message 2/4 */ + u8 *assoc_resp_ftie; + + void (*ft_pending_cb)(void *ctx, const u8 *dst, const u8 *bssid, + u16 auth_transaction, u16 status, + const u8 *ies, size_t ies_len); + void *ft_pending_cb_ctx; + struct wpabuf *ft_pending_req_ies; + u8 ft_pending_pull_nonce[FT_R0KH_R1KH_PULL_NONCE_LEN]; + u8 ft_pending_auth_transaction; + u8 ft_pending_current_ap[ETH_ALEN]; +#endif /* CONFIG_IEEE80211R */ + + int pending_1_of_4_timeout; + +#ifdef CONFIG_P2P + u8 ip_addr[4]; +#endif /* CONFIG_P2P */ +}; + + +/* per group key state machine data */ +struct wpa_group { + struct wpa_group *next; + int vlan_id; + + Boolean GInit; + int GKeyDoneStations; + Boolean GTKReKey; + int GTK_len; + int GN, GM; + Boolean GTKAuthenticator; + u8 Counter[WPA_NONCE_LEN]; + + enum { + WPA_GROUP_GTK_INIT = 0, + WPA_GROUP_SETKEYS, WPA_GROUP_SETKEYSDONE, + WPA_GROUP_FATAL_FAILURE + } wpa_group_state; + + u8 GMK[WPA_GMK_LEN]; + u8 GTK[2][WPA_GTK_MAX_LEN]; + u8 GNonce[WPA_NONCE_LEN]; + Boolean changed; + Boolean first_sta_seen; + Boolean reject_4way_hs_for_entropy; +#ifdef CONFIG_IEEE80211W + u8 IGTK[2][WPA_IGTK_MAX_LEN]; + int GN_igtk, GM_igtk; +#endif /* CONFIG_IEEE80211W */ + /* Number of references except those in struct wpa_group->next */ + unsigned int references; +}; + + +struct wpa_ft_pmk_cache; + +/* per authenticator data */ +struct wpa_authenticator { + struct wpa_group *group; + + unsigned int dot11RSNAStatsTKIPRemoteMICFailures; + u32 dot11RSNAAuthenticationSuiteSelected; + u32 dot11RSNAPairwiseCipherSelected; + u32 dot11RSNAGroupCipherSelected; + u8 dot11RSNAPMKIDUsed[PMKID_LEN]; + u32 dot11RSNAAuthenticationSuiteRequested; /* FIX: update */ + u32 dot11RSNAPairwiseCipherRequested; /* FIX: update */ + u32 dot11RSNAGroupCipherRequested; /* FIX: update */ + unsigned int dot11RSNATKIPCounterMeasuresInvoked; + unsigned int dot11RSNA4WayHandshakeFailures; + + struct wpa_stsl_negotiation *stsl_negotiations; + + struct wpa_auth_config conf; + struct wpa_auth_callbacks cb; + + u8 *wpa_ie; + size_t wpa_ie_len; + + u8 addr[ETH_ALEN]; + + struct rsn_pmksa_cache *pmksa; + struct wpa_ft_pmk_cache *ft_pmk_cache; + +#ifdef CONFIG_P2P + struct bitfield *ip_pool; +#endif /* CONFIG_P2P */ +}; + + +int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len, + const u8 *pmkid); +#if 0 == CFG_ENABLE_WPA_LOG +#define wpa_auth_logger(args...) do {} while (0) +#define wpa_auth_vlogger(args...) do {} while (0) +#else +void wpa_auth_logger(struct wpa_authenticator *wpa_auth, const u8 *addr, + logger_level level, const char *txt); +void wpa_auth_vlogger(struct wpa_authenticator *wpa_auth, const u8 *addr, + logger_level level, const char *fmt, ...); +#endif +void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, + struct wpa_state_machine *sm, int key_info, + const u8 *key_rsc, const u8 *nonce, + const u8 *kde, size_t kde_len, + int keyidx, int encr, int force_version); +int wpa_auth_for_each_sta(struct wpa_authenticator *wpa_auth, + int (*cb)(struct wpa_state_machine *sm, void *ctx), + void *cb_ctx); +int wpa_auth_for_each_auth(struct wpa_authenticator *wpa_auth, + int (*cb)(struct wpa_authenticator *a, void *ctx), + void *cb_ctx); + +#ifdef CONFIG_PEERKEY +int wpa_stsl_remove(struct wpa_authenticator *wpa_auth, + struct wpa_stsl_negotiation *neg); +void wpa_smk_error(struct wpa_authenticator *wpa_auth, + struct wpa_state_machine *sm, + const u8 *key_data, size_t key_data_len); +void wpa_smk_m1(struct wpa_authenticator *wpa_auth, + struct wpa_state_machine *sm, struct wpa_eapol_key *key, + const u8 *key_data, size_t key_data_len); +void wpa_smk_m3(struct wpa_authenticator *wpa_auth, + struct wpa_state_machine *sm, struct wpa_eapol_key *key, + const u8 *key_data, size_t key_data_len); +#endif /* CONFIG_PEERKEY */ + +#ifdef CONFIG_IEEE80211R +int wpa_write_mdie(struct wpa_auth_config *conf, u8 *buf, size_t len); +int wpa_write_ftie(struct wpa_auth_config *conf, const u8 *r0kh_id, + size_t r0kh_id_len, + const u8 *anonce, const u8 *snonce, + u8 *buf, size_t len, const u8 *subelem, + size_t subelem_len); +int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, const u8 *pmk, + struct wpa_ptk *ptk); +struct wpa_ft_pmk_cache * wpa_ft_pmk_cache_init(void); +void wpa_ft_pmk_cache_deinit(struct wpa_ft_pmk_cache *cache); +void wpa_ft_install_ptk(struct wpa_state_machine *sm); +#endif /* CONFIG_IEEE80211R */ + +#endif /* WPA_AUTH_I_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/ap/wpa_auth_ie.c b/beken_os/beken378/func/hostapd-2.5/src/ap/wpa_auth_ie.c new file mode 100755 index 0000000..0c3099e --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/ap/wpa_auth_ie.c @@ -0,0 +1,752 @@ +/* + * hostapd - WPA/RSN IE and KDE definitions + * Copyright (c) 2004-2015, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "common/ieee802_11_defs.h" +#include "ap_config.h" +#include "ieee802_11.h" +#include "wpa_auth.h" +#include "wpa_auth_ie.h" +#include "wpa_auth_i.h" + + +#ifdef CONFIG_RSN_TESTING +int rsn_testing = 0; +#endif /* CONFIG_RSN_TESTING */ + + +static int wpa_write_wpa_ie(struct wpa_auth_config *conf, u8 *buf, size_t len) +{ + struct wpa_ie_hdr *hdr; + int num_suites; + u8 *pos, *count; + u32 suite; + + hdr = (struct wpa_ie_hdr *) buf; + hdr->elem_id = WLAN_EID_VENDOR_SPECIFIC; + RSN_SELECTOR_PUT(hdr->oui, WPA_OUI_TYPE); + WPA_PUT_LE16(hdr->version, WPA_VERSION); + pos = (u8 *) (hdr + 1); + + suite = wpa_cipher_to_suite(WPA_PROTO_WPA, conf->wpa_group); + if (suite == 0) { + wpa_printf(MSG_DEBUG, "Invalid group cipher (%d).", + conf->wpa_group); + return -1; + } + RSN_SELECTOR_PUT(pos, suite); + pos += WPA_SELECTOR_LEN; + + count = pos; + pos += 2; + + num_suites = wpa_cipher_put_suites(pos, conf->wpa_pairwise); + if (num_suites == 0) { + wpa_printf(MSG_DEBUG, "Invalid pairwise cipher (%d).", + conf->wpa_pairwise); + return -1; + } + pos += num_suites * WPA_SELECTOR_LEN; + WPA_PUT_LE16(count, num_suites); + + num_suites = 0; + count = pos; + pos += 2; + + if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) { + RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_UNSPEC_802_1X); + pos += WPA_SELECTOR_LEN; + num_suites++; + } + if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) { + RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X); + pos += WPA_SELECTOR_LEN; + num_suites++; + } + + if (num_suites == 0) { + wpa_printf(MSG_DEBUG, "Invalid key management type (%d).", + conf->wpa_key_mgmt); + return -1; + } + WPA_PUT_LE16(count, num_suites); + + /* WPA Capabilities; use defaults, so no need to include it */ + + hdr->len = (pos - buf) - 2; + + return pos - buf; +} + + +int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len, + const u8 *pmkid) +{ + struct rsn_ie_hdr *hdr; + int num_suites, res; + u8 *pos, *count; + u16 capab; + u32 suite; + + hdr = (struct rsn_ie_hdr *) buf; + hdr->elem_id = WLAN_EID_RSN; + WPA_PUT_LE16(hdr->version, RSN_VERSION); + pos = (u8 *) (hdr + 1); + + suite = wpa_cipher_to_suite(WPA_PROTO_RSN, conf->wpa_group); + if (suite == 0) { + wpa_printf(MSG_DEBUG, "Invalid group cipher (%d).", + conf->wpa_group); + return -1; + } + RSN_SELECTOR_PUT(pos, suite); + pos += RSN_SELECTOR_LEN; + + num_suites = 0; + count = pos; + pos += 2; + +#ifdef CONFIG_RSN_TESTING + if (rsn_testing) { + RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 1)); + pos += RSN_SELECTOR_LEN; + num_suites++; + } +#endif /* CONFIG_RSN_TESTING */ + + res = rsn_cipher_put_suites(pos, conf->rsn_pairwise); + num_suites += res; + pos += res * RSN_SELECTOR_LEN; + +#ifdef CONFIG_RSN_TESTING + if (rsn_testing) { + RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 2)); + pos += RSN_SELECTOR_LEN; + num_suites++; + } +#endif /* CONFIG_RSN_TESTING */ + + if (num_suites == 0) { + wpa_printf(MSG_DEBUG, "Invalid pairwise cipher (%d).", + conf->rsn_pairwise); + return -1; + } + WPA_PUT_LE16(count, num_suites); + + num_suites = 0; + count = pos; + pos += 2; + +#ifdef CONFIG_RSN_TESTING + if (rsn_testing) { + RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 1)); + pos += RSN_SELECTOR_LEN; + num_suites++; + } +#endif /* CONFIG_RSN_TESTING */ + + if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X); + pos += RSN_SELECTOR_LEN; + num_suites++; + } + if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X); + pos += RSN_SELECTOR_LEN; + num_suites++; + } +#ifdef CONFIG_IEEE80211R + if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X); + pos += RSN_SELECTOR_LEN; + num_suites++; + } + if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_PSK); + pos += RSN_SELECTOR_LEN; + num_suites++; + } +#endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_IEEE80211W + if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SHA256); + pos += RSN_SELECTOR_LEN; + num_suites++; + } + if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_SHA256); + pos += RSN_SELECTOR_LEN; + num_suites++; + } +#endif /* CONFIG_IEEE80211W */ +#ifdef CONFIG_SAE + if (conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_SAE); + pos += RSN_SELECTOR_LEN; + num_suites++; + } + if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_SAE) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_SAE); + pos += RSN_SELECTOR_LEN; + num_suites++; + } +#endif /* CONFIG_SAE */ + +#ifdef CONFIG_RSN_TESTING + if (rsn_testing) { + RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 2)); + pos += RSN_SELECTOR_LEN; + num_suites++; + } +#endif /* CONFIG_RSN_TESTING */ + + if (num_suites == 0) { + wpa_printf(MSG_DEBUG, "Invalid key management type (%d).", + conf->wpa_key_mgmt); + return -1; + } + WPA_PUT_LE16(count, num_suites); + + /* RSN Capabilities */ + capab = 0; + if (conf->rsn_preauth) + capab |= WPA_CAPABILITY_PREAUTH; + if (conf->peerkey) + capab |= WPA_CAPABILITY_PEERKEY_ENABLED; + if (conf->wmm_enabled) { + /* 4 PTKSA replay counters when using WMM */ + capab |= (RSN_NUM_REPLAY_COUNTERS_16 << 2); + } +#ifdef CONFIG_IEEE80211W + if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) { + capab |= WPA_CAPABILITY_MFPC; + if (conf->ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED) + capab |= WPA_CAPABILITY_MFPR; + } +#endif /* CONFIG_IEEE80211W */ +#ifdef CONFIG_RSN_TESTING + if (rsn_testing) + capab |= BIT(8) | BIT(14) | BIT(15); +#endif /* CONFIG_RSN_TESTING */ + WPA_PUT_LE16(pos, capab); + pos += 2; + + if (pmkid) { + if (pos + 2 + PMKID_LEN > buf + len) + return -1; + /* PMKID Count */ + WPA_PUT_LE16(pos, 1); + pos += 2; + os_memcpy(pos, pmkid, PMKID_LEN); + pos += PMKID_LEN; + } + +#ifdef CONFIG_IEEE80211W + if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION && + conf->group_mgmt_cipher != WPA_CIPHER_AES_128_CMAC) { + if (pos + 2 + 4 > buf + len) + return -1; + if (pmkid == NULL) { + /* PMKID Count */ + WPA_PUT_LE16(pos, 0); + pos += 2; + } + + /* Management Group Cipher Suite */ + switch (conf->group_mgmt_cipher) { + case WPA_CIPHER_AES_128_CMAC: + RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC); + break; + case WPA_CIPHER_BIP_GMAC_128: + RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_BIP_GMAC_128); + break; + case WPA_CIPHER_BIP_GMAC_256: + RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_BIP_GMAC_256); + break; + case WPA_CIPHER_BIP_CMAC_256: + RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_BIP_CMAC_256); + break; + default: + wpa_printf(MSG_DEBUG, + "Invalid group management cipher (0x%x)", + conf->group_mgmt_cipher); + return -1; + } + pos += RSN_SELECTOR_LEN; + } +#endif /* CONFIG_IEEE80211W */ + +#ifdef CONFIG_RSN_TESTING + if (rsn_testing) { + /* + * Fill in any defined fields and add extra data to the end of + * the element. + */ + int pmkid_count_set = pmkid != NULL; + if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) + pmkid_count_set = 1; + /* PMKID Count */ + WPA_PUT_LE16(pos, 0); + pos += 2; + if (conf->ieee80211w == NO_MGMT_FRAME_PROTECTION) { + /* Management Group Cipher Suite */ + RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC); + pos += RSN_SELECTOR_LEN; + } + + os_memset(pos, 0x12, 17); + pos += 17; + } +#endif /* CONFIG_RSN_TESTING */ + + hdr->len = (pos - buf) - 2; + + return pos - buf; +} + + +int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth) +{ + u8 *pos, buf[128]; + int res; + + pos = buf; + + if (wpa_auth->conf.wpa & WPA_PROTO_RSN) { + res = wpa_write_rsn_ie(&wpa_auth->conf, + pos, buf + sizeof(buf) - pos, NULL); + if (res < 0) + return res; + pos += res; + } +#ifdef CONFIG_IEEE80211R + if (wpa_key_mgmt_ft(wpa_auth->conf.wpa_key_mgmt)) { + res = wpa_write_mdie(&wpa_auth->conf, pos, + buf + sizeof(buf) - pos); + if (res < 0) + return res; + pos += res; + } +#endif /* CONFIG_IEEE80211R */ + if (wpa_auth->conf.wpa & WPA_PROTO_WPA) { + res = wpa_write_wpa_ie(&wpa_auth->conf, + pos, buf + sizeof(buf) - pos); + if (res < 0) + return res; + pos += res; + } + + os_free(wpa_auth->wpa_ie); + wpa_auth->wpa_ie = os_malloc(pos - buf); + if (wpa_auth->wpa_ie == NULL) + return -1; + os_memcpy(wpa_auth->wpa_ie, buf, pos - buf); + wpa_auth->wpa_ie_len = pos - buf; + + return 0; +} + + +u8 * wpa_add_kde(u8 *pos, u32 kde, const u8 *data, size_t data_len, + const u8 *data2, size_t data2_len) +{ + *pos++ = WLAN_EID_VENDOR_SPECIFIC; + *pos++ = RSN_SELECTOR_LEN + data_len + data2_len; + RSN_SELECTOR_PUT(pos, kde); + pos += RSN_SELECTOR_LEN; + os_memcpy(pos, data, data_len); + pos += data_len; + if (data2) { + os_memcpy(pos, data2, data2_len); + pos += data2_len; + } + return pos; +} + +int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, + struct wpa_state_machine *sm, + const u8 *wpa_ie, size_t wpa_ie_len, + const u8 *mdie, size_t mdie_len) +{ + struct wpa_ie_data data; + int ciphers, key_mgmt, res, version; + u32 selector; + size_t i; + + if (wpa_auth == NULL || sm == NULL) + return WPA_NOT_ENABLED; + + if (wpa_ie == NULL || wpa_ie_len < 1) + return WPA_INVALID_IE; + + if (wpa_ie[0] == WLAN_EID_RSN) + version = WPA_PROTO_RSN; + else + version = WPA_PROTO_WPA; + + if (!(wpa_auth->conf.wpa & version)) { + wpa_printf(MSG_DEBUG, "Invalid WPA proto (%d) from " MACSTR, + version, MAC2STR(sm->addr)); + return WPA_INVALID_PROTO; + } + + if (version == WPA_PROTO_RSN) { + res = wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, &data); + + selector = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X; + if (0) { + } +#ifdef CONFIG_IEEE80211R + else if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) + selector = RSN_AUTH_KEY_MGMT_FT_802_1X; + else if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK) + selector = RSN_AUTH_KEY_MGMT_FT_PSK; +#endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_IEEE80211W + else if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) + selector = RSN_AUTH_KEY_MGMT_802_1X_SHA256; + else if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) + selector = RSN_AUTH_KEY_MGMT_PSK_SHA256; +#endif /* CONFIG_IEEE80211W */ +#ifdef CONFIG_SAE + else if (data.key_mgmt & WPA_KEY_MGMT_SAE) + selector = RSN_AUTH_KEY_MGMT_SAE; + else if (data.key_mgmt & WPA_KEY_MGMT_FT_SAE) + selector = RSN_AUTH_KEY_MGMT_FT_SAE; +#endif /* CONFIG_SAE */ + else if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) + selector = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X; + else if (data.key_mgmt & WPA_KEY_MGMT_PSK) + selector = RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X; + wpa_auth->dot11RSNAAuthenticationSuiteSelected = selector; + + selector = wpa_cipher_to_suite(WPA_PROTO_RSN, + data.pairwise_cipher); + if (!selector) + selector = RSN_CIPHER_SUITE_CCMP; + wpa_auth->dot11RSNAPairwiseCipherSelected = selector; + + selector = wpa_cipher_to_suite(WPA_PROTO_RSN, + data.group_cipher); + if (!selector) + selector = RSN_CIPHER_SUITE_CCMP; + wpa_auth->dot11RSNAGroupCipherSelected = selector; + } else { + res = wpa_parse_wpa_ie_wpa(wpa_ie, wpa_ie_len, &data); + + selector = WPA_AUTH_KEY_MGMT_UNSPEC_802_1X; + if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) + selector = WPA_AUTH_KEY_MGMT_UNSPEC_802_1X; + else if (data.key_mgmt & WPA_KEY_MGMT_PSK) + selector = WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X; + wpa_auth->dot11RSNAAuthenticationSuiteSelected = selector; + + selector = wpa_cipher_to_suite(WPA_PROTO_WPA, + data.pairwise_cipher); + if (!selector) + selector = RSN_CIPHER_SUITE_TKIP; + wpa_auth->dot11RSNAPairwiseCipherSelected = selector; + + selector = wpa_cipher_to_suite(WPA_PROTO_WPA, + data.group_cipher); + if (!selector) + selector = WPA_CIPHER_SUITE_TKIP; + wpa_auth->dot11RSNAGroupCipherSelected = selector; + } + if (res) { + wpa_printf(MSG_DEBUG, "Failed to parse WPA/RSN IE from " + MACSTR " (res=%d)", MAC2STR(sm->addr), res); + wpa_hexdump(MSG_DEBUG, "WPA/RSN IE", wpa_ie, wpa_ie_len); + return WPA_INVALID_IE; + } + + if (data.group_cipher != wpa_auth->conf.wpa_group) { + wpa_printf(MSG_DEBUG, "Invalid WPA group cipher (0x%x) from " + MACSTR, data.group_cipher, MAC2STR(sm->addr)); + return WPA_INVALID_GROUP; + } + + key_mgmt = data.key_mgmt & wpa_auth->conf.wpa_key_mgmt; + if (!key_mgmt) { + wpa_printf(MSG_DEBUG, "Invalid WPA key mgmt (0x%x) from " + MACSTR, data.key_mgmt, MAC2STR(sm->addr)); + return WPA_INVALID_AKMP; + } + if (0) { + } +#ifdef CONFIG_IEEE80211R + else if (key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) + sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X; + else if (key_mgmt & WPA_KEY_MGMT_FT_PSK) + sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_PSK; +#endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_IEEE80211W + else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) + sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256; + else if (key_mgmt & WPA_KEY_MGMT_PSK_SHA256) + sm->wpa_key_mgmt = WPA_KEY_MGMT_PSK_SHA256; +#endif /* CONFIG_IEEE80211W */ +#ifdef CONFIG_SAE + else if (key_mgmt & WPA_KEY_MGMT_SAE) + sm->wpa_key_mgmt = WPA_KEY_MGMT_SAE; + else if (key_mgmt & WPA_KEY_MGMT_FT_SAE) + sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_SAE; +#endif /* CONFIG_SAE */ + else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X) + sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X; + else + sm->wpa_key_mgmt = WPA_KEY_MGMT_PSK; + + if (version == WPA_PROTO_RSN) + ciphers = data.pairwise_cipher & wpa_auth->conf.rsn_pairwise; + else + ciphers = data.pairwise_cipher & wpa_auth->conf.wpa_pairwise; + if (!ciphers) { + wpa_printf(MSG_DEBUG, "Invalid %s pairwise cipher (0x%x) " + "from " MACSTR, + version == WPA_PROTO_RSN ? "RSN" : "WPA", + data.pairwise_cipher, MAC2STR(sm->addr)); + return WPA_INVALID_PAIRWISE; + } + +#ifdef CONFIG_IEEE80211W + if (wpa_auth->conf.ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED) { + if (!(data.capabilities & WPA_CAPABILITY_MFPC)) { + wpa_printf(MSG_DEBUG, "Management frame protection " + "required, but client did not enable it"); + return WPA_MGMT_FRAME_PROTECTION_VIOLATION; + } + + if (ciphers & WPA_CIPHER_TKIP) { + wpa_printf(MSG_DEBUG, "Management frame protection " + "cannot use TKIP"); + return WPA_MGMT_FRAME_PROTECTION_VIOLATION; + } + + if (data.mgmt_group_cipher != wpa_auth->conf.group_mgmt_cipher) + { + wpa_printf(MSG_DEBUG, "Unsupported management group " + "cipher %d", data.mgmt_group_cipher); + return WPA_INVALID_MGMT_GROUP_CIPHER; + } + } + + if (wpa_auth->conf.ieee80211w == NO_MGMT_FRAME_PROTECTION || + !(data.capabilities & WPA_CAPABILITY_MFPC)) + sm->mgmt_frame_prot = 0; + else + sm->mgmt_frame_prot = 1; +#endif /* CONFIG_IEEE80211W */ + +#ifdef CONFIG_IEEE80211R + if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { + if (mdie == NULL || mdie_len < MOBILITY_DOMAIN_ID_LEN + 1) { + wpa_printf(MSG_DEBUG, "RSN: Trying to use FT, but " + "MDIE not included"); + return WPA_INVALID_MDIE; + } + if (os_memcmp(mdie, wpa_auth->conf.mobility_domain, + MOBILITY_DOMAIN_ID_LEN) != 0) { + wpa_hexdump(MSG_DEBUG, "RSN: Attempted to use unknown " + "MDIE", mdie, MOBILITY_DOMAIN_ID_LEN); + return WPA_INVALID_MDIE; + } + } +#endif /* CONFIG_IEEE80211R */ + + sm->pairwise = wpa_pick_pairwise_cipher(ciphers, 0); + if (sm->pairwise < 0) + return WPA_INVALID_PAIRWISE; + + /* TODO: clear WPA/WPA2 state if STA changes from one to another */ + if (wpa_ie[0] == WLAN_EID_RSN) + sm->wpa = WPA_VERSION_WPA2; + else + sm->wpa = WPA_VERSION_WPA; + + if (sm->wpa_ie == NULL || sm->wpa_ie_len < wpa_ie_len) { + os_free(sm->wpa_ie); + sm->wpa_ie = os_malloc(wpa_ie_len); + if (sm->wpa_ie == NULL) + return WPA_ALLOC_FAIL; + } + os_memcpy(sm->wpa_ie, wpa_ie, wpa_ie_len); + sm->wpa_ie_len = wpa_ie_len; + + return WPA_IE_OK; + (void)i; +} + +/** + * wpa_parse_generic - Parse EAPOL-Key Key Data Generic IEs + * @pos: Pointer to the IE header + * @end: Pointer to the end of the Key Data buffer + * @ie: Pointer to parsed IE data + * Returns: 0 on success, 1 if end mark is found, -1 on failure + */ +static int wpa_parse_generic(const u8 *pos, const u8 *end, + struct wpa_eapol_ie_parse *ie) +{ + if (pos[1] == 0) + return 1; + + if (pos[1] >= 6 && + RSN_SELECTOR_GET(pos + 2) == WPA_OUI_TYPE && + pos[2 + WPA_SELECTOR_LEN] == 1 && + pos[2 + WPA_SELECTOR_LEN + 1] == 0) { + ie->wpa_ie = pos; + ie->wpa_ie_len = pos[1] + 2; + return 0; + } + + if (pos + 1 + RSN_SELECTOR_LEN < end && + pos[1] >= RSN_SELECTOR_LEN + PMKID_LEN && + RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_PMKID) { + ie->pmkid = pos + 2 + RSN_SELECTOR_LEN; + return 0; + } + + if (pos[1] > RSN_SELECTOR_LEN + 2 && + RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_GROUPKEY) { + ie->gtk = pos + 2 + RSN_SELECTOR_LEN; + ie->gtk_len = pos[1] - RSN_SELECTOR_LEN; + return 0; + } + + if (pos[1] > RSN_SELECTOR_LEN + 2 && + RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_MAC_ADDR) { + ie->mac_addr = pos + 2 + RSN_SELECTOR_LEN; + ie->mac_addr_len = pos[1] - RSN_SELECTOR_LEN; + return 0; + } + +#ifdef CONFIG_PEERKEY + if (pos[1] > RSN_SELECTOR_LEN + 2 && + RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_SMK) { + ie->smk = pos + 2 + RSN_SELECTOR_LEN; + ie->smk_len = pos[1] - RSN_SELECTOR_LEN; + return 0; + } + + if (pos[1] > RSN_SELECTOR_LEN + 2 && + RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_NONCE) { + ie->nonce = pos + 2 + RSN_SELECTOR_LEN; + ie->nonce_len = pos[1] - RSN_SELECTOR_LEN; + return 0; + } + + if (pos[1] > RSN_SELECTOR_LEN + 2 && + RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_LIFETIME) { + ie->lifetime = pos + 2 + RSN_SELECTOR_LEN; + ie->lifetime_len = pos[1] - RSN_SELECTOR_LEN; + return 0; + } + + if (pos[1] > RSN_SELECTOR_LEN + 2 && + RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_ERROR) { + ie->error = pos + 2 + RSN_SELECTOR_LEN; + ie->error_len = pos[1] - RSN_SELECTOR_LEN; + return 0; + } +#endif /* CONFIG_PEERKEY */ + +#ifdef CONFIG_IEEE80211W + if (pos[1] > RSN_SELECTOR_LEN + 2 && + RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_IGTK) { + ie->igtk = pos + 2 + RSN_SELECTOR_LEN; + ie->igtk_len = pos[1] - RSN_SELECTOR_LEN; + return 0; + } +#endif /* CONFIG_IEEE80211W */ + +#ifdef CONFIG_P2P + if (pos[1] >= RSN_SELECTOR_LEN + 1 && + RSN_SELECTOR_GET(pos + 2) == WFA_KEY_DATA_IP_ADDR_REQ) { + ie->ip_addr_req = pos + 2 + RSN_SELECTOR_LEN; + wpa_hexdump(MSG_DEBUG, "WPA: IP Address Request in EAPOL-Key", + ie->ip_addr_req, pos[1] - RSN_SELECTOR_LEN); + return 0; + } + + if (pos[1] >= RSN_SELECTOR_LEN + 3 * 4 && + RSN_SELECTOR_GET(pos + 2) == WFA_KEY_DATA_IP_ADDR_ALLOC) { + ie->ip_addr_alloc = pos + 2 + RSN_SELECTOR_LEN; + wpa_hexdump(MSG_DEBUG, + "WPA: IP Address Allocation in EAPOL-Key", + ie->ip_addr_alloc, pos[1] - RSN_SELECTOR_LEN); + return 0; + } +#endif /* CONFIG_P2P */ + + return 0; +} + + +/** + * wpa_parse_kde_ies - Parse EAPOL-Key Key Data IEs + * @buf: Pointer to the Key Data buffer + * @len: Key Data Length + * @ie: Pointer to parsed IE data + * Returns: 0 on success, -1 on failure + */ +int wpa_parse_kde_ies(const u8 *buf, size_t len, struct wpa_eapol_ie_parse *ie) +{ + const u8 *pos, *end; + int ret = 0; + + os_memset(ie, 0, sizeof(*ie)); + for (pos = buf, end = pos + len; pos + 1 < end; pos += 2 + pos[1]) { + if (pos[0] == 0xdd && + ((pos == buf + len - 1) || pos[1] == 0)) { + /* Ignore padding */ + break; + } + if (pos + 2 + pos[1] > end) { + wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key Key Data " + "underflow (ie=%d len=%d pos=%d)", + pos[0], pos[1], (int) (pos - buf)); + wpa_hexdump_key(MSG_DEBUG, "WPA: Key Data", + buf, len); + ret = -1; + break; + } + if (*pos == WLAN_EID_RSN) { + ie->rsn_ie = pos; + ie->rsn_ie_len = pos[1] + 2; +#ifdef CONFIG_IEEE80211R + } else if (*pos == WLAN_EID_MOBILITY_DOMAIN) { + ie->mdie = pos; + ie->mdie_len = pos[1] + 2; + } else if (*pos == WLAN_EID_FAST_BSS_TRANSITION) { + ie->ftie = pos; + ie->ftie_len = pos[1] + 2; +#endif /* CONFIG_IEEE80211R */ + } else if (*pos == WLAN_EID_VENDOR_SPECIFIC) { + ret = wpa_parse_generic(pos, end, ie); + if (ret < 0) + break; + if (ret > 0) { + ret = 0; + break; + } + } else { + wpa_hexdump(MSG_DEBUG, "WPA: Unrecognized EAPOL-Key " + "Key Data IE", pos, 2 + pos[1]); + } + } + + return ret; +} + + +int wpa_auth_uses_mfp(struct wpa_state_machine *sm) +{ + return sm ? sm->mgmt_frame_prot : 0; +} diff --git a/beken_os/beken378/func/hostapd-2.5/src/ap/wpa_auth_ie.h b/beken_os/beken378/func/hostapd-2.5/src/ap/wpa_auth_ie.h new file mode 100755 index 0000000..f945882 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/ap/wpa_auth_ie.h @@ -0,0 +1,54 @@ +/* + * hostapd - WPA/RSN IE and KDE definitions + * Copyright (c) 2004-2007, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef WPA_AUTH_IE_H +#define WPA_AUTH_IE_H + +struct wpa_eapol_ie_parse { + const u8 *wpa_ie; + size_t wpa_ie_len; + const u8 *rsn_ie; + size_t rsn_ie_len; + const u8 *pmkid; + const u8 *gtk; + size_t gtk_len; + const u8 *mac_addr; + size_t mac_addr_len; +#ifdef CONFIG_PEERKEY + const u8 *smk; + size_t smk_len; + const u8 *nonce; + size_t nonce_len; + const u8 *lifetime; + size_t lifetime_len; + const u8 *error; + size_t error_len; +#endif /* CONFIG_PEERKEY */ +#ifdef CONFIG_IEEE80211W + const u8 *igtk; + size_t igtk_len; +#endif /* CONFIG_IEEE80211W */ +#ifdef CONFIG_IEEE80211R + const u8 *mdie; + size_t mdie_len; + const u8 *ftie; + size_t ftie_len; +#endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_P2P + const u8 *ip_addr_req; + const u8 *ip_addr_alloc; +#endif /* CONFIG_P2P */ +}; + +int wpa_parse_kde_ies(const u8 *buf, size_t len, + struct wpa_eapol_ie_parse *ie); +u8 * wpa_add_kde(u8 *pos, u32 kde, const u8 *data, size_t data_len, + const u8 *data2, size_t data2_len); +int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth); + +#endif /* WPA_AUTH_IE_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/ap/wps_hostapd.h b/beken_os/beken378/func/hostapd-2.5/src/ap/wps_hostapd.h new file mode 100755 index 0000000..204bd82 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/ap/wps_hostapd.h @@ -0,0 +1,92 @@ +/* + * hostapd / WPS integration + * Copyright (c) 2008-2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef WPS_HOSTAPD_H +#define WPS_HOSTAPD_H + +#ifdef CONFIG_WPS + +int hostapd_init_wps(struct hostapd_data *hapd, + struct hostapd_bss_config *conf); +int hostapd_init_wps_complete(struct hostapd_data *hapd); +void hostapd_deinit_wps(struct hostapd_data *hapd); +void hostapd_update_wps(struct hostapd_data *hapd); +void hostapd_wps_eap_completed(struct hostapd_data *hapd); +int hostapd_wps_add_pin(struct hostapd_data *hapd, const u8 *addr, + const char *uuid, const char *pin, int timeout); +int hostapd_wps_button_pushed(struct hostapd_data *hapd, + const u8 *p2p_dev_addr); +int hostapd_wps_cancel(struct hostapd_data *hapd); +int hostapd_wps_get_mib_sta(struct hostapd_data *hapd, const u8 *addr, + char *buf, size_t buflen); +void hostapd_wps_ap_pin_disable(struct hostapd_data *hapd); +const char * hostapd_wps_ap_pin_random(struct hostapd_data *hapd, int timeout); +const char * hostapd_wps_ap_pin_get(struct hostapd_data *hapd); +int hostapd_wps_ap_pin_set(struct hostapd_data *hapd, const char *pin, + int timeout); +void hostapd_wps_update_ie(struct hostapd_data *hapd); +int hostapd_wps_config_ap(struct hostapd_data *hapd, const char *ssid, + const char *auth, const char *encr, const char *key); +int hostapd_wps_nfc_tag_read(struct hostapd_data *hapd, + const struct wpabuf *data); +struct wpabuf * hostapd_wps_nfc_config_token(struct hostapd_data *hapd, + int ndef); +struct wpabuf * hostapd_wps_nfc_hs_cr(struct hostapd_data *hapd, int ndef); +int hostapd_wps_nfc_report_handover(struct hostapd_data *hapd, + const struct wpabuf *req, + const struct wpabuf *sel); +struct wpabuf * hostapd_wps_nfc_token_gen(struct hostapd_data *hapd, int ndef); +int hostapd_wps_nfc_token_enable(struct hostapd_data *hapd); +void hostapd_wps_nfc_token_disable(struct hostapd_data *hapd); + +#else /* CONFIG_WPS */ + +static inline int hostapd_init_wps(struct hostapd_data *hapd, + struct hostapd_bss_config *conf) +{ + return 0; +} + +static inline void hostapd_deinit_wps(struct hostapd_data *hapd) +{ +} + +static inline int hostapd_init_wps_complete(struct hostapd_data *hapd) +{ + return 0; +} + +static inline void hostapd_update_wps(struct hostapd_data *hapd) +{ +} + +static inline void hostapd_wps_eap_completed(struct hostapd_data *hapd) +{ +} + +static inline int hostapd_wps_get_mib_sta(struct hostapd_data *hapd, + const u8 *addr, + char *buf, size_t buflen) +{ + return 0; +} + +static inline int hostapd_wps_button_pushed(struct hostapd_data *hapd, + const u8 *p2p_dev_addr) +{ + return 0; +} + +static inline int hostapd_wps_cancel(struct hostapd_data *hapd) +{ + return 0; +} + +#endif /* CONFIG_WPS */ + +#endif /* WPS_HOSTAPD_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/common/defs.h b/beken_os/beken378/func/hostapd-2.5/src/common/defs.h new file mode 100755 index 0000000..9d701e2 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/common/defs.h @@ -0,0 +1,339 @@ +/* + * WPA Supplicant - Common definitions + * Copyright (c) 2004-2015, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef DEFS_H +#define DEFS_H + +#include "include.h" + +#ifdef FALSE +#undef FALSE +#endif +#ifdef TRUE +#undef TRUE +#endif + +typedef enum { FALSE = 0, TRUE = 1 } Boolean; + +#define WPA_CIPHER_NONE BIT(0) +#define WPA_CIPHER_WEP40 BIT(1) +#define WPA_CIPHER_WEP104 BIT(2) +#define WPA_CIPHER_TKIP BIT(3) +#define WPA_CIPHER_CCMP BIT(4) +#define WPA_CIPHER_AES_128_CMAC BIT(5) +#define WPA_CIPHER_GCMP BIT(6) +#define WPA_CIPHER_SMS4 BIT(7) +#define WPA_CIPHER_GCMP_256 BIT(8) +#define WPA_CIPHER_CCMP_256 BIT(9) +#define WPA_CIPHER_BIP_GMAC_128 BIT(11) +#define WPA_CIPHER_BIP_GMAC_256 BIT(12) +#define WPA_CIPHER_BIP_CMAC_256 BIT(13) +#define WPA_CIPHER_GTK_NOT_USED BIT(14) + +#define WPA_KEY_MGMT_IEEE8021X BIT(0) +#define WPA_KEY_MGMT_PSK BIT(1) +#define WPA_KEY_MGMT_NONE BIT(2) +#define WPA_KEY_MGMT_IEEE8021X_NO_WPA BIT(3) +#define WPA_KEY_MGMT_WPA_NONE BIT(4) +#define WPA_KEY_MGMT_FT_IEEE8021X BIT(5) +#define WPA_KEY_MGMT_FT_PSK BIT(6) +#define WPA_KEY_MGMT_IEEE8021X_SHA256 BIT(7) +#define WPA_KEY_MGMT_PSK_SHA256 BIT(8) +#define WPA_KEY_MGMT_WPS BIT(9) +#define WPA_KEY_MGMT_SAE BIT(10) +#define WPA_KEY_MGMT_FT_SAE BIT(11) +#define WPA_KEY_MGMT_WAPI_PSK BIT(12) +#define WPA_KEY_MGMT_WAPI_CERT BIT(13) +#define WPA_KEY_MGMT_CCKM BIT(14) +#define WPA_KEY_MGMT_OSEN BIT(15) +#define WPA_KEY_MGMT_IEEE8021X_SUITE_B BIT(16) +#define WPA_KEY_MGMT_IEEE8021X_SUITE_B_192 BIT(17) + +static inline int wpa_key_mgmt_wpa_ieee8021x(int akm) +{ + return !!(akm & (WPA_KEY_MGMT_IEEE8021X | + WPA_KEY_MGMT_FT_IEEE8021X | + WPA_KEY_MGMT_CCKM | + WPA_KEY_MGMT_OSEN | + WPA_KEY_MGMT_IEEE8021X_SHA256 | + WPA_KEY_MGMT_IEEE8021X_SUITE_B | + WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)); +} + +static inline int wpa_key_mgmt_wpa_psk(int akm) +{ + return !!(akm & (WPA_KEY_MGMT_PSK | + WPA_KEY_MGMT_FT_PSK | + WPA_KEY_MGMT_PSK_SHA256 | + WPA_KEY_MGMT_SAE | + WPA_KEY_MGMT_FT_SAE)); +} + +static inline int wpa_key_mgmt_ft(int akm) +{ + return !!(akm & (WPA_KEY_MGMT_FT_PSK | + WPA_KEY_MGMT_FT_IEEE8021X | + WPA_KEY_MGMT_FT_SAE)); +} + +static inline int wpa_key_mgmt_sae(int akm) +{ + return !!(akm & (WPA_KEY_MGMT_SAE | + WPA_KEY_MGMT_FT_SAE)); +} + +static inline int wpa_key_mgmt_sha256(int akm) +{ + return !!(akm & (WPA_KEY_MGMT_PSK_SHA256 | + WPA_KEY_MGMT_IEEE8021X_SHA256 | + WPA_KEY_MGMT_OSEN | + WPA_KEY_MGMT_IEEE8021X_SUITE_B)); +} + +static inline int wpa_key_mgmt_sha384(int akm) +{ + return !!(akm & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192); +} + +static inline int wpa_key_mgmt_suite_b(int akm) +{ + return !!(akm & (WPA_KEY_MGMT_IEEE8021X_SUITE_B | + WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)); +} + +static inline int wpa_key_mgmt_wpa(int akm) +{ + return wpa_key_mgmt_wpa_ieee8021x(akm) || + wpa_key_mgmt_wpa_psk(akm) || + wpa_key_mgmt_sae(akm); +} + +static inline int wpa_key_mgmt_wpa_any(int akm) +{ + return wpa_key_mgmt_wpa(akm) || (akm & WPA_KEY_MGMT_WPA_NONE); +} + +static inline int wpa_key_mgmt_cckm(int akm) +{ + return akm == WPA_KEY_MGMT_CCKM; +} + + +#define WPA_PROTO_WPA BIT(0) +#define WPA_PROTO_RSN BIT(1) +#define WPA_PROTO_WAPI BIT(2) +#define WPA_PROTO_OSEN BIT(3) + +#define WPA_AUTH_ALG_OPEN BIT(0) +#define WPA_AUTH_ALG_SHARED BIT(1) +#define WPA_AUTH_ALG_LEAP BIT(2) +#define WPA_AUTH_ALG_FT BIT(3) +#define WPA_AUTH_ALG_SAE BIT(4) + + +enum wpa_alg { + WPA_ALG_NONE, + WPA_ALG_WEP, + WPA_ALG_TKIP, + WPA_ALG_CCMP, + WPA_ALG_IGTK, + WPA_ALG_PMK, + WPA_ALG_GCMP, + WPA_ALG_SMS4, + WPA_ALG_KRK, + WPA_ALG_GCMP_256, + WPA_ALG_CCMP_256, + WPA_ALG_BIP_GMAC_128, + WPA_ALG_BIP_GMAC_256, + WPA_ALG_BIP_CMAC_256 +}; + +/** + * enum wpa_states - wpa_supplicant state + * + * These enumeration values are used to indicate the current wpa_supplicant + * state (wpa_s->wpa_state). The current state can be retrieved with + * wpa_supplicant_get_state() function and the state can be changed by calling + * wpa_supplicant_set_state(). In WPA state machine (wpa.c and preauth.c), the + * wrapper functions wpa_sm_get_state() and wpa_sm_set_state() should be used + * to access the state variable. + */ +enum wpa_states { + /** + * WPA_DISCONNECTED - Disconnected state + * + * This state indicates that client is not associated, but is likely to + * start looking for an access point. This state is entered when a + * connection is lost. + */ + WPA_DISCONNECTED, + + /** + * WPA_INTERFACE_DISABLED - Interface disabled + * + * This state is entered if the network interface is disabled, e.g., + * due to rfkill. wpa_supplicant refuses any new operations that would + * use the radio until the interface has been enabled. + */ + WPA_INTERFACE_DISABLED, + + /** + * WPA_INACTIVE - Inactive state (wpa_supplicant disabled) + * + * This state is entered if there are no enabled networks in the + * configuration. wpa_supplicant is not trying to associate with a new + * network and external interaction (e.g., ctrl_iface call to add or + * enable a network) is needed to start association. + */ + WPA_INACTIVE, + + /** + * WPA_SCANNING - Scanning for a network + * + * This state is entered when wpa_supplicant starts scanning for a + * network. + */ + WPA_SCANNING, + + /** + * WPA_AUTHENTICATING - Trying to authenticate with a BSS/SSID + * + * This state is entered when wpa_supplicant has found a suitable BSS + * to authenticate with and the driver is configured to try to + * authenticate with this BSS. This state is used only with drivers + * that use wpa_supplicant as the SME. + */ + WPA_AUTHENTICATING, + + /** + * WPA_ASSOCIATING - Trying to associate with a BSS/SSID + * + * This state is entered when wpa_supplicant has found a suitable BSS + * to associate with and the driver is configured to try to associate + * with this BSS in ap_scan=1 mode. When using ap_scan=2 mode, this + * state is entered when the driver is configured to try to associate + * with a network using the configured SSID and security policy. + */ + WPA_ASSOCIATING, + + /** + * WPA_ASSOCIATED - Association completed + * + * This state is entered when the driver reports that association has + * been successfully completed with an AP. If IEEE 802.1X is used + * (with or without WPA/WPA2), wpa_supplicant remains in this state + * until the IEEE 802.1X/EAPOL authentication has been completed. + */ + WPA_ASSOCIATED, + + /** + * WPA_4WAY_HANDSHAKE - WPA 4-Way Key Handshake in progress + * + * This state is entered when WPA/WPA2 4-Way Handshake is started. In + * case of WPA-PSK, this happens when receiving the first EAPOL-Key + * frame after association. In case of WPA-EAP, this state is entered + * when the IEEE 802.1X/EAPOL authentication has been completed. + */ + WPA_4WAY_HANDSHAKE, + + /** + * WPA_GROUP_HANDSHAKE - WPA Group Key Handshake in progress + * + * This state is entered when 4-Way Key Handshake has been completed + * (i.e., when the supplicant sends out message 4/4) and when Group + * Key rekeying is started by the AP (i.e., when supplicant receives + * message 1/2). + */ + WPA_GROUP_HANDSHAKE, + + /** + * WPA_COMPLETED - All authentication completed + * + * This state is entered when the full authentication process is + * completed. In case of WPA2, this happens when the 4-Way Handshake is + * successfully completed. With WPA, this state is entered after the + * Group Key Handshake; with IEEE 802.1X (non-WPA) connection is + * completed after dynamic keys are received (or if not used, after + * the EAP authentication has been completed). With static WEP keys and + * plaintext connections, this state is entered when an association + * has been completed. + * + * This state indicates that the supplicant has completed its + * processing for the association phase and that data connection is + * fully configured. + */ + WPA_COMPLETED +}; + +#define MLME_SETPROTECTION_PROTECT_TYPE_NONE 0 +#define MLME_SETPROTECTION_PROTECT_TYPE_RX 1 +#define MLME_SETPROTECTION_PROTECT_TYPE_TX 2 +#define MLME_SETPROTECTION_PROTECT_TYPE_RX_TX 3 + +#define MLME_SETPROTECTION_KEY_TYPE_GROUP 0 +#define MLME_SETPROTECTION_KEY_TYPE_PAIRWISE 1 + + +/** + * enum mfp_options - Management frame protection (IEEE 802.11w) options + */ +enum mfp_options { + NO_MGMT_FRAME_PROTECTION = 0, + MGMT_FRAME_PROTECTION_OPTIONAL = 1, + MGMT_FRAME_PROTECTION_REQUIRED = 2, +}; +#define MGMT_FRAME_PROTECTION_DEFAULT 3 + +/** + * enum hostapd_hw_mode - Hardware mode + */ +enum hostapd_hw_mode { + HOSTAPD_MODE_IEEE80211B, + HOSTAPD_MODE_IEEE80211G, + HOSTAPD_MODE_IEEE80211A, + HOSTAPD_MODE_IEEE80211AD, + HOSTAPD_MODE_IEEE80211ANY, + NUM_HOSTAPD_MODES +}; + +/** + * enum wpa_ctrl_req_type - Control interface request types + */ +enum wpa_ctrl_req_type { + WPA_CTRL_REQ_UNKNOWN, + WPA_CTRL_REQ_EAP_IDENTITY, + WPA_CTRL_REQ_EAP_PASSWORD, + WPA_CTRL_REQ_EAP_NEW_PASSWORD, + WPA_CTRL_REQ_EAP_PIN, + WPA_CTRL_REQ_EAP_OTP, + WPA_CTRL_REQ_EAP_PASSPHRASE, + WPA_CTRL_REQ_SIM, + WPA_CTRL_REQ_PSK_PASSPHRASE, + NUM_WPA_CTRL_REQS +}; + +/* Maximum number of EAP methods to store for EAP server user information */ +#define EAP_MAX_METHODS 8 + +enum mesh_plink_state { + PLINK_LISTEN = 1, + PLINK_OPEN_SENT, + PLINK_OPEN_RCVD, + PLINK_CNF_RCVD, + PLINK_ESTAB, + PLINK_HOLDING, + PLINK_BLOCKED, +}; + +enum set_band { + WPA_SETBAND_AUTO, + WPA_SETBAND_5G, + WPA_SETBAND_2G +}; + +#endif /* DEFS_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/common/eapol_common.h b/beken_os/beken378/func/hostapd-2.5/src/common/eapol_common.h new file mode 100755 index 0000000..22b7b89 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/common/eapol_common.h @@ -0,0 +1,92 @@ +/* + * EAPOL definitions shared between hostapd and wpa_supplicant + * Copyright (c) 2002-2007, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef EAPOL_COMMON_H +#define EAPOL_COMMON_H + +/* IEEE Std 802.1X-2004 */ + +#ifdef _MSC_VER +#pragma pack(push, 1) +#endif /* _MSC_VER */ + +STRUCT_PACKED struct ieee802_1x_hdr { + u8 version; + u8 type; + be16 length; + /* followed by length octets of data */ +}GCC_PACKED; + +STRUCT_PACKED struct ieee8023_hdr { + u8 dest[ETH_ALEN]; + u8 src[ETH_ALEN]; + u16 ethertype; +}GCC_PACKED; + +#ifdef _MSC_VER +#pragma pack(pop) +#endif /* _MSC_VER */ + +#ifdef CONFIG_MACSEC +#define EAPOL_VERSION 3 +#else /* CONFIG_MACSEC */ +#define EAPOL_VERSION 2 +#endif /* CONFIG_MACSEC */ + +enum { IEEE802_1X_TYPE_EAP_PACKET = 0, + IEEE802_1X_TYPE_EAPOL_START = 1, + IEEE802_1X_TYPE_EAPOL_LOGOFF = 2, + IEEE802_1X_TYPE_EAPOL_KEY = 3, + IEEE802_1X_TYPE_EAPOL_ENCAPSULATED_ASF_ALERT = 4, + IEEE802_1X_TYPE_EAPOL_MKA = 5, +}; + +enum { EAPOL_KEY_TYPE_RC4 = 1, EAPOL_KEY_TYPE_RSN = 2, + EAPOL_KEY_TYPE_WPA = 254 }; + + +#define IEEE8021X_REPLAY_COUNTER_LEN 8 +#define IEEE8021X_KEY_SIGN_LEN 16 +#define IEEE8021X_KEY_IV_LEN 16 + +#define IEEE8021X_KEY_INDEX_FLAG 0x80 +#define IEEE8021X_KEY_INDEX_MASK 0x03 + +#ifdef _MSC_VER +#pragma pack(push, 1) +#endif /* _MSC_VER */ + +STRUCT_PACKED struct ieee802_1x_eapol_key { + u8 type; + /* Note: key_length is unaligned */ + u8 key_length[2]; + /* does not repeat within the life of the keying material used to + * encrypt the Key field; 64-bit NTP timestamp MAY be used here */ + u8 replay_counter[IEEE8021X_REPLAY_COUNTER_LEN]; + u8 key_iv[IEEE8021X_KEY_IV_LEN]; /* cryptographically random number */ + u8 key_index; /* key flag in the most significant bit: + * 0 = broadcast (default key), + * 1 = unicast (key mapping key); key index is in the + * 7 least significant bits */ + /* HMAC-MD5 message integrity check computed with MS-MPPE-Send-Key as + * the key */ + u8 key_signature[IEEE8021X_KEY_SIGN_LEN]; + + /* followed by key: if packet body length = 44 + key length, then the + * key field (of key_length bytes) contains the key in encrypted form; + * if packet body length = 44, key field is absent and key_length + * represents the number of least significant octets from + * MS-MPPE-Send-Key attribute to be used as the keying material; + * RC4 key used in encryption = Key-IV + MS-MPPE-Recv-Key */ +}GCC_PACKED; + +#ifdef _MSC_VER +#pragma pack(pop) +#endif /* _MSC_VER */ + +#endif /* EAPOL_COMMON_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/common/hw_features_common.c b/beken_os/beken378/func/hostapd-2.5/src/common/hw_features_common.c new file mode 100755 index 0000000..9c37ea6 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/common/hw_features_common.c @@ -0,0 +1,455 @@ +/* + * Common hostapd/wpa_supplicant HW features + * Copyright (c) 2002-2013, Jouni Malinen + * Copyright (c) 2015, Qualcomm Atheros, Inc. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "defs.h" +#include "ieee802_11_defs.h" +#include "ieee802_11_common.h" +#include "hw_features_common.h" + + +struct hostapd_channel_data * hw_get_channel_chan(struct hostapd_hw_modes *mode, + int chan, int *freq) +{ + int i; + + if (freq) + *freq = 0; + + if (!mode) + return NULL; + + for (i = 0; i < mode->num_channels; i++) { + struct hostapd_channel_data *ch = &mode->channels[i]; + if (ch->chan == chan) { + if (freq) + *freq = ch->freq; + return ch; + } + } + + return NULL; +} + + +struct hostapd_channel_data * hw_get_channel_freq(struct hostapd_hw_modes *mode, + int freq, int *chan) +{ + int i; + + if (chan) + *chan = 0; + + if (!mode) + return NULL; + + for (i = 0; i < mode->num_channels; i++) { + struct hostapd_channel_data *ch = &mode->channels[i]; + if (ch->freq == freq) { + if (chan) + *chan = ch->chan; + return ch; + } + } + + return NULL; +} + + +int hw_get_freq(struct hostapd_hw_modes *mode, int chan) +{ + int freq; + + hw_get_channel_chan(mode, chan, &freq); + + return freq; +} + + +int hw_get_chan(struct hostapd_hw_modes *mode, int freq) +{ + int chan; + + hw_get_channel_freq(mode, freq, &chan); + + return chan; +} + + +int allowed_ht40_channel_pair(struct hostapd_hw_modes *mode, int pri_chan, + int sec_chan) +{ + int ok, j, first; + int allowed[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 140, + 149, 157, 184, 192 }; + size_t k; + + if (pri_chan == sec_chan || !sec_chan) + return 1; /* HT40 not used */ + + wpa_printf(MSG_DEBUG, + "HT40: control channel: %d secondary channel: %d", + pri_chan, sec_chan); + + /* Verify that HT40 secondary channel is an allowed 20 MHz + * channel */ + ok = 0; + for (j = 0; j < mode->num_channels; j++) { + struct hostapd_channel_data *chan = &mode->channels[j]; + if (!(chan->flag & HOSTAPD_CHAN_DISABLED) && + chan->chan == sec_chan) { + ok = 1; + break; + } + } + if (!ok) { + wpa_printf(MSG_ERROR, "HT40 secondary channel %d not allowed", + sec_chan); + return 0; + } + + /* + * Verify that HT40 primary,secondary channel pair is allowed per + * IEEE 802.11n Annex J. This is only needed for 5 GHz band since + * 2.4 GHz rules allow all cases where the secondary channel fits into + * the list of allowed channels (already checked above). + */ + if (mode->mode != HOSTAPD_MODE_IEEE80211A) + return 1; + + first = pri_chan < sec_chan ? pri_chan : sec_chan; + + ok = 0; + for (k = 0; k < ARRAY_SIZE(allowed); k++) { + if (first == allowed[k]) { + ok = 1; + break; + } + } + if (!ok) { + wpa_printf(MSG_ERROR, "HT40 channel pair (%d, %d) not allowed", + pri_chan, sec_chan); + return 0; + } + + return 1; +} + + +void get_pri_sec_chan(struct wpa_scan_res *bss, int *pri_chan, int *sec_chan) +{ + struct ieee80211_ht_operation *oper; + struct ieee802_11_elems elems; + + *pri_chan = *sec_chan = 0; + + ieee802_11_parse_elems((u8 *) (bss + 1), bss->ie_len, &elems, 0); + if (elems.ht_operation) { + oper = (struct ieee80211_ht_operation *) elems.ht_operation; + *pri_chan = oper->primary_chan; + if (oper->ht_param & HT_INFO_HT_PARAM_STA_CHNL_WIDTH) { + int sec = oper->ht_param & + HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK; + if (sec == HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE) + *sec_chan = *pri_chan + 4; + else if (sec == HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW) + *sec_chan = *pri_chan - 4; + } + } +} + + +int check_40mhz_5g(struct hostapd_hw_modes *mode, + struct wpa_scan_results *scan_res, int pri_chan, + int sec_chan) +{ + int pri_freq, sec_freq, pri_bss, sec_bss; + int bss_pri_chan, bss_sec_chan; + size_t i; + int match; + + if (!mode || !scan_res || !pri_chan || !sec_chan || + pri_chan == sec_chan) + return 0; + + pri_freq = hw_get_freq(mode, pri_chan); + sec_freq = hw_get_freq(mode, sec_chan); + + /* + * Switch PRI/SEC channels if Beacons were detected on selected SEC + * channel, but not on selected PRI channel. + */ + pri_bss = sec_bss = 0; + for (i = 0; i < scan_res->num; i++) { + struct wpa_scan_res *bss = scan_res->res[i]; + if (bss->freq == pri_freq) + pri_bss++; + else if (bss->freq == sec_freq) + sec_bss++; + } + if (sec_bss && !pri_bss) { + wpa_printf(MSG_INFO, + "Switch own primary and secondary channel to get secondary channel with no Beacons from other BSSes"); + return 2; + } + + /* + * Match PRI/SEC channel with any existing HT40 BSS on the same + * channels that we are about to use (if already mixed order in + * existing BSSes, use own preference). + */ + match = 0; + for (i = 0; i < scan_res->num; i++) { + struct wpa_scan_res *bss = scan_res->res[i]; + get_pri_sec_chan(bss, &bss_pri_chan, &bss_sec_chan); + if (pri_chan == bss_pri_chan && + sec_chan == bss_sec_chan) { + match = 1; + break; + } + } + if (!match) { + for (i = 0; i < scan_res->num; i++) { + struct wpa_scan_res *bss = scan_res->res[i]; + get_pri_sec_chan(bss, &bss_pri_chan, &bss_sec_chan); + if (pri_chan == bss_sec_chan && + sec_chan == bss_pri_chan) { + wpa_printf(MSG_INFO, "Switch own primary and " + "secondary channel due to BSS " + "overlap with " MACSTR, + MAC2STR(bss->bssid)); + return 2; + } + } + } + + return 1; +} + + +static int check_20mhz_bss(struct wpa_scan_res *bss, int pri_freq, int start, + int end) +{ + struct ieee802_11_elems elems; + struct ieee80211_ht_operation *oper; + + if (bss->freq < start || bss->freq > end || bss->freq == pri_freq) + return 0; + + ieee802_11_parse_elems((u8 *) (bss + 1), bss->ie_len, &elems, 0); + if (!elems.ht_capabilities) { + wpa_printf(MSG_DEBUG, "Found overlapping legacy BSS: " + MACSTR " freq=%d", MAC2STR(bss->bssid), bss->freq); + return 1; + } + + if (elems.ht_operation) { + oper = (struct ieee80211_ht_operation *) elems.ht_operation; + if (oper->ht_param & HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK) + return 0; + + wpa_printf(MSG_DEBUG, "Found overlapping 20 MHz HT BSS: " + MACSTR " freq=%d", MAC2STR(bss->bssid), bss->freq); + return 1; + } + return 0; +} + + +int check_40mhz_2g4(struct hostapd_hw_modes *mode, + struct wpa_scan_results *scan_res, int pri_chan, + int sec_chan) +{ + int pri_freq, sec_freq; + int affected_start, affected_end; + size_t i; + + if (!mode || !scan_res || !pri_chan || !sec_chan || + pri_chan == sec_chan) + return 0; + + pri_freq = hw_get_freq(mode, pri_chan); + sec_freq = hw_get_freq(mode, sec_chan); + + affected_start = (pri_freq + sec_freq) / 2 - 25; + affected_end = (pri_freq + sec_freq) / 2 + 25; + wpa_printf(MSG_DEBUG, "40 MHz affected channel range: [%d,%d] MHz", + affected_start, affected_end); + for (i = 0; i < scan_res->num; i++) { + struct wpa_scan_res *bss = scan_res->res[i]; + int pri = bss->freq; + int sec = pri; + struct ieee802_11_elems elems; + + /* Check for overlapping 20 MHz BSS */ + if (check_20mhz_bss(bss, pri_freq, affected_start, + affected_end)) { + wpa_printf(MSG_DEBUG, + "Overlapping 20 MHz BSS is found"); + return 0; + } + + get_pri_sec_chan(bss, &pri_chan, &sec_chan); + + if (sec_chan) { + if (sec_chan < pri_chan) + sec = pri - 20; + else + sec = pri + 20; + } + + if ((pri < affected_start || pri > affected_end) && + (sec < affected_start || sec > affected_end)) + continue; /* not within affected channel range */ + + wpa_printf(MSG_DEBUG, "Neighboring BSS: " MACSTR + " freq=%d pri=%d sec=%d", + MAC2STR(bss->bssid), bss->freq, pri_chan, sec_chan); + + if (sec_chan) { + if (pri_freq != pri || sec_freq != sec) { + wpa_printf(MSG_DEBUG, + "40 MHz pri/sec mismatch with BSS " + MACSTR + " <%d,%d> (chan=%d%c) vs. <%d,%d>", + MAC2STR(bss->bssid), + pri, sec, pri_chan, + sec > pri ? '+' : '-', + pri_freq, sec_freq); + return 0; + } + } + + ieee802_11_parse_elems((u8 *) (bss + 1), bss->ie_len, &elems, + 0); + if (elems.ht_capabilities) { + struct ieee80211_ht_capabilities *ht_cap = + (struct ieee80211_ht_capabilities *) + elems.ht_capabilities; + + if (le_to_host16(ht_cap->ht_capabilities_info) & + HT_CAP_INFO_40MHZ_INTOLERANT) { + wpa_printf(MSG_DEBUG, + "40 MHz Intolerant is set on channel %d in BSS " + MACSTR, pri, MAC2STR(bss->bssid)); + return 0; + } + } + } + + return 1; +} + + +int hostapd_set_freq_params(struct hostapd_freq_params *data, + enum hostapd_hw_mode mode, + int freq, int channel, int ht_enabled, + int vht_enabled, int sec_channel_offset, + int vht_oper_chwidth, int center_segment0, + int center_segment1, u32 vht_caps) +{ + os_memset(data, 0, sizeof(*data)); + data->mode = mode; + data->freq = freq; + data->channel = channel; + data->ht_enabled = ht_enabled; + data->vht_enabled = vht_enabled; + data->sec_channel_offset = sec_channel_offset; + data->center_freq1 = freq + sec_channel_offset * 10; + data->center_freq2 = 0; + data->bandwidth = sec_channel_offset ? 40 : 20; + + if (data->vht_enabled) switch (vht_oper_chwidth) { + case VHT_CHANWIDTH_USE_HT: + if (center_segment1 || + (center_segment0 != 0 && + 5000 + center_segment0 * 5 != data->center_freq1 && + 2407 + center_segment0 * 5 != data->center_freq1)) + return -1; + break; + case VHT_CHANWIDTH_80P80MHZ: + if (!(vht_caps & VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ)) { + wpa_printf(MSG_ERROR, + "80+80 channel width is not supported!"); + return -1; + } + if (center_segment1 == center_segment0 + 4 || + center_segment1 == center_segment0 - 4) + return -1; + data->center_freq2 = 5000 + center_segment1 * 5; + /* fall through */ + case VHT_CHANWIDTH_80MHZ: + data->bandwidth = 80; + if ((vht_oper_chwidth == 1 && center_segment1) || + (vht_oper_chwidth == 3 && !center_segment1) || + !sec_channel_offset) + return -1; + if (!center_segment0) { + if (channel <= 48) + center_segment0 = 42; + else if (channel <= 64) + center_segment0 = 58; + else if (channel <= 112) + center_segment0 = 106; + else if (channel <= 128) + center_segment0 = 122; + else if (channel <= 144) + center_segment0 = 138; + else if (channel <= 161) + center_segment0 = 155; + data->center_freq1 = 5000 + center_segment0 * 5; + } else { + /* + * Note: HT/VHT config and params are coupled. Check if + * HT40 channel band is in VHT80 Pri channel band + * configuration. + */ + if (center_segment0 == channel + 6 || + center_segment0 == channel + 2 || + center_segment0 == channel - 2 || + center_segment0 == channel - 6) + data->center_freq1 = 5000 + center_segment0 * 5; + else + return -1; + } + break; + case VHT_CHANWIDTH_160MHZ: + data->bandwidth = 160; + if (!(vht_caps & (VHT_CAP_SUPP_CHAN_WIDTH_160MHZ | + VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ))) { + wpa_printf(MSG_ERROR, + "160MHZ channel width is not supported!"); + return -1; + } + if (center_segment1) + return -1; + if (!sec_channel_offset) + return -1; + /* + * Note: HT/VHT config and params are coupled. Check if + * HT40 channel band is in VHT160 channel band configuration. + */ + if (center_segment0 == channel + 14 || + center_segment0 == channel + 10 || + center_segment0 == channel + 6 || + center_segment0 == channel + 2 || + center_segment0 == channel - 2 || + center_segment0 == channel - 6 || + center_segment0 == channel - 10 || + center_segment0 == channel - 14) + data->center_freq1 = 5000 + center_segment0 * 5; + else + return -1; + break; + } + + return 0; +} diff --git a/beken_os/beken378/func/hostapd-2.5/src/common/hw_features_common.h b/beken_os/beken378/func/hostapd-2.5/src/common/hw_features_common.h new file mode 100755 index 0000000..7360b4e --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/common/hw_features_common.h @@ -0,0 +1,39 @@ +/* + * Common hostapd/wpa_supplicant HW features + * Copyright (c) 2002-2013, Jouni Malinen + * Copyright (c) 2015, Qualcomm Atheros, Inc. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef HW_FEATURES_COMMON_H +#define HW_FEATURES_COMMON_H + +#include "drivers/driver.h" + +struct hostapd_channel_data * hw_get_channel_chan(struct hostapd_hw_modes *mode, + int chan, int *freq); +struct hostapd_channel_data * hw_get_channel_freq(struct hostapd_hw_modes *mode, + int freq, int *chan); + +int hw_get_freq(struct hostapd_hw_modes *mode, int chan); +int hw_get_chan(struct hostapd_hw_modes *mode, int freq); + +int allowed_ht40_channel_pair(struct hostapd_hw_modes *mode, int pri_chan, + int sec_chan); +void get_pri_sec_chan(struct wpa_scan_res *bss, int *pri_chan, int *sec_chan); +int check_40mhz_5g(struct hostapd_hw_modes *mode, + struct wpa_scan_results *scan_res, int pri_chan, + int sec_chan); +int check_40mhz_2g4(struct hostapd_hw_modes *mode, + struct wpa_scan_results *scan_res, int pri_chan, + int sec_chan); +int hostapd_set_freq_params(struct hostapd_freq_params *data, + enum hostapd_hw_mode mode, + int freq, int channel, int ht_enabled, + int vht_enabled, int sec_channel_offset, + int vht_oper_chwidth, int center_segment0, + int center_segment1, u32 vht_caps); + +#endif /* HW_FEATURES_COMMON_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/common/ieee802_11_common.c b/beken_os/beken378/func/hostapd-2.5/src/common/ieee802_11_common.c new file mode 100755 index 0000000..390f383 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/common/ieee802_11_common.c @@ -0,0 +1,1154 @@ +/* + * IEEE 802.11 Common routines + * Copyright (c) 2002-2015, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "include.h" +#include "uart_pub.h" + +#include "includes.h" + +#include "common.h" +#include "defs.h" +#include "wpa_common.h" +#include "ieee802_11_defs.h" +#include "ieee802_11_common.h" + + +static int ieee802_11_parse_vendor_specific(const u8 *pos, size_t elen, + struct ieee802_11_elems *elems, + int show_errors) +{ + unsigned int oui; + + /* first 3 bytes in vendor specific information element are the IEEE + * OUI of the vendor. The following byte is used a vendor specific + * sub-type. */ + if (elen < 4) { + if (show_errors) { + wpa_printf(MSG_MSGDUMP, "short vendor specific " + "information element ignored (len=%lu)", + (unsigned long) elen); + } + return -1; + } + + oui = WPA_GET_BE24(pos); + switch (oui) { + case OUI_BEKEN: + break; + + case OUI_MICROSOFT: + /* Microsoft/Wi-Fi information elements are further typed and + * subtyped */ + switch (pos[3]) { + case 1: + /* Microsoft OUI (00:50:F2) with OUI Type 1: + * real WPA information element */ + elems->wpa_ie = pos; + elems->wpa_ie_len = elen; + break; + case WMM_OUI_TYPE: + /* WMM information element */ + if (elen < 5) { + wpa_printf(MSG_MSGDUMP, "short WMM " + "information element ignored " + "(len=%lu)", + (unsigned long) elen); + return -1; + } + switch (pos[4]) { + case WMM_OUI_SUBTYPE_INFORMATION_ELEMENT: + case WMM_OUI_SUBTYPE_PARAMETER_ELEMENT: + /* + * Share same pointer since only one of these + * is used and they start with same data. + * Length field can be used to distinguish the + * IEs. + */ + elems->wmm = pos; + elems->wmm_len = elen; + break; + case WMM_OUI_SUBTYPE_TSPEC_ELEMENT: + elems->wmm_tspec = pos; + elems->wmm_tspec_len = elen; + break; + default: + wpa_printf(MSG_EXCESSIVE, "unknown WMM " + "information element ignored " + "(subtype=%d len=%lu)", + pos[4], (unsigned long) elen); + return -1; + } + break; + case 4: + /* Wi-Fi Protected Setup (WPS) IE */ + elems->wps_ie = pos; + elems->wps_ie_len = elen; + break; + default: + wpa_printf(MSG_EXCESSIVE, "Unknown Microsoft " + "information element ignored " + "(type=%d len=%lu)", + pos[3], (unsigned long) elen); + return -1; + } + break; + + case OUI_WFA: + switch (pos[3]) { + case P2P_OUI_TYPE: + /* Wi-Fi Alliance - P2P IE */ + elems->p2p = pos; + elems->p2p_len = elen; + break; + case WFD_OUI_TYPE: + /* Wi-Fi Alliance - WFD IE */ + elems->wfd = pos; + elems->wfd_len = elen; + break; + case HS20_INDICATION_OUI_TYPE: + /* Hotspot 2.0 */ + elems->hs20 = pos; + elems->hs20_len = elen; + break; + case HS20_OSEN_OUI_TYPE: + /* Hotspot 2.0 OSEN */ + elems->osen = pos; + elems->osen_len = elen; + break; + default: + wpa_printf(MSG_MSGDUMP, "Unknown WFA " + "information element ignored " + "(type=%d len=%lu)", + pos[3], (unsigned long) elen); + return -1; + } + break; + + case OUI_BROADCOM: + switch (pos[3]) { + case VENDOR_HT_CAPAB_OUI_TYPE: + elems->vendor_ht_cap = pos; + elems->vendor_ht_cap_len = elen; + break; + case VENDOR_VHT_TYPE: + if (elen > 4 && + (pos[4] == VENDOR_VHT_SUBTYPE || + pos[4] == VENDOR_VHT_SUBTYPE2)) { + elems->vendor_vht = pos; + elems->vendor_vht_len = elen; + } else + return -1; + break; + default: + wpa_printf(MSG_EXCESSIVE, "Unknown Broadcom " + "information element ignored " + "(type=%d len=%lu)", + pos[3], (unsigned long) elen); + return -1; + } + break; + +#ifdef CONFIG_P2P + case OUI_QCA: + switch (pos[3]) { + case QCA_VENDOR_ELEM_P2P_PREF_CHAN_LIST: + elems->pref_freq_list = pos; + elems->pref_freq_list_len = elen; + break; + default: + wpa_printf(MSG_EXCESSIVE, + "Unknown QCA information element ignored (type=%d len=%lu)", + pos[3], (unsigned long) elen); + return -1; + } + break; +#endif + + default: + wpa_printf(MSG_EXCESSIVE, "unknown vendor specific " + "information element ignored (vendor OUI " + "%02x:%02x:%02x len=%lu)", + pos[0], pos[1], pos[2], (unsigned long) elen); + return -1; + } + + return 0; +} + + +/** + * ieee802_11_parse_elems - Parse information elements in management frames + * @start: Pointer to the start of IEs + * @len: Length of IE buffer in octets + * @elems: Data structure for parsed elements + * @show_errors: Whether to show parsing errors in debug log + * Returns: Parsing result + */ +ParseRes ieee802_11_parse_elems(const u8 *start, size_t len, + struct ieee802_11_elems *elems, + int show_errors) +{ + size_t left = len; + const u8 *pos = start; + int unknown = 0; + + os_memset(elems, 0, sizeof(*elems)); + + while (left >= 2) { + u8 id, elen; + + id = *pos++; + elen = *pos++; + left -= 2; + + if (elen > left) { + if (show_errors) { + wpa_printf(MSG_DEBUG, "IEEE 802.11 element " + "parse failed (id=%d elen=%d " + "left=%lu)", + id, elen, (unsigned long) left); + wpa_hexdump(MSG_MSGDUMP, "IEs", start, len); + } + return ParseFailed; + } + + switch (id) { + case WLAN_EID_SSID: + if (elen > SSID_MAX_LEN) { + wpa_printf(MSG_DEBUG, + "Ignored too long SSID element (elen=%u)", + elen); + break; + } + elems->ssid = pos; + elems->ssid_len = elen; + break; + case WLAN_EID_SUPP_RATES: + elems->supp_rates = pos; + elems->supp_rates_len = elen; + break; + case WLAN_EID_DS_PARAMS: + if (elen < 1) + break; + elems->ds_params = pos; + break; + case WLAN_EID_CF_PARAMS: + case WLAN_EID_TIM: + break; + case WLAN_EID_CHALLENGE: + elems->challenge = pos; + elems->challenge_len = elen; + break; + case WLAN_EID_ERP_INFO: + if (elen < 1) + break; + elems->erp_info = pos; + break; + case WLAN_EID_EXT_SUPP_RATES: + elems->ext_supp_rates = pos; + elems->ext_supp_rates_len = elen; + break; + case WLAN_EID_VENDOR_SPECIFIC: + if (ieee802_11_parse_vendor_specific(pos, elen, + elems, + show_errors)) + unknown++; + break; + case WLAN_EID_RSN: + elems->rsn_ie = pos; + elems->rsn_ie_len = elen; + break; + case WLAN_EID_PWR_CAPABILITY: + break; + case WLAN_EID_SUPPORTED_CHANNELS: + elems->supp_channels = pos; + elems->supp_channels_len = elen; + break; + case WLAN_EID_MOBILITY_DOMAIN: + if (elen < sizeof(struct rsn_mdie)) + break; + elems->mdie = pos; + elems->mdie_len = elen; + break; + case WLAN_EID_FAST_BSS_TRANSITION: + if (elen < sizeof(struct rsn_ftie)) + break; + elems->ftie = pos; + elems->ftie_len = elen; + break; + case WLAN_EID_TIMEOUT_INTERVAL: + if (elen != 5) + break; + elems->timeout_int = pos; + break; + case WLAN_EID_HT_CAP: + if (elen < sizeof(struct ieee80211_ht_capabilities)) + break; + elems->ht_capabilities = pos; + break; + case WLAN_EID_HT_OPERATION: + if (elen < sizeof(struct ieee80211_ht_operation)) + break; + elems->ht_operation = pos; + break; + case WLAN_EID_MESH_CONFIG: + elems->mesh_config = pos; + elems->mesh_config_len = elen; + break; + case WLAN_EID_MESH_ID: + elems->mesh_id = pos; + elems->mesh_id_len = elen; + break; + case WLAN_EID_PEER_MGMT: + elems->peer_mgmt = pos; + elems->peer_mgmt_len = elen; + break; + case WLAN_EID_VHT_CAP: + if (elen < sizeof(struct ieee80211_vht_capabilities)) + break; + elems->vht_capabilities = pos; + break; + case WLAN_EID_VHT_OPERATION: + if (elen < sizeof(struct ieee80211_vht_operation)) + break; + elems->vht_operation = pos; + break; + case WLAN_EID_VHT_OPERATING_MODE_NOTIFICATION: + if (elen != 1) + break; + elems->vht_opmode_notif = pos; + break; + case WLAN_EID_LINK_ID: + if (elen < 18) + break; + elems->link_id = pos; + break; + case WLAN_EID_INTERWORKING: + elems->interworking = pos; + elems->interworking_len = elen; + break; + case WLAN_EID_QOS_MAP_SET: + if (elen < 16) + break; + elems->qos_map_set = pos; + elems->qos_map_set_len = elen; + break; + case WLAN_EID_EXT_CAPAB: + elems->ext_capab = pos; + elems->ext_capab_len = elen; + break; + case WLAN_EID_BSS_MAX_IDLE_PERIOD: + if (elen < 3) + break; + elems->bss_max_idle_period = pos; + break; + case WLAN_EID_SSID_LIST: + elems->ssid_list = pos; + elems->ssid_list_len = elen; + break; + case WLAN_EID_AMPE: + elems->ampe = pos; + elems->ampe_len = elen; + break; + case WLAN_EID_MIC: + elems->mic = pos; + elems->mic_len = elen; + /* after mic everything is encrypted, so stop. */ + left = elen; + break; + case WLAN_EID_MULTI_BAND: + if (elems->mb_ies.nof_ies >= MAX_NOF_MB_IES_SUPPORTED) { + wpa_printf(MSG_MSGDUMP, + "IEEE 802.11 element parse ignored MB IE (id=%d elen=%d)", + id, elen); + break; + } + + elems->mb_ies.ies[elems->mb_ies.nof_ies].ie = pos; + elems->mb_ies.ies[elems->mb_ies.nof_ies].ie_len = elen; + elems->mb_ies.nof_ies++; + break; + default: + unknown++; + if (!show_errors) + break; + wpa_printf(MSG_MSGDUMP, "IEEE 802.11 element parse " + "ignored unknown element (id=%d elen=%d)", + id, elen); + break; + } + + left -= elen; + pos += elen; + } + + if (left) + return ParseFailed; + + return unknown ? ParseUnknown : ParseOK; +} + + +int ieee802_11_ie_count(const u8 *ies, size_t ies_len) +{ + int count = 0; + const u8 *pos, *end; + + if (ies == NULL) + return 0; + + pos = ies; + end = ies + ies_len; + + while (pos + 2 <= end) { + if (pos + 2 + pos[1] > end) + break; + count++; + pos += 2 + pos[1]; + } + + return count; +} + + +struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len, + u32 oui_type) +{ + struct wpabuf *buf; + const u8 *end, *pos, *ie; + + pos = ies; + end = ies + ies_len; + ie = NULL; + + while (pos + 1 < end) { + if (pos + 2 + pos[1] > end) + return NULL; + if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && + WPA_GET_BE32(&pos[2]) == oui_type) { + ie = pos; + break; + } + pos += 2 + pos[1]; + } + + if (ie == NULL) + return NULL; /* No specified vendor IE found */ + + buf = wpabuf_alloc(ies_len); + if (buf == NULL) + return NULL; + + /* + * There may be multiple vendor IEs in the message, so need to + * concatenate their data fields. + */ + while (pos + 1 < end) { + if (pos + 2 + pos[1] > end) + break; + if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && + WPA_GET_BE32(&pos[2]) == oui_type) + wpabuf_put_data(buf, pos + 6, pos[1] - 4); + pos += 2 + pos[1]; + } + + return buf; +} + + +const u8 * get_hdr_bssid(const struct ieee80211_hdr *hdr, size_t len) +{ + u16 fc, type, stype; + + /* + * PS-Poll frames are 16 bytes. All other frames are + * 24 bytes or longer. + */ + if (len < 16) + return NULL; + + fc = le_to_host16(hdr->frame_control); + type = WLAN_FC_GET_TYPE(fc); + stype = WLAN_FC_GET_STYPE(fc); + + switch (type) { + case WLAN_FC_TYPE_DATA: + if (len < 24) + return NULL; + switch (fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) { + case WLAN_FC_FROMDS | WLAN_FC_TODS: + case WLAN_FC_TODS: + return hdr->addr1; + case WLAN_FC_FROMDS: + return hdr->addr2; + default: + return NULL; + } + case WLAN_FC_TYPE_CTRL: + if (stype != WLAN_FC_STYPE_PSPOLL) + return NULL; + return hdr->addr1; + case WLAN_FC_TYPE_MGMT: + return hdr->addr3; + default: + return NULL; + } +} + + +int hostapd_config_wmm_ac(struct hostapd_wmm_ac_params wmm_ac_params[], + const char *name, const char *val) +{ + int num, v; + const char *pos; + struct hostapd_wmm_ac_params *ac; + + /* skip 'wme_ac_' or 'wmm_ac_' prefix */ + pos = name + 7; + if (os_strncmp(pos, "be_", 3) == 0) { + num = 0; + pos += 3; + } else if (os_strncmp(pos, "bk_", 3) == 0) { + num = 1; + pos += 3; + } else if (os_strncmp(pos, "vi_", 3) == 0) { + num = 2; + pos += 3; + } else if (os_strncmp(pos, "vo_", 3) == 0) { + num = 3; + pos += 3; + } else { + wpa_printf(MSG_ERROR, "Unknown WMM name '%s'", pos); + return -1; + } + + ac = &wmm_ac_params[num]; + + if (os_strcmp(pos, "aifs") == 0) { + v = atoi(val); + if (v < 1 || v > 255) { + wpa_printf(MSG_ERROR, "Invalid AIFS value %d", v); + return -1; + } + ac->aifs = v; + } else if (os_strcmp(pos, "cwmin") == 0) { + v = atoi(val); + if (v < 0 || v > 15) { + wpa_printf(MSG_ERROR, "Invalid cwMin value %d", v); + return -1; + } + ac->cwmin = v; + } else if (os_strcmp(pos, "cwmax") == 0) { + v = atoi(val); + if (v < 0 || v > 15) { + wpa_printf(MSG_ERROR, "Invalid cwMax value %d", v); + return -1; + } + ac->cwmax = v; + } else if (os_strcmp(pos, "txop_limit") == 0) { + v = atoi(val); + if (v < 0 || v > 0xffff) { + wpa_printf(MSG_ERROR, "Invalid txop value %d", v); + return -1; + } + ac->txop_limit = v; + } else if (os_strcmp(pos, "acm") == 0) { + v = atoi(val); + if (v < 0 || v > 1) { + wpa_printf(MSG_ERROR, "Invalid acm value %d", v); + return -1; + } + ac->admission_control_mandatory = v; + } else { + wpa_printf(MSG_ERROR, "Unknown wmm_ac_ field '%s'", pos); + return -1; + } + + return 0; +} + + +enum hostapd_hw_mode ieee80211_freq_to_chan(int freq, u8 *channel) +{ + u8 op_class; + + return ieee80211_freq_to_channel_ext(freq, 0, 0, &op_class, channel); +} + + +/** + * ieee80211_freq_to_channel_ext - Convert frequency into channel info + * for HT40 and VHT. DFS channels are not covered. + * @freq: Frequency (MHz) to convert + * @sec_channel: 0 = non-HT40, 1 = sec. channel above, -1 = sec. channel below + * @vht: 0 - non-VHT, 1 - 80 MHz + * @op_class: Buffer for returning operating class + * @channel: Buffer for returning channel number + * Returns: hw_mode on success, NUM_HOSTAPD_MODES on failure + */ +enum hostapd_hw_mode ieee80211_freq_to_channel_ext(unsigned int freq, + int sec_channel, int vht, + u8 *op_class, u8 *channel) +{ + /* TODO: more operating classes */ + + if (sec_channel > 1 || sec_channel < -1) + return NUM_HOSTAPD_MODES; + + if (freq >= 2412 && freq <= 2472) { + if ((freq - 2407) % 5) + return NUM_HOSTAPD_MODES; + + if (vht) + return NUM_HOSTAPD_MODES; + + /* 2.407 GHz, channels 1..13 */ + if (sec_channel == 1) + *op_class = 83; + else if (sec_channel == -1) + *op_class = 84; + else + *op_class = 81; + + *channel = (freq - 2407) / 5; + + return HOSTAPD_MODE_IEEE80211G; + } + + if (freq == 2484) { + if (sec_channel || vht) + return NUM_HOSTAPD_MODES; + + *op_class = 82; /* channel 14 */ + *channel = 14; + + return HOSTAPD_MODE_IEEE80211B; + } + + if (freq >= 4900 && freq < 5000) { + if ((freq - 4000) % 5) + return NUM_HOSTAPD_MODES; + *channel = (freq - 4000) / 5; + *op_class = 0; /* TODO */ + return HOSTAPD_MODE_IEEE80211A; + } + + /* 5 GHz, channels 36..48 */ + if (freq >= 5180 && freq <= 5240) { + if ((freq - 5000) % 5) + return NUM_HOSTAPD_MODES; + + if (sec_channel == 1) + *op_class = 116; + else if (sec_channel == -1) + *op_class = 117; + else if (vht) + *op_class = 128; + else + *op_class = 115; + + *channel = (freq - 5000) / 5; + + return HOSTAPD_MODE_IEEE80211A; + } + + /* 5 GHz, channels 149..161 */ + if (freq >= 5745 && freq <= 5805) { + if ((freq - 5000) % 5) + return NUM_HOSTAPD_MODES; + + if (sec_channel == 1) + *op_class = 126; + else if (sec_channel == -1) + *op_class = 127; + else if (vht) + *op_class = 128; + else + *op_class = 124; + + *channel = (freq - 5000) / 5; + + return HOSTAPD_MODE_IEEE80211A; + } + + /* 5 GHz, channels 149..169 */ + if (freq >= 5745 && freq <= 5845) { + if ((freq - 5000) % 5) + return NUM_HOSTAPD_MODES; + + *op_class = 125; + + *channel = (freq - 5000) / 5; + + return HOSTAPD_MODE_IEEE80211A; + } + + if (freq >= 5000 && freq < 5900) { + if ((freq - 5000) % 5) + return NUM_HOSTAPD_MODES; + *channel = (freq - 5000) / 5; + *op_class = 0; /* TODO */ + return HOSTAPD_MODE_IEEE80211A; + } + + /* 56.16 GHz, channel 1..4 */ + if (freq >= 56160 + 2160 * 1 && freq <= 56160 + 2160 * 4) { + if (sec_channel || vht) + return NUM_HOSTAPD_MODES; + + *channel = (freq - 56160) / 2160; + *op_class = 180; + + return HOSTAPD_MODE_IEEE80211AD; + } + + return NUM_HOSTAPD_MODES; +} + + +static const char *const us_op_class_cc[] = { + "US", "CA", NULL +}; + +static const char *const eu_op_class_cc[] = { + "AL", "AM", "AT", "AZ", "BA", "BE", "BG", "BY", "CH", "CY", "CZ", "DE", + "DK", "EE", "EL", "ES", "FI", "FR", "GE", "HR", "HU", "IE", "IS", "IT", + "LI", "LT", "LU", "LV", "MD", "ME", "MK", "MT", "NL", "NO", "PL", "PT", + "RO", "RS", "RU", "SE", "SI", "SK", "TR", "UA", "UK", NULL +}; + +static const char *const jp_op_class_cc[] = { + "JP", NULL +}; + +static const char *const cn_op_class_cc[] = { + "CN", NULL +}; + + +static int country_match(const char *const cc[], const char *const country) +{ + int i; + + if (country == NULL) + return 0; + for (i = 0; cc[i]; i++) { + if (cc[i][0] == country[0] && cc[i][1] == country[1]) + return 1; + } + + return 0; +} + + +static int ieee80211_chan_to_freq_us(u8 op_class, u8 chan) +{ + switch (op_class) { + case 12: /* channels 1..11 */ + case 32: /* channels 1..7; 40 MHz */ + case 33: /* channels 5..11; 40 MHz */ + if (chan < 1 || chan > 11) + return -1; + return 2407 + 5 * chan; + case 1: /* channels 36,40,44,48 */ + case 2: /* channels 52,56,60,64; dfs */ + case 22: /* channels 36,44; 40 MHz */ + case 23: /* channels 52,60; 40 MHz */ + case 27: /* channels 40,48; 40 MHz */ + case 28: /* channels 56,64; 40 MHz */ + if (chan < 36 || chan > 64) + return -1; + return 5000 + 5 * chan; + case 4: /* channels 100-144 */ + case 24: /* channels 100-140; 40 MHz */ + if (chan < 100 || chan > 144) + return -1; + return 5000 + 5 * chan; + case 3: /* channels 149,153,157,161 */ + case 25: /* channels 149,157; 40 MHz */ + case 26: /* channels 149,157; 40 MHz */ + case 30: /* channels 153,161; 40 MHz */ + case 31: /* channels 153,161; 40 MHz */ + if (chan < 149 || chan > 161) + return -1; + return 5000 + 5 * chan; + case 5: /* channels 149,153,157,161,165 */ + if (chan < 149 || chan > 165) + return -1; + return 5000 + 5 * chan; + case 34: /* 60 GHz band, channels 1..3 */ + if (chan < 1 || chan > 3) + return -1; + return 56160 + 2160 * chan; + } + return -1; +} + + +static int ieee80211_chan_to_freq_eu(u8 op_class, u8 chan) +{ + switch (op_class) { + case 4: /* channels 1..13 */ + case 11: /* channels 1..9; 40 MHz */ + case 12: /* channels 5..13; 40 MHz */ + if (chan < 1 || chan > 13) + return -1; + return 2407 + 5 * chan; + case 1: /* channels 36,40,44,48 */ + case 2: /* channels 52,56,60,64; dfs */ + case 5: /* channels 36,44; 40 MHz */ + case 6: /* channels 52,60; 40 MHz */ + case 8: /* channels 40,48; 40 MHz */ + case 9: /* channels 56,64; 40 MHz */ + if (chan < 36 || chan > 64) + return -1; + return 5000 + 5 * chan; + case 3: /* channels 100-140 */ + case 7: /* channels 100-132; 40 MHz */ + case 10: /* channels 104-136; 40 MHz */ + case 16: /* channels 100-140 */ + if (chan < 100 || chan > 140) + return -1; + return 5000 + 5 * chan; + case 17: /* channels 149,153,157,161,165,169 */ + if (chan < 149 || chan > 169) + return -1; + return 5000 + 5 * chan; + case 18: /* 60 GHz band, channels 1..4 */ + if (chan < 1 || chan > 4) + return -1; + return 56160 + 2160 * chan; + } + return -1; +} + + +static int ieee80211_chan_to_freq_jp(u8 op_class, u8 chan) +{ + switch (op_class) { + case 30: /* channels 1..13 */ + case 56: /* channels 1..9; 40 MHz */ + case 57: /* channels 5..13; 40 MHz */ + if (chan < 1 || chan > 13) + return -1; + return 2407 + 5 * chan; + case 31: /* channel 14 */ + if (chan != 14) + return -1; + return 2414 + 5 * chan; + case 1: /* channels 34,38,42,46(old) or 36,40,44,48 */ + case 32: /* channels 52,56,60,64 */ + case 33: /* channels 52,56,60,64 */ + case 36: /* channels 36,44; 40 MHz */ + case 37: /* channels 52,60; 40 MHz */ + case 38: /* channels 52,60; 40 MHz */ + case 41: /* channels 40,48; 40 MHz */ + case 42: /* channels 56,64; 40 MHz */ + case 43: /* channels 56,64; 40 MHz */ + if (chan < 34 || chan > 64) + return -1; + return 5000 + 5 * chan; + case 34: /* channels 100-140 */ + case 35: /* channels 100-140 */ + case 39: /* channels 100-132; 40 MHz */ + case 40: /* channels 100-132; 40 MHz */ + case 44: /* channels 104-136; 40 MHz */ + case 45: /* channels 104-136; 40 MHz */ + case 58: /* channels 100-140 */ + if (chan < 100 || chan > 140) + return -1; + return 5000 + 5 * chan; + case 59: /* 60 GHz band, channels 1..4 */ + if (chan < 1 || chan > 3) + return -1; + return 56160 + 2160 * chan; + } + return -1; +} + + +static int ieee80211_chan_to_freq_cn(u8 op_class, u8 chan) +{ + switch (op_class) { + case 7: /* channels 1..13 */ + case 8: /* channels 1..9; 40 MHz */ + case 9: /* channels 5..13; 40 MHz */ + if (chan < 1 || chan > 13) + return -1; + return 2407 + 5 * chan; + case 1: /* channels 36,40,44,48 */ + case 2: /* channels 52,56,60,64; dfs */ + case 4: /* channels 36,44; 40 MHz */ + case 5: /* channels 52,60; 40 MHz */ + if (chan < 36 || chan > 64) + return -1; + return 5000 + 5 * chan; + case 3: /* channels 149,153,157,161,165 */ + case 6: /* channels 149,157; 40 MHz */ + if (chan < 149 || chan > 165) + return -1; + return 5000 + 5 * chan; + } + return -1; +} + + +static int ieee80211_chan_to_freq_global(u8 op_class, u8 chan) +{ + /* Table E-4 in IEEE Std 802.11-2012 - Global operating classes */ + switch (op_class) { + case 81: + /* channels 1..13 */ + if (chan < 1 || chan > 13) + return -1; + return 2407 + 5 * chan; + case 82: + /* channel 14 */ + if (chan != 14) + return -1; + return 2414 + 5 * chan; + case 83: /* channels 1..9; 40 MHz */ + case 84: /* channels 5..13; 40 MHz */ + if (chan < 1 || chan > 13) + return -1; + return 2407 + 5 * chan; + case 115: /* channels 36,40,44,48; indoor only */ + case 116: /* channels 36,44; 40 MHz; indoor only */ + case 117: /* channels 40,48; 40 MHz; indoor only */ + case 118: /* channels 52,56,60,64; dfs */ + case 119: /* channels 52,60; 40 MHz; dfs */ + case 120: /* channels 56,64; 40 MHz; dfs */ + if (chan < 36 || chan > 64) + return -1; + return 5000 + 5 * chan; + case 121: /* channels 100-140 */ + case 122: /* channels 100-142; 40 MHz */ + case 123: /* channels 104-136; 40 MHz */ + if (chan < 100 || chan > 140) + return -1; + return 5000 + 5 * chan; + case 124: /* channels 149,153,157,161 */ + case 126: /* channels 149,157; 40 MHz */ + case 127: /* channels 153,161; 40 MHz */ + if (chan < 149 || chan > 161) + return -1; + return 5000 + 5 * chan; + case 125: /* channels 149,153,157,161,165,169 */ + if (chan < 149 || chan > 169) + return -1; + return 5000 + 5 * chan; + case 128: /* center freqs 42, 58, 106, 122, 138, 155; 80 MHz */ + case 130: /* center freqs 42, 58, 106, 122, 138, 155; 80 MHz */ + if (chan < 36 || chan > 161) + return -1; + return 5000 + 5 * chan; + case 129: /* center freqs 50, 114; 160 MHz */ + if (chan < 50 || chan > 114) + return -1; + return 5000 + 5 * chan; + case 180: /* 60 GHz band, channels 1..4 */ + if (chan < 1 || chan > 4) + return -1; + return 56160 + 2160 * chan; + } + return -1; +} + +/** + * ieee80211_chan_to_freq - Convert channel info to frequency + * @country: Country code, if known; otherwise, global operating class is used + * @op_class: Operating class + * @chan: Channel number + * Returns: Frequency in MHz or -1 if the specified channel is unknown + */ +int ieee80211_chan_to_freq(const char *country, u8 op_class, u8 chan) +{ + int freq; + + if (country_match(us_op_class_cc, country)) { + freq = ieee80211_chan_to_freq_us(op_class, chan); + if (freq > 0) + return freq; + } + + if (country_match(eu_op_class_cc, country)) { + freq = ieee80211_chan_to_freq_eu(op_class, chan); + if (freq > 0) + return freq; + } + + if (country_match(jp_op_class_cc, country)) { + freq = ieee80211_chan_to_freq_jp(op_class, chan); + if (freq > 0) + return freq; + } + + if (country_match(cn_op_class_cc, country)) { + freq = ieee80211_chan_to_freq_cn(op_class, chan); + if (freq > 0) + return freq; + } + + return ieee80211_chan_to_freq_global(op_class, chan); +} + + +int ieee80211_is_dfs(int freq) +{ + /* TODO: this could be more accurate to better cover all domains */ + return (freq >= 5260 && freq <= 5320) || (freq >= 5500 && freq <= 5700); +} + + +static int is_11b(u8 rate) +{ + return rate == 0x02 || rate == 0x04 || rate == 0x0b || rate == 0x16; +} + + +int supp_rates_11b_only(struct ieee802_11_elems *elems) +{ + int num_11b = 0, num_others = 0; + int i; + + if (elems->supp_rates == NULL && elems->ext_supp_rates == NULL) + return 0; + + for (i = 0; elems->supp_rates && i < elems->supp_rates_len; i++) { + if (is_11b(elems->supp_rates[i])) + num_11b++; + else + num_others++; + } + + for (i = 0; elems->ext_supp_rates && i < elems->ext_supp_rates_len; + i++) { + if (is_11b(elems->ext_supp_rates[i])) + num_11b++; + else + num_others++; + } + + return num_11b > 0 && num_others == 0; +} + + +const char * fc2str(u16 fc) +{ + u16 stype = WLAN_FC_GET_STYPE(fc); +#define C2S(x) case x: return #x; + + switch (WLAN_FC_GET_TYPE(fc)) { + case WLAN_FC_TYPE_MGMT: + switch (stype) { + C2S(WLAN_FC_STYPE_ASSOC_REQ) + C2S(WLAN_FC_STYPE_ASSOC_RESP) + C2S(WLAN_FC_STYPE_REASSOC_REQ) + C2S(WLAN_FC_STYPE_REASSOC_RESP) + C2S(WLAN_FC_STYPE_PROBE_REQ) + C2S(WLAN_FC_STYPE_PROBE_RESP) + C2S(WLAN_FC_STYPE_BEACON) + C2S(WLAN_FC_STYPE_ATIM) + C2S(WLAN_FC_STYPE_DISASSOC) + C2S(WLAN_FC_STYPE_AUTH) + C2S(WLAN_FC_STYPE_DEAUTH) + C2S(WLAN_FC_STYPE_ACTION) + } + break; + case WLAN_FC_TYPE_CTRL: + switch (stype) { + C2S(WLAN_FC_STYPE_PSPOLL) + C2S(WLAN_FC_STYPE_RTS) + C2S(WLAN_FC_STYPE_CTS) + C2S(WLAN_FC_STYPE_ACK) + C2S(WLAN_FC_STYPE_CFEND) + C2S(WLAN_FC_STYPE_CFENDACK) + } + break; + case WLAN_FC_TYPE_DATA: + switch (stype) { + C2S(WLAN_FC_STYPE_DATA) + C2S(WLAN_FC_STYPE_DATA_CFACK) + C2S(WLAN_FC_STYPE_DATA_CFPOLL) + C2S(WLAN_FC_STYPE_DATA_CFACKPOLL) + C2S(WLAN_FC_STYPE_NULLFUNC) + C2S(WLAN_FC_STYPE_CFACK) + C2S(WLAN_FC_STYPE_CFPOLL) + C2S(WLAN_FC_STYPE_CFACKPOLL) + C2S(WLAN_FC_STYPE_QOS_DATA) + C2S(WLAN_FC_STYPE_QOS_DATA_CFACK) + C2S(WLAN_FC_STYPE_QOS_DATA_CFPOLL) + C2S(WLAN_FC_STYPE_QOS_DATA_CFACKPOLL) + C2S(WLAN_FC_STYPE_QOS_NULL) + C2S(WLAN_FC_STYPE_QOS_CFPOLL) + C2S(WLAN_FC_STYPE_QOS_CFACKPOLL) + } + break; + } + return "WLAN_FC_TYPE_UNKNOWN"; +#undef C2S +} + + +int mb_ies_info_by_ies(struct mb_ies_info *info, const u8 *ies_buf, + size_t ies_len) +{ + os_memset(info, 0, sizeof(*info)); + + while (ies_buf && ies_len >= 2 && + info->nof_ies < MAX_NOF_MB_IES_SUPPORTED) { + size_t len = 2 + ies_buf[1]; + + if (len > ies_len) { + wpa_hexdump(MSG_DEBUG, "Truncated IEs", + ies_buf, ies_len); + return -1; + } + + if (ies_buf[0] == WLAN_EID_MULTI_BAND) { + wpa_printf(MSG_DEBUG, "MB IE of %zu bytes found", len); + info->ies[info->nof_ies].ie = ies_buf + 2; + info->ies[info->nof_ies].ie_len = ies_buf[1]; + info->nof_ies++; + } + + ies_len -= len; + ies_buf += len; + } + + return 0; +} + + +struct wpabuf * mb_ies_by_info(struct mb_ies_info *info) +{ + struct wpabuf *mb_ies = NULL; + + WPA_ASSERT(info != NULL); + + if (info->nof_ies) { + u8 i; + size_t mb_ies_size = 0; + + for (i = 0; i < info->nof_ies; i++) + mb_ies_size += 2 + info->ies[i].ie_len; + + mb_ies = wpabuf_alloc(mb_ies_size); + if (mb_ies) { + for (i = 0; i < info->nof_ies; i++) { + wpabuf_put_u8(mb_ies, WLAN_EID_MULTI_BAND); + wpabuf_put_u8(mb_ies, info->ies[i].ie_len); + wpabuf_put_data(mb_ies, + info->ies[i].ie, + info->ies[i].ie_len); + } + } + } + + return mb_ies; +} diff --git a/beken_os/beken378/func/hostapd-2.5/src/common/ieee802_11_common.h b/beken_os/beken378/func/hostapd-2.5/src/common/ieee802_11_common.h new file mode 100755 index 0000000..afd4d9a --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/common/ieee802_11_common.h @@ -0,0 +1,130 @@ +/* + * IEEE 802.11 Common routines + * Copyright (c) 2002-2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef IEEE802_11_COMMON_H +#define IEEE802_11_COMMON_H + +#include "common/defs.h" + +#define MAX_NOF_MB_IES_SUPPORTED 5 + +struct mb_ies_info { + struct { + const u8 *ie; + u8 ie_len; + } ies[MAX_NOF_MB_IES_SUPPORTED]; + u8 nof_ies; +}; + +/* Parsed Information Elements */ +struct ieee802_11_elems { + const u8 *ssid; + const u8 *supp_rates; + const u8 *ds_params; + const u8 *challenge; + const u8 *erp_info; + const u8 *ext_supp_rates; + const u8 *wpa_ie; + const u8 *rsn_ie; + const u8 *wmm; /* WMM Information or Parameter Element */ + const u8 *wmm_tspec; + const u8 *wps_ie; + const u8 *supp_channels; + const u8 *mdie; + const u8 *ftie; + const u8 *timeout_int; + const u8 *ht_capabilities; + const u8 *ht_operation; + const u8 *mesh_config; + const u8 *mesh_id; + const u8 *peer_mgmt; + const u8 *vht_capabilities; + const u8 *vht_operation; + const u8 *vht_opmode_notif; + const u8 *vendor_ht_cap; + const u8 *vendor_vht; + const u8 *p2p; + const u8 *wfd; + const u8 *link_id; + const u8 *interworking; + const u8 *qos_map_set; + const u8 *hs20; + const u8 *ext_capab; + const u8 *bss_max_idle_period; + const u8 *ssid_list; + const u8 *osen; + const u8 *ampe; + const u8 *mic; + const u8 *pref_freq_list; + + u8 ssid_len; + u8 supp_rates_len; + u8 challenge_len; + u8 ext_supp_rates_len; + u8 wpa_ie_len; + u8 rsn_ie_len; + u8 wmm_len; /* 7 = WMM Information; 24 = WMM Parameter */ + u8 wmm_tspec_len; + u8 wps_ie_len; + u8 supp_channels_len; + u8 mdie_len; + u8 ftie_len; + u8 mesh_config_len; + u8 mesh_id_len; + u8 peer_mgmt_len; + u8 vendor_ht_cap_len; + u8 vendor_vht_len; + u8 p2p_len; + u8 wfd_len; + u8 interworking_len; + u8 qos_map_set_len; + u8 hs20_len; + u8 ext_capab_len; + u8 ssid_list_len; + u8 osen_len; + u8 ampe_len; + u8 mic_len; + u8 pref_freq_list_len; + struct mb_ies_info mb_ies; +}; + +typedef enum { ParseOK = 0, ParseUnknown = 1, ParseFailed = -1 } ParseRes; + +ParseRes ieee802_11_parse_elems(const u8 *start, size_t len, + struct ieee802_11_elems *elems, + int show_errors); +int ieee802_11_ie_count(const u8 *ies, size_t ies_len); +struct wpabuf * ieee802_11_vendor_ie_concat(const u8 *ies, size_t ies_len, + u32 oui_type); +struct ieee80211_hdr; +const u8 * get_hdr_bssid(const struct ieee80211_hdr *hdr, size_t len); + +struct hostapd_wmm_ac_params { + int cwmin; + int cwmax; + int aifs; + int txop_limit; /* in units of 32us */ + int admission_control_mandatory; +}; + +int hostapd_config_wmm_ac(struct hostapd_wmm_ac_params wmm_ac_params[], + const char *name, const char *val); +enum hostapd_hw_mode ieee80211_freq_to_chan(int freq, u8 *channel); +int ieee80211_chan_to_freq(const char *country, u8 op_class, u8 chan); +enum hostapd_hw_mode ieee80211_freq_to_channel_ext(unsigned int freq, + int sec_channel, int vht, + u8 *op_class, u8 *channel); +int ieee80211_is_dfs(int freq); + +int supp_rates_11b_only(struct ieee802_11_elems *elems); +int mb_ies_info_by_ies(struct mb_ies_info *info, const u8 *ies_buf, + size_t ies_len); +struct wpabuf * mb_ies_by_info(struct mb_ies_info *info); + +const char * fc2str(u16 fc); +#endif /* IEEE802_11_COMMON_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/common/ieee802_11_defs.h b/beken_os/beken378/func/hostapd-2.5/src/common/ieee802_11_defs.h new file mode 100755 index 0000000..665a71f --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/common/ieee802_11_defs.h @@ -0,0 +1,1466 @@ +/* + * IEEE 802.11 Frame type definitions + * Copyright (c) 2002-2015, Jouni Malinen + * Copyright (c) 2007-2008 Intel Corporation + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef IEEE802_11_DEFS_H +#define IEEE802_11_DEFS_H + +#include "common.h" + +/* IEEE 802.11 defines */ + +#define WLAN_FC_PVER 0x0003 +#define WLAN_FC_TODS 0x0100 +#define WLAN_FC_FROMDS 0x0200 +#define WLAN_FC_MOREFRAG 0x0400 +#define WLAN_FC_RETRY 0x0800 +#define WLAN_FC_PWRMGT 0x1000 +#define WLAN_FC_MOREDATA 0x2000 +#define WLAN_FC_ISWEP 0x4000 +#define WLAN_FC_ORDER 0x8000 + +#define WLAN_FC_GET_TYPE(fc) (((fc) & 0x000c) >> 2) +#define WLAN_FC_GET_STYPE(fc) (((fc) & 0x00f0) >> 4) + +#define WLAN_INVALID_MGMT_SEQ 0xFFFF + +#define WLAN_GET_SEQ_FRAG(seq) ((seq) & (BIT(3) | BIT(2) | BIT(1) | BIT(0))) +#define WLAN_GET_SEQ_SEQ(seq) \ + (((seq) & (~(BIT(3) | BIT(2) | BIT(1) | BIT(0)))) >> 4) + +#define WLAN_FC_TYPE_MGMT 0 +#define WLAN_FC_TYPE_CTRL 1 +#define WLAN_FC_TYPE_DATA 2 + +/* management */ +#define WLAN_FC_STYPE_ASSOC_REQ 0 +#define WLAN_FC_STYPE_ASSOC_RESP 1 +#define WLAN_FC_STYPE_REASSOC_REQ 2 +#define WLAN_FC_STYPE_REASSOC_RESP 3 +#define WLAN_FC_STYPE_PROBE_REQ 4 +#define WLAN_FC_STYPE_PROBE_RESP 5 +#define WLAN_FC_STYPE_BEACON 8 +#define WLAN_FC_STYPE_ATIM 9 +#define WLAN_FC_STYPE_DISASSOC 10 +#define WLAN_FC_STYPE_AUTH 11 +#define WLAN_FC_STYPE_DEAUTH 12 +#define WLAN_FC_STYPE_ACTION 13 + +/* control */ +#define WLAN_FC_STYPE_PSPOLL 10 +#define WLAN_FC_STYPE_RTS 11 +#define WLAN_FC_STYPE_CTS 12 +#define WLAN_FC_STYPE_ACK 13 +#define WLAN_FC_STYPE_CFEND 14 +#define WLAN_FC_STYPE_CFENDACK 15 + +/* data */ +#define WLAN_FC_STYPE_DATA 0 +#define WLAN_FC_STYPE_DATA_CFACK 1 +#define WLAN_FC_STYPE_DATA_CFPOLL 2 +#define WLAN_FC_STYPE_DATA_CFACKPOLL 3 +#define WLAN_FC_STYPE_NULLFUNC 4 +#define WLAN_FC_STYPE_CFACK 5 +#define WLAN_FC_STYPE_CFPOLL 6 +#define WLAN_FC_STYPE_CFACKPOLL 7 +#define WLAN_FC_STYPE_QOS_DATA 8 +#define WLAN_FC_STYPE_QOS_DATA_CFACK 9 +#define WLAN_FC_STYPE_QOS_DATA_CFPOLL 10 +#define WLAN_FC_STYPE_QOS_DATA_CFACKPOLL 11 +#define WLAN_FC_STYPE_QOS_NULL 12 +#define WLAN_FC_STYPE_QOS_CFPOLL 14 +#define WLAN_FC_STYPE_QOS_CFACKPOLL 15 + +/* Authentication algorithms */ +#define WLAN_AUTH_OPEN 0 +#define WLAN_AUTH_SHARED_KEY 1 +#define WLAN_AUTH_FT 2 +#define WLAN_AUTH_SAE 3 +#define WLAN_AUTH_LEAP 128 + +#define WLAN_AUTH_CHALLENGE_LEN 128 + +#define WLAN_CAPABILITY_ESS BIT(0) +#define WLAN_CAPABILITY_IBSS BIT(1) +#define WLAN_CAPABILITY_CF_POLLABLE BIT(2) +#define WLAN_CAPABILITY_CF_POLL_REQUEST BIT(3) +#define WLAN_CAPABILITY_PRIVACY BIT(4) +#define WLAN_CAPABILITY_SHORT_PREAMBLE BIT(5) +#define WLAN_CAPABILITY_PBCC BIT(6) +#define WLAN_CAPABILITY_CHANNEL_AGILITY BIT(7) +#define WLAN_CAPABILITY_SPECTRUM_MGMT BIT(8) +#define WLAN_CAPABILITY_SHORT_SLOT_TIME BIT(10) +#define WLAN_CAPABILITY_DSSS_OFDM BIT(13) + +/* Status codes (IEEE 802.11-2007, 7.3.1.9, Table 7-23) */ +#define WLAN_STATUS_SUCCESS 0 +#define WLAN_STATUS_UNSPECIFIED_FAILURE 1 +#define WLAN_STATUS_TDLS_WAKEUP_ALTERNATE 2 +#define WLAN_STATUS_TDLS_WAKEUP_REJECT 3 +#define WLAN_STATUS_SECURITY_DISABLED 5 +#define WLAN_STATUS_UNACCEPTABLE_LIFETIME 6 +#define WLAN_STATUS_NOT_IN_SAME_BSS 7 +#define WLAN_STATUS_CAPS_UNSUPPORTED 10 +#define WLAN_STATUS_REASSOC_NO_ASSOC 11 +#define WLAN_STATUS_ASSOC_DENIED_UNSPEC 12 +#define WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG 13 +#define WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION 14 +#define WLAN_STATUS_CHALLENGE_FAIL 15 +#define WLAN_STATUS_AUTH_TIMEOUT 16 +#define WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA 17 +#define WLAN_STATUS_ASSOC_DENIED_RATES 18 +/* IEEE 802.11b */ +#define WLAN_STATUS_ASSOC_DENIED_NOSHORT 19 +#define WLAN_STATUS_ASSOC_DENIED_NOPBCC 20 +#define WLAN_STATUS_ASSOC_DENIED_NOAGILITY 21 +/* IEEE 802.11h */ +#define WLAN_STATUS_SPEC_MGMT_REQUIRED 22 +#define WLAN_STATUS_PWR_CAPABILITY_NOT_VALID 23 +#define WLAN_STATUS_SUPPORTED_CHANNEL_NOT_VALID 24 +/* IEEE 802.11g */ +#define WLAN_STATUS_ASSOC_DENIED_NO_SHORT_SLOT_TIME 25 +#define WLAN_STATUS_ASSOC_DENIED_NO_DSSS_OFDM 26 +#define WLAN_STATUS_ASSOC_DENIED_NO_HT 27 +#define WLAN_STATUS_R0KH_UNREACHABLE 28 +#define WLAN_STATUS_ASSOC_DENIED_NO_PCO 29 +/* IEEE 802.11w */ +#define WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY 30 +#define WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION 31 +#define WLAN_STATUS_UNSPECIFIED_QOS_FAILURE 32 +#define WLAN_STATUS_REQUEST_DECLINED 37 +#define WLAN_STATUS_INVALID_PARAMETERS 38 +/* IEEE 802.11i */ +#define WLAN_STATUS_INVALID_IE 40 +#define WLAN_STATUS_GROUP_CIPHER_NOT_VALID 41 +#define WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID 42 +#define WLAN_STATUS_AKMP_NOT_VALID 43 +#define WLAN_STATUS_UNSUPPORTED_RSN_IE_VERSION 44 +#define WLAN_STATUS_INVALID_RSN_IE_CAPAB 45 +#define WLAN_STATUS_CIPHER_REJECTED_PER_POLICY 46 +#define WLAN_STATUS_TS_NOT_CREATED 47 +#define WLAN_STATUS_DIRECT_LINK_NOT_ALLOWED 48 +#define WLAN_STATUS_DEST_STA_NOT_PRESENT 49 +#define WLAN_STATUS_DEST_STA_NOT_QOS_STA 50 +#define WLAN_STATUS_ASSOC_DENIED_LISTEN_INT_TOO_LARGE 51 +/* IEEE 802.11r */ +#define WLAN_STATUS_INVALID_FT_ACTION_FRAME_COUNT 52 +#define WLAN_STATUS_INVALID_PMKID 53 +#define WLAN_STATUS_INVALID_MDIE 54 +#define WLAN_STATUS_INVALID_FTIE 55 +#define WLAN_STATUS_GAS_ADV_PROTO_NOT_SUPPORTED 59 +#define WLAN_STATUS_NO_OUTSTANDING_GAS_REQ 60 +#define WLAN_STATUS_GAS_RESP_NOT_RECEIVED 61 +#define WLAN_STATUS_STA_TIMED_OUT_WAITING_FOR_GAS_RESP 62 +#define WLAN_STATUS_GAS_RESP_LARGER_THAN_LIMIT 63 +#define WLAN_STATUS_REQ_REFUSED_HOME 64 +#define WLAN_STATUS_ADV_SRV_UNREACHABLE 65 +#define WLAN_STATUS_REQ_REFUSED_SSPN 67 +#define WLAN_STATUS_REQ_REFUSED_UNAUTH_ACCESS 68 +#define WLAN_STATUS_INVALID_RSNIE 72 +#define WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ 76 +#define WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED 77 +#define WLAN_STATUS_TRANSMISSION_FAILURE 79 +#define WLAN_STATUS_REJECTED_WITH_SUGGESTED_BSS_TRANSITION 82 +#define WLAN_STATUS_PENDING_ADMITTING_FST_SESSION 86 +#define WLAN_STATUS_QUERY_RESP_OUTSTANDING 95 +#define WLAN_STATUS_DENIED_WITH_SUGGESTED_BAND_AND_CHANNEL 99 +#define WLAN_STATUS_ASSOC_DENIED_NO_VHT 104 + +/* Reason codes (IEEE 802.11-2007, 7.3.1.7, Table 7-22) */ +#define WLAN_REASON_UNSPECIFIED 1 +#define WLAN_REASON_PREV_AUTH_NOT_VALID 2 +#define WLAN_REASON_DEAUTH_LEAVING 3 +#define WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY 4 +#define WLAN_REASON_DISASSOC_AP_BUSY 5 +#define WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA 6 +#define WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA 7 +#define WLAN_REASON_DISASSOC_STA_HAS_LEFT 8 +#define WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH 9 +/* IEEE 802.11h */ +#define WLAN_REASON_PWR_CAPABILITY_NOT_VALID 10 +#define WLAN_REASON_SUPPORTED_CHANNEL_NOT_VALID 11 +/* IEEE 802.11i */ +#define WLAN_REASON_INVALID_IE 13 +#define WLAN_REASON_MICHAEL_MIC_FAILURE 14 +#define WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT 15 +#define WLAN_REASON_GROUP_KEY_UPDATE_TIMEOUT 16 +#define WLAN_REASON_IE_IN_4WAY_DIFFERS 17 +#define WLAN_REASON_GROUP_CIPHER_NOT_VALID 18 +#define WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID 19 +#define WLAN_REASON_AKMP_NOT_VALID 20 +#define WLAN_REASON_UNSUPPORTED_RSN_IE_VERSION 21 +#define WLAN_REASON_INVALID_RSN_IE_CAPAB 22 +#define WLAN_REASON_IEEE_802_1X_AUTH_FAILED 23 +#define WLAN_REASON_CIPHER_SUITE_REJECTED 24 +#define WLAN_REASON_TDLS_TEARDOWN_UNREACHABLE 25 +#define WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED 26 +/* IEEE 802.11e */ +#define WLAN_REASON_DISASSOC_LOW_ACK 34 +/* IEEE 802.11s */ +#define WLAN_REASON_MESH_PEERING_CANCELLED 52 +#define WLAN_REASON_MESH_MAX_PEERS 53 +#define WLAN_REASON_MESH_CONFIG_POLICY_VIOLATION 54 +#define WLAN_REASON_MESH_CLOSE_RCVD 55 +#define WLAN_REASON_MESH_MAX_RETRIES 56 +#define WLAN_REASON_MESH_CONFIRM_TIMEOUT 57 +#define WLAN_REASON_MESH_INVALID_GTK 58 +#define WLAN_REASON_MESH_INCONSISTENT_PARAMS 59 +#define WLAN_REASON_MESH_INVALID_SECURITY_CAP 60 + +#define WLAN_EID_TIM_LEN 6 + +/* Information Element IDs */ +#define WLAN_EID_SSID 0 +#define WLAN_EID_SUPP_RATES 1 +#define WLAN_EID_FH_PARAMS 2 +#define WLAN_EID_DS_PARAMS 3 +#define WLAN_EID_CF_PARAMS 4 +#define WLAN_EID_TIM 5 +#define WLAN_EID_IBSS_PARAMS 6 +#define WLAN_EID_COUNTRY 7 +#define WLAN_EID_BSS_LOAD 11 +#define WLAN_EID_CHALLENGE 16 +/* EIDs defined by IEEE 802.11h - START */ +#define WLAN_EID_PWR_CONSTRAINT 32 +#define WLAN_EID_PWR_CAPABILITY 33 +#define WLAN_EID_TPC_REQUEST 34 +#define WLAN_EID_TPC_REPORT 35 +#define WLAN_EID_SUPPORTED_CHANNELS 36 +#define WLAN_EID_CHANNEL_SWITCH 37 +#define WLAN_EID_MEASURE_REQUEST 38 +#define WLAN_EID_MEASURE_REPORT 39 +#define WLAN_EID_QUITE 40 +#define WLAN_EID_IBSS_DFS 41 +/* EIDs defined by IEEE 802.11h - END */ +#define WLAN_EID_ERP_INFO 42 +#define WLAN_EID_HT_CAP 45 +#define WLAN_EID_QOS 46 +#define WLAN_EID_RSN 48 +#define WLAN_EID_EXT_SUPP_RATES 50 +#define WLAN_EID_NEIGHBOR_REPORT 52 +#define WLAN_EID_MOBILITY_DOMAIN 54 +#define WLAN_EID_FAST_BSS_TRANSITION 55 +#define WLAN_EID_TIMEOUT_INTERVAL 56 +#define WLAN_EID_RIC_DATA 57 +#define WLAN_EID_SUPPORTED_OPERATING_CLASSES 59 +#define WLAN_EID_HT_OPERATION 61 +#define WLAN_EID_SECONDARY_CHANNEL_OFFSET 62 +#define WLAN_EID_WAPI 68 +#define WLAN_EID_TIME_ADVERTISEMENT 69 +#define WLAN_EID_RRM_ENABLED_CAPABILITIES 70 +#define WLAN_EID_20_40_BSS_COEXISTENCE 72 +#define WLAN_EID_20_40_BSS_INTOLERANT 73 +#define WLAN_EID_OVERLAPPING_BSS_SCAN_PARAMS 74 +#define WLAN_EID_MMIE 76 +#define WLAN_EID_SSID_LIST 84 +#define WLAN_EID_BSS_MAX_IDLE_PERIOD 90 +#define WLAN_EID_TFS_REQ 91 +#define WLAN_EID_TFS_RESP 92 +#define WLAN_EID_WNMSLEEP 93 +#define WLAN_EID_TIME_ZONE 98 +#define WLAN_EID_LINK_ID 101 +#define WLAN_EID_INTERWORKING 107 +#define WLAN_EID_ADV_PROTO 108 +#define WLAN_EID_QOS_MAP_SET 110 +#define WLAN_EID_ROAMING_CONSORTIUM 111 +#define WLAN_EID_MESH_CONFIG 113 +#define WLAN_EID_MESH_ID 114 +#define WLAN_EID_PEER_MGMT 117 +#define WLAN_EID_EXT_CAPAB 127 +#define WLAN_EID_AMPE 139 +#define WLAN_EID_MIC 140 +#define WLAN_EID_CCKM 156 +#define WLAN_EID_MULTI_BAND 158 +#define WLAN_EID_SESSION_TRANSITION 164 +#define WLAN_EID_VHT_CAP 191 +#define WLAN_EID_VHT_OPERATION 192 +#define WLAN_EID_VHT_EXTENDED_BSS_LOAD 193 +#define WLAN_EID_VHT_WIDE_BW_CHSWITCH 194 +#define WLAN_EID_VHT_TRANSMIT_POWER_ENVELOPE 195 +#define WLAN_EID_VHT_CHANNEL_SWITCH_WRAPPER 196 +#define WLAN_EID_VHT_AID 197 +#define WLAN_EID_VHT_QUIET_CHANNEL 198 +#define WLAN_EID_VHT_OPERATING_MODE_NOTIFICATION 199 +#define WLAN_EID_VENDOR_SPECIFIC 221 + + +/* Action frame categories (IEEE 802.11-2007, 7.3.1.11, Table 7-24) */ +#define WLAN_ACTION_SPECTRUM_MGMT 0 +#define WLAN_ACTION_QOS 1 +#define WLAN_ACTION_DLS 2 +#define WLAN_ACTION_BLOCK_ACK 3 +#define WLAN_ACTION_PUBLIC 4 +#define WLAN_ACTION_RADIO_MEASUREMENT 5 +#define WLAN_ACTION_FT 6 +#define WLAN_ACTION_HT 7 +#define WLAN_ACTION_SA_QUERY 8 +#define WLAN_ACTION_PROTECTED_DUAL 9 +#define WLAN_ACTION_WNM 10 +#define WLAN_ACTION_UNPROTECTED_WNM 11 +#define WLAN_ACTION_TDLS 12 +#define WLAN_ACTION_SELF_PROTECTED 15 +#define WLAN_ACTION_WMM 17 /* WMM Specification 1.1 */ +#define WLAN_ACTION_FST 18 +#define WLAN_ACTION_VENDOR_SPECIFIC 127 + +/* Public action codes */ +#define WLAN_PA_20_40_BSS_COEX 0 +#define WLAN_PA_VENDOR_SPECIFIC 9 +#define WLAN_PA_GAS_INITIAL_REQ 10 +#define WLAN_PA_GAS_INITIAL_RESP 11 +#define WLAN_PA_GAS_COMEBACK_REQ 12 +#define WLAN_PA_GAS_COMEBACK_RESP 13 +#define WLAN_TDLS_DISCOVERY_RESPONSE 14 + +/* Protected Dual of Public Action frames */ +#define WLAN_PROT_DSE_ENABLEMENT 1 +#define WLAN_PROT_DSE_DEENABLEMENT 2 +#define WLAN_PROT_EXT_CSA 4 +#define WLAN_PROT_MEASUREMENT_REQ 5 +#define WLAN_PROT_MEASUREMENT_REPORT 6 +#define WLAN_PROT_DSE_POWER_CONSTRAINT 8 +#define WLAN_PROT_VENDOR_SPECIFIC 9 +#define WLAN_PROT_GAS_INITIAL_REQ 10 +#define WLAN_PROT_GAS_INITIAL_RESP 11 +#define WLAN_PROT_GAS_COMEBACK_REQ 12 +#define WLAN_PROT_GAS_COMEBACK_RESP 13 + +/* SA Query Action frame (IEEE 802.11w/D8.0, 7.4.9) */ +#define WLAN_SA_QUERY_REQUEST 0 +#define WLAN_SA_QUERY_RESPONSE 1 + +#define WLAN_SA_QUERY_TR_ID_LEN 2 + +/* TDLS action codes */ +#define WLAN_TDLS_SETUP_REQUEST 0 +#define WLAN_TDLS_SETUP_RESPONSE 1 +#define WLAN_TDLS_SETUP_CONFIRM 2 +#define WLAN_TDLS_TEARDOWN 3 +#define WLAN_TDLS_PEER_TRAFFIC_INDICATION 4 +#define WLAN_TDLS_CHANNEL_SWITCH_REQUEST 5 +#define WLAN_TDLS_CHANNEL_SWITCH_RESPONSE 6 +#define WLAN_TDLS_PEER_PSM_REQUEST 7 +#define WLAN_TDLS_PEER_PSM_RESPONSE 8 +#define WLAN_TDLS_PEER_TRAFFIC_RESPONSE 9 +#define WLAN_TDLS_DISCOVERY_REQUEST 10 + +/* Radio Measurement Action codes */ +#define WLAN_RRM_RADIO_MEASUREMENT_REQUEST 0 +#define WLAN_RRM_RADIO_MEASUREMENT_REPORT 1 +#define WLAN_RRM_LINK_MEASUREMENT_REQUEST 2 +#define WLAN_RRM_LINK_MEASUREMENT_REPORT 3 +#define WLAN_RRM_NEIGHBOR_REPORT_REQUEST 4 +#define WLAN_RRM_NEIGHBOR_REPORT_RESPONSE 5 + +/* Radio Measurement capabilities (from RRM Capabilities IE) */ +/* byte 1 (out of 5) */ +#define WLAN_RRM_CAPS_LINK_MEASUREMENT BIT(0) +#define WLAN_RRM_CAPS_NEIGHBOR_REPORT BIT(1) + +/* Timeout Interval Type */ +#define WLAN_TIMEOUT_REASSOC_DEADLINE 1 +#define WLAN_TIMEOUT_KEY_LIFETIME 2 +#define WLAN_TIMEOUT_ASSOC_COMEBACK 3 + +/* Interworking element (IEEE 802.11u) - Access Network Options */ +#define INTERWORKING_ANO_ACCESS_NETWORK_MASK 0x0f +#define INTERWORKING_ANO_INTERNET 0x10 +#define INTERWORKING_ANO_ASRA 0x20 +#define INTERWORKING_ANO_ESR 0x40 +#define INTERWORKING_ANO_UESA 0x80 + +#define INTERWORKING_ANT_PRIVATE 0 +#define INTERWORKING_ANT_PRIVATE_WITH_GUEST 1 +#define INTERWORKING_ANT_CHARGEABLE_PUBLIC 2 +#define INTERWORKING_ANT_FREE_PUBLIC 3 +#define INTERWORKING_ANT_PERSONAL_DEVICE 4 +#define INTERWORKING_ANT_EMERGENCY_SERVICES 5 +#define INTERWORKING_ANT_TEST 6 +#define INTERWORKING_ANT_WILDCARD 15 + +/* Advertisement Protocol ID definitions (IEEE Std 802.11u-2011) */ +enum adv_proto_id { + ACCESS_NETWORK_QUERY_PROTOCOL = 0, + MIH_INFO_SERVICE = 1, + MIH_CMD_AND_EVENT_DISCOVERY = 2, + EMERGENCY_ALERT_SYSTEM = 3, + ADV_PROTO_VENDOR_SPECIFIC = 221 +}; + +/* Access Network Query Protocol info ID definitions (IEEE Std 802.11u-2011) */ +enum anqp_info_id { + ANQP_QUERY_LIST = 256, + ANQP_CAPABILITY_LIST = 257, + ANQP_VENUE_NAME = 258, + ANQP_EMERGENCY_CALL_NUMBER = 259, + ANQP_NETWORK_AUTH_TYPE = 260, + ANQP_ROAMING_CONSORTIUM = 261, + ANQP_IP_ADDR_TYPE_AVAILABILITY = 262, + ANQP_NAI_REALM = 263, + ANQP_3GPP_CELLULAR_NETWORK = 264, + ANQP_AP_GEOSPATIAL_LOCATION = 265, + ANQP_AP_CIVIC_LOCATION = 266, + ANQP_AP_LOCATION_PUBLIC_URI = 267, + ANQP_DOMAIN_NAME = 268, + ANQP_EMERGENCY_ALERT_URI = 269, + ANQP_EMERGENCY_NAI = 271, + ANQP_VENDOR_SPECIFIC = 56797 +}; + +/* NAI Realm list - EAP Method subfield - Authentication Parameter ID */ +enum nai_realm_eap_auth_param { + NAI_REALM_EAP_AUTH_EXPANDED_EAP_METHOD = 1, + NAI_REALM_EAP_AUTH_NON_EAP_INNER_AUTH = 2, + NAI_REALM_EAP_AUTH_INNER_AUTH_EAP_METHOD = 3, + NAI_REALM_EAP_AUTH_EXPANDED_INNER_EAP_METHOD = 4, + NAI_REALM_EAP_AUTH_CRED_TYPE = 5, + NAI_REALM_EAP_AUTH_TUNNELED_CRED_TYPE = 6, + NAI_REALM_EAP_AUTH_VENDOR_SPECIFIC = 221 +}; + +enum nai_realm_eap_auth_inner_non_eap { + NAI_REALM_INNER_NON_EAP_PAP = 1, + NAI_REALM_INNER_NON_EAP_CHAP = 2, + NAI_REALM_INNER_NON_EAP_MSCHAP = 3, + NAI_REALM_INNER_NON_EAP_MSCHAPV2 = 4 +}; + +enum nai_realm_eap_cred_type { + NAI_REALM_CRED_TYPE_SIM = 1, + NAI_REALM_CRED_TYPE_USIM = 2, + NAI_REALM_CRED_TYPE_NFC_SECURE_ELEMENT = 3, + NAI_REALM_CRED_TYPE_HARDWARE_TOKEN = 4, + NAI_REALM_CRED_TYPE_SOFTOKEN = 5, + NAI_REALM_CRED_TYPE_CERTIFICATE = 6, + NAI_REALM_CRED_TYPE_USERNAME_PASSWORD = 7, + NAI_REALM_CRED_TYPE_NONE = 8, + NAI_REALM_CRED_TYPE_ANONYMOUS = 9, + NAI_REALM_CRED_TYPE_VENDOR_SPECIFIC = 10 +}; + +#ifdef _MSC_VER +#pragma pack(push, 1) +#endif /* _MSC_VER */ + +STRUCT_PACKED struct ieee80211_hdr { + le16 frame_control; + le16 duration_id; + u8 addr1[6]; + u8 addr2[6]; + u8 addr3[6]; + le16 seq_ctrl; + /* followed by 'u8 addr4[6];' if ToDS and FromDS is set in data frame + */ +}GCC_PACKED; + +#define IEEE80211_DA_FROMDS addr1 +#define IEEE80211_BSSID_FROMDS addr2 +#define IEEE80211_SA_FROMDS addr3 + +#define IEEE80211_HDRLEN (sizeof(struct ieee80211_hdr)) + +#define IEEE80211_FC(type, stype) host_to_le16((type << 2) | (stype << 4)) + +#define VARIABLE_ARRAY_SPARE 1 + +STRUCT_PACKED struct ieee80211_mgmt { + le16 frame_control; + le16 duration; + u8 da[6]; + u8 sa[6]; + u8 bssid[6]; + le16 seq_ctrl; + + STRUCT_PACKED union { + STRUCT_PACKED struct { + le16 auth_alg; + le16 auth_transaction; + le16 status_code; + /* possibly followed by Challenge text */ + u8 variable[1]; + }GCC_PACKED auth; + + STRUCT_PACKED struct { + le16 reason_code; + u8 variable[1]; + }GCC_PACKED deauth; + + STRUCT_PACKED struct { + le16 capab_info; + le16 listen_interval; + /* followed by SSID and Supported rates */ + u8 variable[1]; + }GCC_PACKED assoc_req; + + STRUCT_PACKED struct { + le16 capab_info; + le16 status_code; + le16 aid; + /* followed by Supported rates */ + u8 variable[1]; + }GCC_PACKED assoc_resp, reassoc_resp; + + STRUCT_PACKED struct { + le16 capab_info; + le16 listen_interval; + u8 current_ap[6]; + /* followed by SSID and Supported rates */ + u8 variable[1]; + }GCC_PACKED reassoc_req; + + STRUCT_PACKED struct { + le16 reason_code; + u8 variable[1]; + }GCC_PACKED disassoc; + + STRUCT_PACKED struct { + u8 timestamp[8]; + le16 beacon_int; + le16 capab_info; + /* followed by some of SSID, Supported rates, + * FH Params, DS Params, CF Params, IBSS Params, TIM */ + u8 variable[1]; + }GCC_PACKED beacon; + + STRUCT_PACKED struct { + /* only variable items: SSID, Supported rates */ + u8 variable[1]; + }GCC_PACKED probe_req; + + STRUCT_PACKED struct { + u8 timestamp[8]; + le16 beacon_int; + le16 capab_info; + /* followed by some of SSID, Supported rates, +. * FH Params, DS Params, CF Params, IBSS Params */ + u8 variable[1]; + }GCC_PACKED probe_resp; + + STRUCT_PACKED struct { + u8 category; + STRUCT_PACKED union { + STRUCT_PACKED struct { + u8 action_code; + u8 dialog_token; + u8 status_code; + u8 variable[1]; + }GCC_PACKED wmm_action; + + STRUCT_PACKED struct{ + u8 action_code; + u8 element_id; + u8 length; + u8 switch_mode; + u8 new_chan; + u8 switch_count; + }GCC_PACKED chan_switch; + + STRUCT_PACKED struct { + u8 action; + u8 sta_addr[ETH_ALEN]; + u8 target_ap_addr[ETH_ALEN]; + u8 variable[1]; + }GCC_PACKED ft_action_req; + + STRUCT_PACKED struct { + u8 action; + u8 sta_addr[ETH_ALEN]; + u8 target_ap_addr[ETH_ALEN]; + le16 status_code; + u8 variable[1]; + }GCC_PACKED ft_action_resp; + + STRUCT_PACKED struct { + u8 action; + u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN]; + }GCC_PACKED sa_query_req; + + STRUCT_PACKED struct { + u8 action; /* */ + u8 trans_id[WLAN_SA_QUERY_TR_ID_LEN]; + }GCC_PACKED sa_query_resp; + + STRUCT_PACKED struct { + u8 action; + u8 dialogtoken; + u8 variable[1]; + }GCC_PACKED wnm_sleep_req; + + STRUCT_PACKED struct { + u8 action; + u8 dialogtoken; + le16 keydata_len; + u8 variable[1]; + }GCC_PACKED wnm_sleep_resp; + + STRUCT_PACKED struct { + u8 action; + u8 variable[1]; + }GCC_PACKED public_action; + + STRUCT_PACKED struct { + u8 action; /* 9 */ + u8 oui[3]; + /* Vendor-specific content */ + u8 variable[1]; + }GCC_PACKED vs_public_action; + + STRUCT_PACKED struct { + u8 action; /* 7 */ + u8 dialog_token; + u8 req_mode; + le16 disassoc_timer; + u8 validity_interval; + /* BSS Termination Duration (optional), + * Session Information URL (optional), + * BSS Transition Candidate List + * Entries */ + u8 variable[1]; + }GCC_PACKED bss_tm_req; + + STRUCT_PACKED struct { + u8 action; /* 8 */ + u8 dialog_token; + u8 status_code; + u8 bss_termination_delay; + /* Target BSSID (optional), + * BSS Transition Candidate List + * Entries (optional) */ + u8 variable[1]; + }GCC_PACKED bss_tm_resp; + + STRUCT_PACKED struct { + u8 action; /* 6 */ + u8 dialog_token; + u8 query_reason; + /* BSS Transition Candidate List + * Entries (optional) */ + u8 variable[1]; + }GCC_PACKED bss_tm_query; + + STRUCT_PACKED struct { + u8 action; /* 15 */ + u8 variable[1]; + }GCC_PACKED slf_prot_action; + + STRUCT_PACKED struct { + u8 action; + u8 variable[1]; + }GCC_PACKED fst_action; + }GCC_PACKED u; + + }GCC_PACKED action; + }GCC_PACKED u; +}GCC_PACKED; + + +/* Rx MCS bitmask is in the first 77 bits of supported_mcs_set */ +#define IEEE80211_HT_MCS_MASK_LEN 10 + +/* HT Capabilities element */ +STRUCT_PACKED struct ieee80211_ht_capabilities { + le16 ht_capabilities_info; + u8 a_mpdu_params; /* Maximum A-MPDU Length Exponent B0..B1 + * Minimum MPDU Start Spacing B2..B4 + * Reserved B5..B7 */ + u8 supported_mcs_set[16]; + le16 ht_extended_capabilities; + le32 tx_bf_capability_info; + u8 asel_capabilities; +}GCC_PACKED; + + +/* HT Operation element */ +STRUCT_PACKED struct ieee80211_ht_operation { + u8 primary_chan; + /* Five octets of HT Operation Information */ + u8 ht_param; /* B0..B7 */ + le16 operation_mode; /* B8..B23 */ + le16 param; /* B24..B39 */ + u8 basic_mcs_set[16]; +}GCC_PACKED; + + +STRUCT_PACKED struct ieee80211_obss_scan_parameters { + le16 scan_passive_dwell; + le16 scan_active_dwell; + le16 width_trigger_scan_interval; + le16 scan_passive_total_per_channel; + le16 scan_active_total_per_channel; + le16 channel_transition_delay_factor; + le16 scan_activity_threshold; +}GCC_PACKED; + + +STRUCT_PACKED struct ieee80211_vht_capabilities { + le32 vht_capabilities_info; + STRUCT_PACKED struct { + le16 rx_map; + le16 rx_highest; + le16 tx_map; + le16 tx_highest; + }GCC_PACKED vht_supported_mcs_set; +}GCC_PACKED; + +STRUCT_PACKED struct ieee80211_vht_operation { + u8 vht_op_info_chwidth; + u8 vht_op_info_chan_center_freq_seg0_idx; + u8 vht_op_info_chan_center_freq_seg1_idx; + le16 vht_basic_mcs_set; +}GCC_PACKED; + +STRUCT_PACKED struct ieee80211_ampe_ie { + u8 selected_pairwise_suite[4]; + u8 local_nonce[32]; + u8 peer_nonce[32]; + u8 mgtk[16]; + u8 key_rsc[8]; + u8 key_expiration[4]; +}GCC_PACKED; + +#ifdef _MSC_VER +#pragma pack(pop) +#endif /* _MSC_VER */ + +#define ERP_INFO_NON_ERP_PRESENT BIT(0) +#define ERP_INFO_USE_PROTECTION BIT(1) +#define ERP_INFO_BARKER_PREAMBLE_MODE BIT(2) + +#define OVERLAPPING_BSS_TRANS_DELAY_FACTOR 5 + +/* HT Capabilities Info field within HT Capabilities element */ +#define HT_CAP_INFO_LDPC_CODING_CAP ((u16) BIT(0)) +#define HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET ((u16) BIT(1)) +#define HT_CAP_INFO_SMPS_MASK ((u16) (BIT(2) | BIT(3))) +#define HT_CAP_INFO_SMPS_STATIC ((u16) 0) +#define HT_CAP_INFO_SMPS_DYNAMIC ((u16) BIT(2)) +#define HT_CAP_INFO_SMPS_DISABLED ((u16) (BIT(2) | BIT(3))) +#define HT_CAP_INFO_GREEN_FIELD ((u16) BIT(4)) +#define HT_CAP_INFO_SHORT_GI20MHZ ((u16) BIT(5)) +#define HT_CAP_INFO_SHORT_GI40MHZ ((u16) BIT(6)) +#define HT_CAP_INFO_TX_STBC ((u16) BIT(7)) +#define HT_CAP_INFO_RX_STBC_MASK ((u16) (BIT(8) | BIT(9))) +#define HT_CAP_INFO_RX_STBC_1 ((u16) BIT(8)) +#define HT_CAP_INFO_RX_STBC_12 ((u16) BIT(9)) +#define HT_CAP_INFO_RX_STBC_123 ((u16) (BIT(8) | BIT(9))) +#define HT_CAP_INFO_DELAYED_BA ((u16) BIT(10)) +#define HT_CAP_INFO_MAX_AMSDU_SIZE ((u16) BIT(11)) +#define HT_CAP_INFO_DSSS_CCK40MHZ ((u16) BIT(12)) +/* B13 - Reserved (was PSMP support during P802.11n development) */ +#define HT_CAP_INFO_40MHZ_INTOLERANT ((u16) BIT(14)) +#define HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT ((u16) BIT(15)) + +/* HT Extended Capabilities field within HT Capabilities element */ +#define EXT_HT_CAP_INFO_PCO ((u16) BIT(0)) +#define EXT_HT_CAP_INFO_PCO_TRANS_TIME_MASK ((u16) (BIT(1) | BIT(2))) +#define EXT_HT_CAP_INFO_TRANS_TIME_OFFSET 1 +/* B3..B7 - Reserved */ +#define EXT_HT_CAP_INFO_MCS_FEEDBACK_MASK ((u16) (BIT(8) | BIT(9))) +#define EXT_HT_CAP_INFO_MCS_FEEDBACK_OFFSET 8 +#define EXT_HT_CAP_INFO_HTC_SUPPORT ((u16) BIT(10)) +#define EXT_HT_CAP_INFO_RD_RESPONDER ((u16) BIT(11)) +/* B12..B15 - Reserved */ + +/* Transmit Beanforming Capabilities within HT Capabilities element */ +#define TX_BF_CAP_IMPLICIT_TXBF_RX_CAP ((u32) BIT(0)) +#define TX_BF_CAP_RX_STAGGERED_SOUNDING_CAP ((u32) BIT(1)) +#define TX_BF_CAP_TX_STAGGERED_SOUNDING_CAP ((u32) BIT(2)) +#define TX_BF_CAP_RX_NDP_CAP ((u32) BIT(3)) +#define TX_BF_CAP_TX_NDP_CAP ((u32) BIT(4)) +#define TX_BF_CAP_IMPLICIT_TX_BF_CAP ((u32) BIT(5)) +#define TX_BF_CAP_CALIBRATION_MASK ((u32) (BIT(6) | BIT(7)) +#define TX_BF_CAP_CALIB_OFFSET 6 +#define TX_BF_CAP_EXPLICIT_CSI_TXBF_CAP ((u32) BIT(8)) +#define TX_BF_CAP_EXPLICIT_NONCOMPR_STEERING_CAP ((u32) BIT(9)) +#define TX_BF_CAP_EXPLICIT_COMPR_STEERING_CAP ((u32) BIT(10)) +#define TX_BF_CAP_EXPLICIT_TX_BF_CSI_FEEDBACK_MASK ((u32) (BIT(10) | BIT(11))) +#define TX_BF_CAP_EXPLICIT_BF_CSI_FEEDBACK_OFFSET 11 +#define TX_BF_CAP_EXPLICIT_UNCOMPR_STEERING_MATRIX_FEEDBACK_OFFSET 13 +#define TX_BF_CAP_EXPLICIT_COMPRESSED_STEERING_MATRIX_FEEDBACK_OFFSET 15 +#define TX_BF_CAP_MINIMAL_GROUPING_OFFSET 17 +#define TX_BF_CAP_CSI_NUM_BEAMFORMER_ANT_OFFSET 19 +#define TX_BF_CAP_UNCOMPRESSED_STEERING_MATRIX_BEAMFORMER_ANT_OFFSET 21 +#define TX_BF_CAP_COMPRESSED_STEERING_MATRIX_BEAMFORMER_ANT_OFFSET 23 +#define TX_BF_CAP_SCI_MAX_OF_ROWS_BEANFORMER_SUPPORTED_OFFSET 25 +#define TX_BF_CAP_CHANNEL_ESTIMATION_CAP_MASK ((u32) (BIT(27) | BIT(28))) +#define TX_BF_CAP_CHANNEL_ESTIMATION_CAP_OFFSET 27 +/* B29..B31 - Reserved */ + +/* ASEL Capability field within HT Capabilities element */ +#define ASEL_CAP_ASEL_CAPABLE ((u8) BIT(0)) +#define ASEL_CAP_EXPLICIT_CSI_FEEDBACK_BASED_TX_AS_CAP ((u8) BIT(1)) +#define ASEL_CAP_ANT_INDICES_FEEDBACK_BASED_TX_AS_CAP ((u8) BIT(2)) +#define ASEL_CAP_EXPLICIT_CSI_FEEDBACK_CAP ((u8) BIT(3)) +#define ASEL_CAP_ANT_INDICES_FEEDBACK_CAP ((u8) BIT(4)) +#define ASEL_CAP_RX_AS_CAP ((u8) BIT(5)) +#define ASEL_CAP_TX_SOUNDING_PPDUS_CAP ((u8) BIT(6)) +/* B7 - Reserved */ + +/* First octet of HT Operation Information within HT Operation element */ +#define HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK ((u8) BIT(0) | BIT(1)) +#define HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE ((u8) BIT(0)) +#define HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW ((u8) BIT(0) | BIT(1)) +#define HT_INFO_HT_PARAM_STA_CHNL_WIDTH ((u8) BIT(2)) +#define HT_INFO_HT_PARAM_RIFS_MODE ((u8) BIT(3)) +/* B4..B7 - Reserved */ + +/* HT Protection (B8..B9 of HT Operation Information) */ +#define HT_PROT_NO_PROTECTION 0 +#define HT_PROT_NONMEMBER_PROTECTION 1 +#define HT_PROT_20MHZ_PROTECTION 2 +#define HT_PROT_NON_HT_MIXED 3 +/* Bits within ieee80211_ht_operation::operation_mode (BIT(0) maps to B8 in + * HT Operation Information) */ +#define HT_OPER_OP_MODE_HT_PROT_MASK ((u16) (BIT(0) | BIT(1))) /* B8..B9 */ +#define HT_OPER_OP_MODE_NON_GF_HT_STAS_PRESENT ((u16) BIT(2)) /* B10 */ +/* BIT(3), i.e., B11 in HT Operation Information field - Reserved */ +#define HT_OPER_OP_MODE_OBSS_NON_HT_STAS_PRESENT ((u16) BIT(4)) /* B12 */ +/* BIT(5)..BIT(15), i.e., B13..B23 - Reserved */ + +/* Last two octets of HT Operation Information (BIT(0) = B24) */ +/* B24..B29 - Reserved */ +#define HT_OPER_PARAM_DUAL_BEACON ((u16) BIT(6)) +#define HT_OPER_PARAM_DUAL_CTS_PROTECTION ((u16) BIT(7)) +#define HT_OPER_PARAM_STBC_BEACON ((u16) BIT(8)) +#define HT_OPER_PARAM_LSIG_TXOP_PROT_FULL_SUPP ((u16) BIT(9)) +#define HT_OPER_PARAM_PCO_ACTIVE ((u16) BIT(10)) +#define HT_OPER_PARAM_PCO_PHASE ((u16) BIT(11)) +/* B36..B39 - Reserved */ + +#define BSS_MEMBERSHIP_SELECTOR_VHT_PHY 126 +#define BSS_MEMBERSHIP_SELECTOR_HT_PHY 127 + +/* VHT Defines */ +#define VHT_CAP_MAX_MPDU_LENGTH_7991 ((u32) BIT(0)) +#define VHT_CAP_MAX_MPDU_LENGTH_11454 ((u32) BIT(1)) +#define VHT_CAP_MAX_MPDU_LENGTH_MASK ((u32) BIT(0) | BIT(1)) +#define VHT_CAP_MAX_MPDU_LENGTH_MASK_SHIFT 0 +#define VHT_CAP_SUPP_CHAN_WIDTH_160MHZ ((u32) BIT(2)) +#define VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ ((u32) BIT(3)) +#define VHT_CAP_SUPP_CHAN_WIDTH_MASK ((u32) BIT(2) | BIT(3)) +#define VHT_CAP_RXLDPC ((u32) BIT(4)) +#define VHT_CAP_SHORT_GI_80 ((u32) BIT(5)) +#define VHT_CAP_SHORT_GI_160 ((u32) BIT(6)) +#define VHT_CAP_TXSTBC ((u32) BIT(7)) +#define VHT_CAP_RXSTBC_1 ((u32) BIT(8)) +#define VHT_CAP_RXSTBC_2 ((u32) BIT(9)) +#define VHT_CAP_RXSTBC_3 ((u32) BIT(8) | BIT(9)) +#define VHT_CAP_RXSTBC_4 ((u32) BIT(10)) +#define VHT_CAP_RXSTBC_MASK ((u32) BIT(8) | BIT(9) | \ + BIT(10)) +#define VHT_CAP_RXSTBC_MASK_SHIFT 8 +#define VHT_CAP_SU_BEAMFORMER_CAPABLE ((u32) BIT(11)) +#define VHT_CAP_SU_BEAMFORMEE_CAPABLE ((u32) BIT(12)) +#define VHT_CAP_BEAMFORMEE_STS_MAX ((u32) BIT(13) | \ + BIT(14) | BIT(15)) +#define VHT_CAP_BEAMFORMEE_STS_MAX_SHIFT 13 +#define VHT_CAP_BEAMFORMEE_STS_OFFSET 13 +#define VHT_CAP_SOUNDING_DIMENSION_MAX ((u32) BIT(16) | \ + BIT(17) | BIT(18)) +#define VHT_CAP_SOUNDING_DIMENSION_MAX_SHIFT 16 +#define VHT_CAP_SOUNDING_DIMENSION_OFFSET 16 +#define VHT_CAP_MU_BEAMFORMER_CAPABLE ((u32) BIT(19)) +#define VHT_CAP_MU_BEAMFORMEE_CAPABLE ((u32) BIT(20)) +#define VHT_CAP_VHT_TXOP_PS ((u32) BIT(21)) +#define VHT_CAP_HTC_VHT ((u32) BIT(22)) + +#define VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_1 ((u32) BIT(23)) +#define VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_2 ((u32) BIT(24)) +#define VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_3 ((u32) BIT(23) | BIT(24)) +#define VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_4 ((u32) BIT(25)) +#define VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_5 ((u32) BIT(23) | BIT(25)) +#define VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_6 ((u32) BIT(24) | BIT(25)) +#define VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX ((u32) BIT(23) | \ + BIT(24) | BIT(25)) +#define VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT 23 +#define VHT_CAP_VHT_LINK_ADAPTATION_VHT_UNSOL_MFB ((u32) BIT(27)) +#define VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB ((u32) BIT(26) | BIT(27)) +#define VHT_CAP_RX_ANTENNA_PATTERN ((u32) BIT(28)) +#define VHT_CAP_TX_ANTENNA_PATTERN ((u32) BIT(29)) + +#define VHT_OPMODE_CHANNEL_WIDTH_MASK ((u8) BIT(0) | BIT(1)) +#define VHT_OPMODE_CHANNEL_RxNSS_MASK ((u8) BIT(4) | BIT(5) | \ + BIT(6)) +#define VHT_OPMODE_NOTIF_RX_NSS_SHIFT 4 + +#define VHT_RX_NSS_MAX_STREAMS 8 + +/* VHT channel widths */ +#define VHT_CHANWIDTH_USE_HT 0 +#define VHT_CHANWIDTH_80MHZ 1 +#define VHT_CHANWIDTH_160MHZ 2 +#define VHT_CHANWIDTH_80P80MHZ 3 + +#define OUI_BEKEN 0x00001018 + +#define OUI_MICROSOFT 0x0050f2 /* Microsoft (also used in Wi-Fi specs) + * 00:50:F2 */ +#define OUI_TYPE_MICROSOFT_WPA 1 +#define WPA_IE_VENDOR_TYPE 0x0050f201 +#define WMM_IE_VENDOR_TYPE 0x0050f202 +#define WPS_IE_VENDOR_TYPE 0x0050f204 +#define OUI_WFA 0x506f9a +#define P2P_IE_VENDOR_TYPE 0x506f9a09 +#define WFD_IE_VENDOR_TYPE 0x506f9a0a +#define WFD_OUI_TYPE 10 +#define HS20_IE_VENDOR_TYPE 0x506f9a10 +#define OSEN_IE_VENDOR_TYPE 0x506f9a12 + +#define WMM_OUI_TYPE 2 +#define WMM_OUI_SUBTYPE_INFORMATION_ELEMENT 0 +#define WMM_OUI_SUBTYPE_PARAMETER_ELEMENT 1 +#define WMM_OUI_SUBTYPE_TSPEC_ELEMENT 2 +#define WMM_VERSION 1 + +#define WMM_ACTION_CODE_ADDTS_REQ 0 +#define WMM_ACTION_CODE_ADDTS_RESP 1 +#define WMM_ACTION_CODE_DELTS 2 + +#define WMM_ADDTS_STATUS_ADMISSION_ACCEPTED 0 +#define WMM_ADDTS_STATUS_INVALID_PARAMETERS 1 +/* 2 - Reserved */ +#define WMM_ADDTS_STATUS_REFUSED 3 +/* 4-255 - Reserved */ + +/* WMM TSPEC Direction Field Values */ +#define WMM_TSPEC_DIRECTION_UPLINK 0 +#define WMM_TSPEC_DIRECTION_DOWNLINK 1 +/* 2 - Reserved */ +#define WMM_TSPEC_DIRECTION_BI_DIRECTIONAL 3 + +/* + * WMM Information Element (used in (Re)Association Request frames; may also be + * used in Beacon frames) + */ +STRUCT_PACKED struct wmm_information_element { + /* Element ID: 221 (0xdd); Length: 7 */ + /* required fields for WMM version 1 */ + u8 oui[3]; /* 00:50:f2 */ + u8 oui_type; /* 2 */ + u8 oui_subtype; /* 0 */ + u8 version; /* 1 for WMM version 1.0 */ + u8 qos_info; /* AP/STA specific QoS info */ +}GCC_PACKED; + +#define WMM_QOSINFO_AP_UAPSD 0x80 + +#define WMM_QOSINFO_STA_AC_MASK 0x0f +#define WMM_QOSINFO_STA_SP_MASK 0x03 +#define WMM_QOSINFO_STA_SP_SHIFT 5 + +#define WMM_AC_AIFSN_MASK 0x0f +#define WMM_AC_AIFNS_SHIFT 0 +#define WMM_AC_ACM 0x10 +#define WMM_AC_ACI_MASK 0x60 +#define WMM_AC_ACI_SHIFT 5 + +#define WMM_AC_ECWMIN_MASK 0x0f +#define WMM_AC_ECWMIN_SHIFT 0 +#define WMM_AC_ECWMAX_MASK 0xf0 +#define WMM_AC_ECWMAX_SHIFT 4 + +STRUCT_PACKED struct wmm_ac_parameter { + u8 aci_aifsn; /* AIFSN, ACM, ACI */ + u8 cw; /* ECWmin, ECWmax (CW = 2^ECW - 1) */ + le16 txop_limit; +}GCC_PACKED; + +/* + * WMM Parameter Element (used in Beacon, Probe Response, and (Re)Association + * Response frmaes) + */ +STRUCT_PACKED struct wmm_parameter_element { + /* Element ID: 221 (0xdd); Length: 24 */ + /* required fields for WMM version 1 */ + u8 oui[3]; /* 00:50:f2 */ + u8 oui_type; /* 2 */ + u8 oui_subtype; /* 1 */ + u8 version; /* 1 for WMM version 1.0 */ + u8 qos_info; /* AP/STA specific QoS info */ + u8 reserved; /* 0 */ + struct wmm_ac_parameter ac[4]; /* AC_BE, AC_BK, AC_VI, AC_VO */ + +}GCC_PACKED; + +/* WMM TSPEC Element */ +STRUCT_PACKED struct wmm_tspec_element { + u8 eid; /* 221 = 0xdd */ + u8 length; /* 6 + 55 = 61 */ + u8 oui[3]; /* 00:50:f2 */ + u8 oui_type; /* 2 */ + u8 oui_subtype; /* 2 */ + u8 version; /* 1 */ + /* WMM TSPEC body (55 octets): */ + u8 ts_info[3]; + le16 nominal_msdu_size; + le16 maximum_msdu_size; + le32 minimum_service_interval; + le32 maximum_service_interval; + le32 inactivity_interval; + le32 suspension_interval; + le32 service_start_time; + le32 minimum_data_rate; + le32 mean_data_rate; + le32 peak_data_rate; + le32 maximum_burst_size; + le32 delay_bound; + le32 minimum_phy_rate; + le16 surplus_bandwidth_allowance; + le16 medium_time; +}GCC_PACKED; + + +/* Access Categories / ACI to AC coding */ +enum wmm_ac { + WMM_AC_BE = 0 /* Best Effort */, + WMM_AC_BK = 1 /* Background */, + WMM_AC_VI = 2 /* Video */, + WMM_AC_VO = 3 /* Voice */, + WMM_AC_NUM = 4 +}; + + +#define HS20_INDICATION_OUI_TYPE 16 +#define HS20_ANQP_OUI_TYPE 17 +#define HS20_OSEN_OUI_TYPE 18 +#define HS20_STYPE_QUERY_LIST 1 +#define HS20_STYPE_CAPABILITY_LIST 2 +#define HS20_STYPE_OPERATOR_FRIENDLY_NAME 3 +#define HS20_STYPE_WAN_METRICS 4 +#define HS20_STYPE_CONNECTION_CAPABILITY 5 +#define HS20_STYPE_NAI_HOME_REALM_QUERY 6 +#define HS20_STYPE_OPERATING_CLASS 7 +#define HS20_STYPE_OSU_PROVIDERS_LIST 8 +#define HS20_STYPE_ICON_REQUEST 10 +#define HS20_STYPE_ICON_BINARY_FILE 11 + +#define HS20_DGAF_DISABLED 0x01 +#define HS20_PPS_MO_ID_PRESENT 0x02 +#define HS20_ANQP_DOMAIN_ID_PRESENT 0x04 +#define HS20_VERSION 0x10 /* Release 2 */ + +/* WNM-Notification WFA vendors specific subtypes */ +#define HS20_WNM_SUB_REM_NEEDED 0 +#define HS20_WNM_DEAUTH_IMMINENT_NOTICE 1 + +#define HS20_DEAUTH_REASON_CODE_BSS 0 +#define HS20_DEAUTH_REASON_CODE_ESS 1 + +/* Wi-Fi Direct (P2P) */ + +#define P2P_OUI_TYPE 9 + +enum p2p_attr_id { + P2P_ATTR_STATUS = 0, + P2P_ATTR_MINOR_REASON_CODE = 1, + P2P_ATTR_CAPABILITY = 2, + P2P_ATTR_DEVICE_ID = 3, + P2P_ATTR_GROUP_OWNER_INTENT = 4, + P2P_ATTR_CONFIGURATION_TIMEOUT = 5, + P2P_ATTR_LISTEN_CHANNEL = 6, + P2P_ATTR_GROUP_BSSID = 7, + P2P_ATTR_EXT_LISTEN_TIMING = 8, + P2P_ATTR_INTENDED_INTERFACE_ADDR = 9, + P2P_ATTR_MANAGEABILITY = 10, + P2P_ATTR_CHANNEL_LIST = 11, + P2P_ATTR_NOTICE_OF_ABSENCE = 12, + P2P_ATTR_DEVICE_INFO = 13, + P2P_ATTR_GROUP_INFO = 14, + P2P_ATTR_GROUP_ID = 15, + P2P_ATTR_INTERFACE = 16, + P2P_ATTR_OPERATING_CHANNEL = 17, + P2P_ATTR_INVITATION_FLAGS = 18, + P2P_ATTR_OOB_GO_NEG_CHANNEL = 19, + P2P_ATTR_SERVICE_HASH = 21, + P2P_ATTR_SESSION_INFORMATION_DATA = 22, + P2P_ATTR_CONNECTION_CAPABILITY = 23, + P2P_ATTR_ADVERTISEMENT_ID = 24, + P2P_ATTR_ADVERTISED_SERVICE = 25, + P2P_ATTR_SESSION_ID = 26, + P2P_ATTR_FEATURE_CAPABILITY = 27, + P2P_ATTR_PERSISTENT_GROUP = 28, + P2P_ATTR_VENDOR_SPECIFIC = 221 +}; + +#define P2P_MAX_GO_INTENT 15 + +/* P2P Capability - Device Capability bitmap */ +#define P2P_DEV_CAPAB_SERVICE_DISCOVERY BIT(0) +#define P2P_DEV_CAPAB_CLIENT_DISCOVERABILITY BIT(1) +#define P2P_DEV_CAPAB_CONCURRENT_OPER BIT(2) +#define P2P_DEV_CAPAB_INFRA_MANAGED BIT(3) +#define P2P_DEV_CAPAB_DEVICE_LIMIT BIT(4) +#define P2P_DEV_CAPAB_INVITATION_PROCEDURE BIT(5) + +/* P2P Capability - Group Capability bitmap */ +#define P2P_GROUP_CAPAB_GROUP_OWNER BIT(0) +#define P2P_GROUP_CAPAB_PERSISTENT_GROUP BIT(1) +#define P2P_GROUP_CAPAB_GROUP_LIMIT BIT(2) +#define P2P_GROUP_CAPAB_INTRA_BSS_DIST BIT(3) +#define P2P_GROUP_CAPAB_CROSS_CONN BIT(4) +#define P2P_GROUP_CAPAB_PERSISTENT_RECONN BIT(5) +#define P2P_GROUP_CAPAB_GROUP_FORMATION BIT(6) +#define P2P_GROUP_CAPAB_IP_ADDR_ALLOCATION BIT(7) + +/* P2PS Coordination Protocol Transport Bitmap */ +#define P2PS_FEATURE_CAPAB_UDP_TRANSPORT BIT(0) +#define P2PS_FEATURE_CAPAB_MAC_TRANSPORT BIT(1) + +STRUCT_PACKED struct p2ps_feature_capab { + u8 cpt; + u8 reserved; +}GCC_PACKED; + +/* Invitation Flags */ +#define P2P_INVITATION_FLAGS_TYPE BIT(0) + +/* P2P Manageability */ +#define P2P_MAN_DEVICE_MANAGEMENT BIT(0) +#define P2P_MAN_CROSS_CONNECTION_PERMITTED BIT(1) +#define P2P_MAN_COEXISTENCE_OPTIONAL BIT(2) + +enum p2p_status_code { + P2P_SC_SUCCESS = 0, + P2P_SC_FAIL_INFO_CURRENTLY_UNAVAILABLE = 1, + P2P_SC_FAIL_INCOMPATIBLE_PARAMS = 2, + P2P_SC_FAIL_LIMIT_REACHED = 3, + P2P_SC_FAIL_INVALID_PARAMS = 4, + P2P_SC_FAIL_UNABLE_TO_ACCOMMODATE = 5, + P2P_SC_FAIL_PREV_PROTOCOL_ERROR = 6, + P2P_SC_FAIL_NO_COMMON_CHANNELS = 7, + P2P_SC_FAIL_UNKNOWN_GROUP = 8, + P2P_SC_FAIL_BOTH_GO_INTENT_15 = 9, + P2P_SC_FAIL_INCOMPATIBLE_PROV_METHOD = 10, + P2P_SC_FAIL_REJECTED_BY_USER = 11, + P2P_SC_SUCCESS_DEFERRED = 12, +}; + +enum p2p_role_indication { + P2P_DEVICE_NOT_IN_GROUP = 0x00, + P2P_CLIENT_IN_A_GROUP = 0x01, + P2P_GO_IN_A_GROUP = 0x02, +}; + +#define P2P_WILDCARD_SSID "DIRECT-" +#define P2P_WILDCARD_SSID_LEN 7 + +/* P2P action frames */ +enum p2p_act_frame_type { + P2P_NOA = 0, + P2P_PRESENCE_REQ = 1, + P2P_PRESENCE_RESP = 2, + P2P_GO_DISC_REQ = 3 +}; + +/* P2P public action frames */ +enum p2p_action_frame_type { + P2P_GO_NEG_REQ = 0, + P2P_GO_NEG_RESP = 1, + P2P_GO_NEG_CONF = 2, + P2P_INVITATION_REQ = 3, + P2P_INVITATION_RESP = 4, + P2P_DEV_DISC_REQ = 5, + P2P_DEV_DISC_RESP = 6, + P2P_PROV_DISC_REQ = 7, + P2P_PROV_DISC_RESP = 8 +}; + +enum p2p_service_protocol_type { + P2P_SERV_ALL_SERVICES = 0, + P2P_SERV_BONJOUR = 1, + P2P_SERV_UPNP = 2, + P2P_SERV_WS_DISCOVERY = 3, + P2P_SERV_WIFI_DISPLAY = 4, + P2P_SERV_P2PS = 11, + P2P_SERV_VENDOR_SPECIFIC = 255 +}; + +enum p2p_sd_status { + P2P_SD_SUCCESS = 0, + P2P_SD_PROTO_NOT_AVAILABLE = 1, + P2P_SD_REQUESTED_INFO_NOT_AVAILABLE = 2, + P2P_SD_BAD_REQUEST = 3 +}; + + +enum wifi_display_subelem { + WFD_SUBELEM_DEVICE_INFO = 0, + WFD_SUBELEM_ASSOCIATED_BSSID = 1, + WFD_SUBELEM_AUDIO_FORMATS = 2, + WFD_SUBELEM_VIDEO_FORMATS = 3, + WFD_SUBELEM_3D_VIDEO_FORMATS = 4, + WFD_SUBELEM_CONTENT_PROTECTION = 5, + WFD_SUBELEM_COUPLED_SINK = 6, + WFD_SUBELEM_EXT_CAPAB = 7, + WFD_SUBELEM_LOCAL_IP_ADDRESS = 8, + WFD_SUBELEM_SESSION_INFO = 9 +}; + +/* 802.11s */ +#define MESH_SYNC_METHOD_NEIGHBOR_OFFSET 1 +#define MESH_SYNC_METHOD_VENDOR 255 +#define MESH_PATH_PROTOCOL_HWMP 1 +#define MESH_PATH_PROTOCOL_VENDOR 255 +#define MESH_PATH_METRIC_AIRTIME 1 +#define MESH_PATH_METRIC_VENDOR 255 + +enum plink_action_field { + PLINK_OPEN = 1, + PLINK_CONFIRM, + PLINK_CLOSE +}; + +#define OUI_BROADCOM 0x00904c /* Broadcom (Epigram) */ +#define VENDOR_VHT_TYPE 0x04 +#define VENDOR_VHT_SUBTYPE 0x08 +#define VENDOR_VHT_SUBTYPE2 0x00 + +#define VENDOR_HT_CAPAB_OUI_TYPE 0x33 /* 00-90-4c:0x33 */ + +/* cipher suite selectors */ +#define WLAN_CIPHER_SUITE_USE_GROUP 0x000FAC00 +#define WLAN_CIPHER_SUITE_WEP40 0x000FAC01 +#define WLAN_CIPHER_SUITE_TKIP 0x000FAC02 +/* reserved: 0x000FAC03 */ +#define WLAN_CIPHER_SUITE_CCMP 0x000FAC04 +#define WLAN_CIPHER_SUITE_WEP104 0x000FAC05 +#define WLAN_CIPHER_SUITE_AES_CMAC 0x000FAC06 +#define WLAN_CIPHER_SUITE_NO_GROUP_ADDR 0x000FAC07 +#define WLAN_CIPHER_SUITE_GCMP 0x000FAC08 +#define WLAN_CIPHER_SUITE_GCMP_256 0x000FAC09 +#define WLAN_CIPHER_SUITE_CCMP_256 0x000FAC0A +#define WLAN_CIPHER_SUITE_BIP_GMAC_128 0x000FAC0B +#define WLAN_CIPHER_SUITE_BIP_GMAC_256 0x000FAC0C +#define WLAN_CIPHER_SUITE_BIP_CMAC_256 0x000FAC0D + +#define WLAN_CIPHER_SUITE_SMS4 0x00147201 + +#define WLAN_CIPHER_SUITE_CKIP 0x00409600 +#define WLAN_CIPHER_SUITE_CKIP_CMIC 0x00409601 +#define WLAN_CIPHER_SUITE_CMIC 0x00409602 +#define WLAN_CIPHER_SUITE_KRK 0x004096FF /* for nl80211 use only */ + +/* AKM suite selectors */ +#define WLAN_AKM_SUITE_8021X 0x000FAC01 +#define WLAN_AKM_SUITE_PSK 0x000FAC02 +#define WLAN_AKM_SUITE_FT_8021X 0x000FAC03 +#define WLAN_AKM_SUITE_FT_PSK 0x000FAC04 +#define WLAN_AKM_SUITE_8021X_SHA256 0x000FAC05 +#define WLAN_AKM_SUITE_PSK_SHA256 0x000FAC06 +#define WLAN_AKM_SUITE_8021X_SUITE_B 0x000FAC11 +#define WLAN_AKM_SUITE_8021X_SUITE_B_192 0x000FAC12 +#define WLAN_AKM_SUITE_CCKM 0x00409600 +#define WLAN_AKM_SUITE_OSEN 0x506f9a01 + + +/* IEEE 802.11v - WNM Action field values */ +enum wnm_action { + WNM_EVENT_REQ = 0, + WNM_EVENT_REPORT = 1, + WNM_DIAGNOSTIC_REQ = 2, + WNM_DIAGNOSTIC_REPORT = 3, + WNM_LOCATION_CFG_REQ = 4, + WNM_LOCATION_CFG_RESP = 5, + WNM_BSS_TRANS_MGMT_QUERY = 6, + WNM_BSS_TRANS_MGMT_REQ = 7, + WNM_BSS_TRANS_MGMT_RESP = 8, + WNM_FMS_REQ = 9, + WNM_FMS_RESP = 10, + WNM_COLLOCATED_INTERFERENCE_REQ = 11, + WNM_COLLOCATED_INTERFERENCE_REPORT = 12, + WNM_TFS_REQ = 13, + WNM_TFS_RESP = 14, + WNM_TFS_NOTIFY = 15, + WNM_SLEEP_MODE_REQ = 16, + WNM_SLEEP_MODE_RESP = 17, + WNM_TIM_BROADCAST_REQ = 18, + WNM_TIM_BROADCAST_RESP = 19, + WNM_QOS_TRAFFIC_CAPAB_UPDATE = 20, + WNM_CHANNEL_USAGE_REQ = 21, + WNM_CHANNEL_USAGE_RESP = 22, + WNM_DMS_REQ = 23, + WNM_DMS_RESP = 24, + WNM_TIMING_MEASUREMENT_REQ = 25, + WNM_NOTIFICATION_REQ = 26, + WNM_NOTIFICATION_RESP = 27 +}; + +/* IEEE 802.11v - BSS Transition Management Request - Request Mode */ +#define WNM_BSS_TM_REQ_PREF_CAND_LIST_INCLUDED BIT(0) +#define WNM_BSS_TM_REQ_ABRIDGED BIT(1) +#define WNM_BSS_TM_REQ_DISASSOC_IMMINENT BIT(2) +#define WNM_BSS_TM_REQ_BSS_TERMINATION_INCLUDED BIT(3) +#define WNM_BSS_TM_REQ_ESS_DISASSOC_IMMINENT BIT(4) + +/* IEEE Std 802.11-2012 - Table 8-253 */ +enum bss_trans_mgmt_status_code { + WNM_BSS_TM_ACCEPT = 0, + WNM_BSS_TM_REJECT_UNSPECIFIED = 1, + WNM_BSS_TM_REJECT_INSUFFICIENT_BEACON = 2, + WNM_BSS_TM_REJECT_INSUFFICIENT_CAPABITY = 3, + WNM_BSS_TM_REJECT_UNDESIRED = 4, + WNM_BSS_TM_REJECT_DELAY_REQUEST = 5, + WNM_BSS_TM_REJECT_STA_CANDIDATE_LIST_PROVIDED = 6, + WNM_BSS_TM_REJECT_NO_SUITABLE_CANDIDATES = 7, + WNM_BSS_TM_REJECT_LEAVING_ESS = 8 +}; + +#define WNM_NEIGHBOR_TSF 1 +#define WNM_NEIGHBOR_CONDENSED_COUNTRY_STRING 2 +#define WNM_NEIGHBOR_BSS_TRANSITION_CANDIDATE 3 +#define WNM_NEIGHBOR_BSS_TERMINATION_DURATION 4 +#define WNM_NEIGHBOR_BEARING 5 +#define WNM_NEIGHBOR_MEASUREMENT_PILOT 66 +#define WNM_NEIGHBOR_RRM_ENABLED_CAPABILITIES 70 +#define WNM_NEIGHBOR_MULTIPLE_BSSID 71 + +/* QoS action */ +enum qos_action { + QOS_ADDTS_REQ = 0, + QOS_ADDTS_RESP = 1, + QOS_DELTS = 2, + QOS_SCHEDULE = 3, + QOS_QOS_MAP_CONFIG = 4, +}; + +/* IEEE Std 802.11-2012, 8.4.2.62 20/40 BSS Coexistence element */ +#define WLAN_20_40_BSS_COEX_INFO_REQ BIT(0) +#define WLAN_20_40_BSS_COEX_40MHZ_INTOL BIT(1) +#define WLAN_20_40_BSS_COEX_20MHZ_WIDTH_REQ BIT(2) +#define WLAN_20_40_BSS_COEX_OBSS_EXEMPT_REQ BIT(3) +#define WLAN_20_40_BSS_COEX_OBSS_EXEMPT_GRNT BIT(4) + +STRUCT_PACKED struct ieee80211_2040_bss_coex_ie { + u8 element_id; + u8 length; + u8 coex_param; +}GCC_PACKED; + +STRUCT_PACKED struct ieee80211_2040_intol_chan_report { + u8 element_id; + u8 length; + u8 op_class; + u8 variable[]; /* Channel List */ +}GCC_PACKED; + +/* IEEE 802.11v - WNM-Sleep Mode element */ +STRUCT_PACKED struct wnm_sleep_element { + u8 eid; /* WLAN_EID_WNMSLEEP */ + u8 len; + u8 action_type; /* WNM_SLEEP_ENTER/WNM_SLEEP_MODE_EXIT */ + u8 status; + le16 intval; +}GCC_PACKED; + +#define WNM_SLEEP_MODE_ENTER 0 +#define WNM_SLEEP_MODE_EXIT 1 + +enum wnm_sleep_mode_response_status { + WNM_STATUS_SLEEP_ACCEPT = 0, + WNM_STATUS_SLEEP_EXIT_ACCEPT_GTK_UPDATE = 1, + WNM_STATUS_DENIED_ACTION = 2, + WNM_STATUS_DENIED_TMP = 3, + WNM_STATUS_DENIED_KEY = 4, + WNM_STATUS_DENIED_OTHER_WNM_SERVICE = 5 +}; + +/* WNM-Sleep Mode subelement IDs */ +enum wnm_sleep_mode_subelement_id { + WNM_SLEEP_SUBELEM_GTK = 0, + WNM_SLEEP_SUBELEM_IGTK = 1 +}; + +/* Channel Switch modes (802.11h) */ +#define CHAN_SWITCH_MODE_ALLOW_TX 0 +#define CHAN_SWITCH_MODE_BLOCK_TX 1 + +STRUCT_PACKED struct tpc_report { + u8 eid; + u8 len; + u8 tx_power; + u8 link_margin; +}GCC_PACKED; + +/* IEEE Std 802.11-2012, 8.5.7.4 - Link Measurement Request frame format */ +STRUCT_PACKED struct rrm_link_measurement_request { + u8 dialog_token; + s8 tx_power; + s8 max_tp; + u8 variable[]; +}GCC_PACKED; + +/* IEEE Std 802.11-2012, 8.5.7.5 - Link Measurement Report frame format */ +STRUCT_PACKED struct rrm_link_measurement_report { + u8 dialog_token; + struct tpc_report tpc; + u8 rx_ant_id; + u8 tx_ant_id; + u8 rcpi; + u8 rsni; + u8 variable[]; +}GCC_PACKED; + +#define SSID_MAX_LEN 32 + +/* IEEE Std 802.11ad-2012 - Multi-band element */ +STRUCT_PACKED struct multi_band_ie { + u8 eid; /* WLAN_EID_MULTI_BAND */ + u8 len; + u8 mb_ctrl; + u8 band_id; + u8 op_class; + u8 chan; + u8 bssid[ETH_ALEN]; + le16 beacon_int; + u8 tsf_offs[8]; + u8 mb_connection_capability; + u8 fst_session_tmout; + /* Optional: + * STA MAC Address + * Pairwise Cipher Suite Count + * Pairwise Cipher Suite List + */ + u8 variable[]; +}GCC_PACKED; + +enum mb_ctrl_sta_role { + MB_STA_ROLE_AP = 0, + MB_STA_ROLE_TDLS_STA = 1, + MB_STA_ROLE_IBSS_STA = 2, + MB_STA_ROLE_PCP = 3, + MB_STA_ROLE_NON_PCP_NON_AP = 4 +}; + +#define MB_CTRL_ROLE_MASK (BIT(0) | BIT(1) | BIT(2)) +#define MB_CTRL_ROLE(ctrl) ((u8) ((ctrl) & MB_CTRL_ROLE_MASK)) +#define MB_CTRL_STA_MAC_PRESENT ((u8) (BIT(3))) +#define MB_CTRL_PAIRWISE_CIPHER_SUITE_PRESENT ((u8) (BIT(4))) + +enum mb_band_id { + MB_BAND_ID_WIFI_2_4GHZ = 2, /* 2.4 GHz */ + MB_BAND_ID_WIFI_5GHZ = 4, /* 4.9 and 5 GHz */ + MB_BAND_ID_WIFI_60GHZ = 5, /* 60 GHz */ +}; + +#define MB_CONNECTION_CAPABILITY_AP ((u8) (BIT(0))) +#define MB_CONNECTION_CAPABILITY_PCP ((u8) (BIT(1))) +#define MB_CONNECTION_CAPABILITY_DLS ((u8) (BIT(2))) +#define MB_CONNECTION_CAPABILITY_TDLS ((u8) (BIT(3))) +#define MB_CONNECTION_CAPABILITY_IBSS ((u8) (BIT(4))) + +/* IEEE Std 802.11ad-2014 - FST Action field */ +enum fst_action { + FST_ACTION_SETUP_REQUEST = 0, + FST_ACTION_SETUP_RESPONSE = 1, + FST_ACTION_TEAR_DOWN = 2, + FST_ACTION_ACK_REQUEST = 3, + FST_ACTION_ACK_RESPONSE = 4, + FST_ACTION_ON_CHANNEL_TUNNEL = 5, +}; + +#endif /* IEEE802_11_DEFS_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/common/sae.h b/beken_os/beken378/func/hostapd-2.5/src/common/sae.h new file mode 100755 index 0000000..c07026c --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/common/sae.h @@ -0,0 +1,70 @@ +/* + * Simultaneous authentication of equals + * Copyright (c) 2012-2013, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef SAE_H +#define SAE_H + +#define SAE_KCK_LEN 32 +#define SAE_PMK_LEN 32 +#define SAE_PMKID_LEN 16 +#define SAE_KEYSEED_KEY_LEN 32 +#define SAE_MAX_PRIME_LEN 512 +#define SAE_MAX_ECC_PRIME_LEN 66 +#define SAE_COMMIT_MAX_LEN (2 + 3 * SAE_MAX_PRIME_LEN) +#define SAE_CONFIRM_MAX_LEN (2 + SAE_MAX_PRIME_LEN) + +/* Special value returned by sae_parse_commit() */ +#define SAE_SILENTLY_DISCARD 65535 + +struct sae_temporary_data { + u8 kck[SAE_KCK_LEN]; + struct crypto_bignum *own_commit_scalar; + struct crypto_bignum *own_commit_element_ffc; + struct crypto_ec_point *own_commit_element_ecc; + struct crypto_bignum *peer_commit_element_ffc; + struct crypto_ec_point *peer_commit_element_ecc; + struct crypto_ec_point *pwe_ecc; + struct crypto_bignum *pwe_ffc; + struct crypto_bignum *sae_rand; + struct crypto_ec *ec; + int prime_len; + const struct dh_group *dh; + const struct crypto_bignum *prime; + const struct crypto_bignum *order; + struct crypto_bignum *prime_buf; + struct crypto_bignum *order_buf; + struct wpabuf *anti_clogging_token; +}; + +struct sae_data { + enum { SAE_NOTHING, SAE_COMMITTED, SAE_CONFIRMED, SAE_ACCEPTED } state; + u16 send_confirm; + u8 pmk[SAE_PMK_LEN]; + struct crypto_bignum *peer_commit_scalar; + int group; + int sync; + struct sae_temporary_data *tmp; +}; + +int sae_set_group(struct sae_data *sae, int group); +void sae_clear_temp_data(struct sae_data *sae); +void sae_clear_data(struct sae_data *sae); + +int sae_prepare_commit(const u8 *addr1, const u8 *addr2, + const u8 *password, size_t password_len, + struct sae_data *sae); +int sae_process_commit(struct sae_data *sae); +void sae_write_commit(struct sae_data *sae, struct wpabuf *buf, + const struct wpabuf *token); +u16 sae_parse_commit(struct sae_data *sae, const u8 *data, size_t len, + const u8 **token, size_t *token_len, int *allowed_groups); +void sae_write_confirm(struct sae_data *sae, struct wpabuf *buf); +int sae_check_confirm(struct sae_data *sae, const u8 *data, size_t len); +u16 sae_group_allowed(struct sae_data *sae, int *allowed_groups, u16 group); + +#endif /* SAE_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/common/version.h b/beken_os/beken378/func/hostapd-2.5/src/common/version.h new file mode 100755 index 0000000..94abe44 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/common/version.h @@ -0,0 +1,10 @@ +#ifndef VERSION_H +#define VERSION_H + +#ifndef VERSION_STR_POSTFIX +#define VERSION_STR_POSTFIX "" +#endif /* VERSION_STR_POSTFIX */ + +#define VERSION_STR "2.5" VERSION_STR_POSTFIX + +#endif /* VERSION_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/common/wpa_common.c b/beken_os/beken378/func/hostapd-2.5/src/common/wpa_common.c new file mode 100755 index 0000000..0158476 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/common/wpa_common.c @@ -0,0 +1,1174 @@ +/* + * WPA/RSN - Shared functions for supplicant and authenticator + * Copyright (c) 2002-2015, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "crypto/md5.h" +#include "crypto/sha1.h" +#include "crypto/sha256.h" +#include "crypto/sha384.h" +#include "crypto/aes_wrap.h" +#include "crypto/crypto.h" +#include "ieee802_11_defs.h" +#include "defs.h" +#include "wpa_common.h" + + +static unsigned int wpa_kck_len(int akmp) +{ + if (akmp == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) + return 24; + return 16; +} + + +static unsigned int wpa_kek_len(int akmp) +{ + if (akmp == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) + return 32; + return 16; +} + + +unsigned int wpa_mic_len(int akmp) +{ + if (akmp == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) + return 24; + return 16; +} + + +/** + * wpa_eapol_key_mic - Calculate EAPOL-Key MIC + * @key: EAPOL-Key Key Confirmation Key (KCK) + * @key_len: KCK length in octets + * @akmp: WPA_KEY_MGMT_* used in key derivation + * @ver: Key descriptor version (WPA_KEY_INFO_TYPE_*) + * @buf: Pointer to the beginning of the EAPOL header (version field) + * @len: Length of the EAPOL frame (from EAPOL header to the end of the frame) + * @mic: Pointer to the buffer to which the EAPOL-Key MIC is written + * Returns: 0 on success, -1 on failure + * + * Calculate EAPOL-Key MIC for an EAPOL-Key packet. The EAPOL-Key MIC field has + * to be cleared (all zeroes) when calling this function. + * + * Note: 'IEEE Std 802.11i-2004 - 8.5.2 EAPOL-Key frames' has an error in the + * description of the Key MIC calculation. It includes packet data from the + * beginning of the EAPOL-Key header, not EAPOL header. This incorrect change + * happened during final editing of the standard and the correct behavior is + * defined in the last draft (IEEE 802.11i/D10). + */ +int wpa_eapol_key_mic(const u8 *key, size_t key_len, int akmp, int ver, + const u8 *buf, size_t len, u8 *mic) +{ + u8 hash[SHA384_MAC_LEN]; + + switch (ver) { +#ifndef CONFIG_FIPS + case WPA_KEY_INFO_TYPE_HMAC_MD5_RC4: + return hmac_md5(key, key_len, buf, len, mic); +#endif /* CONFIG_FIPS */ + case WPA_KEY_INFO_TYPE_HMAC_SHA1_AES: + if (hmac_sha1(key, key_len, buf, len, hash)) + return -1; + os_memcpy(mic, hash, MD5_MAC_LEN); + break; +#if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211W) + case WPA_KEY_INFO_TYPE_AES_128_CMAC: + return omac1_aes_128(key, buf, len, mic); +#endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W */ + case WPA_KEY_INFO_TYPE_AKM_DEFINED: + switch (akmp) { +#ifdef CONFIG_HS20 + case WPA_KEY_MGMT_OSEN: + return omac1_aes_128(key, buf, len, mic); +#endif /* CONFIG_HS20 */ +#ifdef CONFIG_SUITEB + case WPA_KEY_MGMT_IEEE8021X_SUITE_B: + if (hmac_sha256(key, key_len, buf, len, hash)) + return -1; + os_memcpy(mic, hash, MD5_MAC_LEN); + break; +#endif /* CONFIG_SUITEB */ +#ifdef CONFIG_SUITEB192 + case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192: + if (hmac_sha384(key, key_len, buf, len, hash)) + return -1; + os_memcpy(mic, hash, 24); + break; +#endif /* CONFIG_SUITEB192 */ + default: + return -1; + } + #if (defined(CONFIG_HS20) || defined(CONFIG_SUITEB) || defined(CONFIG_SUITEB192)) + break; + #endif + default: + return -1; + } + + return 0; +} + + +/** + * wpa_pmk_to_ptk - Calculate PTK from PMK, addresses, and nonces + * @pmk: Pairwise master key + * @pmk_len: Length of PMK + * @label: Label to use in derivation + * @addr1: AA or SA + * @addr2: SA or AA + * @nonce1: ANonce or SNonce + * @nonce2: SNonce or ANonce + * @ptk: Buffer for pairwise transient key + * @akmp: Negotiated AKM + * @cipher: Negotiated pairwise cipher + * Returns: 0 on success, -1 on failure + * + * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy + * PTK = PRF-X(PMK, "Pairwise key expansion", + * Min(AA, SA) || Max(AA, SA) || + * Min(ANonce, SNonce) || Max(ANonce, SNonce)) + * + * STK = PRF-X(SMK, "Peer key expansion", + * Min(MAC_I, MAC_P) || Max(MAC_I, MAC_P) || + * Min(INonce, PNonce) || Max(INonce, PNonce)) + */ +int wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label, + const u8 *addr1, const u8 *addr2, + const u8 *nonce1, const u8 *nonce2, + struct wpa_ptk *ptk, int akmp, int cipher) +{ + u8 data[2 * ETH_ALEN + 2 * WPA_NONCE_LEN]; + u8 tmp[WPA_KCK_MAX_LEN + WPA_KEK_MAX_LEN + WPA_TK_MAX_LEN]; + size_t ptk_len; + + if (os_memcmp(addr1, addr2, ETH_ALEN) < 0) { + os_memcpy(data, addr1, ETH_ALEN); + os_memcpy(data + ETH_ALEN, addr2, ETH_ALEN); + } else { + os_memcpy(data, addr2, ETH_ALEN); + os_memcpy(data + ETH_ALEN, addr1, ETH_ALEN); + } + + if (os_memcmp(nonce1, nonce2, WPA_NONCE_LEN) < 0) { + os_memcpy(data + 2 * ETH_ALEN, nonce1, WPA_NONCE_LEN); + os_memcpy(data + 2 * ETH_ALEN + WPA_NONCE_LEN, nonce2, + WPA_NONCE_LEN); + } else { + os_memcpy(data + 2 * ETH_ALEN, nonce2, WPA_NONCE_LEN); + os_memcpy(data + 2 * ETH_ALEN + WPA_NONCE_LEN, nonce1, + WPA_NONCE_LEN); + } + + ptk->kck_len = wpa_kck_len(akmp); + ptk->kek_len = wpa_kek_len(akmp); + ptk->tk_len = wpa_cipher_key_len(cipher); + ptk_len = ptk->kck_len + ptk->kek_len + ptk->tk_len; + +#ifdef CONFIG_SUITEB192 + if (wpa_key_mgmt_sha384(akmp)) + sha384_prf(pmk, pmk_len, label, data, sizeof(data), + tmp, ptk_len); + else +#endif /* CONFIG_SUITEB192 */ +#ifdef CONFIG_IEEE80211W + if (wpa_key_mgmt_sha256(akmp)) + sha256_prf(pmk, pmk_len, label, data, sizeof(data), + tmp, ptk_len); + else +#endif /* CONFIG_IEEE80211W */ + sha1_prf(pmk, pmk_len, label, data, sizeof(data), tmp, ptk_len); + + wpa_printf(MSG_DEBUG, "WPA: PTK derivation - A1=" MACSTR " A2=" MACSTR, + MAC2STR(addr1), MAC2STR(addr2)); + wpa_hexdump(MSG_DEBUG, "WPA: Nonce1", nonce1, WPA_NONCE_LEN); + wpa_hexdump(MSG_DEBUG, "WPA: Nonce2", nonce2, WPA_NONCE_LEN); + wpa_hexdump_key(MSG_DEBUG, "WPA: PMK", pmk, pmk_len); + wpa_hexdump_key(MSG_DEBUG, "WPA: PTK", tmp, ptk_len); + + os_memcpy(ptk->kck, tmp, ptk->kck_len); + wpa_hexdump_key(MSG_DEBUG, "WPA: KCK", ptk->kck, ptk->kck_len); + + os_memcpy(ptk->kek, tmp + ptk->kck_len, ptk->kek_len); + wpa_hexdump_key(MSG_DEBUG, "WPA: KEK", ptk->kek, ptk->kek_len); + + os_memcpy(ptk->tk, tmp + ptk->kck_len + ptk->kek_len, ptk->tk_len); + wpa_hexdump_key(MSG_DEBUG, "WPA: TK", ptk->tk, ptk->tk_len); + + os_memset(tmp, 0, sizeof(tmp)); + return 0; +} + +static int rsn_selector_to_bitfield(const u8 *s) +{ + if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_NONE) + return WPA_CIPHER_NONE; + if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_TKIP) + return WPA_CIPHER_TKIP; + if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_CCMP) + return WPA_CIPHER_CCMP; +#ifdef CONFIG_IEEE80211W + if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_AES_128_CMAC) + return WPA_CIPHER_AES_128_CMAC; +#endif /* CONFIG_IEEE80211W */ + if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_GCMP) + return WPA_CIPHER_GCMP; + if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_CCMP_256) + return WPA_CIPHER_CCMP_256; + if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_GCMP_256) + return WPA_CIPHER_GCMP_256; + if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_BIP_GMAC_128) + return WPA_CIPHER_BIP_GMAC_128; + if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_BIP_GMAC_256) + return WPA_CIPHER_BIP_GMAC_256; + if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_BIP_CMAC_256) + return WPA_CIPHER_BIP_CMAC_256; + if (RSN_SELECTOR_GET(s) == RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED) + return WPA_CIPHER_GTK_NOT_USED; + return 0; +} + + +static int rsn_key_mgmt_to_bitfield(const u8 *s) +{ + if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_UNSPEC_802_1X) + return WPA_KEY_MGMT_IEEE8021X; + if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X) + return WPA_KEY_MGMT_PSK; +#ifdef CONFIG_IEEE80211R + if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_802_1X) + return WPA_KEY_MGMT_FT_IEEE8021X; + if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_PSK) + return WPA_KEY_MGMT_FT_PSK; +#endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_IEEE80211W + if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SHA256) + return WPA_KEY_MGMT_IEEE8021X_SHA256; + if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_PSK_SHA256) + return WPA_KEY_MGMT_PSK_SHA256; +#endif /* CONFIG_IEEE80211W */ +#ifdef CONFIG_SAE + if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_SAE) + return WPA_KEY_MGMT_SAE; + if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_FT_SAE) + return WPA_KEY_MGMT_FT_SAE; +#endif /* CONFIG_SAE */ + if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SUITE_B) + return WPA_KEY_MGMT_IEEE8021X_SUITE_B; + if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192) + return WPA_KEY_MGMT_IEEE8021X_SUITE_B_192; + if (RSN_SELECTOR_GET(s) == RSN_AUTH_KEY_MGMT_OSEN) + return WPA_KEY_MGMT_OSEN; + return 0; +} + + +int wpa_cipher_valid_group(int cipher) +{ + return wpa_cipher_valid_pairwise(cipher) || + cipher == WPA_CIPHER_GTK_NOT_USED; +} + + +#ifdef CONFIG_IEEE80211W +int wpa_cipher_valid_mgmt_group(int cipher) +{ + return cipher == WPA_CIPHER_AES_128_CMAC || + cipher == WPA_CIPHER_BIP_GMAC_128 || + cipher == WPA_CIPHER_BIP_GMAC_256 || + cipher == WPA_CIPHER_BIP_CMAC_256; +} +#endif /* CONFIG_IEEE80211W */ + + +/** + * wpa_parse_wpa_ie_rsn - Parse RSN IE + * @rsn_ie: Buffer containing RSN IE + * @rsn_ie_len: RSN IE buffer length (including IE number and length octets) + * @data: Pointer to structure that will be filled in with parsed data + * Returns: 0 on success, <0 on failure + */ +int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len, + struct wpa_ie_data *data) +{ + const struct rsn_ie_hdr *hdr; + const u8 *pos; + int left; + int i, count; + + os_memset(data, 0, sizeof(*data)); + data->proto = WPA_PROTO_RSN; + data->pairwise_cipher = WPA_CIPHER_CCMP; + data->group_cipher = WPA_CIPHER_CCMP; + data->key_mgmt = WPA_KEY_MGMT_IEEE8021X; + data->capabilities = 0; + data->pmkid = NULL; + data->num_pmkid = 0; +#ifdef CONFIG_IEEE80211W + data->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC; +#else /* CONFIG_IEEE80211W */ + data->mgmt_group_cipher = 0; +#endif /* CONFIG_IEEE80211W */ + + if (rsn_ie_len == 0) { + /* No RSN IE - fail silently */ + return -1; + } + + if (rsn_ie_len < sizeof(struct rsn_ie_hdr)) { + wpa_printf(MSG_DEBUG, "%s: ie len too short %lu", + __func__, (unsigned long) rsn_ie_len); + return -1; + } + + hdr = (const struct rsn_ie_hdr *) rsn_ie; + + if (hdr->elem_id != WLAN_EID_RSN || + hdr->len != rsn_ie_len - 2 || + WPA_GET_LE16(hdr->version) != RSN_VERSION) { + wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version", + __func__); + return -2; + } + + pos = (const u8 *) (hdr + 1); + left = rsn_ie_len - sizeof(*hdr); + + if (left >= RSN_SELECTOR_LEN) { + data->group_cipher = rsn_selector_to_bitfield(pos); + if (!wpa_cipher_valid_group(data->group_cipher)) { + wpa_printf(MSG_DEBUG, "%s: invalid group cipher 0x%x", + __func__, data->group_cipher); + return -1; + } + pos += RSN_SELECTOR_LEN; + left -= RSN_SELECTOR_LEN; + } else if (left > 0) { + wpa_printf(MSG_DEBUG, "%s: ie length mismatch, %u too much", + __func__, left); + return -3; + } + + if (left >= 2) { + data->pairwise_cipher = 0; + count = WPA_GET_LE16(pos); + pos += 2; + left -= 2; + if (count == 0 || count > left / RSN_SELECTOR_LEN) { + wpa_printf(MSG_DEBUG, "%s: ie count botch (pairwise), " + "count %u left %u", __func__, count, left); + return -4; + } + for (i = 0; i < count; i++) { + data->pairwise_cipher |= rsn_selector_to_bitfield(pos); + pos += RSN_SELECTOR_LEN; + left -= RSN_SELECTOR_LEN; + } +#ifdef CONFIG_IEEE80211W + if (data->pairwise_cipher & WPA_CIPHER_AES_128_CMAC) { + wpa_printf(MSG_DEBUG, "%s: AES-128-CMAC used as " + "pairwise cipher", __func__); + return -1; + } +#endif /* CONFIG_IEEE80211W */ + } else if (left == 1) { + wpa_printf(MSG_DEBUG, "%s: ie too short (for key mgmt)", + __func__); + return -5; + } + + if (left >= 2) { + data->key_mgmt = 0; + count = WPA_GET_LE16(pos); + pos += 2; + left -= 2; + if (count == 0 || count > left / RSN_SELECTOR_LEN) { + wpa_printf(MSG_DEBUG, "%s: ie count botch (key mgmt), " + "count %u left %u", __func__, count, left); + return -6; + } + for (i = 0; i < count; i++) { + data->key_mgmt |= rsn_key_mgmt_to_bitfield(pos); + pos += RSN_SELECTOR_LEN; + left -= RSN_SELECTOR_LEN; + } + } else if (left == 1) { + wpa_printf(MSG_DEBUG, "%s: ie too short (for capabilities)", + __func__); + return -7; + } + + if (left >= 2) { + data->capabilities = WPA_GET_LE16(pos); + pos += 2; + left -= 2; + } + + if (left >= 2) { + u16 num_pmkid = WPA_GET_LE16(pos); + pos += 2; + left -= 2; + if (num_pmkid > (unsigned int) left / PMKID_LEN) { + wpa_printf(MSG_DEBUG, "%s: PMKID underflow " + "(num_pmkid=%u left=%d)", + __func__, num_pmkid, left); + data->num_pmkid = 0; + return -9; + } else { + data->num_pmkid = num_pmkid; + data->pmkid = pos; + pos += data->num_pmkid * PMKID_LEN; + left -= data->num_pmkid * PMKID_LEN; + } + } + +#ifdef CONFIG_IEEE80211W + if (left >= 4) { + data->mgmt_group_cipher = rsn_selector_to_bitfield(pos); + if (!wpa_cipher_valid_mgmt_group(data->mgmt_group_cipher)) { + wpa_printf(MSG_DEBUG, "%s: Unsupported management " + "group cipher 0x%x", __func__, + data->mgmt_group_cipher); + return -10; + } + pos += RSN_SELECTOR_LEN; + left -= RSN_SELECTOR_LEN; + } +#endif /* CONFIG_IEEE80211W */ + + if (left > 0) { + wpa_hexdump(MSG_DEBUG, + "wpa_parse_wpa_ie_rsn: ignore trailing bytes", + pos, left); + } + + return 0; +} + + +static int wpa_selector_to_bitfield(const u8 *s) +{ + if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_NONE) + return WPA_CIPHER_NONE; + if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_TKIP) + return WPA_CIPHER_TKIP; + if (RSN_SELECTOR_GET(s) == WPA_CIPHER_SUITE_CCMP) + return WPA_CIPHER_CCMP; + return 0; +} + + +static int wpa_key_mgmt_to_bitfield(const u8 *s) +{ + if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_UNSPEC_802_1X) + return WPA_KEY_MGMT_IEEE8021X; + if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X) + return WPA_KEY_MGMT_PSK; + if (RSN_SELECTOR_GET(s) == WPA_AUTH_KEY_MGMT_NONE) + return WPA_KEY_MGMT_WPA_NONE; + return 0; +} + + +int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len, + struct wpa_ie_data *data) +{ + const struct wpa_ie_hdr *hdr; + const u8 *pos; + int left; + int i, count; + + os_memset(data, 0, sizeof(*data)); + data->proto = WPA_PROTO_WPA; + data->pairwise_cipher = WPA_CIPHER_TKIP; + data->group_cipher = WPA_CIPHER_TKIP; + data->key_mgmt = WPA_KEY_MGMT_IEEE8021X; + data->capabilities = 0; + data->pmkid = NULL; + data->num_pmkid = 0; + data->mgmt_group_cipher = 0; + + if (wpa_ie_len < sizeof(struct wpa_ie_hdr)) { + wpa_printf(MSG_DEBUG, "%s: ie len too short %lu", + __func__, (unsigned long) wpa_ie_len); + return -1; + } + + hdr = (const struct wpa_ie_hdr *) wpa_ie; + + if (hdr->elem_id != WLAN_EID_VENDOR_SPECIFIC || + hdr->len != wpa_ie_len - 2 || + RSN_SELECTOR_GET(hdr->oui) != WPA_OUI_TYPE || + WPA_GET_LE16(hdr->version) != WPA_VERSION) { + wpa_printf(MSG_DEBUG, "%s: malformed ie or unknown version", + __func__); + return -2; + } + + pos = (const u8 *) (hdr + 1); + left = wpa_ie_len - sizeof(*hdr); + + if (left >= WPA_SELECTOR_LEN) { + data->group_cipher = wpa_selector_to_bitfield(pos); + pos += WPA_SELECTOR_LEN; + left -= WPA_SELECTOR_LEN; + } else if (left > 0) { + wpa_printf(MSG_DEBUG, "%s: ie length mismatch, %u too much", + __func__, left); + return -3; + } + + if (left >= 2) { + data->pairwise_cipher = 0; + count = WPA_GET_LE16(pos); + pos += 2; + left -= 2; + if (count == 0 || count > left / WPA_SELECTOR_LEN) { + wpa_printf(MSG_DEBUG, "%s: ie count botch (pairwise), " + "count %u left %u", __func__, count, left); + return -4; + } + for (i = 0; i < count; i++) { + data->pairwise_cipher |= wpa_selector_to_bitfield(pos); + pos += WPA_SELECTOR_LEN; + left -= WPA_SELECTOR_LEN; + } + } else if (left == 1) { + wpa_printf(MSG_DEBUG, "%s: ie too short (for key mgmt)", + __func__); + return -5; + } + + if (left >= 2) { + data->key_mgmt = 0; + count = WPA_GET_LE16(pos); + pos += 2; + left -= 2; + if (count == 0 || count > left / WPA_SELECTOR_LEN) { + wpa_printf(MSG_DEBUG, "%s: ie count botch (key mgmt), " + "count %u left %u", __func__, count, left); + return -6; + } + for (i = 0; i < count; i++) { + data->key_mgmt |= wpa_key_mgmt_to_bitfield(pos); + pos += WPA_SELECTOR_LEN; + left -= WPA_SELECTOR_LEN; + } + } else if (left == 1) { + wpa_printf(MSG_DEBUG, "%s: ie too short (for capabilities)", + __func__); + return -7; + } + + if (left >= 2) { + data->capabilities = WPA_GET_LE16(pos); + pos += 2; + left -= 2; + } + + if (left > 0) { + wpa_hexdump(MSG_DEBUG, + "wpa_parse_wpa_ie_wpa: ignore trailing bytes", + pos, left); + } + + return 0; +} + + + +/** + * rsn_pmkid - Calculate PMK identifier + * @pmk: Pairwise master key + * @pmk_len: Length of pmk in bytes + * @aa: Authenticator address + * @spa: Supplicant address + * @pmkid: Buffer for PMKID + * @use_sha256: Whether to use SHA256-based KDF + * + * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy + * PMKID = HMAC-SHA1-128(PMK, "PMK Name" || AA || SPA) + */ +void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa, + u8 *pmkid, int use_sha256) +{ + char *title = "PMK Name"; + const u8 *addr[3]; + const size_t len[3] = { 8, ETH_ALEN, ETH_ALEN }; + unsigned char hash[SHA256_MAC_LEN]; + + addr[0] = (u8 *) title; + addr[1] = aa; + addr[2] = spa; + +#ifdef CONFIG_IEEE80211W + if (use_sha256) + hmac_sha256_vector(pmk, pmk_len, 3, addr, len, hash); + else +#endif /* CONFIG_IEEE80211W */ + hmac_sha1_vector(pmk, pmk_len, 3, addr, len, hash); + os_memcpy(pmkid, hash, PMKID_LEN); +} + + +/** + * wpa_cipher_txt - Convert cipher suite to a text string + * @cipher: Cipher suite (WPA_CIPHER_* enum) + * Returns: Pointer to a text string of the cipher suite name + */ +const char * wpa_cipher_txt(int cipher) +{ + switch (cipher) { + case WPA_CIPHER_NONE: + return "NONE"; + case WPA_CIPHER_WEP40: + return "WEP-40"; + case WPA_CIPHER_WEP104: + return "WEP-104"; + case WPA_CIPHER_TKIP: + return "TKIP"; + case WPA_CIPHER_CCMP: + return "CCMP"; + case WPA_CIPHER_CCMP | WPA_CIPHER_TKIP: + return "CCMP+TKIP"; + case WPA_CIPHER_GCMP: + return "GCMP"; + case WPA_CIPHER_GCMP_256: + return "GCMP-256"; + case WPA_CIPHER_CCMP_256: + return "CCMP-256"; + case WPA_CIPHER_GTK_NOT_USED: + return "GTK_NOT_USED"; + default: + return "UNKNOWN"; + } +} + + +/** + * wpa_key_mgmt_txt - Convert key management suite to a text string + * @key_mgmt: Key management suite (WPA_KEY_MGMT_* enum) + * @proto: WPA/WPA2 version (WPA_PROTO_*) + * Returns: Pointer to a text string of the key management suite name + */ +const char * wpa_key_mgmt_txt(int key_mgmt, int proto) +{ + switch (key_mgmt) { + case WPA_KEY_MGMT_IEEE8021X: + if (proto == (WPA_PROTO_RSN | WPA_PROTO_WPA)) + return "WPA2+WPA/IEEE 802.1X/EAP"; + return proto == WPA_PROTO_RSN ? + "WPA2/IEEE 802.1X/EAP" : "WPA/IEEE 802.1X/EAP"; + case WPA_KEY_MGMT_PSK: + if (proto == (WPA_PROTO_RSN | WPA_PROTO_WPA)) + return "WPA2-PSK+WPA-PSK"; + return proto == WPA_PROTO_RSN ? + "WPA2-PSK" : "WPA-PSK"; + case WPA_KEY_MGMT_NONE: + return "NONE"; + case WPA_KEY_MGMT_IEEE8021X_NO_WPA: + return "IEEE 802.1X (no WPA)"; +#ifdef CONFIG_IEEE80211R + case WPA_KEY_MGMT_FT_IEEE8021X: + return "FT-EAP"; + case WPA_KEY_MGMT_FT_PSK: + return "FT-PSK"; +#endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_IEEE80211W + case WPA_KEY_MGMT_IEEE8021X_SHA256: + return "WPA2-EAP-SHA256"; + case WPA_KEY_MGMT_PSK_SHA256: + return "WPA2-PSK-SHA256"; +#endif /* CONFIG_IEEE80211W */ + case WPA_KEY_MGMT_WPS: + return "WPS"; + case WPA_KEY_MGMT_SAE: + return "SAE"; + case WPA_KEY_MGMT_FT_SAE: + return "FT-SAE"; + case WPA_KEY_MGMT_OSEN: + return "OSEN"; + case WPA_KEY_MGMT_IEEE8021X_SUITE_B: + return "WPA2-EAP-SUITE-B"; + case WPA_KEY_MGMT_IEEE8021X_SUITE_B_192: + return "WPA2-EAP-SUITE-B-192"; + default: + return "UNKNOWN"; + } +} + + +u32 wpa_akm_to_suite(int akm) +{ + if (akm & WPA_KEY_MGMT_FT_IEEE8021X) + return WLAN_AKM_SUITE_FT_8021X; + if (akm & WPA_KEY_MGMT_FT_PSK) + return WLAN_AKM_SUITE_FT_PSK; + if (akm & WPA_KEY_MGMT_IEEE8021X) + return WLAN_AKM_SUITE_8021X; + if (akm & WPA_KEY_MGMT_IEEE8021X_SHA256) + return WLAN_AKM_SUITE_8021X_SHA256; + if (akm & WPA_KEY_MGMT_IEEE8021X) + return WLAN_AKM_SUITE_8021X; + if (akm & WPA_KEY_MGMT_PSK_SHA256) + return WLAN_AKM_SUITE_PSK_SHA256; + if (akm & WPA_KEY_MGMT_PSK) + return WLAN_AKM_SUITE_PSK; + if (akm & WPA_KEY_MGMT_CCKM) + return WLAN_AKM_SUITE_CCKM; + if (akm & WPA_KEY_MGMT_OSEN) + return WLAN_AKM_SUITE_OSEN; + if (akm & WPA_KEY_MGMT_IEEE8021X_SUITE_B) + return WLAN_AKM_SUITE_8021X_SUITE_B; + if (akm & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) + return WLAN_AKM_SUITE_8021X_SUITE_B_192; + return 0; +} + + +int wpa_compare_rsn_ie(int ft_initial_assoc, + const u8 *ie1, size_t ie1len, + const u8 *ie2, size_t ie2len) +{ + if (ie1 == NULL || ie2 == NULL) + return -1; + + if (ie1len == ie2len && os_memcmp(ie1, ie2, ie1len) == 0) + return 0; /* identical IEs */ + +#ifdef CONFIG_IEEE80211R + if (ft_initial_assoc) { + struct wpa_ie_data ie1d, ie2d; + /* + * The PMKID-List in RSN IE is different between Beacon/Probe + * Response/(Re)Association Request frames and EAPOL-Key + * messages in FT initial mobility domain association. Allow + * for this, but verify that other parts of the RSN IEs are + * identical. + */ + if (wpa_parse_wpa_ie_rsn(ie1, ie1len, &ie1d) < 0 || + wpa_parse_wpa_ie_rsn(ie2, ie2len, &ie2d) < 0) + return -1; + if (ie1d.proto == ie2d.proto && + ie1d.pairwise_cipher == ie2d.pairwise_cipher && + ie1d.group_cipher == ie2d.group_cipher && + ie1d.key_mgmt == ie2d.key_mgmt && + ie1d.capabilities == ie2d.capabilities && + ie1d.mgmt_group_cipher == ie2d.mgmt_group_cipher) + return 0; + } +#endif /* CONFIG_IEEE80211R */ + + return -1; +} + + +#ifdef CONFIG_IEEE80211R +int wpa_insert_pmkid(u8 *ies, size_t ies_len, const u8 *pmkid) +{ + u8 *start, *end, *rpos, *rend; + int added = 0; + + start = ies; + end = ies + ies_len; + + while (start < end) { + if (*start == WLAN_EID_RSN) + break; + start += 2 + start[1]; + } + if (start >= end) { + wpa_printf(MSG_ERROR, "FT: Could not find RSN IE in " + "IEs data"); + return -1; + } + wpa_hexdump(MSG_DEBUG, "FT: RSN IE before modification", + start, 2 + start[1]); + + /* Find start of PMKID-Count */ + rpos = start + 2; + rend = rpos + start[1]; + + /* Skip Version and Group Data Cipher Suite */ + rpos += 2 + 4; + /* Skip Pairwise Cipher Suite Count and List */ + rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN; + /* Skip AKM Suite Count and List */ + rpos += 2 + WPA_GET_LE16(rpos) * RSN_SELECTOR_LEN; + + if (rpos == rend) { + /* Add RSN Capabilities */ + os_memmove(rpos + 2, rpos, end - rpos); + *rpos++ = 0; + *rpos++ = 0; + added += 2; + start[1] += 2; + rend = rpos; + } else { + /* Skip RSN Capabilities */ + rpos += 2; + if (rpos > rend) { + wpa_printf(MSG_ERROR, "FT: Could not parse RSN IE in " + "IEs data"); + return -1; + } + } + + if (rpos == rend) { + /* No PMKID-Count field included; add it */ + os_memmove(rpos + 2 + PMKID_LEN, rpos, end + added - rpos); + WPA_PUT_LE16(rpos, 1); + rpos += 2; + os_memcpy(rpos, pmkid, PMKID_LEN); + added += 2 + PMKID_LEN; + start[1] += 2 + PMKID_LEN; + } else { + /* PMKID-Count was included; use it */ + if (WPA_GET_LE16(rpos) != 0) { + wpa_printf(MSG_ERROR, "FT: Unexpected PMKID " + "in RSN IE in EAPOL-Key data"); + return -1; + } + WPA_PUT_LE16(rpos, 1); + rpos += 2; + os_memmove(rpos + PMKID_LEN, rpos, end + added - rpos); + os_memcpy(rpos, pmkid, PMKID_LEN); + added += PMKID_LEN; + start[1] += PMKID_LEN; + } + + wpa_hexdump(MSG_DEBUG, "FT: RSN IE after modification " + "(PMKID inserted)", start, 2 + start[1]); + + return added; +} +#endif /* CONFIG_IEEE80211R */ + + +int wpa_cipher_key_len(int cipher) +{ + switch (cipher) { + case WPA_CIPHER_CCMP_256: + case WPA_CIPHER_GCMP_256: + case WPA_CIPHER_BIP_GMAC_256: + case WPA_CIPHER_BIP_CMAC_256: + return 32; + case WPA_CIPHER_CCMP: + case WPA_CIPHER_GCMP: + case WPA_CIPHER_AES_128_CMAC: + case WPA_CIPHER_BIP_GMAC_128: + return 16; + case WPA_CIPHER_TKIP: + return 32; + } + + return 0; +} + + +int wpa_cipher_rsc_len(int cipher) +{ + switch (cipher) { + case WPA_CIPHER_CCMP_256: + case WPA_CIPHER_GCMP_256: + case WPA_CIPHER_CCMP: + case WPA_CIPHER_GCMP: + case WPA_CIPHER_TKIP: + return 6; + } + + return 0; +} + + +int wpa_cipher_to_alg(int cipher) +{ + switch (cipher) { + case WPA_CIPHER_CCMP_256: + return WPA_ALG_CCMP_256; + case WPA_CIPHER_GCMP_256: + return WPA_ALG_GCMP_256; + case WPA_CIPHER_CCMP: + return WPA_ALG_CCMP; + case WPA_CIPHER_GCMP: + return WPA_ALG_GCMP; + case WPA_CIPHER_TKIP: + return WPA_ALG_TKIP; + case WPA_CIPHER_AES_128_CMAC: + return WPA_ALG_IGTK; + case WPA_CIPHER_BIP_GMAC_128: + return WPA_ALG_BIP_GMAC_128; + case WPA_CIPHER_BIP_GMAC_256: + return WPA_ALG_BIP_GMAC_256; + case WPA_CIPHER_BIP_CMAC_256: + return WPA_ALG_BIP_CMAC_256; + } + return WPA_ALG_NONE; +} + + +int wpa_cipher_valid_pairwise(int cipher) +{ + return cipher == WPA_CIPHER_CCMP_256 || + cipher == WPA_CIPHER_GCMP_256 || + cipher == WPA_CIPHER_CCMP || + cipher == WPA_CIPHER_GCMP || + cipher == WPA_CIPHER_TKIP; +} + + +u32 wpa_cipher_to_suite(int proto, int cipher) +{ + if (cipher & WPA_CIPHER_CCMP_256) + return RSN_CIPHER_SUITE_CCMP_256; + if (cipher & WPA_CIPHER_GCMP_256) + return RSN_CIPHER_SUITE_GCMP_256; + if (cipher & WPA_CIPHER_CCMP) + return (proto == WPA_PROTO_RSN ? + RSN_CIPHER_SUITE_CCMP : WPA_CIPHER_SUITE_CCMP); + if (cipher & WPA_CIPHER_GCMP) + return RSN_CIPHER_SUITE_GCMP; + if (cipher & WPA_CIPHER_TKIP) + return (proto == WPA_PROTO_RSN ? + RSN_CIPHER_SUITE_TKIP : WPA_CIPHER_SUITE_TKIP); + if (cipher & WPA_CIPHER_NONE) + return (proto == WPA_PROTO_RSN ? + RSN_CIPHER_SUITE_NONE : WPA_CIPHER_SUITE_NONE); + if (cipher & WPA_CIPHER_GTK_NOT_USED) + return RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED; + if (cipher & WPA_CIPHER_AES_128_CMAC) + return RSN_CIPHER_SUITE_AES_128_CMAC; + if (cipher & WPA_CIPHER_BIP_GMAC_128) + return RSN_CIPHER_SUITE_BIP_GMAC_128; + if (cipher & WPA_CIPHER_BIP_GMAC_256) + return RSN_CIPHER_SUITE_BIP_GMAC_256; + if (cipher & WPA_CIPHER_BIP_CMAC_256) + return RSN_CIPHER_SUITE_BIP_CMAC_256; + return 0; +} + + +int rsn_cipher_put_suites(u8 *start, int ciphers) +{ + u8 *pos = start; + + if (ciphers & WPA_CIPHER_CCMP_256) { + RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP_256); + pos += RSN_SELECTOR_LEN; + } + if (ciphers & WPA_CIPHER_GCMP_256) { + RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_GCMP_256); + pos += RSN_SELECTOR_LEN; + } + if (ciphers & WPA_CIPHER_CCMP) { + RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_CCMP); + pos += RSN_SELECTOR_LEN; + } + if (ciphers & WPA_CIPHER_GCMP) { + RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_GCMP); + pos += RSN_SELECTOR_LEN; + } + if (ciphers & WPA_CIPHER_TKIP) { + RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_TKIP); + pos += RSN_SELECTOR_LEN; + } + if (ciphers & WPA_CIPHER_NONE) { + RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_NONE); + pos += RSN_SELECTOR_LEN; + } + + return (pos - start) / RSN_SELECTOR_LEN; +} + + +int wpa_cipher_put_suites(u8 *start, int ciphers) +{ + u8 *pos = start; + + if (ciphers & WPA_CIPHER_CCMP) { + RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_CCMP); + pos += WPA_SELECTOR_LEN; + } + if (ciphers & WPA_CIPHER_TKIP) { + RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_TKIP); + pos += WPA_SELECTOR_LEN; + } + if (ciphers & WPA_CIPHER_NONE) { + RSN_SELECTOR_PUT(pos, WPA_CIPHER_SUITE_NONE); + pos += WPA_SELECTOR_LEN; + } + + return (pos - start) / RSN_SELECTOR_LEN; +} + + +int wpa_pick_pairwise_cipher(int ciphers, int none_allowed) +{ + if (ciphers & WPA_CIPHER_CCMP_256) + return WPA_CIPHER_CCMP_256; + if (ciphers & WPA_CIPHER_GCMP_256) + return WPA_CIPHER_GCMP_256; + if (ciphers & WPA_CIPHER_CCMP) + return WPA_CIPHER_CCMP; + if (ciphers & WPA_CIPHER_GCMP) + return WPA_CIPHER_GCMP; + if (ciphers & WPA_CIPHER_TKIP) + return WPA_CIPHER_TKIP; + if (none_allowed && (ciphers & WPA_CIPHER_NONE)) + return WPA_CIPHER_NONE; + return -1; +} + + +int wpa_pick_group_cipher(int ciphers) +{ + if (ciphers & WPA_CIPHER_CCMP_256) + return WPA_CIPHER_CCMP_256; + if (ciphers & WPA_CIPHER_GCMP_256) + return WPA_CIPHER_GCMP_256; + if (ciphers & WPA_CIPHER_CCMP) + return WPA_CIPHER_CCMP; + if (ciphers & WPA_CIPHER_GCMP) + return WPA_CIPHER_GCMP; + if (ciphers & WPA_CIPHER_GTK_NOT_USED) + return WPA_CIPHER_GTK_NOT_USED; + if (ciphers & WPA_CIPHER_TKIP) + return WPA_CIPHER_TKIP; + return -1; +} + + +int wpa_parse_cipher(const char *value) +{ + int val = 0, last; + char *start, *end, *buf; + + buf = os_strdup(value); + if (buf == NULL) + return -1; + start = buf; + + while (*start != '\0') { + while (*start == ' ' || *start == '\t') + start++; + if (*start == '\0') + break; + end = start; + while (*end != ' ' && *end != '\t' && *end != '\0') + end++; + last = *end == '\0'; + *end = '\0'; + if (os_strcmp(start, "CCMP-256") == 0) + val |= WPA_CIPHER_CCMP_256; + else if (os_strcmp(start, "GCMP-256") == 0) + val |= WPA_CIPHER_GCMP_256; + else if (os_strcmp(start, "CCMP") == 0) + val |= WPA_CIPHER_CCMP; + else if (os_strcmp(start, "GCMP") == 0) + val |= WPA_CIPHER_GCMP; + else if (os_strcmp(start, "TKIP") == 0) + val |= WPA_CIPHER_TKIP; + else if (os_strcmp(start, "WEP104") == 0) + val |= WPA_CIPHER_WEP104; + else if (os_strcmp(start, "WEP40") == 0) + val |= WPA_CIPHER_WEP40; + else if (os_strcmp(start, "NONE") == 0) + val |= WPA_CIPHER_NONE; + else if (os_strcmp(start, "GTK_NOT_USED") == 0) + val |= WPA_CIPHER_GTK_NOT_USED; + else { + os_free(buf); + return -1; + } + + if (last) + break; + start = end + 1; + } + os_free(buf); + + return val; +} + + +int wpa_write_ciphers(char *start, char *end, int ciphers, const char *delim) +{ + char *pos = start; + int ret; + + if (ciphers & WPA_CIPHER_CCMP_256) { + ret = os_snprintf(pos, end - pos, "%sCCMP-256", + pos == start ? "" : delim); + if (os_snprintf_error(end - pos, ret)) + return -1; + pos += ret; + } + if (ciphers & WPA_CIPHER_GCMP_256) { + ret = os_snprintf(pos, end - pos, "%sGCMP-256", + pos == start ? "" : delim); + if (os_snprintf_error(end - pos, ret)) + return -1; + pos += ret; + } + if (ciphers & WPA_CIPHER_CCMP) { + ret = os_snprintf(pos, end - pos, "%sCCMP", + pos == start ? "" : delim); + if (os_snprintf_error(end - pos, ret)) + return -1; + pos += ret; + } + if (ciphers & WPA_CIPHER_GCMP) { + ret = os_snprintf(pos, end - pos, "%sGCMP", + pos == start ? "" : delim); + if (os_snprintf_error(end - pos, ret)) + return -1; + pos += ret; + } + if (ciphers & WPA_CIPHER_TKIP) { + ret = os_snprintf(pos, end - pos, "%sTKIP", + pos == start ? "" : delim); + if (os_snprintf_error(end - pos, ret)) + return -1; + pos += ret; + } + if (ciphers & WPA_CIPHER_NONE) { + ret = os_snprintf(pos, end - pos, "%sNONE", + pos == start ? "" : delim); + if (os_snprintf_error(end - pos, ret)) + return -1; + pos += ret; + } + + return pos - start; +} + + +int wpa_select_ap_group_cipher(int wpa, int wpa_pairwise, int rsn_pairwise) +{ + int pairwise = 0; + + /* Select group cipher based on the enabled pairwise cipher suites */ + if (wpa & 1) + pairwise |= wpa_pairwise; + if (wpa & 2) + pairwise |= rsn_pairwise; + + if (pairwise & WPA_CIPHER_TKIP) + return WPA_CIPHER_TKIP; + if ((pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP)) == WPA_CIPHER_GCMP) + return WPA_CIPHER_GCMP; + if ((pairwise & (WPA_CIPHER_GCMP_256 | WPA_CIPHER_CCMP | + WPA_CIPHER_GCMP)) == WPA_CIPHER_GCMP_256) + return WPA_CIPHER_GCMP_256; + if ((pairwise & (WPA_CIPHER_CCMP_256 | WPA_CIPHER_CCMP | + WPA_CIPHER_GCMP)) == WPA_CIPHER_CCMP_256) + return WPA_CIPHER_CCMP_256; + return WPA_CIPHER_CCMP; +} diff --git a/beken_os/beken378/func/hostapd-2.5/src/common/wpa_common.h b/beken_os/beken378/func/hostapd-2.5/src/common/wpa_common.h new file mode 100755 index 0000000..0e73d29 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/common/wpa_common.h @@ -0,0 +1,444 @@ +/* + * WPA definitions shared between hostapd and wpa_supplicant + * Copyright (c) 2002-2015, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef WPA_COMMON_H +#define WPA_COMMON_H + +#include "common.h" + +/* IEEE 802.11i */ +#define PMKID_LEN 16 +#define PMK_LEN 32 +#define WPA_REPLAY_COUNTER_LEN 8 +#define WPA_NONCE_LEN 32 +#define WPA_KEY_RSC_LEN 8 +#define WPA_GMK_LEN 32 +#define WPA_GTK_MAX_LEN 32 + +#define WPA_ALLOWED_PAIRWISE_CIPHERS \ +(WPA_CIPHER_CCMP | WPA_CIPHER_GCMP | WPA_CIPHER_TKIP | WPA_CIPHER_NONE | \ +WPA_CIPHER_GCMP_256 | WPA_CIPHER_CCMP_256) +#define WPA_ALLOWED_GROUP_CIPHERS \ +(WPA_CIPHER_CCMP | WPA_CIPHER_GCMP | WPA_CIPHER_TKIP | \ +WPA_CIPHER_GCMP_256 | WPA_CIPHER_CCMP_256 | \ +WPA_CIPHER_GTK_NOT_USED) + +#define WPA_SELECTOR_LEN 4 +#define WPA_VERSION 1 +#define RSN_SELECTOR_LEN 4 +#define RSN_VERSION 1 + +#define RSN_SELECTOR(a, b, c, d) \ + ((((u32) (a)) << 24) | (((u32) (b)) << 16) | (((u32) (c)) << 8) | \ + (u32) (d)) + +#define WPA_AUTH_KEY_MGMT_NONE RSN_SELECTOR(0x00, 0x50, 0xf2, 0) +#define WPA_AUTH_KEY_MGMT_UNSPEC_802_1X RSN_SELECTOR(0x00, 0x50, 0xf2, 1) +#define WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X RSN_SELECTOR(0x00, 0x50, 0xf2, 2) +#define WPA_AUTH_KEY_MGMT_CCKM RSN_SELECTOR(0x00, 0x40, 0x96, 0) +#define WPA_CIPHER_SUITE_NONE RSN_SELECTOR(0x00, 0x50, 0xf2, 0) +#define WPA_CIPHER_SUITE_TKIP RSN_SELECTOR(0x00, 0x50, 0xf2, 2) +#define WPA_CIPHER_SUITE_CCMP RSN_SELECTOR(0x00, 0x50, 0xf2, 4) + + +#define RSN_AUTH_KEY_MGMT_UNSPEC_802_1X RSN_SELECTOR(0x00, 0x0f, 0xac, 1) +#define RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X RSN_SELECTOR(0x00, 0x0f, 0xac, 2) +#ifdef CONFIG_IEEE80211R +#define RSN_AUTH_KEY_MGMT_FT_802_1X RSN_SELECTOR(0x00, 0x0f, 0xac, 3) +#define RSN_AUTH_KEY_MGMT_FT_PSK RSN_SELECTOR(0x00, 0x0f, 0xac, 4) +#endif /* CONFIG_IEEE80211R */ +#define RSN_AUTH_KEY_MGMT_802_1X_SHA256 RSN_SELECTOR(0x00, 0x0f, 0xac, 5) +#define RSN_AUTH_KEY_MGMT_PSK_SHA256 RSN_SELECTOR(0x00, 0x0f, 0xac, 6) +#define RSN_AUTH_KEY_MGMT_TPK_HANDSHAKE RSN_SELECTOR(0x00, 0x0f, 0xac, 7) +#define RSN_AUTH_KEY_MGMT_SAE RSN_SELECTOR(0x00, 0x0f, 0xac, 8) +#define RSN_AUTH_KEY_MGMT_FT_SAE RSN_SELECTOR(0x00, 0x0f, 0xac, 9) +#define RSN_AUTH_KEY_MGMT_802_1X_SUITE_B RSN_SELECTOR(0x00, 0x0f, 0xac, 11) +#define RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192 RSN_SELECTOR(0x00, 0x0f, 0xac, 12) +#define RSN_AUTH_KEY_MGMT_FT_802_1X_SUITE_B_192 \ +RSN_SELECTOR(0x00, 0x0f, 0xac, 13) +#define RSN_AUTH_KEY_MGMT_CCKM RSN_SELECTOR(0x00, 0x40, 0x96, 0x00) +#define RSN_AUTH_KEY_MGMT_OSEN RSN_SELECTOR(0x50, 0x6f, 0x9a, 0x01) + +#define RSN_CIPHER_SUITE_NONE RSN_SELECTOR(0x00, 0x0f, 0xac, 0) +#define RSN_CIPHER_SUITE_TKIP RSN_SELECTOR(0x00, 0x0f, 0xac, 2) +#if 0 +#define RSN_CIPHER_SUITE_WRAP RSN_SELECTOR(0x00, 0x0f, 0xac, 3) +#endif +#define RSN_CIPHER_SUITE_CCMP RSN_SELECTOR(0x00, 0x0f, 0xac, 4) +#define RSN_CIPHER_SUITE_AES_128_CMAC RSN_SELECTOR(0x00, 0x0f, 0xac, 6) +#define RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED RSN_SELECTOR(0x00, 0x0f, 0xac, 7) +#define RSN_CIPHER_SUITE_GCMP RSN_SELECTOR(0x00, 0x0f, 0xac, 8) +#define RSN_CIPHER_SUITE_GCMP_256 RSN_SELECTOR(0x00, 0x0f, 0xac, 9) +#define RSN_CIPHER_SUITE_CCMP_256 RSN_SELECTOR(0x00, 0x0f, 0xac, 10) +#define RSN_CIPHER_SUITE_BIP_GMAC_128 RSN_SELECTOR(0x00, 0x0f, 0xac, 11) +#define RSN_CIPHER_SUITE_BIP_GMAC_256 RSN_SELECTOR(0x00, 0x0f, 0xac, 12) +#define RSN_CIPHER_SUITE_BIP_CMAC_256 RSN_SELECTOR(0x00, 0x0f, 0xac, 13) + +/* EAPOL-Key Key Data Encapsulation + * GroupKey and PeerKey require encryption, otherwise, encryption is optional. + */ +#define RSN_KEY_DATA_GROUPKEY RSN_SELECTOR(0x00, 0x0f, 0xac, 1) +#if 0 +#define RSN_KEY_DATA_STAKEY RSN_SELECTOR(0x00, 0x0f, 0xac, 2) +#endif +#define RSN_KEY_DATA_MAC_ADDR RSN_SELECTOR(0x00, 0x0f, 0xac, 3) +#define RSN_KEY_DATA_PMKID RSN_SELECTOR(0x00, 0x0f, 0xac, 4) +#ifdef CONFIG_PEERKEY +#define RSN_KEY_DATA_SMK RSN_SELECTOR(0x00, 0x0f, 0xac, 5) +#define RSN_KEY_DATA_NONCE RSN_SELECTOR(0x00, 0x0f, 0xac, 6) +#define RSN_KEY_DATA_LIFETIME RSN_SELECTOR(0x00, 0x0f, 0xac, 7) +#define RSN_KEY_DATA_ERROR RSN_SELECTOR(0x00, 0x0f, 0xac, 8) +#endif /* CONFIG_PEERKEY */ +#ifdef CONFIG_IEEE80211W +#define RSN_KEY_DATA_IGTK RSN_SELECTOR(0x00, 0x0f, 0xac, 9) +#endif /* CONFIG_IEEE80211W */ +#define RSN_KEY_DATA_KEYID RSN_SELECTOR(0x00, 0x0f, 0xac, 10) +#define RSN_KEY_DATA_MULTIBAND_GTK RSN_SELECTOR(0x00, 0x0f, 0xac, 11) +#define RSN_KEY_DATA_MULTIBAND_KEYID RSN_SELECTOR(0x00, 0x0f, 0xac, 12) + +#define WFA_KEY_DATA_IP_ADDR_REQ RSN_SELECTOR(0x50, 0x6f, 0x9a, 4) +#define WFA_KEY_DATA_IP_ADDR_ALLOC RSN_SELECTOR(0x50, 0x6f, 0x9a, 5) + +#define WPA_OUI_TYPE RSN_SELECTOR(0x00, 0x50, 0xf2, 1) + +#define RSN_SELECTOR_PUT(a, val) WPA_PUT_BE32((u8 *) (a), (val)) +#define RSN_SELECTOR_GET(a) WPA_GET_BE32((const u8 *) (a)) + +#define RSN_NUM_REPLAY_COUNTERS_1 0 +#define RSN_NUM_REPLAY_COUNTERS_2 1 +#define RSN_NUM_REPLAY_COUNTERS_4 2 +#define RSN_NUM_REPLAY_COUNTERS_16 3 + + +#ifdef _MSC_VER +#pragma pack(push, 1) +#endif /* _MSC_VER */ + +#ifdef CONFIG_IEEE80211W +#define WPA_IGTK_LEN 16 +#define WPA_IGTK_MAX_LEN 32 +#endif /* CONFIG_IEEE80211W */ + + +/* IEEE 802.11, 7.3.2.25.3 RSN Capabilities */ +#define WPA_CAPABILITY_PREAUTH BIT(0) +#define WPA_CAPABILITY_NO_PAIRWISE BIT(1) +/* B2-B3: PTKSA Replay Counter */ +/* B4-B5: GTKSA Replay Counter */ +#define WPA_CAPABILITY_MFPR BIT(6) +#define WPA_CAPABILITY_MFPC BIT(7) +/* B8: Reserved */ +#define WPA_CAPABILITY_PEERKEY_ENABLED BIT(9) +#define WPA_CAPABILITY_SPP_A_MSDU_CAPABLE BIT(10) +#define WPA_CAPABILITY_SPP_A_MSDU_REQUIRED BIT(11) +#define WPA_CAPABILITY_PBAC BIT(12) +#define WPA_CAPABILITY_EXT_KEY_ID_FOR_UNICAST BIT(13) +/* B14-B15: Reserved */ + + +/* IEEE 802.11r */ +#define MOBILITY_DOMAIN_ID_LEN 2 +#define FT_R0KH_ID_MAX_LEN 48 +#define FT_R1KH_ID_LEN 6 +#define WPA_PMK_NAME_LEN 16 + + +/* IEEE 802.11, 8.5.2 EAPOL-Key frames */ +#define WPA_KEY_INFO_TYPE_MASK ((u16) (BIT(0) | BIT(1) | BIT(2))) +#define WPA_KEY_INFO_TYPE_AKM_DEFINED 0 +#define WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 BIT(0) +#define WPA_KEY_INFO_TYPE_HMAC_SHA1_AES BIT(1) +#define WPA_KEY_INFO_TYPE_AES_128_CMAC 3 +#define WPA_KEY_INFO_KEY_TYPE BIT(3) /* 1 = Pairwise, 0 = Group key */ +/* bit4..5 is used in WPA, but is reserved in IEEE 802.11i/RSN */ +#define WPA_KEY_INFO_KEY_INDEX_MASK (BIT(4) | BIT(5)) +#define WPA_KEY_INFO_KEY_INDEX_SHIFT 4 +#define WPA_KEY_INFO_INSTALL BIT(6) /* pairwise */ +#define WPA_KEY_INFO_TXRX BIT(6) /* group */ +#define WPA_KEY_INFO_ACK BIT(7) +#define WPA_KEY_INFO_MIC BIT(8) +#define WPA_KEY_INFO_SECURE BIT(9) +#define WPA_KEY_INFO_ERROR BIT(10) +#define WPA_KEY_INFO_REQUEST BIT(11) +#define WPA_KEY_INFO_ENCR_KEY_DATA BIT(12) /* IEEE 802.11i/RSN only */ +#define WPA_KEY_INFO_SMK_MESSAGE BIT(13) + + +STRUCT_PACKED struct wpa_eapol_key { + u8 type; + /* Note: key_info, key_length, and key_data_length are unaligned */ + u8 key_info[2]; /* big endian */ + u8 key_length[2]; /* big endian */ + u8 replay_counter[WPA_REPLAY_COUNTER_LEN]; + u8 key_nonce[WPA_NONCE_LEN]; + u8 key_iv[16]; + u8 key_rsc[WPA_KEY_RSC_LEN]; + u8 key_id[8]; /* Reserved in IEEE 802.11i/RSN */ + u8 key_mic[16]; + u8 key_data_length[2]; /* big endian */ + /* followed by key_data_length bytes of key_data */ +}GCC_PACKED; + +STRUCT_PACKED struct wpa_eapol_key_192 { + u8 type; + /* Note: key_info, key_length, and key_data_length are unaligned */ + u8 key_info[2]; /* big endian */ + u8 key_length[2]; /* big endian */ + u8 replay_counter[WPA_REPLAY_COUNTER_LEN]; + u8 key_nonce[WPA_NONCE_LEN]; + u8 key_iv[16]; + u8 key_rsc[WPA_KEY_RSC_LEN]; + u8 key_id[8]; /* Reserved in IEEE 802.11i/RSN */ + u8 key_mic[24]; + u8 key_data_length[2]; /* big endian */ + /* followed by key_data_length bytes of key_data */ +}GCC_PACKED; + +#define WPA_EAPOL_KEY_MIC_MAX_LEN 24 +#define WPA_KCK_MAX_LEN 24 +#define WPA_KEK_MAX_LEN 32 +#define WPA_TK_MAX_LEN 32 + +/** + * struct wpa_ptk - WPA Pairwise Transient Key + * IEEE Std 802.11i-2004 - 8.5.1.2 Pairwise key hierarchy + */ +struct wpa_ptk { + u8 kck[WPA_KCK_MAX_LEN]; /* EAPOL-Key Key Confirmation Key (KCK) */ + u8 kek[WPA_KEK_MAX_LEN]; /* EAPOL-Key Key Encryption Key (KEK) */ + u8 tk[WPA_TK_MAX_LEN]; /* Temporal Key (TK) */ + size_t kck_len; + size_t kek_len; + size_t tk_len; + int installed; /* 1 if key has already been installed to driver */ +}; + +struct wpa_gtk { + u8 gtk[WPA_GTK_MAX_LEN]; + size_t gtk_len; +}; + +#ifdef CONFIG_IEEE80211W +struct wpa_igtk { + u8 igtk[WPA_IGTK_MAX_LEN]; + size_t igtk_len; +}; +#endif /* CONFIG_IEEE80211W */ + +/* WPA IE version 1 + * 00-50-f2:1 (OUI:OUI type) + * 0x01 0x00 (version; little endian) + * (all following fields are optional:) + * Group Suite Selector (4 octets) (default: TKIP) + * Pairwise Suite Count (2 octets, little endian) (default: 1) + * Pairwise Suite List (4 * n octets) (default: TKIP) + * Authenticated Key Management Suite Count (2 octets, little endian) + * (default: 1) + * Authenticated Key Management Suite List (4 * n octets) + * (default: unspec 802.1X) + * WPA Capabilities (2 octets, little endian) (default: 0) + */ + +STRUCT_PACKED struct wpa_ie_hdr { + u8 elem_id; + u8 len; + u8 oui[4]; /* 24-bit OUI followed by 8-bit OUI type */ + u8 version[2]; /* little endian */ +}GCC_PACKED; + + +/* 1/4: PMKID + * 2/4: RSN IE + * 3/4: one or two RSN IEs + GTK IE (encrypted) + * 4/4: empty + * 1/2: GTK IE (encrypted) + * 2/2: empty + */ + +/* RSN IE version 1 + * 0x01 0x00 (version; little endian) + * (all following fields are optional:) + * Group Suite Selector (4 octets) (default: CCMP) + * Pairwise Suite Count (2 octets, little endian) (default: 1) + * Pairwise Suite List (4 * n octets) (default: CCMP) + * Authenticated Key Management Suite Count (2 octets, little endian) + * (default: 1) + * Authenticated Key Management Suite List (4 * n octets) + * (default: unspec 802.1X) + * RSN Capabilities (2 octets, little endian) (default: 0) + * PMKID Count (2 octets) (default: 0) + * PMKID List (16 * n octets) + * Management Group Cipher Suite (4 octets) (default: AES-128-CMAC) + */ + +STRUCT_PACKED struct rsn_ie_hdr { + u8 elem_id; /* WLAN_EID_RSN */ + u8 len; + u8 version[2]; /* little endian */ +}GCC_PACKED; + + +#ifdef CONFIG_PEERKEY +enum { + STK_MUI_4WAY_STA_AP = 1, + STK_MUI_4WAY_STAT_STA = 2, + STK_MUI_GTK = 3, + STK_MUI_SMK = 4 +}; + +enum { + STK_ERR_STA_NR = 1, + STK_ERR_STA_NRSN = 2, + STK_ERR_CPHR_NS = 3, + STK_ERR_NO_STSL = 4 +}; +#endif /* CONFIG_PEERKEY */ + +STRUCT_PACKED struct rsn_error_kde { + be16 mui; + be16 error_type; +}GCC_PACKED; + +#ifdef CONFIG_IEEE80211W +#define WPA_IGTK_KDE_PREFIX_LEN (2 + 6) +STRUCT_PACKED struct wpa_igtk_kde { + u8 keyid[2]; + u8 pn[6]; + u8 igtk[WPA_IGTK_MAX_LEN]; +}GCC_PACKED; +#endif /* CONFIG_IEEE80211W */ + +struct rsn_mdie { +STRUCT_PACKED u8 mobility_domain[MOBILITY_DOMAIN_ID_LEN]; + u8 ft_capab; +}; + +#define RSN_FT_CAPAB_FT_OVER_DS BIT(0) +#define RSN_FT_CAPAB_FT_RESOURCE_REQ_SUPP BIT(1) + +STRUCT_PACKED struct rsn_ftie { + u8 mic_control[2]; + u8 mic[16]; + u8 anonce[WPA_NONCE_LEN]; + u8 snonce[WPA_NONCE_LEN]; + /* followed by optional parameters */ +}GCC_PACKED; + +#define FTIE_SUBELEM_R1KH_ID 1 +#define FTIE_SUBELEM_GTK 2 +#define FTIE_SUBELEM_R0KH_ID 3 +#define FTIE_SUBELEM_IGTK 4 + +STRUCT_PACKED struct rsn_rdie { + u8 id; + u8 descr_count; + le16 status_code; +}GCC_PACKED; + + +#ifdef _MSC_VER +#pragma pack(pop) +#endif /* _MSC_VER */ + + +int wpa_eapol_key_mic(const u8 *key, size_t key_len, int akmp, int ver, + const u8 *buf, size_t len, u8 *mic); +int wpa_pmk_to_ptk(const u8 *pmk, size_t pmk_len, const char *label, + const u8 *addr1, const u8 *addr2, + const u8 *nonce1, const u8 *nonce2, + struct wpa_ptk *ptk, int akmp, int cipher); + +#ifdef CONFIG_IEEE80211R +int wpa_ft_mic(const u8 *kck, size_t kck_len, const u8 *sta_addr, + const u8 *ap_addr, u8 transaction_seqnum, + const u8 *mdie, size_t mdie_len, + const u8 *ftie, size_t ftie_len, + const u8 *rsnie, size_t rsnie_len, + const u8 *ric, size_t ric_len, u8 *mic); +void wpa_derive_pmk_r0(const u8 *xxkey, size_t xxkey_len, + const u8 *ssid, size_t ssid_len, + const u8 *mdid, const u8 *r0kh_id, size_t r0kh_id_len, + const u8 *s0kh_id, u8 *pmk_r0, u8 *pmk_r0_name); +void wpa_derive_pmk_r1_name(const u8 *pmk_r0_name, const u8 *r1kh_id, + const u8 *s1kh_id, u8 *pmk_r1_name); +void wpa_derive_pmk_r1(const u8 *pmk_r0, const u8 *pmk_r0_name, + const u8 *r1kh_id, const u8 *s1kh_id, + u8 *pmk_r1, u8 *pmk_r1_name); +int wpa_pmk_r1_to_ptk(const u8 *pmk_r1, const u8 *snonce, const u8 *anonce, + const u8 *sta_addr, const u8 *bssid, + const u8 *pmk_r1_name, + struct wpa_ptk *ptk, u8 *ptk_name, int akmp, int cipher); +#endif /* CONFIG_IEEE80211R */ + +struct wpa_ie_data { + int proto; + int pairwise_cipher; + int group_cipher; + int key_mgmt; + int capabilities; + size_t num_pmkid; + const u8 *pmkid; + int mgmt_group_cipher; +}; + + +int wpa_parse_wpa_ie_rsn(const u8 *rsn_ie, size_t rsn_ie_len, + struct wpa_ie_data *data); +int wpa_parse_wpa_ie_wpa(const u8 *wpa_ie, size_t wpa_ie_len, + struct wpa_ie_data *data); + +void rsn_pmkid(const u8 *pmk, size_t pmk_len, const u8 *aa, const u8 *spa, + u8 *pmkid, int use_sha256); +const char * wpa_cipher_txt(int cipher); +const char * wpa_key_mgmt_txt(int key_mgmt, int proto); +u32 wpa_akm_to_suite(int akm); +int wpa_compare_rsn_ie(int ft_initial_assoc, + const u8 *ie1, size_t ie1len, + const u8 *ie2, size_t ie2len); +int wpa_insert_pmkid(u8 *ies, size_t ies_len, const u8 *pmkid); + +struct wpa_ft_ies { + const u8 *mdie; + size_t mdie_len; + const u8 *ftie; + size_t ftie_len; + const u8 *r1kh_id; + const u8 *gtk; + size_t gtk_len; + const u8 *r0kh_id; + size_t r0kh_id_len; + const u8 *rsn; + size_t rsn_len; + const u8 *rsn_pmkid; + const u8 *tie; + size_t tie_len; + const u8 *igtk; + size_t igtk_len; + const u8 *ric; + size_t ric_len; +}; + +int wpa_ft_parse_ies(const u8 *ies, size_t ies_len, struct wpa_ft_ies *parse); + +int wpa_cipher_key_len(int cipher); +int wpa_cipher_rsc_len(int cipher); +int wpa_cipher_to_alg(int cipher); +int wpa_cipher_valid_group(int cipher); +int wpa_cipher_valid_pairwise(int cipher); +int wpa_cipher_valid_mgmt_group(int cipher); +u32 wpa_cipher_to_suite(int proto, int cipher); +int rsn_cipher_put_suites(u8 *pos, int ciphers); +int wpa_cipher_put_suites(u8 *pos, int ciphers); +int wpa_pick_pairwise_cipher(int ciphers, int none_allowed); +int wpa_pick_group_cipher(int ciphers); +int wpa_parse_cipher(const char *value); +int wpa_write_ciphers(char *start, char *end, int ciphers, const char *delim); +int wpa_select_ap_group_cipher(int wpa, int wpa_pairwise, int rsn_pairwise); +unsigned int wpa_mic_len(int akmp); + +#endif /* WPA_COMMON_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/common/wpa_ctrl.h b/beken_os/beken378/func/hostapd-2.5/src/common/wpa_ctrl.h new file mode 100755 index 0000000..3de4682 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/common/wpa_ctrl.h @@ -0,0 +1,472 @@ +/* + * wpa_supplicant/hostapd control interface library + * Copyright (c) 2004-2006, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef WPA_CTRL_H +#define WPA_CTRL_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* wpa_supplicant control interface - fixed message prefixes */ + +/** Interactive request for identity/password/pin */ +#define WPA_CTRL_REQ "CTRL-REQ-" + +/** Response to identity/password/pin request */ +#define WPA_CTRL_RSP "CTRL-RSP-" + +/* Event messages with fixed prefix */ +/** Authentication completed successfully and data connection enabled */ +#define WPA_EVENT_CONNECTED "CTRL-EVENT-CONNECTED " +/** Disconnected, data connection is not available */ +#define WPA_EVENT_DISCONNECTED "CTRL-EVENT-DISCONNECTED " +/** Association rejected during connection attempt */ +#define WPA_EVENT_ASSOC_REJECT "CTRL-EVENT-ASSOC-REJECT " +/** Authentication rejected during connection attempt */ +#define WPA_EVENT_AUTH_REJECT "CTRL-EVENT-AUTH-REJECT " +/** wpa_supplicant is exiting */ +#define WPA_EVENT_TERMINATING "CTRL-EVENT-TERMINATING " +/** Password change was completed successfully */ +#define WPA_EVENT_PASSWORD_CHANGED "CTRL-EVENT-PASSWORD-CHANGED " +/** EAP-Request/Notification received */ +#define WPA_EVENT_EAP_NOTIFICATION "CTRL-EVENT-EAP-NOTIFICATION " +/** EAP authentication started (EAP-Request/Identity received) */ +#define WPA_EVENT_EAP_STARTED "CTRL-EVENT-EAP-STARTED " +/** EAP method proposed by the server */ +#define WPA_EVENT_EAP_PROPOSED_METHOD "CTRL-EVENT-EAP-PROPOSED-METHOD " +/** EAP method selected */ +#define WPA_EVENT_EAP_METHOD "CTRL-EVENT-EAP-METHOD " +/** EAP peer certificate from TLS */ +#define WPA_EVENT_EAP_PEER_CERT "CTRL-EVENT-EAP-PEER-CERT " +/** EAP peer certificate alternative subject name component from TLS */ +#define WPA_EVENT_EAP_PEER_ALT "CTRL-EVENT-EAP-PEER-ALT " +/** EAP TLS certificate chain validation error */ +#define WPA_EVENT_EAP_TLS_CERT_ERROR "CTRL-EVENT-EAP-TLS-CERT-ERROR " +/** EAP status */ +#define WPA_EVENT_EAP_STATUS "CTRL-EVENT-EAP-STATUS " +/** EAP authentication completed successfully */ +#define WPA_EVENT_EAP_SUCCESS "CTRL-EVENT-EAP-SUCCESS " +/** EAP authentication failed (EAP-Failure received) */ +#define WPA_EVENT_EAP_FAILURE "CTRL-EVENT-EAP-FAILURE " +/** Network block temporarily disabled (e.g., due to authentication failure) */ +#define WPA_EVENT_TEMP_DISABLED "CTRL-EVENT-SSID-TEMP-DISABLED " +/** Temporarily disabled network block re-enabled */ +#define WPA_EVENT_REENABLED "CTRL-EVENT-SSID-REENABLED " +/** New scan started */ +#define WPA_EVENT_SCAN_STARTED "CTRL-EVENT-SCAN-STARTED " +/** New scan results available */ +#define WPA_EVENT_SCAN_RESULTS "CTRL-EVENT-SCAN-RESULTS " +/** Scan command failed */ +#define WPA_EVENT_SCAN_FAILED "CTRL-EVENT-SCAN-FAILED " +/** wpa_supplicant state change */ +#define WPA_EVENT_STATE_CHANGE "CTRL-EVENT-STATE-CHANGE " +/** A new BSS entry was added (followed by BSS entry id and BSSID) */ +#define WPA_EVENT_BSS_ADDED "CTRL-EVENT-BSS-ADDED " +/** A BSS entry was removed (followed by BSS entry id and BSSID) */ +#define WPA_EVENT_BSS_REMOVED "CTRL-EVENT-BSS-REMOVED " +/** No suitable network was found */ +#define WPA_EVENT_NETWORK_NOT_FOUND "CTRL-EVENT-NETWORK-NOT-FOUND " +/** Change in the signal level was reported by the driver */ +#define WPA_EVENT_SIGNAL_CHANGE "CTRL-EVENT-SIGNAL-CHANGE " +/** Regulatory domain channel */ +#define WPA_EVENT_REGDOM_CHANGE "CTRL-EVENT-REGDOM-CHANGE " + +/** RSN IBSS 4-way handshakes completed with specified peer */ +#define IBSS_RSN_COMPLETED "IBSS-RSN-COMPLETED " + +/** Notification of frequency conflict due to a concurrent operation. + * + * The indicated network is disabled and needs to be re-enabled before it can + * be used again. + */ +#define WPA_EVENT_FREQ_CONFLICT "CTRL-EVENT-FREQ-CONFLICT " +/** Frequency ranges that the driver recommends to avoid */ +#define WPA_EVENT_AVOID_FREQ "CTRL-EVENT-AVOID-FREQ " +/** WPS overlap detected in PBC mode */ +#define WPS_EVENT_OVERLAP "WPS-OVERLAP-DETECTED " +/** Available WPS AP with active PBC found in scan results */ +#define WPS_EVENT_AP_AVAILABLE_PBC "WPS-AP-AVAILABLE-PBC " +/** Available WPS AP with our address as authorized in scan results */ +#define WPS_EVENT_AP_AVAILABLE_AUTH "WPS-AP-AVAILABLE-AUTH " +/** Available WPS AP with recently selected PIN registrar found in scan results + */ +#define WPS_EVENT_AP_AVAILABLE_PIN "WPS-AP-AVAILABLE-PIN " +/** Available WPS AP found in scan results */ +#define WPS_EVENT_AP_AVAILABLE "WPS-AP-AVAILABLE " +/** A new credential received */ +#define WPS_EVENT_CRED_RECEIVED "WPS-CRED-RECEIVED " +/** M2D received */ +#define WPS_EVENT_M2D "WPS-M2D " +/** WPS registration failed after M2/M2D */ +#define WPS_EVENT_FAIL "WPS-FAIL " +/** WPS registration completed successfully */ +#define WPS_EVENT_SUCCESS "WPS-SUCCESS " +/** WPS enrollment attempt timed out and was terminated */ +#define WPS_EVENT_TIMEOUT "WPS-TIMEOUT " +/* PBC mode was activated */ +#define WPS_EVENT_ACTIVE "WPS-PBC-ACTIVE " +/* PBC mode was disabled */ +#define WPS_EVENT_DISABLE "WPS-PBC-DISABLE " + +#define WPS_EVENT_ENROLLEE_SEEN "WPS-ENROLLEE-SEEN " + +#define WPS_EVENT_OPEN_NETWORK "WPS-OPEN-NETWORK " + +/* WPS ER events */ +#define WPS_EVENT_ER_AP_ADD "WPS-ER-AP-ADD " +#define WPS_EVENT_ER_AP_REMOVE "WPS-ER-AP-REMOVE " +#define WPS_EVENT_ER_ENROLLEE_ADD "WPS-ER-ENROLLEE-ADD " +#define WPS_EVENT_ER_ENROLLEE_REMOVE "WPS-ER-ENROLLEE-REMOVE " +#define WPS_EVENT_ER_AP_SETTINGS "WPS-ER-AP-SETTINGS " +#define WPS_EVENT_ER_SET_SEL_REG "WPS-ER-AP-SET-SEL-REG " + +/* MESH events */ +#define MESH_GROUP_STARTED "MESH-GROUP-STARTED " +#define MESH_GROUP_REMOVED "MESH-GROUP-REMOVED " +#define MESH_PEER_CONNECTED "MESH-PEER-CONNECTED " +#define MESH_PEER_DISCONNECTED "MESH-PEER-DISCONNECTED " +/** Mesh SAE authentication failure. Wrong password suspected. */ +#define MESH_SAE_AUTH_FAILURE "MESH-SAE-AUTH-FAILURE " +#define MESH_SAE_AUTH_BLOCKED "MESH-SAE-AUTH-BLOCKED " + +/* WMM AC events */ +#define WMM_AC_EVENT_TSPEC_ADDED "TSPEC-ADDED " +#define WMM_AC_EVENT_TSPEC_REMOVED "TSPEC-REMOVED " +#define WMM_AC_EVENT_TSPEC_REQ_FAILED "TSPEC-REQ-FAILED " + +/** P2P device found */ +#define P2P_EVENT_DEVICE_FOUND "P2P-DEVICE-FOUND " + +/** P2P device lost */ +#define P2P_EVENT_DEVICE_LOST "P2P-DEVICE-LOST " + +/** A P2P device requested GO negotiation, but we were not ready to start the + * negotiation */ +#define P2P_EVENT_GO_NEG_REQUEST "P2P-GO-NEG-REQUEST " +#define P2P_EVENT_GO_NEG_SUCCESS "P2P-GO-NEG-SUCCESS " +#define P2P_EVENT_GO_NEG_FAILURE "P2P-GO-NEG-FAILURE " +#define P2P_EVENT_GROUP_FORMATION_SUCCESS "P2P-GROUP-FORMATION-SUCCESS " +#define P2P_EVENT_GROUP_FORMATION_FAILURE "P2P-GROUP-FORMATION-FAILURE " +#define P2P_EVENT_GROUP_STARTED "P2P-GROUP-STARTED " +#define P2P_EVENT_GROUP_REMOVED "P2P-GROUP-REMOVED " +#define P2P_EVENT_CROSS_CONNECT_ENABLE "P2P-CROSS-CONNECT-ENABLE " +#define P2P_EVENT_CROSS_CONNECT_DISABLE "P2P-CROSS-CONNECT-DISABLE " +/* parameters: */ +#define P2P_EVENT_PROV_DISC_SHOW_PIN "P2P-PROV-DISC-SHOW-PIN " +/* parameters: */ +#define P2P_EVENT_PROV_DISC_ENTER_PIN "P2P-PROV-DISC-ENTER-PIN " +/* parameters: */ +#define P2P_EVENT_PROV_DISC_PBC_REQ "P2P-PROV-DISC-PBC-REQ " +/* parameters: */ +#define P2P_EVENT_PROV_DISC_PBC_RESP "P2P-PROV-DISC-PBC-RESP " +/* parameters: */ +#define P2P_EVENT_PROV_DISC_FAILURE "P2P-PROV-DISC-FAILURE" +/* parameters: */ +#define P2P_EVENT_SERV_DISC_REQ "P2P-SERV-DISC-REQ " +/* parameters: */ +#define P2P_EVENT_SERV_DISC_RESP "P2P-SERV-DISC-RESP " +#define P2P_EVENT_SERV_ASP_RESP "P2P-SERV-ASP-RESP " +#define P2P_EVENT_INVITATION_RECEIVED "P2P-INVITATION-RECEIVED " +#define P2P_EVENT_INVITATION_RESULT "P2P-INVITATION-RESULT " +#define P2P_EVENT_FIND_STOPPED "P2P-FIND-STOPPED " +#define P2P_EVENT_PERSISTENT_PSK_FAIL "P2P-PERSISTENT-PSK-FAIL id=" +#define P2P_EVENT_PRESENCE_RESPONSE "P2P-PRESENCE-RESPONSE " +#define P2P_EVENT_NFC_BOTH_GO "P2P-NFC-BOTH-GO " +#define P2P_EVENT_NFC_PEER_CLIENT "P2P-NFC-PEER-CLIENT " +#define P2P_EVENT_NFC_WHILE_CLIENT "P2P-NFC-WHILE-CLIENT " +#define P2P_EVENT_FALLBACK_TO_GO_NEG "P2P-FALLBACK-TO-GO-NEG " +#define P2P_EVENT_FALLBACK_TO_GO_NEG_ENABLED "P2P-FALLBACK-TO-GO-NEG-ENABLED " + +/* parameters: */ +#define ESS_DISASSOC_IMMINENT "ESS-DISASSOC-IMMINENT " +#define P2P_EVENT_REMOVE_AND_REFORM_GROUP "P2P-REMOVE-AND-REFORM-GROUP " + +#define P2P_EVENT_P2PS_PROVISION_START "P2PS-PROV-START " +#define P2P_EVENT_P2PS_PROVISION_DONE "P2PS-PROV-DONE " + +#define INTERWORKING_AP "INTERWORKING-AP " +#define INTERWORKING_BLACKLISTED "INTERWORKING-BLACKLISTED " +#define INTERWORKING_NO_MATCH "INTERWORKING-NO-MATCH " +#define INTERWORKING_ALREADY_CONNECTED "INTERWORKING-ALREADY-CONNECTED " +#define INTERWORKING_SELECTED "INTERWORKING-SELECTED " + +/* Credential block added; parameters: */ +#define CRED_ADDED "CRED-ADDED " +/* Credential block modified; parameters: */ +#define CRED_MODIFIED "CRED-MODIFIED " +/* Credential block removed; parameters: */ +#define CRED_REMOVED "CRED-REMOVED " + +#define GAS_RESPONSE_INFO "GAS-RESPONSE-INFO " +/* parameters: */ +#define GAS_QUERY_START "GAS-QUERY-START " +/* parameters: */ +#define GAS_QUERY_DONE "GAS-QUERY-DONE " + +/* parameters: */ +#define ANQP_QUERY_DONE "ANQP-QUERY-DONE " + +#define HS20_SUBSCRIPTION_REMEDIATION "HS20-SUBSCRIPTION-REMEDIATION " +#define HS20_DEAUTH_IMMINENT_NOTICE "HS20-DEAUTH-IMMINENT-NOTICE " + +#define EXT_RADIO_WORK_START "EXT-RADIO-WORK-START " +#define EXT_RADIO_WORK_TIMEOUT "EXT-RADIO-WORK-TIMEOUT " + +#define RRM_EVENT_NEIGHBOR_REP_RXED "RRM-NEIGHBOR-REP-RECEIVED " +#define RRM_EVENT_NEIGHBOR_REP_FAILED "RRM-NEIGHBOR-REP-REQUEST-FAILED " + +/* hostapd control interface - fixed message prefixes */ +#define WPS_EVENT_PIN_NEEDED "WPS-PIN-NEEDED " +#define WPS_EVENT_NEW_AP_SETTINGS "WPS-NEW-AP-SETTINGS " +#define WPS_EVENT_REG_SUCCESS "WPS-REG-SUCCESS " +#define WPS_EVENT_AP_SETUP_LOCKED "WPS-AP-SETUP-LOCKED " +#define WPS_EVENT_AP_SETUP_UNLOCKED "WPS-AP-SETUP-UNLOCKED " +#define WPS_EVENT_AP_PIN_ENABLED "WPS-AP-PIN-ENABLED " +#define WPS_EVENT_AP_PIN_DISABLED "WPS-AP-PIN-DISABLED " +#define AP_STA_CONNECTED "AP-STA-CONNECTED " +#define AP_STA_DISCONNECTED "AP-STA-DISCONNECTED " +#define AP_STA_POSSIBLE_PSK_MISMATCH "AP-STA-POSSIBLE-PSK-MISMATCH " + +#define AP_REJECTED_MAX_STA "AP-REJECTED-MAX-STA " +#define AP_REJECTED_BLOCKED_STA "AP-REJECTED-BLOCKED-STA " + +#define AP_EVENT_ENABLED "AP-ENABLED " +#define AP_EVENT_DISABLED "AP-DISABLED " + +#define INTERFACE_ENABLED "INTERFACE-ENABLED " +#define INTERFACE_DISABLED "INTERFACE-DISABLED " + +#define ACS_EVENT_STARTED "ACS-STARTED " +#define ACS_EVENT_COMPLETED "ACS-COMPLETED " +#define ACS_EVENT_FAILED "ACS-FAILED " + +#define DFS_EVENT_RADAR_DETECTED "DFS-RADAR-DETECTED " +#define DFS_EVENT_NEW_CHANNEL "DFS-NEW-CHANNEL " +#define DFS_EVENT_CAC_START "DFS-CAC-START " +#define DFS_EVENT_CAC_COMPLETED "DFS-CAC-COMPLETED " +#define DFS_EVENT_NOP_FINISHED "DFS-NOP-FINISHED " + +#define AP_CSA_FINISHED "AP-CSA-FINISHED " + +/* BSS Transition Management Response frame received */ +#define BSS_TM_RESP "BSS-TM-RESP " + +/* BSS command information masks */ + +#define WPA_BSS_MASK_ALL 0xFFFDFFFF +#define WPA_BSS_MASK_ID BIT(0) +#define WPA_BSS_MASK_BSSID BIT(1) +#define WPA_BSS_MASK_FREQ BIT(2) +#define WPA_BSS_MASK_BEACON_INT BIT(3) +#define WPA_BSS_MASK_CAPABILITIES BIT(4) +#define WPA_BSS_MASK_QUAL BIT(5) +#define WPA_BSS_MASK_NOISE BIT(6) +#define WPA_BSS_MASK_LEVEL BIT(7) +#define WPA_BSS_MASK_TSF BIT(8) +#define WPA_BSS_MASK_AGE BIT(9) +#define WPA_BSS_MASK_IE BIT(10) +#define WPA_BSS_MASK_FLAGS BIT(11) +#define WPA_BSS_MASK_SSID BIT(12) +#define WPA_BSS_MASK_WPS_SCAN BIT(13) +#define WPA_BSS_MASK_P2P_SCAN BIT(14) +#define WPA_BSS_MASK_INTERNETW BIT(15) +#define WPA_BSS_MASK_WIFI_DISPLAY BIT(16) +#define WPA_BSS_MASK_DELIM BIT(17) +#define WPA_BSS_MASK_MESH_SCAN BIT(18) +#define WPA_BSS_MASK_SNR BIT(19) +#define WPA_BSS_MASK_EST_THROUGHPUT BIT(20) +#define WPA_BSS_MASK_FST BIT(21) + + +/* VENDOR_ELEM_* frame id values */ +enum wpa_vendor_elem_frame { + VENDOR_ELEM_PROBE_REQ_P2P = 0, + VENDOR_ELEM_PROBE_RESP_P2P = 1, + VENDOR_ELEM_PROBE_RESP_P2P_GO = 2, + VENDOR_ELEM_BEACON_P2P_GO = 3, + VENDOR_ELEM_P2P_PD_REQ = 4, + VENDOR_ELEM_P2P_PD_RESP = 5, + VENDOR_ELEM_P2P_GO_NEG_REQ = 6, + VENDOR_ELEM_P2P_GO_NEG_RESP = 7, + VENDOR_ELEM_P2P_GO_NEG_CONF = 8, + VENDOR_ELEM_P2P_INV_REQ = 9, + VENDOR_ELEM_P2P_INV_RESP = 10, + VENDOR_ELEM_P2P_ASSOC_REQ = 11, + VENDOR_ELEM_P2P_ASSOC_RESP = 12, + VENDOR_ELEM_ASSOC_REQ = 13, + NUM_VENDOR_ELEM_FRAMES +}; + + +/* wpa_supplicant/hostapd control interface access */ + +/** + * wpa_ctrl_open - Open a control interface to wpa_supplicant/hostapd + * @ctrl_path: Path for UNIX domain sockets; ignored if UDP sockets are used. + * Returns: Pointer to abstract control interface data or %NULL on failure + * + * This function is used to open a control interface to wpa_supplicant/hostapd. + * ctrl_path is usually /var/run/wpa_supplicant or /var/run/hostapd. This path + * is configured in wpa_supplicant/hostapd and other programs using the control + * interface need to use matching path configuration. + */ +struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path); + +/** + * wpa_ctrl_open2 - Open a control interface to wpa_supplicant/hostapd + * @ctrl_path: Path for UNIX domain sockets; ignored if UDP sockets are used. + * @cli_path: Path for client UNIX domain sockets; ignored if UDP socket + * is used. + * Returns: Pointer to abstract control interface data or %NULL on failure + * + * This function is used to open a control interface to wpa_supplicant/hostapd + * when the socket path for client need to be specified explicitly. Default + * ctrl_path is usually /var/run/wpa_supplicant or /var/run/hostapd and client + * socket path is /tmp. + */ +struct wpa_ctrl * wpa_ctrl_open2(const char *ctrl_path, const char *cli_path); + + +/** + * wpa_ctrl_close - Close a control interface to wpa_supplicant/hostapd + * @ctrl: Control interface data from wpa_ctrl_open() + * + * This function is used to close a control interface. + */ +void wpa_ctrl_close(struct wpa_ctrl *ctrl); + + +/** + * wpa_ctrl_request - Send a command to wpa_supplicant/hostapd + * @ctrl: Control interface data from wpa_ctrl_open() + * @cmd: Command; usually, ASCII text, e.g., "PING" + * @cmd_len: Length of the cmd in bytes + * @reply: Buffer for the response + * @reply_len: Reply buffer length + * @msg_cb: Callback function for unsolicited messages or %NULL if not used + * Returns: 0 on success, -1 on error (send or receive failed), -2 on timeout + * + * This function is used to send commands to wpa_supplicant/hostapd. Received + * response will be written to reply and reply_len is set to the actual length + * of the reply. This function will block for up to two seconds while waiting + * for the reply. If unsolicited messages are received, the blocking time may + * be longer. + * + * msg_cb can be used to register a callback function that will be called for + * unsolicited messages received while waiting for the command response. These + * messages may be received if wpa_ctrl_request() is called at the same time as + * wpa_supplicant/hostapd is sending such a message. This can happen only if + * the program has used wpa_ctrl_attach() to register itself as a monitor for + * event messages. Alternatively to msg_cb, programs can register two control + * interface connections and use one of them for commands and the other one for + * receiving event messages, in other words, call wpa_ctrl_attach() only for + * the control interface connection that will be used for event messages. + */ +int wpa_ctrl_request(struct wpa_ctrl *ctrl, const char *cmd, size_t cmd_len, + char *reply, size_t *reply_len, + void (*msg_cb)(char *msg, size_t len)); + + +/** + * wpa_ctrl_attach - Register as an event monitor for the control interface + * @ctrl: Control interface data from wpa_ctrl_open() + * Returns: 0 on success, -1 on failure, -2 on timeout + * + * This function registers the control interface connection as a monitor for + * wpa_supplicant/hostapd events. After a success wpa_ctrl_attach() call, the + * control interface connection starts receiving event messages that can be + * read with wpa_ctrl_recv(). + */ +int wpa_ctrl_attach(struct wpa_ctrl *ctrl); + + +/** + * wpa_ctrl_detach - Unregister event monitor from the control interface + * @ctrl: Control interface data from wpa_ctrl_open() + * Returns: 0 on success, -1 on failure, -2 on timeout + * + * This function unregisters the control interface connection as a monitor for + * wpa_supplicant/hostapd events, i.e., cancels the registration done with + * wpa_ctrl_attach(). + */ +int wpa_ctrl_detach(struct wpa_ctrl *ctrl); + + +/** + * wpa_ctrl_recv - Receive a pending control interface message + * @ctrl: Control interface data from wpa_ctrl_open() + * @reply: Buffer for the message data + * @reply_len: Length of the reply buffer + * Returns: 0 on success, -1 on failure + * + * This function will receive a pending control interface message. The received + * response will be written to reply and reply_len is set to the actual length + * of the reply. + + * wpa_ctrl_recv() is only used for event messages, i.e., wpa_ctrl_attach() + * must have been used to register the control interface as an event monitor. + */ +int wpa_ctrl_recv(struct wpa_ctrl *ctrl, char *reply, size_t *reply_len); + + +/** + * wpa_ctrl_pending - Check whether there are pending event messages + * @ctrl: Control interface data from wpa_ctrl_open() + * Returns: 1 if there are pending messages, 0 if no, or -1 on error + * + * This function will check whether there are any pending control interface + * message available to be received with wpa_ctrl_recv(). wpa_ctrl_pending() is + * only used for event messages, i.e., wpa_ctrl_attach() must have been used to + * register the control interface as an event monitor. + */ +int wpa_ctrl_pending(struct wpa_ctrl *ctrl); + + +/** + * wpa_ctrl_get_fd - Get file descriptor used by the control interface + * @ctrl: Control interface data from wpa_ctrl_open() + * Returns: File descriptor used for the connection + * + * This function can be used to get the file descriptor that is used for the + * control interface connection. The returned value can be used, e.g., with + * select() while waiting for multiple events. + * + * The returned file descriptor must not be used directly for sending or + * receiving packets; instead, the library functions wpa_ctrl_request() and + * wpa_ctrl_recv() must be used for this. + */ +int wpa_ctrl_get_fd(struct wpa_ctrl *ctrl); + +#ifdef ANDROID +/** + * wpa_ctrl_cleanup() - Delete any local UNIX domain socket files that + * may be left over from clients that were previously connected to + * wpa_supplicant. This keeps these files from being orphaned in the + * event of crashes that prevented them from being removed as part + * of the normal orderly shutdown. + */ +void wpa_ctrl_cleanup(void); +#endif /* ANDROID */ + +#ifdef CONFIG_CTRL_IFACE_UDP +/* Port range for multiple wpa_supplicant instances and multiple VIFs */ +#define WPA_CTRL_IFACE_PORT 9877 +#define WPA_CTRL_IFACE_PORT_LIMIT 50 /* decremented from start */ +#define WPA_GLOBAL_CTRL_IFACE_PORT 9878 +#define WPA_GLOBAL_CTRL_IFACE_PORT_LIMIT 20 /* incremented from start */ + +char * wpa_ctrl_get_remote_ifname(struct wpa_ctrl *ctrl); +#endif /* CONFIG_CTRL_IFACE_UDP */ + + +#ifdef __cplusplus +} +#endif + +#endif /* WPA_CTRL_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/common/wpa_psk_cache.h b/beken_os/beken378/func/hostapd-2.5/src/common/wpa_psk_cache.h new file mode 100755 index 0000000..27cec9b --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/common/wpa_psk_cache.h @@ -0,0 +1,66 @@ +#ifndef __WPA_PSK_CACHE_H_ +#define __WPA_PSK_CACHE_H_ + +#include "includes.h" +#include "typedef.h" +#include "list.h" +#include "rtos_pub.h" +#include "common.h" +#include "wpa_common.h" +#include "build_config.h" +#include "../wpa_supplicant/wpa_supplicant_i.h" + +#ifdef CONFIG_WPA_PSK_CACHE + +#define WPA_PSK_ENTRIES 8 + +#define WPA_PSK_CACHE_FLAG_PENDING 0x1 +#define WPA_PSK_CACHE_FLAG_COMPLETE 0x2 + +struct wpa_psk_cache_item { +#ifdef CONFIG_WPA_PSK_CACHE_MULTI + struct dl_list node; +#endif + char *ssid; + size_t ssid_len; + char *passphrase; + u8 psk[32]; + u8 flags; +}; + +/** + * @complete, @pending are protected by @sema + */ +struct wpa_psk_cache { +#ifdef CONFIG_WPA_PSK_CACHE_MULTI + struct dl_list all; + struct dl_list pending; // calcuthread internal use +#else + struct wpa_psk_cache_item item; +#endif + beken_semaphore_t sema; +}; + +void wpa_psk_cache_init(); +int wpa_get_psk_from_cache(struct wpa_ssid *ssid); +int __wpa_get_psk_from_cache(u8 *ssid, size_t ssid_len, char *passphrase, u8 *psk, size_t psk_len); +int wpa_psk_request(u8 *ssid, size_t ssid_len, char *passphrase, u8 *psk, size_t psk_len); +void start_wpa_psk_cal_thread(); + +#else /* !CONFIG_WPA_PSK_CACHE */ +static inline void wpa_psk_cache_init(void) +{ +} + +static inline int wpa_get_psk_from_cache(struct wpa_ssid *ssid) +{ + return -1; +} + +static inline int wpa_psk_request(u8 *ssid, size_t ssid_len, char *passphrase, u8 *psk, size_t psk_len) +{ + return -1; +} + +#endif // CONFIG_WPA_PSK_CACHE +#endif // __WPA_PSK_CACHE_H_ diff --git a/beken_os/beken378/func/hostapd-2.5/src/crypto/aes-internal-dec.c b/beken_os/beken378/func/hostapd-2.5/src/crypto/aes-internal-dec.c new file mode 100755 index 0000000..720c703 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/crypto/aes-internal-dec.c @@ -0,0 +1,161 @@ +/* + * AES (Rijndael) cipher - decrypt + * + * Modifications to public domain implementation: + * - cleanup + * - use C pre-processor to make it easier to change S table access + * - added option (AES_SMALL_TABLES) for reducing code size by about 8 kB at + * cost of reduced throughput (quite small difference on Pentium 4, + * 10-25% when using -O1 or -O2 optimization) + * + * Copyright (c) 2003-2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "crypto.h" +#include "aes_i.h" + +/** + * Expand the cipher key into the decryption key schedule. + * + * @return the number of rounds for the given cipher key size. + */ +static int rijndaelKeySetupDec(u32 rk[], const u8 cipherKey[], int keyBits) +{ + int Nr, i, j; + u32 temp; + + /* expand the cipher key: */ + Nr = rijndaelKeySetupEnc(rk, cipherKey, keyBits); + if (Nr < 0) + return Nr; + /* invert the order of the round keys: */ + for (i = 0, j = 4*Nr; i < j; i += 4, j -= 4) { + temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp; + temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp; + temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp; + temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp; + } + /* apply the inverse MixColumn transform to all round keys but the + * first and the last: */ + for (i = 1; i < Nr; i++) { + rk += 4; + for (j = 0; j < 4; j++) { + rk[j] = TD0_(TE4((rk[j] >> 24) )) ^ + TD1_(TE4((rk[j] >> 16) & 0xff)) ^ + TD2_(TE4((rk[j] >> 8) & 0xff)) ^ + TD3_(TE4((rk[j] ) & 0xff)); + } + } + + return Nr; +} + +void * aes_decrypt_init(const u8 *key, size_t len) +{ + u32 *rk; + int res; + rk = os_malloc(AES_PRIV_SIZE); + if (rk == NULL) + return NULL; + res = rijndaelKeySetupDec(rk, key, len * 8); + if (res < 0) { + os_free(rk); + return NULL; + } + rk[AES_PRIV_NR_POS] = res; + return rk; +} + +static void rijndaelDecrypt(const u32 rk[/*44*/], int Nr, const u8 ct[16], + u8 pt[16]) +{ + u32 s0, s1, s2, s3, t0, t1, t2, t3; +#ifndef FULL_UNROLL + int r; +#endif /* ?FULL_UNROLL */ + + /* + * map byte array block to cipher state + * and add initial round key: + */ + s0 = GETU32(ct ) ^ rk[0]; + s1 = GETU32(ct + 4) ^ rk[1]; + s2 = GETU32(ct + 8) ^ rk[2]; + s3 = GETU32(ct + 12) ^ rk[3]; + +#define ROUND(i,d,s) \ +d##0 = TD0(s##0) ^ TD1(s##3) ^ TD2(s##2) ^ TD3(s##1) ^ rk[4 * i]; \ +d##1 = TD0(s##1) ^ TD1(s##0) ^ TD2(s##3) ^ TD3(s##2) ^ rk[4 * i + 1]; \ +d##2 = TD0(s##2) ^ TD1(s##1) ^ TD2(s##0) ^ TD3(s##3) ^ rk[4 * i + 2]; \ +d##3 = TD0(s##3) ^ TD1(s##2) ^ TD2(s##1) ^ TD3(s##0) ^ rk[4 * i + 3] + +#ifdef FULL_UNROLL + + ROUND(1,t,s); + ROUND(2,s,t); + ROUND(3,t,s); + ROUND(4,s,t); + ROUND(5,t,s); + ROUND(6,s,t); + ROUND(7,t,s); + ROUND(8,s,t); + ROUND(9,t,s); + if (Nr > 10) { + ROUND(10,s,t); + ROUND(11,t,s); + if (Nr > 12) { + ROUND(12,s,t); + ROUND(13,t,s); + } + } + + rk += Nr << 2; + +#else /* !FULL_UNROLL */ + + /* Nr - 1 full rounds: */ + r = Nr >> 1; + for (;;) { + ROUND(1,t,s); + rk += 8; + if (--r == 0) + break; + ROUND(0,s,t); + } + +#endif /* ?FULL_UNROLL */ + +#undef ROUND + + /* + * apply last round and + * map cipher state to byte array block: + */ + s0 = TD41(t0) ^ TD42(t3) ^ TD43(t2) ^ TD44(t1) ^ rk[0]; + PUTU32(pt , s0); + s1 = TD41(t1) ^ TD42(t0) ^ TD43(t3) ^ TD44(t2) ^ rk[1]; + PUTU32(pt + 4, s1); + s2 = TD41(t2) ^ TD42(t1) ^ TD43(t0) ^ TD44(t3) ^ rk[2]; + PUTU32(pt + 8, s2); + s3 = TD41(t3) ^ TD42(t2) ^ TD43(t1) ^ TD44(t0) ^ rk[3]; + PUTU32(pt + 12, s3); +} + +void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) +{ + u32 *rk = ctx; + rijndaelDecrypt(ctx, rk[AES_PRIV_NR_POS], crypt, plain); +} + + +void aes_decrypt_deinit(void *ctx) +{ + os_memset(ctx, 0, AES_PRIV_SIZE); + os_free(ctx); +} diff --git a/beken_os/beken378/func/hostapd-2.5/src/crypto/aes-internal-enc.c b/beken_os/beken378/func/hostapd-2.5/src/crypto/aes-internal-enc.c new file mode 100755 index 0000000..f3c61b8 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/crypto/aes-internal-enc.c @@ -0,0 +1,126 @@ +/* + * AES (Rijndael) cipher - encrypt + * + * Modifications to public domain implementation: + * - cleanup + * - use C pre-processor to make it easier to change S table access + * - added option (AES_SMALL_TABLES) for reducing code size by about 8 kB at + * cost of reduced throughput (quite small difference on Pentium 4, + * 10-25% when using -O1 or -O2 optimization) + * + * Copyright (c) 2003-2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "crypto.h" +#include "aes_i.h" + +static void rijndaelEncrypt(const u32 rk[], int Nr, const u8 pt[16], u8 ct[16]) +{ + u32 s0, s1, s2, s3, t0, t1, t2, t3; +#ifndef FULL_UNROLL + int r; +#endif /* ?FULL_UNROLL */ + + /* + * map byte array block to cipher state + * and add initial round key: + */ + s0 = GETU32(pt ) ^ rk[0]; + s1 = GETU32(pt + 4) ^ rk[1]; + s2 = GETU32(pt + 8) ^ rk[2]; + s3 = GETU32(pt + 12) ^ rk[3]; + +#define ROUND(i,d,s) \ +d##0 = TE0(s##0) ^ TE1(s##1) ^ TE2(s##2) ^ TE3(s##3) ^ rk[4 * i]; \ +d##1 = TE0(s##1) ^ TE1(s##2) ^ TE2(s##3) ^ TE3(s##0) ^ rk[4 * i + 1]; \ +d##2 = TE0(s##2) ^ TE1(s##3) ^ TE2(s##0) ^ TE3(s##1) ^ rk[4 * i + 2]; \ +d##3 = TE0(s##3) ^ TE1(s##0) ^ TE2(s##1) ^ TE3(s##2) ^ rk[4 * i + 3] + +#ifdef FULL_UNROLL + + ROUND(1,t,s); + ROUND(2,s,t); + ROUND(3,t,s); + ROUND(4,s,t); + ROUND(5,t,s); + ROUND(6,s,t); + ROUND(7,t,s); + ROUND(8,s,t); + ROUND(9,t,s); + if (Nr > 10) { + ROUND(10,s,t); + ROUND(11,t,s); + if (Nr > 12) { + ROUND(12,s,t); + ROUND(13,t,s); + } + } + + rk += Nr << 2; + +#else /* !FULL_UNROLL */ + + /* Nr - 1 full rounds: */ + r = Nr >> 1; + for (;;) { + ROUND(1,t,s); + rk += 8; + if (--r == 0) + break; + ROUND(0,s,t); + } + +#endif /* ?FULL_UNROLL */ + +#undef ROUND + + /* + * apply last round and + * map cipher state to byte array block: + */ + s0 = TE41(t0) ^ TE42(t1) ^ TE43(t2) ^ TE44(t3) ^ rk[0]; + PUTU32(ct , s0); + s1 = TE41(t1) ^ TE42(t2) ^ TE43(t3) ^ TE44(t0) ^ rk[1]; + PUTU32(ct + 4, s1); + s2 = TE41(t2) ^ TE42(t3) ^ TE43(t0) ^ TE44(t1) ^ rk[2]; + PUTU32(ct + 8, s2); + s3 = TE41(t3) ^ TE42(t0) ^ TE43(t1) ^ TE44(t2) ^ rk[3]; + PUTU32(ct + 12, s3); +} + + +void * aes_encrypt_init(const u8 *key, size_t len) +{ + u32 *rk; + int res; + rk = os_malloc(AES_PRIV_SIZE); + if (rk == NULL) + return NULL; + res = rijndaelKeySetupEnc(rk, key, len * 8); + if (res < 0) { + os_free(rk); + return NULL; + } + rk[AES_PRIV_NR_POS] = res; + return rk; +} + + +void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) +{ + u32 *rk = ctx; + rijndaelEncrypt(ctx, rk[AES_PRIV_NR_POS], plain, crypt); +} + + +void aes_encrypt_deinit(void *ctx) +{ + os_memset(ctx, 0, AES_PRIV_SIZE); + os_free(ctx); +} diff --git a/beken_os/beken378/func/hostapd-2.5/src/crypto/aes-internal.c b/beken_os/beken378/func/hostapd-2.5/src/crypto/aes-internal.c new file mode 100755 index 0000000..bd4535d --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/crypto/aes-internal.c @@ -0,0 +1,845 @@ +/* + * AES (Rijndael) cipher + * + * Modifications to public domain implementation: + * - cleanup + * - use C pre-processor to make it easier to change S table access + * - added option (AES_SMALL_TABLES) for reducing code size by about 8 kB at + * cost of reduced throughput (quite small difference on Pentium 4, + * 10-25% when using -O1 or -O2 optimization) + * + * Copyright (c) 2003-2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "crypto.h" +#include "aes_i.h" + +/* + * rijndael-alg-fst.c + * + * @version 3.0 (December 2000) + * + * Optimised ANSI C code for the Rijndael cipher (now AES) + * + * @author Vincent Rijmen + * @author Antoon Bosselaers + * @author Paulo Barreto + * + * This code is hereby placed in the public domain. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS + * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE + * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +/* +Te0[x] = S [x].[02, 01, 01, 03]; +Te1[x] = S [x].[03, 02, 01, 01]; +Te2[x] = S [x].[01, 03, 02, 01]; +Te3[x] = S [x].[01, 01, 03, 02]; +Te4[x] = S [x].[01, 01, 01, 01]; + +Td0[x] = Si[x].[0e, 09, 0d, 0b]; +Td1[x] = Si[x].[0b, 0e, 09, 0d]; +Td2[x] = Si[x].[0d, 0b, 0e, 09]; +Td3[x] = Si[x].[09, 0d, 0b, 0e]; +Td4[x] = Si[x].[01, 01, 01, 01]; +*/ + +const u32 Te0[256] = { + 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU, + 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U, + 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU, + 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU, + 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U, + 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU, + 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU, + 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU, + 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU, + 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU, + 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U, + 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU, + 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU, + 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U, + 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU, + 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU, + 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU, + 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU, + 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU, + 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U, + 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU, + 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU, + 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU, + 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU, + 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U, + 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U, + 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U, + 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U, + 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU, + 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U, + 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U, + 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU, + 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU, + 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U, + 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U, + 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U, + 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU, + 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U, + 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU, + 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U, + 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU, + 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U, + 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U, + 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU, + 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U, + 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U, + 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U, + 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U, + 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U, + 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U, + 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U, + 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U, + 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU, + 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U, + 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U, + 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U, + 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U, + 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U, + 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U, + 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU, + 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U, + 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U, + 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U, + 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU, +}; +#ifndef AES_SMALL_TABLES +const u32 Te1[256] = { + 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU, + 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U, + 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU, + 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U, + 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU, + 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U, + 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU, + 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U, + 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U, + 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU, + 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U, + 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U, + 0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U, + 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU, + 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U, + 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U, + 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU, + 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U, + 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U, + 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U, + 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU, + 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU, + 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U, + 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU, + 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU, + 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U, + 0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU, + 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U, + 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU, + 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U, + 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U, + 0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U, + 0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU, + 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U, + 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU, + 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U, + 0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU, + 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U, + 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U, + 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU, + 0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU, + 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU, + 0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U, + 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U, + 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU, + 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U, + 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU, + 0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U, + 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU, + 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U, + 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU, + 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU, + 0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U, + 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU, + 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U, + 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU, + 0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U, + 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U, + 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U, + 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU, + 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU, + 0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U, + 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU, + 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U, +}; +const u32 Te2[256] = { + 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU, + 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U, + 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU, + 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U, + 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU, + 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U, + 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU, + 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U, + 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U, + 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU, + 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U, + 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U, + 0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U, + 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU, + 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U, + 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U, + 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU, + 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U, + 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U, + 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U, + 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU, + 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU, + 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U, + 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU, + 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU, + 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U, + 0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU, + 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U, + 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU, + 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U, + 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U, + 0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U, + 0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU, + 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U, + 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU, + 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U, + 0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU, + 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U, + 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U, + 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU, + 0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU, + 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU, + 0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U, + 0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U, + 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU, + 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U, + 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU, + 0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U, + 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU, + 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U, + 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU, + 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU, + 0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U, + 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU, + 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U, + 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU, + 0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U, + 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U, + 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U, + 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU, + 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU, + 0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U, + 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU, + 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U, +}; +const u32 Te3[256] = { + + 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U, + 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U, + 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U, + 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU, + 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU, + 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU, + 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U, + 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU, + 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU, + 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U, + 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U, + 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU, + 0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU, + 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU, + 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU, + 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU, + 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U, + 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU, + 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU, + 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U, + 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U, + 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U, + 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U, + 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U, + 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU, + 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U, + 0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU, + 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU, + 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U, + 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U, + 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U, + 0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU, + 0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U, + 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU, + 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU, + 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U, + 0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U, + 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU, + 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U, + 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU, + 0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U, + 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U, + 0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U, + 0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U, + 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU, + 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U, + 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU, + 0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U, + 0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU, + 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U, + 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU, + 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU, + 0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU, + 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU, + 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U, + 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U, + 0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U, + 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U, + 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U, + 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U, + 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU, + 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U, + 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU, + 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU, +}; +const u32 Te4[256] = { + 0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU, + 0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U, + 0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU, + 0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U, + 0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU, + 0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U, + 0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU, + 0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U, + 0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U, + 0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU, + 0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U, + 0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U, + 0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U, + 0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU, + 0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U, + 0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U, + 0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU, + 0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U, + 0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U, + 0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U, + 0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU, + 0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU, + 0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U, + 0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU, + 0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU, + 0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U, + 0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU, + 0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U, + 0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU, + 0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U, + 0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U, + 0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U, + 0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU, + 0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U, + 0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU, + 0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U, + 0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU, + 0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U, + 0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U, + 0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU, + 0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU, + 0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU, + 0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U, + 0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U, + 0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU, + 0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U, + 0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU, + 0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U, + 0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU, + 0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U, + 0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU, + 0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU, + 0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U, + 0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU, + 0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U, + 0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU, + 0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U, + 0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U, + 0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U, + 0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU, + 0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU, + 0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U, + 0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU, + 0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U, +}; +#endif /* AES_SMALL_TABLES */ +const u32 Td0[256] = { + 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U, + 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U, + 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U, + 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU, + 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U, + 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U, + 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU, + 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U, + 0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU, + 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U, + 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U, + 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U, + 0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U, + 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU, + 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U, + 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU, + 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U, + 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU, + 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U, + 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U, + 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U, + 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU, + 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U, + 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU, + 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U, + 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU, + 0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U, + 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU, + 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU, + 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U, + 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU, + 0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U, + 0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU, + 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U, + 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U, + 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U, + 0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU, + 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U, + 0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U, + 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU, + 0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U, + 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U, + 0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U, + 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U, + 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U, + 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU, + 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U, + 0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U, + 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U, + 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U, + 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U, + 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU, + 0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU, + 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU, + 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU, + 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U, + 0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U, + 0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU, + 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU, + 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U, + 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU, + 0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U, + 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U, + 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U, +}; +#ifndef AES_SMALL_TABLES +const u32 Td1[256] = { + 0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU, + 0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U, + 0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU, + 0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U, + 0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U, + 0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U, + 0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U, + 0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U, + 0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U, + 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU, + 0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU, + 0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU, + 0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U, + 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU, + 0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U, + 0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U, + 0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U, + 0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU, + 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU, + 0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U, + 0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU, + 0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U, + 0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU, + 0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU, + 0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U, + 0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U, + 0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U, + 0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU, + 0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U, + 0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU, + 0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U, + 0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U, + 0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U, + 0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU, + 0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U, + 0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U, + 0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U, + 0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U, + 0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U, + 0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U, + 0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU, + 0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU, + 0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U, + 0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU, + 0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U, + 0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU, + 0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU, + 0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U, + 0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU, + 0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U, + 0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U, + 0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U, + 0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U, + 0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U, + 0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U, + 0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U, + 0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU, + 0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U, + 0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U, + 0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU, + 0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U, + 0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U, + 0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U, + 0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U, +}; +const u32 Td2[256] = { + 0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U, + 0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U, + 0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U, + 0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U, + 0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU, + 0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U, + 0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U, + 0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U, + 0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U, + 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU, + 0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U, + 0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U, + 0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU, + 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U, + 0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U, + 0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U, + 0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U, + 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U, + 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U, + 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU, + + 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U, + 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U, + 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U, + 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U, + 0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U, + 0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU, + 0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU, + 0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U, + 0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU, + 0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U, + 0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU, + 0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU, + 0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU, + 0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU, + 0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U, + 0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U, + 0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U, + 0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U, + 0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U, + 0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U, + 0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U, + 0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU, + 0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU, + 0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U, + 0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U, + 0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU, + 0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU, + 0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U, + 0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U, + 0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U, + 0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U, + 0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U, + 0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U, + 0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U, + 0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU, + 0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U, + 0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U, + 0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U, + 0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U, + 0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U, + 0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U, + 0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU, + 0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U, + 0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U, +}; +const u32 Td3[256] = { + 0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU, + 0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU, + 0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U, + 0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U, + 0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU, + 0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU, + 0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U, + 0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU, + 0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U, + 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU, + 0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U, + 0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U, + 0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U, + 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U, + 0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U, + 0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU, + 0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU, + 0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U, + 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U, + 0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU, + 0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU, + 0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U, + 0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U, + 0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U, + 0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U, + 0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU, + 0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U, + 0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U, + 0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU, + 0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU, + 0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U, + 0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U, + 0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U, + 0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU, + 0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U, + 0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U, + 0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U, + 0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U, + 0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U, + 0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U, + 0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U, + 0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU, + 0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U, + 0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U, + 0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU, + 0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU, + 0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U, + 0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU, + 0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U, + 0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U, + 0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U, + 0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U, + 0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U, + 0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U, + 0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU, + 0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU, + 0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU, + 0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU, + 0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U, + 0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U, + 0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U, + 0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU, + 0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U, + 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U, +}; +const u32 Td4[256] = { + 0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U, + 0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U, + 0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU, + 0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU, + 0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U, + 0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U, + 0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U, + 0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU, + 0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U, + 0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU, + 0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU, + 0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU, + 0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U, + 0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U, + 0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U, + 0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U, + 0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U, + 0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U, + 0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU, + 0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U, + 0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U, + 0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU, + 0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U, + 0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U, + 0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U, + 0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU, + 0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U, + 0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U, + 0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU, + 0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U, + 0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U, + 0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU, + 0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U, + 0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU, + 0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU, + 0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U, + 0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U, + 0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U, + 0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U, + 0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU, + 0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U, + 0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U, + 0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU, + 0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU, + 0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU, + 0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U, + 0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU, + 0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U, + 0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U, + 0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U, + 0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U, + 0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU, + 0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U, + 0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU, + 0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU, + 0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU, + 0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU, + 0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U, + 0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU, + 0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U, + 0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU, + 0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U, + 0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U, + 0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU, +}; +const u32 rcon[] = { + 0x01000000, 0x02000000, 0x04000000, 0x08000000, + 0x10000000, 0x20000000, 0x40000000, 0x80000000, + 0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ +}; +#else /* AES_SMALL_TABLES */ +const u8 Td4s[256] = { + 0x52U, 0x09U, 0x6aU, 0xd5U, 0x30U, 0x36U, 0xa5U, 0x38U, + 0xbfU, 0x40U, 0xa3U, 0x9eU, 0x81U, 0xf3U, 0xd7U, 0xfbU, + 0x7cU, 0xe3U, 0x39U, 0x82U, 0x9bU, 0x2fU, 0xffU, 0x87U, + 0x34U, 0x8eU, 0x43U, 0x44U, 0xc4U, 0xdeU, 0xe9U, 0xcbU, + 0x54U, 0x7bU, 0x94U, 0x32U, 0xa6U, 0xc2U, 0x23U, 0x3dU, + 0xeeU, 0x4cU, 0x95U, 0x0bU, 0x42U, 0xfaU, 0xc3U, 0x4eU, + 0x08U, 0x2eU, 0xa1U, 0x66U, 0x28U, 0xd9U, 0x24U, 0xb2U, + 0x76U, 0x5bU, 0xa2U, 0x49U, 0x6dU, 0x8bU, 0xd1U, 0x25U, + 0x72U, 0xf8U, 0xf6U, 0x64U, 0x86U, 0x68U, 0x98U, 0x16U, + 0xd4U, 0xa4U, 0x5cU, 0xccU, 0x5dU, 0x65U, 0xb6U, 0x92U, + 0x6cU, 0x70U, 0x48U, 0x50U, 0xfdU, 0xedU, 0xb9U, 0xdaU, + 0x5eU, 0x15U, 0x46U, 0x57U, 0xa7U, 0x8dU, 0x9dU, 0x84U, + 0x90U, 0xd8U, 0xabU, 0x00U, 0x8cU, 0xbcU, 0xd3U, 0x0aU, + 0xf7U, 0xe4U, 0x58U, 0x05U, 0xb8U, 0xb3U, 0x45U, 0x06U, + 0xd0U, 0x2cU, 0x1eU, 0x8fU, 0xcaU, 0x3fU, 0x0fU, 0x02U, + 0xc1U, 0xafU, 0xbdU, 0x03U, 0x01U, 0x13U, 0x8aU, 0x6bU, + 0x3aU, 0x91U, 0x11U, 0x41U, 0x4fU, 0x67U, 0xdcU, 0xeaU, + 0x97U, 0xf2U, 0xcfU, 0xceU, 0xf0U, 0xb4U, 0xe6U, 0x73U, + 0x96U, 0xacU, 0x74U, 0x22U, 0xe7U, 0xadU, 0x35U, 0x85U, + 0xe2U, 0xf9U, 0x37U, 0xe8U, 0x1cU, 0x75U, 0xdfU, 0x6eU, + 0x47U, 0xf1U, 0x1aU, 0x71U, 0x1dU, 0x29U, 0xc5U, 0x89U, + 0x6fU, 0xb7U, 0x62U, 0x0eU, 0xaaU, 0x18U, 0xbeU, 0x1bU, + 0xfcU, 0x56U, 0x3eU, 0x4bU, 0xc6U, 0xd2U, 0x79U, 0x20U, + 0x9aU, 0xdbU, 0xc0U, 0xfeU, 0x78U, 0xcdU, 0x5aU, 0xf4U, + 0x1fU, 0xddU, 0xa8U, 0x33U, 0x88U, 0x07U, 0xc7U, 0x31U, + 0xb1U, 0x12U, 0x10U, 0x59U, 0x27U, 0x80U, 0xecU, 0x5fU, + 0x60U, 0x51U, 0x7fU, 0xa9U, 0x19U, 0xb5U, 0x4aU, 0x0dU, + 0x2dU, 0xe5U, 0x7aU, 0x9fU, 0x93U, 0xc9U, 0x9cU, 0xefU, + 0xa0U, 0xe0U, 0x3bU, 0x4dU, 0xaeU, 0x2aU, 0xf5U, 0xb0U, + 0xc8U, 0xebU, 0xbbU, 0x3cU, 0x83U, 0x53U, 0x99U, 0x61U, + 0x17U, 0x2bU, 0x04U, 0x7eU, 0xbaU, 0x77U, 0xd6U, 0x26U, + 0xe1U, 0x69U, 0x14U, 0x63U, 0x55U, 0x21U, 0x0cU, 0x7dU, +}; +const u8 rcons[] = { + 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36 + /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ +}; +#endif /* AES_SMALL_TABLES */ +/** + * Expand the cipher key into the encryption key schedule. + * + * @return the number of rounds for the given cipher key size. + */ +int rijndaelKeySetupEnc(u32 rk[], const u8 cipherKey[], int keyBits) +{ + int i; + u32 temp; + + rk[0] = GETU32(cipherKey ); + rk[1] = GETU32(cipherKey + 4); + rk[2] = GETU32(cipherKey + 8); + rk[3] = GETU32(cipherKey + 12); + + if (keyBits == 128) { + for (i = 0; i < 10; i++) { + temp = rk[3]; + rk[4] = rk[0] ^ TE421(temp) ^ TE432(temp) ^ + TE443(temp) ^ TE414(temp) ^ RCON(i); + rk[5] = rk[1] ^ rk[4]; + rk[6] = rk[2] ^ rk[5]; + rk[7] = rk[3] ^ rk[6]; + rk += 4; + } + return 10; + } + + rk[4] = GETU32(cipherKey + 16); + rk[5] = GETU32(cipherKey + 20); + + if (keyBits == 192) { + for (i = 0; i < 8; i++) { + temp = rk[5]; + rk[6] = rk[0] ^ TE421(temp) ^ TE432(temp) ^ + TE443(temp) ^ TE414(temp) ^ RCON(i); + rk[7] = rk[1] ^ rk[6]; + rk[8] = rk[2] ^ rk[7]; + rk[9] = rk[3] ^ rk[8]; + if (i == 7) + return 12; + rk[10] = rk[4] ^ rk[9]; + rk[11] = rk[5] ^ rk[10]; + rk += 6; + } + } + + rk[6] = GETU32(cipherKey + 24); + rk[7] = GETU32(cipherKey + 28); + + if (keyBits == 256) { + for (i = 0; i < 7; i++) { + temp = rk[7]; + rk[8] = rk[0] ^ TE421(temp) ^ TE432(temp) ^ + TE443(temp) ^ TE414(temp) ^ RCON(i); + rk[9] = rk[1] ^ rk[8]; + rk[10] = rk[2] ^ rk[9]; + rk[11] = rk[3] ^ rk[10]; + if (i == 6) + return 14; + temp = rk[11]; + rk[12] = rk[4] ^ TE411(temp) ^ TE422(temp) ^ + TE433(temp) ^ TE444(temp); + rk[13] = rk[5] ^ rk[12]; + rk[14] = rk[6] ^ rk[13]; + rk[15] = rk[7] ^ rk[14]; + rk += 8; + } + } + + return -1; +} diff --git a/beken_os/beken378/func/hostapd-2.5/src/crypto/aes-unwrap.c b/beken_os/beken378/func/hostapd-2.5/src/crypto/aes-unwrap.c new file mode 100755 index 0000000..a5fcba5 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/crypto/aes-unwrap.c @@ -0,0 +1,80 @@ +/* + * AES key unwrap (RFC3394) + * + * Copyright (c) 2003-2007, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "crypto/aes.h" +#include "aes_wrap.h" + +/** + * aes_unwrap - Unwrap key with AES Key Wrap Algorithm (RFC3394) + * @kek: Key encryption key (KEK) + * @kek_len: Length of KEK in octets + * @n: Length of the plaintext key in 64-bit units; e.g., 2 = 128-bit = 16 + * bytes + * @cipher: Wrapped key to be unwrapped, (n + 1) * 64 bits + * @plain: Plaintext key, n * 64 bits + * Returns: 0 on success, -1 on failure (e.g., integrity verification failed) + */ +int aes_unwrap(const u8 *kek, size_t kek_len, int n, const u8 *cipher, + u8 *plain) +{ + u8 a[8], *r, b[AES_BLOCK_SIZE]; + int i, j; + void *ctx; + unsigned int t; + + /* 1) Initialize variables. */ + os_memcpy(a, cipher, 8); + r = plain; + os_memcpy(r, cipher + 8, 8 * n); + + ctx = aes_decrypt_init(kek, kek_len); + if (ctx == NULL) + return -1; + + /* 2) Compute intermediate values. + * For j = 5 to 0 + * For i = n to 1 + * B = AES-1(K, (A ^ t) | R[i]) where t = n*j+i + * A = MSB(64, B) + * R[i] = LSB(64, B) + */ + for (j = 5; j >= 0; j--) { + r = plain + (n - 1) * 8; + for (i = n; i >= 1; i--) { + os_memcpy(b, a, 8); + t = n * j + i; + b[7] ^= t; + b[6] ^= t >> 8; + b[5] ^= t >> 16; + b[4] ^= t >> 24; + + os_memcpy(b + 8, r, 8); + aes_decrypt(ctx, b, b); + os_memcpy(a, b, 8); + os_memcpy(r, b + 8, 8); + r -= 8; + } + } + aes_decrypt_deinit(ctx); + + /* 3) Output results. + * + * These are already in @plain due to the location of temporary + * variables. Just verify that the IV matches with the expected value. + */ + for (i = 0; i < 8; i++) { + if (a[i] != 0xa6) + return -1; + } + + return 0; +} diff --git a/beken_os/beken378/func/hostapd-2.5/src/crypto/aes-wrap.c b/beken_os/beken378/func/hostapd-2.5/src/crypto/aes-wrap.c new file mode 100755 index 0000000..e4dd800 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/crypto/aes-wrap.c @@ -0,0 +1,76 @@ +/* + * AES Key Wrap Algorithm (RFC3394) + * + * Copyright (c) 2003-2007, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "crypto/aes.h" +#include "aes_wrap.h" + +/** + * aes_wrap - Wrap keys with AES Key Wrap Algorithm (RFC3394) + * @kek: Key encryption key (KEK) + * @kek_len: Length of KEK in octets + * @n: Length of the plaintext key in 64-bit units; e.g., 2 = 128-bit = 16 + * bytes + * @plain: Plaintext key to be wrapped, n * 64 bits + * @cipher: Wrapped key, (n + 1) * 64 bits + * Returns: 0 on success, -1 on failure + */ +int aes_wrap(const u8 *kek, size_t kek_len, int n, const u8 *plain, u8 *cipher) +{ + u8 *a, *r, b[AES_BLOCK_SIZE]; + int i, j; + void *ctx; + unsigned int t; + + a = cipher; + r = cipher + 8; + + /* 1) Initialize variables. */ + os_memset(a, 0xa6, 8); + os_memcpy(r, plain, 8 * n); + + ctx = aes_encrypt_init(kek, kek_len); + if (ctx == NULL) + return -1; + + /* 2) Calculate intermediate values. + * For j = 0 to 5 + * For i=1 to n + * B = AES(K, A | R[i]) + * A = MSB(64, B) ^ t where t = (n*j)+i + * R[i] = LSB(64, B) + */ + for (j = 0; j <= 5; j++) { + r = cipher + 8; + for (i = 1; i <= n; i++) { + os_memcpy(b, a, 8); + os_memcpy(b + 8, r, 8); + aes_encrypt(ctx, b, b); + os_memcpy(a, b, 8); + t = n * j + i; + a[7] ^= t; + a[6] ^= t >> 8; + a[5] ^= t >> 16; + a[4] ^= t >> 24; + os_memcpy(r, b + 8, 8); + r += 8; + } + } + aes_encrypt_deinit(ctx); + + /* 3) Output the results. + * + * These are already in @cipher due to the location of temporary + * variables. + */ + + return 0; +} diff --git a/beken_os/beken378/func/hostapd-2.5/src/crypto/aes.h b/beken_os/beken378/func/hostapd-2.5/src/crypto/aes.h new file mode 100755 index 0000000..2de59e0 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/crypto/aes.h @@ -0,0 +1,21 @@ +/* + * AES functions + * Copyright (c) 2003-2006, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef AES_H +#define AES_H + +#define AES_BLOCK_SIZE 16 + +void * aes_encrypt_init(const u8 *key, size_t len); +void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt); +void aes_encrypt_deinit(void *ctx); +void * aes_decrypt_init(const u8 *key, size_t len); +void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain); +void aes_decrypt_deinit(void *ctx); + +#endif /* AES_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/crypto/aes_i.h b/beken_os/beken378/func/hostapd-2.5/src/crypto/aes_i.h new file mode 100755 index 0000000..fa0ed51 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/crypto/aes_i.h @@ -0,0 +1,125 @@ +/* + * AES (Rijndael) cipher + * Copyright (c) 2003-2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef AES_I_H +#define AES_I_H + +#include "crypto/aes.h" + +/* #define FULL_UNROLL */ +#define AES_SMALL_TABLES + +extern const u32 Te0[256]; +extern const u32 Te1[256]; +extern const u32 Te2[256]; +extern const u32 Te3[256]; +extern const u32 Te4[256]; +extern const u32 Td0[256]; +extern const u32 Td1[256]; +extern const u32 Td2[256]; +extern const u32 Td3[256]; +extern const u32 Td4[256]; +extern const u32 rcon[10]; +extern const u8 Td4s[256]; +extern const u8 rcons[10]; + +#ifndef AES_SMALL_TABLES + +#define RCON(i) rcon[(i)] + +#define TE0(i) Te0[((i) >> 24) & 0xff] +#define TE1(i) Te1[((i) >> 16) & 0xff] +#define TE2(i) Te2[((i) >> 8) & 0xff] +#define TE3(i) Te3[(i) & 0xff] +#define TE41(i) (Te4[((i) >> 24) & 0xff] & 0xff000000) +#define TE42(i) (Te4[((i) >> 16) & 0xff] & 0x00ff0000) +#define TE43(i) (Te4[((i) >> 8) & 0xff] & 0x0000ff00) +#define TE44(i) (Te4[(i) & 0xff] & 0x000000ff) +#define TE421(i) (Te4[((i) >> 16) & 0xff] & 0xff000000) +#define TE432(i) (Te4[((i) >> 8) & 0xff] & 0x00ff0000) +#define TE443(i) (Te4[(i) & 0xff] & 0x0000ff00) +#define TE414(i) (Te4[((i) >> 24) & 0xff] & 0x000000ff) +#define TE411(i) (Te4[((i) >> 24) & 0xff] & 0xff000000) +#define TE422(i) (Te4[((i) >> 16) & 0xff] & 0x00ff0000) +#define TE433(i) (Te4[((i) >> 8) & 0xff] & 0x0000ff00) +#define TE444(i) (Te4[(i) & 0xff] & 0x000000ff) +#define TE4(i) (Te4[(i)] & 0x000000ff) + +#define TD0(i) Td0[((i) >> 24) & 0xff] +#define TD1(i) Td1[((i) >> 16) & 0xff] +#define TD2(i) Td2[((i) >> 8) & 0xff] +#define TD3(i) Td3[(i) & 0xff] +#define TD41(i) (Td4[((i) >> 24) & 0xff] & 0xff000000) +#define TD42(i) (Td4[((i) >> 16) & 0xff] & 0x00ff0000) +#define TD43(i) (Td4[((i) >> 8) & 0xff] & 0x0000ff00) +#define TD44(i) (Td4[(i) & 0xff] & 0x000000ff) +#define TD0_(i) Td0[(i) & 0xff] +#define TD1_(i) Td1[(i) & 0xff] +#define TD2_(i) Td2[(i) & 0xff] +#define TD3_(i) Td3[(i) & 0xff] + +#else /* AES_SMALL_TABLES */ + +#define RCON(i) (rcons[(i)] << 24) + +static inline u32 rotr(u32 val, int bits) +{ + return (val >> bits) | (val << (32 - bits)); +} + +#define TE0(i) Te0[((i) >> 24) & 0xff] +#define TE1(i) rotr(Te0[((i) >> 16) & 0xff], 8) +#define TE2(i) rotr(Te0[((i) >> 8) & 0xff], 16) +#define TE3(i) rotr(Te0[(i) & 0xff], 24) +#define TE41(i) ((Te0[((i) >> 24) & 0xff] << 8) & 0xff000000) +#define TE42(i) (Te0[((i) >> 16) & 0xff] & 0x00ff0000) +#define TE43(i) (Te0[((i) >> 8) & 0xff] & 0x0000ff00) +#define TE44(i) ((Te0[(i) & 0xff] >> 8) & 0x000000ff) +#define TE421(i) ((Te0[((i) >> 16) & 0xff] << 8) & 0xff000000) +#define TE432(i) (Te0[((i) >> 8) & 0xff] & 0x00ff0000) +#define TE443(i) (Te0[(i) & 0xff] & 0x0000ff00) +#define TE414(i) ((Te0[((i) >> 24) & 0xff] >> 8) & 0x000000ff) +#define TE411(i) ((Te0[((i) >> 24) & 0xff] << 8) & 0xff000000) +#define TE422(i) (Te0[((i) >> 16) & 0xff] & 0x00ff0000) +#define TE433(i) (Te0[((i) >> 8) & 0xff] & 0x0000ff00) +#define TE444(i) ((Te0[(i) & 0xff] >> 8) & 0x000000ff) +#define TE4(i) ((Te0[(i)] >> 8) & 0x000000ff) + +#define TD0(i) Td0[((i) >> 24) & 0xff] +#define TD1(i) rotr(Td0[((i) >> 16) & 0xff], 8) +#define TD2(i) rotr(Td0[((i) >> 8) & 0xff], 16) +#define TD3(i) rotr(Td0[(i) & 0xff], 24) +#define TD41(i) (Td4s[((i) >> 24) & 0xff] << 24) +#define TD42(i) (Td4s[((i) >> 16) & 0xff] << 16) +#define TD43(i) (Td4s[((i) >> 8) & 0xff] << 8) +#define TD44(i) (Td4s[(i) & 0xff]) +#define TD0_(i) Td0[(i) & 0xff] +#define TD1_(i) rotr(Td0[(i) & 0xff], 8) +#define TD2_(i) rotr(Td0[(i) & 0xff], 16) +#define TD3_(i) rotr(Td0[(i) & 0xff], 24) + +#endif /* AES_SMALL_TABLES */ + +#ifdef _MSC_VER +#define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00) +#define GETU32(p) SWAP(*((u32 *)(p))) +#define PUTU32(ct, st) { *((u32 *)(ct)) = SWAP((st)); } +#else +#define GETU32(pt) (((u32)(pt)[0] << 24) ^ ((u32)(pt)[1] << 16) ^ \ +((u32)(pt)[2] << 8) ^ ((u32)(pt)[3])) +#define PUTU32(ct, st) { \ +(ct)[0] = (u8)((st) >> 24); (ct)[1] = (u8)((st) >> 16); \ +(ct)[2] = (u8)((st) >> 8); (ct)[3] = (u8)(st); } +#endif + +#define AES_PRIV_SIZE (4 * 4 * 15 + 4) +#define AES_PRIV_NR_POS (4 * 15) + +int rijndaelKeySetupEnc(u32 rk[], const u8 cipherKey[], int keyBits); + +#endif /* AES_I_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/crypto/aes_siv.h b/beken_os/beken378/func/hostapd-2.5/src/crypto/aes_siv.h new file mode 100755 index 0000000..463cf65 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/crypto/aes_siv.h @@ -0,0 +1,19 @@ +/* + * AES SIV (RFC 5297) + * Copyright (c) 2013 Cozybit, Inc. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef AES_SIV_H +#define AES_SIV_H + +int aes_siv_encrypt(const u8 *key, const u8 *pw, + size_t pwlen, size_t num_elem, + const u8 *addr[], const size_t *len, u8 *out); +int aes_siv_decrypt(const u8 *key, const u8 *iv_crypt, size_t iv_c_len, + size_t num_elem, const u8 *addr[], const size_t *len, + u8 *out); + +#endif /* AES_SIV_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/crypto/aes_wrap.h b/beken_os/beken378/func/hostapd-2.5/src/crypto/aes_wrap.h new file mode 100755 index 0000000..4a14209 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/crypto/aes_wrap.h @@ -0,0 +1,71 @@ +/* + * AES-based functions + * + * - AES Key Wrap Algorithm (RFC3394) + * - One-Key CBC MAC (OMAC1) hash with AES-128 and AES-256 + * - AES-128 CTR mode encryption + * - AES-128 EAX mode encryption/decryption + * - AES-128 CBC + * - AES-GCM + * - AES-CCM + * + * Copyright (c) 2003-2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef AES_WRAP_H +#define AES_WRAP_H + +int __must_check aes_wrap(const u8 *kek, size_t kek_len, int n, const u8 *plain, + u8 *cipher); +int __must_check aes_unwrap(const u8 *kek, size_t kek_len, int n, + const u8 *cipher, u8 *plain); +int __must_check omac1_aes_vector(const u8 *key, size_t key_len, + size_t num_elem, const u8 *addr[], + const size_t *len, u8 *mac); +int __must_check omac1_aes_128_vector(const u8 *key, size_t num_elem, + const u8 *addr[], const size_t *len, + u8 *mac); +int __must_check omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, + u8 *mac); +int __must_check omac1_aes_256(const u8 *key, const u8 *data, size_t data_len, + u8 *mac); +int __must_check aes_128_encrypt_block(const u8 *key, const u8 *in, u8 *out); +int __must_check aes_128_ctr_encrypt(const u8 *key, const u8 *nonce, + u8 *data, size_t data_len); +int __must_check aes_128_eax_encrypt(const u8 *key, + const u8 *nonce, size_t nonce_len, + const u8 *hdr, size_t hdr_len, + u8 *data, size_t data_len, u8 *tag); +int __must_check aes_128_eax_decrypt(const u8 *key, + const u8 *nonce, size_t nonce_len, + const u8 *hdr, size_t hdr_len, + u8 *data, size_t data_len, const u8 *tag); +int __must_check aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, + size_t data_len); +int __must_check aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, + size_t data_len); +int __must_check aes_gcm_ae(const u8 *key, size_t key_len, + const u8 *iv, size_t iv_len, + const u8 *plain, size_t plain_len, + const u8 *aad, size_t aad_len, + u8 *crypt, u8 *tag); +int __must_check aes_gcm_ad(const u8 *key, size_t key_len, + const u8 *iv, size_t iv_len, + const u8 *crypt, size_t crypt_len, + const u8 *aad, size_t aad_len, const u8 *tag, + u8 *plain); +int __must_check aes_gmac(const u8 *key, size_t key_len, + const u8 *iv, size_t iv_len, + const u8 *aad, size_t aad_len, u8 *tag); +int __must_check aes_ccm_ae(const u8 *key, size_t key_len, const u8 *nonce, + size_t M, const u8 *plain, size_t plain_len, + const u8 *aad, size_t aad_len, u8 *crypt, u8 *auth); +int __must_check aes_ccm_ad(const u8 *key, size_t key_len, const u8 *nonce, + size_t M, const u8 *crypt, size_t crypt_len, + const u8 *aad, size_t aad_len, const u8 *auth, + u8 *plain); + +#endif /* AES_WRAP_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/crypto/crypto.h b/beken_os/beken378/func/hostapd-2.5/src/crypto/crypto.h new file mode 100755 index 0000000..534c4bd --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/crypto/crypto.h @@ -0,0 +1,809 @@ +/* + * Wrapper functions for crypto libraries + * Copyright (c) 2004-2013, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + * + * This file defines the cryptographic functions that need to be implemented + * for wpa_supplicant and hostapd. When TLS is not used, internal + * implementation of MD5, SHA1, and AES is used and no external libraries are + * required. When TLS is enabled (e.g., by enabling EAP-TLS or EAP-PEAP), the + * crypto library used by the TLS implementation is expected to be used for + * non-TLS needs, too, in order to save space by not implementing these + * functions twice. + * + * Wrapper code for using each crypto library is in its own file (crypto*.c) + * and one of these files is build and linked in to provide the functions + * defined here. + */ + +#ifndef CRYPTO_H +#define CRYPTO_H + +/** + * md4_vector - MD4 hash for data vector + * @num_elem: Number of elements in the data vector + * @addr: Pointers to the data areas + * @len: Lengths of the data blocks + * @mac: Buffer for the hash + * Returns: 0 on success, -1 on failure + */ +int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); + +/** + * md5_vector - MD5 hash for data vector + * @num_elem: Number of elements in the data vector + * @addr: Pointers to the data areas + * @len: Lengths of the data blocks + * @mac: Buffer for the hash + * Returns: 0 on success, -1 on failure + */ +int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); + + +/** + * sha1_vector - SHA-1 hash for data vector + * @num_elem: Number of elements in the data vector + * @addr: Pointers to the data areas + * @len: Lengths of the data blocks + * @mac: Buffer for the hash + * Returns: 0 on success, -1 on failure + */ +int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, + u8 *mac); + +/** + * fips186_2-prf - NIST FIPS Publication 186-2 change notice 1 PRF + * @seed: Seed/key for the PRF + * @seed_len: Seed length in bytes + * @x: Buffer for PRF output + * @xlen: Output length in bytes + * Returns: 0 on success, -1 on failure + * + * This function implements random number generation specified in NIST FIPS + * Publication 186-2 for EAP-SIM. This PRF uses a function that is similar to + * SHA-1, but has different message padding. + */ +int __must_check fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x, + size_t xlen); + +/** + * sha256_vector - SHA256 hash for data vector + * @num_elem: Number of elements in the data vector + * @addr: Pointers to the data areas + * @len: Lengths of the data blocks + * @mac: Buffer for the hash + * Returns: 0 on success, -1 on failure + */ +int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, + u8 *mac); + +/** + * des_encrypt - Encrypt one block with DES + * @clear: 8 octets (in) + * @key: 7 octets (in) (no parity bits included) + * @cypher: 8 octets (out) + */ +void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher); + +/** + * aes_encrypt_init - Initialize AES for encryption + * @key: Encryption key + * @len: Key length in bytes (usually 16, i.e., 128 bits) + * Returns: Pointer to context data or %NULL on failure + */ +void * aes_encrypt_init(const u8 *key, size_t len); + +/** + * aes_encrypt - Encrypt one AES block + * @ctx: Context pointer from aes_encrypt_init() + * @plain: Plaintext data to be encrypted (16 bytes) + * @crypt: Buffer for the encrypted data (16 bytes) + */ +void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt); + +/** + * aes_encrypt_deinit - Deinitialize AES encryption + * @ctx: Context pointer from aes_encrypt_init() + */ +void aes_encrypt_deinit(void *ctx); + +/** + * aes_decrypt_init - Initialize AES for decryption + * @key: Decryption key + * @len: Key length in bytes (usually 16, i.e., 128 bits) + * Returns: Pointer to context data or %NULL on failure + */ +void * aes_decrypt_init(const u8 *key, size_t len); + +/** + * aes_decrypt - Decrypt one AES block + * @ctx: Context pointer from aes_encrypt_init() + * @crypt: Encrypted data (16 bytes) + * @plain: Buffer for the decrypted data (16 bytes) + */ +void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain); + +/** + * aes_decrypt_deinit - Deinitialize AES decryption + * @ctx: Context pointer from aes_encrypt_init() + */ +void aes_decrypt_deinit(void *ctx); + + +enum crypto_hash_alg { + CRYPTO_HASH_ALG_MD5, CRYPTO_HASH_ALG_SHA1, + CRYPTO_HASH_ALG_HMAC_MD5, CRYPTO_HASH_ALG_HMAC_SHA1, + CRYPTO_HASH_ALG_SHA256, CRYPTO_HASH_ALG_HMAC_SHA256 +}; + +struct crypto_hash; + +/** + * crypto_hash_init - Initialize hash/HMAC function + * @alg: Hash algorithm + * @key: Key for keyed hash (e.g., HMAC) or %NULL if not needed + * @key_len: Length of the key in bytes + * Returns: Pointer to hash context to use with other hash functions or %NULL + * on failure + * + * This function is only used with internal TLSv1 implementation + * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need + * to implement this. + */ +struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key, + size_t key_len); + +/** + * crypto_hash_update - Add data to hash calculation + * @ctx: Context pointer from crypto_hash_init() + * @data: Data buffer to add + * @len: Length of the buffer + * + * This function is only used with internal TLSv1 implementation + * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need + * to implement this. + */ +void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len); + +/** + * crypto_hash_finish - Complete hash calculation + * @ctx: Context pointer from crypto_hash_init() + * @hash: Buffer for hash value or %NULL if caller is just freeing the hash + * context + * @len: Pointer to length of the buffer or %NULL if caller is just freeing the + * hash context; on return, this is set to the actual length of the hash value + * Returns: 0 on success, -1 if buffer is too small (len set to needed length), + * or -2 on other failures (including failed crypto_hash_update() operations) + * + * This function calculates the hash value and frees the context buffer that + * was used for hash calculation. + * + * This function is only used with internal TLSv1 implementation + * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need + * to implement this. + */ +int crypto_hash_finish(struct crypto_hash *ctx, u8 *hash, size_t *len); + + +enum crypto_cipher_alg { + CRYPTO_CIPHER_NULL = 0, CRYPTO_CIPHER_ALG_AES, CRYPTO_CIPHER_ALG_3DES, + CRYPTO_CIPHER_ALG_DES, CRYPTO_CIPHER_ALG_RC2, CRYPTO_CIPHER_ALG_RC4 +}; + +struct crypto_cipher; + +/** + * crypto_cipher_init - Initialize block/stream cipher function + * @alg: Cipher algorithm + * @iv: Initialization vector for block ciphers or %NULL for stream ciphers + * @key: Cipher key + * @key_len: Length of key in bytes + * Returns: Pointer to cipher context to use with other cipher functions or + * %NULL on failure + * + * This function is only used with internal TLSv1 implementation + * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need + * to implement this. + */ +struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg, + const u8 *iv, const u8 *key, + size_t key_len); + +/** + * crypto_cipher_encrypt - Cipher encrypt + * @ctx: Context pointer from crypto_cipher_init() + * @plain: Plaintext to cipher + * @crypt: Resulting ciphertext + * @len: Length of the plaintext + * Returns: 0 on success, -1 on failure + * + * This function is only used with internal TLSv1 implementation + * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need + * to implement this. + */ +int __must_check crypto_cipher_encrypt(struct crypto_cipher *ctx, + const u8 *plain, u8 *crypt, size_t len); + +/** + * crypto_cipher_decrypt - Cipher decrypt + * @ctx: Context pointer from crypto_cipher_init() + * @crypt: Ciphertext to decrypt + * @plain: Resulting plaintext + * @len: Length of the cipher text + * Returns: 0 on success, -1 on failure + * + * This function is only used with internal TLSv1 implementation + * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need + * to implement this. + */ +int __must_check crypto_cipher_decrypt(struct crypto_cipher *ctx, + const u8 *crypt, u8 *plain, size_t len); + +/** + * crypto_cipher_decrypt - Free cipher context + * @ctx: Context pointer from crypto_cipher_init() + * + * This function is only used with internal TLSv1 implementation + * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need + * to implement this. + */ +void crypto_cipher_deinit(struct crypto_cipher *ctx); + + +struct crypto_public_key; +struct crypto_private_key; + +/** + * crypto_public_key_import - Import an RSA public key + * @key: Key buffer (DER encoded RSA public key) + * @len: Key buffer length in bytes + * Returns: Pointer to the public key or %NULL on failure + * + * This function can just return %NULL if the crypto library supports X.509 + * parsing. In that case, crypto_public_key_from_cert() is used to import the + * public key from a certificate. + * + * This function is only used with internal TLSv1 implementation + * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need + * to implement this. + */ +struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len); + +struct crypto_public_key * +crypto_public_key_import_parts(const u8 *n, size_t n_len, + const u8 *e, size_t e_len); + +/** + * crypto_private_key_import - Import an RSA private key + * @key: Key buffer (DER encoded RSA private key) + * @len: Key buffer length in bytes + * @passwd: Key encryption password or %NULL if key is not encrypted + * Returns: Pointer to the private key or %NULL on failure + * + * This function is only used with internal TLSv1 implementation + * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need + * to implement this. + */ +struct crypto_private_key * crypto_private_key_import(const u8 *key, + size_t len, + const char *passwd); + +/** + * crypto_public_key_from_cert - Import an RSA public key from a certificate + * @buf: DER encoded X.509 certificate + * @len: Certificate buffer length in bytes + * Returns: Pointer to public key or %NULL on failure + * + * This function can just return %NULL if the crypto library does not support + * X.509 parsing. In that case, internal code will be used to parse the + * certificate and public key is imported using crypto_public_key_import(). + * + * This function is only used with internal TLSv1 implementation + * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need + * to implement this. + */ +struct crypto_public_key * crypto_public_key_from_cert(const u8 *buf, + size_t len); + +/** + * crypto_public_key_encrypt_pkcs1_v15 - Public key encryption (PKCS #1 v1.5) + * @key: Public key + * @in: Plaintext buffer + * @inlen: Length of plaintext buffer in bytes + * @out: Output buffer for encrypted data + * @outlen: Length of output buffer in bytes; set to used length on success + * Returns: 0 on success, -1 on failure + * + * This function is only used with internal TLSv1 implementation + * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need + * to implement this. + */ +int __must_check crypto_public_key_encrypt_pkcs1_v15( + struct crypto_public_key *key, const u8 *in, size_t inlen, + u8 *out, size_t *outlen); + +/** + * crypto_private_key_decrypt_pkcs1_v15 - Private key decryption (PKCS #1 v1.5) + * @key: Private key + * @in: Encrypted buffer + * @inlen: Length of encrypted buffer in bytes + * @out: Output buffer for encrypted data + * @outlen: Length of output buffer in bytes; set to used length on success + * Returns: 0 on success, -1 on failure + * + * This function is only used with internal TLSv1 implementation + * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need + * to implement this. + */ +int __must_check crypto_private_key_decrypt_pkcs1_v15( + struct crypto_private_key *key, const u8 *in, size_t inlen, + u8 *out, size_t *outlen); + +/** + * crypto_private_key_sign_pkcs1 - Sign with private key (PKCS #1) + * @key: Private key from crypto_private_key_import() + * @in: Plaintext buffer + * @inlen: Length of plaintext buffer in bytes + * @out: Output buffer for encrypted (signed) data + * @outlen: Length of output buffer in bytes; set to used length on success + * Returns: 0 on success, -1 on failure + * + * This function is only used with internal TLSv1 implementation + * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need + * to implement this. + */ +int __must_check crypto_private_key_sign_pkcs1(struct crypto_private_key *key, + const u8 *in, size_t inlen, + u8 *out, size_t *outlen); + +/** + * crypto_public_key_free - Free public key + * @key: Public key + * + * This function is only used with internal TLSv1 implementation + * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need + * to implement this. + */ +void crypto_public_key_free(struct crypto_public_key *key); + +/** + * crypto_private_key_free - Free private key + * @key: Private key from crypto_private_key_import() + * + * This function is only used with internal TLSv1 implementation + * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need + * to implement this. + */ +void crypto_private_key_free(struct crypto_private_key *key); + +/** + * crypto_public_key_decrypt_pkcs1 - Decrypt PKCS #1 signature + * @key: Public key + * @crypt: Encrypted signature data (using the private key) + * @crypt_len: Encrypted signature data length + * @plain: Buffer for plaintext (at least crypt_len bytes) + * @plain_len: Plaintext length (max buffer size on input, real len on output); + * Returns: 0 on success, -1 on failure + */ +int __must_check crypto_public_key_decrypt_pkcs1( + struct crypto_public_key *key, const u8 *crypt, size_t crypt_len, + u8 *plain, size_t *plain_len); + +/** + * crypto_global_init - Initialize crypto wrapper + * + * This function is only used with internal TLSv1 implementation + * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need + * to implement this. + */ +int __must_check crypto_global_init(void); + +/** + * crypto_global_deinit - Deinitialize crypto wrapper + * + * This function is only used with internal TLSv1 implementation + * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need + * to implement this. + */ +void crypto_global_deinit(void); + +/** + * crypto_mod_exp - Modular exponentiation of large integers + * @base: Base integer (big endian byte array) + * @base_len: Length of base integer in bytes + * @power: Power integer (big endian byte array) + * @power_len: Length of power integer in bytes + * @modulus: Modulus integer (big endian byte array) + * @modulus_len: Length of modulus integer in bytes + * @result: Buffer for the result + * @result_len: Result length (max buffer size on input, real len on output) + * Returns: 0 on success, -1 on failure + * + * This function calculates result = base ^ power mod modulus. modules_len is + * used as the maximum size of modulus buffer. It is set to the used size on + * success. + * + * This function is only used with internal TLSv1 implementation + * (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need + * to implement this. + */ +int __must_check crypto_mod_exp(const u8 *base, size_t base_len, + const u8 *power, size_t power_len, + const u8 *modulus, size_t modulus_len, + u8 *result, size_t *result_len); + +/** + * rc4_skip - XOR RC4 stream to given data with skip-stream-start + * @key: RC4 key + * @keylen: RC4 key length + * @skip: number of bytes to skip from the beginning of the RC4 stream + * @data: data to be XOR'ed with RC4 stream + * @data_len: buf length + * Returns: 0 on success, -1 on failure + * + * Generate RC4 pseudo random stream for the given key, skip beginning of the + * stream, and XOR the end result with the data buffer to perform RC4 + * encryption/decryption. + */ +int rc4_skip(const u8 *key, size_t keylen, size_t skip, + u8 *data, size_t data_len); + +/** + * crypto_get_random - Generate cryptographically strong pseudy-random bytes + * @buf: Buffer for data + * @len: Number of bytes to generate + * Returns: 0 on success, -1 on failure + * + * If the PRNG does not have enough entropy to ensure unpredictable byte + * sequence, this functions must return -1. + */ +int crypto_get_random(void *buf, size_t len); + + +/** + * struct crypto_bignum - bignum + * + * Internal data structure for bignum implementation. The contents is specific + * to the used crypto library. + */ +struct crypto_bignum; + +/** + * crypto_bignum_init - Allocate memory for bignum + * Returns: Pointer to allocated bignum or %NULL on failure + */ +struct crypto_bignum * crypto_bignum_init(void); + +/** + * crypto_bignum_init_set - Allocate memory for bignum and set the value + * @buf: Buffer with unsigned binary value + * @len: Length of buf in octets + * Returns: Pointer to allocated bignum or %NULL on failure + */ +struct crypto_bignum * crypto_bignum_init_set(const u8 *buf, size_t len); + +/** + * crypto_bignum_deinit - Free bignum + * @n: Bignum from crypto_bignum_init() or crypto_bignum_init_set() + * @clear: Whether to clear the value from memory + */ +void crypto_bignum_deinit(struct crypto_bignum *n, int clear); + +/** + * crypto_bignum_to_bin - Set binary buffer to unsigned bignum + * @a: Bignum + * @buf: Buffer for the binary number + * @len: Length of @buf in octets + * @padlen: Length in octets to pad the result to or 0 to indicate no padding + * Returns: Number of octets written on success, -1 on failure + */ +int crypto_bignum_to_bin(const struct crypto_bignum *a, + u8 *buf, size_t buflen, size_t padlen); + +/** + * crypto_bignum_add - c = a + b + * @a: Bignum + * @b: Bignum + * @c: Bignum; used to store the result of a + b + * Returns: 0 on success, -1 on failure + */ +int crypto_bignum_add(const struct crypto_bignum *a, + const struct crypto_bignum *b, + struct crypto_bignum *c); + +/** + * crypto_bignum_mod - c = a % b + * @a: Bignum + * @b: Bignum + * @c: Bignum; used to store the result of a % b + * Returns: 0 on success, -1 on failure + */ +int crypto_bignum_mod(const struct crypto_bignum *a, + const struct crypto_bignum *b, + struct crypto_bignum *c); + +/** + * crypto_bignum_exptmod - Modular exponentiation: d = a^b (mod c) + * @a: Bignum; base + * @b: Bignum; exponent + * @c: Bignum; modulus + * @d: Bignum; used to store the result of a^b (mod c) + * Returns: 0 on success, -1 on failure + */ +int crypto_bignum_exptmod(const struct crypto_bignum *a, + const struct crypto_bignum *b, + const struct crypto_bignum *c, + struct crypto_bignum *d); + +/** + * crypto_bignum_inverse - Inverse a bignum so that a * c = 1 (mod b) + * @a: Bignum + * @b: Bignum + * @c: Bignum; used to store the result + * Returns: 0 on success, -1 on failure + */ +int crypto_bignum_inverse(const struct crypto_bignum *a, + const struct crypto_bignum *b, + struct crypto_bignum *c); + +/** + * crypto_bignum_sub - c = a - b + * @a: Bignum + * @b: Bignum + * @c: Bignum; used to store the result of a - b + * Returns: 0 on success, -1 on failure + */ +int crypto_bignum_sub(const struct crypto_bignum *a, + const struct crypto_bignum *b, + struct crypto_bignum *c); + +/** + * crypto_bignum_div - c = a / b + * @a: Bignum + * @b: Bignum + * @c: Bignum; used to store the result of a / b + * Returns: 0 on success, -1 on failure + */ +int crypto_bignum_div(const struct crypto_bignum *a, + const struct crypto_bignum *b, + struct crypto_bignum *c); + +/** + * crypto_bignum_mulmod - d = a * b (mod c) + * @a: Bignum + * @b: Bignum + * @c: Bignum + * @d: Bignum; used to store the result of (a * b) % c + * Returns: 0 on success, -1 on failure + */ +int crypto_bignum_mulmod(const struct crypto_bignum *a, + const struct crypto_bignum *b, + const struct crypto_bignum *c, + struct crypto_bignum *d); + +/** + * crypto_bignum_cmp - Compare two bignums + * @a: Bignum + * @b: Bignum + * Returns: -1 if a < b, 0 if a == b, or 1 if a > b + */ +int crypto_bignum_cmp(const struct crypto_bignum *a, + const struct crypto_bignum *b); + +/** + * crypto_bignum_bits - Get size of a bignum in bits + * @a: Bignum + * Returns: Number of bits in the bignum + */ +int crypto_bignum_bits(const struct crypto_bignum *a); + +/** + * crypto_bignum_is_zero - Is the given bignum zero + * @a: Bignum + * Returns: 1 if @a is zero or 0 if not + */ +int crypto_bignum_is_zero(const struct crypto_bignum *a); + +/** + * crypto_bignum_is_one - Is the given bignum one + * @a: Bignum + * Returns: 1 if @a is one or 0 if not + */ +int crypto_bignum_is_one(const struct crypto_bignum *a); + +/** + * crypto_bignum_legendre - Compute the Legendre symbol (a/p) + * @a: Bignum + * @p: Bignum + * Returns: Legendre symbol -1,0,1 on success; -2 on calculation failure + */ +int crypto_bignum_legendre(const struct crypto_bignum *a, + const struct crypto_bignum *p); + +/** + * struct crypto_ec - Elliptic curve context + * + * Internal data structure for EC implementation. The contents is specific + * to the used crypto library. + */ +struct crypto_ec; + +/** + * crypto_ec_init - Initialize elliptic curve context + * @group: Identifying number for the ECC group (IANA "Group Description" + * attribute registrty for RFC 2409) + * Returns: Pointer to EC context or %NULL on failure + */ +struct crypto_ec * crypto_ec_init(int group); + +/** + * crypto_ec_deinit - Deinitialize elliptic curve context + * @e: EC context from crypto_ec_init() + */ +void crypto_ec_deinit(struct crypto_ec *e); + +/** + * crypto_ec_prime_len - Get length of the prime in octets + * @e: EC context from crypto_ec_init() + * Returns: Length of the prime defining the group + */ +size_t crypto_ec_prime_len(struct crypto_ec *e); + +/** + * crypto_ec_prime_len_bits - Get length of the prime in bits + * @e: EC context from crypto_ec_init() + * Returns: Length of the prime defining the group in bits + */ +size_t crypto_ec_prime_len_bits(struct crypto_ec *e); + +/** + * crypto_ec_get_prime - Get prime defining an EC group + * @e: EC context from crypto_ec_init() + * Returns: Prime (bignum) defining the group + */ +const struct crypto_bignum * crypto_ec_get_prime(struct crypto_ec *e); + +/** + * crypto_ec_get_order - Get order of an EC group + * @e: EC context from crypto_ec_init() + * Returns: Order (bignum) of the group + */ +const struct crypto_bignum * crypto_ec_get_order(struct crypto_ec *e); + +/** + * struct crypto_ec_point - Elliptic curve point + * + * Internal data structure for EC implementation to represent a point. The + * contents is specific to the used crypto library. + */ +struct crypto_ec_point; + +/** + * crypto_ec_point_init - Initialize data for an EC point + * @e: EC context from crypto_ec_init() + * Returns: Pointer to EC point data or %NULL on failure + */ +struct crypto_ec_point * crypto_ec_point_init(struct crypto_ec *e); + +/** + * crypto_ec_point_deinit - Deinitialize EC point data + * @p: EC point data from crypto_ec_point_init() + * @clear: Whether to clear the EC point value from memory + */ +void crypto_ec_point_deinit(struct crypto_ec_point *p, int clear); + +/** + * crypto_ec_point_to_bin - Write EC point value as binary data + * @e: EC context from crypto_ec_init() + * @p: EC point data from crypto_ec_point_init() + * @x: Buffer for writing the binary data for x coordinate or %NULL if not used + * @y: Buffer for writing the binary data for y coordinate or %NULL if not used + * Returns: 0 on success, -1 on failure + * + * This function can be used to write an EC point as binary data in a format + * that has the x and y coordinates in big endian byte order fields padded to + * the length of the prime defining the group. + */ +int crypto_ec_point_to_bin(struct crypto_ec *e, + const struct crypto_ec_point *point, u8 *x, u8 *y); + +/** + * crypto_ec_point_from_bin - Create EC point from binary data + * @e: EC context from crypto_ec_init() + * @val: Binary data to read the EC point from + * Returns: Pointer to EC point data or %NULL on failure + * + * This function readers x and y coordinates of the EC point from the provided + * buffer assuming the values are in big endian byte order with fields padded to + * the length of the prime defining the group. + */ +struct crypto_ec_point * crypto_ec_point_from_bin(struct crypto_ec *e, + const u8 *val); + +/** + * crypto_bignum_add - c = a + b + * @e: EC context from crypto_ec_init() + * @a: Bignum + * @b: Bignum + * @c: Bignum; used to store the result of a + b + * Returns: 0 on success, -1 on failure + */ +int crypto_ec_point_add(struct crypto_ec *e, const struct crypto_ec_point *a, + const struct crypto_ec_point *b, + struct crypto_ec_point *c); + +/** + * crypto_bignum_mul - res = b * p + * @e: EC context from crypto_ec_init() + * @p: EC point + * @b: Bignum + * @res: EC point; used to store the result of b * p + * Returns: 0 on success, -1 on failure + */ +int crypto_ec_point_mul(struct crypto_ec *e, const struct crypto_ec_point *p, + const struct crypto_bignum *b, + struct crypto_ec_point *res); + +/** + * crypto_ec_point_invert - Compute inverse of an EC point + * @e: EC context from crypto_ec_init() + * @p: EC point to invert (and result of the operation) + * Returns: 0 on success, -1 on failure + */ +int crypto_ec_point_invert(struct crypto_ec *e, struct crypto_ec_point *p); + +/** + * crypto_ec_point_solve_y_coord - Solve y coordinate for an x coordinate + * @e: EC context from crypto_ec_init() + * @p: EC point to use for the returning the result + * @x: x coordinate + * @y_bit: y-bit (0 or 1) for selecting the y value to use + * Returns: 0 on success, -1 on failure + */ +int crypto_ec_point_solve_y_coord(struct crypto_ec *e, + struct crypto_ec_point *p, + const struct crypto_bignum *x, int y_bit); + +/** + * crypto_ec_point_compute_y_sqr - Compute y^2 = x^3 + ax + b + * @e: EC context from crypto_ec_init() + * @x: x coordinate + * Returns: y^2 on success, %NULL failure + */ +struct crypto_bignum * +crypto_ec_point_compute_y_sqr(struct crypto_ec *e, + const struct crypto_bignum *x); + +/** + * crypto_ec_point_is_at_infinity - Check whether EC point is neutral element + * @e: EC context from crypto_ec_init() + * @p: EC point + * Returns: 1 if the specified EC point is the neutral element of the group or + * 0 if not + */ +int crypto_ec_point_is_at_infinity(struct crypto_ec *e, + const struct crypto_ec_point *p); + +/** + * crypto_ec_point_is_on_curve - Check whether EC point is on curve + * @e: EC context from crypto_ec_init() + * @p: EC point + * Returns: 1 if the specified EC point is on the curve or 0 if not + */ +int crypto_ec_point_is_on_curve(struct crypto_ec *e, + const struct crypto_ec_point *p); + +/** + * crypto_ec_point_cmp - Compare two EC points + * @e: EC context from crypto_ec_init() + * @a: EC point + * @b: EC point + * Returns: 0 on equal, non-zero otherwise + */ +int crypto_ec_point_cmp(const struct crypto_ec *e, + const struct crypto_ec_point *a, + const struct crypto_ec_point *b); + +#endif /* CRYPTO_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/crypto/crypto_ali.c b/beken_os/beken378/func/hostapd-2.5/src/crypto/crypto_ali.c new file mode 100755 index 0000000..ace5a17 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/crypto/crypto_ali.c @@ -0,0 +1,209 @@ +/* + * WPA Supplicant / wrapper functions for libalicrypto + * + */ + +#include "includes.h" + +#include "common.h" +#include "crypto.h" +#include "ali_crypto.h" + +void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher) +{ + size_t size; + void *context; + + ali_des_get_ctx_size(DES_ECB, &size); + context = os_malloc(size); + if (context == NULL) + return; + ali_des_init(DES_ECB, true, key, 64, + NULL, context); + ali_des_process(clear, cypher, 8, context); + os_free(context); +} + + +int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) +{ + size_t size; + void *context; + int i; + + ali_hash_get_ctx_size(MD5, &size); + + context = os_malloc(size); + if (context == NULL) { + return -1; + } + os_memset(context, 0, size); + + ali_hash_init(MD5, context); + for (i = 0; i < num_elem; i++) { + ali_hash_update(addr[i], len[i], context); + } + ali_hash_final(mac, context); + + os_free(context); + return 0; +} + + +int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) +{ + size_t size; + void *context; + int i; + + ali_hash_get_ctx_size(SHA1, &size); + + context = os_malloc(size); + if (context == NULL) { + return -1; + } + os_memset(context, 0, size); + + ali_hash_init(SHA1, context); + for (i = 0; i < num_elem; i++) { + ali_hash_update(addr[i], len[i], context); + } + ali_hash_final(mac, context); + + os_free(context); + return 0; +} + +int hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem, + const u8 *addr[], const size_t *len, u8 *mac) +{ + size_t size; + void *context; + int i; + + ali_hmac_get_ctx_size(SHA1, &size); + context = os_malloc(size); + if (context == NULL) { + return -1; + } + os_memset(context, 0, size); + + ali_hmac_init(SHA1, key, key_len, context); + for (i = 0; i < num_elem; i++) { + ali_hmac_update(addr[i], len[i], context); + } + ali_hmac_final(mac, context); + + os_free(context); + + return 0; +} + + +int hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len, + u8 *mac) +{ + return hmac_sha1_vector(key, key_len, 1, &data, &data_len, mac); +} + +int hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem, + const u8 *addr[], const size_t *len, u8 *mac) +{ + size_t size; + void *context; + int i; + + ali_hmac_get_ctx_size(MD5, &size); + + context = os_malloc(size); + if (context == NULL) { + return -1; + } + os_memset(context, 0, size); + + ali_hmac_init(MD5, key, key_len, context); + for (i = 0; i < num_elem; i++) { + ali_hmac_update(addr[i], len[i], context); + } + ali_hmac_final(mac, context); + + os_free(context); + return 0; +} + + +int hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len, + u8 *mac) +{ + return hmac_md5_vector(key, key_len, 1, &data, &data_len, mac); +} + +void * aes_encrypt_init(const u8 *key, size_t len) +{ + size_t size; + void *context; + int ret; + + ali_aes_get_ctx_size(AES_ECB, &size); + + context = os_malloc(size); + if (context == NULL) { + return NULL; + } + os_memset(context, 0, size); + + ret = ali_aes_init(AES_ECB, true, key, NULL, + len, NULL, context); + + if (ret != 0) { + os_free(context); + return NULL; + } + return context; +} + +void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt) +{ + ali_aes_process(plain, crypt, 16, ctx); +} + +void aes_encrypt_deinit(void *ctx) +{ + os_free(ctx); +} + +void * aes_decrypt_init(const u8 *key, size_t len) +{ + size_t size; + void *context; + int ret; + + ali_aes_get_ctx_size(AES_ECB, &size); + + context = os_malloc(size); + if (context == NULL) { + return NULL; + } + os_memset(context, 0, size); + + ret = ali_aes_init(AES_ECB, false, key, NULL, + len, NULL, context); + + if (ret != 0) { + os_free(context); + return NULL; + } + return context; +} + +void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain) +{ + ali_aes_process(crypt, plain, 16, ctx); +} + +void aes_decrypt_deinit(void *ctx) +{ + os_free(ctx); +} + + diff --git a/beken_os/beken378/func/hostapd-2.5/src/crypto/des_i.h b/beken_os/beken378/func/hostapd-2.5/src/crypto/des_i.h new file mode 100755 index 0000000..c9563d2 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/crypto/des_i.h @@ -0,0 +1,25 @@ +/* + * DES and 3DES-EDE ciphers + * Copyright (c) 2006-2009, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef DES_I_H +#define DES_I_H + +struct des3_key_s { + u32 ek[3][32]; + u32 dk[3][32]; +}; + +void des_key_setup(const u8 *key, u32 *ek, u32 *dk); +void des_block_encrypt(const u8 *plain, const u32 *ek, u8 *crypt); +void des_block_decrypt(const u8 *crypt, const u32 *dk, u8 *plain); + +void des3_key_setup(const u8 *key, struct des3_key_s *dkey); +void des3_encrypt(const u8 *plain, const struct des3_key_s *key, u8 *crypt); +void des3_decrypt(const u8 *crypt, const struct des3_key_s *key, u8 *plain); + +#endif /* DES_I_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/crypto/dh_group5.h b/beken_os/beken378/func/hostapd-2.5/src/crypto/dh_group5.h new file mode 100755 index 0000000..abee8ea --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/crypto/dh_group5.h @@ -0,0 +1,18 @@ +/* + * Diffie-Hellman group 5 operations + * Copyright (c) 2009, 2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef DH_GROUP5_H +#define DH_GROUP5_H + +void * dh5_init(struct wpabuf **priv, struct wpabuf **publ); +void * dh5_init_fixed(const struct wpabuf *priv, const struct wpabuf *publ); +struct wpabuf * dh5_derive_shared(void *ctx, const struct wpabuf *peer_public, + const struct wpabuf *own_private); +void dh5_free(void *ctx); + +#endif /* DH_GROUP5_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/crypto/dh_groups.h b/beken_os/beken378/func/hostapd-2.5/src/crypto/dh_groups.h new file mode 100755 index 0000000..d0e74b9 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/crypto/dh_groups.h @@ -0,0 +1,29 @@ +/* + * Diffie-Hellman groups + * Copyright (c) 2007, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef DH_GROUPS_H +#define DH_GROUPS_H + +struct dh_group { + int id; + const u8 *generator; + size_t generator_len; + const u8 *prime; + size_t prime_len; + const u8 *order; + size_t order_len; + unsigned int safe_prime:1; +}; + +const struct dh_group * dh_groups_get(int id); +struct wpabuf * dh_init(const struct dh_group *dh, struct wpabuf **priv); +struct wpabuf * dh_derive_shared(const struct wpabuf *peer_public, + const struct wpabuf *own_private, + const struct dh_group *dh); + +#endif /* DH_GROUPS_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/crypto/md5-internal.c b/beken_os/beken378/func/hostapd-2.5/src/crypto/md5-internal.c new file mode 100755 index 0000000..cdfaba2 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/crypto/md5-internal.c @@ -0,0 +1,287 @@ +/* + * MD5 hash implementation and interface functions + * Copyright (c) 2003-2005, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "crypto/md5.h" +#include "md5_i.h" +#include "crypto.h" + + +static void MD5Transform(u32 buf[4], u32 const in[16]); + + +typedef struct MD5Context MD5_CTX; + + +/** + * md5_vector - MD5 hash for data vector + * @num_elem: Number of elements in the data vector + * @addr: Pointers to the data areas + * @len: Lengths of the data blocks + * @mac: Buffer for the hash + * Returns: 0 on success, -1 of failure + */ +int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) +{ + MD5_CTX ctx; + size_t i; + + MD5Init(&ctx); + for (i = 0; i < num_elem; i++) + MD5Update(&ctx, addr[i], len[i]); + MD5Final(mac, &ctx); + return 0; +} + + +/* ===== start - public domain MD5 implementation ===== */ +/* + * This code implements the MD5 message-digest algorithm. + * The algorithm is due to Ron Rivest. This code was + * written by Colin Plumb in 1993, no copyright is claimed. + * This code is in the public domain; do with it what you wish. + * + * Equivalent code is available from RSA Data Security, Inc. + * This code has been tested against that, and is equivalent, + * except that you don't need to include two pages of legalese + * with every copy. + * + * To compute the message digest of a chunk of bytes, declare an + * MD5Context structure, pass it to MD5Init, call MD5Update as + * needed on buffers full of bytes, and then call MD5Final, which + * will fill a supplied 16-byte array with the digest. + */ + +#ifndef WORDS_BIGENDIAN +#define byteReverse(buf, len) /* Nothing */ +#else +/* + * Note: this code is harmless on little-endian machines. + */ +static void byteReverse(unsigned char *buf, unsigned longs) +{ + u32 t; + do { + t = (u32) ((unsigned) buf[3] << 8 | buf[2]) << 16 | + ((unsigned) buf[1] << 8 | buf[0]); + *(u32 *) buf = t; + buf += 4; + } while (--longs); +} +#endif + +/* + * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious + * initialization constants. + */ +void MD5Init(struct MD5Context *ctx) +{ + ctx->buf[0] = 0x67452301; + ctx->buf[1] = 0xefcdab89; + ctx->buf[2] = 0x98badcfe; + ctx->buf[3] = 0x10325476; + + ctx->bits[0] = 0; + ctx->bits[1] = 0; +} + +/* + * Update context to reflect the concatenation of another buffer full + * of bytes. + */ +void MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len) +{ + u32 t; + + /* Update bitcount */ + + t = ctx->bits[0]; + if ((ctx->bits[0] = t + ((u32) len << 3)) < t) + ctx->bits[1]++; /* Carry from low to high */ + ctx->bits[1] += len >> 29; + + t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */ + + /* Handle any leading odd-sized chunks */ + + if (t) { + unsigned char *p = (unsigned char *) ctx->in + t; + + t = 64 - t; + if (len < t) { + os_memcpy(p, buf, len); + return; + } + os_memcpy(p, buf, t); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (u32 *) ctx->in); + buf += t; + len -= t; + } + /* Process data in 64-byte chunks */ + + while (len >= 64) { + os_memcpy(ctx->in, buf, 64); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (u32 *) ctx->in); + buf += 64; + len -= 64; + } + + /* Handle any remaining bytes of data. */ + + os_memcpy(ctx->in, buf, len); +} + +/* + * Final wrapup - pad to 64-byte boundary with the bit pattern + * 1 0* (64-bit count of bits processed, MSB-first) + */ +void MD5Final(unsigned char digest[16], struct MD5Context *ctx) +{ + unsigned count; + unsigned char *p; + + /* Compute number of bytes mod 64 */ + count = (ctx->bits[0] >> 3) & 0x3F; + + /* Set the first char of padding to 0x80. This is safe since there is + always at least one byte free */ + p = ctx->in + count; + *p++ = 0x80; + + /* Bytes of padding needed to make 64 bytes */ + count = 64 - 1 - count; + + /* Pad out to 56 mod 64 */ + if (count < 8) { + /* Two lots of padding: Pad the first block to 64 bytes */ + os_memset(p, 0, count); + byteReverse(ctx->in, 16); + MD5Transform(ctx->buf, (u32 *) ctx->in); + + /* Now fill the next block with 56 bytes */ + os_memset(ctx->in, 0, 56); + } else { + /* Pad block to 56 bytes */ + os_memset(p, 0, count - 8); + } + byteReverse(ctx->in, 14); + + /* Append length in bits and transform */ + ((u32 *) aliasing_hide_typecast(ctx->in, u32))[14] = ctx->bits[0]; + ((u32 *) aliasing_hide_typecast(ctx->in, u32))[15] = ctx->bits[1]; + + MD5Transform(ctx->buf, (u32 *) ctx->in); + byteReverse((unsigned char *) ctx->buf, 4); + os_memcpy(digest, ctx->buf, 16); + os_memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */ +} + +/* The four core functions - F1 is optimized somewhat */ + +/* #define F1(x, y, z) (x & y | ~x & z) */ +#define F1(x, y, z) (z ^ (x & (y ^ z))) +#define F2(x, y, z) F1(z, x, y) +#define F3(x, y, z) (x ^ y ^ z) +#define F4(x, y, z) (y ^ (x | ~z)) + +/* This is the central step in the MD5 algorithm. */ +#define MD5STEP(f, w, x, y, z, data, s) \ + ( w += f(x, y, z) + data, w = w<>(32-s), w += x ) + +/* + * The core of the MD5 algorithm, this alters an existing MD5 hash to + * reflect the addition of 16 longwords of new data. MD5Update blocks + * the data and converts bytes into longwords for this routine. + */ +static void MD5Transform(u32 buf[4], u32 const in[16]) +{ + register u32 a, b, c, d; + + a = buf[0]; + b = buf[1]; + c = buf[2]; + d = buf[3]; + + MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17); + MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17); + MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22); + MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7); + MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7); + MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12); + MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17); + MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9); + MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9); + MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11); + MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23); + MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6); + MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10); + MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15); + MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21); + + buf[0] += a; + buf[1] += b; + buf[2] += c; + buf[3] += d; +} +/* ===== end - public domain MD5 implementation ===== */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/crypto/md5.c b/beken_os/beken378/func/hostapd-2.5/src/crypto/md5.c new file mode 100755 index 0000000..3892bc2 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/crypto/md5.c @@ -0,0 +1,109 @@ +/* + * MD5 hash implementation and interface functions + * Copyright (c) 2003-2005, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "crypto/md5.h" +#include "crypto.h" + + +/** + * hmac_md5_vector - HMAC-MD5 over data vector (RFC 2104) + * @key: Key for HMAC operations + * @key_len: Length of the key in bytes + * @num_elem: Number of elements in the data vector + * @addr: Pointers to the data areas + * @len: Lengths of the data blocks + * @mac: Buffer for the hash (16 bytes) + * Returns: 0 on success, -1 on failure + */ +int hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem, + const u8 *addr[], const size_t *len, u8 *mac) +{ + u8 k_pad[64]; /* padding - key XORd with ipad/opad */ + u8 tk[16]; + const u8 *_addr[6]; + size_t i, _len[6]; + int res; + + if (num_elem > 5) { + /* + * Fixed limit on the number of fragments to avoid having to + * allocate memory (which could fail). + */ + return -1; + } + + /* if key is longer than 64 bytes reset it to key = MD5(key) */ + if (key_len > 64) { + if (md5_vector(1, &key, &key_len, tk)) + return -1; + key = tk; + key_len = 16; + } + + /* the HMAC_MD5 transform looks like: + * + * MD5(K XOR opad, MD5(K XOR ipad, text)) + * + * where K is an n byte key + * ipad is the byte 0x36 repeated 64 times + * opad is the byte 0x5c repeated 64 times + * and text is the data being protected */ + + /* start out by storing key in ipad */ + os_memset(k_pad, 0, sizeof(k_pad)); + os_memcpy(k_pad, key, key_len); + + /* XOR key with ipad values */ + for (i = 0; i < 64; i++) + k_pad[i] ^= 0x36; + + /* perform inner MD5 */ + _addr[0] = k_pad; + _len[0] = 64; + for (i = 0; i < num_elem; i++) { + _addr[i + 1] = addr[i]; + _len[i + 1] = len[i]; + } + if (md5_vector(1 + num_elem, _addr, _len, mac)) + return -1; + + os_memset(k_pad, 0, sizeof(k_pad)); + os_memcpy(k_pad, key, key_len); + /* XOR key with opad values */ + for (i = 0; i < 64; i++) + k_pad[i] ^= 0x5c; + + /* perform outer MD5 */ + _addr[0] = k_pad; + _len[0] = 64; + _addr[1] = mac; + _len[1] = MD5_MAC_LEN; + res = md5_vector(2, _addr, _len, mac); + os_memset(k_pad, 0, sizeof(k_pad)); + os_memset(tk, 0, sizeof(tk)); + return res; +} + + +/** + * hmac_md5 - HMAC-MD5 over data buffer (RFC 2104) + * @key: Key for HMAC operations + * @key_len: Length of the key in bytes + * @data: Pointers to the data area + * @data_len: Length of the data area + * @mac: Buffer for the hash (16 bytes) + * Returns: 0 on success, -1 on failure + */ +int hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len, + u8 *mac) +{ + return hmac_md5_vector(key, key_len, 1, &data, &data_len, mac); +} diff --git a/beken_os/beken378/func/hostapd-2.5/src/crypto/md5.h b/beken_os/beken378/func/hostapd-2.5/src/crypto/md5.h new file mode 100755 index 0000000..33f8426 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/crypto/md5.h @@ -0,0 +1,19 @@ +/* + * MD5 hash implementation and interface functions + * Copyright (c) 2003-2009, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef MD5_H +#define MD5_H + +#define MD5_MAC_LEN 16 + +int hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem, + const u8 *addr[], const size_t *len, u8 *mac); +int hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len, + u8 *mac); + +#endif /* MD5_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/crypto/md5_i.h b/beken_os/beken378/func/hostapd-2.5/src/crypto/md5_i.h new file mode 100755 index 0000000..7dfc100 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/crypto/md5_i.h @@ -0,0 +1,23 @@ +/* + * MD5 internal definitions + * Copyright (c) 2003-2005, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef MD5_I_H +#define MD5_I_H + +struct MD5Context { + u32 buf[4]; + u32 bits[2]; + u8 in[64]; +}; + +void MD5Init(struct MD5Context *context); +void MD5Update(struct MD5Context *context, unsigned char const *buf, + unsigned len); +void MD5Final(unsigned char digest[16], struct MD5Context *context); + +#endif /* MD5_I_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/crypto/milenage.h b/beken_os/beken378/func/hostapd-2.5/src/crypto/milenage.h new file mode 100755 index 0000000..62137d9 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/crypto/milenage.h @@ -0,0 +1,27 @@ +/* + * UMTS AKA - Milenage algorithm (3GPP TS 35.205, .206, .207, .208) + * Copyright (c) 2006-2007 + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef MILENAGE_H +#define MILENAGE_H + +void milenage_generate(const u8 *opc, const u8 *amf, const u8 *k, + const u8 *sqn, const u8 *_rand, u8 *autn, u8 *ik, + u8 *ck, u8 *res, size_t *res_len); +int milenage_auts(const u8 *opc, const u8 *k, const u8 *_rand, const u8 *auts, + u8 *sqn); +int gsm_milenage(const u8 *opc, const u8 *k, const u8 *_rand, u8 *sres, + u8 *kc); +int milenage_check(const u8 *opc, const u8 *k, const u8 *sqn, const u8 *_rand, + const u8 *autn, u8 *ik, u8 *ck, u8 *res, size_t *res_len, + u8 *auts); +int milenage_f1(const u8 *opc, const u8 *k, const u8 *_rand, + const u8 *sqn, const u8 *amf, u8 *mac_a, u8 *mac_s); +int milenage_f2345(const u8 *opc, const u8 *k, const u8 *_rand, + u8 *res, u8 *ck, u8 *ik, u8 *ak, u8 *akstar); + +#endif /* MILENAGE_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/crypto/ms_funcs.h b/beken_os/beken378/func/hostapd-2.5/src/crypto/ms_funcs.h new file mode 100755 index 0000000..b5b5918 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/crypto/ms_funcs.h @@ -0,0 +1,60 @@ +/* + * WPA Supplicant / shared MSCHAPV2 helper functions / RFC 2433 / RFC 2759 + * Copyright (c) 2004-2009, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef MS_FUNCS_H +#define MS_FUNCS_H + +int generate_nt_response(const u8 *auth_challenge, const u8 *peer_challenge, + const u8 *username, size_t username_len, + const u8 *password, size_t password_len, + u8 *response); +int generate_nt_response_pwhash(const u8 *auth_challenge, + const u8 *peer_challenge, + const u8 *username, size_t username_len, + const u8 *password_hash, + u8 *response); +int generate_authenticator_response(const u8 *password, size_t password_len, + const u8 *peer_challenge, + const u8 *auth_challenge, + const u8 *username, size_t username_len, + const u8 *nt_response, u8 *response); +int generate_authenticator_response_pwhash( + const u8 *password_hash, + const u8 *peer_challenge, const u8 *auth_challenge, + const u8 *username, size_t username_len, + const u8 *nt_response, u8 *response); +int nt_challenge_response(const u8 *challenge, const u8 *password, + size_t password_len, u8 *response); + +void challenge_response(const u8 *challenge, const u8 *password_hash, + u8 *response); +int challenge_hash(const u8 *peer_challenge, const u8 *auth_challenge, + const u8 *username, size_t username_len, u8 *challenge); +int nt_password_hash(const u8 *password, size_t password_len, + u8 *password_hash); +int hash_nt_password_hash(const u8 *password_hash, u8 *password_hash_hash); +int get_master_key(const u8 *password_hash_hash, const u8 *nt_response, + u8 *master_key); +int get_asymetric_start_key(const u8 *master_key, u8 *session_key, + size_t session_key_len, int is_send, + int is_server); +int __must_check encrypt_pw_block_with_password_hash( + const u8 *password, size_t password_len, + const u8 *password_hash, u8 *pw_block); +int __must_check new_password_encrypted_with_old_nt_password_hash( + const u8 *new_password, size_t new_password_len, + const u8 *old_password, size_t old_password_len, + u8 *encrypted_pw_block); +void nt_password_hash_encrypted_with_block(const u8 *password_hash, + const u8 *block, u8 *cypher); +int old_nt_password_hash_encrypted_with_new_nt_password_hash( + const u8 *new_password, size_t new_password_len, + const u8 *old_password, size_t old_password_len, + u8 *encrypted_password_hash); + +#endif /* MS_FUNCS_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/crypto/random.h b/beken_os/beken378/func/hostapd-2.5/src/crypto/random.h new file mode 100755 index 0000000..d13e1c4 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/crypto/random.h @@ -0,0 +1,28 @@ +/* + * Random number generator + * Copyright (c) 2010-2011, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef RANDOM_H +#define RANDOM_H + +#ifdef CONFIG_NO_RANDOM_POOL +#define random_init(e) do { } while (0) +#define random_deinit() do { } while (0) +#define random_add_randomness(b, l) do { } while (0) +#define random_get_bytes(b, l) os_get_random((b), (l)) +#define random_pool_ready() 1 +#define random_mark_pool_ready() do { } while (0) +#else /* CONFIG_NO_RANDOM_POOL */ +void random_init(const char *entropy_file); +void random_deinit(void); +void random_add_randomness(const void *buf, size_t len); +int random_get_bytes(void *buf, size_t len); +int random_pool_ready(void); +void random_mark_pool_ready(void); +#endif /* CONFIG_NO_RANDOM_POOL */ + +#endif /* RANDOM_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/crypto/rc4.c b/beken_os/beken378/func/hostapd-2.5/src/crypto/rc4.c new file mode 100755 index 0000000..98ae269 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/crypto/rc4.c @@ -0,0 +1,54 @@ +/* + * RC4 stream cipher + * Copyright (c) 2002-2005, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "crypto.h" + +#define S_SWAP(a,b) do { u8 t = S[a]; S[a] = S[b]; S[b] = t; } while(0) + +int rc4_skip(const u8 *key, size_t keylen, size_t skip, + u8 *data, size_t data_len) +{ + u32 i, j, k; + u8 S[256], *pos; + size_t kpos; + + /* Setup RC4 state */ + for (i = 0; i < 256; i++) + S[i] = i; + j = 0; + kpos = 0; + for (i = 0; i < 256; i++) { + j = (j + S[i] + key[kpos]) & 0xff; + kpos++; + if (kpos >= keylen) + kpos = 0; + S_SWAP(i, j); + } + + /* Skip the start of the stream */ + i = j = 0; + for (k = 0; k < skip; k++) { + i = (i + 1) & 0xff; + j = (j + S[i]) & 0xff; + S_SWAP(i, j); + } + + /* Apply RC4 to data */ + pos = data; + for (k = 0; k < data_len; k++) { + i = (i + 1) & 0xff; + j = (j + S[i]) & 0xff; + S_SWAP(i, j); + *pos++ ^= S[(S[i] + S[j]) & 0xff]; + } + + return 0; +} diff --git a/beken_os/beken378/func/hostapd-2.5/src/crypto/sha1-internal.c b/beken_os/beken378/func/hostapd-2.5/src/crypto/sha1-internal.c new file mode 100755 index 0000000..45fed2f --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/crypto/sha1-internal.c @@ -0,0 +1,304 @@ +/* + * SHA1 hash implementation and interface functions + * Copyright (c) 2003-2005, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "crypto/sha1.h" +#include "sha1_i.h" +#include "crypto/md5.h" +#include "crypto.h" + +typedef struct SHA1Context SHA1_CTX; + +void SHA1Transform(u32 state[5], const unsigned char buffer[64]); + + +#ifdef CONFIG_CRYPTO_INTERNAL +/** + * sha1_vector - SHA-1 hash for data vector + * @num_elem: Number of elements in the data vector + * @addr: Pointers to the data areas + * @len: Lengths of the data blocks + * @mac: Buffer for the hash + * Returns: 0 on success, -1 of failure + */ +int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) +{ + SHA1_CTX ctx; + size_t i; + + SHA1Init(&ctx); + for (i = 0; i < num_elem; i++) + SHA1Update(&ctx, addr[i], len[i]); + SHA1Final(mac, &ctx); + return 0; +} +#endif /* CONFIG_CRYPTO_INTERNAL */ + + +/* ===== start - public domain SHA1 implementation ===== */ + +/* +SHA-1 in C +By Steve Reid +100% Public Domain + +----------------- +Modified 7/98 +By James H. Brown +Still 100% Public Domain + +Corrected a problem which generated improper hash values on 16 bit machines +Routine SHA1Update changed from + void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int +len) +to + void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned +long len) + +The 'len' parameter was declared an int which works fine on 32 bit machines. +However, on 16 bit machines an int is too small for the shifts being done +against +it. This caused the hash function to generate incorrect values if len was +greater than 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update(). + +Since the file IO in main() reads 16K at a time, any file 8K or larger would +be guaranteed to generate the wrong hash (e.g. Test Vector #3, a million +"a"s). + +I also changed the declaration of variables i & j in SHA1Update to +unsigned long from unsigned int for the same reason. + +These changes should make no difference to any 32 bit implementations since +an +int and a long are the same size in those environments. + +-- +I also corrected a few compiler warnings generated by Borland C. +1. Added #include for exit() prototype +2. Removed unused variable 'j' in SHA1Final +3. Changed exit(0) to return(0) at end of main. + +ALL changes I made can be located by searching for comments containing 'JHB' +----------------- +Modified 8/98 +By Steve Reid +Still 100% public domain + +1- Removed #include and used return() instead of exit() +2- Fixed overwriting of finalcount in SHA1Final() (discovered by Chris Hall) +3- Changed email address from steve@edmweb.com to sreid@sea-to-sky.net + +----------------- +Modified 4/01 +By Saul Kravitz +Still 100% PD +Modified to run on Compaq Alpha hardware. + +----------------- +Modified 4/01 +By Jouni Malinen +Minor changes to match the coding style used in Dynamics. + +Modified September 24, 2004 +By Jouni Malinen +Fixed alignment issue in SHA1Transform when SHA1HANDSOFF is defined. + +*/ + +/* +Test Vectors (from FIPS PUB 180-1) +"abc" + A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D +"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" + 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 +A million repetitions of "a" + 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F +*/ + +#define SHA1HANDSOFF + +#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits)))) + +/* blk0() and blk() perform the initial expand. */ +/* I got the idea of expanding during the round function from SSLeay */ +#ifndef WORDS_BIGENDIAN +#define blk0(i) (block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) | \ + (rol(block->l[i], 8) & 0x00FF00FF)) +#else +#define blk0(i) block->l[i] +#endif +#define blk(i) (block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ \ + block->l[(i + 8) & 15] ^ block->l[(i + 2) & 15] ^ block->l[i & 15], 1)) + +/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ +#define R0(v,w,x,y,z,i) \ + z += ((w & (x ^ y)) ^ y) + blk0(i) + 0x5A827999 + rol(v, 5); \ + w = rol(w, 30); +#define R1(v,w,x,y,z,i) \ + z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \ + w = rol(w, 30); +#define R2(v,w,x,y,z,i) \ + z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); w = rol(w, 30); +#define R3(v,w,x,y,z,i) \ + z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \ + w = rol(w, 30); +#define R4(v,w,x,y,z,i) \ + z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \ + w=rol(w, 30); + + +#ifdef VERBOSE /* SAK */ +void SHAPrintContext(SHA1_CTX *context, char *msg) +{ + os_printf("%s (%d,%d) %x %x %x %x %x\n", + msg, + context->count[0], context->count[1], + context->state[0], + context->state[1], + context->state[2], + context->state[3], + context->state[4]); +} +#endif + +/* Hash a single 512-bit block. This is the core of the algorithm. */ + +void SHA1Transform(u32 state[5], const unsigned char buffer[64]) +{ + u32 a, b, c, d, e; + typedef union { + unsigned char c[64]; + u32 l[16]; + } CHAR64LONG16; + CHAR64LONG16* block; +#ifdef SHA1HANDSOFF + CHAR64LONG16 workspace; + block = &workspace; + os_memcpy(block, buffer, 64); +#else + block = (CHAR64LONG16 *) buffer; +#endif + /* Copy context->state[] to working vars */ + a = state[0]; + b = state[1]; + c = state[2]; + d = state[3]; + e = state[4]; + /* 4 rounds of 20 operations each. Loop unrolled. */ + R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); + R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); + R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); + R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); + R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); + R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); + R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); + R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); + R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); + R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); + R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); + R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); + R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); + R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); + R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); + R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); + R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); + R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); + R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); + R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); + /* Add the working vars back into context.state[] */ + state[0] += a; + state[1] += b; + state[2] += c; + state[3] += d; + state[4] += e; + /* Wipe variables */ + a = b = c = d = e = 0; +#ifdef SHA1HANDSOFF + os_memset(block, 0, 64); +#endif +} + + +/* SHA1Init - Initialize new context */ + +void SHA1Init(SHA1_CTX* context) +{ + /* SHA1 initialization constants */ + context->state[0] = 0x67452301; + context->state[1] = 0xEFCDAB89; + context->state[2] = 0x98BADCFE; + context->state[3] = 0x10325476; + context->state[4] = 0xC3D2E1F0; + context->count[0] = context->count[1] = 0; +} + + +/* Run your data through this. */ + +void SHA1Update(SHA1_CTX* context, const void *_data, u32 len) +{ + u32 i, j; + const unsigned char *data = _data; + +#ifdef VERBOSE + SHAPrintContext(context, "before"); +#endif + j = (context->count[0] >> 3) & 63; + if ((context->count[0] += len << 3) < (len << 3)) + context->count[1]++; + context->count[1] += (len >> 29); + if ((j + len) > 63) { + os_memcpy(&context->buffer[j], data, (i = 64-j)); + SHA1Transform(context->state, context->buffer); + for ( ; i + 63 < len; i += 64) { + SHA1Transform(context->state, &data[i]); + } + j = 0; + } + else i = 0; + os_memcpy(&context->buffer[j], &data[i], len - i); +#ifdef VERBOSE + SHAPrintContext(context, "after "); +#endif +} + + +/* Add padding and return the message digest. */ + +void SHA1Final(unsigned char digest[20], SHA1_CTX* context) +{ + u32 i; + unsigned char finalcount[8]; + + for (i = 0; i < 8; i++) { + finalcount[i] = (unsigned char) + ((context->count[(i >= 4 ? 0 : 1)] >> + ((3-(i & 3)) * 8) ) & 255); /* Endian independent */ + } + SHA1Update(context, (unsigned char *) "\200", 1); + while ((context->count[0] & 504) != 448) { + SHA1Update(context, (unsigned char *) "\0", 1); + } + SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() + */ + for (i = 0; i < 20; i++) { + digest[i] = (unsigned char) + ((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) & + 255); + } + /* Wipe variables */ + i = 0; + os_memset(context->buffer, 0, 64); + os_memset(context->state, 0, 20); + os_memset(context->count, 0, 8); + os_memset(finalcount, 0, 8); +} + +/* ===== end - public domain SHA1 implementation ===== */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/crypto/sha1-pbkdf2.c b/beken_os/beken378/func/hostapd-2.5/src/crypto/sha1-pbkdf2.c new file mode 100755 index 0000000..1c7a565 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/crypto/sha1-pbkdf2.c @@ -0,0 +1,92 @@ +/* + * SHA1-based key derivation function (PBKDF2) for IEEE 802.11i + * Copyright (c) 2003-2005, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "crypto/sha1.h" + +static int pbkdf2_sha1_f(const char *passphrase, const u8 *ssid, + size_t ssid_len, int iterations, unsigned int count, + u8 *digest) +{ + unsigned char tmp[SHA1_MAC_LEN], tmp2[SHA1_MAC_LEN]; + int i, j; + unsigned char count_buf[4]; + const u8 *addr[2]; + size_t len[2]; + size_t passphrase_len = os_strlen(passphrase); + + addr[0] = ssid; + len[0] = ssid_len; + addr[1] = count_buf; + len[1] = 4; + + /* F(P, S, c, i) = U1 xor U2 xor ... Uc + * U1 = PRF(P, S || i) + * U2 = PRF(P, U1) + * Uc = PRF(P, Uc-1) + */ + + count_buf[0] = (count >> 24) & 0xff; + count_buf[1] = (count >> 16) & 0xff; + count_buf[2] = (count >> 8) & 0xff; + count_buf[3] = count & 0xff; + if (hmac_sha1_vector((u8 *) passphrase, passphrase_len, 2, addr, len, + tmp)) + return -1; + os_memcpy(digest, tmp, SHA1_MAC_LEN); + + for (i = 1; i < iterations; i++) { + if (hmac_sha1((u8 *) passphrase, passphrase_len, tmp, + SHA1_MAC_LEN, tmp2)) + return -1; + os_memcpy(tmp, tmp2, SHA1_MAC_LEN); + for (j = 0; j < SHA1_MAC_LEN; j++) + digest[j] ^= tmp2[j]; + } + + return 0; +} + + +/** + * pbkdf2_sha1 - SHA1-based key derivation function (PBKDF2) for IEEE 802.11i + * @passphrase: ASCII passphrase + * @ssid: SSID + * @ssid_len: SSID length in bytes + * @iterations: Number of iterations to run + * @buf: Buffer for the generated key + * @buflen: Length of the buffer in bytes + * Returns: 0 on success, -1 of failure + * + * This function is used to derive PSK for WPA-PSK. For this protocol, + * iterations is set to 4096 and buflen to 32. This function is described in + * IEEE Std 802.11-2004, Clause H.4. The main construction is from PKCS#5 v2.0. + */ +int pbkdf2_sha1(const char *passphrase, const u8 *ssid, size_t ssid_len, + int iterations, u8 *buf, size_t buflen) +{ + unsigned int count = 0; + unsigned char *pos = buf; + size_t left = buflen, plen; + unsigned char digest[SHA1_MAC_LEN]; + + while (left > 0) { + count++; + if (pbkdf2_sha1_f(passphrase, ssid, ssid_len, iterations, + count, digest)) + return -1; + plen = left > SHA1_MAC_LEN ? SHA1_MAC_LEN : left; + os_memcpy(pos, digest, plen); + pos += plen; + left -= plen; + } + + return 0; +} diff --git a/beken_os/beken378/func/hostapd-2.5/src/crypto/sha1-prf.c b/beken_os/beken378/func/hostapd-2.5/src/crypto/sha1-prf.c new file mode 100755 index 0000000..e3e49d1 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/crypto/sha1-prf.c @@ -0,0 +1,67 @@ +/* + * SHA1-based PRF + * Copyright (c) 2003-2005, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "crypto/sha1.h" +#include "crypto.h" + + +/** + * sha1_prf - SHA1-based Pseudo-Random Function (PRF) (IEEE 802.11i, 8.5.1.1) + * @key: Key for PRF + * @key_len: Length of the key in bytes + * @label: A unique label for each purpose of the PRF + * @data: Extra data to bind into the key + * @data_len: Length of the data + * @buf: Buffer for the generated pseudo-random key + * @buf_len: Number of bytes of key to generate + * Returns: 0 on success, -1 of failure + * + * This function is used to derive new, cryptographically separate keys from a + * given key (e.g., PMK in IEEE 802.11i). + */ +int sha1_prf(const u8 *key, size_t key_len, const char *label, + const u8 *data, size_t data_len, u8 *buf, size_t buf_len) +{ + u8 counter = 0; + size_t pos, plen; + u8 hash[SHA1_MAC_LEN]; + size_t label_len = os_strlen(label) + 1; + const unsigned char *addr[3]; + size_t len[3]; + + addr[0] = (u8 *) label; + len[0] = label_len; + addr[1] = data; + len[1] = data_len; + addr[2] = &counter; + len[2] = 1; + + pos = 0; + while (pos < buf_len) { + plen = buf_len - pos; + if (plen >= SHA1_MAC_LEN) { + if (hmac_sha1_vector(key, key_len, 3, addr, len, + &buf[pos])) + return -1; + pos += SHA1_MAC_LEN; + } else { + if (hmac_sha1_vector(key, key_len, 3, addr, len, + hash)) + return -1; + os_memcpy(&buf[pos], hash, plen); + break; + } + counter++; + } + os_memset(hash, 0, sizeof(hash)); + + return 0; +} diff --git a/beken_os/beken378/func/hostapd-2.5/src/crypto/sha1.c b/beken_os/beken378/func/hostapd-2.5/src/crypto/sha1.c new file mode 100755 index 0000000..2653b81 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/crypto/sha1.c @@ -0,0 +1,107 @@ +/* + * SHA1 hash implementation and interface functions + * Copyright (c) 2003-2005, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "crypto/sha1.h" +#include "crypto.h" + + +/** + * hmac_sha1_vector - HMAC-SHA1 over data vector (RFC 2104) + * @key: Key for HMAC operations + * @key_len: Length of the key in bytes + * @num_elem: Number of elements in the data vector + * @addr: Pointers to the data areas + * @len: Lengths of the data blocks + * @mac: Buffer for the hash (20 bytes) + * Returns: 0 on success, -1 on failure + */ +int hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem, + const u8 *addr[], const size_t *len, u8 *mac) +{ + unsigned char k_pad[64]; /* padding - key XORd with ipad/opad */ + unsigned char tk[20]; + const u8 *_addr[6]; + size_t _len[6], i; + int ret; + + if (num_elem > 5) { + /* + * Fixed limit on the number of fragments to avoid having to + * allocate memory (which could fail). + */ + return -1; + } + + /* if key is longer than 64 bytes reset it to key = SHA1(key) */ + if (key_len > 64) { + if (sha1_vector(1, &key, &key_len, tk)) + return -1; + key = tk; + key_len = 20; + } + + /* the HMAC_SHA1 transform looks like: + * + * SHA1(K XOR opad, SHA1(K XOR ipad, text)) + * + * where K is an n byte key + * ipad is the byte 0x36 repeated 64 times + * opad is the byte 0x5c repeated 64 times + * and text is the data being protected */ + + /* start out by storing key in ipad */ + os_memset(k_pad, 0, sizeof(k_pad)); + os_memcpy(k_pad, key, key_len); + /* XOR key with ipad values */ + for (i = 0; i < 64; i++) + k_pad[i] ^= 0x36; + + /* perform inner SHA1 */ + _addr[0] = k_pad; + _len[0] = 64; + for (i = 0; i < num_elem; i++) { + _addr[i + 1] = addr[i]; + _len[i + 1] = len[i]; + } + if (sha1_vector(1 + num_elem, _addr, _len, mac)) + return -1; + + os_memset(k_pad, 0, sizeof(k_pad)); + os_memcpy(k_pad, key, key_len); + /* XOR key with opad values */ + for (i = 0; i < 64; i++) + k_pad[i] ^= 0x5c; + + /* perform outer SHA1 */ + _addr[0] = k_pad; + _len[0] = 64; + _addr[1] = mac; + _len[1] = SHA1_MAC_LEN; + ret = sha1_vector(2, _addr, _len, mac); + os_memset(k_pad, 0, sizeof(k_pad)); + return ret; +} + + +/** + * hmac_sha1 - HMAC-SHA1 over data buffer (RFC 2104) + * @key: Key for HMAC operations + * @key_len: Length of the key in bytes + * @data: Pointers to the data area + * @data_len: Length of the data area + * @mac: Buffer for the hash (20 bytes) + * Returns: 0 on success, -1 of failure + */ +int hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len, + u8 *mac) +{ + return hmac_sha1_vector(key, key_len, 1, &data, &data_len, mac); +} diff --git a/beken_os/beken378/func/hostapd-2.5/src/crypto/sha1.h b/beken_os/beken378/func/hostapd-2.5/src/crypto/sha1.h new file mode 100755 index 0000000..933cd81 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/crypto/sha1.h @@ -0,0 +1,27 @@ +/* + * SHA1 hash implementation and interface functions + * Copyright (c) 2003-2009, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef SHA1_H +#define SHA1_H + +#define SHA1_MAC_LEN 20 + +int hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem, + const u8 *addr[], const size_t *len, u8 *mac); +int hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len, + u8 *mac); +int sha1_prf(const u8 *key, size_t key_len, const char *label, + const u8 *data, size_t data_len, u8 *buf, size_t buf_len); +int sha1_t_prf(const u8 *key, size_t key_len, const char *label, + const u8 *seed, size_t seed_len, u8 *buf, size_t buf_len); +int __must_check tls_prf_sha1_md5(const u8 *secret, size_t secret_len, + const char *label, const u8 *seed, + size_t seed_len, u8 *out, size_t outlen); +int pbkdf2_sha1(const char *passphrase, const u8 *ssid, size_t ssid_len, + int iterations, u8 *buf, size_t buflen); +#endif /* SHA1_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/crypto/sha1_i.h b/beken_os/beken378/func/hostapd-2.5/src/crypto/sha1_i.h new file mode 100755 index 0000000..d3bce29 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/crypto/sha1_i.h @@ -0,0 +1,25 @@ +/* + * SHA1 internal definitions + * Copyright (c) 2003-2005, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef SHA1_I_H +#define SHA1_I_H + +#define CONFIG_CRYPTO_INTERNAL 1 + +struct SHA1Context { + u32 state[5]; + u32 count[2]; + unsigned char buffer[64]; +}; + +void SHA1Init(struct SHA1Context *context); +void SHA1Update(struct SHA1Context *context, const void *data, u32 len); +void SHA1Final(unsigned char digest[20], struct SHA1Context *context); +void SHA1Transform(u32 state[5], const unsigned char buffer[64]); + +#endif /* SHA1_I_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/crypto/sha256.h b/beken_os/beken378/func/hostapd-2.5/src/crypto/sha256.h new file mode 100755 index 0000000..b15f511 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/crypto/sha256.h @@ -0,0 +1,30 @@ +/* + * SHA256 hash implementation and interface functions + * Copyright (c) 2003-2014, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef SHA256_H +#define SHA256_H + +#define SHA256_MAC_LEN 32 + +int hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem, + const u8 *addr[], const size_t *len, u8 *mac); +int hmac_sha256(const u8 *key, size_t key_len, const u8 *data, + size_t data_len, u8 *mac); +void sha256_prf(const u8 *key, size_t key_len, const char *label, + const u8 *data, size_t data_len, u8 *buf, size_t buf_len); +void sha256_prf_bits(const u8 *key, size_t key_len, const char *label, + const u8 *data, size_t data_len, u8 *buf, + size_t buf_len_bits); +void tls_prf_sha256(const u8 *secret, size_t secret_len, + const char *label, const u8 *seed, size_t seed_len, + u8 *out, size_t outlen); +int hmac_sha256_kdf(const u8 *secret, size_t secret_len, + const char *label, const u8 *seed, size_t seed_len, + u8 *out, size_t outlen); + +#endif /* SHA256_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/crypto/sha256_i.h b/beken_os/beken378/func/hostapd-2.5/src/crypto/sha256_i.h new file mode 100755 index 0000000..a502d2b --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/crypto/sha256_i.h @@ -0,0 +1,25 @@ +/* + * SHA-256 internal definitions + * Copyright (c) 2003-2011, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef SHA256_I_H +#define SHA256_I_H + +#define SHA256_BLOCK_SIZE 64 + +struct sha256_state { + u64 length; + u32 state[8], curlen; + u8 buf[SHA256_BLOCK_SIZE]; +}; + +void sha256_init(struct sha256_state *md); +int sha256_process(struct sha256_state *md, const unsigned char *in, + unsigned long inlen); +int sha256_done(struct sha256_state *md, unsigned char *out); + +#endif /* SHA256_I_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/crypto/sha384.h b/beken_os/beken378/func/hostapd-2.5/src/crypto/sha384.h new file mode 100755 index 0000000..3deafa5 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/crypto/sha384.h @@ -0,0 +1,24 @@ +/* + * SHA384 hash implementation and interface functions + * Copyright (c) 2015, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef SHA384_H +#define SHA384_H + +#define SHA384_MAC_LEN 48 + +int hmac_sha384_vector(const u8 *key, size_t key_len, size_t num_elem, + const u8 *addr[], const size_t *len, u8 *mac); +int hmac_sha384(const u8 *key, size_t key_len, const u8 *data, + size_t data_len, u8 *mac); +void sha384_prf(const u8 *key, size_t key_len, const char *label, + const u8 *data, size_t data_len, u8 *buf, size_t buf_len); +void sha384_prf_bits(const u8 *key, size_t key_len, const char *label, + const u8 *data, size_t data_len, u8 *buf, + size_t buf_len_bits); + +#endif /* SHA384_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/crypto/tls.h b/beken_os/beken378/func/hostapd-2.5/src/crypto/tls.h new file mode 100755 index 0000000..2e56233 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/crypto/tls.h @@ -0,0 +1,588 @@ +/* + * SSL/TLS interface definition + * Copyright (c) 2004-2013, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef TLS_H +#define TLS_H + +struct tls_connection; + +struct tls_random { + const u8 *client_random; + size_t client_random_len; + const u8 *server_random; + size_t server_random_len; +}; + +enum tls_event { + TLS_CERT_CHAIN_SUCCESS, + TLS_CERT_CHAIN_FAILURE, + TLS_PEER_CERTIFICATE, + TLS_ALERT +}; + +/* + * Note: These are used as identifier with external programs and as such, the + * values must not be changed. + */ +enum tls_fail_reason { + TLS_FAIL_UNSPECIFIED = 0, + TLS_FAIL_UNTRUSTED = 1, + TLS_FAIL_REVOKED = 2, + TLS_FAIL_NOT_YET_VALID = 3, + TLS_FAIL_EXPIRED = 4, + TLS_FAIL_SUBJECT_MISMATCH = 5, + TLS_FAIL_ALTSUBJECT_MISMATCH = 6, + TLS_FAIL_BAD_CERTIFICATE = 7, + TLS_FAIL_SERVER_CHAIN_PROBE = 8, + TLS_FAIL_DOMAIN_SUFFIX_MISMATCH = 9, + TLS_FAIL_DOMAIN_MISMATCH = 10, +}; + + +#define TLS_MAX_ALT_SUBJECT 10 + +union tls_event_data { + struct { + int depth; + const char *subject; + enum tls_fail_reason reason; + const char *reason_txt; + const struct wpabuf *cert; + } cert_fail; + + struct { + int depth; + const char *subject; + const struct wpabuf *cert; + const u8 *hash; + size_t hash_len; + const char *altsubject[TLS_MAX_ALT_SUBJECT]; + int num_altsubject; + } peer_cert; + + struct { + int is_local; + const char *type; + const char *description; + } alert; +}; + +struct tls_config { + const char *opensc_engine_path; + const char *pkcs11_engine_path; + const char *pkcs11_module_path; + int fips_mode; + int cert_in_cb; + const char *openssl_ciphers; + unsigned int tls_session_lifetime; + + void (*event_cb)(void *ctx, enum tls_event ev, + union tls_event_data *data); + void *cb_ctx; +}; + +#define TLS_CONN_ALLOW_SIGN_RSA_MD5 BIT(0) +#define TLS_CONN_DISABLE_TIME_CHECKS BIT(1) +#define TLS_CONN_DISABLE_SESSION_TICKET BIT(2) +#define TLS_CONN_REQUEST_OCSP BIT(3) +#define TLS_CONN_REQUIRE_OCSP BIT(4) +#define TLS_CONN_DISABLE_TLSv1_1 BIT(5) +#define TLS_CONN_DISABLE_TLSv1_2 BIT(6) +#define TLS_CONN_EAP_FAST BIT(7) +#define TLS_CONN_DISABLE_TLSv1_0 BIT(8) + +/** + * struct tls_connection_params - Parameters for TLS connection + * @ca_cert: File or reference name for CA X.509 certificate in PEM or DER + * format + * @ca_cert_blob: ca_cert as inlined data or %NULL if not used + * @ca_cert_blob_len: ca_cert_blob length + * @ca_path: Path to CA certificates (OpenSSL specific) + * @subject_match: String to match in the subject of the peer certificate or + * %NULL to allow all subjects + * @altsubject_match: String to match in the alternative subject of the peer + * certificate or %NULL to allow all alternative subjects + * @suffix_match: String to suffix match in the dNSName or CN of the peer + * certificate or %NULL to allow all domain names. This may allow subdomains an + * wildcard certificates. Each domain name label must have a full match. + * @domain_match: String to match in the dNSName or CN of the peer + * certificate or %NULL to allow all domain names. This requires a full, + * case-insensitive match. + * @client_cert: File or reference name for client X.509 certificate in PEM or + * DER format + * @client_cert_blob: client_cert as inlined data or %NULL if not used + * @client_cert_blob_len: client_cert_blob length + * @private_key: File or reference name for client private key in PEM or DER + * format (traditional format (RSA PRIVATE KEY) or PKCS#8 (PRIVATE KEY) + * @private_key_blob: private_key as inlined data or %NULL if not used + * @private_key_blob_len: private_key_blob length + * @private_key_passwd: Passphrase for decrypted private key, %NULL if no + * passphrase is used. + * @dh_file: File name for DH/DSA data in PEM format, or %NULL if not used + * @dh_blob: dh_file as inlined data or %NULL if not used + * @dh_blob_len: dh_blob length + * @engine: 1 = use engine (e.g., a smartcard) for private key operations + * (this is OpenSSL specific for now) + * @engine_id: engine id string (this is OpenSSL specific for now) + * @ppin: pointer to the pin variable in the configuration + * (this is OpenSSL specific for now) + * @key_id: the private key's id when using engine (this is OpenSSL + * specific for now) + * @cert_id: the certificate's id when using engine + * @ca_cert_id: the CA certificate's id when using engine + * @openssl_ciphers: OpenSSL cipher configuration + * @flags: Parameter options (TLS_CONN_*) + * @ocsp_stapling_response: DER encoded file with cached OCSP stapling response + * or %NULL if OCSP is not enabled + * + * TLS connection parameters to be configured with tls_connection_set_params() + * and tls_global_set_params(). + * + * Certificates and private key can be configured either as a reference name + * (file path or reference to certificate store) or by providing the same data + * as a pointer to the data in memory. Only one option will be used for each + * field. + */ +struct tls_connection_params { + const char *ca_cert; + const u8 *ca_cert_blob; + size_t ca_cert_blob_len; + const char *ca_path; + const char *subject_match; + const char *altsubject_match; + const char *suffix_match; + const char *domain_match; + const char *client_cert; + const u8 *client_cert_blob; + size_t client_cert_blob_len; + const char *private_key; + const u8 *private_key_blob; + size_t private_key_blob_len; + const char *private_key_passwd; + const char *dh_file; + const u8 *dh_blob; + size_t dh_blob_len; + + /* OpenSSL specific variables */ + int engine; + const char *engine_id; + const char *pin; + const char *key_id; + const char *cert_id; + const char *ca_cert_id; + const char *openssl_ciphers; + + unsigned int flags; + const char *ocsp_stapling_response; +}; + + +/** + * tls_init - Initialize TLS library + * @conf: Configuration data for TLS library + * Returns: Context data to be used as tls_ctx in calls to other functions, + * or %NULL on failure. + * + * Called once during program startup and once for each RSN pre-authentication + * session. In other words, there can be two concurrent TLS contexts. If global + * library initialization is needed (i.e., one that is shared between both + * authentication types), the TLS library wrapper should maintain a reference + * counter and do global initialization only when moving from 0 to 1 reference. + */ +void * tls_init(const struct tls_config *conf); + +/** + * tls_deinit - Deinitialize TLS library + * @tls_ctx: TLS context data from tls_init() + * + * Called once during program shutdown and once for each RSN pre-authentication + * session. If global library deinitialization is needed (i.e., one that is + * shared between both authentication types), the TLS library wrapper should + * maintain a reference counter and do global deinitialization only when moving + * from 1 to 0 references. + */ +void tls_deinit(void *tls_ctx); + +/** + * tls_get_errors - Process pending errors + * @tls_ctx: TLS context data from tls_init() + * Returns: Number of found error, 0 if no errors detected. + * + * Process all pending TLS errors. + */ +int tls_get_errors(void *tls_ctx); + +/** + * tls_connection_init - Initialize a new TLS connection + * @tls_ctx: TLS context data from tls_init() + * Returns: Connection context data, conn for other function calls + */ +struct tls_connection * tls_connection_init(void *tls_ctx); + +/** + * tls_connection_deinit - Free TLS connection data + * @tls_ctx: TLS context data from tls_init() + * @conn: Connection context data from tls_connection_init() + * + * Release all resources allocated for TLS connection. + */ +void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn); + +/** + * tls_connection_established - Has the TLS connection been completed? + * @tls_ctx: TLS context data from tls_init() + * @conn: Connection context data from tls_connection_init() + * Returns: 1 if TLS connection has been completed, 0 if not. + */ +int tls_connection_established(void *tls_ctx, struct tls_connection *conn); + +/** + * tls_connection_shutdown - Shutdown TLS connection + * @tls_ctx: TLS context data from tls_init() + * @conn: Connection context data from tls_connection_init() + * Returns: 0 on success, -1 on failure + * + * Shutdown current TLS connection without releasing all resources. New + * connection can be started by using the same conn without having to call + * tls_connection_init() or setting certificates etc. again. The new + * connection should try to use session resumption. + */ +int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn); + +enum { + TLS_SET_PARAMS_ENGINE_PRV_BAD_PIN = -4, + TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED = -3, + TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED = -2 +}; + +/** + * tls_connection_set_params - Set TLS connection parameters + * @tls_ctx: TLS context data from tls_init() + * @conn: Connection context data from tls_connection_init() + * @params: Connection parameters + * Returns: 0 on success, -1 on failure, + * TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED (-2) on error causing PKCS#11 engine + * failure, or + * TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED (-3) on failure to verify the + * PKCS#11 engine private key, or + * TLS_SET_PARAMS_ENGINE_PRV_BAD_PIN (-4) on PIN error causing PKCS#11 engine + * failure. + */ +int __must_check +tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, + const struct tls_connection_params *params); + +/** + * tls_global_set_params - Set TLS parameters for all TLS connection + * @tls_ctx: TLS context data from tls_init() + * @params: Global TLS parameters + * Returns: 0 on success, -1 on failure, + * TLS_SET_PARAMS_ENGINE_PRV_INIT_FAILED (-2) on error causing PKCS#11 engine + * failure, or + * TLS_SET_PARAMS_ENGINE_PRV_VERIFY_FAILED (-3) on failure to verify the + * PKCS#11 engine private key, or + * TLS_SET_PARAMS_ENGINE_PRV_BAD_PIN (-4) on PIN error causing PKCS#11 engine + * failure. + */ +int __must_check tls_global_set_params( + void *tls_ctx, const struct tls_connection_params *params); + +/** + * tls_global_set_verify - Set global certificate verification options + * @tls_ctx: TLS context data from tls_init() + * @check_crl: 0 = do not verify CRLs, 1 = verify CRL for the user certificate, + * 2 = verify CRL for all certificates + * Returns: 0 on success, -1 on failure + */ +int __must_check tls_global_set_verify(void *tls_ctx, int check_crl); + +/** + * tls_connection_set_verify - Set certificate verification options + * @tls_ctx: TLS context data from tls_init() + * @conn: Connection context data from tls_connection_init() + * @verify_peer: 1 = verify peer certificate + * @flags: Connection flags (TLS_CONN_*) + * @session_ctx: Session caching context or %NULL to use default + * @session_ctx_len: Length of @session_ctx in bytes. + * Returns: 0 on success, -1 on failure + */ +int __must_check tls_connection_set_verify(void *tls_ctx, + struct tls_connection *conn, + int verify_peer, + unsigned int flags, + const u8 *session_ctx, + size_t session_ctx_len); + +/** + * tls_connection_get_random - Get random data from TLS connection + * @tls_ctx: TLS context data from tls_init() + * @conn: Connection context data from tls_connection_init() + * @data: Structure of client/server random data (filled on success) + * Returns: 0 on success, -1 on failure + */ +int __must_check tls_connection_get_random(void *tls_ctx, + struct tls_connection *conn, + struct tls_random *data); + +/** + * tls_connection_prf - Use TLS-PRF to derive keying material + * @tls_ctx: TLS context data from tls_init() + * @conn: Connection context data from tls_connection_init() + * @label: Label (e.g., description of the key) for PRF + * @server_random_first: seed is 0 = client_random|server_random, + * 1 = server_random|client_random + * @skip_keyblock: Skip TLS key block from the beginning of PRF output + * @out: Buffer for output data from TLS-PRF + * @out_len: Length of the output buffer + * Returns: 0 on success, -1 on failure + * + * tls_connection_prf() is required so that further keying material can be + * derived from the master secret. Example implementation of this function is in + * tls_prf_sha1_md5() when it is called with seed set to + * client_random|server_random (or server_random|client_random). For TLSv1.2 and + * newer, a different PRF is needed, though. + */ +int __must_check tls_connection_prf(void *tls_ctx, + struct tls_connection *conn, + const char *label, + int server_random_first, + int skip_keyblock, + u8 *out, size_t out_len); + +/** + * tls_connection_handshake - Process TLS handshake (client side) + * @tls_ctx: TLS context data from tls_init() + * @conn: Connection context data from tls_connection_init() + * @in_data: Input data from TLS server + * @appl_data: Pointer to application data pointer, or %NULL if dropped + * Returns: Output data, %NULL on failure + * + * The caller is responsible for freeing the returned output data. If the final + * handshake message includes application data, this is decrypted and + * appl_data (if not %NULL) is set to point this data. The caller is + * responsible for freeing appl_data. + * + * This function is used during TLS handshake. The first call is done with + * in_data == %NULL and the library is expected to return ClientHello packet. + * This packet is then send to the server and a response from server is given + * to TLS library by calling this function again with in_data pointing to the + * TLS message from the server. + * + * If the TLS handshake fails, this function may return %NULL. However, if the + * TLS library has a TLS alert to send out, that should be returned as the + * output data. In this case, tls_connection_get_failed() must return failure + * (> 0). + * + * tls_connection_established() should return 1 once the TLS handshake has been + * completed successfully. + */ +struct wpabuf * tls_connection_handshake(void *tls_ctx, + struct tls_connection *conn, + const struct wpabuf *in_data, + struct wpabuf **appl_data); + +struct wpabuf * tls_connection_handshake2(void *tls_ctx, + struct tls_connection *conn, + const struct wpabuf *in_data, + struct wpabuf **appl_data, + int *more_data_needed); + +/** + * tls_connection_server_handshake - Process TLS handshake (server side) + * @tls_ctx: TLS context data from tls_init() + * @conn: Connection context data from tls_connection_init() + * @in_data: Input data from TLS peer + * @appl_data: Pointer to application data pointer, or %NULL if dropped + * Returns: Output data, %NULL on failure + * + * The caller is responsible for freeing the returned output data. + */ +struct wpabuf * tls_connection_server_handshake(void *tls_ctx, + struct tls_connection *conn, + const struct wpabuf *in_data, + struct wpabuf **appl_data); + +/** + * tls_connection_encrypt - Encrypt data into TLS tunnel + * @tls_ctx: TLS context data from tls_init() + * @conn: Connection context data from tls_connection_init() + * @in_data: Plaintext data to be encrypted + * Returns: Encrypted TLS data or %NULL on failure + * + * This function is used after TLS handshake has been completed successfully to + * send data in the encrypted tunnel. The caller is responsible for freeing the + * returned output data. + */ +struct wpabuf * tls_connection_encrypt(void *tls_ctx, + struct tls_connection *conn, + const struct wpabuf *in_data); + +/** + * tls_connection_decrypt - Decrypt data from TLS tunnel + * @tls_ctx: TLS context data from tls_init() + * @conn: Connection context data from tls_connection_init() + * @in_data: Encrypted TLS data + * Returns: Decrypted TLS data or %NULL on failure + * + * This function is used after TLS handshake has been completed successfully to + * receive data from the encrypted tunnel. The caller is responsible for + * freeing the returned output data. + */ +struct wpabuf * tls_connection_decrypt(void *tls_ctx, + struct tls_connection *conn, + const struct wpabuf *in_data); + +struct wpabuf * tls_connection_decrypt2(void *tls_ctx, + struct tls_connection *conn, + const struct wpabuf *in_data, + int *more_data_needed); + +/** + * tls_connection_resumed - Was session resumption used + * @tls_ctx: TLS context data from tls_init() + * @conn: Connection context data from tls_connection_init() + * Returns: 1 if current session used session resumption, 0 if not + */ +int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn); + +enum { + TLS_CIPHER_NONE, + TLS_CIPHER_RC4_SHA /* 0x0005 */, + TLS_CIPHER_AES128_SHA /* 0x002f */, + TLS_CIPHER_RSA_DHE_AES128_SHA /* 0x0031 */, + TLS_CIPHER_ANON_DH_AES128_SHA /* 0x0034 */ +}; + +/** + * tls_connection_set_cipher_list - Configure acceptable cipher suites + * @tls_ctx: TLS context data from tls_init() + * @conn: Connection context data from tls_connection_init() + * @ciphers: Zero (TLS_CIPHER_NONE) terminated list of allowed ciphers + * (TLS_CIPHER_*). + * Returns: 0 on success, -1 on failure + */ +int __must_check tls_connection_set_cipher_list(void *tls_ctx, + struct tls_connection *conn, + u8 *ciphers); + +/** + * tls_get_version - Get the current TLS version number + * @tls_ctx: TLS context data from tls_init() + * @conn: Connection context data from tls_connection_init() + * @buf: Buffer for returning the TLS version number + * @buflen: buf size + * Returns: 0 on success, -1 on failure + * + * Get the currently used TLS version number. + */ +int __must_check tls_get_version(void *tls_ctx, struct tls_connection *conn, + char *buf, size_t buflen); + +/** + * tls_get_cipher - Get current cipher name + * @tls_ctx: TLS context data from tls_init() + * @conn: Connection context data from tls_connection_init() + * @buf: Buffer for the cipher name + * @buflen: buf size + * Returns: 0 on success, -1 on failure + * + * Get the name of the currently used cipher. + */ +int __must_check tls_get_cipher(void *tls_ctx, struct tls_connection *conn, + char *buf, size_t buflen); + +/** + * tls_connection_enable_workaround - Enable TLS workaround options + * @tls_ctx: TLS context data from tls_init() + * @conn: Connection context data from tls_connection_init() + * Returns: 0 on success, -1 on failure + * + * This function is used to enable connection-specific workaround options for + * buffer SSL/TLS implementations. + */ +int __must_check tls_connection_enable_workaround(void *tls_ctx, + struct tls_connection *conn); + +/** + * tls_connection_client_hello_ext - Set TLS extension for ClientHello + * @tls_ctx: TLS context data from tls_init() + * @conn: Connection context data from tls_connection_init() + * @ext_type: Extension type + * @data: Extension payload (%NULL to remove extension) + * @data_len: Extension payload length + * Returns: 0 on success, -1 on failure + */ +int __must_check tls_connection_client_hello_ext(void *tls_ctx, + struct tls_connection *conn, + int ext_type, const u8 *data, + size_t data_len); + +/** + * tls_connection_get_failed - Get connection failure status + * @tls_ctx: TLS context data from tls_init() + * @conn: Connection context data from tls_connection_init() + * + * Returns >0 if connection has failed, 0 if not. + */ +int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn); + +/** + * tls_connection_get_read_alerts - Get connection read alert status + * @tls_ctx: TLS context data from tls_init() + * @conn: Connection context data from tls_connection_init() + * Returns: Number of times a fatal read (remote end reported error) has + * happened during this connection. + */ +int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn); + +/** + * tls_connection_get_write_alerts - Get connection write alert status + * @tls_ctx: TLS context data from tls_init() + * @conn: Connection context data from tls_connection_init() + * Returns: Number of times a fatal write (locally detected error) has happened + * during this connection. + */ +int tls_connection_get_write_alerts(void *tls_ctx, + struct tls_connection *conn); + +typedef int (*tls_session_ticket_cb) +(void *ctx, const u8 *ticket, size_t len, const u8 *client_random, + const u8 *server_random, u8 *master_secret); + +int __must_check tls_connection_set_session_ticket_cb( + void *tls_ctx, struct tls_connection *conn, + tls_session_ticket_cb cb, void *ctx); + +void tls_connection_set_log_cb(struct tls_connection *conn, + void (*log_cb)(void *ctx, const char *msg), + void *ctx); + +#define TLS_BREAK_VERIFY_DATA BIT(0) +#define TLS_BREAK_SRV_KEY_X_HASH BIT(1) +#define TLS_BREAK_SRV_KEY_X_SIGNATURE BIT(2) +#define TLS_DHE_PRIME_511B BIT(3) +#define TLS_DHE_PRIME_767B BIT(4) +#define TLS_DHE_PRIME_15 BIT(5) +#define TLS_DHE_PRIME_58B BIT(6) +#define TLS_DHE_NON_PRIME BIT(7) + +void tls_connection_set_test_flags(struct tls_connection *conn, u32 flags); + +int tls_get_library_version(char *buf, size_t buf_len); + +void tls_connection_set_success_data(struct tls_connection *conn, + struct wpabuf *data); + +void tls_connection_set_success_data_resumed(struct tls_connection *conn); + +const struct wpabuf * +tls_connection_get_success_data(struct tls_connection *conn); + +void tls_connection_remove_session(struct tls_connection *conn); + +#endif /* TLS_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/crypto/tls_none.c b/beken_os/beken378/func/hostapd-2.5/src/crypto/tls_none.c new file mode 100755 index 0000000..ae392ad --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/crypto/tls_none.c @@ -0,0 +1,218 @@ +/* + * SSL/TLS interface functions for no TLS case + * Copyright (c) 2004-2009, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "tls.h" + +void * tls_init(const struct tls_config *conf) +{ + return (void *) 1; +} + + +void tls_deinit(void *ssl_ctx) +{ +} + + +int tls_get_errors(void *tls_ctx) +{ + return 0; +} + + +struct tls_connection * tls_connection_init(void *tls_ctx) +{ + return NULL; +} + + +void tls_connection_deinit(void *tls_ctx, struct tls_connection *conn) +{ +} + + +int tls_connection_established(void *tls_ctx, struct tls_connection *conn) +{ + return -1; +} + + +int tls_connection_shutdown(void *tls_ctx, struct tls_connection *conn) +{ + return -1; +} + + +int tls_connection_set_params(void *tls_ctx, struct tls_connection *conn, + const struct tls_connection_params *params) +{ + return -1; +} + + +int tls_global_set_params(void *tls_ctx, + const struct tls_connection_params *params) +{ + return -1; +} + + +int tls_global_set_verify(void *tls_ctx, int check_crl) +{ + return -1; +} + + +int tls_connection_set_verify(void *tls_ctx, struct tls_connection *conn, + int verify_peer, unsigned int flags, + const u8 *session_ctx, size_t session_ctx_len) +{ + return -1; +} + + +int tls_connection_get_random(void *tls_ctx, struct tls_connection *conn, + struct tls_random *data) +{ + return -1; +} + + +int tls_connection_prf(void *tls_ctx, struct tls_connection *conn, + const char *label, int server_random_first, + int skip_keyblock, u8 *out, size_t out_len) +{ + return -1; +} + + +struct wpabuf * tls_connection_handshake(void *tls_ctx, + struct tls_connection *conn, + const struct wpabuf *in_data, + struct wpabuf **appl_data) +{ + return NULL; +} + + +struct wpabuf * tls_connection_server_handshake(void *tls_ctx, + struct tls_connection *conn, + const struct wpabuf *in_data, + struct wpabuf **appl_data) +{ + return NULL; +} + + +struct wpabuf * tls_connection_encrypt(void *tls_ctx, + struct tls_connection *conn, + const struct wpabuf *in_data) +{ + return NULL; +} + + +struct wpabuf * tls_connection_decrypt(void *tls_ctx, + struct tls_connection *conn, + const struct wpabuf *in_data) +{ + return NULL; +} + + +int tls_connection_resumed(void *tls_ctx, struct tls_connection *conn) +{ + return 0; +} + + +int tls_connection_set_cipher_list(void *tls_ctx, struct tls_connection *conn, + u8 *ciphers) +{ + return -1; +} + + +int tls_get_version(void *ssl_ctx, struct tls_connection *conn, + char *buf, size_t buflen) +{ + return -1; +} + + +int tls_get_cipher(void *tls_ctx, struct tls_connection *conn, + char *buf, size_t buflen) +{ + return -1; +} + + +int tls_connection_enable_workaround(void *tls_ctx, + struct tls_connection *conn) +{ + return -1; +} + + +int tls_connection_client_hello_ext(void *tls_ctx, struct tls_connection *conn, + int ext_type, const u8 *data, + size_t data_len) +{ + return -1; +} + + +int tls_connection_get_failed(void *tls_ctx, struct tls_connection *conn) +{ + return 0; +} + + +int tls_connection_get_read_alerts(void *tls_ctx, struct tls_connection *conn) +{ + return 0; +} + + +int tls_connection_get_write_alerts(void *tls_ctx, + struct tls_connection *conn) +{ + return 0; +} + + +int tls_get_library_version(char *buf, size_t buf_len) +{ + return os_snprintf(buf, buf_len, "none"); +} + + +void tls_connection_set_success_data(struct tls_connection *conn, + struct wpabuf *data) +{ +} + + +void tls_connection_set_success_data_resumed(struct tls_connection *conn) +{ +} + + +const struct wpabuf * +tls_connection_get_success_data(struct tls_connection *conn) +{ + return NULL; +} + + +void tls_connection_remove_session(struct tls_connection *conn) +{ +} diff --git a/beken_os/beken378/func/hostapd-2.5/src/drivers/driver.h b/beken_os/beken378/func/hostapd-2.5/src/drivers/driver.h new file mode 100755 index 0000000..eadadf4 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/drivers/driver.h @@ -0,0 +1,4706 @@ +/* + * Driver interface definition + * Copyright (c) 2003-2015, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + * + * This file defines a driver interface used by both %wpa_supplicant and + * hostapd. The first part of the file defines data structures used in various + * driver operations. This is followed by the struct wpa_driver_ops that each + * driver wrapper will beed to define with callback functions for requesting + * driver operations. After this, there are definitions for driver event + * reporting with wpa_supplicant_event() and some convenience helper functions + * that can be used to report events. + */ + +#ifndef DRIVER_H +#define DRIVER_H + +#define WPA_SUPPLICANT_DRIVER_VERSION 4 + +#include "common/defs.h" +#include "common/ieee802_11_defs.h" +#include "utils/list.h" + +#define HOSTAPD_CHAN_DISABLED 0x00000001 +#define HOSTAPD_CHAN_NO_IR 0x00000002 +#define HOSTAPD_CHAN_RADAR 0x00000008 +#define HOSTAPD_CHAN_HT40PLUS 0x00000010 +#define HOSTAPD_CHAN_HT40MINUS 0x00000020 +#define HOSTAPD_CHAN_HT40 0x00000040 +#define HOSTAPD_CHAN_SURVEY_LIST_INITIALIZED 0x00000080 + +#define HOSTAPD_CHAN_DFS_UNKNOWN 0x00000000 +#define HOSTAPD_CHAN_DFS_USABLE 0x00000100 +#define HOSTAPD_CHAN_DFS_UNAVAILABLE 0x00000200 +#define HOSTAPD_CHAN_DFS_AVAILABLE 0x00000300 +#define HOSTAPD_CHAN_DFS_MASK 0x00000300 + +#define HOSTAPD_CHAN_VHT_10_70 0x00000800 +#define HOSTAPD_CHAN_VHT_30_50 0x00001000 +#define HOSTAPD_CHAN_VHT_50_30 0x00002000 +#define HOSTAPD_CHAN_VHT_70_10 0x00004000 + +#define HOSTAPD_CHAN_INDOOR_ONLY 0x00010000 +#define HOSTAPD_CHAN_GO_CONCURRENT 0x00020000 + +/** + * enum reg_change_initiator - Regulatory change initiator + */ +enum reg_change_initiator { + REGDOM_SET_BY_CORE, + REGDOM_SET_BY_USER, + REGDOM_SET_BY_DRIVER, + REGDOM_SET_BY_COUNTRY_IE, + REGDOM_BEACON_HINT, +}; + +/** + * enum reg_type - Regulatory change types + */ +enum reg_type { + REGDOM_TYPE_UNKNOWN, + REGDOM_TYPE_COUNTRY, + REGDOM_TYPE_WORLD, + REGDOM_TYPE_CUSTOM_WORLD, + REGDOM_TYPE_INTERSECTION, +}; + +/** + * struct hostapd_channel_data - Channel information + */ +struct hostapd_channel_data { + /** + * chan - Channel number (IEEE 802.11) + */ + short chan; + + /** + * freq - Frequency in MHz + */ + int freq; + + /** + * flag - Channel flags (HOSTAPD_CHAN_*) + */ + int flag; + + /** + * max_tx_power - Regulatory transmit power limit in dBm + */ + u8 max_tx_power; + + /** + * survey_list - Linked list of surveys (struct freq_survey) + */ + struct dl_list survey_list; + + /** + * min_nf - Minimum observed noise floor, in dBm, based on all + * surveyed channel data + */ + s8 min_nf; + +#ifdef CONFIG_ACS + /** + * interference_factor - Computed interference factor on this + * channel (used internally in src/ap/acs.c; driver wrappers do not + * need to set this) + */ + long double interference_factor; +#endif /* CONFIG_ACS */ + + /** + * dfs_cac_ms - DFS CAC time in milliseconds + */ + unsigned int dfs_cac_ms; +}; + +#define HOSTAPD_MODE_FLAG_HT_INFO_KNOWN BIT(0) +#define HOSTAPD_MODE_FLAG_VHT_INFO_KNOWN BIT(1) + +/** + * struct hostapd_hw_modes - Supported hardware mode information + */ +struct hostapd_hw_modes { + /** + * mode - Hardware mode + */ + enum hostapd_hw_mode mode; + + /** + * num_channels - Number of entries in the channels array + */ + int num_channels; + + /** + * channels - Array of supported channels + */ + struct hostapd_channel_data *channels; + + /** + * num_rates - Number of entries in the rates array + */ + int num_rates; + + /** + * rates - Array of supported rates in 100 kbps units + */ + int *rates; + + /** + * ht_capab - HT (IEEE 802.11n) capabilities + */ + u16 ht_capab; + + /** + * mcs_set - MCS (IEEE 802.11n) rate parameters + */ + u8 mcs_set[16]; + + /** + * a_mpdu_params - A-MPDU (IEEE 802.11n) parameters + */ + u8 a_mpdu_params; + + /** + * vht_capab - VHT (IEEE 802.11ac) capabilities + */ + u32 vht_capab; + + /** + * vht_mcs_set - VHT MCS (IEEE 802.11ac) rate parameters + */ + u8 vht_mcs_set[8]; + + unsigned int flags; /* HOSTAPD_MODE_FLAG_* */ +}; + + +#define IEEE80211_MODE_INFRA 0 +#define IEEE80211_MODE_IBSS 1 +#define IEEE80211_MODE_AP 2 +#define IEEE80211_MODE_MESH 5 + +#define IEEE80211_CAP_ESS 0x0001 +#define IEEE80211_CAP_IBSS 0x0002 +#define IEEE80211_CAP_PRIVACY 0x0010 +#define IEEE80211_CAP_RRM 0x1000 + +/* DMG (60 GHz) IEEE 802.11ad */ +/* type - bits 0..1 */ +#define IEEE80211_CAP_DMG_MASK 0x0003 +#define IEEE80211_CAP_DMG_IBSS 0x0001 /* Tx by: STA */ +#define IEEE80211_CAP_DMG_PBSS 0x0002 /* Tx by: PCP */ +#define IEEE80211_CAP_DMG_AP 0x0003 /* Tx by: AP */ + +#define WPA_SCAN_QUAL_INVALID BIT(0) +#define WPA_SCAN_NOISE_INVALID BIT(1) +#define WPA_SCAN_LEVEL_INVALID BIT(2) +#define WPA_SCAN_LEVEL_DBM BIT(3) +#define WPA_SCAN_ASSOCIATED BIT(5) + +/** + * struct wpa_scan_res - Scan result for an BSS/IBSS + * @flags: information flags about the BSS/IBSS (WPA_SCAN_*) + * @bssid: BSSID + * @freq: frequency of the channel in MHz (e.g., 2412 = channel 1) + * @beacon_int: beacon interval in TUs (host byte order) + * @caps: capability information field in host byte order + * @qual: signal quality + * @noise: noise level + * @level: signal level + * @tsf: Timestamp + * @age: Age of the information in milliseconds (i.e., how many milliseconds + * ago the last Beacon or Probe Response frame was received) + * @est_throughput: Estimated throughput in kbps (this is calculated during + * scan result processing if left zero by the driver wrapper) + * @snr: Signal-to-noise ratio in dB (calculated during scan result processing) + * @ie_len: length of the following IE field in octets + * @beacon_ie_len: length of the following Beacon IE field in octets + * + * This structure is used as a generic format for scan results from the + * driver. Each driver interface implementation is responsible for converting + * the driver or OS specific scan results into this format. + * + * If the driver does not support reporting all IEs, the IE data structure is + * constructed of the IEs that are available. This field will also need to + * include SSID in IE format. All drivers are encouraged to be extended to + * report all IEs to make it easier to support future additions. + * + * This structure data is followed by ie_len octets of IEs from Probe Response + * frame (or if the driver does not indicate source of IEs, these may also be + * from Beacon frame). After the first set of IEs, another set of IEs may follow + * (with beacon_ie_len octets of data) if the driver provides both IE sets. + */ +struct wpa_scan_res { + unsigned int flags; + u8 bssid[ETH_ALEN]; + int freq; + u16 beacon_int; + u16 caps; + int qual; + int noise; + int level; + u64 tsf; + unsigned int age; + unsigned int est_throughput; + int snr; + size_t ie_len; + size_t beacon_ie_len; + /* Followed by ie_len + beacon_ie_len octets of IE data */ +}; + +/** + * struct wpa_scan_results - Scan results + * @res: Array of pointers to allocated variable length scan result entries + * @num: Number of entries in the scan result array + * @fetch_time: Time when the results were fetched from the driver + */ +struct wpa_scan_results { + struct wpa_scan_res **res; + size_t num; + struct os_reltime fetch_time; +}; + +/** + * struct wpa_interface_info - Network interface information + * @next: Pointer to the next interface or NULL if this is the last one + * @ifname: Interface name that can be used with init() or init2() + * @desc: Human readable adapter description (e.g., vendor/model) or NULL if + * not available + * @drv_name: struct wpa_driver_ops::name (note: unlike other strings, this one + * is not an allocated copy, i.e., get_interfaces() caller will not free + * this) + */ +struct wpa_interface_info { + struct wpa_interface_info *next; + char *ifname; + char *desc; + const char *drv_name; +}; + +#define WPAS_MAX_SCAN_SSIDS 16 + +/** + * struct wpa_driver_scan_params - Scan parameters + * Data for struct wpa_driver_ops::scan2(). + */ +struct wpa_driver_scan_params { + /** + * ssids - SSIDs to scan for + */ + struct wpa_driver_scan_ssid { + /** + * ssid - specific SSID to scan for (ProbeReq) + * %NULL or zero-length SSID is used to indicate active scan + * with wildcard SSID. + */ + const u8 *ssid; + /** + * ssid_len: Length of the SSID in octets + */ + size_t ssid_len; + } ssids[WPAS_MAX_SCAN_SSIDS]; + + /** + * num_ssids - Number of entries in ssids array + * Zero indicates a request for a passive scan. + */ + size_t num_ssids; + + /** + * extra_ies - Extra IE(s) to add into Probe Request or %NULL + */ + const u8 *extra_ies; + + /** + * extra_ies_len - Length of extra_ies in octets + */ + size_t extra_ies_len; + + /** + * freqs - Array of frequencies to scan or %NULL for all frequencies + * + * The frequency is set in MHz. The array is zero-terminated. + */ + int *freqs; + + /** + * filter_ssids - Filter for reporting SSIDs + * + * This optional parameter can be used to request the driver wrapper to + * filter scan results to include only the specified SSIDs. %NULL + * indicates that no filtering is to be done. This can be used to + * reduce memory needs for scan results in environments that have large + * number of APs with different SSIDs. + * + * The driver wrapper is allowed to take this allocated buffer into its + * own use by setting the pointer to %NULL. In that case, the driver + * wrapper is responsible for freeing the buffer with os_free() once it + * is not needed anymore. + */ + struct wpa_driver_scan_filter { + u8 ssid[SSID_MAX_LEN]; + size_t ssid_len; + } *filter_ssids; + + /** + * num_filter_ssids - Number of entries in filter_ssids array + */ + size_t num_filter_ssids; + + /** + * filter_rssi - Filter by RSSI + * + * The driver may filter scan results in firmware to reduce host + * wakeups and thereby save power. Specify the RSSI threshold in s32 + * dBm. + */ + s32 filter_rssi; + + /** + * p2p_probe - Used to disable CCK (802.11b) rates for P2P probes + * + * When set, the driver is expected to remove rates 1, 2, 5.5, and 11 + * Mbps from the support rates element(s) in the Probe Request frames + * and not to transmit the frames at any of those rates. + */ + unsigned int p2p_probe:1; + + /** + * only_new_results - Request driver to report only new results + * + * This is used to request the driver to report only BSSes that have + * been detected after this scan request has been started, i.e., to + * flush old cached BSS entries. + */ + unsigned int only_new_results:1; + + /** + * low_priority - Requests driver to use a lower scan priority + * + * This is used to request the driver to use a lower scan priority + * if it supports such a thing. + */ + unsigned int low_priority:1; + + /** + * mac_addr_rand - Requests driver to randomize MAC address + */ + unsigned int mac_addr_rand:1; + + /** + * mac_addr - MAC address used with randomization. The address cannot be + * a multicast one, i.e., bit 0 of byte 0 should not be set. + */ + const u8 *mac_addr; + + /** + * mac_addr_mask - MAC address mask used with randomization. + * + * Bits that are 0 in the mask should be randomized. Bits that are 1 in + * the mask should be taken as is from mac_addr. The mask should not + * allow the generation of a multicast address, i.e., bit 0 of byte 0 + * must be set. + */ + const u8 *mac_addr_mask; + + /* + * NOTE: Whenever adding new parameters here, please make sure + * wpa_scan_clone_params() and wpa_scan_free_params() get updated with + * matching changes. + */ +}; + +/** + * struct wpa_driver_auth_params - Authentication parameters + * Data for struct wpa_driver_ops::authenticate(). + */ +struct wpa_driver_auth_params { + int freq; + const u8 *bssid; + const u8 *ssid; + size_t ssid_len; + int auth_alg; + const u8 *ie; + size_t ie_len; + const u8 *wep_key[4]; + size_t wep_key_len[4]; + int wep_tx_keyidx; + int local_state_change; + + /** + * p2p - Whether this connection is a P2P group + */ + int p2p; + + /** + * sae_data - SAE elements for Authentication frame + * + * This buffer starts with the Authentication transaction sequence + * number field. If SAE is not used, this pointer is %NULL. + */ + const u8 *sae_data; + + /** + * sae_data_len - Length of sae_data buffer in octets + */ + size_t sae_data_len; +}; + +/** + * enum wps_mode - WPS mode + */ +enum wps_mode { + /** + * WPS_MODE_NONE - No WPS provisioning being used + */ + WPS_MODE_NONE, + + /** + * WPS_MODE_OPEN - WPS provisioning with AP that is in open mode + */ + WPS_MODE_OPEN, + + /** + * WPS_MODE_PRIVACY - WPS provisioning with AP that is using protection + */ + WPS_MODE_PRIVACY +}; + +/** + * struct hostapd_freq_params - Channel parameters + */ +struct hostapd_freq_params { + /** + * mode - Mode/band (HOSTAPD_MODE_IEEE80211A, ..) + */ + enum hostapd_hw_mode mode; + + /** + * freq - Primary channel center frequency in MHz + */ + int freq; + + /** + * channel - Channel number + */ + int channel; + + /** + * ht_enabled - Whether HT is enabled + */ + int ht_enabled; + + /** + * sec_channel_offset - Secondary channel offset for HT40 + * + * 0 = HT40 disabled, + * -1 = HT40 enabled, secondary channel below primary, + * 1 = HT40 enabled, secondary channel above primary + */ + int sec_channel_offset; + + /** + * vht_enabled - Whether VHT is enabled + */ + int vht_enabled; + + /** + * center_freq1 - Segment 0 center frequency in MHz + * + * Valid for both HT and VHT. + */ + int center_freq1; + + /** + * center_freq2 - Segment 1 center frequency in MHz + * + * Non-zero only for bandwidth 80 and an 80+80 channel + */ + int center_freq2; + + /** + * bandwidth - Channel bandwidth in MHz (20, 40, 80, 160) + */ + int bandwidth; +}; + +/** + * struct wpa_driver_associate_params - Association parameters + * Data for struct wpa_driver_ops::associate(). + */ +struct wpa_driver_associate_params { + /** + * bssid - BSSID of the selected AP + * This can be %NULL, if ap_scan=2 mode is used and the driver is + * responsible for selecting with which BSS to associate. */ + const u8 *bssid; + + /** + * bssid_hint - BSSID of a proposed AP + * + * This indicates which BSS has been found a suitable candidate for + * initial association for drivers that use driver/firmwate-based BSS + * selection. Unlike the @bssid parameter, @bssid_hint does not limit + * the driver from selecting other BSSes in the ESS. + */ + const u8 *bssid_hint; + + /** + * ssid - The selected SSID + */ + const u8 *ssid; + + /** + * ssid_len - Length of the SSID (1..32) + */ + size_t ssid_len; + + /** + * freq - channel parameters + */ + struct hostapd_freq_params freq; + + /** + * freq_hint - Frequency of the channel the proposed AP is using + * + * This provides a channel on which a suitable BSS has been found as a + * hint for the driver. Unlike the @freq parameter, @freq_hint does not + * limit the driver from selecting other channels for + * driver/firmware-based BSS selection. + */ + int freq_hint; + + /** + * bg_scan_period - Background scan period in seconds, 0 to disable + * background scan, or -1 to indicate no change to default driver + * configuration + */ + int bg_scan_period; + + /** + * beacon_int - Beacon interval for IBSS or 0 to use driver default + */ + int beacon_int; + + /** + * wpa_ie - WPA information element for (Re)Association Request + * WPA information element to be included in (Re)Association + * Request (including information element id and length). Use + * of this WPA IE is optional. If the driver generates the WPA + * IE, it can use pairwise_suite, group_suite, and + * key_mgmt_suite to select proper algorithms. In this case, + * the driver has to notify wpa_supplicant about the used WPA + * IE by generating an event that the interface code will + * convert into EVENT_ASSOCINFO data (see below). + * + * When using WPA2/IEEE 802.11i, wpa_ie is used for RSN IE + * instead. The driver can determine which version is used by + * looking at the first byte of the IE (0xdd for WPA, 0x30 for + * WPA2/RSN). + * + * When using WPS, wpa_ie is used for WPS IE instead of WPA/RSN IE. + */ + const u8 *wpa_ie; + + /** + * wpa_ie_len - length of the wpa_ie + */ + size_t wpa_ie_len; + + /** + * wpa_proto - Bitfield of WPA_PROTO_* values to indicate WPA/WPA2 + */ + unsigned int wpa_proto; + + /** + * pairwise_suite - Selected pairwise cipher suite (WPA_CIPHER_*) + * + * This is usually ignored if @wpa_ie is used. + */ + unsigned int pairwise_suite; + + /** + * group_suite - Selected group cipher suite (WPA_CIPHER_*) + * + * This is usually ignored if @wpa_ie is used. + */ + unsigned int group_suite; + + /** + * key_mgmt_suite - Selected key management suite (WPA_KEY_MGMT_*) + * + * This is usually ignored if @wpa_ie is used. + */ + unsigned int key_mgmt_suite; + + /** + * auth_alg - Allowed authentication algorithms + * Bit field of WPA_AUTH_ALG_* + */ + int auth_alg; + + /** + * mode - Operation mode (infra/ibss) IEEE80211_MODE_* + */ + int mode; + + /** + * wep_key - WEP keys for static WEP configuration + */ + const u8 *wep_key[4]; + + /** + * wep_key_len - WEP key length for static WEP configuration + */ + size_t wep_key_len[4]; + + /** + * wep_tx_keyidx - WEP TX key index for static WEP configuration + */ + int wep_tx_keyidx; + + /** + * mgmt_frame_protection - IEEE 802.11w management frame protection + */ + enum mfp_options mgmt_frame_protection; + + /** + * ft_ies - IEEE 802.11r / FT information elements + * If the supplicant is using IEEE 802.11r (FT) and has the needed keys + * for fast transition, this parameter is set to include the IEs that + * are to be sent in the next FT Authentication Request message. + * update_ft_ies() handler is called to update the IEs for further + * FT messages in the sequence. + * + * The driver should use these IEs only if the target AP is advertising + * the same mobility domain as the one included in the MDIE here. + * + * In ap_scan=2 mode, the driver can use these IEs when moving to a new + * AP after the initial association. These IEs can only be used if the + * target AP is advertising support for FT and is using the same MDIE + * and SSID as the current AP. + * + * The driver is responsible for reporting the FT IEs received from the + * AP's response using wpa_supplicant_event() with EVENT_FT_RESPONSE + * type. update_ft_ies() handler will then be called with the FT IEs to + * include in the next frame in the authentication sequence. + */ + const u8 *ft_ies; + + /** + * ft_ies_len - Length of ft_ies in bytes + */ + size_t ft_ies_len; + + /** + * ft_md - FT Mobility domain (6 octets) (also included inside ft_ies) + * + * This value is provided to allow the driver interface easier access + * to the current mobility domain. This value is set to %NULL if no + * mobility domain is currently active. + */ + const u8 *ft_md; + + /** + * passphrase - RSN passphrase for PSK + * + * This value is made available only for WPA/WPA2-Personal (PSK) and + * only for drivers that set WPA_DRIVER_FLAGS_4WAY_HANDSHAKE. This is + * the 8..63 character ASCII passphrase, if available. Please note that + * this can be %NULL if passphrase was not used to generate the PSK. In + * that case, the psk field must be used to fetch the PSK. + */ + const char *passphrase; + + /** + * psk - RSN PSK (alternative for passphrase for PSK) + * + * This value is made available only for WPA/WPA2-Personal (PSK) and + * only for drivers that set WPA_DRIVER_FLAGS_4WAY_HANDSHAKE. This is + * the 32-octet (256-bit) PSK, if available. The driver wrapper should + * be prepared to handle %NULL value as an error. + */ + const u8 *psk; + + /** + * drop_unencrypted - Enable/disable unencrypted frame filtering + * + * Configure the driver to drop all non-EAPOL frames (both receive and + * transmit paths). Unencrypted EAPOL frames (ethertype 0x888e) must + * still be allowed for key negotiation. + */ + int drop_unencrypted; + + /** + * prev_bssid - Previously used BSSID in this ESS + * + * When not %NULL, this is a request to use reassociation instead of + * association. + */ + const u8 *prev_bssid; + + /** + * wps - WPS mode + * + * If the driver needs to do special configuration for WPS association, + * this variable provides more information on what type of association + * is being requested. Most drivers should not need ot use this. + */ + enum wps_mode wps; + + /** + * p2p - Whether this connection is a P2P group + */ + int p2p; + + /** + * uapsd - UAPSD parameters for the network + * -1 = do not change defaults + * AP mode: 1 = enabled, 0 = disabled + * STA mode: bits 0..3 UAPSD enabled for VO,VI,BK,BE + */ + int uapsd; + + /** + * fixed_bssid - Whether to force this BSSID in IBSS mode + * 1 = Fix this BSSID and prevent merges. + * 0 = Do not fix BSSID. + */ + int fixed_bssid; + + /** + * fixed_freq - Fix control channel in IBSS mode + * 0 = don't fix control channel (default) + * 1 = fix control channel; this prevents IBSS merging with another + * channel + */ + int fixed_freq; + + /** + * disable_ht - Disable HT (IEEE 802.11n) for this connection + */ + int disable_ht; + + /** + * htcaps - HT Capabilities over-rides + * + * Only bits set in the mask will be used, and not all values are used + * by the kernel anyway. Currently, MCS, MPDU and MSDU fields are used. + * + * Pointer to struct ieee80211_ht_capabilities. + */ + const u8 *htcaps; + + /** + * htcaps_mask - HT Capabilities over-rides mask + * + * Pointer to struct ieee80211_ht_capabilities. + */ + const u8 *htcaps_mask; + +#ifdef CONFIG_VHT_OVERRIDES + /** + * disable_vht - Disable VHT for this connection + */ + int disable_vht; + + /** + * VHT capability overrides. + */ + const struct ieee80211_vht_capabilities *vhtcaps; + const struct ieee80211_vht_capabilities *vhtcaps_mask; +#endif /* CONFIG_VHT_OVERRIDES */ + + /** + * req_key_mgmt_offload - Request key management offload for connection + * + * Request key management offload for this connection if the device + * supports it. + */ + int req_key_mgmt_offload; + + /** + * Flag for indicating whether this association includes support for + * RRM (Radio Resource Measurements) + */ + int rrm_used; +}; + +enum hide_ssid { + NO_SSID_HIDING, + HIDDEN_SSID_ZERO_LEN, + HIDDEN_SSID_ZERO_CONTENTS +}; + +struct wowlan_triggers { + u8 any; + u8 disconnect; + u8 magic_pkt; + u8 gtk_rekey_failure; + u8 eap_identity_req; + u8 four_way_handshake; + u8 rfkill_release; +}; + +struct wpa_driver_ap_params { + /** + * head - Beacon head from IEEE 802.11 header to IEs before TIM IE + */ + u8 *head; + + /** + * head_len - Length of the head buffer in octets + */ + size_t head_len; + + /** + * tail - Beacon tail following TIM IE + */ + u8 *tail; + + /** + * tail_len - Length of the tail buffer in octets + */ + size_t tail_len; + + /** + * dtim_period - DTIM period + */ + int dtim_period; + + /** + * beacon_int - Beacon interval + */ + int beacon_int; + + /** + * basic_rates: -1 terminated array of basic rates in 100 kbps + * + * This parameter can be used to set a specific basic rate set for the + * BSS. If %NULL, default basic rate set is used. + */ + int *basic_rates; + + /** + * proberesp - Probe Response template + * + * This is used by drivers that reply to Probe Requests internally in + * AP mode and require the full Probe Response template. + */ + u8 *proberesp; + + /** + * proberesp_len - Length of the proberesp buffer in octets + */ + size_t proberesp_len; + + /** + * ssid - The SSID to use in Beacon/Probe Response frames + */ + const u8 *ssid; + + /** + * ssid_len - Length of the SSID (1..32) + */ + size_t ssid_len; + + /** + * hide_ssid - Whether to hide the SSID + */ + enum hide_ssid hide_ssid; + + /** + * pairwise_ciphers - WPA_CIPHER_* bitfield + */ + unsigned int pairwise_ciphers; + + /** + * group_cipher - WPA_CIPHER_* + */ + unsigned int group_cipher; + + /** + * key_mgmt_suites - WPA_KEY_MGMT_* bitfield + */ + unsigned int key_mgmt_suites; + + /** + * auth_algs - WPA_AUTH_ALG_* bitfield + */ + unsigned int auth_algs; + + /** + * wpa_version - WPA_PROTO_* bitfield + */ + unsigned int wpa_version; + + /** + * privacy - Whether privacy is used in the BSS + */ + int privacy; + + /** + * beacon_ies - WPS/P2P IE(s) for Beacon frames + * + * This is used to add IEs like WPS IE and P2P IE by drivers that do + * not use the full Beacon template. + */ + const struct wpabuf *beacon_ies; + + /** + * proberesp_ies - P2P/WPS IE(s) for Probe Response frames + * + * This is used to add IEs like WPS IE and P2P IE by drivers that + * reply to Probe Request frames internally. + */ + const struct wpabuf *proberesp_ies; + + /** + * assocresp_ies - WPS IE(s) for (Re)Association Response frames + * + * This is used to add IEs like WPS IE by drivers that reply to + * (Re)Association Request frames internally. + */ + const struct wpabuf *assocresp_ies; + + /** + * isolate - Whether to isolate frames between associated stations + * + * If this is non-zero, the AP is requested to disable forwarding of + * frames between associated stations. + */ + int isolate; + + /** + * cts_protect - Whether CTS protection is enabled + */ + int cts_protect; + + /** + * preamble - Whether short preamble is enabled + */ + int preamble; + + /** + * short_slot_time - Whether short slot time is enabled + * + * 0 = short slot time disable, 1 = short slot time enabled, -1 = do + * not set (e.g., when 802.11g mode is not in use) + */ + int short_slot_time; + + /** + * ht_opmode - HT operation mode or -1 if HT not in use + */ + int ht_opmode; + + /** + * interworking - Whether Interworking is enabled + */ + int interworking; + + /** + * hessid - Homogeneous ESS identifier or %NULL if not set + */ + const u8 *hessid; + + /** + * access_network_type - Access Network Type (0..15) + * + * This is used for filtering Probe Request frames when Interworking is + * enabled. + */ + u8 access_network_type; + + /** + * ap_max_inactivity - Timeout in seconds to detect STA's inactivity + * + * This is used by driver which advertises this capability. + */ + int ap_max_inactivity; + + /** + * ctwindow - Client Traffic Window (in TUs) + */ + u8 p2p_go_ctwindow; + + /** + * smps_mode - SMPS mode + * + * SMPS mode to be used by the AP, specified as the relevant bits of + * ht_capab (i.e. HT_CAP_INFO_SMPS_*). + */ + unsigned int smps_mode; + + /** + * disable_dgaf - Whether group-addressed frames are disabled + */ + int disable_dgaf; + + /** + * osen - Whether OSEN security is enabled + */ + int osen; + + /** + * freq - Channel parameters for dynamic bandwidth changes + */ + struct hostapd_freq_params *freq; + + /** + * reenable - Whether this is to re-enable beaconing + */ + int reenable; +}; + +struct wpa_driver_mesh_bss_params { +#define WPA_DRIVER_MESH_CONF_FLAG_AUTO_PLINKS 0x00000001 + /* + * TODO: Other mesh configuration parameters would go here. + * See NL80211_MESHCONF_* for all the mesh config parameters. + */ + unsigned int flags; + int peer_link_timeout; +}; + +struct wpa_driver_mesh_join_params { + const u8 *meshid; + int meshid_len; + const int *basic_rates; + const u8 *ies; + int ie_len; + struct hostapd_freq_params freq; + int beacon_int; + int max_peer_links; + struct wpa_driver_mesh_bss_params conf; +#define WPA_DRIVER_MESH_FLAG_USER_MPM 0x00000001 +#define WPA_DRIVER_MESH_FLAG_DRIVER_MPM 0x00000002 +#define WPA_DRIVER_MESH_FLAG_SAE_AUTH 0x00000004 +#define WPA_DRIVER_MESH_FLAG_AMPE 0x00000008 + unsigned int flags; +}; + +/** + * struct wpa_driver_capa - Driver capability information + */ +struct wpa_driver_capa { +#define WPA_DRIVER_CAPA_KEY_MGMT_WPA 0x00000001 +#define WPA_DRIVER_CAPA_KEY_MGMT_WPA2 0x00000002 +#define WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK 0x00000004 +#define WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK 0x00000008 +#define WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE 0x00000010 +#define WPA_DRIVER_CAPA_KEY_MGMT_FT 0x00000020 +#define WPA_DRIVER_CAPA_KEY_MGMT_FT_PSK 0x00000040 +#define WPA_DRIVER_CAPA_KEY_MGMT_WAPI_PSK 0x00000080 +#define WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B 0x00000100 +#define WPA_DRIVER_CAPA_KEY_MGMT_SUITE_B_192 0x00000200 + /** Bitfield of supported key management suites */ + unsigned int key_mgmt; + +#define WPA_DRIVER_CAPA_ENC_WEP40 0x00000001 +#define WPA_DRIVER_CAPA_ENC_WEP104 0x00000002 +#define WPA_DRIVER_CAPA_ENC_TKIP 0x00000004 +#define WPA_DRIVER_CAPA_ENC_CCMP 0x00000008 +#define WPA_DRIVER_CAPA_ENC_WEP128 0x00000010 +#define WPA_DRIVER_CAPA_ENC_GCMP 0x00000020 +#define WPA_DRIVER_CAPA_ENC_GCMP_256 0x00000040 +#define WPA_DRIVER_CAPA_ENC_CCMP_256 0x00000080 +#define WPA_DRIVER_CAPA_ENC_BIP 0x00000100 +#define WPA_DRIVER_CAPA_ENC_BIP_GMAC_128 0x00000200 +#define WPA_DRIVER_CAPA_ENC_BIP_GMAC_256 0x00000400 +#define WPA_DRIVER_CAPA_ENC_BIP_CMAC_256 0x00000800 +#define WPA_DRIVER_CAPA_ENC_GTK_NOT_USED 0x00001000 + /** Bitfield of supported cipher suites */ + unsigned int enc; + +#define WPA_DRIVER_AUTH_OPEN 0x00000001 +#define WPA_DRIVER_AUTH_SHARED 0x00000002 +#define WPA_DRIVER_AUTH_LEAP 0x00000004 + /** Bitfield of supported IEEE 802.11 authentication algorithms */ + unsigned int auth; + +/** Driver generated WPA/RSN IE */ +#define WPA_DRIVER_FLAGS_DRIVER_IE 0x00000001 +/** Driver needs static WEP key setup after association command */ +#define WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC 0x00000002 +/** Driver takes care of all DFS operations */ +#define WPA_DRIVER_FLAGS_DFS_OFFLOAD 0x00000004 +/** Driver takes care of RSN 4-way handshake internally; PMK is configured with + * struct wpa_driver_ops::set_key using alg = WPA_ALG_PMK */ +#define WPA_DRIVER_FLAGS_4WAY_HANDSHAKE 0x00000008 +/** Driver is for a wired Ethernet interface */ +#define WPA_DRIVER_FLAGS_WIRED 0x00000010 +/** Driver provides separate commands for authentication and association (SME in + * wpa_supplicant). */ +#define WPA_DRIVER_FLAGS_SME 0x00000020 +/** Driver supports AP mode */ +#define WPA_DRIVER_FLAGS_AP 0x00000040 +/** Driver needs static WEP key setup after association has been completed */ +#define WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE 0x00000080 +/** Driver supports dynamic HT 20/40 MHz channel changes during BSS lifetime */ +#define WPA_DRIVER_FLAGS_HT_2040_COEX 0x00000100 +/** Driver supports concurrent P2P operations */ +#define WPA_DRIVER_FLAGS_P2P_CONCURRENT 0x00000200 +/** + * Driver uses the initial interface as a dedicated management interface, i.e., + * it cannot be used for P2P group operations or non-P2P purposes. + */ +#define WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE 0x00000400 +/** This interface is P2P capable (P2P GO or P2P Client) */ +#define WPA_DRIVER_FLAGS_P2P_CAPABLE 0x00000800 +/** Driver supports station and key removal when stopping an AP */ +#define WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT 0x00001000 +/** + * Driver uses the initial interface for P2P management interface and non-P2P + * purposes (e.g., connect to infra AP), but this interface cannot be used for + * P2P group operations. + */ +#define WPA_DRIVER_FLAGS_P2P_MGMT_AND_NON_P2P 0x00002000 +/** + * Driver is known to use sane error codes, i.e., when it indicates that + * something (e.g., association) fails, there was indeed a failure and the + * operation does not end up getting completed successfully later. + */ +#define WPA_DRIVER_FLAGS_SANE_ERROR_CODES 0x00004000 +/** Driver supports off-channel TX */ +#define WPA_DRIVER_FLAGS_OFFCHANNEL_TX 0x00008000 +/** Driver indicates TX status events for EAPOL Data frames */ +#define WPA_DRIVER_FLAGS_EAPOL_TX_STATUS 0x00010000 +/** Driver indicates TX status events for Deauth/Disassoc frames */ +#define WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS 0x00020000 +/** Driver supports roaming (BSS selection) in firmware */ +#define WPA_DRIVER_FLAGS_BSS_SELECTION 0x00040000 +/** Driver supports operating as a TDLS peer */ +#define WPA_DRIVER_FLAGS_TDLS_SUPPORT 0x00080000 +/** Driver requires external TDLS setup/teardown/discovery */ +#define WPA_DRIVER_FLAGS_TDLS_EXTERNAL_SETUP 0x00100000 +/** Driver indicates support for Probe Response offloading in AP mode */ +#define WPA_DRIVER_FLAGS_PROBE_RESP_OFFLOAD 0x00200000 +/** Driver supports U-APSD in AP mode */ +#define WPA_DRIVER_FLAGS_AP_UAPSD 0x00400000 +/** Driver supports inactivity timer in AP mode */ +#define WPA_DRIVER_FLAGS_INACTIVITY_TIMER 0x00800000 +/** Driver expects user space implementation of MLME in AP mode */ +#define WPA_DRIVER_FLAGS_AP_MLME 0x01000000 +/** Driver supports SAE with user space SME */ +#define WPA_DRIVER_FLAGS_SAE 0x02000000 +/** Driver makes use of OBSS scan mechanism in wpa_supplicant */ +#define WPA_DRIVER_FLAGS_OBSS_SCAN 0x04000000 +/** Driver supports IBSS (Ad-hoc) mode */ +#define WPA_DRIVER_FLAGS_IBSS 0x08000000 +/** Driver supports radar detection */ +#define WPA_DRIVER_FLAGS_RADAR 0x10000000 +/** Driver supports a dedicated interface for P2P Device */ +#define WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE 0x20000000 +/** Driver supports QoS Mapping */ +#define WPA_DRIVER_FLAGS_QOS_MAPPING 0x40000000 +/** Driver supports CSA in AP mode */ +#define WPA_DRIVER_FLAGS_AP_CSA 0x80000000 +/** Driver supports mesh */ +#define WPA_DRIVER_FLAGS_MESH 0x0000000100000000ULL +/** Driver support ACS offload */ +#define WPA_DRIVER_FLAGS_ACS_OFFLOAD 0x0000000200000000ULL +/** Driver supports key management offload */ +#define WPA_DRIVER_FLAGS_KEY_MGMT_OFFLOAD 0x0000000400000000ULL +/** Driver supports TDLS channel switching */ +#define WPA_DRIVER_FLAGS_TDLS_CHANNEL_SWITCH 0x0000000800000000ULL +/** Driver supports IBSS with HT datarates */ +#define WPA_DRIVER_FLAGS_HT_IBSS 0x0000001000000000ULL +/** Driver supports IBSS with VHT datarates */ +#define WPA_DRIVER_FLAGS_VHT_IBSS 0x0000002000000000ULL +/** Driver supports automatic band selection */ +#define WPA_DRIVER_FLAGS_SUPPORT_HW_MODE_ANY 0x0000004000000000ULL + u64 flags; + +#define WPA_DRIVER_SMPS_MODE_STATIC 0x00000001 +#define WPA_DRIVER_SMPS_MODE_DYNAMIC 0x00000002 + unsigned int smps_modes; + + unsigned int wmm_ac_supported:1; + + unsigned int mac_addr_rand_scan_supported:1; + unsigned int mac_addr_rand_sched_scan_supported:1; + + /** Maximum number of supported active probe SSIDs */ + int max_scan_ssids; + + /** Maximum number of supported active probe SSIDs for sched_scan */ + int max_sched_scan_ssids; + + /** Whether sched_scan (offloaded scanning) is supported */ + int sched_scan_supported; + + /** Maximum number of supported match sets for sched_scan */ + int max_match_sets; + + /** + * max_remain_on_chan - Maximum remain-on-channel duration in msec + */ + unsigned int max_remain_on_chan; + + /** + * max_stations - Maximum number of associated stations the driver + * supports in AP mode + */ + unsigned int max_stations; + + /** + * probe_resp_offloads - Bitmap of supported protocols by the driver + * for Probe Response offloading. + */ +/** Driver Probe Response offloading support for WPS ver. 1 */ +#define WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS 0x00000001 +/** Driver Probe Response offloading support for WPS ver. 2 */ +#define WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS2 0x00000002 +/** Driver Probe Response offloading support for P2P */ +#define WPA_DRIVER_PROBE_RESP_OFFLOAD_P2P 0x00000004 +/** Driver Probe Response offloading support for IEEE 802.11u (Interworking) */ +#define WPA_DRIVER_PROBE_RESP_OFFLOAD_INTERWORKING 0x00000008 + unsigned int probe_resp_offloads; + + unsigned int max_acl_mac_addrs; + + /** + * Number of supported concurrent channels + */ + unsigned int num_multichan_concurrent; + + /** + * extended_capa - extended capabilities in driver/device + * + * Must be allocated and freed by driver and the pointers must be + * valid for the lifetime of the driver, i.e., freed in deinit() + */ + const u8 *extended_capa, *extended_capa_mask; + unsigned int extended_capa_len; + + struct wowlan_triggers wowlan_triggers; + +/** Driver adds the DS Params Set IE in Probe Request frames */ +#define WPA_DRIVER_FLAGS_DS_PARAM_SET_IE_IN_PROBES 0x00000001 +/** Driver adds the WFA TPC IE in Probe Request frames */ +#define WPA_DRIVER_FLAGS_WFA_TPC_IE_IN_PROBES 0x00000002 +/** Driver handles quiet period requests */ +#define WPA_DRIVER_FLAGS_QUIET 0x00000004 +/** + * Driver is capable of inserting the current TX power value into the body of + * transmitted frames. + * Background: Some Action frames include a TPC Report IE. This IE contains a + * TX power field, which has to be updated by lower layers. One such Action + * frame is Link Measurement Report (part of RRM). Another is TPC Report (part + * of spectrum management). Note that this insertion takes place at a fixed + * offset, namely the 6th byte in the Action frame body. + */ +#define WPA_DRIVER_FLAGS_TX_POWER_INSERTION 0x00000008 + u32 rrm_flags; + + /* Driver concurrency capabilities */ + unsigned int conc_capab; + /* Maximum number of concurrent channels on 2.4 GHz */ + unsigned int max_conc_chan_2_4; + /* Maximum number of concurrent channels on 5 GHz */ + unsigned int max_conc_chan_5_0; +}; + + +struct hostapd_data; + +struct hostap_sta_driver_data { + unsigned long rx_packets, tx_packets, rx_bytes, tx_bytes; + unsigned long current_tx_rate; + unsigned long inactive_msec; + unsigned long flags; + unsigned long num_ps_buf_frames; + unsigned long tx_retry_failed; + unsigned long tx_retry_count; + int last_rssi; + int last_ack_rssi; +}; + +struct hostapd_sta_add_params { + const u8 *addr; + u16 aid; + u16 capability; + const u8 *supp_rates; + size_t supp_rates_len; + u16 listen_interval; + const struct ieee80211_ht_capabilities *ht_capabilities; + const struct ieee80211_vht_capabilities *vht_capabilities; + int vht_opmode_enabled; + u8 vht_opmode; + u32 flags; /* bitmask of WPA_STA_* flags */ + u32 flags_mask; /* unset bits in flags */ +#ifdef CONFIG_MESH + enum mesh_plink_state plink_state; +#endif /* CONFIG_MESH */ + int set; /* Set STA parameters instead of add */ + u8 qosinfo; + const u8 *ext_capab; + size_t ext_capab_len; + const u8 *supp_channels; + size_t supp_channels_len; + const u8 *supp_oper_classes; + size_t supp_oper_classes_len; +}; + +struct mac_address { + u8 addr[ETH_ALEN]; +}; + +struct hostapd_acl_params { + u8 acl_policy; + unsigned int num_mac_acl; + struct mac_address mac_acl[]; +}; + +enum wpa_driver_if_type { + /** + * WPA_IF_STATION - Station mode interface + */ + WPA_IF_STATION, + + /** + * WPA_IF_AP_VLAN - AP mode VLAN interface + * + * This interface shares its address and Beacon frame with the main + * BSS. + */ + WPA_IF_AP_VLAN, + + /** + * WPA_IF_AP_BSS - AP mode BSS interface + * + * This interface has its own address and Beacon frame. + */ + WPA_IF_AP_BSS, + + /** + * WPA_IF_P2P_GO - P2P Group Owner + */ + WPA_IF_P2P_GO, + + /** + * WPA_IF_P2P_CLIENT - P2P Client + */ + WPA_IF_P2P_CLIENT, + + /** + * WPA_IF_P2P_GROUP - P2P Group interface (will become either + * WPA_IF_P2P_GO or WPA_IF_P2P_CLIENT, but the role is not yet known) + */ + WPA_IF_P2P_GROUP, + + /** + * WPA_IF_P2P_DEVICE - P2P Device interface is used to indentify the + * abstracted P2P Device function in the driver + */ + WPA_IF_P2P_DEVICE, + + /* + * WPA_IF_MESH - Mesh interface + */ + WPA_IF_MESH, + + /* + * WPA_IF_TDLS - TDLS offchannel interface (used for pref freq only) + */ + WPA_IF_TDLS, + + /* + * WPA_IF_IBSS - IBSS interface (used for pref freq only) + */ + WPA_IF_IBSS, +}; + +struct wpa_init_params { + void *global_priv; + const u8 *bssid; + const char *ifname; + const char *driver_params; + int use_pae_group_addr; + char **bridge; + size_t num_bridge; + + u8 *own_addr; /* buffer for writing own MAC address */ +}; + + +struct wpa_bss_params { + /** Interface name (for multi-SSID/VLAN support) */ + const char *ifname; + /** Whether IEEE 802.1X or WPA/WPA2 is enabled */ + int enabled; + + int wpa; + int ieee802_1x; + int wpa_group; + int wpa_pairwise; + int wpa_key_mgmt; + int rsn_preauth; + enum mfp_options ieee80211w; +}; + +#define WPA_STA_AUTHORIZED BIT(0) +#define WPA_STA_WMM BIT(1) +#define WPA_STA_SHORT_PREAMBLE BIT(2) +#define WPA_STA_MFP BIT(3) +#define WPA_STA_TDLS_PEER BIT(4) +#define WPA_STA_AUTHENTICATED BIT(5) + +enum tdls_oper { + TDLS_DISCOVERY_REQ, + TDLS_SETUP, + TDLS_TEARDOWN, + TDLS_ENABLE_LINK, + TDLS_DISABLE_LINK, + TDLS_ENABLE0, + TDLS_DISABLE +}; + +enum wnm_oper { + WNM_SLEEP_ENTER_CONFIRM, + WNM_SLEEP_ENTER_FAIL, + WNM_SLEEP_EXIT_CONFIRM, + WNM_SLEEP_EXIT_FAIL, + WNM_SLEEP_TFS_REQ_IE_ADD, /* STA requests driver to add TFS req IE */ + WNM_SLEEP_TFS_REQ_IE_NONE, /* STA requests empty TFS req IE */ + WNM_SLEEP_TFS_REQ_IE_SET, /* AP requests driver to set TFS req IE for + * a STA */ + WNM_SLEEP_TFS_RESP_IE_ADD, /* AP requests driver to add TFS resp IE + * for a STA */ + WNM_SLEEP_TFS_RESP_IE_NONE, /* AP requests empty TFS resp IE */ + WNM_SLEEP_TFS_RESP_IE_SET, /* AP requests driver to set TFS resp IE + * for a STA */ + WNM_SLEEP_TFS_IE_DEL /* AP delete the TFS IE */ +}; + +/* enum chan_width - Channel width definitions */ +enum chan_width { + CHAN_WIDTH_20_NOHT, + CHAN_WIDTH_20, + CHAN_WIDTH_40, + CHAN_WIDTH_80, + CHAN_WIDTH_80P80, + CHAN_WIDTH_160, + CHAN_WIDTH_UNKNOWN +}; + +/** + * struct wpa_signal_info - Information about channel signal quality + */ +struct wpa_signal_info { + u32 frequency; + int above_threshold; + int current_signal; + int avg_signal; + int avg_beacon_signal; + int current_noise; + int current_txrate; + enum chan_width chanwidth; + int center_frq1; + int center_frq2; +}; + +/** + * struct beacon_data - Beacon data + * @head: Head portion of Beacon frame (before TIM IE) + * @tail: Tail portion of Beacon frame (after TIM IE) + * @beacon_ies: Extra information element(s) to add into Beacon frames or %NULL + * @proberesp_ies: Extra information element(s) to add into Probe Response + * frames or %NULL + * @assocresp_ies: Extra information element(s) to add into (Re)Association + * Response frames or %NULL + * @probe_resp: Probe Response frame template + * @head_len: Length of @head + * @tail_len: Length of @tail + * @beacon_ies_len: Length of beacon_ies in octets + * @proberesp_ies_len: Length of proberesp_ies in octets + * @proberesp_ies_len: Length of proberesp_ies in octets + * @probe_resp_len: Length of probe response template (@probe_resp) + */ +struct beacon_data { + u8 *head, *tail; + u8 *beacon_ies; + u8 *proberesp_ies; + u8 *assocresp_ies; + u8 *probe_resp; + + size_t head_len, tail_len; + size_t beacon_ies_len; + size_t proberesp_ies_len; + size_t assocresp_ies_len; + size_t probe_resp_len; +}; + +/** + * struct csa_settings - Settings for channel switch command + * @cs_count: Count in Beacon frames (TBTT) to perform the switch + * @block_tx: 1 - block transmission for CSA period + * @freq_params: Next channel frequency parameter + * @beacon_csa: Beacon/probe resp/asooc resp info for CSA period + * @beacon_after: Next beacon/probe resp/asooc resp info + * @counter_offset_beacon: Offset to the count field in beacon's tail + * @counter_offset_presp: Offset to the count field in probe resp. + */ +struct csa_settings { + u8 cs_count; + u8 block_tx; + + struct hostapd_freq_params freq_params; + struct beacon_data beacon_csa; + struct beacon_data beacon_after; + + u16 counter_offset_beacon; + u16 counter_offset_presp; +}; + +/* TDLS peer capabilities for send_tdls_mgmt() */ +enum tdls_peer_capability { + TDLS_PEER_HT = BIT(0), + TDLS_PEER_VHT = BIT(1), + TDLS_PEER_WMM = BIT(2), +}; + +/* valid info in the wmm_params struct */ +enum wmm_params_valid_info { + WMM_PARAMS_UAPSD_QUEUES_INFO = BIT(0), +}; + +/** + * struct wmm_params - WMM parameterss configured for this association + * @info_bitmap: Bitmap of valid wmm_params info; indicates what fields + * of the struct contain valid information. + * @uapsd_queues: Bitmap of ACs configured for uapsd (valid only if + * %WMM_PARAMS_UAPSD_QUEUES_INFO is set) + */ +struct wmm_params { + u8 info_bitmap; + u8 uapsd_queues; +}; + +#ifdef CONFIG_MACSEC +struct macsec_init_params { + Boolean always_include_sci; + Boolean use_es; + Boolean use_scb; +}; +#endif /* CONFIG_MACSEC */ + +enum drv_br_port_attr { + DRV_BR_PORT_ATTR_PROXYARP, + DRV_BR_PORT_ATTR_HAIRPIN_MODE, +}; + +enum drv_br_net_param { + DRV_BR_NET_PARAM_GARP_ACCEPT, + DRV_BR_MULTICAST_SNOOPING, +}; + +struct drv_acs_params { + /* Selected mode (HOSTAPD_MODE_*) */ + enum hostapd_hw_mode hw_mode; + + /* Indicates whether HT is enabled */ + int ht_enabled; + + /* Indicates whether HT40 is enabled */ + int ht40_enabled; + + /* Indicates whether VHT is enabled */ + int vht_enabled; + + /* Configured ACS channel width */ + u16 ch_width; + + /* ACS channel list info */ + unsigned int ch_list_len; + const u8 *ch_list; + const int *freq_list; +}; + + +/** + * struct wpa_driver_ops - Driver interface API definition + * + * This structure defines the API that each driver interface needs to implement + * for core wpa_supplicant code. All driver specific functionality is captured + * in this wrapper. + */ +struct wpa_driver_ops { + /** Name of the driver interface */ + const char *name; + /** One line description of the driver interface */ + const char *desc; + + /** + * get_bssid - Get the current BSSID + * @priv: private driver interface data + * @bssid: buffer for BSSID (ETH_ALEN = 6 bytes) + * + * Returns: 0 on success, -1 on failure + * + * Query kernel driver for the current BSSID and copy it to bssid. + * Setting bssid to 00:00:00:00:00:00 is recommended if the STA is not + * associated. + */ + int (*get_bssid)(void *priv, u8 *bssid); + + /** + * get_ssid - Get the current SSID + * @priv: private driver interface data + * @ssid: buffer for SSID (at least 32 bytes) + * + * Returns: Length of the SSID on success, -1 on failure + * + * Query kernel driver for the current SSID and copy it to ssid. + * Returning zero is recommended if the STA is not associated. + * + * Note: SSID is an array of octets, i.e., it is not nul terminated and + * can, at least in theory, contain control characters (including nul) + * and as such, should be processed as binary data, not a printable + * string. + */ + int (*get_ssid)(void *priv, u8 *ssid); + + /** + * set_key - Configure encryption key + * @ifname: Interface name (for multi-SSID/VLAN support) + * @priv: private driver interface data + * @alg: encryption algorithm (%WPA_ALG_NONE, %WPA_ALG_WEP, + * %WPA_ALG_TKIP, %WPA_ALG_CCMP, %WPA_ALG_IGTK, %WPA_ALG_PMK, + * %WPA_ALG_GCMP, %WPA_ALG_GCMP_256, %WPA_ALG_CCMP_256, + * %WPA_ALG_BIP_GMAC_128, %WPA_ALG_BIP_GMAC_256, + * %WPA_ALG_BIP_CMAC_256); + * %WPA_ALG_NONE clears the key. + * @addr: Address of the peer STA (BSSID of the current AP when setting + * pairwise key in station mode), ff:ff:ff:ff:ff:ff for + * broadcast keys, %NULL for default keys that are used both for + * broadcast and unicast; when clearing keys, %NULL is used to + * indicate that both the broadcast-only and default key of the + * specified key index is to be cleared + * @key_idx: key index (0..3), usually 0 for unicast keys; 0..4095 for + * IGTK + * @set_tx: configure this key as the default Tx key (only used when + * driver does not support separate unicast/individual key + * @seq: sequence number/packet number, seq_len octets, the next + * packet number to be used for in replay protection; configured + * for Rx keys (in most cases, this is only used with broadcast + * keys and set to zero for unicast keys); %NULL if not set + * @seq_len: length of the seq, depends on the algorithm: + * TKIP: 6 octets, CCMP/GCMP: 6 octets, IGTK: 6 octets + * @key: key buffer; TKIP: 16-byte temporal key, 8-byte Tx Mic key, + * 8-byte Rx Mic Key + * @key_len: length of the key buffer in octets (WEP: 5 or 13, + * TKIP: 32, CCMP/GCMP: 16, IGTK: 16) + * + * Returns: 0 on success, -1 on failure + * + * Configure the given key for the kernel driver. If the driver + * supports separate individual keys (4 default keys + 1 individual), + * addr can be used to determine whether the key is default or + * individual. If only 4 keys are supported, the default key with key + * index 0 is used as the individual key. STA must be configured to use + * it as the default Tx key (set_tx is set) and accept Rx for all the + * key indexes. In most cases, WPA uses only key indexes 1 and 2 for + * broadcast keys, so key index 0 is available for this kind of + * configuration. + * + * Please note that TKIP keys include separate TX and RX MIC keys and + * some drivers may expect them in different order than wpa_supplicant + * is using. If the TX/RX keys are swapped, all TKIP encrypted packets + * will trigger Michael MIC errors. This can be fixed by changing the + * order of MIC keys by swapping te bytes 16..23 and 24..31 of the key + * in driver_*.c set_key() implementation, see driver_ndis.c for an + * example on how this can be done. + */ + int (*set_key)(const char *ifname, void *priv, enum wpa_alg alg, + const u8 *addr, int key_idx, int set_tx, + const u8 *seq, size_t seq_len, + const u8 *key, size_t key_len); + + /** + * init - Initialize driver interface + * @ctx: context to be used when calling wpa_supplicant functions, + * e.g., wpa_supplicant_event() + * @ifname: interface name, e.g., wlan0 + * + * Returns: Pointer to private data, %NULL on failure + * + * Initialize driver interface, including event processing for kernel + * driver events (e.g., associated, scan results, Michael MIC failure). + * This function can allocate a private configuration data area for + * @ctx, file descriptor, interface name, etc. information that may be + * needed in future driver operations. If this is not used, non-NULL + * value will need to be returned because %NULL is used to indicate + * failure. The returned value will be used as 'void *priv' data for + * all other driver_ops functions. + * + * The main event loop (eloop.c) of wpa_supplicant can be used to + * register callback for read sockets (eloop_register_read_sock()). + * + * See below for more information about events and + * wpa_supplicant_event() function. + */ + void * (*init)(void *ctx, const char *ifname); + + /** + * deinit - Deinitialize driver interface + * @priv: private driver interface data from init() + * + * Shut down driver interface and processing of driver events. Free + * private data buffer if one was allocated in init() handler. + */ + void (*deinit)(void *priv); + + /** + * set_param - Set driver configuration parameters + * @priv: private driver interface data from init() + * @param: driver specific configuration parameters + * + * Returns: 0 on success, -1 on failure + * + * Optional handler for notifying driver interface about configuration + * parameters (driver_param). + */ + int (*set_param)(void *priv, const char *param); + + /** + * set_countermeasures - Enable/disable TKIP countermeasures + * @priv: private driver interface data + * @enabled: 1 = countermeasures enabled, 0 = disabled + * + * Returns: 0 on success, -1 on failure + * + * Configure TKIP countermeasures. When these are enabled, the driver + * should drop all received and queued frames that are using TKIP. + */ + int (*set_countermeasures)(void *priv, int enabled); + + /** + * deauthenticate - Request driver to deauthenticate + * @priv: private driver interface data + * @addr: peer address (BSSID of the AP) + * @reason_code: 16-bit reason code to be sent in the deauthentication + * frame + * + * Returns: 0 on success, -1 on failure + */ + int (*deauthenticate)(void *priv, const u8 *addr, int reason_code); + + /** + * associate - Request driver to associate + * @priv: private driver interface data + * @params: association parameters + * + * Returns: 0 on success, -1 on failure + */ + int (*associate)(void *priv, + struct wpa_driver_associate_params *params); + + /** + * add_pmkid - Add PMKSA cache entry to the driver + * @priv: private driver interface data + * @bssid: BSSID for the PMKSA cache entry + * @pmkid: PMKID for the PMKSA cache entry + * + * Returns: 0 on success, -1 on failure + * + * This function is called when a new PMK is received, as a result of + * either normal authentication or RSN pre-authentication. + * + * If the driver generates RSN IE, i.e., it does not use wpa_ie in + * associate(), add_pmkid() can be used to add new PMKSA cache entries + * in the driver. If the driver uses wpa_ie from wpa_supplicant, this + * driver_ops function does not need to be implemented. Likewise, if + * the driver does not support WPA, this function is not needed. + */ + int (*add_pmkid)(void *priv, const u8 *bssid, const u8 *pmkid); + + /** + * remove_pmkid - Remove PMKSA cache entry to the driver + * @priv: private driver interface data + * @bssid: BSSID for the PMKSA cache entry + * @pmkid: PMKID for the PMKSA cache entry + * + * Returns: 0 on success, -1 on failure + * + * This function is called when the supplicant drops a PMKSA cache + * entry for any reason. + * + * If the driver generates RSN IE, i.e., it does not use wpa_ie in + * associate(), remove_pmkid() can be used to synchronize PMKSA caches + * between the driver and wpa_supplicant. If the driver uses wpa_ie + * from wpa_supplicant, this driver_ops function does not need to be + * implemented. Likewise, if the driver does not support WPA, this + * function is not needed. + */ + int (*remove_pmkid)(void *priv, const u8 *bssid, const u8 *pmkid); + + /** + * flush_pmkid - Flush PMKSA cache + * @priv: private driver interface data + * + * Returns: 0 on success, -1 on failure + * + * This function is called when the supplicant drops all PMKSA cache + * entries for any reason. + * + * If the driver generates RSN IE, i.e., it does not use wpa_ie in + * associate(), remove_pmkid() can be used to synchronize PMKSA caches + * between the driver and wpa_supplicant. If the driver uses wpa_ie + * from wpa_supplicant, this driver_ops function does not need to be + * implemented. Likewise, if the driver does not support WPA, this + * function is not needed. + */ + int (*flush_pmkid)(void *priv); + + /** + * get_capa - Get driver capabilities + * @priv: private driver interface data + * + * Returns: 0 on success, -1 on failure + * + * Get driver/firmware/hardware capabilities. + */ + int (*get_capa)(void *priv, struct wpa_driver_capa *capa); + + /** + * poll - Poll driver for association information + * @priv: private driver interface data + * + * This is an option callback that can be used when the driver does not + * provide event mechanism for association events. This is called when + * receiving WPA EAPOL-Key messages that require association + * information. The driver interface is supposed to generate associnfo + * event before returning from this callback function. In addition, the + * driver interface should generate an association event after having + * sent out associnfo. + */ + void (*poll)(void *priv); + + /** + * get_ifname - Get interface name + * @priv: private driver interface data + * + * Returns: Pointer to the interface name. This can differ from the + * interface name used in init() call. Init() is called first. + * + * This optional function can be used to allow the driver interface to + * replace the interface name with something else, e.g., based on an + * interface mapping from a more descriptive name. + */ + const char * (*get_ifname)(void *priv); + + /** + * get_mac_addr - Get own MAC address + * @priv: private driver interface data + * + * Returns: Pointer to own MAC address or %NULL on failure + * + * This optional function can be used to get the own MAC address of the + * device from the driver interface code. This is only needed if the + * l2_packet implementation for the OS does not provide easy access to + * a MAC address. */ + const u8 * (*get_mac_addr)(void *priv); + + /** + * set_operstate - Sets device operating state to DORMANT or UP + * @priv: private driver interface data + * @state: 0 = dormant, 1 = up + * Returns: 0 on success, -1 on failure + * + * This is an optional function that can be used on operating systems + * that support a concept of controlling network device state from user + * space applications. This function, if set, gets called with + * state = 1 when authentication has been completed and with state = 0 + * when connection is lost. + */ + int (*set_operstate)(void *priv, int state); + + /** + * mlme_setprotection - MLME-SETPROTECTION.request primitive + * @priv: Private driver interface data + * @addr: Address of the station for which to set protection (may be + * %NULL for group keys) + * @protect_type: MLME_SETPROTECTION_PROTECT_TYPE_* + * @key_type: MLME_SETPROTECTION_KEY_TYPE_* + * Returns: 0 on success, -1 on failure + * + * This is an optional function that can be used to set the driver to + * require protection for Tx and/or Rx frames. This uses the layer + * interface defined in IEEE 802.11i-2004 clause 10.3.22.1 + * (MLME-SETPROTECTION.request). Many drivers do not use explicit + * set protection operation; instead, they set protection implicitly + * based on configured keys. + */ + int (*mlme_setprotection)(void *priv, const u8 *addr, int protect_type, + int key_type); + + /** + * get_hw_feature_data - Get hardware support data (channels and rates) + * @priv: Private driver interface data + * @num_modes: Variable for returning the number of returned modes + * flags: Variable for returning hardware feature flags + * Returns: Pointer to allocated hardware data on success or %NULL on + * failure. Caller is responsible for freeing this. + */ + struct hostapd_hw_modes * (*get_hw_feature_data)(void *priv, + u16 *num_modes, + u16 *flags); + + /** + * send_mlme - Send management frame from MLME + * @priv: Private driver interface data + * @data: IEEE 802.11 management frame with IEEE 802.11 header + * @data_len: Size of the management frame + * @noack: Do not wait for this frame to be acked (disable retries) + * @freq: Frequency (in MHz) to send the frame on, or 0 to let the + * driver decide + * Returns: 0 on success, -1 on failure + */ + int (*send_mlme)(void *priv, const u8 *data, size_t data_len, + int noack, unsigned int freq); + + /** + * update_ft_ies - Update FT (IEEE 802.11r) IEs + * @priv: Private driver interface data + * @md: Mobility domain (2 octets) (also included inside ies) + * @ies: FT IEs (MDIE, FTIE, ...) or %NULL to remove IEs + * @ies_len: Length of FT IEs in bytes + * Returns: 0 on success, -1 on failure + * + * The supplicant uses this callback to let the driver know that keying + * material for FT is available and that the driver can use the + * provided IEs in the next message in FT authentication sequence. + * + * This function is only needed for driver that support IEEE 802.11r + * (Fast BSS Transition). + */ + int (*update_ft_ies)(void *priv, const u8 *md, const u8 *ies, + size_t ies_len); + + /** + * get_scan_results2 - Fetch the latest scan results + * @priv: private driver interface data + * + * Returns: Allocated buffer of scan results (caller is responsible for + * freeing the data structure) on success, NULL on failure + */ + struct wpa_scan_results * (*get_scan_results2)(void *priv); + + /** + * set_country - Set country + * @priv: Private driver interface data + * @alpha2: country to which to switch to + * Returns: 0 on success, -1 on failure + * + * This function is for drivers which support some form + * of setting a regulatory domain. + */ + int (*set_country)(void *priv, const char *alpha2); + + /** + * get_country - Get country + * @priv: Private driver interface data + * @alpha2: Buffer for returning country code (at least 3 octets) + * Returns: 0 on success, -1 on failure + */ + int (*get_country)(void *priv, char *alpha2); + + /** + * global_init - Global driver initialization + * Returns: Pointer to private data (global), %NULL on failure + * + * This optional function is called to initialize the driver wrapper + * for global data, i.e., data that applies to all interfaces. If this + * function is implemented, global_deinit() will also need to be + * implemented to free the private data. The driver will also likely + * use init2() function instead of init() to get the pointer to global + * data available to per-interface initializer. + */ + void * (*global_init)(void); + + /** + * global_deinit - Global driver deinitialization + * @priv: private driver global data from global_init() + * + * Terminate any global driver related functionality and free the + * global data structure. + */ + void (*global_deinit)(void *priv); + + /** + * init2 - Initialize driver interface (with global data) + * @ctx: context to be used when calling wpa_supplicant functions, + * e.g., wpa_supplicant_event() + * @ifname: interface name, e.g., wlan0 + * @global_priv: private driver global data from global_init() + * Returns: Pointer to private data, %NULL on failure + * + * This function can be used instead of init() if the driver wrapper + * uses global data. + */ + void * (*init2)(void *ctx, const char *ifname, void *global_priv); + + /** + * get_interfaces - Get information about available interfaces + * @global_priv: private driver global data from global_init() + * Returns: Allocated buffer of interface information (caller is + * responsible for freeing the data structure) on success, NULL on + * failure + */ + struct wpa_interface_info * (*get_interfaces)(void *global_priv); + + /** + * scan2 - Request the driver to initiate scan + * @priv: private driver interface data + * @params: Scan parameters + * + * Returns: 0 on success, -1 on failure + * + * Once the scan results are ready, the driver should report scan + * results event for wpa_supplicant which will eventually request the + * results with wpa_driver_get_scan_results2(). + */ + int (*scan2)(void *priv, struct wpa_driver_scan_params *params); + + /** + * authenticate - Request driver to authenticate + * @priv: private driver interface data + * @params: authentication parameters + * Returns: 0 on success, -1 on failure + * + * This is an optional function that can be used with drivers that + * support separate authentication and association steps, i.e., when + * wpa_supplicant can act as the SME. If not implemented, associate() + * function is expected to take care of IEEE 802.11 authentication, + * too. + */ + int (*authenticate)(void *priv, + struct wpa_driver_auth_params *params); + + /** + * set_ap - Set Beacon and Probe Response information for AP mode + * @priv: Private driver interface data + * @params: Parameters to use in AP mode + * + * This function is used to configure Beacon template and/or extra IEs + * to add for Beacon and Probe Response frames for the driver in + * AP mode. The driver is responsible for building the full Beacon + * frame by concatenating the head part with TIM IE generated by the + * driver/firmware and finishing with the tail part. Depending on the + * driver architectue, this can be done either by using the full + * template or the set of additional IEs (e.g., WPS and P2P IE). + * Similarly, Probe Response processing depends on the driver design. + * If the driver (or firmware) takes care of replying to Probe Request + * frames, the extra IEs provided here needs to be added to the Probe + * Response frames. + * + * Returns: 0 on success, -1 on failure + */ + int (*set_ap)(void *priv, struct wpa_driver_ap_params *params); + + /** + * set_acl - Set ACL in AP mode + * @priv: Private driver interface data + * @params: Parameters to configure ACL + * Returns: 0 on success, -1 on failure + * + * This is used only for the drivers which support MAC address ACL. + */ + int (*set_acl)(void *priv, struct hostapd_acl_params *params); + + /** + * hapd_init - Initialize driver interface (hostapd only) + * @hapd: Pointer to hostapd context + * @params: Configuration for the driver wrapper + * Returns: Pointer to private data, %NULL on failure + * + * This function is used instead of init() or init2() when the driver + * wrapper is used with hostapd. + */ + void * (*hapd_init)(struct hostapd_data *hapd, + struct wpa_init_params *params); + + /** + * hapd_deinit - Deinitialize driver interface (hostapd only) + * @priv: Private driver interface data from hapd_init() + */ + void (*hapd_deinit)(void *priv); + + /** + * set_ieee8021x - Enable/disable IEEE 802.1X support (AP only) + * @priv: Private driver interface data + * @params: BSS parameters + * Returns: 0 on success, -1 on failure + * + * This is an optional function to configure the kernel driver to + * enable/disable IEEE 802.1X support and set WPA/WPA2 parameters. This + * can be left undefined (set to %NULL) if IEEE 802.1X support is + * always enabled and the driver uses set_ap() to set WPA/RSN IE + * for Beacon frames. + * + * DEPRECATED - use set_ap() instead + */ + int (*set_ieee8021x)(void *priv, struct wpa_bss_params *params); + + /** + * set_privacy - Enable/disable privacy (AP only) + * @priv: Private driver interface data + * @enabled: 1 = privacy enabled, 0 = disabled + * Returns: 0 on success, -1 on failure + * + * This is an optional function to configure privacy field in the + * kernel driver for Beacon frames. This can be left undefined (set to + * %NULL) if the driver uses the Beacon template from set_ap(). + * + * DEPRECATED - use set_ap() instead + */ + int (*set_privacy)(void *priv, int enabled); + + /** + * get_seqnum - Fetch the current TSC/packet number (AP only) + * @ifname: The interface name (main or virtual) + * @priv: Private driver interface data + * @addr: MAC address of the station or %NULL for group keys + * @idx: Key index + * @seq: Buffer for returning the latest used TSC/packet number + * Returns: 0 on success, -1 on failure + * + * This function is used to fetch the last used TSC/packet number for + * a TKIP, CCMP, GCMP, or BIP/IGTK key. It is mainly used with group + * keys, so there is no strict requirement on implementing support for + * unicast keys (i.e., addr != %NULL). + */ + int (*get_seqnum)(const char *ifname, void *priv, const u8 *addr, + int idx, u8 *seq); + + /** + * flush - Flush all association stations (AP only) + * @priv: Private driver interface data + * Returns: 0 on success, -1 on failure + * + * This function requests the driver to disassociate all associated + * stations. This function does not need to be implemented if the + * driver does not process association frames internally. + */ + int (*flush)(void *priv); + + /** + * set_generic_elem - Add IEs into Beacon/Probe Response frames (AP) + * @priv: Private driver interface data + * @elem: Information elements + * @elem_len: Length of the elem buffer in octets + * Returns: 0 on success, -1 on failure + * + * This is an optional function to add information elements in the + * kernel driver for Beacon and Probe Response frames. This can be left + * undefined (set to %NULL) if the driver uses the Beacon template from + * set_ap(). + * + * DEPRECATED - use set_ap() instead + */ + int (*set_generic_elem)(void *priv, const u8 *elem, size_t elem_len); + + /** + * read_sta_data - Fetch station data + * @priv: Private driver interface data + * @data: Buffer for returning station information + * @addr: MAC address of the station + * Returns: 0 on success, -1 on failure + */ + int (*read_sta_data)(void *priv, struct hostap_sta_driver_data *data, + const u8 *addr); + + /** + * hapd_send_eapol - Send an EAPOL packet (AP only) + * @priv: private driver interface data + * @addr: Destination MAC address + * @data: EAPOL packet starting with IEEE 802.1X header + * @data_len: Length of the EAPOL packet in octets + * @encrypt: Whether the frame should be encrypted + * @own_addr: Source MAC address + * @flags: WPA_STA_* flags for the destination station + * + * Returns: 0 on success, -1 on failure + */ + int (*hapd_send_eapol)(void *priv, const u8 *addr, const u8 *data, + size_t data_len, int encrypt, + const u8 *own_addr, u32 flags); + + /** + * sta_deauth - Deauthenticate a station (AP only) + * @priv: Private driver interface data + * @own_addr: Source address and BSSID for the Deauthentication frame + * @addr: MAC address of the station to deauthenticate + * @reason: Reason code for the Deauthentiation frame + * Returns: 0 on success, -1 on failure + * + * This function requests a specific station to be deauthenticated and + * a Deauthentication frame to be sent to it. + */ + int (*sta_deauth)(void *priv, const u8 *own_addr, const u8 *addr, + int reason); + + /** + * sta_disassoc - Disassociate a station (AP only) + * @priv: Private driver interface data + * @own_addr: Source address and BSSID for the Disassociation frame + * @addr: MAC address of the station to disassociate + * @reason: Reason code for the Disassociation frame + * Returns: 0 on success, -1 on failure + * + * This function requests a specific station to be disassociated and + * a Disassociation frame to be sent to it. + */ + int (*sta_disassoc)(void *priv, const u8 *own_addr, const u8 *addr, + int reason); + + /** + * sta_remove - Remove a station entry (AP only) + * @priv: Private driver interface data + * @addr: MAC address of the station to be removed + * Returns: 0 on success, -1 on failure + */ + int (*sta_remove)(void *priv, const u8 *addr); + + /** + * hapd_get_ssid - Get the current SSID (AP only) + * @priv: Private driver interface data + * @buf: Buffer for returning the SSID + * @len: Maximum length of the buffer + * Returns: Length of the SSID on success, -1 on failure + * + * This function need not be implemented if the driver uses Beacon + * template from set_ap() and does not reply to Probe Request frames. + */ + int (*hapd_get_ssid)(void *priv, u8 *buf, int len); + + /** + * hapd_set_ssid - Set SSID (AP only) + * @priv: Private driver interface data + * @buf: SSID + * @len: Length of the SSID in octets + * Returns: 0 on success, -1 on failure + * + * DEPRECATED - use set_ap() instead + */ + int (*hapd_set_ssid)(void *priv, const u8 *buf, int len); + + /** + * hapd_set_countermeasures - Enable/disable TKIP countermeasures (AP) + * @priv: Private driver interface data + * @enabled: 1 = countermeasures enabled, 0 = disabled + * Returns: 0 on success, -1 on failure + * + * This need not be implemented if the driver does not take care of + * association processing. + */ + int (*hapd_set_countermeasures)(void *priv, int enabled); + + /** + * sta_add - Add a station entry + * @priv: Private driver interface data + * @params: Station parameters + * Returns: 0 on success, -1 on failure + * + * This function is used to add a station entry to the driver once the + * station has completed association. This is only used if the driver + * does not take care of association processing. + * + * With TDLS, this function is also used to add or set (params->set 1) + * TDLS peer entries. + */ + int (*sta_add)(void *priv, struct hostapd_sta_add_params *params); + + /** + * get_inact_sec - Get station inactivity duration (AP only) + * @priv: Private driver interface data + * @addr: Station address + * Returns: Number of seconds station has been inactive, -1 on failure + */ + int (*get_inact_sec)(void *priv, const u8 *addr); + + /** + * sta_clear_stats - Clear station statistics (AP only) + * @priv: Private driver interface data + * @addr: Station address + * Returns: 0 on success, -1 on failure + */ + int (*sta_clear_stats)(void *priv, const u8 *addr); + + /** + * set_freq - Set channel/frequency (AP only) + * @priv: Private driver interface data + * @freq: Channel parameters + * Returns: 0 on success, -1 on failure + */ + int (*set_freq)(void *priv, struct hostapd_freq_params *freq); + + /** + * set_rts - Set RTS threshold + * @priv: Private driver interface data + * @rts: RTS threshold in octets + * Returns: 0 on success, -1 on failure + */ + int (*set_rts)(void *priv, int rts); + + /** + * set_frag - Set fragmentation threshold + * @priv: Private driver interface data + * @frag: Fragmentation threshold in octets + * Returns: 0 on success, -1 on failure + */ + int (*set_frag)(void *priv, int frag); + + /** + * sta_set_flags - Set station flags (AP only) + * @priv: Private driver interface data + * @addr: Station address + * @total_flags: Bitmap of all WPA_STA_* flags currently set + * @flags_or: Bitmap of WPA_STA_* flags to add + * @flags_and: Bitmap of WPA_STA_* flags to us as a mask + * Returns: 0 on success, -1 on failure + */ + int (*sta_set_flags)(void *priv, const u8 *addr, + unsigned int total_flags, unsigned int flags_or, + unsigned int flags_and); + + /** + * set_tx_queue_params - Set TX queue parameters + * @priv: Private driver interface data + * @queue: Queue number (0 = VO, 1 = VI, 2 = BE, 3 = BK) + * @aifs: AIFS + * @cw_min: cwMin + * @cw_max: cwMax + * @burst_time: Maximum length for bursting in 0.1 msec units + */ + int (*set_tx_queue_params)(void *priv, int queue, int aifs, int cw_min, + int cw_max, int burst_time); + + /** + * if_add - Add a virtual interface + * @priv: Private driver interface data + * @type: Interface type + * @ifname: Interface name for the new virtual interface + * @addr: Local address to use for the interface or %NULL to use the + * parent interface address + * @bss_ctx: BSS context for %WPA_IF_AP_BSS interfaces + * @drv_priv: Pointer for overwriting the driver context or %NULL if + * not allowed (applies only to %WPA_IF_AP_BSS type) + * @force_ifname: Buffer for returning an interface name that the + * driver ended up using if it differs from the requested ifname + * @if_addr: Buffer for returning the allocated interface address + * (this may differ from the requested addr if the driver cannot + * change interface address) + * @bridge: Bridge interface to use or %NULL if no bridge configured + * @use_existing: Whether to allow existing interface to be used + * Returns: 0 on success, -1 on failure + */ + int (*if_add)(void *priv, enum wpa_driver_if_type type, + const char *ifname, const u8 *addr, void *bss_ctx, + void **drv_priv, char *force_ifname, u8 *if_addr, + const char *bridge, int use_existing); + + /** + * if_remove - Remove a virtual interface + * @priv: Private driver interface data + * @type: Interface type + * @ifname: Interface name of the virtual interface to be removed + * Returns: 0 on success, -1 on failure + */ + int (*if_remove)(void *priv, enum wpa_driver_if_type type, + const char *ifname); + + /** + * set_sta_vlan - Bind a station into a specific interface (AP only) + * @priv: Private driver interface data + * @ifname: Interface (main or virtual BSS or VLAN) + * @addr: MAC address of the associated station + * @vlan_id: VLAN ID + * Returns: 0 on success, -1 on failure + * + * This function is used to bind a station to a specific virtual + * interface. It is only used if when virtual interfaces are supported, + * e.g., to assign stations to different VLAN interfaces based on + * information from a RADIUS server. This allows separate broadcast + * domains to be used with a single BSS. + */ + int (*set_sta_vlan)(void *priv, const u8 *addr, const char *ifname, + int vlan_id); + + /** + * commit - Optional commit changes handler (AP only) + * @priv: driver private data + * Returns: 0 on success, -1 on failure + * + * This optional handler function can be registered if the driver + * interface implementation needs to commit changes (e.g., by setting + * network interface up) at the end of initial configuration. If set, + * this handler will be called after initial setup has been completed. + */ + int (*commit)(void *priv); + + /** + * send_ether - Send an ethernet packet (AP only) + * @priv: private driver interface data + * @dst: Destination MAC address + * @src: Source MAC address + * @proto: Ethertype + * @data: EAPOL packet starting with IEEE 802.1X header + * @data_len: Length of the EAPOL packet in octets + * Returns: 0 on success, -1 on failure + */ + int (*send_ether)(void *priv, const u8 *dst, const u8 *src, u16 proto, + const u8 *data, size_t data_len); + + /** + * set_radius_acl_auth - Notification of RADIUS ACL change + * @priv: Private driver interface data + * @mac: MAC address of the station + * @accepted: Whether the station was accepted + * @session_timeout: Session timeout for the station + * Returns: 0 on success, -1 on failure + */ + int (*set_radius_acl_auth)(void *priv, const u8 *mac, int accepted, + u32 session_timeout); + + /** + * set_radius_acl_expire - Notification of RADIUS ACL expiration + * @priv: Private driver interface data + * @mac: MAC address of the station + * Returns: 0 on success, -1 on failure + */ + int (*set_radius_acl_expire)(void *priv, const u8 *mac); + + /** + * set_ap_wps_ie - Add WPS IE(s) into Beacon/Probe Response frames (AP) + * @priv: Private driver interface data + * @beacon: WPS IE(s) for Beacon frames or %NULL to remove extra IE(s) + * @proberesp: WPS IE(s) for Probe Response frames or %NULL to remove + * extra IE(s) + * @assocresp: WPS IE(s) for (Re)Association Response frames or %NULL + * to remove extra IE(s) + * Returns: 0 on success, -1 on failure + * + * This is an optional function to add WPS IE in the kernel driver for + * Beacon and Probe Response frames. This can be left undefined (set + * to %NULL) if the driver uses the Beacon template from set_ap() + * and does not process Probe Request frames. If the driver takes care + * of (Re)Association frame processing, the assocresp buffer includes + * WPS IE(s) that need to be added to (Re)Association Response frames + * whenever a (Re)Association Request frame indicated use of WPS. + * + * This will also be used to add P2P IE(s) into Beacon/Probe Response + * frames when operating as a GO. The driver is responsible for adding + * timing related attributes (e.g., NoA) in addition to the IEs + * included here by appending them after these buffers. This call is + * also used to provide Probe Response IEs for P2P Listen state + * operations for drivers that generate the Probe Response frames + * internally. + * + * DEPRECATED - use set_ap() instead + */ + int (*set_ap_wps_ie)(void *priv, const struct wpabuf *beacon, + const struct wpabuf *proberesp, + const struct wpabuf *assocresp); + + /** + * set_supp_port - Set IEEE 802.1X Supplicant Port status + * @priv: Private driver interface data + * @authorized: Whether the port is authorized + * Returns: 0 on success, -1 on failure + */ + int (*set_supp_port)(void *priv, int authorized); + + /** + * set_wds_sta - Bind a station into a 4-address WDS (AP only) + * @priv: Private driver interface data + * @addr: MAC address of the associated station + * @aid: Association ID + * @val: 1 = bind to 4-address WDS; 0 = unbind + * @bridge_ifname: Bridge interface to use for the WDS station or %NULL + * to indicate that bridge is not to be used + * @ifname_wds: Buffer to return the interface name for the new WDS + * station or %NULL to indicate name is not returned. + * Returns: 0 on success, -1 on failure + */ + int (*set_wds_sta)(void *priv, const u8 *addr, int aid, int val, + const char *bridge_ifname, char *ifname_wds); + + /** + * send_action - Transmit an Action frame + * @priv: Private driver interface data + * @freq: Frequency (in MHz) of the channel + * @wait: Time to wait off-channel for a response (in ms), or zero + * @dst: Destination MAC address (Address 1) + * @src: Source MAC address (Address 2) + * @bssid: BSSID (Address 3) + * @data: Frame body + * @data_len: data length in octets + @ @no_cck: Whether CCK rates must not be used to transmit this frame + * Returns: 0 on success, -1 on failure + * + * This command can be used to request the driver to transmit an action + * frame to the specified destination. + * + * If the %WPA_DRIVER_FLAGS_OFFCHANNEL_TX flag is set, the frame will + * be transmitted on the given channel and the device will wait for a + * response on that channel for the given wait time. + * + * If the flag is not set, the wait time will be ignored. In this case, + * if a remain-on-channel duration is in progress, the frame must be + * transmitted on that channel; alternatively the frame may be sent on + * the current operational channel (if in associated state in station + * mode or while operating as an AP.) + */ + int (*send_action)(void *priv, unsigned int freq, unsigned int wait, + const u8 *dst, const u8 *src, const u8 *bssid, + const u8 *data, size_t data_len, int no_cck); + + /** + * send_action_cancel_wait - Cancel action frame TX wait + * @priv: Private driver interface data + * + * This command cancels the wait time associated with sending an action + * frame. It is only available when %WPA_DRIVER_FLAGS_OFFCHANNEL_TX is + * set in the driver flags. + */ + void (*send_action_cancel_wait)(void *priv); + + /** + * remain_on_channel - Remain awake on a channel + * @priv: Private driver interface data + * @freq: Frequency (in MHz) of the channel + * @duration: Duration in milliseconds + * Returns: 0 on success, -1 on failure + * + * This command is used to request the driver to remain awake on the + * specified channel for the specified duration and report received + * Action frames with EVENT_RX_MGMT events. Optionally, received + * Probe Request frames may also be requested to be reported by calling + * probe_req_report(). These will be reported with EVENT_RX_PROBE_REQ. + * + * The driver may not be at the requested channel when this function + * returns, i.e., the return code is only indicating whether the + * request was accepted. The caller will need to wait until the + * EVENT_REMAIN_ON_CHANNEL event indicates that the driver has + * completed the channel change. This may take some time due to other + * need for the radio and the caller should be prepared to timing out + * its wait since there are no guarantees on when this request can be + * executed. + */ + int (*remain_on_channel)(void *priv, unsigned int freq, + unsigned int duration); + + /** + * cancel_remain_on_channel - Cancel remain-on-channel operation + * @priv: Private driver interface data + * + * This command can be used to cancel a remain-on-channel operation + * before its originally requested duration has passed. This could be + * used, e.g., when remain_on_channel() is used to request extra time + * to receive a response to an Action frame and the response is + * received when there is still unneeded time remaining on the + * remain-on-channel operation. + */ + int (*cancel_remain_on_channel)(void *priv); + + /** + * probe_req_report - Request Probe Request frames to be indicated + * @priv: Private driver interface data + * @report: Whether to report received Probe Request frames + * Returns: 0 on success, -1 on failure (or if not supported) + * + * This command can be used to request the driver to indicate when + * Probe Request frames are received with EVENT_RX_PROBE_REQ events. + * Since this operation may require extra resources, e.g., due to less + * optimal hardware/firmware RX filtering, many drivers may disable + * Probe Request reporting at least in station mode. This command is + * used to notify the driver when the Probe Request frames need to be + * reported, e.g., during remain-on-channel operations. + */ + int (*probe_req_report)(void *priv, int report); + + /** + * deinit_ap - Deinitialize AP mode + * @priv: Private driver interface data + * Returns: 0 on success, -1 on failure (or if not supported) + * + * This optional function can be used to disable AP mode related + * configuration. If the interface was not dynamically added, + * change the driver mode to station mode to allow normal station + * operations like scanning to be completed. + */ + int (*deinit_ap)(void *priv); + + /** + * deinit_p2p_cli - Deinitialize P2P client mode + * @priv: Private driver interface data + * Returns: 0 on success, -1 on failure (or if not supported) + * + * This optional function can be used to disable P2P client mode. If the + * interface was not dynamically added, change the interface type back + * to station mode. + */ + int (*deinit_p2p_cli)(void *priv); + + /** + * suspend - Notification on system suspend/hibernate event + * @priv: Private driver interface data + */ + void (*suspend)(void *priv); + + /** + * resume - Notification on system resume/thaw event + * @priv: Private driver interface data + */ + void (*resume)(void *priv); + + /** + * signal_monitor - Set signal monitoring parameters + * @priv: Private driver interface data + * @threshold: Threshold value for signal change events; 0 = disabled + * @hysteresis: Minimum change in signal strength before indicating a + * new event + * Returns: 0 on success, -1 on failure (or if not supported) + * + * This function can be used to configure monitoring of signal strength + * with the current AP. Whenever signal strength drops below the + * %threshold value or increases above it, EVENT_SIGNAL_CHANGE event + * should be generated assuming the signal strength has changed at + * least %hysteresis from the previously indicated signal change event. + */ + int (*signal_monitor)(void *priv, int threshold, int hysteresis); + + /** + * send_frame - Send IEEE 802.11 frame (testing use only) + * @priv: Private driver interface data + * @data: IEEE 802.11 frame with IEEE 802.11 header + * @data_len: Size of the frame + * @encrypt: Whether to encrypt the frame (if keys are set) + * Returns: 0 on success, -1 on failure + * + * This function is only used for debugging purposes and is not + * required to be implemented for normal operations. + */ + int (*send_frame)(void *priv, const u8 *data, size_t data_len, + int encrypt); + + /** + * get_noa - Get current Notice of Absence attribute payload + * @priv: Private driver interface data + * @buf: Buffer for returning NoA + * @buf_len: Buffer length in octets + * Returns: Number of octets used in buf, 0 to indicate no NoA is being + * advertized, or -1 on failure + * + * This function is used to fetch the current Notice of Absence + * attribute value from GO. + */ + int (*get_noa)(void *priv, u8 *buf, size_t buf_len); + + /** + * set_noa - Set Notice of Absence parameters for GO (testing) + * @priv: Private driver interface data + * @count: Count + * @start: Start time in ms from next TBTT + * @duration: Duration in ms + * Returns: 0 on success or -1 on failure + * + * This function is used to set Notice of Absence parameters for GO. It + * is used only for testing. To disable NoA, all parameters are set to + * 0. + */ + int (*set_noa)(void *priv, u8 count, int start, int duration); + + /** + * set_p2p_powersave - Set P2P power save options + * @priv: Private driver interface data + * @legacy_ps: 0 = disable, 1 = enable, 2 = maximum PS, -1 = no change + * @opp_ps: 0 = disable, 1 = enable, -1 = no change + * @ctwindow: 0.. = change (msec), -1 = no change + * Returns: 0 on success or -1 on failure + */ + int (*set_p2p_powersave)(void *priv, int legacy_ps, int opp_ps, + int ctwindow); + + /** + * ampdu - Enable/disable aggregation + * @priv: Private driver interface data + * @ampdu: 1/0 = enable/disable A-MPDU aggregation + * Returns: 0 on success or -1 on failure + */ + int (*ampdu)(void *priv, int ampdu); + + /** + * get_radio_name - Get physical radio name for the device + * @priv: Private driver interface data + * Returns: Radio name or %NULL if not known + * + * The returned data must not be modified by the caller. It is assumed + * that any interface that has the same radio name as another is + * sharing the same physical radio. This information can be used to + * share scan results etc. information between the virtual interfaces + * to speed up various operations. + */ + const char * (*get_radio_name)(void *priv); + + /** + * send_tdls_mgmt - for sending TDLS management packets + * @priv: private driver interface data + * @dst: Destination (peer) MAC address + * @action_code: TDLS action code for the mssage + * @dialog_token: Dialog Token to use in the message (if needed) + * @status_code: Status Code or Reason Code to use (if needed) + * @peer_capab: TDLS peer capability (TDLS_PEER_* bitfield) + * @initiator: Is the current end the TDLS link initiator + * @buf: TDLS IEs to add to the message + * @len: Length of buf in octets + * Returns: 0 on success, negative (<0) on failure + * + * This optional function can be used to send packet to driver which is + * responsible for receiving and sending all TDLS packets. + */ + int (*send_tdls_mgmt)(void *priv, const u8 *dst, u8 action_code, + u8 dialog_token, u16 status_code, u32 peer_capab, + int initiator, const u8 *buf, size_t len); + + /** + * tdls_oper - Ask the driver to perform high-level TDLS operations + * @priv: Private driver interface data + * @oper: TDLS high-level operation. See %enum tdls_oper + * @peer: Destination (peer) MAC address + * Returns: 0 on success, negative (<0) on failure + * + * This optional function can be used to send high-level TDLS commands + * to the driver. + */ + int (*tdls_oper)(void *priv, enum tdls_oper oper, const u8 *peer); + + /** + * wnm_oper - Notify driver of the WNM frame reception + * @priv: Private driver interface data + * @oper: WNM operation. See %enum wnm_oper + * @peer: Destination (peer) MAC address + * @buf: Buffer for the driver to fill in (for getting IE) + * @buf_len: Return the len of buf + * Returns: 0 on success, negative (<0) on failure + */ + int (*wnm_oper)(void *priv, enum wnm_oper oper, const u8 *peer, + u8 *buf, u16 *buf_len); + + /** + * set_qos_map - Set QoS Map + * @priv: Private driver interface data + * @qos_map_set: QoS Map + * @qos_map_set_len: Length of QoS Map + */ + int (*set_qos_map)(void *priv, const u8 *qos_map_set, + u8 qos_map_set_len); + + /** + * br_add_ip_neigh - Add a neigh to the bridge ip neigh table + * @priv: Private driver interface data + * @version: IP version of the IP address, 4 or 6 + * @ipaddr: IP address for the neigh entry + * @prefixlen: IP address prefix length + * @addr: Corresponding MAC address + * Returns: 0 on success, negative (<0) on failure + */ + int (*br_add_ip_neigh)(void *priv, u8 version, const u8 *ipaddr, + int prefixlen, const u8 *addr); + + /** + * br_delete_ip_neigh - Remove a neigh from the bridge ip neigh table + * @priv: Private driver interface data + * @version: IP version of the IP address, 4 or 6 + * @ipaddr: IP address for the neigh entry + * Returns: 0 on success, negative (<0) on failure + */ + int (*br_delete_ip_neigh)(void *priv, u8 version, const u8 *ipaddr); + + /** + * br_port_set_attr - Set a bridge port attribute + * @attr: Bridge port attribute to set + * @val: Value to be set + * Returns: 0 on success, negative (<0) on failure + */ + int (*br_port_set_attr)(void *priv, enum drv_br_port_attr attr, + unsigned int val); + + /** + * br_port_set_attr - Set a bridge network parameter + * @param: Bridge parameter to set + * @val: Value to be set + * Returns: 0 on success, negative (<0) on failure + */ + int (*br_set_net_param)(void *priv, enum drv_br_net_param param, + unsigned int val); + + /** + * set_wowlan - Set wake-on-wireless triggers + * @priv: Private driver interface data + * @triggers: wowlan triggers + */ + int (*set_wowlan)(void *priv, const struct wowlan_triggers *triggers); + + /** + * signal_poll - Get current connection information + * @priv: Private driver interface data + * @signal_info: Connection info structure + */ + int (*signal_poll)(void *priv, struct wpa_signal_info *signal_info); + + /** + * set_authmode - Set authentication algorithm(s) for static WEP + * @priv: Private driver interface data + * @authmode: 1=Open System, 2=Shared Key, 3=both + * Returns: 0 on success, -1 on failure + * + * This function can be used to set authentication algorithms for AP + * mode when static WEP is used. If the driver uses user space MLME/SME + * implementation, there is no need to implement this function. + * + * DEPRECATED - use set_ap() instead + */ + int (*set_authmode)(void *priv, int authmode); + +#ifdef ANDROID + /** + * driver_cmd - Execute driver-specific command + * @priv: Private driver interface data + * @cmd: Command to execute + * @buf: Return buffer + * @buf_len: Buffer length + * Returns: 0 on success, -1 on failure + */ + int (*driver_cmd)(void *priv, char *cmd, char *buf, size_t buf_len); +#endif /* ANDROID */ + + /** + * vendor_cmd - Execute vendor specific command + * @priv: Private driver interface data + * @vendor_id: Vendor id + * @subcmd: Vendor command id + * @data: Vendor command parameters (%NULL if no parameters) + * @data_len: Data length + * @buf: Return buffer (%NULL to ignore reply) + * Returns: 0 on success, negative (<0) on failure + * + * This function handles vendor specific commands that are passed to + * the driver/device. The command is identified by vendor id and + * command id. Parameters can be passed as argument to the command + * in the data buffer. Reply (if any) will be filled in the supplied + * return buffer. + * + * The exact driver behavior is driver interface and vendor specific. As + * an example, this will be converted to a vendor specific cfg80211 + * command in case of the nl80211 driver interface. + */ + int (*vendor_cmd)(void *priv, unsigned int vendor_id, + unsigned int subcmd, const u8 *data, size_t data_len, + struct wpabuf *buf); + + /** + * set_rekey_info - Set rekey information + * @priv: Private driver interface data + * @kek: Current KEK + * @kek_len: KEK length in octets + * @kck: Current KCK + * @kck_len: KCK length in octets + * @replay_ctr: Current EAPOL-Key Replay Counter + * + * This optional function can be used to provide information for the + * driver/firmware to process EAPOL-Key frames in Group Key Handshake + * while the host (including wpa_supplicant) is sleeping. + */ + void (*set_rekey_info)(void *priv, const u8 *kek, size_t kek_len, + const u8 *kck, size_t kck_len, + const u8 *replay_ctr); + + /** + * sta_assoc - Station association indication + * @priv: Private driver interface data + * @own_addr: Source address and BSSID for association frame + * @addr: MAC address of the station to associate + * @reassoc: flag to indicate re-association + * @status: association response status code + * @ie: assoc response ie buffer + * @len: ie buffer length + * Returns: 0 on success, -1 on failure + * + * This function indicates the driver to send (Re)Association + * Response frame to the station. + */ + int (*sta_assoc)(void *priv, const u8 *own_addr, const u8 *addr, + int reassoc, u16 status, const u8 *ie, size_t len); + + /** + * sta_auth - Station authentication indication + * @priv: Private driver interface data + * @own_addr: Source address and BSSID for authentication frame + * @addr: MAC address of the station to associate + * @seq: authentication sequence number + * @status: authentication response status code + * @ie: authentication frame ie buffer + * @len: ie buffer length + * + * This function indicates the driver to send Authentication frame + * to the station. + */ + int (*sta_auth)(void *priv, const u8 *own_addr, const u8 *addr, + u16 seq, u16 status, const u8 *ie, size_t len); + + /** + * add_tspec - Add traffic stream + * @priv: Private driver interface data + * @addr: MAC address of the station to associate + * @tspec_ie: tspec ie buffer + * @tspec_ielen: tspec ie length + * Returns: 0 on success, -1 on failure + * + * This function adds the traffic steam for the station + * and fills the medium_time in tspec_ie. + */ + int (*add_tspec)(void *priv, const u8 *addr, u8 *tspec_ie, + size_t tspec_ielen); + + /** + * add_sta_node - Add a station node in the driver + * @priv: Private driver interface data + * @addr: MAC address of the station to add + * @auth_alg: authentication algorithm used by the station + * Returns: 0 on success, -1 on failure + * + * This function adds the station node in the driver, when + * the station gets added by FT-over-DS. + */ + int (*add_sta_node)(void *priv, const u8 *addr, u16 auth_alg); + + /** + * sched_scan - Request the driver to initiate scheduled scan + * @priv: Private driver interface data + * @params: Scan parameters + * @interval: Interval between scan cycles in milliseconds + * Returns: 0 on success, -1 on failure + * + * This operation should be used for scheduled scan offload to + * the hardware. Every time scan results are available, the + * driver should report scan results event for wpa_supplicant + * which will eventually request the results with + * wpa_driver_get_scan_results2(). This operation is optional + * and if not provided or if it returns -1, we fall back to + * normal host-scheduled scans. + */ + int (*sched_scan)(void *priv, struct wpa_driver_scan_params *params, + u32 interval); + + /** + * stop_sched_scan - Request the driver to stop a scheduled scan + * @priv: Private driver interface data + * Returns: 0 on success, -1 on failure + * + * This should cause the scheduled scan to be stopped and + * results should stop being sent. Must be supported if + * sched_scan is supported. + */ + int (*stop_sched_scan)(void *priv); + + /** + * poll_client - Probe (null data or such) the given station + * @priv: Private driver interface data + * @own_addr: MAC address of sending interface + * @addr: MAC address of the station to probe + * @qos: Indicates whether station is QoS station + * + * This function is used to verify whether an associated station is + * still present. This function does not need to be implemented if the + * driver provides such inactivity polling mechanism. + */ + void (*poll_client)(void *priv, const u8 *own_addr, + const u8 *addr, int qos); + + /** + * radio_disable - Disable/enable radio + * @priv: Private driver interface data + * @disabled: 1=disable 0=enable radio + * Returns: 0 on success, -1 on failure + * + * This optional command is for testing purposes. It can be used to + * disable the radio on a testbed device to simulate out-of-radio-range + * conditions. + */ + int (*radio_disable)(void *priv, int disabled); + + /** + * switch_channel - Announce channel switch and migrate the GO to the + * given frequency + * @priv: Private driver interface data + * @settings: Settings for CSA period and new channel + * Returns: 0 on success, -1 on failure + * + * This function is used to move the GO to the legacy STA channel to + * avoid frequency conflict in single channel concurrency. + */ + int (*switch_channel)(void *priv, struct csa_settings *settings); + + /** + * add_tx_ts - Add traffic stream + * @priv: Private driver interface data + * @tsid: Traffic stream ID + * @addr: Receiver address + * @user_prio: User priority of the traffic stream + * @admitted_time: Admitted time for this TS in units of + * 32 microsecond periods (per second). + * Returns: 0 on success, -1 on failure + */ + int (*add_tx_ts)(void *priv, u8 tsid, const u8 *addr, u8 user_prio, + u16 admitted_time); + + /** + * del_tx_ts - Delete traffic stream + * @priv: Private driver interface data + * @tsid: Traffic stream ID + * @addr: Receiver address + * Returns: 0 on success, -1 on failure + */ + int (*del_tx_ts)(void *priv, u8 tsid, const u8 *addr); + + /** + * Enable channel-switching with TDLS peer + * @priv: Private driver interface data + * @addr: MAC address of the TDLS peer + * @oper_class: Operating class of the switch channel + * @params: Channel specification + * Returns: 0 on success, -1 on failure + * + * The function indicates to driver that it can start switching to a + * different channel with a specified TDLS peer. The switching is + * assumed on until canceled with tdls_disable_channel_switch(). + */ + int (*tdls_enable_channel_switch)( + void *priv, const u8 *addr, u8 oper_class, + const struct hostapd_freq_params *params); + + /** + * Disable channel switching with TDLS peer + * @priv: Private driver interface data + * @addr: MAC address of the TDLS peer + * Returns: 0 on success, -1 on failure + * + * This function indicates to the driver that it should stop switching + * with a given TDLS peer. + */ + int (*tdls_disable_channel_switch)(void *priv, const u8 *addr); + + /** + * start_dfs_cac - Listen for radar interference on the channel + * @priv: Private driver interface data + * @freq: Channel parameters + * Returns: 0 on success, -1 on failure + */ + int (*start_dfs_cac)(void *priv, struct hostapd_freq_params *freq); + + /** + * stop_ap - Removes beacon from AP + * @priv: Private driver interface data + * Returns: 0 on success, -1 on failure (or if not supported) + * + * This optional function can be used to disable AP mode related + * configuration. Unlike deinit_ap, it does not change to station + * mode. + */ + int (*stop_ap)(void *priv); + + /** + * get_survey - Retrieve survey data + * @priv: Private driver interface data + * @freq: If set, survey data for the specified frequency is only + * being requested. If not set, all survey data is requested. + * Returns: 0 on success, -1 on failure + * + * Use this to retrieve: + * + * - the observed channel noise floor + * - the amount of time we have spent on the channel + * - the amount of time during which we have spent on the channel that + * the radio has determined the medium is busy and we cannot + * transmit + * - the amount of time we have spent receiving data + * - the amount of time we have spent transmitting data + * + * This data can be used for spectrum heuristics. One example is + * Automatic Channel Selection (ACS). The channel survey data is + * kept on a linked list on the channel data, one entry is added + * for each survey. The min_nf of the channel is updated for each + * survey. + */ + int (*get_survey)(void *priv, unsigned int freq); + + /** + * status - Get driver interface status information + * @priv: Private driver interface data + * @buf: Buffer for printing tou the status information + * @buflen: Maximum length of the buffer + * Returns: Length of written status information or -1 on failure + */ + int (*status)(void *priv, char *buf, size_t buflen); + + /** + * roaming - Set roaming policy for driver-based BSS selection + * @priv: Private driver interface data + * @allowed: Whether roaming within ESS is allowed + * @bssid: Forced BSSID if roaming is disabled or %NULL if not set + * Returns: Length of written status information or -1 on failure + * + * This optional callback can be used to update roaming policy from the + * associate() command (bssid being set there indicates that the driver + * should not roam before getting this roaming() call to allow roaming. + * If the driver does not indicate WPA_DRIVER_FLAGS_BSS_SELECTION + * capability, roaming policy is handled within wpa_supplicant and there + * is no need to implement or react to this callback. + */ + int (*roaming)(void *priv, int allowed, const u8 *bssid); + + /** + * set_mac_addr - Set MAC address + * @priv: Private driver interface data + * @addr: MAC address to use or %NULL for setting back to permanent + * Returns: 0 on success, -1 on failure + */ + int (*set_mac_addr)(void *priv, const u8 *addr); + +#ifdef CONFIG_MACSEC + int (*macsec_init)(void *priv, struct macsec_init_params *params); + + int (*macsec_deinit)(void *priv); + + /** + * enable_protect_frames - Set protect frames status + * @priv: Private driver interface data + * @enabled: TRUE = protect frames enabled + * FALSE = protect frames disabled + * Returns: 0 on success, -1 on failure (or if not supported) + */ + int (*enable_protect_frames)(void *priv, Boolean enabled); + + /** + * set_replay_protect - Set replay protect status and window size + * @priv: Private driver interface data + * @enabled: TRUE = replay protect enabled + * FALSE = replay protect disabled + * @window: replay window size, valid only when replay protect enabled + * Returns: 0 on success, -1 on failure (or if not supported) + */ + int (*set_replay_protect)(void *priv, Boolean enabled, u32 window); + + /** + * set_current_cipher_suite - Set current cipher suite + * @priv: Private driver interface data + * @cs: EUI64 identifier + * @cs_len: Length of the cs buffer in octets + * Returns: 0 on success, -1 on failure (or if not supported) + */ + int (*set_current_cipher_suite)(void *priv, const u8 *cs, + size_t cs_len); + + /** + * enable_controlled_port - Set controlled port status + * @priv: Private driver interface data + * @enabled: TRUE = controlled port enabled + * FALSE = controlled port disabled + * Returns: 0 on success, -1 on failure (or if not supported) + */ + int (*enable_controlled_port)(void *priv, Boolean enabled); + + /** + * get_receive_lowest_pn - Get receive lowest pn + * @priv: Private driver interface data + * @channel: secure channel + * @an: association number + * @lowest_pn: lowest accept pn + * Returns: 0 on success, -1 on failure (or if not supported) + */ + int (*get_receive_lowest_pn)(void *priv, u32 channel, u8 an, + u32 *lowest_pn); + + /** + * get_transmit_next_pn - Get transmit next pn + * @priv: Private driver interface data + * @channel: secure channel + * @an: association number + * @next_pn: next pn + * Returns: 0 on success, -1 on failure (or if not supported) + */ + int (*get_transmit_next_pn)(void *priv, u32 channel, u8 an, + u32 *next_pn); + + /** + * set_transmit_next_pn - Set transmit next pn + * @priv: Private driver interface data + * @channel: secure channel + * @an: association number + * @next_pn: next pn + * Returns: 0 on success, -1 on failure (or if not supported) + */ + int (*set_transmit_next_pn)(void *priv, u32 channel, u8 an, + u32 next_pn); + + /** + * get_available_receive_sc - get available receive channel + * @priv: Private driver interface data + * @channel: secure channel + * Returns: 0 on success, -1 on failure (or if not supported) + */ + int (*get_available_receive_sc)(void *priv, u32 *channel); + + /** + * create_receive_sc - create secure channel for receiving + * @priv: Private driver interface data + * @channel: secure channel + * @sci_addr: secure channel identifier - address + * @sci_port: secure channel identifier - port + * @conf_offset: confidentiality offset (0, 30, or 50) + * @validation: frame validation policy (0 = Disabled, 1 = Checked, + * 2 = Strict) + * Returns: 0 on success, -1 on failure (or if not supported) + */ + int (*create_receive_sc)(void *priv, u32 channel, const u8 *sci_addr, + u16 sci_port, unsigned int conf_offset, + int validation); + + /** + * delete_receive_sc - delete secure connection for receiving + * @priv: private driver interface data from init() + * @channel: secure channel + * Returns: 0 on success, -1 on failure + */ + int (*delete_receive_sc)(void *priv, u32 channel); + + /** + * create_receive_sa - create secure association for receive + * @priv: private driver interface data from init() + * @channel: secure channel + * @an: association number + * @lowest_pn: the lowest packet number can be received + * @sak: the secure association key + * Returns: 0 on success, -1 on failure + */ + int (*create_receive_sa)(void *priv, u32 channel, u8 an, + u32 lowest_pn, const u8 *sak); + + /** + * enable_receive_sa - enable the SA for receive + * @priv: private driver interface data from init() + * @channel: secure channel + * @an: association number + * Returns: 0 on success, -1 on failure + */ + int (*enable_receive_sa)(void *priv, u32 channel, u8 an); + + /** + * disable_receive_sa - disable SA for receive + * @priv: private driver interface data from init() + * @channel: secure channel index + * @an: association number + * Returns: 0 on success, -1 on failure + */ + int (*disable_receive_sa)(void *priv, u32 channel, u8 an); + + /** + * get_available_transmit_sc - get available transmit channel + * @priv: Private driver interface data + * @channel: secure channel + * Returns: 0 on success, -1 on failure (or if not supported) + */ + int (*get_available_transmit_sc)(void *priv, u32 *channel); + + /** + * create_transmit_sc - create secure connection for transmit + * @priv: private driver interface data from init() + * @channel: secure channel + * @sci_addr: secure channel identifier - address + * @sci_port: secure channel identifier - port + * Returns: 0 on success, -1 on failure + */ + int (*create_transmit_sc)(void *priv, u32 channel, const u8 *sci_addr, + u16 sci_port, unsigned int conf_offset); + + /** + * delete_transmit_sc - delete secure connection for transmit + * @priv: private driver interface data from init() + * @channel: secure channel + * Returns: 0 on success, -1 on failure + */ + int (*delete_transmit_sc)(void *priv, u32 channel); + + /** + * create_transmit_sa - create secure association for transmit + * @priv: private driver interface data from init() + * @channel: secure channel index + * @an: association number + * @next_pn: the packet number used as next transmit packet + * @confidentiality: True if the SA is to provide confidentiality + * as well as integrity + * @sak: the secure association key + * Returns: 0 on success, -1 on failure + */ + int (*create_transmit_sa)(void *priv, u32 channel, u8 an, u32 next_pn, + Boolean confidentiality, const u8 *sak); + + /** + * enable_transmit_sa - enable SA for transmit + * @priv: private driver interface data from init() + * @channel: secure channel + * @an: association number + * Returns: 0 on success, -1 on failure + */ + int (*enable_transmit_sa)(void *priv, u32 channel, u8 an); + + /** + * disable_transmit_sa - disable SA for transmit + * @priv: private driver interface data from init() + * @channel: secure channel + * @an: association number + * Returns: 0 on success, -1 on failure + */ + int (*disable_transmit_sa)(void *priv, u32 channel, u8 an); +#endif /* CONFIG_MACSEC */ + + /** + * init_mesh - Driver specific initialization for mesh + * @priv: Private driver interface data + * Returns: 0 on success, -1 on failure + */ + int (*init_mesh)(void *priv); + + /** + * join_mesh - Join a mesh network + * @priv: Private driver interface data + * @params: Mesh configuration parameters + * Returns: 0 on success, -1 on failure + */ + int (*join_mesh)(void *priv, + struct wpa_driver_mesh_join_params *params); + + /** + * leave_mesh - Leave a mesh network + * @priv: Private driver interface data + * Returns 0 on success, -1 on failure + */ + int (*leave_mesh)(void *priv); + + /** + * do_acs - Automatically select channel + * @priv: Private driver interface data + * @params: Parameters for ACS + * Returns 0 on success, -1 on failure + * + * This command can be used to offload ACS to the driver if the driver + * indicates support for such offloading (WPA_DRIVER_FLAGS_ACS_OFFLOAD). + */ + int (*do_acs)(void *priv, struct drv_acs_params *params); + + /** + * set_band - Notify driver of band selection + * @priv: Private driver interface data + * @band: The selected band(s) + * Returns 0 on success, -1 on failure + */ + int (*set_band)(void *priv, enum set_band band); + + /** + * get_pref_freq_list - Get preferred frequency list for an interface + * @priv: Private driver interface data + * @if_type: Interface type + * @num: Number of channels + * @freq_list: Preferred channel frequency list encoded in MHz values + * Returns 0 on success, -1 on failure + * + * This command can be used to query the preferred frequency list from + * the driver specific to a particular interface type. + */ + int (*get_pref_freq_list)(void *priv, enum wpa_driver_if_type if_type, + unsigned int *num, unsigned int *freq_list); + + /** + * set_prob_oper_freq - Indicate probable P2P operating channel + * @priv: Private driver interface data + * @freq: Channel frequency in MHz + * Returns 0 on success, -1 on failure + * + * This command can be used to inform the driver of the operating + * frequency that an ongoing P2P group formation is likely to come up + * on. Local device is assuming P2P Client role. + */ + int (*set_prob_oper_freq)(void *priv, unsigned int freq); +}; + + +/** + * enum wpa_event_type - Event type for wpa_supplicant_event() calls + */ +enum wpa_event_type { + /** + * EVENT_ASSOC - Association completed + * + * This event needs to be delivered when the driver completes IEEE + * 802.11 association or reassociation successfully. + * wpa_driver_ops::get_bssid() is expected to provide the current BSSID + * after this event has been generated. In addition, optional + * EVENT_ASSOCINFO may be generated just before EVENT_ASSOC to provide + * more information about the association. If the driver interface gets + * both of these events at the same time, it can also include the + * assoc_info data in EVENT_ASSOC call. + */ + EVENT_ASSOC, + + /** + * EVENT_DISASSOC - Association lost + * + * This event should be called when association is lost either due to + * receiving deauthenticate or disassociate frame from the AP or when + * sending either of these frames to the current AP. If the driver + * supports separate deauthentication event, EVENT_DISASSOC should only + * be used for disassociation and EVENT_DEAUTH for deauthentication. + * In AP mode, union wpa_event_data::disassoc_info is required. + */ + EVENT_DISASSOC, + + /** + * EVENT_MICHAEL_MIC_FAILURE - Michael MIC (TKIP) detected + * + * This event must be delivered when a Michael MIC error is detected by + * the local driver. Additional data for event processing is + * provided with union wpa_event_data::michael_mic_failure. This + * information is used to request new encyption key and to initiate + * TKIP countermeasures if needed. + */ + EVENT_MICHAEL_MIC_FAILURE, + + /** + * EVENT_SCAN_RESULTS - Scan results available + * + * This event must be called whenever scan results are available to be + * fetched with struct wpa_driver_ops::get_scan_results(). This event + * is expected to be used some time after struct wpa_driver_ops::scan() + * is called. If the driver provides an unsolicited event when the scan + * has been completed, this event can be used to trigger + * EVENT_SCAN_RESULTS call. If such event is not available from the + * driver, the driver wrapper code is expected to use a registered + * timeout to generate EVENT_SCAN_RESULTS call after the time that the + * scan is expected to be completed. Optional information about + * completed scan can be provided with union wpa_event_data::scan_info. + */ + EVENT_SCAN_RESULTS, + + /** + * EVENT_ASSOCINFO - Report optional extra information for association + * + * This event can be used to report extra association information for + * EVENT_ASSOC processing. This extra information includes IEs from + * association frames and Beacon/Probe Response frames in union + * wpa_event_data::assoc_info. EVENT_ASSOCINFO must be send just before + * EVENT_ASSOC. Alternatively, the driver interface can include + * assoc_info data in the EVENT_ASSOC call if it has all the + * information available at the same point. + */ + EVENT_ASSOCINFO, + + /** + * EVENT_INTERFACE_STATUS - Report interface status changes + * + * This optional event can be used to report changes in interface + * status (interface added/removed) using union + * wpa_event_data::interface_status. This can be used to trigger + * wpa_supplicant to stop and re-start processing for the interface, + * e.g., when a cardbus card is ejected/inserted. + */ + EVENT_INTERFACE_STATUS, + + /** + * EVENT_PMKID_CANDIDATE - Report a candidate AP for pre-authentication + * + * This event can be used to inform wpa_supplicant about candidates for + * RSN (WPA2) pre-authentication. If wpa_supplicant is not responsible + * for scan request (ap_scan=2 mode), this event is required for + * pre-authentication. If wpa_supplicant is performing scan request + * (ap_scan=1), this event is optional since scan results can be used + * to add pre-authentication candidates. union + * wpa_event_data::pmkid_candidate is used to report the BSSID of the + * candidate and priority of the candidate, e.g., based on the signal + * strength, in order to try to pre-authenticate first with candidates + * that are most likely targets for re-association. + * + * EVENT_PMKID_CANDIDATE can be called whenever the driver has updates + * on the candidate list. In addition, it can be called for the current + * AP and APs that have existing PMKSA cache entries. wpa_supplicant + * will automatically skip pre-authentication in cases where a valid + * PMKSA exists. When more than one candidate exists, this event should + * be generated once for each candidate. + * + * Driver will be notified about successful pre-authentication with + * struct wpa_driver_ops::add_pmkid() calls. + */ + EVENT_PMKID_CANDIDATE, + + /** + * EVENT_STKSTART - Request STK handshake (MLME-STKSTART.request) + * + * This event can be used to inform wpa_supplicant about desire to set + * up secure direct link connection between two stations as defined in + * IEEE 802.11e with a new PeerKey mechanism that replaced the original + * STAKey negotiation. The caller will need to set peer address for the + * event. + */ + EVENT_STKSTART, + + /** + * EVENT_TDLS - Request TDLS operation + * + * This event can be used to request a TDLS operation to be performed. + */ + EVENT_TDLS, + + /** + * EVENT_FT_RESPONSE - Report FT (IEEE 802.11r) response IEs + * + * The driver is expected to report the received FT IEs from + * FT authentication sequence from the AP. The FT IEs are included in + * the extra information in union wpa_event_data::ft_ies. + */ + EVENT_FT_RESPONSE, + + /** + * EVENT_IBSS_RSN_START - Request RSN authentication in IBSS + * + * The driver can use this event to inform wpa_supplicant about a STA + * in an IBSS with which protected frames could be exchanged. This + * event starts RSN authentication with the other STA to authenticate + * the STA and set up encryption keys with it. + */ + EVENT_IBSS_RSN_START, + + /** + * EVENT_AUTH - Authentication result + * + * This event should be called when authentication attempt has been + * completed. This is only used if the driver supports separate + * authentication step (struct wpa_driver_ops::authenticate). + * Information about authentication result is included in + * union wpa_event_data::auth. + */ + EVENT_AUTH, + + /** + * EVENT_DEAUTH - Authentication lost + * + * This event should be called when authentication is lost either due + * to receiving deauthenticate frame from the AP or when sending that + * frame to the current AP. + * In AP mode, union wpa_event_data::deauth_info is required. + */ + EVENT_DEAUTH, + + /** + * EVENT_ASSOC_REJECT - Association rejected + * + * This event should be called when (re)association attempt has been + * rejected by the AP. Information about the association response is + * included in union wpa_event_data::assoc_reject. + */ + EVENT_ASSOC_REJECT, + + /** + * EVENT_AUTH_TIMED_OUT - Authentication timed out + */ + EVENT_AUTH_TIMED_OUT, + + /** + * EVENT_ASSOC_TIMED_OUT - Association timed out + */ + EVENT_ASSOC_TIMED_OUT, + + /** + * EVENT_WPS_BUTTON_PUSHED - Report hardware push button press for WPS + */ + EVENT_WPS_BUTTON_PUSHED, + + /** + * EVENT_TX_STATUS - Report TX status + */ + EVENT_TX_STATUS, + + /** + * EVENT_RX_FROM_UNKNOWN - Report RX from unknown STA + */ + EVENT_RX_FROM_UNKNOWN, + + /** + * EVENT_RX_MGMT - Report RX of a management frame + */ + EVENT_RX_MGMT, + + /** + * EVENT_REMAIN_ON_CHANNEL - Remain-on-channel duration started + * + * This event is used to indicate when the driver has started the + * requested remain-on-channel duration. Information about the + * operation is included in union wpa_event_data::remain_on_channel. + */ + EVENT_REMAIN_ON_CHANNEL, + + /** + * EVENT_CANCEL_REMAIN_ON_CHANNEL - Remain-on-channel timed out + * + * This event is used to indicate when the driver has completed + * remain-on-channel duration, i.e., may noot be available on the + * requested channel anymore. Information about the + * operation is included in union wpa_event_data::remain_on_channel. + */ + EVENT_CANCEL_REMAIN_ON_CHANNEL, + + /** + * EVENT_RX_PROBE_REQ - Indicate received Probe Request frame + * + * This event is used to indicate when a Probe Request frame has been + * received. Information about the received frame is included in + * union wpa_event_data::rx_probe_req. The driver is required to report + * these events only after successfully completed probe_req_report() + * commands to request the events (i.e., report parameter is non-zero) + * in station mode. In AP mode, Probe Request frames should always be + * reported. + */ + EVENT_RX_PROBE_REQ, + + /** + * EVENT_NEW_STA - New wired device noticed + * + * This event is used to indicate that a new device has been detected + * in a network that does not use association-like functionality (i.e., + * mainly wired Ethernet). This can be used to start EAPOL + * authenticator when receiving a frame from a device. The address of + * the device is included in union wpa_event_data::new_sta. + */ + EVENT_NEW_STA, + + /** + * EVENT_EAPOL_RX - Report received EAPOL frame + * + * When in AP mode with hostapd, this event is required to be used to + * deliver the receive EAPOL frames from the driver. + */ + EVENT_EAPOL_RX, + + /** + * EVENT_SIGNAL_CHANGE - Indicate change in signal strength + * + * This event is used to indicate changes in the signal strength + * observed in frames received from the current AP if signal strength + * monitoring has been enabled with signal_monitor(). + */ + EVENT_SIGNAL_CHANGE, + + /** + * EVENT_INTERFACE_ENABLED - Notify that interface was enabled + * + * This event is used to indicate that the interface was enabled after + * having been previously disabled, e.g., due to rfkill. + */ + EVENT_INTERFACE_ENABLED, + + /** + * EVENT_INTERFACE_DISABLED - Notify that interface was disabled + * + * This event is used to indicate that the interface was disabled, + * e.g., due to rfkill. + */ + EVENT_INTERFACE_DISABLED, + + /** + * EVENT_CHANNEL_LIST_CHANGED - Channel list changed + * + * This event is used to indicate that the channel list has changed, + * e.g., because of a regulatory domain change triggered by scan + * results including an AP advertising a country code. + */ + EVENT_CHANNEL_LIST_CHANGED, + + /** + * EVENT_INTERFACE_UNAVAILABLE - Notify that interface is unavailable + * + * This event is used to indicate that the driver cannot maintain this + * interface in its operation mode anymore. The most likely use for + * this is to indicate that AP mode operation is not available due to + * operating channel would need to be changed to a DFS channel when + * the driver does not support radar detection and another virtual + * interfaces caused the operating channel to change. Other similar + * resource conflicts could also trigger this for station mode + * interfaces. This event can be propagated when channel switching + * fails. + */ + EVENT_INTERFACE_UNAVAILABLE, + + /** + * EVENT_BEST_CHANNEL + * + * Driver generates this event whenever it detects a better channel + * (e.g., based on RSSI or channel use). This information can be used + * to improve channel selection for a new AP/P2P group. + */ + EVENT_BEST_CHANNEL, + + /** + * EVENT_UNPROT_DEAUTH - Unprotected Deauthentication frame received + * + * This event should be called when a Deauthentication frame is dropped + * due to it not being protected (MFP/IEEE 802.11w). + * union wpa_event_data::unprot_deauth is required to provide more + * details of the frame. + */ + EVENT_UNPROT_DEAUTH, + + /** + * EVENT_UNPROT_DISASSOC - Unprotected Disassociation frame received + * + * This event should be called when a Disassociation frame is dropped + * due to it not being protected (MFP/IEEE 802.11w). + * union wpa_event_data::unprot_disassoc is required to provide more + * details of the frame. + */ + EVENT_UNPROT_DISASSOC, + + /** + * EVENT_STATION_LOW_ACK + * + * Driver generates this event whenever it detected that a particular + * station was lost. Detection can be through massive transmission + * failures for example. + */ + EVENT_STATION_LOW_ACK, + + /** + * EVENT_IBSS_PEER_LOST - IBSS peer not reachable anymore + */ + EVENT_IBSS_PEER_LOST, + + /** + * EVENT_DRIVER_GTK_REKEY - Device/driver did GTK rekey + * + * This event carries the new replay counter to notify wpa_supplicant + * of the current EAPOL-Key Replay Counter in case the driver/firmware + * completed Group Key Handshake while the host (including + * wpa_supplicant was sleeping). + */ + EVENT_DRIVER_GTK_REKEY, + + /** + * EVENT_SCHED_SCAN_STOPPED - Scheduled scan was stopped + */ + EVENT_SCHED_SCAN_STOPPED, + + /** + * EVENT_DRIVER_CLIENT_POLL_OK - Station responded to poll + * + * This event indicates that the station responded to the poll + * initiated with @poll_client. + */ + EVENT_DRIVER_CLIENT_POLL_OK, + + /** + * EVENT_EAPOL_TX_STATUS - notify of EAPOL TX status + */ + EVENT_EAPOL_TX_STATUS, + + /** + * EVENT_CH_SWITCH - AP or GO decided to switch channels + * + * Described in wpa_event_data.ch_switch + * */ + EVENT_CH_SWITCH, + + /** + * EVENT_WNM - Request WNM operation + * + * This event can be used to request a WNM operation to be performed. + */ + EVENT_WNM, + + /** + * EVENT_CONNECT_FAILED_REASON - Connection failure reason in AP mode + * + * This event indicates that the driver reported a connection failure + * with the specified client (for example, max client reached, etc.) in + * AP mode. + */ + EVENT_CONNECT_FAILED_REASON, + + /** + * EVENT_DFS_RADAR_DETECTED - Notify of radar detection + * + * A radar has been detected on the supplied frequency, hostapd should + * react accordingly (e.g., change channel). + */ + EVENT_DFS_RADAR_DETECTED, + + /** + * EVENT_DFS_CAC_FINISHED - Notify that channel availability check has been completed + * + * After a successful CAC, the channel can be marked clear and used. + */ + EVENT_DFS_CAC_FINISHED, + + /** + * EVENT_DFS_CAC_ABORTED - Notify that channel availability check has been aborted + * + * The CAC was not successful, and the channel remains in the previous + * state. This may happen due to a radar beeing detected or other + * external influences. + */ + EVENT_DFS_CAC_ABORTED, + + /** + * EVENT_DFS_NOP_FINISHED - Notify that non-occupancy period is over + * + * The channel which was previously unavailable is now available again. + */ + EVENT_DFS_NOP_FINISHED, + + /** + * EVENT_SURVEY - Received survey data + * + * This event gets triggered when a driver query is issued for survey + * data and the requested data becomes available. The returned data is + * stored in struct survey_results. The results provide at most one + * survey entry for each frequency and at minimum will provide one + * survey entry for one frequency. The survey data can be os_malloc()'d + * and then os_free()'d, so the event callback must only copy data. + */ + EVENT_SURVEY, + + /** + * EVENT_SCAN_STARTED - Scan started + * + * This indicates that driver has started a scan operation either based + * on a request from wpa_supplicant/hostapd or from another application. + * EVENT_SCAN_RESULTS is used to indicate when the scan has been + * completed (either successfully or by getting cancelled). + */ + EVENT_SCAN_STARTED, + + /** + * EVENT_AVOID_FREQUENCIES - Received avoid frequency range + * + * This event indicates a set of frequency ranges that should be avoided + * to reduce issues due to interference or internal co-existence + * information in the driver. + */ + EVENT_AVOID_FREQUENCIES, + + /** + * EVENT_NEW_PEER_CANDIDATE - new (unknown) mesh peer notification + */ + EVENT_NEW_PEER_CANDIDATE, + + /** + * EVENT_ACS_CHANNEL_SELECTED - Received selected channels by ACS + * + * Indicates a pair of primary and secondary channels chosen by ACS + * in device. + */ + EVENT_ACS_CHANNEL_SELECTED, + + /** + * EVENT_DFS_CAC_STARTED - Notify that channel availability check has + * been started. + * + * This event indicates that channel availability check has been started + * on a DFS frequency by a driver that supports DFS Offload. + */ + EVENT_DFS_CAC_STARTED, +}; + + +/** + * struct freq_survey - Channel survey info + * + * @ifidx: Interface index in which this survey was observed + * @freq: Center of frequency of the surveyed channel + * @nf: Channel noise floor in dBm + * @channel_time: Amount of time in ms the radio spent on the channel + * @channel_time_busy: Amount of time in ms the radio detected some signal + * that indicated to the radio the channel was not clear + * @channel_time_rx: Amount of time the radio spent receiving data + * @channel_time_tx: Amount of time the radio spent transmitting data + * @filled: bitmask indicating which fields have been reported, see + * SURVEY_HAS_* defines. + * @list: Internal list pointers + */ +struct freq_survey { + u32 ifidx; + unsigned int freq; + s8 nf; + u64 channel_time; + u64 channel_time_busy; + u64 channel_time_rx; + u64 channel_time_tx; + unsigned int filled; + struct dl_list list; +}; + +#define SURVEY_HAS_NF BIT(0) +#define SURVEY_HAS_CHAN_TIME BIT(1) +#define SURVEY_HAS_CHAN_TIME_BUSY BIT(2) +#define SURVEY_HAS_CHAN_TIME_RX BIT(3) +#define SURVEY_HAS_CHAN_TIME_TX BIT(4) + + +/** + * union wpa_event_data - Additional data for wpa_supplicant_event() calls + */ +union wpa_event_data { + /** + * struct assoc_info - Data for EVENT_ASSOC and EVENT_ASSOCINFO events + * + * This structure is optional for EVENT_ASSOC calls and required for + * EVENT_ASSOCINFO calls. By using EVENT_ASSOC with this data, the + * driver interface does not need to generate separate EVENT_ASSOCINFO + * calls. + */ + struct assoc_info { + /** + * reassoc - Flag to indicate association or reassociation + */ + int reassoc; + + /** + * req_ies - (Re)Association Request IEs + * + * If the driver generates WPA/RSN IE, this event data must be + * returned for WPA handshake to have needed information. If + * wpa_supplicant-generated WPA/RSN IE is used, this + * information event is optional. + * + * This should start with the first IE (fixed fields before IEs + * are not included). + */ + const u8 *req_ies; + + /** + * req_ies_len - Length of req_ies in bytes + */ + size_t req_ies_len; + + /** + * resp_ies - (Re)Association Response IEs + * + * Optional association data from the driver. This data is not + * required WPA, but may be useful for some protocols and as + * such, should be reported if this is available to the driver + * interface. + * + * This should start with the first IE (fixed fields before IEs + * are not included). + */ + const u8 *resp_ies; + + /** + * resp_ies_len - Length of resp_ies in bytes + */ + size_t resp_ies_len; + + /** + * beacon_ies - Beacon or Probe Response IEs + * + * Optional Beacon/ProbeResp data: IEs included in Beacon or + * Probe Response frames from the current AP (i.e., the one + * that the client just associated with). This information is + * used to update WPA/RSN IE for the AP. If this field is not + * set, the results from previous scan will be used. If no + * data for the new AP is found, scan results will be requested + * again (without scan request). At this point, the driver is + * expected to provide WPA/RSN IE for the AP (if WPA/WPA2 is + * used). + * + * This should start with the first IE (fixed fields before IEs + * are not included). + */ + const u8 *beacon_ies; + + /** + * beacon_ies_len - Length of beacon_ies */ + size_t beacon_ies_len; + + /** + * freq - Frequency of the operational channel in MHz + */ + unsigned int freq; + + /** + * wmm_params - WMM parameters used in this association. + */ + struct wmm_params wmm_params; + + /** + * addr - Station address (for AP mode) + */ + const u8 *addr; + + /** + * The following is the key management offload information + * @authorized + * @key_replay_ctr + * @key_replay_ctr_len + * @ptk_kck + * @ptk_kek_len + * @ptk_kek + * @ptk_kek_len + */ + + /** + * authorized - Status of key management offload, + * 1 = successful + */ + int authorized; + + /** + * key_replay_ctr - Key replay counter value last used + * in a valid EAPOL-Key frame + */ + const u8 *key_replay_ctr; + + /** + * key_replay_ctr_len - The length of key_replay_ctr + */ + size_t key_replay_ctr_len; + + /** + * ptk_kck - The derived PTK KCK + */ + const u8 *ptk_kck; + + /** + * ptk_kek_len - The length of ptk_kck + */ + size_t ptk_kck_len; + + /** + * ptk_kek - The derived PTK KEK + */ + const u8 *ptk_kek; + + /** + * ptk_kek_len - The length of ptk_kek + */ + size_t ptk_kek_len; + } assoc_info; + + /** + * struct disassoc_info - Data for EVENT_DISASSOC events + */ + struct disassoc_info { + /** + * addr - Station address (for AP mode) + */ + const u8 *addr; + + /** + * reason_code - Reason Code (host byte order) used in + * Deauthentication frame + */ + u16 reason_code; + + /** + * ie - Optional IE(s) in Disassociation frame + */ + const u8 *ie; + + /** + * ie_len - Length of ie buffer in octets + */ + size_t ie_len; + + /** + * locally_generated - Whether the frame was locally generated + */ + int locally_generated; + } disassoc_info; + + /** + * struct deauth_info - Data for EVENT_DEAUTH events + */ + struct deauth_info { + /** + * addr - Station address (for AP mode) + */ + const u8 *addr; + + /** + * reason_code - Reason Code (host byte order) used in + * Deauthentication frame + */ + u16 reason_code; + + /** + * ie - Optional IE(s) in Deauthentication frame + */ + const u8 *ie; + + /** + * ie_len - Length of ie buffer in octets + */ + size_t ie_len; + + /** + * locally_generated - Whether the frame was locally generated + */ + int locally_generated; + } deauth_info; + + /** + * struct michael_mic_failure - Data for EVENT_MICHAEL_MIC_FAILURE + */ + struct michael_mic_failure { + int unicast; + const u8 *src; + } michael_mic_failure; + + /** + * struct interface_status - Data for EVENT_INTERFACE_STATUS + */ + struct interface_status { + char ifname[100]; + enum { + EVENT_INTERFACE_ADDED, EVENT_INTERFACE_REMOVED + } ievent; + } interface_status; + + /** + * struct pmkid_candidate - Data for EVENT_PMKID_CANDIDATE + */ + struct pmkid_candidate { + /** BSSID of the PMKID candidate */ + u8 bssid[ETH_ALEN]; + /** Smaller the index, higher the priority */ + int index; + /** Whether RSN IE includes pre-authenticate flag */ + int preauth; + } pmkid_candidate; + + /** + * struct stkstart - Data for EVENT_STKSTART + */ + struct stkstart { + u8 peer[ETH_ALEN]; + } stkstart; + + /** + * struct tdls - Data for EVENT_TDLS + */ + struct tdls { + u8 peer[ETH_ALEN]; + enum { + TDLS_REQUEST_SETUP, + TDLS_REQUEST_TEARDOWN, + TDLS_REQUEST_DISCOVER, + } oper; + u16 reason_code; /* for teardown */ + } tdls; + + /** + * struct wnm - Data for EVENT_WNM + */ + struct wnm { + u8 addr[ETH_ALEN]; + enum { + WNM_OPER_SLEEP, + } oper; + enum { + WNM_SLEEP_ENTER, + WNM_SLEEP_EXIT + } sleep_action; + int sleep_intval; + u16 reason_code; + u8 *buf; + u16 buf_len; + } wnm; + + /** + * struct ft_ies - FT information elements (EVENT_FT_RESPONSE) + * + * During FT (IEEE 802.11r) authentication sequence, the driver is + * expected to use this event to report received FT IEs (MDIE, FTIE, + * RSN IE, TIE, possible resource request) to the supplicant. The FT + * IEs for the next message will be delivered through the + * struct wpa_driver_ops::update_ft_ies() callback. + */ + struct ft_ies { + const u8 *ies; + size_t ies_len; + int ft_action; + u8 target_ap[ETH_ALEN]; + /** Optional IE(s), e.g., WMM TSPEC(s), for RIC-Request */ + const u8 *ric_ies; + /** Length of ric_ies buffer in octets */ + size_t ric_ies_len; + } ft_ies; + + /** + * struct ibss_rsn_start - Data for EVENT_IBSS_RSN_START + */ + struct ibss_rsn_start { + u8 peer[ETH_ALEN]; + } ibss_rsn_start; + + /** + * struct auth_info - Data for EVENT_AUTH events + */ + struct auth_info { + u8 peer[ETH_ALEN]; + u8 bssid[ETH_ALEN]; + u16 auth_type; + u16 auth_transaction; + u16 status_code; + const u8 *ies; + size_t ies_len; + } auth; + + /** + * struct assoc_reject - Data for EVENT_ASSOC_REJECT events + */ + struct assoc_reject { + /** + * bssid - BSSID of the AP that rejected association + */ + const u8 *bssid; + + /** + * resp_ies - (Re)Association Response IEs + * + * Optional association data from the driver. This data is not + * required WPA, but may be useful for some protocols and as + * such, should be reported if this is available to the driver + * interface. + * + * This should start with the first IE (fixed fields before IEs + * are not included). + */ + const u8 *resp_ies; + + /** + * resp_ies_len - Length of resp_ies in bytes + */ + size_t resp_ies_len; + + /** + * status_code - Status Code from (Re)association Response + */ + u16 status_code; + } assoc_reject; + + struct timeout_event { + u8 addr[ETH_ALEN]; + } timeout_event; + + /** + * struct tx_status - Data for EVENT_TX_STATUS events + */ + struct tx_status { + u16 type; + u16 stype; + const u8 *dst; + const u8 *data; + size_t data_len; + int ack; + } tx_status; + + /** + * struct rx_from_unknown - Data for EVENT_RX_FROM_UNKNOWN events + */ + struct rx_from_unknown { + const u8 *bssid; + const u8 *addr; + int wds; + } rx_from_unknown; + + /** + * struct rx_mgmt - Data for EVENT_RX_MGMT events + */ + struct rx_mgmt { + const u8 *frame; + size_t frame_len; + u32 datarate; + + /** + * drv_priv - Pointer to store driver private BSS information + * + * If not set to NULL, this is used for comparison with + * hostapd_data->drv_priv to determine which BSS should process + * the frame. + */ + void *drv_priv; + + /** + * freq - Frequency (in MHz) on which the frame was received + */ + int freq; + + /** + * ssi_signal - Signal strength in dBm (or 0 if not available) + */ + int ssi_signal; + } rx_mgmt; + + /** + * struct remain_on_channel - Data for EVENT_REMAIN_ON_CHANNEL events + * + * This is also used with EVENT_CANCEL_REMAIN_ON_CHANNEL events. + */ + struct remain_on_channel { + /** + * freq - Channel frequency in MHz + */ + unsigned int freq; + + /** + * duration - Duration to remain on the channel in milliseconds + */ + unsigned int duration; + } remain_on_channel; + + /** + * struct scan_info - Optional data for EVENT_SCAN_RESULTS events + * @aborted: Whether the scan was aborted + * @freqs: Scanned frequencies in MHz (%NULL = all channels scanned) + * @num_freqs: Number of entries in freqs array + * @ssids: Scanned SSIDs (%NULL or zero-length SSID indicates wildcard + * SSID) + * @num_ssids: Number of entries in ssids array + */ + struct scan_info { + int aborted; + const int *freqs; + size_t num_freqs; + struct wpa_driver_scan_ssid ssids[WPAS_MAX_SCAN_SSIDS]; + size_t num_ssids; + } scan_info; + + /** + * struct rx_probe_req - Data for EVENT_RX_PROBE_REQ events + */ + struct rx_probe_req { + /** + * sa - Source address of the received Probe Request frame + */ + const u8 *sa; + + /** + * da - Destination address of the received Probe Request frame + * or %NULL if not available + */ + const u8 *da; + + /** + * bssid - BSSID of the received Probe Request frame or %NULL + * if not available + */ + const u8 *bssid; + + /** + * ie - IEs from the Probe Request body + */ + const u8 *ie; + + /** + * ie_len - Length of ie buffer in octets + */ + size_t ie_len; + + /** + * signal - signal strength in dBm (or 0 if not available) + */ + int ssi_signal; + } rx_probe_req; + + /** + * struct new_sta - Data for EVENT_NEW_STA events + */ + struct new_sta { + const u8 *addr; + } new_sta; + + /** + * struct eapol_rx - Data for EVENT_EAPOL_RX events + */ + struct eapol_rx { + const u8 *src; + const u8 *data; + size_t data_len; + } eapol_rx; + + /** + * signal_change - Data for EVENT_SIGNAL_CHANGE events + */ + struct wpa_signal_info signal_change; + + /** + * struct best_channel - Data for EVENT_BEST_CHANNEL events + * @freq_24: Best 2.4 GHz band channel frequency in MHz + * @freq_5: Best 5 GHz band channel frequency in MHz + * @freq_overall: Best channel frequency in MHz + * + * 0 can be used to indicate no preference in either band. + */ + struct best_channel { + int freq_24; + int freq_5; + int freq_overall; + } best_chan; + + struct unprot_deauth { + const u8 *sa; + const u8 *da; + u16 reason_code; + } unprot_deauth; + + struct unprot_disassoc { + const u8 *sa; + const u8 *da; + u16 reason_code; + } unprot_disassoc; + + /** + * struct low_ack - Data for EVENT_STATION_LOW_ACK events + * @addr: station address + */ + struct low_ack { + u8 addr[ETH_ALEN]; + } low_ack; + + /** + * struct ibss_peer_lost - Data for EVENT_IBSS_PEER_LOST + */ + struct ibss_peer_lost { + u8 peer[ETH_ALEN]; + } ibss_peer_lost; + + /** + * struct driver_gtk_rekey - Data for EVENT_DRIVER_GTK_REKEY + */ + struct driver_gtk_rekey { + const u8 *bssid; + const u8 *replay_ctr; + } driver_gtk_rekey; + + /** + * struct client_poll - Data for EVENT_DRIVER_CLIENT_POLL_OK events + * @addr: station address + */ + struct client_poll { + u8 addr[ETH_ALEN]; + } client_poll; + + /** + * struct eapol_tx_status + * @dst: Original destination + * @data: Data starting with IEEE 802.1X header (!) + * @data_len: Length of data + * @ack: Indicates ack or lost frame + * + * This corresponds to hapd_send_eapol if the frame sent + * there isn't just reported as EVENT_TX_STATUS. + */ + struct eapol_tx_status { + const u8 *dst; + const u8 *data; + int data_len; + int ack; + } eapol_tx_status; + + /** + * struct ch_switch + * @freq: Frequency of new channel in MHz + * @ht_enabled: Whether this is an HT channel + * @ch_offset: Secondary channel offset + * @ch_width: Channel width + * @cf1: Center frequency 1 + * @cf2: Center frequency 2 + */ + struct ch_switch { + int freq; + int ht_enabled; + int ch_offset; + enum chan_width ch_width; + int cf1; + int cf2; + } ch_switch; + + /** + * struct connect_failed - Data for EVENT_CONNECT_FAILED_REASON + * @addr: Remote client address + * @code: Reason code for connection failure + */ + struct connect_failed_reason { + u8 addr[ETH_ALEN]; + enum { + MAX_CLIENT_REACHED, + BLOCKED_CLIENT + } code; + } connect_failed_reason; + + /** + * struct dfs_event - Data for radar detected events + * @freq: Frequency of the channel in MHz + */ + struct dfs_event { + int freq; + int ht_enabled; + int chan_offset; + enum chan_width chan_width; + int cf1; + int cf2; + } dfs_event; + + /** + * survey_results - Survey result data for EVENT_SURVEY + * @freq_filter: Requested frequency survey filter, 0 if request + * was for all survey data + * @survey_list: Linked list of survey data (struct freq_survey) + */ + struct survey_results { + unsigned int freq_filter; + struct dl_list survey_list; /* struct freq_survey */ + } survey_results; + + /** + * channel_list_changed - Data for EVENT_CHANNEL_LIST_CHANGED + * @initiator: Initiator of the regulatory change + * @type: Regulatory change type + * @alpha2: Country code (or "" if not available) + */ + struct channel_list_changed { + enum reg_change_initiator initiator; + enum reg_type type; + char alpha2[3]; + } channel_list_changed; + + /** + * freq_range - List of frequency ranges + * + * This is used as the data with EVENT_AVOID_FREQUENCIES. + */ + struct wpa_freq_range_list freq_range; + + /** + * struct mesh_peer + * + * @peer: Peer address + * @ies: Beacon IEs + * @ie_len: Length of @ies + * + * Notification of new candidate mesh peer. + */ + struct mesh_peer { + const u8 *peer; + const u8 *ies; + size_t ie_len; + } mesh_peer; + + /** + * struct acs_selected_channels - Data for EVENT_ACS_CHANNEL_SELECTED + * @pri_channel: Selected primary channel + * @sec_channel: Selected secondary channel + * @vht_seg0_center_ch: VHT mode Segment0 center channel + * @vht_seg1_center_ch: VHT mode Segment1 center channel + * @ch_width: Selected Channel width by driver. Driver may choose to + * change hostapd configured ACS channel width due driver internal + * channel restrictions. + * hw_mode: Selected band (used with hw_mode=any) + */ + struct acs_selected_channels { + u8 pri_channel; + u8 sec_channel; + u8 vht_seg0_center_ch; + u8 vht_seg1_center_ch; + u16 ch_width; + enum hostapd_hw_mode hw_mode; + } acs_selected_channels; +}; + +/** + * wpa_supplicant_event - Report a driver event for wpa_supplicant + * @ctx: Context pointer (wpa_s); this is the ctx variable registered + * with struct wpa_driver_ops::init() + * @event: event type (defined above) + * @data: possible extra data for the event + * + * Driver wrapper code should call this function whenever an event is received + * from the driver. + */ +void wpa_supplicant_event(void *ctx, enum wpa_event_type event, + union wpa_event_data *data); +void wpa_supplicant_event_sta(void *ctx, enum wpa_event_type event, + union wpa_event_data *data); + + +/* + * The following inline functions are provided for convenience to simplify + * event indication for some of the common events. + */ + +static inline void drv_event_assoc(void *ctx, const u8 *addr, const u8 *ie, + size_t ielen, int reassoc) +{ + union wpa_event_data event; + os_memset(&event, 0, sizeof(event)); + event.assoc_info.reassoc = reassoc; + event.assoc_info.req_ies = ie; + event.assoc_info.req_ies_len = ielen; + event.assoc_info.addr = addr; + wpa_supplicant_event(ctx, EVENT_ASSOC, &event); +} + +static inline void drv_event_disassoc(void *ctx, const u8 *addr) +{ + union wpa_event_data event; + os_memset(&event, 0, sizeof(event)); + event.disassoc_info.addr = addr; + wpa_supplicant_event(ctx, EVENT_DISASSOC, &event); +} + +static inline void drv_event_eapol_rx(void *ctx, const u8 *src, const u8 *data, + size_t data_len) +{ + union wpa_event_data event; + os_memset(&event, 0, sizeof(event)); + event.eapol_rx.src = src; + event.eapol_rx.data = data; + event.eapol_rx.data_len = data_len; + wpa_supplicant_event(ctx, EVENT_EAPOL_RX, &event); +} + +/* driver_common.c */ +void wpa_scan_results_free(struct wpa_scan_results *res); + +/* Convert wpa_event_type to a string for logging */ +const char * event_to_string(enum wpa_event_type event); + +/* Convert chan_width to a string for logging and control interfaces */ +const char * channel_width_to_string(enum chan_width width); + +int ht_supported(const struct hostapd_hw_modes *mode); +int vht_supported(const struct hostapd_hw_modes *mode); + +struct wowlan_triggers * +wpa_get_wowlan_triggers(const char *wowlan_triggers, + const struct wpa_driver_capa *capa); + +/* NULL terminated array of linked in driver wrappers */ +extern const struct wpa_driver_ops *const wpa_drivers[]; + +#endif /* DRIVER_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/drivers/driver_beken.c b/beken_os/beken378/func/hostapd-2.5/src/drivers/driver_beken.c new file mode 100755 index 0000000..5e24439 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/drivers/driver_beken.c @@ -0,0 +1,1868 @@ +/* + * Driver interaction with Linux Host AP driver + * Copyright (c) 2003-2005, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "include.h" +#include "hostapd_intf_pub.h" +#include "uart_pub.h" + +#include "includes.h" +#include "common.h" +#include "driver.h" +#include "eloop.h" +#include "driver_beken.h" +#include "param_config.h" + +#include "common/ieee802_11_defs.h" +#include "common/ieee802_11_common.h" +#include "l2_packet/l2_packet.h" +#include "fake_socket.h" +#include "priv_netlink.h" +#include "netlink.h" +#include "hostapd_cfg.h" +#include "mac_common.h" +#include "signal.h" +#include "eloop.h" +#include "rw_pub.h" +#include "wlan_ui_pub.h" +#include "role_launch.h" + +static const u8 rfc1042_header[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; + +struct hostap_driver_data +{ + struct hostapd_data *hapd; + struct wpa_supplicant *wpa_s; + + char iface[IFNAMSIZ + 1]; + struct l2_packet_data *sock_xmit; /* raw packet xmit socket */ + int sock; /* raw packet socket for driver access */ + int ioctl_sock; /* socket for ioctl() use */ + + struct netlink_data *netlink; + u8 own_addr[ETH_ALEN]; + u8 vif_index; + + int we_version; + + u8 *generic_ie; + size_t generic_ie_len; + u8 *wps_ie; + size_t wps_ie_len; +}; + +static int hostapd_ioctl(void *priv, struct prism2_hostapd_param *param, int len); +static int hostap_set_iface_flags(void *priv, int dev_up); +extern uint32_t wpa_hostapd_queue_poll(uint32_t param); +extern int hapd_intf_add_vif(struct prism2_hostapd_param *param, int len); + +static void handle_data(struct hostap_driver_data *drv, u8 *buf, size_t len, + u16 stype) +{ + struct ieee80211_hdr *hdr; + u16 fc, ethertype; + u8 *pos, *sa; + size_t left; + union wpa_event_data event; + + if (len < sizeof(struct ieee80211_hdr)) + return; + + hdr = (struct ieee80211_hdr *) buf; + fc = le_to_host16(hdr->frame_control); + + if ((fc & (WLAN_FC_FROMDS | WLAN_FC_TODS)) != WLAN_FC_TODS) + { + os_printf("Not ToDS data frame (fc=0x%04x)\n", fc); + return; + } + + sa = hdr->addr2; + os_memset(&event, 0, sizeof(event)); + event.rx_from_unknown.bssid = 0; // get_hdr_bssid(hdr, len); wangzhilei0 + event.rx_from_unknown.addr = sa; + wpa_supplicant_event(drv->hapd, EVENT_RX_FROM_UNKNOWN, &event); + + pos = (u8 *) (hdr + 1); + left = len - sizeof(*hdr); + + if (left < sizeof(rfc1042_header)) + { + os_printf("Broken data frame\n"); + return; + } + + if (memcmp(pos, rfc1042_header, sizeof(rfc1042_header)) != 0) + { + os_printf("Invalid data frame\n"); + return; + } + pos += sizeof(rfc1042_header); + left -= sizeof(rfc1042_header); + + if (left < 2) + { + os_printf("No ethertype in data frame\n"); + return; + } + + ethertype = WPA_GET_BE16(pos); + pos += 2; + left -= 2; + switch (ethertype) + { + case ETH_P_PAE: + drv_event_eapol_rx(drv->hapd, sa, pos, left); + break; + + default: + os_printf("Unknown ethertype 0x%04x in data frame\n", ethertype); + break; + } +} + + +static void handle_tx_callback(struct hostap_driver_data *drv, u8 *buf, + size_t len, int ok) +{ + struct ieee80211_hdr *hdr; + u16 fc; + union wpa_event_data event; + + hdr = (struct ieee80211_hdr *) buf; + fc = le_to_host16(hdr->frame_control); + + os_memset(&event, 0, sizeof(event)); + event.tx_status.type = WLAN_FC_GET_TYPE(fc); + event.tx_status.stype = WLAN_FC_GET_STYPE(fc); + event.tx_status.dst = hdr->addr1; + event.tx_status.data = buf; + event.tx_status.data_len = len; + event.tx_status.ack = ok; + wpa_supplicant_event(drv->hapd, EVENT_TX_STATUS, &event); +} + + +static void handle_frame(struct hostap_driver_data *drv, u8 *buf, size_t len) +{ + struct ieee80211_hdr *hdr; + u16 fc, type, stype; + size_t data_len = len; + int ver; + union wpa_event_data event; + + /* PSPOLL is only 16 bytes, but driver does not (at least yet) pass + * these to user space */ + if (len < 24) + { + wpa_printf(MSG_MSGDUMP, "handle_frame: too short (%lu)", + (unsigned long) len); + return; + } + + hdr = (struct ieee80211_hdr *) buf; + fc = le_to_host16(hdr->frame_control); + type = WLAN_FC_GET_TYPE(fc); + stype = WLAN_FC_GET_STYPE(fc); + + if (type != WLAN_FC_TYPE_MGMT || stype != WLAN_FC_STYPE_BEACON) + { + wpa_hexdump(MSG_MSGDUMP, "Received management frame", + buf, len); + } + + ver = fc & WLAN_FC_PVER; + + /* protocol version 2 is reserved for indicating ACKed frame (TX + * callbacks), and version 1 for indicating failed frame (no ACK, TX + * callbacks) */ + if (ver == 1 || ver == 2) + { + handle_tx_callback(drv, buf, data_len, ver == 2 ? 1 : 0); + return; + } + else if (ver != 0) + { + os_printf("unknown protocol %d\n", ver); + return; + } + + switch (type) + { + case WLAN_FC_TYPE_MGMT: + os_memset(&event, 0, sizeof(event)); + event.rx_mgmt.frame = buf; + event.rx_mgmt.frame_len = data_len; + wpa_supplicant_event(drv->hapd, EVENT_RX_MGMT, &event); + break; + case WLAN_FC_TYPE_CTRL: + wpa_printf(MSG_DEBUG, "CTRL"); + break; + case WLAN_FC_TYPE_DATA: + wpa_printf(MSG_DEBUG, "DATA"); + handle_data(drv, buf, data_len, stype); + break; + default: + wpa_printf(MSG_DEBUG, "unknown frame type %d", type); + break; + } +} + + +static void handle_read(int sock, void *eloop_ctx, void *sock_ctx) +{ +#define TMP_BUF_LEN 512 + + int len; + unsigned char *buf; + struct hostap_driver_data *drv; + + drv = eloop_ctx; + buf = os_malloc(TMP_BUF_LEN); + if(!buf) { + os_printf("handle_read no mem\r\n"); + goto read_exit; + } + + len = fsocket_recv(sock, buf, TMP_BUF_LEN, 0); + if (len < 0) + { + wpa_printf(MSG_ERROR, "recv: %s", strerror(errno)); + goto read_exit; + } + + handle_frame(drv, buf, len); + +read_exit: + if(buf) + { + os_free(buf); + } + + return; +} + +static void handle_eapol(void *ctx, const u8 *src_addr, const u8 *buf, size_t len) +{ + struct hostap_driver_data *drv = ctx; + drv_event_eapol_rx(drv->hapd, src_addr, buf, len); +} + +int hostap_get_ifhwaddr(int sock, const char *ifname, u8 *addr) +{ + return 0; +} + +static int hostap_init_sockets(struct hostap_driver_data *drv, u8 *own_addr) +{ + int protocol = ETH_P_ALL; + protocol += drv->vif_index; + + drv->sock = fsocket_init(PF_PACKET, SOCK_RAW, protocol); + drv->sock_xmit = l2_packet_init(drv->iface, drv->own_addr, ETH_P_EAPOL, + handle_eapol, drv, 0); + + if (eloop_register_read_sock(drv->sock, handle_read, drv, NULL)) + { + wpa_printf(MSG_ERROR, "Could not register read socket"); + return -1; + } + + if (hostap_set_iface_flags(drv, 1)) + { + return -1; + } + + return hostap_get_ifhwaddr(drv->sock, drv->iface, own_addr); +} + + +static int hostap_send_mlme(void *priv, const u8 *msg, size_t len, int noack, + unsigned int freq) +{ + struct hostap_driver_data *drv = priv; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) msg; + int res; + S_TYPE_PTR type_ptr = os_zalloc(sizeof(S_TYPE_ST)); + + type_ptr->type = HOSTAPD_MGMT; + type_ptr->vif_index = drv->vif_index; + + /* Request TX callback */ + hdr->frame_control |= host_to_le16(BIT(1)); + res = fsocket_send(drv->sock, msg, len, type_ptr); + hdr->frame_control &= ~host_to_le16(BIT(1)); + + return res; +} + + +static int hostap_send_eapol(void *priv, const u8 *addr, const u8 *data, + size_t data_len, int encrypt, const u8 *own_addr, + u32 flags) +{ + struct hostap_driver_data *drv = priv; + int status; + + status = l2_packet_send(drv->sock_xmit, addr, ETH_P_EAPOL, data, data_len); + + return status; +} + + +static int hostap_sta_set_flags(void *priv, const u8 *addr, + unsigned int total_flags, unsigned int flags_or, + unsigned int flags_and) +{ + struct hostap_driver_data *drv = priv; + struct prism2_hostapd_param param; + + if (flags_or & WPA_STA_AUTHORIZED) + flags_or = BIT(5); /* WLAN_STA_AUTHORIZED */ + if (!(flags_and & WPA_STA_AUTHORIZED)) + flags_and = ~ BIT(5); + else + flags_and = ~0; + + memset(¶m, 0, sizeof(param)); + param.cmd = PRISM2_HOSTAPD_SET_FLAGS_STA; + memcpy(param.sta_addr, addr, ETH_ALEN); + param.u.set_flags_sta.flags_or = flags_or; + param.u.set_flags_sta.flags_and = flags_and; + param.vif_idx = drv->vif_index; + + return hostapd_ioctl(drv, ¶m, sizeof(param)); +} + + +static int hostap_set_iface_flags(void *priv, int dev_up) +{ + return 0; +} + + +static int hostapd_ioctl(void *priv, struct prism2_hostapd_param *param, + int len) +{ + struct hostap_driver_data *drv = priv; + struct iwreq iwr; + + memset(&iwr, 0, sizeof(iwr)); + os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); + iwr.u.data.pointer = (c_addr_t) param; + iwr.u.data.length = len; + + if (ioctl_inet(drv->ioctl_sock, drv->vif_index, PRISM2_IOCTL_HOSTAPD, (unsigned long)&iwr) < 0) + { + return -1; + } + + return 0; +} + +static int wpa_driver_hostap_set_key(const char *ifname, void *priv, + enum wpa_alg alg, const u8 *addr, + int key_idx, int set_tx, + const u8 *seq, size_t seq_len, + const u8 *key, size_t key_len) +{ + struct hostap_driver_data *drv = priv; + struct prism2_hostapd_param *param; + u8 *buf; + size_t blen; + int ret = 0; + + blen = sizeof(*param) + key_len; + buf = os_zalloc(blen); + if (buf == NULL) + return -1; + + param = (struct prism2_hostapd_param *) buf; + param->cmd = PRISM2_SET_ENCRYPTION; + if (addr == NULL) + memset(param->sta_addr, 0xff, ETH_ALEN); + else + memcpy(param->sta_addr, addr, ETH_ALEN); + + switch (alg) + { + case WPA_ALG_NONE: + os_strlcpy((char *) param->u.crypt.alg, "NONE", + HOSTAP_CRYPT_ALG_NAME_LEN); + break; + case WPA_ALG_WEP: + if(key_len == 13) + { + os_strlcpy((char *) param->u.crypt.alg, "WEP104", + HOSTAP_CRYPT_ALG_NAME_LEN); + } + else + { + os_strlcpy((char *) param->u.crypt.alg, "WEP40", + HOSTAP_CRYPT_ALG_NAME_LEN); + } + break; + case WPA_ALG_TKIP: + os_strlcpy((char *) param->u.crypt.alg, "TKIP", + HOSTAP_CRYPT_ALG_NAME_LEN); + break; + case WPA_ALG_CCMP: + os_strlcpy((char *) param->u.crypt.alg, "CCMP", + HOSTAP_CRYPT_ALG_NAME_LEN); + break; + default: + os_free(buf); + return -1; + } + param->u.crypt.flags = set_tx ? HOSTAP_CRYPT_FLAG_SET_TX_KEY : 0; + param->u.crypt.idx = key_idx; + param->u.crypt.key_len = key_len; + param->vif_idx = drv->vif_index; + + memcpy((u8 *) (param + 1), key, key_len); + + if (hostapd_ioctl(drv, param, blen)) + { + ret = -1; + } + os_free(buf); + + return ret; +} + + +static int hostap_get_seqnum(const char *ifname, void *priv, const u8 *addr, + int idx, u8 *seq) +{ + struct hostap_driver_data *drv = priv; + struct prism2_hostapd_param *param; + u8 *buf; + size_t blen; + int ret = 0; + + blen = sizeof(*param) + 32; + buf = os_zalloc(blen); + if (buf == NULL) + return -1; + + param = (struct prism2_hostapd_param *) buf; + param->cmd = PRISM2_GET_ENCRYPTION; + if (addr == NULL) + os_memset(param->sta_addr, 0xff, ETH_ALEN); + else + os_memcpy(param->sta_addr, addr, ETH_ALEN); + param->u.crypt.idx = idx; + + if (hostapd_ioctl(drv, param, blen)) + { + os_printf("Failed to get encryption.\n"); + ret = -1; + } + else + { + os_memcpy(seq, param->u.crypt.seq, 8); + } + os_free(buf); + + return ret; +} + + +static int hostap_ioctl_prism2param(void *priv, int param, int value) +{ + struct hostap_driver_data *drv = priv; + struct iwreq iwr; + int *i; + + memset(&iwr, 0, sizeof(iwr)); + os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); + i = (int *) iwr.u.name; + *i++ = param; + *i++ = value; + + if (ioctl_inet(drv->ioctl_sock, drv->vif_index, PRISM2_IOCTL_PRISM2_PARAM, (unsigned long)&iwr) < 0) + { + return -1; + } + + return 0; +} + + +static int hostap_set_ieee8021x(void *priv, struct wpa_bss_params *params) +{ + struct hostap_driver_data *drv = priv; + int enabled = params->enabled; + + /* enable kernel driver support for IEEE 802.1X */ + if (hostap_ioctl_prism2param(drv, PRISM2_PARAM_IEEE_802_1X, enabled)) + { + os_printf("Setup IEEE 802.1X failed\n"); + return -1; + } + + if (!enabled) + return 0; + + /* use host driver implementation of encryption to allow + * individual keys and passing plaintext EAPOL frames */ + if (hostap_ioctl_prism2param(drv, PRISM2_PARAM_HOST_DECRYPT, 1) || + hostap_ioctl_prism2param(drv, PRISM2_PARAM_HOST_ENCRYPT, 1)) + { + os_printf("Setup host-based encryption failed\n"); + return -1; + } + + return 0; +} + + +static int hostap_set_privacy(void *priv, int enabled) +{ + struct hostap_drvier_data *drv = priv; + + return hostap_ioctl_prism2param(drv, PRISM2_PARAM_PRIVACY_INVOKED, + enabled); +} + + +static int hostap_set_ssid(void *priv, const u8 *buf, int len) +{ + struct hostap_driver_data *drv = priv; + struct iwreq iwr; + + memset(&iwr, 0, sizeof(iwr)); + os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); + iwr.u.essid.flags = 1; /* SSID active */ + iwr.u.essid.pointer = (c_addr_t) buf; + iwr.u.essid.length = len + 1; + + if (ioctl_inet(drv->ioctl_sock, drv->vif_index, SIOCSIWESSID, (unsigned long)&iwr) < 0) + { + return -1; + } + + return 0; +} + + +static int hostap_flush(void *priv) +{ + struct hostap_driver_data *drv = priv; + struct prism2_hostapd_param param; + + memset(¶m, 0, sizeof(param)); + param.cmd = PRISM2_HOSTAPD_FLUSH; + return hostapd_ioctl(drv, ¶m, sizeof(param)); +} + + +static int hostap_read_sta_data(void *priv, + struct hostap_sta_driver_data *data, + const u8 *addr) +{ + return 0; +} + +static int wpa_driver_hostap_init_vif(void *priv, u32 type) +{ + struct hostap_driver_data *drv = priv; + struct prism2_hostapd_param param; + + memset(¶m, 0, sizeof(param)); + param.cmd = PRISM2_HOSTAPD_WPA_INIT_VIF; + memcpy(param.sta_addr, drv->own_addr, ETH_ALEN); + param.u.add_if.indx_ptr = &drv->vif_index; + param.u.add_if.type = type; + + return hapd_intf_add_vif(¶m, sizeof(param)); +} + +static int wpa_driver_hostap_deinit_vif(void *priv) +{ + struct hostap_driver_data *drv = priv; + struct prism2_hostapd_param param; + + memset(¶m, 0, sizeof(param)); + param.cmd = PRISM2_HOSTAPD_WPA_DEINIT_VIF; + memcpy(param.sta_addr, drv->own_addr, ETH_ALEN); + param.vif_idx = drv->vif_index; + + return hostapd_ioctl(drv, ¶m, sizeof(param)); +} + +static int wpa_driver_hostap_start_apm(void *priv) +{ + struct hostap_driver_data *drv = priv; + struct prism2_hostapd_param param; + + memset(¶m, 0, sizeof(param)); + param.cmd = PRISM2_HOSTAPD_START_APM; + memcpy(param.sta_addr, drv->own_addr, ETH_ALEN); + param.vif_idx = drv->vif_index; + + return hostapd_ioctl(drv, ¶m, sizeof(param)); +} + +static int wpa_driver_hostap_stop_apm(void *priv) +{ + struct hostap_driver_data *drv = priv; + struct prism2_hostapd_param param; + + memset(¶m, 0, sizeof(param)); + param.cmd = PRISM2_HOSTAPD_STOP_APM; + memcpy(param.sta_addr, drv->own_addr, ETH_ALEN); + param.vif_idx = drv->vif_index; + + return hostapd_ioctl(drv, ¶m, sizeof(param)); +} + + +static int hostap_sta_add(void *priv, struct hostapd_sta_add_params *params) +{ + struct hostap_driver_data *drv = priv; + struct prism2_hostapd_param param; + int tx_supp_rates = 0; + size_t i; + +#define WLAN_RATE_1M BIT(0) +#define WLAN_RATE_2M BIT(1) +#define WLAN_RATE_5M5 BIT(2) +#define WLAN_RATE_11M BIT(3) + + for (i = 0; i < params->supp_rates_len; i++) + { + if ((params->supp_rates[i] & 0x7f) == 2) + tx_supp_rates |= WLAN_RATE_1M; + if ((params->supp_rates[i] & 0x7f) == 4) + tx_supp_rates |= WLAN_RATE_2M; + if ((params->supp_rates[i] & 0x7f) == 11) + tx_supp_rates |= WLAN_RATE_5M5; + if ((params->supp_rates[i] & 0x7f) == 22) + tx_supp_rates |= WLAN_RATE_11M; + } + + memset(¶m, 0, sizeof(param)); + param.cmd = PRISM2_HOSTAPD_ADD_STA; + memcpy(param.sta_addr, params->addr, ETH_ALEN); + param.u.add_sta.aid = params->aid; + param.u.add_sta.capability = params->capability; + param.u.add_sta.tx_supp_rates = tx_supp_rates; + param.vif_idx = drv->vif_index; + + return hostapd_ioctl(drv, ¶m, sizeof(param)); +} + + +static int hostap_sta_remove(void *priv, const u8 *addr) +{ + struct hostap_driver_data *drv = priv; + struct prism2_hostapd_param param; + + hostap_sta_set_flags(drv, addr, 0, 0, ~WPA_STA_AUTHORIZED); + + memset(¶m, 0, sizeof(param)); + param.cmd = PRISM2_HOSTAPD_REMOVE_STA; + memcpy(param.sta_addr, addr, ETH_ALEN); + + param.vif_idx = drv->vif_index; + if (hostapd_ioctl(drv, ¶m, sizeof(param))) + { + os_printf("Remove station failed\n"); + return -1; + } + return 0; +} + + +static int hostap_get_inact_sec(void *priv, const u8 *addr) +{ + struct hostap_driver_data *drv = priv; + struct prism2_hostapd_param param; + + memset(¶m, 0, sizeof(param)); + param.cmd = PRISM2_HOSTAPD_GET_INFO_STA; + memcpy(param.sta_addr, addr, ETH_ALEN); + if (hostapd_ioctl(drv, ¶m, sizeof(param))) + { + return -1; + } + + return param.u.get_info_sta.inactive_sec; +} + + +static int hostap_sta_clear_stats(void *priv, const u8 *addr) +{ + struct hostap_driver_data *drv = priv; + struct prism2_hostapd_param param; + + memset(¶m, 0, sizeof(param)); + param.cmd = PRISM2_HOSTAPD_STA_CLEAR_STATS; + memcpy(param.sta_addr, addr, ETH_ALEN); + if (hostapd_ioctl(drv, ¶m, sizeof(param))) + { + return -1; + } + + return 0; +} + + +static int hostapd_ioctl_set_generic_elem(struct hostap_driver_data *drv) +{ + struct prism2_hostapd_param *param; + int res; + size_t blen, elem_len; + + elem_len = drv->generic_ie_len + drv->wps_ie_len; + blen = PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN + elem_len; + if (blen < sizeof(*param)) + blen = sizeof(*param); + + param = os_zalloc(blen); + if (param == NULL) + return -1; + + param->cmd = PRISM2_HOSTAPD_SET_GENERIC_ELEMENT; + param->u.generic_elem.len = elem_len; + if (drv->generic_ie) + { + os_memcpy(param->u.generic_elem.data, drv->generic_ie, + drv->generic_ie_len); + } + if (drv->wps_ie) + { + os_memcpy(¶m->u.generic_elem.data[drv->generic_ie_len], + drv->wps_ie, drv->wps_ie_len); + } + wpa_hexdump(MSG_DEBUG, "hostap: Set generic IE", + param->u.generic_elem.data, elem_len); + res = hostapd_ioctl(drv, param, blen); + + os_free(param); + + return res; +} + + +static int hostap_set_generic_elem(void *priv, + const u8 *elem, size_t elem_len) +{ + struct hostap_driver_data *drv = priv; + + os_free(drv->generic_ie); + drv->generic_ie = NULL; + drv->generic_ie_len = 0; + if (elem) + { + drv->generic_ie = os_malloc(elem_len); + if (drv->generic_ie == NULL) + return -1; + os_memcpy(drv->generic_ie, elem, elem_len); + drv->generic_ie_len = elem_len; + } + + return hostapd_ioctl_set_generic_elem(drv); +} + + +static int hostap_set_ap_wps_ie(void *priv, const struct wpabuf *beacon, + const struct wpabuf *proberesp, + const struct wpabuf *assocresp) +{ + struct hostap_driver_data *drv = priv; + + /* + * Host AP driver supports only one set of extra IEs, so we need to + * use the Probe Response IEs also for Beacon frames since they include + * more information. + */ + + os_free(drv->wps_ie); + drv->wps_ie = NULL; + drv->wps_ie_len = 0; + if (proberesp) + { + drv->wps_ie = os_malloc(wpabuf_len(proberesp)); + if (drv->wps_ie == NULL) + return -1; + os_memcpy(drv->wps_ie, wpabuf_head(proberesp), + wpabuf_len(proberesp)); + drv->wps_ie_len = wpabuf_len(proberesp); + } + + return hostapd_ioctl_set_generic_elem(drv); +} + + +static void +hostapd_wireless_event_wireless_custom(struct hostap_driver_data *drv, + char *custom) +{ + wpa_printf(MSG_DEBUG, "Custom wireless event: '%s'", custom); + + if (strncmp(custom, "MLME-MICHAELMICFAILURE.indication", 33) == 0) + { + char *pos; + u8 addr[ETH_ALEN]; + pos = strstr(custom, "addr="); + if (pos == NULL) + { + wpa_printf(MSG_DEBUG, + "MLME-MICHAELMICFAILURE.indication " + "without sender address ignored"); + return; + } + pos += 5; + if (hwaddr_aton(pos, addr) == 0) + { + union wpa_event_data data; + os_memset(&data, 0, sizeof(data)); + data.michael_mic_failure.unicast = 1; + data.michael_mic_failure.src = addr; + wpa_supplicant_event(drv->hapd, + EVENT_MICHAEL_MIC_FAILURE, &data); + } + else + { + wpa_printf(MSG_DEBUG, + "MLME-MICHAELMICFAILURE.indication " + "with invalid MAC address"); + } + } +} + + +static void hostapd_wireless_event_wireless(struct hostap_driver_data *drv, + char *data, int len) +{ + struct iw_event iwe_buf, *iwe = &iwe_buf; + char *pos, *end, *custom, *buf; + + pos = data; + end = data + len; + + while (pos + IW_EV_LCP_LEN <= end) + { + /* Event data may be unaligned, so make a local, aligned copy + * before processing. */ + memcpy(&iwe_buf, pos, IW_EV_LCP_LEN); + wpa_printf(MSG_DEBUG, "Wireless event: cmd=0x%x len=%d", + iwe->cmd, iwe->len); + if (iwe->len <= IW_EV_LCP_LEN) + return; + + custom = pos + IW_EV_POINT_LEN; + if (drv->we_version > 18 && + (iwe->cmd == IWEVMICHAELMICFAILURE || + iwe->cmd == IWEVCUSTOM)) + { + /* WE-19 removed the pointer from struct iw_point */ + char *dpos = (char *) &iwe_buf.u.data.length; + int dlen = dpos - (char *) &iwe_buf; + memcpy(dpos, pos + IW_EV_LCP_LEN, + sizeof(struct iw_event) - dlen); + } + else + { + memcpy(&iwe_buf, pos, sizeof(struct iw_event)); + custom += IW_EV_POINT_OFF; + } + + switch (iwe->cmd) + { + case IWEVCUSTOM: + if (custom + iwe->u.data.length > end) + return; + buf = os_malloc(iwe->u.data.length + 1); + if (buf == NULL) + return; + memcpy(buf, custom, iwe->u.data.length); + buf[iwe->u.data.length] = '\0'; + hostapd_wireless_event_wireless_custom(drv, buf); + + os_free(buf); + break; + } + + pos += iwe->len; + } +} + + +static void hostapd_wireless_event_rtm_newlink(void *ctx, + struct ifinfomsg *ifi, + u8 *buf, size_t len) +{ + struct hostap_driver_data *drv = ctx; + int attrlen, rta_len; + struct rtattr *attr; + + /* TODO: use ifi->ifi_index to filter out wireless events from other + * interfaces */ + + attrlen = len; + attr = (struct rtattr *) buf; + + rta_len = RTA_ALIGN(sizeof(struct rtattr)); + while (RTA_OK(attr, attrlen)) + { + if (attr->rta_type == IFLA_WIRELESS) + { + hostapd_wireless_event_wireless( + drv, ((char *) attr) + rta_len, + attr->rta_len - rta_len); + } + attr = RTA_NEXT(attr, attrlen); + } +} + + +static int hostap_get_we_version(struct hostap_driver_data *drv) +{ + struct iw_range *range; + struct iwreq iwr; + int minlen; + size_t buflen; + + drv->we_version = 0; + + /* + * Use larger buffer than struct iw_range in order to allow the + * structure to grow in the future. + */ + buflen = sizeof(struct iw_range) + 500; + range = os_zalloc(buflen); + if (range == NULL) + return -1; + + memset(&iwr, 0, sizeof(iwr)); + os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); + iwr.u.data.pointer = (c_addr_t) range; + iwr.u.data.length = buflen; + + minlen = ((char *) &range->enc_capa) - (char *) range + + sizeof(range->enc_capa); + + if (ioctl_inet(drv->ioctl_sock, drv->vif_index, SIOCGIWRANGE, (unsigned long)&iwr) < 0) + { + os_free(range); + return -1; + } + else if (iwr.u.data.length >= minlen && + range->we_version_compiled >= 18) + { + drv->we_version = range->we_version_compiled; + } + + os_free(range); + return 0; +} + + +static int hostap_wireless_event_init(struct hostap_driver_data *drv) +{ + struct netlink_config *cfg; + + hostap_get_we_version(drv); + + cfg = os_zalloc(sizeof(*cfg)); + if (cfg == NULL) + return -1; + cfg->ctx = drv; + cfg->newlink_cb = hostapd_wireless_event_rtm_newlink; + drv->netlink = 0; + if (drv->netlink == NULL) + { + os_free(cfg); + } + + return 0; +} + + +static void *hostap_init(struct hostapd_data *hapd, + struct wpa_init_params *params) +{ + struct hostap_driver_data *drv; + int ret; + + drv = os_zalloc(sizeof(struct hostap_driver_data)); + if (drv == NULL) + { + os_printf("Allocate hostapd driver failed\n"); + return NULL; + } + + drv->hapd = hapd; + drv->ioctl_sock = -1; + drv->sock = -1; + os_memcpy(drv->iface, params->ifname, sizeof(drv->iface)); + os_memcpy(drv->own_addr, params->own_addr, ETH_ALEN); + + ret = wpa_driver_hostap_init_vif(drv, NL80211_IFTYPE_AP); + if(ret || (drv->vif_index == 0xff)) { + os_printf("Could not found vif: %d\n", drv->vif_index); + os_free(drv); + return NULL; + } + + drv->ioctl_sock = fsocket_init(PF_INET, SOCK_DGRAM, drv->vif_index); + + if (hostap_ioctl_prism2param(drv, PRISM2_PARAM_HOSTAPD, 1)) + { + wpa_printf(MSG_ERROR, + "Could not enable hostapd mode for interface %s", + drv->iface); + fsocket_close(drv->ioctl_sock); + os_free(drv); + return NULL; + } + + ret = wpa_driver_hostap_start_apm(drv); + if(ret) { + os_printf("Start apm failed\n"); + return NULL; + } + + if (hostap_init_sockets(drv, params->own_addr) || + hostap_wireless_event_init(drv)) + { + fsocket_close(drv->ioctl_sock); + os_free(drv); + return NULL; + } + + return drv; +} + + +static void hostap_driver_deinit(void *priv) +{ + struct hostap_driver_data *drv = priv; + + (void) hostap_set_iface_flags(drv, 0); + (void) hostap_ioctl_prism2param(drv, PRISM2_PARAM_HOSTAPD, 0); + (void) hostap_ioctl_prism2param(drv, PRISM2_PARAM_HOSTAPD_STA, 0); + + if(wpa_driver_hostap_stop_apm(drv)) + os_printf("Could not stop apm vif: %d\n", drv->vif_index); + + if(wpa_driver_hostap_deinit_vif(drv)) + os_printf("Could not remove vif: %d\n", drv->vif_index); + + if (drv->ioctl_sock >= 0) + fsocket_close(drv->ioctl_sock); + + if (drv->sock >= 0) { + fsocket_close(drv->sock); + eloop_unregister_read_sock(drv->sock); + } + + l2_packet_deinit(drv->sock_xmit); + + os_free(drv->generic_ie); + os_free(drv->wps_ie); + + os_free(drv); +} + + +static int hostap_sta_deauth(void *priv, const u8 *own_addr, const u8 *addr, + int reason) +{ + struct hostap_driver_data *drv = priv; + struct ieee80211_mgmt mgmt; + + if (is_broadcast_ether_addr(addr)) + { + /* + * New Prism2.5/3 STA firmware versions seem to have issues + * with this broadcast deauth frame. This gets the firmware in + * odd state where nothing works correctly, so let's skip + * sending this for the hostap driver. + */ + return 0; + } + + memset(&mgmt, 0, sizeof(mgmt)); + mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, + WLAN_FC_STYPE_DEAUTH); + memcpy(mgmt.da, addr, ETH_ALEN); + memcpy(mgmt.sa, own_addr, ETH_ALEN); + memcpy(mgmt.bssid, own_addr, ETH_ALEN); + mgmt.u.deauth.reason_code = host_to_le16(reason); + return hostap_send_mlme(drv, (u8 *) &mgmt, IEEE80211_HDRLEN + + sizeof(mgmt.u.deauth), 0, 0); +} + + +int hostap_channel_switch(void *priv, struct csa_settings *settings) +{ + struct hostap_driver_data *drv = priv; + struct prism2_hostapd_param *param; + u8 *buf; + size_t blen; + + blen = sizeof(*param); + buf = os_zalloc(blen); + if(buf == NULL) + { + return -1; + } + + param = (struct prism2_hostapd_param *)buf; + param->cmd = PRISM2_HOSTAPD_CHANNEL_SWITCH; + param->vif_idx = drv->vif_index; + param->u.chan_switch.freq = settings->freq_params.freq; + param->u.chan_switch.csa_cnt = settings->cs_count; + param->u.chan_switch.settings = settings; + + if (hostapd_ioctl(drv, param, blen)) + { + os_free(buf); + return -1; + } + + eloop_register_signal(SIGCSA, wpa_driver_csa_sig_handler, drv->hapd); + + param = (struct prism2_hostapd_param *)buf; + param->vif_idx = drv->vif_index; + param->cmd = PRISM2_HOSTAPD_REG_CSA_CALLBACK; + param->u.reg_csa_event.cb = wpa_handler_signal; + param->u.reg_csa_event.arg = (void *)SIGCSA; + if (hostapd_ioctl(drv, param, blen)) + { + os_free(buf); + return -1; + } + + os_free(buf); + + return 0; +} + +static int hostap_set_freq(void *priv, struct hostapd_freq_params *freq) +{ + struct hostap_driver_data *drv = priv; + struct iwreq iwr; + + os_memset(&iwr, 0, sizeof(iwr)); + os_strlcpy(iwr.ifr_name, drv->iface, IFNAMSIZ); + iwr.u.freq.m = freq->channel; + iwr.u.freq.e = 0; + + if (ioctl_inet(drv->ioctl_sock, drv->vif_index, SIOCSIWFREQ, (unsigned long)&iwr) < 0) + { + wpa_printf(MSG_ERROR, "ioctl[SIOCSIWFREQ]: %s", + strerror(errno)); + return -1; + } + + return 0; +} + +static int hostap_sta_disassoc(void *priv, const u8 *own_addr, const u8 *addr, + int reason) +{ + struct hostap_driver_data *drv = priv; + struct ieee80211_mgmt mgmt; + + memset(&mgmt, 0, sizeof(mgmt)); + mgmt.frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, + WLAN_FC_STYPE_DISASSOC); + memcpy(mgmt.da, addr, ETH_ALEN); + memcpy(mgmt.sa, own_addr, ETH_ALEN); + memcpy(mgmt.bssid, own_addr, ETH_ALEN); + mgmt.u.disassoc.reason_code = host_to_le16(reason); + + return hostap_send_mlme(drv, (u8 *) &mgmt, IEEE80211_HDRLEN + + sizeof(mgmt.u.disassoc), 0, 0); +} + +static struct hostapd_hw_modes *hostap_get_hw_feature_data(void *priv, + u16 *num_modes, + u16 *flags) +{ + struct hostapd_hw_modes *mode; + int i, clen, rlen; + const short chan2freq[14] = + { + 2412, 2417, 2422, 2427, 2432, 2437, 2442, + 2447, 2452, 2457, 2462, 2467, 2472, 2484 + }; + + mode = os_zalloc(sizeof(struct hostapd_hw_modes)); + if (mode == NULL) + return NULL; + + *num_modes = 1; + *flags = 0; + + mode->num_channels = 14; + +#if CFG_SUPPORT_80211G + mode->mode = HOSTAPD_MODE_IEEE80211G; + mode->num_rates = 12; +#else + mode->mode = HOSTAPD_MODE_IEEE80211B; + mode->num_rates = 4; +#endif + + clen = mode->num_channels *sizeof(struct hostapd_channel_data); + rlen = mode->num_rates *sizeof(int); + + mode->channels = os_zalloc(clen); + mode->rates = os_zalloc(rlen); + if (mode->channels == NULL || mode->rates == NULL) + { + os_free(mode->channels); + os_free(mode->rates); + os_free(mode); + return NULL; + } + + for (i = 0; i < 14; i++) + { + mode->channels[i].chan = i + 1; + mode->channels[i].freq = chan2freq[i]; + } + + mode->rates[0] = 10; + mode->rates[1] = 20; + mode->rates[2] = 55; + mode->rates[3] = 110; + +#if CFG_SUPPORT_80211G + mode->rates[4] = 60; + mode->rates[5] = 90; + mode->rates[6] = 120; + mode->rates[7] = 180; + mode->rates[8] = 240; + mode->rates[9] = 360; + mode->rates[10] = 480; + mode->rates[11] = 540; +#endif + + return mode; +} + + +int hostap_set_ap(void *priv, struct wpa_driver_ap_params *params) +{ + struct hostap_driver_data *drv = priv; + char *pos; + char *beacon; + int bcn_len; + int ret; + struct prism2_hostapd_param param; + + memset(¶m, 0, sizeof(param)); + + bcn_len = params->head_len + params->tail_len + WLAN_EID_TIM_LEN; + beacon = (char *)os_malloc(bcn_len); + if(0 == beacon) + { + return 0; + } + + pos = beacon; + os_memcpy(pos, params->head, params->head_len); + pos = pos + params->head_len; + + *pos++ = WLAN_EID_TIM; + *pos++ = 4; + *pos++ = 0; + *pos++ = 2; + *pos++ = 0; + *pos++ = 0; + + os_memcpy(pos, params->tail, params->tail_len); + pos = pos + params->tail_len; + + param.cmd = PRISM2_HOSTAPD_SET_AP_BCN; + param.u.bcn_change.beacon = beacon; + param.u.bcn_change.bcn_len = bcn_len; + param.u.bcn_change.head_len = params->head_len; + param.u.bcn_change.tim_len = 6; + param.vif_idx = drv->vif_index; + + ret = hostapd_ioctl(drv, ¶m, sizeof(param)); + + os_free(beacon); + return ret; +} + +static void hostap_poll_client_null_frame(void *priv, const u8 *own_addr, + const u8 *addr, int qos) +{ + int ret; + struct hostap_driver_data *drv = priv; + struct prism2_hostapd_param param; + + param.cmd = PRISM2_HOSTAPD_POLL_CLIENT_NULL_DATA; + param.u.poll_null_data.own_addr = (u8*)own_addr; + param.u.poll_null_data.sta_addr = (u8*)addr; + + ret = hostapd_ioctl(drv, ¶m, sizeof(param)); + + (void)ret; + + return; +} + +void wpa_driver_hostap_poll_client(void *priv, const u8 *own_addr, + const u8 *addr, int qos) +{ + struct ieee80211_hdr hdr; + + os_memset(&hdr, 0, sizeof(hdr)); + + /* + * WLAN_FC_STYPE_NULLFUNC would be more appropriate, + * but it is apparently not retried so TX Exc events + * are not received for it. + * This is the reason the driver overrides the default + * handling. + */ + hdr.frame_control = IEEE80211_FC(WLAN_FC_TYPE_DATA, + WLAN_FC_STYPE_DATA); + hdr.frame_control |= host_to_le16(WLAN_FC_FROMDS); + + os_memcpy(hdr.IEEE80211_DA_FROMDS, addr, ETH_ALEN); + os_memcpy(hdr.IEEE80211_BSSID_FROMDS, own_addr, ETH_ALEN); + os_memcpy(hdr.IEEE80211_SA_FROMDS, own_addr, ETH_ALEN); + + hostap_send_mlme(priv, (u8 *)&hdr, sizeof(hdr), 0, 0); +} + +void wpa_driver_scan_timeout(void *eloop_data, void *user_ctx) +{ + rw_evt_type sta_status = mhdr_get_station_status(); + uint32_t rl_status = rl_pre_sta_get_status(); + os_printf("wpa_driver_scan_timeout sts_status=%d,rl_status=%d\r\n", sta_status, rl_status); + if ((RW_EVT_STA_SCANNING == sta_status) && (RL_STATUS_STA_SCANNING == rl_status)) + { + wpa_supplicant_event_sta(eloop_data, EVENT_SCAN_RESULTS, NULL); + //rl_pre_sta_set_status(RL_STATUS_STA_LAUNCH_FAILED); + } +} + +void wpa_driver_scan_sig_handler(int sig, void *signal_ctx) +{ + os_null_printf("wpa_driver_scan_cb\r\n"); + eloop_cancel_timeout(wpa_driver_scan_timeout, signal_ctx, NULL); + wpa_supplicant_event_sta(signal_ctx, EVENT_SCAN_RESULTS, NULL); +} + +void wpa_driver_assoc_sig_handler(int sig, void *signal_ctx) +{ + os_null_printf("wpa_driver_assoc_cb\r\n"); + wpa_supplicant_event_sta(signal_ctx, EVENT_ASSOC, NULL); +} + +void wpa_driver_disassoc_sig_handler(int sig, void *signal_ctx) +{ + os_null_printf("wpa_driver_deassoc_cb\r\n"); + wpa_supplicant_event_sta(signal_ctx, EVENT_DISASSOC, NULL); +} + +void wpa_driver_deauth_sig_handler(int sig, void *signal_ctx) +{ + os_null_printf("wpa_driver_deauth_cb\r\n"); + wpa_supplicant_event_sta(signal_ctx, EVENT_DEAUTH, NULL); +} + +void wpa_driver_csa_sig_handler(int sig, void *signal_ctx) +{ + union wpa_event_data data; + + data.ch_switch.freq = bk_wlan_ap_get_frequency(); + data.ch_switch.ht_enabled = 1; + data.ch_switch.ch_offset = 0; + data.ch_switch.ch_width = 20; + data.ch_switch.cf1 = bk_wlan_ap_get_frequency(); + data.ch_switch.cf2 = 0; + + wpa_supplicant_event(signal_ctx, EVENT_CH_SWITCH, &data); +} + +static void *wpa_driver_init(void *ctx, const char *ifname) +{ + struct hostap_driver_data *drv; + int ret; + + drv = os_zalloc(sizeof(struct hostap_driver_data)); + if (drv == NULL) + { + return NULL; + } + + drv->wpa_s = ctx; + os_memcpy(drv->iface, ifname, sizeof(drv->iface)); + wifi_get_mac_address((char *)drv->own_addr, CONFIG_ROLE_STA); + + ret = wpa_driver_hostap_init_vif(drv, NL80211_IFTYPE_STATION); + if(ret || (drv->vif_index == 0xff)) { + os_printf("Could not found vif indix: %d\n", drv->vif_index); + os_free(drv); + return NULL; + } + + drv->ioctl_sock = fsocket_init(PF_INET, SOCK_DGRAM, drv->vif_index); + + return drv; +} + +static void wpa_driver_deinit(void *priv) +{ + struct hostap_driver_data *drv = priv; + + (void) hostap_set_iface_flags(drv, 0); + (void) hostap_ioctl_prism2param(drv, PRISM2_PARAM_HOSTAPD, 0); + (void) hostap_ioctl_prism2param(drv, PRISM2_PARAM_HOSTAPD_STA, 0); + + if(wpa_driver_hostap_deinit_vif(drv)) + os_printf("Could not remove vif: %d\n", drv->vif_index); + + if (drv->ioctl_sock >= 0) + fsocket_close(drv->ioctl_sock); + + if (drv->sock >= 0) + fsocket_close(drv->sock); + + os_free(drv->generic_ie); + os_free(drv->wps_ie); + + os_free(drv); +} + +void wpa_handler_signal(void *arg, u8 vif_idx) +{ + int sig = (int)arg; + extern int eloop_get_signal_count(void); + + if (!eloop_get_signal_count()) + { + os_printf("wpa_handler_signal err failed\r\n"); + return; + } + + eloop_handle_signal(sig); + + wpa_hostapd_queue_poll((uint32_t)vif_idx); +} + +int wpa_driver_scan2(void *priv, struct wpa_driver_scan_params *params) +{ + struct hostap_driver_data *drv = priv; + struct prism2_hostapd_param *param; + u8 *buf; + size_t blen; + int ret = 0, i; + + blen = sizeof(*param); + buf = os_zalloc(blen); + if(buf == NULL) + return -1; + + eloop_register_signal(SIGSCAN, wpa_driver_scan_sig_handler, drv->wpa_s); + + param = (struct prism2_hostapd_param *)buf; + param->cmd = PRISM2_HOSTAPD_REG_SCAN_CALLBACK; + param->vif_idx = drv->vif_index; + param->u.reg_scan_cfm.cb = wpa_handler_signal; + param->u.reg_scan_cfm.arg = (void *)SIGSCAN; + if (hostapd_ioctl(drv, param, blen)) + { + ret = -1; + } + + param = (struct prism2_hostapd_param *)buf; + param->cmd = PRISM2_HOSTAPD_SCAN_REQ; + param->u.scan_req.ssids_num = MIN(SCAN_SSID_MAX, params->num_ssids); + param->vif_idx = drv->vif_index; + + for(i = 0; i < param->u.scan_req.ssids_num; i++) + { + param->u.scan_req.ssids[i].ssid_len = params->ssids[i].ssid_len; + os_memcpy(param->u.scan_req.ssids[i].ssid, params->ssids[i].ssid, param->u.scan_req.ssids[i].ssid_len); + } + + if (hostapd_ioctl(drv, param, blen)) + { + ret = -1; + } + + os_free(buf); + + eloop_register_timeout(5, 0, wpa_driver_scan_timeout, drv->wpa_s, NULL); + + return ret; +} + +struct wpa_scan_results *wpa_driver_get_scan_results2(void *priv) +{ + struct hostap_driver_data *drv = priv; + struct prism2_hostapd_param *param; + struct wpa_scan_results *results = NULL; + u8 *buf; + size_t blen; + int ret = 0; + + blen = sizeof(*param); + buf = os_zalloc(blen); + if(buf == NULL) + { + goto fail_result; + } + + param = (struct prism2_hostapd_param *)buf; + param->cmd = PRISM2_HOSTAPD_GET_SCAN_RESULT; + param->vif_idx = drv->vif_index; + + results = os_zalloc(sizeof(*results)); + if(results == NULL) + { + goto fail_result; + } + results->res = os_calloc(MAX_BSS_LIST, sizeof(struct wpa_scan_res *)); + if (results->res == NULL) + { + goto fail_result; + } + + param->u.scan_rst = results; + + if (hostapd_ioctl(drv, param, blen)) + { + ret = -1; + } + + if(!ret) + { + os_free(buf); + return results; + } + +fail_result: + if(results && results->res) + { + os_free(results->res); + results->res = NULL; + } + + if(results) + { + os_free(results); + results = NULL; + } + + if(buf) + { + os_free(buf); + buf = NULL; + } + + return NULL; +} + +int wpa_driver_associate(void *priv, struct wpa_driver_associate_params *params) +{ + struct hostap_driver_data *drv = priv; + struct prism2_hostapd_param *param; + u8 *buf; + size_t blen; + int ret = 0; + + blen = sizeof(*param); + buf = os_zalloc(blen); + if(buf == NULL) + { + return -1; + } + + eloop_register_signal(SIGASSOC, wpa_driver_assoc_sig_handler, drv->wpa_s); + + param = (struct prism2_hostapd_param *)buf; + param->vif_idx = drv->vif_index; + param->cmd = PRISM2_HOSTAPD_REG_ASSOC_CALLBACK; + param->u.reg_assoc_cfm.cb = wpa_handler_signal; + param->u.reg_assoc_cfm.arg = (void *)SIGASSOC; + if (hostapd_ioctl(drv, param, blen)) + { + ret = -1; + } + + eloop_register_signal(SIGDISASSOC, wpa_driver_disassoc_sig_handler, drv->wpa_s); + + param->cmd = PRISM2_HOSTAPD_REG_DISASSOC_CALLBACK; + param->vif_idx = drv->vif_index; + param->u.reg_disassoc_evt.cb = wpa_handler_signal; + param->u.reg_disassoc_evt.arg = (void *)SIGDISASSOC; + if (hostapd_ioctl(drv, param, blen)) + { + ret = -1; + } + + eloop_register_signal(SIGDEAUTH, wpa_driver_deauth_sig_handler, drv->wpa_s); + + param->cmd = PRISM2_HOSTAPD_REG_DEAUTH_CALLBACK; + param->vif_idx = drv->vif_index; + param->u.reg_deauth_evt.cb = wpa_handler_signal; + param->u.reg_deauth_evt.arg = (void *)SIGDEAUTH; + if (hostapd_ioctl(drv, param, blen)) + { + ret = -1; + } + + os_null_printf("wpa_driver_associate\r\n"); + param = (struct prism2_hostapd_param *)buf; + param->cmd = PRISM2_HOSTAPD_ASSOC_REQ; + param->vif_idx = drv->vif_index; + if(params->auth_alg & WPA_AUTH_ALG_OPEN) + { + param->u.assoc_req.auth_alg = HOSTAP_AUTH_OPEN; + } + else + { + param->u.assoc_req.auth_alg = HOSTAP_AUTH_SHARED; + } + os_memcpy(param->u.assoc_req.bssid, params->bssid, ETH_ALEN); + param->u.assoc_req.ssid_len = params->ssid_len; + os_memcpy(param->u.assoc_req.ssid, params->ssid, param->u.assoc_req.ssid_len); + param->u.assoc_req.proto = params->wpa_proto; + param->u.assoc_req.ie_len = params->wpa_ie_len; + os_memcpy((u8 *)param->u.assoc_req.ie_buf, params->wpa_ie, param->u.assoc_req.ie_len); + + if(hostapd_ioctl(drv, param, blen)) + { + ret = -1; + } + else + { + param->cmd = PRISM2_HOSTAPD_ASSOC_ACK; + param->vif_idx = drv->vif_index; + hostapd_ioctl(drv, param, blen); + } + + os_free(buf); + + return ret; +} + +int wpa_driver_get_bssid(void *priv, u8 *bssid) +{ + struct hostap_driver_data *drv = priv; + struct prism2_hostapd_param *param; + u8 *buf; + size_t blen; + + blen = sizeof(*param); + buf = os_zalloc(blen); + if(buf == NULL) + { + return -1; + } + + param = (struct prism2_hostapd_param *)buf; + param->cmd = PRISM2_HOSTAPD_GET_BSS_INFO; + param->vif_idx = drv->vif_index; + if (hostapd_ioctl(drv, param, blen)) + { + os_free(buf); + return -1; + } + os_memcpy(bssid, param->u.bss_info.bssid, ETH_ALEN); + os_free(buf); + + return 0; +} + +int wpa_driver_get_ssid(void *priv, u8 *ssid) +{ + struct hostap_driver_data *drv = priv; + struct prism2_hostapd_param *param; + u8 *buf, len; + size_t blen; + + blen = sizeof(*param); + buf = os_zalloc(blen); + if(buf == NULL) + { + return -1; + } + + param = (struct prism2_hostapd_param *)buf; + param->cmd = PRISM2_HOSTAPD_GET_BSS_INFO; + param->vif_idx = drv->vif_index; + if (hostapd_ioctl(drv, param, blen)) + { + os_free(buf); + return -1; + } + + len = MIN(SSID_MAX_LEN, os_strlen((char*)param->u.bss_info.ssid)); + os_memcpy(ssid, param->u.bss_info.ssid, len); + os_free(buf); + + return len; +} + +const u8 *wpa_driver_get_mac(void *priv) +{ + struct hostap_driver_data *drv = priv; + + return drv->own_addr; +} + +int wpa_driver_get_capa(void *priv, struct wpa_driver_capa *capa) +{ + os_memset(capa, 0, sizeof(*capa)); + + capa->max_scan_ssids = 1; + capa->enc = WPA_DRIVER_CAPA_ENC_WEP40 + | WPA_DRIVER_CAPA_ENC_WEP104 + | WPA_DRIVER_CAPA_ENC_TKIP + | WPA_DRIVER_CAPA_ENC_CCMP; + capa->flags = WPA_DRIVER_FLAGS_AP_CSA; + + return 0; +} + +int wpa_driver_set_operstate(void *priv, int state) +{ + struct hostap_driver_data *drv = priv; + struct prism2_hostapd_param *param; + u8 *buf; + size_t blen; + int ret = 0; + + if(state == 0) + return 0; + + blen = sizeof(*param); + buf = os_zalloc(blen); + if(buf == NULL) + return -1; + + param = (struct prism2_hostapd_param *)buf; + param->cmd = PRISM2_HOSTAPD_REG_APP_START; + param->vif_idx = drv->vif_index; + if(hostapd_ioctl(drv, param, blen)) + { + ret = -1; + } + + os_free(buf); + + return ret; +} + +int wpa_driver_deauthenticate(void *priv, const u8 *addr, int reason_code) +{ + struct hostap_driver_data *drv = priv; + struct prism2_hostapd_param *param; + u8 *buf; + size_t blen; + int ret = 0; + + blen = sizeof(*param); + buf = os_zalloc(blen); + if(buf == NULL) + { + return -1; + } + + param = (struct prism2_hostapd_param *)buf; + param->cmd = PRISM2_HOSTAPD_DISCONN_REQ; + param->vif_idx = drv->vif_index; + param->u.disconnect_req.reason = reason_code; + if (hostapd_ioctl(drv, param, blen)) + { + ret = -1; + } + + os_free(buf); + + return ret; +} + +const struct wpa_driver_ops wpa_driver_hostap_ops = +{ + .name = "hostap_beken", + .desc = "Host AP driver", + + .hapd_init = hostap_init, + .hapd_deinit = hostap_driver_deinit, + .set_ieee8021x = hostap_set_ieee8021x, + .set_privacy = hostap_set_privacy, + .get_seqnum = hostap_get_seqnum, + .flush = hostap_flush, + .set_generic_elem = hostap_set_generic_elem, + .read_sta_data = hostap_read_sta_data, + .hapd_send_eapol = hostap_send_eapol, + .sta_set_flags = hostap_sta_set_flags, + .sta_deauth = hostap_sta_deauth, + .sta_disassoc = hostap_sta_disassoc, + .sta_remove = hostap_sta_remove, + .hapd_set_ssid = hostap_set_ssid, + .send_mlme = hostap_send_mlme, + .sta_add = hostap_sta_add, + .get_inact_sec = hostap_get_inact_sec, + .sta_clear_stats = hostap_sta_clear_stats, + .get_hw_feature_data = hostap_get_hw_feature_data, + .set_ap_wps_ie = hostap_set_ap_wps_ie, + .set_freq = hostap_set_freq, + .switch_channel = hostap_channel_switch, + + .set_key = wpa_driver_hostap_set_key, + .poll_client = hostap_poll_client_null_frame, + .set_ap = hostap_set_ap, + .init = wpa_driver_init, + .deinit = wpa_driver_deinit, + .scan2 = wpa_driver_scan2, + .get_scan_results2 = wpa_driver_get_scan_results2, + .deauthenticate = wpa_driver_deauthenticate, + .associate = wpa_driver_associate, + .get_bssid = wpa_driver_get_bssid, + .get_ssid = wpa_driver_get_ssid, + .get_mac_addr = wpa_driver_get_mac, + .get_capa = wpa_driver_get_capa, + .set_operstate = wpa_driver_set_operstate, +}; + +#if CFG_ENABLE_WPA_LOG +void wpa_dbg(void *ctx, int level, const char *fmt, ...) +{ + va_list ap; + char *buf; + int buflen; + int len; + + va_start(ap, fmt); + buflen = vsnprintf(NULL, 0, fmt, ap) + 1; + va_end(ap); + + buf = os_malloc(buflen); + if (buf == NULL) { + bk_printf("wpa_msg: Failed to allocate message " + "buffer"); + return; + } + va_start(ap, fmt); + + len = vsnprintf(buf, buflen, fmt, ap); + va_end(ap); + bk_send_string(1, buf); + os_free(buf); + + bk_printf("\r\n"); +} +#endif // CFG_ENABLE_WPA_LOG + diff --git a/beken_os/beken378/func/hostapd-2.5/src/drivers/driver_beken.h b/beken_os/beken378/func/hostapd-2.5/src/drivers/driver_beken.h new file mode 100755 index 0000000..6c7b100 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/drivers/driver_beken.h @@ -0,0 +1,799 @@ +/* + * Driver interaction with Linux Host AP driver + * Copyright (c) 2002-2006, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef HOSTAP_DRIVER_H +#define HOSTAP_DRIVER_H + +#include "ddrv.h" +#include "fake_socket.h" + +typedef void * c_addr_t; + + +#define IWEVGENIE 0x8C05 /* Generic IE (WPA, RSN, WMM, ..) + * (scan results); This includes id and + * length fields. One IWEVGENIE may + * contain more than one IE. Scan + * results may contain one or more + * IWEVGENIE events. */ +#define IWEVMICHAELMICFAILURE 0x8C06 /* Michael MIC failure + * (struct iw_michaelmicfailure) + */ +#define IWEVASSOCREQIE 0x8C07 /* IEs used in (Re)Association Request. + * The data includes id and length + * fields and may contain more than one + * IE. This event is required in + * Managed mode if the driver + * generates its own WPA/RSN IE. This + * should be sent just before + * IWEVREGISTERED event for the + * association. */ +#define IWEVASSOCRESPIE 0x8C08 /* IEs used in (Re)Association + * Response. The data includes id and + * length fields and may contain more + * than one IE. This may be sent + * between IWEVASSOCREQIE and + * IWEVREGISTERED events for the + * association. */ +#define IWEVPMKIDCAND 0x8C09 /* PMKID candidate for RSN + * pre-authentication + * (struct iw_pmkid_cand) */ + +#define IWEVTXDROP 0x8C00 /* Packet dropped to excessive retry */ +#define IWEVQUAL 0x8C01 /* Quality part of statistics (scan) */ +#define IWEVCUSTOM 0x8C02 /* Driver specific ascii string */ +#define IWEVREGISTERED 0x8C03 /* Discovered a new node (AP mode) */ +#define IWEVEXPIRED 0x8C04 /* Expired a node (AP mode) */ +#define IWEVGENIE 0x8C05 /* Generic IE (WPA, RSN, WMM, ..) + * (scan results); This includes id and + * length fields. One IWEVGENIE may + * contain more than one IE. Scan + * results may contain one or more + * IWEVGENIE events. */ +#define IWEVMICHAELMICFAILURE 0x8C06 /* Michael MIC failure + * (struct iw_michaelmicfailure) + */ +#define IWEVASSOCREQIE 0x8C07 /* IEs used in (Re)Association Request. + * The data includes id and length + * fields and may contain more than one + * IE. This event is required in + * Managed mode if the driver + * generates its own WPA/RSN IE. This + * should be sent just before + * IWEVREGISTERED event for the + * association. */ +#define IWEVASSOCRESPIE 0x8C08 /* IEs used in (Re)Association + * Response. The data includes id and + * length fields and may contain more + * than one IE. This may be sent + * between IWEVASSOCREQIE and + * IWEVREGISTERED events for the + * association. */ +#define IWEVPMKIDCAND 0x8C09 /* PMKID candidate for RSN + * pre-authentication + * (struct iw_pmkid_cand) */ + + +/* Wireless Identification */ +#define SIOCSIWCOMMIT 0x8B00 /* Commit pending changes to driver */ +#define SIOCGIWNAME 0x8B01 /* get name == wireless protocol */ +/* SIOCGIWNAME is used to verify the presence of Wireless Extensions. + * Common values : "IEEE 802.11-DS", "IEEE 802.11-FH", "IEEE 802.11b"... + * Don't put the name of your driver there, it's useless. */ + +/* Basic operations */ +#define SIOCSIWNWID 0x8B02 /* set network id (pre-802.11) */ +#define SIOCGIWNWID 0x8B03 /* get network id (the cell) */ +#define SIOCSIWFREQ 0x8B04 /* set channel/frequency (Hz) */ +#define SIOCGIWFREQ 0x8B05 /* get channel/frequency (Hz) */ +#define SIOCSIWMODE 0x8B06 /* set operation mode */ +#define SIOCGIWMODE 0x8B07 /* get operation mode */ +#define SIOCSIWSENS 0x8B08 /* set sensitivity (dBm) */ +#define SIOCGIWSENS 0x8B09 /* get sensitivity (dBm) */ + +/* Informative stuff */ +#define SIOCSIWRANGE 0x8B0A /* Unused */ +#define SIOCGIWRANGE 0x8B0B /* Get range of parameters */ +#define SIOCSIWPRIV 0x8B0C /* Unused */ +#define SIOCGIWPRIV 0x8B0D /* get private ioctl interface info */ +#define SIOCSIWSTATS 0x8B0E /* Unused */ +#define SIOCGIWSTATS 0x8B0F /* Get /proc/net/wireless stats */ +/* SIOCGIWSTATS is strictly used between user space and the kernel, and + * is never passed to the driver (i.e. the driver will never see it). */ + +/* Spy support (statistics per MAC address - used for Mobile IP support) */ +#define SIOCSIWSPY 0x8B10 /* set spy addresses */ +#define SIOCGIWSPY 0x8B11 /* get spy info (quality of link) */ +#define SIOCSIWTHRSPY 0x8B12 /* set spy threshold (spy event) */ +#define SIOCGIWTHRSPY 0x8B13 /* get spy threshold */ + +/* Access Point manipulation */ +#define SIOCSIWAP 0x8B14 /* set access point MAC addresses */ +#define SIOCGIWAP 0x8B15 /* get access point MAC addresses */ +#define SIOCGIWAPLIST 0x8B17 /* Deprecated in favor of scanning */ +#define SIOCSIWSCAN 0x8B18 /* trigger scanning (list cells) */ +#define SIOCGIWSCAN 0x8B19 /* get scanning results */ + +/* 802.11 specific support */ +#define SIOCSIWESSID 0x8B1A /* set ESSID (network name) */ +#define SIOCGIWESSID 0x8B1B /* get ESSID */ +#define SIOCSIWNICKN 0x8B1C /* set node name/nickname */ +#define SIOCGIWNICKN 0x8B1D /* get node name/nickname */ +/* As the ESSID and NICKN are strings up to 32 bytes long, it doesn't fit + * within the 'iwreq' structure, so we need to use the 'data' member to + * point to a string in user space, like it is done for RANGE... */ + +/* Other parameters useful in 802.11 and some other devices */ +#define SIOCSIWRATE 0x8B20 /* set default bit rate (bps) */ +#define SIOCGIWRATE 0x8B21 /* get default bit rate (bps) */ +#define SIOCSIWRTS 0x8B22 /* set RTS/CTS threshold (bytes) */ +#define SIOCGIWRTS 0x8B23 /* get RTS/CTS threshold (bytes) */ +#define SIOCSIWFRAG 0x8B24 /* set fragmentation thr (bytes) */ +#define SIOCGIWFRAG 0x8B25 /* get fragmentation thr (bytes) */ +#define SIOCSIWTXPOW 0x8B26 /* set transmit power (dBm) */ +#define SIOCGIWTXPOW 0x8B27 /* get transmit power (dBm) */ +#define SIOCSIWRETRY 0x8B28 /* set retry limits and lifetime */ +#define SIOCGIWRETRY 0x8B29 /* get retry limits and lifetime */ + +/* Encoding stuff (scrambling, hardware security, WEP...) */ +#define SIOCSIWENCODE 0x8B2A /* set encoding token & mode */ +#define SIOCGIWENCODE 0x8B2B /* get encoding token & mode */ +/* Power saving stuff (power management, unicast and multicast) */ +#define SIOCSIWPOWER 0x8B2C /* set Power Management settings */ +#define SIOCGIWPOWER 0x8B2D /* get Power Management settings */ + +/* WPA : Generic IEEE 802.11 informatiom element (e.g., for WPA/RSN/WMM). + * This ioctl uses struct iw_point and data buffer that includes IE id and len + * fields. More than one IE may be included in the request. Setting the generic + * IE to empty buffer (len=0) removes the generic IE from the driver. Drivers + * are allowed to generate their own WPA/RSN IEs, but in these cases, drivers + * are required to report the used IE as a wireless event, e.g., when + * associating with an AP. */ +#define SIOCSIWGENIE 0x8B30 /* set generic IE */ +#define SIOCGIWGENIE 0x8B31 /* get generic IE */ + +/* WPA : IEEE 802.11 MLME requests */ +#define SIOCSIWMLME 0x8B16 /* request MLME operation; uses + * struct iw_mlme */ +/* WPA : Authentication mode parameters */ +#define SIOCSIWAUTH 0x8B32 /* set authentication mode params */ +#define SIOCGIWAUTH 0x8B33 /* get authentication mode params */ + +/* WPA : Extended version of encoding configuration */ +#define SIOCSIWENCODEEXT 0x8B34 /* set encoding token & mode */ +#define SIOCGIWENCODEEXT 0x8B35 /* get encoding token & mode */ + +/* WPA2 : PMKSA cache management */ +#define SIOCSIWPMKSA 0x8B36 /* PMKSA cache operation */ + +/* --------------------------- SUBTYPES --------------------------- */ +/* + * For all data larger than 16 octets, we need to use a + * pointer to memory allocated in user space. + */ +struct iw_point +{ + void *pointer; /* Pointer to the data (in user space) */ + __u16 length; /* number of fields or size in bytes */ + __u16 flags; /* Optional params */ +}; + + +/* ------------------------ IOCTL REQUEST ------------------------ */ +/* + * Generic format for most parameters that fit in an int + */ +struct iw_param +{ + __s32 value; /* The value of the parameter itself */ + __u8 fixed; /* Hardware should not use auto select */ + __u8 disabled; /* Disable the feature */ + __u16 flags; /* Various specifc flags (if any) */ +}; +/* + * A frequency + * For numbers lower than 10^9, we encode the number in 'm' and + * set 'e' to 0 + * For number greater than 10^9, we divide it by the lowest power + * of 10 to get 'm' lower than 10^9, with 'm'= f / (10^'e')... + * The power of 10 is in 'e', the result of the division is in 'm'. + */ +struct iw_freq +{ + __s32 m; /* Mantissa */ + __s16 e; /* Exponent */ + __u8 i; /* List index (when in range struct) */ + __u8 flags; /* Flags (fixed/auto) */ +}; + +/* + * Quality of the link + */ +struct iw_quality +{ + __u8 qual; /* link quality (%retries, SNR, + %missed beacons or better...) */ + __u8 level; /* signal level (dBm) */ + __u8 noise; /* noise level (dBm) */ + __u8 updated; /* Flags to know if updated */ +}; + +/* + * Packet discarded in the wireless adapter due to + * "wireless" specific problems... + * Note : the list of counter and statistics in net_device_stats + * is already pretty exhaustive, and you should use that first. + * This is only additional stats... + */ +struct iw_discarded +{ + __u32 nwid; /* Rx : Wrong nwid/essid */ + __u32 code; /* Rx : Unable to code/decode (WEP) */ + __u32 fragment; /* Rx : Can't perform MAC reassembly */ + __u32 retries; /* Tx : Max MAC retries num reached */ + __u32 misc; /* Others cases */ +}; + +/* + * Packet/Time period missed in the wireless adapter due to + * "wireless" specific problems... + */ +struct iw_missed +{ + __u32 beacon; /* Missed beacons/superframe */ +}; + +/* + * This structure defines the payload of an ioctl, and is used + * below. + * + * Note that this structure should fit on the memory footprint + * of iwreq (which is the same as ifreq), which mean a max size of + * 16 octets = 128 bits. Warning, pointers might be 64 bits wide... + * You should check this when increasing the structures defined + * above in this file... + */ +union iwreq_data +{ + /* Config - generic */ + char name[IFNAMSIZ]; + /* Name : used to verify the presence of wireless extensions. + * Name of the protocol/provider... */ + + struct iw_point essid; /* Extended network name */ + struct iw_param nwid; /* network id (or domain - the cell) */ + struct iw_freq freq; /* frequency or channel : + * 0-1000 = channel + * > 1000 = frequency in Hz */ + + struct iw_param sens; /* signal level threshold */ + struct iw_param bitrate; /* default bit rate */ + struct iw_param txpower; /* default transmit power */ + struct iw_param rts; /* RTS threshold threshold */ + struct iw_param frag; /* Fragmentation threshold */ + __u32 mode; /* Operation mode */ + struct iw_param retry; /* Retry limits & lifetime */ + + struct iw_point encoding; /* Encoding stuff : tokens */ + struct iw_param power; /* PM duration/timeout */ + struct iw_quality qual; /* Quality part of statistics */ + + struct sockaddr ap_addr; /* Access point address */ + struct sockaddr addr; /* Destination address (hw/mac) */ + + struct iw_param param; /* Other small parameters */ + struct iw_point data; /* Other large parameters */ +}; + +/* + * The structure to exchange data for ioctl. + * This structure is the same as 'struct ifreq', but (re)defined for + * convenience... + * Do I need to remind you about structure size (32 octets) ? + */ +struct iwreq +{ + char ifr_name[IFNAMSIZ]; /* if name, e.g. "eth0" */ + + /* Data part (defined just above) */ + union iwreq_data u; +}; + +/* -------------------------- IOCTL DATA -------------------------- */ +/* + * For those ioctl which want to exchange mode data that what could + * fit in the above structure... + */ + +/* + * Range of parameters + */ +#define SCAN_SSID_MAX 2 + +/* Maximum frequencies in the range struct */ +#define IW_MAX_FREQUENCIES 32 +/* Note : if you have something like 80 frequencies, + * don't increase this constant and don't fill the frequency list. + * The user will be able to set by channel anyway... */ + +/* Maximum bit rates in the range struct */ +#define IW_MAX_BITRATES 32 + +/* Maximum tx powers in the range struct */ +#define IW_MAX_TXPOWER 8 +/* Note : if you more than 8 TXPowers, just set the max and min or + * a few of them in the struct iw_range. */ + +/* Maximum of address that you may set with SPY */ +#define IW_MAX_SPY 8 + +/* Maximum of address that you may get in the + list of access points in range */ +#define IW_MAX_AP 64 + +/* Maximum size of the ESSID and NICKN strings */ +#define IW_ESSID_MAX_SIZE 32 +/* Maximum number of size of encoding token available + * they are listed in the range structure */ +#define IW_MAX_ENCODING_SIZES 8 + +/* Maximum size of the encoding token in bytes */ +#define IW_ENCODING_TOKEN_MAX 64 /* 512 bits (for now) */ + +struct iw_range +{ + /* Informative stuff (to choose between different interface) */ + __u32 throughput; /* To give an idea... */ + /* In theory this value should be the maximum benchmarked + * TCP/IP throughput, because with most of these devices the + * bit rate is meaningless (overhead an co) to estimate how + * fast the connection will go and pick the fastest one. + * I suggest people to play with Netperf or any benchmark... + */ + + /* NWID (or domain id) */ + __u32 min_nwid; /* Minimal NWID we are able to set */ + __u32 max_nwid; /* Maximal NWID we are able to set */ + + /* Old Frequency (backward compat - moved lower ) */ + __u16 old_num_channels; + __u8 old_num_frequency; + + /* Scan capabilities */ + __u8 scan_capa; /* IW_SCAN_CAPA_* bit field */ + + /* Wireless event capability bitmasks */ + __u32 event_capa[6]; + + /* signal level threshold range */ + __s32 sensitivity; + + /* Quality of link & SNR stuff */ + /* Quality range (link, level, noise) + * If the quality is absolute, it will be in the range [0 ; max_qual], + * if the quality is dBm, it will be in the range [max_qual ; 0]. + * Don't forget that we use 8 bit arithmetics... */ + struct iw_quality max_qual; /* Quality of the link */ + /* This should contain the average/typical values of the quality + * indicator. This should be the threshold between a "good" and + * a "bad" link (example : monitor going from green to orange). + * Currently, user space apps like quality monitors don't have any + * way to calibrate the measurement. With this, they can split + * the range between 0 and max_qual in different quality level + * (using a geometric subdivision centered on the average). + * I expect that people doing the user space apps will feedback + * us on which value we need to put in each driver... */ + struct iw_quality avg_qual; /* Quality of the link */ + + /* Rates */ + __u8 num_bitrates; /* Number of entries in the list */ + __s32 bitrate[IW_MAX_BITRATES]; /* list, in bps */ + + /* RTS threshold */ + __s32 min_rts; /* Minimal RTS threshold */ + __s32 max_rts; /* Maximal RTS threshold */ + + /* Frag threshold */ + __s32 min_frag; /* Minimal frag threshold */ + __s32 max_frag; /* Maximal frag threshold */ + + /* Power Management duration & timeout */ + __s32 min_pmp; /* Minimal PM period */ + __s32 max_pmp; /* Maximal PM period */ + __s32 min_pmt; /* Minimal PM timeout */ + __s32 max_pmt; /* Maximal PM timeout */ + __u16 pmp_flags; /* How to decode max/min PM period */ + __u16 pmt_flags; /* How to decode max/min PM timeout */ + __u16 pm_capa; /* What PM options are supported */ + + /* Encoder stuff */ + __u16 encoding_size[IW_MAX_ENCODING_SIZES]; /* Different token sizes */ + __u8 num_encoding_sizes; /* Number of entry in the list */ + __u8 max_encoding_tokens; /* Max number of tokens */ + /* For drivers that need a "login/passwd" form */ + __u8 encoding_login_index; /* token index for login token */ + + /* Transmit power */ + __u16 txpower_capa; /* What options are supported */ + __u8 num_txpower; /* Number of entries in the list */ + __s32 txpower[IW_MAX_TXPOWER]; /* list, in bps */ + + /* Wireless Extension version info */ + __u8 we_version_compiled; /* Must be WIRELESS_EXT */ + __u8 we_version_source; /* Last update of source */ + + /* Retry limits and lifetime */ + __u16 retry_capa; /* What retry options are supported */ + __u16 retry_flags; /* How to decode max/min retry limit */ + __u16 r_time_flags; /* How to decode max/min retry life */ + __s32 min_retry; /* Minimal number of retries */ + __s32 max_retry; /* Maximal number of retries */ + __s32 min_r_time; /* Minimal retry lifetime */ + __s32 max_r_time; /* Maximal retry lifetime */ + + /* Frequency */ + __u16 num_channels; /* Number of channels [0; num - 1] */ + __u8 num_frequency; /* Number of entry in the list */ + struct iw_freq freq[IW_MAX_FREQUENCIES]; /* list */ + /* Note : this frequency list doesn't need to fit channel numbers, + * because each entry contain its channel index */ + + __u32 enc_capa; /* IW_ENC_CAPA_* bit field */ +}; + +/* ----------------------- WIRELESS EVENTS ----------------------- */ +/* + * Wireless events are carried through the rtnetlink socket to user + * space. They are encapsulated in the IFLA_WIRELESS field of + * a RTM_NEWLINK message. + */ + +/* + * A Wireless Event. Contains basically the same data as the ioctl... + */ +struct iw_event +{ + __u16 len; /* Real length of this stuff */ + __u16 cmd; /* Wireless IOCTL */ + union iwreq_data u; /* IOCTL fixed payload */ +}; + +/* Size of the Event prefix (including padding and alignement junk) */ +#define IW_EV_LCP_LEN (sizeof(struct iw_event) - sizeof(union iwreq_data)) +/* Size of the various events */ +#define IW_EV_CHAR_LEN (IW_EV_LCP_LEN + IFNAMSIZ) +#define IW_EV_UINT_LEN (IW_EV_LCP_LEN + sizeof(__u32)) +#define IW_EV_FREQ_LEN (IW_EV_LCP_LEN + sizeof(struct iw_freq)) +#define IW_EV_PARAM_LEN (IW_EV_LCP_LEN + sizeof(struct iw_param)) +#define IW_EV_ADDR_LEN (IW_EV_LCP_LEN + sizeof(struct sockaddr)) +#define IW_EV_QUAL_LEN (IW_EV_LCP_LEN + sizeof(struct iw_quality)) + +/* iw_point events are special. First, the payload (extra data) come at + * the end of the event, so they are bigger than IW_EV_POINT_LEN. Second, + * we omit the pointer, so start at an offset. */ +#define IW_EV_POINT_OFF (((char *) &(((struct iw_point *) NULL)->length)) - \ + (char *) NULL) +#define IW_EV_POINT_LEN (IW_EV_LCP_LEN + sizeof(struct iw_point) - \ + IW_EV_POINT_OFF) + +/* MTU to be set for the wlan#ap device; this is mainly needed for IEEE 802.1X + * frames that might be longer than normal default MTU and they are not + * fragmented */ +#define HOSTAPD_MTU 2290 + +/* netdevice private ioctls (used, e.g., with iwpriv from user space) */ + +/* New wireless extensions API - SET/GET convention (even ioctl numbers are + * root only) + */ +#define PRISM2_IOCTL_PRISM2_PARAM (SIOCIWFIRSTPRIV + 0) +#define PRISM2_IOCTL_GET_PRISM2_PARAM (SIOCIWFIRSTPRIV + 1) +#define PRISM2_IOCTL_WRITEMIF (SIOCIWFIRSTPRIV + 2) +#define PRISM2_IOCTL_READMIF (SIOCIWFIRSTPRIV + 3) +#define PRISM2_IOCTL_MONITOR (SIOCIWFIRSTPRIV + 4) +#define PRISM2_IOCTL_RESET (SIOCIWFIRSTPRIV + 6) +#define PRISM2_IOCTL_INQUIRE (SIOCIWFIRSTPRIV + 8) +#define PRISM2_IOCTL_WDS_ADD (SIOCIWFIRSTPRIV + 10) +#define PRISM2_IOCTL_WDS_DEL (SIOCIWFIRSTPRIV + 12) +#define PRISM2_IOCTL_SET_RID_WORD (SIOCIWFIRSTPRIV + 14) +#define PRISM2_IOCTL_MACCMD (SIOCIWFIRSTPRIV + 16) +#define PRISM2_IOCTL_ADDMAC (SIOCIWFIRSTPRIV + 18) +#define PRISM2_IOCTL_DELMAC (SIOCIWFIRSTPRIV + 20) +#define PRISM2_IOCTL_KICKMAC (SIOCIWFIRSTPRIV + 22) + +/* following are not in SIOCGIWPRIV list; check permission in the driver code + */ +#define PRISM2_IOCTL_DOWNLOAD (SIOCDEVPRIVATE + 13) +#define PRISM2_IOCTL_HOSTAPD (SIOCDEVPRIVATE + 14) + + +/* PRISM2_IOCTL_PRISM2_PARAM ioctl() subtypes: */ +enum { + /* PRISM2_PARAM_PTYPE = 1, */ /* REMOVED 2003-10-22 */ + PRISM2_PARAM_TXRATECTRL = 2, + PRISM2_PARAM_BEACON_INT = 3, + PRISM2_PARAM_PSEUDO_IBSS = 4, + PRISM2_PARAM_ALC = 5, + /* PRISM2_PARAM_TXPOWER = 6, */ /* REMOVED 2003-10-22 */ + PRISM2_PARAM_DUMP = 7, + PRISM2_PARAM_OTHER_AP_POLICY = 8, + PRISM2_PARAM_AP_MAX_INACTIVITY = 9, + PRISM2_PARAM_AP_BRIDGE_PACKETS = 10, + PRISM2_PARAM_DTIM_PERIOD = 11, + PRISM2_PARAM_AP_NULLFUNC_ACK = 12, + PRISM2_PARAM_MAX_WDS = 13, + PRISM2_PARAM_AP_AUTOM_AP_WDS = 14, + PRISM2_PARAM_AP_AUTH_ALGS = 15, + PRISM2_PARAM_MONITOR_ALLOW_FCSERR = 16, + PRISM2_PARAM_HOST_ENCRYPT = 17, + PRISM2_PARAM_HOST_DECRYPT = 18, + PRISM2_PARAM_BUS_MASTER_THRESHOLD_RX = 19, + PRISM2_PARAM_BUS_MASTER_THRESHOLD_TX = 20, + PRISM2_PARAM_HOST_ROAMING = 21, + PRISM2_PARAM_BCRX_STA_KEY = 22, + PRISM2_PARAM_IEEE_802_1X = 23, + PRISM2_PARAM_ANTSEL_TX = 24, + PRISM2_PARAM_ANTSEL_RX = 25, + PRISM2_PARAM_MONITOR_TYPE = 26, + PRISM2_PARAM_WDS_TYPE = 27, + PRISM2_PARAM_HOSTSCAN = 28, + PRISM2_PARAM_AP_SCAN = 29, + PRISM2_PARAM_ENH_SEC = 30, + PRISM2_PARAM_IO_DEBUG = 31, + PRISM2_PARAM_BASIC_RATES = 32, + PRISM2_PARAM_OPER_RATES = 33, + PRISM2_PARAM_HOSTAPD = 34, + PRISM2_PARAM_HOSTAPD_STA = 35, + PRISM2_PARAM_WPA = 36, + PRISM2_PARAM_PRIVACY_INVOKED = 37, + PRISM2_PARAM_TKIP_COUNTERMEASURES = 38, + PRISM2_PARAM_DROP_UNENCRYPTED = 39, + PRISM2_PARAM_SCAN_CHANNEL_MASK = 40, +}; + +enum { HOSTAP_ANTSEL_DO_NOT_TOUCH = 0, HOSTAP_ANTSEL_DIVERSITY = 1, + HOSTAP_ANTSEL_LOW = 2, HOSTAP_ANTSEL_HIGH = 3 }; + + +/* PRISM2_IOCTL_MACCMD ioctl() subcommands: */ +enum { AP_MAC_CMD_POLICY_OPEN = 0, AP_MAC_CMD_POLICY_ALLOW = 1, + AP_MAC_CMD_POLICY_DENY = 2, AP_MAC_CMD_FLUSH = 3, + AP_MAC_CMD_KICKALL = 4 }; + + +/* PRISM2_IOCTL_DOWNLOAD ioctl() dl_cmd: */ +enum { + PRISM2_DOWNLOAD_VOLATILE = 1 /* RAM */, + /* Note! Old versions of prism2_srec have a fatal error in CRC-16 + * calculation, which will corrupt all non-volatile downloads. + * PRISM2_DOWNLOAD_NON_VOLATILE used to be 2, but it is now 3 to + * prevent use of old versions of prism2_srec for non-volatile + * download. */ + PRISM2_DOWNLOAD_NON_VOLATILE = 3 /* FLASH */, + PRISM2_DOWNLOAD_VOLATILE_GENESIS = 4 /* RAM in Genesis mode */, + /* Persistent versions of volatile download commands (keep firmware + * data in memory and automatically re-download after hw_reset */ + PRISM2_DOWNLOAD_VOLATILE_PERSISTENT = 5, + PRISM2_DOWNLOAD_VOLATILE_GENESIS_PERSISTENT = 6, +}; + +struct prism2_download_param { + u32 dl_cmd; + u32 start_addr; + u32 num_areas; + + struct prism2_download_area { + u32 addr; /* wlan card address */ + u32 len; + c_addr_t ptr; /* pointer to data in user space */ + } *data; +}; + +#define PRISM2_MAX_DOWNLOAD_AREA_LEN 131072 +#define PRISM2_MAX_DOWNLOAD_LEN 262144 + + +/* PRISM2_IOCTL_HOSTAPD ioctl() cmd: */ +enum { + PRISM2_HOSTAPD_FLUSH = 1, + PRISM2_HOSTAPD_ADD_STA = 2, + PRISM2_HOSTAPD_REMOVE_STA = 3, + PRISM2_HOSTAPD_GET_INFO_STA = 4, + + /* REMOVED: PRISM2_HOSTAPD_RESET_TXEXC_STA = 5, */ + PRISM2_SET_ENCRYPTION = 6, + PRISM2_GET_ENCRYPTION = 7, + PRISM2_HOSTAPD_SET_FLAGS_STA = 8, + PRISM2_HOSTAPD_GET_RID = 9, + PRISM2_HOSTAPD_SET_RID = 10, + PRISM2_HOSTAPD_SET_ASSOC_AP_ADDR = 11, + PRISM2_HOSTAPD_SET_GENERIC_ELEMENT = 12, + PRISM2_HOSTAPD_MLME = 13, + PRISM2_HOSTAPD_SCAN_REQ = 14, + PRISM2_HOSTAPD_STA_CLEAR_STATS = 15, + PRISM2_HOSTAPD_GET_SCAN_RESULT = 16, + PRISM2_HOSTAPD_ASSOC_REQ = 17, + PRISM2_HOSTAPD_ASSOC_ACK = 18, + + PRISM2_HOSTAPD_REG_SCAN_CALLBACK = 19, + PRISM2_HOSTAPD_REG_ASSOC_CALLBACK = 20, + PRISM2_HOSTAPD_REG_DISASSOC_CALLBACK = 21, + PRISM2_HOSTAPD_REG_DEAUTH_CALLBACK = 22, + PRISM2_HOSTAPD_REG_APP_START = 23, + + PRISM2_HOSTAPD_DISCONN_REQ = 24, + PRISM2_HOSTAPD_WPA_INIT_VIF = 25, + PRISM2_HOSTAPD_WPA_DEINIT_VIF = 26, + PRISM2_HOSTAPD_START_APM = 27, + PRISM2_HOSTAPD_SET_AP_BCN = 28, + PRISM2_HOSTAPD_GET_BSS_INFO = 29, + PRISM2_HOSTAPD_CHANNEL_SWITCH = 30, + PRISM2_HOSTAPD_STOP_APM = 31, + + PRISM2_HOSTAPD_REG_CSA_CALLBACK = 32, + PRISM2_HOSTAPD_POLL_CLIENT_NULL_DATA = 33, +}; + +#define PRISM2_HOSTAPD_MAX_BUF_SIZE 1024 +#define PRISM2_HOSTAPD_RID_HDR_LEN \ +((size_t) (&((struct prism2_hostapd_param *) 0)->u.rid.data)) +#define PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN \ +((size_t) (&((struct prism2_hostapd_param *) 0)->u.generic_elem.data)) + +/* Maximum length for algorithm names (-1 for nul termination) used in ioctl() + */ +#define HOSTAP_CRYPT_ALG_NAME_LEN 16 +#define HOSTAP_AUTH_OPEN 0 +#define HOSTAP_AUTH_SHARED 1 + +struct prism2_hostapd_param { + u32 cmd; + u8 sta_addr[ETH_ALEN]; + u8 vif_idx ; + + union { + struct { + u8* own_addr; + u8* sta_addr; + }poll_null_data; + + struct { + FUNC_2PARAM_PTR cb; + void *arg; + } reg_scan_cfm; + + struct { + FUNC_2PARAM_PTR cb; + void *arg; + } reg_assoc_cfm; + + struct { + FUNC_2PARAM_PTR cb; + void *arg; + } reg_disassoc_evt, reg_deauth_evt; + + struct { + u16 aid; + u16 capability; + u8 tx_supp_rates; + } add_sta; + + struct { + u32 type; + u8* indx_ptr; + } add_if; + + struct { + u32 inactive_sec; + } get_info_sta; + + struct { + void *beacon; + u16 bcn_len; + u16 head_len; + u8 tim_len; + } bcn_change; + + struct { + u8 alg[HOSTAP_CRYPT_ALG_NAME_LEN]; + u32 flags; + u32 err; + u8 idx; + u8 seq[8]; /* sequence counter (set: RX, get: TX) */ + u16 key_len; + u8 *key; + } crypt; + + struct { + u32 flags_and; + u32 flags_or; + } set_flags_sta; + + struct { + u16 rid; + u16 len; + u8 data[0]; + } rid; + + struct { + u8 len; + u8 data[0]; + } generic_elem; + + struct { +#define MLME_STA_DEAUTH 0 +#define MLME_STA_DISASSOC 1 + u16 cmd; + u16 reason_code; + } mlme; + + struct { + struct { + u8 ssid_len; + u8 ssid[SSID_MAX_LEN]; + }ssids[SCAN_SSID_MAX]; + u8 ssids_num; + int freqs[14]; //FIXME: 5G + } scan_req; + + struct wpa_scan_results *scan_rst; + + struct { + u8 bssid[ETH_ALEN]; + u8 ssid_len; + u8 ssid[SSID_MAX_LEN]; + u8 proto; + u8 auth_alg; + u8 mfp; + u16 ie_len; + u32 ie_buf[64]; + u16 bcn_len; + u8 bcn_buf[0]; + } assoc_req; + + struct { + u32 reason; + } disconnect_req; + + struct { + u32 freq; + u32 csa_cnt; + + struct csa_settings *settings; + } chan_switch; + + struct { + FUNC_2PARAM_PTR cb; + void *arg; + } reg_csa_event; + + struct { + u8 bssid[ETH_ALEN]; + u8 ssid[SSID_MAX_LEN]; + } bss_info; + } u; +}; + +#define HOSTAP_CRYPT_FLAG_SET_TX_KEY BIT(0) +#define HOSTAP_CRYPT_FLAG_PERMANENT BIT(1) + +#define HOSTAP_CRYPT_ERR_UNKNOWN_ALG 2 +#define HOSTAP_CRYPT_ERR_UNKNOWN_ADDR 3 +#define HOSTAP_CRYPT_ERR_CRYPT_INIT_FAILED 4 +#define HOSTAP_CRYPT_ERR_KEY_SET_FAILED 5 +#define HOSTAP_CRYPT_ERR_TX_KEY_SET_FAILED 6 +#define HOSTAP_CRYPT_ERR_CARD_CONF_FAILED 7 + +void wpa_handler_signal(void *arg, u8 vif_idx); +void wpa_driver_scan_sig_handler(int sig, void *signal_ctx); +void wpa_driver_assoc_sig_handler(int sig, void *signal_ctx); +void wpa_driver_disassoc_sig_handler(int sig, void *signal_ctx); +void wpa_driver_deauth_sig_handler(int sig, void *signal_ctx); +void wpa_driver_csa_sig_handler(int sig, void *signal_ctx); + +#endif /* HOSTAP_DRIVER_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/drivers/driver_common.c b/beken_os/beken378/func/hostapd-2.5/src/drivers/driver_common.c new file mode 100755 index 0000000..225bafa --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/drivers/driver_common.c @@ -0,0 +1,227 @@ +/* + * Common driver-related functions + * Copyright (c) 2003-2011, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "includes.h" +#include "utils/common.h" +#include "driver.h" + +void wpa_scan_results_free(struct wpa_scan_results *res) +{ + size_t i; + + if (res == NULL) + return; + + for (i = 0; i < res->num; i++) + { + os_free(res->res[i]); + res->res[i] = 0; + } + + os_free(res->res); + res->res = 0; + + os_free(res); + res = 0; +} + + +const char * event_to_string(enum wpa_event_type event) +{ +#define E2S(n) case EVENT_ ## n: return #n + switch (event) { + E2S(ASSOC); + E2S(DISASSOC); + E2S(MICHAEL_MIC_FAILURE); + E2S(SCAN_RESULTS); + E2S(ASSOCINFO); + E2S(INTERFACE_STATUS); + E2S(PMKID_CANDIDATE); + E2S(STKSTART); + E2S(TDLS); + E2S(FT_RESPONSE); + E2S(IBSS_RSN_START); + E2S(AUTH); + E2S(DEAUTH); + E2S(ASSOC_REJECT); + E2S(AUTH_TIMED_OUT); + E2S(ASSOC_TIMED_OUT); + E2S(WPS_BUTTON_PUSHED); + E2S(TX_STATUS); + E2S(RX_FROM_UNKNOWN); + E2S(RX_MGMT); + E2S(REMAIN_ON_CHANNEL); + E2S(CANCEL_REMAIN_ON_CHANNEL); + E2S(RX_PROBE_REQ); + E2S(NEW_STA); + E2S(EAPOL_RX); + E2S(SIGNAL_CHANGE); + E2S(INTERFACE_ENABLED); + E2S(INTERFACE_DISABLED); + E2S(CHANNEL_LIST_CHANGED); + E2S(INTERFACE_UNAVAILABLE); + E2S(BEST_CHANNEL); + E2S(UNPROT_DEAUTH); + E2S(UNPROT_DISASSOC); + E2S(STATION_LOW_ACK); + E2S(IBSS_PEER_LOST); + E2S(DRIVER_GTK_REKEY); + E2S(SCHED_SCAN_STOPPED); + E2S(DRIVER_CLIENT_POLL_OK); + E2S(EAPOL_TX_STATUS); + E2S(CH_SWITCH); + E2S(WNM); + E2S(CONNECT_FAILED_REASON); + E2S(DFS_RADAR_DETECTED); + E2S(DFS_CAC_FINISHED); + E2S(DFS_CAC_ABORTED); + E2S(DFS_NOP_FINISHED); + E2S(SURVEY); + E2S(SCAN_STARTED); + E2S(AVOID_FREQUENCIES); + E2S(NEW_PEER_CANDIDATE); + E2S(ACS_CHANNEL_SELECTED); + E2S(DFS_CAC_STARTED); + } + + return "UNKNOWN"; +#undef E2S +} + + +const char * channel_width_to_string(enum chan_width width) +{ + switch (width) { + case CHAN_WIDTH_20_NOHT: + return "20 MHz (no HT)"; + case CHAN_WIDTH_20: + return "20 MHz"; + case CHAN_WIDTH_40: + return "40 MHz"; + case CHAN_WIDTH_80: + return "80 MHz"; + case CHAN_WIDTH_80P80: + return "80+80 MHz"; + case CHAN_WIDTH_160: + return "160 MHz"; + default: + return "unknown"; + } +} + + +int ht_supported(const struct hostapd_hw_modes *mode) +{ + if (!(mode->flags & HOSTAPD_MODE_FLAG_HT_INFO_KNOWN)) { + /* + * The driver did not indicate whether it supports HT. Assume + * it does to avoid connection issues. + */ + return 1; + } + + /* + * IEEE Std 802.11n-2009 20.1.1: + * An HT non-AP STA shall support all EQM rates for one spatial stream. + */ + return mode->mcs_set[0] == 0xff; +} + + +int vht_supported(const struct hostapd_hw_modes *mode) +{ + if (!(mode->flags & HOSTAPD_MODE_FLAG_VHT_INFO_KNOWN)) { + /* + * The driver did not indicate whether it supports VHT. Assume + * it does to avoid connection issues. + */ + return 1; + } + + /* + * A VHT non-AP STA shall support MCS 0-7 for one spatial stream. + * TODO: Verify if this complies with the standard + */ + return (mode->vht_mcs_set[0] & 0x3) != 3; +} + + +static int wpa_check_wowlan_trigger(const char *start, const char *trigger, + int capa_trigger, u8 *param_trigger) +{ + if (os_strcmp(start, trigger) != 0) + return 0; + if (!capa_trigger) + return 0; + + *param_trigger = 1; + return 1; +} + + +struct wowlan_triggers * +wpa_get_wowlan_triggers(const char *wowlan_triggers, + const struct wpa_driver_capa *capa) +{ + struct wowlan_triggers *triggers; + char *start, *end, *buf; + int last; + + if (!wowlan_triggers) + return NULL; + + buf = os_strdup(wowlan_triggers); + if (buf == NULL) + return NULL; + + triggers = os_zalloc(sizeof(*triggers)); + if (triggers == NULL) + goto out; + +#define CHECK_TRIGGER(trigger) \ + wpa_check_wowlan_trigger(start, #trigger, \ + capa->wowlan_triggers.trigger, \ + &triggers->trigger) + + start = buf; + while (*start != '\0') { + while (isblank(((unsigned char)*start))) + start++; + if (*start == '\0') + break; + end = start; + while (!isblank(((unsigned char)*end)) && ((unsigned char)*end) != '\0') + end++; + last = *end == '\0'; + *end = '\0'; + + if (!CHECK_TRIGGER(any) && + !CHECK_TRIGGER(disconnect) && + !CHECK_TRIGGER(magic_pkt) && + !CHECK_TRIGGER(gtk_rekey_failure) && + !CHECK_TRIGGER(eap_identity_req) && + !CHECK_TRIGGER(four_way_handshake) && + !CHECK_TRIGGER(rfkill_release)) { + wpa_printf(MSG_DEBUG, + "Unknown/unsupported wowlan trigger '%s'", + start); + os_free(triggers); + triggers = NULL; + goto out; + } + + if (last) + break; + start = end + 1; + } +#undef CHECK_TRIGGER + +out: + os_free(buf); + return triggers; +} diff --git a/beken_os/beken378/func/hostapd-2.5/src/drivers/drivers.c b/beken_os/beken378/func/hostapd-2.5/src/drivers/drivers.c new file mode 100755 index 0000000..af3e5d5 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/drivers/drivers.c @@ -0,0 +1,22 @@ +/* + * Driver interface list + * Copyright (c) 2004-2005, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "driver.h" + +#ifdef CONFIG_DRIVER_BEKEN +extern struct wpa_driver_ops wpa_driver_hostap_ops; /* driver_hostap.c */ +#endif /* CONFIG_DRIVER_BEKEN */ + +const struct wpa_driver_ops *const wpa_drivers[] = +{ +#ifdef CONFIG_DRIVER_BEKEN + &wpa_driver_hostap_ops, +#endif /* CONFIG_DRIVER_BEKEN */ + + NULL +}; diff --git a/beken_os/beken378/func/hostapd-2.5/src/drivers/linux_defines.h b/beken_os/beken378/func/hostapd-2.5/src/drivers/linux_defines.h new file mode 100755 index 0000000..a107479 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/drivers/linux_defines.h @@ -0,0 +1,46 @@ +/* + * Linux defines for values that are not yet included in common C libraries + * Copyright (c) 2014, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef LINUX_DEFINES_H +#define LINUX_DEFINES_H + +#ifndef SO_WIFI_STATUS +# if defined(__sparc__) +# define SO_WIFI_STATUS 0x0025 +# elif defined(__parisc__) +# define SO_WIFI_STATUS 0x4022 +# else +# define SO_WIFI_STATUS 41 +# endif + +# define SCM_WIFI_STATUS SO_WIFI_STATUS +#endif + +#ifndef SO_EE_ORIGIN_TXSTATUS +#define SO_EE_ORIGIN_TXSTATUS 4 +#endif + +#ifndef PACKET_TX_TIMESTAMP +#define PACKET_TX_TIMESTAMP 16 +#endif + +#ifndef IFF_LOWER_UP +#define IFF_LOWER_UP 0x10000 /* driver signals L1 up */ +#endif +#ifndef IFF_DORMANT +#define IFF_DORMANT 0x20000 /* driver signals dormant */ +#endif + +#ifndef IF_OPER_DORMANT +#define IF_OPER_DORMANT 5 +#endif +#ifndef IF_OPER_UP +#define IF_OPER_UP 6 +#endif + +#endif /* LINUX_DEFINES_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/drivers/linux_ioctl.h b/beken_os/beken378/func/hostapd-2.5/src/drivers/linux_ioctl.h new file mode 100755 index 0000000..6de4d9b --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/drivers/linux_ioctl.h @@ -0,0 +1,23 @@ +/* + * Linux ioctl helper functions for driver wrappers + * Copyright (c) 2002-2010, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef LINUX_IOCTL_H +#define LINUX_IOCTL_H + +int linux_set_iface_flags(int sock, const char *ifname, int dev_up); +int linux_iface_up(int sock, const char *ifname); +int linux_get_ifhwaddr(int sock, const char *ifname, u8 *addr); +int linux_set_ifhwaddr(int sock, const char *ifname, const u8 *addr); +int linux_br_add(int sock, const char *brname); +int linux_br_del(int sock, const char *brname); +int linux_br_add_if(int sock, const char *brname, const char *ifname); +int linux_br_del_if(int sock, const char *brname, const char *ifname); +int linux_br_get(char *brname, const char *ifname); +int linux_master_get(char *master_ifname, const char *ifname); + +#endif /* LINUX_IOCTL_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/drivers/netlink.h b/beken_os/beken378/func/hostapd-2.5/src/drivers/netlink.h new file mode 100755 index 0000000..3a7340e --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/drivers/netlink.h @@ -0,0 +1,28 @@ +/* + * Netlink helper functions for driver wrappers + * Copyright (c) 2002-2009, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef NETLINK_H +#define NETLINK_H + +struct netlink_data; +struct ifinfomsg; + +struct netlink_config { + void *ctx; + void (*newlink_cb)(void *ctx, struct ifinfomsg *ifi, u8 *buf, + size_t len); + void (*dellink_cb)(void *ctx, struct ifinfomsg *ifi, u8 *buf, + size_t len); +}; + +struct netlink_data * netlink_init(struct netlink_config *cfg); +void netlink_deinit(struct netlink_data *netlink); +int netlink_send_oper_ifla(struct netlink_data *netlink, int ifindex, + int linkmode, int operstate); + +#endif /* NETLINK_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/drivers/nl80211_copy.h b/beken_os/beken378/func/hostapd-2.5/src/drivers/nl80211_copy.h new file mode 100755 index 0000000..fac3c0f --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/drivers/nl80211_copy.h @@ -0,0 +1,4587 @@ +#ifndef __LINUX_NL80211_H +#define __LINUX_NL80211_H +/* + * 802.11 netlink interface public header + * + * Copyright 2006-2010 Johannes Berg + * Copyright 2008 Michael Wu + * Copyright 2008 Luis Carlos Cobo + * Copyright 2008 Michael Buesch + * Copyright 2008, 2009 Luis R. Rodriguez + * Copyright 2008 Jouni Malinen + * Copyright 2008 Colin McCabe + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + */ + +/* + * This header file defines the userspace API to the wireless stack. Please + * be careful not to break things - i.e. don't move anything around or so + * unless you can demonstrate that it breaks neither API nor ABI. + * + * Additions to the API should be accompanied by actual implementations in + * an upstream driver, so that example implementations exist in case there + * are ever concerns about the precise semantics of the API or changes are + * needed, and to ensure that code for dead (no longer implemented) API + * can actually be identified and removed. + * Nonetheless, semantics should also be documented carefully in this file. + */ + +#include + +#define NL80211_GENL_NAME "nl80211" + +#define NL80211_MULTICAST_GROUP_CONFIG "config" +#define NL80211_MULTICAST_GROUP_SCAN "scan" +#define NL80211_MULTICAST_GROUP_REG "regulatory" +#define NL80211_MULTICAST_GROUP_MLME "mlme" +#define NL80211_MULTICAST_GROUP_VENDOR "vendor" +#define NL80211_MULTICAST_GROUP_TESTMODE "testmode" + +/** + * DOC: Station handling + * + * Stations are added per interface, but a special case exists with VLAN + * interfaces. When a station is bound to an AP interface, it may be moved + * into a VLAN identified by a VLAN interface index (%NL80211_ATTR_STA_VLAN). + * The station is still assumed to belong to the AP interface it was added + * to. + * + * Station handling varies per interface type and depending on the driver's + * capabilities. + * + * For drivers supporting TDLS with external setup (WIPHY_FLAG_SUPPORTS_TDLS + * and WIPHY_FLAG_TDLS_EXTERNAL_SETUP), the station lifetime is as follows: + * - a setup station entry is added, not yet authorized, without any rate + * or capability information, this just exists to avoid race conditions + * - when the TDLS setup is done, a single NL80211_CMD_SET_STATION is valid + * to add rate and capability information to the station and at the same + * time mark it authorized. + * - %NL80211_TDLS_ENABLE_LINK is then used + * - after this, the only valid operation is to remove it by tearing down + * the TDLS link (%NL80211_TDLS_DISABLE_LINK) + * + * TODO: need more info for other interface types + */ + +/** + * DOC: Frame transmission/registration support + * + * Frame transmission and registration support exists to allow userspace + * management entities such as wpa_supplicant react to management frames + * that are not being handled by the kernel. This includes, for example, + * certain classes of action frames that cannot be handled in the kernel + * for various reasons. + * + * Frame registration is done on a per-interface basis and registrations + * cannot be removed other than by closing the socket. It is possible to + * specify a registration filter to register, for example, only for a + * certain type of action frame. In particular with action frames, those + * that userspace registers for will not be returned as unhandled by the + * driver, so that the registered application has to take responsibility + * for doing that. + * + * The type of frame that can be registered for is also dependent on the + * driver and interface type. The frame types are advertised in wiphy + * attributes so applications know what to expect. + * + * NOTE: When an interface changes type while registrations are active, + * these registrations are ignored until the interface type is + * changed again. This means that changing the interface type can + * lead to a situation that couldn't otherwise be produced, but + * any such registrations will be dormant in the sense that they + * will not be serviced, i.e. they will not receive any frames. + * + * Frame transmission allows userspace to send for example the required + * responses to action frames. It is subject to some sanity checking, + * but many frames can be transmitted. When a frame was transmitted, its + * status is indicated to the sending socket. + * + * For more technical details, see the corresponding command descriptions + * below. + */ + +/** + * DOC: Virtual interface / concurrency capabilities + * + * Some devices are able to operate with virtual MACs, they can have + * more than one virtual interface. The capability handling for this + * is a bit complex though, as there may be a number of restrictions + * on the types of concurrency that are supported. + * + * To start with, each device supports the interface types listed in + * the %NL80211_ATTR_SUPPORTED_IFTYPES attribute, but by listing the + * types there no concurrency is implied. + * + * Once concurrency is desired, more attributes must be observed: + * To start with, since some interface types are purely managed in + * software, like the AP-VLAN type in mac80211 for example, there's + * an additional list of these, they can be added at any time and + * are only restricted by some semantic restrictions (e.g. AP-VLAN + * cannot be added without a corresponding AP interface). This list + * is exported in the %NL80211_ATTR_SOFTWARE_IFTYPES attribute. + * + * Further, the list of supported combinations is exported. This is + * in the %NL80211_ATTR_INTERFACE_COMBINATIONS attribute. Basically, + * it exports a list of "groups", and at any point in time the + * interfaces that are currently active must fall into any one of + * the advertised groups. Within each group, there are restrictions + * on the number of interfaces of different types that are supported + * and also the number of different channels, along with potentially + * some other restrictions. See &enum nl80211_if_combination_attrs. + * + * All together, these attributes define the concurrency of virtual + * interfaces that a given device supports. + */ + +/** + * DOC: packet coalesce support + * + * In most cases, host that receives IPv4 and IPv6 multicast/broadcast + * packets does not do anything with these packets. Therefore the + * reception of these unwanted packets causes unnecessary processing + * and power consumption. + * + * Packet coalesce feature helps to reduce number of received interrupts + * to host by buffering these packets in firmware/hardware for some + * predefined time. Received interrupt will be generated when one of the + * following events occur. + * a) Expiration of hardware timer whose expiration time is set to maximum + * coalescing delay of matching coalesce rule. + * b) Coalescing buffer in hardware reaches it's limit. + * c) Packet doesn't match any of the configured coalesce rules. + * + * User needs to configure following parameters for creating a coalesce + * rule. + * a) Maximum coalescing delay + * b) List of packet patterns which needs to be matched + * c) Condition for coalescence. pattern 'match' or 'no match' + * Multiple such rules can be created. + */ + +/** + * enum nl80211_commands - supported nl80211 commands + * + * @NL80211_CMD_UNSPEC: unspecified command to catch errors + * + * @NL80211_CMD_GET_WIPHY: request information about a wiphy or dump request + * to get a list of all present wiphys. + * @NL80211_CMD_SET_WIPHY: set wiphy parameters, needs %NL80211_ATTR_WIPHY or + * %NL80211_ATTR_IFINDEX; can be used to set %NL80211_ATTR_WIPHY_NAME, + * %NL80211_ATTR_WIPHY_TXQ_PARAMS, %NL80211_ATTR_WIPHY_FREQ (and the + * attributes determining the channel width; this is used for setting + * monitor mode channel), %NL80211_ATTR_WIPHY_RETRY_SHORT, + * %NL80211_ATTR_WIPHY_RETRY_LONG, %NL80211_ATTR_WIPHY_FRAG_THRESHOLD, + * and/or %NL80211_ATTR_WIPHY_RTS_THRESHOLD. + * However, for setting the channel, see %NL80211_CMD_SET_CHANNEL + * instead, the support here is for backward compatibility only. + * @NL80211_CMD_NEW_WIPHY: Newly created wiphy, response to get request + * or rename notification. Has attributes %NL80211_ATTR_WIPHY and + * %NL80211_ATTR_WIPHY_NAME. + * @NL80211_CMD_DEL_WIPHY: Wiphy deleted. Has attributes + * %NL80211_ATTR_WIPHY and %NL80211_ATTR_WIPHY_NAME. + * + * @NL80211_CMD_GET_INTERFACE: Request an interface's configuration; + * either a dump request for all interfaces or a specific get with a + * single %NL80211_ATTR_IFINDEX is supported. + * @NL80211_CMD_SET_INTERFACE: Set type of a virtual interface, requires + * %NL80211_ATTR_IFINDEX and %NL80211_ATTR_IFTYPE. + * @NL80211_CMD_NEW_INTERFACE: Newly created virtual interface or response + * to %NL80211_CMD_GET_INTERFACE. Has %NL80211_ATTR_IFINDEX, + * %NL80211_ATTR_WIPHY and %NL80211_ATTR_IFTYPE attributes. Can also + * be sent from userspace to request creation of a new virtual interface, + * then requires attributes %NL80211_ATTR_WIPHY, %NL80211_ATTR_IFTYPE and + * %NL80211_ATTR_IFNAME. + * @NL80211_CMD_DEL_INTERFACE: Virtual interface was deleted, has attributes + * %NL80211_ATTR_IFINDEX and %NL80211_ATTR_WIPHY. Can also be sent from + * userspace to request deletion of a virtual interface, then requires + * attribute %NL80211_ATTR_IFINDEX. + * + * @NL80211_CMD_GET_KEY: Get sequence counter information for a key specified + * by %NL80211_ATTR_KEY_IDX and/or %NL80211_ATTR_MAC. + * @NL80211_CMD_SET_KEY: Set key attributes %NL80211_ATTR_KEY_DEFAULT, + * %NL80211_ATTR_KEY_DEFAULT_MGMT, or %NL80211_ATTR_KEY_THRESHOLD. + * @NL80211_CMD_NEW_KEY: add a key with given %NL80211_ATTR_KEY_DATA, + * %NL80211_ATTR_KEY_IDX, %NL80211_ATTR_MAC, %NL80211_ATTR_KEY_CIPHER, + * and %NL80211_ATTR_KEY_SEQ attributes. + * @NL80211_CMD_DEL_KEY: delete a key identified by %NL80211_ATTR_KEY_IDX + * or %NL80211_ATTR_MAC. + * + * @NL80211_CMD_GET_BEACON: (not used) + * @NL80211_CMD_SET_BEACON: change the beacon on an access point interface + * using the %NL80211_ATTR_BEACON_HEAD and %NL80211_ATTR_BEACON_TAIL + * attributes. For drivers that generate the beacon and probe responses + * internally, the following attributes must be provided: %NL80211_ATTR_IE, + * %NL80211_ATTR_IE_PROBE_RESP and %NL80211_ATTR_IE_ASSOC_RESP. + * @NL80211_CMD_START_AP: Start AP operation on an AP interface, parameters + * are like for %NL80211_CMD_SET_BEACON, and additionally parameters that + * do not change are used, these include %NL80211_ATTR_BEACON_INTERVAL, + * %NL80211_ATTR_DTIM_PERIOD, %NL80211_ATTR_SSID, + * %NL80211_ATTR_HIDDEN_SSID, %NL80211_ATTR_CIPHERS_PAIRWISE, + * %NL80211_ATTR_CIPHER_GROUP, %NL80211_ATTR_WPA_VERSIONS, + * %NL80211_ATTR_AKM_SUITES, %NL80211_ATTR_PRIVACY, + * %NL80211_ATTR_AUTH_TYPE, %NL80211_ATTR_INACTIVITY_TIMEOUT, + * %NL80211_ATTR_ACL_POLICY and %NL80211_ATTR_MAC_ADDRS. + * The channel to use can be set on the interface or be given using the + * %NL80211_ATTR_WIPHY_FREQ and the attributes determining channel width. + * @NL80211_CMD_NEW_BEACON: old alias for %NL80211_CMD_START_AP + * @NL80211_CMD_STOP_AP: Stop AP operation on the given interface + * @NL80211_CMD_DEL_BEACON: old alias for %NL80211_CMD_STOP_AP + * + * @NL80211_CMD_GET_STATION: Get station attributes for station identified by + * %NL80211_ATTR_MAC on the interface identified by %NL80211_ATTR_IFINDEX. + * @NL80211_CMD_SET_STATION: Set station attributes for station identified by + * %NL80211_ATTR_MAC on the interface identified by %NL80211_ATTR_IFINDEX. + * @NL80211_CMD_NEW_STATION: Add a station with given attributes to the + * the interface identified by %NL80211_ATTR_IFINDEX. + * @NL80211_CMD_DEL_STATION: Remove a station identified by %NL80211_ATTR_MAC + * or, if no MAC address given, all stations, on the interface identified + * by %NL80211_ATTR_IFINDEX. %NL80211_ATTR_MGMT_SUBTYPE and + * %NL80211_ATTR_REASON_CODE can optionally be used to specify which type + * of disconnection indication should be sent to the station + * (Deauthentication or Disassociation frame and reason code for that + * frame). + * + * @NL80211_CMD_GET_MPATH: Get mesh path attributes for mesh path to + * destination %NL80211_ATTR_MAC on the interface identified by + * %NL80211_ATTR_IFINDEX. + * @NL80211_CMD_SET_MPATH: Set mesh path attributes for mesh path to + * destination %NL80211_ATTR_MAC on the interface identified by + * %NL80211_ATTR_IFINDEX. + * @NL80211_CMD_NEW_MPATH: Create a new mesh path for the destination given by + * %NL80211_ATTR_MAC via %NL80211_ATTR_MPATH_NEXT_HOP. + * @NL80211_CMD_DEL_MPATH: Delete a mesh path to the destination given by + * %NL80211_ATTR_MAC. + * @NL80211_CMD_NEW_PATH: Add a mesh path with given attributes to the + * the interface identified by %NL80211_ATTR_IFINDEX. + * @NL80211_CMD_DEL_PATH: Remove a mesh path identified by %NL80211_ATTR_MAC + * or, if no MAC address given, all mesh paths, on the interface identified + * by %NL80211_ATTR_IFINDEX. + * @NL80211_CMD_SET_BSS: Set BSS attributes for BSS identified by + * %NL80211_ATTR_IFINDEX. + * + * @NL80211_CMD_GET_REG: ask the wireless core to send us its currently set + * regulatory domain. If %NL80211_ATTR_WIPHY is specified and the device + * has a private regulatory domain, it will be returned. Otherwise, the + * global regdomain will be returned. + * A device will have a private regulatory domain if it uses the + * regulatory_hint() API. Even when a private regdomain is used the channel + * information will still be mended according to further hints from + * the regulatory core to help with compliance. A dump version of this API + * is now available which will returns the global regdomain as well as + * all private regdomains of present wiphys (for those that have it). + * If a wiphy is self-managed (%NL80211_ATTR_WIPHY_SELF_MANAGED_REG), then + * its private regdomain is the only valid one for it. The regulatory + * core is not used to help with compliance in this case. + * @NL80211_CMD_SET_REG: Set current regulatory domain. CRDA sends this command + * after being queried by the kernel. CRDA replies by sending a regulatory + * domain structure which consists of %NL80211_ATTR_REG_ALPHA set to our + * current alpha2 if it found a match. It also provides + * NL80211_ATTR_REG_RULE_FLAGS, and a set of regulatory rules. Each + * regulatory rule is a nested set of attributes given by + * %NL80211_ATTR_REG_RULE_FREQ_[START|END] and + * %NL80211_ATTR_FREQ_RANGE_MAX_BW with an attached power rule given by + * %NL80211_ATTR_REG_RULE_POWER_MAX_ANT_GAIN and + * %NL80211_ATTR_REG_RULE_POWER_MAX_EIRP. + * @NL80211_CMD_REQ_SET_REG: ask the wireless core to set the regulatory domain + * to the specified ISO/IEC 3166-1 alpha2 country code. The core will + * store this as a valid request and then query userspace for it. + * + * @NL80211_CMD_GET_MESH_CONFIG: Get mesh networking properties for the + * interface identified by %NL80211_ATTR_IFINDEX + * + * @NL80211_CMD_SET_MESH_CONFIG: Set mesh networking properties for the + * interface identified by %NL80211_ATTR_IFINDEX + * + * @NL80211_CMD_SET_MGMT_EXTRA_IE: Set extra IEs for management frames. The + * interface is identified with %NL80211_ATTR_IFINDEX and the management + * frame subtype with %NL80211_ATTR_MGMT_SUBTYPE. The extra IE data to be + * added to the end of the specified management frame is specified with + * %NL80211_ATTR_IE. If the command succeeds, the requested data will be + * added to all specified management frames generated by + * kernel/firmware/driver. + * Note: This command has been removed and it is only reserved at this + * point to avoid re-using existing command number. The functionality this + * command was planned for has been provided with cleaner design with the + * option to specify additional IEs in NL80211_CMD_TRIGGER_SCAN, + * NL80211_CMD_AUTHENTICATE, NL80211_CMD_ASSOCIATE, + * NL80211_CMD_DEAUTHENTICATE, and NL80211_CMD_DISASSOCIATE. + * + * @NL80211_CMD_GET_SCAN: get scan results + * @NL80211_CMD_TRIGGER_SCAN: trigger a new scan with the given parameters + * %NL80211_ATTR_TX_NO_CCK_RATE is used to decide whether to send the + * probe requests at CCK rate or not. + * @NL80211_CMD_NEW_SCAN_RESULTS: scan notification (as a reply to + * NL80211_CMD_GET_SCAN and on the "scan" multicast group) + * @NL80211_CMD_SCAN_ABORTED: scan was aborted, for unspecified reasons, + * partial scan results may be available + * + * @NL80211_CMD_START_SCHED_SCAN: start a scheduled scan at certain + * intervals, as specified by %NL80211_ATTR_SCHED_SCAN_INTERVAL. + * Like with normal scans, if SSIDs (%NL80211_ATTR_SCAN_SSIDS) + * are passed, they are used in the probe requests. For + * broadcast, a broadcast SSID must be passed (ie. an empty + * string). If no SSID is passed, no probe requests are sent and + * a passive scan is performed. %NL80211_ATTR_SCAN_FREQUENCIES, + * if passed, define which channels should be scanned; if not + * passed, all channels allowed for the current regulatory domain + * are used. Extra IEs can also be passed from the userspace by + * using the %NL80211_ATTR_IE attribute. The first cycle of the + * scheduled scan can be delayed by %NL80211_ATTR_SCHED_SCAN_DELAY + * is supplied. + * @NL80211_CMD_STOP_SCHED_SCAN: stop a scheduled scan. Returns -ERRNOENT if + * scheduled scan is not running. The caller may assume that as soon + * as the call returns, it is safe to start a new scheduled scan again. + * @NL80211_CMD_SCHED_SCAN_RESULTS: indicates that there are scheduled scan + * results available. + * @NL80211_CMD_SCHED_SCAN_STOPPED: indicates that the scheduled scan has + * stopped. The driver may issue this event at any time during a + * scheduled scan. One reason for stopping the scan is if the hardware + * does not support starting an association or a normal scan while running + * a scheduled scan. This event is also sent when the + * %NL80211_CMD_STOP_SCHED_SCAN command is received or when the interface + * is brought down while a scheduled scan was running. + * + * @NL80211_CMD_GET_SURVEY: get survey resuls, e.g. channel occupation + * or noise level + * @NL80211_CMD_NEW_SURVEY_RESULTS: survey data notification (as a reply to + * NL80211_CMD_GET_SURVEY and on the "scan" multicast group) + * + * @NL80211_CMD_SET_PMKSA: Add a PMKSA cache entry, using %NL80211_ATTR_MAC + * (for the BSSID) and %NL80211_ATTR_PMKID. + * @NL80211_CMD_DEL_PMKSA: Delete a PMKSA cache entry, using %NL80211_ATTR_MAC + * (for the BSSID) and %NL80211_ATTR_PMKID. + * @NL80211_CMD_FLUSH_PMKSA: Flush all PMKSA cache entries. + * + * @NL80211_CMD_REG_CHANGE: indicates to userspace the regulatory domain + * has been changed and provides details of the request information + * that caused the change such as who initiated the regulatory request + * (%NL80211_ATTR_REG_INITIATOR), the wiphy_idx + * (%NL80211_ATTR_REG_ALPHA2) on which the request was made from if + * the initiator was %NL80211_REGDOM_SET_BY_COUNTRY_IE or + * %NL80211_REGDOM_SET_BY_DRIVER, the type of regulatory domain + * set (%NL80211_ATTR_REG_TYPE), if the type of regulatory domain is + * %NL80211_REG_TYPE_COUNTRY the alpha2 to which we have moved on + * to (%NL80211_ATTR_REG_ALPHA2). + * @NL80211_CMD_REG_BEACON_HINT: indicates to userspace that an AP beacon + * has been found while world roaming thus enabling active scan or + * any mode of operation that initiates TX (beacons) on a channel + * where we would not have been able to do either before. As an example + * if you are world roaming (regulatory domain set to world or if your + * driver is using a custom world roaming regulatory domain) and while + * doing a passive scan on the 5 GHz band you find an AP there (if not + * on a DFS channel) you will now be able to actively scan for that AP + * or use AP mode on your card on that same channel. Note that this will + * never be used for channels 1-11 on the 2 GHz band as they are always + * enabled world wide. This beacon hint is only sent if your device had + * either disabled active scanning or beaconing on a channel. We send to + * userspace the wiphy on which we removed a restriction from + * (%NL80211_ATTR_WIPHY) and the channel on which this occurred + * before (%NL80211_ATTR_FREQ_BEFORE) and after (%NL80211_ATTR_FREQ_AFTER) + * the beacon hint was processed. + * + * @NL80211_CMD_AUTHENTICATE: authentication request and notification. + * This command is used both as a command (request to authenticate) and + * as an event on the "mlme" multicast group indicating completion of the + * authentication process. + * When used as a command, %NL80211_ATTR_IFINDEX is used to identify the + * interface. %NL80211_ATTR_MAC is used to specify PeerSTAAddress (and + * BSSID in case of station mode). %NL80211_ATTR_SSID is used to specify + * the SSID (mainly for association, but is included in authentication + * request, too, to help BSS selection. %NL80211_ATTR_WIPHY_FREQ is used + * to specify the frequence of the channel in MHz. %NL80211_ATTR_AUTH_TYPE + * is used to specify the authentication type. %NL80211_ATTR_IE is used to + * define IEs (VendorSpecificInfo, but also including RSN IE and FT IEs) + * to be added to the frame. + * When used as an event, this reports reception of an Authentication + * frame in station and IBSS modes when the local MLME processed the + * frame, i.e., it was for the local STA and was received in correct + * state. This is similar to MLME-AUTHENTICATE.confirm primitive in the + * MLME SAP interface (kernel providing MLME, userspace SME). The + * included %NL80211_ATTR_FRAME attribute contains the management frame + * (including both the header and frame body, but not FCS). This event is + * also used to indicate if the authentication attempt timed out. In that + * case the %NL80211_ATTR_FRAME attribute is replaced with a + * %NL80211_ATTR_TIMED_OUT flag (and %NL80211_ATTR_MAC to indicate which + * pending authentication timed out). + * @NL80211_CMD_ASSOCIATE: association request and notification; like + * NL80211_CMD_AUTHENTICATE but for Association and Reassociation + * (similar to MLME-ASSOCIATE.request, MLME-REASSOCIATE.request, + * MLME-ASSOCIATE.confirm or MLME-REASSOCIATE.confirm primitives). + * @NL80211_CMD_DEAUTHENTICATE: deauthentication request and notification; like + * NL80211_CMD_AUTHENTICATE but for Deauthentication frames (similar to + * MLME-DEAUTHENTICATION.request and MLME-DEAUTHENTICATE.indication + * primitives). + * @NL80211_CMD_DISASSOCIATE: disassociation request and notification; like + * NL80211_CMD_AUTHENTICATE but for Disassociation frames (similar to + * MLME-DISASSOCIATE.request and MLME-DISASSOCIATE.indication primitives). + * + * @NL80211_CMD_MICHAEL_MIC_FAILURE: notification of a locally detected Michael + * MIC (part of TKIP) failure; sent on the "mlme" multicast group; the + * event includes %NL80211_ATTR_MAC to describe the source MAC address of + * the frame with invalid MIC, %NL80211_ATTR_KEY_TYPE to show the key + * type, %NL80211_ATTR_KEY_IDX to indicate the key identifier, and + * %NL80211_ATTR_KEY_SEQ to indicate the TSC value of the frame; this + * event matches with MLME-MICHAELMICFAILURE.indication() primitive + * + * @NL80211_CMD_JOIN_IBSS: Join a new IBSS -- given at least an SSID and a + * FREQ attribute (for the initial frequency if no peer can be found) + * and optionally a MAC (as BSSID) and FREQ_FIXED attribute if those + * should be fixed rather than automatically determined. Can only be + * executed on a network interface that is UP, and fixed BSSID/FREQ + * may be rejected. Another optional parameter is the beacon interval, + * given in the %NL80211_ATTR_BEACON_INTERVAL attribute, which if not + * given defaults to 100 TU (102.4ms). + * @NL80211_CMD_LEAVE_IBSS: Leave the IBSS -- no special arguments, the IBSS is + * determined by the network interface. + * + * @NL80211_CMD_TESTMODE: testmode command, takes a wiphy (or ifindex) attribute + * to identify the device, and the TESTDATA blob attribute to pass through + * to the driver. + * + * @NL80211_CMD_CONNECT: connection request and notification; this command + * requests to connect to a specified network but without separating + * auth and assoc steps. For this, you need to specify the SSID in a + * %NL80211_ATTR_SSID attribute, and can optionally specify the association + * IEs in %NL80211_ATTR_IE, %NL80211_ATTR_AUTH_TYPE, %NL80211_ATTR_USE_MFP, + * %NL80211_ATTR_MAC, %NL80211_ATTR_WIPHY_FREQ, %NL80211_ATTR_CONTROL_PORT, + * %NL80211_ATTR_CONTROL_PORT_ETHERTYPE, + * %NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT, %NL80211_ATTR_MAC_HINT, and + * %NL80211_ATTR_WIPHY_FREQ_HINT. + * If included, %NL80211_ATTR_MAC and %NL80211_ATTR_WIPHY_FREQ are + * restrictions on BSS selection, i.e., they effectively prevent roaming + * within the ESS. %NL80211_ATTR_MAC_HINT and %NL80211_ATTR_WIPHY_FREQ_HINT + * can be included to provide a recommendation of the initial BSS while + * allowing the driver to roam to other BSSes within the ESS and also to + * ignore this recommendation if the indicated BSS is not ideal. Only one + * set of BSSID,frequency parameters is used (i.e., either the enforcing + * %NL80211_ATTR_MAC,%NL80211_ATTR_WIPHY_FREQ or the less strict + * %NL80211_ATTR_MAC_HINT and %NL80211_ATTR_WIPHY_FREQ_HINT). + * Background scan period can optionally be + * specified in %NL80211_ATTR_BG_SCAN_PERIOD, + * if not specified default background scan configuration + * in driver is used and if period value is 0, bg scan will be disabled. + * This attribute is ignored if driver does not support roam scan. + * It is also sent as an event, with the BSSID and response IEs when the + * connection is established or failed to be established. This can be + * determined by the STATUS_CODE attribute. + * @NL80211_CMD_ROAM: request that the card roam (currently not implemented), + * sent as an event when the card/driver roamed by itself. + * @NL80211_CMD_DISCONNECT: drop a given connection; also used to notify + * userspace that a connection was dropped by the AP or due to other + * reasons, for this the %NL80211_ATTR_DISCONNECTED_BY_AP and + * %NL80211_ATTR_REASON_CODE attributes are used. + * + * @NL80211_CMD_SET_WIPHY_NETNS: Set a wiphy's netns. Note that all devices + * associated with this wiphy must be down and will follow. + * + * @NL80211_CMD_REMAIN_ON_CHANNEL: Request to remain awake on the specified + * channel for the specified amount of time. This can be used to do + * off-channel operations like transmit a Public Action frame and wait for + * a response while being associated to an AP on another channel. + * %NL80211_ATTR_IFINDEX is used to specify which interface (and thus + * radio) is used. %NL80211_ATTR_WIPHY_FREQ is used to specify the + * frequency for the operation. + * %NL80211_ATTR_DURATION is used to specify the duration in milliseconds + * to remain on the channel. This command is also used as an event to + * notify when the requested duration starts (it may take a while for the + * driver to schedule this time due to other concurrent needs for the + * radio). + * When called, this operation returns a cookie (%NL80211_ATTR_COOKIE) + * that will be included with any events pertaining to this request; + * the cookie is also used to cancel the request. + * @NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL: This command can be used to cancel a + * pending remain-on-channel duration if the desired operation has been + * completed prior to expiration of the originally requested duration. + * %NL80211_ATTR_WIPHY or %NL80211_ATTR_IFINDEX is used to specify the + * radio. The %NL80211_ATTR_COOKIE attribute must be given as well to + * uniquely identify the request. + * This command is also used as an event to notify when a requested + * remain-on-channel duration has expired. + * + * @NL80211_CMD_SET_TX_BITRATE_MASK: Set the mask of rates to be used in TX + * rate selection. %NL80211_ATTR_IFINDEX is used to specify the interface + * and @NL80211_ATTR_TX_RATES the set of allowed rates. + * + * @NL80211_CMD_REGISTER_FRAME: Register for receiving certain mgmt frames + * (via @NL80211_CMD_FRAME) for processing in userspace. This command + * requires an interface index, a frame type attribute (optional for + * backward compatibility reasons, if not given assumes action frames) + * and a match attribute containing the first few bytes of the frame + * that should match, e.g. a single byte for only a category match or + * four bytes for vendor frames including the OUI. The registration + * cannot be dropped, but is removed automatically when the netlink + * socket is closed. Multiple registrations can be made. + * @NL80211_CMD_REGISTER_ACTION: Alias for @NL80211_CMD_REGISTER_FRAME for + * backward compatibility + * @NL80211_CMD_FRAME: Management frame TX request and RX notification. This + * command is used both as a request to transmit a management frame and + * as an event indicating reception of a frame that was not processed in + * kernel code, but is for us (i.e., which may need to be processed in a + * user space application). %NL80211_ATTR_FRAME is used to specify the + * frame contents (including header). %NL80211_ATTR_WIPHY_FREQ is used + * to indicate on which channel the frame is to be transmitted or was + * received. If this channel is not the current channel (remain-on-channel + * or the operational channel) the device will switch to the given channel + * and transmit the frame, optionally waiting for a response for the time + * specified using %NL80211_ATTR_DURATION. When called, this operation + * returns a cookie (%NL80211_ATTR_COOKIE) that will be included with the + * TX status event pertaining to the TX request. + * %NL80211_ATTR_TX_NO_CCK_RATE is used to decide whether to send the + * management frames at CCK rate or not in 2GHz band. + * %NL80211_ATTR_CSA_C_OFFSETS_TX is an array of offsets to CSA + * counters which will be updated to the current value. This attribute + * is used during CSA period. + * @NL80211_CMD_FRAME_WAIT_CANCEL: When an off-channel TX was requested, this + * command may be used with the corresponding cookie to cancel the wait + * time if it is known that it is no longer necessary. + * @NL80211_CMD_ACTION: Alias for @NL80211_CMD_FRAME for backward compatibility. + * @NL80211_CMD_FRAME_TX_STATUS: Report TX status of a management frame + * transmitted with %NL80211_CMD_FRAME. %NL80211_ATTR_COOKIE identifies + * the TX command and %NL80211_ATTR_FRAME includes the contents of the + * frame. %NL80211_ATTR_ACK flag is included if the recipient acknowledged + * the frame. + * @NL80211_CMD_ACTION_TX_STATUS: Alias for @NL80211_CMD_FRAME_TX_STATUS for + * backward compatibility. + * + * @NL80211_CMD_SET_POWER_SAVE: Set powersave, using %NL80211_ATTR_PS_STATE + * @NL80211_CMD_GET_POWER_SAVE: Get powersave status in %NL80211_ATTR_PS_STATE + * + * @NL80211_CMD_SET_CQM: Connection quality monitor configuration. This command + * is used to configure connection quality monitoring notification trigger + * levels. + * @NL80211_CMD_NOTIFY_CQM: Connection quality monitor notification. This + * command is used as an event to indicate the that a trigger level was + * reached. + * @NL80211_CMD_SET_CHANNEL: Set the channel (using %NL80211_ATTR_WIPHY_FREQ + * and the attributes determining channel width) the given interface + * (identifed by %NL80211_ATTR_IFINDEX) shall operate on. + * In case multiple channels are supported by the device, the mechanism + * with which it switches channels is implementation-defined. + * When a monitor interface is given, it can only switch channel while + * no other interfaces are operating to avoid disturbing the operation + * of any other interfaces, and other interfaces will again take + * precedence when they are used. + * + * @NL80211_CMD_SET_WDS_PEER: Set the MAC address of the peer on a WDS interface. + * + * @NL80211_CMD_JOIN_MESH: Join a mesh. The mesh ID must be given, and initial + * mesh config parameters may be given. + * @NL80211_CMD_LEAVE_MESH: Leave the mesh network -- no special arguments, the + * network is determined by the network interface. + * + * @NL80211_CMD_UNPROT_DEAUTHENTICATE: Unprotected deauthentication frame + * notification. This event is used to indicate that an unprotected + * deauthentication frame was dropped when MFP is in use. + * @NL80211_CMD_UNPROT_DISASSOCIATE: Unprotected disassociation frame + * notification. This event is used to indicate that an unprotected + * disassociation frame was dropped when MFP is in use. + * + * @NL80211_CMD_NEW_PEER_CANDIDATE: Notification on the reception of a + * beacon or probe response from a compatible mesh peer. This is only + * sent while no station information (sta_info) exists for the new peer + * candidate and when @NL80211_MESH_SETUP_USERSPACE_AUTH, + * @NL80211_MESH_SETUP_USERSPACE_AMPE, or + * @NL80211_MESH_SETUP_USERSPACE_MPM is set. On reception of this + * notification, userspace may decide to create a new station + * (@NL80211_CMD_NEW_STATION). To stop this notification from + * reoccurring, the userspace authentication daemon may want to create the + * new station with the AUTHENTICATED flag unset and maybe change it later + * depending on the authentication result. + * + * @NL80211_CMD_GET_WOWLAN: get Wake-on-Wireless-LAN (WoWLAN) settings. + * @NL80211_CMD_SET_WOWLAN: set Wake-on-Wireless-LAN (WoWLAN) settings. + * Since wireless is more complex than wired ethernet, it supports + * various triggers. These triggers can be configured through this + * command with the %NL80211_ATTR_WOWLAN_TRIGGERS attribute. For + * more background information, see + * http://wireless.kernel.org/en/users/Documentation/WoWLAN. + * The @NL80211_CMD_SET_WOWLAN command can also be used as a notification + * from the driver reporting the wakeup reason. In this case, the + * @NL80211_ATTR_WOWLAN_TRIGGERS attribute will contain the reason + * for the wakeup, if it was caused by wireless. If it is not present + * in the wakeup notification, the wireless device didn't cause the + * wakeup but reports that it was woken up. + * + * @NL80211_CMD_SET_REKEY_OFFLOAD: This command is used give the driver + * the necessary information for supporting GTK rekey offload. This + * feature is typically used during WoWLAN. The configuration data + * is contained in %NL80211_ATTR_REKEY_DATA (which is nested and + * contains the data in sub-attributes). After rekeying happened, + * this command may also be sent by the driver as an MLME event to + * inform userspace of the new replay counter. + * + * @NL80211_CMD_PMKSA_CANDIDATE: This is used as an event to inform userspace + * of PMKSA caching dandidates. + * + * @NL80211_CMD_TDLS_OPER: Perform a high-level TDLS command (e.g. link setup). + * In addition, this can be used as an event to request userspace to take + * actions on TDLS links (set up a new link or tear down an existing one). + * In such events, %NL80211_ATTR_TDLS_OPERATION indicates the requested + * operation, %NL80211_ATTR_MAC contains the peer MAC address, and + * %NL80211_ATTR_REASON_CODE the reason code to be used (only with + * %NL80211_TDLS_TEARDOWN). + * @NL80211_CMD_TDLS_MGMT: Send a TDLS management frame. The + * %NL80211_ATTR_TDLS_ACTION attribute determines the type of frame to be + * sent. Public Action codes (802.11-2012 8.1.5.1) will be sent as + * 802.11 management frames, while TDLS action codes (802.11-2012 + * 8.5.13.1) will be encapsulated and sent as data frames. The currently + * supported Public Action code is %WLAN_PUB_ACTION_TDLS_DISCOVER_RES + * and the currently supported TDLS actions codes are given in + * &enum ieee80211_tdls_actioncode. + * + * @NL80211_CMD_UNEXPECTED_FRAME: Used by an application controlling an AP + * (or GO) interface (i.e. hostapd) to ask for unexpected frames to + * implement sending deauth to stations that send unexpected class 3 + * frames. Also used as the event sent by the kernel when such a frame + * is received. + * For the event, the %NL80211_ATTR_MAC attribute carries the TA and + * other attributes like the interface index are present. + * If used as the command it must have an interface index and you can + * only unsubscribe from the event by closing the socket. Subscription + * is also for %NL80211_CMD_UNEXPECTED_4ADDR_FRAME events. + * + * @NL80211_CMD_UNEXPECTED_4ADDR_FRAME: Sent as an event indicating that the + * associated station identified by %NL80211_ATTR_MAC sent a 4addr frame + * and wasn't already in a 4-addr VLAN. The event will be sent similarly + * to the %NL80211_CMD_UNEXPECTED_FRAME event, to the same listener. + * + * @NL80211_CMD_PROBE_CLIENT: Probe an associated station on an AP interface + * by sending a null data frame to it and reporting when the frame is + * acknowleged. This is used to allow timing out inactive clients. Uses + * %NL80211_ATTR_IFINDEX and %NL80211_ATTR_MAC. The command returns a + * direct reply with an %NL80211_ATTR_COOKIE that is later used to match + * up the event with the request. The event includes the same data and + * has %NL80211_ATTR_ACK set if the frame was ACKed. + * + * @NL80211_CMD_REGISTER_BEACONS: Register this socket to receive beacons from + * other BSSes when any interfaces are in AP mode. This helps implement + * OLBC handling in hostapd. Beacons are reported in %NL80211_CMD_FRAME + * messages. Note that per PHY only one application may register. + * + * @NL80211_CMD_SET_NOACK_MAP: sets a bitmap for the individual TIDs whether + * No Acknowledgement Policy should be applied. + * + * @NL80211_CMD_CH_SWITCH_NOTIFY: An AP or GO may decide to switch channels + * independently of the userspace SME, send this event indicating + * %NL80211_ATTR_IFINDEX is now on %NL80211_ATTR_WIPHY_FREQ and the + * attributes determining channel width. This indication may also be + * sent when a remotely-initiated switch (e.g., when a STA receives a CSA + * from the remote AP) is completed; + * + * @NL80211_CMD_CH_SWITCH_STARTED_NOTIFY: Notify that a channel switch + * has been started on an interface, regardless of the initiator + * (ie. whether it was requested from a remote device or + * initiated on our own). It indicates that + * %NL80211_ATTR_IFINDEX will be on %NL80211_ATTR_WIPHY_FREQ + * after %NL80211_ATTR_CH_SWITCH_COUNT TBTT's. The userspace may + * decide to react to this indication by requesting other + * interfaces to change channel as well. + * + * @NL80211_CMD_START_P2P_DEVICE: Start the given P2P Device, identified by + * its %NL80211_ATTR_WDEV identifier. It must have been created with + * %NL80211_CMD_NEW_INTERFACE previously. After it has been started, the + * P2P Device can be used for P2P operations, e.g. remain-on-channel and + * public action frame TX. + * @NL80211_CMD_STOP_P2P_DEVICE: Stop the given P2P Device, identified by + * its %NL80211_ATTR_WDEV identifier. + * + * @NL80211_CMD_CONN_FAILED: connection request to an AP failed; used to + * notify userspace that AP has rejected the connection request from a + * station, due to particular reason. %NL80211_ATTR_CONN_FAILED_REASON + * is used for this. + * + * @NL80211_CMD_SET_MCAST_RATE: Change the rate used to send multicast frames + * for IBSS or MESH vif. + * + * @NL80211_CMD_SET_MAC_ACL: sets ACL for MAC address based access control. + * This is to be used with the drivers advertising the support of MAC + * address based access control. List of MAC addresses is passed in + * %NL80211_ATTR_MAC_ADDRS and ACL policy is passed in + * %NL80211_ATTR_ACL_POLICY. Driver will enable ACL with this list, if it + * is not already done. The new list will replace any existing list. Driver + * will clear its ACL when the list of MAC addresses passed is empty. This + * command is used in AP/P2P GO mode. Driver has to make sure to clear its + * ACL list during %NL80211_CMD_STOP_AP. + * + * @NL80211_CMD_RADAR_DETECT: Start a Channel availability check (CAC). Once + * a radar is detected or the channel availability scan (CAC) has finished + * or was aborted, or a radar was detected, usermode will be notified with + * this event. This command is also used to notify userspace about radars + * while operating on this channel. + * %NL80211_ATTR_RADAR_EVENT is used to inform about the type of the + * event. + * + * @NL80211_CMD_GET_PROTOCOL_FEATURES: Get global nl80211 protocol features, + * i.e. features for the nl80211 protocol rather than device features. + * Returns the features in the %NL80211_ATTR_PROTOCOL_FEATURES bitmap. + * + * @NL80211_CMD_UPDATE_FT_IES: Pass down the most up-to-date Fast Transition + * Information Element to the WLAN driver + * + * @NL80211_CMD_FT_EVENT: Send a Fast transition event from the WLAN driver + * to the supplicant. This will carry the target AP's MAC address along + * with the relevant Information Elements. This event is used to report + * received FT IEs (MDIE, FTIE, RSN IE, TIE, RICIE). + * + * @NL80211_CMD_CRIT_PROTOCOL_START: Indicates user-space will start running + * a critical protocol that needs more reliability in the connection to + * complete. + * + * @NL80211_CMD_CRIT_PROTOCOL_STOP: Indicates the connection reliability can + * return back to normal. + * + * @NL80211_CMD_GET_COALESCE: Get currently supported coalesce rules. + * @NL80211_CMD_SET_COALESCE: Configure coalesce rules or clear existing rules. + * + * @NL80211_CMD_CHANNEL_SWITCH: Perform a channel switch by announcing the + * the new channel information (Channel Switch Announcement - CSA) + * in the beacon for some time (as defined in the + * %NL80211_ATTR_CH_SWITCH_COUNT parameter) and then change to the + * new channel. Userspace provides the new channel information (using + * %NL80211_ATTR_WIPHY_FREQ and the attributes determining channel + * width). %NL80211_ATTR_CH_SWITCH_BLOCK_TX may be supplied to inform + * other station that transmission must be blocked until the channel + * switch is complete. + * + * @NL80211_CMD_VENDOR: Vendor-specified command/event. The command is specified + * by the %NL80211_ATTR_VENDOR_ID attribute and a sub-command in + * %NL80211_ATTR_VENDOR_SUBCMD. Parameter(s) can be transported in + * %NL80211_ATTR_VENDOR_DATA. + * For feature advertisement, the %NL80211_ATTR_VENDOR_DATA attribute is + * used in the wiphy data as a nested attribute containing descriptions + * (&struct nl80211_vendor_cmd_info) of the supported vendor commands. + * This may also be sent as an event with the same attributes. + * + * @NL80211_CMD_SET_QOS_MAP: Set Interworking QoS mapping for IP DSCP values. + * The QoS mapping information is included in %NL80211_ATTR_QOS_MAP. If + * that attribute is not included, QoS mapping is disabled. Since this + * QoS mapping is relevant for IP packets, it is only valid during an + * association. This is cleared on disassociation and AP restart. + * + * @NL80211_CMD_ADD_TX_TS: Ask the kernel to add a traffic stream for the given + * %NL80211_ATTR_TSID and %NL80211_ATTR_MAC with %NL80211_ATTR_USER_PRIO + * and %NL80211_ATTR_ADMITTED_TIME parameters. + * Note that the action frame handshake with the AP shall be handled by + * userspace via the normal management RX/TX framework, this only sets + * up the TX TS in the driver/device. + * If the admitted time attribute is not added then the request just checks + * if a subsequent setup could be successful, the intent is to use this to + * avoid setting up a session with the AP when local restrictions would + * make that impossible. However, the subsequent "real" setup may still + * fail even if the check was successful. + * @NL80211_CMD_DEL_TX_TS: Remove an existing TS with the %NL80211_ATTR_TSID + * and %NL80211_ATTR_MAC parameters. It isn't necessary to call this + * before removing a station entry entirely, or before disassociating + * or similar, cleanup will happen in the driver/device in this case. + * + * @NL80211_CMD_GET_MPP: Get mesh path attributes for mesh proxy path to + * destination %NL80211_ATTR_MAC on the interface identified by + * %NL80211_ATTR_IFINDEX. + * + * @NL80211_CMD_JOIN_OCB: Join the OCB network. The center frequency and + * bandwidth of a channel must be given. + * @NL80211_CMD_LEAVE_OCB: Leave the OCB network -- no special arguments, the + * network is determined by the network interface. + * + * @NL80211_CMD_TDLS_CHANNEL_SWITCH: Start channel-switching with a TDLS peer, + * identified by the %NL80211_ATTR_MAC parameter. A target channel is + * provided via %NL80211_ATTR_WIPHY_FREQ and other attributes determining + * channel width/type. The target operating class is given via + * %NL80211_ATTR_OPER_CLASS. + * The driver is responsible for continually initiating channel-switching + * operations and returning to the base channel for communication with the + * AP. + * @NL80211_CMD_TDLS_CANCEL_CHANNEL_SWITCH: Stop channel-switching with a TDLS + * peer given by %NL80211_ATTR_MAC. Both peers must be on the base channel + * when this command completes. + * + * @NL80211_CMD_WIPHY_REG_CHANGE: Similar to %NL80211_CMD_REG_CHANGE, but used + * as an event to indicate changes for devices with wiphy-specific regdom + * management. + * + * @NL80211_CMD_MAX: highest used command number + * @__NL80211_CMD_AFTER_LAST: internal use + */ +enum nl80211_commands { +/* don't change the order or add anything between, this is ABI! */ + NL80211_CMD_UNSPEC, + + NL80211_CMD_GET_WIPHY, /* can dump */ + NL80211_CMD_SET_WIPHY, + NL80211_CMD_NEW_WIPHY, + NL80211_CMD_DEL_WIPHY, + + NL80211_CMD_GET_INTERFACE, /* can dump */ + NL80211_CMD_SET_INTERFACE, + NL80211_CMD_NEW_INTERFACE, + NL80211_CMD_DEL_INTERFACE, + + NL80211_CMD_GET_KEY, + NL80211_CMD_SET_KEY, + NL80211_CMD_NEW_KEY, + NL80211_CMD_DEL_KEY, + + NL80211_CMD_GET_BEACON, + NL80211_CMD_SET_BEACON, + NL80211_CMD_START_AP, + NL80211_CMD_NEW_BEACON = NL80211_CMD_START_AP, + NL80211_CMD_STOP_AP, + NL80211_CMD_DEL_BEACON = NL80211_CMD_STOP_AP, + + NL80211_CMD_GET_STATION, + NL80211_CMD_SET_STATION, + NL80211_CMD_NEW_STATION, + NL80211_CMD_DEL_STATION, + + NL80211_CMD_GET_MPATH, + NL80211_CMD_SET_MPATH, + NL80211_CMD_NEW_MPATH, + NL80211_CMD_DEL_MPATH, + + NL80211_CMD_SET_BSS, + + NL80211_CMD_SET_REG, + NL80211_CMD_REQ_SET_REG, + + NL80211_CMD_GET_MESH_CONFIG, + NL80211_CMD_SET_MESH_CONFIG, + + NL80211_CMD_SET_MGMT_EXTRA_IE /* reserved; not used */, + + NL80211_CMD_GET_REG, + + NL80211_CMD_GET_SCAN, + NL80211_CMD_TRIGGER_SCAN, + NL80211_CMD_NEW_SCAN_RESULTS, + NL80211_CMD_SCAN_ABORTED, + + NL80211_CMD_REG_CHANGE, + + NL80211_CMD_AUTHENTICATE, + NL80211_CMD_ASSOCIATE, + NL80211_CMD_DEAUTHENTICATE, + NL80211_CMD_DISASSOCIATE, + + NL80211_CMD_MICHAEL_MIC_FAILURE, + + NL80211_CMD_REG_BEACON_HINT, + + NL80211_CMD_JOIN_IBSS, + NL80211_CMD_LEAVE_IBSS, + + NL80211_CMD_TESTMODE, + + NL80211_CMD_CONNECT, + NL80211_CMD_ROAM, + NL80211_CMD_DISCONNECT, + + NL80211_CMD_SET_WIPHY_NETNS, + + NL80211_CMD_GET_SURVEY, + NL80211_CMD_NEW_SURVEY_RESULTS, + + NL80211_CMD_SET_PMKSA, + NL80211_CMD_DEL_PMKSA, + NL80211_CMD_FLUSH_PMKSA, + + NL80211_CMD_REMAIN_ON_CHANNEL, + NL80211_CMD_CANCEL_REMAIN_ON_CHANNEL, + + NL80211_CMD_SET_TX_BITRATE_MASK, + + NL80211_CMD_REGISTER_FRAME, + NL80211_CMD_REGISTER_ACTION = NL80211_CMD_REGISTER_FRAME, + NL80211_CMD_FRAME, + NL80211_CMD_ACTION = NL80211_CMD_FRAME, + NL80211_CMD_FRAME_TX_STATUS, + NL80211_CMD_ACTION_TX_STATUS = NL80211_CMD_FRAME_TX_STATUS, + + NL80211_CMD_SET_POWER_SAVE, + NL80211_CMD_GET_POWER_SAVE, + + NL80211_CMD_SET_CQM, + NL80211_CMD_NOTIFY_CQM, + + NL80211_CMD_SET_CHANNEL, + NL80211_CMD_SET_WDS_PEER, + + NL80211_CMD_FRAME_WAIT_CANCEL, + + NL80211_CMD_JOIN_MESH, + NL80211_CMD_LEAVE_MESH, + + NL80211_CMD_UNPROT_DEAUTHENTICATE, + NL80211_CMD_UNPROT_DISASSOCIATE, + + NL80211_CMD_NEW_PEER_CANDIDATE, + + NL80211_CMD_GET_WOWLAN, + NL80211_CMD_SET_WOWLAN, + + NL80211_CMD_START_SCHED_SCAN, + NL80211_CMD_STOP_SCHED_SCAN, + NL80211_CMD_SCHED_SCAN_RESULTS, + NL80211_CMD_SCHED_SCAN_STOPPED, + + NL80211_CMD_SET_REKEY_OFFLOAD, + + NL80211_CMD_PMKSA_CANDIDATE, + + NL80211_CMD_TDLS_OPER, + NL80211_CMD_TDLS_MGMT, + + NL80211_CMD_UNEXPECTED_FRAME, + + NL80211_CMD_PROBE_CLIENT, + + NL80211_CMD_REGISTER_BEACONS, + + NL80211_CMD_UNEXPECTED_4ADDR_FRAME, + + NL80211_CMD_SET_NOACK_MAP, + + NL80211_CMD_CH_SWITCH_NOTIFY, + + NL80211_CMD_START_P2P_DEVICE, + NL80211_CMD_STOP_P2P_DEVICE, + + NL80211_CMD_CONN_FAILED, + + NL80211_CMD_SET_MCAST_RATE, + + NL80211_CMD_SET_MAC_ACL, + + NL80211_CMD_RADAR_DETECT, + + NL80211_CMD_GET_PROTOCOL_FEATURES, + + NL80211_CMD_UPDATE_FT_IES, + NL80211_CMD_FT_EVENT, + + NL80211_CMD_CRIT_PROTOCOL_START, + NL80211_CMD_CRIT_PROTOCOL_STOP, + + NL80211_CMD_GET_COALESCE, + NL80211_CMD_SET_COALESCE, + + NL80211_CMD_CHANNEL_SWITCH, + + NL80211_CMD_VENDOR, + + NL80211_CMD_SET_QOS_MAP, + + NL80211_CMD_ADD_TX_TS, + NL80211_CMD_DEL_TX_TS, + + NL80211_CMD_GET_MPP, + + NL80211_CMD_JOIN_OCB, + NL80211_CMD_LEAVE_OCB, + + NL80211_CMD_CH_SWITCH_STARTED_NOTIFY, + + NL80211_CMD_TDLS_CHANNEL_SWITCH, + NL80211_CMD_TDLS_CANCEL_CHANNEL_SWITCH, + + NL80211_CMD_WIPHY_REG_CHANGE, + + /* add new commands above here */ + + /* used to define NL80211_CMD_MAX below */ + __NL80211_CMD_AFTER_LAST, + NL80211_CMD_MAX = __NL80211_CMD_AFTER_LAST - 1 +}; + +/* + * Allow user space programs to use #ifdef on new commands by defining them + * here + */ +#define NL80211_CMD_SET_BSS NL80211_CMD_SET_BSS +#define NL80211_CMD_SET_MGMT_EXTRA_IE NL80211_CMD_SET_MGMT_EXTRA_IE +#define NL80211_CMD_REG_CHANGE NL80211_CMD_REG_CHANGE +#define NL80211_CMD_AUTHENTICATE NL80211_CMD_AUTHENTICATE +#define NL80211_CMD_ASSOCIATE NL80211_CMD_ASSOCIATE +#define NL80211_CMD_DEAUTHENTICATE NL80211_CMD_DEAUTHENTICATE +#define NL80211_CMD_DISASSOCIATE NL80211_CMD_DISASSOCIATE +#define NL80211_CMD_REG_BEACON_HINT NL80211_CMD_REG_BEACON_HINT + +#define NL80211_ATTR_FEATURE_FLAGS NL80211_ATTR_FEATURE_FLAGS + +/* source-level API compatibility */ +#define NL80211_CMD_GET_MESH_PARAMS NL80211_CMD_GET_MESH_CONFIG +#define NL80211_CMD_SET_MESH_PARAMS NL80211_CMD_SET_MESH_CONFIG +#define NL80211_MESH_SETUP_VENDOR_PATH_SEL_IE NL80211_MESH_SETUP_IE + +/** + * enum nl80211_attrs - nl80211 netlink attributes + * + * @NL80211_ATTR_UNSPEC: unspecified attribute to catch errors + * + * @NL80211_ATTR_WIPHY: index of wiphy to operate on, cf. + * /sys/class/ieee80211//index + * @NL80211_ATTR_WIPHY_NAME: wiphy name (used for renaming) + * @NL80211_ATTR_WIPHY_TXQ_PARAMS: a nested array of TX queue parameters + * @NL80211_ATTR_WIPHY_FREQ: frequency of the selected channel in MHz, + * defines the channel together with the (deprecated) + * %NL80211_ATTR_WIPHY_CHANNEL_TYPE attribute or the attributes + * %NL80211_ATTR_CHANNEL_WIDTH and if needed %NL80211_ATTR_CENTER_FREQ1 + * and %NL80211_ATTR_CENTER_FREQ2 + * @NL80211_ATTR_CHANNEL_WIDTH: u32 attribute containing one of the values + * of &enum nl80211_chan_width, describing the channel width. See the + * documentation of the enum for more information. + * @NL80211_ATTR_CENTER_FREQ1: Center frequency of the first part of the + * channel, used for anything but 20 MHz bandwidth + * @NL80211_ATTR_CENTER_FREQ2: Center frequency of the second part of the + * channel, used only for 80+80 MHz bandwidth + * @NL80211_ATTR_WIPHY_CHANNEL_TYPE: included with NL80211_ATTR_WIPHY_FREQ + * if HT20 or HT40 are to be used (i.e., HT disabled if not included): + * NL80211_CHAN_NO_HT = HT not allowed (i.e., same as not including + * this attribute) + * NL80211_CHAN_HT20 = HT20 only + * NL80211_CHAN_HT40MINUS = secondary channel is below the primary channel + * NL80211_CHAN_HT40PLUS = secondary channel is above the primary channel + * This attribute is now deprecated. + * @NL80211_ATTR_WIPHY_RETRY_SHORT: TX retry limit for frames whose length is + * less than or equal to the RTS threshold; allowed range: 1..255; + * dot11ShortRetryLimit; u8 + * @NL80211_ATTR_WIPHY_RETRY_LONG: TX retry limit for frames whose length is + * greater than the RTS threshold; allowed range: 1..255; + * dot11ShortLongLimit; u8 + * @NL80211_ATTR_WIPHY_FRAG_THRESHOLD: fragmentation threshold, i.e., maximum + * length in octets for frames; allowed range: 256..8000, disable + * fragmentation with (u32)-1; dot11FragmentationThreshold; u32 + * @NL80211_ATTR_WIPHY_RTS_THRESHOLD: RTS threshold (TX frames with length + * larger than or equal to this use RTS/CTS handshake); allowed range: + * 0..65536, disable with (u32)-1; dot11RTSThreshold; u32 + * @NL80211_ATTR_WIPHY_COVERAGE_CLASS: Coverage Class as defined by IEEE 802.11 + * section 7.3.2.9; dot11CoverageClass; u8 + * + * @NL80211_ATTR_IFINDEX: network interface index of the device to operate on + * @NL80211_ATTR_IFNAME: network interface name + * @NL80211_ATTR_IFTYPE: type of virtual interface, see &enum nl80211_iftype + * + * @NL80211_ATTR_WDEV: wireless device identifier, used for pseudo-devices + * that don't have a netdev (u64) + * + * @NL80211_ATTR_MAC: MAC address (various uses) + * + * @NL80211_ATTR_KEY_DATA: (temporal) key data; for TKIP this consists of + * 16 bytes encryption key followed by 8 bytes each for TX and RX MIC + * keys + * @NL80211_ATTR_KEY_IDX: key ID (u8, 0-3) + * @NL80211_ATTR_KEY_CIPHER: key cipher suite (u32, as defined by IEEE 802.11 + * section 7.3.2.25.1, e.g. 0x000FAC04) + * @NL80211_ATTR_KEY_SEQ: transmit key sequence number (IV/PN) for TKIP and + * CCMP keys, each six bytes in little endian + * @NL80211_ATTR_KEY_DEFAULT: Flag attribute indicating the key is default key + * @NL80211_ATTR_KEY_DEFAULT_MGMT: Flag attribute indicating the key is the + * default management key + * @NL80211_ATTR_CIPHER_SUITES_PAIRWISE: For crypto settings for connect or + * other commands, indicates which pairwise cipher suites are used + * @NL80211_ATTR_CIPHER_SUITE_GROUP: For crypto settings for connect or + * other commands, indicates which group cipher suite is used + * + * @NL80211_ATTR_BEACON_INTERVAL: beacon interval in TU + * @NL80211_ATTR_DTIM_PERIOD: DTIM period for beaconing + * @NL80211_ATTR_BEACON_HEAD: portion of the beacon before the TIM IE + * @NL80211_ATTR_BEACON_TAIL: portion of the beacon after the TIM IE + * + * @NL80211_ATTR_STA_AID: Association ID for the station (u16) + * @NL80211_ATTR_STA_FLAGS: flags, nested element with NLA_FLAG attributes of + * &enum nl80211_sta_flags (deprecated, use %NL80211_ATTR_STA_FLAGS2) + * @NL80211_ATTR_STA_LISTEN_INTERVAL: listen interval as defined by + * IEEE 802.11 7.3.1.6 (u16). + * @NL80211_ATTR_STA_SUPPORTED_RATES: supported rates, array of supported + * rates as defined by IEEE 802.11 7.3.2.2 but without the length + * restriction (at most %NL80211_MAX_SUPP_RATES). + * @NL80211_ATTR_STA_VLAN: interface index of VLAN interface to move station + * to, or the AP interface the station was originally added to to. + * @NL80211_ATTR_STA_INFO: information about a station, part of station info + * given for %NL80211_CMD_GET_STATION, nested attribute containing + * info as possible, see &enum nl80211_sta_info. + * + * @NL80211_ATTR_WIPHY_BANDS: Information about an operating bands, + * consisting of a nested array. + * + * @NL80211_ATTR_MESH_ID: mesh id (1-32 bytes). + * @NL80211_ATTR_STA_PLINK_ACTION: action to perform on the mesh peer link + * (see &enum nl80211_plink_action). + * @NL80211_ATTR_MPATH_NEXT_HOP: MAC address of the next hop for a mesh path. + * @NL80211_ATTR_MPATH_INFO: information about a mesh_path, part of mesh path + * info given for %NL80211_CMD_GET_MPATH, nested attribute described at + * &enum nl80211_mpath_info. + * + * @NL80211_ATTR_MNTR_FLAGS: flags, nested element with NLA_FLAG attributes of + * &enum nl80211_mntr_flags. + * + * @NL80211_ATTR_REG_ALPHA2: an ISO-3166-alpha2 country code for which the + * current regulatory domain should be set to or is already set to. + * For example, 'CR', for Costa Rica. This attribute is used by the kernel + * to query the CRDA to retrieve one regulatory domain. This attribute can + * also be used by userspace to query the kernel for the currently set + * regulatory domain. We chose an alpha2 as that is also used by the + * IEEE-802.11 country information element to identify a country. + * Users can also simply ask the wireless core to set regulatory domain + * to a specific alpha2. + * @NL80211_ATTR_REG_RULES: a nested array of regulatory domain regulatory + * rules. + * + * @NL80211_ATTR_BSS_CTS_PROT: whether CTS protection is enabled (u8, 0 or 1) + * @NL80211_ATTR_BSS_SHORT_PREAMBLE: whether short preamble is enabled + * (u8, 0 or 1) + * @NL80211_ATTR_BSS_SHORT_SLOT_TIME: whether short slot time enabled + * (u8, 0 or 1) + * @NL80211_ATTR_BSS_BASIC_RATES: basic rates, array of basic + * rates in format defined by IEEE 802.11 7.3.2.2 but without the length + * restriction (at most %NL80211_MAX_SUPP_RATES). + * + * @NL80211_ATTR_HT_CAPABILITY: HT Capability information element (from + * association request when used with NL80211_CMD_NEW_STATION) + * + * @NL80211_ATTR_SUPPORTED_IFTYPES: nested attribute containing all + * supported interface types, each a flag attribute with the number + * of the interface mode. + * + * @NL80211_ATTR_MGMT_SUBTYPE: Management frame subtype for + * %NL80211_CMD_SET_MGMT_EXTRA_IE. + * + * @NL80211_ATTR_IE: Information element(s) data (used, e.g., with + * %NL80211_CMD_SET_MGMT_EXTRA_IE). + * + * @NL80211_ATTR_MAX_NUM_SCAN_SSIDS: number of SSIDs you can scan with + * a single scan request, a wiphy attribute. + * @NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS: number of SSIDs you can + * scan with a single scheduled scan request, a wiphy attribute. + * @NL80211_ATTR_MAX_SCAN_IE_LEN: maximum length of information elements + * that can be added to a scan request + * @NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN: maximum length of information + * elements that can be added to a scheduled scan request + * @NL80211_ATTR_MAX_MATCH_SETS: maximum number of sets that can be + * used with @NL80211_ATTR_SCHED_SCAN_MATCH, a wiphy attribute. + * + * @NL80211_ATTR_SCAN_FREQUENCIES: nested attribute with frequencies (in MHz) + * @NL80211_ATTR_SCAN_SSIDS: nested attribute with SSIDs, leave out for passive + * scanning and include a zero-length SSID (wildcard) for wildcard scan + * @NL80211_ATTR_BSS: scan result BSS + * + * @NL80211_ATTR_REG_INITIATOR: indicates who requested the regulatory domain + * currently in effect. This could be any of the %NL80211_REGDOM_SET_BY_* + * @NL80211_ATTR_REG_TYPE: indicates the type of the regulatory domain currently + * set. This can be one of the nl80211_reg_type (%NL80211_REGDOM_TYPE_*) + * + * @NL80211_ATTR_SUPPORTED_COMMANDS: wiphy attribute that specifies + * an array of command numbers (i.e. a mapping index to command number) + * that the driver for the given wiphy supports. + * + * @NL80211_ATTR_FRAME: frame data (binary attribute), including frame header + * and body, but not FCS; used, e.g., with NL80211_CMD_AUTHENTICATE and + * NL80211_CMD_ASSOCIATE events + * @NL80211_ATTR_SSID: SSID (binary attribute, 0..32 octets) + * @NL80211_ATTR_AUTH_TYPE: AuthenticationType, see &enum nl80211_auth_type, + * represented as a u32 + * @NL80211_ATTR_REASON_CODE: ReasonCode for %NL80211_CMD_DEAUTHENTICATE and + * %NL80211_CMD_DISASSOCIATE, u16 + * + * @NL80211_ATTR_KEY_TYPE: Key Type, see &enum nl80211_key_type, represented as + * a u32 + * + * @NL80211_ATTR_FREQ_BEFORE: A channel which has suffered a regulatory change + * due to considerations from a beacon hint. This attribute reflects + * the state of the channel _before_ the beacon hint processing. This + * attributes consists of a nested attribute containing + * NL80211_FREQUENCY_ATTR_* + * @NL80211_ATTR_FREQ_AFTER: A channel which has suffered a regulatory change + * due to considerations from a beacon hint. This attribute reflects + * the state of the channel _after_ the beacon hint processing. This + * attributes consists of a nested attribute containing + * NL80211_FREQUENCY_ATTR_* + * + * @NL80211_ATTR_CIPHER_SUITES: a set of u32 values indicating the supported + * cipher suites + * + * @NL80211_ATTR_FREQ_FIXED: a flag indicating the IBSS should not try to look + * for other networks on different channels + * + * @NL80211_ATTR_TIMED_OUT: a flag indicating than an operation timed out; this + * is used, e.g., with %NL80211_CMD_AUTHENTICATE event + * + * @NL80211_ATTR_USE_MFP: Whether management frame protection (IEEE 802.11w) is + * used for the association (&enum nl80211_mfp, represented as a u32); + * this attribute can be used + * with %NL80211_CMD_ASSOCIATE and %NL80211_CMD_CONNECT requests + * + * @NL80211_ATTR_STA_FLAGS2: Attribute containing a + * &struct nl80211_sta_flag_update. + * + * @NL80211_ATTR_CONTROL_PORT: A flag indicating whether user space controls + * IEEE 802.1X port, i.e., sets/clears %NL80211_STA_FLAG_AUTHORIZED, in + * station mode. If the flag is included in %NL80211_CMD_ASSOCIATE + * request, the driver will assume that the port is unauthorized until + * authorized by user space. Otherwise, port is marked authorized by + * default in station mode. + * @NL80211_ATTR_CONTROL_PORT_ETHERTYPE: A 16-bit value indicating the + * ethertype that will be used for key negotiation. It can be + * specified with the associate and connect commands. If it is not + * specified, the value defaults to 0x888E (PAE, 802.1X). This + * attribute is also used as a flag in the wiphy information to + * indicate that protocols other than PAE are supported. + * @NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT: When included along with + * %NL80211_ATTR_CONTROL_PORT_ETHERTYPE, indicates that the custom + * ethertype frames used for key negotiation must not be encrypted. + * + * @NL80211_ATTR_TESTDATA: Testmode data blob, passed through to the driver. + * We recommend using nested, driver-specific attributes within this. + * + * @NL80211_ATTR_DISCONNECTED_BY_AP: A flag indicating that the DISCONNECT + * event was due to the AP disconnecting the station, and not due to + * a local disconnect request. + * @NL80211_ATTR_STATUS_CODE: StatusCode for the %NL80211_CMD_CONNECT + * event (u16) + * @NL80211_ATTR_PRIVACY: Flag attribute, used with connect(), indicating + * that protected APs should be used. This is also used with NEW_BEACON to + * indicate that the BSS is to use protection. + * + * @NL80211_ATTR_CIPHERS_PAIRWISE: Used with CONNECT, ASSOCIATE, and NEW_BEACON + * to indicate which unicast key ciphers will be used with the connection + * (an array of u32). + * @NL80211_ATTR_CIPHER_GROUP: Used with CONNECT, ASSOCIATE, and NEW_BEACON to + * indicate which group key cipher will be used with the connection (a + * u32). + * @NL80211_ATTR_WPA_VERSIONS: Used with CONNECT, ASSOCIATE, and NEW_BEACON to + * indicate which WPA version(s) the AP we want to associate with is using + * (a u32 with flags from &enum nl80211_wpa_versions). + * @NL80211_ATTR_AKM_SUITES: Used with CONNECT, ASSOCIATE, and NEW_BEACON to + * indicate which key management algorithm(s) to use (an array of u32). + * + * @NL80211_ATTR_REQ_IE: (Re)association request information elements as + * sent out by the card, for ROAM and successful CONNECT events. + * @NL80211_ATTR_RESP_IE: (Re)association response information elements as + * sent by peer, for ROAM and successful CONNECT events. + * + * @NL80211_ATTR_PREV_BSSID: previous BSSID, to be used by in ASSOCIATE + * commands to specify using a reassociate frame + * + * @NL80211_ATTR_KEY: key information in a nested attribute with + * %NL80211_KEY_* sub-attributes + * @NL80211_ATTR_KEYS: array of keys for static WEP keys for connect() + * and join_ibss(), key information is in a nested attribute each + * with %NL80211_KEY_* sub-attributes + * + * @NL80211_ATTR_PID: Process ID of a network namespace. + * + * @NL80211_ATTR_GENERATION: Used to indicate consistent snapshots for + * dumps. This number increases whenever the object list being + * dumped changes, and as such userspace can verify that it has + * obtained a complete and consistent snapshot by verifying that + * all dump messages contain the same generation number. If it + * changed then the list changed and the dump should be repeated + * completely from scratch. + * + * @NL80211_ATTR_4ADDR: Use 4-address frames on a virtual interface + * + * @NL80211_ATTR_SURVEY_INFO: survey information about a channel, part of + * the survey response for %NL80211_CMD_GET_SURVEY, nested attribute + * containing info as possible, see &enum survey_info. + * + * @NL80211_ATTR_PMKID: PMK material for PMKSA caching. + * @NL80211_ATTR_MAX_NUM_PMKIDS: maximum number of PMKIDs a firmware can + * cache, a wiphy attribute. + * + * @NL80211_ATTR_DURATION: Duration of an operation in milliseconds, u32. + * @NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION: Device attribute that + * specifies the maximum duration that can be requested with the + * remain-on-channel operation, in milliseconds, u32. + * + * @NL80211_ATTR_COOKIE: Generic 64-bit cookie to identify objects. + * + * @NL80211_ATTR_TX_RATES: Nested set of attributes + * (enum nl80211_tx_rate_attributes) describing TX rates per band. The + * enum nl80211_band value is used as the index (nla_type() of the nested + * data. If a band is not included, it will be configured to allow all + * rates based on negotiated supported rates information. This attribute + * is used with %NL80211_CMD_SET_TX_BITRATE_MASK. + * + * @NL80211_ATTR_FRAME_MATCH: A binary attribute which typically must contain + * at least one byte, currently used with @NL80211_CMD_REGISTER_FRAME. + * @NL80211_ATTR_FRAME_TYPE: A u16 indicating the frame type/subtype for the + * @NL80211_CMD_REGISTER_FRAME command. + * @NL80211_ATTR_TX_FRAME_TYPES: wiphy capability attribute, which is a + * nested attribute of %NL80211_ATTR_FRAME_TYPE attributes, containing + * information about which frame types can be transmitted with + * %NL80211_CMD_FRAME. + * @NL80211_ATTR_RX_FRAME_TYPES: wiphy capability attribute, which is a + * nested attribute of %NL80211_ATTR_FRAME_TYPE attributes, containing + * information about which frame types can be registered for RX. + * + * @NL80211_ATTR_ACK: Flag attribute indicating that the frame was + * acknowledged by the recipient. + * + * @NL80211_ATTR_PS_STATE: powersave state, using &enum nl80211_ps_state values. + * + * @NL80211_ATTR_CQM: connection quality monitor configuration in a + * nested attribute with %NL80211_ATTR_CQM_* sub-attributes. + * + * @NL80211_ATTR_LOCAL_STATE_CHANGE: Flag attribute to indicate that a command + * is requesting a local authentication/association state change without + * invoking actual management frame exchange. This can be used with + * NL80211_CMD_AUTHENTICATE, NL80211_CMD_DEAUTHENTICATE, + * NL80211_CMD_DISASSOCIATE. + * + * @NL80211_ATTR_AP_ISOLATE: (AP mode) Do not forward traffic between stations + * connected to this BSS. + * + * @NL80211_ATTR_WIPHY_TX_POWER_SETTING: Transmit power setting type. See + * &enum nl80211_tx_power_setting for possible values. + * @NL80211_ATTR_WIPHY_TX_POWER_LEVEL: Transmit power level in signed mBm units. + * This is used in association with @NL80211_ATTR_WIPHY_TX_POWER_SETTING + * for non-automatic settings. + * + * @NL80211_ATTR_SUPPORT_IBSS_RSN: The device supports IBSS RSN, which mostly + * means support for per-station GTKs. + * + * @NL80211_ATTR_WIPHY_ANTENNA_TX: Bitmap of allowed antennas for transmitting. + * This can be used to mask out antennas which are not attached or should + * not be used for transmitting. If an antenna is not selected in this + * bitmap the hardware is not allowed to transmit on this antenna. + * + * Each bit represents one antenna, starting with antenna 1 at the first + * bit. Depending on which antennas are selected in the bitmap, 802.11n + * drivers can derive which chainmasks to use (if all antennas belonging to + * a particular chain are disabled this chain should be disabled) and if + * a chain has diversity antennas wether diversity should be used or not. + * HT capabilities (STBC, TX Beamforming, Antenna selection) can be + * derived from the available chains after applying the antenna mask. + * Non-802.11n drivers can derive wether to use diversity or not. + * Drivers may reject configurations or RX/TX mask combinations they cannot + * support by returning -ERRINVAL. + * + * @NL80211_ATTR_WIPHY_ANTENNA_RX: Bitmap of allowed antennas for receiving. + * This can be used to mask out antennas which are not attached or should + * not be used for receiving. If an antenna is not selected in this bitmap + * the hardware should not be configured to receive on this antenna. + * For a more detailed description see @NL80211_ATTR_WIPHY_ANTENNA_TX. + * + * @NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX: Bitmap of antennas which are available + * for configuration as TX antennas via the above parameters. + * + * @NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX: Bitmap of antennas which are available + * for configuration as RX antennas via the above parameters. + * + * @NL80211_ATTR_MCAST_RATE: Multicast tx rate (in 100 kbps) for IBSS + * + * @NL80211_ATTR_OFFCHANNEL_TX_OK: For management frame TX, the frame may be + * transmitted on another channel when the channel given doesn't match + * the current channel. If the current channel doesn't match and this + * flag isn't set, the frame will be rejected. This is also used as an + * nl80211 capability flag. + * + * @NL80211_ATTR_BSS_HT_OPMODE: HT operation mode (u16) + * + * @NL80211_ATTR_KEY_DEFAULT_TYPES: A nested attribute containing flags + * attributes, specifying what a key should be set as default as. + * See &enum nl80211_key_default_types. + * + * @NL80211_ATTR_MESH_SETUP: Optional mesh setup parameters. These cannot be + * changed once the mesh is active. + * @NL80211_ATTR_MESH_CONFIG: Mesh configuration parameters, a nested attribute + * containing attributes from &enum nl80211_meshconf_params. + * @NL80211_ATTR_SUPPORT_MESH_AUTH: Currently, this means the underlying driver + * allows auth frames in a mesh to be passed to userspace for processing via + * the @NL80211_MESH_SETUP_USERSPACE_AUTH flag. + * @NL80211_ATTR_STA_PLINK_STATE: The state of a mesh peer link as defined in + * &enum nl80211_plink_state. Used when userspace is driving the peer link + * management state machine. @NL80211_MESH_SETUP_USERSPACE_AMPE or + * @NL80211_MESH_SETUP_USERSPACE_MPM must be enabled. + * + * @NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED: indicates, as part of the wiphy + * capabilities, the supported WoWLAN triggers + * @NL80211_ATTR_WOWLAN_TRIGGERS: used by %NL80211_CMD_SET_WOWLAN to + * indicate which WoW triggers should be enabled. This is also + * used by %NL80211_CMD_GET_WOWLAN to get the currently enabled WoWLAN + * triggers. + * + * @NL80211_ATTR_SCHED_SCAN_INTERVAL: Interval between scheduled scan + * cycles, in msecs. + * + * @NL80211_ATTR_SCHED_SCAN_MATCH: Nested attribute with one or more + * sets of attributes to match during scheduled scans. Only BSSs + * that match any of the sets will be reported. These are + * pass-thru filter rules. + * For a match to succeed, the BSS must match all attributes of a + * set. Since not every hardware supports matching all types of + * attributes, there is no guarantee that the reported BSSs are + * fully complying with the match sets and userspace needs to be + * able to ignore them by itself. + * Thus, the implementation is somewhat hardware-dependent, but + * this is only an optimization and the userspace application + * needs to handle all the non-filtered results anyway. + * If the match attributes don't make sense when combined with + * the values passed in @NL80211_ATTR_SCAN_SSIDS (eg. if an SSID + * is included in the probe request, but the match attributes + * will never let it go through), -ERRINVAL may be returned. + * If ommited, no filtering is done. + * + * @NL80211_ATTR_INTERFACE_COMBINATIONS: Nested attribute listing the supported + * interface combinations. In each nested item, it contains attributes + * defined in &enum nl80211_if_combination_attrs. + * @NL80211_ATTR_SOFTWARE_IFTYPES: Nested attribute (just like + * %NL80211_ATTR_SUPPORTED_IFTYPES) containing the interface types that + * are managed in software: interfaces of these types aren't subject to + * any restrictions in their number or combinations. + * + * @NL80211_ATTR_REKEY_DATA: nested attribute containing the information + * necessary for GTK rekeying in the device, see &enum nl80211_rekey_data. + * + * @NL80211_ATTR_SCAN_SUPP_RATES: rates per to be advertised as supported in scan, + * nested array attribute containing an entry for each band, with the entry + * being a list of supported rates as defined by IEEE 802.11 7.3.2.2 but + * without the length restriction (at most %NL80211_MAX_SUPP_RATES). + * + * @NL80211_ATTR_HIDDEN_SSID: indicates whether SSID is to be hidden from Beacon + * and Probe Response (when response to wildcard Probe Request); see + * &enum nl80211_hidden_ssid, represented as a u32 + * + * @NL80211_ATTR_IE_PROBE_RESP: Information element(s) for Probe Response frame. + * This is used with %NL80211_CMD_NEW_BEACON and %NL80211_CMD_SET_BEACON to + * provide extra IEs (e.g., WPS/P2P IE) into Probe Response frames when the + * driver (or firmware) replies to Probe Request frames. + * @NL80211_ATTR_IE_ASSOC_RESP: Information element(s) for (Re)Association + * Response frames. This is used with %NL80211_CMD_NEW_BEACON and + * %NL80211_CMD_SET_BEACON to provide extra IEs (e.g., WPS/P2P IE) into + * (Re)Association Response frames when the driver (or firmware) replies to + * (Re)Association Request frames. + * + * @NL80211_ATTR_STA_WME: Nested attribute containing the wme configuration + * of the station, see &enum nl80211_sta_wme_attr. + * @NL80211_ATTR_SUPPORT_AP_UAPSD: the device supports uapsd when working + * as AP. + * + * @NL80211_ATTR_ROAM_SUPPORT: Indicates whether the firmware is capable of + * roaming to another AP in the same ESS if the signal lever is low. + * + * @NL80211_ATTR_PMKSA_CANDIDATE: Nested attribute containing the PMKSA caching + * candidate information, see &enum nl80211_pmksa_candidate_attr. + * + * @NL80211_ATTR_TX_NO_CCK_RATE: Indicates whether to use CCK rate or not + * for management frames transmission. In order to avoid p2p probe/action + * frames are being transmitted at CCK rate in 2GHz band, the user space + * applications use this attribute. + * This attribute is used with %NL80211_CMD_TRIGGER_SCAN and + * %NL80211_CMD_FRAME commands. + * + * @NL80211_ATTR_TDLS_ACTION: Low level TDLS action code (e.g. link setup + * request, link setup confirm, link teardown, etc.). Values are + * described in the TDLS (802.11z) specification. + * @NL80211_ATTR_TDLS_DIALOG_TOKEN: Non-zero token for uniquely identifying a + * TDLS conversation between two devices. + * @NL80211_ATTR_TDLS_OPERATION: High level TDLS operation; see + * &enum nl80211_tdls_operation, represented as a u8. + * @NL80211_ATTR_TDLS_SUPPORT: A flag indicating the device can operate + * as a TDLS peer sta. + * @NL80211_ATTR_TDLS_EXTERNAL_SETUP: The TDLS discovery/setup and teardown + * procedures should be performed by sending TDLS packets via + * %NL80211_CMD_TDLS_MGMT. Otherwise %NL80211_CMD_TDLS_OPER should be + * used for asking the driver to perform a TDLS operation. + * + * @NL80211_ATTR_DEVICE_AP_SME: This u32 attribute may be listed for devices + * that have AP support to indicate that they have the AP SME integrated + * with support for the features listed in this attribute, see + * &enum nl80211_ap_sme_features. + * + * @NL80211_ATTR_DONT_WAIT_FOR_ACK: Used with %NL80211_CMD_FRAME, this tells + * the driver to not wait for an acknowledgement. Note that due to this, + * it will also not give a status callback nor return a cookie. This is + * mostly useful for probe responses to save airtime. + * + * @NL80211_ATTR_FEATURE_FLAGS: This u32 attribute contains flags from + * &enum nl80211_feature_flags and is advertised in wiphy information. + * @NL80211_ATTR_PROBE_RESP_OFFLOAD: Indicates that the HW responds to probe + * requests while operating in AP-mode. + * This attribute holds a bitmap of the supported protocols for + * offloading (see &enum nl80211_probe_resp_offload_support_attr). + * + * @NL80211_ATTR_PROBE_RESP: Probe Response template data. Contains the entire + * probe-response frame. The DA field in the 802.11 header is zero-ed out, + * to be filled by the FW. + * @NL80211_ATTR_DISABLE_HT: Force HT capable interfaces to disable + * this feature. Currently, only supported in mac80211 drivers. + * @NL80211_ATTR_HT_CAPABILITY_MASK: Specify which bits of the + * ATTR_HT_CAPABILITY to which attention should be paid. + * Currently, only mac80211 NICs support this feature. + * The values that may be configured are: + * MCS rates, MAX-AMSDU, HT-20-40 and HT_CAP_SGI_40 + * AMPDU density and AMPDU factor. + * All values are treated as suggestions and may be ignored + * by the driver as required. The actual values may be seen in + * the station debugfs ht_caps file. + * + * @NL80211_ATTR_DFS_REGION: region for regulatory rules which this country + * abides to when initiating radiation on DFS channels. A country maps + * to one DFS region. + * + * @NL80211_ATTR_NOACK_MAP: This u16 bitmap contains the No Ack Policy of + * up to 16 TIDs. + * + * @NL80211_ATTR_INACTIVITY_TIMEOUT: timeout value in seconds, this can be + * used by the drivers which has MLME in firmware and does not have support + * to report per station tx/rx activity to free up the staion entry from + * the list. This needs to be used when the driver advertises the + * capability to timeout the stations. + * + * @NL80211_ATTR_RX_SIGNAL_DBM: signal strength in dBm (as a 32-bit int); + * this attribute is (depending on the driver capabilities) added to + * received frames indicated with %NL80211_CMD_FRAME. + * + * @NL80211_ATTR_BG_SCAN_PERIOD: Background scan period in seconds + * or 0 to disable background scan. + * + * @NL80211_ATTR_USER_REG_HINT_TYPE: type of regulatory hint passed from + * userspace. If unset it is assumed the hint comes directly from + * a user. If set code could specify exactly what type of source + * was used to provide the hint. For the different types of + * allowed user regulatory hints see nl80211_user_reg_hint_type. + * + * @NL80211_ATTR_CONN_FAILED_REASON: The reason for which AP has rejected + * the connection request from a station. nl80211_connect_failed_reason + * enum has different reasons of connection failure. + * + * @NL80211_ATTR_SAE_DATA: SAE elements in Authentication frames. This starts + * with the Authentication transaction sequence number field. + * + * @NL80211_ATTR_VHT_CAPABILITY: VHT Capability information element (from + * association request when used with NL80211_CMD_NEW_STATION) + * + * @NL80211_ATTR_SCAN_FLAGS: scan request control flags (u32) + * + * @NL80211_ATTR_P2P_CTWINDOW: P2P GO Client Traffic Window (u8), used with + * the START_AP and SET_BSS commands + * @NL80211_ATTR_P2P_OPPPS: P2P GO opportunistic PS (u8), used with the + * START_AP and SET_BSS commands. This can have the values 0 or 1; + * if not given in START_AP 0 is assumed, if not given in SET_BSS + * no change is made. + * + * @NL80211_ATTR_LOCAL_MESH_POWER_MODE: local mesh STA link-specific power mode + * defined in &enum nl80211_mesh_power_mode. + * + * @NL80211_ATTR_ACL_POLICY: ACL policy, see &enum nl80211_acl_policy, + * carried in a u32 attribute + * + * @NL80211_ATTR_MAC_ADDRS: Array of nested MAC addresses, used for + * MAC ACL. + * + * @NL80211_ATTR_MAC_ACL_MAX: u32 attribute to advertise the maximum + * number of MAC addresses that a device can support for MAC + * ACL. + * + * @NL80211_ATTR_RADAR_EVENT: Type of radar event for notification to userspace, + * contains a value of enum nl80211_radar_event (u32). + * + * @NL80211_ATTR_EXT_CAPA: 802.11 extended capabilities that the kernel driver + * has and handles. The format is the same as the IE contents. See + * 802.11-2012 8.4.2.29 for more information. + * @NL80211_ATTR_EXT_CAPA_MASK: Extended capabilities that the kernel driver + * has set in the %NL80211_ATTR_EXT_CAPA value, for multibit fields. + * + * @NL80211_ATTR_STA_CAPABILITY: Station capabilities (u16) are advertised to + * the driver, e.g., to enable TDLS power save (PU-APSD). + * + * @NL80211_ATTR_STA_EXT_CAPABILITY: Station extended capabilities are + * advertised to the driver, e.g., to enable TDLS off channel operations + * and PU-APSD. + * + * @NL80211_ATTR_PROTOCOL_FEATURES: global nl80211 feature flags, see + * &enum nl80211_protocol_features, the attribute is a u32. + * + * @NL80211_ATTR_SPLIT_WIPHY_DUMP: flag attribute, userspace supports + * receiving the data for a single wiphy split across multiple + * messages, given with wiphy dump message + * + * @NL80211_ATTR_MDID: Mobility Domain Identifier + * + * @NL80211_ATTR_IE_RIC: Resource Information Container Information + * Element + * + * @NL80211_ATTR_CRIT_PROT_ID: critical protocol identifier requiring increased + * reliability, see &enum nl80211_crit_proto_id (u16). + * @NL80211_ATTR_MAX_CRIT_PROT_DURATION: duration in milliseconds in which + * the connection should have increased reliability (u16). + * + * @NL80211_ATTR_PEER_AID: Association ID for the peer TDLS station (u16). + * This is similar to @NL80211_ATTR_STA_AID but with a difference of being + * allowed to be used with the first @NL80211_CMD_SET_STATION command to + * update a TDLS peer STA entry. + * + * @NL80211_ATTR_COALESCE_RULE: Coalesce rule information. + * + * @NL80211_ATTR_CH_SWITCH_COUNT: u32 attribute specifying the number of TBTT's + * until the channel switch event. + * @NL80211_ATTR_CH_SWITCH_BLOCK_TX: flag attribute specifying that transmission + * must be blocked on the current channel (before the channel switch + * operation). + * @NL80211_ATTR_CSA_IES: Nested set of attributes containing the IE information + * for the time while performing a channel switch. + * @NL80211_ATTR_CSA_C_OFF_BEACON: An array of offsets (u16) to the channel + * switch counters in the beacons tail (%NL80211_ATTR_BEACON_TAIL). + * @NL80211_ATTR_CSA_C_OFF_PRESP: An array of offsets (u16) to the channel + * switch counters in the probe response (%NL80211_ATTR_PROBE_RESP). + * + * @NL80211_ATTR_RXMGMT_FLAGS: flags for nl80211_send_mgmt(), u32. + * As specified in the &enum nl80211_rxmgmt_flags. + * + * @NL80211_ATTR_STA_SUPPORTED_CHANNELS: array of supported channels. + * + * @NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES: array of supported + * supported operating classes. + * + * @NL80211_ATTR_HANDLE_DFS: A flag indicating whether user space + * controls DFS operation in IBSS mode. If the flag is included in + * %NL80211_CMD_JOIN_IBSS request, the driver will allow use of DFS + * channels and reports radar events to userspace. Userspace is required + * to react to radar events, e.g. initiate a channel switch or leave the + * IBSS network. + * + * @NL80211_ATTR_SUPPORT_5_MHZ: A flag indicating that the device supports + * 5 MHz channel bandwidth. + * @NL80211_ATTR_SUPPORT_10_MHZ: A flag indicating that the device supports + * 10 MHz channel bandwidth. + * + * @NL80211_ATTR_OPMODE_NOTIF: Operating mode field from Operating Mode + * Notification Element based on association request when used with + * %NL80211_CMD_NEW_STATION; u8 attribute. + * + * @NL80211_ATTR_VENDOR_ID: The vendor ID, either a 24-bit OUI or, if + * %NL80211_VENDOR_ID_IS_LINUX is set, a special Linux ID (not used yet) + * @NL80211_ATTR_VENDOR_SUBCMD: vendor sub-command + * @NL80211_ATTR_VENDOR_DATA: data for the vendor command, if any; this + * attribute is also used for vendor command feature advertisement + * @NL80211_ATTR_VENDOR_EVENTS: used for event list advertising in the wiphy + * info, containing a nested array of possible events + * + * @NL80211_ATTR_QOS_MAP: IP DSCP mapping for Interworking QoS mapping. This + * data is in the format defined for the payload of the QoS Map Set element + * in IEEE Std 802.11-2012, 8.4.2.97. + * + * @NL80211_ATTR_MAC_HINT: MAC address recommendation as initial BSS + * @NL80211_ATTR_WIPHY_FREQ_HINT: frequency of the recommended initial BSS + * + * @NL80211_ATTR_MAX_AP_ASSOC_STA: Device attribute that indicates how many + * associated stations are supported in AP mode (including P2P GO); u32. + * Since drivers may not have a fixed limit on the maximum number (e.g., + * other concurrent operations may affect this), drivers are allowed to + * advertise values that cannot always be met. In such cases, an attempt + * to add a new station entry with @NL80211_CMD_NEW_STATION may fail. + * + * @NL80211_ATTR_CSA_C_OFFSETS_TX: An array of csa counter offsets (u16) which + * should be updated when the frame is transmitted. + * @NL80211_ATTR_MAX_CSA_COUNTERS: U8 attribute used to advertise the maximum + * supported number of csa counters. + * + * @NL80211_ATTR_TDLS_PEER_CAPABILITY: flags for TDLS peer capabilities, u32. + * As specified in the &enum nl80211_tdls_peer_capability. + * + * @NL80211_ATTR_SOCKET_OWNER: Flag attribute, if set during interface + * creation then the new interface will be owned by the netlink socket + * that created it and will be destroyed when the socket is closed. + * If set during scheduled scan start then the new scan req will be + * owned by the netlink socket that created it and the scheduled scan will + * be stopped when the socket is closed. + * If set during configuration of regulatory indoor operation then the + * regulatory indoor configuration would be owned by the netlink socket + * that configured the indoor setting, and the indoor operation would be + * cleared when the socket is closed. + * + * @NL80211_ATTR_TDLS_INITIATOR: flag attribute indicating the current end is + * the TDLS link initiator. + * + * @NL80211_ATTR_USE_RRM: flag for indicating whether the current connection + * shall support Radio Resource Measurements (11k). This attribute can be + * used with %NL80211_CMD_ASSOCIATE and %NL80211_CMD_CONNECT requests. + * User space applications are expected to use this flag only if the + * underlying device supports these minimal RRM features: + * %NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES, + * %NL80211_FEATURE_QUIET, + * If this flag is used, driver must add the Power Capabilities IE to the + * association request. In addition, it must also set the RRM capability + * flag in the association request's Capability Info field. + * + * @NL80211_ATTR_WIPHY_DYN_ACK: flag attribute used to enable ACK timeout + * estimation algorithm (dynack). In order to activate dynack + * %NL80211_FEATURE_ACKTO_ESTIMATION feature flag must be set by lower + * drivers to indicate dynack capability. Dynack is automatically disabled + * setting valid value for coverage class. + * + * @NL80211_ATTR_TSID: a TSID value (u8 attribute) + * @NL80211_ATTR_USER_PRIO: user priority value (u8 attribute) + * @NL80211_ATTR_ADMITTED_TIME: admitted time in units of 32 microseconds + * (per second) (u16 attribute) + * + * @NL80211_ATTR_SMPS_MODE: SMPS mode to use (ap mode). see + * &enum nl80211_smps_mode. + * + * @NL80211_ATTR_OPER_CLASS: operating class + * + * @NL80211_ATTR_MAC_MASK: MAC address mask + * + * @NL80211_ATTR_WIPHY_SELF_MANAGED_REG: flag attribute indicating this device + * is self-managing its regulatory information and any regulatory domain + * obtained from it is coming from the device's wiphy and not the global + * cfg80211 regdomain. + * + * @NL80211_ATTR_EXT_FEATURES: extended feature flags contained in a byte + * array. The feature flags are identified by their bit index (see &enum + * nl80211_ext_feature_index). The bit index is ordered starting at the + * least-significant bit of the first byte in the array, ie. bit index 0 + * is located at bit 0 of byte 0. bit index 25 would be located at bit 1 + * of byte 3 (u8 array). + * + * @NL80211_ATTR_SURVEY_RADIO_STATS: Request overall radio statistics to be + * returned along with other survey data. If set, @NL80211_CMD_GET_SURVEY + * may return a survey entry without a channel indicating global radio + * statistics (only some values are valid and make sense.) + * For devices that don't return such an entry even then, the information + * should be contained in the result as the sum of the respective counters + * over all channels. + * + * @NL80211_ATTR_SCHED_SCAN_DELAY: delay before a scheduled scan (or a + * WoWLAN net-detect scan) is started, u32 in seconds. + + * @NL80211_ATTR_REG_INDOOR: flag attribute, if set indicates that the device + * is operating in an indoor environment. + * + * @NUM_NL80211_ATTR: total number of nl80211_attrs available + * @NL80211_ATTR_MAX: highest attribute number currently defined + * @__NL80211_ATTR_AFTER_LAST: internal use + */ +enum nl80211_attrs { +/* don't change the order or add anything between, this is ABI! */ + NL80211_ATTR_UNSPEC, + + NL80211_ATTR_WIPHY, + NL80211_ATTR_WIPHY_NAME, + + NL80211_ATTR_IFINDEX, + NL80211_ATTR_IFNAME, + NL80211_ATTR_IFTYPE, + + NL80211_ATTR_MAC, + + NL80211_ATTR_KEY_DATA, + NL80211_ATTR_KEY_IDX, + NL80211_ATTR_KEY_CIPHER, + NL80211_ATTR_KEY_SEQ, + NL80211_ATTR_KEY_DEFAULT, + + NL80211_ATTR_BEACON_INTERVAL, + NL80211_ATTR_DTIM_PERIOD, + NL80211_ATTR_BEACON_HEAD, + NL80211_ATTR_BEACON_TAIL, + + NL80211_ATTR_STA_AID, + NL80211_ATTR_STA_FLAGS, + NL80211_ATTR_STA_LISTEN_INTERVAL, + NL80211_ATTR_STA_SUPPORTED_RATES, + NL80211_ATTR_STA_VLAN, + NL80211_ATTR_STA_INFO, + + NL80211_ATTR_WIPHY_BANDS, + + NL80211_ATTR_MNTR_FLAGS, + + NL80211_ATTR_MESH_ID, + NL80211_ATTR_STA_PLINK_ACTION, + NL80211_ATTR_MPATH_NEXT_HOP, + NL80211_ATTR_MPATH_INFO, + + NL80211_ATTR_BSS_CTS_PROT, + NL80211_ATTR_BSS_SHORT_PREAMBLE, + NL80211_ATTR_BSS_SHORT_SLOT_TIME, + + NL80211_ATTR_HT_CAPABILITY, + + NL80211_ATTR_SUPPORTED_IFTYPES, + + NL80211_ATTR_REG_ALPHA2, + NL80211_ATTR_REG_RULES, + + NL80211_ATTR_MESH_CONFIG, + + NL80211_ATTR_BSS_BASIC_RATES, + + NL80211_ATTR_WIPHY_TXQ_PARAMS, + NL80211_ATTR_WIPHY_FREQ, + NL80211_ATTR_WIPHY_CHANNEL_TYPE, + + NL80211_ATTR_KEY_DEFAULT_MGMT, + + NL80211_ATTR_MGMT_SUBTYPE, + NL80211_ATTR_IE, + + NL80211_ATTR_MAX_NUM_SCAN_SSIDS, + + NL80211_ATTR_SCAN_FREQUENCIES, + NL80211_ATTR_SCAN_SSIDS, + NL80211_ATTR_GENERATION, /* replaces old SCAN_GENERATION */ + NL80211_ATTR_BSS, + + NL80211_ATTR_REG_INITIATOR, + NL80211_ATTR_REG_TYPE, + + NL80211_ATTR_SUPPORTED_COMMANDS, + + NL80211_ATTR_FRAME, + NL80211_ATTR_SSID, + NL80211_ATTR_AUTH_TYPE, + NL80211_ATTR_REASON_CODE, + + NL80211_ATTR_KEY_TYPE, + + NL80211_ATTR_MAX_SCAN_IE_LEN, + NL80211_ATTR_CIPHER_SUITES, + + NL80211_ATTR_FREQ_BEFORE, + NL80211_ATTR_FREQ_AFTER, + + NL80211_ATTR_FREQ_FIXED, + + + NL80211_ATTR_WIPHY_RETRY_SHORT, + NL80211_ATTR_WIPHY_RETRY_LONG, + NL80211_ATTR_WIPHY_FRAG_THRESHOLD, + NL80211_ATTR_WIPHY_RTS_THRESHOLD, + + NL80211_ATTR_TIMED_OUT, + + NL80211_ATTR_USE_MFP, + + NL80211_ATTR_STA_FLAGS2, + + NL80211_ATTR_CONTROL_PORT, + + NL80211_ATTR_TESTDATA, + + NL80211_ATTR_PRIVACY, + + NL80211_ATTR_DISCONNECTED_BY_AP, + NL80211_ATTR_STATUS_CODE, + + NL80211_ATTR_CIPHER_SUITES_PAIRWISE, + NL80211_ATTR_CIPHER_SUITE_GROUP, + NL80211_ATTR_WPA_VERSIONS, + NL80211_ATTR_AKM_SUITES, + + NL80211_ATTR_REQ_IE, + NL80211_ATTR_RESP_IE, + + NL80211_ATTR_PREV_BSSID, + + NL80211_ATTR_KEY, + NL80211_ATTR_KEYS, + + NL80211_ATTR_PID, + + NL80211_ATTR_4ADDR, + + NL80211_ATTR_SURVEY_INFO, + + NL80211_ATTR_PMKID, + NL80211_ATTR_MAX_NUM_PMKIDS, + + NL80211_ATTR_DURATION, + + NL80211_ATTR_COOKIE, + + NL80211_ATTR_WIPHY_COVERAGE_CLASS, + + NL80211_ATTR_TX_RATES, + + NL80211_ATTR_FRAME_MATCH, + + NL80211_ATTR_ACK, + + NL80211_ATTR_PS_STATE, + + NL80211_ATTR_CQM, + + NL80211_ATTR_LOCAL_STATE_CHANGE, + + NL80211_ATTR_AP_ISOLATE, + + NL80211_ATTR_WIPHY_TX_POWER_SETTING, + NL80211_ATTR_WIPHY_TX_POWER_LEVEL, + + NL80211_ATTR_TX_FRAME_TYPES, + NL80211_ATTR_RX_FRAME_TYPES, + NL80211_ATTR_FRAME_TYPE, + + NL80211_ATTR_CONTROL_PORT_ETHERTYPE, + NL80211_ATTR_CONTROL_PORT_NO_ENCRYPT, + + NL80211_ATTR_SUPPORT_IBSS_RSN, + + NL80211_ATTR_WIPHY_ANTENNA_TX, + NL80211_ATTR_WIPHY_ANTENNA_RX, + + NL80211_ATTR_MCAST_RATE, + + NL80211_ATTR_OFFCHANNEL_TX_OK, + + NL80211_ATTR_BSS_HT_OPMODE, + + NL80211_ATTR_KEY_DEFAULT_TYPES, + + NL80211_ATTR_MAX_REMAIN_ON_CHANNEL_DURATION, + + NL80211_ATTR_MESH_SETUP, + + NL80211_ATTR_WIPHY_ANTENNA_AVAIL_TX, + NL80211_ATTR_WIPHY_ANTENNA_AVAIL_RX, + + NL80211_ATTR_SUPPORT_MESH_AUTH, + NL80211_ATTR_STA_PLINK_STATE, + + NL80211_ATTR_WOWLAN_TRIGGERS, + NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED, + + NL80211_ATTR_SCHED_SCAN_INTERVAL, + + NL80211_ATTR_INTERFACE_COMBINATIONS, + NL80211_ATTR_SOFTWARE_IFTYPES, + + NL80211_ATTR_REKEY_DATA, + + NL80211_ATTR_MAX_NUM_SCHED_SCAN_SSIDS, + NL80211_ATTR_MAX_SCHED_SCAN_IE_LEN, + + NL80211_ATTR_SCAN_SUPP_RATES, + + NL80211_ATTR_HIDDEN_SSID, + + NL80211_ATTR_IE_PROBE_RESP, + NL80211_ATTR_IE_ASSOC_RESP, + + NL80211_ATTR_STA_WME, + NL80211_ATTR_SUPPORT_AP_UAPSD, + + NL80211_ATTR_ROAM_SUPPORT, + + NL80211_ATTR_SCHED_SCAN_MATCH, + NL80211_ATTR_MAX_MATCH_SETS, + + NL80211_ATTR_PMKSA_CANDIDATE, + + NL80211_ATTR_TX_NO_CCK_RATE, + + NL80211_ATTR_TDLS_ACTION, + NL80211_ATTR_TDLS_DIALOG_TOKEN, + NL80211_ATTR_TDLS_OPERATION, + NL80211_ATTR_TDLS_SUPPORT, + NL80211_ATTR_TDLS_EXTERNAL_SETUP, + + NL80211_ATTR_DEVICE_AP_SME, + + NL80211_ATTR_DONT_WAIT_FOR_ACK, + + NL80211_ATTR_FEATURE_FLAGS, + + NL80211_ATTR_PROBE_RESP_OFFLOAD, + + NL80211_ATTR_PROBE_RESP, + + NL80211_ATTR_DFS_REGION, + + NL80211_ATTR_DISABLE_HT, + NL80211_ATTR_HT_CAPABILITY_MASK, + + NL80211_ATTR_NOACK_MAP, + + NL80211_ATTR_INACTIVITY_TIMEOUT, + + NL80211_ATTR_RX_SIGNAL_DBM, + + NL80211_ATTR_BG_SCAN_PERIOD, + + NL80211_ATTR_WDEV, + + NL80211_ATTR_USER_REG_HINT_TYPE, + + NL80211_ATTR_CONN_FAILED_REASON, + + NL80211_ATTR_SAE_DATA, + + NL80211_ATTR_VHT_CAPABILITY, + + NL80211_ATTR_SCAN_FLAGS, + + NL80211_ATTR_CHANNEL_WIDTH, + NL80211_ATTR_CENTER_FREQ1, + NL80211_ATTR_CENTER_FREQ2, + + NL80211_ATTR_P2P_CTWINDOW, + NL80211_ATTR_P2P_OPPPS, + + NL80211_ATTR_LOCAL_MESH_POWER_MODE, + + NL80211_ATTR_ACL_POLICY, + + NL80211_ATTR_MAC_ADDRS, + + NL80211_ATTR_MAC_ACL_MAX, + + NL80211_ATTR_RADAR_EVENT, + + NL80211_ATTR_EXT_CAPA, + NL80211_ATTR_EXT_CAPA_MASK, + + NL80211_ATTR_STA_CAPABILITY, + NL80211_ATTR_STA_EXT_CAPABILITY, + + NL80211_ATTR_PROTOCOL_FEATURES, + NL80211_ATTR_SPLIT_WIPHY_DUMP, + + NL80211_ATTR_DISABLE_VHT, + NL80211_ATTR_VHT_CAPABILITY_MASK, + + NL80211_ATTR_MDID, + NL80211_ATTR_IE_RIC, + + NL80211_ATTR_CRIT_PROT_ID, + NL80211_ATTR_MAX_CRIT_PROT_DURATION, + + NL80211_ATTR_PEER_AID, + + NL80211_ATTR_COALESCE_RULE, + + NL80211_ATTR_CH_SWITCH_COUNT, + NL80211_ATTR_CH_SWITCH_BLOCK_TX, + NL80211_ATTR_CSA_IES, + NL80211_ATTR_CSA_C_OFF_BEACON, + NL80211_ATTR_CSA_C_OFF_PRESP, + + NL80211_ATTR_RXMGMT_FLAGS, + + NL80211_ATTR_STA_SUPPORTED_CHANNELS, + + NL80211_ATTR_STA_SUPPORTED_OPER_CLASSES, + + NL80211_ATTR_HANDLE_DFS, + + NL80211_ATTR_SUPPORT_5_MHZ, + NL80211_ATTR_SUPPORT_10_MHZ, + + NL80211_ATTR_OPMODE_NOTIF, + + NL80211_ATTR_VENDOR_ID, + NL80211_ATTR_VENDOR_SUBCMD, + NL80211_ATTR_VENDOR_DATA, + NL80211_ATTR_VENDOR_EVENTS, + + NL80211_ATTR_QOS_MAP, + + NL80211_ATTR_MAC_HINT, + NL80211_ATTR_WIPHY_FREQ_HINT, + + NL80211_ATTR_MAX_AP_ASSOC_STA, + + NL80211_ATTR_TDLS_PEER_CAPABILITY, + + NL80211_ATTR_SOCKET_OWNER, + + NL80211_ATTR_CSA_C_OFFSETS_TX, + NL80211_ATTR_MAX_CSA_COUNTERS, + + NL80211_ATTR_TDLS_INITIATOR, + + NL80211_ATTR_USE_RRM, + + NL80211_ATTR_WIPHY_DYN_ACK, + + NL80211_ATTR_TSID, + NL80211_ATTR_USER_PRIO, + NL80211_ATTR_ADMITTED_TIME, + + NL80211_ATTR_SMPS_MODE, + + NL80211_ATTR_OPER_CLASS, + + NL80211_ATTR_MAC_MASK, + + NL80211_ATTR_WIPHY_SELF_MANAGED_REG, + + NL80211_ATTR_EXT_FEATURES, + + NL80211_ATTR_SURVEY_RADIO_STATS, + + NL80211_ATTR_NETNS_FD, + + NL80211_ATTR_SCHED_SCAN_DELAY, + + NL80211_ATTR_REG_INDOOR, + + /* add attributes here, update the policy in nl80211.c */ + + __NL80211_ATTR_AFTER_LAST, + NUM_NL80211_ATTR = __NL80211_ATTR_AFTER_LAST, + NL80211_ATTR_MAX = __NL80211_ATTR_AFTER_LAST - 1 +}; + +/* source-level API compatibility */ +#define NL80211_ATTR_SCAN_GENERATION NL80211_ATTR_GENERATION +#define NL80211_ATTR_MESH_PARAMS NL80211_ATTR_MESH_CONFIG +#define NL80211_ATTR_IFACE_SOCKET_OWNER NL80211_ATTR_SOCKET_OWNER + +/* + * Allow user space programs to use #ifdef on new attributes by defining them + * here + */ +#define NL80211_CMD_CONNECT NL80211_CMD_CONNECT +#define NL80211_ATTR_HT_CAPABILITY NL80211_ATTR_HT_CAPABILITY +#define NL80211_ATTR_BSS_BASIC_RATES NL80211_ATTR_BSS_BASIC_RATES +#define NL80211_ATTR_WIPHY_TXQ_PARAMS NL80211_ATTR_WIPHY_TXQ_PARAMS +#define NL80211_ATTR_WIPHY_FREQ NL80211_ATTR_WIPHY_FREQ +#define NL80211_ATTR_WIPHY_CHANNEL_TYPE NL80211_ATTR_WIPHY_CHANNEL_TYPE +#define NL80211_ATTR_MGMT_SUBTYPE NL80211_ATTR_MGMT_SUBTYPE +#define NL80211_ATTR_IE NL80211_ATTR_IE +#define NL80211_ATTR_REG_INITIATOR NL80211_ATTR_REG_INITIATOR +#define NL80211_ATTR_REG_TYPE NL80211_ATTR_REG_TYPE +#define NL80211_ATTR_FRAME NL80211_ATTR_FRAME +#define NL80211_ATTR_SSID NL80211_ATTR_SSID +#define NL80211_ATTR_AUTH_TYPE NL80211_ATTR_AUTH_TYPE +#define NL80211_ATTR_REASON_CODE NL80211_ATTR_REASON_CODE +#define NL80211_ATTR_CIPHER_SUITES_PAIRWISE NL80211_ATTR_CIPHER_SUITES_PAIRWISE +#define NL80211_ATTR_CIPHER_SUITE_GROUP NL80211_ATTR_CIPHER_SUITE_GROUP +#define NL80211_ATTR_WPA_VERSIONS NL80211_ATTR_WPA_VERSIONS +#define NL80211_ATTR_AKM_SUITES NL80211_ATTR_AKM_SUITES +#define NL80211_ATTR_KEY NL80211_ATTR_KEY +#define NL80211_ATTR_KEYS NL80211_ATTR_KEYS +#define NL80211_ATTR_FEATURE_FLAGS NL80211_ATTR_FEATURE_FLAGS + +#define NL80211_MAX_SUPP_RATES 32 +#define NL80211_MAX_SUPP_HT_RATES 77 +#define NL80211_MAX_SUPP_REG_RULES 64 +#define NL80211_TKIP_DATA_OFFSET_ENCR_KEY 0 +#define NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY 16 +#define NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY 24 +#define NL80211_HT_CAPABILITY_LEN 26 +#define NL80211_VHT_CAPABILITY_LEN 12 + +#define NL80211_MAX_NR_CIPHER_SUITES 5 +#define NL80211_MAX_NR_AKM_SUITES 2 + +#define NL80211_MIN_REMAIN_ON_CHANNEL_TIME 10 + +/* default RSSI threshold for scan results if none specified. */ +#define NL80211_SCAN_RSSI_THOLD_OFF -300 + +#define NL80211_CQM_TXE_MAX_INTVL 1800 + +/** + * enum nl80211_iftype - (virtual) interface types + * + * @NL80211_IFTYPE_UNSPECIFIED: unspecified type, driver decides + * @NL80211_IFTYPE_ADHOC: independent BSS member + * @NL80211_IFTYPE_STATION: managed BSS member + * @NL80211_IFTYPE_AP: access point + * @NL80211_IFTYPE_AP_VLAN: VLAN interface for access points; VLAN interfaces + * are a bit special in that they must always be tied to a pre-existing + * AP type interface. + * @NL80211_IFTYPE_WDS: wireless distribution interface + * @NL80211_IFTYPE_MONITOR: monitor interface receiving all frames + * @NL80211_IFTYPE_MESH_POINT: mesh point + * @NL80211_IFTYPE_P2P_CLIENT: P2P client + * @NL80211_IFTYPE_P2P_GO: P2P group owner + * @NL80211_IFTYPE_P2P_DEVICE: P2P device interface type, this is not a netdev + * and therefore can't be created in the normal ways, use the + * %NL80211_CMD_START_P2P_DEVICE and %NL80211_CMD_STOP_P2P_DEVICE + * commands to create and destroy one + * @NL80211_IF_TYPE_OCB: Outside Context of a BSS + * This mode corresponds to the MIB variable dot11OCBActivated=true + * @NL80211_IFTYPE_MAX: highest interface type number currently defined + * @NUM_NL80211_IFTYPES: number of defined interface types + * + * These values are used with the %NL80211_ATTR_IFTYPE + * to set the type of an interface. + * + */ +enum nl80211_iftype { + NL80211_IFTYPE_UNSPECIFIED, + NL80211_IFTYPE_ADHOC, + NL80211_IFTYPE_STATION, + NL80211_IFTYPE_AP, + NL80211_IFTYPE_AP_VLAN, + NL80211_IFTYPE_WDS, + NL80211_IFTYPE_MONITOR, + NL80211_IFTYPE_MESH_POINT, + NL80211_IFTYPE_P2P_CLIENT, + NL80211_IFTYPE_P2P_GO, + NL80211_IFTYPE_P2P_DEVICE, + NL80211_IFTYPE_OCB, + + /* keep last */ + NUM_NL80211_IFTYPES, + NL80211_IFTYPE_MAX = NUM_NL80211_IFTYPES - 1 +}; + +/** + * enum nl80211_sta_flags - station flags + * + * Station flags. When a station is added to an AP interface, it is + * assumed to be already associated (and hence authenticated.) + * + * @__NL80211_STA_FLAG_INVALID: attribute number 0 is reserved + * @NL80211_STA_FLAG_AUTHORIZED: station is authorized (802.1X) + * @NL80211_STA_FLAG_SHORT_PREAMBLE: station is capable of receiving frames + * with short barker preamble + * @NL80211_STA_FLAG_WME: station is WME/QoS capable + * @NL80211_STA_FLAG_MFP: station uses management frame protection + * @NL80211_STA_FLAG_AUTHENTICATED: station is authenticated + * @NL80211_STA_FLAG_TDLS_PEER: station is a TDLS peer -- this flag should + * only be used in managed mode (even in the flags mask). Note that the + * flag can't be changed, it is only valid while adding a station, and + * attempts to change it will silently be ignored (rather than rejected + * as errors.) + * @NL80211_STA_FLAG_ASSOCIATED: station is associated; used with drivers + * that support %NL80211_FEATURE_FULL_AP_CLIENT_STATE to transition a + * previously added station into associated state + * @NL80211_STA_FLAG_MAX: highest station flag number currently defined + * @__NL80211_STA_FLAG_AFTER_LAST: internal use + */ +enum nl80211_sta_flags { + __NL80211_STA_FLAG_INVALID, + NL80211_STA_FLAG_AUTHORIZED, + NL80211_STA_FLAG_SHORT_PREAMBLE, + NL80211_STA_FLAG_WME, + NL80211_STA_FLAG_MFP, + NL80211_STA_FLAG_AUTHENTICATED, + NL80211_STA_FLAG_TDLS_PEER, + NL80211_STA_FLAG_ASSOCIATED, + + /* keep last */ + __NL80211_STA_FLAG_AFTER_LAST, + NL80211_STA_FLAG_MAX = __NL80211_STA_FLAG_AFTER_LAST - 1 +}; + +#define NL80211_STA_FLAG_MAX_OLD_API NL80211_STA_FLAG_TDLS_PEER + +/** + * struct nl80211_sta_flag_update - station flags mask/set + * @mask: mask of station flags to set + * @set: which values to set them to + * + * Both mask and set contain bits as per &enum nl80211_sta_flags. + */ +struct nl80211_sta_flag_update { + __u32 mask; + __u32 set; +} __attribute__((packed)); + +/** + * enum nl80211_rate_info - bitrate information + * + * These attribute types are used with %NL80211_STA_INFO_TXRATE + * when getting information about the bitrate of a station. + * There are 2 attributes for bitrate, a legacy one that represents + * a 16-bit value, and new one that represents a 32-bit value. + * If the rate value fits into 16 bit, both attributes are reported + * with the same value. If the rate is too high to fit into 16 bits + * (>6.5535Gbps) only 32-bit attribute is included. + * User space tools encouraged to use the 32-bit attribute and fall + * back to the 16-bit one for compatibility with older kernels. + * + * @__NL80211_RATE_INFO_INVALID: attribute number 0 is reserved + * @NL80211_RATE_INFO_BITRATE: total bitrate (u16, 100kbit/s) + * @NL80211_RATE_INFO_MCS: mcs index for 802.11n (u8) + * @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 MHz dualchannel bitrate + * @NL80211_RATE_INFO_SHORT_GI: 400ns guard interval + * @NL80211_RATE_INFO_BITRATE32: total bitrate (u32, 100kbit/s) + * @NL80211_RATE_INFO_MAX: highest rate_info number currently defined + * @NL80211_RATE_INFO_VHT_MCS: MCS index for VHT (u8) + * @NL80211_RATE_INFO_VHT_NSS: number of streams in VHT (u8) + * @NL80211_RATE_INFO_80_MHZ_WIDTH: 80 MHz VHT rate + * @NL80211_RATE_INFO_80P80_MHZ_WIDTH: unused - 80+80 is treated the + * same as 160 for purposes of the bitrates + * @NL80211_RATE_INFO_160_MHZ_WIDTH: 160 MHz VHT rate + * @NL80211_RATE_INFO_10_MHZ_WIDTH: 10 MHz width - note that this is + * a legacy rate and will be reported as the actual bitrate, i.e. + * half the base (20 MHz) rate + * @NL80211_RATE_INFO_5_MHZ_WIDTH: 5 MHz width - note that this is + * a legacy rate and will be reported as the actual bitrate, i.e. + * a quarter of the base (20 MHz) rate + * @__NL80211_RATE_INFO_AFTER_LAST: internal use + */ +enum nl80211_rate_info { + __NL80211_RATE_INFO_INVALID, + NL80211_RATE_INFO_BITRATE, + NL80211_RATE_INFO_MCS, + NL80211_RATE_INFO_40_MHZ_WIDTH, + NL80211_RATE_INFO_SHORT_GI, + NL80211_RATE_INFO_BITRATE32, + NL80211_RATE_INFO_VHT_MCS, + NL80211_RATE_INFO_VHT_NSS, + NL80211_RATE_INFO_80_MHZ_WIDTH, + NL80211_RATE_INFO_80P80_MHZ_WIDTH, + NL80211_RATE_INFO_160_MHZ_WIDTH, + NL80211_RATE_INFO_10_MHZ_WIDTH, + NL80211_RATE_INFO_5_MHZ_WIDTH, + + /* keep last */ + __NL80211_RATE_INFO_AFTER_LAST, + NL80211_RATE_INFO_MAX = __NL80211_RATE_INFO_AFTER_LAST - 1 +}; + +/** + * enum nl80211_sta_bss_param - BSS information collected by STA + * + * These attribute types are used with %NL80211_STA_INFO_BSS_PARAM + * when getting information about the bitrate of a station. + * + * @__NL80211_STA_BSS_PARAM_INVALID: attribute number 0 is reserved + * @NL80211_STA_BSS_PARAM_CTS_PROT: whether CTS protection is enabled (flag) + * @NL80211_STA_BSS_PARAM_SHORT_PREAMBLE: whether short preamble is enabled + * (flag) + * @NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME: whether short slot time is enabled + * (flag) + * @NL80211_STA_BSS_PARAM_DTIM_PERIOD: DTIM period for beaconing (u8) + * @NL80211_STA_BSS_PARAM_BEACON_INTERVAL: Beacon interval (u16) + * @NL80211_STA_BSS_PARAM_MAX: highest sta_bss_param number currently defined + * @__NL80211_STA_BSS_PARAM_AFTER_LAST: internal use + */ +enum nl80211_sta_bss_param { + __NL80211_STA_BSS_PARAM_INVALID, + NL80211_STA_BSS_PARAM_CTS_PROT, + NL80211_STA_BSS_PARAM_SHORT_PREAMBLE, + NL80211_STA_BSS_PARAM_SHORT_SLOT_TIME, + NL80211_STA_BSS_PARAM_DTIM_PERIOD, + NL80211_STA_BSS_PARAM_BEACON_INTERVAL, + + /* keep last */ + __NL80211_STA_BSS_PARAM_AFTER_LAST, + NL80211_STA_BSS_PARAM_MAX = __NL80211_STA_BSS_PARAM_AFTER_LAST - 1 +}; + +/** + * enum nl80211_sta_info - station information + * + * These attribute types are used with %NL80211_ATTR_STA_INFO + * when getting information about a station. + * + * @__NL80211_STA_INFO_INVALID: attribute number 0 is reserved + * @NL80211_STA_INFO_INACTIVE_TIME: time since last activity (u32, msecs) + * @NL80211_STA_INFO_RX_BYTES: total received bytes (MPDU length) + * (u32, from this station) + * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (MPDU length) + * (u32, to this station) + * @NL80211_STA_INFO_RX_BYTES64: total received bytes (MPDU length) + * (u64, from this station) + * @NL80211_STA_INFO_TX_BYTES64: total transmitted bytes (MPDU length) + * (u64, to this station) + * @NL80211_STA_INFO_SIGNAL: signal strength of last received PPDU (u8, dBm) + * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate, nested attribute + * containing info as possible, see &enum nl80211_rate_info + * @NL80211_STA_INFO_RX_PACKETS: total received packet (MSDUs and MMPDUs) + * (u32, from this station) + * @NL80211_STA_INFO_TX_PACKETS: total transmitted packets (MSDUs and MMPDUs) + * (u32, to this station) + * @NL80211_STA_INFO_TX_RETRIES: total retries (MPDUs) (u32, to this station) + * @NL80211_STA_INFO_TX_FAILED: total failed packets (MPDUs) + * (u32, to this station) + * @NL80211_STA_INFO_SIGNAL_AVG: signal strength average (u8, dBm) + * @NL80211_STA_INFO_LLID: the station's mesh LLID + * @NL80211_STA_INFO_PLID: the station's mesh PLID + * @NL80211_STA_INFO_PLINK_STATE: peer link state for the station + * (see %enum nl80211_plink_state) + * @NL80211_STA_INFO_RX_BITRATE: last unicast data frame rx rate, nested + * attribute, like NL80211_STA_INFO_TX_BITRATE. + * @NL80211_STA_INFO_BSS_PARAM: current station's view of BSS, nested attribute + * containing info as possible, see &enum nl80211_sta_bss_param + * @NL80211_STA_INFO_CONNECTED_TIME: time since the station is last connected + * @NL80211_STA_INFO_STA_FLAGS: Contains a struct nl80211_sta_flag_update. + * @NL80211_STA_INFO_BEACON_LOSS: count of times beacon loss was detected (u32) + * @NL80211_STA_INFO_T_OFFSET: timing offset with respect to this STA (s64) + * @NL80211_STA_INFO_LOCAL_PM: local mesh STA link-specific power mode + * @NL80211_STA_INFO_PEER_PM: peer mesh STA link-specific power mode + * @NL80211_STA_INFO_NONPEER_PM: neighbor mesh STA power save mode towards + * non-peer STA + * @NL80211_STA_INFO_CHAIN_SIGNAL: per-chain signal strength of last PPDU + * Contains a nested array of signal strength attributes (u8, dBm) + * @NL80211_STA_INFO_CHAIN_SIGNAL_AVG: per-chain signal strength average + * Same format as NL80211_STA_INFO_CHAIN_SIGNAL. + * @NL80211_STA_EXPECTED_THROUGHPUT: expected throughput considering also the + * 802.11 header (u32, kbps) + * @NL80211_STA_INFO_RX_DROP_MISC: RX packets dropped for unspecified reasons + * (u64) + * @NL80211_STA_INFO_BEACON_RX: number of beacons received from this peer (u64) + * @NL80211_STA_INFO_BEACON_SIGNAL_AVG: signal strength average + * for beacons only (u8, dBm) + * @NL80211_STA_INFO_TID_STATS: per-TID statistics (see &enum nl80211_tid_stats) + * This is a nested attribute where each the inner attribute number is the + * TID+1 and the special TID 16 (i.e. value 17) is used for non-QoS frames; + * each one of those is again nested with &enum nl80211_tid_stats + * attributes carrying the actual values. + * @__NL80211_STA_INFO_AFTER_LAST: internal + * @NL80211_STA_INFO_MAX: highest possible station info attribute + */ +enum nl80211_sta_info { + __NL80211_STA_INFO_INVALID, + NL80211_STA_INFO_INACTIVE_TIME, + NL80211_STA_INFO_RX_BYTES, + NL80211_STA_INFO_TX_BYTES, + NL80211_STA_INFO_LLID, + NL80211_STA_INFO_PLID, + NL80211_STA_INFO_PLINK_STATE, + NL80211_STA_INFO_SIGNAL, + NL80211_STA_INFO_TX_BITRATE, + NL80211_STA_INFO_RX_PACKETS, + NL80211_STA_INFO_TX_PACKETS, + NL80211_STA_INFO_TX_RETRIES, + NL80211_STA_INFO_TX_FAILED, + NL80211_STA_INFO_SIGNAL_AVG, + NL80211_STA_INFO_RX_BITRATE, + NL80211_STA_INFO_BSS_PARAM, + NL80211_STA_INFO_CONNECTED_TIME, + NL80211_STA_INFO_STA_FLAGS, + NL80211_STA_INFO_BEACON_LOSS, + NL80211_STA_INFO_T_OFFSET, + NL80211_STA_INFO_LOCAL_PM, + NL80211_STA_INFO_PEER_PM, + NL80211_STA_INFO_NONPEER_PM, + NL80211_STA_INFO_RX_BYTES64, + NL80211_STA_INFO_TX_BYTES64, + NL80211_STA_INFO_CHAIN_SIGNAL, + NL80211_STA_INFO_CHAIN_SIGNAL_AVG, + NL80211_STA_INFO_EXPECTED_THROUGHPUT, + NL80211_STA_INFO_RX_DROP_MISC, + NL80211_STA_INFO_BEACON_RX, + NL80211_STA_INFO_BEACON_SIGNAL_AVG, + NL80211_STA_INFO_TID_STATS, + + /* keep last */ + __NL80211_STA_INFO_AFTER_LAST, + NL80211_STA_INFO_MAX = __NL80211_STA_INFO_AFTER_LAST - 1 +}; + +/** + * enum nl80211_tid_stats - per TID statistics attributes + * @__NL80211_TID_STATS_INVALID: attribute number 0 is reserved + * @NL80211_TID_STATS_RX_MSDU: number of MSDUs received (u64) + * @NL80211_TID_STATS_TX_MSDU: number of MSDUs transmitted (or + * attempted to transmit; u64) + * @NL80211_TID_STATS_TX_MSDU_RETRIES: number of retries for + * transmitted MSDUs (not counting the first attempt; u64) + * @NL80211_TID_STATS_TX_MSDU_FAILED: number of failed transmitted + * MSDUs (u64) + * @NUM_NL80211_TID_STATS: number of attributes here + * @NL80211_TID_STATS_MAX: highest numbered attribute here + */ +enum nl80211_tid_stats { + __NL80211_TID_STATS_INVALID, + NL80211_TID_STATS_RX_MSDU, + NL80211_TID_STATS_TX_MSDU, + NL80211_TID_STATS_TX_MSDU_RETRIES, + NL80211_TID_STATS_TX_MSDU_FAILED, + + /* keep last */ + NUM_NL80211_TID_STATS, + NL80211_TID_STATS_MAX = NUM_NL80211_TID_STATS - 1 +}; + +/** + * enum nl80211_mpath_flags - nl80211 mesh path flags + * + * @NL80211_MPATH_FLAG_ACTIVE: the mesh path is active + * @NL80211_MPATH_FLAG_RESOLVING: the mesh path discovery process is running + * @NL80211_MPATH_FLAG_SN_VALID: the mesh path contains a valid SN + * @NL80211_MPATH_FLAG_FIXED: the mesh path has been manually set + * @NL80211_MPATH_FLAG_RESOLVED: the mesh path discovery process succeeded + */ +enum nl80211_mpath_flags { + NL80211_MPATH_FLAG_ACTIVE = 1<<0, + NL80211_MPATH_FLAG_RESOLVING = 1<<1, + NL80211_MPATH_FLAG_SN_VALID = 1<<2, + NL80211_MPATH_FLAG_FIXED = 1<<3, + NL80211_MPATH_FLAG_RESOLVED = 1<<4, +}; + +/** + * enum nl80211_mpath_info - mesh path information + * + * These attribute types are used with %NL80211_ATTR_MPATH_INFO when getting + * information about a mesh path. + * + * @__NL80211_MPATH_INFO_INVALID: attribute number 0 is reserved + * @NL80211_MPATH_INFO_FRAME_QLEN: number of queued frames for this destination + * @NL80211_MPATH_INFO_SN: destination sequence number + * @NL80211_MPATH_INFO_METRIC: metric (cost) of this mesh path + * @NL80211_MPATH_INFO_EXPTIME: expiration time for the path, in msec from now + * @NL80211_MPATH_INFO_FLAGS: mesh path flags, enumerated in + * &enum nl80211_mpath_flags; + * @NL80211_MPATH_INFO_DISCOVERY_TIMEOUT: total path discovery timeout, in msec + * @NL80211_MPATH_INFO_DISCOVERY_RETRIES: mesh path discovery retries + * @NL80211_MPATH_INFO_MAX: highest mesh path information attribute number + * currently defind + * @__NL80211_MPATH_INFO_AFTER_LAST: internal use + */ +enum nl80211_mpath_info { + __NL80211_MPATH_INFO_INVALID, + NL80211_MPATH_INFO_FRAME_QLEN, + NL80211_MPATH_INFO_SN, + NL80211_MPATH_INFO_METRIC, + NL80211_MPATH_INFO_EXPTIME, + NL80211_MPATH_INFO_FLAGS, + NL80211_MPATH_INFO_DISCOVERY_TIMEOUT, + NL80211_MPATH_INFO_DISCOVERY_RETRIES, + + /* keep last */ + __NL80211_MPATH_INFO_AFTER_LAST, + NL80211_MPATH_INFO_MAX = __NL80211_MPATH_INFO_AFTER_LAST - 1 +}; + +/** + * enum nl80211_band_attr - band attributes + * @__NL80211_BAND_ATTR_INVALID: attribute number 0 is reserved + * @NL80211_BAND_ATTR_FREQS: supported frequencies in this band, + * an array of nested frequency attributes + * @NL80211_BAND_ATTR_RATES: supported bitrates in this band, + * an array of nested bitrate attributes + * @NL80211_BAND_ATTR_HT_MCS_SET: 16-byte attribute containing the MCS set as + * defined in 802.11n + * @NL80211_BAND_ATTR_HT_CAPA: HT capabilities, as in the HT information IE + * @NL80211_BAND_ATTR_HT_AMPDU_FACTOR: A-MPDU factor, as in 11n + * @NL80211_BAND_ATTR_HT_AMPDU_DENSITY: A-MPDU density, as in 11n + * @NL80211_BAND_ATTR_VHT_MCS_SET: 32-byte attribute containing the MCS set as + * defined in 802.11ac + * @NL80211_BAND_ATTR_VHT_CAPA: VHT capabilities, as in the HT information IE + * @NL80211_BAND_ATTR_MAX: highest band attribute currently defined + * @__NL80211_BAND_ATTR_AFTER_LAST: internal use + */ +enum nl80211_band_attr { + __NL80211_BAND_ATTR_INVALID, + NL80211_BAND_ATTR_FREQS, + NL80211_BAND_ATTR_RATES, + + NL80211_BAND_ATTR_HT_MCS_SET, + NL80211_BAND_ATTR_HT_CAPA, + NL80211_BAND_ATTR_HT_AMPDU_FACTOR, + NL80211_BAND_ATTR_HT_AMPDU_DENSITY, + + NL80211_BAND_ATTR_VHT_MCS_SET, + NL80211_BAND_ATTR_VHT_CAPA, + + /* keep last */ + __NL80211_BAND_ATTR_AFTER_LAST, + NL80211_BAND_ATTR_MAX = __NL80211_BAND_ATTR_AFTER_LAST - 1 +}; + +#define NL80211_BAND_ATTR_HT_CAPA NL80211_BAND_ATTR_HT_CAPA + +/** + * enum nl80211_frequency_attr - frequency attributes + * @__NL80211_FREQUENCY_ATTR_INVALID: attribute number 0 is reserved + * @NL80211_FREQUENCY_ATTR_FREQ: Frequency in MHz + * @NL80211_FREQUENCY_ATTR_DISABLED: Channel is disabled in current + * regulatory domain. + * @NL80211_FREQUENCY_ATTR_NO_IR: no mechanisms that initiate radiation + * are permitted on this channel, this includes sending probe + * requests, or modes of operation that require beaconing. + * @NL80211_FREQUENCY_ATTR_RADAR: Radar detection is mandatory + * on this channel in current regulatory domain. + * @NL80211_FREQUENCY_ATTR_MAX_TX_POWER: Maximum transmission power in mBm + * (100 * dBm). + * @NL80211_FREQUENCY_ATTR_DFS_STATE: current state for DFS + * (enum nl80211_dfs_state) + * @NL80211_FREQUENCY_ATTR_DFS_TIME: time in miliseconds for how long + * this channel is in this DFS state. + * @NL80211_FREQUENCY_ATTR_NO_HT40_MINUS: HT40- isn't possible with this + * channel as the control channel + * @NL80211_FREQUENCY_ATTR_NO_HT40_PLUS: HT40+ isn't possible with this + * channel as the control channel + * @NL80211_FREQUENCY_ATTR_NO_80MHZ: any 80 MHz channel using this channel + * as the primary or any of the secondary channels isn't possible, + * this includes 80+80 channels + * @NL80211_FREQUENCY_ATTR_NO_160MHZ: any 160 MHz (but not 80+80) channel + * using this channel as the primary or any of the secondary channels + * isn't possible + * @NL80211_FREQUENCY_ATTR_DFS_CAC_TIME: DFS CAC time in milliseconds. + * @NL80211_FREQUENCY_ATTR_INDOOR_ONLY: Only indoor use is permitted on this + * channel. A channel that has the INDOOR_ONLY attribute can only be + * used when there is a clear assessment that the device is operating in + * an indoor surroundings, i.e., it is connected to AC power (and not + * through portable DC inverters) or is under the control of a master + * that is acting as an AP and is connected to AC power. + * @NL80211_FREQUENCY_ATTR_GO_CONCURRENT: GO operation is allowed on this + * channel if it's connected concurrently to a BSS on the same channel on + * the 2 GHz band or to a channel in the same UNII band (on the 5 GHz + * band), and IEEE80211_CHAN_RADAR is not set. Instantiating a GO on a + * channel that has the GO_CONCURRENT attribute set can be done when there + * is a clear assessment that the device is operating under the guidance of + * an authorized master, i.e., setting up a GO while the device is also + * connected to an AP with DFS and radar detection on the UNII band (it is + * up to user-space, i.e., wpa_supplicant to perform the required + * verifications) + * @NL80211_FREQUENCY_ATTR_NO_20MHZ: 20 MHz operation is not allowed + * on this channel in current regulatory domain. + * @NL80211_FREQUENCY_ATTR_NO_10MHZ: 10 MHz operation is not allowed + * on this channel in current regulatory domain. + * @NL80211_FREQUENCY_ATTR_MAX: highest frequency attribute number + * currently defined + * @__NL80211_FREQUENCY_ATTR_AFTER_LAST: internal use + * + * See https://apps.fcc.gov/eas/comments/GetPublishedDocument.html?id=327&tn=528122 + * for more information on the FCC description of the relaxations allowed + * by NL80211_FREQUENCY_ATTR_INDOOR_ONLY and + * NL80211_FREQUENCY_ATTR_GO_CONCURRENT. + */ +enum nl80211_frequency_attr { + __NL80211_FREQUENCY_ATTR_INVALID, + NL80211_FREQUENCY_ATTR_FREQ, + NL80211_FREQUENCY_ATTR_DISABLED, + NL80211_FREQUENCY_ATTR_NO_IR, + __NL80211_FREQUENCY_ATTR_NO_IBSS, + NL80211_FREQUENCY_ATTR_RADAR, + NL80211_FREQUENCY_ATTR_MAX_TX_POWER, + NL80211_FREQUENCY_ATTR_DFS_STATE, + NL80211_FREQUENCY_ATTR_DFS_TIME, + NL80211_FREQUENCY_ATTR_NO_HT40_MINUS, + NL80211_FREQUENCY_ATTR_NO_HT40_PLUS, + NL80211_FREQUENCY_ATTR_NO_80MHZ, + NL80211_FREQUENCY_ATTR_NO_160MHZ, + NL80211_FREQUENCY_ATTR_DFS_CAC_TIME, + NL80211_FREQUENCY_ATTR_INDOOR_ONLY, + NL80211_FREQUENCY_ATTR_GO_CONCURRENT, + NL80211_FREQUENCY_ATTR_NO_20MHZ, + NL80211_FREQUENCY_ATTR_NO_10MHZ, + + /* keep last */ + __NL80211_FREQUENCY_ATTR_AFTER_LAST, + NL80211_FREQUENCY_ATTR_MAX = __NL80211_FREQUENCY_ATTR_AFTER_LAST - 1 +}; + +#define NL80211_FREQUENCY_ATTR_MAX_TX_POWER NL80211_FREQUENCY_ATTR_MAX_TX_POWER +#define NL80211_FREQUENCY_ATTR_PASSIVE_SCAN NL80211_FREQUENCY_ATTR_NO_IR +#define NL80211_FREQUENCY_ATTR_NO_IBSS NL80211_FREQUENCY_ATTR_NO_IR +#define NL80211_FREQUENCY_ATTR_NO_IR NL80211_FREQUENCY_ATTR_NO_IR + +/** + * enum nl80211_bitrate_attr - bitrate attributes + * @__NL80211_BITRATE_ATTR_INVALID: attribute number 0 is reserved + * @NL80211_BITRATE_ATTR_RATE: Bitrate in units of 100 kbps + * @NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE: Short preamble supported + * in 2.4 GHz band. + * @NL80211_BITRATE_ATTR_MAX: highest bitrate attribute number + * currently defined + * @__NL80211_BITRATE_ATTR_AFTER_LAST: internal use + */ +enum nl80211_bitrate_attr { + __NL80211_BITRATE_ATTR_INVALID, + NL80211_BITRATE_ATTR_RATE, + NL80211_BITRATE_ATTR_2GHZ_SHORTPREAMBLE, + + /* keep last */ + __NL80211_BITRATE_ATTR_AFTER_LAST, + NL80211_BITRATE_ATTR_MAX = __NL80211_BITRATE_ATTR_AFTER_LAST - 1 +}; + +/** + * enum nl80211_initiator - Indicates the initiator of a reg domain request + * @NL80211_REGDOM_SET_BY_CORE: Core queried CRDA for a dynamic world + * regulatory domain. + * @NL80211_REGDOM_SET_BY_USER: User asked the wireless core to set the + * regulatory domain. + * @NL80211_REGDOM_SET_BY_DRIVER: a wireless drivers has hinted to the + * wireless core it thinks its knows the regulatory domain we should be in. + * @NL80211_REGDOM_SET_BY_COUNTRY_IE: the wireless core has received an + * 802.11 country information element with regulatory information it + * thinks we should consider. cfg80211 only processes the country + * code from the IE, and relies on the regulatory domain information + * structure passed by userspace (CRDA) from our wireless-regdb. + * If a channel is enabled but the country code indicates it should + * be disabled we disable the channel and re-enable it upon disassociation. + */ +enum nl80211_reg_initiator { + NL80211_REGDOM_SET_BY_CORE, + NL80211_REGDOM_SET_BY_USER, + NL80211_REGDOM_SET_BY_DRIVER, + NL80211_REGDOM_SET_BY_COUNTRY_IE, +}; + +/** + * enum nl80211_reg_type - specifies the type of regulatory domain + * @NL80211_REGDOM_TYPE_COUNTRY: the regulatory domain set is one that pertains + * to a specific country. When this is set you can count on the + * ISO / IEC 3166 alpha2 country code being valid. + * @NL80211_REGDOM_TYPE_WORLD: the regulatory set domain is the world regulatory + * domain. + * @NL80211_REGDOM_TYPE_CUSTOM_WORLD: the regulatory domain set is a custom + * driver specific world regulatory domain. These do not apply system-wide + * and are only applicable to the individual devices which have requested + * them to be applied. + * @NL80211_REGDOM_TYPE_INTERSECTION: the regulatory domain set is the product + * of an intersection between two regulatory domains -- the previously + * set regulatory domain on the system and the last accepted regulatory + * domain request to be processed. + */ +enum nl80211_reg_type { + NL80211_REGDOM_TYPE_COUNTRY, + NL80211_REGDOM_TYPE_WORLD, + NL80211_REGDOM_TYPE_CUSTOM_WORLD, + NL80211_REGDOM_TYPE_INTERSECTION, +}; + +/** + * enum nl80211_reg_rule_attr - regulatory rule attributes + * @__NL80211_REG_RULE_ATTR_INVALID: attribute number 0 is reserved + * @NL80211_ATTR_REG_RULE_FLAGS: a set of flags which specify additional + * considerations for a given frequency range. These are the + * &enum nl80211_reg_rule_flags. + * @NL80211_ATTR_FREQ_RANGE_START: starting frequencry for the regulatory + * rule in KHz. This is not a center of frequency but an actual regulatory + * band edge. + * @NL80211_ATTR_FREQ_RANGE_END: ending frequency for the regulatory rule + * in KHz. This is not a center a frequency but an actual regulatory + * band edge. + * @NL80211_ATTR_FREQ_RANGE_MAX_BW: maximum allowed bandwidth for this + * frequency range, in KHz. + * @NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN: the maximum allowed antenna gain + * for a given frequency range. The value is in mBi (100 * dBi). + * If you don't have one then don't send this. + * @NL80211_ATTR_POWER_RULE_MAX_EIRP: the maximum allowed EIRP for + * a given frequency range. The value is in mBm (100 * dBm). + * @NL80211_ATTR_DFS_CAC_TIME: DFS CAC time in milliseconds. + * If not present or 0 default CAC time will be used. + * @NL80211_REG_RULE_ATTR_MAX: highest regulatory rule attribute number + * currently defined + * @__NL80211_REG_RULE_ATTR_AFTER_LAST: internal use + */ +enum nl80211_reg_rule_attr { + __NL80211_REG_RULE_ATTR_INVALID, + NL80211_ATTR_REG_RULE_FLAGS, + + NL80211_ATTR_FREQ_RANGE_START, + NL80211_ATTR_FREQ_RANGE_END, + NL80211_ATTR_FREQ_RANGE_MAX_BW, + + NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN, + NL80211_ATTR_POWER_RULE_MAX_EIRP, + + NL80211_ATTR_DFS_CAC_TIME, + + /* keep last */ + __NL80211_REG_RULE_ATTR_AFTER_LAST, + NL80211_REG_RULE_ATTR_MAX = __NL80211_REG_RULE_ATTR_AFTER_LAST - 1 +}; + +/** + * enum nl80211_sched_scan_match_attr - scheduled scan match attributes + * @__NL80211_SCHED_SCAN_MATCH_ATTR_INVALID: attribute number 0 is reserved + * @NL80211_SCHED_SCAN_MATCH_ATTR_SSID: SSID to be used for matching, + * only report BSS with matching SSID. + * @NL80211_SCHED_SCAN_MATCH_ATTR_RSSI: RSSI threshold (in dBm) for reporting a + * BSS in scan results. Filtering is turned off if not specified. Note that + * if this attribute is in a match set of its own, then it is treated as + * the default value for all matchsets with an SSID, rather than being a + * matchset of its own without an RSSI filter. This is due to problems with + * how this API was implemented in the past. Also, due to the same problem, + * the only way to create a matchset with only an RSSI filter (with this + * attribute) is if there's only a single matchset with the RSSI attribute. + * @NL80211_SCHED_SCAN_MATCH_ATTR_MAX: highest scheduled scan filter + * attribute number currently defined + * @__NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST: internal use + */ +enum nl80211_sched_scan_match_attr { + __NL80211_SCHED_SCAN_MATCH_ATTR_INVALID, + + NL80211_SCHED_SCAN_MATCH_ATTR_SSID, + NL80211_SCHED_SCAN_MATCH_ATTR_RSSI, + + /* keep last */ + __NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST, + NL80211_SCHED_SCAN_MATCH_ATTR_MAX = + __NL80211_SCHED_SCAN_MATCH_ATTR_AFTER_LAST - 1 +}; + +/* only for backward compatibility */ +#define NL80211_ATTR_SCHED_SCAN_MATCH_SSID NL80211_SCHED_SCAN_MATCH_ATTR_SSID + +/** + * enum nl80211_reg_rule_flags - regulatory rule flags + * + * @NL80211_RRF_NO_OFDM: OFDM modulation not allowed + * @NL80211_RRF_NO_CCK: CCK modulation not allowed + * @NL80211_RRF_NO_INDOOR: indoor operation not allowed + * @NL80211_RRF_NO_OUTDOOR: outdoor operation not allowed + * @NL80211_RRF_DFS: DFS support is required to be used + * @NL80211_RRF_PTP_ONLY: this is only for Point To Point links + * @NL80211_RRF_PTMP_ONLY: this is only for Point To Multi Point links + * @NL80211_RRF_NO_IR: no mechanisms that initiate radiation are allowed, + * this includes probe requests or modes of operation that require + * beaconing. + * @NL80211_RRF_AUTO_BW: maximum available bandwidth should be calculated + * base on contiguous rules and wider channels will be allowed to cross + * multiple contiguous/overlapping frequency ranges. + * @NL80211_RRF_GO_CONCURRENT: See &NL80211_FREQUENCY_ATTR_GO_CONCURRENT + * @NL80211_RRF_NO_HT40MINUS: channels can't be used in HT40- operation + * @NL80211_RRF_NO_HT40PLUS: channels can't be used in HT40+ operation + * @NL80211_RRF_NO_80MHZ: 80MHz operation not allowed + * @NL80211_RRF_NO_160MHZ: 160MHz operation not allowed + */ +enum nl80211_reg_rule_flags { + NL80211_RRF_NO_OFDM = 1<<0, + NL80211_RRF_NO_CCK = 1<<1, + NL80211_RRF_NO_INDOOR = 1<<2, + NL80211_RRF_NO_OUTDOOR = 1<<3, + NL80211_RRF_DFS = 1<<4, + NL80211_RRF_PTP_ONLY = 1<<5, + NL80211_RRF_PTMP_ONLY = 1<<6, + NL80211_RRF_NO_IR = 1<<7, + __NL80211_RRF_NO_IBSS = 1<<8, + NL80211_RRF_AUTO_BW = 1<<11, + NL80211_RRF_GO_CONCURRENT = 1<<12, + NL80211_RRF_NO_HT40MINUS = 1<<13, + NL80211_RRF_NO_HT40PLUS = 1<<14, + NL80211_RRF_NO_80MHZ = 1<<15, + NL80211_RRF_NO_160MHZ = 1<<16, +}; + +#define NL80211_RRF_PASSIVE_SCAN NL80211_RRF_NO_IR +#define NL80211_RRF_NO_IBSS NL80211_RRF_NO_IR +#define NL80211_RRF_NO_IR NL80211_RRF_NO_IR +#define NL80211_RRF_NO_HT40 (NL80211_RRF_NO_HT40MINUS |\ + NL80211_RRF_NO_HT40PLUS) + +/* For backport compatibility with older userspace */ +#define NL80211_RRF_NO_IR_ALL (NL80211_RRF_NO_IR | __NL80211_RRF_NO_IBSS) + +/** + * enum nl80211_dfs_regions - regulatory DFS regions + * + * @NL80211_DFS_UNSET: Country has no DFS master region specified + * @NL80211_DFS_FCC: Country follows DFS master rules from FCC + * @NL80211_DFS_ETSI: Country follows DFS master rules from ETSI + * @NL80211_DFS_JP: Country follows DFS master rules from JP/MKK/Telec + */ +enum nl80211_dfs_regions { + NL80211_DFS_UNSET = 0, + NL80211_DFS_FCC = 1, + NL80211_DFS_ETSI = 2, + NL80211_DFS_JP = 3, +}; + +/** + * enum nl80211_user_reg_hint_type - type of user regulatory hint + * + * @NL80211_USER_REG_HINT_USER: a user sent the hint. This is always + * assumed if the attribute is not set. + * @NL80211_USER_REG_HINT_CELL_BASE: the hint comes from a cellular + * base station. Device drivers that have been tested to work + * properly to support this type of hint can enable these hints + * by setting the NL80211_FEATURE_CELL_BASE_REG_HINTS feature + * capability on the struct wiphy. The wireless core will + * ignore all cell base station hints until at least one device + * present has been registered with the wireless core that + * has listed NL80211_FEATURE_CELL_BASE_REG_HINTS as a + * supported feature. + * @NL80211_USER_REG_HINT_INDOOR: a user sent an hint indicating that the + * platform is operating in an indoor environment. + */ +enum nl80211_user_reg_hint_type { + NL80211_USER_REG_HINT_USER = 0, + NL80211_USER_REG_HINT_CELL_BASE = 1, + NL80211_USER_REG_HINT_INDOOR = 2, +}; + +/** + * enum nl80211_survey_info - survey information + * + * These attribute types are used with %NL80211_ATTR_SURVEY_INFO + * when getting information about a survey. + * + * @__NL80211_SURVEY_INFO_INVALID: attribute number 0 is reserved + * @NL80211_SURVEY_INFO_FREQUENCY: center frequency of channel + * @NL80211_SURVEY_INFO_NOISE: noise level of channel (u8, dBm) + * @NL80211_SURVEY_INFO_IN_USE: channel is currently being used + * @NL80211_SURVEY_INFO_TIME: amount of time (in ms) that the radio + * was turned on (on channel or globally) + * @NL80211_SURVEY_INFO_TIME_BUSY: amount of the time the primary + * channel was sensed busy (either due to activity or energy detect) + * @NL80211_SURVEY_INFO_TIME_EXT_BUSY: amount of time the extension + * channel was sensed busy + * @NL80211_SURVEY_INFO_TIME_RX: amount of time the radio spent + * receiving data (on channel or globally) + * @NL80211_SURVEY_INFO_TIME_TX: amount of time the radio spent + * transmitting data (on channel or globally) + * @NL80211_SURVEY_INFO_TIME_SCAN: time the radio spent for scan + * (on this channel or globally) + * @NL80211_SURVEY_INFO_MAX: highest survey info attribute number + * currently defined + * @__NL80211_SURVEY_INFO_AFTER_LAST: internal use + */ +enum nl80211_survey_info { + __NL80211_SURVEY_INFO_INVALID, + NL80211_SURVEY_INFO_FREQUENCY, + NL80211_SURVEY_INFO_NOISE, + NL80211_SURVEY_INFO_IN_USE, + NL80211_SURVEY_INFO_TIME, + NL80211_SURVEY_INFO_TIME_BUSY, + NL80211_SURVEY_INFO_TIME_EXT_BUSY, + NL80211_SURVEY_INFO_TIME_RX, + NL80211_SURVEY_INFO_TIME_TX, + NL80211_SURVEY_INFO_TIME_SCAN, + + /* keep last */ + __NL80211_SURVEY_INFO_AFTER_LAST, + NL80211_SURVEY_INFO_MAX = __NL80211_SURVEY_INFO_AFTER_LAST - 1 +}; + +/* keep old names for compatibility */ +#define NL80211_SURVEY_INFO_CHANNEL_TIME NL80211_SURVEY_INFO_TIME +#define NL80211_SURVEY_INFO_CHANNEL_TIME_BUSY NL80211_SURVEY_INFO_TIME_BUSY +#define NL80211_SURVEY_INFO_CHANNEL_TIME_EXT_BUSY NL80211_SURVEY_INFO_TIME_EXT_BUSY +#define NL80211_SURVEY_INFO_CHANNEL_TIME_RX NL80211_SURVEY_INFO_TIME_RX +#define NL80211_SURVEY_INFO_CHANNEL_TIME_TX NL80211_SURVEY_INFO_TIME_TX + +/** + * enum nl80211_mntr_flags - monitor configuration flags + * + * Monitor configuration flags. + * + * @__NL80211_MNTR_FLAG_INVALID: reserved + * + * @NL80211_MNTR_FLAG_FCSFAIL: pass frames with bad FCS + * @NL80211_MNTR_FLAG_PLCPFAIL: pass frames with bad PLCP + * @NL80211_MNTR_FLAG_CONTROL: pass control frames + * @NL80211_MNTR_FLAG_OTHER_BSS: disable BSSID filtering + * @NL80211_MNTR_FLAG_COOK_FRAMES: report frames after processing. + * overrides all other flags. + * @NL80211_MNTR_FLAG_ACTIVE: use the configured MAC address + * and ACK incoming unicast packets. + * + * @__NL80211_MNTR_FLAG_AFTER_LAST: internal use + * @NL80211_MNTR_FLAG_MAX: highest possible monitor flag + */ +enum nl80211_mntr_flags { + __NL80211_MNTR_FLAG_INVALID, + NL80211_MNTR_FLAG_FCSFAIL, + NL80211_MNTR_FLAG_PLCPFAIL, + NL80211_MNTR_FLAG_CONTROL, + NL80211_MNTR_FLAG_OTHER_BSS, + NL80211_MNTR_FLAG_COOK_FRAMES, + NL80211_MNTR_FLAG_ACTIVE, + + /* keep last */ + __NL80211_MNTR_FLAG_AFTER_LAST, + NL80211_MNTR_FLAG_MAX = __NL80211_MNTR_FLAG_AFTER_LAST - 1 +}; + +/** + * enum nl80211_mesh_power_mode - mesh power save modes + * + * @NL80211_MESH_POWER_UNKNOWN: The mesh power mode of the mesh STA is + * not known or has not been set yet. + * @NL80211_MESH_POWER_ACTIVE: Active mesh power mode. The mesh STA is + * in Awake state all the time. + * @NL80211_MESH_POWER_LIGHT_SLEEP: Light sleep mode. The mesh STA will + * alternate between Active and Doze states, but will wake up for + * neighbor's beacons. + * @NL80211_MESH_POWER_DEEP_SLEEP: Deep sleep mode. The mesh STA will + * alternate between Active and Doze states, but may not wake up + * for neighbor's beacons. + * + * @__NL80211_MESH_POWER_AFTER_LAST - internal use + * @NL80211_MESH_POWER_MAX - highest possible power save level + */ + +enum nl80211_mesh_power_mode { + NL80211_MESH_POWER_UNKNOWN, + NL80211_MESH_POWER_ACTIVE, + NL80211_MESH_POWER_LIGHT_SLEEP, + NL80211_MESH_POWER_DEEP_SLEEP, + + __NL80211_MESH_POWER_AFTER_LAST, + NL80211_MESH_POWER_MAX = __NL80211_MESH_POWER_AFTER_LAST - 1 +}; + +/** + * enum nl80211_meshconf_params - mesh configuration parameters + * + * Mesh configuration parameters. These can be changed while the mesh is + * active. + * + * @__NL80211_MESHCONF_INVALID: internal use + * + * @NL80211_MESHCONF_RETRY_TIMEOUT: specifies the initial retry timeout in + * millisecond units, used by the Peer Link Open message + * + * @NL80211_MESHCONF_CONFIRM_TIMEOUT: specifies the initial confirm timeout, in + * millisecond units, used by the peer link management to close a peer link + * + * @NL80211_MESHCONF_HOLDING_TIMEOUT: specifies the holding timeout, in + * millisecond units + * + * @NL80211_MESHCONF_MAX_PEER_LINKS: maximum number of peer links allowed + * on this mesh interface + * + * @NL80211_MESHCONF_MAX_RETRIES: specifies the maximum number of peer link + * open retries that can be sent to establish a new peer link instance in a + * mesh + * + * @NL80211_MESHCONF_TTL: specifies the value of TTL field set at a source mesh + * point. + * + * @NL80211_MESHCONF_AUTO_OPEN_PLINKS: whether we should automatically open + * peer links when we detect compatible mesh peers. Disabled if + * @NL80211_MESH_SETUP_USERSPACE_MPM or @NL80211_MESH_SETUP_USERSPACE_AMPE are + * set. + * + * @NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES: the number of action frames + * containing a PREQ that an MP can send to a particular destination (path + * target) + * + * @NL80211_MESHCONF_PATH_REFRESH_TIME: how frequently to refresh mesh paths + * (in milliseconds) + * + * @NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT: minimum length of time to wait + * until giving up on a path discovery (in milliseconds) + * + * @NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT: The time (in TUs) for which mesh + * points receiving a PREQ shall consider the forwarding information from + * the root to be valid. (TU = time unit) + * + * @NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL: The minimum interval of time (in + * TUs) during which an MP can send only one action frame containing a PREQ + * reference element + * + * @NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME: The interval of time (in TUs) + * that it takes for an HWMP information element to propagate across the + * mesh + * + * @NL80211_MESHCONF_HWMP_ROOTMODE: whether root mode is enabled or not + * + * @NL80211_MESHCONF_ELEMENT_TTL: specifies the value of TTL field set at a + * source mesh point for path selection elements. + * + * @NL80211_MESHCONF_HWMP_RANN_INTERVAL: The interval of time (in TUs) between + * root announcements are transmitted. + * + * @NL80211_MESHCONF_GATE_ANNOUNCEMENTS: Advertise that this mesh station has + * access to a broader network beyond the MBSS. This is done via Root + * Announcement frames. + * + * @NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL: The minimum interval of time (in + * TUs) during which a mesh STA can send only one Action frame containing a + * PERR element. + * + * @NL80211_MESHCONF_FORWARDING: set Mesh STA as forwarding or non-forwarding + * or forwarding entity (default is TRUE - forwarding entity) + * + * @NL80211_MESHCONF_RSSI_THRESHOLD: RSSI threshold in dBm. This specifies the + * threshold for average signal strength of candidate station to establish + * a peer link. + * + * @NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR: maximum number of neighbors + * to synchronize to for 11s default synchronization method + * (see 11C.12.2.2) + * + * @NL80211_MESHCONF_HT_OPMODE: set mesh HT protection mode. + * + * @NL80211_MESHCONF_ATTR_MAX: highest possible mesh configuration attribute + * + * @NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT: The time (in TUs) for + * which mesh STAs receiving a proactive PREQ shall consider the forwarding + * information to the root mesh STA to be valid. + * + * @NL80211_MESHCONF_HWMP_ROOT_INTERVAL: The interval of time (in TUs) between + * proactive PREQs are transmitted. + * + * @NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL: The minimum interval of time + * (in TUs) during which a mesh STA can send only one Action frame + * containing a PREQ element for root path confirmation. + * + * @NL80211_MESHCONF_POWER_MODE: Default mesh power mode for new peer links. + * type &enum nl80211_mesh_power_mode (u32) + * + * @NL80211_MESHCONF_AWAKE_WINDOW: awake window duration (in TUs) + * + * @NL80211_MESHCONF_PLINK_TIMEOUT: If no tx activity is seen from a STA we've + * established peering with for longer than this time (in seconds), then + * remove it from the STA's list of peers. You may set this to 0 to disable + * the removal of the STA. Default is 30 minutes. + * + * @__NL80211_MESHCONF_ATTR_AFTER_LAST: internal use + */ +enum nl80211_meshconf_params { + __NL80211_MESHCONF_INVALID, + NL80211_MESHCONF_RETRY_TIMEOUT, + NL80211_MESHCONF_CONFIRM_TIMEOUT, + NL80211_MESHCONF_HOLDING_TIMEOUT, + NL80211_MESHCONF_MAX_PEER_LINKS, + NL80211_MESHCONF_MAX_RETRIES, + NL80211_MESHCONF_TTL, + NL80211_MESHCONF_AUTO_OPEN_PLINKS, + NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, + NL80211_MESHCONF_PATH_REFRESH_TIME, + NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT, + NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT, + NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL, + NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME, + NL80211_MESHCONF_HWMP_ROOTMODE, + NL80211_MESHCONF_ELEMENT_TTL, + NL80211_MESHCONF_HWMP_RANN_INTERVAL, + NL80211_MESHCONF_GATE_ANNOUNCEMENTS, + NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL, + NL80211_MESHCONF_FORWARDING, + NL80211_MESHCONF_RSSI_THRESHOLD, + NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR, + NL80211_MESHCONF_HT_OPMODE, + NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT, + NL80211_MESHCONF_HWMP_ROOT_INTERVAL, + NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL, + NL80211_MESHCONF_POWER_MODE, + NL80211_MESHCONF_AWAKE_WINDOW, + NL80211_MESHCONF_PLINK_TIMEOUT, + + /* keep last */ + __NL80211_MESHCONF_ATTR_AFTER_LAST, + NL80211_MESHCONF_ATTR_MAX = __NL80211_MESHCONF_ATTR_AFTER_LAST - 1 +}; + +/** + * enum nl80211_mesh_setup_params - mesh setup parameters + * + * Mesh setup parameters. These are used to start/join a mesh and cannot be + * changed while the mesh is active. + * + * @__NL80211_MESH_SETUP_INVALID: Internal use + * + * @NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL: Enable this option to use a + * vendor specific path selection algorithm or disable it to use the + * default HWMP. + * + * @NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC: Enable this option to use a + * vendor specific path metric or disable it to use the default Airtime + * metric. + * + * @NL80211_MESH_SETUP_IE: Information elements for this mesh, for instance, a + * robust security network ie, or a vendor specific information element + * that vendors will use to identify the path selection methods and + * metrics in use. + * + * @NL80211_MESH_SETUP_USERSPACE_AUTH: Enable this option if an authentication + * daemon will be authenticating mesh candidates. + * + * @NL80211_MESH_SETUP_USERSPACE_AMPE: Enable this option if an authentication + * daemon will be securing peer link frames. AMPE is a secured version of + * Mesh Peering Management (MPM) and is implemented with the assistance of + * a userspace daemon. When this flag is set, the kernel will send peer + * management frames to a userspace daemon that will implement AMPE + * functionality (security capabilities selection, key confirmation, and + * key management). When the flag is unset (default), the kernel can + * autonomously complete (unsecured) mesh peering without the need of a + * userspace daemon. + * + * @NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC: Enable this option to use a + * vendor specific synchronization method or disable it to use the default + * neighbor offset synchronization + * + * @NL80211_MESH_SETUP_USERSPACE_MPM: Enable this option if userspace will + * implement an MPM which handles peer allocation and state. + * + * @NL80211_MESH_SETUP_AUTH_PROTOCOL: Inform the kernel of the authentication + * method (u8, as defined in IEEE 8.4.2.100.6, e.g. 0x1 for SAE). + * Default is no authentication method required. + * + * @NL80211_MESH_SETUP_ATTR_MAX: highest possible mesh setup attribute number + * + * @__NL80211_MESH_SETUP_ATTR_AFTER_LAST: Internal use + */ +enum nl80211_mesh_setup_params { + __NL80211_MESH_SETUP_INVALID, + NL80211_MESH_SETUP_ENABLE_VENDOR_PATH_SEL, + NL80211_MESH_SETUP_ENABLE_VENDOR_METRIC, + NL80211_MESH_SETUP_IE, + NL80211_MESH_SETUP_USERSPACE_AUTH, + NL80211_MESH_SETUP_USERSPACE_AMPE, + NL80211_MESH_SETUP_ENABLE_VENDOR_SYNC, + NL80211_MESH_SETUP_USERSPACE_MPM, + NL80211_MESH_SETUP_AUTH_PROTOCOL, + + /* keep last */ + __NL80211_MESH_SETUP_ATTR_AFTER_LAST, + NL80211_MESH_SETUP_ATTR_MAX = __NL80211_MESH_SETUP_ATTR_AFTER_LAST - 1 +}; + +/** + * enum nl80211_txq_attr - TX queue parameter attributes + * @__NL80211_TXQ_ATTR_INVALID: Attribute number 0 is reserved + * @NL80211_TXQ_ATTR_AC: AC identifier (NL80211_AC_*) + * @NL80211_TXQ_ATTR_TXOP: Maximum burst time in units of 32 usecs, 0 meaning + * disabled + * @NL80211_TXQ_ATTR_CWMIN: Minimum contention window [a value of the form + * 2^n-1 in the range 1..32767] + * @NL80211_TXQ_ATTR_CWMAX: Maximum contention window [a value of the form + * 2^n-1 in the range 1..32767] + * @NL80211_TXQ_ATTR_AIFS: Arbitration interframe space [0..255] + * @__NL80211_TXQ_ATTR_AFTER_LAST: Internal + * @NL80211_TXQ_ATTR_MAX: Maximum TXQ attribute number + */ +enum nl80211_txq_attr { + __NL80211_TXQ_ATTR_INVALID, + NL80211_TXQ_ATTR_AC, + NL80211_TXQ_ATTR_TXOP, + NL80211_TXQ_ATTR_CWMIN, + NL80211_TXQ_ATTR_CWMAX, + NL80211_TXQ_ATTR_AIFS, + + /* keep last */ + __NL80211_TXQ_ATTR_AFTER_LAST, + NL80211_TXQ_ATTR_MAX = __NL80211_TXQ_ATTR_AFTER_LAST - 1 +}; + +enum nl80211_ac { + NL80211_AC_VO, + NL80211_AC_VI, + NL80211_AC_BE, + NL80211_AC_BK, + NL80211_NUM_ACS +}; + +/* backward compat */ +#define NL80211_TXQ_ATTR_QUEUE NL80211_TXQ_ATTR_AC +#define NL80211_TXQ_Q_VO NL80211_AC_VO +#define NL80211_TXQ_Q_VI NL80211_AC_VI +#define NL80211_TXQ_Q_BE NL80211_AC_BE +#define NL80211_TXQ_Q_BK NL80211_AC_BK + +/** + * enum nl80211_channel_type - channel type + * @NL80211_CHAN_NO_HT: 20 MHz, non-HT channel + * @NL80211_CHAN_HT20: 20 MHz HT channel + * @NL80211_CHAN_HT40MINUS: HT40 channel, secondary channel + * below the control channel + * @NL80211_CHAN_HT40PLUS: HT40 channel, secondary channel + * above the control channel + */ +enum nl80211_channel_type { + NL80211_CHAN_NO_HT, + NL80211_CHAN_HT20, + NL80211_CHAN_HT40MINUS, + NL80211_CHAN_HT40PLUS +}; + +/** + * enum nl80211_chan_width - channel width definitions + * + * These values are used with the %NL80211_ATTR_CHANNEL_WIDTH + * attribute. + * + * @NL80211_CHAN_WIDTH_20_NOHT: 20 MHz, non-HT channel + * @NL80211_CHAN_WIDTH_20: 20 MHz HT channel + * @NL80211_CHAN_WIDTH_40: 40 MHz channel, the %NL80211_ATTR_CENTER_FREQ1 + * attribute must be provided as well + * @NL80211_CHAN_WIDTH_80: 80 MHz channel, the %NL80211_ATTR_CENTER_FREQ1 + * attribute must be provided as well + * @NL80211_CHAN_WIDTH_80P80: 80+80 MHz channel, the %NL80211_ATTR_CENTER_FREQ1 + * and %NL80211_ATTR_CENTER_FREQ2 attributes must be provided as well + * @NL80211_CHAN_WIDTH_160: 160 MHz channel, the %NL80211_ATTR_CENTER_FREQ1 + * attribute must be provided as well + * @NL80211_CHAN_WIDTH_5: 5 MHz OFDM channel + * @NL80211_CHAN_WIDTH_10: 10 MHz OFDM channel + */ +enum nl80211_chan_width { + NL80211_CHAN_WIDTH_20_NOHT, + NL80211_CHAN_WIDTH_20, + NL80211_CHAN_WIDTH_40, + NL80211_CHAN_WIDTH_80, + NL80211_CHAN_WIDTH_80P80, + NL80211_CHAN_WIDTH_160, + NL80211_CHAN_WIDTH_5, + NL80211_CHAN_WIDTH_10, +}; + +/** + * enum nl80211_bss_scan_width - control channel width for a BSS + * + * These values are used with the %NL80211_BSS_CHAN_WIDTH attribute. + * + * @NL80211_BSS_CHAN_WIDTH_20: control channel is 20 MHz wide or compatible + * @NL80211_BSS_CHAN_WIDTH_10: control channel is 10 MHz wide + * @NL80211_BSS_CHAN_WIDTH_5: control channel is 5 MHz wide + */ +enum nl80211_bss_scan_width { + NL80211_BSS_CHAN_WIDTH_20, + NL80211_BSS_CHAN_WIDTH_10, + NL80211_BSS_CHAN_WIDTH_5, +}; + +/** + * enum nl80211_bss - netlink attributes for a BSS + * + * @__NL80211_BSS_INVALID: invalid + * @NL80211_BSS_BSSID: BSSID of the BSS (6 octets) + * @NL80211_BSS_FREQUENCY: frequency in MHz (u32) + * @NL80211_BSS_TSF: TSF of the received probe response/beacon (u64) + * (if @NL80211_BSS_PRESP_DATA is present then this is known to be + * from a probe response, otherwise it may be from the same beacon + * that the NL80211_BSS_BEACON_TSF will be from) + * @NL80211_BSS_BEACON_INTERVAL: beacon interval of the (I)BSS (u16) + * @NL80211_BSS_CAPABILITY: capability field (CPU order, u16) + * @NL80211_BSS_INFORMATION_ELEMENTS: binary attribute containing the + * raw information elements from the probe response/beacon (bin); + * if the %NL80211_BSS_BEACON_IES attribute is present and the data is + * different then the IEs here are from a Probe Response frame; otherwise + * they are from a Beacon frame. + * However, if the driver does not indicate the source of the IEs, these + * IEs may be from either frame subtype. + * If present, the @NL80211_BSS_PRESP_DATA attribute indicates that the + * data here is known to be from a probe response, without any heuristics. + * @NL80211_BSS_SIGNAL_MBM: signal strength of probe response/beacon + * in mBm (100 * dBm) (s32) + * @NL80211_BSS_SIGNAL_UNSPEC: signal strength of the probe response/beacon + * in unspecified units, scaled to 0..100 (u8) + * @NL80211_BSS_STATUS: status, if this BSS is "used" + * @NL80211_BSS_SEEN_MS_AGO: age of this BSS entry in ms + * @NL80211_BSS_BEACON_IES: binary attribute containing the raw information + * elements from a Beacon frame (bin); not present if no Beacon frame has + * yet been received + * @NL80211_BSS_CHAN_WIDTH: channel width of the control channel + * (u32, enum nl80211_bss_scan_width) + * @NL80211_BSS_BEACON_TSF: TSF of the last received beacon (u64) + * (not present if no beacon frame has been received yet) + * @NL80211_BSS_PRESP_DATA: the data in @NL80211_BSS_INFORMATION_ELEMENTS and + * @NL80211_BSS_TSF is known to be from a probe response (flag attribute) + * @__NL80211_BSS_AFTER_LAST: internal + * @NL80211_BSS_MAX: highest BSS attribute + */ +enum nl80211_bss { + __NL80211_BSS_INVALID, + NL80211_BSS_BSSID, + NL80211_BSS_FREQUENCY, + NL80211_BSS_TSF, + NL80211_BSS_BEACON_INTERVAL, + NL80211_BSS_CAPABILITY, + NL80211_BSS_INFORMATION_ELEMENTS, + NL80211_BSS_SIGNAL_MBM, + NL80211_BSS_SIGNAL_UNSPEC, + NL80211_BSS_STATUS, + NL80211_BSS_SEEN_MS_AGO, + NL80211_BSS_BEACON_IES, + NL80211_BSS_CHAN_WIDTH, + NL80211_BSS_BEACON_TSF, + NL80211_BSS_PRESP_DATA, + + /* keep last */ + __NL80211_BSS_AFTER_LAST, + NL80211_BSS_MAX = __NL80211_BSS_AFTER_LAST - 1 +}; + +/** + * enum nl80211_bss_status - BSS "status" + * @NL80211_BSS_STATUS_AUTHENTICATED: Authenticated with this BSS. + * Note that this is no longer used since cfg80211 no longer + * keeps track of whether or not authentication was done with + * a given BSS. + * @NL80211_BSS_STATUS_ASSOCIATED: Associated with this BSS. + * @NL80211_BSS_STATUS_IBSS_JOINED: Joined to this IBSS. + * + * The BSS status is a BSS attribute in scan dumps, which + * indicates the status the interface has wrt. this BSS. + */ +enum nl80211_bss_status { + NL80211_BSS_STATUS_AUTHENTICATED, + NL80211_BSS_STATUS_ASSOCIATED, + NL80211_BSS_STATUS_IBSS_JOINED, +}; + +/** + * enum nl80211_auth_type - AuthenticationType + * + * @NL80211_AUTHTYPE_OPEN_SYSTEM: Open System authentication + * @NL80211_AUTHTYPE_SHARED_KEY: Shared Key authentication (WEP only) + * @NL80211_AUTHTYPE_FT: Fast BSS Transition (IEEE 802.11r) + * @NL80211_AUTHTYPE_NETWORK_EAP: Network EAP (some Cisco APs and mainly LEAP) + * @NL80211_AUTHTYPE_SAE: Simultaneous authentication of equals + * @__NL80211_AUTHTYPE_NUM: internal + * @NL80211_AUTHTYPE_MAX: maximum valid auth algorithm + * @NL80211_AUTHTYPE_AUTOMATIC: determine automatically (if necessary by + * trying multiple times); this is invalid in netlink -- leave out + * the attribute for this on CONNECT commands. + */ +enum nl80211_auth_type { + NL80211_AUTHTYPE_OPEN_SYSTEM, + NL80211_AUTHTYPE_SHARED_KEY, + NL80211_AUTHTYPE_FT, + NL80211_AUTHTYPE_NETWORK_EAP, + NL80211_AUTHTYPE_SAE, + + /* keep last */ + __NL80211_AUTHTYPE_NUM, + NL80211_AUTHTYPE_MAX = __NL80211_AUTHTYPE_NUM - 1, + NL80211_AUTHTYPE_AUTOMATIC +}; + +/** + * enum nl80211_key_type - Key Type + * @NL80211_KEYTYPE_GROUP: Group (broadcast/multicast) key + * @NL80211_KEYTYPE_PAIRWISE: Pairwise (unicast/individual) key + * @NL80211_KEYTYPE_PEERKEY: PeerKey (DLS) + * @NUM_NL80211_KEYTYPES: number of defined key types + */ +enum nl80211_key_type { + NL80211_KEYTYPE_GROUP, + NL80211_KEYTYPE_PAIRWISE, + NL80211_KEYTYPE_PEERKEY, + + NUM_NL80211_KEYTYPES +}; + +/** + * enum nl80211_mfp - Management frame protection state + * @NL80211_MFP_NO: Management frame protection not used + * @NL80211_MFP_REQUIRED: Management frame protection required + */ +enum nl80211_mfp { + NL80211_MFP_NO, + NL80211_MFP_REQUIRED, +}; + +enum nl80211_wpa_versions { + NL80211_WPA_VERSION_1 = 1 << 0, + NL80211_WPA_VERSION_2 = 1 << 1, +}; + +/** + * enum nl80211_key_default_types - key default types + * @__NL80211_KEY_DEFAULT_TYPE_INVALID: invalid + * @NL80211_KEY_DEFAULT_TYPE_UNICAST: key should be used as default + * unicast key + * @NL80211_KEY_DEFAULT_TYPE_MULTICAST: key should be used as default + * multicast key + * @NUM_NL80211_KEY_DEFAULT_TYPES: number of default types + */ +enum nl80211_key_default_types { + __NL80211_KEY_DEFAULT_TYPE_INVALID, + NL80211_KEY_DEFAULT_TYPE_UNICAST, + NL80211_KEY_DEFAULT_TYPE_MULTICAST, + + NUM_NL80211_KEY_DEFAULT_TYPES +}; + +/** + * enum nl80211_key_attributes - key attributes + * @__NL80211_KEY_INVALID: invalid + * @NL80211_KEY_DATA: (temporal) key data; for TKIP this consists of + * 16 bytes encryption key followed by 8 bytes each for TX and RX MIC + * keys + * @NL80211_KEY_IDX: key ID (u8, 0-3) + * @NL80211_KEY_CIPHER: key cipher suite (u32, as defined by IEEE 802.11 + * section 7.3.2.25.1, e.g. 0x000FAC04) + * @NL80211_KEY_SEQ: transmit key sequence number (IV/PN) for TKIP and + * CCMP keys, each six bytes in little endian + * @NL80211_KEY_DEFAULT: flag indicating default key + * @NL80211_KEY_DEFAULT_MGMT: flag indicating default management key + * @NL80211_KEY_TYPE: the key type from enum nl80211_key_type, if not + * specified the default depends on whether a MAC address was + * given with the command using the key or not (u32) + * @NL80211_KEY_DEFAULT_TYPES: A nested attribute containing flags + * attributes, specifying what a key should be set as default as. + * See &enum nl80211_key_default_types. + * @__NL80211_KEY_AFTER_LAST: internal + * @NL80211_KEY_MAX: highest key attribute + */ +enum nl80211_key_attributes { + __NL80211_KEY_INVALID, + NL80211_KEY_DATA, + NL80211_KEY_IDX, + NL80211_KEY_CIPHER, + NL80211_KEY_SEQ, + NL80211_KEY_DEFAULT, + NL80211_KEY_DEFAULT_MGMT, + NL80211_KEY_TYPE, + NL80211_KEY_DEFAULT_TYPES, + + /* keep last */ + __NL80211_KEY_AFTER_LAST, + NL80211_KEY_MAX = __NL80211_KEY_AFTER_LAST - 1 +}; + +/** + * enum nl80211_tx_rate_attributes - TX rate set attributes + * @__NL80211_TXRATE_INVALID: invalid + * @NL80211_TXRATE_LEGACY: Legacy (non-MCS) rates allowed for TX rate selection + * in an array of rates as defined in IEEE 802.11 7.3.2.2 (u8 values with + * 1 = 500 kbps) but without the IE length restriction (at most + * %NL80211_MAX_SUPP_RATES in a single array). + * @NL80211_TXRATE_HT: HT (MCS) rates allowed for TX rate selection + * in an array of MCS numbers. + * @NL80211_TXRATE_VHT: VHT rates allowed for TX rate selection, + * see &struct nl80211_txrate_vht + * @NL80211_TXRATE_GI: configure GI, see &enum nl80211_txrate_gi + * @__NL80211_TXRATE_AFTER_LAST: internal + * @NL80211_TXRATE_MAX: highest TX rate attribute + */ +enum nl80211_tx_rate_attributes { + __NL80211_TXRATE_INVALID, + NL80211_TXRATE_LEGACY, + NL80211_TXRATE_HT, + NL80211_TXRATE_VHT, + NL80211_TXRATE_GI, + + /* keep last */ + __NL80211_TXRATE_AFTER_LAST, + NL80211_TXRATE_MAX = __NL80211_TXRATE_AFTER_LAST - 1 +}; + +#define NL80211_TXRATE_MCS NL80211_TXRATE_HT +#define NL80211_VHT_NSS_MAX 8 + +/** + * struct nl80211_txrate_vht - VHT MCS/NSS txrate bitmap + * @mcs: MCS bitmap table for each NSS (array index 0 for 1 stream, etc.) + */ +struct nl80211_txrate_vht { + __u16 mcs[NL80211_VHT_NSS_MAX]; +}; + +enum nl80211_txrate_gi { + NL80211_TXRATE_DEFAULT_GI, + NL80211_TXRATE_FORCE_SGI, + NL80211_TXRATE_FORCE_LGI, +}; + +/** + * enum nl80211_band - Frequency band + * @NL80211_BAND_2GHZ: 2.4 GHz ISM band + * @NL80211_BAND_5GHZ: around 5 GHz band (4.9 - 5.7 GHz) + * @NL80211_BAND_60GHZ: around 60 GHz band (58.32 - 64.80 GHz) + */ +enum nl80211_band { + NL80211_BAND_2GHZ, + NL80211_BAND_5GHZ, + NL80211_BAND_60GHZ, +}; + +/** + * enum nl80211_ps_state - powersave state + * @NL80211_PS_DISABLED: powersave is disabled + * @NL80211_PS_ENABLED: powersave is enabled + */ +enum nl80211_ps_state { + NL80211_PS_DISABLED, + NL80211_PS_ENABLED, +}; + +/** + * enum nl80211_attr_cqm - connection quality monitor attributes + * @__NL80211_ATTR_CQM_INVALID: invalid + * @NL80211_ATTR_CQM_RSSI_THOLD: RSSI threshold in dBm. This value specifies + * the threshold for the RSSI level at which an event will be sent. Zero + * to disable. + * @NL80211_ATTR_CQM_RSSI_HYST: RSSI hysteresis in dBm. This value specifies + * the minimum amount the RSSI level must change after an event before a + * new event may be issued (to reduce effects of RSSI oscillation). + * @NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT: RSSI threshold event + * @NL80211_ATTR_CQM_PKT_LOSS_EVENT: a u32 value indicating that this many + * consecutive packets were not acknowledged by the peer + * @NL80211_ATTR_CQM_TXE_RATE: TX error rate in %. Minimum % of TX failures + * during the given %NL80211_ATTR_CQM_TXE_INTVL before an + * %NL80211_CMD_NOTIFY_CQM with reported %NL80211_ATTR_CQM_TXE_RATE and + * %NL80211_ATTR_CQM_TXE_PKTS is generated. + * @NL80211_ATTR_CQM_TXE_PKTS: number of attempted packets in a given + * %NL80211_ATTR_CQM_TXE_INTVL before %NL80211_ATTR_CQM_TXE_RATE is + * checked. + * @NL80211_ATTR_CQM_TXE_INTVL: interval in seconds. Specifies the periodic + * interval in which %NL80211_ATTR_CQM_TXE_PKTS and + * %NL80211_ATTR_CQM_TXE_RATE must be satisfied before generating an + * %NL80211_CMD_NOTIFY_CQM. Set to 0 to turn off TX error reporting. + * @NL80211_ATTR_CQM_BEACON_LOSS_EVENT: flag attribute that's set in a beacon + * loss event + * @__NL80211_ATTR_CQM_AFTER_LAST: internal + * @NL80211_ATTR_CQM_MAX: highest key attribute + */ +enum nl80211_attr_cqm { + __NL80211_ATTR_CQM_INVALID, + NL80211_ATTR_CQM_RSSI_THOLD, + NL80211_ATTR_CQM_RSSI_HYST, + NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT, + NL80211_ATTR_CQM_PKT_LOSS_EVENT, + NL80211_ATTR_CQM_TXE_RATE, + NL80211_ATTR_CQM_TXE_PKTS, + NL80211_ATTR_CQM_TXE_INTVL, + NL80211_ATTR_CQM_BEACON_LOSS_EVENT, + + /* keep last */ + __NL80211_ATTR_CQM_AFTER_LAST, + NL80211_ATTR_CQM_MAX = __NL80211_ATTR_CQM_AFTER_LAST - 1 +}; + +/** + * enum nl80211_cqm_rssi_threshold_event - RSSI threshold event + * @NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW: The RSSI level is lower than the + * configured threshold + * @NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH: The RSSI is higher than the + * configured threshold + * @NL80211_CQM_RSSI_BEACON_LOSS_EVENT: (reserved, never sent) + */ +enum nl80211_cqm_rssi_threshold_event { + NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW, + NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH, + NL80211_CQM_RSSI_BEACON_LOSS_EVENT, +}; + + +/** + * enum nl80211_tx_power_setting - TX power adjustment + * @NL80211_TX_POWER_AUTOMATIC: automatically determine transmit power + * @NL80211_TX_POWER_LIMITED: limit TX power by the mBm parameter + * @NL80211_TX_POWER_FIXED: fix TX power to the mBm parameter + */ +enum nl80211_tx_power_setting { + NL80211_TX_POWER_AUTOMATIC, + NL80211_TX_POWER_LIMITED, + NL80211_TX_POWER_FIXED, +}; + +/** + * enum nl80211_packet_pattern_attr - packet pattern attribute + * @__NL80211_PKTPAT_INVALID: invalid number for nested attribute + * @NL80211_PKTPAT_PATTERN: the pattern, values where the mask has + * a zero bit are ignored + * @NL80211_PKTPAT_MASK: pattern mask, must be long enough to have + * a bit for each byte in the pattern. The lowest-order bit corresponds + * to the first byte of the pattern, but the bytes of the pattern are + * in a little-endian-like format, i.e. the 9th byte of the pattern + * corresponds to the lowest-order bit in the second byte of the mask. + * For example: The match 00:xx:00:00:xx:00:00:00:00:xx:xx:xx (where + * xx indicates "don't care") would be represented by a pattern of + * twelve zero bytes, and a mask of "0xed,0x01". + * Note that the pattern matching is done as though frames were not + * 802.11 frames but 802.3 frames, i.e. the frame is fully unpacked + * first (including SNAP header unpacking) and then matched. + * @NL80211_PKTPAT_OFFSET: packet offset, pattern is matched after + * these fixed number of bytes of received packet + * @NUM_NL80211_PKTPAT: number of attributes + * @MAX_NL80211_PKTPAT: max attribute number + */ +enum nl80211_packet_pattern_attr { + __NL80211_PKTPAT_INVALID, + NL80211_PKTPAT_MASK, + NL80211_PKTPAT_PATTERN, + NL80211_PKTPAT_OFFSET, + + NUM_NL80211_PKTPAT, + MAX_NL80211_PKTPAT = NUM_NL80211_PKTPAT - 1, +}; + +/** + * struct nl80211_pattern_support - packet pattern support information + * @max_patterns: maximum number of patterns supported + * @min_pattern_len: minimum length of each pattern + * @max_pattern_len: maximum length of each pattern + * @max_pkt_offset: maximum Rx packet offset + * + * This struct is carried in %NL80211_WOWLAN_TRIG_PKT_PATTERN when + * that is part of %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED or in + * %NL80211_ATTR_COALESCE_RULE_PKT_PATTERN when that is part of + * %NL80211_ATTR_COALESCE_RULE in the capability information given + * by the kernel to userspace. + */ +struct nl80211_pattern_support { + __u32 max_patterns; + __u32 min_pattern_len; + __u32 max_pattern_len; + __u32 max_pkt_offset; +} __attribute__((packed)); + +/* only for backward compatibility */ +#define __NL80211_WOWLAN_PKTPAT_INVALID __NL80211_PKTPAT_INVALID +#define NL80211_WOWLAN_PKTPAT_MASK NL80211_PKTPAT_MASK +#define NL80211_WOWLAN_PKTPAT_PATTERN NL80211_PKTPAT_PATTERN +#define NL80211_WOWLAN_PKTPAT_OFFSET NL80211_PKTPAT_OFFSET +#define NUM_NL80211_WOWLAN_PKTPAT NUM_NL80211_PKTPAT +#define MAX_NL80211_WOWLAN_PKTPAT MAX_NL80211_PKTPAT +#define nl80211_wowlan_pattern_support nl80211_pattern_support + +/** + * enum nl80211_wowlan_triggers - WoWLAN trigger definitions + * @__NL80211_WOWLAN_TRIG_INVALID: invalid number for nested attributes + * @NL80211_WOWLAN_TRIG_ANY: wake up on any activity, do not really put + * the chip into a special state -- works best with chips that have + * support for low-power operation already (flag) + * Note that this mode is incompatible with all of the others, if + * any others are even supported by the device. + * @NL80211_WOWLAN_TRIG_DISCONNECT: wake up on disconnect, the way disconnect + * is detected is implementation-specific (flag) + * @NL80211_WOWLAN_TRIG_MAGIC_PKT: wake up on magic packet (6x 0xff, followed + * by 16 repetitions of MAC addr, anywhere in payload) (flag) + * @NL80211_WOWLAN_TRIG_PKT_PATTERN: wake up on the specified packet patterns + * which are passed in an array of nested attributes, each nested attribute + * defining a with attributes from &struct nl80211_wowlan_trig_pkt_pattern. + * Each pattern defines a wakeup packet. Packet offset is associated with + * each pattern which is used while matching the pattern. The matching is + * done on the MSDU, i.e. as though the packet was an 802.3 packet, so the + * pattern matching is done after the packet is converted to the MSDU. + * + * In %NL80211_ATTR_WOWLAN_TRIGGERS_SUPPORTED, it is a binary attribute + * carrying a &struct nl80211_pattern_support. + * + * When reporting wakeup. it is a u32 attribute containing the 0-based + * index of the pattern that caused the wakeup, in the patterns passed + * to the kernel when configuring. + * @NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED: Not a real trigger, and cannot be + * used when setting, used only to indicate that GTK rekeying is supported + * by the device (flag) + * @NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE: wake up on GTK rekey failure (if + * done by the device) (flag) + * @NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST: wake up on EAP Identity Request + * packet (flag) + * @NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE: wake up on 4-way handshake (flag) + * @NL80211_WOWLAN_TRIG_RFKILL_RELEASE: wake up when rfkill is released + * (on devices that have rfkill in the device) (flag) + * @NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211: For wakeup reporting only, contains + * the 802.11 packet that caused the wakeup, e.g. a deauth frame. The frame + * may be truncated, the @NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211_LEN + * attribute contains the original length. + * @NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211_LEN: Original length of the 802.11 + * packet, may be bigger than the @NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211 + * attribute if the packet was truncated somewhere. + * @NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023: For wakeup reporting only, contains the + * 802.11 packet that caused the wakeup, e.g. a magic packet. The frame may + * be truncated, the @NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023_LEN attribute + * contains the original length. + * @NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023_LEN: Original length of the 802.3 + * packet, may be bigger than the @NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023 + * attribute if the packet was truncated somewhere. + * @NL80211_WOWLAN_TRIG_TCP_CONNECTION: TCP connection wake, see DOC section + * "TCP connection wakeup" for more details. This is a nested attribute + * containing the exact information for establishing and keeping alive + * the TCP connection. + * @NL80211_WOWLAN_TRIG_TCP_WAKEUP_MATCH: For wakeup reporting only, the + * wakeup packet was received on the TCP connection + * @NL80211_WOWLAN_TRIG_WAKEUP_TCP_CONNLOST: For wakeup reporting only, the + * TCP connection was lost or failed to be established + * @NL80211_WOWLAN_TRIG_WAKEUP_TCP_NOMORETOKENS: For wakeup reporting only, + * the TCP connection ran out of tokens to use for data to send to the + * service + * @NL80211_WOWLAN_TRIG_NET_DETECT: wake up when a configured network + * is detected. This is a nested attribute that contains the + * same attributes used with @NL80211_CMD_START_SCHED_SCAN. It + * specifies how the scan is performed (e.g. the interval, the + * channels to scan and the initial delay) as well as the scan + * results that will trigger a wake (i.e. the matchsets). This + * attribute is also sent in a response to + * @NL80211_CMD_GET_WIPHY, indicating the number of match sets + * supported by the driver (u32). + * @NL80211_WOWLAN_TRIG_NET_DETECT_RESULTS: nested attribute + * containing an array with information about what triggered the + * wake up. If no elements are present in the array, it means + * that the information is not available. If more than one + * element is present, it means that more than one match + * occurred. + * Each element in the array is a nested attribute that contains + * one optional %NL80211_ATTR_SSID attribute and one optional + * %NL80211_ATTR_SCAN_FREQUENCIES attribute. At least one of + * these attributes must be present. If + * %NL80211_ATTR_SCAN_FREQUENCIES contains more than one + * frequency, it means that the match occurred in more than one + * channel. + * @NUM_NL80211_WOWLAN_TRIG: number of wake on wireless triggers + * @MAX_NL80211_WOWLAN_TRIG: highest wowlan trigger attribute number + * + * These nested attributes are used to configure the wakeup triggers and + * to report the wakeup reason(s). + */ +enum nl80211_wowlan_triggers { + __NL80211_WOWLAN_TRIG_INVALID, + NL80211_WOWLAN_TRIG_ANY, + NL80211_WOWLAN_TRIG_DISCONNECT, + NL80211_WOWLAN_TRIG_MAGIC_PKT, + NL80211_WOWLAN_TRIG_PKT_PATTERN, + NL80211_WOWLAN_TRIG_GTK_REKEY_SUPPORTED, + NL80211_WOWLAN_TRIG_GTK_REKEY_FAILURE, + NL80211_WOWLAN_TRIG_EAP_IDENT_REQUEST, + NL80211_WOWLAN_TRIG_4WAY_HANDSHAKE, + NL80211_WOWLAN_TRIG_RFKILL_RELEASE, + NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211, + NL80211_WOWLAN_TRIG_WAKEUP_PKT_80211_LEN, + NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023, + NL80211_WOWLAN_TRIG_WAKEUP_PKT_8023_LEN, + NL80211_WOWLAN_TRIG_TCP_CONNECTION, + NL80211_WOWLAN_TRIG_WAKEUP_TCP_MATCH, + NL80211_WOWLAN_TRIG_WAKEUP_TCP_CONNLOST, + NL80211_WOWLAN_TRIG_WAKEUP_TCP_NOMORETOKENS, + NL80211_WOWLAN_TRIG_NET_DETECT, + NL80211_WOWLAN_TRIG_NET_DETECT_RESULTS, + + /* keep last */ + NUM_NL80211_WOWLAN_TRIG, + MAX_NL80211_WOWLAN_TRIG = NUM_NL80211_WOWLAN_TRIG - 1 +}; + +/** + * DOC: TCP connection wakeup + * + * Some devices can establish a TCP connection in order to be woken up by a + * packet coming in from outside their network segment, or behind NAT. If + * configured, the device will establish a TCP connection to the given + * service, and periodically send data to that service. The first data + * packet is usually transmitted after SYN/ACK, also ACKing the SYN/ACK. + * The data packets can optionally include a (little endian) sequence + * number (in the TCP payload!) that is generated by the device, and, also + * optionally, a token from a list of tokens. This serves as a keep-alive + * with the service, and for NATed connections, etc. + * + * During this keep-alive period, the server doesn't send any data to the + * client. When receiving data, it is compared against the wakeup pattern + * (and mask) and if it matches, the host is woken up. Similarly, if the + * connection breaks or cannot be established to start with, the host is + * also woken up. + * + * Developer's note: ARP offload is required for this, otherwise TCP + * response packets might not go through correctly. + */ + +/** + * struct nl80211_wowlan_tcp_data_seq - WoWLAN TCP data sequence + * @start: starting value + * @offset: offset of sequence number in packet + * @len: length of the sequence value to write, 1 through 4 + * + * Note: don't confuse with the TCP sequence number(s), this is for the + * keepalive packet payload. The actual value is written into the packet + * in little endian. + */ +struct nl80211_wowlan_tcp_data_seq { + __u32 start, offset, len; +}; + +/** + * struct nl80211_wowlan_tcp_data_token - WoWLAN TCP data token config + * @offset: offset of token in packet + * @len: length of each token + * @token_stream: stream of data to be used for the tokens, the length must + * be a multiple of @len for this to make sense + */ +struct nl80211_wowlan_tcp_data_token { + __u32 offset, len; + __u8 token_stream[]; +}; + +/** + * struct nl80211_wowlan_tcp_data_token_feature - data token features + * @min_len: minimum token length + * @max_len: maximum token length + * @bufsize: total available token buffer size (max size of @token_stream) + */ +struct nl80211_wowlan_tcp_data_token_feature { + __u32 min_len, max_len, bufsize; +}; + +/** + * enum nl80211_wowlan_tcp_attrs - WoWLAN TCP connection parameters + * @__NL80211_WOWLAN_TCP_INVALID: invalid number for nested attributes + * @NL80211_WOWLAN_TCP_SRC_IPV4: source IPv4 address (in network byte order) + * @NL80211_WOWLAN_TCP_DST_IPV4: destination IPv4 address + * (in network byte order) + * @NL80211_WOWLAN_TCP_DST_MAC: destination MAC address, this is given because + * route lookup when configured might be invalid by the time we suspend, + * and doing a route lookup when suspending is no longer possible as it + * might require ARP querying. + * @NL80211_WOWLAN_TCP_SRC_PORT: source port (u16); optional, if not given a + * socket and port will be allocated + * @NL80211_WOWLAN_TCP_DST_PORT: destination port (u16) + * @NL80211_WOWLAN_TCP_DATA_PAYLOAD: data packet payload, at least one byte. + * For feature advertising, a u32 attribute holding the maximum length + * of the data payload. + * @NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ: data packet sequence configuration + * (if desired), a &struct nl80211_wowlan_tcp_data_seq. For feature + * advertising it is just a flag + * @NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN: data packet token configuration, + * see &struct nl80211_wowlan_tcp_data_token and for advertising see + * &struct nl80211_wowlan_tcp_data_token_feature. + * @NL80211_WOWLAN_TCP_DATA_INTERVAL: data interval in seconds, maximum + * interval in feature advertising (u32) + * @NL80211_WOWLAN_TCP_WAKE_PAYLOAD: wake packet payload, for advertising a + * u32 attribute holding the maximum length + * @NL80211_WOWLAN_TCP_WAKE_MASK: Wake packet payload mask, not used for + * feature advertising. The mask works like @NL80211_PKTPAT_MASK + * but on the TCP payload only. + * @NUM_NL80211_WOWLAN_TCP: number of TCP attributes + * @MAX_NL80211_WOWLAN_TCP: highest attribute number + */ +enum nl80211_wowlan_tcp_attrs { + __NL80211_WOWLAN_TCP_INVALID, + NL80211_WOWLAN_TCP_SRC_IPV4, + NL80211_WOWLAN_TCP_DST_IPV4, + NL80211_WOWLAN_TCP_DST_MAC, + NL80211_WOWLAN_TCP_SRC_PORT, + NL80211_WOWLAN_TCP_DST_PORT, + NL80211_WOWLAN_TCP_DATA_PAYLOAD, + NL80211_WOWLAN_TCP_DATA_PAYLOAD_SEQ, + NL80211_WOWLAN_TCP_DATA_PAYLOAD_TOKEN, + NL80211_WOWLAN_TCP_DATA_INTERVAL, + NL80211_WOWLAN_TCP_WAKE_PAYLOAD, + NL80211_WOWLAN_TCP_WAKE_MASK, + + /* keep last */ + NUM_NL80211_WOWLAN_TCP, + MAX_NL80211_WOWLAN_TCP = NUM_NL80211_WOWLAN_TCP - 1 +}; + +/** + * struct nl80211_coalesce_rule_support - coalesce rule support information + * @max_rules: maximum number of rules supported + * @pat: packet pattern support information + * @max_delay: maximum supported coalescing delay in msecs + * + * This struct is carried in %NL80211_ATTR_COALESCE_RULE in the + * capability information given by the kernel to userspace. + */ +struct nl80211_coalesce_rule_support { + __u32 max_rules; + struct nl80211_pattern_support pat; + __u32 max_delay; +} __attribute__((packed)); + +/** + * enum nl80211_attr_coalesce_rule - coalesce rule attribute + * @__NL80211_COALESCE_RULE_INVALID: invalid number for nested attribute + * @NL80211_ATTR_COALESCE_RULE_DELAY: delay in msecs used for packet coalescing + * @NL80211_ATTR_COALESCE_RULE_CONDITION: condition for packet coalescence, + * see &enum nl80211_coalesce_condition. + * @NL80211_ATTR_COALESCE_RULE_PKT_PATTERN: packet offset, pattern is matched + * after these fixed number of bytes of received packet + * @NUM_NL80211_ATTR_COALESCE_RULE: number of attributes + * @NL80211_ATTR_COALESCE_RULE_MAX: max attribute number + */ +enum nl80211_attr_coalesce_rule { + __NL80211_COALESCE_RULE_INVALID, + NL80211_ATTR_COALESCE_RULE_DELAY, + NL80211_ATTR_COALESCE_RULE_CONDITION, + NL80211_ATTR_COALESCE_RULE_PKT_PATTERN, + + /* keep last */ + NUM_NL80211_ATTR_COALESCE_RULE, + NL80211_ATTR_COALESCE_RULE_MAX = NUM_NL80211_ATTR_COALESCE_RULE - 1 +}; + +/** + * enum nl80211_coalesce_condition - coalesce rule conditions + * @NL80211_COALESCE_CONDITION_MATCH: coalaesce Rx packets when patterns + * in a rule are matched. + * @NL80211_COALESCE_CONDITION_NO_MATCH: coalesce Rx packets when patterns + * in a rule are not matched. + */ +enum nl80211_coalesce_condition { + NL80211_COALESCE_CONDITION_MATCH, + NL80211_COALESCE_CONDITION_NO_MATCH +}; + +/** + * enum nl80211_iface_limit_attrs - limit attributes + * @NL80211_IFACE_LIMIT_UNSPEC: (reserved) + * @NL80211_IFACE_LIMIT_MAX: maximum number of interfaces that + * can be chosen from this set of interface types (u32) + * @NL80211_IFACE_LIMIT_TYPES: nested attribute containing a + * flag attribute for each interface type in this set + * @NUM_NL80211_IFACE_LIMIT: number of attributes + * @MAX_NL80211_IFACE_LIMIT: highest attribute number + */ +enum nl80211_iface_limit_attrs { + NL80211_IFACE_LIMIT_UNSPEC, + NL80211_IFACE_LIMIT_MAX, + NL80211_IFACE_LIMIT_TYPES, + + /* keep last */ + NUM_NL80211_IFACE_LIMIT, + MAX_NL80211_IFACE_LIMIT = NUM_NL80211_IFACE_LIMIT - 1 +}; + +/** + * enum nl80211_if_combination_attrs -- interface combination attributes + * + * @NL80211_IFACE_COMB_UNSPEC: (reserved) + * @NL80211_IFACE_COMB_LIMITS: Nested attributes containing the limits + * for given interface types, see &enum nl80211_iface_limit_attrs. + * @NL80211_IFACE_COMB_MAXNUM: u32 attribute giving the total number of + * interfaces that can be created in this group. This number doesn't + * apply to interfaces purely managed in software, which are listed + * in a separate attribute %NL80211_ATTR_INTERFACES_SOFTWARE. + * @NL80211_IFACE_COMB_STA_AP_BI_MATCH: flag attribute specifying that + * beacon intervals within this group must be all the same even for + * infrastructure and AP/GO combinations, i.e. the GO(s) must adopt + * the infrastructure network's beacon interval. + * @NL80211_IFACE_COMB_NUM_CHANNELS: u32 attribute specifying how many + * different channels may be used within this group. + * @NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS: u32 attribute containing the bitmap + * of supported channel widths for radar detection. + * @NL80211_IFACE_COMB_RADAR_DETECT_REGIONS: u32 attribute containing the bitmap + * of supported regulatory regions for radar detection. + * @NUM_NL80211_IFACE_COMB: number of attributes + * @MAX_NL80211_IFACE_COMB: highest attribute number + * + * Examples: + * limits = [ #{STA} <= 1, #{AP} <= 1 ], matching BI, channels = 1, max = 2 + * => allows an AP and a STA that must match BIs + * + * numbers = [ #{AP, P2P-GO} <= 8 ], channels = 1, max = 8 + * => allows 8 of AP/GO + * + * numbers = [ #{STA} <= 2 ], channels = 2, max = 2 + * => allows two STAs on different channels + * + * numbers = [ #{STA} <= 1, #{P2P-client,P2P-GO} <= 3 ], max = 4 + * => allows a STA plus three P2P interfaces + * + * The list of these four possiblities could completely be contained + * within the %NL80211_ATTR_INTERFACE_COMBINATIONS attribute to indicate + * that any of these groups must match. + * + * "Combinations" of just a single interface will not be listed here, + * a single interface of any valid interface type is assumed to always + * be possible by itself. This means that implicitly, for each valid + * interface type, the following group always exists: + * numbers = [ #{} <= 1 ], channels = 1, max = 1 + */ +enum nl80211_if_combination_attrs { + NL80211_IFACE_COMB_UNSPEC, + NL80211_IFACE_COMB_LIMITS, + NL80211_IFACE_COMB_MAXNUM, + NL80211_IFACE_COMB_STA_AP_BI_MATCH, + NL80211_IFACE_COMB_NUM_CHANNELS, + NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS, + NL80211_IFACE_COMB_RADAR_DETECT_REGIONS, + + /* keep last */ + NUM_NL80211_IFACE_COMB, + MAX_NL80211_IFACE_COMB = NUM_NL80211_IFACE_COMB - 1 +}; + + +/** + * enum nl80211_plink_state - state of a mesh peer link finite state machine + * + * @NL80211_PLINK_LISTEN: initial state, considered the implicit + * state of non existant mesh peer links + * @NL80211_PLINK_OPN_SNT: mesh plink open frame has been sent to + * this mesh peer + * @NL80211_PLINK_OPN_RCVD: mesh plink open frame has been received + * from this mesh peer + * @NL80211_PLINK_CNF_RCVD: mesh plink confirm frame has been + * received from this mesh peer + * @NL80211_PLINK_ESTAB: mesh peer link is established + * @NL80211_PLINK_HOLDING: mesh peer link is being closed or cancelled + * @NL80211_PLINK_BLOCKED: all frames transmitted from this mesh + * plink are discarded + * @NUM_NL80211_PLINK_STATES: number of peer link states + * @MAX_NL80211_PLINK_STATES: highest numerical value of plink states + */ +enum nl80211_plink_state { + NL80211_PLINK_LISTEN, + NL80211_PLINK_OPN_SNT, + NL80211_PLINK_OPN_RCVD, + NL80211_PLINK_CNF_RCVD, + NL80211_PLINK_ESTAB, + NL80211_PLINK_HOLDING, + NL80211_PLINK_BLOCKED, + + /* keep last */ + NUM_NL80211_PLINK_STATES, + MAX_NL80211_PLINK_STATES = NUM_NL80211_PLINK_STATES - 1 +}; + +/** + * enum nl80211_plink_action - actions to perform in mesh peers + * + * @NL80211_PLINK_ACTION_NO_ACTION: perform no action + * @NL80211_PLINK_ACTION_OPEN: start mesh peer link establishment + * @NL80211_PLINK_ACTION_BLOCK: block traffic from this mesh peer + * @NUM_NL80211_PLINK_ACTIONS: number of possible actions + */ +enum plink_actions { + NL80211_PLINK_ACTION_NO_ACTION, + NL80211_PLINK_ACTION_OPEN, + NL80211_PLINK_ACTION_BLOCK, + + NUM_NL80211_PLINK_ACTIONS, +}; + + +#define NL80211_KCK_LEN 16 +#define NL80211_KEK_LEN 16 +#define NL80211_REPLAY_CTR_LEN 8 + +/** + * enum nl80211_rekey_data - attributes for GTK rekey offload + * @__NL80211_REKEY_DATA_INVALID: invalid number for nested attributes + * @NL80211_REKEY_DATA_KEK: key encryption key (binary) + * @NL80211_REKEY_DATA_KCK: key confirmation key (binary) + * @NL80211_REKEY_DATA_REPLAY_CTR: replay counter (binary) + * @NUM_NL80211_REKEY_DATA: number of rekey attributes (internal) + * @MAX_NL80211_REKEY_DATA: highest rekey attribute (internal) + */ +enum nl80211_rekey_data { + __NL80211_REKEY_DATA_INVALID, + NL80211_REKEY_DATA_KEK, + NL80211_REKEY_DATA_KCK, + NL80211_REKEY_DATA_REPLAY_CTR, + + /* keep last */ + NUM_NL80211_REKEY_DATA, + MAX_NL80211_REKEY_DATA = NUM_NL80211_REKEY_DATA - 1 +}; + +/** + * enum nl80211_hidden_ssid - values for %NL80211_ATTR_HIDDEN_SSID + * @NL80211_HIDDEN_SSID_NOT_IN_USE: do not hide SSID (i.e., broadcast it in + * Beacon frames) + * @NL80211_HIDDEN_SSID_ZERO_LEN: hide SSID by using zero-length SSID element + * in Beacon frames + * @NL80211_HIDDEN_SSID_ZERO_CONTENTS: hide SSID by using correct length of SSID + * element in Beacon frames but zero out each byte in the SSID + */ +enum nl80211_hidden_ssid { + NL80211_HIDDEN_SSID_NOT_IN_USE, + NL80211_HIDDEN_SSID_ZERO_LEN, + NL80211_HIDDEN_SSID_ZERO_CONTENTS +}; + +/** + * enum nl80211_sta_wme_attr - station WME attributes + * @__NL80211_STA_WME_INVALID: invalid number for nested attribute + * @NL80211_STA_WME_UAPSD_QUEUES: bitmap of uapsd queues. the format + * is the same as the AC bitmap in the QoS info field. + * @NL80211_STA_WME_MAX_SP: max service period. the format is the same + * as the MAX_SP field in the QoS info field (but already shifted down). + * @__NL80211_STA_WME_AFTER_LAST: internal + * @NL80211_STA_WME_MAX: highest station WME attribute + */ +enum nl80211_sta_wme_attr { + __NL80211_STA_WME_INVALID, + NL80211_STA_WME_UAPSD_QUEUES, + NL80211_STA_WME_MAX_SP, + + /* keep last */ + __NL80211_STA_WME_AFTER_LAST, + NL80211_STA_WME_MAX = __NL80211_STA_WME_AFTER_LAST - 1 +}; + +/** + * enum nl80211_pmksa_candidate_attr - attributes for PMKSA caching candidates + * @__NL80211_PMKSA_CANDIDATE_INVALID: invalid number for nested attributes + * @NL80211_PMKSA_CANDIDATE_INDEX: candidate index (u32; the smaller, the higher + * priority) + * @NL80211_PMKSA_CANDIDATE_BSSID: candidate BSSID (6 octets) + * @NL80211_PMKSA_CANDIDATE_PREAUTH: RSN pre-authentication supported (flag) + * @NUM_NL80211_PMKSA_CANDIDATE: number of PMKSA caching candidate attributes + * (internal) + * @MAX_NL80211_PMKSA_CANDIDATE: highest PMKSA caching candidate attribute + * (internal) + */ +enum nl80211_pmksa_candidate_attr { + __NL80211_PMKSA_CANDIDATE_INVALID, + NL80211_PMKSA_CANDIDATE_INDEX, + NL80211_PMKSA_CANDIDATE_BSSID, + NL80211_PMKSA_CANDIDATE_PREAUTH, + + /* keep last */ + NUM_NL80211_PMKSA_CANDIDATE, + MAX_NL80211_PMKSA_CANDIDATE = NUM_NL80211_PMKSA_CANDIDATE - 1 +}; + +/** + * enum nl80211_tdls_operation - values for %NL80211_ATTR_TDLS_OPERATION + * @NL80211_TDLS_DISCOVERY_REQ: Send a TDLS discovery request + * @NL80211_TDLS_SETUP: Setup TDLS link + * @NL80211_TDLS_TEARDOWN: Teardown a TDLS link which is already established + * @NL80211_TDLS_ENABLE_LINK: Enable TDLS link + * @NL80211_TDLS_DISABLE_LINK: Disable TDLS link + */ +enum nl80211_tdls_operation { + NL80211_TDLS_DISCOVERY_REQ, + NL80211_TDLS_SETUP, + NL80211_TDLS_TEARDOWN, + NL80211_TDLS_ENABLE_LINK, + NL80211_TDLS_DISABLE_LINK, +}; + +/* + * enum nl80211_ap_sme_features - device-integrated AP features + * Reserved for future use, no bits are defined in + * NL80211_ATTR_DEVICE_AP_SME yet. +enum nl80211_ap_sme_features { +}; + */ + +/** + * enum nl80211_feature_flags - device/driver features + * @NL80211_FEATURE_SK_TX_STATUS: This driver supports reflecting back + * TX status to the socket error queue when requested with the + * socket option. + * @NL80211_FEATURE_HT_IBSS: This driver supports IBSS with HT datarates. + * @NL80211_FEATURE_INACTIVITY_TIMER: This driver takes care of freeing up + * the connected inactive stations in AP mode. + * @NL80211_FEATURE_CELL_BASE_REG_HINTS: This driver has been tested + * to work properly to suppport receiving regulatory hints from + * cellular base stations. + * @NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL: (no longer available, only + * here to reserve the value for API/ABI compatibility) + * @NL80211_FEATURE_SAE: This driver supports simultaneous authentication of + * equals (SAE) with user space SME (NL80211_CMD_AUTHENTICATE) in station + * mode + * @NL80211_FEATURE_LOW_PRIORITY_SCAN: This driver supports low priority scan + * @NL80211_FEATURE_SCAN_FLUSH: Scan flush is supported + * @NL80211_FEATURE_AP_SCAN: Support scanning using an AP vif + * @NL80211_FEATURE_VIF_TXPOWER: The driver supports per-vif TX power setting + * @NL80211_FEATURE_NEED_OBSS_SCAN: The driver expects userspace to perform + * OBSS scans and generate 20/40 BSS coex reports. This flag is used only + * for drivers implementing the CONNECT API, for AUTH/ASSOC it is implied. + * @NL80211_FEATURE_P2P_GO_CTWIN: P2P GO implementation supports CT Window + * setting + * @NL80211_FEATURE_P2P_GO_OPPPS: P2P GO implementation supports opportunistic + * powersave + * @NL80211_FEATURE_FULL_AP_CLIENT_STATE: The driver supports full state + * transitions for AP clients. Without this flag (and if the driver + * doesn't have the AP SME in the device) the driver supports adding + * stations only when they're associated and adds them in associated + * state (to later be transitioned into authorized), with this flag + * they should be added before even sending the authentication reply + * and then transitioned into authenticated, associated and authorized + * states using station flags. + * Note that even for drivers that support this, the default is to add + * stations in authenticated/associated state, so to add unauthenticated + * stations the authenticated/associated bits have to be set in the mask. + * @NL80211_FEATURE_ADVERTISE_CHAN_LIMITS: cfg80211 advertises channel limits + * (HT40, VHT 80/160 MHz) if this flag is set + * @NL80211_FEATURE_USERSPACE_MPM: This driver supports a userspace Mesh + * Peering Management entity which may be implemented by registering for + * beacons or NL80211_CMD_NEW_PEER_CANDIDATE events. The mesh beacon is + * still generated by the driver. + * @NL80211_FEATURE_ACTIVE_MONITOR: This driver supports an active monitor + * interface. An active monitor interface behaves like a normal monitor + * interface, but gets added to the driver. It ensures that incoming + * unicast packets directed at the configured interface address get ACKed. + * @NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE: This driver supports dynamic + * channel bandwidth change (e.g., HT 20 <-> 40 MHz channel) during the + * lifetime of a BSS. + * @NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES: This device adds a DS Parameter + * Set IE to probe requests. + * @NL80211_FEATURE_WFA_TPC_IE_IN_PROBES: This device adds a WFA TPC Report IE + * to probe requests. + * @NL80211_FEATURE_QUIET: This device, in client mode, supports Quiet Period + * requests sent to it by an AP. + * @NL80211_FEATURE_TX_POWER_INSERTION: This device is capable of inserting the + * current tx power value into the TPC Report IE in the spectrum + * management TPC Report action frame, and in the Radio Measurement Link + * Measurement Report action frame. + * @NL80211_FEATURE_ACKTO_ESTIMATION: This driver supports dynamic ACK timeout + * estimation (dynack). %NL80211_ATTR_WIPHY_DYN_ACK flag attribute is used + * to enable dynack. + * @NL80211_FEATURE_STATIC_SMPS: Device supports static spatial + * multiplexing powersave, ie. can turn off all but one chain + * even on HT connections that should be using more chains. + * @NL80211_FEATURE_DYNAMIC_SMPS: Device supports dynamic spatial + * multiplexing powersave, ie. can turn off all but one chain + * and then wake the rest up as required after, for example, + * rts/cts handshake. + * @NL80211_FEATURE_SUPPORTS_WMM_ADMISSION: the device supports setting up WMM + * TSPEC sessions (TID aka TSID 0-7) with the %NL80211_CMD_ADD_TX_TS + * command. Standard IEEE 802.11 TSPEC setup is not yet supported, it + * needs to be able to handle Block-Ack agreements and other things. + * @NL80211_FEATURE_MAC_ON_CREATE: Device supports configuring + * the vif's MAC address upon creation. + * See 'macaddr' field in the vif_params (cfg80211.h). + * @NL80211_FEATURE_TDLS_CHANNEL_SWITCH: Driver supports channel switching when + * operating as a TDLS peer. + * @NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR: This device/driver supports using a + * random MAC address during scan (if the device is unassociated); the + * %NL80211_SCAN_FLAG_RANDOM_ADDR flag may be set for scans and the MAC + * address mask/value will be used. + * @NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR: This device/driver supports + * using a random MAC address for every scan iteration during scheduled + * scan (while not associated), the %NL80211_SCAN_FLAG_RANDOM_ADDR may + * be set for scheduled scan and the MAC address mask/value will be used. + * @NL80211_FEATURE_ND_RANDOM_MAC_ADDR: This device/driver supports using a + * random MAC address for every scan iteration during "net detect", i.e. + * scan in unassociated WoWLAN, the %NL80211_SCAN_FLAG_RANDOM_ADDR may + * be set for scheduled scan and the MAC address mask/value will be used. + */ +enum nl80211_feature_flags { + NL80211_FEATURE_SK_TX_STATUS = 1 << 0, + NL80211_FEATURE_HT_IBSS = 1 << 1, + NL80211_FEATURE_INACTIVITY_TIMER = 1 << 2, + NL80211_FEATURE_CELL_BASE_REG_HINTS = 1 << 3, + NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL = 1 << 4, + NL80211_FEATURE_SAE = 1 << 5, + NL80211_FEATURE_LOW_PRIORITY_SCAN = 1 << 6, + NL80211_FEATURE_SCAN_FLUSH = 1 << 7, + NL80211_FEATURE_AP_SCAN = 1 << 8, + NL80211_FEATURE_VIF_TXPOWER = 1 << 9, + NL80211_FEATURE_NEED_OBSS_SCAN = 1 << 10, + NL80211_FEATURE_P2P_GO_CTWIN = 1 << 11, + NL80211_FEATURE_P2P_GO_OPPPS = 1 << 12, + /* bit 13 is reserved */ + NL80211_FEATURE_ADVERTISE_CHAN_LIMITS = 1 << 14, + NL80211_FEATURE_FULL_AP_CLIENT_STATE = 1 << 15, + NL80211_FEATURE_USERSPACE_MPM = 1 << 16, + NL80211_FEATURE_ACTIVE_MONITOR = 1 << 17, + NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE = 1 << 18, + NL80211_FEATURE_DS_PARAM_SET_IE_IN_PROBES = 1 << 19, + NL80211_FEATURE_WFA_TPC_IE_IN_PROBES = 1 << 20, + NL80211_FEATURE_QUIET = 1 << 21, + NL80211_FEATURE_TX_POWER_INSERTION = 1 << 22, + NL80211_FEATURE_ACKTO_ESTIMATION = 1 << 23, + NL80211_FEATURE_STATIC_SMPS = 1 << 24, + NL80211_FEATURE_DYNAMIC_SMPS = 1 << 25, + NL80211_FEATURE_SUPPORTS_WMM_ADMISSION = 1 << 26, + NL80211_FEATURE_MAC_ON_CREATE = 1 << 27, + NL80211_FEATURE_TDLS_CHANNEL_SWITCH = 1 << 28, + NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR = 1 << 29, + NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR = 1 << 30, + NL80211_FEATURE_ND_RANDOM_MAC_ADDR = 1 << 31, +}; + +/** + * enum nl80211_ext_feature_index - bit index of extended features. + * @NL80211_EXT_FEATURE_VHT_IBSS: This driver supports IBSS with VHT datarates. + * + * @NUM_NL80211_EXT_FEATURES: number of extended features. + * @MAX_NL80211_EXT_FEATURES: highest extended feature index. + */ +enum nl80211_ext_feature_index { + NL80211_EXT_FEATURE_VHT_IBSS, + + /* add new features before the definition below */ + NUM_NL80211_EXT_FEATURES, + MAX_NL80211_EXT_FEATURES = NUM_NL80211_EXT_FEATURES - 1 +}; + +/** + * enum nl80211_probe_resp_offload_support_attr - optional supported + * protocols for probe-response offloading by the driver/FW. + * To be used with the %NL80211_ATTR_PROBE_RESP_OFFLOAD attribute. + * Each enum value represents a bit in the bitmap of supported + * protocols. Typically a subset of probe-requests belonging to a + * supported protocol will be excluded from offload and uploaded + * to the host. + * + * @NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS: Support for WPS ver. 1 + * @NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2: Support for WPS ver. 2 + * @NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P: Support for P2P + * @NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U: Support for 802.11u + */ +enum nl80211_probe_resp_offload_support_attr { + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS = 1<<0, + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 = 1<<1, + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P = 1<<2, + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_80211U = 1<<3, +}; + +/** + * enum nl80211_connect_failed_reason - connection request failed reasons + * @NL80211_CONN_FAIL_MAX_CLIENTS: Maximum number of clients that can be + * handled by the AP is reached. + * @NL80211_CONN_FAIL_BLOCKED_CLIENT: Connection request is rejected due to ACL. + */ +enum nl80211_connect_failed_reason { + NL80211_CONN_FAIL_MAX_CLIENTS, + NL80211_CONN_FAIL_BLOCKED_CLIENT, +}; + +/** + * enum nl80211_scan_flags - scan request control flags + * + * Scan request control flags are used to control the handling + * of NL80211_CMD_TRIGGER_SCAN and NL80211_CMD_START_SCHED_SCAN + * requests. + * + * @NL80211_SCAN_FLAG_LOW_PRIORITY: scan request has low priority + * @NL80211_SCAN_FLAG_FLUSH: flush cache before scanning + * @NL80211_SCAN_FLAG_AP: force a scan even if the interface is configured + * as AP and the beaconing has already been configured. This attribute is + * dangerous because will destroy stations performance as a lot of frames + * will be lost while scanning off-channel, therefore it must be used only + * when really needed + * @NL80211_SCAN_FLAG_RANDOM_ADDR: use a random MAC address for this scan (or + * for scheduled scan: a different one for every scan iteration). When the + * flag is set, depending on device capabilities the @NL80211_ATTR_MAC and + * @NL80211_ATTR_MAC_MASK attributes may also be given in which case only + * the masked bits will be preserved from the MAC address and the remainder + * randomised. If the attributes are not given full randomisation (46 bits, + * locally administered 1, multicast 0) is assumed. + * This flag must not be requested when the feature isn't supported, check + * the nl80211 feature flags for the device. + */ +enum nl80211_scan_flags { + NL80211_SCAN_FLAG_LOW_PRIORITY = 1<<0, + NL80211_SCAN_FLAG_FLUSH = 1<<1, + NL80211_SCAN_FLAG_AP = 1<<2, + NL80211_SCAN_FLAG_RANDOM_ADDR = 1<<3, +}; + +/** + * enum nl80211_acl_policy - access control policy + * + * Access control policy is applied on a MAC list set by + * %NL80211_CMD_START_AP and %NL80211_CMD_SET_MAC_ACL, to + * be used with %NL80211_ATTR_ACL_POLICY. + * + * @NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED: Deny stations which are + * listed in ACL, i.e. allow all the stations which are not listed + * in ACL to authenticate. + * @NL80211_ACL_POLICY_DENY_UNLESS_LISTED: Allow the stations which are listed + * in ACL, i.e. deny all the stations which are not listed in ACL. + */ +enum nl80211_acl_policy { + NL80211_ACL_POLICY_ACCEPT_UNLESS_LISTED, + NL80211_ACL_POLICY_DENY_UNLESS_LISTED, +}; + +/** + * enum nl80211_smps_mode - SMPS mode + * + * Requested SMPS mode (for AP mode) + * + * @NL80211_SMPS_OFF: SMPS off (use all antennas). + * @NL80211_SMPS_STATIC: static SMPS (use a single antenna) + * @NL80211_SMPS_DYNAMIC: dynamic smps (start with a single antenna and + * turn on other antennas after CTS/RTS). + */ +enum nl80211_smps_mode { + NL80211_SMPS_OFF, + NL80211_SMPS_STATIC, + NL80211_SMPS_DYNAMIC, + + __NL80211_SMPS_AFTER_LAST, + NL80211_SMPS_MAX = __NL80211_SMPS_AFTER_LAST - 1 +}; + +/** + * enum nl80211_radar_event - type of radar event for DFS operation + * + * Type of event to be used with NL80211_ATTR_RADAR_EVENT to inform userspace + * about detected radars or success of the channel available check (CAC) + * + * @NL80211_RADAR_DETECTED: A radar pattern has been detected. The channel is + * now unusable. + * @NL80211_RADAR_CAC_FINISHED: Channel Availability Check has been finished, + * the channel is now available. + * @NL80211_RADAR_CAC_ABORTED: Channel Availability Check has been aborted, no + * change to the channel status. + * @NL80211_RADAR_NOP_FINISHED: The Non-Occupancy Period for this channel is + * over, channel becomes usable. + */ +enum nl80211_radar_event { + NL80211_RADAR_DETECTED, + NL80211_RADAR_CAC_FINISHED, + NL80211_RADAR_CAC_ABORTED, + NL80211_RADAR_NOP_FINISHED, +}; + +/** + * enum nl80211_dfs_state - DFS states for channels + * + * Channel states used by the DFS code. + * + * @NL80211_DFS_USABLE: The channel can be used, but channel availability + * check (CAC) must be performed before using it for AP or IBSS. + * @NL80211_DFS_UNAVAILABLE: A radar has been detected on this channel, it + * is therefore marked as not available. + * @NL80211_DFS_AVAILABLE: The channel has been CAC checked and is available. + */ +enum nl80211_dfs_state { + NL80211_DFS_USABLE, + NL80211_DFS_UNAVAILABLE, + NL80211_DFS_AVAILABLE, +}; + +/** + * enum enum nl80211_protocol_features - nl80211 protocol features + * @NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP: nl80211 supports splitting + * wiphy dumps (if requested by the application with the attribute + * %NL80211_ATTR_SPLIT_WIPHY_DUMP. Also supported is filtering the + * wiphy dump by %NL80211_ATTR_WIPHY, %NL80211_ATTR_IFINDEX or + * %NL80211_ATTR_WDEV. + */ +enum nl80211_protocol_features { + NL80211_PROTOCOL_FEATURE_SPLIT_WIPHY_DUMP = 1 << 0, +}; + +/** + * enum nl80211_crit_proto_id - nl80211 critical protocol identifiers + * + * @NL80211_CRIT_PROTO_UNSPEC: protocol unspecified. + * @NL80211_CRIT_PROTO_DHCP: BOOTP or DHCPv6 protocol. + * @NL80211_CRIT_PROTO_EAPOL: EAPOL protocol. + * @NL80211_CRIT_PROTO_APIPA: APIPA protocol. + * @NUM_NL80211_CRIT_PROTO: must be kept last. + */ +enum nl80211_crit_proto_id { + NL80211_CRIT_PROTO_UNSPEC, + NL80211_CRIT_PROTO_DHCP, + NL80211_CRIT_PROTO_EAPOL, + NL80211_CRIT_PROTO_APIPA, + /* add other protocols before this one */ + NUM_NL80211_CRIT_PROTO +}; + +/* maximum duration for critical protocol measures */ +#define NL80211_CRIT_PROTO_MAX_DURATION 5000 /* msec */ + +/** + * enum nl80211_rxmgmt_flags - flags for received management frame. + * + * Used by cfg80211_rx_mgmt() + * + * @NL80211_RXMGMT_FLAG_ANSWERED: frame was answered by device/driver. + */ +enum nl80211_rxmgmt_flags { + NL80211_RXMGMT_FLAG_ANSWERED = 1 << 0, +}; + +/* + * If this flag is unset, the lower 24 bits are an OUI, if set + * a Linux nl80211 vendor ID is used (no such IDs are allocated + * yet, so that's not valid so far) + */ +#define NL80211_VENDOR_ID_IS_LINUX 0x80000000 + +/** + * struct nl80211_vendor_cmd_info - vendor command data + * @vendor_id: If the %NL80211_VENDOR_ID_IS_LINUX flag is clear, then the + * value is a 24-bit OUI; if it is set then a separately allocated ID + * may be used, but no such IDs are allocated yet. New IDs should be + * added to this file when needed. + * @subcmd: sub-command ID for the command + */ +struct nl80211_vendor_cmd_info { + __u32 vendor_id; + __u32 subcmd; +}; + +/** + * enum nl80211_tdls_peer_capability - TDLS peer flags. + * + * Used by tdls_mgmt() to determine which conditional elements need + * to be added to TDLS Setup frames. + * + * @NL80211_TDLS_PEER_HT: TDLS peer is HT capable. + * @NL80211_TDLS_PEER_VHT: TDLS peer is VHT capable. + * @NL80211_TDLS_PEER_WMM: TDLS peer is WMM capable. + */ +enum nl80211_tdls_peer_capability { + NL80211_TDLS_PEER_HT = 1<<0, + NL80211_TDLS_PEER_VHT = 1<<1, + NL80211_TDLS_PEER_WMM = 1<<2, +}; + +#endif /* __LINUX_NL80211_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/drivers/priv_netlink.h b/beken_os/beken378/func/hostapd-2.5/src/drivers/priv_netlink.h new file mode 100755 index 0000000..d3f091c --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/drivers/priv_netlink.h @@ -0,0 +1,109 @@ +/* + * wpa_supplicant - Private copy of Linux netlink/rtnetlink definitions. + * Copyright (c) 2003-2005, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef PRIV_NETLINK_H +#define PRIV_NETLINK_H + +/* + * This should be replaced with user space header once one is available with C + * library, etc.. + */ + +#ifndef IFF_LOWER_UP +#define IFF_LOWER_UP 0x10000 /* driver signals L1 up */ +#endif +#ifndef IFF_DORMANT +#define IFF_DORMANT 0x20000 /* driver signals dormant */ +#endif + +#ifndef IFLA_IFNAME +#define IFLA_IFNAME 3 +#endif +#ifndef IFLA_WIRELESS +#define IFLA_WIRELESS 11 +#endif +#ifndef IFLA_OPERSTATE +#define IFLA_OPERSTATE 16 +#endif +#ifndef IFLA_LINKMODE +#define IFLA_LINKMODE 17 +#define IF_OPER_DORMANT 5 +#define IF_OPER_UP 6 +#endif + +#define NLM_F_REQUEST 1 + +#define NETLINK_ROUTE 0 +#define RTMGRP_LINK 1 +#define RTM_BASE 0x10 +#define RTM_NEWLINK (RTM_BASE + 0) +#define RTM_DELLINK (RTM_BASE + 1) +#define RTM_SETLINK (RTM_BASE + 3) + +#define NLMSG_ALIGNTO 4 +#define NLMSG_ALIGN(len) (((len) + NLMSG_ALIGNTO - 1) & ~(NLMSG_ALIGNTO - 1)) +#define NLMSG_HDRLEN ((int) NLMSG_ALIGN(sizeof(struct nlmsghdr))) +#define NLMSG_LENGTH(len) ((len) + NLMSG_ALIGN(sizeof(struct nlmsghdr))) +#define NLMSG_SPACE(len) NLMSG_ALIGN(NLMSG_LENGTH(len)) +#define NLMSG_DATA(nlh) ((void*) (((char*) nlh) + NLMSG_LENGTH(0))) +#define NLMSG_NEXT(nlh,len) ((len) -= NLMSG_ALIGN((nlh)->nlmsg_len), \ + (struct nlmsghdr *) \ + (((char *)(nlh)) + NLMSG_ALIGN((nlh)->nlmsg_len))) +#define NLMSG_OK(nlh,len) ((len) >= (int) sizeof(struct nlmsghdr) && \ + (nlh)->nlmsg_len >= sizeof(struct nlmsghdr) && \ + (int) (nlh)->nlmsg_len <= (len)) +#define NLMSG_PAYLOAD(nlh,len) ((nlh)->nlmsg_len - NLMSG_SPACE((len))) + +#define RTA_ALIGNTO 4 +#define RTA_ALIGN(len) (((len) + RTA_ALIGNTO - 1) & ~(RTA_ALIGNTO - 1)) +#define RTA_OK(rta,len) \ +((len) > 0 && (rta)->rta_len >= sizeof(struct rtattr) && \ +(rta)->rta_len <= (len)) +#define RTA_NEXT(rta,attrlen) \ +((attrlen) -= RTA_ALIGN((rta)->rta_len), \ +(struct rtattr *) (((char *)(rta)) + RTA_ALIGN((rta)->rta_len))) +#define RTA_LENGTH(len) (RTA_ALIGN(sizeof(struct rtattr)) + (len)) +#define RTA_SPACE(len) RTA_ALIGN(RTA_LENGTH(len)) +#define RTA_DATA(rta) ((void *) (((char *) (rta)) + RTA_LENGTH(0))) +#define RTA_PAYLOAD(rta) ((int) ((rta)->rta_len) - RTA_LENGTH(0)) + + +struct sockaddr_nl +{ + sa_family_t nl_family; + unsigned short nl_pad; + u32 nl_pid; + u32 nl_groups; +}; + +struct nlmsghdr +{ + u32 nlmsg_len; + u16 nlmsg_type; + u16 nlmsg_flags; + u32 nlmsg_seq; + u32 nlmsg_pid; +}; + +struct ifinfomsg +{ + unsigned char ifi_family; + unsigned char __ifi_pad; + unsigned short ifi_type; + int ifi_index; + unsigned ifi_flags; + unsigned ifi_change; +}; + +struct rtattr +{ + unsigned short rta_len; + unsigned short rta_type; +}; + +#endif /* PRIV_NETLINK_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/eapol_supp/eapol_supp_sm.h b/beken_os/beken378/func/hostapd-2.5/src/eapol_supp/eapol_supp_sm.h new file mode 100755 index 0000000..0433881 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/eapol_supp/eapol_supp_sm.h @@ -0,0 +1,424 @@ +/* + * EAPOL supplicant state machines + * Copyright (c) 2004-2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef EAPOL_SUPP_SM_H +#define EAPOL_SUPP_SM_H + +#include "common/defs.h" + +typedef enum { Unauthorized, Authorized } PortStatus; +typedef enum { Auto, ForceUnauthorized, ForceAuthorized } PortControl; + +/** + * struct eapol_config - Per network configuration for EAPOL state machines + */ +struct eapol_config { + /** + * accept_802_1x_keys - Accept IEEE 802.1X (non-WPA) EAPOL-Key frames + * + * This variable should be set to 1 when using EAPOL state machines + * with non-WPA security policy to generate dynamic WEP keys. When + * using WPA, this should be set to 0 so that WPA state machine can + * process the EAPOL-Key frames. + */ + int accept_802_1x_keys; + +#define EAPOL_REQUIRE_KEY_UNICAST BIT(0) +#define EAPOL_REQUIRE_KEY_BROADCAST BIT(1) + /** + * required_keys - Which EAPOL-Key packets are required + * + * This variable determines which EAPOL-Key packets are required before + * marking connection authenticated. This is a bit field of + * EAPOL_REQUIRE_KEY_UNICAST and EAPOL_REQUIRE_KEY_BROADCAST flags. + */ + int required_keys; + + /** + * fast_reauth - Whether fast EAP reauthentication is enabled + */ + int fast_reauth; + + /** + * workaround - Whether EAP workarounds are enabled + */ + unsigned int workaround; + + /** + * eap_disabled - Whether EAP is disabled + */ + int eap_disabled; + + /** + * external_sim - Use external processing for SIM/USIM operations + */ + int external_sim; + +#define EAPOL_LOCAL_WPS_IN_USE BIT(0) +#define EAPOL_PEER_IS_WPS20_AP BIT(1) + /** + * wps - Whether this connection is used for WPS + */ + int wps; +}; + +struct eapol_sm; +struct wpa_config_blob; + +enum eapol_supp_result { + EAPOL_SUPP_RESULT_FAILURE, + EAPOL_SUPP_RESULT_SUCCESS, + EAPOL_SUPP_RESULT_EXPECTED_FAILURE +}; + +/** + * struct eapol_ctx - Global (for all networks) EAPOL state machine context + */ +struct eapol_ctx { + /** + * ctx - Pointer to arbitrary upper level context + */ + void *ctx; + + /** + * preauth - IEEE 802.11i/RSN pre-authentication + * + * This EAPOL state machine is used for IEEE 802.11i/RSN + * pre-authentication + */ + int preauth; + + /** + * cb - Function to be called when EAPOL negotiation has been completed + * @eapol: Pointer to EAPOL state machine data + * @result: Whether the authentication was completed successfully + * @ctx: Pointer to context data (cb_ctx) + * + * This optional callback function will be called when the EAPOL + * authentication has been completed. This allows the owner of the + * EAPOL state machine to process the key and terminate the EAPOL state + * machine. Currently, this is used only in RSN pre-authentication. + */ + void (*cb)(struct eapol_sm *eapol, enum eapol_supp_result result, + void *ctx); + + /** + * cb_ctx - Callback context for cb() + */ + void *cb_ctx; + + /** + * msg_ctx - Callback context for wpa_msg() calls + */ + void *msg_ctx; + + /** + * scard_ctx - Callback context for PC/SC scard_*() function calls + * + * This context can be updated with eapol_sm_register_scard_ctx(). + */ + void *scard_ctx; + + /** + * eapol_send_ctx - Callback context for eapol_send() calls + */ + void *eapol_send_ctx; + + /** + * eapol_done_cb - Function to be called at successful completion + * @ctx: Callback context (ctx) + * + * This function is called at the successful completion of EAPOL + * authentication. If dynamic WEP keys are used, this is called only + * after all the expected keys have been received. + */ + void (*eapol_done_cb)(void *ctx); + + /** + * eapol_send - Send EAPOL packets + * @ctx: Callback context (eapol_send_ctx) + * @type: EAPOL type (IEEE802_1X_TYPE_*) + * @buf: Pointer to EAPOL payload + * @len: Length of the EAPOL payload + * Returns: 0 on success, -1 on failure + */ + int (*eapol_send)(void *ctx, int type, const u8 *buf, size_t len); + + /** + * set_wep_key - Configure WEP keys + * @ctx: Callback context (ctx) + * @unicast: Non-zero = unicast, 0 = multicast/broadcast key + * @keyidx: Key index (0..3) + * @key: WEP key + * @keylen: Length of the WEP key + * Returns: 0 on success, -1 on failure + */ + int (*set_wep_key)(void *ctx, int unicast, int keyidx, + const u8 *key, size_t keylen); + + /** + * aborted_cached - Notify that cached PMK attempt was aborted + * @ctx: Callback context (ctx) + */ + void (*aborted_cached)(void *ctx); + + /** + * opensc_engine_path - Path to the OpenSSL engine for opensc + * + * This is an OpenSSL specific configuration option for loading OpenSC + * engine (engine_opensc.so); if %NULL, this engine is not loaded. + */ + const char *opensc_engine_path; + + /** + * pkcs11_engine_path - Path to the OpenSSL engine for PKCS#11 + * + * This is an OpenSSL specific configuration option for loading PKCS#11 + * engine (engine_pkcs11.so); if %NULL, this engine is not loaded. + */ + const char *pkcs11_engine_path; + + /** + * pkcs11_module_path - Path to the OpenSSL OpenSC/PKCS#11 module + * + * This is an OpenSSL specific configuration option for configuring + * path to OpenSC/PKCS#11 engine (opensc-pkcs11.so); if %NULL, this + * module is not loaded. + */ + const char *pkcs11_module_path; + + /** + * openssl_ciphers - OpenSSL cipher string + * + * This is an OpenSSL specific configuration option for configuring the + * default ciphers. If not set, "DEFAULT:!EXP:!LOW" is used as the + * default. + */ + const char *openssl_ciphers; + + /** + * wps - WPS context data + * + * This is only used by EAP-WSC and can be left %NULL if not available. + */ + struct wps_context *wps; + + /** + * eap_param_needed - Notify that EAP parameter is needed + * @ctx: Callback context (ctx) + * @field: Field indicator (e.g., WPA_CTRL_REQ_EAP_IDENTITY) + * @txt: User readable text describing the required parameter + */ + void (*eap_param_needed)(void *ctx, enum wpa_ctrl_req_type field, + const char *txt); + + /** + * port_cb - Set port authorized/unauthorized callback (optional) + * @ctx: Callback context (ctx) + * @authorized: Whether the supplicant port is now in authorized state + */ + void (*port_cb)(void *ctx, int authorized); + + /** + * cert_cb - Notification of a peer certificate + * @ctx: Callback context (ctx) + * @depth: Depth in certificate chain (0 = server) + * @subject: Subject of the peer certificate + * @altsubject: Select fields from AltSubject of the peer certificate + * @num_altsubject: Number of altsubject values + * @cert_hash: SHA-256 hash of the certificate + * @cert: Peer certificate + */ + void (*cert_cb)(void *ctx, int depth, const char *subject, + const char *altsubject[], int num_altsubject, + const char *cert_hash, const struct wpabuf *cert); + + /** + * cert_in_cb - Include server certificates in callback + */ + int cert_in_cb; + + /** + * status_cb - Notification of a change in EAP status + * @ctx: Callback context (ctx) + * @status: Step in the process of EAP authentication + * @parameter: Step-specific parameter, e.g., EAP method name + */ + void (*status_cb)(void *ctx, const char *status, + const char *parameter); + +#ifdef CONFIG_EAP_PROXY + /** + * eap_proxy_cb - Callback signifying any updates from eap_proxy + * @ctx: eapol_ctx from eap_peer_sm_init() call + */ + void (*eap_proxy_cb)(void *ctx); +#endif /* CONFIG_EAP_PROXY */ + + /** + * set_anon_id - Set or add anonymous identity + * @ctx: eapol_ctx from eap_peer_sm_init() call + * @id: Anonymous identity (e.g., EAP-SIM pseudonym) + * @len: Length of anonymous identity in octets + */ + void (*set_anon_id)(void *ctx, const u8 *id, size_t len); +}; + + +struct eap_peer_config; +struct ext_password_data; + +#ifdef IEEE8021X_EAPOL +struct eapol_sm *eapol_sm_init(struct eapol_ctx *ctx); +void eapol_sm_deinit(struct eapol_sm *sm); +void eapol_sm_step(struct eapol_sm *sm); +int eapol_sm_get_status(struct eapol_sm *sm, char *buf, size_t buflen, + int verbose); +int eapol_sm_get_mib(struct eapol_sm *sm, char *buf, size_t buflen); +void eapol_sm_configure(struct eapol_sm *sm, int heldPeriod, int authPeriod, + int startPeriod, int maxStart); +int eapol_sm_rx_eapol(struct eapol_sm *sm, const u8 *src, const u8 *buf, + size_t len); +void eapol_sm_notify_tx_eapol_key(struct eapol_sm *sm); +void eapol_sm_notify_portEnabled(struct eapol_sm *sm, Boolean enabled); +void eapol_sm_notify_portValid(struct eapol_sm *sm, Boolean valid); +void eapol_sm_notify_eap_success(struct eapol_sm *sm, Boolean success); +void eapol_sm_notify_eap_fail(struct eapol_sm *sm, Boolean fail); +void eapol_sm_notify_config(struct eapol_sm *sm, + struct eap_peer_config *config, + const struct eapol_config *conf); +int eapol_sm_get_key(struct eapol_sm *sm, u8 *key, size_t len); +const u8 * eapol_sm_get_session_id(struct eapol_sm *sm, size_t *len); +void eapol_sm_notify_logoff(struct eapol_sm *sm, Boolean logoff); +void eapol_sm_notify_cached(struct eapol_sm *sm); +void eapol_sm_notify_pmkid_attempt(struct eapol_sm *sm); +void eapol_sm_register_scard_ctx(struct eapol_sm *sm, void *ctx); +void eapol_sm_notify_portControl(struct eapol_sm *sm, PortControl portControl); +void eapol_sm_notify_ctrl_attached(struct eapol_sm *sm); +void eapol_sm_notify_ctrl_response(struct eapol_sm *sm); +void eapol_sm_request_reauth(struct eapol_sm *sm); +void eapol_sm_notify_lower_layer_success(struct eapol_sm *sm, int in_eapol_sm); +void eapol_sm_invalidate_cached_session(struct eapol_sm *sm); +const char * eapol_sm_get_method_name(struct eapol_sm *sm); +void eapol_sm_set_ext_pw_ctx(struct eapol_sm *sm, + struct ext_password_data *ext); +int eapol_sm_failed(struct eapol_sm *sm); +void eapol_sm_erp_flush(struct eapol_sm *sm); +int eapol_sm_get_eap_proxy_imsi(struct eapol_sm *sm, char *imsi, size_t *len); +#else /* IEEE8021X_EAPOL */ +static inline struct eapol_sm *eapol_sm_init(struct eapol_ctx *ctx) +{ + os_free(ctx); + return (struct eapol_sm *) 1; +} +static inline void eapol_sm_deinit(struct eapol_sm *sm) +{ +} +static inline void eapol_sm_step(struct eapol_sm *sm) +{ +} +static inline int eapol_sm_get_status(struct eapol_sm *sm, char *buf, + size_t buflen, int verbose) +{ + return 0; +} +static inline int eapol_sm_get_mib(struct eapol_sm *sm, char *buf, + size_t buflen) +{ + return 0; +} +static inline void eapol_sm_configure(struct eapol_sm *sm, int heldPeriod, + int authPeriod, int startPeriod, + int maxStart) +{ +} +static inline int eapol_sm_rx_eapol(struct eapol_sm *sm, const u8 *src, + const u8 *buf, size_t len) +{ + return 0; +} +static inline void eapol_sm_notify_tx_eapol_key(struct eapol_sm *sm) +{ +} +static inline void eapol_sm_notify_portEnabled(struct eapol_sm *sm, + Boolean enabled) +{ +} +static inline void eapol_sm_notify_portValid(struct eapol_sm *sm, + Boolean valid) +{ +} +static inline void eapol_sm_notify_eap_success(struct eapol_sm *sm, + Boolean success) +{ +} +static inline void eapol_sm_notify_eap_fail(struct eapol_sm *sm, Boolean fail) +{ +} +static inline void eapol_sm_notify_config(struct eapol_sm *sm, + struct eap_peer_config *config, + struct eapol_config *conf) +{ +} +static inline int eapol_sm_get_key(struct eapol_sm *sm, u8 *key, size_t len) +{ + return -1; +} +static inline const u8 * +eapol_sm_get_session_id(struct eapol_sm *sm, size_t *len) +{ + return NULL; +} +static inline void eapol_sm_notify_logoff(struct eapol_sm *sm, Boolean logoff) +{ +} +static inline void eapol_sm_notify_cached(struct eapol_sm *sm) +{ +} +static inline void eapol_sm_notify_pmkid_attempt(struct eapol_sm *sm) +{ +} +#define eapol_sm_register_scard_ctx(sm, ctx) do { } while (0) +static inline void eapol_sm_notify_portControl(struct eapol_sm *sm, + PortControl portControl) +{ +} +static inline void eapol_sm_notify_ctrl_attached(struct eapol_sm *sm) +{ +} +static inline void eapol_sm_notify_ctrl_response(struct eapol_sm *sm) +{ +} +static inline void eapol_sm_request_reauth(struct eapol_sm *sm) +{ +} +static inline void eapol_sm_notify_lower_layer_success(struct eapol_sm *sm, + int in_eapol_sm) +{ +} +static inline void eapol_sm_invalidate_cached_session(struct eapol_sm *sm) +{ +} +static inline const char * eapol_sm_get_method_name(struct eapol_sm *sm) +{ + return NULL; +} +static inline void eapol_sm_set_ext_pw_ctx(struct eapol_sm *sm, + struct ext_password_data *ext) +{ +} +static inline int eapol_sm_failed(struct eapol_sm *sm) +{ + return 0; +} +static inline void eapol_sm_erp_flush(struct eapol_sm *sm) +{ +} +#endif /* IEEE8021X_EAPOL */ + +#endif /* EAPOL_SUPP_SM_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/l2_packet/l2_packet.h b/beken_os/beken378/func/hostapd-2.5/src/l2_packet/l2_packet.h new file mode 100755 index 0000000..7644e8f --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/l2_packet/l2_packet.h @@ -0,0 +1,154 @@ +/* + * WPA Supplicant - Layer2 packet interface definition + * Copyright (c) 2003-2005, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + * + * This file defines an interface for layer 2 (link layer) packet sending and + * receiving. l2_packet_linux.c is one implementation for such a layer 2 + * implementation using Linux packet sockets and l2_packet_pcap.c another one + * using libpcap and libdnet. When porting %wpa_supplicant to other operating + * systems, a new l2_packet implementation may need to be added. + */ + +#ifndef L2_PACKET_H +#define L2_PACKET_H + +/** + * struct l2_packet_data - Internal l2_packet data structure + * + * This structure is used by the l2_packet implementation to store its private + * data. Other files use a pointer to this data when calling the l2_packet + * functions, but the contents of this structure should not be used directly + * outside l2_packet implementation. + */ +struct l2_packet_data; + +#ifdef _MSC_VER +#pragma pack(push, 1) +#endif /* _MSC_VER */ + +STRUCT_PACKED struct l2_ethhdr { + u8 h_dest[ETH_ALEN]; + u8 h_source[ETH_ALEN]; + be16 h_proto; +}GCC_PACKED; + +#ifdef _MSC_VER +#pragma pack(pop) +#endif /* _MSC_VER */ + +enum l2_packet_filter_type { + L2_PACKET_FILTER_DHCP, + L2_PACKET_FILTER_NDISC, +}; + +/** + * l2_packet_init - Initialize l2_packet interface + * @ifname: Interface name + * @own_addr: Optional own MAC address if available from driver interface or + * %NULL if not available + * @protocol: Ethernet protocol number in host byte order + * @rx_callback: Callback function that will be called for each received packet + * @rx_callback_ctx: Callback data (ctx) for calls to rx_callback() + * @l2_hdr: 1 = include layer 2 header, 0 = do not include header + * Returns: Pointer to internal data or %NULL on failure + * + * rx_callback function will be called with src_addr pointing to the source + * address (MAC address) of the the packet. If l2_hdr is set to 0, buf + * points to len bytes of the payload after the layer 2 header and similarly, + * TX buffers start with payload. This behavior can be changed by setting + * l2_hdr=1 to include the layer 2 header in the data buffer. + */ +struct l2_packet_data * l2_packet_init( + const char *ifname, const u8 *own_addr, unsigned short protocol, + void (*rx_callback)(void *ctx, const u8 *src_addr, + const u8 *buf, size_t len), + void *rx_callback_ctx, int l2_hdr); + +/** + * l2_packet_init_bridge - Like l2_packet_init() but with bridge workaround + * + * This version of l2_packet_init() can be used to enable a workaround for Linux + * packet socket in case of a station interface in a bridge. + */ +struct l2_packet_data * l2_packet_init_bridge( + const char *br_ifname, const char *ifname, const u8 *own_addr, + unsigned short protocol, + void (*rx_callback)(void *ctx, const u8 *src_addr, + const u8 *buf, size_t len), + void *rx_callback_ctx, int l2_hdr); + +/** + * l2_packet_deinit - Deinitialize l2_packet interface + * @l2: Pointer to internal l2_packet data from l2_packet_init() + */ +void l2_packet_deinit(struct l2_packet_data *l2); + +/** + * l2_packet_get_own_addr - Get own layer 2 address + * @l2: Pointer to internal l2_packet data from l2_packet_init() + * @addr: Buffer for the own address (6 bytes) + * Returns: 0 on success, -1 on failure + */ +int l2_packet_get_own_addr(struct l2_packet_data *l2, u8 *addr); + +/** + * l2_packet_send - Send a packet + * @l2: Pointer to internal l2_packet data from l2_packet_init() + * @dst_addr: Destination address for the packet (only used if l2_hdr == 0) + * @proto: Protocol/ethertype for the packet in host byte order (only used if + * l2_hdr == 0) + * @buf: Packet contents to be sent; including layer 2 header if l2_hdr was + * set to 1 in l2_packet_init() call. Otherwise, only the payload of the packet + * is included. + * @len: Length of the buffer (including l2 header only if l2_hdr == 1) + * Returns: >=0 on success, <0 on failure + */ +int l2_packet_send(struct l2_packet_data *l2, const u8 *dst_addr, u16 proto, + const u8 *buf, size_t len); + +/** + * l2_packet_get_ip_addr - Get the current IP address from the interface + * @l2: Pointer to internal l2_packet data from l2_packet_init() + * @buf: Buffer for the IP address in text format + * @len: Maximum buffer length + * Returns: 0 on success, -1 on failure + * + * This function can be used to get the current IP address from the interface + * bound to the l2_packet. This is mainly for status information and the IP + * address will be stored as an ASCII string. This function is not essential + * for %wpa_supplicant operation, so full implementation is not required. + * l2_packet implementation will need to define the function, but it can return + * -1 if the IP address information is not available. + */ +int l2_packet_get_ip_addr(struct l2_packet_data *l2, char *buf, size_t len); + + +/** + * l2_packet_notify_auth_start - Notify l2_packet about start of authentication + * @l2: Pointer to internal l2_packet data from l2_packet_init() + * + * This function is called when authentication is expected to start, e.g., when + * association has been completed, in order to prepare l2_packet implementation + * for EAPOL frames. This function is used mainly if the l2_packet code needs + * to do polling in which case it can increasing polling frequency. This can + * also be an empty function if the l2_packet implementation does not benefit + * from knowing about the starting authentication. + */ +void l2_packet_notify_auth_start(struct l2_packet_data *l2); + +/** + * l2_packet_set_packet_filter - Set socket filter for l2_packet + * @l2: Pointer to internal l2_packet data from l2_packet_init() + * @type: enum l2_packet_filter_type, type of filter + * Returns: 0 on success, -1 on failure + * + * This function is used to set the socket filter for l2_packet socket. + * + */ +int l2_packet_set_packet_filter(struct l2_packet_data *l2, + enum l2_packet_filter_type type); + +#endif /* L2_PACKET_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/l2_packet/l2_packet_none.c b/beken_os/beken378/func/hostapd-2.5/src/l2_packet/l2_packet_none.c new file mode 100755 index 0000000..0d3918e --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/l2_packet/l2_packet_none.c @@ -0,0 +1,231 @@ +/* + * WPA Supplicant - Layer2 packet handling example with dummy functions + * Copyright (c) 2003-2005, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + * + * This file can be used as a starting point for layer2 packet implementation. + */ + +#include "includes.h" + +#include "common.h" +#include "eloop.h" +#include "l2_packet.h" +#include "fake_socket.h" +#include "mac.h" +#include "rw_msdu.h" +#include "uart_pub.h" + +#define L2_RX_TMP_BUF_LEN 512 + +struct l2_packet_data { + char ifname[17]; + u8 own_addr[ETH_ALEN]; + u8 vif_index; + void (*rx_callback)(void *ctx, const u8 *src_addr, + const u8 *buf, size_t len); + void *rx_callback_ctx; + int l2_hdr; /* whether to include layer 2 (Ethernet) header data + * buffers */ + int fd; +}; + + +int l2_packet_get_own_addr(struct l2_packet_data *l2, u8 *addr) +{ + os_memcpy(addr, l2->own_addr, ETH_ALEN); + return 0; +} + +/** + * send L2 packet + * return: <0 if error, else 0. + */ +int __l2_packet_send(struct l2_packet_data *l2, const u8 *dst_addr, u16 proto, + const u8 *buf, size_t len, int sync) +{ + int data_len, ret = 0; + struct l2_ethhdr *eth; + S_TYPE_PTR type_ptr; + unsigned char *data_buf = NULL; + struct ieee80211_tx_cb cb; //control block + + type_ptr = os_zalloc(sizeof(S_TYPE_ST)); + if(!type_ptr) { + ret = -1; + if(type_ptr){ + os_free(type_ptr); + } + goto send_exit; + } + + data_len = len + sizeof(struct l2_ethhdr); + data_buf = os_zalloc(data_len); + if(data_buf == NULL){ + ret = -1; + goto send_exit; + } + + eth = (struct l2_ethhdr *) data_buf; + os_memcpy(eth->h_dest, dst_addr, ETH_ALEN); + os_memcpy(eth->h_source, l2->own_addr, ETH_ALEN); + eth->h_proto = host_to_be16(proto); + os_memcpy(eth+1, buf, len); + + type_ptr->type = HOSTAPD_DATA; + + type_ptr->vif_index = l2->vif_index; + type_ptr->sync = sync; + + cb.result = -1; + if (sync) { +#if CFG_SUPPORT_ALIOS + ret = rtos_init_semaphore(&cb.sema, 0); +#else + ret = rtos_init_semaphore(&cb.sema, 1); +#endif + type_ptr->args = (void *)&cb; + } + + fsocket_send(l2->fd, data_buf, data_len, type_ptr); + if (sync) { + ret = rtos_get_semaphore(&cb.sema, 5*1000 /*BEKEN_NEVER_TIMEOUT*/); + if (ret != kNoErr) { + bk_printf("%s: send failed\r\n", __func__); + } else { + ret = cb.result; + bk_printf("%s: ret %d\r\n", __func__, ret); + } + rtos_deinit_semaphore(&cb.sema); + } + +send_exit: + if(data_buf){ + os_free(data_buf); + } + + return ret; +} + +int l2_packet_send(struct l2_packet_data *l2, const u8 *dst_addr, u16 proto, + const u8 *buf, size_t len) +{ + return __l2_packet_send(l2, dst_addr, proto, buf, len, 0); +} + +int l2_packet_send_sync(struct l2_packet_data *l2, const u8 *dst_addr, u16 proto, + const u8 *buf, size_t len) +{ + return __l2_packet_send(l2, dst_addr, proto, buf, len, 1); +} + +static void l2_packet_receive(int sock, void *eloop_ctx, void *sock_ctx) +{ + int len; + unsigned char *buf; + struct l2_ethhdr *hdr; + struct l2_packet_data *l2 = eloop_ctx; + + buf = os_malloc(L2_RX_TMP_BUF_LEN); + ASSERT(buf); + + len = fsocket_recv(sock, buf, L2_RX_TMP_BUF_LEN, 0); + if (len < 0) { + wpa_printf(MSG_ERROR, "recv: %s", strerror(errno)); + goto recv_exit; + } + + hdr = (struct l2_ethhdr *) buf; + l2->rx_callback(l2->rx_callback_ctx, + hdr->h_source, + buf + sizeof(struct l2_ethhdr), + len - sizeof(struct l2_ethhdr)); + +recv_exit: + if(buf) + { + os_free(buf); + } + + return; +} + +extern UINT8 rwm_mgmt_vif_mac2idx(void *mac); +struct l2_packet_data * l2_packet_init( + const char *ifname, const u8 *own_addr, unsigned short protocol, + void (*rx_callback)(void *ctx, const u8 *src_addr, + const u8 *buf, size_t len), + void *rx_callback_ctx, int l2_hdr) +{ + struct l2_packet_data *l2; + + l2 = os_zalloc(sizeof(struct l2_packet_data)); + if (l2 == NULL) + return NULL; + os_strlcpy(l2->ifname, ifname, sizeof(l2->ifname)); + os_memcpy(l2->own_addr, own_addr, ETH_ALEN); + + l2->vif_index = rwm_mgmt_vif_mac2idx((void*)own_addr); + if(l2->vif_index == 0xff) { + os_printf("not found vif_index in l2_packet_init\r\n"); + } + + l2->rx_callback = rx_callback; + l2->rx_callback_ctx = rx_callback_ctx; + l2->l2_hdr = l2_hdr; + + /* + * TODO: open connection for receiving frames + */ + protocol += l2->vif_index; + l2->fd = fsocket_init(PF_PACKET, SOCK_RAW, protocol); + if (l2->fd >= 0) + eloop_register_read_sock(l2->fd, l2_packet_receive, l2, NULL); + + return l2; +} + +struct l2_packet_data * l2_packet_init_bridge( + const char *br_ifname, const char *ifname, const u8 *own_addr, + unsigned short protocol, + void (*rx_callback)(void *ctx, const u8 *src_addr, + const u8 *buf, size_t len), + void *rx_callback_ctx, int l2_hdr) +{ + return l2_packet_init(br_ifname, own_addr, protocol, rx_callback, + rx_callback_ctx, l2_hdr); +} + +void l2_packet_deinit(struct l2_packet_data *l2) +{ + if (l2 == NULL) + return; + + if (l2->fd >= 0) + { + eloop_unregister_read_sock(l2->fd); + /* TODO: close connection */ + fsocket_close(l2->fd); + } + + os_free(l2); +} + +int l2_packet_get_ip_addr(struct l2_packet_data *l2, char *buf, size_t len) +{ + /* TODO: get interface IP address */ + return -1; +} + +void l2_packet_notify_auth_start(struct l2_packet_data *l2) +{ + /* This function can be left empty */ +} + +int l2_packet_set_packet_filter(struct l2_packet_data *l2, + enum l2_packet_filter_type type) +{ + return -1; +} diff --git a/beken_os/beken378/func/hostapd-2.5/src/rsn_supp/peerkey.h b/beken_os/beken378/func/hostapd-2.5/src/rsn_supp/peerkey.h new file mode 100755 index 0000000..6ccd948 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/rsn_supp/peerkey.h @@ -0,0 +1,82 @@ +/* + * WPA Supplicant - PeerKey for Direct Link Setup (DLS) + * Copyright (c) 2006-2015, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef PEERKEY_H +#define PEERKEY_H + +#define PEERKEY_MAX_IE_LEN 80 +struct wpa_peerkey { + struct wpa_peerkey *next; + int initiator; /* whether this end was initator for SMK handshake */ + u8 addr[ETH_ALEN]; /* other end MAC address */ + u8 inonce[WPA_NONCE_LEN]; /* Initiator Nonce */ + u8 pnonce[WPA_NONCE_LEN]; /* Peer Nonce */ + u8 rsnie_i[PEERKEY_MAX_IE_LEN]; /* Initiator RSN IE */ + size_t rsnie_i_len; + u8 rsnie_p[PEERKEY_MAX_IE_LEN]; /* Peer RSN IE */ + size_t rsnie_p_len; + u8 smk[PMK_LEN]; + int smk_complete; + u8 smkid[PMKID_LEN]; + u32 lifetime; + int cipher; /* Selected cipher (WPA_CIPHER_*) */ + u8 replay_counter[WPA_REPLAY_COUNTER_LEN]; + int replay_counter_set; + int akmp; + + struct wpa_ptk stk, tstk; + int stk_set, tstk_set; +}; + + +#ifdef CONFIG_PEERKEY + +int peerkey_verify_eapol_key_mic(struct wpa_sm *sm, + struct wpa_peerkey *peerkey, + struct wpa_eapol_key_192 *key, u16 ver, + const u8 *buf, size_t len); +void peerkey_rx_eapol_4way(struct wpa_sm *sm, struct wpa_peerkey *peerkey, + struct wpa_eapol_key *key, u16 key_info, u16 ver, + const u8 *key_data, size_t key_data_len); +void peerkey_rx_eapol_smk(struct wpa_sm *sm, const u8 *src_addr, + struct wpa_eapol_key *key, size_t extra_len, + u16 key_info, u16 ver); +void peerkey_deinit(struct wpa_sm *sm); + +#else /* CONFIG_PEERKEY */ + +static inline int +peerkey_verify_eapol_key_mic(struct wpa_sm *sm, + struct wpa_peerkey *peerkey, + struct wpa_eapol_key *key, u16 ver, + const u8 *buf, size_t len) +{ + return -1; +} + +static inline void +peerkey_rx_eapol_4way(struct wpa_sm *sm, struct wpa_peerkey *peerkey, + struct wpa_eapol_key *key, u16 key_info, u16 ver, + const u8 *key_data, size_t key_data_len) +{ +} + +static inline void +peerkey_rx_eapol_smk(struct wpa_sm *sm, const u8 *src_addr, + struct wpa_eapol_key *key, size_t extra_len, + u16 key_info, u16 ver) +{ +} + +static inline void peerkey_deinit(struct wpa_sm *sm) +{ +} + +#endif /* CONFIG_PEERKEY */ + +#endif /* PEERKEY_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/rsn_supp/pmksa_cache.h b/beken_os/beken378/func/hostapd-2.5/src/rsn_supp/pmksa_cache.h new file mode 100755 index 0000000..f8e040e --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/rsn_supp/pmksa_cache.h @@ -0,0 +1,134 @@ +/* + * wpa_supplicant - WPA2/RSN PMKSA cache functions + * Copyright (c) 2003-2009, 2011-2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef PMKSA_CACHE_H +#define PMKSA_CACHE_H + +/** + * struct rsn_pmksa_cache_entry - PMKSA cache entry + */ +struct rsn_pmksa_cache_entry { + struct rsn_pmksa_cache_entry *next; + u8 pmkid[PMKID_LEN]; + u8 pmk[PMK_LEN]; + size_t pmk_len; + os_time_t expiration; + int akmp; /* WPA_KEY_MGMT_* */ + u8 aa[ETH_ALEN]; + + os_time_t reauth_time; + + /** + * network_ctx - Network configuration context + * + * This field is only used to match PMKSA cache entries to a specific + * network configuration (e.g., a specific SSID and security policy). + * This can be a pointer to the configuration entry, but PMKSA caching + * code does not dereference the value and this could be any kind of + * identifier. + */ + void *network_ctx; + int opportunistic; +}; + +struct rsn_pmksa_cache; + +enum pmksa_free_reason { + PMKSA_FREE, + PMKSA_REPLACE, + PMKSA_EXPIRE, +}; + +#ifdef IEEE8021X_EAPOL + +struct rsn_pmksa_cache * +pmksa_cache_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry, + void *ctx, enum pmksa_free_reason reason), + void *ctx, struct wpa_sm *sm); +void pmksa_cache_deinit(struct rsn_pmksa_cache *pmksa); +struct rsn_pmksa_cache_entry * pmksa_cache_get(struct rsn_pmksa_cache *pmksa, + const u8 *aa, const u8 *pmkid, + const void *network_ctx); +int pmksa_cache_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len); +struct rsn_pmksa_cache_entry * +pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len, + const u8 *kck, size_t kck_len, + const u8 *aa, const u8 *spa, void *network_ctx, int akmp); +struct rsn_pmksa_cache_entry * pmksa_cache_get_current(struct wpa_sm *sm); +void pmksa_cache_clear_current(struct wpa_sm *sm); +int pmksa_cache_set_current(struct wpa_sm *sm, const u8 *pmkid, + const u8 *bssid, void *network_ctx, + int try_opportunistic); +struct rsn_pmksa_cache_entry * +pmksa_cache_get_opportunistic(struct rsn_pmksa_cache *pmksa, + void *network_ctx, const u8 *aa); +void pmksa_cache_flush(struct rsn_pmksa_cache *pmksa, void *network_ctx, + const u8 *pmk, size_t pmk_len); + +#else /* IEEE8021X_EAPOL */ + +static inline struct rsn_pmksa_cache * +pmksa_cache_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry, + void *ctx, enum pmksa_free_reason reason), + void *ctx, struct wpa_sm *sm) +{ + return (void *) -1; +} + +static inline void pmksa_cache_deinit(struct rsn_pmksa_cache *pmksa) +{ +} + +static inline struct rsn_pmksa_cache_entry * +pmksa_cache_get(struct rsn_pmksa_cache *pmksa, const u8 *aa, const u8 *pmkid, + const void *network_ctx) +{ + return NULL; +} + +static inline struct rsn_pmksa_cache_entry * +pmksa_cache_get_current(struct wpa_sm *sm) +{ + return NULL; +} + +static inline int pmksa_cache_list(struct rsn_pmksa_cache *pmksa, char *buf, + size_t len) +{ + return -1; +} + +static inline struct rsn_pmksa_cache_entry * +pmksa_cache_add(struct rsn_pmksa_cache *pmksa, const u8 *pmk, size_t pmk_len, + const u8 *kck, size_t kck_len, + const u8 *aa, const u8 *spa, void *network_ctx, int akmp) +{ + return NULL; +} + +static inline void pmksa_cache_clear_current(struct wpa_sm *sm) +{ +} + +static inline int pmksa_cache_set_current(struct wpa_sm *sm, const u8 *pmkid, + const u8 *bssid, + void *network_ctx, + int try_opportunistic) +{ + return -1; +} + +static inline void pmksa_cache_flush(struct rsn_pmksa_cache *pmksa, + void *network_ctx, + const u8 *pmk, size_t pmk_len) +{ +} + +#endif /* IEEE8021X_EAPOL */ + +#endif /* PMKSA_CACHE_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/rsn_supp/preauth.h b/beken_os/beken378/func/hostapd-2.5/src/rsn_supp/preauth.h new file mode 100755 index 0000000..277f066 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/rsn_supp/preauth.h @@ -0,0 +1,79 @@ +/* + * wpa_supplicant - WPA2/RSN pre-authentication functions + * Copyright (c) 2003-2009, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef PREAUTH_H +#define PREAUTH_H + +struct wpa_scan_results; + +#ifdef IEEE8021X_EAPOL + +void pmksa_candidate_free(struct wpa_sm *sm); +int rsn_preauth_init(struct wpa_sm *sm, const u8 *dst, + struct eap_peer_config *eap_conf); +void rsn_preauth_deinit(struct wpa_sm *sm); +int rsn_preauth_scan_results(struct wpa_sm *sm); +void rsn_preauth_scan_result(struct wpa_sm *sm, const u8 *bssid, + const u8 *ssid, const u8 *rsn); +void pmksa_candidate_add(struct wpa_sm *sm, const u8 *bssid, + int prio, int preauth); +void rsn_preauth_candidate_process(struct wpa_sm *sm); +int rsn_preauth_get_status(struct wpa_sm *sm, char *buf, size_t buflen, + int verbose); +int rsn_preauth_in_progress(struct wpa_sm *sm); + +#else /* IEEE8021X_EAPOL */ + +static inline void pmksa_candidate_free(struct wpa_sm *sm) +{ +} + +static inline void rsn_preauth_candidate_process(struct wpa_sm *sm) +{ +} + +static inline int rsn_preauth_init(struct wpa_sm *sm, const u8 *dst, + struct eap_peer_config *eap_conf) +{ + return -1; +} + +static inline void rsn_preauth_deinit(struct wpa_sm *sm) +{ +} + +static inline int rsn_preauth_scan_results(struct wpa_sm *sm) +{ + return -1; +} + +static inline void rsn_preauth_scan_result(struct wpa_sm *sm, const u8 *bssid, + const u8 *ssid, const u8 *rsn) +{ +} + +static inline void pmksa_candidate_add(struct wpa_sm *sm, + const u8 *bssid, + int prio, int preauth) +{ +} + +static inline int rsn_preauth_get_status(struct wpa_sm *sm, char *buf, + size_t buflen, int verbose) +{ + return 0; +} + +static inline int rsn_preauth_in_progress(struct wpa_sm *sm) +{ + return 0; +} + +#endif /* IEEE8021X_EAPOL */ + +#endif /* PREAUTH_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/rsn_supp/wpa.c b/beken_os/beken378/func/hostapd-2.5/src/rsn_supp/wpa.c new file mode 100755 index 0000000..970536f --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/rsn_supp/wpa.c @@ -0,0 +1,2447 @@ +/* + * WPA Supplicant - WPA state machine and EAPOL-Key processing + * Copyright (c) 2003-2015, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "crypto/aes_wrap.h" +#include "crypto/crypto.h" +#include "crypto/random.h" +#include "common/ieee802_11_defs.h" +#include "eapol_supp/eapol_supp_sm.h" +#include "wpa.h" +#include "eloop.h" +#include "preauth.h" +#include "pmksa_cache.h" +#include "wpa_i.h" +#include "wpa_ie.h" +#include "peerkey.h" + +#include "include.h" +#include "uart_pub.h" + +/** + * wpa_eapol_key_send - Send WPA/RSN EAPOL-Key message + * @sm: Pointer to WPA state machine data from wpa_sm_init() + * @kck: Key Confirmation Key (KCK, part of PTK) + * @kck_len: KCK length in octets + * @ver: Version field from Key Info + * @dest: Destination address for the frame + * @proto: Ethertype (usually ETH_P_EAPOL) + * @msg: EAPOL-Key message + * @msg_len: Length of message + * @key_mic: Pointer to the buffer to which the EAPOL-Key MIC is written + * Returns: >= 0 on success, < 0 on failure + */ +int wpa_eapol_key_send(struct wpa_sm *sm, const u8 *kck, size_t kck_len, + int ver, const u8 *dest, u16 proto, + u8 *msg, size_t msg_len, u8 *key_mic) +{ + int ret = -1; + size_t mic_len = wpa_mic_len(sm->key_mgmt); + + if (is_zero_ether_addr(dest) && is_zero_ether_addr(sm->bssid)) { + /* + * Association event was not yet received; try to fetch + * BSSID from the driver. + */ + if (wpa_sm_get_bssid(sm, sm->bssid) < 0) { + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, + "WPA: Failed to read BSSID for " + "EAPOL-Key destination address"); + } else { + dest = sm->bssid; + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, + "WPA: Use BSSID (" MACSTR + ") as the destination for EAPOL-Key", + MAC2STR(dest)); + } + } + if (key_mic && + wpa_eapol_key_mic(kck, kck_len, sm->key_mgmt, ver, msg, msg_len, + key_mic)) { + wpa_msg(sm->ctx->msg_ctx, MSG_ERROR, + "WPA: Failed to generate EAPOL-Key version %d key_mgmt 0x%x MIC", + ver, sm->key_mgmt); + goto out; + } + wpa_hexdump_key(MSG_DEBUG, "WPA: KCK", kck, kck_len); + wpa_hexdump(MSG_DEBUG, "WPA: Derived Key MIC", key_mic, mic_len); + wpa_hexdump(MSG_MSGDUMP, "WPA: TX EAPOL-Key", msg, msg_len); + ret = wpa_sm_ether_send(sm, dest, proto, msg, msg_len); + eapol_sm_notify_tx_eapol_key(sm->eapol); + + (void)mic_len; + +out: + os_free(msg); + return ret; +} + + +/** + * wpa_sm_key_request - Send EAPOL-Key Request + * @sm: Pointer to WPA state machine data from wpa_sm_init() + * @error: Indicate whether this is an Michael MIC error report + * @pairwise: 1 = error report for pairwise packet, 0 = for group packet + * + * Send an EAPOL-Key Request to the current authenticator. This function is + * used to request rekeying and it is usually called when a local Michael MIC + * failure is detected. + */ +void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise) +{ + size_t mic_len, hdrlen, rlen; + struct wpa_eapol_key *reply; + struct wpa_eapol_key_192 *reply192; + int key_info, ver; + u8 bssid[ETH_ALEN], *rbuf, *key_mic; + + if (sm->key_mgmt == WPA_KEY_MGMT_OSEN || + wpa_key_mgmt_suite_b(sm->key_mgmt)) + ver = WPA_KEY_INFO_TYPE_AKM_DEFINED; + else if (wpa_key_mgmt_ft(sm->key_mgmt) || + wpa_key_mgmt_sha256(sm->key_mgmt)) + ver = WPA_KEY_INFO_TYPE_AES_128_CMAC; + else if (sm->pairwise_cipher != WPA_CIPHER_TKIP) + ver = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES; + else + ver = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4; + + if (wpa_sm_get_bssid(sm, bssid) < 0) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "Failed to read BSSID for EAPOL-Key request"); + return; + } + + mic_len = wpa_mic_len(sm->key_mgmt); + hdrlen = mic_len == 24 ? sizeof(*reply192) : sizeof(*reply); + rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, + hdrlen, &rlen, (void *) &reply); + if (rbuf == NULL) + return; + reply192 = (struct wpa_eapol_key_192 *) reply; + + reply->type = (sm->proto == WPA_PROTO_RSN || + sm->proto == WPA_PROTO_OSEN) ? + EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA; + key_info = WPA_KEY_INFO_REQUEST | ver; + if (sm->ptk_set) + key_info |= WPA_KEY_INFO_MIC; + if (error) + key_info |= WPA_KEY_INFO_ERROR; + if (pairwise) + key_info |= WPA_KEY_INFO_KEY_TYPE; + WPA_PUT_BE16(reply->key_info, key_info); + WPA_PUT_BE16(reply->key_length, 0); + os_memcpy(reply->replay_counter, sm->request_counter, + WPA_REPLAY_COUNTER_LEN); + inc_byte_array(sm->request_counter, WPA_REPLAY_COUNTER_LEN); + + if (mic_len == 24) + WPA_PUT_BE16(reply192->key_data_length, 0); + else + WPA_PUT_BE16(reply->key_data_length, 0); + if (!(key_info & WPA_KEY_INFO_MIC)) + key_mic = NULL; + else + key_mic = reply192->key_mic; /* same offset in reply */ + + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "WPA: Sending EAPOL-Key Request (error=%d " + "pairwise=%d ptk_set=%d len=%lu)", + error, pairwise, sm->ptk_set, (unsigned long) rlen); + wpa_eapol_key_send(sm, sm->ptk.kck, sm->ptk.kck_len, ver, bssid, + ETH_P_EAPOL, rbuf, rlen, key_mic); +} + +void wpa_supplicant_key_mgmt_set_pmk(struct wpa_sm *sm) +{ + if (wpa_sm_key_mgmt_set_pmk(sm, sm->pmk, sm->pmk_len)) + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, + "RSN: Cannot set PMK for key management offload"); +} + +static int wpa_supplicant_get_pmk(struct wpa_sm *sm, + const unsigned char *src_addr, + const u8 *pmkid) +{ + if (sm->pmk_len > 0) + return 0; + else + return 1; +} + +/** + * wpa_supplicant_send_2_of_4 - Send message 2 of WPA/RSN 4-Way Handshake + * @sm: Pointer to WPA state machine data from wpa_sm_init() + * @dst: Destination address for the frame + * @key: Pointer to the EAPOL-Key frame header + * @ver: Version bits from EAPOL-Key Key Info + * @nonce: Nonce value for the EAPOL-Key frame + * @wpa_ie: WPA/RSN IE + * @wpa_ie_len: Length of the WPA/RSN IE + * @ptk: PTK to use for keyed hash and encryption + * Returns: >=0 on success, <0 on failure + */ +int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst, + const struct wpa_eapol_key *key, + int ver, const u8 *nonce, + const u8 *wpa_ie, size_t wpa_ie_len, + struct wpa_ptk *ptk) +{ + size_t mic_len, hdrlen, rlen; + struct wpa_eapol_key *reply; + struct wpa_eapol_key_192 *reply192; + u8 *rbuf, *key_mic; + u8 *rsn_ie_buf = NULL; + + if (wpa_ie == NULL) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: No wpa_ie set - " + "cannot generate msg 2/4"); + return -1; + } + wpa_hexdump(MSG_DEBUG, "WPA: WPA IE for msg 2/4", wpa_ie, wpa_ie_len); + + mic_len = wpa_mic_len(sm->key_mgmt); + hdrlen = mic_len == 24 ? sizeof(*reply192) : sizeof(*reply); + rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, + NULL, hdrlen + wpa_ie_len, + &rlen, (void *) &reply); + if (rbuf == NULL) { + os_free(rsn_ie_buf); + return -1; + } + reply192 = (struct wpa_eapol_key_192 *) reply; + + reply->type = (sm->proto == WPA_PROTO_RSN || + sm->proto == WPA_PROTO_OSEN) ? + EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA; + WPA_PUT_BE16(reply->key_info, + ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_MIC); + if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) + WPA_PUT_BE16(reply->key_length, 0); + else + os_memcpy(reply->key_length, key->key_length, 2); + os_memcpy(reply->replay_counter, key->replay_counter, + WPA_REPLAY_COUNTER_LEN); + wpa_hexdump(MSG_DEBUG, "WPA: Replay Counter", reply->replay_counter, + WPA_REPLAY_COUNTER_LEN); + + key_mic = reply192->key_mic; /* same offset for reply and reply192 */ + if (mic_len == 24) { + WPA_PUT_BE16(reply192->key_data_length, wpa_ie_len); + os_memcpy(reply192 + 1, wpa_ie, wpa_ie_len); + } else { + WPA_PUT_BE16(reply->key_data_length, wpa_ie_len); + os_memcpy(reply + 1, wpa_ie, wpa_ie_len); + } + os_free(rsn_ie_buf); + + os_memcpy(reply->key_nonce, nonce, WPA_NONCE_LEN); + + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 2/4"); + return wpa_eapol_key_send(sm, ptk->kck, ptk->kck_len, ver, dst, ETH_P_EAPOL, + rbuf, rlen, key_mic); +} + + +static int wpa_derive_ptk(struct wpa_sm *sm, const unsigned char *src_addr, + const struct wpa_eapol_key *key, struct wpa_ptk *ptk) +{ + return wpa_pmk_to_ptk(sm->pmk, sm->pmk_len, "Pairwise key expansion", + sm->own_addr, sm->bssid, sm->snonce, + key->key_nonce, ptk, sm->key_mgmt, + sm->pairwise_cipher); +} + + +static void wpa_supplicant_process_1_of_4(struct wpa_sm *sm, + const unsigned char *src_addr, + const struct wpa_eapol_key *key, + u16 ver, const u8 *key_data, + size_t key_data_len) +{ + struct wpa_eapol_ie_parse ie; + struct wpa_ptk *ptk; + int res; + u8 *kde, *kde_buf = NULL; + size_t kde_len; + + if (wpa_sm_get_network_ctx(sm) == NULL) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: No SSID info " + "found (msg 1 of 4)"); + return; + } + + wpa_sm_set_state(sm, WPA_4WAY_HANDSHAKE); + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: RX message 1 of 4-Way " + "Handshake from " MACSTR " (ver=%d)", MAC2STR(src_addr), ver); + + os_memset(&ie, 0, sizeof(ie)); + + if (sm->proto == WPA_PROTO_RSN) { + /* RSN: msg 1/4 should contain PMKID for the selected PMK */ + wpa_hexdump(MSG_DEBUG, "RSN: msg 1/4 key data", + key_data, key_data_len); + if (wpa_supplicant_parse_ies(key_data, key_data_len, &ie) < 0) + goto failed; + if (ie.pmkid) { + wpa_hexdump(MSG_DEBUG, "RSN: PMKID from " + "Authenticator", ie.pmkid, PMKID_LEN); + } + } + + res = wpa_supplicant_get_pmk(sm, src_addr, ie.pmkid); + if (res == -2) { + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "RSN: Do not reply to " + "msg 1/4 - requesting full EAP authentication"); + return; + } + if (res) + goto failed; + + if (sm->renew_snonce) { + if (random_get_bytes(sm->snonce, WPA_NONCE_LEN)) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "WPA: Failed to get random data for SNonce"); + goto failed; + } + sm->renew_snonce = 0; + wpa_hexdump(MSG_DEBUG, "WPA: Renewed SNonce", + sm->snonce, WPA_NONCE_LEN); + } + + /* Calculate PTK which will be stored as a temporary PTK until it has + * been verified when processing message 3/4. */ + ptk = &sm->tptk; + wpa_derive_ptk(sm, src_addr, key, ptk); + if (sm->pairwise_cipher == WPA_CIPHER_TKIP) { + u8 buf[8]; + /* Supplicant: swap tx/rx Mic keys */ + os_memcpy(buf, &ptk->tk[16], 8); + os_memcpy(&ptk->tk[16], &ptk->tk[24], 8); + os_memcpy(&ptk->tk[24], buf, 8); + os_memset(buf, 0, sizeof(buf)); + } + sm->tptk_set = 1; + + kde = sm->assoc_wpa_ie; + kde_len = sm->assoc_wpa_ie_len; + +#ifdef CONFIG_P2P + if (sm->p2p) { + kde_buf = os_malloc(kde_len + 2 + RSN_SELECTOR_LEN + 1); + if (kde_buf) { + u8 *pos; + wpa_printf(MSG_DEBUG, "P2P: Add IP Address Request KDE " + "into EAPOL-Key 2/4"); + os_memcpy(kde_buf, kde, kde_len); + kde = kde_buf; + pos = kde + kde_len; + *pos++ = WLAN_EID_VENDOR_SPECIFIC; + *pos++ = RSN_SELECTOR_LEN + 1; + RSN_SELECTOR_PUT(pos, WFA_KEY_DATA_IP_ADDR_REQ); + pos += RSN_SELECTOR_LEN; + *pos++ = 0x01; + kde_len = pos - kde; + } + } +#endif /* CONFIG_P2P */ + + if (wpa_supplicant_send_2_of_4(sm, sm->bssid, key, ver, sm->snonce, + kde, kde_len, ptk) < 0) + goto tx_failed; + + os_free(kde_buf); + os_memcpy(sm->anonce, key->key_nonce, WPA_NONCE_LEN); + return; + +tx_failed: + os_printf("%s: tx eapol failed\r\n", __func__); + return; //server may retry to resend to us. + +failed: + os_free(kde_buf); + wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED); +} + + +static void wpa_sm_start_preauth(void *eloop_ctx, void *timeout_ctx) +{ + struct wpa_sm *sm = eloop_ctx; + rsn_preauth_candidate_process(sm); +} + +static void wpa_supplicant_key_neg_complete(struct wpa_sm *sm, + const u8 *addr, int secure) +{ + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "WPA: Key negotiation completed with " + MACSTR " [PTK=%s GTK=%s]", MAC2STR(addr), + wpa_cipher_txt(sm->pairwise_cipher), + wpa_cipher_txt(sm->group_cipher)); + wpa_sm_cancel_auth_timeout(sm); + wpa_sm_set_state(sm, WPA_COMPLETED); + + if (secure) { + wpa_sm_mlme_setprotection( + sm, addr, MLME_SETPROTECTION_PROTECT_TYPE_RX_TX, + MLME_SETPROTECTION_KEY_TYPE_PAIRWISE); + eapol_sm_notify_portValid(sm->eapol, TRUE); + if (wpa_key_mgmt_wpa_psk(sm->key_mgmt)) + eapol_sm_notify_eap_success(sm->eapol, TRUE); + /* + * Start preauthentication after a short wait to avoid a + * possible race condition between the data receive and key + * configuration after the 4-Way Handshake. This increases the + * likelihood of the first preauth EAPOL-Start frame getting to + * the target AP. + */ + eloop_register_timeout(1, 0, wpa_sm_start_preauth, sm, NULL); + } +} + + +static void wpa_sm_rekey_ptk(void *eloop_ctx, void *timeout_ctx) +{ + struct wpa_sm *sm = eloop_ctx; + os_printf("WPA: Request PTK rekeying\r\n"); + wpa_sm_key_request(sm, 0, 1); +} + + +static int wpa_supplicant_install_ptk(struct wpa_sm *sm, + const struct wpa_eapol_key *key) +{ + int keylen, rsclen; + enum wpa_alg alg; + const u8 *key_rsc; + u8 null_rsc[8] = { 0, 0, 0, 0, 0, 0, 0, 0 }; + + if (sm->ptk.installed) { + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, + "WPA: Do not re-install same PTK to the driver"); + return 0; + } + + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, + "WPA: Installing PTK to the driver"); + + if (sm->pairwise_cipher == WPA_CIPHER_NONE) { + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Pairwise Cipher " + "Suite: NONE - do not use pairwise keys"); + return 0; + } + + if (!wpa_cipher_valid_pairwise(sm->pairwise_cipher)) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "WPA: Unsupported pairwise cipher %d", + sm->pairwise_cipher); + return -1; + } + + alg = (enum wpa_alg)wpa_cipher_to_alg(sm->pairwise_cipher); + keylen = wpa_cipher_key_len(sm->pairwise_cipher); + rsclen = wpa_cipher_rsc_len(sm->pairwise_cipher); + + if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) { + key_rsc = null_rsc; + } else { + key_rsc = key->key_rsc; + wpa_hexdump(MSG_DEBUG, "WPA: RSC", key_rsc, rsclen); + } + + if (wpa_sm_set_key(sm, alg, sm->bssid, 0, 1, key_rsc, rsclen, + sm->ptk.tk, keylen) < 0) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "WPA: Failed to set PTK to the " + "driver (alg=%d keylen=%d bssid=" MACSTR ")", + alg, keylen, MAC2STR(sm->bssid)); + return -1; + } + + /* TK is not needed anymore in supplicant */ + os_memset(sm->ptk.tk, 0, WPA_TK_MAX_LEN); + sm->ptk.installed = 1; + + if (sm->wpa_ptk_rekey) { + eloop_cancel_timeout(wpa_sm_rekey_ptk, sm, NULL); + eloop_register_timeout(sm->wpa_ptk_rekey, 0, wpa_sm_rekey_ptk, + sm, NULL); + } + + return 0; +} + + +static int wpa_supplicant_check_group_cipher(struct wpa_sm *sm, + int group_cipher, + int keylen, int maxkeylen, + int *key_rsc_len, + enum wpa_alg *alg) +{ + int klen; + + *alg = (enum wpa_alg)wpa_cipher_to_alg(group_cipher); + if (*alg == WPA_ALG_NONE) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "WPA: Unsupported Group Cipher %d", + group_cipher); + return -1; + } + *key_rsc_len = wpa_cipher_rsc_len(group_cipher); + + klen = wpa_cipher_key_len(group_cipher); + if (keylen != klen || maxkeylen < klen) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "WPA: Unsupported %s Group Cipher key length %d (%d)", + wpa_cipher_txt(group_cipher), keylen, maxkeylen); + return -1; + } + return 0; +} + + +struct wpa_gtk_data { + enum wpa_alg alg; + int tx, key_rsc_len, keyidx; + u8 gtk[32]; + int gtk_len; +}; + + +static int wpa_supplicant_install_gtk(struct wpa_sm *sm, + const struct wpa_gtk_data *gd, + const u8 *key_rsc, int wnm_sleep) +{ + const u8 *_gtk = gd->gtk; + u8 gtk_buf[32]; + + /* Detect possible key reinstallation */ + if ((sm->gtk.gtk_len == (size_t) gd->gtk_len && + os_memcmp(sm->gtk.gtk, gd->gtk, sm->gtk.gtk_len) == 0) || + (sm->gtk_wnm_sleep.gtk_len == (size_t) gd->gtk_len && + os_memcmp(sm->gtk_wnm_sleep.gtk, gd->gtk, + sm->gtk_wnm_sleep.gtk_len) == 0)) { + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, + "WPA: Not reinstalling already in-use GTK to the driver (keyidx=%d tx=%d len=%d)", + gd->keyidx, gd->tx, gd->gtk_len); + return 0; + } + + wpa_hexdump_key(MSG_DEBUG, "WPA: Group Key", gd->gtk, gd->gtk_len); + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, + "WPA: Installing GTK to the driver (keyidx=%d tx=%d len=%d)", + gd->keyidx, gd->tx, gd->gtk_len); + wpa_hexdump(MSG_DEBUG, "WPA: RSC", key_rsc, gd->key_rsc_len); + if (sm->group_cipher == WPA_CIPHER_TKIP) { + /* Swap Tx/Rx keys for Michael MIC */ + os_memcpy(gtk_buf, gd->gtk, 16); + os_memcpy(gtk_buf + 16, gd->gtk + 24, 8); + os_memcpy(gtk_buf + 24, gd->gtk + 16, 8); + _gtk = gtk_buf; + } + if (sm->pairwise_cipher == WPA_CIPHER_NONE) { + if (wpa_sm_set_key(sm, gd->alg, NULL, + gd->keyidx, 1, key_rsc, gd->key_rsc_len, + _gtk, gd->gtk_len) < 0) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "WPA: Failed to set GTK to the driver " + "(Group only)"); + os_memset(gtk_buf, 0, sizeof(gtk_buf)); + return -1; + } + } else if (wpa_sm_set_key(sm, gd->alg, broadcast_ether_addr, + gd->keyidx, gd->tx, key_rsc, gd->key_rsc_len, + _gtk, gd->gtk_len) < 0) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "WPA: Failed to set GTK to " + "the driver (alg=%d keylen=%d keyidx=%d)", + gd->alg, gd->gtk_len, gd->keyidx); + os_memset(gtk_buf, 0, sizeof(gtk_buf)); + return -1; + } + os_memset(gtk_buf, 0, sizeof(gtk_buf)); + + if (wnm_sleep) { + sm->gtk_wnm_sleep.gtk_len = gd->gtk_len; + os_memcpy(sm->gtk_wnm_sleep.gtk, gd->gtk, + sm->gtk_wnm_sleep.gtk_len); + } else { + sm->gtk.gtk_len = gd->gtk_len; + os_memcpy(sm->gtk.gtk, gd->gtk, sm->gtk.gtk_len); + } + + return 0; +} + + +static int wpa_supplicant_gtk_tx_bit_workaround(const struct wpa_sm *sm, + int tx) +{ + if (tx && sm->pairwise_cipher != WPA_CIPHER_NONE) { + /* Ignore Tx bit for GTK if a pairwise key is used. One AP + * seemed to set this bit (incorrectly, since Tx is only when + * doing Group Key only APs) and without this workaround, the + * data connection does not work because wpa_supplicant + * configured non-zero keyidx to be used for unicast. */ + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "WPA: Tx bit set for GTK, but pairwise " + "keys are used - ignore Tx bit"); + return 0; + } + return tx; +} + + +static int wpa_supplicant_pairwise_gtk(struct wpa_sm *sm, + const struct wpa_eapol_key *key, + const u8 *gtk, size_t gtk_len, + int key_info) +{ + struct wpa_gtk_data gd; + + /* + * IEEE Std 802.11i-2004 - 8.5.2 EAPOL-Key frames - Figure 43x + * GTK KDE format: + * KeyID[bits 0-1], Tx [bit 2], Reserved [bits 3-7] + * Reserved [bits 0-7] + * GTK + */ + os_memset(&gd, 0, sizeof(gd)); + wpa_hexdump_key(MSG_DEBUG, "RSN: received GTK in pairwise handshake", + gtk, gtk_len); + + if (gtk_len < 2 || gtk_len - 2 > sizeof(gd.gtk)) + return -1; + + gd.keyidx = gtk[0] & 0x3; + gd.tx = wpa_supplicant_gtk_tx_bit_workaround(sm, + !!(gtk[0] & BIT(2))); + gtk += 2; + gtk_len -= 2; + + os_memcpy(gd.gtk, gtk, gtk_len); + gd.gtk_len = gtk_len; + + if (sm->group_cipher != WPA_CIPHER_GTK_NOT_USED && + (wpa_supplicant_check_group_cipher(sm, sm->group_cipher, + gtk_len, gtk_len, + &gd.key_rsc_len, &gd.alg) || + wpa_supplicant_install_gtk(sm, &gd, key->key_rsc, 0))) + { + os_memset(&gd, 0, sizeof(gd)); + return -1; + } + os_memset(&gd, 0, sizeof(gd)); + + wpa_supplicant_key_neg_complete(sm, sm->bssid, + key_info & WPA_KEY_INFO_SECURE); + return 0; +} + +#ifdef CONFIG_IEEE80211W +static int wpa_supplicant_install_igtk(struct wpa_sm *sm, + const struct wpa_igtk_kde *igtk, + int wnm_sleep)) +{ + size_t len = wpa_cipher_key_len(sm->mgmt_group_cipher); + u16 keyidx = WPA_GET_LE16(igtk->keyid); + + /* Detect possible key reinstallation */ + if ((sm->igtk.igtk_len == len && + os_memcmp(sm->igtk.igtk, igtk->igtk, sm->igtk.igtk_len) == 0) || + (sm->igtk_wnm_sleep.igtk_len == len && + os_memcmp(sm->igtk_wnm_sleep.igtk, igtk->igtk, + sm->igtk_wnm_sleep.igtk_len) == 0)) { + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, + "WPA: Not reinstalling already in-use IGTK to the driver (keyidx=%d)", + keyidx); + return 0; + } + + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, + "WPA: IGTK keyid %d pn %02x%02x%02x%02x%02x%02x", + keyidx, MAC2STR(igtk->pn)); + wpa_hexdump_key(MSG_DEBUG, "WPA: IGTK", igtk->igtk, len); + if (keyidx > 4095) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "WPA: Invalid IGTK KeyID %d", keyidx); + return -1; + } + if (wpa_sm_set_key(sm, wpa_cipher_to_alg(sm->mgmt_group_cipher), + broadcast_ether_addr, + keyidx, 0, igtk->pn, sizeof(igtk->pn), + igtk->igtk, len) < 0) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "WPA: Failed to configure IGTK to the driver"); + return -1; + } + + if (wnm_sleep) { + sm->igtk_wnm_sleep.igtk_len = len; + os_memcpy(sm->igtk_wnm_sleep.igtk, igtk->igtk, + sm->igtk_wnm_sleep.igtk_len); + } else { + sm->igtk.igtk_len = len; + os_memcpy(sm->igtk.igtk, igtk->igtk, sm->igtk.igtk_len); + } + + return 0; +} +#endif /* CONFIG_IEEE80211W */ + + +static int ieee80211w_set_keys(struct wpa_sm *sm, + struct wpa_eapol_ie_parse *ie) +{ +#ifdef CONFIG_IEEE80211W + if (!wpa_cipher_valid_mgmt_group(sm->mgmt_group_cipher)) + return 0; + + if (ie->igtk) { + size_t len; + const struct wpa_igtk_kde *igtk; + + len = wpa_cipher_key_len(sm->mgmt_group_cipher); + if (ie->igtk_len != WPA_IGTK_KDE_PREFIX_LEN + len) + return -1; + + igtk = (const struct wpa_igtk_kde *) ie->igtk; + + if (wpa_supplicant_install_igtk(sm, igtk, 0) < 0) + return -1; + } + + return 0; +#else /* CONFIG_IEEE80211W */ + return 0; +#endif /* CONFIG_IEEE80211W */ +} + + +static void wpa_report_ie_mismatch(struct wpa_sm *sm, + const char *reason, const u8 *src_addr, + const u8 *wpa_ie, size_t wpa_ie_len, + const u8 *rsn_ie, size_t rsn_ie_len) +{ + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, "WPA: %s (src=" MACSTR ")", + reason, MAC2STR(src_addr)); + + if (sm->ap_wpa_ie) { + wpa_hexdump(MSG_INFO, "WPA: WPA IE in Beacon/ProbeResp", + sm->ap_wpa_ie, sm->ap_wpa_ie_len); + } + if (wpa_ie) { + if (!sm->ap_wpa_ie) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "WPA: No WPA IE in Beacon/ProbeResp"); + } + wpa_hexdump(MSG_INFO, "WPA: WPA IE in 3/4 msg", + wpa_ie, wpa_ie_len); + } + + if (sm->ap_rsn_ie) { + wpa_hexdump(MSG_INFO, "WPA: RSN IE in Beacon/ProbeResp", + sm->ap_rsn_ie, sm->ap_rsn_ie_len); + } + if (rsn_ie) { + if (!sm->ap_rsn_ie) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "WPA: No RSN IE in Beacon/ProbeResp"); + } + wpa_hexdump(MSG_INFO, "WPA: RSN IE in 3/4 msg", + rsn_ie, rsn_ie_len); + } + + wpa_sm_deauthenticate(sm, WLAN_REASON_IE_IN_4WAY_DIFFERS); +} + +static int wpa_supplicant_validate_ie(struct wpa_sm *sm, + const unsigned char *src_addr, + struct wpa_eapol_ie_parse *ie) +{ + if (sm->ap_wpa_ie == NULL && sm->ap_rsn_ie == NULL) { + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, + "WPA: No WPA/RSN IE for this AP known. " + "Trying to get from scan results"); + if (wpa_sm_get_beacon_ie(sm) < 0) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "WPA: Could not find AP from " + "the scan results"); + } else { + wpa_msg(sm->ctx->msg_ctx, MSG_DEBUG, + "WPA: Found the current AP from " + "updated scan results"); + } + } + + if (ie->wpa_ie == NULL && ie->rsn_ie == NULL && + (sm->ap_wpa_ie || sm->ap_rsn_ie)) { + wpa_report_ie_mismatch(sm, "IE in 3/4 msg does not match " + "with IE in Beacon/ProbeResp (no IE?)", + src_addr, ie->wpa_ie, ie->wpa_ie_len, + ie->rsn_ie, ie->rsn_ie_len); + return -1; + } + + if ((ie->wpa_ie && sm->ap_wpa_ie && + (ie->wpa_ie_len != sm->ap_wpa_ie_len || + os_memcmp(ie->wpa_ie, sm->ap_wpa_ie, ie->wpa_ie_len) != 0)) || + (ie->rsn_ie && sm->ap_rsn_ie && + wpa_compare_rsn_ie(wpa_key_mgmt_ft(sm->key_mgmt), + sm->ap_rsn_ie, sm->ap_rsn_ie_len, + ie->rsn_ie, ie->rsn_ie_len))) { + wpa_report_ie_mismatch(sm, "IE in 3/4 msg does not match " + "with IE in Beacon/ProbeResp", + src_addr, ie->wpa_ie, ie->wpa_ie_len, + ie->rsn_ie, ie->rsn_ie_len); + return -1; + } + + if (sm->proto == WPA_PROTO_WPA && + ie->rsn_ie && sm->ap_rsn_ie == NULL && sm->rsn_enabled) { + wpa_report_ie_mismatch(sm, "Possible downgrade attack " + "detected - RSN was enabled and RSN IE " + "was in msg 3/4, but not in " + "Beacon/ProbeResp", + src_addr, ie->wpa_ie, ie->wpa_ie_len, + ie->rsn_ie, ie->rsn_ie_len); + return -1; + } + + return 0; +} + + +/** + * wpa_supplicant_send_4_of_4 - Send message 4 of WPA/RSN 4-Way Handshake + * @sm: Pointer to WPA state machine data from wpa_sm_init() + * @dst: Destination address for the frame + * @key: Pointer to the EAPOL-Key frame header + * @ver: Version bits from EAPOL-Key Key Info + * @key_info: Key Info + * @ptk: PTK to use for keyed hash and encryption + * Returns: 0 on success, -1 on failure + */ +int wpa_supplicant_send_4_of_4(struct wpa_sm *sm, const unsigned char *dst, + const struct wpa_eapol_key *key, + u16 ver, u16 key_info, + struct wpa_ptk *ptk) +{ + size_t mic_len, hdrlen, rlen; + struct wpa_eapol_key *reply; + struct wpa_eapol_key_192 *reply192; + u8 *rbuf, *key_mic; + + mic_len = wpa_mic_len(sm->key_mgmt); + hdrlen = mic_len == 24 ? sizeof(*reply192) : sizeof(*reply); + rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, + hdrlen, &rlen, (void *) &reply); + if (rbuf == NULL) + return -1; + reply192 = (struct wpa_eapol_key_192 *) reply; + + reply->type = (sm->proto == WPA_PROTO_RSN || + sm->proto == WPA_PROTO_OSEN) ? + EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA; + key_info &= WPA_KEY_INFO_SECURE; + key_info |= ver | WPA_KEY_INFO_KEY_TYPE | WPA_KEY_INFO_MIC; + WPA_PUT_BE16(reply->key_info, key_info); + if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) + WPA_PUT_BE16(reply->key_length, 0); + else + os_memcpy(reply->key_length, key->key_length, 2); + os_memcpy(reply->replay_counter, key->replay_counter, + WPA_REPLAY_COUNTER_LEN); + + key_mic = reply192->key_mic; /* same offset for reply and reply192 */ + if (mic_len == 24) + WPA_PUT_BE16(reply192->key_data_length, 0); + else + WPA_PUT_BE16(reply->key_data_length, 0); + + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 4/4"); + return wpa_eapol_key_send(sm, ptk->kck, ptk->kck_len, ver, dst, ETH_P_EAPOL, + rbuf, rlen, key_mic); +} + + +static void wpa_supplicant_process_3_of_4(struct wpa_sm *sm, + const struct wpa_eapol_key *key, + u16 ver, const u8 *key_data, + size_t key_data_len) +{ + u16 key_info, keylen; + struct wpa_eapol_ie_parse ie; + + wpa_sm_set_state(sm, WPA_4WAY_HANDSHAKE); + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: RX message 3 of 4-Way " + "Handshake from " MACSTR " (ver=%d)", MAC2STR(sm->bssid), ver); + + key_info = WPA_GET_BE16(key->key_info); + + wpa_hexdump(MSG_DEBUG, "WPA: IE KeyData", key_data, key_data_len); + if (wpa_supplicant_parse_ies(key_data, key_data_len, &ie) < 0) + goto failed; + if (ie.gtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "WPA: GTK IE in unencrypted key data"); + goto failed; + } +#ifdef CONFIG_IEEE80211W + if (ie.igtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "WPA: IGTK KDE in unencrypted key data"); + goto failed; + } + + if (ie.igtk && + wpa_cipher_valid_mgmt_group(sm->mgmt_group_cipher) && + ie.igtk_len != WPA_IGTK_KDE_PREFIX_LEN + + (unsigned int) wpa_cipher_key_len(sm->mgmt_group_cipher)) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "WPA: Invalid IGTK KDE length %lu", + (unsigned long) ie.igtk_len); + goto failed; + } +#endif /* CONFIG_IEEE80211W */ + + if (wpa_supplicant_validate_ie(sm, sm->bssid, &ie) < 0) + goto failed; + + if (os_memcmp(sm->anonce, key->key_nonce, WPA_NONCE_LEN) != 0) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "WPA: ANonce from message 1 of 4-Way Handshake " + "differs from 3 of 4-Way Handshake - drop packet (src=" + MACSTR ")", MAC2STR(sm->bssid)); + goto failed; + } + + keylen = WPA_GET_BE16(key->key_length); + if (keylen != wpa_cipher_key_len(sm->pairwise_cipher)) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "WPA: Invalid %s key length %d (src=" MACSTR + ")", wpa_cipher_txt(sm->pairwise_cipher), keylen, + MAC2STR(sm->bssid)); + goto failed; + } + +#ifdef CONFIG_P2P + if (ie.ip_addr_alloc) { + os_memcpy(sm->p2p_ip_addr, ie.ip_addr_alloc, 3 * 4); + wpa_hexdump(MSG_DEBUG, "P2P: IP address info", + sm->p2p_ip_addr, sizeof(sm->p2p_ip_addr)); + } +#endif /* CONFIG_P2P */ + + if (wpa_supplicant_send_4_of_4(sm, sm->bssid, key, ver, key_info, + &sm->ptk) < 0) { + goto tx_failed; + } + + /* SNonce was successfully used in msg 3/4, so mark it to be renewed + * for the next 4-Way Handshake. If msg 3 is received again, the old + * SNonce will still be used to avoid changing PTK. */ + sm->renew_snonce = 1; + + if (key_info & WPA_KEY_INFO_INSTALL) { + if (wpa_supplicant_install_ptk(sm, key)) + goto failed; + } + + if (key_info & WPA_KEY_INFO_SECURE) { + wpa_sm_mlme_setprotection( + sm, sm->bssid, MLME_SETPROTECTION_PROTECT_TYPE_RX, + MLME_SETPROTECTION_KEY_TYPE_PAIRWISE); + eapol_sm_notify_portValid(sm->eapol, TRUE); + } + wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE); + + if (sm->group_cipher == WPA_CIPHER_GTK_NOT_USED) { + wpa_supplicant_key_neg_complete(sm, sm->bssid, + key_info & WPA_KEY_INFO_SECURE); + } else if (ie.gtk && + wpa_supplicant_pairwise_gtk(sm, key, + ie.gtk, ie.gtk_len, key_info) < 0) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "RSN: Failed to configure GTK"); + goto failed; + } + + if (ieee80211w_set_keys(sm, &ie) < 0) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "RSN: Failed to configure IGTK"); + goto failed; + } + + if (ie.gtk) + wpa_sm_set_rekey_offload(sm); + + if (sm->proto == WPA_PROTO_RSN && wpa_key_mgmt_suite_b(sm->key_mgmt)) { + struct rsn_pmksa_cache_entry *sa; + + sa = pmksa_cache_add(sm->pmksa, sm->pmk, sm->pmk_len, + sm->ptk.kck, sm->ptk.kck_len, + sm->bssid, sm->own_addr, + sm->network_ctx, sm->key_mgmt); + if (!sm->cur_pmksa) + sm->cur_pmksa = sa; + } + + sm->msg_3_of_4_ok = 1; + return; + +tx_failed: + os_printf("%s: tx eapol failed\r\n", __func__); + return; //server may retry to resend to us. + +failed: + wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED); +} + + +static int wpa_supplicant_process_1_of_2_rsn(struct wpa_sm *sm, + const u8 *keydata, + size_t keydatalen, + u16 key_info, + struct wpa_gtk_data *gd) +{ + int maxkeylen; + struct wpa_eapol_ie_parse ie; + + wpa_hexdump(MSG_DEBUG, "RSN: msg 1/2 key data", keydata, keydatalen); + if (wpa_supplicant_parse_ies(keydata, keydatalen, &ie) < 0) + return -1; + if (ie.gtk && !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "WPA: GTK IE in unencrypted key data"); + return -1; + } + if (ie.gtk == NULL) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "WPA: No GTK IE in Group Key msg 1/2"); + return -1; + } + maxkeylen = gd->gtk_len = ie.gtk_len - 2; + + if (wpa_supplicant_check_group_cipher(sm, sm->group_cipher, + gd->gtk_len, maxkeylen, + &gd->key_rsc_len, &gd->alg)) + return -1; + + wpa_hexdump_key(MSG_DEBUG, "RSN: received GTK in group key handshake", + ie.gtk, ie.gtk_len); + gd->keyidx = ie.gtk[0] & 0x3; + gd->tx = wpa_supplicant_gtk_tx_bit_workaround(sm, + !!(ie.gtk[0] & BIT(2))); + if (ie.gtk_len - 2 > sizeof(gd->gtk)) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "RSN: Too long GTK in GTK IE (len=%lu)", + (unsigned long) ie.gtk_len - 2); + return -1; + } + os_memcpy(gd->gtk, ie.gtk + 2, ie.gtk_len - 2); + + if (ieee80211w_set_keys(sm, &ie) < 0) + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "RSN: Failed to configure IGTK"); + + return 0; +} + + +static int wpa_supplicant_process_1_of_2_wpa(struct wpa_sm *sm, + const struct wpa_eapol_key *key, + const u8 *key_data, + size_t key_data_len, u16 key_info, + u16 ver, struct wpa_gtk_data *gd) +{ + size_t maxkeylen; + u16 gtk_len; + + gtk_len = WPA_GET_BE16(key->key_length); + maxkeylen = key_data_len; + if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { + if (maxkeylen < 8) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "WPA: Too short maxkeylen (%lu)", + (unsigned long) maxkeylen); + return -1; + } + maxkeylen -= 8; + } + + if (gtk_len > maxkeylen || + wpa_supplicant_check_group_cipher(sm, sm->group_cipher, + gtk_len, maxkeylen, + &gd->key_rsc_len, &gd->alg)) + return -1; + + gd->gtk_len = gtk_len; + gd->keyidx = (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >> + WPA_KEY_INFO_KEY_INDEX_SHIFT; + if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 && sm->ptk.kek_len == 16) { +#ifdef CONFIG_NO_RC4 + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "WPA: RC4 not supported in the build"); + return -1; +#else /* CONFIG_NO_RC4 */ + u8 ek[32]; + if (key_data_len > sizeof(gd->gtk)) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "WPA: RC4 key data too long (%lu)", + (unsigned long) key_data_len); + return -1; + } + os_memcpy(ek, key->key_iv, 16); + os_memcpy(ek + 16, sm->ptk.kek, sm->ptk.kek_len); + os_memcpy(gd->gtk, key_data, key_data_len); + if (rc4_skip(ek, 32, 256, gd->gtk, key_data_len)) { + os_memset(ek, 0, sizeof(ek)); + wpa_msg(sm->ctx->msg_ctx, MSG_ERROR, + "WPA: RC4 failed"); + return -1; + } + os_memset(ek, 0, sizeof(ek)); +#endif /* CONFIG_NO_RC4 */ + } else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { + if (maxkeylen % 8) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "WPA: Unsupported AES-WRAP len %lu", + (unsigned long) maxkeylen); + return -1; + } + if (maxkeylen > sizeof(gd->gtk)) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "WPA: AES-WRAP key data " + "too long (keydatalen=%lu maxkeylen=%lu)", + (unsigned long) key_data_len, + (unsigned long) maxkeylen); + return -1; + } + if (aes_unwrap(sm->ptk.kek, sm->ptk.kek_len, maxkeylen / 8, + key_data, gd->gtk)) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "WPA: AES unwrap failed - could not decrypt " + "GTK"); + return -1; + } + } else { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "WPA: Unsupported key_info type %d", ver); + return -1; + } + gd->tx = wpa_supplicant_gtk_tx_bit_workaround( + sm, !!(key_info & WPA_KEY_INFO_TXRX)); + return 0; +} + + +static int wpa_supplicant_send_2_of_2(struct wpa_sm *sm, + const struct wpa_eapol_key *key, + int ver, u16 key_info) +{ + size_t mic_len, hdrlen, rlen; + struct wpa_eapol_key *reply; + struct wpa_eapol_key_192 *reply192; + u8 *rbuf, *key_mic; + + mic_len = wpa_mic_len(sm->key_mgmt); + hdrlen = mic_len == 24 ? sizeof(*reply192) : sizeof(*reply); + rbuf = wpa_sm_alloc_eapol(sm, IEEE802_1X_TYPE_EAPOL_KEY, NULL, + hdrlen, &rlen, (void *) &reply); + if (rbuf == NULL) + return -1; + reply192 = (struct wpa_eapol_key_192 *) reply; + + reply->type = (sm->proto == WPA_PROTO_RSN || + sm->proto == WPA_PROTO_OSEN) ? + EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA; + key_info &= WPA_KEY_INFO_KEY_INDEX_MASK; + key_info |= ver | WPA_KEY_INFO_MIC | WPA_KEY_INFO_SECURE; + WPA_PUT_BE16(reply->key_info, key_info); + if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) + WPA_PUT_BE16(reply->key_length, 0); + else + os_memcpy(reply->key_length, key->key_length, 2); + os_memcpy(reply->replay_counter, key->replay_counter, + WPA_REPLAY_COUNTER_LEN); + + key_mic = reply192->key_mic; /* same offset for reply and reply192 */ + if (mic_len == 24) + WPA_PUT_BE16(reply192->key_data_length, 0); + else + WPA_PUT_BE16(reply->key_data_length, 0); + + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Sending EAPOL-Key 2/2"); + return wpa_eapol_key_send(sm, sm->ptk.kck, sm->ptk.kck_len, ver, sm->bssid, + ETH_P_EAPOL, rbuf, rlen, key_mic); +} + + +static void wpa_supplicant_process_1_of_2(struct wpa_sm *sm, + const unsigned char *src_addr, + const struct wpa_eapol_key *key, + const u8 *key_data, + size_t key_data_len, u16 ver) +{ + u16 key_info; + int rekey, ret; + struct wpa_gtk_data gd; + + if (!sm->msg_3_of_4_ok) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "WPA: Group Key Handshake started prior to completion of 4-way handshake"); + goto failed; + } + + os_memset(&gd, 0, sizeof(gd)); + + rekey = wpa_sm_get_state(sm) == WPA_COMPLETED; + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: RX message 1 of Group Key " + "Handshake from " MACSTR " (ver=%d)", MAC2STR(src_addr), ver); + + key_info = WPA_GET_BE16(key->key_info); + + if (sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) { + ret = wpa_supplicant_process_1_of_2_rsn(sm, key_data, + key_data_len, key_info, + &gd); + } else { + ret = wpa_supplicant_process_1_of_2_wpa(sm, key, key_data, + key_data_len, + key_info, ver, &gd); + } + + wpa_sm_set_state(sm, WPA_GROUP_HANDSHAKE); + + if (ret) + goto failed; + + if (wpa_supplicant_install_gtk(sm, &gd, key->key_rsc, 0)) + goto failed; + + if (wpa_supplicant_send_2_of_2(sm, key, ver, key_info)) + goto tx_failed; + os_memset(&gd, 0, sizeof(gd)); + + if (rekey) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Group rekeying " + "completed with " MACSTR " [GTK=%s]", + MAC2STR(sm->bssid), wpa_cipher_txt(sm->group_cipher)); + wpa_sm_cancel_auth_timeout(sm); + wpa_sm_set_state(sm, WPA_COMPLETED); + } else { + wpa_supplicant_key_neg_complete(sm, sm->bssid, + key_info & + WPA_KEY_INFO_SECURE); + } + + wpa_sm_set_rekey_offload(sm); + + return; + +tx_failed: + wpa_dbg("%s: tx eapol failed\r\n",MSG_WARNING, __func__); + return; //server may retry to resend to us. + +failed: + os_memset(&gd, 0, sizeof(gd)); + wpa_sm_deauthenticate(sm, WLAN_REASON_UNSPECIFIED); +} + + +static int wpa_supplicant_verify_eapol_key_mic(struct wpa_sm *sm, + struct wpa_eapol_key_192 *key, + u16 ver, + const u8 *buf, size_t len) +{ + u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN]; + int ok = 0; + size_t mic_len = wpa_mic_len(sm->key_mgmt); + + os_memcpy(mic, key->key_mic, mic_len); + if (sm->tptk_set) { + os_memset(key->key_mic, 0, mic_len); + wpa_eapol_key_mic(sm->tptk.kck, sm->tptk.kck_len, sm->key_mgmt, + ver, buf, len, key->key_mic); + if (os_memcmp_const(mic, key->key_mic, mic_len) != 0) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "WPA: Invalid EAPOL-Key MIC " + "when using TPTK - ignoring TPTK"); + } else { + ok = 1; + sm->tptk_set = 0; + sm->ptk_set = 1; + os_memcpy(&sm->ptk, &sm->tptk, sizeof(sm->ptk)); + os_memset(&sm->tptk, 0, sizeof(sm->tptk)); + } + } + + if (!ok && sm->ptk_set) { + os_memset(key->key_mic, 0, mic_len); + wpa_eapol_key_mic(sm->ptk.kck, sm->ptk.kck_len, sm->key_mgmt, + ver, buf, len, key->key_mic); + if (os_memcmp_const(mic, key->key_mic, mic_len) != 0) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "WPA: Invalid EAPOL-Key MIC - " + "dropping packet"); + return -1; + } + ok = 1; + } + + if (!ok) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "WPA: Could not verify EAPOL-Key MIC - " + "dropping packet"); + return -1; + } + + os_memcpy(sm->rx_replay_counter, key->replay_counter, + WPA_REPLAY_COUNTER_LEN); + sm->rx_replay_counter_set = 1; + return 0; +} + + +/* Decrypt RSN EAPOL-Key key data (RC4 or AES-WRAP) */ +static int wpa_supplicant_decrypt_key_data(struct wpa_sm *sm, + struct wpa_eapol_key *key, u16 ver, + u8 *key_data, size_t *key_data_len) +{ + wpa_hexdump(MSG_DEBUG, "RSN: encrypted key data", + key_data, *key_data_len); + if (!sm->ptk_set) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "WPA: PTK not available, cannot decrypt EAPOL-Key Key " + "Data"); + return -1; + } + + /* Decrypt key data here so that this operation does not need + * to be implemented separately for each message type. */ + if (ver == WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 && sm->ptk.kek_len == 16) { +#ifdef CONFIG_NO_RC4 + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "WPA: RC4 not supported in the build"); + return -1; +#else /* CONFIG_NO_RC4 */ + u8 ek[32]; + os_memcpy(ek, key->key_iv, 16); + os_memcpy(ek + 16, sm->ptk.kek, sm->ptk.kek_len); + if (rc4_skip(ek, 32, 256, key_data, *key_data_len)) { + os_memset(ek, 0, sizeof(ek)); + wpa_msg(sm->ctx->msg_ctx, MSG_ERROR, + "WPA: RC4 failed"); + return -1; + } + os_memset(ek, 0, sizeof(ek)); +#endif /* CONFIG_NO_RC4 */ + } else if (ver == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES || + ver == WPA_KEY_INFO_TYPE_AES_128_CMAC || + sm->key_mgmt == WPA_KEY_MGMT_OSEN || + wpa_key_mgmt_suite_b(sm->key_mgmt)) { + u8 *buf; + if (*key_data_len < 8 || *key_data_len % 8) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "WPA: Unsupported AES-WRAP len %u", + (unsigned int) *key_data_len); + return -1; + } + *key_data_len -= 8; /* AES-WRAP adds 8 bytes */ + buf = os_malloc(*key_data_len); + if (buf == NULL) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "WPA: No memory for AES-UNWRAP buffer"); + return -1; + } + if (aes_unwrap(sm->ptk.kek, sm->ptk.kek_len, *key_data_len / 8, + key_data, buf)) { + os_free(buf); + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "WPA: AES unwrap failed - " + "could not decrypt EAPOL-Key key data"); + return -1; + } + os_memcpy(key_data, buf, *key_data_len); + os_free(buf); + WPA_PUT_BE16(key->key_data_length, *key_data_len); + } else { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "WPA: Unsupported key_info type %d", ver); + return -1; + } + wpa_hexdump_key(MSG_DEBUG, "WPA: decrypted EAPOL-Key key data", + key_data, *key_data_len); + return 0; +} + + +/** + * wpa_sm_aborted_cached - Notify WPA that PMKSA caching was aborted + * @sm: Pointer to WPA state machine data from wpa_sm_init() + */ +void wpa_sm_aborted_cached(struct wpa_sm *sm) +{ + if (sm && sm->cur_pmksa) { + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, + "RSN: Cancelling PMKSA caching attempt"); + sm->cur_pmksa = NULL; + } +} + + +static void wpa_eapol_key_dump(struct wpa_sm *sm, + const struct wpa_eapol_key *key, + unsigned int key_data_len, + const u8 *mic, unsigned int mic_len) +{ +#ifndef CONFIG_NO_STDOUT_DEBUG + u16 key_info = WPA_GET_BE16(key->key_info); + + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, " EAPOL-Key type=%d", key->type); + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, + " key_info 0x%x (ver=%d keyidx=%d rsvd=%d %s%s%s%s%s%s%s%s)", + key_info, key_info & WPA_KEY_INFO_TYPE_MASK, + (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) >> + WPA_KEY_INFO_KEY_INDEX_SHIFT, + (key_info & (BIT(13) | BIT(14) | BIT(15))) >> 13, + key_info & WPA_KEY_INFO_KEY_TYPE ? "Pairwise" : "Group", + key_info & WPA_KEY_INFO_INSTALL ? " Install" : "", + key_info & WPA_KEY_INFO_ACK ? " Ack" : "", + key_info & WPA_KEY_INFO_MIC ? " MIC" : "", + key_info & WPA_KEY_INFO_SECURE ? " Secure" : "", + key_info & WPA_KEY_INFO_ERROR ? " Error" : "", + key_info & WPA_KEY_INFO_REQUEST ? " Request" : "", + key_info & WPA_KEY_INFO_ENCR_KEY_DATA ? " Encr" : ""); + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, + " key_length=%u key_data_length=%u", + WPA_GET_BE16(key->key_length), key_data_len); + wpa_hexdump(MSG_DEBUG, " replay_counter", + key->replay_counter, WPA_REPLAY_COUNTER_LEN); + wpa_hexdump(MSG_DEBUG, " key_nonce", key->key_nonce, WPA_NONCE_LEN); + wpa_hexdump(MSG_DEBUG, " key_iv", key->key_iv, 16); + wpa_hexdump(MSG_DEBUG, " key_rsc", key->key_rsc, 8); + wpa_hexdump(MSG_DEBUG, " key_id (reserved)", key->key_id, 8); + wpa_hexdump(MSG_DEBUG, " key_mic", mic, mic_len); +#endif /* CONFIG_NO_STDOUT_DEBUG */ +} + + +/** + * wpa_sm_rx_eapol - Process received WPA EAPOL frames + * @sm: Pointer to WPA state machine data from wpa_sm_init() + * @src_addr: Source MAC address of the EAPOL packet + * @buf: Pointer to the beginning of the EAPOL data (EAPOL header) + * @len: Length of the EAPOL frame + * Returns: 1 = WPA EAPOL-Key processed, 0 = not a WPA EAPOL-Key, -1 failure + * + * This function is called for each received EAPOL frame. Other than EAPOL-Key + * frames can be skipped if filtering is done elsewhere. wpa_sm_rx_eapol() is + * only processing WPA and WPA2 EAPOL-Key frames. + * + * The received EAPOL-Key packets are validated and valid packets are replied + * to. In addition, key material (PTK, GTK) is configured at the end of a + * successful key handshake. + */ +int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr, + const u8 *buf, size_t len) +{ + size_t plen, data_len, key_data_len; + const struct ieee802_1x_hdr *hdr; + struct wpa_eapol_key *key; + struct wpa_eapol_key_192 *key192; + u16 key_info, ver; + u8 *tmp = NULL; + int ret = -1; + struct wpa_peerkey *peerkey = NULL; + u8 *key_data; + size_t mic_len, keyhdrlen; + +#ifdef CONFIG_IEEE80211R + sm->ft_completed = 0; +#endif /* CONFIG_IEEE80211R */ + + mic_len = wpa_mic_len(sm->key_mgmt); + keyhdrlen = mic_len == 24 ? sizeof(*key192) : sizeof(*key); + + if (len < sizeof(*hdr) + keyhdrlen) { + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, + "WPA: EAPOL frame too short to be a WPA " + "EAPOL-Key (len %lu, expecting at least %lu)", + (unsigned long) len, + (unsigned long) sizeof(*hdr) + keyhdrlen); + return 0; + } + + hdr = (const struct ieee802_1x_hdr *) buf; + plen = be_to_host16(hdr->length); + data_len = plen + sizeof(*hdr); + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, + "IEEE 802.1X RX: version=%d type=%d length=%lu", + hdr->version, hdr->type, (unsigned long) plen); + + if (hdr->version < EAPOL_VERSION) { + /* TODO: backwards compatibility */ + } + if (hdr->type != IEEE802_1X_TYPE_EAPOL_KEY) { + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, + "WPA: EAPOL frame (type %u) discarded, " + "not a Key frame", hdr->type); + ret = 0; + goto out; + } + wpa_hexdump(MSG_MSGDUMP, "WPA: RX EAPOL-Key", buf, len); + if (plen > len - sizeof(*hdr) || plen < keyhdrlen) { + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, + "WPA: EAPOL frame payload size %lu " + "invalid (frame size %lu)", + (unsigned long) plen, (unsigned long) len); + ret = 0; + goto out; + } + if (data_len < len) { + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, + "WPA: ignoring %lu bytes after the IEEE 802.1X data", + (unsigned long) len - data_len); + } + + /* + * Make a copy of the frame since we need to modify the buffer during + * MAC validation and Key Data decryption. + */ + tmp = os_malloc(data_len); + if (tmp == NULL) + goto out; + os_memcpy(tmp, buf, data_len); + key = (struct wpa_eapol_key *) (tmp + sizeof(struct ieee802_1x_hdr)); + key192 = (struct wpa_eapol_key_192 *) + (tmp + sizeof(struct ieee802_1x_hdr)); + if (mic_len == 24) + key_data = (u8 *) (key192 + 1); + else + key_data = (u8 *) (key + 1); + + if (key->type != EAPOL_KEY_TYPE_WPA && key->type != EAPOL_KEY_TYPE_RSN) + { + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, + "WPA: EAPOL-Key type (%d) unknown, discarded", + key->type); + ret = 0; + goto out; + } + + if (mic_len == 24) + key_data_len = WPA_GET_BE16(key192->key_data_length); + else + key_data_len = WPA_GET_BE16(key->key_data_length); + wpa_eapol_key_dump(sm, key, key_data_len, key192->key_mic, mic_len); + + if (key_data_len > plen - keyhdrlen) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, "WPA: Invalid EAPOL-Key " + "frame - key_data overflow (%u > %u)", + (unsigned int) key_data_len, + (unsigned int) (plen - keyhdrlen)); + goto out; + } + + eapol_sm_notify_lower_layer_success(sm->eapol, 0); + key_info = WPA_GET_BE16(key->key_info); + ver = key_info & WPA_KEY_INFO_TYPE_MASK; + if (ver != WPA_KEY_INFO_TYPE_HMAC_MD5_RC4 && +#if defined(CONFIG_IEEE80211R) || defined(CONFIG_IEEE80211W) + ver != WPA_KEY_INFO_TYPE_AES_128_CMAC && +#endif /* CONFIG_IEEE80211R || CONFIG_IEEE80211W */ + ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES && + !wpa_key_mgmt_suite_b(sm->key_mgmt) && + sm->key_mgmt != WPA_KEY_MGMT_OSEN) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "WPA: Unsupported EAPOL-Key descriptor version %d", + ver); + goto out; + } + + if (sm->key_mgmt == WPA_KEY_MGMT_OSEN && + ver != WPA_KEY_INFO_TYPE_AKM_DEFINED) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "OSEN: Unsupported EAPOL-Key descriptor version %d", + ver); + goto out; + } + + if (wpa_key_mgmt_suite_b(sm->key_mgmt) && + ver != WPA_KEY_INFO_TYPE_AKM_DEFINED) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "RSN: Unsupported EAPOL-Key descriptor version %d (expected AKM defined = 0)", + ver); + goto out; + } + +#ifdef CONFIG_IEEE80211W + if (wpa_key_mgmt_sha256(sm->key_mgmt)) { + if (ver != WPA_KEY_INFO_TYPE_AES_128_CMAC && + sm->key_mgmt != WPA_KEY_MGMT_OSEN && + !wpa_key_mgmt_suite_b(sm->key_mgmt)) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "WPA: AP did not use the " + "negotiated AES-128-CMAC"); + goto out; + } + } else +#endif /* CONFIG_IEEE80211W */ + if (sm->pairwise_cipher == WPA_CIPHER_CCMP && + !wpa_key_mgmt_suite_b(sm->key_mgmt) && + ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "WPA: CCMP is used, but EAPOL-Key " + "descriptor version (%d) is not 2", ver); + if (sm->group_cipher != WPA_CIPHER_CCMP && + !(key_info & WPA_KEY_INFO_KEY_TYPE)) { + /* Earlier versions of IEEE 802.11i did not explicitly + * require version 2 descriptor for all EAPOL-Key + * packets, so allow group keys to use version 1 if + * CCMP is not used for them. */ + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "WPA: Backwards compatibility: allow invalid " + "version for non-CCMP group keys"); + } else if (ver == WPA_KEY_INFO_TYPE_AES_128_CMAC) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "WPA: Interoperability workaround: allow incorrect (should have been HMAC-SHA1), but stronger (is AES-128-CMAC), descriptor version to be used"); + } else + goto out; + } else if (sm->pairwise_cipher == WPA_CIPHER_GCMP && + !wpa_key_mgmt_suite_b(sm->key_mgmt) && + ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "WPA: GCMP is used, but EAPOL-Key " + "descriptor version (%d) is not 2", ver); + goto out; + } + +#ifdef CONFIG_PEERKEY + for (peerkey = sm->peerkey; peerkey; peerkey = peerkey->next) { + if (os_memcmp(peerkey->addr, src_addr, ETH_ALEN) == 0) + break; + } + + if (!(key_info & WPA_KEY_INFO_SMK_MESSAGE) && peerkey) { + if (!peerkey->initiator && peerkey->replay_counter_set && + os_memcmp(key->replay_counter, peerkey->replay_counter, + WPA_REPLAY_COUNTER_LEN) <= 0) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "RSN: EAPOL-Key Replay Counter did not " + "increase (STK) - dropping packet"); + goto out; + } else if (peerkey->initiator) { + u8 _tmp[WPA_REPLAY_COUNTER_LEN]; + os_memcpy(_tmp, key->replay_counter, + WPA_REPLAY_COUNTER_LEN); + inc_byte_array(_tmp, WPA_REPLAY_COUNTER_LEN); + if (os_memcmp(_tmp, peerkey->replay_counter, + WPA_REPLAY_COUNTER_LEN) != 0) { + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, + "RSN: EAPOL-Key Replay " + "Counter did not match (STK) - " + "dropping packet"); + goto out; + } + } + } + + if (peerkey && peerkey->initiator && (key_info & WPA_KEY_INFO_ACK)) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "RSN: Ack bit in key_info from STK peer"); + goto out; + } +#endif /* CONFIG_PEERKEY */ + + if (!peerkey && sm->rx_replay_counter_set && + os_memcmp(key->replay_counter, sm->rx_replay_counter, + WPA_REPLAY_COUNTER_LEN) <= 0) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "WPA: EAPOL-Key Replay Counter did not increase - " + "dropping packet"); + goto out; + } + + if (!(key_info & (WPA_KEY_INFO_ACK | WPA_KEY_INFO_SMK_MESSAGE)) +#ifdef CONFIG_PEERKEY + && (peerkey == NULL || !peerkey->initiator) +#endif /* CONFIG_PEERKEY */ + ) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "WPA: No Ack bit in key_info"); + goto out; + } + + if (key_info & WPA_KEY_INFO_REQUEST) { + wpa_msg(sm->ctx->msg_ctx, MSG_INFO, + "WPA: EAPOL-Key with Request bit - dropped"); + goto out; + } + + if ((key_info & WPA_KEY_INFO_MIC) && !peerkey && + wpa_supplicant_verify_eapol_key_mic(sm, key192, ver, tmp, data_len)) + goto out; + +#ifdef CONFIG_PEERKEY + if ((key_info & WPA_KEY_INFO_MIC) && peerkey && + peerkey_verify_eapol_key_mic(sm, peerkey, key192, ver, tmp, + data_len)) + goto out; +#endif /* CONFIG_PEERKEY */ + + if ((sm->proto == WPA_PROTO_RSN || sm->proto == WPA_PROTO_OSEN) && + (key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) { + if (wpa_supplicant_decrypt_key_data(sm, key, ver, key_data, + &key_data_len)) + goto out; + } + + if (key_info & WPA_KEY_INFO_KEY_TYPE) { + if (key_info & WPA_KEY_INFO_KEY_INDEX_MASK) { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "WPA: Ignored EAPOL-Key (Pairwise) with " + "non-zero key index"); + goto out; + } + if (peerkey) { + /* PeerKey 4-Way Handshake */ + peerkey_rx_eapol_4way(sm, peerkey, key, key_info, ver, + key_data, key_data_len); + } else if (key_info & WPA_KEY_INFO_MIC) { + /* 3/4 4-Way Handshake */ + wpa_supplicant_process_3_of_4(sm, key, ver, key_data, + key_data_len); + } else { + /* 1/4 4-Way Handshake */ + wpa_supplicant_process_1_of_4(sm, src_addr, key, + ver, key_data, + key_data_len); + } + } else if (key_info & WPA_KEY_INFO_SMK_MESSAGE) { + /* PeerKey SMK Handshake */ + peerkey_rx_eapol_smk(sm, src_addr, key, key_data_len, key_info, + ver); + } else { + if (key_info & WPA_KEY_INFO_MIC) { + /* 1/2 Group Key Handshake */ + wpa_supplicant_process_1_of_2(sm, src_addr, key, + key_data, key_data_len, + ver); + } else { + wpa_msg(sm->ctx->msg_ctx, MSG_WARNING, + "WPA: EAPOL-Key (Group) without Mic bit - " + "dropped"); + } + } + + ret = 1; + +out: + bin_clear_free(tmp, data_len); + return ret; +} + + +/** + * wpa_sm_init - Initialize WPA state machine + * @ctx: Context pointer for callbacks; this needs to be an allocated buffer + * Returns: Pointer to the allocated WPA state machine data + * + * This function is used to allocate a new WPA state machine and the returned + * value is passed to all WPA state machine calls. + */ +struct wpa_sm * wpa_sm_init(struct wpa_sm_ctx *ctx) +{ + struct wpa_sm *sm; + + sm = os_zalloc(sizeof(*sm)); + if (sm == NULL) + return NULL; + dl_list_init(&sm->pmksa_candidates); + sm->renew_snonce = 1; + sm->ctx = ctx; + + sm->dot11RSNAConfigPMKLifetime = 43200; + sm->dot11RSNAConfigPMKReauthThreshold = 70; + sm->dot11RSNAConfigSATimeout = 60; + + return sm; +} + + +/** + * wpa_sm_deinit - Deinitialize WPA state machine + * @sm: Pointer to WPA state machine data from wpa_sm_init() + */ +void wpa_sm_deinit(struct wpa_sm *sm) +{ + if (sm == NULL) + return; + pmksa_cache_deinit(sm->pmksa); + eloop_cancel_timeout(wpa_sm_start_preauth, sm, NULL); + eloop_cancel_timeout(wpa_sm_rekey_ptk, sm, NULL); + os_free(sm->assoc_wpa_ie); + os_free(sm->ap_wpa_ie); + os_free(sm->ap_rsn_ie); + wpa_sm_drop_sa(sm); + os_free(sm->ctx); + peerkey_deinit(sm); +#ifdef CONFIG_IEEE80211R + os_free(sm->assoc_resp_ies); +#endif /* CONFIG_IEEE80211R */ + os_free(sm); +} + + +/** + * wpa_sm_notify_assoc - Notify WPA state machine about association + * @sm: Pointer to WPA state machine data from wpa_sm_init() + * @bssid: The BSSID of the new association + * + * This function is called to let WPA state machine know that the connection + * was established. + */ +void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid) +{ + int clear_keys = 1; + + if (sm == NULL) + return; + + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, + "WPA: Association event - clear replay counter"); + os_memcpy(sm->bssid, bssid, ETH_ALEN); + os_memset(sm->rx_replay_counter, 0, WPA_REPLAY_COUNTER_LEN); + sm->rx_replay_counter_set = 0; + sm->renew_snonce = 1; + if (os_memcmp(sm->preauth_bssid, bssid, ETH_ALEN) == 0) + rsn_preauth_deinit(sm); + + if (clear_keys) { + /* + * IEEE 802.11, 8.4.10: Delete PTK SA on (re)association if + * this is not part of a Fast BSS Transition. + */ + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Clear old PTK"); + sm->ptk_set = 0; + os_memset(&sm->ptk, 0, sizeof(sm->ptk)); + sm->tptk_set = 0; + os_memset(&sm->tptk, 0, sizeof(sm->tptk)); + os_memset(&sm->gtk, 0, sizeof(sm->gtk)); + os_memset(&sm->gtk_wnm_sleep, 0, sizeof(sm->gtk_wnm_sleep)); +#ifdef CONFIG_IEEE80211W + os_memset(&sm->igtk, 0, sizeof(sm->igtk)); + os_memset(&sm->igtk_wnm_sleep, 0, sizeof(sm->igtk_wnm_sleep)); +#endif /* CONFIG_IEEE80211W */ + } + +#ifdef CONFIG_TDLS + wpa_tdls_assoc(sm); +#endif /* CONFIG_TDLS */ + +#ifdef CONFIG_P2P + os_memset(sm->p2p_ip_addr, 0, sizeof(sm->p2p_ip_addr)); +#endif /* CONFIG_P2P */ +} + + +/** + * wpa_sm_notify_disassoc - Notify WPA state machine about disassociation + * @sm: Pointer to WPA state machine data from wpa_sm_init() + * + * This function is called to let WPA state machine know that the connection + * was lost. This will abort any existing pre-authentication session. + */ +void wpa_sm_notify_disassoc(struct wpa_sm *sm) +{ + if(!sm) + return; + eloop_cancel_timeout(wpa_sm_start_preauth, sm, NULL); + eloop_cancel_timeout(wpa_sm_rekey_ptk, sm, NULL); + peerkey_deinit(sm); + rsn_preauth_deinit(sm); + pmksa_cache_clear_current(sm); + if (wpa_sm_get_state(sm) == WPA_4WAY_HANDSHAKE) + sm->dot11RSNA4WayHandshakeFailures++; +#ifdef CONFIG_TDLS + wpa_tdls_disassoc(sm); +#endif /* CONFIG_TDLS */ + + /* Keys are not needed in the WPA state machine anymore */ + wpa_sm_drop_sa(sm); + + sm->msg_3_of_4_ok = 0; +} + + +/** + * wpa_sm_set_pmk - Set PMK + * @sm: Pointer to WPA state machine data from wpa_sm_init() + * @pmk: The new PMK + * @pmk_len: The length of the new PMK in bytes + * @bssid: AA to add into PMKSA cache or %NULL to not cache the PMK + * + * Configure the PMK for WPA state machine. + */ +void wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len, + const u8 *bssid) +{ + if (sm == NULL) + return; + + sm->pmk_len = pmk_len; + os_memcpy(sm->pmk, pmk, pmk_len); + + if (bssid) { + pmksa_cache_add(sm->pmksa, pmk, pmk_len, NULL, 0, + bssid, sm->own_addr, + sm->network_ctx, sm->key_mgmt); + } +} + + +/** + * wpa_sm_set_pmk_from_pmksa - Set PMK based on the current PMKSA + * @sm: Pointer to WPA state machine data from wpa_sm_init() + * + * Take the PMK from the current PMKSA into use. If no PMKSA is active, the PMK + * will be cleared. + */ +void wpa_sm_set_pmk_from_pmksa(struct wpa_sm *sm) +{ + if (sm == NULL) + return; + + sm->pmk_len = PMK_LEN; + os_memset(sm->pmk, 0, PMK_LEN); +} + + +/** + * wpa_sm_set_fast_reauth - Set fast reauthentication (EAP) enabled/disabled + * @sm: Pointer to WPA state machine data from wpa_sm_init() + * @fast_reauth: Whether fast reauthentication (EAP) is allowed + */ +void wpa_sm_set_fast_reauth(struct wpa_sm *sm, int fast_reauth) +{ + if (sm) + sm->fast_reauth = fast_reauth; +} + + +/** + * wpa_sm_set_scard_ctx - Set context pointer for smartcard callbacks + * @sm: Pointer to WPA state machine data from wpa_sm_init() + * @scard_ctx: Context pointer for smartcard related callback functions + */ +void wpa_sm_set_scard_ctx(struct wpa_sm *sm, void *scard_ctx) +{ + if (sm == NULL) + return; + sm->scard_ctx = scard_ctx; + if (sm->preauth_eapol) + eapol_sm_register_scard_ctx(sm->preauth_eapol, scard_ctx); +} + + +/** + * wpa_sm_set_config - Notification of current configration change + * @sm: Pointer to WPA state machine data from wpa_sm_init() + * @config: Pointer to current network configuration + * + * Notify WPA state machine that configuration has changed. config will be + * stored as a backpointer to network configuration. This can be %NULL to clear + * the stored pointed. + */ +void wpa_sm_set_config(struct wpa_sm *sm, struct rsn_supp_config *config) +{ + if (!sm) + return; + + if (config) { + sm->network_ctx = config->network_ctx; + sm->peerkey_enabled = config->peerkey_enabled; + sm->allowed_pairwise_cipher = config->allowed_pairwise_cipher; + sm->proactive_key_caching = config->proactive_key_caching; + sm->eap_workaround = config->eap_workaround; + sm->eap_conf_ctx = config->eap_conf_ctx; + if (config->ssid) { + os_memcpy(sm->ssid, config->ssid, config->ssid_len); + sm->ssid_len = config->ssid_len; + } else + sm->ssid_len = 0; + sm->wpa_ptk_rekey = config->wpa_ptk_rekey; + sm->p2p = config->p2p; + } else { + sm->network_ctx = NULL; + sm->peerkey_enabled = 0; + sm->allowed_pairwise_cipher = 0; + sm->proactive_key_caching = 0; + sm->eap_workaround = 0; + sm->eap_conf_ctx = NULL; + sm->ssid_len = 0; + sm->wpa_ptk_rekey = 0; + sm->p2p = 0; + } +} + + +/** + * wpa_sm_set_own_addr - Set own MAC address + * @sm: Pointer to WPA state machine data from wpa_sm_init() + * @addr: Own MAC address + */ +void wpa_sm_set_own_addr(struct wpa_sm *sm, const u8 *addr) +{ + if (sm) + os_memcpy(sm->own_addr, addr, ETH_ALEN); +} + + +/** + * wpa_sm_set_ifname - Set network interface name + * @sm: Pointer to WPA state machine data from wpa_sm_init() + * @ifname: Interface name + * @bridge_ifname: Optional bridge interface name (for pre-auth) + */ +void wpa_sm_set_ifname(struct wpa_sm *sm, const char *ifname, + const char *bridge_ifname) +{ + if (sm) { + sm->ifname = ifname; + sm->bridge_ifname = bridge_ifname; + } +} + + +/** + * wpa_sm_set_eapol - Set EAPOL state machine pointer + * @sm: Pointer to WPA state machine data from wpa_sm_init() + * @eapol: Pointer to EAPOL state machine allocated with eapol_sm_init() + */ +void wpa_sm_set_eapol(struct wpa_sm *sm, struct eapol_sm *eapol) +{ + if (sm) + sm->eapol = eapol; +} + + +/** + * wpa_sm_set_param - Set WPA state machine parameters + * @sm: Pointer to WPA state machine data from wpa_sm_init() + * @param: Parameter field + * @value: Parameter value + * Returns: 0 on success, -1 on failure + */ +int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param, + unsigned int value) +{ + int ret = 0; + + if (sm == NULL) + return -1; + + switch (param) { + case RSNA_PMK_LIFETIME: + if (value > 0) + sm->dot11RSNAConfigPMKLifetime = value; + else + ret = -1; + break; + case RSNA_PMK_REAUTH_THRESHOLD: + if (value > 0 && value <= 100) + sm->dot11RSNAConfigPMKReauthThreshold = value; + else + ret = -1; + break; + case RSNA_SA_TIMEOUT: + if (value > 0) + sm->dot11RSNAConfigSATimeout = value; + else + ret = -1; + break; + case WPA_PARAM_PROTO: + sm->proto = value; + break; + case WPA_PARAM_PAIRWISE: + sm->pairwise_cipher = value; + break; + case WPA_PARAM_GROUP: + sm->group_cipher = value; + break; + case WPA_PARAM_KEY_MGMT: + sm->key_mgmt = value; + break; +#ifdef CONFIG_IEEE80211W + case WPA_PARAM_MGMT_GROUP: + sm->mgmt_group_cipher = value; + break; +#endif /* CONFIG_IEEE80211W */ + case WPA_PARAM_RSN_ENABLED: + sm->rsn_enabled = value; + break; + case WPA_PARAM_MFP: + sm->mfp = value; + break; + default: + break; + } + + return ret; +} + + +/** + * wpa_sm_get_status - Get WPA state machine + * @sm: Pointer to WPA state machine data from wpa_sm_init() + * @buf: Buffer for status information + * @buflen: Maximum buffer length + * @verbose: Whether to include verbose status information + * Returns: Number of bytes written to buf. + * + * Query WPA state machine for status information. This function fills in + * a text area with current status information. If the buffer (buf) is not + * large enough, status information will be truncated to fit the buffer. + */ +int wpa_sm_get_status(struct wpa_sm *sm, char *buf, size_t buflen, + int verbose) +{ + char *pos = buf, *end = buf + buflen; + int ret; + + ret = os_snprintf(pos, end - pos, + "pairwise_cipher=%s\n" + "group_cipher=%s\n" + "key_mgmt=%s\n", + wpa_cipher_txt(sm->pairwise_cipher), + wpa_cipher_txt(sm->group_cipher), + wpa_key_mgmt_txt(sm->key_mgmt, sm->proto)); + if (os_snprintf_error(end - pos, ret)) + return pos - buf; + pos += ret; + + if (sm->mfp != NO_MGMT_FRAME_PROTECTION && sm->ap_rsn_ie) { + struct wpa_ie_data rsn; + if (wpa_parse_wpa_ie_rsn(sm->ap_rsn_ie, sm->ap_rsn_ie_len, &rsn) + >= 0 && + rsn.capabilities & (WPA_CAPABILITY_MFPR | + WPA_CAPABILITY_MFPC)) { + ret = os_snprintf(pos, end - pos, "pmf=%d\n", + (rsn.capabilities & + WPA_CAPABILITY_MFPR) ? 2 : 1); + if (os_snprintf_error(end - pos, ret)) + return pos - buf; + pos += ret; + } + } + + return pos - buf; +} + + +int wpa_sm_pmf_enabled(struct wpa_sm *sm) +{ + struct wpa_ie_data rsn; + + if (sm->mfp == NO_MGMT_FRAME_PROTECTION || !sm->ap_rsn_ie) + return 0; + + if (wpa_parse_wpa_ie_rsn(sm->ap_rsn_ie, sm->ap_rsn_ie_len, &rsn) >= 0 && + rsn.capabilities & (WPA_CAPABILITY_MFPR | WPA_CAPABILITY_MFPC)) + return 1; + + return 0; +} + + +/** + * wpa_sm_set_assoc_wpa_ie_default - Generate own WPA/RSN IE from configuration + * @sm: Pointer to WPA state machine data from wpa_sm_init() + * @wpa_ie: Pointer to buffer for WPA/RSN IE + * @wpa_ie_len: Pointer to the length of the wpa_ie buffer + * Returns: 0 on success, -1 on failure + */ +int wpa_sm_set_assoc_wpa_ie_default(struct wpa_sm *sm, u8 *wpa_ie, + size_t *wpa_ie_len) +{ + int res; + + if (sm == NULL) + return -1; + + res = wpa_gen_wpa_ie(sm, wpa_ie, *wpa_ie_len); + if (res < 0) + return -1; + *wpa_ie_len = res; + + wpa_hexdump(MSG_DEBUG, "WPA: Set own WPA IE default", + wpa_ie, *wpa_ie_len); + + if (sm->assoc_wpa_ie == NULL) { + /* + * Make a copy of the WPA/RSN IE so that 4-Way Handshake gets + * the correct version of the IE even if PMKSA caching is + * aborted (which would remove PMKID from IE generation). + */ + sm->assoc_wpa_ie = os_malloc(*wpa_ie_len); + if (sm->assoc_wpa_ie == NULL) + return -1; + + os_memcpy(sm->assoc_wpa_ie, wpa_ie, *wpa_ie_len); + sm->assoc_wpa_ie_len = *wpa_ie_len; + } + + return 0; +} + + +/** + * wpa_sm_set_assoc_wpa_ie - Set own WPA/RSN IE from (Re)AssocReq + * @sm: Pointer to WPA state machine data from wpa_sm_init() + * @ie: Pointer to IE data (starting from id) + * @len: IE length + * Returns: 0 on success, -1 on failure + * + * Inform WPA state machine about the WPA/RSN IE used in (Re)Association + * Request frame. The IE will be used to override the default value generated + * with wpa_sm_set_assoc_wpa_ie_default(). + */ +int wpa_sm_set_assoc_wpa_ie(struct wpa_sm *sm, const u8 *ie, size_t len) +{ + if (sm == NULL) + return -1; + + os_free(sm->assoc_wpa_ie); + if (ie == NULL || len == 0) { + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, + "WPA: clearing own WPA/RSN IE"); + sm->assoc_wpa_ie = NULL; + sm->assoc_wpa_ie_len = 0; + } else { + wpa_hexdump(MSG_DEBUG, "WPA: set own WPA/RSN IE", ie, len); + sm->assoc_wpa_ie = os_malloc(len); + if (sm->assoc_wpa_ie == NULL) + return -1; + + os_memcpy(sm->assoc_wpa_ie, ie, len); + sm->assoc_wpa_ie_len = len; + } + + return 0; +} + + +/** + * wpa_sm_set_ap_wpa_ie - Set AP WPA IE from Beacon/ProbeResp + * @sm: Pointer to WPA state machine data from wpa_sm_init() + * @ie: Pointer to IE data (starting from id) + * @len: IE length + * Returns: 0 on success, -1 on failure + * + * Inform WPA state machine about the WPA IE used in Beacon / Probe Response + * frame. + */ +int wpa_sm_set_ap_wpa_ie(struct wpa_sm *sm, const u8 *ie, size_t len) +{ + if (sm == NULL) + return -1; + + os_free(sm->ap_wpa_ie); + if (ie == NULL || len == 0) { + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, + "WPA: clearing AP WPA IE"); + sm->ap_wpa_ie = NULL; + sm->ap_wpa_ie_len = 0; + } else { + wpa_hexdump(MSG_DEBUG, "WPA: set AP WPA IE", ie, len); + sm->ap_wpa_ie = os_malloc(len); + if (sm->ap_wpa_ie == NULL) + return -1; + + os_memcpy(sm->ap_wpa_ie, ie, len); + sm->ap_wpa_ie_len = len; + } + + return 0; +} + + +/** + * wpa_sm_set_ap_rsn_ie - Set AP RSN IE from Beacon/ProbeResp + * @sm: Pointer to WPA state machine data from wpa_sm_init() + * @ie: Pointer to IE data (starting from id) + * @len: IE length + * Returns: 0 on success, -1 on failure + * + * Inform WPA state machine about the RSN IE used in Beacon / Probe Response + * frame. + */ +int wpa_sm_set_ap_rsn_ie(struct wpa_sm *sm, const u8 *ie, size_t len) +{ + if (sm == NULL) + return -1; + + os_free(sm->ap_rsn_ie); + if (ie == NULL || len == 0) { + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, + "WPA: clearing AP RSN IE"); + sm->ap_rsn_ie = NULL; + sm->ap_rsn_ie_len = 0; + } else { + wpa_hexdump(MSG_DEBUG, "WPA: set AP RSN IE", ie, len); + sm->ap_rsn_ie = os_malloc(len); + if (sm->ap_rsn_ie == NULL) + return -1; + + os_memcpy(sm->ap_rsn_ie, ie, len); + sm->ap_rsn_ie_len = len; + } + + return 0; +} + + +/** + * wpa_sm_parse_own_wpa_ie - Parse own WPA/RSN IE + * @sm: Pointer to WPA state machine data from wpa_sm_init() + * @data: Pointer to data area for parsing results + * Returns: 0 on success, -1 if IE is not known, or -2 on parsing failure + * + * Parse the contents of the own WPA or RSN IE from (Re)AssocReq and write the + * parsed data into data. + */ +int wpa_sm_parse_own_wpa_ie(struct wpa_sm *sm, struct wpa_ie_data *data) +{ + if (sm == NULL) + return -1; + + if (sm->assoc_wpa_ie == NULL) { + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, + "WPA: No WPA/RSN IE available from association info"); + return -1; + } + if (wpa_parse_wpa_ie(sm->assoc_wpa_ie, sm->assoc_wpa_ie_len, data)) + return -2; + return 0; +} + + +int wpa_sm_pmksa_cache_list(struct wpa_sm *sm, char *buf, size_t len) +{ + return pmksa_cache_list(sm->pmksa, buf, len); +} + + +void wpa_sm_drop_sa(struct wpa_sm *sm) +{ + wpa_dbg(sm->ctx->msg_ctx, MSG_DEBUG, "WPA: Clear old PMK and PTK"); + sm->ptk_set = 0; + sm->tptk_set = 0; + os_memset(sm->pmk, 0, sizeof(sm->pmk)); + os_memset(&sm->ptk, 0, sizeof(sm->ptk)); + os_memset(&sm->tptk, 0, sizeof(sm->tptk)); + os_memset(&sm->gtk, 0, sizeof(sm->gtk)); + os_memset(&sm->gtk_wnm_sleep, 0, sizeof(sm->gtk_wnm_sleep)); +#ifdef CONFIG_IEEE80211W + os_memset(&sm->igtk, 0, sizeof(sm->igtk)); + os_memset(&sm->gtk_wnm_sleep, 0, sizeof(sm->gtk_wnm_sleep)); +#endif /* CONFIG_IEEE80211W */ +#ifdef CONFIG_IEEE80211R + os_memset(sm->xxkey, 0, sizeof(sm->xxkey)); + os_memset(sm->pmk_r0, 0, sizeof(sm->pmk_r0)); + os_memset(sm->pmk_r1, 0, sizeof(sm->pmk_r1)); +#endif /* CONFIG_IEEE80211R */ +} + + +int wpa_sm_has_ptk(struct wpa_sm *sm) +{ + if (sm == NULL) + return 0; + return sm->ptk_set; +} + + +void wpa_sm_update_replay_ctr(struct wpa_sm *sm, const u8 *replay_ctr) +{ + os_memcpy(sm->rx_replay_counter, replay_ctr, WPA_REPLAY_COUNTER_LEN); +} + + +void wpa_sm_pmksa_cache_flush(struct wpa_sm *sm, void *network_ctx) +{ + pmksa_cache_flush(sm->pmksa, network_ctx, NULL, 0); +} + +#ifdef CONFIG_PEERKEY +int wpa_sm_rx_eapol_peerkey(struct wpa_sm *sm, const u8 *src_addr, + const u8 *buf, size_t len) +{ + struct wpa_peerkey *peerkey; + + for (peerkey = sm->peerkey; peerkey; peerkey = peerkey->next) { + if (os_memcmp(peerkey->addr, src_addr, ETH_ALEN) == 0) + break; + } + + if (!peerkey) + return 0; + + wpa_sm_rx_eapol(sm, src_addr, buf, len); + + return 1; +} +#endif /* CONFIG_PEERKEY */ + + +#ifdef CONFIG_P2P + +int wpa_sm_get_p2p_ip_addr(struct wpa_sm *sm, u8 *buf) +{ + if (sm == NULL || WPA_GET_BE32(sm->p2p_ip_addr) == 0) + return -1; + os_memcpy(buf, sm->p2p_ip_addr, 3 * 4); + return 0; +} + +#endif /* CONFIG_P2P */ + + +void wpa_sm_set_rx_replay_ctr(struct wpa_sm *sm, const u8 *rx_replay_counter) +{ + if (rx_replay_counter == NULL) + return; + + os_memcpy(sm->rx_replay_counter, rx_replay_counter, + WPA_REPLAY_COUNTER_LEN); + sm->rx_replay_counter_set = 1; + wpa_printf(MSG_DEBUG, "Updated key replay counter"); +} + + +void wpa_sm_set_ptk_kck_kek(struct wpa_sm *sm, + const u8 *ptk_kck, size_t ptk_kck_len, + const u8 *ptk_kek, size_t ptk_kek_len) +{ + if (ptk_kck && ptk_kck_len <= WPA_KCK_MAX_LEN) { + os_memcpy(sm->ptk.kck, ptk_kck, ptk_kck_len); + sm->ptk.kck_len = ptk_kck_len; + wpa_printf(MSG_DEBUG, "Updated PTK KCK"); + } + if (ptk_kek && ptk_kek_len <= WPA_KEK_MAX_LEN) { + os_memcpy(sm->ptk.kek, ptk_kek, ptk_kek_len); + sm->ptk.kek_len = ptk_kek_len; + wpa_printf(MSG_DEBUG, "Updated PTK KEK"); + } + sm->ptk_set = 1; +} diff --git a/beken_os/beken378/func/hostapd-2.5/src/rsn_supp/wpa.h b/beken_os/beken378/func/hostapd-2.5/src/rsn_supp/wpa.h new file mode 100755 index 0000000..e163b70 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/rsn_supp/wpa.h @@ -0,0 +1,421 @@ +/* + * wpa_supplicant - WPA definitions + * Copyright (c) 2003-2015, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef WPA_H +#define WPA_H + +#include "common/defs.h" +#include "common/eapol_common.h" +#include "common/wpa_common.h" +#include "common/ieee802_11_defs.h" + +struct wpa_sm; +struct eapol_sm; +struct wpa_config_blob; +struct hostapd_freq_params; + +struct wpa_sm_ctx { + void *ctx; /* pointer to arbitrary upper level context */ + void *msg_ctx; /* upper level context for wpa_msg() calls */ + + void (*set_state)(void *ctx, enum wpa_states state); + enum wpa_states (*get_state)(void *ctx); + void (*deauthenticate)(void * ctx, int reason_code); + int (*set_key)(void *ctx, enum wpa_alg alg, + const u8 *addr, int key_idx, int set_tx, + const u8 *seq, size_t seq_len, + const u8 *key, size_t key_len); + void * (*get_network_ctx)(void *ctx); + int (*get_bssid)(void *ctx, u8 *bssid); + int (*ether_send)(void *ctx, const u8 *dest, u16 proto, const u8 *buf, + size_t len); + int (*get_beacon_ie)(void *ctx); + void (*cancel_auth_timeout)(void *ctx); + u8 * (*alloc_eapol)(void *ctx, u8 type, const void *data, u16 data_len, + size_t *msg_len, void **data_pos); + int (*add_pmkid)(void *ctx, const u8 *bssid, const u8 *pmkid); + int (*remove_pmkid)(void *ctx, const u8 *bssid, const u8 *pmkid); + void (*set_config_blob)(void *ctx, struct wpa_config_blob *blob); + const struct wpa_config_blob * (*get_config_blob)(void *ctx, + const char *name); + int (*mlme_setprotection)(void *ctx, const u8 *addr, + int protection_type, int key_type); + int (*update_ft_ies)(void *ctx, const u8 *md, const u8 *ies, + size_t ies_len); + int (*send_ft_action)(void *ctx, u8 action, const u8 *target_ap, + const u8 *ies, size_t ies_len); + int (*mark_authenticated)(void *ctx, const u8 *target_ap); +#ifdef CONFIG_TDLS + int (*tdls_get_capa)(void *ctx, int *tdls_supported, + int *tdls_ext_setup, int *tdls_chan_switch); + int (*send_tdls_mgmt)(void *ctx, const u8 *dst, + u8 action_code, u8 dialog_token, + u16 status_code, u32 peer_capab, + int initiator, const u8 *buf, size_t len); + int (*tdls_oper)(void *ctx, int oper, const u8 *peer); + int (*tdls_peer_addset)(void *ctx, const u8 *addr, int add, u16 aid, + u16 capability, const u8 *supp_rates, + size_t supp_rates_len, + const struct ieee80211_ht_capabilities *ht_capab, + const struct ieee80211_vht_capabilities *vht_capab, + u8 qosinfo, int wmm, const u8 *ext_capab, + size_t ext_capab_len, const u8 *supp_channels, + size_t supp_channels_len, + const u8 *supp_oper_classes, + size_t supp_oper_classes_len); + int (*tdls_enable_channel_switch)( + void *ctx, const u8 *addr, u8 oper_class, + const struct hostapd_freq_params *params); + int (*tdls_disable_channel_switch)(void *ctx, const u8 *addr); +#endif /* CONFIG_TDLS */ + void (*set_rekey_offload)(void *ctx, const u8 *kek, size_t kek_len, + const u8 *kck, size_t kck_len, + const u8 *replay_ctr); + int (*key_mgmt_set_pmk)(void *ctx, const u8 *pmk, size_t pmk_len); +}; + + +enum wpa_sm_conf_params { + RSNA_PMK_LIFETIME /* dot11RSNAConfigPMKLifetime */, + RSNA_PMK_REAUTH_THRESHOLD /* dot11RSNAConfigPMKReauthThreshold */, + RSNA_SA_TIMEOUT /* dot11RSNAConfigSATimeout */, + WPA_PARAM_PROTO, + WPA_PARAM_PAIRWISE, + WPA_PARAM_GROUP, + WPA_PARAM_KEY_MGMT, + WPA_PARAM_MGMT_GROUP, + WPA_PARAM_RSN_ENABLED, + WPA_PARAM_MFP +}; + +struct rsn_supp_config { + void *network_ctx; + int peerkey_enabled; + int allowed_pairwise_cipher; /* bitfield of WPA_CIPHER_* */ + int proactive_key_caching; + int eap_workaround; + void *eap_conf_ctx; + const u8 *ssid; + size_t ssid_len; + int wpa_ptk_rekey; + int p2p; +}; + +#ifndef CONFIG_NO_WPA + +struct wpa_sm * wpa_sm_init(struct wpa_sm_ctx *ctx); +void wpa_sm_deinit(struct wpa_sm *sm); +void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid); +void wpa_sm_notify_disassoc(struct wpa_sm *sm); +void wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk, size_t pmk_len, + const u8 *bssid); +void wpa_sm_set_pmk_from_pmksa(struct wpa_sm *sm); +void wpa_sm_set_fast_reauth(struct wpa_sm *sm, int fast_reauth); +void wpa_sm_set_scard_ctx(struct wpa_sm *sm, void *scard_ctx); +void wpa_sm_set_config(struct wpa_sm *sm, struct rsn_supp_config *config); +void wpa_sm_set_own_addr(struct wpa_sm *sm, const u8 *addr); +void wpa_sm_set_ifname(struct wpa_sm *sm, const char *ifname, + const char *bridge_ifname); +void wpa_sm_set_eapol(struct wpa_sm *sm, struct eapol_sm *eapol); +int wpa_sm_set_assoc_wpa_ie(struct wpa_sm *sm, const u8 *ie, size_t len); +int wpa_sm_set_assoc_wpa_ie_default(struct wpa_sm *sm, u8 *wpa_ie, + size_t *wpa_ie_len); +int wpa_sm_set_ap_wpa_ie(struct wpa_sm *sm, const u8 *ie, size_t len); +int wpa_sm_set_ap_rsn_ie(struct wpa_sm *sm, const u8 *ie, size_t len); +int wpa_sm_get_mib(struct wpa_sm *sm, char *buf, size_t buflen); + +int wpa_sm_set_param(struct wpa_sm *sm, enum wpa_sm_conf_params param, + unsigned int value); + +int wpa_sm_get_status(struct wpa_sm *sm, char *buf, size_t buflen, + int verbose); +int wpa_sm_pmf_enabled(struct wpa_sm *sm); + +void wpa_sm_key_request(struct wpa_sm *sm, int error, int pairwise); + +int wpa_parse_wpa_ie(const u8 *wpa_ie, size_t wpa_ie_len, + struct wpa_ie_data *data); + +void wpa_sm_aborted_cached(struct wpa_sm *sm); +int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr, + const u8 *buf, size_t len); +int wpa_sm_parse_own_wpa_ie(struct wpa_sm *sm, struct wpa_ie_data *data); +int wpa_sm_pmksa_cache_list(struct wpa_sm *sm, char *buf, size_t len); +void wpa_sm_drop_sa(struct wpa_sm *sm); +int wpa_sm_has_ptk(struct wpa_sm *sm); + +void wpa_sm_update_replay_ctr(struct wpa_sm *sm, const u8 *replay_ctr); + +void wpa_sm_pmksa_cache_flush(struct wpa_sm *sm, void *network_ctx); + +int wpa_sm_get_p2p_ip_addr(struct wpa_sm *sm, u8 *buf); + +void wpa_sm_set_rx_replay_ctr(struct wpa_sm *sm, const u8 *rx_replay_counter); +void wpa_sm_set_ptk_kck_kek(struct wpa_sm *sm, + const u8 *ptk_kck, size_t ptk_kck_len, + const u8 *ptk_kek, size_t ptk_kek_len); + +#else /* CONFIG_NO_WPA */ + +static inline struct wpa_sm * wpa_sm_init(struct wpa_sm_ctx *ctx) +{ + return (struct wpa_sm *) 1; +} + +static inline void wpa_sm_deinit(struct wpa_sm *sm) +{ +} + +static inline void wpa_sm_notify_assoc(struct wpa_sm *sm, const u8 *bssid) +{ +} + +static inline void wpa_sm_notify_disassoc(struct wpa_sm *sm) +{ +} + +static inline void wpa_sm_set_pmk(struct wpa_sm *sm, const u8 *pmk, + size_t pmk_len) +{ +} + +static inline void wpa_sm_set_pmk_from_pmksa(struct wpa_sm *sm) +{ +} + +static inline void wpa_sm_set_fast_reauth(struct wpa_sm *sm, int fast_reauth) +{ +} + +static inline void wpa_sm_set_scard_ctx(struct wpa_sm *sm, void *scard_ctx) +{ +} + +static inline void wpa_sm_set_config(struct wpa_sm *sm, + struct rsn_supp_config *config) +{ +} + +static inline void wpa_sm_set_own_addr(struct wpa_sm *sm, const u8 *addr) +{ +} + +static inline void wpa_sm_set_ifname(struct wpa_sm *sm, const char *ifname, + const char *bridge_ifname) +{ +} + +static inline void wpa_sm_set_eapol(struct wpa_sm *sm, struct eapol_sm *eapol) +{ +} + +static inline int wpa_sm_set_assoc_wpa_ie(struct wpa_sm *sm, const u8 *ie, + size_t len) +{ + return -1; +} + +static inline int wpa_sm_set_assoc_wpa_ie_default(struct wpa_sm *sm, + u8 *wpa_ie, + size_t *wpa_ie_len) +{ + return -1; +} + +static inline int wpa_sm_set_ap_wpa_ie(struct wpa_sm *sm, const u8 *ie, + size_t len) +{ + return -1; +} + +static inline int wpa_sm_set_ap_rsn_ie(struct wpa_sm *sm, const u8 *ie, + size_t len) +{ + return -1; +} + +static inline int wpa_sm_get_mib(struct wpa_sm *sm, char *buf, size_t buflen) +{ + return 0; +} + +static inline int wpa_sm_set_param(struct wpa_sm *sm, + enum wpa_sm_conf_params param, + unsigned int value) +{ + return -1; +} + +static inline int wpa_sm_get_status(struct wpa_sm *sm, char *buf, + size_t buflen, int verbose) +{ + return 0; +} + +static inline int wpa_sm_pmf_enabled(struct wpa_sm *sm) +{ + return 0; +} + +static inline void wpa_sm_key_request(struct wpa_sm *sm, int error, + int pairwise) +{ +} + +static inline int wpa_parse_wpa_ie(const u8 *wpa_ie, size_t wpa_ie_len, + struct wpa_ie_data *data) +{ + return -1; +} + +static inline void wpa_sm_aborted_cached(struct wpa_sm *sm) +{ +} + +static inline int wpa_sm_rx_eapol(struct wpa_sm *sm, const u8 *src_addr, + const u8 *buf, size_t len) +{ + return -1; +} + +static inline int wpa_sm_parse_own_wpa_ie(struct wpa_sm *sm, + struct wpa_ie_data *data) +{ + return -1; +} + +static inline int wpa_sm_pmksa_cache_list(struct wpa_sm *sm, char *buf, + size_t len) +{ + return -1; +} + +static inline void wpa_sm_drop_sa(struct wpa_sm *sm) +{ +} + +static inline int wpa_sm_has_ptk(struct wpa_sm *sm) +{ + return 0; +} + +static inline void wpa_sm_update_replay_ctr(struct wpa_sm *sm, + const u8 *replay_ctr) +{ +} + +static inline void wpa_sm_pmksa_cache_flush(struct wpa_sm *sm, + void *network_ctx) +{ +} + +static inline void wpa_sm_set_rx_replay_ctr(struct wpa_sm *sm, + const u8 *rx_replay_counter) +{ +} + +static inline void wpa_sm_set_ptk_kck_kek(struct wpa_sm *sm, const u8 *ptk_kck, + const u8 *ptk_kek) +{ +} + +#endif /* CONFIG_NO_WPA */ + +#ifdef CONFIG_PEERKEY +int wpa_sm_stkstart(struct wpa_sm *sm, const u8 *peer); +int wpa_sm_rx_eapol_peerkey(struct wpa_sm *sm, const u8 *src_addr, + const u8 *buf, size_t len); +#else /* CONFIG_PEERKEY */ +static inline int wpa_sm_stkstart(struct wpa_sm *sm, const u8 *peer) +{ + return -1; +} + +static inline int wpa_sm_rx_eapol_peerkey(struct wpa_sm *sm, const u8 *src_addr, + const u8 *buf, size_t len) +{ + return 0; +} +#endif /* CONFIG_PEERKEY */ + +#ifdef CONFIG_IEEE80211R + +int wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *ies, size_t ies_len); +int wpa_ft_prepare_auth_request(struct wpa_sm *sm, const u8 *mdie); +int wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len, + int ft_action, const u8 *target_ap, + const u8 *ric_ies, size_t ric_ies_len); +int wpa_ft_is_completed(struct wpa_sm *sm); +void wpa_reset_ft_completed(struct wpa_sm *sm); +int wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, + size_t ies_len, const u8 *src_addr); +int wpa_ft_start_over_ds(struct wpa_sm *sm, const u8 *target_ap, + const u8 *mdie); + +#else /* CONFIG_IEEE80211R */ + +static inline int +wpa_sm_set_ft_params(struct wpa_sm *sm, const u8 *ies, size_t ies_len) +{ + return 0; +} + +static inline int wpa_ft_prepare_auth_request(struct wpa_sm *sm, + const u8 *mdie) +{ + return 0; +} + +static inline int +wpa_ft_process_response(struct wpa_sm *sm, const u8 *ies, size_t ies_len, + int ft_action, const u8 *target_ap) +{ + return 0; +} + +static inline int wpa_ft_is_completed(struct wpa_sm *sm) +{ + return 0; +} + +static inline void wpa_reset_ft_completed(struct wpa_sm *sm) +{ +} + +static inline int +wpa_ft_validate_reassoc_resp(struct wpa_sm *sm, const u8 *ies, size_t ies_len, + const u8 *src_addr) +{ + return -1; +} + +#endif /* CONFIG_IEEE80211R */ + + +/* tdls.c */ +void wpa_tdls_ap_ies(struct wpa_sm *sm, const u8 *ies, size_t len); +void wpa_tdls_assoc_resp_ies(struct wpa_sm *sm, const u8 *ies, size_t len); +int wpa_tdls_start(struct wpa_sm *sm, const u8 *addr); +void wpa_tdls_remove(struct wpa_sm *sm, const u8 *addr); +int wpa_tdls_teardown_link(struct wpa_sm *sm, const u8 *addr, u16 reason_code); +int wpa_tdls_send_discovery_request(struct wpa_sm *sm, const u8 *addr); +int wpa_tdls_init(struct wpa_sm *sm); +void wpa_tdls_teardown_peers(struct wpa_sm *sm); +void wpa_tdls_deinit(struct wpa_sm *sm); +void wpa_tdls_enable(struct wpa_sm *sm, int enabled); +void wpa_tdls_disable_unreachable_link(struct wpa_sm *sm, const u8 *addr); +const char * wpa_tdls_get_link_status(struct wpa_sm *sm, const u8 *addr); +int wpa_tdls_is_external_setup(struct wpa_sm *sm); +int wpa_tdls_enable_chan_switch(struct wpa_sm *sm, const u8 *addr, + u8 oper_class, + struct hostapd_freq_params *freq_params); +int wpa_tdls_disable_chan_switch(struct wpa_sm *sm, const u8 *addr); + +int wpa_wnmsleep_install_key(struct wpa_sm *sm, u8 subelem_id, u8 *buf); + +#endif /* WPA_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/rsn_supp/wpa_i.h b/beken_os/beken378/func/hostapd-2.5/src/rsn_supp/wpa_i.h new file mode 100755 index 0000000..f9854e9 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/rsn_supp/wpa_i.h @@ -0,0 +1,356 @@ +/* + * Internal WPA/RSN supplicant state machine definitions + * Copyright (c) 2004-2015, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef WPA_I_H +#define WPA_I_H + +#include "utils/list.h" + +struct wpa_peerkey; +struct wpa_tdls_peer; +struct wpa_eapol_key; + +/** + * struct wpa_sm - Internal WPA state machine data + */ +struct wpa_sm { + u8 pmk[PMK_LEN]; + size_t pmk_len; + struct wpa_ptk ptk, tptk; + int ptk_set, tptk_set; + unsigned int msg_3_of_4_ok:1; + u8 snonce[WPA_NONCE_LEN]; + u8 anonce[WPA_NONCE_LEN]; /* ANonce from the last 1/4 msg */ + int renew_snonce; + u8 rx_replay_counter[WPA_REPLAY_COUNTER_LEN]; + int rx_replay_counter_set; + u8 request_counter[WPA_REPLAY_COUNTER_LEN]; + struct wpa_gtk gtk; + struct wpa_gtk gtk_wnm_sleep; +#ifdef CONFIG_IEEE80211W + struct wpa_igtk igtk; + struct wpa_igtk igtk_wnm_sleep; +#endif /* CONFIG_IEEE80211W */ + + struct eapol_sm *eapol; /* EAPOL state machine from upper level code */ + + struct rsn_pmksa_cache *pmksa; /* PMKSA cache */ + struct rsn_pmksa_cache_entry *cur_pmksa; /* current PMKSA entry */ + struct dl_list pmksa_candidates; + + struct l2_packet_data *l2_preauth; + struct l2_packet_data *l2_preauth_br; + struct l2_packet_data *l2_tdls; + u8 preauth_bssid[ETH_ALEN]; /* current RSN pre-auth peer or + * 00:00:00:00:00:00 if no pre-auth is + * in progress */ + struct eapol_sm *preauth_eapol; + + struct wpa_sm_ctx *ctx; + + void *scard_ctx; /* context for smartcard callbacks */ + int fast_reauth; /* whether EAP fast re-authentication is enabled */ + + void *network_ctx; + int peerkey_enabled; + int allowed_pairwise_cipher; /* bitfield of WPA_CIPHER_* */ + int proactive_key_caching; + int eap_workaround; + void *eap_conf_ctx; + u8 ssid[32]; + size_t ssid_len; + int wpa_ptk_rekey; + int p2p; + + u8 own_addr[ETH_ALEN]; + const char *ifname; + const char *bridge_ifname; + u8 bssid[ETH_ALEN]; + + unsigned int dot11RSNAConfigPMKLifetime; + unsigned int dot11RSNAConfigPMKReauthThreshold; + unsigned int dot11RSNAConfigSATimeout; + + unsigned int dot11RSNA4WayHandshakeFailures; + + /* Selected configuration (based on Beacon/ProbeResp WPA IE) */ + unsigned int proto; + unsigned int pairwise_cipher; + unsigned int group_cipher; + unsigned int key_mgmt; + unsigned int mgmt_group_cipher; + + int rsn_enabled; /* Whether RSN is enabled in configuration */ + int mfp; /* 0 = disabled, 1 = optional, 2 = mandatory */ + + u8 *assoc_wpa_ie; /* Own WPA/RSN IE from (Re)AssocReq */ + size_t assoc_wpa_ie_len; + u8 *ap_wpa_ie, *ap_rsn_ie; + size_t ap_wpa_ie_len, ap_rsn_ie_len; + +#ifdef CONFIG_PEERKEY + struct wpa_peerkey *peerkey; +#endif /* CONFIG_PEERKEY */ +#ifdef CONFIG_TDLS + struct wpa_tdls_peer *tdls; + int tdls_prohibited; + int tdls_chan_switch_prohibited; + int tdls_disabled; + + /* The driver supports TDLS */ + int tdls_supported; + + /* + * The driver requires explicit discovery/setup/teardown frames sent + * to it via tdls_mgmt. + */ + int tdls_external_setup; + + /* The driver supports TDLS channel switching */ + int tdls_chan_switch; +#endif /* CONFIG_TDLS */ +#ifdef CONFIG_P2P + u8 p2p_ip_addr[3 * 4]; +#endif /* CONFIG_P2P */ +}; + + +static inline void wpa_sm_set_state(struct wpa_sm *sm, enum wpa_states state) +{ + WPA_ASSERT(sm->ctx->set_state); + sm->ctx->set_state(sm->ctx->ctx, state); +} + +static inline enum wpa_states wpa_sm_get_state(struct wpa_sm *sm) +{ + WPA_ASSERT(sm->ctx->get_state); + return sm->ctx->get_state(sm->ctx->ctx); +} + +static inline void wpa_sm_deauthenticate(struct wpa_sm *sm, int reason_code) +{ + WPA_ASSERT(sm->ctx->deauthenticate); + sm->ctx->deauthenticate(sm->ctx->ctx, reason_code); +} + +static inline int wpa_sm_set_key(struct wpa_sm *sm, enum wpa_alg alg, + const u8 *addr, int key_idx, int set_tx, + const u8 *seq, size_t seq_len, + const u8 *key, size_t key_len) +{ + WPA_ASSERT(sm->ctx->set_key); + return sm->ctx->set_key(sm->ctx->ctx, alg, addr, key_idx, set_tx, + seq, seq_len, key, key_len); +} + +static inline void * wpa_sm_get_network_ctx(struct wpa_sm *sm) +{ + WPA_ASSERT(sm->ctx->get_network_ctx); + return sm->ctx->get_network_ctx(sm->ctx->ctx); +} + +static inline int wpa_sm_get_bssid(struct wpa_sm *sm, u8 *bssid) +{ + WPA_ASSERT(sm->ctx->get_bssid); + return sm->ctx->get_bssid(sm->ctx->ctx, bssid); +} + +static inline int wpa_sm_ether_send(struct wpa_sm *sm, const u8 *dest, + u16 proto, const u8 *buf, size_t len) +{ + WPA_ASSERT(sm->ctx->ether_send); + return sm->ctx->ether_send(sm->ctx->ctx, dest, proto, buf, len); +} + +static inline int wpa_sm_get_beacon_ie(struct wpa_sm *sm) +{ + WPA_ASSERT(sm->ctx->get_beacon_ie); + return sm->ctx->get_beacon_ie(sm->ctx->ctx); +} + +static inline void wpa_sm_cancel_auth_timeout(struct wpa_sm *sm) +{ + WPA_ASSERT(sm->ctx->cancel_auth_timeout); + sm->ctx->cancel_auth_timeout(sm->ctx->ctx); +} + +static inline u8 * wpa_sm_alloc_eapol(struct wpa_sm *sm, u8 type, + const void *data, u16 data_len, + size_t *msg_len, void **data_pos) +{ + WPA_ASSERT(sm->ctx->alloc_eapol); + return sm->ctx->alloc_eapol(sm->ctx->ctx, type, data, data_len, + msg_len, data_pos); +} + +static inline int wpa_sm_add_pmkid(struct wpa_sm *sm, const u8 *bssid, + const u8 *pmkid) +{ + WPA_ASSERT(sm->ctx->add_pmkid); + return sm->ctx->add_pmkid(sm->ctx->ctx, bssid, pmkid); +} + +static inline int wpa_sm_remove_pmkid(struct wpa_sm *sm, const u8 *bssid, + const u8 *pmkid) +{ + WPA_ASSERT(sm->ctx->remove_pmkid); + return sm->ctx->remove_pmkid(sm->ctx->ctx, bssid, pmkid); +} + +static inline int wpa_sm_mlme_setprotection(struct wpa_sm *sm, const u8 *addr, + int protect_type, int key_type) +{ + WPA_ASSERT(sm->ctx->mlme_setprotection); + return sm->ctx->mlme_setprotection(sm->ctx->ctx, addr, protect_type, + key_type); +} + +static inline int wpa_sm_update_ft_ies(struct wpa_sm *sm, const u8 *md, + const u8 *ies, size_t ies_len) +{ + if (sm->ctx->update_ft_ies) + return sm->ctx->update_ft_ies(sm->ctx->ctx, md, ies, ies_len); + return -1; +} + +static inline int wpa_sm_send_ft_action(struct wpa_sm *sm, u8 action, + const u8 *target_ap, + const u8 *ies, size_t ies_len) +{ + if (sm->ctx->send_ft_action) + return sm->ctx->send_ft_action(sm->ctx->ctx, action, target_ap, + ies, ies_len); + return -1; +} + +static inline int wpa_sm_mark_authenticated(struct wpa_sm *sm, + const u8 *target_ap) +{ + if (sm->ctx->mark_authenticated) + return sm->ctx->mark_authenticated(sm->ctx->ctx, target_ap); + return -1; +} + +static inline void wpa_sm_set_rekey_offload(struct wpa_sm *sm) +{ + if (!sm->ctx->set_rekey_offload) + return; + sm->ctx->set_rekey_offload(sm->ctx->ctx, sm->ptk.kek, sm->ptk.kek_len, + sm->ptk.kck, sm->ptk.kck_len, + sm->rx_replay_counter); +} + +#ifdef CONFIG_TDLS +static inline int wpa_sm_tdls_get_capa(struct wpa_sm *sm, + int *tdls_supported, + int *tdls_ext_setup, + int *tdls_chan_switch) +{ + if (sm->ctx->tdls_get_capa) + return sm->ctx->tdls_get_capa(sm->ctx->ctx, tdls_supported, + tdls_ext_setup, tdls_chan_switch); + return -1; +} + +static inline int wpa_sm_send_tdls_mgmt(struct wpa_sm *sm, const u8 *dst, + u8 action_code, u8 dialog_token, + u16 status_code, u32 peer_capab, + int initiator, const u8 *buf, + size_t len) +{ + if (sm->ctx->send_tdls_mgmt) + return sm->ctx->send_tdls_mgmt(sm->ctx->ctx, dst, action_code, + dialog_token, status_code, + peer_capab, initiator, buf, + len); + return -1; +} + +static inline int wpa_sm_tdls_oper(struct wpa_sm *sm, int oper, + const u8 *peer) +{ + if (sm->ctx->tdls_oper) + return sm->ctx->tdls_oper(sm->ctx->ctx, oper, peer); + return -1; +} + +static inline int +wpa_sm_tdls_peer_addset(struct wpa_sm *sm, const u8 *addr, int add, + u16 aid, u16 capability, const u8 *supp_rates, + size_t supp_rates_len, + const struct ieee80211_ht_capabilities *ht_capab, + const struct ieee80211_vht_capabilities *vht_capab, + u8 qosinfo, int wmm, const u8 *ext_capab, + size_t ext_capab_len, const u8 *supp_channels, + size_t supp_channels_len, const u8 *supp_oper_classes, + size_t supp_oper_classes_len) +{ + if (sm->ctx->tdls_peer_addset) + return sm->ctx->tdls_peer_addset(sm->ctx->ctx, addr, add, + aid, capability, supp_rates, + supp_rates_len, ht_capab, + vht_capab, qosinfo, wmm, + ext_capab, ext_capab_len, + supp_channels, + supp_channels_len, + supp_oper_classes, + supp_oper_classes_len); + return -1; +} + +static inline int +wpa_sm_tdls_enable_channel_switch(struct wpa_sm *sm, const u8 *addr, + u8 oper_class, + const struct hostapd_freq_params *freq_params) +{ + if (sm->ctx->tdls_enable_channel_switch) + return sm->ctx->tdls_enable_channel_switch(sm->ctx->ctx, addr, + oper_class, + freq_params); + return -1; +} + +static inline int +wpa_sm_tdls_disable_channel_switch(struct wpa_sm *sm, const u8 *addr) +{ + if (sm->ctx->tdls_disable_channel_switch) + return sm->ctx->tdls_disable_channel_switch(sm->ctx->ctx, addr); + return -1; +} +#endif /* CONFIG_TDLS */ + +static inline int wpa_sm_key_mgmt_set_pmk(struct wpa_sm *sm, + const u8 *pmk, size_t pmk_len) +{ + if (!sm->proactive_key_caching) + return 0; + if (!sm->ctx->key_mgmt_set_pmk) + return -1; + return sm->ctx->key_mgmt_set_pmk(sm->ctx->ctx, pmk, pmk_len); +} + +int wpa_eapol_key_send(struct wpa_sm *sm, const u8 *kck, size_t kck_len, + int ver, const u8 *dest, u16 proto, + u8 *msg, size_t msg_len, u8 *key_mic); +int wpa_supplicant_send_2_of_4(struct wpa_sm *sm, const unsigned char *dst, + const struct wpa_eapol_key *key, + int ver, const u8 *nonce, + const u8 *wpa_ie, size_t wpa_ie_len, + struct wpa_ptk *ptk); +int wpa_supplicant_send_4_of_4(struct wpa_sm *sm, const unsigned char *dst, + const struct wpa_eapol_key *key, + u16 ver, u16 key_info, + struct wpa_ptk *ptk); + +int wpa_derive_ptk_ft(struct wpa_sm *sm, const unsigned char *src_addr, + const struct wpa_eapol_key *key, struct wpa_ptk *ptk); + +void wpa_tdls_assoc(struct wpa_sm *sm); +void wpa_tdls_disassoc(struct wpa_sm *sm); + +#endif /* WPA_I_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/rsn_supp/wpa_ie.c b/beken_os/beken378/func/hostapd-2.5/src/rsn_supp/wpa_ie.c new file mode 100755 index 0000000..c4197d9 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/rsn_supp/wpa_ie.c @@ -0,0 +1,531 @@ +/* + * wpa_supplicant - WPA/RSN IE and KDE processing + * Copyright (c) 2003-2015, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "wpa.h" +#include "common/ieee802_11_defs.h" +#include "wpa_i.h" +#include "wpa_ie.h" + + +/** + * wpa_parse_wpa_ie - Parse WPA/RSN IE + * @wpa_ie: Pointer to WPA or RSN IE + * @wpa_ie_len: Length of the WPA/RSN IE + * @data: Pointer to data area for parsing results + * Returns: 0 on success, -1 on failure + * + * Parse the contents of WPA or RSN IE and write the parsed data into data. + */ +int wpa_parse_wpa_ie(const u8 *wpa_ie, size_t wpa_ie_len, + struct wpa_ie_data *data) +{ + if (wpa_ie_len >= 1 && wpa_ie[0] == WLAN_EID_RSN) + return wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, data); + if (wpa_ie_len >= 6 && wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC && + wpa_ie[1] >= 4 && WPA_GET_BE32(&wpa_ie[2]) == OSEN_IE_VENDOR_TYPE) + return wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, data); + else + return wpa_parse_wpa_ie_wpa(wpa_ie, wpa_ie_len, data); +} + +/** + * wpa_parse_vendor_specific - Parse Vendor Specific IEs + * @pos: Pointer to the IE header + * @end: Pointer to the end of the Key Data buffer + * @ie: Pointer to parsed IE data + * Returns: 0 on success, 1 if end mark is found, -1 on failure + */ +static int wpa_parse_vendor_specific(const u8 *pos, const u8 *end, + struct wpa_eapol_ie_parse *ie) +{ + unsigned int oui; + + if (pos[1] < 4) { + wpa_printf(MSG_MSGDUMP, "Too short vendor specific IE ignored (len=%u)", + pos[1]); + return 1; + } + + oui = WPA_GET_BE24(&pos[2]); + if (oui == OUI_MICROSOFT && pos[5] == WMM_OUI_TYPE && pos[1] > 4) { + if (pos[6] == WMM_OUI_SUBTYPE_INFORMATION_ELEMENT) { + ie->wmm = &pos[2]; + ie->wmm_len = pos[1]; + wpa_hexdump(MSG_DEBUG, "WPA: WMM IE", + ie->wmm, ie->wmm_len); + } else if (pos[6] == WMM_OUI_SUBTYPE_PARAMETER_ELEMENT) { + ie->wmm = &pos[2]; + ie->wmm_len = pos[1]; + wpa_hexdump(MSG_DEBUG, "WPA: WMM Parameter Element", + ie->wmm, ie->wmm_len); + } + } + return 0; +} + + +/** + * wpa_parse_generic - Parse EAPOL-Key Key Data Generic IEs + * @pos: Pointer to the IE header + * @end: Pointer to the end of the Key Data buffer + * @ie: Pointer to parsed IE data + * Returns: 0 on success, 1 if end mark is found, -1 on failure + */ +static int wpa_parse_generic(const u8 *pos, const u8 *end, + struct wpa_eapol_ie_parse *ie) +{ + if (pos[1] == 0) + return 1; + + if (pos[1] >= 6 && + RSN_SELECTOR_GET(pos + 2) == WPA_OUI_TYPE && + pos[2 + WPA_SELECTOR_LEN] == 1 && + pos[2 + WPA_SELECTOR_LEN + 1] == 0) { + ie->wpa_ie = pos; + ie->wpa_ie_len = pos[1] + 2; + wpa_hexdump(MSG_DEBUG, "WPA: WPA IE in EAPOL-Key", + ie->wpa_ie, ie->wpa_ie_len); + return 0; + } + + if (pos + 1 + RSN_SELECTOR_LEN < end && + pos[1] >= RSN_SELECTOR_LEN + PMKID_LEN && + RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_PMKID) { + ie->pmkid = pos + 2 + RSN_SELECTOR_LEN; + wpa_hexdump(MSG_DEBUG, "WPA: PMKID in EAPOL-Key", + pos, pos[1] + 2); + return 0; + } + + if (pos[1] > RSN_SELECTOR_LEN + 2 && + RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_GROUPKEY) { + ie->gtk = pos + 2 + RSN_SELECTOR_LEN; + ie->gtk_len = pos[1] - RSN_SELECTOR_LEN; + wpa_hexdump_key(MSG_DEBUG, "WPA: GTK in EAPOL-Key", + pos, pos[1] + 2); + return 0; + } + + if (pos[1] > RSN_SELECTOR_LEN + 2 && + RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_MAC_ADDR) { + ie->mac_addr = pos + 2 + RSN_SELECTOR_LEN; + ie->mac_addr_len = pos[1] - RSN_SELECTOR_LEN; + wpa_hexdump(MSG_DEBUG, "WPA: MAC Address in EAPOL-Key", + pos, pos[1] + 2); + return 0; + } + +#ifdef CONFIG_PEERKEY + if (pos[1] > RSN_SELECTOR_LEN + 2 && + RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_SMK) { + ie->smk = pos + 2 + RSN_SELECTOR_LEN; + ie->smk_len = pos[1] - RSN_SELECTOR_LEN; + wpa_hexdump_key(MSG_DEBUG, "WPA: SMK in EAPOL-Key", + pos, pos[1] + 2); + return 0; + } + + if (pos[1] > RSN_SELECTOR_LEN + 2 && + RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_NONCE) { + ie->nonce = pos + 2 + RSN_SELECTOR_LEN; + ie->nonce_len = pos[1] - RSN_SELECTOR_LEN; + wpa_hexdump(MSG_DEBUG, "WPA: Nonce in EAPOL-Key", + pos, pos[1] + 2); + return 0; + } + + if (pos[1] > RSN_SELECTOR_LEN + 2 && + RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_LIFETIME) { + ie->lifetime = pos + 2 + RSN_SELECTOR_LEN; + ie->lifetime_len = pos[1] - RSN_SELECTOR_LEN; + wpa_hexdump(MSG_DEBUG, "WPA: Lifetime in EAPOL-Key", + pos, pos[1] + 2); + return 0; + } + + if (pos[1] > RSN_SELECTOR_LEN + 2 && + RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_ERROR) { + ie->error = pos + 2 + RSN_SELECTOR_LEN; + ie->error_len = pos[1] - RSN_SELECTOR_LEN; + wpa_hexdump(MSG_DEBUG, "WPA: Error in EAPOL-Key", + pos, pos[1] + 2); + return 0; + } +#endif /* CONFIG_PEERKEY */ + +#ifdef CONFIG_IEEE80211W + if (pos[1] > RSN_SELECTOR_LEN + 2 && + RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_IGTK) { + ie->igtk = pos + 2 + RSN_SELECTOR_LEN; + ie->igtk_len = pos[1] - RSN_SELECTOR_LEN; + wpa_hexdump_key(MSG_DEBUG, "WPA: IGTK in EAPOL-Key", + pos, pos[1] + 2); + return 0; + } +#endif /* CONFIG_IEEE80211W */ + +#ifdef CONFIG_P2P + if (pos[1] >= RSN_SELECTOR_LEN + 1 && + RSN_SELECTOR_GET(pos + 2) == WFA_KEY_DATA_IP_ADDR_REQ) { + ie->ip_addr_req = pos + 2 + RSN_SELECTOR_LEN; + wpa_hexdump(MSG_DEBUG, "WPA: IP Address Request in EAPOL-Key", + ie->ip_addr_req, pos[1] - RSN_SELECTOR_LEN); + return 0; + } + + if (pos[1] >= RSN_SELECTOR_LEN + 3 * 4 && + RSN_SELECTOR_GET(pos + 2) == WFA_KEY_DATA_IP_ADDR_ALLOC) { + ie->ip_addr_alloc = pos + 2 + RSN_SELECTOR_LEN; + wpa_hexdump(MSG_DEBUG, + "WPA: IP Address Allocation in EAPOL-Key", + ie->ip_addr_alloc, pos[1] - RSN_SELECTOR_LEN); + return 0; + } +#endif /* CONFIG_P2P */ + + return 0; +} + + +/** + * wpa_supplicant_parse_ies - Parse EAPOL-Key Key Data IEs + * @buf: Pointer to the Key Data buffer + * @len: Key Data Length + * @ie: Pointer to parsed IE data + * Returns: 0 on success, -1 on failure + */ +int wpa_supplicant_parse_ies(const u8 *buf, size_t len, + struct wpa_eapol_ie_parse *ie) +{ + const u8 *pos, *end; + int ret = 0; + + os_memset(ie, 0, sizeof(*ie)); + for (pos = buf, end = pos + len; pos + 1 < end; pos += 2 + pos[1]) { + if (pos[0] == 0xdd && + ((pos == buf + len - 1) || pos[1] == 0)) { + /* Ignore padding */ + break; + } + if (pos + 2 + pos[1] > end) { + wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key Key Data " + "underflow (ie=%d len=%d pos=%d)", + pos[0], pos[1], (int) (pos - buf)); + wpa_hexdump_key(MSG_DEBUG, "WPA: Key Data", + buf, len); + ret = -1; + break; + } + if (*pos == WLAN_EID_RSN) { + ie->rsn_ie = pos; + ie->rsn_ie_len = pos[1] + 2; + wpa_hexdump(MSG_DEBUG, "WPA: RSN IE in EAPOL-Key", + ie->rsn_ie, ie->rsn_ie_len); + } else if (*pos == WLAN_EID_MOBILITY_DOMAIN && + pos[1] >= sizeof(struct rsn_mdie)) { + ie->mdie = pos; + ie->mdie_len = pos[1] + 2; + wpa_hexdump(MSG_DEBUG, "WPA: MDIE in EAPOL-Key", + ie->mdie, ie->mdie_len); + } else if (*pos == WLAN_EID_FAST_BSS_TRANSITION && + pos[1] >= sizeof(struct rsn_ftie)) { + ie->ftie = pos; + ie->ftie_len = pos[1] + 2; + wpa_hexdump(MSG_DEBUG, "WPA: FTIE in EAPOL-Key", + ie->ftie, ie->ftie_len); + } else if (*pos == WLAN_EID_TIMEOUT_INTERVAL && pos[1] >= 5) { + if (pos[2] == WLAN_TIMEOUT_REASSOC_DEADLINE) { + ie->reassoc_deadline = pos; + wpa_hexdump(MSG_DEBUG, "WPA: Reassoc Deadline " + "in EAPOL-Key", + ie->reassoc_deadline, pos[1] + 2); + } else if (pos[2] == WLAN_TIMEOUT_KEY_LIFETIME) { + ie->key_lifetime = pos; + wpa_hexdump(MSG_DEBUG, "WPA: KeyLifetime " + "in EAPOL-Key", + ie->key_lifetime, pos[1] + 2); + } else { + wpa_hexdump(MSG_DEBUG, "WPA: Unrecognized " + "EAPOL-Key Key Data IE", + pos, 2 + pos[1]); + } + } else if (*pos == WLAN_EID_LINK_ID) { + if (pos[1] >= 18) { + ie->lnkid = pos; + ie->lnkid_len = pos[1] + 2; + } + } else if (*pos == WLAN_EID_EXT_CAPAB) { + ie->ext_capab = pos; + ie->ext_capab_len = pos[1] + 2; + } else if (*pos == WLAN_EID_SUPP_RATES) { + ie->supp_rates = pos; + ie->supp_rates_len = pos[1] + 2; + } else if (*pos == WLAN_EID_EXT_SUPP_RATES) { + ie->ext_supp_rates = pos; + ie->ext_supp_rates_len = pos[1] + 2; + } else if (*pos == WLAN_EID_HT_CAP && + pos[1] >= sizeof(struct ieee80211_ht_capabilities)) { + ie->ht_capabilities = pos + 2; + } else if (*pos == WLAN_EID_VHT_AID) { + if (pos[1] >= 2) + ie->aid = WPA_GET_LE16(pos + 2) & 0x3fff; + } else if (*pos == WLAN_EID_VHT_CAP && + pos[1] >= sizeof(struct ieee80211_vht_capabilities)) + { + ie->vht_capabilities = pos + 2; + } else if (*pos == WLAN_EID_QOS && pos[1] >= 1) { + ie->qosinfo = pos[2]; + } else if (*pos == WLAN_EID_SUPPORTED_CHANNELS) { + ie->supp_channels = pos + 2; + ie->supp_channels_len = pos[1]; + } else if (*pos == WLAN_EID_SUPPORTED_OPERATING_CLASSES) { + /* + * The value of the Length field of the Supported + * Operating Classes element is between 2 and 253. + * Silently skip invalid elements to avoid interop + * issues when trying to use the value. + */ + if (pos[1] >= 2 && pos[1] <= 253) { + ie->supp_oper_classes = pos + 2; + ie->supp_oper_classes_len = pos[1]; + } + } else if (*pos == WLAN_EID_VENDOR_SPECIFIC) { + ret = wpa_parse_generic(pos, end, ie); + if (ret < 0) + break; + if (ret > 0) { + ret = 0; + break; + } + + ret = wpa_parse_vendor_specific(pos, end, ie); + if (ret < 0) + break; + if (ret > 0) { + ret = 0; + break; + } + } else { + wpa_hexdump(MSG_DEBUG, "WPA: Unrecognized EAPOL-Key " + "Key Data IE", pos, 2 + pos[1]); + } + } + + return ret; +} + + +static int wpa_gen_wpa_ie_wpa(u8 *wpa_ie, size_t wpa_ie_len, + int pairwise_cipher, int group_cipher, + int key_mgmt) +{ + u8 *pos; + struct wpa_ie_hdr *hdr; + u32 suite; + + if (wpa_ie_len < sizeof(*hdr) + WPA_SELECTOR_LEN + + 2 + WPA_SELECTOR_LEN + 2 + WPA_SELECTOR_LEN) + return -1; + + hdr = (struct wpa_ie_hdr *) wpa_ie; + hdr->elem_id = WLAN_EID_VENDOR_SPECIFIC; + RSN_SELECTOR_PUT(hdr->oui, WPA_OUI_TYPE); + WPA_PUT_LE16(hdr->version, WPA_VERSION); + pos = (u8 *) (hdr + 1); + + suite = wpa_cipher_to_suite(WPA_PROTO_WPA, group_cipher); + if (suite == 0) { + wpa_printf(MSG_WARNING, "Invalid group cipher (%d).", + group_cipher); + return -1; + } + RSN_SELECTOR_PUT(pos, suite); + pos += WPA_SELECTOR_LEN; + + *pos++ = 1; + *pos++ = 0; + suite = wpa_cipher_to_suite(WPA_PROTO_WPA, pairwise_cipher); + if (suite == 0 || + (!wpa_cipher_valid_pairwise(pairwise_cipher) && + pairwise_cipher != WPA_CIPHER_NONE)) { + wpa_printf(MSG_WARNING, "Invalid pairwise cipher (%d).", + pairwise_cipher); + return -1; + } + RSN_SELECTOR_PUT(pos, suite); + pos += WPA_SELECTOR_LEN; + + *pos++ = 1; + *pos++ = 0; + if (key_mgmt == WPA_KEY_MGMT_IEEE8021X) { + RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_UNSPEC_802_1X); + } else if (key_mgmt == WPA_KEY_MGMT_PSK) { + RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X); + } else if (key_mgmt == WPA_KEY_MGMT_WPA_NONE) { + RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_NONE); + } else if (key_mgmt == WPA_KEY_MGMT_CCKM) { + RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_CCKM); + } else { + wpa_printf(MSG_WARNING, "Invalid key management type (%d).", + key_mgmt); + return -1; + } + pos += WPA_SELECTOR_LEN; + + /* WPA Capabilities; use defaults, so no need to include it */ + + hdr->len = (pos - wpa_ie) - 2; + + WPA_ASSERT((size_t) (pos - wpa_ie) <= wpa_ie_len); + + return pos - wpa_ie; +} + + +static int wpa_gen_wpa_ie_rsn(u8 *rsn_ie, size_t rsn_ie_len, + int pairwise_cipher, int group_cipher, + int key_mgmt, int mgmt_group_cipher, + struct wpa_sm *sm) +{ + u8 *pos; + struct rsn_ie_hdr *hdr; + u16 capab; + u32 suite; + + if (rsn_ie_len < sizeof(*hdr) + RSN_SELECTOR_LEN + + 2 + RSN_SELECTOR_LEN + 2 + RSN_SELECTOR_LEN + 2 + + (sm->cur_pmksa ? 2 + PMKID_LEN : 0)) { + wpa_printf(MSG_DEBUG, "RSN: Too short IE buffer (%lu bytes)", + (unsigned long) rsn_ie_len); + return -1; + } + + hdr = (struct rsn_ie_hdr *) rsn_ie; + hdr->elem_id = WLAN_EID_RSN; + WPA_PUT_LE16(hdr->version, RSN_VERSION); + pos = (u8 *) (hdr + 1); + + suite = wpa_cipher_to_suite(WPA_PROTO_RSN, group_cipher); + if (suite == 0) { + wpa_printf(MSG_WARNING, "Invalid group cipher (%d).", + group_cipher); + return -1; + } + RSN_SELECTOR_PUT(pos, suite); + pos += RSN_SELECTOR_LEN; + + *pos++ = 1; + *pos++ = 0; + suite = wpa_cipher_to_suite(WPA_PROTO_RSN, pairwise_cipher); + if (suite == 0 || + (!wpa_cipher_valid_pairwise(pairwise_cipher) && + pairwise_cipher != WPA_CIPHER_NONE)) { + wpa_printf(MSG_WARNING, "Invalid pairwise cipher (%d).", + pairwise_cipher); + return -1; + } + RSN_SELECTOR_PUT(pos, suite); + pos += RSN_SELECTOR_LEN; + + *pos++ = 1; + *pos++ = 0; + if (key_mgmt == WPA_KEY_MGMT_IEEE8021X) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X); + } else if (key_mgmt == WPA_KEY_MGMT_PSK) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X); + } else if (key_mgmt == WPA_KEY_MGMT_CCKM) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_CCKM); +#ifdef CONFIG_IEEE80211R + } else if (key_mgmt == WPA_KEY_MGMT_FT_IEEE8021X) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X); + } else if (key_mgmt == WPA_KEY_MGMT_FT_PSK) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_PSK); +#endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_IEEE80211W + } else if (key_mgmt == WPA_KEY_MGMT_IEEE8021X_SHA256) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SHA256); + } else if (key_mgmt == WPA_KEY_MGMT_PSK_SHA256) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_SHA256); +#endif /* CONFIG_IEEE80211W */ +#ifdef CONFIG_SAE + } else if (key_mgmt == WPA_KEY_MGMT_SAE) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_SAE); + } else if (key_mgmt == WPA_KEY_MGMT_FT_SAE) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_SAE); +#endif /* CONFIG_SAE */ + } else if (key_mgmt == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192); + } else if (key_mgmt == WPA_KEY_MGMT_IEEE8021X_SUITE_B) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SUITE_B); + } else { + wpa_printf(MSG_WARNING, "Invalid key management type (%d).", + key_mgmt); + return -1; + } + pos += RSN_SELECTOR_LEN; + + /* RSN Capabilities */ + capab = 0; +#ifdef CONFIG_IEEE80211W + if (sm->mfp) + capab |= WPA_CAPABILITY_MFPC; + if (sm->mfp == 2) + capab |= WPA_CAPABILITY_MFPR; +#endif /* CONFIG_IEEE80211W */ + WPA_PUT_LE16(pos, capab); + pos += 2; + +#ifdef CONFIG_IEEE80211W + if (wpa_cipher_valid_mgmt_group(mgmt_group_cipher)) { + if (!sm->cur_pmksa) { + /* PMKID Count */ + WPA_PUT_LE16(pos, 0); + pos += 2; + } + + /* Management Group Cipher Suite */ + RSN_SELECTOR_PUT(pos, wpa_cipher_to_suite(WPA_PROTO_RSN, + mgmt_group_cipher)); + pos += RSN_SELECTOR_LEN; + } +#endif /* CONFIG_IEEE80211W */ + + hdr->len = (pos - rsn_ie) - 2; + + WPA_ASSERT((size_t) (pos - rsn_ie) <= rsn_ie_len); + + return pos - rsn_ie; +} + + + +/** + * wpa_gen_wpa_ie - Generate WPA/RSN IE based on current security policy + * @sm: Pointer to WPA state machine data from wpa_sm_init() + * @wpa_ie: Pointer to memory area for the generated WPA/RSN IE + * @wpa_ie_len: Maximum length of the generated WPA/RSN IE + * Returns: Length of the generated WPA/RSN IE or -1 on failure + */ +int wpa_gen_wpa_ie(struct wpa_sm *sm, u8 *wpa_ie, size_t wpa_ie_len) +{ + if (sm->proto == WPA_PROTO_RSN) + return wpa_gen_wpa_ie_rsn(wpa_ie, wpa_ie_len, + sm->pairwise_cipher, + sm->group_cipher, + sm->key_mgmt, sm->mgmt_group_cipher, + sm); + else + return wpa_gen_wpa_ie_wpa(wpa_ie, wpa_ie_len, + sm->pairwise_cipher, + sm->group_cipher, + sm->key_mgmt); +} + diff --git a/beken_os/beken378/func/hostapd-2.5/src/rsn_supp/wpa_ie.h b/beken_os/beken378/func/hostapd-2.5/src/rsn_supp/wpa_ie.h new file mode 100755 index 0000000..fe95af0 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/rsn_supp/wpa_ie.h @@ -0,0 +1,72 @@ +/* + * wpa_supplicant - WPA/RSN IE and KDE definitions + * Copyright (c) 2004-2007, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef WPA_IE_H +#define WPA_IE_H + +struct wpa_sm; + +struct wpa_eapol_ie_parse { + const u8 *wpa_ie; + size_t wpa_ie_len; + const u8 *rsn_ie; + size_t rsn_ie_len; + const u8 *pmkid; + const u8 *gtk; + size_t gtk_len; + const u8 *mac_addr; + size_t mac_addr_len; +#ifdef CONFIG_PEERKEY + const u8 *smk; + size_t smk_len; + const u8 *nonce; + size_t nonce_len; + const u8 *lifetime; + size_t lifetime_len; + const u8 *error; + size_t error_len; +#endif /* CONFIG_PEERKEY */ +#ifdef CONFIG_IEEE80211W + const u8 *igtk; + size_t igtk_len; +#endif /* CONFIG_IEEE80211W */ + const u8 *mdie; + size_t mdie_len; + const u8 *ftie; + size_t ftie_len; + const u8 *reassoc_deadline; + const u8 *key_lifetime; + const u8 *lnkid; + size_t lnkid_len; + const u8 *ext_capab; + size_t ext_capab_len; + const u8 *supp_rates; + size_t supp_rates_len; + const u8 *ext_supp_rates; + size_t ext_supp_rates_len; + const u8 *ht_capabilities; + const u8 *vht_capabilities; + const u8 *supp_channels; + size_t supp_channels_len; + const u8 *supp_oper_classes; + size_t supp_oper_classes_len; + u8 qosinfo; + u16 aid; + const u8 *wmm; + size_t wmm_len; +#ifdef CONFIG_P2P + const u8 *ip_addr_req; + const u8 *ip_addr_alloc; +#endif /* CONFIG_P2P */ +}; + +int wpa_supplicant_parse_ies(const u8 *buf, size_t len, + struct wpa_eapol_ie_parse *ie); +int wpa_gen_wpa_ie(struct wpa_sm *sm, u8 *wpa_ie, size_t wpa_ie_len); + +#endif /* WPA_IE_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/utils/base64.h b/beken_os/beken378/func/hostapd-2.5/src/utils/base64.h new file mode 100755 index 0000000..aa21fd0 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/utils/base64.h @@ -0,0 +1,17 @@ +/* + * Base64 encoding/decoding (RFC1341) + * Copyright (c) 2005, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef BASE64_H +#define BASE64_H + +unsigned char * base64_encode(const unsigned char *src, size_t len, + size_t *out_len); +unsigned char * base64_decode(const unsigned char *src, size_t len, + size_t *out_len); + +#endif /* BASE64_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/utils/build_config.h b/beken_os/beken378/func/hostapd-2.5/src/utils/build_config.h new file mode 100755 index 0000000..ec5359b --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/utils/build_config.h @@ -0,0 +1,260 @@ +/* + * wpa_supplicant/hostapd - Build time configuration defines + * Copyright (c) 2005-2006, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + * + * This header file can be used to define configuration defines that were + * originally defined in Makefile. This is mainly meant for IDE use or for + * systems that do not have suitable 'make' tool. In these cases, it may be + * easier to have a single place for defining all the needed C pre-processor + * defines. + */ + +#ifndef BUILD_CONFIG_H +#define BUILD_CONFIG_H + +#include "sys_config.h" +#include "rwnx_config.h" +/* Insert configuration defines, e.g., #define EAP_MD5, here, if needed. */ + +/* if want supplicant supports AP, enable CONFIG_AP */ +//#define CONFIG_AP +#define NEED_AP_MLME +#define CONFIG_NO_CONFIG_WRITE +#define OS_NO_C_LIB_DEFINES +#define HOSTAPD +#define CONFIG_NO_CONFIG_BLOBS + +#if CFG_IEEE80211N +/* IEEE 802.11n (High Throughput) support */ +#define CONFIG_IEEE80211N 1 +#endif + +/* Driver interface for beken driver */ +#define CONFIG_DRIVER_BEKEN 1 + +/* Driver interface for wired authenticator */ +//#define CONFIG_DRIVER_WIRED 1 + +/* Driver interface for drivers using the nl80211 kernel interface */ +//#define CONFIG_DRIVER_NL80211 1 + +/* Use libnl v2.0 (or 3.0) libraries */ +//#define CONFIG_LIBNL20 1 +/* Use libnl 3.2 libraries */ +//#define CONFIG_LIBNL32 1 + +/* Driver interface for FreeBSD net80211 layer */ +//#define CONFIG_DRIVER_BSD 1 +/* Driver interface for no driver */ +//#define CONFIG_DRIVER_NONE 1 + +/* IEEE 802.11F/IAPP */ +//#define CONFIG_IAPP 1 + +/* WPA2/IEEE 802.11i RSN pre-authentication */ +//#define CONFIG_RSN_PREAUTH 1 + +/* PeerKey handshake for Station to Station Link (IEEE 802.11e DLS) */ +//#define CONFIG_PEERKEY 1 + +/* IEEE 802.11w (management frame protection) */ +//#define CONFIG_IEEE80211W 1 + +/* Integrated EAP server */ +//#define CONFIG_EAP 1 +/* EAP Re-authentication Protocol (ERP) in integrated EAP server */ +//#define CONFIG_ERP 1 +/* EAP-MD5 for the integrated EAP server */ +#define CONFIG_EAP_MD5 1 +/* EAP-TLS for the integrated EAP server */ +#define CONFIG_EAP_TLS 1 +/* EAP-MSCHAPv2 for the integrated EAP server */ +//#define CONFIG_EAP_MSCHAPV2 1 +/* EAP-PEAP for the integrated EAP server */ +//#define CONFIG_EAP_PEAP 1 +/* EAP-GTC for the integrated EAP server */ +//#define CONFIG_EAP_GTC 1 +/* EAP-TTLS for the integrated EAP server */ +//#define CONFIG_EAP_TTLS 1 +/* EAP-SIM for the integrated EAP server */ +//#define CONFIG_EAP_SIM 1 +/* EAP-AKA for the integrated EAP server */ +//#define CONFIG_EAP_AKA 1 +/* EAP-AKA' for the integrated EAP server. + This requires CONFIG_EAP_AKA to be enabled, too. */ +//#define CONFIG_EAP_AKA_PRIME 1 +/* EAP-PAX for the integrated EAP server */ +//#define CONFIG_EAP_PAX 1 +/* EAP-PSK for the integrated EAP server (this is _not_ needed for WPA-PSK) */ +//#define CONFIG_EAP_PSK 1 +/* EAP-pwd for the integrated EAP server (secure authentication with a password) */ +//#define CONFIG_EAP_PWD 1 +/* EAP-SAKE for the integrated EAP server */ +//#define CONFIG_EAP_SAKE 1 + +/* EAP-GPSK for the integrated EAP server */ +//#define CONFIG_EAP_GPSK 1 +/* Include support for optional SHA256 cipher suite in EAP-GPSK */ +//#define CONFIG_EAP_GPSK_SHA256 1 + +/* EAP-FAST for the integrated EAP server + * Note: If OpenSSL is used as the TLS library, OpenSSL 1.0 or newer is needed + * for EAP-FAST support. Older OpenSSL releases would need to be patched, e.g., + * with openssl-0.9.8x-tls-extensions.patch, to add the needed functions. */ +//#define CONFIG_EAP_FAST 1 + +/* Wi-Fi Protected Setup (WPS) */ +//#define CONFIG_WPS 1 +/* Enable UPnP support for external WPS Registrars */ +//#define CONFIG_WPS_UPNP 1 +/* Enable WPS support with NFC config method */ +//#define CONFIG_WPS_NFC 1 + +/* EAP-IKEv2 */ +//#define CONFIG_EAP_IKEV2 1 + +/* Trusted Network Connect (EAP-TNC) */ +//#define CONFIG_EAP_TNC 1 + +/* EAP-EKE for the integrated EAP server */ +//#define CONFIG_EAP_EKE 1 + +/* PKCS#12 (PFX) support (used to read private key and certificate file from + * a file that usually has extension .p12 or .pfx) */ +//#define CONFIG_PKCS12 1 + +/* RADIUS authentication server. This provides access to the integrated EAP + * server from external hosts using RADIUS. */ +//#define CONFIG_RADIUS_SERVER 1 + +/* Build IPv6 support for RADIUS operations */ +//#define CONFIG_IPV6 1 + +/* IEEE Std 802.11r-2008 (Fast BSS Transition) */ +//#define CONFIG_IEEE80211R 1 + +/* Use the hostapd's IEEE 802.11 authentication (ACL), but without + * the IEEE 802.11 Management capability (e.g., FreeBSD/net80211) */ +//#define CONFIG_DRIVER_RADIUS_ACL 1 + +/* Wireless Network Management (IEEE Std 802.11v-2011) + Note: This is experimental and not complete implementation. */ +//#define CONFIG_WNM 1 + +/* IEEE 802.11ac (Very High Throughput) support */ +//#define CONFIG_IEEE80211AC 1 + +/* Remove debugging code that is printing out debug messages to stdout. + * This can be used to reduce the size of the hostapd considerably if debugging + * code is not needed. */ +#define CONFIG_NO_STDOUT_DEBUG 1 + +/* Add support for writing debug log to a file: -f /tmp/hostapd.log + * Disabled by default. */ +//#define CONFIG_DEBUG_FILE 1 + +/* Add support for sending all debug messages (regardless of debug verbosity) + * to the Linux kernel tracing facility. This helps debug the entire stack by + * making it easy to record everything happening from the driver up into the + * same file, e.g., using trace-cmd. */ +//#define CONFIG_DEBUG_LINUX_TRACING 1 + +/* Remove support for RADIUS accounting */ +#define CONFIG_NO_ACCOUNTING 1 + +/* Remove support for RADIUS */ +#define CONFIG_NO_RADIUS 1 + +/* Remove support for VLANs */ +#define CONFIG_NO_VLAN 1 + +/* Enable support for fully dynamic VLANs. This enables hostapd to + * automatically create bridge and VLAN interfaces if necessary. */ +//#define CONFIG_FULL_DYNAMIC_VLAN 1 + +/* Use netlink-based kernel API for VLAN operations instead of ioctl() + * Note: This requires libnl 3.1 or newer. */ +//#define CONFIG_VLAN_NETLINK 1 + +/* Remove support for dumping internal state through control interface commands + * This can be used to reduce binary size at the cost of disabling a debugging option. */ +#define CONFIG_NO_DUMP_STATE 1 + +/* Enable tracing code for developer debugging + * This tracks use of memory allocations and other registrations and reports + * incorrect use with a backtrace of call (or allocation) location. */ +//#define CONFIG_WPA_TRACE 1 + +/* Use libbfd to get more details for developer debugging + * This enables use of libbfd to get more detailed symbols for the backtraces + * generated by CONFIG_WPA_TRACE. */ +//#define CONFIG_WPA_TRACE_BFD 1 + +/* os_get_random() function is used to fetch random data when needed. */ +#define CONFIG_NO_RANDOM_POOL 1 + +/* Should we use poll instead of select? Select is used by default. */ +//#define CONFIG_ELOOP_POLL 1 + +/* Should we use epoll instead of select? Select is used by default. */ +//#define CONFIG_ELOOP_EPOLL 1 + +/* Select TLS implementation + * openssl = OpenSSL (default) + * gnutls = GnuTLS + * internal = Internal TLSv1 implementation (experimental) + * none = Empty template */ +//#define CONFIG_TLS openssl + +/* TLS-based EAP methods require at least TLS v1.0. Newer version of TLS (v1.1) + * can be enabled to get a stronger construction of messages when block ciphers + * are used. */ +//#define CONFIG_TLSV11 1 + +/* TLS-based EAP methods require at least TLS v1.0. Newer version of TLS (v1.2) + * can be enabled to enable use of stronger crypto algorithms. */ +//#define CONFIG_TLSV12 1 + +/* If CONFIG_TLS=internal is used, additional library and include paths are + * needed for LibTomMath. Alternatively, an integrated, minimal version of + * LibTomMath can be used. See beginning of libtommath.c for details on benefits + * and drawbacks of this option. */ +//#define CONFIG_INTERNAL_LIBTOMMATH 1 +/* At the cost of about 4 kB of additional binary size, the internal LibTomMath + * can be configured to include faster routines for exptmod, sqr, and div to + * speed up DH and RSA calculation considerably */ +//#define CONFIG_INTERNAL_LIBTOMMATH_FAST 1 + +/* Interworking (IEEE 802.11u) + * This can be used to enable functionality to improve interworking with + * external networks. */ +//#define CONFIG_INTERWORKING 1 + +/* Hotspot 2.0 */ +//#define CONFIG_HS20 1 + +/* Enable SQLite database support in hlr_auc_gw, EAP-SIM DB, and eap_user_file */ +//#define CONFIG_SQLITE 1 + +/* Enable Fast Session Transfer (FST) */ +//#define CONFIG_FST 1 + +/* Enable CLI commands for FST testing */ +//#define CONFIG_FST_TEST 1 + +/* Testing options + * This can be used to enable some testing options (see also the example + * configuration file) that are really useful only for testing clients that + * connect to this hostapd. These options allow, for example, to drop a + * certain percentage of probe requests or auth/(re)assoc frames. */ +//#define CONFIG_TESTING_OPTIONS 1 + +/* Automatic Channel Selection */ +//#define CONFIG_ACS 1 + +#define CONFIG_NO_HOSTAPD_LOGGER 1 +#define CONFIG_NO_WPA_MSG 1 +#endif /* BUILD_CONFIG_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/utils/common.c b/beken_os/beken378/func/hostapd-2.5/src/utils/common.c new file mode 100755 index 0000000..c039277 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/utils/common.c @@ -0,0 +1,1125 @@ +/* + * wpa_supplicant/hostapd / common helper functions, etc. + * Copyright (c) 2002-2007, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "includes.h" + +#include "common/ieee802_11_defs.h" +#include "common.h" + + +static int hex2num(char c) +{ + if (c >= '0' && c <= '9') + return c - '0'; + if (c >= 'a' && c <= 'f') + return c - 'a' + 10; + if (c >= 'A' && c <= 'F') + return c - 'A' + 10; + return -1; +} + + +int hex2byte(const char *hex) +{ + int a, b; + a = hex2num(*hex++); + if (a < 0) + return -1; + b = hex2num(*hex++); + if (b < 0) + return -1; + return (a << 4) | b; +} + + +static const char * hwaddr_parse(const char *txt, u8 *addr) +{ + size_t i; + + for (i = 0; i < ETH_ALEN; i++) { + int a; + + a = hex2byte(txt); + if (a < 0) + return NULL; + txt += 2; + addr[i] = a; + if (i < ETH_ALEN - 1 && *txt++ != ':') + return NULL; + } + return txt; +} + + +/** + * hwaddr_aton - Convert ASCII string to MAC address (colon-delimited format) + * @txt: MAC address as a string (e.g., "00:11:22:33:44:55") + * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes) + * Returns: 0 on success, -1 on failure (e.g., string not a MAC address) + */ +int hwaddr_aton(const char *txt, u8 *addr) +{ + return hwaddr_parse(txt, addr) ? 0 : -1; +} + + +/** + * hwaddr_masked_aton - Convert ASCII string with optional mask to MAC address (colon-delimited format) + * @txt: MAC address with optional mask as a string (e.g., "00:11:22:33:44:55/ff:ff:ff:ff:00:00") + * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes) + * @mask: Buffer for the MAC address mask (ETH_ALEN = 6 bytes) + * @maskable: Flag to indicate whether a mask is allowed + * Returns: 0 on success, -1 on failure (e.g., string not a MAC address) + */ +int hwaddr_masked_aton(const char *txt, u8 *addr, u8 *mask, u8 maskable) +{ + const char *r; + + /* parse address part */ + r = hwaddr_parse(txt, addr); + if (!r) + return -1; + + /* check for optional mask */ + if (((unsigned char)*r) == '\0' || isspace(((unsigned char)*r))) { + /* no mask specified, assume default */ + os_memset(mask, 0xff, ETH_ALEN); + } else if (maskable && *r == '/') { + /* mask specified and allowed */ + r = hwaddr_parse(r + 1, mask); + /* parser error? */ + if (!r) + return -1; + } else { + /* mask specified but not allowed or trailing garbage */ + return -1; + } + + return 0; +} + + +/** + * hwaddr_compact_aton - Convert ASCII string to MAC address (no colon delimitors format) + * @txt: MAC address as a string (e.g., "001122334455") + * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes) + * Returns: 0 on success, -1 on failure (e.g., string not a MAC address) + */ +int hwaddr_compact_aton(const char *txt, u8 *addr) +{ + int i; + + for (i = 0; i < 6; i++) { + int a, b; + + a = hex2num(*txt++); + if (a < 0) + return -1; + b = hex2num(*txt++); + if (b < 0) + return -1; + *addr++ = (a << 4) | b; + } + + return 0; +} + +/** + * hwaddr_aton2 - Convert ASCII string to MAC address (in any known format) + * @txt: MAC address as a string (e.g., 00:11:22:33:44:55 or 0011.2233.4455) + * @addr: Buffer for the MAC address (ETH_ALEN = 6 bytes) + * Returns: Characters used (> 0) on success, -1 on failure + */ +int hwaddr_aton2(const char *txt, u8 *addr) +{ + int i; + const char *pos = txt; + + for (i = 0; i < 6; i++) { + int a, b; + + while (*pos == ':' || *pos == '.' || *pos == '-') + pos++; + + a = hex2num(*pos++); + if (a < 0) + return -1; + b = hex2num(*pos++); + if (b < 0) + return -1; + *addr++ = (a << 4) | b; + } + + return pos - txt; +} + + +/** + * hexstr2bin - Convert ASCII hex string into binary data + * @hex: ASCII hex string (e.g., "01ab") + * @buf: Buffer for the binary data + * @len: Length of the text to convert in bytes (of buf); hex will be double + * this size + * Returns: 0 on success, -1 on failure (invalid hex string) + */ +int hexstr2bin(const char *hex, u8 *buf, size_t len) +{ + size_t i; + int a; + const char *ipos = hex; + u8 *opos = buf; + + for (i = 0; i < len; i++) { + a = hex2byte(ipos); + if (a < 0) + return -1; + *opos++ = a; + ipos += 2; + } + return 0; +} + + +int hwaddr_mask_txt(char *buf, size_t len, const u8 *addr, const u8 *mask) +{ + size_t i; + int print_mask = 0; + int res; + + for (i = 0; i < ETH_ALEN; i++) { + if (mask[i] != 0xff) { + print_mask = 1; + break; + } + } + + if (print_mask) + res = os_snprintf(buf, len, MACSTR "/" MACSTR, + MAC2STR(addr), MAC2STR(mask)); + else + res = os_snprintf(buf, len, MACSTR, MAC2STR(addr)); + if (os_snprintf_error(len, res)) + return -1; + return res; +} + + +/** + * inc_byte_array - Increment arbitrary length byte array by one + * @counter: Pointer to byte array + * @len: Length of the counter in bytes + * + * This function increments the last byte of the counter by one and continues + * rolling over to more significant bytes if the byte was incremented from + * 0xff to 0x00. + */ +void inc_byte_array(u8 *counter, size_t len) +{ + int pos = len - 1; + while (pos >= 0) { + counter[pos]++; + if (counter[pos] != 0) + break; + pos--; + } +} + + +void wpa_get_ntp_timestamp(u8 *buf) +{ + struct os_time now; + u32 sec, usec; + be32 tmp; + + /* 64-bit NTP timestamp (time from 1900-01-01 00:00:00) */ + os_get_time(&now); + sec = now.sec + 2208988800U; /* Epoch to 1900 */ + /* Estimate 2^32/10^6 = 4295 - 1/32 - 1/512 */ + usec = now.usec; + usec = 4295 * usec - (usec >> 5) - (usec >> 9); + tmp = host_to_be32(sec); + os_memcpy(buf, (u8 *) &tmp, 4); + tmp = host_to_be32(usec); + os_memcpy(buf + 4, (u8 *) &tmp, 4); +} + +/** + * wpa_scnprintf - Simpler-to-use snprintf function + * @buf: Output buffer + * @size: Buffer size + * @fmt: format + * + * Simpler snprintf version that doesn't require further error checks - the + * return value only indicates how many bytes were actually written, excluding + * the NULL byte (i.e., 0 on error, size-1 if buffer is not big enough). + */ +int wpa_scnprintf(char *buf, size_t size, const char *fmt, ...) +{ + va_list ap; + int ret; + + if (!size) + return 0; + + va_start(ap, fmt); + ret = vsnprintf(buf, size, fmt, ap); + va_end(ap); + + if (ret < 0) + return 0; + if ((size_t) ret >= size) + return size - 1; + + return ret; +} + + +int wpa_snprintf_hex_sep(char *buf, size_t buf_size, const u8 *data, size_t len, + char sep) +{ + size_t i; + char *pos = buf, *end = buf + buf_size; + int ret; + + if (buf_size == 0) + return 0; + + for (i = 0; i < len; i++) { + ret = os_snprintf(pos, end - pos, "%02x%c", + data[i], sep); + if (os_snprintf_error(end - pos, ret)) { + end[-1] = '\0'; + return pos - buf; + } + pos += ret; + } + pos[-1] = '\0'; + return pos - buf; +} + + +static inline int _wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, + size_t len, int uppercase) +{ + size_t i; + char *pos = buf, *end = buf + buf_size; + int ret; + if (buf_size == 0) + return 0; + for (i = 0; i < len; i++) { + ret = os_snprintf(pos, end - pos, uppercase ? "%02X" : "%02x", + data[i]); + if (os_snprintf_error(end - pos, ret)) { + end[-1] = '\0'; + return pos - buf; + } + pos += ret; + } + end[-1] = '\0'; + return pos - buf; +} + +/** + * wpa_snprintf_hex - Print data as a hex string into a buffer + * @buf: Memory area to use as the output buffer + * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1) + * @data: Data to be printed + * @len: Length of data in bytes + * Returns: Number of bytes written + */ +int wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len) +{ + return _wpa_snprintf_hex(buf, buf_size, data, len, 0); +} + + +/** + * wpa_snprintf_hex_uppercase - Print data as a upper case hex string into buf + * @buf: Memory area to use as the output buffer + * @buf_size: Maximum buffer size in bytes (should be at least 2 * len + 1) + * @data: Data to be printed + * @len: Length of data in bytes + * Returns: Number of bytes written + */ +int wpa_snprintf_hex_uppercase(char *buf, size_t buf_size, const u8 *data, + size_t len) +{ + return _wpa_snprintf_hex(buf, buf_size, data, len, 1); +} + + +#ifdef CONFIG_ANSI_C_EXTRA + +#ifdef _WIN32_WCE +void perror(const char *s) +{ + wpa_printf(MSG_ERROR, "%s: GetLastError: %d", + s, (int) GetLastError()); +} +#endif /* _WIN32_WCE */ + + +int optind = 1; +int optopt; +char *optarg; + +int getopt(int argc, char *const argv[], const char *optstring) +{ + static int optchr = 1; + char *cp; + + if (optchr == 1) { + if (optind >= argc) { + /* all arguments processed */ + return EOF; + } + + if (argv[optind][0] != '-' || argv[optind][1] == '\0') { + /* no option characters */ + return EOF; + } + } + + if (os_strcmp(argv[optind], "--") == 0) { + /* no more options */ + optind++; + return EOF; + } + + optopt = argv[optind][optchr]; + cp = os_strchr(optstring, optopt); + if (cp == NULL || optopt == ':') { + if (argv[optind][++optchr] == '\0') { + optchr = 1; + optind++; + } + return '?'; + } + + if (cp[1] == ':') { + /* Argument required */ + optchr = 1; + if (argv[optind][optchr + 1]) { + /* No space between option and argument */ + optarg = &argv[optind++][optchr + 1]; + } else if (++optind >= argc) { + /* option requires an argument */ + return '?'; + } else { + /* Argument in the next argv */ + optarg = argv[optind++]; + } + } else { + /* No argument */ + if (argv[optind][++optchr] == '\0') { + optchr = 1; + optind++; + } + optarg = NULL; + } + return *cp; +} +#endif /* CONFIG_ANSI_C_EXTRA */ + + +#ifdef CONFIG_NATIVE_WINDOWS +/** + * wpa_unicode2ascii_inplace - Convert unicode string into ASCII + * @str: Pointer to string to convert + * + * This function converts a unicode string to ASCII using the same + * buffer for output. If UNICODE is not set, the buffer is not + * modified. + */ +void wpa_unicode2ascii_inplace(TCHAR *str) +{ +#ifdef UNICODE + char *dst = (char *) str; + while (*str) + *dst++ = (char) *str++; + *dst = '\0'; +#endif /* UNICODE */ +} + + +TCHAR * wpa_strdup_tchar(const char *str) +{ +#ifdef UNICODE + TCHAR *buf; + buf = os_malloc((strlen(str) + 1) * sizeof(TCHAR)); + if (buf == NULL) + return NULL; + wsprintf(buf, L"%S", str); + return buf; +#else /* UNICODE */ + return os_strdup(str); +#endif /* UNICODE */ +} +#endif /* CONFIG_NATIVE_WINDOWS */ + + +void printf_encode(char *txt, size_t maxlen, const u8 *data, size_t len) +{ + char *end = txt + maxlen; + size_t i; + + for (i = 0; i < len; i++) { + if (txt + 4 >= end) + break; + + switch (data[i]) { + case '\"': + *txt++ = '\\'; + *txt++ = '\"'; + break; + case '\\': + *txt++ = '\\'; + *txt++ = '\\'; + break; + case '\033': + *txt++ = '\\'; + *txt++ = 'e'; + break; + case '\n': + *txt++ = '\\'; + *txt++ = 'n'; + break; + case '\r': + *txt++ = '\\'; + *txt++ = 'r'; + break; + case '\t': + *txt++ = '\\'; + *txt++ = 't'; + break; + default: + if (data[i] >= 32 && data[i] <= 127) { + *txt++ = data[i]; + } else { + txt += os_snprintf(txt, end - txt, "\\x%02x", + data[i]); + } + break; + } + } + + *txt = '\0'; +} + + +size_t printf_decode(u8 *buf, size_t maxlen, const char *str) +{ + const char *pos = str; + size_t len = 0; + int val; + + while (*pos) { + if (len + 1 >= maxlen) + break; + switch (*pos) { + case '\\': + pos++; + switch (*pos) { + case '\\': + buf[len++] = '\\'; + pos++; + break; + case '"': + buf[len++] = '"'; + pos++; + break; + case 'n': + buf[len++] = '\n'; + pos++; + break; + case 'r': + buf[len++] = '\r'; + pos++; + break; + case 't': + buf[len++] = '\t'; + pos++; + break; + case 'e': + buf[len++] = '\033'; + pos++; + break; + case 'x': + pos++; + val = hex2byte(pos); + if (val < 0) { + val = hex2num(*pos); + if (val < 0) + break; + buf[len++] = val; + pos++; + } else { + buf[len++] = val; + pos += 2; + } + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + val = *pos++ - '0'; + if (*pos >= '0' && *pos <= '7') + val = val * 8 + (*pos++ - '0'); + if (*pos >= '0' && *pos <= '7') + val = val * 8 + (*pos++ - '0'); + buf[len++] = val; + break; + default: + break; + } + break; + default: + buf[len++] = *pos++; + break; + } + } + if (maxlen > len) + buf[len] = '\0'; + + return len; +} + + +/** + * wpa_ssid_txt - Convert SSID to a printable string + * @ssid: SSID (32-octet string) + * @ssid_len: Length of ssid in octets + * Returns: Pointer to a printable string + * + * This function can be used to convert SSIDs into printable form. In most + * cases, SSIDs do not use unprintable characters, but IEEE 802.11 standard + * does not limit the used character set, so anything could be used in an SSID. + * + * This function uses a static buffer, so only one call can be used at the + * time, i.e., this is not re-entrant and the returned buffer must be used + * before calling this again. + */ +const char * wpa_ssid_txt(const u8 *ssid, size_t ssid_len) +{ + static char ssid_txt[SSID_MAX_LEN * 4 + 1]; + + if (ssid == NULL) { + ssid_txt[0] = '\0'; + return ssid_txt; + } + + printf_encode(ssid_txt, sizeof(ssid_txt), ssid, ssid_len); + return ssid_txt; +} + + +void * __hide_aliasing_typecast(void *foo) +{ + return foo; +} + + +char * wpa_config_parse_string(const char *value, size_t *len) +{ + if (*value == '"') { + const char *pos; + char *str; + value++; + pos = os_strrchr(value, '"'); + if (pos == NULL || pos[1] != '\0') + return NULL; + *len = pos - value; + str = dup_binstr(value, *len); + if (str == NULL) + return NULL; + return str; + } else if (*value == 'P' && value[1] == '"') { + const char *pos; + char *tstr, *str; + size_t tlen; + value += 2; + pos = os_strrchr(value, '"'); + if (pos == NULL || pos[1] != '\0') + return NULL; + tlen = pos - value; + tstr = dup_binstr(value, tlen); + if (tstr == NULL) + return NULL; + + str = os_malloc(tlen + 1); + if (str == NULL) { + os_free(tstr); + return NULL; + } + + *len = printf_decode((u8 *) str, tlen + 1, tstr); + os_free(tstr); + + return str; + } else { + u8 *str; + size_t tlen, hlen = os_strlen(value); + if (hlen & 1) + return NULL; + tlen = hlen / 2; + str = os_malloc(tlen + 1); + if (str == NULL) + return NULL; + if (hexstr2bin(value, str, tlen)) { + os_free(str); + return NULL; + } + str[tlen] = '\0'; + *len = tlen; + return (char *) str; + } +} + + +int is_hex(const u8 *data, size_t len) +{ + size_t i; + + for (i = 0; i < len; i++) { + if (data[i] < 32 || data[i] >= 127) + return 1; + } + return 0; +} + + +size_t merge_byte_arrays(u8 *res, size_t res_len, + const u8 *src1, size_t src1_len, + const u8 *src2, size_t src2_len) +{ + size_t len = 0; + + os_memset(res, 0, res_len); + + if (src1) { + if (src1_len >= res_len) { + os_memcpy(res, src1, res_len); + return res_len; + } + + os_memcpy(res, src1, src1_len); + len += src1_len; + } + + if (src2) { + if (len + src2_len >= res_len) { + os_memcpy(res + len, src2, res_len - len); + return res_len; + } + + os_memcpy(res + len, src2, src2_len); + len += src2_len; + } + + return len; +} + + +char * dup_binstr(const void *src, size_t len) +{ + char *res; + + if (src == NULL) + return NULL; + res = os_malloc(len + 1); + if (res == NULL) + return NULL; + os_memcpy(res, src, len); + res[len] = '\0'; + + return res; +} + + +int freq_range_list_parse(struct wpa_freq_range_list *res, const char *value) +{ + struct wpa_freq_range *freq = NULL, *n; + unsigned int count = 0; + const char *pos, *pos2, *pos3; + + /* + * Comma separated list of frequency ranges. + * For example: 2412-2432,2462,5000-6000 + */ + pos = value; + while (pos && pos[0]) { + n = os_realloc_array(freq, count + 1, + sizeof(struct wpa_freq_range)); + if (n == NULL) { + os_free(freq); + return -1; + } + freq = n; + freq[count].min = atoi(pos); + pos2 = os_strchr(pos, '-'); + pos3 = os_strchr(pos, ','); + if (pos2 && (!pos3 || pos2 < pos3)) { + pos2++; + freq[count].max = atoi(pos2); + } else + freq[count].max = freq[count].min; + pos = pos3; + if (pos) + pos++; + count++; + } + + os_free(res->range); + res->range = freq; + res->num = count; + + return 0; +} + + +int freq_range_list_includes(const struct wpa_freq_range_list *list, + unsigned int freq) +{ + unsigned int i; + + if (list == NULL) + return 0; + + for (i = 0; i < list->num; i++) { + if (freq >= list->range[i].min && freq <= list->range[i].max) + return 1; + } + + return 0; +} + + +char * freq_range_list_str(const struct wpa_freq_range_list *list) +{ + char *buf, *pos, *end; + size_t maxlen; + unsigned int i; + int res; + + if (list->num == 0) + return NULL; + + maxlen = list->num * 30; + buf = os_malloc(maxlen); + if (buf == NULL) + return NULL; + pos = buf; + end = buf + maxlen; + + for (i = 0; i < list->num; i++) { + struct wpa_freq_range *range = &list->range[i]; + + if (range->min == range->max) + res = os_snprintf(pos, end - pos, "%s%u", + i == 0 ? "" : ",", range->min); + else + res = os_snprintf(pos, end - pos, "%s%u-%u", + i == 0 ? "" : ",", + range->min, range->max); + if (os_snprintf_error(end - pos, res)) { + os_free(buf); + return NULL; + } + pos += res; + } + + return buf; +} + + +int int_array_len(const int *a) +{ + int i; + for (i = 0; a && a[i]; i++) + ; + return i; +} + + +void int_array_concat(int **res, const int *a) +{ + int reslen, alen, i; + int *n; + + reslen = int_array_len(*res); + alen = int_array_len(a); + + n = os_realloc_array(*res, reslen + alen + 1, sizeof(int)); + if (n == NULL) { + os_free(*res); + *res = NULL; + return; + } + for (i = 0; i <= alen; i++) + n[reslen + i] = a[i]; + *res = n; +} + + +static int freq_cmp(const void *a, const void *b) +{ + int _a = *(int *) a; + int _b = *(int *) b; + + if (_a == 0) + return 1; + if (_b == 0) + return -1; + return _a - _b; +} + + +void int_array_sort_unique(int *a) +{ + int alen; + int i, j; + + if (a == NULL) + return; + + alen = int_array_len(a); + qsort(a, alen, sizeof(int), freq_cmp); + + i = 0; + j = 1; + while (a[i] && a[j]) { + if (a[i] == a[j]) { + j++; + continue; + } + a[++i] = a[j++]; + } + if (a[i]) + i++; + a[i] = 0; +} + + +void int_array_add_unique(int **res, int a) +{ + int reslen; + int *n; + + for (reslen = 0; *res && (*res)[reslen]; reslen++) { + if ((*res)[reslen] == a) + return; /* already in the list */ + } + + n = os_realloc_array(*res, reslen + 2, sizeof(int)); + if (n == NULL) { + os_free(*res); + *res = NULL; + return; + } + + n[reslen] = a; + n[reslen + 1] = 0; + + *res = n; +} + + +void str_clear_free(char *str) +{ + if (str) { + size_t len = os_strlen(str); + os_memset(str, 0, len); + os_free(str); + } +} + + +void bin_clear_free(void *bin, size_t len) +{ + if (bin) { + os_memset(bin, 0, len); + os_free(bin); + } +} + + +int random_mac_addr(u8 *addr) +{ + if (os_get_random(addr, ETH_ALEN) < 0) + return -1; + addr[0] &= 0xfe; /* unicast */ + addr[0] |= 0x02; /* locally administered */ + return 0; +} + + +int random_mac_addr_keep_oui(u8 *addr) +{ + if (os_get_random(addr + 3, 3) < 0) + return -1; + addr[0] &= 0xfe; /* unicast */ + addr[0] |= 0x02; /* locally administered */ + return 0; +} + + +/** + * cstr_token - Get next token from const char string + * @str: a constant string to tokenize + * @delim: a string of delimiters + * @last: a pointer to a character following the returned token + * It has to be set to NULL for the first call and passed for any + * futher call. + * Returns: a pointer to token position in str or NULL + * + * This function is similar to str_token, but it can be used with both + * char and const char strings. Differences: + * - The str buffer remains unmodified + * - The returned token is not a NULL terminated string, but a token + * position in str buffer. If a return value is not NULL a size + * of the returned token could be calculated as (last - token). + */ +const char * cstr_token(const char *str, const char *delim, const char **last) +{ + const char *end, *token = str; + + if (!str || !delim || !last) + return NULL; + + if (*last) + token = *last; + + while (*token && os_strchr(delim, *token)) + token++; + + if (!*token) + return NULL; + + end = token + 1; + + while (*end && !os_strchr(delim, *end)) + end++; + + *last = end; + return token; +} + + +/** + * str_token - Get next token from a string + * @buf: String to tokenize. Note that the string might be modified. + * @delim: String of delimiters + * @context: Pointer to save our context. Should be initialized with + * NULL on the first call, and passed for any further call. + * Returns: The next token, NULL if there are no more valid tokens. + */ +char * str_token(char *str, const char *delim, char **context) +{ + char *token = (char *) cstr_token(str, delim, (const char **) context); + + if (token && **context) + *(*context)++ = '\0'; + + return token; +} + + +size_t utf8_unescape(const char *inp, size_t in_size, + char *outp, size_t out_size) +{ + size_t res_size = 0; + + if (!inp || !outp) + return 0; + + if (!in_size) + in_size = os_strlen(inp); + + /* Advance past leading single quote */ + if (*inp == '\'' && in_size) { + inp++; + in_size--; + } + + while (in_size--) { + if (res_size >= out_size) + return 0; + + switch (*inp) { + case '\'': + /* Terminate on bare single quote */ + *outp = '\0'; + return res_size; + + case '\\': + if (!in_size--) + return 0; + inp++; + /* fall through */ + + default: + *outp++ = *inp++; + res_size++; + } + } + + /* NUL terminate if space allows */ + if (res_size < out_size) + *outp = '\0'; + + return res_size; +} + + +size_t utf8_escape(const char *inp, size_t in_size, + char *outp, size_t out_size) +{ + size_t res_size = 0; + + if (!inp || !outp) + return 0; + + /* inp may or may not be NUL terminated, but must be if 0 size + * is specified */ + if (!in_size) + in_size = os_strlen(inp); + + while (in_size--) { + if (res_size++ >= out_size) + return 0; + + switch (*inp) { + case '\\': + case '\'': + if (res_size++ >= out_size) + return 0; + *outp++ = '\\'; + /* fall through */ + + default: + *outp++ = *inp++; + break; + } + } + + /* NUL terminate if space allows */ + if (res_size < out_size) + *outp = '\0'; + + return res_size; +} + + +int is_ctrl_char(char c) +{ + return c > 0 && c < 32; +} diff --git a/beken_os/beken378/func/hostapd-2.5/src/utils/common.h b/beken_os/beken378/func/hostapd-2.5/src/utils/common.h new file mode 100755 index 0000000..69ca904 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/utils/common.h @@ -0,0 +1,482 @@ +/* + * wpa_supplicant/hostapd / common helper functions, etc. + * Copyright (c) 2002-2007, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef COMMON_H +#define COMMON_H + +#include "os.h" +#include "include.h" +#include "includes.h" + +#define __BYTE_ORDER __LITTLE_ENDIAN + +#if defined(__linux__) || defined(__GLIBC__) +#include +#include +#endif /* __linux__ */ + +#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || \ + defined(__OpenBSD__) +#include +#include +#define __BYTE_ORDER _BYTE_ORDER +#define __LITTLE_ENDIAN _LITTLE_ENDIAN +#define __BIG_ENDIAN _BIG_ENDIAN + +#define bswap_16 bswap16 +#define bswap_32 bswap32 +#define bswap_64 bswap64 +#endif /* defined(__FreeBSD__) || defined(__NetBSD__) || + * defined(__DragonFly__) || defined(__OpenBSD__) */ + + +/* Define platform specific integer types */ + +#ifndef WPA_TYPES_DEFINED + +#ifdef CONFIG_USE_INTTYPES_H +#include +#else +#include +#endif + +#define WPA_TYPES_DEFINED +#endif /* !WPA_TYPES_DEFINED */ + +/* Define platform specific byte swapping macros */ + +#if defined(__CYGWIN__) || defined(CONFIG_NATIVE_WINDOWS) + +static inline unsigned short wpa_swap_16(unsigned short v) +{ + return ((v & 0xff) << 8) | (v >> 8); +} + +static inline unsigned int wpa_swap_32(unsigned int v) +{ + return ((v & 0xff) << 24) | ((v & 0xff00) << 8) | + ((v & 0xff0000) >> 8) | (v >> 24); +} + +#define le_to_host16(n) (n) +#define host_to_le16(n) (n) +#define be_to_host16(n) wpa_swap_16(n) +#define host_to_be16(n) wpa_swap_16(n) +#define le_to_host32(n) (n) +#define host_to_le32(n) (n) +#define be_to_host32(n) wpa_swap_32(n) +#define host_to_be32(n) wpa_swap_32(n) + +#define WPA_BYTE_SWAP_DEFINED + +#endif /* __CYGWIN__ || CONFIG_NATIVE_WINDOWS */ + + +#ifndef bswap_16 +#define bswap_16(a) ((((u16) (a) << 8) & 0xff00) | (((u16) (a) >> 8) & 0xff)) +#endif + +#ifndef bswap_32 +#define bswap_32(a) ((((u32) (a) << 24) & 0xff000000) | \ + (((u32) (a) << 8) & 0xff0000) | \ + (((u32) (a) >> 8) & 0xff00) | \ + (((u32) (a) >> 24) & 0xff)) +#endif + +#ifndef WPA_BYTE_SWAP_DEFINED + +#ifndef __BYTE_ORDER +#ifndef __LITTLE_ENDIAN +#ifndef __BIG_ENDIAN +#define __LITTLE_ENDIAN 1234 +#define __BIG_ENDIAN 4321 +#endif /* __BIG_ENDIAN */ +#endif /* __LITTLE_ENDIAN */ +#endif /* __BYTE_ORDER */ + +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define le_to_host16(n) ((__force u16) (le16) (n)) +#define host_to_le16(n) ((__force le16) (u16) (n)) +#define be_to_host16(n) bswap_16((__force u16) (be16) (n)) +#define host_to_be16(n) ((__force be16) bswap_16((n))) +#define le_to_host32(n) ((__force u32) (le32) (n)) +#define host_to_le32(n) ((__force le32) (u32) (n)) +#define be_to_host32(n) bswap_32((__force u32) (be32) (n)) +#define host_to_be32(n) ((__force be32) bswap_32((n))) +#define le_to_host64(n) ((__force u64) (le64) (n)) +#define host_to_le64(n) ((__force le64) (u64) (n)) +#define be_to_host64(n) bswap_64((__force u64) (be64) (n)) +#define host_to_be64(n) ((__force be64) bswap_64((n))) +#elif __BYTE_ORDER == __BIG_ENDIAN +#define le_to_host16(n) bswap_16(n) +#define host_to_le16(n) bswap_16(n) +#define be_to_host16(n) (n) +#define host_to_be16(n) (n) +#define le_to_host32(n) bswap_32(n) +#define host_to_le32(n) bswap_32(n) +#define be_to_host32(n) (n) +#define host_to_be32(n) (n) +#define le_to_host64(n) bswap_64(n) +#define host_to_le64(n) bswap_64(n) +#define be_to_host64(n) (n) +#define host_to_be64(n) (n) + +#ifndef WORDS_BIGENDIAN +#define WORDS_BIGENDIAN +#endif + +#else +#error Could not determine CPU byte order +#endif + +#define WPA_BYTE_SWAP_DEFINED +#endif /* !WPA_BYTE_SWAP_DEFINED */ + + +/* Macros for handling unaligned memory accesses */ + +static inline u16 WPA_GET_BE16(const u8 *a) +{ + return (a[0] << 8) | a[1]; +} + +static inline void WPA_PUT_BE16(u8 *a, u16 val) +{ + a[0] = val >> 8; + a[1] = val & 0xff; +} + +static inline u16 WPA_GET_LE16(const u8 *a) +{ + return (a[1] << 8) | a[0]; +} + +static inline void WPA_PUT_LE16(u8 *a, u16 val) +{ + a[1] = val >> 8; + a[0] = val & 0xff; +} + +static inline u32 WPA_GET_BE24(const u8 *a) +{ + return (a[0] << 16) | (a[1] << 8) | a[2]; +} + +static inline void WPA_PUT_BE24(u8 *a, u32 val) +{ + a[0] = (val >> 16) & 0xff; + a[1] = (val >> 8) & 0xff; + a[2] = val & 0xff; +} + +static inline u32 WPA_GET_BE32(const u8 *a) +{ + return ((u32) a[0] << 24) | (a[1] << 16) | (a[2] << 8) | a[3]; +} + +static inline void WPA_PUT_BE32(u8 *a, u32 val) +{ + a[0] = (val >> 24) & 0xff; + a[1] = (val >> 16) & 0xff; + a[2] = (val >> 8) & 0xff; + a[3] = val & 0xff; +} + +static inline u32 WPA_GET_LE32(const u8 *a) +{ + return ((u32) a[3] << 24) | (a[2] << 16) | (a[1] << 8) | a[0]; +} + +static inline void WPA_PUT_LE32(u8 *a, u32 val) +{ + a[3] = (val >> 24) & 0xff; + a[2] = (val >> 16) & 0xff; + a[1] = (val >> 8) & 0xff; + a[0] = val & 0xff; +} + +static inline u64 WPA_GET_BE64(const u8 *a) +{ + return (((u64) a[0]) << 56) | (((u64) a[1]) << 48) | + (((u64) a[2]) << 40) | (((u64) a[3]) << 32) | + (((u64) a[4]) << 24) | (((u64) a[5]) << 16) | + (((u64) a[6]) << 8) | ((u64) a[7]); +} + +static inline void WPA_PUT_BE64(u8 *a, u64 val) +{ + a[0] = val >> 56; + a[1] = val >> 48; + a[2] = val >> 40; + a[3] = val >> 32; + a[4] = val >> 24; + a[5] = val >> 16; + a[6] = val >> 8; + a[7] = val & 0xff; +} + +static inline u64 WPA_GET_LE64(const u8 *a) +{ + return (((u64) a[7]) << 56) | (((u64) a[6]) << 48) | + (((u64) a[5]) << 40) | (((u64) a[4]) << 32) | + (((u64) a[3]) << 24) | (((u64) a[2]) << 16) | + (((u64) a[1]) << 8) | ((u64) a[0]); +} + +static inline void WPA_PUT_LE64(u8 *a, u64 val) +{ + a[7] = val >> 56; + a[6] = val >> 48; + a[5] = val >> 40; + a[4] = val >> 32; + a[3] = val >> 24; + a[2] = val >> 16; + a[1] = val >> 8; + a[0] = val & 0xff; +} + + +#ifndef ETH_ALEN +#define ETH_ALEN 6 +#endif +#ifndef ETH_HLEN +#define ETH_HLEN 14 +#endif +#ifndef IFNAMSIZ +#define IFNAMSIZ 16 +#endif +#ifndef ETH_P_ALL +#define ETH_P_ALL 0x0003 +#endif +#ifndef ETH_P_80211_ENCAP +#define ETH_P_80211_ENCAP 0x890d /* TDLS comes under this category */ +#endif +#ifndef ETH_P_PAE +#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ +#endif /* ETH_P_PAE */ +#ifndef ETH_P_EAPOL +#define ETH_P_EAPOL ETH_P_PAE +#endif /* ETH_P_EAPOL */ +#ifndef ETH_P_RSN_PREAUTH +#define ETH_P_RSN_PREAUTH 0x88c7 +#endif /* ETH_P_RSN_PREAUTH */ +#ifndef ETH_P_RRB +#define ETH_P_RRB 0x890D +#endif /* ETH_P_RRB */ + +#define STRUCT_PACKED +#define GCC_PACKED __attribute__ ((packed)) +#define PRINTF_FORMAT(a,b) + +#ifdef CONFIG_ANSI_C_EXTRA + +#if !defined(_MSC_VER) || _MSC_VER < 1400 +/* snprintf - used in number of places; sprintf() is _not_ a good replacement + * due to possible buffer overflow; see, e.g., + * http://www.ijs.si/software/snprintf/ for portable implementation of + * snprintf. */ +int snprintf(char *str, size_t size, const char *format, ...); + +/* vsnprintf - only used for wpa_msg() in wpa_supplicant.c */ +int vsnprintf(char *str, size_t size, const char *format, va_list ap); +#endif /* !defined(_MSC_VER) || _MSC_VER < 1400 */ + +/* getopt - only used in main.c */ +int getopt(int argc, char *const argv[], const char *optstring); +extern char *optarg; +extern int optind; + +#ifndef CONFIG_NO_SOCKLEN_T_TYPEDEF +#ifndef __socklen_t_defined +typedef int socklen_t; +#endif +#endif + +/* inline - define as __inline or just define it to be empty, if needed */ +#ifdef CONFIG_NO_INLINE +#define inline +#else +#define inline __inline +#endif + +#ifndef __func__ +#define __func__ "__func__ not defined" +#endif + +#ifndef MSG_DONTWAIT +#define MSG_DONTWAIT 0 +#endif + +#ifdef _WIN32_WCE +void perror(const char *s); +#endif /* _WIN32_WCE */ + +#endif /* CONFIG_ANSI_C_EXTRA */ + +#ifndef MAC2STR +#define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5] +#define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x " + +/* + * Compact form for string representation of MAC address + * To be used, e.g., for constructing dbus paths for P2P Devices + */ +#define COMPACT_MACSTR "%02x%02x%02x%02x%02x%02x" +#endif + +#ifndef BIT +#define BIT(x) (1U << (x)) +#endif + +/* + * Definitions for sparse validation + * (http://kernel.org/pub/linux/kernel/people/josh/sparse/) + */ +#ifdef __CHECKER__ +#define __force __attribute__((force)) +#define __bitwise __attribute__((bitwise)) +#else +#define __force +#define __bitwise +#endif + +typedef u16 __bitwise be16; +typedef u16 __bitwise le16; +typedef u32 __bitwise be32; +typedef u32 __bitwise le32; +typedef u64 __bitwise be64; +typedef u64 __bitwise le64; + +#ifndef __must_check +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) +#define __must_check __attribute__((__warn_unused_result__)) +#else +#define __must_check +#endif /* __GNUC__ */ +#endif /* __must_check */ + +#ifndef __maybe_unused +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) +#define __maybe_unused __attribute__((unused)) +#else +#define __maybe_unused +#endif /* __GNUC__ */ +#endif /* __must_check */ + +int hwaddr_aton(const char *txt, u8 *addr); +int hwaddr_masked_aton(const char *txt, u8 *addr, u8 *mask, u8 maskable); +int hwaddr_compact_aton(const char *txt, u8 *addr); +int hwaddr_aton2(const char *txt, u8 *addr); +int hex2byte(const char *hex); +int hexstr2bin(const char *hex, u8 *buf, size_t len); +void inc_byte_array(u8 *counter, size_t len); +void wpa_get_ntp_timestamp(u8 *buf); +int wpa_scnprintf(char *buf, size_t size, const char *fmt, ...); +int wpa_snprintf_hex_sep(char *buf, size_t buf_size, const u8 *data, size_t len, + char sep); +int wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len); +int wpa_snprintf_hex_uppercase(char *buf, size_t buf_size, const u8 *data, + size_t len); + +int hwaddr_mask_txt(char *buf, size_t len, const u8 *addr, const u8 *mask); + +#ifdef CONFIG_NATIVE_WINDOWS +void wpa_unicode2ascii_inplace(TCHAR *str); +TCHAR * wpa_strdup_tchar(const char *str); +#else /* CONFIG_NATIVE_WINDOWS */ +#define wpa_unicode2ascii_inplace(s) do { } while (0) +#define wpa_strdup_tchar(s) strdup((s)) +#endif /* CONFIG_NATIVE_WINDOWS */ + +void printf_encode(char *txt, size_t maxlen, const u8 *data, size_t len); +size_t printf_decode(u8 *buf, size_t maxlen, const char *str); + +const char * wpa_ssid_txt(const u8 *ssid, size_t ssid_len); + +char * wpa_config_parse_string(const char *value, size_t *len); +int is_hex(const u8 *data, size_t len); +size_t merge_byte_arrays(u8 *res, size_t res_len, + const u8 *src1, size_t src1_len, + const u8 *src2, size_t src2_len); +char * dup_binstr(const void *src, size_t len); + +static inline int is_zero_ether_addr(const u8 *a) +{ + return !(a[0] | a[1] | a[2] | a[3] | a[4] | a[5]); +} + +static inline int is_broadcast_ether_addr(const u8 *a) +{ + return (a[0] & a[1] & a[2] & a[3] & a[4] & a[5]) == 0xff; +} + +static inline int is_multicast_ether_addr(const u8 *a) +{ + return a[0] & 0x01; +} + +#define broadcast_ether_addr (const u8 *) "\xff\xff\xff\xff\xff\xff" + +#include "wpa_debug.h" + + +struct wpa_freq_range_list { + struct wpa_freq_range { + unsigned int min; + unsigned int max; + } *range; + unsigned int num; +}; + +int freq_range_list_parse(struct wpa_freq_range_list *res, const char *value); +int freq_range_list_includes(const struct wpa_freq_range_list *list, + unsigned int freq); +char * freq_range_list_str(const struct wpa_freq_range_list *list); + +int int_array_len(const int *a); +void int_array_concat(int **res, const int *a); +void int_array_sort_unique(int *a); +void int_array_add_unique(int **res, int a); + +#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) + +void str_clear_free(char *str); +void bin_clear_free(void *bin, size_t len); + +int random_mac_addr(u8 *addr); +int random_mac_addr_keep_oui(u8 *addr); + +const char * cstr_token(const char *str, const char *delim, const char **last); +char * str_token(char *str, const char *delim, char **context); +size_t utf8_escape(const char *inp, size_t in_size, + char *outp, size_t out_size); +size_t utf8_unescape(const char *inp, size_t in_size, + char *outp, size_t out_size); +int is_ctrl_char(char c); + + +/* + * gcc 4.4 ends up generating strict-aliasing warnings about some very common + * networking socket uses that do not really result in a real problem and + * cannot be easily avoided with union-based type-punning due to struct + * definitions including another struct in system header files. To avoid having + * to fully disable strict-aliasing warnings, provide a mechanism to hide the + * typecast from aliasing for now. A cleaner solution will hopefully be found + * in the future to handle these cases. + */ +void * __hide_aliasing_typecast(void *foo); +#define aliasing_hide_typecast(a,t) (t *) __hide_aliasing_typecast((a)) + +#ifdef CONFIG_VALGRIND +#include +#define WPA_MEM_DEFINED(ptr, len) VALGRIND_MAKE_MEM_DEFINED((ptr), (len)) +#else /* CONFIG_VALGRIND */ +#define WPA_MEM_DEFINED(ptr, len) do { } while (0) +#endif /* CONFIG_VALGRIND */ + +#endif /* COMMON_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/utils/eloop.c b/beken_os/beken378/func/hostapd-2.5/src/utils/eloop.c new file mode 100755 index 0000000..08e88b8 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/utils/eloop.c @@ -0,0 +1,801 @@ +/* + * Event loop based on select() loop + * Copyright (c) 2002-2009, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ +#include "include.h" +#include "fake_clock_pub.h" +#include "uart_pub.h" +#include "includes.h" +#include "common.h" +#include "trace.h" +#include "eloop.h" +#include "signal.h" +#include "errno-base.h" +#include "sk_intf.h" +#include "main_none.h" +#include "mac.h" +#include "rtos_error.h" +#include "rtos_pub.h" +#include "rw_pub.h" + +static struct eloop_data eloop; + +int eloop_get_signal_count(void) +{ + return eloop.signal_count; +} + +int eloop_init(void) +{ + os_memset(&eloop, 0, sizeof(eloop)); + dl_list_init(&eloop.timeout); + + eloop.exceptions.count = 1; + + return 0; +} + +static int eloop_sock_table_add_sock(struct eloop_sock_table *table, + int sock, eloop_sock_handler handler, + void *eloop_data, void *user_data) +{ + struct eloop_sock *tmp; + int new_max_sock; + + if (sock > eloop.max_sock) + new_max_sock = sock; + else + new_max_sock = eloop.max_sock; + + if (table == NULL) + return -1; + + eloop_trace_sock_remove_ref(table); + tmp = os_realloc_array(table->table, table->count + 1, + sizeof(struct eloop_sock)); + if (tmp == NULL) { + eloop_trace_sock_add_ref(table); + return -1; + } + + tmp[table->count].sock = sock; + tmp[table->count].eloop_data = eloop_data; + tmp[table->count].user_data = user_data; + tmp[table->count].handler = handler; + wpa_trace_record(&tmp[table->count]); + + table->count++; + table->table = tmp; + eloop.max_sock = new_max_sock; + eloop.count++; + table->changed = 1; + eloop_trace_sock_add_ref(table); + + return 0; +} + + +static void eloop_sock_table_remove_sock(struct eloop_sock_table *table, + int sock) +{ + int i; + + if (table == NULL || table->table == NULL || table->count == 0) + return; + + for (i = 0; i < table->count; i++) { + if (table->table[i].sock == sock) + break; + } + if (i == table->count) + return; + eloop_trace_sock_remove_ref(table); + if (i != table->count - 1) { + os_memmove(&table->table[i], &table->table[i + 1], + (table->count - i - 1) * + sizeof(struct eloop_sock)); + } + table->count--; + eloop.count--; + table->changed = 1; + eloop_trace_sock_add_ref(table); + + return; +} + +static void eloop_sock_table_destroy(struct eloop_sock_table *table) +{ + if (table) { + int i; + for (i = 0; i < table->count && table->table; i++) { + wpa_printf(MSG_INFO, "ELOOP: remaining socket: " + "sock=%d eloop_data=%p user_data=%p " + "handler=%p", + table->table[i].sock, + table->table[i].eloop_data, + table->table[i].user_data, + table->table[i].handler); + wpa_trace_dump_funcname("eloop unregistered socket " + "handler", + table->table[i].handler); + wpa_trace_dump("eloop sock", &table->table[i]); + } + + os_free(table->table); + } +} + + +int eloop_register_read_sock(int sock, eloop_sock_handler handler, + void *eloop_data, void *user_data) +{ + return eloop_register_sock(sock, EVENT_TYPE_READ, handler, + eloop_data, user_data); +} + + +void eloop_unregister_read_sock(int sock) +{ + eloop_unregister_sock(sock, EVENT_TYPE_READ); +} + + +static struct eloop_sock_table *eloop_get_sock_table(eloop_event_type type) +{ + switch (type) { + case EVENT_TYPE_READ: + return &eloop.readers; + case EVENT_TYPE_WRITE: + return &eloop.writers; + case EVENT_TYPE_EXCEPTION: + return &eloop.exceptions; + } + + return NULL; +} + + +int eloop_register_sock(int sock, eloop_event_type type, + eloop_sock_handler handler, + void *eloop_data, void *user_data) +{ + struct eloop_sock_table *table; + + assert(sock >= 0); + table = eloop_get_sock_table(type); + return eloop_sock_table_add_sock(table, sock, handler, + eloop_data, user_data); +} + + +void eloop_unregister_sock(int sock, eloop_event_type type) +{ + struct eloop_sock_table *table; + + table = eloop_get_sock_table(type); + eloop_sock_table_remove_sock(table, sock); +} + + +int eloop_register_timeout(unsigned int secs, + unsigned int usecs, + eloop_timeout_handler handler, + void *eloop_data, + void *user_data) +{ + os_time_t now_sec; + struct eloop_timeout *timeout, *tmp; + + ASSERT(handler); + + timeout = os_zalloc(sizeof(*timeout)); + if (timeout == NULL) + { + os_printf("------------eloop_register_malloc_failed\r\n"); + return -1; + } + + if (os_get_reltime(&timeout->time) < 0) + { + os_free(timeout); + os_printf("------------os_get_reltimeErr\r\n"); + return -1; + } + + now_sec = timeout->time.sec; + timeout->time.sec += secs; + if (timeout->time.sec < now_sec) { + /* + * Integer overflow - assume long enough timeout to be assumed + * to be infinite, i.e., the timeout would never happen. + */ + os_printf("------------ELOOP: Too long timeout\r\n"); + os_free(timeout); + return 0; + } + + timeout->time.usec += usecs; + while (timeout->time.usec >= 1000000) { + timeout->time.sec++; + timeout->time.usec -= 1000000; + } + timeout->eloop_data = eloop_data; + timeout->user_data = user_data; + timeout->handler = handler; + + dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) { + if (os_reltime_before(&timeout->time, &tmp->time)) { + dl_list_add(tmp->list.prev, &timeout->list); + return 0; + } + } + dl_list_add_tail(&eloop.timeout, &timeout->list); + + return 0; +} + +void eloop_remove_timeout(struct eloop_timeout *timeout) +{ + dl_list_del(&timeout->list); + os_free(timeout); +} + +int eloop_cancel_timeout(eloop_timeout_handler handler, + void *eloop_data, void *user_data) +{ + struct eloop_timeout *timeout, *prev; + int removed = 0; + + dl_list_for_each_safe(timeout, prev, &eloop.timeout, + struct eloop_timeout, list) + { + if (timeout->handler == handler && + (timeout->eloop_data == eloop_data || + eloop_data == ELOOP_ALL_CTX) && + (timeout->user_data == user_data || + user_data == ELOOP_ALL_CTX)) + { + eloop_remove_timeout(timeout); + removed++; + } + } + + return removed; +} + + +int eloop_cancel_timeout_one(eloop_timeout_handler handler, + void *eloop_data, void *user_data, + struct os_reltime *remaining) +{ + struct eloop_timeout *timeout, *prev; + int removed = 0; + struct os_reltime now; + + os_get_reltime(&now); + remaining->sec = remaining->usec = 0; + + dl_list_for_each_safe(timeout, prev, &eloop.timeout, + struct eloop_timeout, list){ + if (timeout->handler == handler && + (timeout->eloop_data == eloop_data) && + (timeout->user_data == user_data)) { + removed = 1; + if (os_reltime_before(&now, &timeout->time)) + os_reltime_sub(&timeout->time, &now, remaining); + eloop_remove_timeout(timeout); + break; + } + } + + return removed; +} + +int eloop_is_timeout_registered(eloop_timeout_handler handler, + void *eloop_data, void *user_data) +{ + struct eloop_timeout *tmp; + + dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) + { + if (tmp->handler == handler + && tmp->eloop_data == eloop_data + && tmp->user_data == user_data) + { + return 1; + } + } + + return 0; +} + +int eloop_deplete_timeout(unsigned int req_secs, unsigned int req_usecs, + eloop_timeout_handler handler, void *eloop_data, + void *user_data) +{ + struct os_reltime now, requested, remaining; + struct eloop_timeout *tmp; + + dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) { + if (tmp->handler == handler && + tmp->eloop_data == eloop_data && + tmp->user_data == user_data) { + requested.sec = req_secs; + requested.usec = req_usecs; + os_get_reltime(&now); + os_reltime_sub(&tmp->time, &now, &remaining); + if (os_reltime_before(&requested, &remaining)) { + eloop_cancel_timeout(handler, eloop_data, + user_data); + eloop_register_timeout(requested.sec, + requested.usec, + handler, eloop_data, + user_data); + return 1; + } + return 0; + } + } + + return -1; +} + +int eloop_replenish_timeout(unsigned int req_secs, + unsigned int req_usecs, + eloop_timeout_handler handler, + void *eloop_data, + void *user_data) +{ + struct os_reltime now, requested, remaining; + struct eloop_timeout *tmp; + + dl_list_for_each(tmp, &eloop.timeout, struct eloop_timeout, list) { + if (tmp->handler == handler && + tmp->eloop_data == eloop_data && + tmp->user_data == user_data) { + requested.sec = req_secs; + requested.usec = req_usecs; + os_get_reltime(&now); + os_reltime_sub(&tmp->time, &now, &remaining); + if (os_reltime_before(&remaining, &requested)) { + eloop_cancel_timeout(handler, eloop_data, + user_data); + eloop_register_timeout(requested.sec, + requested.usec, + handler, eloop_data, + user_data); + return 1; + } + return 0; + } + } + + return -1; +} + +static void eloop_handle_alarm(int sig) +{ + wpa_printf(MSG_ERROR, "eloop: could not process SIGINT or SIGTERM in " + "two seconds. Looks like there\n" + "is a bug that ends up in a busy loop that " + "prevents clean shutdown.\n" + "Killing program forcefully.\n"); +} + +void eloop_handle_signal(int sig) +{ + int i; + GLOBAL_INT_DECLARATION(); + +#ifndef CONFIG_NATIVE_WINDOWS + if ((sig == SIGINT || sig == SIGTERM) && !eloop.pending_terminate) { + /* Use SIGALRM to break out from potential busy loops that + * would not allow the program to be killed. */ + eloop.pending_terminate = 1; + bk_signal(SIGALRM, eloop_handle_alarm); + bk_alarm(2); + } +#endif /* CONFIG_NATIVE_WINDOWS */ + + GLOBAL_INT_DISABLE(); + eloop.signaled++; + for (i = 0; i < eloop.signal_count; i++) { + if (eloop.signals[i].sig == sig) { + eloop.signals[i].signaled++; + break; + } + } + GLOBAL_INT_RESTORE(); +} + +int eloop_signal_is_registered(int sig) +{ + int i; + int hit_flag = 0; + GLOBAL_INT_DECLARATION(); + + GLOBAL_INT_DISABLE(); + for (i = 0; i < eloop.signal_count; i++) { + if (sig == eloop.signals[i].sig) { + hit_flag = 1; + break; + } + } + GLOBAL_INT_RESTORE(); + + return hit_flag; +} + +static void eloop_process_pending_signals(void) +{ + int i,sig; + int sig_count; + void *user_data; + eloop_signal_handler handler; + GLOBAL_INT_DECLARATION(); + + GLOBAL_INT_DISABLE(); + if (eloop.signaled == 0) + { + GLOBAL_INT_RESTORE(); + return; + } + eloop.signaled = 0; + sig_count = eloop.signal_count; + + if (eloop.pending_terminate) { +#ifndef CONFIG_NATIVE_WINDOWS + bk_alarm(0); +#endif /* CONFIG_NATIVE_WINDOWS */ + eloop.pending_terminate = 0; + } + GLOBAL_INT_RESTORE(); + + for (i = 0; i < sig_count; i++) { + GLOBAL_INT_DISABLE(); + if (eloop.signals[i].signaled) { + eloop.signals[i].signaled = 0; + + handler = eloop.signals[i].handler; + sig = eloop.signals[i].sig; + user_data = eloop.signals[i].user_data; + ASSERT(handler); + GLOBAL_INT_RESTORE(); + + handler(sig,user_data); + }else{ + GLOBAL_INT_RESTORE(); + } + } +} + +int eloop_register_signal(int sig, eloop_signal_handler handler, + void *user_data) +{ + struct eloop_signal *tmp; + GLOBAL_INT_DECLARATION(); + + if(eloop_signal_is_registered(sig)) + { + return 0; + } + + GLOBAL_INT_DISABLE(); + tmp = os_realloc_array(eloop.signals, eloop.signal_count + 1, + sizeof(struct eloop_signal)); + if (tmp == NULL) + { + GLOBAL_INT_RESTORE(); + return -1; + } + + tmp[eloop.signal_count].sig = sig; + tmp[eloop.signal_count].user_data = user_data; + tmp[eloop.signal_count].handler = handler; + tmp[eloop.signal_count].signaled = 0; + + eloop.signal_count++; + eloop.signals = tmp; + GLOBAL_INT_RESTORE(); + + return 0; +} + +static void eloop_signals_remove_signal(int sig) +{ + int i; + GLOBAL_INT_DECLARATION(); + + if (eloop.signals == NULL || eloop.signal_count == 0) + return; + + for (i = 0; i < eloop.signal_count; i++) { + if (eloop.signals[i].sig == sig) + break; + } + if (i == eloop.signal_count) + return; + + GLOBAL_INT_DISABLE(); + if (i != eloop.signal_count - 1) { + os_memmove(&eloop.signals[i], &eloop.signals[i+1], + (eloop.signal_count - i - 1) * + sizeof(struct eloop_signal)); + } + eloop.signal_count--; + GLOBAL_INT_RESTORE(); + + return; +} + +int eloop_register_signal_terminate(eloop_signal_handler handler, + void *user_data) +{ + int ret = eloop_register_signal(SIGINT, handler, user_data); + if (ret == 0) + ret = eloop_register_signal(SIGTERM, handler, user_data); + return ret; +} + +int eloop_register_signal_reconfig(eloop_signal_handler handler, + void *user_data) +{ + return eloop_register_signal(SIGHUP, handler, user_data); +} + +void eloop_remove_sta_added_signals(void) +{ + eloop_signals_remove_signal(SIGINT); + eloop_signals_remove_signal(SIGTERM); + eloop_signals_remove_signal(SIGHUP); + eloop_signals_remove_signal(SIGSCAN); + eloop_signals_remove_signal(SIGASSOC); + eloop_signals_remove_signal(SIGDISASSOC); + eloop_signals_remove_signal(SIGDEAUTH); + eloop_signals_remove_signal(SIGCSA); +} + +void eloop_reader_dispatch(int sk) +{ + int i; + void *eloop_data = 0; + void *user_data = 0; + eloop_sock_handler handler; + + handler = 0; + for(i = 0; i < eloop.readers.count; i ++) + { + if(sk == eloop.readers.table[i].sock) + { + handler = eloop.readers.table[i].handler; + eloop_data = eloop.readers.table[i].eloop_data; + user_data = eloop.readers.table[i].user_data; + + break; + } + } + + if(handler) + { + handler(sk, eloop_data, user_data); // handle_read + } +} + +void eloop_handler_sock_event(int flag) +{ + int sk; + + // invild vif indx + if(flag == 0xff) + return; + + if(ws_mgmt_peek_rxed_next_payload_size(flag)) + { + sk = mgmt_get_socket_num(flag); + eloop_reader_dispatch(sk); + } + + if (ws_data_peek_rxed_next_payload_size(flag)) + { + sk = data_get_socket_num(flag); + eloop_reader_dispatch(sk); + } +} + +void eloop_timeout_run(void) +{ + struct os_reltime now; + + if (!eloop.terminate + && (!dl_list_empty(&eloop.timeout))) { + struct eloop_timeout *timeout, *prv; + + /* check if some registered timeouts have occurred */ + dl_list_for_each_safe(timeout, prv, &eloop.timeout, struct eloop_timeout, list) + { + os_get_reltime(&now); + if (!os_reltime_before(&now, &timeout->time)) { + void *eloop_data = timeout->eloop_data; + void *user_data = timeout->user_data; + eloop_timeout_handler handler = + timeout->handler; + + eloop_remove_timeout(timeout); + + handler(eloop_data, user_data); + }else{ + break; + } + } + } +} + +extern beken_queue_t wpah_queue; +extern int hostapd_is_exiting(void); +extern int hostapd_exit_handler(void); +extern int hostapd_exit_done(void); +extern int supplicant_is_exiting(void); +extern int supplicant_exit_handler(void); +extern int supplicant_exit_done(void); +void eloop_run(void) +{ + struct os_reltime tv, now; + int timeout_ms = BEKEN_WAIT_FOREVER; + WPAH_MSG_ST msg; + int ret, flag = 0xff; + + while(!eloop.terminate && + (!dl_list_empty(&eloop.timeout) || eloop.readers.count > 0 || + eloop.writers.count > 0 || eloop.exceptions.count > 0)) + { + struct eloop_timeout *timeout; + + timeout_ms = BEKEN_WAIT_FOREVER; + + if (eloop.pending_terminate) { + /* + * This may happen in some corner cases where a signal + * is received during a blocking operation. We need to + * process the pending signals and exit if requested to + * avoid hitting the SIGALRM limit if the blocking + * operation took more than two seconds. + */ + eloop_process_pending_signals(); + if (eloop.terminate) + break; + } + + if(hostapd_is_exiting()) + { + hostapd_exit_handler(); + hostapd_exit_done(); + } + + if(supplicant_is_exiting()) + { + supplicant_exit_handler(); + supplicant_exit_done(); + } + + timeout = dl_list_first(&eloop.timeout, struct eloop_timeout, + list); + if (timeout) { + os_get_reltime(&now); + if (os_reltime_before(&now, &timeout->time)) + os_reltime_sub(&timeout->time, &now, &tv); + else + tv.sec = tv.usec = 0; + timeout_ms = tv.sec * 1000 + tv.usec / 1000; + } + + if(wpah_queue) { + ret = rtos_pop_from_queue(&wpah_queue, &msg, timeout_ms); + if(kNoErr == ret) + { + flag = msg.argu; + } + } + + eloop_process_pending_signals(); + + /* check if some registered timeouts have occurred */ + timeout = dl_list_first(&eloop.timeout, struct eloop_timeout, + list); + if (timeout) { + os_get_reltime(&now); + if (!os_reltime_before(&now, &timeout->time)) { + void *eloop_data = timeout->eloop_data; + void *user_data = timeout->user_data; + eloop_timeout_handler handler = + timeout->handler; + eloop_remove_timeout(timeout); + handler(eloop_data, user_data); + } + } + + eloop_handler_sock_event(flag); + } + + eloop.terminate = 0; + + return; +} + +void eloop_terminate(void) +{ + eloop.terminate = 1; +} + +void eloop_destroy(void) +{ + struct eloop_timeout *timeout, *prev; + struct os_reltime now; + + os_get_reltime(&now); + dl_list_for_each_safe(timeout, prev, &eloop.timeout, + struct eloop_timeout, list) { + int sec, usec; + sec = timeout->time.sec - now.sec; + usec = timeout->time.usec - now.usec; + if (timeout->time.usec < now.usec) { + sec--; + usec += 1000000; + } + wpa_printf(MSG_INFO, "ELOOP: remaining timeout: %d.%06d " + "eloop_data=%p user_data=%p handler=%p", + sec, usec, timeout->eloop_data, timeout->user_data, + timeout->handler); + wpa_trace_dump_funcname("eloop unregistered timeout handler", + timeout->handler); + wpa_trace_dump("eloop timeout", timeout); + eloop_remove_timeout(timeout); + } + if(eloop.readers.count == 0) { + eloop_sock_table_destroy(&eloop.readers); + eloop.readers.table = NULL; + } + eloop_sock_table_destroy(&eloop.writers); + eloop_sock_table_destroy(&eloop.exceptions); + if(eloop.signal_count == 0) { + os_free(eloop.signals); + eloop.signals = NULL; + } + +#ifdef CONFIG_ELOOP_POLL + os_free(eloop.pollfds); + os_free(eloop.pollfds_map); +#endif /* CONFIG_ELOOP_POLL */ +#ifdef CONFIG_ELOOP_EPOLL + os_free(eloop.epoll_table); + os_free(eloop.epoll_events); + fsocket_close(eloop.epollfd); +#endif /* CONFIG_ELOOP_EPOLL */ +} + +void eloop_free_resource(void) +{ + if(eloop.readers.count == 0) { + eloop_sock_table_destroy(&eloop.readers); + eloop.readers.table = NULL; + } + eloop_sock_table_destroy(&eloop.writers); + eloop_sock_table_destroy(&eloop.exceptions); + if(eloop.signal_count == 0) { + os_free(eloop.signals); + eloop.signals = NULL; + } +} + +int eloop_terminated(void) +{ + return eloop.terminate || eloop.pending_terminate; +} + +void eloop_wait_for_read_sock(int sock) +{ +} +//eof + diff --git a/beken_os/beken378/func/hostapd-2.5/src/utils/eloop.h b/beken_os/beken378/func/hostapd-2.5/src/utils/eloop.h new file mode 100755 index 0000000..2c209d6 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/utils/eloop.h @@ -0,0 +1,449 @@ +/* + * Event loop + * Copyright (c) 2002-2006, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + * + * This file defines an event loop interface that supports processing events + * from registered timeouts (i.e., do something after N seconds), sockets + * (e.g., a new packet available for reading), and signals. eloop.c is an + * implementation of this interface using select() and sockets. This is + * suitable for most UNIX/POSIX systems. When porting to other operating + * systems, it may be necessary to replace that implementation with OS specific + * mechanisms. + */ + +#ifndef ELOOP_H +#define ELOOP_H + +#include "include.h" +#include "rtos_pub.h" + +#include "list.h" + +#define assert ASSERT + +//#define ELOOP_DEBUG + +#ifdef ELOOP_DEBUG +#define ELOOP_PRT os_printf +#define ELOOP_WPRT warning_prf +#else +#define ELOOP_PRT os_null_printf +#define ELOOP_WPRT warning_prf +#endif + + +#define eloop_trace_sock_add_ref(table) do { } while (0) +#define eloop_trace_sock_remove_ref(table) do { } while (0) + +/** + * ELOOP_ALL_CTX - eloop_cancel_timeout() magic number to match all timeouts + */ +#define ELOOP_ALL_CTX (void *) -1 + + +/** + * eloop_event_type - eloop socket event type for eloop_register_sock() + * @EVENT_TYPE_READ: Socket has data available for reading + * @EVENT_TYPE_WRITE: Socket has room for new data to be written + * @EVENT_TYPE_EXCEPTION: An exception has been reported + */ +typedef enum { + EVENT_TYPE_READ = 0, + EVENT_TYPE_WRITE, + EVENT_TYPE_EXCEPTION +} eloop_event_type; + +/** + * eloop_sock_handler - eloop socket event callback type + * @sock: File descriptor number for the socket + * @eloop_ctx: Registered callback context data (eloop_data) + * @sock_ctx: Registered callback context data (user_data) + */ +typedef void (*eloop_sock_handler)(int sock, void *eloop_ctx, void *sock_ctx); + +/** + * eloop_event_handler - eloop generic event callback type + * @eloop_ctx: Registered callback context data (eloop_data) + * @sock_ctx: Registered callback context data (user_data) + */ +typedef void (*eloop_event_handler)(void *eloop_data, void *user_ctx); + +/** + * eloop_timeout_handler - eloop timeout event callback type + * @eloop_ctx: Registered callback context data (eloop_data) + * @sock_ctx: Registered callback context data (user_data) + */ +typedef void (*eloop_timeout_handler)(void *eloop_data, void *user_ctx); + +/** + * eloop_signal_handler - eloop signal event callback type + * @sig: Signal number + * @signal_ctx: Registered callback context data (user_data from + * eloop_register_signal(), eloop_register_signal_terminate(), or + * eloop_register_signal_reconfig() call) + */ +typedef void (*eloop_signal_handler)(int sig, void *signal_ctx); + +struct eloop_sock { + int sock; + void *eloop_data; + void *user_data; + eloop_sock_handler handler; +}; + +struct eloop_ind{ + struct dl_list free_hdr; + beken2_timer_t bk_tmr; +}; + +struct eloop_timeout { + struct dl_list list; + struct os_reltime time; + + eloop_timeout_handler handler; + void *eloop_data; + void *user_data; +}; + +struct eloop_signal { + int sig; + void *user_data; + eloop_signal_handler handler; + int signaled; +}; + +struct eloop_sock_table { + int count; + struct eloop_sock *table; + eloop_event_type type; + int changed; +}; + +struct ind_entity{ + uint32_t flag; + struct dl_list pending_free_ind_tmr; +}; + +struct eloop_data { + int max_sock; + + int count; /* sum of all table counts */ + + struct dl_list timeout; + + struct eloop_sock_table readers; + struct eloop_sock_table writers; + struct eloop_sock_table exceptions; + + int signal_count; + struct eloop_signal *signals; + int signaled; + int pending_terminate; + + int terminate; +}; + +typedef struct wpah_msg_st { + u32 argu; +}WPAH_MSG_ST, *WPAH_MSG_PTR; +/** + * eloop_init() - Initialize global event loop data + * Returns: 0 on success, -1 on failure + * + * This function must be called before any other eloop_* function. + */ +int eloop_init(void); + +/** + * eloop_register_read_sock - Register handler for read events + * @sock: File descriptor number for the socket + * @handler: Callback function to be called when data is available for reading + * @eloop_data: Callback context data (eloop_ctx) + * @user_data: Callback context data (sock_ctx) + * Returns: 0 on success, -1 on failure + * + * Register a read socket notifier for the given file descriptor. The handler + * function will be called whenever data is available for reading from the + * socket. The handler function is responsible for clearing the event after + * having processed it in order to avoid eloop from calling the handler again + * for the same event. + */ +int eloop_register_read_sock(int sock, eloop_sock_handler handler, + void *eloop_data, void *user_data); + +/** + * eloop_unregister_read_sock - Unregister handler for read events + * @sock: File descriptor number for the socket + * + * Unregister a read socket notifier that was previously registered with + * eloop_register_read_sock(). + */ +void eloop_unregister_read_sock(int sock); + +/** + * eloop_register_sock - Register handler for socket events + * @sock: File descriptor number for the socket + * @type: Type of event to wait for + * @handler: Callback function to be called when the event is triggered + * @eloop_data: Callback context data (eloop_ctx) + * @user_data: Callback context data (sock_ctx) + * Returns: 0 on success, -1 on failure + * + * Register an event notifier for the given socket's file descriptor. The + * handler function will be called whenever the that event is triggered for the + * socket. The handler function is responsible for clearing the event after + * having processed it in order to avoid eloop from calling the handler again + * for the same event. + */ +int eloop_register_sock(int sock, eloop_event_type type, + eloop_sock_handler handler, + void *eloop_data, void *user_data); + +/** + * eloop_unregister_sock - Unregister handler for socket events + * @sock: File descriptor number for the socket + * @type: Type of event for which sock was registered + * + * Unregister a socket event notifier that was previously registered with + * eloop_register_sock(). + */ +void eloop_unregister_sock(int sock, eloop_event_type type); + +/** + * eloop_register_event - Register handler for generic events + * @event: Event to wait (eloop implementation specific) + * @event_size: Size of event data + * @handler: Callback function to be called when event is triggered + * @eloop_data: Callback context data (eloop_data) + * @user_data: Callback context data (user_data) + * Returns: 0 on success, -1 on failure + * + * Register an event handler for the given event. This function is used to + * register eloop implementation specific events which are mainly targeted for + * operating system specific code (driver interface and l2_packet) since the + * portable code will not be able to use such an OS-specific call. The handler + * function will be called whenever the event is triggered. The handler + * function is responsible for clearing the event after having processed it in + * order to avoid eloop from calling the handler again for the same event. + * + * In case of Windows implementation (eloop_win.c), event pointer is of HANDLE + * type, i.e., void*. The callers are likely to have 'HANDLE h' type variable, + * and they would call this function with eloop_register_event(h, sizeof(h), + * ...). + */ +int eloop_register_event(void *event, size_t event_size, + eloop_event_handler handler, + void *eloop_data, void *user_data); + +/** + * eloop_unregister_event - Unregister handler for a generic event + * @event: Event to cancel (eloop implementation specific) + * @event_size: Size of event data + * + * Unregister a generic event notifier that was previously registered with + * eloop_register_event(). + */ +void eloop_unregister_event(void *event, size_t event_size); + +/** + * eloop_register_timeout - Register timeout + * @secs: Number of seconds to the timeout + * @usecs: Number of microseconds to the timeout + * @handler: Callback function to be called when timeout occurs + * @eloop_data: Callback context data (eloop_ctx) + * @user_data: Callback context data (sock_ctx) + * Returns: 0 on success, -1 on failure + * + * Register a timeout that will cause the handler function to be called after + * given time. + */ +int eloop_register_timeout(unsigned int secs, + unsigned int usecs, + eloop_timeout_handler handler, + void *eloop_data, + void *user_data); + +/** + * eloop_cancel_timeout - Cancel timeouts + * @handler: Matching callback function + * @eloop_data: Matching eloop_data or %ELOOP_ALL_CTX to match all + * @user_data: Matching user_data or %ELOOP_ALL_CTX to match all + * Returns: Number of cancelled timeouts + * + * Cancel matching timeouts registered with + * eloop_register_timeout(). ELOOP_ALL_CTX can be used as a wildcard for + * cancelling all timeouts regardless of eloop_data/user_data. + */ +int eloop_cancel_timeout(eloop_timeout_handler handler, + void *eloop_data, void *user_data); + +/** + * eloop_cancel_timeout_one - Cancel a single timeout + * @handler: Matching callback function + * @eloop_data: Matching eloop_data + * @user_data: Matching user_data + * @remaining: Time left on the cancelled timer + * Returns: Number of cancelled timeouts + * + * Cancel matching timeout registered with + * eloop_register_timeout() and return the remaining time left. + */ +int eloop_cancel_timeout_one(eloop_timeout_handler handler, + void *eloop_data, void *user_data, + struct os_reltime *remaining); + +/** + * eloop_is_timeout_registered - Check if a timeout is already registered + * @handler: Matching callback function + * @eloop_data: Matching eloop_data + * @user_data: Matching user_data + * Returns: 1 if the timeout is registered, 0 if the timeout is not registered + * + * Determine if a matching timeout is registered + * with eloop_register_timeout(). + */ +int eloop_is_timeout_registered(eloop_timeout_handler handler, + void *eloop_data, void *user_data); + +/** + * eloop_deplete_timeout - Deplete a timeout that is already registered + * @req_secs: Requested number of seconds to the timeout + * @req_usecs: Requested number of microseconds to the timeout + * @handler: Matching callback function + * @eloop_data: Matching eloop_data + * @user_data: Matching user_data + * Returns: 1 if the timeout is depleted, 0 if no change is made, -1 if no + * timeout matched + * + * Find a registered matching timeout. If found, + * deplete the timeout if remaining time is more than the requested time. + */ +int eloop_deplete_timeout(unsigned int req_secs, unsigned int req_usecs, + eloop_timeout_handler handler, void *eloop_data, + void *user_data); + +/** + * eloop_replenish_timeout - Replenish a timeout that is already registered + * @req_secs: Requested number of seconds to the timeout + * @req_usecs: Requested number of microseconds to the timeout + * @handler: Matching callback function + * @eloop_data: Matching eloop_data + * @user_data: Matching user_data + * Returns: 1 if the timeout is replenished, 0 if no change is made, -1 if no + * timeout matched + * + * Find a registered matching timeout. If found, + * replenish the timeout if remaining time is less than the requested time. + */ +int eloop_replenish_timeout(unsigned int req_secs, unsigned int req_usecs, + eloop_timeout_handler handler, void *eloop_data, + void *user_data); + +/** + * eloop_register_signal - Register handler for signals + * @sig: Signal number (e.g., SIGHUP) + * @handler: Callback function to be called when the signal is received + * @user_data: Callback context data (signal_ctx) + * Returns: 0 on success, -1 on failure + * + * Register a callback function that will be called when a signal is received. + * The callback function is actually called only after the system signal + * handler has returned. This means that the normal limits for sighandlers + * (i.e., only "safe functions" allowed) do not apply for the registered + * callback. + */ +int eloop_register_signal(int sig, eloop_signal_handler handler, + void *user_data); + +/** + * eloop_register_signal_terminate - Register handler for terminate signals + * @handler: Callback function to be called when the signal is received + * @user_data: Callback context data (signal_ctx) + * Returns: 0 on success, -1 on failure + * + * Register a callback function that will be called when a process termination + * signal is received. The callback function is actually called only after the + * system signal handler has returned. This means that the normal limits for + * sighandlers (i.e., only "safe functions" allowed) do not apply for the + * registered callback. + * + * This function is a more portable version of eloop_register_signal() since + * the knowledge of exact details of the signals is hidden in eloop + * implementation. In case of operating systems using signal(), this function + * registers handlers for SIGINT and SIGTERM. + */ +int eloop_register_signal_terminate(eloop_signal_handler handler, + void *user_data); + +/** + * eloop_register_signal_reconfig - Register handler for reconfig signals + * @handler: Callback function to be called when the signal is received + * @user_data: Callback context data (signal_ctx) + * Returns: 0 on success, -1 on failure + * + * Register a callback function that will be called when a reconfiguration / + * hangup signal is received. The callback function is actually called only + * after the system signal handler has returned. This means that the normal + * limits for sighandlers (i.e., only "safe functions" allowed) do not apply + * for the registered callback. + * + * This function is a more portable version of eloop_register_signal() since + * the knowledge of exact details of the signals is hidden in eloop + * implementation. In case of operating systems using signal(), this function + * registers a handler for SIGHUP. + */ +int eloop_register_signal_reconfig(eloop_signal_handler handler, + void *user_data); + +/** + * eloop_run - Start the event loop + * + * Start the event loop and continue running as long as there are any + * registered event handlers. This function is run after event loop has been + * initialized with event_init() and one or more events have been registered. + */ +void eloop_run(void); + + +/** + * eloop_terminate - Terminate event loop + * + * Terminate event loop even if there are registered events. This can be used + * to request the program to be terminated cleanly. + */ +void eloop_terminate(void); + +/** + * eloop_destroy - Free any resources allocated for the event loop + * + * After calling eloop_destroy(), other eloop_* functions must not be called + * before re-running eloop_init(). + */ +void eloop_destroy(void); +void eloop_free_resource(void); + +/** + * eloop_terminated - Check whether event loop has been terminated + * Returns: 1 = event loop terminate, 0 = event loop still running + * + * This function can be used to check whether eloop_terminate() has been called + * to request termination of the event loop. This is normally used to abort + * operations that may still be queued to be run when eloop_terminate() was + * called. + */ +int eloop_terminated(void); +void eloop_handle_signal(int sig); + +/** + * eloop_wait_for_read_sock - Wait for a single reader + * @sock: File descriptor number for the socket + * + * Do a blocking wait for a single read socket. + */ +void eloop_wait_for_read_sock(int sock); +void eloop_remove_timeout(struct eloop_timeout *timeout); +void eloop_remove_sta_added_signals(void); +#endif /* ELOOP_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/utils/ext_password_i.h b/beken_os/beken378/func/hostapd-2.5/src/utils/ext_password_i.h new file mode 100755 index 0000000..043e731 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/utils/ext_password_i.h @@ -0,0 +1,23 @@ +/* + * External password backend - internal definitions + * Copyright (c) 2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef EXT_PASSWORD_I_H +#define EXT_PASSWORD_I_H + +#include "ext_password.h" + +struct ext_password_backend { + const char *name; + void * (*init)(const char *params); + void (*deinit)(void *ctx); + struct wpabuf * (*get)(void *ctx, const char *name); +}; + +struct wpabuf * ext_password_alloc(size_t len); + +#endif /* EXT_PASSWORD_I_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/utils/includes.h b/beken_os/beken378/func/hostapd-2.5/src/utils/includes.h new file mode 100755 index 0000000..9640205 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/utils/includes.h @@ -0,0 +1,26 @@ +/* + * wpa_supplicant/hostapd - Default include files + * Copyright (c) 2005-2006, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + * + * This header file is included into all C files so that commonly used header + * files can be selected with OS specific ifdef blocks in one place instead of + * having to have OS/C library specific selection in many files. + */ + +#ifndef INCLUDES_H +#define INCLUDES_H + +#include "build_config.h" + +#include +#include +#include +#include +#include + +#include + +#endif /* INCLUDES_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/utils/ip_addr.h b/beken_os/beken378/func/hostapd-2.5/src/utils/ip_addr.h new file mode 100755 index 0000000..77b99fd --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/utils/ip_addr.h @@ -0,0 +1,35 @@ +/* + * IP address processing + * Copyright (c) 2003-2006, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef IP_ADDR_H +#define IP_ADDR_H + +struct in_addr +{ + int s_addr; +}; + +struct hostapd_ip_addr { + int af; /* AF_INET / AF_INET6 */ + + union { + struct in_addr v4; + +#ifdef CONFIG_IPV6 + struct in6_addr v6; +#endif /* CONFIG_IPV6 */ + + u8 max_len[16]; + } u; +}; + +const char * hostapd_ip_txt(const struct hostapd_ip_addr *addr, char *buf, + size_t buflen); +int hostapd_parse_ip_addr(const char *txt, struct hostapd_ip_addr *addr); + +#endif /* IP_ADDR_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/utils/list.h b/beken_os/beken378/func/hostapd-2.5/src/utils/list.h new file mode 100755 index 0000000..ee2f485 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/utils/list.h @@ -0,0 +1,97 @@ +/* + * Doubly-linked list + * Copyright (c) 2009, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef LIST_H +#define LIST_H + +/** + * struct dl_list - Doubly-linked list + */ +struct dl_list { + struct dl_list *next; + struct dl_list *prev; +}; + +#define DL_LIST_HEAD_INIT(l) { &(l), &(l) } + +static inline void dl_list_init(struct dl_list *list) +{ + list->next = list; + list->prev = list; +} + +static inline void dl_list_add(struct dl_list *list, struct dl_list *item) +{ + item->next = list->next; + item->prev = list; + list->next->prev = item; + list->next = item; +} + +static inline void dl_list_add_tail(struct dl_list *list, struct dl_list *item) +{ + dl_list_add(list->prev, item); +} + +static inline void dl_list_del(struct dl_list *item) +{ + item->next->prev = item->prev; + item->prev->next = item->next; + item->next = NULL; + item->prev = NULL; +} + +static inline int dl_list_empty(struct dl_list *list) +{ + return list->next == list; +} + +static inline unsigned int dl_list_len(struct dl_list *list) +{ + struct dl_list *item; + int count = 0; + for (item = list->next; item != list; item = item->next) + count++; + return count; +} + +#ifndef offsetof +#define offsetof(type, member) ((long) &((type *) 0)->member) +#endif + +#define dl_list_entry(item, type, member) \ + ((type *) ((char *) item - offsetof(type, member))) + +#define dl_list_first(list, type, member) \ + (dl_list_empty((list)) ? NULL : \ + dl_list_entry((list)->next, type, member)) + +#define dl_list_last(list, type, member) \ + (dl_list_empty((list)) ? NULL : \ + dl_list_entry((list)->prev, type, member)) + +#define dl_list_for_each(item, list, type, member) \ + for (item = dl_list_entry((list)->next, type, member); \ + &item->member != (list); \ + item = dl_list_entry(item->member.next, type, member)) + +#define dl_list_for_each_safe(item, n, list, type, member) \ + for (item = dl_list_entry((list)->next, type, member), \ + n = dl_list_entry(item->member.next, type, member); \ + &item->member != (list); \ + item = n, n = dl_list_entry(n->member.next, type, member)) + +#define dl_list_for_each_reverse(item, list, type, member) \ + for (item = dl_list_entry((list)->prev, type, member); \ + &item->member != (list); \ + item = dl_list_entry(item->member.prev, type, member)) + +#define DEFINE_DL_LIST(name) \ + struct dl_list name = { &(name), &(name) } + +#endif /* LIST_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/utils/os.h b/beken_os/beken378/func/hostapd-2.5/src/utils/os.h new file mode 100755 index 0000000..79dacf9 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/utils/os.h @@ -0,0 +1,377 @@ +/* + * OS specific functions + * Copyright (c) 2005-2009, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef OS_H +#define OS_H + +#include "include.h" +#include "mem_pub.h" + +#include + +typedef long os_time_t; + +/** + * os_sleep - Sleep (sec, usec) + * @sec: Number of seconds to sleep + * @usec: Number of microseconds to sleep + */ +void os_sleep(os_time_t sec, os_time_t usec); + +struct os_time { + os_time_t sec; + os_time_t usec; +}; + +struct os_reltime { + os_time_t sec; + os_time_t usec; +}; + +/** + * os_get_time - Get current time (sec, usec) + * @t: Pointer to buffer for the time + * Returns: 0 on success, -1 on failure + */ +int os_get_time(struct os_time *t); + +/** + * os_get_reltime - Get relative time (sec, usec) + * @t: Pointer to buffer for the time + * Returns: 0 on success, -1 on failure + */ +int os_get_reltime(struct os_reltime *t); + + +/* Helpers for handling struct os_time */ + +static inline int os_time_before(struct os_time *a, struct os_time *b) +{ + return (a->sec < b->sec) || + (a->sec == b->sec && a->usec < b->usec); +} + + +static inline void os_time_sub(struct os_time *a, struct os_time *b, + struct os_time *res) +{ + res->sec = a->sec - b->sec; + res->usec = a->usec - b->usec; + if (res->usec < 0) { + res->sec--; + res->usec += 1000000; + } +} + + +/* Helpers for handling struct os_reltime */ + +static inline int os_reltime_before(struct os_reltime *a, + struct os_reltime *b) +{ + return (a->sec < b->sec) || + (a->sec == b->sec && a->usec < b->usec); +} + + +static inline void os_reltime_sub(struct os_reltime *a, struct os_reltime *b, + struct os_reltime *res) +{ + res->sec = a->sec - b->sec; + res->usec = a->usec - b->usec; + if (res->usec < 0) { + res->sec--; + res->usec += 1000000; + } +} + + +static inline void os_reltime_age(struct os_reltime *start, + struct os_reltime *age) +{ + struct os_reltime now; + + os_get_reltime(&now); + os_reltime_sub(&now, start, age); +} + + +static inline int os_reltime_expired(struct os_reltime *now, + struct os_reltime *ts, + os_time_t timeout_secs) +{ + struct os_reltime age; + + os_reltime_sub(now, ts, &age); + return (age.sec > timeout_secs) || + (age.sec == timeout_secs && age.usec > 0); +} + + +static inline int os_reltime_initialized(struct os_reltime *t) +{ + return t->sec != 0 || t->usec != 0; +} + + +/** + * os_mktime - Convert broken-down time into seconds since 1970-01-01 + * @year: Four digit year + * @month: Month (1 .. 12) + * @day: Day of month (1 .. 31) + * @hour: Hour (0 .. 23) + * @min: Minute (0 .. 59) + * @sec: Second (0 .. 60) + * @t: Buffer for returning calendar time representation (seconds since + * 1970-01-01 00:00:00) + * Returns: 0 on success, -1 on failure + * + * Note: The result is in seconds from Epoch, i.e., in UTC, not in local time + * which is used by POSIX mktime(). + */ +int os_mktime(int year, int month, int day, int hour, int min, int sec, + os_time_t *t); + +struct os_tm { + int sec; /* 0..59 or 60 for leap seconds */ + int min; /* 0..59 */ + int hour; /* 0..23 */ + int day; /* 1..31 */ + int month; /* 1..12 */ + int year; /* Four digit year */ +}; + +int os_gmtime(os_time_t t, struct os_tm *tm); + +/** + * os_daemonize - Run in the background (detach from the controlling terminal) + * @pid_file: File name to write the process ID to or %NULL to skip this + * Returns: 0 on success, -1 on failure + */ +int os_daemonize(const char *pid_file); + +/** + * os_daemonize_terminate - Stop running in the background (remove pid file) + * @pid_file: File name to write the process ID to or %NULL to skip this + */ +void os_daemonize_terminate(const char *pid_file); + +/** + * os_get_random - Get cryptographically strong pseudo random data + * @buf: Buffer for pseudo random data + * @len: Length of the buffer + * Returns: 0 on success, -1 on failure + */ +int os_get_random(unsigned char *buf, size_t len); + +/** + * os_random - Get pseudo random value (not necessarily very strong) + * Returns: Pseudo random value + */ +unsigned long os_random(void); + +/** + * os_rel2abs_path - Get an absolute path for a file + * @rel_path: Relative path to a file + * Returns: Absolute path for the file or %NULL on failure + * + * This function tries to convert a relative path of a file to an absolute path + * in order for the file to be found even if current working directory has + * changed. The returned value is allocated and caller is responsible for + * freeing it. It is acceptable to just return the same path in an allocated + * buffer, e.g., return strdup(rel_path). This function is only used to find + * configuration files when os_daemonize() may have changed the current working + * directory and relative path would be pointing to a different location. + */ +char * os_rel2abs_path(const char *rel_path); + +/** + * os_program_init - Program initialization (called at start) + * Returns: 0 on success, -1 on failure + * + * This function is called when a programs starts. If there are any OS specific + * processing that is needed, it can be placed here. It is also acceptable to + * just return 0 if not special processing is needed. + */ +int os_program_init(void); + +/** + * os_program_deinit - Program deinitialization (called just before exit) + * + * This function is called just before a program exists. If there are any OS + * specific processing, e.g., freeing resourced allocated in os_program_init(), + * it should be done here. It is also acceptable for this function to do + * nothing. + */ +void os_program_deinit(void); + +/** + * os_setenv - Set environment variable + * @name: Name of the variable + * @value: Value to set to the variable + * @overwrite: Whether existing variable should be overwritten + * Returns: 0 on success, -1 on error + * + * This function is only used for wpa_cli action scripts. OS wrapper does not + * need to implement this if such functionality is not needed. + */ +int os_setenv(const char *name, const char *value, int overwrite); + +/** + * os_unsetenv - Delete environent variable + * @name: Name of the variable + * Returns: 0 on success, -1 on error + * + * This function is only used for wpa_cli action scripts. OS wrapper does not + * need to implement this if such functionality is not needed. + */ +int os_unsetenv(const char *name); + +/** + * os_readfile - Read a file to an allocated memory buffer + * @name: Name of the file to read + * @len: For returning the length of the allocated buffer + * Returns: Pointer to the allocated buffer or %NULL on failure + * + * This function allocates memory and reads the given file to this buffer. Both + * binary and text files can be read with this function. The caller is + * responsible for freeing the returned buffer with os_free(). + */ +char * os_readfile(const char *name, size_t *len); + +/** + * os_file_exists - Check whether the specified file exists + * @fname: Path and name of the file + * Returns: 1 if the file exists or 0 if not + */ +int os_file_exists(const char *fname); + +/** + * os_fdatasync - Sync a file's (for a given stream) state with storage device + * @stream: the stream to be flushed + * Returns: 0 if the operation succeeded or -1 on failure + */ +int os_fdatasync(FILE *stream); + +/** + * os_zalloc - Allocate and zero memory + * @size: Number of bytes to allocate + * Returns: Pointer to allocated and zeroed memory or %NULL on failure + * + * Caller is responsible for freeing the returned buffer with os_free(). + */ +//void * os_zalloc(size_t size); + +/** + * os_calloc - Allocate and zero memory for an array + * @nmemb: Number of members in the array + * @size: Number of bytes in each member + * Returns: Pointer to allocated and zeroed memory or %NULL on failure + * + * This function can be used as a wrapper for os_zalloc(nmemb * size) when an + * allocation is used for an array. The main benefit over os_zalloc() is in + * having an extra check to catch integer overflows in multiplication. + * + * Caller is responsible for freeing the returned buffer with os_free(). + */ +static inline void * os_calloc(size_t nmemb, size_t size) +{ + if (size && nmemb > (~(size_t) 0) / size) + return NULL; + return os_zalloc(nmemb * size); +} + + +/* + * The following functions are wrapper for standard ANSI C or POSIX functions. + * By default, they are just defined to use the standard function name and no + * os_*.c implementation is needed for them. This avoids extra function calls + * by allowing the C pre-processor take care of the function name mapping. + * + * If the target system uses a C library that does not provide these functions, + * build_config.h can be used to define the wrappers to use a different + * function name. This can be done on function-by-function basis since the + * defines here are only used if build_config.h does not define the os_* name. + * If needed, os_*.c file can be used to implement the functions that are not + * included in the C library on the target system. Alternatively, + * OS_NO_C_LIB_DEFINES can be defined to skip all defines here in which case + * these functions need to be implemented in os_*.c file for the target system. + */ + +static inline int os_snprintf_error(size_t size, int res) +{ + return res < 0 || (unsigned int) res >= size; +} + + +static inline void * os_realloc_array(void *ptr, size_t nmemb, size_t size) +{ + if (size && nmemb > (~(size_t) 0) / size) + return NULL; + + return (void *)os_realloc(ptr, nmemb * size); +} + +/** + * os_remove_in_array - Remove a member from an array by index + * @ptr: Pointer to the array + * @nmemb: Current member count of the array + * @size: The size per member of the array + * @idx: Index of the member to be removed + */ +static inline void os_remove_in_array(void *ptr, size_t nmemb, size_t size, + size_t idx) +{ + if (idx < nmemb - 1) + os_memmove(((unsigned char *) ptr) + idx * size, + ((unsigned char *) ptr) + (idx + 1) * size, + (nmemb - idx - 1) * size); +} + +/** + * os_strlcpy - Copy a string with size bound and NUL-termination + * @dest: Destination + * @src: Source + * @siz: Size of the target buffer + * Returns: Total length of the target string (length of src) (not including + * NUL-termination) + * + * This function matches in behavior with the strlcpy(3) function in OpenBSD. + */ +size_t os_strlcpy(char *dest, const char *src, size_t siz); + +/** + * os_memcmp_const - Constant time memory comparison + * @a: First buffer to compare + * @b: Second buffer to compare + * @len: Number of octets to compare + * Returns: 0 if buffers are equal, non-zero if not + * + * This function is meant for comparing passwords or hash values where + * difference in execution time could provide external observer information + * about the location of the difference in the memory buffers. The return value + * does not behave like os_memcmp(), i.e., os_memcmp_const() cannot be used to + * sort items into a defined order. Unlike os_memcmp(), execution time of + * os_memcmp_const() does not depend on the contents of the compared memory + * buffers, but only on the total compared length. + */ +int os_memcmp_const(const void *a, const void *b, size_t len); + +/** + * os_exec - Execute an external program + * @program: Path to the program + * @arg: Command line argument string + * @wait_completion: Whether to wait until the program execution completes + * Returns: 0 on success, -1 on error + */ +int os_exec(const char *program, const char *arg, int wait_completion); + + +#define TEST_FAIL() 0 + +#endif /* OS_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/utils/os_none.c b/beken_os/beken378/func/hostapd-2.5/src/utils/os_none.c new file mode 100755 index 0000000..97a5cda --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/utils/os_none.c @@ -0,0 +1,130 @@ +/* + * wpa_supplicant/hostapd / Empty OS specific functions + * Copyright (c) 2005-2006, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + * + * This file can be used as a starting point when adding a new OS target. The + * functions here do not really work as-is since they are just empty or only + * return an error value. os_internal.c can be used as another starting point + * or reference since it has example implementation of many of these functions. + */ + +#include "include.h" +#include "fake_clock_pub.h" + +#include "includes.h" + +#include "os.h" + +void os_sleep(os_time_t sec, os_time_t usec) +{ +} + + +int os_get_time(struct os_time *t) +{ + t->sec = fclk_get_second(); + t->usec = (fclk_get_tick() * FCLK_DURATION_MS * 1000) % 1000000; + + return 0; +} + + +int os_get_reltime(struct os_reltime *t) +{ + t->sec = fclk_get_second(); + t->usec = (fclk_get_tick() * FCLK_DURATION_MS * 1000) % 1000000; + + return 0; +} + + +int os_mktime(int year, int month, int day, int hour, int min, int sec, + os_time_t *t) +{ + return -1; +} + +int os_gmtime(os_time_t t, struct os_tm *tm) +{ + return -1; +} + + +int os_daemonize(const char *pid_file) +{ + return -1; +} + + +void os_daemonize_terminate(const char *pid_file) +{ +} + + +int os_get_random(unsigned char *buf, size_t len) +{ + srand(fclk_get_second()); + while(len--){ + *buf++ = rand()%255; + } + return 0; +} + + +unsigned long os_random(void) +{ + return rand(); +} + + +char * os_rel2abs_path(const char *rel_path) +{ + return NULL; /* strdup(rel_path) can be used here */ +} + + +int os_program_init(void) +{ + return 0; +} + + +void os_program_deinit(void) +{ +} + + +int os_setenv(const char *name, const char *value, int overwrite) +{ + return -1; +} + + +int os_unsetenv(const char *name) +{ + return -1; +} + + +char * os_readfile(const char *name, size_t *len) +{ + return NULL; +} + + +int os_fdatasync(FILE *stream) +{ + return 0; +} + + +int os_exec(const char *program, const char *arg, int wait_completion) +{ + return -1; +} + +// eof + diff --git a/beken_os/beken378/func/hostapd-2.5/src/utils/platform.h b/beken_os/beken378/func/hostapd-2.5/src/utils/platform.h new file mode 100755 index 0000000..46cfe78 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/utils/platform.h @@ -0,0 +1,21 @@ +#ifndef PLATFORM_H +#define PLATFORM_H + +#include "includes.h" +#include "common.h" + +#define le16_to_cpu le_to_host16 +#define le32_to_cpu le_to_host32 + +#define get_unaligned(p) \ +({ \ + struct packed_dummy_struct { \ + typeof(*(p)) __val; \ + } __attribute__((packed)) *__ptr = (void *) (p); \ + \ + __ptr->__val; \ +}) +#define get_unaligned_le16(p) le16_to_cpu(get_unaligned((uint16_t *)(p))) +#define get_unaligned_le32(p) le32_to_cpu(get_unaligned((uint32_t *)(p))) + +#endif /* PLATFORM_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/utils/state_machine.h b/beken_os/beken378/func/hostapd-2.5/src/utils/state_machine.h new file mode 100755 index 0000000..aeb9c13 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/utils/state_machine.h @@ -0,0 +1,138 @@ +/* + * wpa_supplicant/hostapd - State machine definitions + * Copyright (c) 2002-2005, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + * + * This file includes a set of pre-processor macros that can be used to + * implement a state machine. In addition to including this header file, each + * file implementing a state machine must define STATE_MACHINE_DATA to be the + * data structure including state variables (enum machine_state, + * Boolean changed), and STATE_MACHINE_DEBUG_PREFIX to be a string that is used + * as a prefix for all debug messages. If SM_ENTRY_MA macro is used to define + * a group of state machines with shared data structure, STATE_MACHINE_ADDR + * needs to be defined to point to the MAC address used in debug output. + * SM_ENTRY_M macro can be used to define similar group of state machines + * without this additional debug info. + */ + +#ifndef STATE_MACHINE_H +#define STATE_MACHINE_H + +/** + * SM_STATE - Declaration of a state machine function + * @machine: State machine name + * @state: State machine state + * + * This macro is used to declare a state machine function. It is used in place + * of a C function definition to declare functions to be run when the state is + * entered by calling SM_ENTER or SM_ENTER_GLOBAL. + */ +#define SM_STATE(machine, state) \ +static void sm_ ## machine ## _ ## state ## _Enter(STATE_MACHINE_DATA *sm, \ + int global) + +/** + * SM_ENTRY - State machine function entry point + * @machine: State machine name + * @state: State machine state + * + * This macro is used inside each state machine function declared with + * SM_STATE. SM_ENTRY should be in the beginning of the function body, but + * after declaration of possible local variables. This macro prints debug + * information about state transition and update the state machine state. + */ +#define SM_ENTRY(machine, state) \ +if (!global || sm->machine ## _state != machine ## _ ## state) { \ + sm->changed = TRUE; \ + wpa_printf(MSG_DEBUG, STATE_MACHINE_DEBUG_PREFIX ": " #machine \ + " entering state " #state); \ +} \ +sm->machine ## _state = machine ## _ ## state; + +/** + * SM_ENTRY_M - State machine function entry point for state machine group + * @machine: State machine name + * @_state: State machine state + * @data: State variable prefix (full variable: prefix_state) + * + * This macro is like SM_ENTRY, but for state machine groups that use a shared + * data structure for more than one state machine. Both machine and prefix + * parameters are set to "sub-state machine" name. prefix is used to allow more + * than one state variable to be stored in the same data structure. + */ +#define SM_ENTRY_M(machine, _state, data) \ +if (!global || sm->data ## _ ## state != machine ## _ ## _state) { \ + sm->changed = TRUE; \ + wpa_printf(MSG_DEBUG, STATE_MACHINE_DEBUG_PREFIX ": " \ + #machine " entering state " #_state); \ +} \ +sm->data ## _ ## state = machine ## _ ## _state; + +/** + * SM_ENTRY_MA - State machine function entry point for state machine group + * @machine: State machine name + * @_state: State machine state + * @data: State variable prefix (full variable: prefix_state) + * + * This macro is like SM_ENTRY_M, but a MAC address is included in debug + * output. STATE_MACHINE_ADDR has to be defined to point to the MAC address to + * be included in debug. + */ +#define SM_ENTRY_MA(machine, _state, data) \ +if (!global || sm->data ## _ ## state != machine ## _ ## _state) { \ + sm->changed = TRUE; \ + wpa_printf(MSG_DEBUG, STATE_MACHINE_DEBUG_PREFIX ": " MACSTR " " \ + #machine " entering state " #_state "\r\n", \ + MAC2STR(STATE_MACHINE_ADDR)); \ +} \ +sm->data ## _ ## state = machine ## _ ## _state; + +/** + * SM_ENTER - Enter a new state machine state + * @machine: State machine name + * @state: State machine state + * + * This macro expands to a function call to a state machine function defined + * with SM_STATE macro. SM_ENTER is used in a state machine step function to + * move the state machine to a new state. + */ +#define SM_ENTER(machine, state) \ +sm_ ## machine ## _ ## state ## _Enter(sm, 0) + +/** + * SM_ENTER_GLOBAL - Enter a new state machine state based on global rule + * @machine: State machine name + * @state: State machine state + * + * This macro is like SM_ENTER, but this is used when entering a new state + * based on a global (not specific to any particular state) rule. A separate + * macro is used to avoid unwanted debug message floods when the same global + * rule is forcing a state machine to remain in on state. + */ +#define SM_ENTER_GLOBAL(machine, state) \ +sm_ ## machine ## _ ## state ## _Enter(sm, 1) + +/** + * SM_STEP - Declaration of a state machine step function + * @machine: State machine name + * + * This macro is used to declare a state machine step function. It is used in + * place of a C function definition to declare a function that is used to move + * state machine to a new state based on state variables. This function uses + * SM_ENTER and SM_ENTER_GLOBAL macros to enter new state. + */ +#define SM_STEP(machine) \ +static void sm_ ## machine ## _Step(STATE_MACHINE_DATA *sm) + +/** + * SM_STEP_RUN - Call the state machine step function + * @machine: State machine name + * + * This macro expands to a function call to a state machine step function + * defined with SM_STEP macro. + */ +#define SM_STEP_RUN(machine) sm_ ## machine ## _Step(sm) + +#endif /* STATE_MACHINE_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/utils/trace.h b/beken_os/beken378/func/hostapd-2.5/src/utils/trace.h new file mode 100755 index 0000000..9a01dcd --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/utils/trace.h @@ -0,0 +1,29 @@ +/* + * Backtrace debugging + * Copyright (c) 2009, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef TRACE_H +#define TRACE_H + +#define WPA_TRACE_LEN 16 + +#ifndef WPA_TRACE +#define WPA_TRACE_INFO +#define WPA_TRACE_REF(n) +#define wpa_trace_dump(title, ptr) do { } while (0) +#define wpa_trace_record(ptr) do { } while (0) +#define wpa_trace_show(title) do { } while (0) +#define wpa_trace_add_ref(ptr, name, addr) do { } while (0) +#define wpa_trace_remove_ref(ptr, name, addr) do { } while (0) +#define wpa_trace_check_ref(addr) do { } while (0) +#endif /* WPA_TRACE */ + +#ifndef WPA_TRACE_BFD +#define wpa_trace_dump_funcname(title, pc) do { } while (0) +#endif /* WPA_TRACE_BFD */ + +#endif /* TRACE_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/utils/uuid.h b/beken_os/beken378/func/hostapd-2.5/src/utils/uuid.h new file mode 100755 index 0000000..5e860cb --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/utils/uuid.h @@ -0,0 +1,18 @@ +/* + * Universally Unique IDentifier (UUID) + * Copyright (c) 2008, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef UUID_H +#define UUID_H + +#define UUID_LEN 16 + +int uuid_str2bin(const char *str, u8 *bin); +int uuid_bin2str(const u8 *bin, char *str, size_t max_len); +int is_nil_uuid(const u8 *uuid); + +#endif /* UUID_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/utils/wpa_debug.h b/beken_os/beken378/func/hostapd-2.5/src/utils/wpa_debug.h new file mode 100755 index 0000000..fe579e9 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/utils/wpa_debug.h @@ -0,0 +1,265 @@ +/* + * wpa_supplicant/hostapd / Debug prints + * Copyright (c) 2002-2013, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef WPA_DEBUG_H +#define WPA_DEBUG_H + +#include "wpabuf.h" +#include "sys_config.h" + +extern int wpa_debug_level; +extern int wpa_debug_show_keys; +extern int wpa_debug_timestamp; + +/* Debugging function - conditional printf and hex dump. Driver wrappers can + * use these for debugging purposes. */ + +enum { + MSG_EXCESSIVE, + MSG_MSGDUMP, + MSG_DEBUG, + MSG_INFO, + MSG_WARNING, + MSG_ERROR +}; + +#ifdef CONFIG_NO_STDOUT_DEBUG +#define wpa_debug_print_timestamp() do { } while (0) +#define wpa_hexdump(l,t,b,le) do { } while (0) +#define wpa_hexdump_buf(l,t,b) do { } while (0) +#define wpa_hexdump_key(l,t,b,le) do { } while (0) +#define wpa_hexdump_buf_key(l,t,b) do { } while (0) +#define wpa_hexdump_ascii(l,t,b,le) do { } while (0) +#define wpa_hexdump_ascii_key(l,t,b,le) do { } while (0) +#define wpa_debug_open_file(p) do { } while (0) +#define wpa_debug_close_file() do { } while (0) +#define wpa_debug_setup_stdout() do { } while (0) + +static inline int wpa_debug_reopen_file(void) +{ + return 0; +} +#endif /* CONFIG_NO_STDOUT_DEBUG */ + +#if 0 == CFG_ENABLE_WPA_LOG +#define wpa_dbg(args...) do {} while (0) +#define wpa_printf(args...) do {} while(0) +#else +void wpa_dbg(void *ctx, int level, const char *fmt, ...); +#define wpa_printf(level, fmt, ...) wpa_dbg(NULL, level, fmt, ##__VA_ARGS__) +#endif + +#ifdef CONFIG_NO_WPA_MSG +#define wpa_msg(args...) do { } while (0) +#define wpa_msg_ctrl(args...) do { } while (0) +#define wpa_msg_global(args...) do { } while (0) +#define wpa_msg_global_ctrl(args...) do { } while (0) +#define wpa_msg_no_global(args...) do { } while (0) +#define wpa_msg_global_only(args...) do { } while (0) +#define wpa_msg_register_cb(f) do { } while (0) +#define wpa_msg_register_ifname_cb(f) do { } while (0) +#else /* CONFIG_NO_WPA_MSG */ +/** + * wpa_msg - Conditional printf for default target and ctrl_iface monitors + * @ctx: Pointer to context data; this is the ctx variable registered + * with struct wpa_driver_ops::init() + * @level: priority level (MSG_*) of the message + * @fmt: printf format string, followed by optional arguments + * + * This function is used to print conditional debugging and error messages. The + * output may be directed to stdout, stderr, and/or syslog based on + * configuration. This function is like wpa_printf(), but it also sends the + * same message to all attached ctrl_iface monitors. + * + * Note: New line '\n' is added to the end of the text when printing to stdout. + */ +void wpa_msg(void *ctx, int level, const char *fmt, ...) PRINTF_FORMAT(3, 4); + +/** + * wpa_msg_ctrl - Conditional printf for ctrl_iface monitors + * @ctx: Pointer to context data; this is the ctx variable registered + * with struct wpa_driver_ops::init() + * @level: priority level (MSG_*) of the message + * @fmt: printf format string, followed by optional arguments + * + * This function is used to print conditional debugging and error messages. + * This function is like wpa_msg(), but it sends the output only to the + * attached ctrl_iface monitors. In other words, it can be used for frequent + * events that do not need to be sent to syslog. + */ +void wpa_msg_ctrl(void *ctx, int level, const char *fmt, ...) +PRINTF_FORMAT(3, 4); + +/** + * wpa_msg_global - Global printf for ctrl_iface monitors + * @ctx: Pointer to context data; this is the ctx variable registered + * with struct wpa_driver_ops::init() + * @level: priority level (MSG_*) of the message + * @fmt: printf format string, followed by optional arguments + * + * This function is used to print conditional debugging and error messages. + * This function is like wpa_msg(), but it sends the output as a global event, + * i.e., without being specific to an interface. For backwards compatibility, + * an old style event is also delivered on one of the interfaces (the one + * specified by the context data). + */ +void wpa_msg_global(void *ctx, int level, const char *fmt, ...) +PRINTF_FORMAT(3, 4); + +/** + * wpa_msg_global_ctrl - Conditional global printf for ctrl_iface monitors + * @ctx: Pointer to context data; this is the ctx variable registered + * with struct wpa_driver_ops::init() + * @level: priority level (MSG_*) of the message + * @fmt: printf format string, followed by optional arguments + * + * This function is used to print conditional debugging and error messages. + * This function is like wpa_msg_global(), but it sends the output only to the + * attached global ctrl_iface monitors. In other words, it can be used for + * frequent events that do not need to be sent to syslog. + */ +void wpa_msg_global_ctrl(void *ctx, int level, const char *fmt, ...) +PRINTF_FORMAT(3, 4); + +/** + * wpa_msg_no_global - Conditional printf for ctrl_iface monitors + * @ctx: Pointer to context data; this is the ctx variable registered + * with struct wpa_driver_ops::init() + * @level: priority level (MSG_*) of the message + * @fmt: printf format string, followed by optional arguments + * + * This function is used to print conditional debugging and error messages. + * This function is like wpa_msg(), but it does not send the output as a global + * event. + */ +void wpa_msg_no_global(void *ctx, int level, const char *fmt, ...) +PRINTF_FORMAT(3, 4); + +/** + * wpa_msg_global_only - Conditional printf for ctrl_iface monitors + * @ctx: Pointer to context data; this is the ctx variable registered + * with struct wpa_driver_ops::init() + * @level: priority level (MSG_*) of the message + * @fmt: printf format string, followed by optional arguments + * + * This function is used to print conditional debugging and error messages. + * This function is like wpa_msg_global(), but it sends the output only as a + * global event. + */ +void wpa_msg_global_only(void *ctx, int level, const char *fmt, ...) +PRINTF_FORMAT(3, 4); + +enum wpa_msg_type { + WPA_MSG_PER_INTERFACE, + WPA_MSG_GLOBAL, + WPA_MSG_NO_GLOBAL, + WPA_MSG_ONLY_GLOBAL, +}; + +typedef void (*wpa_msg_cb_func)(void *ctx, int level, enum wpa_msg_type type, + const char *txt, size_t len); + +/** + * wpa_msg_register_cb - Register callback function for wpa_msg() messages + * @func: Callback function (%NULL to unregister) + */ +void wpa_msg_register_cb(wpa_msg_cb_func func); + +typedef const char * (*wpa_msg_get_ifname_func)(void *ctx); +void wpa_msg_register_ifname_cb(wpa_msg_get_ifname_func func); + +#endif /* CONFIG_NO_WPA_MSG */ + +#ifdef CONFIG_NO_HOSTAPD_LOGGER +#define hostapd_logger(args...) do { } while (0) +#define hostapd_logger_register_cb(f) do { } while (0) +#else /* CONFIG_NO_HOSTAPD_LOGGER */ +void hostapd_logger(void *ctx, const u8 *addr, unsigned int module, int level, + const char *fmt, ...) PRINTF_FORMAT(5, 6); + +typedef void (*hostapd_logger_cb_func)(void *ctx, const u8 *addr, + unsigned int module, int level, + const char *txt, size_t len); + +/** + * hostapd_logger_register_cb - Register callback function for hostapd_logger() + * @func: Callback function (%NULL to unregister) + */ +void hostapd_logger_register_cb(hostapd_logger_cb_func func); +#endif /* CONFIG_NO_HOSTAPD_LOGGER */ + +#define HOSTAPD_MODULE_IEEE80211 0x00000001 +#define HOSTAPD_MODULE_IEEE8021X 0x00000002 +#define HOSTAPD_MODULE_RADIUS 0x00000004 +#define HOSTAPD_MODULE_WPA 0x00000008 +#define HOSTAPD_MODULE_DRIVER 0x00000010 +#define HOSTAPD_MODULE_IAPP 0x00000020 +#define HOSTAPD_MODULE_MLME 0x00000040 + +enum hostapd_logger_level { + HOSTAPD_LEVEL_DEBUG_VERBOSE = 0, + HOSTAPD_LEVEL_DEBUG = 1, + HOSTAPD_LEVEL_INFO = 2, + HOSTAPD_LEVEL_NOTICE = 3, + HOSTAPD_LEVEL_WARNING = 4 +}; + + +#ifdef CONFIG_DEBUG_SYSLOG + +void wpa_debug_open_syslog(void); +void wpa_debug_close_syslog(void); + +#else /* CONFIG_DEBUG_SYSLOG */ + +static inline void wpa_debug_open_syslog(void) +{ +} + +static inline void wpa_debug_close_syslog(void) +{ +} + +#endif /* CONFIG_DEBUG_SYSLOG */ + +#ifdef CONFIG_DEBUG_LINUX_TRACING + +int wpa_debug_open_linux_tracing(void); +void wpa_debug_close_linux_tracing(void); + +#else /* CONFIG_DEBUG_LINUX_TRACING */ + +static inline int wpa_debug_open_linux_tracing(void) +{ + return 0; +} + +static inline void wpa_debug_close_linux_tracing(void) +{ +} + +#endif /* CONFIG_DEBUG_LINUX_TRACING */ + + +#ifdef EAPOL_TEST +#define WPA_ASSERT(a) \ + do { \ + if (!(a)) { \ + os_printf("WPA_ASSERT FAILED '" #a "' " \ + "%s %s:%d\n", \ + __FUNCTION__, __FILE__, __LINE__); \ + } \ + } while (0) +#else +#define WPA_ASSERT(a) do { } while (0) +#endif + +const char * debug_level_str(int level); +int str_to_debug_level(const char *s); + +#endif /* WPA_DEBUG_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/utils/wpabuf.c b/beken_os/beken378/func/hostapd-2.5/src/utils/wpabuf.c new file mode 100755 index 0000000..e410d4f --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/utils/wpabuf.c @@ -0,0 +1,309 @@ +/* + * Dynamic data buffer + * Copyright (c) 2007-2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "trace.h" +#include "wpabuf.h" + +#ifdef WPA_TRACE +#define WPABUF_MAGIC 0x51a974e3 + +struct wpabuf_trace { + unsigned int magic; +} __attribute__((aligned(8))); + +static struct wpabuf_trace * wpabuf_get_trace(const struct wpabuf *buf) +{ + return (struct wpabuf_trace *) + ((const u8 *) buf - sizeof(struct wpabuf_trace)); +} +#endif /* WPA_TRACE */ + + +static void wpabuf_overflow(const struct wpabuf *buf, size_t len) +{ +#ifdef WPA_TRACE + struct wpabuf_trace *trace = wpabuf_get_trace(buf); + if (trace->magic != WPABUF_MAGIC) { + wpa_printf(MSG_ERROR, "wpabuf: invalid magic %x", + trace->magic); + } +#endif /* WPA_TRACE */ + wpa_printf(MSG_ERROR, "wpabuf %p (size=%lu used=%lu) overflow len=%lu", + buf, (unsigned long) buf->size, (unsigned long) buf->used, + (unsigned long) len); + wpa_trace_show("wpabuf overflow"); +} + + +int wpabuf_resize(struct wpabuf **_buf, size_t add_len) +{ + struct wpabuf *buf = *_buf; +#ifdef WPA_TRACE + struct wpabuf_trace *trace; +#endif /* WPA_TRACE */ + + if (buf == NULL) { + *_buf = wpabuf_alloc(add_len); + return *_buf == NULL ? -1 : 0; + } + +#ifdef WPA_TRACE + trace = wpabuf_get_trace(buf); + if (trace->magic != WPABUF_MAGIC) { + wpa_printf(MSG_ERROR, "wpabuf: invalid magic %x", + trace->magic); + wpa_trace_show("wpabuf_resize invalid magic"); + } +#endif /* WPA_TRACE */ + + if (buf->used + add_len > buf->size) { + unsigned char *nbuf; + if (buf->flags & WPABUF_FLAG_EXT_DATA) { + nbuf = os_realloc(buf->buf, buf->used + add_len); + if (nbuf == NULL) + return -1; + os_memset(nbuf + buf->used, 0, add_len); + buf->buf = nbuf; + } else { +#ifdef WPA_TRACE + nbuf = os_realloc(trace, sizeof(struct wpabuf_trace) + + sizeof(struct wpabuf) + + buf->used + add_len); + if (nbuf == NULL) + return -1; + trace = (struct wpabuf_trace *) nbuf; + buf = (struct wpabuf *) (trace + 1); + os_memset(nbuf + sizeof(struct wpabuf_trace) + + sizeof(struct wpabuf) + buf->used, 0, + add_len); +#else /* WPA_TRACE */ + nbuf = os_realloc(buf, sizeof(struct wpabuf) + + buf->used + add_len); + if (nbuf == NULL) + return -1; + buf = (struct wpabuf *) nbuf; + os_memset(nbuf + sizeof(struct wpabuf) + buf->used, 0, + add_len); +#endif /* WPA_TRACE */ + buf->buf = (u8 *) (buf + 1); + *_buf = buf; + } + buf->size = buf->used + add_len; + } + + return 0; +} + + +/** + * wpabuf_alloc - Allocate a wpabuf of the given size + * @len: Length for the allocated buffer + * Returns: Buffer to the allocated wpabuf or %NULL on failure + */ +struct wpabuf * wpabuf_alloc(size_t len) +{ +#ifdef WPA_TRACE + struct wpabuf_trace *trace = os_zalloc(sizeof(struct wpabuf_trace) + + sizeof(struct wpabuf) + len); + struct wpabuf *buf; + if (trace == NULL) + return NULL; + trace->magic = WPABUF_MAGIC; + buf = (struct wpabuf *) (trace + 1); +#else /* WPA_TRACE */ + struct wpabuf *buf = os_zalloc(sizeof(struct wpabuf) + len); + if (buf == NULL) + return NULL; +#endif /* WPA_TRACE */ + + buf->size = len; + buf->buf = (u8 *) (buf + 1); + return buf; +} + + +struct wpabuf * wpabuf_alloc_ext_data(u8 *data, size_t len) +{ +#ifdef WPA_TRACE + struct wpabuf_trace *trace = os_zalloc(sizeof(struct wpabuf_trace) + + sizeof(struct wpabuf)); + struct wpabuf *buf; + if (trace == NULL) + return NULL; + trace->magic = WPABUF_MAGIC; + buf = (struct wpabuf *) (trace + 1); +#else /* WPA_TRACE */ + struct wpabuf *buf = os_zalloc(sizeof(struct wpabuf)); + if (buf == NULL) + return NULL; +#endif /* WPA_TRACE */ + + buf->size = len; + buf->used = len; + buf->buf = data; + buf->flags |= WPABUF_FLAG_EXT_DATA; + + return buf; +} + + +struct wpabuf * wpabuf_alloc_copy(const void *data, size_t len) +{ + struct wpabuf *buf = wpabuf_alloc(len); + if (buf) + wpabuf_put_data(buf, data, len); + return buf; +} + + +struct wpabuf * wpabuf_dup(const struct wpabuf *src) +{ + struct wpabuf *buf = wpabuf_alloc(wpabuf_len(src)); + if (buf) + wpabuf_put_data(buf, wpabuf_head(src), wpabuf_len(src)); + return buf; +} + + +/** + * wpabuf_free - Free a wpabuf + * @buf: wpabuf buffer + */ +void wpabuf_free(struct wpabuf *buf) +{ +#ifdef WPA_TRACE + struct wpabuf_trace *trace; + if (buf == NULL) + return; + trace = wpabuf_get_trace(buf); + if (trace->magic != WPABUF_MAGIC) { + wpa_printf(MSG_ERROR, "wpabuf_free: invalid magic %x", + trace->magic); + wpa_trace_show("wpabuf_free magic mismatch"); + } + if (buf->flags & WPABUF_FLAG_EXT_DATA) + os_free(buf->buf); + os_free(trace); +#else /* WPA_TRACE */ + if (buf == NULL) + return; + if (buf->flags & WPABUF_FLAG_EXT_DATA) + os_free(buf->buf); + os_free(buf); +#endif /* WPA_TRACE */ +} + + +void wpabuf_clear_free(struct wpabuf *buf) +{ + if (buf) { + os_memset(wpabuf_mhead(buf), 0, wpabuf_len(buf)); + wpabuf_free(buf); + } +} + + +void * wpabuf_put(struct wpabuf *buf, size_t len) +{ + void *tmp = wpabuf_mhead_u8(buf) + wpabuf_len(buf); + buf->used += len; + if (buf->used > buf->size) { + wpabuf_overflow(buf, len); + } + return tmp; +} + + +/** + * wpabuf_concat - Concatenate two buffers into a newly allocated one + * @a: First buffer + * @b: Second buffer + * Returns: wpabuf with concatenated a + b data or %NULL on failure + * + * Both buffers a and b will be freed regardless of the return value. Input + * buffers can be %NULL which is interpreted as an empty buffer. + */ +struct wpabuf * wpabuf_concat(struct wpabuf *a, struct wpabuf *b) +{ + struct wpabuf *n = NULL; + size_t len = 0; + + if (b == NULL) + return a; + + if (a) + len += wpabuf_len(a); + if (b) + len += wpabuf_len(b); + + n = wpabuf_alloc(len); + if (n) { + if (a) + wpabuf_put_buf(n, a); + if (b) + wpabuf_put_buf(n, b); + } + + wpabuf_free(a); + wpabuf_free(b); + + return n; +} + + +/** + * wpabuf_zeropad - Pad buffer with 0x00 octets (prefix) to specified length + * @buf: Buffer to be padded + * @len: Length for the padded buffer + * Returns: wpabuf padded to len octets or %NULL on failure + * + * If buf is longer than len octets or of same size, it will be returned as-is. + * Otherwise a new buffer is allocated and prefixed with 0x00 octets followed + * by the source data. The source buffer will be freed on error, i.e., caller + * will only be responsible on freeing the returned buffer. If buf is %NULL, + * %NULL will be returned. + */ +struct wpabuf * wpabuf_zeropad(struct wpabuf *buf, size_t len) +{ + struct wpabuf *ret; + size_t blen; + + if (buf == NULL) + return NULL; + + blen = wpabuf_len(buf); + if (blen >= len) + return buf; + + ret = wpabuf_alloc(len); + if (ret) { + os_memset(wpabuf_put(ret, len - blen), 0, len - blen); + wpabuf_put_buf(ret, buf); + } + wpabuf_free(buf); + + return ret; +} + + +void wpabuf_printf(struct wpabuf *buf, char *fmt, ...) +{ + va_list ap; + void *tmp = wpabuf_mhead_u8(buf) + wpabuf_len(buf); + int res; + + va_start(ap, fmt); + res = vsnprintf(tmp, buf->size - buf->used, fmt, ap); + va_end(ap); + if (res < 0 || (size_t) res >= buf->size - buf->used) + wpabuf_overflow(buf, res); + buf->used += res; +} diff --git a/beken_os/beken378/func/hostapd-2.5/src/utils/wpabuf.h b/beken_os/beken378/func/hostapd-2.5/src/utils/wpabuf.h new file mode 100755 index 0000000..47b549b --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/utils/wpabuf.h @@ -0,0 +1,167 @@ +/* + * Dynamic data buffer + * Copyright (c) 2007-2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef WPABUF_H +#define WPABUF_H + +#include "include.h" +#include "mem_pub.h" +#include "str_pub.h" + +/* wpabuf::buf is a pointer to external data */ +#define WPABUF_FLAG_EXT_DATA BIT(0) + +/* + * Internal data structure for wpabuf. Please do not touch this directly from + * elsewhere. This is only defined in header file to allow inline functions + * from this file to access data. + */ +struct wpabuf { + size_t size; /* total size of the allocated buffer */ + size_t used; /* length of data in the buffer */ + u8 *buf; /* pointer to the head of the buffer */ + unsigned int flags; + /* optionally followed by the allocated buffer */ +}; + + +int wpabuf_resize(struct wpabuf **buf, size_t add_len); +struct wpabuf * wpabuf_alloc(size_t len); +struct wpabuf * wpabuf_alloc_ext_data(u8 *data, size_t len); +struct wpabuf * wpabuf_alloc_copy(const void *data, size_t len); +struct wpabuf * wpabuf_dup(const struct wpabuf *src); +void wpabuf_free(struct wpabuf *buf); +void wpabuf_clear_free(struct wpabuf *buf); +void * wpabuf_put(struct wpabuf *buf, size_t len); +struct wpabuf * wpabuf_concat(struct wpabuf *a, struct wpabuf *b); +struct wpabuf * wpabuf_zeropad(struct wpabuf *buf, size_t len); +void wpabuf_printf(struct wpabuf *buf, char *fmt, ...) PRINTF_FORMAT(2, 3); + + +/** + * wpabuf_size - Get the currently allocated size of a wpabuf buffer + * @buf: wpabuf buffer + * Returns: Currently allocated size of the buffer + */ +static inline size_t wpabuf_size(const struct wpabuf *buf) +{ + return buf->size; +} + +/** + * wpabuf_len - Get the current length of a wpabuf buffer data + * @buf: wpabuf buffer + * Returns: Currently used length of the buffer + */ +static inline size_t wpabuf_len(const struct wpabuf *buf) +{ + return buf->used; +} + +/** + * wpabuf_tailroom - Get size of available tail room in the end of the buffer + * @buf: wpabuf buffer + * Returns: Tail room (in bytes) of available space in the end of the buffer + */ +static inline size_t wpabuf_tailroom(const struct wpabuf *buf) +{ + return buf->size - buf->used; +} + +/** + * wpabuf_head - Get pointer to the head of the buffer data + * @buf: wpabuf buffer + * Returns: Pointer to the head of the buffer data + */ +static inline const void * wpabuf_head(const struct wpabuf *buf) +{ + return buf->buf; +} + +static inline const u8 * wpabuf_head_u8(const struct wpabuf *buf) +{ + return wpabuf_head(buf); +} + +/** + * wpabuf_mhead - Get modifiable pointer to the head of the buffer data + * @buf: wpabuf buffer + * Returns: Pointer to the head of the buffer data + */ +static inline void * wpabuf_mhead(struct wpabuf *buf) +{ + return buf->buf; +} + +static inline u8 * wpabuf_mhead_u8(struct wpabuf *buf) +{ + return wpabuf_mhead(buf); +} + +static inline void wpabuf_put_u8(struct wpabuf *buf, u8 data) +{ + u8 *pos = wpabuf_put(buf, 1); + *pos = data; +} + +static inline void wpabuf_put_le16(struct wpabuf *buf, u16 data) +{ + u8 *pos = wpabuf_put(buf, 2); + WPA_PUT_LE16(pos, data); +} + +static inline void wpabuf_put_le32(struct wpabuf *buf, u32 data) +{ + u8 *pos = wpabuf_put(buf, 4); + WPA_PUT_LE32(pos, data); +} + +static inline void wpabuf_put_be16(struct wpabuf *buf, u16 data) +{ + u8 *pos = wpabuf_put(buf, 2); + WPA_PUT_BE16(pos, data); +} + +static inline void wpabuf_put_be24(struct wpabuf *buf, u32 data) +{ + u8 *pos = wpabuf_put(buf, 3); + WPA_PUT_BE24(pos, data); +} + +static inline void wpabuf_put_be32(struct wpabuf *buf, u32 data) +{ + u8 *pos = wpabuf_put(buf, 4); + WPA_PUT_BE32(pos, data); +} + +static inline void wpabuf_put_data(struct wpabuf *buf, const void *data, + size_t len) +{ + if (data) + os_memcpy(wpabuf_put(buf, len), data, len); +} + +static inline void wpabuf_put_buf(struct wpabuf *dst, + const struct wpabuf *src) +{ + wpabuf_put_data(dst, wpabuf_head(src), wpabuf_len(src)); +} + +static inline void wpabuf_set(struct wpabuf *buf, const void *data, size_t len) +{ + buf->buf = (u8 *) data; + buf->flags = WPABUF_FLAG_EXT_DATA; + buf->size = buf->used = len; +} + +static inline void wpabuf_put_str(struct wpabuf *dst, const char *str) +{ + wpabuf_put_data(dst, str, os_strlen(str)); +} + +#endif /* WPABUF_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/wps/http.h b/beken_os/beken378/func/hostapd-2.5/src/wps/http.h new file mode 100755 index 0000000..2fee3a8 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/wps/http.h @@ -0,0 +1,29 @@ +/* + * HTTP for WPS + * Copyright (c) 2000-2003 Intel Corporation + * Copyright (c) 2006-2007 Sony Corporation + * Copyright (c) 2008-2009 Atheros Communications + * Copyright (c) 2009, Jouni Malinen + * + * See wps_upnp.c for more details on licensing and code history. + */ + +#ifndef HTTP_H +#define HTTP_H + +enum http_reply_code { + HTTP_OK = 200, + HTTP_BAD_REQUEST = 400, + UPNP_INVALID_ACTION = 401, + UPNP_INVALID_ARGS = 402, + HTTP_NOT_FOUND = 404, + HTTP_PRECONDITION_FAILED = 412, + HTTP_INTERNAL_SERVER_ERROR = 500, + HTTP_UNIMPLEMENTED = 501, + UPNP_ACTION_FAILED = 501, + UPNP_ARG_VALUE_INVALID = 600, + UPNP_ARG_VALUE_OUT_OF_RANGE = 601, + UPNP_OUT_OF_MEMORY = 603 +}; + +#endif /* HTTP_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/wps/http_client.h b/beken_os/beken378/func/hostapd-2.5/src/wps/http_client.h new file mode 100755 index 0000000..ddee2ad --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/wps/http_client.h @@ -0,0 +1,40 @@ +/* + * http_client - HTTP client + * Copyright (c) 2009, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef HTTP_CLIENT_H +#define HTTP_CLIENT_H + +struct http_client; + +enum http_client_event { + HTTP_CLIENT_FAILED, + HTTP_CLIENT_TIMEOUT, + HTTP_CLIENT_OK, + HTTP_CLIENT_INVALID_REPLY, +}; + +char * http_client_url_parse(const char *url, struct sockaddr_in *dst, + char **path); +struct http_client * http_client_addr(struct sockaddr_in *dst, + struct wpabuf *req, size_t max_response, + void (*cb)(void *ctx, + struct http_client *c, + enum http_client_event event), + void *cb_ctx); +struct http_client * http_client_url(const char *url, + struct wpabuf *req, size_t max_response, + void (*cb)(void *ctx, + struct http_client *c, + enum http_client_event event), + void *cb_ctx); +void http_client_free(struct http_client *c); +struct wpabuf * http_client_get_body(struct http_client *c); +char * http_client_get_hdr_line(struct http_client *c, const char *tag); +char * http_link_update(char *url, const char *base); + +#endif /* HTTP_CLIENT_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/wps/http_server.h b/beken_os/beken378/func/hostapd-2.5/src/wps/http_server.h new file mode 100755 index 0000000..4b2b749 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/wps/http_server.h @@ -0,0 +1,33 @@ +/* + * http_server - HTTP server + * Copyright (c) 2009, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef HTTP_SERVER_H +#define HTTP_SERVER_H + +struct http_server; +struct http_request; + +void http_request_deinit(struct http_request *req); +void http_request_send(struct http_request *req, struct wpabuf *resp); +void http_request_send_and_deinit(struct http_request *req, + struct wpabuf *resp); +enum httpread_hdr_type http_request_get_type(struct http_request *req); +char * http_request_get_uri(struct http_request *req); +char * http_request_get_hdr(struct http_request *req); +char * http_request_get_data(struct http_request *req); +char * http_request_get_hdr_line(struct http_request *req, const char *tag); +struct sockaddr_in * http_request_get_cli_addr(struct http_request *req); + +struct http_server * http_server_init(struct in_addr *addr, int port, + void (*cb)(void *ctx, + struct http_request *req), + void *cb_ctx); +void http_server_deinit(struct http_server *srv); +int http_server_get_port(struct http_server *srv); + +#endif /* HTTP_SERVER_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/wps/httpread.h b/beken_os/beken378/func/hostapd-2.5/src/wps/httpread.h new file mode 100755 index 0000000..454b618 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/wps/httpread.h @@ -0,0 +1,117 @@ +/* + * httpread - Manage reading file(s) from HTTP/TCP socket + * Author: Ted Merrill + * Copyright 2008 Atheros Communications + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef HTTPREAD_H +#define HTTPREAD_H + +/* event types (passed to callback) */ +enum httpread_event { + HTTPREAD_EVENT_FILE_READY = 1, /* including reply ready */ + HTTPREAD_EVENT_TIMEOUT = 2, + HTTPREAD_EVENT_ERROR = 3 /* misc. error, esp malloc error */ +}; + + +/* header type detected + * available to callback via call to httpread_reply_code_get() + */ +enum httpread_hdr_type { + HTTPREAD_HDR_TYPE_UNKNOWN = 0, /* none of the following */ + HTTPREAD_HDR_TYPE_REPLY = 1, /* hdr begins w/ HTTP/ */ + HTTPREAD_HDR_TYPE_GET = 2, /* hdr begins with GET */ + HTTPREAD_HDR_TYPE_HEAD = 3, /* hdr begins with HEAD */ + HTTPREAD_HDR_TYPE_POST = 4, /* hdr begins with POST */ + HTTPREAD_HDR_TYPE_PUT = 5, /* hdr begins with ... */ + HTTPREAD_HDR_TYPE_DELETE = 6, /* hdr begins with ... */ + HTTPREAD_HDR_TYPE_TRACE = 7, /* hdr begins with ... */ + HTTPREAD_HDR_TYPE_CONNECT = 8, /* hdr begins with ... */ + HTTPREAD_HDR_TYPE_NOTIFY = 9, /* hdr begins with ... */ + HTTPREAD_HDR_TYPE_M_SEARCH = 10, /* hdr begins with ... */ + HTTPREAD_HDR_TYPE_M_POST = 11, /* hdr begins with ... */ + HTTPREAD_HDR_TYPE_SUBSCRIBE = 12, /* hdr begins with ... */ + HTTPREAD_HDR_TYPE_UNSUBSCRIBE = 13, /* hdr begins with ... */ + + HTTPREAD_N_HDR_TYPES /* keep last */ +}; + + +/* control instance -- opaque struct declaration + */ +struct httpread; + + +/* httpread_destroy -- if h is non-NULL, clean up + * This must eventually be called by the application following + * call of the application's callback and may be called + * earlier if desired. + */ +void httpread_destroy(struct httpread *h); + +/* httpread_create -- start a new reading session making use of eloop. + * The new instance will use the socket descriptor for reading (until + * it gets a file and not after) but will not close the socket, even + * when the instance is destroyed (the application must do that). + * Return NULL on error. + * + * Provided that httpread_create successfully returns a handle, + * the callback fnc is called to handle httpread_event events. + * The caller should do destroy on any errors or unknown events. + * + * Pass max_bytes == 0 to not read body at all (required for e.g. + * reply to HEAD request). + */ +struct httpread * httpread_create( + int sd, /* descriptor of TCP socket to read from */ + void (*cb)(struct httpread *handle, void *cookie, + enum httpread_event e), /* call on event */ + void *cookie, /* pass to callback */ + int max_bytes, /* maximum file size else abort it */ + int timeout_seconds /* 0; or total duration timeout period */ + ); + +/* httpread_hdr_type_get -- When file is ready, returns header type. + */ +enum httpread_hdr_type httpread_hdr_type_get(struct httpread *h); + + +/* httpread_uri_get -- When file is ready, uri_get returns (translated) URI + * or possibly NULL (which would be an error). + */ +char *httpread_uri_get(struct httpread *h); + +/* httpread_reply_code_get -- When reply is ready, returns reply code */ +int httpread_reply_code_get(struct httpread *h); + + +/* httpread_length_get -- When file is ready, returns file length. */ +int httpread_length_get(struct httpread *h); + +/* httpread_data_get -- When file is ready, returns file content + * with null byte appened. + * Might return NULL in some error condition. + */ +void * httpread_data_get(struct httpread *h); + +/* httpread_hdr_get -- When file is ready, returns header content + * with null byte appended. + * Might return NULL in some error condition. + */ +char * httpread_hdr_get(struct httpread *h); + +/* httpread_hdr_line_get -- When file is ready, returns pointer + * to line within header content matching the given tag + * (after the tag itself and any spaces/tabs). + * + * The tag should end with a colon for reliable matching. + * + * If not found, returns NULL; + */ +char * httpread_hdr_line_get(struct httpread *h, const char *tag); + +#endif /* HTTPREAD_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/wps/upnp_xml.h b/beken_os/beken378/func/hostapd-2.5/src/wps/upnp_xml.h new file mode 100755 index 0000000..616af3d --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/wps/upnp_xml.h @@ -0,0 +1,25 @@ +/* + * UPnP XML helper routines + * Copyright (c) 2000-2003 Intel Corporation + * Copyright (c) 2006-2007 Sony Corporation + * Copyright (c) 2008-2009 Atheros Communications + * Copyright (c) 2009, Jouni Malinen + * + * See wps_upnp.c for more details on licensing and code history. + */ + +#ifndef UPNP_XML_H +#define UPNP_XML_H + +#include "http.h" + +void xml_data_encode(struct wpabuf *buf, const char *data, int len); +void xml_add_tagged_data(struct wpabuf *buf, const char *tag, + const char *data); +int xml_next_tag(const char *in, const char **out, + const char **out_tagname, const char **end); +char * xml_get_first_item(const char *doc, const char *item); +struct wpabuf * xml_get_base64_item(const char *data, const char *name, + enum http_reply_code *ret); + +#endif /* UPNP_XML_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/wps/wps.h b/beken_os/beken378/func/hostapd-2.5/src/wps/wps.h new file mode 100755 index 0000000..2c91d16 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/wps/wps.h @@ -0,0 +1,1041 @@ +/* + * Wi-Fi Protected Setup + * Copyright (c) 2007-2013, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef WPS_H +#define WPS_H + +#include "common/ieee802_11_defs.h" +#include "wps_defs.h" + +/** + * enum wsc_op_code - EAP-WSC OP-Code values + */ +enum wsc_op_code { + WSC_UPnP = 0 /* No OP Code in UPnP transport */, + WSC_Start = 0x01, + WSC_ACK = 0x02, + WSC_NACK = 0x03, + WSC_MSG = 0x04, + WSC_Done = 0x05, + WSC_FRAG_ACK = 0x06 +}; + +struct wps_registrar; +struct upnp_wps_device_sm; +struct wps_er; +struct wps_parse_attr; + +/** + * struct wps_credential - WPS Credential + * @ssid: SSID + * @ssid_len: Length of SSID + * @auth_type: Authentication Type (WPS_AUTH_OPEN, .. flags) + * @encr_type: Encryption Type (WPS_ENCR_NONE, .. flags) + * @key_idx: Key index + * @key: Key + * @key_len: Key length in octets + * @mac_addr: MAC address of the Credential receiver + * @cred_attr: Unparsed Credential attribute data (used only in cred_cb()); + * this may be %NULL, if not used + * @cred_attr_len: Length of cred_attr in octets + */ +struct wps_credential { + u8 ssid[SSID_MAX_LEN]; + size_t ssid_len; + u16 auth_type; + u16 encr_type; + u8 key_idx; + u8 key[64]; + size_t key_len; + u8 mac_addr[ETH_ALEN]; + const u8 *cred_attr; + size_t cred_attr_len; +}; + +#define WPS_DEV_TYPE_LEN 8 +#define WPS_DEV_TYPE_BUFSIZE 21 +#define WPS_SEC_DEV_TYPE_MAX_LEN 128 +/* maximum number of advertised WPS vendor extension attributes */ +#define MAX_WPS_VENDOR_EXTENSIONS 10 +/* maximum size of WPS Vendor extension attribute */ +#define WPS_MAX_VENDOR_EXT_LEN 1024 +/* maximum number of parsed WPS vendor extension attributes */ +#define MAX_WPS_PARSE_VENDOR_EXT 10 + +/** + * struct wps_device_data - WPS Device Data + * @mac_addr: Device MAC address + * @device_name: Device Name (0..32 octets encoded in UTF-8) + * @manufacturer: Manufacturer (0..64 octets encoded in UTF-8) + * @model_name: Model Name (0..32 octets encoded in UTF-8) + * @model_number: Model Number (0..32 octets encoded in UTF-8) + * @serial_number: Serial Number (0..32 octets encoded in UTF-8) + * @pri_dev_type: Primary Device Type + * @sec_dev_type: Array of secondary device types + * @num_sec_dev_type: Number of secondary device types + * @os_version: OS Version + * @rf_bands: RF bands (WPS_RF_24GHZ, WPS_RF_50GHZ, WPS_RF_60GHZ flags) + * @p2p: Whether the device is a P2P device + */ +struct wps_device_data { + u8 mac_addr[ETH_ALEN]; + char *device_name; + char *manufacturer; + char *model_name; + char *model_number; + char *serial_number; + u8 pri_dev_type[WPS_DEV_TYPE_LEN]; +#define WPS_SEC_DEVICE_TYPES 5 + u8 sec_dev_type[WPS_SEC_DEVICE_TYPES][WPS_DEV_TYPE_LEN]; + u8 num_sec_dev_types; + u32 os_version; + u8 rf_bands; + u16 config_methods; + struct wpabuf *vendor_ext_m1; + struct wpabuf *vendor_ext[MAX_WPS_VENDOR_EXTENSIONS]; + + int p2p; +}; + +/** + * struct wps_config - WPS configuration for a single registration protocol run + */ +struct wps_config { + /** + * wps - Pointer to long term WPS context + */ + struct wps_context *wps; + + /** + * registrar - Whether this end is a Registrar + */ + int registrar; + + /** + * pin - Enrollee Device Password (%NULL for Registrar or PBC) + */ + const u8 *pin; + + /** + * pin_len - Length on pin in octets + */ + size_t pin_len; + + /** + * pbc - Whether this is protocol run uses PBC + */ + int pbc; + + /** + * assoc_wps_ie: (Re)AssocReq WPS IE (in AP; %NULL if not AP) + */ + const struct wpabuf *assoc_wps_ie; + + /** + * new_ap_settings - New AP settings (%NULL if not used) + * + * This parameter provides new AP settings when using a wireless + * stations as a Registrar to configure the AP. %NULL means that AP + * will not be reconfigured, i.e., the station will only learn the + * current AP settings by using AP PIN. + */ + const struct wps_credential *new_ap_settings; + + /** + * peer_addr: MAC address of the peer in AP; %NULL if not AP + */ + const u8 *peer_addr; + + /** + * use_psk_key - Use PSK format key in Credential + * + * Force PSK format to be used instead of ASCII passphrase when + * building Credential for an Enrollee. The PSK value is set in + * struct wpa_context::psk. + */ + int use_psk_key; + + /** + * dev_pw_id - Device Password ID for Enrollee when PIN is used + */ + u16 dev_pw_id; + + /** + * p2p_dev_addr - P2P Device Address from (Re)Association Request + * + * On AP/GO, this is set to the P2P Device Address of the associating + * P2P client if a P2P IE is included in the (Re)Association Request + * frame and the P2P Device Address is included. Otherwise, this is set + * to %NULL to indicate the station does not have a P2P Device Address. + */ + const u8 *p2p_dev_addr; + + /** + * pbc_in_m1 - Do not remove PushButton config method in M1 (AP) + * + * This can be used to enable a workaround to allow Windows 7 to use + * PBC with the AP. + */ + int pbc_in_m1; + + /** + * peer_pubkey_hash - Peer public key hash or %NULL if not known + */ + const u8 *peer_pubkey_hash; +}; + +struct wps_data * wps_init(const struct wps_config *cfg); + +void wps_deinit(struct wps_data *data); + +/** + * enum wps_process_res - WPS message processing result + */ +enum wps_process_res { + /** + * WPS_DONE - Processing done + */ + WPS_DONE, + + /** + * WPS_CONTINUE - Processing continues + */ + WPS_CONTINUE, + + /** + * WPS_FAILURE - Processing failed + */ + WPS_FAILURE, + + /** + * WPS_PENDING - Processing continues, but waiting for an external + * event (e.g., UPnP message from an external Registrar) + */ + WPS_PENDING +}; +enum wps_process_res wps_process_msg(struct wps_data *wps, + enum wsc_op_code op_code, + const struct wpabuf *msg); + +struct wpabuf * wps_get_msg(struct wps_data *wps, enum wsc_op_code *op_code); + +int wps_is_selected_pbc_registrar(const struct wpabuf *msg); +int wps_is_selected_pin_registrar(const struct wpabuf *msg); +int wps_ap_priority_compar(const struct wpabuf *wps_a, + const struct wpabuf *wps_b); +int wps_is_addr_authorized(const struct wpabuf *msg, const u8 *addr, + int ver1_compat); +const u8 * wps_get_uuid_e(const struct wpabuf *msg); +int wps_is_20(const struct wpabuf *msg); + +struct wpabuf * wps_build_assoc_req_ie(enum wps_request_type req_type); +struct wpabuf * wps_build_assoc_resp_ie(void); +struct wpabuf * wps_build_probe_req_ie(u16 pw_id, struct wps_device_data *dev, + const u8 *uuid, + enum wps_request_type req_type, + unsigned int num_req_dev_types, + const u8 *req_dev_types); + + +/** + * struct wps_registrar_config - WPS Registrar configuration + */ +struct wps_registrar_config { + /** + * new_psk_cb - Callback for new PSK + * @ctx: Higher layer context data (cb_ctx) + * @mac_addr: MAC address of the Enrollee + * @p2p_dev_addr: P2P Device Address of the Enrollee or all zeros if not + * @psk: The new PSK + * @psk_len: The length of psk in octets + * Returns: 0 on success, -1 on failure + * + * This callback is called when a new per-device PSK is provisioned. + */ + int (*new_psk_cb)(void *ctx, const u8 *mac_addr, const u8 *p2p_dev_addr, + const u8 *psk, size_t psk_len); + + /** + * set_ie_cb - Callback for WPS IE changes + * @ctx: Higher layer context data (cb_ctx) + * @beacon_ie: WPS IE for Beacon + * @probe_resp_ie: WPS IE for Probe Response + * Returns: 0 on success, -1 on failure + * + * This callback is called whenever the WPS IE in Beacon or Probe + * Response frames needs to be changed (AP only). Callee is responsible + * for freeing the buffers. + */ + int (*set_ie_cb)(void *ctx, struct wpabuf *beacon_ie, + struct wpabuf *probe_resp_ie); + + /** + * pin_needed_cb - Callback for requesting a PIN + * @ctx: Higher layer context data (cb_ctx) + * @uuid_e: UUID-E of the unknown Enrollee + * @dev: Device Data from the unknown Enrollee + * + * This callback is called whenever an unknown Enrollee requests to use + * PIN method and a matching PIN (Device Password) is not found in + * Registrar data. + */ + void (*pin_needed_cb)(void *ctx, const u8 *uuid_e, + const struct wps_device_data *dev); + + /** + * reg_success_cb - Callback for reporting successful registration + * @ctx: Higher layer context data (cb_ctx) + * @mac_addr: MAC address of the Enrollee + * @uuid_e: UUID-E of the Enrollee + * @dev_pw: Device Password (PIN) used during registration + * @dev_pw_len: Length of dev_pw in octets + * + * This callback is called whenever an Enrollee completes registration + * successfully. + */ + void (*reg_success_cb)(void *ctx, const u8 *mac_addr, + const u8 *uuid_e, const u8 *dev_pw, + size_t dev_pw_len); + + /** + * set_sel_reg_cb - Callback for reporting selected registrar changes + * @ctx: Higher layer context data (cb_ctx) + * @sel_reg: Whether the Registrar is selected + * @dev_passwd_id: Device Password ID to indicate with method or + * specific password the Registrar intends to use + * @sel_reg_config_methods: Bit field of active config methods + * + * This callback is called whenever the Selected Registrar state + * changes (e.g., a new PIN becomes available or PBC is invoked). This + * callback is only used by External Registrar implementation; + * set_ie_cb() is used by AP implementation in similar caes, but it + * provides the full WPS IE data instead of just the minimal Registrar + * state information. + */ + void (*set_sel_reg_cb)(void *ctx, int sel_reg, u16 dev_passwd_id, + u16 sel_reg_config_methods); + + /** + * enrollee_seen_cb - Callback for reporting Enrollee based on ProbeReq + * @ctx: Higher layer context data (cb_ctx) + * @addr: MAC address of the Enrollee + * @uuid_e: UUID of the Enrollee + * @pri_dev_type: Primary device type + * @config_methods: Config Methods + * @dev_password_id: Device Password ID + * @request_type: Request Type + * @dev_name: Device Name (if available) + */ + void (*enrollee_seen_cb)(void *ctx, const u8 *addr, const u8 *uuid_e, + const u8 *pri_dev_type, u16 config_methods, + u16 dev_password_id, u8 request_type, + const char *dev_name); + + /** + * cb_ctx: Higher layer context data for Registrar callbacks + */ + void *cb_ctx; + + /** + * skip_cred_build: Do not build credential + * + * This option can be used to disable internal code that builds + * Credential attribute into M8 based on the current network + * configuration and Enrollee capabilities. The extra_cred data will + * then be used as the Credential(s). + */ + int skip_cred_build; + + /** + * extra_cred: Additional Credential attribute(s) + * + * This optional data (set to %NULL to disable) can be used to add + * Credential attribute(s) for other networks into M8. If + * skip_cred_build is set, this will also override the automatically + * generated Credential attribute. + */ + const u8 *extra_cred; + + /** + * extra_cred_len: Length of extra_cred in octets + */ + size_t extra_cred_len; + + /** + * disable_auto_conf - Disable auto-configuration on first registration + * + * By default, the AP that is started in not configured state will + * generate a random PSK and move to configured state when the first + * registration protocol run is completed successfully. This option can + * be used to disable this functionality and leave it up to an external + * program to take care of configuration. This requires the extra_cred + * to be set with a suitable Credential and skip_cred_build being used. + */ + int disable_auto_conf; + + /** + * static_wep_only - Whether the BSS supports only static WEP + */ + int static_wep_only; + + /** + * dualband - Whether this is a concurrent dualband AP + */ + int dualband; + + /** + * force_per_enrollee_psk - Force per-Enrollee random PSK + * + * This forces per-Enrollee random PSK to be generated even if a default + * PSK is set for a network. + */ + int force_per_enrollee_psk; +}; + + +/** + * enum wps_event - WPS event types + */ +enum wps_event { + /** + * WPS_EV_M2D - M2D received (Registrar did not know us) + */ + WPS_EV_M2D, + + /** + * WPS_EV_FAIL - Registration failed + */ + WPS_EV_FAIL, + + /** + * WPS_EV_SUCCESS - Registration succeeded + */ + WPS_EV_SUCCESS, + + /** + * WPS_EV_PWD_AUTH_FAIL - Password authentication failed + */ + WPS_EV_PWD_AUTH_FAIL, + + /** + * WPS_EV_PBC_OVERLAP - PBC session overlap detected + */ + WPS_EV_PBC_OVERLAP, + + /** + * WPS_EV_PBC_TIMEOUT - PBC walktime expired before protocol run start + */ + WPS_EV_PBC_TIMEOUT, + + /** + * WPS_EV_PBC_ACTIVE - PBC mode was activated + */ + WPS_EV_PBC_ACTIVE, + + /** + * WPS_EV_PBC_DISABLE - PBC mode was disabled + */ + WPS_EV_PBC_DISABLE, + + /** + * WPS_EV_ER_AP_ADD - ER: AP added + */ + WPS_EV_ER_AP_ADD, + + /** + * WPS_EV_ER_AP_REMOVE - ER: AP removed + */ + WPS_EV_ER_AP_REMOVE, + + /** + * WPS_EV_ER_ENROLLEE_ADD - ER: Enrollee added + */ + WPS_EV_ER_ENROLLEE_ADD, + + /** + * WPS_EV_ER_ENROLLEE_REMOVE - ER: Enrollee removed + */ + WPS_EV_ER_ENROLLEE_REMOVE, + + /** + * WPS_EV_ER_AP_SETTINGS - ER: AP Settings learned + */ + WPS_EV_ER_AP_SETTINGS, + + /** + * WPS_EV_ER_SET_SELECTED_REGISTRAR - ER: SetSelectedRegistrar event + */ + WPS_EV_ER_SET_SELECTED_REGISTRAR, + + /** + * WPS_EV_AP_PIN_SUCCESS - External Registrar used correct AP PIN + */ + WPS_EV_AP_PIN_SUCCESS +}; + +/** + * union wps_event_data - WPS event data + */ +union wps_event_data { + /** + * struct wps_event_m2d - M2D event data + */ + struct wps_event_m2d { + u16 config_methods; + const u8 *manufacturer; + size_t manufacturer_len; + const u8 *model_name; + size_t model_name_len; + const u8 *model_number; + size_t model_number_len; + const u8 *serial_number; + size_t serial_number_len; + const u8 *dev_name; + size_t dev_name_len; + const u8 *primary_dev_type; /* 8 octets */ + u16 config_error; + u16 dev_password_id; + } m2d; + + /** + * struct wps_event_fail - Registration failure information + * @msg: enum wps_msg_type + */ + struct wps_event_fail { + int msg; + u16 config_error; + u16 error_indication; + u8 peer_macaddr[ETH_ALEN]; + } fail; + + struct wps_event_success { + u8 peer_macaddr[ETH_ALEN]; + } success; + + struct wps_event_pwd_auth_fail { + int enrollee; + int part; + u8 peer_macaddr[ETH_ALEN]; + } pwd_auth_fail; + + struct wps_event_er_ap { + const u8 *uuid; + const u8 *mac_addr; + const char *friendly_name; + const char *manufacturer; + const char *manufacturer_url; + const char *model_description; + const char *model_name; + const char *model_number; + const char *model_url; + const char *serial_number; + const char *upc; + const u8 *pri_dev_type; + u8 wps_state; + } ap; + + struct wps_event_er_enrollee { + const u8 *uuid; + const u8 *mac_addr; + int m1_received; + u16 config_methods; + u16 dev_passwd_id; + const u8 *pri_dev_type; + const char *dev_name; + const char *manufacturer; + const char *model_name; + const char *model_number; + const char *serial_number; + } enrollee; + + struct wps_event_er_ap_settings { + const u8 *uuid; + const struct wps_credential *cred; + } ap_settings; + + struct wps_event_er_set_selected_registrar { + const u8 *uuid; + int sel_reg; + u16 dev_passwd_id; + u16 sel_reg_config_methods; + enum { + WPS_ER_SET_SEL_REG_START, + WPS_ER_SET_SEL_REG_DONE, + WPS_ER_SET_SEL_REG_FAILED + } state; + } set_sel_reg; +}; + +/** + * struct upnp_pending_message - Pending PutWLANResponse messages + * @next: Pointer to next pending message or %NULL + * @addr: NewWLANEventMAC + * @msg: NewMessage + * @type: Message Type + */ +struct upnp_pending_message { + struct upnp_pending_message *next; + u8 addr[ETH_ALEN]; + struct wpabuf *msg; + enum wps_msg_type type; +}; + +/** + * struct wps_context - Long term WPS context data + * + * This data is stored at the higher layer Authenticator or Supplicant data + * structures and it is maintained over multiple registration protocol runs. + */ +struct wps_context { + /** + * ap - Whether the local end is an access point + */ + int ap; + + /** + * registrar - Pointer to WPS registrar data from wps_registrar_init() + */ + struct wps_registrar *registrar; + + /** + * wps_state - Current WPS state + */ + enum wps_state wps_state; + + /** + * ap_setup_locked - Whether AP setup is locked (only used at AP) + */ + int ap_setup_locked; + + /** + * uuid - Own UUID + */ + u8 uuid[16]; + + /** + * ssid - SSID + * + * This SSID is used by the Registrar to fill in information for + * Credentials. In addition, AP uses it when acting as an Enrollee to + * notify Registrar of the current configuration. + */ + u8 ssid[SSID_MAX_LEN]; + + /** + * ssid_len - Length of ssid in octets + */ + size_t ssid_len; + + /** + * dev - Own WPS device data + */ + struct wps_device_data dev; + + /** + * dh_ctx - Context data for Diffie-Hellman operation + */ + void *dh_ctx; + + /** + * dh_privkey - Diffie-Hellman private key + */ + struct wpabuf *dh_privkey; + + /** + * dh_pubkey_oob - Diffie-Hellman public key + */ + struct wpabuf *dh_pubkey; + + /** + * config_methods - Enabled configuration methods + * + * Bit field of WPS_CONFIG_* + */ + u16 config_methods; + + /** + * encr_types - Enabled encryption types (bit field of WPS_ENCR_*) + */ + u16 encr_types; + + /** + * auth_types - Authentication types (bit field of WPS_AUTH_*) + */ + u16 auth_types; + + /** + * encr_types - Current AP encryption type (WPS_ENCR_*) + */ + u16 ap_encr_type; + + /** + * ap_auth_type - Current AP authentication types (WPS_AUTH_*) + */ + u16 ap_auth_type; + + /** + * network_key - The current Network Key (PSK) or %NULL to generate new + * + * If %NULL, Registrar will generate per-device PSK. In addition, AP + * uses this when acting as an Enrollee to notify Registrar of the + * current configuration. + * + * When using WPA/WPA2-Person, this key can be either the ASCII + * passphrase (8..63 characters) or the 32-octet PSK (64 hex + * characters). When this is set to the ASCII passphrase, the PSK can + * be provided in the psk buffer and used per-Enrollee to control which + * key type is included in the Credential (e.g., to reduce calculation + * need on low-powered devices by provisioning PSK while still allowing + * other devices to get the passphrase). + */ + u8 *network_key; + + /** + * network_key_len - Length of network_key in octets + */ + size_t network_key_len; + + /** + * psk - The current network PSK + * + * This optional value can be used to provide the current PSK if + * network_key is set to the ASCII passphrase. + */ + u8 psk[32]; + + /** + * psk_set - Whether psk value is set + */ + int psk_set; + + /** + * ap_settings - AP Settings override for M7 (only used at AP) + * + * If %NULL, AP Settings attributes will be generated based on the + * current network configuration. + */ + u8 *ap_settings; + + /** + * ap_settings_len - Length of ap_settings in octets + */ + size_t ap_settings_len; + + /** + * friendly_name - Friendly Name (required for UPnP) + */ + char *friendly_name; + + /** + * manufacturer_url - Manufacturer URL (optional for UPnP) + */ + char *manufacturer_url; + + /** + * model_description - Model Description (recommended for UPnP) + */ + char *model_description; + + /** + * model_url - Model URL (optional for UPnP) + */ + char *model_url; + + /** + * upc - Universal Product Code (optional for UPnP) + */ + char *upc; + + /** + * cred_cb - Callback to notify that new Credentials were received + * @ctx: Higher layer context data (cb_ctx) + * @cred: The received Credential + * Return: 0 on success, -1 on failure + */ + int (*cred_cb)(void *ctx, const struct wps_credential *cred); + + /** + * event_cb - Event callback (state information about progress) + * @ctx: Higher layer context data (cb_ctx) + * @event: Event type + * @data: Event data + */ + void (*event_cb)(void *ctx, enum wps_event event, + union wps_event_data *data); + + /** + * rf_band_cb - Fetch currently used RF band + * @ctx: Higher layer context data (cb_ctx) + * Return: Current used RF band or 0 if not known + */ + int (*rf_band_cb)(void *ctx); + + /** + * cb_ctx: Higher layer context data for callbacks + */ + void *cb_ctx; + + struct upnp_wps_device_sm *wps_upnp; + + /* Pending messages from UPnP PutWLANResponse */ + struct upnp_pending_message *upnp_msgs; + + u16 ap_nfc_dev_pw_id; + struct wpabuf *ap_nfc_dh_pubkey; + struct wpabuf *ap_nfc_dh_privkey; + struct wpabuf *ap_nfc_dev_pw; +}; + +struct wps_registrar * +wps_registrar_init(struct wps_context *wps, + const struct wps_registrar_config *cfg); +void wps_registrar_deinit(struct wps_registrar *reg); +int wps_registrar_add_pin(struct wps_registrar *reg, const u8 *addr, + const u8 *uuid, const u8 *pin, size_t pin_len, + int timeout); +int wps_registrar_invalidate_pin(struct wps_registrar *reg, const u8 *uuid); +int wps_registrar_wps_cancel(struct wps_registrar *reg); +int wps_registrar_unlock_pin(struct wps_registrar *reg, const u8 *uuid); +int wps_registrar_button_pushed(struct wps_registrar *reg, + const u8 *p2p_dev_addr); +void wps_registrar_complete(struct wps_registrar *registrar, const u8 *uuid_e, + const u8 *dev_pw, size_t dev_pw_len); +void wps_registrar_probe_req_rx(struct wps_registrar *reg, const u8 *addr, + const struct wpabuf *wps_data, + int p2p_wildcard); +int wps_registrar_update_ie(struct wps_registrar *reg); +int wps_registrar_get_info(struct wps_registrar *reg, const u8 *addr, + char *buf, size_t buflen); +int wps_registrar_config_ap(struct wps_registrar *reg, + struct wps_credential *cred); +int wps_registrar_add_nfc_pw_token(struct wps_registrar *reg, + const u8 *pubkey_hash, u16 pw_id, + const u8 *dev_pw, size_t dev_pw_len, + int pk_hash_provided_oob); +int wps_registrar_add_nfc_password_token(struct wps_registrar *reg, + const u8 *oob_dev_pw, + size_t oob_dev_pw_len); +void wps_registrar_flush(struct wps_registrar *reg); + +int wps_build_credential_wrap(struct wpabuf *msg, + const struct wps_credential *cred); + +unsigned int wps_pin_checksum(unsigned int pin); +unsigned int wps_pin_valid(unsigned int pin); +unsigned int wps_generate_pin(void); +int wps_pin_str_valid(const char *pin); +void wps_free_pending_msgs(struct upnp_pending_message *msgs); + +struct wpabuf * wps_get_oob_cred(struct wps_context *wps, int rf_band, + int channel); +int wps_oob_use_cred(struct wps_context *wps, struct wps_parse_attr *attr); +int wps_attr_text(struct wpabuf *data, char *buf, char *end); +const char * wps_ei_str(enum wps_error_indication ei); + +struct wps_er * wps_er_init(struct wps_context *wps, const char *ifname, + const char *filter); +void wps_er_refresh(struct wps_er *er); +void wps_er_deinit(struct wps_er *er, void (*cb)(void *ctx), void *ctx); +void wps_er_set_sel_reg(struct wps_er *er, int sel_reg, u16 dev_passwd_id, + u16 sel_reg_config_methods); +int wps_er_pbc(struct wps_er *er, const u8 *uuid, const u8 *addr); +const u8 * wps_er_get_sta_uuid(struct wps_er *er, const u8 *addr); +int wps_er_learn(struct wps_er *er, const u8 *uuid, const u8 *addr, + const u8 *pin, size_t pin_len); +int wps_er_set_config(struct wps_er *er, const u8 *uuid, const u8 *addr, + const struct wps_credential *cred); +int wps_er_config(struct wps_er *er, const u8 *uuid, const u8 *addr, + const u8 *pin, size_t pin_len, + const struct wps_credential *cred); +struct wpabuf * wps_er_config_token_from_cred(struct wps_context *wps, + struct wps_credential *cred); +struct wpabuf * wps_er_nfc_config_token(struct wps_er *er, const u8 *uuid, + const u8 *addr); +struct wpabuf * wps_er_nfc_handover_sel(struct wps_er *er, + struct wps_context *wps, const u8 *uuid, + const u8 *addr, struct wpabuf *pubkey); + +int wps_dev_type_str2bin(const char *str, u8 dev_type[WPS_DEV_TYPE_LEN]); +char * wps_dev_type_bin2str(const u8 dev_type[WPS_DEV_TYPE_LEN], char *buf, + size_t buf_len); +void uuid_gen_mac_addr(const u8 *mac_addr, u8 *uuid); +u16 wps_config_methods_str2bin(const char *str); +struct wpabuf * wps_build_nfc_pw_token(u16 dev_pw_id, + const struct wpabuf *pubkey, + const struct wpabuf *dev_pw); +struct wpabuf * wps_nfc_token_build(int ndef, int id, struct wpabuf *pubkey, + struct wpabuf *dev_pw); +int wps_nfc_gen_dh(struct wpabuf **pubkey, struct wpabuf **privkey); +struct wpabuf * wps_nfc_token_gen(int ndef, int *id, struct wpabuf **pubkey, + struct wpabuf **privkey, + struct wpabuf **dev_pw); +struct wpabuf * wps_build_nfc_handover_req(struct wps_context *ctx, + struct wpabuf *nfc_dh_pubkey); +struct wpabuf * wps_build_nfc_handover_sel(struct wps_context *ctx, + struct wpabuf *nfc_dh_pubkey, + const u8 *bssid, int freq); +struct wpabuf * wps_build_nfc_handover_req_p2p(struct wps_context *ctx, + struct wpabuf *nfc_dh_pubkey); +struct wpabuf * wps_build_nfc_handover_sel_p2p(struct wps_context *ctx, + int nfc_dev_pw_id, + struct wpabuf *nfc_dh_pubkey, + struct wpabuf *nfc_dev_pw); + +/* ndef.c */ +struct wpabuf * ndef_parse_wifi(const struct wpabuf *buf); +struct wpabuf * ndef_build_wifi(const struct wpabuf *buf); +struct wpabuf * ndef_parse_p2p(const struct wpabuf *buf); +struct wpabuf * ndef_build_p2p(const struct wpabuf *buf); + +#ifdef CONFIG_WPS_STRICT +int wps_validate_beacon(const struct wpabuf *wps_ie); +int wps_validate_beacon_probe_resp(const struct wpabuf *wps_ie, int probe, + const u8 *addr); +int wps_validate_probe_req(const struct wpabuf *wps_ie, const u8 *addr); +int wps_validate_assoc_req(const struct wpabuf *wps_ie); +int wps_validate_assoc_resp(const struct wpabuf *wps_ie); +int wps_validate_m1(const struct wpabuf *tlvs); +int wps_validate_m2(const struct wpabuf *tlvs); +int wps_validate_m2d(const struct wpabuf *tlvs); +int wps_validate_m3(const struct wpabuf *tlvs); +int wps_validate_m4(const struct wpabuf *tlvs); +int wps_validate_m4_encr(const struct wpabuf *tlvs, int wps2); +int wps_validate_m5(const struct wpabuf *tlvs); +int wps_validate_m5_encr(const struct wpabuf *tlvs, int wps2); +int wps_validate_m6(const struct wpabuf *tlvs); +int wps_validate_m6_encr(const struct wpabuf *tlvs, int wps2); +int wps_validate_m7(const struct wpabuf *tlvs); +int wps_validate_m7_encr(const struct wpabuf *tlvs, int ap, int wps2); +int wps_validate_m8(const struct wpabuf *tlvs); +int wps_validate_m8_encr(const struct wpabuf *tlvs, int ap, int wps2); +int wps_validate_wsc_ack(const struct wpabuf *tlvs); +int wps_validate_wsc_nack(const struct wpabuf *tlvs); +int wps_validate_wsc_done(const struct wpabuf *tlvs); +int wps_validate_upnp_set_selected_registrar(const struct wpabuf *tlvs); +#else /* CONFIG_WPS_STRICT */ +static inline int wps_validate_beacon(const struct wpabuf *wps_ie){ + return 0; +} + +static inline int wps_validate_beacon_probe_resp(const struct wpabuf *wps_ie, + int probe, const u8 *addr) +{ + return 0; +} + +static inline int wps_validate_probe_req(const struct wpabuf *wps_ie, + const u8 *addr) +{ + return 0; +} + +static inline int wps_validate_assoc_req(const struct wpabuf *wps_ie) +{ + return 0; +} + +static inline int wps_validate_assoc_resp(const struct wpabuf *wps_ie) +{ + return 0; +} + +static inline int wps_validate_m1(const struct wpabuf *tlvs) +{ + return 0; +} + +static inline int wps_validate_m2(const struct wpabuf *tlvs) +{ + return 0; +} + +static inline int wps_validate_m2d(const struct wpabuf *tlvs) +{ + return 0; +} + +static inline int wps_validate_m3(const struct wpabuf *tlvs) +{ + return 0; +} + +static inline int wps_validate_m4(const struct wpabuf *tlvs) +{ + return 0; +} + +static inline int wps_validate_m4_encr(const struct wpabuf *tlvs, int wps2) +{ + return 0; +} + +static inline int wps_validate_m5(const struct wpabuf *tlvs) +{ + return 0; +} + +static inline int wps_validate_m5_encr(const struct wpabuf *tlvs, int wps2) +{ + return 0; +} + +static inline int wps_validate_m6(const struct wpabuf *tlvs) +{ + return 0; +} + +static inline int wps_validate_m6_encr(const struct wpabuf *tlvs, int wps2) +{ + return 0; +} + +static inline int wps_validate_m7(const struct wpabuf *tlvs) +{ + return 0; +} + +static inline int wps_validate_m7_encr(const struct wpabuf *tlvs, int ap, + int wps2) +{ + return 0; +} + +static inline int wps_validate_m8(const struct wpabuf *tlvs) +{ + return 0; +} + +static inline int wps_validate_m8_encr(const struct wpabuf *tlvs, int ap, + int wps2) +{ + return 0; +} + +static inline int wps_validate_wsc_ack(const struct wpabuf *tlvs) +{ + return 0; +} + +static inline int wps_validate_wsc_nack(const struct wpabuf *tlvs) +{ + return 0; +} + +static inline int wps_validate_wsc_done(const struct wpabuf *tlvs) +{ + return 0; +} + +static inline int wps_validate_upnp_set_selected_registrar( + const struct wpabuf *tlvs) +{ + return 0; +} +#endif /* CONFIG_WPS_STRICT */ + +#endif /* WPS_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/wps/wps_attr_parse.h b/beken_os/beken378/func/hostapd-2.5/src/wps/wps_attr_parse.h new file mode 100755 index 0000000..8188fe9 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/wps/wps_attr_parse.h @@ -0,0 +1,104 @@ +/* + * Wi-Fi Protected Setup - attribute parsing + * Copyright (c) 2008-2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef WPS_ATTR_PARSE_H +#define WPS_ATTR_PARSE_H + +#include "wps.h" + +struct wps_parse_attr { + /* fixed length fields */ + const u8 *version; /* 1 octet */ + const u8 *version2; /* 1 octet */ + const u8 *msg_type; /* 1 octet */ + const u8 *enrollee_nonce; /* WPS_NONCE_LEN (16) octets */ + const u8 *registrar_nonce; /* WPS_NONCE_LEN (16) octets */ + const u8 *uuid_r; /* WPS_UUID_LEN (16) octets */ + const u8 *uuid_e; /* WPS_UUID_LEN (16) octets */ + const u8 *auth_type_flags; /* 2 octets */ + const u8 *encr_type_flags; /* 2 octets */ + const u8 *conn_type_flags; /* 1 octet */ + const u8 *config_methods; /* 2 octets */ + const u8 *sel_reg_config_methods; /* 2 octets */ + const u8 *primary_dev_type; /* 8 octets */ + const u8 *rf_bands; /* 1 octet */ + const u8 *assoc_state; /* 2 octets */ + const u8 *config_error; /* 2 octets */ + const u8 *dev_password_id; /* 2 octets */ + const u8 *os_version; /* 4 octets */ + const u8 *wps_state; /* 1 octet */ + const u8 *authenticator; /* WPS_AUTHENTICATOR_LEN (8) octets */ + const u8 *r_hash1; /* WPS_HASH_LEN (32) octets */ + const u8 *r_hash2; /* WPS_HASH_LEN (32) octets */ + const u8 *e_hash1; /* WPS_HASH_LEN (32) octets */ + const u8 *e_hash2; /* WPS_HASH_LEN (32) octets */ + const u8 *r_snonce1; /* WPS_SECRET_NONCE_LEN (16) octets */ + const u8 *r_snonce2; /* WPS_SECRET_NONCE_LEN (16) octets */ + const u8 *e_snonce1; /* WPS_SECRET_NONCE_LEN (16) octets */ + const u8 *e_snonce2; /* WPS_SECRET_NONCE_LEN (16) octets */ + const u8 *key_wrap_auth; /* WPS_KWA_LEN (8) octets */ + const u8 *auth_type; /* 2 octets */ + const u8 *encr_type; /* 2 octets */ + const u8 *network_idx; /* 1 octet */ + const u8 *network_key_idx; /* 1 octet */ + const u8 *mac_addr; /* ETH_ALEN (6) octets */ + const u8 *selected_registrar; /* 1 octet (Bool) */ + const u8 *request_type; /* 1 octet */ + const u8 *response_type; /* 1 octet */ + const u8 *ap_setup_locked; /* 1 octet */ + const u8 *settings_delay_time; /* 1 octet */ + const u8 *network_key_shareable; /* 1 octet (Bool) */ + const u8 *request_to_enroll; /* 1 octet (Bool) */ + const u8 *ap_channel; /* 2 octets */ + const u8 *registrar_configuration_methods; /* 2 octets */ + + /* variable length fields */ + const u8 *manufacturer; + const u8 *model_name; + const u8 *model_number; + const u8 *serial_number; + const u8 *dev_name; + const u8 *public_key; + const u8 *encr_settings; + const u8 *ssid; /* <= 32 octets */ + const u8 *network_key; /* <= 64 octets */ + const u8 *authorized_macs; /* <= 30 octets */ + const u8 *sec_dev_type_list; /* <= 128 octets */ + const u8 *oob_dev_password; /* 38..54 octets */ + u16 manufacturer_len; + u16 model_name_len; + u16 model_number_len; + u16 serial_number_len; + u16 dev_name_len; + u16 public_key_len; + u16 encr_settings_len; + u16 ssid_len; + u16 network_key_len; + u16 authorized_macs_len; + u16 sec_dev_type_list_len; + u16 oob_dev_password_len; + + /* attributes that can occur multiple times */ +#define MAX_CRED_COUNT 10 +#define MAX_REQ_DEV_TYPE_COUNT 10 + + unsigned int num_cred; + unsigned int num_req_dev_type; + unsigned int num_vendor_ext; + + u16 cred_len[MAX_CRED_COUNT]; + u16 vendor_ext_len[MAX_WPS_PARSE_VENDOR_EXT]; + + const u8 *cred[MAX_CRED_COUNT]; + const u8 *req_dev_type[MAX_REQ_DEV_TYPE_COUNT]; + const u8 *vendor_ext[MAX_WPS_PARSE_VENDOR_EXT]; +}; + +int wps_parse_msg(const struct wpabuf *msg, struct wps_parse_attr *attr); + +#endif /* WPS_ATTR_PARSE_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/wps/wps_defs.h b/beken_os/beken378/func/hostapd-2.5/src/wps/wps_defs.h new file mode 100755 index 0000000..a23b979 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/wps/wps_defs.h @@ -0,0 +1,379 @@ +/* + * Wi-Fi Protected Setup - message definitions + * Copyright (c) 2008, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef WPS_DEFS_H +#define WPS_DEFS_H + +#ifdef CONFIG_WPS_TESTING + +extern int wps_version_number; +extern int wps_testing_dummy_cred; +extern int wps_corrupt_pkhash; +#define WPS_VERSION wps_version_number + +#else /* CONFIG_WPS_TESTING */ + +#define WPS_VERSION 0x20 + +#endif /* CONFIG_WPS_TESTING */ + +/* Diffie-Hellman 1536-bit MODP Group; RFC 3526, Group 5 */ +#define WPS_DH_GROUP 5 + +#define WPS_UUID_LEN 16 +#define WPS_NONCE_LEN 16 +#define WPS_AUTHENTICATOR_LEN 8 +#define WPS_AUTHKEY_LEN 32 +#define WPS_KEYWRAPKEY_LEN 16 +#define WPS_EMSK_LEN 32 +#define WPS_PSK_LEN 16 +#define WPS_SECRET_NONCE_LEN 16 +#define WPS_HASH_LEN 32 +#define WPS_KWA_LEN 8 +#define WPS_MGMTAUTHKEY_LEN 32 +#define WPS_MGMTENCKEY_LEN 16 +#define WPS_MGMT_KEY_ID_LEN 16 +#define WPS_OOB_DEVICE_PASSWORD_MIN_LEN 16 +#define WPS_OOB_DEVICE_PASSWORD_LEN 32 +#define WPS_OOB_PUBKEY_HASH_LEN 20 +#define WPS_DEV_NAME_MAX_LEN 32 +#define WPS_MANUFACTURER_MAX_LEN 64 +#define WPS_MODEL_NAME_MAX_LEN 32 +#define WPS_MODEL_NUMBER_MAX_LEN 32 +#define WPS_SERIAL_NUMBER_MAX_LEN 32 + +/* Attribute Types */ +enum wps_attribute { + ATTR_AP_CHANNEL = 0x1001, + ATTR_ASSOC_STATE = 0x1002, + ATTR_AUTH_TYPE = 0x1003, + ATTR_AUTH_TYPE_FLAGS = 0x1004, + ATTR_AUTHENTICATOR = 0x1005, + ATTR_CONFIG_METHODS = 0x1008, + ATTR_CONFIG_ERROR = 0x1009, + ATTR_CONFIRM_URL4 = 0x100a, + ATTR_CONFIRM_URL6 = 0x100b, + ATTR_CONN_TYPE = 0x100c, + ATTR_CONN_TYPE_FLAGS = 0x100d, + ATTR_CRED = 0x100e, + ATTR_ENCR_TYPE = 0x100f, + ATTR_ENCR_TYPE_FLAGS = 0x1010, + ATTR_DEV_NAME = 0x1011, + ATTR_DEV_PASSWORD_ID = 0x1012, + ATTR_E_HASH1 = 0x1014, + ATTR_E_HASH2 = 0x1015, + ATTR_E_SNONCE1 = 0x1016, + ATTR_E_SNONCE2 = 0x1017, + ATTR_ENCR_SETTINGS = 0x1018, + ATTR_ENROLLEE_NONCE = 0x101a, + ATTR_FEATURE_ID = 0x101b, + ATTR_IDENTITY = 0x101c, + ATTR_IDENTITY_PROOF = 0x101d, + ATTR_KEY_WRAP_AUTH = 0x101e, + ATTR_KEY_ID = 0x101f, + ATTR_MAC_ADDR = 0x1020, + ATTR_MANUFACTURER = 0x1021, + ATTR_MSG_TYPE = 0x1022, + ATTR_MODEL_NAME = 0x1023, + ATTR_MODEL_NUMBER = 0x1024, + ATTR_NETWORK_INDEX = 0x1026, + ATTR_NETWORK_KEY = 0x1027, + ATTR_NETWORK_KEY_INDEX = 0x1028, + ATTR_NEW_DEVICE_NAME = 0x1029, + ATTR_NEW_PASSWORD = 0x102a, + ATTR_OOB_DEVICE_PASSWORD = 0x102c, + ATTR_OS_VERSION = 0x102d, + ATTR_POWER_LEVEL = 0x102f, + ATTR_PSK_CURRENT = 0x1030, + ATTR_PSK_MAX = 0x1031, + ATTR_PUBLIC_KEY = 0x1032, + ATTR_RADIO_ENABLE = 0x1033, + ATTR_REBOOT = 0x1034, + ATTR_REGISTRAR_CURRENT = 0x1035, + ATTR_REGISTRAR_ESTABLISHED = 0x1036, + ATTR_REGISTRAR_LIST = 0x1037, + ATTR_REGISTRAR_MAX = 0x1038, + ATTR_REGISTRAR_NONCE = 0x1039, + ATTR_REQUEST_TYPE = 0x103a, + ATTR_RESPONSE_TYPE = 0x103b, + ATTR_RF_BANDS = 0x103c, + ATTR_R_HASH1 = 0x103d, + ATTR_R_HASH2 = 0x103e, + ATTR_R_SNONCE1 = 0x103f, + ATTR_R_SNONCE2 = 0x1040, + ATTR_SELECTED_REGISTRAR = 0x1041, + ATTR_SERIAL_NUMBER = 0x1042, + ATTR_WPS_STATE = 0x1044, + ATTR_SSID = 0x1045, + ATTR_TOTAL_NETWORKS = 0x1046, + ATTR_UUID_E = 0x1047, + ATTR_UUID_R = 0x1048, + ATTR_VENDOR_EXT = 0x1049, + ATTR_VERSION = 0x104a, + ATTR_X509_CERT_REQ = 0x104b, + ATTR_X509_CERT = 0x104c, + ATTR_EAP_IDENTITY = 0x104d, + ATTR_MSG_COUNTER = 0x104e, + ATTR_PUBKEY_HASH = 0x104f, + ATTR_REKEY_KEY = 0x1050, + ATTR_KEY_LIFETIME = 0x1051, + ATTR_PERMITTED_CFG_METHODS = 0x1052, + ATTR_SELECTED_REGISTRAR_CONFIG_METHODS = 0x1053, + ATTR_PRIMARY_DEV_TYPE = 0x1054, + ATTR_SECONDARY_DEV_TYPE_LIST = 0x1055, + ATTR_PORTABLE_DEV = 0x1056, + ATTR_AP_SETUP_LOCKED = 0x1057, + ATTR_APPLICATION_EXT = 0x1058, + ATTR_EAP_TYPE = 0x1059, + ATTR_IV = 0x1060, + ATTR_KEY_PROVIDED_AUTO = 0x1061, + ATTR_802_1X_ENABLED = 0x1062, + ATTR_APPSESSIONKEY = 0x1063, + ATTR_WEPTRANSMITKEY = 0x1064, + ATTR_REQUESTED_DEV_TYPE = 0x106a, + ATTR_EXTENSIBILITY_TEST = 0x10fa /* _NOT_ defined in the spec */ +}; + +#define WPS_VENDOR_ID_WFA 14122 + +/* WFA Vendor Extension subelements */ +enum { + WFA_ELEM_VERSION2 = 0x00, + WFA_ELEM_AUTHORIZEDMACS = 0x01, + WFA_ELEM_NETWORK_KEY_SHAREABLE = 0x02, + WFA_ELEM_REQUEST_TO_ENROLL = 0x03, + WFA_ELEM_SETTINGS_DELAY_TIME = 0x04, + WFA_ELEM_REGISTRAR_CONFIGURATION_METHODS = 0x05 +}; + +/* Device Password ID */ +enum wps_dev_password_id { + DEV_PW_DEFAULT = 0x0000, + DEV_PW_USER_SPECIFIED = 0x0001, + DEV_PW_MACHINE_SPECIFIED = 0x0002, + DEV_PW_REKEY = 0x0003, + DEV_PW_PUSHBUTTON = 0x0004, + DEV_PW_REGISTRAR_SPECIFIED = 0x0005, + DEV_PW_NFC_CONNECTION_HANDOVER = 0x0007, + DEV_PW_P2PS_DEFAULT = 0x0008 +}; + +/* Message Type */ +enum wps_msg_type { + WPS_Beacon = 0x01, + WPS_ProbeRequest = 0x02, + WPS_ProbeResponse = 0x03, + WPS_M1 = 0x04, + WPS_M2 = 0x05, + WPS_M2D = 0x06, + WPS_M3 = 0x07, + WPS_M4 = 0x08, + WPS_M5 = 0x09, + WPS_M6 = 0x0a, + WPS_M7 = 0x0b, + WPS_M8 = 0x0c, + WPS_WSC_ACK = 0x0d, + WPS_WSC_NACK = 0x0e, + WPS_WSC_DONE = 0x0f +}; + +/* Authentication Type Flags */ +#define WPS_AUTH_OPEN 0x0001 +#define WPS_AUTH_WPAPSK 0x0002 +#define WPS_AUTH_SHARED 0x0004 /* deprecated */ +#define WPS_AUTH_WPA 0x0008 +#define WPS_AUTH_WPA2 0x0010 +#define WPS_AUTH_WPA2PSK 0x0020 +#define WPS_AUTH_TYPES (WPS_AUTH_OPEN | WPS_AUTH_WPAPSK | WPS_AUTH_SHARED | \ + WPS_AUTH_WPA | WPS_AUTH_WPA2 | WPS_AUTH_WPA2PSK) + +/* Encryption Type Flags */ +#define WPS_ENCR_NONE 0x0001 +#define WPS_ENCR_WEP 0x0002 /* deprecated */ +#define WPS_ENCR_TKIP 0x0004 +#define WPS_ENCR_AES 0x0008 +#define WPS_ENCR_TYPES (WPS_ENCR_NONE | WPS_ENCR_WEP | WPS_ENCR_TKIP | \ + WPS_ENCR_AES) + +/* Configuration Error */ +enum wps_config_error { + WPS_CFG_NO_ERROR = 0, + WPS_CFG_OOB_IFACE_READ_ERROR = 1, + WPS_CFG_DECRYPTION_CRC_FAILURE = 2, + WPS_CFG_24_CHAN_NOT_SUPPORTED = 3, + WPS_CFG_50_CHAN_NOT_SUPPORTED = 4, + WPS_CFG_SIGNAL_TOO_WEAK = 5, + WPS_CFG_NETWORK_AUTH_FAILURE = 6, + WPS_CFG_NETWORK_ASSOC_FAILURE = 7, + WPS_CFG_NO_DHCP_RESPONSE = 8, + WPS_CFG_FAILED_DHCP_CONFIG = 9, + WPS_CFG_IP_ADDR_CONFLICT = 10, + WPS_CFG_NO_CONN_TO_REGISTRAR = 11, + WPS_CFG_MULTIPLE_PBC_DETECTED = 12, + WPS_CFG_ROGUE_SUSPECTED = 13, + WPS_CFG_DEVICE_BUSY = 14, + WPS_CFG_SETUP_LOCKED = 15, + WPS_CFG_MSG_TIMEOUT = 16, + WPS_CFG_REG_SESS_TIMEOUT = 17, + WPS_CFG_DEV_PASSWORD_AUTH_FAILURE = 18, + WPS_CFG_60G_CHAN_NOT_SUPPORTED = 19, + WPS_CFG_PUBLIC_KEY_HASH_MISMATCH = 20 +}; + +/* Vendor specific Error Indication for WPS event messages */ +enum wps_error_indication { + WPS_EI_NO_ERROR, + WPS_EI_SECURITY_TKIP_ONLY_PROHIBITED, + WPS_EI_SECURITY_WEP_PROHIBITED, + WPS_EI_AUTH_FAILURE, + NUM_WPS_EI_VALUES +}; + +/* RF Bands */ +#define WPS_RF_24GHZ 0x01 +#define WPS_RF_50GHZ 0x02 +#define WPS_RF_60GHZ 0x04 + +/* Config Methods */ +#define WPS_CONFIG_USBA 0x0001 +#define WPS_CONFIG_ETHERNET 0x0002 +#define WPS_CONFIG_LABEL 0x0004 +#define WPS_CONFIG_DISPLAY 0x0008 +#define WPS_CONFIG_EXT_NFC_TOKEN 0x0010 +#define WPS_CONFIG_INT_NFC_TOKEN 0x0020 +#define WPS_CONFIG_NFC_INTERFACE 0x0040 +#define WPS_CONFIG_PUSHBUTTON 0x0080 +#define WPS_CONFIG_KEYPAD 0x0100 +#define WPS_CONFIG_VIRT_PUSHBUTTON 0x0280 +#define WPS_CONFIG_PHY_PUSHBUTTON 0x0480 +#define WPS_CONFIG_P2PS 0x1000 +#define WPS_CONFIG_VIRT_DISPLAY 0x2008 +#define WPS_CONFIG_PHY_DISPLAY 0x4008 + +/* Connection Type Flags */ +#define WPS_CONN_ESS 0x01 +#define WPS_CONN_IBSS 0x02 + +/* Wi-Fi Protected Setup State */ +enum wps_state { + WPS_STATE_NOT_CONFIGURED = 1, + WPS_STATE_CONFIGURED = 2 +}; + +/* Association State */ +enum wps_assoc_state { + WPS_ASSOC_NOT_ASSOC = 0, + WPS_ASSOC_CONN_SUCCESS = 1, + WPS_ASSOC_CFG_FAILURE = 2, + WPS_ASSOC_FAILURE = 3, + WPS_ASSOC_IP_FAILURE = 4 +}; + + +#define WPS_DEV_OUI_WFA 0x0050f204 + +enum wps_dev_categ { + WPS_DEV_COMPUTER = 1, + WPS_DEV_INPUT = 2, + WPS_DEV_PRINTER = 3, + WPS_DEV_CAMERA = 4, + WPS_DEV_STORAGE = 5, + WPS_DEV_NETWORK_INFRA = 6, + WPS_DEV_DISPLAY = 7, + WPS_DEV_MULTIMEDIA = 8, + WPS_DEV_GAMING = 9, + WPS_DEV_PHONE = 10, + WPS_DEV_AUDIO = 11, +}; + +enum wps_dev_subcateg { + WPS_DEV_COMPUTER_PC = 1, + WPS_DEV_COMPUTER_SERVER = 2, + WPS_DEV_COMPUTER_MEDIA_CENTER = 3, + WPS_DEV_COMPUTER_ULTRA_MOBILE = 4, + WPS_DEV_COMPUTER_NOTEBOOK = 5, + WPS_DEV_COMPUTER_DESKTOP = 6, + WPS_DEV_COMPUTER_MID = 7, + WPS_DEV_COMPUTER_NETBOOK = 8, + WPS_DEV_COMPUTER_TABLET = 9, + WPS_DEV_INPUT_KEYBOARD = 1, + WPS_DEV_INPUT_MOUSE = 2, + WPS_DEV_INPUT_JOYSTICK = 3, + WPS_DEV_INPUT_TRACKBALL = 4, + WPS_DEV_INPUT_GAMING = 5, + WPS_DEV_INPUT_REMOTE = 6, + WPS_DEV_INPUT_TOUCHSCREEN = 7, + WPS_DEV_INPUT_BIOMETRIC_READER = 8, + WPS_DEV_INPUT_BARCODE_READER = 9, + WPS_DEV_PRINTER_PRINTER = 1, + WPS_DEV_PRINTER_SCANNER = 2, + WPS_DEV_PRINTER_FAX = 3, + WPS_DEV_PRINTER_COPIER = 4, + WPS_DEV_PRINTER_ALL_IN_ONE = 5, + WPS_DEV_CAMERA_DIGITAL_STILL_CAMERA = 1, + WPS_DEV_CAMERA_VIDEO = 2, + WPS_DEV_CAMERA_WEB = 3, + WPS_DEV_CAMERA_SECURITY = 4, + WPS_DEV_STORAGE_NAS = 1, + WPS_DEV_NETWORK_INFRA_AP = 1, + WPS_DEV_NETWORK_INFRA_ROUTER = 2, + WPS_DEV_NETWORK_INFRA_SWITCH = 3, + WPS_DEV_NETWORK_INFRA_GATEWAY = 4, + WPS_DEV_NETWORK_INFRA_BRIDGE = 5, + WPS_DEV_DISPLAY_TV = 1, + WPS_DEV_DISPLAY_PICTURE_FRAME = 2, + WPS_DEV_DISPLAY_PROJECTOR = 3, + WPS_DEV_DISPLAY_MONITOR = 4, + WPS_DEV_MULTIMEDIA_DAR = 1, + WPS_DEV_MULTIMEDIA_PVR = 2, + WPS_DEV_MULTIMEDIA_MCX = 3, + WPS_DEV_MULTIMEDIA_SET_TOP_BOX = 4, + WPS_DEV_MULTIMEDIA_MEDIA_SERVER = 5, + WPS_DEV_MULTIMEDIA_PORTABLE_VIDEO_PLAYER = 6, + WPS_DEV_GAMING_XBOX = 1, + WPS_DEV_GAMING_XBOX360 = 2, + WPS_DEV_GAMING_PLAYSTATION = 3, + WPS_DEV_GAMING_GAME_CONSOLE = 4, + WPS_DEV_GAMING_PORTABLE_DEVICE = 5, + WPS_DEV_PHONE_WINDOWS_MOBILE = 1, + WPS_DEV_PHONE_SINGLE_MODE = 2, + WPS_DEV_PHONE_DUAL_MODE = 3, + WPS_DEV_PHONE_SP_SINGLE_MODE = 4, + WPS_DEV_PHONE_SP_DUAL_MODE = 5, + WPS_DEV_AUDIO_TUNER_RECV = 1, + WPS_DEV_AUDIO_SPEAKERS = 2, + WPS_DEV_AUDIO_PMP = 3, + WPS_DEV_AUDIO_HEADSET = 4, + WPS_DEV_AUDIO_HEADPHONES = 5, + WPS_DEV_AUDIO_MICROPHONE = 6, + WPS_DEV_AUDIO_HOME_THEATRE = 7, +}; + + +/* Request Type */ +enum wps_request_type { + WPS_REQ_ENROLLEE_INFO = 0, + WPS_REQ_ENROLLEE = 1, + WPS_REQ_REGISTRAR = 2, + WPS_REQ_WLAN_MANAGER_REGISTRAR = 3 +}; + +/* Response Type */ +enum wps_response_type { + WPS_RESP_ENROLLEE_INFO = 0, + WPS_RESP_ENROLLEE = 1, + WPS_RESP_REGISTRAR = 2, + WPS_RESP_AP = 3 +}; + +/* Walk Time for push button configuration (in seconds) */ +#define WPS_PBC_WALK_TIME 120 + +#define WPS_MAX_AUTHORIZED_MACS 5 + +#endif /* WPS_DEFS_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/wps/wps_dev_attr.h b/beken_os/beken378/func/hostapd-2.5/src/wps/wps_dev_attr.h new file mode 100755 index 0000000..c9034ad --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/wps/wps_dev_attr.h @@ -0,0 +1,39 @@ +/* + * Wi-Fi Protected Setup - device attributes + * Copyright (c) 2008, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef WPS_DEV_ATTR_H +#define WPS_DEV_ATTR_H + +struct wps_parse_attr; + +int wps_build_manufacturer(struct wps_device_data *dev, struct wpabuf *msg); +int wps_build_model_name(struct wps_device_data *dev, struct wpabuf *msg); +int wps_build_model_number(struct wps_device_data *dev, struct wpabuf *msg); +int wps_build_serial_number(struct wps_device_data *dev, struct wpabuf *msg); +int wps_build_dev_name(struct wps_device_data *dev, struct wpabuf *msg); +int wps_build_device_attrs(struct wps_device_data *dev, struct wpabuf *msg); +int wps_build_os_version(struct wps_device_data *dev, struct wpabuf *msg); +int wps_build_vendor_ext_m1(struct wps_device_data *dev, struct wpabuf *msg); +int wps_build_rf_bands(struct wps_device_data *dev, struct wpabuf *msg, + u8 rf_band); +int wps_build_primary_dev_type(struct wps_device_data *dev, + struct wpabuf *msg); +int wps_build_secondary_dev_type(struct wps_device_data *dev, + struct wpabuf *msg); +int wps_build_dev_name(struct wps_device_data *dev, struct wpabuf *msg); +int wps_process_device_attrs(struct wps_device_data *dev, + struct wps_parse_attr *attr); +int wps_process_os_version(struct wps_device_data *dev, const u8 *ver); +int wps_process_rf_bands(struct wps_device_data *dev, const u8 *bands); +void wps_device_data_free(struct wps_device_data *dev); +int wps_build_vendor_ext(struct wps_device_data *dev, struct wpabuf *msg); +int wps_build_req_dev_type(struct wps_device_data *dev, struct wpabuf *msg, + unsigned int num_req_dev_types, + const u8 *req_dev_types); + +#endif /* WPS_DEV_ATTR_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/wps/wps_er.h b/beken_os/beken378/func/hostapd-2.5/src/wps/wps_er.h new file mode 100755 index 0000000..4b48ff6 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/wps/wps_er.h @@ -0,0 +1,112 @@ +/* + * Wi-Fi Protected Setup - External Registrar + * Copyright (c) 2009, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef WPS_ER_H +#define WPS_ER_H + +#include "utils/list.h" + +struct wps_er_sta { + struct dl_list list; + struct wps_er_ap *ap; + u8 addr[ETH_ALEN]; + u16 config_methods; + u8 uuid[WPS_UUID_LEN]; + u8 pri_dev_type[8]; + u16 dev_passwd_id; + int m1_received; + char *manufacturer; + char *model_name; + char *model_number; + char *serial_number; + char *dev_name; + struct wps_data *wps; + struct http_client *http; + struct wps_credential *cred; +}; + +struct wps_er_ap { + struct dl_list list; + struct wps_er *er; + struct dl_list sta; /* list of STAs/Enrollees using this AP */ + struct in_addr addr; + char *location; + struct http_client *http; + struct wps_data *wps; + + u8 uuid[WPS_UUID_LEN]; + u8 pri_dev_type[8]; + u8 wps_state; + u8 mac_addr[ETH_ALEN]; + char *friendly_name; + char *manufacturer; + char *manufacturer_url; + char *model_description; + char *model_name; + char *model_number; + char *model_url; + char *serial_number; + char *udn; + char *upc; + + char *scpd_url; + char *control_url; + char *event_sub_url; + + int subscribed; + u8 sid[WPS_UUID_LEN]; + unsigned int id; + + struct wps_credential *ap_settings; + + void (*m1_handler)(struct wps_er_ap *ap, struct wpabuf *m1); +}; + +struct wps_er_ap_settings { + struct dl_list list; + u8 uuid[WPS_UUID_LEN]; + struct wps_credential ap_settings; +}; + +struct wps_er { + struct wps_context *wps; + char ifname[17]; + int forced_ifname; + u8 mac_addr[ETH_ALEN]; /* mac addr of network i.f. we use */ + char *ip_addr_text; /* IP address of network i.f. we use */ + unsigned ip_addr; /* IP address of network i.f. we use (host order) */ + int multicast_sd; + int ssdp_sd; + struct dl_list ap; + struct dl_list ap_unsubscribing; + struct dl_list ap_settings; + struct http_server *http_srv; + int http_port; + unsigned int next_ap_id; + unsigned int event_id; + int deinitializing; + void (*deinit_done_cb)(void *ctx); + void *deinit_done_ctx; + struct in_addr filter_addr; + int skip_set_sel_reg; + const u8 *set_sel_reg_uuid_filter; +}; + + +/* wps_er.c */ +void wps_er_ap_add(struct wps_er *er, const u8 *uuid, struct in_addr *addr, + const char *location, int max_age); +void wps_er_ap_remove(struct wps_er *er, struct in_addr *addr); +int wps_er_ap_cache_settings(struct wps_er *er, struct in_addr *addr); + +/* wps_er_ssdp.c */ +int wps_er_ssdp_init(struct wps_er *er); +void wps_er_ssdp_deinit(struct wps_er *er); +void wps_er_send_ssdp_msearch(struct wps_er *er); + +#endif /* WPS_ER_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/wps/wps_i.h b/beken_os/beken378/func/hostapd-2.5/src/wps/wps_i.h new file mode 100755 index 0000000..f7154f8 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/wps/wps_i.h @@ -0,0 +1,218 @@ +/* + * Wi-Fi Protected Setup - internal definitions + * Copyright (c) 2008-2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef WPS_I_H +#define WPS_I_H + +#include "wps.h" +#include "wps_attr_parse.h" + +struct wps_nfc_pw_token; + +/** + * struct wps_data - WPS registration protocol data + * + * This data is stored at the EAP-WSC server/peer method and it is kept for a + * single registration protocol run. + */ +struct wps_data { + /** + * wps - Pointer to long term WPS context + */ + struct wps_context *wps; + + /** + * registrar - Whether this end is a Registrar + */ + int registrar; + + /** + * er - Whether the local end is an external registrar + */ + int er; + + enum { + /* Enrollee states */ + SEND_M1, RECV_M2, SEND_M3, RECV_M4, SEND_M5, RECV_M6, SEND_M7, + RECV_M8, RECEIVED_M2D, WPS_MSG_DONE, RECV_ACK, WPS_FINISHED, + SEND_WSC_NACK, + + /* Registrar states */ + RECV_M1, SEND_M2, RECV_M3, SEND_M4, RECV_M5, SEND_M6, + RECV_M7, SEND_M8, RECV_DONE, SEND_M2D, RECV_M2D_ACK + } state; + + u8 uuid_e[WPS_UUID_LEN]; + u8 uuid_r[WPS_UUID_LEN]; + u8 mac_addr_e[ETH_ALEN]; + u8 nonce_e[WPS_NONCE_LEN]; + u8 nonce_r[WPS_NONCE_LEN]; + u8 psk1[WPS_PSK_LEN]; + u8 psk2[WPS_PSK_LEN]; + u8 snonce[2 * WPS_SECRET_NONCE_LEN]; + u8 peer_hash1[WPS_HASH_LEN]; + u8 peer_hash2[WPS_HASH_LEN]; + + struct wpabuf *dh_privkey; + struct wpabuf *dh_pubkey_e; + struct wpabuf *dh_pubkey_r; + u8 authkey[WPS_AUTHKEY_LEN]; + u8 keywrapkey[WPS_KEYWRAPKEY_LEN]; + u8 emsk[WPS_EMSK_LEN]; + + struct wpabuf *last_msg; + + u8 *dev_password; + size_t dev_password_len; + u16 dev_pw_id; + int pbc; + u8 *alt_dev_password; + size_t alt_dev_password_len; + u16 alt_dev_pw_id; + + u8 peer_pubkey_hash[WPS_OOB_PUBKEY_HASH_LEN]; + int peer_pubkey_hash_set; + + /** + * request_type - Request Type attribute from (Re)AssocReq + */ + u8 request_type; + + /** + * encr_type - Available encryption types + */ + u16 encr_type; + + /** + * auth_type - Available authentication types + */ + u16 auth_type; + + u8 *new_psk; + size_t new_psk_len; + + int wps_pin_revealed; + struct wps_credential cred; + + struct wps_device_data peer_dev; + + /** + * config_error - Configuration Error value to be used in NACK + */ + u16 config_error; + u16 error_indication; + + int ext_reg; + int int_reg; + + struct wps_credential *new_ap_settings; + + void *dh_ctx; + + void (*ap_settings_cb)(void *ctx, const struct wps_credential *cred); + void *ap_settings_cb_ctx; + + struct wps_credential *use_cred; + + int use_psk_key; + u8 p2p_dev_addr[ETH_ALEN]; /* P2P Device Address of the client or + * 00:00:00:00:00:00 if not a P2p client */ + int pbc_in_m1; + + struct wps_nfc_pw_token *nfc_pw_token; +}; + + +/* wps_common.c */ +void wps_kdf(const u8 *key, const u8 *label_prefix, size_t label_prefix_len, + const char *label, u8 *res, size_t res_len); +int wps_derive_keys(struct wps_data *wps); +void wps_derive_psk(struct wps_data *wps, const u8 *dev_passwd, + size_t dev_passwd_len); +struct wpabuf * wps_decrypt_encr_settings(struct wps_data *wps, const u8 *encr, + size_t encr_len); +void wps_fail_event(struct wps_context *wps, enum wps_msg_type msg, + u16 config_error, u16 error_indication, const u8 *mac_addr); +void wps_success_event(struct wps_context *wps, const u8 *mac_addr); +void wps_pwd_auth_fail_event(struct wps_context *wps, int enrollee, int part, + const u8 *mac_addr); +void wps_pbc_overlap_event(struct wps_context *wps); +void wps_pbc_timeout_event(struct wps_context *wps); +void wps_pbc_active_event(struct wps_context *wps); +void wps_pbc_disable_event(struct wps_context *wps); + +struct wpabuf * wps_build_wsc_ack(struct wps_data *wps); +struct wpabuf * wps_build_wsc_nack(struct wps_data *wps); + +/* wps_attr_build.c */ +int wps_build_public_key(struct wps_data *wps, struct wpabuf *msg); +int wps_build_req_type(struct wpabuf *msg, enum wps_request_type type); +int wps_build_resp_type(struct wpabuf *msg, enum wps_response_type type); +int wps_build_config_methods(struct wpabuf *msg, u16 methods); +int wps_build_uuid_e(struct wpabuf *msg, const u8 *uuid); +int wps_build_dev_password_id(struct wpabuf *msg, u16 id); +int wps_build_config_error(struct wpabuf *msg, u16 err); +int wps_build_authenticator(struct wps_data *wps, struct wpabuf *msg); +int wps_build_key_wrap_auth(struct wps_data *wps, struct wpabuf *msg); +int wps_build_encr_settings(struct wps_data *wps, struct wpabuf *msg, + struct wpabuf *plain); +int wps_build_version(struct wpabuf *msg); +int wps_build_wfa_ext(struct wpabuf *msg, int req_to_enroll, + const u8 *auth_macs, size_t auth_macs_count); +int wps_build_msg_type(struct wpabuf *msg, enum wps_msg_type msg_type); +int wps_build_enrollee_nonce(struct wps_data *wps, struct wpabuf *msg); +int wps_build_registrar_nonce(struct wps_data *wps, struct wpabuf *msg); +int wps_build_auth_type_flags(struct wps_data *wps, struct wpabuf *msg); +int wps_build_encr_type_flags(struct wps_data *wps, struct wpabuf *msg); +int wps_build_conn_type_flags(struct wps_data *wps, struct wpabuf *msg); +int wps_build_assoc_state(struct wps_data *wps, struct wpabuf *msg); +int wps_build_oob_dev_pw(struct wpabuf *msg, u16 dev_pw_id, + const struct wpabuf *pubkey, const u8 *dev_pw, + size_t dev_pw_len); +struct wpabuf * wps_ie_encapsulate(struct wpabuf *data); +int wps_build_mac_addr(struct wpabuf *msg, const u8 *addr); +int wps_build_rf_bands_attr(struct wpabuf *msg, u8 rf_bands); +int wps_build_ap_channel(struct wpabuf *msg, u16 ap_channel); + +/* wps_attr_process.c */ +int wps_process_authenticator(struct wps_data *wps, const u8 *authenticator, + const struct wpabuf *msg); +int wps_process_key_wrap_auth(struct wps_data *wps, struct wpabuf *msg, + const u8 *key_wrap_auth); +int wps_process_cred(struct wps_parse_attr *attr, + struct wps_credential *cred); +int wps_process_ap_settings(struct wps_parse_attr *attr, + struct wps_credential *cred); + +/* wps_enrollee.c */ +struct wpabuf * wps_enrollee_get_msg(struct wps_data *wps, + enum wsc_op_code *op_code); +enum wps_process_res wps_enrollee_process_msg(struct wps_data *wps, + enum wsc_op_code op_code, + const struct wpabuf *msg); + +/* wps_registrar.c */ +struct wpabuf * wps_registrar_get_msg(struct wps_data *wps, + enum wsc_op_code *op_code); +enum wps_process_res wps_registrar_process_msg(struct wps_data *wps, + enum wsc_op_code op_code, + const struct wpabuf *msg); +int wps_build_cred(struct wps_data *wps, struct wpabuf *msg); +int wps_device_store(struct wps_registrar *reg, + struct wps_device_data *dev, const u8 *uuid); +void wps_registrar_selected_registrar_changed(struct wps_registrar *reg, + u16 dev_pw_id); +const u8 * wps_authorized_macs(struct wps_registrar *reg, size_t *count); +int wps_registrar_pbc_overlap(struct wps_registrar *reg, + const u8 *addr, const u8 *uuid_e); +void wps_registrar_remove_nfc_pw_token(struct wps_registrar *reg, + struct wps_nfc_pw_token *token); +int wps_cb_new_psk(struct wps_registrar *reg, const u8 *mac_addr, + const u8 *p2p_dev_addr, const u8 *psk, size_t psk_len); + +#endif /* WPS_I_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/wps/wps_upnp.h b/beken_os/beken378/func/hostapd-2.5/src/wps/wps_upnp.h new file mode 100755 index 0000000..87b7ab1 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/wps/wps_upnp.h @@ -0,0 +1,48 @@ +/* + * UPnP WPS Device + * Copyright (c) 2000-2003 Intel Corporation + * Copyright (c) 2006-2007 Sony Corporation + * Copyright (c) 2008-2009 Atheros Communications + * Copyright (c) 2009, Jouni Malinen + * + * See wps_upnp.c for more details on licensing and code history. + */ + +#ifndef WPS_UPNP_H +#define WPS_UPNP_H + +struct upnp_wps_device_sm; +struct wps_context; +struct wps_data; + +struct upnp_wps_peer { + struct wps_data *wps; +}; + +enum upnp_wps_wlanevent_type { + UPNP_WPS_WLANEVENT_TYPE_PROBE = 1, + UPNP_WPS_WLANEVENT_TYPE_EAP = 2 +}; + +struct upnp_wps_device_ctx { + int (*rx_req_put_wlan_response)( + void *priv, enum upnp_wps_wlanevent_type ev_type, + const u8 *mac_addr, const struct wpabuf *msg, + enum wps_msg_type msg_type); + + char *ap_pin; +}; + +struct upnp_wps_device_sm * +upnp_wps_device_init(struct upnp_wps_device_ctx *ctx, struct wps_context *wps, + void *priv, char *net_if); +void upnp_wps_device_deinit(struct upnp_wps_device_sm *sm, void *priv); + +int upnp_wps_device_send_wlan_event(struct upnp_wps_device_sm *sm, + const u8 from_mac_addr[ETH_ALEN], + enum upnp_wps_wlanevent_type ev_type, + const struct wpabuf *msg); +int upnp_wps_subscribers(struct upnp_wps_device_sm *sm); +int upnp_wps_set_ap_pin(struct upnp_wps_device_sm *sm, const char *ap_pin); + +#endif /* WPS_UPNP_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/src/wps/wps_upnp_i.h b/beken_os/beken378/func/hostapd-2.5/src/wps/wps_upnp_i.h new file mode 100755 index 0000000..f289fe6 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/src/wps/wps_upnp_i.h @@ -0,0 +1,193 @@ +/* + * UPnP for WPS / internal definitions + * Copyright (c) 2000-2003 Intel Corporation + * Copyright (c) 2006-2007 Sony Corporation + * Copyright (c) 2008-2009 Atheros Communications + * Copyright (c) 2009, Jouni Malinen + * + * See wps_upnp.c for more details on licensing and code history. + */ + +#ifndef WPS_UPNP_I_H +#define WPS_UPNP_I_H + +#include "utils/list.h" +#include "http.h" + +#define UPNP_MULTICAST_ADDRESS "239.255.255.250" /* for UPnP multicasting */ +#define UPNP_MULTICAST_PORT 1900 /* UDP port to monitor for UPnP */ + +/* min subscribe time per UPnP standard */ +#define UPNP_SUBSCRIBE_SEC_MIN 1800 +/* subscribe time we use */ +#define UPNP_SUBSCRIBE_SEC (UPNP_SUBSCRIBE_SEC_MIN + 1) + +/* "filenames" used in URLs that we service via our "web server": */ +#define UPNP_WPS_DEVICE_XML_FILE "wps_device.xml" +#define UPNP_WPS_SCPD_XML_FILE "wps_scpd.xml" +#define UPNP_WPS_DEVICE_CONTROL_FILE "wps_control" +#define UPNP_WPS_DEVICE_EVENT_FILE "wps_event" + +#define MULTICAST_MAX_READ 1600 /* max bytes we'll read for UPD request */ + + +struct upnp_wps_device_sm; +struct wps_registrar; + + +enum advertisement_type_enum { + ADVERTISE_UP = 0, + ADVERTISE_DOWN = 1, + MSEARCH_REPLY = 2 +}; + +/* + * Advertisements are broadcast via UDP NOTIFYs, and are also the essence of + * the reply to UDP M-SEARCH requests. This struct handles both cases. + * + * A state machine is needed because a number of variant forms must be sent in + * separate packets and spread out in time to avoid congestion. + */ +struct advertisement_state_machine { + struct dl_list list; + enum advertisement_type_enum type; + int state; + int nerrors; + struct sockaddr_in client; /* for M-SEARCH replies */ +}; + + +/* + * An address of a subscriber (who may have multiple addresses). We are + * supposed to send (via TCP) updates to each subscriber, trying each address + * for a subscriber until we find one that seems to work. + */ +struct subscr_addr { + struct dl_list list; + char *domain_and_port; /* domain and port part of url */ + char *path; /* "filepath" part of url (from "mem") */ + struct sockaddr_in saddr; /* address for doing connect */ + unsigned num_failures; +}; + + +/* + * Subscribers to our events are recorded in this struct. This includes a max + * of one outgoing connection (sending an "event message") per subscriber. We + * also have to age out subscribers unless they renew. + */ +struct subscription { + struct dl_list list; + struct upnp_wps_device_sm *sm; /* parent */ + time_t timeout_time; /* when to age out the subscription */ + unsigned next_subscriber_sequence; /* number our messages */ + /* + * This uuid identifies the subscription and is randomly generated by + * us and given to the subscriber when the subscription is accepted; + * and is then included with each event sent to the subscriber. + */ + u8 uuid[UUID_LEN]; + /* Linked list of address alternatives (rotate through on failure) */ + struct dl_list addr_list; + struct dl_list event_queue; /* Queued event messages. */ + struct wps_event_ *current_event; /* non-NULL if being sent (not in q) + */ + int last_event_failed; /* Whether delivery of last event failed */ + + /* Information from SetSelectedRegistrar action */ + u8 selected_registrar; + u16 dev_password_id; + u16 config_methods; + u8 authorized_macs[WPS_MAX_AUTHORIZED_MACS][ETH_ALEN]; + struct wps_registrar *reg; +}; + + +struct upnp_wps_device_interface { + struct dl_list list; + struct upnp_wps_device_ctx *ctx; /* callback table */ + struct wps_context *wps; + void *priv; + + /* FIX: maintain separate structures for each UPnP peer */ + struct upnp_wps_peer peer; +}; + +/* + * Our instance data corresponding to the AP device. Note that there may be + * multiple wireless interfaces sharing the same UPnP device instance. Each + * such interface is stored in the list of struct upnp_wps_device_interface + * instances. + * + * This is known as an opaque struct declaration to users of the WPS UPnP code. + */ +struct upnp_wps_device_sm { + struct dl_list interfaces; /* struct upnp_wps_device_interface */ + char *root_dir; + char *desc_url; + int started; /* nonzero if we are active */ + u8 mac_addr[ETH_ALEN]; /* mac addr of network i.f. we use */ + char *ip_addr_text; /* IP address of network i.f. we use */ + unsigned ip_addr; /* IP address of network i.f. we use (host order) */ + int multicast_sd; /* send multicast messages over this socket */ + int ssdp_sd; /* receive discovery UPD packets on socket */ + int ssdp_sd_registered; /* nonzero if we must unregister */ + unsigned advertise_count; /* how many advertisements done */ + struct advertisement_state_machine advertisement; + struct dl_list msearch_replies; + int web_port; /* our port that others get xml files from */ + struct http_server *web_srv; + /* Note: subscriptions are kept in expiry order */ + struct dl_list subscriptions; + int event_send_all_queued; /* if we are scheduled to send events soon + */ + + char *wlanevent; /* the last WLANEvent data */ + enum upnp_wps_wlanevent_type wlanevent_type; + os_time_t last_event_sec; + unsigned int num_events_in_sec; +}; + +/* wps_upnp.c */ +void format_date(struct wpabuf *buf); +struct subscription * subscription_start(struct upnp_wps_device_sm *sm, + const char *callback_urls); +struct subscription * subscription_renew(struct upnp_wps_device_sm *sm, + const u8 uuid[UUID_LEN]); +void subscription_destroy(struct subscription *s); +struct subscription * subscription_find(struct upnp_wps_device_sm *sm, + const u8 uuid[UUID_LEN]); +void subscr_addr_delete(struct subscr_addr *a); +int get_netif_info(const char *net_if, unsigned *ip_addr, char **ip_addr_text, + u8 mac[ETH_ALEN]); + +/* wps_upnp_ssdp.c */ +void msearchreply_state_machine_stop(struct advertisement_state_machine *a); +int advertisement_state_machine_start(struct upnp_wps_device_sm *sm); +void advertisement_state_machine_stop(struct upnp_wps_device_sm *sm, + int send_byebye); +void ssdp_listener_stop(struct upnp_wps_device_sm *sm); +int ssdp_listener_start(struct upnp_wps_device_sm *sm); +int ssdp_listener_open(void); +int add_ssdp_network(const char *net_if); +int ssdp_open_multicast_sock(u32 ip_addr, const char *forced_ifname); +int ssdp_open_multicast(struct upnp_wps_device_sm *sm); + +/* wps_upnp_web.c */ +int web_listener_start(struct upnp_wps_device_sm *sm); +void web_listener_stop(struct upnp_wps_device_sm *sm); + +/* wps_upnp_event.c */ +int event_add(struct subscription *s, const struct wpabuf *data, int probereq); +void event_delete_all(struct subscription *s); +void event_send_all_later(struct upnp_wps_device_sm *sm); +void event_send_stop_all(struct upnp_wps_device_sm *sm); + +/* wps_upnp_ap.c */ +int upnp_er_set_selected_registrar(struct wps_registrar *reg, + struct subscription *s, + const struct wpabuf *msg); +void upnp_er_remove_notification(struct wps_registrar *reg, + struct subscription *s); + +#endif /* WPS_UPNP_I_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/autoscan.h b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/autoscan.h new file mode 100755 index 0000000..e2a7652 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/autoscan.h @@ -0,0 +1,49 @@ +/* + * WPA Supplicant - auto scan + * Copyright (c) 2012, Intel Corporation. All rights reserved. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef AUTOSCAN_H +#define AUTOSCAN_H + +struct wpa_supplicant; + +struct autoscan_ops { + const char *name; + + void * (*init)(struct wpa_supplicant *wpa_s, const char *params); + void (*deinit)(void *priv); + + int (*notify_scan)(void *priv, struct wpa_scan_results *scan_res); +}; + +#ifdef CONFIG_AUTOSCAN + +int autoscan_init(struct wpa_supplicant *wpa_s, int req_scan); +void autoscan_deinit(struct wpa_supplicant *wpa_s); +int autoscan_notify_scan(struct wpa_supplicant *wpa_s, + struct wpa_scan_results *scan_res); + +#else /* CONFIG_AUTOSCAN */ + +static inline int autoscan_init(struct wpa_supplicant *wpa_s, int req_scan) +{ + return 0; +} + +static inline void autoscan_deinit(struct wpa_supplicant *wpa_s) +{ +} + +static inline int autoscan_notify_scan(struct wpa_supplicant *wpa_s, + struct wpa_scan_results *scan_res) +{ + return 0; +} + +#endif /* CONFIG_AUTOSCAN */ + +#endif /* AUTOSCAN_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/bgscan.h b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/bgscan.h new file mode 100755 index 0000000..9131e4e --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/bgscan.h @@ -0,0 +1,73 @@ +/* + * WPA Supplicant - background scan and roaming interface + * Copyright (c) 2009-2010, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef BGSCAN_H +#define BGSCAN_H + +struct wpa_supplicant; +struct wpa_ssid; + +struct bgscan_ops { + const char *name; + + void * (*init)(struct wpa_supplicant *wpa_s, const char *params, + const struct wpa_ssid *ssid); + void (*deinit)(void *priv); + + int (*notify_scan)(void *priv, struct wpa_scan_results *scan_res); + void (*notify_beacon_loss)(void *priv); + void (*notify_signal_change)(void *priv, int above, + int current_signal, + int current_noise, + int current_txrate); +}; + +#ifdef CONFIG_BGSCAN + +int bgscan_init(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, + const char *name); +void bgscan_deinit(struct wpa_supplicant *wpa_s); +int bgscan_notify_scan(struct wpa_supplicant *wpa_s, + struct wpa_scan_results *scan_res); +void bgscan_notify_beacon_loss(struct wpa_supplicant *wpa_s); +void bgscan_notify_signal_change(struct wpa_supplicant *wpa_s, int above, + int current_signal, int current_noise, + int current_txrate); + +#else /* CONFIG_BGSCAN */ + +static inline int bgscan_init(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid, const char name) +{ + return 0; +} + +static inline void bgscan_deinit(struct wpa_supplicant *wpa_s) +{ +} + +static inline int bgscan_notify_scan(struct wpa_supplicant *wpa_s, + struct wpa_scan_results *scan_res) +{ + return 0; +} + +static inline void bgscan_notify_beacon_loss(struct wpa_supplicant *wpa_s) +{ +} + +static inline void bgscan_notify_signal_change(struct wpa_supplicant *wpa_s, + int above, int current_signal, + int current_noise, + int current_txrate) +{ +} + +#endif /* CONFIG_BGSCAN */ + +#endif /* BGSCAN_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/blacklist.c b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/blacklist.c new file mode 100755 index 0000000..35486be --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/blacklist.c @@ -0,0 +1,118 @@ +/* + * wpa_supplicant - Temporary BSSID blacklist + * Copyright (c) 2003-2007, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "wpa_supplicant_i.h" +#include "blacklist.h" + +/** + * wpa_blacklist_get - Get the blacklist entry for a BSSID + * @wpa_s: Pointer to wpa_supplicant data + * @bssid: BSSID + * Returns: Matching blacklist entry for the BSSID or %NULL if not found + */ +struct wpa_blacklist * wpa_blacklist_get(struct wpa_supplicant *wpa_s, + const u8 *bssid) +{ + struct wpa_blacklist *e; + + if (wpa_s == NULL || bssid == NULL) + return NULL; + + e = wpa_s->blacklist; + while (e) { + if (os_memcmp(e->bssid, bssid, ETH_ALEN) == 0) + return e; + e = e->next; + } + + return NULL; +} + + +/** + * wpa_blacklist_add - Add an BSSID to the blacklist + * @wpa_s: Pointer to wpa_supplicant data + * @bssid: BSSID to be added to the blacklist + * Returns: Current blacklist count on success, -1 on failure + * + * This function adds the specified BSSID to the blacklist or increases the + * blacklist count if the BSSID was already listed. It should be called when + * an association attempt fails either due to the selected BSS rejecting + * association or due to timeout. + * + * This blacklist is used to force %wpa_supplicant to go through all available + * BSSes before retrying to associate with an BSS that rejected or timed out + * association. It does not prevent the listed BSS from being used; it only + * changes the order in which they are tried. + */ +int wpa_blacklist_add(struct wpa_supplicant *wpa_s, const u8 *bssid) +{ + wpa_dbg(wpa_s, MSG_DEBUG, "attempt to add blacklist, but ignore"); + return -1; +} + + +/** + * wpa_blacklist_del - Remove an BSSID from the blacklist + * @wpa_s: Pointer to wpa_supplicant data + * @bssid: BSSID to be removed from the blacklist + * Returns: 0 on success, -1 on failure + */ +int wpa_blacklist_del(struct wpa_supplicant *wpa_s, const u8 *bssid) +{ + struct wpa_blacklist *e, *prev = NULL; + + if (wpa_s == NULL || bssid == NULL) + return -1; + + e = wpa_s->blacklist; + while (e) { + if (os_memcmp(e->bssid, bssid, ETH_ALEN) == 0) { + if (prev == NULL) { + wpa_s->blacklist = e->next; + } else { + prev->next = e->next; + } + wpa_printf(MSG_DEBUG, "Removed BSSID " MACSTR " from " + "blacklist", MAC2STR(bssid)); + os_free(e); + return 0; + } + prev = e; + e = e->next; + } + return -1; +} + + +/** + * wpa_blacklist_clear - Clear the blacklist of all entries + * @wpa_s: Pointer to wpa_supplicant data + */ +void wpa_blacklist_clear(struct wpa_supplicant *wpa_s) +{ + struct wpa_blacklist *e, *prev; + int max_count = 0; + + e = wpa_s->blacklist; + wpa_s->blacklist = NULL; + while (e) { + if (e->count > max_count) + max_count = e->count; + prev = e; + e = e->next; + wpa_printf(MSG_DEBUG, "Removed BSSID " MACSTR " from " + "blacklist (clear)", MAC2STR(prev->bssid)); + os_free(prev); + } + + wpa_s->extra_blacklist_count += max_count; +} diff --git a/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/blacklist.h b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/blacklist.h new file mode 100755 index 0000000..ae06986 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/blacklist.h @@ -0,0 +1,24 @@ +/* + * wpa_supplicant - Temporary BSSID blacklist + * Copyright (c) 2003-2007, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef BLACKLIST_H +#define BLACKLIST_H + +struct wpa_blacklist { + struct wpa_blacklist *next; + u8 bssid[ETH_ALEN]; + int count; +}; + +struct wpa_blacklist * wpa_blacklist_get(struct wpa_supplicant *wpa_s, + const u8 *bssid); +int wpa_blacklist_add(struct wpa_supplicant *wpa_s, const u8 *bssid); +int wpa_blacklist_del(struct wpa_supplicant *wpa_s, const u8 *bssid); +void wpa_blacklist_clear(struct wpa_supplicant *wpa_s); + +#endif /* BLACKLIST_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/bss.c b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/bss.c new file mode 100755 index 0000000..208e0b6 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/bss.c @@ -0,0 +1,1235 @@ +/* + * BSS table + * Copyright (c) 2009-2015, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "utils/eloop.h" +#include "common/ieee802_11_defs.h" +#include "drivers/driver.h" +#include "wpa_supplicant_i.h" +#include "config.h" +#include "notify.h" +#include "scan.h" +#include "bss.h" + + +#define WPA_BSS_FREQ_CHANGED_FLAG BIT(0) +#define WPA_BSS_SIGNAL_CHANGED_FLAG BIT(1) +#define WPA_BSS_PRIVACY_CHANGED_FLAG BIT(2) +#define WPA_BSS_MODE_CHANGED_FLAG BIT(3) +#define WPA_BSS_WPAIE_CHANGED_FLAG BIT(4) +#define WPA_BSS_RSNIE_CHANGED_FLAG BIT(5) +#define WPA_BSS_WPS_CHANGED_FLAG BIT(6) +#define WPA_BSS_RATES_CHANGED_FLAG BIT(7) +#define WPA_BSS_IES_CHANGED_FLAG BIT(8) + + +static void wpa_bss_set_hessid(struct wpa_bss *bss) +{ +#ifdef CONFIG_INTERWORKING + const u8 *ie = wpa_bss_get_ie(bss, WLAN_EID_INTERWORKING); + if (ie == NULL || (ie[1] != 7 && ie[1] != 9)) { + os_memset(bss->hessid, 0, ETH_ALEN); + return; + } + if (ie[1] == 7) + os_memcpy(bss->hessid, ie + 3, ETH_ALEN); + else + os_memcpy(bss->hessid, ie + 5, ETH_ALEN); +#endif /* CONFIG_INTERWORKING */ +} + + +/** + * wpa_bss_anqp_alloc - Allocate ANQP data structure for a BSS entry + * Returns: Allocated ANQP data structure or %NULL on failure + * + * The allocated ANQP data structure has its users count set to 1. It may be + * shared by multiple BSS entries and each shared entry is freed with + * wpa_bss_anqp_free(). + */ +struct wpa_bss_anqp * wpa_bss_anqp_alloc(void) +{ + struct wpa_bss_anqp *anqp; + anqp = os_zalloc(sizeof(*anqp)); + if (anqp == NULL) + return NULL; + anqp->users = 1; + return anqp; +} + + +/** + * wpa_bss_anqp_clone - Clone an ANQP data structure + * @anqp: ANQP data structure from wpa_bss_anqp_alloc() + * Returns: Cloned ANQP data structure or %NULL on failure + */ +static struct wpa_bss_anqp * wpa_bss_anqp_clone(struct wpa_bss_anqp *anqp) +{ + struct wpa_bss_anqp *n; + + n = os_zalloc(sizeof(*n)); + if (n == NULL) + return NULL; + +#define ANQP_DUP(f) if (anqp->f) n->f = wpabuf_dup(anqp->f) +#ifdef CONFIG_INTERWORKING + ANQP_DUP(capability_list); + ANQP_DUP(venue_name); + ANQP_DUP(network_auth_type); + ANQP_DUP(roaming_consortium); + ANQP_DUP(ip_addr_type_availability); + ANQP_DUP(nai_realm); + ANQP_DUP(anqp_3gpp); + ANQP_DUP(domain_name); +#endif /* CONFIG_INTERWORKING */ +#ifdef CONFIG_HS20 + ANQP_DUP(hs20_capability_list); + ANQP_DUP(hs20_operator_friendly_name); + ANQP_DUP(hs20_wan_metrics); + ANQP_DUP(hs20_connection_capability); + ANQP_DUP(hs20_operating_class); + ANQP_DUP(hs20_osu_providers_list); +#endif /* CONFIG_HS20 */ +#undef ANQP_DUP + + return n; +} + + +/** + * wpa_bss_anqp_unshare_alloc - Unshare ANQP data (if shared) in a BSS entry + * @bss: BSS entry + * Returns: 0 on success, -1 on failure + * + * This function ensures the specific BSS entry has an ANQP data structure that + * is not shared with any other BSS entry. + */ +int wpa_bss_anqp_unshare_alloc(struct wpa_bss *bss) +{ + struct wpa_bss_anqp *anqp; + + if (bss->anqp && bss->anqp->users > 1) { + /* allocated, but shared - clone an unshared copy */ + anqp = wpa_bss_anqp_clone(bss->anqp); + if (anqp == NULL) + return -1; + anqp->users = 1; + bss->anqp->users--; + bss->anqp = anqp; + return 0; + } + + if (bss->anqp) + return 0; /* already allocated and not shared */ + + /* not allocated - allocate a new storage area */ + bss->anqp = wpa_bss_anqp_alloc(); + return bss->anqp ? 0 : -1; +} + + +/** + * wpa_bss_anqp_free - Free an ANQP data structure + * @anqp: ANQP data structure from wpa_bss_anqp_alloc() or wpa_bss_anqp_clone() + */ +static void wpa_bss_anqp_free(struct wpa_bss_anqp *anqp) +{ + if (anqp == NULL) + return; + + anqp->users--; + if (anqp->users > 0) { + /* Another BSS entry holds a pointer to this ANQP info */ + return; + } + +#ifdef CONFIG_INTERWORKING + wpabuf_free(anqp->capability_list); + wpabuf_free(anqp->venue_name); + wpabuf_free(anqp->network_auth_type); + wpabuf_free(anqp->roaming_consortium); + wpabuf_free(anqp->ip_addr_type_availability); + wpabuf_free(anqp->nai_realm); + wpabuf_free(anqp->anqp_3gpp); + wpabuf_free(anqp->domain_name); +#endif /* CONFIG_INTERWORKING */ +#ifdef CONFIG_HS20 + wpabuf_free(anqp->hs20_capability_list); + wpabuf_free(anqp->hs20_operator_friendly_name); + wpabuf_free(anqp->hs20_wan_metrics); + wpabuf_free(anqp->hs20_connection_capability); + wpabuf_free(anqp->hs20_operating_class); + wpabuf_free(anqp->hs20_osu_providers_list); +#endif /* CONFIG_HS20 */ + + os_free(anqp); +} + + +static void wpa_bss_update_pending_connect(struct wpa_supplicant *wpa_s, + struct wpa_bss *old_bss, + struct wpa_bss *new_bss) +{ + struct wpa_radio_work *work; + struct wpa_connect_work *cwork; + + work = radio_work_pending(wpa_s, "sme-connect"); + if (!work) + work = radio_work_pending(wpa_s, "connect"); + if (!work) + return; + + cwork = work->ctx; + if (cwork->bss != old_bss) + return; + + wpa_printf(MSG_DEBUG, + "Update BSS pointer for the pending connect radio work"); + cwork->bss = new_bss; + if (!new_bss) + cwork->bss_removed = 1; +} + + +static void wpa_bss_remove(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, + const char *reason) +{ + if (wpa_s->last_scan_res) { + unsigned int i; + for (i = 0; i < wpa_s->last_scan_res_used; i++) { + if (wpa_s->last_scan_res[i] == bss) { + os_memmove(&wpa_s->last_scan_res[i], + &wpa_s->last_scan_res[i + 1], + (wpa_s->last_scan_res_used - i - 1) + * sizeof(struct wpa_bss *)); + wpa_s->last_scan_res_used--; + break; + } + } + } + wpa_bss_update_pending_connect(wpa_s, bss, NULL); + dl_list_del(&bss->list); + dl_list_del(&bss->list_id); + wpa_s->num_bss--; + wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Remove id %u BSSID " MACSTR + " SSID '%s' due to %s", bss->id, MAC2STR(bss->bssid), + wpa_ssid_txt(bss->ssid, bss->ssid_len), reason); + wpas_notify_bss_removed(wpa_s, bss->bssid, bss->id); + wpa_bss_anqp_free(bss->anqp); + os_free(bss); +} + + +/** + * wpa_bss_get - Fetch a BSS table entry based on BSSID and SSID + * @wpa_s: Pointer to wpa_supplicant data + * @bssid: BSSID + * @ssid: SSID + * @ssid_len: Length of @ssid + * Returns: Pointer to the BSS entry or %NULL if not found + */ +struct wpa_bss * wpa_bss_get(struct wpa_supplicant *wpa_s, const u8 *bssid, + const u8 *ssid, size_t ssid_len) +{ + struct wpa_bss *bss; + if (!wpa_supplicant_filter_bssid_match(wpa_s, bssid)) + return NULL; + dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { + if (os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0 && + bss->ssid_len == ssid_len && + os_memcmp(bss->ssid, ssid, ssid_len) == 0) + return bss; + } + return NULL; +} + + +static void calculate_update_time(const struct os_reltime *fetch_time, + unsigned int age_ms, + struct os_reltime *update_time) +{ + os_time_t usec; + + update_time->sec = fetch_time->sec; + update_time->usec = fetch_time->usec; + update_time->sec -= age_ms / 1000; + usec = (age_ms % 1000) * 1000; + if (update_time->usec < usec) { + update_time->sec--; + update_time->usec += 1000000; + } + update_time->usec -= usec; +} + + +static void wpa_bss_copy_res(struct wpa_bss *dst, struct wpa_scan_res *src, + struct os_reltime *fetch_time) +{ + dst->flags = src->flags; + os_memcpy(dst->bssid, src->bssid, ETH_ALEN); + dst->freq = src->freq; + dst->beacon_int = src->beacon_int; + dst->caps = src->caps; + dst->qual = src->qual; + dst->noise = src->noise; + dst->level = src->level; + dst->tsf = src->tsf; + dst->est_throughput = src->est_throughput; + dst->snr = src->snr; + + calculate_update_time(fetch_time, src->age, &dst->last_update); +} + + +static int wpa_bss_known(struct wpa_supplicant *wpa_s, struct wpa_bss *bss) +{ + struct wpa_ssid *ssid; + + for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { + if (ssid->ssid == NULL || ssid->ssid_len == 0) + continue; + if (ssid->ssid_len == bss->ssid_len && + os_memcmp(ssid->ssid, bss->ssid, ssid->ssid_len) == 0) + return 1; + } + + return 0; +} + + +static int wpa_bss_in_use(struct wpa_supplicant *wpa_s, struct wpa_bss *bss) +{ + if (bss == wpa_s->current_bss) + return 1; + + if (wpa_s->current_bss && + (bss->ssid_len != wpa_s->current_bss->ssid_len || + os_memcmp(bss->ssid, wpa_s->current_bss->ssid, + bss->ssid_len) != 0)) + return 0; /* SSID has changed */ + + return !is_zero_ether_addr(bss->bssid) && + (os_memcmp(bss->bssid, wpa_s->bssid, ETH_ALEN) == 0 || + os_memcmp(bss->bssid, wpa_s->pending_bssid, ETH_ALEN) == 0); +} + + +static int wpa_bss_remove_oldest_unknown(struct wpa_supplicant *wpa_s) +{ + struct wpa_bss *bss; + + dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { + if (!wpa_bss_known(wpa_s, bss)) { + wpa_bss_remove(wpa_s, bss, __func__); + return 0; + } + } + + return -1; +} + + +static int wpa_bss_remove_oldest(struct wpa_supplicant *wpa_s) +{ + struct wpa_bss *bss; + + /* + * Remove the oldest entry that does not match with any configured + * network. + */ + if (wpa_bss_remove_oldest_unknown(wpa_s) == 0) + return 0; + + /* + * Remove the oldest entry that isn't currently in use. + */ + dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { + if (!wpa_bss_in_use(wpa_s, bss)) { + wpa_bss_remove(wpa_s, bss, __func__); + return 0; + } + } + + return -1; +} + + +static struct wpa_bss * wpa_bss_add(struct wpa_supplicant *wpa_s, + const u8 *ssid, size_t ssid_len, + struct wpa_scan_res *res, + struct os_reltime *fetch_time) +{ + struct wpa_bss *bss; + + bss = os_zalloc(sizeof(*bss) + res->ie_len + res->beacon_ie_len); + if (bss == NULL) + return NULL; + bss->id = wpa_s->bss_next_id++; + bss->last_update_idx = wpa_s->bss_update_idx; + wpa_bss_copy_res(bss, res, fetch_time); + os_memcpy(bss->ssid, ssid, ssid_len); + bss->ssid_len = ssid_len; + bss->ie_len = res->ie_len; + bss->beacon_ie_len = res->beacon_ie_len; + os_memcpy(bss + 1, res + 1, res->ie_len + res->beacon_ie_len); + wpa_bss_set_hessid(bss); + + if (wpa_s->num_bss + 1 > wpa_s->conf->bss_max_count && + wpa_bss_remove_oldest(wpa_s) != 0) { + wpa_printf(MSG_ERROR, "Increasing the MAX BSS count to %d " + "because all BSSes are in use. We should normally " + "not get here!", (int) wpa_s->num_bss + 1); + wpa_s->conf->bss_max_count = wpa_s->num_bss + 1; + } + + dl_list_add_tail(&wpa_s->bss, &bss->list); + dl_list_add_tail(&wpa_s->bss_id, &bss->list_id); + wpa_s->num_bss++; + wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Add new id %u BSSID " MACSTR + " SSID '%s' freq %d", + bss->id, MAC2STR(bss->bssid), wpa_ssid_txt(ssid, ssid_len), + bss->freq); + wpas_notify_bss_added(wpa_s, bss->bssid, bss->id); + return bss; +} + + +static int are_ies_equal(const struct wpa_bss *old, + const struct wpa_scan_res *new_res, u32 ie) +{ + const u8 *old_ie, *new_ie; + struct wpabuf *old_ie_buff = NULL; + struct wpabuf *new_ie_buff = NULL; + int new_ie_len, old_ie_len, ret, is_multi; + + switch (ie) { + case WPA_IE_VENDOR_TYPE: + old_ie = wpa_bss_get_vendor_ie(old, ie); + new_ie = wpa_scan_get_vendor_ie(new_res, ie); + is_multi = 0; + break; + case WPS_IE_VENDOR_TYPE: + old_ie_buff = wpa_bss_get_vendor_ie_multi(old, ie); + new_ie_buff = wpa_scan_get_vendor_ie_multi(new_res, ie); + is_multi = 1; + break; + case WLAN_EID_RSN: + case WLAN_EID_SUPP_RATES: + case WLAN_EID_EXT_SUPP_RATES: + old_ie = wpa_bss_get_ie(old, ie); + new_ie = wpa_scan_get_ie(new_res, ie); + is_multi = 0; + break; + default: + wpa_printf(MSG_DEBUG, "bss: %s: cannot compare IEs", __func__); + return 0; + } + + if (is_multi) { + /* in case of multiple IEs stored in buffer */ + old_ie = old_ie_buff ? wpabuf_head_u8(old_ie_buff) : NULL; + new_ie = new_ie_buff ? wpabuf_head_u8(new_ie_buff) : NULL; + old_ie_len = old_ie_buff ? wpabuf_len(old_ie_buff) : 0; + new_ie_len = new_ie_buff ? wpabuf_len(new_ie_buff) : 0; + } else { + /* in case of single IE */ + old_ie_len = old_ie ? old_ie[1] + 2 : 0; + new_ie_len = new_ie ? new_ie[1] + 2 : 0; + } + + if (!old_ie || !new_ie) + ret = !old_ie && !new_ie; + else + ret = (old_ie_len == new_ie_len && + os_memcmp(old_ie, new_ie, old_ie_len) == 0); + + wpabuf_free(old_ie_buff); + wpabuf_free(new_ie_buff); + + return ret; +} + + +static u32 wpa_bss_compare_res(const struct wpa_bss *old, + const struct wpa_scan_res *new_res) +{ + u32 changes = 0; + int caps_diff = old->caps ^ new_res->caps; + + if (old->freq != new_res->freq) + changes |= WPA_BSS_FREQ_CHANGED_FLAG; + + if (old->level != new_res->level) + changes |= WPA_BSS_SIGNAL_CHANGED_FLAG; + + if (caps_diff & IEEE80211_CAP_PRIVACY) + changes |= WPA_BSS_PRIVACY_CHANGED_FLAG; + + if (caps_diff & IEEE80211_CAP_IBSS) + changes |= WPA_BSS_MODE_CHANGED_FLAG; + + if (old->ie_len == new_res->ie_len && + os_memcmp(old + 1, new_res + 1, old->ie_len) == 0) + return changes; + changes |= WPA_BSS_IES_CHANGED_FLAG; + + if (!are_ies_equal(old, new_res, WPA_IE_VENDOR_TYPE)) + changes |= WPA_BSS_WPAIE_CHANGED_FLAG; + + if (!are_ies_equal(old, new_res, WLAN_EID_RSN)) + changes |= WPA_BSS_RSNIE_CHANGED_FLAG; + + if (!are_ies_equal(old, new_res, WPS_IE_VENDOR_TYPE)) + changes |= WPA_BSS_WPS_CHANGED_FLAG; + + if (!are_ies_equal(old, new_res, WLAN_EID_SUPP_RATES) || + !are_ies_equal(old, new_res, WLAN_EID_EXT_SUPP_RATES)) + changes |= WPA_BSS_RATES_CHANGED_FLAG; + + return changes; +} + + +static void notify_bss_changes(struct wpa_supplicant *wpa_s, u32 changes, + const struct wpa_bss *bss) +{ + if (changes & WPA_BSS_FREQ_CHANGED_FLAG) + wpas_notify_bss_freq_changed(wpa_s, bss->id); + + if (changes & WPA_BSS_SIGNAL_CHANGED_FLAG) + wpas_notify_bss_signal_changed(wpa_s, bss->id); + + if (changes & WPA_BSS_PRIVACY_CHANGED_FLAG) + wpas_notify_bss_privacy_changed(wpa_s, bss->id); + + if (changes & WPA_BSS_MODE_CHANGED_FLAG) + wpas_notify_bss_mode_changed(wpa_s, bss->id); + + if (changes & WPA_BSS_WPAIE_CHANGED_FLAG) + wpas_notify_bss_wpaie_changed(wpa_s, bss->id); + + if (changes & WPA_BSS_RSNIE_CHANGED_FLAG) + wpas_notify_bss_rsnie_changed(wpa_s, bss->id); + + if (changes & WPA_BSS_WPS_CHANGED_FLAG) + wpas_notify_bss_wps_changed(wpa_s, bss->id); + + if (changes & WPA_BSS_IES_CHANGED_FLAG) + wpas_notify_bss_ies_changed(wpa_s, bss->id); + + if (changes & WPA_BSS_RATES_CHANGED_FLAG) + wpas_notify_bss_rates_changed(wpa_s, bss->id); + + wpas_notify_bss_seen(wpa_s, bss->id); +} + + +static struct wpa_bss * +wpa_bss_update(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, + struct wpa_scan_res *res, struct os_reltime *fetch_time) +{ + u32 changes; + + changes = wpa_bss_compare_res(bss, res); + if (changes & WPA_BSS_FREQ_CHANGED_FLAG) + wpa_printf(MSG_DEBUG, "BSS: " MACSTR " changed freq %d --> %d", + MAC2STR(bss->bssid), bss->freq, res->freq); + bss->scan_miss_count = 0; + bss->last_update_idx = wpa_s->bss_update_idx; + wpa_bss_copy_res(bss, res, fetch_time); + /* Move the entry to the end of the list */ + dl_list_del(&bss->list); +#ifdef CONFIG_P2P + if (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) && + !wpa_scan_get_vendor_ie(res, P2P_IE_VENDOR_TYPE)) { + /* + * This can happen when non-P2P station interface runs a scan + * without P2P IE in the Probe Request frame. P2P GO would reply + * to that with a Probe Response that does not include P2P IE. + * Do not update the IEs in this BSS entry to avoid such loss of + * information that may be needed for P2P operations to + * determine group information. + */ + wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Do not update scan IEs for " + MACSTR " since that would remove P2P IE information", + MAC2STR(bss->bssid)); + } else +#endif /* CONFIG_P2P */ + if (bss->ie_len + bss->beacon_ie_len >= + res->ie_len + res->beacon_ie_len) { + os_memcpy(bss + 1, res + 1, res->ie_len + res->beacon_ie_len); + bss->ie_len = res->ie_len; + bss->beacon_ie_len = res->beacon_ie_len; + } else { + struct wpa_bss *nbss; + struct dl_list *prev = bss->list_id.prev; + dl_list_del(&bss->list_id); + nbss = os_realloc(bss, sizeof(*bss) + res->ie_len + + res->beacon_ie_len); + if (nbss) { + unsigned int i; + for (i = 0; i < wpa_s->last_scan_res_used; i++) { + if (wpa_s->last_scan_res[i] == bss) { + wpa_s->last_scan_res[i] = nbss; + break; + } + } + if (wpa_s->current_bss == bss) + wpa_s->current_bss = nbss; + wpa_bss_update_pending_connect(wpa_s, bss, nbss); + bss = nbss; + os_memcpy(bss + 1, res + 1, + res->ie_len + res->beacon_ie_len); + bss->ie_len = res->ie_len; + bss->beacon_ie_len = res->beacon_ie_len; + } + dl_list_add(prev, &bss->list_id); + } + if (changes & WPA_BSS_IES_CHANGED_FLAG) + wpa_bss_set_hessid(bss); + dl_list_add_tail(&wpa_s->bss, &bss->list); + + notify_bss_changes(wpa_s, changes, bss); + + return bss; +} + + +/** + * wpa_bss_update_start - Start a BSS table update from scan results + * @wpa_s: Pointer to wpa_supplicant data + * + * This function is called at the start of each BSS table update round for new + * scan results. The actual scan result entries are indicated with calls to + * wpa_bss_update_scan_res() and the update round is finished with a call to + * wpa_bss_update_end(). + */ +void wpa_bss_update_start(struct wpa_supplicant *wpa_s) +{ + wpa_s->bss_update_idx++; + wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Start scan result update %u", + wpa_s->bss_update_idx); + wpa_s->last_scan_res_used = 0; +} + + +/** + * wpa_bss_update_scan_res - Update a BSS table entry based on a scan result + * @wpa_s: Pointer to wpa_supplicant data + * @res: Scan result + * @fetch_time: Time when the result was fetched from the driver + * + * This function updates a BSS table entry (or adds one) based on a scan result. + * This is called separately for each scan result between the calls to + * wpa_bss_update_start() and wpa_bss_update_end(). + */ +void wpa_bss_update_scan_res(struct wpa_supplicant *wpa_s, + struct wpa_scan_res *res, + struct os_reltime *fetch_time) +{ + const u8 *ssid, *p2p; + struct wpa_bss *bss; + + if (wpa_s->conf->ignore_old_scan_res) { + struct os_reltime update; + calculate_update_time(fetch_time, res->age, &update); + if (os_reltime_before(&update, &wpa_s->scan_trigger_time)) { + struct os_reltime age; + os_reltime_sub(&wpa_s->scan_trigger_time, &update, + &age); + wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Ignore driver BSS " + "table entry that is %u.%06u seconds older " + "than our scan trigger", + (unsigned int) age.sec, + (unsigned int) age.usec); + return; + } + } + + ssid = wpa_scan_get_ie(res, WLAN_EID_SSID); + if (ssid == NULL) { + wpa_dbg(wpa_s, MSG_DEBUG, "BSS: No SSID IE included for " + MACSTR, MAC2STR(res->bssid)); + return; + } + if (ssid[1] > SSID_MAX_LEN) { + wpa_dbg(wpa_s, MSG_DEBUG, "BSS: Too long SSID IE included for " + MACSTR, MAC2STR(res->bssid)); + return; + } + + p2p = wpa_scan_get_vendor_ie(res, P2P_IE_VENDOR_TYPE); +#ifdef CONFIG_P2P + if (p2p == NULL && + wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE) { + /* + * If it's a P2P specific interface, then don't update + * the scan result without a P2P IE. + */ + wpa_printf(MSG_DEBUG, "BSS: No P2P IE - skipping BSS " MACSTR + " update for P2P interface", MAC2STR(res->bssid)); + return; + } +#endif /* CONFIG_P2P */ + if (p2p && ssid[1] == P2P_WILDCARD_SSID_LEN && + os_memcmp(ssid + 2, P2P_WILDCARD_SSID, P2P_WILDCARD_SSID_LEN) == 0) + return; /* Skip P2P listen discovery results here */ + + /* TODO: add option for ignoring BSSes we are not interested in + * (to save memory) + mesh = wpa_scan_get_ie(res, WLAN_EID_MESH_ID); + if (mesh && mesh[1] <= SSID_MAX_LEN) + ssid = mesh;*/ + + bss = wpa_bss_get(wpa_s, res->bssid, ssid + 2, ssid[1]); + if (bss == NULL) + bss = wpa_bss_add(wpa_s, ssid + 2, ssid[1], res, fetch_time); + else { + bss = wpa_bss_update(wpa_s, bss, res, fetch_time); + if (wpa_s->last_scan_res) { + unsigned int i; + for (i = 0; i < wpa_s->last_scan_res_used; i++) { + if (bss == wpa_s->last_scan_res[i]) { + /* Already in the list */ + return; + } + } + } + } + + if (bss == NULL) + return; + if (wpa_s->last_scan_res_used >= wpa_s->last_scan_res_size) { + struct wpa_bss **n; + unsigned int siz; + if (wpa_s->last_scan_res_size == 0) + siz = 32; + else + siz = wpa_s->last_scan_res_size * 2; + n = os_realloc_array(wpa_s->last_scan_res, siz, + sizeof(struct wpa_bss *)); + if (n == NULL) + return; + wpa_s->last_scan_res = n; + wpa_s->last_scan_res_size = siz; + } + + if (wpa_s->last_scan_res) + wpa_s->last_scan_res[wpa_s->last_scan_res_used++] = bss; +} + + +static int wpa_bss_included_in_scan(const struct wpa_bss *bss, + const struct scan_info *info) +{ + int found; + size_t i; + + if (info == NULL) + return 1; + + if (info->num_freqs) { + found = 0; + for (i = 0; i < info->num_freqs; i++) { + if (bss->freq == info->freqs[i]) { + found = 1; + break; + } + } + if (!found) + return 0; + } + + if (info->num_ssids) { + found = 0; + for (i = 0; i < info->num_ssids; i++) { + const struct wpa_driver_scan_ssid *s = &info->ssids[i]; + if ((s->ssid == NULL || s->ssid_len == 0) || + (s->ssid_len == bss->ssid_len && + os_memcmp(s->ssid, bss->ssid, bss->ssid_len) == + 0)) { + found = 1; + break; + } + } + if (!found) + return 0; + } + + return 1; +} + + +/** + * wpa_bss_update_end - End a BSS table update from scan results + * @wpa_s: Pointer to wpa_supplicant data + * @info: Information about scan parameters + * @new_scan: Whether this update round was based on a new scan + * + * This function is called at the end of each BSS table update round for new + * scan results. The start of the update was indicated with a call to + * wpa_bss_update_start(). + */ +void wpa_bss_update_end(struct wpa_supplicant *wpa_s, struct scan_info *info, + int new_scan) +{ + struct wpa_bss *bss, *n; + + os_get_reltime(&wpa_s->last_scan); + if (!new_scan) + return; /* do not expire entries without new scan */ + + dl_list_for_each_safe(bss, n, &wpa_s->bss, struct wpa_bss, list) { + if (wpa_bss_in_use(wpa_s, bss)) + continue; + if (!wpa_bss_included_in_scan(bss, info)) + continue; /* expire only BSSes that were scanned */ + if (bss->last_update_idx < wpa_s->bss_update_idx) + bss->scan_miss_count++; + if (bss->scan_miss_count >= + wpa_s->conf->bss_expiration_scan_count) { + wpa_bss_remove(wpa_s, bss, "no match in scan"); + } + } + + wpa_printf(MSG_DEBUG, "BSS: last_scan_res_used=%u/%u", + wpa_s->last_scan_res_used, wpa_s->last_scan_res_size); +} + + +/** + * wpa_bss_flush_by_age - Flush old BSS entries + * @wpa_s: Pointer to wpa_supplicant data + * @age: Maximum entry age in seconds + * + * Remove BSS entries that have not been updated during the last @age seconds. + */ +void wpa_bss_flush_by_age(struct wpa_supplicant *wpa_s, int age) +{ + struct wpa_bss *bss, *n; + struct os_reltime t; + + if (dl_list_empty(&wpa_s->bss)) + return; + + os_get_reltime(&t); + t.sec -= age; + + dl_list_for_each_safe(bss, n, &wpa_s->bss, struct wpa_bss, list) { + if (wpa_bss_in_use(wpa_s, bss)) + continue; + + if (os_reltime_before(&bss->last_update, &t)) { + wpa_bss_remove(wpa_s, bss, __func__); + } else + break; + } +} + + +/** + * wpa_bss_init - Initialize BSS table + * @wpa_s: Pointer to wpa_supplicant data + * Returns: 0 on success, -1 on failure + * + * This prepares BSS table lists and timer for periodic updates. The BSS table + * is deinitialized with wpa_bss_deinit() once not needed anymore. + */ +int wpa_bss_init(struct wpa_supplicant *wpa_s) +{ + dl_list_init(&wpa_s->bss); + dl_list_init(&wpa_s->bss_id); + return 0; +} + + +/** + * wpa_bss_flush - Flush all unused BSS entries + * @wpa_s: Pointer to wpa_supplicant data + */ +void wpa_bss_flush(struct wpa_supplicant *wpa_s) +{ + struct wpa_bss *bss, *n; + + wpa_s->clear_driver_scan_cache = 1; + + if (wpa_s->bss.next == NULL) + return; /* BSS table not yet initialized */ + + dl_list_for_each_safe(bss, n, &wpa_s->bss, struct wpa_bss, list) { + if (wpa_bss_in_use(wpa_s, bss)) + continue; + wpa_bss_remove(wpa_s, bss, __func__); + } +} + + +/** + * wpa_bss_deinit - Deinitialize BSS table + * @wpa_s: Pointer to wpa_supplicant data + */ +void wpa_bss_deinit(struct wpa_supplicant *wpa_s) +{ + wpa_bss_flush(wpa_s); +} + + +/** + * wpa_bss_get_bssid - Fetch a BSS table entry based on BSSID + * @wpa_s: Pointer to wpa_supplicant data + * @bssid: BSSID + * Returns: Pointer to the BSS entry or %NULL if not found + */ +struct wpa_bss * wpa_bss_get_bssid(struct wpa_supplicant *wpa_s, + const u8 *bssid) +{ + struct wpa_bss *bss; + if (!wpa_supplicant_filter_bssid_match(wpa_s, bssid)) + return NULL; + dl_list_for_each_reverse(bss, &wpa_s->bss, struct wpa_bss, list) { + if (os_memcmp(bss->bssid, bssid, ETH_ALEN) == 0) + return bss; + } + return NULL; +} + + +/** + * wpa_bss_get_bssid_latest - Fetch the latest BSS table entry based on BSSID + * @wpa_s: Pointer to wpa_supplicant data + * @bssid: BSSID + * Returns: Pointer to the BSS entry or %NULL if not found + * + * This function is like wpa_bss_get_bssid(), but full BSS table is iterated to + * find the entry that has the most recent update. This can help in finding the + * correct entry in cases where the SSID of the AP may have changed recently + * (e.g., in WPS reconfiguration cases). + */ +struct wpa_bss * wpa_bss_get_bssid_latest(struct wpa_supplicant *wpa_s, + const u8 *bssid) +{ + struct wpa_bss *bss, *found = NULL; + if (!wpa_supplicant_filter_bssid_match(wpa_s, bssid)) + return NULL; + dl_list_for_each_reverse(bss, &wpa_s->bss, struct wpa_bss, list) { + if (os_memcmp(bss->bssid, bssid, ETH_ALEN) != 0) + continue; + if (found == NULL || + os_reltime_before(&found->last_update, &bss->last_update)) + found = bss; + } + return found; +} + + +#ifdef CONFIG_P2P +/** + * wpa_bss_get_p2p_dev_addr - Fetch a BSS table entry based on P2P Device Addr + * @wpa_s: Pointer to wpa_supplicant data + * @dev_addr: P2P Device Address of the GO + * Returns: Pointer to the BSS entry or %NULL if not found + */ +struct wpa_bss * wpa_bss_get_p2p_dev_addr(struct wpa_supplicant *wpa_s, + const u8 *dev_addr) +{ + struct wpa_bss *bss; + dl_list_for_each_reverse(bss, &wpa_s->bss, struct wpa_bss, list) { + u8 addr[ETH_ALEN]; + if (p2p_parse_dev_addr((const u8 *) (bss + 1), bss->ie_len, + addr) == 0 && + os_memcmp(addr, dev_addr, ETH_ALEN) == 0) + return bss; + } + return NULL; +} +#endif /* CONFIG_P2P */ + + +/** + * wpa_bss_get_id - Fetch a BSS table entry based on identifier + * @wpa_s: Pointer to wpa_supplicant data + * @id: Unique identifier (struct wpa_bss::id) assigned for the entry + * Returns: Pointer to the BSS entry or %NULL if not found + */ +struct wpa_bss * wpa_bss_get_id(struct wpa_supplicant *wpa_s, unsigned int id) +{ + struct wpa_bss *bss; + dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { + if (bss->id == id) + return bss; + } + return NULL; +} + + +/** + * wpa_bss_get_id_range - Fetch a BSS table entry based on identifier range + * @wpa_s: Pointer to wpa_supplicant data + * @idf: Smallest allowed identifier assigned for the entry + * @idf: Largest allowed identifier assigned for the entry + * Returns: Pointer to the BSS entry or %NULL if not found + * + * This function is similar to wpa_bss_get_id() but allows a BSS entry with the + * smallest id value to be fetched within the specified range without the + * caller having to know the exact id. + */ +struct wpa_bss * wpa_bss_get_id_range(struct wpa_supplicant *wpa_s, + unsigned int idf, unsigned int idl) +{ + struct wpa_bss *bss; + dl_list_for_each(bss, &wpa_s->bss_id, struct wpa_bss, list_id) { + if (bss->id >= idf && bss->id <= idl) + return bss; + } + return NULL; +} + + +/** + * wpa_bss_get_ie - Fetch a specified information element from a BSS entry + * @bss: BSS table entry + * @ie: Information element identitifier (WLAN_EID_*) + * Returns: Pointer to the information element (id field) or %NULL if not found + * + * This function returns the first matching information element in the BSS + * entry. + */ +const u8 * wpa_bss_get_ie(const struct wpa_bss *bss, u8 ie) +{ + const u8 *end, *pos; + + pos = (const u8 *) (bss + 1); + end = pos + bss->ie_len; + + while (pos + 1 < end) { + if (pos + 2 + pos[1] > end) + break; + if (pos[0] == ie) + return pos; + pos += 2 + pos[1]; + } + + return NULL; +} + + +/** + * wpa_bss_get_vendor_ie - Fetch a vendor information element from a BSS entry + * @bss: BSS table entry + * @vendor_type: Vendor type (four octets starting the IE payload) + * Returns: Pointer to the information element (id field) or %NULL if not found + * + * This function returns the first matching information element in the BSS + * entry. + */ +const u8 * wpa_bss_get_vendor_ie(const struct wpa_bss *bss, u32 vendor_type) +{ + const u8 *end, *pos; + + pos = (const u8 *) (bss + 1); + end = pos + bss->ie_len; + + while (pos + 1 < end) { + if (pos + 2 + pos[1] > end) + break; + if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && + vendor_type == WPA_GET_BE32(&pos[2])) + return pos; + pos += 2 + pos[1]; + } + + return NULL; +} + + +/** + * wpa_bss_get_vendor_ie_beacon - Fetch a vendor information from a BSS entry + * @bss: BSS table entry + * @vendor_type: Vendor type (four octets starting the IE payload) + * Returns: Pointer to the information element (id field) or %NULL if not found + * + * This function returns the first matching information element in the BSS + * entry. + * + * This function is like wpa_bss_get_vendor_ie(), but uses IE buffer only + * from Beacon frames instead of either Beacon or Probe Response frames. + */ +const u8 * wpa_bss_get_vendor_ie_beacon(const struct wpa_bss *bss, + u32 vendor_type) +{ + const u8 *end, *pos; + + if (bss->beacon_ie_len == 0) + return NULL; + + pos = (const u8 *) (bss + 1); + pos += bss->ie_len; + end = pos + bss->beacon_ie_len; + + while (pos + 1 < end) { + if (pos + 2 + pos[1] > end) + break; + if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && + vendor_type == WPA_GET_BE32(&pos[2])) + return pos; + pos += 2 + pos[1]; + } + + return NULL; +} + + +/** + * wpa_bss_get_vendor_ie_multi - Fetch vendor IE data from a BSS entry + * @bss: BSS table entry + * @vendor_type: Vendor type (four octets starting the IE payload) + * Returns: Pointer to the information element payload or %NULL if not found + * + * This function returns concatenated payload of possibly fragmented vendor + * specific information elements in the BSS entry. The caller is responsible for + * freeing the returned buffer. + */ +struct wpabuf * wpa_bss_get_vendor_ie_multi(const struct wpa_bss *bss, + u32 vendor_type) +{ + struct wpabuf *buf; + const u8 *end, *pos; + + buf = wpabuf_alloc(bss->ie_len); + if (buf == NULL) + return NULL; + + pos = (const u8 *) (bss + 1); + end = pos + bss->ie_len; + + while (pos + 1 < end) { + if (pos + 2 + pos[1] > end) + break; + if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && + vendor_type == WPA_GET_BE32(&pos[2])) + wpabuf_put_data(buf, pos + 2 + 4, pos[1] - 4); + pos += 2 + pos[1]; + } + + if (wpabuf_len(buf) == 0) { + wpabuf_free(buf); + buf = NULL; + } + + return buf; +} + + +/** + * wpa_bss_get_vendor_ie_multi_beacon - Fetch vendor IE data from a BSS entry + * @bss: BSS table entry + * @vendor_type: Vendor type (four octets starting the IE payload) + * Returns: Pointer to the information element payload or %NULL if not found + * + * This function returns concatenated payload of possibly fragmented vendor + * specific information elements in the BSS entry. The caller is responsible for + * freeing the returned buffer. + * + * This function is like wpa_bss_get_vendor_ie_multi(), but uses IE buffer only + * from Beacon frames instead of either Beacon or Probe Response frames. + */ +struct wpabuf * wpa_bss_get_vendor_ie_multi_beacon(const struct wpa_bss *bss, + u32 vendor_type) +{ + struct wpabuf *buf; + const u8 *end, *pos; + + buf = wpabuf_alloc(bss->beacon_ie_len); + if (buf == NULL) + return NULL; + + pos = (const u8 *) (bss + 1); + pos += bss->ie_len; + end = pos + bss->beacon_ie_len; + + while (pos + 1 < end) { + if (pos + 2 + pos[1] > end) + break; + if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && + vendor_type == WPA_GET_BE32(&pos[2])) + wpabuf_put_data(buf, pos + 2 + 4, pos[1] - 4); + pos += 2 + pos[1]; + } + + if (wpabuf_len(buf) == 0) { + wpabuf_free(buf); + buf = NULL; + } + + return buf; +} + + +/** + * wpa_bss_get_max_rate - Get maximum legacy TX rate supported in a BSS + * @bss: BSS table entry + * Returns: Maximum legacy rate in units of 500 kbps + */ +int wpa_bss_get_max_rate(const struct wpa_bss *bss) +{ + int rate = 0; + const u8 *ie; + int i; + + ie = wpa_bss_get_ie(bss, WLAN_EID_SUPP_RATES); + for (i = 0; ie && i < ie[1]; i++) { + if ((ie[i + 2] & 0x7f) > rate) + rate = ie[i + 2] & 0x7f; + } + + ie = wpa_bss_get_ie(bss, WLAN_EID_EXT_SUPP_RATES); + for (i = 0; ie && i < ie[1]; i++) { + if ((ie[i + 2] & 0x7f) > rate) + rate = ie[i + 2] & 0x7f; + } + + return rate; +} + + +/** + * wpa_bss_get_bit_rates - Get legacy TX rates supported in a BSS + * @bss: BSS table entry + * @rates: Buffer for returning a pointer to the rates list (units of 500 kbps) + * Returns: number of legacy TX rates or -1 on failure + * + * The caller is responsible for freeing the returned buffer with os_free() in + * case of success. + */ +int wpa_bss_get_bit_rates(const struct wpa_bss *bss, u8 **rates) +{ + const u8 *ie, *ie2; + int i, j; + unsigned int len; + u8 *r; + + ie = wpa_bss_get_ie(bss, WLAN_EID_SUPP_RATES); + ie2 = wpa_bss_get_ie(bss, WLAN_EID_EXT_SUPP_RATES); + + len = (ie ? ie[1] : 0) + (ie2 ? ie2[1] : 0); + + r = os_malloc(len); + if (!r) + return -1; + + for (i = 0; ie && i < ie[1]; i++) + r[i] = ie[i + 2] & 0x7f; + + for (j = 0; ie2 && j < ie2[1]; j++) + r[i + j] = ie2[j + 2] & 0x7f; + + *rates = r; + return len; +} diff --git a/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/bss.h b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/bss.h new file mode 100755 index 0000000..b215380 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/bss.h @@ -0,0 +1,150 @@ +/* + * BSS table + * Copyright (c) 2009-2015, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef BSS_H +#define BSS_H + +struct wpa_scan_res; + +#define WPA_BSS_QUAL_INVALID BIT(0) +#define WPA_BSS_NOISE_INVALID BIT(1) +#define WPA_BSS_LEVEL_INVALID BIT(2) +#define WPA_BSS_LEVEL_DBM BIT(3) +#define WPA_BSS_AUTHENTICATED BIT(4) +#define WPA_BSS_ASSOCIATED BIT(5) +#define WPA_BSS_ANQP_FETCH_TRIED BIT(6) + +/** + * struct wpa_bss_anqp - ANQP data for a BSS entry (struct wpa_bss) + */ +struct wpa_bss_anqp { + /** Number of BSS entries referring to this ANQP data instance */ + unsigned int users; +#ifdef CONFIG_INTERWORKING + struct wpabuf *capability_list; + struct wpabuf *venue_name; + struct wpabuf *network_auth_type; + struct wpabuf *roaming_consortium; + struct wpabuf *ip_addr_type_availability; + struct wpabuf *nai_realm; + struct wpabuf *anqp_3gpp; + struct wpabuf *domain_name; +#endif /* CONFIG_INTERWORKING */ +#ifdef CONFIG_HS20 + struct wpabuf *hs20_capability_list; + struct wpabuf *hs20_operator_friendly_name; + struct wpabuf *hs20_wan_metrics; + struct wpabuf *hs20_connection_capability; + struct wpabuf *hs20_operating_class; + struct wpabuf *hs20_osu_providers_list; +#endif /* CONFIG_HS20 */ +}; + +/** + * struct wpa_bss - BSS table + * + * This structure is used to store information about neighboring BSSes in + * generic format. It is mainly updated based on scan results from the driver. + */ +struct wpa_bss { + /** List entry for struct wpa_supplicant::bss */ + struct dl_list list; + /** List entry for struct wpa_supplicant::bss_id */ + struct dl_list list_id; + /** Unique identifier for this BSS entry */ + unsigned int id; + /** Number of counts without seeing this BSS */ + unsigned int scan_miss_count; + /** Index of the last scan update */ + unsigned int last_update_idx; + /** Information flags about the BSS/IBSS (WPA_BSS_*) */ + unsigned int flags; + /** BSSID */ + u8 bssid[ETH_ALEN]; + /** HESSID */ + u8 hessid[ETH_ALEN]; + /** SSID */ + u8 ssid[SSID_MAX_LEN]; + /** Length of SSID */ + size_t ssid_len; + /** Frequency of the channel in MHz (e.g., 2412 = channel 1) */ + int freq; + /** Beacon interval in TUs (host byte order) */ + u16 beacon_int; + /** Capability information field in host byte order */ + u16 caps; + /** Signal quality */ + int qual; + /** Noise level */ + int noise; + /** Signal level */ + int level; + /** Timestamp of last Beacon/Probe Response frame */ + u64 tsf; + /** Time of the last update (i.e., Beacon or Probe Response RX) */ + struct os_reltime last_update; + /** Estimated throughput in kbps */ + unsigned int est_throughput; + /** Signal-to-noise ratio in dB */ + int snr; + /** ANQP data */ + struct wpa_bss_anqp *anqp; + /** Length of the following IE field in octets (from Probe Response) */ + size_t ie_len; + /** Length of the following Beacon IE field in octets */ + size_t beacon_ie_len; + /* followed by ie_len octets of IEs */ + /* followed by beacon_ie_len octets of IEs */ +}; + +void wpa_bss_update_start(struct wpa_supplicant *wpa_s); +void wpa_bss_update_scan_res(struct wpa_supplicant *wpa_s, + struct wpa_scan_res *res, + struct os_reltime *fetch_time); +void wpa_bss_update_end(struct wpa_supplicant *wpa_s, struct scan_info *info, + int new_scan); +int wpa_bss_init(struct wpa_supplicant *wpa_s); +void wpa_bss_deinit(struct wpa_supplicant *wpa_s); +void wpa_bss_flush(struct wpa_supplicant *wpa_s); +void wpa_bss_flush_by_age(struct wpa_supplicant *wpa_s, int age); +struct wpa_bss * wpa_bss_get(struct wpa_supplicant *wpa_s, const u8 *bssid, + const u8 *ssid, size_t ssid_len); +struct wpa_bss * wpa_bss_get_bssid(struct wpa_supplicant *wpa_s, + const u8 *bssid); +struct wpa_bss * wpa_bss_get_bssid_latest(struct wpa_supplicant *wpa_s, + const u8 *bssid); +struct wpa_bss * wpa_bss_get_p2p_dev_addr(struct wpa_supplicant *wpa_s, + const u8 *dev_addr); +struct wpa_bss * wpa_bss_get_id(struct wpa_supplicant *wpa_s, unsigned int id); +struct wpa_bss * wpa_bss_get_id_range(struct wpa_supplicant *wpa_s, + unsigned int idf, unsigned int idl); +const u8 * wpa_bss_get_ie(const struct wpa_bss *bss, u8 ie); +const u8 * wpa_bss_get_vendor_ie(const struct wpa_bss *bss, u32 vendor_type); +const u8 * wpa_bss_get_vendor_ie_beacon(const struct wpa_bss *bss, + u32 vendor_type); +struct wpabuf * wpa_bss_get_vendor_ie_multi(const struct wpa_bss *bss, + u32 vendor_type); +struct wpabuf * wpa_bss_get_vendor_ie_multi_beacon(const struct wpa_bss *bss, + u32 vendor_type); +int wpa_bss_get_max_rate(const struct wpa_bss *bss); +int wpa_bss_get_bit_rates(const struct wpa_bss *bss, u8 **rates); +struct wpa_bss_anqp * wpa_bss_anqp_alloc(void); +int wpa_bss_anqp_unshare_alloc(struct wpa_bss *bss); + +static inline int bss_is_dmg(const struct wpa_bss *bss) +{ + return bss->freq > 45000; +} + +static inline void wpa_bss_update_level(struct wpa_bss *bss, int new_level) +{ + if (bss != NULL && new_level < 0) + bss->level = new_level; +} + +#endif /* BSS_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/config.c b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/config.c new file mode 100755 index 0000000..806a5d6 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/config.c @@ -0,0 +1,4003 @@ +/* + * WPA Supplicant / Configuration parser and common functions + * Copyright (c) 2003-2015, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "includes.h" + +#include "wpa_common.h" +#include "utils/uuid.h" +#include "utils/ip_addr.h" +#include "config.h" +#include "str_pub.h" + +#if !defined(CONFIG_CTRL_IFACE) && defined(CONFIG_NO_CONFIG_WRITE) +#define NO_CONFIG_WRITE +#endif + +/* + * Structure for network configuration parsing. This data is used to implement + * a generic parser for each network block variable. The table of configuration + * variables is defined below in this file (ssid_fields[]). + */ +struct parse_data { + /* Configuration variable name */ + char *name; + + /* Parser function for this variable */ + int (*parser)(const struct parse_data *data, struct wpa_ssid *ssid, + int line, const char *value); + +#ifndef NO_CONFIG_WRITE + /* Writer function (i.e., to get the variable in text format from + * internal presentation). */ + char * (*writer)(const struct parse_data *data, struct wpa_ssid *ssid); +#endif /* NO_CONFIG_WRITE */ + + /* Variable specific parameters for the parser. */ + void *param1, *param2, *param3, *param4; + + /* 0 = this variable can be included in debug output and ctrl_iface + * 1 = this variable contains key/private data and it must not be + * included in debug output unless explicitly requested. In + * addition, this variable will not be readable through the + * ctrl_iface. + */ + int key_data; +}; + + +static int wpa_config_parse_str(const struct parse_data *data, + struct wpa_ssid *ssid, + int line, const char *value) +{ + size_t res_len, *dst_len; + char **dst, *tmp; + + if (os_strcmp(value, "NULL") == 0) { + wpa_printf(MSG_DEBUG, "Unset configuration string '%s'", + data->name); + tmp = NULL; + res_len = 0; + goto set; + } + + tmp = wpa_config_parse_string(value, &res_len); + if (tmp == NULL) { + wpa_printf(MSG_ERROR, "Line %d: failed to parse %s '%s'.", + line, data->name, + data->key_data ? "[KEY DATA REMOVED]" : value); + return -1; + } + + if (data->key_data) { + wpa_hexdump_ascii_key(MSG_MSGDUMP, data->name, + (u8 *) tmp, res_len); + } else { + wpa_hexdump_ascii(MSG_MSGDUMP, data->name, + (u8 *) tmp, res_len); + } + + if (data->param3 && res_len < (size_t) data->param3) { + wpa_printf(MSG_ERROR, "Line %d: too short %s (len=%lu " + "min_len=%ld)", line, data->name, + (unsigned long) res_len, (long) data->param3); + os_free(tmp); + return -1; + } + + if (data->param4 && res_len > (size_t) data->param4) { + wpa_printf(MSG_ERROR, "Line %d: too long %s (len=%lu " + "max_len=%ld)", line, data->name, + (unsigned long) res_len, (long) data->param4); + os_free(tmp); + return -1; + } + +set: + dst = (char **) (((u8 *) ssid) + (long) data->param1); + dst_len = (size_t *) (((u8 *) ssid) + (long) data->param2); + os_free(*dst); + *dst = tmp; + if (data->param2) + *dst_len = res_len; + + return 0; +} + + +#ifndef NO_CONFIG_WRITE +static char * wpa_config_write_string_ascii(const u8 *value, size_t len) +{ + char *buf; + + buf = os_malloc(len + 3); + if (buf == NULL) + return NULL; + buf[0] = '"'; + os_memcpy(buf + 1, value, len); + buf[len + 1] = '"'; + buf[len + 2] = '\0'; + + return buf; +} + + +static char * wpa_config_write_string_hex(const u8 *value, size_t len) +{ + char *buf; + + buf = os_zalloc(2 * len + 1); + if (buf == NULL) + return NULL; + wpa_snprintf_hex(buf, 2 * len + 1, value, len); + + return buf; +} + + +static char * wpa_config_write_string(const u8 *value, size_t len) +{ + if (value == NULL) + return NULL; + + if (is_hex(value, len)) + return wpa_config_write_string_hex(value, len); + else + return wpa_config_write_string_ascii(value, len); +} + + +static char * wpa_config_write_str(const struct parse_data *data, + struct wpa_ssid *ssid) +{ + size_t len; + char **src; + + src = (char **) (((u8 *) ssid) + (long) data->param1); + if (*src == NULL) + return NULL; + + if (data->param2) + len = *((size_t *) (((u8 *) ssid) + (long) data->param2)); + else + len = os_strlen(*src); + + return wpa_config_write_string((const u8 *) *src, len); +} +#endif /* NO_CONFIG_WRITE */ + + +static int wpa_config_parse_int(const struct parse_data *data, + struct wpa_ssid *ssid, + int line, const char *value) +{ + int val, *dst; + char *end; + + dst = (int *) (((u8 *) ssid) + (long) data->param1); + val = strtol(value, &end, 0); + if (*end) { + wpa_printf(MSG_ERROR, "Line %d: invalid number \"%s\"", + line, value); + return -1; + } + *dst = val; + wpa_printf(MSG_MSGDUMP, "%s=%d (0x%x)", data->name, *dst, *dst); + + if (data->param3 && *dst < (long) data->param3) { + wpa_printf(MSG_ERROR, "Line %d: too small %s (value=%d " + "min_value=%ld)", line, data->name, *dst, + (long) data->param3); + *dst = (long) data->param3; + return -1; + } + + if (data->param4 && *dst > (long) data->param4) { + wpa_printf(MSG_ERROR, "Line %d: too large %s (value=%d " + "max_value=%ld)", line, data->name, *dst, + (long) data->param4); + *dst = (long) data->param4; + return -1; + } + + return 0; +} + + +#ifndef NO_CONFIG_WRITE +static char * wpa_config_write_int(const struct parse_data *data, + struct wpa_ssid *ssid) +{ + int *src, res; + char *value; + + src = (int *) (((u8 *) ssid) + (long) data->param1); + + value = os_malloc(20); + if (value == NULL) + return NULL; + res = os_snprintf(value, 20, "%d", *src); + if (os_snprintf_error(20, res)) { + os_free(value); + return NULL; + } + value[20 - 1] = '\0'; + return value; +} +#endif /* NO_CONFIG_WRITE */ + + +static int wpa_config_parse_addr_list(const struct parse_data *data, + int line, const char *value, + u8 **list, size_t *num, char *name, + u8 abort_on_error, u8 masked) +{ + const char *pos; + u8 *buf, *n, addr[2 * ETH_ALEN]; + size_t count; + + buf = NULL; + count = 0; + + pos = value; + while (pos && *pos) { + while (*pos == ' ') + pos++; + + if (hwaddr_masked_aton(pos, addr, &addr[ETH_ALEN], masked)) { + if (abort_on_error || count == 0) { + wpa_printf(MSG_ERROR, + "Line %d: Invalid %s address '%s'", + line, name, value); + os_free(buf); + return -1; + } + /* continue anyway since this could have been from a + * truncated configuration file line */ + wpa_printf(MSG_INFO, + "Line %d: Ignore likely truncated %s address '%s'", + line, name, pos); + } else { + n = os_realloc_array(buf, count + 1, 2 * ETH_ALEN); + if (n == NULL) { + os_free(buf); + return -1; + } + buf = n; + os_memmove(buf + 2 * ETH_ALEN, buf, + count * 2 * ETH_ALEN); + os_memcpy(buf, addr, 2 * ETH_ALEN); + count++; + wpa_printf(MSG_MSGDUMP, + "%s: addr=" MACSTR " mask=" MACSTR, + name, MAC2STR(addr), + MAC2STR(&addr[ETH_ALEN])); + } + + pos = os_strchr(pos, ' '); + } + + os_free(*list); + *list = buf; + *num = count; + + return 0; +} + + +#ifndef NO_CONFIG_WRITE +static char * wpa_config_write_addr_list(const struct parse_data *data, + const u8 *list, size_t num, char *name) +{ + char *value, *end, *pos; + int res; + size_t i; + + if (list == NULL || num == 0) + return NULL; + + value = os_malloc(2 * 20 * num); + if (value == NULL) + return NULL; + pos = value; + end = value + 2 * 20 * num; + + for (i = num; i > 0; i--) { + const u8 *a = list + (i - 1) * 2 * ETH_ALEN; + const u8 *m = a + ETH_ALEN; + + if (i < num) + *pos++ = ' '; + res = hwaddr_mask_txt(pos, end - pos, a, m); + if (res < 0) { + os_free(value); + return NULL; + } + pos += res; + } + + return value; +} +#endif /* NO_CONFIG_WRITE */ + +static int wpa_config_parse_bssid(const struct parse_data *data, + struct wpa_ssid *ssid, int line, + const char *value) +{ + if (value[0] == '\0' || os_strcmp(value, "\"\"") == 0 || + os_strcmp(value, "any") == 0) { + ssid->bssid_set = 0; + wpa_printf(MSG_MSGDUMP, "BSSID any"); + return 0; + } + if (hwaddr_aton(value, ssid->bssid)) { + wpa_printf(MSG_ERROR, "Line %d: Invalid BSSID '%s'.", + line, value); + return -1; + } + ssid->bssid_set = 1; + wpa_hexdump(MSG_MSGDUMP, "BSSID", ssid->bssid, ETH_ALEN); + return 0; +} + + +#ifndef NO_CONFIG_WRITE +static char * wpa_config_write_bssid(const struct parse_data *data, + struct wpa_ssid *ssid) +{ + char *value; + int res; + + if (!ssid->bssid_set) + return NULL; + + value = os_malloc(20); + if (value == NULL) + return NULL; + res = os_snprintf(value, 20, MACSTR, MAC2STR(ssid->bssid)); + if (os_snprintf_error(20, res)) { + os_free(value); + return NULL; + } + value[20 - 1] = '\0'; + return value; +} +#endif /* NO_CONFIG_WRITE */ + + +static int wpa_config_parse_bssid_blacklist(const struct parse_data *data, + struct wpa_ssid *ssid, int line, + const char *value) +{ + return wpa_config_parse_addr_list(data, line, value, + &ssid->bssid_blacklist, + &ssid->num_bssid_blacklist, + "bssid_blacklist", 1, 1); +} + + +#ifndef NO_CONFIG_WRITE +static char * wpa_config_write_bssid_blacklist(const struct parse_data *data, + struct wpa_ssid *ssid) +{ + return wpa_config_write_addr_list(data, ssid->bssid_blacklist, + ssid->num_bssid_blacklist, + "bssid_blacklist"); +} +#endif /* NO_CONFIG_WRITE */ + + +static int wpa_config_parse_bssid_whitelist(const struct parse_data *data, + struct wpa_ssid *ssid, int line, + const char *value) +{ + return wpa_config_parse_addr_list(data, line, value, + &ssid->bssid_whitelist, + &ssid->num_bssid_whitelist, + "bssid_whitelist", 1, 1); +} + + +#ifndef NO_CONFIG_WRITE +static char * wpa_config_write_bssid_whitelist(const struct parse_data *data, + struct wpa_ssid *ssid) +{ + return wpa_config_write_addr_list(data, ssid->bssid_whitelist, + ssid->num_bssid_whitelist, + "bssid_whitelist"); +} +#endif /* NO_CONFIG_WRITE */ + + +static int wpa_config_parse_psk(const struct parse_data *data, + struct wpa_ssid *ssid, int line, + const char *value) +{ +#ifdef CONFIG_EXT_PASSWORD + if (os_strncmp(value, "ext:", 4) == 0) { + str_clear_free(ssid->passphrase); + ssid->passphrase = NULL; + ssid->psk_set = 0; + os_free(ssid->ext_psk); + ssid->ext_psk = os_strdup(value + 4); + if (ssid->ext_psk == NULL) + return -1; + wpa_printf(MSG_DEBUG, "PSK: External password '%s'", + ssid->ext_psk); + return 0; + } +#endif /* CONFIG_EXT_PASSWORD */ + + if (*value == '"') { +#ifndef CONFIG_NO_PBKDF2 + const char *pos; + size_t len; + + value++; + pos = os_strrchr(value, '"'); + if (pos) + len = pos - value; + else + len = os_strlen(value); + if (len < 8 || len > 63) { + wpa_printf(MSG_ERROR, "Line %d: Invalid passphrase " + "length %lu (expected: 8..63) '%s'.", + line, (unsigned long) len, value); + return -1; + } + wpa_hexdump_ascii_key(MSG_MSGDUMP, "PSK (ASCII passphrase)", + (u8 *) value, len); + if (ssid->passphrase && os_strlen(ssid->passphrase) == len && + os_memcmp(ssid->passphrase, value, len) == 0) + return 0; + ssid->psk_set = 0; + str_clear_free(ssid->passphrase); + ssid->passphrase = dup_binstr(value, len); + if (ssid->passphrase == NULL) + return -1; + return 0; +#else /* CONFIG_NO_PBKDF2 */ + wpa_printf(MSG_ERROR, "Line %d: ASCII passphrase not " + "supported.", line); + return -1; +#endif /* CONFIG_NO_PBKDF2 */ + } + + if (hexstr2bin(value, ssid->psk, PMK_LEN) || + value[PMK_LEN * 2] != '\0') { + wpa_printf(MSG_ERROR, "Line %d: Invalid PSK '%s'.", + line, value); + return -1; + } + + str_clear_free(ssid->passphrase); + ssid->passphrase = NULL; + + ssid->psk_set = 1; + wpa_hexdump_key(MSG_MSGDUMP, "PSK", ssid->psk, PMK_LEN); + + return 0; +} + + +#ifndef NO_CONFIG_WRITE +static char * wpa_config_write_psk(const struct parse_data *data, + struct wpa_ssid *ssid) +{ +#ifdef CONFIG_EXT_PASSWORD + if (ssid->ext_psk) { + size_t len = 4 + os_strlen(ssid->ext_psk) + 1; + char *buf = os_malloc(len); + int res; + + if (buf == NULL) + return NULL; + res = os_snprintf(buf, len, "ext:%s", ssid->ext_psk); + if (os_snprintf_error(len, res)) { + os_free(buf); + buf = NULL; + } + return buf; + } +#endif /* CONFIG_EXT_PASSWORD */ + + if (ssid->passphrase) + return wpa_config_write_string_ascii( + (const u8 *) ssid->passphrase, + os_strlen(ssid->passphrase)); + + if (ssid->psk_set) + return wpa_config_write_string_hex(ssid->psk, PMK_LEN); + + return NULL; +} +#endif /* NO_CONFIG_WRITE */ + + +static int wpa_config_parse_proto(const struct parse_data *data, + struct wpa_ssid *ssid, int line, + const char *value) +{ + int val = 0, last, errors = 0; + char *start, *end, *buf; + + buf = os_strdup(value); + if (buf == NULL) + return -1; + start = buf; + + while (*start != '\0') { + while (*start == ' ' || *start == '\t') + start++; + if (*start == '\0') + break; + end = start; + while (*end != ' ' && *end != '\t' && *end != '\0') + end++; + last = *end == '\0'; + *end = '\0'; + if (os_strcmp(start, "WPA") == 0) + val |= WPA_PROTO_WPA; + else if (os_strcmp(start, "RSN") == 0 || + os_strcmp(start, "WPA2") == 0) + val |= WPA_PROTO_RSN; + else if (os_strcmp(start, "OSEN") == 0) + val |= WPA_PROTO_OSEN; + else { + wpa_printf(MSG_ERROR, "Line %d: invalid proto '%s'", + line, start); + errors++; + } + + if (last) + break; + start = end + 1; + } + os_free(buf); + + if (val == 0) { + wpa_printf(MSG_ERROR, + "Line %d: no proto values configured.", line); + errors++; + } + + wpa_printf(MSG_MSGDUMP, "proto: 0x%x", val); + ssid->proto = val; + return errors ? -1 : 0; +} + + +#ifndef NO_CONFIG_WRITE +static char * wpa_config_write_proto(const struct parse_data *data, + struct wpa_ssid *ssid) +{ + int ret; + char *buf, *pos, *end; + + pos = buf = os_zalloc(20); + if (buf == NULL) + return NULL; + end = buf + 20; + + if (ssid->proto & WPA_PROTO_WPA) { + ret = os_snprintf(pos, end - pos, "%sWPA", + pos == buf ? "" : " "); + if (os_snprintf_error(end - pos, ret)) + return buf; + pos += ret; + } + + if (ssid->proto & WPA_PROTO_RSN) { + ret = os_snprintf(pos, end - pos, "%sRSN", + pos == buf ? "" : " "); + if (os_snprintf_error(end - pos, ret)) + return buf; + pos += ret; + } + + if (ssid->proto & WPA_PROTO_OSEN) { + ret = os_snprintf(pos, end - pos, "%sOSEN", + pos == buf ? "" : " "); + if (os_snprintf_error(end - pos, ret)) + return buf; + pos += ret; + } + + if (pos == buf) { + os_free(buf); + buf = NULL; + } + + return buf; +} +#endif /* NO_CONFIG_WRITE */ + + +static int wpa_config_parse_key_mgmt(const struct parse_data *data, + struct wpa_ssid *ssid, int line, + const char *value) +{ + int val = 0, last, errors = 0; + char *start, *end, *buf; + + buf = os_strdup(value); + if (buf == NULL) + return -1; + start = buf; + + while (*start != '\0') { + while (*start == ' ' || *start == '\t') + start++; + if (*start == '\0') + break; + end = start; + while (*end != ' ' && *end != '\t' && *end != '\0') + end++; + last = *end == '\0'; + *end = '\0'; + if (os_strcmp(start, "WPA-PSK") == 0) + val |= WPA_KEY_MGMT_PSK; + else if (os_strcmp(start, "WPA-EAP") == 0) + val |= WPA_KEY_MGMT_IEEE8021X; + else if (os_strcmp(start, "IEEE8021X") == 0) + val |= WPA_KEY_MGMT_IEEE8021X_NO_WPA; + else if (os_strcmp(start, "NONE") == 0) + val |= WPA_KEY_MGMT_NONE; + else if (os_strcmp(start, "WPA-NONE") == 0) + val |= WPA_KEY_MGMT_WPA_NONE; +#ifdef CONFIG_IEEE80211R + else if (os_strcmp(start, "FT-PSK") == 0) + val |= WPA_KEY_MGMT_FT_PSK; + else if (os_strcmp(start, "FT-EAP") == 0) + val |= WPA_KEY_MGMT_FT_IEEE8021X; +#endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_IEEE80211W + else if (os_strcmp(start, "WPA-PSK-SHA256") == 0) + val |= WPA_KEY_MGMT_PSK_SHA256; + else if (os_strcmp(start, "WPA-EAP-SHA256") == 0) + val |= WPA_KEY_MGMT_IEEE8021X_SHA256; +#endif /* CONFIG_IEEE80211W */ +#ifdef CONFIG_WPS + else if (os_strcmp(start, "WPS") == 0) + val |= WPA_KEY_MGMT_WPS; +#endif /* CONFIG_WPS */ +#ifdef CONFIG_SAE + else if (os_strcmp(start, "SAE") == 0) + val |= WPA_KEY_MGMT_SAE; + else if (os_strcmp(start, "FT-SAE") == 0) + val |= WPA_KEY_MGMT_FT_SAE; +#endif /* CONFIG_SAE */ +#ifdef CONFIG_HS20 + else if (os_strcmp(start, "OSEN") == 0) + val |= WPA_KEY_MGMT_OSEN; +#endif /* CONFIG_HS20 */ +#ifdef CONFIG_SUITEB + else if (os_strcmp(start, "WPA-EAP-SUITE-B") == 0) + val |= WPA_KEY_MGMT_IEEE8021X_SUITE_B; +#endif /* CONFIG_SUITEB */ +#ifdef CONFIG_SUITEB192 + else if (os_strcmp(start, "WPA-EAP-SUITE-B-192") == 0) + val |= WPA_KEY_MGMT_IEEE8021X_SUITE_B_192; +#endif /* CONFIG_SUITEB192 */ + else { + wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'", + line, start); + errors++; + } + + if (last) + break; + start = end + 1; + } + os_free(buf); + + if (val == 0) { + wpa_printf(MSG_ERROR, + "Line %d: no key_mgmt values configured.", line); + errors++; + } + + wpa_printf(MSG_MSGDUMP, "key_mgmt: 0x%x", val); + ssid->key_mgmt = val; + return errors ? -1 : 0; +} + + +#ifndef NO_CONFIG_WRITE +static char * wpa_config_write_key_mgmt(const struct parse_data *data, + struct wpa_ssid *ssid) +{ + char *buf, *pos, *end; + int ret; + + pos = buf = os_zalloc(100); + if (buf == NULL) + return NULL; + end = buf + 100; + + if (ssid->key_mgmt & WPA_KEY_MGMT_PSK) { + ret = os_snprintf(pos, end - pos, "%sWPA-PSK", + pos == buf ? "" : " "); + if (os_snprintf_error(end - pos, ret)) { + end[-1] = '\0'; + return buf; + } + pos += ret; + } + + if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X) { + ret = os_snprintf(pos, end - pos, "%sWPA-EAP", + pos == buf ? "" : " "); + if (os_snprintf_error(end - pos, ret)) { + end[-1] = '\0'; + return buf; + } + pos += ret; + } + + if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) { + ret = os_snprintf(pos, end - pos, "%sIEEE8021X", + pos == buf ? "" : " "); + if (os_snprintf_error(end - pos, ret)) { + end[-1] = '\0'; + return buf; + } + pos += ret; + } + + if (ssid->key_mgmt & WPA_KEY_MGMT_NONE) { + ret = os_snprintf(pos, end - pos, "%sNONE", + pos == buf ? "" : " "); + if (os_snprintf_error(end - pos, ret)) { + end[-1] = '\0'; + return buf; + } + pos += ret; + } + + if (ssid->key_mgmt & WPA_KEY_MGMT_WPA_NONE) { + ret = os_snprintf(pos, end - pos, "%sWPA-NONE", + pos == buf ? "" : " "); + if (os_snprintf_error(end - pos, ret)) { + end[-1] = '\0'; + return buf; + } + pos += ret; + } + +#ifdef CONFIG_IEEE80211R + if (ssid->key_mgmt & WPA_KEY_MGMT_FT_PSK) { + ret = os_snprintf(pos, end - pos, "%sFT-PSK", + pos == buf ? "" : " "); + if (os_snprintf_error(end - pos, ret)) { + end[-1] = '\0'; + return buf; + } + pos += ret; + } + + if (ssid->key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) { + ret = os_snprintf(pos, end - pos, "%sFT-EAP", + pos == buf ? "" : " "); + if (os_snprintf_error(end - pos, ret)) { + end[-1] = '\0'; + return buf; + } + pos += ret; + } +#endif /* CONFIG_IEEE80211R */ + +#ifdef CONFIG_IEEE80211W + if (ssid->key_mgmt & WPA_KEY_MGMT_PSK_SHA256) { + ret = os_snprintf(pos, end - pos, "%sWPA-PSK-SHA256", + pos == buf ? "" : " "); + if (os_snprintf_error(end - pos, ret)) { + end[-1] = '\0'; + return buf; + } + pos += ret; + } + + if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) { + ret = os_snprintf(pos, end - pos, "%sWPA-EAP-SHA256", + pos == buf ? "" : " "); + if (os_snprintf_error(end - pos, ret)) { + end[-1] = '\0'; + return buf; + } + pos += ret; + } +#endif /* CONFIG_IEEE80211W */ + +#ifdef CONFIG_WPS + if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) { + ret = os_snprintf(pos, end - pos, "%sWPS", + pos == buf ? "" : " "); + if (os_snprintf_error(end - pos, ret)) { + end[-1] = '\0'; + return buf; + } + pos += ret; + } +#endif /* CONFIG_WPS */ + +#ifdef CONFIG_SAE + if (ssid->key_mgmt & WPA_KEY_MGMT_SAE) { + ret = os_snprintf(pos, end - pos, "%sSAE", + pos == buf ? "" : " "); + if (os_snprintf_error(end - pos, ret)) { + end[-1] = '\0'; + return buf; + } + pos += ret; + } + + if (ssid->key_mgmt & WPA_KEY_MGMT_FT_SAE) { + ret = os_snprintf(pos, end - pos, "%sFT-SAE", + pos == buf ? "" : " "); + if (os_snprintf_error(end - pos, ret)) { + end[-1] = '\0'; + return buf; + } + pos += ret; + } +#endif /* CONFIG_SAE */ + +#ifdef CONFIG_HS20 + if (ssid->key_mgmt & WPA_KEY_MGMT_OSEN) { + ret = os_snprintf(pos, end - pos, "%sOSEN", + pos == buf ? "" : " "); + if (os_snprintf_error(end - pos, ret)) { + end[-1] = '\0'; + return buf; + } + pos += ret; + } +#endif /* CONFIG_HS20 */ + +#ifdef CONFIG_SUITEB + if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) { + ret = os_snprintf(pos, end - pos, "%sWPA-EAP-SUITE-B", + pos == buf ? "" : " "); + if (os_snprintf_error(end - pos, ret)) { + end[-1] = '\0'; + return buf; + } + pos += ret; + } +#endif /* CONFIG_SUITEB */ + +#ifdef CONFIG_SUITEB192 + if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) { + ret = os_snprintf(pos, end - pos, "%sWPA-EAP-SUITE-B-192", + pos == buf ? "" : " "); + if (os_snprintf_error(end - pos, ret)) { + end[-1] = '\0'; + return buf; + } + pos += ret; + } +#endif /* CONFIG_SUITEB192 */ + + if (pos == buf) { + os_free(buf); + buf = NULL; + } + + return buf; +} +#endif /* NO_CONFIG_WRITE */ + + +static int wpa_config_parse_cipher(int line, const char *value) +{ + int val = wpa_parse_cipher(value); + if (val < 0) { + wpa_printf(MSG_ERROR, "Line %d: invalid cipher '%s'.", + line, value); + return -1; + } + if (val == 0) { + wpa_printf(MSG_ERROR, "Line %d: no cipher values configured.", + line); + return -1; + } + return val; +} + + +#ifndef NO_CONFIG_WRITE +static char * wpa_config_write_cipher(int cipher) +{ + char *buf = os_zalloc(50); + if (buf == NULL) + return NULL; + + if (wpa_write_ciphers(buf, buf + 50, cipher, " ") < 0) { + os_free(buf); + return NULL; + } + + return buf; +} +#endif /* NO_CONFIG_WRITE */ + + +static int wpa_config_parse_pairwise(const struct parse_data *data, + struct wpa_ssid *ssid, int line, + const char *value) +{ + int val; + val = wpa_config_parse_cipher(line, value); + if (val == -1) + return -1; + if (val & ~WPA_ALLOWED_PAIRWISE_CIPHERS) { + wpa_printf(MSG_ERROR, "Line %d: not allowed pairwise cipher " + "(0x%x).", line, val); + return -1; + } + + wpa_printf(MSG_MSGDUMP, "pairwise: 0x%x", val); + ssid->pairwise_cipher = val; + + return 0; +} + + +#ifndef NO_CONFIG_WRITE +static char * wpa_config_write_pairwise(const struct parse_data *data, + struct wpa_ssid *ssid) +{ + return wpa_config_write_cipher(ssid->pairwise_cipher); +} +#endif /* NO_CONFIG_WRITE */ + + +static int wpa_config_parse_group(const struct parse_data *data, + struct wpa_ssid *ssid, int line, + const char *value) +{ + int val; + val = wpa_config_parse_cipher(line, value); + if (val == -1) + return -1; + + /* + * Backwards compatibility - filter out WEP ciphers that were previously + * allowed. + */ + val &= ~(WPA_CIPHER_WEP104 | WPA_CIPHER_WEP40); + + if (val & ~WPA_ALLOWED_GROUP_CIPHERS) { + wpa_printf(MSG_ERROR, "Line %d: not allowed group cipher " + "(0x%x).", line, val); + return -1; + } + + wpa_printf(MSG_MSGDUMP, "group: 0x%x", val); + ssid->group_cipher = val; + + return 0; +} + + +#ifndef NO_CONFIG_WRITE +static char * wpa_config_write_group(const struct parse_data *data, + struct wpa_ssid *ssid) +{ + return wpa_config_write_cipher(ssid->group_cipher); +} +#endif /* NO_CONFIG_WRITE */ + + +static int wpa_config_parse_auth_alg(const struct parse_data *data, + struct wpa_ssid *ssid, int line, + const char *value) +{ + int val = 0, last, errors = 0; + char *start, *end, *buf; + + buf = os_strdup(value); + if (buf == NULL) + return -1; + start = buf; + + while (*start != '\0') { + while (*start == ' ' || *start == '\t') + start++; + if (*start == '\0') + break; + end = start; + while (*end != ' ' && *end != '\t' && *end != '\0') + end++; + last = *end == '\0'; + *end = '\0'; + if (os_strcmp(start, "OPEN") == 0) + val |= WPA_AUTH_ALG_OPEN; + else if (os_strcmp(start, "SHARED") == 0) + val |= WPA_AUTH_ALG_SHARED; + else if (os_strcmp(start, "LEAP") == 0) + val |= WPA_AUTH_ALG_LEAP; + else { + wpa_printf(MSG_ERROR, "Line %d: invalid auth_alg '%s'", + line, start); + errors++; + } + + if (last) + break; + start = end + 1; + } + os_free(buf); + + if (val == 0) { + wpa_printf(MSG_ERROR, + "Line %d: no auth_alg values configured.", line); + errors++; + } + + wpa_printf(MSG_MSGDUMP, "auth_alg: 0x%x", val); + ssid->auth_alg = val; + return errors ? -1 : 0; +} + + +#ifndef NO_CONFIG_WRITE +static char * wpa_config_write_auth_alg(const struct parse_data *data, + struct wpa_ssid *ssid) +{ + char *buf, *pos, *end; + int ret; + + pos = buf = os_zalloc(30); + if (buf == NULL) + return NULL; + end = buf + 30; + + if (ssid->auth_alg & WPA_AUTH_ALG_OPEN) { + ret = os_snprintf(pos, end - pos, "%sOPEN", + pos == buf ? "" : " "); + if (os_snprintf_error(end - pos, ret)) { + end[-1] = '\0'; + return buf; + } + pos += ret; + } + + if (ssid->auth_alg & WPA_AUTH_ALG_SHARED) { + ret = os_snprintf(pos, end - pos, "%sSHARED", + pos == buf ? "" : " "); + if (os_snprintf_error(end - pos, ret)) { + end[-1] = '\0'; + return buf; + } + pos += ret; + } + + if (ssid->auth_alg & WPA_AUTH_ALG_LEAP) { + ret = os_snprintf(pos, end - pos, "%sLEAP", + pos == buf ? "" : " "); + if (os_snprintf_error(end - pos, ret)) { + end[-1] = '\0'; + return buf; + } + pos += ret; + } + + if (pos == buf) { + os_free(buf); + buf = NULL; + } + + return buf; +} +#endif /* NO_CONFIG_WRITE */ + + +static int * wpa_config_parse_int_array(const char *value) +{ + int *freqs; + size_t used, len; + const char *pos; + + used = 0; + len = 10; + freqs = os_calloc(len + 1, sizeof(int)); + if (freqs == NULL) + return NULL; + + pos = value; + while (pos) { + while (*pos == ' ') + pos++; + if (used == len) { + int *n; + size_t i; + n = os_realloc_array(freqs, len * 2 + 1, sizeof(int)); + if (n == NULL) { + os_free(freqs); + return NULL; + } + for (i = len; i <= len * 2; i++) + n[i] = 0; + freqs = n; + len *= 2; + } + + freqs[used] = atoi(pos); + if (freqs[used] == 0) + break; + used++; + pos = os_strchr(pos + 1, ' '); + } + + return freqs; +} + + +static int wpa_config_parse_scan_freq(const struct parse_data *data, + struct wpa_ssid *ssid, int line, + const char *value) +{ + int *freqs; + + freqs = wpa_config_parse_int_array(value); + if (freqs == NULL) + return -1; + if (freqs[0] == 0) { + os_free(freqs); + freqs = NULL; + } + os_free(ssid->scan_freq); + ssid->scan_freq = freqs; + + return 0; +} + + +static int wpa_config_parse_freq_list(const struct parse_data *data, + struct wpa_ssid *ssid, int line, + const char *value) +{ + int *freqs; + + freqs = wpa_config_parse_int_array(value); + if (freqs == NULL) + return -1; + if (freqs[0] == 0) { + os_free(freqs); + freqs = NULL; + } + os_free(ssid->freq_list); + ssid->freq_list = freqs; + + return 0; +} + + +#ifndef NO_CONFIG_WRITE +static char * wpa_config_write_freqs(const struct parse_data *data, + const int *freqs) +{ + char *buf, *pos, *end; + int i, ret; + size_t count; + + if (freqs == NULL) + return NULL; + + count = 0; + for (i = 0; freqs[i]; i++) + count++; + + pos = buf = os_zalloc(10 * count + 1); + if (buf == NULL) + return NULL; + end = buf + 10 * count + 1; + + for (i = 0; freqs[i]; i++) { + ret = os_snprintf(pos, end - pos, "%s%u", + i == 0 ? "" : " ", freqs[i]); + if (os_snprintf_error(end - pos, ret)) { + end[-1] = '\0'; + return buf; + } + pos += ret; + } + + return buf; +} + + +static char * wpa_config_write_scan_freq(const struct parse_data *data, + struct wpa_ssid *ssid) +{ + return wpa_config_write_freqs(data, ssid->scan_freq); +} + + +static char * wpa_config_write_freq_list(const struct parse_data *data, + struct wpa_ssid *ssid) +{ + return wpa_config_write_freqs(data, ssid->freq_list); +} +#endif /* NO_CONFIG_WRITE */ + + +#ifdef IEEE8021X_EAPOL +static int wpa_config_parse_eap(const struct parse_data *data, + struct wpa_ssid *ssid, int line, + const char *value) +{ + int last, errors = 0; + char *start, *end, *buf; + struct eap_method_type *methods = NULL, *tmp; + size_t num_methods = 0; + + buf = os_strdup(value); + if (buf == NULL) + return -1; + start = buf; + + while (*start != '\0') { + while (*start == ' ' || *start == '\t') + start++; + if (*start == '\0') + break; + end = start; + while (*end != ' ' && *end != '\t' && *end != '\0') + end++; + last = *end == '\0'; + *end = '\0'; + tmp = methods; + methods = os_realloc_array(methods, num_methods + 1, + sizeof(*methods)); + if (methods == NULL) { + os_free(tmp); + os_free(buf); + return -1; + } + methods[num_methods].method = eap_peer_get_type( + start, &methods[num_methods].vendor); + if (methods[num_methods].vendor == EAP_VENDOR_IETF && + methods[num_methods].method == EAP_TYPE_NONE) { + wpa_printf(MSG_ERROR, "Line %d: unknown EAP method " + "'%s'", line, start); + wpa_printf(MSG_ERROR, "You may need to add support for" + " this EAP method during wpa_supplicant\n" + "build time configuration.\n" + "See README for more information."); + errors++; + } else if (methods[num_methods].vendor == EAP_VENDOR_IETF && + methods[num_methods].method == EAP_TYPE_LEAP) + ssid->leap++; + else + ssid->non_leap++; + num_methods++; + if (last) + break; + start = end + 1; + } + os_free(buf); + + tmp = methods; + methods = os_realloc_array(methods, num_methods + 1, sizeof(*methods)); + if (methods == NULL) { + os_free(tmp); + return -1; + } + methods[num_methods].vendor = EAP_VENDOR_IETF; + methods[num_methods].method = EAP_TYPE_NONE; + num_methods++; + + wpa_hexdump(MSG_MSGDUMP, "eap methods", + (u8 *) methods, num_methods * sizeof(*methods)); + os_free(ssid->eap.eap_methods); + ssid->eap.eap_methods = methods; + return errors ? -1 : 0; +} + + +#ifndef NO_CONFIG_WRITE +static char * wpa_config_write_eap(const struct parse_data *data, + struct wpa_ssid *ssid) +{ + int i, ret; + char *buf, *pos, *end; + const struct eap_method_type *eap_methods = ssid->eap.eap_methods; + const char *name; + + if (eap_methods == NULL) + return NULL; + + pos = buf = os_zalloc(100); + if (buf == NULL) + return NULL; + end = buf + 100; + + for (i = 0; eap_methods[i].vendor != EAP_VENDOR_IETF || + eap_methods[i].method != EAP_TYPE_NONE; i++) { + name = eap_get_name(eap_methods[i].vendor, + eap_methods[i].method); + if (name) { + ret = os_snprintf(pos, end - pos, "%s%s", + pos == buf ? "" : " ", name); + if (os_snprintf_error(end - pos, ret)) + break; + pos += ret; + } + } + + end[-1] = '\0'; + + return buf; +} +#endif /* NO_CONFIG_WRITE */ + + +static int wpa_config_parse_password(const struct parse_data *data, + struct wpa_ssid *ssid, int line, + const char *value) +{ + u8 *hash; + + if (os_strcmp(value, "NULL") == 0) { + wpa_printf(MSG_DEBUG, "Unset configuration string 'password'"); + bin_clear_free(ssid->eap.password, ssid->eap.password_len); + ssid->eap.password = NULL; + ssid->eap.password_len = 0; + return 0; + } + +#ifdef CONFIG_EXT_PASSWORD + if (os_strncmp(value, "ext:", 4) == 0) { + char *name = os_strdup(value + 4); + if (name == NULL) + return -1; + bin_clear_free(ssid->eap.password, ssid->eap.password_len); + ssid->eap.password = (u8 *) name; + ssid->eap.password_len = os_strlen(name); + ssid->eap.flags &= ~EAP_CONFIG_FLAGS_PASSWORD_NTHASH; + ssid->eap.flags |= EAP_CONFIG_FLAGS_EXT_PASSWORD; + return 0; + } +#endif /* CONFIG_EXT_PASSWORD */ + + if (os_strncmp(value, "hash:", 5) != 0) { + char *tmp; + size_t res_len; + + tmp = wpa_config_parse_string(value, &res_len); + if (tmp == NULL) { + wpa_printf(MSG_ERROR, "Line %d: failed to parse " + "password.", line); + return -1; + } + wpa_hexdump_ascii_key(MSG_MSGDUMP, data->name, + (u8 *) tmp, res_len); + + bin_clear_free(ssid->eap.password, ssid->eap.password_len); + ssid->eap.password = (u8 *) tmp; + ssid->eap.password_len = res_len; + ssid->eap.flags &= ~EAP_CONFIG_FLAGS_PASSWORD_NTHASH; + ssid->eap.flags &= ~EAP_CONFIG_FLAGS_EXT_PASSWORD; + + return 0; + } + + + /* NtPasswordHash: hash:<32 hex digits> */ + if (os_strlen(value + 5) != 2 * 16) { + wpa_printf(MSG_ERROR, "Line %d: Invalid password hash length " + "(expected 32 hex digits)", line); + return -1; + } + + hash = os_malloc(16); + if (hash == NULL) + return -1; + + if (hexstr2bin(value + 5, hash, 16)) { + os_free(hash); + wpa_printf(MSG_ERROR, "Line %d: Invalid password hash", line); + return -1; + } + + wpa_hexdump_key(MSG_MSGDUMP, data->name, hash, 16); + + bin_clear_free(ssid->eap.password, ssid->eap.password_len); + ssid->eap.password = hash; + ssid->eap.password_len = 16; + ssid->eap.flags |= EAP_CONFIG_FLAGS_PASSWORD_NTHASH; + ssid->eap.flags &= ~EAP_CONFIG_FLAGS_EXT_PASSWORD; + + return 0; +} + + +#ifndef NO_CONFIG_WRITE +static char * wpa_config_write_password(const struct parse_data *data, + struct wpa_ssid *ssid) +{ + char *buf; + + if (ssid->eap.password == NULL) + return NULL; + +#ifdef CONFIG_EXT_PASSWORD + if (ssid->eap.flags & EAP_CONFIG_FLAGS_EXT_PASSWORD) { + buf = os_zalloc(4 + ssid->eap.password_len + 1); + if (buf == NULL) + return NULL; + os_memcpy(buf, "ext:", 4); + os_memcpy(buf + 4, ssid->eap.password, ssid->eap.password_len); + return buf; + } +#endif /* CONFIG_EXT_PASSWORD */ + + if (!(ssid->eap.flags & EAP_CONFIG_FLAGS_PASSWORD_NTHASH)) { + return wpa_config_write_string( + ssid->eap.password, ssid->eap.password_len); + } + + buf = os_malloc(5 + 32 + 1); + if (buf == NULL) + return NULL; + + os_memcpy(buf, "hash:", 5); + wpa_snprintf_hex(buf + 5, 32 + 1, ssid->eap.password, 16); + + return buf; +} +#endif /* NO_CONFIG_WRITE */ +#endif /* IEEE8021X_EAPOL */ + + +static int wpa_config_parse_wep_key(u8 *key, size_t *len, int line, + const char *value, int idx) +{ + char *buf, title[20]; + int res; + + buf = wpa_config_parse_string(value, len); + if (buf == NULL) { + wpa_printf(MSG_ERROR, "Line %d: Invalid WEP key %d '%s'.", + line, idx, value); + return -1; + } + if (*len > MAX_WEP_KEY_LEN) { + wpa_printf(MSG_ERROR, "Line %d: Too long WEP key %d '%s'.", + line, idx, value); + os_free(buf); + return -1; + } + if (*len && *len != 5 && *len != 13 && *len != 16) { + wpa_printf(MSG_ERROR, "Line %d: Invalid WEP key length %u - " + "this network block will be ignored", + line, (unsigned int) *len); + } + os_memcpy(key, buf, *len); + str_clear_free(buf); + res = os_snprintf(title, sizeof(title), "wep_key%d", idx); + if (!os_snprintf_error(sizeof(title), res)) + wpa_hexdump_key(MSG_MSGDUMP, title, key, *len); + return 0; +} + + +static int wpa_config_parse_wep_key0(const struct parse_data *data, + struct wpa_ssid *ssid, int line, + const char *value) +{ + return wpa_config_parse_wep_key(ssid->wep_key[0], + &ssid->wep_key_len[0], line, + value, 0); +} + + +static int wpa_config_parse_wep_key1(const struct parse_data *data, + struct wpa_ssid *ssid, int line, + const char *value) +{ + return wpa_config_parse_wep_key(ssid->wep_key[1], + &ssid->wep_key_len[1], line, + value, 1); +} + + +static int wpa_config_parse_wep_key2(const struct parse_data *data, + struct wpa_ssid *ssid, int line, + const char *value) +{ + return wpa_config_parse_wep_key(ssid->wep_key[2], + &ssid->wep_key_len[2], line, + value, 2); +} + + +static int wpa_config_parse_wep_key3(const struct parse_data *data, + struct wpa_ssid *ssid, int line, + const char *value) +{ + return wpa_config_parse_wep_key(ssid->wep_key[3], + &ssid->wep_key_len[3], line, + value, 3); +} + + +#ifndef NO_CONFIG_WRITE +static char * wpa_config_write_wep_key(struct wpa_ssid *ssid, int idx) +{ + if (ssid->wep_key_len[idx] == 0) + return NULL; + return wpa_config_write_string(ssid->wep_key[idx], + ssid->wep_key_len[idx]); +} + + +static char * wpa_config_write_wep_key0(const struct parse_data *data, + struct wpa_ssid *ssid) +{ + return wpa_config_write_wep_key(ssid, 0); +} + + +static char * wpa_config_write_wep_key1(const struct parse_data *data, + struct wpa_ssid *ssid) +{ + return wpa_config_write_wep_key(ssid, 1); +} + + +static char * wpa_config_write_wep_key2(const struct parse_data *data, + struct wpa_ssid *ssid) +{ + return wpa_config_write_wep_key(ssid, 2); +} + + +static char * wpa_config_write_wep_key3(const struct parse_data *data, + struct wpa_ssid *ssid) +{ + return wpa_config_write_wep_key(ssid, 3); +} +#endif /* NO_CONFIG_WRITE */ + + +#ifdef CONFIG_P2P + +static int wpa_config_parse_go_p2p_dev_addr(const struct parse_data *data, + struct wpa_ssid *ssid, int line, + const char *value) +{ + if (value[0] == '\0' || os_strcmp(value, "\"\"") == 0 || + os_strcmp(value, "any") == 0) { + os_memset(ssid->go_p2p_dev_addr, 0, ETH_ALEN); + wpa_printf(MSG_MSGDUMP, "GO P2P Device Address any"); + return 0; + } + if (hwaddr_aton(value, ssid->go_p2p_dev_addr)) { + wpa_printf(MSG_ERROR, "Line %d: Invalid GO P2P Device Address '%s'.", + line, value); + return -1; + } + ssid->bssid_set = 1; + wpa_printf(MSG_MSGDUMP, "GO P2P Device Address " MACSTR, + MAC2STR(ssid->go_p2p_dev_addr)); + return 0; +} + + +#ifndef NO_CONFIG_WRITE +static char * wpa_config_write_go_p2p_dev_addr(const struct parse_data *data, + struct wpa_ssid *ssid) +{ + char *value; + int res; + + if (is_zero_ether_addr(ssid->go_p2p_dev_addr)) + return NULL; + + value = os_malloc(20); + if (value == NULL) + return NULL; + res = os_snprintf(value, 20, MACSTR, MAC2STR(ssid->go_p2p_dev_addr)); + if (os_snprintf_error(20, res)) { + os_free(value); + return NULL; + } + value[20 - 1] = '\0'; + return value; +} +#endif /* NO_CONFIG_WRITE */ + + +static int wpa_config_parse_p2p_client_list(const struct parse_data *data, + struct wpa_ssid *ssid, int line, + const char *value) +{ + return wpa_config_parse_addr_list(data, line, value, + &ssid->p2p_client_list, + &ssid->num_p2p_clients, + "p2p_client_list", 0, 0); +} + + +#ifndef NO_CONFIG_WRITE +static char * wpa_config_write_p2p_client_list(const struct parse_data *data, + struct wpa_ssid *ssid) +{ + return wpa_config_write_addr_list(data, ssid->p2p_client_list, + ssid->num_p2p_clients, + "p2p_client_list"); +} +#endif /* NO_CONFIG_WRITE */ + + +static int wpa_config_parse_psk_list(const struct parse_data *data, + struct wpa_ssid *ssid, int line, + const char *value) +{ + struct psk_list_entry *p; + const char *pos; + + p = os_zalloc(sizeof(*p)); + if (p == NULL) + return -1; + + pos = value; + if (os_strncmp(pos, "P2P-", 4) == 0) { + p->p2p = 1; + pos += 4; + } + + if (hwaddr_aton(pos, p->addr)) { + wpa_printf(MSG_ERROR, "Line %d: Invalid psk_list address '%s'", + line, pos); + os_free(p); + return -1; + } + pos += 17; + if (*pos != '-') { + wpa_printf(MSG_ERROR, "Line %d: Invalid psk_list '%s'", + line, pos); + os_free(p); + return -1; + } + pos++; + + if (hexstr2bin(pos, p->psk, PMK_LEN) || pos[PMK_LEN * 2] != '\0') { + wpa_printf(MSG_ERROR, "Line %d: Invalid psk_list PSK '%s'", + line, pos); + os_free(p); + return -1; + } + + dl_list_add(&ssid->psk_list, &p->list); + + return 0; +} + + +#ifndef NO_CONFIG_WRITE +static char * wpa_config_write_psk_list(const struct parse_data *data, + struct wpa_ssid *ssid) +{ + return NULL; +} +#endif /* NO_CONFIG_WRITE */ + +#endif /* CONFIG_P2P */ + + +#ifdef CONFIG_MESH + +static int wpa_config_parse_mesh_basic_rates(const struct parse_data *data, + struct wpa_ssid *ssid, int line, + const char *value) +{ + int *rates = wpa_config_parse_int_array(value); + + if (rates == NULL) { + wpa_printf(MSG_ERROR, "Line %d: Invalid mesh_basic_rates '%s'", + line, value); + return -1; + } + if (rates[0] == 0) { + os_free(rates); + rates = NULL; + } + + os_free(ssid->mesh_basic_rates); + ssid->mesh_basic_rates = rates; + + return 0; +} + + +#ifndef NO_CONFIG_WRITE + +static char * wpa_config_write_mesh_basic_rates(const struct parse_data *data, + struct wpa_ssid *ssid) +{ + return wpa_config_write_freqs(data, ssid->mesh_basic_rates); +} + +#endif /* NO_CONFIG_WRITE */ + +#endif /* CONFIG_MESH */ + + +/* Helper macros for network block parser */ + +#ifdef OFFSET +#undef OFFSET +#endif /* OFFSET */ +/* OFFSET: Get offset of a variable within the wpa_ssid structure */ +#define OFFSET(v) ((void *) &((struct wpa_ssid *) 0)->v) + +/* STR: Define a string variable for an ASCII string; f = field name */ +#ifdef NO_CONFIG_WRITE +#define _STR(f) #f, wpa_config_parse_str, OFFSET(f) +#define _STRe(f) #f, wpa_config_parse_str, OFFSET(eap.f) +#else /* NO_CONFIG_WRITE */ +#define _STR(f) #f, wpa_config_parse_str, wpa_config_write_str, OFFSET(f) +#define _STRe(f) #f, wpa_config_parse_str, wpa_config_write_str, OFFSET(eap.f) +#endif /* NO_CONFIG_WRITE */ +#define STR(f) _STR(f), NULL, NULL, NULL, 0 +#define STRe(f) _STRe(f), NULL, NULL, NULL, 0 +#define STR_KEY(f) _STR(f), NULL, NULL, NULL, 1 +#define STR_KEYe(f) _STRe(f), NULL, NULL, NULL, 1 + +/* STR_LEN: Define a string variable with a separate variable for storing the + * data length. Unlike STR(), this can be used to store arbitrary binary data + * (i.e., even nul termination character). */ +#define _STR_LEN(f) _STR(f), OFFSET(f ## _len) +#define _STR_LENe(f) _STRe(f), OFFSET(eap.f ## _len) +#define STR_LEN(f) _STR_LEN(f), NULL, NULL, 0 +#define STR_LENe(f) _STR_LENe(f), NULL, NULL, 0 +#define STR_LEN_KEY(f) _STR_LEN(f), NULL, NULL, 1 + +/* STR_RANGE: Like STR_LEN(), but with minimum and maximum allowed length + * explicitly specified. */ +#define _STR_RANGE(f, min, max) _STR_LEN(f), (void *) (min), (void *) (max) +#define STR_RANGE(f, min, max) _STR_RANGE(f, min, max), 0 +#define STR_RANGE_KEY(f, min, max) _STR_RANGE(f, min, max), 1 + +#ifdef NO_CONFIG_WRITE +#define _INT(f) #f, wpa_config_parse_int, OFFSET(f), (void *) 0 +#define _INTe(f) #f, wpa_config_parse_int, OFFSET(eap.f), (void *) 0 +#else /* NO_CONFIG_WRITE */ +#define _INT(f) #f, wpa_config_parse_int, wpa_config_write_int, \ + OFFSET(f), (void *) 0 +#define _INTe(f) #f, wpa_config_parse_int, wpa_config_write_int, \ + OFFSET(eap.f), (void *) 0 +#endif /* NO_CONFIG_WRITE */ + +/* INT: Define an integer variable */ +#define INT(f) _INT(f), NULL, NULL, 0 +#define INTe(f) _INTe(f), NULL, NULL, 0 + +/* INT_RANGE: Define an integer variable with allowed value range */ +#define INT_RANGE(f, min, max) _INT(f), (void *) (min), (void *) (max), 0 + +/* FUNC: Define a configuration variable that uses a custom function for + * parsing and writing the value. */ +#ifdef NO_CONFIG_WRITE +#define _FUNC(f) #f, wpa_config_parse_ ## f, NULL, NULL, NULL, NULL +#else /* NO_CONFIG_WRITE */ +#define _FUNC(f) #f, wpa_config_parse_ ## f, wpa_config_write_ ## f, \ + NULL, NULL, NULL, NULL +#endif /* NO_CONFIG_WRITE */ +#define FUNC(f) _FUNC(f), 0 +#define FUNC_KEY(f) _FUNC(f), 1 + +/* + * Table of network configuration variables. This table is used to parse each + * network configuration variable, e.g., each line in wpa_supplicant.conf file + * that is inside a network block. + * + * This table is generated using the helper macros defined above and with + * generous help from the C pre-processor. The field name is stored as a string + * into .name and for STR and INT types, the offset of the target buffer within + * struct wpa_ssid is stored in .param1. .param2 (if not NULL) is similar + * offset to the field containing the length of the configuration variable. + * .param3 and .param4 can be used to mark the allowed range (length for STR + * and value for INT). + * + * For each configuration line in wpa_supplicant.conf, the parser goes through + * this table and select the entry that matches with the field name. The parser + * function (.parser) is then called to parse the actual value of the field. + * + * This kind of mechanism makes it easy to add new configuration parameters, + * since only one line needs to be added into this table and into the + * struct wpa_ssid definition if the new variable is either a string or + * integer. More complex types will need to use their own parser and writer + * functions. + */ +static const struct parse_data ssid_fields[] = { + { STR_RANGE(ssid, 0, SSID_MAX_LEN) }, + { INT_RANGE(scan_ssid, 0, 1) }, + { FUNC(bssid) }, + { FUNC(bssid_blacklist) }, + { FUNC(bssid_whitelist) }, + { FUNC_KEY(psk) }, + { INT(mem_only_psk) }, + { FUNC(proto) }, + { FUNC(key_mgmt) }, + { INT(bg_scan_period) }, + { FUNC(pairwise) }, + { FUNC(group) }, + { FUNC(auth_alg) }, + { FUNC(scan_freq) }, + { FUNC(freq_list) }, +#ifdef IEEE8021X_EAPOL + { FUNC(eap) }, + { STR_LENe(identity) }, + { STR_LENe(anonymous_identity) }, + { FUNC_KEY(password) }, + { STRe(ca_cert) }, + { STRe(ca_path) }, + { STRe(client_cert) }, + { STRe(private_key) }, + { STR_KEYe(private_key_passwd) }, + { STRe(dh_file) }, + { STRe(subject_match) }, + { STRe(altsubject_match) }, + { STRe(domain_suffix_match) }, + { STRe(domain_match) }, + { STRe(ca_cert2) }, + { STRe(ca_path2) }, + { STRe(client_cert2) }, + { STRe(private_key2) }, + { STR_KEYe(private_key2_passwd) }, + { STRe(dh_file2) }, + { STRe(subject_match2) }, + { STRe(altsubject_match2) }, + { STRe(domain_suffix_match2) }, + { STRe(domain_match2) }, + { STRe(phase1) }, + { STRe(phase2) }, + { STRe(pcsc) }, + { STR_KEYe(pin) }, + { STRe(engine_id) }, + { STRe(key_id) }, + { STRe(cert_id) }, + { STRe(ca_cert_id) }, + { STR_KEYe(pin2) }, + { STRe(engine2_id) }, + { STRe(key2_id) }, + { STRe(cert2_id) }, + { STRe(ca_cert2_id) }, + { INTe(engine) }, + { INTe(engine2) }, + { INT(eapol_flags) }, + { INTe(sim_num) }, + { STRe(openssl_ciphers) }, + { INTe(erp) }, +#endif /* IEEE8021X_EAPOL */ + { FUNC_KEY(wep_key0) }, + { FUNC_KEY(wep_key1) }, + { FUNC_KEY(wep_key2) }, + { FUNC_KEY(wep_key3) }, + { INT(wep_tx_keyidx) }, + { INT(priority) }, +#ifdef IEEE8021X_EAPOL + { INT(eap_workaround) }, + { STRe(pac_file) }, + { INTe(fragment_size) }, + { INTe(ocsp) }, +#endif /* IEEE8021X_EAPOL */ +#ifdef CONFIG_MESH + { INT_RANGE(mode, 0, 5) }, + { INT_RANGE(no_auto_peer, 0, 1) }, +#else /* CONFIG_MESH */ + { INT_RANGE(mode, 0, 4) }, +#endif /* CONFIG_MESH */ + { INT_RANGE(proactive_key_caching, 0, 1) }, + { INT_RANGE(disabled, 0, 2) }, + { STR(id_str) }, +#ifdef CONFIG_IEEE80211W + { INT_RANGE(ieee80211w, 0, 2) }, +#endif /* CONFIG_IEEE80211W */ + { INT_RANGE(peerkey, 0, 1) }, + { INT_RANGE(mixed_cell, 0, 1) }, + { INT_RANGE(frequency, 0, 65000) }, + { INT_RANGE(fixed_freq, 0, 1) }, +#ifdef CONFIG_MESH + { FUNC(mesh_basic_rates) }, + { INT(dot11MeshMaxRetries) }, + { INT(dot11MeshRetryTimeout) }, + { INT(dot11MeshConfirmTimeout) }, + { INT(dot11MeshHoldingTimeout) }, +#endif /* CONFIG_MESH */ + { INT(wpa_ptk_rekey) }, + { STR(bgscan) }, + { INT_RANGE(ignore_broadcast_ssid, 0, 2) }, +#ifdef CONFIG_P2P + { FUNC(go_p2p_dev_addr) }, + { FUNC(p2p_client_list) }, + { FUNC(psk_list) }, +#endif /* CONFIG_P2P */ +#ifdef CONFIG_HT_OVERRIDES + { INT_RANGE(disable_ht, 0, 1) }, + { INT_RANGE(disable_ht40, -1, 1) }, + { INT_RANGE(disable_sgi, 0, 1) }, + { INT_RANGE(disable_ldpc, 0, 1) }, + { INT_RANGE(ht40_intolerant, 0, 1) }, + { INT_RANGE(disable_max_amsdu, -1, 1) }, + { INT_RANGE(ampdu_factor, -1, 3) }, + { INT_RANGE(ampdu_density, -1, 7) }, + { STR(ht_mcs) }, +#endif /* CONFIG_HT_OVERRIDES */ +#ifdef CONFIG_VHT_OVERRIDES + { INT_RANGE(disable_vht, 0, 1) }, + { INT(vht_capa) }, + { INT(vht_capa_mask) }, + { INT_RANGE(vht_rx_mcs_nss_1, -1, 3) }, + { INT_RANGE(vht_rx_mcs_nss_2, -1, 3) }, + { INT_RANGE(vht_rx_mcs_nss_3, -1, 3) }, + { INT_RANGE(vht_rx_mcs_nss_4, -1, 3) }, + { INT_RANGE(vht_rx_mcs_nss_5, -1, 3) }, + { INT_RANGE(vht_rx_mcs_nss_6, -1, 3) }, + { INT_RANGE(vht_rx_mcs_nss_7, -1, 3) }, + { INT_RANGE(vht_rx_mcs_nss_8, -1, 3) }, + { INT_RANGE(vht_tx_mcs_nss_1, -1, 3) }, + { INT_RANGE(vht_tx_mcs_nss_2, -1, 3) }, + { INT_RANGE(vht_tx_mcs_nss_3, -1, 3) }, + { INT_RANGE(vht_tx_mcs_nss_4, -1, 3) }, + { INT_RANGE(vht_tx_mcs_nss_5, -1, 3) }, + { INT_RANGE(vht_tx_mcs_nss_6, -1, 3) }, + { INT_RANGE(vht_tx_mcs_nss_7, -1, 3) }, + { INT_RANGE(vht_tx_mcs_nss_8, -1, 3) }, +#endif /* CONFIG_VHT_OVERRIDES */ + { INT(ap_max_inactivity) }, + { INT(dtim_period) }, + { INT(beacon_int) }, +#ifdef CONFIG_MACSEC + { INT_RANGE(macsec_policy, 0, 1) }, +#endif /* CONFIG_MACSEC */ +#ifdef CONFIG_HS20 + { INT(update_identifier) }, +#endif /* CONFIG_HS20 */ + { INT_RANGE(mac_addr, 0, 2) }, +}; + +#undef OFFSET +#undef _STR +#undef STR +#undef STR_KEY +#undef _STR_LEN +#undef STR_LEN +#undef STR_LEN_KEY +#undef _STR_RANGE +#undef STR_RANGE +#undef STR_RANGE_KEY +#undef _INT +#undef INT +#undef INT_RANGE +#undef _FUNC +#undef FUNC +#undef FUNC_KEY +#define NUM_SSID_FIELDS ARRAY_SIZE(ssid_fields) + + +/** + * wpa_config_add_prio_network - Add a network to priority lists + * @config: Configuration data from wpa_config_read() + * @ssid: Pointer to the network configuration to be added to the list + * Returns: 0 on success, -1 on failure + * + * This function is used to add a network block to the priority list of + * networks. This must be called for each network when reading in the full + * configuration. In addition, this can be used indirectly when updating + * priorities by calling wpa_config_update_prio_list(). + */ +int wpa_config_add_prio_network(struct wpa_config *config, + struct wpa_ssid *ssid) +{ + int prio; + struct wpa_ssid *prev, **nlist; + + /* + * Add to an existing priority list if one is available for the + * configured priority level for this network. + */ + for (prio = 0; prio < config->num_prio; prio++) { + prev = config->pssid[prio]; + if (prev->priority == ssid->priority) { + while (prev->pnext) + prev = prev->pnext; + prev->pnext = ssid; + return 0; + } + } + + /* First network for this priority - add a new priority list */ + nlist = os_realloc_array(config->pssid, config->num_prio + 1, + sizeof(struct wpa_ssid *)); + if (nlist == NULL) + return -1; + + for (prio = 0; prio < config->num_prio; prio++) { + if (nlist[prio]->priority < ssid->priority) { + os_memmove(&nlist[prio + 1], &nlist[prio], + (config->num_prio - prio) * + sizeof(struct wpa_ssid *)); + break; + } + } + + nlist[prio] = ssid; + config->num_prio++; + config->pssid = nlist; + + return 0; +} + + +/** + * wpa_config_update_prio_list - Update network priority list + * @config: Configuration data from wpa_config_read() + * Returns: 0 on success, -1 on failure + * + * This function is called to update the priority list of networks in the + * configuration when a network is being added or removed. This is also called + * if a priority for a network is changed. + */ +int wpa_config_update_prio_list(struct wpa_config *config) +{ + struct wpa_ssid *ssid; + int ret = 0; + + os_free(config->pssid); + config->pssid = NULL; + config->num_prio = 0; + + ssid = config->ssid; + while (ssid) { + ssid->pnext = NULL; + if (wpa_config_add_prio_network(config, ssid) < 0) + ret = -1; + ssid = ssid->next; + } + + return ret; +} + +/** + * wpa_config_free_ssid - Free network/ssid configuration data + * @ssid: Configuration data for the network + * + * This function frees all resources allocated for the network configuration + * data. + */ +void wpa_config_free_ssid(struct wpa_ssid *ssid) +{ + struct psk_list_entry *psk; + + os_free(ssid->ssid); + str_clear_free(ssid->passphrase); + os_free(ssid->ext_psk); + +#ifdef IEEE8021X_EAPOL + eap_peer_config_free(&ssid->eap); +#endif /* IEEE8021X_EAPOL */ + + os_free(ssid->id_str); + os_free(ssid->scan_freq); + os_free(ssid->freq_list); + os_free(ssid->bgscan); + os_free(ssid->p2p_client_list); + os_free(ssid->bssid_blacklist); + os_free(ssid->bssid_whitelist); + +#ifdef CONFIG_HT_OVERRIDES + os_free(ssid->ht_mcs); +#endif /* CONFIG_HT_OVERRIDES */ + +#ifdef CONFIG_MESH + os_free(ssid->mesh_basic_rates); +#endif /* CONFIG_MESH */ + + while (NULL != (psk = dl_list_first(&ssid->psk_list, struct psk_list_entry, + list))) { + dl_list_del(&psk->list); + bin_clear_free(psk, sizeof(*psk)); + } + bin_clear_free(ssid, sizeof(*ssid)); +} + + +void wpa_config_free_cred(struct wpa_cred *cred) +{ + size_t i; + + os_free(cred->realm); + str_clear_free(cred->username); + str_clear_free(cred->password); + os_free(cred->ca_cert); + os_free(cred->client_cert); + os_free(cred->private_key); + str_clear_free(cred->private_key_passwd); + os_free(cred->imsi); + str_clear_free(cred->milenage); + for (i = 0; i < cred->num_domain; i++) + os_free(cred->domain[i]); + os_free(cred->domain); + os_free(cred->domain_suffix_match); + os_free(cred->eap_method); + os_free(cred->phase1); + os_free(cred->phase2); + os_free(cred->excluded_ssid); + os_free(cred->roaming_partner); + os_free(cred->provisioning_sp); + for (i = 0; i < cred->num_req_conn_capab; i++) + os_free(cred->req_conn_capab_port[i]); + os_free(cred->req_conn_capab_port); + os_free(cred->req_conn_capab_proto); + os_free(cred); +} + + + + + +/** + * wpa_config_free - Free configuration data + * @config: Configuration data from wpa_config_read() + * + * This function frees all resources allocated for the configuration data by + * wpa_config_read(). + */ +void wpa_config_free(struct wpa_config *config) +{ + struct wpa_ssid *ssid, *prev = NULL; + struct wpa_cred *cred, *cprev; + int i; + + ssid = config->ssid; + while (ssid) { + prev = ssid; + ssid = ssid->next; + wpa_config_free_ssid(prev); + } + + wpabuf_free(config->wps_vendor_ext_m1); + for (i = 0; i < MAX_WPS_VENDOR_EXT; i++) + wpabuf_free(config->wps_vendor_ext[i]); + os_free(config->ctrl_interface); + os_free(config->ctrl_interface_group); + os_free(config->opensc_engine_path); + os_free(config->pkcs11_engine_path); + os_free(config->pkcs11_module_path); + os_free(config->openssl_ciphers); + os_free(config->pcsc_reader); + str_clear_free(config->pcsc_pin); + os_free(config->driver_param); + os_free(config->device_name); + os_free(config->manufacturer); + os_free(config->model_name); + os_free(config->model_number); + os_free(config->serial_number); + os_free(config->config_methods); + os_free(config->p2p_ssid_postfix); + os_free(config->pssid); + os_free(config->p2p_pref_chan); + os_free(config->p2p_no_go_freq.range); + os_free(config->autoscan); + os_free(config->freq_list); + wpabuf_free(config->wps_nfc_dh_pubkey); + wpabuf_free(config->wps_nfc_dh_privkey); + wpabuf_free(config->wps_nfc_dev_pw); + os_free(config->ext_password_backend); + os_free(config->sae_groups); + wpabuf_free(config->ap_vendor_elements); + os_free(config->osu_dir); + os_free(config->bgscan); + os_free(config->wowlan_triggers); + os_free(config->fst_group_id); + os_free(config); + (void)cred; + (void)cprev; +} + + +/** + * wpa_config_foreach_network - Iterate over each configured network + * @config: Configuration data from wpa_config_read() + * @func: Callback function to process each network + * @arg: Opaque argument to pass to callback function + * + * Iterate over the set of configured networks calling the specified + * function for each item. We guard against callbacks removing the + * supplied network. + */ +void wpa_config_foreach_network(struct wpa_config *config, + void (*func)(void *, struct wpa_ssid *), + void *arg) +{ + struct wpa_ssid *ssid, *next; + + ssid = config->ssid; + while (ssid) { + next = ssid->next; + func(arg, ssid); + ssid = next; + } +} + + +/** + * wpa_config_get_network - Get configured network based on id + * @config: Configuration data from wpa_config_read() + * @id: Unique network id to search for + * Returns: Network configuration or %NULL if not found + */ +struct wpa_ssid * wpa_config_get_network(struct wpa_config *config, int id) +{ + struct wpa_ssid *ssid; + + ssid = config->ssid; + while (ssid) { + if (id == ssid->id) + break; + ssid = ssid->next; + } + + return ssid; +} + + +/** + * wpa_config_add_network - Add a new network with empty configuration + * @config: Configuration data from wpa_config_read() + * Returns: The new network configuration or %NULL if operation failed + */ +struct wpa_ssid * wpa_config_add_network(struct wpa_config *config) +{ + int id; + struct wpa_ssid *ssid, *last = NULL; + + id = -1; + ssid = config->ssid; + while (ssid) { + if (ssid->id > id) + id = ssid->id; + last = ssid; + ssid = ssid->next; + } + id++; + + ssid = os_zalloc(sizeof(*ssid)); + if (ssid == NULL) + return NULL; + ssid->id = id; + dl_list_init(&ssid->psk_list); + if (last) + last->next = ssid; + else + config->ssid = ssid; + + wpa_config_update_prio_list(config); + + return ssid; +} + + +/** + * wpa_config_remove_network - Remove a configured network based on id + * @config: Configuration data from wpa_config_read() + * @id: Unique network id to search for + * Returns: 0 on success, or -1 if the network was not found + */ +int wpa_config_remove_network(struct wpa_config *config, int id) +{ + struct wpa_ssid *ssid, *prev = NULL; + + ssid = config->ssid; + while (ssid) { + if (id == ssid->id) + break; + prev = ssid; + ssid = ssid->next; + } + + if (ssid == NULL) + return -1; + + if (prev) + prev->next = ssid->next; + else + config->ssid = ssid->next; + + wpa_config_update_prio_list(config); + wpa_config_free_ssid(ssid); + return 0; +} + + +/** + * wpa_config_set_network_defaults - Set network default values + * @ssid: Pointer to network configuration data + */ +void wpa_config_set_network_defaults(struct wpa_ssid *ssid) +{ + ssid->proto = DEFAULT_PROTO; + ssid->pairwise_cipher = DEFAULT_PAIRWISE; + ssid->group_cipher = DEFAULT_GROUP; + ssid->key_mgmt = DEFAULT_KEY_MGMT; + ssid->bg_scan_period = DEFAULT_BG_SCAN_PERIOD; + +#ifdef CONFIG_MESH + ssid->dot11MeshMaxRetries = DEFAULT_MESH_MAX_RETRIES; + ssid->dot11MeshRetryTimeout = DEFAULT_MESH_RETRY_TIMEOUT; + ssid->dot11MeshConfirmTimeout = DEFAULT_MESH_CONFIRM_TIMEOUT; + ssid->dot11MeshHoldingTimeout = DEFAULT_MESH_HOLDING_TIMEOUT; +#endif /* CONFIG_MESH */ + +#ifdef CONFIG_HT_OVERRIDES + ssid->disable_ht = DEFAULT_DISABLE_HT; + ssid->disable_ht40 = DEFAULT_DISABLE_HT40; + ssid->disable_sgi = DEFAULT_DISABLE_SGI; + ssid->disable_ldpc = DEFAULT_DISABLE_LDPC; + ssid->disable_max_amsdu = DEFAULT_DISABLE_MAX_AMSDU; + ssid->ampdu_factor = DEFAULT_AMPDU_FACTOR; + ssid->ampdu_density = DEFAULT_AMPDU_DENSITY; +#endif /* CONFIG_HT_OVERRIDES */ + +#ifdef CONFIG_VHT_OVERRIDES + ssid->vht_rx_mcs_nss_1 = -1; + ssid->vht_rx_mcs_nss_2 = -1; + ssid->vht_rx_mcs_nss_3 = -1; + ssid->vht_rx_mcs_nss_4 = -1; + ssid->vht_rx_mcs_nss_5 = -1; + ssid->vht_rx_mcs_nss_6 = -1; + ssid->vht_rx_mcs_nss_7 = -1; + ssid->vht_rx_mcs_nss_8 = -1; + ssid->vht_tx_mcs_nss_1 = -1; + ssid->vht_tx_mcs_nss_2 = -1; + ssid->vht_tx_mcs_nss_3 = -1; + ssid->vht_tx_mcs_nss_4 = -1; + ssid->vht_tx_mcs_nss_5 = -1; + ssid->vht_tx_mcs_nss_6 = -1; + ssid->vht_tx_mcs_nss_7 = -1; + ssid->vht_tx_mcs_nss_8 = -1; +#endif /* CONFIG_VHT_OVERRIDES */ + + ssid->proactive_key_caching = -1; + +#ifdef CONFIG_IEEE80211W + ssid->ieee80211w = MGMT_FRAME_PROTECTION_DEFAULT; +#endif /* CONFIG_IEEE80211W */ + ssid->mac_addr = -1; +} + + +/** + * wpa_config_set - Set a variable in network configuration + * @ssid: Pointer to network configuration data + * @var: Variable name, e.g., "ssid" + * @value: Variable value + * @line: Line number in configuration file or 0 if not used + * Returns: 0 on success, -1 on failure + * + * This function can be used to set network configuration variables based on + * both the configuration file and management interface input. The value + * parameter must be in the same format as the text-based configuration file is + * using. For example, strings are using double quotation marks. + */ +int wpa_config_set(struct wpa_ssid *ssid, const char *var, const char *value, + int line) +{ + size_t i; + int ret = 0; + + if (ssid == NULL || var == NULL || value == NULL) + return -1; + + for (i = 0; i < NUM_SSID_FIELDS; i++) { + const struct parse_data *field = &ssid_fields[i]; + if (os_strcmp(var, field->name) != 0) + continue; + + if (field->parser(field, ssid, line, value)) { + if (line) { + wpa_printf(MSG_ERROR, "Line %d: failed to " + "parse %s '%s'.", line, var, value); + } + ret = -1; + } + break; + } + if (i == NUM_SSID_FIELDS) { + if (line) { + wpa_printf(MSG_ERROR, "Line %d: unknown network field " + "'%s'.", line, var); + } + ret = -1; + } + + return ret; +} + + +int wpa_config_set_quoted(struct wpa_ssid *ssid, const char *var, + const char *value) +{ + size_t len; + char *buf; + int ret; + + len = os_strlen(value); + buf = os_malloc(len + 3); + if (buf == NULL) + return -1; + buf[0] = '"'; + os_memcpy(buf + 1, value, len); + buf[len + 1] = '"'; + buf[len + 2] = '\0'; + ret = wpa_config_set(ssid, var, buf, 0); + os_free(buf); + return ret; +} + + +/** + * wpa_config_get_all - Get all options from network configuration + * @ssid: Pointer to network configuration data + * @get_keys: Determines if keys/passwords will be included in returned list + * (if they may be exported) + * Returns: %NULL terminated list of all set keys and their values in the form + * of [key1, val1, key2, val2, ... , NULL] + * + * This function can be used to get list of all configured network properties. + * The caller is responsible for freeing the returned list and all its + * elements. + */ +char ** wpa_config_get_all(struct wpa_ssid *ssid, int get_keys) +{ +#ifdef NO_CONFIG_WRITE + return NULL; +#else /* NO_CONFIG_WRITE */ + + const struct parse_data *field; + char *key, *value; + size_t i; + char **props; + int fields_num; + + get_keys = get_keys && ssid->export_keys; + + props = os_calloc(2 * NUM_SSID_FIELDS + 1, sizeof(char *)); + if (!props) + return NULL; + + fields_num = 0; + for (i = 0; i < NUM_SSID_FIELDS; i++) { + field = &ssid_fields[i]; + if (field->key_data && !get_keys) + continue; + value = field->writer(field, ssid); + if (value == NULL) + continue; + if (os_strlen(value) == 0) { + os_free(value); + continue; + } + + key = os_strdup(field->name); + if (key == NULL) { + os_free(value); + goto err; + } + + props[fields_num * 2] = key; + props[fields_num * 2 + 1] = value; + + fields_num++; + } + + return props; + +err: + value = *props; + while (value) + os_free(value++); + os_free(props); + return NULL; +#endif /* NO_CONFIG_WRITE */ +} + + +#ifndef NO_CONFIG_WRITE +/** + * wpa_config_get - Get a variable in network configuration + * @ssid: Pointer to network configuration data + * @var: Variable name, e.g., "ssid" + * Returns: Value of the variable or %NULL on failure + * + * This function can be used to get network configuration variables. The + * returned value is a copy of the configuration variable in text format, i.e,. + * the same format that the text-based configuration file and wpa_config_set() + * are using for the value. The caller is responsible for freeing the returned + * value. + */ +char * wpa_config_get(struct wpa_ssid *ssid, const char *var) +{ + size_t i; + + if (ssid == NULL || var == NULL) + return NULL; + + for (i = 0; i < NUM_SSID_FIELDS; i++) { + const struct parse_data *field = &ssid_fields[i]; + if (os_strcmp(var, field->name) == 0) + return field->writer(field, ssid); + } + + return NULL; +} + + +/** + * wpa_config_get_no_key - Get a variable in network configuration (no keys) + * @ssid: Pointer to network configuration data + * @var: Variable name, e.g., "ssid" + * Returns: Value of the variable or %NULL on failure + * + * This function can be used to get network configuration variable like + * wpa_config_get(). The only difference is that this functions does not expose + * key/password material from the configuration. In case a key/password field + * is requested, the returned value is an empty string or %NULL if the variable + * is not set or "*" if the variable is set (regardless of its value). The + * returned value is a copy of the configuration variable in text format, i.e,. + * the same format that the text-based configuration file and wpa_config_set() + * are using for the value. The caller is responsible for freeing the returned + * value. + */ +char * wpa_config_get_no_key(struct wpa_ssid *ssid, const char *var) +{ + size_t i; + + if (ssid == NULL || var == NULL) + return NULL; + + for (i = 0; i < NUM_SSID_FIELDS; i++) { + const struct parse_data *field = &ssid_fields[i]; + if (os_strcmp(var, field->name) == 0) { + char *res = field->writer(field, ssid); + if (field->key_data) { + if (res && res[0]) { + wpa_printf(MSG_DEBUG, "Do not allow " + "key_data field to be " + "exposed"); + str_clear_free(res); + return os_strdup("*"); + } + + os_free(res); + return NULL; + } + return res; + } + } + + return NULL; +} +#endif /* NO_CONFIG_WRITE */ + + +/** + * wpa_config_update_psk - Update WPA PSK based on passphrase and SSID + * @ssid: Pointer to network configuration data + * + * This function must be called to update WPA PSK when either SSID or the + * passphrase has changed for the network configuration. + */ +void wpa_config_update_psk(struct wpa_ssid *ssid) +{ +#ifndef CONFIG_NO_PBKDF2 + pbkdf2_sha1(ssid->passphrase, ssid->ssid, ssid->ssid_len, 4096, + ssid->psk, PMK_LEN); + wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)", + ssid->psk, PMK_LEN); + ssid->psk_set = 1; +#endif /* CONFIG_NO_PBKDF2 */ +} + +static int wpa_config_set_cred_req_conn_capab(struct wpa_cred *cred, + const char *value) +{ + u8 *proto; + int **port; + int *ports, *nports; + const char *pos; + unsigned int num_ports; + + proto = os_realloc_array(cred->req_conn_capab_proto, + cred->num_req_conn_capab + 1, sizeof(u8)); + if (proto == NULL) + return -1; + cred->req_conn_capab_proto = proto; + + port = os_realloc_array(cred->req_conn_capab_port, + cred->num_req_conn_capab + 1, sizeof(int *)); + if (port == NULL) + return -1; + cred->req_conn_capab_port = port; + + proto[cred->num_req_conn_capab] = atoi(value); + + pos = os_strchr(value, ':'); + if (pos == NULL) { + port[cred->num_req_conn_capab] = NULL; + cred->num_req_conn_capab++; + return 0; + } + pos++; + + ports = NULL; + num_ports = 0; + + while (*pos) { + nports = os_realloc_array(ports, num_ports + 1, sizeof(int)); + if (nports == NULL) { + os_free(ports); + return -1; + } + ports = nports; + ports[num_ports++] = atoi(pos); + + pos = os_strchr(pos, ','); + if (pos == NULL) + break; + pos++; + } + + nports = os_realloc_array(ports, num_ports + 1, sizeof(int)); + if (nports == NULL) { + os_free(ports); + return -1; + } + ports = nports; + ports[num_ports] = -1; + + port[cred->num_req_conn_capab] = ports; + cred->num_req_conn_capab++; + return 0; +} + +int wpa_config_set_cred(struct wpa_cred *cred, const char *var, + const char *value, int line) +{ + char *val; + size_t len; + + if (os_strcmp(var, "temporary") == 0) { + cred->temporary = atoi(value); + return 0; + } + + if (os_strcmp(var, "priority") == 0) { + cred->priority = atoi(value); + return 0; + } + + if (os_strcmp(var, "sp_priority") == 0) { + int prio = atoi(value); + if (prio < 0 || prio > 255) + return -1; + cred->sp_priority = prio; + return 0; + } + + if (os_strcmp(var, "password") == 0 && + os_strncmp(value, "ext:", 4) == 0) { + str_clear_free(cred->password); + cred->password = os_strdup(value); + cred->ext_password = 1; + return 0; + } + + if (os_strcmp(var, "update_identifier") == 0) { + cred->update_identifier = atoi(value); + return 0; + } + + if (os_strcmp(var, "min_dl_bandwidth_home") == 0) { + cred->min_dl_bandwidth_home = atoi(value); + return 0; + } + + if (os_strcmp(var, "min_ul_bandwidth_home") == 0) { + cred->min_ul_bandwidth_home = atoi(value); + return 0; + } + + if (os_strcmp(var, "min_dl_bandwidth_roaming") == 0) { + cred->min_dl_bandwidth_roaming = atoi(value); + return 0; + } + + if (os_strcmp(var, "min_ul_bandwidth_roaming") == 0) { + cred->min_ul_bandwidth_roaming = atoi(value); + return 0; + } + + if (os_strcmp(var, "max_bss_load") == 0) { + cred->max_bss_load = atoi(value); + return 0; + } + + if (os_strcmp(var, "req_conn_capab") == 0) + return wpa_config_set_cred_req_conn_capab(cred, value); + + if (os_strcmp(var, "ocsp") == 0) { + cred->ocsp = atoi(value); + return 0; + } + + if (os_strcmp(var, "sim_num") == 0) { + cred->sim_num = atoi(value); + return 0; + } + + val = wpa_config_parse_string(value, &len); + if (val == NULL) { + wpa_printf(MSG_ERROR, "Line %d: invalid field '%s' string " + "value '%s'.", line, var, value); + return -1; + } + + if (os_strcmp(var, "realm") == 0) { + os_free(cred->realm); + cred->realm = val; + return 0; + } + + if (os_strcmp(var, "username") == 0) { + str_clear_free(cred->username); + cred->username = val; + return 0; + } + + if (os_strcmp(var, "password") == 0) { + str_clear_free(cred->password); + cred->password = val; + cred->ext_password = 0; + return 0; + } + + if (os_strcmp(var, "ca_cert") == 0) { + os_free(cred->ca_cert); + cred->ca_cert = val; + return 0; + } + + if (os_strcmp(var, "client_cert") == 0) { + os_free(cred->client_cert); + cred->client_cert = val; + return 0; + } + + if (os_strcmp(var, "private_key") == 0) { + os_free(cred->private_key); + cred->private_key = val; + return 0; + } + + if (os_strcmp(var, "private_key_passwd") == 0) { + str_clear_free(cred->private_key_passwd); + cred->private_key_passwd = val; + return 0; + } + + if (os_strcmp(var, "imsi") == 0) { + os_free(cred->imsi); + cred->imsi = val; + return 0; + } + + if (os_strcmp(var, "milenage") == 0) { + str_clear_free(cred->milenage); + cred->milenage = val; + return 0; + } + + if (os_strcmp(var, "domain_suffix_match") == 0) { + os_free(cred->domain_suffix_match); + cred->domain_suffix_match = val; + return 0; + } + + if (os_strcmp(var, "domain") == 0) { + char **new_domain; + new_domain = os_realloc_array(cred->domain, + cred->num_domain + 1, + sizeof(char *)); + if (new_domain == NULL) { + os_free(val); + return -1; + } + new_domain[cred->num_domain++] = val; + cred->domain = new_domain; + return 0; + } + + if (os_strcmp(var, "phase1") == 0) { + os_free(cred->phase1); + cred->phase1 = val; + return 0; + } + + if (os_strcmp(var, "phase2") == 0) { + os_free(cred->phase2); + cred->phase2 = val; + return 0; + } + + if (os_strcmp(var, "roaming_consortium") == 0) { + if (len < 3 || len > sizeof(cred->roaming_consortium)) { + wpa_printf(MSG_ERROR, "Line %d: invalid " + "roaming_consortium length %d (3..15 " + "expected)", line, (int) len); + os_free(val); + return -1; + } + os_memcpy(cred->roaming_consortium, val, len); + cred->roaming_consortium_len = len; + os_free(val); + return 0; + } + + if (os_strcmp(var, "required_roaming_consortium") == 0) { + if (len < 3 || len > sizeof(cred->required_roaming_consortium)) + { + wpa_printf(MSG_ERROR, "Line %d: invalid " + "required_roaming_consortium length %d " + "(3..15 expected)", line, (int) len); + os_free(val); + return -1; + } + os_memcpy(cred->required_roaming_consortium, val, len); + cred->required_roaming_consortium_len = len; + os_free(val); + return 0; + } + + if (os_strcmp(var, "excluded_ssid") == 0) { + struct excluded_ssid *e; + + if (len > SSID_MAX_LEN) { + wpa_printf(MSG_ERROR, "Line %d: invalid " + "excluded_ssid length %d", line, (int) len); + os_free(val); + return -1; + } + + e = os_realloc_array(cred->excluded_ssid, + cred->num_excluded_ssid + 1, + sizeof(struct excluded_ssid)); + if (e == NULL) { + os_free(val); + return -1; + } + cred->excluded_ssid = e; + + e = &cred->excluded_ssid[cred->num_excluded_ssid++]; + os_memcpy(e->ssid, val, len); + e->ssid_len = len; + + os_free(val); + + return 0; + } + + if (os_strcmp(var, "roaming_partner") == 0) { + struct roaming_partner *p; + char *pos; + + p = os_realloc_array(cred->roaming_partner, + cred->num_roaming_partner + 1, + sizeof(struct roaming_partner)); + if (p == NULL) { + os_free(val); + return -1; + } + cred->roaming_partner = p; + + p = &cred->roaming_partner[cred->num_roaming_partner]; + + pos = os_strchr(val, ','); + if (pos == NULL) { + os_free(val); + return -1; + } + *pos++ = '\0'; + if (pos - val - 1 >= (int) sizeof(p->fqdn)) { + os_free(val); + return -1; + } + os_memcpy(p->fqdn, val, pos - val); + + p->exact_match = atoi(pos); + + pos = os_strchr(pos, ','); + if (pos == NULL) { + os_free(val); + return -1; + } + *pos++ = '\0'; + + p->priority = atoi(pos); + + pos = os_strchr(pos, ','); + if (pos == NULL) { + os_free(val); + return -1; + } + *pos++ = '\0'; + + if (os_strlen(pos) >= sizeof(p->country)) { + os_free(val); + return -1; + } + os_memcpy(p->country, pos, os_strlen(pos) + 1); + + cred->num_roaming_partner++; + os_free(val); + + return 0; + } + + if (os_strcmp(var, "provisioning_sp") == 0) { + os_free(cred->provisioning_sp); + cred->provisioning_sp = val; + return 0; + } + + if (line) { + wpa_printf(MSG_ERROR, "Line %d: unknown cred field '%s'.", + line, var); + } + + os_free(val); + + return -1; +} + +static char * alloc_int_str(int val) +{ + const unsigned int bufsize = 20; + char *buf; + int res; + + buf = os_malloc(bufsize); + if (buf == NULL) + return NULL; + res = os_snprintf(buf, bufsize, "%d", val); + if (os_snprintf_error(bufsize, res)) { + os_free(buf); + buf = NULL; + } + return buf; +} + +static char * alloc_strdup(const char *str) +{ + if (str == NULL) + return NULL; + return os_strdup(str); +} + +char * wpa_config_get_cred_no_key(struct wpa_cred *cred, const char *var) +{ + if (os_strcmp(var, "temporary") == 0) + return alloc_int_str(cred->temporary); + + if (os_strcmp(var, "priority") == 0) + return alloc_int_str(cred->priority); + + if (os_strcmp(var, "sp_priority") == 0) + return alloc_int_str(cred->sp_priority); + + if (os_strcmp(var, "update_identifier") == 0) + return alloc_int_str(cred->update_identifier); + + if (os_strcmp(var, "min_dl_bandwidth_home") == 0) + return alloc_int_str(cred->min_dl_bandwidth_home); + + if (os_strcmp(var, "min_ul_bandwidth_home") == 0) + return alloc_int_str(cred->min_ul_bandwidth_home); + + if (os_strcmp(var, "min_dl_bandwidth_roaming") == 0) + return alloc_int_str(cred->min_dl_bandwidth_roaming); + + if (os_strcmp(var, "min_ul_bandwidth_roaming") == 0) + return alloc_int_str(cred->min_ul_bandwidth_roaming); + + if (os_strcmp(var, "max_bss_load") == 0) + return alloc_int_str(cred->max_bss_load); + + if (os_strcmp(var, "req_conn_capab") == 0) { + unsigned int i; + char *buf, *end, *pos; + int ret; + + if (!cred->num_req_conn_capab) + return NULL; + + buf = os_malloc(4000); + if (buf == NULL) + return NULL; + pos = buf; + end = pos + 4000; + for (i = 0; i < cred->num_req_conn_capab; i++) { + int *ports; + + ret = os_snprintf(pos, end - pos, "%s%u", + i > 0 ? "\n" : "", + cred->req_conn_capab_proto[i]); + if (os_snprintf_error(end - pos, ret)) + return buf; + pos += ret; + + ports = cred->req_conn_capab_port[i]; + if (ports) { + int j; + for (j = 0; ports[j] != -1; j++) { + ret = os_snprintf(pos, end - pos, + "%s%d", + j > 0 ? "," : ":", + ports[j]); + if (os_snprintf_error(end - pos, ret)) + return buf; + pos += ret; + } + } + } + + return buf; + } + + if (os_strcmp(var, "ocsp") == 0) + return alloc_int_str(cred->ocsp); + + if (os_strcmp(var, "realm") == 0) + return alloc_strdup(cred->realm); + + if (os_strcmp(var, "username") == 0) + return alloc_strdup(cred->username); + + if (os_strcmp(var, "password") == 0) { + if (!cred->password) + return NULL; + return alloc_strdup("*"); + } + + if (os_strcmp(var, "ca_cert") == 0) + return alloc_strdup(cred->ca_cert); + + if (os_strcmp(var, "client_cert") == 0) + return alloc_strdup(cred->client_cert); + + if (os_strcmp(var, "private_key") == 0) + return alloc_strdup(cred->private_key); + + if (os_strcmp(var, "private_key_passwd") == 0) { + if (!cred->private_key_passwd) + return NULL; + return alloc_strdup("*"); + } + + if (os_strcmp(var, "imsi") == 0) + return alloc_strdup(cred->imsi); + + if (os_strcmp(var, "milenage") == 0) { + if (!(cred->milenage)) + return NULL; + return alloc_strdup("*"); + } + + if (os_strcmp(var, "domain_suffix_match") == 0) + return alloc_strdup(cred->domain_suffix_match); + + if (os_strcmp(var, "domain") == 0) { + unsigned int i; + char *buf, *end, *pos; + int ret; + + if (!cred->num_domain) + return NULL; + + buf = os_malloc(4000); + if (buf == NULL) + return NULL; + pos = buf; + end = pos + 4000; + + for (i = 0; i < cred->num_domain; i++) { + ret = os_snprintf(pos, end - pos, "%s%s", + i > 0 ? "\n" : "", cred->domain[i]); + if (os_snprintf_error(end - pos, ret)) + return buf; + pos += ret; + } + + return buf; + } + + if (os_strcmp(var, "phase1") == 0) + return alloc_strdup(cred->phase1); + + if (os_strcmp(var, "phase2") == 0) + return alloc_strdup(cred->phase2); + + if (os_strcmp(var, "roaming_consortium") == 0) { + size_t buflen; + char *buf; + + if (!cred->roaming_consortium_len) + return NULL; + buflen = cred->roaming_consortium_len * 2 + 1; + buf = os_malloc(buflen); + if (buf == NULL) + return NULL; + wpa_snprintf_hex(buf, buflen, cred->roaming_consortium, + cred->roaming_consortium_len); + return buf; + } + + if (os_strcmp(var, "required_roaming_consortium") == 0) { + size_t buflen; + char *buf; + + if (!cred->required_roaming_consortium_len) + return NULL; + buflen = cred->required_roaming_consortium_len * 2 + 1; + buf = os_malloc(buflen); + if (buf == NULL) + return NULL; + wpa_snprintf_hex(buf, buflen, cred->required_roaming_consortium, + cred->required_roaming_consortium_len); + return buf; + } + + if (os_strcmp(var, "excluded_ssid") == 0) { + unsigned int i; + char *buf, *end, *pos; + + if (!cred->num_excluded_ssid) + return NULL; + + buf = os_malloc(4000); + if (buf == NULL) + return NULL; + pos = buf; + end = pos + 4000; + + for (i = 0; i < cred->num_excluded_ssid; i++) { + struct excluded_ssid *e; + int ret; + + e = &cred->excluded_ssid[i]; + ret = os_snprintf(pos, end - pos, "%s%s", + i > 0 ? "\n" : "", + wpa_ssid_txt(e->ssid, e->ssid_len)); + if (os_snprintf_error(end - pos, ret)) + return buf; + pos += ret; + } + + return buf; + } + + if (os_strcmp(var, "roaming_partner") == 0) { + unsigned int i; + char *buf, *end, *pos; + + if (!cred->num_roaming_partner) + return NULL; + + buf = os_malloc(4000); + if (buf == NULL) + return NULL; + pos = buf; + end = pos + 4000; + + for (i = 0; i < cred->num_roaming_partner; i++) { + struct roaming_partner *p; + int ret; + + p = &cred->roaming_partner[i]; + ret = os_snprintf(pos, end - pos, "%s%s,%d,%u,%s", + i > 0 ? "\n" : "", + p->fqdn, p->exact_match, p->priority, + p->country); + if (os_snprintf_error(end - pos, ret)) + return buf; + pos += ret; + } + + return buf; + } + + if (os_strcmp(var, "provisioning_sp") == 0) + return alloc_strdup(cred->provisioning_sp); + + return NULL; +} + + +struct wpa_cred * wpa_config_get_cred(struct wpa_config *config, int id) +{ + struct wpa_cred *cred; + + cred = config->cred; + while (cred) { + if (id == cred->id) + break; + cred = cred->next; + } + + return cred; +} + + +struct wpa_cred * wpa_config_add_cred(struct wpa_config *config) +{ + int id; + struct wpa_cred *cred, *last = NULL; + + id = -1; + cred = config->cred; + while (cred) { + if (cred->id > id) + id = cred->id; + last = cred; + cred = cred->next; + } + id++; + + cred = os_zalloc(sizeof(*cred)); + if (cred == NULL) + return NULL; + cred->id = id; + cred->sim_num = DEFAULT_USER_SELECTED_SIM; + if (last) + last->next = cred; + else + config->cred = cred; + + return cred; +} + + +int wpa_config_remove_cred(struct wpa_config *config, int id) +{ + struct wpa_cred *cred, *prev = NULL; + + cred = config->cred; + while (cred) { + if (id == cred->id) + break; + prev = cred; + cred = cred->next; + } + + if (cred == NULL) + return -1; + + if (prev) + prev->next = cred->next; + else + config->cred = cred->next; + + wpa_config_free_cred(cred); + return 0; +} + + + +/** + * wpa_config_alloc_empty - Allocate an empty configuration + * @ctrl_interface: Control interface parameters, e.g., path to UNIX domain + * socket + * @driver_param: Driver parameters + * Returns: Pointer to allocated configuration data or %NULL on failure + */ +struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface, + const char *driver_param) +{ + struct wpa_config *config; + const int aCWmin = 4, aCWmax = 10; + const struct hostapd_wmm_ac_params ac_bk = + { aCWmin, aCWmax, 7, 0, 0 }; /* background traffic */ + const struct hostapd_wmm_ac_params ac_be = + { aCWmin, aCWmax, 3, 0, 0 }; /* best effort traffic */ + const struct hostapd_wmm_ac_params ac_vi = /* video traffic */ + { aCWmin - 1, aCWmin, 2, 3000 / 32, 0 }; + const struct hostapd_wmm_ac_params ac_vo = /* voice traffic */ + { aCWmin - 2, aCWmin - 1, 2, 1500 / 32, 0 }; + + config = os_zalloc(sizeof(*config)); + if (config == NULL) + return NULL; + config->eapol_version = DEFAULT_EAPOL_VERSION; + config->ap_scan = DEFAULT_AP_SCAN; + config->user_mpm = DEFAULT_USER_MPM; + config->max_peer_links = DEFAULT_MAX_PEER_LINKS; + config->mesh_max_inactivity = DEFAULT_MESH_MAX_INACTIVITY; + config->dot11RSNASAERetransPeriod = + DEFAULT_DOT11_RSNA_SAE_RETRANS_PERIOD; + config->fast_reauth = DEFAULT_FAST_REAUTH; + config->p2p_go_intent = DEFAULT_P2P_GO_INTENT; + config->p2p_intra_bss = DEFAULT_P2P_INTRA_BSS; + config->p2p_go_freq_change_policy = DEFAULT_P2P_GO_FREQ_MOVE; + config->p2p_go_max_inactivity = DEFAULT_P2P_GO_MAX_INACTIVITY; + config->p2p_optimize_listen_chan = DEFAULT_P2P_OPTIMIZE_LISTEN_CHAN; + config->p2p_go_ctwindow = DEFAULT_P2P_GO_CTWINDOW; + config->bss_max_count = DEFAULT_BSS_MAX_COUNT; + config->bss_expiration_age = DEFAULT_BSS_EXPIRATION_AGE; + config->bss_expiration_scan_count = DEFAULT_BSS_EXPIRATION_SCAN_COUNT; + config->max_num_sta = DEFAULT_MAX_NUM_STA; + config->access_network_type = DEFAULT_ACCESS_NETWORK_TYPE; + config->scan_cur_freq = DEFAULT_SCAN_CUR_FREQ; + config->wmm_ac_params[0] = ac_be; + config->wmm_ac_params[1] = ac_bk; + config->wmm_ac_params[2] = ac_vi; + config->wmm_ac_params[3] = ac_vo; + config->p2p_search_delay = DEFAULT_P2P_SEARCH_DELAY; + config->rand_addr_lifetime = DEFAULT_RAND_ADDR_LIFETIME; + config->key_mgmt_offload = DEFAULT_KEY_MGMT_OFFLOAD; + config->cert_in_cb = DEFAULT_CERT_IN_CB; + + if (ctrl_interface) + config->ctrl_interface = os_strdup(ctrl_interface); + if (driver_param) + config->driver_param = os_strdup(driver_param); + + return config; +} + + +#ifndef CONFIG_NO_STDOUT_DEBUG +/** + * wpa_config_debug_dump_networks - Debug dump of configured networks + * @config: Configuration data from wpa_config_read() + */ +void wpa_config_debug_dump_networks(struct wpa_config *config) +{ + int prio; + struct wpa_ssid *ssid; + + for (prio = 0; prio < config->num_prio; prio++) { + ssid = config->pssid[prio]; + wpa_printf(MSG_DEBUG, "Priority group %d", + ssid->priority); + while (ssid) { + wpa_printf(MSG_DEBUG, " id=%d ssid='%s'", + ssid->id, + wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); + ssid = ssid->pnext; + } + } +} +#endif /* CONFIG_NO_STDOUT_DEBUG */ + + +struct global_parse_data { + char *name; + int (*parser)(const struct global_parse_data *data, + struct wpa_config *config, int line, const char *value); + int (*get)(const char *name, struct wpa_config *config, long offset, + char *buf, size_t buflen, int pretty_print); + void *param1, *param2, *param3; + unsigned int changed_flag; +}; + + +static int wpa_global_config_parse_int(const struct global_parse_data *data, + struct wpa_config *config, int line, + const char *pos) +{ + int val, *dst; + char *end; + + dst = (int *) (((u8 *) config) + (long) data->param1); + val = strtol(pos, &end, 0); + if (*end) { + wpa_printf(MSG_ERROR, "Line %d: invalid number \"%s\"", + line, pos); + return -1; + } + *dst = val; + + wpa_printf(MSG_DEBUG, "%s=%d", data->name, *dst); + + if (data->param2 && *dst < (long) data->param2) { + wpa_printf(MSG_ERROR, "Line %d: too small %s (value=%d " + "min_value=%ld)", line, data->name, *dst, + (long) data->param2); + *dst = (long) data->param2; + return -1; + } + + if (data->param3 && *dst > (long) data->param3) { + wpa_printf(MSG_ERROR, "Line %d: too large %s (value=%d " + "max_value=%ld)", line, data->name, *dst, + (long) data->param3); + *dst = (long) data->param3; + return -1; + } + + return 0; +} + + +static int wpa_global_config_parse_str(const struct global_parse_data *data, + struct wpa_config *config, int line, + const char *pos) +{ + size_t len; + char **dst, *tmp; + + len = os_strlen(pos); + if (data->param2 && len < (size_t) data->param2) { + wpa_printf(MSG_ERROR, "Line %d: too short %s (len=%lu " + "min_len=%ld)", line, data->name, + (unsigned long) len, (long) data->param2); + return -1; + } + + if (data->param3 && len > (size_t) data->param3) { + wpa_printf(MSG_ERROR, "Line %d: too long %s (len=%lu " + "max_len=%ld)", line, data->name, + (unsigned long) len, (long) data->param3); + return -1; + } + + tmp = os_strdup(pos); + if (tmp == NULL) + return -1; + + dst = (char **) (((u8 *) config) + (long) data->param1); + os_free(*dst); + *dst = tmp; + wpa_printf(MSG_DEBUG, "%s='%s'", data->name, *dst); + + return 0; +} + + +static int wpa_config_process_bgscan(const struct global_parse_data *data, + struct wpa_config *config, int line, + const char *pos) +{ + size_t len; + char *tmp; + int res; + + tmp = wpa_config_parse_string(pos, &len); + if (tmp == NULL) { + wpa_printf(MSG_ERROR, "Line %d: failed to parse %s", + line, data->name); + return -1; + } + + res = wpa_global_config_parse_str(data, config, line, tmp); + os_free(tmp); + return res; +} + + +static int wpa_global_config_parse_bin(const struct global_parse_data *data, + struct wpa_config *config, int line, + const char *pos) +{ + size_t len; + struct wpabuf **dst, *tmp; + + len = os_strlen(pos); + if (len & 0x01) + return -1; + + tmp = wpabuf_alloc(len / 2); + if (tmp == NULL) + return -1; + + if (hexstr2bin(pos, wpabuf_put(tmp, len / 2), len / 2)) { + wpabuf_free(tmp); + return -1; + } + + dst = (struct wpabuf **) (((u8 *) config) + (long) data->param1); + wpabuf_free(*dst); + *dst = tmp; + wpa_printf(MSG_DEBUG, "%s", data->name); + + return 0; +} + + +static int wpa_config_process_freq_list(const struct global_parse_data *data, + struct wpa_config *config, int line, + const char *value) +{ + int *freqs; + + freqs = wpa_config_parse_int_array(value); + if (freqs == NULL) + return -1; + if (freqs[0] == 0) { + os_free(freqs); + freqs = NULL; + } + os_free(config->freq_list); + config->freq_list = freqs; + return 0; +} + + +#ifdef CONFIG_P2P +static int wpa_global_config_parse_ipv4(const struct global_parse_data *data, + struct wpa_config *config, int line, + const char *pos) +{ + u32 *dst; + struct hostapd_ip_addr addr; + + if (hostapd_parse_ip_addr(pos, &addr) < 0) + return -1; + if (addr.af != AF_INET) + return -1; + + dst = (u32 *) (((u8 *) config) + (long) data->param1); + os_memcpy(dst, &addr.u.v4.s_addr, 4); + wpa_printf(MSG_DEBUG, "%s = 0x%x", data->name, + WPA_GET_BE32((u8 *) dst)); + + return 0; +} +#endif /* CONFIG_P2P */ + + +static int wpa_config_process_country(const struct global_parse_data *data, + struct wpa_config *config, int line, + const char *pos) +{ + if (!pos[0] || !pos[1]) { + wpa_printf(MSG_DEBUG, "Invalid country set"); + return -1; + } + config->country[0] = pos[0]; + config->country[1] = pos[1]; + wpa_printf(MSG_DEBUG, "country='%c%c'", + config->country[0], config->country[1]); + return 0; +} + + +static int wpa_config_process_load_dynamic_eap( + const struct global_parse_data *data, struct wpa_config *config, + int line, const char *so) +{ +#ifdef CONFIG_FULL_SUPPLICANT + int ret; + wpa_printf(MSG_DEBUG, "load_dynamic_eap=%s", so); + ret = eap_peer_method_load(so); + if (ret == -2) { + wpa_printf(MSG_DEBUG, "This EAP type was already loaded - not " + "reloading."); + } else if (ret) { + wpa_printf(MSG_ERROR, "Line %d: Failed to load dynamic EAP " + "method '%s'.", line, so); + return -1; + } +#endif + + return 0; +} + +static int wpa_config_process_hessid( + const struct global_parse_data *data, + struct wpa_config *config, int line, const char *pos) +{ + if (hwaddr_aton2(pos, config->hessid) < 0) { + wpa_printf(MSG_ERROR, "Line %d: Invalid hessid '%s'", + line, pos); + return -1; + } + + return 0; +} + + +static int wpa_config_process_sae_groups( + const struct global_parse_data *data, + struct wpa_config *config, int line, const char *pos) +{ + int *groups = wpa_config_parse_int_array(pos); + if (groups == NULL) { + wpa_printf(MSG_ERROR, "Line %d: Invalid sae_groups '%s'", + line, pos); + return -1; + } + + os_free(config->sae_groups); + config->sae_groups = groups; + + return 0; +} + + +static int wpa_config_process_ap_vendor_elements( + const struct global_parse_data *data, + struct wpa_config *config, int line, const char *pos) +{ + struct wpabuf *tmp; + int len = os_strlen(pos) / 2; + u8 *p; + + if (!len) { + wpa_printf(MSG_ERROR, "Line %d: invalid ap_vendor_elements", + line); + return -1; + } + + tmp = wpabuf_alloc(len); + if (tmp) { + p = wpabuf_put(tmp, len); + + if (hexstr2bin(pos, p, len)) { + wpa_printf(MSG_ERROR, "Line %d: invalid " + "ap_vendor_elements", line); + wpabuf_free(tmp); + return -1; + } + + wpabuf_free(config->ap_vendor_elements); + config->ap_vendor_elements = tmp; + } else { + wpa_printf(MSG_ERROR, "Cannot allocate memory for " + "ap_vendor_elements"); + return -1; + } + + return 0; +} + + +#ifdef CONFIG_CTRL_IFACE +static int wpa_config_process_no_ctrl_interface( + const struct global_parse_data *data, + struct wpa_config *config, int line, const char *pos) +{ + wpa_printf(MSG_DEBUG, "no_ctrl_interface -> ctrl_interface=NULL"); + os_free(config->ctrl_interface); + config->ctrl_interface = NULL; + return 0; +} +#endif /* CONFIG_CTRL_IFACE */ + + +static int wpa_config_get_int(const char *name, struct wpa_config *config, + long offset, char *buf, size_t buflen, + int pretty_print) +{ + int *val = (int *) (((u8 *) config) + (long) offset); + + if (pretty_print) + return os_snprintf(buf, buflen, "%s=%d\n", name, *val); + return os_snprintf(buf, buflen, "%d", *val); +} + + +static int wpa_config_get_str(const char *name, struct wpa_config *config, + long offset, char *buf, size_t buflen, + int pretty_print) +{ + char **val = (char **) (((u8 *) config) + (long) offset); + int res; + + if (pretty_print) + res = os_snprintf(buf, buflen, "%s=%s\n", name, + *val ? *val : "null"); + else if (!*val) + return -1; + else + res = os_snprintf(buf, buflen, "%s", *val); + if (os_snprintf_error(buflen, res)) + res = -1; + + return res; +} + + +#ifdef CONFIG_P2P +static int wpa_config_get_ipv4(const char *name, struct wpa_config *config, + long offset, char *buf, size_t buflen, + int pretty_print) +{ + void *val = ((u8 *) config) + (long) offset; + int res; + char addr[INET_ADDRSTRLEN]; + + if (!val || !inet_ntop(AF_INET, val, addr, sizeof(addr))) + return -1; + + if (pretty_print) + res = os_snprintf(buf, buflen, "%s=%s\n", name, addr); + else + res = os_snprintf(buf, buflen, "%s", addr); + + if (os_snprintf_error(buflen, res)) + res = -1; + + return res; +} +#endif /* CONFIG_P2P */ + + +#ifdef OFFSET +#undef OFFSET +#endif /* OFFSET */ +/* OFFSET: Get offset of a variable within the wpa_config structure */ +#define OFFSET(v) ((void *) &((struct wpa_config *) 0)->v) + +#define FUNC(f) #f, wpa_config_process_ ## f, NULL, OFFSET(f), NULL, NULL +#define FUNC_NO_VAR(f) #f, wpa_config_process_ ## f, NULL, NULL, NULL, NULL +#define _INT(f) #f, wpa_global_config_parse_int, wpa_config_get_int, OFFSET(f) +#define INT(f) _INT(f), NULL, NULL +#define INT_RANGE(f, min, max) _INT(f), (void *) min, (void *) max +#define _STR(f) #f, wpa_global_config_parse_str, wpa_config_get_str, OFFSET(f) +#define STR(f) _STR(f), NULL, NULL +#define STR_RANGE(f, min, max) _STR(f), (void *) min, (void *) max +#define BIN(f) #f, wpa_global_config_parse_bin, NULL, OFFSET(f), NULL, NULL +#define IPV4(f) #f, wpa_global_config_parse_ipv4, wpa_config_get_ipv4, \ + OFFSET(f), NULL, NULL + +static const struct global_parse_data global_fields[] = { +#ifdef CONFIG_CTRL_IFACE + { STR(ctrl_interface), 0 }, + { FUNC_NO_VAR(no_ctrl_interface), 0 }, + { STR(ctrl_interface_group), 0 } /* deprecated */, +#endif /* CONFIG_CTRL_IFACE */ +#ifdef CONFIG_MACSEC + { INT_RANGE(eapol_version, 1, 3), 0 }, +#else /* CONFIG_MACSEC */ + { INT_RANGE(eapol_version, 1, 2), 0 }, +#endif /* CONFIG_MACSEC */ + { INT(ap_scan), 0 }, + { FUNC(bgscan), 0 }, +#ifdef CONFIG_MESH + { INT(user_mpm), 0 }, + { INT_RANGE(max_peer_links, 0, 255), 0 }, + { INT(mesh_max_inactivity), 0 }, + { INT(dot11RSNASAERetransPeriod), 0 }, +#endif /* CONFIG_MESH */ + { INT(disable_scan_offload), 0 }, + { INT(fast_reauth), 0 }, + { STR(opensc_engine_path), 0 }, + { STR(pkcs11_engine_path), 0 }, + { STR(pkcs11_module_path), 0 }, + { STR(openssl_ciphers), 0 }, + { STR(pcsc_reader), 0 }, + { STR(pcsc_pin), 0 }, + { INT(external_sim), 0 }, + { STR(driver_param), 0 }, + { INT(dot11RSNAConfigPMKLifetime), 0 }, + { INT(dot11RSNAConfigPMKReauthThreshold), 0 }, + { INT(dot11RSNAConfigSATimeout), 0 }, +#ifndef CONFIG_NO_CONFIG_WRITE + { INT(update_config), 0 }, +#endif /* CONFIG_NO_CONFIG_WRITE */ + { FUNC_NO_VAR(load_dynamic_eap), 0 }, +#ifdef CONFIG_WPS + { FUNC(uuid), CFG_CHANGED_UUID }, + { STR_RANGE(device_name, 0, WPS_DEV_NAME_MAX_LEN), + CFG_CHANGED_DEVICE_NAME }, + { STR_RANGE(manufacturer, 0, 64), CFG_CHANGED_WPS_STRING }, + { STR_RANGE(model_name, 0, 32), CFG_CHANGED_WPS_STRING }, + { STR_RANGE(model_number, 0, 32), CFG_CHANGED_WPS_STRING }, + { STR_RANGE(serial_number, 0, 32), CFG_CHANGED_WPS_STRING }, + { FUNC(device_type), CFG_CHANGED_DEVICE_TYPE }, + { FUNC(os_version), CFG_CHANGED_OS_VERSION }, + { STR(config_methods), CFG_CHANGED_CONFIG_METHODS }, + { INT_RANGE(wps_cred_processing, 0, 2), 0 }, + { FUNC(wps_vendor_ext_m1), CFG_CHANGED_VENDOR_EXTENSION }, +#endif /* CONFIG_WPS */ +#ifdef CONFIG_P2P + { FUNC(sec_device_type), CFG_CHANGED_SEC_DEVICE_TYPE }, + { INT(p2p_listen_reg_class), CFG_CHANGED_P2P_LISTEN_CHANNEL }, + { INT(p2p_listen_channel), CFG_CHANGED_P2P_LISTEN_CHANNEL }, + { INT(p2p_oper_reg_class), CFG_CHANGED_P2P_OPER_CHANNEL }, + { INT(p2p_oper_channel), CFG_CHANGED_P2P_OPER_CHANNEL }, + { INT_RANGE(p2p_go_intent, 0, 15), 0 }, + { STR(p2p_ssid_postfix), CFG_CHANGED_P2P_SSID_POSTFIX }, + { INT_RANGE(persistent_reconnect, 0, 1), 0 }, + { INT_RANGE(p2p_intra_bss, 0, 1), CFG_CHANGED_P2P_INTRA_BSS }, + { INT(p2p_group_idle), 0 }, + { INT_RANGE(p2p_go_freq_change_policy, 0, P2P_GO_FREQ_MOVE_MAX), 0 }, + { INT_RANGE(p2p_passphrase_len, 8, 63), + CFG_CHANGED_P2P_PASSPHRASE_LEN }, + { FUNC(p2p_pref_chan), CFG_CHANGED_P2P_PREF_CHAN }, + { FUNC(p2p_no_go_freq), CFG_CHANGED_P2P_PREF_CHAN }, + { INT_RANGE(p2p_add_cli_chan, 0, 1), 0 }, + { INT_RANGE(p2p_optimize_listen_chan, 0, 1), 0 }, + { INT(p2p_go_ht40), 0 }, + { INT(p2p_go_vht), 0 }, + { INT(p2p_disabled), 0 }, + { INT_RANGE(p2p_go_ctwindow, 0, 127), 0 }, + { INT(p2p_no_group_iface), 0 }, + { INT_RANGE(p2p_ignore_shared_freq, 0, 1), 0 }, + { IPV4(ip_addr_go), 0 }, + { IPV4(ip_addr_mask), 0 }, + { IPV4(ip_addr_start), 0 }, + { IPV4(ip_addr_end), 0 }, + { INT_RANGE(p2p_cli_probe, 0, 1), 0 }, +#endif /* CONFIG_P2P */ + { FUNC(country), CFG_CHANGED_COUNTRY }, + { INT(bss_max_count), 0 }, + { INT(bss_expiration_age), 0 }, + { INT(bss_expiration_scan_count), 0 }, + { INT_RANGE(filter_ssids, 0, 1), 0 }, + { INT_RANGE(filter_rssi, -100, 0), 0 }, + { INT(max_num_sta), 0 }, + { INT_RANGE(disassoc_low_ack, 0, 1), 0 }, +#ifdef CONFIG_HS20 + { INT_RANGE(hs20, 0, 1), 0 }, +#endif /* CONFIG_HS20 */ + { INT_RANGE(interworking, 0, 1), 0 }, + { FUNC(hessid), 0 }, + { INT_RANGE(access_network_type, 0, 15), 0 }, + { INT_RANGE(pbc_in_m1, 0, 1), 0 }, + { STR(autoscan), 0 }, + { INT_RANGE(wps_nfc_dev_pw_id, 0x10, 0xffff), + CFG_CHANGED_NFC_PASSWORD_TOKEN }, + { BIN(wps_nfc_dh_pubkey), CFG_CHANGED_NFC_PASSWORD_TOKEN }, + { BIN(wps_nfc_dh_privkey), CFG_CHANGED_NFC_PASSWORD_TOKEN }, + { BIN(wps_nfc_dev_pw), CFG_CHANGED_NFC_PASSWORD_TOKEN }, + { STR(ext_password_backend), CFG_CHANGED_EXT_PW_BACKEND }, + { INT(p2p_go_max_inactivity), 0 }, + { INT_RANGE(auto_interworking, 0, 1), 0 }, + { INT(okc), 0 }, + { INT(pmf), 0 }, + { FUNC(sae_groups), 0 }, + { INT(dtim_period), 0 }, + { INT(beacon_int), 0 }, + { FUNC(ap_vendor_elements), 0 }, + { INT_RANGE(ignore_old_scan_res, 0, 1), 0 }, + { FUNC(freq_list), 0 }, + { INT(scan_cur_freq), 0 }, + { INT(sched_scan_interval), 0 }, + { INT(tdls_external_control), 0}, + { STR(osu_dir), 0 }, + { STR(wowlan_triggers), 0 }, + { INT(p2p_search_delay), 0}, + { INT(mac_addr), 0 }, + { INT(rand_addr_lifetime), 0 }, + { INT(preassoc_mac_addr), 0 }, + { INT(key_mgmt_offload), 0}, + { INT(passive_scan), 0 }, + { INT(reassoc_same_bss_optim), 0 }, + { INT(wps_priority), 0}, +#ifdef CONFIG_FST + { STR_RANGE(fst_group_id, 1, FST_MAX_GROUP_ID_LEN), 0 }, + { INT_RANGE(fst_priority, 1, FST_MAX_PRIO_VALUE), 0 }, + { INT_RANGE(fst_llt, 1, FST_MAX_LLT_MS), 0 }, +#endif /* CONFIG_FST */ +}; + +#undef FUNC +#undef _INT +#undef INT +#undef INT_RANGE +#undef _STR +#undef STR +#undef STR_RANGE +#undef BIN +#undef IPV4 +#define NUM_GLOBAL_FIELDS ARRAY_SIZE(global_fields) + + +int wpa_config_dump_values(struct wpa_config *config, char *buf, size_t buflen) +{ + int result = 0; + size_t i; + + for (i = 0; i < NUM_GLOBAL_FIELDS; i++) { + const struct global_parse_data *field = &global_fields[i]; + int tmp; + + if (!field->get) + continue; + + tmp = field->get(field->name, config, (long) field->param1, + buf, buflen, 1); + if (tmp < 0) + return -1; + buf += tmp; + buflen -= tmp; + result += tmp; + } + return result; +} + + +int wpa_config_get_value(const char *name, struct wpa_config *config, + char *buf, size_t buflen) +{ + size_t i; + + for (i = 0; i < NUM_GLOBAL_FIELDS; i++) { + const struct global_parse_data *field = &global_fields[i]; + + if (os_strcmp(name, field->name) != 0) + continue; + if (!field->get) + break; + return field->get(name, config, (long) field->param1, + buf, buflen, 0); + } + + return -1; +} + + +int wpa_config_process_global(struct wpa_config *config, char *pos, int line) +{ + size_t i; + int ret = 0; + + for (i = 0; i < NUM_GLOBAL_FIELDS; i++) { + const struct global_parse_data *field = &global_fields[i]; + size_t flen = os_strlen(field->name); + if (os_strncmp(pos, field->name, flen) != 0 || + pos[flen] != '=') + continue; + + if (field->parser(field, config, line, pos + flen + 1)) { + wpa_printf(MSG_ERROR, "Line %d: failed to " + "parse '%s'.", line, pos); + ret = -1; + } + if (field->changed_flag == CFG_CHANGED_NFC_PASSWORD_TOKEN) + config->wps_nfc_pw_from_config = 1; + config->changed_parameters |= field->changed_flag; + break; + } + if (i == NUM_GLOBAL_FIELDS) { +#ifdef CONFIG_AP + if (os_strncmp(pos, "wmm_ac_", 7) == 0) { + char *tmp = os_strchr(pos, '='); + if (tmp == NULL) { + if (line < 0) + return -1; + wpa_printf(MSG_ERROR, "Line %d: invalid line " + "'%s'", line, pos); + return -1; + } + *tmp++ = '\0'; + if (hostapd_config_wmm_ac(config->wmm_ac_params, pos, + tmp)) { + wpa_printf(MSG_ERROR, "Line %d: invalid WMM " + "AC item", line); + return -1; + } + } +#endif /* CONFIG_AP */ + if (line < 0) + return -1; + wpa_printf(MSG_ERROR, "Line %d: unknown global field '%s'.", + line, pos); + ret = -1; + } + + return ret; +} diff --git a/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/config.h b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/config.h new file mode 100755 index 0000000..b661145 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/config.h @@ -0,0 +1,1345 @@ +/* + * WPA Supplicant / Configuration file structures + * Copyright (c) 2003-2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef CONFIG_H +#define CONFIG_H + +#define DEFAULT_EAPOL_VERSION 1 +#ifdef CONFIG_NO_SCAN_PROCESSING +#define DEFAULT_AP_SCAN 2 +#else /* CONFIG_NO_SCAN_PROCESSING */ +#define DEFAULT_AP_SCAN 1 +#endif /* CONFIG_NO_SCAN_PROCESSING */ +#define DEFAULT_USER_MPM 1 +#define DEFAULT_MAX_PEER_LINKS 99 +#define DEFAULT_MESH_MAX_INACTIVITY 300 +/* + * The default dot11RSNASAERetransPeriod is defined as 40 ms in the standard, + * but use 1000 ms in practice to avoid issues on low power CPUs. + */ +#define DEFAULT_DOT11_RSNA_SAE_RETRANS_PERIOD 1000 +#define DEFAULT_FAST_REAUTH 1 +#define DEFAULT_P2P_GO_INTENT 7 +#define DEFAULT_P2P_INTRA_BSS 1 +#define DEFAULT_P2P_GO_MAX_INACTIVITY (5 * 60) +#define DEFAULT_P2P_OPTIMIZE_LISTEN_CHAN 0 +#define DEFAULT_BSS_MAX_COUNT 200 +#define DEFAULT_BSS_EXPIRATION_AGE 180 +#define DEFAULT_BSS_EXPIRATION_SCAN_COUNT 2 +#define DEFAULT_MAX_NUM_STA 128 +#define DEFAULT_ACCESS_NETWORK_TYPE 15 +#define DEFAULT_SCAN_CUR_FREQ 0 +#define DEFAULT_P2P_SEARCH_DELAY 500 +#define DEFAULT_RAND_ADDR_LIFETIME 60 +#define DEFAULT_KEY_MGMT_OFFLOAD 1 +#define DEFAULT_CERT_IN_CB 1 +#define DEFAULT_P2P_GO_CTWINDOW 0 + +#include "config_ssid.h" +#include "wps/wps.h" +#include "common/ieee802_11_defs.h" +#include "common/ieee802_11_common.h" + + +struct wpa_cred { + /** + * next - Next credential in the list + * + * This pointer can be used to iterate over all credentials. The head + * of this list is stored in the cred field of struct wpa_config. + */ + struct wpa_cred *next; + + /** + * id - Unique id for the credential + * + * This identifier is used as a unique identifier for each credential + * block when using the control interface. Each credential is allocated + * an id when it is being created, either when reading the + * configuration file or when a new credential is added through the + * control interface. + */ + int id; + + /** + * temporary - Whether this credential is temporary and not to be saved + */ + int temporary; + + /** + * priority - Priority group + * + * By default, all networks and credentials get the same priority group + * (0). This field can be used to give higher priority for credentials + * (and similarly in struct wpa_ssid for network blocks) to change the + * Interworking automatic networking selection behavior. The matching + * network (based on either an enabled network block or a credential) + * with the highest priority value will be selected. + */ + int priority; + + /** + * pcsc - Use PC/SC and SIM/USIM card + */ + int pcsc; + + /** + * realm - Home Realm for Interworking + */ + char *realm; + + /** + * username - Username for Interworking network selection + */ + char *username; + + /** + * password - Password for Interworking network selection + */ + char *password; + + /** + * ext_password - Whether password is a name for external storage + */ + int ext_password; + + /** + * ca_cert - CA certificate for Interworking network selection + */ + char *ca_cert; + + /** + * client_cert - File path to client certificate file (PEM/DER) + * + * This field is used with Interworking networking selection for a case + * where client certificate/private key is used for authentication + * (EAP-TLS). Full path to the file should be used since working + * directory may change when wpa_supplicant is run in the background. + * + * Alternatively, a named configuration blob can be used by setting + * this to blob://blob_name. + */ + char *client_cert; + + /** + * private_key - File path to client private key file (PEM/DER/PFX) + * + * When PKCS#12/PFX file (.p12/.pfx) is used, client_cert should be + * commented out. Both the private key and certificate will be read + * from the PKCS#12 file in this case. Full path to the file should be + * used since working directory may change when wpa_supplicant is run + * in the background. + * + * Windows certificate store can be used by leaving client_cert out and + * configuring private_key in one of the following formats: + * + * cert://substring_to_match + * + * hash://certificate_thumbprint_in_hex + * + * For example: private_key="hash://63093aa9c47f56ae88334c7b65a4" + * + * Note that when running wpa_supplicant as an application, the user + * certificate store (My user account) is used, whereas computer store + * (Computer account) is used when running wpasvc as a service. + * + * Alternatively, a named configuration blob can be used by setting + * this to blob://blob_name. + */ + char *private_key; + + /** + * private_key_passwd - Password for private key file + */ + char *private_key_passwd; + + /** + * imsi - IMSI in | | '-' | format + */ + char *imsi; + + /** + * milenage - Milenage parameters for SIM/USIM simulator in + * :: format + */ + char *milenage; + + /** + * domain_suffix_match - Constraint for server domain name + * + * If set, this FQDN is used as a suffix match requirement for the AAA + * server certificate in SubjectAltName dNSName element(s). If a + * matching dNSName is found, this constraint is met. If no dNSName + * values are present, this constraint is matched against SubjectName CN + * using same suffix match comparison. Suffix match here means that the + * host/domain name is compared one label at a time starting from the + * top-level domain and all the labels in @domain_suffix_match shall be + * included in the certificate. The certificate may include additional + * sub-level labels in addition to the required labels. + * + * For example, domain_suffix_match=example.com would match + * test.example.com but would not match test-example.com. + */ + char *domain_suffix_match; + + /** + * domain - Home service provider FQDN(s) + * + * This is used to compare against the Domain Name List to figure out + * whether the AP is operated by the Home SP. Multiple domain entries + * can be used to configure alternative FQDNs that will be considered + * home networks. + */ + char **domain; + + /** + * num_domain - Number of FQDNs in the domain array + */ + size_t num_domain; + + /** + * roaming_consortium - Roaming Consortium OI + * + * If roaming_consortium_len is non-zero, this field contains the + * Roaming Consortium OI that can be used to determine which access + * points support authentication with this credential. This is an + * alternative to the use of the realm parameter. When using Roaming + * Consortium to match the network, the EAP parameters need to be + * pre-configured with the credential since the NAI Realm information + * may not be available or fetched. + */ + u8 roaming_consortium[15]; + + /** + * roaming_consortium_len - Length of roaming_consortium + */ + size_t roaming_consortium_len; + + u8 required_roaming_consortium[15]; + size_t required_roaming_consortium_len; + + /** + * eap_method - EAP method to use + * + * Pre-configured EAP method to use with this credential or %NULL to + * indicate no EAP method is selected, i.e., the method will be + * selected automatically based on ANQP information. + */ + struct eap_method_type *eap_method; + + /** + * phase1 - Phase 1 (outer authentication) parameters + * + * Pre-configured EAP parameters or %NULL. + */ + char *phase1; + + /** + * phase2 - Phase 2 (inner authentication) parameters + * + * Pre-configured EAP parameters or %NULL. + */ + char *phase2; + + struct excluded_ssid { + u8 ssid[SSID_MAX_LEN]; + size_t ssid_len; + } *excluded_ssid; + size_t num_excluded_ssid; + + struct roaming_partner { + char fqdn[128]; + int exact_match; + u8 priority; + char country[3]; + } *roaming_partner; + size_t num_roaming_partner; + + int update_identifier; + + /** + * provisioning_sp - FQDN of the SP that provisioned the credential + */ + char *provisioning_sp; + + /** + * sp_priority - Credential priority within a provisioning SP + * + * This is the priority of the credential among all credentials + * provisionined by the same SP (i.e., for entries that have identical + * provisioning_sp value). The range of this priority is 0-255 with 0 + * being the highest and 255 the lower priority. + */ + int sp_priority; + + unsigned int min_dl_bandwidth_home; + unsigned int min_ul_bandwidth_home; + unsigned int min_dl_bandwidth_roaming; + unsigned int min_ul_bandwidth_roaming; + + /** + * max_bss_load - Maximum BSS Load Channel Utilization (1..255) + * This value is used as the maximum channel utilization for network + * selection purposes for home networks. If the AP does not advertise + * BSS Load or if the limit would prevent any connection, this + * constraint will be ignored. + */ + unsigned int max_bss_load; + + unsigned int num_req_conn_capab; + u8 *req_conn_capab_proto; + int **req_conn_capab_port; + + /** + * ocsp - Whether to use/require OCSP to check server certificate + * + * 0 = do not use OCSP stapling (TLS certificate status extension) + * 1 = try to use OCSP stapling, but not require response + * 2 = require valid OCSP stapling response + */ + int ocsp; + + /** + * sim_num - User selected SIM identifier + * + * This variable is used for identifying which SIM is used if the system + * has more than one. + */ + int sim_num; +}; + + +#define CFG_CHANGED_DEVICE_NAME BIT(0) +#define CFG_CHANGED_CONFIG_METHODS BIT(1) +#define CFG_CHANGED_DEVICE_TYPE BIT(2) +#define CFG_CHANGED_OS_VERSION BIT(3) +#define CFG_CHANGED_UUID BIT(4) +#define CFG_CHANGED_COUNTRY BIT(5) +#define CFG_CHANGED_SEC_DEVICE_TYPE BIT(6) +#define CFG_CHANGED_P2P_SSID_POSTFIX BIT(7) +#define CFG_CHANGED_WPS_STRING BIT(8) +#define CFG_CHANGED_P2P_INTRA_BSS BIT(9) +#define CFG_CHANGED_VENDOR_EXTENSION BIT(10) +#define CFG_CHANGED_P2P_LISTEN_CHANNEL BIT(11) +#define CFG_CHANGED_P2P_OPER_CHANNEL BIT(12) +#define CFG_CHANGED_P2P_PREF_CHAN BIT(13) +#define CFG_CHANGED_EXT_PW_BACKEND BIT(14) +#define CFG_CHANGED_NFC_PASSWORD_TOKEN BIT(15) +#define CFG_CHANGED_P2P_PASSPHRASE_LEN BIT(16) + +/** + * struct wpa_config - wpa_supplicant configuration data + * + * This data structure is presents the per-interface (radio) configuration + * data. In many cases, there is only one struct wpa_config instance, but if + * more than one network interface is being controlled, one instance is used + * for each. + */ +struct wpa_config { + /** + * ssid - Head of the global network list + * + * This is the head for the list of all the configured networks. + */ + struct wpa_ssid *ssid; + + /** + * pssid - Per-priority network lists (in priority order) + */ + struct wpa_ssid **pssid; + + /** + * num_prio - Number of different priorities used in the pssid lists + * + * This indicates how many per-priority network lists are included in + * pssid. + */ + int num_prio; + + /** + * cred - Head of the credential list + * + * This is the head for the list of all the configured credentials. + */ + struct wpa_cred *cred; + + /** + * eapol_version - IEEE 802.1X/EAPOL version number + * + * wpa_supplicant is implemented based on IEEE Std 802.1X-2004 which + * defines EAPOL version 2. However, there are many APs that do not + * handle the new version number correctly (they seem to drop the + * frames completely). In order to make wpa_supplicant interoperate + * with these APs, the version number is set to 1 by default. This + * configuration value can be used to set it to the new version (2). + */ + int eapol_version; + + /** + * ap_scan - AP scanning/selection + * + * By default, wpa_supplicant requests driver to perform AP + * scanning and then uses the scan results to select a + * suitable AP. Another alternative is to allow the driver to + * take care of AP scanning and selection and use + * wpa_supplicant just to process EAPOL frames based on IEEE + * 802.11 association information from the driver. + * + * 1: wpa_supplicant initiates scanning and AP selection (default). + * + * 0: Driver takes care of scanning, AP selection, and IEEE 802.11 + * association parameters (e.g., WPA IE generation); this mode can + * also be used with non-WPA drivers when using IEEE 802.1X mode; + * do not try to associate with APs (i.e., external program needs + * to control association). This mode must also be used when using + * wired Ethernet drivers. + * + * 2: like 0, but associate with APs using security policy and SSID + * (but not BSSID); this can be used, e.g., with ndiswrapper and NDIS + * drivers to enable operation with hidden SSIDs and optimized roaming; + * in this mode, the network blocks in the configuration are tried + * one by one until the driver reports successful association; each + * network block should have explicit security policy (i.e., only one + * option in the lists) for key_mgmt, pairwise, group, proto variables. + * + * Note: ap_scan=2 should not be used with the nl80211 driver interface + * (the current Linux interface). ap_scan=1 is optimized work working + * with nl80211. For finding networks using hidden SSID, scan_ssid=1 in + * the network block can be used with nl80211. + */ + int ap_scan; + + /** + * bgscan - Background scan and roaming parameters or %NULL if none + * + * This is an optional set of parameters for background scanning and + * roaming within a network (ESS). For more detailed information see + * ssid block documentation. + * + * The variable defines default bgscan behavior for all BSS station + * networks except for those which have their own bgscan configuration. + */ + char *bgscan; + + /** + * disable_scan_offload - Disable automatic offloading of scan requests + * + * By default, %wpa_supplicant tries to offload scanning if the driver + * indicates support for this (sched_scan). This configuration + * parameter can be used to disable this offloading mechanism. + */ + int disable_scan_offload; + + /** + * ctrl_interface - Parameters for the control interface + * + * If this is specified, %wpa_supplicant will open a control interface + * that is available for external programs to manage %wpa_supplicant. + * The meaning of this string depends on which control interface + * mechanism is used. For all cases, the existence of this parameter + * in configuration is used to determine whether the control interface + * is enabled. + * + * For UNIX domain sockets (default on Linux and BSD): This is a + * directory that will be created for UNIX domain sockets for listening + * to requests from external programs (CLI/GUI, etc.) for status + * information and configuration. The socket file will be named based + * on the interface name, so multiple %wpa_supplicant processes can be + * run at the same time if more than one interface is used. + * /var/run/wpa_supplicant is the recommended directory for sockets and + * by default, wpa_cli will use it when trying to connect with + * %wpa_supplicant. + * + * Access control for the control interface can be configured + * by setting the directory to allow only members of a group + * to use sockets. This way, it is possible to run + * %wpa_supplicant as root (since it needs to change network + * configuration and open raw sockets) and still allow GUI/CLI + * components to be run as non-root users. However, since the + * control interface can be used to change the network + * configuration, this access needs to be protected in many + * cases. By default, %wpa_supplicant is configured to use gid + * 0 (root). If you want to allow non-root users to use the + * control interface, add a new group and change this value to + * match with that group. Add users that should have control + * interface access to this group. + * + * When configuring both the directory and group, use following format: + * DIR=/var/run/wpa_supplicant GROUP=wheel + * DIR=/var/run/wpa_supplicant GROUP=0 + * (group can be either group name or gid) + * + * For UDP connections (default on Windows): The value will be ignored. + * This variable is just used to select that the control interface is + * to be created. The value can be set to, e.g., udp + * (ctrl_interface=udp). + * + * For Windows Named Pipe: This value can be used to set the security + * descriptor for controlling access to the control interface. Security + * descriptor can be set using Security Descriptor String Format (see + * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/secauthz/security/security_descriptor_string_format.asp). + * The descriptor string needs to be prefixed with SDDL=. For example, + * ctrl_interface=SDDL=D: would set an empty DACL (which will reject + * all connections). + */ + char *ctrl_interface; + + /** + * ctrl_interface_group - Control interface group (DEPRECATED) + * + * This variable is only used for backwards compatibility. Group for + * UNIX domain sockets should now be specified using GROUP=group in + * ctrl_interface variable. + */ + char *ctrl_interface_group; + + /** + * fast_reauth - EAP fast re-authentication (session resumption) + * + * By default, fast re-authentication is enabled for all EAP methods + * that support it. This variable can be used to disable fast + * re-authentication (by setting fast_reauth=0). Normally, there is no + * need to disable fast re-authentication. + */ + int fast_reauth; + + /** + * opensc_engine_path - Path to the OpenSSL engine for opensc + * + * This is an OpenSSL specific configuration option for loading OpenSC + * engine (engine_opensc.so); if %NULL, this engine is not loaded. + */ + char *opensc_engine_path; + + /** + * pkcs11_engine_path - Path to the OpenSSL engine for PKCS#11 + * + * This is an OpenSSL specific configuration option for loading PKCS#11 + * engine (engine_pkcs11.so); if %NULL, this engine is not loaded. + */ + char *pkcs11_engine_path; + + /** + * pkcs11_module_path - Path to the OpenSSL OpenSC/PKCS#11 module + * + * This is an OpenSSL specific configuration option for configuring + * path to OpenSC/PKCS#11 engine (opensc-pkcs11.so); if %NULL, this + * module is not loaded. + */ + char *pkcs11_module_path; + + /** + * openssl_ciphers - OpenSSL cipher string + * + * This is an OpenSSL specific configuration option for configuring the + * default ciphers. If not set, "DEFAULT:!EXP:!LOW" is used as the + * default. + */ + char *openssl_ciphers; + + /** + * pcsc_reader - PC/SC reader name prefix + * + * If not %NULL, PC/SC reader with a name that matches this prefix is + * initialized for SIM/USIM access. Empty string can be used to match + * the first available reader. + */ + char *pcsc_reader; + + /** + * pcsc_pin - PIN for USIM, GSM SIM, and smartcards + * + * This field is used to configure PIN for SIM/USIM for EAP-SIM and + * EAP-AKA. If left out, this will be asked through control interface. + */ + char *pcsc_pin; + + /** + * external_sim - Use external processing for SIM/USIM operations + */ + int external_sim; + + /** + * driver_param - Driver interface parameters + * + * This text string is passed to the selected driver interface with the + * optional struct wpa_driver_ops::set_param() handler. This can be + * used to configure driver specific options without having to add new + * driver interface functionality. + */ + char *driver_param; + + /** + * dot11RSNAConfigPMKLifetime - Maximum lifetime of a PMK + * + * dot11 MIB variable for the maximum lifetime of a PMK in the PMK + * cache (unit: seconds). + */ + unsigned int dot11RSNAConfigPMKLifetime; + + /** + * dot11RSNAConfigPMKReauthThreshold - PMK re-authentication threshold + * + * dot11 MIB variable for the percentage of the PMK lifetime + * that should expire before an IEEE 802.1X reauthentication occurs. + */ + unsigned int dot11RSNAConfigPMKReauthThreshold; + + /** + * dot11RSNAConfigSATimeout - Security association timeout + * + * dot11 MIB variable for the maximum time a security association + * shall take to set up (unit: seconds). + */ + unsigned int dot11RSNAConfigSATimeout; + + /** + * update_config - Is wpa_supplicant allowed to update configuration + * + * This variable control whether wpa_supplicant is allow to re-write + * its configuration with wpa_config_write(). If this is zero, + * configuration data is only changed in memory and the external data + * is not overriden. If this is non-zero, wpa_supplicant will update + * the configuration data (e.g., a file) whenever configuration is + * changed. This update may replace the old configuration which can + * remove comments from it in case of a text file configuration. + */ + int update_config; + + /** + * blobs - Configuration blobs + */ + struct wpa_config_blob *blobs; + + /** + * uuid - Universally Unique IDentifier (UUID; see RFC 4122) for WPS + */ + u8 uuid[16]; + + /** + * device_name - Device Name (WPS) + * User-friendly description of device; up to 32 octets encoded in + * UTF-8 + */ + char *device_name; + + /** + * manufacturer - Manufacturer (WPS) + * The manufacturer of the device (up to 64 ASCII characters) + */ + char *manufacturer; + + /** + * model_name - Model Name (WPS) + * Model of the device (up to 32 ASCII characters) + */ + char *model_name; + + /** + * model_number - Model Number (WPS) + * Additional device description (up to 32 ASCII characters) + */ + char *model_number; + + /** + * serial_number - Serial Number (WPS) + * Serial number of the device (up to 32 characters) + */ + char *serial_number; + + /** + * device_type - Primary Device Type (WPS) + */ + u8 device_type[WPS_DEV_TYPE_LEN]; + + /** + * config_methods - Config Methods + * + * This is a space-separated list of supported WPS configuration + * methods. For example, "label virtual_display virtual_push_button + * keypad". + * Available methods: usba ethernet label display ext_nfc_token + * int_nfc_token nfc_interface push_button keypad + * virtual_display physical_display + * virtual_push_button physical_push_button. + */ + char *config_methods; + + /** + * os_version - OS Version (WPS) + * 4-octet operating system version number + */ + u8 os_version[4]; + + /** + * country - Country code + * + * This is the ISO/IEC alpha2 country code for which we are operating + * in + */ + char country[2]; + + /** + * wps_cred_processing - Credential processing + * + * 0 = process received credentials internally + * 1 = do not process received credentials; just pass them over + * ctrl_iface to external program(s) + * 2 = process received credentials internally and pass them over + * ctrl_iface to external program(s) + */ + int wps_cred_processing; + +#define MAX_SEC_DEVICE_TYPES 5 + /** + * sec_device_types - Secondary Device Types (P2P) + */ + u8 sec_device_type[MAX_SEC_DEVICE_TYPES][WPS_DEV_TYPE_LEN]; + int num_sec_device_types; + + int p2p_listen_reg_class; + int p2p_listen_channel; + int p2p_oper_reg_class; + int p2p_oper_channel; + int p2p_go_intent; + char *p2p_ssid_postfix; + int persistent_reconnect; + int p2p_intra_bss; + unsigned int num_p2p_pref_chan; + struct p2p_channel *p2p_pref_chan; + struct wpa_freq_range_list p2p_no_go_freq; + int p2p_add_cli_chan; + int p2p_ignore_shared_freq; + int p2p_optimize_listen_chan; + + struct wpabuf *wps_vendor_ext_m1; + +#define MAX_WPS_VENDOR_EXT 10 + /** + * wps_vendor_ext - Vendor extension attributes in WPS + */ + struct wpabuf *wps_vendor_ext[MAX_WPS_VENDOR_EXT]; + + /** + * p2p_group_idle - Maximum idle time in seconds for P2P group + * + * This value controls how long a P2P group is maintained after there + * is no other members in the group. As a GO, this means no associated + * stations in the group. As a P2P client, this means no GO seen in + * scan results. The maximum idle time is specified in seconds with 0 + * indicating no time limit, i.e., the P2P group remains in active + * state indefinitely until explicitly removed. As a P2P client, the + * maximum idle time of P2P_MAX_CLIENT_IDLE seconds is enforced, i.e., + * this parameter is mainly meant for GO use and for P2P client, it can + * only be used to reduce the default timeout to smaller value. A + * special value -1 can be used to configure immediate removal of the + * group for P2P client role on any disconnection after the data + * connection has been established. + */ + int p2p_group_idle; + + /** + * p2p_go_freq_change_policy - The GO frequency change policy + * + * This controls the behavior of the GO when there is a change in the + * map of the currently used frequencies in case more than one channel + * is supported. + * + * @P2P_GO_FREQ_MOVE_SCM: Prefer working in a single channel mode if + * possible. In case the GO is the only interface using its frequency + * and there are other station interfaces on other frequencies, the GO + * will migrate to one of these frequencies. + * + * @P2P_GO_FREQ_MOVE_SCM_PEER_SUPPORTS: Same as P2P_GO_FREQ_MOVE_SCM, + * but a transition is possible only in case one of the other used + * frequencies is one of the frequencies in the intersection of the + * frequency list of the local device and the peer device. + * + * @P2P_GO_FREQ_MOVE_STAY: Prefer to stay on the current frequency. + */ + enum { + P2P_GO_FREQ_MOVE_SCM = 0, + P2P_GO_FREQ_MOVE_SCM_PEER_SUPPORTS = 1, + P2P_GO_FREQ_MOVE_STAY = 2, + P2P_GO_FREQ_MOVE_MAX = P2P_GO_FREQ_MOVE_STAY, + } p2p_go_freq_change_policy; + +#define DEFAULT_P2P_GO_FREQ_MOVE P2P_GO_FREQ_MOVE_STAY + + /** + * p2p_passphrase_len - Passphrase length (8..63) for P2P GO + * + * This parameter controls the length of the random passphrase that is + * generated at the GO. + */ + unsigned int p2p_passphrase_len; + + /** + * bss_max_count - Maximum number of BSS entries to keep in memory + */ + unsigned int bss_max_count; + + /** + * bss_expiration_age - BSS entry age after which it can be expired + * + * This value controls the time in seconds after which a BSS entry + * gets removed if it has not been updated or is not in use. + */ + unsigned int bss_expiration_age; + + /** + * bss_expiration_scan_count - Expire BSS after number of scans + * + * If the BSS entry has not been seen in this many scans, it will be + * removed. A value of 1 means that entry is removed after the first + * scan in which the BSSID is not seen. Larger values can be used + * to avoid BSS entries disappearing if they are not visible in + * every scan (e.g., low signal quality or interference). + */ + unsigned int bss_expiration_scan_count; + + /** + * filter_ssids - SSID-based scan result filtering + * + * 0 = do not filter scan results + * 1 = only include configured SSIDs in scan results/BSS table + */ + int filter_ssids; + + /** + * filter_rssi - RSSI-based scan result filtering + * + * 0 = do not filter scan results + * -n = filter scan results below -n dBm + */ + int filter_rssi; + + /** + * max_num_sta - Maximum number of STAs in an AP/P2P GO + */ + unsigned int max_num_sta; + + /** + * freq_list - Array of allowed scan frequencies or %NULL for all + * + * This is an optional zero-terminated array of frequencies in + * megahertz (MHz) to allow for narrowing scanning range. + */ + int *freq_list; + + /** + * scan_cur_freq - Whether to scan only the current channel + * + * If true, attempt to scan only the current channel if any other + * VIFs on this radio are already associated on a particular channel. + */ + int scan_cur_freq; + + /** + * changed_parameters - Bitmap of changed parameters since last update + */ + unsigned int changed_parameters; + + /** + * disassoc_low_ack - Disassocicate stations with massive packet loss + */ + int disassoc_low_ack; + + /** + * interworking - Whether Interworking (IEEE 802.11u) is enabled + */ + int interworking; + + /** + * access_network_type - Access Network Type + * + * When Interworking is enabled, scans will be limited to APs that + * advertise the specified Access Network Type (0..15; with 15 + * indicating wildcard match). + */ + int access_network_type; + + /** + * hessid - Homogenous ESS identifier + * + * If this is set (any octet is non-zero), scans will be used to + * request response only from BSSes belonging to the specified + * Homogeneous ESS. This is used only if interworking is enabled. + */ + u8 hessid[ETH_ALEN]; + + /** + * hs20 - Hotspot 2.0 + */ + int hs20; + + /** + * pbc_in_m1 - AP mode WPS probing workaround for PBC with Windows 7 + * + * Windows 7 uses incorrect way of figuring out AP's WPS capabilities + * by acting as a Registrar and using M1 from the AP. The config + * methods attribute in that message is supposed to indicate only the + * configuration method supported by the AP in Enrollee role, i.e., to + * add an external Registrar. For that case, PBC shall not be used and + * as such, the PushButton config method is removed from M1 by default. + * If pbc_in_m1=1 is included in the configuration file, the PushButton + * config method is left in M1 (if included in config_methods + * parameter) to allow Windows 7 to use PBC instead of PIN (e.g., from + * a label in the AP). + */ + int pbc_in_m1; + + /** + * autoscan - Automatic scan parameters or %NULL if none + * + * This is an optional set of parameters for automatic scanning + * within an interface in following format: + * : + */ + char *autoscan; + + /** + * wps_nfc_pw_from_config - NFC Device Password was read from config + * + * This parameter can be determined whether the NFC Device Password was + * included in the configuration (1) or generated dynamically (0). Only + * the former case is re-written back to the configuration file. + */ + int wps_nfc_pw_from_config; + + /** + * wps_nfc_dev_pw_id - NFC Device Password ID for password token + */ + int wps_nfc_dev_pw_id; + + /** + * wps_nfc_dh_pubkey - NFC DH Public Key for password token + */ + struct wpabuf *wps_nfc_dh_pubkey; + + /** + * wps_nfc_dh_privkey - NFC DH Private Key for password token + */ + struct wpabuf *wps_nfc_dh_privkey; + + /** + * wps_nfc_dev_pw - NFC Device Password for password token + */ + struct wpabuf *wps_nfc_dev_pw; + + /** + * ext_password_backend - External password backend or %NULL if none + * + * format: [:] + */ + char *ext_password_backend; + + /* + * p2p_go_max_inactivity - Timeout in seconds to detect STA inactivity + * + * This timeout value is used in P2P GO mode to clean up + * inactive stations. + * By default: 300 seconds. + */ + int p2p_go_max_inactivity; + + struct hostapd_wmm_ac_params wmm_ac_params[4]; + + /** + * auto_interworking - Whether to use network selection automatically + * + * 0 = do not automatically go through Interworking network selection + * (i.e., require explicit interworking_select command for this) + * 1 = perform Interworking network selection if one or more + * credentials have been configured and scan did not find a + * matching network block + */ + int auto_interworking; + + /** + * p2p_go_ht40 - Default mode for HT40 enable when operating as GO. + * + * This will take effect for p2p_group_add, p2p_connect, and p2p_invite. + * Note that regulatory constraints and driver capabilities are + * consulted anyway, so setting it to 1 can't do real harm. + * By default: 0 (disabled) + */ + int p2p_go_ht40; + + /** + * p2p_go_vht - Default mode for VHT enable when operating as GO + * + * This will take effect for p2p_group_add, p2p_connect, and p2p_invite. + * Note that regulatory constraints and driver capabilities are + * consulted anyway, so setting it to 1 can't do real harm. + * By default: 0 (disabled) + */ + int p2p_go_vht; + + /** + * p2p_go_ctwindow - CTWindow to use when operating as GO + * + * By default: 0 (no CTWindow). Values 0-127 can be used to indicate + * the length of the CTWindow in TUs. + */ + int p2p_go_ctwindow; + + /** + * p2p_disabled - Whether P2P operations are disabled for this interface + */ + int p2p_disabled; + + /** + * p2p_no_group_iface - Whether group interfaces can be used + * + * By default, wpa_supplicant will create a separate interface for P2P + * group operations if the driver supports this. This functionality can + * be disabled by setting this parameter to 1. In that case, the same + * interface that was used for the P2P management operations is used + * also for the group operation. + */ + int p2p_no_group_iface; + + /** + * p2p_cli_probe - Enable/disable P2P CLI probe request handling + * + * If this parameter is set to 1, a connected P2P Client will receive + * and handle Probe Request frames. Setting this parameter to 0 + * disables this option. Default value: 0. + * + * Note: Setting this property at run time takes effect on the following + * interface state transition to/from the WPA_COMPLETED state. + */ + int p2p_cli_probe; + + /** + * okc - Whether to enable opportunistic key caching by default + * + * By default, OKC is disabled unless enabled by the per-network + * proactive_key_caching=1 parameter. okc=1 can be used to change this + * default behavior. + */ + int okc; + + /** + * pmf - Whether to enable/require PMF by default + * + * By default, PMF is disabled unless enabled by the per-network + * ieee80211w=1 or ieee80211w=2 parameter. pmf=1/2 can be used to change + * this default behavior. + */ + enum mfp_options pmf; + + /** + * sae_groups - Preference list of enabled groups for SAE + * + * By default (if this parameter is not set), the mandatory group 19 + * (ECC group defined over a 256-bit prime order field) is preferred, + * but other groups are also enabled. If this parameter is set, the + * groups will be tried in the indicated order. + */ + int *sae_groups; + + /** + * dtim_period - Default DTIM period in Beacon intervals + * + * This parameter can be used to set the default value for network + * blocks that do not specify dtim_period. + */ + int dtim_period; + + /** + * beacon_int - Default Beacon interval in TU + * + * This parameter can be used to set the default value for network + * blocks that do not specify beacon_int. + */ + int beacon_int; + + /** + * ap_vendor_elements: Vendor specific elements for Beacon/ProbeResp + * + * This parameter can be used to define additional vendor specific + * elements for Beacon and Probe Response frames in AP/P2P GO mode. The + * format for these element(s) is a hexdump of the raw information + * elements (id+len+payload for one or more elements). + */ + struct wpabuf *ap_vendor_elements; + + /** + * ignore_old_scan_res - Ignore scan results older than request + * + * The driver may have a cache of scan results that makes it return + * information that is older than our scan trigger. This parameter can + * be used to configure such old information to be ignored instead of + * allowing it to update the internal BSS table. + */ + int ignore_old_scan_res; + + /** + * sched_scan_interval - schedule scan interval + */ + unsigned int sched_scan_interval; + + /** + * tdls_external_control - External control for TDLS setup requests + * + * Enable TDLS mode where external programs are given the control + * to specify the TDLS link to get established to the driver. The + * driver requests the TDLS setup to the supplicant only for the + * specified TDLS peers. + */ + int tdls_external_control; + + u8 ip_addr_go[4]; + u8 ip_addr_mask[4]; + u8 ip_addr_start[4]; + u8 ip_addr_end[4]; + + /** + * osu_dir - OSU provider information directory + * + * If set, allow FETCH_OSU control interface command to be used to fetch + * OSU provider information into all APs and store the results in this + * directory. + */ + char *osu_dir; + + /** + * wowlan_triggers - Wake-on-WLAN triggers + * + * If set, these wowlan triggers will be configured. + */ + char *wowlan_triggers; + + /** + * p2p_search_delay - Extra delay between concurrent search iterations + * + * Add extra delay (in milliseconds) between search iterations when + * there is a concurrent operation to make p2p_find friendlier to + * concurrent operations by avoiding it from taking 100% of radio + * resources. + */ + unsigned int p2p_search_delay; + + /** + * mac_addr - MAC address policy default + * + * 0 = use permanent MAC address + * 1 = use random MAC address for each ESS connection + * 2 = like 1, but maintain OUI (with local admin bit set) + * + * By default, permanent MAC address is used unless policy is changed by + * the per-network mac_addr parameter. Global mac_addr=1 can be used to + * change this default behavior. + */ + int mac_addr; + + /** + * rand_addr_lifetime - Lifetime of random MAC address in seconds + */ + unsigned int rand_addr_lifetime; + + /** + * preassoc_mac_addr - Pre-association MAC address policy + * + * 0 = use permanent MAC address + * 1 = use random MAC address + * 2 = like 1, but maintain OUI (with local admin bit set) + */ + int preassoc_mac_addr; + + /** + * key_mgmt_offload - Use key management offload + * + * Key management offload should be used if the device supports it. + * Key management offload is the capability of a device operating as + * a station to do the exchange necessary to establish temporal keys + * during initial RSN connection, after roaming, or during a PTK + * rekeying operation. + */ + int key_mgmt_offload; + + /** + * user_mpm - MPM residency + * + * 0: MPM lives in driver. + * 1: wpa_supplicant handles peering and station allocation. + * + * If AMPE or SAE is enabled, the MPM is always in userspace. + */ + int user_mpm; + + /** + * max_peer_links - Maximum number of peer links + * + * Maximum number of mesh peering currently maintained by the STA. + */ + int max_peer_links; + + /** + * cert_in_cb - Whether to include a peer certificate dump in events + * + * This controls whether peer certificates for authentication server and + * its certificate chain are included in EAP peer certificate events. + */ + int cert_in_cb; + + /** + * mesh_max_inactivity - Timeout in seconds to detect STA inactivity + * + * This timeout value is used in mesh STA to clean up inactive stations. + * By default: 300 seconds. + */ + int mesh_max_inactivity; + + /** + * dot11RSNASAERetransPeriod - Timeout to retransmit SAE Auth frame + * + * This timeout value is used in mesh STA to retransmit + * SAE Authentication frame. + * By default: 1000 milliseconds. + */ + int dot11RSNASAERetransPeriod; + + /** + * passive_scan - Whether to force passive scan for network connection + * + * This parameter can be used to force only passive scanning to be used + * for network connection cases. It should be noted that this will slow + * down scan operations and reduce likelihood of finding the AP. In + * addition, some use cases will override this due to functional + * requirements, e.g., for finding an AP that uses hidden SSID + * (scan_ssid=1) or P2P device discovery. + */ + int passive_scan; + + /** + * reassoc_same_bss_optim - Whether to optimize reassoc-to-same-BSS + */ + int reassoc_same_bss_optim; + + /** + * wps_priority - Priority for the networks added through WPS + * + * This priority value will be set to each network profile that is added + * by executing the WPS protocol. + */ + int wps_priority; + + /** + * fst_group_id - FST group ID + */ + char *fst_group_id; + + /** + * fst_priority - priority of the interface within the FST group + */ + int fst_priority; + + /** + * fst_llt - default FST LLT (Link-Lost Timeout) to be used for the + * interface. + */ + int fst_llt; +}; + + +/* Prototypes for common functions from config.c */ + +void wpa_config_free(struct wpa_config *ssid); +void wpa_config_free_ssid(struct wpa_ssid *ssid); +void wpa_config_foreach_network(struct wpa_config *config, + void (*func)(void *, struct wpa_ssid *), + void *arg); +struct wpa_ssid * wpa_config_get_network(struct wpa_config *config, int id); +struct wpa_ssid * wpa_config_add_network(struct wpa_config *config); +int wpa_config_remove_network(struct wpa_config *config, int id); +void wpa_config_set_network_defaults(struct wpa_ssid *ssid); +int wpa_config_set(struct wpa_ssid *ssid, const char *var, const char *value, + int line); +int wpa_config_set_quoted(struct wpa_ssid *ssid, const char *var, + const char *value); +int wpa_config_dump_values(struct wpa_config *config, char *buf, + size_t buflen); +int wpa_config_get_value(const char *name, struct wpa_config *config, + char *buf, size_t buflen); + +char ** wpa_config_get_all(struct wpa_ssid *ssid, int get_keys); +char * wpa_config_get(struct wpa_ssid *ssid, const char *var); +char * wpa_config_get_no_key(struct wpa_ssid *ssid, const char *var); +void wpa_config_update_psk(struct wpa_ssid *ssid); +int wpa_config_add_prio_network(struct wpa_config *config, + struct wpa_ssid *ssid); +int wpa_config_update_prio_list(struct wpa_config *config); +const struct wpa_config_blob * wpa_config_get_blob(struct wpa_config *config, + const char *name); +void wpa_config_set_blob(struct wpa_config *config, + struct wpa_config_blob *blob); +void wpa_config_free_blob(struct wpa_config_blob *blob); +int wpa_config_remove_blob(struct wpa_config *config, const char *name); +void wpa_config_flush_blobs(struct wpa_config *config); + +struct wpa_cred * wpa_config_get_cred(struct wpa_config *config, int id); +struct wpa_cred * wpa_config_add_cred(struct wpa_config *config); +int wpa_config_remove_cred(struct wpa_config *config, int id); +void wpa_config_free_cred(struct wpa_cred *cred); +int wpa_config_set_cred(struct wpa_cred *cred, const char *var, + const char *value, int line); +char * wpa_config_get_cred_no_key(struct wpa_cred *cred, const char *var); + +struct wpa_config * wpa_config_alloc_empty(const char *ctrl_interface, + const char *driver_param); +#ifndef CONFIG_NO_STDOUT_DEBUG +void wpa_config_debug_dump_networks(struct wpa_config *config); +#else /* CONFIG_NO_STDOUT_DEBUG */ +#define wpa_config_debug_dump_networks(c) do { } while (0) +#endif /* CONFIG_NO_STDOUT_DEBUG */ +#ifndef CONFIG_NO_PBKDF2 +int pbkdf2_sha1(const char *passphrase, const u8 *ssid, size_t ssid_len, + int iterations, u8 *buf, size_t buflen); +#endif + +/* Prototypes for common functions from config.c */ +int wpa_config_process_global(struct wpa_config *config, char *pos, int line); + + +/* Prototypes for backend specific functions from the selected config_*.c */ + +/** + * wpa_config_read - Read and parse configuration database + * @name: Name of the configuration (e.g., path and file name for the + * configuration file) + * @cfgp: Pointer to previously allocated configuration data or %NULL if none + * Returns: Pointer to allocated configuration data or %NULL on failure + * + * This function reads configuration data, parses its contents, and allocates + * data structures needed for storing configuration information. The allocated + * data can be freed with wpa_config_free(). + * + * Each configuration backend needs to implement this function. + */ +struct wpa_config * wpa_config_read(const char *name, struct wpa_config *cfgp); + +/** + * wpa_config_write - Write or update configuration data + * @name: Name of the configuration (e.g., path and file name for the + * configuration file) + * @config: Configuration data from wpa_config_read() + * Returns: 0 on success, -1 on failure + * + * This function write all configuration data into an external database (e.g., + * a text file) in a format that can be read with wpa_config_read(). This can + * be used to allow wpa_supplicant to update its configuration, e.g., when a + * new network is added or a password is changed. + * + * Each configuration backend needs to implement this function. + */ +int wpa_config_write(const char *name, struct wpa_config *config); + +#endif /* CONFIG_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/config_none.c b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/config_none.c new file mode 100755 index 0000000..405e22d --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/config_none.c @@ -0,0 +1,416 @@ +/* + * WPA Supplicant / Configuration backend: empty starting point + * Copyright (c) 2003-2005, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + * + * This file implements dummy example of a configuration backend. None of the + * functions are actually implemented so this can be used as a simple + * compilation test or a starting point for a new configuration backend. + */ +#include "includes.h" +#include "common.h" +#include "config.h" +#include "base64.h" +#include "param_config.h" +#include "uart_pub.h" +#include "wlan_ui_pub.h" +#include "wpa_common.h" +#include "role_launch.h" + +#if CFG_IEEE80211N +static void wpa_config_ht_cap_by_sec(int sec) +{ + if(sec == SECURITY_TYPE_WEP + || sec == SECURITY_TYPE_WPA_TKIP + || sec == SECURITY_TYPE_WPA2_TKIP) + { + rw_ieee80211_set_ht_cap(0); + } + else + { + rw_ieee80211_set_ht_cap(1); + } +} +#endif + +static int wpa_config_validate_network(struct wpa_ssid *ssid, int line) +{ + int errors = 0; + + if ((ssid->group_cipher & WPA_CIPHER_CCMP) && + !(ssid->pairwise_cipher & WPA_CIPHER_CCMP) && + !(ssid->pairwise_cipher & WPA_CIPHER_NONE)) { + /* Group cipher cannot be stronger than the pairwise cipher. */ + wpa_printf(MSG_DEBUG, "Line %d: removed CCMP from group cipher" + " list since it was not allowed for pairwise " + "cipher", line); + ssid->group_cipher &= ~WPA_CIPHER_CCMP; + } + + if (ssid->mode == WPAS_MODE_MESH && + (ssid->key_mgmt != WPA_KEY_MGMT_NONE && + ssid->key_mgmt != WPA_KEY_MGMT_SAE)) { + wpa_printf(MSG_ERROR, + "Line %d: key_mgmt for mesh network should be open or SAE", + line); + errors++; + } + + return errors; +} + +static int set_wpa_psk(struct wpa_ssid *ssid) +{ + int errors = 0; + + if (g_sta_param_ptr->key_len < 8 || g_sta_param_ptr->key_len > 64) { + os_printf("Invalid passphrase " + "length %lu (expected: 8..63) '%s'.", + (unsigned long) g_sta_param_ptr->key_len, (char *)g_sta_param_ptr->key); + errors++; + + return 1; + } else if (g_sta_param_ptr->key_len == 64) { + wpa_printf(MSG_ERROR, "use PSK"); + if (hexstr2bin((char*)g_sta_param_ptr->key, ssid->psk, 32) || + g_sta_param_ptr->key[64] != '\0') { + wpa_printf(MSG_ERROR, "Invalid PSK '%s'.", + g_sta_param_ptr->key); + errors++; + } + ssid->passphrase = NULL; + ssid->psk_set = 1; + } else { + str_clear_free(ssid->passphrase); + ssid->passphrase = dup_binstr(g_sta_param_ptr->key, g_sta_param_ptr->key_len); + ssid->psk_set = 0; + } + ssid->key_mgmt |= WPA_KEY_MGMT_PSK; +#ifdef CONFIG_IEEE80211W + ssid->key_mgmt |= WPA_KEY_MGMT_PSK_SHA256; +#endif +#ifdef CONFIG_SAE + ssid->key_mgmt |= WPA_KEY_MGMT_SAE; +#endif + ssid->mem_only_psk = 0; + + os_null_printf("%s:%d errors=%d,key_len=%d,orig_key_len=%d,%.*s,%.*s\r\n", __FUNCTION__, __LINE__, errors, g_sta_param_ptr->key_len, g_sta_param_ptr->orig_key_len, g_sta_param_ptr->key_len, g_sta_param_ptr->key, g_sta_param_ptr->orig_key_len, g_sta_param_ptr->orig_key); + return errors; +} + +static int set_wep_key(struct wpa_ssid*ssid) +{ + int errors = 0; + + ssid->wep_tx_keyidx = 0; + ssid->auth_alg = WPA_AUTH_ALG_OPEN|WPA_AUTH_ALG_SHARED; + if(g_sta_param_ptr->key_len == 5 || + g_sta_param_ptr->key_len == 13){ + os_memcpy(ssid->wep_key[0], (char *)g_sta_param_ptr->key, g_sta_param_ptr->key_len); + ssid->wep_key_len[0] = g_sta_param_ptr->key_len; + }else if(g_sta_param_ptr->key_len == 10 || + g_sta_param_ptr->key_len == 26){ + ssid->wep_key_len[0] = g_sta_param_ptr->key_len / 2; + hexstr2bin((char*)g_sta_param_ptr->key, (unsigned char*)ssid->wep_key[0],ssid->wep_key_len[0] ); + }else if(g_sta_param_ptr->orig_key_len == 5 || + g_sta_param_ptr->orig_key_len == 13){ + os_memcpy(ssid->wep_key[0], (char *)g_sta_param_ptr->orig_key, g_sta_param_ptr->orig_key_len); + ssid->wep_key_len[0] = g_sta_param_ptr->orig_key_len; + }else if(g_sta_param_ptr->orig_key_len == 10 || + g_sta_param_ptr->orig_key_len == 26){ + ssid->wep_key_len[0] = g_sta_param_ptr->orig_key_len / 2; + hexstr2bin((char*)g_sta_param_ptr->orig_key, (unsigned char*)ssid->wep_key[0],ssid->wep_key_len[0]); + }else{ + errors++; +#if RL_SUPPORT_FAST_CONNECT + bk_printf("%s:%d rl_clear_bssid_info\r\n", __FUNCTION__, __LINE__); + rl_clear_bssid_info(); +#endif + } + ssid->mem_only_psk = 0; + os_null_printf("%s:%d errors=%d,key_len=%d,orig_key_len=%d,%.*s,%.*s\r\n", __FUNCTION__, __LINE__, errors, g_sta_param_ptr->key_len, g_sta_param_ptr->orig_key_len, g_sta_param_ptr->key_len, g_sta_param_ptr->key, g_sta_param_ptr->orig_key_len, g_sta_param_ptr->orig_key); + return errors; +} + +static int cipher2security(struct wpa_ie_data *ie) +{ + bk_printf("%s %d %d %d %d\n", __FUNCTION__, ie->key_mgmt, ie->proto, ie->pairwise_cipher, ie->group_cipher); + switch(ie->key_mgmt) { + case WPA_KEY_MGMT_PSK: + if (ie->proto == WPA_PROTO_WPA) { + if (ie->pairwise_cipher & WPA_CIPHER_CCMP) + return SECURITY_TYPE_WPA_AES; + else + return SECURITY_TYPE_WPA_TKIP; + } else if (ie->proto == (WPA_PROTO_WPA|WPA_PROTO_RSN)) { + return SECURITY_TYPE_WPA2_MIXED; + } else { + if (ie->pairwise_cipher == (WPA_CIPHER_CCMP|WPA_CIPHER_TKIP)) + return SECURITY_TYPE_WPA2_MIXED; + else if (ie->pairwise_cipher & WPA_CIPHER_CCMP) + return SECURITY_TYPE_WPA2_AES; + else + return SECURITY_TYPE_WPA2_TKIP; + } + break; + case WPA_KEY_MGMT_NONE: + if (ie->pairwise_cipher == WPA_CIPHER_NONE) + return SECURITY_TYPE_NONE; + else + return SECURITY_TYPE_WEP; + break; + default: + return SECURITY_TYPE_AUTO; + } +} + +static int security2cipher(struct wpa_ie_data *ie, int security) +{ + os_memset(ie, 0, sizeof(*ie)); + + switch(security) { + case SECURITY_TYPE_NONE: + ie->key_mgmt = WPA_KEY_MGMT_NONE; + ie->pairwise_cipher = WPA_CIPHER_NONE; + break; + case SECURITY_TYPE_WEP: + ie->key_mgmt = WPA_KEY_MGMT_NONE; + ie->pairwise_cipher = WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104; + break; + case SECURITY_TYPE_WPA_TKIP: + ie->key_mgmt = WPA_KEY_MGMT_PSK; + ie->pairwise_cipher = WPA_CIPHER_TKIP; + ie->group_cipher = WPA_CIPHER_TKIP; + ie->proto = WPA_PROTO_WPA; + break; + + case SECURITY_TYPE_WPA2_TKIP: + ie->key_mgmt = WPA_KEY_MGMT_PSK; + ie->pairwise_cipher = WPA_CIPHER_TKIP; + ie->group_cipher = WPA_CIPHER_TKIP; + ie->proto = WPA_PROTO_RSN; + break; + case SECURITY_TYPE_WPA_AES: + ie->key_mgmt = WPA_KEY_MGMT_PSK; + ie->pairwise_cipher = WPA_CIPHER_TKIP|WPA_CIPHER_CCMP; + ie->group_cipher = WPA_CIPHER_TKIP; + ie->proto = WPA_PROTO_WPA; + break; + case SECURITY_TYPE_WPA2_AES: + ie->key_mgmt = WPA_KEY_MGMT_PSK; + ie->pairwise_cipher = WPA_CIPHER_CCMP; + ie->group_cipher = WPA_CIPHER_CCMP; + ie->proto = WPA_PROTO_RSN; + break; + case SECURITY_TYPE_WPA2_MIXED: + ie->key_mgmt = WPA_KEY_MGMT_PSK; + ie->pairwise_cipher = WPA_CIPHER_TKIP|WPA_CIPHER_CCMP; + ie->group_cipher = WPA_CIPHER_TKIP; + ie->proto = WPA_PROTO_WPA|WPA_PROTO_RSN; + break; + default: + break; + } + bk_printf("%s %d %d %d %d security=%d\n", __FUNCTION__, ie->key_mgmt, ie->proto, ie->pairwise_cipher, ie->group_cipher, security); + + return 0; +} + +int wpa_config_set_none(struct wpa_ssid *ssid) +{ + ssid->key_mgmt = WPA_KEY_MGMT_NONE; + ssid->mem_only_psk = 0; + g_sta_param_ptr->cipher_suite = SECURITY_TYPE_NONE; + + return 0; +} + +int wpa_config_set_wep(struct wpa_ssid *ssid) +{ + int ret; + + ret = set_wep_key(ssid); + if(!ret) { + g_sta_param_ptr->cipher_suite = SECURITY_TYPE_WEP; + }else{ + mhdr_set_station_status(RW_EVT_STA_PASSWORD_WRONG); + } + + return 0; +} + +#if RL_SUPPORT_FAST_CONNECT +static void wpa_config_update_fast_psk(struct wpa_ssid *ssid) +{ + RL_BSSID_INFO_T bssid_info; + rl_read_bssid_info(&bssid_info); + + if(os_memcmp(ssid->ssid, bssid_info.ssid, ssid->ssid_len) == 0 + && os_strcmp(ssid->passphrase, (char*)bssid_info.pwd) == 0) + { + bk_printf("Skip PSK caculation if SSID and passphrase are same \n"); + os_memset(&ssid->psk, 0, sizeof(ssid->psk)); + os_strcpy((char *)ssid->psk, (char *)bssid_info.psk); + ssid->psk_set = 1; + } + else + { + wpa_config_update_psk(ssid); + } +} +#endif + +int wpa_config_set_wpa(struct wpa_ssid *ssid, struct wpa_ie_data *ie) +{ + int ret; + + ssid->group_cipher = ie->group_cipher; + ssid->pairwise_cipher = ie->pairwise_cipher; + ssid->key_mgmt = ie->key_mgmt; + ssid->proto = ie->proto; + + if ((ssid->psk_set) || (ssid->passphrase!=NULL)) { + return 0; + } + + ret = set_wpa_psk(ssid); + if(!ret){ + g_sta_param_ptr->cipher_suite = cipher2security(ie); + #if CFG_IEEE80211N + wpa_config_ht_cap_by_sec(g_sta_param_ptr->cipher_suite); + #endif + if (ssid->passphrase && (ssid->psk_set == 0)) { + #if RL_SUPPORT_FAST_CONNECT + wpa_config_update_fast_psk(ssid); + #else + wpa_config_update_psk(ssid); + #endif + } + }else{ + mhdr_set_station_status(RW_EVT_STA_PASSWORD_WRONG); + } + + return ret; +} + +static struct wpa_ssid * wpa_config_read_network(int *line, int id) +{ + struct wpa_ssid *ssid; + struct wpa_ie_data ie; + int errors = 0; + + ssid = os_zalloc(sizeof(*ssid)); + if (ssid == NULL) + return NULL; + + dl_list_init(&ssid->psk_list); + ssid->id = id; + + wpa_config_set_network_defaults(ssid); + + ssid->ssid = (u8*)dup_binstr(g_sta_param_ptr->ssid.array, g_sta_param_ptr->ssid.length); + ssid->ssid_len = g_sta_param_ptr->ssid.length; + ssid->key_mgmt = 0; + + if ((g_sta_param_ptr->fast_connect_set) && (g_sta_param_ptr->cipher_suite != SECURITY_TYPE_AUTO)){ + os_memcpy(ssid->bssid, g_sta_param_ptr->fast_connect.bssid, 6); + bk_printf("bssid %02x-%02x-%02x-%02x-%02x-%02x\r\n", + ssid->bssid[0],ssid->bssid[1],ssid->bssid[2], + ssid->bssid[3],ssid->bssid[4],ssid->bssid[5]); + ssid->bssid_set = 1; + if(g_sta_param_ptr->cipher_suite == SECURITY_TYPE_NONE){ + /*do nothing*/ + }else if(g_sta_param_ptr->cipher_suite == SECURITY_TYPE_WEP){ + errors += wpa_config_set_wep(ssid); + }else{ + #if CFG_IEEE80211N + wpa_config_ht_cap_by_sec(g_sta_param_ptr->cipher_suite); + #endif + security2cipher(&ie, g_sta_param_ptr->cipher_suite); + wpa_config_set_wpa(ssid, &ie); + } + } else { + ssid->mem_only_psk = 1; + } + + errors += wpa_config_validate_network(ssid, *line); + if(errors){ + wpa_config_free_ssid(ssid); + ssid = NULL; + } + + return ssid; +} + +struct wpa_config * wpa_config_read(const char *name, struct wpa_config *cfgp) +{ + struct wpa_config *config; + struct wpa_ssid *ssid, *tail, *head; + int id = 0, line = 0, errors = 0; + + if (cfgp) + config = cfgp; + else + config = wpa_config_alloc_empty(NULL, NULL); + if (config == NULL) + return NULL; + tail = head = config->ssid; + while (tail && tail->next) + tail = tail->next; + + ssid = wpa_config_read_network(&line, id++); + if(ssid == NULL){ + errors++; + goto error; + } + if (head == NULL) { + head = tail = ssid; + } else { + tail->next = ssid; + tail = ssid; + } + if(wpa_config_add_prio_network(config, ssid)){ + errors++; + goto error; + } + + config->ssid = head; + wpa_config_debug_dump_networks(config); + +error: + if(errors){ + wpa_config_free(config); + config = NULL; + head = NULL; + } + return config; +} + + +int wpa_config_write(const char *name, struct wpa_config *config) +{ + struct wpa_ssid *ssid; + //struct wpa_config_blob *blob; + + wpa_printf(MSG_DEBUG, "Writing configuration file '%s'", name); + + /* TODO: write global config parameters */ + + +#if 0 + for (ssid = config->ssid; ssid; ssid = ssid->next) { + /* TODO: write networks */ + } + + for (blob = config->blobs; blob; blob = blob->next) { + /* TODO: write blobs */ + } +#endif + + return 0; + (void)ssid; +} +// eof + diff --git a/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/config_none.h b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/config_none.h new file mode 100755 index 0000000..a79fadd --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/config_none.h @@ -0,0 +1,15 @@ +#ifndef _CONFIG_NONE_H_ +#define _CONFIG_NONE_H_ + +#include "config.h" + +extern int wpa_config_set_none(struct wpa_ssid *ssid); +extern int wpa_config_set_wep(struct wpa_ssid *ssid); +extern int wpa_config_set_wpa(struct wpa_ssid *ssid, struct wpa_ie_data *ie); + +extern struct wpa_config * wpa_config_read(const char *name, struct wpa_config *cfgp); +extern int wpa_config_write(const char *name, struct wpa_config *config); + +#endif // _CONFIG_NONE_H_ +// eof + diff --git a/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/config_ssid.h b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/config_ssid.h new file mode 100755 index 0000000..b54b390 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/config_ssid.h @@ -0,0 +1,723 @@ +/* + * WPA Supplicant / Network configuration structures + * Copyright (c) 2003-2013, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef CONFIG_SSID_H +#define CONFIG_SSID_H + +#include "common/defs.h" +#include "utils/list.h" + + +#define DEFAULT_EAP_WORKAROUND ((unsigned int) -1) +#define DEFAULT_EAPOL_FLAGS (EAPOL_FLAG_REQUIRE_KEY_UNICAST | \ + EAPOL_FLAG_REQUIRE_KEY_BROADCAST) +#define DEFAULT_PROTO (WPA_PROTO_WPA | WPA_PROTO_RSN) +#define DEFAULT_KEY_MGMT (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_IEEE8021X) +#define DEFAULT_PAIRWISE (WPA_CIPHER_CCMP | WPA_CIPHER_TKIP) +#define DEFAULT_GROUP (WPA_CIPHER_CCMP | WPA_CIPHER_TKIP) +#define DEFAULT_FRAGMENT_SIZE 1398 + +#define DEFAULT_BG_SCAN_PERIOD -1 +#define DEFAULT_MESH_MAX_RETRIES 2 +#define DEFAULT_MESH_RETRY_TIMEOUT 40 +#define DEFAULT_MESH_CONFIRM_TIMEOUT 40 +#define DEFAULT_MESH_HOLDING_TIMEOUT 40 +#define DEFAULT_DISABLE_HT 0 +#define DEFAULT_DISABLE_HT40 0 +#define DEFAULT_DISABLE_SGI 0 +#define DEFAULT_DISABLE_LDPC 0 +#define DEFAULT_DISABLE_MAX_AMSDU -1 /* no change */ +#define DEFAULT_AMPDU_FACTOR -1 /* no change */ +#define DEFAULT_AMPDU_DENSITY -1 /* no change */ +#define DEFAULT_USER_SELECTED_SIM 1 + +struct psk_list_entry { + struct dl_list list; + u8 addr[ETH_ALEN]; + u8 psk[32]; + u8 p2p; +}; + +/** + * struct wpa_ssid - Network configuration data + * + * This structure includes all the configuration variables for a network. This + * data is included in the per-interface configuration data as an element of + * the network list, struct wpa_config::ssid. Each network block in the + * configuration is mapped to a struct wpa_ssid instance. + */ +struct wpa_ssid { + /** + * next - Next network in global list + * + * This pointer can be used to iterate over all networks. The head of + * this list is stored in the ssid field of struct wpa_config. + */ + struct wpa_ssid *next; + + /** + * pnext - Next network in per-priority list + * + * This pointer can be used to iterate over all networks in the same + * priority class. The heads of these list are stored in the pssid + * fields of struct wpa_config. + */ + struct wpa_ssid *pnext; + + /** + * id - Unique id for the network + * + * This identifier is used as a unique identifier for each network + * block when using the control interface. Each network is allocated an + * id when it is being created, either when reading the configuration + * file or when a new network is added through the control interface. + */ + int id; + + /** + * priority - Priority group + * + * By default, all networks will get same priority group (0). If some + * of the networks are more desirable, this field can be used to change + * the order in which wpa_supplicant goes through the networks when + * selecting a BSS. The priority groups will be iterated in decreasing + * priority (i.e., the larger the priority value, the sooner the + * network is matched against the scan results). Within each priority + * group, networks will be selected based on security policy, signal + * strength, etc. + * + * Please note that AP scanning with scan_ssid=1 and ap_scan=2 mode are + * not using this priority to select the order for scanning. Instead, + * they try the networks in the order that used in the configuration + * file. + */ + int priority; + + /** + * ssid - Service set identifier (network name) + * + * This is the SSID for the network. For wireless interfaces, this is + * used to select which network will be used. If set to %NULL (or + * ssid_len=0), any SSID can be used. For wired interfaces, this must + * be set to %NULL. Note: SSID may contain any characters, even nul + * (ASCII 0) and as such, this should not be assumed to be a nul + * terminated string. ssid_len defines how many characters are valid + * and the ssid field is not guaranteed to be nul terminated. + */ + u8 *ssid; + + /** + * ssid_len - Length of the SSID + */ + size_t ssid_len; + + /** + * bssid - BSSID + * + * If set, this network block is used only when associating with the AP + * using the configured BSSID + * + * If this is a persistent P2P group (disabled == 2), this is the GO + * Device Address. + */ + u8 bssid[ETH_ALEN]; + + /** + * bssid_blacklist - List of inacceptable BSSIDs + */ + u8 *bssid_blacklist; + size_t num_bssid_blacklist; + + /** + * bssid_blacklist - List of acceptable BSSIDs + */ + u8 *bssid_whitelist; + size_t num_bssid_whitelist; + + /** + * bssid_set - Whether BSSID is configured for this network + */ + int bssid_set; + + /** + * go_p2p_dev_addr - GO's P2P Device Address or all zeros if not set + */ + u8 go_p2p_dev_addr[ETH_ALEN]; + + /** + * psk - WPA pre-shared key (256 bits) + */ + u8 psk[32]; + + /** + * psk_set - Whether PSK field is configured + */ + int psk_set; + + /** + * passphrase - WPA ASCII passphrase + * + * If this is set, psk will be generated using the SSID and passphrase + * configured for the network. ASCII passphrase must be between 8 and + * 63 characters (inclusive). + */ + char *passphrase; + + /** + * ext_psk - PSK/passphrase name in external storage + * + * If this is set, PSK/passphrase will be fetched from external storage + * when requesting association with the network. + */ + char *ext_psk; + + /** + * mem_only_psk - Whether to keep PSK/passphrase only in memory + * + * 0 = allow psk/passphrase to be stored to the configuration file + * 1 = do not store psk/passphrase to the configuration file + */ + int mem_only_psk; + + /** + * pairwise_cipher - Bitfield of allowed pairwise ciphers, WPA_CIPHER_* + */ + int pairwise_cipher; + + /** + * group_cipher - Bitfield of allowed group ciphers, WPA_CIPHER_* + */ + int group_cipher; + + /** + * key_mgmt - Bitfield of allowed key management protocols + * + * WPA_KEY_MGMT_* + */ + int key_mgmt; + + /** + * bg_scan_period - Background scan period in seconds, 0 to disable, or + * -1 to indicate no change to default driver configuration + */ + int bg_scan_period; + + /** + * proto - Bitfield of allowed protocols, WPA_PROTO_* + */ + int proto; + + /** + * auth_alg - Bitfield of allowed authentication algorithms + * + * WPA_AUTH_ALG_* + */ + int auth_alg; + + /** + * scan_ssid - Scan this SSID with Probe Requests + * + * scan_ssid can be used to scan for APs using hidden SSIDs. + * Note: Many drivers do not support this. ap_mode=2 can be used with + * such drivers to use hidden SSIDs. Note2: Most nl80211-based drivers + * do support scan_ssid=1 and that should be used with them instead of + * ap_scan=2. + */ + int scan_ssid; + +#ifdef IEEE8021X_EAPOL +#define EAPOL_FLAG_REQUIRE_KEY_UNICAST BIT(0) +#define EAPOL_FLAG_REQUIRE_KEY_BROADCAST BIT(1) + /** + * eapol_flags - Bit field of IEEE 802.1X/EAPOL options (EAPOL_FLAG_*) + */ + int eapol_flags; + + /** + * eap - EAP peer configuration for this network + */ + struct eap_peer_config eap; +#endif /* IEEE8021X_EAPOL */ + +#define NUM_WEP_KEYS 4 +#define MAX_WEP_KEY_LEN 16 + /** + * wep_key - WEP keys + */ + u8 wep_key[NUM_WEP_KEYS][MAX_WEP_KEY_LEN]; + + /** + * wep_key_len - WEP key lengths + */ + size_t wep_key_len[NUM_WEP_KEYS]; + + /** + * wep_tx_keyidx - Default key index for TX frames using WEP + */ + int wep_tx_keyidx; + + /** + * proactive_key_caching - Enable proactive key caching + * + * This field can be used to enable proactive key caching which is also + * known as opportunistic PMKSA caching for WPA2. This is disabled (0) + * by default unless default value is changed with the global okc=1 + * parameter. Enable by setting this to 1. + * + * Proactive key caching is used to make supplicant assume that the APs + * are using the same PMK and generate PMKSA cache entries without + * doing RSN pre-authentication. This requires support from the AP side + * and is normally used with wireless switches that co-locate the + * authenticator. + * + * Internally, special value -1 is used to indicate that the parameter + * was not specified in the configuration (i.e., default behavior is + * followed). + */ + int proactive_key_caching; + + /** + * mixed_cell - Whether mixed cells are allowed + * + * This option can be used to configure whether so called mixed cells, + * i.e., networks that use both plaintext and encryption in the same + * SSID, are allowed. This is disabled (0) by default. Enable by + * setting this to 1. + */ + int mixed_cell; + +#ifdef IEEE8021X_EAPOL + + /** + * leap - Number of EAP methods using LEAP + * + * This field should be set to 1 if LEAP is enabled. This is used to + * select IEEE 802.11 authentication algorithm. + */ + int leap; + + /** + * non_leap - Number of EAP methods not using LEAP + * + * This field should be set to >0 if any EAP method other than LEAP is + * enabled. This is used to select IEEE 802.11 authentication + * algorithm. + */ + int non_leap; + + /** + * eap_workaround - EAP workarounds enabled + * + * wpa_supplicant supports number of "EAP workarounds" to work around + * interoperability issues with incorrectly behaving authentication + * servers. This is recommended to be enabled by default because some + * of the issues are present in large number of authentication servers. + * + * Strict EAP conformance mode can be configured by disabling + * workarounds with eap_workaround = 0. + */ + unsigned int eap_workaround; + +#endif /* IEEE8021X_EAPOL */ + + /** + * mode - IEEE 802.11 operation mode (Infrastucture/IBSS) + * + * 0 = infrastructure (Managed) mode, i.e., associate with an AP. + * + * 1 = IBSS (ad-hoc, peer-to-peer) + * + * 2 = AP (access point) + * + * 3 = P2P Group Owner (can be set in the configuration file) + * + * 4 = P2P Group Formation (used internally; not in configuration + * files) + * + * 5 = Mesh + * + * Note: IBSS can only be used with key_mgmt NONE (plaintext and static + * WEP) and WPA-PSK (with proto=RSN). In addition, key_mgmt=WPA-NONE + * (fixed group key TKIP/CCMP) is available for backwards compatibility, + * but its use is deprecated. WPA-None requires following network block + * options: proto=WPA, key_mgmt=WPA-NONE, pairwise=NONE, group=TKIP (or + * CCMP, but not both), and psk must also be set (either directly or + * using ASCII passphrase). + */ + enum wpas_mode { + WPAS_MODE_INFRA = 0, + WPAS_MODE_IBSS = 1, + WPAS_MODE_AP = 2, + WPAS_MODE_P2P_GO = 3, + WPAS_MODE_P2P_GROUP_FORMATION = 4, + WPAS_MODE_MESH = 5, + } mode; + + /** + * disabled - Whether this network is currently disabled + * + * 0 = this network can be used (default). + * 1 = this network block is disabled (can be enabled through + * ctrl_iface, e.g., with wpa_cli or wpa_gui). + * 2 = this network block includes parameters for a persistent P2P + * group (can be used with P2P ctrl_iface commands) + */ + int disabled; + + /** + * disabled_for_connect - Whether this network was temporarily disabled + * + * This flag is used to reenable all the temporarily disabled networks + * after either the success or failure of a WPS connection. + */ + int disabled_for_connect; + + /** + * peerkey - Whether PeerKey handshake for direct links is allowed + * + * This is only used when both RSN/WPA2 and IEEE 802.11e (QoS) are + * enabled. + * + * 0 = disabled (default) + * 1 = enabled + */ + int peerkey; + + /** + * id_str - Network identifier string for external scripts + * + * This value is passed to external ctrl_iface monitors in + * WPA_EVENT_CONNECTED event and wpa_cli sets this as WPA_ID_STR + * environment variable for action scripts. + */ + char *id_str; + +#ifdef CONFIG_IEEE80211W + /** + * ieee80211w - Whether management frame protection is enabled + * + * This value is used to configure policy for management frame + * protection (IEEE 802.11w). 0 = disabled, 1 = optional, 2 = required. + * This is disabled by default unless the default value has been changed + * with the global pmf=1/2 parameter. + * + * Internally, special value 3 is used to indicate that the parameter + * was not specified in the configuration (i.e., default behavior is + * followed). + */ + enum mfp_options ieee80211w; +#endif /* CONFIG_IEEE80211W */ + + /** + * frequency - Channel frequency in megahertz (MHz) for IBSS + * + * This value is used to configure the initial channel for IBSS (adhoc) + * networks, e.g., 2412 = IEEE 802.11b/g channel 1. It is ignored in + * the infrastructure mode. In addition, this value is only used by the + * station that creates the IBSS. If an IBSS network with the + * configured SSID is already present, the frequency of the network + * will be used instead of this configured value. + */ + int frequency; + + /** + * fixed_freq - Use fixed frequency for IBSS + */ + int fixed_freq; + + /** + * mesh_basic_rates - BSS Basic rate set for mesh network + * + */ + int *mesh_basic_rates; + + /** + * Mesh network plink parameters + */ + int dot11MeshMaxRetries; + int dot11MeshRetryTimeout; /* msec */ + int dot11MeshConfirmTimeout; /* msec */ + int dot11MeshHoldingTimeout; /* msec */ + + int ht40; + + int vht; + + /** + * wpa_ptk_rekey - Maximum lifetime for PTK in seconds + * + * This value can be used to enforce rekeying of PTK to mitigate some + * attacks against TKIP deficiencies. + */ + int wpa_ptk_rekey; + + /** + * scan_freq - Array of frequencies to scan or %NULL for all + * + * This is an optional zero-terminated array of frequencies in + * megahertz (MHz) to include in scan requests when searching for this + * network. This can be used to speed up scanning when the network is + * known to not use all possible channels. + */ + int *scan_freq; + + /** + * bgscan - Background scan and roaming parameters or %NULL if none + * + * This is an optional set of parameters for background scanning and + * roaming within a network (ESS) in following format: + * : + */ + char *bgscan; + + /** + * ignore_broadcast_ssid - Hide SSID in AP mode + * + * Send empty SSID in beacons and ignore probe request frames that do + * not specify full SSID, i.e., require stations to know SSID. + * default: disabled (0) + * 1 = send empty (length=0) SSID in beacon and ignore probe request + * for broadcast SSID + * 2 = clear SSID (ASCII 0), but keep the original length (this may be + * required with some clients that do not support empty SSID) and + * ignore probe requests for broadcast SSID + */ + int ignore_broadcast_ssid; + + /** + * freq_list - Array of allowed frequencies or %NULL for all + * + * This is an optional zero-terminated array of frequencies in + * megahertz (MHz) to allow for selecting the BSS. If set, scan results + * that do not match any of the specified frequencies are not + * considered when selecting a BSS. + */ + int *freq_list; + + /** + * p2p_client_list - List of P2P Clients in a persistent group (GO) + * + * This is a list of P2P Clients (P2P Device Address) that have joined + * the persistent group. This is maintained on the GO for persistent + * group entries (disabled == 2). + */ + u8 *p2p_client_list; + + /** + * num_p2p_clients - Number of entries in p2p_client_list + */ + size_t num_p2p_clients; + +#ifndef P2P_MAX_STORED_CLIENTS +#define P2P_MAX_STORED_CLIENTS 100 +#endif /* P2P_MAX_STORED_CLIENTS */ + + /** + * psk_list - Per-client PSKs (struct psk_list_entry) + */ + struct dl_list psk_list; + + /** + * p2p_group - Network generated as a P2P group (used internally) + */ + int p2p_group; + + /** + * p2p_persistent_group - Whether this is a persistent group + */ + int p2p_persistent_group; + + /** + * temporary - Whether this network is temporary and not to be saved + */ + int temporary; + + /** + * export_keys - Whether keys may be exported + * + * This attribute will be set when keys are determined through + * WPS or similar so that they may be exported. + */ + int export_keys; + +#ifdef CONFIG_HT_OVERRIDES + /** + * disable_ht - Disable HT (IEEE 802.11n) for this network + * + * By default, use it if it is available, but this can be configured + * to 1 to have it disabled. + */ + int disable_ht; + + /** + * disable_ht40 - Disable HT40 for this network + * + * By default, use it if it is available, but this can be configured + * to 1 to have it disabled. + */ + int disable_ht40; + + /** + * disable_sgi - Disable SGI (Short Guard Interval) for this network + * + * By default, use it if it is available, but this can be configured + * to 1 to have it disabled. + */ + int disable_sgi; + + /** + * disable_ldpc - Disable LDPC for this network + * + * By default, use it if it is available, but this can be configured + * to 1 to have it disabled. + */ + int disable_ldpc; + + /** + * ht40_intolerant - Indicate 40 MHz intolerant for this network + */ + int ht40_intolerant; + + /** + * disable_max_amsdu - Disable MAX A-MSDU + * + * A-MDSU will be 3839 bytes when disabled, or 7935 + * when enabled (assuming it is otherwise supported) + * -1 (default) means do not apply any settings to the kernel. + */ + int disable_max_amsdu; + + /** + * ampdu_factor - Maximum A-MPDU Length Exponent + * + * Value: 0-3, see 7.3.2.56.3 in IEEE Std 802.11n-2009. + */ + int ampdu_factor; + + /** + * ampdu_density - Minimum A-MPDU Start Spacing + * + * Value: 0-7, see 7.3.2.56.3 in IEEE Std 802.11n-2009. + */ + int ampdu_density; + + /** + * ht_mcs - Allowed HT-MCS rates, in ASCII hex: ffff0000... + * + * By default (empty string): Use whatever the OS has configured. + */ + char *ht_mcs; +#endif /* CONFIG_HT_OVERRIDES */ + +#ifdef CONFIG_VHT_OVERRIDES + /** + * disable_vht - Disable VHT (IEEE 802.11ac) for this network + * + * By default, use it if it is available, but this can be configured + * to 1 to have it disabled. + */ + int disable_vht; + + /** + * vht_capa - VHT capabilities to use + */ + unsigned int vht_capa; + + /** + * vht_capa_mask - mask for VHT capabilities + */ + unsigned int vht_capa_mask; + + int vht_rx_mcs_nss_1, vht_rx_mcs_nss_2, + vht_rx_mcs_nss_3, vht_rx_mcs_nss_4, + vht_rx_mcs_nss_5, vht_rx_mcs_nss_6, + vht_rx_mcs_nss_7, vht_rx_mcs_nss_8; + int vht_tx_mcs_nss_1, vht_tx_mcs_nss_2, + vht_tx_mcs_nss_3, vht_tx_mcs_nss_4, + vht_tx_mcs_nss_5, vht_tx_mcs_nss_6, + vht_tx_mcs_nss_7, vht_tx_mcs_nss_8; +#endif /* CONFIG_VHT_OVERRIDES */ + + /** + * ap_max_inactivity - Timeout in seconds to detect STA's inactivity + * + * This timeout value is used in AP mode to clean up inactive stations. + * By default: 300 seconds. + */ + int ap_max_inactivity; + + /** + * dtim_period - DTIM period in Beacon intervals + * By default: 2 + */ + int dtim_period; + + /** + * beacon_int - Beacon interval (default: 100 TU) + */ + int beacon_int; + + /** + * auth_failures - Number of consecutive authentication failures + */ + unsigned int auth_failures; + + /** + * disabled_until - Network block disabled until this time if non-zero + */ + struct os_reltime disabled_until; + + /** + * parent_cred - Pointer to parent wpa_cred entry + * + * This pointer can be used to delete temporary networks when a wpa_cred + * that was used to create them is removed. This pointer should not be + * dereferences since it may not be updated in all cases. + */ + void *parent_cred; + +#ifdef CONFIG_MACSEC + /** + * macsec_policy - Determines the policy for MACsec secure session + * + * 0: MACsec not in use (default) + * 1: MACsec enabled - Should secure, accept key server's advice to + * determine whether to use a secure session or not. + */ + int macsec_policy; +#endif /* CONFIG_MACSEC */ + +#ifdef CONFIG_HS20 + int update_identifier; +#endif /* CONFIG_HS20 */ + + unsigned int wps_run; + + /** + * mac_addr - MAC address policy + * + * 0 = use permanent MAC address + * 1 = use random MAC address for each ESS connection + * 2 = like 1, but maintain OUI (with local admin bit set) + * + * Internally, special value -1 is used to indicate that the parameter + * was not specified in the configuration (i.e., default behavior is + * followed). + */ + int mac_addr; + + /** + * no_auto_peer - Do not automatically peer with compatible mesh peers + * + * When unset, the reception of a beacon from a another mesh peer in + * this MBSS will trigger a peering attempt. + */ + int no_auto_peer; +}; + +#endif /* CONFIG_SSID_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/ctrl_iface.h b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/ctrl_iface.h new file mode 100755 index 0000000..d54cc07 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/ctrl_iface.h @@ -0,0 +1,159 @@ +/* + * WPA Supplicant / UNIX domain socket -based control interface + * Copyright (c) 2004-2005, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef CTRL_IFACE_H +#define CTRL_IFACE_H + +#ifdef CONFIG_CTRL_IFACE + +/* Shared functions from ctrl_iface.c; to be called by ctrl_iface backends */ + +/** + * wpa_supplicant_ctrl_iface_process - Process ctrl_iface command + * @wpa_s: Pointer to wpa_supplicant data + * @buf: Received command buffer (nul terminated string) + * @resp_len: Variable to be set to the response length + * Returns: Response (*resp_len bytes) or %NULL on failure + * + * Control interface backends call this function when receiving a message that + * they do not process internally, i.e., anything else than ATTACH, DETACH, + * and LEVEL. The return response value is then sent to the external program + * that sent the command. Caller is responsible for freeing the buffer after + * this. If %NULL is returned, *resp_len can be set to two special values: + * 1 = send "FAIL\n" response, 2 = send "OK\n" response. If *resp_len has any + * other value, no response is sent. + */ +char * wpa_supplicant_ctrl_iface_process(struct wpa_supplicant *wpa_s, + char *buf, size_t *resp_len); + +/** + * wpa_supplicant_global_ctrl_iface_process - Process global ctrl_iface command + * @global: Pointer to global data from wpa_supplicant_init() + * @buf: Received command buffer (nul terminated string) + * @resp_len: Variable to be set to the response length + * Returns: Response (*resp_len bytes) or %NULL on failure + * + * Control interface backends call this function when receiving a message from + * the global ctrl_iface connection. The return response value is then sent to + * the external program that sent the command. Caller is responsible for + * freeing the buffer after this. If %NULL is returned, *resp_len can be set to + * two special values: 1 = send "FAIL\n" response, 2 = send "OK\n" response. If + * *resp_len has any other value, no response is sent. + */ +char * wpa_supplicant_global_ctrl_iface_process(struct wpa_global *global, + char *buf, size_t *resp_len); + + +/* Functions that each ctrl_iface backend must implement */ + +/** + * wpa_supplicant_ctrl_iface_init - Initialize control interface + * @wpa_s: Pointer to wpa_supplicant data + * Returns: Pointer to private data on success, %NULL on failure + * + * Initialize the control interface and start receiving commands from external + * programs. + * + * Required to be implemented in each control interface backend. + */ +struct ctrl_iface_priv * +wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s); + +/** + * wpa_supplicant_ctrl_iface_deinit - Deinitialize control interface + * @priv: Pointer to private data from wpa_supplicant_ctrl_iface_init() + * + * Deinitialize the control interface that was initialized with + * wpa_supplicant_ctrl_iface_init(). + * + * Required to be implemented in each control interface backend. + */ +void wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv); + +/** + * wpa_supplicant_ctrl_iface_wait - Wait for ctrl_iface monitor + * @priv: Pointer to private data from wpa_supplicant_ctrl_iface_init() + * + * Wait until the first message from an external program using the control + * interface is received. This function can be used to delay normal startup + * processing to allow control interface programs to attach with + * %wpa_supplicant before normal operations are started. + * + * Required to be implemented in each control interface backend. + */ +void wpa_supplicant_ctrl_iface_wait(struct ctrl_iface_priv *priv); + +/** + * wpa_supplicant_global_ctrl_iface_init - Initialize global control interface + * @global: Pointer to global data from wpa_supplicant_init() + * Returns: Pointer to private data on success, %NULL on failure + * + * Initialize the global control interface and start receiving commands from + * external programs. + * + * Required to be implemented in each control interface backend. + */ +struct ctrl_iface_global_priv * +wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global); + +/** + * wpa_supplicant_global_ctrl_iface_deinit - Deinitialize global ctrl interface + * @priv: Pointer to private data from wpa_supplicant_global_ctrl_iface_init() + * + * Deinitialize the global control interface that was initialized with + * wpa_supplicant_global_ctrl_iface_init(). + * + * Required to be implemented in each control interface backend. + */ +void wpa_supplicant_global_ctrl_iface_deinit( + struct ctrl_iface_global_priv *priv); + +void wpas_ctrl_radio_work_flush(struct wpa_supplicant *wpa_s); + +#else /* CONFIG_CTRL_IFACE */ + +static inline struct ctrl_iface_priv * +wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s) +{ + return (void *) -1; +} + +static inline void +wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv) +{ +} + +static inline void +wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv *priv, int level, + char *buf, size_t len) +{ +} + +static inline void +wpa_supplicant_ctrl_iface_wait(struct ctrl_iface_priv *priv) +{ +} + +static inline struct ctrl_iface_global_priv * +wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global) +{ + return (void *) 1; +} + +static inline void +wpa_supplicant_global_ctrl_iface_deinit(struct ctrl_iface_global_priv *priv) +{ +} + +static inline void wpas_ctrl_radio_work_flush(struct wpa_supplicant *wpa_s) +{ +} + +#endif /* CONFIG_CTRL_IFACE */ + +#endif /* CTRL_IFACE_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/driver_i.h b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/driver_i.h new file mode 100755 index 0000000..17f5aaf --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/driver_i.h @@ -0,0 +1,918 @@ +/* + * wpa_supplicant - Internal driver interface wrappers + * Copyright (c) 2003-2015, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef DRIVER_I_H +#define DRIVER_I_H + +#include "drivers/driver.h" + +void wpa_supplicant_event_sta(void *ctx, enum wpa_event_type event, + union wpa_event_data *data); + +/* driver_ops */ +static inline void * wpa_drv_init(struct wpa_supplicant *wpa_s, + const char *ifname) +{ + if (wpa_s->driver->init2) + return wpa_s->driver->init2(wpa_s, ifname, + wpa_s->global_drv_priv); + if (wpa_s->driver->init) { + return wpa_s->driver->init(wpa_s, ifname); + } + return NULL; +} + +static inline void wpa_drv_deinit(struct wpa_supplicant *wpa_s) +{ + if (wpa_s->driver->deinit) + wpa_s->driver->deinit(wpa_s->drv_priv); +} + +static inline int wpa_drv_set_param(struct wpa_supplicant *wpa_s, + const char *param) +{ + if (wpa_s->driver->set_param) + return wpa_s->driver->set_param(wpa_s->drv_priv, param); + return 0; +} + +static inline int wpa_drv_set_countermeasures(struct wpa_supplicant *wpa_s, + int enabled) +{ + if (wpa_s->driver->set_countermeasures) { + return wpa_s->driver->set_countermeasures(wpa_s->drv_priv, + enabled); + } + return -1; +} + +static inline int wpa_drv_authenticate(struct wpa_supplicant *wpa_s, + struct wpa_driver_auth_params *params) +{ + if (wpa_s->driver->authenticate) + return wpa_s->driver->authenticate(wpa_s->drv_priv, params); + return -1; +} + +static inline int wpa_drv_associate(struct wpa_supplicant *wpa_s, + struct wpa_driver_associate_params *params) +{ + if (wpa_s->driver->associate) { + return wpa_s->driver->associate(wpa_s->drv_priv, params); + } + return -1; +} + +static inline int wpa_drv_init_mesh(struct wpa_supplicant *wpa_s) +{ + if (wpa_s->driver->init_mesh) + return wpa_s->driver->init_mesh(wpa_s->drv_priv); + return -1; +} + +static inline int wpa_drv_join_mesh(struct wpa_supplicant *wpa_s, + struct wpa_driver_mesh_join_params *params) +{ + if (wpa_s->driver->join_mesh) + return wpa_s->driver->join_mesh(wpa_s->drv_priv, params); + return -1; +} + +static inline int wpa_drv_leave_mesh(struct wpa_supplicant *wpa_s) +{ + if (wpa_s->driver->leave_mesh) + return wpa_s->driver->leave_mesh(wpa_s->drv_priv); + return -1; +} + +static inline int wpa_drv_scan(struct wpa_supplicant *wpa_s, + struct wpa_driver_scan_params *params) +{ +#ifdef CONFIG_TESTING_OPTIONS + if (wpa_s->test_failure == WPAS_TEST_FAILURE_SCAN_TRIGGER) + return -ERRBUSY; +#endif /* CONFIG_TESTING_OPTIONS */ + if (wpa_s->driver->scan2) + return wpa_s->driver->scan2(wpa_s->drv_priv, params); + return -1; +} + +static inline int wpa_drv_sched_scan(struct wpa_supplicant *wpa_s, + struct wpa_driver_scan_params *params, + u32 interval) +{ + if (wpa_s->driver->sched_scan) + return wpa_s->driver->sched_scan(wpa_s->drv_priv, + params, interval); + return -1; +} + +static inline int wpa_drv_stop_sched_scan(struct wpa_supplicant *wpa_s) +{ + if (wpa_s->driver->stop_sched_scan) + return wpa_s->driver->stop_sched_scan(wpa_s->drv_priv); + return -1; +} + +static inline struct wpa_scan_results * wpa_drv_get_scan_results2( + struct wpa_supplicant *wpa_s) +{ + if ((wpa_s->driver) && (wpa_s->driver->get_scan_results2)) + return wpa_s->driver->get_scan_results2(wpa_s->drv_priv); + return NULL; +} + +static inline int wpa_drv_get_bssid(struct wpa_supplicant *wpa_s, u8 *bssid) +{ + if (wpa_s->driver->get_bssid) { + return wpa_s->driver->get_bssid(wpa_s->drv_priv, bssid); + } + return -1; +} + +static inline int wpa_drv_get_ssid(struct wpa_supplicant *wpa_s, u8 *ssid) +{ + if (wpa_s->driver->get_ssid) { + return wpa_s->driver->get_ssid(wpa_s->drv_priv, ssid); + } + return -1; +} + +static inline int wpa_drv_set_key(struct wpa_supplicant *wpa_s, + enum wpa_alg alg, const u8 *addr, + int key_idx, int set_tx, + const u8 *seq, size_t seq_len, + const u8 *key, size_t key_len) +{ + if (alg != WPA_ALG_NONE) { + if (key_idx >= 0 && key_idx <= 6) + wpa_s->keys_cleared &= ~BIT(key_idx); + else + wpa_s->keys_cleared = 0; + } + if (wpa_s->driver->set_key) { + return wpa_s->driver->set_key(wpa_s->ifname, wpa_s->drv_priv, + alg, addr, key_idx, set_tx, + seq, seq_len, key, key_len); + } + return -1; +} + +static inline int wpa_drv_sta_deauth(struct wpa_supplicant *wpa_s, + const u8 *addr, int reason_code) +{ + if (wpa_s->driver->sta_deauth) { + return wpa_s->driver->sta_deauth(wpa_s->drv_priv, + wpa_s->own_addr, addr, + reason_code); + } + return -1; +} + +static inline int wpa_drv_deauthenticate(struct wpa_supplicant *wpa_s, + const u8 *addr, int reason_code) +{ + if (wpa_s->driver->deauthenticate) { + return wpa_s->driver->deauthenticate(wpa_s->drv_priv, addr, + reason_code); + } + return -1; +} + +static inline int wpa_drv_add_pmkid(struct wpa_supplicant *wpa_s, + const u8 *bssid, const u8 *pmkid) +{ + if (wpa_s->driver->add_pmkid) { + return wpa_s->driver->add_pmkid(wpa_s->drv_priv, bssid, pmkid); + } + return -1; +} + +static inline int wpa_drv_remove_pmkid(struct wpa_supplicant *wpa_s, + const u8 *bssid, const u8 *pmkid) +{ + if (wpa_s->driver->remove_pmkid) { + return wpa_s->driver->remove_pmkid(wpa_s->drv_priv, bssid, + pmkid); + } + return -1; +} + +static inline int wpa_drv_flush_pmkid(struct wpa_supplicant *wpa_s) +{ + if (wpa_s->driver->flush_pmkid) { + return wpa_s->driver->flush_pmkid(wpa_s->drv_priv); + } + return -1; +} + +static inline int wpa_drv_get_capa(struct wpa_supplicant *wpa_s, + struct wpa_driver_capa *capa) +{ + if (wpa_s->driver->get_capa) { + return wpa_s->driver->get_capa(wpa_s->drv_priv, capa); + } + return -1; +} + +static inline void wpa_drv_poll(struct wpa_supplicant *wpa_s) +{ + if (wpa_s->driver->poll) { + wpa_s->driver->poll(wpa_s->drv_priv); + } +} + +static inline const char * wpa_drv_get_ifname(struct wpa_supplicant *wpa_s) +{ + if (wpa_s->driver->get_ifname) { + return wpa_s->driver->get_ifname(wpa_s->drv_priv); + } + return NULL; +} + +static inline const char * +wpa_driver_get_radio_name(struct wpa_supplicant *wpa_s) +{ + if (wpa_s->driver->get_radio_name) + return wpa_s->driver->get_radio_name(wpa_s->drv_priv); + return NULL; +} + +static inline const u8 * wpa_drv_get_mac_addr(struct wpa_supplicant *wpa_s) +{ + if (wpa_s->driver->get_mac_addr) { + return wpa_s->driver->get_mac_addr(wpa_s->drv_priv); + } + return NULL; +} + +static inline int wpa_drv_set_operstate(struct wpa_supplicant *wpa_s, + int state) +{ + if (wpa_s->driver->set_operstate) + return wpa_s->driver->set_operstate(wpa_s->drv_priv, state); + return 0; +} + +static inline int wpa_drv_mlme_setprotection(struct wpa_supplicant *wpa_s, + const u8 *addr, int protect_type, + int key_type) +{ + if (wpa_s->driver->mlme_setprotection) + return wpa_s->driver->mlme_setprotection(wpa_s->drv_priv, addr, + protect_type, + key_type); + return 0; +} + +static inline struct hostapd_hw_modes * +wpa_drv_get_hw_feature_data(struct wpa_supplicant *wpa_s, u16 *num_modes, + u16 *flags) +{ + if (wpa_s->driver->get_hw_feature_data) + return wpa_s->driver->get_hw_feature_data(wpa_s->drv_priv, + num_modes, flags); + return NULL; +} + +static inline int wpa_drv_set_country(struct wpa_supplicant *wpa_s, + const char *alpha2) +{ + if (wpa_s->driver->set_country) + return wpa_s->driver->set_country(wpa_s->drv_priv, alpha2); + return 0; +} + +static inline int wpa_drv_send_mlme(struct wpa_supplicant *wpa_s, + const u8 *data, size_t data_len, int noack, + unsigned int freq) +{ + if (wpa_s->driver->send_mlme) + return wpa_s->driver->send_mlme(wpa_s->drv_priv, + data, data_len, noack, + freq); + return -1; +} + +static inline int wpa_drv_update_ft_ies(struct wpa_supplicant *wpa_s, + const u8 *md, + const u8 *ies, size_t ies_len) +{ + if (wpa_s->driver->update_ft_ies) + return wpa_s->driver->update_ft_ies(wpa_s->drv_priv, md, + ies, ies_len); + return -1; +} + +static inline int wpa_drv_set_ap(struct wpa_supplicant *wpa_s, + struct wpa_driver_ap_params *params) +{ + if (wpa_s->driver->set_ap) + return wpa_s->driver->set_ap(wpa_s->drv_priv, params); + return -1; +} + +static inline int wpa_drv_sta_add(struct wpa_supplicant *wpa_s, + struct hostapd_sta_add_params *params) +{ + if (wpa_s->driver->sta_add) + return wpa_s->driver->sta_add(wpa_s->drv_priv, params); + return -1; +} + +static inline int wpa_drv_sta_remove(struct wpa_supplicant *wpa_s, + const u8 *addr) +{ + if (wpa_s->driver->sta_remove) + return wpa_s->driver->sta_remove(wpa_s->drv_priv, addr); + return -1; +} + +static inline int wpa_drv_hapd_send_eapol(struct wpa_supplicant *wpa_s, + const u8 *addr, const u8 *data, + size_t data_len, int encrypt, + const u8 *own_addr, u32 flags) +{ + if (wpa_s->driver->hapd_send_eapol) + return wpa_s->driver->hapd_send_eapol(wpa_s->drv_priv, addr, + data, data_len, encrypt, + own_addr, flags); + return -1; +} + +static inline int wpa_drv_sta_set_flags(struct wpa_supplicant *wpa_s, + const u8 *addr, int total_flags, + int flags_or, int flags_and) +{ + if (wpa_s->driver->sta_set_flags) + return wpa_s->driver->sta_set_flags(wpa_s->drv_priv, addr, + total_flags, flags_or, + flags_and); + return -1; +} + +static inline int wpa_drv_set_supp_port(struct wpa_supplicant *wpa_s, + int authorized) +{ + if (wpa_s->driver->set_supp_port) { + return wpa_s->driver->set_supp_port(wpa_s->drv_priv, + authorized); + } + return 0; +} + +static inline int wpa_drv_send_action(struct wpa_supplicant *wpa_s, + unsigned int freq, + unsigned int wait, + const u8 *dst, const u8 *src, + const u8 *bssid, + const u8 *data, size_t data_len, + int no_cck) +{ + if (wpa_s->driver->send_action) + return wpa_s->driver->send_action(wpa_s->drv_priv, freq, + wait, dst, src, bssid, + data, data_len, no_cck); + return -1; +} + +static inline void wpa_drv_send_action_cancel_wait(struct wpa_supplicant *wpa_s) +{ + if (wpa_s->driver->send_action_cancel_wait) + wpa_s->driver->send_action_cancel_wait(wpa_s->drv_priv); +} + +static inline int wpa_drv_set_freq(struct wpa_supplicant *wpa_s, + struct hostapd_freq_params *freq) +{ + if (wpa_s->driver->set_freq) + return wpa_s->driver->set_freq(wpa_s->drv_priv, freq); + return -1; +} + +static inline int wpa_drv_if_add(struct wpa_supplicant *wpa_s, + enum wpa_driver_if_type type, + const char *ifname, const u8 *addr, + void *bss_ctx, char *force_ifname, + u8 *if_addr, const char *bridge) +{ + if (wpa_s->driver->if_add) + return wpa_s->driver->if_add(wpa_s->drv_priv, type, ifname, + addr, bss_ctx, NULL, force_ifname, + if_addr, bridge, 0); + return -1; +} + +static inline int wpa_drv_if_remove(struct wpa_supplicant *wpa_s, + enum wpa_driver_if_type type, + const char *ifname) +{ + if (wpa_s->driver->if_remove) + return wpa_s->driver->if_remove(wpa_s->drv_priv, type, ifname); + return -1; +} + +static inline int wpa_drv_remain_on_channel(struct wpa_supplicant *wpa_s, + unsigned int freq, + unsigned int duration) +{ + if (wpa_s->driver->remain_on_channel) + return wpa_s->driver->remain_on_channel(wpa_s->drv_priv, freq, + duration); + return -1; +} + +static inline int wpa_drv_cancel_remain_on_channel( + struct wpa_supplicant *wpa_s) +{ + if (wpa_s->driver->cancel_remain_on_channel) + return wpa_s->driver->cancel_remain_on_channel( + wpa_s->drv_priv); + return -1; +} + +static inline int wpa_drv_probe_req_report(struct wpa_supplicant *wpa_s, + int report) +{ + if (wpa_s->driver->probe_req_report) + return wpa_s->driver->probe_req_report(wpa_s->drv_priv, + report); + return -1; +} + +static inline int wpa_drv_deinit_ap(struct wpa_supplicant *wpa_s) +{ + if (wpa_s->driver->deinit_ap) + return wpa_s->driver->deinit_ap(wpa_s->drv_priv); + return 0; +} + +static inline int wpa_drv_deinit_p2p_cli(struct wpa_supplicant *wpa_s) +{ + if (wpa_s->driver->deinit_p2p_cli) + return wpa_s->driver->deinit_p2p_cli(wpa_s->drv_priv); + return 0; +} + +static inline void wpa_drv_suspend(struct wpa_supplicant *wpa_s) +{ + if (wpa_s->driver->suspend) + wpa_s->driver->suspend(wpa_s->drv_priv); +} + +static inline void wpa_drv_resume(struct wpa_supplicant *wpa_s) +{ + if (wpa_s->driver->resume) + wpa_s->driver->resume(wpa_s->drv_priv); +} + +static inline int wpa_drv_signal_monitor(struct wpa_supplicant *wpa_s, + int threshold, int hysteresis) +{ + if (wpa_s->driver->signal_monitor) + return wpa_s->driver->signal_monitor(wpa_s->drv_priv, + threshold, hysteresis); + return -1; +} + +static inline int wpa_drv_signal_poll(struct wpa_supplicant *wpa_s, + struct wpa_signal_info *si) +{ + if (wpa_s->driver->signal_poll) + return wpa_s->driver->signal_poll(wpa_s->drv_priv, si); + return -1; +} + +static inline int wpa_drv_pktcnt_poll(struct wpa_supplicant *wpa_s, + struct hostap_sta_driver_data *sta) +{ + if (wpa_s->driver->read_sta_data) + return wpa_s->driver->read_sta_data(wpa_s->drv_priv, sta, + wpa_s->bssid); + return -1; +} + +static inline int wpa_drv_set_ap_wps_ie(struct wpa_supplicant *wpa_s, + const struct wpabuf *beacon, + const struct wpabuf *proberesp, + const struct wpabuf *assocresp) +{ + if (!wpa_s->driver->set_ap_wps_ie) + return -1; + return wpa_s->driver->set_ap_wps_ie(wpa_s->drv_priv, beacon, + proberesp, assocresp); +} + +static inline int wpa_drv_get_noa(struct wpa_supplicant *wpa_s, + u8 *buf, size_t buf_len) +{ + if (!wpa_s->driver->get_noa) + return -1; + return wpa_s->driver->get_noa(wpa_s->drv_priv, buf, buf_len); +} + +static inline int wpa_drv_set_p2p_powersave(struct wpa_supplicant *wpa_s, + int legacy_ps, int opp_ps, + int ctwindow) +{ + if (!wpa_s->driver->set_p2p_powersave) + return -1; + return wpa_s->driver->set_p2p_powersave(wpa_s->drv_priv, legacy_ps, + opp_ps, ctwindow); +} + +static inline int wpa_drv_ampdu(struct wpa_supplicant *wpa_s, int ampdu) +{ + if (!wpa_s->driver->ampdu) + return -1; + return wpa_s->driver->ampdu(wpa_s->drv_priv, ampdu); +} + +static inline int wpa_drv_send_tdls_mgmt(struct wpa_supplicant *wpa_s, + const u8 *dst, u8 action_code, + u8 dialog_token, u16 status_code, + u32 peer_capab, int initiator, + const u8 *buf, size_t len) +{ + if (wpa_s->driver->send_tdls_mgmt) { + return wpa_s->driver->send_tdls_mgmt(wpa_s->drv_priv, dst, + action_code, dialog_token, + status_code, peer_capab, + initiator, buf, len); + } + return -1; +} + +static inline int wpa_drv_tdls_oper(struct wpa_supplicant *wpa_s, + enum tdls_oper oper, const u8 *peer) +{ + if (!wpa_s->driver->tdls_oper) + return -1; + return wpa_s->driver->tdls_oper(wpa_s->drv_priv, oper, peer); +} + +#ifdef ANDROID +static inline int wpa_drv_driver_cmd(struct wpa_supplicant *wpa_s, + char *cmd, char *buf, size_t buf_len) +{ + if (!wpa_s->driver->driver_cmd) + return -1; + return wpa_s->driver->driver_cmd(wpa_s->drv_priv, cmd, buf, buf_len); +} +#endif /* ANDROID */ + +static inline void wpa_drv_set_rekey_info(struct wpa_supplicant *wpa_s, + const u8 *kek, size_t kek_len, + const u8 *kck, size_t kck_len, + const u8 *replay_ctr) +{ + if (!wpa_s->driver->set_rekey_info) + return; + wpa_s->driver->set_rekey_info(wpa_s->drv_priv, kek, kek_len, + kck, kck_len, replay_ctr); +} + +static inline int wpa_drv_radio_disable(struct wpa_supplicant *wpa_s, + int disabled) +{ + if (!wpa_s->driver->radio_disable) + return -1; + return wpa_s->driver->radio_disable(wpa_s->drv_priv, disabled); +} + +static inline int wpa_drv_switch_channel(struct wpa_supplicant *wpa_s, + struct csa_settings *settings) +{ + if (!wpa_s->driver->switch_channel) + return -1; + return wpa_s->driver->switch_channel(wpa_s->drv_priv, settings); +} + +static inline int wpa_drv_add_ts(struct wpa_supplicant *wpa_s, u8 tsid, + const u8 *address, u8 user_priority, + u16 admitted_time) +{ + if (!wpa_s->driver->add_tx_ts) + return -1; + return wpa_s->driver->add_tx_ts(wpa_s->drv_priv, tsid, address, + user_priority, admitted_time); +} + +static inline int wpa_drv_del_ts(struct wpa_supplicant *wpa_s, u8 tid, + const u8 *address) +{ + if (!wpa_s->driver->del_tx_ts) + return -1; + return wpa_s->driver->del_tx_ts(wpa_s->drv_priv, tid, address); +} + +static inline int wpa_drv_tdls_enable_channel_switch( + struct wpa_supplicant *wpa_s, const u8 *addr, u8 oper_class, + const struct hostapd_freq_params *freq_params) +{ + if (!wpa_s->driver->tdls_enable_channel_switch) + return -1; + return wpa_s->driver->tdls_enable_channel_switch(wpa_s->drv_priv, addr, + oper_class, + freq_params); +} + +static inline int +wpa_drv_tdls_disable_channel_switch(struct wpa_supplicant *wpa_s, + const u8 *addr) +{ + if (!wpa_s->driver->tdls_disable_channel_switch) + return -1; + return wpa_s->driver->tdls_disable_channel_switch(wpa_s->drv_priv, + addr); +} + +static inline int wpa_drv_wnm_oper(struct wpa_supplicant *wpa_s, + enum wnm_oper oper, const u8 *peer, + u8 *buf, u16 *buf_len) +{ + if (!wpa_s->driver->wnm_oper) + return -1; + return wpa_s->driver->wnm_oper(wpa_s->drv_priv, oper, peer, buf, + buf_len); +} + +static inline int wpa_drv_status(struct wpa_supplicant *wpa_s, + char *buf, size_t buflen) +{ + if (!wpa_s->driver->status) + return -1; + return wpa_s->driver->status(wpa_s->drv_priv, buf, buflen); +} + +static inline int wpa_drv_set_qos_map(struct wpa_supplicant *wpa_s, + const u8 *qos_map_set, u8 qos_map_set_len) +{ + if (!wpa_s->driver->set_qos_map) + return -1; + return wpa_s->driver->set_qos_map(wpa_s->drv_priv, qos_map_set, + qos_map_set_len); +} + +static inline int wpa_drv_wowlan(struct wpa_supplicant *wpa_s, + const struct wowlan_triggers *triggers) +{ + if (!wpa_s->driver->set_wowlan) + return -1; + return wpa_s->driver->set_wowlan(wpa_s->drv_priv, triggers); +} + +static inline int wpa_drv_vendor_cmd(struct wpa_supplicant *wpa_s, + int vendor_id, int subcmd, const u8 *data, + size_t data_len, struct wpabuf *buf) +{ + if (!wpa_s->driver->vendor_cmd) + return -1; + return wpa_s->driver->vendor_cmd(wpa_s->drv_priv, vendor_id, subcmd, + data, data_len, buf); +} + +static inline int wpa_drv_roaming(struct wpa_supplicant *wpa_s, int allowed, + const u8 *bssid) +{ + if (!wpa_s->driver->roaming) + return -1; + return wpa_s->driver->roaming(wpa_s->drv_priv, allowed, bssid); +} + +static inline int wpa_drv_set_mac_addr(struct wpa_supplicant *wpa_s, + const u8 *addr) +{ + if (!wpa_s->driver->set_mac_addr) + return -1; + return wpa_s->driver->set_mac_addr(wpa_s->drv_priv, addr); +} + + +#ifdef CONFIG_MACSEC + +static inline int wpa_drv_macsec_init(struct wpa_supplicant *wpa_s, + struct macsec_init_params *params) +{ + if (!wpa_s->driver->macsec_init) + return -1; + return wpa_s->driver->macsec_init(wpa_s->drv_priv, params); +} + +static inline int wpa_drv_macsec_deinit(struct wpa_supplicant *wpa_s) +{ + if (!wpa_s->driver->macsec_deinit) + return -1; + return wpa_s->driver->macsec_deinit(wpa_s->drv_priv); +} + +static inline int wpa_drv_enable_protect_frames(struct wpa_supplicant *wpa_s, + Boolean enabled) +{ + if (!wpa_s->driver->enable_protect_frames) + return -1; + return wpa_s->driver->enable_protect_frames(wpa_s->drv_priv, enabled); +} + +static inline int wpa_drv_set_replay_protect(struct wpa_supplicant *wpa_s, + Boolean enabled, u32 window) +{ + if (!wpa_s->driver->set_replay_protect) + return -1; + return wpa_s->driver->set_replay_protect(wpa_s->drv_priv, enabled, + window); +} + +static inline int wpa_drv_set_current_cipher_suite(struct wpa_supplicant *wpa_s, + const u8 *cs, size_t cs_len) +{ + if (!wpa_s->driver->set_current_cipher_suite) + return -1; + return wpa_s->driver->set_current_cipher_suite(wpa_s->drv_priv, cs, + cs_len); +} + +static inline int wpa_drv_enable_controlled_port(struct wpa_supplicant *wpa_s, + Boolean enabled) +{ + if (!wpa_s->driver->enable_controlled_port) + return -1; + return wpa_s->driver->enable_controlled_port(wpa_s->drv_priv, enabled); +} + +static inline int wpa_drv_get_receive_lowest_pn(struct wpa_supplicant *wpa_s, + u32 channel, u8 an, + u32 *lowest_pn) +{ + if (!wpa_s->driver->get_receive_lowest_pn) + return -1; + return wpa_s->driver->get_receive_lowest_pn(wpa_s->drv_priv, channel, + an, lowest_pn); +} + +static inline int wpa_drv_get_transmit_next_pn(struct wpa_supplicant *wpa_s, + u32 channel, u8 an, + u32 *next_pn) +{ + if (!wpa_s->driver->get_transmit_next_pn) + return -1; + return wpa_s->driver->get_transmit_next_pn(wpa_s->drv_priv, channel, + an, next_pn); +} + +static inline int wpa_drv_set_transmit_next_pn(struct wpa_supplicant *wpa_s, + u32 channel, u8 an, + u32 next_pn) +{ + if (!wpa_s->driver->set_transmit_next_pn) + return -1; + return wpa_s->driver->set_transmit_next_pn(wpa_s->drv_priv, channel, + an, next_pn); +} + +static inline int wpa_drv_get_available_receive_sc(struct wpa_supplicant *wpa_s, + u32 *channel) +{ + if (!wpa_s->driver->get_available_receive_sc) + return -1; + return wpa_s->driver->get_available_receive_sc(wpa_s->drv_priv, + channel); +} + +static inline int +wpa_drv_create_receive_sc(struct wpa_supplicant *wpa_s, u32 channel, + const u8 *sci_addr, u16 sci_port, + unsigned int conf_offset, int validation) +{ + if (!wpa_s->driver->create_receive_sc) + return -1; + return wpa_s->driver->create_receive_sc(wpa_s->drv_priv, channel, + sci_addr, sci_port, conf_offset, + validation); +} + +static inline int wpa_drv_delete_receive_sc(struct wpa_supplicant *wpa_s, + u32 channel) +{ + if (!wpa_s->driver->delete_receive_sc) + return -1; + return wpa_s->driver->delete_receive_sc(wpa_s->drv_priv, channel); +} + +static inline int wpa_drv_create_receive_sa(struct wpa_supplicant *wpa_s, + u32 channel, u8 an, + u32 lowest_pn, const u8 *sak) +{ + if (!wpa_s->driver->create_receive_sa) + return -1; + return wpa_s->driver->create_receive_sa(wpa_s->drv_priv, channel, an, + lowest_pn, sak); +} + +static inline int wpa_drv_enable_receive_sa(struct wpa_supplicant *wpa_s, + u32 channel, u8 an) +{ + if (!wpa_s->driver->enable_receive_sa) + return -1; + return wpa_s->driver->enable_receive_sa(wpa_s->drv_priv, channel, an); +} + +static inline int wpa_drv_disable_receive_sa(struct wpa_supplicant *wpa_s, + u32 channel, u8 an) +{ + if (!wpa_s->driver->disable_receive_sa) + return -1; + return wpa_s->driver->disable_receive_sa(wpa_s->drv_priv, channel, an); +} + +static inline int +wpa_drv_get_available_transmit_sc(struct wpa_supplicant *wpa_s, u32 *channel) +{ + if (!wpa_s->driver->get_available_transmit_sc) + return -1; + return wpa_s->driver->get_available_transmit_sc(wpa_s->drv_priv, + channel); +} + +static inline int +wpa_drv_create_transmit_sc(struct wpa_supplicant *wpa_s, u32 channel, + const u8 *sci_addr, u16 sci_port, + unsigned int conf_offset) +{ + if (!wpa_s->driver->create_transmit_sc) + return -1; + return wpa_s->driver->create_transmit_sc(wpa_s->drv_priv, channel, + sci_addr, sci_port, + conf_offset); +} + +static inline int wpa_drv_delete_transmit_sc(struct wpa_supplicant *wpa_s, + u32 channel) +{ + if (!wpa_s->driver->delete_transmit_sc) + return -1; + return wpa_s->driver->delete_transmit_sc(wpa_s->drv_priv, channel); +} + +static inline int wpa_drv_create_transmit_sa(struct wpa_supplicant *wpa_s, + u32 channel, u8 an, + u32 next_pn, + Boolean confidentiality, + const u8 *sak) +{ + if (!wpa_s->driver->create_transmit_sa) + return -1; + return wpa_s->driver->create_transmit_sa(wpa_s->drv_priv, channel, an, + next_pn, confidentiality, sak); +} + +static inline int wpa_drv_enable_transmit_sa(struct wpa_supplicant *wpa_s, + u32 channel, u8 an) +{ + if (!wpa_s->driver->enable_transmit_sa) + return -1; + return wpa_s->driver->enable_transmit_sa(wpa_s->drv_priv, channel, an); +} + +static inline int wpa_drv_disable_transmit_sa(struct wpa_supplicant *wpa_s, + u32 channel, u8 an) +{ + if (!wpa_s->driver->disable_transmit_sa) + return -1; + return wpa_s->driver->disable_transmit_sa(wpa_s->drv_priv, channel, an); +} +#endif /* CONFIG_MACSEC */ + +static inline int wpa_drv_setband(struct wpa_supplicant *wpa_s, + enum set_band band) +{ + if (!wpa_s->driver->set_band) + return -1; + return wpa_s->driver->set_band(wpa_s->drv_priv, band); +} + +static inline int wpa_drv_get_pref_freq_list(struct wpa_supplicant *wpa_s, + enum wpa_driver_if_type if_type, + unsigned int *num, + unsigned int *freq_list) +{ + if (!wpa_s->driver->get_pref_freq_list) + return -1; + return wpa_s->driver->get_pref_freq_list(wpa_s->drv_priv, if_type, + num, freq_list); +} + +static inline int wpa_drv_set_prob_oper_freq(struct wpa_supplicant *wpa_s, + unsigned int freq) +{ + if (!wpa_s->driver->set_prob_oper_freq) + return 0; + return wpa_s->driver->set_prob_oper_freq(wpa_s->drv_priv, freq); +} + +#endif /* DRIVER_I_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/events.c b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/events.c new file mode 100755 index 0000000..03d6d9b --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/events.c @@ -0,0 +1,3788 @@ +/* + * WPA Supplicant - Driver event processing + * Copyright (c) 2003-2015, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ +#include "includes.h" +#include "common.h" +#include "eapol_supp/eapol_supp_sm.h" +#include "rsn_supp/wpa.h" +#include "eloop.h" +#include "config.h" +#include "l2_packet/l2_packet.h" +#include "wpa_supplicant_i.h" +#include "driver_i.h" +#include "rsn_supp/preauth.h" +#include "rsn_supp/pmksa_cache.h" +#include "common/wpa_ctrl.h" +#include "ap/hostapd.h" +#include "wnm_sta.h" +#include "notify.h" +#include "common/ieee802_11_defs.h" +#include "common/ieee802_11_common.h" +#include "crypto/random.h" +#include "blacklist.h" +#include "wpas_glue.h" +#include "wps_supplicant.h" +#include "ibss_rsn.h" +#include "sme.h" +#include "gas_query.h" +#include "p2p_supplicant.h" +#include "bgscan.h" +#include "autoscan.h" +#include "bss.h" +#include "scan.h" +#include "offchannel.h" +#include "interworking.h" +#include "mesh.h" +#include "mesh_mpm.h" +#include "wmm_ac.h" + +#include "include.h" +#include "wlan_ui_pub.h" +#include "uart_pub.h" +#include "param_config.h" +#include "config_none.h" + +#ifndef CONFIG_NO_SCAN_PROCESSING +static int wpas_select_network_from_last_scan(struct wpa_supplicant *wpa_s, + int new_scan, int own_request); +#endif /* CONFIG_NO_SCAN_PROCESSING */ + + +static int wpas_temp_disabled(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid) +{ + struct os_reltime now; + + if (ssid == NULL || ssid->disabled_until.sec == 0) + return 0; + + os_get_reltime(&now); + if (ssid->disabled_until.sec > now.sec) + return ssid->disabled_until.sec - now.sec; + + wpas_clear_temp_disabled(wpa_s, ssid, 0); + + return 0; +} + + +/** + * wpas_reenabled_network_time - Time until first network is re-enabled + * @wpa_s: Pointer to wpa_supplicant data + * Returns: If all enabled networks are temporarily disabled, returns the time + * (in sec) until the first network is re-enabled. Otherwise returns 0. + * + * This function is used in case all enabled networks are temporarily disabled, + * in which case it returns the time (in sec) that the first network will be + * re-enabled. The function assumes that at least one network is enabled. + */ +static int wpas_reenabled_network_time(struct wpa_supplicant *wpa_s) +{ + struct wpa_ssid *ssid; + int disabled_for, res = 0; + +#ifdef CONFIG_INTERWORKING + if (wpa_s->conf->auto_interworking && wpa_s->conf->interworking && + wpa_s->conf->cred) + return 0; +#endif /* CONFIG_INTERWORKING */ + + for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { + if (ssid->disabled) + continue; + + disabled_for = wpas_temp_disabled(wpa_s, ssid); + if (!disabled_for) + return 0; + + if (!res || disabled_for < res) + res = disabled_for; + } + + return res; +} + + +void wpas_network_reenabled(void *eloop_ctx, void *timeout_ctx) +{ + struct wpa_supplicant *wpa_s = eloop_ctx; + + if (wpa_s->disconnected || wpa_s->wpa_state != WPA_SCANNING) + return; + + if (wpa_supplicant_fast_associate(wpa_s) != 1) { + wpa_supplicant_cancel_sched_scan(wpa_s); + wpa_supplicant_req_scan(wpa_s, 0, 0); + } +} + + +static struct wpa_bss * wpa_supplicant_get_new_bss( + struct wpa_supplicant *wpa_s, const u8 *bssid) +{ + struct wpa_bss *bss = NULL; + struct wpa_ssid *ssid = wpa_s->current_ssid; + + if (ssid->ssid_len > 0) + bss = wpa_bss_get(wpa_s, bssid, ssid->ssid, ssid->ssid_len); + if (!bss) + bss = wpa_bss_get_bssid(wpa_s, bssid); + + return bss; +} + + +static void wpa_supplicant_update_current_bss(struct wpa_supplicant *wpa_s) +{ + struct wpa_bss *bss = wpa_supplicant_get_new_bss(wpa_s, wpa_s->bssid); + + if (!bss) { + wpa_supplicant_update_scan_results(wpa_s); + + /* Get the BSS from the new scan results */ + bss = wpa_supplicant_get_new_bss(wpa_s, wpa_s->bssid); + } + + if (bss) + wpa_s->current_bss = bss; +} + + +static int wpa_supplicant_select_config(struct wpa_supplicant *wpa_s) +{ + struct wpa_ssid *ssid, *old_ssid; + u8 drv_ssid[SSID_MAX_LEN]; + size_t drv_ssid_len; + int res; + + if (wpa_s->conf->ap_scan == 1 && wpa_s->current_ssid) { + wpa_supplicant_update_current_bss(wpa_s); + + if (wpa_s->current_ssid->ssid_len == 0) + return 0; /* current profile still in use */ + res = wpa_drv_get_ssid(wpa_s, drv_ssid); + if (res < 0) { + wpa_msg(wpa_s, MSG_INFO, + "Failed to read SSID from driver"); + return 0; /* try to use current profile */ + } + drv_ssid_len = res; + + if (drv_ssid_len == wpa_s->current_ssid->ssid_len && + os_memcmp(drv_ssid, wpa_s->current_ssid->ssid, + drv_ssid_len) == 0) + return 0; /* current profile still in use */ + + wpa_msg(wpa_s, MSG_DEBUG, + "Driver-initiated BSS selection changed the SSID to %s", + wpa_ssid_txt(drv_ssid, drv_ssid_len)); + /* continue selecting a new network profile */ + } + + wpa_dbg(wpa_s, MSG_DEBUG, "Select network based on association " + "information"); + ssid = wpa_supplicant_get_ssid(wpa_s); + if (ssid == NULL) { + wpa_msg(wpa_s, MSG_INFO, + "No network configuration found for the current AP"); + return -1; + } + + if (wpas_network_disabled(wpa_s, ssid)) { + wpa_dbg(wpa_s, MSG_DEBUG, "Selected network is disabled"); + return -1; + } + + if (disallowed_bssid(wpa_s, wpa_s->bssid) || + disallowed_ssid(wpa_s, ssid->ssid, ssid->ssid_len)) { + wpa_dbg(wpa_s, MSG_DEBUG, "Selected BSS is disallowed"); + return -1; + } + + res = wpas_temp_disabled(wpa_s, ssid); + if (res > 0) { + wpa_dbg(wpa_s, MSG_DEBUG, "Selected network is temporarily " + "disabled for %d second(s)", res); + return -1; + } + + wpa_dbg(wpa_s, MSG_DEBUG, "Network configuration found for the " + "current AP"); + if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) { + u8 wpa_ie[80]; + size_t wpa_ie_len = sizeof(wpa_ie); + if (wpa_supplicant_set_suites(wpa_s, NULL, ssid, + wpa_ie, &wpa_ie_len) < 0) + wpa_dbg(wpa_s, MSG_DEBUG, "Could not set WPA suites"); + } else { + wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); + } + + if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) + eapol_sm_invalidate_cached_session(wpa_s->eapol); + old_ssid = wpa_s->current_ssid; + wpa_s->current_ssid = ssid; + + wpa_supplicant_update_current_bss(wpa_s); + + wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid); + wpa_supplicant_initiate_eapol(wpa_s); + if (old_ssid != wpa_s->current_ssid) + wpas_notify_network_changed(wpa_s); + + return 0; +} + + +void wpa_supplicant_stop_countermeasures(void *eloop_ctx, void *sock_ctx) +{ + struct wpa_supplicant *wpa_s = eloop_ctx; + + if (wpa_s->countermeasures) { + wpa_s->countermeasures = 0; + wpa_drv_set_countermeasures(wpa_s, 0); + wpa_msg(wpa_s, MSG_INFO, "WPA: TKIP countermeasures stopped"); + + /* + * It is possible that the device is sched scanning, which means + * that a connection attempt will be done only when we receive + * scan results. However, in this case, it would be preferable + * to scan and connect immediately, so cancel the sched_scan and + * issue a regular scan flow. + */ + wpa_supplicant_cancel_sched_scan(wpa_s); + wpa_supplicant_req_scan(wpa_s, 0, 0); + } +} + + +void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s) +{ + int bssid_changed; + + wnm_bss_keep_alive_deinit(wpa_s); + +#ifdef CONFIG_IBSS_RSN + ibss_rsn_deinit(wpa_s->ibss_rsn); + wpa_s->ibss_rsn = NULL; +#endif /* CONFIG_IBSS_RSN */ + +#ifdef CONFIG_AP + wpa_supplicant_ap_deinit(wpa_s); +#endif /* CONFIG_AP */ + + if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) + return; + + wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); + bssid_changed = !is_zero_ether_addr(wpa_s->bssid); + os_memset(wpa_s->bssid, 0, ETH_ALEN); + os_memset(wpa_s->pending_bssid, 0, ETH_ALEN); + sme_clear_on_disassoc(wpa_s); + wpa_s->current_bss = NULL; + wpa_s->assoc_freq = 0; + + if (bssid_changed) + wpas_notify_bssid_changed(wpa_s); + + eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE); + eapol_sm_notify_portValid(wpa_s->eapol, FALSE); + if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) + eapol_sm_notify_eap_success(wpa_s->eapol, FALSE); + wpa_s->ap_ies_from_associnfo = 0; + wpa_s->current_ssid = NULL; + eapol_sm_notify_config(wpa_s->eapol, NULL, NULL); + wpa_s->key_mgmt = 0; + + wpas_rrm_reset(wpa_s); +} + +void wpa_find_assoc_pmkid(struct wpa_supplicant *wpa_s) +{ + struct wpa_ie_data ie; + int pmksa_set = -1; + size_t i; + + if (wpa_sm_parse_own_wpa_ie(wpa_s->wpa, &ie) < 0 || + ie.pmkid == NULL) + return; + + for (i = 0; i < ie.num_pmkid; i++) { + pmksa_set = pmksa_cache_set_current(wpa_s->wpa, + ie.pmkid + i * PMKID_LEN, + NULL, NULL, 0); + if (pmksa_set == 0) { + eapol_sm_notify_pmkid_attempt(wpa_s->eapol); + break; + } + } + + wpa_dbg(wpa_s, MSG_DEBUG, "RSN: PMKID from assoc IE %sfound from " + "PMKSA cache", pmksa_set == 0 ? "" : "not "); +} + +#ifdef CONFIG_FULL_SUPPLICANT +static void wpa_supplicant_event_pmkid_candidate(struct wpa_supplicant *wpa_s, + union wpa_event_data *data) +{ + if (data == NULL) { + wpa_dbg(wpa_s, MSG_DEBUG, "RSN: No data in PMKID candidate " + "event"); + return; + } + wpa_dbg(wpa_s, MSG_DEBUG, "RSN: PMKID candidate event - bssid=" MACSTR + " index=%d preauth=%d", + MAC2STR(data->pmkid_candidate.bssid), + data->pmkid_candidate.index, + data->pmkid_candidate.preauth); + + pmksa_candidate_add(wpa_s->wpa, data->pmkid_candidate.bssid, + data->pmkid_candidate.index, + data->pmkid_candidate.preauth); +} +#endif + +static int wpa_supplicant_dynamic_keys(struct wpa_supplicant *wpa_s) +{ + if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE || + wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) + return 0; + +#ifdef IEEE8021X_EAPOL + if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA && + wpa_s->current_ssid && + !(wpa_s->current_ssid->eapol_flags & + (EAPOL_FLAG_REQUIRE_KEY_UNICAST | + EAPOL_FLAG_REQUIRE_KEY_BROADCAST))) { + /* IEEE 802.1X, but not using dynamic WEP keys (i.e., either + * plaintext or static WEP keys). */ + return 0; + } +#endif /* IEEE8021X_EAPOL */ + + return 1; +} + + +#ifndef CONFIG_NO_SCAN_PROCESSING + +static const u8 * get_ie(u8 *ie_start, int len, u8 ie) +{ + const u8 *end, *pos; + + pos = (const u8 *) ie_start; + end = pos + len; + + while (pos + 1 < end) { + if (pos + 2 + pos[1] > end) + break; + if (pos[0] == ie) + return pos; + pos += 2 + pos[1]; + } + + return NULL; +} + +const u8 * get_vendor_ie(u8 *ie_start, int len, u32 vendor_type) +{ + const u8 *end, *pos; + + pos = (const u8 *) (ie_start); + end = pos + len; + + while (pos + 1 < end) { + if (pos + 2 + pos[1] > end) + break; + if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && + vendor_type == WPA_GET_BE32(&pos[2])) + return pos; + pos += 2 + pos[1]; + } + + return NULL; +} + +int get_security_type_from_ie(u8 *ie_start, int len, u16 caps) +{ + const u8 *rsn_ie, *wpa_ie; + struct wpa_ie_data ie = {0}; + + if ((caps & IEEE80211_CAP_PRIVACY) == 0) + return SECURITY_TYPE_NONE; + + rsn_ie = get_ie(ie_start, len, WLAN_EID_RSN); + if (rsn_ie) { + if (wpa_parse_wpa_ie(rsn_ie, 2 + rsn_ie[1], &ie) == 0) { + if(ie.pairwise_cipher == (WPA_CIPHER_CCMP|WPA_CIPHER_TKIP)) + return SECURITY_TYPE_WPA2_MIXED; + if(ie.pairwise_cipher == WPA_CIPHER_CCMP) + return SECURITY_TYPE_WPA2_AES; + if(ie.pairwise_cipher == WPA_CIPHER_TKIP) + return SECURITY_TYPE_WPA2_TKIP; + } + } + + wpa_ie = get_vendor_ie(ie_start, len, WPA_IE_VENDOR_TYPE); + if (wpa_ie) { + if (wpa_parse_wpa_ie(wpa_ie, 2 + wpa_ie[1], &ie) == 0) { + if(ie.pairwise_cipher == WPA_CIPHER_CCMP) + return SECURITY_TYPE_WPA_AES; + if(ie.pairwise_cipher == WPA_CIPHER_TKIP) + return SECURITY_TYPE_WPA_TKIP; + } + } + + return SECURITY_TYPE_WEP; +} + +static int has_wep_key(struct wpa_ssid *ssid) +{ + int i; + + for (i = 0; i < NUM_WEP_KEYS; i++) { + if (ssid->wep_key_len[i]) + return 1; + } + + return 0; +} + + +static int wpa_supplicant_match_privacy(struct wpa_bss *bss, + struct wpa_ssid *ssid, int wpa) +{ + int privacy = 0; + + if (ssid->mixed_cell) + return 1; + +#ifdef CONFIG_WPS + if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) + return 1; +#endif /* CONFIG_WPS */ + + if (has_wep_key(ssid)) + privacy = 1; + +#ifdef IEEE8021X_EAPOL + if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && + ssid->eapol_flags & (EAPOL_FLAG_REQUIRE_KEY_UNICAST | + EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) + privacy = 1; +#endif /* IEEE8021X_EAPOL */ + + if (wpa_key_mgmt_wpa(ssid->key_mgmt)) + privacy = 1; + + if (ssid->key_mgmt & WPA_KEY_MGMT_OSEN) + privacy = 1; + + if (bss->caps & IEEE80211_CAP_PRIVACY){ + if(!wpa){ + wpa_config_set_wep(ssid); + privacy = 1; + } + return privacy; + } + return !privacy; +} + + +static int wpa_supplicant_ssid_bss_match(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid, + struct wpa_bss *bss) +{ + struct wpa_ie_data ie; + int proto_match = 0; + const u8 *rsn_ie, *wpa_ie; + int ret; + int wep_ok; + + ret = wpas_wps_ssid_bss_match(wpa_s, ssid, bss); + if (ret >= 0) + return ret; + + /* Allow TSN if local configuration accepts WEP use without WPA/WPA2 */ + wep_ok = !wpa_key_mgmt_wpa(ssid->key_mgmt) && + (((ssid->key_mgmt & WPA_KEY_MGMT_NONE) && + ssid->wep_key_len[ssid->wep_tx_keyidx] > 0) || + (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)); + + rsn_ie = wpa_bss_get_ie(bss, WLAN_EID_RSN); + while ((ssid->proto & WPA_PROTO_RSN) && rsn_ie) { + proto_match++; + + if (wpa_parse_wpa_ie(rsn_ie, 2 + rsn_ie[1], &ie)) { + os_null_printf(" skip RSN IE - parse " + "failed\r\n"); + break; + } + + wpa_config_set_wpa(ssid, &ie); + + if (wep_ok && + (ie.group_cipher & (WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104))) + { + os_printf(" selected based on TSN " + "in RSN IE\r\n"); + return 1; + } + + if (!(ie.proto & ssid->proto)) { + os_printf(" skip RSN IE - proto " + "mismatch\r\n"); + break; + } + + if (!(ie.pairwise_cipher & ssid->pairwise_cipher)) { + os_printf(" skip RSN IE - PTK " + "cipher mismatch\r\n"); + break; + } + + if (!(ie.group_cipher & ssid->group_cipher)) { + os_printf(" skip RSN IE - GTK " + "cipher mismatch\r\n"); + break; + } + + if (!(ie.key_mgmt & ssid->key_mgmt)) { + os_printf(" skip RSN IE - key mgmt " + "mismatch\r\n"); + break; + } + +#ifdef CONFIG_IEEE80211W + if (!(ie.capabilities & WPA_CAPABILITY_MFPC) && + wpas_get_ssid_pmf(wpa_s, ssid) == + MGMT_FRAME_PROTECTION_REQUIRED) { + wpa_dbg(wpa_s, MSG_DEBUG, " skip RSN IE - no mgmt " + "frame protection"); + break; + } +#endif /* CONFIG_IEEE80211W */ + + wpa_dbg(wpa_s, MSG_DEBUG, " selected based on RSN IE"); + return 1; + } + + wpa_ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); + while ((ssid->proto & WPA_PROTO_WPA) && wpa_ie) { + proto_match++; + + if (wpa_parse_wpa_ie(wpa_ie, 2 + wpa_ie[1], &ie)) { + wpa_dbg(wpa_s, MSG_DEBUG, " skip WPA IE - parse " + "failed"); + break; + } + + wpa_config_set_wpa(ssid, &ie); + + if (wep_ok && + (ie.group_cipher & (WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104))) + { + wpa_dbg(wpa_s, MSG_DEBUG, " selected based on TSN " + "in WPA IE"); + return 1; + } + + if (!(ie.proto & ssid->proto)) { + wpa_dbg(wpa_s, MSG_DEBUG, " skip WPA IE - proto " + "mismatch"); + break; + } + + if (!(ie.pairwise_cipher & ssid->pairwise_cipher)) { + wpa_dbg(wpa_s, MSG_DEBUG, " skip WPA IE - PTK " + "cipher mismatch"); + break; + } + + if (!(ie.group_cipher & ssid->group_cipher)) { + wpa_dbg(wpa_s, MSG_DEBUG, " skip WPA IE - GTK " + "cipher mismatch"); + break; + } + + if (!(ie.key_mgmt & ssid->key_mgmt)) { + wpa_dbg(wpa_s, MSG_DEBUG, " skip WPA IE - key mgmt " + "mismatch"); + break; + } + + wpa_dbg(wpa_s, MSG_DEBUG, " selected based on WPA IE"); + return 1; + } + + if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && !wpa_ie && + !rsn_ie) { + wpa_dbg(wpa_s, MSG_DEBUG, " allow for non-WPA IEEE 802.1X"); + return 1; + } + + if ((ssid->proto & (WPA_PROTO_WPA | WPA_PROTO_RSN)) && + wpa_key_mgmt_wpa(ssid->key_mgmt) && proto_match == 0) { + wpa_dbg(wpa_s, MSG_DEBUG, " skip - no WPA/RSN proto match"); + return 0; + } + + if ((ssid->key_mgmt & WPA_KEY_MGMT_OSEN) && + wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE)) { + wpa_dbg(wpa_s, MSG_DEBUG, " allow in OSEN"); + return 1; + } + + if (!wpa_key_mgmt_wpa(ssid->key_mgmt)) { + wpa_dbg(wpa_s, MSG_DEBUG, " allow in non-WPA/WPA2"); + return 1; + } + + wpa_dbg(wpa_s, MSG_DEBUG, " reject due to mismatch with " + "WPA/WPA2"); + + return 0; +} + + +static int freq_allowed(int *freqs, int freq) +{ + int i; + + if (freqs == NULL) + return 1; + + for (i = 0; freqs[i]; i++) + if (freqs[i] == freq) + return 1; + return 0; +} + + +static int rate_match(struct wpa_supplicant *wpa_s, struct wpa_bss *bss) +{ + const struct hostapd_hw_modes *mode = NULL, *modes; + const u8 scan_ie[2] = { WLAN_EID_SUPP_RATES, WLAN_EID_EXT_SUPP_RATES }; + const u8 *rate_ie; + int i, j, k; + + if (bss->freq == 0) + return 1; /* Cannot do matching without knowing band */ + + modes = wpa_s->hw.modes; + if (modes == NULL) { + /* + * The driver does not provide any additional information + * about the utilized hardware, so allow the connection attempt + * to continue. + */ + return 1; + } + + for (i = 0; i < wpa_s->hw.num_modes; i++) { + for (j = 0; j < modes[i].num_channels; j++) { + int freq = modes[i].channels[j].freq; + if (freq == bss->freq) { + if (mode && + mode->mode == HOSTAPD_MODE_IEEE80211G) + break; /* do not allow 802.11b replace + * 802.11g */ + mode = &modes[i]; + break; + } + } + } + + if (mode == NULL) + return 0; + + for (i = 0; i < (int) sizeof(scan_ie); i++) { + rate_ie = wpa_bss_get_ie(bss, scan_ie[i]); + if (rate_ie == NULL) + continue; + + for (j = 2; j < rate_ie[1] + 2; j++) { + int flagged = !!(rate_ie[j] & 0x80); + int r = (rate_ie[j] & 0x7f) * 5; + + /* + * IEEE Std 802.11n-2009 7.3.2.2: + * The new BSS Membership selector value is encoded + * like a legacy basic rate, but it is not a rate and + * only indicates if the BSS members are required to + * support the mandatory features of Clause 20 [HT PHY] + * in order to join the BSS. + */ + if (flagged && ((rate_ie[j] & 0x7f) == + BSS_MEMBERSHIP_SELECTOR_HT_PHY)) { + if (!ht_supported(mode)) { + wpa_dbg(wpa_s, MSG_DEBUG, + " hardware does not support " + "HT PHY"); + return 0; + } + continue; + } + + /* There's also a VHT selector for 802.11ac */ + if (flagged && ((rate_ie[j] & 0x7f) == + BSS_MEMBERSHIP_SELECTOR_VHT_PHY)) { + if (!vht_supported(mode)) { + wpa_dbg(wpa_s, MSG_DEBUG, + " hardware does not support " + "VHT PHY"); + return 0; + } + continue; + } + + if (!flagged) + continue; + + /* check for legacy basic rates */ + for (k = 0; k < mode->num_rates; k++) { + if (mode->rates[k] == r) + break; + } + if (k == mode->num_rates) { + /* + * IEEE Std 802.11-2007 7.3.2.2 demands that in + * order to join a BSS all required rates + * have to be supported by the hardware. + */ + wpa_dbg(wpa_s, MSG_DEBUG, + " hardware does not support required rate %d.%d Mbps (freq=%d mode==%d num_rates=%d)", + r / 10, r % 10, + bss->freq, mode->mode, mode->num_rates); + return 0; + } + } + } + + return 1; +} + + +/* + * Test whether BSS is in an ESS. + * This is done differently in DMG (60 GHz) and non-DMG bands + */ +static int bss_is_ess(struct wpa_bss *bss) +{ + if (bss_is_dmg(bss)) { + return (bss->caps & IEEE80211_CAP_DMG_MASK) == + IEEE80211_CAP_DMG_AP; + } + + return ((bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) == + IEEE80211_CAP_ESS); +} + + +static int match_mac_mask(const u8 *addr_a, const u8 *addr_b, const u8 *mask) +{ + size_t i; + + for (i = 0; i < ETH_ALEN; i++) { + if ((addr_a[i] & mask[i]) != (addr_b[i] & mask[i])) + return 0; + } + return 1; +} + + +static int addr_in_list(const u8 *addr, const u8 *list, size_t num) +{ + size_t i; + + for (i = 0; i < num; i++) { + const u8 *a = list + i * ETH_ALEN * 2; + const u8 *m = a + ETH_ALEN; + + if (match_mac_mask(a, addr, m)) + return 1; + } + return 0; +} + + +static struct wpa_ssid * wpa_scan_res_match(struct wpa_supplicant *wpa_s, + int i, struct wpa_bss *bss, + struct wpa_ssid *group, + int only_first_ssid) +{ + u8 wpa_ie_len, rsn_ie_len; + int wpa; + struct wpa_blacklist *e; + const u8 *ie; + struct wpa_ssid *ssid; + int osen; + + ie = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); + wpa_ie_len = ie ? ie[1] : 0; + + ie = wpa_bss_get_ie(bss, WLAN_EID_RSN); + rsn_ie_len = ie ? ie[1] : 0; + + ie = wpa_bss_get_vendor_ie(bss, OSEN_IE_VENDOR_TYPE); + osen = ie != NULL; + + wpa_dbg(wpa_s, MSG_DEBUG, "%d: " MACSTR " ssid='%s' " + "wpa_ie_len=%u rsn_ie_len=%u caps=0x%x level=%d freq=%d %s%s%s", + i, MAC2STR(bss->bssid), wpa_ssid_txt(bss->ssid, bss->ssid_len), + wpa_ie_len, rsn_ie_len, bss->caps, bss->level, bss->freq, + wpa_bss_get_vendor_ie(bss, WPS_IE_VENDOR_TYPE) ? " wps" : "", + (wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) || + wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE)) ? + " p2p" : "", + osen ? " osen=1" : ""); + + e = wpa_blacklist_get(wpa_s, bss->bssid); + if (e) { + int limit = 1; + if (wpa_supplicant_enabled_networks(wpa_s) == 1) { + /* + * When only a single network is enabled, we can + * trigger blacklisting on the first failure. This + * should not be done with multiple enabled networks to + * avoid getting forced to move into a worse ESS on + * single error if there are no other BSSes of the + * current ESS. + */ + limit = 0; + } + if (e->count > limit) { + wpa_dbg(wpa_s, MSG_DEBUG, " skip - blacklisted " + "(count=%d limit=%d)", e->count, limit); + return NULL; + } + } + + if (bss->ssid_len == 0) { + wpa_dbg(wpa_s, MSG_DEBUG, " skip - SSID not known"); + return NULL; + } + + if (disallowed_bssid(wpa_s, bss->bssid)) { + wpa_dbg(wpa_s, MSG_DEBUG, " skip - BSSID disallowed"); + return NULL; + } + + if (disallowed_ssid(wpa_s, bss->ssid, bss->ssid_len)) { + wpa_dbg(wpa_s, MSG_DEBUG, " skip - SSID disallowed"); + return NULL; + } + + wpa = wpa_ie_len > 0 || rsn_ie_len > 0; + + for (ssid = group; ssid; ssid = only_first_ssid ? NULL : ssid->pnext) { + int check_ssid = wpa ? 1 : (ssid->ssid_len != 0); + int res; + + if (wpas_network_disabled(wpa_s, ssid)) { + wpa_dbg(wpa_s, MSG_DEBUG, " skip - disabled"); + continue; + } + + res = wpas_temp_disabled(wpa_s, ssid); + if (res > 0) { + wpa_dbg(wpa_s, MSG_DEBUG, " skip - disabled " + "temporarily for %d second(s)", res); + continue; + } + +#ifdef CONFIG_WPS + if ((ssid->key_mgmt & WPA_KEY_MGMT_WPS) && e && e->count > 0) { + wpa_dbg(wpa_s, MSG_DEBUG, " skip - blacklisted " + "(WPS)"); + continue; + } + + if (wpa && ssid->ssid_len == 0 && + wpas_wps_ssid_wildcard_ok(wpa_s, ssid, bss)) + check_ssid = 0; + + if (!wpa && (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) { + /* Only allow wildcard SSID match if an AP + * advertises active WPS operation that matches + * with our mode. */ + check_ssid = 1; + if (ssid->ssid_len == 0 && + wpas_wps_ssid_wildcard_ok(wpa_s, ssid, bss)) + check_ssid = 0; + } +#endif /* CONFIG_WPS */ + + if (ssid->bssid_set && ssid->ssid_len == 0 && + os_memcmp(bss->bssid, ssid->bssid, ETH_ALEN) == 0) + check_ssid = 0; + + if (check_ssid && + (bss->ssid_len != ssid->ssid_len || + os_memcmp(bss->ssid, ssid->ssid, bss->ssid_len) != 0)) { + wpa_dbg(wpa_s, MSG_DEBUG, " skip - SSID mismatch"); + continue; + } + + if(!wpa && + (os_memcmp(bss->ssid, ssid->ssid, bss->ssid_len) == 0)){ + wpa_config_set_none(ssid); + } + + if (ssid->bssid_set && + os_memcmp(bss->bssid, ssid->bssid, ETH_ALEN) != 0) { + wpa_dbg(wpa_s, MSG_DEBUG, " skip - BSSID mismatch"); + continue; + } + + /* check blacklist */ + if (ssid->num_bssid_blacklist && + addr_in_list(bss->bssid, ssid->bssid_blacklist, + ssid->num_bssid_blacklist)) { + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - BSSID blacklisted"); + continue; + } + + /* if there is a whitelist, only accept those APs */ + if (ssid->num_bssid_whitelist && + !addr_in_list(bss->bssid, ssid->bssid_whitelist, + ssid->num_bssid_whitelist)) { + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - BSSID not in whitelist"); + continue; + } + + if (!wpa_supplicant_ssid_bss_match(wpa_s, ssid, bss)) + continue; + + if (!osen && !wpa && + !(ssid->key_mgmt & WPA_KEY_MGMT_NONE) && + !(ssid->key_mgmt & WPA_KEY_MGMT_WPS) && + !(ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)) { + wpa_dbg(wpa_s, MSG_DEBUG, " skip - non-WPA network " + "not allowed"); + continue; + } + + if (wpa && !wpa_key_mgmt_wpa(ssid->key_mgmt) && + has_wep_key(ssid)) { + wpa_dbg(wpa_s, MSG_DEBUG, " skip - ignore WPA/WPA2 AP for WEP network block"); + continue; + } + + if ((ssid->key_mgmt & WPA_KEY_MGMT_OSEN) && !osen) { + wpa_dbg(wpa_s, MSG_DEBUG, " skip - non-OSEN network " + "not allowed"); + continue; + } + + if (!wpa_supplicant_match_privacy(bss, ssid, wpa)) { + wpa_dbg(wpa_s, MSG_DEBUG, " skip - privacy " + "mismatch"); + continue; + } + + if (!bss_is_ess(bss)) { + wpa_dbg(wpa_s, MSG_DEBUG, " skip - not ESS network"); + continue; + } + + if (!freq_allowed(ssid->freq_list, bss->freq)) { + wpa_dbg(wpa_s, MSG_DEBUG, " skip - frequency not " + "allowed"); + continue; + } + + if (!rate_match(wpa_s, bss)) { + wpa_dbg(wpa_s, MSG_DEBUG, " skip - rate sets do " + "not match"); + continue; + } + +#ifdef CONFIG_P2P + if (ssid->p2p_group && + !wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE) && + !wpa_bss_get_vendor_ie_beacon(bss, P2P_IE_VENDOR_TYPE)) { + wpa_dbg(wpa_s, MSG_DEBUG, " skip - no P2P IE seen"); + continue; + } + + if (!is_zero_ether_addr(ssid->go_p2p_dev_addr)) { + struct wpabuf *p2p_ie; + u8 dev_addr[ETH_ALEN]; + + ie = wpa_bss_get_vendor_ie(bss, P2P_IE_VENDOR_TYPE); + if (ie == NULL) { + wpa_dbg(wpa_s, MSG_DEBUG, " skip - no P2P element"); + continue; + } + p2p_ie = wpa_bss_get_vendor_ie_multi( + bss, P2P_IE_VENDOR_TYPE); + if (p2p_ie == NULL) { + wpa_dbg(wpa_s, MSG_DEBUG, " skip - could not fetch P2P element"); + continue; + } + + if (p2p_parse_dev_addr_in_p2p_ie(p2p_ie, dev_addr) < 0 + || os_memcmp(dev_addr, ssid->go_p2p_dev_addr, + ETH_ALEN) != 0) { + wpa_dbg(wpa_s, MSG_DEBUG, " skip - no matching GO P2P Device Address in P2P element"); + wpabuf_free(p2p_ie); + continue; + } + wpabuf_free(p2p_ie); + } + + /* + * TODO: skip the AP if its P2P IE has Group Formation + * bit set in the P2P Group Capability Bitmap and we + * are not in Group Formation with that device. + */ +#endif /* CONFIG_P2P */ + + if (os_reltime_before(&bss->last_update, &wpa_s->scan_min_time)) + { + struct os_reltime diff; + + os_reltime_sub(&wpa_s->scan_min_time, + &bss->last_update, &diff); + wpa_dbg(wpa_s, MSG_DEBUG, + " skip - scan result not recent enough (%u.%06u seconds too old)", + (unsigned int) diff.sec, + (unsigned int) diff.usec); + continue; + } + + /* Matching configuration found */ + return ssid; + } + + /* No matching configuration found */ + return NULL; +} + + +static struct wpa_bss * +wpa_supplicant_select_bss(struct wpa_supplicant *wpa_s, + struct wpa_ssid *group, + struct wpa_ssid **selected_ssid, + int only_first_ssid) +{ + unsigned int i; + + if (only_first_ssid) + wpa_dbg(wpa_s, MSG_DEBUG, "Try to find BSS matching pre-selected network id=%d", + group->id); + else + wpa_dbg(wpa_s, MSG_DEBUG, "Selecting BSS from priority group %d", + group->priority); + + for (i = 0; i < wpa_s->last_scan_res_used; i++) { + struct wpa_bss *bss = wpa_s->last_scan_res[i]; + *selected_ssid = wpa_scan_res_match(wpa_s, i, bss, group, + only_first_ssid); + if (!*selected_ssid) + continue; + wpa_dbg(wpa_s, MSG_DEBUG, " selected BSS " MACSTR + " ssid='%s'", + MAC2STR(bss->bssid), + wpa_ssid_txt(bss->ssid, bss->ssid_len)); + return bss; + } + + return NULL; +} + +struct wpa_bss * wpa_supplicant_pick_network(struct wpa_supplicant *wpa_s, + struct wpa_ssid **selected_ssid) +{ + struct wpa_bss *selected = NULL; + int prio; + struct wpa_ssid *next_ssid = NULL; + struct wpa_ssid *ssid; + + if (wpa_s->last_scan_res == NULL || + wpa_s->last_scan_res_used == 0) + return NULL; /* no scan results from last update */ + + if (wpa_s->next_ssid) { + /* check that next_ssid is still valid */ + for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { + if (ssid == wpa_s->next_ssid) + break; + } + next_ssid = ssid; + wpa_s->next_ssid = NULL; + } + + while (selected == NULL) { + for (prio = 0; prio < wpa_s->conf->num_prio; prio++) { + if (next_ssid && next_ssid->priority == + wpa_s->conf->pssid[prio]->priority) { + selected = wpa_supplicant_select_bss( + wpa_s, next_ssid, selected_ssid, 1); + if (selected) + break; + } + selected = wpa_supplicant_select_bss( + wpa_s, wpa_s->conf->pssid[prio], + selected_ssid, 0); + if (selected) + break; + } + + if (selected == NULL && wpa_s->blacklist && + !wpa_s->countermeasures) { + wpa_dbg(wpa_s, MSG_DEBUG, "No APs found - clear " + "blacklist and try again"); + wpa_blacklist_clear(wpa_s); + wpa_s->blacklist_cleared++; + } else if (selected == NULL) + break; + } + + ssid = *selected_ssid; + if (selected && ssid && ssid->mem_only_psk && !ssid->psk_set && + !ssid->passphrase && !ssid->ext_psk) { + const char *field_name, *txt = NULL; + + wpa_dbg(wpa_s, MSG_DEBUG, + "PSK/passphrase not yet available for the selected network"); + + wpas_notify_network_request(wpa_s, ssid, + WPA_CTRL_REQ_PSK_PASSPHRASE, NULL); + + field_name = wpa_supplicant_ctrl_req_to_string( + WPA_CTRL_REQ_PSK_PASSPHRASE, NULL, &txt); + if (field_name == NULL) + return NULL; + + wpas_send_ctrl_req(wpa_s, ssid, field_name, txt); + + selected = NULL; + } + + return selected; +} + +extern void mhdr_set_station_status_when_reconnect_over(void); +void wpa_supplicant_rescan_terminal(void) +{ + mhdr_set_station_status_when_reconnect_over(); +} + +static void wpa_supplicant_req_new_scan(struct wpa_supplicant *wpa_s, + int timeout_sec, int timeout_usec) +{ + if (!wpa_supplicant_enabled_networks(wpa_s)) { + /* + * No networks are enabled; short-circuit request so + * we don't wait timeout seconds before transitioning + * to INACTIVE state. + */ + wpa_dbg(wpa_s, MSG_DEBUG, "Short-circuit new scan request " + "since there are no enabled networks"); + wpa_supplicant_set_state(wpa_s, WPA_INACTIVE); + return; + } + + wpa_s->scan_for_connection = 1; + wpa_supplicant_req_scan(wpa_s, timeout_sec, timeout_usec); +} + + +int wpa_supplicant_connect(struct wpa_supplicant *wpa_s, + struct wpa_bss *selected, + struct wpa_ssid *ssid) +{ + os_null_printf("wpa_supplicant_connect\r\n"); + if (wpas_wps_scan_pbc_overlap(wpa_s, selected, ssid)) { + wpa_msg(wpa_s, MSG_INFO, WPS_EVENT_OVERLAP + "PBC session overlap"); + wpas_notify_wps_event_pbc_overlap(wpa_s); +#ifdef CONFIG_P2P + if (wpa_s->p2p_group_interface == P2P_GROUP_INTERFACE_CLIENT || + wpa_s->p2p_in_provisioning) { + eloop_register_timeout(0, 0, wpas_p2p_pbc_overlap_cb, + wpa_s, NULL); + return -1; + } +#endif /* CONFIG_P2P */ + +#ifdef CONFIG_WPS + wpas_wps_pbc_overlap(wpa_s); + wpas_wps_cancel(wpa_s); +#endif /* CONFIG_WPS */ + return -1; + } + + wpa_msg(wpa_s, MSG_DEBUG, + "Considering connect request: reassociate: %d selected: " + MACSTR " bssid: " MACSTR " pending: " MACSTR + " wpa_state: %s ssid=%p current_ssid=%p", + wpa_s->reassociate, MAC2STR(selected->bssid), + MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid), + wpa_supplicant_state_txt(wpa_s->wpa_state), + ssid, wpa_s->current_ssid); + + /* + * Do not trigger new association unless the BSSID has changed or if + * reassociation is requested. If we are in process of associating with + * the selected BSSID, do not trigger new attempt. + */ + if (wpa_s->reassociate || + (os_memcmp(selected->bssid, wpa_s->bssid, ETH_ALEN) != 0 && + ((wpa_s->wpa_state != WPA_ASSOCIATING && + wpa_s->wpa_state != WPA_AUTHENTICATING) || + (!is_zero_ether_addr(wpa_s->pending_bssid) && + os_memcmp(selected->bssid, wpa_s->pending_bssid, ETH_ALEN) != + 0) || + (is_zero_ether_addr(wpa_s->pending_bssid) && + ssid != wpa_s->current_ssid)))) { + wpa_msg(wpa_s, MSG_DEBUG, "Request association with " MACSTR, + MAC2STR(selected->bssid)); + wpa_supplicant_associate(wpa_s, selected, ssid); + } else { + wpa_dbg(wpa_s, MSG_DEBUG, "Already associated or trying to " + "connect with the selected AP"); + } + + return 0; +} + + +static struct wpa_ssid * +wpa_supplicant_pick_new_network(struct wpa_supplicant *wpa_s) +{ + int prio; + struct wpa_ssid *ssid; + + for (prio = 0; prio < wpa_s->conf->num_prio; prio++) { + for (ssid = wpa_s->conf->pssid[prio]; ssid; ssid = ssid->pnext) + { + if (wpas_network_disabled(wpa_s, ssid)) + continue; + if (ssid->mode == IEEE80211_MODE_IBSS || + ssid->mode == IEEE80211_MODE_AP || + ssid->mode == IEEE80211_MODE_MESH) + return ssid; + } + } + return NULL; +} + + +/* TODO: move the rsn_preauth_scan_result*() to be called from notify.c based + * on BSS added and BSS changed events */ +static void wpa_supplicant_rsn_preauth_scan_results( + struct wpa_supplicant *wpa_s) +{ + struct wpa_bss *bss; + + if (rsn_preauth_scan_results(wpa_s->wpa) < 0) + return; + + dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { + const u8 *ssid, *rsn; + + ssid = wpa_bss_get_ie(bss, WLAN_EID_SSID); + if (ssid == NULL) + continue; + + rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN); + if (rsn == NULL) + continue; + + rsn_preauth_scan_result(wpa_s->wpa, bss->bssid, ssid, rsn); + } + +} + + +static int wpa_supplicant_need_to_roam(struct wpa_supplicant *wpa_s, + struct wpa_bss *selected, + struct wpa_ssid *ssid) +{ + struct wpa_bss *current_bss = NULL; +#ifndef CONFIG_NO_ROAMING + int min_diff; +#endif /* CONFIG_NO_ROAMING */ + + if (wpa_s->reassociate) + return 1; /* explicit request to reassociate */ + if (wpa_s->wpa_state < WPA_ASSOCIATED) + return 1; /* we are not associated; continue */ + if (wpa_s->current_ssid == NULL) + return 1; /* unknown current SSID */ + if (wpa_s->current_ssid != ssid) + return 1; /* different network block */ + + if (wpas_driver_bss_selection(wpa_s)) + return 0; /* Driver-based roaming */ + + if (wpa_s->current_ssid->ssid) + current_bss = wpa_bss_get(wpa_s, wpa_s->bssid, + wpa_s->current_ssid->ssid, + wpa_s->current_ssid->ssid_len); + if (!current_bss) + current_bss = wpa_bss_get_bssid(wpa_s, wpa_s->bssid); + + if (!current_bss) + return 1; /* current BSS not seen in scan results */ + + if (current_bss == selected) + return 0; + + if (selected->last_update_idx > current_bss->last_update_idx) + return 1; /* current BSS not seen in the last scan */ + +#ifndef CONFIG_NO_ROAMING + wpa_dbg(wpa_s, MSG_DEBUG, "Considering within-ESS reassociation"); + wpa_dbg(wpa_s, MSG_DEBUG, "Current BSS: " MACSTR + " level=%d snr=%d est_throughput=%u", + MAC2STR(current_bss->bssid), current_bss->level, + current_bss->snr, current_bss->est_throughput); + wpa_dbg(wpa_s, MSG_DEBUG, "Selected BSS: " MACSTR + " level=%d snr=%d est_throughput=%u", + MAC2STR(selected->bssid), selected->level, + selected->snr, selected->est_throughput); + + if (wpa_s->current_ssid->bssid_set && + os_memcmp(selected->bssid, wpa_s->current_ssid->bssid, ETH_ALEN) == + 0) { + wpa_dbg(wpa_s, MSG_DEBUG, "Allow reassociation - selected BSS " + "has preferred BSSID"); + return 1; + } + + if (selected->est_throughput > current_bss->est_throughput + 5000) { + wpa_dbg(wpa_s, MSG_DEBUG, + "Allow reassociation - selected BSS has better estimated throughput"); + return 1; + } + + if (current_bss->level < 0 && current_bss->level > selected->level) { + wpa_dbg(wpa_s, MSG_DEBUG, "Skip roam - Current BSS has better " + "signal level"); + return 0; + } + + min_diff = 2; + if (current_bss->level < 0) { + if (current_bss->level < -85) + min_diff = 1; + else if (current_bss->level < -80) + min_diff = 2; + else if (current_bss->level < -75) + min_diff = 3; + else if (current_bss->level < -70) + min_diff = 4; + else + min_diff = 5; + } + if (abs(current_bss->level - selected->level) < min_diff) { + wpa_dbg(wpa_s, MSG_DEBUG, "Skip roam - too small difference " + "in signal level"); + return 0; + } + + return 1; +#else /* CONFIG_NO_ROAMING */ + return 0; +#endif /* CONFIG_NO_ROAMING */ +} + + +/* Return != 0 if no scan results could be fetched or if scan results should not + * be shared with other virtual interfaces. */ +static int _wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s, + union wpa_event_data *data, + int own_request) +{ + struct wpa_scan_results *scan_res = NULL; + int ret = 0; + int ap = 0; +#ifndef CONFIG_NO_RANDOM_POOL + size_t i, num; +#endif /* CONFIG_NO_RANDOM_POOL */ + +#ifdef CONFIG_AP + if (wpa_s->ap_iface) + ap = 1; +#endif /* CONFIG_AP */ + + wpa_supplicant_notify_scanning(wpa_s, 0); + + scan_res = wpa_supplicant_get_scan_results(wpa_s, + data ? &data->scan_info : + NULL, 1); + if (scan_res == NULL) { + if (wpa_s->conf->ap_scan == 2 || ap || + wpa_s->scan_res_handler == scan_only_handler) + return -1; + if (!own_request) + return -1; + + os_printf("Failed to get scan results, retry cnt=%d\r\n", + g_sta_param_ptr->retry_cnt); + if(g_sta_param_ptr->retry_cnt) + { + wpa_supplicant_req_new_scan(wpa_s, 1, 0); + } + else + { + wpa_supplicant_rescan_terminal(); + } + + ret = -1; + goto scan_work_done; + } + +#ifndef CONFIG_NO_RANDOM_POOL + num = scan_res->num; + if (num > 10) + num = 10; + for (i = 0; i < num; i++) { + u8 buf[5]; + struct wpa_scan_res *res = scan_res->res[i]; + buf[0] = res->bssid[5]; + buf[1] = res->qual & 0xff; + buf[2] = res->noise & 0xff; + buf[3] = res->level & 0xff; + buf[4] = res->tsf & 0xff; + random_add_randomness(buf, sizeof(buf)); + } +#endif /* CONFIG_NO_RANDOM_POOL */ + + if (own_request && wpa_s->scan_res_handler && + (wpa_s->own_scan_running || !wpa_s->radio->external_scan_running)) { + void (*scan_res_handler)(struct wpa_supplicant *wpa_s, + struct wpa_scan_results *scan_res); + + scan_res_handler = wpa_s->scan_res_handler; + wpa_s->scan_res_handler = NULL; + scan_res_handler(wpa_s, scan_res); + ret = -2; + goto scan_work_done; + } + + if (ap) { + wpa_dbg(wpa_s, MSG_DEBUG, "Ignore scan results in AP mode"); +#ifdef CONFIG_AP + if (wpa_s->ap_iface->scan_cb) + wpa_s->ap_iface->scan_cb(wpa_s->ap_iface); +#endif /* CONFIG_AP */ + goto scan_work_done; + } + + wpa_dbg(wpa_s, MSG_DEBUG, "New scan results available (own=%u ext=%u)", + wpa_s->own_scan_running, wpa_s->radio->external_scan_running); + if (wpa_s->last_scan_req == MANUAL_SCAN_REQ && + wpa_s->manual_scan_use_id && wpa_s->own_scan_running) { + wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_SCAN_RESULTS "id=%u", + wpa_s->manual_scan_id); + wpa_s->manual_scan_use_id = 0; + } else { + wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_SCAN_RESULTS); + } + wpas_notify_scan_results(wpa_s); + + wpas_notify_scan_done(wpa_s, 1); + + if (!wpa_s->own_scan_running && wpa_s->radio->external_scan_running) { + wpa_dbg(wpa_s, MSG_DEBUG, "Do not use results from externally requested scan operation for network selection"); + wpa_scan_results_free(scan_res); + return 0; + } + + if (wnm_scan_process(wpa_s, 1) > 0) + goto scan_work_done; + + if (sme_proc_obss_scan(wpa_s) > 0) + goto scan_work_done; + + if ((wpa_s->conf->ap_scan == 2 && !wpas_wps_searching(wpa_s))) + goto scan_work_done; + + if (autoscan_notify_scan(wpa_s, scan_res)) + goto scan_work_done; + + if (wpa_s->disconnected) { + wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); + os_printf("Failed to get scan results - disconnect\r\n"); + ret = -3; + goto scan_work_done; + } + + if (!wpas_driver_bss_selection(wpa_s) && + bgscan_notify_scan(wpa_s, scan_res) == 1) + goto scan_work_done; + + wpas_wps_update_ap_info(wpa_s, scan_res); + + wpa_scan_results_free(scan_res); + + if (wpa_s->scan_work) { + struct wpa_radio_work *work = wpa_s->scan_work; + wpa_s->scan_work = NULL; + radio_work_done(work); + } + + return wpas_select_network_from_last_scan(wpa_s, 1, own_request); + +scan_work_done: + wpa_scan_results_free(scan_res); + if (wpa_s->scan_work) { + struct wpa_radio_work *work = wpa_s->scan_work; + wpa_s->scan_work = NULL; + radio_work_done(work); + } + return ret; +} + + +static int wpas_select_network_from_last_scan(struct wpa_supplicant *wpa_s, + int new_scan, int own_request) +{ + struct wpa_bss *selected; + struct wpa_ssid *ssid = NULL; + int time_to_reenable = wpas_reenabled_network_time(wpa_s); + + if (time_to_reenable > 0) { + os_null_printf("Postpone network selection by %d seconds since all networks are disabled\r\n", + time_to_reenable); + eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL); + eloop_register_timeout(time_to_reenable, 0, + wpas_network_reenabled, wpa_s, NULL); + return 0; + } + + if (wpa_s->p2p_mgmt) + return 0; /* no normal connection on p2p_mgmt interface */ + + selected = wpa_supplicant_pick_network(wpa_s, &ssid); + if (selected) { + int skip; + skip = !wpa_supplicant_need_to_roam(wpa_s, selected, ssid); + if (skip) { + if (new_scan) + wpa_supplicant_rsn_preauth_scan_results(wpa_s); + return 0; + } + + if (wpa_supplicant_connect(wpa_s, selected, ssid) < 0) { + os_printf("Connect failed\r\n"); + return -1; + } + if (new_scan) + wpa_supplicant_rsn_preauth_scan_results(wpa_s); + /* + * Do not notify other virtual radios of scan results since we do not + * want them to start other associations at the same time. + */ + return 1; + } else { +#ifdef CONFIG_MESH + if (wpa_s->ifmsh) { + wpa_msg(wpa_s, MSG_INFO, + "Avoiding join because we already joined a mesh group"); + return 0; + } +#endif /* CONFIG_MESH */ + os_printf("No suitable network found\r\n"); + + extern u8 supplicant_main_is_exit(void); + // if del sta command has send, return; + if(supplicant_main_is_exit()) + { + // wpa_global_ptr is null, may be del vif + return 2; + } + + ssid = wpa_supplicant_pick_new_network(wpa_s); + if (ssid) { + os_null_printf("Setup a new network\r\n"); + wpa_supplicant_associate(wpa_s, NULL, ssid); + if (new_scan) + wpa_supplicant_rsn_preauth_scan_results(wpa_s); + } else if (own_request) { + /* + * No SSID found. If SCAN results are as a result of + * own scan request and not due to a scan request on + * another shared interface, try another scan. + */ + int timeout_sec = wpa_s->scan_interval; + int timeout_usec = 0; +#ifdef CONFIG_P2P + int res; + + res = wpas_p2p_scan_no_go_seen(wpa_s); + if (res == 2) + return 2; + if (res == 1) + return 0; + + if (wpa_s->p2p_in_provisioning || + wpa_s->show_group_started || + wpa_s->p2p_in_invitation) { + /* + * Use shorter wait during P2P Provisioning + * state and during P2P join-a-group operation + * to speed up group formation. + */ + timeout_sec = 0; + timeout_usec = 250000; + wpa_supplicant_req_new_scan(wpa_s, timeout_sec, + timeout_usec); + return 0; + } +#endif /* CONFIG_P2P */ +#ifdef CONFIG_INTERWORKING + if (wpa_s->conf->auto_interworking && + wpa_s->conf->interworking && + wpa_s->conf->cred) { + wpa_dbg(wpa_s, MSG_DEBUG, "Interworking: " + "start ANQP fetch since no matching " + "networks found"); + wpa_s->network_select = 1; + wpa_s->auto_network_select = 1; + interworking_start_fetch_anqp(wpa_s); + return 1; + } +#endif /* CONFIG_INTERWORKING */ +#ifdef CONFIG_WPS + if (wpa_s->after_wps > 0 || wpas_wps_searching(wpa_s)) { + wpa_dbg(wpa_s, MSG_DEBUG, "Use shorter wait during WPS processing"); + timeout_sec = 0; + timeout_usec = 500000; + wpa_supplicant_req_new_scan(wpa_s, timeout_sec, + timeout_usec); + return 0; + } +#endif /* CONFIG_WPS */ + if (wpa_supplicant_req_sched_scan(wpa_s)) + wpa_supplicant_req_new_scan(wpa_s, timeout_sec, + timeout_usec); + + wpa_msg_ctrl(wpa_s, MSG_INFO, + WPA_EVENT_NETWORK_NOT_FOUND); + } + } + return 0; +} + + +static int wpa_supplicant_event_scan_results(struct wpa_supplicant *wpa_s, + union wpa_event_data *data) +{ + struct wpa_supplicant *ifs; + int res; + + res = _wpa_supplicant_event_scan_results(wpa_s, data, 1); + if (res == 2) { + /* + * Interface may have been removed, so must not dereference + * wpa_s after this. + */ + os_null_printf("Interface may removed\r\n"); + return 1; + } + if (res != 0) { + /* + * If no scan results could be fetched, then no need to + * notify those interfaces that did not actually request + * this scan. Similarly, if scan results started a new operation on this + * interface, do not notify other interfaces to avoid concurrent + * operations during a connection attempt. + */ + return 0; + } + + /* + * Check other interfaces to see if they share the same radio. If + * so, they get updated with this same scan info. + */ + dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant, + radio_list) { + if (ifs != wpa_s) { + wpa_printf(MSG_DEBUG, "%s: Updating scan results from " + "sibling", ifs->ifname); + _wpa_supplicant_event_scan_results(ifs, data, 0); + } + } + + return 0; +} + +#endif /* CONFIG_NO_SCAN_PROCESSING */ + + +int wpa_supplicant_fast_associate(struct wpa_supplicant *wpa_s) +{ +#ifdef CONFIG_NO_SCAN_PROCESSING + return -1; +#else /* CONFIG_NO_SCAN_PROCESSING */ + struct os_reltime now; + + if (wpa_s->last_scan_res_used == 0) + return -1; + + os_get_reltime(&now); + if (os_reltime_expired(&now, &wpa_s->last_scan, 5)) { + wpa_printf(MSG_DEBUG, "Fast associate: Old scan results"); + return -1; + } + + return wpas_select_network_from_last_scan(wpa_s, 0, 1); +#endif /* CONFIG_NO_SCAN_PROCESSING */ +} + +#ifdef CONFIG_WNM + +static void wnm_bss_keep_alive(void *eloop_ctx, void *sock_ctx) +{ + struct wpa_supplicant *wpa_s = eloop_ctx; + + if (wpa_s->wpa_state < WPA_ASSOCIATED) + return; + + if (!wpa_s->no_keep_alive) { + wpa_printf(MSG_DEBUG, "WNM: Send keep-alive to AP " MACSTR, + MAC2STR(wpa_s->bssid)); + /* TODO: could skip this if normal data traffic has been sent */ + /* TODO: Consider using some more appropriate data frame for + * this */ + if (wpa_s->l2) + l2_packet_send(wpa_s->l2, wpa_s->bssid, 0x0800, + (u8 *) "", 0); + } + +#ifdef CONFIG_SME + if (wpa_s->sme.bss_max_idle_period) { + unsigned int msec; + msec = wpa_s->sme.bss_max_idle_period * 1024; /* times 1000 */ + if (msec > 100) + msec -= 100; + eloop_register_timeout(msec / 1000, msec % 1000 * 1000, + wnm_bss_keep_alive, wpa_s, NULL); + } +#endif /* CONFIG_SME */ +} + + +static void wnm_process_assoc_resp(struct wpa_supplicant *wpa_s, + const u8 *ies, size_t ies_len) +{ + struct ieee802_11_elems elems; + + if (ies == NULL) + return; + + if (ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed) + return; + +#ifdef CONFIG_SME + if (elems.bss_max_idle_period) { + unsigned int msec; + wpa_s->sme.bss_max_idle_period = + WPA_GET_LE16(elems.bss_max_idle_period); + wpa_printf(MSG_DEBUG, "WNM: BSS Max Idle Period: %u (* 1000 " + "TU)%s", wpa_s->sme.bss_max_idle_period, + (elems.bss_max_idle_period[2] & 0x01) ? + " (protected keep-live required)" : ""); + if (wpa_s->sme.bss_max_idle_period == 0) + wpa_s->sme.bss_max_idle_period = 1; + if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) { + eloop_cancel_timeout(wnm_bss_keep_alive, wpa_s, NULL); + /* msec times 1000 */ + msec = wpa_s->sme.bss_max_idle_period * 1024; + if (msec > 100) + msec -= 100; + eloop_register_timeout(msec / 1000, msec % 1000 * 1000, + wnm_bss_keep_alive, wpa_s, + NULL); + } + } +#endif /* CONFIG_SME */ +} + +#endif /* CONFIG_WNM */ + + +void wnm_bss_keep_alive_deinit(struct wpa_supplicant *wpa_s) +{ +#ifdef CONFIG_WNM + eloop_cancel_timeout(wnm_bss_keep_alive, wpa_s, NULL); +#endif /* CONFIG_WNM */ +} + + +#ifdef CONFIG_INTERWORKING + +static int wpas_qos_map_set(struct wpa_supplicant *wpa_s, const u8 *qos_map, + size_t len) +{ + int res; + + wpa_hexdump(MSG_DEBUG, "Interworking: QoS Map Set", qos_map, len); + res = wpa_drv_set_qos_map(wpa_s, qos_map, len); + if (res) { + wpa_printf(MSG_DEBUG, "Interworking: Failed to configure QoS Map Set to the driver"); + } + + return res; +} + + +static void interworking_process_assoc_resp(struct wpa_supplicant *wpa_s, + const u8 *ies, size_t ies_len) +{ + struct ieee802_11_elems elems; + + if (ies == NULL) + return; + + if (ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed) + return; + + if (elems.qos_map_set) { + wpas_qos_map_set(wpa_s, elems.qos_map_set, + elems.qos_map_set_len); + } +} +#endif /* CONFIG_INTERWORKING */ + +int wpa_supplicant_event_associnfo(struct wpa_supplicant *wpa_s, + union wpa_event_data *data) +{ + int l, len, found = 0, wpa_found, rsn_found; + const u8 *p; +#ifdef CONFIG_IEEE80211R + u8 bssid[ETH_ALEN]; +#endif /* CONFIG_IEEE80211R */ + + wpa_dbg(wpa_s, MSG_DEBUG, "Association info event"); + if (data->assoc_info.req_ies) + wpa_hexdump(MSG_DEBUG, "req_ies", data->assoc_info.req_ies, + data->assoc_info.req_ies_len); + if (data->assoc_info.resp_ies) { + wpa_hexdump(MSG_DEBUG, "resp_ies", data->assoc_info.resp_ies, + data->assoc_info.resp_ies_len); +#ifdef CONFIG_TDLS + wpa_tdls_assoc_resp_ies(wpa_s->wpa, data->assoc_info.resp_ies, + data->assoc_info.resp_ies_len); +#endif /* CONFIG_TDLS */ +#ifdef CONFIG_WNM + wnm_process_assoc_resp(wpa_s, data->assoc_info.resp_ies, + data->assoc_info.resp_ies_len); +#endif /* CONFIG_WNM */ +#ifdef CONFIG_INTERWORKING + interworking_process_assoc_resp(wpa_s, data->assoc_info.resp_ies, + data->assoc_info.resp_ies_len); +#endif /* CONFIG_INTERWORKING */ + } + if (data->assoc_info.beacon_ies) + wpa_hexdump(MSG_DEBUG, "beacon_ies", + data->assoc_info.beacon_ies, + data->assoc_info.beacon_ies_len); + if (data->assoc_info.freq) + wpa_dbg(wpa_s, MSG_DEBUG, "freq=%u MHz", + data->assoc_info.freq); + + p = data->assoc_info.req_ies; + l = data->assoc_info.req_ies_len; + + /* Go through the IEs and make a copy of the WPA/RSN IE, if present. */ + while (p && l >= 2) { + len = p[1] + 2; + if (len > l) { + wpa_hexdump(MSG_DEBUG, "Truncated IE in assoc_info", + p, l); + break; + } + if ((p[0] == WLAN_EID_VENDOR_SPECIFIC && p[1] >= 6 && + (os_memcmp(&p[2], "\x00\x50\xF2\x01\x01\x00", 6) == 0)) || + (p[0] == WLAN_EID_RSN && p[1] >= 2)) { + if (wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, p, len)) + break; + found = 1; + wpa_find_assoc_pmkid(wpa_s); + break; + } + l -= len; + p += len; + } + if (!found && data->assoc_info.req_ies) + wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0); + +#ifdef CONFIG_IEEE80211R +#ifdef CONFIG_SME + if (wpa_s->sme.auth_alg == WPA_AUTH_ALG_FT) { + if (wpa_drv_get_bssid(wpa_s, bssid) < 0 || + wpa_ft_validate_reassoc_resp(wpa_s->wpa, + data->assoc_info.resp_ies, + data->assoc_info.resp_ies_len, + bssid) < 0) { + wpa_dbg(wpa_s, MSG_DEBUG, "FT: Validation of " + "Reassociation Response failed"); + wpa_supplicant_deauthenticate( + wpa_s, WLAN_REASON_INVALID_IE); + return -1; + } + } + + p = data->assoc_info.resp_ies; + l = data->assoc_info.resp_ies_len; + +#ifdef CONFIG_WPS_STRICT + if (p && wpa_s->current_ssid && + wpa_s->current_ssid->key_mgmt == WPA_KEY_MGMT_WPS) { + struct wpabuf *wps; + wps = ieee802_11_vendor_ie_concat(p, l, WPS_IE_VENDOR_TYPE); + if (wps == NULL) { + wpa_msg(wpa_s, MSG_INFO, "WPS-STRICT: AP did not " + "include WPS IE in (Re)Association Response"); + return -1; + } + + if (wps_validate_assoc_resp(wps) < 0) { + wpabuf_free(wps); + wpa_supplicant_deauthenticate( + wpa_s, WLAN_REASON_INVALID_IE); + return -1; + } + wpabuf_free(wps); + } +#endif /* CONFIG_WPS_STRICT */ + + /* Go through the IEs and make a copy of the MDIE, if present. */ + while (p && l >= 2) { + len = p[1] + 2; + if (len > l) { + wpa_hexdump(MSG_DEBUG, "Truncated IE in assoc_info", + p, l); + break; + } + if (p[0] == WLAN_EID_MOBILITY_DOMAIN && + p[1] >= MOBILITY_DOMAIN_ID_LEN) { + wpa_s->sme.ft_used = 1; + os_memcpy(wpa_s->sme.mobility_domain, p + 2, + MOBILITY_DOMAIN_ID_LEN); + break; + } + l -= len; + p += len; + } +#endif /* CONFIG_SME */ + + /* Process FT when SME is in the driver */ + if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) && + wpa_ft_is_completed(wpa_s->wpa)) { + if (wpa_drv_get_bssid(wpa_s, bssid) < 0 || + wpa_ft_validate_reassoc_resp(wpa_s->wpa, + data->assoc_info.resp_ies, + data->assoc_info.resp_ies_len, + bssid) < 0) { + wpa_dbg(wpa_s, MSG_DEBUG, "FT: Validation of " + "Reassociation Response failed"); + wpa_supplicant_deauthenticate( + wpa_s, WLAN_REASON_INVALID_IE); + return -1; + } + wpa_dbg(wpa_s, MSG_DEBUG, "FT: Reassociation Response done"); + } + + wpa_sm_set_ft_params(wpa_s->wpa, data->assoc_info.resp_ies, + data->assoc_info.resp_ies_len); +#endif /* CONFIG_IEEE80211R */ + + /* WPA/RSN IE from Beacon/ProbeResp */ + p = data->assoc_info.beacon_ies; + l = data->assoc_info.beacon_ies_len; + + /* Go through the IEs and make a copy of the WPA/RSN IEs, if present. + */ + wpa_found = rsn_found = 0; + while (p && l >= 2) { + len = p[1] + 2; + if (len > l) { + wpa_hexdump(MSG_DEBUG, "Truncated IE in beacon_ies", + p, l); + break; + } + if (!wpa_found && + p[0] == WLAN_EID_VENDOR_SPECIFIC && p[1] >= 6 && + os_memcmp(&p[2], "\x00\x50\xF2\x01\x01\x00", 6) == 0) { + wpa_found = 1; + wpa_sm_set_ap_wpa_ie(wpa_s->wpa, p, len); + } + + if (!rsn_found && + p[0] == WLAN_EID_RSN && p[1] >= 2) { + rsn_found = 1; + wpa_sm_set_ap_rsn_ie(wpa_s->wpa, p, len); + } + + l -= len; + p += len; + } + + if (!wpa_found && data->assoc_info.beacon_ies) + wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0); + if (!rsn_found && data->assoc_info.beacon_ies) + wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0); + if (wpa_found || rsn_found) + wpa_s->ap_ies_from_associnfo = 1; + +#ifdef CONFIG_FST + wpabuf_free(wpa_s->received_mb_ies); + wpa_s->received_mb_ies = NULL; + if (wpa_s->fst) { + struct mb_ies_info mb_ies; + + wpa_printf(MSG_DEBUG, "Looking for MB IE"); + if (!mb_ies_info_by_ies(&mb_ies, data->assoc_info.resp_ies, + data->assoc_info.resp_ies_len)) + wpa_s->received_mb_ies = mb_ies_by_info(&mb_ies); + } +#endif /* CONFIG_FST */ + + if (wpa_s->assoc_freq && data->assoc_info.freq && + wpa_s->assoc_freq != data->assoc_info.freq) { + wpa_printf(MSG_DEBUG, "Operating frequency changed from " + "%u to %u MHz", + wpa_s->assoc_freq, data->assoc_info.freq); + wpa_supplicant_update_scan_results(wpa_s); + } + + wpa_s->assoc_freq = data->assoc_info.freq; + + return 0; +} + +static int wpa_supplicant_assoc_update_ie(struct wpa_supplicant *wpa_s) +{ + const u8 *bss_wpa = NULL, *bss_rsn = NULL; + + if (!wpa_s->current_bss || !wpa_s->current_ssid) + return -1; + + if (!wpa_key_mgmt_wpa_any(wpa_s->current_ssid->key_mgmt)) + return 0; + + bss_wpa = wpa_bss_get_vendor_ie(wpa_s->current_bss, + WPA_IE_VENDOR_TYPE); + bss_rsn = wpa_bss_get_ie(wpa_s->current_bss, WLAN_EID_RSN); + + if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa, + bss_wpa ? 2 + bss_wpa[1] : 0) || + wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn, + bss_rsn ? 2 + bss_rsn[1] : 0)) + return -1; + + return 0; +} + + +static void wpa_supplicant_event_assoc(struct wpa_supplicant *wpa_s, + union wpa_event_data *data) +{ + u8 bssid[ETH_ALEN]; + int ft_completed; + int new_bss = 0; + +#ifdef CONFIG_AP + if (wpa_s->ap_iface) { + if (!data) + return; + hostapd_notif_assoc(wpa_s->ap_iface->bss[0], + data->assoc_info.addr, + data->assoc_info.req_ies, + data->assoc_info.req_ies_len, + data->assoc_info.reassoc); + return; + } +#endif /* CONFIG_AP */ + + eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL); + + ft_completed = wpa_ft_is_completed(wpa_s->wpa); + if (data && wpa_supplicant_event_associnfo(wpa_s, data) < 0) + return; + + if (wpa_drv_get_bssid(wpa_s, bssid) < 0) { + wpa_dbg(wpa_s, MSG_ERROR, "Failed to get BSSID"); + wpa_supplicant_deauthenticate( + wpa_s, WLAN_REASON_DEAUTH_LEAVING); + return; + } + + wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATED); + if (os_memcmp(bssid, wpa_s->bssid, ETH_ALEN) != 0) { + wpa_dbg(wpa_s, MSG_DEBUG, "Associated to a new BSS: BSSID=" + MACSTR, MAC2STR(bssid)); + new_bss = 1; + random_add_randomness(bssid, ETH_ALEN); + os_memcpy(wpa_s->bssid, bssid, ETH_ALEN); + os_memset(wpa_s->pending_bssid, 0, ETH_ALEN); + wpas_notify_bssid_changed(wpa_s); + + if (wpa_supplicant_dynamic_keys(wpa_s) && !ft_completed) { + wpa_clear_keys(wpa_s, bssid); + } + if (wpa_supplicant_select_config(wpa_s) < 0) { + wpa_supplicant_deauthenticate( + wpa_s, WLAN_REASON_DEAUTH_LEAVING); + return; + } + } + + if (wpa_s->conf->ap_scan == 1 && + (0 != (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION))) { + if (wpa_supplicant_assoc_update_ie(wpa_s) < 0 && new_bss) + wpa_msg(wpa_s, MSG_WARNING, + "WPA/RSN IEs not updated"); + } + +#ifdef CONFIG_SME + os_memcpy(wpa_s->sme.prev_bssid, bssid, ETH_ALEN); + wpa_s->sme.prev_bssid_set = 1; + wpa_s->sme.last_unprot_disconnect.sec = 0; +#endif /* CONFIG_SME */ + + wpa_msg(wpa_s, MSG_INFO, "Associated with " MACSTR, MAC2STR(bssid)); + wpa_sm_notify_assoc(wpa_s->wpa, bssid); + if (wpa_s->l2) + l2_packet_notify_auth_start(wpa_s->l2); + + /* + * Set portEnabled first to FALSE in order to get EAP state machine out + * of the SUCCESS state and eapSuccess cleared. Without this, EAPOL PAE + * state machine may transit to AUTHENTICATING state based on obsolete + * eapSuccess and then trigger BE_AUTH to SUCCESS and PAE to + * AUTHENTICATED without ever giving chance to EAP state machine to + * reset the state. + */ + if (!ft_completed) { + eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE); + eapol_sm_notify_portValid(wpa_s->eapol, FALSE); + } + if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) || ft_completed) + eapol_sm_notify_eap_success(wpa_s->eapol, FALSE); + /* 802.1X::portControl = Auto */ + eapol_sm_notify_portEnabled(wpa_s->eapol, TRUE); + wpa_s->eapol_received = 0; + + if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE || + wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE || + (wpa_s->current_ssid && + wpa_s->current_ssid->mode == IEEE80211_MODE_IBSS)) { + if (wpa_s->current_ssid && + wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE && + (wpa_s->drv_flags & + WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE)) { + /* + * Set the key after having received joined-IBSS event + * from the driver. + */ + wpa_supplicant_set_wpa_none_key(wpa_s, + wpa_s->current_ssid); + } + wpa_supplicant_cancel_auth_timeout(wpa_s); + wpa_supplicant_set_state(wpa_s, WPA_COMPLETED); + } else if (!ft_completed) { + /* Timeout for receiving the first EAPOL packet */ + wpa_supplicant_req_auth_timeout(wpa_s, 10, 0); + } + wpa_supplicant_cancel_scan(wpa_s); + + if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) && + wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) { + /* + * We are done; the driver will take care of RSN 4-way + * handshake. + */ + wpa_supplicant_cancel_auth_timeout(wpa_s); + wpa_supplicant_set_state(wpa_s, WPA_COMPLETED); + eapol_sm_notify_portValid(wpa_s->eapol, TRUE); + eapol_sm_notify_eap_success(wpa_s->eapol, TRUE); + } else if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) && + wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) { + /* + * The driver will take care of RSN 4-way handshake, so we need + * to allow EAPOL supplicant to complete its work without + * waiting for WPA supplicant. + */ + eapol_sm_notify_portValid(wpa_s->eapol, TRUE); + } else if (ft_completed) { + /* + * FT protocol completed - make sure EAPOL state machine ends + * up in authenticated. + */ + wpa_supplicant_cancel_auth_timeout(wpa_s); + wpa_supplicant_set_state(wpa_s, WPA_COMPLETED); + eapol_sm_notify_portValid(wpa_s->eapol, TRUE); + eapol_sm_notify_eap_success(wpa_s->eapol, TRUE); + } + + wpa_s->last_eapol_matches_bssid = 0; + + if (wpa_s->pending_eapol_rx) { + struct os_reltime now, age; + os_get_reltime(&now); + os_reltime_sub(&now, &wpa_s->pending_eapol_rx_time, &age); + if (age.sec == 0 && age.usec < 100000 && + os_memcmp(wpa_s->pending_eapol_rx_src, bssid, ETH_ALEN) == + 0) { + wpa_dbg(wpa_s, MSG_DEBUG, "Process pending EAPOL " + "frame that was received just before " + "association notification"); + wpa_supplicant_rx_eapol( + wpa_s, wpa_s->pending_eapol_rx_src, + wpabuf_head(wpa_s->pending_eapol_rx), + wpabuf_len(wpa_s->pending_eapol_rx)); + } + wpabuf_free(wpa_s->pending_eapol_rx); + wpa_s->pending_eapol_rx = NULL; + } + + if ((wpa_s->key_mgmt == WPA_KEY_MGMT_NONE || + wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) && + wpa_s->current_ssid && + (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC_DONE)) { + /* Set static WEP keys again */ + wpa_set_wep_keys(wpa_s, wpa_s->current_ssid); + } + +#ifdef CONFIG_IBSS_RSN + if (wpa_s->current_ssid && + wpa_s->current_ssid->mode == WPAS_MODE_IBSS && + wpa_s->key_mgmt != WPA_KEY_MGMT_NONE && + wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE && + wpa_s->ibss_rsn == NULL) { + wpa_s->ibss_rsn = ibss_rsn_init(wpa_s); + if (!wpa_s->ibss_rsn) { + wpa_msg(wpa_s, MSG_INFO, "Failed to init IBSS RSN"); + wpa_supplicant_deauthenticate( + wpa_s, WLAN_REASON_DEAUTH_LEAVING); + return; + } + + ibss_rsn_set_psk(wpa_s->ibss_rsn, wpa_s->current_ssid->psk); + } +#endif /* CONFIG_IBSS_RSN */ + + wpas_wps_notify_assoc(wpa_s, bssid); + + if (data) { + wmm_ac_notify_assoc(wpa_s, data->assoc_info.resp_ies, + data->assoc_info.resp_ies_len, + &data->assoc_info.wmm_params); + + if (wpa_s->reassoc_same_bss) + wmm_ac_restore_tspecs(wpa_s); + } +} + + +static int disconnect_reason_recoverable(u16 reason_code) +{ + return reason_code == WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY || + reason_code == WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA || + reason_code == WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA; +} + + +static void wpa_supplicant_event_disassoc(struct wpa_supplicant *wpa_s, + u16 reason_code, + int locally_generated) +{ + const u8 *bssid; + + if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) { + /* + * At least Host AP driver and a Prism3 card seemed to be + * generating streams of disconnected events when configuring + * IBSS for WPA-None. Ignore them for now. + */ + return; + } + + bssid = wpa_s->bssid; + if (is_zero_ether_addr(bssid)) + bssid = wpa_s->pending_bssid; + + if (!is_zero_ether_addr(bssid) || + wpa_s->wpa_state >= WPA_AUTHENTICATING) { + wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_DISCONNECTED "bssid=" MACSTR + " reason=%d%s", + MAC2STR(bssid), reason_code, + locally_generated ? " locally_generated=1" : ""); + } +} + + +static int could_be_psk_mismatch(struct wpa_supplicant *wpa_s, u16 reason_code, + int locally_generated) +{ + if (wpa_s->wpa_state != WPA_4WAY_HANDSHAKE || + !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) + return 0; /* Not in 4-way handshake with PSK */ + + /* + * It looks like connection was lost while trying to go through PSK + * 4-way handshake. Filter out known disconnection cases that are caused + * by something else than PSK mismatch to avoid confusing reports. + */ + + if (locally_generated) { + if (reason_code == WLAN_REASON_IE_IN_4WAY_DIFFERS) + return 0; + } + + return 1; +} + + +static void wpa_supplicant_event_disassoc_finish(struct wpa_supplicant *wpa_s, + u16 reason_code, + int locally_generated) +{ + const u8 *bssid; + int authenticating; + u8 prev_pending_bssid[ETH_ALEN]; + struct wpa_bss *fast_reconnect = NULL; + struct wpa_ssid *fast_reconnect_ssid = NULL; + struct wpa_ssid *last_ssid; + + authenticating = wpa_s->wpa_state == WPA_AUTHENTICATING; + os_memcpy(prev_pending_bssid, wpa_s->pending_bssid, ETH_ALEN); + + if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) { + /* + * At least Host AP driver and a Prism3 card seemed to be + * generating streams of disconnected events when configuring + * IBSS for WPA-None. Ignore them for now. + */ + wpa_dbg(wpa_s, MSG_DEBUG, "Disconnect event - ignore in " + "IBSS/WPA-None mode"); + return; + } + + if (could_be_psk_mismatch(wpa_s, reason_code, locally_generated)) { + wpa_msg(wpa_s, MSG_INFO, "WPA: 4-Way Handshake failed - " + "pre-shared key may be incorrect"); + if (wpas_p2p_4way_hs_failed(wpa_s) > 0) + return; /* P2P group removed */ + wpas_auth_failed(wpa_s, "WRONG_KEY"); + } + if (!wpa_s->disconnected && + (!wpa_s->auto_reconnect_disabled || + wpa_s->key_mgmt == WPA_KEY_MGMT_WPS || + wpas_wps_searching(wpa_s))) { + wpa_dbg(wpa_s, MSG_DEBUG, "Auto connect enabled: try to " + "reconnect (wps=%d/%d wpa_state=%d)", + wpa_s->key_mgmt == WPA_KEY_MGMT_WPS, + wpas_wps_searching(wpa_s), + wpa_s->wpa_state); + if (wpa_s->wpa_state == WPA_COMPLETED && + wpa_s->current_ssid && + wpa_s->current_ssid->mode == WPAS_MODE_INFRA && + !locally_generated && + disconnect_reason_recoverable(reason_code)) { + /* + * It looks like the AP has dropped association with + * us, but could allow us to get back in. Try to + * reconnect to the same BSS without full scan to save + * time for some common cases. + */ + fast_reconnect = wpa_s->current_bss; + fast_reconnect_ssid = wpa_s->current_ssid; + } else if (wpa_s->wpa_state >= WPA_ASSOCIATING) + wpa_supplicant_req_scan(wpa_s, 0, 100000); + else + wpa_dbg(wpa_s, MSG_DEBUG, "Do not request new " + "immediate scan"); + } else { + wpa_dbg(wpa_s, MSG_DEBUG, "Auto connect disabled: do not " + "try to re-connect"); + wpa_s->reassociate = 0; + wpa_s->disconnected = 1; + if (!wpa_s->pno) + wpa_supplicant_cancel_sched_scan(wpa_s); + } + bssid = wpa_s->bssid; + if (is_zero_ether_addr(bssid)) + bssid = wpa_s->pending_bssid; + if (wpa_s->wpa_state >= WPA_AUTHENTICATING) + wpas_connection_failed(wpa_s, bssid); + wpa_sm_notify_disassoc(wpa_s->wpa); + if (locally_generated) + wpa_s->disconnect_reason = -reason_code; + else + wpa_s->disconnect_reason = reason_code; + wpas_notify_disconnect_reason(wpa_s); + if (wpa_supplicant_dynamic_keys(wpa_s)) { + wpa_dbg(wpa_s, MSG_DEBUG, "Disconnect event - remove keys"); + wpa_clear_keys(wpa_s, wpa_s->bssid); + } + last_ssid = wpa_s->current_ssid; + wpa_supplicant_mark_disassoc(wpa_s); + + if (authenticating && (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME)) { + sme_disassoc_while_authenticating(wpa_s, prev_pending_bssid); + wpa_s->current_ssid = last_ssid; + } + + if (fast_reconnect && + !wpas_network_disabled(wpa_s, fast_reconnect_ssid) && + !disallowed_bssid(wpa_s, fast_reconnect->bssid) && + !disallowed_ssid(wpa_s, fast_reconnect->ssid, + fast_reconnect->ssid_len) && + !wpas_temp_disabled(wpa_s, fast_reconnect_ssid)) { +#ifndef CONFIG_NO_SCAN_PROCESSING + wpa_dbg(wpa_s, MSG_DEBUG, "Try to reconnect to the same BSS"); + if (wpa_supplicant_connect(wpa_s, fast_reconnect, + fast_reconnect_ssid) < 0) { + /* Recover through full scan */ + wpa_supplicant_req_scan(wpa_s, 0, 100000); + } +#endif /* CONFIG_NO_SCAN_PROCESSING */ + } else if (fast_reconnect) { + /* + * Could not reconnect to the same BSS due to network being + * disabled. Use a new scan to match the alternative behavior + * above, i.e., to continue automatic reconnection attempt in a + * way that enforces disabled network rules. + */ + wpa_supplicant_req_scan(wpa_s, 0, 100000); + } +} + + +#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT +void wpa_supplicant_delayed_mic_error_report(void *eloop_ctx, void *sock_ctx) +{ + struct wpa_supplicant *wpa_s = eloop_ctx; + + if (!wpa_s->pending_mic_error_report) + return; + + wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Sending pending MIC error report"); + wpa_sm_key_request(wpa_s->wpa, 1, wpa_s->pending_mic_error_pairwise); + wpa_s->pending_mic_error_report = 0; +} +#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */ + +#ifdef CONFIG_FULL_SUPPLICANT +static void +wpa_supplicant_event_michael_mic_failure(struct wpa_supplicant *wpa_s, + union wpa_event_data *data) +{ + int pairwise; + struct os_reltime t; + + wpa_msg(wpa_s, MSG_WARNING, "Michael MIC failure detected"); + pairwise = (data && data->michael_mic_failure.unicast); + os_get_reltime(&t); + if ((wpa_s->last_michael_mic_error.sec && + !os_reltime_expired(&t, &wpa_s->last_michael_mic_error, 60)) || + wpa_s->pending_mic_error_report) { + if (wpa_s->pending_mic_error_report) { + /* + * Send the pending MIC error report immediately since + * we are going to start countermeasures and AP better + * do the same. + */ + wpa_sm_key_request(wpa_s->wpa, 1, + wpa_s->pending_mic_error_pairwise); + } + + /* Send the new MIC error report immediately since we are going + * to start countermeasures and AP better do the same. + */ + wpa_sm_key_request(wpa_s->wpa, 1, pairwise); + + /* initialize countermeasures */ + wpa_s->countermeasures = 1; + + wpa_blacklist_add(wpa_s, wpa_s->bssid); + + wpa_msg(wpa_s, MSG_WARNING, "TKIP countermeasures started"); + + /* + * Need to wait for completion of request frame. We do not get + * any callback for the message completion, so just wait a + * short while and hope for the best. */ + os_sleep(0, 10000); + + wpa_drv_set_countermeasures(wpa_s, 1); + wpa_supplicant_deauthenticate(wpa_s, + WLAN_REASON_MICHAEL_MIC_FAILURE); + eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, + wpa_s, NULL); + eloop_register_timeout(60, 0, + wpa_supplicant_stop_countermeasures, + wpa_s, NULL); + /* TODO: mark the AP rejected for 60 second. STA is + * allowed to associate with another AP.. */ + } else { +#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT + if (wpa_s->mic_errors_seen) { + /* + * Reduce the effectiveness of Michael MIC error + * reports as a means for attacking against TKIP if + * more than one MIC failure is noticed with the same + * PTK. We delay the transmission of the reports by a + * random time between 0 and 60 seconds in order to + * force the attacker wait 60 seconds before getting + * the information on whether a frame resulted in a MIC + * failure. + */ + u8 rval[4]; + int sec; + + if (os_get_random(rval, sizeof(rval)) < 0) + sec = os_random() % 60; + else + sec = WPA_GET_BE32(rval) % 60; + wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Delay MIC error " + "report %d seconds", sec); + wpa_s->pending_mic_error_report = 1; + wpa_s->pending_mic_error_pairwise = pairwise; + eloop_cancel_timeout( + wpa_supplicant_delayed_mic_error_report, + wpa_s, NULL); + eloop_register_timeout( + sec, os_random() % 1000000, + wpa_supplicant_delayed_mic_error_report, + wpa_s, NULL); + } else { + wpa_sm_key_request(wpa_s->wpa, 1, pairwise); + } +#else /* CONFIG_DELAYED_MIC_ERROR_REPORT */ + wpa_sm_key_request(wpa_s->wpa, 1, pairwise); +#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */ + } + wpa_s->last_michael_mic_error = t; + wpa_s->mic_errors_seen++; +} +#endif + +#ifdef CONFIG_TERMINATE_ONLASTIF +static int any_interfaces(struct wpa_supplicant *head) +{ + struct wpa_supplicant *wpa_s; + + for (wpa_s = head; wpa_s != NULL; wpa_s = wpa_s->next) + if (!wpa_s->interface_removed) + return 1; + return 0; +} +#endif /* CONFIG_TERMINATE_ONLASTIF */ + +#ifdef CONFIG_FULL_SUPPLICANT +static void +wpa_supplicant_event_interface_status(struct wpa_supplicant *wpa_s, + union wpa_event_data *data) +{ + if (os_strcmp(wpa_s->ifname, data->interface_status.ifname) != 0) + return; + + switch (data->interface_status.ievent) { + case EVENT_INTERFACE_ADDED: + if (!wpa_s->interface_removed) + break; + wpa_s->interface_removed = 0; + wpa_dbg(wpa_s, MSG_DEBUG, "Configured interface was added"); + if (wpa_supplicant_driver_init(wpa_s) < 0) { + wpa_msg(wpa_s, MSG_INFO, "Failed to initialize the " + "driver after interface was added"); + } + +#ifdef CONFIG_P2P + if (!wpa_s->global->p2p && + !wpa_s->global->p2p_disabled && + !wpa_s->conf->p2p_disabled && + (wpa_s->drv_flags & + WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) && + wpas_p2p_add_p2pdev_interface( + wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) { + wpa_printf(MSG_INFO, + "P2P: Failed to enable P2P Device interface"); + /* Try to continue without. P2P will be disabled. */ + } +#endif /* CONFIG_P2P */ + + break; + case EVENT_INTERFACE_REMOVED: + wpa_dbg(wpa_s, MSG_DEBUG, "Configured interface was removed"); + wpa_s->interface_removed = 1; + wpa_supplicant_mark_disassoc(wpa_s); + wpa_supplicant_set_state(wpa_s, WPA_INTERFACE_DISABLED); + l2_packet_deinit(wpa_s->l2); + wpa_s->l2 = NULL; + +#ifdef CONFIG_P2P + if (wpa_s->global->p2p && + wpa_s->global->p2p_init_wpa_s->parent == wpa_s && + (wpa_s->drv_flags & + WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) { + wpa_dbg(wpa_s, MSG_DEBUG, + "Removing P2P Device interface"); + wpa_supplicant_remove_iface( + wpa_s->global, wpa_s->global->p2p_init_wpa_s, + 0); + wpa_s->global->p2p_init_wpa_s = NULL; + } +#endif /* CONFIG_P2P */ + +#ifdef CONFIG_TERMINATE_ONLASTIF + /* check if last interface */ + if (!any_interfaces(wpa_s->global->ifaces)) + eloop_terminate(); +#endif /* CONFIG_TERMINATE_ONLASTIF */ + break; + } +} +#endif + +#ifdef CONFIG_PEERKEY +static void +wpa_supplicant_event_stkstart(struct wpa_supplicant *wpa_s, + union wpa_event_data *data) +{ + if (data == NULL) + return; + wpa_sm_stkstart(wpa_s->wpa, data->stkstart.peer); +} +#endif /* CONFIG_PEERKEY */ + + +#ifdef CONFIG_TDLS +static void wpa_supplicant_event_tdls(struct wpa_supplicant *wpa_s, + union wpa_event_data *data) +{ + if (data == NULL) + return; + switch (data->tdls.oper) { + case TDLS_REQUEST_SETUP: + wpa_tdls_remove(wpa_s->wpa, data->tdls.peer); + if (wpa_tdls_is_external_setup(wpa_s->wpa)) + wpa_tdls_start(wpa_s->wpa, data->tdls.peer); + else + wpa_drv_tdls_oper(wpa_s, TDLS_SETUP, data->tdls.peer); + break; + case TDLS_REQUEST_TEARDOWN: + if (wpa_tdls_is_external_setup(wpa_s->wpa)) + wpa_tdls_teardown_link(wpa_s->wpa, data->tdls.peer, + data->tdls.reason_code); + else + wpa_drv_tdls_oper(wpa_s, TDLS_TEARDOWN, + data->tdls.peer); + break; + case TDLS_REQUEST_DISCOVER: + wpa_tdls_send_discovery_request(wpa_s->wpa, + data->tdls.peer); + break; + } +} +#endif /* CONFIG_TDLS */ + + +#ifdef CONFIG_WNM +static void wpa_supplicant_event_wnm(struct wpa_supplicant *wpa_s, + union wpa_event_data *data) +{ + if (data == NULL) + return; + switch (data->wnm.oper) { + case WNM_OPER_SLEEP: + wpa_printf(MSG_DEBUG, "Start sending WNM-Sleep Request " + "(action=%d, intval=%d)", + data->wnm.sleep_action, data->wnm.sleep_intval); + ieee802_11_send_wnmsleep_req(wpa_s, data->wnm.sleep_action, + data->wnm.sleep_intval, NULL); + break; + } +} +#endif /* CONFIG_WNM */ + + +#ifdef CONFIG_IEEE80211R +static void +wpa_supplicant_event_ft_response(struct wpa_supplicant *wpa_s, + union wpa_event_data *data) +{ + if (data == NULL) + return; + + if (wpa_ft_process_response(wpa_s->wpa, data->ft_ies.ies, + data->ft_ies.ies_len, + data->ft_ies.ft_action, + data->ft_ies.target_ap, + data->ft_ies.ric_ies, + data->ft_ies.ric_ies_len) < 0) { + wpa_dbg(wpa_s, MSG_DEBUG, + "SME: FT Authentication response processing failed"); + wpas_connection_failed(wpa_s, wpa_s->pending_bssid); + wpa_supplicant_mark_disassoc(wpa_s); + return; + } + #ifdef CONFIG_SME + { + struct wpa_bss *bss; + bss = wpa_bss_get_bssid(wpa_s, data->ft_ies.target_ap); + if (bss) + { + wpa_s->sme.freq = bss->freq; + wpa_s->sme.ssid_len = bss->ssid_len; + if (bss->ssid_len > 0) + os_memcpy(wpa_s->sme.ssid, bss->ssid, bss->ssid_len); + } + sme_associate(wpa_s, WPAS_MODE_INFRA, data->ft_ies.target_ap, + WLAN_AUTH_FT); + } + #endif /* CONFIG_SME */ +} +#endif /* CONFIG_IEEE80211R */ + + +#ifdef CONFIG_IBSS_RSN +static void wpa_supplicant_event_ibss_rsn_start(struct wpa_supplicant *wpa_s, + union wpa_event_data *data) +{ + struct wpa_ssid *ssid; + if (wpa_s->wpa_state < WPA_ASSOCIATED) + return; + if (data == NULL) + return; + ssid = wpa_s->current_ssid; + if (ssid == NULL) + return; + if (ssid->mode != WPAS_MODE_IBSS || !wpa_key_mgmt_wpa(ssid->key_mgmt)) + return; + + ibss_rsn_start(wpa_s->ibss_rsn, data->ibss_rsn_start.peer); +} + + +static void wpa_supplicant_event_ibss_auth(struct wpa_supplicant *wpa_s, + union wpa_event_data *data) +{ + struct wpa_ssid *ssid = wpa_s->current_ssid; + + if (ssid == NULL) + return; + + /* check if the ssid is correctly configured as IBSS/RSN */ + if (ssid->mode != WPAS_MODE_IBSS || !wpa_key_mgmt_wpa(ssid->key_mgmt)) + return; + + ibss_rsn_handle_auth(wpa_s->ibss_rsn, data->rx_mgmt.frame, + data->rx_mgmt.frame_len); +} +#endif /* CONFIG_IBSS_RSN */ + + +#ifdef CONFIG_IEEE80211R +static void ft_rx_action(struct wpa_supplicant *wpa_s, const u8 *data, + size_t len) +{ + const u8 *sta_addr, *target_ap_addr; + u16 status; + + wpa_hexdump(MSG_MSGDUMP, "FT: RX Action", data, len); + if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME)) + return; /* only SME case supported for now */ + if (len < 1 + 2 * ETH_ALEN + 2) + return; + if (data[0] != 2) + return; /* Only FT Action Response is supported for now */ + sta_addr = data + 1; + target_ap_addr = data + 1 + ETH_ALEN; + status = WPA_GET_LE16(data + 1 + 2 * ETH_ALEN); + wpa_dbg(wpa_s, MSG_DEBUG, "FT: Received FT Action Response: STA " + MACSTR " TargetAP " MACSTR " status %u", + MAC2STR(sta_addr), MAC2STR(target_ap_addr), status); + + if (os_memcmp(sta_addr, wpa_s->own_addr, ETH_ALEN) != 0) { + wpa_dbg(wpa_s, MSG_DEBUG, "FT: Foreign STA Address " MACSTR + " in FT Action Response", MAC2STR(sta_addr)); + return; + } + + if (status) { + wpa_dbg(wpa_s, MSG_DEBUG, "FT: FT Action Response indicates " + "failure (status code %d)", status); + /* TODO: report error to FT code(?) */ + return; + } + + if (wpa_ft_process_response(wpa_s->wpa, data + 1 + 2 * ETH_ALEN + 2, + len - (1 + 2 * ETH_ALEN + 2), 1, + target_ap_addr, NULL, 0) < 0) + return; + +#ifdef CONFIG_SME + { + struct wpa_bss *bss; + bss = wpa_bss_get_bssid(wpa_s, target_ap_addr); + if (bss) + wpa_s->sme.freq = bss->freq; + wpa_s->sme.auth_alg = WPA_AUTH_ALG_FT; + sme_associate(wpa_s, WPAS_MODE_INFRA, target_ap_addr, + WLAN_AUTH_FT); + } +#endif /* CONFIG_SME */ +} +#endif /* CONFIG_IEEE80211R */ + + +void wpa_supplicant_event_unprot_deauth(struct wpa_supplicant *wpa_s, + struct unprot_deauth *e) +{ +#ifdef CONFIG_IEEE80211W + wpa_printf(MSG_DEBUG, "Unprotected Deauthentication frame " + "dropped: " MACSTR " -> " MACSTR + " (reason code %u)", + MAC2STR(e->sa), MAC2STR(e->da), e->reason_code); + sme_event_unprot_disconnect(wpa_s, e->sa, e->da, e->reason_code); +#endif /* CONFIG_IEEE80211W */ +} + + +void wpa_supplicant_event_unprot_disassoc(struct wpa_supplicant *wpa_s, + struct unprot_disassoc *e) +{ +#ifdef CONFIG_IEEE80211W + wpa_printf(MSG_DEBUG, "Unprotected Disassociation frame " + "dropped: " MACSTR " -> " MACSTR + " (reason code %u)", + MAC2STR(e->sa), MAC2STR(e->da), e->reason_code); + sme_event_unprot_disconnect(wpa_s, e->sa, e->da, e->reason_code); +#endif /* CONFIG_IEEE80211W */ +} + + +static void wpas_event_disconnect(struct wpa_supplicant *wpa_s, const u8 *addr, + u16 reason_code, int locally_generated, + const u8 *ie, size_t ie_len, int deauth) +{ +#ifdef CONFIG_AP + if (wpa_s->ap_iface && addr) { + hostapd_notif_disassoc(wpa_s->ap_iface->bss[0], addr); + return; + } + + if (wpa_s->ap_iface) { + wpa_dbg(wpa_s, MSG_DEBUG, "Ignore deauth event in AP mode"); + return; + } +#endif /* CONFIG_AP */ + + if (!locally_generated) + wpa_s->own_disconnect_req = 0; + + wpa_supplicant_event_disassoc(wpa_s, reason_code, locally_generated); + + if (((reason_code == WLAN_REASON_IEEE_802_1X_AUTH_FAILED || + ((wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) || + (wpa_s->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA)) && + eapol_sm_failed(wpa_s->eapol))) && + !wpa_s->eap_expected_failure)) + wpas_auth_failed(wpa_s, "AUTH_FAILED"); + +#ifdef CONFIG_P2P + if (deauth && reason_code > 0) { + if (wpas_p2p_deauth_notif(wpa_s, addr, reason_code, ie, ie_len, + locally_generated) > 0) { + /* + * The interface was removed, so cannot continue + * processing any additional operations after this. + */ + return; + } + } +#endif /* CONFIG_P2P */ + + wpa_supplicant_event_disassoc_finish(wpa_s, reason_code, + locally_generated); +} + + +static void wpas_event_disassoc(struct wpa_supplicant *wpa_s, + struct disassoc_info *info) +{ + u16 reason_code = 0; + int locally_generated = 0; + const u8 *addr = NULL; + const u8 *ie = NULL; + size_t ie_len = 0; + + wpa_dbg(wpa_s, MSG_DEBUG, "Disassociation notification"); + + if (info) { + addr = info->addr; + ie = info->ie; + ie_len = info->ie_len; + reason_code = info->reason_code; + locally_generated = info->locally_generated; + wpa_dbg(wpa_s, MSG_DEBUG, " * reason %u%s", reason_code, + locally_generated ? " (locally generated)" : ""); + if (addr) + wpa_dbg(wpa_s, MSG_DEBUG, " * address " MACSTR, + MAC2STR(addr)); + wpa_hexdump(MSG_DEBUG, "Disassociation frame IE(s)", + ie, ie_len); + } + +#ifdef CONFIG_AP + if (wpa_s->ap_iface && info && info->addr) { + hostapd_notif_disassoc(wpa_s->ap_iface->bss[0], info->addr); + return; + } + + if (wpa_s->ap_iface) { + wpa_dbg(wpa_s, MSG_DEBUG, "Ignore disassoc event in AP mode"); + return; + } +#endif /* CONFIG_AP */ + +#ifdef CONFIG_P2P + if (info) { + wpas_p2p_disassoc_notif( + wpa_s, info->addr, reason_code, info->ie, info->ie_len, + locally_generated); + } +#endif /* CONFIG_P2P */ + + if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) + sme_event_disassoc(wpa_s, info); + + wpas_event_disconnect(wpa_s, addr, reason_code, locally_generated, + ie, ie_len, 0); +} + + +static void wpas_event_deauth(struct wpa_supplicant *wpa_s, + struct deauth_info *info) +{ + u16 reason_code = 0; + int locally_generated = 0; + const u8 *addr = NULL; + const u8 *ie = NULL; + size_t ie_len = 0; + + wpa_dbg(wpa_s, MSG_DEBUG, "Deauthentication notification"); + + if (info) { + addr = info->addr; + ie = info->ie; + ie_len = info->ie_len; + reason_code = info->reason_code; + locally_generated = info->locally_generated; + wpa_dbg(wpa_s, MSG_DEBUG, " * reason %u%s", + reason_code, + locally_generated ? " (locally generated)" : ""); + if (addr) { + wpa_dbg(wpa_s, MSG_DEBUG, " * address " MACSTR, + MAC2STR(addr)); + } + wpa_hexdump(MSG_DEBUG, "Deauthentication frame IE(s)", + ie, ie_len); + } + + wpa_reset_ft_completed(wpa_s->wpa); + + wpas_event_disconnect(wpa_s, addr, reason_code, + locally_generated, ie, ie_len, 1); +} + +void wpa_supplicant_update_channel_list( + struct wpa_supplicant *wpa_s, struct channel_list_changed *info) +{ + struct wpa_supplicant *ifs; + + if (wpa_s->drv_priv == NULL) + return; /* Ignore event during drv initialization */ + + dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant, + radio_list) { + wpa_printf(MSG_DEBUG, "%s: Updating hw mode", + ifs->ifname); + free_hw_features(ifs); + ifs->hw.modes = wpa_drv_get_hw_feature_data( + ifs, &ifs->hw.num_modes, &ifs->hw.flags); + } + + /* Restart sched_scan with updated channel list */ + if (wpa_s->sched_scanning) { + wpa_dbg(wpa_s, MSG_DEBUG, + "Channel list changed restart sched scan."); + wpa_supplicant_cancel_sched_scan(wpa_s); + wpa_supplicant_req_scan(wpa_s, 0, 0); + } + + wpas_p2p_update_channel_list(wpa_s, WPAS_P2P_CHANNEL_UPDATE_DRIVER); +} + +static void wpas_event_rx_mgmt_action(struct wpa_supplicant *wpa_s, + const u8 *frame, size_t len, int freq, + int rssi) +{ + const struct ieee80211_mgmt *mgmt; + const u8 *payload; + size_t plen; + u8 category; + + if (len < IEEE80211_HDRLEN + 2) + return; + + mgmt = (const struct ieee80211_mgmt *) frame; + payload = frame + IEEE80211_HDRLEN; + category = *payload++; + plen = len - IEEE80211_HDRLEN - 1; + + wpa_dbg(wpa_s, MSG_DEBUG, "Received Action frame: SA=" MACSTR + " Category=%u DataLen=%d freq=%d MHz", + MAC2STR(mgmt->sa), category, (int) plen, freq); + + if (category == WLAN_ACTION_WMM) { + wmm_ac_rx_action(wpa_s, mgmt->da, mgmt->sa, payload, plen); + return; + } + +#ifdef CONFIG_IEEE80211R + if (category == WLAN_ACTION_FT) { + ft_rx_action(wpa_s, payload, plen); + return; + } +#endif /* CONFIG_IEEE80211R */ + +#ifdef CONFIG_IEEE80211W +#ifdef CONFIG_SME + if (category == WLAN_ACTION_SA_QUERY) { + sme_sa_query_rx(wpa_s, mgmt->sa, payload, plen); + return; + } +#endif /* CONFIG_SME */ +#endif /* CONFIG_IEEE80211W */ + +#ifdef CONFIG_WNM + if (mgmt->u.action.category == WLAN_ACTION_WNM) { + ieee802_11_rx_wnm_action(wpa_s, mgmt, len); + return; + } +#endif /* CONFIG_WNM */ + +#ifdef CONFIG_GAS + if ((mgmt->u.action.category == WLAN_ACTION_PUBLIC || + mgmt->u.action.category == WLAN_ACTION_PROTECTED_DUAL) && + gas_query_rx(wpa_s->gas, mgmt->da, mgmt->sa, mgmt->bssid, + mgmt->u.action.category, + payload, plen, freq) == 0) + return; +#endif /* CONFIG_GAS */ + +#ifdef CONFIG_TDLS + if (category == WLAN_ACTION_PUBLIC && plen >= 4 && + payload[0] == WLAN_TDLS_DISCOVERY_RESPONSE) { + wpa_dbg(wpa_s, MSG_DEBUG, + "TDLS: Received Discovery Response from " MACSTR, + MAC2STR(mgmt->sa)); + return; + } +#endif /* CONFIG_TDLS */ + +#ifdef CONFIG_INTERWORKING + if (category == WLAN_ACTION_QOS && plen >= 1 && + payload[0] == QOS_QOS_MAP_CONFIG) { + const u8 *pos = payload + 1; + size_t qlen = plen - 1; + wpa_dbg(wpa_s, MSG_DEBUG, "Interworking: Received QoS Map Configure frame from " + MACSTR, MAC2STR(mgmt->sa)); + if (os_memcmp(mgmt->sa, wpa_s->bssid, ETH_ALEN) == 0 && + qlen > 2 && pos[0] == WLAN_EID_QOS_MAP_SET && + pos[1] <= qlen - 2 && pos[1] >= 16) + wpas_qos_map_set(wpa_s, pos + 2, pos[1]); + return; + } +#endif /* CONFIG_INTERWORKING */ + +#ifdef CONFIG_RRM + if (category == WLAN_ACTION_RADIO_MEASUREMENT && + payload[0] == WLAN_RRM_NEIGHBOR_REPORT_RESPONSE) { + wpas_rrm_process_neighbor_rep(wpa_s, payload + 1, plen - 1); + return; + } + + if (category == WLAN_ACTION_RADIO_MEASUREMENT && + payload[0] == WLAN_RRM_LINK_MEASUREMENT_REQUEST) { + wpas_rrm_handle_link_measurement_request(wpa_s, mgmt->sa, + payload + 1, plen - 1, + rssi); + return; + } +#endif + +#ifdef CONFIG_FST + if (mgmt->u.action.category == WLAN_ACTION_FST && wpa_s->fst) { + fst_rx_action(wpa_s->fst, mgmt, len); + return; + } +#endif /* CONFIG_FST */ + + wpas_p2p_rx_action(wpa_s, mgmt->da, mgmt->sa, mgmt->bssid, + category, payload, plen, freq); + if (wpa_s->ifmsh) + mesh_mpm_action_rx(wpa_s, mgmt, len); +} + +#ifdef CONFIG_FULL_SUPPLICANT +static void wpa_supplicant_notify_avoid_freq(struct wpa_supplicant *wpa_s, + union wpa_event_data *event) +{ + struct wpa_freq_range_list *list; + char *str = NULL; + + list = &event->freq_range; + + if (list->num) + str = freq_range_list_str(list); + wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_AVOID_FREQ "ranges=%s", + str ? str : ""); + +#ifdef CONFIG_P2P + if (freq_range_list_parse(&wpa_s->global->p2p_go_avoid_freq, str)) { + wpa_dbg(wpa_s, MSG_ERROR, "%s: Failed to parse freq range", + __func__); + } else { + wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Update channel list based on frequency avoid event"); + + /* + * The update channel flow will also take care of moving a GO + * from the unsafe frequency if needed. + */ + wpas_p2p_update_channel_list(wpa_s, + WPAS_P2P_CHANNEL_UPDATE_AVOID); + } +#endif /* CONFIG_P2P */ + + os_free(str); +} +#endif + +static void wpa_supplicant_event_assoc_auth(struct wpa_supplicant *wpa_s, + union wpa_event_data *data) +{ + wpa_dbg(wpa_s, MSG_DEBUG, + "Connection authorized by device, previous state %d", + wpa_s->wpa_state); + if (wpa_s->wpa_state == WPA_ASSOCIATED) { + wpa_supplicant_cancel_auth_timeout(wpa_s); + wpa_supplicant_set_state(wpa_s, WPA_COMPLETED); + eapol_sm_notify_portValid(wpa_s->eapol, TRUE); + eapol_sm_notify_eap_success(wpa_s->eapol, TRUE); + } + wpa_sm_set_rx_replay_ctr(wpa_s->wpa, data->assoc_info.key_replay_ctr); + wpa_sm_set_ptk_kck_kek(wpa_s->wpa, data->assoc_info.ptk_kck, + data->assoc_info.ptk_kck_len, + data->assoc_info.ptk_kek, + data->assoc_info.ptk_kek_len); +} + + +void wpa_supplicant_event_sta(void *ctx, enum wpa_event_type event, + union wpa_event_data *data) +{ + struct wpa_supplicant *wpa_s = ctx; + + if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED && + event != EVENT_INTERFACE_ENABLED && + event != EVENT_INTERFACE_STATUS && + event != EVENT_SCHED_SCAN_STOPPED) { + wpa_dbg(wpa_s, MSG_DEBUG, + "Ignore event %s (%d) while interface is disabled", + event_to_string(event), event); + return; + } + +#ifndef CONFIG_NO_STDOUT_DEBUG +{ + int level = MSG_DEBUG; + + if (event == EVENT_RX_MGMT && data->rx_mgmt.frame_len >= 24) { + const struct ieee80211_hdr *hdr; + u16 fc; + hdr = (const struct ieee80211_hdr *) data->rx_mgmt.frame; + fc = le_to_host16(hdr->frame_control); + if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && + WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON) + level = MSG_EXCESSIVE; + } + + wpa_dbg(wpa_s, level, "Event %s (%d) received", + event_to_string(event), event); +} +#endif /* CONFIG_NO_STDOUT_DEBUG */ + + switch (event) { +#ifdef CONFIG_FULL_SUPPLICANT + case EVENT_AUTH: + sme_event_auth(wpa_s, data); + break; +#endif + case EVENT_ASSOC: + wpa_supplicant_event_assoc(wpa_s, data); + if (data && data->assoc_info.authorized) + wpa_supplicant_event_assoc_auth(wpa_s, data); + break; + case EVENT_DISASSOC: + wpas_event_disassoc(wpa_s, + data ? &data->disassoc_info : NULL); + break; + case EVENT_DEAUTH: + wpas_event_deauth(wpa_s, + data ? &data->deauth_info : NULL); + break; +#ifdef CONFIG_FULL_SUPPLICANT + case EVENT_MICHAEL_MIC_FAILURE: + wpa_supplicant_event_michael_mic_failure(wpa_s, data); + break; +#endif +#ifndef CONFIG_NO_SCAN_PROCESSING + case EVENT_SCAN_STARTED: + os_get_reltime(&wpa_s->scan_start_time); + if (wpa_s->own_scan_requested) { + struct os_reltime diff; + + os_reltime_sub(&wpa_s->scan_start_time, + &wpa_s->scan_trigger_time, &diff); + wpa_dbg(wpa_s, MSG_DEBUG, "Own scan request started a scan in %ld.%06ld seconds", + diff.sec, diff.usec); + wpa_s->own_scan_requested = 0; + wpa_s->own_scan_running = 1; + if (wpa_s->last_scan_req == MANUAL_SCAN_REQ && + wpa_s->manual_scan_use_id) { + wpa_msg_ctrl(wpa_s, MSG_INFO, + WPA_EVENT_SCAN_STARTED "id=%u", + wpa_s->manual_scan_id); + } else { + wpa_msg_ctrl(wpa_s, MSG_INFO, + WPA_EVENT_SCAN_STARTED); + } + } else { + wpa_dbg(wpa_s, MSG_DEBUG, "External program started a scan"); + wpa_s->radio->external_scan_running = 1; + wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_SCAN_STARTED); + } + break; + case EVENT_SCAN_RESULTS: + if (os_reltime_initialized(&wpa_s->scan_start_time)) { + struct os_reltime now, diff; + os_get_reltime(&now); + os_reltime_sub(&now, &wpa_s->scan_start_time, &diff); + wpa_s->scan_start_time.sec = 0; + wpa_s->scan_start_time.usec = 0; + os_printf("Scan completed in %ld.%06ld seconds\r\n", + diff.sec, diff.usec); + } + if (wpa_supplicant_event_scan_results(wpa_s, data)) + break; /* interface may have been removed */ + wpa_s->own_scan_running = 0; + wpa_s->radio->external_scan_running = 0; + + radio_work_check_next(wpa_s); + break; +#endif /* CONFIG_NO_SCAN_PROCESSING */ +#ifdef CONFIG_FULL_SUPPLICANT + case EVENT_ASSOCINFO: + wpa_supplicant_event_associnfo(wpa_s, data); + break; + case EVENT_INTERFACE_STATUS: + wpa_supplicant_event_interface_status(wpa_s, data); + break; + case EVENT_PMKID_CANDIDATE: + wpa_supplicant_event_pmkid_candidate(wpa_s, data); + break; +#endif +#ifdef CONFIG_PEERKEY + case EVENT_STKSTART: + wpa_supplicant_event_stkstart(wpa_s, data); + break; +#endif /* CONFIG_PEERKEY */ +#ifdef CONFIG_TDLS + case EVENT_TDLS: + wpa_supplicant_event_tdls(wpa_s, data); + break; +#endif /* CONFIG_TDLS */ +#ifdef CONFIG_WNM + case EVENT_WNM: + wpa_supplicant_event_wnm(wpa_s, data); + break; +#endif /* CONFIG_WNM */ +#ifdef CONFIG_IEEE80211R + case EVENT_FT_RESPONSE: + wpa_supplicant_event_ft_response(wpa_s, data); + break; +#endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_IBSS_RSN + case EVENT_IBSS_RSN_START: + wpa_supplicant_event_ibss_rsn_start(wpa_s, data); + break; +#endif /* CONFIG_IBSS_RSN */ +#ifdef CONFIG_FULL_SUPPLICANT + case EVENT_ASSOC_REJECT: + if (data->assoc_reject.bssid) + wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_ASSOC_REJECT + "bssid=" MACSTR " status_code=%u", + MAC2STR(data->assoc_reject.bssid), + data->assoc_reject.status_code); + else + wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_ASSOC_REJECT + "status_code=%u", + data->assoc_reject.status_code); + if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) + sme_event_assoc_reject(wpa_s, data); + else { + const u8 *bssid = data->assoc_reject.bssid; + if (bssid == NULL || is_zero_ether_addr(bssid)) + bssid = wpa_s->pending_bssid; + wpas_connection_failed(wpa_s, bssid); + wpa_supplicant_mark_disassoc(wpa_s); + } + break; + case EVENT_AUTH_TIMED_OUT: + /* It is possible to get this event from earlier connection */ + if (wpa_s->current_ssid && + wpa_s->current_ssid->mode == WPAS_MODE_MESH) { + wpa_dbg(wpa_s, MSG_DEBUG, + "Ignore AUTH_TIMED_OUT in mesh configuration"); + break; + } + if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) + sme_event_auth_timed_out(wpa_s, data); + break; + case EVENT_ASSOC_TIMED_OUT: + /* It is possible to get this event from earlier connection */ + if (wpa_s->current_ssid && + wpa_s->current_ssid->mode == WPAS_MODE_MESH) { + wpa_dbg(wpa_s, MSG_DEBUG, + "Ignore ASSOC_TIMED_OUT in mesh configuration"); + break; + } + if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) + sme_event_assoc_timed_out(wpa_s, data); + break; +#endif + case EVENT_TX_STATUS: + wpa_dbg(wpa_s, MSG_DEBUG, "EVENT_TX_STATUS dst=" MACSTR + " type=%d stype=%d", + MAC2STR(data->tx_status.dst), + data->tx_status.type, data->tx_status.stype); +#ifdef CONFIG_AP + if (wpa_s->ap_iface == NULL) { +#ifdef CONFIG_OFFCHANNEL + if (data->tx_status.type == WLAN_FC_TYPE_MGMT && + data->tx_status.stype == WLAN_FC_STYPE_ACTION) + offchannel_send_action_tx_status( + wpa_s, data->tx_status.dst, + data->tx_status.data, + data->tx_status.data_len, + data->tx_status.ack ? + OFFCHANNEL_SEND_ACTION_SUCCESS : + OFFCHANNEL_SEND_ACTION_NO_ACK); +#endif /* CONFIG_OFFCHANNEL */ + break; + } +#endif /* CONFIG_AP */ +#ifdef CONFIG_AP + switch (data->tx_status.type) { + case WLAN_FC_TYPE_MGMT: + ap_mgmt_tx_cb(wpa_s, data->tx_status.data, + data->tx_status.data_len, + data->tx_status.stype, + data->tx_status.ack); + break; + case WLAN_FC_TYPE_DATA: + ap_tx_status(wpa_s, data->tx_status.dst, + data->tx_status.data, + data->tx_status.data_len, + data->tx_status.ack); + break; + } +#endif /* CONFIG_AP */ + break; +#ifdef CONFIG_AP + case EVENT_EAPOL_TX_STATUS: + ap_eapol_tx_status(wpa_s, data->eapol_tx_status.dst, + data->eapol_tx_status.data, + data->eapol_tx_status.data_len, + data->eapol_tx_status.ack); + break; + case EVENT_DRIVER_CLIENT_POLL_OK: + ap_client_poll_ok(wpa_s, data->client_poll.addr); + break; + case EVENT_RX_FROM_UNKNOWN: + if (wpa_s->ap_iface == NULL) + break; + ap_rx_from_unknown_sta(wpa_s, data->rx_from_unknown.addr, + data->rx_from_unknown.wds); + break; + case EVENT_CH_SWITCH: + if (!data) + break; + if (!wpa_s->ap_iface) { + wpa_dbg(wpa_s, MSG_DEBUG, "AP: Ignore channel switch " + "event in non-AP mode"); + break; + } + + wpas_ap_ch_switch(wpa_s, data->ch_switch.freq, + data->ch_switch.ht_enabled, + data->ch_switch.ch_offset, + data->ch_switch.ch_width, + data->ch_switch.cf1, + data->ch_switch.cf2); + break; +#ifdef NEED_AP_MLME + case EVENT_DFS_RADAR_DETECTED: + if (data) + wpas_event_dfs_radar_detected(wpa_s, &data->dfs_event); + break; + case EVENT_DFS_CAC_STARTED: + if (data) + wpas_event_dfs_cac_started(wpa_s, &data->dfs_event); + break; + case EVENT_DFS_CAC_FINISHED: + if (data) + wpas_event_dfs_cac_finished(wpa_s, &data->dfs_event); + break; + case EVENT_DFS_CAC_ABORTED: + if (data) + wpas_event_dfs_cac_aborted(wpa_s, &data->dfs_event); + break; + case EVENT_DFS_NOP_FINISHED: + if (data) + wpas_event_dfs_cac_nop_finished(wpa_s, + &data->dfs_event); + break; +#endif /* NEED_AP_MLME */ +#endif /* CONFIG_AP */ + case EVENT_RX_MGMT: { + u16 fc, stype; + const struct ieee80211_mgmt *mgmt; + +#ifdef CONFIG_TESTING_OPTIONS + if (wpa_s->ext_mgmt_frame_handling) { + struct rx_mgmt *rx = &data->rx_mgmt; + size_t hex_len = 2 * rx->frame_len + 1; + char *hex = os_malloc(hex_len); + if (hex) { + wpa_snprintf_hex(hex, hex_len, + rx->frame, rx->frame_len); + wpa_msg(wpa_s, MSG_INFO, "MGMT-RX freq=%d datarate=%u ssi_signal=%d %s", + rx->freq, rx->datarate, rx->ssi_signal, + hex); + os_free(hex); + } + break; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + mgmt = (const struct ieee80211_mgmt *) + data->rx_mgmt.frame; + fc = le_to_host16(mgmt->frame_control); + stype = WLAN_FC_GET_STYPE(fc); + +#ifdef CONFIG_AP + if (wpa_s->ap_iface == NULL) { +#endif /* CONFIG_AP */ + if (stype == WLAN_FC_STYPE_ACTION) { + wpas_event_rx_mgmt_action( + wpa_s, data->rx_mgmt.frame, + data->rx_mgmt.frame_len, + data->rx_mgmt.freq, + data->rx_mgmt.ssi_signal); + break; + } + + if (wpa_s->ifmsh) { + mesh_mpm_mgmt_rx(wpa_s, &data->rx_mgmt); + break; + } + + wpa_dbg(wpa_s, MSG_DEBUG, "AP: ignore received " + "management frame in non-AP mode"); + break; +#ifdef CONFIG_AP + } + + if (stype == WLAN_FC_STYPE_PROBE_REQ && + data->rx_mgmt.frame_len > 24) { + const u8 *ie = mgmt->u.probe_req.variable; + size_t ie_len = data->rx_mgmt.frame_len - + (mgmt->u.probe_req.variable - + data->rx_mgmt.frame); + + wpas_notify_preq(wpa_s, mgmt->sa, mgmt->da, + mgmt->bssid, ie, ie_len, + data->rx_mgmt.ssi_signal); + } + + ap_mgmt_rx(wpa_s, &data->rx_mgmt); +#endif /* CONFIG_AP */ + break; + } +#ifdef CONFIG_FULL_SUPPLICANT + case EVENT_RX_PROBE_REQ: + if (data->rx_probe_req.sa == NULL || + data->rx_probe_req.ie == NULL) + break; +#ifdef CONFIG_AP + if (wpa_s->ap_iface) { + hostapd_probe_req_rx(wpa_s->ap_iface->bss[0], + data->rx_probe_req.sa, + data->rx_probe_req.da, + data->rx_probe_req.bssid, + data->rx_probe_req.ie, + data->rx_probe_req.ie_len, + data->rx_probe_req.ssi_signal); + break; + } +#endif /* CONFIG_AP */ + wpas_p2p_probe_req_rx(wpa_s, data->rx_probe_req.sa, + data->rx_probe_req.da, + data->rx_probe_req.bssid, + data->rx_probe_req.ie, + data->rx_probe_req.ie_len, + 0, + data->rx_probe_req.ssi_signal); + break; + case EVENT_REMAIN_ON_CHANNEL: +#ifdef CONFIG_OFFCHANNEL + offchannel_remain_on_channel_cb( + wpa_s, data->remain_on_channel.freq, + data->remain_on_channel.duration); +#endif /* CONFIG_OFFCHANNEL */ + wpas_p2p_remain_on_channel_cb( + wpa_s, data->remain_on_channel.freq, + data->remain_on_channel.duration); + break; + case EVENT_CANCEL_REMAIN_ON_CHANNEL: +#ifdef CONFIG_OFFCHANNEL + offchannel_cancel_remain_on_channel_cb( + wpa_s, data->remain_on_channel.freq); +#endif /* CONFIG_OFFCHANNEL */ + wpas_p2p_cancel_remain_on_channel_cb( + wpa_s, data->remain_on_channel.freq); + break; + case EVENT_EAPOL_RX: + wpa_supplicant_rx_eapol(wpa_s, data->eapol_rx.src, + data->eapol_rx.data, + data->eapol_rx.data_len); + break; + case EVENT_SIGNAL_CHANGE: + wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_SIGNAL_CHANGE + "above=%d signal=%d noise=%d txrate=%d", + data->signal_change.above_threshold, + data->signal_change.current_signal, + data->signal_change.current_noise, + data->signal_change.current_txrate); + wpa_bss_update_level(wpa_s->current_bss, + data->signal_change.current_signal); + bgscan_notify_signal_change( + wpa_s, data->signal_change.above_threshold, + data->signal_change.current_signal, + data->signal_change.current_noise, + data->signal_change.current_txrate); + break; + case EVENT_INTERFACE_ENABLED: + wpa_dbg(wpa_s, MSG_DEBUG, "Interface was enabled"); + if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) { + wpa_supplicant_update_mac_addr(wpa_s); + if (wpa_s->p2p_mgmt) { + wpa_supplicant_set_state(wpa_s, + WPA_DISCONNECTED); + break; + } + +#ifdef CONFIG_AP + if (!wpa_s->ap_iface) { + wpa_supplicant_set_state(wpa_s, + WPA_DISCONNECTED); + wpa_s->scan_req = NORMAL_SCAN_REQ; + wpa_supplicant_req_scan(wpa_s, 0, 0); + } else + wpa_supplicant_set_state(wpa_s, + WPA_COMPLETED); +#else /* CONFIG_AP */ + wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); + wpa_supplicant_req_scan(wpa_s, 0, 0); +#endif /* CONFIG_AP */ + } + break; + case EVENT_INTERFACE_DISABLED: + wpa_dbg(wpa_s, MSG_DEBUG, "Interface was disabled"); +#ifdef CONFIG_P2P + if (wpa_s->p2p_group_interface == P2P_GROUP_INTERFACE_GO || + (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group && + wpa_s->current_ssid->mode == WPAS_MODE_P2P_GO)) { + /* + * Mark interface disabled if this happens to end up not + * being removed as a separate P2P group interface. + */ + wpa_supplicant_set_state(wpa_s, WPA_INTERFACE_DISABLED); + /* + * The interface was externally disabled. Remove + * it assuming an external entity will start a + * new session if needed. + */ + if (wpa_s->current_ssid && + wpa_s->current_ssid->p2p_group) + wpas_p2p_interface_unavailable(wpa_s); + else + wpas_p2p_disconnect(wpa_s); + /* + * wpa_s instance may have been freed, so must not use + * it here anymore. + */ + break; + } + if (wpa_s->p2p_scan_work && wpa_s->global->p2p && + p2p_in_progress(wpa_s->global->p2p) > 1) { + /* This radio work will be cancelled, so clear P2P + * state as well. + */ + p2p_stop_find(wpa_s->global->p2p); + } +#endif /* CONFIG_P2P */ + + if (wpa_s->wpa_state >= WPA_AUTHENTICATING) { + /* + * Indicate disconnection to keep ctrl_iface events + * consistent. + */ + wpa_supplicant_event_disassoc( + wpa_s, WLAN_REASON_DEAUTH_LEAVING, 1); + } + wpa_supplicant_mark_disassoc(wpa_s); + radio_remove_works(wpa_s, NULL, 0); + + wpa_supplicant_set_state(wpa_s, WPA_INTERFACE_DISABLED); + break; + case EVENT_CHANNEL_LIST_CHANGED: + wpa_supplicant_update_channel_list( + wpa_s, &data->channel_list_changed); + break; + case EVENT_INTERFACE_UNAVAILABLE: + wpas_p2p_interface_unavailable(wpa_s); + break; + case EVENT_BEST_CHANNEL: + wpa_dbg(wpa_s, MSG_DEBUG, "Best channel event received " + "(%d %d %d)", + data->best_chan.freq_24, data->best_chan.freq_5, + data->best_chan.freq_overall); + wpa_s->best_24_freq = data->best_chan.freq_24; + wpa_s->best_5_freq = data->best_chan.freq_5; + wpa_s->best_overall_freq = data->best_chan.freq_overall; + wpas_p2p_update_best_channels(wpa_s, data->best_chan.freq_24, + data->best_chan.freq_5, + data->best_chan.freq_overall); + break; + case EVENT_UNPROT_DEAUTH: + wpa_supplicant_event_unprot_deauth(wpa_s, + &data->unprot_deauth); + break; + case EVENT_UNPROT_DISASSOC: + wpa_supplicant_event_unprot_disassoc(wpa_s, + &data->unprot_disassoc); + break; + case EVENT_STATION_LOW_ACK: +#ifdef CONFIG_AP + if (wpa_s->ap_iface && data) + hostapd_event_sta_low_ack(wpa_s->ap_iface->bss[0], + data->low_ack.addr); +#endif /* CONFIG_AP */ +#ifdef CONFIG_TDLS + if (data) + wpa_tdls_disable_unreachable_link(wpa_s->wpa, + data->low_ack.addr); +#endif /* CONFIG_TDLS */ + break; + case EVENT_IBSS_PEER_LOST: +#ifdef CONFIG_IBSS_RSN + ibss_rsn_stop(wpa_s->ibss_rsn, data->ibss_peer_lost.peer); +#endif /* CONFIG_IBSS_RSN */ + break; + case EVENT_DRIVER_GTK_REKEY: + if (os_memcmp(data->driver_gtk_rekey.bssid, + wpa_s->bssid, ETH_ALEN)) + break; + if (!wpa_s->wpa) + break; + wpa_sm_update_replay_ctr(wpa_s->wpa, + data->driver_gtk_rekey.replay_ctr); + break; + case EVENT_SCHED_SCAN_STOPPED: + wpa_s->pno = 0; + wpa_s->sched_scanning = 0; + resched = wpa_s->scanning; + wpa_supplicant_notify_scanning(wpa_s, 0); + + if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) + break; + + /* + * Start a new sched scan to continue searching for more SSIDs + * either if timed out or PNO schedule scan is pending. + */ + if (wpa_s->sched_scan_timed_out) { + wpa_supplicant_req_sched_scan(wpa_s); + } else if (wpa_s->pno_sched_pending) { + wpa_s->pno_sched_pending = 0; + wpas_start_pno(wpa_s); + } else if (resched) { + wpa_supplicant_req_scan(wpa_s, 0, 0); + } + + break; + case EVENT_WPS_BUTTON_PUSHED: +#ifdef CONFIG_WPS + wpas_wps_start_pbc(wpa_s, NULL, 0); +#endif /* CONFIG_WPS */ + break; + case EVENT_AVOID_FREQUENCIES: + wpa_supplicant_notify_avoid_freq(wpa_s, data); + break; + case EVENT_CONNECT_FAILED_REASON: +#ifdef CONFIG_AP + if (!wpa_s->ap_iface || !data) + break; + hostapd_event_connect_failed_reason( + wpa_s->ap_iface->bss[0], + data->connect_failed_reason.addr, + data->connect_failed_reason.code); +#endif /* CONFIG_AP */ + break; +#endif + case EVENT_NEW_PEER_CANDIDATE: +#ifdef CONFIG_MESH + if (!wpa_s->ifmsh || !data) + break; + wpa_mesh_notify_peer(wpa_s, data->mesh_peer.peer, + data->mesh_peer.ies, + data->mesh_peer.ie_len); +#endif /* CONFIG_MESH */ + break; + default: + wpa_msg(wpa_s, MSG_INFO, "Unknown event %d", event); + break; + } +} diff --git a/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/gas_query.h b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/gas_query.h new file mode 100755 index 0000000..ad13490 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/gas_query.h @@ -0,0 +1,59 @@ +/* + * Generic advertisement service (GAS) query + * Copyright (c) 2009, Atheros Communications + * Copyright (c) 2011, Qualcomm Atheros + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef GAS_QUERY_H +#define GAS_QUERY_H + +struct gas_query; + +#ifdef CONFIG_GAS + +struct gas_query * gas_query_init(struct wpa_supplicant *wpa_s); +void gas_query_deinit(struct gas_query *gas); +int gas_query_rx(struct gas_query *gas, const u8 *da, const u8 *sa, + const u8 *bssid, u8 categ, const u8 *data, size_t len, + int freq); + +/** + * enum gas_query_result - GAS query result + */ +enum gas_query_result { + GAS_QUERY_SUCCESS, + GAS_QUERY_FAILURE, + GAS_QUERY_TIMEOUT, + GAS_QUERY_PEER_ERROR, + GAS_QUERY_INTERNAL_ERROR, + GAS_QUERY_CANCELLED, + GAS_QUERY_DELETED_AT_DEINIT +}; + +int gas_query_req(struct gas_query *gas, const u8 *dst, int freq, + struct wpabuf *req, + void (*cb)(void *ctx, const u8 *dst, u8 dialog_token, + enum gas_query_result result, + const struct wpabuf *adv_proto, + const struct wpabuf *resp, u16 status_code), + void *ctx); +void gas_query_cancel(struct gas_query *gas, const u8 *dst, u8 dialog_token); + +#else /* CONFIG_GAS */ + +static inline struct gas_query * gas_query_init(struct wpa_supplicant *wpa_s) +{ + return (void *) 1; +} + +static inline void gas_query_deinit(struct gas_query *gas) +{ +} + +#endif /* CONFIG_GAS */ + + +#endif /* GAS_QUERY_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/hs20_supplicant.h b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/hs20_supplicant.h new file mode 100755 index 0000000..85b5120 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/hs20_supplicant.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2011-2013, Qualcomm Atheros, Inc. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef HS20_SUPPLICANT_H +#define HS20_SUPPLICANT_H + +void wpas_hs20_add_indication(struct wpabuf *buf, int pps_mo_id); + +int hs20_anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, u32 stypes, + const u8 *payload, size_t payload_len); +struct wpabuf * hs20_build_anqp_req(u32 stypes, const u8 *payload, + size_t payload_len); +void hs20_put_anqp_req(u32 stypes, const u8 *payload, size_t payload_len, + struct wpabuf *buf); +void hs20_parse_rx_hs20_anqp_resp(struct wpa_supplicant *wpa_s, + struct wpa_bss *bss, const u8 *sa, + const u8 *data, size_t slen); +int is_hs20_network(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, + struct wpa_bss *bss); +int hs20_get_pps_mo_id(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid); +void hs20_notify_parse_done(struct wpa_supplicant *wpa_s); + +void hs20_rx_subscription_remediation(struct wpa_supplicant *wpa_s, + const char *url, u8 osu_method); +void hs20_rx_deauth_imminent_notice(struct wpa_supplicant *wpa_s, u8 code, + u16 reauth_delay, const char *url); + +void hs20_free_osu_prov(struct wpa_supplicant *wpa_s); +void hs20_next_osu_icon(struct wpa_supplicant *wpa_s); +void hs20_osu_icon_fetch(struct wpa_supplicant *wpa_s); +int hs20_fetch_osu(struct wpa_supplicant *wpa_s); +void hs20_cancel_fetch_osu(struct wpa_supplicant *wpa_s); +void hs20_icon_fetch_failed(struct wpa_supplicant *wpa_s); +void hs20_start_osu_scan(struct wpa_supplicant *wpa_s); +void hs20_deinit(struct wpa_supplicant *wpa_s); + +#endif /* HS20_SUPPLICANT_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/ibss_rsn.h b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/ibss_rsn.h new file mode 100755 index 0000000..67fae2d --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/ibss_rsn.h @@ -0,0 +1,64 @@ +/* + * wpa_supplicant - IBSS RSN + * Copyright (c) 2009, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef IBSS_RSN_H +#define IBSS_RSN_H + +struct ibss_rsn; + +/* not authenticated */ +#define IBSS_RSN_AUTH_NOT_AUTHENTICATED 0x00 +/* remote peer sent an EAPOL message */ +#define IBSS_RSN_AUTH_EAPOL_BY_PEER 0x01 +/* we sent an AUTH message with seq 1 */ +#define IBSS_RSN_AUTH_BY_US 0x02 +/* we sent an EAPOL message */ +#define IBSS_RSN_AUTH_EAPOL_BY_US 0x04 +/* PTK derived as supplicant */ +#define IBSS_RSN_SET_PTK_SUPP 0x08 +/* PTK derived as authenticator */ +#define IBSS_RSN_SET_PTK_AUTH 0x10 +/* PTK completion reported */ +#define IBSS_RSN_REPORTED_PTK 0x20 + +struct ibss_rsn_peer { + struct ibss_rsn_peer *next; + struct ibss_rsn *ibss_rsn; + + u8 addr[ETH_ALEN]; + + struct wpa_sm *supp; + enum wpa_states supp_state; + u8 supp_ie[80]; + size_t supp_ie_len; + + struct wpa_state_machine *auth; + int authentication_status; + + struct os_reltime own_auth_tx; +}; + +struct ibss_rsn { + struct wpa_supplicant *wpa_s; + struct wpa_authenticator *auth_group; + struct ibss_rsn_peer *peers; + u8 psk[PMK_LEN]; +}; + + +struct ibss_rsn * ibss_rsn_init(struct wpa_supplicant *wpa_s); +void ibss_rsn_deinit(struct ibss_rsn *ibss_rsn); +int ibss_rsn_start(struct ibss_rsn *ibss_rsn, const u8 *addr); +void ibss_rsn_stop(struct ibss_rsn *ibss_rsn, const u8 *peermac); +int ibss_rsn_rx_eapol(struct ibss_rsn *ibss_rsn, const u8 *src_addr, + const u8 *buf, size_t len); +void ibss_rsn_set_psk(struct ibss_rsn *ibss_rsn, const u8 *psk); +void ibss_rsn_handle_auth(struct ibss_rsn *ibss_rsn, const u8 *auth_frame, + size_t len); + +#endif /* IBSS_RSN_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/interworking.h b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/interworking.h new file mode 100755 index 0000000..3743dc0 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/interworking.h @@ -0,0 +1,36 @@ +/* + * Interworking (IEEE 802.11u) + * Copyright (c) 2011-2012, Qualcomm Atheros + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef INTERWORKING_H +#define INTERWORKING_H + +enum gas_query_result; + +int anqp_send_req(struct wpa_supplicant *wpa_s, const u8 *dst, + u16 info_ids[], size_t num_ids, u32 subtypes); +void anqp_resp_cb(void *ctx, const u8 *dst, u8 dialog_token, + enum gas_query_result result, + const struct wpabuf *adv_proto, + const struct wpabuf *resp, u16 status_code); +int gas_send_request(struct wpa_supplicant *wpa_s, const u8 *dst, + const struct wpabuf *adv_proto, + const struct wpabuf *query); +int interworking_fetch_anqp(struct wpa_supplicant *wpa_s); +void interworking_stop_fetch_anqp(struct wpa_supplicant *wpa_s); +int interworking_select(struct wpa_supplicant *wpa_s, int auto_select, + int *freqs); +int interworking_connect(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, + int only_add); +void interworking_start_fetch_anqp(struct wpa_supplicant *wpa_s); +int interworking_home_sp_cred(struct wpa_supplicant *wpa_s, + struct wpa_cred *cred, + struct wpabuf *domain_names); +int domain_name_list_contains(struct wpabuf *domain_names, + const char *domain, int exact_match); + +#endif /* INTERWORKING_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/main_supplicant.c b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/main_supplicant.c new file mode 100755 index 0000000..8c9a73f --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/main_supplicant.c @@ -0,0 +1,285 @@ +/* + * WPA Supplicant / main() function for UNIX like OSes and MinGW + * Copyright (c) 2003-2013, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ +#include "includes.h" +#include "common.h" +#include "wpa_supplicant_i.h" +#include "driver_i.h" +#include "main_none.h" +#include "ps.h" + +#if (!CFG_SUPPORT_ALIOS) +#include "sys_rtos.h" +#endif +#include "rtos_pub.h" +#include "rtos_error.h" +#include "uart_pub.h" +#include "signal.h" +#include "eloop.h" +#include "config.h" + +static struct wpa_global *wpa_global_ptr = NULL; +#if (CFG_SUPPORT_ALIOS || CFG_SUPPORT_RTT) +beken_thread_t wpas_thread_handle = NULL; +extern beken_thread_t hostapd_thread_handle; +#else +xTaskHandle wpas_thread_handle = NULL; +extern xTaskHandle hostapd_thread_handle; +#endif +uint32_t wpas_stack_size = 3500; +extern beken_semaphore_t wpa_hostapd_sema; +struct wpa_ssid_value *wpas_connect_ssid = 0; +struct wpa_interface *wpas_ifaces = 0; +uint32_t supplicant_exit_flag = 0; + +extern beken_queue_t wpah_queue; + +extern void wpas_thread_start(void); +extern void wpas_thread_stop(void); +extern void wpa_handler_signal(void *arg, u8 vif_idx); +extern void dhcp_stop_timeout_check(void); +extern uint32_t wpa_hostapd_queue_poll(uint32_t param); + +struct wpa_supplicant *wpa_suppliant_ctrl_get_wpas() +{ + if (!wpa_global_ptr) + return NULL; + return wpa_global_ptr->ifaces; +} + +int wpa_get_psk(char *psk) +{ + struct wpa_config *conf = NULL; + + if(!psk) + { + return -1; + } + memset(psk, 0, 32); + conf = wpa_global_ptr->ifaces->conf; + memcpy(psk, conf->ssid->psk, 32); + + return 0; +} + +int supplicant_exit_done(void) +{ + supplicant_exit_flag = 0; + os_printf("supplicant_exit_done\r\n"); + + return 0; +} + +int supplicant_is_exiting(void) +{ + return supplicant_exit_flag; +} + +int supplicant_main_exit(void) +{ + uint32_t ret; + + supplicant_exit_flag = 1; + + ret = wpa_hostapd_queue_poll(0xff); + while((0 == ret) && supplicant_exit_flag) + { + os_printf("supplicant_main_exiting\r\n"); + rtos_delay_milliseconds(10); + } + + return 0; +} + +int supplicant_exit_handler(void) +{ + if (wpa_global_ptr == NULL) + return 0; + + if(wpa_global_ptr) + { + wpa_supplicant_deinit(wpa_global_ptr); + wpa_global_ptr = NULL; + } + + if(wpas_ifaces) + { + os_free(wpas_ifaces); + wpas_ifaces = 0; + } + + if(wpas_connect_ssid) + { + os_free(wpas_connect_ssid); + wpas_connect_ssid = 0; + } + + return 0; +} + +u8 supplicant_main_is_exit(void) +{ + return (wpa_global_ptr==NULL)?1:0; +} + +int supplicant_main_entry(char *oob_ssid) +{ + int i; + int iface_count, exitcode = -1; + struct wpa_params params; + struct wpa_supplicant *wpa_s; + struct wpa_interface *iface; + + os_memset(¶ms, 0, sizeof(params)); + params.wpa_debug_level = MSG_INFO; + + if(0 == wpas_ifaces) + { + wpas_ifaces = os_zalloc(sizeof(struct wpa_interface)); + if (wpas_ifaces == NULL) + return -1; + } + + iface = wpas_ifaces; + iface_count = 1; + iface->ifname = bss_iface; + exitcode = 0; + + wpa_global_ptr = wpa_supplicant_init(¶ms); + if (wpa_global_ptr == NULL) + { + wpa_printf(MSG_ERROR, "Failed to initialize wpa_supplicant"); + exitcode = -1; + goto out; + } + else + { + wpa_printf(MSG_INFO, "Successfully initialized wpa_supplicant"); + } + + for (i = 0; exitcode == 0 && i < iface_count; i++) + { + if (wpas_ifaces[i].ctrl_interface == NULL && + wpas_ifaces[i].ifname == NULL) + { + if (iface_count == 1 + && (params.ctrl_interface + || params.dbus_ctrl_interface)) + { + break; + } + + exitcode = -1; + break; + } + + wpa_s = wpa_supplicant_add_iface(wpa_global_ptr, &wpas_ifaces[i], NULL); + if (wpa_s == NULL) + { + exitcode = -1; + break; + } + + + if(oob_ssid) + { + int len; + int oob_ssid_len; + + ASSERT(0 == wpa_s->ssids_from_scan_req); + oob_ssid_len = os_strlen(oob_ssid); + + if(0 == wpas_connect_ssid) + { + wpas_connect_ssid = (struct wpa_ssid_value *)os_malloc(sizeof(struct wpa_ssid_value)); + ASSERT(wpas_connect_ssid); + } + + len = MIN(SSID_MAX_LEN, oob_ssid_len); + + wpas_connect_ssid->ssid_len = len; + os_memcpy(wpas_connect_ssid->ssid, oob_ssid, len); + + wpa_s->num_ssids_from_scan_req = 1; + wpa_s->ssids_from_scan_req = wpas_connect_ssid; + wpa_s->scan_req = MANUAL_SCAN_REQ; + os_printf("MANUAL_SCAN_REQ\r\n"); + } + } + + if (exitcode) + { + wpa_supplicant_deinit(wpa_global_ptr); + } + else + { + wpa_supplicant_run(wpa_global_ptr); + + return 0; + } + +out: + os_free(wpas_ifaces); + wpas_ifaces = 0; + + os_free(params.pid_file); + params.pid_file = 0; + + return exitcode; +} + +static void wpas_thread_main( void *arg ) +{ + eloop_init(); + + eloop_run(); + + wpas_thread_handle = NULL; + rtos_deinit_queue(&wpah_queue); + wpah_queue = NULL; + rtos_delete_thread(NULL); +} + +void wpas_thread_start(void) +{ + OSStatus ret; + + if(wpah_queue == NULL) { + ret = rtos_init_queue(&wpah_queue, + "wpah_queue", + sizeof(WPAH_MSG_ST), + 10); + ASSERT(kNoErr == ret); + } + + if(NULL == wpas_thread_handle) + { + ret = rtos_create_thread(&wpas_thread_handle, + THD_WPAS_PRIORITY, + "wpas_thread", + (beken_thread_function_t)wpas_thread_main, + (unsigned short)wpas_stack_size, + (beken_thread_arg_t)NULLPTR); + ASSERT(kNoErr == ret); + } +} + +void wpas_thread_stop(void) +{ + wpa_handler_signal((void*)SIGTERM, 0xff); + + while(wpas_thread_handle != NULL) { + rtos_delay_milliseconds(10); + } +} + +u8* wpas_get_sta_psk(void) +{ + return wpa_global_ptr->ifaces->conf->ssid->psk; +} +// eof + diff --git a/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/mesh.h b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/mesh.h new file mode 100755 index 0000000..3cb7f1b --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/mesh.h @@ -0,0 +1,44 @@ +/* + * WPA Supplicant - Basic mesh mode routines + * Copyright (c) 2013-2014, cozybit, Inc. All rights reserved. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef MESH_H +#define MESH_H + +int wpa_supplicant_join_mesh(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid); +int wpa_supplicant_leave_mesh(struct wpa_supplicant *wpa_s); +void wpa_supplicant_mesh_iface_deinit(struct wpa_supplicant *wpa_s, + struct hostapd_iface *ifmsh); +int wpas_mesh_scan_result_text(const u8 *ies, size_t ies_len, char *buf, + char *end); +int wpas_mesh_add_interface(struct wpa_supplicant *wpa_s, char *ifname, + size_t len); + +#ifdef CONFIG_MESH + +void wpa_mesh_notify_peer(struct wpa_supplicant *wpa_s, const u8 *addr, + const u8 *ies, size_t ie_len); +void wpa_supplicant_mesh_add_scan_ie(struct wpa_supplicant *wpa_s, + struct wpabuf **extra_ie); + +#else /* CONFIG_MESH */ + +static inline void wpa_mesh_notify_peer(struct wpa_supplicant *wpa_s, + const u8 *addr, + const u8 *ies, size_t ie_len) +{ +} + +static inline void wpa_supplicant_mesh_add_scan_ie(struct wpa_supplicant *wpa_s, + struct wpabuf **extra_ie) +{ +} + +#endif /* CONFIG_MESH */ + +#endif /* MESH_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/mesh_mpm.h b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/mesh_mpm.h new file mode 100755 index 0000000..7ebaef0 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/mesh_mpm.h @@ -0,0 +1,43 @@ +/* + * WPA Supplicant - Basic mesh peer management + * Copyright (c) 2013-2014, cozybit, Inc. All rights reserved. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef MESH_MPM_H +#define MESH_MPM_H + +/* notify MPM of new mesh peer to be inserted in MPM and driver */ +void wpa_mesh_new_mesh_peer(struct wpa_supplicant *wpa_s, const u8 *addr, + struct ieee802_11_elems *elems); +void mesh_mpm_deinit(struct wpa_supplicant *wpa_s, struct hostapd_iface *ifmsh); +void mesh_mpm_auth_peer(struct wpa_supplicant *wpa_s, const u8 *addr); +void mesh_mpm_free_sta(struct sta_info *sta); +void wpa_mesh_set_plink_state(struct wpa_supplicant *wpa_s, + struct sta_info *sta, + enum mesh_plink_state state); + +#ifdef CONFIG_MESH + +void mesh_mpm_action_rx(struct wpa_supplicant *wpa_s, + const struct ieee80211_mgmt *mgmt, size_t len); +void mesh_mpm_mgmt_rx(struct wpa_supplicant *wpa_s, struct rx_mgmt *rx_mgmt); + +#else /* CONFIG_MESH */ + +static inline void mesh_mpm_action_rx(struct wpa_supplicant *wpa_s, + const struct ieee80211_mgmt *mgmt, + size_t len) +{ +} + +static inline void mesh_mpm_mgmt_rx(struct wpa_supplicant *wpa_s, + struct rx_mgmt *rx_mgmt) +{ +} + +#endif /* CONFIG_MESH */ + +#endif /* MESH_MPM_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/mesh_rsn.h b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/mesh_rsn.h new file mode 100755 index 0000000..b1471b2 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/mesh_rsn.h @@ -0,0 +1,36 @@ +/* + * WPA Supplicant - Mesh RSN routines + * Copyright (c) 2013-2014, cozybit, Inc. All rights reserved. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef MESH_RSN_H +#define MESH_RSN_H + +struct mesh_rsn { + struct wpa_supplicant *wpa_s; + struct wpa_authenticator *auth; + u8 mgtk[16]; +#ifdef CONFIG_SAE + struct wpabuf *sae_token; + int sae_group_index; +#endif /* CONFIG_SAE */ +}; + +struct mesh_rsn * mesh_rsn_auth_init(struct wpa_supplicant *wpa_s, + struct mesh_conf *conf); +int mesh_rsn_auth_sae_sta(struct wpa_supplicant *wpa_s, struct sta_info *sta); +int mesh_rsn_derive_mtk(struct wpa_supplicant *wpa_s, struct sta_info *sta); +void mesh_rsn_get_pmkid(struct mesh_rsn *rsn, struct sta_info *sta, u8 *pmkid); +void mesh_rsn_init_ampe_sta(struct wpa_supplicant *wpa_s, + struct sta_info *sta); +int mesh_rsn_protect_frame(struct mesh_rsn *rsn, struct sta_info *sta, + const u8 *cat, struct wpabuf *buf); +int mesh_rsn_process_ampe(struct wpa_supplicant *wpa_s, struct sta_info *sta, + struct ieee802_11_elems *elems, const u8 *cat, + const u8 *start, size_t elems_len); +void mesh_auth_timer(void *eloop_ctx, void *user_data); + +#endif /* MESH_RSN_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/notify.c b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/notify.c new file mode 100755 index 0000000..d43a1ef --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/notify.c @@ -0,0 +1,900 @@ +/* + * wpa_supplicant - Event notifications + * Copyright (c) 2009-2010, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "common/wpa_ctrl.h" +#include "config.h" +#include "wpa_supplicant_i.h" +#include "wps_supplicant.h" +#include "rsn_supp/wpa.h" +#include "driver_i.h" +#include "scan.h" +#include "p2p_supplicant.h" +#include "sme.h" +#include "notify.h" + +int wpas_notify_supplicant_initialized(struct wpa_global *global) +{ +#ifdef CONFIG_DBUS + if (global->params.dbus_ctrl_interface) { + global->dbus = wpas_dbus_init(global); + if (global->dbus == NULL) + return -1; + } +#endif /* CONFIG_DBUS */ + + return 0; +} + + +void wpas_notify_supplicant_deinitialized(struct wpa_global *global) +{ +#ifdef CONFIG_DBUS + if (global->dbus) + wpas_dbus_deinit(global->dbus); +#endif /* CONFIG_DBUS */ +} + + +int wpas_notify_iface_added(struct wpa_supplicant *wpa_s) +{ + if (wpa_s->p2p_mgmt) + return 0; + +#ifdef CONFIG_DBUS + if (wpas_dbus_register_iface(wpa_s)) + return -1; + + if (wpas_dbus_register_interface(wpa_s)) + return -1; +#endif /* CONFIG_DBUS */ + + return 0; +} + + +void wpas_notify_iface_removed(struct wpa_supplicant *wpa_s) +{ + if (wpa_s->p2p_mgmt) + return; + +#ifdef CONFIG_DBUS + /* unregister interface in old DBus ctrl iface */ + wpas_dbus_unregister_iface(wpa_s); + + /* unregister interface in new DBus ctrl iface */ + wpas_dbus_unregister_interface(wpa_s); +#endif /* CONFIG_DBUS */ +} + + +void wpas_notify_state_changed(struct wpa_supplicant *wpa_s, + enum wpa_states new_state, + enum wpa_states old_state) +{ + if (wpa_s->p2p_mgmt) + return; + +#ifdef CONFIG_DBUS + /* notify the old DBus API */ + wpa_supplicant_dbus_notify_state_change(wpa_s, new_state, + old_state); + + /* notify the new DBus API */ + wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_STATE); +#endif /* CONFIG_DBUS */ + +#ifdef CONFIG_FST + if (wpa_s->fst && !is_zero_ether_addr(wpa_s->bssid)) { + if (new_state == WPA_COMPLETED) + fst_notify_peer_connected(wpa_s->fst, wpa_s->bssid); + else if (old_state >= WPA_ASSOCIATED && + new_state < WPA_ASSOCIATED) + fst_notify_peer_disconnected(wpa_s->fst, wpa_s->bssid); + } +#endif /* CONFIG_FST */ + + if (new_state == WPA_COMPLETED) + wpas_p2p_notif_connected(wpa_s); + else if (old_state >= WPA_ASSOCIATED && new_state < WPA_ASSOCIATED) + wpas_p2p_notif_disconnected(wpa_s); + + sme_state_changed(wpa_s); + +#ifdef ANDROID + wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_STATE_CHANGE + "id=%d state=%d BSSID=" MACSTR " SSID=%s", + wpa_s->current_ssid ? wpa_s->current_ssid->id : -1, + new_state, + MAC2STR(wpa_s->bssid), + wpa_s->current_ssid && wpa_s->current_ssid->ssid ? + wpa_ssid_txt(wpa_s->current_ssid->ssid, + wpa_s->current_ssid->ssid_len) : ""); +#endif /* ANDROID */ +} + + +void wpas_notify_disconnect_reason(struct wpa_supplicant *wpa_s) +{ + if (wpa_s->p2p_mgmt) + return; + +#ifdef CONFIG_DBUS + wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_DISCONNECT_REASON); +#endif /* CONFIG_DBUS */ +} + + +void wpas_notify_network_changed(struct wpa_supplicant *wpa_s) +{ + if (wpa_s->p2p_mgmt) + return; + +#ifdef CONFIG_DBUS + wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_CURRENT_NETWORK); +#endif /* CONFIG_DBUS */ +} + + +void wpas_notify_ap_scan_changed(struct wpa_supplicant *wpa_s) +{ + if (wpa_s->p2p_mgmt) + return; + +#ifdef CONFIG_DBUS + wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_AP_SCAN); +#endif /* CONFIG_DBUS */ +} + + +void wpas_notify_bssid_changed(struct wpa_supplicant *wpa_s) +{ + if (wpa_s->p2p_mgmt) + return; + +#ifdef CONFIG_DBUS + wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_CURRENT_BSS); +#endif /* CONFIG_DBUS */ +} + + +void wpas_notify_auth_changed(struct wpa_supplicant *wpa_s) +{ + if (wpa_s->p2p_mgmt) + return; + +#ifdef CONFIG_DBUS + wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_CURRENT_AUTH_MODE); +#endif /* CONFIG_DBUS */ +} + + +void wpas_notify_network_enabled_changed(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid) +{ + if (wpa_s->p2p_mgmt) + return; + +#ifdef CONFIG_DBUS + wpas_dbus_signal_network_enabled_changed(wpa_s, ssid); +#endif +} + + +void wpas_notify_network_selected(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid) +{ + if (wpa_s->p2p_mgmt) + return; + +#ifdef CONFIG_DBUS + wpas_dbus_signal_network_selected(wpa_s, ssid->id); +#endif +} + + +void wpas_notify_network_request(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid, + enum wpa_ctrl_req_type rtype, + const char *default_txt) +{ + if (wpa_s->p2p_mgmt) + return; + +#ifdef CONFIG_DBUS + wpas_dbus_signal_network_request(wpa_s, ssid, rtype, default_txt); +#endif +} + + +void wpas_notify_scanning(struct wpa_supplicant *wpa_s) +{ + if (wpa_s->p2p_mgmt) + return; + +#ifdef CONFIG_DBUS + /* notify the old DBus API */ + wpa_supplicant_dbus_notify_scanning(wpa_s); + + /* notify the new DBus API */ + wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_SCANNING); +#endif +} + + +void wpas_notify_scan_done(struct wpa_supplicant *wpa_s, int success) +{ + if (wpa_s->p2p_mgmt) + return; + +#ifdef CONFIG_DBUS + wpas_dbus_signal_scan_done(wpa_s, success); +#endif +} + + +void wpas_notify_scan_results(struct wpa_supplicant *wpa_s) +{ + if (wpa_s->p2p_mgmt) + return; + +#ifdef CONFIG_DBUS + /* notify the old DBus API */ + wpa_supplicant_dbus_notify_scan_results(wpa_s); +#endif + + wpas_wps_notify_scan_results(wpa_s); +} + + +void wpas_notify_wps_credential(struct wpa_supplicant *wpa_s, + const struct wps_credential *cred) +{ + if (wpa_s->p2p_mgmt) + return; + +#ifdef CONFIG_WPS + /* notify the old DBus API */ + wpa_supplicant_dbus_notify_wps_cred(wpa_s, cred); + /* notify the new DBus API */ + wpas_dbus_signal_wps_cred(wpa_s, cred); +#endif /* CONFIG_WPS */ +} + + +void wpas_notify_wps_event_m2d(struct wpa_supplicant *wpa_s, + struct wps_event_m2d *m2d) +{ + if (wpa_s->p2p_mgmt) + return; + +#ifdef CONFIG_WPS + wpas_dbus_signal_wps_event_m2d(wpa_s, m2d); +#endif /* CONFIG_WPS */ +} + + +void wpas_notify_wps_event_fail(struct wpa_supplicant *wpa_s, + struct wps_event_fail *fail) +{ + if (wpa_s->p2p_mgmt) + return; + +#ifdef CONFIG_WPS + wpas_dbus_signal_wps_event_fail(wpa_s, fail); +#endif /* CONFIG_WPS */ +} + + +void wpas_notify_wps_event_success(struct wpa_supplicant *wpa_s) +{ + if (wpa_s->p2p_mgmt) + return; + +#ifdef CONFIG_WPS + wpas_dbus_signal_wps_event_success(wpa_s); +#endif /* CONFIG_WPS */ +} + +void wpas_notify_wps_event_pbc_overlap(struct wpa_supplicant *wpa_s) +{ + if (wpa_s->p2p_mgmt) + return; + +#ifdef CONFIG_WPS + wpas_dbus_signal_wps_event_pbc_overlap(wpa_s); +#endif /* CONFIG_WPS */ +} + + +void wpas_notify_network_added(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid) +{ + if (wpa_s->p2p_mgmt) + return; + +#ifdef CONFIG_DBUS + /* + * Networks objects created during any P2P activities should not be + * exposed out. They might/will confuse certain non-P2P aware + * applications since these network objects won't behave like + * regular ones. + */ + if (!ssid->p2p_group && wpa_s->global->p2p_group_formation != wpa_s) + wpas_dbus_register_network(wpa_s, ssid); +#endif +} + + +void wpas_notify_persistent_group_added(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid) +{ +#ifdef CONFIG_P2P + wpas_dbus_register_persistent_group(wpa_s, ssid); +#endif /* CONFIG_P2P */ +} + + +void wpas_notify_persistent_group_removed(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid) +{ +#ifdef CONFIG_P2P + wpas_dbus_unregister_persistent_group(wpa_s, ssid->id); +#endif /* CONFIG_P2P */ +} + + +void wpas_notify_network_removed(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid) +{ + if (wpa_s->next_ssid == ssid) + wpa_s->next_ssid = NULL; + if (wpa_s->wpa) + wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid); +#ifdef CONFIG_DBUS + if (!ssid->p2p_group && wpa_s->global->p2p_group_formation != wpa_s && + !wpa_s->p2p_mgmt) + wpas_dbus_unregister_network(wpa_s, ssid->id); +#endif + if (network_is_persistent_group(ssid)) + wpas_notify_persistent_group_removed(wpa_s, ssid); + + wpas_p2p_network_removed(wpa_s, ssid); +} + + +void wpas_notify_bss_added(struct wpa_supplicant *wpa_s, + u8 bssid[], unsigned int id) +{ + if (wpa_s->p2p_mgmt) + return; + +#ifdef CONFIG_DBUS + wpas_dbus_register_bss(wpa_s, bssid, id); +#endif + wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_BSS_ADDED "%u " MACSTR, + id, MAC2STR(bssid)); +} + + +void wpas_notify_bss_removed(struct wpa_supplicant *wpa_s, + u8 bssid[], unsigned int id) +{ + if (wpa_s->p2p_mgmt) + return; + +#ifdef CONFIG_DBUS + wpas_dbus_unregister_bss(wpa_s, bssid, id); +#endif + wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_BSS_REMOVED "%u " MACSTR, + id, MAC2STR(bssid)); +} + + +void wpas_notify_bss_freq_changed(struct wpa_supplicant *wpa_s, + unsigned int id) +{ + if (wpa_s->p2p_mgmt) + return; + +#ifdef CONFIG_DBUS + wpas_dbus_bss_signal_prop_changed(wpa_s, WPAS_DBUS_BSS_PROP_FREQ, id); +#endif +} + + +void wpas_notify_bss_signal_changed(struct wpa_supplicant *wpa_s, + unsigned int id) +{ + if (wpa_s->p2p_mgmt) + return; + +#ifdef CONFIG_DBUS + wpas_dbus_bss_signal_prop_changed(wpa_s, WPAS_DBUS_BSS_PROP_SIGNAL, + id); +#endif +} + + +void wpas_notify_bss_privacy_changed(struct wpa_supplicant *wpa_s, + unsigned int id) +{ + if (wpa_s->p2p_mgmt) + return; + +#ifdef CONFIG_DBUS + wpas_dbus_bss_signal_prop_changed(wpa_s, WPAS_DBUS_BSS_PROP_PRIVACY, + id); +#endif +} + + +void wpas_notify_bss_mode_changed(struct wpa_supplicant *wpa_s, + unsigned int id) +{ + if (wpa_s->p2p_mgmt) + return; + +#ifdef CONFIG_DBUS + wpas_dbus_bss_signal_prop_changed(wpa_s, WPAS_DBUS_BSS_PROP_MODE, id); +#endif +} + + +void wpas_notify_bss_wpaie_changed(struct wpa_supplicant *wpa_s, + unsigned int id) +{ + if (wpa_s->p2p_mgmt) + return; + +#ifdef CONFIG_DBUS + wpas_dbus_bss_signal_prop_changed(wpa_s, WPAS_DBUS_BSS_PROP_WPA, id); +#endif +} + + +void wpas_notify_bss_rsnie_changed(struct wpa_supplicant *wpa_s, + unsigned int id) +{ + if (wpa_s->p2p_mgmt) + return; + +#ifdef CONFIG_DBUS + wpas_dbus_bss_signal_prop_changed(wpa_s, WPAS_DBUS_BSS_PROP_RSN, id); +#endif +} + + +void wpas_notify_bss_wps_changed(struct wpa_supplicant *wpa_s, + unsigned int id) +{ + if (wpa_s->p2p_mgmt) + return; + +#ifdef CONFIG_WPS + wpas_dbus_bss_signal_prop_changed(wpa_s, WPAS_DBUS_BSS_PROP_WPS, id); +#endif /* CONFIG_WPS */ +} + + +void wpas_notify_bss_ies_changed(struct wpa_supplicant *wpa_s, + unsigned int id) +{ + if (wpa_s->p2p_mgmt) + return; + +#ifdef CONFIG_DBUS + wpas_dbus_bss_signal_prop_changed(wpa_s, WPAS_DBUS_BSS_PROP_IES, id); +#endif +} + + +void wpas_notify_bss_rates_changed(struct wpa_supplicant *wpa_s, + unsigned int id) +{ + if (wpa_s->p2p_mgmt) + return; + +#ifdef CONFIG_DBUS + wpas_dbus_bss_signal_prop_changed(wpa_s, WPAS_DBUS_BSS_PROP_RATES, id); +#endif +} + + +void wpas_notify_bss_seen(struct wpa_supplicant *wpa_s, unsigned int id) +{ + if (wpa_s->p2p_mgmt) + return; + +#ifdef CONFIG_DBUS + wpas_dbus_bss_signal_prop_changed(wpa_s, WPAS_DBUS_BSS_PROP_AGE, id); +#endif +} + + +void wpas_notify_blob_added(struct wpa_supplicant *wpa_s, const char *name) +{ + if (wpa_s->p2p_mgmt) + return; + +#ifdef CONFIG_DBUS + wpas_dbus_signal_blob_added(wpa_s, name); +#endif +} + + +void wpas_notify_blob_removed(struct wpa_supplicant *wpa_s, const char *name) +{ + if (wpa_s->p2p_mgmt) + return; + +#ifdef CONFIG_DBUS + wpas_dbus_signal_blob_removed(wpa_s, name); +#endif +} + + +void wpas_notify_debug_level_changed(struct wpa_global *global) +{ +#ifdef CONFIG_DBUS + wpas_dbus_signal_debug_level_changed(global); +#endif +} + + +void wpas_notify_debug_timestamp_changed(struct wpa_global *global) +{ +#ifdef CONFIG_DBUS + wpas_dbus_signal_debug_timestamp_changed(global); +#endif +} + + +void wpas_notify_debug_show_keys_changed(struct wpa_global *global) +{ +#ifdef CONFIG_DBUS + wpas_dbus_signal_debug_show_keys_changed(global); +#endif +} + + +void wpas_notify_suspend(struct wpa_global *global) +{ + struct wpa_supplicant *wpa_s; + + os_get_time(&global->suspend_time); + wpa_printf(MSG_DEBUG, "System suspend notification"); + for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) + wpa_drv_suspend(wpa_s); +} + + +void wpas_notify_resume(struct wpa_global *global) +{ + struct os_time now; + int slept; + struct wpa_supplicant *wpa_s; + + if (global->suspend_time.sec == 0) + slept = -1; + else { + os_get_time(&now); + slept = now.sec - global->suspend_time.sec; + } + (void)slept; + wpa_printf(MSG_DEBUG, "System resume notification (slept %d seconds)", + slept); + + for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) { + wpa_drv_resume(wpa_s); + if (wpa_s->wpa_state == WPA_DISCONNECTED) + wpa_supplicant_req_scan(wpa_s, 0, 100000); + } +} + + +#ifdef CONFIG_P2P + +void wpas_notify_p2p_find_stopped(struct wpa_supplicant *wpa_s) +{ + /* Notify P2P find has stopped */ + wpas_dbus_signal_p2p_find_stopped(wpa_s); +} + + +void wpas_notify_p2p_device_found(struct wpa_supplicant *wpa_s, + const u8 *dev_addr, int new_device) +{ + if (new_device) { + /* Create the new peer object */ + wpas_dbus_register_peer(wpa_s, dev_addr); + } + + /* Notify a new peer has been detected*/ + wpas_dbus_signal_peer_device_found(wpa_s, dev_addr); +} + + +void wpas_notify_p2p_device_lost(struct wpa_supplicant *wpa_s, + const u8 *dev_addr) +{ + wpas_dbus_unregister_peer(wpa_s, dev_addr); + + /* Create signal on interface object*/ + wpas_dbus_signal_peer_device_lost(wpa_s, dev_addr); +} + + +void wpas_notify_p2p_group_removed(struct wpa_supplicant *wpa_s, + const struct wpa_ssid *ssid, + const char *role) +{ + wpas_dbus_signal_p2p_group_removed(wpa_s, role); + + wpas_dbus_unregister_p2p_group(wpa_s, ssid); +} + + +void wpas_notify_p2p_go_neg_req(struct wpa_supplicant *wpa_s, + const u8 *src, u16 dev_passwd_id, u8 go_intent) +{ + wpas_dbus_signal_p2p_go_neg_req(wpa_s, src, dev_passwd_id, go_intent); +} + + +void wpas_notify_p2p_go_neg_completed(struct wpa_supplicant *wpa_s, + struct p2p_go_neg_results *res) +{ + wpas_dbus_signal_p2p_go_neg_resp(wpa_s, res); +} + + +void wpas_notify_p2p_invitation_result(struct wpa_supplicant *wpa_s, + int status, const u8 *bssid) +{ + wpas_dbus_signal_p2p_invitation_result(wpa_s, status, bssid); +} + + +void wpas_notify_p2p_sd_request(struct wpa_supplicant *wpa_s, + int freq, const u8 *sa, u8 dialog_token, + u16 update_indic, const u8 *tlvs, + size_t tlvs_len) +{ + wpas_dbus_signal_p2p_sd_request(wpa_s, freq, sa, dialog_token, + update_indic, tlvs, tlvs_len); +} + + +void wpas_notify_p2p_sd_response(struct wpa_supplicant *wpa_s, + const u8 *sa, u16 update_indic, + const u8 *tlvs, size_t tlvs_len) +{ + wpas_dbus_signal_p2p_sd_response(wpa_s, sa, update_indic, + tlvs, tlvs_len); +} + + +/** + * wpas_notify_p2p_provision_discovery - Notification of provision discovery + * @dev_addr: Who sent the request or responded to our request. + * @request: Will be 1 if request, 0 for response. + * @status: Valid only in case of response (0 in case of success) + * @config_methods: WPS config methods + * @generated_pin: PIN to be displayed in case of WPS_CONFIG_DISPLAY method + * + * This can be used to notify: + * - Requests or responses + * - Various config methods + * - Failure condition in case of response + */ +void wpas_notify_p2p_provision_discovery(struct wpa_supplicant *wpa_s, + const u8 *dev_addr, int request, + enum p2p_prov_disc_status status, + u16 config_methods, + unsigned int generated_pin) +{ + wpas_dbus_signal_p2p_provision_discovery(wpa_s, dev_addr, request, + status, config_methods, + generated_pin); +} + + +void wpas_notify_p2p_group_started(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid, int network_id, + int client) +{ + /* Notify a group has been started */ + wpas_dbus_register_p2p_group(wpa_s, ssid); + + wpas_dbus_signal_p2p_group_started(wpa_s, ssid, client, network_id); +} + + +void wpas_notify_p2p_group_formation_failure(struct wpa_supplicant *wpa_s, + const char *reason) +{ + /* Notify a group formation failed */ + wpas_dbus_signal_p2p_group_formation_failure(wpa_s, reason); +} + + +void wpas_notify_p2p_wps_failed(struct wpa_supplicant *wpa_s, + struct wps_event_fail *fail) +{ + wpas_dbus_signal_p2p_wps_failed(wpa_s, fail); +} + + +void wpas_notify_p2p_invitation_received(struct wpa_supplicant *wpa_s, + const u8 *sa, const u8 *go_dev_addr, + const u8 *bssid, int id, int op_freq) +{ + /* Notify a P2P Invitation Request */ + wpas_dbus_signal_p2p_invitation_received(wpa_s, sa, go_dev_addr, bssid, + id, op_freq); +} + +#endif /* CONFIG_P2P */ + + +static void wpas_notify_ap_sta_authorized(struct wpa_supplicant *wpa_s, + const u8 *sta, + const u8 *p2p_dev_addr) +{ +#ifdef CONFIG_P2P + wpas_p2p_notify_ap_sta_authorized(wpa_s, p2p_dev_addr); + + /* + * Create 'peer-joined' signal on group object -- will also + * check P2P itself. + */ + if (p2p_dev_addr) + wpas_dbus_signal_p2p_peer_joined(wpa_s, p2p_dev_addr); +#endif /* CONFIG_P2P */ + +#ifdef CONFIG_DBUS + /* Notify listeners a new station has been authorized */ + wpas_dbus_signal_sta_authorized(wpa_s, sta); +#endif +} + + +static void wpas_notify_ap_sta_deauthorized(struct wpa_supplicant *wpa_s, + const u8 *sta, + const u8 *p2p_dev_addr) +{ +#ifdef CONFIG_P2P + /* + * Create 'peer-disconnected' signal on group object if this + * is a P2P group. + */ + if (p2p_dev_addr) + wpas_dbus_signal_p2p_peer_disconnected(wpa_s, p2p_dev_addr); +#endif /* CONFIG_P2P */ + +#ifdef CONFIG_DBUS + /* Notify listeners a station has been deauthorized */ + wpas_dbus_signal_sta_deauthorized(wpa_s, sta); +#endif +} + + +void wpas_notify_sta_authorized(struct wpa_supplicant *wpa_s, + const u8 *mac_addr, int authorized, + const u8 *p2p_dev_addr) +{ + if (authorized) + wpas_notify_ap_sta_authorized(wpa_s, mac_addr, p2p_dev_addr); + else + wpas_notify_ap_sta_deauthorized(wpa_s, mac_addr, p2p_dev_addr); +} + + +void wpas_notify_certification(struct wpa_supplicant *wpa_s, int depth, + const char *subject, const char *altsubject[], + int num_altsubject, const char *cert_hash, + const struct wpabuf *cert) +{ + wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_EAP_PEER_CERT + "depth=%d subject='%s'%s%s", + depth, subject, cert_hash ? " hash=" : "", + cert_hash ? cert_hash : ""); + + if (cert) { + char *cert_hex; + size_t len = wpabuf_len(cert) * 2 + 1; + cert_hex = os_malloc(len); + if (cert_hex) { + wpa_snprintf_hex(cert_hex, len, wpabuf_head(cert), + wpabuf_len(cert)); + wpa_msg_ctrl(wpa_s, MSG_INFO, + WPA_EVENT_EAP_PEER_CERT + "depth=%d subject='%s' cert=%s", + depth, subject, cert_hex); + os_free(cert_hex); + } + } + + if (altsubject) { + int i; + + for (i = 0; i < num_altsubject; i++) + wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_EAP_PEER_ALT + "depth=%d %s", depth, altsubject[i]); + } + +#ifdef CONFIG_DBUS + /* notify the old DBus API */ + wpa_supplicant_dbus_notify_certification(wpa_s, depth, subject, + cert_hash, cert); + /* notify the new DBus API */ + wpas_dbus_signal_certification(wpa_s, depth, subject, altsubject, + num_altsubject, cert_hash, cert); +#endif +} + + +void wpas_notify_preq(struct wpa_supplicant *wpa_s, + const u8 *addr, const u8 *dst, const u8 *bssid, + const u8 *ie, size_t ie_len, u32 ssi_signal) +{ +#ifdef CONFIG_AP + wpas_dbus_signal_preq(wpa_s, addr, dst, bssid, ie, ie_len, ssi_signal); +#endif /* CONFIG_AP */ +} + + +void wpas_notify_eap_status(struct wpa_supplicant *wpa_s, const char *status, + const char *parameter) +{ +#ifdef CONFIG_DBUS + wpas_dbus_signal_eap_status(wpa_s, status, parameter); +#endif + wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_EAP_STATUS + "status='%s' parameter='%s'", + status, parameter); +} + + +void wpas_notify_network_bssid_set_changed(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid) +{ + if (wpa_s->current_ssid != ssid) + return; + + wpa_dbg(wpa_s, MSG_DEBUG, + "Network bssid config changed for the current network - within-ESS roaming %s", + ssid->bssid_set ? "disabled" : "enabled"); + + wpa_drv_roaming(wpa_s, !ssid->bssid_set, + ssid->bssid_set ? ssid->bssid : NULL); +} + + +void wpas_notify_network_type_changed(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid) +{ +#ifdef CONFIG_P2P + if (ssid->disabled == 2) { + /* Changed from normal network profile to persistent group */ + ssid->disabled = 0; + wpas_dbus_unregister_network(wpa_s, ssid->id); + ssid->disabled = 2; + ssid->p2p_persistent_group = 1; + wpas_dbus_register_persistent_group(wpa_s, ssid); + } else { + /* Changed from persistent group to normal network profile */ + wpas_dbus_unregister_persistent_group(wpa_s, ssid->id); + ssid->p2p_persistent_group = 0; + wpas_dbus_register_network(wpa_s, ssid); + } +#endif /* CONFIG_P2P */ +} diff --git a/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/notify.h b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/notify.h new file mode 100755 index 0000000..b617700 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/notify.h @@ -0,0 +1,144 @@ +/* + * wpa_supplicant - Event notifications + * Copyright (c) 2009-2010, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef NOTIFY_H +#define NOTIFY_H + +struct wps_credential; +struct wps_event_m2d; +struct wps_event_fail; + +int wpas_notify_supplicant_initialized(struct wpa_global *global); +void wpas_notify_supplicant_deinitialized(struct wpa_global *global); +int wpas_notify_iface_added(struct wpa_supplicant *wpa_s); +void wpas_notify_iface_removed(struct wpa_supplicant *wpa_s); +void wpas_notify_state_changed(struct wpa_supplicant *wpa_s, + enum wpa_states new_state, + enum wpa_states old_state); +void wpas_notify_disconnect_reason(struct wpa_supplicant *wpa_s); +void wpas_notify_network_changed(struct wpa_supplicant *wpa_s); +void wpas_notify_ap_scan_changed(struct wpa_supplicant *wpa_s); +void wpas_notify_bssid_changed(struct wpa_supplicant *wpa_s); +void wpas_notify_auth_changed(struct wpa_supplicant *wpa_s); +void wpas_notify_network_enabled_changed(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid); +void wpas_notify_network_selected(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid); +void wpas_notify_network_request(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid, + enum wpa_ctrl_req_type rtype, + const char *default_txt); +void wpas_notify_scanning(struct wpa_supplicant *wpa_s); +void wpas_notify_scan_done(struct wpa_supplicant *wpa_s, int success); +void wpas_notify_scan_results(struct wpa_supplicant *wpa_s); +void wpas_notify_wps_credential(struct wpa_supplicant *wpa_s, + const struct wps_credential *cred); +void wpas_notify_wps_event_m2d(struct wpa_supplicant *wpa_s, + struct wps_event_m2d *m2d); +void wpas_notify_wps_event_fail(struct wpa_supplicant *wpa_s, + struct wps_event_fail *fail); +void wpas_notify_wps_event_success(struct wpa_supplicant *wpa_s); +void wpas_notify_wps_event_pbc_overlap(struct wpa_supplicant *wpa_s); +void wpas_notify_network_added(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid); +void wpas_notify_network_removed(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid); +void wpas_notify_bss_added(struct wpa_supplicant *wpa_s, u8 bssid[], + unsigned int id); +void wpas_notify_bss_removed(struct wpa_supplicant *wpa_s, u8 bssid[], + unsigned int id); +void wpas_notify_bss_freq_changed(struct wpa_supplicant *wpa_s, + unsigned int id); +void wpas_notify_bss_signal_changed(struct wpa_supplicant *wpa_s, + unsigned int id); +void wpas_notify_bss_privacy_changed(struct wpa_supplicant *wpa_s, + unsigned int id); +void wpas_notify_bss_mode_changed(struct wpa_supplicant *wpa_s, + unsigned int id); +void wpas_notify_bss_wpaie_changed(struct wpa_supplicant *wpa_s, + unsigned int id); +void wpas_notify_bss_rsnie_changed(struct wpa_supplicant *wpa_s, + unsigned int id); +void wpas_notify_bss_wps_changed(struct wpa_supplicant *wpa_s, + unsigned int id); +void wpas_notify_bss_ies_changed(struct wpa_supplicant *wpa_s, + unsigned int id); +void wpas_notify_bss_rates_changed(struct wpa_supplicant *wpa_s, + unsigned int id); +void wpas_notify_bss_seen(struct wpa_supplicant *wpa_s, unsigned int id); +void wpas_notify_blob_added(struct wpa_supplicant *wpa_s, const char *name); +void wpas_notify_blob_removed(struct wpa_supplicant *wpa_s, const char *name); + +void wpas_notify_debug_level_changed(struct wpa_global *global); +void wpas_notify_debug_timestamp_changed(struct wpa_global *global); +void wpas_notify_debug_show_keys_changed(struct wpa_global *global); +void wpas_notify_suspend(struct wpa_global *global); +void wpas_notify_resume(struct wpa_global *global); + +void wpas_notify_sta_authorized(struct wpa_supplicant *wpa_s, + const u8 *mac_addr, int authorized, + const u8 *p2p_dev_addr); +#ifdef CONFIG_P2P +void wpas_notify_p2p_find_stopped(struct wpa_supplicant *wpa_s); +void wpas_notify_p2p_device_found(struct wpa_supplicant *wpa_s, + const u8 *dev_addr, int new_device); +void wpas_notify_p2p_device_lost(struct wpa_supplicant *wpa_s, + const u8 *dev_addr); +void wpas_notify_p2p_group_removed(struct wpa_supplicant *wpa_s, + const struct wpa_ssid *ssid, + const char *role); +void wpas_notify_p2p_go_neg_req(struct wpa_supplicant *wpa_s, + const u8 *src, u16 dev_passwd_id, u8 go_intent); +void wpas_notify_p2p_go_neg_completed(struct wpa_supplicant *wpa_s, + struct p2p_go_neg_results *res); +void wpas_notify_p2p_invitation_result(struct wpa_supplicant *wpa_s, + int status, const u8 *bssid); +void wpas_notify_p2p_sd_request(struct wpa_supplicant *wpa_s, + int freq, const u8 *sa, u8 dialog_token, + u16 update_indic, const u8 *tlvs, + size_t tlvs_len); +void wpas_notify_p2p_sd_response(struct wpa_supplicant *wpa_s, + const u8 *sa, u16 update_indic, + const u8 *tlvs, size_t tlvs_len); +void wpas_notify_p2p_provision_discovery(struct wpa_supplicant *wpa_s, + const u8 *dev_addr, int request, + enum p2p_prov_disc_status status, + u16 config_methods, + unsigned int generated_pin); +void wpas_notify_p2p_group_started(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid, int network_id, + int client); +void wpas_notify_p2p_group_formation_failure(struct wpa_supplicant *wpa_s, + const char *reason); +void wpas_notify_persistent_group_added(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid); +void wpas_notify_persistent_group_removed(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid); + +void wpas_notify_p2p_wps_failed(struct wpa_supplicant *wpa_s, + struct wps_event_fail *fail); +#endif + +void wpas_notify_certification(struct wpa_supplicant *wpa_s, int depth, + const char *subject, const char *altsubject[], + int num_altsubject, const char *cert_hash, + const struct wpabuf *cert); +void wpas_notify_preq(struct wpa_supplicant *wpa_s, + const u8 *addr, const u8 *dst, const u8 *bssid, + const u8 *ie, size_t ie_len, u32 ssi_signal); +void wpas_notify_eap_status(struct wpa_supplicant *wpa_s, const char *status, + const char *parameter); +void wpas_notify_network_bssid_set_changed(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid); +void wpas_notify_network_type_changed(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid); +void wpas_notify_p2p_invitation_received(struct wpa_supplicant *wpa_s, + const u8 *sa, const u8 *go_dev_addr, + const u8 *bssid, int id, int op_freq); + +#endif /* NOTIFY_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/offchannel.h b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/offchannel.h new file mode 100755 index 0000000..0ad7e18 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/offchannel.h @@ -0,0 +1,35 @@ +/* + * wpa_supplicant - Off-channel Action frame TX/RX + * Copyright (c) 2009-2010, Atheros Communications + * Copyright (c) 2011, Qualcomm Atheros + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef OFFCHANNEL_H +#define OFFCHANNEL_H + +int offchannel_send_action(struct wpa_supplicant *wpa_s, unsigned int freq, + const u8 *dst, const u8 *src, const u8 *bssid, + const u8 *buf, size_t len, unsigned int wait_time, + void (*tx_cb)(struct wpa_supplicant *wpa_s, + unsigned int freq, const u8 *dst, + const u8 *src, const u8 *bssid, + const u8 *data, size_t data_len, + enum offchannel_send_action_result + result), + int no_cck); +void offchannel_send_action_done(struct wpa_supplicant *wpa_s); +void offchannel_remain_on_channel_cb(struct wpa_supplicant *wpa_s, + unsigned int freq, unsigned int duration); +void offchannel_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s, + unsigned int freq); +void offchannel_deinit(struct wpa_supplicant *wpa_s); +void offchannel_send_action_tx_status( + struct wpa_supplicant *wpa_s, const u8 *dst, const u8 *data, + size_t data_len, enum offchannel_send_action_result result); +const void * offchannel_pending_action_tx(struct wpa_supplicant *wpa_s); +void offchannel_clear_pending_action_tx(struct wpa_supplicant *wpa_s); + +#endif /* OFFCHANNEL_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/p2p_supplicant.h b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/p2p_supplicant.h new file mode 100755 index 0000000..56e6834 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/p2p_supplicant.h @@ -0,0 +1,335 @@ +/* + * wpa_supplicant - P2P + * Copyright (c) 2009-2010, Atheros Communications + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef P2P_SUPPLICANT_H +#define P2P_SUPPLICANT_H + +enum p2p_wps_method; +struct p2p_go_neg_results; +enum p2p_send_action_result; +struct p2p_peer_info; +struct p2p_channels; +struct wps_event_fail; +struct p2ps_provision; + +enum wpas_p2p_channel_update_trig { + WPAS_P2P_CHANNEL_UPDATE_ANY, + WPAS_P2P_CHANNEL_UPDATE_DRIVER, + WPAS_P2P_CHANNEL_UPDATE_STATE_CHANGE, + WPAS_P2P_CHANNEL_UPDATE_AVOID, + WPAS_P2P_CHANNEL_UPDATE_DISALLOW, + WPAS_P2P_CHANNEL_UPDATE_CS, +}; + +int wpas_p2p_add_p2pdev_interface(struct wpa_supplicant *wpa_s, + const char *conf_p2p_dev); +struct wpa_supplicant * wpas_get_p2p_go_iface(struct wpa_supplicant *wpa_s, + const u8 *ssid, size_t ssid_len); +struct wpa_supplicant * wpas_get_p2p_client_iface(struct wpa_supplicant *wpa_s, + const u8 *peer_dev_addr); +int wpas_p2p_connect(struct wpa_supplicant *wpa_s, const u8 *peer_addr, + const char *pin, enum p2p_wps_method wps_method, + int persistent_group, int auto_join, int join, + int auth, int go_intent, int freq, int persistent_id, + int pd, int ht40, int vht); +int wpas_p2p_handle_frequency_conflicts(struct wpa_supplicant *wpa_s, + int freq, struct wpa_ssid *ssid); +int wpas_p2p_group_add(struct wpa_supplicant *wpa_s, int persistent_group, + int freq, int ht40, int vht); +int wpas_p2p_group_add_persistent(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid, int addr_allocated, + int force_freq, int neg_freq, int ht40, + int vht, const struct p2p_channels *channels, + int connection_timeout, int force_scan); +struct p2p_group * wpas_p2p_group_init(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid); +enum wpas_p2p_prov_disc_use { + WPAS_P2P_PD_FOR_GO_NEG, + WPAS_P2P_PD_FOR_JOIN, + WPAS_P2P_PD_AUTO, + WPAS_P2P_PD_FOR_ASP +}; +int wpas_p2p_prov_disc(struct wpa_supplicant *wpa_s, const u8 *peer_addr, + const char *config_method, + enum wpas_p2p_prov_disc_use use, + struct p2ps_provision *p2ps_prov); +void wpas_send_action_tx_status(struct wpa_supplicant *wpa_s, const u8 *dst, + const u8 *data, size_t data_len, + enum p2p_send_action_result result); +int wpas_p2p_scan_result_text(const u8 *ies, size_t ies_len, char *buf, + char *end); +enum p2p_discovery_type; +int wpas_p2p_find(struct wpa_supplicant *wpa_s, unsigned int timeout, + enum p2p_discovery_type type, + unsigned int num_req_dev_types, const u8 *req_dev_types, + const u8 *dev_id, unsigned int search_delay, + u8 seek_cnt, const char **seek_string, int freq); +void wpas_p2p_stop_find(struct wpa_supplicant *wpa_s); +int wpas_p2p_listen(struct wpa_supplicant *wpa_s, unsigned int timeout); +int wpas_p2p_listen_start(struct wpa_supplicant *wpa_s, unsigned int timeout); +int wpas_p2p_assoc_req_ie(struct wpa_supplicant *wpa_s, struct wpa_bss *bss, + u8 *buf, size_t len, int p2p_group); +void wpas_p2p_scan_ie(struct wpa_supplicant *wpa_s, struct wpabuf *ies); +u64 wpas_p2p_sd_request(struct wpa_supplicant *wpa_s, const u8 *dst, + const struct wpabuf *tlvs); +u64 wpas_p2p_sd_request_asp(struct wpa_supplicant *wpa_s, const u8 *dst, u8 id, + const char *svc_str, const char *info_substr); +u64 wpas_p2p_sd_request_upnp(struct wpa_supplicant *wpa_s, const u8 *dst, + u8 version, const char *query); +u64 wpas_p2p_sd_request_wifi_display(struct wpa_supplicant *wpa_s, + const u8 *dst, const char *role); +int wpas_p2p_sd_cancel_request(struct wpa_supplicant *wpa_s, u64 req); +void wpas_p2p_sd_response(struct wpa_supplicant *wpa_s, int freq, + const u8 *dst, u8 dialog_token, + const struct wpabuf *resp_tlvs); +void wpas_p2p_sd_service_update(struct wpa_supplicant *wpa_s); +void wpas_p2p_service_flush(struct wpa_supplicant *wpa_s); +int wpas_p2p_service_add_bonjour(struct wpa_supplicant *wpa_s, + struct wpabuf *query, struct wpabuf *resp); +int wpas_p2p_service_del_bonjour(struct wpa_supplicant *wpa_s, + const struct wpabuf *query); +int wpas_p2p_service_add_upnp(struct wpa_supplicant *wpa_s, u8 version, + const char *service); +int wpas_p2p_service_del_upnp(struct wpa_supplicant *wpa_s, u8 version, + const char *service); +int wpas_p2p_service_add_asp(struct wpa_supplicant *wpa_s, int auto_accept, + u32 adv_id, const char *adv_str, u8 svc_state, + u16 config_methods, const char *svc_info, + const u8 *cpt_priority); +int wpas_p2p_service_del_asp(struct wpa_supplicant *wpa_s, u32 adv_id); +void wpas_p2p_service_flush_asp(struct wpa_supplicant *wpa_s); +int wpas_p2p_service_p2ps_id_exists(struct wpa_supplicant *wpa_s, u32 adv_id); +void wpas_sd_request(void *ctx, int freq, const u8 *sa, u8 dialog_token, + u16 update_indic, const u8 *tlvs, size_t tlvs_len); +void wpas_sd_response(void *ctx, const u8 *sa, u16 update_indic, + const u8 *tlvs, size_t tlvs_len); +int wpas_p2p_reject(struct wpa_supplicant *wpa_s, const u8 *addr); +int wpas_p2p_invite(struct wpa_supplicant *wpa_s, const u8 *peer_addr, + struct wpa_ssid *ssid, const u8 *go_dev_addr, int freq, + int ht40, int vht, int pref_freq); +int wpas_p2p_invite_group(struct wpa_supplicant *wpa_s, const char *ifname, + const u8 *peer_addr, const u8 *go_dev_addr); +int wpas_p2p_presence_req(struct wpa_supplicant *wpa_s, u32 duration1, + u32 interval1, u32 duration2, u32 interval2); +int wpas_p2p_ext_listen(struct wpa_supplicant *wpa_s, unsigned int period, + unsigned int interval); +int wpas_p2p_deauth_notif(struct wpa_supplicant *wpa_s, const u8 *bssid, + u16 reason_code, const u8 *ie, size_t ie_len, + int locally_generated); +void wpas_p2p_disassoc_notif(struct wpa_supplicant *wpa_s, const u8 *bssid, + u16 reason_code, const u8 *ie, size_t ie_len, + int locally_generated); +int wpas_p2p_set_noa(struct wpa_supplicant *wpa_s, u8 count, int start, + int duration); +int wpas_p2p_set_cross_connect(struct wpa_supplicant *wpa_s, int enabled); +int wpas_p2p_cancel(struct wpa_supplicant *wpa_s); +int wpas_p2p_unauthorize(struct wpa_supplicant *wpa_s, const char *addr); +int wpas_p2p_disconnect(struct wpa_supplicant *wpa_s); +struct wpa_ssid * wpas_p2p_get_persistent(struct wpa_supplicant *wpa_s, + const u8 *addr, const u8 *ssid, + size_t ssid_len); +void wpas_p2p_notify_ap_sta_authorized(struct wpa_supplicant *wpa_s, + const u8 *addr); +int wpas_p2p_scan_no_go_seen(struct wpa_supplicant *wpa_s); +int wpas_p2p_get_ht40_mode(struct wpa_supplicant *wpa_s, + struct hostapd_hw_modes *mode, u8 channel); +int wpas_p2p_get_vht80_center(struct wpa_supplicant *wpa_s, + struct hostapd_hw_modes *mode, u8 channel); +unsigned int wpas_p2p_search_delay(struct wpa_supplicant *wpa_s); +void wpas_p2p_new_psk_cb(struct wpa_supplicant *wpa_s, const u8 *mac_addr, + const u8 *p2p_dev_addr, + const u8 *psk, size_t psk_len); +void wpas_p2p_remove_client(struct wpa_supplicant *wpa_s, const u8 *peer, + int iface_addr); +struct wpabuf * wpas_p2p_nfc_handover_req(struct wpa_supplicant *wpa_s, + int ndef); +struct wpabuf * wpas_p2p_nfc_handover_sel(struct wpa_supplicant *wpa_s, + int ndef, int tag); +int wpas_p2p_nfc_tag_process(struct wpa_supplicant *wpa_s, + const struct wpabuf *data, int forced_freq); +int wpas_p2p_nfc_report_handover(struct wpa_supplicant *wpa_s, int init, + const struct wpabuf *req, + const struct wpabuf *sel, int forced_freq); +int wpas_p2p_nfc_tag_enabled(struct wpa_supplicant *wpa_s, int enabled); +void wpas_p2p_pbc_overlap_cb(void *eloop_ctx, void *timeout_ctx); + +#ifdef CONFIG_P2P + +int wpas_p2p_init(struct wpa_global *global, struct wpa_supplicant *wpa_s); +void wpas_p2p_deinit(struct wpa_supplicant *wpa_s); +void wpas_p2p_completed(struct wpa_supplicant *wpa_s); +void wpas_p2p_update_config(struct wpa_supplicant *wpa_s); +int wpas_p2p_probe_req_rx(struct wpa_supplicant *wpa_s, const u8 *addr, + const u8 *dst, const u8 *bssid, + const u8 *ie, size_t ie_len, + unsigned int rx_freq, int ssi_signal); +void wpas_p2p_wps_success(struct wpa_supplicant *wpa_s, const u8 *peer_addr, + int registrar); + +void wpas_p2p_update_channel_list(struct wpa_supplicant *wpa_s, + enum wpas_p2p_channel_update_trig trig); + +void wpas_p2p_update_best_channels(struct wpa_supplicant *wpa_s, + int freq_24, int freq_5, int freq_overall); +void wpas_p2p_rx_action(struct wpa_supplicant *wpa_s, const u8 *da, + const u8 *sa, const u8 *bssid, + u8 category, const u8 *data, size_t len, int freq); +void wpas_p2p_remain_on_channel_cb(struct wpa_supplicant *wpa_s, + unsigned int freq, unsigned int duration); +void wpas_p2p_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s, + unsigned int freq); +void wpas_p2p_interface_unavailable(struct wpa_supplicant *wpa_s); +void wpas_p2p_notif_connected(struct wpa_supplicant *wpa_s); +void wpas_p2p_notif_disconnected(struct wpa_supplicant *wpa_s); +int wpas_p2p_notif_pbc_overlap(struct wpa_supplicant *wpa_s); +int wpas_p2p_4way_hs_failed(struct wpa_supplicant *wpa_s); +void wpas_p2p_ap_setup_failed(struct wpa_supplicant *wpa_s); +void wpas_p2p_indicate_state_change(struct wpa_supplicant *wpa_s); +void wpas_p2p_deinit_iface(struct wpa_supplicant *wpa_s); +void wpas_p2p_ap_deinit(struct wpa_supplicant *wpa_s); +void wpas_p2p_network_removed(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid); +int wpas_p2p_in_progress(struct wpa_supplicant *wpa_s); +int wpas_p2p_wps_eapol_cb(struct wpa_supplicant *wpa_s); +void wpas_p2p_wps_failed(struct wpa_supplicant *wpa_s, + struct wps_event_fail *fail); +int wpas_p2p_group_remove(struct wpa_supplicant *wpa_s, const char *ifname); + +#else /* CONFIG_P2P */ + +static inline int +wpas_p2p_init(struct wpa_global *global, struct wpa_supplicant *wpa_s) +{ + return 0; +} + +static inline void wpas_p2p_deinit(struct wpa_supplicant *wpa_s) +{ +} + +static inline void wpas_p2p_completed(struct wpa_supplicant *wpa_s) +{ +} + +static inline void wpas_p2p_update_config(struct wpa_supplicant *wpa_s) +{ +} + +static inline int wpas_p2p_probe_req_rx(struct wpa_supplicant *wpa_s, + const u8 *addr, + const u8 *dst, const u8 *bssid, + const u8 *ie, size_t ie_len, + unsigned int rx_freq, int ssi_signal) +{ + return 0; +} + +static inline void wpas_p2p_wps_success(struct wpa_supplicant *wpa_s, + const u8 *peer_addr, int registrar) +{ +} + +static inline void +wpas_p2p_update_channel_list(struct wpa_supplicant *wpa_s, + enum wpas_p2p_channel_update_trig trig) +{ +} + +static inline void wpas_p2p_update_best_channels(struct wpa_supplicant *wpa_s, + int freq_24, int freq_5, + int freq_overall) +{ +} + +static inline void wpas_p2p_rx_action(struct wpa_supplicant *wpa_s, + const u8 *da, + const u8 *sa, const u8 *bssid, + u8 category, const u8 *data, size_t len, + int freq) +{ +} + +static inline void wpas_p2p_remain_on_channel_cb(struct wpa_supplicant *wpa_s, + unsigned int freq, + unsigned int duration) +{ +} + +static inline void +wpas_p2p_cancel_remain_on_channel_cb(struct wpa_supplicant *wpa_s, + unsigned int freq) +{ +} + +static inline void wpas_p2p_interface_unavailable(struct wpa_supplicant *wpa_s) +{ +} + +static inline void wpas_p2p_notif_connected(struct wpa_supplicant *wpa_s) +{ +} + +static inline void wpas_p2p_notif_disconnected(struct wpa_supplicant *wpa_s) +{ +} + +static inline int wpas_p2p_notif_pbc_overlap(struct wpa_supplicant *wpa_s) +{ + return 0; +} + +static inline int wpas_p2p_4way_hs_failed(struct wpa_supplicant *wpa_s) +{ + return 0; +} + +static inline void wpas_p2p_ap_setup_failed(struct wpa_supplicant *wpa_s) +{ +} + +static inline void wpas_p2p_indicate_state_change(struct wpa_supplicant *wpa_s) +{ +} + +static inline void wpas_p2p_deinit_iface(struct wpa_supplicant *wpa_s) +{ +} + +static inline void wpas_p2p_ap_deinit(struct wpa_supplicant *wpa_s) +{ +} + +static inline void wpas_p2p_network_removed(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid) +{ +} + +static inline int wpas_p2p_in_progress(struct wpa_supplicant *wpa_s) +{ + return 0; +} + +static inline int wpas_p2p_wps_eapol_cb(struct wpa_supplicant *wpa_s) +{ + return 0; +} + +static inline void wpas_p2p_wps_failed(struct wpa_supplicant *wpa_s, + struct wps_event_fail *fail) +{ +} + +static inline int wpas_p2p_group_remove(struct wpa_supplicant *wpa_s, + const char *ifname) +{ + return 0; +} + +#endif /* CONFIG_P2P */ + +#endif /* P2P_SUPPLICANT_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/scan.h b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/scan.h new file mode 100755 index 0000000..7650f5a --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/scan.h @@ -0,0 +1,58 @@ +/* + * WPA Supplicant - Scanning + * Copyright (c) 2003-2014, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef SCAN_H +#define SCAN_H + +int wpa_supplicant_enabled_networks(struct wpa_supplicant *wpa_s); +void wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec); +int wpa_supplicant_delayed_sched_scan(struct wpa_supplicant *wpa_s, + int sec, int usec); +int wpa_supplicant_req_sched_scan(struct wpa_supplicant *wpa_s); +void wpa_supplicant_cancel_scan(struct wpa_supplicant *wpa_s); +void wpa_supplicant_cancel_delayed_sched_scan(struct wpa_supplicant *wpa_s); +void wpa_supplicant_cancel_sched_scan(struct wpa_supplicant *wpa_s); +void wpa_supplicant_notify_scanning(struct wpa_supplicant *wpa_s, + int scanning); +struct wpa_driver_scan_params; +int wpa_supplicant_trigger_scan(struct wpa_supplicant *wpa_s, + struct wpa_driver_scan_params *params); +struct wpa_scan_results * +wpa_supplicant_get_scan_results(struct wpa_supplicant *wpa_s, + struct scan_info *info, int new_scan); +int wpa_supplicant_update_scan_results(struct wpa_supplicant *wpa_s); +const u8 * wpa_scan_get_ie(const struct wpa_scan_res *res, u8 ie); +const u8 * wpa_scan_get_vendor_ie(const struct wpa_scan_res *res, + u32 vendor_type); +const u8 * wpa_scan_get_vendor_ie_beacon(const struct wpa_scan_res *res, + u32 vendor_type); +struct wpabuf * wpa_scan_get_vendor_ie_multi(const struct wpa_scan_res *res, + u32 vendor_type); +int wpa_supplicant_filter_bssid_match(struct wpa_supplicant *wpa_s, + const u8 *bssid); +void wpa_supplicant_update_scan_int(struct wpa_supplicant *wpa_s, int sec); +void scan_only_handler(struct wpa_supplicant *wpa_s, + struct wpa_scan_results *scan_res); +int wpas_scan_scheduled(struct wpa_supplicant *wpa_s); +int wpa_supplicant_start_sched_scan(struct wpa_supplicant *wpa_s, + struct wpa_driver_scan_params *params, + int interval); +int wpa_supplicant_stop_sched_scan(struct wpa_supplicant *wpa_s); +struct wpa_driver_scan_params * +wpa_scan_clone_params(const struct wpa_driver_scan_params *src); +void wpa_scan_free_params(struct wpa_driver_scan_params *params); +int wpas_start_pno(struct wpa_supplicant *wpa_s); +int wpas_stop_pno(struct wpa_supplicant *wpa_s); + +void wpas_mac_addr_rand_scan_clear(struct wpa_supplicant *wpa_s, + unsigned int type); +int wpas_mac_addr_rand_scan_set(struct wpa_supplicant *wpa_s, + unsigned int type, const u8 *addr, + const u8 *mask); + +#endif /* SCAN_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/sme.h b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/sme.h new file mode 100755 index 0000000..fd5c3b4 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/sme.h @@ -0,0 +1,118 @@ +/* + * wpa_supplicant - SME + * Copyright (c) 2009-2010, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef SME_H +#define SME_H + +#ifdef CONFIG_SME + +void sme_authenticate(struct wpa_supplicant *wpa_s, + struct wpa_bss *bss, struct wpa_ssid *ssid); +void sme_associate(struct wpa_supplicant *wpa_s, enum wpas_mode mode, + const u8 *bssid, u16 auth_type); +void sme_event_auth(struct wpa_supplicant *wpa_s, union wpa_event_data *data); +int sme_update_ft_ies(struct wpa_supplicant *wpa_s, const u8 *md, + const u8 *ies, size_t ies_len); +void sme_event_assoc_reject(struct wpa_supplicant *wpa_s, + union wpa_event_data *data); +void sme_event_auth_timed_out(struct wpa_supplicant *wpa_s, + union wpa_event_data *data); +void sme_event_assoc_timed_out(struct wpa_supplicant *wpa_s, + union wpa_event_data *data); +void sme_event_disassoc(struct wpa_supplicant *wpa_s, + struct disassoc_info *info); +void sme_event_unprot_disconnect(struct wpa_supplicant *wpa_s, const u8 *sa, + const u8 *da, u16 reason_code); +void sme_sa_query_rx(struct wpa_supplicant *wpa_s, const u8 *sa, + const u8 *data, size_t len); +void sme_state_changed(struct wpa_supplicant *wpa_s); +void sme_disassoc_while_authenticating(struct wpa_supplicant *wpa_s, + const u8 *prev_pending_bssid); +void sme_clear_on_disassoc(struct wpa_supplicant *wpa_s); +void sme_deinit(struct wpa_supplicant *wpa_s); + +int sme_proc_obss_scan(struct wpa_supplicant *wpa_s); +void sme_sched_obss_scan(struct wpa_supplicant *wpa_s, int enable); + +#else /* CONFIG_SME */ + +static inline void sme_authenticate(struct wpa_supplicant *wpa_s, + struct wpa_bss *bss, + struct wpa_ssid *ssid) +{ +} + +static inline void sme_event_auth(struct wpa_supplicant *wpa_s, + union wpa_event_data *data) +{ +} + +static inline int sme_update_ft_ies(struct wpa_supplicant *wpa_s, const u8 *md, + const u8 *ies, size_t ies_len) +{ + return -1; +} + + +static inline void sme_event_assoc_reject(struct wpa_supplicant *wpa_s, + union wpa_event_data *data) +{ +} + +static inline void sme_event_auth_timed_out(struct wpa_supplicant *wpa_s, + union wpa_event_data *data) +{ +} + +static inline void sme_event_assoc_timed_out(struct wpa_supplicant *wpa_s, + union wpa_event_data *data) +{ +} + +static inline void sme_event_disassoc(struct wpa_supplicant *wpa_s, + struct disassoc_info *info) +{ +} + +static inline void sme_event_unprot_disconnect(struct wpa_supplicant *wpa_s, + const u8 *sa, const u8 *da, + u16 reason_code) +{ +} + +static inline void sme_state_changed(struct wpa_supplicant *wpa_s) +{ +} + +static inline void +sme_disassoc_while_authenticating(struct wpa_supplicant *wpa_s, + const u8 *prev_pending_bssid) +{ +} + +static inline void sme_clear_on_disassoc(struct wpa_supplicant *wpa_s) +{ +} + +static inline void sme_deinit(struct wpa_supplicant *wpa_s) +{ +} + +static inline int sme_proc_obss_scan(struct wpa_supplicant *wpa_s) +{ + return 0; +} + +static inline void sme_sched_obss_scan(struct wpa_supplicant *wpa_s, + int enable) +{ +} + +#endif /* CONFIG_SME */ + +#endif /* SME_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/wifi_display.h b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/wifi_display.h new file mode 100755 index 0000000..0966bdb --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/wifi_display.h @@ -0,0 +1,24 @@ +/* + * wpa_supplicant - Wi-Fi Display + * Copyright (c) 2011, Atheros Communications, Inc. + * Copyright (c) 2011-2012, Qualcomm Atheros, Inc. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef WIFI_DISPLAY_H +#define WIFI_DISPLAY_H + +int wifi_display_init(struct wpa_global *global); +void wifi_display_deinit(struct wpa_global *global); +void wifi_display_enable(struct wpa_global *global, int enabled); +struct wpabuf *wifi_display_get_wfd_ie(struct wpa_global *global); +int wifi_display_subelem_set(struct wpa_global *global, char *cmd); +int wifi_display_subelem_set_from_ies(struct wpa_global *global, + struct wpabuf *ie); +int wifi_display_subelem_get(struct wpa_global *global, char *cmd, + char *buf, size_t buflen); +char * wifi_display_subelem_hex(const struct wpabuf *wfd_subelems, u8 id); + +#endif /* WIFI_DISPLAY_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/wmm_ac.c b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/wmm_ac.c new file mode 100755 index 0000000..5301b01 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/wmm_ac.c @@ -0,0 +1,996 @@ +/* + * Wi-Fi Multimedia Admission Control (WMM-AC) + * Copyright(c) 2014, Intel Mobile Communication GmbH. + * Copyright(c) 2014, Intel Corporation. All rights reserved. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "includes.h" + +#include "utils/common.h" +#include "utils/list.h" +#include "utils/eloop.h" +#include "common/ieee802_11_common.h" +#include "wpa_supplicant_i.h" +#include "bss.h" +#include "driver_i.h" +#include "wmm_ac.h" + +static void wmm_ac_addts_req_timeout(void *eloop_ctx, void *timeout_ctx); + +static const enum wmm_ac up_to_ac[8] = { + WMM_AC_BK, + WMM_AC_BE, + WMM_AC_BE, + WMM_AC_BK, + WMM_AC_VI, + WMM_AC_VI, + WMM_AC_VO, + WMM_AC_VO +}; + + +static inline u8 wmm_ac_get_tsid(const struct wmm_tspec_element *tspec) +{ + return (tspec->ts_info[0] >> 1) & 0x0f; +} + + +static u8 wmm_ac_get_direction(const struct wmm_tspec_element *tspec) +{ + return (tspec->ts_info[0] >> 5) & 0x03; +} + + +static u8 wmm_ac_get_user_priority(const struct wmm_tspec_element *tspec) +{ + return (tspec->ts_info[1] >> 3) & 0x07; +} + + +static u8 wmm_ac_direction_to_idx(u8 direction) +{ + switch (direction) { + case WMM_AC_DIR_UPLINK: + return TS_DIR_IDX_UPLINK; + case WMM_AC_DIR_DOWNLINK: + return TS_DIR_IDX_DOWNLINK; + case WMM_AC_DIR_BIDIRECTIONAL: + return TS_DIR_IDX_BIDI; + default: + wpa_printf(MSG_ERROR, "Invalid direction: %d", direction); + return WMM_AC_DIR_UPLINK; + } +} + + +static int wmm_ac_add_ts(struct wpa_supplicant *wpa_s, const u8 *addr, + const struct wmm_tspec_element *tspec) +{ + struct wmm_tspec_element *_tspec; + int ret; + u16 admitted_time = le_to_host16(tspec->medium_time); + u8 up = wmm_ac_get_user_priority(tspec); + u8 ac = up_to_ac[up]; + u8 dir = wmm_ac_get_direction(tspec); + u8 tsid = wmm_ac_get_tsid(tspec); + int idx = wmm_ac_direction_to_idx(dir); // enum ts_dir_idx + + /* should have been verified before, but double-check here */ + if (wpa_s->tspecs[ac][idx]) { + wpa_printf(MSG_ERROR, + "WMM AC: tspec (ac=%d, dir=%d) already exists!", + ac, dir); + return -1; + } + + /* copy tspec */ + _tspec = os_malloc(sizeof(*_tspec)); + if (!_tspec) + return -1; + + /* store the admitted TSPEC */ + os_memcpy(_tspec, tspec, sizeof(*_tspec)); + + if (dir != WMM_AC_DIR_DOWNLINK) { + ret = wpa_drv_add_ts(wpa_s, tsid, addr, up, admitted_time); + wpa_printf(MSG_DEBUG, + "WMM AC: Add TS: addr=" MACSTR + " TSID=%u admitted time=%u, ret=%d", + MAC2STR(addr), tsid, admitted_time, ret); + if (ret < 0) { + os_free(_tspec); + return -1; + } + } + + wpa_s->tspecs[ac][idx] = _tspec; + + wpa_printf(MSG_DEBUG, "Traffic stream was created successfully"); + + wpa_msg(wpa_s, MSG_INFO, WMM_AC_EVENT_TSPEC_ADDED + "tsid=%d addr=" MACSTR " admitted_time=%d", + tsid, MAC2STR(addr), admitted_time); + + return 0; +} + + +static void wmm_ac_del_ts_idx(struct wpa_supplicant *wpa_s, u8 ac, + enum ts_dir_idx dir) +{ + struct wmm_tspec_element *tspec = wpa_s->tspecs[ac][dir]; + u8 tsid; + + if (!tspec) + return; + + tsid = wmm_ac_get_tsid(tspec); + wpa_printf(MSG_DEBUG, "WMM AC: Del TS ac=%d tsid=%d", ac, tsid); + + /* update the driver in case of uplink/bidi */ + if (wmm_ac_get_direction(tspec) != WMM_AC_DIR_DOWNLINK) + wpa_drv_del_ts(wpa_s, tsid, wpa_s->bssid); + + wpa_msg(wpa_s, MSG_INFO, WMM_AC_EVENT_TSPEC_REMOVED + "tsid=%d addr=" MACSTR, tsid, MAC2STR(wpa_s->bssid)); + + os_free(wpa_s->tspecs[ac][dir]); + wpa_s->tspecs[ac][dir] = NULL; +} + + +static void wmm_ac_del_req(struct wpa_supplicant *wpa_s, int failed) +{ + struct wmm_ac_addts_request *req = wpa_s->addts_request; + + if (!req) + return; + + if (failed) + wpa_msg(wpa_s, MSG_INFO, WMM_AC_EVENT_TSPEC_REQ_FAILED + "tsid=%u", wmm_ac_get_tsid(&req->tspec)); + + eloop_cancel_timeout(wmm_ac_addts_req_timeout, wpa_s, req); + wpa_s->addts_request = NULL; + os_free(req); +} + + +static void wmm_ac_addts_req_timeout(void *eloop_ctx, void *timeout_ctx) +{ + struct wpa_supplicant *wpa_s = eloop_ctx; + struct wmm_ac_addts_request *addts_req = timeout_ctx; + + wpa_printf(MSG_DEBUG, + "Timeout getting ADDTS response (tsid=%d up=%d)", + wmm_ac_get_tsid(&addts_req->tspec), + wmm_ac_get_user_priority(&addts_req->tspec)); + + wmm_ac_del_req(wpa_s, 1); + (void)addts_req; +} + + +static int wmm_ac_send_addts_request(struct wpa_supplicant *wpa_s, + const struct wmm_ac_addts_request *req) +{ + struct wpabuf *buf; + int ret; + + wpa_printf(MSG_DEBUG, "Sending ADDTS Request to " MACSTR, + MAC2STR(req->address)); + + /* category + action code + dialog token + status + sizeof(tspec) */ + buf = wpabuf_alloc(4 + sizeof(req->tspec)); + if (!buf) { + wpa_printf(MSG_ERROR, "WMM AC: Allocation error"); + return -1; + } + + wpabuf_put_u8(buf, WLAN_ACTION_WMM); + wpabuf_put_u8(buf, WMM_ACTION_CODE_ADDTS_REQ); + wpabuf_put_u8(buf, req->dialog_token); + wpabuf_put_u8(buf, 0); /* status code */ + wpabuf_put_data(buf, &req->tspec, sizeof(req->tspec)); + + ret = wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, req->address, + wpa_s->own_addr, wpa_s->bssid, + wpabuf_head(buf), wpabuf_len(buf), 0); + if (ret) { + wpa_printf(MSG_WARNING, + "WMM AC: Failed to send ADDTS Request"); + } + + wpabuf_free(buf); + return ret; +} + + +static int wmm_ac_send_delts(struct wpa_supplicant *wpa_s, + const struct wmm_tspec_element *tspec, + const u8 *address) +{ + struct wpabuf *buf; + int ret; + + /* category + action code + dialog token + status + sizeof(tspec) */ + buf = wpabuf_alloc(4 + sizeof(*tspec)); + if (!buf) + return -1; + + wpa_printf(MSG_DEBUG, "Sending DELTS to " MACSTR, MAC2STR(address)); + + /* category + action code + dialog token + status + sizeof(tspec) */ + wpabuf_put_u8(buf, WLAN_ACTION_WMM); + wpabuf_put_u8(buf, WMM_ACTION_CODE_DELTS); + wpabuf_put_u8(buf, 0); /* Dialog Token (not used) */ + wpabuf_put_u8(buf, 0); /* Status Code (not used) */ + wpabuf_put_data(buf, tspec, sizeof(*tspec)); + + ret = wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, address, + wpa_s->own_addr, wpa_s->bssid, + wpabuf_head(buf), wpabuf_len(buf), 0); + if (ret) + wpa_printf(MSG_WARNING, "Failed to send DELTS frame"); + + wpabuf_free(buf); + return ret; +} + + +/* return the AC using the given TSPEC tid */ +static int wmm_ac_find_tsid(struct wpa_supplicant *wpa_s, u8 tsid, + enum ts_dir_idx *dir) +{ + int ac; + int idx; // enum ts_dir_idx + + for (ac = 0; ac < WMM_AC_NUM; ac++) { + for (idx = 0; idx < TS_DIR_IDX_COUNT; idx++) { + if (wpa_s->tspecs[ac][idx] && + wmm_ac_get_tsid(wpa_s->tspecs[ac][idx]) == tsid) { + if (dir) + *dir = (enum ts_dir_idx)idx; + return ac; + } + } + } + + return -1; +} + + +static struct wmm_ac_addts_request * +wmm_ac_build_addts_req(struct wpa_supplicant *wpa_s, + const struct wmm_ac_ts_setup_params *params, + const u8 *address) +{ + struct wmm_ac_addts_request *addts_req; + struct wmm_tspec_element *tspec; + u8 ac = up_to_ac[params->user_priority]; + u8 uapsd = wpa_s->wmm_ac_assoc_info->ac_params[ac].uapsd; + + addts_req = os_zalloc(sizeof(*addts_req)); + if (!addts_req) + return NULL; + + tspec = &addts_req->tspec; + os_memcpy(addts_req->address, address, ETH_ALEN); + + /* The dialog token cannot be zero */ + if (++wpa_s->wmm_ac_last_dialog_token == 0) + wpa_s->wmm_ac_last_dialog_token++; + + addts_req->dialog_token = wpa_s->wmm_ac_last_dialog_token; + tspec->eid = WLAN_EID_VENDOR_SPECIFIC; + tspec->length = sizeof(*tspec) - 2; /* reduce eid and length */ + tspec->oui[0] = 0x00; + tspec->oui[1] = 0x50; + tspec->oui[2] = 0xf2; + tspec->oui_type = WMM_OUI_TYPE; + tspec->oui_subtype = WMM_OUI_SUBTYPE_TSPEC_ELEMENT; + tspec->version = WMM_VERSION; + + tspec->ts_info[0] = params->tsid << 1; + tspec->ts_info[0] |= params->direction << 5; + tspec->ts_info[0] |= WMM_AC_ACCESS_POLICY_EDCA << 7; + tspec->ts_info[1] = uapsd << 2; + tspec->ts_info[1] |= params->user_priority << 3; + tspec->ts_info[2] = 0; + + tspec->nominal_msdu_size = host_to_le16(params->nominal_msdu_size); + if (params->fixed_nominal_msdu) + tspec->nominal_msdu_size |= + host_to_le16(WMM_AC_FIXED_MSDU_SIZE); + + tspec->mean_data_rate = host_to_le32(params->mean_data_rate); + tspec->minimum_phy_rate = host_to_le32(params->minimum_phy_rate); + tspec->surplus_bandwidth_allowance = + host_to_le16(params->surplus_bandwidth_allowance); + + return addts_req; +} + + +static int param_in_range(const char *name, long value, + long min_val, long max_val) +{ + if (value < min_val || (max_val >= 0 && value > max_val)) { + wpa_printf(MSG_DEBUG, + "WMM AC: param %s (%ld) is out of range (%ld-%ld)", + name, value, min_val, max_val); + return 0; + } + + return 1; +} + + +static int wmm_ac_should_replace_ts(struct wpa_supplicant *wpa_s, + u8 tsid, u8 ac, u8 dir) +{ + int idx; // enum ts_dir_idx + int cur_ac, existing_ts = 0, replace_ts = 0; + + cur_ac = wmm_ac_find_tsid(wpa_s, tsid, (enum ts_dir_idx *)&idx); + if (cur_ac >= 0) { + if (cur_ac != ac) { + wpa_printf(MSG_DEBUG, + "WMM AC: TSID %i already exists on different ac (%d)", + tsid, cur_ac); + return -1; + } + + /* same tsid - this tspec will replace the current one */ + replace_ts |= BIT(idx); + } + + for (idx = 0; idx < TS_DIR_IDX_COUNT; idx++) { + if (wpa_s->tspecs[ac][idx]) + existing_ts |= BIT(idx); + } + + switch (dir) { + case WMM_AC_DIR_UPLINK: + /* replace existing uplink/bidi tspecs */ + replace_ts |= existing_ts & (BIT(TS_DIR_IDX_UPLINK) | + BIT(TS_DIR_IDX_BIDI)); + break; + case WMM_AC_DIR_DOWNLINK: + /* replace existing downlink/bidi tspecs */ + replace_ts |= existing_ts & (BIT(TS_DIR_IDX_DOWNLINK) | + BIT(TS_DIR_IDX_BIDI)); + break; + case WMM_AC_DIR_BIDIRECTIONAL: + /* replace all existing tspecs */ + replace_ts |= existing_ts; + break; + default: + return -1; + } + + return replace_ts; +} + + +static int wmm_ac_ts_req_is_valid(struct wpa_supplicant *wpa_s, + const struct wmm_ac_ts_setup_params *params) +{ + enum wmm_ac req_ac; + +#define PARAM_IN_RANGE(field, min_value, max_value) \ + param_in_range(#field, params->field, min_value, max_value) + + if (!PARAM_IN_RANGE(tsid, 0, WMM_AC_MAX_TID) || + !PARAM_IN_RANGE(user_priority, 0, WMM_AC_MAX_USER_PRIORITY) || + !PARAM_IN_RANGE(nominal_msdu_size, 1, WMM_AC_MAX_NOMINAL_MSDU) || + !PARAM_IN_RANGE(mean_data_rate, 1, -1) || + !PARAM_IN_RANGE(minimum_phy_rate, 1, -1) || + !PARAM_IN_RANGE(surplus_bandwidth_allowance, WMM_AC_MIN_SBA_UNITY, + -1)) + return 0; +#undef PARAM_IN_RANGE + + if (!(params->direction == WMM_TSPEC_DIRECTION_UPLINK || + params->direction == WMM_TSPEC_DIRECTION_DOWNLINK || + params->direction == WMM_TSPEC_DIRECTION_BI_DIRECTIONAL)) { + wpa_printf(MSG_DEBUG, "WMM AC: invalid TS direction: %d", + params->direction); + return 0; + } + + req_ac = up_to_ac[params->user_priority]; + + /* Requested accesss category must have acm */ + if (!wpa_s->wmm_ac_assoc_info->ac_params[req_ac].acm) { + wpa_printf(MSG_DEBUG, "WMM AC: AC %d is not ACM", req_ac); + return 0; + } + + if (wmm_ac_should_replace_ts(wpa_s, params->tsid, req_ac, + params->direction) < 0) + return 0; + + return 1; +} + + +static struct wmm_ac_assoc_data * +wmm_ac_process_param_elem(struct wpa_supplicant *wpa_s, const u8 *ies, + size_t ies_len) +{ + struct ieee802_11_elems elems; + struct wmm_parameter_element *wmm_params; + struct wmm_ac_assoc_data *assoc_data; + int i; + + /* Parsing WMM Parameter Element */ + if (ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed) { + wpa_printf(MSG_DEBUG, "WMM AC: could not parse assoc ies"); + return NULL; + } + + if (!elems.wmm) { + wpa_printf(MSG_DEBUG, "WMM AC: No WMM IE"); + return NULL; + } + + if (elems.wmm_len != sizeof(*wmm_params)) { + wpa_printf(MSG_DEBUG, "WMM AC: Invalid WMM ie length"); + return NULL; + } + + wmm_params = (struct wmm_parameter_element *)(elems.wmm); + + assoc_data = os_zalloc(sizeof(*assoc_data)); + if (!assoc_data) + return NULL; + + for (i = 0; i < WMM_AC_NUM; i++) + assoc_data->ac_params[i].acm = + !!(wmm_params->ac[i].aci_aifsn & WMM_AC_ACM); + + wpa_printf(MSG_DEBUG, + "WMM AC: AC mandatory: AC_BE=%u AC_BK=%u AC_VI=%u AC_VO=%u", + assoc_data->ac_params[WMM_AC_BE].acm, + assoc_data->ac_params[WMM_AC_BK].acm, + assoc_data->ac_params[WMM_AC_VI].acm, + assoc_data->ac_params[WMM_AC_VO].acm); + + return assoc_data; +} + + +static int wmm_ac_init(struct wpa_supplicant *wpa_s, const u8 *ies, + size_t ies_len, const struct wmm_params *wmm_params) +{ + struct wmm_ac_assoc_data *assoc_data; + u8 ac; + + if (wpa_s->wmm_ac_assoc_info) { + wpa_printf(MSG_ERROR, "WMM AC: Already initialized"); + return -1; + } + + if (!ies) { + wpa_printf(MSG_ERROR, "WMM AC: Missing IEs"); + return -1; + } + + if (!(wmm_params->info_bitmap & WMM_PARAMS_UAPSD_QUEUES_INFO)) { + wpa_printf(MSG_DEBUG, "WMM AC: Missing U-APSD configuration"); + return -1; + } + + os_memset(wpa_s->tspecs, 0, sizeof(wpa_s->tspecs)); + wpa_s->wmm_ac_last_dialog_token = 0; + wpa_s->addts_request = NULL; + + assoc_data = wmm_ac_process_param_elem(wpa_s, ies, ies_len); + if (!assoc_data) + return -1; + + wpa_printf(MSG_DEBUG, "WMM AC: U-APSD queues=0x%x", + wmm_params->uapsd_queues); + + for (ac = 0; ac < WMM_AC_NUM; ac++) { + assoc_data->ac_params[ac].uapsd = + !!(wmm_params->uapsd_queues & BIT(ac)); + } + + wpa_s->wmm_ac_assoc_info = assoc_data; + return 0; +} + + +static void wmm_ac_del_ts(struct wpa_supplicant *wpa_s, u8 ac, int dir_bitmap) +{ + int idx; + + for (idx = 0; idx < TS_DIR_IDX_COUNT; idx++) { + if (!(dir_bitmap & BIT(idx))) + continue; + + wmm_ac_del_ts_idx(wpa_s, ac, (enum ts_dir_idx)idx); + } +} + + +static void wmm_ac_deinit(struct wpa_supplicant *wpa_s) +{ + int i; + + for (i = 0; i < WMM_AC_NUM; i++) + wmm_ac_del_ts(wpa_s, i, TS_DIR_IDX_ALL); + + /* delete pending add_ts requset */ + wmm_ac_del_req(wpa_s, 1); + + os_free(wpa_s->wmm_ac_assoc_info); + wpa_s->wmm_ac_assoc_info = NULL; +} + + +void wmm_ac_notify_assoc(struct wpa_supplicant *wpa_s, const u8 *ies, + size_t ies_len, const struct wmm_params *wmm_params) +{ + if (wmm_ac_init(wpa_s, ies, ies_len, wmm_params)) + return; + + wpa_printf(MSG_DEBUG, + "WMM AC: Valid WMM association, WMM AC is enabled"); +} + + +void wmm_ac_notify_disassoc(struct wpa_supplicant *wpa_s) +{ + if (!wpa_s->wmm_ac_assoc_info) + return; + + wmm_ac_deinit(wpa_s); + wpa_printf(MSG_DEBUG, "WMM AC: WMM AC is disabled"); +} + + +int wpas_wmm_ac_delts(struct wpa_supplicant *wpa_s, u8 tsid) +{ + struct wmm_tspec_element tspec; + int ac; + enum ts_dir_idx dir; + + if (!wpa_s->wmm_ac_assoc_info) { + wpa_printf(MSG_DEBUG, + "WMM AC: Failed to delete TS, WMM AC is disabled"); + return -1; + } + + ac = wmm_ac_find_tsid(wpa_s, tsid, &dir); + if (ac < 0) { + wpa_printf(MSG_DEBUG, "WMM AC: TS does not exist"); + return -1; + } + + tspec = *wpa_s->tspecs[ac][dir]; + + wmm_ac_del_ts_idx(wpa_s, ac, dir); + + wmm_ac_send_delts(wpa_s, &tspec, wpa_s->bssid); + + return 0; +} + + +int wpas_wmm_ac_addts(struct wpa_supplicant *wpa_s, + struct wmm_ac_ts_setup_params *params) +{ + struct wmm_ac_addts_request *addts_req; + + if (!wpa_s->wmm_ac_assoc_info) { + wpa_printf(MSG_DEBUG, + "WMM AC: Cannot add TS - missing assoc data"); + return -1; + } + + if (wpa_s->addts_request) { + wpa_printf(MSG_DEBUG, + "WMM AC: can't add TS - ADDTS request is already pending"); + return -1; + } + + /* + * we can setup downlink TS even without driver support. + * however, we need driver support for the other directions. + */ + if (params->direction != WMM_AC_DIR_DOWNLINK && + !wpa_s->wmm_ac_supported) { + wpa_printf(MSG_DEBUG, + "Cannot set uplink/bidi TS without driver support"); + return -1; + } + + if (!wmm_ac_ts_req_is_valid(wpa_s, params)) + return -1; + + wpa_printf(MSG_DEBUG, "WMM AC: TS setup request (addr=" MACSTR + " tsid=%u user priority=%u direction=%d)", + MAC2STR(wpa_s->bssid), params->tsid, + params->user_priority, params->direction); + + addts_req = wmm_ac_build_addts_req(wpa_s, params, wpa_s->bssid); + if (!addts_req) + return -1; + + if (wmm_ac_send_addts_request(wpa_s, addts_req)) + goto err; + + /* save as pending and set ADDTS resp timeout to 1 second */ + wpa_s->addts_request = addts_req; + eloop_register_timeout(1, 0, wmm_ac_addts_req_timeout, + wpa_s, addts_req); + return 0; +err: + os_free(addts_req); + return -1; +} + + +static void wmm_ac_handle_delts(struct wpa_supplicant *wpa_s, const u8 *sa, + const struct wmm_tspec_element *tspec) +{ + int ac; + u8 tsid; + enum ts_dir_idx idx; + + tsid = wmm_ac_get_tsid(tspec); + + wpa_printf(MSG_DEBUG, + "WMM AC: DELTS frame has been received TSID=%u addr=" + MACSTR, tsid, MAC2STR(sa)); + + ac = wmm_ac_find_tsid(wpa_s, tsid, &idx); + if (ac < 0) { + wpa_printf(MSG_DEBUG, + "WMM AC: Ignoring DELTS frame - TSID does not exist"); + return; + } + + wmm_ac_del_ts_idx(wpa_s, ac, idx); + + wpa_printf(MSG_DEBUG, + "TS was deleted successfully (tsid=%u address=" MACSTR ")", + tsid, MAC2STR(sa)); +} + + +static void wmm_ac_handle_addts_resp(struct wpa_supplicant *wpa_s, const u8 *sa, + const u8 resp_dialog_token, const u8 status_code, + const struct wmm_tspec_element *tspec) +{ + struct wmm_ac_addts_request *req = wpa_s->addts_request; + u8 ac, tsid, up, dir; + int replace_tspecs; + + tsid = wmm_ac_get_tsid(tspec); + dir = wmm_ac_get_direction(tspec); + up = wmm_ac_get_user_priority(tspec); + ac = up_to_ac[up]; + + /* make sure we have a matching addts request */ + if (!req || req->dialog_token != resp_dialog_token) { + wpa_printf(MSG_DEBUG, + "WMM AC: no req with dialog=%u, ignoring frame", + resp_dialog_token); + return; + } + + /* make sure the params are the same */ + if (os_memcmp(req->address, sa, ETH_ALEN) != 0 || + tsid != wmm_ac_get_tsid(&req->tspec) || + up != wmm_ac_get_user_priority(&req->tspec) || + dir != wmm_ac_get_direction(&req->tspec)) { + wpa_printf(MSG_DEBUG, + "WMM AC: ADDTS params do not match, ignoring frame"); + return; + } + + /* delete pending request */ + wmm_ac_del_req(wpa_s, 0); + + wpa_printf(MSG_DEBUG, + "ADDTS response status=%d tsid=%u up=%u direction=%u", + status_code, tsid, up, dir); + + if (status_code != WMM_ADDTS_STATUS_ADMISSION_ACCEPTED) { + wpa_printf(MSG_INFO, "WMM AC: ADDTS request was rejected"); + goto err_msg; + } + + replace_tspecs = wmm_ac_should_replace_ts(wpa_s, tsid, ac, dir); + if (replace_tspecs < 0) + goto err_delts; + + wpa_printf(MSG_DEBUG, "ts idx replace bitmap: 0x%x", replace_tspecs); + + /* when replacing tspecs - delete first */ + wmm_ac_del_ts(wpa_s, ac, replace_tspecs); + + /* Creating a new traffic stream */ + wpa_printf(MSG_DEBUG, + "WMM AC: adding a new TS with TSID=%u address="MACSTR + " medium time=%u access category=%d dir=%d ", + tsid, MAC2STR(sa), + le_to_host16(tspec->medium_time), ac, dir); + + if (wmm_ac_add_ts(wpa_s, sa, tspec)) + goto err_delts; + + return; + +err_delts: + /* ask the ap to delete the tspec */ + wmm_ac_send_delts(wpa_s, tspec, sa); +err_msg: + wpa_msg(wpa_s, MSG_INFO, WMM_AC_EVENT_TSPEC_REQ_FAILED "tsid=%u", + tsid); +} + + +void wmm_ac_rx_action(struct wpa_supplicant *wpa_s, const u8 *da, + const u8 *sa, const u8 *data, size_t len) +{ + u8 action; + u8 dialog_token; + u8 status_code; + struct ieee802_11_elems elems; + struct wmm_tspec_element *tspec; + + if (wpa_s->wmm_ac_assoc_info == NULL) { + wpa_printf(MSG_DEBUG, + "WMM AC: WMM AC is disabled, ignoring action frame"); + return; + } + + action = data[0]; + + if (action != WMM_ACTION_CODE_ADDTS_RESP && + action != WMM_ACTION_CODE_DELTS) { + wpa_printf(MSG_DEBUG, + "WMM AC: Unknown action (%d), ignoring action frame", + action); + return; + } + + /* WMM AC action frame */ + if (os_memcmp(da, wpa_s->own_addr, ETH_ALEN) != 0) { + wpa_printf(MSG_DEBUG, "WMM AC: frame destination addr="MACSTR + " is other than ours, ignoring frame", MAC2STR(da)); + return; + } + + if (os_memcmp(sa, wpa_s->bssid, ETH_ALEN) != 0) { + wpa_printf(MSG_DEBUG, "WMM AC: ignore frame with sa " MACSTR + " different other than our bssid", MAC2STR(da)); + return; + } + + if (len < 2 + sizeof(struct wmm_tspec_element)) { + wpa_printf(MSG_DEBUG, + "WMM AC: Short ADDTS response ignored (len=%lu)", + (unsigned long) len); + return; + } + + data++; + len--; + dialog_token = data[0]; + status_code = data[1]; + + if (ieee802_11_parse_elems(data + 2, len - 2, &elems, 1) != ParseOK) { + wpa_printf(MSG_DEBUG, + "WMM AC: Could not parse WMM AC action from " MACSTR, + MAC2STR(sa)); + return; + } + + /* the struct also contains the type and value, so decrease it */ + if (elems.wmm_tspec_len != sizeof(struct wmm_tspec_element) - 2) { + wpa_printf(MSG_DEBUG, "WMM AC: missing or wrong length TSPEC"); + return; + } + + tspec = (struct wmm_tspec_element *)(elems.wmm_tspec - 2); + + wpa_printf(MSG_DEBUG, "WMM AC: RX WMM AC Action from " MACSTR, + MAC2STR(sa)); + wpa_hexdump(MSG_MSGDUMP, "WMM AC: WMM AC Action content", data, len); + + switch (action) { + case WMM_ACTION_CODE_ADDTS_RESP: + wmm_ac_handle_addts_resp(wpa_s, sa, dialog_token, status_code, + tspec); + break; + case WMM_ACTION_CODE_DELTS: + wmm_ac_handle_delts(wpa_s, sa, tspec); + break; + default: + break; + } +} + + +static const char * get_ac_str(u8 ac) +{ + switch (ac) { + case WMM_AC_BE: + return "BE"; + case WMM_AC_BK: + return "BK"; + case WMM_AC_VI: + return "VI"; + case WMM_AC_VO: + return "VO"; + default: + return "N/A"; + } +} + + +static const char * get_direction_str(u8 direction) +{ + switch (direction) { + case WMM_AC_DIR_DOWNLINK: + return "Downlink"; + case WMM_AC_DIR_UPLINK: + return "Uplink"; + case WMM_AC_DIR_BIDIRECTIONAL: + return "Bi-directional"; + default: + return "N/A"; + } +} + + +int wpas_wmm_ac_status(struct wpa_supplicant *wpa_s, char *buf, size_t buflen) +{ + struct wmm_ac_assoc_data *assoc_info = wpa_s->wmm_ac_assoc_info; + int idx; + int pos = 0; + u8 ac, up; + + if (!assoc_info) { + return wpa_scnprintf(buf, buflen - pos, + "Not associated to a WMM AP, WMM AC is Disabled\n"); + } + + pos += wpa_scnprintf(buf + pos, buflen - pos, "WMM AC is Enabled\n"); + + for (ac = 0; ac < WMM_AC_NUM; ac++) { + int ts_count = 0; + + pos += wpa_scnprintf(buf + pos, buflen - pos, + "%s: acm=%d uapsd=%d\n", + get_ac_str(ac), + assoc_info->ac_params[ac].acm, + assoc_info->ac_params[ac].uapsd); + + for (idx = 0; idx < TS_DIR_IDX_COUNT; idx++) { + struct wmm_tspec_element *tspec; + u8 dir, tsid; + const char *dir_str; + + tspec = wpa_s->tspecs[ac][idx]; + if (!tspec) + continue; + + ts_count++; + + dir = wmm_ac_get_direction(tspec); + dir_str = get_direction_str(dir); + tsid = wmm_ac_get_tsid(tspec); + up = wmm_ac_get_user_priority(tspec); + + pos += wpa_scnprintf(buf + pos, buflen - pos, + "\tTSID=%u UP=%u\n" + "\tAddress = "MACSTR"\n" + "\tWMM AC dir = %s\n" + "\tTotal admitted time = %u\n\n", + tsid, up, + MAC2STR(wpa_s->bssid), + dir_str, + le_to_host16(tspec->medium_time)); + } + + if (!ts_count) { + pos += wpa_scnprintf(buf + pos, buflen - pos, + "\t(No Traffic Stream)\n\n"); + } + } + + return pos; +} + + +static u8 wmm_ac_get_tspecs_count(struct wpa_supplicant *wpa_s) +{ + int ac, dir, tspecs_count = 0; + + for (ac = 0; ac < WMM_AC_NUM; ac++) { + for (dir = 0; dir < TS_DIR_IDX_COUNT; dir++) { + if (wpa_s->tspecs[ac][dir]) + tspecs_count++; + } + } + + return tspecs_count; +} + + +void wmm_ac_save_tspecs(struct wpa_supplicant *wpa_s) +{ + int ac, dir, tspecs_count; + + wpa_printf(MSG_DEBUG, "WMM AC: Save last configured tspecs"); + + if (!wpa_s->wmm_ac_assoc_info) + return; + + tspecs_count = wmm_ac_get_tspecs_count(wpa_s); + if (!tspecs_count) { + wpa_printf(MSG_DEBUG, "WMM AC: No configured TSPECs"); + return; + } + + wpa_printf(MSG_DEBUG, "WMM AC: Saving tspecs"); + + wmm_ac_clear_saved_tspecs(wpa_s); + wpa_s->last_tspecs = os_calloc(tspecs_count, + sizeof(*wpa_s->last_tspecs)); + if (!wpa_s->last_tspecs) { + wpa_printf(MSG_ERROR, "WMM AC: Failed to save tspecs!"); + return; + } + + for (ac = 0; ac < WMM_AC_NUM; ac++) { + for (dir = 0; dir < TS_DIR_IDX_COUNT; dir++) { + if (!wpa_s->tspecs[ac][dir]) + continue; + + wpa_s->last_tspecs[wpa_s->last_tspecs_count++] = + *wpa_s->tspecs[ac][dir]; + } + } + + wpa_printf(MSG_DEBUG, "WMM AC: Successfully saved %d TSPECs", + wpa_s->last_tspecs_count); +} + + +void wmm_ac_clear_saved_tspecs(struct wpa_supplicant *wpa_s) +{ + if (wpa_s->last_tspecs) { + wpa_printf(MSG_DEBUG, "WMM AC: Clear saved tspecs"); + os_free(wpa_s->last_tspecs); + wpa_s->last_tspecs = NULL; + wpa_s->last_tspecs_count = 0; + } +} + + +int wmm_ac_restore_tspecs(struct wpa_supplicant *wpa_s) +{ + unsigned int i; + + if (!wpa_s->wmm_ac_assoc_info || !wpa_s->last_tspecs_count) + return 0; + + wpa_printf(MSG_DEBUG, "WMM AC: Restore %u saved tspecs", + wpa_s->last_tspecs_count); + + for (i = 0; i < wpa_s->last_tspecs_count; i++) + wmm_ac_add_ts(wpa_s, wpa_s->bssid, &wpa_s->last_tspecs[i]); + + return 0; +} diff --git a/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/wmm_ac.h b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/wmm_ac.h new file mode 100755 index 0000000..5171b16 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/wmm_ac.h @@ -0,0 +1,176 @@ +/* + * Wi-Fi Multimedia Admission Control (WMM-AC) + * Copyright(c) 2014, Intel Mobile Communication GmbH. + * Copyright(c) 2014, Intel Corporation. All rights reserved. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef WMM_AC_H +#define WMM_AC_H + +#include "common/ieee802_11_defs.h" +#include "drivers/driver.h" + +struct wpa_supplicant; + +#define WMM_AC_ACCESS_POLICY_EDCA 1 +#define WMM_AC_FIXED_MSDU_SIZE BIT(15) + +#define WMM_AC_MAX_TID 7 +#define WMM_AC_MAX_USER_PRIORITY 7 +#define WMM_AC_MIN_SBA_UNITY 0x2000 +#define WMM_AC_MAX_NOMINAL_MSDU 32767 + +/** + * struct wmm_ac_assoc_data - WMM Admission Control Association Data + * + * This struct will store any relevant WMM association data needed by WMM AC. + * In case there is a valid WMM association, an instance of this struct will be + * created. In case there is no instance of this struct, the station is not + * associated to a valid WMM BSS and hence, WMM AC will not be used. + */ +struct wmm_ac_assoc_data { + struct { + /* + * acm - Admission Control Mandatory + * In case an access category is ACM, the traffic will have + * to be admitted by WMM-AC's admission mechanism before use. + */ + unsigned int acm:1; + + /* + * uapsd_queues - Unscheduled Automatic Power Save Delivery + * queues. + * Indicates whether ACs are configured for U-APSD (or legacy + * PS). Storing this value is necessary in order to set the + * Power Save Bit (PSB) in ADDTS request Action frames (if not + * given). + */ + unsigned int uapsd:1; + } ac_params[WMM_AC_NUM]; +}; + +/** + * wmm_ac_dir - WMM Admission Control Direction + */ +enum wmm_ac_dir { + WMM_AC_DIR_UPLINK = 0, + WMM_AC_DIR_DOWNLINK = 1, + WMM_AC_DIR_BIDIRECTIONAL = 3 +}; + +/** + * ts_dir_idx - indices of internally saved tspecs + * + * we can have multiple tspecs (downlink + uplink) per ac. + * save them in array, and use the enum to directly access + * the respective tspec slot (according to the direction). + */ +enum ts_dir_idx { + TS_DIR_IDX_UPLINK, + TS_DIR_IDX_DOWNLINK, + TS_DIR_IDX_BIDI, + + TS_DIR_IDX_COUNT +}; +#define TS_DIR_IDX_ALL (BIT(TS_DIR_IDX_COUNT) - 1) + +/** + * struct wmm_ac_addts_request - ADDTS Request Information + * + * The last sent ADDTS request(s) will be saved as element(s) of this struct in + * order to be compared with the received ADDTS response in ADDTS response + * action frame handling and should be stored until that point. + * In case a new traffic stream will be created/replaced/updated, only its + * relevant traffic stream information will be stored as a wmm_ac_ts struct. + */ +struct wmm_ac_addts_request { + /* + * dialog token - Used to link the recived ADDTS response with this + * saved ADDTS request when ADDTS response is being handled + */ + u8 dialog_token; + + /* + * address - The alleged traffic stream's receiver/transmitter address + * Address and TID are used to identify the TS (TID is contained in + * TSPEC) + */ + u8 address[ETH_ALEN]; + + /* + * tspec - Traffic Stream Specification, will be used to compare the + * sent TSPEC in ADDTS request to the received TSPEC in ADDTS response + * and act accordingly in ADDTS response handling + */ + struct wmm_tspec_element tspec; +}; + + +/** + * struct wmm_ac_ts_setup_params - TS setup parameters + * + * This struct holds parameters which should be provided + * to wmm_ac_ts_setup in order to setup a traffic stream + */ +struct wmm_ac_ts_setup_params { + /* + * tsid - Traffic ID + * TID and address are used to identify the TS + */ + int tsid; + + /* + * direction - Traffic Stream's direction + */ + enum wmm_ac_dir direction; + + /* + * user_priority - Traffic Stream's user priority + */ + int user_priority; + + /* + * nominal_msdu_size - Nominal MAC service data unit size + */ + int nominal_msdu_size; + + /* + * fixed_nominal_msdu - Whether the size is fixed + * 0 = Nominal MSDU size is not fixed + * 1 = Nominal MSDU size is fixed + */ + int fixed_nominal_msdu; + + /* + * surplus_bandwidth_allowance - Specifies excess time allocation + */ + int mean_data_rate; + + /* + * minimum_phy_rate - Specifies the minimum supported PHY rate in bps + */ + int minimum_phy_rate; + + /* + * surplus_bandwidth_allowance - Specifies excess time allocation + */ + int surplus_bandwidth_allowance; +}; + +void wmm_ac_notify_assoc(struct wpa_supplicant *wpa_s, const u8 *ies, + size_t ies_len, const struct wmm_params *wmm_params); +void wmm_ac_notify_disassoc(struct wpa_supplicant *wpa_s); +int wpas_wmm_ac_addts(struct wpa_supplicant *wpa_s, + struct wmm_ac_ts_setup_params *params); +int wpas_wmm_ac_delts(struct wpa_supplicant *wpa_s, u8 tsid); +void wmm_ac_rx_action(struct wpa_supplicant *wpa_s, const u8 *da, + const u8 *sa, const u8 *data, size_t len); +int wpas_wmm_ac_status(struct wpa_supplicant *wpa_s, char *buf, size_t buflen); +void wmm_ac_save_tspecs(struct wpa_supplicant *wpa_s); +void wmm_ac_clear_saved_tspecs(struct wpa_supplicant *wpa_s); +int wmm_ac_restore_tspecs(struct wpa_supplicant *wpa_s); + +#endif /* WMM_AC_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/wnm_sta.h b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/wnm_sta.h new file mode 100755 index 0000000..8de4348 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/wnm_sta.h @@ -0,0 +1,77 @@ +/* + * IEEE 802.11v WNM related functions and structures + * Copyright (c) 2011-2012, Qualcomm Atheros, Inc. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef WNM_STA_H +#define WNM_STA_H + +struct measurement_pilot { + u8 measurement_pilot; + u8 subelem_len; + u8 subelems[255]; +}; + +struct multiple_bssid { + u8 max_bssid_indicator; + u8 subelem_len; + u8 subelems[255]; +}; + +struct neighbor_report { + u8 bssid[ETH_ALEN]; + u32 bssid_info; + u8 regulatory_class; + u8 channel_number; + u8 phy_type; + u8 preference; /* valid if preference_present=1 */ + u16 tsf_offset; /* valid if tsf_present=1 */ + u16 beacon_int; /* valid if tsf_present=1 */ + char country[2]; /* valid if country_present=1 */ + u8 rm_capab[5]; /* valid if rm_capab_present=1 */ + u16 bearing; /* valid if bearing_present=1 */ + u16 rel_height; /* valid if bearing_present=1 */ + u32 distance; /* valid if bearing_present=1 */ + u64 bss_term_tsf; /* valid if bss_term_present=1 */ + u16 bss_term_dur; /* valid if bss_term_present=1 */ + unsigned int preference_present:1; + unsigned int tsf_present:1; + unsigned int country_present:1; + unsigned int rm_capab_present:1; + unsigned int bearing_present:1; + unsigned int bss_term_present:1; + struct measurement_pilot *meas_pilot; + struct multiple_bssid *mul_bssid; + int freq; +}; + + +int ieee802_11_send_wnmsleep_req(struct wpa_supplicant *wpa_s, + u8 action, u16 intval, struct wpabuf *tfs_req); + +void ieee802_11_rx_wnm_action(struct wpa_supplicant *wpa_s, + const struct ieee80211_mgmt *mgmt, size_t len); + +int wnm_send_bss_transition_mgmt_query(struct wpa_supplicant *wpa_s, + u8 query_reason); +void wnm_deallocate_memory(struct wpa_supplicant *wpa_s); + + +#ifdef CONFIG_WNM + +int wnm_scan_process(struct wpa_supplicant *wpa_s, int reply_on_fail); + +#else /* CONFIG_WNM */ + +static inline int wnm_scan_process(struct wpa_supplicant *wpa_s, + int reply_on_fail) +{ + return 0; +} + +#endif /* CONFIG_WNM */ + +#endif /* WNM_STA_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/wpa_scan.c b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/wpa_scan.c new file mode 100755 index 0000000..e8f26e2 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/wpa_scan.c @@ -0,0 +1,2414 @@ +/* + * WPA Supplicant - Scanning + * Copyright (c) 2003-2014, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "utils/eloop.h" +#include "common/ieee802_11_defs.h" +#include "common/wpa_ctrl.h" +#include "config.h" +#include "wpa_supplicant_i.h" +#include "driver_i.h" +#include "wps_supplicant.h" +#include "p2p_supplicant.h" +#include "hs20_supplicant.h" +#include "notify.h" +#include "bss.h" +#include "scan.h" +#include "mesh.h" +#include "errno-base.h" + +#include "include.h" +#include "uart_pub.h" +#include "param_config.h" +#include "mcu_ps_pub.h" + +static void wpa_supplicant_gen_assoc_event(struct wpa_supplicant *wpa_s) +{ + struct wpa_ssid *ssid; + union wpa_event_data data; + + ssid = wpa_supplicant_get_ssid(wpa_s); + if (ssid == NULL) + return; + + if (wpa_s->current_ssid == NULL) { + wpa_s->current_ssid = ssid; + if (wpa_s->current_ssid != NULL) + wpas_notify_network_changed(wpa_s); + } + wpa_supplicant_initiate_eapol(wpa_s); + wpa_dbg(wpa_s, MSG_DEBUG, "Already associated with a configured " + "network - generating associated event"); + os_memset(&data, 0, sizeof(data)); + wpa_supplicant_event_sta(wpa_s, EVENT_ASSOC, &data); +} + + +#ifdef CONFIG_WPS +static int wpas_wps_in_use(struct wpa_supplicant *wpa_s, + enum wps_request_type *req_type) +{ + struct wpa_ssid *ssid; + int wps = 0; + + for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { + if (!(ssid->key_mgmt & WPA_KEY_MGMT_WPS)) + continue; + + wps = 1; + *req_type = wpas_wps_get_req_type(ssid); + if (!ssid->eap.phase1) + continue; + + if (os_strstr(ssid->eap.phase1, "pbc=1")) + return 2; + } + +#ifdef CONFIG_P2P + if (!wpa_s->global->p2p_disabled && wpa_s->global->p2p && + !wpa_s->conf->p2p_disabled) { + wpa_s->wps->dev.p2p = 1; + if (!wps) { + wps = 1; + *req_type = WPS_REQ_ENROLLEE_INFO; + } + } +#endif /* CONFIG_P2P */ + + return wps; +} +#endif /* CONFIG_WPS */ + + +/** + * wpa_supplicant_enabled_networks - Check whether there are enabled networks + * @wpa_s: Pointer to wpa_supplicant data + * Returns: 0 if no networks are enabled, >0 if networks are enabled + * + * This function is used to figure out whether any networks (or Interworking + * with enabled credentials and auto_interworking) are present in the current + * configuration. + */ +int wpa_supplicant_enabled_networks(struct wpa_supplicant *wpa_s) +{ + struct wpa_ssid *ssid = wpa_s->conf->ssid; + int count = 0, disabled = 0; + + if (wpa_s->p2p_mgmt) + return 0; /* no normal network profiles on p2p_mgmt interface */ + + while (ssid) { + if (!wpas_network_disabled(wpa_s, ssid)) + count++; + else + disabled++; + ssid = ssid->next; + } + if (wpa_s->conf->cred && wpa_s->conf->interworking && + wpa_s->conf->auto_interworking) + count++; + if (count == 0 && disabled > 0) { + wpa_dbg(wpa_s, MSG_DEBUG, "No enabled networks (%d disabled " + "networks)", disabled); + } + return count; +} + + +static void wpa_supplicant_assoc_try(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid) +{ + while (ssid) { + if (!wpas_network_disabled(wpa_s, ssid)) + break; + ssid = ssid->next; + } + + /* ap_scan=2 mode - try to associate with each SSID. */ + if (ssid == NULL) { + wpa_dbg(wpa_s, MSG_DEBUG, "wpa_supplicant_assoc_try: Reached " + "end of scan list - go back to beginning"); + wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN; + wpa_supplicant_req_scan(wpa_s, 0, 0); + return; + } + if (ssid->next) { + /* Continue from the next SSID on the next attempt. */ + wpa_s->prev_scan_ssid = ssid; + } else { + /* Start from the beginning of the SSID list. */ + wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN; + } + wpa_supplicant_associate(wpa_s, NULL, ssid); +} + + +static void wpas_trigger_scan_cb(struct wpa_radio_work *work, int deinit) +{ + struct wpa_supplicant *wpa_s = work->wpa_s; + struct wpa_driver_scan_params *params = work->ctx; + int ret; + + if (deinit) { + if (!work->started) { + wpa_scan_free_params(params); + return; + } + wpa_supplicant_notify_scanning(wpa_s, 0); + wpas_notify_scan_done(wpa_s, 0); + wpa_s->scan_work = NULL; + return; + } + +#ifdef CONFIG_RANDOM_MAC + if (wpas_update_random_addr_disassoc(wpa_s) < 0) { + wpa_msg(wpa_s, MSG_INFO, + "Failed to assign random MAC address for a scan"); + radio_work_done(work); + return; + } +#endif + + wpa_supplicant_notify_scanning(wpa_s, 1); + + if (wpa_s->clear_driver_scan_cache) { + wpa_printf(MSG_DEBUG, + "Request driver to clear scan cache due to local BSS flush"); + params->only_new_results = 1; + } + + os_null_printf("wpa_drv_scan\r\n"); + ret = wpa_drv_scan(wpa_s, params); + wpa_scan_free_params(params); + work->ctx = NULL; + if (ret) { + int retry = wpa_s->last_scan_req != MANUAL_SCAN_REQ; + + if (wpa_s->disconnected) + retry = 0; + + wpa_supplicant_notify_scanning(wpa_s, 0); + wpas_notify_scan_done(wpa_s, 0); + if (wpa_s->wpa_state == WPA_SCANNING) + wpa_supplicant_set_state(wpa_s, + wpa_s->scan_prev_wpa_state); + wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_SCAN_FAILED "ret=%d%s", + ret, retry ? " retry=1" : ""); + radio_work_done(work); + + if (retry) { + /* Restore scan_req since we will try to scan again */ + wpa_s->scan_req = wpa_s->last_scan_req; + wpa_supplicant_req_scan(wpa_s, 1, 0); + } + return; + } + + os_get_reltime(&wpa_s->scan_trigger_time); + wpa_s->scan_runs++; + wpa_s->normal_scans++; + wpa_s->own_scan_requested = 1; + wpa_s->clear_driver_scan_cache = 0; + wpa_s->scan_work = work; +} + + +/** + * wpa_supplicant_trigger_scan - Request driver to start a scan + * @wpa_s: Pointer to wpa_supplicant data + * @params: Scan parameters + * Returns: 0 on success, -1 on failure + */ +int wpa_supplicant_trigger_scan(struct wpa_supplicant *wpa_s, + struct wpa_driver_scan_params *params) +{ + struct wpa_driver_scan_params *ctx; + + if (wpa_s->scan_work) { + wpa_dbg(wpa_s, MSG_INFO, "Reject scan trigger since one is already pending"); + return -1; + } + + ctx = wpa_scan_clone_params(params); + if (ctx == NULL) + return -1; + + if (radio_add_work(wpa_s, 0, "scan", 0, wpas_trigger_scan_cb, ctx) < 0) + { + wpa_scan_free_params(ctx); + return -1; + } + + return 0; +} + + +static void +wpa_supplicant_delayed_sched_scan_timeout(void *eloop_ctx, void *timeout_ctx) +{ + struct wpa_supplicant *wpa_s = eloop_ctx; + + wpa_dbg(wpa_s, MSG_DEBUG, "Starting delayed sched scan"); + + if (wpa_supplicant_req_sched_scan(wpa_s)) + wpa_supplicant_req_scan(wpa_s, 0, 0); +} + + +static void +wpa_supplicant_sched_scan_timeout(void *eloop_ctx, void *timeout_ctx) +{ + struct wpa_supplicant *wpa_s = eloop_ctx; + + wpa_dbg(wpa_s, MSG_DEBUG, "Sched scan timeout - stopping it"); + + wpa_s->sched_scan_timed_out = 1; + wpa_supplicant_cancel_sched_scan(wpa_s); +} + + +int wpa_supplicant_start_sched_scan(struct wpa_supplicant *wpa_s, + struct wpa_driver_scan_params *params, + int interval) +{ + int ret; + + wpa_supplicant_notify_scanning(wpa_s, 1); + ret = wpa_drv_sched_scan(wpa_s, params, interval * 1000); + if (ret) + wpa_supplicant_notify_scanning(wpa_s, 0); + else + wpa_s->sched_scanning = 1; + + return ret; +} + + +int wpa_supplicant_stop_sched_scan(struct wpa_supplicant *wpa_s) +{ + int ret; + + ret = wpa_drv_stop_sched_scan(wpa_s); + if (ret) { + wpa_dbg(wpa_s, MSG_DEBUG, "stopping sched_scan failed!"); + /* TODO: what to do if stopping fails? */ + return -1; + } + + return ret; +} + + +static struct wpa_driver_scan_filter * +wpa_supplicant_build_filter_ssids(struct wpa_config *conf, size_t *num_ssids) +{ + struct wpa_driver_scan_filter *ssids; + struct wpa_ssid *ssid; + size_t count; + + *num_ssids = 0; + if (!conf->filter_ssids) + return NULL; + + for (count = 0, ssid = conf->ssid; ssid; ssid = ssid->next) { + if (ssid->ssid && ssid->ssid_len) + count++; + } + if (count == 0) + return NULL; + ssids = os_calloc(count, sizeof(struct wpa_driver_scan_filter)); + if (ssids == NULL) + return NULL; + + for (ssid = conf->ssid; ssid; ssid = ssid->next) { + if (!ssid->ssid || !ssid->ssid_len) + continue; + os_memcpy(ssids[*num_ssids].ssid, ssid->ssid, ssid->ssid_len); + ssids[*num_ssids].ssid_len = ssid->ssid_len; + (*num_ssids)++; + } + + return ssids; +} + + +static void wpa_supplicant_optimize_freqs( + struct wpa_supplicant *wpa_s, struct wpa_driver_scan_params *params) +{ +#ifdef CONFIG_P2P + if (params->freqs == NULL && wpa_s->p2p_in_provisioning && + wpa_s->go_params) { + /* Optimize provisioning state scan based on GO information */ + if (wpa_s->p2p_in_provisioning < 5 && + wpa_s->go_params->freq > 0) { + wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Scan only GO " + "preferred frequency %d MHz", + wpa_s->go_params->freq); + params->freqs = os_calloc(2, sizeof(int)); + if (params->freqs) + params->freqs[0] = wpa_s->go_params->freq; + } else if (wpa_s->p2p_in_provisioning < 8 && + wpa_s->go_params->freq_list[0]) { + wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Scan only common " + "channels"); + int_array_concat(¶ms->freqs, + wpa_s->go_params->freq_list); + if (params->freqs) + int_array_sort_unique(params->freqs); + } + wpa_s->p2p_in_provisioning++; + } + + if (params->freqs == NULL && wpa_s->p2p_in_invitation) { + /* + * Optimize scan based on GO information during persistent + * group reinvocation + */ + if (wpa_s->p2p_in_invitation < 5 && + wpa_s->p2p_invite_go_freq > 0) { + wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Scan only GO preferred frequency %d MHz during invitation", + wpa_s->p2p_invite_go_freq); + params->freqs = os_calloc(2, sizeof(int)); + if (params->freqs) + params->freqs[0] = wpa_s->p2p_invite_go_freq; + } + wpa_s->p2p_in_invitation++; + if (wpa_s->p2p_in_invitation > 20) { + /* + * This should not really happen since the variable is + * cleared on group removal, but if it does happen, make + * sure we do not get stuck in special invitation scan + * mode. + */ + wpa_dbg(wpa_s, MSG_DEBUG, "P2P: Clear p2p_in_invitation"); + wpa_s->p2p_in_invitation = 0; + } + } +#endif /* CONFIG_P2P */ +} + +static struct wpabuf * wpa_supplicant_extra_ies(struct wpa_supplicant *wpa_s) +{ + struct wpabuf *extra_ie = NULL; + u8 ext_capab[18]; + int ext_capab_len; + + ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab, + sizeof(ext_capab)); + if (ext_capab_len > 0 && + wpabuf_resize(&extra_ie, ext_capab_len) == 0) + wpabuf_put_data(extra_ie, ext_capab, ext_capab_len); + + + return extra_ie; +} + + +#ifdef CONFIG_P2P + +/* + * Check whether there are any enabled networks or credentials that could be + * used for a non-P2P connection. + */ +static int non_p2p_network_enabled(struct wpa_supplicant *wpa_s) +{ + struct wpa_ssid *ssid; + + for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { + if (wpas_network_disabled(wpa_s, ssid)) + continue; + if (!ssid->p2p_group) + return 1; + } + + if (wpa_s->conf->cred && wpa_s->conf->interworking && + wpa_s->conf->auto_interworking) + return 1; + + return 0; +} + +#endif /* CONFIG_P2P */ + + +static struct hostapd_hw_modes * get_mode(struct hostapd_hw_modes *modes, + u16 num_modes, + enum hostapd_hw_mode mode) +{ + u16 i; + + for (i = 0; i < num_modes; i++) { + if (modes[i].mode == mode) + return &modes[i]; + } + + return NULL; +} + + +static void wpa_setband_scan_freqs_list(struct wpa_supplicant *wpa_s, + enum hostapd_hw_mode band, + struct wpa_driver_scan_params *params) +{ + /* Include only supported channels for the specified band */ + struct hostapd_hw_modes *mode; + int count, i; + + mode = get_mode(wpa_s->hw.modes, wpa_s->hw.num_modes, band); + if (mode == NULL) { + /* No channels supported in this band - use empty list */ + params->freqs = os_zalloc(sizeof(int)); + return; + } + + params->freqs = os_calloc(mode->num_channels + 1, sizeof(int)); + if (params->freqs == NULL) + return; + for (count = 0, i = 0; i < mode->num_channels; i++) { + if (mode->channels[i].flag & HOSTAPD_CHAN_DISABLED) + continue; + params->freqs[count++] = mode->channels[i].freq; + } +} + + +static void wpa_setband_scan_freqs(struct wpa_supplicant *wpa_s, + struct wpa_driver_scan_params *params) +{ + if (wpa_s->hw.modes == NULL) + return; /* unknown what channels the driver supports */ + if (params->freqs) + return; /* already using a limited channel set */ + if (wpa_s->setband == WPA_SETBAND_5G) + wpa_setband_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211A, + params); + else if (wpa_s->setband == WPA_SETBAND_2G) + wpa_setband_scan_freqs_list(wpa_s, HOSTAPD_MODE_IEEE80211G, + params); +} + + +static void wpa_set_scan_ssids(struct wpa_supplicant *wpa_s, + struct wpa_driver_scan_params *params, + size_t max_ssids) +{ + unsigned int i; + struct wpa_ssid *ssid; + + for (i = 0; i < wpa_s->scan_id_count; i++) { + unsigned int j; + + ssid = wpa_config_get_network(wpa_s->conf, wpa_s->scan_id[i]); + if (!ssid || !ssid->scan_ssid) + continue; + + for (j = 0; j < params->num_ssids; j++) { + if (params->ssids[j].ssid_len == ssid->ssid_len && + params->ssids[j].ssid && + os_memcmp(params->ssids[j].ssid, ssid->ssid, + ssid->ssid_len) == 0) + break; + } + if (j < params->num_ssids) + continue; /* already in the list */ + + if (params->num_ssids + 1 > max_ssids) { + wpa_printf(MSG_DEBUG, + "Over max scan SSIDs for manual request"); + break; + } + + wpa_printf(MSG_DEBUG, "Scan SSID (manual request): %s", + wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); + params->ssids[params->num_ssids].ssid = ssid->ssid; + params->ssids[params->num_ssids].ssid_len = ssid->ssid_len; + params->num_ssids++; + } + + wpa_s->scan_id_count = 0; +} + + +static int wpa_set_ssids_from_scan_req(struct wpa_supplicant *wpa_s, + struct wpa_driver_scan_params *params, + size_t max_ssids) +{ + unsigned int i; + + if (wpa_s->ssids_from_scan_req == NULL || + wpa_s->num_ssids_from_scan_req == 0) + return 0; + + if (wpa_s->num_ssids_from_scan_req > max_ssids) { + wpa_s->num_ssids_from_scan_req = max_ssids; + wpa_printf(MSG_DEBUG, "Over max scan SSIDs from scan req: %u", + (unsigned int) max_ssids); + } + + for (i = 0; i < wpa_s->num_ssids_from_scan_req; i++) { + params->ssids[i].ssid = wpa_s->ssids_from_scan_req[i].ssid; + params->ssids[i].ssid_len = + wpa_s->ssids_from_scan_req[i].ssid_len; + wpa_hexdump_ascii(MSG_DEBUG, "specific SSID", + params->ssids[i].ssid, + params->ssids[i].ssid_len); + } + + params->num_ssids = wpa_s->num_ssids_from_scan_req; + //wpa_s->num_ssids_from_scan_req = 0; + return 1; +} + +static void wpa_supplicant_scan(void *eloop_ctx, void *timeout_ctx) +{ + struct wpa_supplicant *wpa_s = eloop_ctx; + struct wpa_ssid *ssid; + int ret, p2p_in_prog; + struct wpabuf *extra_ie = NULL; + struct wpa_driver_scan_params params; + struct wpa_driver_scan_params *scan_params; + size_t max_ssids; + int connect_without_scan = 0; + + os_null_printf("wpa_supplicant_scan\r\n"); + if (wpa_s->pno || wpa_s->pno_sched_pending) { + wpa_dbg(wpa_s, MSG_DEBUG, "Skip scan - PNO is in progress"); + return; + } + + if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) { + wpa_dbg(wpa_s, MSG_DEBUG, "Skip scan - interface disabled"); + return; + } + + if (wpa_s->disconnected && wpa_s->scan_req == NORMAL_SCAN_REQ) { + wpa_dbg(wpa_s, MSG_DEBUG, "Disconnected - do not scan"); + wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); + return; + } + + if (wpa_s->scanning) { + /* + * If we are already in scanning state, we shall reschedule the + * the incoming scan request. + */ + wpa_dbg(wpa_s, MSG_DEBUG, "Already scanning - Reschedule the incoming scan req"); + wpa_supplicant_req_scan(wpa_s, 1, 0); + return; + } + + if (!wpa_supplicant_enabled_networks(wpa_s) && + wpa_s->scan_req == NORMAL_SCAN_REQ) { + wpa_dbg(wpa_s, MSG_DEBUG, "No enabled networks - do not scan"); + wpa_supplicant_set_state(wpa_s, WPA_INACTIVE); + return; + } + + if (wpa_s->conf->ap_scan != 0 && + (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)) { + wpa_dbg(wpa_s, MSG_DEBUG, "Using wired authentication - " + "overriding ap_scan configuration"); + wpa_s->conf->ap_scan = 0; + wpas_notify_ap_scan_changed(wpa_s); + } + + if (wpa_s->conf->ap_scan == 0) { + wpa_supplicant_gen_assoc_event(wpa_s); + return; + } + + ssid = NULL; + if (wpa_s->scan_req != MANUAL_SCAN_REQ && + wpa_s->connect_without_scan) { + connect_without_scan = 1; + for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { + if (ssid == wpa_s->connect_without_scan) + break; + } + } + if(g_sta_param_ptr->fast_connect_set){ + connect_without_scan = 1; + ssid = wpa_s->conf->ssid; + } + + p2p_in_prog = wpas_p2p_in_progress(wpa_s); + if (p2p_in_prog && p2p_in_prog != 2 && + (!ssid || + (ssid->mode != WPAS_MODE_AP && ssid->mode != WPAS_MODE_P2P_GO))) { + wpa_dbg(wpa_s, MSG_DEBUG, "Delay station mode scan while P2P operation is in progress"); + wpa_supplicant_req_scan(wpa_s, 5, 0); + return; + } + + if (wpa_s->conf->ap_scan == 2) + max_ssids = 1; + else { + max_ssids = wpa_s->max_scan_ssids; + if (max_ssids > WPAS_MAX_SCAN_SSIDS) + max_ssids = WPAS_MAX_SCAN_SSIDS; + } + + wpa_s->last_scan_req = wpa_s->scan_req; + //wpa_s->scan_req = NORMAL_SCAN_REQ; + + if (connect_without_scan) { + wpa_s->connect_without_scan = NULL; + if (ssid) { + wpa_printf(MSG_DEBUG, "Start a pre-selected network " + "without scan step"); + wpa_supplicant_associate(wpa_s, NULL, ssid); + return; + } + } + + os_memset(¶ms, 0, sizeof(params)); + + wpa_s->scan_prev_wpa_state = wpa_s->wpa_state; + if (wpa_s->wpa_state == WPA_DISCONNECTED || + wpa_s->wpa_state == WPA_INACTIVE) + wpa_supplicant_set_state(wpa_s, WPA_SCANNING); + + /* + * If autoscan has set its own scanning parameters + */ + if (wpa_s->autoscan_params != NULL) { + scan_params = wpa_s->autoscan_params; + goto scan; + } + + if (wpa_s->last_scan_req == MANUAL_SCAN_REQ && + wpa_set_ssids_from_scan_req(wpa_s, ¶ms, max_ssids)) { + wpa_printf(MSG_DEBUG, "Use specific SSIDs from SCAN command"); + goto ssid_list_set; + } + +#ifdef CONFIG_P2P + if ((wpa_s->p2p_in_provisioning || wpa_s->show_group_started) && + wpa_s->go_params && !wpa_s->conf->passive_scan) { + wpa_printf(MSG_DEBUG, "P2P: Use specific SSID for scan during P2P group formation (p2p_in_provisioning=%d show_group_started=%d)", + wpa_s->p2p_in_provisioning, + wpa_s->show_group_started); + params.ssids[0].ssid = wpa_s->go_params->ssid; + params.ssids[0].ssid_len = wpa_s->go_params->ssid_len; + params.num_ssids = 1; + goto ssid_list_set; + } + + if (wpa_s->p2p_in_invitation) { + if (wpa_s->current_ssid) { + wpa_printf(MSG_DEBUG, "P2P: Use specific SSID for scan during invitation"); + params.ssids[0].ssid = wpa_s->current_ssid->ssid; + params.ssids[0].ssid_len = + wpa_s->current_ssid->ssid_len; + params.num_ssids = 1; + } else { + wpa_printf(MSG_DEBUG, "P2P: No specific SSID known for scan during invitation"); + } + goto ssid_list_set; + } +#endif /* CONFIG_P2P */ + + /* Find the starting point from which to continue scanning */ + ssid = wpa_s->conf->ssid; + if (wpa_s->prev_scan_ssid != WILDCARD_SSID_SCAN) { + while (ssid) { + if (ssid == wpa_s->prev_scan_ssid) { + ssid = ssid->next; + break; + } + ssid = ssid->next; + } + } + + if (wpa_s->last_scan_req != MANUAL_SCAN_REQ && +#ifdef CONFIG_AP + !wpa_s->ap_iface && +#endif /* CONFIG_AP */ + wpa_s->conf->ap_scan == 2) { + wpa_s->connect_without_scan = NULL; + wpa_s->prev_scan_wildcard = 0; + wpa_supplicant_assoc_try(wpa_s, ssid); + return; + } else if (wpa_s->conf->ap_scan == 2) { + /* + * User-initiated scan request in ap_scan == 2; scan with + * wildcard SSID. + */ + ssid = NULL; + } else if (wpa_s->reattach && wpa_s->current_ssid != NULL) { + /* + * Perform single-channel single-SSID scan for + * reassociate-to-same-BSS operation. + */ + /* Setup SSID */ + ssid = wpa_s->current_ssid; + wpa_hexdump_ascii(MSG_DEBUG, "Scan SSID", + ssid->ssid, ssid->ssid_len); + params.ssids[0].ssid = ssid->ssid; + params.ssids[0].ssid_len = ssid->ssid_len; + params.num_ssids = 1; + + /* + * Allocate memory for frequency array, allocate one extra + * slot for the zero-terminator. + */ + params.freqs = os_malloc(sizeof(int) * 2); + if (params.freqs == NULL) { + wpa_dbg(wpa_s, MSG_ERROR, "Memory allocation failed"); + return; + } + params.freqs[0] = wpa_s->assoc_freq; + params.freqs[1] = 0; + + /* + * Reset the reattach flag so that we fall back to full scan if + * this scan fails. + */ + wpa_s->reattach = 0; + } else { + struct wpa_ssid *start = ssid, *tssid; + int freqs_set = 0; + if (ssid == NULL && max_ssids > 1) + ssid = wpa_s->conf->ssid; + while (ssid) { + if (!wpas_network_disabled(wpa_s, ssid) && + ssid->scan_ssid) { + wpa_hexdump_ascii(MSG_DEBUG, "Scan SSID", + ssid->ssid, ssid->ssid_len); + params.ssids[params.num_ssids].ssid = + ssid->ssid; + params.ssids[params.num_ssids].ssid_len = + ssid->ssid_len; + params.num_ssids++; + if (params.num_ssids + 1 >= max_ssids) + break; + } + ssid = ssid->next; + if (ssid == start) + break; + if (ssid == NULL && max_ssids > 1 && + start != wpa_s->conf->ssid) + ssid = wpa_s->conf->ssid; + } + + if (wpa_s->scan_id_count && + wpa_s->last_scan_req == MANUAL_SCAN_REQ) + wpa_set_scan_ssids(wpa_s, ¶ms, max_ssids); + + for (tssid = wpa_s->conf->ssid; + wpa_s->last_scan_req != MANUAL_SCAN_REQ && tssid; + tssid = tssid->next) { + if (wpas_network_disabled(wpa_s, tssid)) + continue; + if ((params.freqs || !freqs_set) && tssid->scan_freq) { + int_array_concat(¶ms.freqs, + tssid->scan_freq); + } else { + os_free(params.freqs); + params.freqs = NULL; + } + freqs_set = 1; + } + int_array_sort_unique(params.freqs); + } + + if (ssid && max_ssids == 1) { + /* + * If the driver is limited to 1 SSID at a time interleave + * wildcard SSID scans with specific SSID scans to avoid + * waiting a long time for a wildcard scan. + */ + if (!wpa_s->prev_scan_wildcard) { + params.ssids[0].ssid = NULL; + params.ssids[0].ssid_len = 0; + wpa_s->prev_scan_wildcard = 1; + wpa_dbg(wpa_s, MSG_DEBUG, "Starting AP scan for " + "wildcard SSID (Interleave with specific)"); + } else { + wpa_s->prev_scan_ssid = ssid; + wpa_s->prev_scan_wildcard = 0; + wpa_dbg(wpa_s, MSG_DEBUG, + "Starting AP scan for specific SSID: %s", + wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); + } + } else if (ssid) { + /* max_ssids > 1 */ + + wpa_s->prev_scan_ssid = ssid; + wpa_dbg(wpa_s, MSG_DEBUG, "Include wildcard SSID in " + "the scan request"); + params.num_ssids++; + } else if (wpa_s->last_scan_req == MANUAL_SCAN_REQ && + wpa_s->manual_scan_passive && params.num_ssids == 0) { + wpa_dbg(wpa_s, MSG_DEBUG, "Use passive scan based on manual request"); + } else if (wpa_s->conf->passive_scan) { + wpa_dbg(wpa_s, MSG_DEBUG, + "Use passive scan based on configuration"); + } else { + wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN; + params.num_ssids++; + wpa_dbg(wpa_s, MSG_DEBUG, "Starting AP scan for wildcard " + "SSID"); + } + +ssid_list_set: + wpa_supplicant_optimize_freqs(wpa_s, ¶ms); + extra_ie = wpa_supplicant_extra_ies(wpa_s); + + if (wpa_s->last_scan_req == MANUAL_SCAN_REQ && + wpa_s->manual_scan_only_new) { + wpa_printf(MSG_DEBUG, + "Request driver to clear scan cache due to manual only_new=1 scan"); + params.only_new_results = 1; + } + + if (wpa_s->last_scan_req == MANUAL_SCAN_REQ && params.freqs == NULL && + wpa_s->manual_scan_freqs) { + wpa_dbg(wpa_s, MSG_DEBUG, "Limit manual scan to specified channels"); + params.freqs = wpa_s->manual_scan_freqs; + wpa_s->manual_scan_freqs = NULL; + } + + if (params.freqs == NULL && wpa_s->next_scan_freqs) { + wpa_dbg(wpa_s, MSG_DEBUG, "Optimize scan based on previously " + "generated frequency list"); + params.freqs = wpa_s->next_scan_freqs; + } else + os_free(wpa_s->next_scan_freqs); + wpa_s->next_scan_freqs = NULL; + wpa_setband_scan_freqs(wpa_s, ¶ms); + + /* See if user specified frequencies. If so, scan only those. */ + if (wpa_s->conf->freq_list && !params.freqs) { + wpa_dbg(wpa_s, MSG_DEBUG, + "Optimize scan based on conf->freq_list"); + int_array_concat(¶ms.freqs, wpa_s->conf->freq_list); + } + + /* Use current associated channel? */ + if (wpa_s->conf->scan_cur_freq && !params.freqs) { + unsigned int num = wpa_s->num_multichan_concurrent; + + params.freqs = os_calloc(num + 1, sizeof(int)); + if (params.freqs) { + num = get_shared_radio_freqs(wpa_s, params.freqs, num); + if (num > 0) { + wpa_dbg(wpa_s, MSG_DEBUG, "Scan only the " + "current operating channels since " + "scan_cur_freq is enabled"); + } else { + os_free(params.freqs); + params.freqs = NULL; + } + } + } + + params.filter_ssids = wpa_supplicant_build_filter_ssids( + wpa_s->conf, ¶ms.num_filter_ssids); + if (extra_ie) { + params.extra_ies = wpabuf_head(extra_ie); + params.extra_ies_len = wpabuf_len(extra_ie); + } + +#ifdef CONFIG_P2P + if (wpa_s->p2p_in_provisioning || wpa_s->p2p_in_invitation || + (wpa_s->show_group_started && wpa_s->go_params)) { + /* + * The interface may not yet be in P2P mode, so we have to + * explicitly request P2P probe to disable CCK rates. + */ + params.p2p_probe = 1; + } +#endif /* CONFIG_P2P */ + + if (wpa_s->mac_addr_rand_enable & MAC_ADDR_RAND_SCAN) { + params.mac_addr_rand = 1; + if (wpa_s->mac_addr_scan) { + params.mac_addr = wpa_s->mac_addr_scan; + params.mac_addr_mask = wpa_s->mac_addr_scan + ETH_ALEN; + } + } + + scan_params = ¶ms; + +scan: +#ifdef CONFIG_P2P + /* + * If the driver does not support multi-channel concurrency and a + * virtual interface that shares the same radio with the wpa_s interface + * is operating there may not be need to scan other channels apart from + * the current operating channel on the other virtual interface. Filter + * out other channels in case we are trying to find a connection for a + * station interface when we are not configured to prefer station + * connection and a concurrent operation is already in process. + */ + if (wpa_s->scan_for_connection && + wpa_s->last_scan_req == NORMAL_SCAN_REQ && + !scan_params->freqs && !params.freqs && + wpas_is_p2p_prioritized(wpa_s) && + wpa_s->p2p_group_interface == NOT_P2P_GROUP_INTERFACE && + non_p2p_network_enabled(wpa_s)) { + unsigned int num = wpa_s->num_multichan_concurrent; + + params.freqs = os_calloc(num + 1, sizeof(int)); + if (params.freqs) { + num = get_shared_radio_freqs(wpa_s, params.freqs, num); + if (num > 0 && num == wpa_s->num_multichan_concurrent) { + wpa_dbg(wpa_s, MSG_DEBUG, "Scan only the current operating channels since all channels are already used"); + } else { + os_free(params.freqs); + params.freqs = NULL; + } + } + } +#endif /* CONFIG_P2P */ + + ret = wpa_supplicant_trigger_scan(wpa_s, scan_params); + + if (ret && wpa_s->last_scan_req == MANUAL_SCAN_REQ && params.freqs && + !wpa_s->manual_scan_freqs) { + /* Restore manual_scan_freqs for the next attempt */ + wpa_s->manual_scan_freqs = params.freqs; + params.freqs = NULL; + } + + wpabuf_free(extra_ie); + os_free(params.freqs); + os_free(params.filter_ssids); + + if (ret) { + wpa_msg(wpa_s, MSG_WARNING, "Failed to initiate AP scan"); + if (wpa_s->scan_prev_wpa_state != wpa_s->wpa_state) + wpa_supplicant_set_state(wpa_s, + wpa_s->scan_prev_wpa_state); + /* Restore scan_req since we will try to scan again */ + wpa_s->scan_req = wpa_s->last_scan_req; + wpa_supplicant_req_scan(wpa_s, 1, 0); + } else { + wpa_s->scan_for_connection = 0; +#ifdef CONFIG_INTERWORKING + wpa_s->interworking_fast_assoc_tried = 0; +#endif /* CONFIG_INTERWORKING */ + } +} + + +void wpa_supplicant_update_scan_int(struct wpa_supplicant *wpa_s, int sec) +{ + struct os_reltime remaining, new_int; + int cancelled; + + cancelled = eloop_cancel_timeout_one(wpa_supplicant_scan, wpa_s, NULL, + &remaining); + + new_int.sec = sec; + new_int.usec = 0; + if (cancelled && os_reltime_before(&remaining, &new_int)) { + new_int.sec = remaining.sec; + new_int.usec = remaining.usec; + } + + if (cancelled) { + eloop_register_timeout(new_int.sec, new_int.usec, + wpa_supplicant_scan, wpa_s, NULL); + } + wpa_s->scan_interval = sec; +} + +extern void wpa_supplicant_rescan_terminal(void); +/** + * wpa_supplicant_req_scan - Schedule a scan for neighboring access points + * @wpa_s: Pointer to wpa_supplicant data + * @sec: Number of seconds after which to scan + * @usec: Number of microseconds after which to scan + * + * This function is used to schedule a scan for neighboring access points after + * the specified time. + */ +void wpa_supplicant_req_scan(struct wpa_supplicant *wpa_s, int sec, int usec) +{ + int res; + + os_null_printf("wpa_supplicant_req_scan\r\n"); + mcu_prevent_set(MCU_PS_CONNECT); + + if (wpa_s->p2p_mgmt) { + wpa_dbg(wpa_s, MSG_DEBUG, + "Ignore scan request (%d.%06d sec) on p2p_mgmt interface", + sec, usec); + return; + } + + res = eloop_deplete_timeout(sec, + usec, + wpa_supplicant_scan, + wpa_s, + NULL); + if (res == 1) + { + os_printf("Rescheduling scan request: %d.%06d sec\r\n", + sec, usec); + } + else if (res == 0) + { + os_printf("Ignore new scan request for %d.%06d sec\r\n", + sec, usec); + } + else + { + os_printf("Setting scan[retry%d] request: %d.%06d sec\r\n", g_sta_param_ptr->retry_cnt, sec, usec); + + if(g_sta_param_ptr->retry_cnt) + { + g_sta_param_ptr->retry_cnt--; + eloop_register_timeout(sec, usec, wpa_supplicant_scan, wpa_s, NULL); + } + else + { + wpa_supplicant_rescan_terminal(); + } + } +} + + +/** + * wpa_supplicant_delayed_sched_scan - Request a delayed scheduled scan + * @wpa_s: Pointer to wpa_supplicant data + * @sec: Number of seconds after which to scan + * @usec: Number of microseconds after which to scan + * Returns: 0 on success or -1 otherwise + * + * This function is used to schedule periodic scans for neighboring + * access points after the specified time. + */ +int wpa_supplicant_delayed_sched_scan(struct wpa_supplicant *wpa_s, + int sec, int usec) +{ + if (!wpa_s->sched_scan_supported) + return -1; + + eloop_register_timeout(sec, usec, + wpa_supplicant_delayed_sched_scan_timeout, + wpa_s, NULL); + + return 0; +} + + +/** + * wpa_supplicant_req_sched_scan - Start a periodic scheduled scan + * @wpa_s: Pointer to wpa_supplicant data + * Returns: 0 is sched_scan was started or -1 otherwise + * + * This function is used to schedule periodic scans for neighboring + * access points repeating the scan continuously. + */ +int wpa_supplicant_req_sched_scan(struct wpa_supplicant *wpa_s) +{ + struct wpa_driver_scan_params params; + struct wpa_driver_scan_params *scan_params; + enum wpa_states prev_state; + struct wpa_ssid *ssid = NULL; + struct wpabuf *extra_ie = NULL; + int ret; + unsigned int max_sched_scan_ssids; + int wildcard = 0; + int need_ssids; + + if (!wpa_s->sched_scan_supported) + return -1; + +#if 0 + if (wpa_s->max_sched_scan_ssids > WPAS_MAX_SCAN_SSIDS) + max_sched_scan_ssids = WPAS_MAX_SCAN_SSIDS; + else + max_sched_scan_ssids = wpa_s->max_sched_scan_ssids; + if (max_sched_scan_ssids < 1 || wpa_s->conf->disable_scan_offload) + return -1; + + if (wpa_s->sched_scanning) { + wpa_dbg(wpa_s, MSG_DEBUG, "Already sched scanning"); + return 0; + } + + need_ssids = 0; + for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { + if (!wpas_network_disabled(wpa_s, ssid) && !ssid->scan_ssid) { + /* Use wildcard SSID to find this network */ + wildcard = 1; + } else if (!wpas_network_disabled(wpa_s, ssid) && + ssid->ssid_len) + need_ssids++; + +#ifdef CONFIG_WPS + if (!wpas_network_disabled(wpa_s, ssid) && + ssid->key_mgmt == WPA_KEY_MGMT_WPS) { + /* + * Normal scan is more reliable and faster for WPS + * operations and since these are for short periods of + * time, the benefit of trying to use sched_scan would + * be limited. + */ + wpa_dbg(wpa_s, MSG_DEBUG, "Use normal scan instead of " + "sched_scan for WPS"); + return -1; + } +#endif /* CONFIG_WPS */ + } + if (wildcard) + need_ssids++; + + if (wpa_s->normal_scans < 3 && + (need_ssids <= wpa_s->max_scan_ssids || + wpa_s->max_scan_ssids >= (int) max_sched_scan_ssids)) { + /* + * When normal scan can speed up operations, use that for the + * first operations before starting the sched_scan to allow + * user space sleep more. We do this only if the normal scan + * has functionality that is suitable for this or if the + * sched_scan does not have better support for multiple SSIDs. + */ + wpa_dbg(wpa_s, MSG_DEBUG, "Use normal scan instead of " + "sched_scan for initial scans (normal_scans=%d)", + wpa_s->normal_scans); + return -1; + } + + os_memset(¶ms, 0, sizeof(params)); + + /* If we can't allocate space for the filters, we just don't filter */ + params.filter_ssids = os_calloc(wpa_s->max_match_sets, + sizeof(struct wpa_driver_scan_filter)); + + prev_state = wpa_s->wpa_state; + if (wpa_s->wpa_state == WPA_DISCONNECTED || + wpa_s->wpa_state == WPA_INACTIVE) + wpa_supplicant_set_state(wpa_s, WPA_SCANNING); + + if (wpa_s->autoscan_params != NULL) { + scan_params = wpa_s->autoscan_params; + goto scan; + } + + /* Find the starting point from which to continue scanning */ + ssid = wpa_s->conf->ssid; + if (wpa_s->prev_sched_ssid) { + while (ssid) { + if (ssid == wpa_s->prev_sched_ssid) { + ssid = ssid->next; + break; + } + ssid = ssid->next; + } + } + + if (!ssid || !wpa_s->prev_sched_ssid) { + wpa_dbg(wpa_s, MSG_DEBUG, "Beginning of SSID list"); + if (wpa_s->conf->sched_scan_interval) + wpa_s->sched_scan_interval = + wpa_s->conf->sched_scan_interval; + if (wpa_s->sched_scan_interval == 0) + wpa_s->sched_scan_interval = 10; + wpa_s->sched_scan_timeout = max_sched_scan_ssids * 2; + wpa_s->first_sched_scan = 1; + ssid = wpa_s->conf->ssid; + wpa_s->prev_sched_ssid = ssid; + } + + if (wildcard) { + wpa_dbg(wpa_s, MSG_DEBUG, "Add wildcard SSID to sched_scan"); + params.num_ssids++; + } + + while (ssid) { + if (wpas_network_disabled(wpa_s, ssid)) + goto next; + + if (params.num_filter_ssids < wpa_s->max_match_sets && + params.filter_ssids && ssid->ssid && ssid->ssid_len) { + wpa_dbg(wpa_s, MSG_DEBUG, "add to filter ssid: %s", + wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); + os_memcpy(params.filter_ssids[params.num_filter_ssids].ssid, + ssid->ssid, ssid->ssid_len); + params.filter_ssids[params.num_filter_ssids].ssid_len = + ssid->ssid_len; + params.num_filter_ssids++; + } else if (params.filter_ssids && ssid->ssid && ssid->ssid_len) + { + wpa_dbg(wpa_s, MSG_DEBUG, "Not enough room for SSID " + "filter for sched_scan - drop filter"); + os_free(params.filter_ssids); + params.filter_ssids = NULL; + params.num_filter_ssids = 0; + } + + if (ssid->scan_ssid && ssid->ssid && ssid->ssid_len) { + if (params.num_ssids == max_sched_scan_ssids) + break; /* only room for broadcast SSID */ + wpa_dbg(wpa_s, MSG_DEBUG, + "add to active scan ssid: %s", + wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); + params.ssids[params.num_ssids].ssid = + ssid->ssid; + params.ssids[params.num_ssids].ssid_len = + ssid->ssid_len; + params.num_ssids++; + if (params.num_ssids >= max_sched_scan_ssids) { + wpa_s->prev_sched_ssid = ssid; + do { + ssid = ssid->next; + } while (ssid && + (wpas_network_disabled(wpa_s, ssid) || + !ssid->scan_ssid)); + break; + } + } + + next: + wpa_s->prev_sched_ssid = ssid; + ssid = ssid->next; + } + + if (params.num_filter_ssids == 0) { + os_free(params.filter_ssids); + params.filter_ssids = NULL; + } + + extra_ie = wpa_supplicant_extra_ies(wpa_s); + if (extra_ie) { + params.extra_ies = wpabuf_head(extra_ie); + params.extra_ies_len = wpabuf_len(extra_ie); + } + + if (wpa_s->conf->filter_rssi) + params.filter_rssi = wpa_s->conf->filter_rssi; + + /* See if user specified frequencies. If so, scan only those. */ + if (wpa_s->conf->freq_list && !params.freqs) { + wpa_dbg(wpa_s, MSG_DEBUG, + "Optimize scan based on conf->freq_list"); + int_array_concat(¶ms.freqs, wpa_s->conf->freq_list); + } + + scan_params = ¶ms; + +scan: + if (ssid || !wpa_s->first_sched_scan) { + wpa_dbg(wpa_s, MSG_DEBUG, + "Starting sched scan: interval %d timeout %d", + wpa_s->sched_scan_interval, wpa_s->sched_scan_timeout); + } else { + wpa_dbg(wpa_s, MSG_DEBUG, + "Starting sched scan: interval %d (no timeout)", + wpa_s->sched_scan_interval); + } + + wpa_setband_scan_freqs(wpa_s, scan_params); + + if (wpa_s->mac_addr_rand_enable & MAC_ADDR_RAND_SCHED_SCAN) { + params.mac_addr_rand = 1; + if (wpa_s->mac_addr_sched_scan) { + params.mac_addr = wpa_s->mac_addr_sched_scan; + params.mac_addr_mask = wpa_s->mac_addr_sched_scan + + ETH_ALEN; + } + } + + ret = wpa_supplicant_start_sched_scan(wpa_s, scan_params, + wpa_s->sched_scan_interval); + wpabuf_free(extra_ie); + os_free(params.filter_ssids); + if (ret) { + wpa_msg(wpa_s, MSG_WARNING, "Failed to initiate sched scan"); + if (prev_state != wpa_s->wpa_state) + wpa_supplicant_set_state(wpa_s, prev_state); + return ret; + } + + /* If we have more SSIDs to scan, add a timeout so we scan them too */ + if (ssid || !wpa_s->first_sched_scan) { + wpa_s->sched_scan_timed_out = 0; + eloop_register_timeout(wpa_s->sched_scan_timeout, 0, + wpa_supplicant_sched_scan_timeout, + wpa_s, NULL); + wpa_s->first_sched_scan = 0; + wpa_s->sched_scan_timeout /= 2; + wpa_s->sched_scan_interval *= 2; + if (wpa_s->sched_scan_timeout < wpa_s->sched_scan_interval) { + wpa_s->sched_scan_interval = 10; + wpa_s->sched_scan_timeout = max_sched_scan_ssids * 2; + } + } + + /* If there is no more ssids, start next time from the beginning */ + if (!ssid) + wpa_s->prev_sched_ssid = NULL; + + return 0; +#else + return 0; + (void)need_ssids; + (void)wildcard; + (void)max_sched_scan_ssids; + (void)ret; + (void)extra_ie; + (void)ssid; + (void)prev_state; + (void)scan_params; + (void)params; +#endif +} + + +/** + * wpa_supplicant_cancel_scan - Cancel a scheduled scan request + * @wpa_s: Pointer to wpa_supplicant data + * + * This function is used to cancel a scan request scheduled with + * wpa_supplicant_req_scan(). + */ +void wpa_supplicant_cancel_scan(struct wpa_supplicant *wpa_s) +{ + os_null_printf("Cancelling scan request\r\n"); + eloop_cancel_timeout(wpa_supplicant_scan, wpa_s, NULL); +} + + +/** + * wpa_supplicant_cancel_delayed_sched_scan - Stop a delayed scheduled scan + * @wpa_s: Pointer to wpa_supplicant data + * + * This function is used to stop a delayed scheduled scan. + */ +void wpa_supplicant_cancel_delayed_sched_scan(struct wpa_supplicant *wpa_s) +{ + if (!wpa_s->sched_scan_supported) + return; + + wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling delayed sched scan"); + eloop_cancel_timeout(wpa_supplicant_delayed_sched_scan_timeout, + wpa_s, NULL); +} + + +/** + * wpa_supplicant_cancel_sched_scan - Stop running scheduled scans + * @wpa_s: Pointer to wpa_supplicant data + * + * This function is used to stop a periodic scheduled scan. + */ +void wpa_supplicant_cancel_sched_scan(struct wpa_supplicant *wpa_s) +{ + if (!wpa_s->sched_scanning) + return; + + wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling sched scan"); + eloop_cancel_timeout(wpa_supplicant_sched_scan_timeout, wpa_s, NULL); + wpa_supplicant_stop_sched_scan(wpa_s); +} + + +/** + * wpa_supplicant_notify_scanning - Indicate possible scan state change + * @wpa_s: Pointer to wpa_supplicant data + * @scanning: Whether scanning is currently in progress + * + * This function is to generate scanning notifycations. It is called whenever + * there may have been a change in scanning (scan started, completed, stopped). + * wpas_notify_scanning() is called whenever the scanning state changed from the + * previously notified state. + */ +void wpa_supplicant_notify_scanning(struct wpa_supplicant *wpa_s, + int scanning) +{ + if (wpa_s->scanning != scanning) { + wpa_s->scanning = scanning; + wpas_notify_scanning(wpa_s); + } +} + + +static int wpa_scan_get_max_rate(const struct wpa_scan_res *res) +{ + int rate = 0; + const u8 *ie; + int i; + + ie = wpa_scan_get_ie(res, WLAN_EID_SUPP_RATES); + for (i = 0; ie && i < ie[1]; i++) { + if ((ie[i + 2] & 0x7f) > rate) + rate = ie[i + 2] & 0x7f; + } + + ie = wpa_scan_get_ie(res, WLAN_EID_EXT_SUPP_RATES); + for (i = 0; ie && i < ie[1]; i++) { + if ((ie[i + 2] & 0x7f) > rate) + rate = ie[i + 2] & 0x7f; + } + + return rate; +} + + +/** + * wpa_scan_get_ie - Fetch a specified information element from a scan result + * @res: Scan result entry + * @ie: Information element identitifier (WLAN_EID_*) + * Returns: Pointer to the information element (id field) or %NULL if not found + * + * This function returns the first matching information element in the scan + * result. + */ +const u8 * wpa_scan_get_ie(const struct wpa_scan_res *res, u8 ie) +{ + const u8 *end, *pos; + + pos = (const u8 *) (res + 1); + end = pos + res->ie_len; + + while (pos + 1 < end) { + if (pos + 2 + pos[1] > end) + break; + if (pos[0] == ie) + return pos; + pos += 2 + pos[1]; + } + + return NULL; +} + + +/** + * wpa_scan_get_vendor_ie - Fetch vendor information element from a scan result + * @res: Scan result entry + * @vendor_type: Vendor type (four octets starting the IE payload) + * Returns: Pointer to the information element (id field) or %NULL if not found + * + * This function returns the first matching information element in the scan + * result. + */ +const u8 * wpa_scan_get_vendor_ie(const struct wpa_scan_res *res, + u32 vendor_type) +{ + const u8 *end, *pos; + + pos = (const u8 *) (res + 1); + end = pos + res->ie_len; + + while (pos + 1 < end) { + if (pos + 2 + pos[1] > end) + break; + if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && + vendor_type == WPA_GET_BE32(&pos[2])) + return pos; + pos += 2 + pos[1]; + } + + return NULL; +} + + +/** + * wpa_scan_get_vendor_ie_beacon - Fetch vendor information from a scan result + * @res: Scan result entry + * @vendor_type: Vendor type (four octets starting the IE payload) + * Returns: Pointer to the information element (id field) or %NULL if not found + * + * This function returns the first matching information element in the scan + * result. + * + * This function is like wpa_scan_get_vendor_ie(), but uses IE buffer only + * from Beacon frames instead of either Beacon or Probe Response frames. + */ +const u8 * wpa_scan_get_vendor_ie_beacon(const struct wpa_scan_res *res, + u32 vendor_type) +{ + const u8 *end, *pos; + + if (res->beacon_ie_len == 0) + return NULL; + + pos = (const u8 *) (res + 1); + pos += res->ie_len; + end = pos + res->beacon_ie_len; + + while (pos + 1 < end) { + if (pos + 2 + pos[1] > end) + break; + if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && + vendor_type == WPA_GET_BE32(&pos[2])) + return pos; + pos += 2 + pos[1]; + } + + return NULL; +} + + +/** + * wpa_scan_get_vendor_ie_multi - Fetch vendor IE data from a scan result + * @res: Scan result entry + * @vendor_type: Vendor type (four octets starting the IE payload) + * Returns: Pointer to the information element payload or %NULL if not found + * + * This function returns concatenated payload of possibly fragmented vendor + * specific information elements in the scan result. The caller is responsible + * for freeing the returned buffer. + */ +struct wpabuf * wpa_scan_get_vendor_ie_multi(const struct wpa_scan_res *res, + u32 vendor_type) +{ + struct wpabuf *buf; + const u8 *end, *pos; + + buf = wpabuf_alloc(res->ie_len); + if (buf == NULL) + return NULL; + + pos = (const u8 *) (res + 1); + end = pos + res->ie_len; + + while (pos + 1 < end) { + if (pos + 2 + pos[1] > end) + break; + if (pos[0] == WLAN_EID_VENDOR_SPECIFIC && pos[1] >= 4 && + vendor_type == WPA_GET_BE32(&pos[2])) + wpabuf_put_data(buf, pos + 2 + 4, pos[1] - 4); + pos += 2 + pos[1]; + } + + if (wpabuf_len(buf) == 0) { + wpabuf_free(buf); + buf = NULL; + } + + return buf; +} + + +/* + * Channels with a great SNR can operate at full rate. What is a great SNR? + * This doc https://supportforums.cisco.com/docs/DOC-12954 says, "the general + * rule of thumb is that any SNR above 20 is good." This one + * http://www.cisco.com/en/US/tech/tk722/tk809/technologies_q_and_a_item09186a00805e9a96.shtml#qa23 + * recommends 25 as a minimum SNR for 54 Mbps data rate. 30 is chosen here as a + * conservative value. + */ +#define GREAT_SNR 30 + +#define IS_5GHZ(n) (n > 4000) + +/* Compare function for sorting scan results. Return >0 if @b is considered + * better. */ +static int wpa_scan_result_compar(const void *a, const void *b) +{ + struct wpa_scan_res **_wa = (void *) a; + struct wpa_scan_res **_wb = (void *) b; + struct wpa_scan_res *wa = *_wa; + struct wpa_scan_res *wb = *_wb; + int wpa_a, wpa_b; + int snr_a, snr_b, snr_a_full, snr_b_full; + + /* WPA/WPA2 support preferred */ + wpa_a = wpa_scan_get_vendor_ie(wa, WPA_IE_VENDOR_TYPE) != NULL || + wpa_scan_get_ie(wa, WLAN_EID_RSN) != NULL; + wpa_b = wpa_scan_get_vendor_ie(wb, WPA_IE_VENDOR_TYPE) != NULL || + wpa_scan_get_ie(wb, WLAN_EID_RSN) != NULL; + + if (wpa_b && !wpa_a) + return 1; + if (!wpa_b && wpa_a) + return -1; + + /* privacy support preferred */ + if ((wa->caps & IEEE80211_CAP_PRIVACY) == 0 && + (wb->caps & IEEE80211_CAP_PRIVACY)) + return 1; + if ((wa->caps & IEEE80211_CAP_PRIVACY) && + (wb->caps & IEEE80211_CAP_PRIVACY) == 0) + return -1; + + if (wa->flags & wb->flags & WPA_SCAN_LEVEL_DBM) { + snr_a_full = wa->snr; + snr_a = MIN(wa->snr, GREAT_SNR); + snr_b_full = wb->snr; + snr_b = MIN(wb->snr, GREAT_SNR); + } else { + /* Level is not in dBm, so we can't calculate + * SNR. Just use raw level (units unknown). */ + snr_a = snr_a_full = wa->level; + snr_b = snr_b_full = wb->level; + } + + /* if SNR is close, decide by max rate or frequency band */ + if ((snr_a && snr_b && abs(snr_b - snr_a) < 5) || + (wa->qual && wb->qual && abs(wb->qual - wa->qual) < 10)) { + if (wa->est_throughput != wb->est_throughput) + return wb->est_throughput - wa->est_throughput; + if (IS_5GHZ(wa->freq) ^ IS_5GHZ(wb->freq)) + return IS_5GHZ(wa->freq) ? -1 : 1; + } + + /* all things being equal, use SNR; if SNRs are + * identical, use quality values since some drivers may only report + * that value and leave the signal level zero */ + if (snr_b_full == snr_a_full) + return wb->qual - wa->qual; + return snr_b_full - snr_a_full; +#undef MIN +} + + +#ifdef CONFIG_WPS +/* Compare function for sorting scan results when searching a WPS AP for + * provisioning. Return >0 if @b is considered better. */ +static int wpa_scan_result_wps_compar(const void *a, const void *b) +{ + struct wpa_scan_res **_wa = (void *) a; + struct wpa_scan_res **_wb = (void *) b; + struct wpa_scan_res *wa = *_wa; + struct wpa_scan_res *wb = *_wb; + int uses_wps_a, uses_wps_b; + struct wpabuf *wps_a, *wps_b; + int res; + + /* Optimization - check WPS IE existence before allocated memory and + * doing full reassembly. */ + uses_wps_a = wpa_scan_get_vendor_ie(wa, WPS_IE_VENDOR_TYPE) != NULL; + uses_wps_b = wpa_scan_get_vendor_ie(wb, WPS_IE_VENDOR_TYPE) != NULL; + if (uses_wps_a && !uses_wps_b) + return -1; + if (!uses_wps_a && uses_wps_b) + return 1; + + if (uses_wps_a && uses_wps_b) { + wps_a = wpa_scan_get_vendor_ie_multi(wa, WPS_IE_VENDOR_TYPE); + wps_b = wpa_scan_get_vendor_ie_multi(wb, WPS_IE_VENDOR_TYPE); + res = wps_ap_priority_compar(wps_a, wps_b); + wpabuf_free(wps_a); + wpabuf_free(wps_b); + if (res) + return res; + } + + /* + * Do not use current AP security policy as a sorting criteria during + * WPS provisioning step since the AP may get reconfigured at the + * completion of provisioning. + */ + + /* all things being equal, use signal level; if signal levels are + * identical, use quality values since some drivers may only report + * that value and leave the signal level zero */ + if (wb->level == wa->level) + return wb->qual - wa->qual; + return wb->level - wa->level; +} +#endif /* CONFIG_WPS */ + + +static void dump_scan_res(struct wpa_scan_results *scan_res) +{ +#ifndef CONFIG_NO_STDOUT_DEBUG + size_t i; + + if (scan_res->res == NULL || scan_res->num == 0) + return; + + wpa_printf(MSG_EXCESSIVE, "Sorted scan results"); + + for (i = 0; i < scan_res->num; i++) { + struct wpa_scan_res *r = scan_res->res[i]; + u8 *pos; + if (r->flags & WPA_SCAN_LEVEL_DBM) { + int noise_valid = !(r->flags & WPA_SCAN_NOISE_INVALID); + + wpa_printf(MSG_EXCESSIVE, MACSTR " freq=%d qual=%d " + "noise=%d%s level=%d snr=%d%s flags=0x%x age=%u est=%u", + MAC2STR(r->bssid), r->freq, r->qual, + r->noise, noise_valid ? "" : "~", r->level, + r->snr, r->snr >= GREAT_SNR ? "*" : "", + r->flags, + r->age, r->est_throughput); + } else { + wpa_printf(MSG_EXCESSIVE, MACSTR " freq=%d qual=%d " + "noise=%d level=%d flags=0x%x age=%u est=%u", + MAC2STR(r->bssid), r->freq, r->qual, + r->noise, r->level, r->flags, r->age, + r->est_throughput); + } + pos = (u8 *) (r + 1); + if (r->ie_len) + wpa_hexdump(MSG_EXCESSIVE, "IEs", pos, r->ie_len); + pos += r->ie_len; + if (r->beacon_ie_len) + wpa_hexdump(MSG_EXCESSIVE, "Beacon IEs", + pos, r->beacon_ie_len); + } +#endif /* CONFIG_NO_STDOUT_DEBUG */ +} + + +/** + * wpa_supplicant_filter_bssid_match - Is the specified BSSID allowed + * @wpa_s: Pointer to wpa_supplicant data + * @bssid: BSSID to check + * Returns: 0 if the BSSID is filtered or 1 if not + * + * This function is used to filter out specific BSSIDs from scan reslts mainly + * for testing purposes (SET bssid_filter ctrl_iface command). + */ +int wpa_supplicant_filter_bssid_match(struct wpa_supplicant *wpa_s, + const u8 *bssid) +{ + size_t i; + + if (wpa_s->bssid_filter == NULL) + return 1; + + for (i = 0; i < wpa_s->bssid_filter_count; i++) { + if (os_memcmp(wpa_s->bssid_filter + i * ETH_ALEN, bssid, + ETH_ALEN) == 0) + return 1; + } + + return 0; +} + + +static void filter_scan_res(struct wpa_supplicant *wpa_s, + struct wpa_scan_results *res) +{ + size_t i, j; + + if (wpa_s->bssid_filter == NULL) + return; + + for (i = 0, j = 0; i < res->num; i++) { + if (wpa_supplicant_filter_bssid_match(wpa_s, + res->res[i]->bssid)) { + res->res[j++] = res->res[i]; + } else { + os_free(res->res[i]); + res->res[i] = NULL; + } + } + + if (res->num != j) { + wpa_printf(MSG_DEBUG, "Filtered out %d scan results", + (int) (res->num - j)); + res->num = j; + } +} + + +/* + * Noise floor values to use when we have signal strength + * measurements, but no noise floor measurments. These values were + * measured in an office environment with many APs. + */ +#define DEFAULT_NOISE_FLOOR_2GHZ (-89) +#define DEFAULT_NOISE_FLOOR_5GHZ (-92) + +static void scan_snr(struct wpa_scan_res *res) +{ + if (res->flags & WPA_SCAN_NOISE_INVALID) { + res->noise = IS_5GHZ(res->freq) ? + DEFAULT_NOISE_FLOOR_5GHZ : + DEFAULT_NOISE_FLOOR_2GHZ; + } + + if (res->flags & WPA_SCAN_LEVEL_DBM) { + res->snr = res->level - res->noise; + } else { + /* Level is not in dBm, so we can't calculate + * SNR. Just use raw level (units unknown). */ + res->snr = res->level; + } +} + + +static unsigned int max_ht20_rate(int snr) +{ + if (snr < 6) + return 6500; /* HT20 MCS0 */ + if (snr < 8) + return 13000; /* HT20 MCS1 */ + if (snr < 13) + return 19500; /* HT20 MCS2 */ + if (snr < 17) + return 26000; /* HT20 MCS3 */ + if (snr < 20) + return 39000; /* HT20 MCS4 */ + if (snr < 23) + return 52000; /* HT20 MCS5 */ + if (snr < 24) + return 58500; /* HT20 MCS6 */ + return 65000; /* HT20 MCS7 */ +} + + +static unsigned int max_ht40_rate(int snr) +{ + if (snr < 3) + return 13500; /* HT40 MCS0 */ + if (snr < 6) + return 27000; /* HT40 MCS1 */ + if (snr < 10) + return 40500; /* HT40 MCS2 */ + if (snr < 15) + return 54000; /* HT40 MCS3 */ + if (snr < 17) + return 81000; /* HT40 MCS4 */ + if (snr < 22) + return 108000; /* HT40 MCS5 */ + if (snr < 24) + return 121500; /* HT40 MCS6 */ + return 135000; /* HT40 MCS7 */ +} + + +static unsigned int max_vht80_rate(int snr) +{ + if (snr < 1) + return 0; + if (snr < 2) + return 29300; /* VHT80 MCS0 */ + if (snr < 5) + return 58500; /* VHT80 MCS1 */ + if (snr < 9) + return 87800; /* VHT80 MCS2 */ + if (snr < 11) + return 117000; /* VHT80 MCS3 */ + if (snr < 15) + return 175500; /* VHT80 MCS4 */ + if (snr < 16) + return 234000; /* VHT80 MCS5 */ + if (snr < 18) + return 263300; /* VHT80 MCS6 */ + if (snr < 20) + return 292500; /* VHT80 MCS7 */ + if (snr < 22) + return 351000; /* VHT80 MCS8 */ + return 390000; /* VHT80 MCS9 */ +} + + +static void scan_est_throughput(struct wpa_supplicant *wpa_s, + struct wpa_scan_res *res) +{ + enum local_hw_capab capab = wpa_s->hw_capab; + int rate; /* max legacy rate in 500 kb/s units */ + const u8 *ie; + unsigned int est, tmp; + int snr = res->snr; + + if (res->est_throughput) + return; + + /* Get maximum legacy rate */ + rate = wpa_scan_get_max_rate(res); + + /* Limit based on estimated SNR */ + if (rate > 1 * 2 && snr < 1) + rate = 1 * 2; + else if (rate > 2 * 2 && snr < 4) + rate = 2 * 2; + else if (rate > 6 * 2 && snr < 5) + rate = 6 * 2; + else if (rate > 9 * 2 && snr < 6) + rate = 9 * 2; + else if (rate > 12 * 2 && snr < 7) + rate = 12 * 2; + else if (rate > 18 * 2 && snr < 10) + rate = 18 * 2; + else if (rate > 24 * 2 && snr < 11) + rate = 24 * 2; + else if (rate > 36 * 2 && snr < 15) + rate = 36 * 2; + else if (rate > 48 * 2 && snr < 19) + rate = 48 * 2; + else if (rate > 54 * 2 && snr < 21) + rate = 54 * 2; + est = rate * 500; + + if (capab == CAPAB_HT || capab == CAPAB_HT40 || capab == CAPAB_VHT) { + ie = wpa_scan_get_ie(res, WLAN_EID_HT_CAP); + if (ie) { + tmp = max_ht20_rate(snr); + if (tmp > est) + est = tmp; + } + } + + if (capab == CAPAB_HT40 || capab == CAPAB_VHT) { + ie = wpa_scan_get_ie(res, WLAN_EID_HT_OPERATION); + if (ie && ie[1] >= 2 && + (ie[3] & HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK)) { + tmp = max_ht40_rate(snr); + if (tmp > est) + est = tmp; + } + } + + if (capab == CAPAB_VHT) { + /* Use +1 to assume VHT is always faster than HT */ + ie = wpa_scan_get_ie(res, WLAN_EID_VHT_CAP); + if (ie) { + tmp = max_ht20_rate(snr) + 1; + if (tmp > est) + est = tmp; + + ie = wpa_scan_get_ie(res, WLAN_EID_HT_OPERATION); + if (ie && ie[1] >= 2 && + (ie[3] & + HT_INFO_HT_PARAM_SECONDARY_CHNL_OFF_MASK)) { + tmp = max_ht40_rate(snr) + 1; + if (tmp > est) + est = tmp; + } + + ie = wpa_scan_get_ie(res, WLAN_EID_VHT_OPERATION); + if (ie && ie[1] >= 1 && + (ie[2] & VHT_OPMODE_CHANNEL_WIDTH_MASK)) { + tmp = max_vht80_rate(snr) + 1; + if (tmp > est) + est = tmp; + } + } + } + + /* TODO: channel utilization and AP load (e.g., from AP Beacon) */ + + res->est_throughput = est; +} + + +/** + * wpa_supplicant_get_scan_results - Get scan results + * @wpa_s: Pointer to wpa_supplicant data + * @info: Information about what was scanned or %NULL if not available + * @new_scan: Whether a new scan was performed + * Returns: Scan results, %NULL on failure + * + * This function request the current scan results from the driver and updates + * the local BSS list wpa_s->bss. The caller is responsible for freeing the + * results with wpa_scan_results_free(). + */ +struct wpa_scan_results * +wpa_supplicant_get_scan_results(struct wpa_supplicant *wpa_s, + struct scan_info *info, int new_scan) +{ + struct wpa_scan_results *scan_res; + size_t i; + int (*compar)(const void *, const void *) = wpa_scan_result_compar; + + scan_res = wpa_drv_get_scan_results2(wpa_s); + if (scan_res == NULL) { + wpa_dbg(wpa_s, MSG_DEBUG, "Failed to get scan results"); + return NULL; + } + if (scan_res->fetch_time.sec == 0) { + /* + * Make sure we have a valid timestamp if the driver wrapper + * does not set this. + */ + os_get_reltime(&scan_res->fetch_time); + } + filter_scan_res(wpa_s, scan_res); + + for (i = 0; i < scan_res->num; i++) { + struct wpa_scan_res *scan_res_item = scan_res->res[i]; + + scan_snr(scan_res_item); + scan_est_throughput(wpa_s, scan_res_item); + } + +#ifdef CONFIG_WPS + if (wpas_wps_searching(wpa_s)) { + wpa_dbg(wpa_s, MSG_DEBUG, "WPS: Order scan results with WPS " + "provisioning rules"); + compar = wpa_scan_result_wps_compar; + } +#endif /* CONFIG_WPS */ + + qsort(scan_res->res, scan_res->num, sizeof(struct wpa_scan_res *), + compar); + dump_scan_res(scan_res); + + wpa_bss_update_start(wpa_s); + for (i = 0; i < scan_res->num; i++) + wpa_bss_update_scan_res(wpa_s, scan_res->res[i], + &scan_res->fetch_time); + wpa_bss_update_end(wpa_s, info, new_scan); + + return scan_res; +} + + +/** + * wpa_supplicant_update_scan_results - Update scan results from the driver + * @wpa_s: Pointer to wpa_supplicant data + * Returns: 0 on success, -1 on failure + * + * This function updates the BSS table within wpa_supplicant based on the + * currently available scan results from the driver without requesting a new + * scan. This is used in cases where the driver indicates an association + * (including roaming within ESS) and wpa_supplicant does not yet have the + * needed information to complete the connection (e.g., to perform validation + * steps in 4-way handshake). + */ +int wpa_supplicant_update_scan_results(struct wpa_supplicant *wpa_s) +{ + struct wpa_scan_results *scan_res; + scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0); + if (scan_res == NULL) + return -1; + wpa_scan_results_free(scan_res); + + return 0; +} + + +/** + * scan_only_handler - Reports scan results + */ +void scan_only_handler(struct wpa_supplicant *wpa_s, + struct wpa_scan_results *scan_res) +{ + wpa_dbg(wpa_s, MSG_DEBUG, "Scan-only results received"); + if (wpa_s->last_scan_req == MANUAL_SCAN_REQ && + wpa_s->manual_scan_use_id && wpa_s->own_scan_running) { + wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_SCAN_RESULTS "id=%u", + wpa_s->manual_scan_id); + wpa_s->manual_scan_use_id = 0; + } else { + wpa_msg_ctrl(wpa_s, MSG_INFO, WPA_EVENT_SCAN_RESULTS); + } + wpas_notify_scan_results(wpa_s); + wpas_notify_scan_done(wpa_s, 1); + if (wpa_s->scan_work) { + struct wpa_radio_work *work = wpa_s->scan_work; + wpa_s->scan_work = NULL; + radio_work_done(work); + } +} + +int wpas_scan_scheduled(struct wpa_supplicant *wpa_s) +{ + return eloop_is_timeout_registered(wpa_supplicant_scan, wpa_s, NULL); +} + + +struct wpa_driver_scan_params * +wpa_scan_clone_params(const struct wpa_driver_scan_params *src) +{ + struct wpa_driver_scan_params *params; + size_t i; + u8 *n; + + params = os_zalloc(sizeof(*params)); + if (params == NULL) + return NULL; + + for (i = 0; i < src->num_ssids; i++) { + if (src->ssids[i].ssid) { + n = os_malloc(src->ssids[i].ssid_len); + if (n == NULL) + goto failed; + os_memcpy(n, src->ssids[i].ssid, + src->ssids[i].ssid_len); + params->ssids[i].ssid = n; + params->ssids[i].ssid_len = src->ssids[i].ssid_len; + } + } + params->num_ssids = src->num_ssids; + + if (src->extra_ies) { + n = os_malloc(src->extra_ies_len); + if (n == NULL) + goto failed; + os_memcpy(n, src->extra_ies, src->extra_ies_len); + params->extra_ies = n; + params->extra_ies_len = src->extra_ies_len; + } + + if (src->freqs) { + int len = int_array_len(src->freqs); + params->freqs = os_malloc((len + 1) * sizeof(int)); + if (params->freqs == NULL) + goto failed; + os_memcpy(params->freqs, src->freqs, (len + 1) * sizeof(int)); + } + + if (src->filter_ssids) { + params->filter_ssids = os_malloc(sizeof(*params->filter_ssids) * + src->num_filter_ssids); + if (params->filter_ssids == NULL) + goto failed; + os_memcpy(params->filter_ssids, src->filter_ssids, + sizeof(*params->filter_ssids) * + src->num_filter_ssids); + params->num_filter_ssids = src->num_filter_ssids; + } + + params->filter_rssi = src->filter_rssi; + params->p2p_probe = src->p2p_probe; + params->only_new_results = src->only_new_results; + params->low_priority = src->low_priority; + + if (src->mac_addr_rand) { + params->mac_addr_rand = src->mac_addr_rand; + + if (src->mac_addr && src->mac_addr_mask) { + u8 *mac_addr; + + mac_addr = os_malloc(2 * ETH_ALEN); + if (!mac_addr) + goto failed; + + os_memcpy(mac_addr, src->mac_addr, ETH_ALEN); + os_memcpy(mac_addr + ETH_ALEN, src->mac_addr_mask, + ETH_ALEN); + params->mac_addr = mac_addr; + params->mac_addr_mask = mac_addr + ETH_ALEN; + } + } + return params; + +failed: + wpa_scan_free_params(params); + return NULL; +} + + +void wpa_scan_free_params(struct wpa_driver_scan_params *params) +{ + size_t i; + + if (params == NULL) + return; + + for (i = 0; i < params->num_ssids; i++) + os_free((u8 *) params->ssids[i].ssid); + os_free((u8 *) params->extra_ies); + os_free(params->freqs); + os_free(params->filter_ssids); + + /* + * Note: params->mac_addr_mask points to same memory allocation and + * must not be freed separately. + */ + os_free((u8 *) params->mac_addr); + + os_free(params); +} + + +int wpas_start_pno(struct wpa_supplicant *wpa_s) +{ + int ret, interval, prio; + size_t i, num_ssid, num_match_ssid; + struct wpa_ssid *ssid; + struct wpa_driver_scan_params params; + + if (!wpa_s->sched_scan_supported) + return -1; + + if (wpa_s->pno || wpa_s->pno_sched_pending) + return 0; + + if ((wpa_s->wpa_state > WPA_SCANNING) && + (wpa_s->wpa_state <= WPA_COMPLETED)) { + wpa_printf(MSG_ERROR, "PNO: In assoc process"); + return -ERRAGAIN; + } + + if (wpa_s->wpa_state == WPA_SCANNING) { + wpa_supplicant_cancel_scan(wpa_s); + if (wpa_s->sched_scanning) { + wpa_printf(MSG_DEBUG, "Schedule PNO on completion of " + "ongoing sched scan"); + wpa_supplicant_cancel_sched_scan(wpa_s); + wpa_s->pno_sched_pending = 1; + return 0; + } + } + + os_memset(¶ms, 0, sizeof(params)); + + num_ssid = num_match_ssid = 0; + ssid = wpa_s->conf->ssid; + while (ssid) { + if (!wpas_network_disabled(wpa_s, ssid)) { + num_match_ssid++; + if (ssid->scan_ssid) + num_ssid++; + } + ssid = ssid->next; + } + + if (num_match_ssid == 0) { + wpa_printf(MSG_DEBUG, "PNO: No configured SSIDs"); + return -1; + } + + if (num_match_ssid > num_ssid) { + params.num_ssids++; /* wildcard */ + num_ssid++; + } + + if (num_ssid > WPAS_MAX_SCAN_SSIDS) { + wpa_printf(MSG_DEBUG, "PNO: Use only the first %u SSIDs from " + "%u", WPAS_MAX_SCAN_SSIDS, (unsigned int) num_ssid); + num_ssid = WPAS_MAX_SCAN_SSIDS; + } + + if (num_match_ssid > wpa_s->max_match_sets) { + num_match_ssid = wpa_s->max_match_sets; + wpa_dbg(wpa_s, MSG_DEBUG, "PNO: Too many SSIDs to match"); + } + params.filter_ssids = os_calloc(num_match_ssid, + sizeof(struct wpa_driver_scan_filter)); + if (params.filter_ssids == NULL) + return -1; + + i = 0; + prio = 0; + ssid = wpa_s->conf->pssid[prio]; + while (ssid) { + if (!wpas_network_disabled(wpa_s, ssid)) { + if (ssid->scan_ssid && params.num_ssids < num_ssid) { + params.ssids[params.num_ssids].ssid = + ssid->ssid; + params.ssids[params.num_ssids].ssid_len = + ssid->ssid_len; + params.num_ssids++; + } + os_memcpy(params.filter_ssids[i].ssid, ssid->ssid, + ssid->ssid_len); + params.filter_ssids[i].ssid_len = ssid->ssid_len; + params.num_filter_ssids++; + i++; + if (i == num_match_ssid) + break; + } + if (ssid->pnext) + ssid = ssid->pnext; + else if (prio + 1 == wpa_s->conf->num_prio) + break; + else + ssid = wpa_s->conf->pssid[++prio]; + } + + if (wpa_s->conf->filter_rssi) + params.filter_rssi = wpa_s->conf->filter_rssi; + + interval = wpa_s->conf->sched_scan_interval ? + wpa_s->conf->sched_scan_interval : 10; + + if (params.freqs == NULL && wpa_s->manual_sched_scan_freqs) { + wpa_dbg(wpa_s, MSG_DEBUG, "Limit sched scan to specified channels"); + params.freqs = wpa_s->manual_sched_scan_freqs; + } + + if (wpa_s->mac_addr_rand_enable & MAC_ADDR_RAND_PNO) { + params.mac_addr_rand = 1; + if (wpa_s->mac_addr_pno) { + params.mac_addr = wpa_s->mac_addr_pno; + params.mac_addr_mask = wpa_s->mac_addr_pno + ETH_ALEN; + } + } + + ret = wpa_supplicant_start_sched_scan(wpa_s, ¶ms, interval); + os_free(params.filter_ssids); + if (ret == 0) + wpa_s->pno = 1; + else + wpa_msg(wpa_s, MSG_ERROR, "Failed to schedule PNO"); + return ret; +} + + +int wpas_stop_pno(struct wpa_supplicant *wpa_s) +{ + int ret = 0; + + if (!wpa_s->pno) + return 0; + + ret = wpa_supplicant_stop_sched_scan(wpa_s); + + wpa_s->pno = 0; + wpa_s->pno_sched_pending = 0; + + if (wpa_s->wpa_state == WPA_SCANNING) + wpa_supplicant_req_scan(wpa_s, 0, 0); + + return ret; +} + + +void wpas_mac_addr_rand_scan_clear(struct wpa_supplicant *wpa_s, + unsigned int type) +{ + type &= MAC_ADDR_RAND_ALL; + wpa_s->mac_addr_rand_enable &= ~type; + + if (type & MAC_ADDR_RAND_SCAN) { + os_free(wpa_s->mac_addr_scan); + wpa_s->mac_addr_scan = NULL; + } + + if (type & MAC_ADDR_RAND_SCHED_SCAN) { + os_free(wpa_s->mac_addr_sched_scan); + wpa_s->mac_addr_sched_scan = NULL; + } + + if (type & MAC_ADDR_RAND_PNO) { + os_free(wpa_s->mac_addr_pno); + wpa_s->mac_addr_pno = NULL; + } +} + + +int wpas_mac_addr_rand_scan_set(struct wpa_supplicant *wpa_s, + unsigned int type, const u8 *addr, + const u8 *mask) +{ + u8 *tmp = NULL; + + wpas_mac_addr_rand_scan_clear(wpa_s, type); + + if (addr) { + tmp = os_malloc(2 * ETH_ALEN); + if (!tmp) + return -1; + os_memcpy(tmp, addr, ETH_ALEN); + os_memcpy(tmp + ETH_ALEN, mask, ETH_ALEN); + } + + if (type == MAC_ADDR_RAND_SCAN) { + wpa_s->mac_addr_scan = tmp; + } else if (type == MAC_ADDR_RAND_SCHED_SCAN) { + wpa_s->mac_addr_sched_scan = tmp; + } else if (type == MAC_ADDR_RAND_PNO) { + wpa_s->mac_addr_pno = tmp; + } else { + wpa_printf(MSG_INFO, + "scan: Invalid MAC randomization type=0x%x", + type); + os_free(tmp); + return -1; + } + + wpa_s->mac_addr_rand_enable |= type; + return 0; +} diff --git a/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/wpa_supplicant.c b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/wpa_supplicant.c new file mode 100755 index 0000000..11418c3 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/wpa_supplicant.c @@ -0,0 +1,5255 @@ +/* + * WPA Supplicant + * Copyright (c) 2003-2015, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + * + * This file implements functions for registering and unregistering + * %wpa_supplicant interfaces. In addition, this file contains number of + * functions for managing network connections. + */ + +#include "includes.h" + +#include "common.h" +#include "crypto/random.h" +#include "crypto/sha1.h" +#include "eapol_supp/eapol_supp_sm.h" +#include "rsn_supp/wpa.h" +#include "eloop.h" +#include "config.h" +#include "l2_packet/l2_packet.h" +#include "wpa_supplicant_i.h" +#include "driver_i.h" +#include "ctrl_iface.h" +#include "common/version.h" +#include "rsn_supp/preauth.h" +#include "rsn_supp/pmksa_cache.h" +#include "common/wpa_ctrl.h" +#include "common/ieee802_11_defs.h" +#include "common/hw_features_common.h" +#include "blacklist.h" +#include "wpas_glue.h" +#include "wps_supplicant.h" +#include "ibss_rsn.h" +#include "sme.h" +#include "gas_query.h" +#include "p2p_supplicant.h" +#include "wifi_display.h" +#include "notify.h" +#include "bgscan.h" +#include "autoscan.h" +#include "bss.h" +#include "scan.h" +#include "offchannel.h" +#include "hs20_supplicant.h" +#include "wnm_sta.h" +#include "wpas_kay.h" +#include "mesh.h" +#include "errno-base.h" +#include "str_pub.h" + +#include "include.h" +#include "uart_pub.h" +#include "role_launch.h" +#if RL_SUPPORT_FAST_CONNECT +#include "param_config.h" +#endif + +#if 1 //wangzhilei +int wpa_debug_level = MSG_INFO; +int wpa_debug_show_keys = 0; +int wpa_debug_timestamp = 0; +#endif + +extern struct wpa_ssid_value *wpas_connect_ssid; +extern void sta_ip_down(void); +extern void sta_ip_start(void); +extern uint32_t wpa_hostapd_queue_poll(uint32_t param); + +/* Configure default/group WEP keys for static WEP */ +int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) +{ + int i, set = 0; + + for (i = 0; i < NUM_WEP_KEYS; i++) { + if (ssid->wep_key_len[i] == 0) + continue; + + set = 1; + + wpa_drv_set_key(wpa_s, WPA_ALG_WEP, NULL, + i, i == ssid->wep_tx_keyidx, NULL, 0, + ssid->wep_key[i], ssid->wep_key_len[i]); + } + + return set; +} + +int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid) +{ + u8 key[32]; + size_t keylen; + enum wpa_alg alg; + u8 seq[6] = { 0 }; + int ret; + + /* IBSS/WPA-None uses only one key (Group) for both receiving and + * sending unicast and multicast packets. */ + + if (ssid->mode != WPAS_MODE_IBSS) { + wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid mode %d (not " + "IBSS/ad-hoc) for WPA-None", ssid->mode); + return -1; + } + + if (!ssid->psk_set) { + wpa_msg(wpa_s, MSG_INFO, "WPA: No PSK configured for " + "WPA-None"); + return -1; + } + + switch (wpa_s->group_cipher) { + case WPA_CIPHER_CCMP: + os_memcpy(key, ssid->psk, 16); + keylen = 16; + alg = WPA_ALG_CCMP; + break; + case WPA_CIPHER_GCMP: + os_memcpy(key, ssid->psk, 16); + keylen = 16; + alg = WPA_ALG_GCMP; + break; + case WPA_CIPHER_TKIP: + /* WPA-None uses the same Michael MIC key for both TX and RX */ + os_memcpy(key, ssid->psk, 16 + 8); + os_memcpy(key + 16 + 8, ssid->psk + 16, 8); + keylen = 32; + alg = WPA_ALG_TKIP; + break; + default: + wpa_msg(wpa_s, MSG_INFO, "WPA: Invalid group cipher %d for " + "WPA-None", wpa_s->group_cipher); + return -1; + } + + /* TODO: should actually remember the previously used seq#, both for TX + * and RX from each STA.. */ + ret = wpa_drv_set_key(wpa_s, alg, NULL, 0, 1, seq, 6, key, keylen); + os_memset(key, 0, sizeof(key)); + return ret; +} + + +static void wpa_supplicant_timeout(void *eloop_ctx, void *timeout_ctx) +{ + struct wpa_supplicant *wpa_s = eloop_ctx; + const u8 *bssid = wpa_s->bssid; + if (is_zero_ether_addr(bssid)) + bssid = wpa_s->pending_bssid; + wpa_msg(wpa_s, MSG_INFO, "Authentication with " MACSTR " timed out.", + MAC2STR(bssid)); + + wpa_blacklist_add(wpa_s, bssid); + wpa_sm_notify_disassoc(wpa_s->wpa); + wpa_supplicant_deauthenticate(wpa_s, WLAN_REASON_DEAUTH_LEAVING); + wpa_s->reassociate = 1; + + /* + * If we timed out, the AP or the local radio may be busy. + * So, wait a second until scanning again. + */ + wpa_supplicant_req_scan(wpa_s, 1, 0); +} + + +/** + * wpa_supplicant_req_auth_timeout - Schedule a timeout for authentication + * @wpa_s: Pointer to wpa_supplicant data + * @sec: Number of seconds after which to time out authentication + * @usec: Number of microseconds after which to time out authentication + * + * This function is used to schedule a timeout for the current authentication + * attempt. + */ +void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s, + int sec, int usec) +{ + if (wpa_s->conf->ap_scan == 0 && + (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED)) + return; + + wpa_dbg(wpa_s, MSG_DEBUG, "Setting authentication timeout: %d sec " + "%d usec", sec, usec); + eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL); + eloop_register_timeout(sec, usec, wpa_supplicant_timeout, wpa_s, NULL); +} + + +/** + * wpa_supplicant_cancel_auth_timeout - Cancel authentication timeout + * @wpa_s: Pointer to wpa_supplicant data + * + * This function is used to cancel authentication timeout scheduled with + * wpa_supplicant_req_auth_timeout() and it is called when authentication has + * been completed. + */ +void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s) +{ + wpa_dbg(wpa_s, MSG_DEBUG, "Cancelling authentication timeout"); + eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL); + + wpa_blacklist_del(wpa_s, wpa_s->bssid); +} + + +/** + * wpa_supplicant_initiate_eapol - Configure EAPOL state machine + * @wpa_s: Pointer to wpa_supplicant data + * + * This function is used to configure EAPOL state machine based on the selected + * authentication mode. + */ +void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s) +{ +#ifdef IEEE8021X_EAPOL + struct eapol_config eapol_conf; + struct wpa_ssid *ssid = wpa_s->current_ssid; + +#ifdef CONFIG_IBSS_RSN + if (ssid->mode == WPAS_MODE_IBSS && + wpa_s->key_mgmt != WPA_KEY_MGMT_NONE && + wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) { + /* + * RSN IBSS authentication is per-STA and we can disable the + * per-BSSID EAPOL authentication. + */ + eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized); + eapol_sm_notify_eap_success(wpa_s->eapol, TRUE); + eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE); + return; + } +#endif /* CONFIG_IBSS_RSN */ + + eapol_sm_notify_eap_success(wpa_s->eapol, FALSE); + eapol_sm_notify_eap_fail(wpa_s->eapol, FALSE); + + if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE || + wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) + eapol_sm_notify_portControl(wpa_s->eapol, ForceAuthorized); + else + eapol_sm_notify_portControl(wpa_s->eapol, Auto); + + os_memset(&eapol_conf, 0, sizeof(eapol_conf)); + if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) { + eapol_conf.accept_802_1x_keys = 1; + eapol_conf.required_keys = 0; + if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_UNICAST) { + eapol_conf.required_keys |= EAPOL_REQUIRE_KEY_UNICAST; + } + if (ssid->eapol_flags & EAPOL_FLAG_REQUIRE_KEY_BROADCAST) { + eapol_conf.required_keys |= + EAPOL_REQUIRE_KEY_BROADCAST; + } + + if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED) + eapol_conf.required_keys = 0; + } + eapol_conf.fast_reauth = wpa_s->conf->fast_reauth; + eapol_conf.workaround = ssid->eap_workaround; + eapol_conf.eap_disabled = + !wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) && + wpa_s->key_mgmt != WPA_KEY_MGMT_IEEE8021X_NO_WPA && + wpa_s->key_mgmt != WPA_KEY_MGMT_WPS; + eapol_conf.external_sim = wpa_s->conf->external_sim; + +#ifdef CONFIG_WPS + if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) { + eapol_conf.wps |= EAPOL_LOCAL_WPS_IN_USE; + if (wpa_s->current_bss) { + struct wpabuf *ie; + ie = wpa_bss_get_vendor_ie_multi(wpa_s->current_bss, + WPS_IE_VENDOR_TYPE); + if (ie) { + if (wps_is_20(ie)) + eapol_conf.wps |= + EAPOL_PEER_IS_WPS20_AP; + wpabuf_free(ie); + } + } + } +#endif /* CONFIG_WPS */ + + eapol_sm_notify_config(wpa_s->eapol, &ssid->eap, &eapol_conf); + + ieee802_1x_alloc_kay_sm(wpa_s, ssid); +#endif /* IEEE8021X_EAPOL */ +} + + +/** + * wpa_supplicant_set_non_wpa_policy - Set WPA parameters to non-WPA mode + * @wpa_s: Pointer to wpa_supplicant data + * @ssid: Configuration data for the network + * + * This function is used to configure WPA state machine and related parameters + * to a mode where WPA is not enabled. This is called as part of the + * authentication configuration when the selected network does not use WPA. + */ +void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid) +{ + int i; + + if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) + wpa_s->key_mgmt = WPA_KEY_MGMT_WPS; + else if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) + wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA; + else + wpa_s->key_mgmt = WPA_KEY_MGMT_NONE; + wpa_sm_set_ap_wpa_ie(wpa_s->wpa, NULL, 0); + wpa_sm_set_ap_rsn_ie(wpa_s->wpa, NULL, 0); + wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0); + wpa_s->pairwise_cipher = WPA_CIPHER_NONE; + wpa_s->group_cipher = WPA_CIPHER_NONE; + wpa_s->mgmt_group_cipher = 0; + + for (i = 0; i < NUM_WEP_KEYS; i++) { + if (ssid->wep_key_len[i] > 5) { + wpa_s->pairwise_cipher = WPA_CIPHER_WEP104; + wpa_s->group_cipher = WPA_CIPHER_WEP104; + break; + } else if (ssid->wep_key_len[i] > 0) { + wpa_s->pairwise_cipher = WPA_CIPHER_WEP40; + wpa_s->group_cipher = WPA_CIPHER_WEP40; + break; + } + } + + wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED, 0); + wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt); + wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE, + wpa_s->pairwise_cipher); + wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher); +#ifdef CONFIG_IEEE80211W + wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP, + wpa_s->mgmt_group_cipher); +#endif /* CONFIG_IEEE80211W */ + + pmksa_cache_clear_current(wpa_s->wpa); +} + + +void free_hw_features(struct wpa_supplicant *wpa_s) +{ + int i; + if (wpa_s->hw.modes == NULL) + return; + + for (i = 0; i < wpa_s->hw.num_modes; i++) { + os_free(wpa_s->hw.modes[i].channels); + os_free(wpa_s->hw.modes[i].rates); + } + + os_free(wpa_s->hw.modes); + wpa_s->hw.modes = NULL; +} + + +static void wpa_supplicant_cleanup(struct wpa_supplicant *wpa_s) +{ + int i; + + bgscan_deinit(wpa_s); + autoscan_deinit(wpa_s); + l2_packet_deinit(wpa_s->l2); + wpa_s->l2 = NULL; +#ifdef CONFIG_FULL_SUPPLICANT + if (wpa_s->l2_br) { + l2_packet_deinit(wpa_s->l2_br); + wpa_s->l2_br = NULL; + } +#endif + if (wpa_s->conf != NULL) { + struct wpa_ssid *ssid; + for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) + wpas_notify_network_removed(wpa_s, ssid); + } + + os_free(wpa_s->confname); + wpa_s->confname = NULL; + + os_free(wpa_s->confanother); + wpa_s->confanother = NULL; + + wpa_sm_set_eapol(wpa_s->wpa, NULL); + eapol_sm_deinit(wpa_s->eapol); + wpa_s->eapol = NULL; + + rsn_preauth_deinit(wpa_s->wpa); + +#ifdef CONFIG_TDLS + wpa_tdls_deinit(wpa_s->wpa); +#endif /* CONFIG_TDLS */ + + wmm_ac_clear_saved_tspecs(wpa_s); + pmksa_candidate_free(wpa_s->wpa); + wpa_sm_deinit(wpa_s->wpa); + wpa_s->wpa = NULL; + wpa_blacklist_clear(wpa_s); + + wpa_bss_deinit(wpa_s); + + wpa_supplicant_cancel_delayed_sched_scan(wpa_s); + wpa_supplicant_cancel_scan(wpa_s); + wpa_supplicant_cancel_auth_timeout(wpa_s); + eloop_cancel_timeout(wpa_supplicant_stop_countermeasures, wpa_s, NULL); +#ifdef CONFIG_DELAYED_MIC_ERROR_REPORT + eloop_cancel_timeout(wpa_supplicant_delayed_mic_error_report, + wpa_s, NULL); +#endif /* CONFIG_DELAYED_MIC_ERROR_REPORT */ + + eloop_cancel_timeout(wpas_network_reenabled, wpa_s, NULL); + + wpas_wps_deinit(wpa_s); + + wpabuf_free(wpa_s->pending_eapol_rx); + wpa_s->pending_eapol_rx = NULL; + +#ifdef CONFIG_IBSS_RSN + ibss_rsn_deinit(wpa_s->ibss_rsn); + wpa_s->ibss_rsn = NULL; +#endif /* CONFIG_IBSS_RSN */ + + sme_deinit(wpa_s); + +#ifdef CONFIG_AP + wpa_supplicant_ap_deinit(wpa_s); +#endif /* CONFIG_AP */ + + wpas_p2p_deinit(wpa_s); + + wpa_supplicant_cancel_sched_scan(wpa_s); + + os_free(wpa_s->next_scan_freqs); + wpa_s->next_scan_freqs = NULL; + + os_free(wpa_s->manual_scan_freqs); + wpa_s->manual_scan_freqs = NULL; + + os_free(wpa_s->manual_sched_scan_freqs); + wpa_s->manual_sched_scan_freqs = NULL; + + wpas_mac_addr_rand_scan_clear(wpa_s, MAC_ADDR_RAND_ALL); + + free_hw_features(wpa_s); + + ieee802_1x_dealloc_kay_sm(wpa_s); + + os_free(wpa_s->bssid_filter); + wpa_s->bssid_filter = NULL; + + os_free(wpa_s->disallow_aps_bssid); + wpa_s->disallow_aps_bssid = NULL; + os_free(wpa_s->disallow_aps_ssid); + wpa_s->disallow_aps_ssid = NULL; + + wnm_bss_keep_alive_deinit(wpa_s); +#ifdef CONFIG_WNM + wnm_deallocate_memory(wpa_s); +#endif /* CONFIG_WNM */ + + os_free(wpa_s->last_scan_res); + wpa_s->last_scan_res = NULL; + +#ifdef CONFIG_HS20 + hs20_deinit(wpa_s); +#endif /* CONFIG_HS20 */ + + for (i = 0; i < NUM_VENDOR_ELEM_FRAMES; i++) { + wpabuf_free(wpa_s->vendor_elem[i]); + wpa_s->vendor_elem[i] = NULL; + } + + wmm_ac_notify_disassoc(wpa_s); +} + + +/** + * wpa_clear_keys - Clear keys configured for the driver + * @wpa_s: Pointer to wpa_supplicant data + * @addr: Previously used BSSID or %NULL if not available + * + * This function clears the encryption keys that has been previously configured + * for the driver. + */ +void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr) +{ + int i, max; + +#ifdef CONFIG_IEEE80211W + max = 6; +#else /* CONFIG_IEEE80211W */ + max = 4; +#endif /* CONFIG_IEEE80211W */ + + /* MLME-DELETEKEYS.request */ + for (i = 0; i < max; i++) { + if (wpa_s->keys_cleared & BIT(i)) + continue; + + wpa_drv_set_key(wpa_s, WPA_ALG_NONE, NULL, i, 0, NULL, 0, + NULL, 0); + } + if (!(wpa_s->keys_cleared & BIT(0)) && addr && + !is_zero_ether_addr(addr)) { + wpa_drv_set_key(wpa_s, WPA_ALG_NONE, addr, 0, 0, NULL, 0, NULL, + 0); + /* MLME-SETPROTECTION.request(None) */ + wpa_drv_mlme_setprotection( + wpa_s, addr, + MLME_SETPROTECTION_PROTECT_TYPE_NONE, + MLME_SETPROTECTION_KEY_TYPE_PAIRWISE); + } + wpa_s->keys_cleared = (u32) -1; +} + + +/** + * wpa_supplicant_state_txt - Get the connection state name as a text string + * @state: State (wpa_state; WPA_*) + * Returns: The state name as a printable text string + */ +const char * wpa_supplicant_state_txt(enum wpa_states state) +{ + switch (state) { + case WPA_DISCONNECTED: + return "DISCONNECTED"; + case WPA_INACTIVE: + return "INACTIVE"; + case WPA_INTERFACE_DISABLED: + return "INTERFACE_DISABLED"; + case WPA_SCANNING: + return "SCANNING"; + case WPA_AUTHENTICATING: + return "AUTHENTICATING"; + case WPA_ASSOCIATING: + return "ASSOCIATING"; + case WPA_ASSOCIATED: + return "ASSOCIATED"; + case WPA_4WAY_HANDSHAKE: + return "4WAY_HANDSHAKE"; + case WPA_GROUP_HANDSHAKE: + return "GROUP_HANDSHAKE"; + case WPA_COMPLETED: + return "COMPLETED"; + default: + return "UNKNOWN"; + } +} + + +#ifdef CONFIG_BGSCAN + +static void wpa_supplicant_start_bgscan(struct wpa_supplicant *wpa_s) +{ + const char *name; + + if (wpa_s->current_ssid && wpa_s->current_ssid->bgscan) + name = wpa_s->current_ssid->bgscan; + else + name = wpa_s->conf->bgscan; + if (name == NULL || name[0] == '\0') + return; + if (wpas_driver_bss_selection(wpa_s)) + return; + if (wpa_s->current_ssid == wpa_s->bgscan_ssid) + return; +#ifdef CONFIG_P2P + if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE) + return; +#endif /* CONFIG_P2P */ + + bgscan_deinit(wpa_s); + if (wpa_s->current_ssid) { + if (bgscan_init(wpa_s, wpa_s->current_ssid, name)) { + wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize " + "bgscan"); + /* + * Live without bgscan; it is only used as a roaming + * optimization, so the initial connection is not + * affected. + */ + } else { + struct wpa_scan_results *scan_res; + wpa_s->bgscan_ssid = wpa_s->current_ssid; + scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, + 0); + if (scan_res) { + bgscan_notify_scan(wpa_s, scan_res); + wpa_scan_results_free(scan_res); + } + } + } else + wpa_s->bgscan_ssid = NULL; +} + + +static void wpa_supplicant_stop_bgscan(struct wpa_supplicant *wpa_s) +{ + if (wpa_s->bgscan_ssid != NULL) { + bgscan_deinit(wpa_s); + wpa_s->bgscan_ssid = NULL; + } +} + +#endif /* CONFIG_BGSCAN */ + + +static void wpa_supplicant_start_autoscan(struct wpa_supplicant *wpa_s) +{ + if (autoscan_init(wpa_s, 0)) + wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize autoscan"); +} + + +static void wpa_supplicant_stop_autoscan(struct wpa_supplicant *wpa_s) +{ + autoscan_deinit(wpa_s); +} + + +void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s) +{ + if (wpa_s->wpa_state == WPA_DISCONNECTED || + wpa_s->wpa_state == WPA_SCANNING) { + autoscan_deinit(wpa_s); + wpa_supplicant_start_autoscan(wpa_s); + } +} + + +/** + * wpa_supplicant_set_state - Set current connection state + * @wpa_s: Pointer to wpa_supplicant data + * @state: The new connection state + * + * This function is called whenever the connection state changes, e.g., + * association is completed for WPA/WPA2 4-Way Handshake is started. + */ +void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s, + enum wpa_states state) +{ + enum wpa_states old_state = wpa_s->wpa_state; + + wpa_dbg(wpa_s, MSG_DEBUG, "State: %s -> %s", + wpa_supplicant_state_txt(wpa_s->wpa_state), + wpa_supplicant_state_txt(state)); + + if (state == WPA_INTERFACE_DISABLED) { + /* Assure normal scan when interface is restored */ + wpa_s->normal_scans = 0; + } + + if (state == WPA_COMPLETED) { + wpas_connect_work_done(wpa_s); + /* Reinitialize normal_scan counter */ + wpa_s->normal_scans = 0; + wpa_drv_sta_set_flags(wpa_s, wpa_s->bssid, ~0, WPA_STA_AUTHORIZED, ~0); + + sta_ip_start(); + } + if(state == WPA_DISCONNECTED && state != wpa_s->wpa_state){ + wpa_config_set_network_defaults(wpa_s->conf->ssid); + #if 1 + for(int i=0;iconf->ssid->wep_key_len[i] = 0; + //memset(wpa_s->conf->ssid->wep_key,0,NUM_WEP_KEYS); + #endif + + wpa_s->conf->ssid->mem_only_psk = 1; // set psk, to enable rescan. + sta_ip_down(); + } + +#ifdef CONFIG_P2P + /* + * P2PS client has to reply to Probe Request frames received on the + * group operating channel. Enable Probe Request frame reporting for + * P2P connected client in case p2p_cli_probe configuration property is + * set to 1. + */ + if (wpa_s->conf->p2p_cli_probe && wpa_s->current_ssid && + wpa_s->current_ssid->mode == WPAS_MODE_INFRA && + wpa_s->current_ssid->p2p_group) { + if (state == WPA_COMPLETED && !wpa_s->p2p_cli_probe) { + wpa_dbg(wpa_s, MSG_DEBUG, + "P2P: Enable CLI Probe Request RX reporting"); + wpa_s->p2p_cli_probe = + wpa_drv_probe_req_report(wpa_s, 1) >= 0; + } else if (state != WPA_COMPLETED && wpa_s->p2p_cli_probe) { + wpa_dbg(wpa_s, MSG_DEBUG, + "P2P: Disable CLI Probe Request RX reporting"); + wpa_s->p2p_cli_probe = 0; + wpa_drv_probe_req_report(wpa_s, 0); + } + } +#endif /* CONFIG_P2P */ + + if (state != WPA_SCANNING) + wpa_supplicant_notify_scanning(wpa_s, 0); + + if (state == WPA_COMPLETED && wpa_s->new_connection) { + struct wpa_ssid *ssid = wpa_s->current_ssid; +#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG) + wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_CONNECTED "- Connection to " + MACSTR " completed [id=%d id_str=%s]", + MAC2STR(wpa_s->bssid), + ssid ? ssid->id : -1, + ssid && ssid->id_str ? ssid->id_str : ""); +#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */ + wpas_clear_temp_disabled(wpa_s, ssid, 1); + + wpa_blacklist_clear(wpa_s); + + wpa_s->extra_blacklist_count = 0; + wpa_s->new_connection = 0; + wpa_drv_set_operstate(wpa_s, 1); +#ifndef IEEE8021X_EAPOL + wpa_drv_set_supp_port(wpa_s, 1); +#endif /* IEEE8021X_EAPOL */ + wpa_s->after_wps = 0; + wpa_s->known_wps_freq = 0; + wpas_p2p_completed(wpa_s); + + sme_sched_obss_scan(wpa_s, 1); + } else if (state == WPA_DISCONNECTED || state == WPA_ASSOCIATING || + state == WPA_ASSOCIATED) { + wpa_s->new_connection = 1; + wpa_drv_set_operstate(wpa_s, 0); +#ifndef IEEE8021X_EAPOL + wpa_drv_set_supp_port(wpa_s, 0); +#endif /* IEEE8021X_EAPOL */ + sme_sched_obss_scan(wpa_s, 0); + } + wpa_s->wpa_state = state; + +#ifdef CONFIG_BGSCAN + if (state == WPA_COMPLETED) + wpa_supplicant_start_bgscan(wpa_s); + else if (state < WPA_ASSOCIATED) + wpa_supplicant_stop_bgscan(wpa_s); +#endif /* CONFIG_BGSCAN */ + + if (state == WPA_AUTHENTICATING) + wpa_supplicant_stop_autoscan(wpa_s); + + if (state == WPA_DISCONNECTED || state == WPA_INACTIVE) + wpa_supplicant_start_autoscan(wpa_s); + + if (old_state >= WPA_ASSOCIATED && wpa_s->wpa_state < WPA_ASSOCIATED) + wmm_ac_notify_disassoc(wpa_s); + + if (wpa_s->wpa_state != old_state) { + wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state); + + /* + * Notify the P2P Device interface about a state change in one + * of the interfaces. + */ + wpas_p2p_indicate_state_change(wpa_s); + + if (wpa_s->wpa_state == WPA_COMPLETED || + old_state == WPA_COMPLETED) + wpas_notify_auth_changed(wpa_s); + } +} + +#ifdef CONFIG_FULL_SUPPLICANT +void wpa_supplicant_terminate_proc(struct wpa_global *global) +{ + int pending = 0; +#ifdef CONFIG_WPS + struct wpa_supplicant *wpa_s = global->ifaces; + while (wpa_s) { + struct wpa_supplicant *next = wpa_s->next; + if (wpas_wps_terminate_pending(wpa_s) == 1) + pending = 1; +#ifdef CONFIG_P2P + if (wpa_s->p2p_group_interface != NOT_P2P_GROUP_INTERFACE || + (wpa_s->current_ssid && wpa_s->current_ssid->p2p_group)) + wpas_p2p_disconnect(wpa_s); +#endif /* CONFIG_P2P */ + wpa_s = next; + } +#endif /* CONFIG_WPS */ + if (pending) + return; + eloop_terminate(); +} + + +static void wpa_supplicant_terminate(int sig, void *signal_ctx) +{ + struct wpa_global *global = signal_ctx; + wpa_supplicant_terminate_proc(global); +} + + +void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s) +{ + enum wpa_states old_state = wpa_s->wpa_state; + + wpa_s->pairwise_cipher = 0; + wpa_s->group_cipher = 0; + wpa_s->mgmt_group_cipher = 0; + wpa_s->key_mgmt = 0; + if (wpa_s->wpa_state != WPA_INTERFACE_DISABLED) + wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); + + if (wpa_s->wpa_state != old_state) + wpas_notify_state_changed(wpa_s, wpa_s->wpa_state, old_state); +} + + +/** + * wpa_supplicant_reload_configuration - Reload configuration data + * @wpa_s: Pointer to wpa_supplicant data + * Returns: 0 on success or -1 if configuration parsing failed + * + * This function can be used to request that the configuration data is reloaded + * (e.g., after configuration file change). This function is reloading + * configuration only for one interface, so this may need to be called multiple + * times if %wpa_supplicant is controlling multiple interfaces and all + * interfaces need reconfiguration. + */ +int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s) +{ + struct wpa_config *conf; + int reconf_ctrl; + int old_ap_scan; + + if (wpa_s->confname == NULL) + return -1; + conf = wpa_config_read(wpa_s->confname, NULL); + if (conf == NULL) { + wpa_msg(wpa_s, MSG_ERROR, "Failed to parse the configuration " + "file '%s' - exiting", wpa_s->confname); + return -1; + } + wpa_config_read(wpa_s->confanother, conf); + + conf->changed_parameters = (unsigned int) -1; + + reconf_ctrl = !!conf->ctrl_interface != !!wpa_s->conf->ctrl_interface + || (conf->ctrl_interface && wpa_s->conf->ctrl_interface && + os_strcmp(conf->ctrl_interface, + wpa_s->conf->ctrl_interface) != 0); + + if (reconf_ctrl && wpa_s->ctrl_iface) { + wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface); + wpa_s->ctrl_iface = NULL; + } + + eapol_sm_invalidate_cached_session(wpa_s->eapol); + if (wpa_s->current_ssid) { + if (wpa_s->wpa_state >= WPA_AUTHENTICATING) + wpa_s->own_disconnect_req = 1; + wpa_supplicant_deauthenticate(wpa_s, + WLAN_REASON_DEAUTH_LEAVING); + } + + /* + * TODO: should notify EAPOL SM about changes in opensc_engine_path, + * pkcs11_engine_path, pkcs11_module_path, openssl_ciphers. + */ + if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt)) { + /* + * Clear forced success to clear EAP state for next + * authentication. + */ + eapol_sm_notify_eap_success(wpa_s->eapol, FALSE); + } + eapol_sm_notify_config(wpa_s->eapol, NULL, NULL); + wpa_sm_set_config(wpa_s->wpa, NULL); + wpa_sm_pmksa_cache_flush(wpa_s->wpa, NULL); + wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth); + rsn_preauth_deinit(wpa_s->wpa); + + old_ap_scan = wpa_s->conf->ap_scan; + wpa_config_free(wpa_s->conf); + wpa_s->conf = conf; + if (old_ap_scan != wpa_s->conf->ap_scan) + wpas_notify_ap_scan_changed(wpa_s); + + if (reconf_ctrl) + wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s); + + wpa_supplicant_update_config(wpa_s); + + wpa_supplicant_clear_status(wpa_s); + if (wpa_supplicant_enabled_networks(wpa_s)) { + wpa_s->reassociate = 1; + wpa_supplicant_req_scan(wpa_s, 0, 0); + } + wpa_dbg(wpa_s, MSG_DEBUG, "Reconfiguration completed"); + return 0; +} + + +static void wpa_supplicant_reconfig(int sig, void *signal_ctx) +{ + struct wpa_global *global = signal_ctx; + struct wpa_supplicant *wpa_s; + for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) { + wpa_dbg(wpa_s, MSG_DEBUG, "Signal %d received - reconfiguring", + sig); + if (wpa_supplicant_reload_configuration(wpa_s) < 0) { + wpa_supplicant_terminate_proc(global); + } + } +} +#endif + +static int wpa_supplicant_suites_from_ai(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid, + struct wpa_ie_data *ie) +{ + int ret = wpa_sm_parse_own_wpa_ie(wpa_s->wpa, ie); + if (ret) { + if (ret == -2) { + wpa_msg(wpa_s, MSG_INFO, "WPA: Failed to parse WPA IE " + "from association info"); + } + return -1; + } + + wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Using WPA IE from AssocReq to set " + "cipher suites"); + if (!(ie->group_cipher & ssid->group_cipher)) { + wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled group " + "cipher 0x%x (mask 0x%x) - reject", + ie->group_cipher, ssid->group_cipher); + return -1; + } + if (!(ie->pairwise_cipher & ssid->pairwise_cipher)) { + wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled pairwise " + "cipher 0x%x (mask 0x%x) - reject", + ie->pairwise_cipher, ssid->pairwise_cipher); + return -1; + } + if (!(ie->key_mgmt & ssid->key_mgmt)) { + wpa_msg(wpa_s, MSG_INFO, "WPA: Driver used disabled key " + "management 0x%x (mask 0x%x) - reject", + ie->key_mgmt, ssid->key_mgmt); + return -1; + } + +#ifdef CONFIG_IEEE80211W + if (!(ie->capabilities & WPA_CAPABILITY_MFPC) && + wpas_get_ssid_pmf(wpa_s, ssid) == MGMT_FRAME_PROTECTION_REQUIRED) { + wpa_msg(wpa_s, MSG_INFO, "WPA: Driver associated with an AP " + "that does not support management frame protection - " + "reject"); + return -1; + } +#endif /* CONFIG_IEEE80211W */ + + return 0; +} + + +/** + * wpa_supplicant_set_suites - Set authentication and encryption parameters + * @wpa_s: Pointer to wpa_supplicant data + * @bss: Scan results for the selected BSS, or %NULL if not available + * @ssid: Configuration data for the selected network + * @wpa_ie: Buffer for the WPA/RSN IE + * @wpa_ie_len: Maximum wpa_ie buffer size on input. This is changed to be the + * used buffer length in case the functions returns success. + * Returns: 0 on success or -1 on failure + * + * This function is used to configure authentication and encryption parameters + * based on the network configuration and scan result for the selected BSS (if + * available). + */ +int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, + struct wpa_bss *bss, struct wpa_ssid *ssid, + u8 *wpa_ie, size_t *wpa_ie_len) +{ + struct wpa_ie_data ie; + int sel, proto; + const u8 *bss_wpa, *bss_rsn; + + if (bss) { + bss_wpa = wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE); + bss_rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN); + } else + bss_wpa = bss_rsn = NULL; + + if (bss_rsn && (ssid->proto & WPA_PROTO_RSN) && + wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie) == 0 && + (ie.group_cipher & ssid->group_cipher) && + (ie.pairwise_cipher & ssid->pairwise_cipher) && + (ie.key_mgmt & ssid->key_mgmt)) { + wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using IEEE 802.11i/D9.0"); + proto = WPA_PROTO_RSN; + } else if (bss_wpa && (ssid->proto & WPA_PROTO_WPA) && + wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie) == 0 && + (ie.group_cipher & ssid->group_cipher) && + (ie.pairwise_cipher & ssid->pairwise_cipher) && + (ie.key_mgmt & ssid->key_mgmt)) { + wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using IEEE 802.11i/D3.0"); + proto = WPA_PROTO_WPA; + } else if (bss) { + wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select WPA/RSN"); + wpa_dbg(wpa_s, MSG_DEBUG, + "WPA: ssid proto=0x%x pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x", + ssid->proto, ssid->pairwise_cipher, ssid->group_cipher, + ssid->key_mgmt); + wpa_dbg(wpa_s, MSG_DEBUG, "WPA: BSS " MACSTR " ssid='%s'%s%s", + MAC2STR(bss->bssid), + wpa_ssid_txt(bss->ssid, bss->ssid_len), + bss_wpa ? " WPA" : "", + bss_rsn ? " RSN" : ""); + if (bss_rsn) { + wpa_hexdump(MSG_DEBUG, "RSN", bss_rsn, 2 + bss_rsn[1]); + if (wpa_parse_wpa_ie(bss_rsn, 2 + bss_rsn[1], &ie)) { + wpa_dbg(wpa_s, MSG_DEBUG, + "Could not parse RSN element"); + } else { + wpa_dbg(wpa_s, MSG_DEBUG, + "RSN: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x", + ie.pairwise_cipher, ie.group_cipher, + ie.key_mgmt); + } + } + if (bss_wpa) { + wpa_hexdump(MSG_DEBUG, "WPA", bss_wpa, 2 + bss_wpa[1]); + if (wpa_parse_wpa_ie(bss_wpa, 2 + bss_wpa[1], &ie)) { + wpa_dbg(wpa_s, MSG_DEBUG, + "Could not parse WPA element"); + } else { + wpa_dbg(wpa_s, MSG_DEBUG, + "WPA: pairwise_cipher=0x%x group_cipher=0x%x key_mgmt=0x%x", + ie.pairwise_cipher, ie.group_cipher, + ie.key_mgmt); + } + } + return -1; + } else { + if (ssid->proto & WPA_PROTO_OSEN) + proto = WPA_PROTO_OSEN; + else if (ssid->proto & WPA_PROTO_RSN) + proto = WPA_PROTO_RSN; + else + proto = WPA_PROTO_WPA; + if (wpa_supplicant_suites_from_ai(wpa_s, ssid, &ie) < 0) { + os_memset(&ie, 0, sizeof(ie)); + ie.group_cipher = ssid->group_cipher; + ie.pairwise_cipher = ssid->pairwise_cipher; + ie.key_mgmt = ssid->key_mgmt; +#ifdef CONFIG_IEEE80211W + ie.mgmt_group_cipher = + ssid->ieee80211w != NO_MGMT_FRAME_PROTECTION ? + WPA_CIPHER_AES_128_CMAC : 0; +#endif /* CONFIG_IEEE80211W */ + wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Set cipher suites " + "based on configuration"); + } else + proto = ie.proto; + } + + wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected cipher suites: group %d " + "pairwise %d key_mgmt %d proto %d", + ie.group_cipher, ie.pairwise_cipher, ie.key_mgmt, proto); +#ifdef CONFIG_IEEE80211W + if (ssid->ieee80211w) { + wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected mgmt group cipher %d", + ie.mgmt_group_cipher); + } +#endif /* CONFIG_IEEE80211W */ + + wpa_s->wpa_proto = proto; + wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PROTO, proto); + wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_RSN_ENABLED, + !!(ssid->proto & (WPA_PROTO_RSN | WPA_PROTO_OSEN))); + + if (bss || !wpa_s->ap_ies_from_associnfo) { + if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, bss_wpa, + bss_wpa ? 2 + bss_wpa[1] : 0) || + wpa_sm_set_ap_rsn_ie(wpa_s->wpa, bss_rsn, + bss_rsn ? 2 + bss_rsn[1] : 0)) + return -1; + } + + sel = ie.group_cipher & ssid->group_cipher; + wpa_s->group_cipher = wpa_pick_group_cipher(sel); + if (wpa_s->group_cipher < 0) { + wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select group " + "cipher"); + return -1; + } + wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using GTK %s", + wpa_cipher_txt(wpa_s->group_cipher)); + + sel = ie.pairwise_cipher & ssid->pairwise_cipher; + wpa_s->pairwise_cipher = wpa_pick_pairwise_cipher(sel, 1); + if (wpa_s->pairwise_cipher < 0) { + wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select pairwise " + "cipher"); + return -1; + } + wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using PTK %s", + wpa_cipher_txt(wpa_s->pairwise_cipher)); + + sel = ie.key_mgmt & ssid->key_mgmt; +#ifdef CONFIG_SAE + if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_SAE)) + sel &= ~(WPA_KEY_MGMT_SAE | WPA_KEY_MGMT_FT_SAE); +#endif /* CONFIG_SAE */ + if (0) { +#ifdef CONFIG_SAE + } else if (sel & WPA_KEY_MGMT_SAE) { + wpa_s->key_mgmt = WPA_KEY_MGMT_SAE; + wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT SAE"); + } else if (sel & WPA_KEY_MGMT_FT_SAE) { + wpa_s->key_mgmt = WPA_KEY_MGMT_FT_SAE; + wpa_dbg(wpa_s, MSG_DEBUG, "RSN: using KEY_MGMT FT/SAE"); +#endif /* CONFIG_SAE */ +#ifdef CONFIG_IEEE80211W + } else if (sel & WPA_KEY_MGMT_IEEE8021X_SHA256) { + wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256; + wpa_dbg(wpa_s, MSG_DEBUG, + "WPA: using KEY_MGMT 802.1X with SHA256"); + } else if (sel & WPA_KEY_MGMT_PSK_SHA256) { + wpa_s->key_mgmt = WPA_KEY_MGMT_PSK_SHA256; + wpa_dbg(wpa_s, MSG_DEBUG, + "WPA: using KEY_MGMT PSK with SHA256"); +#endif /* CONFIG_IEEE80211W */ + } else if (sel & WPA_KEY_MGMT_IEEE8021X) { + wpa_s->key_mgmt = WPA_KEY_MGMT_IEEE8021X; + wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT 802.1X"); + } else if (sel & WPA_KEY_MGMT_PSK) { + wpa_s->key_mgmt = WPA_KEY_MGMT_PSK; + wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-PSK"); + } else if (sel & WPA_KEY_MGMT_WPA_NONE) { + wpa_s->key_mgmt = WPA_KEY_MGMT_WPA_NONE; + wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using KEY_MGMT WPA-NONE"); + } else { + wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to select " + "authenticated key management type"); + return -1; + } + + wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_KEY_MGMT, wpa_s->key_mgmt); + wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_PAIRWISE, + wpa_s->pairwise_cipher); + wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_GROUP, wpa_s->group_cipher); + +#ifdef CONFIG_IEEE80211W + sel = ie.mgmt_group_cipher; + if (wpas_get_ssid_pmf(wpa_s, ssid) == NO_MGMT_FRAME_PROTECTION || + !(ie.capabilities & WPA_CAPABILITY_MFPC)) + sel = 0; + if (sel & WPA_CIPHER_AES_128_CMAC) { + wpa_s->mgmt_group_cipher = WPA_CIPHER_AES_128_CMAC; + wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher " + "AES-128-CMAC"); + } else if (sel & WPA_CIPHER_BIP_GMAC_128) { + wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_128; + wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher " + "BIP-GMAC-128"); + } else if (sel & WPA_CIPHER_BIP_GMAC_256) { + wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_GMAC_256; + wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher " + "BIP-GMAC-256"); + } else if (sel & WPA_CIPHER_BIP_CMAC_256) { + wpa_s->mgmt_group_cipher = WPA_CIPHER_BIP_CMAC_256; + wpa_dbg(wpa_s, MSG_DEBUG, "WPA: using MGMT group cipher " + "BIP-CMAC-256"); + } else { + wpa_s->mgmt_group_cipher = 0; + wpa_dbg(wpa_s, MSG_DEBUG, "WPA: not using MGMT group cipher"); + } + wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MGMT_GROUP, + wpa_s->mgmt_group_cipher); + wpa_sm_set_param(wpa_s->wpa, WPA_PARAM_MFP, + wpas_get_ssid_pmf(wpa_s, ssid)); +#endif /* CONFIG_IEEE80211W */ + + if (wpa_sm_set_assoc_wpa_ie_default(wpa_s->wpa, wpa_ie, wpa_ie_len)) { + wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to generate WPA IE"); + return -1; + } + + if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt)) { + int psk_set = 0; + + if (ssid->psk_set) { + wpa_sm_set_pmk(wpa_s->wpa, ssid->psk, PMK_LEN, NULL); + psk_set = 1; + } +#ifndef CONFIG_NO_PBKDF2 + if (bss && ssid->bssid_set && ssid->ssid_len == 0 && + ssid->passphrase) { + u8 psk[PMK_LEN]; + + pbkdf2_sha1(ssid->passphrase, bss->ssid, bss->ssid_len, + 4096, psk, PMK_LEN); + + wpa_hexdump_key(MSG_MSGDUMP, "PSK (from passphrase)", + psk, PMK_LEN); + wpa_sm_set_pmk(wpa_s->wpa, psk, PMK_LEN, NULL); + psk_set = 1; + os_memset(psk, 0, sizeof(psk)); + } +#endif /* CONFIG_NO_PBKDF2 */ + + if (!psk_set) { + wpa_msg(wpa_s, MSG_INFO, + "No PSK available for association"); + return -1; + } + } else + wpa_sm_set_pmk_from_pmksa(wpa_s->wpa); + + return 0; +} + + +static void wpas_ext_capab_byte(struct wpa_supplicant *wpa_s, u8 *pos, int idx) +{ + *pos = 0x00; + + switch (idx) { + case 0: /* Bits 0-7 */ + break; + case 1: /* Bits 8-15 */ + break; + case 2: /* Bits 16-23 */ +#ifdef CONFIG_WNM + *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */ + *pos |= 0x08; /* Bit 19 - BSS Transition */ +#endif /* CONFIG_WNM */ + break; + case 3: /* Bits 24-31 */ +#ifdef CONFIG_WNM + *pos |= 0x02; /* Bit 25 - SSID List */ +#endif /* CONFIG_WNM */ +#ifdef CONFIG_INTERWORKING + if (wpa_s->conf->interworking) + *pos |= 0x80; /* Bit 31 - Interworking */ +#endif /* CONFIG_INTERWORKING */ + break; + case 4: /* Bits 32-39 */ +#ifdef CONFIG_INTERWORKING + if (wpa_s->drv_flags / WPA_DRIVER_FLAGS_QOS_MAPPING) + *pos |= 0x01; /* Bit 32 - QoS Map */ +#endif /* CONFIG_INTERWORKING */ + break; + case 5: /* Bits 40-47 */ +#ifdef CONFIG_HS20 + if (wpa_s->conf->hs20) + *pos |= 0x40; /* Bit 46 - WNM-Notification */ +#endif /* CONFIG_HS20 */ + break; + case 6: /* Bits 48-55 */ + break; + } +} + + +int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen) +{ + u8 *pos = buf; + u8 len = 6, i; + + if (len < wpa_s->extended_capa_len) + len = wpa_s->extended_capa_len; + if (buflen < (size_t) len + 2) { + wpa_printf(MSG_INFO, + "Not enough room for building extended capabilities element"); + return -1; + } + + *pos++ = WLAN_EID_EXT_CAPAB; + *pos++ = len; + for (i = 0; i < len; i++, pos++) { + wpas_ext_capab_byte(wpa_s, pos, i); + + if (i < wpa_s->extended_capa_len) { + *pos &= ~wpa_s->extended_capa_mask[i]; + *pos |= wpa_s->extended_capa[i]; + } + } + + while (len > 0 && buf[1 + len] == 0) { + len--; + buf[1] = len; + } + if (len == 0) + return 0; + + return 2 + len; +} + + +static int wpas_valid_bss(struct wpa_supplicant *wpa_s, + struct wpa_bss *test_bss) +{ + struct wpa_bss *bss; + + dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { + if (bss == test_bss) + return 1; + } + + return 0; +} + + +static int wpas_valid_ssid(struct wpa_supplicant *wpa_s, + struct wpa_ssid *test_ssid) +{ + struct wpa_ssid *ssid; + + for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) { + if (ssid == test_ssid) + return 1; + } + + return 0; +} + + +int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss, + struct wpa_ssid *test_ssid) +{ + if (test_bss && !wpas_valid_bss(wpa_s, test_bss)) + return 0; + + return test_ssid == NULL || wpas_valid_ssid(wpa_s, test_ssid); +} + + +void wpas_connect_work_free(struct wpa_connect_work *cwork) +{ + if (cwork == NULL) + return; + os_free(cwork); +} + + +void wpas_connect_work_done(struct wpa_supplicant *wpa_s) +{ + struct wpa_connect_work *cwork; + struct wpa_radio_work *work = wpa_s->connect_work; + + if (!work) + return; + + wpa_s->connect_work = NULL; + cwork = work->ctx; + work->ctx = NULL; + wpas_connect_work_free(cwork); + radio_work_done(work); +} + +#ifdef CONFIG_RANDOM_MAC +int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style) +{ + struct os_reltime now; + u8 addr[ETH_ALEN]; + + os_get_reltime(&now); + if (wpa_s->last_mac_addr_style == style && + wpa_s->last_mac_addr_change.sec != 0 && + !os_reltime_expired(&now, &wpa_s->last_mac_addr_change, + wpa_s->conf->rand_addr_lifetime)) { + wpa_msg(wpa_s, MSG_DEBUG, + "Previously selected random MAC address has not yet expired"); + return 0; + } + + switch (style) { + case 1: + if (random_mac_addr(addr) < 0) + return -1; + break; + case 2: + os_memcpy(addr, wpa_s->perm_addr, ETH_ALEN); + if (random_mac_addr_keep_oui(addr) < 0) + return -1; + break; + default: + return -1; + } + + if (wpa_drv_set_mac_addr(wpa_s, addr) < 0) { + wpa_msg(wpa_s, MSG_INFO, + "Failed to set random MAC address"); + return -1; + } + + os_get_reltime(&wpa_s->last_mac_addr_change); + wpa_s->mac_addr_changed = 1; + wpa_s->last_mac_addr_style = style; + + if (wpa_supplicant_update_mac_addr(wpa_s) < 0) { + wpa_msg(wpa_s, MSG_INFO, + "Could not update MAC address information"); + return -1; + } + + wpa_msg(wpa_s, MSG_DEBUG, "Using random MAC address " MACSTR, + MAC2STR(addr)); + + return 0; +} + + +int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s) +{ + if (wpa_s->wpa_state >= WPA_AUTHENTICATING || + !wpa_s->conf->preassoc_mac_addr) + return 0; + + return wpas_update_random_addr(wpa_s, wpa_s->conf->preassoc_mac_addr); +} +#endif /* CONFIG_RANDOM_MAC */ + +static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit); + +/** + * wpa_supplicant_associate - Request association + * @wpa_s: Pointer to wpa_supplicant data + * @bss: Scan results for the selected BSS, or %NULL if not available + * @ssid: Configuration data for the selected network + * + * This function is used to request %wpa_supplicant to associate with a BSS. + */ +void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, + struct wpa_bss *bss, struct wpa_ssid *ssid) +{ + struct wpa_connect_work *cwork; +#ifdef CONFIG_RANDOM_MAC + int rand_style; + + if (ssid->mac_addr == -1) + rand_style = wpa_s->conf->mac_addr; + else + rand_style = ssid->mac_addr; +#endif + + wmm_ac_clear_saved_tspecs(wpa_s); + + wpa_s->reassoc_same_bss = 0; + + if (wpa_s->last_ssid == ssid) { + wpa_dbg(wpa_s, MSG_DEBUG, "Re-association to the same ESS"); + if (wpa_s->current_bss && wpa_s->current_bss == bss) { + wmm_ac_save_tspecs(wpa_s); + + wpa_s->reassoc_same_bss = 1; + } +#ifdef CONFIG_RANDOM_MAC + } else if (rand_style > 0) { + if (wpas_update_random_addr(wpa_s, rand_style) < 0) + return; + wpa_sm_pmksa_cache_flush(wpa_s->wpa, ssid); +#endif + } else if (wpa_s->mac_addr_changed) { + if (wpa_drv_set_mac_addr(wpa_s, NULL) < 0) { + wpa_msg(wpa_s, MSG_INFO, + "Could not restore permanent MAC address"); + return; + } + wpa_s->mac_addr_changed = 0; + if (wpa_supplicant_update_mac_addr(wpa_s) < 0) { + wpa_msg(wpa_s, MSG_INFO, + "Could not update MAC address information"); + return; + } + wpa_msg(wpa_s, MSG_DEBUG, "Using permanent MAC address"); + } + wpa_s->last_ssid = ssid; + +#ifdef CONFIG_IBSS_RSN + ibss_rsn_deinit(wpa_s->ibss_rsn); + wpa_s->ibss_rsn = NULL; +#endif /* CONFIG_IBSS_RSN */ + + if (ssid->mode == WPAS_MODE_AP || ssid->mode == WPAS_MODE_P2P_GO || + ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) { +#ifdef CONFIG_AP + if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_AP)) { + wpa_msg(wpa_s, MSG_INFO, "Driver does not support AP " + "mode"); + return; + } + if (wpa_supplicant_create_ap(wpa_s, ssid) < 0) { + wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); + if (ssid->mode == WPAS_MODE_P2P_GROUP_FORMATION) + wpas_p2p_ap_setup_failed(wpa_s); + return; + } + wpa_s->current_bss = bss; +#else /* CONFIG_AP */ + wpa_msg(wpa_s, MSG_ERROR, "AP mode support not included in " + "the build"); +#endif /* CONFIG_AP */ + return; + } + + if (ssid->mode == WPAS_MODE_MESH) { +#ifdef CONFIG_MESH + if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_MESH)) { + wpa_msg(wpa_s, MSG_INFO, + "Driver does not support mesh mode"); + return; + } + if (bss) + ssid->frequency = bss->freq; + if (wpa_supplicant_join_mesh(wpa_s, ssid) < 0) { + wpa_msg(wpa_s, MSG_ERROR, "Could not join mesh"); + return; + } + wpa_s->current_bss = bss; + wpa_msg_ctrl(wpa_s, MSG_INFO, MESH_GROUP_STARTED + "ssid=\"%s\" id=%d", + wpa_ssid_txt(ssid->ssid, ssid->ssid_len), + ssid->id); +#else /* CONFIG_MESH */ + wpa_msg(wpa_s, MSG_ERROR, + "mesh mode support not included in the build"); +#endif /* CONFIG_MESH */ + return; + } + +#ifdef CONFIG_TDLS + if (bss) + wpa_tdls_ap_ies(wpa_s->wpa, (const u8 *) (bss + 1), + bss->ie_len); +#endif /* CONFIG_TDLS */ + + if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) && + ssid->mode == IEEE80211_MODE_INFRA) { + sme_authenticate(wpa_s, bss, ssid); + return; + } + + if (wpa_s->connect_work) { + wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since connect_work exist"); + return; + } + + if (radio_work_pending(wpa_s, "connect")) { + wpa_dbg(wpa_s, MSG_DEBUG, "Reject wpa_supplicant_associate() call since pending work exist"); + return; + } + + cwork = os_zalloc(sizeof(*cwork)); + if (cwork == NULL) + return; + + cwork->bss = bss; + cwork->ssid = ssid; + + if (radio_add_work(wpa_s, bss ? bss->freq : 0, "connect", 1, + wpas_start_assoc_cb, cwork) < 0) { + os_free(cwork); + } +} + +static int bss_is_ibss(struct wpa_bss *bss) +{ + return (bss->caps & (IEEE80211_CAP_ESS | IEEE80211_CAP_IBSS)) == + IEEE80211_CAP_IBSS; +} + +void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s, + const struct wpa_ssid *ssid, + struct hostapd_freq_params *freq) +{ + enum hostapd_hw_mode hw_mode; + struct hostapd_hw_modes *mode = NULL; + int ht40plus[] = { 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157, + 184, 192 }; + int vht80[] = { 36, 52, 100, 116, 132, 149 }; + struct hostapd_channel_data *pri_chan = NULL, *sec_chan = NULL; + u8 channel; + int i, chan_idx, ht40 = -1, res, obss_scan = 1; + unsigned int j; + struct hostapd_freq_params vht_freq; + + freq->freq = ssid->frequency; + + for (j = 0; j < wpa_s->last_scan_res_used; j++) { + struct wpa_bss *bss = wpa_s->last_scan_res[j]; + + if (ssid->mode != WPAS_MODE_IBSS) + break; + + /* Don't adjust control freq in case of fixed_freq */ + if (ssid->fixed_freq) + break; + + if (!bss_is_ibss(bss)) + continue; + + if (ssid->ssid_len == bss->ssid_len && + os_memcmp(ssid->ssid, bss->ssid, bss->ssid_len) == 0) { + wpa_printf(MSG_DEBUG, + "IBSS already found in scan results, adjust control freq: %d", + bss->freq); + freq->freq = bss->freq; + obss_scan = 0; + break; + } + } + + /* For IBSS check HT_IBSS flag */ + if (ssid->mode == WPAS_MODE_IBSS && + !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_HT_IBSS)) + return; + + if (wpa_s->group_cipher == WPA_CIPHER_WEP40 || + wpa_s->group_cipher == WPA_CIPHER_WEP104 || + wpa_s->pairwise_cipher == WPA_CIPHER_TKIP) { + wpa_printf(MSG_DEBUG, + "IBSS: WEP/TKIP detected, do not try to enable HT"); + return; + } + + hw_mode = ieee80211_freq_to_chan(freq->freq, &channel); + for (i = 0; wpa_s->hw.modes && i < wpa_s->hw.num_modes; i++) { + if (wpa_s->hw.modes[i].mode == hw_mode) { + mode = &wpa_s->hw.modes[i]; + break; + } + } + + if (!mode) + return; + + freq->ht_enabled = ht_supported(mode); + if (!freq->ht_enabled) + return; + + /* Setup higher BW only for 5 GHz */ + if (mode->mode != HOSTAPD_MODE_IEEE80211A) + return; + + for (chan_idx = 0; chan_idx < mode->num_channels; chan_idx++) { + pri_chan = &mode->channels[chan_idx]; + if (pri_chan->chan == channel) + break; + pri_chan = NULL; + } + if (!pri_chan) + return; + + /* Check primary channel flags */ + if (pri_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR)) + return; + + /* Check/setup HT40+/HT40- */ + for (j = 0; j < ARRAY_SIZE(ht40plus); j++) { + if (ht40plus[j] == channel) { + ht40 = 1; + break; + } + } + + /* Find secondary channel */ + for (i = 0; i < mode->num_channels; i++) { + sec_chan = &mode->channels[i]; + if (sec_chan->chan == channel + ht40 * 4) + break; + sec_chan = NULL; + } + if (!sec_chan) + return; + + /* Check secondary channel flags */ + if (sec_chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR)) + return; + + freq->channel = pri_chan->chan; + + switch (ht40) { + case -1: + if (!(pri_chan->flag & HOSTAPD_CHAN_HT40MINUS)) + return; + freq->sec_channel_offset = -1; + break; + case 1: + if (!(pri_chan->flag & HOSTAPD_CHAN_HT40PLUS)) + return; + freq->sec_channel_offset = 1; + break; + default: + break; + } + + if (freq->sec_channel_offset && obss_scan) { + struct wpa_scan_results *scan_res; + + scan_res = wpa_supplicant_get_scan_results(wpa_s, NULL, 0); + if (scan_res == NULL) { + /* Back to HT20 */ + freq->sec_channel_offset = 0; + return; + } + + res = check_40mhz_5g(mode, scan_res, pri_chan->chan, + sec_chan->chan); + switch (res) { + case 0: + /* Back to HT20 */ + freq->sec_channel_offset = 0; + break; + case 1: + /* Configuration allowed */ + break; + case 2: + /* Switch pri/sec channels */ + freq->freq = hw_get_freq(mode, sec_chan->chan); + freq->sec_channel_offset = -freq->sec_channel_offset; + freq->channel = sec_chan->chan; + break; + default: + freq->sec_channel_offset = 0; + break; + } + + wpa_scan_results_free(scan_res); + } + + wpa_printf(MSG_DEBUG, + "IBSS/mesh: setup freq channel %d, sec_channel_offset %d", + freq->channel, freq->sec_channel_offset); + + /* Not sure if mesh is ready for VHT */ + if (ssid->mode != WPAS_MODE_IBSS) + return; + + /* For IBSS check VHT_IBSS flag */ + if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_VHT_IBSS)) + return; + + vht_freq = *freq; + + vht_freq.vht_enabled = vht_supported(mode); + if (!vht_freq.vht_enabled) + return; + + /* setup center_freq1, bandwidth */ + for (j = 0; j < ARRAY_SIZE(vht80); j++) { + if (freq->channel >= vht80[j] && + freq->channel < vht80[j] + 16) + break; + } + + if (j == ARRAY_SIZE(vht80)) + return; + + for (i = vht80[j]; i < vht80[j] + 16; i += 4) { + struct hostapd_channel_data *chan; + + chan = hw_get_channel_chan(mode, i, NULL); + if (!chan) + return; + + /* Back to HT configuration if channel not usable */ + if (chan->flag & (HOSTAPD_CHAN_DISABLED | HOSTAPD_CHAN_NO_IR)) + return; + } + + if (hostapd_set_freq_params(&vht_freq, mode->mode, freq->freq, + freq->channel, freq->ht_enabled, + vht_freq.vht_enabled, + freq->sec_channel_offset, + VHT_CHANWIDTH_80MHZ, + vht80[j] + 6, 0, 0) != 0) + return; + + *freq = vht_freq; + + wpa_printf(MSG_DEBUG, "IBSS: VHT setup freq cf1 %d, cf2 %d, bw %d", + freq->center_freq1, freq->center_freq2, freq->bandwidth); +} + + +static void wpas_start_assoc_cb(struct wpa_radio_work *work, int deinit) +{ + struct wpa_connect_work *cwork = work->ctx; + struct wpa_bss *bss = cwork->bss; + struct wpa_ssid *ssid = cwork->ssid; + struct wpa_supplicant *wpa_s = work->wpa_s; + u8 wpa_ie[200]; + size_t wpa_ie_len; + int use_crypt, ret, i, bssid_changed; + int algs = WPA_AUTH_ALG_OPEN; + unsigned int cipher_pairwise, cipher_group; + struct wpa_driver_associate_params params; + int wep_keys_set = 0; + int assoc_failed = 0; + struct wpa_ssid *old_ssid; +#ifdef CONFIG_HT_OVERRIDES + struct ieee80211_ht_capabilities htcaps; + struct ieee80211_ht_capabilities htcaps_mask; +#endif /* CONFIG_HT_OVERRIDES */ +#ifdef CONFIG_VHT_OVERRIDES + struct ieee80211_vht_capabilities vhtcaps; + struct ieee80211_vht_capabilities vhtcaps_mask; +#endif /* CONFIG_VHT_OVERRIDES */ + + if (deinit) { + if (work->started) { + wpa_s->connect_work = NULL; + + /* cancel possible auth. timeout */ + eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, + NULL); + } + wpas_connect_work_free(cwork); + return; + } + + wpa_s->connect_work = work; + + if (cwork->bss_removed || !wpas_valid_bss_ssid(wpa_s, bss, ssid) || + wpas_network_disabled(wpa_s, ssid)) { + wpa_dbg(wpa_s, MSG_DEBUG, "BSS/SSID entry for association not valid anymore - drop connection attempt"); + wpas_connect_work_done(wpa_s); + return; + } + + os_memset(¶ms, 0, sizeof(params)); + wpa_s->reassociate = 0; + wpa_s->eap_expected_failure = 0; + if (bss && + (!wpas_driver_bss_selection(wpa_s) || wpas_wps_searching(wpa_s))) { +#ifdef CONFIG_IEEE80211R + const u8 *ie, *md = NULL; +#endif /* CONFIG_IEEE80211R */ + wpa_msg(wpa_s, MSG_INFO, "Trying to associate with " MACSTR + " (SSID='%s' freq=%d MHz)", MAC2STR(bss->bssid), + wpa_ssid_txt(bss->ssid, bss->ssid_len), bss->freq); + bssid_changed = !is_zero_ether_addr(wpa_s->bssid); + os_memset(wpa_s->bssid, 0, ETH_ALEN); + os_memcpy(wpa_s->pending_bssid, bss->bssid, ETH_ALEN); + if (bssid_changed) + wpas_notify_bssid_changed(wpa_s); +#ifdef CONFIG_IEEE80211R + ie = wpa_bss_get_ie(bss, WLAN_EID_MOBILITY_DOMAIN); + if (ie && ie[1] >= MOBILITY_DOMAIN_ID_LEN) + md = ie + 2; + wpa_sm_set_ft_params(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0); + if (md) { + /* Prepare for the next transition */ + wpa_ft_prepare_auth_request(wpa_s->wpa, ie); + } +#endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_WPS + } else if ((ssid->ssid == NULL || ssid->ssid_len == 0) && + wpa_s->conf->ap_scan == 2 && + (ssid->key_mgmt & WPA_KEY_MGMT_WPS)) { + /* Use ap_scan==1 style network selection to find the network + */ + wpas_connect_work_done(wpa_s); + wpa_s->scan_req = MANUAL_SCAN_REQ; + wpa_s->reassociate = 1; + wpa_supplicant_req_scan(wpa_s, 0, 0); + return; +#endif /* CONFIG_WPS */ + } else { + wpa_msg(wpa_s, MSG_INFO, "Trying to associate with SSID '%s'", + wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); + os_memset(wpa_s->pending_bssid, 0, ETH_ALEN); + } + if (!wpa_s->pno) + wpa_supplicant_cancel_sched_scan(wpa_s); + + wpa_supplicant_cancel_scan(wpa_s); + + /* Starting new association, so clear the possibly used WPA IE from the + * previous association. */ + wpa_sm_set_assoc_wpa_ie(wpa_s->wpa, NULL, 0); + +#ifdef IEEE8021X_EAPOL + if (ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) { + if (ssid->leap) { + if (ssid->non_leap == 0) + algs = WPA_AUTH_ALG_LEAP; + else + algs |= WPA_AUTH_ALG_LEAP; + } + } +#endif /* IEEE8021X_EAPOL */ + wpa_dbg(wpa_s, MSG_DEBUG, "Automatic auth_alg selection: 0x%x", algs); + if (ssid->auth_alg) { + algs = ssid->auth_alg; + wpa_dbg(wpa_s, MSG_DEBUG, "Overriding auth_alg selection: " + "0x%x", algs); + } + + if (bss && (wpa_bss_get_vendor_ie(bss, WPA_IE_VENDOR_TYPE) || + wpa_bss_get_ie(bss, WLAN_EID_RSN)) && + wpa_key_mgmt_wpa(ssid->key_mgmt)) { + int try_opportunistic; + try_opportunistic = (ssid->proactive_key_caching < 0 ? + wpa_s->conf->okc : + ssid->proactive_key_caching) && + (ssid->proto & WPA_PROTO_RSN); + if (pmksa_cache_set_current(wpa_s->wpa, NULL, bss->bssid, + ssid, try_opportunistic) == 0) + eapol_sm_notify_pmkid_attempt(wpa_s->eapol); + wpa_ie_len = sizeof(wpa_ie); + if (wpa_supplicant_set_suites(wpa_s, bss, ssid, + wpa_ie, &wpa_ie_len)) { + wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA " + "key management and encryption suites"); + wpas_connect_work_done(wpa_s); + return; + } + } else if ((ssid->key_mgmt & WPA_KEY_MGMT_IEEE8021X_NO_WPA) && bss && + wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) { + /* + * Both WPA and non-WPA IEEE 802.1X enabled in configuration - + * use non-WPA since the scan results did not indicate that the + * AP is using WPA or WPA2. + */ + wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); + wpa_ie_len = 0; + wpa_s->wpa_proto = 0; + } else if (wpa_key_mgmt_wpa_any(ssid->key_mgmt)) { + wpa_ie_len = sizeof(wpa_ie); + if (wpa_supplicant_set_suites(wpa_s, NULL, ssid, + wpa_ie, &wpa_ie_len)) { + wpa_msg(wpa_s, MSG_WARNING, "WPA: Failed to set WPA " + "key management and encryption suites (no " + "scan results)"); + wpas_connect_work_done(wpa_s); + return; + } +#ifdef CONFIG_WPS + } else if (ssid->key_mgmt & WPA_KEY_MGMT_WPS) { + struct wpabuf *wps_ie; + wps_ie = wps_build_assoc_req_ie(wpas_wps_get_req_type(ssid)); + if (wps_ie && wpabuf_len(wps_ie) <= sizeof(wpa_ie)) { + wpa_ie_len = wpabuf_len(wps_ie); + os_memcpy(wpa_ie, wpabuf_head(wps_ie), wpa_ie_len); + } else + wpa_ie_len = 0; + wpabuf_free(wps_ie); + wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); + if (!bss || (bss->caps & IEEE80211_CAP_PRIVACY)) + params.wps = WPS_MODE_PRIVACY; + else + params.wps = WPS_MODE_OPEN; + wpa_s->wpa_proto = 0; +#endif /* CONFIG_WPS */ + } else { + wpa_supplicant_set_non_wpa_policy(wpa_s, ssid); + wpa_ie_len = 0; + wpa_s->wpa_proto = 0; + } + +#ifdef CONFIG_P2P + if (wpa_s->global->p2p) { + u8 *pos; + size_t len; + int res; + pos = wpa_ie + wpa_ie_len; + len = sizeof(wpa_ie) - wpa_ie_len; + res = wpas_p2p_assoc_req_ie(wpa_s, bss, pos, len, + ssid->p2p_group); + if (res >= 0) + wpa_ie_len += res; + } + + wpa_s->cross_connect_disallowed = 0; + if (bss) { + struct wpabuf *p2p; + p2p = wpa_bss_get_vendor_ie_multi(bss, P2P_IE_VENDOR_TYPE); + if (p2p) { + wpa_s->cross_connect_disallowed = + p2p_get_cross_connect_disallowed(p2p); + wpabuf_free(p2p); + wpa_dbg(wpa_s, MSG_DEBUG, "P2P: WLAN AP %s cross " + "connection", + wpa_s->cross_connect_disallowed ? + "disallows" : "allows"); + } + } + + os_memset(wpa_s->p2p_ip_addr_info, 0, sizeof(wpa_s->p2p_ip_addr_info)); +#endif /* CONFIG_P2P */ + +#ifdef CONFIG_HS20 + if (is_hs20_network(wpa_s, ssid, bss)) { + struct wpabuf *hs20; + hs20 = wpabuf_alloc(20); + if (hs20) { + int pps_mo_id = hs20_get_pps_mo_id(wpa_s, ssid); + size_t len; + + wpas_hs20_add_indication(hs20, pps_mo_id); + len = sizeof(wpa_ie) - wpa_ie_len; + if (wpabuf_len(hs20) <= len) { + os_memcpy(wpa_ie + wpa_ie_len, + wpabuf_head(hs20), wpabuf_len(hs20)); + wpa_ie_len += wpabuf_len(hs20); + } + wpabuf_free(hs20); + } + } +#endif /* CONFIG_HS20 */ + + /* + * Workaround: Add Extended Capabilities element only if the AP + * included this element in Beacon/Probe Response frames. Some older + * APs seem to have interoperability issues if this element is + * included, so while the standard may require us to include the + * element in all cases, it is justifiable to skip it to avoid + * interoperability issues. + */ + if (!bss || wpa_bss_get_ie(bss, WLAN_EID_EXT_CAPAB)) { + u8 ext_capab[18]; + int ext_capab_len; + ext_capab_len = wpas_build_ext_capab(wpa_s, ext_capab, + sizeof(ext_capab)); + if (ext_capab_len > 0) { + u8 *pos = wpa_ie; + if (wpa_ie_len > 0 && pos[0] == WLAN_EID_RSN) + pos += 2 + pos[1]; + os_memmove(pos + ext_capab_len, pos, + wpa_ie_len - (pos - wpa_ie)); + wpa_ie_len += ext_capab_len; + os_memcpy(pos, ext_capab, ext_capab_len); + } + } + + if (wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]) { + struct wpabuf *buf = wpa_s->vendor_elem[VENDOR_ELEM_ASSOC_REQ]; + size_t len; + + len = sizeof(wpa_ie) - wpa_ie_len; + if (wpabuf_len(buf) <= len) { + os_memcpy(wpa_ie + wpa_ie_len, + wpabuf_head(buf), wpabuf_len(buf)); + wpa_ie_len += wpabuf_len(buf); + } + } + +#ifdef CONFIG_FST + if (wpa_s->fst_ies) { + int fst_ies_len = wpabuf_len(wpa_s->fst_ies); + + if (wpa_ie_len + fst_ies_len <= sizeof(wpa_ie)) { + os_memcpy(wpa_ie + wpa_ie_len, + wpabuf_head(wpa_s->fst_ies), fst_ies_len); + wpa_ie_len += fst_ies_len; + } + } +#endif /* CONFIG_FST */ + + wpa_clear_keys(wpa_s, bss ? bss->bssid : NULL); + use_crypt = 1; + cipher_pairwise = wpa_s->pairwise_cipher; + cipher_group = wpa_s->group_cipher; + if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE || + wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) { +#if RL_SUPPORT_FAST_CONNECT + if ((wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) && (0 != g_sta_param_ptr->fast_connect_set)) + { + os_null_printf("%s:%d rl_clear_bssid_info\r\n", __FUNCTION__, __LINE__); + rl_clear_bssid_info(); + } +#endif + if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) + use_crypt = 0; + if (wpa_set_wep_keys(wpa_s, ssid)) { + use_crypt = 1; + wep_keys_set = 1; + } + } + if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) + use_crypt = 0; + +#ifdef IEEE8021X_EAPOL + if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) { + if ((ssid->eapol_flags & + (EAPOL_FLAG_REQUIRE_KEY_UNICAST | + EAPOL_FLAG_REQUIRE_KEY_BROADCAST)) == 0 && + !wep_keys_set) { + use_crypt = 0; + } else { + /* Assume that dynamic WEP-104 keys will be used and + * set cipher suites in order for drivers to expect + * encryption. */ + cipher_pairwise = cipher_group = WPA_CIPHER_WEP104; + } + } +#endif /* IEEE8021X_EAPOL */ + + if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) { + /* Set the key before (and later after) association */ + wpa_supplicant_set_wpa_none_key(wpa_s, ssid); + } + + wpa_supplicant_set_state(wpa_s, WPA_ASSOCIATING); + if (bss) { + params.ssid = bss->ssid; + params.ssid_len = bss->ssid_len; + if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) { + wpa_printf(MSG_DEBUG, "Limit connection to BSSID " + MACSTR " freq=%u MHz based on scan results " + "(bssid_set=%d)", + MAC2STR(bss->bssid), bss->freq, + ssid->bssid_set); + params.bssid = bss->bssid; + params.freq.freq = bss->freq; + } + params.bssid_hint = bss->bssid; + params.freq_hint = bss->freq; + } else { + params.ssid = ssid->ssid; + params.ssid_len = ssid->ssid_len; + } + + if (ssid->mode == WPAS_MODE_IBSS && ssid->bssid_set && + wpa_s->conf->ap_scan == 2) { + params.bssid = ssid->bssid; + params.fixed_bssid = 1; + } + if(ssid->bssid_set){ + params.bssid = ssid->bssid; + ssid->bssid_set = 0; + } + +#ifdef CONIFG_FULL_SUPPLICANT + /* Initial frequency for IBSS/mesh */ + if ((ssid->mode == WPAS_MODE_IBSS || ssid->mode == WPAS_MODE_MESH) && + ssid->frequency > 0 && params.freq.freq == 0) + ibss_mesh_setup_freq(wpa_s, ssid, ¶ms.freq); + + if (ssid->mode == WPAS_MODE_IBSS) { + params.fixed_freq = ssid->fixed_freq; + if (ssid->beacon_int) + params.beacon_int = ssid->beacon_int; + else + params.beacon_int = wpa_s->conf->beacon_int; + } +#endif + + params.wpa_ie = wpa_ie; + params.wpa_ie_len = wpa_ie_len; + params.pairwise_suite = cipher_pairwise; + params.group_suite = cipher_group; + params.key_mgmt_suite = wpa_s->key_mgmt; + params.wpa_proto = wpa_s->wpa_proto; + params.auth_alg = algs; + params.mode = ssid->mode; + params.bg_scan_period = ssid->bg_scan_period; + for (i = 0; i < NUM_WEP_KEYS; i++) { + if (ssid->wep_key_len[i]) + params.wep_key[i] = ssid->wep_key[i]; + params.wep_key_len[i] = ssid->wep_key_len[i]; + } + params.wep_tx_keyidx = ssid->wep_tx_keyidx; + + if ((wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) && + (params.key_mgmt_suite == WPA_KEY_MGMT_PSK || + params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK)) { + params.passphrase = ssid->passphrase; + if (ssid->psk_set) + params.psk = ssid->psk; + } + + if (wpa_s->conf->key_mgmt_offload) { + if (params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X || + params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SHA256 || + params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B || + params.key_mgmt_suite == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) + params.req_key_mgmt_offload = + ssid->proactive_key_caching < 0 ? + wpa_s->conf->okc : ssid->proactive_key_caching; + else + params.req_key_mgmt_offload = 1; + + if ((params.key_mgmt_suite == WPA_KEY_MGMT_PSK || + params.key_mgmt_suite == WPA_KEY_MGMT_PSK_SHA256 || + params.key_mgmt_suite == WPA_KEY_MGMT_FT_PSK) && + ssid->psk_set) + params.psk = ssid->psk; + } + + params.drop_unencrypted = use_crypt; + +#ifdef CONFIG_IEEE80211W + params.mgmt_frame_protection = wpas_get_ssid_pmf(wpa_s, ssid); + if (params.mgmt_frame_protection != NO_MGMT_FRAME_PROTECTION && bss) { + const u8 *rsn = wpa_bss_get_ie(bss, WLAN_EID_RSN); + struct wpa_ie_data ie; + if (rsn && wpa_parse_wpa_ie(rsn, 2 + rsn[1], &ie) == 0 && + ie.capabilities & + (WPA_CAPABILITY_MFPC | WPA_CAPABILITY_MFPR)) { + wpa_dbg(wpa_s, MSG_DEBUG, "WPA: Selected AP supports " + "MFP: require MFP"); + params.mgmt_frame_protection = + MGMT_FRAME_PROTECTION_REQUIRED; + } + } +#endif /* CONFIG_IEEE80211W */ + + params.p2p = ssid->p2p_group; + + if (wpa_s->parent->set_sta_uapsd) + params.uapsd = wpa_s->parent->sta_uapsd; + else + params.uapsd = -1; + +#ifdef CONFIG_HT_OVERRIDES + os_memset(&htcaps, 0, sizeof(htcaps)); + os_memset(&htcaps_mask, 0, sizeof(htcaps_mask)); + params.htcaps = (u8 *) &htcaps; + params.htcaps_mask = (u8 *) &htcaps_mask; + wpa_supplicant_apply_ht_overrides(wpa_s, ssid, ¶ms); +#endif /* CONFIG_HT_OVERRIDES */ +#ifdef CONFIG_VHT_OVERRIDES + os_memset(&vhtcaps, 0, sizeof(vhtcaps)); + os_memset(&vhtcaps_mask, 0, sizeof(vhtcaps_mask)); + params.vhtcaps = &vhtcaps; + params.vhtcaps_mask = &vhtcaps_mask; + wpa_supplicant_apply_vht_overrides(wpa_s, ssid, ¶ms); +#endif /* CONFIG_VHT_OVERRIDES */ + +#ifdef CONFIG_P2P + /* + * If multi-channel concurrency is not supported, check for any + * frequency conflict. In case of any frequency conflict, remove the + * least prioritized connection. + */ + if (wpa_s->num_multichan_concurrent < 2) { + int freq, num; + num = get_shared_radio_freqs(wpa_s, &freq, 1); + if (num > 0 && freq > 0 && freq != params.freq.freq) { + wpa_printf(MSG_DEBUG, + "Assoc conflicting freq found (%d != %d)", + freq, params.freq.freq); + if (wpas_p2p_handle_frequency_conflicts( + wpa_s, params.freq.freq, ssid) < 0) { + wpas_connect_work_done(wpa_s); + return; + } + } + } +#endif /* CONFIG_P2P */ + + ret = wpa_drv_associate(wpa_s, ¶ms); + if (ret < 0) { + os_printf("Association request to the driver failed\r\n"); + if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SANE_ERROR_CODES) { + /* + * The driver is known to mean what is saying, so we + * can stop right here; the association will not + * succeed. + */ + wpas_connection_failed(wpa_s, wpa_s->pending_bssid); + wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); + os_memset(wpa_s->pending_bssid, 0, ETH_ALEN); + return; + } + /* try to continue anyway; new association will be tried again + * after timeout */ + assoc_failed = 1; + } + + if (wpa_s->key_mgmt == WPA_KEY_MGMT_WPA_NONE) { + /* Set the key after the association just in case association + * cleared the previously configured key. */ + wpa_supplicant_set_wpa_none_key(wpa_s, ssid); + /* No need to timeout authentication since there is no key + * management. */ + wpa_supplicant_cancel_auth_timeout(wpa_s); + wpa_supplicant_set_state(wpa_s, WPA_COMPLETED); +#ifdef CONFIG_IBSS_RSN + } else if (ssid->mode == WPAS_MODE_IBSS && + wpa_s->key_mgmt != WPA_KEY_MGMT_NONE && + wpa_s->key_mgmt != WPA_KEY_MGMT_WPA_NONE) { + /* + * RSN IBSS authentication is per-STA and we can disable the + * per-BSSID authentication. + */ + wpa_supplicant_cancel_auth_timeout(wpa_s); +#endif /* CONFIG_IBSS_RSN */ + } else { + /* Timeout for IEEE 802.11 authentication and association */ + int timeout = 60; + + if (assoc_failed) { + /* give IBSS a bit more time */ + timeout = ssid->mode == WPAS_MODE_IBSS ? 10 : 5; + } else if (wpa_s->conf->ap_scan == 1) { + /* give IBSS a bit more time */ + timeout = ssid->mode == WPAS_MODE_IBSS ? 20 : 10; + } + wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0); + } + + if (wep_keys_set && + (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SET_KEYS_AFTER_ASSOC)) { + /* Set static WEP keys again */ + wpa_set_wep_keys(wpa_s, ssid); + } + + if (wpa_s->current_ssid && wpa_s->current_ssid != ssid) { + /* + * Do not allow EAP session resumption between different + * network configurations. + */ + eapol_sm_invalidate_cached_session(wpa_s->eapol); + } + old_ssid = wpa_s->current_ssid; + wpa_s->current_ssid = ssid; + if (!wpas_driver_bss_selection(wpa_s) || ssid->bssid_set) + wpa_s->current_bss = bss; + wpa_supplicant_rsn_supp_set_config(wpa_s, wpa_s->current_ssid); + wpa_supplicant_initiate_eapol(wpa_s); + if (old_ssid != wpa_s->current_ssid) + wpas_notify_network_changed(wpa_s); +} + + +static void wpa_supplicant_clear_connection(struct wpa_supplicant *wpa_s, + const u8 *addr) +{ + struct wpa_ssid *old_ssid; + + wpas_connect_work_done(wpa_s); + wpa_clear_keys(wpa_s, addr); + old_ssid = wpa_s->current_ssid; + wpa_supplicant_mark_disassoc(wpa_s); + wpa_sm_set_config(wpa_s->wpa, NULL); + eapol_sm_notify_config(wpa_s->eapol, NULL, NULL); + if (old_ssid != wpa_s->current_ssid) + wpas_notify_network_changed(wpa_s); + eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL); +} + + +/** + * wpa_supplicant_deauthenticate - Deauthenticate the current connection + * @wpa_s: Pointer to wpa_supplicant data + * @reason_code: IEEE 802.11 reason code for the deauthenticate frame + * + * This function is used to request %wpa_supplicant to deauthenticate from the + * current AP. + */ +void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s, + int reason_code) +{ + u8 *addr = NULL; + union wpa_event_data event; + int zero_addr = 0; + + wpa_dbg(wpa_s, MSG_DEBUG, "Request to deauthenticate - bssid=" MACSTR + " pending_bssid=" MACSTR " reason=%d state=%s", + MAC2STR(wpa_s->bssid), MAC2STR(wpa_s->pending_bssid), + reason_code, wpa_supplicant_state_txt(wpa_s->wpa_state)); + + if (!is_zero_ether_addr(wpa_s->bssid)) + addr = wpa_s->bssid; + else if (!is_zero_ether_addr(wpa_s->pending_bssid) && + (wpa_s->wpa_state == WPA_AUTHENTICATING || + wpa_s->wpa_state == WPA_ASSOCIATING)) + addr = wpa_s->pending_bssid; + else if (wpa_s->wpa_state == WPA_ASSOCIATING) { + /* + * When using driver-based BSS selection, we may not know the + * BSSID with which we are currently trying to associate. We + * need to notify the driver of this disconnection even in such + * a case, so use the all zeros address here. + */ + addr = wpa_s->bssid; + zero_addr = 1; + } + +#ifdef CONFIG_TDLS + wpa_tdls_teardown_peers(wpa_s->wpa); +#endif /* CONFIG_TDLS */ + +#ifdef CONFIG_MESH + if (wpa_s->ifmsh) { + wpa_msg_ctrl(wpa_s, MSG_INFO, MESH_GROUP_REMOVED "%s", + wpa_s->ifname); + wpa_supplicant_leave_mesh(wpa_s); + } +#endif /* CONFIG_MESH */ + + if (addr) { + wpa_drv_deauthenticate(wpa_s, addr, reason_code); + os_memset(&event, 0, sizeof(event)); + event.deauth_info.reason_code = (u16) reason_code; + event.deauth_info.locally_generated = 1; + wpa_supplicant_event_sta(wpa_s, EVENT_DEAUTH, &event); + if (zero_addr) + addr = NULL; + } + + wpa_supplicant_clear_connection(wpa_s, addr); +} + +static void wpa_supplicant_enable_one_network(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid) +{ + if (!ssid || !ssid->disabled || ssid->disabled == 2) + return; + + ssid->disabled = 0; + wpas_clear_temp_disabled(wpa_s, ssid, 1); + wpas_notify_network_enabled_changed(wpa_s, ssid); + + /* + * Try to reassociate since there is no current configuration and a new + * network was made available. + */ + if (!wpa_s->current_ssid && !wpa_s->disconnected) + wpa_s->reassociate = 1; +} + + +/** + * wpa_supplicant_enable_network - Mark a configured network as enabled + * @wpa_s: wpa_supplicant structure for a network interface + * @ssid: wpa_ssid structure for a configured network or %NULL + * + * Enables the specified network or all networks if no network specified. + */ +void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid) +{ + if (ssid == NULL) { + for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) + wpa_supplicant_enable_one_network(wpa_s, ssid); + } else + wpa_supplicant_enable_one_network(wpa_s, ssid); + + if (wpa_s->reassociate && !wpa_s->disconnected && + (!wpa_s->current_ssid || + wpa_s->wpa_state == WPA_DISCONNECTED || + wpa_s->wpa_state == WPA_SCANNING)) { + if (wpa_s->sched_scanning) { + wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan to add " + "new network to scan filters"); + wpa_supplicant_cancel_sched_scan(wpa_s); + } + + if (wpa_supplicant_fast_associate(wpa_s) != 1) { + wpa_s->scan_req = NORMAL_SCAN_REQ; + wpa_supplicant_req_scan(wpa_s, 0, 0); + } + } +} + + +/** + * wpa_supplicant_disable_network - Mark a configured network as disabled + * @wpa_s: wpa_supplicant structure for a network interface + * @ssid: wpa_ssid structure for a configured network or %NULL + * + * Disables the specified network or all networks if no network specified. + */ +void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid) +{ + struct wpa_ssid *other_ssid; + int was_disabled; + + if (ssid == NULL) { + if (wpa_s->sched_scanning) + wpa_supplicant_cancel_sched_scan(wpa_s); + + for (other_ssid = wpa_s->conf->ssid; other_ssid; + other_ssid = other_ssid->next) { + was_disabled = other_ssid->disabled; + if (was_disabled == 2) + continue; /* do not change persistent P2P group + * data */ + + other_ssid->disabled = 1; + + if (was_disabled != other_ssid->disabled) + wpas_notify_network_enabled_changed( + wpa_s, other_ssid); + } + if (wpa_s->current_ssid) + wpa_supplicant_deauthenticate( + wpa_s, WLAN_REASON_DEAUTH_LEAVING); + } else if (ssid->disabled != 2) { + if (ssid == wpa_s->current_ssid) + wpa_supplicant_deauthenticate( + wpa_s, WLAN_REASON_DEAUTH_LEAVING); + + was_disabled = ssid->disabled; + + ssid->disabled = 1; + + if (was_disabled != ssid->disabled) { + wpas_notify_network_enabled_changed(wpa_s, ssid); + if (wpa_s->sched_scanning) { + wpa_printf(MSG_DEBUG, "Stop ongoing sched_scan " + "to remove network from filters"); + wpa_supplicant_cancel_sched_scan(wpa_s); + wpa_supplicant_req_scan(wpa_s, 0, 0); + } + } + } +} + + +/** + * wpa_supplicant_select_network - Attempt association with a network + * @wpa_s: wpa_supplicant structure for a network interface + * @ssid: wpa_ssid structure for a configured network or %NULL for any network + */ +void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid) +{ + + struct wpa_ssid *other_ssid; + int disconnected = 0; + + if (ssid && ssid != wpa_s->current_ssid && wpa_s->current_ssid) { + if (wpa_s->wpa_state >= WPA_AUTHENTICATING) + wpa_s->own_disconnect_req = 1; + wpa_supplicant_deauthenticate( + wpa_s, WLAN_REASON_DEAUTH_LEAVING); + disconnected = 1; + } + + if (ssid) + wpas_clear_temp_disabled(wpa_s, ssid, 1); + + /* + * Mark all other networks disabled or mark all networks enabled if no + * network specified. + */ + for (other_ssid = wpa_s->conf->ssid; other_ssid; + other_ssid = other_ssid->next) { + int was_disabled = other_ssid->disabled; + if (was_disabled == 2) + continue; /* do not change persistent P2P group data */ + + other_ssid->disabled = ssid ? (ssid->id != other_ssid->id) : 0; + if (was_disabled && !other_ssid->disabled) + wpas_clear_temp_disabled(wpa_s, other_ssid, 0); + + if (was_disabled != other_ssid->disabled) + wpas_notify_network_enabled_changed(wpa_s, other_ssid); + } + + if (ssid && ssid == wpa_s->current_ssid && wpa_s->current_ssid) { + /* We are already associated with the selected network */ + wpa_printf(MSG_DEBUG, "Already associated with the " + "selected network - do nothing"); + return; + } + + if (ssid) { + wpa_s->current_ssid = ssid; + eapol_sm_notify_config(wpa_s->eapol, NULL, NULL); + wpa_s->connect_without_scan = + (ssid->mode == WPAS_MODE_MESH) ? ssid : NULL; + + /* + * Don't optimize next scan freqs since a new ESS has been + * selected. + */ + os_free(wpa_s->next_scan_freqs); + wpa_s->next_scan_freqs = NULL; + } else { + wpa_s->connect_without_scan = NULL; + } + + wpa_s->disconnected = 0; + wpa_s->reassociate = 1; + + if (wpa_s->connect_without_scan || + wpa_supplicant_fast_associate(wpa_s) != 1) { + wpa_s->scan_req = NORMAL_SCAN_REQ; + wpa_supplicant_req_scan(wpa_s, 0, disconnected ? 100000 : 0); + } + + if (ssid) + wpas_notify_network_selected(wpa_s, ssid); +} + +/** + * wpa_supplicant_set_ap_scan - Set AP scan mode for interface + * @wpa_s: wpa_supplicant structure for a network interface + * @ap_scan: AP scan mode + * Returns: 0 if succeed or -1 if ap_scan has an invalid value + * + */ +int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, int ap_scan) +{ + + int old_ap_scan; + + if (ap_scan < 0 || ap_scan > 2) + return -1; + + if (ap_scan == 2 && os_strcmp(wpa_s->driver->name, "nl80211") == 0) { + wpa_printf(MSG_INFO, + "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures"); + } + +#ifdef ANDROID + if (ap_scan == 2 && ap_scan != wpa_s->conf->ap_scan && + wpa_s->wpa_state >= WPA_ASSOCIATING && + wpa_s->wpa_state < WPA_COMPLETED) { + wpa_printf(MSG_ERROR, "ap_scan = %d (%d) rejected while " + "associating", wpa_s->conf->ap_scan, ap_scan); + return 0; + } +#endif /* ANDROID */ + + old_ap_scan = wpa_s->conf->ap_scan; + wpa_s->conf->ap_scan = ap_scan; + + if (old_ap_scan != wpa_s->conf->ap_scan) + wpas_notify_ap_scan_changed(wpa_s); + + return 0; +} + + +/** + * wpa_supplicant_set_bss_expiration_age - Set BSS entry expiration age + * @wpa_s: wpa_supplicant structure for a network interface + * @expire_age: Expiration age in seconds + * Returns: 0 if succeed or -1 if expire_age has an invalid value + * + */ +int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s, + unsigned int bss_expire_age) +{ + if (bss_expire_age < 10) { + wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration age %u", + bss_expire_age); + return -1; + } + wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration age: %d sec", + bss_expire_age); + wpa_s->conf->bss_expiration_age = bss_expire_age; + + return 0; +} + + +/** + * wpa_supplicant_set_bss_expiration_count - Set BSS entry expiration scan count + * @wpa_s: wpa_supplicant structure for a network interface + * @expire_count: number of scans after which an unseen BSS is reclaimed + * Returns: 0 if succeed or -1 if expire_count has an invalid value + * + */ +int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s, + unsigned int bss_expire_count) +{ + if (bss_expire_count < 1) { + wpa_msg(wpa_s, MSG_ERROR, "Invalid bss expiration count %u", + bss_expire_count); + return -1; + } + wpa_msg(wpa_s, MSG_DEBUG, "Setting bss expiration scan count: %u", + bss_expire_count); + wpa_s->conf->bss_expiration_scan_count = bss_expire_count; + + return 0; +} + + +/** + * wpa_supplicant_set_scan_interval - Set scan interval + * @wpa_s: wpa_supplicant structure for a network interface + * @scan_interval: scan interval in seconds + * Returns: 0 if succeed or -1 if scan_interval has an invalid value + * + */ +int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s, + int scan_interval) +{ + if (scan_interval < 0) { + wpa_msg(wpa_s, MSG_ERROR, "Invalid scan interval %d", + scan_interval); + return -1; + } + wpa_msg(wpa_s, MSG_DEBUG, "Setting scan interval: %d sec", + scan_interval); + wpa_supplicant_update_scan_int(wpa_s, scan_interval); + + return 0; +} + + +/** + * wpa_supplicant_set_debug_params - Set global debug params + * @global: wpa_global structure + * @debug_level: debug level + * @debug_timestamp: determines if show timestamp in debug data + * @debug_show_keys: determines if show keys in debug data + * Returns: 0 if succeed or -1 if debug_level has wrong value + */ +int wpa_supplicant_set_debug_params(struct wpa_global *global, int debug_level, + int debug_timestamp, int debug_show_keys) +{ + + int old_level, old_timestamp, old_show_keys; + + /* check for allowed debuglevels */ + if (debug_level != MSG_EXCESSIVE && + debug_level != MSG_MSGDUMP && + debug_level != MSG_DEBUG && + debug_level != MSG_INFO && + debug_level != MSG_WARNING && + debug_level != MSG_ERROR) + return -1; + + old_level = wpa_debug_level; + old_timestamp = wpa_debug_timestamp; + old_show_keys = wpa_debug_show_keys; + + wpa_debug_level = debug_level; + wpa_debug_timestamp = debug_timestamp ? 1 : 0; + wpa_debug_show_keys = debug_show_keys ? 1 : 0; + + if (wpa_debug_level != old_level) + wpas_notify_debug_level_changed(global); + if (wpa_debug_timestamp != old_timestamp) + wpas_notify_debug_timestamp_changed(global); + if (wpa_debug_show_keys != old_show_keys) + wpas_notify_debug_show_keys_changed(global); + + return 0; +} + + +/** + * wpa_supplicant_get_ssid - Get a pointer to the current network structure + * @wpa_s: Pointer to wpa_supplicant data + * Returns: A pointer to the current network structure or %NULL on failure + */ +struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s) +{ + struct wpa_ssid *entry; + u8 ssid[SSID_MAX_LEN]; + int res; + size_t ssid_len; + u8 bssid[ETH_ALEN]; + int wired; + + res = wpa_drv_get_ssid(wpa_s, ssid); + if (res < 0) { + wpa_msg(wpa_s, MSG_WARNING, "Could not read SSID from " + "driver"); + return NULL; + } + ssid_len = res; + + if (wpa_drv_get_bssid(wpa_s, bssid) < 0) { + wpa_msg(wpa_s, MSG_WARNING, "Could not read BSSID from " + "driver"); + return NULL; + } + + wired = wpa_s->conf->ap_scan == 0 && + (wpa_s->drv_flags & WPA_DRIVER_FLAGS_WIRED); + + entry = wpa_s->conf->ssid; + while (entry) { + if (!wpas_network_disabled(wpa_s, entry) && + ((ssid_len == entry->ssid_len && + os_memcmp(ssid, entry->ssid, ssid_len) == 0) || wired) && + (!entry->bssid_set || + os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)) + return entry; +#ifdef CONFIG_WPS + if (!wpas_network_disabled(wpa_s, entry) && + (entry->key_mgmt & WPA_KEY_MGMT_WPS) && + (entry->ssid == NULL || entry->ssid_len == 0) && + (!entry->bssid_set || + os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0)) + return entry; +#endif /* CONFIG_WPS */ + + if (!wpas_network_disabled(wpa_s, entry) && entry->bssid_set && + entry->ssid_len == 0 && + os_memcmp(bssid, entry->bssid, ETH_ALEN) == 0) + return entry; + + entry = entry->next; + } + + return NULL; +} + + +static int select_driver(struct wpa_supplicant *wpa_s, int i) +{ + struct wpa_global *global = wpa_s->global; + + if (wpa_drivers[i]->global_init && global->drv_priv[i] == NULL) { + global->drv_priv[i] = wpa_drivers[i]->global_init(); + if (global->drv_priv[i] == NULL) { + wpa_printf(MSG_ERROR, "Failed to initialize driver " + "'%s'", wpa_drivers[i]->name); + return -1; + } + } + + wpa_s->driver = wpa_drivers[i]; + wpa_s->global_drv_priv = global->drv_priv[i]; + + return 0; +} + + +static int wpa_supplicant_set_driver(struct wpa_supplicant *wpa_s, + const char *name) +{ + int i; + size_t len; + const char *pos, *driver = name; + + if (wpa_s == NULL) + return -1; + + if (wpa_drivers[0] == NULL) { + wpa_msg(wpa_s, MSG_ERROR, "No driver interfaces build into " + "wpa_supplicant"); + return -1; + } + + if (name == NULL) { + /* default to first driver in the list */ + return select_driver(wpa_s, 0); + } + + do { + pos = os_strchr(driver, ','); + if (pos) + len = pos - driver; + else + len = os_strlen(driver); + + for (i = 0; wpa_drivers[i]; i++) { + if (os_strlen(wpa_drivers[i]->name) == len && + os_strncmp(driver, wpa_drivers[i]->name, len) == + 0) { + /* First driver that succeeds wins */ + if (select_driver(wpa_s, i) == 0) + return 0; + } + } + + driver = pos + 1; + } while (pos); + + wpa_msg(wpa_s, MSG_ERROR, "Unsupported driver '%s'", name); + return -1; +} + + +/** + * wpa_supplicant_rx_eapol - Deliver a received EAPOL frame to wpa_supplicant + * @ctx: Context pointer (wpa_s); this is the ctx variable registered + * with struct wpa_driver_ops::init() + * @src_addr: Source address of the EAPOL frame + * @buf: EAPOL data starting from the EAPOL header (i.e., no Ethernet header) + * @len: Length of the EAPOL data + * + * This function is called for each received EAPOL frame. Most driver + * interfaces rely on more generic OS mechanism for receiving frames through + * l2_packet, but if such a mechanism is not available, the driver wrapper may + * take care of received EAPOL frames and deliver them to the core supplicant + * code by calling this function. + */ +void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr, + const u8 *buf, size_t len) +{ + struct wpa_supplicant *wpa_s = ctx; + + wpa_hexdump(MSG_MSGDUMP, "RX EAPOL", buf, len); + +#ifdef CONFIG_PEERKEY + if (wpa_s->wpa_state > WPA_ASSOCIATED && wpa_s->current_ssid && + wpa_s->current_ssid->peerkey && + !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) && + wpa_sm_rx_eapol_peerkey(wpa_s->wpa, src_addr, buf, len) == 1) { + wpa_dbg(wpa_s, MSG_DEBUG, "RSN: Processed PeerKey EAPOL-Key"); + return; + } +#endif /* CONFIG_PEERKEY */ + + if (wpa_s->wpa_state < WPA_ASSOCIATED || + (wpa_s->last_eapol_matches_bssid && +#ifdef CONFIG_AP + !wpa_s->ap_iface && +#endif /* CONFIG_AP */ + os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) != 0)) { + /* + * There is possible race condition between receiving the + * association event and the EAPOL frame since they are coming + * through different paths from the driver. In order to avoid + * issues in trying to process the EAPOL frame before receiving + * association information, lets queue it for processing until + * the association event is received. This may also be needed in + * driver-based roaming case, so also use src_addr != BSSID as a + * trigger if we have previously confirmed that the + * Authenticator uses BSSID as the src_addr (which is not the + * case with wired IEEE 802.1X). + */ + os_null_printf("Not associated - Delay processing " + "of received EAPOL frame (state=%s bssid=" MACSTR ")\r\n", + wpa_supplicant_state_txt(wpa_s->wpa_state), + MAC2STR(wpa_s->bssid)); + wpabuf_free(wpa_s->pending_eapol_rx); + wpa_s->pending_eapol_rx = wpabuf_alloc_copy(buf, len); + if (wpa_s->pending_eapol_rx) { + os_get_reltime(&wpa_s->pending_eapol_rx_time); + os_memcpy(wpa_s->pending_eapol_rx_src, src_addr, + ETH_ALEN); + } + return; + } + + wpa_s->last_eapol_matches_bssid = + os_memcmp(src_addr, wpa_s->bssid, ETH_ALEN) == 0; + +#ifdef CONFIG_AP + if (wpa_s->ap_iface) { + wpa_supplicant_ap_rx_eapol(wpa_s, src_addr, buf, len); + return; + } +#endif /* CONFIG_AP */ + + if (wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) { + wpa_dbg(wpa_s, MSG_DEBUG, "Ignored received EAPOL frame since " + "no key management is configured"); + return; + } + + if (wpa_s->eapol_received == 0 && + (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE) || + !wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) || + wpa_s->wpa_state != WPA_COMPLETED) && + (wpa_s->current_ssid == NULL || + wpa_s->current_ssid->mode != IEEE80211_MODE_IBSS)) { + /* Timeout for completing IEEE 802.1X and WPA authentication */ + int timeout = 10; + + if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt) || + wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA || + wpa_s->key_mgmt == WPA_KEY_MGMT_WPS) { + /* Use longer timeout for IEEE 802.1X/EAP */ + timeout = 70; + } + +#ifdef CONFIG_WPS + if (wpa_s->current_ssid && wpa_s->current_bss && + (wpa_s->current_ssid->key_mgmt & WPA_KEY_MGMT_WPS) && + eap_is_wps_pin_enrollee(&wpa_s->current_ssid->eap)) { + /* + * Use shorter timeout if going through WPS AP iteration + * for PIN config method with an AP that does not + * advertise Selected Registrar. + */ + struct wpabuf *wps_ie; + + wps_ie = wpa_bss_get_vendor_ie_multi( + wpa_s->current_bss, WPS_IE_VENDOR_TYPE); + if (wps_ie && + !wps_is_addr_authorized(wps_ie, wpa_s->own_addr, 1)) + timeout = 10; + wpabuf_free(wps_ie); + } +#endif /* CONFIG_WPS */ + + wpa_supplicant_req_auth_timeout(wpa_s, timeout, 0); + } + wpa_s->eapol_received++; + + if (wpa_s->countermeasures) { + wpa_msg(wpa_s, MSG_INFO, "WPA: Countermeasures - dropped " + "EAPOL packet"); + return; + } + +#ifdef CONFIG_IBSS_RSN + if (wpa_s->current_ssid && + wpa_s->current_ssid->mode == WPAS_MODE_IBSS) { + ibss_rsn_rx_eapol(wpa_s->ibss_rsn, src_addr, buf, len); + return; + } +#endif /* CONFIG_IBSS_RSN */ + + /* Source address of the incoming EAPOL frame could be compared to the + * current BSSID. However, it is possible that a centralized + * Authenticator could be using another MAC address than the BSSID of + * an AP, so just allow any address to be used for now. The replies are + * still sent to the current BSSID (if available), though. */ + + os_memcpy(wpa_s->last_eapol_src, src_addr, ETH_ALEN); + if (!wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) && + eapol_sm_rx_eapol(wpa_s->eapol, src_addr, buf, len) > 0) + return; + wpa_drv_poll(wpa_s); + if (!(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE)) + wpa_sm_rx_eapol(wpa_s->wpa, src_addr, buf, len); + else if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) { + /* + * Set portValid = TRUE here since we are going to skip 4-way + * handshake processing which would normally set portValid. We + * need this to allow the EAPOL state machines to be completed + * without going through EAPOL-Key handshake. + */ + eapol_sm_notify_portValid(wpa_s->eapol, TRUE); + } +} + + +int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s) +{ + if ((!wpa_s->p2p_mgmt || + !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) && + !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_P2P_DEDICATED_INTERFACE)) { + l2_packet_deinit(wpa_s->l2); + wpa_s->l2 = l2_packet_init(wpa_s->ifname, + wpa_drv_get_mac_addr(wpa_s), + ETH_P_EAPOL, + wpa_supplicant_rx_eapol, wpa_s, 0); + if (wpa_s->l2 == NULL) + return -1; + } else { + const u8 *addr = wpa_drv_get_mac_addr(wpa_s); + if (addr) + os_memcpy(wpa_s->own_addr, addr, ETH_ALEN); + } + + if (wpa_s->l2 && l2_packet_get_own_addr(wpa_s->l2, wpa_s->own_addr)) { + wpa_msg(wpa_s, MSG_ERROR, "Failed to get own L2 address"); + return -1; + } + + wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr); + + return 0; +} + +#ifdef CONFIG_FULL_SUPPLICANT +static void wpa_supplicant_rx_eapol_bridge(void *ctx, const u8 *src_addr, + const u8 *buf, size_t len) +{ + struct wpa_supplicant *wpa_s = ctx; + const struct l2_ethhdr *eth; + + if (len < sizeof(*eth)) + return; + eth = (const struct l2_ethhdr *) buf; + + if (os_memcmp(eth->h_dest, wpa_s->own_addr, ETH_ALEN) != 0 && + !(eth->h_dest[0] & 0x01)) { + wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR + " (bridge - not for this interface - ignore)", + MAC2STR(src_addr), MAC2STR(eth->h_dest)); + return; + } + + wpa_dbg(wpa_s, MSG_DEBUG, "RX EAPOL from " MACSTR " to " MACSTR + " (bridge)", MAC2STR(src_addr), MAC2STR(eth->h_dest)); + wpa_supplicant_rx_eapol(wpa_s, src_addr, buf + sizeof(*eth), + len - sizeof(*eth)); +} +#endif + +/** + * wpa_supplicant_driver_init - Initialize driver interface parameters + * @wpa_s: Pointer to wpa_supplicant data + * Returns: 0 on success, -1 on failure + * + * This function is called to initialize driver interface parameters. + * wpa_drv_init() must have been called before this function to initialize the + * driver interface. + */ +int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s) +{ + static int interface_count = 0; + + os_null_printf("wpa_dInit\r\n"); + if (wpa_supplicant_update_mac_addr(wpa_s) < 0) + return -1; + + wpa_dbg(wpa_s, MSG_DEBUG, "Own MAC address: " MACSTR, + MAC2STR(wpa_s->own_addr)); + os_memcpy(wpa_s->perm_addr, wpa_s->own_addr, ETH_ALEN); + wpa_sm_set_own_addr(wpa_s->wpa, wpa_s->own_addr); + +#ifdef CONFIG_FULL_SUPPLICANT + if (wpa_s->bridge_ifname[0]) { + wpa_dbg(wpa_s, MSG_DEBUG, "Receiving packets from bridge " + "interface '%s'", wpa_s->bridge_ifname); + wpa_s->l2_br = l2_packet_init_bridge( + wpa_s->bridge_ifname, wpa_s->ifname, wpa_s->own_addr, + ETH_P_EAPOL, wpa_supplicant_rx_eapol_bridge, wpa_s, 1); + if (wpa_s->l2_br == NULL) { + wpa_msg(wpa_s, MSG_ERROR, "Failed to open l2_packet " + "connection for the bridge interface '%s'", + wpa_s->bridge_ifname); + return -1; + } + } +#endif + if (wpa_s->conf->ap_scan == 2 && + os_strcmp(wpa_s->driver->name, "nl80211") == 0) { + wpa_printf(MSG_INFO, + "Note: nl80211 driver interface is not designed to be used with ap_scan=2; this can result in connection failures"); + } + + wpa_clear_keys(wpa_s, NULL); + + /* Make sure that TKIP countermeasures are not left enabled (could + * happen if wpa_supplicant is killed during countermeasures. */ + wpa_drv_set_countermeasures(wpa_s, 0); + + wpa_dbg(wpa_s, MSG_DEBUG, "RSN: flushing PMKID list in the driver"); + wpa_drv_flush_pmkid(wpa_s); + + wpa_s->prev_scan_ssid = WILDCARD_SSID_SCAN; + wpa_s->prev_scan_wildcard = 0; + + if (wpa_supplicant_enabled_networks(wpa_s)) { + if (wpa_s->wpa_state == WPA_INTERFACE_DISABLED) { + wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); + interface_count = 0; + } + +#ifndef ANDROID + if (!wpa_s->p2p_mgmt && + wpa_supplicant_delayed_sched_scan(wpa_s, + interface_count % 3, + 100000)) + wpa_supplicant_req_scan(wpa_s, interface_count % 3, + 100000); +#endif /* ANDROID */ + + interface_count++; + } else + wpa_supplicant_set_state(wpa_s, WPA_INACTIVE); + + return 0; +} + +static struct wpa_supplicant * +wpa_supplicant_alloc(struct wpa_supplicant *parent) +{ + struct wpa_supplicant *wpa_s; + + wpa_s = os_zalloc(sizeof(*wpa_s)); + if (wpa_s == NULL) + return NULL; + wpa_s->scan_req = INITIAL_SCAN_REQ; + wpa_s->scan_interval = 5; + wpa_s->new_connection = 1; + wpa_s->parent = parent ? parent : wpa_s; + wpa_s->sched_scanning = 0; + + return wpa_s; +} + + +#ifdef CONFIG_HT_OVERRIDES + +static int wpa_set_htcap_mcs(struct wpa_supplicant *wpa_s, + struct ieee80211_ht_capabilities *htcaps, + struct ieee80211_ht_capabilities *htcaps_mask, + const char *ht_mcs) +{ + /* parse ht_mcs into hex array */ + int i; + const char *tmp = ht_mcs; + char *end = NULL; + + /* If ht_mcs is null, do not set anything */ + if (!ht_mcs) + return 0; + + /* This is what we are setting in the kernel */ + os_memset(&htcaps->supported_mcs_set, 0, IEEE80211_HT_MCS_MASK_LEN); + + wpa_msg(wpa_s, MSG_DEBUG, "set_htcap, ht_mcs -:%s:-", ht_mcs); + + for (i = 0; i < IEEE80211_HT_MCS_MASK_LEN; i++) { + errno = 0; + long v = strtol(tmp, &end, 16); + if (errno == 0) { + wpa_msg(wpa_s, MSG_DEBUG, + "htcap value[%i]: %ld end: %p tmp: %p", + i, v, end, tmp); + if (end == tmp) + break; + + htcaps->supported_mcs_set[i] = v; + tmp = end; + } else { + wpa_msg(wpa_s, MSG_ERROR, + "Failed to parse ht-mcs: %s, error: %s\n", + ht_mcs, strerror(errno)); + return -1; + } + } + + /* + * If we were able to parse any values, then set mask for the MCS set. + */ + if (i) { + os_memset(&htcaps_mask->supported_mcs_set, 0xff, + IEEE80211_HT_MCS_MASK_LEN - 1); + /* skip the 3 reserved bits */ + htcaps_mask->supported_mcs_set[IEEE80211_HT_MCS_MASK_LEN - 1] = + 0x1f; + } + + return 0; +} + + +static int wpa_disable_max_amsdu(struct wpa_supplicant *wpa_s, + struct ieee80211_ht_capabilities *htcaps, + struct ieee80211_ht_capabilities *htcaps_mask, + int disabled) +{ + le16 msk; + + wpa_msg(wpa_s, MSG_DEBUG, "set_disable_max_amsdu: %d", disabled); + + if (disabled == -1) + return 0; + + msk = host_to_le16(HT_CAP_INFO_MAX_AMSDU_SIZE); + htcaps_mask->ht_capabilities_info |= msk; + if (disabled) + htcaps->ht_capabilities_info &= msk; + else + htcaps->ht_capabilities_info |= msk; + + return 0; +} + + +static int wpa_set_ampdu_factor(struct wpa_supplicant *wpa_s, + struct ieee80211_ht_capabilities *htcaps, + struct ieee80211_ht_capabilities *htcaps_mask, + int factor) +{ + wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_factor: %d", factor); + + if (factor == -1) + return 0; + + if (factor < 0 || factor > 3) { + wpa_msg(wpa_s, MSG_ERROR, "ampdu_factor: %d out of range. " + "Must be 0-3 or -1", factor); + return -ERRINVAL; + } + + htcaps_mask->a_mpdu_params |= 0x3; /* 2 bits for factor */ + htcaps->a_mpdu_params &= ~0x3; + htcaps->a_mpdu_params |= factor & 0x3; + + return 0; +} + + +static int wpa_set_ampdu_density(struct wpa_supplicant *wpa_s, + struct ieee80211_ht_capabilities *htcaps, + struct ieee80211_ht_capabilities *htcaps_mask, + int density) +{ + wpa_msg(wpa_s, MSG_DEBUG, "set_ampdu_density: %d", density); + + if (density == -1) + return 0; + + if (density < 0 || density > 7) { + wpa_msg(wpa_s, MSG_ERROR, + "ampdu_density: %d out of range. Must be 0-7 or -1.", + density); + return -ERRINVAL; + } + + htcaps_mask->a_mpdu_params |= 0x1C; + htcaps->a_mpdu_params &= ~(0x1C); + htcaps->a_mpdu_params |= (density << 2) & 0x1C; + + return 0; +} + + +static int wpa_set_disable_ht40(struct wpa_supplicant *wpa_s, + struct ieee80211_ht_capabilities *htcaps, + struct ieee80211_ht_capabilities *htcaps_mask, + int disabled) +{ + /* Masking these out disables HT40 */ + le16 msk = host_to_le16(HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET | + HT_CAP_INFO_SHORT_GI40MHZ); + + wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ht40: %d", disabled); + + if (disabled) + htcaps->ht_capabilities_info &= ~msk; + else + htcaps->ht_capabilities_info |= msk; + + htcaps_mask->ht_capabilities_info |= msk; + + return 0; +} + + +static int wpa_set_disable_sgi(struct wpa_supplicant *wpa_s, + struct ieee80211_ht_capabilities *htcaps, + struct ieee80211_ht_capabilities *htcaps_mask, + int disabled) +{ + /* Masking these out disables SGI */ + le16 msk = host_to_le16(HT_CAP_INFO_SHORT_GI20MHZ | + HT_CAP_INFO_SHORT_GI40MHZ); + + wpa_msg(wpa_s, MSG_DEBUG, "set_disable_sgi: %d", disabled); + + if (disabled) + htcaps->ht_capabilities_info &= ~msk; + else + htcaps->ht_capabilities_info |= msk; + + htcaps_mask->ht_capabilities_info |= msk; + + return 0; +} + + +static int wpa_set_disable_ldpc(struct wpa_supplicant *wpa_s, + struct ieee80211_ht_capabilities *htcaps, + struct ieee80211_ht_capabilities *htcaps_mask, + int disabled) +{ + /* Masking these out disables LDPC */ + le16 msk = host_to_le16(HT_CAP_INFO_LDPC_CODING_CAP); + + wpa_msg(wpa_s, MSG_DEBUG, "set_disable_ldpc: %d", disabled); + + if (disabled) + htcaps->ht_capabilities_info &= ~msk; + else + htcaps->ht_capabilities_info |= msk; + + htcaps_mask->ht_capabilities_info |= msk; + + return 0; +} + + +void wpa_supplicant_apply_ht_overrides( + struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, + struct wpa_driver_associate_params *params) +{ + struct ieee80211_ht_capabilities *htcaps; + struct ieee80211_ht_capabilities *htcaps_mask; + + if (!ssid) + return; + + params->disable_ht = ssid->disable_ht; + if (!params->htcaps || !params->htcaps_mask) + return; + + htcaps = (struct ieee80211_ht_capabilities *) params->htcaps; + htcaps_mask = (struct ieee80211_ht_capabilities *) params->htcaps_mask; + wpa_set_htcap_mcs(wpa_s, htcaps, htcaps_mask, ssid->ht_mcs); + wpa_disable_max_amsdu(wpa_s, htcaps, htcaps_mask, + ssid->disable_max_amsdu); + wpa_set_ampdu_factor(wpa_s, htcaps, htcaps_mask, ssid->ampdu_factor); + wpa_set_ampdu_density(wpa_s, htcaps, htcaps_mask, ssid->ampdu_density); + wpa_set_disable_ht40(wpa_s, htcaps, htcaps_mask, ssid->disable_ht40); + wpa_set_disable_sgi(wpa_s, htcaps, htcaps_mask, ssid->disable_sgi); + wpa_set_disable_ldpc(wpa_s, htcaps, htcaps_mask, ssid->disable_ldpc); + + if (ssid->ht40_intolerant) { + le16 bit = host_to_le16(HT_CAP_INFO_40MHZ_INTOLERANT); + htcaps->ht_capabilities_info |= bit; + htcaps_mask->ht_capabilities_info |= bit; + } +} + +#endif /* CONFIG_HT_OVERRIDES */ + + +#ifdef CONFIG_VHT_OVERRIDES +void wpa_supplicant_apply_vht_overrides( + struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, + struct wpa_driver_associate_params *params) +{ + struct ieee80211_vht_capabilities *vhtcaps; + struct ieee80211_vht_capabilities *vhtcaps_mask; + + if (!ssid) + return; + + params->disable_vht = ssid->disable_vht; + + vhtcaps = (void *) params->vhtcaps; + vhtcaps_mask = (void *) params->vhtcaps_mask; + + if (!vhtcaps || !vhtcaps_mask) + return; + + vhtcaps->vht_capabilities_info = ssid->vht_capa; + vhtcaps_mask->vht_capabilities_info = ssid->vht_capa_mask; + +#ifdef CONFIG_HT_OVERRIDES + /* if max ampdu is <= 3, we have to make the HT cap the same */ + if (ssid->vht_capa_mask & VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) { + int max_ampdu; + + max_ampdu = (ssid->vht_capa & + VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX) >> + VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MAX_SHIFT; + + max_ampdu = max_ampdu < 3 ? max_ampdu : 3; + wpa_set_ampdu_factor(wpa_s, + (void *) params->htcaps, + (void *) params->htcaps_mask, + max_ampdu); + } +#endif /* CONFIG_HT_OVERRIDES */ + +#define OVERRIDE_MCS(i) \ + if (ssid->vht_tx_mcs_nss_ ##i >= 0) { \ + vhtcaps_mask->vht_supported_mcs_set.tx_map |= \ + 3 << 2 * (i - 1); \ + vhtcaps->vht_supported_mcs_set.tx_map |= \ + ssid->vht_tx_mcs_nss_ ##i << 2 * (i - 1); \ + } \ + if (ssid->vht_rx_mcs_nss_ ##i >= 0) { \ + vhtcaps_mask->vht_supported_mcs_set.rx_map |= \ + 3 << 2 * (i - 1); \ + vhtcaps->vht_supported_mcs_set.rx_map |= \ + ssid->vht_rx_mcs_nss_ ##i << 2 * (i - 1); \ + } + + OVERRIDE_MCS(1); + OVERRIDE_MCS(2); + OVERRIDE_MCS(3); + OVERRIDE_MCS(4); + OVERRIDE_MCS(5); + OVERRIDE_MCS(6); + OVERRIDE_MCS(7); + OVERRIDE_MCS(8); +} +#endif /* CONFIG_VHT_OVERRIDES */ + +static struct wpa_radio * radio_add_interface(struct wpa_supplicant *wpa_s, + const char *rn) +{ + struct wpa_supplicant *iface = wpa_s->global->ifaces; + struct wpa_radio *radio; + + while (rn && iface) { + radio = iface->radio; + if (radio && os_strcmp(rn, radio->name) == 0) { + wpa_printf(MSG_DEBUG, "Add interface %s to existing radio %s", + wpa_s->ifname, rn); + dl_list_add(&radio->ifaces, &wpa_s->radio_list); + return radio; + } + + iface = iface->next; + } + + radio = os_zalloc(sizeof(*radio)); + if (radio == NULL) + return NULL; + + if (rn) + os_strlcpy(radio->name, rn, sizeof(radio->name)); + dl_list_init(&radio->ifaces); + dl_list_init(&radio->work); + dl_list_add(&radio->ifaces, &wpa_s->radio_list); + + return radio; +} + + +static void radio_work_free(struct wpa_radio_work *work) +{ + if (work->wpa_s->scan_work == work) { + /* This should not really happen. */ + wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as scan_work", + work->type, work, work->started); + work->wpa_s->scan_work = NULL; + } + +#ifdef CONFIG_P2P + if (work->wpa_s->p2p_scan_work == work) { + /* This should not really happen. */ + wpa_dbg(work->wpa_s, MSG_INFO, "Freeing radio work '%s'@%p (started=%d) that is marked as p2p_scan_work", + work->type, work, work->started); + work->wpa_s->p2p_scan_work = NULL; + } +#endif /* CONFIG_P2P */ + + dl_list_del(&work->list); + os_free(work); +} + + +static void radio_start_next_work(void *eloop_ctx, void *timeout_ctx) +{ + struct wpa_radio *radio = eloop_ctx; + struct wpa_radio_work *work; + struct os_reltime now, diff; + struct wpa_supplicant *wpa_s; + + work = dl_list_first(&radio->work, struct wpa_radio_work, list); + if (work == NULL) + return; + + if (work->started) + return; /* already started and still in progress */ + + wpa_s = dl_list_first(&radio->ifaces, struct wpa_supplicant, + radio_list); + if (wpa_s && wpa_s->radio->external_scan_running) { + wpa_printf(MSG_DEBUG, "Delay radio work start until externally triggered scan completes"); + return; + } + + os_get_reltime(&now); + os_reltime_sub(&now, &work->time, &diff); + wpa_dbg(work->wpa_s, MSG_DEBUG, "Starting radio work '%s'@%p after %ld.%06ld second wait", + work->type, work, diff.sec, diff.usec); + work->started = 1; + work->time = now; + work->cb(work, 0); +} + + +/* + * This function removes both started and pending radio works running on + * the provided interface's radio. + * Prior to the removal of the radio work, its callback (cb) is called with + * deinit set to be 1. Each work's callback is responsible for clearing its + * internal data and restoring to a correct state. + * @wpa_s: wpa_supplicant data + * @type: type of works to be removed + * @remove_all: 1 to remove all the works on this radio, 0 to remove only + * this interface's works. + */ +void radio_remove_works(struct wpa_supplicant *wpa_s, + const char *type, int remove_all) +{ + struct wpa_radio_work *work, *tmp; + struct wpa_radio *radio = wpa_s->radio; + + dl_list_for_each_safe(work, tmp, &radio->work, struct wpa_radio_work, + list) { + if (type && os_strcmp(type, work->type) != 0) + continue; + + /* skip other ifaces' works */ + if (!remove_all && work->wpa_s != wpa_s) + continue; + + wpa_dbg(wpa_s, MSG_DEBUG, "Remove radio work '%s'@%p%s", + work->type, work, work->started ? " (started)" : ""); + work->cb(work, 1); + radio_work_free(work); + } + + /* in case we removed the started work */ + radio_work_check_next(wpa_s); +} + + +static void radio_remove_interface(struct wpa_supplicant *wpa_s) +{ + struct wpa_radio *radio = wpa_s->radio; + + if (!radio) + return; + + dl_list_del(&wpa_s->radio_list); + radio_remove_works(wpa_s, NULL, 0); + wpa_s->radio = NULL; + if (!dl_list_empty(&radio->ifaces)) + return; /* Interfaces remain for this radio */ + + wpa_printf(MSG_DEBUG, "Remove radio %s", radio->name); + eloop_cancel_timeout(radio_start_next_work, radio, NULL); + os_free(radio); +} + + +void radio_work_check_next(struct wpa_supplicant *wpa_s) +{ + struct wpa_radio *radio = wpa_s->radio; + + if (dl_list_empty(&radio->work)) + return; + if (wpa_s->ext_work_in_progress) { + wpa_printf(MSG_DEBUG, + "External radio work in progress - delay start of pending item"); + return; + } + eloop_cancel_timeout(radio_start_next_work, radio, NULL); + + eloop_register_timeout(0, 0, radio_start_next_work, radio, NULL); +} + + +/** + * radio_add_work - Add a radio work item + * @wpa_s: Pointer to wpa_supplicant data + * @freq: Frequency of the offchannel operation in MHz or 0 + * @type: Unique identifier for each type of work + * @next: Force as the next work to be executed + * @cb: Callback function for indicating when radio is available + * @ctx: Context pointer for the work (work->ctx in cb()) + * Returns: 0 on success, -1 on failure + * + * This function is used to request time for an operation that requires + * exclusive radio control. Once the radio is available, the registered callback + * function will be called. radio_work_done() must be called once the exclusive + * radio operation has been completed, so that the radio is freed for other + * operations. The special case of deinit=1 is used to free the context data + * during interface removal. That does not allow the callback function to start + * the radio operation, i.e., it must free any resources allocated for the radio + * work and return. + * + * The @freq parameter can be used to indicate a single channel on which the + * offchannel operation will occur. This may allow multiple radio work + * operations to be performed in parallel if they apply for the same channel. + * Setting this to 0 indicates that the work item may use multiple channels or + * requires exclusive control of the radio. + */ +int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq, + const char *type, int next, + void (*cb)(struct wpa_radio_work *work, int deinit), + void *ctx) +{ + struct wpa_radio_work *work; + int was_empty; + + work = os_zalloc(sizeof(*work)); + if (work == NULL) + return -1; + + os_get_reltime(&work->time); + work->freq = freq; + work->type = type; + work->wpa_s = wpa_s; + work->cb = cb; + work->ctx = ctx; + + was_empty = dl_list_empty(&wpa_s->radio->work); + if (next) + dl_list_add(&wpa_s->radio->work, &work->list); + else + dl_list_add_tail(&wpa_s->radio->work, &work->list); + if (was_empty) { + wpa_dbg(wpa_s, MSG_DEBUG, "First radio work item in the queue - schedule start immediately"); + radio_work_check_next(wpa_s); + } + + return 0; +} + + +/** + * radio_work_done - Indicate that a radio work item has been completed + * @work: Completed work + * + * This function is called once the callback function registered with + * radio_add_work() has completed its work. + */ +void radio_work_done(struct wpa_radio_work *work) +{ + struct wpa_supplicant *wpa_s = work->wpa_s; + struct os_reltime now, diff; + unsigned int started = work->started; + struct wpa_driver_scan_params *params = work->ctx; + + os_get_reltime(&now); + os_reltime_sub(&now, &work->time, &diff); + + if(params) + { + wpa_scan_free_params(params); + } + wpa_dbg(wpa_s, MSG_DEBUG, "Radio work '%s'@%p %s in %ld.%06ld seconds", + work->type, work, started ? "done" : "canceled", + diff.sec, diff.usec); + radio_work_free(work); + + if (started) + radio_work_check_next(wpa_s); +} + + +struct wpa_radio_work * +radio_work_pending(struct wpa_supplicant *wpa_s, const char *type) +{ + struct wpa_radio_work *work; + struct wpa_radio *radio = wpa_s->radio; + + dl_list_for_each(work, &radio->work, struct wpa_radio_work, list) { + if (work->wpa_s == wpa_s && os_strcmp(work->type, type) == 0) + return work; + } + + return NULL; +} + +static int wpas_init_driver(struct wpa_supplicant *wpa_s, + struct wpa_interface *iface) +{ + const char *ifname, *driver, *rn; + + driver = iface->driver; +next_driver: + if (wpa_supplicant_set_driver(wpa_s, driver) < 0) + return -1; + + wpa_s->drv_priv = wpa_drv_init(wpa_s, wpa_s->ifname); + if (wpa_s->drv_priv == NULL) { + const char *pos; + pos = driver ? os_strchr(driver, ',') : NULL; + if (pos) { + wpa_dbg(wpa_s, MSG_DEBUG, "Failed to initialize " + "driver interface - try next driver wrapper"); + driver = pos + 1; + goto next_driver; + } + wpa_msg(wpa_s, MSG_ERROR, "Failed to initialize driver " + "interface"); + return -1; + } + if (wpa_drv_set_param(wpa_s, wpa_s->conf->driver_param) < 0) { + wpa_msg(wpa_s, MSG_ERROR, "Driver interface rejected " + "driver_param '%s'", wpa_s->conf->driver_param); + return -1; + } + + ifname = wpa_drv_get_ifname(wpa_s); + if (ifname && os_strcmp(ifname, wpa_s->ifname) != 0) { + wpa_dbg(wpa_s, MSG_DEBUG, "Driver interface replaced " + "interface name with '%s'", ifname); + os_strlcpy(wpa_s->ifname, ifname, sizeof(wpa_s->ifname)); + } + + rn = wpa_driver_get_radio_name(wpa_s); + if (rn && rn[0] == '\0') + rn = NULL; + + wpa_s->radio = radio_add_interface(wpa_s, rn); + if (wpa_s->radio == NULL) + return -1; + + return 0; +} + + +static int wpa_supplicant_init_iface(struct wpa_supplicant *wpa_s, + struct wpa_interface *iface) +{ + struct wpa_driver_capa capa; + int capa_res; + + if (iface->confname) { +#ifdef CONFIG_BACKEND_FILE + wpa_s->confname = os_rel2abs_path(iface->confname); + if (wpa_s->confname == NULL) { + wpa_printf(MSG_ERROR, "Failed to get absolute path " + "for configuration file '%s'.", + iface->confname); + return -1; + } + wpa_printf(MSG_DEBUG, "Configuration file '%s' -> '%s'", + iface->confname, wpa_s->confname); +#else /* CONFIG_BACKEND_FILE */ + wpa_s->confname = os_strdup(iface->confname); +#endif /* CONFIG_BACKEND_FILE */ + wpa_s->conf = wpa_config_read(wpa_s->confname, NULL); + if (wpa_s->conf == NULL) { + wpa_printf(MSG_ERROR, "Failed to read or parse " + "configuration '%s'.", wpa_s->confname); + return -1; + } + wpa_s->confanother = os_rel2abs_path(iface->confanother); + wpa_config_read(wpa_s->confanother, wpa_s->conf); + + /* + * Override ctrl_interface and driver_param if set on command + * line. + */ + if (iface->ctrl_interface) { + os_free(wpa_s->conf->ctrl_interface); + wpa_s->conf->ctrl_interface = + os_strdup(iface->ctrl_interface); + } + + if (iface->driver_param) { + os_free(wpa_s->conf->driver_param); + wpa_s->conf->driver_param = + os_strdup(iface->driver_param); + } + + if (iface->p2p_mgmt && !iface->ctrl_interface) { + os_free(wpa_s->conf->ctrl_interface); + wpa_s->conf->ctrl_interface = NULL; + } + } else{ + wpa_s->conf = wpa_config_read(NULL, NULL); + if(wpa_s->conf == NULL){ + return -1; + } + /* + * Override ctrl_interface and driver_param if set on command + * line. + */ + if (iface->ctrl_interface) { + os_free(wpa_s->conf->ctrl_interface); + wpa_s->conf->ctrl_interface = + os_strdup(iface->ctrl_interface); + } + + if (iface->driver_param) { + os_free(wpa_s->conf->driver_param); + wpa_s->conf->driver_param = + os_strdup(iface->driver_param); + } + + if (iface->p2p_mgmt && !iface->ctrl_interface) { + os_free(wpa_s->conf->ctrl_interface); + wpa_s->conf->ctrl_interface = NULL; + } + } + + if (wpa_s->conf == NULL) { + wpa_printf(MSG_ERROR, "\nNo configuration found."); + return -1; + } + + if (iface->ifname == NULL) { + wpa_printf(MSG_ERROR, "\nInterface name is required."); + return -1; + } + if (os_strlen(iface->ifname) >= sizeof(wpa_s->ifname)) { + wpa_printf(MSG_ERROR, "\nToo long interface name '%s'.", + iface->ifname); + return -1; + } + os_strlcpy(wpa_s->ifname, iface->ifname, sizeof(wpa_s->ifname)); + +#ifdef CONFIG_FULL_SUPPLICANT + if (iface->bridge_ifname) { + if (os_strlen(iface->bridge_ifname) >= + sizeof(wpa_s->bridge_ifname)) { + wpa_printf(MSG_ERROR, "\nToo long bridge interface " + "name '%s'.", iface->bridge_ifname); + return -1; + } + os_strlcpy(wpa_s->bridge_ifname, iface->bridge_ifname, + sizeof(wpa_s->bridge_ifname)); + } +#endif + + /* RSNA Supplicant Key Management - INITIALIZE */ + eapol_sm_notify_portEnabled(wpa_s->eapol, FALSE); + eapol_sm_notify_portValid(wpa_s->eapol, FALSE); + + /* Initialize driver interface and register driver event handler before + * L2 receive handler so that association events are processed before + * EAPOL-Key packets if both become available for the same select() + * call. */ + if (wpas_init_driver(wpa_s, iface) < 0) + return -1; + + if (wpa_supplicant_init_wpa(wpa_s) < 0) + return -1; + + wpa_sm_set_ifname(wpa_s->wpa, wpa_s->ifname, +#ifdef CONFIG_FULL_SUPPLICANT + wpa_s->bridge_ifname[0] ? wpa_s->bridge_ifname : +#endif + NULL); + wpa_sm_set_fast_reauth(wpa_s->wpa, wpa_s->conf->fast_reauth); + + if (wpa_s->conf->dot11RSNAConfigPMKLifetime && + wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_LIFETIME, + wpa_s->conf->dot11RSNAConfigPMKLifetime)) { + wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for " + "dot11RSNAConfigPMKLifetime"); + return -1; + } + + if (wpa_s->conf->dot11RSNAConfigPMKReauthThreshold && + wpa_sm_set_param(wpa_s->wpa, RSNA_PMK_REAUTH_THRESHOLD, + wpa_s->conf->dot11RSNAConfigPMKReauthThreshold)) { + wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for " + "dot11RSNAConfigPMKReauthThreshold"); + return -1; + } + + if (wpa_s->conf->dot11RSNAConfigSATimeout && + wpa_sm_set_param(wpa_s->wpa, RSNA_SA_TIMEOUT, + wpa_s->conf->dot11RSNAConfigSATimeout)) { + wpa_msg(wpa_s, MSG_ERROR, "Invalid WPA parameter value for " + "dot11RSNAConfigSATimeout"); + return -1; + } + + wpa_s->hw.modes = wpa_drv_get_hw_feature_data(wpa_s, + &wpa_s->hw.num_modes, + &wpa_s->hw.flags); + if (wpa_s->hw.modes) { + u16 i; + + for (i = 0; i < wpa_s->hw.num_modes; i++) { + if (wpa_s->hw.modes[i].vht_capab) { + wpa_s->hw_capab = CAPAB_VHT; + break; + } + + if (wpa_s->hw.modes[i].ht_capab & + HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) + wpa_s->hw_capab = CAPAB_HT40; + else if (wpa_s->hw.modes[i].ht_capab && + wpa_s->hw_capab == CAPAB_NO_HT_VHT) + wpa_s->hw_capab = CAPAB_HT; + } + } + + capa_res = wpa_drv_get_capa(wpa_s, &capa); + if (capa_res == 0) { + wpa_s->drv_capa_known = 1; + wpa_s->drv_flags = capa.flags; + wpa_s->drv_enc = capa.enc; + wpa_s->drv_smps_modes = capa.smps_modes; + wpa_s->drv_rrm_flags = capa.rrm_flags; + wpa_s->probe_resp_offloads = capa.probe_resp_offloads; + wpa_s->max_scan_ssids = capa.max_scan_ssids; + wpa_s->max_sched_scan_ssids = capa.max_sched_scan_ssids; + wpa_s->sched_scan_supported = capa.sched_scan_supported; + wpa_s->max_match_sets = capa.max_match_sets; + wpa_s->max_remain_on_chan = capa.max_remain_on_chan; + wpa_s->max_stations = capa.max_stations; + wpa_s->extended_capa = capa.extended_capa; + wpa_s->extended_capa_mask = capa.extended_capa_mask; + wpa_s->extended_capa_len = capa.extended_capa_len; + wpa_s->num_multichan_concurrent = + capa.num_multichan_concurrent; + wpa_s->wmm_ac_supported = capa.wmm_ac_supported; + + if (capa.mac_addr_rand_scan_supported) + wpa_s->mac_addr_rand_supported |= MAC_ADDR_RAND_SCAN; + if (wpa_s->sched_scan_supported && + capa.mac_addr_rand_sched_scan_supported) + wpa_s->mac_addr_rand_supported |= + (MAC_ADDR_RAND_SCHED_SCAN | MAC_ADDR_RAND_PNO); + } + if (wpa_s->max_remain_on_chan == 0) + wpa_s->max_remain_on_chan = 1000; + +#ifdef CONFIG_P2P + /* + * Only take p2p_mgmt parameters when P2P Device is supported. + * Doing it here as it determines whether l2_packet_init() will be done + * during wpa_supplicant_driver_init(). + */ + if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) + wpa_s->p2p_mgmt = iface->p2p_mgmt; + else + iface->p2p_mgmt = 1; +#endif + + if (wpa_s->num_multichan_concurrent == 0) + wpa_s->num_multichan_concurrent = 1; + + if (wpa_supplicant_driver_init(wpa_s) < 0) + return -1; + +#ifdef CONFIG_TDLS + if ((!iface->p2p_mgmt || + !(wpa_s->drv_flags & + WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE)) && + wpa_tdls_init(wpa_s->wpa)) + return -1; +#endif /* CONFIG_TDLS */ + + if (wpa_s->conf->country[0] && wpa_s->conf->country[1] && + wpa_drv_set_country(wpa_s, wpa_s->conf->country)) { + wpa_dbg(wpa_s, MSG_DEBUG, "Failed to set country"); + return -1; + } + + if (wpas_wps_init(wpa_s)) + return -1; + + if (wpa_supplicant_init_eapol(wpa_s) < 0) + return -1; + wpa_sm_set_eapol(wpa_s->wpa, wpa_s->eapol); + +#ifdef CONFIG_CTRL_IFACE + wpa_s->ctrl_iface = wpa_supplicant_ctrl_iface_init(wpa_s); + if (wpa_s->ctrl_iface == NULL) { + wpa_printf(MSG_ERROR, + "Failed to initialize control interface '%s'.\n" + "You may have another wpa_supplicant process " + "already running or the file was\n" + "left by an unclean termination of wpa_supplicant " + "in which case you will need\n" + "to manually remove this file before starting " + "wpa_supplicant again.\n", + wpa_s->conf->ctrl_interface); + return -1; + } +#endif + +#ifdef CONFIG_P2P + if (iface->p2p_mgmt && wpas_p2p_init(wpa_s->global, wpa_s) < 0) { + wpa_msg(wpa_s, MSG_ERROR, "Failed to init P2P"); + return -1; + } +#endif + + if (wpa_bss_init(wpa_s) < 0) + return -1; + + return 0; +} + + +static void wpa_supplicant_deinit_iface(struct wpa_supplicant *wpa_s, + int notify, int terminate) +{ + struct wpa_global *global = wpa_s->global; + struct wpa_supplicant *iface, *prev; + +#ifdef CONFIG_P2P + if (wpa_s == wpa_s->parent) + wpas_p2p_group_remove(wpa_s, "*"); +#endif + + iface = global->ifaces; + while (iface) { + if (iface == wpa_s || iface->parent != wpa_s) { + iface = iface->next; + continue; + } + wpa_printf(MSG_DEBUG, + "Remove remaining child interface %s from parent %s", + iface->ifname, wpa_s->ifname); + prev = iface; + iface = iface->next; + wpa_supplicant_remove_iface(global, prev, terminate); + } + + wpa_s->disconnected = 1; + if (wpa_s->drv_priv) { + wpa_supplicant_deauthenticate(wpa_s, + WLAN_REASON_DEAUTH_LEAVING); + + wpa_drv_set_countermeasures(wpa_s, 0); + wpa_clear_keys(wpa_s, NULL); + } + + wpa_supplicant_cleanup(wpa_s); +#ifdef CONFIG_P2P + wpas_p2p_deinit_iface(wpa_s); +#endif + wpas_ctrl_radio_work_flush(wpa_s); + radio_remove_interface(wpa_s); + +#ifdef CONFIG_FST + if (wpa_s->fst) { + fst_detach(wpa_s->fst); + wpa_s->fst = NULL; + } + if (wpa_s->received_mb_ies) { + wpabuf_free(wpa_s->received_mb_ies); + wpa_s->received_mb_ies = NULL; + } +#endif /* CONFIG_FST */ + + if (wpa_s->drv_priv) + wpa_drv_deinit(wpa_s); + + if (notify) + wpas_notify_iface_removed(wpa_s); + + if (terminate) + wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TERMINATING); + +#ifdef CONFIG_CTRL_IFACE + if (wpa_s->ctrl_iface) { + wpa_supplicant_ctrl_iface_deinit(wpa_s->ctrl_iface); + wpa_s->ctrl_iface = NULL; + } +#endif + +#ifdef CONFIG_MESH + if (wpa_s->ifmsh) { + wpa_supplicant_mesh_iface_deinit(wpa_s, wpa_s->ifmsh); + wpa_s->ifmsh = NULL; + } +#endif /* CONFIG_MESH */ + + if (wpa_s->conf != NULL) { + wpa_config_free(wpa_s->conf); + wpa_s->conf = NULL; + } + + os_free(wpa_s->ssids_from_scan_req); + wpa_s->ssids_from_scan_req = 0; + wpas_connect_ssid = 0; + + os_free(wpa_s); +} + + +/** + * wpa_supplicant_add_iface - Add a new network interface + * @global: Pointer to global data from wpa_supplicant_init() + * @iface: Interface configuration options + * @parent: Parent interface or %NULL to assign new interface as parent + * Returns: Pointer to the created interface or %NULL on failure + * + * This function is used to add new network interfaces for %wpa_supplicant. + * This can be called before wpa_supplicant_run() to add interfaces before the + * main event loop has been started. In addition, new interfaces can be added + * dynamically while %wpa_supplicant is already running. This could happen, + * e.g., when a hotplug network adapter is inserted. + */ +struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global, + struct wpa_interface *iface, + struct wpa_supplicant *parent) +{ + struct wpa_supplicant *wpa_s; + struct wpa_interface t_iface; + struct wpa_ssid *ssid; + + if (global == NULL || iface == NULL) + return NULL; + + wpa_s = wpa_supplicant_alloc(parent); + if (wpa_s == NULL) + return NULL; + + wpa_s->global = global; + + t_iface = *iface; + if (wpa_supplicant_init_iface(wpa_s, &t_iface)) { + wpa_printf(MSG_DEBUG, "Failed to add interface %s", + iface->ifname); + wpa_supplicant_deinit_iface(wpa_s, 0, 0); + return NULL; + } + + if (iface->p2p_mgmt == 0) { + /* Notify the control interfaces about new iface */ + if (wpas_notify_iface_added(wpa_s)) { + wpa_supplicant_deinit_iface(wpa_s, 1, 0); + return NULL; + } + + for (ssid = wpa_s->conf->ssid; ssid; ssid = ssid->next) + wpas_notify_network_added(wpa_s, ssid); + } + + wpa_s->next = global->ifaces; + global->ifaces = wpa_s; + + wpa_dbg(wpa_s, MSG_DEBUG, "Added interface %s", wpa_s->ifname); + wpa_supplicant_set_state(wpa_s, WPA_DISCONNECTED); + +#ifdef CONFIG_P2P + if (wpa_s->global->p2p == NULL && + !wpa_s->global->p2p_disabled && !wpa_s->conf->p2p_disabled && + (wpa_s->drv_flags & WPA_DRIVER_FLAGS_DEDICATED_P2P_DEVICE) && + wpas_p2p_add_p2pdev_interface( + wpa_s, wpa_s->global->params.conf_p2p_dev) < 0) { + wpa_printf(MSG_INFO, + "P2P: Failed to enable P2P Device interface"); + /* Try to continue without. P2P will be disabled. */ + } +#endif /* CONFIG_P2P */ + + return wpa_s; +} + + +/** + * wpa_supplicant_remove_iface - Remove a network interface + * @global: Pointer to global data from wpa_supplicant_init() + * @wpa_s: Pointer to the network interface to be removed + * Returns: 0 if interface was removed, -1 if interface was not found + * + * This function can be used to dynamically remove network interfaces from + * %wpa_supplicant, e.g., when a hotplug network adapter is ejected. In + * addition, this function is used to remove all remaining interfaces when + * %wpa_supplicant is terminated. + */ +int wpa_supplicant_remove_iface(struct wpa_global *global, + struct wpa_supplicant *wpa_s, + int terminate) +{ + struct wpa_supplicant *prev; +#ifdef CONFIG_MESH + unsigned int mesh_if_created = wpa_s->mesh_if_created; + char *ifname = NULL; +#endif /* CONFIG_MESH */ + + /* Remove interface from the global list of interfaces */ + prev = global->ifaces; + if (prev == wpa_s) { + global->ifaces = wpa_s->next; + } else { + while (prev && prev->next != wpa_s) + prev = prev->next; + if (prev == NULL) + return -1; + prev->next = wpa_s->next; + } + + wpa_dbg(wpa_s, MSG_DEBUG, "Removing interface %s", wpa_s->ifname); + +#ifdef CONFIG_MESH + if (mesh_if_created) { + ifname = os_strdup(wpa_s->ifname); + if (ifname == NULL) { + wpa_dbg(wpa_s, MSG_ERROR, + "mesh: Failed to malloc ifname"); + return -1; + } + } +#endif /* CONFIG_MESH */ + + if (global->p2p_group_formation == wpa_s) + global->p2p_group_formation = NULL; + if (global->p2p_invite_group == wpa_s) + global->p2p_invite_group = NULL; + wpa_supplicant_deinit_iface(wpa_s, 1, terminate); + +#ifdef CONFIG_MESH + if (mesh_if_created) { + wpa_drv_if_remove(global->ifaces, WPA_IF_MESH, ifname); + os_free(ifname); + } +#endif /* CONFIG_MESH */ + + return 0; +} + +/** + * wpa_supplicant_get_iface - Get a new network interface + * @global: Pointer to global data from wpa_supplicant_init() + * @ifname: Interface name + * Returns: Pointer to the interface or %NULL if not found + */ +struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global, + const char *ifname) +{ + struct wpa_supplicant *wpa_s; + + for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) { + if (os_strcmp(wpa_s->ifname, ifname) == 0) + return wpa_s; + } + return NULL; +} + + +#ifndef CONFIG_NO_WPA_MSG +static const char * wpa_supplicant_msg_ifname_cb(void *ctx) +{ + struct wpa_supplicant *wpa_s = ctx; + if (wpa_s == NULL) + return NULL; + return wpa_s->ifname; +} +#endif /* CONFIG_NO_WPA_MSG */ + + +#ifndef WPA_SUPPLICANT_CLEANUP_INTERVAL +#define WPA_SUPPLICANT_CLEANUP_INTERVAL 10 +#endif /* WPA_SUPPLICANT_CLEANUP_INTERVAL */ + +/* Periodic cleanup tasks */ +static void wpas_periodic(void *eloop_ctx, void *timeout_ctx) +{ + struct wpa_global *global = eloop_ctx; + struct wpa_supplicant *wpa_s; + + eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0, + wpas_periodic, global, NULL); + +#ifdef CONFIG_P2P + if (global->p2p) + p2p_expire_peers(global->p2p); +#endif /* CONFIG_P2P */ + + for (wpa_s = global->ifaces; wpa_s; wpa_s = wpa_s->next) { + wpa_bss_flush_by_age(wpa_s, wpa_s->conf->bss_expiration_age); +#ifdef CONFIG_AP + ap_periodic(wpa_s); +#endif /* CONFIG_AP */ + } +} + + +/** + * wpa_supplicant_init - Initialize %wpa_supplicant + * @params: Parameters for %wpa_supplicant + * Returns: Pointer to global %wpa_supplicant data, or %NULL on failure + * + * This function is used to initialize %wpa_supplicant. After successful + * initialization, the returned data pointer can be used to add and remove + * network interfaces, and eventually, to deinitialize %wpa_supplicant. + */ +struct wpa_global * wpa_supplicant_init(struct wpa_params *params) +{ + struct wpa_global *global; + int ret, i; + + if (params == NULL) + return NULL; + +#ifndef CONFIG_NO_WPA_MSG + wpa_msg_register_ifname_cb(wpa_supplicant_msg_ifname_cb); +#endif /* CONFIG_NO_WPA_MSG */ + + if (params->wpa_debug_file_path) + wpa_debug_open_file(params->wpa_debug_file_path); + else + wpa_debug_setup_stdout(); + if (params->wpa_debug_syslog) + wpa_debug_open_syslog(); + if (params->wpa_debug_tracing) { + ret = wpa_debug_open_linux_tracing(); + if (ret) { + wpa_printf(MSG_ERROR, + "Failed to enable trace logging"); + return NULL; + } + } + + global = os_zalloc(sizeof(*global)); + if (global == NULL) + return NULL; + + dl_list_init(&global->p2p_srv_bonjour); + dl_list_init(&global->p2p_srv_upnp); + global->params.daemonize = params->daemonize; + global->params.wait_for_monitor = params->wait_for_monitor; + global->params.dbus_ctrl_interface = params->dbus_ctrl_interface; + if (params->pid_file) + global->params.pid_file = os_strdup(params->pid_file); + if (params->ctrl_interface) + global->params.ctrl_interface = + os_strdup(params->ctrl_interface); + if (params->ctrl_interface_group) + global->params.ctrl_interface_group = + os_strdup(params->ctrl_interface_group); + if (params->override_driver) + global->params.override_driver = + os_strdup(params->override_driver); + if (params->override_ctrl_interface) + global->params.override_ctrl_interface = + os_strdup(params->override_ctrl_interface); +#ifdef CONFIG_P2P + if (params->conf_p2p_dev) + global->params.conf_p2p_dev = + os_strdup(params->conf_p2p_dev); +#endif /* CONFIG_P2P */ + wpa_debug_level = global->params.wpa_debug_level = + params->wpa_debug_level; + wpa_debug_show_keys = global->params.wpa_debug_show_keys = + params->wpa_debug_show_keys; + wpa_debug_timestamp = global->params.wpa_debug_timestamp = + params->wpa_debug_timestamp; + + wpa_printf(MSG_DEBUG, "wpa_supplicant v" VERSION_STR); + + random_init(params->entropy_file); + + global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global); + if (global->ctrl_iface == NULL) { + wpa_supplicant_deinit(global); + return NULL; + } + + if (wpas_notify_supplicant_initialized(global)) { + wpa_supplicant_deinit(global); + return NULL; + } + + for (i = 0; wpa_drivers[i]; i++) + global->drv_count++; + if (global->drv_count == 0) { + wpa_printf(MSG_ERROR, "No drivers enabled"); + wpa_supplicant_deinit(global); + return NULL; + } + global->drv_priv = os_calloc(global->drv_count, sizeof(void *)); + if (global->drv_priv == NULL) { + wpa_supplicant_deinit(global); + return NULL; + } + +#ifdef CONFIG_WIFI_DISPLAY + if (wifi_display_init(global) < 0) { + wpa_printf(MSG_ERROR, "Failed to initialize Wi-Fi Display"); + wpa_supplicant_deinit(global); + return NULL; + } +#endif /* CONFIG_WIFI_DISPLAY */ + + eloop_register_timeout(WPA_SUPPLICANT_CLEANUP_INTERVAL, 0, + wpas_periodic, global, NULL); + + return global; +} + + +/** + * wpa_supplicant_run - Run the %wpa_supplicant main event loop + * @global: Pointer to global data from wpa_supplicant_init() + * Returns: 0 after successful event loop run, -1 on failure + * + * This function starts the main event loop and continues running as long as + * there are any remaining events. In most cases, this function is running as + * long as the %wpa_supplicant process in still in use. + */ +int wpa_supplicant_run(struct wpa_global *global) +{ + wpa_hostapd_queue_poll((uint32_t)0xff); + + return 0; +} + + +/** + * wpa_supplicant_deinit - Deinitialize %wpa_supplicant + * @global: Pointer to global data from wpa_supplicant_init() + * + * This function is called to deinitialize %wpa_supplicant and to free all + * allocated resources. Remaining network interfaces will also be removed. + */ +void wpa_supplicant_deinit(struct wpa_global *global) +{ + int i; + + if (global == NULL) + return; + + eloop_cancel_timeout(wpas_periodic, global, NULL); + eloop_remove_sta_added_signals(); + +#ifdef CONFIG_WIFI_DISPLAY + wifi_display_deinit(global); +#endif /* CONFIG_WIFI_DISPLAY */ + + while (global->ifaces) + wpa_supplicant_remove_iface(global, global->ifaces, 1); + + if (global->ctrl_iface) + wpa_supplicant_global_ctrl_iface_deinit(global->ctrl_iface); + + wpas_notify_supplicant_deinitialized(global); + + for (i = 0; wpa_drivers[i] && global->drv_priv; i++) { + if (!global->drv_priv[i]) + continue; + wpa_drivers[i]->global_deinit(global->drv_priv[i]); + } + os_free(global->drv_priv); + + random_deinit(); + + //eloop_remove_sta_added_signals(); + eloop_free_resource(); + + if (global->params.pid_file) { + os_daemonize_terminate(global->params.pid_file); + os_free(global->params.pid_file); + } + os_free(global->params.ctrl_interface); + os_free(global->params.ctrl_interface_group); + os_free(global->params.override_driver); + os_free(global->params.override_ctrl_interface); +#ifdef CONFIG_P2P + os_free(global->params.conf_p2p_dev); +#endif /* CONFIG_P2P */ + + os_free(global->p2p_disallow_freq.range); + os_free(global->p2p_go_avoid_freq.range); + os_free(global->add_psk); + + os_free(global); + wpa_debug_close_syslog(); + wpa_debug_close_file(); + wpa_debug_close_linux_tracing(); +} + + +void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s) +{ + if ((wpa_s->conf->changed_parameters & CFG_CHANGED_COUNTRY) && + wpa_s->conf->country[0] && wpa_s->conf->country[1]) { + char country[3]; + country[0] = wpa_s->conf->country[0]; + country[1] = wpa_s->conf->country[1]; + country[2] = '\0'; + if (wpa_drv_set_country(wpa_s, country) < 0) { + wpa_printf(MSG_ERROR, "Failed to set country code " + "'%s'", country); + } + } + +#ifdef CONFIG_WPS + wpas_wps_update_config(wpa_s); +#endif /* CONFIG_WPS */ + wpas_p2p_update_config(wpa_s); + wpa_s->conf->changed_parameters = 0; +} + + +void add_freq(int *freqs, int *num_freqs, int freq) +{ + int i; + + for (i = 0; i < *num_freqs; i++) { + if (freqs[i] == freq) + return; + } + + freqs[*num_freqs] = freq; + (*num_freqs)++; +} + +static int * get_bss_freqs_in_ess(struct wpa_supplicant *wpa_s) +{ + struct wpa_bss *bss, *cbss; + const int max_freqs = 10; + int *freqs; + int num_freqs = 0; + + freqs = os_calloc(max_freqs + 1, sizeof(int)); + if (freqs == NULL) + return NULL; + + cbss = wpa_s->current_bss; + + dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { + if (bss == cbss) + continue; + if (bss->ssid_len == cbss->ssid_len && + os_memcmp(bss->ssid, cbss->ssid, bss->ssid_len) == 0 /*&& + wpa_blacklist_get(wpa_s, bss->bssid) == NULL*/) { + add_freq(freqs, &num_freqs, bss->freq); + if (num_freqs == max_freqs) + break; + } + } + + if (num_freqs == 0) { + os_free(freqs); + freqs = NULL; + } + + return freqs; +} + +void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid) +{ + int timeout; + int count = 0; + int *freqs = NULL; + + wpas_connect_work_done(wpa_s); + + /* + * Remove possible authentication timeout since the connection failed. + */ + eloop_cancel_timeout(wpa_supplicant_timeout, wpa_s, NULL); + + /* + * There is no point in blacklisting the AP if this event is + * generated based on local request to disconnect. + */ + if (wpa_s->own_disconnect_req) { + wpa_s->own_disconnect_req = 0; + wpa_dbg(wpa_s, MSG_DEBUG, + "Ignore connection failure due to local request to disconnect"); + return; + } + if (wpa_s->disconnected) { + wpa_dbg(wpa_s, MSG_DEBUG, "Ignore connection failure " + "indication since interface has been put into " + "disconnected state"); + return; + } + + /* + * Add the failed BSSID into the blacklist and speed up next scan + * attempt if there could be other APs that could accept association. + * The current blacklist count indicates how many times we have tried + * connecting to this AP and multiple attempts mean that other APs are + * either not available or has already been tried, so that we can start + * increasing the delay here to avoid constant scanning. + */ + count = wpa_blacklist_add(wpa_s, bssid); + if (count == 1 && wpa_s->current_bss) { + /* + * This BSS was not in the blacklist before. If there is + * another BSS available for the same ESS, we should try that + * next. Otherwise, we may as well try this one once more + * before allowing other, likely worse, ESSes to be considered. + */ + freqs = get_bss_freqs_in_ess(wpa_s); + if (freqs) { + wpa_dbg(wpa_s, MSG_DEBUG, "Another BSS in this ESS " + "has been seen; try it next"); + wpa_blacklist_add(wpa_s, bssid); + /* + * On the next scan, go through only the known channels + * used in this ESS based on previous scans to speed up + * common load balancing use case. + */ + os_free(wpa_s->next_scan_freqs); + wpa_s->next_scan_freqs = freqs; + } + } + + /* + * Add previous failure count in case the temporary blacklist was + * cleared due to no other BSSes being available. + */ + count += wpa_s->extra_blacklist_count; + + if (count > 3 && wpa_s->current_ssid) { + wpa_printf(MSG_DEBUG, "Continuous association failures - " + "consider temporary network disabling"); + wpas_auth_failed(wpa_s, "CONN_FAILED"); + } + + switch (count) { + case 1: + timeout = 100; + break; + case 2: + timeout = 500; + break; + case 3: + timeout = 1000; + break; + case 4: + timeout = 5000; + break; + default: + timeout = 10000; + break; + } + + wpa_dbg(wpa_s, MSG_DEBUG, "Blacklist count %d --> request scan in %d " + "ms", count, timeout); + + /* + * TODO: if more than one possible AP is available in scan results, + * could try the other ones before requesting a new scan. + */ + wpa_supplicant_req_scan(wpa_s, timeout / 1000, + 1000 * (timeout % 1000)); +} + + +int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s) +{ + return wpa_s->conf->ap_scan == 2 || + (wpa_s->drv_flags & WPA_DRIVER_FLAGS_BSS_SELECTION); +} + +int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) +{ + int i; + unsigned int drv_enc; + + if (wpa_s->p2p_mgmt) + return 1; /* no normal network profiles on p2p_mgmt interface */ + + if (ssid == NULL) + return 1; + + if (ssid->disabled) + return 1; + + if (wpa_s->drv_capa_known) + drv_enc = wpa_s->drv_enc; + else + drv_enc = (unsigned int) -1; + + for (i = 0; i < NUM_WEP_KEYS; i++) { + size_t len = ssid->wep_key_len[i]; + if (len == 0) + continue; + if (len == 5 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP40)) + continue; + if (len == 13 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP104)) + continue; + if (len == 16 && (drv_enc & WPA_DRIVER_CAPA_ENC_WEP128)) + continue; + return 1; /* invalid WEP key */ + } + + if (wpa_key_mgmt_wpa_psk(ssid->key_mgmt) && !ssid->psk_set && + (!ssid->passphrase || ssid->ssid_len != 0) && !ssid->ext_psk && + !ssid->mem_only_psk) + return 1; + + return 0; +} + + +int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid) +{ +#ifdef CONFIG_IEEE80211W + if (ssid == NULL || ssid->ieee80211w == MGMT_FRAME_PROTECTION_DEFAULT) { + if (wpa_s->conf->pmf == MGMT_FRAME_PROTECTION_OPTIONAL && + !(wpa_s->drv_enc & WPA_DRIVER_CAPA_ENC_BIP)) { + /* + * Driver does not support BIP -- ignore pmf=1 default + * since the connection with PMF would fail and the + * configuration does not require PMF to be enabled. + */ + return NO_MGMT_FRAME_PROTECTION; + } + + return wpa_s->conf->pmf; + } + + return ssid->ieee80211w; +#else /* CONFIG_IEEE80211W */ + return NO_MGMT_FRAME_PROTECTION; +#endif /* CONFIG_IEEE80211W */ +} + + +int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s) +{ + if (wpa_s->global->conc_pref == WPA_CONC_PREF_P2P) + return 1; + if (wpa_s->global->conc_pref == WPA_CONC_PREF_STA) + return 0; + return -1; +} + + +void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason) +{ + struct wpa_ssid *ssid = wpa_s->current_ssid; + int dur; + struct os_reltime now; + + if (ssid == NULL) { + wpa_printf(MSG_DEBUG, "Authentication failure but no known " + "SSID block"); + return; + } + + if (ssid->key_mgmt == WPA_KEY_MGMT_WPS) + return; + + ssid->auth_failures++; + +#ifdef CONFIG_P2P + if (ssid->p2p_group && + (wpa_s->p2p_in_provisioning || wpa_s->show_group_started)) { + /* + * Skip the wait time since there is a short timeout on the + * connection to a P2P group. + */ + return; + } +#endif /* CONFIG_P2P */ + + if (ssid->auth_failures > 50) + dur = 300; + else if (ssid->auth_failures > 10) + dur = 120; + else if (ssid->auth_failures > 5) + dur = 90; + else if (ssid->auth_failures > 3) + dur = 60; + else if (ssid->auth_failures > 2) + dur = 30; + else if (ssid->auth_failures > 1) + dur = 20; + else + dur = 10; + + if (ssid->auth_failures > 1 && + wpa_key_mgmt_wpa_ieee8021x(ssid->key_mgmt)) + dur += os_random() % (ssid->auth_failures * 10); + + os_get_reltime(&now); + if (now.sec + dur <= ssid->disabled_until.sec) + return; + + ssid->disabled_until.sec = now.sec + dur; + + wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_TEMP_DISABLED + "id=%d ssid=\"%s\" auth_failures=%u duration=%d reason=%s", + ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len), + ssid->auth_failures, dur, reason); +} + + +void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid, int clear_failures) +{ + if (ssid == NULL) + return; + + if (ssid->disabled_until.sec) { + wpa_msg(wpa_s, MSG_INFO, WPA_EVENT_REENABLED + "id=%d ssid=\"%s\"", + ssid->id, wpa_ssid_txt(ssid->ssid, ssid->ssid_len)); + } + ssid->disabled_until.sec = 0; + ssid->disabled_until.usec = 0; + if (clear_failures) + ssid->auth_failures = 0; +} + + +int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid) +{ + size_t i; + + if (wpa_s->disallow_aps_bssid == NULL) + return 0; + + for (i = 0; i < wpa_s->disallow_aps_bssid_count; i++) { + if (os_memcmp(wpa_s->disallow_aps_bssid + i * ETH_ALEN, + bssid, ETH_ALEN) == 0) + return 1; + } + + return 0; +} + + +int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid, + size_t ssid_len) +{ + size_t i; + + if (wpa_s->disallow_aps_ssid == NULL || ssid == NULL) + return 0; + + for (i = 0; i < wpa_s->disallow_aps_ssid_count; i++) { + struct wpa_ssid_value *s = &wpa_s->disallow_aps_ssid[i]; + if (ssid_len == s->ssid_len && + os_memcmp(ssid, s->ssid, ssid_len) == 0) + return 1; + } + + return 0; +} + + +/** + * wpas_request_connection - Request a new connection + * @wpa_s: Pointer to the network interface + * + * This function is used to request a new connection to be found. It will mark + * the interface to allow reassociation and request a new scan to find a + * suitable network to connect to. + */ +void wpas_request_connection(struct wpa_supplicant *wpa_s) +{ + wpa_s->normal_scans = 0; + wpa_s->scan_req = NORMAL_SCAN_REQ; + wpa_supplicant_reinit_autoscan(wpa_s); + wpa_s->extra_blacklist_count = 0; + wpa_s->disconnected = 0; + wpa_s->reassociate = 1; + + if (wpa_supplicant_fast_associate(wpa_s) != 1) + wpa_supplicant_req_scan(wpa_s, 0, 0); + else + wpa_s->reattach = 0; +} + +void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title, + struct wpa_used_freq_data *freqs_data, + unsigned int len) +{ +} + +/* + * Find the operating frequencies of any of the virtual interfaces that + * are using the same radio as the current interface, and in addition, get + * information about the interface types that are using the frequency. + */ +int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s, + struct wpa_used_freq_data *freqs_data, + unsigned int len) +{ + struct wpa_supplicant *ifs; + u8 bssid[ETH_ALEN]; + int freq; + unsigned int idx = 0, i; + + wpa_dbg(wpa_s, MSG_DEBUG, + "Determining shared radio frequencies (max len %u)", len); + os_memset(freqs_data, 0, sizeof(struct wpa_used_freq_data) * len); + + dl_list_for_each(ifs, &wpa_s->radio->ifaces, struct wpa_supplicant, + radio_list) { + if (idx == len) + break; + + if (ifs->current_ssid == NULL || ifs->assoc_freq == 0) + continue; + + if (ifs->current_ssid->mode == WPAS_MODE_AP || + ifs->current_ssid->mode == WPAS_MODE_P2P_GO || + ifs->current_ssid->mode == WPAS_MODE_MESH) + freq = ifs->current_ssid->frequency; + else if (wpa_drv_get_bssid(ifs, bssid) == 0) + freq = ifs->assoc_freq; + else + continue; + + /* Hold only distinct freqs */ + for (i = 0; i < idx; i++) + if (freqs_data[i].freq == freq) + break; + + if (i == idx) + freqs_data[idx++].freq = freq; + + if (ifs->current_ssid->mode == WPAS_MODE_INFRA) { + freqs_data[i].flags |= ifs->current_ssid->p2p_group ? + WPA_FREQ_USED_BY_P2P_CLIENT : + WPA_FREQ_USED_BY_INFRA_STATION; + } + } + + dump_freq_data(wpa_s, "completed iteration", freqs_data, idx); + return idx; +} + + +/* + * Find the operating frequencies of any of the virtual interfaces that + * are using the same radio as the current interface. + */ +int get_shared_radio_freqs(struct wpa_supplicant *wpa_s, + int *freq_array, unsigned int len) +{ + struct wpa_used_freq_data *freqs_data; + int num, i; + + os_memset(freq_array, 0, sizeof(int) * len); + + freqs_data = os_calloc(len, sizeof(struct wpa_used_freq_data)); + if (!freqs_data) + return -1; + + num = get_shared_radio_freqs_data(wpa_s, freqs_data, len); + for (i = 0; i < num; i++) + freq_array[i] = freqs_data[i].freq; + + os_free(freqs_data); + + return num; +} + + +static void wpas_rrm_neighbor_rep_timeout_handler(void *data, void *user_ctx) +{ + struct rrm_data *rrm = data; + + if (!rrm->notify_neighbor_rep) { + wpa_printf(MSG_ERROR, + "RRM: Unexpected neighbor report timeout"); + return; + } + + wpa_printf(MSG_DEBUG, "RRM: Notifying neighbor report - NONE"); + rrm->notify_neighbor_rep(rrm->neighbor_rep_cb_ctx, NULL); + + rrm->notify_neighbor_rep = NULL; + rrm->neighbor_rep_cb_ctx = NULL; +} + + +/* + * wpas_rrm_reset - Clear and reset all RRM data in wpa_supplicant + * @wpa_s: Pointer to wpa_supplicant + */ +void wpas_rrm_reset(struct wpa_supplicant *wpa_s) +{ + wpa_s->rrm.rrm_used = 0; + + eloop_cancel_timeout(wpas_rrm_neighbor_rep_timeout_handler, &wpa_s->rrm, + NULL); + if (wpa_s->rrm.notify_neighbor_rep) + wpas_rrm_neighbor_rep_timeout_handler(&wpa_s->rrm, NULL); + wpa_s->rrm.next_neighbor_rep_token = 1; +} + + +/* + * wpas_rrm_process_neighbor_rep - Handle incoming neighbor report + * @wpa_s: Pointer to wpa_supplicant + * @report: Neighbor report buffer, prefixed by a 1-byte dialog token + * @report_len: Length of neighbor report buffer + */ +void wpas_rrm_process_neighbor_rep(struct wpa_supplicant *wpa_s, + const u8 *report, size_t report_len) +{ + struct wpabuf *neighbor_rep; + + wpa_hexdump(MSG_DEBUG, "RRM: New Neighbor Report", report, report_len); + if (report_len < 1) + return; + + if (report[0] != wpa_s->rrm.next_neighbor_rep_token - 1) { + wpa_printf(MSG_DEBUG, + "RRM: Discarding neighbor report with token %d (expected %d)", + report[0], wpa_s->rrm.next_neighbor_rep_token - 1); + return; + } + + eloop_cancel_timeout(wpas_rrm_neighbor_rep_timeout_handler, &wpa_s->rrm, + NULL); + + if (!wpa_s->rrm.notify_neighbor_rep) { + wpa_printf(MSG_ERROR, "RRM: Unexpected neighbor report"); + return; + } + + /* skipping the first byte, which is only an id (dialog token) */ + neighbor_rep = wpabuf_alloc(report_len - 1); + if (neighbor_rep == NULL) + return; + wpabuf_put_data(neighbor_rep, report + 1, report_len - 1); + wpa_printf(MSG_DEBUG, "RRM: Notifying neighbor report (token = %d)", + report[0]); + wpa_s->rrm.notify_neighbor_rep(wpa_s->rrm.neighbor_rep_cb_ctx, + neighbor_rep); + wpa_s->rrm.notify_neighbor_rep = NULL; + wpa_s->rrm.neighbor_rep_cb_ctx = NULL; +} + + +/** + * wpas_rrm_send_neighbor_rep_request - Request a neighbor report from our AP + * @wpa_s: Pointer to wpa_supplicant + * @ssid: if not null, this is sent in the request. Otherwise, no SSID IE + * is sent in the request. + * @cb: Callback function to be called once the requested report arrives, or + * timed out after RRM_NEIGHBOR_REPORT_TIMEOUT seconds. + * In the former case, 'neighbor_rep' is a newly allocated wpabuf, and it's + * the requester's responsibility to free it. + * In the latter case NULL will be sent in 'neighbor_rep'. + * @cb_ctx: Context value to send the callback function + * Returns: 0 in case of success, negative error code otherwise + * + * In case there is a previous request which has not been answered yet, the + * new request fails. The caller may retry after RRM_NEIGHBOR_REPORT_TIMEOUT. + * Request must contain a callback function. + */ +int wpas_rrm_send_neighbor_rep_request(struct wpa_supplicant *wpa_s, + const struct wpa_ssid *ssid, + void (*cb)(void *ctx, + struct wpabuf *neighbor_rep), + void *cb_ctx) +{ + struct wpabuf *buf; + const u8 *rrm_ie; + + if (wpa_s->wpa_state != WPA_COMPLETED || wpa_s->current_ssid == NULL) { + wpa_printf(MSG_DEBUG, "RRM: No connection, no RRM."); + return -ERRNOTCONN; + } + + if (!wpa_s->rrm.rrm_used) { + wpa_printf(MSG_DEBUG, "RRM: No RRM in current connection."); + return -ERROPNOTSUPP; + } + + rrm_ie = wpa_bss_get_ie(wpa_s->current_bss, + WLAN_EID_RRM_ENABLED_CAPABILITIES); + if (!rrm_ie || !(wpa_s->current_bss->caps & IEEE80211_CAP_RRM) || + !(rrm_ie[2] & WLAN_RRM_CAPS_NEIGHBOR_REPORT)) { + wpa_printf(MSG_DEBUG, + "RRM: No network support for Neighbor Report."); + return -ERROPNOTSUPP; + } + + if (!cb) { + wpa_printf(MSG_DEBUG, + "RRM: Neighbor Report request must provide a callback."); + return -ERRINVAL; + } + + /* Refuse if there's a live request */ + if (wpa_s->rrm.notify_neighbor_rep) { + wpa_printf(MSG_DEBUG, + "RRM: Currently handling previous Neighbor Report."); + return -ERRBUSY; + } + + /* 3 = action category + action code + dialog token */ + buf = wpabuf_alloc(3 + (ssid ? 2 + ssid->ssid_len : 0)); + if (buf == NULL) { + wpa_printf(MSG_DEBUG, + "RRM: Failed to allocate Neighbor Report Request"); + return -ERRNOMEM; + } + + wpa_printf(MSG_DEBUG, "RRM: Neighbor report request (for %s), token=%d", + (ssid ? wpa_ssid_txt(ssid->ssid, ssid->ssid_len) : ""), + wpa_s->rrm.next_neighbor_rep_token); + + wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT); + wpabuf_put_u8(buf, WLAN_RRM_NEIGHBOR_REPORT_REQUEST); + wpabuf_put_u8(buf, wpa_s->rrm.next_neighbor_rep_token); + if (ssid) { + wpabuf_put_u8(buf, WLAN_EID_SSID); + wpabuf_put_u8(buf, ssid->ssid_len); + wpabuf_put_data(buf, ssid->ssid, ssid->ssid_len); + } + + wpa_s->rrm.next_neighbor_rep_token++; + + if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, wpa_s->bssid, + wpa_s->own_addr, wpa_s->bssid, + wpabuf_head(buf), wpabuf_len(buf), 0) < 0) { + wpa_printf(MSG_DEBUG, + "RRM: Failed to send Neighbor Report Request"); + wpabuf_free(buf); + return -ERRCANCELED; + } + + wpa_s->rrm.neighbor_rep_cb_ctx = cb_ctx; + wpa_s->rrm.notify_neighbor_rep = cb; + eloop_register_timeout(RRM_NEIGHBOR_REPORT_TIMEOUT, 0, + wpas_rrm_neighbor_rep_timeout_handler, + &wpa_s->rrm, NULL); + + wpabuf_free(buf); + return 0; +} + + +void wpas_rrm_handle_link_measurement_request(struct wpa_supplicant *wpa_s, + const u8 *src, + const u8 *frame, size_t len, + int rssi) +{ + struct wpabuf *buf; + const struct rrm_link_measurement_request *req; + struct rrm_link_measurement_report report; + + if (wpa_s->wpa_state != WPA_COMPLETED) { + wpa_printf(MSG_INFO, + "RRM: Ignoring link measurement request. Not associated"); + return; + } + + if (!wpa_s->rrm.rrm_used) { + wpa_printf(MSG_INFO, + "RRM: Ignoring link measurement request. Not RRM network"); + return; + } + + if (!(wpa_s->drv_rrm_flags & WPA_DRIVER_FLAGS_TX_POWER_INSERTION)) { + wpa_printf(MSG_INFO, + "RRM: Measurement report failed. TX power insertion not supported"); + return; + } + + req = (const struct rrm_link_measurement_request *) frame; + if (len < sizeof(*req)) { + wpa_printf(MSG_INFO, + "RRM: Link measurement report failed. Request too short"); + return; + } + + os_memset(&report, 0, sizeof(report)); + report.tpc.eid = WLAN_EID_TPC_REPORT; + report.tpc.len = 2; + report.rsni = 255; /* 255 indicates that RSNI is not available */ + report.dialog_token = req->dialog_token; + + /* + * It's possible to estimate RCPI based on RSSI in dBm. This + * calculation will not reflect the correct value for high rates, + * but it's good enough for Action frames which are transmitted + * with up to 24 Mbps rates. + */ + if (!rssi) + report.rcpi = 255; /* not available */ + else if (rssi < -110) + report.rcpi = 0; + else if (rssi > 0) + report.rcpi = 220; + else + report.rcpi = (rssi + 110) * 2; + + /* action_category + action_code */ + buf = wpabuf_alloc(2 + sizeof(report)); + if (buf == NULL) { + wpa_printf(MSG_ERROR, + "RRM: Link measurement report failed. Buffer allocation failed"); + return; + } + + wpabuf_put_u8(buf, WLAN_ACTION_RADIO_MEASUREMENT); + wpabuf_put_u8(buf, WLAN_RRM_LINK_MEASUREMENT_REPORT); + wpabuf_put_data(buf, &report, sizeof(report)); + wpa_hexdump(MSG_DEBUG, "RRM: Link measurement report:", + wpabuf_head(buf), wpabuf_len(buf)); + + if (wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, src, + wpa_s->own_addr, wpa_s->bssid, + wpabuf_head(buf), wpabuf_len(buf), 0)) { + wpa_printf(MSG_ERROR, + "RRM: Link measurement report failed. Send action failed"); + } + wpabuf_free(buf); +} diff --git a/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/wpa_supplicant_i.h b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/wpa_supplicant_i.h new file mode 100755 index 0000000..c76f8dc --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/wpa_supplicant_i.h @@ -0,0 +1,1135 @@ +/* + * wpa_supplicant - Internal definitions + * Copyright (c) 2003-2014, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef WPA_SUPPLICANT_I_H +#define WPA_SUPPLICANT_I_H + +#include "utils/list.h" +#include "common/defs.h" +#include "common/sae.h" +#include "common/wpa_ctrl.h" +#include "wps/wps_defs.h" +#include "config_ssid.h" +#include "wmm_ac.h" + +extern const char *const wpa_supplicant_version; +extern const char *const wpa_supplicant_license; +#ifndef CONFIG_NO_STDOUT_DEBUG +extern const char *const wpa_supplicant_full_license1; +extern const char *const wpa_supplicant_full_license2; +extern const char *const wpa_supplicant_full_license3; +extern const char *const wpa_supplicant_full_license4; +extern const char *const wpa_supplicant_full_license5; +#endif /* CONFIG_NO_STDOUT_DEBUG */ + +struct wpa_sm; +struct wpa_supplicant; +struct ibss_rsn; +struct scan_info; +struct wpa_bss; +struct wpa_scan_results; +struct hostapd_hw_modes; +struct wpa_driver_associate_params; + +/* + * Forward declarations of private structures used within the ctrl_iface + * backends. Other parts of wpa_supplicant do not have access to data stored in + * these structures. + */ +struct ctrl_iface_priv; +struct ctrl_iface_global_priv; +struct wpas_dbus_priv; + +/** + * struct wpa_interface - Parameters for wpa_supplicant_add_iface() + */ +struct wpa_interface { + /** + * confname - Configuration name (file or profile) name + * + * This can also be %NULL when a configuration file is not used. In + * that case, ctrl_interface must be set to allow the interface to be + * configured. + */ + const char *confname; + + /** + * confanother - Additional configuration name (file or profile) name + * + * This can also be %NULL when the additional configuration file is not + * used. + */ + const char *confanother; + + /** + * ctrl_interface - Control interface parameter + * + * If a configuration file is not used, this variable can be used to + * set the ctrl_interface parameter that would have otherwise been read + * from the configuration file. If both confname and ctrl_interface are + * set, ctrl_interface is used to override the value from configuration + * file. + */ + const char *ctrl_interface; + + /** + * driver - Driver interface name, or %NULL to use the default driver + */ + const char *driver; + + /** + * driver_param - Driver interface parameters + * + * If a configuration file is not used, this variable can be used to + * set the driver_param parameters that would have otherwise been read + * from the configuration file. If both confname and driver_param are + * set, driver_param is used to override the value from configuration + * file. + */ + const char *driver_param; + + /** + * ifname - Interface name + */ + const char *ifname; + + /** + * bridge_ifname - Optional bridge interface name + * + * If the driver interface (ifname) is included in a Linux bridge + * device, the bridge interface may need to be used for receiving EAPOL + * frames. This can be enabled by setting this variable to enable + * receiving of EAPOL frames from an additional interface. + */ + const char *bridge_ifname; + + /** + * p2p_mgmt - Interface used for P2P management (P2P Device operations) + * + * Indicates whether wpas_p2p_init() must be called for this interface. + * This is used only when the driver supports a dedicated P2P Device + * interface that is not a network interface. + */ + int p2p_mgmt; +}; + +/** + * struct wpa_params - Parameters for wpa_supplicant_init() + */ +struct wpa_params { + /** + * daemonize - Run %wpa_supplicant in the background + */ + int daemonize; + + /** + * wait_for_monitor - Wait for a monitor program before starting + */ + int wait_for_monitor; + + /** + * pid_file - Path to a PID (process ID) file + * + * If this and daemonize are set, process ID of the background process + * will be written to the specified file. + */ + char *pid_file; + + /** + * wpa_debug_level - Debugging verbosity level (e.g., MSG_INFO) + */ + int wpa_debug_level; + + /** + * wpa_debug_show_keys - Whether keying material is included in debug + * + * This parameter can be used to allow keying material to be included + * in debug messages. This is a security risk and this option should + * not be enabled in normal configuration. If needed during + * development or while troubleshooting, this option can provide more + * details for figuring out what is happening. + */ + int wpa_debug_show_keys; + + /** + * wpa_debug_timestamp - Whether to include timestamp in debug messages + */ + int wpa_debug_timestamp; + + /** + * ctrl_interface - Global ctrl_iface path/parameter + */ + char *ctrl_interface; + + /** + * ctrl_interface_group - Global ctrl_iface group + */ + char *ctrl_interface_group; + + /** + * dbus_ctrl_interface - Enable the DBus control interface + */ + int dbus_ctrl_interface; + + /** + * wpa_debug_file_path - Path of debug file or %NULL to use stdout + */ + const char *wpa_debug_file_path; + + /** + * wpa_debug_syslog - Enable log output through syslog + */ + int wpa_debug_syslog; + + /** + * wpa_debug_tracing - Enable log output through Linux tracing + */ + int wpa_debug_tracing; + + /** + * override_driver - Optional driver parameter override + * + * This parameter can be used to override the driver parameter in + * dynamic interface addition to force a specific driver wrapper to be + * used instead. + */ + char *override_driver; + + /** + * override_ctrl_interface - Optional ctrl_interface override + * + * This parameter can be used to override the ctrl_interface parameter + * in dynamic interface addition to force a control interface to be + * created. + */ + char *override_ctrl_interface; + + /** + * entropy_file - Optional entropy file + * + * This parameter can be used to configure wpa_supplicant to maintain + * its internal entropy store over restarts. + */ + char *entropy_file; + +#ifdef CONFIG_P2P + /** + * conf_p2p_dev - Configuration file used to hold the + * P2P Device configuration parameters. + * + * This can also be %NULL. In such a case, if a P2P Device dedicated + * interfaces is created, the main configuration file will be used. + */ + char *conf_p2p_dev; +#endif /* CONFIG_P2P */ + +}; + +struct p2p_srv_bonjour { + struct dl_list list; + struct wpabuf *query; + struct wpabuf *resp; +}; + +struct p2p_srv_upnp { + struct dl_list list; + u8 version; + char *service; +}; + +/** + * struct wpa_global - Internal, global data for all %wpa_supplicant interfaces + * + * This structure is initialized by calling wpa_supplicant_init() when starting + * %wpa_supplicant. + */ +struct wpa_global { + struct wpa_supplicant *ifaces; + struct wpa_params params; + struct ctrl_iface_global_priv *ctrl_iface; + struct wpas_dbus_priv *dbus; + void **drv_priv; + size_t drv_count; + struct os_time suspend_time; + struct p2p_data *p2p; + struct wpa_supplicant *p2p_init_wpa_s; + struct wpa_supplicant *p2p_group_formation; + struct wpa_supplicant *p2p_invite_group; + u8 p2p_dev_addr[ETH_ALEN]; + struct os_reltime p2p_go_wait_client; + struct dl_list p2p_srv_bonjour; /* struct p2p_srv_bonjour */ + struct dl_list p2p_srv_upnp; /* struct p2p_srv_upnp */ + int p2p_disabled; + int cross_connection; + struct wpa_freq_range_list p2p_disallow_freq; + struct wpa_freq_range_list p2p_go_avoid_freq; + enum wpa_conc_pref { + WPA_CONC_PREF_NOT_SET, + WPA_CONC_PREF_STA, + WPA_CONC_PREF_P2P + } conc_pref; + unsigned int p2p_per_sta_psk:1; + unsigned int p2p_fail_on_wps_complete:1; + unsigned int p2p_24ghz_social_channels:1; + unsigned int pending_p2ps_group:1; + unsigned int pending_group_iface_for_p2ps:1; + +#ifdef CONFIG_WIFI_DISPLAY + int wifi_display; +#define MAX_WFD_SUBELEMS 10 + struct wpabuf *wfd_subelem[MAX_WFD_SUBELEMS]; +#endif /* CONFIG_WIFI_DISPLAY */ + + struct psk_list_entry *add_psk; /* From group formation */ +}; + + +/** + * struct wpa_radio - Internal data for per-radio information + * + * This structure is used to share data about configured interfaces + * (struct wpa_supplicant) that share the same physical radio, e.g., to allow + * better coordination of offchannel operations. + */ +struct wpa_radio { + char name[16]; /* from driver_ops get_radio_name() or empty if not + * available */ + unsigned int external_scan_running:1; + struct dl_list ifaces; /* struct wpa_supplicant::radio_list entries */ + struct dl_list work; /* struct wpa_radio_work::list entries */ +}; + +/** + * struct wpa_radio_work - Radio work item + */ +struct wpa_radio_work { + struct dl_list list; + unsigned int freq; /* known frequency (MHz) or 0 for multiple/unknown */ + const char *type; + struct wpa_supplicant *wpa_s; + void (*cb)(struct wpa_radio_work *work, int deinit); + void *ctx; + unsigned int started:1; + struct os_reltime time; +}; + +int radio_add_work(struct wpa_supplicant *wpa_s, unsigned int freq, + const char *type, int next, + void (*cb)(struct wpa_radio_work *work, int deinit), + void *ctx); +void radio_work_done(struct wpa_radio_work *work); +void radio_remove_works(struct wpa_supplicant *wpa_s, + const char *type, int remove_all); +void radio_work_check_next(struct wpa_supplicant *wpa_s); +struct wpa_radio_work * +radio_work_pending(struct wpa_supplicant *wpa_s, const char *type); + +struct wpa_connect_work { + unsigned int sme:1; + unsigned int bss_removed:1; + struct wpa_bss *bss; + struct wpa_ssid *ssid; +}; + +int wpas_valid_bss_ssid(struct wpa_supplicant *wpa_s, struct wpa_bss *test_bss, + struct wpa_ssid *test_ssid); +void wpas_connect_work_free(struct wpa_connect_work *cwork); +void wpas_connect_work_done(struct wpa_supplicant *wpa_s); + +struct wpa_external_work { + unsigned int id; + char type[100]; + unsigned int timeout; +}; + +/** + * offchannel_send_action_result - Result of offchannel send Action frame + */ +enum offchannel_send_action_result { + OFFCHANNEL_SEND_ACTION_SUCCESS /**< Frame was send and acknowledged */, + OFFCHANNEL_SEND_ACTION_NO_ACK /**< Frame was sent, but not acknowledged + */, + OFFCHANNEL_SEND_ACTION_FAILED /**< Frame was not sent due to a failure + */ +}; + +struct wps_ap_info { + u8 bssid[ETH_ALEN]; + enum wps_ap_info_type { + WPS_AP_NOT_SEL_REG, + WPS_AP_SEL_REG, + WPS_AP_SEL_REG_OUR + } type; + unsigned int tries; + struct os_reltime last_attempt; + unsigned int pbc_active; + u8 uuid[WPS_UUID_LEN]; +}; + +struct wpa_ssid_value { + u8 ssid[SSID_MAX_LEN]; + size_t ssid_len; +}; + +#define WPA_FREQ_USED_BY_INFRA_STATION BIT(0) +#define WPA_FREQ_USED_BY_P2P_CLIENT BIT(1) + +struct wpa_used_freq_data { + int freq; + unsigned int flags; +}; + +#define RRM_NEIGHBOR_REPORT_TIMEOUT 1 /* 1 second for AP to send a report */ + +/* + * struct rrm_data - Data used for managing RRM features + */ +struct rrm_data { + /* rrm_used - indication regarding the current connection */ + unsigned int rrm_used:1; + + /* + * notify_neighbor_rep - Callback for notifying report requester + */ + void (*notify_neighbor_rep)(void *ctx, struct wpabuf *neighbor_rep); + + /* + * neighbor_rep_cb_ctx - Callback context + * Received in the callback registration, and sent to the callback + * function as a parameter. + */ + void *neighbor_rep_cb_ctx; + + /* next_neighbor_rep_token - Next request's dialog token */ + u8 next_neighbor_rep_token; +}; + +enum wpa_supplicant_test_failure { + WPAS_TEST_FAILURE_NONE, + WPAS_TEST_FAILURE_SCAN_TRIGGER, +}; + +/** + * struct wpa_supplicant - Internal data for wpa_supplicant interface + * + * This structure contains the internal data for core wpa_supplicant code. This + * should be only used directly from the core code. However, a pointer to this + * data is used from other files as an arbitrary context pointer in calls to + * core functions. + */ +struct wpa_supplicant { + struct wpa_global *global; + struct wpa_radio *radio; /* shared radio context */ + struct dl_list radio_list; /* list head: struct wpa_radio::ifaces */ + struct wpa_supplicant *parent; + struct wpa_supplicant *next; + struct l2_packet_data *l2; + struct l2_packet_data *l2_br; + unsigned char own_addr[ETH_ALEN]; + unsigned char perm_addr[ETH_ALEN]; + char ifname[IFNAMSIZ]; +#ifdef CONFIG_CTRL_IFACE_DBUS + char *dbus_path; +#endif /* CONFIG_CTRL_IFACE_DBUS */ +#ifdef CONFIG_CTRL_IFACE_DBUS_NEW + char *dbus_new_path; + char *dbus_groupobj_path; +#ifdef CONFIG_AP + char *preq_notify_peer; +#endif /* CONFIG_AP */ +#endif /* CONFIG_CTRL_IFACE_DBUS_NEW */ +#ifdef CONFIG_FULL_SUPPLICANT + char bridge_ifname[16]; +#endif + char *confname; + char *confanother; + + struct wpa_config *conf; + int countermeasures; + struct os_reltime last_michael_mic_error; + u8 bssid[ETH_ALEN]; + u8 pending_bssid[ETH_ALEN]; /* If wpa_state == WPA_ASSOCIATING, this + * field contains the target BSSID. */ + int reassociate; /* reassociation requested */ + int reassoc_same_bss; /* reassociating to the same bss */ + int disconnected; /* all connections disabled; i.e., do no reassociate + * before this has been cleared */ + struct wpa_ssid *current_ssid; + struct wpa_ssid *last_ssid; + struct wpa_bss *current_bss; + int ap_ies_from_associnfo; + unsigned int assoc_freq; + + /* Selected configuration (based on Beacon/ProbeResp WPA IE) */ + int pairwise_cipher; + int group_cipher; + int key_mgmt; + int wpa_proto; + int mgmt_group_cipher; + + void *drv_priv; /* private data used by driver_ops */ + void *global_drv_priv; + + u8 *bssid_filter; + size_t bssid_filter_count; + + u8 *disallow_aps_bssid; + size_t disallow_aps_bssid_count; + struct wpa_ssid_value *disallow_aps_ssid; + size_t disallow_aps_ssid_count; + + enum set_band setband; + + /* Preferred network for the next connection attempt */ + struct wpa_ssid *next_ssid; + + /* previous scan was wildcard when interleaving between + * wildcard scans and specific SSID scan when max_ssids=1 */ + int prev_scan_wildcard; + struct wpa_ssid *prev_scan_ssid; /* previously scanned SSID; + * NULL = not yet initialized (start + * with wildcard SSID) + * WILDCARD_SSID_SCAN = wildcard + * SSID was used in the previous scan + */ +#define WILDCARD_SSID_SCAN ((struct wpa_ssid *) 1) + + struct wpa_ssid *prev_sched_ssid; /* last SSID used in sched scan */ + int sched_scan_timeout; + int sched_scan_interval; + int first_sched_scan; + int sched_scan_timed_out; + + void (*scan_res_handler)(struct wpa_supplicant *wpa_s, + struct wpa_scan_results *scan_res); + struct dl_list bss; /* struct wpa_bss::list */ + struct dl_list bss_id; /* struct wpa_bss::list_id */ + size_t num_bss; + unsigned int bss_update_idx; + unsigned int bss_next_id; + + /* + * Pointers to BSS entries in the order they were in the last scan + * results. + */ + struct wpa_bss **last_scan_res; + unsigned int last_scan_res_used; + unsigned int last_scan_res_size; + struct os_reltime last_scan; + + const struct wpa_driver_ops *driver; + int interface_removed; /* whether the network interface has been + * removed */ + struct wpa_sm *wpa; + struct eapol_sm *eapol; + +#ifdef CONFIG_CTRL_IFACE + struct ctrl_iface_priv *ctrl_iface; +#endif + + enum wpa_states wpa_state; + struct wpa_radio_work *scan_work; + int scanning; + int sched_scanning; + int new_connection; + + int eapol_received; /* number of EAPOL packets received after the + * previous association event */ + + unsigned char last_eapol_src[ETH_ALEN]; + + unsigned int keys_cleared; /* bitfield of key indexes that the driver is + * known not to be configured with a key */ + + struct wpa_blacklist *blacklist; + + /** + * extra_blacklist_count - Sum of blacklist counts after last connection + * + * This variable is used to maintain a count of temporary blacklisting + * failures (maximum number for any BSS) over blacklist clear + * operations. This is needed for figuring out whether there has been + * failures prior to the last blacklist clear operation which happens + * whenever no other not-blacklisted BSS candidates are available. This + * gets cleared whenever a connection has been established successfully. + */ + int extra_blacklist_count; + + /** + * scan_req - Type of the scan request + */ + enum scan_req_type { + /** + * NORMAL_SCAN_REQ - Normal scan request + * + * This is used for scans initiated by wpa_supplicant to find an + * AP for a connection. + */ + NORMAL_SCAN_REQ, + + /** + * INITIAL_SCAN_REQ - Initial scan request + * + * This is used for the first scan on an interface to force at + * least one scan to be run even if the configuration does not + * include any enabled networks. + */ + INITIAL_SCAN_REQ, + + /** + * MANUAL_SCAN_REQ - Manual scan request + * + * This is used for scans where the user request a scan or + * a specific wpa_supplicant operation (e.g., WPS) requires scan + * to be run. + */ + MANUAL_SCAN_REQ + } scan_req, last_scan_req; + enum wpa_states scan_prev_wpa_state; + struct os_reltime scan_trigger_time, scan_start_time; + /* Minimum freshness requirement for connection purposes */ + struct os_reltime scan_min_time; + int scan_runs; /* number of scan runs since WPS was started */ + int *next_scan_freqs; + int *manual_scan_freqs; + int *manual_sched_scan_freqs; + unsigned int manual_scan_passive:1; + unsigned int manual_scan_use_id:1; + unsigned int manual_scan_only_new:1; + unsigned int own_scan_requested:1; + unsigned int own_scan_running:1; + unsigned int clear_driver_scan_cache:1; + unsigned int manual_scan_id; + int scan_interval; /* time in sec between scans to find suitable AP */ + int normal_scans; /* normal scans run before sched_scan */ + int scan_for_connection; /* whether the scan request was triggered for + * finding a connection */ +#define MAX_SCAN_ID 16 + int scan_id[MAX_SCAN_ID]; + unsigned int scan_id_count; + + struct wpa_ssid_value *ssids_from_scan_req; + unsigned int num_ssids_from_scan_req; + + u64 drv_flags; + unsigned int drv_enc; + unsigned int drv_smps_modes; + unsigned int drv_rrm_flags; + + /* + * A bitmap of supported protocols for probe response offload. See + * struct wpa_driver_capa in driver.h + */ + unsigned int probe_resp_offloads; + + /* extended capabilities supported by the driver */ + const u8 *extended_capa, *extended_capa_mask; + unsigned int extended_capa_len; + + int max_scan_ssids; + int max_sched_scan_ssids; + int sched_scan_supported; + unsigned int max_match_sets; + unsigned int max_remain_on_chan; + unsigned int max_stations; + + int pending_mic_error_report; + int pending_mic_error_pairwise; + int mic_errors_seen; /* Michael MIC errors with the current PTK */ + + struct wps_context *wps; + int wps_success; /* WPS success event received */ + struct wps_er *wps_er; + unsigned int wps_run; + struct os_reltime wps_pin_start_time; + int blacklist_cleared; + + struct wpabuf *pending_eapol_rx; + struct os_reltime pending_eapol_rx_time; + u8 pending_eapol_rx_src[ETH_ALEN]; + unsigned int last_eapol_matches_bssid:1; + unsigned int eap_expected_failure:1; + unsigned int reattach:1; /* reassociation to the same BSS requested */ + unsigned int mac_addr_changed:1; + unsigned int added_vif:1; + + struct os_reltime last_mac_addr_change; + int last_mac_addr_style; + + struct ibss_rsn *ibss_rsn; + + int set_sta_uapsd; + int sta_uapsd; + int set_ap_uapsd; + int ap_uapsd; + +#ifdef CONFIG_SME + struct { + u8 ssid[SSID_MAX_LEN]; + size_t ssid_len; + int freq; + u8 assoc_req_ie[200]; + size_t assoc_req_ie_len; + int mfp; + int ft_used; + u8 mobility_domain[2]; + u8 *ft_ies; + size_t ft_ies_len; + u8 prev_bssid[ETH_ALEN]; + int prev_bssid_set; + int auth_alg; + int proto; + + int sa_query_count; /* number of pending SA Query requests; + * 0 = no SA Query in progress */ + int sa_query_timed_out; + u8 *sa_query_trans_id; /* buffer of WLAN_SA_QUERY_TR_ID_LEN * + * sa_query_count octets of pending + * SA Query transaction identifiers */ + struct os_reltime sa_query_start; + struct os_reltime last_unprot_disconnect; + enum { HT_SEC_CHAN_UNKNOWN, + HT_SEC_CHAN_ABOVE, + HT_SEC_CHAN_BELOW } ht_sec_chan; + u8 sched_obss_scan; + u16 obss_scan_int; + u16 bss_max_idle_period; +#ifdef CONFIG_SAE + struct sae_data sae; + struct wpabuf *sae_token; + int sae_group_index; + unsigned int sae_pmksa_caching:1; +#endif /* CONFIG_SAE */ + } sme; +#endif /* CONFIG_SME */ + +#ifdef CONFIG_AP + struct hostapd_iface *ap_iface; + void (*ap_configured_cb)(void *ctx, void *data); + void *ap_configured_cb_ctx; + void *ap_configured_cb_data; +#endif /* CONFIG_AP */ + + struct hostapd_iface *ifmsh; +#ifdef CONFIG_MESH + struct mesh_rsn *mesh_rsn; + int mesh_if_idx; + unsigned int mesh_if_created:1; + unsigned int mesh_ht_enabled:1; + int mesh_auth_block_duration; /* sec */ +#endif /* CONFIG_MESH */ + + int p2p_mgmt; + +#ifdef CONFIG_P2P + struct p2p_go_neg_results *go_params; + int create_p2p_iface; + u8 pending_interface_addr[ETH_ALEN]; + char pending_interface_name[100]; + int pending_interface_type; + int p2p_group_idx; + unsigned int pending_listen_freq; + unsigned int pending_listen_duration; + enum { + NOT_P2P_GROUP_INTERFACE, + P2P_GROUP_INTERFACE_PENDING, + P2P_GROUP_INTERFACE_GO, + P2P_GROUP_INTERFACE_CLIENT + } p2p_group_interface; + struct p2p_group *p2p_group; + int p2p_long_listen; /* remaining time in long Listen state in ms */ + char p2p_pin[10]; + int p2p_wps_method; + u8 p2p_auth_invite[ETH_ALEN]; + int p2p_sd_over_ctrl_iface; + int p2p_in_provisioning; + int p2p_in_invitation; + int p2p_invite_go_freq; + int pending_invite_ssid_id; + int show_group_started; + u8 go_dev_addr[ETH_ALEN]; + int pending_pd_before_join; + u8 pending_join_iface_addr[ETH_ALEN]; + u8 pending_join_dev_addr[ETH_ALEN]; + int pending_join_wps_method; + u8 p2p_join_ssid[SSID_MAX_LEN]; + size_t p2p_join_ssid_len; + int p2p_join_scan_count; + int auto_pd_scan_retry; + int force_long_sd; + u16 pending_pd_config_methods; + enum { + NORMAL_PD, AUTO_PD_GO_NEG, AUTO_PD_JOIN, AUTO_PD_ASP + } pending_pd_use; + + /* + * Whether cross connection is disallowed by the AP to which this + * interface is associated (only valid if there is an association). + */ + int cross_connect_disallowed; + + /* + * Whether this P2P group is configured to use cross connection (only + * valid if this is P2P GO interface). The actual cross connect packet + * forwarding may not be configured depending on the uplink status. + */ + int cross_connect_enabled; + + /* Whether cross connection forwarding is in use at the moment. */ + int cross_connect_in_use; + + /* + * Uplink interface name for cross connection + */ + char cross_connect_uplink[100]; + + unsigned int p2p_auto_join:1; + unsigned int p2p_auto_pd:1; + unsigned int p2p_persistent_group:1; + unsigned int p2p_fallback_to_go_neg:1; + unsigned int p2p_pd_before_go_neg:1; + unsigned int p2p_go_ht40:1; + unsigned int p2p_go_vht:1; + unsigned int user_initiated_pd:1; + unsigned int p2p_go_group_formation_completed:1; + unsigned int group_formation_reported:1; + unsigned int waiting_presence_resp; + int p2p_first_connection_timeout; + unsigned int p2p_nfc_tag_enabled:1; + unsigned int p2p_peer_oob_pk_hash_known:1; + unsigned int p2p_disable_ip_addr_req:1; + unsigned int p2ps_method_config_any:1; + unsigned int p2p_cli_probe:1; + int p2p_persistent_go_freq; + int p2p_persistent_id; + int p2p_go_intent; + int p2p_connect_freq; + struct os_reltime p2p_auto_started; + struct wpa_ssid *p2p_last_4way_hs_fail; + struct wpa_radio_work *p2p_scan_work; + struct wpa_radio_work *p2p_listen_work; + struct wpa_radio_work *p2p_send_action_work; + + u16 p2p_oob_dev_pw_id; /* OOB Device Password Id for group formation */ + struct wpabuf *p2p_oob_dev_pw; /* OOB Device Password for group + * formation */ + u8 p2p_peer_oob_pubkey_hash[WPS_OOB_PUBKEY_HASH_LEN]; + u8 p2p_ip_addr_info[3 * 4]; + + /* group common frequencies */ + int *p2p_group_common_freqs; + unsigned int p2p_group_common_freqs_num; + u8 p2ps_join_addr[ETH_ALEN]; +#endif /* CONFIG_P2P */ + + struct wpa_ssid *bgscan_ssid; + const struct bgscan_ops *bgscan; + void *bgscan_priv; + + const struct autoscan_ops *autoscan; + struct wpa_driver_scan_params *autoscan_params; + void *autoscan_priv; + + struct wpa_ssid *connect_without_scan; + + struct wps_ap_info *wps_ap; + size_t num_wps_ap; + int wps_ap_iter; + + int after_wps; + int known_wps_freq; + unsigned int wps_freq; + int wps_fragment_size; + int auto_reconnect_disabled; + + /* Channel preferences for AP/P2P GO use */ + int best_24_freq; + int best_5_freq; + int best_overall_freq; + +#ifdef CONFIG_INTERWORKING + unsigned int fetch_anqp_in_progress:1; + unsigned int network_select:1; + unsigned int auto_select:1; + unsigned int auto_network_select:1; + unsigned int interworking_fast_assoc_tried:1; + unsigned int fetch_all_anqp:1; + unsigned int fetch_osu_info:1; + unsigned int fetch_osu_waiting_scan:1; + unsigned int fetch_osu_icon_in_progress:1; + struct wpa_bss *interworking_gas_bss; + unsigned int osu_icon_id; + struct osu_provider *osu_prov; + size_t osu_prov_count; + struct os_reltime osu_icon_fetch_start; + unsigned int num_osu_scans; + unsigned int num_prov_found; +#endif /* CONFIG_INTERWORKING */ + unsigned int drv_capa_known; + + struct { + struct hostapd_hw_modes *modes; + u16 num_modes; + u16 flags; + } hw; + enum local_hw_capab { + CAPAB_NO_HT_VHT, + CAPAB_HT, + CAPAB_HT40, + CAPAB_VHT, + } hw_capab; +#ifdef CONFIG_MACSEC + struct ieee802_1x_kay *kay; +#endif /* CONFIG_MACSEC */ + + int pno; + int pno_sched_pending; + + /* WLAN_REASON_* reason codes. Negative if locally generated. */ + int disconnect_reason; + + unsigned int no_keep_alive:1; + unsigned int ext_mgmt_frame_handling:1; + unsigned int ext_eapol_frame_io:1; + unsigned int wmm_ac_supported:1; + unsigned int ext_work_in_progress:1; + unsigned int own_disconnect_req:1; + +#define MAC_ADDR_RAND_SCAN BIT(0) +#define MAC_ADDR_RAND_SCHED_SCAN BIT(1) +#define MAC_ADDR_RAND_PNO BIT(2) +#define MAC_ADDR_RAND_ALL (MAC_ADDR_RAND_SCAN | \ + MAC_ADDR_RAND_SCHED_SCAN | \ + MAC_ADDR_RAND_PNO) + unsigned int mac_addr_rand_supported; + unsigned int mac_addr_rand_enable; + + /* MAC Address followed by mask (2 * ETH_ALEN) */ + u8 *mac_addr_scan; + u8 *mac_addr_sched_scan; + u8 *mac_addr_pno; + +#ifdef CONFIG_WNM + u8 wnm_dialog_token; + u8 wnm_reply; + u8 wnm_num_neighbor_report; + u8 wnm_mode; + u16 wnm_dissoc_timer; + u8 wnm_bss_termination_duration[12]; + struct neighbor_report *wnm_neighbor_report_elements; + struct os_reltime wnm_cand_valid_until; + u8 wnm_cand_from_bss[ETH_ALEN]; +#endif /* CONFIG_WNM */ + +#ifdef CONFIG_TESTING_GET_GTK + u8 last_gtk[32]; + size_t last_gtk_len; +#endif /* CONFIG_TESTING_GET_GTK */ + + unsigned int num_multichan_concurrent; + struct wpa_radio_work *connect_work; + + struct wpabuf *vendor_elem[NUM_VENDOR_ELEM_FRAMES]; + + struct wmm_ac_assoc_data *wmm_ac_assoc_info; + struct wmm_tspec_element *tspecs[WMM_AC_NUM][TS_DIR_IDX_COUNT]; + struct wmm_ac_addts_request *addts_request; + u8 wmm_ac_last_dialog_token; + struct wmm_tspec_element *last_tspecs; + u8 last_tspecs_count; + + struct rrm_data rrm; + +#ifdef CONFIG_FST + struct fst_iface *fst; + const struct wpabuf *fst_ies; + struct wpabuf *received_mb_ies; +#endif /* CONFIG_FST */ +}; + + +/* wpa_supplicant.c */ +void wpa_supplicant_apply_ht_overrides( + struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, + struct wpa_driver_associate_params *params); +void wpa_supplicant_apply_vht_overrides( + struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, + struct wpa_driver_associate_params *params); + +int wpa_set_wep_keys(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid); +int wpa_supplicant_set_wpa_none_key(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid); + +int wpa_supplicant_reload_configuration(struct wpa_supplicant *wpa_s); + +const char * wpa_supplicant_state_txt(enum wpa_states state); +int wpa_supplicant_update_mac_addr(struct wpa_supplicant *wpa_s); +int wpa_supplicant_driver_init(struct wpa_supplicant *wpa_s); +int wpa_supplicant_set_suites(struct wpa_supplicant *wpa_s, + struct wpa_bss *bss, struct wpa_ssid *ssid, + u8 *wpa_ie, size_t *wpa_ie_len); +void wpa_supplicant_associate(struct wpa_supplicant *wpa_s, + struct wpa_bss *bss, + struct wpa_ssid *ssid); +void wpa_supplicant_set_non_wpa_policy(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid); +void wpa_supplicant_initiate_eapol(struct wpa_supplicant *wpa_s); +void wpa_clear_keys(struct wpa_supplicant *wpa_s, const u8 *addr); +void wpa_supplicant_req_auth_timeout(struct wpa_supplicant *wpa_s, + int sec, int usec); +void wpa_supplicant_reinit_autoscan(struct wpa_supplicant *wpa_s); +void wpa_supplicant_set_state(struct wpa_supplicant *wpa_s, + enum wpa_states state); +struct wpa_ssid * wpa_supplicant_get_ssid(struct wpa_supplicant *wpa_s); +const char * wpa_supplicant_get_eap_mode(struct wpa_supplicant *wpa_s); +void wpa_supplicant_cancel_auth_timeout(struct wpa_supplicant *wpa_s); +void wpa_supplicant_deauthenticate(struct wpa_supplicant *wpa_s, + int reason_code); + +void wpa_supplicant_enable_network(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid); +void wpa_supplicant_disable_network(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid); +void wpa_supplicant_select_network(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid); +int wpas_set_pkcs11_engine_and_module_path(struct wpa_supplicant *wpa_s, + const char *pkcs11_engine_path, + const char *pkcs11_module_path); +int wpa_supplicant_set_ap_scan(struct wpa_supplicant *wpa_s, + int ap_scan); +int wpa_supplicant_set_bss_expiration_age(struct wpa_supplicant *wpa_s, + unsigned int expire_age); +int wpa_supplicant_set_bss_expiration_count(struct wpa_supplicant *wpa_s, + unsigned int expire_count); +int wpa_supplicant_set_scan_interval(struct wpa_supplicant *wpa_s, + int scan_interval); +int wpa_supplicant_set_debug_params(struct wpa_global *global, + int debug_level, int debug_timestamp, + int debug_show_keys); +void free_hw_features(struct wpa_supplicant *wpa_s); + +void wpa_show_license(void); + +struct wpa_supplicant * wpa_supplicant_add_iface(struct wpa_global *global, + struct wpa_interface *iface, + struct wpa_supplicant *parent); +int wpa_supplicant_remove_iface(struct wpa_global *global, + struct wpa_supplicant *wpa_s, + int terminate); +struct wpa_supplicant * wpa_supplicant_get_iface(struct wpa_global *global, + const char *ifname); +struct wpa_global * wpa_supplicant_init(struct wpa_params *params); +int wpa_supplicant_run(struct wpa_global *global); +void wpa_supplicant_deinit(struct wpa_global *global); + +int wpa_supplicant_scard_init(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid); +void wpa_supplicant_terminate_proc(struct wpa_global *global); +void wpa_supplicant_rx_eapol(void *ctx, const u8 *src_addr, + const u8 *buf, size_t len); +void wpa_supplicant_update_config(struct wpa_supplicant *wpa_s); +void wpa_supplicant_clear_status(struct wpa_supplicant *wpa_s); +void wpas_connection_failed(struct wpa_supplicant *wpa_s, const u8 *bssid); +int wpas_driver_bss_selection(struct wpa_supplicant *wpa_s); +int wpas_is_p2p_prioritized(struct wpa_supplicant *wpa_s); +void wpas_auth_failed(struct wpa_supplicant *wpa_s, char *reason); +void wpas_clear_temp_disabled(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid, int clear_failures); +int disallowed_bssid(struct wpa_supplicant *wpa_s, const u8 *bssid); +int disallowed_ssid(struct wpa_supplicant *wpa_s, const u8 *ssid, + size_t ssid_len); +void wpas_request_connection(struct wpa_supplicant *wpa_s); +int wpas_build_ext_capab(struct wpa_supplicant *wpa_s, u8 *buf, size_t buflen); +int wpas_update_random_addr(struct wpa_supplicant *wpa_s, int style); +int wpas_update_random_addr_disassoc(struct wpa_supplicant *wpa_s); +void add_freq(int *freqs, int *num_freqs, int freq); + +void wpas_rrm_reset(struct wpa_supplicant *wpa_s); +void wpas_rrm_process_neighbor_rep(struct wpa_supplicant *wpa_s, + const u8 *report, size_t report_len); +int wpas_rrm_send_neighbor_rep_request(struct wpa_supplicant *wpa_s, + const struct wpa_ssid *ssid, + void (*cb)(void *ctx, + struct wpabuf *neighbor_rep), + void *cb_ctx); +void wpas_rrm_handle_link_measurement_request(struct wpa_supplicant *wpa_s, + const u8 *src, + const u8 *frame, size_t len, + int rssi); + +/** + * wpa_supplicant_ctrl_iface_ctrl_rsp_handle - Handle a control response + * @wpa_s: Pointer to wpa_supplicant data + * @ssid: Pointer to the network block the reply is for + * @field: field the response is a reply for + * @value: value (ie, password, etc) for @field + * Returns: 0 on success, non-zero on error + * + * Helper function to handle replies to control interface requests. + */ +int wpa_supplicant_ctrl_iface_ctrl_rsp_handle(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid, + const char *field, + const char *value); + +void ibss_mesh_setup_freq(struct wpa_supplicant *wpa_s, + const struct wpa_ssid *ssid, + struct hostapd_freq_params *freq); + +/* events.c */ +void wpa_supplicant_mark_disassoc(struct wpa_supplicant *wpa_s); +int wpa_supplicant_connect(struct wpa_supplicant *wpa_s, + struct wpa_bss *selected, + struct wpa_ssid *ssid); +void wpa_supplicant_stop_countermeasures(void *eloop_ctx, void *sock_ctx); +void wpa_supplicant_delayed_mic_error_report(void *eloop_ctx, void *sock_ctx); +void wnm_bss_keep_alive_deinit(struct wpa_supplicant *wpa_s); +int wpa_supplicant_fast_associate(struct wpa_supplicant *wpa_s); +struct wpa_bss * wpa_supplicant_pick_network(struct wpa_supplicant *wpa_s, + struct wpa_ssid **selected_ssid); + +/* eap_register.c */ +int eap_register_methods(void); + +/** + * Utility method to tell if a given network is for persistent group storage + * @ssid: Network object + * Returns: 1 if network is a persistent group, 0 otherwise + */ +static inline int network_is_persistent_group(struct wpa_ssid *ssid) +{ + return ssid->disabled == 2 && ssid->p2p_persistent_group; +} + +int wpas_network_disabled(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid); +int wpas_get_ssid_pmf(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid); + +int wpas_init_ext_pw(struct wpa_supplicant *wpa_s); + +void dump_freq_data(struct wpa_supplicant *wpa_s, const char *title, + struct wpa_used_freq_data *freqs_data, + unsigned int len); + +int get_shared_radio_freqs_data(struct wpa_supplicant *wpa_s, + struct wpa_used_freq_data *freqs_data, + unsigned int len); +int get_shared_radio_freqs(struct wpa_supplicant *wpa_s, + int *freq_array, unsigned int len); + +void wpas_network_reenabled(void *eloop_ctx, void *timeout_ctx); + +#ifdef CONFIG_FST + +struct fst_wpa_obj; + +void fst_wpa_supplicant_fill_iface_obj(struct wpa_supplicant *wpa_s, + struct fst_wpa_obj *iface_obj); + +#endif /* CONFIG_FST */ + +#endif /* WPA_SUPPLICANT_I_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/wpas_glue.c b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/wpas_glue.c new file mode 100755 index 0000000..28caf3c --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/wpas_glue.c @@ -0,0 +1,1098 @@ +/* + * WPA Supplicant - Glue code to setup EAPOL and RSN modules + * Copyright (c) 2003-2015, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "eapol_supp/eapol_supp_sm.h" +#include "rsn_supp/wpa.h" +#include "eloop.h" +#include "config.h" +#include "l2_packet/l2_packet.h" +#include "common/wpa_common.h" +#include "wpa_supplicant_i.h" +#include "driver_i.h" +#include "sme.h" +#include "common/ieee802_11_defs.h" +#include "common/wpa_ctrl.h" +#include "wpas_glue.h" +#include "wps_supplicant.h" +#include "bss.h" +#include "scan.h" +#include "notify.h" +#include "wpas_kay.h" + + +#if defined(IEEE8021X_EAPOL) || !defined(CONFIG_NO_WPA) +static u8 * wpa_alloc_eapol(const struct wpa_supplicant *wpa_s, u8 type, + const void *data, u16 data_len, + size_t *msg_len, void **data_pos) +{ + struct ieee802_1x_hdr *hdr; + + *msg_len = sizeof(*hdr) + data_len; + hdr = os_malloc(*msg_len); + if (hdr == NULL) + return NULL; + + hdr->version = wpa_s->conf->eapol_version; + hdr->type = type; + hdr->length = host_to_be16(data_len); + + if (data) + os_memcpy(hdr + 1, data, data_len); + else + os_memset(hdr + 1, 0, data_len); + + if (data_pos) + *data_pos = hdr + 1; + + return (u8 *) hdr; +} + +extern int l2_packet_send_sync(struct l2_packet_data *l2, const u8 *dst_addr, u16 proto, + const u8 *buf, size_t len); +/** + * wpa_ether_send - Send Ethernet frame + * @wpa_s: Pointer to wpa_supplicant data + * @dest: Destination MAC address + * @proto: Ethertype in host byte order + * @buf: Frame payload starting from IEEE 802.1X header + * @len: Frame payload length + * Returns: >=0 on success, <0 on failure + */ +static int wpa_ether_send(struct wpa_supplicant *wpa_s, const u8 *dest, + u16 proto, const u8 *buf, size_t len) +{ +#ifdef CONFIG_TESTING_OPTIONS + if (wpa_s->ext_eapol_frame_io && proto == ETH_P_EAPOL) { + size_t hex_len = 2 * len + 1; + char *hex = os_malloc(hex_len); + + if (hex == NULL) + return -1; + wpa_snprintf_hex(hex, hex_len, buf, len); + wpa_msg(wpa_s, MSG_INFO, "EAPOL-TX " MACSTR " %s", + MAC2STR(dest), hex); + os_free(hex); + return 0; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + if (wpa_s->l2) { + return l2_packet_send_sync(wpa_s->l2, dest, proto, buf, len); + } + + return -1; +} +#endif /* IEEE8021X_EAPOL || !CONFIG_NO_WPA */ + + +#ifdef IEEE8021X_EAPOL + +/** + * wpa_supplicant_eapol_send - Send IEEE 802.1X EAPOL packet to Authenticator + * @ctx: Pointer to wpa_supplicant data (wpa_s) + * @type: IEEE 802.1X packet type (IEEE802_1X_TYPE_*) + * @buf: EAPOL payload (after IEEE 802.1X header) + * @len: EAPOL payload length + * Returns: >=0 on success, <0 on failure + * + * This function adds Ethernet and IEEE 802.1X header and sends the EAPOL frame + * to the current Authenticator. + */ +static int wpa_supplicant_eapol_send(void *ctx, int type, const u8 *buf, + size_t len) +{ + struct wpa_supplicant *wpa_s = ctx; + u8 *msg, *dst, bssid[ETH_ALEN]; + size_t msglen; + int res; + + /* TODO: could add l2_packet_sendmsg that allows fragments to avoid + * extra copy here */ + + if (wpa_key_mgmt_wpa_psk(wpa_s->key_mgmt) || + wpa_s->key_mgmt == WPA_KEY_MGMT_NONE) { + /* Current SSID is not using IEEE 802.1X/EAP, so drop possible + * EAPOL frames (mainly, EAPOL-Start) from EAPOL state + * machines. */ + wpa_printf(MSG_DEBUG, "WPA: drop TX EAPOL in non-IEEE 802.1X " + "mode (type=%d len=%lu)", type, + (unsigned long) len); + return -1; + } + + if (pmksa_cache_get_current(wpa_s->wpa) && + type == IEEE802_1X_TYPE_EAPOL_START) { + /* + * We were trying to use PMKSA caching and sending EAPOL-Start + * would abort that and trigger full EAPOL authentication. + * However, we've already waited for the AP/Authenticator to + * start 4-way handshake or EAP authentication, and apparently + * it has not done so since the startWhen timer has reached zero + * to get the state machine sending EAPOL-Start. This is not + * really supposed to happen, but an interoperability issue with + * a deployed AP has been identified where the connection fails + * due to that AP failing to operate correctly if PMKID is + * included in the Association Request frame. To work around + * this, assume PMKSA caching failed and try to initiate full + * EAP authentication. + */ + if (!wpa_s->current_ssid || + wpa_s->current_ssid->eap_workaround) { + wpa_printf(MSG_DEBUG, + "RSN: Timeout on waiting for the AP to initiate 4-way handshake for PMKSA caching or EAP authentication - try to force it to start EAP authentication"); + } else { + wpa_printf(MSG_DEBUG, + "RSN: PMKSA caching - do not send EAPOL-Start"); + return -1; + } + } + + if (is_zero_ether_addr(wpa_s->bssid)) { + wpa_printf(MSG_DEBUG, "BSSID not set when trying to send an " + "EAPOL frame"); + if (wpa_drv_get_bssid(wpa_s, bssid) == 0 && + !is_zero_ether_addr(bssid)) { + dst = bssid; + wpa_printf(MSG_DEBUG, "Using current BSSID " MACSTR + " from the driver as the EAPOL destination", + MAC2STR(dst)); + } else { + dst = wpa_s->last_eapol_src; + wpa_printf(MSG_DEBUG, "Using the source address of the" + " last received EAPOL frame " MACSTR " as " + "the EAPOL destination", + MAC2STR(dst)); + } + } else { + /* BSSID was already set (from (Re)Assoc event, so use it as + * the EAPOL destination. */ + dst = wpa_s->bssid; + } + + msg = wpa_alloc_eapol(wpa_s, type, buf, len, &msglen, NULL); + if (msg == NULL) + return -1; + + wpa_printf(MSG_DEBUG, "TX EAPOL: dst=" MACSTR, MAC2STR(dst)); + wpa_hexdump(MSG_MSGDUMP, "TX EAPOL", msg, msglen); + res = wpa_ether_send(wpa_s, dst, ETH_P_EAPOL, msg, msglen); + os_free(msg); + return res; +} + + +/** + * wpa_eapol_set_wep_key - set WEP key for the driver + * @ctx: Pointer to wpa_supplicant data (wpa_s) + * @unicast: 1 = individual unicast key, 0 = broadcast key + * @keyidx: WEP key index (0..3) + * @key: Pointer to key data + * @keylen: Key length in bytes + * Returns: 0 on success or < 0 on error. + */ +static int wpa_eapol_set_wep_key(void *ctx, int unicast, int keyidx, + const u8 *key, size_t keylen) +{ + struct wpa_supplicant *wpa_s = ctx; + if (wpa_s->key_mgmt == WPA_KEY_MGMT_IEEE8021X_NO_WPA) { + int cipher = (keylen == 5) ? WPA_CIPHER_WEP40 : + WPA_CIPHER_WEP104; + if (unicast) + wpa_s->pairwise_cipher = cipher; + else + wpa_s->group_cipher = cipher; + } + + return wpa_drv_set_key(wpa_s, WPA_ALG_WEP, + unicast ? wpa_s->bssid : NULL, + keyidx, unicast, NULL, 0, key, keylen); +} + + +static void wpa_supplicant_aborted_cached(void *ctx) +{ + struct wpa_supplicant *wpa_s = ctx; + wpa_sm_aborted_cached(wpa_s->wpa); +} + + +static const char * result_str(enum eapol_supp_result result) +{ + switch (result) { + case EAPOL_SUPP_RESULT_FAILURE: + return "FAILURE"; + case EAPOL_SUPP_RESULT_SUCCESS: + return "SUCCESS"; + case EAPOL_SUPP_RESULT_EXPECTED_FAILURE: + return "EXPECTED_FAILURE"; + } + return "?"; +} + +static void wpa_supplicant_eapol_cb(struct eapol_sm *eapol, + enum eapol_supp_result result, + void *ctx) +{ + struct wpa_supplicant *wpa_s = ctx; + int res, pmk_len; + u8 pmk[PMK_LEN]; + + wpa_printf(MSG_DEBUG, "EAPOL authentication completed - result=%s", + result_str(result)); + + if (wpas_wps_eapol_cb(wpa_s) > 0) + return; + + wpa_s->eap_expected_failure = result == + EAPOL_SUPP_RESULT_EXPECTED_FAILURE; + + if (result != EAPOL_SUPP_RESULT_SUCCESS) { + /* + * Make sure we do not get stuck here waiting for long EAPOL + * timeout if the AP does not disconnect in case of + * authentication failure. + */ + wpa_supplicant_req_auth_timeout(wpa_s, 2, 0); + } else { + ieee802_1x_notify_create_actor(wpa_s, wpa_s->last_eapol_src); + } + + if (result != EAPOL_SUPP_RESULT_SUCCESS || + !(wpa_s->drv_flags & WPA_DRIVER_FLAGS_4WAY_HANDSHAKE)) + return; + + if (!wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) + return; + + wpa_printf(MSG_DEBUG, "Configure PMK for driver-based RSN 4-way " + "handshake"); + + pmk_len = PMK_LEN; + if (wpa_key_mgmt_ft(wpa_s->key_mgmt)) { +#ifdef CONFIG_IEEE80211R + u8 buf[2 * PMK_LEN]; + wpa_printf(MSG_DEBUG, "RSN: Use FT XXKey as PMK for " + "driver-based 4-way hs and FT"); + res = eapol_sm_get_key(eapol, buf, 2 * PMK_LEN); + if (res == 0) { + os_memcpy(pmk, buf + PMK_LEN, PMK_LEN); + os_memset(buf, 0, sizeof(buf)); + } +#else /* CONFIG_IEEE80211R */ + res = -1; +#endif /* CONFIG_IEEE80211R */ + } else { + res = eapol_sm_get_key(eapol, pmk, PMK_LEN); + if (res) { + /* + * EAP-LEAP is an exception from other EAP methods: it + * uses only 16-byte PMK. + */ + res = eapol_sm_get_key(eapol, pmk, 16); + pmk_len = 16; + } + } + + if (res) { + wpa_printf(MSG_DEBUG, "Failed to get PMK from EAPOL state " + "machines"); + return; + } + + wpa_hexdump_key(MSG_DEBUG, "RSN: Configure PMK for driver-based 4-way " + "handshake", pmk, pmk_len); + + if (wpa_drv_set_key(wpa_s, WPA_ALG_PMK, NULL, 0, 0, NULL, 0, pmk, + pmk_len)) { + wpa_printf(MSG_DEBUG, "Failed to set PMK to the driver"); + } + + wpa_supplicant_cancel_scan(wpa_s); + wpa_supplicant_cancel_auth_timeout(wpa_s); + wpa_supplicant_set_state(wpa_s, WPA_COMPLETED); + +} + + +static void wpa_supplicant_notify_eapol_done(void *ctx) +{ + struct wpa_supplicant *wpa_s = ctx; + wpa_msg(wpa_s, MSG_DEBUG, "WPA: EAPOL processing complete"); + if (wpa_key_mgmt_wpa_ieee8021x(wpa_s->key_mgmt)) { + wpa_supplicant_set_state(wpa_s, WPA_4WAY_HANDSHAKE); + } else { + wpa_supplicant_cancel_auth_timeout(wpa_s); + wpa_supplicant_set_state(wpa_s, WPA_COMPLETED); + } +} + +#endif /* IEEE8021X_EAPOL */ + + +#ifndef CONFIG_NO_WPA + +static int wpa_get_beacon_ie(struct wpa_supplicant *wpa_s) +{ + int ret = 0; + struct wpa_bss *curr = NULL, *bss; + struct wpa_ssid *ssid = wpa_s->current_ssid; + const u8 *ie; + + dl_list_for_each(bss, &wpa_s->bss, struct wpa_bss, list) { + if (os_memcmp(bss->bssid, wpa_s->bssid, ETH_ALEN) != 0) + continue; + if (ssid == NULL || + ((bss->ssid_len == ssid->ssid_len && + os_memcmp(bss->ssid, ssid->ssid, ssid->ssid_len) == 0) || + ssid->ssid_len == 0)) { + curr = bss; + break; + } + } + + if (curr) { + ie = wpa_bss_get_vendor_ie(curr, WPA_IE_VENDOR_TYPE); + if (wpa_sm_set_ap_wpa_ie(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0)) + ret = -1; + + ie = wpa_bss_get_ie(curr, WLAN_EID_RSN); + if (wpa_sm_set_ap_rsn_ie(wpa_s->wpa, ie, ie ? 2 + ie[1] : 0)) + ret = -1; + } else { + ret = -1; + } + + return ret; +} + + +static int wpa_supplicant_get_beacon_ie(void *ctx) +{ + struct wpa_supplicant *wpa_s = ctx; + if (wpa_get_beacon_ie(wpa_s) == 0) { + return 0; + } + + /* No WPA/RSN IE found in the cached scan results. Try to get updated + * scan results from the driver. */ + if (wpa_supplicant_update_scan_results(wpa_s) < 0) + return -1; + + return wpa_get_beacon_ie(wpa_s); +} + + +static u8 * _wpa_alloc_eapol(void *wpa_s, u8 type, + const void *data, u16 data_len, + size_t *msg_len, void **data_pos) +{ + return wpa_alloc_eapol(wpa_s, type, data, data_len, msg_len, data_pos); +} + + +static int _wpa_ether_send(void *wpa_s, const u8 *dest, u16 proto, + const u8 *buf, size_t len) +{ + return wpa_ether_send(wpa_s, dest, proto, buf, len); +} + + +static void _wpa_supplicant_cancel_auth_timeout(void *wpa_s) +{ + wpa_supplicant_cancel_auth_timeout(wpa_s); +} + + +static void _wpa_supplicant_set_state(void *wpa_s, enum wpa_states state) +{ + wpa_supplicant_set_state(wpa_s, state); +} + + +/** + * wpa_supplicant_get_state - Get the connection state + * @wpa_s: Pointer to wpa_supplicant data + * Returns: The current connection state (WPA_*) + */ +static enum wpa_states wpa_supplicant_get_state(struct wpa_supplicant *wpa_s) +{ + return wpa_s->wpa_state; +} + + +static enum wpa_states _wpa_supplicant_get_state(void *wpa_s) +{ + return wpa_supplicant_get_state(wpa_s); +} + + +static void _wpa_supplicant_deauthenticate(void *wpa_s, int reason_code) +{ + wpa_supplicant_deauthenticate(wpa_s, reason_code); + /* Schedule a scan to make sure we continue looking for networks */ + wpa_supplicant_req_scan(wpa_s, 5, 0); +} + + +static void * wpa_supplicant_get_network_ctx(void *wpa_s) +{ + return wpa_supplicant_get_ssid(wpa_s); +} + + +static int wpa_supplicant_get_bssid(void *ctx, u8 *bssid) +{ + struct wpa_supplicant *wpa_s = ctx; + return wpa_drv_get_bssid(wpa_s, bssid); +} + + +static int wpa_supplicant_set_key(void *_wpa_s, enum wpa_alg alg, + const u8 *addr, int key_idx, int set_tx, + const u8 *seq, size_t seq_len, + const u8 *key, size_t key_len) +{ + struct wpa_supplicant *wpa_s = _wpa_s; + if (alg == WPA_ALG_TKIP && key_idx == 0 && key_len == 32) { + /* Clear the MIC error counter when setting a new PTK. */ + wpa_s->mic_errors_seen = 0; + } +#ifdef CONFIG_TESTING_GET_GTK + if (key_idx > 0 && addr && is_broadcast_ether_addr(addr) && + alg != WPA_ALG_NONE && key_len <= sizeof(wpa_s->last_gtk)) { + os_memcpy(wpa_s->last_gtk, key, key_len); + wpa_s->last_gtk_len = key_len; + } +#endif /* CONFIG_TESTING_GET_GTK */ + + return wpa_drv_set_key(wpa_s, alg, addr, key_idx, set_tx, seq, seq_len, + key, key_len); +} + + +static int wpa_supplicant_mlme_setprotection(void *wpa_s, const u8 *addr, + int protection_type, + int key_type) +{ + return wpa_drv_mlme_setprotection(wpa_s, addr, protection_type, + key_type); +} + + +static int wpa_supplicant_add_pmkid(void *wpa_s, + const u8 *bssid, const u8 *pmkid) +{ + return wpa_drv_add_pmkid(wpa_s, bssid, pmkid); +} + + +static int wpa_supplicant_remove_pmkid(void *wpa_s, + const u8 *bssid, const u8 *pmkid) +{ + return wpa_drv_remove_pmkid(wpa_s, bssid, pmkid); +} + + +#ifdef CONFIG_IEEE80211R +static int wpa_supplicant_update_ft_ies(void *ctx, const u8 *md, + const u8 *ies, size_t ies_len) +{ + struct wpa_supplicant *wpa_s = ctx; + if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_SME) + return sme_update_ft_ies(wpa_s, md, ies, ies_len); + sme_update_ft_ies(wpa_s, md, ies, ies_len); + return wpa_drv_update_ft_ies(wpa_s, md, ies, ies_len); +} + + +static int wpa_supplicant_send_ft_action(void *ctx, u8 action, + const u8 *target_ap, + const u8 *ies, size_t ies_len) +{ + struct wpa_supplicant *wpa_s = ctx; + int ret; + u8 *data, *pos; + size_t data_len; + + if (action != 1) { + wpa_printf(MSG_ERROR, "Unsupported send_ft_action action %d", + action); + return -1; + } + + /* + * Action frame payload: + * Category[1] = 6 (Fast BSS Transition) + * Action[1] = 1 (Fast BSS Transition Request) + * STA Address + * Target AP Address + * FT IEs + */ + + data_len = 2 + 2 * ETH_ALEN + ies_len; + data = os_malloc(data_len); + if (data == NULL) + return -1; + pos = data; + *pos++ = 0x06; /* FT Action category */ + *pos++ = action; + os_memcpy(pos, wpa_s->own_addr, ETH_ALEN); + pos += ETH_ALEN; + os_memcpy(pos, target_ap, ETH_ALEN); + pos += ETH_ALEN; + os_memcpy(pos, ies, ies_len); + + ret = wpa_drv_send_action(wpa_s, wpa_s->assoc_freq, 0, + wpa_s->bssid, wpa_s->own_addr, wpa_s->bssid, + data, data_len, 0); + os_free(data); + + return ret; +} + + +static int wpa_supplicant_mark_authenticated(void *ctx, const u8 *target_ap) +{ + struct wpa_supplicant *wpa_s = ctx; + struct wpa_driver_auth_params params; + struct wpa_bss *bss; + + bss = wpa_bss_get_bssid(wpa_s, target_ap); + if (bss == NULL) + return -1; + + os_memset(¶ms, 0, sizeof(params)); + params.bssid = target_ap; + params.freq = bss->freq; + params.ssid = bss->ssid; + params.ssid_len = bss->ssid_len; + params.auth_alg = WPA_AUTH_ALG_FT; + params.local_state_change = 1; + return wpa_drv_authenticate(wpa_s, ¶ms); +} +#endif /* CONFIG_IEEE80211R */ + + +#ifdef CONFIG_TDLS + +static int wpa_supplicant_tdls_get_capa(void *ctx, int *tdls_supported, + int *tdls_ext_setup, + int *tdls_chan_switch) +{ + struct wpa_supplicant *wpa_s = ctx; + + *tdls_supported = 0; + *tdls_ext_setup = 0; + *tdls_chan_switch = 0; + + if (!wpa_s->drv_capa_known) + return -1; + + if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_TDLS_SUPPORT) + *tdls_supported = 1; + + if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_TDLS_EXTERNAL_SETUP) + *tdls_ext_setup = 1; + + if (wpa_s->drv_flags & WPA_DRIVER_FLAGS_TDLS_CHANNEL_SWITCH) + *tdls_chan_switch = 1; + + return 0; +} + + +static int wpa_supplicant_send_tdls_mgmt(void *ctx, const u8 *dst, + u8 action_code, u8 dialog_token, + u16 status_code, u32 peer_capab, + int initiator, const u8 *buf, + size_t len) +{ + struct wpa_supplicant *wpa_s = ctx; + return wpa_drv_send_tdls_mgmt(wpa_s, dst, action_code, dialog_token, + status_code, peer_capab, initiator, buf, + len); +} + + +static int wpa_supplicant_tdls_oper(void *ctx, int oper, const u8 *peer) +{ + struct wpa_supplicant *wpa_s = ctx; + return wpa_drv_tdls_oper(wpa_s, oper, peer); +} + + +static int wpa_supplicant_tdls_peer_addset( + void *ctx, const u8 *peer, int add, u16 aid, u16 capability, + const u8 *supp_rates, size_t supp_rates_len, + const struct ieee80211_ht_capabilities *ht_capab, + const struct ieee80211_vht_capabilities *vht_capab, + u8 qosinfo, int wmm, const u8 *ext_capab, size_t ext_capab_len, + const u8 *supp_channels, size_t supp_channels_len, + const u8 *supp_oper_classes, size_t supp_oper_classes_len) +{ + struct wpa_supplicant *wpa_s = ctx; + struct hostapd_sta_add_params params; + + os_memset(¶ms, 0, sizeof(params)); + + params.addr = peer; + params.aid = aid; + params.capability = capability; + params.flags = WPA_STA_TDLS_PEER | WPA_STA_AUTHORIZED; + + /* + * Don't rely only on qosinfo for WMM capability. It may be 0 even when + * present. Allow the WMM IE to also indicate QoS support. + */ + if (wmm || qosinfo) + params.flags |= WPA_STA_WMM; + + params.ht_capabilities = ht_capab; + params.vht_capabilities = vht_capab; + params.qosinfo = qosinfo; + params.listen_interval = 0; + params.supp_rates = supp_rates; + params.supp_rates_len = supp_rates_len; + params.set = !add; + params.ext_capab = ext_capab; + params.ext_capab_len = ext_capab_len; + params.supp_channels = supp_channels; + params.supp_channels_len = supp_channels_len; + params.supp_oper_classes = supp_oper_classes; + params.supp_oper_classes_len = supp_oper_classes_len; + + return wpa_drv_sta_add(wpa_s, ¶ms); +} + + +static int wpa_supplicant_tdls_enable_channel_switch( + void *ctx, const u8 *addr, u8 oper_class, + const struct hostapd_freq_params *params) +{ + struct wpa_supplicant *wpa_s = ctx; + + return wpa_drv_tdls_enable_channel_switch(wpa_s, addr, oper_class, + params); +} + + +static int wpa_supplicant_tdls_disable_channel_switch(void *ctx, const u8 *addr) +{ + struct wpa_supplicant *wpa_s = ctx; + + return wpa_drv_tdls_disable_channel_switch(wpa_s, addr); +} + +#endif /* CONFIG_TDLS */ + +#endif /* CONFIG_NO_WPA */ + + +enum wpa_ctrl_req_type wpa_supplicant_ctrl_req_from_string(const char *field) +{ + if (os_strcmp(field, "IDENTITY") == 0) + return WPA_CTRL_REQ_EAP_IDENTITY; + else if (os_strcmp(field, "PASSWORD") == 0) + return WPA_CTRL_REQ_EAP_PASSWORD; + else if (os_strcmp(field, "NEW_PASSWORD") == 0) + return WPA_CTRL_REQ_EAP_NEW_PASSWORD; + else if (os_strcmp(field, "PIN") == 0) + return WPA_CTRL_REQ_EAP_PIN; + else if (os_strcmp(field, "OTP") == 0) + return WPA_CTRL_REQ_EAP_OTP; + else if (os_strcmp(field, "PASSPHRASE") == 0) + return WPA_CTRL_REQ_EAP_PASSPHRASE; + else if (os_strcmp(field, "SIM") == 0) + return WPA_CTRL_REQ_SIM; + else if (os_strcmp(field, "PSK_PASSPHRASE") == 0) + return WPA_CTRL_REQ_PSK_PASSPHRASE; + return WPA_CTRL_REQ_UNKNOWN; +} + + +const char * wpa_supplicant_ctrl_req_to_string(enum wpa_ctrl_req_type field, + const char *default_txt, + const char **txt) +{ + const char *ret = NULL; + + *txt = default_txt; + + switch (field) { + case WPA_CTRL_REQ_EAP_IDENTITY: + *txt = "Identity"; + ret = "IDENTITY"; + break; + case WPA_CTRL_REQ_EAP_PASSWORD: + *txt = "Password"; + ret = "PASSWORD"; + break; + case WPA_CTRL_REQ_EAP_NEW_PASSWORD: + *txt = "New Password"; + ret = "NEW_PASSWORD"; + break; + case WPA_CTRL_REQ_EAP_PIN: + *txt = "PIN"; + ret = "PIN"; + break; + case WPA_CTRL_REQ_EAP_OTP: + ret = "OTP"; + break; + case WPA_CTRL_REQ_EAP_PASSPHRASE: + *txt = "Private key passphrase"; + ret = "PASSPHRASE"; + break; + case WPA_CTRL_REQ_SIM: + ret = "SIM"; + break; + case WPA_CTRL_REQ_PSK_PASSPHRASE: + *txt = "PSK or passphrase"; + ret = "PSK_PASSPHRASE"; + break; + default: + break; + } + + /* txt needs to be something */ + if (*txt == NULL) { + wpa_printf(MSG_WARNING, "No message for request %d", field); + ret = NULL; + } + + return ret; +} + + +void wpas_send_ctrl_req(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, + const char *field_name, const char *txt) +{ + char *buf; + size_t buflen; + int len; + + buflen = 100 + os_strlen(txt) + ssid->ssid_len; + buf = os_malloc(buflen); + if (buf == NULL) + return; + len = os_snprintf(buf, buflen, "%s-%d:%s needed for SSID ", + field_name, ssid->id, txt); + if (os_snprintf_error(buflen, len)) { + os_free(buf); + return; + } + if (ssid->ssid && buflen > len + ssid->ssid_len) { + os_memcpy(buf + len, ssid->ssid, ssid->ssid_len); + len += ssid->ssid_len; + buf[len] = '\0'; + } + buf[buflen - 1] = '\0'; + wpa_msg(wpa_s, MSG_INFO, WPA_CTRL_REQ "%s", buf); + os_free(buf); +} + + +#ifdef IEEE8021X_EAPOL +#if defined(CONFIG_CTRL_IFACE) || !defined(CONFIG_NO_STDOUT_DEBUG) +static void wpa_supplicant_eap_param_needed(void *ctx, + enum wpa_ctrl_req_type field, + const char *default_txt) +{ + struct wpa_supplicant *wpa_s = ctx; + struct wpa_ssid *ssid = wpa_s->current_ssid; + const char *field_name, *txt = NULL; + + if (ssid == NULL) + return; + + wpas_notify_network_request(wpa_s, ssid, field, default_txt); + + field_name = wpa_supplicant_ctrl_req_to_string(field, default_txt, + &txt); + if (field_name == NULL) { + wpa_printf(MSG_WARNING, "Unhandled EAP param %d needed", + field); + return; + } + + wpas_notify_eap_status(wpa_s, "eap parameter needed", field_name); + + wpas_send_ctrl_req(wpa_s, ssid, field_name, txt); +} +#else /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */ +#define wpa_supplicant_eap_param_needed NULL +#endif /* CONFIG_CTRL_IFACE || !CONFIG_NO_STDOUT_DEBUG */ + + +#ifdef CONFIG_EAP_PROXY +static void wpa_supplicant_eap_proxy_cb(void *ctx) +{ + struct wpa_supplicant *wpa_s = ctx; + size_t len; + + wpa_s->mnc_len = eapol_sm_get_eap_proxy_imsi(wpa_s->eapol, + wpa_s->imsi, &len); + if (wpa_s->mnc_len > 0) { + wpa_s->imsi[len] = '\0'; + wpa_printf(MSG_DEBUG, "eap_proxy: IMSI %s (MNC length %d)", + wpa_s->imsi, wpa_s->mnc_len); + } else { + wpa_printf(MSG_DEBUG, "eap_proxy: IMSI not available"); + } +} +#endif /* CONFIG_EAP_PROXY */ + + +static void wpa_supplicant_port_cb(void *ctx, int authorized) +{ + struct wpa_supplicant *wpa_s = ctx; +#ifdef CONFIG_AP + if (wpa_s->ap_iface) { + wpa_printf(MSG_DEBUG, "AP mode active - skip EAPOL Supplicant " + "port status: %s", + authorized ? "Authorized" : "Unauthorized"); + return; + } +#endif /* CONFIG_AP */ + wpa_printf(MSG_DEBUG, "EAPOL: Supplicant port status: %s", + authorized ? "Authorized" : "Unauthorized"); + wpa_drv_set_supp_port(wpa_s, authorized); +} + + +static void wpa_supplicant_cert_cb(void *ctx, int depth, const char *subject, + const char *altsubject[], int num_altsubject, + const char *cert_hash, + const struct wpabuf *cert) +{ + struct wpa_supplicant *wpa_s = ctx; + + wpas_notify_certification(wpa_s, depth, subject, altsubject, + num_altsubject, cert_hash, cert); +} + + +static void wpa_supplicant_status_cb(void *ctx, const char *status, + const char *parameter) +{ + struct wpa_supplicant *wpa_s = ctx; + + wpas_notify_eap_status(wpa_s, status, parameter); +} + + +static void wpa_supplicant_set_anon_id(void *ctx, const u8 *id, size_t len) +{ + struct wpa_supplicant *wpa_s = ctx; + char *str; + int res; + + wpa_hexdump_ascii(MSG_DEBUG, "EAP method updated anonymous_identity", + id, len); + + if (wpa_s->current_ssid == NULL) + return; + + if (id == NULL) { + if (wpa_config_set(wpa_s->current_ssid, "anonymous_identity", + "NULL", 0) < 0) + return; + } else { + str = os_malloc(len * 2 + 1); + if (str == NULL) + return; + wpa_snprintf_hex(str, len * 2 + 1, id, len); + res = wpa_config_set(wpa_s->current_ssid, "anonymous_identity", + str, 0); + os_free(str); + if (res < 0) + return; + } + + if (wpa_s->conf->update_config) { + res = wpa_config_write(wpa_s->confname, wpa_s->conf); + if (res) { + wpa_printf(MSG_DEBUG, "Failed to update config after " + "anonymous_id update"); + } + } +} +#endif /* IEEE8021X_EAPOL */ + + +int wpa_supplicant_init_eapol(struct wpa_supplicant *wpa_s) +{ +#ifdef IEEE8021X_EAPOL + struct eapol_ctx *ctx; + ctx = os_zalloc(sizeof(*ctx)); + if (ctx == NULL) { + wpa_printf(MSG_ERROR, "Failed to allocate EAPOL context."); + return -1; + } + + ctx->ctx = wpa_s; + ctx->msg_ctx = wpa_s; + ctx->eapol_send_ctx = wpa_s; + ctx->preauth = 0; + ctx->eapol_done_cb = wpa_supplicant_notify_eapol_done; + ctx->eapol_send = wpa_supplicant_eapol_send; + ctx->set_wep_key = wpa_eapol_set_wep_key; + ctx->aborted_cached = wpa_supplicant_aborted_cached; + ctx->opensc_engine_path = wpa_s->conf->opensc_engine_path; + ctx->pkcs11_engine_path = wpa_s->conf->pkcs11_engine_path; + ctx->pkcs11_module_path = wpa_s->conf->pkcs11_module_path; + ctx->openssl_ciphers = wpa_s->conf->openssl_ciphers; + ctx->wps = wpa_s->wps; + ctx->eap_param_needed = wpa_supplicant_eap_param_needed; +#ifdef CONFIG_EAP_PROXY + ctx->eap_proxy_cb = wpa_supplicant_eap_proxy_cb; +#endif /* CONFIG_EAP_PROXY */ + ctx->port_cb = wpa_supplicant_port_cb; + ctx->cb = wpa_supplicant_eapol_cb; + ctx->cert_cb = wpa_supplicant_cert_cb; + ctx->cert_in_cb = wpa_s->conf->cert_in_cb; + ctx->status_cb = wpa_supplicant_status_cb; + ctx->set_anon_id = wpa_supplicant_set_anon_id; + ctx->cb_ctx = wpa_s; + wpa_s->eapol = eapol_sm_init(ctx); + if (wpa_s->eapol == NULL) { + os_free(ctx); + wpa_printf(MSG_ERROR, "Failed to initialize EAPOL state " + "machines."); + return -1; + } +#endif /* IEEE8021X_EAPOL */ + + return 0; +} + + +#ifndef CONFIG_NO_WPA +static void wpa_supplicant_set_rekey_offload(void *ctx, + const u8 *kek, size_t kek_len, + const u8 *kck, size_t kck_len, + const u8 *replay_ctr) +{ + struct wpa_supplicant *wpa_s = ctx; + + wpa_drv_set_rekey_info(wpa_s, kek, kek_len, kck, kck_len, replay_ctr); +} +#endif /* CONFIG_NO_WPA */ + +#ifndef CONFIG_NO_WPA +static int wpa_supplicant_key_mgmt_set_pmk(void *ctx, const u8 *pmk, + size_t pmk_len) +{ + struct wpa_supplicant *wpa_s = ctx; + + if (wpa_s->conf->key_mgmt_offload && + (wpa_s->drv_flags & WPA_DRIVER_FLAGS_KEY_MGMT_OFFLOAD)) + { + return wpa_drv_set_key(wpa_s, WPA_ALG_PMK, NULL, 0, 0, + NULL, 0, pmk, pmk_len); + } + else + return 0; +} +#endif + +int wpa_supplicant_init_wpa(struct wpa_supplicant *wpa_s) +{ +#ifndef CONFIG_NO_WPA + struct wpa_sm_ctx *ctx; + ctx = os_zalloc(sizeof(*ctx)); + if (ctx == NULL) { + wpa_printf(MSG_ERROR, "Failed to allocate WPA context."); + return -1; + } + + ctx->ctx = wpa_s; + ctx->msg_ctx = wpa_s; + ctx->set_state = _wpa_supplicant_set_state; + ctx->get_state = _wpa_supplicant_get_state; + ctx->deauthenticate = _wpa_supplicant_deauthenticate; + ctx->set_key = wpa_supplicant_set_key; + ctx->get_network_ctx = wpa_supplicant_get_network_ctx; + ctx->get_bssid = wpa_supplicant_get_bssid; + ctx->ether_send = _wpa_ether_send; + ctx->get_beacon_ie = wpa_supplicant_get_beacon_ie; + ctx->alloc_eapol = _wpa_alloc_eapol; + ctx->cancel_auth_timeout = _wpa_supplicant_cancel_auth_timeout; + ctx->add_pmkid = wpa_supplicant_add_pmkid; + ctx->remove_pmkid = wpa_supplicant_remove_pmkid; + ctx->mlme_setprotection = wpa_supplicant_mlme_setprotection; +#ifdef CONFIG_IEEE80211R + ctx->update_ft_ies = wpa_supplicant_update_ft_ies; + ctx->send_ft_action = wpa_supplicant_send_ft_action; + ctx->mark_authenticated = wpa_supplicant_mark_authenticated; +#endif /* CONFIG_IEEE80211R */ +#ifdef CONFIG_TDLS + ctx->tdls_get_capa = wpa_supplicant_tdls_get_capa; + ctx->send_tdls_mgmt = wpa_supplicant_send_tdls_mgmt; + ctx->tdls_oper = wpa_supplicant_tdls_oper; + ctx->tdls_peer_addset = wpa_supplicant_tdls_peer_addset; + ctx->tdls_enable_channel_switch = + wpa_supplicant_tdls_enable_channel_switch; + ctx->tdls_disable_channel_switch = + wpa_supplicant_tdls_disable_channel_switch; +#endif /* CONFIG_TDLS */ + ctx->set_rekey_offload = wpa_supplicant_set_rekey_offload; + ctx->key_mgmt_set_pmk = wpa_supplicant_key_mgmt_set_pmk; + + wpa_s->wpa = wpa_sm_init(ctx); + if (wpa_s->wpa == NULL) { + wpa_printf(MSG_ERROR, "Failed to initialize WPA state " + "machine"); + os_free(ctx); + return -1; + } +#endif /* CONFIG_NO_WPA */ + + return 0; +} + + +void wpa_supplicant_rsn_supp_set_config(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid) +{ + struct rsn_supp_config conf; + if (ssid) { + os_memset(&conf, 0, sizeof(conf)); + conf.network_ctx = ssid; + conf.peerkey_enabled = ssid->peerkey; + conf.allowed_pairwise_cipher = ssid->pairwise_cipher; +#ifdef IEEE8021X_EAPOL + conf.proactive_key_caching = ssid->proactive_key_caching < 0 ? + wpa_s->conf->okc : ssid->proactive_key_caching; + conf.eap_workaround = ssid->eap_workaround; + conf.eap_conf_ctx = &ssid->eap; +#endif /* IEEE8021X_EAPOL */ + conf.ssid = ssid->ssid; + conf.ssid_len = ssid->ssid_len; + conf.wpa_ptk_rekey = ssid->wpa_ptk_rekey; +#ifdef CONFIG_P2P + if (ssid->p2p_group && wpa_s->current_bss && + !wpa_s->p2p_disable_ip_addr_req) { + struct wpabuf *p2p; + p2p = wpa_bss_get_vendor_ie_multi(wpa_s->current_bss, + P2P_IE_VENDOR_TYPE); + if (p2p) { + u8 group_capab; + group_capab = p2p_get_group_capab(p2p); + if (group_capab & + P2P_GROUP_CAPAB_IP_ADDR_ALLOCATION) + conf.p2p = 1; + wpabuf_free(p2p); + } + } +#endif /* CONFIG_P2P */ + } + wpa_sm_set_config(wpa_s->wpa, ssid ? &conf : NULL); +} diff --git a/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/wpas_glue.h b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/wpas_glue.h new file mode 100755 index 0000000..5585e56 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/wpas_glue.h @@ -0,0 +1,28 @@ +/* + * WPA Supplicant - Glue code to setup EAPOL and RSN modules + * Copyright (c) 2003-2008, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef WPAS_GLUE_H +#define WPAS_GLUE_H + +enum wpa_ctrl_req_type; + +int wpa_supplicant_init_eapol(struct wpa_supplicant *wpa_s); +int wpa_supplicant_init_wpa(struct wpa_supplicant *wpa_s); +void wpa_supplicant_rsn_supp_set_config(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid); + +const char * wpa_supplicant_ctrl_req_to_string(enum wpa_ctrl_req_type field, + const char *default_txt, + const char **txt); + +enum wpa_ctrl_req_type wpa_supplicant_ctrl_req_from_string(const char *field); + +void wpas_send_ctrl_req(struct wpa_supplicant *wpa_s, struct wpa_ssid *ssid, + const char *field_name, const char *txt); + +#endif /* WPAS_GLUE_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/wpas_kay.h b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/wpas_kay.h new file mode 100755 index 0000000..b7236d0 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/wpas_kay.h @@ -0,0 +1,41 @@ +/* + * IEEE 802.1X-2010 KaY Interface + * Copyright (c) 2013-2014, Qualcomm Atheros, Inc. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef WPAS_KAY_H +#define WPAS_KAY_H + +#ifdef CONFIG_MACSEC + +int ieee802_1x_alloc_kay_sm(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid); +void * ieee802_1x_notify_create_actor(struct wpa_supplicant *wpa_s, + const u8 *peer_addr); +void ieee802_1x_dealloc_kay_sm(struct wpa_supplicant *wpa_s); + +#else /* CONFIG_MACSEC */ + +static inline int ieee802_1x_alloc_kay_sm(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid) +{ + return 0; +} + +static inline void * +ieee802_1x_notify_create_actor(struct wpa_supplicant *wpa_s, + const u8 *peer_addr) +{ + return NULL; +} + +static inline void ieee802_1x_dealloc_kay_sm(struct wpa_supplicant *wpa_s) +{ +} + +#endif /* CONFIG_MACSEC */ + +#endif /* WPAS_KAY_H */ diff --git a/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/wps_supplicant.h b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/wps_supplicant.h new file mode 100755 index 0000000..3c25ca8 --- /dev/null +++ b/beken_os/beken378/func/hostapd-2.5/wpa_supplicant/wps_supplicant.h @@ -0,0 +1,152 @@ +/* + * wpa_supplicant / WPS integration + * Copyright (c) 2008-2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef WPS_SUPPLICANT_H +#define WPS_SUPPLICANT_H + +struct wpa_scan_results; + +#ifdef CONFIG_WPS + +#include "wps/wps.h" +#include "wps/wps_defs.h" + +struct wpa_bss; + +struct wps_new_ap_settings { + const char *ssid_hex; + const char *auth; + const char *encr; + const char *key_hex; +}; + +int wpas_wps_init(struct wpa_supplicant *wpa_s); +void wpas_wps_deinit(struct wpa_supplicant *wpa_s); +int wpas_wps_eapol_cb(struct wpa_supplicant *wpa_s); +enum wps_request_type wpas_wps_get_req_type(struct wpa_ssid *ssid); +int wpas_wps_start_pbc(struct wpa_supplicant *wpa_s, const u8 *bssid, + int p2p_group); +int wpas_wps_start_pin(struct wpa_supplicant *wpa_s, const u8 *bssid, + const char *pin, int p2p_group, u16 dev_pw_id); +void wpas_wps_pbc_overlap(struct wpa_supplicant *wpa_s); +int wpas_wps_cancel(struct wpa_supplicant *wpa_s); +int wpas_wps_start_reg(struct wpa_supplicant *wpa_s, const u8 *bssid, + const char *pin, struct wps_new_ap_settings *settings); +int wpas_wps_ssid_bss_match(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid, struct wpa_bss *bss); +int wpas_wps_ssid_wildcard_ok(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid, struct wpa_bss *bss); +int wpas_wps_scan_pbc_overlap(struct wpa_supplicant *wpa_s, + struct wpa_bss *selected, struct wpa_ssid *ssid); +void wpas_wps_notify_scan_results(struct wpa_supplicant *wpa_s); +int wpas_wps_searching(struct wpa_supplicant *wpa_s); +int wpas_wps_scan_result_text(const u8 *ies, size_t ies_len, char *pos, + char *end); +int wpas_wps_er_start(struct wpa_supplicant *wpa_s, const char *filter); +void wpas_wps_er_stop(struct wpa_supplicant *wpa_s); +int wpas_wps_er_add_pin(struct wpa_supplicant *wpa_s, const u8 *addr, + const char *uuid, const char *pin); +int wpas_wps_er_pbc(struct wpa_supplicant *wpa_s, const char *uuid); +int wpas_wps_er_learn(struct wpa_supplicant *wpa_s, const char *uuid, + const char *pin); +int wpas_wps_er_set_config(struct wpa_supplicant *wpa_s, const char *uuid, + int id); +int wpas_wps_er_config(struct wpa_supplicant *wpa_s, const char *uuid, + const char *pin, struct wps_new_ap_settings *settings); +struct wpabuf * wpas_wps_er_nfc_config_token(struct wpa_supplicant *wpa_s, + int ndef, const char *uuid); +int wpas_wps_terminate_pending(struct wpa_supplicant *wpa_s); +void wpas_wps_update_config(struct wpa_supplicant *wpa_s); +struct wpabuf * wpas_wps_nfc_config_token(struct wpa_supplicant *wpa_s, + int ndef, const char *id_str); +struct wpabuf * wpas_wps_nfc_token(struct wpa_supplicant *wpa_s, int ndef); +int wpas_wps_start_nfc(struct wpa_supplicant *wpa_s, const u8 *dev_addr, + const u8 *bssid, + const struct wpabuf *dev_pw, u16 dev_pw_id, + int p2p_group, const u8 *peer_pubkey_hash, + const u8 *ssid, size_t ssid_len, int freq); +int wpas_wps_nfc_tag_read(struct wpa_supplicant *wpa_s, + const struct wpabuf *data, int forced_freq); +struct wpabuf * wpas_wps_nfc_handover_req(struct wpa_supplicant *wpa_s, + int ndef); +struct wpabuf * wpas_wps_nfc_handover_sel(struct wpa_supplicant *wpa_s, + int ndef, int cr, const char *uuid); +int wpas_wps_nfc_report_handover(struct wpa_supplicant *wpa_s, + const struct wpabuf *req, + const struct wpabuf *sel); +int wpas_er_wps_nfc_report_handover(struct wpa_supplicant *wpa_s, + const struct wpabuf *req, + const struct wpabuf *sel); +void wpas_wps_update_ap_info(struct wpa_supplicant *wpa_s, + struct wpa_scan_results *scan_res); +void wpas_wps_notify_assoc(struct wpa_supplicant *wpa_s, const u8 *bssid); + +#else /* CONFIG_WPS */ + +static inline int wpas_wps_init(struct wpa_supplicant *wpa_s) +{ + return 0; +} + +static inline void wpas_wps_deinit(struct wpa_supplicant *wpa_s) +{ +} + +static inline int wpas_wps_eapol_cb(struct wpa_supplicant *wpa_s) +{ + return 0; +} + +static inline u8 wpas_wps_get_req_type(struct wpa_ssid *ssid) +{ + return 0; +} + +static inline int wpas_wps_ssid_bss_match(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid, + struct wpa_bss *bss) +{ + return -1; +} + +static inline int wpas_wps_ssid_wildcard_ok(struct wpa_supplicant *wpa_s, + struct wpa_ssid *ssid, + struct wpa_bss *bss) +{ + return 0; +} + +static inline int wpas_wps_scan_pbc_overlap(struct wpa_supplicant *wpa_s, + struct wpa_bss *selected, + struct wpa_ssid *ssid) +{ + return 0; +} + +static inline void wpas_wps_notify_scan_results(struct wpa_supplicant *wpa_s) +{ +} + +static inline int wpas_wps_searching(struct wpa_supplicant *wpa_s) +{ + return 0; +} + +static inline void wpas_wps_update_ap_info(struct wpa_supplicant *wpa_s, + struct wpa_scan_results *scan_res) +{ +} + +static inline void wpas_wps_notify_assoc(struct wpa_supplicant *wpa_s, + const u8 *bssid) +{ +} + +#endif /* CONFIG_WPS */ + +#endif /* WPS_SUPPLICANT_H */ diff --git a/beken_os/beken378/func/hostapd_intf/hostapd_intf.c b/beken_os/beken378/func/hostapd_intf/hostapd_intf.c new file mode 100755 index 0000000..98a4c10 --- /dev/null +++ b/beken_os/beken378/func/hostapd_intf/hostapd_intf.c @@ -0,0 +1,1113 @@ +#include "include.h" +#include "hostapd_intf.h" +#include "sk_intf.h" +#include "mem_pub.h" +#include "me_task.h" +#include "ke_event.h" +#include "fake_socket.h" +#include "uart_pub.h" +#include "ieee802_11_defs.h" +#include "driver.h" +#include "driver_beken.h" +#include "hostapd_cfg.h" +#include "rw_pub.h" +#include "drv_model_pub.h" +#include "sta_mgmt.h" +#include "vif_mgmt.h" +#include "sa_station.h" +#include "sa_ap.h" +#include "wlan_ui_pub.h" +#include "param_config.h" +#include "sm_task.h" +#include "rw_msg_rx.h" +#include "mm_bcn.h" + +#if CFG_ROLE_LAUNCH +#include "role_launch.h" +#endif +#include "mcu_ps_pub.h" +#include "power_save_pub.h" +#include "fake_clock_pub.h" +#include "errno.h" +#include "ieee802_11_common.h" + +struct scanu_rst_upload *s_scan_result_upload_ptr; + +extern enum hostapd_hw_mode ieee80211_freq_to_chan(int freq, u8 *channel); +extern FUNC_1PARAM_PTR bk_wlan_get_status_cb(void); +void wpa_hostapd_release_scan_rst(void); +#if CFG_WPA_CTRL_IFACE +extern int wpa_is_scan_only(); +#endif + +struct mm_bcn_change_req *hadp_intf_get_bcn_change_req(uint8_t vif_id, struct beacon_data *bcn_info) +{ +#define BCN_TIM_IE_LEN 6 + uint8_t tim_ie[BCN_TIM_IE_LEN] = {5, 4, 0, 2, 0, 0}; + uint8_t *beacon_ptr = 0; + uint32_t bcn_len; + struct mm_bcn_change_req *req = 0; + +#ifdef ADD_BEACON_IES_ENABLE + bcn_len = bcn_info->head_len + BCN_TIM_IE_LEN + bcn_info->tail_len + + bcn_info->beacon_ies_len; +#else + bcn_len = bcn_info->head_len + BCN_TIM_IE_LEN + bcn_info->tail_len; +#endif + + beacon_ptr = (uint8_t *)os_malloc(bcn_len); + if (!beacon_ptr) + goto exit_get_failed; + + req = ke_msg_alloc(MM_BCN_CHANGE_REQ, TASK_MM, TASK_API, + sizeof(struct mm_bcn_change_req)); + if (!req) + goto exit_get_failed; + + if(bcn_info->head && bcn_info->head_len) + { + os_memcpy(beacon_ptr, bcn_info->head, bcn_info->head_len); + } + + os_memcpy((void *)((uint32_t)beacon_ptr + bcn_info->head_len), tim_ie, BCN_TIM_IE_LEN); + + if(bcn_info->tail && bcn_info->tail_len) + { + os_memcpy((void *)((uint32_t)beacon_ptr + bcn_info->head_len + BCN_TIM_IE_LEN), + bcn_info->tail, bcn_info->tail_len); + } + +#ifdef ADD_BEACON_IES_ENABLE + if(bcn_info->beacon_ies && bcn_info->beacon_ies_len) + { + os_memcpy((void *)((uint32_t)beacon_ptr + bcn_info->head_len + bcn_info->tail_len), + bcn_info->beacon_ies, bcn_info->beacon_ies_len); + } +#endif // ADD_BEACON_IES_ENABLE + + req->bcn_ptr = (uint32_t)(beacon_ptr); + req->bcn_len = bcn_len; + req->tim_len = BCN_TIM_IE_LEN; + req->tim_oft = bcn_info->head_len; + req->inst_nbr = vif_id; + req->bcn_ptr_malloc_flag = 1; + + return req; + +exit_get_failed: + if(req) + os_free(req); + + if(beacon_ptr) + os_free(beacon_ptr); + + return NULL; +} + +struct mm_bcn_change_req *hadp_intf_get_csa_bcn_req(struct csa_settings *settings, + uint8_t vif_id, struct beacon_data *bcn_info) +{ + uint16_t csa_cnt_offset; + struct mm_bcn_change_req *req; + + req = hadp_intf_get_bcn_change_req(vif_id, bcn_info); + +#if CFG_USE_WPA_29 + csa_cnt_offset = settings->counter_offset_beacon[0] + 6 + bcn_info->head_len; // tim_ie_len == 6 +#else + csa_cnt_offset = settings->counter_offset_beacon + 6 + bcn_info->head_len; // tim_ie_len == 6 +#endif + req->csa_oft[0] = csa_cnt_offset & 0xff; + req->csa_oft[1] = (csa_cnt_offset & 0xff00) >> 8; + + return req; +} + +struct mm_bcn_change_req *hadp_intf_get_csa_after_bcn_req(uint8_t vif_id, struct beacon_data *bcn_info) +{ + return hadp_intf_get_bcn_change_req(vif_id, bcn_info); +} + +int wpa_intf_channel_switch(struct prism2_hostapd_param *param, int len) +{ + uint8_t vif_id; + uint32_t freq; + uint8_t chann; + uint32_t csa_count; + struct vif_info_tag *vif; + struct csa_settings *settings; + struct mm_bcn_change_req *param_csa; + struct mm_bcn_change_req *param_csa_after; + + freq = param->u.chan_switch.freq; + csa_count = param->u.chan_switch.csa_cnt; + + vif_id = param->vif_idx; + vif = vif_mgmt_get_entry(vif_id); + + ieee80211_freq_to_chan(freq, &chann); + if(chann == bk_wlan_ap_get_channel_config()) + { + WPAS_WPRT("csa_over_same_channel\r\n"); + return -1; + } + +#if CFG_ROLE_LAUNCH + if(rl_pre_sta_set_status(RL_STATUS_STA_CHANNEL_SWITCHING)) + { + return -1; + } +#endif + + mm_channel_switch_init(vif, freq, csa_count); + + WPAS_PRT("[csa]intf_channel_switch:%x:%d:%d\r\n", vif, param->vif_idx, csa_count); + settings = param->u.chan_switch.settings; + param_csa = hadp_intf_get_csa_bcn_req(settings, vif_id, &settings->beacon_csa); + param_csa_after = hadp_intf_get_csa_after_bcn_req(vif_id, &settings->beacon_after); + mm_csa_beacon_change(param_csa, param_csa_after); + + return 0; +} + +int hapd_intf_sta_add(struct prism2_hostapd_param *param, int len) +{ + int ret; + struct add_sta_st add_sta; + struct me_sta_add_cfm *cfm + = (struct me_sta_add_cfm *)os_malloc(sizeof(struct me_sta_add_cfm)); + + if(NULL == cfm) + { + WPAS_PRT("sta_add buf_failed\r\n"); + return HINTF_FAILURE; + } + + add_sta.aid = param->u.add_sta.aid; + add_sta.ap_vif_idx = param->vif_idx; + add_sta.sta_addr = param->sta_addr; + add_sta.capability = param->u.add_sta.capability; + add_sta.tx_supp_rates = param->u.add_sta.tx_supp_rates; + + ret = rw_msg_send_me_sta_add(&add_sta, cfm); + if(!ret && (cfm->status == CO_OK)) + { + WPAS_PRT("sta_idx:%d, pm_state:%d\r\n", cfm->sta_idx, cfm->pm_state); + +#if CFG_USE_AP_PS + rwm_flush_txing_list(cfm->sta_idx); +#endif + } + os_free(cfm); + + return ret; +} + +int hapd_get_sta_info(struct prism2_hostapd_param *param, int len) +{ + int delta_sec = 0; + struct sta_info_tag *entry; + uint32 tick_cnt; + + if(NULL == param) + { + return -1; + } + + param->u.get_info_sta.inactive_sec = 0; + + entry = sta_mgmt_get_sta(param->sta_addr); + WPAS_PRT("entry:0x%x entry->pre_rx_timepoint:%d\r\n", entry, entry->pre_rx_timepoint); + if(entry && entry->pre_rx_timepoint) + { + tick_cnt = fclk_get_tick(); + if(tick_cnt > entry->pre_rx_timepoint) + { + delta_sec = (tick_cnt - entry->pre_rx_timepoint) / TICK_PER_SECOND; + } + else + { + delta_sec = (0xFFFFFFFF - entry->pre_rx_timepoint + tick_cnt) / TICK_PER_SECOND; + } + WPAS_PRT("delta_sec:%d\r\n", delta_sec); + param->u.get_info_sta.inactive_sec = delta_sec; + } + + return 0; +} + +int hapd_intf_sta_del(struct prism2_hostapd_param *param, int len) +{ + bool tdls_sta = 0; + u8 sta_idx; + sta_idx = rwm_mgmt_sta_mac2idx(param->sta_addr); + + if(sta_idx == 0xff) + return 0; + + WPAS_PRT("hapd_intf_sta_del:%d\r\n", sta_idx); + +#if CFG_USE_AP_PS + rwm_flush_txing_list(sta_idx); +#endif + + return rw_msg_send_me_sta_del(sta_idx, tdls_sta); +} + +int hapd_intf_add_key(struct prism2_hostapd_param *param, int len) +{ + int ret; + KEY_PARAM_T key_param; + struct mm_key_add_cfm *cfm + = (struct mm_key_add_cfm *)os_malloc(sizeof(struct mm_key_add_cfm)); + + if(NULL == cfm) + { + WPAS_PRT("key_add buf_failed\r\n"); + return HINTF_FAILURE; + } + + if(os_strcmp((char *)param->u.crypt.alg, "WEP40") == 0) + { + WPAS_PRT("add WEP40\r\n"); + key_param.cipher_suite = MAC_RSNIE_CIPHER_WEP40; + } + else if(os_strcmp((char *)param->u.crypt.alg, "WEP104") == 0) + { + WPAS_PRT("add WEP104\r\n"); + key_param.cipher_suite = MAC_RSNIE_CIPHER_WEP104; + } + else if(os_strcmp((char *)param->u.crypt.alg, "TKIP") == 0) + { + WPAS_PRT("add TKIP\r\n"); + key_param.cipher_suite = MAC_RSNIE_CIPHER_TKIP; + } + else if(os_strcmp((char *)param->u.crypt.alg, "CCMP") == 0) + { + WPAS_PRT("hapd_intf_add_key CCMP\r\n"); + key_param.cipher_suite = MAC_RSNIE_CIPHER_CCMP; + } +#if CFG_MFP + else if(os_strcmp((char *)param->u.crypt.alg, "BIP") == 0) + { + WPAS_PRT("hapd_intf_add_key BIP\r\n"); + key_param.cipher_suite = MAC_RSNIE_CIPHER_AES_CMAC; + } +#endif + + if(is_broadcast_ether_addr(param->sta_addr)) + { + WPAS_PRT("add is_broadcast_ether_addr\r\n"); + key_param.sta_idx = 0xFF; + key_param.inst_nbr = param->vif_idx; + } + else + { + WPAS_PRT("add sta_mgmt_get_sta\r\n"); + key_param.sta_idx = rwm_mgmt_sta_mac2idx(param->sta_addr); + key_param.inst_nbr = param->vif_idx; + } + + key_param.key_idx = param->u.crypt.idx; + key_param.key.length = param->u.crypt.key_len; + os_memcpy((u8 *) & (key_param.key.array[0]), (u8 *)¶m[1], key_param.key.length); + + WPAS_PRT("sta:%d, vif:%d, key:%d\r\n", + key_param.sta_idx, key_param.inst_nbr, key_param.key_idx); + + ps_set_key_prevent(); + mcu_prevent_set(MCU_PS_ADD_KEY); +#if CFG_USE_STA_PS + bk_wlan_dtim_rf_ps_mode_do_wakeup(); +#endif + + ret = rw_msg_send_key_add(&key_param, cfm); + if(!ret && (cfm->status == CO_OK)) + { + WPAS_PRT("add hw key idx:%d\r\n", cfm->hw_key_idx); + } + + os_free(cfm); + + return ret; +} + + +int hapd_intf_del_key(struct prism2_hostapd_param *param, int len) +{ + u8 hw_key_idx = 0; + + if( (param->sta_addr == NULL) || is_broadcast_ether_addr(param->sta_addr)) + { + hw_key_idx = rwm_mgmt_get_hwkeyidx(param->vif_idx, 0xff); + } + else + { + u8 staid = rwm_mgmt_sta_mac2idx(param->sta_addr); + if(staid == 0xff) + return 0; + hw_key_idx = rwm_mgmt_get_hwkeyidx(param->vif_idx, staid); + } + + if(hw_key_idx > MM_SEC_MAX_KEY_NBR) + return 0; + + WPAS_PRT("del hw key idx:%d\r\n", hw_key_idx); + + return rw_msg_send_key_del(hw_key_idx); + +} + +int hapd_intf_add_vif(struct prism2_hostapd_param *param, int len) +{ + int ret; + struct mm_add_if_cfm *cfm + = (struct mm_add_if_cfm *)os_malloc(sizeof(struct mm_add_if_cfm)); + + if(NULL == cfm) + { + WPAS_PRT("vif_add buf_failed\r\n"); + return HINTF_FAILURE; + } + + ret = rw_msg_send_add_if((const unsigned char *)¶m->sta_addr, + param->u.add_if.type, 0, cfm); + + if(ret || (cfm->status != CO_OK)) + { + SAAP_PRT("MM_ADD_IF_REQ failed!\r\n"); + os_free(cfm); + return -1; + } + SAAP_PRT("hapd_intf_add_vif,type:%d, s:%d, id:%d\r\n", + param->u.add_if.type, cfm->status, cfm->inst_nbr); + + if(cfm->inst_nbr >= NX_VIRT_DEV_MAX) + return -1; + + *(param->u.add_if.indx_ptr) = cfm->inst_nbr; + + os_free(cfm); + + return 0; +} + +int hapd_intf_remove_vif(struct prism2_hostapd_param *param, int len) +{ + u8 vif_index = param->vif_idx; + + if(vif_index >= NX_VIRT_DEV_MAX) + return -1; + + WPAS_PRT("wpa/host apd remove_if:%d\r\n", vif_index); + + return rw_msg_send_remove_if(vif_index); +} + +int hapd_intf_start_apm(struct prism2_hostapd_param *param, int len) +{ + int ret; + struct apm_start_cfm *cfm + = (struct apm_start_cfm *)os_malloc(sizeof(struct apm_start_cfm)); + + if(NULL == cfm) + { + WPAS_PRT("apm_start buf_failed\r\n"); + return HINTF_FAILURE; + } + + ret = rw_msg_send_apm_start_req(param->vif_idx, g_ap_param_ptr->chann, cfm); + if(ret) + { + SAAP_PRT("hapd_intf_start_apm failed!\r\n"); + os_free(cfm); + return -1; + } + + if(cfm->status == CO_OK) + { + SAAP_PRT("vif_idx:%d, ch_idx:%d, bcmc_idx:%d\r\n", cfm->vif_idx, + cfm->ch_idx, cfm->bcmc_idx); + } + os_free(cfm); + return 0; +} + +int hapd_intf_stop_apm(struct prism2_hostapd_param *param, int len) +{ + int ret; + ret = rw_msg_send_apm_stop_req(param->vif_idx); + if(ret) + { + SAAP_PRT("hapd_intf_stop_apm failed!\r\n"); + return -1; + } + return 0; +} + +int hapd_intf_set_ap_bcn(struct prism2_hostapd_param *param, int len) +{ + char *bcn_buf; + BCN_PARAM_ST bcn_param; + +#if CFG_ROLE_LAUNCH + if(rl_pre_ap_set_status(RL_STATUS_AP_UPDATING_BCN)) + { + return 0; + } +#endif + + if(param->u.bcn_change.bcn_len == 0) + { + WPAS_WPRT("hapd_intf_set_ap bcn len = 0\r\n"); + return 0; + } + + bcn_buf = (char *)os_malloc(param->u.bcn_change.bcn_len); + if(!bcn_buf) + { + WPAS_WPRT("hapd_intf_set_ap no buffer\r\n"); + return -1; + } + + os_memcpy(bcn_buf, param->u.bcn_change.beacon, param->u.bcn_change.bcn_len); + os_memset(&bcn_param, 0, sizeof(BCN_PARAM_ST)); + + bcn_param.bcn_ptr = (u32 *)bcn_buf; + bcn_param.bcn_len = param->u.bcn_change.bcn_len; + bcn_param.tim_len = param->u.bcn_change.tim_len; + bcn_param.tim_oft = param->u.bcn_change.head_len; + bcn_param.vif_idx = param->vif_idx; + bcn_param.csa_oft = NULL; + bcn_param.flag = 1; + + return rw_msg_send_bcn_change((void *)&bcn_param); +} + +void wpa_buffer_scan_results(void) +{ + s_scan_result_upload_ptr = sr_get_scan_results(); +} + +void wpa_clear_scan_results(void) +{ + s_scan_result_upload_ptr = 0; +} + +int wpa_reg_assoc_cfm_callback(struct prism2_hostapd_param *param, int len) +{ + ASSERT(param); + mhdr_assoc_cfm_cb(param->u.reg_assoc_cfm.cb, + param->u.reg_assoc_cfm.arg); + + return 0; +} + +int wpa_reg_scan_cfm_callback(struct prism2_hostapd_param *param, int len) +{ + ASSERT(param); +#if CFG_WPA_CTRL_IFACE + mhdr_scanu_reg_cb_for_wpa(param->u.reg_scan_cfm.cb, + param->u.reg_scan_cfm.arg); +#else + mhdr_scanu_reg_cb(param->u.reg_scan_cfm.cb, + param->u.reg_scan_cfm.arg); +#endif + + return 0; +} + +int wpa_reg_deassoc_evt_callback(struct prism2_hostapd_param *param, int len) +{ + ASSERT(param); + mhdr_deassoc_evt_cb(param->u.reg_disassoc_evt.cb, + param->u.reg_disassoc_evt.arg); + + return 0; +} + +int wpa_reg_deauth_evt_callback(struct prism2_hostapd_param *param, int len) +{ + ASSERT(param); + mhdr_deauth_evt_cb(param->u.reg_deauth_evt.cb, + param->u.reg_deauth_evt.arg); + + return 0; +} + +int wpa_send_scan_req(struct prism2_hostapd_param *param, int len) +{ + UINT8 i; + SCAN_PARAM_T scan_param; + + WPAS_PRT("wpa_send_scan_req\r\n"); + scan_param.num_ssids = param->u.scan_req.ssids_num; + for(i = 0; i < scan_param.num_ssids; i++) + { + scan_param.ssids[i].length = param->u.scan_req.ssids[i].ssid_len; + os_memcpy(scan_param.ssids[i].array, param->u.scan_req.ssids[i].ssid, scan_param.ssids[i].length); + } + scan_param.bssid = mac_addr_bcst; + scan_param.vif_idx = param->vif_idx; + os_memcpy(scan_param.freqs, param->u.scan_req.freqs, sizeof(scan_param.freqs)); + +#if CFG_WPA_CTRL_IFACE + if (!wpa_is_scan_only()) +#endif + mhdr_set_station_status(RW_EVT_STA_SCANNING); // only set status if we are not scan only + return rw_msg_send_scanu_req(&scan_param); +} + +/* extract neccary ies for wpa_s */ +int wlan_get_bss_beacon_ies(struct wpabuf *buf, const u8 *bcn_ie, int ie_len) +{ + const u8 *ie; + const u8 *vsie; + u8 ies[] = {WLAN_EID_SSID, WLAN_EID_RSN}; + + buf->used = 0; + + // IEs + for (int i = 0; i < ARRAY_SIZE(ies); i++) { + ie = get_ie(bcn_ie, ie_len, ies[i]); + if (ie) { + if (wpabuf_tailroom(buf) >= ie[1] + 2) + wpabuf_put_data(buf, ie, ie[1] + 2); + } + } + + // VS IE + vsie = get_vendor_ie(bcn_ie, ie_len, WPA_IE_VENDOR_TYPE); + if (vsie) { + if (wpabuf_tailroom(buf) >= vsie[1] + 2) + wpabuf_put_data(buf, vsie, vsie[1] + 2); + } + + return 0; +} + +extern uint32_t wifi_get_rescan_cnt(void); +int wpa_get_scan_rst(struct prism2_hostapd_param *param, int len) +{ + struct wpa_scan_results *results = param->u.scan_rst; + struct sta_scan_res *scan_rst_ptr; + struct wpa_scan_res *r; + FUNC_1PARAM_PTR fn; + int i, ret = 0; + u32 val; + +#if CFG_WPA_CTRL_IFACE + if (!wpa_is_scan_only()) +#endif + mhdr_set_station_status(RW_EVT_STA_SCAN_OVER); + + if(NULL == s_scan_result_upload_ptr) + { + WPAS_PRT("get_scan_rst_null\r\n"); + fn = bk_wlan_get_status_cb(); + if(fn) + { + val = RW_EVT_STA_NO_AP_FOUND; + (*fn)(&val); + } +#if CFG_WPA_CTRL_IFACE + if (!wpa_is_scan_only()) +#endif + mhdr_set_station_status(RW_EVT_STA_NO_AP_FOUND); + +#if CFG_ROLE_LAUNCH + uint32_t rl_cancel_flag; + if((0 == wifi_get_rescan_cnt()) || rl_pre_sta_get_cancel()) + { + WPAS_PRT("RL_STATUS_STA_LAUNCH_FAILED\r\n"); + rl_cancel_flag = rl_pre_sta_set_status(RL_STATUS_STA_LAUNCH_FAILED); + } + else + { + WPAS_PRT("RL_STATUS_STA_SCAN_VAIN\r\n"); + rl_cancel_flag = rl_pre_sta_set_status(RL_STATUS_STA_SCAN_VAIN); + } + + if(rl_cancel_flag) + { + bk_wlan_terminate_sta_rescan(); + } +#endif + +#if CFG_WPA_CTRL_IFACE + /* Don't fail get scan result, but allow zero scan result */ + return 0; +#else + return -1; +#endif + } + +#if CFG_ROLE_LAUNCH + if(rl_pre_sta_set_status(RL_STATUS_STA_CONNECTING)) + { + return -1; + } +#endif + + WPAS_PRT("wpa_get_scan_rst:%d\r\n", s_scan_result_upload_ptr->scanu_num); + for(i = 0; i < s_scan_result_upload_ptr->scanu_num; i++) + { + scan_rst_ptr = s_scan_result_upload_ptr->res[i]; + r = os_zalloc(sizeof(*r) + scan_rst_ptr->ie_len); + if (r == NULL) + { + //ret = -1; + WPAS_PRT("wpa_get_scan_rst break;\r\n"); + break; + } + + os_memcpy(r->bssid, scan_rst_ptr->bssid, ETH_ALEN); + r->level = scan_rst_ptr->level; + r->freq = rw_ieee80211_get_centre_frequency(scan_rst_ptr->channel); + r->beacon_int = scan_rst_ptr->beacon_int; + r->caps = scan_rst_ptr->caps; + r->tsf = WPA_GET_BE64(scan_rst_ptr->tsf); + r->ie_len = scan_rst_ptr->ie_len; + os_memcpy(r + 1, scan_rst_ptr + 1, scan_rst_ptr->ie_len); + + results->res[results->num++] = r; + } + +#if CFG_WPA_CTRL_IFACE + /* doesn't need to keep, all info are stored in wpas */ + wpa_hostapd_release_scan_rst(); +#endif + + return ret; +} + +int wpa_send_assoc_req(struct prism2_hostapd_param *param, int len) +{ + CONNECT_PARAM_T *connect_param; + int ret = 0; + + + connect_param = os_zalloc(sizeof(*connect_param) + param->u.assoc_req.bcn_len); + if (!connect_param) + return -1; + + os_memcpy((UINT8 *)&connect_param->bssid, param->u.assoc_req.bssid, ETH_ALEN); + connect_param->flags = CONTROL_PORT_HOST; + if (param->u.assoc_req.proto & (WPA_PROTO_WPA | WPA_PROTO_RSN)) + connect_param->flags |= WPA_WPA2_IN_USE; + + if (param->u.assoc_req.mfp == MGMT_FRAME_PROTECTION_REQUIRED) + connect_param->flags |= MFP_IN_USE; + + connect_param->vif_idx = param->vif_idx; + connect_param->ssid.length = param->u.assoc_req.ssid_len; + os_memcpy(connect_param->ssid.array, param->u.assoc_req.ssid, connect_param->ssid.length); + connect_param->ie_len = param->u.assoc_req.ie_len; + os_memcpy((UINT8 *)connect_param->ie_buf, (UINT8 *)param->u.assoc_req.ie_buf, connect_param->ie_len); + connect_param->bcn_len = param->u.assoc_req.bcn_len; + if (connect_param->bcn_len) + os_memcpy((UINT8 *)connect_param->bcn_buf, (UINT8 *)param->u.assoc_req.bcn_buf, connect_param->bcn_len); + + connect_param->auth_type = param->u.assoc_req.auth_alg; + ret = sa_station_send_associate_cmd(connect_param); + + os_free(connect_param); + + if (s_scan_result_upload_ptr) { + sr_release_scan_results(s_scan_result_upload_ptr); + s_scan_result_upload_ptr = NULL; + } + + return ret; +} + +int wpa_send_disconnect_req(struct prism2_hostapd_param *param, int len) +{ + FUNC_1PARAM_PTR fn; + u32 val; + DISCONNECT_PARAM_T disconnect_param = {0}; + disconnect_param.vif_idx = param->vif_idx; + disconnect_param.reason_code = param->u.disconnect_req.reason; + + switch(disconnect_param.reason_code) + { + case WLAN_REASON_PREV_AUTH_NOT_VALID: + case WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT: + val = RW_EVT_STA_PASSWORD_WRONG; + break; + + case MAC_RS_DIASSOC_TOO_MANY_STA: + val = RW_EVT_STA_ASSOC_FULL; + break; + + case WLAN_REASON_DEAUTH_LEAVING: + default: + val = RW_EVT_STA_CONNECT_FAILED; + break; + } + extern bool sta_active_disconnection; + if (!sta_active_disconnection) { + fn = bk_wlan_get_status_cb(); + if(fn) + { + (*fn)(&val); + } + mhdr_set_station_status(val); + } + + return rw_msg_send_sm_disconnect_req(&disconnect_param); +} + +#ifdef CONFIG_SAE_EXTERNAL +int wpa_send_external_auth_status(struct prism2_hostapd_param *param, int len) +{ + EXTERNAL_AUTH_PARAM_T oper_param = {0}; + + oper_param.vif_idx = param->vif_idx; + oper_param.status = param->u.external_auth_status.status; + + return rw_msg_send_sm_external_auth_status(&oper_param); +} +#endif + +int wpa_get_bss_info(struct prism2_hostapd_param *param, int len) +{ + int ret, ssid_len; + struct sm_get_bss_info_cfm *cfm; + + cfm = os_malloc(sizeof(struct sm_get_bss_info_cfm)); + + if(NULL == cfm) + { + WPAS_PRT("bss_get_info buf_failed\r\n"); + return HINTF_FAILURE; + } + + ret = rw_msg_get_bss_info(param->vif_idx, (void *)cfm); + if(ret) + return -1; + + os_memcpy(param->u.bss_info.bssid, cfm->bssid, ETH_ALEN); + ssid_len = MIN(SSID_MAX_LEN, os_strlen((char*)cfm->ssid)); + os_memcpy(param->u.bss_info.ssid, cfm->ssid, ssid_len); + os_free(cfm); + + return 0; +} + +int wpa_hostapd_set_sta_flag(struct prism2_hostapd_param *param, int len) +{ + u32 set_flag = param->u.set_flags_sta.flags_or; + u32 mask = param->u.set_flags_sta.flags_and; + u32 flag = 0; + bool opened = 0; + u8 sta_idx; + + flag |= set_flag; + flag &= mask; + + if(!flag) + return 0; + + if( !(flag & WPA_STA_AUTHENTICATED)) + return 0; + + sta_idx = rwm_mgmt_sta_mac2idx(param->sta_addr); + if(sta_idx == 0xff) + return 0; + + opened = 1; + + return rw_msg_me_set_control_port_req(opened, sta_idx); +} + +void wpa_hostapd_release_scan_rst(void) +{ + if(s_scan_result_upload_ptr) + { + sr_release_scan_results(s_scan_result_upload_ptr); + s_scan_result_upload_ptr = NULL; + } + else + { + SCAN_RST_UPLOAD_T *rst = sr_get_scan_results(); + sr_release_scan_results(rst); + } +} + +void hapd_poll_callback(void *env, uint32_t status) +{ + uint32_t sta_id = (uint32_t)env; + struct sta_info_tag *sta_entry; + + ASSERT(INVALID_STA_IDX != sta_id); + + if(!(status & FRAME_SUCCESSFUL_TX_BIT)) + { + WPAS_WPRT("noAck\r\n"); + return; + } + + sta_entry = sta_mgmt_get_sta_with_id(sta_id); + if(sta_entry) + { + sta_entry->pre_rx_timepoint = fclk_get_tick(); + WPAS_PRT("update_tp:%d\r\n", sta_entry->pre_rx_timepoint); + } +} + +int hapd_poll_null_frame(struct prism2_hostapd_param *param, int len) +{ + uint32_t sta_id; + + sta_id = sta_mgmt_get_sta_id(param->u.poll_null_data.sta_addr); + if(INVALID_STA_IDX == sta_id) + { + return 1; + } + + txl_frame_send_null_frame(sta_id, hapd_poll_callback, (void *)sta_id); + + return 0; +} + +int hapd_intf_ioctl(unsigned long arg) +{ + u32 cmd; + int len, ret = 0; + struct iwreq *iwr_ptr; + struct prism2_hostapd_param *param; + + if(0 == arg) + { + ret = EINVAL; + goto ioctl_exit; + } + + iwr_ptr = (struct iwreq *)arg; + len = iwr_ptr->u.data.length; + param = iwr_ptr->u.data.pointer; + + cmd = param->cmd; + switch(cmd) + { + case PRISM2_HOSTAPD_POLL_CLIENT_NULL_DATA: + ret = hapd_poll_null_frame(param, len); + break; + + case PRISM2_HOSTAPD_CHANNEL_SWITCH: + ret = wpa_intf_channel_switch(param, len); + break; + + case PRISM2_HOSTAPD_WPA_INIT_VIF: + ret = hapd_intf_add_vif(param, len); + break; + + case PRISM2_HOSTAPD_SET_FLAGS_STA: + ret = wpa_hostapd_set_sta_flag(param, len); + break; + + case PRISM2_HOSTAPD_START_APM: + ret = hapd_intf_start_apm(param, len); + break; + + case PRISM2_HOSTAPD_STOP_APM: + ret = hapd_intf_stop_apm(param, len); + break; + + case PRISM2_HOSTAPD_SET_AP_BCN: + ret = hapd_intf_set_ap_bcn(param, len); + break; + + case PRISM2_SET_ENCRYPTION: + if(os_strcmp((const char *)param->u.crypt.alg, "NONE") == 0) + { + ret = hapd_intf_del_key(param, len); + mcu_prevent_clear(MCU_PS_ADD_KEY); + } + else + { + ret = hapd_intf_add_key(param, len); + } + break; + + case PRISM2_GET_ENCRYPTION: + break; + + case PRISM2_HOSTAPD_FLUSH: + break; + + case PRISM2_HOSTAPD_ADD_STA: + ret = hapd_intf_sta_add(param, len); + break; + + case PRISM2_HOSTAPD_REMOVE_STA: + ret = hapd_intf_sta_del(param, len); + break; + + case PRISM2_HOSTAPD_GET_INFO_STA: + ret = hapd_get_sta_info(param, len); + break; + + case PRISM2_HOSTAPD_STA_CLEAR_STATS: + break; + + case PRISM2_HOSTAPD_SET_GENERIC_ELEMENT: + break; + + case PRISM2_HOSTAPD_REG_SCAN_CALLBACK: + wpa_reg_scan_cfm_callback(param, len); + break; + + case PRISM2_HOSTAPD_REG_CSA_CALLBACK: + ASSERT(param); + mm_csa_event_cb(param->u.reg_csa_event.cb, + param->u.reg_csa_event.arg); + break; + + case PRISM2_HOSTAPD_REG_ASSOC_CALLBACK: + wpa_reg_assoc_cfm_callback(param, len); + break; + case PRISM2_HOSTAPD_SCAN_REQ: + ret = wpa_send_scan_req(param, len); + break; + + case PRISM2_HOSTAPD_GET_SCAN_RESULT: + ret = wpa_get_scan_rst(param, len); + break; + + case PRISM2_HOSTAPD_ASSOC_REQ: + ret = wpa_send_assoc_req(param, len); + break; + + case PRISM2_HOSTAPD_ASSOC_ACK: + break; + + case PRISM2_HOSTAPD_REG_DISASSOC_CALLBACK: + wpa_reg_deassoc_evt_callback(param, len); + break; + + case PRISM2_HOSTAPD_REG_DEAUTH_CALLBACK: + wpa_reg_deauth_evt_callback(param, len); + break; + + case PRISM2_HOSTAPD_REG_APP_START: + break; + + case PRISM2_HOSTAPD_DISCONN_REQ: + wpa_send_disconnect_req(param, len); + break; + + case PRISM2_HOSTAPD_WPA_DEINIT_VIF: + ret = hapd_intf_remove_vif(param, len); + break; + + case PRISM2_HOSTAPD_GET_BSS_INFO: + ret = wpa_get_bss_info(param, len); + break; + +#ifdef CONFIG_SAE_EXTERNAL + case PRISM2_HOSTAPD_EXTERNAL_AUTH_STATUS: + ret = wpa_send_external_auth_status(param, len); + break; +#endif + + default: + break; + } + +ioctl_exit: + return ret; +} + +void hapd_intf_ke_rx_handle(int dummy) +{ + int payload_size; + unsigned char *buf; + S_TYPE_PTR type_ptr = (S_TYPE_PTR)dummy; + + if(type_ptr->type == HOSTAPD_MGMT +#if NX_MFP + || type_ptr->type == HOSTAPD_MGMT_ROBUST +#endif + ) + { + int param_len; + struct ke_msg *kmsg_dst; + struct me_mgmt_tx_req *mgmt_tx_ptr; + + payload_size = ke_mgmt_peek_rxed_next_payload_size(type_ptr->vif_index); + ASSERT(payload_size); + buf = (unsigned char *)os_malloc(payload_size); + if(0 == buf) + { + goto exit; + } + ke_mgmt_packet_rx(buf, payload_size, type_ptr->vif_index); + param_len = sizeof(struct me_mgmt_tx_req); + kmsg_dst = (struct ke_msg *)os_malloc(sizeof(struct ke_msg) + + param_len); + if(0 == kmsg_dst) + { + goto kmsg_malloc_fail; + } + os_memset(kmsg_dst, 0, (sizeof(struct ke_msg) + param_len)); + + kmsg_dst->id = ME_MGMT_TX_REQ; + kmsg_dst->dest_id = TASK_ME; + kmsg_dst->src_id = 100; + kmsg_dst->param_len = param_len; + + mgmt_tx_ptr = (struct me_mgmt_tx_req *)kmsg_dst->param; + mgmt_tx_ptr->addr = (UINT32)buf; + mgmt_tx_ptr->hostid = (UINT32)buf; + mgmt_tx_ptr->len = payload_size; +#if NX_MFP + mgmt_tx_ptr->robust = !!(type_ptr->type == HOSTAPD_MGMT_ROBUST); +#endif + mgmt_tx_ptr->req_malloc_flag = 1; + mgmt_tx_ptr->vif_idx = type_ptr->vif_index; + mgmt_tx_ptr->freq = type_ptr->freq; + + ke_msg_send(ke_msg2param(kmsg_dst)); + } + else if(type_ptr->type == HOSTAPD_DATA) + { + UINT8 *pd_ptr; + + payload_size = ke_data_peek_rxed_next_payload_size(type_ptr->vif_index); + pd_ptr = (UINT8 *)os_malloc(payload_size); + if(NULL == pd_ptr) + { + WPAS_WPRT("hapd_intf_tx_error\r\n"); + goto exit; + } + + ke_l2_packet_rx(pd_ptr, payload_size, type_ptr->vif_index); + + ps_set_data_prevent(); + +#if CFG_USE_STA_PS + extern int bmsg_ps_handler_rf_ps_mode_real_wakeup(void); + bmsg_ps_handler_rf_ps_mode_real_wakeup(); + bk_wlan_dtim_rf_ps_mode_do_wakeup(); +#endif + + rwm_transfer(type_ptr->vif_index, pd_ptr, payload_size, type_ptr->sync, type_ptr->args); + + os_free(pd_ptr); + } + + os_free(type_ptr); + return; + +kmsg_malloc_fail: + os_free(buf); + +exit: + os_free(type_ptr); + return; +} + +// eof + diff --git a/beken_os/beken378/func/hostapd_intf/hostapd_intf.h b/beken_os/beken378/func/hostapd_intf/hostapd_intf.h new file mode 100755 index 0000000..c0e3e0f --- /dev/null +++ b/beken_os/beken378/func/hostapd_intf/hostapd_intf.h @@ -0,0 +1,19 @@ +#ifndef _HOSTAPD_INTF_H_ +#define _HOSTAPD_INTF_H_ + +#define HINTF_SUCCESS (0) +#define HINTF_FAILURE (-1) + +//#define WPAS_DEBUG + +#ifdef WPAS_DEBUG +#define WPAS_PRT os_printf +#define WPAS_WPRT warning_prf +#else +#define WPAS_PRT os_null_printf +#define WPAS_WPRT warning_prf +#endif + +#endif +// eof + diff --git a/beken_os/beken378/func/include/app_music_pub.h b/beken_os/beken378/func/include/app_music_pub.h new file mode 100755 index 0000000..a976864 --- /dev/null +++ b/beken_os/beken378/func/include/app_music_pub.h @@ -0,0 +1,8 @@ +#ifndef _APP_MUSIC_PUB_H_ +#define _APP_MUSIC_PUB_H_ + +extern void media_thread_init(void); +extern void media_msg_sender(void const *param_ptr); +extern void key_init(void); + +#endif diff --git a/beken_os/beken378/func/include/bk7011_cal_pub.h b/beken_os/beken378/func/include/bk7011_cal_pub.h new file mode 100755 index 0000000..c9f124b --- /dev/null +++ b/beken_os/beken378/func/include/bk7011_cal_pub.h @@ -0,0 +1,273 @@ +#ifndef _BK7011_CAL_PUB_H_ +#define _BK7011_CAL_PUB_H_ + +#include "typedef.h" +#include "sys_config.h" +#define CALI_MODE_AUTO 0 +#define CALI_MODE_MANUAL 1 + +#define CFG_TEMP_DETECT_VERSION0 0U +#define CFG_TEMP_DETECT_VERSION1 1U + +#define CFG_TEMP_DIFF_PWR_FREQOFFSET 1 + +#define BK_FLASH_OPT_TLV_HEADER (0x00564c54) // ASIC TLV +typedef enum{ + TXID = 0x11111100, + TXPWR_TAB_TAB = 0x22222200, + CALI_MAIN_TX = 0x33333300, + CALI_MAIN_RX = 0x44444400, + TXEND = 0xeeeeeeee, + TXNON = 0xffffffff +}TXSTRUCT; + +#define DEFAULT_TXID_ID (12345678) +#if (CFG_SOC_NAME == SOC_BK7231N) +#define DEFAULT_TXID_THERMAL (350) +#else +#define DEFAULT_TXID_THERMAL (280) //180430,7231:315,7231U:340 +#endif +#define DEFAULT_TXID_CHANNEL (22222222) +#define DEFAULT_TXID_LPF_CAP_I (0x80) +#define DEFAULT_TXID_LPF_CAP_Q (0x80) +typedef enum{ + TXID_ID = TXID+1, + TXID_MAC, + TXID_THERMAL, + TXID_CHANNEL, + TXID_XTAL, + TXID_ADC, + TXID_LPFCAP, + TXID_END, + TXID_NON = TXID+0xFF +}TXIDList; + +typedef enum{ + TXPWR_ENABLE_ID = TXPWR_TAB_TAB+1, + TXPWR_TAB_B_ID, + TXPWR_TAB_G_ID, + TXPWR_TAB_N_ID, + TXPWR_TAB_DIF_GN20_ID, + TXPWR_TAB_DIF_GN40_ID, + TXPWR_TAB_BLE_ID, + TXPWR_TAB_CALI_STATUTS, + TXPWR_END, + TXPWR_NON = TXPWR_TAB_TAB+0xFF +}TXPWR_ELEM_ID; + +typedef enum { + TXPWR_NONE_RD = 0u, + TXPWR_TAB_B_RD = 0x1u, + TXPWR_TAB_G_RD = 0x2u, + TXPWR_TAB_N_RD = 0x4u, + TXPWR_TAB_BLE = 0x8u, +} TXPWR_IS_RD; + +typedef enum{ + CM_TX_DCOR_MOD = CALI_MAIN_TX+1, + CM_TX_DCOR_PA, + CM_TX_PREGAIN, + CM_TX_I_DC_COMP, + CM_TX_Q_DC_COMP, + CM_TX_I_GAIN_COMP, + CM_TX_Q_GAIN_COMP, + CM_TX_I_FILTER_CORNER, + CM_TX_Q_FILTER_CORNER, + CM_TX_PHASE_COMP, + CM_TX_PHASE_TY2, + CM_TX_END, + CM_TX_NON = CALI_MAIN_TX+0xFF +}CM_TX_ELEM_ID; + +typedef enum{ + CM_RX_DC_GAIN_TAB = CALI_MAIN_RX+1, + CM_RX_AMP_ERR_WR, + CM_RX_PHASE_ERR_WR, + CM_RX_END, + CM_RX_NON = CALI_MAIN_RX+0xFF +}CM_RX_ELEM_ID; + +#define LOAD_FROM_FLASH 1 +#define LOAD_FROM_CALI 0 + +#if (CFG_SOC_NAME == SOC_BK7231) +#define CFG_TEMP_DETECT_VERSION CFG_TEMP_DETECT_VERSION0 +#else +#define CFG_TEMP_DETECT_VERSION CFG_TEMP_DETECT_VERSION1 +#endif + +#if CFG_TEMP_DETECT_VERSION == CFG_TEMP_DETECT_VERSION1 +#if (CFG_SOC_NAME == SOC_BK7231N) +typedef struct tmp_pwr_st {//do + unsigned trx0x0c_12_15 : 4; //not used on BK7231N actually + signed p_index_delta : 6; + signed p_index_delta_g : 6; + signed p_index_delta_ble : 6; + signed xtal_c_dlta : 8; +} TMP_PWR_ST, *TMP_PWR_PTR; +#else +typedef struct tmp_pwr_st { + unsigned trx0x0c_12_15 : 4; + signed p_index_delta : 6; + signed p_index_delta_g : 6; + signed p_index_delta_ble : 6; + unsigned xtal_c_dlta : 6; +} TMP_PWR_ST, *TMP_PWR_PTR; +#endif +#else +typedef struct tmp_pwr_st { + UINT8 mod; + UINT8 pa; + UINT16 pwr_idx_shift; +} TMP_PWR_ST, *TMP_PWR_PTR; +#endif + +struct temp_cal_pwr_st { + UINT8 idx; + UINT8 mode; + INT16 shift; + INT16 shift_g; +}; + +typedef enum +{ + TEMPERATURE_TYPE_UNKNOWN = 0, + TEMPERATURE_TYPE_LOW, + TEMPERATURE_TYPE_NORMAL, + TEMPERATURE_TYPE_HIGH, +} temperature_type; + + +extern void manual_cal_load_bandgap_calm(void); +void bk7011_cal_vdddig_by_temperature(temperature_type new_temperature_type); + +extern void calibration_main(void); +extern INT32 rwnx_cal_load_trx_rcbekn_reg_val(void); +extern void rwnx_cal_set_txpwr_by_rate(INT32 rate, UINT32 test_mode); +extern void rwnx_cal_set_txpwr_by_channel(UINT32 channel); +extern INT32 rwnx_cal_save_trx_rcbekn_reg_val(void); +extern void do_calibration_in_temp_dect(void); +extern void bk7011_cal_bias(void); +extern void bk7011_cal_bias_high_temprature(UINT8 high_temprature); +extern void bk7011_cal_dpll(void); +extern void rwnx_cal_set_txpwr(UINT32 pwr_gain, UINT32 grate); +extern UINT32 manual_cal_get_pwr_idx_shift(UINT32 rate, UINT32 bandwidth, UINT32 *pwr_gain); +extern int manual_cal_get_txpwr(UINT32 rate, UINT32 channel, UINT32 bandwidth, UINT32 *pwr_gain); +extern void manual_cal_save_txpwr(UINT32 rate, UINT32 channel, UINT32 pwr_gain); +#if (CFG_SOC_NAME == SOC_BK7231U) || (SOC_BK7231N == CFG_SOC_NAME) +extern void manual_cal_11b_2_ble(void); +#endif +extern UINT32 manual_cal_fitting_txpwr_tab(void); +extern void manual_cal_show_txpwr_tab(void); +extern UINT32 manual_cal_load_txpwr_tab_flash(void); +extern int manual_cal_save_txpwr_tab_to_flash(void); +extern int manual_cal_save_chipinfo_tab_to_flash(void); +extern UINT8 manual_cal_wirte_otp_flash(UINT32 addr, UINT32 len, UINT8 *buf); +extern UINT8 manual_cal_read_otp_flash(UINT32 addr, UINT32 len, UINT8 *buf); +extern UINT32 manual_cal_load_default_txpwr_tab(UINT32 is_ready_flash); +extern void manual_cal_set_dif_g_n40(UINT32 diff); +extern void manual_cal_set_dif_g_n20(UINT32 diff); +extern void manual_cal_get_current_temperature(void); +extern int manual_cal_write_macaddr_to_flash(UINT8 *mac_ptr); +extern int manual_cal_get_macaddr_from_flash(UINT8 *mac_ptr); +extern int manual_cal_set_rfcali_status_inflash(UINT32 rf_status); +extern int manual_cal_get_rfcali_status_inflash(UINT32 *rf_status); +extern void manual_cal_show_otp_flash(void); +extern void manual_cal_clear_otp_flash(void); +extern void manual_cal_set_xtal(UINT32 xtal); +extern void manual_cal_set_lpf_iq(UINT32 lpf_i, UINT32 lpf_q); +extern void manual_cal_load_lpf_iq_tag_flash(void); +extern void manual_cal_load_xtal_tag_flash(void); +#if CFG_TEMP_DETECT_VERSION == CFG_TEMP_DETECT_VERSION1 +void manual_cal_do_xtal_temp_delta_set(INT8 shift); +#endif +extern void manual_cal_do_xtal_cali(UINT16 cur_val, UINT16 *last, UINT16 thre, UINT16 init_val); +extern UINT32 manual_cal_get_xtal(void); +extern INT8 manual_cal_get_dbm_by_rate(UINT32 rate, UINT32 bandwidth); +extern INT8 manual_cal_get_cur_txpwr_dbm(void); +extern int manual_cal_load_temp_tag_from_flash(void); +extern int manual_cal_load_xtal_tag_from_flash(void); +extern void manual_cal_load_differ_tag_from_flash(void); +extern UINT32 manual_cal_g_rfcali_status(void); + +extern void bk7011_micopwr_config_tssi_read_prepare(void); +extern void bk7011_micopwr_tssi_read(void); +extern void bk7011_micopwr_tssi_show(void); +extern void rwnx_cal_set_reg_adda_ldo(UINT32 val); +extern void rwnx_cal_set_reg_rx_ldo(void); + +extern void manual_cal_tmp_pwr_init(UINT16 init_temp, UINT16 init_thre, UINT16 init_dist); +extern void manual_cal_tmp_pwr_init_reg(UINT16 reg_mod, UINT16 reg_pa); +extern void manual_cal_temp_pwr_unint(void); +extern void manual_cal_set_tmp_pwr_flag(UINT8 flag); +extern TMP_PWR_PTR manual_cal_set_tmp_pwr(UINT16 cur_val, UINT16 thre, UINT16 *last); +extern UINT32 manual_cal_load_temp_tag_flash(void); +extern UINT32 manual_cal_load_adc_cali_flash(void); +extern void manual_cal_do_single_temperature(void); +extern void manual_cal_set_rate_dist_for_txpwr(int dist_b, int dist_g, int dist_n40, int dist_ble); + +extern void rwnx_cal_set_reg_mod_pa(UINT16 reg_mod, UINT16 reg_pa); +extern void rwnx_cal_do_temp_detect(UINT16 cur_val, UINT16 thre, UINT16 *last); +extern void rwnx_cal_set_lpfcap_iq(UINT32 lpfcap_i, UINT32 lpfcap_q); +extern void rwnx_cal_set_40M_extra_setting(UINT8 val); +extern void rwnx_cal_set_40M_setting(void); +extern void rwnx_cal_set_20M_setting(void); + +extern void rwnx_cal_set_txpwr_for_ble_boardcast(void); +extern void bk7011_set_rf_config_tssithred_b(int tssi_thred_b); +extern void bk7011_set_rf_config_tssithred_g(int tssi_thred_g); +extern void rwnx_cal_recover_txpwr_for_wifi(void); +extern void rwnx_cal_recover_rf_setting(void); +extern void rwnx_cal_recover_wifi_setting(void); +extern void rwnx_cal_initial_calibration(void); + +extern UINT32 rwnx_tpc_pwr_idx_translate(UINT32 pwr_gain, UINT32 rate, UINT32 print_log ); +extern UINT32 rwnx_tpc_get_pwridx_by_rate(UINT32 rate, UINT32 print_log); +extern void rwnx_use_tpc_set_pwr(void); +extern void rwnx_no_use_tpc_set_pwr(void); +extern UINT32 rwnx_is_tpc_bit_on(void); +extern UINT32 rwnx_sys_is_enable_hw_tpc(void); +extern void bk7011_set_rf_config_tssithred(int tssi_thred); +extern int bk7011_is_rfcali_mode_auto(void); +extern void bk7011_set_rfcali_mode(int mode); +extern void bk7011_cal_dcormod_show(void); +extern void bk7011_get_tx_filter_corner(INT32 *tx_ifilter_corner, INT32 *tx_qfilter_corner); +extern void bk7011_get_tx_dc_comp(INT32 *tx_i_dc_comp, INT32 *tx_q_dc_comp); +extern void bk7011_get_tx_gain_comp(INT32 *tx_i_gain_comp, INT32 *tx_q_gain_comp); +extern void bk7011_get_tx_phase(INT32 *tx_phase_comp, INT32 *tx_phase_ty2); +extern void bk7011_get_rx_err_wr(INT32 *rx_amp_err_wr, INT32 *rx_phase_err_wr, INT32 *rx_dc_gain_tab); +extern void bk7011_get_tx_tssi_thred(INT32 *tx_tssi_thred_b, INT32 *tx_tssi_thred_g); + +extern void rwnx_cal_ble_set_rfconfig(void); +extern void rwnx_cal_ble_recover_rfconfig(void); +extern void manual_cal_set_setp0(void); +extern void manual_cal_set_setp1(void); +extern void manual_cal_clear_setp(void); +extern void manual_cal_set_rfcal_step0(void); +extern int manual_cal_rfcali_status(void); +extern UINT32 manual_cal_check_pwr_idx(UINT32 *level); +extern UINT32 manual_cal_is_in_rftest_mode(void); + +extern void rwnx_cal_en_extra_txpa(void); +extern void rwnx_cal_dis_extra_txpa(void); + +extern int manual_cal_save_cailmain_tx_tab_to_flash(void); +extern int manual_cal_save_cailmain_rx_tab_to_flash(void); +extern int manual_cal_need_load_cmtag_from_flash(void); +extern int manual_set_cmtag(UINT32 status); +extern void do_all_calibration(void); + +void bk7011_vdddig_patch(int increment) __attribute__ ((weak)); + +extern UINT32 rwnx_cal_load_user_rfcali_mode(int *rfcali_mode) __attribute__ ((weak)); +extern UINT32 rwnx_cal_load_user_g_tssi_threshold(int *tssi_g) __attribute__ ((weak)); +extern UINT32 rwnx_cal_load_user_b_tssi_threshold(int *tssi_b) __attribute__ ((weak)); +extern UINT32 rwnx_cal_is_auto_rfcali_printf_on(void) __attribute__ ((weak)); + +extern void cmd_rfcali_cfg_mode(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv); +extern void cmd_rfcali_cfg_rate_dist(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv); +extern void cmd_rfcali_cfg_tssi_g(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv); +extern void cmd_rfcali_cfg_tssi_b(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv); +extern void cmd_rfcali_show_data(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv); + +#endif // _BK7011_CAL_PUB_H_ diff --git a/beken_os/beken378/func/include/driver_audio_if_pub.h b/beken_os/beken378/func/include/driver_audio_if_pub.h new file mode 100755 index 0000000..c7f1f3b --- /dev/null +++ b/beken_os/beken378/func/include/driver_audio_if_pub.h @@ -0,0 +1,14 @@ +#ifndef DRIVER_AUDIO_IF_PUB_H +#define DRIVER_AUDIO_IF_PUB_H + +extern void aud_open(void); +extern void aud_close(void); +extern uint8_t aud_get_channel(void); +extern uint16_t aud_get_buffer_size(void); +extern void aud_fill_buffer( uint8_t *buff, uint16_t len ); +extern uint16_t aud_get_buffer_length(uint8_t *buff, uint16_t len); +extern void aud_initial(uint32_t freq, uint32_t channels, uint32_t bits_per_sample); +extern uint16_t aud_get_fill_size(void); +extern int32_t aud_hw_init(void); +extern uint8_t is_aud_opened(void); +#endif diff --git a/beken_os/beken378/func/include/driver_codec_es8374_pub.h b/beken_os/beken378/func/include/driver_codec_es8374_pub.h new file mode 100755 index 0000000..f2a19f8 --- /dev/null +++ b/beken_os/beken378/func/include/driver_codec_es8374_pub.h @@ -0,0 +1,9 @@ +#ifndef _DRIVER_CODEC_ES8374_PUB_H_ +#define _DRIVER_CODEC_ES8374_PUB_H_ + +extern void es8374_codec_init(void); +extern void es8374_codec_configure(unsigned int fs, unsigned char datawidth); +extern void es8374_codec_close(void); +extern void es8374_codec_volume_control(unsigned char volume); +extern void es8374_codec_mute_control(BOOL enable); +#endif diff --git a/beken_os/beken378/func/include/fake_clock_pub.h b/beken_os/beken378/func/include/fake_clock_pub.h new file mode 100755 index 0000000..6412eba --- /dev/null +++ b/beken_os/beken378/func/include/fake_clock_pub.h @@ -0,0 +1,32 @@ +#ifndef _FAKE_CLOCK_PUB_H_ +#define _FAKE_CLOCK_PUB_H_ + +#include "include.h" + +//#define FCLK_PWM_ID PWM0 +#define FCLK_TIMER_ID BKTIMER3 +#define CAL_TIMER_ID BKTIMER2 +#if CFG_SUPPORT_RTT +#define FCLK_DURATION_MS (1000 / RT_TICK_PER_SECOND) + +#define FCLK_SECOND (RT_TICK_PER_SECOND) +#else +#define FCLK_DURATION_MS 2 + +#define FCLK_SECOND (1000/FCLK_DURATION_MS) +#define TICK_PER_SECOND FCLK_SECOND +#endif + +#define BK_MS_TO_TICKS(x) ((x) / (FCLK_DURATION_MS)) +#define BK_TICKS_TO_MS(x) ((x) * (FCLK_DURATION_MS)) + +extern UINT64 fclk_get_tick(void); +extern UINT32 fclk_get_second(void); +extern void fclk_reset_count(void); +extern void fclk_init(void); +extern UINT32 fclk_from_sec_to_tick(UINT32 sec); +extern UINT32 fclk_cal_endvalue(UINT32 mode); + +#endif // _FAKE_CLOCK_PUB_H_ +// eof + diff --git a/beken_os/beken378/func/include/func_pub.h b/beken_os/beken378/func/include/func_pub.h new file mode 100755 index 0000000..90dee4b --- /dev/null +++ b/beken_os/beken378/func/include/func_pub.h @@ -0,0 +1,17 @@ +#ifndef _FUNC_PUB_H_ +#define _FUNC_PUB_H_ + +#define FUNC_DEBUG +#ifdef FUNC_DEBUG +#define FUNC_PRT os_printf +#define FUNC_WPRT warning_prf +#else +#define FUNC_PRT os_null_printf +#define FUNC_WPRT os_null_printf +#endif + +extern UINT32 func_init_extended(void); +extern UINT32 func_init_basic(void); +#endif // _FUNC_PUB_H_ +// eof + diff --git a/beken_os/beken378/func/include/fusb_pub.h b/beken_os/beken378/func/include/fusb_pub.h new file mode 100755 index 0000000..160897b --- /dev/null +++ b/beken_os/beken378/func/include/fusb_pub.h @@ -0,0 +1,16 @@ +#ifndef _FUSB_PUB_H_ +#define _FUSB_PUB_H_ + +//#define FMSC_TEST +//#define FHID_TEST +//#define FUVC_TEST + +#define FUSB_FAILURE ((UINT32)-1) +#define FUSB_SUCCESS (0) + +extern UINT32 fusb_init(void); +void fmsc_fiddle_process(void); + +#endif +// eof + diff --git a/beken_os/beken378/func/include/hostapd_intf_pub.h b/beken_os/beken378/func/include/hostapd_intf_pub.h new file mode 100755 index 0000000..78135ac --- /dev/null +++ b/beken_os/beken378/func/include/hostapd_intf_pub.h @@ -0,0 +1,14 @@ +#ifndef _HOSTAPD_INTF_PUB_H_ +#define _HOSTAPD_INTF_PUB_H_ + +extern int hapd_intf_ioctl(unsigned long arg); +extern void hapd_intf_ke_rx_handle(INT32 dummy); +extern int hapd_intf_set_ap(void *beacon, int bcn_len, int head_len); + +extern void wpa_buffer_scan_results(void); +extern void wpa_clear_scan_results(void); +extern void wpa_enable_traffic_port_at_opensystem(void); + +#endif +// eof + diff --git a/beken_os/beken378/func/include/manual_ps_pub.h b/beken_os/beken378/func/include/manual_ps_pub.h new file mode 100755 index 0000000..c25852d --- /dev/null +++ b/beken_os/beken378/func/include/manual_ps_pub.h @@ -0,0 +1,54 @@ +#ifndef _MANUAL_PS_PUB_H_ +#define _MANUAL_PS_PUB_H_ + + +typedef enum { + PS_DEEP_WAKEUP_GPIO = 1, + PS_DEEP_WAKEUP_RTC = 2, + PS_DEEP_WAKEUP_USB = 4, +} PS_DEEP_WAKEUP_WAY; + +typedef struct ps_deep_ctrl { + + /*deep_sleep wakeup modes */ + PS_DEEP_WAKEUP_WAY wake_up_way; + + /** @brief Request deep sleep,and wakeup by gpio,rtc,or usb. + * + * @param gpio_index_map:Indicate which GPIOs can wake up deep sleep, + * if the bit is set to 1. + * gpio_index_map is hex and every bits is map to gpio31-gpio0. + * ps:gpio1 as uart RX pin must be wake up from falling + * gpio_edge_map:The gpio edge bitmap for wakeup gpios, + * gpio_edge_map is hex and every bits is map to gpio31-gpio0. + * 0:high level wakeup,1:low level wakeup. + * gpio_stay_lo_map:The gpio bitmap which need stay ,not change in deep sleep. + * gpio_stay_lo_map is hex and every bits is map to gpio31-gpio0. + * gpio_last_index_map:Indicate which GPIOs can wake up deep sleep, + * if the bit is set to 1. + * gpio_index_map is hex and every bits is map to gpio39-gpio32. + * gpio_last_edge_map:The gpio edge bitmap for wakeup gpios, + * gpio_edge_map is hex and every bits is map to gpio39-gpio32. + * 0:high level wakeup,1:low level wakeup. + * gpio_stay_hi_map:The gpio bitmap which need stay ,not change in deep sleep. + * gpio_stay_hi_map is hex and every bits is map to gpio39-gpio32. + * + * sleep_time:the time secound when use PS_DEEP_WAKEUP_RTC wakeup. + * lpo_32k_src:the RTC wakeup source.LPO_SELECT_ROSC or LPO_SELECT_32K_XTAL. + */ + + UINT32 gpio_index_map; + UINT32 gpio_edge_map; + UINT32 gpio_stay_lo_map; + UINT32 gpio_last_index_map; + UINT32 gpio_last_edge_map; + UINT32 gpio_stay_hi_map; + + UINT32 sleep_time; + UINT32 lpo_32k_src; +} PS_DEEP_CTRL_PARAM; + +#define PS_SUPPORT_MANUAL_SLEEP 0 + +#endif + diff --git a/beken_os/beken378/func/include/mcu_ps_pub.h b/beken_os/beken378/func/include/mcu_ps_pub.h new file mode 100755 index 0000000..9a7550d --- /dev/null +++ b/beken_os/beken378/func/include/mcu_ps_pub.h @@ -0,0 +1,80 @@ +#ifndef _MCU_PS_PUB_H_ +#define _MCU_PS_PUB_H_ + +#include "typedef.h" +#include "fake_clock_pub.h" +#include "icu_pub.h" + +#define CFG_MCU_PS_SELECT_120M 1 + +typedef struct mcu_ps{ + UINT8 mcu_ps_on; + int peri_busy_count; + UINT32 mcu_prevent; +}MCU_PS_INFO; + +typedef struct sctrl_mcu_ps{ + UINT8 hw_sleep ; + UINT8 first_sleep ; + UINT8 mcu_use_dco; +}SCTRL_MCU_PS_INFO; + +#define MCU_PS_CONNECT CO_BIT(0) +#define MCU_PS_ADD_KEY CO_BIT(1) +#define MCU_PS_BLE_FROBID (1UL<<(2)) + +#define CHIP_U_MCU_WKUP_USE_TIMER 1 + + +extern void vTaskStepTick( const TickType_t ); +extern void mcu_ps_init(void); +extern void mcu_ps_exit(void); +extern UINT32 mcu_power_save(UINT32 ); +extern void mcu_prevent_clear(UINT32 ); +extern void mcu_prevent_set(UINT32 ); +extern void peri_busy_count_dec(void ); +extern void peri_busy_count_add(void ); +extern UINT32 peri_busy_count_get(void ); +extern UINT32 mcu_prevent_get(void ); +extern UINT32 fclk_update_tick(UINT32 tick); +extern void mcu_ps_dump(void); +extern void ps_pwm_reconfig(UINT32 ,UINT8 ); +extern void ps_pwm_resume_tick(void); +extern void ps_pwm_suspend_tick(UINT32 ); + + +extern void ps_timer3_measure_prepare(void); +extern UINT32 mcu_ps_tsf_cal(UINT64); +extern UINT32 mcu_ps_machw_cal(void); +extern UINT32 mcu_ps_machw_reset(void); +extern UINT32 mcu_ps_machw_init(void); + +#define PS_PWM_ID FCLK_PWM_ID +#if (PS_PWM_ID == PWM0) +#define MCU_PS_PWM_COUNTER PWM0_COUNTER +#define MCU_PS_PWM_DUTY_CYCLE PWM0_DUTY_CYCLE +#define PWD_MCU_WAKE_PWM_BIT PWD_PWM0_CLK_BIT +#elif(PS_PWM_ID == PWM1) +#define MCU_PS_PWM_COUNTER PWM1_COUNTER +#define MCU_PS_PWM_DUTY_CYCLE PWM1_DUTY_CYCLE +#define PWD_MCU_WAKE_PWM_BIT PWD_PWM1_CLK_BIT +#elif(PS_PWM_ID == PWM2) +#define MCU_PS_PWM_COUNTER PWM2_COUNTER +#define MCU_PS_PWM_DUTY_CYCLE PWM2_DUTY_CYCLE +#define PWD_MCU_WAKE_PWM_BIT PWD_PWM2_CLK_BIT +#elif(PS_PWM_ID == PWM3) +#define MCU_PS_PWM_COUNTER PWM3_COUNTER +#define MCU_PS_PWM_DUTY_CYCLE PWM3_DUTY_CYCLE +#define PWD_MCU_WAKE_PWM_BIT PWD_PWM3_CLK_BIT +#elif(PS_PWM_ID == PWM4) +#define MCU_PS_PWM_COUNTER PWM4_COUNTER +#define MCU_PS_PWM_DUTY_CYCLE PWM4_DUTY_CYCLE +#define PWD_MCU_WAKE_PWM_BIT PWD_PWM4_CLK_BIT +#elif(PS_PWM_ID == PWM5) +#define MCU_PS_PWM_COUNTER PWM5_COUNTER +#define MCU_PS_PWM_DUTY_CYCLE PWM5_DUTY_CYCLE +#define PWD_MCU_WAKE_PWM_BIT PWD_PWM5_CLK_BIT +#endif + +#endif + diff --git a/beken_os/beken378/func/include/music_msg_pub.h b/beken_os/beken378/func/include/music_msg_pub.h new file mode 100755 index 0000000..1b5c748 --- /dev/null +++ b/beken_os/beken378/func/include/music_msg_pub.h @@ -0,0 +1,89 @@ +#ifndef _MSG_PUB_H_ +#define _MSG_PUB_H_ + +#define MSG_SUCCESS_RET (0) +#define MSG_FAILURE_RET (-1) + +//-------״̬--------- +#define KEY_SHORT_UP 0x00 +#define KEY_HOLD 0x4000 +#define KEY_LONG 0x8000 +#define KEY_LONG_UP 0xc000 +#define KEY_DOUBLE_CLICK 0x2000 +#define KEY_IRDA_LONG 0x1000 +#define KEY_IRDA_SHORT 0x800 + +/* message table*/ +#define KEY_MSG_GP (0x00000000) /* Attention: special msg*/ +#define SDMUSIC_MSG_GP (0x10000000) +#define UDISK_MSG_GP (0x20000000) +#define LINEIN_MSG_GP (0x30000000) +#define OTHER_MSG_GP (0x40000000) + +/* Name format: MSG_module_messageInformation + assume: message number is less than 65535 at one module +*/ +enum +{ + MSG_NULL = 0, + /* Attention: special msg for key press, from 0x00000000--0x00000fff*/ + //-------Ϣֵ--------- + MSG_KEY_0 = MSG_NULL + 0x1, + MSG_KEY_1, + MSG_KEY_2, + MSG_KEY_3, + MSG_KEY_4, + MSG_KEY_5, + MSG_KEY_6, + MSG_KEY_7, + MSG_KEY_8, + MSG_KEY_9, + MSG_BT_MIX_KEY, + MSG_KEY_PLAY, + MSG_KEY_STOP, + MSG_KEY_PLUS, + MSG_KEY_MINUS, + MSG_KEY_PREV, + MSG_KEY_NEXT, + MSG_KEY_VOL_DOWN, + MSG_KEY_VOL_UP, + MSG_KEY_MODE, + MSG_KEY_POWER, + MSG_KEY_CALL, + MSG_NO_KEY = 0xff, + + /*sd music msg*/ + MSG_SD_INIT = SDMUSIC_MSG_GP + 0x0000, + MSG_SD_ATTACH, /* sd attach or detach*/ + MSG_SD_DETACH, + + + /*usb disk msg*/ + MSG_UDISK_INIT = UDISK_MSG_GP + 0x0000, + MSG_USB_ATTACH, + MSG_USB_DETATCH, + + /*linein msg*/ + MSG_LINEIN_INIT = LINEIN_MSG_GP + 0x0000, + MSG_LINEIN_ATTACH, + MSG_LINEIN_DETACH, + + /*other msg*/ + MSG_LED_INIT = OTHER_MSG_GP + 0x0000, + MSG_DEBUG_UART_RX, /* debug uart gets datum*/ + MSG_SDADC, /* sdadc*/ + MSG_MUSIC_PLAY, + MSG_MUSIC_STOP, + MSG_POWER_DOWN, + MSG_POWER_UP, + MSG_IRDA_RX, + MSG_LOWPOWER_DETECT, + MSG_MEDIA_READ_ERR, /* mp3-mode,SD/Udisk read Err */ + MSG_INPUT_TIMEOUT, + MSG_HALF_SECOND, + + MSG_1S_TIMER +}; + +#endif +// EOF diff --git a/beken_os/beken378/func/include/net_param_pub.h b/beken_os/beken378/func/include/net_param_pub.h new file mode 100755 index 0000000..b645c24 --- /dev/null +++ b/beken_os/beken378/func/include/net_param_pub.h @@ -0,0 +1,58 @@ +#ifndef _CFG_INFO_PUB_H +#define _CFG_INFO_PUB_H + + +#define INFO_TLV_HEADER (0x00564c54) // ASCII TLV + +typedef enum{ + AUTO_CONNECT_ITEM = 0x11111111, + WIFI_MODE_ITEM = 0x22222222, + DHCP_MODE_ITEM = 0x33333333, + WIFI_MAC_ITEM = 0x44444444, + SSID_KEY_ITEM = 0x55555555, + IP_CONFIG_ITEM = 0x66666666, + RF_CFG_TSSI_ITEM = 0x77777777, + RF_CFG_DIST_ITEM = 0x88888888, + RF_CFG_MODE_ITEM = 0x99999999, + CHARGE_CONFIG_ITEM = 0xaaaaaaaa, + RF_CFG_TSSI_B_ITEM = 0xbbbbbbbb +}NET_INFO_ITEM; + +typedef struct info_item_st +{ + UINT32 type; + UINT32 len; +}INFO_ITEM_ST,TLV_HEADER_ST,*INFO_ITEM_ST_PTR; + +typedef struct item_common_st +{ + INFO_ITEM_ST head; + UINT32 value; +}ITEM_COMM_ST,*ITEM_COMM_ST_PTR; + +typedef struct item_mac_addr_st +{ + INFO_ITEM_ST head; + char mac[6]; + char reserved[2];// 4bytes boundary +}ITEM_MAC_ADDR_ST,*ITEM_MAC_ADDR_ST_PTR; + +typedef struct item_ssidkey_st +{ + INFO_ITEM_ST head; + char wifi_ssid[32]; + char wifi_key[64]; +}ITEM_SSIDKEY_ST,*ITEM_SSIDKEY_ST_PTR; + +typedef struct item_ip_config_st +{ + INFO_ITEM_ST head; + char local_ip_addr[16]; + char net_mask[16]; + char gateway_ip_addr[16]; +}ITEM_IP_CONFIG_ST,*ITEM_IP_CONFIG_ST_PTR; + +UINT32 test_get_whole_tbl(UINT8 *ptr); +UINT32 save_info_item(NET_INFO_ITEM item,UINT8 *ptr0,UINT8*ptr1,UINT8 *ptr2); +UINT32 get_info_item(NET_INFO_ITEM item,UINT8 *ptr0,UINT8 *ptr1, UINT8 *ptr2); +#endif diff --git a/beken_os/beken378/func/include/power_save_pub.h b/beken_os/beken378/func/include/power_save_pub.h new file mode 100755 index 0000000..bfdd064 --- /dev/null +++ b/beken_os/beken378/func/include/power_save_pub.h @@ -0,0 +1,187 @@ +#ifndef _POWER_SAVE_PUB_H_ +#define _POWER_SAVE_PUB_H_ + +#include "arch.h" +#include "rtos_pub.h" +#include "rw_pub.h" +#include "wlan_ui_pub.h" + +//#define PS_DEBUG + +#ifdef PS_DEBUG +#define PS_PRT os_printf +#define PS_WPRT os_printf +#define PS_DBG os_printf + +#else +#define PS_PRT os_null_printf +#define PS_WPRT os_null_printf +#define PS_DBG os_null_printf + +#endif + +#define PS_DTIM_WITH_NORMAL 0 + +typedef enum { + PS_BMSG_IOCTL_RF_ENABLE = 0, + PS_BMSG_IOCTL_RF_DISANABLE = 1, + PS_BMSG_IOCTL_MCU_ENABLE = 2, + PS_BMSG_IOCTL_MCU_DISANABLE = 3, + PS_BMSG_IOCTL_RF_USER_WKUP = 4, + PS_BMSG_IOCTL_RF_KP_SET = 5, + PS_BMSG_IOCTL_RF_TD_SET = 6, + PS_BMSG_IOCTL_RF_KP_HANDLER = 7, + PS_BMSG_IOCTL_RF_TD_HANDLER = 8, + PS_BMSG_IOCTL_RF_KP_STOP = 9, + PS_BMSG_IOCTL_WAIT_TM_SET = 10, + PS_BMSG_IOCTL_WAIT_TM_HANDLER = 11, + PS_BMSG_IOCTL_RF_PS_TIMER_INIT = 12, + PS_BMSG_IOCTL_RF_PS_TIMER_DEINIT = 13, + +} PS_BMSG_IOCTL_CMD; + +#define ICU_BASE (0x00802000) +#define ICU_INTERRUPT_ENABLE (ICU_BASE + 16 * 4) + +#define ICU_PERI_CLK_PWD (ICU_BASE + 2 * 4) + +#define ICU_ARM_WAKEUP_EN (ICU_BASE + 20 * 4) + +#define PS_WAKEUP_MOTHOD_RW 1 + +enum +{ + NEED_DISABLE = 0, + NEED_REBOOT = 1, + NEED_START_EZ = 2, + NEED_STOP_EZ = 3, +}; +#define NEED_DISABLE_BIT CO_BIT(NEED_DISABLE) +#define NEED_REBOOT_BIT CO_BIT(NEED_REBOOT) +#define NEED_START_EZ_BIT CO_BIT(NEED_START_EZ) +#define NEED_STOP_EZ_BIT CO_BIT(NEED_STOP_EZ) + +typedef enum { + PS_FORBID_NO_ON = 1, + PS_FORBID_PREVENT = 2, + PS_FORBID_VIF_PREVENT = 3, + PS_FORBID_IN_DOZE = 4, + PS_FORBID_KEEVT_ON = 5, + PS_FORBID_BMSG_ON = 6, + PS_FORBID_TXING = 7, + PS_FORBID_HW_TIMER = 8, + PS_FORBID_RXING = 9, +} PS_FORBID_STATUS; + +typedef enum { + PS_NO_PS_MODE = 0, + PS_STANDBY_PS_MODE = 1, + PS_MCU_PS_MODE = 2, + PS_DTIM_PS_MODE = 3, + PS_DTIM_PS_OPENING = 4, + PS_DTIM_PS_CLOSING = 5, +} PS_MODE_STATUS; + + +#define PRINT_LR_REGISTER() \ +{ \ + \ + uint32_t value; \ + \ + __asm volatile( \ + "MOV %0,lr\n" \ + :"=r" (value) \ + : \ + :"memory" \ + ); \ + \ + os_printf("lr:%x\r\n", value); \ +} + +extern UINT8 power_save_if_ps_can_sleep(void); +extern UINT16 power_save_forbid_trace(PS_FORBID_STATUS forbid); +extern UINT16 power_save_beacon_len_get(void); +extern void power_save_dump(void); +extern UINT8 power_save_if_rf_sleep(); +extern UINT16 power_save_radio_wkup_get(void); +extern void power_save_radio_wkup_set(UINT16); +extern UINT8 power_save_set_dtim_multi(UINT8); +extern UINT8 power_save_sm_set_all_bcmc(UINT8 ); +extern void power_save_wkup_event_set(UINT32); +extern UINT8 power_save_if_ps_rf_dtim_enabled(void); +extern int power_save_dtim_enable(); +extern int power_save_dtim_disable(); +extern void power_save_rf_dtim_manual_do_wakeup(void); +extern void power_save_rf_ps_wkup_semlist_set(void); +extern bool power_save_rf_sleep_check( void ); +extern void ps_set_key_prevent(void); +extern void ps_clear_key_prevent(void); +extern void ps_set_data_prevent(void); +extern void ps_clear_prevent(void); +extern void txl_cntrl_dec_pck_cnt(void); +extern void txl_cntrl_inc_pck_cnt(void); +extern int bmsg_is_empty(void); +extern int net_if_is_up(void); +extern void power_save_beacon_len_set(UINT16 ); +extern void power_save_beacon_state_update(void); +extern void power_save_cal_bcn_liston_int(UINT16); +extern void power_save_delay_sleep_check(void); +extern int power_save_dtim_disable_handler(void); +extern int power_save_dtim_enable_handler(void); +extern INT8 power_save_if_sleep_at_first(void); +extern UINT8 power_save_if_sleep_first(void); +extern PS_MODE_STATUS power_save_ps_mode_get(void); +extern void power_save_ps_mode_set(PS_MODE_STATUS ); +extern void power_save_rf_ps_wkup_semlist_init(void); +extern void * power_save_rf_ps_wkup_semlist_create(void); +extern void power_save_rf_ps_wkup_semlist_wait(void *sem_list_p); +extern void power_save_rf_ps_wkup_semlist_destroy(void *sem_list_p); +extern void power_save_rf_ps_wkup_semlist_get(void *); +extern void power_save_set_dtim_count(UINT8 ); +extern void power_save_set_dtim_period(UINT8 ); +extern void power_save_sleep_status_set(void); +extern bool power_save_sleep(void); +extern void power_save_wkup_event_clear(UINT32 ); +extern void power_save_wkup_event_set(UINT32 ); +extern UINT32 power_save_wkup_event_get(void); +extern UINT8 power_save_get_liston_int(void); +extern int power_save_get_wkup_less_time(); +extern void power_save_set_linger_time(UINT32); +extern void power_save_dtim_wake(UINT32 ); +extern UINT32 power_save_use_pwm_isr(void); +extern void power_save_td_ck_timer_set(void); +extern void power_save_pwm_isr(UINT8 param); +extern void power_save_keep_timer_set(void); +extern void power_save_keep_timer_real_handler(); +extern void power_save_td_ck_timer_real_handler(); +extern void power_save_keep_timer_stop(void); +extern UINT32 power_save_get_sleep_count(void); +extern void power_save_set_reseted_flag(void); +extern void power_save_set_keep_timer_time(UINT32); +extern uint8_t ble_switch_mac_sleeped; + + + +/***************************************************************************/ +#define CHECK_OPERATE_RF_REG_IF_IN_SLEEP() \ + do { \ + GLOBAL_INT_DECLARATION(); \ + GLOBAL_INT_DISABLE(); \ + if (power_save_if_rf_sleep() || ble_switch_mac_sleeped) \ + { \ + GLOBAL_INT_RESTORE(); \ + break; \ + } \ + if (sctrl_if_rf_sleep()) \ + { \ + sctrl_rf_wakeup(); \ + } + +#define CHECK_OPERATE_RF_REG_IF_IN_SLEEP_END() \ + GLOBAL_INT_RESTORE(); \ + } while(0) +/***************************************************************************/ + +#endif // _POWER_SAVE_PUB_H_ +// eof + diff --git a/beken_os/beken378/func/include/ps_debug_pub.h b/beken_os/beken378/func/include/ps_debug_pub.h new file mode 100755 index 0000000..b80414b --- /dev/null +++ b/beken_os/beken378/func/include/ps_debug_pub.h @@ -0,0 +1,94 @@ +#ifndef _PS_DEBUG_H_ +#define _PS_DEBUG_H_ +#include "arm_arch.h" + +#define PS_USE_GPIO_TRACE 0 +#define PS_NO_USE_GPIO_WAKE 1 +#define PS_NO_USE_UART1_WAKE 0 + +#if (CFG_SOC_NAME == SOC_BK7231) + +#define PS_CK_GPIO (0x0802800 +(10*4)) +#define PS_UP_GPIO (0x0802800 +(14*4)) +#define PS_RX_GPIO (0x0802800 +(15*4)) +#define PS_BCN_GPIO (0x0802800 +(11*4)) +#define PS_DOWN_GPIO (0x0802800 +(17*4)) +#define PS_PWM_GPIO (0x0802800 +(16*4)) +#elif (CFG_SOC_NAME == SOC_BK7231U) || (CFG_SOC_NAME == SOC_BK7231N) +#define PS_CK_GPIO (0x0802800 +(6*4)) +#define PS_UP_GPIO (0x0802800 +(16*4)) +#define PS_RX_GPIO (0x0802800 +(17*4)) +#define PS_BCN_GPIO (0x0802800 +(7*4)) +#define PS_DOWN_GPIO (0x0802800 +(14*4)) +#define PS_PWM_GPIO (0x0802800 +(15*4)) +#elif (CFG_SOC_NAME == SOC_BK7221U) +#define PS_CK_GPIO (0x0802800 +(27*4)) +#define PS_UP_GPIO (0x0802800 +(22*4)) +#define PS_RX_GPIO (0x0802800 +(23*4)) +#define PS_BCN_GPIO (0x0802800 +(30*4)) +#define PS_DOWN_GPIO (0x0802800 +(20*4)) +#define PS_PWM_GPIO (0x0802800 +(21*4)) +#endif + +#if PS_USE_GPIO_TRACE +#if PS_NO_USE_GPIO_WAKE +#define PS_DEBUG_UP_OUT (REG_WRITE(PS_UP_GPIO, 0x00)) +#define PS_DEBUG_RX_OUT (REG_WRITE(PS_RX_GPIO, 0x00)) +#else +#define PS_DEBUG_UP_OUT +#define PS_DEBUG_RX_OUT +#endif + +#if PS_NO_USE_UART1_WAKE +#define PS_DEBUG_CK_OUT (REG_WRITE(PS_CK_GPIO, 0x00)) +#define PS_DEBUG_BCN_OUT (REG_WRITE(PS_BCN_GPIO, 0x00)) +#else +#define PS_DEBUG_CK_OUT +#define PS_DEBUG_BCN_OUT +#endif +#define PS_DEBUG_DOWN_OUT (REG_WRITE(PS_DOWN_GPIO, 0x00)) +#define PS_DEBUG_PWM_OUT (REG_WRITE(PS_PWM_GPIO, 0x00)) + +#if PS_NO_USE_GPIO_WAKE +#define PS_DEBUG_UP_TRIGER (REG_WRITE(PS_UP_GPIO,(REG_READ(PS_UP_GPIO))^(0x2))) +#define PS_DEBUG_RX_TRIGER (REG_WRITE(PS_RX_GPIO,(REG_READ(PS_RX_GPIO))^(0x2))) +#else +#define PS_DEBUG_UP_TRIGER +#define PS_DEBUG_RX_TRIGER +#endif + +#if PS_NO_USE_UART1_WAKE +#define PS_DEBUG_CK_TRIGER (REG_WRITE(PS_CK_GPIO,(REG_READ(PS_CK_GPIO))^(0x2))) +#define PS_DEBUG_BCN_TRIGER (REG_WRITE(PS_BCN_GPIO,(REG_READ(PS_BCN_GPIO))^(0x2))) +#define PS_DEBUG_BCN_HIGH (REG_WRITE(PS_BCN_GPIO,(REG_READ(PS_BCN_GPIO))|(0x2))) +#define PS_DEBUG_BCN_LOW (REG_WRITE(PS_BCN_GPIO,(REG_READ(PS_BCN_GPIO))&(~0x2))) + +#else +#define PS_DEBUG_CK_TRIGER +#define PS_DEBUG_BCN_TRIGER +#endif +#define PS_DEBUG_DOWN_TRIGER (REG_WRITE(PS_DOWN_GPIO,(REG_READ(PS_DOWN_GPIO))^(0x2))) +#define PS_DEBUG_PWM_TRIGER (REG_WRITE(PS_PWM_GPIO,(REG_READ(PS_PWM_GPIO))^(0x2))) +#define PS_DEBUG_PWM_HIGH (REG_WRITE(PS_PWM_GPIO,(REG_READ(PS_PWM_GPIO))|(0x2))) +#define PS_DEBUG_PWM_LOW (REG_WRITE(PS_PWM_GPIO,(REG_READ(PS_PWM_GPIO))&(~0x2))) + +#else +#define PS_DEBUG_UP_OUT +#define PS_DEBUG_RX_OUT +#define PS_DEBUG_CK_OUT +#define PS_DEBUG_BCN_OUT +#define PS_DEBUG_DOWN_OUT +#define PS_DEBUG_PWM_OUT +#define PS_DEBUG_UP_TRIGER +#define PS_DEBUG_RX_TRIGER +#define PS_DEBUG_CK_TRIGER +#define PS_DEBUG_BCN_TRIGER +#define PS_DEBUG_DOWN_TRIGER +#define PS_DEBUG_PWM_TRIGER +#endif + +#endif // _PS_DEBUG_H_ +// eof + + + diff --git a/beken_os/beken378/func/include/pseudo_random_pub.h b/beken_os/beken378/func/include/pseudo_random_pub.h new file mode 100755 index 0000000..fd5e431 --- /dev/null +++ b/beken_os/beken378/func/include/pseudo_random_pub.h @@ -0,0 +1,7 @@ +#ifndef _PSEUDO_RANDOM_PUB_H_ +#define _PSEUDO_RANDOM_PUB_H_ + +extern uint32_t prandom_get(void); + +#endif // _PSEUDO_RANDOM_PUB_H_ +// eof diff --git a/beken_os/beken378/func/include/rw_pub.h b/beken_os/beken378/func/include/rw_pub.h new file mode 100755 index 0000000..8cdf559 --- /dev/null +++ b/beken_os/beken378/func/include/rw_pub.h @@ -0,0 +1,363 @@ +#ifndef _RW_PUB_H_ +#define _RW_PUB_H_ + +#include "ke_msg.h" +#include "uart_pub.h" +#include "rw_ieee80211.h" +#include "rtos_pub.h" +#include "rw_ieee80211.h" +#include "apm_task.h" +#include "me_task.h" +#include "mm_task.h" +#include "mm.h" +#include "lwip/netif.h" +#include "vif_mgmt.h" + +#define RWI_DEBUG + +#ifdef RWI_DEBUG +#define RWI_PRT os_printf +#define RWI_WPRT warning_prf +#else +#define RWI_PRT os_null_printf +#define RWI_WPRT os_null_printf +#endif + +#define RW_SUCCESS (0) +#define RW_FAILURE ((UINT32)-1) + +typedef struct cfg80211_connect_params +{ + uint32_t flags; + uint32_t vif_idx; + uint8_t auth_type; + struct mac_addr bssid; + struct mac_ssid ssid; + struct scan_chan_tag chan; + uint16_t ie_len; + uint32_t ie_buf[64]; + uint16_t bcn_len; + uint32_t bcn_buf[0]; +} CONNECT_PARAM_T; + +typedef struct cfg80211_external_auth_params +{ + uint32_t vif_idx; + uint16_t status; +} EXTERNAL_AUTH_PARAM_T; + +typedef struct cfg80211_scan_params +{ + uint8_t num_ssids; + uint8_t vif_idx; + struct mac_ssid ssids[SCAN_SSID_MAX]; + struct mac_addr bssid; + int freqs[14]; //FIXME: 5G +} SCAN_PARAM_T; + +typedef struct cfg80211_fast_scan_params +{ + struct mac_ssid ssid; + struct mac_addr bssid; + + uint16_t probe_delay; + uint16_t min_ch_time; + uint16_t max_ch_time; + uint16_t ch_num; +}FAST_SCAN_PARAM_T; + +typedef struct cfg80211_disconnect_params +{ + uint16_t reason_code; + uint8_t vif_idx; +}DISCONNECT_PARAM_T; + +typedef struct scanu_rst_upload +{ + UINT8 scanu_num; + struct sta_scan_res **res; +}SCAN_RST_UPLOAD_T, *SCAN_RST_UPLOAD_PTR; + + +typedef struct sta_scan_res +{ + UINT8 bssid[6]; + char ssid[32]; /**< The SSID of an access point. */ + char on_channel; // 1: ds IE channel=center_freq, 0: != + char channel; + bool is_probersp; // true if scan result is probe response + UINT16 beacon_int; + UINT16 caps; + int level; + int security; // security type + UINT8 tsf[8]; + UINT32 ie_len; + /* Followed by ie_len of IE data */ +}SCAN_RST_ITEM_T, *SCAN_RST_ITEM_PTR; + + +typedef struct +{ + char ssid[MAC_SSID_LEN]; + char ap_power; +}AP_INFO_T; + +typedef struct +{ + uint16_t ap_num; + uint16_t ap_max; + + AP_INFO_T *ap_list; +} SCAN_RESULT_SET; + +typedef struct +{ + FUNC_2PARAM_PTR cb; + void *ctxt_arg; +}IND_CALLBACK_T; + +typedef struct +{ + int8_t rssi; + uint8_t ssid[32]; + uint8_t bssid[6]; + uint16_t freq; +}BSS_INFO_T; + +enum nl80211_iftype { + NL80211_IFTYPE_UNSPECIFIED, + NL80211_IFTYPE_ADHOC, + NL80211_IFTYPE_STATION, + NL80211_IFTYPE_AP, + NL80211_IFTYPE_AP_VLAN, + NL80211_IFTYPE_WDS, + NL80211_IFTYPE_MONITOR, + NL80211_IFTYPE_MESH_POINT, + NL80211_IFTYPE_P2P_CLIENT, + NL80211_IFTYPE_P2P_GO, + NL80211_IFTYPE_P2P_DEVICE, + NL80211_IFTYPE_OCB, + + /* keep last */ + NUM_NL80211_IFTYPES, + NL80211_IFTYPE_MAX = NUM_NL80211_IFTYPES - 1 +}; + +typedef enum +{ + /* for station mode */ + RW_EVT_STA_IDLE = 0, + RW_EVT_STA_SCANNING, + RW_EVT_STA_SCAN_OVER, + RW_EVT_STA_CONNECTING, + RW_EVT_STA_BEACON_LOSE, + RW_EVT_STA_PASSWORD_WRONG, /* 5 */ + RW_EVT_STA_NO_AP_FOUND, + RW_EVT_STA_ASSOC_FULL, + RW_EVT_STA_DISCONNECTED, /* 8 disconnect with server */ + RW_EVT_STA_CONNECT_FAILED, /* 9 authentication failed */ + RW_EVT_STA_DHCP_FAILED, + RW_EVT_STA_CONNECTED, /* 11 authentication success */ + RW_EVT_STA_GOT_IP, + + /* for softap mode */ + RW_EVT_AP_CONNECTED, /* a client association success */ + RW_EVT_AP_DISCONNECTED, /* a client disconnect */ + RW_EVT_AP_CONNECT_FAILED, /* a client association failed */ + + RW_EVT_MAX +}rw_evt_type; + +typedef int (*rw_event_handler)(rw_evt_type evt_type, void *data); + +struct rw_evt_payload +{ + uint8_t mac[6]; +}; + +struct add_sta_st { + u16 aid; + u16 capability; + void *sta_addr; + u8 tx_supp_rates; + u8 ap_vif_idx; +} ; + +typedef struct cfg80211_key_params +{ + uint8_t cipher_suite; + uint8_t sta_idx; + uint8_t inst_nbr; + uint8_t key_idx; + uint8_t hw_key_idx; + struct mac_sec_key key; +} KEY_PARAM_T; + +typedef struct msg_send_node +{ + struct co_list_hdr hdr; + struct ke_msg *msg; + void *cfm; + beken_semaphore_t semaphore; + uint16_t reqid; +}MSG_SND_NODE_ST, *MSG_SND_NODE_PTR; + +typedef struct bcn_param_st { + u32 *bcn_ptr; + u16 bcn_len; + u16 tim_oft; + + u8 tim_len; + u8 vif_idx; + u16 flag; + + u8* csa_oft; +} BCN_PARAM_ST, *BCN_PARAM_PTR; + +typedef enum { + WIFI_COUNTRY_POLICY_AUTO, /**< Country policy is auto, use the country info of AP to which the station is connected */ + WIFI_COUNTRY_POLICY_MANUAL, /**< Country policy is manual, always use the configured country info */ +} wifi_country_policy_t; + +/** @brief Structure describing WiFi country-based regional restrictions. */ +typedef struct { + char cc[3]; /**< country code string */ + uint8_t schan; /**< start channel */ + uint8_t nchan; /**< total channel number */ + int8_t max_tx_power; /**< maximum tx power */ + wifi_country_policy_t policy; /**< country policy */ +} wifi_country_t; + +typedef struct vif_info_tag VIF_INF_ST; +typedef struct vif_info_tag* VIF_INF_PTR; +typedef struct sta_info_tag STA_INF_ST; +typedef struct sta_info_tag* STA_INF_PTR; + +extern struct co_list rw_msg_tx_head; +extern struct co_list rw_msg_rx_head; + +extern void mt_msg_dispatch(UINT16 cmd, void *param); +extern void mr_kmsg_flush(void); +extern UINT32 mr_kmsg_fwd(struct ke_msg *msg); +extern UINT32 mr_kmsg_fuzzy_handle(void); +extern UINT32 mr_kmsg_exact_handle(UINT16 rsp); +extern void mhdr_assoc_cfm_cb(FUNC_2PARAM_PTR ind_cb, void *ctxt); +extern void mhdr_scanu_reg_cb(FUNC_2PARAM_PTR ind_cb, void *ctxt); +extern void mhdr_connect_user_cb(FUNC_2PARAM_PTR ind_cb, void *ctxt); +extern UINT32 rw_ieee80211_init(void); +extern UINT32 rw_ieee80211_get_centre_frequency(UINT32 chan_id); +extern UINT8 rw_ieee80211_get_chan_id(UINT32 freq); +extern void *sr_get_scan_results(void); +extern void sr_release_scan_results(SCAN_RST_UPLOAD_PTR ptr); +extern UINT32 rwm_transfer(UINT8 vif_idx, UINT8 *buf, UINT32 len, int sync, void *arg); +extern void* rwm_transfer_pre(UINT8 vif_idx, UINT8 *buf, UINT32 len); +extern UINT32 rwm_uploaded_data_handle(UINT8 *upper_buf, UINT32 len); +extern UINT32 rwm_get_rx_valid_node_len(void); +extern void mhdr_set_station_status(rw_evt_type val); +extern rw_evt_type mhdr_get_station_status(void); + +typedef void (*STATION_STATUS_CB)(rw_evt_type type); +extern void mhdr_set_station_status_cb(STATION_STATUS_CB cb); + +extern int rw_msg_send(const void *msg_params, uint16_t reqid, void *cfm); +extern int rw_msg_send_reset(void); +extern int rw_msg_send_start(void); + +/** + * @brief equest MAC to enter active mode. + * This function changes MAC state to ACTIVE. + * + * @return 0 if success, else failed. + */ +extern int rw_msg_send_mm_active_req(); +extern int rw_msg_send_me_config_req(void); +extern int rw_msg_send_me_chan_config_req(void); +extern int rw_msg_send_add_if(const unsigned char *mac, + enum nl80211_iftype iftype, bool p2p, struct mm_add_if_cfm *cfm); +extern int rw_msg_send_remove_if(u8 vif_index); +extern int rw_msg_send_apm_start_req(u8 vif_index, u8 channel, + struct apm_start_cfm *cfm); +extern int rw_msg_send_bcn_change(void *bcn_param); +extern int rw_msg_send_me_sta_add(struct add_sta_st *param, + struct me_sta_add_cfm *cfm); +extern int rw_msg_send_me_sta_del(u8 sta_idx, bool tdls_sta); +extern int rw_msg_me_set_control_port_req(bool opened, u8 sta_idx); +extern int rw_msg_send_key_add(KEY_PARAM_T *param, struct mm_key_add_cfm *cfm); +extern int rw_msg_send_key_del(u8 hw_key_idx); +extern int rw_msg_send_scanu_req(SCAN_PARAM_T *scan_param); +extern int rw_msg_send_connection_loss_ind(u8 vif_index); +extern int rw_msg_get_bss_info(u8 vif_idx, void *cfm); +extern int rw_msg_get_channel(void *cfm); +extern int rw_msg_set_filter(uint32_t filter); +extern int rw_msg_set_channel(uint32_t channel, uint32_t band_width, void *cfm); +extern int rw_msg_send_scan_cancel_req(void *cfm); +extern int rw_msg_send_sm_disconnect_req(DISCONNECT_PARAM_T *param); +extern int rw_msg_send_sm_connect_req( CONNECT_PARAM_T *sme, void *cfm); +extern int rw_msg_send_tim_update(u8 vif_idx, u16 aid, u8 tx_status); +extern int rw_msg_send_apm_stop_req(u8 vif_index); +extern int rw_msg_set_power(u8 vif_idx, u8 power); +extern int rw_msg_send_sm_external_auth_status(EXTERNAL_AUTH_PARAM_T *auth_param); + + +extern VIF_INF_PTR rwm_mgmt_vif_idx2ptr(UINT8 vif_idx); +extern VIF_INF_PTR rwm_mgmt_vif_type2ptr(UINT8 vif_type); +extern STA_INF_PTR rwm_mgmt_sta_idx2ptr(UINT8 staid); +extern STA_INF_PTR rwm_mgmt_sta_mac2ptr(void *mac); +extern UINT8 rwm_mgmt_sta_mac2idx(void *mac); +extern UINT8 rwm_mgmt_vif_mac2idx(void *mac); +extern UINT8 rwm_mgmt_vif_name2idx(char *name); +extern UINT8 rwm_mgmt_get_hwkeyidx(UINT8 vif_idx, UINT8 staid); +extern void rwm_mgmt_set_vif_netif(struct netif *net_if); +extern struct netif *rwm_mgmt_get_vif2netif(UINT8 vif_idx); +extern UINT8 rwm_mgmt_get_netif2vif(struct netif *netif); +extern UINT8 rwm_mgmt_tx_get_staidx(UINT8 vif_idx, void *dstmac); +extern u8 rwn_mgmt_is_only_sta_role_add(void); +extern void rwm_msdu_init(void); +extern void rwm_flush_txing_list(UINT8 sta_idx); +extern void rwm_msdu_ps_change_ind_handler(void *msg) ; +extern void rwm_msdu_send_txing_node(UINT8 sta_idx); + +__INLINE u8 rwm_mgmt_is_ap_inface(u8 vif_idx) +{ + return (vif_info_tab[vif_idx].type == VIF_AP); +} + +__INLINE u8 rwm_mgmt_is_sta_inface(u8 vif_idx) +{ + return (vif_info_tab[vif_idx].type == VIF_STA); +} + +__INLINE void *rwm_mgmt_is_vif_first_used(void) +{ + return((void *)co_list_pick(&vif_mgmt_env.used_list)); +} + +__INLINE void *rwm_mgmt_next(VIF_INF_PTR vif_entry) +{ + return((void *)co_list_next(&vif_entry->list_hdr)); +} + +__INLINE u8 rwm_mgmt_get_type(u8 vif_idx) +{ + return (vif_info_tab[vif_idx].type); +} + +__INLINE void *rwm_mgmt_get_addr(u8 vif_idx) +{ + return (&vif_info_tab[vif_idx].mac_addr); +} + +extern const UINT8 beacon[149]; + +UINT32 rw_ieee80211_set_country(const wifi_country_t *country); +UINT32 rw_ieee80211_get_country(wifi_country_t *country); +UINT8 rw_ieee80211_init_scan_chan(struct scanu_start_req *req); +UINT8 rw_ieee80211_is_scan_rst_in_countrycode(UINT8 freq); + +#if CFG_IEEE80211N +void rw_ieee80211_set_ht_cap(UINT8 ht_supp); +#endif + +#endif //_RW_PUB_H_ +// eof + diff --git a/beken_os/beken378/func/include/rx_sensitivity_pub.h b/beken_os/beken378/func/include/rx_sensitivity_pub.h new file mode 100755 index 0000000..b3ea9a2 --- /dev/null +++ b/beken_os/beken378/func/include/rx_sensitivity_pub.h @@ -0,0 +1,26 @@ +#ifndef _RX_SENSITIVITY_H_ +#define _RX_SENSITIVITY_H_ + +/******************************************************************************* +* Function Declarations +*******************************************************************************/ +extern void rs_test(void); +extern void rx_get_rx_result_begin(void); +extern void rx_get_rx_result_end(void); +extern UINT32 rs_set_channel(UINT32 channel_id); +extern UINT32 rs_set_mode(UINT32 mode); + +extern void rx_clean_rx_statistic_result(void); +extern UINT32 rx_get_rx20M_statistic_result(void); +extern UINT32 rx_get_rx40M_statistic_result(void); + +extern void rx_clean_ble_rx_result(void); +extern void rx_start_ble_rx_counting(); +extern void rs_ble_test_start(UINT32 channel); +extern void rs_ble_test_stop(void); +extern void rx_get_ble_rx_result(void); + + +#endif //_RX_SENSITIVITY_H_ +// eof + diff --git a/beken_os/beken378/func/include/schedule_pub.h b/beken_os/beken378/func/include/schedule_pub.h new file mode 100755 index 0000000..a46a06a --- /dev/null +++ b/beken_os/beken378/func/include/schedule_pub.h @@ -0,0 +1,6 @@ +#ifndef _SCHEDULE_PUB_H_ +#define _SCHEDULE_PUB_H_ + +#endif // _SCHEDULE_PUB_H_ +// eof + diff --git a/beken_os/beken378/func/include/sdio_intf_pub.h b/beken_os/beken378/func/include/sdio_intf_pub.h new file mode 100755 index 0000000..ed3ec53 --- /dev/null +++ b/beken_os/beken378/func/include/sdio_intf_pub.h @@ -0,0 +1,31 @@ +#ifndef _SDIO_INTF_PUB_H_ +#define _SDIO_INTF_PUB_H_ + +#include "sdio_pub.h" +#include "ke_msg.h" +#include "tx_swdesc.h" + +#define SDIO_INTF_FAILURE ((UINT32)-1) +#define SDIO_INTF_SUCCESS (0) + +/******************************************************************************* +* Function Declarations +*******************************************************************************/ +extern UINT32 sdio_intf_init(void); +extern void sdio_emb_rxed_evt(int dummy); +extern UINT32 outbound_upload_data(UINT8 *buf_ptr, UINT32 len); +extern UINT32 sdio_get_free_node(UINT8 **buf_pptr, UINT32 buf_size); +extern void sdio_emb_rxed_evt(int dummy); +extern void inbound_cfm(void *); +extern UINT32 sdio_emb_kmsg_fwd(struct ke_msg *msg); + +extern UINT32 sdio_get_free_node_count(void); +extern UINT32 sdio_release_one_node(SDIO_NODE_PTR mem_node_ptr); + +extern void sdio_trans_evt(int dummy); +extern SDIO_NODE_PTR sdio_get_rxed_node(void); +extern int sdio_trans_init(void); + +#endif // _SDIO_INTF_PUB_H_ + + diff --git a/beken_os/beken378/func/include/start_type_pub.h b/beken_os/beken378/func/include/start_type_pub.h new file mode 100755 index 0000000..3ba7f22 --- /dev/null +++ b/beken_os/beken378/func/include/start_type_pub.h @@ -0,0 +1,42 @@ +#ifndef _START_TYPE_PUB_H_ +#define _START_TYPE_PUB_H_ + +#define START_TYPE_ADDR (0x0080a080) + +#define CRASH_XAT0_VALUE 0xbedead00 +#define CRASH_UNDEFINED_VALUE 0xbedead01 +#define CRASH_PREFETCH_ABORT_VALUE 0xbedead02 +#define CRASH_DATA_ABORT_VALUE 0xbedead03 +#define CRASH_UNUSED_VALUE 0xbedead04 +#define CRASH_2ND_XAT0_VALUE 0xbedead05 + +#define START_TYPE_DMEMORY_ADDR (0x0040001c) + + +typedef enum { + RESET_SOURCE_POWERON = 0, + RESET_SOURCE_REBOOT = 1, + RESET_SOURCE_WATCHDOG = 2, + + RESET_SOURCE_DEEPPS_GPIO = 3, + RESET_SOURCE_DEEPPS_RTC = 4, + + RESET_SOURCE_CRASH_XAT0 = 5, + RESET_SOURCE_CRASH_UNDEFINED = 6, + RESET_SOURCE_CRASH_PREFETCH_ABORT = 7, + RESET_SOURCE_CRASH_DATA_ABORT = 8, + RESET_SOURCE_CRASH_UNUSED = 9, + RESET_SOURCE_CRASH_PER_XAT0 = 10, + + RESET_SOURCE_UNKNOWN = 0xb, +} RESET_SOURCE_STATUS; + +extern RESET_SOURCE_STATUS bk_misc_init_start_type(void); +extern void bk_misc_update_set_type(RESET_SOURCE_STATUS type); +extern RESET_SOURCE_STATUS bk_misc_get_start_type(); +extern RESET_SOURCE_STATUS sctrl_get_deep_sleep_wake_soure(void); +extern void bk_misc_check_start_type(); + +#endif ///_START_TYPE_PUB_H_ + +// eof \ No newline at end of file diff --git a/beken_os/beken378/func/include/target_util_pub.h b/beken_os/beken378/func/include/target_util_pub.h new file mode 100755 index 0000000..a46f457 --- /dev/null +++ b/beken_os/beken378/func/include/target_util_pub.h @@ -0,0 +1,9 @@ +#ifndef _TARGET_UTIL_PUB_H_ +#define _TARGET_UTIL_PUB_H_ + +extern void delay(INT32 num); +extern void delay_ms(UINT32 ms_count); +extern void delay_sec(UINT32 ms_count); +extern void delay_tick(UINT32 tick_count); + +#endif // _TARGET_UTIL_PUB_H_ diff --git a/beken_os/beken378/func/include/tx_evm_pub.h b/beken_os/beken378/func/include/tx_evm_pub.h new file mode 100755 index 0000000..b582fa7 --- /dev/null +++ b/beken_os/beken378/func/include/tx_evm_pub.h @@ -0,0 +1,45 @@ +#ifndef _TX_EVM_PUB_H_ +#define _TX_EVM_PUB_H_ + +#include "hal_desc.h" + +#define TX_LEGACY_MODE (1) +#define TX_HT_VHT_MODE (2) + +#define TX_LEGACY_DATA_LEN_MASK (0xFFF) +#define TX_HT_VHT_DATA_LEN_MASK (0xFFFFF) + +typedef enum +{ + SINGLE_CARRIER_11B, + SINGLE_CARRIER_11G, + SINGLE_CARRIER_BLE +} SC_TYPE_T; + +/******************************************************************************* +* Function Declarations +*******************************************************************************/ +extern void evm_via_mac_evt(INT32 dummy); +extern void evm_via_mac_begin(void); +extern void evm_via_mac_continue(void); +extern UINT32 evm_bypass_mac_set_tx_data_length(UINT32 modul_format, UINT32 len, UINT32 rate, UINT32 bandwidth, UINT32 need_change); +extern UINT32 evm_bypass_mac_set_rate_mformat(UINT32 ppdu_rate, UINT32 m_format); +extern void evm_bypass_mac_set_channel(UINT32 channel); +extern void evm_via_mac_set_channel(UINT32 channel); +extern void evm_bypass_mac_test(void); +extern void evm_via_mac_set_rate(HW_RATE_E rate, uint32_t modul_format, uint32_t guard_i_tpye); +extern void evm_set_bandwidth(UINT32 bandwidth); +extern void evm_stop_bypass_mac(void); +extern void evm_bypass_mac_set_guard_i_type(UINT32 gi_tpye); +extern void evm_start_bypass_mac(void); +extern void evm_bypass_set_single_carrier(SC_TYPE_T type, UINT32 rate); +extern void evm_bypass_ble_test_start(UINT32 channel); +extern void evm_bypass_ble_test_stop(void); +extern void evm_via_mac_init(void); +extern void evm_via_mac_set_power(UINT32 pwr_idx); +extern void evm_via_mac_set_bandwidth(UINT32 bandwidth); +extern UINT32 evm_bypass_mac_set_txdelay(UINT32 delay_us); + +#endif //_TX_EVM_PUB_H_ +// eof + diff --git a/beken_os/beken378/func/include/uart_debug_pub.h b/beken_os/beken378/func/include/uart_debug_pub.h new file mode 100755 index 0000000..13e06f6 --- /dev/null +++ b/beken_os/beken378/func/include/uart_debug_pub.h @@ -0,0 +1,14 @@ +#ifndef _UART_DEBUG_PUB_H_ +#define _UART_DEBUG_PUB_H_ + +#include "uart_pub.h" + +/******************************************************************************* +* Function Declarations +*******************************************************************************/ +extern UINT32 udebug_has_ctrlc(void); +extern UINT32 udebug_wait_ctrlc_exit(void); +extern UINT32 uart_debug_init(void); + +#endif // _UART_DEBUG_PUB_H_ + diff --git a/beken_os/beken378/func/include/ump3_pub.h b/beken_os/beken378/func/include/ump3_pub.h new file mode 100755 index 0000000..b17e061 --- /dev/null +++ b/beken_os/beken378/func/include/ump3_pub.h @@ -0,0 +1,8 @@ +#ifndef _U_MP3_PUB_H_ +#define _U_MP3_PUB_H_ + +extern void um_init(void); +extern void um_uninit(void); + +#endif // _U_MP3_PUB_H_ +// eof diff --git a/beken_os/beken378/func/include/wlan_cli_pub.h b/beken_os/beken378/func/include/wlan_cli_pub.h new file mode 100755 index 0000000..013a661 --- /dev/null +++ b/beken_os/beken378/func/include/wlan_cli_pub.h @@ -0,0 +1,171 @@ +/** + * UNPUBLISHED PROPRIETARY SOURCE CODE + * Copyright (c) 2016 BEKEN Inc. + * + * The contents of this file may not be disclosed to third parties, copied or + * duplicated in any form, in whole or in part, without the prior written + * permission of BEKEN Corporation. + * + */ +#ifndef __WLAN_CLI_PUB_H__ +#define __WLAN_CLI_PUB_H__ + +#include "include.h" +#include "BkDriverUart.h" + +#if CFG_UART2_CLI +#define CLI_UART BK_UART_2 +#else +#define CLI_UART BK_UART_1 +#endif + +#define RX_WAIT BEKEN_WAIT_FOREVER +#define SEND_WAIT BEKEN_WAIT_FOREVER + +#define RET_CHAR '\n' +#define END_CHAR '\r' +#define PROMPT "\r\n# " +#define EXIT_MSG "exit" + +#define NUM_BUFFERS 1 +#define MAX_COMMANDS 64 +#define INBUF_SIZE 128 +#define OUTBUF_SIZE 2048 + +#define LOG_SERVICE_BUFLEN 100 + +/** Structure for registering CLI commands */ +struct cli_command +{ + /** The name of the CLI command */ + const char *name; + /** The help text associated with the command */ + const char *help; + /** The function that should be invoked for this command. */ + void (*function) (char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv); +}; + +struct cli_st +{ + int initialized; + const struct cli_command *commands[MAX_COMMANDS]; + unsigned int num_commands; + int echo_disabled; + + unsigned int bp; /* buffer pointer */ + char inbuf[INBUF_SIZE]; + + char outbuf[OUTBUF_SIZE]; +} ; + + +#define cmd_printf(...) do{\ + if (xWriteBufferLen > 0) {\ + snprintf(pcWriteBuffer, xWriteBufferLen, __VA_ARGS__);\ + xWriteBufferLen-= os_strlen(pcWriteBuffer);\ + pcWriteBuffer+= os_strlen(pcWriteBuffer);\ + }\ + }while(0) + + +#define CLI_ARGS char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv + +#define is_print(c) ((u8_t)c >= 0x20 && (u8_t)c <= 0x7f) + +/** Register a CLI command + * + * This function registers a command with the command-line interface. + * + * \param[in] command The structure to register one CLI command + * \return 0 on success + * \return 1 on failure + */ +int cli_register_command(const struct cli_command *command); + +/** Unregister a CLI command + * + * This function unregisters a command from the command-line interface. + * + * \param[in] command The structure to unregister one CLI command + * \return 0 on success + * \return 1 on failure + */ +int cli_unregister_command(const struct cli_command *command); + + + +/** Stop the CLI thread and carry out the cleanup + * + * \return kNoErr on success + * \return error code otherwise. + * + */ +int cli_stop(void); + +/** Register a batch of CLI commands + * + * Often, a module will want to register several commands. + * + * \param[in] commands Pointer to an array of commands. + * \param[in] num_commands Number of commands in the array. + * \return 0 on success + * \return 1 on failure + */ +int cli_register_commands(const struct cli_command *commands, int num_commands); + +/** Unregister a batch of CLI commands + * + * \param[in] commands Pointer to an array of commands. + * \param[in] num_commands Number of commands in the array. + * \return 0 on success + * \return 1 on failure + */ +int cli_unregister_commands(const struct cli_command *commands, + int num_commands); + +/* Get a CLI msg + * + * If an external input task wants to use the CLI, it can use + * cli_get_cmd_buffer() to get a command buffer that it can then + * submit to the CLI later using cli_submit_cmd_buffer(). + * + * \param buff Pointer to a char * to place the buffer pointer in. + * \return 0 on success + * \return error code otherwise. + */ +int cli_getchar(char *inbuf); +int cli_getchars(char *inbuf, int len); +int cli_get_all_chars_len(void); +int cli_getchars_prefetch(char *inbuf, int len); + +/* Send CLI output msg + * + * \param buff Pointer to a char * buffer. + * \return 0 on success + * \return error code otherwise. + */ +int cli_printf(const char *buff, ...); + + +// library CLI APIs +int cli_init(void); +void wifistate_Command(CLI_ARGS); +void wifidebug_Command(CLI_ARGS); +void wifiscan_Command(CLI_ARGS); +void ifconfig_Command(CLI_ARGS); +void arp_Command(CLI_ARGS); +void ping_Command(CLI_ARGS); +void dns_Command(CLI_ARGS); +void socket_show_Command(CLI_ARGS); +void memory_show_Command(CLI_ARGS); +void memory_dump_Command(CLI_ARGS); +void memory_set_Command(CLI_ARGS); +//void memp_dump_Command(CLI_ARGS); +void driver_state_Command(CLI_ARGS); + +#ifdef MOC +void task_Command(CLI_ARGS); +#endif + +#endif + diff --git a/beken_os/beken378/func/include/wlan_ui_pub.h b/beken_os/beken378/func/include/wlan_ui_pub.h new file mode 100755 index 0000000..4d176bd --- /dev/null +++ b/beken_os/beken378/func/include/wlan_ui_pub.h @@ -0,0 +1,596 @@ +#ifndef _WLAN_UI_PUB_ +#define _WLAN_UI_PUB_ + +#pragma once + +#include "include.h" +#include "rtos_pub.h" +#include "rw_pub.h" + +#if CFG_WPA_CTRL_IFACE +#include "wlan_defs.h" +#include "notifier.h" +#endif +#if CFG_SUPPORT_ALIOS +#include +#endif +#include "manual_ps_pub.h" + +#define ICU_BASE (0x00802000) +#define ICU_INT_STATUS (ICU_BASE + 19 * 4) + +#if CFG_SUPPORT_ALIOS +enum { + WLAN_ENC_OPEN, + WLAN_ENC_WEP, + WLAN_ENC_CCMP, + WLAN_ENC_TKIP, +}; +#else +#define WiFi_Interface wlanInterfaceTypedef + +#define DHCP_DISABLE (0) /**< Disable DHCP service. */ +#define DHCP_CLIENT (1) /**< Enable DHCP client which get IP address from DHCP server automatically, + reset Wi-Fi connection if failed. */ +#define DHCP_SERVER (2) /**< Enable DHCP server, needs assign a static address as local address. */ + +typedef enum _wifi_dis_reason +{ + UNSUPPORT_ENCRYPT = 0, + WRONG_PASSPHRASE, + DEAUTHENTICATION, + DISASSOCIATION, + AP_MISSING, + DISCONNECT, +} WIFI_DISCONN_REASON; + +typedef struct _wifi_link_info +{ + uint8_t bssid[6]; + int16_t rssi; + + uint32_t data_rate; + WIFI_DISCONN_REASON reason; +} WIFI_LINK_INFO_T; + +/** + * @brief wlan network interface enumeration definition. + */ +typedef enum +{ + SOFT_AP, /**< Act as an access point, and other station can connect, 4 stations Max*/ + STATION /**< Act as a station which can connect to an access point*/ +} wlanInterfaceTypedef; + +/** + * @brief Wi-Fi security type enumeration definition. + */ +enum wlan_sec_type_e +{ + SECURITY_TYPE_NONE, /**< Open system. */ + SECURITY_TYPE_WEP, /**< Wired Equivalent Privacy. WEP security. */ + SECURITY_TYPE_WPA_TKIP, /**< WPA /w TKIP */ + SECURITY_TYPE_WPA_AES, /**< WPA /w AES */ + SECURITY_TYPE_WPA2_TKIP, /**< WPA2 /w TKIP */ + SECURITY_TYPE_WPA2_AES, /**< WPA2 /w AES */ + SECURITY_TYPE_WPA2_MIXED, /**< WPA2 /w AES or TKIP */ + SECURITY_TYPE_WPA3_SAE, /**< WPA3 SAE */ + SECURITY_TYPE_WPA3_WPA2_MIXED, /** WPA3 SAE or WPA2 AES */ + SECURITY_TYPE_AUTO, /**< It is used when calling @ref bkWlanStartAdv, _BK_ read security type from scan result. */ +}; +#endif + +enum +{ + WLAN_RX_BEACON, /* receive beacon packet */ + WLAN_RX_PROBE_REQ, /* receive probe request packet */ + WLAN_RX_PROBE_RES, /* receive probe response packet */ + WLAN_RX_ACTION, /* receive action packet */ + WLAN_RX_MANAGEMENT,/* receive ALL management packet */ + WLAN_RX_DATA, /* receive ALL data packet */ + WLAN_RX_MCAST_DATA,/* receive ALL multicast and broadcast packet */ + + WLAN_RX_ALL, /* receive ALL 802.11 packet */ +}; + +#if (!CFG_SUPPORT_ALIOS) +typedef uint8_t wlan_sec_type_t; + +/** + * @brief wlan local IP information structure definition. + */ +typedef struct +{ + uint8_t dhcp; /**< DHCP mode: @ref DHCP_Disable, @ref DHCP_Client, @ref DHCP_Server.*/ + char ip[16]; /**< Local IP address on the target wlan interface: @ref wlanInterfaceTypedef.*/ + char gate[16]; /**< Router IP address on the target wlan interface: @ref wlanInterfaceTypedef.*/ + char mask[16]; /**< Netmask on the target wlan interface: @ref wlanInterfaceTypedef.*/ + char dns[16]; /**< DNS server IP address.*/ + char mac[16]; /**< MAC address, example: "C89346112233".*/ + char broadcastip[16]; +} IPStatusTypedef; + +/** + * @brief Scan result using normal scan. + */ +typedef struct _ScanResult +{ + char ApNum; /**< The number of access points found in scanning. */ + struct + { + char ssid[33]; /**< The SSID of an access point. */ + char ApPower; /**< Signal strength, min:0, max:100. */ + } *ApList; +} ScanResult; + +/** + * @brief Scan result using advanced scan. + */ +typedef struct _ScanResult_adv +{ + char ApNum; /**< The number of access points found in scanning.*/ + struct ApListStruct + { + char ssid[33]; /**< The SSID of an access point.*/ + char ApPower; /**< Signal strength, min:0, max:100*/ + uint8_t bssid[6]; /**< The BSSID of an access point.*/ + char channel; /**< The RF frequency, 1-13*/ + wlan_sec_type_t security; /**< Security type, @ref wlan_sec_type_t*/ + } *ApList; +} ScanResult_adv; + +/** + * @brief Input network paras, used in bk_wlan_start function. + */ +typedef struct _network_InitTypeDef_st +{ + char wifi_mode; /**< DHCP mode: @ref wlanInterfaceTypedef.*/ + char wifi_ssid[33]; /**< SSID of the wlan needs to be connected.*/ + char wifi_key[64]; /**< Security key of the wlan needs to be connected, ignored in an open system.*/ + char local_ip_addr[16]; /**< Static IP configuration, Local IP address. */ + char net_mask[16]; /**< Static IP configuration, Netmask. */ + char gateway_ip_addr[16]; /**< Static IP configuration, Router IP address. */ + char dns_server_ip_addr[16]; /**< Static IP configuration, DNS server IP address. */ + char dhcp_mode; /**< DHCP mode, @ref DHCP_Disable, @ref DHCP_Client and @ref DHCP_Server. */ + char reserved[32]; + int wifi_retry_interval; /**< Retry interval if an error is occured when connecting an access point, + time unit is millisecond. */ +} network_InitTypeDef_st; + +/** + * @brief Advanced precise wlan parameters, used in @ref network_InitTypeDef_adv_st. + */ +typedef struct +{ + char ssid[32]; /**< SSID of the wlan that needs to be connected. Example: "SSID String". */ + char bssid[6]; /**< BSSID of the wlan needs to be connected. Example: {0xC8 0x93 0x46 0x11 0x22 0x33}. */ + uint8_t channel; /**< Wlan's RF frequency, channel 0-13. 1-13 means a fixed channel + that can speed up a connection procedure, 0 is not a fixed input + means all channels are possible*/ + wlan_sec_type_t security; +} apinfo_adv_t; + +/** + * @brief Input network precise paras in bkWlanStartAdv function. + */ +typedef struct _network_InitTypeDef_adv_st +{ + apinfo_adv_t ap_info; /**< @ref apinfo_adv_t. */ + char key[64]; /**< Security key or PMK of the wlan. */ + int key_len; /**< The length of the key. */ + char local_ip_addr[16]; /**< Static IP configuration, Local IP address. */ + char net_mask[16]; /**< Static IP configuration, Netmask. */ + char gateway_ip_addr[16]; /**< Static IP configuration, Router IP address. */ + char dns_server_ip_addr[16]; /**< Static IP configuration, DNS server IP address. */ + char dhcp_mode; /**< DHCP mode, @ref DHCP_Disable, @ref DHCP_Client and @ref DHCP_Server. */ + char reserved[32]; + int wifi_retry_interval; /**< Retry interval if an error is occured when connecting an access point, + time unit is millisecond. */ +} network_InitTypeDef_adv_st; + +typedef struct _network_InitTypeDef_ap_st +{ + char wifi_ssid[32]; + char wifi_key[64]; + uint8_t channel; + wlan_sec_type_t security; + uint8_t ssid_hidden; + uint8_t max_con; + char local_ip_addr[16]; + char net_mask[16]; + char gateway_ip_addr[16]; + char dns_server_ip_addr[16]; + char dhcp_mode; + char reserved[32]; + int wifi_retry_interval; +} network_InitTypeDef_ap_st; + +/** + * @brief Current link status in station mode. + */ +typedef struct _linkStatus_t +{ + int conn_state; /**< The link to wlan is established or not, 0: disconnected, 1: connected. */ + int wifi_strength; /**< Signal strength of the current connected AP */ + uint8_t ssid[32]; /**< SSID of the current connected wlan */ + uint8_t bssid[6]; /**< BSSID of the current connected wlan */ + int channel; /**< Channel of the current connected wlan */ + wlan_sec_type_t security; +} LinkStatusTypeDef; + +/*WiFi Monitor */ +/* @brief define the monitor callback function. + * @param data: the 802.11 packet + * @param len: the length of this packet, include FCS + * @param rssi: the rssi of the received packet. + */ +typedef struct +{ + int8_t rssi; +}hal_wifi_link_info_t; + +//same with RL_BSSID_INFO_T{} +struct wlan_fast_connect_info +{ + uint8_t ssid[33]; + uint8_t bssid[6]; + uint8_t security; + uint8_t channel; + uint8_t psk[65]; + uint8_t pwd[65]; +}; + + +typedef struct vif_addcfg_st { + char *ssid; + char *key; + char *name; + u8 wlan_role; + u8 adv; +} VIF_ADDCFG_ST, *VIF_ADDCFG_PTR; + +typedef void (*monitor_data_cb_t)(uint8_t *data, int len, hal_wifi_link_info_t *info); +#endif + +/** + * @brief configure country info + * + * @attention 1. The default country is {.cc="CN", .schan=1, .nchan=13, policy=WIFI_COUNTRY_POLICY_AUTO} + * @attention 2. When the country policy is WIFI_COUNTRY_POLICY_AUTO, the country info of the AP to which + * the station is connected is used. E.g. if the configured country info is {.cc="USA", .schan=1, .nchan=11} + * and the country info of the AP to which the station is connected is {.cc="JP", .schan=1, .nchan=14} + * then the country info that will be used is {.cc="JP", .schan=1, .nchan=14}. If the station disconnected + * from the AP the country info is set back back to the country info of the station automatically, + * {.cc="USA", .schan=1, .nchan=11} in the example. + * @attention 3. When the country policy is WIFI_COUNTRY_POLICY_MANUAL, always use the configured country info. + * @attention 4. When the country info is changed because of configuration or because the station connects to a different + * external AP, the country IE in probe response/beacon of the soft-AP is changed also. + * @attention 5. The country configuration is not stored into flash + * @attention 6. This API doesn't validate the per-country rules, it's up to the user to fill in all fields according to + * local regulations. + * + * @param country the configured country info + * + * @return + * - kNoErr: succeed + * - kNotInitializedErr: WiFi is not initialized + * - kParamErr: invalid argument + */ +OSStatus bk_wlan_set_country(const wifi_country_t *country); + +/** + * @brief get the current country info + * + * @param country country info + * + * @return + * - kNoErr: succeed + * - kNotInitializedErr: WiFi is not initialized + * - kParamErr: invalid argument + */ +OSStatus bk_wlan_get_country(wifi_country_t *country); + +/** + * @brief set the max tx power + * + * @param max tx power + */ +void bk_wlan_set_max_txpwr(FP32 max_tx_pwr); + +/** @brief Connect or establish a Wi-Fi network in normal mode (station or soft ap mode). + * + * @detail This function can establish a Wi-Fi connection as a station or create + * a soft AP that other staions can connect (4 stations Max). In station mode, + * _BK_ first scan all of the supported Wi-Fi channels to find a wlan that + * matchs the input SSID, and read the security mode. Then try to connect + * to the target wlan. If any error occurs in the connection procedure or + * disconnected after a successful connection, _BK_ start the reconnection + * procedure in backgound after a time interval defined in inNetworkInitPara. + * Call this function twice when setup coexistence mode (staion + soft ap). + * This function retruns immediately in station mode, and the connection will + * be executed in background. + * + * @param inNetworkInitPara: Specifies wlan parameters. + * + * @return In station mode, allways retrurn kWlanNoErr. + * In soft ap mode, return kWlanXXXErr + */ +#if CFG_SUPPORT_ALIOS +OSStatus bk_wlan_start(hal_wifi_init_type_t* inNetworkInitPara); +#else +OSStatus bk_wlan_start(network_InitTypeDef_st* inNetworkInitPara); +#endif +/** @brief Connect to a Wi-Fi network with advantage settings (station mode only) + * + * @detail This function can connect to an access point with precise settings, + * that greatly speed up the connection if the input settings are correct + * and fixed. If this fast connection is failed for some reason, _BK_ + * change back to normal: scan + connect mode refer to @ref bkWlanStart. + * This function returns after the fast connection try. + * + * @note This function cannot establish a soft ap, use StartNetwork() for this + * purpose. + * If input SSID length is 0, _BK_ use BSSID to connect the target wlan. + * If both SSID and BSSID are all wrong, the connection will be failed. + * + * @param inNetworkInitParaAdv: Specifies the precise wlan parameters. + * + * @retrun Allways return kWlanNoErr although error occurs in first fast try + * kWlanTimeoutErr: DHCP client timeout + */ +#if CFG_SUPPORT_ALIOS +OSStatus bk_wlan_start_sta_adv(hal_wifi_init_type_adv_t* inNetworkInitParaAdv); +#else +OSStatus bk_wlan_start_sta_adv(network_InitTypeDef_adv_st* inNetworkInitParaAdv); +#endif +/** @brief Read current IP status on a network interface. + * + * @param outNetpara: Point to the buffer to store the IP address. + * @param inInterface: Specifies wlan interface. + * @arg Soft_AP: The soft AP that established by bkWlanStart() + * @arg Station: The interface that connected to an access point + * + * @return kNoErr : on success. + * @return kGeneralErr : if an error occurred + */ +#if CFG_SUPPORT_ALIOS +OSStatus bk_wlan_get_ip_status(hal_wifi_ip_stat_t *outNetpara, hal_wifi_type_t inInterface); +#else +OSStatus bk_wlan_get_ip_status(IPStatusTypedef *outNetpara, WiFi_Interface inInterface); +#endif +/** @brief Read current wireless link status on station interface. + * + * @param outStatus: Point to the buffer to store the link status. + * + * @return kNoErr : on success. + * @return kGeneralErr : if an error occurred + */ +#if CFG_SUPPORT_ALIOS +OSStatus bk_wlan_get_link_status(hal_wifi_link_stat_t *outStatus); +#else +OSStatus bk_wlan_get_link_status(LinkStatusTypeDef *outStatus); +#endif +/** @brief Start a wlan scanning in 2.4GHz in _BK_ backfround. + * + * @detail Once the scan is completed, _BK_ sends a notify: + * bk_notify_WIFI_SCAN_COMPLETED, with callback function: + * void (*function)(ScanResult *pApList, bk_Context_t * const inContext) + * Register callback function using @ref bk_add_notification() before scan. + */ +#if CFG_SUPPORT_ALIOS +void bk_wlan_start_scan(uint8_t adv); +#else +int bk_wlan_start_scan(void); +#endif +/** @brief Add the packet type which monitor should receive + * + * @detail This function can be called many times to receive different wifi packets. + */ +int bk_wlan_monitor_rx_type(int type); + +/** @brief Start wifi monitor mode + * + * @detail This function disconnect wifi station and softAP. + * + */ +int bk_wlan_start_monitor(void); + +/** @brief Stop wifi monitor mode + * + */ +int bk_wlan_stop_monitor(void); + +/** @brief Set the monitor channel + * + * @detail This function change the monitor channel (from 1~13). + * it can change the channel dynamically, don't need restart monitor mode. + */ +int bk_wlan_set_channel_sync(int channel); +int bk_wlan_set_channel(int channel); + +/** @brief Register the monitor callback function + * Once received a 802.11 packet call the registered function to return the packet. + */ +#if CFG_SUPPORT_ALIOS +OSStatus bk_wlan_start_sta(hal_wifi_init_type_t *inNetworkInitPara); +OSStatus bk_wlan_start_ap(hal_wifi_init_type_t *inNetworkInitPara); +OSStatus bk_wlan_set_ip_status(hal_wifi_ip_stat_t *inNetpara, hal_wifi_type_t inInterface); +#else +OSStatus bk_wlan_start_sta(network_InitTypeDef_st *inNetworkInitPara); +OSStatus bk_wlan_start_ap(network_InitTypeDef_st *inNetworkInitPara); +OSStatus bk_wlan_set_ip_status(IPStatusTypedef *inNetpara, WiFi_Interface inInterface); +OSStatus bk_wlan_start_ap_adv(network_InitTypeDef_ap_st *inNetworkInitParaAP); +void bk_wlan_ap_para_info_get(network_InitTypeDef_ap_st *ap_info); +#endif + +extern void bk_wlan_register_monitor_cb(monitor_data_cb_t fn); +extern monitor_data_cb_t bk_wlan_get_monitor_cb(void); +extern monitor_data_cb_t bk_wlan_get_bcn_cb(void); +extern void bk_wlan_enable_lsig(void); +extern void bk_wlan_disable_lsig(void); +extern int bk_wlan_is_monitor_mode(void); +extern void bk_wlan_set_ap_monitor_coexist(int val); +extern int bk_wlan_get_ap_monitor_coexist(); +extern uint32_t bk_sta_cipher_is_open(void); +extern uint32_t bk_sta_cipher_is_wep(void); +extern int bk_sta_cipher_type(void); +extern int bk_wlan_stop(char mode); +extern void bk_wlan_ap_set_channel_config(uint8_t channel); +extern uint8_t bk_wlan_ap_get_channel_config(void); +extern uint32_t bk_wlan_ap_get_frequency(void); +extern uint32_t bk_wlan_get_INT_status(void); +extern void bk_wlan_terminate_sta_rescan(void); +extern int is_apm_bss_config_empty(void); + +/** @brief Request deep sleep,and wakeup by gpio,rtc,or usb. + * + * @param first set PS_DEEP_CTRL_PARAM struct. + */ +extern void bk_enter_deep_sleep_mode ( PS_DEEP_CTRL_PARAM *deep_param ); + + +/** @brief Enable dtim power save,close rf,and wakeup by ieee dtim dynamical + * + */ +extern int bk_wlan_dtim_rf_ps_mode_enable(void ); + +/** @brief Request exit power save by ieee dtim + */ +int bk_wlan_dtim_rf_ps_mode_disable(void); + +/** @brief Send exit dtim dynamical ps mode msg + */ +int power_save_dtim_rf_ps_disable_send_msg(void); + + +/** @brief Open dtim with normal flag + */ +extern int bk_wlan_dtim_with_normal_open(void); +/** @brief Close dtim with normal flag + */ +extern int bk_wlan_dtim_with_normal_close(void); + +extern int bk_wlan_mcu_ps_mode_disable(void); +/** @brief When in dtim rf off mode,user can manual wakeup before dtim wakeup time. + */ +extern int bk_wlan_dtim_rf_ps_mode_do_wakeup(); +extern int bk_wlan_dtim_rf_ps_disable_send_msg(void); +extern int bk_wlan_dtim_rf_ps_set_linger_time(UINT32 ); + +extern int bk_wlan_mcu_suppress_and_sleep(UINT32); + + +extern void user_callback_register(void); +/** @brief Enable mcu power save,close mcu ,and wakeup by irq + * + */ +extern int bk_wlan_mcu_ps_mode_enable(void); + +extern int bk_wlan_mcu_ps_mode_disable(void); +enum +{ + RF_SLEEP = 0, + MCU_SLEEP, + LOW_SLEEP, + DEEP_PS, +} ; +#define PS_RF_SLEEP_BIT CO_BIT(RF_SLEEP) +#define PS_MCU_SLEEP_BIT CO_BIT(MCU_SLEEP) +#define PS_DEEP_SLEEP_BIT CO_BIT(DEEP_PS) +typedef UINT32 BK_PS_LEVEL; + +void bk_wlan_connection_loss(void); +int bk_wlan_start_assign_scan(UINT8 **ssid_ary, UINT8 ssid_num); + +void bk_wlan_scan_ap_reg_cb(FUNC_2PARAM_PTR ind_cb); +unsigned char bk_wlan_get_scan_ap_result_numbers(void); +void bk_wlan_get_scan_ap_result(SCAN_RST_ITEM_PTR scan_rst_table,unsigned char get_scanu_num); +void bk_wlan_ap_set_default_channel(uint8_t channel); +void bk_wlan_phy_open_cca(void); +void bk_wlan_phy_close_cca(void); +void bk_wlan_phy_show_cca(void); +extern void net_wlan_add_netif(void *mac); +extern void wpa_hostapd_release_scan_rst(void); + +#ifdef CONFIG_AOS_MESH +void wlan_register_mesh_monitor_cb(monitor_data_cb_t fn); +monitor_data_cb_t wlan_get_mesh_monitor_cb(void); +int wlan_is_mesh_monitor_mode(void); +int wlan_set_mesh_bssid(uint8_t *bssid); +uint8_t *wlan_get_mesh_bssid(void); +#endif +#if CFG_WPA_CTRL_IFACE +int wlan_sta_set(uint8_t *ssid, uint8_t ssid_len, uint8_t *psk); +int wlan_sta_set_config(wlan_sta_config_t *config); +int wlan_sta_get_config(wlan_sta_config_t *config); +int wlan_sta_set_autoconnect(int enable); +int wlan_sta_get_bss_size(uint32_t * size); +int wlan_sta_get_bss(wlan_sta_bss_info_t * bss_get); +int wlan_sta_set_bss(wlan_sta_bss_info_t * bss_set); +int wlan_sta_enable(void); +int wlan_sta_disable(void); +int wlan_sta_scan_once(void); +int wlan_sta_scan(wlan_sta_scan_param_t *param); +int wlan_sta_scan_result(ScanResult_adv *results); +int wlan_sta_scan_interval(int sec); +int wlan_sta_bss_max_count(uint8_t count); +int wlan_sta_bss_flush(int age); +int wlan_sta_connect(int chan); +int wlan_sta_disconnect(void); +int wlan_sta_state(wlan_sta_states_t *state); +int wlan_sta_ap_info(struct ApListStruct *ap); +int wlan_sta_gen_psk(wlan_gen_psk_param_t *param); +int wlan_ap_set(uint8_t *ssid, uint8_t ssid_len, uint8_t *psk); + +int wlan_ap_set_config(wlan_ap_config_t *config); +int wlan_ap_get_config(wlan_ap_config_t *config); +int wlan_ap_enable(void); +int wlan_ap_reload(void); +int wlan_ap_disable(void); +int wlan_ap_sta_num(int *num); +int wlan_ap_sta_info(wlan_ap_stas_t *stas); +int wlan_register_notifier(notify_func func, void *arg); +int wlan_unregister_notifier(notify_func func, void *arg); + +void wlan_read_fast_connect_info(struct wlan_fast_connect_info *fci); +void wlan_write_fast_connect_info(struct wlan_fast_connect_info *fci); +void wlan_clear_fast_connect_info(void); +#endif + + +uint32_t bk_wlan_reg_rx_mgmt_cb(mgmt_rx_cb_t cb, uint32_t rx_mgmt_flag); +uint32_t bk_wlan_start_ez_of_sta(void); +uint32_t bk_wlan_stop_ez_of_sta(void); +int bk_wlan_send_80211_raw_frame(uint8_t *buffer, int len); +int bk_wlan_send_raw_frame_with_cb(uint8_t *buffer, int len, void *cb, void *param); + +#if CFG_SUPPORT_ALIOS +/**********************for alios*******************************/ +static void scan_cb(void *ctxt, void *user); +static void scan_adv_cb(void *ctxt, void *user); +void bk_wifi_get_mac_address(char *mac); +void bk_wifi_set_mac_address(char *mac); +static void bk_monitor_callback(uint8_t *data, int len, hal_wifi_link_info_t *info); +void bk_wlan_register_mgnt_monitor_cb(monitor_data_cb_t fn); +monitor_data_cb_t bk_wlan_get_mgnt_monitor_cb(void); +int bk_wlan_suspend(void); +int bk_wlan_suspend_station(void); +int bk_wlan_suspend_softap(void); +uint32_t bk_wlan_max_power_level_get(void); +OSStatus bk_wlan_get_bssid_info(hal_wifi_ap_info_adv_t *ap, uint8_t **key, int *key_len); +#endif + +extern int bk_wlan_dtim_rf_ps_timer_pause(void); +extern int bk_wlan_dtim_rf_ps_timer_start(void); +extern int bk_wlan_dtim_rf_ps_mode_disable(void); +extern int bk_wlan_dtim_rf_ps_mode_enable(void ); +extern int wifi_set_mac_address(char *mac); +extern void wifi_get_mac_address(char *mac, u8 type); +extern int bk_wlan_get_channel(void); + +extern void bk_reboot(void); + +extern int bk_wlan_send_80211_beacon_frame(uint8_t channel, uint8_t *ssid, uint8_t ssid_len); + +#endif// _WLAN_UI_PUB_ + diff --git a/beken_os/beken378/func/joint_up/role_launch.c b/beken_os/beken378/func/joint_up/role_launch.c new file mode 100755 index 0000000..9a31c93 --- /dev/null +++ b/beken_os/beken378/func/joint_up/role_launch.c @@ -0,0 +1,1072 @@ +#include "include.h" +#include "sys_rtos.h" +#include "role_launch.h" +#include "mem_pub.h" +#include "str_pub.h" +#include "rtos_pub.h" +#include "rtos_error.h" +#include "wlan_ui_pub.h" +#include "ieee802_11_defs.h" + +#if RL_SUPPORT_FAST_CONNECT +#include "drv_model_pub.h" +#include "flash_pub.h" +#include "param_config.h" +#endif + +#if (FAST_CONNECT_INFO_ENC_METHOD != ENC_METHOD_NULL) +#include "soft_encrypt.h" +#endif + +#if CFG_ROLE_LAUNCH +RL_T g_role_launch = {{0}}; +RL_SOCKET_T g_rl_socket = {0}; +RL_SOCKET_CACHE_T g_sta_cache = {0}; + +extern u8* wpas_get_sta_psk(void); + +#if RL_SUPPORT_FAST_CONNECT +extern void user_connected_callback(FUNCPTR fn); +#endif + +#if (FAST_CONNECT_INFO_ENC_METHOD == ENC_METHOD_XOR) +void bssid_info_enc(RL_BSSID_INFO_PTR bssid_info) +{ + RL_BSSID_INFO_T tmp_out; + GLOBAL_INT_DECLARATION(); + + GLOBAL_INT_DISABLE(); + xor_enc(bssid_info, &tmp_out, sizeof(tmp_out)); + os_memcpy(bssid_info, &tmp_out, sizeof(tmp_out)); + GLOBAL_INT_RESTORE(); +} + +void bssid_info_dec(RL_BSSID_INFO_PTR bssid_info) +{ + RL_BSSID_INFO_T tmp_out; + GLOBAL_INT_DECLARATION(); + + GLOBAL_INT_DISABLE(); + xor_dec(bssid_info, &tmp_out, sizeof(tmp_out)); + os_memcpy(bssid_info, &tmp_out, sizeof(tmp_out)); + GLOBAL_INT_RESTORE(); +} +#elif (FAST_CONNECT_INFO_ENC_METHOD == ENC_METHOD_AES) +void bssid_info_enc(RL_BSSID_INFO_PTR bssid_info) +{ + RL_BSSID_INFO_T tmp_out; + weeny_aes_context ctx; + uint8_t iv[BK_AES_IV_LEN + 1]; + uint8_t private_key[BK_AES_KEY_LEN + 1]; + GLOBAL_INT_DECLARATION(); + + GLOBAL_INT_DISABLE(); + memcpy(iv, BK_TINY_AES_IV, strlen(BK_TINY_AES_IV)); + iv[sizeof(iv) - 1] = '\0'; + memcpy(private_key, BK_TINY_AES_KEY, strlen(BK_TINY_AES_KEY)); + private_key[sizeof(private_key) - 1] = '\0'; + + memset(&tmp_out, 0x0, sizeof(tmp_out)); + weeny_aes_setkey_enc(&ctx, (uint8_t *) private_key, 256); + weeny_aes_crypt_cbc(&ctx, AES_ENCRYPT, sizeof(tmp_out), iv, (unsigned char *)bssid_info, (unsigned char *)&tmp_out); + os_memcpy(bssid_info, &tmp_out, sizeof(tmp_out)); + GLOBAL_INT_RESTORE(); +} + +void bssid_info_dec(RL_BSSID_INFO_PTR bssid_info) +{ + RL_BSSID_INFO_T tmp_out; + weeny_aes_context ctx; + uint8_t iv[BK_AES_IV_LEN + 1]; + uint8_t private_key[BK_AES_KEY_LEN + 1]; + GLOBAL_INT_DECLARATION(); + + GLOBAL_INT_DISABLE(); + memcpy(iv, BK_TINY_AES_IV, strlen(BK_TINY_AES_IV)); + iv[sizeof(iv) - 1] = '\0'; + memcpy(private_key, BK_TINY_AES_KEY, strlen(BK_TINY_AES_KEY)); + private_key[sizeof(private_key) - 1] = '\0'; + + memset(&tmp_out, 0x0, sizeof(tmp_out)); + weeny_aes_setkey_dec(&ctx, (uint8_t *) private_key, 256); + weeny_aes_crypt_cbc(&ctx, AES_DECRYPT, sizeof(tmp_out), iv, (unsigned char *)bssid_info, (unsigned char *)&tmp_out); + os_memcpy(bssid_info, &tmp_out, sizeof(tmp_out)); + GLOBAL_INT_RESTORE(); +} +#endif + +#if RL_SUPPORT_FAST_CONNECT +#define BSSID_INFO_ADDR 0x1D1000 /*reserve 4k for bssid info*/ + +void rl_read_bssid_info(RL_BSSID_INFO_PTR bssid_info) +{ + UINT32 status, addr,ret; + DD_HANDLE flash_hdl; + + flash_hdl = ddev_open(FLASH_DEV_NAME,&status,0); + if(DD_HANDLE_UNVALID == flash_hdl) + { + os_null_printf("DD_HANDLE_UNVALID\r\n"); + return; + } + + addr = BSSID_INFO_ADDR; + ret = ddev_read(flash_hdl, (char *)bssid_info, sizeof(RL_BSSID_INFO_T), addr); + if(DRV_FAILURE == ret) + { + os_null_printf("DRV_FAILURE\r\n"); + } + +#if (FAST_CONNECT_INFO_ENC_METHOD != ENC_METHOD_NULL) + bssid_info_dec(bssid_info); +#endif + + ddev_close(flash_hdl); +} + +static void rl_write_bssid_info(void) +{ + int i; + uint8_t *psk; + UINT32 status; + uint32_t addr; + RL_BSSID_INFO_T bssid_info, pre_bssid; + LinkStatusTypeDef link_status; + uint8_t protect_flag, protect_param, temp[4]; + DD_HANDLE flash_hdl; + uint32_t ssid_len; + + os_memset(&link_status, 0, sizeof(link_status)); + bk_wlan_get_link_status(&link_status); + os_memset(&bssid_info, 0, sizeof(bssid_info)); + + ssid_len = os_strlen((const char*)link_status.ssid); + if(ssid_len > SSID_MAX_LEN) + { + ssid_len = SSID_MAX_LEN; + } + os_strncpy((char*)bssid_info.ssid, (char*)link_status.ssid, ssid_len); + os_memcpy(bssid_info.bssid, link_status.bssid, 6); + bssid_info.security = link_status.security; + bssid_info.channel = link_status.channel; + + psk = wpas_get_sta_psk(); + os_memset(temp, 0, sizeof(temp)); + for(i = 0; i < 32; i++) + { + sprintf((char*)temp, "%02x", psk[i]); + strcat((char*)bssid_info.psk, (char*)temp); + } + if (g_sta_param_ptr) + { + os_strcpy((char*)bssid_info.pwd, (char *)g_sta_param_ptr->orig_key); + } + + /*obtain the previous bssid-info*/ + rl_read_bssid_info(&pre_bssid); + + /*if different, save the latest information about fast connect*/ + if(0 == os_memcmp(&pre_bssid, &bssid_info, sizeof(bssid_info))) + { + bk_printf("same_bssid_info\r\n"); + goto wr_exit; + } + + flash_hdl = ddev_open(FLASH_DEV_NAME, &status, 0); + ddev_control(flash_hdl, CMD_FLASH_GET_PROTECT, &protect_flag); + protect_param = FLASH_PROTECT_NONE; + ddev_control(flash_hdl, CMD_FLASH_SET_PROTECT, (void *)&protect_param); + addr = BSSID_INFO_ADDR; + ddev_control(flash_hdl, CMD_FLASH_ERASE_SECTOR, (void *)&addr); + +#if (FAST_CONNECT_INFO_ENC_METHOD != ENC_METHOD_NULL) + bssid_info_enc(&bssid_info); +#endif + + ddev_write(flash_hdl, (char*)&bssid_info, sizeof(bssid_info), addr); + ddev_control(flash_hdl, CMD_FLASH_SET_PROTECT, (void *)&protect_flag); + ddev_close(flash_hdl); + +wr_exit: + return; +} + +static void rl_sta_fast_connect(RL_BSSID_INFO_PTR bssid_info) +{ + network_InitTypeDef_adv_st inNetworkInitParaAdv; + + os_memset(&inNetworkInitParaAdv, 0, sizeof(inNetworkInitParaAdv)); + + os_strcpy((char*)inNetworkInitParaAdv.ap_info.ssid, (char*)bssid_info->ssid); + os_memcpy(inNetworkInitParaAdv.ap_info.bssid, bssid_info->bssid, 6); + inNetworkInitParaAdv.ap_info.security = bssid_info->security; + inNetworkInitParaAdv.ap_info.channel = bssid_info->channel; + + if(bssid_info->security < SECURITY_TYPE_WPA_TKIP) + { + os_strcpy((char*)inNetworkInitParaAdv.key, (char*)bssid_info->pwd); + inNetworkInitParaAdv.key_len = os_strlen((char*)bssid_info->pwd); + } + else + { + os_strcpy((char*)inNetworkInitParaAdv.key, (char*)bssid_info->psk); + inNetworkInitParaAdv.key_len = os_strlen((char*)bssid_info->psk); + } + inNetworkInitParaAdv.dhcp_mode = DHCP_CLIENT; + + bk_wlan_start_sta_adv(&inNetworkInitParaAdv); +} + +void rl_clear_bssid_info(void) +{ + DD_HANDLE flash_hdl; + UINT32 status; + uint32_t addr; + uint8_t protect_flag, protect_param; + + /* clear fast connect flag when clear bssid info in flash */ + g_sta_param_ptr->fast_connect_set = 0; + flash_hdl = ddev_open(FLASH_DEV_NAME, &status, 0); + ddev_control(flash_hdl, CMD_FLASH_GET_PROTECT, &protect_flag); + protect_param = FLASH_PROTECT_NONE; + ddev_control(flash_hdl, CMD_FLASH_SET_PROTECT, (void *)&protect_param); + addr = BSSID_INFO_ADDR; + ddev_control(flash_hdl, CMD_FLASH_ERASE_SECTOR, (void *)&addr); + ddev_control(flash_hdl, CMD_FLASH_SET_PROTECT, (void *)&protect_flag); + ddev_close(flash_hdl); +} +#endif + +uint32_t rl_launch_sta(void) +{ + uint32_t next_launch_flag = 0; + RL_ENTITY_T *entity, *pre_entity; + uint32_t ret = LAUNCH_STATUS_OVER; + + if(NULL == g_role_launch.jl_previous_sta) + { + if(g_role_launch.jl_following_sta) + { + pre_entity = g_role_launch.jl_following_sta; + g_role_launch.jl_previous_sta = pre_entity; + g_role_launch.jl_following_sta = NULL; + + rl_sta_request_start(&pre_entity->rlaunch); + + ret = LAUNCH_STATUS_CONT; + } + } + else + { + if(g_role_launch.jl_following_sta) + { + entity = g_role_launch.jl_following_sta; + if(LAUNCH_TYPE_ASAP == entity->launch_type) + { + rl_pre_sta_set_cancel(); + } + } + + pre_entity = g_role_launch.jl_previous_sta; + if(pre_entity->relaunch_limit + && (pre_entity->launch_count >= pre_entity->relaunch_limit)) + { + rl_pre_sta_set_cancel(); + } + + next_launch_flag = rl_sta_may_next_launch(); + if(next_launch_flag) + { + rl_pre_sta_stop_launch(); + + pre_entity = g_role_launch.jl_previous_sta; + rl_free_entity(pre_entity); + + pre_entity = g_role_launch.jl_following_sta; + g_role_launch.jl_previous_sta = pre_entity; + g_role_launch.jl_following_sta = NULL; + + if(pre_entity) + { + rl_sta_request_start(&pre_entity->rlaunch); + + ret = LAUNCH_STATUS_CONT; + } + } + else + { + ret = LAUNCH_STATUS_CONT; + } + } + + return ret; +} + +uint32_t rl_launch_ap(void) +{ + uint32_t cancel_pre_flag = 0; + uint32_t next_launch_flag = 0; + RL_ENTITY_T *entity, *pre_entity; + uint32_t ret = LAUNCH_STATUS_OVER; + + if(NULL == g_role_launch.jl_previous_ap) + { + if(g_role_launch.jl_following_ap) + { + pre_entity = g_role_launch.jl_following_ap; + g_role_launch.jl_previous_ap = pre_entity; + g_role_launch.jl_following_ap = NULL; + + rl_pre_ap_init(); + rl_ap_request_start(&pre_entity->rlaunch); + + ret = LAUNCH_STATUS_CONT; + } + } + else + { + if(g_role_launch.jl_following_ap) + { + entity = g_role_launch.jl_following_ap; + if(LAUNCH_TYPE_ASAP == entity->launch_type) + { + cancel_pre_flag = 1; + rl_pre_ap_set_cancel(); + } + } + + pre_entity = g_role_launch.jl_previous_ap; + if(pre_entity->relaunch_limit + && (pre_entity->launch_count >= pre_entity->relaunch_limit)) + { + cancel_pre_flag = 1; + rl_pre_ap_set_cancel(); + } + + next_launch_flag = rl_ap_may_next_launch(cancel_pre_flag); + if(next_launch_flag) + { + rl_pre_ap_stop_launch(); + + pre_entity = g_role_launch.jl_previous_ap; + rl_free_entity(pre_entity); + + pre_entity = g_role_launch.jl_following_ap; + g_role_launch.jl_previous_ap = pre_entity; + g_role_launch.jl_following_ap = NULL; + + if(pre_entity) + { + rl_pre_ap_init(); + rl_ap_request_start(&pre_entity->rlaunch); + + ret = LAUNCH_STATUS_CONT; + } + } + else + { + ret = LAUNCH_STATUS_CONT; + } + } + + return ret; +} + +uint32_t rl_relaunch_chance(void) +{ + ASSERT(rtos_is_oneshot_timer_init(&g_role_launch.rl_timer)); + + rtos_oneshot_reload_timer(&g_role_launch.rl_timer); + + return 0; +} + +uint32_t rl_sta_req_is_null(void) +{ + uint32_t ret = 0; + GLOBAL_INT_DECLARATION(); + + GLOBAL_INT_DISABLE(); + if((0 == g_role_launch.jl_previous_sta) + && (0 == g_role_launch.jl_following_sta)) + { + ret = 1; + } + GLOBAL_INT_RESTORE(); + + return ret; +} + +uint32_t _sta_request_enter(LAUNCH_REQ *param, FUNC_1PARAM_PTR completion) +{ + uint32_t ret = 0; + RL_ENTITY_T *entity = 0; + GLOBAL_INT_DECLARATION(); + + GLOBAL_INT_DISABLE(); + if((0 == g_role_launch.jl_previous_ap) + && (0 == g_role_launch.jl_previous_sta)) + { + entity = rl_alloc_entity(param, completion); + + g_role_launch.jl_previous_sta = entity; + + JL_PRT("rl_sta_start\r\n"); + rl_sta_request_start(param); + + ret = 1; + } + else if(0 == g_role_launch.jl_following_sta) + { + entity = rl_alloc_entity(param, completion); + + g_role_launch.jl_following_sta = entity; + rl_start(); + ret = 2; + } + else + { + os_printf("cmd queue fill:%d vs %d\n", rl_pre_sta_get_status(), mhdr_get_station_status()); + rl_pre_sta_set_cancel(); + rl_start(); + } + + if(entity + && (PRE_ENTITY_IDLE == g_role_launch.pre_entity_type)) + { + g_role_launch.pre_entity_type = PRE_ENTITY_STA; + } + GLOBAL_INT_RESTORE(); + + return ret; +} + +uint32_t _ap_request_enter(LAUNCH_REQ *param, FUNC_1PARAM_PTR completion) +{ + uint32_t ret = 0; + RL_ENTITY_T *entity = 0; + GLOBAL_INT_DECLARATION(); + + GLOBAL_INT_DISABLE(); + if((0 == g_role_launch.jl_previous_ap) + && (0 == g_role_launch.jl_previous_sta)) + { + entity = rl_alloc_entity(param, completion); + + g_role_launch.jl_previous_ap = entity; + + JL_PRT("rl_ap_start\r\n"); + rl_ap_request_start(param); + + ret = 1; + } + else if(0 == g_role_launch.jl_following_ap) + { + entity = rl_alloc_entity(param, completion); + + g_role_launch.jl_following_ap = entity; + rl_start(); + + ret = 2; + } + else + { + os_printf("cmd queue fil2!\n"); + rl_start(); + } + + if(entity + && (PRE_ENTITY_IDLE == g_role_launch.pre_entity_type)) + { + g_role_launch.pre_entity_type = PRE_ENTITY_AP; + } + GLOBAL_INT_RESTORE(); + + return ret; +} + +void rl_enter_handler(void *left, void *right) +{ + uint8_t *ptr; + uint32_t ret; + LAUNCH_REQ *ap_param; + LAUNCH_REQ *sta_param; + uint32_t hit_ap, hit_sta; + FUNC_1PARAM_PTR ap_completion; + FUNC_1PARAM_PTR sta_completion; + + GLOBAL_INT_DECLARATION(); + + JL_PRT("rl_enter_handler\r\n"); + ptr = (uint8_t *)os_malloc(sizeof(*ap_param) + sizeof(*sta_param)); + if(0 == ptr) + { + return; + } + ap_param = (LAUNCH_REQ *)ptr; + sta_param = (LAUNCH_REQ *)&((LAUNCH_REQ *)ptr)[1]; + + GLOBAL_INT_DISABLE(); + ap_completion = g_rl_socket.ap_completion; + *ap_param = g_rl_socket.ap_param; + hit_ap = g_rl_socket.ap_req_flag; + + sta_completion = g_rl_socket.sta_completion; + *sta_param = g_rl_socket.sta_param; + hit_sta = g_rl_socket.sta_req_flag; + + os_memset(&g_rl_socket, 0, sizeof(g_rl_socket)); + GLOBAL_INT_RESTORE(); + + if(hit_sta) + { + JL_PRT("_sta_request_enter:0x%x :0x%x \r\n", g_role_launch.jl_previous_sta, g_role_launch.jl_following_sta); + ret = _sta_request_enter(sta_param, sta_completion); + if(ret) + { + g_sta_cache.sta_completion = sta_completion; + g_sta_cache.sta_param = *sta_param; + g_sta_cache.sta_req_flag = 1; + } + } + + if(hit_ap) + { + JL_PRT("_ap_request_enter\r\n"); + _ap_request_enter(ap_param, ap_completion); + } + + os_free(ptr); + ptr = 0; +} + +extern void mhdr_set_station_status_when_reconnect_over(void); +uint32_t rl_sta_cache_request_enter(void) +{ + uint32_t ret = 0; + GLOBAL_INT_DECLARATION(); + + JL_PRT("sta_cache_request\r\n"); + GLOBAL_INT_DISABLE(); + + do + { + if(g_sta_param_ptr->retry_cnt) + { + os_printf("g_sta_param_ptr->retry_cnt:%d\r\n", g_sta_param_ptr->retry_cnt); + g_sta_param_ptr->retry_cnt--; + } + else + { + mhdr_set_station_status_when_reconnect_over(); + + /* the opportunity of reconnecting is over*/ + break; + } + + if(g_sta_cache.sta_req_flag) + { + rl_sta_request_enter(&g_sta_cache.sta_param, g_sta_cache.sta_completion); + + ret = 1; + } + + os_memset(&g_sta_cache, 0, sizeof(g_sta_cache)); + }while(0); + + GLOBAL_INT_RESTORE(); + + return ret; +} + +void rl_launch_handler(void *left, void *right) +{ + uint32_t ap_ret = LAUNCH_STATUS_OVER; + uint32_t sta_ret = LAUNCH_STATUS_OVER; + + JL_PRT("rl_launch_handler\r\n"); + switch(g_role_launch.pre_entity_type) + { + case PRE_ENTITY_AP: + ap_ret = rl_launch_ap(); + if(LAUNCH_STATUS_OVER == ap_ret) + { + g_role_launch.pre_entity_type = PRE_ENTITY_STA; + + sta_ret = rl_launch_sta(); + } + break; + + case PRE_ENTITY_STA: + sta_ret = rl_launch_sta(); + if(LAUNCH_STATUS_OVER == sta_ret) + { + g_role_launch.pre_entity_type = PRE_ENTITY_AP; + + ap_ret = rl_launch_ap(); + } + break; + + case PRE_ENTITY_IDLE: + break; + + default: + break; + } + + if(!((LAUNCH_STATUS_OVER == sta_ret) + && (LAUNCH_STATUS_OVER == ap_ret))) + { + rl_relaunch_chance(); + } +} + +void rl_init(void) +{ + OSStatus err = kNoErr; + + JL_PRT("rl_init\r\n"); + err = rtos_init_oneshot_timer(&g_role_launch.rl_timer, + RL_LAUNCH_PERIOD, + (timer_2handler_t)rl_launch_handler, + NULL, + NULL); + ASSERT(kNoErr == err); + + err = rtos_init_oneshot_timer(&g_role_launch.enter_timer, + RL_ENTER_PERIOD, + (timer_2handler_t)rl_enter_handler, + NULL, + NULL); + ASSERT(kNoErr == err); + g_role_launch.rl_timer_flag = RL_TIMER_INIT; + +#if RL_SUPPORT_FAST_CONNECT + user_connected_callback(rl_write_bssid_info); +#endif +} + +void rl_uninit(void) +{ + OSStatus err = kNoErr; + + JL_PRT("rl_uninit\r\n"); + + if(RL_TIMER_START == g_role_launch.rl_timer_flag) + { + rl_stop(); + } + + err = rtos_deinit_oneshot_timer(&g_role_launch.rl_timer); + ASSERT(kNoErr == err); + + err = rtos_deinit_oneshot_timer(&g_role_launch.enter_timer); + ASSERT(kNoErr == err); + + g_role_launch.rl_timer_flag = RL_TIMER_UNINIT; +} + +void rl_start(void) +{ + OSStatus err = kNoErr; + + JL_PRT("rl_timer-stop\r\n"); + err = rtos_stop_oneshot_timer(&g_role_launch.rl_timer); + if(kNoErr != err) + { + JL_PRT("ERR:%d\r\n", err); + } + g_role_launch.rl_timer_flag = RL_TIMER_STOP; + + JL_PRT("rl_start_timer\r\n"); + err = rtos_start_oneshot_timer(&g_role_launch.rl_timer); + if(kNoErr != err) + { + JL_PRT("err:%d\r\n", err); + } + + ASSERT(kNoErr == err); + + g_role_launch.rl_timer_flag = RL_TIMER_START; +} + +void rl_stop(void) +{ + OSStatus err = kNoErr; + + err = rtos_stop_oneshot_timer(&g_role_launch.rl_timer); + ASSERT(kNoErr == err); + + JL_PRT("rl_stop\r\n"); + err = rtos_stop_oneshot_timer(&g_role_launch.enter_timer); + ASSERT(kNoErr == err); + + g_role_launch.rl_timer_flag = RL_TIMER_STOP; +} + +RL_ENTITY_T *rl_alloc_entity(LAUNCH_REQ *param, FUNC_1PARAM_PTR completion) +{ + RL_ENTITY_T *entity; + + entity = (RL_ENTITY_T *)os_zalloc(sizeof(RL_ENTITY_T)); + ASSERT(entity); + + entity->completion_cb = completion; + entity->launch_type = LAUNCH_TYPE_ASAP; + os_memcpy(&entity->rlaunch, param, sizeof(LAUNCH_REQ)); + + return entity; +} + +void rl_free_entity(RL_ENTITY_T *d) +{ + os_free(d); +} + +uint32_t rl_pre_sta_stop_launch(void) +{ + return 0; +} + +uint32_t rl_pre_ap_stop_launch(void) +{ + return 0; +} + +uint32_t rl_sta_may_next_launch(void) +{ + uint32_t yes = 0; + + if((RL_STATUS_STA_CSA_LAUNCHED_UNCERTAINTY != (rl_pre_sta_get_status() & RL_STATUS_OTHER_MASK)) + && ((rl_pre_sta_get_status() & RL_STATUS_CANCEL) + || (RL_STATUS_STA_LAUNCHED == rl_pre_sta_get_status()) + || (RL_STATUS_STA_LAUNCH_FAILED == rl_pre_sta_get_status()))) + { + yes = 1; + } + else if(g_role_launch.pre_sta_cancel + && ((RL_STATUS_STA_DHCPING == rl_pre_sta_get_status()) + || (RL_STATUS_STA_CONNECTING == rl_pre_sta_get_status()) + || (RL_STATUS_STA_SCAN_VAIN == rl_pre_sta_get_status()))) + { + yes = 2; + } + else + { + if(RL_STATUS_STA_LAUNCH_FAILED == rl_pre_sta_get_status()) + { + yes = 3; + } + } + if (yes) + { + os_printf("rl_sta_may_next_launch=%d\n", yes); + } + + return yes; +} + +uint32_t rl_ap_may_next_launch(uint32_t pre_cancel) +{ + uint32_t yes = 0; + + if(0 == pre_cancel) + { + yes = 1; + goto exit_check; + } + + if(((RL_STATUS_AP_TRANSMITTED_BCN + RL_STATUS_CANCEL) == rl_pre_ap_get_status()) + || (RL_STATUS_AP_LAUNCHED == (rl_pre_ap_get_status() & (~RL_STATUS_CANCEL)))) + { + yes = 1; + } + +exit_check: + return yes; +} + +uint32_t rl_pre_sta_get_status(void) +{ + return g_role_launch.pre_sta_status; +} + +uint32_t rl_pre_ap_get_status(void) +{ + return g_role_launch.pre_ap_status; +} + +uint32_t rl_pre_sta_set_status(uint32_t status) +{ + uint32_t cancel = 0; + GLOBAL_INT_DECLARATION(); + + GLOBAL_INT_DISABLE(); + if((RL_STATUS_STA_CHANNEL_SWITCHING == g_role_launch.pre_sta_status) + && (RL_STATUS_STA_LAUNCHED == status)) + { + g_role_launch.pre_sta_status = RL_STATUS_STA_CSA_LAUNCHED_UNCERTAINTY; + } + else if((RL_STATUS_STA_CSA_LAUNCHED_UNCERTAINTY == g_role_launch.pre_sta_status) + && (RL_STATUS_STA_CHANNEL_SWITCHED== status)) + { + g_role_launch.pre_sta_status = RL_STATUS_STA_LAUNCHED; + } + else + { + g_role_launch.pre_sta_status = status; + } + + cancel = g_role_launch.pre_sta_cancel; + if(cancel) + { + g_role_launch.pre_sta_status |= RL_STATUS_CANCEL; + } + GLOBAL_INT_RESTORE(); + + return cancel; +} + +uint32_t rl_pre_ap_disable_autobcn(void) +{ + if(g_role_launch.pre_ap_cancel) + { + mm_hw_ap_disable(); + } + + return g_role_launch.pre_ap_cancel; +} + +uint32_t rl_pre_ap_set_status(uint32_t status) +{ + uint32_t cancel = 0; + GLOBAL_INT_DECLARATION(); + + GLOBAL_INT_DISABLE(); + g_role_launch.pre_ap_status = status; + cancel = g_role_launch.pre_ap_cancel; + if(cancel) + { + g_role_launch.pre_ap_status += RL_STATUS_CANCEL; + } + + GLOBAL_INT_RESTORE(); + + return cancel; +} + +uint32_t rl_pre_sta_get_cancel(void) +{ + return g_role_launch.pre_sta_cancel; +} + +void rl_pre_sta_set_cancel(void) +{ + g_role_launch.pre_sta_cancel = 1; +} + +void rl_pre_sta_clear_cancel(void) +{ + g_role_launch.pre_sta_cancel = 0; +} + +uint32_t fl_get_pre_sta_cancel_status(void) +{ + return g_role_launch.pre_sta_cancel; +} + +void rl_pre_ap_set_cancel(void) +{ + g_role_launch.pre_ap_cancel = 1; +} + +void rl_pre_ap_clear_cancel(void) +{ + g_role_launch.pre_ap_cancel = 0; +} + +uint32_t fl_get_pre_ap_cancel_status(void) +{ + return g_role_launch.pre_ap_cancel; +} + +void rl_pre_ap_init(void) +{ + g_role_launch.pre_ap_cancel = 0; + g_role_launch.pre_ap_status = 0; +} + +void rl_pre_sta_init(void) +{ + g_role_launch.pre_sta_cancel = 0; + g_role_launch.pre_sta_status = 0; +} + +void rl_sta_request_start(LAUNCH_REQ *req) +{ + extern void demo_scan_app_init(void); +#if RL_SUPPORT_FAST_CONNECT + RL_BSSID_INFO_T bssid_info; + uint32_t ssid_len; +#endif + + ASSERT(req); + + switch(req->req_type) + { + case LAUNCH_REQ_STA: + rl_pre_sta_init(); + #if RL_SUPPORT_FAST_CONNECT + if (g_sta_param_ptr) + { + g_sta_param_ptr->orig_key_len = os_strlen(req->descr.wifi_key); + if (g_sta_param_ptr->orig_key_len >= sizeof(g_sta_param_ptr->orig_key)) + { + g_sta_param_ptr->orig_key_len = sizeof(g_sta_param_ptr->orig_key) - 1; + } + os_memcpy((uint8_t *)g_sta_param_ptr->orig_key, req->descr.wifi_key, g_sta_param_ptr->orig_key_len); + g_sta_param_ptr->orig_key[g_sta_param_ptr->orig_key_len] = '\0'; + } + rl_read_bssid_info(&bssid_info); + + uint32_t req_ssid_len = os_strlen((char*)req->descr.wifi_ssid); + ssid_len = os_strlen((char*)bssid_info.ssid); + + ssid_len = (req_ssid_len > ssid_len)? req_ssid_len : ssid_len; + if(ssid_len > SSID_MAX_LEN) + { + ssid_len = SSID_MAX_LEN; + } + if(os_memcmp(req->descr.wifi_ssid, bssid_info.ssid, ssid_len) == 0 + && os_strcmp((char*)req->descr.wifi_key, (char*)bssid_info.pwd) == 0) + { + bk_printf("fast_connect\r\n"); + if(rl_pre_sta_get_status() == RL_STATUS_STA_SCANNING) + { + os_printf("[wzl]It's scanning, terminate scan!\r\n"); + extern void scan_fast_terminate(void); + scan_fast_terminate(); + while(rl_pre_sta_get_status() == RL_STATUS_STA_SCANNING) + { + rtos_delay_milliseconds(20); + } + } + + rl_sta_fast_connect(&bssid_info); + } + else + { + k_printf("normal_connect\r\n"); + bk_wlan_start_sta(&req->descr); + } + #else + k_printf("normal_connect\r\n"); + bk_wlan_start_sta(&req->descr); + #endif + break; + + case LAUNCH_REQ_PURE_STA_SCAN: + rl_pre_sta_init(); + demo_scan_app_init(); + break; + + case LAUNCH_REQ_DELIF_STA: + bk_wlan_stop(STATION); + break; + + default: + break; + } +} + +void rl_ap_request_start(LAUNCH_REQ *req) +{ + ASSERT(req); + + switch(req->req_type) + { + case LAUNCH_REQ_AP: + rl_pre_ap_init(); + bk_wlan_start_ap(&req->descr); + break; + + case LAUNCH_REQ_DELIF_AP: + bk_wlan_stop(SOFT_AP); + break; + + default: + break; + } +} + +void rl_sta_request_enter(LAUNCH_REQ *param, FUNC_1PARAM_PTR completion) +{ + OSStatus err = kNoErr; + + GLOBAL_INT_DECLARATION(); + + JL_PRT("rl_sta_request_enter\r\n"); + GLOBAL_INT_DISABLE(); + g_rl_socket.sta_completion = completion; + g_rl_socket.sta_param = *param; + g_rl_socket.sta_req_flag = 1; + + JL_PRT("enter_timer-Sstop\r\n"); + err = rtos_stop_oneshot_timer(&g_role_launch.enter_timer); + if(kNoErr != err) + { + JL_PRT("enter_timer-Sstop:0x%x\r\n", err); + } + + JL_PRT("enter_timer-Sstart\r\n"); + err = rtos_start_oneshot_timer(&g_role_launch.enter_timer); + if(kNoErr != err) + { + JL_PRT("enter_timer-Sstart:0x%x\r\n", err); + } + + ASSERT(kNoErr == err); + GLOBAL_INT_RESTORE(); +} + +void rl_ap_request_enter(LAUNCH_REQ *param, FUNC_1PARAM_PTR completion) +{ + OSStatus err = kNoErr; + + GLOBAL_INT_DECLARATION(); + + JL_PRT("rl_ap_request_enter\r\n"); + + GLOBAL_INT_DISABLE(); + g_rl_socket.ap_completion = completion; + g_rl_socket.ap_param = *param; + g_rl_socket.ap_req_flag = 1; + + JL_PRT("enter_timer-Astop\r\n"); + rtos_stop_oneshot_timer(&g_role_launch.enter_timer); + + JL_PRT("enter_timer-Astart\r\n"); + err = rtos_start_oneshot_timer(&g_role_launch.enter_timer); + ASSERT(kNoErr == err); + GLOBAL_INT_RESTORE(); +} + +#else +uint32_t rl_pre_sta_set_status(uint32_t status) +{ + return 0; +} + +uint32_t rl_pre_ap_set_status(uint32_t status) +{ + return 0; +} + +uint32_t rl_pre_ap_disable_autobcn(void) +{ + return 0; +} +#endif // CFG_ROLE_LAUNCH + +// eof + diff --git a/beken_os/beken378/func/joint_up/role_launch.h b/beken_os/beken378/func/joint_up/role_launch.h new file mode 100755 index 0000000..3174ad2 --- /dev/null +++ b/beken_os/beken378/func/joint_up/role_launch.h @@ -0,0 +1,206 @@ +#ifndef _ROLE_LAUNCH_H_ +#define _ROLE_LAUNCH_H_ + +#include "wlan_ui_pub.h" + +#define JL_DEBUG 0 + +#if JL_DEBUG +#define JL_PRT os_printf +#define JL_WARN warning_prf +#define JL_FATAL fatal_prf +#else +#define JL_PRT null_prf +#define JL_WARN null_prf +#define JL_FATAL null_prf +#endif + +#define RL_LAUNCH_PERIOD 250 +#define RL_ENTER_PERIOD 150 + +#define RL_SUPPORT_FAST_CONNECT 1 + +typedef network_InitTypeDef_st LAUNCH_DESCR; + +enum +{ + LAUNCH_REQ_STA = 1, + LAUNCH_REQ_AP, + LAUNCH_REQ_PURE_STA_SCAN, + LAUNCH_REQ_DELIF_STA, + LAUNCH_REQ_DELIF_AP, + LAUNCH_REQ_MAX +}; + +typedef struct _launch_req_ +{ + LAUNCH_DESCR descr; + uint32_t req_type; +}LAUNCH_REQ, *LAUNCH_REQ_PTR; + +enum +{ + LAUNCH_TYPE_ASAP = 1, /*ASAP: as soon as possible*/ + LAUNCH_TYPE_RECONN +}; + +enum +{ + LAUNCH_STATUS_OVER = 0, + LAUNCH_STATUS_CONT +}; + +typedef struct _rl_socket_cache_ +{ + uint32_t sta_req_flag; + LAUNCH_REQ sta_param; + FUNC_1PARAM_PTR sta_completion; +}RL_SOCKET_CACHE_T; + +typedef struct _rl_socket_ +{ + uint32_t sta_req_flag; + LAUNCH_REQ sta_param; + FUNC_1PARAM_PTR sta_completion; + + uint32_t ap_req_flag; + LAUNCH_REQ ap_param; + FUNC_1PARAM_PTR ap_completion; +}RL_SOCKET_T; + +typedef struct _rlaunch_entity_ +{ + uint32_t launch_type; + + uint32_t relaunch_limit; + uint32_t launch_count; + + LAUNCH_REQ rlaunch; + FUNC_1PARAM_PTR completion_cb; +}RL_ENTITY_T, *RL_ENTITY_PTR; + +#if RL_SUPPORT_FAST_CONNECT +typedef struct _rl_bssid_info_ +{ + uint8_t ssid[33]; + uint8_t bssid[6]; + uint8_t security; + uint8_t channel; + uint8_t psk[65]; + uint8_t pwd[65]; + + #if (FAST_CONNECT_INFO_ENC_METHOD == ENC_METHOD_AES) + uint8_t padding[5]; /* aes attention: sizeof(RL_BSSID_INFO_T) = 16 *n*/ + #endif +}RL_BSSID_INFO_T, *RL_BSSID_INFO_PTR; +#endif + +#define RL_STATUS_CANCEL 0x8000 +#define RL_STATUS_CANCEL_MASK 0x8000 +#define RL_STATUS_OTHER_MASK 0x7FFF + +enum +{ + RL_STATUS_UNKNOWN = 0, + RL_STATUS_STA_INITING = 1, + RL_STATUS_STA_SCANNING = 2, + RL_STATUS_STA_SCAN_VAIN = 3, + RL_STATUS_STA_SCAN_OVER = 4, + RL_STATUS_STA_CONNECTING = 5, + RL_STATUS_STA_DHCPING = 6, + RL_STATUS_STA_CHANNEL_SWITCHING = 7, + RL_STATUS_STA_CHANNEL_SWITCHED = 8, + RL_STATUS_STA_CSA_LAUNCHED_UNCERTAINTY = 9, + RL_STATUS_STA_LAUNCHED = 0xa, + RL_STATUS_STA_LAUNCH_FAILED = 0xb, + RL_STATUS_STA_PS_SETTING = 0xc, + + RL_STATUS_AP_INITING = 0x11, + RL_STATUS_AP_UPDATING_BCN = 0x12, + RL_STATUS_AP_TRANSMITTING_BCN = 0x13, + RL_STATUS_AP_TRANSMITTED_BCN = 0x14, + RL_STATUS_AP_LAUNCHED +}; + +enum +{ + RL_TIMER_UNINIT = 0, + RL_TIMER_INIT, + RL_TIMER_START, + RL_TIMER_STOP +}; + +enum +{ + PRE_ENTITY_IDLE = 0, + PRE_ENTITY_STA, + PRE_ENTITY_AP, + PRE_ENTITY_MESH +}; + +typedef struct _role_launch_ +{ + beken2_timer_t enter_timer; + beken2_timer_t rl_timer; + uint32_t rl_timer_flag; + + uint32_t pre_entity_type; + uint32_t pre_sta_cancel; + uint32_t pre_sta_status; + uint32_t pre_ap_cancel; + uint32_t pre_ap_status; + + RL_ENTITY_T *jl_previous_sta; + RL_ENTITY_T *jl_following_sta; + + RL_ENTITY_T *jl_previous_ap; + RL_ENTITY_T *jl_following_ap; +}RL_T, *RL_PTR; + +/******************************************************************************* +* Function Declarations +*******************************************************************************/ +#if CFG_ROLE_LAUNCH +extern void rl_init(void); +extern void rl_uninit(void); +extern void rl_start(void); +extern void rl_stop(void); +extern void rl_pre_ap_init(void); +extern void rl_pre_sta_init(void); +extern uint32_t rl_launch_sta(void); +extern uint32_t rl_launch_ap(void); +extern uint32_t rl_relaunch_chance(void); +extern void rl_launch_handler(void *left, void *right); +extern void rl_free_entity(RL_ENTITY_T *d); +extern uint32_t rl_pre_sta_stop_launch(void); +extern uint32_t rl_pre_ap_stop_launch(void); +extern uint32_t rl_sta_may_next_launch(void); +extern uint32_t rl_ap_may_next_launch(uint32_t pre_cancel); +extern uint32_t rl_pre_sta_get_status(void); +extern uint32_t rl_pre_ap_get_status(void); +extern uint32_t rl_pre_sta_set_status(uint32_t status); +extern uint32_t rl_pre_ap_set_status(uint32_t status); +extern void rl_pre_sta_set_cancel(void); +extern uint32_t rl_pre_sta_get_cancel(void); +extern void rl_pre_sta_clear_cancel(void); +extern uint32_t fl_get_pre_sta_cancel_status(void); +extern void rl_pre_ap_set_cancel(void); +extern void rl_pre_ap_clear_cancel(void); +extern uint32_t rl_pre_ap_disable_autobcn(void); +extern uint32_t fl_get_pre_ap_cancel_status(void); +extern RL_ENTITY_T *rl_alloc_entity(LAUNCH_REQ *param, FUNC_1PARAM_PTR completion); +extern void rl_sta_request_start(LAUNCH_REQ *param); +extern void rl_ap_request_start(LAUNCH_REQ *param); +extern void rl_sta_request_enter(LAUNCH_REQ *param, FUNC_1PARAM_PTR completion); +extern void rl_ap_request_enter(LAUNCH_REQ *param, FUNC_1PARAM_PTR completion); +extern uint32_t rl_sta_cache_request_enter(void); +extern uint32_t rl_sta_req_is_null(void); +#endif + +#if RL_SUPPORT_FAST_CONNECT +extern void rl_read_bssid_info(RL_BSSID_INFO_PTR bssid_info); +extern void rl_clear_bssid_info(void); +#endif + +#endif //_ROLE_LAUNCH_H_ + diff --git a/beken_os/beken378/func/key/key_main.c b/beken_os/beken378/func/key/key_main.c new file mode 100755 index 0000000..c3abeda --- /dev/null +++ b/beken_os/beken378/func/key/key_main.c @@ -0,0 +1,100 @@ +#include "include.h" +#include "typedef.h" +#include "arm_arch.h" +#include "gpio_pub.h" +#include "key_main.h" +#include "multi_button.h" +#include "rtos_pub.h" + +beken_timer_t g_key_timer; + + +#if 1 +BUTTON_S button_test; + +void key_short_press(void *param) +{ + KEY_PRT("key_short_press\r\n"); +} + +void key_double_press(void *param) +{ + KEY_PRT("key_double_press\r\n"); +} + +void key_long_press_hold(void *param) +{ + KEY_PRT("key_long_press_hold\r\n"); +} +#endif + +void key_get_setting(void) +{ +} + +void key_configure(void) +{ + OSStatus result; + key_item_configure(); + + result = rtos_init_timer(&g_key_timer, + KEY_TMR_DURATION, + button_ticks, + (void *)0); + ASSERT(kNoErr == result); + + result = rtos_start_timer(&g_key_timer); + ASSERT(kNoErr == result); +} + +void key_unconfig(void) +{ + OSStatus ret; + + if(rtos_is_timer_init(&g_key_timer)) + { + if (rtos_is_timer_running(&g_key_timer)) + { + ret = rtos_stop_timer(&g_key_timer); + ASSERT(kNoErr == ret); + } + + ret = rtos_deinit_timer(&g_key_timer); + ASSERT(kNoErr == ret); + } +} + +uint8_t key_get_gpio_value(void) +{ + return bk_gpio_input(GPIO_TEST_ID); +} + +uint8_t key_gpio_init(void) +{ + bk_gpio_config_input_pup(GPIO_TEST_ID); +} + +void key_item_configure(void) +{ + key_gpio_init(); + button_init(&button_test, key_get_gpio_value, 0); + + button_attach(&button_test, SINGLE_CLICK, key_short_press); + button_attach(&button_test, DOUBLE_CLICK, key_double_press); + button_attach(&button_test, LONG_PRESS_HOLD, key_long_press_hold); + + button_start(&button_test); +} + +void key_initialization(void) +{ + key_configure(); +} + +void key_uninitialization(void) +{ + key_unconfig(); +} + +// eof + diff --git a/beken_os/beken378/func/key/key_main.h b/beken_os/beken378/func/key/key_main.h new file mode 100755 index 0000000..f265f36 --- /dev/null +++ b/beken_os/beken378/func/key/key_main.h @@ -0,0 +1,24 @@ +#ifndef _KEY_MAIN_H_ +#define _KEY_MAIN_H_ + +#include "gpio_pub.h" +#include "uart_pub.h" + +#define KEY_DEBUG + +#ifdef KEY_DEBUG +#define KEY_PRT os_printf +#define KEY_WPRT warning_prf +#else +#define KEY_PRT os_null_printf +#define KEY_WPRT os_null_printf +#endif + +#define GPIO_TEST_ID GPIO23 +#define KEY_TMR_DURATION 5 + +extern void key_get_setting(void); +extern void key_configure(void); +extern void key_item_configure(void); + +#endif // diff --git a/beken_os/beken378/func/key/multi_button.c b/beken_os/beken378/func/key/multi_button.c new file mode 100755 index 0000000..022243f --- /dev/null +++ b/beken_os/beken378/func/key/multi_button.c @@ -0,0 +1,199 @@ +#include "include.h" +#include "typedef.h" +#include "arm_arch.h" +#include "uart_pub.h" +#include "multi_button.h" + +#define EVENT_CB(ev) if(handle->cb[ev])handle->cb[ev]((BUTTON_S*)handle) + +//button handle list head. +static BUTTON_S* head_handle = NULL; + +/** + * @brief Initializes the button struct handle. + * @param handle: the button handle strcut. + * @param pin_level: read the HAL GPIO of the connet button level. + * @param active_level: pressed GPIO level. + * @retval None + */ +void button_init(BUTTON_S* handle, uint8_t(*pin_level)(), uint8_t active_level) +{ + memset(handle, sizeof(BUTTON_S), 0); + + handle->event = (uint8_t)NONE_PRESS; + handle->hal_button_Level = pin_level; + handle->button_level = handle->hal_button_Level(); + handle->active_level = active_level; +} + +/** + * @brief Attach the button event callback function. + * @param handle: the button handle strcut. + * @param event: trigger event type. + * @param cb: callback function. + * @retval None + */ +void button_attach(BUTTON_S* handle, PRESS_EVT event, btn_callback cb) +{ + handle->cb[event] = cb; +} + +/** + * @brief Inquire the button event happen. + * @param handle: the button handle strcut. + * @retval button event. + */ +PRESS_EVT button_get_event(BUTTON_S* handle) +{ + return (PRESS_EVT)(handle->event); +} + +/** + * @brief BUTTON_S driver core function, driver state machine. + * @param handle: the button handle strcut. + * @retval None + */ +void button_handler(BUTTON_S* handle) +{ + uint8_t read_gpio_level = handle->hal_button_Level(); + + //ticks counter working.. + if((handle->state) > 0) handle->ticks++; + + /*------------button debounce handle---------------*/ + if(read_gpio_level != handle->button_level) { //not equal to prev one + //continue read 3 times same new level change + if(++(handle->debounce_cnt) >= DEBOUNCE_TICKS) { + handle->button_level = read_gpio_level; + handle->debounce_cnt = 0; + } + } else { //leved not change ,counter reset. + handle->debounce_cnt = 0; + } + + /*-----------------State machine-------------------*/ + switch (handle->state) { + case 0: + if(handle->button_level == handle->active_level) { //start press down + handle->event = (uint8_t)PRESS_DOWN; + EVENT_CB(PRESS_DOWN); + handle->ticks = 0; + handle->repeat = 1; + handle->state = 1; + } else { + handle->event = (uint8_t)NONE_PRESS; + } + break; + + case 1: + if(handle->button_level != handle->active_level) { //released press up + handle->event = (uint8_t)PRESS_UP; + EVENT_CB(PRESS_UP); + handle->ticks = 0; + handle->state = 2; + + } else if(handle->ticks > LONG_TICKS) { + handle->event = (uint8_t)LONG_RRESS_START; + EVENT_CB(LONG_RRESS_START); + handle->state = 5; + } + break; + + case 2: + if(handle->button_level == handle->active_level) { //press down again + handle->event = (uint8_t)PRESS_DOWN; + EVENT_CB(PRESS_DOWN); + handle->repeat++; + if(handle->repeat == 2) { + EVENT_CB(DOUBLE_CLICK); // repeat hit + } + EVENT_CB(PRESS_REPEAT); // repeat hit + handle->ticks = 0; + handle->state = 3; + } else if(handle->ticks > SHORT_TICKS) { //released timeout + if(handle->repeat == 1) { + handle->event = (uint8_t)SINGLE_CLICK; + EVENT_CB(SINGLE_CLICK); + } else if(handle->repeat == 2) { + handle->event = (uint8_t)DOUBLE_CLICK; + } + handle->state = 0; + } + break; + + case 3: + if(handle->button_level != handle->active_level) { //released press up + handle->event = (uint8_t)PRESS_UP; + EVENT_CB(PRESS_UP); + if(handle->ticks < SHORT_TICKS) { + handle->ticks = 0; + handle->state = 2; //repeat press + } else { + handle->state = 0; + } + } + break; + + case 5: + if(handle->button_level == handle->active_level) { + //continue hold trigger + handle->event = (uint8_t)LONG_PRESS_HOLD; + EVENT_CB(LONG_PRESS_HOLD); + + } else { //releasd + handle->event = (uint8_t)PRESS_UP; + EVENT_CB(PRESS_UP); + handle->state = 0; //reset + } + break; + } +} + +/** + * @brief Start the button work, add the handle into work list. + * @param handle: target handle strcut. + * @retval 0: succeed. -1: already exist. + */ +int button_start(BUTTON_S* handle) +{ + BUTTON_S* target = head_handle; + while(target) { + if(target == handle) return -1; //already exist. + target = target->next; + } + handle->next = head_handle; + head_handle = handle; + return 0; +} + +/** + * @brief Stop the button work, remove the handle off work list. + * @param handle: target handle strcut. + * @retval None + */ +void button_stop(BUTTON_S* handle) +{ + BUTTON_S** curr; + + for(curr = &head_handle; *curr; ) { + BUTTON_S* entry = *curr; + if (entry == handle) { + *curr = entry->next; + } else + curr = &entry->next; + } +} + +/** + * @brief background ticks, timer repeat invoking interval 5ms. + * @param None. + * @retval None + */ +void button_ticks(void *param) +{ + BUTTON_S* target; + for(target=head_handle; target; target=target->next) { + button_handler(target); + } +} + diff --git a/beken_os/beken378/func/key/multi_button.h b/beken_os/beken378/func/key/multi_button.h new file mode 100755 index 0000000..ce695f4 --- /dev/null +++ b/beken_os/beken378/func/key/multi_button.h @@ -0,0 +1,57 @@ +#ifndef _MULTI_BUTTON_H_ +#define _MULTI_BUTTON_H_ + +#include "stdint.h" +#include "string.h" + +//According to your need to modify the constants. +#define TICKS_INTERVAL 5 //ms +#define DEBOUNCE_TICKS 3 //MAX 8 +#define SHORT_TICKS (300 /TICKS_INTERVAL) +#define LONG_TICKS (1000 /TICKS_INTERVAL) + + +typedef void (*btn_callback)(void*); + +typedef enum { + PRESS_DOWN = 0, + PRESS_UP, + PRESS_REPEAT, + SINGLE_CLICK, + DOUBLE_CLICK, + LONG_RRESS_START, + LONG_PRESS_HOLD, + number_of_event, + NONE_PRESS +}PRESS_EVT; + +typedef struct _button_ { + uint16_t ticks; + uint8_t repeat : 4; + uint8_t event : 4; + uint8_t state : 3; + uint8_t debounce_cnt : 3; + uint8_t active_level : 1; + uint8_t button_level : 1; + + uint8_t (*hal_button_Level)(void); + btn_callback cb[number_of_event]; + struct _button_ *next; +}BUTTON_S; + +#ifdef __cplusplus +extern "C" { +#endif + +void button_init(BUTTON_S* handle, uint8_t(*pin_level)(), uint8_t active_level); +void button_attach(BUTTON_S* handle, PRESS_EVT event, btn_callback cb); +PRESS_EVT button_get_event(BUTTON_S* handle); +int button_start(BUTTON_S* handle); +void button_stop(BUTTON_S* handle); +void button_ticks(void *param); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/beken_os/beken378/func/key_handle/key_handle.c b/beken_os/beken378/func/key_handle/key_handle.c new file mode 100755 index 0000000..905a606 --- /dev/null +++ b/beken_os/beken378/func/key_handle/key_handle.c @@ -0,0 +1,167 @@ +#include "key_handle.h" +#include "error.h" +#include "include.h" +#include "typedef.h" +#include "arm_arch.h" +#include "gpio_pub.h" +#include "uart_pub.h" +#include "music_msg_pub.h" + +#if(CONFIG_APP_MP3PLAYER == 1) +#define SD_DEBOUNCE_COUNT 50 +#define KEY_SCAN_INTERVAL_10MS 10 + +#if (CFG_SOC_NAME == SOC_BK7221U) +#define SD_CARD_DETECT_PIN 31 +#else +#define SD_CARD_DETECT_PIN 25 +#endif + +#define KEY_PLAY_PAUSE_PIN 28 + +#define SD_CARD_OFFLINE 0 +#define SD_CARD_ONLINE 1 + +#define KEY_SHORTUP_COUNTER 3 //30ms +#define KEY_LONG_COUNTER 80 //800ms +#define KEY_LONGUP_COUNTER 84 //840ms +#define KEY_HOLD_COUNTER 110 //1100ms + +static void key_scan_callback( void * arg ); +extern void bmsg_music_sender(void *arg); + +static UINT16 backup_keyval = MSG_NO_KEY; +static UINT16 keycount = 0; +static UINT16 sd_online = SD_CARD_OFFLINE; +static UINT16 detect_cnt = 0; +static beken_timer_t key_handle_timer = {0}; + + +void key_init(void) +{ + UINT32 param; + OSStatus err; + + param = GPIO_CFG_PARAM(SD_CARD_DETECT_PIN, GMODE_INPUT_PULLUP); + sddev_control(GPIO_DEV_NAME, CMD_GPIO_CFG, ¶m); + + param = GPIO_CFG_PARAM(KEY_PLAY_PAUSE_PIN, GMODE_INPUT_PULLUP); + sddev_control(GPIO_DEV_NAME, CMD_GPIO_CFG, ¶m); + + + err = rtos_init_timer(&key_handle_timer, + KEY_SCAN_INTERVAL_10MS, + key_scan_callback, + (void *)0); + ASSERT(kNoErr == err); + err = rtos_start_timer(&key_handle_timer); + ASSERT(kNoErr == err); + + KEY_PRT("==key init==\r\n"); +} + +uint8 sd_is_attached(void) +{ + return (sd_online); +} + +static void sd_detect_handle() +{ + UINT32 sd_pin_level; + UINT32 sd_detect_pin = SD_CARD_DETECT_PIN; + + sd_pin_level = sddev_control(GPIO_DEV_NAME, CMD_GPIO_INPUT, &sd_detect_pin); + UINT32 msg; + if(sd_pin_level) + { + if(sd_online == SD_CARD_ONLINE) + { + detect_cnt = 0; + sd_online = SD_CARD_OFFLINE; + msg = MSG_SD_DETACH; + //?detach??? + bmsg_music_sender((void*)msg); + } + } + else + { + if(sd_online == SD_CARD_OFFLINE) + { + if(detect_cnt < SD_DEBOUNCE_COUNT) + detect_cnt++; + else + { + sd_online = SD_CARD_ONLINE; + msg = MSG_SD_ATTACH; + //?attach??? + bmsg_music_sender((void*)msg); + } + } + } +} + +static UINT16 keyIOdetect(void) +{ + UINT16 key_pin_level; + UINT16 keyValue= MSG_NO_KEY;; + UINT32 key_detect_pin = KEY_PLAY_PAUSE_PIN; + + key_pin_level = sddev_control(GPIO_DEV_NAME, CMD_GPIO_INPUT, &key_detect_pin); + if(key_pin_level==0) + keyValue = MSG_KEY_PLAY; + + return keyValue; +} + + +static void key_detect_handle(void) +{ + UINT32 msg; + UINT16 keyval = keyIOdetect(); + + if(keyval == MSG_NO_KEY) + { + if(keycount >= KEY_SHORTUP_COUNTER) + { + if(keycount > KEY_LONG_COUNTER) + msg = KEY_LONG_UP|backup_keyval; + else + msg = backup_keyval; + bmsg_music_sender((void*)msg); + } + keycount = 0; + backup_keyval = MSG_NO_KEY; + } + else + { + if(keyval!=backup_keyval) + { + keycount = 0; + backup_keyval = keyval; + } + + keycount++; + + if((keycount == KEY_LONG_COUNTER)||(keycount == KEY_HOLD_COUNTER)) + { + if(keycount == KEY_LONG_COUNTER) + { + msg = KEY_LONG|keyval; + } + else + { + keycount = KEY_LONGUP_COUNTER; + msg = KEY_HOLD|keyval; + } + bmsg_music_sender((void*)msg); + } + } +} + + +static void key_scan_callback( void * arg ) +{ + sd_detect_handle(); + key_detect_handle(); +} +#endif diff --git a/beken_os/beken378/func/key_handle/key_handle.h b/beken_os/beken378/func/key_handle/key_handle.h new file mode 100755 index 0000000..fc4a4f7 --- /dev/null +++ b/beken_os/beken378/func/key_handle/key_handle.h @@ -0,0 +1,16 @@ +#ifndef _KEY_HANDLE_H_ +#define _KEY_HANDLE_H_ + +#include "sys_rtos.h" +#include "rtos_pub.h" + +#define KEY_DEBUG + +#ifdef KEY_DEBUG +#define KEY_PRT os_printf +#else +#define APP_PRT os_null_printf +#endif + + +#endif diff --git a/beken_os/beken378/func/libc/libc.h b/beken_os/beken378/func/libc/libc.h new file mode 100755 index 0000000..7207928 --- /dev/null +++ b/beken_os/beken378/func/libc/libc.h @@ -0,0 +1,319 @@ +/**************************************************************************** + * libs/libc/libc.h + * + * Copyright (C) 2007-2014, 2016-2017 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +#ifndef __LIBC_LIBC_H +#define __LIBC_LIBC_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +// #include + +#include +#include +#include +#include +#include +// #include + +// #include + +#define CONFIG_HAVE_LONG_LONG +// #define CONFIG_LIBC_FLOATINGPOINT +#define CONFIG_LIBC_SCANSET +#define CONFIG_STDIO_DISABLE_BUFFERING +#define FAR +#define CODE +#define IPTR +#define ERROR -1 + +#define DEBUGASSERT(...) do {} while(0) +#define linfo(...) do {} while(0) + +struct lib_instream_s; +typedef CODE int (*lib_getc_t)(FAR struct lib_instream_s *this); + +struct lib_instream_s +{ + lib_getc_t get; /* Get one character from the instream */ + int nget; /* Total number of characters gotten. Written + * by get method, readable by user */ +}; + +/* These are streams that operate on a fixed-sized block of memory */ + +struct lib_meminstream_s +{ + struct lib_instream_s public; + FAR const char *buffer; /* Address of first byte in the buffer */ + size_t buflen; /* Size of the buffer in bytes */ +}; + +/* Seek-able streams */ + +struct lib_sistream_s; +typedef CODE int (*lib_sigetc_t)(FAR struct lib_sistream_s *this); +typedef CODE off_t (*lib_siseek_t)(FAR struct lib_sistream_s *this, + off_t offset, int whence); + +struct lib_sostream_s; +typedef CODE void (*lib_soputc_t)(FAR struct lib_sostream_s *this, int ch); +typedef CODE int (*lib_soflush_t)(FAR struct lib_sostream_s *this); +typedef CODE off_t (*lib_soseek_t)(FAR struct lib_sostream_s *this, + off_t offset, int whence); + +struct lib_sistream_s +{ + lib_sigetc_t get; /* Get one character from the instream */ + lib_siseek_t seek; /* Seek to a position in the instream */ + int nget; /* Total number of characters gotten. Written + * by get method, readable by user */ +}; + +struct lib_memsistream_s +{ + struct lib_sistream_s public; + FAR const char *buffer; /* Address of first byte in the buffer */ + size_t offset; /* Current buffer offset in bytes */ + size_t buflen; /* Size of the buffer in bytes */ +}; + + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* This configuration directory is used in environment variable processing + * when we need to reference the user's home directory. There are no user + * directories in NuttX so, by default, this always refers to the root + * directory. + */ + +#ifndef CONFIG_LIB_HOMEDIR +# define CONFIG_LIB_HOMEDIR "/" +#endif + +/* If C std I/O buffering is not supported, then we don't need its semaphore + * protection. + */ + +#ifdef CONFIG_STDIO_DISABLE_BUFFERING +# define lib_sem_initialize(s) +# define lib_take_semaphore(s) +# define lib_give_semaphore(s) +#endif + +/* The NuttX C library an be build in two modes: (1) as a standard, C-library + * that can be used by normal, user-space applications, or (2) as a special, + * kernel-mode C-library only used within the OS. If NuttX is not being + * built as separated kernel- and user-space modules, then only the first + * mode is supported. + */ + +#if (defined(CONFIG_BUILD_PROTECTED) && defined(__KERNEL__)) || \ + defined(CONFIG_BUILD_KERNEL) +# include + +/* Domain-specific allocations */ + +# define lib_malloc(s) kmm_malloc(s) +# define lib_zalloc(s) kmm_zalloc(s) +# define lib_realloc(p,s) kmm_realloc(p,s) +# define lib_memalign(p,s) kmm_memalign(p,s) +# define lib_free(p) kmm_free(p) + +/* User-accessible allocations */ + +# define lib_umalloc(s) kumm_malloc(s) +# define lib_uzalloc(s) kumm_zalloc(s) +# define lib_urealloc(p,s) kumm_realloc(p,s) +# define lib_ufree(p) kumm_free(p) + +#else +# include + +/* Domain-specific allocations */ + +# define lib_malloc(s) malloc(s) +# define lib_zalloc(s) zalloc(s) +# define lib_realloc(p,s) realloc(p,s) +# define lib_free(p) free(p) + +/* User-accessible allocations */ + +# define lib_umalloc(s) malloc(s) +# define lib_uzalloc(s) zalloc(s) +# define lib_urealloc(p,s) realloc(p,s) +# define lib_ufree(p) free(p) + +#endif + +#define LIB_BUFLEN_UNKNOWN INT_MAX + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/**************************************************************************** + * Public Data + ****************************************************************************/ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + + /**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + + /* Defined in lib_streamsem.c */ + +#if CONFIG_NFILE_STREAMS > 0 + void stream_semtake(FAR struct streamlist *list); + void stream_semgive(FAR struct streamlist *list); +#endif + + /* Defined in lib_dtoa.c */ + +#ifdef CONFIG_LIBC_FLOATINGPOINT + char *__dtoa(double d, int mode, int ndigits, int *decpt, int *sign, + char **rve); +#endif + + /* Defined in lib_fopen.c */ + + int lib_mode2oflags(FAR const char *mode); + + /* Defined in lib_libfwrite.c */ + + ssize_t lib_fwrite(FAR const void *ptr, size_t count, FAR FILE *stream); + + /* Defined in lib_libfread.c */ + + ssize_t lib_fread(FAR void *ptr, size_t count, FAR FILE *stream); + + /* Defined in lib_libfgets.c */ + + FAR char *lib_fgets(FAR char *buf, size_t buflen, FILE *stream, + bool keepnl, bool consume); + + /* Defined in lib_libfflush.c */ + + ssize_t lib_fflush(FAR FILE *stream, bool bforce); + + /* Defined in lib_rdflush.c */ + + int lib_rdflush(FAR FILE *stream); + + /* Defined in lib_wrflush.c */ + + int lib_wrflush(FAR FILE *stream); + + /* Defined in lib_sem.c */ + +#ifndef CONFIG_STDIO_DISABLE_BUFFERING + void lib_sem_initialize(FAR struct file_struct *stream); + void lib_take_semaphore(FAR struct file_struct *stream); + void lib_give_semaphore(FAR struct file_struct *stream); +#endif + + /* Defined in lib_libgetbase.c */ + + int lib_getbase(const char *nptr, const char **endptr); + + /* Defined in lib_skipspace.c */ + + void lib_skipspace(const char **pptr); + + /* Defined in lib_isbasedigit.c */ + + bool lib_isbasedigit(int ch, int base, int *value); + + /* Defined in lib_checkbase.c */ + + int lib_checkbase(int base, const char **pptr); + + /* Defined in lib_expi.c */ + +#ifdef CONFIG_LIBM + float lib_expif(size_t n); + double lib_expi(size_t n); +#endif + + /* Defined in lib_libsqrtapprox.c */ + +#ifdef CONFIG_LIBM + float lib_sqrtapprox(float x); +#endif + + /* Defined in lib_parsehostfile.c */ + +#ifdef CONFIG_NETDB_HOSTFILE + struct hostent; + ssize_t lib_parse_hostfile(FAR FILE *stream, FAR struct hostent *host, + FAR char *buf, size_t buflen); +#endif + + + void lib_meminstream(FAR struct lib_meminstream_s *instream, + FAR const char *bufstart, int buflen); + + + /**************************************************************************** + * Name: lib_vscanf + * + * Description: + * Stream-oriented implementation that underlies scanf family: scanf, + * fscanf, vfscanf, sscanf, and vsscanf + * + ****************************************************************************/ + + int lib_vscanf(FAR struct lib_instream_s *obj, FAR int *lastc, + FAR const IPTR char *src, va_list ap); + + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __LIBC_LIBC_H */ + diff --git a/beken_os/beken378/func/libc/stdio/lib_libvscanf.c b/beken_os/beken378/func/libc/stdio/lib_libvscanf.c new file mode 100755 index 0000000..0bb2968 --- /dev/null +++ b/beken_os/beken378/func/libc/stdio/lib_libvscanf.c @@ -0,0 +1,1223 @@ +/**************************************************************************** + * libs/libc/stdio/lib_libsscanf.c + * + * Copyright (C) 2007, 2008, 2011-2014, 2016, 2019 Gregory Nutt. All + * rights reserved. + * Author: Gregory Nutt + * Johannes Schock + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +// #include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// #include +// #include + +#include "libc.h" + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/* CONFIG_LIBC_LONG_LONG is not a valid selection of the compiler does not + * support long long types. + */ + +#ifndef CONFIG_HAVE_LONG_LONG +# undef CONFIG_LIBC_LONG_LONG +#endif + +#define MAXLN 128 + +#define HH_MOD -2 +#define H_MOD -1 +#define NO_MOD 0 +#define L_MOD 1 +#define LL_MOD 2 + +#ifndef MIN +# define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#endif + +#ifndef MAX +# define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: findscanset + * + * Description: + * Fill in the given table from the scanset at the given format. + * Return a pointer to the character the closing ']'. + * The table has a 1 wherever characters should be considered part of the + * scanset. + * + * Function findscanset based on source function __sccl of FreeBSD + * (https://github.com/lattera/freebsd/blob/master/sys/kern/subr_scanf.c) + * + ****************************************************************************/ + +#ifdef CONFIG_LIBC_SCANSET +static FAR const char *findscanset(FAR const char *fmt, + FAR unsigned char set[32]) +{ + int c; + int n; + int v; + int i; + + fmt++; /* Skip '[' */ + + /* First `clear' the whole table */ + + c = *fmt++; /* First char hat => negated scanset */ + if (c == '^') + { + v = 1; /* Default => accept */ + c = *fmt++; /* Get new first char */ + } + else + { + v = 0; /* Default => reject */ + } + + memset(set, 0, 32); + if (c == 0) + { + goto doexit; + } + + /* Now set the entries corresponding to the actual scanset to the opposite + * of the above. The first character may be ']' (or '-') without being + * special; the last character may be '-'. + */ + + for (; ; ) + { + set[c / 8] |= (1 << (c % 8)); /* Take character c */ + +doswitch:n = *fmt++; /* Examine the next */ + switch (n) + { + case 0: /* Format ended too soon */ + case ']': /* End of scanset */ + goto doexit; + + case '-': + /* A scanset of the form [01+-] is defined as "the digit 0, the + * digit 1, the character +, the character -", but the effect of a + * scanset such as [a-zA-Z0-9] is implementation defined. The V7 + * Unix scanf treats "a-z" as "the letters a through z", but treats + * "a-a" as "the letter a, the character -, and the letter a". For + * compatibility, the `-' is not considerd to define a range if the + * character following it is either a close bracket (required by + * ANSI) or is not numerically greater than the character* we just + * stored in the table (c). + */ + + n = *fmt; + if (n == ']' || n < c) + { + c = '-'; + break; /* Resume the for (; ; ) */ + } + + fmt++; + do + { + /* Fill in the range */ + + c++; + set[c / 8] |= (1 << (c % 8)); /* Take character c */ + } + while (c < n); + + /* Alas, the V7 Unix scanf also treats formats such as [a-c-e] as + * "the letters a through e". This too is permitted by the + * standard. + */ + + goto doswitch; + + default: /* Just another character */ + c = n; + break; + } + } + +doexit: + if (v) /* Default => accept */ + { + for (i = 0; i < 32; i++) /* Invert all */ + { + set[i] ^= 0xff; + } + } + + return (fmt - 1); +} +#endif + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lib_vscanf + * + * Description: + * Stream-oriented implementation that underlies scanf family: scanf, + * fscanf, vfscanf, sscanf, and vsscanf + * + ****************************************************************************/ + +int lib_vscanf(FAR struct lib_instream_s *obj, FAR int *lastc, + FAR const IPTR char *fmt, va_list ap) +{ + int c; + FAR char *tv; + FAR const char *tc; + int modifier; + bool noassign; + bool conv; + int assigncount; + int count; + int ngetstart; + int width; + int fwidth; + int base = 10; + char tmp[MAXLN]; + +#ifdef CONFIG_LIBC_LONG_LONG + FAR unsigned long long *plonglong = NULL; +#endif + FAR unsigned long *plong = NULL; + FAR unsigned int *pint = NULL; + FAR unsigned short *pshort = NULL; + FAR unsigned char *pchar = NULL; + +#ifdef CONFIG_LIBC_SCANSET + unsigned char set[32]; /* Bit field (256 / 8) */ +#endif + + /* keep this for future reference linfo("buf=\"%s\" fmt=\"%s\"\n", buf, fmt); */ + + /* Parse the format, extracting values from the input buffer as needed */ + + assigncount = 0; + count = 0; + width = 0; + conv = false; + noassign = false; + modifier = NO_MOD; + ngetstart = obj->nget; /* for %n calculations */ + + /* Make sure lastc is not NULL. */ + + if (lastc == NULL) + { + lastc = &c; + } + + /* Loop until all characters in the fmt string have been processed. We may + * have to continue loop after reaching the end the input data in order to + * handle trailing %n format specifiers. + */ + + /* Get first character, we keep always the next character in c */ + + c = obj->get(obj); + + while (*fmt) + { + /* Skip over white spaces */ + + if (isspace((unsigned char)*fmt)) + { + while (isspace(c)) + { + c = obj->get(obj); + } + } + + while (isspace((unsigned char)*fmt)) + { + fmt++; + } + + /* Check for a conversion specifier */ + + if (*fmt == '%') + { + //linfo("Specifier found\n"); + + /* Check for qualifiers on the conversion specifier */ + + fmt++; + for (; *fmt; fmt++) + { + //linfo("Processing %c\n", *fmt); + +#ifdef CONFIG_LIBC_SCANSET + if (strchr("dibouxXcseEfFgGaAn[%", *fmt)) +#else + if (strchr("dibouxXcseEfFgGaAn%", *fmt)) +#endif + { + if (*fmt != '%') + { + conv = true; + } + break; + } + + if (*fmt == '*') + { + noassign = true; + } + else if (*fmt == 'l' || *fmt == 'L') + { + modifier = L_MOD; + + if (*(fmt + 1) == 'l' || *(fmt + 1) == 'L') + { + modifier = LL_MOD; + fmt++; + } + } + else if (*fmt == 'h' || *fmt == 'H') + { + modifier = H_MOD; + + if (*(fmt + 1) == 'h' || *(fmt + 1) == 'H') + { + modifier = HH_MOD; + fmt++; + } + } + else if (*fmt >= '1' && *fmt <= '9') + { + for (tc = fmt; isdigit((unsigned char)*fmt); fmt++) + ; + strncpy(tmp, tc, fmt - tc); + tmp[fmt - tc] = '\0'; + width = atoi(tmp); + fmt--; + } + } + + /* Process %s: String conversion */ + + if (*fmt == 's') + { + //linfo("Performing string conversion\n"); + + /* Get a pointer to the char * value. We need to do this even + * of we have reached the end of the input data in order to + * update the 'ap' variable. + */ + + tv = NULL; /* To avoid warnings about begin uninitialized */ + if (!noassign) + { + tv = va_arg(ap, FAR char *); + tv[0] = '\0'; + } + + /* Skip over white space */ + + while (isspace(c)) + { + c = obj->get(obj); + } + + /* But we only perform the data conversion is we still have + * bytes remaining in the input data stream. + */ + + if (c > 0) + { + /* Use the actual field's width if 1) no fieldwidth + * specified or 2) the actual field's width is smaller + * than fieldwidth specified. + */ + + fwidth = 0; + while ((!width || (fwidth < width)) && (c > 0) && + !isspace(c)) + { + if (!noassign) + { + tv[fwidth] = c; + } + + fwidth++; + c = obj->get(obj); + } + + if (!noassign) + { + tv[fwidth] = '\0'; + assigncount++; + } + + count++; + } + } + +#ifdef CONFIG_LIBC_SCANSET + /* Process %[: Scanset conversion */ + + if (*fmt == '[') + { + linfo("Performing scanset conversion\n"); + + fmt = findscanset(fmt, set); /* find scanset */ + + /* Get a pointer to the char * value. We need to do this even + * if we have reached the end of the input data in order to + * update the 'ap' variable. + */ + + tv = NULL; /* To avoid warnings about begin uninitialized */ + if (!noassign) + { + tv = va_arg(ap, FAR char *); + tv[0] = '\0'; + } + + /* But we only perform the data conversion is we still have + * bytes remaining in the input data stream. + */ + + if (c > 0) + { + + /* Use the actual field's width if 1) no fieldwidth + * specified or 2) the actual field's width is smaller + * than the fieldwidth specified. + */ + + fwidth = 0; + while ((!width || (fwidth < width)) && (c > 0) + && ((set[c / 8] & (1 << (c % 8))) != 0)) + { + if (!noassign) + { + tv[fwidth] = c; + } + + fwidth++; + c = obj->get(obj); + } + + if (!fwidth) + { + *lastc = c; + return assigncount; + } + + if (!noassign) + { + tv[fwidth] = '\0'; + assigncount++; + } + + count++; + } + } +#endif + + /* Process %c: Character conversion */ + + else if (*fmt == 'c') + { + linfo("Performing character conversion\n"); + + /* Get a pointer to the char * value. We need to do this even + * if we have reached the end of the input data in order to + * update the 'ap' variable. + */ + + tv = NULL; /* To avoid warnings about being uninitialized */ + if (!noassign) + { + tv = va_arg(ap, FAR char *); + tv[0] = '\0'; + } + + /* But we only perform the data conversion is we still have + * bytes remaining in the input data stream. + */ + + if (c > 0) + { + /* Was a field width specified? */ + + if (!width) + { + /* No, then width is this one single character */ + + width = 1; + } + + /* Copy the character(s) (if we are making an assignment) */ + + fwidth = 0; + while ((fwidth < width) && c > 0) + { + if (!noassign) + { + tv[fwidth] = c; + } + + fwidth++; + c = obj->get(obj); + } + + if (fwidth != width) + { + *lastc = c; + return assigncount; + } + + if (!noassign) + { + assigncount++; + } + + count++; + } + } + + /* Process %d, %o, %b, %x, %u: Various integer conversions */ + + else if (strchr("dobxXui", *fmt)) + { + bool sign; + + linfo("Performing integer conversion\n"); + + /* Get a pointer to the integer value. We need to do this even + * if we have reached the end of the input data in order to + * update the 'ap' variable. + */ + + if (!noassign) + { + /* We have to check whether we need to return a long or an + * int. + */ + + switch (modifier) + { + case HH_MOD: + pchar = va_arg(ap, FAR unsigned char *); + *pchar = 0; + break; + + case H_MOD: + pshort = va_arg(ap, FAR unsigned short *); + *pshort = 0; + break; + + case NO_MOD: + pint = va_arg(ap, FAR unsigned int *); + *pint = 0; + break; + + default: + case L_MOD: + plong = va_arg(ap, FAR unsigned long *); + *plong = 0; + break; + +#ifdef CONFIG_LIBC_LONG_LONG + case LL_MOD: + plonglong = va_arg(ap, FAR unsigned long long *); + *plonglong = 0; + break; +#endif + } + } + + /* Skip over any white space before the integer string */ + + while (isspace(c)) + { + c = obj->get(obj); + } + + /* But we only perform the data conversion if we still have + * bytes remaining in the input data stream. + */ + + if (c > 0) + { + FAR char *endptr; + int prefix; + bool stopconv; + //int errsave; + unsigned long tmplong = 0; +#ifdef CONFIG_LIBC_LONG_LONG + unsigned long long tmplonglong = 0; +#endif + /* Copy the real string into a temporary working buffer. */ + + if (!width || width > sizeof(tmp) - 1) + { + width = sizeof(tmp) - 1; + } + + /* The base of the integer conversion depends on the + * specific conversion specification. + */ + + fwidth = 0; + prefix = 0; + stopconv = false; + sign = false; + + switch (*fmt) + { + default: + case 'd': + sign = true; + + /* FALLTHROUGH */ + + case 'u': + while (fwidth < width && !stopconv) + { + if (c == '-' || c == '+') + { + if (fwidth != 0) + { + stopconv = true; + } + } + else if (!(c >= '0' && c <= '9')) + { + stopconv = true; + } + + if (!stopconv) + { + tmp[fwidth++] = c; + c = obj->get(obj); + } + } + + base = 10; + break; + + case 'x': + case 'X': + while (fwidth < width && !stopconv) + { + if (c == '-' || c == '+') + { + if (fwidth != 0) + { + stopconv = true; + } + } + else if (c == '0') + { + if (prefix == 0) + { + prefix = 1; + } + } + else if (c == 'x' || c == 'X') + { + if (prefix == 1) + { + prefix = 2; + } + else + { + stopconv = true; + } + } + else if (!((c >= '0' && c <= '9') || + (c >= 'a' && c <= 'f') || + (c >= 'A' && c <= 'F'))) + { + stopconv = true; + } + else + { + prefix = 2; + } + + if (!stopconv) + { + tmp[fwidth++] = c; + c = obj->get(obj); + } + } + + base = 16; + break; + + case 'o': + while (fwidth < width && !stopconv) + { + if (c == '-' || c == '+') + { + if (fwidth != 0) + { + stopconv = true; + } + } + else if (!(c >= '0' && c <= '7')) + { + stopconv = true; + } + + if (!stopconv) + { + tmp[fwidth++] = c; + c = obj->get(obj); + } + } + + base = 8; + break; + + case 'b': /* not official? */ + while (fwidth < width && !stopconv) + { + if (c == '-' || c == '+') + { + if (fwidth != 0) + { + stopconv = true; + } + } + else if (!(c >= '0' && c <= '1')) + { + stopconv = true; + } + + if (!stopconv) + { + tmp[fwidth++] = c; + c = obj->get(obj); + } + } + + base = 2; + break; + + case 'i': + sign = true; + base = 10; + + while (fwidth < width && !stopconv) + { + if (c == '-' || c == '+') + { + if (fwidth != 0) + { + stopconv = true; + } + } + else if (c == '0') + { + if (prefix == 0) + { + prefix = 1; + base = 8; + } + } + else if (c == 'x' || c == 'X') + { + if (prefix == 1) + { + prefix = 2; + base = 16; + } + else + { + stopconv = true; + } + } + else if (!((c >= '0' && c <= '7' && base >= 8) || + (c >= '8' && c <= '9' && base >= 10) || + (c >= 'a' && c <= 'f' && base == 16) || + (c >= 'A' && c <= 'F' && base == 16))) + { + stopconv = true; + } + else + { + prefix = 2; + } + + if (!stopconv) + { + tmp[fwidth++] = c; + c = obj->get(obj); + } + } + break; + } + + tmp[fwidth] = 0; + + //linfo("tmp[]=\"%s\"\n", tmp); + + /* Perform the integer conversion */ + /* Preserve the errno value */ + + //errsave = get_errno(); + //set_errno(0); + + switch (modifier) + { +#ifndef CONFIG_LIBC_LONG_LONG + case LL_MOD: +#endif + case HH_MOD: + case H_MOD: + case NO_MOD: + default: + if (sign) + { + tmplong = strtol(tmp, &endptr, base); + } + else + { + tmplong = strtoul(tmp, &endptr, base); + } + break; + +#ifdef CONFIG_LIBC_LONG_LONG + case LL_MOD: + if (sign) + { + tmplonglong = strtoll(tmp, &endptr, base); + } + else + { + tmplonglong = strtoull(tmp, &endptr, base); + } + break; +#endif + } + + /* Check if the number was successfully converted */ + + if (tmp == endptr /* || get_errno() == ERANGE */) + { + *lastc = c; + return assigncount; + } + + //set_errno(errsave); + if (!noassign) + { + /* We have to check whether we need to return a long or + * an int. + */ + + switch (modifier) + { + case HH_MOD: + linfo("Return %ld to 0x%p\n", tmplong, pchar); + *pchar = (unsigned char)tmplong; + break; + + case H_MOD: + linfo("Return %ld to 0x%p\n", tmplong, pshort); + *pshort = (unsigned short)tmplong; + break; + + case NO_MOD: + linfo("Return %ld to 0x%p\n", tmplong, pint); + *pint = (unsigned int)tmplong; + break; + +#ifndef CONFIG_LIBC_LONG_LONG + case L_MOD: +#endif + default: + linfo("Return %ld to 0x%p\n", tmplong, plong); + *plong = tmplong; + break; + +#ifdef CONFIG_LIBC_LONG_LONG + case LL_MOD: + linfo("Return %lld to 0x%p\n", tmplonglong, + plonglong); + *plonglong = tmplonglong; + break; +#endif + } + + assigncount++; + } + + count++; + } + } + + /* Process %a, %A, %f, %F, %e, %E, %g, and %G: Floating point + * conversions. + */ + + else if (strchr("aAfFeEgG", *fmt) != NULL) + { +#ifdef CONFIG_HAVE_DOUBLE + FAR double_t *pd = NULL; +#endif + FAR float *pf = NULL; + + linfo("Performing floating point conversion\n"); + + /* Get a pointer to the double value. We need to do this even + * if we have reached the end of the input data in order to + * upate the 'ap' variable. + */ + + if (!noassign) + { + /* We have to check whether we need to return a float or a + * double. + */ + +#ifdef CONFIG_HAVE_DOUBLE + if (modifier >= L_MOD) + { + pd = va_arg(ap, FAR double_t *); + *pd = 0.0; + } + else +#endif + { + pf = va_arg(ap, FAR float *); + *pf = 0.0; + } + } + +#ifdef CONFIG_LIBC_FLOATINGPOINT + + /* Skip over any white space before the real string */ + + while (isspace(c)) + { + c = obj->get(obj); + } + + /* But we only perform the data conversion is we still have + * bytes remaining in the input data stream. + */ + + if (c > 0) + { + FAR char *endptr; + bool expnt; + bool dot; + bool sign; + bool stopconv; + int errsave; +# ifdef CONFIG_HAVE_DOUBLE + double_t dvalue; +# endif + float fvalue; + + /* Was a fieldwidth specified? */ + + if (!width || width > sizeof(tmp) - 1) + { + width = sizeof(tmp) - 1; + } + + /* Copy the real string into a temporary working buffer. */ + + fwidth = 0; + expnt = false; + sign = false; + dot = false; + stopconv = false; + + while (fwidth < width && !stopconv) + { + if (c == '-' || c == '+') + { + if (!sign) + { + sign = true; + } + else + { + stopconv = true; + } + } + else if (c == '.') + { + if (!dot) + { + dot = true; + sign = true; + } + else + { + stopconv = true; + } + } + else if (c == 'e' || c == 'E') + { + if (!expnt) + { + expnt = true; + sign = false; + } + else + { + stopconv = true; + } + } + else if (!(c >= '0' && c <= '9')) + { + stopconv = true; + } + else + { + sign = true; + } + + if (!stopconv) + { + tmp[fwidth++] = c; + c = obj->get(obj); + } + } + + tmp[fwidth] = 0; + + linfo("tmp[]=\"%s\"\n", tmp); + + /* Perform the floating point conversion */ + /* Preserve the errno value */ + + errsave = get_errno(); + set_errno(0); + +# ifdef CONFIG_HAVE_DOUBLE + if (modifier >= L_MOD) + { + /* Get the converted double_t value */ + + dvalue = strtod(tmp, &endptr); + } + else +# endif + { + fvalue = strtof(tmp, &endptr); + } + + /* Check if the number was successfully converted */ + + if (tmp == endptr || get_errno() == ERANGE) + { + *lastc = c; + return assigncount; + } + + set_errno(errsave); + + if (!noassign) + { + + /* We have to check whether we need to return a float or + * a double_t. + */ + +# ifdef CONFIG_HAVE_DOUBLE + if (modifier >= L_MOD) + { + /* Return the double_t value */ + + linfo("Return %f to %p\n", dvalue, pd); + *pd = dvalue; + } + else +# endif + { + /* Return the float value */ + + linfo("Return %f to %p\n", (double_t)fvalue, pf); + *pf = fvalue; + } + + assigncount++; + } + count++; + + } +#endif + } + + /* Process %n: Character count */ + + else if (*fmt == 'n') + { + linfo("Performing character count\n"); + + if (!noassign) + { + size_t nchars = (size_t) (obj->nget - ngetstart); + + if (c != EOF) + { + /* One more character already read */ + + nchars--; + } + + /* Note %n does not count as a conversion */ + + switch (modifier) + { + case HH_MOD: + pchar = va_arg(ap, FAR unsigned char *); + *pchar = (unsigned char)nchars; + break; + + case H_MOD: + pshort = va_arg(ap, FAR unsigned short *); + *pshort = (unsigned short)nchars; + break; + + case NO_MOD: + pint = va_arg(ap, FAR unsigned int *); + *pint = (unsigned int)nchars; + break; + + default: + case L_MOD: + plong = va_arg(ap, FAR unsigned long *); + *plong = (unsigned long)nchars; + break; + +#ifdef CONFIG_LIBC_LONG_LONG + case LL_MOD: + plonglong = va_arg(ap, FAR unsigned long long *); + *plonglong = (unsigned long long)nchars; + break; +#endif + } + } + count++; + + } + else if (*fmt == '%') + { + if (c != '%') + { + break; + } + else + { + c = obj->get(obj); + } + } + + width = 0; + noassign = false; + modifier = NO_MOD; + + fmt++; + } + + /* It is not a conversion specifier */ + + else if (c > 0) + { +#if 0 + /* Skip over any leading spaces in the input buffer */ + + while (isspace(c)) + { + c = obj->get(obj); + } +#endif + + /* Skip over matching characters in the buffer and format */ + + if (*fmt != c) + { + break; + } + else + { + fmt++; + c = obj->get(obj); + } + } + else + { + /* NULL terminator encountered */ + + break; + } + } + + /* sscanf is required to return EOF if the input ends before the first + * matching failure or conversion. + */ + + *lastc = c; + return (count || !conv) ? assigncount : EOF; +} + diff --git a/beken_os/beken378/func/libc/stdio/lib_meminstream.c b/beken_os/beken378/func/libc/stdio/lib_meminstream.c new file mode 100755 index 0000000..840a1fa --- /dev/null +++ b/beken_os/beken378/func/libc/stdio/lib_meminstream.c @@ -0,0 +1,102 @@ +/**************************************************************************** + * libs/libc/stdio/lib_meminstream.c + * + * Copyright (C) 2007-2009, 2011-2012, 2014 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "libc.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: meminstream_getc + ****************************************************************************/ + +static int meminstream_getc(FAR struct lib_instream_s *this) +{ + FAR struct lib_meminstream_s *mthis = (FAR struct lib_meminstream_s *)this; + int ret; + + DEBUGASSERT(this); + + /* Get the next character (if any) from the buffer */ + + if (this->nget < mthis->buflen) + { + ret = mthis->buffer[this->nget]; + this->nget++; + } + else + { + ret = EOF; + } + + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lib_meminstream + * + * Description: + * Initializes a stream for use with a fixed-size memory buffer. + * + * Input Parameters: + * instream - User allocated, uninitialized instance of struct + * lib_meminstream_s to be initialized. + * bufstart - Address of the beginning of the fixed-size memory buffer + * buflen - Size of the fixed-sized memory buffer in bytes + * + * Returned Value: + * None (instream initialized). + * + ****************************************************************************/ + +void lib_meminstream(FAR struct lib_meminstream_s *instream, + FAR const char *bufstart, int buflen) +{ + instream->public.get = meminstream_getc; + instream->public.nget = 0; /* Will be buffer index */ + instream->buffer = bufstart; /* Start of buffer */ + instream->buflen = buflen; /* Length of the buffer */ +} diff --git a/beken_os/beken378/func/libc/stdio/lib_memsistream.c b/beken_os/beken378/func/libc/stdio/lib_memsistream.c new file mode 100755 index 0000000..8abbe28 --- /dev/null +++ b/beken_os/beken378/func/libc/stdio/lib_memsistream.c @@ -0,0 +1,148 @@ +/**************************************************************************** + * libs/libc/stdio/lib_memsistream.c + * + * Copyright (C) 2014 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include "libc.h" + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: memsistream_getc + ****************************************************************************/ + +static int memsistream_getc(FAR struct lib_sistream_s *this) +{ + FAR struct lib_memsistream_s *mthis = (FAR struct lib_memsistream_s *)this; + int ret; + + DEBUGASSERT(this); + + /* Get the next character (if any) from the buffer */ + + if (mthis->offset < mthis->buflen) + { + ret = mthis->buffer[mthis->offset]; + mthis->offset++; + this->nget++; + } + else + { + ret = EOF; + } + + return ret; +} + +/**************************************************************************** + * Name: memsistream_seek + ****************************************************************************/ + +static off_t memsistream_seek(FAR struct lib_sistream_s *this, off_t offset, + int whence) +{ + FAR struct lib_memsistream_s *mthis = (FAR struct lib_memsistream_s *)this; + off_t newpos; + + DEBUGASSERT(this); + + switch (whence) + { + case SEEK_CUR: + newpos = (off_t)mthis->offset + offset; + break; + + case SEEK_SET: + newpos = offset; + break; + + case SEEK_END: + newpos = (off_t)mthis->buflen + offset; + break; + + default: + return (off_t)ERROR; + } + + /* Make sure that the new position is within range */ + + if (newpos < 0 || newpos >= (off_t)mthis->buflen) + { + return (off_t)ERROR; + } + + /* Return the new position */ + + mthis->offset = (size_t)newpos; + return newpos; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: lib_memsistream + * + * Description: + * Initializes a stream for use with a fixed-size memory buffer. + * + * Input Parameters: + * instream - User allocated, uninitialized instance of struct + * lib_memsistream_s to be initialized. + * bufstart - Address of the beginning of the fixed-size memory buffer + * buflen - Size of the fixed-sized memory buffer in bytes + * + * Returned Value: + * None (instream initialized). + * + ****************************************************************************/ + +void lib_memsistream(FAR struct lib_memsistream_s *instream, + FAR const char *bufstart, int buflen) +{ + instream->public.get = memsistream_getc; + instream->public.seek = memsistream_seek; + instream->public.nget = 0; /* Total number of characters read */ + instream->buffer = bufstart; /* Start of buffer */ + instream->offset = 0; /* Will be the buffer index */ + instream->buflen = buflen; /* Length of the buffer */ +} diff --git a/beken_os/beken378/func/libc/stdio/lib_sscanf.c b/beken_os/beken378/func/libc/stdio/lib_sscanf.c new file mode 100755 index 0000000..65af7d2 --- /dev/null +++ b/beken_os/beken378/func/libc/stdio/lib_sscanf.c @@ -0,0 +1,70 @@ +/**************************************************************************** + * libs/libc/stdio/lib_sscanf.c + * + * Copyright (C) 2007-2009, 2011, 2019 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * Johannes Schock + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include +// #include +// #include "libc.h" + + +#define FAR +#define IPTR + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: sscanf + ****************************************************************************/ + +int __wrap_sscanf(FAR const char *buf, FAR const IPTR char *fmt, ...) +{ + va_list ap; + int n; + + /* vsscanf from the buffer */ + + va_start(ap, fmt); + n = vsscanf(buf, fmt, ap); + va_end(ap); + + return n; +} diff --git a/beken_os/beken378/func/libc/stdio/lib_vsscanf.c b/beken_os/beken378/func/libc/stdio/lib_vsscanf.c new file mode 100755 index 0000000..98ca233 --- /dev/null +++ b/beken_os/beken378/func/libc/stdio/lib_vsscanf.c @@ -0,0 +1,77 @@ +/**************************************************************************** + * libs/libc/stdio/lib_vscanf.c + * + * Copyright (C) 2019 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +// #include + +#include +#include +#include +// #include + +// #include + +#include "libc.h" + +#define FAR + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: vsscanf + ****************************************************************************/ + +int vsscanf(FAR const char *buf, FAR const char *fmt, va_list ap) +{ + struct lib_meminstream_s meminstream; + int n; + + /* Initialize a memory stream to freadm from the buffer */ + + lib_meminstream((FAR struct lib_meminstream_s *)&meminstream, buf, + LIB_BUFLEN_UNKNOWN); + + /* Then let lib_vscanf do the real work */ + + + n = lib_vscanf((FAR struct lib_instream_s *)&meminstream.public, NULL, + fmt, ap); + return n; +} diff --git a/beken_os/beken378/func/libc/stdlib/lib_qsort.c b/beken_os/beken378/func/libc/stdlib/lib_qsort.c new file mode 100755 index 0000000..0f89389 --- /dev/null +++ b/beken_os/beken378/func/libc/stdlib/lib_qsort.c @@ -0,0 +1,300 @@ +/**************************************************************************** + * libs/libc/stdlib/lib_qsort.c + * + * Copyright (C) 2007, 2009, 2011 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Leveraged from: + * + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +// #include + +#include +#include + +#define FAR +#define CODE + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define min(a, b) (a) < (b) ? a : b + +#define swapcode(TYPE, parmi, parmj, n) \ +{ \ + long i = (n) / sizeof (TYPE); \ + register TYPE *pi = (TYPE *)(parmi); \ + register TYPE *pj = (TYPE *)(parmj); \ + do { \ + register TYPE t = *pi; \ + *pi++ = *pj; \ + *pj++ = t; \ + } while (--i > 0); \ +} + +#define SWAPINIT(a, width) \ + swaptype = ((FAR char *)a - (FAR char *)0) % sizeof(long) || \ + width % sizeof(long) ? 2 : width == sizeof(long)? 0 : 1; + +#define swap(a, b) \ + if (swaptype == 0) \ +{ \ + long t = *(long *)(a); \ + *(long *)(a) = *(long *)(b); \ + *(long *)(b) = t; \ +} \ +else \ +{ \ + swapfunc(a, b, width, swaptype); \ +} + +#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype) + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static inline void swapfunc(FAR char *a, FAR char *b, int n, int swaptype); +static inline FAR char *med3(FAR char *a, FAR char *b, FAR char *c, + CODE int (*compar)(FAR const void *, + FAR const void *)); + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static inline void swapfunc(FAR char *a, FAR char *b, int n, int swaptype) +{ + if (swaptype <= 1) + { + swapcode(long, a, b, n) + } + else + { + swapcode(char, a, b, n) + } +} + +static inline FAR char *med3(FAR char *a, FAR char *b, FAR char *c, + CODE int (*compar)(FAR const void *, + FAR const void *)) +{ + return compar(a, b) < 0 ? + (compar(b, c) < 0 ? b : (compar(a, c) < 0 ? c : a)) : + (compar(b, c) > 0 ? b : (compar(a, c) < 0 ? a : c)); +} + +/**************************************************************************** + * Public Function + ****************************************************************************/ + +/**************************************************************************** + * Name: qsort + * + * Description: + * The qsort() function will sort an array of 'nel' objects, the initial + * element of which is pointed to by 'base'. The size of each object, in + * bytes, is specified by the 'width" argument. If the 'nel' argument has + * the value zero, the comparison function pointed to by 'compar' will not + * be called and no rearrangement will take place. + * + * The application will ensure that the comparison function pointed to by + * 'compar' does not alter the contents of the array. The implementation + * may reorder elements of the array between calls to the comparison + * function, but will not alter the contents of any individual element. + * + * When the same objects (consisting of 'width" bytes, irrespective of + * their current positions in the array) are passed more than once to + * the comparison function, the results will be consistent with one + * another. That is, they will define a total ordering on the array. + * + * The contents of the array will be sorted in ascending order according + * to a comparison function. The 'compar' argument is a pointer to the + * comparison function, which is called with two arguments that point to + * the elements being compared. The application will ensure that the + * function returns an integer less than, equal to, or greater than 0, + * if the first argument is considered respectively less than, equal to, + * or greater than the second. If two members compare as equal, their + * order in the sorted array is unspecified. + * + * (Based on description from OpenGroup.org). + * + * Returned Value: + * The qsort() function will not return a value. + * + * Notes from the original BSD version: + * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function". + * + ****************************************************************************/ + +void __wrap_qsort(FAR void *base, size_t nel, size_t width, + CODE int(*compar)(FAR const void *, FAR const void *)) +{ + FAR char *pa; + FAR char *pb; + FAR char *pc; + FAR char *pd; + FAR char *pl; + FAR char *pm; + FAR char *pn; + int swaptype; + int swap_cnt; + int d; + int r; + +loop: + SWAPINIT(base, width); + swap_cnt = 0; + + if (nel < 7) + { + for (pm = (FAR char *)base + width; + pm < (FAR char *)base + nel * width; + pm += width) + { + for (pl = pm; + pl > (FAR char *)base && compar(pl - width, pl) > 0; + pl -= width) + { + swap(pl, pl - width); + } + } + + return; + } + + pm = (FAR char *)base + (nel / 2) * width; + if (nel > 7) + { + pl = base; + pn = (FAR char *)base + (nel - 1) * width; + if (nel > 40) + { + d = (nel / 8) * width; + pl = med3(pl, pl + d, pl + 2 * d, compar); + pm = med3(pm - d, pm, pm + d, compar); + pn = med3(pn - 2 * d, pn - d, pn, compar); + } + + pm = med3(pl, pm, pn, compar); + } + + swap(base, pm); + pa = pb = (FAR char *)base + width; + + pc = pd = (FAR char *)base + (nel - 1) * width; + for (; ; ) + { + while (pb <= pc && (r = compar(pb, base)) <= 0) + { + if (r == 0) + { + swap_cnt = 1; + swap(pa, pb); + pa += width; + } + + pb += width; + } + + while (pb <= pc && (r = compar(pc, base)) >= 0) + { + if (r == 0) + { + swap_cnt = 1; + swap(pc, pd); + pd -= width; + } + + pc -= width; + } + + if (pb > pc) + { + break; + } + + swap(pb, pc); + swap_cnt = 1; + pb += width; + pc -= width; + } + + if (swap_cnt == 0) + { + /* Switch to insertion sort */ + + for (pm = (FAR char *)base + width; + pm < (FAR char *)base + nel * width; + pm += width) + { + for (pl = pm; + pl > (FAR char *)base && compar(pl - width, pl) > 0; + pl -= width) + { + swap(pl, pl - width); + } + } + + return; + } + + pn = (FAR char *)base + nel * width; + r = min(pa - (FAR char *)base, pb - pa); + vecswap(base, pb - r, r); + + r = min(pd - pc, pn - pd - width); + vecswap(pb, pn - r, r); + + if ((r = pb - pa) > width) + { + qsort(base, r / width, width, compar); + } + + if ((r = pd - pc) > width) + { + /* Iterate rather than recurse to save stack space */ + + base = pn - r; + nel = r / width; + goto loop; + } +} diff --git a/beken_os/beken378/func/libc/stdlib/lib_strtod.c b/beken_os/beken378/func/libc/stdlib/lib_strtod.c new file mode 100755 index 0000000..b9d465b --- /dev/null +++ b/beken_os/beken378/func/libc/stdlib/lib_strtod.c @@ -0,0 +1,264 @@ +/**************************************************************************** + * libs/libc/stdlib/lib_strtod.c + * Convert string to double + * + * Copyright (C) 2002 Michael Ringgaard. All rights reserved. + * Copyright (C) 2006-2007 H. Peter Anvin. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the project nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +//#include +//#include + +#include +#include +#include + +#define CONFIG_HAVE_DOUBLE +#define FAR + +#ifdef CONFIG_HAVE_DOUBLE + +/**************************************************************************** + * Pre-processor definitions + ****************************************************************************/ + +/* These are predefined with GCC, but could be issues for other compilers. If + * not defined, an arbitrary big number is put in for now. These should be + * added to nuttx/compiler for your compiler. + */ + +#if !defined(__DBL_MIN_EXP__) || !defined(__DBL_MAX_EXP__) +# ifdef CONFIG_CPP_HAVE_WARNING +# warning "Size of exponent is unknown" +# endif +# undef __DBL_MIN_EXP__ +# define __DBL_MIN_EXP__ (-1021) +# undef __DBL_MAX_EXP__ +# define __DBL_MAX_EXP__ (1024) +#endif + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static inline int is_real(double x) +{ + const double infinite = 1.0/0.0; + return (x < infinite) && (x >= -infinite); +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/***************************************************(************************ + * Name: strtod + * + * Description: + * Convert a string to a double value + * + ****************************************************************************/ + +double lib_strtod(FAR const char *str, FAR char **endptr) +{ + double number; + int exponent; + int negative; + FAR char *p = (FAR char *) str; + double p10; + int n; + int num_digits; + int num_decimals; + const double infinite = 1.0/0.0; + + /* Skip leading whitespace */ + + while (isspace((unsigned char)(*p))) + { + p++; + } + + /* Handle optional sign */ + + negative = 0; + switch (*p) + { + case '-': + negative = 1; /* Fall through to increment position */ + /* FALLTHROUGH */ + case '+': + p++; + /* FALLTHROUGH */ + default: + break; + } + + number = 0.; + exponent = 0; + num_digits = 0; + num_decimals = 0; + + /* Process string of digits */ + + while (isdigit((unsigned char)*p)) + { + number = number * 10. + (*p - '0'); + p++; + num_digits++; + } + + /* Process decimal part */ + + if (*p == '.') + { + p++; + + while (isdigit((unsigned char)*p)) + { + number = number * 10. + (*p - '0'); + p++; + num_digits++; + num_decimals++; + } + + exponent -= num_decimals; + } + + if (num_digits == 0) + { + //set_errno(ERANGE); + number = 0.0; + goto errout; + } + + /* Correct for sign */ + + if (negative) + { + number = -number; + } + + /* Process an exponent string */ + + if (*p == 'e' || *p == 'E') + { + /* Handle optional sign */ + + negative = 0; + switch (*++p) + { + case '-': + negative = 1; /* Fall through to increment pos */ + /* FALLTHROUGH */ + case '+': + p++; + /* FALLTHROUGH */ + default: + break; + } + + /* Process string of digits */ + + n = 0; + while (isdigit((unsigned char)*p)) + { + n = n * 10 + (*p - '0'); + p++; + } + + if (negative) + { + exponent -= n; + } + else + { + exponent += n; + } + } + + if (exponent < __DBL_MIN_EXP__ || + exponent > __DBL_MAX_EXP__) + { + //set_errno(ERANGE); + number = infinite; + goto errout; + } + + /* Scale the result */ + + p10 = 10.; + n = exponent; + if (n < 0) + { + n = -n; + } + + while (n) + { + if (n & 1) + { + if (exponent < 0) + { + number /= p10; + } + else + { + number *= p10; + } + } + + n >>= 1; + p10 *= p10; + } + + if (!is_real(number)) + { + //set_errno(ERANGE); + } + +errout: + if (endptr) + { + *endptr = p; + } + + return number; +} + +double __wrap_strtod(FAR const char *str, FAR char **endptr) +{ + return lib_strtod(str, endptr); +} + +#endif /* CONFIG_HAVE_DOUBLE */ diff --git a/beken_os/beken378/func/lwip_intf/dhcpd/dhcp-bootp.h b/beken_os/beken378/func/lwip_intf/dhcpd/dhcp-bootp.h new file mode 100755 index 0000000..54dca99 --- /dev/null +++ b/beken_os/beken378/func/lwip_intf/dhcpd/dhcp-bootp.h @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2008-2015, Marvell International Ltd. + * All Rights Reserved. + */ +#ifndef __DHCP_BOOTP_H_ +#define __DHCP_BOOTP_H_ + +#define DHCP_SERVER_PORT 67 +#define DHCP_CLIENT_PORT 68 + +#define NAMESERVER_PORT 53 + +#define CTRL_PORT 12679 + +#define BOOTP_OP_REQUEST 1 +#define BOOTP_OP_RESPONSE 2 + +#define BOOTP_OPTION_SUBNET_MASK 1 +#define BOOTP_OPTION_ROUTER 3 +#define BOOTP_OPTION_NAMESERVER 6 +#define BOOTP_OPTION_REQUESTED_IP 50 +#define BOOTP_OPTION_ADDRESS_TIME 51 +#define BOOTP_OPTION_DHCP_MESSAGE 53 +#define BOOTP_OPTION_DHCP_SERVER_ID 54 +#define BOOTP_END_OPTION 0xFF + +enum dhcp_message_type { + DHCP_MESSAGE_DISCOVER = 1, + DHCP_MESSAGE_OFFER = 2, + DHCP_MESSAGE_REQUEST = 3, + DHCP_MESSAGE_DECLINE = 4, + DHCP_MESSAGE_ACK = 5, + DHCP_MESSAGE_NAK = 6, + DHCP_MESSAGE_RELEASE = 7, + DHCP_MESSAGE_INFORM = 8, + DHCP_NO_RESPONSE = 255 +}; + +struct bootp_header { + uint8_t op; /* message type */ + uint8_t htype; /* hardware type (1 = ethernet) */ + uint8_t hlen; /* hardware address length (6) */ + uint8_t hops; /* (0) */ + uint32_t xid; /* transaction ID */ + uint16_t secs; /* seconds elapsed */ + uint16_t flags; /* bootp flags */ + uint32_t ciaddr; /* client IP address */ + uint32_t yiaddr; /* your IP address */ + uint32_t siaddr; /* next server IP address */ + uint32_t riaddr; /* relay agent IP address */ + uint8_t chaddr[6]; /* client MAC address */ + uint8_t pad[10 + 192]; /* 10 octets of padding, 192 octets of + padding */ + uint32_t cookie; /* magic cookie */ +} __attribute__((packed)); + +struct bootp_option { + uint8_t type; + uint8_t length; + char value[0]; +} __attribute__((packed)); +#define ETH_P_RARP 0x8035 + +#define ETH_HW_ADDR_LEN 6 +#define IP_ADDR_LEN 4 +#define ARP_FRAME_TYPE 0x0806 +#define ETHER_HW_TYPE 1 +#define IP_PROTO_TYPE 0x0800 +#define OP_ARP_REQUEST 2 +#define SOCK_PACKET 10 + +struct arp_packet { + uint8_t targ_hw_addr[ETH_HW_ADDR_LEN]; + uint8_t src_hw_addr[ETH_HW_ADDR_LEN]; + uint16_t frame_type; + uint16_t hw_type; + uint16_t prot_type; + uint8_t hw_addr_size; + uint8_t prot_addr_size; + uint16_t op; + uint8_t sndr_hw_addr[ETH_HW_ADDR_LEN]; + char sndr_ip_addr[IP_ADDR_LEN]; + uint8_t rcpt_hw_addr[ETH_HW_ADDR_LEN]; + char rcpt_ip_addr[IP_ADDR_LEN]; + uint8_t padding[18]; +}; + +#endif diff --git a/beken_os/beken378/func/lwip_intf/dhcpd/dhcp-priv.h b/beken_os/beken378/func/lwip_intf/dhcpd/dhcp-priv.h new file mode 100755 index 0000000..2dffbd2 --- /dev/null +++ b/beken_os/beken378/func/lwip_intf/dhcpd/dhcp-priv.h @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2008-2015, Marvell International Ltd. + * All Rights Reserved. + */ + +#ifndef __DHCP_PRIV_H__ +#define __DHCP_PRIV_H__ + +#include "lwip/sockets.h" + +#if 0 +#define dhcp_e(...) \ + bk_printf("dhcp: %s\r\n", ##__VA_ARGS__) +#define dhcp_w(...) \ + bk_printf("dhcp: %s\r\n", ##__VA_ARGS__) + +#define dhcp_d(...) \ + bk_printf("dhcp: %s\r\n", ##__VA_ARGS__) +#else +#define dhcp_d(...) +#define dhcp_e(...) +#define dhcp_w(...) +#endif + +#define SERVER_BUFFER_SIZE 1024 +#define MAC_IP_CACHE_SIZE 8 + +struct client_mac_cache { + uint8_t client_mac[6]; /* mac address of the connected device */ + uint32_t client_ip; /* ip address of the connected device */ +}; + +struct dhcp_server_data { + int sock; + int dnssock; + int ctrlsock; + int count_clients; /* to keep count of cached devices */ + char *msg; + struct sockaddr_in saddr; /* dhcp server address */ + struct sockaddr_in dnsaddr; /* dns server address */ + struct sockaddr_in uaddr; /* unicast address */ + struct sockaddr_in baddr; /* broadcast address */ + struct sockaddr_in ctrladdr; + struct client_mac_cache ip_mac_mapping[MAC_IP_CACHE_SIZE]; + uint32_t netmask; /* network order */ + uint32_t my_ip; /* network order */ + uint32_t client_ip; /* last address that was requested, network + * order */ + uint32_t current_ip; /* keep track of assigned IP addresses */ + uint32_t router_ip; /* router IP addresses */ + void *prv; +}; + +void dhcp_enable_nack_dns_server(void); +int dhcp_server_init(void *intrfc_handle); +void dhcp_server(void* data); +int dhcp_send_halt(void); +int dhcp_free_allocations(void); + +#endif diff --git a/beken_os/beken378/func/lwip_intf/dhcpd/dhcp-server-main.c b/beken_os/beken378/func/lwip_intf/dhcpd/dhcp-server-main.c new file mode 100755 index 0000000..684541d --- /dev/null +++ b/beken_os/beken378/func/lwip_intf/dhcpd/dhcp-server-main.c @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2008-2015, Marvell International Ltd. + * All Rights Reserved. + */ + +/** dhcp-server-main.c: CLI based APIs for the DHCP Server + */ +#include +#include "rtos_pub.h" +#include "dhcp-priv.h" + +static beken_thread_t dhcpd_thread; +static bool dhcpd_running; + +int dhcp_server_start(void *intrfc_handle) +{ + int ret; + + dhcp_d("DHCP server start request \r\n"); + + dhcp_enable_nack_dns_server(); + + if (dhcpd_running || dhcp_server_init(intrfc_handle)) + return -1; + + ret = rtos_create_thread(&dhcpd_thread, + BEKEN_APPLICATION_PRIORITY, + "dhcp-server", + (beken_thread_function_t)dhcp_server, + #if !OSMALLOC_STATISTICAL + 1024, + #else + 1024*2, + #endif + 0); + if (ret) { + dhcp_free_allocations(); + return -1; + } + + dhcpd_running = 1; + return 0; +} + +void dhcp_server_stop(void) +{ + dhcp_d("DHCP server stop request\r\n"); + if (dhcpd_running) { + if (dhcp_send_halt() != 0) { + dhcp_w("failed to send halt to DHCP thread\r\n"); + return; + } + if (rtos_delete_thread(&dhcpd_thread) != 0) + dhcp_w("failed to delete thread\r\n"); + dhcpd_running = 0; + } else { + dhcp_w("server not dhcpd_running.\r\n"); + } +} + diff --git a/beken_os/beken378/func/lwip_intf/dhcpd/dhcp-server.c b/beken_os/beken378/func/lwip_intf/dhcpd/dhcp-server.c new file mode 100755 index 0000000..f381d80 --- /dev/null +++ b/beken_os/beken378/func/lwip_intf/dhcpd/dhcp-server.c @@ -0,0 +1,897 @@ +/** dhcp-server.c: The DHCP Server + */ +#include +#include "rtos_pub.h" +#include "dhcp-bootp.h" +#include "dns.h" +#include "dhcp-priv.h" +#include "str_pub.h" +#include "mem_pub.h" +#include "etharp.h" + +#define os_mem_alloc os_malloc +#define os_mem_free os_free +#define SEND_RESPONSE(w,x,y,z) send_response(w,x,y,z) + +#define DEFAULT_DHCP_ADDRESS_TIMEOUT (60U*60U*1U) /* 1 hour */ +#define CLIENT_IP_NOT_FOUND 0x00000000 + +uint32_t dhcp_address_timeout = DEFAULT_DHCP_ADDRESS_TIMEOUT; +static beken_mutex_t dhcpd_mutex; +static int (*dhcp_nack_dns_server_handler)(char *msg, int len, + struct sockaddr_in *fromaddr); + +struct dhcp_server_data dhcps; + +extern int net_get_if_macaddr(void *macaddr, void *intrfc_handle); +extern int net_get_if_ip_addr(uint32_t *ip, void *intrfc_handle); +extern int net_get_if_ip_mask(uint32_t *nm, void *intrfc_handle); +extern int net_get_if_gw_addr(uint32_t *ip, void *intrfc_handle); +static void get_broadcast_addr(struct sockaddr_in *addr); +static int get_ip_addr_from_interface(uint32_t *ip, void *interface_handle); +static int get_netmask_from_interface(uint32_t *nm, void *interface_handle); +static int get_mac_addr_from_interface(void *mac, void *interface_handle); +static int get_gateway_from_interface(uint32_t *gw, void *interface_handle); +static int send_gratuitous_arp(uint32_t ip); +static bool ac_add(uint8_t *chaddr, uint32_t client_ip); +static uint32_t ac_lookup_mac(uint8_t *chaddr); +static uint8_t *ac_lookup_ip(uint32_t client_ip); +static bool ac_not_full(); + +static bool ac_add(uint8_t *chaddr, uint32_t client_ip) +{ + /* adds ip-mac mapping in cache */ + if (ac_not_full()) { + dhcps.ip_mac_mapping[dhcps.count_clients].client_mac[0] + = chaddr[0]; + dhcps.ip_mac_mapping[dhcps.count_clients].client_mac[1] + = chaddr[1]; + dhcps.ip_mac_mapping[dhcps.count_clients].client_mac[2] + = chaddr[2]; + dhcps.ip_mac_mapping[dhcps.count_clients].client_mac[3] + = chaddr[3]; + dhcps.ip_mac_mapping[dhcps.count_clients].client_mac[4] + = chaddr[4]; + dhcps.ip_mac_mapping[dhcps.count_clients].client_mac[5] + = chaddr[5]; + dhcps.ip_mac_mapping[dhcps.count_clients].client_ip = client_ip; + dhcps.count_clients++; + return 0; + } + return -1; +} + +static uint32_t ac_lookup_mac(uint8_t *chaddr) +{ + /* returns ip address, if mac address is present in cache */ + int i; + for (i = 0; i < dhcps.count_clients && i < MAC_IP_CACHE_SIZE; i++) { + if ((dhcps.ip_mac_mapping[i].client_mac[0] == chaddr[0]) && + (dhcps.ip_mac_mapping[i].client_mac[1] == chaddr[1]) && + (dhcps.ip_mac_mapping[i].client_mac[2] == chaddr[2]) && + (dhcps.ip_mac_mapping[i].client_mac[3] == chaddr[3]) && + (dhcps.ip_mac_mapping[i].client_mac[4] == chaddr[4]) && + (dhcps.ip_mac_mapping[i].client_mac[5] == chaddr[5])) { + return dhcps.ip_mac_mapping[i].client_ip; + } + } + return CLIENT_IP_NOT_FOUND; +} + +static uint8_t *ac_lookup_ip(uint32_t client_ip) +{ + /* returns mac address, if ip address is present in cache */ + int i; + for (i = 0; i < dhcps.count_clients && i < MAC_IP_CACHE_SIZE; i++) { + if ((dhcps.ip_mac_mapping[i].client_ip) == client_ip) { + return dhcps.ip_mac_mapping[i].client_mac; + } + } + return NULL; +} + +static bool ac_not_full() +{ + /* returns true if cache is not full */ + return (dhcps.count_clients < MAC_IP_CACHE_SIZE); +} + +static bool ac_valid_ip(uint32_t requested_ip) +{ + /* skip over our own address, the network address or the + * broadcast address + */ + if (requested_ip == ntohl(dhcps.my_ip) || + (requested_ip == ntohl(dhcps.my_ip & + dhcps.netmask)) || + (requested_ip == ntohl((dhcps.my_ip | + (0xffffffff & ~dhcps.netmask))))) { + return false; + } + if (ac_lookup_ip(htonl(requested_ip)) != NULL) + return false; + return true; +} + +static void write_u32(char *dest, uint32_t be_value) +{ + *dest++ = be_value & 0xFF; + *dest++ = (be_value >> 8) & 0xFF; + *dest++ = (be_value >> 16) & 0xFF; + *dest = be_value >> 24; +} + +/* Configure the DHCP dynamic IP lease time*/ +int dhcp_server_lease_timeout(uint32_t val) +{ + if ((val == 0) || (val > (60U*60U*24U*49700U))) { + return -EINVAL; + } else { + dhcp_address_timeout = val; + return 0; + } +} + +/* calculate the address to give out to the next DHCP DISCOVER request + * + * DHCP clients will be assigned addresses in sequence in the subnet's address space. + */ +static unsigned int next_yiaddr() +{ +#ifdef CONFIG_DHCP_SERVER_DEBUG + struct in_addr ip; +#endif + uint32_t new_ip; + struct bootp_header *hdr = (struct bootp_header *)dhcps.msg; + + /* if device requesting for ip address is already registered, + * if yes, assign previous ip address to it + */ + new_ip = ac_lookup_mac(hdr->chaddr); + if (new_ip == (CLIENT_IP_NOT_FOUND)) { + /* next IP address in the subnet */ + dhcps.current_ip = ntohl(dhcps.my_ip & dhcps.netmask) | + ((dhcps.current_ip + 1) & ntohl(~dhcps.netmask)); + while (!ac_valid_ip(dhcps.current_ip)) { + dhcps.current_ip = ntohl(dhcps.my_ip & dhcps.netmask) | + ((dhcps.current_ip + 1) & + ntohl(~dhcps.netmask)); + } + + new_ip = htonl(dhcps.current_ip); + + if (ac_add(hdr->chaddr, new_ip) != + 0) + dhcp_w("No space to store new mapping..\r\n"); + } + +#ifdef CONFIG_DHCP_SERVER_DEBUG + ip.s_addr = new_ip; + dhcp_d("New client IP will be %s\r\n", inet_ntoa(ip)); + ip.s_addr = dhcps.my_ip & dhcps.netmask; +#endif + + return new_ip; +} + +static unsigned int make_response(char *msg, enum dhcp_message_type type) +{ + struct bootp_header *hdr; + struct bootp_option *opt; + char *offset = msg; + + hdr = (struct bootp_header *)offset; + hdr->op = BOOTP_OP_RESPONSE; + hdr->htype = 1; + hdr->hlen = 6; + hdr->hops = 0; + hdr->ciaddr = 0; + hdr->yiaddr = (type == DHCP_MESSAGE_ACK) ? dhcps.client_ip : 0; + hdr->yiaddr = (type == DHCP_MESSAGE_OFFER) ? + next_yiaddr() : hdr->yiaddr; + hdr->siaddr = 0; + hdr->riaddr = 0; + offset += sizeof(struct bootp_header); + + opt = (struct bootp_option *)offset; + opt->type = BOOTP_OPTION_DHCP_MESSAGE; + *(uint8_t *) opt->value = type; + opt->length = 1; + offset += sizeof(struct bootp_option) + opt->length; + + if (type == DHCP_MESSAGE_NAK) + return (unsigned int)(offset - msg); + + opt = (struct bootp_option *)offset; + opt->type = BOOTP_OPTION_SUBNET_MASK; + write_u32(opt->value, dhcps.netmask); + opt->length = 4; + offset += sizeof(struct bootp_option) + opt->length; + + opt = (struct bootp_option *)offset; + opt->type = BOOTP_OPTION_ADDRESS_TIME; + write_u32(opt->value, htonl(dhcp_address_timeout)); + opt->length = 4; + offset += sizeof(struct bootp_option) + opt->length; + + opt = (struct bootp_option *)offset; + opt->type = BOOTP_OPTION_DHCP_SERVER_ID; + write_u32(opt->value, dhcps.my_ip); + opt->length = 4; + offset += sizeof(struct bootp_option) + opt->length; + + opt = (struct bootp_option *)offset; + opt->type = BOOTP_OPTION_ROUTER; + write_u32(opt->value, dhcps.router_ip); + opt->length = 4; + offset += sizeof(struct bootp_option) + opt->length; + + opt = (struct bootp_option *)offset; + opt->type = BOOTP_OPTION_NAMESERVER; + if (dhcp_nack_dns_server_handler) + write_u32(opt->value, dhcps.router_ip); + else + write_u32(opt->value, 0); + opt->length = 4; + offset += sizeof(struct bootp_option) + opt->length; + + opt = (struct bootp_option *)offset; + opt->type = BOOTP_END_OPTION; + offset++; + + return (unsigned int)(offset - msg); +} + +int dhcp_get_ip_from_mac(uint8_t *client_mac, uint32_t *client_ip) +{ + *client_ip = ac_lookup_mac(client_mac); + if (*client_ip == CLIENT_IP_NOT_FOUND) { + return -1; + } + return 0; +} + +extern void ap_set_default_netif(void); +extern void reset_default_netif(void); + +static int send_response(int sock, struct sockaddr *addr, char *msg, int len) +{ + int nb; + unsigned int sent = 0; +#if 0 /* Deleted by Tuya, because of bind this socket to ap-netif in function dhcp_server_init */ + // // in AP+STA mode, should set ap-netif as default + int dest_ip = ((struct sockaddr_in *)addr)->sin_addr.s_addr; + if((dest_ip == IPADDR_ANY) || (dest_ip == IPADDR_BROADCAST)) + ap_set_default_netif(); +#endif + while (sent < len) { + nb = lwip_sendto(sock, msg + sent, len - sent, 0, addr, + sizeof(struct sockaddr_in)); + if (nb < 0) { + dhcp_e("failed to send response, addr %p:%d\r\n", + ((struct sockaddr_in *)addr)->sin_addr, + ((struct sockaddr_in *)addr)->sin_port); + return -1; + } + sent += nb; + } + + // rest default netif to sta's netif + //if((dest_ip == IPADDR_ANY) || (dest_ip == IPADDR_BROADCAST)) + //reset_default_netif(); + + dhcp_d("sent response, %d bytes %s\r\n", sent, + inet_ntoa(((struct sockaddr_in *)addr)->sin_addr)); + return 0; +} + +#define ERROR_REFUSED 5 +static int process_dns_message(char *msg, int len, struct sockaddr_in *fromaddr) +{ + struct dns_header *hdr; + char *endp = msg + len; + int nq; + + if (len < sizeof(struct dns_header)) { + dhcp_e("DNS request is not complete, hence ignoring it\r\n"); + return -1; + } + + hdr = (struct dns_header *)msg; + + dhcp_d("DNS transaction id: 0x%x\r\n", htons(hdr->id)); + + if (hdr->flags.fields.qr) { + dhcp_e("ignoring this dns message (not a query)\r\n"); + return -1; + } + + nq = ntohs(hdr->num_questions); + dhcp_d("we were asked %d questions\r\n", nq); + + if (nq <= 0) { + dhcp_e("ignoring this dns msg (not a query or 0 questions)\r\n"); + return -1; + } + + /* make the header represent a response */ + hdr->flags.fields.qr = 1; + hdr->flags.fields.opcode = 0; + /* Errors are never authoritative (unless they are + NXDOMAINS, which this is not) */ + hdr->flags.fields.aa = 0; + hdr->flags.fields.tc = 0; + hdr->flags.fields.rd = 1; + hdr->flags.fields.ra = 0; + hdr->flags.fields.rcode = ERROR_REFUSED; + hdr->flags.num = htons(hdr->flags.num); + /* number of entries in questions section */ + hdr->num_questions = htons(0x01); + hdr->answer_rrs = 0; /* number of resource records in answer section */ + hdr->authority_rrs = 0; + hdr->additional_rrs = 0; + SEND_RESPONSE(dhcps.dnssock, (struct sockaddr *)fromaddr, + msg, endp - msg); + + return -1; +} + +static int process_dhcp_message(char *msg, int len) +{ + struct bootp_header *hdr; + struct bootp_option *opt; + uint8_t response_type = DHCP_NO_RESPONSE; + unsigned int consumed = 0; + bool got_ip = 0; + bool need_ip = 0; + bool got_client_ip = 0; + uint32_t new_ip; + + if (!msg || + len < sizeof(struct bootp_header) + sizeof(struct bootp_option) + 1) + return -1; + + hdr = (struct bootp_header *)msg; + + switch (hdr->op) { + case BOOTP_OP_REQUEST: + dhcp_d("bootp request\r\n"); + break; + case BOOTP_OP_RESPONSE: + dhcp_d("bootp response\r\n"); + break; + default: + dhcp_e("invalid op code: %d\r\n", hdr->op); + return -1; + } + + if (hdr->htype != 1 || hdr->hlen != 6) { + dhcp_e("invalid htype or hlen\r\n"); + return -1; + } + + dhcp_d("client MAC: %02X:%02X:%02X:%02X:%02X:%02X\r\n", hdr->chaddr[0], + hdr->chaddr[1], hdr->chaddr[2], hdr->chaddr[3], hdr->chaddr[4], + hdr->chaddr[5]); + + dhcp_d("magic cookie: 0x%X\r\n", hdr->cookie); + + len -= sizeof(struct bootp_header); + opt = (struct bootp_option *)(msg + sizeof(struct bootp_header)); + while (len > 0 && opt->type != BOOTP_END_OPTION) { + if (opt->type == BOOTP_OPTION_DHCP_MESSAGE && opt->length == 1) { + dhcp_d("found DHCP message option\r\n"); + switch (*(uint8_t *) opt->value) { + case DHCP_MESSAGE_DISCOVER: + dhcp_d("DHCP discover\r\n"); + response_type = DHCP_MESSAGE_OFFER; + break; + + case DHCP_MESSAGE_REQUEST: + dhcp_d("DHCP request\r\n"); + need_ip = 1; + if (hdr->ciaddr != 0x0000000) { + dhcps.client_ip = hdr->ciaddr; + got_client_ip = 1; + } + break; + + default: + dhcp_d("ignoring message type %d\r\n", + *(uint8_t *) opt->value); + break; + } + } + if (opt->type == BOOTP_OPTION_REQUESTED_IP && opt->length == 4) { + dhcp_d("found REQUESTED IP option %hhu.%hhu.%hhu.%hhu\r\n", + (uint8_t)opt->value[0], + (uint8_t)opt->value[1], + (uint8_t)opt->value[2], + (uint8_t)opt->value[3]); + memcpy((uint8_t *) &dhcps.client_ip, (uint8_t *) opt->value, 4); + got_client_ip = 1; + } + + if (got_client_ip) { + /* requested address outside of subnet */ + if ((dhcps.client_ip & dhcps.netmask) == + (dhcps.my_ip & dhcps.netmask)) { + + /* When client requests an IP address, + * DHCP-server checks if the valid + * IP-MAC entry is present in the + * ip-mac cache, if yes, also checks + * if the requested IP is same as the + * IP address present in IP-MAC entry, + * if yes, it allows the device to + * continue with the requested IP + * address. + */ + new_ip = ac_lookup_mac(hdr->chaddr); + if (new_ip != (CLIENT_IP_NOT_FOUND)) { + /* if new_ip is equal to requested ip */ + if (new_ip == dhcps.client_ip) { + got_ip = 1; + } else { + got_ip = 0; + } + } else if (ac_valid_ip + (ntohl(dhcps.client_ip))) { + /* When client requests with an IP + * address that is within subnet range + * and not assigned to any other client, + * then dhcp-server allows that device + * to continue with that IP address. + * And if IP-MAC cache is not full then + * adds this entry in cache. + */ + if (ac_not_full()) { + ac_add(hdr->chaddr, + dhcps.client_ip); + } else { + dhcp_w("No space to store new \r\n" + "mapping..\r\n"); + } + got_ip = 1; + } + } + } + + /* look at the next option (if any) */ + consumed = sizeof(struct bootp_option) + opt->length; + len -= consumed; + opt = (struct bootp_option *)((char *)opt + consumed); + if (need_ip) + response_type = got_ip ? DHCP_MESSAGE_ACK : + DHCP_MESSAGE_NAK; + } + + if (response_type != DHCP_NO_RESPONSE) { + uint32_t dst_ip = 0, retry = 0; + int send_byte; + struct bootp_header *hdr; + + send_byte = make_response(msg, (enum dhcp_message_type)response_type); + hdr = (struct bootp_header *)msg; + + dst_ip = hdr->yiaddr; + + if(dst_ip != 0) { + dhcps.uaddr.sin_addr.s_addr = dst_ip; + + //dhcps.baddr.sin_addr.s_addr = dst_ip; + dhcp_d("change dhcps.uaddr: %s\r\n", inet_ntoa(dhcps.uaddr.sin_addr)); + + etharp_add_static_entry((ip4_addr_t *)&dst_ip, (struct eth_addr *)hdr->chaddr); + + retry = 0; + + dhcp_d("this pkt resp is unicast\r\n"); + hdr->flags &= ~(htons(1<<15)); + while(1) { + SEND_RESPONSE(dhcps.sock, + (struct sockaddr *)&dhcps.uaddr, msg, send_byte); + + if(++retry == 1) + break; + } + etharp_remove_static_entry((ip4_addr_t *)&dst_ip); + } + + dhcp_d("this pkt resp is broadcast\r\n"); + hdr->flags |= (htons(1<<15)); + retry = 0; + while(1) { + SEND_RESPONSE(dhcps.sock, + (struct sockaddr *)&dhcps.baddr, msg, send_byte); + + if(++retry == 3) + break; + } + + if (response_type == DHCP_MESSAGE_ACK) + send_gratuitous_arp(dhcps.my_ip); + return 0; + } + + dhcp_d("ignoring DHCP packet\r\n"); + return 0; +} + +static void dhcp_clean_sockets(void) +{ + int ret; + + if (dhcps.sock != -1) { + ret = lwip_close(dhcps.sock); + if (ret != 0) { + dhcp_w("Failed to close dhcp socket\r\n"); + } + dhcps.sock = -1; + } + if ( dhcp_nack_dns_server_handler ) + { + if ( dhcps.dnssock != -1 ) + { + ret = lwip_close(dhcps.dnssock); + if ( ret != 0 ) + { + dhcp_w("Failed to close dns port socket\r\n"); + } + dhcps.dnssock= -1; + } + } + if ( dhcps.ctrlsock != -1 ) + { + ret = lwip_close(dhcps.ctrlsock); + if ( ret != 0 ) + { + dhcp_w("Failed to close ctrol port socket\r\n"); + } + dhcps.ctrlsock = -1; + } +} + +void dhcp_server(void* data) +{ + int ret; + struct sockaddr_in caddr; + int max_sock; + int len; + socklen_t flen = sizeof(caddr); + fd_set rfds; + + + rtos_lock_mutex(&dhcpd_mutex); + + while (1) { + FD_ZERO(&rfds); + FD_SET(dhcps.sock, &rfds); + max_sock = dhcps.sock; + + if (dhcp_nack_dns_server_handler) { + FD_SET(dhcps.dnssock, &rfds); + max_sock = (dhcps.sock > dhcps.dnssock ? + dhcps.sock : dhcps.dnssock); + } + + FD_SET(dhcps.ctrlsock, &rfds); + max_sock = (dhcps.sock > dhcps.ctrlsock ? + dhcps.sock : dhcps.ctrlsock); + + ret = lwip_select(max_sock + 1, &rfds, NULL, NULL, NULL); + + /* Error in select? */ + if (ret < 0) { + dhcp_e("select failed\r\n", -1); + goto done; + } + + if (FD_ISSET(dhcps.sock, &rfds)) { + len = lwip_recvfrom(dhcps.sock, dhcps.msg, + SERVER_BUFFER_SIZE, + 0, (struct sockaddr *)&caddr, &flen); + if (len > 0) { + dhcp_d("recved msg on dhcp sock len: %d\r\n", len); + process_dhcp_message(dhcps.msg, len); + } + } + + if ( dhcp_nack_dns_server_handler ) + { + if (FD_ISSET(dhcps.dnssock, &rfds)) { + len = lwip_recvfrom(dhcps.dnssock, dhcps.msg, + SERVER_BUFFER_SIZE, + 0, (struct sockaddr *)&caddr, &flen); + if (len > 0) { + dhcp_d("recved msg on dns sock len: %d\r\n", len); + dhcp_nack_dns_server_handler(dhcps.msg, len, + &caddr); + } + } + } + + if ( FD_ISSET(dhcps.ctrlsock, &rfds) ) + { + len = lwip_recvfrom(dhcps.ctrlsock, dhcps.msg, + SERVER_BUFFER_SIZE, + 0, (struct sockaddr *)&caddr, &flen); + if ( len > 0 ) + { + if ( os_strcmp(dhcps.msg, "HALT") == 0 ) + { + goto done; + } + } + } + } + +done: + dhcp_clean_sockets(); + rtos_unlock_mutex(&dhcpd_mutex); + rtos_delete_thread(NULL); +} + +static int create_and_bind_udp_socket(struct sockaddr_in *address, + void *intrfc_handle) +{ + int one = 1; + int ret; + + int sock = lwip_socket(PF_INET, SOCK_DGRAM, 0); + if (sock == -1) { + dhcp_e("failed to create a socket\r\n"); + return -1; + } + + ret = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&one, + sizeof(int)); + if (ret == -1) { + /* This is unimplemented in lwIP, hence do not return */ + dhcp_e("failed to set SO_REUSEADDR\r\n"); + } + + if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, + (char *)&one, sizeof(one)) == -1) { + dhcp_e("failed to set SO_BROADCAST\r\n"); + lwip_close(sock); + return -1; + } + + ret = lwip_bind(sock, (struct sockaddr *)address, + sizeof(struct sockaddr)); + + if (ret) { + dhcp_e("failed to bind server socket\r\n"); + dhcp_e("socket err: %d\r\n", errno); + lwip_close(sock); + return -1; + } + return sock; +} + +int dhcp_server_init(void *intrfc_handle) +{ + int ret = 0; + + memset(&dhcps, 0, sizeof(dhcps)); + dhcps.msg = (char*)os_mem_alloc(SERVER_BUFFER_SIZE); + if (dhcps.msg == NULL) + return -1; + ret = rtos_init_mutex(&dhcpd_mutex); + if (ret != 0) + return -1; + + get_broadcast_addr(&dhcps.baddr); + dhcps.baddr.sin_port = htons(DHCP_CLIENT_PORT); + + get_broadcast_addr(&dhcps.uaddr); + dhcps.uaddr.sin_port = htons(DHCP_CLIENT_PORT); + + if (get_ip_addr_from_interface(&dhcps.my_ip, intrfc_handle) < 0) { + dhcp_e("failed to look up our IP address from interface\r\n"); + ret = -1; + goto out; + } + + if (get_netmask_from_interface(&dhcps.netmask, intrfc_handle) < 0) { + dhcp_e("failed to look up our netmask from interface\r\n"); + ret = -1; + goto out; + } + + if (get_gateway_from_interface(&dhcps.router_ip, intrfc_handle) < 0) { + dhcp_e("failed to look up our netmask from interface\r\n"); + ret = -1; + goto out; + } + + + dhcps.saddr.sin_family = AF_INET; +#if 1 + dhcps.saddr.sin_addr.s_addr = dhcps.my_ip; /* Added by Tuya */ +#else + dhcps.saddr.sin_addr.s_addr = INADDR_ANY; +#endif + dhcps.saddr.sin_port = htons(DHCP_SERVER_PORT); + dhcps.sock = create_and_bind_udp_socket(&dhcps.saddr, intrfc_handle); + + if (dhcps.sock < 0) { + ret = -1; + goto out; + } + + if (dhcp_nack_dns_server_handler) { + dhcps.dnsaddr.sin_family = AF_INET; +#if 1 + dhcps.dnsaddr.sin_addr.s_addr = dhcps.my_ip; /* Added by Tuya */ +#else + dhcps.dnsaddr.sin_addr.s_addr = INADDR_ANY; +#endif + dhcps.dnsaddr.sin_port = htons(NAMESERVER_PORT); + dhcps.dnssock = create_and_bind_udp_socket(&dhcps.dnsaddr, + intrfc_handle); + if (dhcps.dnssock < 0) + return -1; + } + + dhcps.ctrladdr.sin_family = AF_INET; + dhcps.ctrladdr.sin_addr.s_addr = inet_addr("127.0.0.1"); + dhcps.ctrladdr.sin_port = htons(CTRL_PORT); + dhcps.ctrlsock = create_and_bind_udp_socket(&dhcps.ctrladdr, + intrfc_handle); + if ( dhcps.ctrlsock < 0 ) + { + ret = -1; + goto out; + } + + dhcps.prv = intrfc_handle; + + dhcps.current_ip = ntohl(dhcps.my_ip & dhcps.netmask) | ((99) & ntohl(~dhcps.netmask)); + //os_printf("[abc] %x, %x, %x\r\n", dhcps.current_ip, dhcps.my_ip, dhcps.router_ip); + + return 0; + +out: + os_mem_free(dhcps.msg); + dhcps.msg = NULL; + rtos_deinit_mutex(&dhcpd_mutex); + return ret; +} + +void dhcp_enable_nack_dns_server(void) +{ + dhcp_nack_dns_server_handler = process_dns_message; +} + +static int send_ctrl_msg(const char *msg) +{ + int ret; + + ret = lwip_sendto(dhcps.ctrlsock, msg, os_strlen(msg)+1, 0, + (struct sockaddr *)&dhcps.ctrladdr, sizeof(struct sockaddr_in)); + + return ret; +} + +int dhcp_send_halt(void) +{ + int ret; + + ret = send_ctrl_msg("HALT"); + if ( ret < 0 ) + { + dhcp_w("Failed to send HALT: %d.\r\n", ret); + return -1; + } + + ret = dhcp_free_allocations(); + + return ret; +} + +int dhcp_free_allocations(void) +{ + /* Wait for 10 seconds */ + rtos_lock_mutex(&dhcpd_mutex); + + dhcp_clean_sockets(); + + rtos_unlock_mutex(&dhcpd_mutex); + + if (dhcps.msg) { + os_mem_free(dhcps.msg); + dhcps.msg = NULL; + } + return rtos_deinit_mutex(&dhcpd_mutex); +} + +static int send_gratuitous_arp(uint32_t ip) +{ + int sock; + struct arp_packet pkt; + struct sockaddr_in to_addr; + to_addr.sin_family = AF_INET; + to_addr.sin_addr.s_addr = ip; + pkt.frame_type = htons(ARP_FRAME_TYPE); + pkt.hw_type = htons(ETHER_HW_TYPE); + pkt.prot_type = htons(IP_PROTO_TYPE); + pkt.hw_addr_size = ETH_HW_ADDR_LEN; + pkt.prot_addr_size = IP_ADDR_LEN; + pkt.op = htons(OP_ARP_REQUEST); + + write_u32(pkt.sndr_ip_addr, ip); + write_u32(pkt.rcpt_ip_addr, ip); + + memset(pkt.targ_hw_addr, 0xff, ETH_HW_ADDR_LEN); + memset(pkt.rcpt_hw_addr, 0xff, ETH_HW_ADDR_LEN); + get_mac_addr_from_interface((void*)pkt.sndr_hw_addr, dhcps.prv); + get_mac_addr_from_interface((void*)pkt.src_hw_addr, dhcps.prv); + + sock = lwip_socket(AF_INET, SOCK_DGRAM, 0); + if (sock < 0) { + dhcp_e("Could not open socket to send Gratuitous ARP\r\n"); + return -1; + } + memset(pkt.padding, 0, sizeof(pkt.padding)); + + if (lwip_sendto(sock, (char *)&pkt, sizeof(pkt), 0, + (struct sockaddr *)&to_addr, sizeof(to_addr)) < 0) { + dhcp_e("Failed to send Gratuitous ARP\r\n"); + lwip_close(sock); + return -1; + } + dhcp_d("Gratuitous ARP sent\r\n"); + lwip_close(sock); + return 0; +} + +static void get_broadcast_addr(struct sockaddr_in *addr) +{ + addr->sin_family = AF_INET; + /* limited broadcast addr (255.255.255.255) */ + addr->sin_addr.s_addr = 0xffffffff; + addr->sin_len = sizeof(struct sockaddr_in); +} + +static int get_mac_addr_from_interface(void *mac, void *interface_handle) +{ + return net_get_if_macaddr(mac, interface_handle); +} + +static int get_ip_addr_from_interface(uint32_t *ip, void *interface_handle) +{ + return net_get_if_ip_addr(ip, interface_handle); +} + +static int get_netmask_from_interface(uint32_t *nm, void *interface_handle) +{ + return net_get_if_ip_mask(nm, interface_handle); +} + +static int get_gateway_from_interface(uint32_t *gw, void *interface_handle) +{ + return net_get_if_gw_addr(gw, interface_handle); +} + +uint8_t* dhcp_lookup_mac(uint8_t *chaddr) +{ + /* returns ip address, if mac address is present in cache */ + int i; + struct in_addr ip; + for (i = 0; i < dhcps.count_clients && i < MAC_IP_CACHE_SIZE; i++) { + if ((dhcps.ip_mac_mapping[i].client_mac[0] == chaddr[0]) && + (dhcps.ip_mac_mapping[i].client_mac[1] == chaddr[1]) && + (dhcps.ip_mac_mapping[i].client_mac[2] == chaddr[2]) && + (dhcps.ip_mac_mapping[i].client_mac[3] == chaddr[3]) && + (dhcps.ip_mac_mapping[i].client_mac[4] == chaddr[4]) && + (dhcps.ip_mac_mapping[i].client_mac[5] == chaddr[5])) { + + ip.s_addr = dhcps.ip_mac_mapping[i].client_ip; + + return (uint8_t*)inet_ntoa(ip); + } + } + return 0; +} \ No newline at end of file diff --git a/beken_os/beken378/func/lwip_intf/dhcpd/dns.h b/beken_os/beken378/func/lwip_intf/dhcpd/dns.h new file mode 100755 index 0000000..396b5d5 --- /dev/null +++ b/beken_os/beken378/func/lwip_intf/dhcpd/dns.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2008-2015, Marvell International Ltd. + * All Rights Reserved. + */ +#ifndef __DNS_H__ +#define __DNS_H__ + +struct dns_header { + uint16_t id; + union { + struct { + uint16_t rcode:4, /* response code */ + cd:1, /* checking disabled RFC-2535 */ + ad:1, /* authentic data RFC-2535 */ + z:1, /* zero */ + ra:1, /* recursion available */ + rd:1, /* recursion desired */ + tc:1, /* truncated */ + aa:1, /* authoritative answer */ + opcode:4, /* (should be 0 for normal DNS messages) */ + qr:1; /* query/response */ + } fields ; + uint16_t num; + } flags ; + uint16_t num_questions; + uint16_t answer_rrs; + uint16_t authority_rrs; + uint16_t additional_rrs; +} __attribute__((packed)); + +struct dns_question { + /* query name (label) field */ + uint16_t type; + uint16_t class; +} __attribute__((packed)); + +struct dns_rr { + uint16_t name_ptr; /* pointer to name */ + uint16_t type; /* resource type */ + uint16_t class; /* resource class */ + uint32_t ttl; /* time to live */ + uint16_t rdlength; /* resource data length */ + uint32_t rd; /* resource data: we only provide a + 4-byte data response (an IP + address) but this is actually a + field of length rdlength */ +} __attribute__((packed)); + +#endif /* __DNS_H__ */ diff --git a/beken_os/beken378/func/lwip_intf/platform_stub.c b/beken_os/beken378/func/lwip_intf/platform_stub.c new file mode 100755 index 0000000..56a76e8 --- /dev/null +++ b/beken_os/beken378/func/lwip_intf/platform_stub.c @@ -0,0 +1,69 @@ +/** + ****************************************************************************** + * @file platform_init.c + * @version V1.0.0 + * @date 05-May-2014 + * @brief This file provide functions called by _BK_ to drive stm32f2xx + * platform: - e.g. power save, reboot, platform initialize + ****************************************************************************** + * UNPUBLISHED PROPRIETARY SOURCE CODE + * Copyright (c) 2016 BEKEN Inc. + * + * The contents of this file may not be disclosed to third parties, copied or + * duplicated in any form, in whole or in part, without the prior written + * permission of BEKEN Corporation. + ****************************************************************************** + */ +#include "include.h" +#include +#include +#include + +#include "sys_rtos.h" +#include "mem_pub.h" + +/************** wrap C library functions **************/ +void * __wrap_malloc (size_t size) +{ + return pvPortMalloc(size); +} + +void * __wrap__malloc_r (void *p, size_t size) +{ + + return pvPortMalloc(size); +} + +void __wrap_free (void *pv) +{ + vPortFree(pv); +} + +void * __wrap_calloc (size_t a, size_t b) +{ + void *pvReturn; + + pvReturn = pvPortMalloc( a*b ); + if (pvReturn) + { + os_memset(pvReturn, 0, a*b); + } + + return pvReturn; +} + +void * __wrap_realloc (void* pv, size_t size) +{ + return pvPortRealloc(pv, size); +} + +void __wrap__free_r (void *p, void *x) +{ + __wrap_free(x); +} + +void* __wrap__realloc_r (void *p, void* x, size_t sz) +{ + return __wrap_realloc (x, sz); +} + diff --git a/beken_os/beken378/func/lwip_intf/tcp_server.c b/beken_os/beken378/func/lwip_intf/tcp_server.c new file mode 100755 index 0000000..38da828 --- /dev/null +++ b/beken_os/beken378/func/lwip_intf/tcp_server.c @@ -0,0 +1,386 @@ +/** + ****************************************************************************** + * @file tcp_server.c + * @version V1.0.0 + * @date 21-May-2015 + * @brief tcp server Demo + ****************************************************************************** + * + * The MIT License + * Copyright (c) 2014 BEKEN Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR + * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + ****************************************************************************** + */ + +#include "include.h" +#include "rtos_pub.h" +#include "rtos_error.h" +#include "lwip/sockets.h" +#include "mem_pub.h" +#include "str_pub.h" + +#define tcp_server_log(M, ...) os_printf("TCP", M, ##__VA_ARGS__) + +#define SERVER_PORT 20000 /*set up a tcp server,port at 20000*/ + +int my_fd = -1; + + +int unw_recv(const int fd, void *buf, u32 nbytes) +{ + fd_set readfds, errfds; + int ret = 0; + + if( fd < 0 ) + { + return -1;//UNW_FAIL; + } + + FD_ZERO( &readfds ); + FD_ZERO( &errfds ); + FD_SET( fd, &readfds ); + FD_SET( fd, &errfds ); + + ret = select( fd+1, &readfds, NULL, &errfds, NULL); + os_printf("select ret:%d, %d, %d\r\n", ret, FD_ISSET( fd, &readfds ), FD_ISSET( fd, &errfds )); + + if(ret > 0 && FD_ISSET( fd, &readfds )) + return recv(fd,buf,nbytes,0); + else + return -1;//UNW_FAIL; + +} + +void tcp_client_thread( beken_thread_arg_t arg ) +{ + OSStatus err = kNoErr; + int fd = (int) arg; + int len = 0; + fd_set readfds, errfds, readfds2; + char *buf = NULL; + + my_fd = fd; + + buf = (char*) os_malloc( 1024 ); + ASSERT(buf); + + #if CFG_USE_TUYA_CCA_TEST + for(int i=0; i<1024; i++) + { + buf[i] = i & 0xff; + } + #endif + + while ( 1 ) + { + + { + #if !CFG_USE_TUYA_CCA_TEST + len = recv( fd, buf, 1024, 0 ); + + if ( len <= 0 ) + { + os_printf( "TCP Client is disconnected, fd: %d", fd ); + goto exit; + } + #else + len = 1024; + #endif + + len = send( fd, buf, len, 0 ); + + #if CFG_USE_TUYA_CCA_TEST + rtos_delay_milliseconds(10); + #endif + } + } + +exit: + if ( err != kNoErr ) + tcp_server_log( "TCP client thread exit with err: %d", err ); + + if ( buf != NULL ) + os_free( buf ); + + close( fd ); + rtos_delete_thread( NULL ); +} + +volatile u8 test_flag = 0; +void close_tcp_client(void) +{ + os_printf("close_tcp_client:%d, %p\r\n", my_fd, rtos_get_current_thread()); + test_flag = 1; + close( my_fd ); + my_fd = -1; +} + +/* TCP server listener thread */ +void tcp_server_thread( beken_thread_arg_t arg ) +{ + (void)( arg ); + OSStatus err = kNoErr; + struct sockaddr_in server_addr, client_addr; + socklen_t sockaddr_t_size = sizeof(client_addr); + char client_ip_str[16]; + int tcp_listen_fd = -1, client_fd = -1; + fd_set readfds; + + tcp_listen_fd = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ); + + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = INADDR_ANY;/* Accept conenction request on all network interface */ + server_addr.sin_port = htons( SERVER_PORT );/* Server listen on port: 20000 */ + err = bind( tcp_listen_fd, (struct sockaddr *) &server_addr, sizeof(server_addr) ); + + err = listen( tcp_listen_fd, 0 ); + + while ( 1 ) + { + FD_ZERO( &readfds ); + FD_SET( tcp_listen_fd, &readfds ); + + select( tcp_listen_fd + 1, &readfds, NULL, NULL, NULL); + + if ( FD_ISSET( tcp_listen_fd, &readfds ) ) + { + client_fd = accept( tcp_listen_fd, (struct sockaddr *) &client_addr, &sockaddr_t_size ); + if ( client_fd >= 0 ) + { + os_strcpy( client_ip_str, inet_ntoa( client_addr.sin_addr ) ); + tcp_server_log( "TCP Client %s:%d connected, fd: %d", client_ip_str, client_addr.sin_port, client_fd ); + if ( kNoErr + != rtos_create_thread( NULL, BEKEN_APPLICATION_PRIORITY, + "TCP Clients", + (beken_thread_function_t)tcp_client_thread, + 0x800, + (beken_thread_arg_t)client_fd ) ) + { + close( client_fd ); + client_fd = -1; + } + } + } + } + + if ( err != kNoErr ) + tcp_server_log( "Server listerner thread exit with err: %d", err ); + + close( tcp_listen_fd ); + rtos_delete_thread( NULL ); +} + +void make_tcp_server_command(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + OSStatus err = kNoErr; + + err = rtos_create_thread( NULL, BEKEN_APPLICATION_PRIORITY, + "TCP_server", + (beken_thread_function_t)tcp_server_thread, + 0x800, + (beken_thread_arg_t)0 ); + if(err != kNoErr) + { + os_printf("create \"TCP_server\" thread failed!\r\n"); + } +} + +#if CFG_USE_TUYA_CCA_TEST +#include "udp_server_demo.h" +#include "include.h" + +#include "rtos_pub.h" +#include "doubly_list.h" +#include "mem_pub.h" +#include "str_pub.h" +#include "lwip/sockets.h" +#include "BkDriverUart.h" +#include "Error.h" +#include "uart_pub.h" +#include "lwip/sockets.h" +#include "lwip/ip_addr.h" +#include "lwip/inet.h" + +#define UDP_LISTENER_PORT 55000 + +char * gbuf; +int udp_listen_fd = -1; +int client_udp_flag = 0; + +void show_udp_recv(char *buf, unsigned int len) +{ + while(len--) + { + os_printf("%02x", *buf++); + } + os_printf("\r\n"); +} + +void udp_client_thread( beken_thread_arg_t arg ) +{ + OSStatus err = kNoErr; + struct sockaddr_in client_addr; + int len = 0; + fd_set readfds, errfds, readfds2; + char *buf = NULL; + + buf = gbuf; + os_memcpy(&client_addr, arg, sizeof(struct sockaddr_in)); + + for(int i=0; i<1024; i++) + { + buf[i] = i & 0xff; + } + + + while ( 1 ) + { + + { + #if 0 + len = recv( fd, buf, 1024, 0 ); + + if ( len <= 0 ) + { + os_printf( "TCP Client is disconnected, fd: %d", fd ); + goto exit; + } + #else + len = 1024; + #endif + + len = sendto( udp_listen_fd, buf, len, 0 , (struct sockaddr *)&client_addr, sizeof(client_addr)); + + rtos_delay_milliseconds(10); + } + } + +exit: + + client_udp_flag = 0; + rtos_delete_thread( NULL ); +} + + +/* TCP server listener thread */ +void udp_server_thread( beken_thread_arg_t arg ) +{ + + struct sockaddr_in server_addr, client_addr; + socklen_t client_addr_len = sizeof(client_addr); + OSStatus err = kNoErr; + char *buf = NULL; + int len = 0; + fd_set readfds; + + buf = (char *) os_malloc( 1024 ); + if(buf == NULL) + { + os_printf("buf == NULL\r\n"); + goto exit; + } + gbuf = buf; + + udp_listen_fd = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP );//Make UDP socket + if(udp_listen_fd == -1) + { + os_printf("udp_listen_fd == -1\r\n"); + goto exit; + } + + server_addr.sin_family = AF_INET; + server_addr.sin_addr.s_addr = INADDR_ANY; + server_addr.sin_port = htons(UDP_LISTENER_PORT); + + err = bind( udp_listen_fd, (struct sockaddr *) &server_addr, sizeof(server_addr) ); + + while ( 1 ) + { + FD_ZERO( &readfds ); + FD_SET( udp_listen_fd, &readfds ); + + select( udp_listen_fd + 1, &readfds, NULL, NULL, NULL); + + if ( FD_ISSET( udp_listen_fd, &readfds ) ) + { + if ( FD_ISSET( udp_listen_fd, &readfds ) ) /*one client has data*/ + { + len = recvfrom( udp_listen_fd, buf, 1024, 0 , (struct sockaddr *) &client_addr, &client_addr_len); + #if 0 + //show_udp_recv(buf, len); + if(len) + { + len = sendto( udp_listen_fd, buf, len, 0 , (struct sockaddr *) &client_addr, sizeof(client_addr)); + } + #else + if(client_udp_flag == 1) + continue; + + client_udp_flag = 1; + if ( kNoErr + != rtos_create_thread( NULL, BEKEN_APPLICATION_PRIORITY, + "UDP Clients", + (beken_thread_function_t)udp_client_thread, + 0x800, + (beken_thread_arg_t)&client_addr ) ) + { + client_udp_flag = 0; + } + + #endif + } + } + } + +exit: + if ( err != kNoErr ) + { + os_printf( "Server listener thread exit with err: %d", err ); + } + + if(udp_listen_fd) + { + close( udp_listen_fd ); + } + + if(buf) + { + os_free(buf); + } + + rtos_delete_thread( NULL ); +} + + +int demo_start_upd( void ) +{ + OSStatus err = kNoErr; + + err = rtos_create_thread( NULL, BEKEN_APPLICATION_PRIORITY, + "udp_server", + (beken_thread_function_t)udp_server_thread, + 0x800, + (beken_thread_arg_t)0 ); + return err; +} + + + +#endif + diff --git a/beken_os/beken378/func/misc/fake_clock.c b/beken_os/beken378/func/misc/fake_clock.c new file mode 100755 index 0000000..44f741a --- /dev/null +++ b/beken_os/beken378/func/misc/fake_clock.c @@ -0,0 +1,391 @@ +#include "include.h" +#include "fake_clock_pub.h" +#if (CFG_SOC_NAME == SOC_BK7231) +#include "pwm_pub.h" +#else +#include "bk_timer_pub.h" +#endif +#include "icu_pub.h" +#include "drv_model_pub.h" +#include "uart_pub.h" + +#if CFG_SUPPORT_ALIOS +#include "rtos_pub.h" +#include "ll.h" +#include "k_api.h" +#else +#include "sys_rtos.h" +#include "arm_arch.h" +#endif +#include "power_save_pub.h" + +#if CFG_USE_MCU_PS +#include "mcu_ps_pub.h" +#endif + +#if CFG_BK7221_MDM_WATCHDOG_PATCH +void rc_reset_patch(void); +#endif + +static volatile UINT64 current_us = 0; +static volatile UINT32 current_clock = 0; +static volatile UINT32 current_seconds = 0; +static UINT32 second_countdown = FCLK_SECOND; + +extern void mcu_ps_increase_clr(void); +#define ONE_CAL_TIME 15000 + +typedef struct +{ + UINT32 fclk_tick; + UINT32 tmp1; +} CAL_TICK_T; +static CAL_TICK_T cal_tick_save; +UINT32 use_cal_net = 0; + +extern uint32_t mcu_ps_need_pstick(void); + +void fclk_hdl(UINT8 param) +{ + GLOBAL_INT_DECLARATION(); +#if CFG_USE_STA_PS + if(power_save_use_pwm_isr()) + { + power_save_pwm_isr(param); + return; + } + + if(!mcu_ps_need_pstick()) + { + return; + } +#endif + +#if CFG_BK7221_MDM_WATCHDOG_PATCH + rc_reset_patch(); +#endif + +#if (!CFG_SUPPORT_ALIOS) + /* Increment the tick counter. */ + GLOBAL_INT_DISABLE(); + current_clock ++; + + if (--second_countdown == 0) + { + current_seconds ++; + second_countdown = FCLK_SECOND; + } + + if( xTaskIncrementTick() != pdFALSE ) + { + /* Select a new task to run. */ + vTaskSwitchContext(); + } + + GLOBAL_INT_RESTORE(); +#endif + +#ifdef BEKEN_START_WDT + /* fresh watch dog if needed */ + if(current_seconds % 5) + { + bk_wdg_reload(); + } +#endif + +#if CFG_SUPPORT_ALIOS + krhino_tick_proc(); +#endif +} + +static UINT32 fclk_freertos_update_tick(UINT32 tick) +{ + current_clock += tick; + + while(tick >= FCLK_SECOND) + { + current_seconds ++; + tick -= FCLK_SECOND; + } + + if(second_countdown <= tick) + { + current_seconds ++; + second_countdown = FCLK_SECOND - (tick - second_countdown); + } + else + { + second_countdown -= tick; + } + + return 0; +} + +UINT32 fclk_update_tick(UINT32 tick) +{ +#if (CFG_SUPPORT_RTT) + rtt_update_tick(tick); +#elif (CFG_SUPPORT_ALIOS) + krhino_update_sys_tick((UINT64)tick); +#else + GLOBAL_INT_DECLARATION(); + + if(tick == 0) + return 0; + + GLOBAL_INT_DISABLE(); +#if CFG_USE_MCU_PS + mcu_ps_increase_clr(); +#endif + fclk_freertos_update_tick(tick); + vTaskStepTick( tick ); + GLOBAL_INT_RESTORE(); + +#endif + return 0; +} + +UINT32 fclk_freertos_get_tick(void) +{ + return current_clock; +} + +UINT64 fclk_get_tick(void) +{ + UINT64 fclk; +#if (CFG_SUPPORT_RTT) + fclk = (UINT64)rt_tick_get(); +#elif (CFG_SUPPORT_ALIOS) + fclk = krhino_sys_tick_get(); +#else + fclk = (UINT64)fclk_freertos_get_tick(); +#endif + return fclk; +} + +UINT32 fclk_get_second(void) +{ +#if (CFG_SUPPORT_RTT) + return (rt_tick_get()/FCLK_SECOND); +#elif (CFG_SUPPORT_ALIOS) + return (krhino_sys_tick_get()/FCLK_SECOND); +#else + return current_clock/FCLK_SECOND; +#endif +} + +UINT32 fclk_from_sec_to_tick(UINT32 sec) +{ + return sec * FCLK_SECOND; +} + +void fclk_reset_count(void) +{ + current_clock = 0; + current_seconds = 0; +} + +UINT32 timer_cal_init(void) +{ + UINT32 fclk; + + fclk = BK_TICKS_TO_MS(fclk_get_tick()); + + cal_tick_save.fclk_tick = fclk; + cal_tick_save.tmp1 = 0; + return 0; +} + +extern int increase_tick; +UINT32 timer_cal_tick(void) +{ + UINT32 fclk, tmp2; + INT32 lost; + GLOBAL_INT_DECLARATION(); + + GLOBAL_INT_DISABLE(); + + fclk = BK_TICKS_TO_MS(fclk_get_tick()); + cal_tick_save.tmp1 += ONE_CAL_TIME; + + tmp2 = fclk; + + lost = (INT32)(cal_tick_save.tmp1 - (UINT32)tmp2); + + if((lost >= (2*FCLK_DURATION_MS))) + { + if(lost > 200) + { + //os_printf("m cal_:%x %x\r\n", lost, machw); + } + + lost -= FCLK_DURATION_MS; + fclk_update_tick(BK_MS_TO_TICKS(lost)); + increase_tick = 0; + } + #if 1 + else + { + if(lost <= (-(2*FCLK_DURATION_MS))) + { + if(lost < (-50000)) + { + os_printf("m reset:%x %x\r\n", lost); + } + increase_tick = lost + FCLK_DURATION_MS; + } + } + #endif + //os_printf("tc:%d\r\n",lost); + +#if CFG_USE_MCU_PS + mcu_ps_machw_init(); +#endif + GLOBAL_INT_RESTORE(); + return 0 ; + +///CAL_RESET: + timer_cal_init(); + GLOBAL_INT_RESTORE(); + return 0 ; +} + + +void cal_timer_hdl(UINT8 param) +{ +#if CFG_USE_MCU_PS + timer_cal_tick(); +#endif +} + +void cal_timer_set(void) +{ + timer_param_t param; + UINT32 ret; + UINT32 timer_channel; + + timer_cal_init(); + + param.channel = CAL_TIMER_ID; + param.div = 1; + param.period = ONE_CAL_TIME; + param.t_Int_Handler= cal_timer_hdl; + + ret = sddev_control(TIMER_DEV_NAME, CMD_TIMER_INIT_PARAM, ¶m); + ASSERT(BK_TIMER_SUCCESS == ret); + timer_channel = param.channel; + ret = sddev_control(TIMER_DEV_NAME, CMD_TIMER_UNIT_ENABLE, &timer_channel); + ASSERT(BK_TIMER_SUCCESS == ret); +} + +void cal_timer_deset(void) +{ + UINT32 ret; + UINT32 timer_channel; + + timer_channel = CAL_TIMER_ID; + ret = sddev_control(TIMER_DEV_NAME, CMD_TIMER_UNIT_DISABLE, &timer_channel); + ASSERT(BK_TIMER_SUCCESS == ret); + timer_cal_init(); +} + +UINT32 bk_cal_init(UINT32 setting) +{ + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + + if(1 == setting) + { + cal_timer_deset(); + use_cal_net = 1; +#if CFG_USE_MCU_PS + mcu_ps_machw_init(); +#endif + os_printf("decset:%d %d %d %d\r\n",use_cal_net,current_clock,fclk_get_second(),xTaskGetTickCount()); + } + else + { +#if CFG_USE_MCU_PS + mcu_ps_machw_cal(); +#endif + cal_timer_set(); + use_cal_net = 0; +#if CFG_USE_MCU_PS + mcu_ps_machw_reset(); +#endif + os_null_printf("cset:%d %d %d %d\r\n",use_cal_net,current_clock,fclk_get_second(),xTaskGetTickCount()); + } + GLOBAL_INT_RESTORE(); + + return 0; +} + +#if (CFG_SOC_NAME == SOC_BK7231) +UINT32 fclk_cal_endvalue(UINT32 mode) +{ + UINT32 value = 1; + + if(PWM_CLK_32K == mode) + { + /*32k clock*/ + value = FCLK_DURATION_MS * 32; + } + else if(PWM_CLK_26M == mode) + { + /*26m clock*/ +#if CFG_SUPPORT_ALIOS + value = 26000000 / RHINO_CONFIG_TICKS_PER_SECOND; +#else + value = FCLK_DURATION_MS * 26000; +#endif + } + + return value; +} +#endif + +void fclk_init(void) +{ + UINT32 ret; + #if (CFG_SOC_NAME == SOC_BK7231) + pwm_param_t param; + + /*init pwm*/ + param.channel = FCLK_PWM_ID; + param.cfg.bits.en = PWM_ENABLE; + param.cfg.bits.int_en = PWM_INT_EN; + param.cfg.bits.mode = PWM_TIMER_MODE; + +#if(CFG_RUNNING_PLATFORM == FPGA_PLATFORM) // FPGA:PWM0-2-32kCLK, pwm3-5-24CLK + param.cfg.bits.clk = PWM_CLK_32K; +#else + param.cfg.bits.clk = PWM_CLK_26M; +#endif + + param.p_Int_Handler = fclk_hdl; + param.duty_cycle = 0; + param.end_value = fclk_cal_endvalue((UINT32)param.cfg.bits.clk); + + ret = sddev_control(PWM_DEV_NAME, CMD_PWM_INIT_PARAM, ¶m); + ASSERT(PWM_SUCCESS == ret); + #else + timer_param_t param; + param.channel = FCLK_TIMER_ID; + param.div = 1; + param.period = FCLK_DURATION_MS; + param.t_Int_Handler= fclk_hdl; + + ret = sddev_control(TIMER_DEV_NAME, CMD_TIMER_INIT_PARAM, ¶m); + ASSERT(BK_TIMER_SUCCESS == ret); + UINT32 timer_channel; + timer_channel = param.channel; + ret = sddev_control(TIMER_DEV_NAME, CMD_TIMER_UNIT_ENABLE, &timer_channel); + ASSERT(BK_TIMER_SUCCESS == ret); + + bk_cal_init(0); + #endif + +} + +// eof + diff --git a/beken_os/beken378/func/misc/pseudo_random.c b/beken_os/beken378/func/misc/pseudo_random.c new file mode 100755 index 0000000..f29f780 --- /dev/null +++ b/beken_os/beken378/func/misc/pseudo_random.c @@ -0,0 +1,10 @@ +#include "include.h" +#include "reg_mac_core.h" + +uint32_t prandom_get(void) +{ + return nxmac_monotonic_counter_2_lo_get(); +} + +// eof + diff --git a/beken_os/beken378/func/misc/soft_encrypt.c b/beken_os/beken378/func/misc/soft_encrypt.c new file mode 100755 index 0000000..427fd1b --- /dev/null +++ b/beken_os/beken378/func/misc/soft_encrypt.c @@ -0,0 +1,818 @@ +#include "soft_encrypt.h" +#include + +#if (0 == WEENY_AES_ROM_TABLES) +#include "mem_pub.h" +#include "uart_pub.h" +#endif + +char xor_key[XOR_KEY_COUNT] = {0x55, 0xaa, 0x5a, 0x55, 0xa5, 77, 99, 127}; +int xor_key_id = 0; + +void xor_key_init(void) +{ + xor_key_id = 0; +} + +char xor_get_key(void) +{ + return xor_key[(xor_key_id ++) & (XOR_KEY_COUNT - 1)]; +} + +void xor_enc(void *in, void *out, int len) +{ + int i; + char *input = (char *)in; + char *output = (char *)out; + + xor_key_init(); + for (i = 0; i < len; i ++) + output[i] = input[i] ^ xor_get_key(); +} + +void xor_dec(void *in, void *out, int len) +{ + xor_enc(in, out, len); +} + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef GET_ULONG_LE +#define GET_ULONG_LE(n,b,i) \ + { \ + (n) = ( (unsigned long) (b)[(i) ] ) \ + | ( (unsigned long) (b)[(i) + 1] << 8 ) \ + | ( (unsigned long) (b)[(i) + 2] << 16 ) \ + | ( (unsigned long) (b)[(i) + 3] << 24 ); \ + } +#endif + +#ifndef PUT_ULONG_LE +#define PUT_ULONG_LE(n,b,i) \ + { \ + (b)[(i) ] = (unsigned char) ( (n) ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \ + } +#endif + +#if WEENY_AES_ROM_TABLES +/* + * Forward S-box + */ +static 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 unsigned long FT0[256] = { FT }; + +#undef V + +#define V(a,b,c,d) 0x##b##c##d##a +static unsigned long FT1[256] = { FT }; + +#undef V + +#define V(a,b,c,d) 0x##c##d##a##b +static unsigned long FT2[256] = { FT }; + +#undef V + +#define V(a,b,c,d) 0x##d##a##b##c +static unsigned long FT3[256] = { FT }; + +#undef V + +#undef FT + +/* + * Reverse S-box + */ +static 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 unsigned long RT0[256] = { RT }; + +#undef V + +#define V(a,b,c,d) 0x##b##c##d##a +static unsigned long RT1[256] = { RT }; + +#undef V + +#define V(a,b,c,d) 0x##c##d##a##b +static unsigned long RT2[256] = { RT }; + +#undef V + +#define V(a,b,c,d) 0x##d##a##b##c +static unsigned long RT3[256] = { RT }; + +#undef V + +#undef RT + +/* + * Round constants + */ +static unsigned long RCON[10] = { + 0x00000001, 0x00000002, 0x00000004, 0x00000008, + 0x00000010, 0x00000020, 0x00000040, 0x00000080, + 0x0000001B, 0x00000036 +}; + +#else + +/* + * Forward S-box & tables + */ +static unsigned char FSb[256]; +static unsigned long FT0[256]; +static unsigned long FT1[256]; +static unsigned long FT2[256]; +static unsigned long FT3[256]; + +/* + * Reverse S-box & tables + */ +static unsigned char RSb[256]; +static unsigned long RT0[256]; +static unsigned long RT1[256]; +static unsigned long RT2[256]; +static unsigned long RT3[256]; + +/* + * Round constants + */ +static unsigned long 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, *log; + int *tmp; + + tmp = (int *)os_malloc((POW_LEN + LOG_LEN) * sizeof(pow[0])); + if (NULL == tmp) { + os_printf("aes_gen_tables failed\r\n"); + return; + } + + pow = tmp; + log = &tmp[POW_LEN]; + + /* + * 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] = (unsigned long)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] = ((unsigned long)y) ^ + ((unsigned long)x << 8) ^ + ((unsigned long)x << 16) ^ ((unsigned long)z << 24); + + FT1[i] = ROTL8(FT0[i]); + FT2[i] = ROTL8(FT1[i]); + FT3[i] = ROTL8(FT2[i]); + + x = RSb[i]; + + RT0[i] = ((unsigned long)MUL(0x0E, x)) ^ + ((unsigned long)MUL(0x09, x) << 8) ^ + ((unsigned long)MUL(0x0D, x) << 16) ^ + ((unsigned long)MUL(0x0B, x) << 24); + + RT1[i] = ROTL8(RT0[i]); + RT2[i] = ROTL8(RT1[i]); + RT3[i] = ROTL8(RT2[i]); + } + + if (tmp) { + os_free(tmp); + tmp = NULL; + } +} + +#endif + +/* + * AES key schedule (encryption) + */ +void weeny_aes_setkey_enc(weeny_aes_context *ctx, unsigned char *key, int keysize) +{ + int i; + unsigned long *RK; + +#if !WEENY_AES_ROM_TABLES + if (aes_init_done == 0) { + aes_gen_tables(); + aes_init_done = 1; + } +#endif + + switch (keysize) { + case 128: + ctx->nr = 10; + break; + case 192: + ctx->nr = 12; + break; + case 256: + ctx->nr = 14; + break; + default: + return; + } + + ctx->rk = RK = ctx->buf; + + for (i = 0; i < (keysize >> 5); i++) + GET_ULONG_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] ^ + ((unsigned long)FSb[(RK[3] >> 8) & 0xFF]) ^ + ((unsigned long)FSb[(RK[3] >> 16) & 0xFF] << 8) ^ + ((unsigned long)FSb[(RK[3] >> 24) & 0xFF] << 16) ^ + ((unsigned long)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] ^ + ((unsigned long)FSb[(RK[5] >> 8) & 0xFF]) ^ + ((unsigned long)FSb[(RK[5] >> 16) & 0xFF] << 8) ^ + ((unsigned long)FSb[(RK[5] >> 24) & 0xFF] << 16) ^ + ((unsigned long)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] ^ + ((unsigned long)FSb[(RK[7] >> 8) & 0xFF]) ^ + ((unsigned long)FSb[(RK[7] >> 16) & 0xFF] << 8) ^ + ((unsigned long)FSb[(RK[7] >> 24) & 0xFF] << 16) ^ + ((unsigned long)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] ^ + ((unsigned long)FSb[(RK[11]) & 0xFF]) ^ + ((unsigned long)FSb[(RK[11] >> 8) & 0xFF] << 8) ^ + ((unsigned long)FSb[(RK[11] >> 16) & 0xFF] << 16) ^ + ((unsigned long)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; + + default: + + break; + } +} + +/* + * AES key schedule (decryption) + */ +void weeny_aes_setkey_dec(weeny_aes_context *ctx, unsigned char *key, int keysize) +{ + int i, j; + weeny_aes_context cty; + unsigned long *RK; + unsigned long *SK; + + switch (keysize) { + case 128: + ctx->nr = 10; + break; + case 192: + ctx->nr = 12; + break; + case 256: + ctx->nr = 14; + break; + default: + return; + } + + ctx->rk = RK = ctx->buf; + + weeny_aes_setkey_enc(&cty, key, keysize); + 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++; + + memset(&cty, 0, sizeof(weeny_aes_context)); +} + +#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/decryption + */ +void weeny_aes_crypt_ecb(weeny_aes_context *ctx, + int mode, unsigned char input[16], unsigned char output[16]) +{ + int i; + unsigned long *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; + + RK = ctx->rk; + + GET_ULONG_LE(X0, input, 0); + X0 ^= *RK++; + GET_ULONG_LE(X1, input, 4); + X1 ^= *RK++; + GET_ULONG_LE(X2, input, 8); + X2 ^= *RK++; + GET_ULONG_LE(X3, input, 12); + X3 ^= *RK++; + + if (mode == AES_DECRYPT) { + for (i = (ctx->nr >> 1) - 1; i > 0; i--) { + AES_RROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3); + AES_RROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3); + } + + AES_RROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3); + + X0 = *RK++ ^ + ((unsigned long)RSb[(Y0) & 0xFF]) ^ + ((unsigned long)RSb[(Y3 >> 8) & 0xFF] << 8) ^ + ((unsigned long)RSb[(Y2 >> 16) & 0xFF] << 16) ^ + ((unsigned long)RSb[(Y1 >> 24) & 0xFF] << 24); + + X1 = *RK++ ^ + ((unsigned long)RSb[(Y1) & 0xFF]) ^ + ((unsigned long)RSb[(Y0 >> 8) & 0xFF] << 8) ^ + ((unsigned long)RSb[(Y3 >> 16) & 0xFF] << 16) ^ + ((unsigned long)RSb[(Y2 >> 24) & 0xFF] << 24); + + X2 = *RK++ ^ + ((unsigned long)RSb[(Y2) & 0xFF]) ^ + ((unsigned long)RSb[(Y1 >> 8) & 0xFF] << 8) ^ + ((unsigned long)RSb[(Y0 >> 16) & 0xFF] << 16) ^ + ((unsigned long)RSb[(Y3 >> 24) & 0xFF] << 24); + + X3 = *RK++ ^ + ((unsigned long)RSb[(Y3) & 0xFF]) ^ + ((unsigned long)RSb[(Y2 >> 8) & 0xFF] << 8) ^ + ((unsigned long)RSb[(Y1 >> 16) & 0xFF] << 16) ^ + ((unsigned long)RSb[(Y0 >> 24) & 0xFF] << 24); + } else { /* AES_ENCRYPT */ + for (i = (ctx->nr >> 1) - 1; i > 0; i--) { + AES_FROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3); + AES_FROUND(X0, X1, X2, X3, Y0, Y1, Y2, Y3); + } + + AES_FROUND(Y0, Y1, Y2, Y3, X0, X1, X2, X3); + + X0 = *RK++ ^ + ((unsigned long)FSb[(Y0) & 0xFF]) ^ + ((unsigned long)FSb[(Y1 >> 8) & 0xFF] << 8) ^ + ((unsigned long)FSb[(Y2 >> 16) & 0xFF] << 16) ^ + ((unsigned long)FSb[(Y3 >> 24) & 0xFF] << 24); + + X1 = *RK++ ^ + ((unsigned long)FSb[(Y1) & 0xFF]) ^ + ((unsigned long)FSb[(Y2 >> 8) & 0xFF] << 8) ^ + ((unsigned long)FSb[(Y3 >> 16) & 0xFF] << 16) ^ + ((unsigned long)FSb[(Y0 >> 24) & 0xFF] << 24); + + X2 = *RK++ ^ + ((unsigned long)FSb[(Y2) & 0xFF]) ^ + ((unsigned long)FSb[(Y3 >> 8) & 0xFF] << 8) ^ + ((unsigned long)FSb[(Y0 >> 16) & 0xFF] << 16) ^ + ((unsigned long)FSb[(Y1 >> 24) & 0xFF] << 24); + + X3 = *RK++ ^ + ((unsigned long)FSb[(Y3) & 0xFF]) ^ + ((unsigned long)FSb[(Y0 >> 8) & 0xFF] << 8) ^ + ((unsigned long)FSb[(Y1 >> 16) & 0xFF] << 16) ^ + ((unsigned long)FSb[(Y2 >> 24) & 0xFF] << 24); + } + + PUT_ULONG_LE(X0, output, 0); + PUT_ULONG_LE(X1, output, 4); + PUT_ULONG_LE(X2, output, 8); + PUT_ULONG_LE(X3, output, 12); +} + +/* + * AES-CBC buffer encryption/decryption + */ +void weeny_aes_crypt_cbc(weeny_aes_context *ctx, + int mode, + int length, + unsigned char iv[16], + unsigned char *input, unsigned char *output) +{ + int i; + unsigned char temp[16]; + + if (mode == AES_DECRYPT) { + while (length > 0) { + memcpy(temp, input, 16); + weeny_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]); + + weeny_aes_crypt_ecb(ctx, mode, output, output); + memcpy(iv, output, 16); + + input += 16; + output += 16; + length -= 16; + } + } +} + +/* + * AES-CFB128 buffer encryption/decryption + */ +void weeny_aes_crypt_cfb128(weeny_aes_context *ctx, + int mode, + int length, + int *iv_off, + unsigned char iv[16], + unsigned char *input, unsigned char *output) +{ + int c, n = *iv_off; + + if (mode == AES_DECRYPT) { + while (length--) { + if (n == 0) + weeny_aes_crypt_ecb(ctx, 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) + weeny_aes_crypt_ecb(ctx, AES_ENCRYPT, iv, iv); + + iv[n] = *output++ = (unsigned char)(iv[n] ^ *input++); + + n = (n + 1) & 0x0F; + } + } + + *iv_off = n; +} +//eof diff --git a/beken_os/beken378/func/misc/soft_encrypt.h b/beken_os/beken378/func/misc/soft_encrypt.h new file mode 100755 index 0000000..aca3bdd --- /dev/null +++ b/beken_os/beken378/func/misc/soft_encrypt.h @@ -0,0 +1,103 @@ +#ifndef _SOFT_ENCRYPT_H_ +#define _SOFT_ENCRYPT_H_ + +#define AES_ENCRYPT 1 +#define AES_DECRYPT 0 + +#define WEENY_AES_ROM_TABLES 0 +#define XOR_KEY_COUNT 8 + +#define BK_AES_IV_LEN (16) +#define BK_AES_KEY_LEN (32) +#define BK_TINY_AES_IV "0123456789ABCEEF" +#define BK_TINY_AES_KEY "0123456789ABCEEF0123456789ABCDEF" + +#define POW_LEN (256) +#define LOG_LEN (256) + +/** + * \brief AES context structure + */ +typedef struct { + int nr; /*!< number of rounds */ + unsigned long *rk; /*!< AES round keys */ + unsigned long buf[68]; /*!< unaligned data */ +} weeny_aes_context; + +#ifdef __cplusplus +extern "C" { +#endif + +void xor_enc(void *in, void *out, int len); +void xor_dec(void *in, void *out, int len); + +/** + * \brief AES key schedule (encryption) + * + * \param ctx AES context to be initialized + * \param key encryption key + * \param keysize must be 128, 192 or 256 + */ +void weeny_aes_setkey_enc(weeny_aes_context *ctx, unsigned char *key, int keysize); + +/** + * \brief AES key schedule (decryption) + * + * \param ctx AES context to be initialized + * \param key decryption key + * \param keysize must be 128, 192 or 256 + */ +void weeny_aes_setkey_dec(weeny_aes_context *ctx, unsigned char *key, int keysize); + +/** + * \brief AES-ECB block encryption/decryption + * + * \param ctx AES context + * \param mode AES_ENCRYPT or AES_DECRYPT + * \param input 16-byte input block + * \param output 16-byte output block + */ +void weeny_aes_crypt_ecb(weeny_aes_context *ctx, + int mode, + unsigned char input[16], unsigned char output[16]); + +/** + * \brief AES-CBC buffer encryption/decryption + * + * \param ctx AES context + * \param mode AES_ENCRYPT or 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 + */ +void weeny_aes_crypt_cbc(weeny_aes_context *ctx, + int mode, + int length, + unsigned char iv[16], + unsigned char *input, unsigned char *output); + +/** + * \brief AES-CFB128 buffer encryption/decryption + * + * \param ctx AES context + * \param mode AES_ENCRYPT or AES_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 + */ +void weeny_aes_crypt_cfb128(weeny_aes_context *ctx, + int mode, + int length, + int *iv_off, + unsigned char iv[16], + unsigned char *input, unsigned char *output); + +#ifdef __cplusplus +} +#endif +#endif //_SOFT_ENCRYPT_H_ +// eof + diff --git a/beken_os/beken378/func/misc/start_type.c b/beken_os/beken378/func/misc/start_type.c new file mode 100755 index 0000000..0c5258e --- /dev/null +++ b/beken_os/beken378/func/misc/start_type.c @@ -0,0 +1,195 @@ +#include "include.h" +#include "fake_clock_pub.h" +#include "icu_pub.h" +#include "drv_model_pub.h" +#include "uart_pub.h" +#include "icu.h" +#include "../wdt/wdt.h" +#include "wdt_pub.h" +#include "target_util_pub.h" + +#if CFG_SUPPORT_ALIOS +#include "rtos_pub.h" +#include "ll.h" +#include "k_api.h" +#else +#include "sys_rtos.h" +#include "arm_arch.h" +#endif +#include "sys_ctrl_pub.h" + +#include "start_type_pub.h" + +void bk_misc_crash_xat0_reboot(void) +{ + UINT32 wdt_val = 5; + UINT32 parameter = PWD_ARM_WATCHDOG_CLK_BIT; + + os_printf("xat0_reboot\r\n"); + + GLOBAL_INT_DECLARATION(); + + GLOBAL_INT_DISABLE(); + + icu_ctrl(CMD_CLK_PWR_DOWN, (void *)¶meter); + delay(30000); //100ms + wdt_ctrl(WCMD_SET_PERIOD, &wdt_val); + icu_ctrl(CMD_CLK_PWR_UP, (void *)¶meter); + while(1); + GLOBAL_INT_RESTORE(); + +} + +static RESET_SOURCE_STATUS start_type; +RESET_SOURCE_STATUS bk_misc_get_start_type() +{ + return start_type; +} + +#if (CFG_SOC_NAME == SOC_BK7231N) +extern UINT32 sctrl_ctrl(UINT32 cmd, void *param); +//only can be do once + RESET_SOURCE_STATUS bk_misc_init_start_type(void) +{ + uint32_t misc_value; + sctrl_ctrl(CMD_GET_SCTRL_RETETION, &misc_value); + + if((start_type = sctrl_get_deep_sleep_wake_soure()) == 0) + { + if(0 == (misc_value & SW_RETENTION_WDT_FLAG)) + { + if((uint32_t)CRASH_XAT0_VALUE == + *((volatile uint32_t *)(START_TYPE_DMEMORY_ADDR))) + { + start_type = RESET_SOURCE_CRASH_PER_XAT0; + } + else + { + start_type = RESET_SOURCE_POWERON; + } + } + else + { + switch(misc_value & SW_RETENTION_VAL_MASK) + { + case (RESET_SOURCE_REBOOT & SW_RETENTION_VAL_MASK): + start_type = RESET_SOURCE_REBOOT; + break; + case (CRASH_UNDEFINED_VALUE & SW_RETENTION_VAL_MASK): + start_type = RESET_SOURCE_CRASH_UNDEFINED; + break; + case (CRASH_PREFETCH_ABORT_VALUE & SW_RETENTION_VAL_MASK): + start_type = RESET_SOURCE_CRASH_PREFETCH_ABORT; + break; + case (CRASH_DATA_ABORT_VALUE & SW_RETENTION_VAL_MASK): + start_type = RESET_SOURCE_CRASH_DATA_ABORT; + break; + case (CRASH_UNUSED_VALUE & SW_RETENTION_VAL_MASK): + start_type = RESET_SOURCE_CRASH_UNUSED; + break; + case (CRASH_2ND_XAT0_VALUE & SW_RETENTION_VAL_MASK): + start_type = RESET_SOURCE_CRASH_XAT0; + break; + + case (RESET_SOURCE_WATCHDOG & SW_RETENTION_VAL_MASK): + start_type = RESET_SOURCE_WATCHDOG; + break; + default: + start_type = RESET_SOURCE_UNKNOWN; + break; + } + } + } + //clear + sctrl_ctrl(CMD_SET_SCTRL_RETETION, &misc_value); + + *((volatile uint32_t *)(START_TYPE_DMEMORY_ADDR)) = (uint32_t)CRASH_XAT0_VALUE; + + os_printf("bk_misc_init_start_type %x %x\r\n",start_type,misc_value); + return start_type; + +} +void bk_misc_update_set_type(RESET_SOURCE_STATUS type) +{ + uint32_t misc_value = type & SW_RETENTION_VAL_MASK; + sctrl_ctrl(CMD_SET_SCTRL_RETETION, &misc_value); +} + +void bk_misc_check_start_type() +{ + if (RESET_SOURCE_CRASH_PER_XAT0 == start_type) { + uint32_t misc_value = CRASH_2ND_XAT0_VALUE & SW_RETENTION_VAL_MASK; + sctrl_ctrl(CMD_SET_SCTRL_RETETION, &misc_value); + bk_misc_crash_xat0_reboot(); + } +} +#else +//only can be do once + RESET_SOURCE_STATUS bk_misc_init_start_type(void) +{ + uint32_t misc_value = *((volatile uint32_t *)(START_TYPE_ADDR)); + + if((start_type = sctrl_get_deep_sleep_wake_soure()) == 0) + { + switch(misc_value) + { + case RESET_SOURCE_REBOOT: + start_type = misc_value; + break; + case CRASH_UNDEFINED_VALUE: + start_type = RESET_SOURCE_CRASH_UNDEFINED; + break; + case CRASH_PREFETCH_ABORT_VALUE: + start_type = RESET_SOURCE_CRASH_PREFETCH_ABORT; + break; + case CRASH_DATA_ABORT_VALUE: + start_type = RESET_SOURCE_CRASH_DATA_ABORT; + break; + case CRASH_UNUSED_VALUE: + start_type = RESET_SOURCE_CRASH_UNUSED; + break; + case CRASH_XAT0_VALUE: + start_type = RESET_SOURCE_CRASH_PER_XAT0; + break; + case CRASH_2ND_XAT0_VALUE: + start_type = RESET_SOURCE_CRASH_XAT0; + break; + + case RESET_SOURCE_WATCHDOG: + if((uint32_t)CRASH_XAT0_VALUE == + *((volatile uint32_t *)(START_TYPE_DMEMORY_ADDR))) + { + start_type = RESET_SOURCE_CRASH_PER_XAT0; + } + else + { + start_type = misc_value; + } + break; + default: + start_type = RESET_SOURCE_POWERON; + break; + } + } + + *((volatile uint32_t *)(START_TYPE_DMEMORY_ADDR)) = (uint32_t)CRASH_XAT0_VALUE; + *((volatile uint32_t *)(START_TYPE_ADDR)) = (uint32_t)CRASH_XAT0_VALUE; + + //os_printf("bk_misc_init_start_type %x %x\r\n",start_type,misc_value); + return start_type; +} + +void bk_misc_update_set_type(RESET_SOURCE_STATUS type) +{ + *((volatile uint32_t *)(START_TYPE_ADDR)) = (uint32_t)type; + //os_printf("bk_wlan_update_set_type %d\r\n",*((volatile uint32_t *)(START_TYPE_ADDR))); +} + +void bk_misc_check_start_type() +{ + if (RESET_SOURCE_CRASH_PER_XAT0 == start_type) { + *((volatile uint32_t *)(START_TYPE_ADDR)) = (uint32_t)CRASH_2ND_XAT0_VALUE; + bk_misc_crash_xat0_reboot(); + } +} +#endif diff --git a/beken_os/beken378/func/misc/target_util.c b/beken_os/beken378/func/misc/target_util.c new file mode 100755 index 0000000..392fea9 --- /dev/null +++ b/beken_os/beken378/func/misc/target_util.c @@ -0,0 +1,107 @@ +#include "include.h" +#include "arm_arch.h" + +#include "target_util_pub.h" +#include "sys_ctrl_pub.h" +#include "fake_clock_pub.h" +#include "drv_model_pub.h" + +/******************************************************************************* +* Function Implemantation +*******************************************************************************/ +/* + MCLK:26MHz, delay(1): about 25us + delay(10):about 125us + delay(100):about 850us + */ +void delay(INT32 num) +{ + volatile INT32 i, j; + + for(i = 0; i < num; i ++) + { + for(j = 0; j < 100; j ++) + ; + } +} + +/* + when parameter is 1, the return result is approximately 1 ms; + */ +void delay_ms(UINT32 ms_count) +{ + UINT32 ret; + UINT32 div; + UINT32 clk = 0; + UINT32 cell; + SYS_CTRL_U param; + + ret = sddev_control(SCTRL_DEV_NAME, CMD_GET_SCTRL_CONTROL, ¶m); + ASSERT(SCTRL_SUCCESS == ret); + + div = param.bits.mclk_div; + switch(param.bits.mclk_mux) + { + case MCLK_MODE_DCO: + case MCLK_MODE_26M_XTAL: + clk = 26000000; + break; + + case MCLK_MODE_DPLL: + clk = 480000000 / (2 << div); + break; + + case MCLK_MODE_LPO: + clk = 32000; + break; + + default: + break; + } + + ASSERT(clk); + + cell = 100 * clk / 26000000; + delay(ms_count * cell); +} + +/* + [delay offset]worst case: delay about 1 second; + */ +void delay_sec(UINT32 ms_count) +{ + UINT32 t0; + UINT32 t1; + + t0 = fclk_get_second(); + while(1) + { + t1 = fclk_get_second(); + if(t1 - t0 >= 1) + { + break; + } + } +} + +/* + [delay offset]worst case: delay about 1 tick; + */ +void delay_tick(UINT32 tick_count) +{ + UINT32 t0; + UINT32 t1; + + t0 = fclk_get_tick(); + while(1) + { + t1 = fclk_get_tick(); + if(t1 - t0 >= 1) + { + break; + } + } +} + +// EOF + diff --git a/beken_os/beken378/func/music_player/Mp3Lib/asmmisc.S b/beken_os/beken378/func/music_player/Mp3Lib/asmmisc.S new file mode 100755 index 0000000..974ea05 --- /dev/null +++ b/beken_os/beken378/func/music_player/Mp3Lib/asmmisc.S @@ -0,0 +1,65 @@ +#/* ***** BEGIN LICENSE BLOCK ***** +# * Version: RCSL 1.0/RPSL 1.0 +# * +# * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. +# * +# * The contents of this file, and the files included with this file, are +# * subject to the current version of the RealNetworks Public Source License +# * Version 1.0 (the "RPSL") available at +# * http://www.helixcommunity.org/content/rpsl unless you have licensed +# * the file under the RealNetworks Community Source License Version 1.0 +# * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, +# * in which case the RCSL will apply. You may also obtain the license terms +# * directly from RealNetworks. You may not use this file except in +# * compliance with the RPSL or, if you have a valid RCSL with RealNetworks +# * applicable to this file, the RCSL. Please see the applicable RPSL or +# * RCSL for the rights, obligations and limitations governing use of the +# * contents of the file. +# * +# * This file is part of the Helix DNA Technology. RealNetworks is the +# * developer of the Original Code and owns the copyrights in the portions +# * it created. +# * +# * This file, and the files included with this file, is distributed and made +# * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER +# * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, +# * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS +# * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. +# * +# * Technology Compatibility Kit Test Suite(s) Location: +# * http://www.helixcommunity.org/content/tck +# * +# * Contributor(s): +# * +# * ***** END LICENSE BLOCK ***** */ + + +# AREA |.text|, CODE, READONLY +# int xmp3_MULSHIFT32(int x, int y) +# EXPORT xmp3_MULSHIFT32 + +.syntax unified +/*.thumb*/ +.text + + .global xmp3_MULSHIFT32 + /* .thumb_func*/ + xmp3_MULSHIFT32: + smull r2, r0, r1, r0 +# mov pc, lr // KJ changed to BX for Cortex + BX lr + + + + .global xmp3_FASTABS + /* .thumb_func*/ + xmp3_FASTABS: + # eor r1,r0,r0, asr #31 + # sub r0,r1,r0, asr #31 + BX lr + + # eor t, x, x, asr #31 // T:=X XOR (X>>31) + # sub t, t, x, asr #31 // T:=T-(X>>31) + + + .END diff --git a/beken_os/beken378/func/music_player/Mp3Lib/asmpoly_thumb2.S b/beken_os/beken378/func/music_player/Mp3Lib/asmpoly_thumb2.S new file mode 100755 index 0000000..f909652 --- /dev/null +++ b/beken_os/beken378/func/music_player/Mp3Lib/asmpoly_thumb2.S @@ -0,0 +1,381 @@ +.syntax unified +/*.thumb*/ +.text + +/*.equ PCM , r0*/ +PCM .req r0 +VB1 .req r1 +COEF .req r2 + +VLO .req r0 +VHI .req r3 + +SUM1LL .req r4 +SUM1LH .req r5 +SUM2LL .req r6 +SUM2LH .req r7 +SUM1RL .req r8 +SUM1RH .req r9 +SUM2RL .req r10 +SUM2RH .req r11 + +CF1 .req r12 +CF2 .req r14 + +SIGN .req r12 +MAXPOS .req r14 + +I .req r12 + +.global RNDVAL +/* RNDVAL SETA (1 << ((32 - 12) + (6 - 1))) */ +.equ RNDVAL, 0x02000000 /*(1 << (25)) */ + + /*; C64TOS - clip 64-bit accumulator to short (no rounding) + ; xl, xh = value (lo 32, hi 32) + ; input assumed to have 6 fraction bits + ; sign = temp variable to use for sign + ; maxPos = 0x00007fff (takes 2 instr. to generate - calculating + ; once and using repeatedly saves if you do several CTOS in a row) */ + .macro C64TOS _xl, _xh, _sign, _maxPos + mov \_xl, \_xl, lsr #(20+6) + orr \_xl, \_xl, \_xh, lsl #(12-6) + mov \_sign, \_xl, ASR #31 + cmp \_sign, \_xl, ASR #15 + it ne + eorne \_xl, \_sign, \_maxPos + .endm + + /* ; MC0S - process 2 taps, 1 sample per channel (sample 0) */ + /* ; x = vb1 offset */ + .MACRO MC0S val_x + + ldr CF1, [COEF], #4 + ldr CF2, [COEF], #4 + ldr VLO, [VB1, #(4*(\val_x))] + ldr VHI, [VB1, #(4*(23 - \val_x))] + + smlal SUM1LL, SUM1LH, VLO, CF1 + ldr VLO, [VB1, #(4*(32 + \val_x))] + rsb CF2, CF2, #0 + smlal SUM1LL, SUM1LH, VHI, CF2 + ldr VHI, [VB1, #(4*(32 + 23 - \val_x))] + + smlal SUM1RL, SUM1RH, VLO, CF1 + smlal SUM1RL, SUM1RH, VHI, CF2 + + .ENDM + +/* ; MC1S - process 2 taps, 1 sample per channel (sample 16) + ; x = vb1 offset */ + .MACRO MC1S val_x + + ldr CF1, [COEF], #4 + ldr VLO, [VB1, #(4*(\val_x))] + ldr VHI, [VB1, #(4*(32 + \val_x))] + smlal SUM1LL, SUM1LH, VLO, CF1 + smlal SUM1RL, SUM1RH, VHI, CF1 + + .ENDM + +/* ; MC2S - process 2 taps, 2 samples per channel + ; x = vb1 offset */ + .MACRO MC2S val_x + + /* ; load data as far as possible in advance of using it */ + ldr CF1, [COEF], #4 + ldr CF2, [COEF], #4 + ldr VLO, [VB1, #(4*(\val_x))] + ldr VHI, [VB1, #(4*(23 - \val_x))] + + smlal SUM1LL, SUM1LH, VLO, CF1 + smlal SUM2LL, SUM2LH, VLO, CF2 + rsb CF2, CF2, #0 + smlal SUM2LL, SUM2LH, VHI, CF1 + smlal SUM1LL, SUM1LH, VHI, CF2 + + ldr VHI, [VB1, #(4*(32 + 23 - \val_x))] + ldr VLO, [VB1, #(4*(32 + \val_x))] + + smlal SUM1RL, SUM1RH, VHI, CF2 + smlal SUM2RL, SUM2RH, VHI, CF1 + rsb CF2, CF2, #0 + smlal SUM1RL, SUM1RH, VLO, CF1 + smlal SUM2RL, SUM2RH, VLO, CF2 + .ENDM + + +/* ; void PolyphaseStereo(short *pcm, int *vbuf, const int *coefBase) */ + .global xmp3_PolyphaseStereo +/*.thumb_func*/ + xmp3_PolyphaseStereo: + + stmfd sp!, {r4-r11, r14} + +/* ; clear out stack space for 2 local variables (4 bytes each) */ + sub sp, sp, #8 + str PCM , [sp, #4] /*; sp[1] = pcm pointer */ + +/* ; special case, output sample 0 */ + mov SUM1LL, #RNDVAL /* ; load rndVal (low 32) */ + mov SUM1RL, #RNDVAL /* ; load rndVal (low 32) */ + mov SUM1LH, #0 + mov SUM1RH, #0 + + MC0S 0 + MC0S 1 + MC0S 2 + MC0S 3 + MC0S 4 + MC0S 5 + MC0S 6 + MC0S 7 + + ldr PCM, [sp, #4] /* ; load pcm pointer */ + mov MAXPOS, #0x7f00 + orr MAXPOS, MAXPOS, #0xff + + C64TOS SUM1LL, SUM1LH, SIGN, MAXPOS + C64TOS SUM1RL, SUM1RH, SIGN, MAXPOS + + strh SUM1LL, [PCM, #(2*0)] + strh SUM1RL, [PCM, #(2*1)] + + /* ; special case, output sample 16 */ + add COEF, COEF, #(4*(256-16)) /* ; coef = coefBase + 256 (was coefBase + 16 after MC0S block) */ + add VB1, VB1, #(4*1024) /* ; vb1 = vbuf + 64*16 */ + + mov SUM1LL, #RNDVAL /* ; load rndVal (low 32) */ + mov SUM1RL, #RNDVAL /* ; load rndVal (low 32) */ + mov SUM1LH, #0 + mov SUM1RH, #0 + + MC1S 0 + MC1S 1 + MC1S 2 + MC1S 3 + MC1S 4 + MC1S 5 + MC1S 6 + MC1S 7 + + ldr PCM, [sp, #4] /* load pcm pointer */ + mov MAXPOS, #0x7f00 + orr MAXPOS, MAXPOS, #0xff + + C64TOS SUM1LL, SUM1LH, SIGN, MAXPOS + C64TOS SUM1RL, SUM1RH, SIGN, MAXPOS + + strh SUM1LL, [PCM, #(2*(2*16+0))] + strh SUM1RL, [PCM, #(2*(2*16+1))] + + /*; main convolution loop: sum1L = samples 1, 2, 3, ... 15 sum2L = samples 31, 30, ... 17 */ + sub COEF, COEF, #(4*(264-16)) /* ; coef = coefBase + 16 (was coefBase + 264 after MC1S block) */ + sub VB1, VB1, #(4*(1024-64)) /* ; vb1 = vbuf + 64 (was vbuf + 64*16 after MC1S block) */ + mov I, #15 /* ; loop counter, count down */ + add PCM, PCM, #(2*2) /* ; pcm+=2 */ + +LoopPS: + str I, [sp, #0] /* ; sp[0] = i (loop counter) */ + str PCM, [sp, #4] /* ; sp[1] = pcm (pointer to pcm buffer) */ + + mov SUM1LL, #RNDVAL /* ; load rndVal (low 32) */ + mov SUM1RL, #RNDVAL /* ; load rndVal (low 32) */ + mov SUM2LL, #RNDVAL /* ; load rndVal (low 32) */ + mov SUM2RL, #RNDVAL /* ; load rndVal (low 32) */ + + mov SUM1LH, #0 + mov SUM1RH, #0 + mov SUM2LH, #0 + mov SUM2RH, #0 + + MC2S 0 + MC2S 1 + MC2S 2 + MC2S 3 + MC2S 4 + MC2S 5 + MC2S 6 + MC2S 7 + + add VB1, VB1, #(4*64) /*; vb1 += 64*/ + + ldr PCM, [sp, #4] /*; load pcm pointer*/ + mov MAXPOS, #0x7f00 + orr MAXPOS, MAXPOS, #0xff + + C64TOS SUM1LL, SUM1LH, SIGN, MAXPOS + C64TOS SUM1RL, SUM1RH, SIGN, MAXPOS + C64TOS SUM2LL, SUM2LH, SIGN, MAXPOS + C64TOS SUM2RL, SUM2RH, SIGN, MAXPOS + + ldr I, [sp, #0] /*; load loop counter*/ + add CF2, PCM, I, lsl #3 /*; CF2 = PCM + 4*i (short offset)*/ + strh SUM2LL, [CF2], #2 /*; *(pcm + 2*2*i + 0)*/ + strh SUM2RL, [CF2], #2 /*; *(pcm + 2*2*i + 1)*/ + + strh SUM1LL, [PCM], #2 /*; *(pcm + 0)*/ + strh SUM1RL, [PCM], #2 /*; *(pcm + 1)*/ + + subs I, I, #1 + bne LoopPS + + /* ; restore stack pointer*/ + add sp, sp, #8 + + ldmfd sp!, {r4-r11, pc} + /* ENDFUNC*/ + +/*;; MONO PROCESSING*/ + + /*; MC0M - process 2 taps, 1 sample (sample 0)*/ + /*; x = vb1 offset*/ + .MACRO MC0M val_x + + ldr CF1, [COEF], #4 + ldr CF2, [COEF], #4 + ldr VLO, [VB1, #(4*(\val_x))] + ldr VHI, [VB1, #(4*(23 - \val_x))] + + rsb CF2, CF2, #0 + smlal SUM1LL, SUM1LH, VLO, CF1 + smlal SUM1LL, SUM1LH, VHI, CF2 + + .endm + /*MEND ; MC0M*/ + + /*; MC1M - process 2 taps, 1 sample (sample 16)*/ + /*; x = vb1 offset*/ + .MACRO MC1M val_x + + ldr CF1, [COEF], #4 + ldr VLO, [VB1, #(4*(\val_x))] + smlal SUM1LL, SUM1LH, VLO, CF1 + + .endm + /*MEND ; MC1M*/ + + /* ; MC2M - process 2 taps, 2 samples*/ + /* ; x = vb1 offset*/ + .MACRO MC2M val_x + + /* ; load data as far as possible in advance of using it*/ + ldr CF1, [COEF], #4 + ldr CF2, [COEF], #4 + ldr VLO, [VB1, #(4*(\val_x))] + ldr VHI, [VB1, #(4*(23 - \val_x))] + + smlal SUM1LL, SUM1LH, VLO, CF1 + smlal SUM2LL, SUM2LH, VLO, CF2 + rsb CF2, CF2, #0 + smlal SUM1LL, SUM1LH, VHI, CF2 + smlal SUM2LL, SUM2LH, VHI, CF1 + + .endm + /*MEND ; MC2M*/ + +/*; void PolyphaseMono(short *pcm, int *vbuf, const int *coefBase)*/ + +.global xmp3_PolyphaseMono +/*.thumb_func */ + xmp3_PolyphaseMono: + + + stmfd sp!, {r4-r11, r14} + + /*; clear out stack space for 4 local variables (4 bytes each)*/ + sub sp, sp, #8 + str PCM, [sp, #4] /*; sp[1] = pcm pointer*/ + + /* ; special case, output sample 0*/ + mov SUM1LL, #RNDVAL /* ; load rndVal (low 32)*/ + mov SUM1LH, #0 + + MC0M 0 + MC0M 1 + MC0M 2 + MC0M 3 + MC0M 4 + MC0M 5 + MC0M 6 + MC0M 7 + + ldr PCM, [sp, #4] /*; load pcm pointer*/ + mov MAXPOS, #0x7f00 + orr MAXPOS, MAXPOS, #0xff + + C64TOS SUM1LL, SUM1LH, SIGN, MAXPOS + strh SUM1LL, [PCM, #(2*0)] + + /* ; special case, output sample 16*/ + add COEF, COEF, #(4*(256-16)) /* ; coef = coefBase + 256 (was coefBase + 16 after MC0M block)*/ + add VB1, VB1, #(4*1024) /* ; vb1 = vbuf + 64*16*/ + + mov SUM1LL, #RNDVAL /* ; load rndVal (low 32)*/ + mov SUM1LH, #0 + + MC1M 0 + MC1M 1 + MC1M 2 + MC1M 3 + MC1M 4 + MC1M 5 + MC1M 6 + MC1M 7 + + ldr PCM, [sp, #4] /* ; load pcm pointer*/ + mov MAXPOS, #0x7f00 + orr MAXPOS, MAXPOS, #0xff + + C64TOS SUM1LL, SUM1LH, SIGN, MAXPOS + + strh SUM1LL, [PCM, #(2*16)] + + /* ; main convolution loop: sum1L = samples 1, 2, 3, ... 15 sum2L = samples 31, 30, ... 17*/ + sub COEF, COEF, #(4*(264-16)) /* ; coef = coefBase + 16 (was coefBase + 264 after MC1M block)*/ + sub VB1, VB1, #(4*(1024-64)) /* ; vb1 = vbuf + 64 (was vbuf + 64*16 after MC1M block)*/ + mov I, #15 /* ; loop counter, count down*/ + add PCM, PCM, #(2) /* ; pcm++*/ + +LoopPM: + str I, [sp, #0] /* ; sp[0] = i (loop counter)*/ + str PCM, [sp, #4] /* ; sp[1] = pcm (pointer to pcm buffer)*/ + + mov SUM1LL, #RNDVAL /* ; load rndVal (low 32)*/ + mov SUM2LL, #RNDVAL /* ; load rndVal (low 32)*/ + mov SUM1LH, #0 + mov SUM2LH, #0 + + MC2M 0 + MC2M 1 + MC2M 2 + MC2M 3 + MC2M 4 + MC2M 5 + MC2M 6 + MC2M 7 + + add VB1, VB1, #(4*64) /*; vb1 += 64*/ + + ldr PCM, [sp, #4] /*; load pcm pointer*/ + mov MAXPOS, #0x7f00 + orr MAXPOS, MAXPOS, #0xff + + C64TOS SUM1LL, SUM1LH, SIGN, MAXPOS + C64TOS SUM2LL, SUM2LH, SIGN, MAXPOS + + ldr I, [sp, #0] /*; load loop counter*/ + add CF2, PCM, I, lsl #2 /*; CF2 = PCM + 2*i (short offset)*/ + strh SUM2LL, [CF2], #2 ; /**(pcm + 2*i + 0)*/ + strh SUM1LL, [PCM], #2 ; /**(pcm + 0) ; pcm++*/ + + subs I, I, #1 + bne LoopPM + + /* ; restore stack pointer*/ + add sp, sp, #8 + + ldmfd sp!, {r4-r11, pc} + + + .END diff --git a/beken_os/beken378/func/music_player/Mp3Lib/assembly.h b/beken_os/beken378/func/music_player/Mp3Lib/assembly.h new file mode 100755 index 0000000..2046462 --- /dev/null +++ b/beken_os/beken378/func/music_player/Mp3Lib/assembly.h @@ -0,0 +1,307 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: RCSL 1.0/RPSL 1.0 + * + * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. + * + * The contents of this file, and the files included with this file, are + * subject to the current version of the RealNetworks Public Source License + * Version 1.0 (the "RPSL") available at + * http://www.helixcommunity.org/content/rpsl unless you have licensed + * the file under the RealNetworks Community Source License Version 1.0 + * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, + * in which case the RCSL will apply. You may also obtain the license terms + * directly from RealNetworks. You may not use this file except in + * compliance with the RPSL or, if you have a valid RCSL with RealNetworks + * applicable to this file, the RCSL. Please see the applicable RPSL or + * RCSL for the rights, obligations and limitations governing use of the + * contents of the file. + * + * This file is part of the Helix DNA Technology. RealNetworks is the + * developer of the Original Code and owns the copyrights in the portions + * it created. + * + * This file, and the files included with this file, is distributed and made + * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * + * Technology Compatibility Kit Test Suite(s) Location: + * http://www.helixcommunity.org/content/tck + * + * Contributor(s): + * + * ***** END LICENSE BLOCK ***** */ + +/************************************************************************************** + * Fixed-point MP3 decoder + * Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com) + * June 2003 + * + * assembly.h - assembly language functions and prototypes for supported platforms + * + * - inline rountines with access to 64-bit multiply results + * - x86 (_WIN32) and ARM (ARM_ADS, _WIN32_WCE) versions included + * - some inline functions are mix of asm and C for speed + * - some functions are in native asm files, so only the prototype is given here + * + * MULSHIFT32(x, y) signed multiply of two 32-bit integers (x and y), returns top 32 bits of 64-bit result + * FASTABS(x) branchless absolute value of signed integer x + * CLZ(x) count leading zeros in x + * MADD64(sum, x, y) (Windows only) sum [64-bit] += x [32-bit] * y [32-bit] + * SHL64(sum, x, y) (Windows only) 64-bit left shift using __int64 + * SAR64(sum, x, y) (Windows only) 64-bit right shift using __int64 + */ +#ifndef _ASSEMBLY_H +#define _ASSEMBLY_H + +#include "include.h" + +#if (CONFIG_APP_MP3PLAYER == 1) +#if (defined _WIN32 && !defined _WIN32_WCE) || (defined __WINS__ && defined _SYMBIAN) || defined(_OPENWAVE_SIMULATOR) || defined(WINCE_EMULATOR) /* Symbian emulator for Ix86 */ + +#pragma warning( disable : 4035 ) /* complains about inline asm not returning a value */ + +static __inline int MULSHIFT32(int x, int y) +{ + __asm { + mov eax, x + imul y + mov eax, edx + } +} + +static __inline int FASTABS(int x) +{ + int sign; + + sign = x >> (sizeof(int) * 8 - 1); + x ^= sign; + x -= sign; + + return x; +} + +static __inline int CLZ(int x) +{ + int numZeros; + + if (!x) + return (sizeof(int) * 8); + + numZeros = 0; + while (!(x & 0x80000000)) { + numZeros++; + x <<= 1; + } + + return numZeros; +} + +/* MADD64, SHL64, SAR64: + * write in assembly to avoid dependency on run-time lib for 64-bit shifts, muls + * (sometimes compiler thunks to function calls instead of code generating) + * required for Symbian emulator + */ +#ifdef __CW32__ +typedef long long Word64; +#else +typedef __int64 Word64; +#endif + +static __inline Word64 MADD64(Word64 sum, int x, int y) +{ + unsigned int sumLo = ((unsigned int *)&sum)[0]; + int sumHi = ((int *)&sum)[1]; + + __asm { + mov eax, x + imul y + add eax, sumLo + adc edx, sumHi + } + + /* equivalent to return (sum + ((__int64)x * y)); */ +} + +static __inline Word64 SHL64(Word64 x, int n) +{ + unsigned int xLo = ((unsigned int *)&x)[0]; + int xHi = ((int *)&x)[1]; + unsigned char nb = (unsigned char)n; + + if (n < 32) { + __asm { + mov edx, xHi + mov eax, xLo + mov cl, nb + shld edx, eax, cl + shl eax, cl + } + } else if (n < 64) { + /* shl masks cl to 0x1f */ + __asm { + mov edx, xLo + mov cl, nb + xor eax, eax + shl edx, cl + } + } else { + __asm { + xor edx, edx + xor eax, eax + } + } +} + +static __inline Word64 SAR64(Word64 x, int n) +{ + unsigned int xLo = ((unsigned int *)&x)[0]; + int xHi = ((int *)&x)[1]; + unsigned char nb = (unsigned char)n; + + if (n < 32) { + __asm { + mov edx, xHi + mov eax, xLo + mov cl, nb + shrd eax, edx, cl + sar edx, cl + } + } else if (n < 64) { + /* sar masks cl to 0x1f */ + __asm { + mov edx, xHi + mov eax, xHi + mov cl, nb + sar edx, 31 + sar eax, cl + } + } else { + __asm { + sar xHi, 31 + mov eax, xHi + mov edx, xHi + } + } +} + +#elif (defined _WIN32) && (defined _WIN32_WCE) + +/* use asm function for now (EVC++ 3.0 does horrible job compiling __int64 version) */ +#define MULSHIFT32 xmp3_MULSHIFT32 +int MULSHIFT32(int x, int y); + +static __inline int FASTABS(int x) +{ + int sign; + + sign = x >> (sizeof(int) * 8 - 1); + x ^= sign; + x -= sign; + + return x; +} + +static __inline int CLZ(int x) +{ + int numZeros; + + if (!x) + return (sizeof(int) * 8); + + numZeros = 0; + while (!(x & 0x80000000)) { + numZeros++; + x <<= 1; + } + + return numZeros; +} + +#elif defined ARM_ADS + +static __inline int MULSHIFT32(int x, int y) +{ + /* important rules for smull RdLo, RdHi, Rm, Rs: + * RdHi and Rm can't be the same register + * RdLo and Rm can't be the same register + * RdHi and RdLo can't be the same register + * Note: Rs determines early termination (leading sign bits) so if you want to specify + * which operand is Rs, put it in the SECOND argument (y) + * For inline assembly, x and y are not assumed to be R0, R1 so it shouldn't matter + * which one is returned. (If this were a function call, returning y (R1) would + * require an extra "mov r0, r1") + */ + int zlow; + __asm { + smull zlow,y,x,y + } + + return y; +} + +static __inline int FASTABS(int x) +{ + int t=0; /*Really is not necessary to initialiaze only to avoid warning*/ + + __asm { + eor t, x, x, asr #31 // T:=X XOR (X>>31) + sub t, t, x, asr #31 // T:=T-(X>>31) + } + + return t; +} + +static __inline int CLZ(int x) +{ + int numZeros; + + if (!x) + return (sizeof(int) * 8); + + numZeros = 0; + while (!(x & 0x80000000)) { + numZeros++; + x <<= 1; + } + + return numZeros; +} + +#elif defined(__GNUC__) && defined(ARM) + +typedef long long Word64; + +#define MULSHIFT32 xmp3_MULSHIFT32 +extern int MULSHIFT32(int x, int y); + + +#define FASTABS xmp3_FASTABS +int FASTABS(int x); + + +static __inline int CLZ(int x) +{ + int numZeros; + + if (!x) + return (sizeof(int) * 8); + + numZeros = 0; + while (!(x & 0x80000000)) { + numZeros++; + x <<= 1; + } + + return numZeros; +} + +#else + +#error Unsupported platform in assembly.h + +#endif /* platforms */ + +#endif /* CONFIG_APP_MP3PLAYER */ +#endif /* _ASSEMBLY_H */ diff --git a/beken_os/beken378/func/music_player/Mp3Lib/bitstream.c b/beken_os/beken378/func/music_player/Mp3Lib/bitstream.c new file mode 100755 index 0000000..af5733c --- /dev/null +++ b/beken_os/beken378/func/music_player/Mp3Lib/bitstream.c @@ -0,0 +1,423 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: RCSL 1.0/RPSL 1.0 + * + * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. + * + * The contents of this file, and the files included with this file, are + * subject to the current version of the RealNetworks Public Source License + * Version 1.0 (the "RPSL") available at + * http://www.helixcommunity.org/content/rpsl unless you have licensed + * the file under the RealNetworks Community Source License Version 1.0 + * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, + * in which case the RCSL will apply. You may also obtain the license terms + * directly from RealNetworks. You may not use this file except in + * compliance with the RPSL or, if you have a valid RCSL with RealNetworks + * applicable to this file, the RCSL. Please see the applicable RPSL or + * RCSL for the rights, obligations and limitations governing use of the + * contents of the file. + * + * This file is part of the Helix DNA Technology. RealNetworks is the + * developer of the Original Code and owns the copyrights in the portions + * it created. + * + * This file, and the files included with this file, is distributed and made + * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * + * Technology Compatibility Kit Test Suite(s) Location: + * http://www.helixcommunity.org/content/tck + * + * Contributor(s): + * + * ***** END LICENSE BLOCK ***** */ + +/************************************************************************************** + * Fixed-point MP3 decoder + * Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com) + * June 2003 + * + * bitstream.c - bitstream unpacking, frame header parsing, side info parsing + **************************************************************************************/ +#include "include.h" + +#include "coder.h" +#include "assembly.h" + +#if (CONFIG_APP_MP3PLAYER == 1) +/************************************************************************************** + * Function: SetBitstreamPointer + * + * Description: initialize bitstream reader + * + * Inputs: pointer to BitStreamInfo struct + * number of bytes in bitstream + * pointer to byte-aligned buffer of data to read from + * + * Outputs: filled bitstream info struct + * + * Return: none + **************************************************************************************/ +void SetBitstreamPointer(BitStreamInfo *bsi, int nBytes, unsigned char *buf) +{ + /* init bitstream */ + bsi->bytePtr = buf; + bsi->iCache = 0; /* 4-byte unsigned int */ + bsi->cachedBits = 0; /* i.e. zero bits in cache */ + bsi->nBytes = nBytes; +} + +/************************************************************************************** + * Function: RefillBitstreamCache + * + * Description: read new data from bitstream buffer into bsi cache + * + * Inputs: pointer to initialized BitStreamInfo struct + * + * Outputs: updated bitstream info struct + * + * Return: none + * + * Notes: only call when iCache is completely drained (resets bitOffset to 0) + * always loads 4 new bytes except when bsi->nBytes < 4 (end of buffer) + * stores data as big-endian in cache, regardless of machine endian-ness + * + * TODO: optimize for ARM + * possibly add little/big-endian modes for doing 32-bit loads + **************************************************************************************/ +static __inline void RefillBitstreamCache(BitStreamInfo *bsi) +{ + int nBytes = bsi->nBytes; + + /* optimize for common case, independent of machine endian-ness */ + if (nBytes >= 4) { + bsi->iCache = (*bsi->bytePtr++) << 24; + bsi->iCache |= (*bsi->bytePtr++) << 16; + bsi->iCache |= (*bsi->bytePtr++) << 8; + bsi->iCache |= (*bsi->bytePtr++); + bsi->cachedBits = 32; + bsi->nBytes -= 4; + } else { + bsi->iCache = 0; + while (nBytes--) { + bsi->iCache |= (*bsi->bytePtr++); + bsi->iCache <<= 8; + } + bsi->iCache <<= ((3 - bsi->nBytes)*8); + bsi->cachedBits = 8*bsi->nBytes; + bsi->nBytes = 0; + } +} + +/************************************************************************************** + * Function: GetBits + * + * Description: get bits from bitstream, advance bitstream pointer + * + * Inputs: pointer to initialized BitStreamInfo struct + * number of bits to get from bitstream + * + * Outputs: updated bitstream info struct + * + * Return: the next nBits bits of data from bitstream buffer + * + * Notes: nBits must be in range [0, 31], nBits outside this range masked by 0x1f + * for speed, does not indicate error if you overrun bit buffer + * if nBits = 0, returns 0 (useful for scalefactor unpacking) + * + * TODO: optimize for ARM + **************************************************************************************/ +unsigned int GetBits(BitStreamInfo *bsi, int nBits) +{ + unsigned int data, lowBits; + + nBits &= 0x1f; /* nBits mod 32 to avoid unpredictable results like >> by negative amount */ + data = bsi->iCache >> (31 - nBits); /* unsigned >> so zero-extend */ + data >>= 1; /* do as >> 31, >> 1 so that nBits = 0 works okay (returns 0) */ + bsi->iCache <<= nBits; /* left-justify cache */ + bsi->cachedBits -= nBits; /* how many bits have we drawn from the cache so far */ + + /* if we cross an int boundary, refill the cache */ + if (bsi->cachedBits < 0) { + lowBits = -bsi->cachedBits; + RefillBitstreamCache(bsi); + data |= bsi->iCache >> (32 - lowBits); /* get the low-order bits */ + + bsi->cachedBits -= lowBits; /* how many bits have we drawn from the cache so far */ + bsi->iCache <<= lowBits; /* left-justify cache */ + } + + return data; +} + +/************************************************************************************** + * Function: CalcBitsUsed + * + * Description: calculate how many bits have been read from bitstream + * + * Inputs: pointer to initialized BitStreamInfo struct + * pointer to start of bitstream buffer + * bit offset into first byte of startBuf (0-7) + * + * Outputs: none + * + * Return: number of bits read from bitstream, as offset from startBuf:startOffset + **************************************************************************************/ +int CalcBitsUsed(BitStreamInfo *bsi, unsigned char *startBuf, int startOffset) +{ + int bitsUsed; + + bitsUsed = (bsi->bytePtr - startBuf) * 8; + bitsUsed -= bsi->cachedBits; + bitsUsed -= startOffset; + + return bitsUsed; +} + +/************************************************************************************** + * Function: CheckPadBit + * + * Description: check whether padding byte is present in an MP3 frame + * + * Inputs: MP3DecInfo struct with valid FrameHeader struct + * (filled by UnpackFrameHeader()) + * + * Outputs: none + * + * Return: 1 if pad bit is set, 0 if not, -1 if null input pointer + **************************************************************************************/ +int CheckPadBit(MP3DecInfo *mp3DecInfo) +{ + FrameHeader *fh; + + /* validate pointers */ + if (!mp3DecInfo || !mp3DecInfo->FrameHeaderPS) + return -1; + + fh = ((FrameHeader *)(mp3DecInfo->FrameHeaderPS)); + + return (fh->paddingBit ? 1 : 0); +} + +/************************************************************************************** + * Function: UnpackFrameHeader + * + * Description: parse the fields of the MP3 frame header + * + * Inputs: buffer pointing to a complete MP3 frame header (4 bytes, plus 2 if CRC) + * + * Outputs: filled frame header info in the MP3DecInfo structure + * updated platform-specific FrameHeader struct + * + * Return: length (in bytes) of frame header (for caller to calculate offset to + * first byte following frame header) + * -1 if null frameHeader or invalid header + * + * TODO: check for valid modes, depending on capabilities of decoder + * test CRC on actual stream (verify no endian problems) + **************************************************************************************/ +int UnpackFrameHeader(MP3DecInfo *mp3DecInfo, unsigned char *buf) +{ + + int verIdx; + FrameHeader *fh; + int frame_size=0; + /* validate pointers and sync word */ + if (!mp3DecInfo || !mp3DecInfo->FrameHeaderPS || (buf[0] & SYNCWORDH) != SYNCWORDH || (buf[1] & SYNCWORDL) != SYNCWORDL) + return -1; + + fh = ((FrameHeader *)(mp3DecInfo->FrameHeaderPS)); + + /* read header fields - use bitmasks instead of GetBits() for speed, since format never varies */ + verIdx = (buf[1] >> 3) & 0x03; + fh->ver = (MPEGVersion)( verIdx == 0 ? MPEG25 : ((verIdx & 0x01) ? MPEG1 : MPEG2) ); + fh->layer = 4 - ((buf[1] >> 1) & 0x03); /* easy mapping of index to layer number, 4 = error */ + fh->crc = 1 - ((buf[1] >> 0) & 0x01); + fh->brIdx = (buf[2] >> 4) & 0x0f; + fh->srIdx = (buf[2] >> 2) & 0x03; + fh->paddingBit = (buf[2] >> 1) & 0x01; + fh->privateBit = (buf[2] >> 0) & 0x01; + fh->sMode = (StereoMode)((buf[3] >> 6) & 0x03); /* maps to correct enum (see definition) */ + fh->modeExt = (buf[3] >> 4) & 0x03; + fh->copyFlag = (buf[3] >> 3) & 0x01; + fh->origFlag = (buf[3] >> 2) & 0x01; + fh->emphasis = (buf[3] >> 0) & 0x03; + + /* check parameters to avoid indexing tables with bad values */ + if (fh->srIdx == 3 || fh->layer == 4 || fh->brIdx == 15) + { + /*need for delay for sometime*/ + return -1; + } + + fh->sfBand = &sfBandTable[fh->ver][fh->srIdx]; /* for readability (we reference sfBandTable many times in decoder) */ + if (fh->sMode != Joint) /* just to be safe (dequant, stproc check fh->modeExt) */ + fh->modeExt = 0; + + /* init user-accessible data */ + mp3DecInfo->nChans = (fh->sMode == Mono ? 1 : 2); + mp3DecInfo->samprate = samplerateTab[fh->ver][fh->srIdx]; + mp3DecInfo->nGrans = (fh->ver == MPEG1 ? NGRANS_MPEG1 : NGRANS_MPEG2); + mp3DecInfo->nGranSamps = ((int)samplesPerFrameTab[fh->ver][fh->layer - 1]) / mp3DecInfo->nGrans; + mp3DecInfo->layer = fh->layer; + mp3DecInfo->version = fh->ver; + + /* get bitrate and nSlots from table, unless brIdx == 0 (free mode) in which case caller must figure it out himself + * question - do we want to overwrite mp3DecInfo->bitrate with 0 each time if it's free mode, and + * copy the pre-calculated actual free bitrate into it in mp3dec.c (according to the spec, + * this shouldn't be necessary, since it should be either all frames free or none free) + */ + if (fh->brIdx) + { + mp3DecInfo->bitrate = ((int)bitrateTab[fh->ver][fh->layer - 1][fh->brIdx]) * 1000; + + /* nSlots = total frame bytes (from table) - sideInfo bytes - header - CRC (if present) + pad (if present) */ + mp3DecInfo->nSlots = (int)slotTab[fh->ver][fh->srIdx][fh->brIdx] - + (int)sideBytesTab[fh->ver][(fh->sMode == Mono ? 0 : 1)] - + 4 - (fh->crc ? 2 : 0) + (fh->paddingBit ? 1 : 0); + + /************************/ + frame_size = mp3DecInfo->bitrate/1000; + switch(fh->layer) { + case 1: + frame_size = (frame_size * 12000) / mp3DecInfo->samprate; + frame_size = (frame_size + fh->paddingBit) * 4; + break; + case 2: + frame_size = (frame_size * 144000) / mp3DecInfo->samprate; + frame_size += fh->paddingBit; + break; + default: + case 3: + if(fh->ver > 0) //MPEG 2/2.5 + frame_size = (frame_size * 72000) / mp3DecInfo->samprate; + else //MPEG 1 + frame_size = (frame_size * 144000) / mp3DecInfo->samprate; + frame_size += fh->paddingBit; + break; + } + mp3DecInfo->framesize = frame_size; + /***********************/ + } + else + { + mp3DecInfo->framesize = 0; + } + + /* load crc word, if enabled, and return length of frame header (in bytes) */ + if (fh->crc) { + fh->CRCWord = ((int)buf[4] << 8 | (int)buf[5] << 0); + return 6; + } else { + fh->CRCWord = 0; + return 4; + } +} + +/************************************************************************************** + * Function: UnpackSideInfo + * + * Description: parse the fields of the MP3 side info header + * + * Inputs: MP3DecInfo structure filled by UnpackFrameHeader() + * buffer pointing to the MP3 side info data + * + * Outputs: updated mainDataBegin in MP3DecInfo struct + * updated private (platform-specific) SideInfo struct + * + * Return: length (in bytes) of side info data + * -1 if null input pointers + **************************************************************************************/ +int UnpackSideInfo(MP3DecInfo *mp3DecInfo, unsigned char *buf) +{ + int gr, ch, bd, nBytes; + BitStreamInfo bitStreamInfo, *bsi; + FrameHeader *fh; + SideInfo *si; + SideInfoSub *sis; + + /* validate pointers and sync word */ + if (!mp3DecInfo || !mp3DecInfo->FrameHeaderPS || !mp3DecInfo->SideInfoPS) + return -1; + + fh = ((FrameHeader *)(mp3DecInfo->FrameHeaderPS)); + si = ((SideInfo *)(mp3DecInfo->SideInfoPS)); + + bsi = &bitStreamInfo; + if (fh->ver == MPEG1) { + /* MPEG 1 */ + nBytes = (fh->sMode == Mono ? SIBYTES_MPEG1_MONO : SIBYTES_MPEG1_STEREO); + SetBitstreamPointer(bsi, nBytes, buf); + si->mainDataBegin = GetBits(bsi, 9); + si->privateBits = GetBits(bsi, (fh->sMode == Mono ? 5 : 3)); + + for (ch = 0; ch < mp3DecInfo->nChans; ch++) + for (bd = 0; bd < MAX_SCFBD; bd++) + si->scfsi[ch][bd] = GetBits(bsi, 1); + } else { + /* MPEG 2, MPEG 2.5 */ + nBytes = (fh->sMode == Mono ? SIBYTES_MPEG2_MONO : SIBYTES_MPEG2_STEREO); + SetBitstreamPointer(bsi, nBytes, buf); + si->mainDataBegin = GetBits(bsi, 8); + si->privateBits = GetBits(bsi, (fh->sMode == Mono ? 1 : 2)); + } + + for(gr =0; gr < mp3DecInfo->nGrans; gr++) { + for (ch = 0; ch < mp3DecInfo->nChans; ch++) { + sis = &si->sis[gr][ch]; /* side info subblock for this granule, channel */ + + sis->part23Length = GetBits(bsi, 12); + sis->nBigvals = GetBits(bsi, 9); + sis->globalGain = GetBits(bsi, 8); + sis->sfCompress = GetBits(bsi, (fh->ver == MPEG1 ? 4 : 9)); + sis->winSwitchFlag = GetBits(bsi, 1); + + if(sis->winSwitchFlag) { + /* this is a start, stop, short, or mixed block */ + sis->blockType = GetBits(bsi, 2); /* 0 = normal, 1 = start, 2 = short, 3 = stop */ + sis->mixedBlock = GetBits(bsi, 1); /* 0 = not mixed, 1 = mixed */ + sis->tableSelect[0] = GetBits(bsi, 5); + sis->tableSelect[1] = GetBits(bsi, 5); + sis->tableSelect[2] = 0; /* unused */ + sis->subBlockGain[0] = GetBits(bsi, 3); + sis->subBlockGain[1] = GetBits(bsi, 3); + sis->subBlockGain[2] = GetBits(bsi, 3); + + /* TODO - check logic */ + if (sis->blockType == 0) { + /* this should not be allowed, according to spec */ + sis->nBigvals = 0; + sis->part23Length = 0; + sis->sfCompress = 0; + } else if (sis->blockType == 2 && sis->mixedBlock == 0) { + /* short block, not mixed */ + sis->region0Count = 8; + } else { + /* start, stop, or short-mixed */ + sis->region0Count = 7; + } + sis->region1Count = 20 - sis->region0Count; + } else { + /* this is a normal block */ + sis->blockType = 0; + sis->mixedBlock = 0; + sis->tableSelect[0] = GetBits(bsi, 5); + sis->tableSelect[1] = GetBits(bsi, 5); + sis->tableSelect[2] = GetBits(bsi, 5); + sis->region0Count = GetBits(bsi, 4); + sis->region1Count = GetBits(bsi, 3); + } + sis->preFlag = (fh->ver == MPEG1 ? GetBits(bsi, 1) : 0); + sis->sfactScale = GetBits(bsi, 1); + sis->count1TableSelect = GetBits(bsi, 1); + } + } + mp3DecInfo->mainDataBegin = si->mainDataBegin; /* needed by main decode loop */ + + ASSERT(nBytes == CalcBitsUsed(bsi, buf, 0) >> 3); + + return nBytes; +} +#endif /* CONFIG_APP_MP3PLAYER */ + diff --git a/beken_os/beken378/func/music_player/Mp3Lib/buffers.c b/beken_os/beken378/func/music_player/Mp3Lib/buffers.c new file mode 100755 index 0000000..d0b52e7 --- /dev/null +++ b/beken_os/beken378/func/music_player/Mp3Lib/buffers.c @@ -0,0 +1,250 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: RCSL 1.0/RPSL 1.0 + * + * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. + * + * The contents of this file, and the files included with this file, are + * subject to the current version of the RealNetworks Public Source License + * Version 1.0 (the "RPSL") available at + * http://www.helixcommunity.org/content/rpsl unless you have licensed + * the file under the RealNetworks Community Source License Version 1.0 + * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, + * in which case the RCSL will apply. You may also obtain the license terms + * directly from RealNetworks. You may not use this file except in + * compliance with the RPSL or, if you have a valid RCSL with RealNetworks + * applicable to this file, the RCSL. Please see the applicable RPSL or + * RCSL for the rights, obligations and limitations governing use of the + * contents of the file. + * + * This file is part of the Helix DNA Technology. RealNetworks is the + * developer of the Original Code and owns the copyrights in the portions + * it created. + * + * This file, and the files included with this file, is distributed and made + * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * + * Technology Compatibility Kit Test Suite(s) Location: + * http://www.helixcommunity.org/content/tck + * + * Contributor(s): + * + * ***** END LICENSE BLOCK ***** */ + +/************************************************************************************** + * Fixed-point MP3 decoder + * Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com) + * June 2003 + * + * buffers.c - allocation and freeing of internal MP3 decoder buffers + * + * All memory allocation for the codec is done in this file, so if you don't want + * to use other the default system malloc() and free() for heap management this is + * the only file you'll need to change. + **************************************************************************************/ + +#include "include.h" +#include "coder.h" +#include "layer21.h" +#include +#include +#include "mp3common.h" +#include "uart_pub.h" + +#if (CONFIG_APP_MP3PLAYER == 1) +#include "mem_pub.h" +/************************************************************************************** + * Function: ClearBuffer + * + * Description: fill buffer with 0's + * + * Inputs: pointer to buffer + * number of bytes to fill with 0 + * + * Outputs: cleared buffer + * + * Return: none + * + * Notes: slow, platform-independent equivalent to memset(buf, 0, nBytes) + **************************************************************************************/ +void ClearBuffer(void *buf, int nBytes) +{ + int i; + unsigned char *cbuf = (unsigned char *)buf; + + for (i = 0; i < nBytes; i++) + cbuf[i] = 0; + +} + +void ClearMP3(MP3DecInfo *mp3DecInfo) +{ + ClearBuffer(mp3DecInfo->FrameHeaderPS, sizeof(FrameHeader)); + ClearBuffer(mp3DecInfo->SideInfoPS, sizeof(SideInfo)); + ClearBuffer(mp3DecInfo->ScaleFactorInfoPS, sizeof(ScaleFactorInfo)); + ClearBuffer(mp3DecInfo->HuffmanInfoPS, sizeof(HuffmanInfo)); + ClearBuffer(mp3DecInfo->DequantInfoPS, sizeof(DequantInfo)); + ClearBuffer(mp3DecInfo->IMDCTInfoPS, sizeof(IMDCTInfo)); + ClearBuffer(mp3DecInfo->SubbandInfoPS, sizeof(SubbandInfo)); + ClearBuffer(mp3DecInfo->L2DecInfo, sizeof(L2DecodeContext)); + + mp3DecInfo->freeBitrateFlag = 0; + mp3DecInfo->freeBitrateSlots = 0; + + /* user-accessible info */ + mp3DecInfo->bitrate = 0; + mp3DecInfo->nChans = 0; + mp3DecInfo->samprate = 0; + mp3DecInfo->nGrans = 0; /* granules per frame */ + mp3DecInfo->nGranSamps = 0; /* samples per granule */ + mp3DecInfo->nSlots = 0; + mp3DecInfo->layer = 0; +#if CALC_PLAY_TIME + // mp3DecInfo->curFramecnt = 0; + //mp3DecInfo->totalframes = 0; + //mp3DecInfo->filetype = 0; + // mp3DecInfo->timePerframe = 0; +#endif + memset(&mp3DecInfo->version, 0, sizeof(MPEGVersion)); + + mp3DecInfo->mainDataBegin = 0; + mp3DecInfo->mainDataBytes = 0; +} +/************************************************************************************** + * Function: AllocateBuffers + * + * Description: allocate all the memory needed for the MP3 decoder + * + * Inputs: none + * + * Outputs: none + * + * Return: pointer to MP3DecInfo structure (initialized with pointers to all + * the internal buffers needed for decoding, all other members of + * MP3DecInfo structure set to 0) + * + * Notes: if one or more mallocs fail, function frees any buffers already + * allocated before returning + * + * Changed by Kasper Jepsen to support static buffers as well. + * + **************************************************************************************/ +MP3DecInfo *AllocateBuffers(void) +{ + MP3DecInfo *mp3DecInfo_pointer; + FrameHeader *fh; + SideInfo *si; + ScaleFactorInfo *sfi; + HuffmanInfo *hi; + DequantInfo *di; + IMDCTInfo *mi; + SubbandInfo *sbi; + L2DecodeContext *l2i; + + mp3DecInfo_pointer = (MP3DecInfo *)os_malloc(sizeof(MP3DecInfo)); + if(!mp3DecInfo_pointer) + return 0; + + mp3DecInfo_pointer->err_cnt = 0; + mp3DecInfo_pointer->decode_state = MP3_DECODE_NONE; + + sbi = (SubbandInfo *) os_malloc(sizeof(SubbandInfo)); + mi = (IMDCTInfo *) os_malloc(sizeof(IMDCTInfo)); + hi = (HuffmanInfo *) os_malloc(sizeof(HuffmanInfo)); + si = (SideInfo *) os_malloc(sizeof(SideInfo)); + fh = (FrameHeader *) os_malloc(sizeof(FrameHeader)); + sfi = (ScaleFactorInfo *) os_malloc(sizeof(ScaleFactorInfo)); + di = (DequantInfo *) os_malloc(sizeof(DequantInfo)); + l2i = (L2DecodeContext *) os_malloc(sizeof(L2DecodeContext)); + + + if (!fh || !si || !sfi || !hi || !di || !mi || !sbi || !l2i) { + os_printf("sbi=%x\r\n",sbi); + os_printf("sizeof(SubbandInfo)=%d\r\n",sizeof(SubbandInfo)); + + os_printf("mi=%x\r\n",mi); + os_printf("sizeof(IMDCTInfo)=%d\r\n",sizeof(IMDCTInfo)); + + os_printf("hi=%x\r\n",hi); + os_printf("sizeof(HuffmanInfo)=%d\r\n",sizeof(HuffmanInfo)); + + os_printf("si=%x\r\n",si); + os_printf("sizeof(SideInfo)=%d\r\n",sizeof(SideInfo)); + + os_printf("fh=%x\r\n",fh); + os_printf("sizeof(FrameHeader)=%d\r\n",sizeof(FrameHeader)); + + os_printf("sfi=%x\r\n",sfi); + os_printf("sizeof(ScaleFactorInfo)=%d\r\n",sizeof(ScaleFactorInfo)); + + os_printf("di=%x\r\n",di); + os_printf("sizeof(DequantInfo)=%d\r\n",sizeof(DequantInfo)); + + os_printf("l2i=%x\r\n",l2i); + os_printf("sizeof(L2DecodeContext)=%d\r\n",sizeof(L2DecodeContext)); + + os_printf("sizeof=%d\r\n",sizeof(FrameHeader)+sizeof(SideInfo)+sizeof(ScaleFactorInfo)+sizeof(HuffmanInfo)+sizeof(DequantInfo)+sizeof(IMDCTInfo)+sizeof(SubbandInfo)+sizeof(L2DecodeContext)); + + FreeBuffers(mp3DecInfo_pointer); + return 0; + } + + memset(sbi,0,sizeof(SubbandInfo)); + memset(mi,0,sizeof(IMDCTInfo)); + memset(hi,0,sizeof(HuffmanInfo)); + memset(si,0,sizeof(SideInfo)); + memset(fh,0,sizeof(FrameHeader)); + memset(sfi,0,sizeof(ScaleFactorInfo)); + memset(di,0,sizeof(DequantInfo)); + memset(l2i,0,sizeof(L2DecodeContext)); + + mp3DecInfo_pointer->FrameHeaderPS = (void *)fh; + mp3DecInfo_pointer->SideInfoPS = (void *)si; + mp3DecInfo_pointer->ScaleFactorInfoPS = (void *)sfi; + mp3DecInfo_pointer->HuffmanInfoPS = (void *)hi; + mp3DecInfo_pointer->DequantInfoPS = (void *)di; + mp3DecInfo_pointer->IMDCTInfoPS = (void *)mi; + mp3DecInfo_pointer->SubbandInfoPS = (void *)sbi; + mp3DecInfo_pointer->L2DecInfo = (void *)l2i; + + return mp3DecInfo_pointer; +} + +/************************************************************************************** + * Function: FreeBuffers + * + * Description: frees all the memory used by the MP3 decoder + * + * Inputs: pointer to initialized MP3DecInfo structure + * + * Outputs: none + * + * Return: none + * + * Notes: safe to call even if some buffers were not allocated (uses SAFE_FREE) + **************************************************************************************/ +void FreeBuffers(MP3DecInfo *mp3DecInfo) +{ + L2DecodeContext *l2i; + if (!mp3DecInfo) + return; + l2i = (L2DecodeContext *)(mp3DecInfo->L2DecInfo); + + os_free(mp3DecInfo->FrameHeaderPS); + os_free(mp3DecInfo->SideInfoPS); + os_free(mp3DecInfo->ScaleFactorInfoPS); + os_free(mp3DecInfo->HuffmanInfoPS); + os_free(mp3DecInfo->DequantInfoPS); + + l2i->inbuf = NULL; + l2i->inbuf_ptr = NULL; + l2i->sb_samples = NULL; + os_free(mp3DecInfo->L2DecInfo); + os_free(mp3DecInfo->IMDCTInfoPS); + os_free(mp3DecInfo->SubbandInfoPS); + os_free(mp3DecInfo); +} +#endif /* CONFIG_APP_MP3PLAYER */ +//EOF diff --git a/beken_os/beken378/func/music_player/Mp3Lib/coder.h b/beken_os/beken378/func/music_player/Mp3Lib/coder.h new file mode 100755 index 0000000..29c8bb5 --- /dev/null +++ b/beken_os/beken378/func/music_player/Mp3Lib/coder.h @@ -0,0 +1,320 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: RCSL 1.0/RPSL 1.0 + * + * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. + * + * The contents of this file, and the files included with this file, are + * subject to the current version of the RealNetworks Public Source License + * Version 1.0 (the "RPSL") available at + * http://www.helixcommunity.org/content/rpsl unless you have licensed + * the file under the RealNetworks Community Source License Version 1.0 + * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, + * in which case the RCSL will apply. You may also obtain the license terms + * directly from RealNetworks. You may not use this file except in + * compliance with the RPSL or, if you have a valid RCSL with RealNetworks + * applicable to this file, the RCSL. Please see the applicable RPSL or + * RCSL for the rights, obligations and limitations governing use of the + * contents of the file. + * + * This file is part of the Helix DNA Technology. RealNetworks is the + * developer of the Original Code and owns the copyrights in the portions + * it created. + * + * This file, and the files included with this file, is distributed and made + * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * + * Technology Compatibility Kit Test Suite(s) Location: + * http://www.helixcommunity.org/content/tck + * + * Contributor(s): + * + * ***** END LICENSE BLOCK ***** */ + +/************************************************************************************** + * Fixed-point MP3 decoder + * Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com) + * June 2003 + * + * coder.h - private, implementation-specific header file + **************************************************************************************/ + +#ifndef _CODER_H +#define _CODER_H + +#include "include.h" +#include "mp3common.h" + +#if (CONFIG_APP_MP3PLAYER == 1) +#if defined(ASSERT) +#undef ASSERT +#endif +#if defined(_WIN32) && defined(_M_IX86) && (defined (_DEBUG) || defined (REL_ENABLE_ASSERTS)) +#define ASSERT(x) if (!(x)) __asm int 3; +#else +#define ASSERT(x) /* do nothing */ +#endif + +#ifndef MAX +#define MAX(a,b) ((a) > (b) ? (a) : (b)) +#endif + +#ifndef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +/* clip to range [-2^n, 2^n - 1] */ +#define CLIP_2N(y, n) { \ + int sign = (y) >> 31; \ + if (sign != (y) >> (n)) { \ + (y) = sign ^ ((1 << (n)) - 1); \ + } \ +} + +#define SIBYTES_MPEG1_MONO 17 +#define SIBYTES_MPEG1_STEREO 32 +#define SIBYTES_MPEG2_MONO 9 +#define SIBYTES_MPEG2_STEREO 17 + +/* number of fraction bits for pow43Tab (see comments there) */ +#define POW43_FRACBITS_LOW 22 +#define POW43_FRACBITS_HIGH 12 + +#define DQ_FRACBITS_OUT 25 /* number of fraction bits in output of dequant */ +#define IMDCT_SCALE 2 /* additional scaling (by sqrt(2)) for fast IMDCT36 */ + +#define HUFF_PAIRTABS 32 +#define BLOCK_SIZE 18 +#define NBANDS 32 +#define MAX_REORDER_SAMPS ((192-126)*3) /* largest critical band for short blocks (see sfBandTable) */ +#define VBUF_LENGTH (18 * 2 * NBANDS) /* for double-sized vbuf FIFO */ + +/* additional external symbols to name-mangle for static linking */ +#define SetBitstreamPointer STATNAME(SetBitstreamPointer) +#define GetBits STATNAME(GetBits) +#define CalcBitsUsed STATNAME(CalcBitsUsed) +#define DequantChannel STATNAME(DequantChannel) +#define MidSideProc STATNAME(MidSideProc) +#define IntensityProcMPEG1 STATNAME(IntensityProcMPEG1) +#define IntensityProcMPEG2 STATNAME(IntensityProcMPEG2) +#define PolyphaseMono STATNAME(PolyphaseMono) +#define PolyphaseStereo STATNAME(PolyphaseStereo) +#define FDCT32 STATNAME(FDCT32) + +#define ISFMpeg1 STATNAME(ISFMpeg1) +#define ISFMpeg2 STATNAME(ISFMpeg2) +#define ISFIIP STATNAME(ISFIIP) +#define uniqueIDTab STATNAME(uniqueIDTab) +#define coef32 STATNAME(coef32) +#define polyCoef STATNAME(polyCoef) +#define csa STATNAME(csa) +#define imdctWin STATNAME(imdctWin) + +#define huffTable STATNAME(huffTable) +#define huffTabOffset STATNAME(huffTabOffset) +#define huffTabLookup STATNAME(huffTabLookup) +#define quadTable STATNAME(quadTable) +#define quadTabOffset STATNAME(quadTabOffset) +#define quadTabMaxBits STATNAME(quadTabMaxBits) + +#define pcm_Alaw_table STATNAME(pcm_Alaw_table) +#define pcm_Ulaw_table STATNAME(pcm_Ulaw_table) + + +/* map these to the corresponding 2-bit values in the frame header */ +typedef enum { + Stereo = 0x00, /* two independent channels, but L and R frames might have different # of bits */ + Joint = 0x01, /* coupled channels - layer III: mix of M-S and intensity, Layers I/II: intensity and direct coding only */ + Dual = 0x02, /* two independent channels, L and R always have exactly 1/2 the total bitrate */ + Mono = 0x03 /* one channel */ +} StereoMode; + +typedef struct _BitStreamInfo { + unsigned char *bytePtr; + unsigned int iCache; + int cachedBits; + int nBytes; +} BitStreamInfo; + +typedef struct _FrameHeader { + MPEGVersion ver; /* version ID */ + int layer; /* layer index (1, 2, or 3) */ + int crc; /* CRC flag: 0 = disabled, 1 = enabled */ + int brIdx; /* bitrate index (0 - 15) */ + int srIdx; /* sample rate index (0 - 2) */ + int paddingBit; /* padding flag: 0 = no padding, 1 = single pad byte */ + int privateBit; /* unused */ + StereoMode sMode; /* mono/stereo mode */ + int modeExt; /* used to decipher joint stereo mode */ + int copyFlag; /* copyright flag: 0 = no, 1 = yes */ + int origFlag; /* original flag: 0 = copy, 1 = original */ + int emphasis; /* deemphasis mode */ + int CRCWord; /* CRC word (16 bits, 0 if crc not enabled) */ + + const SFBandTable *sfBand; +} FrameHeader; + +typedef struct _SideInfoSub { + int part23Length; /* number of bits in main data */ + int nBigvals; /* 2x this = first set of Huffman cw's (maximum amplitude can be > 1) */ + int globalGain; /* overall gain for dequantizer */ + int sfCompress; /* unpacked to figure out number of bits in scale factors */ + int winSwitchFlag; /* window switching flag */ + int blockType; /* block type */ + int mixedBlock; /* 0 = regular block (all short or long), 1 = mixed block */ + int tableSelect[3]; /* index of Huffman tables for the big values regions */ + int subBlockGain[3]; /* subblock gain offset, relative to global gain */ + int region0Count; /* 1+region0Count = num scale factor bands in first region of bigvals */ + int region1Count; /* 1+region1Count = num scale factor bands in second region of bigvals */ + int preFlag; /* for optional high frequency boost */ + int sfactScale; /* scaling of the scalefactors */ + int count1TableSelect; /* index of Huffman table for quad codewords */ +} SideInfoSub; + +typedef struct _SideInfo { + int mainDataBegin; + int privateBits; + int scfsi[MAX_NCHAN][MAX_SCFBD]; /* 4 scalefactor bands per channel */ + + SideInfoSub sis[MAX_NGRAN][MAX_NCHAN]; +} SideInfo; + +typedef struct { + int cbType; /* pure long = 0, pure short = 1, mixed = 2 */ + int cbEndS[3]; /* number nonzero short cb's, per subbblock */ + int cbEndSMax; /* max of cbEndS[] */ + int cbEndL; /* number nonzero long cb's */ +} CriticalBandInfo; + +typedef struct _DequantInfo { + int workBuf[MAX_REORDER_SAMPS]; /* workbuf for reordering short blocks */ + CriticalBandInfo cbi[MAX_NCHAN]; /* filled in dequantizer, used in joint stereo reconstruction */ +} DequantInfo; + +typedef struct _HuffmanInfo { + int huffDecBuf[MAX_NCHAN][MAX_NSAMP]; /* used both for decoded Huffman values and dequantized coefficients */ + int nonZeroBound[MAX_NCHAN]; /* number of coeffs in huffDecBuf[ch] which can be > 0 */ + int gb[MAX_NCHAN]; /* minimum number of guard bits in huffDecBuf[ch] */ +} HuffmanInfo; + +typedef enum _HuffTabType { + noBits, + oneShot, + loopNoLinbits, + loopLinbits, + quadA, + quadB, + invalidTab +} HuffTabType; + +typedef struct _HuffTabLookup { + int linBits; + HuffTabType tabType; +} HuffTabLookup; + +typedef struct _IMDCTInfo { + int outBuf[MAX_NCHAN][BLOCK_SIZE][NBANDS]; /* output of IMDCT */ + int overBuf[MAX_NCHAN][MAX_NSAMP / 2]; /* overlap-add buffer (by symmetry, only need 1/2 size) */ + int numPrevIMDCT[MAX_NCHAN]; /* how many IMDCT's calculated in this channel on prev. granule */ + int prevType[MAX_NCHAN]; + int prevWinSwitch[MAX_NCHAN]; + int gb[MAX_NCHAN]; +} IMDCTInfo; + +typedef struct _BlockCount { + int nBlocksLong; + int nBlocksTotal; + int nBlocksPrev; + int prevType; + int prevWinSwitch; + int currWinSwitch; + int gbIn; + int gbOut; +} BlockCount; + +/* max bits in scalefactors = 5, so use char's to save space */ +typedef struct _ScaleFactorInfoSub { + char l[23]; /* [band] */ + char s[13][3]; /* [band][window] */ +} ScaleFactorInfoSub; + +/* used in MPEG 2, 2.5 intensity (joint) stereo only */ +typedef struct _ScaleFactorJS { + int intensityScale; + int slen[4]; + int nr[4]; +} ScaleFactorJS; + +typedef struct _ScaleFactorInfo { + ScaleFactorInfoSub sfis[MAX_NGRAN][MAX_NCHAN]; + ScaleFactorJS sfjs; +} ScaleFactorInfo; + +/* NOTE - could get by with smaller vbuf if memory is more important than speed + * (in Subband, instead of replicating each block in FDCT32 you would do a memmove on the + * last 15 blocks to shift them down one, a hardware style FIFO) + */ +typedef struct _SubbandInfo { + int vbuf[MAX_NCHAN * VBUF_LENGTH]; /* vbuf for fast DCT-based synthesis PQMF - double size for speed (no modulo indexing) */ + int vindex; /* internal index for tracking position in vbuf */ +} SubbandInfo; + + +/* bitstream.c */ +void SetBitstreamPointer(BitStreamInfo *bsi, int nBytes, unsigned char *buf); +unsigned int GetBits(BitStreamInfo *bsi, int nBits); +int CalcBitsUsed(BitStreamInfo *bsi, unsigned char *startBuf, int startOffset); + +/* dequant.c, dqchan.c, stproc.c */ +int DequantChannel(int *sampleBuf, int *workBuf, int *nonZeroBound, FrameHeader *fh, SideInfoSub *sis, + ScaleFactorInfoSub *sfis, CriticalBandInfo *cbi); +void MidSideProc(int x[MAX_NCHAN][MAX_NSAMP], int nSamps, int mOut[2]); +void IntensityProcMPEG1(int x[MAX_NCHAN][MAX_NSAMP], int nSamps, FrameHeader *fh, ScaleFactorInfoSub *sfis, + CriticalBandInfo *cbi, int midSideFlag, int mixFlag, int mOut[2]); +void IntensityProcMPEG2(int x[MAX_NCHAN][MAX_NSAMP], int nSamps, FrameHeader *fh, ScaleFactorInfoSub *sfis, + CriticalBandInfo *cbi, ScaleFactorJS *sfjs, int midSideFlag, int mixFlag, int mOut[2]); + +/* dct32.c */ +void FDCT32(int *x, int *d, int offset, int oddBlock, int gb); + +/* hufftabs.c */ +extern const HuffTabLookup huffTabLookup[HUFF_PAIRTABS]; +extern const int huffTabOffset[HUFF_PAIRTABS]; +extern const unsigned short huffTable[]; +extern const unsigned char quadTable[64+16]; +extern const int quadTabOffset[2]; +extern const int quadTabMaxBits[2]; + +/* polyphase.c (or asmpoly.s) + * some platforms require a C++ compile of all source files, + * so if we're compiling C as C++ and using native assembly + * for these functions we need to prevent C++ name mangling. + */ +#ifdef __cplusplus +extern "C" { +#endif +void PolyphaseMono(short *pcm, int *vbuf, const int *coefBase); +void PolyphaseStereo(short *pcm, int *vbuf, const int *coefBase); +#ifdef __cplusplus +} +#endif + +/* trigtabs.c */ +extern const int imdctWin[4][36]; +extern const int ISFMpeg1[2][7]; +extern const int ISFMpeg2[2][2][16]; +extern const int ISFIIP[2][2]; +extern const int csa[8][2]; +extern const int coef32[31]; +extern const int polyCoef[264]; + +/*wav A-law/mu-law*/ + +extern const short pcm_Ulaw_table[256]; +extern const short pcm_Alaw_table[256]; + + +#endif /* CONFIG_APP_MP3PLAYER */ +#endif /* _CODER_H */ diff --git a/beken_os/beken378/func/music_player/Mp3Lib/dct32.c b/beken_os/beken378/func/music_player/Mp3Lib/dct32.c new file mode 100755 index 0000000..dcabfc2 --- /dev/null +++ b/beken_os/beken378/func/music_player/Mp3Lib/dct32.c @@ -0,0 +1,279 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: RCSL 1.0/RPSL 1.0 + * + * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. + * + * The contents of this file, and the files included with this file, are + * subject to the current version of the RealNetworks Public Source License + * Version 1.0 (the "RPSL") available at + * http://www.helixcommunity.org/content/rpsl unless you have licensed + * the file under the RealNetworks Community Source License Version 1.0 + * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, + * in which case the RCSL will apply. You may also obtain the license terms + * directly from RealNetworks. You may not use this file except in + * compliance with the RPSL or, if you have a valid RCSL with RealNetworks + * applicable to this file, the RCSL. Please see the applicable RPSL or + * RCSL for the rights, obligations and limitations governing use of the + * contents of the file. + * + * This file is part of the Helix DNA Technology. RealNetworks is the + * developer of the Original Code and owns the copyrights in the portions + * it created. + * + * This file, and the files included with this file, is distributed and made + * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * + * Technology Compatibility Kit Test Suite(s) Location: + * http://www.helixcommunity.org/content/tck + * + * Contributor(s): + * + * ***** END LICENSE BLOCK ***** */ + +/************************************************************************************** + * Fixed-point MP3 decoder + * Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com) + * June 2003 + * + * dct32.c - optimized implementations of 32-point DCT for matrixing stage of + * polyphase filter + **************************************************************************************/ + +#include "coder.h" +#include "assembly.h" +#if (CONFIG_APP_MP3PLAYER == 1) +#define COS0_0 0x4013c251 /* Q31 */ +#define COS0_1 0x40b345bd /* Q31 */ +#define COS0_2 0x41fa2d6d /* Q31 */ +#define COS0_3 0x43f93421 /* Q31 */ +#define COS0_4 0x46cc1bc4 /* Q31 */ +#define COS0_5 0x4a9d9cf0 /* Q31 */ +#define COS0_6 0x4fae3711 /* Q31 */ +#define COS0_7 0x56601ea7 /* Q31 */ +#define COS0_8 0x5f4cf6eb /* Q31 */ +#define COS0_9 0x6b6fcf26 /* Q31 */ +#define COS0_10 0x7c7d1db3 /* Q31 */ +#define COS0_11 0x4ad81a97 /* Q30 */ +#define COS0_12 0x5efc8d96 /* Q30 */ +#define COS0_13 0x41d95790 /* Q29 */ +#define COS0_14 0x6d0b20cf /* Q29 */ +#define COS0_15 0x518522fb /* Q27 */ + +#define COS1_0 0x404f4672 /* Q31 */ +#define COS1_1 0x42e13c10 /* Q31 */ +#define COS1_2 0x48919f44 /* Q31 */ +#define COS1_3 0x52cb0e63 /* Q31 */ +#define COS1_4 0x64e2402e /* Q31 */ +#define COS1_5 0x43e224a9 /* Q30 */ +#define COS1_6 0x6e3c92c1 /* Q30 */ +#define COS1_7 0x519e4e04 /* Q28 */ + +#define COS2_0 0x4140fb46 /* Q31 */ +#define COS2_1 0x4cf8de88 /* Q31 */ +#define COS2_2 0x73326bbf /* Q31 */ +#define COS2_3 0x52036742 /* Q29 */ + +#define COS3_0 0x4545e9ef /* Q31 */ +#define COS3_1 0x539eba45 /* Q30 */ + +#define COS4_0 0x5a82799a /* Q31 */ + +static const int dcttab[48] = { + /* first pass */ + COS0_0, COS0_15, COS1_0, /* 31, 27, 31 */ + COS0_1, COS0_14, COS1_1, /* 31, 29, 31 */ + COS0_2, COS0_13, COS1_2, /* 31, 29, 31 */ + COS0_3, COS0_12, COS1_3, /* 31, 30, 31 */ + COS0_4, COS0_11, COS1_4, /* 31, 30, 31 */ + COS0_5, COS0_10, COS1_5, /* 31, 31, 30 */ + COS0_6, COS0_9, COS1_6, /* 31, 31, 30 */ + COS0_7, COS0_8, COS1_7, /* 31, 31, 28 */ + /* second pass */ + COS2_0, COS2_3, COS3_0, /* 31, 29, 31 */ + COS2_1, COS2_2, COS3_1, /* 31, 31, 30 */ + -COS2_0, -COS2_3, COS3_0, /* 31, 29, 31 */ + -COS2_1, -COS2_2, COS3_1, /* 31, 31, 30 */ + COS2_0, COS2_3, COS3_0, /* 31, 29, 31 */ + COS2_1, COS2_2, COS3_1, /* 31, 31, 30 */ + -COS2_0, -COS2_3, COS3_0, /* 31, 29, 31 */ + -COS2_1, -COS2_2, COS3_1, /* 31, 31, 30 */ +}; + +#define D32FP(i, s0, s1, s2) { \ + a0 = buf[i]; a3 = buf[31-i]; \ + a1 = buf[15-i]; a2 = buf[16+i]; \ + b0 = a0 + a3; b3 = MULSHIFT32(*cptr++, a0 - a3) << (s0); \ + b1 = a1 + a2; b2 = MULSHIFT32(*cptr++, a1 - a2) << (s1); \ + buf[i] = b0 + b1; buf[15-i] = MULSHIFT32(*cptr, b0 - b1) << (s2); \ + buf[16+i] = b2 + b3; buf[31-i] = MULSHIFT32(*cptr++, b3 - b2) << (s2); \ +} + +/************************************************************************************** + * Function: FDCT32 + * + * Description: Ken's highly-optimized 32-point DCT (radix-4 + radix-8) + * + * Inputs: input buffer, length = 32 samples + * require at least 6 guard bits in input vector x to avoid possibility + * of overflow in internal calculations (see bbtest_imdct test app) + * buffer offset and oddblock flag for polyphase filter input buffer + * number of guard bits in input + * + * Outputs: output buffer, data copied and interleaved for polyphase filter + * no guarantees about number of guard bits in output + * + * Return: none + * + * Notes: number of muls = 4*8 + 12*4 = 80 + * final stage of DCT is hardcoded to shuffle data into the proper order + * for the polyphase filterbank + * fully unrolled stage 1, for max precision (scale the 1/cos() factors + * differently, depending on magnitude) + * guard bit analysis verified by exhaustive testing of all 2^32 + * combinations of max pos/max neg values in x[] + * + * TODO: code organization and optimization for ARM + * possibly interleave stereo (cut # of coef loads in half - may not have + * enough registers) + **************************************************************************************/ +void FDCT32(int *buf, int *dest, int offset, int oddBlock, int gb) +{ + int i, s, tmp, es; + const int *cptr = dcttab; + int a0, a1, a2, a3, a4, a5, a6, a7; + int b0, b1, b2, b3, b4, b5, b6, b7; + int *d; + + /* scaling - ensure at least 6 guard bits for DCT + * (in practice this is already true 99% of time, so this code is + * almost never triggered) + */ + es = 0; + if (gb < 6) { + es = 6 - gb; + for (i = 0; i < 32; i++) + buf[i] >>= es; + } + + /* first pass */ + D32FP(0, 1, 5, 1); + D32FP(1, 1, 3, 1); + D32FP(2, 1, 3, 1); + D32FP(3, 1, 2, 1); + D32FP(4, 1, 2, 1); + D32FP(5, 1, 1, 2); + D32FP(6, 1, 1, 2); + D32FP(7, 1, 1, 4); + + /* second pass */ + for (i = 4; i > 0; i--) { + a0 = buf[0]; a7 = buf[7]; a3 = buf[3]; a4 = buf[4]; + b0 = a0 + a7; b7 = MULSHIFT32(*cptr++, a0 - a7) << 1; + b3 = a3 + a4; b4 = MULSHIFT32(*cptr++, a3 - a4) << 3; + a0 = b0 + b3; a3 = MULSHIFT32(*cptr, b0 - b3) << 1; + a4 = b4 + b7; a7 = MULSHIFT32(*cptr++, b7 - b4) << 1; + + a1 = buf[1]; a6 = buf[6]; a2 = buf[2]; a5 = buf[5]; + b1 = a1 + a6; b6 = MULSHIFT32(*cptr++, a1 - a6) << 1; + b2 = a2 + a5; b5 = MULSHIFT32(*cptr++, a2 - a5) << 1; + a1 = b1 + b2; a2 = MULSHIFT32(*cptr, b1 - b2) << 2; + a5 = b5 + b6; a6 = MULSHIFT32(*cptr++, b6 - b5) << 2; + + b0 = a0 + a1; b1 = MULSHIFT32(COS4_0, a0 - a1) << 1; + b2 = a2 + a3; b3 = MULSHIFT32(COS4_0, a3 - a2) << 1; + buf[0] = b0; buf[1] = b1; + buf[2] = b2 + b3; buf[3] = b3; + + b4 = a4 + a5; b5 = MULSHIFT32(COS4_0, a4 - a5) << 1; + b6 = a6 + a7; b7 = MULSHIFT32(COS4_0, a7 - a6) << 1; + b6 += b7; + buf[4] = b4 + b6; buf[5] = b5 + b7; + buf[6] = b5 + b6; buf[7] = b7; + + buf += 8; + } + buf -= 32; /* reset */ + + /* sample 0 - always delayed one block */ + d = dest + 64*16 + ((offset - oddBlock) & 7) + (oddBlock ? 0 : VBUF_LENGTH); + s = buf[ 0]; d[0] = d[8] = s; + + /* samples 16 to 31 */ + d = dest + offset + (oddBlock ? VBUF_LENGTH : 0); + + s = buf[ 1]; d[0] = d[8] = s; d += 64; + + tmp = buf[25] + buf[29]; + s = buf[17] + tmp; d[0] = d[8] = s; d += 64; + s = buf[ 9] + buf[13]; d[0] = d[8] = s; d += 64; + s = buf[21] + tmp; d[0] = d[8] = s; d += 64; + + tmp = buf[29] + buf[27]; + s = buf[ 5]; d[0] = d[8] = s; d += 64; + s = buf[21] + tmp; d[0] = d[8] = s; d += 64; + s = buf[13] + buf[11]; d[0] = d[8] = s; d += 64; + s = buf[19] + tmp; d[0] = d[8] = s; d += 64; + + tmp = buf[27] + buf[31]; + s = buf[ 3]; d[0] = d[8] = s; d += 64; + s = buf[19] + tmp; d[0] = d[8] = s; d += 64; + s = buf[11] + buf[15]; d[0] = d[8] = s; d += 64; + s = buf[23] + tmp; d[0] = d[8] = s; d += 64; + + tmp = buf[31]; + s = buf[ 7]; d[0] = d[8] = s; d += 64; + s = buf[23] + tmp; d[0] = d[8] = s; d += 64; + s = buf[15]; d[0] = d[8] = s; d += 64; + s = tmp; d[0] = d[8] = s; + + /* samples 16 to 1 (sample 16 used again) */ + d = dest + 16 + ((offset - oddBlock) & 7) + (oddBlock ? 0 : VBUF_LENGTH); + + s = buf[ 1]; d[0] = d[8] = s; d += 64; + + tmp = buf[30] + buf[25]; + s = buf[17] + tmp; d[0] = d[8] = s; d += 64; + s = buf[14] + buf[ 9]; d[0] = d[8] = s; d += 64; + s = buf[22] + tmp; d[0] = d[8] = s; d += 64; + s = buf[ 6]; d[0] = d[8] = s; d += 64; + + tmp = buf[26] + buf[30]; + s = buf[22] + tmp; d[0] = d[8] = s; d += 64; + s = buf[10] + buf[14]; d[0] = d[8] = s; d += 64; + s = buf[18] + tmp; d[0] = d[8] = s; d += 64; + s = buf[ 2]; d[0] = d[8] = s; d += 64; + + tmp = buf[28] + buf[26]; + s = buf[18] + tmp; d[0] = d[8] = s; d += 64; + s = buf[12] + buf[10]; d[0] = d[8] = s; d += 64; + s = buf[20] + tmp; d[0] = d[8] = s; d += 64; + s = buf[ 4]; d[0] = d[8] = s; d += 64; + + tmp = buf[24] + buf[28]; + s = buf[20] + tmp; d[0] = d[8] = s; d += 64; + s = buf[ 8] + buf[12]; d[0] = d[8] = s; d += 64; + s = buf[16] + tmp; d[0] = d[8] = s; + + /* this is so rarely invoked that it's not worth making two versions of the output + * shuffle code (one for no shift, one for clip + variable shift) like in IMDCT + * here we just load, clip, shift, and store on the rare instances that es != 0 + */ + if (es) { + d = dest + 64*16 + ((offset - oddBlock) & 7) + (oddBlock ? 0 : VBUF_LENGTH); + s = d[0]; CLIP_2N(s, 31 - es); d[0] = d[8] = (s << es); + + d = dest + offset + (oddBlock ? VBUF_LENGTH : 0); + for (i = 16; i <= 31; i++) { + s = d[0]; CLIP_2N(s, 31 - es); d[0] = d[8] = (s << es); d += 64; + } + + d = dest + 16 + ((offset - oddBlock) & 7) + (oddBlock ? 0 : VBUF_LENGTH); + for (i = 15; i >= 0; i--) { + s = d[0]; CLIP_2N(s, 31 - es); d[0] = d[8] = (s << es); d += 64; + } + } +} +#endif /* CONFIG_APP_MP3PLAYER */ diff --git a/beken_os/beken378/func/music_player/Mp3Lib/dequant.c b/beken_os/beken378/func/music_player/Mp3Lib/dequant.c new file mode 100755 index 0000000..cf3f49e --- /dev/null +++ b/beken_os/beken378/func/music_player/Mp3Lib/dequant.c @@ -0,0 +1,159 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: RCSL 1.0/RPSL 1.0 + * + * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. + * + * The contents of this file, and the files included with this file, are + * subject to the current version of the RealNetworks Public Source License + * Version 1.0 (the "RPSL") available at + * http://www.helixcommunity.org/content/rpsl unless you have licensed + * the file under the RealNetworks Community Source License Version 1.0 + * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, + * in which case the RCSL will apply. You may also obtain the license terms + * directly from RealNetworks. You may not use this file except in + * compliance with the RPSL or, if you have a valid RCSL with RealNetworks + * applicable to this file, the RCSL. Please see the applicable RPSL or + * RCSL for the rights, obligations and limitations governing use of the + * contents of the file. + * + * This file is part of the Helix DNA Technology. RealNetworks is the + * developer of the Original Code and owns the copyrights in the portions + * it created. + * + * This file, and the files included with this file, is distributed and made + * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * + * Technology Compatibility Kit Test Suite(s) Location: + * http://www.helixcommunity.org/content/tck + * + * Contributor(s): + * + * ***** END LICENSE BLOCK ***** */ + +/************************************************************************************** + * Fixed-point MP3 decoder + * Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com) + * June 2003 + * + * dequant.c - dequantization, stereo processing (intensity, mid-side), short-block + * coefficient reordering + **************************************************************************************/ + +#include "coder.h" +#include "assembly.h" +#if (CONFIG_APP_MP3PLAYER == 1) +/************************************************************************************** + * Function: Dequantize + * + * Description: dequantize coefficients, decode stereo, reorder short blocks + * (one granule-worth) + * + * Inputs: MP3DecInfo structure filled by UnpackFrameHeader(), UnpackSideInfo(), + * UnpackScaleFactors(), and DecodeHuffman() (for this granule) + * index of current granule + * + * Outputs: dequantized and reordered coefficients in hi->huffDecBuf + * (one granule-worth, all channels), format = Q26 + * operates in-place on huffDecBuf but also needs di->workBuf + * updated hi->nonZeroBound index for both channels + * + * Return: 0 on success, -1 if null input pointers + * + * Notes: In calling output Q(DQ_FRACBITS_OUT), we assume an implicit bias + * of 2^15. Some (floating-point) reference implementations factor this + * into the 2^(0.25 * gain) scaling explicitly. But to avoid precision + * loss, we don't do that. Instead take it into account in the final + * round to PCM (>> by 15 less than we otherwise would have). + * Equivalently, we can think of the dequantized coefficients as + * Q(DQ_FRACBITS_OUT - 15) with no implicit bias. + **************************************************************************************/ +int Dequantize(MP3DecInfo *mp3DecInfo, int gr) +{ + int i, ch, nSamps, mOut[2]; + FrameHeader *fh; + SideInfo *si; + ScaleFactorInfo *sfi; + HuffmanInfo *hi; + DequantInfo *di; + CriticalBandInfo *cbi; + + /* validate pointers */ + if (!mp3DecInfo || !mp3DecInfo->FrameHeaderPS || !mp3DecInfo->SideInfoPS || !mp3DecInfo->ScaleFactorInfoPS || + !mp3DecInfo->HuffmanInfoPS || !mp3DecInfo->DequantInfoPS) + return -1; + + fh = (FrameHeader *)(mp3DecInfo->FrameHeaderPS); + + /* si is an array of up to 4 structs, stored as gr0ch0, gr0ch1, gr1ch0, gr1ch1 */ + si = (SideInfo *)(mp3DecInfo->SideInfoPS); + sfi = (ScaleFactorInfo *)(mp3DecInfo->ScaleFactorInfoPS); + hi = (HuffmanInfo *)mp3DecInfo->HuffmanInfoPS; + di = (DequantInfo *)mp3DecInfo->DequantInfoPS; + cbi = di->cbi; + mOut[0] = mOut[1] = 0; + + /* dequantize all the samples in each channel */ + for (ch = 0; ch < mp3DecInfo->nChans; ch++) { + hi->gb[ch] = DequantChannel(hi->huffDecBuf[ch], di->workBuf, &hi->nonZeroBound[ch], fh, + &si->sis[gr][ch], &sfi->sfis[gr][ch], &cbi[ch]); + } + + /* joint stereo processing assumes one guard bit in input samples + * it's extremely rare not to have at least one gb, so if this is the case + * just make a pass over the data and clip to [-2^30+1, 2^30-1] + * in practice this may never happen + */ + if (fh->modeExt && (hi->gb[0] < 1 || hi->gb[1] < 1)) { + for (i = 0; i < hi->nonZeroBound[0]; i++) { + if (hi->huffDecBuf[0][i] < -0x3fffffff) hi->huffDecBuf[0][i] = -0x3fffffff; + if (hi->huffDecBuf[0][i] > 0x3fffffff) hi->huffDecBuf[0][i] = 0x3fffffff; + } + for (i = 0; i < hi->nonZeroBound[1]; i++) { + if (hi->huffDecBuf[1][i] < -0x3fffffff) hi->huffDecBuf[1][i] = -0x3fffffff; + if (hi->huffDecBuf[1][i] > 0x3fffffff) hi->huffDecBuf[1][i] = 0x3fffffff; + } + } + + /* do mid-side stereo processing, if enabled */ + if (fh->modeExt >> 1) { + if (fh->modeExt & 0x01) { + /* intensity stereo enabled - run mid-side up to start of right zero region */ + if (cbi[1].cbType == 0) + nSamps = fh->sfBand->l[cbi[1].cbEndL + 1]; + else + nSamps = 3 * fh->sfBand->s[cbi[1].cbEndSMax + 1]; + } else { + /* intensity stereo disabled - run mid-side on whole spectrum */ + nSamps = MAX(hi->nonZeroBound[0], hi->nonZeroBound[1]); + } + MidSideProc(hi->huffDecBuf, nSamps, mOut); + } + + /* do intensity stereo processing, if enabled */ + if (fh->modeExt & 0x01) { + nSamps = hi->nonZeroBound[0]; + if (fh->ver == MPEG1) { + IntensityProcMPEG1(hi->huffDecBuf, nSamps, fh, &sfi->sfis[gr][1], di->cbi, + fh->modeExt >> 1, si->sis[gr][1].mixedBlock, mOut); + } else { + IntensityProcMPEG2(hi->huffDecBuf, nSamps, fh, &sfi->sfis[gr][1], di->cbi, &sfi->sfjs, + fh->modeExt >> 1, si->sis[gr][1].mixedBlock, mOut); + } + } + + /* adjust guard bit count and nonZeroBound if we did any stereo processing */ + if (fh->modeExt) { + hi->gb[0] = CLZ(mOut[0]) - 1; + hi->gb[1] = CLZ(mOut[1]) - 1; + nSamps = MAX(hi->nonZeroBound[0], hi->nonZeroBound[1]); + hi->nonZeroBound[0] = nSamps; + hi->nonZeroBound[1] = nSamps; + } + + /* output format Q(DQ_FRACBITS_OUT) */ + return 0; +} +#endif /* CONFIG_APP_MP3PLAYER */ diff --git a/beken_os/beken378/func/music_player/Mp3Lib/dqchan.c b/beken_os/beken378/func/music_player/Mp3Lib/dqchan.c new file mode 100755 index 0000000..3028f3c --- /dev/null +++ b/beken_os/beken378/func/music_player/Mp3Lib/dqchan.c @@ -0,0 +1,373 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: RCSL 1.0/RPSL 1.0 + * + * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. + * + * The contents of this file, and the files included with this file, are + * subject to the current version of the RealNetworks Public Source License + * Version 1.0 (the "RPSL") available at + * http://www.helixcommunity.org/content/rpsl unless you have licensed + * the file under the RealNetworks Community Source License Version 1.0 + * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, + * in which case the RCSL will apply. You may also obtain the license terms + * directly from RealNetworks. You may not use this file except in + * compliance with the RPSL or, if you have a valid RCSL with RealNetworks + * applicable to this file, the RCSL. Please see the applicable RPSL or + * RCSL for the rights, obligations and limitations governing use of the + * contents of the file. + * + * This file is part of the Helix DNA Technology. RealNetworks is the + * developer of the Original Code and owns the copyrights in the portions + * it created. + * + * This file, and the files included with this file, is distributed and made + * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * + * Technology Compatibility Kit Test Suite(s) Location: + * http://www.helixcommunity.org/content/tck + * + * Contributor(s): + * + * ***** END LICENSE BLOCK ***** */ + +/************************************************************************************** + * Fixed-point MP3 decoder + * Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com) + * August 2003 + * + * dqchan.c - dequantization of transform coefficients + **************************************************************************************/ + +#include "coder.h" +#include "assembly.h" +#if (CONFIG_APP_MP3PLAYER == 1) +typedef int ARRAY3[3]; /* for short-block reordering */ + +/* optional pre-emphasis for high-frequency scale factor bands */ +static const char preTab[22] = { 0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,2,2,3,3,3,2,0 }; + +/* pow(2,-i/4) for i=0..3, Q31 format */ +static const int pow14[4] = { + 0x7fffffff, 0x6ba27e65, 0x5a82799a, 0x4c1bf829 +}; + +/* pow(2,-i/4) * pow(j,4/3) for i=0..3 j=0..15, Q25 format */ +static const int pow43_14[4][16] = { +{ 0x00000000, 0x10000000, 0x285145f3, 0x453a5cdb, /* Q28 */ + 0x0cb2ff53, 0x111989d6, 0x15ce31c8, 0x1ac7f203, + 0x20000000, 0x257106b9, 0x2b16b4a3, 0x30ed74b4, + 0x36f23fa5, 0x3d227bd3, 0x437be656, 0x49fc823c, }, + +{ 0x00000000, 0x0d744fcd, 0x21e71f26, 0x3a36abd9, + 0x0aadc084, 0x0e610e6e, 0x12560c1d, 0x168523cf, + 0x1ae89f99, 0x1f7c03a4, 0x243bae49, 0x29249c67, + 0x2e34420f, 0x33686f85, 0x38bf3dff, 0x3e370182, }, + +{ 0x00000000, 0x0b504f33, 0x1c823e07, 0x30f39a55, + 0x08facd62, 0x0c176319, 0x0f6b3522, 0x12efe2ad, + 0x16a09e66, 0x1a79a317, 0x1e77e301, 0x2298d5b4, + 0x26da56fc, 0x2b3a902a, 0x2fb7e7e7, 0x3450f650, }, + +{ 0x00000000, 0x09837f05, 0x17f910d7, 0x2929c7a9, + 0x078d0dfa, 0x0a2ae661, 0x0cf73154, 0x0fec91cb, + 0x1306fe0a, 0x16434a6c, 0x199ee595, 0x1d17ae3d, + 0x20abd76a, 0x2459d551, 0x28204fbb, 0x2bfe1808, }, +}; + +/* pow(j,4/3) for j=16..63, Q23 format */ +static const int pow43[] = { + 0x1428a2fa, 0x15db1bd6, 0x1796302c, 0x19598d85, + 0x1b24e8bb, 0x1cf7fcfa, 0x1ed28af2, 0x20b4582a, + 0x229d2e6e, 0x248cdb55, 0x26832fda, 0x28800000, + 0x2a832287, 0x2c8c70a8, 0x2e9bc5d8, 0x30b0ff99, + 0x32cbfd4a, 0x34eca001, 0x3712ca62, 0x393e6088, + 0x3b6f47e0, 0x3da56717, 0x3fe0a5fc, 0x4220ed72, + 0x44662758, 0x46b03e7c, 0x48ff1e87, 0x4b52b3f3, + 0x4daaebfd, 0x5007b497, 0x5268fc62, 0x54ceb29c, + 0x5738c721, 0x59a72a59, 0x5c19cd35, 0x5e90a129, + 0x610b9821, 0x638aa47f, 0x660db90f, 0x6894c90b, + 0x6b1fc80c, 0x6daeaa0d, 0x70416360, 0x72d7e8b0, + 0x75722ef9, 0x78102b85, 0x7ab1d3ec, 0x7d571e09, +}; + +/* sqrt(0.5) in Q31 format */ +#define SQRTHALF 0x5a82799a + +/* + * Minimax polynomial approximation to pow(x, 4/3), over the range + * poly43lo: x = [0.5, 0.7071] + * poly43hi: x = [0.7071, 1.0] + * + * Relative error < 1E-7 + * Coefs are scaled by 4, 2, 1, 0.5, 0.25 + */ +static const int poly43lo[5] = { 0x29a0bda9, 0xb02e4828, 0x5957aa1b, 0x236c498d, 0xff581859 }; +static const int poly43hi[5] = { 0x10852163, 0xd333f6a4, 0x46e9408b, 0x27c2cef0, 0xfef577b4 }; + +/* pow(2, i*4/3) as exp and frac */ +static const int pow2exp[8] = { 14, 13, 11, 10, 9, 7, 6, 5 }; + +static const int pow2frac[8] = { + 0x6597fa94, 0x50a28be6, 0x7fffffff, 0x6597fa94, + 0x50a28be6, 0x7fffffff, 0x6597fa94, 0x50a28be6 +}; + +/************************************************************************************** + * Function: DequantBlock + * + * Description: Ken's highly-optimized, low memory dequantizer performing the operation + * y = pow(x, 4.0/3.0) * pow(2, 25 - scale/4.0) + * + * Inputs: input buffer of decode Huffman codewords (signed-magnitude) + * output buffer of same length (in-place (outbuf = inbuf) is allowed) + * number of samples + * + * Outputs: dequantized samples in Q25 format + * + * Return: bitwise-OR of the unsigned outputs (for guard bit calculations) + **************************************************************************************/ +static int DequantBlock(int *inbuf, int *outbuf, int num, int scale) +{ + int tab4[4]; + int scalef, scalei, shift; + int sx, x, y; + int mask = 0; + const int *tab16, *coef; + + tab16 = pow43_14[scale & 0x3]; + scalef = pow14[scale & 0x3]; + scalei = MIN(scale >> 2, 31); /* smallest input scale = -47, so smallest scalei = -12 */ + + /* cache first 4 values */ + shift = MIN(scalei + 3, 31); + shift = MAX(shift, 0); + tab4[0] = 0; + tab4[1] = tab16[1] >> shift; + tab4[2] = tab16[2] >> shift; + tab4[3] = tab16[3] >> shift; + + do { + + sx = *inbuf++; + x = sx & 0x7fffffff; /* sx = sign|mag */ + + if (x < 4) { + + y = tab4[x]; + + } else if (x < 16) { + + y = tab16[x]; + y = (scalei < 0) ? y << -scalei : y >> scalei; + + } else { + + if (x < 64) { + + y = pow43[x-16]; + + /* fractional scale */ + y = MULSHIFT32(y, scalef); + shift = scalei - 3; + + } else { + + /* normalize to [0x40000000, 0x7fffffff] */ + x <<= 17; + shift = 0; + if (x < 0x08000000) + x <<= 4, shift += 4; + if (x < 0x20000000) + x <<= 2, shift += 2; + if (x < 0x40000000) + x <<= 1, shift += 1; + + coef = (x < SQRTHALF) ? poly43lo : poly43hi; + + /* polynomial */ + y = coef[0]; + y = MULSHIFT32(y, x) + coef[1]; + y = MULSHIFT32(y, x) + coef[2]; + y = MULSHIFT32(y, x) + coef[3]; + y = MULSHIFT32(y, x) + coef[4]; + y = MULSHIFT32(y, pow2frac[shift]) << 3; + + /* fractional scale */ + y = MULSHIFT32(y, scalef); + shift = scalei - pow2exp[shift]; + } + + /* integer scale */ + if (shift < 0) { + shift = -shift; + if (y > (0x7fffffff >> shift)) + y = 0x7fffffff; /* clip */ + else + y <<= shift; + } else { + y >>= shift; + } + } + + /* sign and store */ + mask |= y; + *outbuf++ = (sx < 0) ? -y : y; + + } while (--num); + + return mask; +} + +/************************************************************************************** + * Function: DequantChannel + * + * Description: dequantize one granule, one channel worth of decoded Huffman codewords + * + * Inputs: sample buffer (decoded Huffman codewords), length = MAX_NSAMP samples + * work buffer for reordering short-block, length = MAX_REORDER_SAMPS + * samples (3 * width of largest short-block critical band) + * non-zero bound for this channel/granule + * valid FrameHeader, SideInfoSub, ScaleFactorInfoSub, and CriticalBandInfo + * structures for this channel/granule + * + * Outputs: MAX_NSAMP dequantized samples in sampleBuf + * updated non-zero bound (indicating which samples are != 0 after DQ) + * filled-in cbi structure indicating start and end critical bands + * + * Return: minimum number of guard bits in dequantized sampleBuf + * + * Notes: dequantized samples in Q(DQ_FRACBITS_OUT) format + **************************************************************************************/ +int DequantChannel(int *sampleBuf, int *workBuf, int *nonZeroBound, FrameHeader *fh, SideInfoSub *sis, + ScaleFactorInfoSub *sfis, CriticalBandInfo *cbi) +{ + int i, j, w, cb; + int cbEndL, cbStartS, cbEndS; + int nSamps, nonZero, sfactMultiplier, gbMask; + int globalGain, gainI; + int cbMax[3]; + ARRAY3 *buf; /* short block reorder */ + + /* set default start/end points for short/long blocks - will update with non-zero cb info */ + if (sis->blockType == 2) { + if (sis->mixedBlock) { + cbEndL = (fh->ver == MPEG1 ? 8 : 6); + cbStartS = 3; + } else { + cbEndL = 0; + cbStartS = 0; + } + cbEndS = 13; + } else { + /* long block */ + cbEndL = 22; + cbStartS = 13; + cbEndS = 13; + } + cbMax[2] = cbMax[1] = cbMax[0] = 0; + gbMask = 0; + i = 0; + + /* sfactScale = 0 --> quantizer step size = 2 + * sfactScale = 1 --> quantizer step size = sqrt(2) + * so sfactMultiplier = 2 or 4 (jump through globalGain by powers of 2 or sqrt(2)) + */ + sfactMultiplier = 2 * (sis->sfactScale + 1); + + /* offset globalGain by -2 if midSide enabled, for 1/sqrt(2) used in MidSideProc() + * (DequantBlock() does 0.25 * gainI so knocking it down by two is the same as + * dividing every sample by sqrt(2) = multiplying by 2^-.5) + */ + globalGain = sis->globalGain; + if (fh->modeExt >> 1) + globalGain -= 2; + globalGain += IMDCT_SCALE; /* scale everything by sqrt(2), for fast IMDCT36 */ + + /* long blocks */ + for (cb = 0; cb < cbEndL; cb++) { + + nonZero = 0; + nSamps = fh->sfBand->l[cb + 1] - fh->sfBand->l[cb]; + gainI = 210 - globalGain + sfactMultiplier * (sfis->l[cb] + (sis->preFlag ? (int)preTab[cb] : 0)); + + nonZero |= DequantBlock(sampleBuf + i, sampleBuf + i, nSamps, gainI); + i += nSamps; + + /* update highest non-zero critical band */ + if (nonZero) + cbMax[0] = cb; + gbMask |= nonZero; + + if (i >= *nonZeroBound) + break; + } + + /* set cbi (Type, EndS[], EndSMax will be overwritten if we proceed to do short blocks) */ + cbi->cbType = 0; /* long only */ + cbi->cbEndL = cbMax[0]; + cbi->cbEndS[0] = cbi->cbEndS[1] = cbi->cbEndS[2] = 0; + cbi->cbEndSMax = 0; + + /* early exit if no short blocks */ + if (cbStartS >= 12) + return CLZ(gbMask) - 1; + + /* short blocks */ + cbMax[2] = cbMax[1] = cbMax[0] = cbStartS; + for (cb = cbStartS; cb < cbEndS; cb++) { + + nSamps = fh->sfBand->s[cb + 1] - fh->sfBand->s[cb]; + for (w = 0; w < 3; w++) { + nonZero = 0; + gainI = 210 - globalGain + 8*sis->subBlockGain[w] + sfactMultiplier*(sfis->s[cb][w]); + + nonZero |= DequantBlock(sampleBuf + i + nSamps*w, workBuf + nSamps*w, nSamps, gainI); + + /* update highest non-zero critical band */ + if (nonZero) + cbMax[w] = cb; + gbMask |= nonZero; + } + + /* reorder blocks */ + buf = (ARRAY3 *)(sampleBuf + i); + i += 3*nSamps; + for (j = 0; j < nSamps; j++) { + buf[j][0] = workBuf[0*nSamps + j]; + buf[j][1] = workBuf[1*nSamps + j]; + buf[j][2] = workBuf[2*nSamps + j]; + } + + ASSERT(3*nSamps <= MAX_REORDER_SAMPS); + + if (i >= *nonZeroBound) + break; + } + + /* i = last non-zero INPUT sample processed, which corresponds to highest possible non-zero + * OUTPUT sample (after reorder) + * however, the original nzb is no longer necessarily true + * for each cb, buf[][] is updated with 3*nSamps samples (i increases 3*nSamps each time) + * (buf[j + 1][0] = 3 (input) samples ahead of buf[j][0]) + * so update nonZeroBound to i + */ + *nonZeroBound = i; + + ASSERT(*nonZeroBound <= MAX_NSAMP); + + cbi->cbType = (sis->mixedBlock ? 2 : 1); /* 2 = mixed short/long, 1 = short only */ + + cbi->cbEndS[0] = cbMax[0]; + cbi->cbEndS[1] = cbMax[1]; + cbi->cbEndS[2] = cbMax[2]; + + cbi->cbEndSMax = cbMax[0]; + cbi->cbEndSMax = MAX(cbi->cbEndSMax, cbMax[1]); + cbi->cbEndSMax = MAX(cbi->cbEndSMax, cbMax[2]); + + return CLZ(gbMask) - 1; +} +#endif /* CONFIG_APP_MP3PLAYER */ diff --git a/beken_os/beken378/func/music_player/Mp3Lib/huffman.c b/beken_os/beken378/func/music_player/Mp3Lib/huffman.c new file mode 100755 index 0000000..6a0b020 --- /dev/null +++ b/beken_os/beken378/func/music_player/Mp3Lib/huffman.c @@ -0,0 +1,459 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: RCSL 1.0/RPSL 1.0 + * + * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. + * + * The contents of this file, and the files included with this file, are + * subject to the current version of the RealNetworks Public Source License + * Version 1.0 (the "RPSL") available at + * http://www.helixcommunity.org/content/rpsl unless you have licensed + * the file under the RealNetworks Community Source License Version 1.0 + * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, + * in which case the RCSL will apply. You may also obtain the license terms + * directly from RealNetworks. You may not use this file except in + * compliance with the RPSL or, if you have a valid RCSL with RealNetworks + * applicable to this file, the RCSL. Please see the applicable RPSL or + * RCSL for the rights, obligations and limitations governing use of the + * contents of the file. + * + * This file is part of the Helix DNA Technology. RealNetworks is the + * developer of the Original Code and owns the copyrights in the portions + * it created. + * + * This file, and the files included with this file, is distributed and made + * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * + * Technology Compatibility Kit Test Suite(s) Location: + * http://www.helixcommunity.org/content/tck + * + * Contributor(s): + * + * ***** END LICENSE BLOCK ***** */ + +/************************************************************************************** + * Fixed-point MP3 decoder + * Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com) + * July 2003 + * + * huffman.c - Huffman decoding of transform coefficients + **************************************************************************************/ + +#include "coder.h" +#if (CONFIG_APP_MP3PLAYER == 1) +/* helper macros - see comments in hufftabs.c about the format of the huffman tables */ +#define GetMaxbits(x) ((int)( (((unsigned short)(x)) >> 0) & 0x000f)) +#define GetHLen(x) ((int)( (((unsigned short)(x)) >> 12) & 0x000f)) +#define GetCWY(x) ((int)( (((unsigned short)(x)) >> 8) & 0x000f)) +#define GetCWX(x) ((int)( (((unsigned short)(x)) >> 4) & 0x000f)) +#define GetSignBits(x) ((int)( (((unsigned short)(x)) >> 0) & 0x000f)) + +#define GetHLenQ(x) ((int)( (((unsigned char)(x)) >> 4) & 0x0f)) +#define GetCWVQ(x) ((int)( (((unsigned char)(x)) >> 3) & 0x01)) +#define GetCWWQ(x) ((int)( (((unsigned char)(x)) >> 2) & 0x01)) +#define GetCWXQ(x) ((int)( (((unsigned char)(x)) >> 1) & 0x01)) +#define GetCWYQ(x) ((int)( (((unsigned char)(x)) >> 0) & 0x01)) + +/* apply sign of s to the positive number x (save in MSB, will do two's complement in dequant) */ +#define ApplySign(x, s) { (x) |= ((s) & 0x80000000); } + +/************************************************************************************** + * Function: DecodeHuffmanPairs + * + * Description: decode 2-way vector Huffman codes in the "bigValues" region of spectrum + * + * Inputs: valid BitStreamInfo struct, pointing to start of pair-wise codes + * pointer to xy buffer to received decoded values + * number of codewords to decode + * index of Huffman table to use + * number of bits remaining in bitstream + * + * Outputs: pairs of decoded coefficients in vwxy + * updated BitStreamInfo struct + * + * Return: number of bits used, or -1 if out of bits + * + * Notes: assumes that nVals is an even number + * si_huff.bit tests every Huffman codeword in every table (though not + * necessarily all linBits outputs for x,y > 15) + **************************************************************************************/ +static int DecodeHuffmanPairs(int *xy, int nVals, int tabIdx, int bitsLeft, unsigned char *buf, int bitOffset) +{ + int i, x, y; + int cachedBits, padBits, len, startBits, linBits, maxBits, minBits; + HuffTabType tabType; + unsigned short cw, *tBase, *tCurr; + unsigned int cache; + + if(nVals <= 0) + return 0; + + if (bitsLeft < 0) + return -1; + startBits = bitsLeft; + + tBase = (unsigned short *)(huffTable + huffTabOffset[tabIdx]); + linBits = huffTabLookup[tabIdx].linBits; + tabType = huffTabLookup[tabIdx].tabType; + + ASSERT(!(nVals & 0x01)); + ASSERT(tabIdx < HUFF_PAIRTABS); + ASSERT(tabIdx >= 0); + ASSERT(tabType != invalidTab); + + /* initially fill cache with any partial byte */ + cache = 0; + cachedBits = (8 - bitOffset) & 0x07; + if (cachedBits) + cache = (unsigned int)(*buf++) << (32 - cachedBits); + bitsLeft -= cachedBits; + + if (tabType == noBits) { + /* table 0, no data, x = y = 0 */ + for (i = 0; i < nVals; i+=2) { + xy[i+0] = 0; + xy[i+1] = 0; + } + return 0; + } else if (tabType == oneShot) { + /* single lookup, no escapes */ + maxBits = GetMaxbits(tBase[0]); + tBase++; + padBits = 0; + while (nVals > 0) { + /* refill cache - assumes cachedBits <= 16 */ + if (bitsLeft >= 16) { + /* load 2 new bytes into left-justified cache */ + cache |= (unsigned int)(*buf++) << (24 - cachedBits); + cache |= (unsigned int)(*buf++) << (16 - cachedBits); + cachedBits += 16; + bitsLeft -= 16; + } else { + /* last time through, pad cache with zeros and drain cache */ + if (cachedBits + bitsLeft <= 0) return -1; + if (bitsLeft > 0) cache |= (unsigned int)(*buf++) << (24 - cachedBits); + if (bitsLeft > 8) cache |= (unsigned int)(*buf++) << (16 - cachedBits); + cachedBits += bitsLeft; + bitsLeft = 0; + + cache &= (signed int)0x80000000 >> (cachedBits - 1); + padBits = 11; + cachedBits += padBits; /* okay if this is > 32 (0's automatically shifted in from right) */ + } + + /* largest maxBits = 9, plus 2 for sign bits, so make sure cache has at least 11 bits */ + while (nVals > 0 && cachedBits >= 11 ) { + cw = tBase[cache >> (32 - maxBits)]; + len = GetHLen(cw); + cachedBits -= len; + cache <<= len; + + x = GetCWX(cw); if (x) {ApplySign(x, cache); cache <<= 1; cachedBits--;} + y = GetCWY(cw); if (y) {ApplySign(y, cache); cache <<= 1; cachedBits--;} + + /* ran out of bits - should never have consumed padBits */ + if (cachedBits < padBits) + return -1; + + *xy++ = x; + *xy++ = y; + nVals -= 2; + } + } + bitsLeft += (cachedBits - padBits); + return (startBits - bitsLeft); + } else if (tabType == loopLinbits || tabType == loopNoLinbits) { + tCurr = tBase; + padBits = 0; + while (nVals > 0) { + /* refill cache - assumes cachedBits <= 16 */ + if (bitsLeft >= 16) { + /* load 2 new bytes into left-justified cache */ + cache |= (unsigned int)(*buf++) << (24 - cachedBits); + cache |= (unsigned int)(*buf++) << (16 - cachedBits); + cachedBits += 16; + bitsLeft -= 16; + } else { + /* last time through, pad cache with zeros and drain cache */ + if (cachedBits + bitsLeft <= 0) return -1; + if (bitsLeft > 0) cache |= (unsigned int)(*buf++) << (24 - cachedBits); + if (bitsLeft > 8) cache |= (unsigned int)(*buf++) << (16 - cachedBits); + cachedBits += bitsLeft; + bitsLeft = 0; + + cache &= (signed int)0x80000000 >> (cachedBits - 1); + padBits = 11; + cachedBits += padBits; /* okay if this is > 32 (0's automatically shifted in from right) */ + } + + /* largest maxBits = 9, plus 2 for sign bits, so make sure cache has at least 11 bits */ + while (nVals > 0 && cachedBits >= 11 ) { + maxBits = GetMaxbits(tCurr[0]); + cw = tCurr[(cache >> (32 - maxBits)) + 1]; + len = GetHLen(cw); + if (!len) { + cachedBits -= maxBits; + cache <<= maxBits; + tCurr += cw; + continue; + } + cachedBits -= len; + cache <<= len; + + x = GetCWX(cw); + y = GetCWY(cw); + + if (x == 15 && tabType == loopLinbits) { + minBits = linBits + 1 + (y ? 1 : 0); + if (cachedBits + bitsLeft < minBits) + return -1; + while (cachedBits < minBits) { + cache |= (unsigned int)(*buf++) << (24 - cachedBits); + cachedBits += 8; + bitsLeft -= 8; + } + if (bitsLeft < 0) { + cachedBits += bitsLeft; + bitsLeft = 0; + cache &= (signed int)0x80000000 >> (cachedBits - 1); + } + x += (int)(cache >> (32 - linBits)); + cachedBits -= linBits; + cache <<= linBits; + } + if (x) {ApplySign(x, cache); cache <<= 1; cachedBits--;} + + if (y == 15 && tabType == loopLinbits) { + minBits = linBits + 1; + if (cachedBits + bitsLeft < minBits) + return -1; + while (cachedBits < minBits) { + cache |= (unsigned int)(*buf++) << (24 - cachedBits); + cachedBits += 8; + bitsLeft -= 8; + } + if (bitsLeft < 0) { + cachedBits += bitsLeft; + bitsLeft = 0; + cache &= (signed int)0x80000000 >> (cachedBits - 1); + } + y += (int)(cache >> (32 - linBits)); + cachedBits -= linBits; + cache <<= linBits; + } + if (y) {ApplySign(y, cache); cache <<= 1; cachedBits--;} + + /* ran out of bits - should never have consumed padBits */ + if (cachedBits < padBits) + return -1; + + *xy++ = x; + *xy++ = y; + nVals -= 2; + tCurr = tBase; + } + } + bitsLeft += (cachedBits - padBits); + return (startBits - bitsLeft); + } + + /* error in bitstream - trying to access unused Huffman table */ + return -1; +} + +/************************************************************************************** + * Function: DecodeHuffmanQuads + * + * Description: decode 4-way vector Huffman codes in the "count1" region of spectrum + * + * Inputs: valid BitStreamInfo struct, pointing to start of quadword codes + * pointer to vwxy buffer to received decoded values + * maximum number of codewords to decode + * index of quadword table (0 = table A, 1 = table B) + * number of bits remaining in bitstream + * + * Outputs: quadruples of decoded coefficients in vwxy + * updated BitStreamInfo struct + * + * Return: index of the first "zero_part" value (index of the first sample + * of the quad word after which all samples are 0) + * + * Notes: si_huff.bit tests every vwxy output in both quad tables + **************************************************************************************/ +static int DecodeHuffmanQuads(int *vwxy, int nVals, int tabIdx, int bitsLeft, unsigned char *buf, int bitOffset) +{ + int i, v, w, x, y; + int len, maxBits, cachedBits, padBits; + unsigned int cache; + unsigned char cw, *tBase; + + if (bitsLeft <= 0) + return 0; + + tBase = (unsigned char *)quadTable + quadTabOffset[tabIdx]; + maxBits = quadTabMaxBits[tabIdx]; + + /* initially fill cache with any partial byte */ + cache = 0; + cachedBits = (8 - bitOffset) & 0x07; + if (cachedBits) + cache = (unsigned int)(*buf++) << (32 - cachedBits); + bitsLeft -= cachedBits; + + i = padBits = 0; + while (i < (nVals - 3)) { + /* refill cache - assumes cachedBits <= 16 */ + if (bitsLeft >= 16) { + /* load 2 new bytes into left-justified cache */ + cache |= (unsigned int)(*buf++) << (24 - cachedBits); + cache |= (unsigned int)(*buf++) << (16 - cachedBits); + cachedBits += 16; + bitsLeft -= 16; + } else { + /* last time through, pad cache with zeros and drain cache */ + if (cachedBits + bitsLeft <= 0) return i; + if (bitsLeft > 0) cache |= (unsigned int)(*buf++) << (24 - cachedBits); + if (bitsLeft > 8) cache |= (unsigned int)(*buf++) << (16 - cachedBits); + cachedBits += bitsLeft; + bitsLeft = 0; + + cache &= (signed int)0x80000000 >> (cachedBits - 1); + padBits = 10; + cachedBits += padBits; /* okay if this is > 32 (0's automatically shifted in from right) */ + } + + /* largest maxBits = 6, plus 4 for sign bits, so make sure cache has at least 10 bits */ + while (i < (nVals - 3) && cachedBits >= 10 ) { + cw = tBase[cache >> (32 - maxBits)]; + len = GetHLenQ(cw); + cachedBits -= len; + cache <<= len; + + v = GetCWVQ(cw); if(v) {ApplySign(v, cache); cache <<= 1; cachedBits--;} + w = GetCWWQ(cw); if(w) {ApplySign(w, cache); cache <<= 1; cachedBits--;} + x = GetCWXQ(cw); if(x) {ApplySign(x, cache); cache <<= 1; cachedBits--;} + y = GetCWYQ(cw); if(y) {ApplySign(y, cache); cache <<= 1; cachedBits--;} + + /* ran out of bits - okay (means we're done) */ + if (cachedBits < padBits) + return i; + + *vwxy++ = v; + *vwxy++ = w; + *vwxy++ = x; + *vwxy++ = y; + i += 4; + } + } + + /* decoded max number of quad values */ + return i; +} + +/************************************************************************************** + * Function: DecodeHuffman + * + * Description: decode one granule, one channel worth of Huffman codes + * + * Inputs: MP3DecInfo structure filled by UnpackFrameHeader(), UnpackSideInfo(), + * and UnpackScaleFactors() (for this granule) + * buffer pointing to start of Huffman data in MP3 frame + * pointer to bit offset (0-7) indicating starting bit in buf[0] + * number of bits in the Huffman data section of the frame + * (could include padding bits) + * index of current granule and channel + * + * Outputs: decoded coefficients in hi->huffDecBuf[ch] (hi pointer in mp3DecInfo) + * updated bitOffset + * + * Return: length (in bytes) of Huffman codes + * bitOffset also returned in parameter (0 = MSB, 7 = LSB of + * byte located at buf + offset) + * -1 if null input pointers, huffBlockBits < 0, or decoder runs + * out of bits prematurely (invalid bitstream) + **************************************************************************************/ +int DecodeHuffman(MP3DecInfo *mp3DecInfo, unsigned char *buf, int *bitOffset, int huffBlockBits, int gr, int ch) +{ + int r1Start, r2Start, rEnd[4]; /* region boundaries */ + int i, w, bitsUsed, bitsLeft; + unsigned char *startBuf = buf; + + FrameHeader *fh; + SideInfo *si; + SideInfoSub *sis; + //ScaleFactorInfo *sfi; + HuffmanInfo *hi; + + /* validate pointers */ + if (!mp3DecInfo || !mp3DecInfo->FrameHeaderPS || !mp3DecInfo->SideInfoPS || !mp3DecInfo->ScaleFactorInfoPS || !mp3DecInfo->HuffmanInfoPS) + return -1; + + fh = ((FrameHeader *)(mp3DecInfo->FrameHeaderPS)); + si = ((SideInfo *)(mp3DecInfo->SideInfoPS)); + sis = &si->sis[gr][ch]; + //sfi = ((ScaleFactorInfo *)(mp3DecInfo->ScaleFactorInfoPS)); + hi = (HuffmanInfo*)(mp3DecInfo->HuffmanInfoPS); + + if (huffBlockBits < 0) + return -1; + + /* figure out region boundaries (the first 2*bigVals coefficients divided into 3 regions) */ + if (sis->winSwitchFlag && sis->blockType == 2) { + if (sis->mixedBlock == 0) { + r1Start = fh->sfBand->s[(sis->region0Count + 1)/3] * 3; + } else { + if (fh->ver == MPEG1) { + r1Start = fh->sfBand->l[sis->region0Count + 1]; + } else { + /* see MPEG2 spec for explanation */ + w = fh->sfBand->s[4] - fh->sfBand->s[3]; + r1Start = fh->sfBand->l[6] + 2*w; + } + } + r2Start = MAX_NSAMP; /* short blocks don't have region 2 */ + } else { + r1Start = fh->sfBand->l[sis->region0Count + 1]; + r2Start = fh->sfBand->l[sis->region0Count + 1 + sis->region1Count + 1]; + } + + /* offset rEnd index by 1 so first region = rEnd[1] - rEnd[0], etc. */ + rEnd[3] = MIN(MAX_NSAMP, 2 * sis->nBigvals); + rEnd[2] = MIN(r2Start, rEnd[3]); + rEnd[1] = MIN(r1Start, rEnd[3]); + rEnd[0] = 0; + + /* rounds up to first all-zero pair (we don't check last pair for (x,y) == (non-zero, zero)) */ + hi->nonZeroBound[ch] = rEnd[3]; + + /* decode Huffman pairs (rEnd[i] are always even numbers) */ + bitsLeft = huffBlockBits; + for (i = 0; i < 3; i++) { + bitsUsed = DecodeHuffmanPairs(hi->huffDecBuf[ch] + rEnd[i], rEnd[i+1] - rEnd[i], sis->tableSelect[i], bitsLeft, buf, *bitOffset); + if (bitsUsed < 0 || bitsUsed > bitsLeft) /* error - overran end of bitstream */ + return -1; + + /* update bitstream position */ + buf += (bitsUsed + *bitOffset) >> 3; + *bitOffset = (bitsUsed + *bitOffset) & 0x07; + bitsLeft -= bitsUsed; + } + + /* decode Huffman quads (if any) */ + hi->nonZeroBound[ch] += DecodeHuffmanQuads(hi->huffDecBuf[ch] + rEnd[3], MAX_NSAMP - rEnd[3], sis->count1TableSelect, bitsLeft, buf, *bitOffset); + + ASSERT(hi->nonZeroBound[ch] <= MAX_NSAMP); + for (i = hi->nonZeroBound[ch]; i < MAX_NSAMP; i++) + hi->huffDecBuf[ch][i] = 0; + + /* If bits used for 576 samples < huffBlockBits, then the extras are considered + * to be stuffing bits (throw away, but need to return correct bitstream position) + */ + buf += (bitsLeft + *bitOffset) >> 3; + *bitOffset = (bitsLeft + *bitOffset) & 0x07; + + return (buf - startBuf); +} +#endif /* CONFIG_APP_MP3PLAYER */ + diff --git a/beken_os/beken378/func/music_player/Mp3Lib/hufftabs.c b/beken_os/beken378/func/music_player/Mp3Lib/hufftabs.c new file mode 100755 index 0000000..7de586e --- /dev/null +++ b/beken_os/beken378/func/music_player/Mp3Lib/hufftabs.c @@ -0,0 +1,756 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: RCSL 1.0/RPSL 1.0 + * + * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. + * + * The contents of this file, and the files included with this file, are + * subject to the current version of the RealNetworks Public Source License + * Version 1.0 (the "RPSL") available at + * http://www.helixcommunity.org/content/rpsl unless you have licensed + * the file under the RealNetworks Community Source License Version 1.0 + * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, + * in which case the RCSL will apply. You may also obtain the license terms + * directly from RealNetworks. You may not use this file except in + * compliance with the RPSL or, if you have a valid RCSL with RealNetworks + * applicable to this file, the RCSL. Please see the applicable RPSL or + * RCSL for the rights, obligations and limitations governing use of the + * contents of the file. + * + * This file is part of the Helix DNA Technology. RealNetworks is the + * developer of the Original Code and owns the copyrights in the portions + * it created. + * + * This file, and the files included with this file, is distributed and made + * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * + * Technology Compatibility Kit Test Suite(s) Location: + * http://www.helixcommunity.org/content/tck + * + * Contributor(s): + * + * ***** END LICENSE BLOCK ***** */ + +/************************************************************************************** + * Fixed-point MP3 decoder + * Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com) + * June 2003 + * + * hufftabs.c - compressed Huffman code tables + **************************************************************************************/ + +#include "coder.h" +#if (CONFIG_APP_MP3PLAYER == 1) +/* NOTE - regenerated tables to use shorts instead of ints + * (all needed data can fit in 16 bits - see below) + * + * format 0xABCD + * A = length of codeword + * B = y value + * C = x value + * D = number of sign bits (0, 1, or 2) + * + * to read a CW, the code reads maxbits from the stream (dep. on + * table index), but doesn't remove them from the bitstream reader + * then it gets the correct CW by direct lookup into the table + * of length (2^maxbits) (more complicated for non-oneShot...) + * for CW's with hlen < maxbits, there are multiple entries in the + * table (extra bits are don't cares) + * the bitstream reader then "purges" (or removes) only the correct + * number of bits for the chosen CW + * + * entries starting with F are special: D (signbits) is maxbits, + * so the decoder always checks huffTableXX[0] first, gets the + * signbits, and reads that many bits from the bitstream + * (sometimes it takes > 1 read to get the value, so maxbits is + * can get updated by jumping to another value starting with 0xF) + * entries starting with 0 are also special: A = hlen = 0, rest of + * value is an offset to jump higher in the table (for tables of + * type loopNoLinbits or loopLinbits) + */ + +/* store Huffman codes as one big table plus table of offsets, since some platforms + * don't properly support table-of-tables (table of pointers to other const tables) + */ +const unsigned short huffTable[] = { + /* huffTable01[9] */ + 0xf003, 0x3112, 0x3101, 0x2011, 0x2011, 0x1000, 0x1000, 0x1000, + 0x1000, + + /* huffTable02[65] */ + 0xf006, 0x6222, 0x6201, 0x5212, 0x5212, 0x5122, 0x5122, 0x5021, + 0x5021, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, + 0x3112, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, + 0x3101, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, + 0x3011, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, + + /* huffTable03[65] */ + 0xf006, 0x6222, 0x6201, 0x5212, 0x5212, 0x5122, 0x5122, 0x5021, + 0x5021, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, + 0x3011, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, + 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, + 0x2112, 0x2101, 0x2101, 0x2101, 0x2101, 0x2101, 0x2101, 0x2101, + 0x2101, 0x2101, 0x2101, 0x2101, 0x2101, 0x2101, 0x2101, 0x2101, + 0x2101, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, + 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, + 0x2000, + + /* huffTable05[257] */ + 0xf008, 0x8332, 0x8322, 0x7232, 0x7232, 0x6132, 0x6132, 0x6132, + 0x6132, 0x7312, 0x7312, 0x7301, 0x7301, 0x7031, 0x7031, 0x7222, + 0x7222, 0x6212, 0x6212, 0x6212, 0x6212, 0x6122, 0x6122, 0x6122, + 0x6122, 0x6201, 0x6201, 0x6201, 0x6201, 0x6021, 0x6021, 0x6021, + 0x6021, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, + 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, + 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, + 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, + 0x3112, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, + 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, + 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, + 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, + 0x3101, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, + 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, + 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, + 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, + 0x3011, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, + + /* huffTable06[129] */ + 0xf007, 0x7332, 0x7301, 0x6322, 0x6322, 0x6232, 0x6232, 0x6031, + 0x6031, 0x5312, 0x5312, 0x5312, 0x5312, 0x5132, 0x5132, 0x5132, + 0x5132, 0x5222, 0x5222, 0x5222, 0x5222, 0x5201, 0x5201, 0x5201, + 0x5201, 0x4212, 0x4212, 0x4212, 0x4212, 0x4212, 0x4212, 0x4212, + 0x4212, 0x4122, 0x4122, 0x4122, 0x4122, 0x4122, 0x4122, 0x4122, + 0x4122, 0x4021, 0x4021, 0x4021, 0x4021, 0x4021, 0x4021, 0x4021, + 0x4021, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, + 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, + 0x3101, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, + 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, + 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, + 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, + 0x2112, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, + 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, + 0x3011, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, + 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, + 0x3000, + + /* huffTable07[110] */ + 0xf006, 0x0041, 0x0052, 0x005b, 0x0060, 0x0063, 0x0068, 0x006b, + 0x6212, 0x5122, 0x5122, 0x6201, 0x6021, 0x4112, 0x4112, 0x4112, + 0x4112, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, + 0x3101, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, + 0x3011, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0xf004, 0x4552, 0x4542, 0x4452, 0x4352, 0x3532, 0x3532, + 0x3442, 0x3442, 0x3522, 0x3522, 0x3252, 0x3252, 0x2512, 0x2512, + 0x2512, 0x2512, 0xf003, 0x2152, 0x2152, 0x3501, 0x3432, 0x2051, + 0x2051, 0x3342, 0x3332, 0xf002, 0x2422, 0x2242, 0x1412, 0x1412, + 0xf001, 0x1142, 0x1041, 0xf002, 0x2401, 0x2322, 0x2232, 0x2301, + 0xf001, 0x1312, 0x1132, 0xf001, 0x1031, 0x1222, + + /* huffTable08[280] */ + 0xf008, 0x0101, 0x010a, 0x010f, 0x8512, 0x8152, 0x0112, 0x0115, + 0x8422, 0x8242, 0x8412, 0x7142, 0x7142, 0x8401, 0x8041, 0x8322, + 0x8232, 0x8312, 0x8132, 0x8301, 0x8031, 0x6222, 0x6222, 0x6222, + 0x6222, 0x6201, 0x6201, 0x6201, 0x6201, 0x6021, 0x6021, 0x6021, + 0x6021, 0x4212, 0x4212, 0x4212, 0x4212, 0x4212, 0x4212, 0x4212, + 0x4212, 0x4212, 0x4212, 0x4212, 0x4212, 0x4212, 0x4212, 0x4212, + 0x4212, 0x4122, 0x4122, 0x4122, 0x4122, 0x4122, 0x4122, 0x4122, + 0x4122, 0x4122, 0x4122, 0x4122, 0x4122, 0x4122, 0x4122, 0x4122, + 0x4122, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, + 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, + 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, + 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, + 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, + 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, + 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, + 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, 0x2112, + 0x2112, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, + 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, + 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, + 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, + 0x3101, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, + 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, + 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, + 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, + 0x3011, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, + 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, + 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, + 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, + 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, + 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, + 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, + 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, + 0x2000, 0xf003, 0x3552, 0x3452, 0x2542, 0x2542, 0x1352, 0x1352, + 0x1352, 0x1352, 0xf002, 0x2532, 0x2442, 0x1522, 0x1522, 0xf001, + 0x1252, 0x1501, 0xf001, 0x1432, 0x1342, 0xf001, 0x1051, 0x1332, + + /* huffTable09[93] */ + 0xf006, 0x0041, 0x004a, 0x004f, 0x0052, 0x0057, 0x005a, 0x6412, + 0x6142, 0x6322, 0x6232, 0x5312, 0x5312, 0x5132, 0x5132, 0x6301, + 0x6031, 0x5222, 0x5222, 0x5201, 0x5201, 0x4212, 0x4212, 0x4212, + 0x4212, 0x4122, 0x4122, 0x4122, 0x4122, 0x4021, 0x4021, 0x4021, + 0x4021, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, + 0x3112, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, + 0x3101, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, + 0x3011, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, + 0x3000, 0xf003, 0x3552, 0x3542, 0x2532, 0x2532, 0x2352, 0x2352, + 0x3452, 0x3501, 0xf002, 0x2442, 0x2522, 0x2252, 0x2512, 0xf001, + 0x1152, 0x1432, 0xf002, 0x1342, 0x1342, 0x2051, 0x2401, 0xf001, + 0x1422, 0x1242, 0xf001, 0x1332, 0x1041, + + /* huffTable10[320] */ + 0xf008, 0x0101, 0x010a, 0x010f, 0x0118, 0x011b, 0x0120, 0x0125, + 0x8712, 0x8172, 0x012a, 0x012d, 0x0132, 0x8612, 0x8162, 0x8061, + 0x0137, 0x013a, 0x013d, 0x8412, 0x8142, 0x8041, 0x8322, 0x8232, + 0x8301, 0x7312, 0x7312, 0x7132, 0x7132, 0x7031, 0x7031, 0x7222, + 0x7222, 0x6212, 0x6212, 0x6212, 0x6212, 0x6122, 0x6122, 0x6122, + 0x6122, 0x6201, 0x6201, 0x6201, 0x6201, 0x6021, 0x6021, 0x6021, + 0x6021, 0x4112, 0x4112, 0x4112, 0x4112, 0x4112, 0x4112, 0x4112, + 0x4112, 0x4112, 0x4112, 0x4112, 0x4112, 0x4112, 0x4112, 0x4112, + 0x4112, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, + 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, + 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, + 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, + 0x3101, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, + 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, + 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, + 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, + 0x3011, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0xf003, 0x3772, 0x3762, 0x3672, 0x3752, 0x3572, 0x3662, + 0x2742, 0x2742, 0xf002, 0x2472, 0x2652, 0x2562, 0x2732, 0xf003, + 0x2372, 0x2372, 0x2642, 0x2642, 0x3552, 0x3452, 0x2362, 0x2362, + 0xf001, 0x1722, 0x1272, 0xf002, 0x2462, 0x2701, 0x1071, 0x1071, + 0xf002, 0x1262, 0x1262, 0x2542, 0x2532, 0xf002, 0x1601, 0x1601, + 0x2352, 0x2442, 0xf001, 0x1632, 0x1622, 0xf002, 0x2522, 0x2252, + 0x1512, 0x1512, 0xf002, 0x1152, 0x1152, 0x2432, 0x2342, 0xf001, + 0x1501, 0x1051, 0xf001, 0x1422, 0x1242, 0xf001, 0x1332, 0x1401, + + /* huffTable11[296] */ + 0xf008, 0x0101, 0x0106, 0x010f, 0x0114, 0x0117, 0x8722, 0x8272, + 0x011c, 0x7172, 0x7172, 0x8712, 0x8071, 0x8632, 0x8362, 0x8061, + 0x011f, 0x0122, 0x8512, 0x7262, 0x7262, 0x8622, 0x8601, 0x7612, + 0x7612, 0x7162, 0x7162, 0x8152, 0x8432, 0x8051, 0x0125, 0x8422, + 0x8242, 0x8412, 0x8142, 0x8401, 0x8041, 0x7322, 0x7322, 0x7232, + 0x7232, 0x6312, 0x6312, 0x6312, 0x6312, 0x6132, 0x6132, 0x6132, + 0x6132, 0x7301, 0x7301, 0x7031, 0x7031, 0x6222, 0x6222, 0x6222, + 0x6222, 0x5122, 0x5122, 0x5122, 0x5122, 0x5122, 0x5122, 0x5122, + 0x5122, 0x4212, 0x4212, 0x4212, 0x4212, 0x4212, 0x4212, 0x4212, + 0x4212, 0x4212, 0x4212, 0x4212, 0x4212, 0x4212, 0x4212, 0x4212, + 0x4212, 0x5201, 0x5201, 0x5201, 0x5201, 0x5201, 0x5201, 0x5201, + 0x5201, 0x5021, 0x5021, 0x5021, 0x5021, 0x5021, 0x5021, 0x5021, + 0x5021, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, + 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, + 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, + 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, + 0x3112, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, + 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, + 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, + 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, + 0x3101, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, + 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, + 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, + 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, + 0x3011, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, + 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, + 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, + 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, + 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, + 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, + 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, + 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, 0x2000, + 0x2000, 0xf002, 0x2772, 0x2762, 0x2672, 0x2572, 0xf003, 0x2662, + 0x2662, 0x2742, 0x2742, 0x2472, 0x2472, 0x3752, 0x3552, 0xf002, + 0x2652, 0x2562, 0x1732, 0x1732, 0xf001, 0x1372, 0x1642, 0xf002, + 0x2542, 0x2452, 0x2532, 0x2352, 0xf001, 0x1462, 0x1701, 0xf001, + 0x1442, 0x1522, 0xf001, 0x1252, 0x1501, 0xf001, 0x1342, 0x1332, + + /* huffTable12[185] */ + 0xf007, 0x0081, 0x008a, 0x008f, 0x0092, 0x0097, 0x009a, 0x009d, + 0x00a2, 0x00a5, 0x00a8, 0x7622, 0x7262, 0x7162, 0x00ad, 0x00b0, + 0x00b3, 0x7512, 0x7152, 0x7432, 0x7342, 0x00b6, 0x7422, 0x7242, + 0x7412, 0x6332, 0x6332, 0x6142, 0x6142, 0x6322, 0x6322, 0x6232, + 0x6232, 0x7041, 0x7301, 0x6031, 0x6031, 0x5312, 0x5312, 0x5312, + 0x5312, 0x5132, 0x5132, 0x5132, 0x5132, 0x5222, 0x5222, 0x5222, + 0x5222, 0x4212, 0x4212, 0x4212, 0x4212, 0x4212, 0x4212, 0x4212, + 0x4212, 0x4122, 0x4122, 0x4122, 0x4122, 0x4122, 0x4122, 0x4122, + 0x4122, 0x5201, 0x5201, 0x5201, 0x5201, 0x5021, 0x5021, 0x5021, + 0x5021, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, + 0x4000, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, + 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, + 0x3112, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, + 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, 0x3101, + 0x3101, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, + 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, + 0x3011, 0xf003, 0x3772, 0x3762, 0x2672, 0x2672, 0x2752, 0x2752, + 0x2572, 0x2572, 0xf002, 0x2662, 0x2742, 0x2472, 0x2562, 0xf001, + 0x1652, 0x1732, 0xf002, 0x2372, 0x2552, 0x1722, 0x1722, 0xf001, + 0x1272, 0x1642, 0xf001, 0x1462, 0x1712, 0xf002, 0x1172, 0x1172, + 0x2701, 0x2071, 0xf001, 0x1632, 0x1362, 0xf001, 0x1542, 0x1452, + 0xf002, 0x1442, 0x1442, 0x2601, 0x2501, 0xf001, 0x1612, 0x1061, + 0xf001, 0x1532, 0x1352, 0xf001, 0x1522, 0x1252, 0xf001, 0x1051, + 0x1401, + + /* huffTable13[497] */ + 0xf006, 0x0041, 0x0082, 0x00c3, 0x00e4, 0x0105, 0x0116, 0x011f, + 0x0130, 0x0139, 0x013e, 0x0143, 0x0146, 0x6212, 0x6122, 0x6201, + 0x6021, 0x4112, 0x4112, 0x4112, 0x4112, 0x4101, 0x4101, 0x4101, + 0x4101, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, + 0x3011, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0xf006, 0x0108, 0x0111, 0x011a, 0x0123, 0x012c, 0x0131, + 0x0136, 0x013f, 0x0144, 0x0147, 0x014c, 0x0151, 0x0156, 0x015b, + 0x6f12, 0x61f2, 0x60f1, 0x0160, 0x0163, 0x0166, 0x62e2, 0x0169, + 0x6e12, 0x61e2, 0x016c, 0x016f, 0x0172, 0x0175, 0x0178, 0x017b, + 0x66c2, 0x6d32, 0x017e, 0x6d22, 0x62d2, 0x6d12, 0x67b2, 0x0181, + 0x0184, 0x63c2, 0x0187, 0x6b42, 0x51d2, 0x51d2, 0x6d01, 0x60d1, + 0x6a82, 0x68a2, 0x6c42, 0x64c2, 0x6b62, 0x66b2, 0x5c32, 0x5c32, + 0x5c22, 0x5c22, 0x52c2, 0x52c2, 0x5b52, 0x5b52, 0x65b2, 0x6982, + 0x5c12, 0x5c12, 0xf006, 0x51c2, 0x51c2, 0x6892, 0x6c01, 0x50c1, + 0x50c1, 0x64b2, 0x6a62, 0x66a2, 0x6972, 0x5b32, 0x5b32, 0x53b2, + 0x53b2, 0x6882, 0x6a52, 0x5b22, 0x5b22, 0x65a2, 0x6962, 0x54a2, + 0x54a2, 0x6872, 0x6782, 0x5492, 0x5492, 0x6772, 0x6672, 0x42b2, + 0x42b2, 0x42b2, 0x42b2, 0x4b12, 0x4b12, 0x4b12, 0x4b12, 0x41b2, + 0x41b2, 0x41b2, 0x41b2, 0x5b01, 0x5b01, 0x50b1, 0x50b1, 0x5692, + 0x5692, 0x5a42, 0x5a42, 0x5a32, 0x5a32, 0x53a2, 0x53a2, 0x5952, + 0x5952, 0x5592, 0x5592, 0x4a22, 0x4a22, 0x4a22, 0x4a22, 0x42a2, + 0x42a2, 0x42a2, 0x42a2, 0xf005, 0x4a12, 0x4a12, 0x41a2, 0x41a2, + 0x5a01, 0x5862, 0x40a1, 0x40a1, 0x5682, 0x5942, 0x4392, 0x4392, + 0x5932, 0x5852, 0x5582, 0x5762, 0x4922, 0x4922, 0x4292, 0x4292, + 0x5752, 0x5572, 0x4832, 0x4832, 0x4382, 0x4382, 0x5662, 0x5742, + 0x5472, 0x5652, 0x5562, 0x5372, 0xf005, 0x3912, 0x3912, 0x3912, + 0x3912, 0x3192, 0x3192, 0x3192, 0x3192, 0x4901, 0x4901, 0x4091, + 0x4091, 0x4842, 0x4842, 0x4482, 0x4482, 0x4272, 0x4272, 0x5642, + 0x5462, 0x3822, 0x3822, 0x3822, 0x3822, 0x3282, 0x3282, 0x3282, + 0x3282, 0x3812, 0x3812, 0x3812, 0x3812, 0xf004, 0x4732, 0x4722, + 0x3712, 0x3712, 0x3172, 0x3172, 0x4552, 0x4701, 0x4071, 0x4632, + 0x4362, 0x4542, 0x4452, 0x4622, 0x4262, 0x4532, 0xf003, 0x2182, + 0x2182, 0x3801, 0x3081, 0x3612, 0x3162, 0x3601, 0x3061, 0xf004, + 0x4352, 0x4442, 0x3522, 0x3522, 0x3252, 0x3252, 0x3501, 0x3501, + 0x2512, 0x2512, 0x2512, 0x2512, 0x2152, 0x2152, 0x2152, 0x2152, + 0xf003, 0x3432, 0x3342, 0x3051, 0x3422, 0x3242, 0x3332, 0x2412, + 0x2412, 0xf002, 0x1142, 0x1142, 0x2401, 0x2041, 0xf002, 0x2322, + 0x2232, 0x1312, 0x1312, 0xf001, 0x1132, 0x1301, 0xf001, 0x1031, + 0x1222, 0xf003, 0x0082, 0x008b, 0x008e, 0x0091, 0x0094, 0x0097, + 0x3ce2, 0x3dd2, 0xf003, 0x0093, 0x3eb2, 0x3be2, 0x3f92, 0x39f2, + 0x3ae2, 0x3db2, 0x3bd2, 0xf003, 0x3f82, 0x38f2, 0x3cc2, 0x008d, + 0x3e82, 0x0090, 0x27f2, 0x27f2, 0xf003, 0x2ad2, 0x2ad2, 0x3da2, + 0x3cb2, 0x3bc2, 0x36f2, 0x2f62, 0x2f62, 0xf002, 0x28e2, 0x2f52, + 0x2d92, 0x29d2, 0xf002, 0x25f2, 0x27e2, 0x2ca2, 0x2bb2, 0xf003, + 0x2f42, 0x2f42, 0x24f2, 0x24f2, 0x3ac2, 0x36e2, 0x23f2, 0x23f2, + 0xf002, 0x1f32, 0x1f32, 0x2d82, 0x28d2, 0xf001, 0x1f22, 0x12f2, + 0xf002, 0x2e62, 0x2c92, 0x1f01, 0x1f01, 0xf002, 0x29c2, 0x2e52, + 0x1ba2, 0x1ba2, 0xf002, 0x2d72, 0x27d2, 0x1e42, 0x1e42, 0xf002, + 0x28c2, 0x26d2, 0x1e32, 0x1e32, 0xf002, 0x19b2, 0x19b2, 0x2b92, + 0x2aa2, 0xf001, 0x1ab2, 0x15e2, 0xf001, 0x14e2, 0x1c82, 0xf001, + 0x1d62, 0x13e2, 0xf001, 0x1e22, 0x1e01, 0xf001, 0x10e1, 0x1d52, + 0xf001, 0x15d2, 0x1c72, 0xf001, 0x17c2, 0x1d42, 0xf001, 0x1b82, + 0x18b2, 0xf001, 0x14d2, 0x1a92, 0xf001, 0x19a2, 0x1c62, 0xf001, + 0x13d2, 0x1b72, 0xf001, 0x1c52, 0x15c2, 0xf001, 0x1992, 0x1a72, + 0xf001, 0x17a2, 0x1792, 0xf003, 0x0023, 0x3df2, 0x2de2, 0x2de2, + 0x1ff2, 0x1ff2, 0x1ff2, 0x1ff2, 0xf001, 0x1fe2, 0x1fd2, 0xf001, + 0x1ee2, 0x1fc2, 0xf001, 0x1ed2, 0x1fb2, 0xf001, 0x1bf2, 0x1ec2, + 0xf002, 0x1cd2, 0x1cd2, 0x2fa2, 0x29e2, 0xf001, 0x1af2, 0x1dc2, + 0xf001, 0x1ea2, 0x1e92, 0xf001, 0x1f72, 0x1e72, 0xf001, 0x1ef2, + 0x1cf2, + + /* huffTable15[580] */ + 0xf008, 0x0101, 0x0122, 0x0143, 0x0154, 0x0165, 0x0176, 0x017f, + 0x0188, 0x0199, 0x01a2, 0x01ab, 0x01b4, 0x01bd, 0x01c2, 0x01cb, + 0x01d4, 0x01d9, 0x01de, 0x01e3, 0x01e8, 0x01ed, 0x01f2, 0x01f7, + 0x01fc, 0x0201, 0x0204, 0x0207, 0x020a, 0x020f, 0x0212, 0x0215, + 0x021a, 0x021d, 0x0220, 0x8192, 0x0223, 0x0226, 0x0229, 0x022c, + 0x022f, 0x8822, 0x8282, 0x8812, 0x8182, 0x0232, 0x0235, 0x0238, + 0x023b, 0x8722, 0x8272, 0x8462, 0x8712, 0x8552, 0x8172, 0x023e, + 0x8632, 0x8362, 0x8542, 0x8452, 0x8622, 0x8262, 0x8612, 0x0241, + 0x8532, 0x7162, 0x7162, 0x8352, 0x8442, 0x7522, 0x7522, 0x7252, + 0x7252, 0x7512, 0x7512, 0x7152, 0x7152, 0x8501, 0x8051, 0x7432, + 0x7432, 0x7342, 0x7342, 0x7422, 0x7422, 0x7242, 0x7242, 0x7332, + 0x7332, 0x6142, 0x6142, 0x6142, 0x6142, 0x7412, 0x7412, 0x7401, + 0x7401, 0x6322, 0x6322, 0x6322, 0x6322, 0x6232, 0x6232, 0x6232, + 0x6232, 0x7041, 0x7041, 0x7301, 0x7301, 0x6312, 0x6312, 0x6312, + 0x6312, 0x6132, 0x6132, 0x6132, 0x6132, 0x6031, 0x6031, 0x6031, + 0x6031, 0x5222, 0x5222, 0x5222, 0x5222, 0x5222, 0x5222, 0x5222, + 0x5222, 0x5212, 0x5212, 0x5212, 0x5212, 0x5212, 0x5212, 0x5212, + 0x5212, 0x5122, 0x5122, 0x5122, 0x5122, 0x5122, 0x5122, 0x5122, + 0x5122, 0x5201, 0x5201, 0x5201, 0x5201, 0x5201, 0x5201, 0x5201, + 0x5201, 0x5021, 0x5021, 0x5021, 0x5021, 0x5021, 0x5021, 0x5021, + 0x5021, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, + 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, + 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, + 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, 0x3112, + 0x3112, 0x4101, 0x4101, 0x4101, 0x4101, 0x4101, 0x4101, 0x4101, + 0x4101, 0x4101, 0x4101, 0x4101, 0x4101, 0x4101, 0x4101, 0x4101, + 0x4101, 0x4011, 0x4011, 0x4011, 0x4011, 0x4011, 0x4011, 0x4011, + 0x4011, 0x4011, 0x4011, 0x4011, 0x4011, 0x4011, 0x4011, 0x4011, + 0x4011, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, + 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, + 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, + 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, 0x3000, + 0x3000, 0xf005, 0x5ff2, 0x5fe2, 0x5ef2, 0x5fd2, 0x4ee2, 0x4ee2, + 0x5df2, 0x5fc2, 0x5cf2, 0x5ed2, 0x5de2, 0x5fb2, 0x4bf2, 0x4bf2, + 0x5ec2, 0x5ce2, 0x4dd2, 0x4dd2, 0x4fa2, 0x4fa2, 0x4af2, 0x4af2, + 0x4eb2, 0x4eb2, 0x4be2, 0x4be2, 0x4dc2, 0x4dc2, 0x4cd2, 0x4cd2, + 0x4f92, 0x4f92, 0xf005, 0x49f2, 0x49f2, 0x4ae2, 0x4ae2, 0x4db2, + 0x4db2, 0x4bd2, 0x4bd2, 0x4f82, 0x4f82, 0x48f2, 0x48f2, 0x4cc2, + 0x4cc2, 0x4e92, 0x4e92, 0x49e2, 0x49e2, 0x4f72, 0x4f72, 0x47f2, + 0x47f2, 0x4da2, 0x4da2, 0x4ad2, 0x4ad2, 0x4cb2, 0x4cb2, 0x4f62, + 0x4f62, 0x5ea2, 0x5f01, 0xf004, 0x3bc2, 0x3bc2, 0x36f2, 0x36f2, + 0x4e82, 0x48e2, 0x4f52, 0x4d92, 0x35f2, 0x35f2, 0x3e72, 0x3e72, + 0x37e2, 0x37e2, 0x3ca2, 0x3ca2, 0xf004, 0x3ac2, 0x3ac2, 0x3bb2, + 0x3bb2, 0x49d2, 0x4d82, 0x3f42, 0x3f42, 0x34f2, 0x34f2, 0x3f32, + 0x3f32, 0x33f2, 0x33f2, 0x38d2, 0x38d2, 0xf004, 0x36e2, 0x36e2, + 0x3f22, 0x3f22, 0x32f2, 0x32f2, 0x4e62, 0x40f1, 0x3f12, 0x3f12, + 0x31f2, 0x31f2, 0x3c92, 0x3c92, 0x39c2, 0x39c2, 0xf003, 0x3e52, + 0x3ba2, 0x3ab2, 0x35e2, 0x3d72, 0x37d2, 0x3e42, 0x34e2, 0xf003, + 0x3c82, 0x38c2, 0x3e32, 0x3d62, 0x36d2, 0x33e2, 0x3b92, 0x39b2, + 0xf004, 0x3e22, 0x3e22, 0x3aa2, 0x3aa2, 0x32e2, 0x32e2, 0x3e12, + 0x3e12, 0x31e2, 0x31e2, 0x4e01, 0x40e1, 0x3d52, 0x3d52, 0x35d2, + 0x35d2, 0xf003, 0x3c72, 0x37c2, 0x3d42, 0x3b82, 0x24d2, 0x24d2, + 0x38b2, 0x3a92, 0xf003, 0x39a2, 0x3c62, 0x36c2, 0x3d32, 0x23d2, + 0x23d2, 0x22d2, 0x22d2, 0xf003, 0x3d22, 0x3d01, 0x2d12, 0x2d12, + 0x2b72, 0x2b72, 0x27b2, 0x27b2, 0xf003, 0x21d2, 0x21d2, 0x3c52, + 0x30d1, 0x25c2, 0x25c2, 0x2a82, 0x2a82, 0xf002, 0x28a2, 0x2c42, + 0x24c2, 0x2b62, 0xf003, 0x26b2, 0x26b2, 0x3992, 0x3c01, 0x2c32, + 0x2c32, 0x23c2, 0x23c2, 0xf003, 0x2a72, 0x2a72, 0x27a2, 0x27a2, + 0x26a2, 0x26a2, 0x30c1, 0x3b01, 0xf002, 0x12c2, 0x12c2, 0x2c22, + 0x2b52, 0xf002, 0x25b2, 0x2c12, 0x2982, 0x2892, 0xf002, 0x21c2, + 0x2b42, 0x24b2, 0x2a62, 0xf002, 0x2b32, 0x2972, 0x13b2, 0x13b2, + 0xf002, 0x2792, 0x2882, 0x2b22, 0x2a52, 0xf002, 0x12b2, 0x12b2, + 0x25a2, 0x2b12, 0xf002, 0x11b2, 0x11b2, 0x20b1, 0x2962, 0xf002, + 0x2692, 0x2a42, 0x24a2, 0x2872, 0xf002, 0x2782, 0x2a32, 0x13a2, + 0x13a2, 0xf001, 0x1952, 0x1592, 0xf001, 0x1a22, 0x12a2, 0xf001, + 0x1a12, 0x11a2, 0xf002, 0x2a01, 0x20a1, 0x1862, 0x1862, 0xf001, + 0x1682, 0x1942, 0xf001, 0x1492, 0x1932, 0xf002, 0x1392, 0x1392, + 0x2772, 0x2901, 0xf001, 0x1852, 0x1582, 0xf001, 0x1922, 0x1762, + 0xf001, 0x1672, 0x1292, 0xf001, 0x1912, 0x1091, 0xf001, 0x1842, + 0x1482, 0xf001, 0x1752, 0x1572, 0xf001, 0x1832, 0x1382, 0xf001, + 0x1662, 0x1742, 0xf001, 0x1472, 0x1801, 0xf001, 0x1081, 0x1652, + 0xf001, 0x1562, 0x1732, 0xf001, 0x1372, 0x1642, 0xf001, 0x1701, + 0x1071, 0xf001, 0x1601, 0x1061, + + /* huffTable16[651] */ + 0xf008, 0x0101, 0x010a, 0x0113, 0x8ff2, 0x0118, 0x011d, 0x0120, + 0x82f2, 0x0131, 0x8f12, 0x81f2, 0x0134, 0x0145, 0x0156, 0x0167, + 0x0178, 0x0189, 0x019a, 0x01a3, 0x01ac, 0x01b5, 0x01be, 0x01c7, + 0x01d0, 0x01d9, 0x01de, 0x01e3, 0x01e6, 0x01eb, 0x01f0, 0x8152, + 0x01f3, 0x01f6, 0x01f9, 0x01fc, 0x8412, 0x8142, 0x01ff, 0x8322, + 0x8232, 0x7312, 0x7312, 0x7132, 0x7132, 0x8301, 0x8031, 0x7222, + 0x7222, 0x6212, 0x6212, 0x6212, 0x6212, 0x6122, 0x6122, 0x6122, + 0x6122, 0x6201, 0x6201, 0x6201, 0x6201, 0x6021, 0x6021, 0x6021, + 0x6021, 0x4112, 0x4112, 0x4112, 0x4112, 0x4112, 0x4112, 0x4112, + 0x4112, 0x4112, 0x4112, 0x4112, 0x4112, 0x4112, 0x4112, 0x4112, + 0x4112, 0x4101, 0x4101, 0x4101, 0x4101, 0x4101, 0x4101, 0x4101, + 0x4101, 0x4101, 0x4101, 0x4101, 0x4101, 0x4101, 0x4101, 0x4101, + 0x4101, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, + 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, + 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, + 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, 0x3011, + 0x3011, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, 0x1000, + 0x1000, 0xf003, 0x3fe2, 0x3ef2, 0x3fd2, 0x3df2, 0x3fc2, 0x3cf2, + 0x3fb2, 0x3bf2, 0xf003, 0x2fa2, 0x2fa2, 0x3af2, 0x3f92, 0x39f2, + 0x38f2, 0x2f82, 0x2f82, 0xf002, 0x2f72, 0x27f2, 0x2f62, 0x26f2, + 0xf002, 0x2f52, 0x25f2, 0x1f42, 0x1f42, 0xf001, 0x14f2, 0x13f2, + 0xf004, 0x10f1, 0x10f1, 0x10f1, 0x10f1, 0x10f1, 0x10f1, 0x10f1, + 0x10f1, 0x2f32, 0x2f32, 0x2f32, 0x2f32, 0x00e2, 0x00f3, 0x00fc, + 0x0105, 0xf001, 0x1f22, 0x1f01, 0xf004, 0x00fa, 0x00ff, 0x0104, + 0x0109, 0x010c, 0x0111, 0x0116, 0x0119, 0x011e, 0x0123, 0x0128, + 0x43e2, 0x012d, 0x0130, 0x0133, 0x0136, 0xf004, 0x0128, 0x012b, + 0x012e, 0x4d01, 0x0131, 0x0134, 0x0137, 0x4c32, 0x013a, 0x4c12, + 0x40c1, 0x013d, 0x32e2, 0x32e2, 0x4e22, 0x4e12, 0xf004, 0x43d2, + 0x4d22, 0x42d2, 0x41d2, 0x4b32, 0x012f, 0x3d12, 0x3d12, 0x44c2, + 0x4b62, 0x43c2, 0x47a2, 0x3c22, 0x3c22, 0x42c2, 0x45b2, 0xf004, + 0x41c2, 0x4c01, 0x4b42, 0x44b2, 0x4a62, 0x46a2, 0x33b2, 0x33b2, + 0x4a52, 0x45a2, 0x3b22, 0x3b22, 0x32b2, 0x32b2, 0x3b12, 0x3b12, + 0xf004, 0x31b2, 0x31b2, 0x4b01, 0x40b1, 0x4962, 0x4692, 0x4a42, + 0x44a2, 0x4872, 0x4782, 0x33a2, 0x33a2, 0x4a32, 0x4952, 0x3a22, + 0x3a22, 0xf004, 0x4592, 0x4862, 0x31a2, 0x31a2, 0x4682, 0x4772, + 0x3492, 0x3492, 0x4942, 0x4752, 0x3762, 0x3762, 0x22a2, 0x22a2, + 0x22a2, 0x22a2, 0xf003, 0x2a12, 0x2a12, 0x3a01, 0x30a1, 0x3932, + 0x3392, 0x3852, 0x3582, 0xf003, 0x2922, 0x2922, 0x2292, 0x2292, + 0x3672, 0x3901, 0x2912, 0x2912, 0xf003, 0x2192, 0x2192, 0x3091, + 0x3842, 0x3482, 0x3572, 0x3832, 0x3382, 0xf003, 0x3662, 0x3822, + 0x2282, 0x2282, 0x3742, 0x3472, 0x2812, 0x2812, 0xf003, 0x2182, + 0x2182, 0x2081, 0x2081, 0x3801, 0x3652, 0x2732, 0x2732, 0xf003, + 0x2372, 0x2372, 0x3562, 0x3642, 0x2722, 0x2722, 0x2272, 0x2272, + 0xf003, 0x3462, 0x3552, 0x2701, 0x2701, 0x1712, 0x1712, 0x1712, + 0x1712, 0xf002, 0x1172, 0x1172, 0x2071, 0x2632, 0xf002, 0x2362, + 0x2542, 0x2452, 0x2622, 0xf001, 0x1262, 0x1612, 0xf002, 0x1162, + 0x1162, 0x2601, 0x2061, 0xf002, 0x1352, 0x1352, 0x2532, 0x2442, + 0xf001, 0x1522, 0x1252, 0xf001, 0x1512, 0x1501, 0xf001, 0x1432, + 0x1342, 0xf001, 0x1051, 0x1422, 0xf001, 0x1242, 0x1332, 0xf001, + 0x1401, 0x1041, 0xf004, 0x4ec2, 0x0086, 0x3ed2, 0x3ed2, 0x39e2, + 0x39e2, 0x4ae2, 0x49d2, 0x2ee2, 0x2ee2, 0x2ee2, 0x2ee2, 0x3de2, + 0x3de2, 0x3be2, 0x3be2, 0xf003, 0x2eb2, 0x2eb2, 0x2dc2, 0x2dc2, + 0x3cd2, 0x3bd2, 0x2ea2, 0x2ea2, 0xf003, 0x2cc2, 0x2cc2, 0x3da2, + 0x3ad2, 0x3e72, 0x3ca2, 0x2ac2, 0x2ac2, 0xf003, 0x39c2, 0x3d72, + 0x2e52, 0x2e52, 0x1db2, 0x1db2, 0x1db2, 0x1db2, 0xf002, 0x1e92, + 0x1e92, 0x2cb2, 0x2bc2, 0xf002, 0x2e82, 0x28e2, 0x2d92, 0x27e2, + 0xf002, 0x2bb2, 0x2d82, 0x28d2, 0x2e62, 0xf001, 0x16e2, 0x1c92, + 0xf002, 0x2ba2, 0x2ab2, 0x25e2, 0x27d2, 0xf002, 0x1e42, 0x1e42, + 0x24e2, 0x2c82, 0xf001, 0x18c2, 0x1e32, 0xf002, 0x1d62, 0x1d62, + 0x26d2, 0x2b92, 0xf002, 0x29b2, 0x2aa2, 0x11e2, 0x11e2, 0xf002, + 0x14d2, 0x14d2, 0x28b2, 0x29a2, 0xf002, 0x1b72, 0x1b72, 0x27b2, + 0x20d1, 0xf001, 0x1e01, 0x10e1, 0xf001, 0x1d52, 0x15d2, 0xf001, + 0x1c72, 0x17c2, 0xf001, 0x1d42, 0x1b82, 0xf001, 0x1a92, 0x1c62, + 0xf001, 0x16c2, 0x1d32, 0xf001, 0x1c52, 0x15c2, 0xf001, 0x1a82, + 0x18a2, 0xf001, 0x1992, 0x1c42, 0xf001, 0x16b2, 0x1a72, 0xf001, + 0x1b52, 0x1982, 0xf001, 0x1892, 0x1972, 0xf001, 0x1792, 0x1882, + 0xf001, 0x1ce2, 0x1dd2, + + /* huffTable24[705] */ + 0xf009, 0x8fe2, 0x8fe2, 0x8ef2, 0x8ef2, 0x8fd2, 0x8fd2, 0x8df2, + 0x8df2, 0x8fc2, 0x8fc2, 0x8cf2, 0x8cf2, 0x8fb2, 0x8fb2, 0x8bf2, + 0x8bf2, 0x7af2, 0x7af2, 0x7af2, 0x7af2, 0x8fa2, 0x8fa2, 0x8f92, + 0x8f92, 0x79f2, 0x79f2, 0x79f2, 0x79f2, 0x78f2, 0x78f2, 0x78f2, + 0x78f2, 0x8f82, 0x8f82, 0x8f72, 0x8f72, 0x77f2, 0x77f2, 0x77f2, + 0x77f2, 0x7f62, 0x7f62, 0x7f62, 0x7f62, 0x76f2, 0x76f2, 0x76f2, + 0x76f2, 0x7f52, 0x7f52, 0x7f52, 0x7f52, 0x75f2, 0x75f2, 0x75f2, + 0x75f2, 0x7f42, 0x7f42, 0x7f42, 0x7f42, 0x74f2, 0x74f2, 0x74f2, + 0x74f2, 0x7f32, 0x7f32, 0x7f32, 0x7f32, 0x73f2, 0x73f2, 0x73f2, + 0x73f2, 0x7f22, 0x7f22, 0x7f22, 0x7f22, 0x72f2, 0x72f2, 0x72f2, + 0x72f2, 0x71f2, 0x71f2, 0x71f2, 0x71f2, 0x8f12, 0x8f12, 0x80f1, + 0x80f1, 0x9f01, 0x0201, 0x0206, 0x020b, 0x0210, 0x0215, 0x021a, + 0x021f, 0x4ff2, 0x4ff2, 0x4ff2, 0x4ff2, 0x4ff2, 0x4ff2, 0x4ff2, + 0x4ff2, 0x4ff2, 0x4ff2, 0x4ff2, 0x4ff2, 0x4ff2, 0x4ff2, 0x4ff2, + 0x4ff2, 0x4ff2, 0x4ff2, 0x4ff2, 0x4ff2, 0x4ff2, 0x4ff2, 0x4ff2, + 0x4ff2, 0x4ff2, 0x4ff2, 0x4ff2, 0x4ff2, 0x4ff2, 0x4ff2, 0x4ff2, + 0x4ff2, 0x0224, 0x0229, 0x0232, 0x0237, 0x023a, 0x023f, 0x0242, + 0x0245, 0x024a, 0x024d, 0x0250, 0x0253, 0x0256, 0x0259, 0x025c, + 0x025f, 0x0262, 0x0265, 0x0268, 0x026b, 0x026e, 0x0271, 0x0274, + 0x0277, 0x027a, 0x027d, 0x0280, 0x0283, 0x0288, 0x028b, 0x028e, + 0x0291, 0x0294, 0x0297, 0x029a, 0x029f, 0x94b2, 0x02a4, 0x02a7, + 0x02aa, 0x93b2, 0x9882, 0x02af, 0x92b2, 0x02b2, 0x02b5, 0x9692, + 0x94a2, 0x02b8, 0x9782, 0x9a32, 0x93a2, 0x9952, 0x9592, 0x9a22, + 0x92a2, 0x91a2, 0x9862, 0x9682, 0x9772, 0x9942, 0x9492, 0x9932, + 0x9392, 0x9852, 0x9582, 0x9922, 0x9762, 0x9672, 0x9292, 0x9912, + 0x9192, 0x9842, 0x9482, 0x9752, 0x9572, 0x9832, 0x9382, 0x9662, + 0x9822, 0x9282, 0x9812, 0x9742, 0x9472, 0x9182, 0x02bb, 0x9652, + 0x9562, 0x9712, 0x02be, 0x8372, 0x8372, 0x9732, 0x9722, 0x8272, + 0x8272, 0x8642, 0x8642, 0x8462, 0x8462, 0x8552, 0x8552, 0x8172, + 0x8172, 0x8632, 0x8632, 0x8362, 0x8362, 0x8542, 0x8542, 0x8452, + 0x8452, 0x8622, 0x8622, 0x8262, 0x8262, 0x8612, 0x8612, 0x8162, + 0x8162, 0x9601, 0x9061, 0x8532, 0x8532, 0x8352, 0x8352, 0x8442, + 0x8442, 0x8522, 0x8522, 0x8252, 0x8252, 0x8512, 0x8512, 0x9501, + 0x9051, 0x7152, 0x7152, 0x7152, 0x7152, 0x8432, 0x8432, 0x8342, + 0x8342, 0x7422, 0x7422, 0x7422, 0x7422, 0x7242, 0x7242, 0x7242, + 0x7242, 0x7332, 0x7332, 0x7332, 0x7332, 0x7412, 0x7412, 0x7412, + 0x7412, 0x7142, 0x7142, 0x7142, 0x7142, 0x8401, 0x8401, 0x8041, + 0x8041, 0x7322, 0x7322, 0x7322, 0x7322, 0x7232, 0x7232, 0x7232, + 0x7232, 0x6312, 0x6312, 0x6312, 0x6312, 0x6312, 0x6312, 0x6312, + 0x6312, 0x6132, 0x6132, 0x6132, 0x6132, 0x6132, 0x6132, 0x6132, + 0x6132, 0x7301, 0x7301, 0x7301, 0x7301, 0x7031, 0x7031, 0x7031, + 0x7031, 0x6222, 0x6222, 0x6222, 0x6222, 0x6222, 0x6222, 0x6222, + 0x6222, 0x5212, 0x5212, 0x5212, 0x5212, 0x5212, 0x5212, 0x5212, + 0x5212, 0x5212, 0x5212, 0x5212, 0x5212, 0x5212, 0x5212, 0x5212, + 0x5212, 0x5122, 0x5122, 0x5122, 0x5122, 0x5122, 0x5122, 0x5122, + 0x5122, 0x5122, 0x5122, 0x5122, 0x5122, 0x5122, 0x5122, 0x5122, + 0x5122, 0x6201, 0x6201, 0x6201, 0x6201, 0x6201, 0x6201, 0x6201, + 0x6201, 0x6021, 0x6021, 0x6021, 0x6021, 0x6021, 0x6021, 0x6021, + 0x6021, 0x4112, 0x4112, 0x4112, 0x4112, 0x4112, 0x4112, 0x4112, + 0x4112, 0x4112, 0x4112, 0x4112, 0x4112, 0x4112, 0x4112, 0x4112, + 0x4112, 0x4112, 0x4112, 0x4112, 0x4112, 0x4112, 0x4112, 0x4112, + 0x4112, 0x4112, 0x4112, 0x4112, 0x4112, 0x4112, 0x4112, 0x4112, + 0x4112, 0x4101, 0x4101, 0x4101, 0x4101, 0x4101, 0x4101, 0x4101, + 0x4101, 0x4101, 0x4101, 0x4101, 0x4101, 0x4101, 0x4101, 0x4101, + 0x4101, 0x4101, 0x4101, 0x4101, 0x4101, 0x4101, 0x4101, 0x4101, + 0x4101, 0x4101, 0x4101, 0x4101, 0x4101, 0x4101, 0x4101, 0x4101, + 0x4101, 0x4011, 0x4011, 0x4011, 0x4011, 0x4011, 0x4011, 0x4011, + 0x4011, 0x4011, 0x4011, 0x4011, 0x4011, 0x4011, 0x4011, 0x4011, + 0x4011, 0x4011, 0x4011, 0x4011, 0x4011, 0x4011, 0x4011, 0x4011, + 0x4011, 0x4011, 0x4011, 0x4011, 0x4011, 0x4011, 0x4011, 0x4011, + 0x4011, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, + 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, + 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, + 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, 0x4000, + 0x4000, 0xf002, 0x2ee2, 0x2ed2, 0x2de2, 0x2ec2, 0xf002, 0x2ce2, + 0x2dd2, 0x2eb2, 0x2be2, 0xf002, 0x2dc2, 0x2cd2, 0x2ea2, 0x2ae2, + 0xf002, 0x2db2, 0x2bd2, 0x2cc2, 0x2e92, 0xf002, 0x29e2, 0x2da2, + 0x2ad2, 0x2cb2, 0xf002, 0x2bc2, 0x2e82, 0x28e2, 0x2d92, 0xf002, + 0x29d2, 0x2e72, 0x27e2, 0x2ca2, 0xf002, 0x2ac2, 0x2bb2, 0x2d82, + 0x28d2, 0xf003, 0x3e01, 0x30e1, 0x2d01, 0x2d01, 0x16e2, 0x16e2, + 0x16e2, 0x16e2, 0xf002, 0x2e62, 0x2c92, 0x19c2, 0x19c2, 0xf001, + 0x1e52, 0x1ab2, 0xf002, 0x15e2, 0x15e2, 0x2ba2, 0x2d72, 0xf001, + 0x17d2, 0x14e2, 0xf001, 0x1c82, 0x18c2, 0xf002, 0x2e42, 0x2e22, + 0x1e32, 0x1e32, 0xf001, 0x1d62, 0x16d2, 0xf001, 0x13e2, 0x1b92, + 0xf001, 0x19b2, 0x1aa2, 0xf001, 0x12e2, 0x1e12, 0xf001, 0x11e2, + 0x1d52, 0xf001, 0x15d2, 0x1c72, 0xf001, 0x17c2, 0x1d42, 0xf001, + 0x1b82, 0x18b2, 0xf001, 0x14d2, 0x1a92, 0xf001, 0x19a2, 0x1c62, + 0xf001, 0x16c2, 0x1d32, 0xf001, 0x13d2, 0x1d22, 0xf001, 0x12d2, + 0x1d12, 0xf001, 0x1b72, 0x17b2, 0xf001, 0x11d2, 0x1c52, 0xf001, + 0x15c2, 0x1a82, 0xf001, 0x18a2, 0x1992, 0xf001, 0x1c42, 0x14c2, + 0xf001, 0x1b62, 0x16b2, 0xf002, 0x20d1, 0x2c01, 0x1c32, 0x1c32, + 0xf001, 0x13c2, 0x1a72, 0xf001, 0x17a2, 0x1c22, 0xf001, 0x12c2, + 0x1b52, 0xf001, 0x15b2, 0x1c12, 0xf001, 0x1982, 0x1892, 0xf001, + 0x11c2, 0x1b42, 0xf002, 0x20c1, 0x2b01, 0x1b32, 0x1b32, 0xf002, + 0x20b1, 0x2a01, 0x1a12, 0x1a12, 0xf001, 0x1a62, 0x16a2, 0xf001, + 0x1972, 0x1792, 0xf002, 0x20a1, 0x2901, 0x1091, 0x1091, 0xf001, + 0x1b22, 0x1a52, 0xf001, 0x15a2, 0x1b12, 0xf001, 0x11b2, 0x1962, + 0xf001, 0x1a42, 0x1872, 0xf001, 0x1801, 0x1081, 0xf001, 0x1701, + 0x1071, +}; + +#define HUFF_OFFSET_01 0 +#define HUFF_OFFSET_02 ( 9 + HUFF_OFFSET_01) +#define HUFF_OFFSET_03 ( 65 + HUFF_OFFSET_02) +#define HUFF_OFFSET_05 ( 65 + HUFF_OFFSET_03) +#define HUFF_OFFSET_06 (257 + HUFF_OFFSET_05) +#define HUFF_OFFSET_07 (129 + HUFF_OFFSET_06) +#define HUFF_OFFSET_08 (110 + HUFF_OFFSET_07) +#define HUFF_OFFSET_09 (280 + HUFF_OFFSET_08) +#define HUFF_OFFSET_10 ( 93 + HUFF_OFFSET_09) +#define HUFF_OFFSET_11 (320 + HUFF_OFFSET_10) +#define HUFF_OFFSET_12 (296 + HUFF_OFFSET_11) +#define HUFF_OFFSET_13 (185 + HUFF_OFFSET_12) +#define HUFF_OFFSET_15 (497 + HUFF_OFFSET_13) +#define HUFF_OFFSET_16 (580 + HUFF_OFFSET_15) +#define HUFF_OFFSET_24 (651 + HUFF_OFFSET_16) + +const int huffTabOffset[HUFF_PAIRTABS] = { + 0, + HUFF_OFFSET_01, + HUFF_OFFSET_02, + HUFF_OFFSET_03, + 0, + HUFF_OFFSET_05, + HUFF_OFFSET_06, + HUFF_OFFSET_07, + HUFF_OFFSET_08, + HUFF_OFFSET_09, + HUFF_OFFSET_10, + HUFF_OFFSET_11, + HUFF_OFFSET_12, + HUFF_OFFSET_13, + 0, + HUFF_OFFSET_15, + HUFF_OFFSET_16, + HUFF_OFFSET_16, + HUFF_OFFSET_16, + HUFF_OFFSET_16, + HUFF_OFFSET_16, + HUFF_OFFSET_16, + HUFF_OFFSET_16, + HUFF_OFFSET_16, + HUFF_OFFSET_24, + HUFF_OFFSET_24, + HUFF_OFFSET_24, + HUFF_OFFSET_24, + HUFF_OFFSET_24, + HUFF_OFFSET_24, + HUFF_OFFSET_24, + HUFF_OFFSET_24, +}; + +const HuffTabLookup huffTabLookup[HUFF_PAIRTABS] = { + { 0, noBits }, + { 0, oneShot }, + { 0, oneShot }, + { 0, oneShot }, + { 0, invalidTab }, + { 0, oneShot }, + { 0, oneShot }, + { 0, loopNoLinbits }, + { 0, loopNoLinbits }, + { 0, loopNoLinbits }, + { 0, loopNoLinbits }, + { 0, loopNoLinbits }, + { 0, loopNoLinbits }, + { 0, loopNoLinbits }, + { 0, invalidTab }, + { 0, loopNoLinbits }, + { 1, loopLinbits }, + { 2, loopLinbits }, + { 3, loopLinbits }, + { 4, loopLinbits }, + { 6, loopLinbits }, + { 8, loopLinbits }, + { 10, loopLinbits }, + { 13, loopLinbits }, + { 4, loopLinbits }, + { 5, loopLinbits }, + { 6, loopLinbits }, + { 7, loopLinbits }, + { 8, loopLinbits }, + { 9, loopLinbits }, + { 11, loopLinbits }, + { 13, loopLinbits }, +}; + +/* tables for quadruples + * format 0xAB + * A = length of codeword + * B = codeword + */ +const unsigned char quadTable[64+16] = { + /* table A */ + 0x6b, 0x6f, 0x6d, 0x6e, 0x67, 0x65, 0x59, 0x59, + 0x56, 0x56, 0x53, 0x53, 0x5a, 0x5a, 0x5c, 0x5c, + 0x42, 0x42, 0x42, 0x42, 0x41, 0x41, 0x41, 0x41, + 0x44, 0x44, 0x44, 0x44, 0x48, 0x48, 0x48, 0x48, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, + /* table B */ + 0x4f, 0x4e, 0x4d, 0x4c, 0x4b, 0x4a, 0x49, 0x48, + 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, 0x40, +}; + +const int quadTabOffset[2] = {0, 64}; +const int quadTabMaxBits[2] = {6, 4}; +#endif /* CONFIG_APP_MP3PLAYER */ diff --git a/beken_os/beken378/func/music_player/Mp3Lib/imdct.c b/beken_os/beken378/func/music_player/Mp3Lib/imdct.c new file mode 100755 index 0000000..3fbf522 --- /dev/null +++ b/beken_os/beken378/func/music_player/Mp3Lib/imdct.c @@ -0,0 +1,780 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: RCSL 1.0/RPSL 1.0 + * + * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. + * + * The contents of this file, and the files included with this file, are + * subject to the current version of the RealNetworks Public Source License + * Version 1.0 (the "RPSL") available at + * http://www.helixcommunity.org/content/rpsl unless you have licensed + * the file under the RealNetworks Community Source License Version 1.0 + * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, + * in which case the RCSL will apply. You may also obtain the license terms + * directly from RealNetworks. You may not use this file except in + * compliance with the RPSL or, if you have a valid RCSL with RealNetworks + * applicable to this file, the RCSL. Please see the applicable RPSL or + * RCSL for the rights, obligations and limitations governing use of the + * contents of the file. + * + * This file is part of the Helix DNA Technology. RealNetworks is the + * developer of the Original Code and owns the copyrights in the portions + * it created. + * + * This file, and the files included with this file, is distributed and made + * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * + * Technology Compatibility Kit Test Suite(s) Location: + * http://www.helixcommunity.org/content/tck + * + * Contributor(s): + * + * ***** END LICENSE BLOCK ***** */ + +/************************************************************************************** + * Fixed-point MP3 decoder + * Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com) + * June 2003 + * + * imdct.c - antialias, inverse transform (short/long/mixed), windowing, + * overlap-add, frequency inversion + **************************************************************************************/ + +#include "coder.h" +#include "assembly.h" +#if (CONFIG_APP_MP3PLAYER == 1) +/************************************************************************************** + * Function: AntiAlias + * + * Description: smooth transition across DCT block boundaries (every 18 coefficients) + * + * Inputs: vector of dequantized coefficients, length = (nBfly+1) * 18 + * number of "butterflies" to perform (one butterfly means one + * inter-block smoothing operation) + * + * Outputs: updated coefficient vector x + * + * Return: none + * + * Notes: weighted average of opposite bands (pairwise) from the 8 samples + * before and after each block boundary + * nBlocks = (nonZeroBound + 7) / 18, since nZB is the first ZERO sample + * above which all other samples are also zero + * max gain per sample = 1.372 + * MAX(i) (abs(csa[i][0]) + abs(csa[i][1])) + * bits gained = 0 + * assume at least 1 guard bit in x[] to avoid overflow + * (should be guaranteed from dequant, and max gain from stproc * max + * gain from AntiAlias < 2.0) + **************************************************************************************/ +static void AntiAlias(int *x, int nBfly) +{ + int k, a0, b0, c0, c1; + const int *c; + + /* csa = Q31 */ + for (k = nBfly; k > 0; k--) { + c = csa[0]; + x += 18; + + a0 = x[-1]; c0 = *c; c++; b0 = x[0]; c1 = *c; c++; + x[-1] = (MULSHIFT32(c0, a0) - MULSHIFT32(c1, b0)) << 1; + x[0] = (MULSHIFT32(c0, b0) + MULSHIFT32(c1, a0)) << 1; + + a0 = x[-2]; c0 = *c; c++; b0 = x[1]; c1 = *c; c++; + x[-2] = (MULSHIFT32(c0, a0) - MULSHIFT32(c1, b0)) << 1; + x[1] = (MULSHIFT32(c0, b0) + MULSHIFT32(c1, a0)) << 1; + + a0 = x[-3]; c0 = *c; c++; b0 = x[2]; c1 = *c; c++; + x[-3] = (MULSHIFT32(c0, a0) - MULSHIFT32(c1, b0)) << 1; + x[2] = (MULSHIFT32(c0, b0) + MULSHIFT32(c1, a0)) << 1; + + a0 = x[-4]; c0 = *c; c++; b0 = x[3]; c1 = *c; c++; + x[-4] = (MULSHIFT32(c0, a0) - MULSHIFT32(c1, b0)) << 1; + x[3] = (MULSHIFT32(c0, b0) + MULSHIFT32(c1, a0)) << 1; + + a0 = x[-5]; c0 = *c; c++; b0 = x[4]; c1 = *c; c++; + x[-5] = (MULSHIFT32(c0, a0) - MULSHIFT32(c1, b0)) << 1; + x[4] = (MULSHIFT32(c0, b0) + MULSHIFT32(c1, a0)) << 1; + + a0 = x[-6]; c0 = *c; c++; b0 = x[5]; c1 = *c; c++; + x[-6] = (MULSHIFT32(c0, a0) - MULSHIFT32(c1, b0)) << 1; + x[5] = (MULSHIFT32(c0, b0) + MULSHIFT32(c1, a0)) << 1; + + a0 = x[-7]; c0 = *c; c++; b0 = x[6]; c1 = *c; c++; + x[-7] = (MULSHIFT32(c0, a0) - MULSHIFT32(c1, b0)) << 1; + x[6] = (MULSHIFT32(c0, b0) + MULSHIFT32(c1, a0)) << 1; + + a0 = x[-8]; c0 = *c; c++; b0 = x[7]; c1 = *c; c++; + x[-8] = (MULSHIFT32(c0, a0) - MULSHIFT32(c1, b0)) << 1; + x[7] = (MULSHIFT32(c0, b0) + MULSHIFT32(c1, a0)) << 1; + } +} + +/************************************************************************************** + * Function: WinPrevious + * + * Description: apply specified window to second half of previous IMDCT (overlap part) + * + * Inputs: vector of 9 coefficients (xPrev) + * + * Outputs: 18 windowed output coefficients (gain 1 integer bit) + * window type (0, 1, 2, 3) + * + * Return: none + * + * Notes: produces 9 output samples from 18 input samples via symmetry + * all blocks gain at least 1 guard bit via window (long blocks get extra + * sign bit, short blocks can have one addition but max gain < 1.0) + **************************************************************************************/ +static void WinPrevious(int *xPrev, int *xPrevWin, int btPrev) +{ + int i, x, *xp, *xpwLo, *xpwHi, wLo, wHi; + const int *wpLo, *wpHi; + + xp = xPrev; + /* mapping (see IMDCT12x3): xPrev[0-2] = sum[6-8], xPrev[3-8] = sum[12-17] */ + if (btPrev == 2) { + /* this could be reordered for minimum loads/stores */ + wpLo = imdctWin[btPrev]; + xPrevWin[ 0] = MULSHIFT32(wpLo[ 6], xPrev[2]) + MULSHIFT32(wpLo[0], xPrev[6]); + xPrevWin[ 1] = MULSHIFT32(wpLo[ 7], xPrev[1]) + MULSHIFT32(wpLo[1], xPrev[7]); + xPrevWin[ 2] = MULSHIFT32(wpLo[ 8], xPrev[0]) + MULSHIFT32(wpLo[2], xPrev[8]); + xPrevWin[ 3] = MULSHIFT32(wpLo[ 9], xPrev[0]) + MULSHIFT32(wpLo[3], xPrev[8]); + xPrevWin[ 4] = MULSHIFT32(wpLo[10], xPrev[1]) + MULSHIFT32(wpLo[4], xPrev[7]); + xPrevWin[ 5] = MULSHIFT32(wpLo[11], xPrev[2]) + MULSHIFT32(wpLo[5], xPrev[6]); + xPrevWin[ 6] = MULSHIFT32(wpLo[ 6], xPrev[5]); + xPrevWin[ 7] = MULSHIFT32(wpLo[ 7], xPrev[4]); + xPrevWin[ 8] = MULSHIFT32(wpLo[ 8], xPrev[3]); + xPrevWin[ 9] = MULSHIFT32(wpLo[ 9], xPrev[3]); + xPrevWin[10] = MULSHIFT32(wpLo[10], xPrev[4]); + xPrevWin[11] = MULSHIFT32(wpLo[11], xPrev[5]); + xPrevWin[12] = xPrevWin[13] = xPrevWin[14] = xPrevWin[15] = xPrevWin[16] = xPrevWin[17] = 0; + } else { + /* use ARM-style pointers (*ptr++) so that ADS compiles well */ + wpLo = imdctWin[btPrev] + 18; + wpHi = wpLo + 17; + xpwLo = xPrevWin; + xpwHi = xPrevWin + 17; + for (i = 9; i > 0; i--) { + x = *xp++; wLo = *wpLo++; wHi = *wpHi--; + *xpwLo++ = MULSHIFT32(wLo, x); + *xpwHi-- = MULSHIFT32(wHi, x); + } + } +} + +/************************************************************************************** + * Function: FreqInvertRescale + * + * Description: do frequency inversion (odd samples of odd blocks) and rescale + * if necessary (extra guard bits added before IMDCT) + * + * Inputs: output vector y (18 new samples, spaced NBANDS apart) + * previous sample vector xPrev (9 samples) + * index of current block + * number of extra shifts added before IMDCT (usually 0) + * + * Outputs: inverted and rescaled (as necessary) outputs + * rescaled (as necessary) previous samples + * + * Return: updated mOut (from new outputs y) + **************************************************************************************/ +static int FreqInvertRescale(int *y, int *xPrev, int blockIdx, int es) +{ + int i, d, mOut; + int y0, y1, y2, y3, y4, y5, y6, y7, y8; + + if (es == 0) { + /* fast case - frequency invert only (no rescaling) - can fuse into overlap-add for speed, if desired */ + if (blockIdx & 0x01) { + y += NBANDS; + y0 = *y; y += 2*NBANDS; + y1 = *y; y += 2*NBANDS; + y2 = *y; y += 2*NBANDS; + y3 = *y; y += 2*NBANDS; + y4 = *y; y += 2*NBANDS; + y5 = *y; y += 2*NBANDS; + y6 = *y; y += 2*NBANDS; + y7 = *y; y += 2*NBANDS; + y8 = *y; y += 2*NBANDS; + + y -= 18*NBANDS; + *y = -y0; y += 2*NBANDS; + *y = -y1; y += 2*NBANDS; + *y = -y2; y += 2*NBANDS; + *y = -y3; y += 2*NBANDS; + *y = -y4; y += 2*NBANDS; + *y = -y5; y += 2*NBANDS; + *y = -y6; y += 2*NBANDS; + *y = -y7; y += 2*NBANDS; + *y = -y8; y += 2*NBANDS; + } + return 0; + } else { + /* undo pre-IMDCT scaling, clipping if necessary */ + mOut = 0; + if (blockIdx & 0x01) { + /* frequency invert */ + for (i = 0; i < 18; i+=2) { + d = *y; CLIP_2N(d, 31 - es); *y = d << es; mOut |= FASTABS(*y); y += NBANDS; + d = -*y; CLIP_2N(d, 31 - es); *y = d << es; mOut |= FASTABS(*y); y += NBANDS; + d = *xPrev; CLIP_2N(d, 31 - es); *xPrev++ = d << es; + } + } else { + for (i = 0; i < 18; i+=2) { + d = *y; CLIP_2N(d, 31 - es); *y = d << es; mOut |= FASTABS(*y); y += NBANDS; + d = *y; CLIP_2N(d, 31 - es); *y = d << es; mOut |= FASTABS(*y); y += NBANDS; + d = *xPrev; CLIP_2N(d, 31 - es); *xPrev++ = d << es; + } + } + return mOut; + } +} + +/* format = Q31 + * #define M_PI 3.14159265358979323846 + * double u = 2.0 * M_PI / 9.0; + * float c0 = sqrt(3.0) / 2.0; + * float c1 = cos(u); + * float c2 = cos(2*u); + * float c3 = sin(u); + * float c4 = sin(2*u); + */ +static const int c9_0 = 0x6ed9eba1; +static const int c9_1 = 0x620dbe8b; +static const int c9_2 = 0x163a1a7e; +static const int c9_3 = 0x5246dd49; +static const int c9_4 = 0x7e0e2e32; + +/* format = Q31 + * cos(((0:8) + 0.5) * (pi/18)) + */ +static const int c18[9] = { + 0x7f834ed0, 0x7ba3751d, 0x7401e4c1, 0x68d9f964, 0x5a82799a, 0x496af3e2, 0x36185aee, 0x2120fb83, 0x0b27eb5c, +}; + +/* require at least 3 guard bits in x[] to ensure no overflow */ +static __inline void idct9(int *x) +{ + int a1, a2, a3, a4, a5, a6, a7, a8, a9; + int a10, a11, a12, a13, a14, a15, a16, a17, a18; + int a19, a20, a21, a22, a23, a24, a25, a26, a27; + int m1, m3, m5, m6, m7, m8, m9, m10, m11, m12; + int x0, x1, x2, x3, x4, x5, x6, x7, x8; + + x0 = x[0]; x1 = x[1]; x2 = x[2]; x3 = x[3]; x4 = x[4]; + x5 = x[5]; x6 = x[6]; x7 = x[7]; x8 = x[8]; + + a1 = x0 - x6; + a2 = x1 - x5; + a3 = x1 + x5; + a4 = x2 - x4; + a5 = x2 + x4; + a6 = x2 + x8; + a7 = x1 + x7; + + a8 = a6 - a5; /* ie x[8] - x[4] */ + a9 = a3 - a7; /* ie x[5] - x[7] */ + a10 = a2 - x7; /* ie x[1] - x[5] - x[7] */ + a11 = a4 - x8; /* ie x[2] - x[4] - x[8] */ + + /* do the << 1 as constant shifts where mX is actually used (free, no stall or extra inst.) */ + m1 = MULSHIFT32(c9_0, x3); + m3 = MULSHIFT32(c9_0, a10); + m5 = MULSHIFT32(c9_1, a5); + m6 = MULSHIFT32(c9_2, a6); + m7 = MULSHIFT32(c9_1, a8); + m8 = MULSHIFT32(c9_2, a5); + m9 = MULSHIFT32(c9_3, a9); + m10 = MULSHIFT32(c9_4, a7); + m11 = MULSHIFT32(c9_3, a3); + m12 = MULSHIFT32(c9_4, a9); + + a12 = x[0] + (x[6] >> 1); + a13 = a12 + ( m1 << 1); + a14 = a12 - ( m1 << 1); + a15 = a1 + ( a11 >> 1); + a16 = ( m5 << 1) + (m6 << 1); + a17 = ( m7 << 1) - (m8 << 1); + a18 = a16 + a17; + a19 = ( m9 << 1) + (m10 << 1); + a20 = (m11 << 1) - (m12 << 1); + + a21 = a20 - a19; + a22 = a13 + a16; + a23 = a14 + a16; + a24 = a14 + a17; + a25 = a13 + a17; + a26 = a14 - a18; + a27 = a13 - a18; + + x0 = a22 + a19; x[0] = x0; + x1 = a15 + (m3 << 1); x[1] = x1; + x2 = a24 + a20; x[2] = x2; + x3 = a26 - a21; x[3] = x3; + x4 = a1 - a11; x[4] = x4; + x5 = a27 + a21; x[5] = x5; + x6 = a25 - a20; x[6] = x6; + x7 = a15 - (m3 << 1); x[7] = x7; + x8 = a23 - a19; x[8] = x8; +} + +/* let c(j) = cos(M_PI/36 * ((j)+0.5)), s(j) = sin(M_PI/36 * ((j)+0.5)) + * then fastWin[2*j+0] = c(j)*(s(j) + c(j)), j = [0, 8] + * fastWin[2*j+1] = c(j)*(s(j) - c(j)) + * format = Q30 + */ +static const int fastWin36[18] = { + 0x42aace8b, 0xc2e92724, 0x47311c28, 0xc95f619a, 0x4a868feb, 0xd0859d8c, + 0x4c913b51, 0xd8243ea0, 0x4d413ccc, 0xe0000000, 0x4c913b51, 0xe7dbc161, + 0x4a868feb, 0xef7a6275, 0x47311c28, 0xf6a09e67, 0x42aace8b, 0xfd16d8dd, +}; + +/************************************************************************************** + * Function: IMDCT36 + * + * Description: 36-point modified DCT, with windowing and overlap-add (50% overlap) + * + * Inputs: vector of 18 coefficients (N/2 inputs produces N outputs, by symmetry) + * overlap part of last IMDCT (9 samples - see output comments) + * window type (0,1,2,3) of current and previous block + * current block index (for deciding whether to do frequency inversion) + * number of guard bits in input vector + * + * Outputs: 18 output samples, after windowing and overlap-add with last frame + * second half of (unwindowed) 36-point IMDCT - save for next time + * only save 9 xPrev samples, using symmetry (see WinPrevious()) + * + * Notes: this is Ken's hyper-fast algorithm, including symmetric sin window + * optimization, if applicable + * total number of multiplies, general case: + * 2*10 (idct9) + 9 (last stage imdct) + 36 (for windowing) = 65 + * total number of multiplies, btCurr == 0 && btPrev == 0: + * 2*10 (idct9) + 9 (last stage imdct) + 18 (for windowing) = 47 + * + * blockType == 0 is by far the most common case, so it should be + * possible to use the fast path most of the time + * this is the fastest known algorithm for performing + * long IMDCT + windowing + overlap-add in MP3 + * + * Return: mOut (OR of abs(y) for all y calculated here) + * + * TODO: optimize for ARM (reorder window coefs, ARM-style pointers in C, + * inline asm may or may not be helpful) + **************************************************************************************/ +static int IMDCT36(int *xCurr, int *xPrev, int *y, int btCurr, int btPrev, int blockIdx, int gb) +{ + int i, es, xBuf[18], xPrevWin[18]; + int acc1, acc2, s, d, t, mOut; + int xo, xe, c, *xp, yLo, yHi; + const int *cp, *wp; + + acc1 = acc2 = 0; + xCurr += 17; + + /* 7 gb is always adequate for antialias + accumulator loop + idct9 */ + if (gb < 7) { + /* rarely triggered - 5% to 10% of the time on normal clips (with Q25 input) */ + es = 7 - gb; + for (i = 8; i >= 0; i--) { + acc1 = ((*xCurr--) >> es) - acc1; + acc2 = acc1 - acc2; + acc1 = ((*xCurr--) >> es) - acc1; + xBuf[i+9] = acc2; /* odd */ + xBuf[i+0] = acc1; /* even */ + xPrev[i] >>= es; + } + } else { + es = 0; + /* max gain = 18, assume adequate guard bits */ + for (i = 8; i >= 0; i--) { + acc1 = (*xCurr--) - acc1; + acc2 = acc1 - acc2; + acc1 = (*xCurr--) - acc1; + xBuf[i+9] = acc2; /* odd */ + xBuf[i+0] = acc1; /* even */ + } + } + /* xEven[0] and xOdd[0] scaled by 0.5 */ + xBuf[9] >>= 1; + xBuf[0] >>= 1; + + /* do 9-point IDCT on even and odd */ + idct9(xBuf+0); /* even */ + idct9(xBuf+9); /* odd */ + + xp = xBuf + 8; + cp = c18 + 8; + mOut = 0; + if (btPrev == 0 && btCurr == 0) { + /* fast path - use symmetry of sin window to reduce windowing multiplies to 18 (N/2) */ + wp = fastWin36; + for (i = 0; i < 9; i++) { + /* do ARM-style pointer arithmetic (i still needed for y[] indexing - compiler spills if 2 y pointers) */ + c = *cp--; xo = *(xp + 9); xe = *xp--; + /* gain 2 int bits here */ + xo = MULSHIFT32(c, xo); /* 2*c18*xOdd (mul by 2 implicit in scaling) */ + xe >>= 2; + + s = -(*xPrev); /* sum from last block (always at least 2 guard bits) */ + d = -(xe - xo); /* gain 2 int bits, don't shift xo (effective << 1 to eat sign bit, << 1 for mul by 2) */ + (*xPrev++) = xe + xo; /* symmetry - xPrev[i] = xPrev[17-i] for long blocks */ + t = s - d; + + yLo = (d + (MULSHIFT32(t, *wp++) << 2)); + yHi = (s + (MULSHIFT32(t, *wp++) << 2)); + y[(i)*NBANDS] = yLo; + y[(17-i)*NBANDS] = yHi; + mOut |= FASTABS(yLo); + mOut |= FASTABS(yHi); + } + } else { + /* slower method - either prev or curr is using window type != 0 so do full 36-point window + * output xPrevWin has at least 3 guard bits (xPrev has 2, gain 1 in WinPrevious) + */ + WinPrevious(xPrev, xPrevWin, btPrev); + + wp = imdctWin[btCurr]; + for (i = 0; i < 9; i++) { + c = *cp--; xo = *(xp + 9); xe = *xp--; + /* gain 2 int bits here */ + xo = MULSHIFT32(c, xo); /* 2*c18*xOdd (mul by 2 implicit in scaling) */ + xe >>= 2; + + d = xe - xo; + (*xPrev++) = xe + xo; /* symmetry - xPrev[i] = xPrev[17-i] for long blocks */ + + yLo = (xPrevWin[i] + MULSHIFT32(d, wp[i])) << 2; + yHi = (xPrevWin[17-i] + MULSHIFT32(d, wp[17-i])) << 2; + y[(i)*NBANDS] = yLo; + y[(17-i)*NBANDS] = yHi; + mOut |= FASTABS(yLo); + mOut |= FASTABS(yHi); + } + } + + xPrev -= 9; + mOut |= FreqInvertRescale(y, xPrev, blockIdx, es); + + return mOut; +} + +static const int c3_0 = 0x6ed9eba1; /* format = Q31, cos(pi/6) */ +static const int c6[3] = { 0x7ba3751d, 0x5a82799a, 0x2120fb83 }; /* format = Q31, cos(((0:2) + 0.5) * (pi/6)) */ + +/* 12-point inverse DCT, used in IMDCT12x3() + * 4 input guard bits will ensure no overflow + */ +static __inline void imdct12 (int *x, int *out) +{ + int a0, a1, a2; + int x0, x1, x2, x3, x4, x5; + + x0 = *x; x+=3; x1 = *x; x+=3; + x2 = *x; x+=3; x3 = *x; x+=3; + x4 = *x; x+=3; x5 = *x; x+=3; + + x4 -= x5; + x3 -= x4; + x2 -= x3; + x3 -= x5; + x1 -= x2; + x0 -= x1; + x1 -= x3; + + x0 >>= 1; + x1 >>= 1; + + a0 = MULSHIFT32(c3_0, x2) << 1; + a1 = x0 + (x4 >> 1); + a2 = x0 - x4; + x0 = a1 + a0; + x2 = a2; + x4 = a1 - a0; + + a0 = MULSHIFT32(c3_0, x3) << 1; + a1 = x1 + (x5 >> 1); + a2 = x1 - x5; + + /* cos window odd samples, mul by 2, eat sign bit */ + x1 = MULSHIFT32(c6[0], a1 + a0) << 2; + x3 = MULSHIFT32(c6[1], a2) << 2; + x5 = MULSHIFT32(c6[2], a1 - a0) << 2; + + *out = x0 + x1; out++; + *out = x2 + x3; out++; + *out = x4 + x5; out++; + *out = x4 - x5; out++; + *out = x2 - x3; out++; + *out = x0 - x1; +} + +/************************************************************************************** + * Function: IMDCT12x3 + * + * Description: three 12-point modified DCT's for short blocks, with windowing, + * short block concatenation, and overlap-add + * + * Inputs: 3 interleaved vectors of 6 samples each + * (block0[0], block1[0], block2[0], block0[1], block1[1]....) + * overlap part of last IMDCT (9 samples - see output comments) + * window type (0,1,2,3) of previous block + * current block index (for deciding whether to do frequency inversion) + * number of guard bits in input vector + * + * Outputs: updated sample vector x, net gain of 1 integer bit + * second half of (unwindowed) IMDCT's - save for next time + * only save 9 xPrev samples, using symmetry (see WinPrevious()) + * + * Return: mOut (OR of abs(y) for all y calculated here) + * + * TODO: optimize for ARM + **************************************************************************************/ +static int IMDCT12x3(int *xCurr, int *xPrev, int *y, int btPrev, int blockIdx, int gb) +{ + int i, es, mOut, yLo, xBuf[18], xPrevWin[18]; /* need temp buffer for reordering short blocks */ + const int *wp; + + es = 0; + /* 7 gb is always adequate for accumulator loop + idct12 + window + overlap */ + if (gb < 7) { + es = 7 - gb; + for (i = 0; i < 18; i+=2) { + xCurr[i+0] >>= es; + xCurr[i+1] >>= es; + *xPrev++ >>= es; + } + xPrev -= 9; + } + + /* requires 4 input guard bits for each imdct12 */ + imdct12(xCurr + 0, xBuf + 0); + imdct12(xCurr + 1, xBuf + 6); + imdct12(xCurr + 2, xBuf + 12); + + /* window previous from last time */ + WinPrevious(xPrev, xPrevWin, btPrev); + + /* could unroll this for speed, minimum loads (short blocks usually rare, so doesn't make much overall difference) + * xPrevWin[i] << 2 still has 1 gb always, max gain of windowed xBuf stuff also < 1.0 and gain the sign bit + * so y calculations won't overflow + */ + wp = imdctWin[2]; + mOut = 0; + for (i = 0; i < 3; i++) { + yLo = (xPrevWin[ 0+i] << 2); + mOut |= FASTABS(yLo); y[( 0+i)*NBANDS] = yLo; + yLo = (xPrevWin[ 3+i] << 2); + mOut |= FASTABS(yLo); y[( 3+i)*NBANDS] = yLo; + yLo = (xPrevWin[ 6+i] << 2) + (MULSHIFT32(wp[0+i], xBuf[3+i])); + mOut |= FASTABS(yLo); y[( 6+i)*NBANDS] = yLo; + yLo = (xPrevWin[ 9+i] << 2) + (MULSHIFT32(wp[3+i], xBuf[5-i])); + mOut |= FASTABS(yLo); y[( 9+i)*NBANDS] = yLo; + yLo = (xPrevWin[12+i] << 2) + (MULSHIFT32(wp[6+i], xBuf[2-i]) + MULSHIFT32(wp[0+i], xBuf[(6+3)+i])); + mOut |= FASTABS(yLo); y[(12+i)*NBANDS] = yLo; + yLo = (xPrevWin[15+i] << 2) + (MULSHIFT32(wp[9+i], xBuf[0+i]) + MULSHIFT32(wp[3+i], xBuf[(6+5)-i])); + mOut |= FASTABS(yLo); y[(15+i)*NBANDS] = yLo; + } + + /* save previous (unwindowed) for overlap - only need samples 6-8, 12-17 */ + for (i = 6; i < 9; i++) + *xPrev++ = xBuf[i] >> 2; + for (i = 12; i < 18; i++) + *xPrev++ = xBuf[i] >> 2; + + xPrev -= 9; + mOut |= FreqInvertRescale(y, xPrev, blockIdx, es); + + return mOut; +} + +/************************************************************************************** + * Function: HybridTransform + * + * Description: IMDCT's, windowing, and overlap-add on long/short/mixed blocks + * + * Inputs: vector of input coefficients, length = nBlocksTotal * 18) + * vector of overlap samples from last time, length = nBlocksPrev * 9) + * buffer for output samples, length = MAXNSAMP + * SideInfoSub struct for this granule/channel + * BlockCount struct with necessary info + * number of non-zero input and overlap blocks + * number of long blocks in input vector (rest assumed to be short blocks) + * number of blocks which use long window (type) 0 in case of mixed block + * (bc->currWinSwitch, 0 for non-mixed blocks) + * + * Outputs: transformed, windowed, and overlapped sample buffer + * does frequency inversion on odd blocks + * updated buffer of samples for overlap + * + * Return: number of non-zero IMDCT blocks calculated in this call + * (including overlap-add) + * + * TODO: examine mixedBlock/winSwitch logic carefully (test he_mode.bit) + **************************************************************************************/ +static int HybridTransform(int *xCurr, int *xPrev, int y[BLOCK_SIZE][NBANDS], SideInfoSub *sis, BlockCount *bc) +{ + int xPrevWin[18], currWinIdx, prevWinIdx; + int i, j, nBlocksOut, nonZero, mOut; + int fiBit, xp; + + ASSERT(bc->nBlocksLong <= NBANDS); + ASSERT(bc->nBlocksTotal <= NBANDS); + ASSERT(bc->nBlocksPrev <= NBANDS); + + mOut = 0; + + /* do long blocks, if any */ + for(i = 0; i < bc->nBlocksLong; i++) { + /* currWinIdx picks the right window for long blocks (if mixed, long blocks use window type 0) */ + currWinIdx = sis->blockType; + if (sis->mixedBlock && i < bc->currWinSwitch) + currWinIdx = 0; + + prevWinIdx = bc->prevType; + if (i < bc->prevWinSwitch) + prevWinIdx = 0; + + /* do 36-point IMDCT, including windowing and overlap-add */ + mOut |= IMDCT36(xCurr, xPrev, &(y[0][i]), currWinIdx, prevWinIdx, i, bc->gbIn); + xCurr += 18; + xPrev += 9; + } + + /* do short blocks (if any) */ + for ( ; i < bc->nBlocksTotal; i++) { + ASSERT(sis->blockType == 2); + + prevWinIdx = bc->prevType; + if (i < bc->prevWinSwitch) + prevWinIdx = 0; + + mOut |= IMDCT12x3(xCurr, xPrev, &(y[0][i]), prevWinIdx, i, bc->gbIn); + xCurr += 18; + xPrev += 9; + } + nBlocksOut = i; + + /* window and overlap prev if prev longer that current */ + for ( ; i < bc->nBlocksPrev; i++) { + prevWinIdx = bc->prevType; + if (i < bc->prevWinSwitch) + prevWinIdx = 0; + WinPrevious(xPrev, xPrevWin, prevWinIdx); + + nonZero = 0; + fiBit = i << 31; + for (j = 0; j < 9; j++) { + xp = xPrevWin[2*j+0] << 2; /* << 2 temp for scaling */ + nonZero |= xp; + y[2*j+0][i] = xp; + mOut |= FASTABS(xp); + + /* frequency inversion on odd blocks/odd samples (flip sign if i odd, j odd) */ + xp = xPrevWin[2*j+1] << 2; + xp = (xp ^ (fiBit >> 31)) + (i & 0x01); + nonZero |= xp; + y[2*j+1][i] = xp; + mOut |= FASTABS(xp); + + xPrev[j] = 0; + } + xPrev += 9; + if (nonZero) + nBlocksOut = i; + } + + /* clear rest of blocks */ + for ( ; i < 32; i++) { + for (j = 0; j < 18; j++) + y[j][i] = 0; + } + + bc->gbOut = CLZ(mOut) - 1; + + return nBlocksOut; +} + +/************************************************************************************** + * Function: IMDCT + * + * Description: do alias reduction, inverse MDCT, overlap-add, and frequency inversion + * + * Inputs: MP3DecInfo structure filled by UnpackFrameHeader(), UnpackSideInfo(), + * UnpackScaleFactors(), and DecodeHuffman() (for this granule, channel) + * includes PCM samples in overBuf (from last call to IMDCT) for OLA + * index of current granule and channel + * + * Outputs: PCM samples in outBuf, for input to subband transform + * PCM samples in overBuf, for OLA next time + * updated hi->nonZeroBound index for this channel + * + * Return: 0 on success, -1 if null input pointers + **************************************************************************************/ +int IMDCT(MP3DecInfo *mp3DecInfo, int gr, int ch) +{ + int nBfly, blockCutoff; + FrameHeader *fh; + SideInfo *si; + HuffmanInfo *hi; + IMDCTInfo *mi; + BlockCount bc; + + /* validate pointers */ + if (!mp3DecInfo || !mp3DecInfo->FrameHeaderPS || !mp3DecInfo->SideInfoPS || + !mp3DecInfo->HuffmanInfoPS || !mp3DecInfo->IMDCTInfoPS) + return -1; + + /* si is an array of up to 4 structs, stored as gr0ch0, gr0ch1, gr1ch0, gr1ch1 */ + fh = (FrameHeader *)(mp3DecInfo->FrameHeaderPS); + si = (SideInfo *)(mp3DecInfo->SideInfoPS); + hi = (HuffmanInfo*)(mp3DecInfo->HuffmanInfoPS); + mi = (IMDCTInfo *)(mp3DecInfo->IMDCTInfoPS); + + /* anti-aliasing done on whole long blocks only + * for mixed blocks, nBfly always 1, except 3 for 8 kHz MPEG 2.5 (see sfBandTab) + * nLongBlocks = number of blocks with (possibly) non-zero power + * nBfly = number of butterflies to do (nLongBlocks - 1, unless no long blocks) + */ + blockCutoff = fh->sfBand->l[(fh->ver == MPEG1 ? 8 : 6)] / 18; /* same as 3* num short sfb's in spec */ + if (si->sis[gr][ch].blockType != 2) { + /* all long transforms */ + bc.nBlocksLong = MIN((hi->nonZeroBound[ch] + 7) / 18 + 1, 32); + nBfly = bc.nBlocksLong - 1; + } else if (si->sis[gr][ch].blockType == 2 && si->sis[gr][ch].mixedBlock) { + /* mixed block - long transforms until cutoff, then short transforms */ + bc.nBlocksLong = blockCutoff; + nBfly = bc.nBlocksLong - 1; + } else { + /* all short transforms */ + bc.nBlocksLong = 0; + nBfly = 0; + } + + AntiAlias(hi->huffDecBuf[ch], nBfly); + hi->nonZeroBound[ch] = MAX(hi->nonZeroBound[ch], (nBfly * 18) + 8); + + ASSERT(hi->nonZeroBound[ch] <= MAX_NSAMP); + + /* for readability, use a struct instead of passing a million parameters to HybridTransform() */ + bc.nBlocksTotal = (hi->nonZeroBound[ch] + 17) / 18; + bc.nBlocksPrev = mi->numPrevIMDCT[ch]; + bc.prevType = mi->prevType[ch]; + bc.prevWinSwitch = mi->prevWinSwitch[ch]; + bc.currWinSwitch = (si->sis[gr][ch].mixedBlock ? blockCutoff : 0); /* where WINDOW switches (not nec. transform) */ + bc.gbIn = hi->gb[ch]; + + mi->numPrevIMDCT[ch] = HybridTransform(hi->huffDecBuf[ch], mi->overBuf[ch], mi->outBuf[ch], &si->sis[gr][ch], &bc); + mi->prevType[ch] = si->sis[gr][ch].blockType; + mi->prevWinSwitch[ch] = bc.currWinSwitch; /* 0 means not a mixed block (either all short or all long) */ + mi->gb[ch] = bc.gbOut; + + ASSERT(mi->numPrevIMDCT[ch] <= NBANDS); + + /* output has gained 2 int bits */ + return 0; +} +#endif /* CONFIG_APP_MP3PLAYER */ diff --git a/beken_os/beken378/func/music_player/Mp3Lib/layer21.c b/beken_os/beken378/func/music_player/Mp3Lib/layer21.c new file mode 100755 index 0000000..76f85fa --- /dev/null +++ b/beken_os/beken378/func/music_player/Mp3Lib/layer21.c @@ -0,0 +1,1253 @@ +#include +#include +#include "layer21.h" +#include "mp3dec.h" + +#if (CONFIG_APP_MP3PLAYER == 1) + +const uint16_t mpa_bitrate_tab[2][3][15] = { + { {0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448 }, + {0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384 }, + {0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320 } }, + { {0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256}, + {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160}, + {0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160} + } +}; + +const uint16_t mpa_freq_tab[3] = { 44100, 48000, 32000 }; + +/*******************************************************/ +/* layer 2 tables */ + +const int sblimit_table[5] = { 27 , 30 , 8, 12 , 30 }; + +const int quant_steps[17] = { + 3, 5, 7, 9, 15, + 31, 63, 127, 255, 511, + 1023, 2047, 4095, 8191, 16383, + 32767, 65535 +}; + +/* we use a negative value if grouped */ +const int quant_bits[17] = { + -5, -7, 3, -10, 4, + 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, + 15, 16 +}; + +/* encoding tables which give the quantization index. Note how it is + possible to store them efficiently ! */ +const unsigned char alloc_table_0[] = { + 4, 0, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 4, 0, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 4, 0, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 2, 0, 1, 16, + 2, 0, 1, 16, + 2, 0, 1, 16, + 2, 0, 1, 16, +}; + +const unsigned char alloc_table_1[] = { + 4, 0, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 4, 0, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 4, 0, 2, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 3, 0, 1, 2, 3, 4, 5, 16, + 2, 0, 1, 16, + 2, 0, 1, 16, + 2, 0, 1, 16, + 2, 0, 1, 16, + 2, 0, 1, 16, + 2, 0, 1, 16, + 2, 0, 1, 16, +}; + +const unsigned char alloc_table_2[] = { + 4, 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 4, 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, +}; + +const unsigned char alloc_table_3[] = { + 4, 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 4, 0, 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, +}; + +const unsigned char alloc_table_4[] = { + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 4, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, + 3, 0, 1, 3, 4, 5, 6, 7, + 2, 0, 1, 3, + 2, 0, 1, 3, + 2, 0, 1, 3, + 2, 0, 1, 3, + 2, 0, 1, 3, + 2, 0, 1, 3, + 2, 0, 1, 3, + 2, 0, 1, 3, + 2, 0, 1, 3, + 2, 0, 1, 3, + 2, 0, 1, 3, + 2, 0, 1, 3, + 2, 0, 1, 3, + 2, 0, 1, 3, + 2, 0, 1, 3, + 2, 0, 1, 3, + 2, 0, 1, 3, + 2, 0, 1, 3, + 2, 0, 1, 3, +}; + +const uint8_t * const alloc_tables[5] = + { alloc_table_0, alloc_table_1, alloc_table_2, alloc_table_3, alloc_table_4}; + +/*******************************************************/ + +const int16_t window[512]= + { + /********window begin *************/ + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + 0x0000,0x0000,0x0000,0xffff,0xffff,0xffff,0xffff,0xffff, + 0xffff,0xffff,0xfffe,0xfffe,0xfffe,0xfffe,0xfffe,0xfffd, + 0xfffd,0xfffd,0xfffc,0xfffc,0xfffb,0xfffb,0xfffa,0xfffa, + 0xfff9,0xfff8,0xfff7,0xfff7,0xfff6,0xfff5,0xfff4,0xfff3, + 0xfff2,0xfff0,0xffef,0xffee,0xffec,0xffeb,0xffe9,0xffe8, + 0xffe6,0xffe4,0xffe3,0xffe1,0xffdf,0xffdd,0xffdb,0xffda, + 0xffd8,0xffd6,0xffd4,0xffd2,0xffd1,0xffcf,0xffce,0xffcc, + 0x0035,0x0037,0x0038,0x0038,0x0039,0x0039,0x0039,0x0039, + 0x0038,0x0037,0x0036,0x0034,0x0032,0x002f,0x002c,0x0029, + 0x0025,0x0020,0x001b,0x0015,0x000e,0x0007,0x0000,0xfff7, + 0xffee,0xffe4,0xffda,0xffcf,0xffc3,0xffb7,0xffa9,0xff9c, + 0xff8d,0xff7e,0xff6f,0xff5f,0xff4e,0xff3d,0xff2c,0xff1a, + 0xff08,0xfef6,0xfee4,0xfed2,0xfebf,0xfead,0xfe9b,0xfe8a, + 0xfe78,0xfe68,0xfe58,0xfe48,0xfe3a,0xfe2d,0xfe20,0xfe16, + 0xfe0c,0xfe04,0xfdfe,0xfdf9,0xfdf7,0xfdf6,0xfdf8,0xfdfc, + 0x01fd,0x01f4,0x01e8,0x01d9,0x01c8,0x01b3,0x019b,0x0180, + 0x0162,0x0140,0x011b,0x00f3,0x00c7,0x0097,0x0065,0x002e, + 0xfff5,0xffb8,0xff78,0xff35,0xfeee,0xfea5,0xfe59,0xfe0b, + 0xfdba,0xfd66,0xfd11,0xfcba,0xfc62,0xfc08,0xfbae,0xfb53, + 0xfaf8,0xfa9d,0xfa42,0xf9e9,0xf991,0xf93a,0xf8e6,0xf895, + 0xf847,0xf7fc,0xf7b5,0xf773,0xf737,0xf6ff,0xf6ce,0xf6a4, + 0xf680,0xf665,0xf651,0xf646,0xf645,0xf64c,0xf65e,0xf67b, + 0xf6a2,0xf6d5,0xf713,0xf75e,0xf7b5,0xf819,0xf88a,0xf909, + 0x066c,0x05d2,0x052a,0x0474,0x03b0,0x02de,0x01fd,0x010f, + 0x0012,0xff07,0xfdee,0xfcc7,0xfb93,0xfa52,0xf904,0xf7a9, + 0xf642,0xf4d0,0xf353,0xf1cb,0xf039,0xee9e,0xecfb,0xeb4f, + 0xe99c,0xe7e3,0xe624,0xe460,0xe298,0xe0cd,0xdf00,0xdd32, + 0xdb64,0xd996,0xd7ca,0xd601,0xd43b,0xd27a,0xd0bf,0xcf0a, + 0xcd5d,0xcbb9,0xca1e,0xc88e,0xc709,0xc591,0xc426,0xc2c9, + 0xc17b,0xc03e,0xbf11,0xbdf5,0xbceb,0xbbf4,0xbb11,0xba41, + 0xb986,0xb8df,0xb84e,0xb7d3,0xb76e,0xb71f,0xb6e6,0xb6c4, + 0x4948,0x493c,0x491a,0x48e1,0x4892,0x482d,0x47b2,0x4721, + 0x467a,0x45bf,0x44ef,0x440c,0x4315,0x420b,0x40ef,0x3fc2, + 0x3e85,0x3d37,0x3bda,0x3a6f,0x38f7,0x3772,0x35e2,0x3447, + 0x32a3,0x30f6,0x2f41,0x2d86,0x2bc5,0x29ff,0x2836,0x266a, + 0x249c,0x22ce,0x2100,0x1f33,0x1d68,0x1ba0,0x19dc,0x181d, + 0x1664,0x14b1,0x1305,0x1162,0x0fc7,0x0e35,0x0cad,0x0b30, + 0x09be,0x0857,0x06fc,0x05ae,0x046d,0x0339,0x0212,0x00f9, + 0xffee,0xfef1,0xfe03,0xfd22,0xfc50,0xfb8c,0xfad6,0xfa2e, + 0x066c,0x06f7,0x0776,0x07e7,0x084b,0x08a2,0x08ed,0x092b, + 0x095e,0x0985,0x09a2,0x09b4,0x09bb,0x09ba,0x09af,0x099b, + 0x0980,0x095c,0x0932,0x0901,0x08c9,0x088d,0x084b,0x0804, + 0x07b9,0x076b,0x071a,0x06c6,0x066f,0x0617,0x05be,0x0563, + 0x0508,0x04ad,0x0452,0x03f8,0x039e,0x0346,0x02ef,0x029a, + 0x0246,0x01f5,0x01a7,0x015b,0x0112,0x00cb,0x0088,0x0048, + 0x000b,0xffd2,0xff9b,0xff69,0xff39,0xff0d,0xfee5,0xfec0, + 0xfe9e,0xfe80,0xfe65,0xfe4d,0xfe38,0xfe27,0xfe18,0xfe0c, + 0x01fd,0x0204,0x0208,0x020a,0x0209,0x0207,0x0202,0x01fc, + 0x01f4,0x01ea,0x01e0,0x01d3,0x01c6,0x01b8,0x01a8,0x0198, + 0x0188,0x0176,0x0165,0x0153,0x0141,0x012e,0x011c,0x010a, + 0x00f8,0x00e6,0x00d4,0x00c3,0x00b2,0x00a1,0x0091,0x0082, + 0x0073,0x0064,0x0057,0x0049,0x003d,0x0031,0x0026,0x001c, + 0x0012,0x0009,0x0000,0xfff9,0xfff2,0xffeb,0xffe5,0xffe0, + 0xffdb,0xffd7,0xffd4,0xffd1,0xffce,0xffcc,0xffca,0xffc9, + 0xffc8,0xffc7,0xffc7,0xffc7,0xffc7,0xffc8,0xffc8,0xffc9, + 0x0035,0x0034,0x0032,0x0031,0x002f,0x002e,0x002c,0x002a, + 0x0028,0x0026,0x0025,0x0023,0x0021,0x001f,0x001d,0x001c, + 0x001a,0x0018,0x0017,0x0015,0x0014,0x0012,0x0011,0x0010, + 0x000e,0x000d,0x000c,0x000b,0x000a,0x0009,0x0009,0x0008, + 0x0007,0x0006,0x0006,0x0005,0x0005,0x0004,0x0004,0x0003, + 0x0003,0x0003,0x0002,0x0002,0x0002,0x0002,0x0002,0x0001, + 0x0001,0x0001,0x0001,0x0001,0x0001,0x0001,0x0000,0x0000, + 0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000,0x0000, + /********window end*************/ + }; +/* lower 2 bits: modulo 3, higher bits: shift */ +const uint16_t scale_factor_modshift[64] = + { + /********scale_factor_modshift begin *************/ + 0x0000,0x0001,0x0002,0x0004,0x0005,0x0006,0x0008,0x0009, + 0x000a,0x000c,0x000d,0x000e,0x0010,0x0011,0x0012,0x0014, + 0x0015,0x0016,0x0018,0x0019,0x001a,0x001c,0x001d,0x001e, + 0x0020,0x0021,0x0022,0x0024,0x0025,0x0026,0x0028,0x0029, + 0x002a,0x002c,0x002d,0x002e,0x0030,0x0031,0x0032,0x0034, + 0x0035,0x0036,0x0038,0x0039,0x003a,0x003c,0x003d,0x003e, + 0x0040,0x0041,0x0042,0x0044,0x0045,0x0046,0x0048,0x0049, + 0x004a,0x004c,0x004d,0x004e,0x0050,0x0051,0x0052,0x0054, + /********scale_factor_modshift end*************/ + }; +/* [i][j]: 2^(-j/3) * FRAC_ONE * 2^(i+2) / (2^(i+2) - 1) */ +const int32_t scale_factor_mult[15][3] = + { + /********scale_factor_mult begin *************/ + {0x00015554,0x00010ee9,0x0000d705}, + {0x00012492,0x0000e836,0x0000b84e}, + {0x00011110,0x0000d8ba,0x0000ac04}, + {0x00010842,0x0000d1bd,0x0000a678}, + {0x00010410,0x0000ce69,0x0000a3d4}, + {0x00010204,0x0000ccc9,0x0000a28a}, + {0x00010100,0x0000cbfb,0x0000a1e6}, + {0x00010080,0x0000cb95,0x0000a195}, + {0x00010040,0x0000cb62,0x0000a16d}, + {0x00010020,0x0000cb49,0x0000a159}, + {0x00010010,0x0000cb3c,0x0000a14f}, + {0x00010008,0x0000cb36,0x0000a14a}, + {0x00010004,0x0000cb33,0x0000a147}, + {0x00010002,0x0000cb31,0x0000a146}, + {0xffff0000,0xffff34d0,0xffff5ebb}, + /********scale_factor_mult end*************/ + }; +/* mult table for layer 2 group quantization */ + +#define SCALE_GEN(v) \ + { FIXR(1.0 * (v)), FIXR(0.7937005259 * (v)), FIXR(0.6299605249 * (v)) } + +const int32_t scale_factor_mult2[3][3] = { + SCALE_GEN(4.0 / 3.0), /* 3 steps */ + SCALE_GEN(4.0 / 5.0), /* 5 steps */ + SCALE_GEN(4.0 / 9.0), /* 9 steps */ +}; + +/* 2^(n/4) */ +const uint32_t scale_factor_mult3[4] = + { + FIXR(1.0), + FIXR(1.18920711500272106671), + FIXR(1.41421356237309504880), + FIXR(1.68179283050742908605), + }; +#define COS0_0 FIXR(0.50060299823519630134) +#define COS0_1 FIXR(0.50547095989754365998) +#define COS0_2 FIXR(0.51544730992262454697) +#define COS0_3 FIXR(0.53104259108978417447) +#define COS0_4 FIXR(0.55310389603444452782) +#define COS0_5 FIXR(0.58293496820613387367) +#define COS0_6 FIXR(0.62250412303566481615) +#define COS0_7 FIXR(0.67480834145500574602) +#define COS0_8 FIXR(0.74453627100229844977) +#define COS0_9 FIXR(0.83934964541552703873) +#define COS0_10 FIXR(0.97256823786196069369) +#define COS0_11 FIXR(1.16943993343288495515) +#define COS0_12 FIXR(1.48416461631416627724) +#define COS0_13 FIXR(2.05778100995341155085) +#define COS0_14 FIXR(3.40760841846871878570) +#define COS0_15 FIXR(10.19000812354805681150) + +#define COS1_0 FIXR(0.50241928618815570551) +#define COS1_1 FIXR(0.52249861493968888062) +#define COS1_2 FIXR(0.56694403481635770368) +#define COS1_3 FIXR(0.64682178335999012954) +#define COS1_4 FIXR(0.78815462345125022473) +#define COS1_5 FIXR(1.06067768599034747134) +#define COS1_6 FIXR(1.72244709823833392782) +#define COS1_7 FIXR(5.10114861868916385802) + +#define COS2_0 FIXR(0.50979557910415916894) +#define COS2_1 FIXR(0.60134488693504528054) +#define COS2_2 FIXR(0.89997622313641570463) +#define COS2_3 FIXR(2.56291544774150617881) + +#define COS3_0 FIXR(0.54119610014619698439) +#define COS3_1 FIXR(1.30656296487637652785) + +#define COS4_0 FIXR(0.70710678118654752439) + +/* butterfly operator */ +#define BF(a, b, c) \ + { \ + tmp0 = tab[a] + tab[b]; \ + tmp1 = tab[a] - tab[b]; \ + tab[a] = tmp0; \ + tab[b] = MULL(tmp1, c); \ + } + +#define BF1(a, b, c, d) \ + { \ + BF(a, b, COS4_0); \ + BF(c, d, -COS4_0); \ + tab[c] += tab[d]; \ + } + +#define BF2(a, b, c, d) \ + { \ + BF(a, b, COS4_0); \ + BF(c, d, -COS4_0); \ + tab[c] += tab[d]; \ + tab[a] += tab[c]; \ + tab[c] += tab[b]; \ + tab[b] += tab[d]; \ + } + +#define ADD(a, b) tab[a] += tab[b] + +/* DCT32 without 1/sqrt(2) coef zero scaling. */ +static void dct32(int32_t *out, int32_t *tab) +{ + int tmp0, tmp1; + + /* pass 1 */ + BF(0, 31, COS0_0); + BF(1, 30, COS0_1); + BF(2, 29, COS0_2); + BF(3, 28, COS0_3); + BF(4, 27, COS0_4); + BF(5, 26, COS0_5); + BF(6, 25, COS0_6); + BF(7, 24, COS0_7); + BF(8, 23, COS0_8); + BF(9, 22, COS0_9); + BF(10, 21, COS0_10); + BF(11, 20, COS0_11); + BF(12, 19, COS0_12); + BF(13, 18, COS0_13); + BF(14, 17, COS0_14); + BF(15, 16, COS0_15); + + /* pass 2 */ + BF(0, 15, COS1_0); + BF(1, 14, COS1_1); + BF(2, 13, COS1_2); + BF(3, 12, COS1_3); + BF(4, 11, COS1_4); + BF(5, 10, COS1_5); + BF(6, 9, COS1_6); + BF(7, 8, COS1_7); + + BF(16, 31, -COS1_0); + BF(17, 30, -COS1_1); + BF(18, 29, -COS1_2); + BF(19, 28, -COS1_3); + BF(20, 27, -COS1_4); + BF(21, 26, -COS1_5); + BF(22, 25, -COS1_6); + BF(23, 24, -COS1_7); + + /* pass 3 */ + BF(0, 7, COS2_0); + BF(1, 6, COS2_1); + BF(2, 5, COS2_2); + BF(3, 4, COS2_3); + + BF(8, 15, -COS2_0); + BF(9, 14, -COS2_1); + BF(10, 13, -COS2_2); + BF(11, 12, -COS2_3); + + BF(16, 23, COS2_0); + BF(17, 22, COS2_1); + BF(18, 21, COS2_2); + BF(19, 20, COS2_3); + + BF(24, 31, -COS2_0); + BF(25, 30, -COS2_1); + BF(26, 29, -COS2_2); + BF(27, 28, -COS2_3); + + /* pass 4 */ + BF(0, 3, COS3_0); + BF(1, 2, COS3_1); + + BF(4, 7, -COS3_0); + BF(5, 6, -COS3_1); + + BF(8, 11, COS3_0); + BF(9, 10, COS3_1); + + BF(12, 15, -COS3_0); + BF(13, 14, -COS3_1); + + BF(16, 19, COS3_0); + BF(17, 18, COS3_1); + + BF(20, 23, -COS3_0); + BF(21, 22, -COS3_1); + + BF(24, 27, COS3_0); + BF(25, 26, COS3_1); + + BF(28, 31, -COS3_0); + BF(29, 30, -COS3_1); + + /* pass 5 */ + BF1(0, 1, 2, 3); + BF2(4, 5, 6, 7); + BF1(8, 9, 10, 11); + BF2(12, 13, 14, 15); + BF1(16, 17, 18, 19); + BF2(20, 21, 22, 23); + BF1(24, 25, 26, 27); + BF2(28, 29, 30, 31); + + /* pass 6 */ + + ADD( 8, 12); + ADD(12, 10); + ADD(10, 14); + ADD(14, 9); + ADD( 9, 13); + ADD(13, 11); + ADD(11, 15); + + out[ 0] = tab[0]; + out[16] = tab[1]; + out[ 8] = tab[2]; + out[24] = tab[3]; + out[ 4] = tab[4]; + out[20] = tab[5]; + out[12] = tab[6]; + out[28] = tab[7]; + out[ 2] = tab[8]; + out[18] = tab[9]; + out[10] = tab[10]; + out[26] = tab[11]; + out[ 6] = tab[12]; + out[22] = tab[13]; + out[14] = tab[14]; + out[30] = tab[15]; + + ADD(24, 28); + ADD(28, 26); + ADD(26, 30); + ADD(30, 25); + ADD(25, 29); + ADD(29, 27); + ADD(27, 31); + + out[ 1] = tab[16] + tab[24]; + out[17] = tab[17] + tab[25]; + out[ 9] = tab[18] + tab[26]; + out[25] = tab[19] + tab[27]; + out[ 5] = tab[20] + tab[28]; + out[21] = tab[21] + tab[29]; + out[13] = tab[22] + tab[30]; + out[29] = tab[23] + tab[31]; + out[ 3] = tab[24] + tab[20]; + out[19] = tab[25] + tab[21]; + out[11] = tab[26] + tab[22]; + out[27] = tab[27] + tab[23]; + out[ 7] = tab[28] + tab[18]; + out[23] = tab[29] + tab[19]; + out[15] = tab[30] + tab[17]; + out[31] = tab[31]; +} +/* signed 16x16 -> 32 multiply add accumulate */ +#define MACS(rt, ra, rb) rt += (ra) * (rb) + +/* signed 16x16 -> 32 multiply */ +#define MULS(ra, rb) ((ra) * (rb)) + +#define OUT_SHIFT (WFRAC_BITS + FRAC_BITS - 15) + +static int round_sample(int sum) +{ + int sum1; + sum1 = (sum + (1 << (OUT_SHIFT - 1))) >> OUT_SHIFT; + if (sum1 < -32768) + sum1 = -32768; + else if (sum1 > 32767) + sum1 = 32767; + //printf("smpls 1:%d\r\n",sum1); + return sum1; +} +#define SUM8(sum, op, w, p) \ + { \ + sum op MULS((w)[0 * 64], p[0 * 64]); \ + sum op MULS((w)[1 * 64], p[1 * 64]); \ + sum op MULS((w)[2 * 64], p[2 * 64]); \ + sum op MULS((w)[3 * 64], p[3 * 64]); \ + sum op MULS((w)[4 * 64], p[4 * 64]); \ + sum op MULS((w)[5 * 64], p[5 * 64]); \ + sum op MULS((w)[6 * 64], p[6 * 64]); \ + sum op MULS((w)[7 * 64], p[7 * 64]); \ + } + +#define SUM8P2(sum1, op1, sum2, op2, w1, w2, p) \ + { \ + int tmp; \ + tmp = p[0 * 64]; \ + sum1 op1 MULS((w1)[0 * 64], tmp); \ + sum2 op2 MULS((w2)[0 * 64], tmp); \ + tmp = p[1 * 64]; \ + sum1 op1 MULS((w1)[1 * 64], tmp); \ + sum2 op2 MULS((w2)[1 * 64], tmp); \ + tmp = p[2 * 64]; \ + sum1 op1 MULS((w1)[2 * 64], tmp); \ + sum2 op2 MULS((w2)[2 * 64], tmp); \ + tmp = p[3 * 64]; \ + sum1 op1 MULS((w1)[3 * 64], tmp); \ + sum2 op2 MULS((w2)[3 * 64], tmp); \ + tmp = p[4 * 64]; \ + sum1 op1 MULS((w1)[4 * 64], tmp); \ + sum2 op2 MULS((w2)[4 * 64], tmp); \ + tmp = p[5 * 64]; \ + sum1 op1 MULS((w1)[5 * 64], tmp); \ + sum2 op2 MULS((w2)[5 * 64], tmp); \ + tmp = p[6 * 64]; \ + sum1 op1 MULS((w1)[6 * 64], tmp); \ + sum2 op2 MULS((w2)[6 * 64], tmp); \ + tmp = p[7 * 64]; \ + sum1 op1 MULS((w1)[7 * 64], tmp); \ + sum2 op2 MULS((w2)[7 * 64], tmp); \ + } + +int unaligned32_be(const void *v) +{ + return SWAP32( (*(uint32_t*)(v))); //original +} + +void init_get_bits(GetBitContext *s, + const uint8_t *buffer, int bit_size) +{ + const int buffer_size= (bit_size+7)>>3; + + s->buffer= buffer; + s->size_in_bits= bit_size; + s->buffer_end= buffer + buffer_size; + s->index=0; +#if 0 + { + OPEN_READER(re, s) + UPDATE_CACHE(re, s) + UPDATE_CACHE(re, s) + CLOSE_READER(re, s) + } +#endif +} + +void skip_bits(GetBitContext *s, int n) +{ + //Note gcc seems to optimize this to s->index+=n for the ALT_READER :)) +#if 1 + s->index+=n; +#else + OPEN_READER(re, s) + UPDATE_CACHE(re, s) + LAST_SKIP_BITS(re, s, n) + CLOSE_READER(re, s) +#endif + } + + +int get_bits_count(GetBitContext *s) +{ + return s->index; +} +unsigned int get_bits1(GetBitContext *s) +{ + int index= s->index; + uint8_t result= s->buffer[ index>>3 ]; + result<<= (index&0x07); + result>>= 8 - 1; + index++; + s->index= index; + return result; +} +unsigned int get_bits(GetBitContext *s, int n){ +#if 0 + register int tmp; + OPEN_READER(re, s) + UPDATE_CACHE(re, s) + tmp= SHOW_UBITS(re, s, n); + LAST_SKIP_BITS(re, s, n) + CLOSE_READER(re, s) +#else + uint32_t tmp=0; + uint16_t i; + for(i=0;i>=1; +#endif + //printf("bits:%x\n",tmp); + return tmp; +} + + + + +/* 32 sub band synthesis filter. Input: 32 sub band samples, Output: + 32 samples. */ +/* XXX: optimize by avoiding ring buffer usage */ +static void synth_filter(L2DecodeContext *s1, + int ch, int16_t *samples, int incr, + int32_t sb_samples[SBLIMIT]) +{ + int32_t tmp[32]; + register int16_t *synth_buf; + register const int16_t *w, *w2, *p; + int j, offset, v; + int16_t *samples2; +#if FRAC_BITS <= 15 + int sum, sum2; +#else + int64_t sum, sum2; +#endif + + dct32(tmp, sb_samples); + offset = s1->synth_buf_offset[ch]; + synth_buf = s1->synth_buf + ch*1024 + offset; + + for(j=0;j<32;j++) { + v = tmp[j]; +#if FRAC_BITS <= 15 + /* NOTE: can cause a loss in precision if very high amplitude + sound */ + if (v > 32767) + v = 32767; + else if (v < -32768) + v = -32768; +#endif + synth_buf[j] = v; + } + /* copy to avoid wrap */ + memcpy(synth_buf + 512, synth_buf, 32 * sizeof(int16_t)); + + samples2 = samples + 31 * incr; + w = window; + w2 = window + 31; + + sum = 0; + p = synth_buf + 16; + SUM8(sum, +=, w, p); + p = synth_buf + 48; + SUM8(sum, -=, w + 32, p); + *samples = round_sample(sum); + samples += incr; + w++; + + /* we calculate two samples at the same time to avoid one memory + access per two sample */ + for(j=1;j<16;j++) { + sum = 0; + sum2 = 0; + p = synth_buf + 16 + j; + SUM8P2(sum, +=, sum2, -=, w, w2, p); + p = synth_buf + 48 - j; + SUM8P2(sum, -=, sum2, -=, w + 32, w2 + 32, p); + + *samples = round_sample(sum); + samples += incr; + *samples2 = round_sample(sum2); + samples2 -= incr; + w++; + w2--; + } + + p = synth_buf + 32; + sum = 0; + SUM8(sum, -=, w + 32, p); + *samples = round_sample(sum); + + offset = (offset - 32) & 511; + s1->synth_buf_offset[ch] = offset; +} + + +/* layer 1 unscaling */ +/* n = number of bits of the mantissa minus 1 */ +static int l1_unscale(int n, int mant, int scale_factor) +{ + int shift, mod; + int64_t val; + + shift = scale_factor_modshift[scale_factor]; + mod = shift & 3; + shift >>= 2; + val = MUL64(mant + (-1 << n) + 1, scale_factor_mult[n-1][mod]); + shift += n; + /* NOTE: at this point, 1 <= shift >= 21 + 15 */ + return (int)((val + (1L << (shift - 1))) >> shift); +} + +static int l2_unscale_group(int steps, int mant, int scale_factor) +{ + int shift, mod, val; + + shift = scale_factor_modshift[scale_factor]; + mod = shift & 3; + shift >>= 2; + + val = (mant - (steps >> 1)) * scale_factor_mult2[steps >> 2][mod]; + /* NOTE: at this point, 0 <= shift <= 21 */ + if (shift > 0) + val = (val + (1 << (shift - 1))) >> shift; + return val; +} +/* fast header check for resync */ +static int check_header(uint32_t header) +{ + /* header */ + if ((header & 0xffe00000) != 0xffe00000) + return -1; + /* layer check */ + if (((header >> 17) & 3) == 0) + return -1; + /* bit rate */ + if (((header >> 12) & 0xf) == 0xf) + return -1; + /* frequency */ + if (((header >> 10) & 3) == 3) + return -1; + return 0; +} + +/* header + layer + bitrate + freq + lsf/mpeg25 */ +#define SAME_HEADER_MASK \ + (0xffe00000 | (3 << 17) | (0xf << 12) | (3 << 10) | (3 << 19)) + +/* header decoding. MUST check the header before because no + consistency check is done there. Return 1 if free format found and + that the frame size must be computed externally */ +static int decode_header(L2DecodeContext *s, uint32_t header) +{ + int sample_rate, frame_size, mpeg25, padding; + int sample_rate_index, bitrate_index; + if (header & (1<<20)) { + s->lsf = (header & (1<<19)) ? 0 : 1; + mpeg25 = 0; + } else { + s->lsf = 1; + mpeg25 = 1; + } + + s->layer = 4 - ((header >> 17) & 3); + /* extract frequency */ + sample_rate_index = (header >> 10) & 3; + sample_rate = mpa_freq_tab[sample_rate_index] >> (s->lsf + mpeg25); + sample_rate_index += 3 * (s->lsf + mpeg25); + s->sample_rate_index = sample_rate_index; + s->error_protection = ((header >> 16) & 1) ^ 1; + s->sample_rate = sample_rate; + + bitrate_index = (header >> 12) & 0xf; + padding = (header >> 9) & 1; + s->mode = (header >> 6) & 3; + s->mode_ext = (header >> 4) & 3; + + if (s->mode == MPA_MONO) + s->nb_channels = 1; + else + s->nb_channels = 2; + + if (bitrate_index != 0) { + frame_size = mpa_bitrate_tab[s->lsf][s->layer - 1][bitrate_index]; + s->bit_rate = frame_size * 1000; + switch(s->layer) { + case 1: + frame_size = (frame_size * 12000) / sample_rate; + frame_size = (frame_size + padding) * 4; + break; + case 2: + frame_size = (frame_size * 144000) / sample_rate; + frame_size += padding; + break; + default: + case 3: + frame_size = (frame_size * 144000) / (sample_rate << s->lsf); + frame_size += padding; + break; + } + s->frame_size = frame_size; + } else { + /* if no frame size computed, signal it */ + if (!s->free_format_frame_size) + return 1; + /* free format: compute bitrate and real frame size from the + frame size we extracted by reading the bitstream */ + s->frame_size = s->free_format_frame_size; + switch(s->layer) { + case 1: + s->frame_size += padding * 4; + s->bit_rate = (s->frame_size * sample_rate) / 48000; + break; + case 2: + s->frame_size += padding; + s->bit_rate = (s->frame_size * sample_rate) / 144000; + break; + default: + case 3: + s->frame_size += padding; + s->bit_rate = (s->frame_size * (sample_rate << s->lsf)) / 144000; + break; + } + } + + return 0; +} + +/* useful helper to get mpeg audio stream infos. Return -1 if error in + header, otherwise the coded frame size in bytes */ +int mpa_decode_header(L2DecodeContext *s, uint32_t head) +{ + uint32_t nHead = SWAP32(head); + + + if (check_header(nHead) != 0) + { + printf("check_header Error\n"); + return -1; + } + + if (decode_header(s, nHead) != 0) + { + return -1; + } + return s->frame_size; +} +/* return the number of decoded frames */ +static int mp_decode_layer1(L2DecodeContext *s) +{ + int bound, i, v=0, n, ch, j, mant; + uint8_t allocation[MPA_MAX_CHANNELS][SBLIMIT]; + uint8_t scale_factors[MPA_MAX_CHANNELS][SBLIMIT]; + + if (s->mode == MPA_JSTEREO) + bound = (s->mode_ext + 1) * 4; + else + bound = SBLIMIT; + + /* allocation bits */ + for(i=0;inb_channels;ch++) { + allocation[ch][i] = get_bits(&s->gb, 4); + } + } + for(i=bound;igb, 4); + } + + /* scale factors */ + for(i=0;inb_channels;ch++) { + if (allocation[ch][i]) + scale_factors[ch][i] = get_bits(&s->gb, 6); + } + } + for(i=bound;igb, 6); + scale_factors[1][i] = get_bits(&s->gb, 6); + } + } + + /* compute samples */ + for(j=0;j<12;j++) { + for(i=0;inb_channels;ch++) { + n = allocation[ch][i]; + if (n) { + mant = get_bits(&s->gb, n + 1); + v = l1_unscale(n, mant, scale_factors[ch][i]); + } else { + v = 0; + } + //s->sb_samples[ch][j][i] = v; + s->sb_samples[ch*12*32+j*32+i] = v; + } + } + for(i=bound;igb, n + 1); + v = l1_unscale(n, mant, scale_factors[0][i]); + //s->sb_samples[0][j][i] = v; + s->sb_samples[0*12*32+j*32+i] = v; + v = l1_unscale(n, mant, scale_factors[1][i]); + //s->sb_samples[1][j][i] = v; + s->sb_samples[1*12*32+j*32+i] = v; + } else { + //s->sb_samples[0][j][i] = 0; + s->sb_samples[0*12*32+j*32+i] = v; + //s->sb_samples[1][j][i] = 0; + s->sb_samples[1*12*32+j*32+i] = v; + } + } + } + return 12; +} + +/* bitrate is in kb/s */ +int l2_select_table(int bitrate, int nb_channels, int freq, int lsf) +{ + int ch_bitrate, table; + + ch_bitrate = bitrate / nb_channels; + if (!lsf) { + if ((freq == 48000 && ch_bitrate >= 56) || + (ch_bitrate >= 56 && ch_bitrate <= 80)) + table = 0; + else if (freq != 48000 && ch_bitrate >= 96) + table = 1; + else if (freq != 32000 && ch_bitrate <= 48) + table = 2; + else + table = 3; + } else { + table = 4; + } + return table; +} + +static int mp_decode_layer2(L2DecodeContext *s) +{ + int sblimit; /* number of used subbands */ + const unsigned char *alloc_table; + int table, bit_alloc_bits, i, j, ch, bound, v; + unsigned char bit_alloc[MPA_MAX_CHANNELS][SBLIMIT]; + unsigned char scale_code[MPA_MAX_CHANNELS][SBLIMIT]; + unsigned char scale_factors[MPA_MAX_CHANNELS][SBLIMIT][3], *sf; + int scale, qindex, bits, steps, k, l, m, b; + + /* select decoding table */ + table = l2_select_table(s->bit_rate / 1000, s->nb_channels, + s->sample_rate, s->lsf); + sblimit = sblimit_table[table]; + alloc_table = alloc_tables[table]; + + if (s->mode == MPA_JSTEREO) + bound = (s->mode_ext + 1) * 4; + else + bound = sblimit; + + + /* sanity check */ + if( bound > sblimit ) bound = sblimit; + + /* parse bit allocation */ + j = 0; + for(i=0;inb_channels;ch++) { + bit_alloc[ch][i] = get_bits(&s->gb, bit_alloc_bits); + } + j += 1 << bit_alloc_bits; + } + for(i=bound;igb, bit_alloc_bits); + bit_alloc[0][i] = v; + bit_alloc[1][i] = v; + j += 1 << bit_alloc_bits; + } + + /* scale codes */ + for(i=0;inb_channels;ch++) { + if (bit_alloc[ch][i]) + scale_code[ch][i] = get_bits(&s->gb, 2); + } + } + + /* scale factors */ + for(i=0;inb_channels;ch++) { + if (bit_alloc[ch][i]) { + sf = scale_factors[ch][i]; + switch(scale_code[ch][i]) { + default: + case 0: + sf[0] = get_bits(&s->gb, 6); + sf[1] = get_bits(&s->gb, 6); + sf[2] = get_bits(&s->gb, 6); + break; + case 2: + sf[0] = get_bits(&s->gb, 6); + sf[1] = sf[0]; + sf[2] = sf[0]; + break; + case 1: + sf[0] = get_bits(&s->gb, 6); + sf[2] = get_bits(&s->gb, 6); + sf[1] = sf[0]; + break; + case 3: + sf[0] = get_bits(&s->gb, 6); + sf[2] = get_bits(&s->gb, 6); + sf[1] = sf[2]; + break; + } + } + } + } + + /* samples */ + for(k=0;k<3;k++) + { + for(l=0;l<12;l+=3) + { + j = 0; + for(i=0;inb_channels;ch++) + { + b = bit_alloc[ch][i]; + if (b) + { + scale = scale_factors[ch][i][k]; + qindex = alloc_table[j+b]; + bits = quant_bits[qindex]; + if (bits < 0) { + /* 3 values at the same time */ + v = get_bits(&s->gb, -bits); + steps = quant_steps[qindex]; + //s->sb_samples[ch][k * 12 + l + 0][i] = + s->sb_samples[ch*36*32+(k * 12 + l + 0)*32+i] = + l2_unscale_group(steps, v % steps, scale); + v = v / steps; + //s->sb_samples[ch][k * 12 + l + 1][i] = + s->sb_samples[ch*36*32+(k * 12 + l + 1)*32+i] = + l2_unscale_group(steps, v % steps, scale); + v = v / steps; + //s->sb_samples[ch][k * 12 + l + 2][i] = + s->sb_samples[ch*36*32+(k * 12 + l + 2)*32+i] = + l2_unscale_group(steps, v, scale); + } else { + for(m=0;m<3;m++) { + v = get_bits(&s->gb, bits); + v = l1_unscale(bits - 1, v, scale); + //s->sb_samples[ch][k * 12 + l + m][i] = v; + s->sb_samples[ch*36*32+(k * 12 + l + m)*32+i] = v; + } + } + } else { + //s->sb_samples[ch][k * 12 + l + 0][i] = 0; + s->sb_samples[ch*36*32+(k * 12 + l + 0)*32+i] = 0; + //s->sb_samples[ch][k * 12 + l + 1][i] = 0; + s->sb_samples[ch*36*32+(k * 12 + l + 1)*32+i] = 0; + //s->sb_samples[ch][k * 12 + l + 2][i] = 0; + s->sb_samples[ch*36*32+(k * 12 + l + 2)*32+i] = 0; + } + } + /* next subband in alloc table */ + j += 1 << bit_alloc_bits; + } + /* XXX: find a way to avoid this duplication of code */ + for(i=bound;igb, -bits); + steps = quant_steps[qindex]; + mant = v % steps; + v = v / steps; + //s->sb_samples[0][k * 12 + l + 0][i] = + s->sb_samples[0*36*32+(k * 12 + l + 0)*32+i] = + l2_unscale_group(steps, mant, scale0); + //s->sb_samples[1][k * 12 + l + 0][i] = + s->sb_samples[1*36*32+(k * 12 + l + 0)*32+i] = + l2_unscale_group(steps, mant, scale1); + mant = v % steps; + v = v / steps; + //s->sb_samples[0][k * 12 + l + 1][i] = + s->sb_samples[0*36*32+(k * 12 + l + 1)*32+i] = + l2_unscale_group(steps, mant, scale0); + //s->sb_samples[1][k * 12 + l + 1][i] = + s->sb_samples[1*36*32+(k * 12 + l + 1)*32+i] = + l2_unscale_group(steps, mant, scale1); + //s->sb_samples[0][k * 12 + l + 2][i] = + s->sb_samples[0*36*32+(k * 12 + l + 2)*32+i] = + l2_unscale_group(steps, v, scale0); + //s->sb_samples[1][k * 12 + l + 2][i] = + s->sb_samples[1*36*32+(k * 12 + l + 2)*32+i] = + l2_unscale_group(steps, v, scale1); + } else { + for(m=0;m<3;m++) { + mant = get_bits(&s->gb, bits); + //s->sb_samples[0][k * 12 + l + m][i] = + s->sb_samples[0*36*32+(k * 12 + l + m)*32+i] = + l1_unscale(bits - 1, mant, scale0); + //s->sb_samples[1][k * 12 + l + m][i] = + s->sb_samples[1*36*32+(k * 12 + l + m)*32+i] = + l1_unscale(bits - 1, mant, scale1); + } + } + } else { + //s->sb_samples[0][k * 12 + l + 0][i] = 0; + s->sb_samples[0*36*32+(k * 12 + l + 0)*32+i] = 0; + //s->sb_samples[0][k * 12 + l + 1][i] = 0; + s->sb_samples[0*36*32+(k * 12 + l + 1)*32+i] = 0; + //s->sb_samples[0][k * 12 + l + 2][i] = 0; + s->sb_samples[0*36*32+(k * 12 + l + 2)*32+i] = 0; + //s->sb_samples[1][k * 12 + l + 0][i] = 0; + s->sb_samples[1*36*32+(k * 12 + l + 0)*32+i] = 0; + //s->sb_samples[1][k * 12 + l + 1][i] = 0; + s->sb_samples[1*36*32+(k * 12 + l + 1)*32+i] = 0; + //s->sb_samples[1][k * 12 + l + 2][i] = 0; + s->sb_samples[1*36*32+(k * 12 + l + 2)*32+i] = 0; + } + /* next subband in alloc table */ + j += 1 << bit_alloc_bits; + } + /* fill remaining samples to zero */ + for(i=sblimit;inb_channels;ch++) { + //s->sb_samples[ch][k * 12 + l + 0][i] = 0; + s->sb_samples[ch*36*32+(k * 12 + l + 0)*32+i] = 0; + //s->sb_samples[ch][k * 12 + l + 1][i] = 0; + s->sb_samples[ch*36*32+(k * 12 + l + 1)*32+i] = 0; + //s->sb_samples[ch][k * 12 + l + 2][i] = 0; + s->sb_samples[ch*36*32+(k * 12 + l + 2)*32+i] = 0; + } + } + } + } + return 3 * 12; +} +static int mp_decode_frame(L2DecodeContext *s, + short *samples) +{ + int i, nb_frames=0, ch; + short *samples_ptr; + + init_get_bits(&s->gb, s->inbuf + HEADER_SIZE, + (s->inbuf_ptr - s->inbuf - HEADER_SIZE)*8); + + /* skip error protection field */ + if (s->error_protection) + get_bits(&s->gb, 16); + + switch(s->layer) + { + case 1: + nb_frames = mp_decode_layer1(s); + break; + case 2: + nb_frames = mp_decode_layer2(s); + break; + case 3: + default: + break; + } + /* apply the synthesis filter */ + for(ch=0;chnb_channels;ch++) + { + samples_ptr = samples + ch; + for(i=0;inb_channels, + s->sb_samples+ch*nb_frames*32+i*32); + samples_ptr += 32 * s->nb_channels; + } + } + return nb_frames * 32 * s->nb_channels; +} +int L2_decode_frame(L2DecodeContext *l2Dec, + void *data, int *data_size, + uint8_t * buf, int buf_size) +{ + L2DecodeContext *s = (L2DecodeContext *)(l2Dec); + + uint32_t header; + short *out_samples = data; + memcpy(&header,buf,4); + if(mpa_decode_header(s, header)<=0) + { + *data_size = 0; + return 0; + } + s->inbuf = buf; + s->inbuf_ptr = buf + buf_size; + + *data_size = mp_decode_frame(s, out_samples); + + return *data_size; +} + +uint32_t L2_GetFrameSize(L2DecodeContext *s,uint32_t head) +{ + uint32_t nHead = SWAP32(head); + + if (check_header(nHead) != 0) + return 0; + + if (decode_header(s, nHead) != 0) + { + return 0; + } + return s->frame_size; +} +#endif /*CONFIG_APP_MP3PLAYER*/ diff --git a/beken_os/beken378/func/music_player/Mp3Lib/layer21.h b/beken_os/beken378/func/music_player/Mp3Lib/layer21.h new file mode 100755 index 0000000..87bf7f2 --- /dev/null +++ b/beken_os/beken378/func/music_player/Mp3Lib/layer21.h @@ -0,0 +1,78 @@ +#ifndef _LAYER21_H +#define _LAYER21_H + +#include "include.h" + +#if (CONFIG_APP_MP3PLAYER == 1) + /* max frame size, in samples */ +#define MPA_FRAME_SIZE 1152 + + /* max compressed frame size */ +#define MPA_MAX_CODED_FRAME_SIZE 1792 + +#define MPA_MAX_CHANNELS 2 + +#define SBLIMIT 32 /* number of subbands */ + +#define MPA_STEREO 0 +#define MPA_JSTEREO 1 +#define MPA_DUAL 2 +#define MPA_MONO 3 + +#define HEADER_SIZE 4 +#define BACKSTEP_SIZE 512 + +#define FRAC_BITS 15 /* fractional bits for sb_samples and dct */ +#define WFRAC_BITS 14 /* fractional bits for window */ + +#define FRAC_ONE (1 << FRAC_BITS) + +#define int64_t_C(c) (c ## L) + +#define MULL32(a,b) (((int32_t)(a) * (int32_t)(b)) >> FRAC_BITS) +#define MULL(a,b) (((int64_t)(a) * (int64_t)(b)) >> FRAC_BITS) +#define MUL64(a,b) ((int64_t)(a) * (int64_t)(b)) + +#define FIX(a) ((int)((a) * FRAC_ONE)) + +/* WARNING: only correct for posititive numbers */ +#define FIXR(a) ((int)((a) * FRAC_ONE + 0.5)) +#define FRAC_RND(a) (((a) + (FRAC_ONE/2)) >> FRAC_BITS) +#define SWAP32(val) (uint32_t)((((uint32_t)(val)) & 0x000000FF)<<24| \ + (((uint32_t)(val)) & 0x0000FF00)<<8 | \ + (((uint32_t)(val)) & 0x00FF0000)>>8 | \ + (((uint32_t)(val)) & 0xFF000000)>>24) +typedef int16_t MPA_INT; + +typedef struct _GetBitContext +{ + const uint8_t *buffer, *buffer_end; + int index; + int size_in_bits; +} GetBitContext; + +typedef struct _L2DecodeContext { + uint8_t *inbuf_ptr, *inbuf; + int32_t frame_size; + int32_t free_format_frame_size; + int32_t error_protection; + int32_t layer; + int32_t sample_rate; + int32_t mode; + int32_t mode_ext; + int32_t sample_rate_index; /* between 0 and 8 */ + int32_t bit_rate; + int32_t lsf; + GetBitContext gb; + int32_t nb_channels; + int16_t *synth_buf;//synth_buf[2][512 * 2]; + int32_t synth_buf_offset[2]; + int32_t *sb_samples; +} L2DecodeContext; + +int L2_decode_frame(L2DecodeContext *l2Dec, + void *data, int *data_size, + uint8_t * buf, int buf_size); +uint32_t L2_GetFrameSize(L2DecodeContext *s,uint32_t head); +#endif /* CONFIG_APP_MP3PLAYER */ +#endif diff --git a/beken_os/beken378/func/music_player/Mp3Lib/mp3_play.c b/beken_os/beken378/func/music_player/Mp3Lib/mp3_play.c new file mode 100755 index 0000000..194eae1 --- /dev/null +++ b/beken_os/beken378/func/music_player/Mp3Lib/mp3_play.c @@ -0,0 +1,71 @@ +/** + ****************************************************************************** + * @file Project/play.c + * @version V1.0.0 + * @brief this file provides all audio play relevant function + ****************************************************************************** + * @copy + * + * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS + * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE + * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY + * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING + * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE + * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. + * + */ + +/* Includes ------------------------------------------------------------------*/ +#include +#include "mp3dec.h" +#include "mp3common.h" + +#if (CONFIG_APP_MP3PLAYER == 1) +/************************************************************************************/ +/* +* File Name : Convert_Stereo ת +* Description : I have do some modification in Subband() function due to the long time of +* decode.Using PolyphaseMono() function which is used in decode mono mp3,to decode +* Stereo,so must use this funtion to convert mono to Stereo. +* Input : Adress of buffer data +* Output : None +* Return : None +*/ +/************************************************************************************/ +void Convert_Stereo(short *buffer) +{ + int i,j,k=0; + for(i=0;i<(2304/64);i++) //36 + { + for(j=31+i*64,k=j+32;j>=0+i*64;j--,k-=2) + { + buffer[k]=buffer[j]; + buffer[k-1]=buffer[j]; + } + } +} + +/***********************************************************************************/ +/* +* File Name : Convert_Mono +* Description : ĵMP3Ŀܣ1152֣*ı䵥 +* Input : Adress of buffer data +* Output : None +* Return : None +*/ +/***********************************************************************************/ +void Convert_Mono(short *buffer, int outputSamps) +{ + int i; + if(outputSamps > 1152) + { + return; + } + for (i = outputSamps - 1; i >= 0; i--) + { + buffer[i * 2 + 1] = buffer[i]; + buffer[i * 2] = buffer[i]; + } +} +#endif /* CONFIG_APP_MP3PLAYER */ + diff --git a/beken_os/beken378/func/music_player/Mp3Lib/mp3common.h b/beken_os/beken378/func/music_player/Mp3Lib/mp3common.h new file mode 100755 index 0000000..2bbd4a8 --- /dev/null +++ b/beken_os/beken378/func/music_player/Mp3Lib/mp3common.h @@ -0,0 +1,139 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: RCSL 1.0/RPSL 1.0 + * + * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. + * + * The contents of this file, and the files included with this file, are + * subject to the current version of the RealNetworks Public Source License + * Version 1.0 (the "RPSL") available at + * http://www.helixcommunity.org/content/rpsl unless you have licensed + * the file under the RealNetworks Community Source License Version 1.0 + * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, + * in which case the RCSL will apply. You may also obtain the license terms + * directly from RealNetworks. You may not use this file except in + * compliance with the RPSL or, if you have a valid RCSL with RealNetworks + * applicable to this file, the RCSL. Please see the applicable RPSL or + * RCSL for the rights, obligations and limitations governing use of the + * contents of the file. + * + * This file is part of the Helix DNA Technology. RealNetworks is the + * developer of the Original Code and owns the copyrights in the portions + * it created. + * + * This file, and the files included with this file, is distributed and made + * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * + * Technology Compatibility Kit Test Suite(s) Location: + * http://www.helixcommunity.org/content/tck + * + * Contributor(s): + * + * ***** END LICENSE BLOCK ***** */ + +/************************************************************************************** + * Fixed-point MP3 decoder + * Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com) + * June 2003 + * + * mp3common.h - implementation-independent API's, datatypes, and definitions + **************************************************************************************/ + +#ifndef _MP3COMMON_H +#define _MP3COMMON_H + +#include "include.h" +#include "mp3dec.h" +#include "statname.h" /* do name-mangling for static linking */ + +#if (CONFIG_APP_MP3PLAYER == 1) + +#define MAX_SCFBD 4 /* max scalefactor bands per channel */ +#define NGRANS_MPEG1 2 +#define NGRANS_MPEG2 1 + +/* 11-bit syncword if MPEG 2.5 extensions are enabled */ +#define SYNCWORDH 0xff +#define SYNCWORDL 0xe0 +#define SYNCWORD_NOT_SURE 0x7f000000 + +/* 12-bit syncword if MPEG 1,2 only are supported + * #define SYNCWORDH 0xff + * #define SYNCWORDL 0xf0 + */ + +typedef struct _MP3DecInfo { + /* pointers to platform-specific data structures */ + void *FrameHeaderPS; + void *SideInfoPS; + void *ScaleFactorInfoPS; + void *HuffmanInfoPS; + void *DequantInfoPS; + void *IMDCTInfoPS; + void *SubbandInfoPS; + void *L2DecInfo; + + unsigned char bit_reservoir[BIT_RESVOR_SIZE]; + unsigned char *mainBuf; + unsigned char *mainBuf_ptr; + int mainBuf_len; + + /* special info for "free" bitrate files */ + int freeBitrateFlag; + int freeBitrateSlots; + + /* user-accessible info */ + int bitrate; + int nChans; + int samprate; + int nGrans; /* granules per frame */ + int nGranSamps; /* samples per granule */ + int nSlots; + int layer; +#if CALC_PLAY_TIME + int curFramecnt; + int totalframes; + int filetype; /*CBR:0x1, VBR:Xing 0x2--VBRI 0x4*/ + int timePerframe; +#endif + MPEGVersion version; + + int mainDataBegin; + int mainDataBytes; + int framesize; + int part23Length[MAX_NGRAN][MAX_NCHAN]; + + unsigned int decode_state; + unsigned int err_cnt; + +} MP3DecInfo; + +typedef struct _SFBandTable { + short l[23]; + short s[14]; +} SFBandTable; + +/* decoder functions which must be implemented for each platform */ +MP3DecInfo *AllocateBuffers(void); +void FreeBuffers(MP3DecInfo *mp3DecInfo); +int CheckPadBit(MP3DecInfo *mp3DecInfo); +int UnpackFrameHeader(MP3DecInfo *mp3DecInfo, unsigned char *buf); +int UnpackSideInfo(MP3DecInfo *mp3DecInfo, unsigned char *buf); +int DecodeHuffman(MP3DecInfo *mp3DecInfo, unsigned char *buf, int *bitOffset, int huffBlockBits, int gr, int ch); +int Dequantize(MP3DecInfo *mp3DecInfo, int gr); +int IMDCT(MP3DecInfo *mp3DecInfo, int gr, int ch); +int UnpackScaleFactors(MP3DecInfo *mp3DecInfo, unsigned char *buf, int *bitOffset, int bitsAvail, int gr, int ch); +int Subband(MP3DecInfo *mp3DecInfo, short **pcmBuf); + +/* mp3tabs.c - global ROM tables */ +extern const int samplerateTab[3][3]; +extern const short bitrateTab[3][3][15]; +extern const short samplesPerFrameTab[3][3]; +extern const short bitsPerSlotTab[3]; +extern const short sideBytesTab[3][2]; +extern const short slotTab[3][3][15]; +extern const SFBandTable sfBandTable[3][3]; +#endif /* CONFIG_APP_MP3PLAYER */ +#endif /* _MP3COMMON_H */ diff --git a/beken_os/beken378/func/music_player/Mp3Lib/mp3dec.c b/beken_os/beken378/func/music_player/Mp3Lib/mp3dec.c new file mode 100755 index 0000000..11ed7f8 --- /dev/null +++ b/beken_os/beken378/func/music_player/Mp3Lib/mp3dec.c @@ -0,0 +1,932 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: RCSL 1.0/RPSL 1.0 + * + * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. + * + * The contents of this file, and the files included with this file, are + * subject to the current version of the RealNetworks Public Source License + * Version 1.0 (the "RPSL") available at + * http://www.helixcommunity.org/content/rpsl unless you have licensed + * the file under the RealNetworks Community Source License Version 1.0 + * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, + * in which case the RCSL will apply. You may also obtain the license terms + * directly from RealNetworks. You may not use this file except in + * compliance with the RPSL or, if you have a valid RCSL with RealNetworks + * applicable to this file, the RCSL. Please see the applicable RPSL or + * RCSL for the rights, obligations and limitations governing use of the + * contents of the file. + * + * This file is part of the Helix DNA Technology. RealNetworks is the + * developer of the Original Code and owns the copyrights in the portions + * it created. + * + * This file, and the files included with this file, is distributed and made + * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * + * Technology Compatibility Kit Test Suite(s) Location: + * http://www.helixcommunity.org/content/tck + * + * Contributor(s): + * + * ***** END LICENSE BLOCK ***** */ + +/************************************************************************************** + * Fixed-point MP3 decoder + * Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com) + * June 2003 + * + * mp3dec.c - platform-independent top level MP3 decoder API + **************************************************************************************/ +#include "include.h" // J.Sz. 21/04/2006 +#include "string.h" // J.Sz. 21/04/2006 +#include "mp3common.h" /* includes mp3dec.h (public API) and internal, platform-independent API */ +#include "layer21.h" +#include "uart_pub.h" + +#if (CONFIG_APP_MP3PLAYER == 1) +#define MP3HEADERMASK 0x0F0CFFFF + +int16 MP3FixDiv(int32 num,int32 denum) +{ + int16 div = 0; + if(denum <= 0) + return 0; + if(num < denum) + return 0; + while(num >= denum) + { + num -= denum; + div++; + } + return div; + +} +/************************************************************************************** + * Function: MP3InitDecoder + * + * Description: allocate memory for platform-specific data + * clear all the user-accessible fields + * + * Inputs: none + * + * Outputs: none + * + * Return: handle to mp3 decoder instance, 0 if malloc fails + **************************************************************************************/ +HMP3Decoder MP3InitDecoder(void) +{ + MP3DecInfo *mp3DecInfo; + + mp3DecInfo = AllocateBuffers(); + return (HMP3Decoder)mp3DecInfo; +} + +/************************************************************************************** + * Function: MP3FreeDecoder + * + * Description: free platform-specific data allocated by InitMP3Decoder + * zero out the contents of MP3DecInfo struct + * + * Inputs: valid MP3 decoder instance pointer (HMP3Decoder) + * + * Outputs: none + * + * Return: none + **************************************************************************************/ +void MP3FreeDecoder(HMP3Decoder hMP3Decoder) +{ + MP3DecInfo *mp3DecInfo = (MP3DecInfo *)hMP3Decoder; + + if (!mp3DecInfo) + return; + + FreeBuffers(mp3DecInfo); +} + +/************************************************************************************** + * Function: MP3FindSyncWord + * + * Description: locate the next byte-alinged sync word in the raw mp3 stream + * + * Inputs: buffer to search for sync word + * max number of bytes to search in buffer + * + * Outputs: none + * + * Return: offset to first sync word (bytes from start of buf) + * -1 if sync not found after searching nBytes + * SYNCWORD_NOT_SURE means that this syncword is not sure, because + * there are no enough data in the buffer + **************************************************************************************/ +int MP3FindSyncWord(HMP3Decoder hMP3Decoder,unsigned char *buf, int nBytes) +{ + int i; + int frsz; + uint32_t header0,header1; + MP3DecInfo *mp3DecInfo = (MP3DecInfo *)hMP3Decoder; + /* find byte-aligned syncword - need 12 (MPEG 1,2) or 11 (MPEG 2.5) matching bits */ + for (i = 0; i < nBytes - 5; i++) { + if ( (buf[i+0] & SYNCWORDH) == SYNCWORDH && (buf[i+1] & SYNCWORDL) == SYNCWORDL ) + { + + frsz = UnpackFrameHeader(mp3DecInfo,buf+i); + if(frsz < 0) + { + //os_printf("MP3 Header Err...0\r\n"); + continue; + } + frsz = mp3DecInfo->framesize; + if(frsz == 0) + { + os_printf("MP3 Header Err...1\r\n"); + continue; + } + if((frsz + i) > (nBytes-5)) + { + /* this syncword is not sure, because there are no enough data + in the buffer */ + return SYNCWORD_NOT_SURE | i; + } + memcpy(&header0,buf+i,4); + memcpy(&header1,buf+i+frsz,4); + //os_printf("head01:%x,%x,i = %d, frsz = %d,nBytes = %d\r\n",header0,header1,i,frsz,nBytes); + if((header0 & MP3HEADERMASK) == (header1 & MP3HEADERMASK)) + { + return i; + } + else + { + //os_printf("MP3 Header Err...2\r\n"); + continue; + } + } + + } + return -1; +} + +int MP3FindSyncWord_Free(unsigned char *buf, int nBytes) +{ + int i; + /* find byte-aligned syncword - need 12 (MPEG 1,2) or 11 (MPEG 2.5) matching bits */ + for (i = 0; i < nBytes - 1; i++) { + if ( (buf[i+0] & SYNCWORDH) == SYNCWORDH && (buf[i+1] & SYNCWORDL) == SYNCWORDL ) + { + return i; + } + + } + + return -1; +} + +/************************************************************************************** + * Function: MP3FindFreeSync + * + * Description: figure out number of bytes between adjacent sync words in "free" mode + * + * Inputs: buffer to search for next sync word + * the 4-byte frame header starting at the current sync word + * max number of bytes to search in buffer + * + * Outputs: none + * + * Return: offset to next sync word, minus any pad byte (i.e. nSlots) + * -1 if sync not found after searching nBytes + * + * Notes: this checks that the first 22 bits of the next frame header are the + * same as the current frame header, but it's still not foolproof + * (could accidentally find a sequence in the bitstream which + * appears to match but is not actually the next frame header) + * this could be made more error-resilient by checking several frames + * in a row and verifying that nSlots is the same in each case + * since free mode requires CBR (see spec) we generally only call + * this function once (first frame) then store the result (nSlots) + * and just use it from then on + **************************************************************************************/ +static int MP3FindFreeSync(unsigned char *buf, unsigned char firstFH[4], int nBytes) +{ + int offset = 0; + unsigned char *bufPtr = buf; + /* loop until we either: + * - run out of nBytes (FindMP3SyncWord() returns -1) + * - find the next valid frame header (sync word, version, layer, CRC flag, bitrate, and sample rate + * in next header must match current header) + */ + while (1) { + offset = MP3FindSyncWord_Free(bufPtr, nBytes); + bufPtr += offset; + if (offset < 0) { + return -1; + } else if ( (bufPtr[0] == firstFH[0]) && (bufPtr[1] == firstFH[1]) && ((bufPtr[2] & 0xfc) == (firstFH[2] & 0xfc)) ) { + /* want to return number of bytes per frame, NOT counting the padding byte, so subtract one if padFlag == 1 */ + if ((firstFH[2] >> 1) & 0x01) + bufPtr--; + return bufPtr - buf; + } + bufPtr += 3; + nBytes -= (offset + 3); + }; + + return -1; +} + +/************************************************************************************** + * Function: MP3GetLastFrameInfo + * + * Description: get info about last MP3 frame decoded (number of sampled decoded, + * sample rate, bitrate, etc.) + * + * Inputs: valid MP3 decoder instance pointer (HMP3Decoder) + * pointer to MP3FrameInfo struct + * + * Outputs: filled-in MP3FrameInfo struct + * + * Return: none + * + * Notes: call this right after calling MP3Decode + **************************************************************************************/ +void MP3GetLastFrameInfo(HMP3Decoder hMP3Decoder, MP3FrameInfo *mp3FrameInfo) +{ + MP3DecInfo *mp3DecInfo = (MP3DecInfo *)hMP3Decoder; + + //if (!mp3DecInfo || mp3DecInfo->layer != 3) { + if(!mp3DecInfo) + { + mp3FrameInfo->bitrate = 0; + mp3FrameInfo->nChans = 0; + mp3FrameInfo->samprate = 0; + mp3FrameInfo->bitsPerSample = 0; + mp3FrameInfo->outputSamps = 0; + mp3FrameInfo->layer = 0; + mp3FrameInfo->version = 0; + } else { + mp3FrameInfo->bitrate = mp3DecInfo->bitrate; + mp3FrameInfo->nChans = mp3DecInfo->nChans; + mp3FrameInfo->samprate = mp3DecInfo->samprate; + mp3FrameInfo->bitsPerSample = 16; + mp3FrameInfo->outputSamps = mp3DecInfo->nChans * (int)samplesPerFrameTab[mp3DecInfo->version][mp3DecInfo->layer - 1]; + mp3FrameInfo->layer = mp3DecInfo->layer; + mp3FrameInfo->version = mp3DecInfo->version; + } +} + +/************************************************************************************** + * Function: MP3GetNextFrameInfo + * + * Description: parse MP3 frame header + * + * Inputs: valid MP3 decoder instance pointer (HMP3Decoder) + * pointer to MP3FrameInfo struct + * pointer to buffer containing valid MP3 frame header (located using + * MP3FindSyncWord(), above) + * + * Outputs: filled-in MP3FrameInfo struct + * + * Return: error code, defined in mp3dec.h (0 means no error, < 0 means error) + **************************************************************************************/ +int MP3GetNextFrameInfo(HMP3Decoder hMP3Decoder, MP3FrameInfo *mp3FrameInfo, unsigned char *buf) +{ + MP3DecInfo *mp3DecInfo = (MP3DecInfo *)hMP3Decoder; + + if (!mp3DecInfo) + return ERR_MP3_NULL_POINTER; + + //if (UnpackFrameHeader(mp3DecInfo, buf) == -1 || mp3DecInfo->layer != 3) + if (UnpackFrameHeader(mp3DecInfo, buf) == -1) + return ERR_MP3_INVALID_FRAMEHEADER; + + MP3GetLastFrameInfo(mp3DecInfo, mp3FrameInfo); + + return ERR_MP3_NONE; +} + +/************************************************************************************** + * Function: MP3ClearBadFrame + * + * Description: zero out pcm buffer if error decoding MP3 frame + * + * Inputs: mp3DecInfo struct with correct frame size parameters filled in + * pointer pcm output buffer + * + * Outputs: zeroed out pcm buffer + * + * Return: none + **************************************************************************************/ +static void MP3ClearBadFrame(MP3DecInfo *mp3DecInfo, short *outbuf) +{ +} + + +#include "ff.h" +extern FIL *newFatfs; + +#define BUF_CUTDOWN_DEBUG os_printf + +const char ID3_HEADER[3] = "ID3"; +int MP3_Get_ID3_Offset(unsigned char *buf, int nBytes) +{ + int offset; + /* the head of id3 should be large than 9 byte */ + if(nBytes < 10) + return -1; + /* in the start of the mp3 file, "ID3" stand for the id3 head */ + if ((buf[0]==ID3_HEADER[0]) && (buf[1]==ID3_HEADER[1]) && (buf[2]==ID3_HEADER[2])) + { + /* byte6-9 is size(28bit) of all title, each of them only use the low 7bit */ + offset = ((buf[6]&0x7f)<<21) + ((buf[7]&0x7f)<<14) + ((buf[8]&0x7f)<<7) + (buf[9]&0x7f); + /* offset need add the head of ID3 */ + offset += 10; + + return offset; + } + + return -1; +} + +static int file_read(unsigned char *buf, int size) +{ + unsigned int readbytes=0; + int ret; + if (newFatfs == NULL) + return -1; + + ret = f_read(newFatfs, buf, size, &readbytes); + if( ret != FR_OK ) { + BUF_CUTDOWN_DEBUG("file_read: ret%d\r\n", ret); + return FR_DISK_ERR; + } + ret = f_EOF(newFatfs); + + if( ret == FR_FILE_END) + return FR_FILE_END; + + if(readbytes != size) + return FR_DISK_ERR; + + return FR_OK; +} + +static int file_seek(int pos) +{ + int ret; + if (newFatfs == NULL) + return FR_NO_FILE; + + ret = f_lseek(newFatfs, (uint32)pos); + if(ret != FR_OK) + return ret; + + return(f_EOF(newFatfs)); +} + +/************************************************************************************** + * Function: MP3Decode + * + * Description: decode one frame of MP3 data + * + * Inputs: valid MP3 decoder instance pointer (HMP3Decoder) + * double pointer to buffer of MP3 data (containing headers + mainData) + * number of valid bytes remaining in inbuf + * pointer to outbuf, big enough to hold one frame of decoded PCM samples + * flag indicating whether MP3 data is normal MPEG format (useSize = 0) + * or reformatted as "self-contained" frames (useSize = 1) + * + * Outputs: PCM data in outbuf, interleaved LRLRLR... if stereo + * number of output samples = nGrans * nGranSamps * nChans + * updated inbuf pointer, updated bytesLeft + * + * Return: error code, defined in mp3dec.h (0 means no error, < 0 means error) + * + * Notes: switching useSize on and off between frames in the same stream + * is not supported (bit reservoir is not maintained if useSize on) + **************************************************************************************/ +#define GET_MAINBUF_FREE_LEN(p) ((int)((p->mainBuf+READBUF_SIZE)-(p->mainBuf_ptr+p->mainBuf_len))) +#define GET_MAINBUF_DATA_LEN(p) ((int)(p->mainBuf_len)) + +int MP3FileGetData(MP3DecInfo *mp3DecInfo, unsigned char flag, + unsigned char **inbuf, int *bytesLeft) +{ + + int ret = 0; + unsigned char *buf=NULL; + int readsize = 0; + + buf = mp3DecInfo->mainBuf+BIT_RESVOR_SIZE; + if(!flag) + { + readsize = READBUF_SIZE-BIT_RESVOR_SIZE; // 1940 - 512 = 1428 = 357*4 + BUF_CUTDOWN_DEBUG("full rdsize:%d\r\n", readsize); + ret = file_read(buf, readsize); + BUF_CUTDOWN_DEBUG("full ret:%d\r\n", ret); + if(ret != FR_OK) + return ret; + *bytesLeft = READBUF_SIZE-BIT_RESVOR_SIZE; + } + else + { + uint8 *prt = (uint8 *)mp3DecInfo->HuffmanInfoPS; + + memmove(buf, *inbuf, mp3DecInfo->mainBuf_len); + mp3DecInfo->mainBuf_ptr = mp3DecInfo->mainBuf+BIT_RESVOR_SIZE; + + buf += mp3DecInfo->mainBuf_len; + readsize = GET_MAINBUF_FREE_LEN(mp3DecInfo); + + readsize &= 0xfffffffc; + ret = file_read(prt, readsize); + if(ret != FR_OK) + return ret; + memmove(buf, prt, readsize); + + *bytesLeft += readsize; + } + + mp3DecInfo->mainBuf_ptr = mp3DecInfo->mainBuf+BIT_RESVOR_SIZE; + *inbuf = mp3DecInfo->mainBuf+BIT_RESVOR_SIZE; + + return 0; +} + +#if CALC_PLAY_TIME +const char XING_HDR[4] = "Xing"; +const char VBRI_HDR[4] = "VBRI"; +void MP3_Find_CBR_Header(MP3DecInfo *mp3DecInfo, unsigned char *buf, + int nBytes) +{ + /* the head of id3 should be large than 9 byte */ + if(nBytes < 8) + return; + + if((buf[0]==XING_HDR[0]) && (buf[1]==XING_HDR[1]) + && (buf[2]==XING_HDR[2]) && (buf[3]==XING_HDR[3])) { + unsigned char flags = buf[7]; + os_printf("xing header\r\n"); + os_printf("flag:0x%x-0x%x-0x%x-0x%x\r\n", buf[4], buf[5],buf[6], buf[7]); + mp3DecInfo->filetype = VBR_XING_FILE; + buf += 8; + nBytes -= 8; + + if((flags&0x1)){ + unsigned char *total_frame_ptr = buf; + unsigned int total_frame; + if(nBytes > 4){ + total_frame = (total_frame_ptr[0]<<24) + + (total_frame_ptr[1]<<16) + (total_frame_ptr[2]<<8) + + (total_frame_ptr[3]); + os_printf("total frames:%d\r\n", total_frame); + mp3DecInfo->totalframes = total_frame; + buf += 4; + } else { + return; + } + } + } + else if((buf[0]==VBRI_HDR[0]) && (buf[1]==VBRI_HDR[1]) + && (buf[2]==VBRI_HDR[2]) && (buf[3]==VBRI_HDR[3])) { + unsigned char *total_frame_ptr = buf + 14; + unsigned int total_frame; + os_printf("vbri header\r\n"); + mp3DecInfo->filetype = VBR_VBRI_FILE; + nBytes -= 14; + if(nBytes > 4){ + total_frame = (total_frame_ptr[0]<<24) + + (total_frame_ptr[1]<<16) + (total_frame_ptr[2]<<8) + + (total_frame_ptr[3]); + os_printf("total frames:%d\r\n", total_frame); + mp3DecInfo->totalframes = total_frame; + } else { + return; + } + + } else { + os_printf("no a VBR file, maybe a CBR file\r\n"); + os_printf("totalframes is ready:%d\r\n", mp3DecInfo->totalframes); + // mp3DecInfo->totalframes = fUseLen; + mp3DecInfo->filetype = CBR_FILE; + } +} + +void MP3_Show_Play_Time(int time) +{ + int min, sec; + + min = time / 60; + sec = time % 60; + os_printf("%02d:%02d\r\n", min, sec); +} + +void MP3_Calc_Play_Time(HMP3Decoder hMP3Decoder, MP3FrameInfo *mp3FrameInfo) +{ + int total_playtime; + MP3DecInfo *mp3DecInfo = (MP3DecInfo *)hMP3Decoder; + + int filetype = mp3DecInfo->filetype; + mp3DecInfo->timePerframe = PRECISION * mp3FrameInfo->outputSamps + / (mp3FrameInfo->nChans * mp3FrameInfo->samprate); + os_printf("timePerframe = %d\r\n",mp3DecInfo->timePerframe); + + switch(filetype){ + case CBR_FILE: + total_playtime = mp3DecInfo->totalframes * 8 / mp3DecInfo->bitrate; + os_printf("total time = %d\r\n",total_playtime); + MP3_Show_Play_Time(total_playtime); + break; + + case VBR_VBRI_FILE: + case VBR_XING_FILE:{ + total_playtime = mp3DecInfo->totalframes * mp3DecInfo->timePerframe + / PRECISION; + os_printf("total time = %d\r\n",total_playtime); + MP3_Show_Play_Time(total_playtime); + } + break; + default: + break; + } +} + +int MP3_Calc_Current_Play_Time(HMP3Decoder hMP3Decoder) +{ + int current_playtime; + MP3DecInfo *mp3DecInfo = (MP3DecInfo *)hMP3Decoder; + + current_playtime = mp3DecInfo->curFramecnt * mp3DecInfo->timePerframe + / PRECISION; + + // MP3_Show_Play_Time(current_playtime); + + return current_playtime; +} +#endif +int bitOffset, mainBits, gr; +unsigned char *mainPtr; +int MP3Decode(HMP3Decoder hMP3Decoder, short *outbuf, int *pcm_size) +{ + int offset,ch, fhBytes, siBytes, freeFrameBytes,result; + int prevBitOffset, sfBlockBits, huffBlockBits; + + MP3DecInfo *mp3DecInfo = (MP3DecInfo *)hMP3Decoder; + + unsigned char **inbuf = NULL; + int *bytesLeft = NULL; + + if (!mp3DecInfo) + return ERR_MP3_NULL_POINTER; + + inbuf = &mp3DecInfo->mainBuf_ptr; + bytesLeft = &mp3DecInfo->mainBuf_len; + *pcm_size = 0; + +start_decode: + switch (mp3DecInfo->decode_state) + { + case MP3_DECODE_FIND_ID3_INFO: + { + int offset, off_4_lign; +// if(MP3FileGetData(mp3DecInfo, 0, inbuf, bytesLeft)) +// return ERR_MP3_READ_DATA_FAILED; + + result = MP3FileGetData(mp3DecInfo, 0, inbuf, bytesLeft); + if(result != FR_OK) + { + if(result == ERR_MP3_FILE_END) + return ERR_MP3_FILE_END; + else + return ERR_MP3_READ_DATA_FAILED; + } + + offset = MP3_Get_ID3_Offset(*inbuf, *bytesLeft); + BUF_CUTDOWN_DEBUG("ID3: offset:%d\r\n", offset); + + if(offset<=0) + { + os_printf("can't found ID3 info\r\n"); + mp3DecInfo->decode_state = MP3_DECODE_FIND_SYNC_WORD; + goto start_decode; + } + #if CALC_PLAY_TIME + mp3DecInfo->totalframes -= offset; + os_printf("change totalframes len:%d, offset:%d\r\n", mp3DecInfo->totalframes + , offset); + #endif + + off_4_lign = offset & 0xfffffffc; // bk3253 file_seek must 4btye laign + BUF_CUTDOWN_DEBUG("off_4_lign0:%d\r\n", off_4_lign); + result = file_seek(off_4_lign); + + if(result != FR_OK) + { + if(result != ERR_MP3_FILE_END) + return ERR_MP3_READ_DATA_FAILED; + else + return ERR_MP3_FILE_END; + } + + *bytesLeft = 0; //give up all the date that ready read. + +// if(MP3FileGetData(mp3DecInfo, 0, inbuf, bytesLeft)) +// return ERR_MP3_READ_DATA_FAILED; + result = MP3FileGetData(mp3DecInfo, 0, inbuf, bytesLeft); + if(result != FR_OK) + { + if(result == ERR_MP3_FILE_END) + return ERR_MP3_FILE_END; + else + return ERR_MP3_READ_DATA_FAILED; + } + + off_4_lign = offset & 0x3; + BUF_CUTDOWN_DEBUG("off_4_lign1:%d\r\n", off_4_lign); + if(off_4_lign) + memset(*inbuf, 0, off_4_lign); // clear the unuse data + + mp3DecInfo->decode_state = MP3_DECODE_FIND_SYNC_WORD; + //break; + } + + case MP3_DECODE_FIND_SYNC_WORD: + { + int ofst = MP3FindSyncWord((HMP3Decoder)mp3DecInfo,*inbuf, *bytesLeft); + if(ofst<0) + { +// if(MP3FileGetData(mp3DecInfo, 0, inbuf, bytesLeft)) +// return ERR_MP3_READ_DATA_FAILED; + result = MP3FileGetData(mp3DecInfo, 0, inbuf, bytesLeft); + if(result != FR_OK) + { + if(result == ERR_MP3_FILE_END) + return ERR_MP3_FILE_END; + else + return ERR_MP3_READ_DATA_FAILED; + } + + /* if err counter exceeds the MAX_DECODE_ERR_TIMES, we should exit the whole decode process */ + mp3DecInfo->err_cnt++; + if(mp3DecInfo->err_cnt > MAX_DECODE_ERR_TIMES) + return ERR_MP3_DECODE_MAX_ERR; + goto start_decode; + } + + offset = ofst & (~SYNCWORD_NOT_SURE); // get the offset + ofst = (ofst & SYNCWORD_NOT_SURE)?1:0; // syncword is not sure? + + *inbuf += offset; + *bytesLeft -= offset; + + result = MP3FileGetData(mp3DecInfo, 1, inbuf, bytesLeft); + if(result != FR_OK) + { + if(result == ERR_MP3_FILE_END) + return ERR_MP3_FILE_END; + else + return ERR_MP3_READ_DATA_FAILED; + } + + if(ofst) // syncword is not sure + { + /* we isn't sure that the sync word is right or not, at this time, + we have filled our buffer, if we have enough data in buffer,so + call MP3FindSyncWord again. buf if the whole buffer len is less + than one frame, let decode to slove this problem */ + if(GET_MAINBUF_DATA_LEN(mp3DecInfo) >= mp3DecInfo->framesize + 5) + goto start_decode; + } + mp3DecInfo->decode_state = MP3_DECODE_HEADER_SIDEINFO; + //break; + } + + case MP3_DECODE_HEADER_SIDEINFO: + { + /* unpack frame header */ + fhBytes = UnpackFrameHeader(mp3DecInfo, *inbuf); + if (fhBytes < 0) + { + os_printf("I am sure this not a mp3 file\r\n"); + /* don't clear outbuf since we don't know size (failed to parse header) */ + return ERR_MP3_INVALID_FRAMEHEADER; + } + + if(mp3DecInfo->layer != 3) + { + int32_t nL2FrmSize; + int32_t header; + memcpy(&header,*inbuf,4); + nL2FrmSize = L2_GetFrameSize(mp3DecInfo->L2DecInfo,header); + if(GET_MAINBUF_DATA_LEN(mp3DecInfo) < nL2FrmSize) + { +// if(MP3FileGetData(mp3DecInfo, 1, inbuf, bytesLeft)) +// return ERR_MP3_READ_DATA_FAILED; + result = MP3FileGetData(mp3DecInfo, 1, inbuf, bytesLeft); + if(result != FR_OK) + { + if(result == ERR_MP3_FILE_END) + return ERR_MP3_FILE_END; + else + return ERR_MP3_READ_DATA_FAILED; + } + } + #if CALC_PLAY_TIME + if(!mp3DecInfo->filetype) { + MP3_Find_CBR_Header(mp3DecInfo, *inbuf, *bytesLeft); + } + mp3DecInfo->curFramecnt++; + #endif + *pcm_size = L2_decode_frame(mp3DecInfo->L2DecInfo,outbuf,&ch,*inbuf,nL2FrmSize); + //return ch; + *inbuf += nL2FrmSize; + *bytesLeft -= nL2FrmSize; + mp3DecInfo->decode_state = MP3_DECODE_FIND_SYNC_WORD; + return ERR_MP3_NONE; + } + + *inbuf += fhBytes; + + /* unpack side info */ + siBytes = UnpackSideInfo(mp3DecInfo, *inbuf); + if (siBytes < 0) + { + MP3ClearBadFrame(mp3DecInfo, outbuf); + return ERR_MP3_INVALID_SIDEINFO; + } + *inbuf += siBytes; + *bytesLeft -= (fhBytes + siBytes); + #if CALC_PLAY_TIME + if(!mp3DecInfo->filetype) { + MP3_Find_CBR_Header(mp3DecInfo, *inbuf, *bytesLeft); + } + mp3DecInfo->curFramecnt++; + #endif + + /* if free mode, need to calculate bitrate and nSlots manually, based on frame size */ + if (mp3DecInfo->bitrate == 0 || mp3DecInfo->freeBitrateFlag) { + if (!mp3DecInfo->freeBitrateFlag) { + /* first time through, need to scan for next sync word and figure out frame size */ + mp3DecInfo->freeBitrateFlag = 1; + mp3DecInfo->freeBitrateSlots = MP3FindFreeSync(*inbuf, *inbuf - fhBytes - siBytes, *bytesLeft); + if (mp3DecInfo->freeBitrateSlots < 0) { + MP3ClearBadFrame(mp3DecInfo, outbuf); + return ERR_MP3_FREE_BITRATE_SYNC; + } + freeFrameBytes = mp3DecInfo->freeBitrateSlots + fhBytes + siBytes; + mp3DecInfo->bitrate = (freeFrameBytes * mp3DecInfo->samprate * 8) / (mp3DecInfo->nGrans * mp3DecInfo->nGranSamps); + } + mp3DecInfo->nSlots = mp3DecInfo->freeBitrateSlots + CheckPadBit(mp3DecInfo); /* add pad byte, if required */ + } + + mp3DecInfo->decode_state = MP3_DECODE_COPY_MAIN_DATE; + //break; + } + + case MP3_DECODE_COPY_MAIN_DATE: + { + { + /* out of data - assume last or truncated frame */ + if (mp3DecInfo->nSlots > *bytesLeft) + { + MP3ClearBadFrame(mp3DecInfo, outbuf); + return ERR_MP3_INDATA_UNDERFLOW; + } + + /* fill main data buffer with enough new data for this frame */ + if (mp3DecInfo->mainDataBytes >= mp3DecInfo->mainDataBegin) { + + unsigned char *p_des, *p_src; + unsigned int len; + p_des = mp3DecInfo->mainBuf+BIT_RESVOR_SIZE-mp3DecInfo->mainDataBegin; + p_src = mp3DecInfo->bit_reservoir + BIT_RESVOR_SIZE - mp3DecInfo->mainDataBegin; + len = mp3DecInfo->mainDataBegin; + memmove(p_des, p_src, len); + + p_des = mp3DecInfo->mainBuf+BIT_RESVOR_SIZE; + p_src = *inbuf; + len = *bytesLeft; + memmove(p_des, p_src, len); + *inbuf = p_des; + + mp3DecInfo->mainDataBytes = mp3DecInfo->mainDataBegin + mp3DecInfo->nSlots; + *inbuf += mp3DecInfo->nSlots; + *bytesLeft -= (mp3DecInfo->nSlots); + mainPtr = mp3DecInfo->mainBuf+BIT_RESVOR_SIZE-mp3DecInfo->mainDataBegin; + + p_des = mp3DecInfo->bit_reservoir; + p_src = *inbuf - BIT_RESVOR_SIZE; + len = BIT_RESVOR_SIZE; + memcpy(p_des, p_src, len); + + } else { + /* not enough data in bit reservoir from previous frames (perhaps starting in middle of file) */ + unsigned char *p_des, *p_src; + unsigned int len; + + p_des = mp3DecInfo->mainBuf+BIT_RESVOR_SIZE; + p_src = *inbuf; + len = *bytesLeft; + memmove(p_des, p_src, len); + *inbuf = p_des; + + mp3DecInfo->mainDataBytes += mp3DecInfo->nSlots; + *inbuf += mp3DecInfo->nSlots; + *bytesLeft -= (mp3DecInfo->nSlots); + + MP3ClearBadFrame(mp3DecInfo, outbuf); + return ERR_MP3_MAINDATA_UNDERFLOW; + } + } + + bitOffset = 0; + mainBits = mp3DecInfo->mainDataBytes * 8; + + mp3DecInfo->decode_state = MP3_DECODE_CALU_CRUCIAL_DAT; + gr = 0; + + //break; + } + + case MP3_DECODE_CALU_CRUCIAL_DAT: + { + if(gr < mp3DecInfo->nGrans) + { + for (ch = 0; ch < mp3DecInfo->nChans; ch++) + { + /* unpack scale factors and compute size of scale factor block */ + prevBitOffset = bitOffset; + offset = UnpackScaleFactors(mp3DecInfo, mainPtr, &bitOffset, mainBits, gr, ch); + + sfBlockBits = 8*offset - prevBitOffset + bitOffset; + huffBlockBits = mp3DecInfo->part23Length[gr][ch] - sfBlockBits; + mainPtr += offset; + mainBits -= sfBlockBits; + + if (offset < 0 || mainBits < huffBlockBits) + { + MP3ClearBadFrame(mp3DecInfo, outbuf); + return ERR_MP3_INVALID_SCALEFACT; + } + + /* decode Huffman code words */ + prevBitOffset = bitOffset; + offset = DecodeHuffman(mp3DecInfo, mainPtr, &bitOffset, huffBlockBits, gr, ch); + if (offset < 0) + { + MP3ClearBadFrame(mp3DecInfo, outbuf); + return ERR_MP3_INVALID_HUFFCODES; + } + + mainPtr += offset; + mainBits -= (8*offset - prevBitOffset + bitOffset); + } + /* dequantize coefficients, decode stereo, reorder short blocks */ + if (Dequantize(mp3DecInfo, gr) < 0) { + MP3ClearBadFrame(mp3DecInfo, outbuf); + return ERR_MP3_INVALID_DEQUANTIZE; + } + + /* alias reduction, inverse MDCT, overlap-add, frequency inversion */ + for (ch = 0; ch < mp3DecInfo->nChans; ch++) + if (IMDCT(mp3DecInfo, gr, ch) < 0) + { + MP3ClearBadFrame(mp3DecInfo, outbuf); + return ERR_MP3_INVALID_IMDCT; + } + } + gr++; + + mp3DecInfo->decode_state = MP3_DECODE_CALU_SUBBAND; + } + + case MP3_DECODE_CALU_SUBBAND: + { + short *outbuf_ptr = outbuf; + if (Subband(mp3DecInfo, &outbuf) < 0) + { + MP3ClearBadFrame(mp3DecInfo, outbuf); + return ERR_MP3_INVALID_SUBBAND; + } + + *pcm_size = outbuf - outbuf_ptr; + + if(gr < mp3DecInfo->nGrans) + { + mp3DecInfo->decode_state = MP3_DECODE_CALU_CRUCIAL_DAT; + } + else + { + mainPtr = mp3DecInfo->mainBuf_ptr; + mp3DecInfo->decode_state = MP3_DECODE_FIND_SYNC_WORD; + } + break; + } + + default: + return ERR_UNKNOWN; + break; + } + + return ERR_MP3_NONE; +} +#endif /* CONFIG_APP_MP3PLAYER */ + diff --git a/beken_os/beken378/func/music_player/Mp3Lib/mp3dec.h b/beken_os/beken378/func/music_player/Mp3Lib/mp3dec.h new file mode 100755 index 0000000..7eb496d --- /dev/null +++ b/beken_os/beken378/func/music_player/Mp3Lib/mp3dec.h @@ -0,0 +1,172 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: RCSL 1.0/RPSL 1.0 + * + * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. + * + * The contents of this file, and the files included with this file, are + * subject to the current version of the RealNetworks Public Source License + * Version 1.0 (the "RPSL") available at + * http://www.helixcommunity.org/content/rpsl unless you have licensed + * the file under the RealNetworks Community Source License Version 1.0 + * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, + * in which case the RCSL will apply. You may also obtain the license terms + * directly from RealNetworks. You may not use this file except in + * compliance with the RPSL or, if you have a valid RCSL with RealNetworks + * applicable to this file, the RCSL. Please see the applicable RPSL or + * RCSL for the rights, obligations and limitations governing use of the + * contents of the file. + * + * This file is part of the Helix DNA Technology. RealNetworks is the + * developer of the Original Code and owns the copyrights in the portions + * it created. + * + * This file, and the files included with this file, is distributed and made + * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * + * Technology Compatibility Kit Test Suite(s) Location: + * http://www.helixcommunity.org/content/tck + * + * Contributor(s): + * + * ***** END LICENSE BLOCK ***** */ + +/************************************************************************************** + * Fixed-point MP3 decoder + * Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com) + * June 2003 + * + * mp3dec.h - public C API for MP3 decoder + **************************************************************************************/ +#ifndef _MP3DEC_H +#define _MP3DEC_H + +#include "include.h" + +#if (CONFIG_APP_MP3PLAYER == 1) +#define ARM + +#if defined(_WIN32) && !defined(_WIN32_WCE) +# +#elif defined(_WIN32) && defined(_WIN32_WCE) && defined(ARM) +# +#elif defined(_WIN32) && defined(WINCE_EMULATOR) +# +#elif defined(ARM_ADS) +# +#elif defined(_SYMBIAN) && defined(__WINS__) /* Symbian emulator for Ix86 */ +# +#elif defined(__GNUC__) && defined(ARM) +# +#elif defined(__GNUC__) && defined(__i386__) +# +#elif defined(_OPENWAVE_SIMULATOR) || defined(_OPENWAVE_ARMULATOR) +# +#else +#error No platform defined. See valid options in mp3dec.h +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* determining MAINBUF_SIZE: + * max mainDataBegin = (2^9 - 1) bytes (since 9-bit offset) = 511 + * max nSlots (concatenated with mainDataBegin bytes from before) = 1440 - 9 - 4 + 1 = 1428 + * 511 + 1428 = 1939, round up to 1940 (4-byte align) + */ +#define MAINBUF_SIZE 1940 + +#define BIT_RESVOR_SIZE (512) +#define READBUF_SIZE (1940) +#define MAX_DECODE_ERR_TIMES 2000 + +#define MAX_NGRAN 2 /* max granules */ +#define MAX_NCHAN 2 /* max channels */ +#define MAX_NSAMP 576 /* max samples per channel, per granule */ + +/* map to 0,1,2 to make table indexing easier */ +typedef enum { + MPEG1 = 0, + MPEG2 = 1, + MPEG25 = 2 +} MPEGVersion; + +#if CALC_PLAY_TIME +enum { + TPYE_NONE = 0, + CBR_FILE, + VBR_XING_FILE, + VBR_VBRI_FILE +} FILETPYE; +#define PRECISION 10000 +#endif +typedef void *HMP3Decoder; + +enum { + ERR_MP3_NONE = 0, + ERR_MP3_INDATA_UNDERFLOW = 1, + ERR_MP3_MAINDATA_UNDERFLOW = 2, + ERR_MP3_FREE_BITRATE_SYNC = 3, // + ERR_MP3_OUT_OF_MEMORY = 4, // + ERR_MP3_NULL_POINTER = 5, // + ERR_MP3_INVALID_FRAMEHEADER = 6, // + ERR_MP3_INVALID_SIDEINFO = 7, // + ERR_MP3_INVALID_SCALEFACT = 8, // + ERR_MP3_INVALID_HUFFCODES = 9, // + ERR_MP3_INVALID_DEQUANTIZE = 10, // + ERR_MP3_INVALID_IMDCT = 11, // + ERR_MP3_INVALID_SUBBAND = 12, // + ERR_MP3_READ_DATA_FAILED = 13, + ERR_MP3_DECODE_MAX_ERR = 14, + ERR_MP3_FILE_END = 20, + ERR_UNKNOWN = -9999 +}; + +enum { + MP3_DECODE_NONE = 0, + MP3_DECODE_FIND_ID3_INFO = 1, + MP3_DECODE_FIND_SYNC_WORD = 2, + MP3_DECODE_HEADER_SIDEINFO = 3, + MP3_DECODE_COPY_MAIN_DATE = 4, + + + MP3_DECODE_CALU_CRUCIAL_DAT = 5, + MP3_DECODE_CALU_SUBBAND = 6, + MP3_DECODE_WAITING_FOR_BUFF = 7, + + + MP3_DECODE_UNKNOW = 9999 +}; + +typedef struct _MP3FrameInfo { + int bitrate; + int nChans; + int samprate; + int bitsPerSample; + int outputSamps; + int layer; + int version; +} MP3FrameInfo; + +/* public API */ +HMP3Decoder MP3InitDecoder(void); +void MP3FreeDecoder(HMP3Decoder hMP3Decoder); +int MP3Decode(HMP3Decoder hMP3Decoder, short *outbuf, int *pcm_size); +void MP3GetLastFrameInfo(HMP3Decoder hMP3Decoder, MP3FrameInfo *mp3FrameInfo); +int MP3GetNextFrameInfo(HMP3Decoder hMP3Decoder, MP3FrameInfo *mp3FrameInfo, unsigned char *buf); +int MP3FindSyncWord(HMP3Decoder hMP3Decoder,unsigned char *buf, int nBytes); + +#if CALC_PLAY_TIME +void MP3_Restore_Useful_data_len(int len); +void MP3_Calc_Play_Time(HMP3Decoder hMP3Decoder, MP3FrameInfo *mp3FrameInfo); +int MP3_Calc_Current_Play_Time(HMP3Decoder hMP3Decoder); +void MP3_Show_Play_Time(int time); +#endif +#ifdef __cplusplus +} +#endif +#endif /* CONFIG_APP_MP3PLAYER */ +#endif /* _MP3DEC_H */ diff --git a/beken_os/beken378/func/music_player/Mp3Lib/mp3tabs.c b/beken_os/beken378/func/music_player/Mp3Lib/mp3tabs.c new file mode 100755 index 0000000..1ac66a7 --- /dev/null +++ b/beken_os/beken378/func/music_player/Mp3Lib/mp3tabs.c @@ -0,0 +1,181 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: RCSL 1.0/RPSL 1.0 + * + * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. + * + * The contents of this file, and the files included with this file, are + * subject to the current version of the RealNetworks Public Source License + * Version 1.0 (the "RPSL") available at + * http://www.helixcommunity.org/content/rpsl unless you have licensed + * the file under the RealNetworks Community Source License Version 1.0 + * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, + * in which case the RCSL will apply. You may also obtain the license terms + * directly from RealNetworks. You may not use this file except in + * compliance with the RPSL or, if you have a valid RCSL with RealNetworks + * applicable to this file, the RCSL. Please see the applicable RPSL or + * RCSL for the rights, obligations and limitations governing use of the + * contents of the file. + * + * This file is part of the Helix DNA Technology. RealNetworks is the + * developer of the Original Code and owns the copyrights in the portions + * it created. + * + * This file, and the files included with this file, is distributed and made + * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * + * Technology Compatibility Kit Test Suite(s) Location: + * http://www.helixcommunity.org/content/tck + * + * Contributor(s): + * + * ***** END LICENSE BLOCK ***** */ + +/************************************************************************************** + * Fixed-point MP3 decoder + * Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com) + * June 2003 + * + * mp3tabs.c - platform-independent tables for MP3 decoder (global, read-only) + **************************************************************************************/ + +#include "mp3common.h" +#if (CONFIG_APP_MP3PLAYER == 1) +/* indexing = [version][samplerate index] + * sample rate of frame (Hz) + */ +const int samplerateTab[3][3] = { + {44100, 48000, 32000}, /* MPEG-1 */ + {22050, 24000, 16000}, /* MPEG-2 */ + {11025, 12000, 8000}, /* MPEG-2.5 */ +}; + +/* indexing = [version][layer][bitrate index] + * bitrate (kbps) of frame + * - bitrate index == 0 is "free" mode (bitrate determined on the fly by + * counting bits between successive sync words) + */ +const short bitrateTab[3][3][15] = { + { + /* MPEG-1 */ + { 0, 32, 64, 96,128,160,192,224,256,288,320,352,384,416,448}, /* Layer 1 */ + { 0, 32, 48, 56, 64, 80, 96,112,128,160,192,224,256,320,384}, /* Layer 2 */ + { 0, 32, 40, 48, 56, 64, 80, 96,112,128,160,192,224,256,320}, /* Layer 3 */ + }, + { + /* MPEG-2 */ + { 0, 32, 48, 56, 64, 80, 96,112,128,144,160,176,192,224,256}, /* Layer 1 */ + { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160}, /* Layer 2 */ + { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160}, /* Layer 3 */ + }, + { + /* MPEG-2.5 */ + { 0, 32, 48, 56, 64, 80, 96,112,128,144,160,176,192,224,256}, /* Layer 1 */ + { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160}, /* Layer 2 */ + { 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160}, /* Layer 3 */ + }, +}; + +/* indexing = [version][layer] + * number of samples in one frame (per channel) + */ +const short samplesPerFrameTab[3][3] = { + {384, 1152, 1152 }, /* MPEG1 */ + {384, 1152, 576 }, /* MPEG2 */ + {384, 1152, 576 }, /* MPEG2.5 */ +}; + +/* layers 1, 2, 3 */ +const short bitsPerSlotTab[3] = {32, 8, 8}; + +/* indexing = [version][mono/stereo] + * number of bytes in side info section of bitstream + */ +const short sideBytesTab[3][2] = { + {17, 32}, /* MPEG-1: mono, stereo */ + { 9, 17}, /* MPEG-2: mono, stereo */ + { 9, 17}, /* MPEG-2.5: mono, stereo */ +}; + +/* indexing = [version][sampleRate][bitRate] + * for layer3, nSlots = floor(samps/frame * bitRate / sampleRate / 8) + * - add one pad slot if necessary + */ +const short slotTab[3][3][15] = { + { + /* MPEG-1 */ + { 0, 104, 130, 156, 182, 208, 261, 313, 365, 417, 522, 626, 731, 835,1044 }, /* 44 kHz */ + { 0, 96, 120, 144, 168, 192, 240, 288, 336, 384, 480, 576, 672, 768, 960 }, /* 48 kHz */ + { 0, 144, 180, 216, 252, 288, 360, 432, 504, 576, 720, 864,1008,1152,1440 }, /* 32 kHz */ + }, + { + /* MPEG-2 */ + { 0, 26, 52, 78, 104, 130, 156, 182, 208, 261, 313, 365, 417, 470, 522 }, /* 22 kHz */ + { 0, 24, 48, 72, 96, 120, 144, 168, 192, 240, 288, 336, 384, 432, 480 }, /* 24 kHz */ + { 0, 36, 72, 108, 144, 180, 216, 252, 288, 360, 432, 504, 576, 648, 720 }, /* 16 kHz */ + }, + { + /* MPEG-2.5 */ + { 0, 52, 104, 156, 208, 261, 313, 365, 417, 522, 626, 731, 835, 940,1044 }, /* 11 kHz */ + { 0, 48, 96, 144, 192, 240, 288, 336, 384, 480, 576, 672, 768, 864, 960 }, /* 12 kHz */ + { 0, 72, 144, 216, 288, 360, 432, 504, 576, 720, 864,1008,1152,1296,1440 }, /* 8 kHz */ + }, +}; + +/* indexing = [version][sampleRate][long (.l) or short (.s) block] + * sfBandTable[v][s].l[cb] = index of first bin in critical band cb (long blocks) + * sfBandTable[v][s].s[cb] = index of first bin in critical band cb (short blocks) + */ +const SFBandTable sfBandTable[3][3] = { + { + /* MPEG-1 (44, 48, 32 kHz) */ + { + { 0, 4, 8, 12, 16, 20, 24, 30, 36, 44, 52, 62, 74, 90,110,134,162,196,238,288,342,418,576 }, + { 0, 4, 8, 12, 16, 22, 30, 40, 52, 66, 84,106,136,192 } + }, + { + { 0, 4, 8, 12, 16, 20, 24, 30, 36, 42, 50, 60, 72, 88,106,128,156,190,230,276,330,384,576 }, + { 0, 4, 8, 12, 16, 22, 28, 38, 50, 64, 80,100,126,192 } + }, + { + { 0, 4, 8, 12, 16, 20, 24, 30, 36, 44, 54, 66, 82,102,126,156,194,240,296,364,448,550,576 }, + { 0, 4, 8, 12, 16, 22, 30, 42, 58, 78,104,138,180,192 } + } + }, + + { + /* MPEG-2 (22, 24, 16 kHz) */ + { + { 0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96,116,140,168,200,238,284,336,396,464,522,576 }, + { 0, 4, 8, 12, 18, 24, 32, 42, 56, 74,100,132,174,192 } + }, + { + { 0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96,114,136,162,194,232,278,332,394,464,540,576 }, + { 0, 4, 8, 12, 18, 26, 36, 48, 62, 80,104,136,180,192 } + }, + { + { 0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96,116,140,168,200,238,284,336,396,464,522,576 }, + { 0, 4, 8, 12, 18, 26, 36, 48, 62, 80,104,134,174,192 } + }, + }, + + { + /* MPEG-2.5 (11, 12, 8 kHz) */ + { + { 0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96,116,140,168,200,238,284,336,396,464,522,576 }, + { 0, 4, 8, 12, 18, 26, 36, 48, 62, 80,104,134,174,192 } + }, + { + { 0, 6, 12, 18, 24, 30, 36, 44, 54, 66, 80, 96,116,140,168,200,238,284,336,396,464,522,576 }, + { 0, 4, 8, 12, 18, 26, 36, 48, 62, 80,104,134,174,192 } + }, + { + { 0, 12, 24, 36, 48, 60, 72, 88,108,132,160,192,232,280,336,400,476,566,568,570,572,574,576 }, + { 0, 8, 16, 24, 36, 52, 72, 96,124,160,162,164,166,192 } + }, + }, +}; +#endif /* CONFIG_APP_MP3PLAYER */ + diff --git a/beken_os/beken378/func/music_player/Mp3Lib/mpadecobjfixpt.h b/beken_os/beken378/func/music_player/Mp3Lib/mpadecobjfixpt.h new file mode 100755 index 0000000..e459952 --- /dev/null +++ b/beken_os/beken378/func/music_player/Mp3Lib/mpadecobjfixpt.h @@ -0,0 +1,108 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: RCSL 1.0/RPSL 1.0 + * + * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. + * + * The contents of this file, and the files included with this file, are + * subject to the current version of the RealNetworks Public Source License + * Version 1.0 (the "RPSL") available at + * http://www.helixcommunity.org/content/rpsl unless you have licensed + * the file under the RealNetworks Community Source License Version 1.0 + * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, + * in which case the RCSL will apply. You may also obtain the license terms + * directly from RealNetworks. You may not use this file except in + * compliance with the RPSL or, if you have a valid RCSL with RealNetworks + * applicable to this file, the RCSL. Please see the applicable RPSL or + * RCSL for the rights, obligations and limitations governing use of the + * contents of the file. + * + * This file is part of the Helix DNA Technology. RealNetworks is the + * developer of the Original Code and owns the copyrights in the portions + * it created. + * + * This file, and the files included with this file, is distributed and made + * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * + * Technology Compatibility Kit Test Suite(s) Location: + * http://www.helixcommunity.org/content/tck + * + * Contributor(s): + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef _MPADECOBJFIXPT_H_ +#define _MPADECOBJFIXPT_H_ + +#include "mp3dec.h" /* public C API for new MP3 decoder */ +#if (CONFIG_APP_MP3PLAYER == 1) +class CMpaDecObj +{ +public: + CMpaDecObj(); + ~CMpaDecObj(); + + /////////////////////////////////////////////////////////////////////////// + // Function: Init_n + // Purpose: Initialize the mp3 decoder. + // Parameters: pSync a pointer to a syncword + // ulSize the size of the buffer pSync points to + // bUseSize this tells the decoder to use the input frame + // size on the decode instead of calculating + // the frame size. This is necessary when + // our formatted mp3 data (main_data_begin always + // equal to 0). + // + // Returns: returns 1 on success, 0 on failure + /////////////////////////////////////////////////////////////////////////// + int Init_n(unsigned char *pSync, + unsigned long ulSize, + unsigned char bUseSize=0); + + /////////////////////////////////////////////////////////////////////////// + // Function: DecodeFrame_v + // Purpose: Decodes one mp3 frame + // Parameters: pSource pointer to an mp3 frame (at a syncword) + // pulSize size of the buffer pSource points to. It will + // contain the number of mp3 bytes decoded upon + // return. + // pPCM pointer to a buffer to decode into + // pulPCMSize size of the PCM buffer. It will contain the + // number of PCM bytes prodced upon return. + /////////////////////////////////////////////////////////////////////////// + void DecodeFrame_v(unsigned char *pSource, + unsigned long *pulSize, + unsigned char *pPCM, + unsigned long *pulPCMSize); + + // overloaded new version that returns error code in errCode + void DecodeFrame_v(unsigned char *pSource, + unsigned long *pulSize, + unsigned char *pPCM, + unsigned long *pulPCMSize, + int *errCode); + + void GetPCMInfo_v(unsigned long &ulSampRate, + int &nChannels, + int &nBitsPerSample); + + // return number of samples per frame, PER CHANNEL (renderer multiplies this result by nChannels) + int GetSamplesPerFrame_n(); + + void SetTrustPackets(unsigned char bTrust) { m_bTrustPackets = bTrust; } + +private: + void * m_pDec; // generic void ptr + + void * m_pDecL1; // not implemented (could use old Xing mpadecl1.cpp) + void * m_pDecL2; // not implemented (could use old Xing mpadecl2.cpp) + HMP3Decoder m_pDecL3; + + MP3FrameInfo m_lastMP3FrameInfo; + unsigned char m_bUseFrameSize; + unsigned char m_bTrustPackets; +}; +#endif /* CONFIG_APP_MP3PLAYER */ +#endif /* _MPADECOBJFIXPT_H_ */ diff --git a/beken_os/beken378/func/music_player/Mp3Lib/scalfact.c b/beken_os/beken378/func/music_player/Mp3Lib/scalfact.c new file mode 100755 index 0000000..43d2023 --- /dev/null +++ b/beken_os/beken378/func/music_player/Mp3Lib/scalfact.c @@ -0,0 +1,392 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: RCSL 1.0/RPSL 1.0 + * + * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. + * + * The contents of this file, and the files included with this file, are + * subject to the current version of the RealNetworks Public Source License + * Version 1.0 (the "RPSL") available at + * http://www.helixcommunity.org/content/rpsl unless you have licensed + * the file under the RealNetworks Community Source License Version 1.0 + * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, + * in which case the RCSL will apply. You may also obtain the license terms + * directly from RealNetworks. You may not use this file except in + * compliance with the RPSL or, if you have a valid RCSL with RealNetworks + * applicable to this file, the RCSL. Please see the applicable RPSL or + * RCSL for the rights, obligations and limitations governing use of the + * contents of the file. + * + * This file is part of the Helix DNA Technology. RealNetworks is the + * developer of the Original Code and owns the copyrights in the portions + * it created. + * + * This file, and the files included with this file, is distributed and made + * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * + * Technology Compatibility Kit Test Suite(s) Location: + * http://www.helixcommunity.org/content/tck + * + * Contributor(s): + * + * ***** END LICENSE BLOCK ***** */ + +/************************************************************************************** + * Fixed-point MP3 decoder + * Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com) + * June 2003 + * + * scalfact.c - scalefactor unpacking functions + **************************************************************************************/ +#include "include.h" +#include "coder.h" + +#if (CONFIG_APP_MP3PLAYER == 1) +/* scale factor lengths (num bits) */ +static const char SFLenTab[16][2] = { + {0, 0}, {0, 1}, + {0, 2}, {0, 3}, + {3, 0}, {1, 1}, + {1, 2}, {1, 3}, + {2, 1}, {2, 2}, + {2, 3}, {3, 1}, + {3, 2}, {3, 3}, + {4, 2}, {4, 3}, +}; + +/************************************************************************************** + * Function: UnpackSFMPEG1 + * + * Description: unpack MPEG 1 scalefactors from bitstream + * + * Inputs: BitStreamInfo, SideInfoSub, ScaleFactorInfoSub structs for this + * granule/channel + * vector of scfsi flags from side info, length = 4 (MAX_SCFBD) + * index of current granule + * ScaleFactorInfoSub from granule 0 (for granule 1, if scfsi[i] is set, + * then we just replicate the scale factors from granule 0 in the + * i'th set of scalefactor bands) + * + * Outputs: updated BitStreamInfo struct + * scalefactors in sfis (short and/or long arrays, as appropriate) + * + * Return: none + * + * Notes: set order of short blocks to s[band][window] instead of s[window][band] + * so that we index through consectutive memory locations when unpacking + * (make sure dequantizer follows same convention) + * Illegal Intensity Position = 7 (always) for MPEG1 scale factors + **************************************************************************************/ +static void UnpackSFMPEG1(BitStreamInfo *bsi, SideInfoSub *sis, ScaleFactorInfoSub *sfis, int *scfsi, int gr, ScaleFactorInfoSub *sfisGr0) +{ + int sfb; + int slen0, slen1; + + /* these can be 0, so make sure GetBits(bsi, 0) returns 0 (no >> 32 or anything) */ + slen0 = (int)SFLenTab[sis->sfCompress][0]; + slen1 = (int)SFLenTab[sis->sfCompress][1]; + + if (sis->blockType == 2) { + /* short block, type 2 (implies winSwitchFlag == 1) */ + if (sis->mixedBlock) { + /* do long block portion */ + for (sfb = 0; sfb < 8; sfb++) + sfis->l[sfb] = (char)GetBits(bsi, slen0); + sfb = 3; + } else { + /* all short blocks */ + sfb = 0; + } + + for ( ; sfb < 6; sfb++) { + sfis->s[sfb][0] = (char)GetBits(bsi, slen0); + sfis->s[sfb][1] = (char)GetBits(bsi, slen0); + sfis->s[sfb][2] = (char)GetBits(bsi, slen0); + } + + for ( ; sfb < 12; sfb++) { + sfis->s[sfb][0] = (char)GetBits(bsi, slen1); + sfis->s[sfb][1] = (char)GetBits(bsi, slen1); + sfis->s[sfb][2] = (char)GetBits(bsi, slen1); + } + + /* last sf band not transmitted */ + sfis->s[12][0] = sfis->s[12][1] = sfis->s[12][2] = 0; + } else { + /* long blocks, type 0, 1, or 3 */ + if(gr == 0) { + /* first granule */ + for (sfb = 0; sfb < 11; sfb++) + sfis->l[sfb] = (char)GetBits(bsi, slen0); + for (sfb = 11; sfb < 21; sfb++) + sfis->l[sfb] = (char)GetBits(bsi, slen1); + return; + } else { + /* second granule + * scfsi: 0 = different scalefactors for each granule, 1 = copy sf's from granule 0 into granule 1 + * for block type == 2, scfsi is always 0 + */ + sfb = 0; + if(scfsi[0]) for( ; sfb < 6 ; sfb++) sfis->l[sfb] = sfisGr0->l[sfb]; + else for( ; sfb < 6 ; sfb++) sfis->l[sfb] = (char)GetBits(bsi, slen0); + if(scfsi[1]) for( ; sfb <11 ; sfb++) sfis->l[sfb] = sfisGr0->l[sfb]; + else for( ; sfb <11 ; sfb++) sfis->l[sfb] = (char)GetBits(bsi, slen0); + if(scfsi[2]) for( ; sfb <16 ; sfb++) sfis->l[sfb] = sfisGr0->l[sfb]; + else for( ; sfb <16 ; sfb++) sfis->l[sfb] = (char)GetBits(bsi, slen1); + if(scfsi[3]) for( ; sfb <21 ; sfb++) sfis->l[sfb] = sfisGr0->l[sfb]; + else for( ; sfb <21 ; sfb++) sfis->l[sfb] = (char)GetBits(bsi, slen1); + } + /* last sf band not transmitted */ + sfis->l[21] = 0; + sfis->l[22] = 0; + } +} + +/* NRTab[size + 3*is_right][block type][partition] + * block type index: 0 = (bt0,bt1,bt3), 1 = bt2 non-mixed, 2 = bt2 mixed + * partition: scale factor groups (sfb1 through sfb4) + * for block type = 2 (mixed or non-mixed) / by 3 is rolled into this table + * (for 3 short blocks per long block) + * see 2.4.3.2 in MPEG 2 (low sample rate) spec + * stuff rolled into this table: + * NRTab[x][1][y] --> (NRTab[x][1][y]) / 3 + * NRTab[x][2][>=1] --> (NRTab[x][2][>=1]) / 3 (first partition is long block) + */ +static const char NRTab[6][3][4] = { + /* non-intensity stereo */ + { {6, 5, 5, 5}, + {3, 3, 3, 3}, /* includes / 3 */ + {6, 3, 3, 3}, /* includes / 3 except for first entry */ + }, + { {6, 5, 7, 3}, + {3, 3, 4, 2}, + {6, 3, 4, 2}, + }, + { {11, 10, 0, 0}, + {6, 6, 0, 0}, + {6, 3, 6, 0}, /* spec = [15,18,0,0], but 15 = 6L + 9S, so move 9/3=3 into col 1, 18/3=6 into col 2 and adj. slen[1,2] below */ + }, + /* intensity stereo, right chan */ + { {7, 7, 7, 0}, + {4, 4, 4, 0}, + {6, 5, 4, 0}, + }, + { {6, 6, 6, 3}, + {4, 3, 3, 2}, + {6, 4, 3, 2}, + }, + { {8, 8, 5, 0}, + {5, 4, 3, 0}, + {6, 6, 3, 0}, + } +}; + +/************************************************************************************** + * Function: UnpackSFMPEG2 + * + * Description: unpack MPEG 2 scalefactors from bitstream + * + * Inputs: BitStreamInfo, SideInfoSub, ScaleFactorInfoSub structs for this + * granule/channel + * index of current granule and channel + * ScaleFactorInfoSub from this granule + * modeExt field from frame header, to tell whether intensity stereo is on + * ScaleFactorJS struct for storing IIP info used in Dequant() + * + * Outputs: updated BitStreamInfo struct + * scalefactors in sfis (short and/or long arrays, as appropriate) + * updated intensityScale and preFlag flags + * + * Return: none + * + * Notes: Illegal Intensity Position = (2^slen) - 1 for MPEG2 scale factors + * + * TODO: optimize the / and % stuff (only do one divide, get modulo x + * with (x / m) * m, etc.) + **************************************************************************************/ +static void UnpackSFMPEG2(BitStreamInfo *bsi, SideInfoSub *sis, ScaleFactorInfoSub *sfis, int gr, int ch, int modeExt, ScaleFactorJS *sfjs) +{ + + int i, sfb, sfcIdx, btIdx, nrIdx;//, iipTest; + int slen[4], nr[4]; + int sfCompress, preFlag, intensityScale; + + sfCompress = sis->sfCompress; + preFlag = 0; + intensityScale = 0; + + /* stereo mode bits (1 = on): bit 1 = mid-side on/off, bit 0 = intensity on/off */ + if (! ((modeExt & 0x01) && (ch == 1)) ) { + /* in other words: if ((modeExt & 0x01) == 0 || ch == 0) */ + if (sfCompress < 400) { + /* max slen = floor[(399/16) / 5] = 4 */ + slen[0] = (sfCompress >> 4) / 5; + slen[1]= (sfCompress >> 4) % 5; + slen[2]= (sfCompress & 0x0f) >> 2; + slen[3]= (sfCompress & 0x03); + sfcIdx = 0; + } else if (sfCompress < 500) { + /* max slen = floor[(99/4) / 5] = 4 */ + sfCompress -= 400; + slen[0] = (sfCompress >> 2) / 5; + slen[1]= (sfCompress >> 2) % 5; + slen[2]= (sfCompress & 0x03); + slen[3]= 0; + sfcIdx = 1; + } else { + /* max slen = floor[11/3] = 3 (sfCompress = 9 bits in MPEG2) */ + sfCompress -= 500; + slen[0] = sfCompress / 3; + slen[1] = sfCompress % 3; + slen[2] = slen[3] = 0; + if (sis->mixedBlock) { + /* adjust for long/short mix logic (see comment above in NRTab[] definition) */ + slen[2] = slen[1]; + slen[1] = slen[0]; + } + preFlag = 1; + sfcIdx = 2; + } + } else { + /* intensity stereo ch = 1 (right) */ + intensityScale = sfCompress & 0x01; + sfCompress >>= 1; + if (sfCompress < 180) { + /* max slen = floor[35/6] = 5 (from mod 36) */ + slen[0] = (sfCompress / 36); + slen[1] = (sfCompress % 36) / 6; + slen[2] = (sfCompress % 36) % 6; + slen[3] = 0; + sfcIdx = 3; + } else if (sfCompress < 244) { + /* max slen = floor[63/16] = 3 */ + sfCompress -= 180; + slen[0] = (sfCompress & 0x3f) >> 4; + slen[1] = (sfCompress & 0x0f) >> 2; + slen[2] = (sfCompress & 0x03); + slen[3] = 0; + sfcIdx = 4; + } else { + /* max slen = floor[11/3] = 3 (max sfCompress >> 1 = 511/2 = 255) */ + sfCompress -= 244; + slen[0] = (sfCompress / 3); + slen[1] = (sfCompress % 3); + slen[2] = slen[3] = 0; + sfcIdx = 5; + } + } + + /* set index based on block type: (0,1,3) --> 0, (2 non-mixed) --> 1, (2 mixed) ---> 2 */ + btIdx = 0; + if (sis->blockType == 2) + btIdx = (sis->mixedBlock ? 2 : 1); + for (i = 0; i < 4; i++) + nr[i] = (int)NRTab[sfcIdx][btIdx][i]; + + /* save intensity stereo scale factor info */ + if( (modeExt & 0x01) && (ch == 1) ) { + for (i = 0; i < 4; i++) { + sfjs->slen[i] = slen[i]; + sfjs->nr[i] = nr[i]; + } + sfjs->intensityScale = intensityScale; + } + sis->preFlag = preFlag; + + /* short blocks */ + if(sis->blockType == 2) { + if(sis->mixedBlock) { + /* do long block portion */ + //iipTest = (1 << slen[0]) - 1; + for (sfb=0; sfb < 6; sfb++) { + sfis->l[sfb] = (char)GetBits(bsi, slen[0]); + } + sfb = 3; /* start sfb for short */ + nrIdx = 1; + } else { + /* all short blocks, so start nr, sfb at 0 */ + sfb = 0; + nrIdx = 0; + } + + /* remaining short blocks, sfb just keeps incrementing */ + for ( ; nrIdx <= 3; nrIdx++) { + //iipTest = (1 << slen[nrIdx]) - 1; + for (i=0; i < nr[nrIdx]; i++, sfb++) { + sfis->s[sfb][0] = (char)GetBits(bsi, slen[nrIdx]); + sfis->s[sfb][1] = (char)GetBits(bsi, slen[nrIdx]); + sfis->s[sfb][2] = (char)GetBits(bsi, slen[nrIdx]); + } + } + /* last sf band not transmitted */ + sfis->s[12][0] = sfis->s[12][1] = sfis->s[12][2] = 0; + } else { + /* long blocks */ + sfb = 0; + for (nrIdx = 0; nrIdx <= 3; nrIdx++) { + //iipTest = (1 << slen[nrIdx]) - 1; + for(i=0; i < nr[nrIdx]; i++, sfb++) { + sfis->l[sfb] = (char)GetBits(bsi, slen[nrIdx]); + } + } + /* last sf band not transmitted */ + sfis->l[21] = sfis->l[22] = 0; + + } +} + +/************************************************************************************** + * Function: UnpackScaleFactors + * + * Description: parse the fields of the MP3 scale factor data section + * + * Inputs: MP3DecInfo structure filled by UnpackFrameHeader() and UnpackSideInfo() + * buffer pointing to the MP3 scale factor data + * pointer to bit offset (0-7) indicating starting bit in buf[0] + * number of bits available in data buffer + * index of current granule and channel + * + * Outputs: updated platform-specific ScaleFactorInfo struct + * updated bitOffset + * + * Return: length (in bytes) of scale factor data, -1 if null input pointers + **************************************************************************************/ +int UnpackScaleFactors(MP3DecInfo *mp3DecInfo, unsigned char *buf, int *bitOffset, int bitsAvail, int gr, int ch) +{ + int bitsUsed; + unsigned char *startBuf; + BitStreamInfo bitStreamInfo, *bsi; + FrameHeader *fh; + SideInfo *si; + ScaleFactorInfo *sfi; + + /* validate pointers */ + if (!mp3DecInfo || !mp3DecInfo->FrameHeaderPS || !mp3DecInfo->SideInfoPS || !mp3DecInfo->ScaleFactorInfoPS) + return -1; + fh = ((FrameHeader *)(mp3DecInfo->FrameHeaderPS)); + si = ((SideInfo *)(mp3DecInfo->SideInfoPS)); + sfi = ((ScaleFactorInfo *)(mp3DecInfo->ScaleFactorInfoPS)); + + /* init GetBits reader */ + startBuf = buf; + bsi = &bitStreamInfo; + SetBitstreamPointer(bsi, (bitsAvail + *bitOffset + 7) / 8, buf); + if (*bitOffset) + GetBits(bsi, *bitOffset); + + if (fh->ver == MPEG1) + UnpackSFMPEG1(bsi, &si->sis[gr][ch], &sfi->sfis[gr][ch], si->scfsi[ch], gr, &sfi->sfis[0][ch]); + else + UnpackSFMPEG2(bsi, &si->sis[gr][ch], &sfi->sfis[gr][ch], gr, ch, fh->modeExt, &sfi->sfjs); + + mp3DecInfo->part23Length[gr][ch] = si->sis[gr][ch].part23Length; + + bitsUsed = CalcBitsUsed(bsi, buf, *bitOffset); + buf += (bitsUsed + *bitOffset) >> 3; + *bitOffset = (bitsUsed + *bitOffset) & 0x07; + + return (buf - startBuf); +} +#endif /* CONFIG_APP_MP3PLAYER */ diff --git a/beken_os/beken378/func/music_player/Mp3Lib/statname.h b/beken_os/beken378/func/music_player/Mp3Lib/statname.h new file mode 100755 index 0000000..a6f00ce --- /dev/null +++ b/beken_os/beken378/func/music_player/Mp3Lib/statname.h @@ -0,0 +1,89 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: RCSL 1.0/RPSL 1.0 + * + * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. + * + * The contents of this file, and the files included with this file, are + * subject to the current version of the RealNetworks Public Source License + * Version 1.0 (the "RPSL") available at + * http://www.helixcommunity.org/content/rpsl unless you have licensed + * the file under the RealNetworks Community Source License Version 1.0 + * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, + * in which case the RCSL will apply. You may also obtain the license terms + * directly from RealNetworks. You may not use this file except in + * compliance with the RPSL or, if you have a valid RCSL with RealNetworks + * applicable to this file, the RCSL. Please see the applicable RPSL or + * RCSL for the rights, obligations and limitations governing use of the + * contents of the file. + * + * This file is part of the Helix DNA Technology. RealNetworks is the + * developer of the Original Code and owns the copyrights in the portions + * it created. + * + * This file, and the files included with this file, is distributed and made + * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * + * Technology Compatibility Kit Test Suite(s) Location: + * http://www.helixcommunity.org/content/tck + * + * Contributor(s): + * + * ***** END LICENSE BLOCK ***** */ + +/************************************************************************************** + * Fixed-point MP3 decoder + * Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com) + * June 2003 + * + * statname.h - name mangling macros for static linking + **************************************************************************************/ + +#ifndef _STATNAME_H +#define _STATNAME_H + +#if (CONFIG_APP_MP3PLAYER == 1) +/* define STAT_PREFIX to a unique name for static linking + * all the C functions and global variables will be mangled by the preprocessor + * e.g. void FFT(int *fftbuf) becomes void cook_FFT(int *fftbuf) + */ +#define STAT_PREFIX xmp3 + +#define STATCC1(x,y,z) STATCC2(x,y,z) +#define STATCC2(x,y,z) x##y##z + +#ifdef STAT_PREFIX +#define STATNAME(func) STATCC1(STAT_PREFIX, _, func) +#else +#define STATNAME(func) func +#endif + +/* these symbols are common to all implementations */ +#define CheckPadBit STATNAME(CheckPadBit) +#define UnpackFrameHeader STATNAME(UnpackFrameHeader) +#define UnpackSideInfo STATNAME(UnpackSideInfo) +#define AllocateBuffers STATNAME(AllocateBuffers) +#define FreeBuffers STATNAME(FreeBuffers) +#define DecodeHuffman STATNAME(DecodeHuffman) +#define Dequantize STATNAME(Dequantize) +#define IMDCT STATNAME(IMDCT) +#define UnpackScaleFactors STATNAME(UnpackScaleFactors) +#define Subband STATNAME(Subband) + +#define samplerateTab STATNAME(samplerateTab) +#define bitrateTab STATNAME(bitrateTab) +#define samplesPerFrameTab STATNAME(samplesPerFrameTab) +#define bitsPerSlotTab STATNAME(bitsPerSlotTab) +#define sideBytesTab STATNAME(sideBytesTab) +#define slotTab STATNAME(slotTab) +#define sfBandTable STATNAME(sfBandTable) + +/* in your implementation's top-level include file (e.g. real\coder.h) you should + * add new #define sym STATNAME(sym) lines for all the + * additional global functions or variables which your + * implementation uses + */ +#endif /* CONFIG_APP_MP3PLAYER */ +#endif /* _STATNAME_H */ diff --git a/beken_os/beken378/func/music_player/Mp3Lib/stproc.c b/beken_os/beken378/func/music_player/Mp3Lib/stproc.c new file mode 100755 index 0000000..19c45f3 --- /dev/null +++ b/beken_os/beken378/func/music_player/Mp3Lib/stproc.c @@ -0,0 +1,296 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: RCSL 1.0/RPSL 1.0 + * + * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. + * + * The contents of this file, and the files included with this file, are + * subject to the current version of the RealNetworks Public Source License + * Version 1.0 (the "RPSL") available at + * http://www.helixcommunity.org/content/rpsl unless you have licensed + * the file under the RealNetworks Community Source License Version 1.0 + * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, + * in which case the RCSL will apply. You may also obtain the license terms + * directly from RealNetworks. You may not use this file except in + * compliance with the RPSL or, if you have a valid RCSL with RealNetworks + * applicable to this file, the RCSL. Please see the applicable RPSL or + * RCSL for the rights, obligations and limitations governing use of the + * contents of the file. + * + * This file is part of the Helix DNA Technology. RealNetworks is the + * developer of the Original Code and owns the copyrights in the portions + * it created. + * + * This file, and the files included with this file, is distributed and made + * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * + * Technology Compatibility Kit Test Suite(s) Location: + * http://www.helixcommunity.org/content/tck + * + * Contributor(s): + * + * ***** END LICENSE BLOCK ***** */ + +/************************************************************************************** + * Fixed-point MP3 decoder + * Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com) + * June 2003 + * + * stproc.c - mid-side and intensity (MPEG1 and MPEG2) stereo processing + **************************************************************************************/ + +#include "coder.h" +#include "assembly.h" +#if (CONFIG_APP_MP3PLAYER == 1) +/************************************************************************************** + * Function: MidSideProc + * + * Description: sum-difference stereo reconstruction + * + * Inputs: vector x with dequantized samples from left and right channels + * number of non-zero samples (MAX of left and right) + * assume 1 guard bit in input + * guard bit mask (left and right channels) + * + * Outputs: updated sample vector x + * updated guard bit mask + * + * Return: none + * + * Notes: assume at least 1 GB in input + **************************************************************************************/ +void MidSideProc(int x[MAX_NCHAN][MAX_NSAMP], int nSamps, int mOut[2]) +{ + int i, xr, xl, mOutL, mOutR; + + /* L = (M+S)/sqrt(2), R = (M-S)/sqrt(2) + * NOTE: 1/sqrt(2) done in DequantChannel() - see comments there + */ + mOutL = mOutR = 0; + for(i = 0; i < nSamps; i++) { + xl = x[0][i]; + xr = x[1][i]; + x[0][i] = xl + xr; + x[1][i] = xl - xr; + mOutL |= FASTABS(x[0][i]); + mOutR |= FASTABS(x[1][i]); + } + mOut[0] |= mOutL; + mOut[1] |= mOutR; +} + +/************************************************************************************** + * Function: IntensityProcMPEG1 + * + * Description: intensity stereo processing for MPEG1 + * + * Inputs: vector x with dequantized samples from left and right channels + * number of non-zero samples in left channel + * valid FrameHeader struct + * two each of ScaleFactorInfoSub, CriticalBandInfo structs (both channels) + * flags indicating midSide on/off, mixedBlock on/off + * guard bit mask (left and right channels) + * + * Outputs: updated sample vector x + * updated guard bit mask + * + * Return: none + * + * Notes: assume at least 1 GB in input + * + * TODO: combine MPEG1/2 into one function (maybe) + * make sure all the mixed-block and IIP logic is right + **************************************************************************************/ +void IntensityProcMPEG1(int x[MAX_NCHAN][MAX_NSAMP], int nSamps, FrameHeader *fh, ScaleFactorInfoSub *sfis, + CriticalBandInfo *cbi, int midSideFlag, int mixFlag, int mOut[2]) +{ + int i=0, j=0, n=0, cb=0, w=0; + int sampsLeft, isf, mOutL, mOutR, xl, xr; + int fl, fr, fls[3], frs[3]; + int cbStartL=0, cbStartS=0, cbEndL=0, cbEndS=0; + int *isfTab; + + /* NOTE - this works fine for mixed blocks, as long as the switch point starts in the + * short block section (i.e. on or after sample 36 = sfBand->l[8] = 3*sfBand->s[3] + * is this a safe assumption? + * TODO - intensity + mixed not quite right (diff = 11 on he_mode) + * figure out correct implementation (spec ambiguous about when to do short block reorder) + */ + if (cbi[1].cbType == 0) { + /* long block */ + cbStartL = cbi[1].cbEndL + 1; + cbEndL = cbi[0].cbEndL + 1; + cbStartS = cbEndS = 0; + i = fh->sfBand->l[cbStartL]; + } else if (cbi[1].cbType == 1 || cbi[1].cbType == 2) { + /* short or mixed block */ + cbStartS = cbi[1].cbEndSMax + 1; + cbEndS = cbi[0].cbEndSMax + 1; + cbStartL = cbEndL = 0; + i = 3 * fh->sfBand->s[cbStartS]; + } + + sampsLeft = nSamps - i; /* process to length of left */ + isfTab = (int *)ISFMpeg1[midSideFlag]; + mOutL = mOutR = 0; + + /* long blocks */ + for (cb = cbStartL; cb < cbEndL && sampsLeft > 0; cb++) { + isf = sfis->l[cb]; + if (isf == 7) { + fl = ISFIIP[midSideFlag][0]; + fr = ISFIIP[midSideFlag][1]; + } else { + fl = isfTab[isf]; + fr = isfTab[6] - isfTab[isf]; + } + + n = fh->sfBand->l[cb + 1] - fh->sfBand->l[cb]; + for (j = 0; j < n && sampsLeft > 0; j++, i++) { + xr = MULSHIFT32(fr, x[0][i]) << 2; x[1][i] = xr; mOutR |= FASTABS(xr); + xl = MULSHIFT32(fl, x[0][i]) << 2; x[0][i] = xl; mOutL |= FASTABS(xl); + sampsLeft--; + } + } + + /* short blocks */ + for (cb = cbStartS; cb < cbEndS && sampsLeft >= 3; cb++) { + for (w = 0; w < 3; w++) { + isf = sfis->s[cb][w]; + if (isf == 7) { + fls[w] = ISFIIP[midSideFlag][0]; + frs[w] = ISFIIP[midSideFlag][1]; + } else { + fls[w] = isfTab[isf]; + frs[w] = isfTab[6] - isfTab[isf]; + } + } + + n = fh->sfBand->s[cb + 1] - fh->sfBand->s[cb]; + for (j = 0; j < n && sampsLeft >= 3; j++, i+=3) { + xr = MULSHIFT32(frs[0], x[0][i+0]) << 2; x[1][i+0] = xr; mOutR |= FASTABS(xr); + xl = MULSHIFT32(fls[0], x[0][i+0]) << 2; x[0][i+0] = xl; mOutL |= FASTABS(xl); + xr = MULSHIFT32(frs[1], x[0][i+1]) << 2; x[1][i+1] = xr; mOutR |= FASTABS(xr); + xl = MULSHIFT32(fls[1], x[0][i+1]) << 2; x[0][i+1] = xl; mOutL |= FASTABS(xl); + xr = MULSHIFT32(frs[2], x[0][i+2]) << 2; x[1][i+2] = xr; mOutR |= FASTABS(xr); + xl = MULSHIFT32(fls[2], x[0][i+2]) << 2; x[0][i+2] = xl; mOutL |= FASTABS(xl); + sampsLeft -= 3; + } + } + mOut[0] = mOutL; + mOut[1] = mOutR; + + return; +} + +/************************************************************************************** + * Function: IntensityProcMPEG2 + * + * Description: intensity stereo processing for MPEG2 + * + * Inputs: vector x with dequantized samples from left and right channels + * number of non-zero samples in left channel + * valid FrameHeader struct + * two each of ScaleFactorInfoSub, CriticalBandInfo structs (both channels) + * ScaleFactorJS struct with joint stereo info from UnpackSFMPEG2() + * flags indicating midSide on/off, mixedBlock on/off + * guard bit mask (left and right channels) + * + * Outputs: updated sample vector x + * updated guard bit mask + * + * Return: none + * + * Notes: assume at least 1 GB in input + * + * TODO: combine MPEG1/2 into one function (maybe) + * make sure all the mixed-block and IIP logic is right + * probably redo IIP logic to be simpler + **************************************************************************************/ +void IntensityProcMPEG2(int x[MAX_NCHAN][MAX_NSAMP], int nSamps, FrameHeader *fh, ScaleFactorInfoSub *sfis, + CriticalBandInfo *cbi, ScaleFactorJS *sfjs, int midSideFlag, int mixFlag, int mOut[2]) +{ + int i, j, k, n, r, cb, w; + int fl, fr, mOutL, mOutR, xl, xr; + int sampsLeft; + int isf, sfIdx, tmp, il[23]; + int *isfTab; + int cbStartL, cbStartS, cbEndL, cbEndS; + + isfTab = (int *)ISFMpeg2[sfjs->intensityScale][midSideFlag]; + mOutL = mOutR = 0; + + /* fill buffer with illegal intensity positions (depending on slen) */ + for (k = r = 0; r < 4; r++) { + tmp = (1 << sfjs->slen[r]) - 1; + for (j = 0; j < sfjs->nr[r]; j++, k++) + il[k] = tmp; + } + + if (cbi[1].cbType == 0) { + /* long blocks */ + il[21] = il[22] = 1; + cbStartL = cbi[1].cbEndL + 1; /* start at end of right */ + cbEndL = cbi[0].cbEndL + 1; /* process to end of left */ + i = fh->sfBand->l[cbStartL]; + sampsLeft = nSamps - i; + + for(cb = cbStartL; cb < cbEndL; cb++) { + sfIdx = sfis->l[cb]; + if (sfIdx == il[cb]) { + fl = ISFIIP[midSideFlag][0]; + fr = ISFIIP[midSideFlag][1]; + } else { + isf = (sfis->l[cb] + 1) >> 1; + fl = isfTab[(sfIdx & 0x01 ? isf : 0)]; + fr = isfTab[(sfIdx & 0x01 ? 0 : isf)]; + } + n = MIN(fh->sfBand->l[cb + 1] - fh->sfBand->l[cb], sampsLeft); + + for(j = 0; j < n; j++, i++) { + xr = MULSHIFT32(fr, x[0][i]) << 2; x[1][i] = xr; mOutR |= FASTABS(xr); + xl = MULSHIFT32(fl, x[0][i]) << 2; x[0][i] = xl; mOutL |= FASTABS(xl); + } + + /* early exit once we've used all the non-zero samples */ + sampsLeft -= n; + if (sampsLeft == 0) + break; + } + } else { + /* short or mixed blocks */ + il[12] = 1; + + for(w = 0; w < 3; w++) { + cbStartS = cbi[1].cbEndS[w] + 1; /* start at end of right */ + cbEndS = cbi[0].cbEndS[w] + 1; /* process to end of left */ + i = 3 * fh->sfBand->s[cbStartS] + w; + + /* skip through sample array by 3, so early-exit logic would be more tricky */ + for(cb = cbStartS; cb < cbEndS; cb++) { + sfIdx = sfis->s[cb][w]; + if (sfIdx == il[cb]) { + fl = ISFIIP[midSideFlag][0]; + fr = ISFIIP[midSideFlag][1]; + } else { + isf = (sfis->s[cb][w] + 1) >> 1; + fl = isfTab[(sfIdx & 0x01 ? isf : 0)]; + fr = isfTab[(sfIdx & 0x01 ? 0 : isf)]; + } + n = fh->sfBand->s[cb + 1] - fh->sfBand->s[cb]; + + for(j = 0; j < n; j++, i+=3) { + xr = MULSHIFT32(fr, x[0][i]) << 2; x[1][i] = xr; mOutR |= FASTABS(xr); + xl = MULSHIFT32(fl, x[0][i]) << 2; x[0][i] = xl; mOutL |= FASTABS(xl); + } + } + } + } + mOut[0] = mOutL; + mOut[1] = mOutR; + + return; +} +#endif /* CONFIG_APP_MP3PLAYER */ diff --git a/beken_os/beken378/func/music_player/Mp3Lib/subband.c b/beken_os/beken378/func/music_player/Mp3Lib/subband.c new file mode 100755 index 0000000..f965a61 --- /dev/null +++ b/beken_os/beken378/func/music_player/Mp3Lib/subband.c @@ -0,0 +1,99 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: RCSL 1.0/RPSL 1.0 + * + * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. + * + * The contents of this file, and the files included with this file, are + * subject to the current version of the RealNetworks Public Source License + * Version 1.0 (the "RPSL") available at + * http://www.helixcommunity.org/content/rpsl unless you have licensed + * the file under the RealNetworks Community Source License Version 1.0 + * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, + * in which case the RCSL will apply. You may also obtain the license terms + * directly from RealNetworks. You may not use this file except in + * compliance with the RPSL or, if you have a valid RCSL with RealNetworks + * applicable to this file, the RCSL. Please see the applicable RPSL or + * RCSL for the rights, obligations and limitations governing use of the + * contents of the file. + * + * This file is part of the Helix DNA Technology. RealNetworks is the + * developer of the Original Code and owns the copyrights in the portions + * it created. + * + * This file, and the files included with this file, is distributed and made + * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * + * Technology Compatibility Kit Test Suite(s) Location: + * http://www.helixcommunity.org/content/tck + * + * Contributor(s): + * + * ***** END LICENSE BLOCK ***** */ + +/************************************************************************************** + * Fixed-point MP3 decoder + * Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com) + * June 2003 + * + * subband.c - subband transform (synthesis filterbank implemented via 32-point DCT + * followed by polyphase filter) + **************************************************************************************/ +#include "include.h" +#include "coder.h" +#include "assembly.h" + +#if (CONFIG_APP_MP3PLAYER == 1) +/************************************************************************************** + * Function: Subband + * + * Description: do subband transform on all the blocks in one granule, all channels + * + * Inputs: filled MP3DecInfo structure, after calling IMDCT for all channels + * vbuf[ch] and vindex[ch] must be preserved between calls + * + * Outputs: decoded PCM data, interleaved LRLRLR... if stereo + * + * Return: 0 on success, -1 if null input pointers + **************************************************************************************/ +int Subband(MP3DecInfo *mp3DecInfo, short **pcmBuf) +{ + int b; + IMDCTInfo *mi; + SubbandInfo *sbi; + + /* validate pointers */ + if (!mp3DecInfo || !mp3DecInfo->HuffmanInfoPS || !mp3DecInfo->IMDCTInfoPS || !mp3DecInfo->SubbandInfoPS) + return -1; + + mi = (IMDCTInfo *)(mp3DecInfo->IMDCTInfoPS); + sbi = (SubbandInfo*)(mp3DecInfo->SubbandInfoPS); + + if (mp3DecInfo->nChans == 2) { + /* stereo */ + for (b = 0; b < BLOCK_SIZE; b++) { + + /*the normal code*/ + FDCT32(mi->outBuf[0][b], sbi->vbuf + 0*32, sbi->vindex, (b & 0x01), mi->gb[0]); + FDCT32(mi->outBuf[1][b], sbi->vbuf + 1*32, sbi->vindex, (b & 0x01), mi->gb[1]); + PolyphaseStereo(*pcmBuf, sbi->vbuf + sbi->vindex + VBUF_LENGTH * (b & 0x01), polyCoef); + sbi->vindex = (sbi->vindex - (b & 0x01)) & 7; + *pcmBuf += (2*NBANDS); + } + } else { + /* mono */ + for (b = 0; b < BLOCK_SIZE; b++) { + FDCT32(mi->outBuf[0][b], sbi->vbuf + 0*32, sbi->vindex, (b & 0x01), mi->gb[0]); + PolyphaseMono(*pcmBuf, sbi->vbuf + sbi->vindex + VBUF_LENGTH * (b & 0x01), polyCoef); + sbi->vindex = (sbi->vindex - (b & 0x01)) & 7; + *pcmBuf += NBANDS; + } + } + + return 0; +} +#endif /* CONFIG_APP_MP3PLAYER */ +// eof + diff --git a/beken_os/beken378/func/music_player/Mp3Lib/trigtabs.c b/beken_os/beken378/func/music_player/Mp3Lib/trigtabs.c new file mode 100755 index 0000000..57a7dcb --- /dev/null +++ b/beken_os/beken378/func/music_player/Mp3Lib/trigtabs.c @@ -0,0 +1,311 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: RCSL 1.0/RPSL 1.0 + * + * Portions Copyright (c) 1995-2002 RealNetworks, Inc. All Rights Reserved. + * + * The contents of this file, and the files included with this file, are + * subject to the current version of the RealNetworks Public Source License + * Version 1.0 (the "RPSL") available at + * http://www.helixcommunity.org/content/rpsl unless you have licensed + * the file under the RealNetworks Community Source License Version 1.0 + * (the "RCSL") available at http://www.helixcommunity.org/content/rcsl, + * in which case the RCSL will apply. You may also obtain the license terms + * directly from RealNetworks. You may not use this file except in + * compliance with the RPSL or, if you have a valid RCSL with RealNetworks + * applicable to this file, the RCSL. Please see the applicable RPSL or + * RCSL for the rights, obligations and limitations governing use of the + * contents of the file. + * + * This file is part of the Helix DNA Technology. RealNetworks is the + * developer of the Original Code and owns the copyrights in the portions + * it created. + * + * This file, and the files included with this file, is distributed and made + * available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * + * Technology Compatibility Kit Test Suite(s) Location: + * http://www.helixcommunity.org/content/tck + * + * Contributor(s): + * + * ***** END LICENSE BLOCK ***** */ + +/************************************************************************************** + * Fixed-point MP3 decoder + * Jon Recker (jrecker@real.com), Ken Cooke (kenc@real.com) + * June 2003 + * + * trigtabs.c - global ROM tables for pre-calculated trig coefficients + **************************************************************************************/ + +#include "coder.h" +#if (CONFIG_APP_MP3PLAYER == 1) +/* post-IMDCT window, win[blockType][i] + * format = Q31 + * Fused sin window with final stage of IMDCT + * includes 1/sqrt(2) scaling, since we scale by sqrt(2) in dequant in order + * for fast IMDCT36 to be usable + * + * for(i=0;i<9;i++) win[0][i] = sin(pi/36 *(i+0.5)); + * for(i=9;i<36;i++) win[0][i] = -sin(pi/36 *(i+0.5)); + * + * for(i=0;i<9;i++) win[1][i] = sin(pi/36 *(i+0.5)); + * for(i=9;i<18;i++) win[1][i] = -sin(pi/36 *(i+0.5)); + * for(i=18;i<24;i++) win[1][i] = -1; + * for(i=24;i<30;i++) win[1][i] = -sin(pi/12 *(i+0.5-18)); + * for(i=30;i<36;i++) win[1][i] = 0; + * + * for(i=0;i<6;i++) win[3][i] = 0; + * for(i=6;i<9;i++) win[3][i] = sin(pi/12 *(i+0.5-6)); + * for(i=9;i<12;i++) win[3][i] = -sin(pi/12 *(i+0.5-6)); + * for(i=12;i<18;i++) win[3][i] = -1; + * for(i=18;i<36;i++) win[3][i] = -sin(pi/36*(i+0.5)); + * + * for(i=0;i<3;i++) win[2][i] = sin(pi/12*(i+0.5)); + * for(i=3;i<12;i++) win[2][i] = -sin(pi/12*(i+0.5)); + * for(i=12;i<36;i++) win[2][i] = 0; + * + * for (i = 0; i < 4; i++) { + * if (i == 2) { + * win[i][8] *= cos(pi/12 * (0+0.5)); + * win[i][9] *= cos(pi/12 * (0+0.5)); + * win[i][7] *= cos(pi/12 * (1+0.5)); + * win[i][10] *= cos(pi/12 * (1+0.5)); + * win[i][6] *= cos(pi/12 * (2+0.5)); + * win[i][11] *= cos(pi/12 * (2+0.5)); + * win[i][0] *= cos(pi/12 * (3+0.5)); + * win[i][5] *= cos(pi/12 * (3+0.5)); + * win[i][1] *= cos(pi/12 * (4+0.5)); + * win[i][4] *= cos(pi/12 * (4+0.5)); + * win[i][2] *= cos(pi/12 * (5+0.5)); + * win[i][3] *= cos(pi/12 * (5+0.5)); + * } else { + * for (j = 0; j < 9; j++) { + * win[i][8-j] *= cos(pi/36 * (17-j+0.5)); + * win[i][9+j] *= cos(pi/36 * (17-j+0.5)); + * } + * for (j = 0; j < 9; j++) { + * win[i][18+8-j] *= cos(pi/36 * (j+0.5)); + * win[i][18+9+j] *= cos(pi/36 * (j+0.5)); + * } + * } + * } + * for (i = 0; i < 4; i++) + * for (j = 0; j < 36; j++) + * win[i][j] *= 1.0 / sqrt(2); + */ +const int imdctWin[4][36] = { + { + 0x02aace8b, 0x07311c28, 0x0a868fec, 0x0c913b52, 0x0d413ccd, 0x0c913b52, 0x0a868fec, 0x07311c28, + 0x02aace8b, 0xfd16d8dd, 0xf6a09e66, 0xef7a6275, 0xe7dbc161, 0xe0000000, 0xd8243e9f, 0xd0859d8b, + 0xc95f619a, 0xc2e92723, 0xbd553175, 0xb8cee3d8, 0xb5797014, 0xb36ec4ae, 0xb2bec333, 0xb36ec4ae, + 0xb5797014, 0xb8cee3d8, 0xbd553175, 0xc2e92723, 0xc95f619a, 0xd0859d8b, 0xd8243e9f, 0xe0000000, + 0xe7dbc161, 0xef7a6275, 0xf6a09e66, 0xfd16d8dd, + }, + { + 0x02aace8b, 0x07311c28, 0x0a868fec, 0x0c913b52, 0x0d413ccd, 0x0c913b52, 0x0a868fec, 0x07311c28, + 0x02aace8b, 0xfd16d8dd, 0xf6a09e66, 0xef7a6275, 0xe7dbc161, 0xe0000000, 0xd8243e9f, 0xd0859d8b, + 0xc95f619a, 0xc2e92723, 0xbd44ef14, 0xb831a052, 0xb3aa3837, 0xafb789a4, 0xac6145bb, 0xa9adecdc, + 0xa864491f, 0xad1868f0, 0xb8431f49, 0xc8f42236, 0xdda8e6b1, 0xf47755dc, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, + { + 0x07311c28, 0x0d413ccd, 0x07311c28, 0xf6a09e66, 0xe0000000, 0xc95f619a, 0xb8cee3d8, 0xb2bec333, + 0xb8cee3d8, 0xc95f619a, 0xe0000000, 0xf6a09e66, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, + }, + { + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x028e9709, 0x04855ec0, + 0x026743a1, 0xfcde2c10, 0xf515dc82, 0xec93e53b, 0xe4c880f8, 0xdd5d0b08, 0xd63510b7, 0xcf5e834a, + 0xc8e6b562, 0xc2da4105, 0xbd553175, 0xb8cee3d8, 0xb5797014, 0xb36ec4ae, 0xb2bec333, 0xb36ec4ae, + 0xb5797014, 0xb8cee3d8, 0xbd553175, 0xc2e92723, 0xc95f619a, 0xd0859d8b, 0xd8243e9f, 0xe0000000, + 0xe7dbc161, 0xef7a6275, 0xf6a09e66, 0xfd16d8dd, + }, +}; + +/* indexing = [mid-side off/on][intensity scale factor] + * format = Q30, range = [0.0, 1.414] + * + * mid-side off: + * ISFMpeg1[0][i] = tan(i*pi/12) / [1 + tan(i*pi/12)] (left scalefactor) + * = 1 / [1 + tan(i*pi/12)] (right scalefactor) + * + * mid-side on: + * ISFMpeg1[1][i] = sqrt(2) * ISFMpeg1[0][i] + * + * output L = ISFMpeg1[midSide][isf][0] * input L + * output R = ISFMpeg1[midSide][isf][1] * input L + * + * obviously left scalefactor + right scalefactor = 1 (m-s off) or sqrt(2) (m-s on) + * so just store left and calculate right as 1 - left + * (can derive as right = ISFMpeg1[x][6] - left) + * + * if mid-side enabled, multiply joint stereo scale factors by sqrt(2) + * - we scaled whole spectrum by 1/sqrt(2) in Dequant for the M+S/sqrt(2) in MidSideProc + * - but the joint stereo part of the spectrum doesn't need this, so we have to undo it + * + * if scale factor is and illegal intensity position, this becomes a passthrough + * - gain = [1, 0] if mid-side off, since L is coded directly and R = 0 in this region + * - gain = [1, 1] if mid-side on, since L = (M+S)/sqrt(2), R = (M-S)/sqrt(2) + * - and since S = 0 in the joint stereo region (above NZB right) then L = R = M * 1.0 + */ +const int ISFMpeg1[2][7] = { + {0x00000000, 0x0d8658ba, 0x176cf5d0, 0x20000000, 0x28930a2f, 0x3279a745, 0x40000000}, + {0x00000000, 0x13207f5c, 0x2120fb83, 0x2d413ccc, 0x39617e16, 0x4761fa3d, 0x5a827999} +}; + +/* indexing = [intensity scale on/off][mid-side off/on][intensity scale factor] + * format = Q30, range = [0.0, 1.414] + * + * if (isf == 0) kl = 1.0 kr = 1.0 + * else if (isf & 0x01 == 0x01) kl = i0^((isf+1)/2), kr = 1.0 + * else if (isf & 0x01 == 0x00) kl = 1.0, kr = i0^(isf/2) + * + * if (intensityScale == 1) i0 = 1/sqrt(2) = 0x2d413ccc (Q30) + * else i0 = 1/sqrt(sqrt(2)) = 0x35d13f32 (Q30) + * + * see comments for ISFMpeg1 (just above) regarding scaling, sqrt(2), etc. + * + * compress the MPEG2 table using the obvious identities above... + * for isf = [0, 1, 2, ... 30], let sf = table[(isf+1) >> 1] + * - if isf odd, L = sf*L, R = tab[0]*R + * - if isf even, L = tab[0]*L, R = sf*R + */ +const int ISFMpeg2[2][2][16] = { +{ + { + /* intensityScale off, mid-side off */ + 0x40000000, 0x35d13f32, 0x2d413ccc, 0x260dfc14, 0x1fffffff, 0x1ae89f99, 0x16a09e66, 0x1306fe0a, + 0x0fffffff, 0x0d744fcc, 0x0b504f33, 0x09837f05, 0x07ffffff, 0x06ba27e6, 0x05a82799, 0x04c1bf82, + }, + { + /* intensityScale off, mid-side on */ + 0x5a827999, 0x4c1bf827, 0x3fffffff, 0x35d13f32, 0x2d413ccc, 0x260dfc13, 0x1fffffff, 0x1ae89f99, + 0x16a09e66, 0x1306fe09, 0x0fffffff, 0x0d744fcc, 0x0b504f33, 0x09837f04, 0x07ffffff, 0x06ba27e6, + }, +}, +{ + { + /* intensityScale on, mid-side off */ + 0x40000000, 0x2d413ccc, 0x20000000, 0x16a09e66, 0x10000000, 0x0b504f33, 0x08000000, 0x05a82799, + 0x04000000, 0x02d413cc, 0x02000000, 0x016a09e6, 0x01000000, 0x00b504f3, 0x00800000, 0x005a8279, + }, + /* intensityScale on, mid-side on */ + { + 0x5a827999, 0x3fffffff, 0x2d413ccc, 0x1fffffff, 0x16a09e66, 0x0fffffff, 0x0b504f33, 0x07ffffff, + 0x05a82799, 0x03ffffff, 0x02d413cc, 0x01ffffff, 0x016a09e6, 0x00ffffff, 0x00b504f3, 0x007fffff, + } +} +}; + +/* indexing = [intensity scale on/off][left/right] + * format = Q30, range = [0.0, 1.414] + * + * illegal intensity position scalefactors (see comments on ISFMpeg1) + */ +const int ISFIIP[2][2] = { + {0x40000000, 0x00000000}, /* mid-side off */ + {0x40000000, 0x40000000}, /* mid-side on */ +}; + +const unsigned char uniqueIDTab[8] = {0x5f, 0x4b, 0x43, 0x5f, 0x5f, 0x4a, 0x52, 0x5f}; + +/* anti-alias coefficients - see spec Annex B, table 3-B.9 + * csa[0][i] = CSi, csa[1][i] = CAi + * format = Q31 + */ +const int csa[8][2] = { + {0x6dc253f0, 0xbe2500aa}, + {0x70dcebe4, 0xc39e4949}, + {0x798d6e73, 0xd7e33f4a}, + {0x7ddd40a7, 0xe8b71176}, + {0x7f6d20b7, 0xf3e4fe2f}, + {0x7fe47e40, 0xfac1a3c7}, + {0x7ffcb263, 0xfe2ebdc6}, + {0x7fffc694, 0xff86c25d}, +}; + +/* format = Q30, range = [0.0981, 1.9976] + * + * n = 16; + * k = 0; + * for(i=0; i<5; i++, n=n/2) { + * for(p=0; p +#include "error.h" +#include "typedef.h" +#include "arm_arch.h" +#include "uart_pub.h" +#include "mem_pub.h" +#include "music_msg_pub.h" +#include "driver_audio_if_pub.h" +#include "playmode_pub.h" +#include "app.h" +#include "app_music.h" +#include "mp3dec.h" +#include "mp3common.h" +#include "coder.h" +#include "layer21.h" + +MEDIA_CORE_T g_media_core = {0}; + + +#if (CONFIG_APP_MP3PLAYER == 1) +#define USE_EXTERNAL_DAC + +extern void ClearMP3(MP3DecInfo *mp3DecInfo); +UINT8 media_app_msg_handler(UINT32 msg_id); +UINT16 currentDir = 0; +UINT32 file_ptr_save = 0; +static app_player_ctrl app_player; +app_player_ctrl_backup player_config_backup; + +UINT8 *readBuf; +UINT16 *mp3_pcm_ptr; +UINT16 *mp3_pcm_ptr_tmp; +INT32 pcm_size = 0; +volatile UINT8 aud_buff_full = 0; +volatile UINT32 buf_free; + +UINT16 *aulawsmpl; +UINT16 *alawtbl; +UINT16 *ulawtbl; +UINT8 *rbbuf; +HMP3Decoder hMP3Decoder; //Ϣṹ +MP3FrameInfo mp3FrameInfo; //mp3ļϢṹ +MP3DecInfo *mp3decinfo; + +UINT16 input_number; +UINT8 init=0; +UINT8 mp3_play_flag = 0; +UINT8 t=0; +static UINT8 media_err_cnt = 0; +UINT8 play_derect = 0; // 1:next, 0 :previous +UINT8 appPlayerPlayMode=0; +UINT8 media_playing_flag = 0;//current meida playing status +FIL *newFatfs; + +static void app_player_mp3_file_end( void ); +static void app_player_process_file_end( void ); + +static void mp3_mem_init(void) +{ + L2DecodeContext *l2i; + + if(NULL == hMP3Decoder) + { + hMP3Decoder = MP3InitDecoder(); + } + if(NULL == hMP3Decoder) + { + APP_MUSIC_PRT("hMP3Decoder_malloc_fail\r\n"); + return; + } + + mp3decinfo = (MP3DecInfo*)hMP3Decoder; + readBuf= (unsigned char*)ff_memalloc(READBUF_SIZE); //FOR READ BUF + mp3decinfo->mainBuf = readBuf; + mp3decinfo->mainBuf_ptr = mp3decinfo->mainBuf + BIT_RESVOR_SIZE; + mp3decinfo->mainBuf_len = 0; + mp3decinfo->err_cnt = 0; + + mp3_pcm_ptr = (short*)mp3decinfo->HuffmanInfoPS; + + l2i = (L2DecodeContext *)(mp3decinfo->L2DecInfo); + l2i->sb_samples = (int32_t*)(mp3decinfo->SubbandInfoPS); + l2i->synth_buf = (INT16 *)(mp3decinfo->IMDCTInfoPS); + + + return; +} + + +static void mp3_mem_uninit(void) +{ + if(readBuf) + { + APP_MUSIC_PRT("mp3 mem free 1\r\n"); + os_free(readBuf); + readBuf = NULL; + mp3decinfo->mainBuf = NULL; + } + + if(hMP3Decoder) + { + APP_MUSIC_PRT("mp3 mem free 3\r\n"); + MP3FreeDecoder(hMP3Decoder); + hMP3Decoder = NULL; + mp3decinfo = NULL; + } +} + + +static void app_player_mp3_init(void) +{ + mp3_mem_init(); + init=0; + t = 0; +} + + +static int app_player_to_first_file( void ) +{ + FILE_INFO *pFile; + + uint32 player_flag = app_player.player_flag; + uint32 schedule_cmd = app_player.schedule_cmd; + memset( (uint8 *)&app_player, 0, sizeof( app_player_ctrl ) ); + app_player.player_flag = player_flag; + app_player.schedule_cmd = schedule_cmd; + if( 0 == get_musicfile_count()) + { + return -1; + } + newFatfs = Get_File_From_Number(0); + pFile = get_file_info(); + + app_player.player_flag &= ~APP_PLAYER_FLAG_PLAY_END; + app_player.file_index = 0; + app_player.file_info.file_blks = newFatfs->obj.objsize; + app_player.file_info.file_start_cluster = newFatfs->obj.sclust; + + app_player.block_played = 0; + memcpy(app_player.file_info.ext_name,pFile->extname,3); + memcpy(app_player.file_info.filename,pFile->fname,8); + return 0; +} + + +static int app_player_get_next_stream_file( void ) +{ + FILE_INFO *pFile ; + uint16 musicfilecount = get_musicfile_count(); + + if( 0 == musicfilecount) + { + return -1; + } + + app_player.file_index++; + if(app_player.file_index > (musicfilecount-1)) + app_player.file_index = 0; + + newFatfs = Get_File_From_Number(app_player.file_index); + pFile = get_file_info(); + + app_player.player_flag &= ~APP_PLAYER_FLAG_PLAY_END; + app_player.file_info.file_blks = newFatfs->obj.objsize; + app_player.file_info.file_start_cluster = newFatfs->obj.sclust; + app_player.block_played = 0; + + memcpy(app_player.file_info.ext_name,pFile->extname,3); + memcpy(app_player.file_info.filename,pFile->fname,8); + + return 0; +} + + +static int app_player_get_prev_stream_file( void ) +{ + FILE_INFO *pFile; + uint16 musicfilecount = get_musicfile_count(); + + if( 0 == musicfilecount) + { + return -1; + } + + app_player.file_index--; + if(app_player.file_index < 0) + app_player.file_index = musicfilecount-1; + + newFatfs = Get_File_From_Number(app_player.file_index); + pFile = get_file_info(); + + app_player.player_flag &= ~APP_PLAYER_FLAG_PLAY_END; + app_player.file_info.file_blks = newFatfs->obj.objsize; + app_player.file_info.file_start_cluster = newFatfs->obj.sclust; + app_player.block_played = 0; + + memcpy(app_player.file_info.ext_name,pFile->extname,3); + memcpy(app_player.file_info.filename,pFile->fname,8); + + return 0; +} +static int app_player_get_fix_stream_file( uint16 fileIndex ) +{ + FILE_INFO *pFile ; + uint16 musicfilecount = get_musicfile_count(); + + if( 0 == musicfilecount) + { + return -1; + } + + app_player.file_index = fileIndex; + if(app_player.file_index > (musicfilecount-1)) + app_player.file_index = 0; + + newFatfs = Get_File_From_Number(app_player.file_index); + pFile = get_file_info(); + + app_player.player_flag &= ~APP_PLAYER_FLAG_PLAY_END; + app_player.file_info.file_blks = newFatfs->obj.objsize; + app_player.file_info.file_start_cluster = newFatfs->obj.sclust; + app_player.block_played = 0; + + memcpy(app_player.file_info.ext_name,pFile->extname,3); + memcpy(app_player.file_info.filename,pFile->fname,8); + + return 0; +} + +static int app_player_play_mp3_file( void ) +{ + int err; + static UINT32 error_cnt = 0; + + if(!hMP3Decoder && mp3_play_flag) + { + return ERR_UNKNOWN; + } + err = ERR_MP3_NONE; + if(aud_buff_full) + goto fill_aud_buff; + + err = MP3Decode(hMP3Decoder, mp3_pcm_ptr, &pcm_size); + + if(err != ERR_MP3_NONE) + { + switch(err) + { + + case ERR_MP3_INDATA_UNDERFLOW: + { + if(f_EOF(newFatfs) == FR_FILE_END) + { + APP_MUSIC_PRT("===file end====\r\n"); + app_player_mp3_file_end(); + app_player_process_file_end(); + } + else + { + mp3decinfo->decode_state = MP3_DECODE_FIND_ID3_INFO; + APP_MUSIC_PRT("not the end of the file\r\n"); + } + break; + } + case ERR_MP3_READ_DATA_FAILED: + { + APP_MUSIC_PRT("**mp3 read error**\r\n"); + break; + } + case ERR_MP3_FILE_END: + { + app_player_mp3_file_end(); + APP_MUSIC_PRT("mmmm\r\n"); + app_player_process_file_end(); + APP_MUSIC_PRT("nnnnn\r\n"); + break; + } + case ERR_MP3_MAINDATA_UNDERFLOW: + { + mp3decinfo->decode_state = MP3_DECODE_FIND_SYNC_WORD; + break; + } + case ERR_MP3_DECODE_MAX_ERR: + APP_MUSIC_PRT("---mp3 max error------\r\n"); + app_player_mp3_file_end(); + app_player_process_file_end(); + break; + default: + ClearMP3((MP3DecInfo *)hMP3Decoder); + mp3decinfo->decode_state = MP3_DECODE_FIND_SYNC_WORD; + break; + + } + APP_MUSIC_PRT("mp3 error retrun:%x,%x\r\n",app_player.player_flag & APP_PLAYER_FLAG_PLAY_PAUSE,app_player.schedule_cmd & 0xFFFF ); + return err; + } + + error_cnt = 0; + // wait for at least 4 corret frame decode. + if(init == 0) + { + if(t <= APP_PLAYER_AUDIO_INITION_BEGIN) + { + if(mp3decinfo->decode_state == MP3_DECODE_FIND_SYNC_WORD) + t++; + return ERR_MP3_NONE; + } + + MP3GetLastFrameInfo(hMP3Decoder, &mp3FrameInfo); //ý + APP_MUSIC_PRT("%dkb/s, ԭ%dHZ\r\n", + (mp3FrameInfo.bitrate)/1000,mp3FrameInfo.samprate); + APP_MUSIC_PRT("ԭ%d, MPAG:%d,:%d\r\n", + mp3FrameInfo.nChans,mp3FrameInfo.version,mp3FrameInfo.layer); + APP_MUSIC_PRT("outputsamps:%d\r\n",mp3FrameInfo.outputSamps); + APP_MUSIC_PRT("ÿ֡:%d\r\n",mp3decinfo->framesize); + + aud_initial(mp3FrameInfo.samprate, 2, 16 ); + init=1; + } + mp3_pcm_ptr_tmp = mp3_pcm_ptr; + MP3GetLastFrameInfo(hMP3Decoder, &mp3FrameInfo); + if(mp3FrameInfo.nChans == 1) + { + Convert_Mono(mp3_pcm_ptr,pcm_size); + pcm_size <<= 1; + } + +fill_aud_buff: + buf_free = aud_get_buffer_size(); + if(buf_free > pcm_size*2) + { + aud_fill_buffer((uint8*)mp3_pcm_ptr_tmp, pcm_size*2); + aud_buff_full = 0; + pcm_size = 0; + } + else + { + /*at least 128 byte space in audbuffer, we can fill it*/ + if(buf_free>=128) + { + //we cann't fill audbuffer to full, should be 4bytes less + //see func: aud_fill_buffer + buf_free = (buf_free&0xfffffffe)-4; + aud_fill_buffer((uint8*)mp3_pcm_ptr_tmp, buf_free); + mp3_pcm_ptr_tmp += (buf_free>>1); + pcm_size -= (buf_free>>1); + } + aud_buff_full = 1; + } + + if(is_aud_opened()==0) + aud_open(); + + return ERR_MP3_NONE; +} + + +static void app_player_play_pause( UINT8 play_pause ) +{ + UINT32 readbytes = 0; + + if(get_musicfile_count() == 0 ) + return; + + APP_MUSIC_PRT("---play_pause:%x,flag:%x----\r\n",play_pause,app_player.player_flag & APP_PLAYER_FLAG_PLAY_PAUSE); + if( (play_pause == 0) && (app_player.player_flag & APP_PLAYER_FLAG_PLAY_PAUSE )) // pause + { + app_player.player_flag &= ~APP_PLAYER_FLAG_PLAY_PAUSE; + aud_close(); + } + else if( play_pause && !( app_player.player_flag & APP_PLAYER_FLAG_PLAY_PAUSE)) + { + if( strncmp( app_player.file_info.ext_name, "MP3", 3 ) == 0 ) + { + if(mp3_play_flag != 1) + { + APP_MUSIC_PRT("start playing start \r\n"); + + app_player_mp3_init(); + if(mp3decinfo) + { + mp3decinfo->decode_state = MP3_DECODE_FIND_ID3_INFO; + + } + else + { + APP_MUSIC_PRT("mp3 memery initial unsucssed\r\n"); + } + mp3_play_flag = 1; + } + else + { + mp3decinfo->decode_state = MP3_DECODE_FIND_SYNC_WORD; + init = 0; + t = 0; + aud_buff_full = 0; + } + } + else + { + return; + } + app_player.player_flag |= APP_PLAYER_FLAG_PLAY_PAUSE; + } +} + + +static void app_player_process_schedule_cmd( void ) +{ + switch( app_player.schedule_cmd & 0xFFFF ) + { + case APP_PLAYER_SCHEDULE_CMD_MODE_CHANGE: + aud_close(); + app_player.schedule_cmd = 0; + break; + + case APP_PLAYER_SCHEDULE_CMD_FIX_SONG: + if(app_player.player_flag & APP_PLAYER_FLAG_HW_ATTACH ) + { + int get_next_return=0; + + play_derect = 1; + + app_player.player_flag &= ~APP_PLAYER_FLAG_PLAY_END; + if(mp3_play_flag == 1) + { + APP_MUSIC_PRT("END 3\r\n"); + app_player_mp3_file_end(); + } + + get_next_return = app_player_get_fix_stream_file(input_number-1); // get next file + input_number = 0; + + if( app_player.schedule_cmd & APP_PLAY_SCHEDULE_CMD_PLAY_FLAG ) + app_player_play_pause(1); + (void)get_next_return; + } + app_player.schedule_cmd = 0; + break; + + case APP_PLAYER_SCHEDULE_CMD_NEXT_SONG: + if(app_player.player_flag & APP_PLAYER_FLAG_HW_ATTACH ) + { + int get_next_return=0; + + play_derect = 1; + app_player.player_flag &= ~APP_PLAYER_FLAG_PLAY_END; + + if(mp3_play_flag == 1) + { + APP_MUSIC_PRT("END 3\r\n"); + app_player_mp3_file_end(); + } + get_next_return = app_player_get_next_stream_file(); // get next file + + if( app_player.schedule_cmd & APP_PLAY_SCHEDULE_CMD_PLAY_FLAG ) + app_player_play_pause(1); + (void)get_next_return; + } + app_player.schedule_cmd = 0; + break; + + case APP_PLAYER_SCHEDULE_CMD_PREV_SONG: + if(app_player.player_flag & APP_PLAYER_FLAG_HW_ATTACH ) + { + int get_pre_return=0; + play_derect = 0; + app_player.player_flag &= ~APP_PLAYER_FLAG_PLAY_END; + if(mp3_play_flag == 1) + { + APP_MUSIC_PRT("END 4\r\n"); + app_player_mp3_file_end(); + } + get_pre_return = app_player_get_prev_stream_file(); + + if( app_player.schedule_cmd & APP_PLAY_SCHEDULE_CMD_PLAY_FLAG ) + app_player_play_pause(1); + (void)get_pre_return; + } + app_player.schedule_cmd = 0; + break; + + default: + break; + } +} + + +static void app_player_file_info_init( void ) +{ + int file_index; + FILE_INFO *pFile; + if( 0 == get_musicfile_count()) + { + return; + } + + memset( (uint8 *)&app_player, 0, sizeof( app_player ) ); + app_player.player_flag |= (APP_PLAYER_FLAG_PLAY_CONTINOUS|APP_PLAYER_FLAG_PLAY_CYCLE|APP_PLAYER_FLAG_HW_ATTACH); + + file_index = player_config_backup.file_index; + + if(file_index > (get_musicfile_count()-1) || file_index < 0) + { + app_player_to_first_file(); + } + else + { + newFatfs = Get_File_From_Number(file_index); + pFile = get_file_info(); + app_player.player_flag &= ~APP_PLAYER_FLAG_PLAY_END; + app_player.file_info.file_blks = newFatfs->obj.objsize; + app_player.file_info.file_start_cluster = newFatfs->obj.sclust; + app_player.block_played = 0; + memcpy(app_player.file_info.ext_name,pFile->extname,3); + memcpy(app_player.file_info.filename,pFile->fname,8); + if(app_player.file_info.file_blks == player_config_backup.file_size_blks) + { + app_player.file_index = player_config_backup.file_index; + app_player.block_played = player_config_backup.block_played; + if( strncmp(app_player.file_info.ext_name, "MP3", 3 ) == 0 ) + { + f_lseek(newFatfs, app_player.block_played); + } + } + else + { + app_player_to_first_file(); + } + } +} + + +static uint8 app_player_play_func( void ) +{ + if( !(app_player.player_flag & APP_PLAYER_FLAG_HW_ATTACH )) + { + app_player_process_schedule_cmd(); + return 1; + } + + if( app_player.player_flag & APP_PLAYER_FLAG_PLAY_PAUSE ) + { + if( strncmp( app_player.file_info.ext_name, "MP3", 3 ) == 0 ) + { + if(app_player_play_mp3_file()) + { + return 2; + } + } + } + app_player_process_schedule_cmd(); + if(aud_buff_full) + return 1; + else + return 0; +} + +static void app_player_mp3_file_end( void ) +{ + t = 0; + init=0; + media_err_cnt = 0; + mp3_play_flag = 0; + + aud_buff_full = 0; + aud_close(); + + mp3_mem_uninit(); + + rbbuf = NULL; + f_close(newFatfs); +} +static void app_player_stop( void ) +{ + if( app_player.file_index < 0 ) + return; + + app_player.player_flag &= ~APP_PLAYER_FLAG_PLAY_PAUSE; + if( strncmp( app_player.file_info.ext_name, "MP3", 3 ) == 0 ) + { + app_player.block_played = 0; + } +} + +static void app_player_process_file_end( void ) +{ + if(app_player.media_err_status == FR_DISK_ERR) + { + app_player.media_err_status = FR_OK; + return; + } + app_player.player_flag &= ~APP_PLAYER_FLAG_PLAY_PAUSE; + if( app_player.player_flag & APP_PLAYER_FLAG_PLAY_CONTINOUS ) + { + int get_file_return = 0; + + if(appPlayerPlayMode==APP_PLAYER_MODE_PLAY_ONE) + get_file_return = app_player_get_fix_stream_file(app_player.file_index); // get current file + else + get_file_return = app_player_get_next_stream_file(); // get next file + app_player_play_pause(1); // not the file list end, just play next file + (void)get_file_return; + } + else // not continous play + { + if( app_player.player_flag & APP_PLAYER_FLAG_PLAY_CYCLE ) // cycle , play last index + { + f_lseek(newFatfs,0); + app_player.block_played = 0; + app_player_play_pause(1); + } + else // just close + { + app_player_stop(); + aud_close(); + } + } +} + + +static void app_player_unload(void) +{ + FRESULT err = FR_OK; + app_player_play_pause(0); + aud_close(); + if(mp3_play_flag == 1) + { + app_player_mp3_file_end(); + } + media_uninit(); + memset( &app_player, 0, sizeof(app_player_ctrl) ); +} + +void media_msg_sender(void const *param_ptr) +{ + OSStatus ret; + MEDIA_MSG_T msg; + + msg.id = (UINT32)param_ptr; + ret = rtos_push_to_queue(&g_media_core.io_queue, &msg, BEKEN_NO_WAIT); + if(kNoErr != ret) + { + APP_MUSIC_PRT("media_msg_sender_fail\r\n"); + } +} + +static void app_media_thread( void *arg ) +{ + OSStatus ret; + MEDIA_MSG_T msg; + UINT8 play_flag = 0; + UINT32 msg_timeout_ms = BEKEN_WAIT_FOREVER; + UINT8 meida_play=0; + + while(1) + { + ret = rtos_pop_from_queue(&g_media_core.io_queue, &msg, msg_timeout_ms); + if(kNoErr == ret) + { + play_flag = media_app_msg_handler(msg.id); + } +#ifdef USE_EXTERNAL_DAC + if(play_flag) + { + while(1) + { + if(app_player_play_func()) + break; + } + } + msg_timeout_ms = 2; +#endif + } +} + +static void media_thread_uninit(void) +{ + if(g_media_core.handle) + { + rtos_delete_thread(&g_media_core.handle); + g_media_core.handle = 0; + } + + if(g_media_core.io_queue) + { + rtos_deinit_queue(&g_media_core.io_queue); + g_media_core.io_queue = 0; + } + + g_media_core.queue_item_count = 0; + g_media_core.stack_size = 0; +} + +#endif + + +void media_thread_init(void) +{ +#if (CONFIG_APP_MP3PLAYER == 1) + OSStatus ret; + + g_media_core.queue_item_count = MEDIA_QITEM_COUNT; + g_media_core.stack_size = MEDIA_STACK_SIZE; + + ret = rtos_init_queue(&g_media_core.io_queue, + "media queue", + sizeof(MEDIA_MSG_T), + g_media_core.queue_item_count); + if (kNoErr != ret) + { + APP_MUSIC_PRT("Create media queue failed\r\n"); + goto fail; + } + + ret = rtos_create_thread(&g_media_core.handle, + THD_MEDIA_PRIORITY, + "media_thread", + (beken_thread_function_t)app_media_thread, + (unsigned short)g_media_core.stack_size, + (beken_thread_arg_t)0); + + if (kNoErr != ret) + { + APP_MUSIC_PRT("Create medai thread failed\r\n"); + goto fail; + } +#ifdef USE_EXTERNAL_DAC + if(aud_hw_init()!=kNoErr) + goto fail; +#endif + return; +fail: + media_thread_uninit(); +#endif +} + + +#if (CONFIG_APP_MP3PLAYER == 1) +UINT8 media_app_msg_handler(UINT32 msg_id) +{ + UINT8 ret = 0; + static UINT8 media_ok = 0; + switch(msg_id) + { + case MSG_SD_ATTACH: + APP_MUSIC_PRT("---attach---\r\n"); +#if (CONFIG_APP_MP3PLAYER == 1) + media_init(0); + if(get_fat_ok_flag()) + { + media_ok = 1; + app_player_file_info_init(); + app_player_play_pause( !(app_player.player_flag & APP_PLAYER_FLAG_PLAY_PAUSE ) ); + ret = 1; + } +#endif + break; + case MSG_SD_DETACH: + media_ok = 0; + APP_MUSIC_PRT("---dettach---\r\n"); +#if (CONFIG_APP_MP3PLAYER == 1) + app_player_unload(); +#endif + break; + case MSG_MUSIC_PLAY: + if(media_ok == 1) + { + ret= 1; + } + else + ret = 0; + break; + +#ifdef USE_EXTERNAL_DAC + case MSG_KEY_PLAY|KEY_LONG: + case MSG_KEY_PLAY: + if(app_player.player_flag & APP_PLAYER_FLAG_PLAY_PAUSE) + ret = 0; + else + ret = 1; + app_player_play_pause(!(app_player.player_flag & APP_PLAYER_FLAG_PLAY_PAUSE)); + break; +#endif + } + return ret; +} +#endif diff --git a/beken_os/beken378/func/music_player/app_music.h b/beken_os/beken378/func/music_player/app_music.h new file mode 100755 index 0000000..abc2d61 --- /dev/null +++ b/beken_os/beken378/func/music_player/app_music.h @@ -0,0 +1,92 @@ +#ifndef _APP_MUSIC_H_ +#define _APP_MUSIC_H_ +#include "sys_rtos.h" +#include "rtos_pub.h" + +#define APP_MUSIC_DEBUG + +#ifdef APP_MUSIC_DEBUG +#define APP_MUSIC_PRT os_printf +#else +#define APP_MUSIC_PRT os_null_printf +#endif + +typedef struct _app_player_ctrl_s +{ + fat_file_info_t file_info; // cur file info + UINT32 file_index; // file handle + UINT32 block_played; + + UINT32 player_flag; + UINT32 schedule_cmd; + UINT8 media_err_status; + +}app_player_ctrl; + +typedef struct _app_player_ctrl_backup_s +{ + UINT32 file_index; // file handle + UINT32 file_size_blks; + UINT32 block_played; +}app_player_ctrl_backup; + + +#define MEDIA_STACK_SIZE 4096 +#define MEDIA_QITEM_COUNT 16 + +typedef struct +{ + uint32_t id; +} MEDIA_MSG_T, *MEDIA_MSG_PTR; + + +typedef struct _media_core_ +{ + uint32_t queue_item_count; + beken_queue_t io_queue; + xTaskHandle handle; + uint32_t stack_size; +} MEDIA_CORE_T; + +#define MEDIA_ERR_CNT_THRE 15 + +enum +{ + APP_PLAYER_SCHEDULE_CMD_NEXT_SONG = 1, + APP_PLAYER_SCHEDULE_CMD_PREV_SONG = 2, + APP_PLAYER_SCHEDULE_CMD_NEXT_DIR = 3, + APP_PLAYER_SCHEDULE_CMD_MODE_CHANGE = 4, + APP_PLAYER_SCHEDULE_CMD_PREV_DIR = 5, + APP_PLAYER_SCHEDULE_CMD_FIX_SONG = 8, +}; + +#define APP_PLAY_SCHEDULE_CMD_PLAY_FLAG 0x40000000 +#define APP_PLAYER_FLAG_HW_ATTACH 0x1 +#define APP_PLAYER_FLAG_PLAY_PAUSE 0x2 +#define APP_PLAYER_FLAG_PLAY_CONTINOUS 0x4 +#define APP_PLAYER_FLAG_PLAY_CYCLE 0x8 +#define APP_PLAYER_FLAG_PLAY_END 0x10 + +// not implemented yet +#define APP_PLAYER_FLAG_RANDOM_ORDER 0x2000 + +#define APP_PLAYER_HW_STANDBY_TIME 100 +#define APP_PLAYER_WAVE_READ_BLOCK_NUM 4 +// before setting audio corretly, we need wait for at least 4 corret +// frame decode. +#define APP_PLAYER_AUDIO_INITION_BEGIN 4 + + +void Convert_Mono(short *buffer, int outputSamps); + +enum +{ + APP_PLAYER_MODE_PLAY_ALL_CYCLE = 0, //иѭ + APP_PLAYER_MODE_PLAY_DIR_CYCLE = 1, //ļѭ + APP_PLAYER_MODE_PLAY_ONE = 2, //ѭ + APP_PLAYER_MODE_PLAY_RANDOM = 3, //漴 + APP_PLAYER_MODE_END +}; + +#endif + diff --git a/beken_os/beken378/func/music_player/driver_audio_if.c b/beken_os/beken378/func/music_player/driver_audio_if.c new file mode 100755 index 0000000..7a1ad5e --- /dev/null +++ b/beken_os/beken378/func/music_player/driver_audio_if.c @@ -0,0 +1,293 @@ +#include "driver_audio_if.h" +#include "mem_pub.h" +#include "i2s_pub.h" +#include "gpio_pub.h" +#include "uart_pub.h" +#include "drv_model_pub.h" +#include +#include "driver_codec_es8374_pub.h" +#if (CONFIG_APP_MP3PLAYER==1) + +typedef struct _driver_audio_codec_option_s +{ + void (*codec_init)(); + void (*codec_configure)(unsigned int, unsigned char); + void (*codec_close)(); + void (*codec_volume_control)(unsigned char volume); + void (*codec_mute_control)(BOOL enable); +}driver_audio_codec_option; + + +typedef struct driver_iis_global_setting_s +{ + UINT8 datawidth; + UINT8 volume; + driver_audio_codec_option codec_ops; +}driver_iis_global_setting_t; + +volatile driver_iis_global_setting_t iis_global_setting; + + +static driver_audio_codec_option audio_codec_ops = +{ + es8374_codec_init, + es8374_codec_configure, + es8374_codec_close, + es8374_codec_volume_control, + es8374_codec_mute_control +}; + +AUDIO_CTRL_BLK audio_ctrl_blk = {0}; + +static uint16_t rb_get_fill_size(driver_ringbuff_t *rb) +{ + if (rb->buffp == NULL) + { + DRIVER_AUDIO_PRT("Buffer_null_1\n"); + return -1; + } + + return rb->buffer_fill; +} + + +static uint16_t rb_get_buffer_size(driver_ringbuff_t *rb) +{ + if (rb->buffp == NULL) + { + DRIVER_AUDIO_PRT("Buffer_null_1\n"); + return -1; + } + + return (rb->buffer_len - rb->buffer_fill); +} + + +static uint16_t rb_fill_buffer( driver_ringbuff_t *rb, uint8_t *buff, uint16_t size) +{ + uint16_t buff_space, cpy_size, differ; + + GLOBAL_INT_DECLARATION(); + + if (rb->buffp == NULL) + { + DRIVER_AUDIO_PRT("Buffer_null_3\n"); + return -1; + } + buff_space = rb_get_buffer_size(rb); + + if( buff_space >= size ) + cpy_size = size; + else + { + cpy_size = buff_space; + } + + if( rb->wptr + cpy_size > rb->buffer_len ) + { + differ = rb->buffer_len - rb->wptr; + memcpy( (uint8_t *)&rb->buffp[rb->wptr], + buff, differ); + memcpy( (uint8_t *)&rb->buffp[0], buff + differ, cpy_size - differ); + rb->wptr = cpy_size - differ; + } + else + { + memcpy( (uint8_t *)&rb->buffp[rb->wptr], + buff, cpy_size); + rb->wptr += cpy_size; + } + + if( rb->wptr >= rb->buffer_len) + rb->wptr -= rb->buffer_len; + + GLOBAL_INT_DISABLE(); + rb->buffer_fill += cpy_size; + GLOBAL_INT_RESTORE(); + + return cpy_size; +} + +static void rb_init( driver_ringbuff_t *rb, uint8_t *pbuff, uint16_t len ) +{ + memset( (uint8_t *)rb, 0, sizeof(driver_ringbuff_t)); + + rb->buffp = pbuff; + rb->buffer_len = len; + rb->buffer_fill = 0; + + return; +} +static int16_t rb_get_buffer_with_length( driver_ringbuff_t *rb, uint8_t *buff, uint16_t len ) +{ + int32_t ret = 0; + int32_t size1, size2; + GLOBAL_INT_DECLARATION(); + + if (rb->buffp == NULL) + { + DRIVER_AUDIO_PRT("Buffer_null_4\r\n"); + return 0; + } + + if (!rb->buffer_fill) + goto exit; + + if( rb->rptr >= rb->wptr ) + { + size1 = rb->buffer_len - rb->rptr; + size2 = rb->wptr; + + if( len < size1 ) + { + memcpy( buff, &rb->buffp[rb->rptr], len ); + ret = len; + rb->rptr += len; + } + else + { + memcpy( buff, &rb->buffp[rb->rptr], size1 ); + if( len - size1 < size2 ) + { + memcpy( buff + size1, &rb->buffp[0], (len - size1) ); + ret = len; + rb->rptr = len - size1; + } + else + { + memcpy( buff + size1, &rb->buffp[0], size2 ); + ret = size1 + size2; + rb->rptr = size2; + } + } + } + else + { + size1 = rb->wptr - rb->rptr; + + if( len < size1 ) + { + memcpy( buff, &rb->buffp[rb->rptr], len ); + ret = len; + rb->rptr += len; + } + else + { + memcpy( buff, &rb->buffp[rb->rptr], size1 ); + ret = size1; + rb->rptr += size1; + } + } + + GLOBAL_INT_DISABLE(); + rb->buffer_fill -= ret; + GLOBAL_INT_RESTORE(); + +exit: + return ret; +} + + +void aud_initial(uint32_t freq, uint32_t channels, uint32_t bits_per_sample) +{ + i2s_rate_t rate; + rate.datawidth = bits_per_sample; + rate.freq = freq; + + sddev_control(I2S_DEV_NAME,I2S_CMD_SET_FREQ_DATAWIDTH,&rate); + iis_global_setting.codec_ops.codec_configure(rate.freq,rate.datawidth); + audio_ctrl_blk.channels = channels; +} + +int32_t aud_hw_init(void) +{ +//output 26M clk to dac MCLK + UINT32 param = GFUNC_MODE_CLK26M; + sddev_control(GPIO_DEV_NAME, CMD_GPIO_ENABLE_SECOND, ¶m); + + vTaskDelay(10); + sddev_control(I2S_DEV_NAME, I2S_HW_SET, (void *)0); + + memset((void *)&iis_global_setting, 0, sizeof(driver_iis_global_setting_t)); + iis_global_setting.codec_ops = audio_codec_ops; + + if(audio_ctrl_blk.data_buff == NULL) + { + audio_ctrl_blk.data_buff = os_malloc(AUDIO_BUFF_LEN); + if(audio_ctrl_blk.data_buff == NULL) + { + DRIVER_AUDIO_PRT("===audio malloc error==\r\n"); + return -1; + } + } + + rb_init( &audio_ctrl_blk.aud_rb, (uint8_t *)audio_ctrl_blk.data_buff, AUDIO_BUFF_LEN ); + iis_global_setting.codec_ops.codec_init(); + aud_initial(44100,2,16); + return 0; +} + + + +void aud_open( void ) +{ + UINT8 enable = 1; + DRIVER_AUDIO_PRT("aud open\r\n"); + sddev_control(I2S_DEV_NAME, I2S_CMD_ACTIVE, (void *)&enable); + iis_global_setting.codec_ops.codec_mute_control(0); +} + +void aud_close(void) +{ + UINT8 enable = 0; + DRIVER_AUDIO_PRT("aud close\r\n"); + iis_global_setting.codec_ops.codec_mute_control(1); + sddev_control(I2S_DEV_NAME, I2S_CMD_ACTIVE, (void *)&enable); +} + +uint8_t is_aud_opened(void) +{ + return is_i2s_active(); +} + +uint16_t aud_get_buffer_size(void) +{ return rb_get_buffer_size( &audio_ctrl_blk.aud_rb ); +} + +void aud_fill_buffer( uint8_t *buff, uint16_t len ) +{ + rb_fill_buffer(&audio_ctrl_blk.aud_rb, buff, len); +} + +uint16_t aud_get_buffer_length(uint8_t *buff, uint16_t len) +{ + return rb_get_buffer_with_length(&audio_ctrl_blk.aud_rb, buff, len); +} + +uint8_t aud_get_channel(void) +{ + uint8_t ret; + + if(audio_ctrl_blk.data_buff) + { + ret = audio_ctrl_blk.channels; + } + else + { + ret = 0; + } + + return ret; +} + +uint16_t aud_get_fill_size(void) +{ + if(audio_ctrl_blk.data_buff) + { + return rb_get_fill_size(&audio_ctrl_blk.aud_rb); + } + + return 0; +} +// eof +#endif diff --git a/beken_os/beken378/func/music_player/driver_audio_if.h b/beken_os/beken378/func/music_player/driver_audio_if.h new file mode 100755 index 0000000..8e2fdd2 --- /dev/null +++ b/beken_os/beken378/func/music_player/driver_audio_if.h @@ -0,0 +1,33 @@ +#ifndef _DRIVER_AUDIO_IF_H_ +#define _DRIVER_AUDIO_IF_H_ +#include "sys_rtos.h" +#include "rtos_pub.h" + +#define AUDIO_BUFF_LEN (6144) + +#define DRIVER_AUDIO_DEBUG + +#ifdef DRIVER_AUDIO_DEBUG +#define DRIVER_AUDIO_PRT os_printf +#else +#define DRIVER_AUDIO_PRT os_null_printf +#endif + +typedef struct _driver_ringbuff_s +{ + uint16_t buffer_len; + uint16_t buffer_fill; + uint16_t wptr; + uint16_t rptr; + uint8_t *buffp; +} driver_ringbuff_t; + +typedef struct +{ + uint8_t *data_buff; + driver_ringbuff_t aud_rb; + uint32_t channels; +} AUDIO_CTRL_BLK; +#endif +// eof + diff --git a/beken_os/beken378/func/music_player/fs_fat/disk_io.c b/beken_os/beken378/func/music_player/fs_fat/disk_io.c new file mode 100755 index 0000000..228a27b --- /dev/null +++ b/beken_os/beken378/func/music_player/fs_fat/disk_io.c @@ -0,0 +1,217 @@ +/*-----------------------------------------------------------------------*/ +/* Low level disk I/O module skeleton for FatFs (C)ChaN, 2016 */ +/*-----------------------------------------------------------------------*/ +/* If a working storage control module is available, it should be */ +/* attached to the FatFs via a glue function rather than modifying it. */ +/* This is an example of glue functions to attach various exsisting */ +/* storage control modules to the FatFs module with a defined API. */ +/*-----------------------------------------------------------------------*/ +#include "include.h" + + +#include "ff.h" + +#include "sdcard.h" +#include "sdcard_pub.h" + +#include "drv_model_pub.h" +#include "sys_ctrl_pub.h" +#include "diskio.h" /* FatFs lower layer API */ + +#include "uart_pub.h" + +/* Definitions of physical drive number for each drive */ +#define DEV_SD 0 /* Example: Map MMC/SD card to physical drive 1 */ +#define DEV_USB 1 /* Example: Map USB MSD to physical drive 2 */ + +#if CFG_USE_SDCARD_HOST + DD_HANDLE sdcard_hdl = DD_HANDLE_UNVALID; +#endif + +//static DD_HANDLE usb_hdl =DD_HANDLE_UNVALID; +/*-----------------------------------------------------------------------*/ +/* Get Drive Status */ +/*-----------------------------------------------------------------------*/ +DSTATUS disk_status ( + BYTE pdrv /* Physical drive nmuber to identify the drive */ +) +{ + DSTATUS stat; + int result; + + switch (pdrv) { + case DEV_SD : + stat = RES_OK; + return stat; + + case DEV_USB : + return stat; + + default: + break; + } + return STA_NOINIT; +} + +/*-----------------------------------------------------------------------*/ +/* Inidialize a Drive */ +/*-----------------------------------------------------------------------*/ +DSTATUS disk_initialize ( + BYTE pdrv /* Physical drive nmuber to identify the drive */ +) +{ + DSTATUS stat; + INT result; + UINT status = RES_NOTRDY; + + switch (pdrv) { + case DEV_SD : +#if CFG_USE_SDCARD_HOST + sdcard_hdl = ddev_open(SDCARD_DEV_NAME, &status, 0); +#endif + stat = (DSTATUS)status; + if(stat != FR_OK) + stat = RES_NOTRDY; + return stat; + + case DEV_USB : + return stat; + + default: + break; + } + return STA_NOINIT; +} + + + +/*-----------------------------------------------------------------------*/ +/* Read Sector(s) */ +/*-----------------------------------------------------------------------*/ + +DRESULT disk_read ( + BYTE pdrv, /* Physical drive nmuber to identify the drive */ + BYTE *buff, /* Data buffer to store read data */ + DWORD sector, /* Start sector in LBA */ + UINT count /* Number of sectors to read */ +) +{ + DRESULT res = RES_ERROR; + int result; + + switch (pdrv) { + case DEV_SD : +#if CFG_USE_SDCARD_HOST + // translate the arguments here + if(sdcard_hdl!=DD_HANDLE_UNVALID) + { + result = ddev_read(sdcard_hdl, buff, count, sector); + if(result == RES_OK) + res = RES_OK; + } +#endif + return res; + + case DEV_USB : + return res; + + default: + break; + } + + return RES_PARERR; +} + +/*-----------------------------------------------------------------------*/ +/* Write Sector(s) */ +/*-----------------------------------------------------------------------*/ +DRESULT disk_write ( + BYTE pdrv, /* Physical drive nmuber to identify the drive */ + BYTE *buff, /* Data to be written */ + DWORD sector, /* Start sector in LBA */ + UINT count /* Number of sectors to write */ +) +{ + DRESULT res = RES_ERROR; + int result; + + switch (pdrv) { + case DEV_SD : +#if CFG_USE_SDCARD_HOST + // translate the arguments here + if(sdcard_hdl!=DD_HANDLE_UNVALID) + { + result = ddev_write(sdcard_hdl, buff, count, sector); + if(result == RES_OK) + res = RES_OK; + } +#endif + return res; + + case DEV_USB : + // translate the arguments here + return res; + + default: + break; + } + + return RES_PARERR; +} + +/*-----------------------------------------------------------------------*/ +/* Miscellaneous Functions */ +/*-----------------------------------------------------------------------*/ + +DRESULT disk_ioctl ( + BYTE pdrv, /* Physical drive nmuber (0..) */ + BYTE cmd, /* Control code */ + void *buff /* Buffer to send/receive control data */ +) +{ + DRESULT res = FR_OK; + + switch (pdrv) { + case DEV_SD : + // Process of the command for the MMC/SD card + return res; + + case DEV_USB : + // Process of the command the USB drive + return res; + + default: + break; + + } + + return RES_PARERR; +} + +DSTATUS disk_uninitialize ( BYTE pdrv/* Physical drive nmuber to identify the drive */ +) +{ + DSTATUS stat; + UINT32 result=RES_ERROR; + switch (pdrv) { + case DEV_SD : +#if CFG_USE_SDCARD_HOST + result = ddev_close(sdcard_hdl); +#endif + break; + + case DEV_USB : + break; + + default: + break; + } + if(result != DRV_SUCCESS) + stat = RES_ERROR; + else + stat = RES_OK; + + return stat; +} +// eof + diff --git a/beken_os/beken378/func/music_player/fs_fat/diskio.h b/beken_os/beken378/func/music_player/fs_fat/diskio.h new file mode 100755 index 0000000..4c8d7d8 --- /dev/null +++ b/beken_os/beken378/func/music_player/fs_fat/diskio.h @@ -0,0 +1,74 @@ +/*-----------------------------------------------------------------------/ +/ Low level disk interface modlue include file (C)ChaN, 2014 / +/-----------------------------------------------------------------------*/ + +#ifndef _DISKIO_DEFINED_ +#define _DISKIO_DEFINED_ + +#ifdef __cplusplus +extern "C" { +#endif +#include "integer.h" + +/* Status of Disk Functions */ +typedef BYTE DSTATUS; + +/* Results of Disk Functions */ +typedef enum { + RES_OK = 0, /* 0: Successful */ + RES_ERROR, /* 1: R/W Error */ + RES_WRPRT, /* 2: Write Protected */ + RES_NOTRDY, /* 3: Not Ready */ + RES_PARERR /* 4: Invalid Parameter */ +} DRESULT; + + +/*---------------------------------------*/ +/* Prototypes for disk control functions */ +DSTATUS disk_initialize (BYTE pdrv); +DSTATUS disk_status (BYTE pdrv); +DRESULT disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count); +DRESULT disk_write (BYTE pdrv, BYTE* buff, DWORD sector, UINT count); +DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff); +DSTATUS disk_uninitialize ( BYTE pdrv); + +/* Disk Status Bits (DSTATUS) */ +#define STA_NOINIT 0x01 /* Drive not initialized */ +#define STA_NODISK 0x02 /* No medium in the drive */ +#define STA_PROTECT 0x04 /* Write protected */ + +/* Command code for disk_ioctrl fucntion */ +/* Generic command (Used by FatFs) */ +#define CTRL_SYNC 0 /* Complete pending write process (needed at _FS_READONLY == 0) */ +#define GET_SECTOR_COUNT 1 /* Get media size (needed at _USE_MKFS == 1) */ +#define GET_SECTOR_SIZE 2 /* Get sector size (needed at _MAX_SS != _MIN_SS) */ +#define GET_BLOCK_SIZE 3 /* Get erase block size (needed at _USE_MKFS == 1) */ +#define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at _USE_TRIM == 1) */ + +/* Generic command (Not used by FatFs) */ +#define CTRL_POWER 5 /* Get/Set power status */ +#define CTRL_LOCK 6 /* Lock/Unlock media removal */ +#define CTRL_EJECT 7 /* Eject media */ +#define CTRL_FORMAT 8 /* Create physical format on the media */ + +/* MMC/SDC specific ioctl command */ +#define MMC_GET_TYPE 10 /* Get card type */ +#define MMC_GET_CSD 11 /* Get CSD */ +#define MMC_GET_CID 12 /* Get CID */ +#define MMC_GET_OCR 13 /* Get OCR */ +#define MMC_GET_SDSTAT 14 /* Get SD status */ +#define ISDIO_READ 55 /* Read data form SD iSDIO register */ +#define ISDIO_WRITE 56 /* Write data to SD iSDIO register */ +#define ISDIO_MRITE 57 /* Masked write data to SD iSDIO register */ + +/* ATA/CF specific ioctl command */ +#define ATA_GET_REV 20 /* Get F/W revision */ +#define ATA_GET_MODEL 21 /* Get model name */ +#define ATA_GET_SN 22 /* Get serial number */ + +#ifdef __cplusplus +} +#endif + +#endif // _DISKIO_DEFINED_ +// eof diff --git a/beken_os/beken378/func/music_player/fs_fat/ff.c b/beken_os/beken378/func/music_player/fs_fat/ff.c new file mode 100755 index 0000000..bc2c9df --- /dev/null +++ b/beken_os/beken378/func/music_player/fs_fat/ff.c @@ -0,0 +1,6321 @@ +/*----------------------------------------------------------------------------/ +/ FatFs - Generic FAT Filesystem Module R0.13 / +/-----------------------------------------------------------------------------/ +/ +/ Copyright (C) 2017, ChaN, all right reserved. +/ +/ FatFs module is an open source software. Redistribution and use of FatFs in +/ source and binary forms, with or without modification, are permitted provided +/ that the following condition is met: +/ +/ 1. Redistributions of source code must retain the above copyright notice, +/ this condition and the following disclaimer. +/ +/ This software is provided by the copyright holder and contributors "AS IS" +/ and any warranties related to this software are DISCLAIMED. +/ The copyright owner or contributors be NOT LIABLE for any damages caused +/ by use of this software. +/ +/----------------------------------------------------------------------------*/ +#include "ff.h" /* Declarations of FatFs API */ +#include "diskio.h" /* Declarations of device I/O functions */ +/*-------------------------------------------------------------------------- + + Module Private Definitions + +---------------------------------------------------------------------------*/ + +#if FF_DEFINED != 87030 /* Revision ID */ +#error Wrong include file (ff.h). +#endif + + +/* ASCII code support macros */ +#define IsUpper(c) ((c) >= 'A' && (c) <= 'Z') +#define IsLower(c) ((c) >= 'a' && (c) <= 'z') +#define IsDigit(c) ((c) >= '0' && (c) <= '9') + + +/* Additional file attribute bits for internal use */ +#define AM_VOL 0x08 /* Volume label */ +#define AM_LFN 0x0F /* LFN entry */ +#define AM_MASK 0x3F /* Mask of defined bits */ + + +/* Additional file access control and file status flags for internal use */ +#define FA_SEEKEND 0x20 /* Seek to end of the file on file open */ +#define FA_MODIFIED 0x40 /* File has been modified */ +#define FA_DIRTY 0x80 /* FIL.buf[] needs to be written-back */ + + +/* Name status flags in fn[11] */ +#define NSFLAG 11 /* Index of the name status byte */ +#define NS_LOSS 0x01 /* Out of 8.3 format */ +#define NS_LFN 0x02 /* Force to create LFN entry */ +#define NS_LAST 0x04 /* Last segment */ +#define NS_BODY 0x08 /* Lower case flag (body) */ +#define NS_EXT 0x10 /* Lower case flag (ext) */ +#define NS_DOT 0x20 /* Dot entry */ +#define NS_NOLFN 0x40 /* Do not find LFN */ +#define NS_NONAME 0x80 /* Not followed */ + + +/* Limits and boundaries */ +#define MAX_DIR 0x200000 /* Max size of FAT directory */ +#define MAX_DIR_EX 0x10000000 /* Max size of exFAT directory */ +#define MAX_FAT12 0xFF5 /* Max FAT12 clusters (differs from specs, but correct for real DOS/Windows behavior) */ +#define MAX_FAT16 0xFFF5 /* Max FAT16 clusters (differs from specs, but correct for real DOS/Windows behavior) */ +#define MAX_FAT32 0x0FFFFFF5 /* Max FAT32 clusters (not specified, practical limit) */ +#define MAX_EXFAT 0x7FFFFFFD /* Max exFAT clusters (differs from specs, implementation limit) */ + + +/* FatFs refers the FAT structure as simple byte array instead of structure member +/ because the C structure is not binary compatible between different platforms */ + +#define BS_JmpBoot 0 /* x86 jump instruction (3-byte) */ +#define BS_OEMName 3 /* OEM name (8-byte) */ +#define BPB_BytsPerSec 11 /* Sector size [byte] (WORD) */ +#define BPB_SecPerClus 13 /* Cluster size [sector] (BYTE) */ +#define BPB_RsvdSecCnt 14 /* Size of reserved area [sector] (WORD) */ +#define BPB_NumFATs 16 /* Number of FATs (BYTE) */ +#define BPB_RootEntCnt 17 /* Size of root directory area for FAT [entry] (WORD) */ +#define BPB_TotSec16 19 /* Volume size (16-bit) [sector] (WORD) */ +#define BPB_Media 21 /* Media descriptor byte (BYTE) */ +#define BPB_FATSz16 22 /* FAT size (16-bit) [sector] (WORD) */ +#define BPB_SecPerTrk 24 /* Number of sectors per track for int13h [sector] (WORD) */ +#define BPB_NumHeads 26 /* Number of heads for int13h (WORD) */ +#define BPB_HiddSec 28 /* Volume offset from top of the drive (DWORD) */ +#define BPB_TotSec32 32 /* Volume size (32-bit) [sector] (DWORD) */ +#define BS_DrvNum 36 /* Physical drive number for int13h (BYTE) */ +#define BS_NTres 37 /* WindowsNT error flag (BYTE) */ +#define BS_BootSig 38 /* Extended boot signature (BYTE) */ +#define BS_VolID 39 /* Volume serial number (DWORD) */ +#define BS_VolLab 43 /* Volume label string (8-byte) */ +#define BS_FilSysType 54 /* Filesystem type string (8-byte) */ +#define BS_BootCode 62 /* Boot code (448-byte) */ +#define BS_55AA 510 /* Signature word (WORD) */ + +#define BPB_FATSz32 36 /* FAT32: FAT size [sector] (DWORD) */ +#define BPB_ExtFlags32 40 /* FAT32: Extended flags (WORD) */ +#define BPB_FSVer32 42 /* FAT32: Filesystem version (WORD) */ +#define BPB_RootClus32 44 /* FAT32: Root directory cluster (DWORD) */ +#define BPB_FSInfo32 48 /* FAT32: Offset of FSINFO sector (WORD) */ +#define BPB_BkBootSec32 50 /* FAT32: Offset of backup boot sector (WORD) */ +#define BS_DrvNum32 64 /* FAT32: Physical drive number for int13h (BYTE) */ +#define BS_NTres32 65 /* FAT32: Error flag (BYTE) */ +#define BS_BootSig32 66 /* FAT32: Extended boot signature (BYTE) */ +#define BS_VolID32 67 /* FAT32: Volume serial number (DWORD) */ +#define BS_VolLab32 71 /* FAT32: Volume label string (8-byte) */ +#define BS_FilSysType32 82 /* FAT32: Filesystem type string (8-byte) */ +#define BS_BootCode32 90 /* FAT32: Boot code (420-byte) */ + +#define BPB_ZeroedEx 11 /* exFAT: MBZ field (53-byte) */ +#define BPB_VolOfsEx 64 /* exFAT: Volume offset from top of the drive [sector] (QWORD) */ +#define BPB_TotSecEx 72 /* exFAT: Volume size [sector] (QWORD) */ +#define BPB_FatOfsEx 80 /* exFAT: FAT offset from top of the volume [sector] (DWORD) */ +#define BPB_FatSzEx 84 /* exFAT: FAT size [sector] (DWORD) */ +#define BPB_DataOfsEx 88 /* exFAT: Data offset from top of the volume [sector] (DWORD) */ +#define BPB_NumClusEx 92 /* exFAT: Number of clusters (DWORD) */ +#define BPB_RootClusEx 96 /* exFAT: Root directory start cluster (DWORD) */ +#define BPB_VolIDEx 100 /* exFAT: Volume serial number (DWORD) */ +#define BPB_FSVerEx 104 /* exFAT: Filesystem version (WORD) */ +#define BPB_VolFlagEx 106 /* exFAT: Volume flags (BYTE) */ +#define BPB_ActFatEx 107 /* exFAT: Active FAT flags (BYTE) */ +#define BPB_BytsPerSecEx 108 /* exFAT: Log2 of sector size in unit of byte (BYTE) */ +#define BPB_SecPerClusEx 109 /* exFAT: Log2 of cluster size in unit of sector (BYTE) */ +#define BPB_NumFATsEx 110 /* exFAT: Number of FATs (BYTE) */ +#define BPB_DrvNumEx 111 /* exFAT: Physical drive number for int13h (BYTE) */ +#define BPB_PercInUseEx 112 /* exFAT: Percent in use (BYTE) */ +#define BPB_RsvdEx 113 /* exFAT: Reserved (7-byte) */ +#define BS_BootCodeEx 120 /* exFAT: Boot code (390-byte) */ + +#define DIR_Name 0 /* Short file name (11-byte) */ +#define DIR_Attr 11 /* Attribute (BYTE) */ +#define DIR_NTres 12 /* Lower case flag (BYTE) */ +#define DIR_CrtTime10 13 /* Created time sub-second (BYTE) */ +#define DIR_CrtTime 14 /* Created time (DWORD) */ +#define DIR_LstAccDate 18 /* Last accessed date (WORD) */ +#define DIR_FstClusHI 20 /* Higher 16-bit of first cluster (WORD) */ +#define DIR_ModTime 22 /* Modified time (DWORD) */ +#define DIR_FstClusLO 26 /* Lower 16-bit of first cluster (WORD) */ +#define DIR_FileSize 28 /* File size (DWORD) */ +#define LDIR_Ord 0 /* LFN: LFN order and LLE flag (BYTE) */ +#define LDIR_Attr 11 /* LFN: LFN attribute (BYTE) */ +#define LDIR_Type 12 /* LFN: Entry type (BYTE) */ +#define LDIR_Chksum 13 /* LFN: Checksum of the SFN (BYTE) */ +#define LDIR_FstClusLO 26 /* LFN: MBZ field (WORD) */ +#define XDIR_Type 0 /* exFAT: Type of exFAT directory entry (BYTE) */ +#define XDIR_NumLabel 1 /* exFAT: Number of volume label characters (BYTE) */ +#define XDIR_Label 2 /* exFAT: Volume label (11-WORD) */ +#define XDIR_CaseSum 4 /* exFAT: Sum of case conversion table (DWORD) */ +#define XDIR_NumSec 1 /* exFAT: Number of secondary entries (BYTE) */ +#define XDIR_SetSum 2 /* exFAT: Sum of the set of directory entries (WORD) */ +#define XDIR_Attr 4 /* exFAT: File attribute (WORD) */ +#define XDIR_CrtTime 8 /* exFAT: Created time (DWORD) */ +#define XDIR_ModTime 12 /* exFAT: Modified time (DWORD) */ +#define XDIR_AccTime 16 /* exFAT: Last accessed time (DWORD) */ +#define XDIR_CrtTime10 20 /* exFAT: Created time subsecond (BYTE) */ +#define XDIR_ModTime10 21 /* exFAT: Modified time subsecond (BYTE) */ +#define XDIR_CrtTZ 22 /* exFAT: Created timezone (BYTE) */ +#define XDIR_ModTZ 23 /* exFAT: Modified timezone (BYTE) */ +#define XDIR_AccTZ 24 /* exFAT: Last accessed timezone (BYTE) */ +#define XDIR_GenFlags 33 /* exFAT: General secondary flags (BYTE) */ +#define XDIR_NumName 35 /* exFAT: Number of file name characters (BYTE) */ +#define XDIR_NameHash 36 /* exFAT: Hash of file name (WORD) */ +#define XDIR_ValidFileSize 40 /* exFAT: Valid file size (QWORD) */ +#define XDIR_FstClus 52 /* exFAT: First cluster of the file data (DWORD) */ +#define XDIR_FileSize 56 /* exFAT: File/Directory size (QWORD) */ + +#define SZDIRE 32 /* Size of a directory entry */ +#define DDEM 0xE5 /* Deleted directory entry mark set to DIR_Name[0] */ +#define RDDEM 0x05 /* Replacement of the character collides with DDEM */ +#define LLEF 0x40 /* Last long entry flag in LDIR_Ord */ + +#define FSI_LeadSig 0 /* FAT32 FSI: Leading signature (DWORD) */ +#define FSI_StrucSig 484 /* FAT32 FSI: Structure signature (DWORD) */ +#define FSI_Free_Count 488 /* FAT32 FSI: Number of free clusters (DWORD) */ +#define FSI_Nxt_Free 492 /* FAT32 FSI: Last allocated cluster (DWORD) */ + +#define MBR_Table 446 /* MBR: Offset of partition table in the MBR */ +#define SZ_PTE 16 /* MBR: Size of a partition table entry */ +#define PTE_Boot 0 /* MBR PTE: Boot indicator */ +#define PTE_StHead 1 /* MBR PTE: Start head */ +#define PTE_StSec 2 /* MBR PTE: Start sector */ +#define PTE_StCyl 3 /* MBR PTE: Start cylinder */ +#define PTE_System 4 /* MBR PTE: System ID */ +#define PTE_EdHead 5 /* MBR PTE: End head */ +#define PTE_EdSec 6 /* MBR PTE: End sector */ +#define PTE_EdCyl 7 /* MBR PTE: End cylinder */ +#define PTE_StLba 8 /* MBR PTE: Start in LBA */ +#define PTE_SizLba 12 /* MBR PTE: Size in LBA */ + + +/* Post process after fatal error on file operation */ +#define ABORT(fs, res) { fp->err = (BYTE)(res); LEAVE_FF(fs, res); } + + +/* Reentrancy related */ +#if FF_FS_REENTRANT +#if FF_USE_LFN == 1 +#error Static LFN work area cannot be used at thread-safe configuration +#endif +#define LEAVE_FF(fs, res) { unlock_fs(fs, res); return res; } +#else +#define LEAVE_FF(fs, res) return res +#endif + + +/* Definitions of volume - partition conversion */ +#if FF_MULTI_PARTITION +#define LD2PD(vol) VolToPart[vol].pd /* Get physical drive number */ +#define LD2PT(vol) VolToPart[vol].pt /* Get partition index */ +#else +#define LD2PD(vol) (BYTE)(vol) /* Each logical drive is bound to the same physical drive number */ +#define LD2PT(vol) 0 /* Find first valid partition or in SFD */ +#endif + + +/* Definitions of sector size */ +#if (FF_MAX_SS < FF_MIN_SS) || (FF_MAX_SS != 512 && FF_MAX_SS != 1024 && FF_MAX_SS != 2048 && FF_MAX_SS != 4096) || (FF_MIN_SS != 512 && FF_MIN_SS != 1024 && FF_MIN_SS != 2048 && FF_MIN_SS != 4096) +#error Wrong sector size configuration +#endif +#if FF_MAX_SS == FF_MIN_SS +#define SS(fs) ((UINT)FF_MAX_SS) /* Fixed sector size */ +#else +#define SS(fs) ((fs)->ssize) /* Variable sector size */ +#endif + + +/* Timestamp */ +#if FF_FS_NORTC == 1 +#if FF_NORTC_YEAR < 1980 || FF_NORTC_YEAR > 2107 || FF_NORTC_MON < 1 || FF_NORTC_MON > 12 || FF_NORTC_MDAY < 1 || FF_NORTC_MDAY > 31 +#error Invalid FF_FS_NORTC settings +#endif +#define GET_FATTIME() ((DWORD)(FF_NORTC_YEAR - 1980) << 25 | (DWORD)FF_NORTC_MON << 21 | (DWORD)FF_NORTC_MDAY << 16) +#else +#define GET_FATTIME() get_fattime() +#endif + + +/* File lock controls */ +#if FF_FS_LOCK != 0 +#if FF_FS_READONLY +#error FF_FS_LOCK must be 0 at read-only configuration +#endif +typedef struct { + FATFS *fs; /* Object ID 1, volume (NULL:blank entry) */ + DWORD clu; /* Object ID 2, containing directory (0:root) */ + DWORD ofs; /* Object ID 3, offset in the directory */ + WORD ctr; /* Object open counter, 0:none, 0x01..0xFF:read mode open count, 0x100:write mode */ +} FILESEM; +#endif + + +/* SBCS up-case tables (\x80-\xFF) */ +#define TBL_CT437 {0x80,0x9A,0x45,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F, \ + 0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,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, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT720 {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ + 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,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, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT737 {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ + 0x90,0x92,0x92,0x93,0x94,0x95,0x96,0x97,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87, \ + 0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F,0x90,0x91,0xAA,0x92,0x93,0x94,0x95,0x96, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,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, \ + 0x97,0xEA,0xEB,0xEC,0xE4,0xED,0xEE,0xEF,0xF5,0xF0,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT771 {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ + 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,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,0xDC,0xDE,0xDE, \ + 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0xF0,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF8,0xFA,0xFA,0xFC,0xFC,0xFE,0xFF} +#define TBL_CT775 {0x80,0x9A,0x91,0xA0,0x8E,0x95,0x8F,0x80,0xAD,0xED,0x8A,0x8A,0xA1,0x8D,0x8E,0x8F, \ + 0x90,0x92,0x92,0xE2,0x99,0x95,0x96,0x97,0x97,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ + 0xA0,0xA1,0xE0,0xA3,0xA3,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xB5,0xB6,0xB7,0xB8,0xBD,0xBE,0xC6,0xC7,0xA5,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE3,0xE8,0xE8,0xEA,0xEA,0xEE,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT850 {0x43,0x55,0x45,0x41,0x41,0x41,0x41,0x43,0x45,0x45,0x45,0x49,0x49,0x49,0x41,0x41, \ + 0x45,0x92,0x92,0x4F,0x4F,0x4F,0x55,0x55,0x59,0x4F,0x55,0x4F,0x9C,0x4F,0x9E,0x9F, \ + 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0x41,0x41,0x41,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0x41,0x41,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD1,0xD1,0x45,0x45,0x45,0x49,0x49,0x49,0x49,0xD9,0xDA,0xDB,0xDC,0xDD,0x49,0xDF, \ + 0x4F,0xE1,0x4F,0x4F,0x4F,0x4F,0xE6,0xE8,0xE8,0x55,0x55,0x55,0x59,0x59,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT852 {0x80,0x9A,0x90,0xB6,0x8E,0xDE,0x8F,0x80,0x9D,0xD3,0x8A,0x8A,0xD7,0x8D,0x8E,0x8F, \ + 0x90,0x91,0x91,0xE2,0x99,0x95,0x95,0x97,0x97,0x99,0x9A,0x9B,0x9B,0x9D,0x9E,0xAC, \ + 0xB5,0xD6,0xE0,0xE9,0xA4,0xA4,0xA6,0xA6,0xA8,0xA8,0xAA,0x8D,0xAC,0xB8,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBD,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC6,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD1,0xD1,0xD2,0xD3,0xD2,0xD5,0xD6,0xD7,0xB7,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE3,0xD5,0xE6,0xE6,0xE8,0xE9,0xE8,0xEB,0xED,0xED,0xDD,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xEB,0xFC,0xFC,0xFE,0xFF} +#define TBL_CT855 {0x81,0x81,0x83,0x83,0x85,0x85,0x87,0x87,0x89,0x89,0x8B,0x8B,0x8D,0x8D,0x8F,0x8F, \ + 0x91,0x91,0x93,0x93,0x95,0x95,0x97,0x97,0x99,0x99,0x9B,0x9B,0x9D,0x9D,0x9F,0x9F, \ + 0xA1,0xA1,0xA3,0xA3,0xA5,0xA5,0xA7,0xA7,0xA9,0xA9,0xAB,0xAB,0xAD,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB6,0xB6,0xB8,0xB8,0xB9,0xBA,0xBB,0xBC,0xBE,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD1,0xD1,0xD3,0xD3,0xD5,0xD5,0xD7,0xD7,0xDD,0xD9,0xDA,0xDB,0xDC,0xDD,0xE0,0xDF, \ + 0xE0,0xE2,0xE2,0xE4,0xE4,0xE6,0xE6,0xE8,0xE8,0xEA,0xEA,0xEC,0xEC,0xEE,0xEE,0xEF, \ + 0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF8,0xFA,0xFA,0xFC,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT857 {0x80,0x9A,0x90,0xB6,0x8E,0xB7,0x8F,0x80,0xD2,0xD3,0xD4,0xD8,0xD7,0x49,0x8E,0x8F, \ + 0x90,0x92,0x92,0xE2,0x99,0xE3,0xEA,0xEB,0x98,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9E, \ + 0xB5,0xD6,0xE0,0xE9,0xA5,0xA5,0xA6,0xA6,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC7,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD0,0xD1,0xD2,0xD3,0xD4,0x49,0xD6,0xD7,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0xDF, \ + 0xE0,0xE1,0xE2,0xE3,0xE5,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xDE,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT860 {0x80,0x9A,0x90,0x8F,0x8E,0x91,0x86,0x80,0x89,0x89,0x92,0x8B,0x8C,0x98,0x8E,0x8F, \ + 0x90,0x91,0x92,0x8C,0x99,0xA9,0x96,0x9D,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x86,0x8B,0x9F,0x96,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,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, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT861 {0x80,0x9A,0x90,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x8B,0x8B,0x8D,0x8E,0x8F, \ + 0x90,0x92,0x92,0x4F,0x99,0x8D,0x55,0x97,0x97,0x99,0x9A,0x9D,0x9C,0x9D,0x9E,0x9F, \ + 0xA4,0xA5,0xA6,0xA7,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,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, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT862 {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ + 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,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, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT863 {0x43,0x55,0x45,0x41,0x41,0x41,0x86,0x43,0x45,0x45,0x45,0x49,0x49,0x8D,0x41,0x8F, \ + 0x45,0x45,0x45,0x4F,0x45,0x49,0x55,0x55,0x98,0x4F,0x55,0x9B,0x9C,0x55,0x55,0x9F, \ + 0xA0,0xA1,0x4F,0x55,0xA4,0xA5,0xA6,0xA7,0x49,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,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, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT864 {0x80,0x9A,0x45,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F, \ + 0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,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, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT865 {0x80,0x9A,0x90,0x41,0x8E,0x41,0x8F,0x80,0x45,0x45,0x45,0x49,0x49,0x49,0x8E,0x8F, \ + 0x90,0x92,0x92,0x4F,0x99,0x4F,0x55,0x55,0x59,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x41,0x49,0x4F,0x55,0xA5,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,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, \ + 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF, \ + 0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF7,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT866 {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ + 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,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, \ + 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x9B,0x9C,0x9D,0x9E,0x9F, \ + 0xF0,0xF0,0xF2,0xF2,0xF4,0xF4,0xF6,0xF6,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF} +#define TBL_CT869 {0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8A,0x8B,0x8C,0x8D,0x8E,0x8F, \ + 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9A,0x86,0x9C,0x8D,0x8F,0x90, \ + 0x91,0x90,0x92,0x95,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF, \ + 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5,0xB6,0xB7,0xB8,0xB9,0xBA,0xBB,0xBC,0xBD,0xBE,0xBF, \ + 0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF, \ + 0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xA4,0xA5,0xA6,0xD9,0xDA,0xDB,0xDC,0xA7,0xA8,0xDF, \ + 0xA9,0xAA,0xAC,0xAD,0xB5,0xB6,0xB7,0xB8,0xBD,0xBE,0xC6,0xC7,0xCF,0xCF,0xD0,0xEF, \ + 0xF0,0xF1,0xD1,0xD2,0xD3,0xF5,0xD4,0xF7,0xF8,0xF9,0xD5,0x96,0x95,0x98,0xFE,0xFF} + + +/* DBCS code range |----- 1st byte -----| |----------- 2nd byte -----------| */ +#define TBL_DC932 {0x81, 0x9F, 0xE0, 0xFC, 0x40, 0x7E, 0x80, 0xFC, 0x00, 0x00} +#define TBL_DC936 {0x81, 0xFE, 0x00, 0x00, 0x40, 0x7E, 0x80, 0xFE, 0x00, 0x00} +#define TBL_DC949 {0x81, 0xFE, 0x00, 0x00, 0x41, 0x5A, 0x61, 0x7A, 0x81, 0xFE} +#define TBL_DC950 {0x81, 0xFE, 0x00, 0x00, 0x40, 0x7E, 0xA1, 0xFE, 0x00, 0x00} + + +/* Macros for table definitions */ +#define MERGE_2STR(a, b) a ## b +#define MKCVTBL(hd, cp) MERGE_2STR(hd, cp) + + + + +/*-------------------------------------------------------------------------- + + Module Private Work Area + +---------------------------------------------------------------------------*/ +/* Remark: Variables defined here without initial value shall be guaranteed +/ zero/null at start-up. If not, the linker option or start-up routine is +/ not compliance with C standard. */ + +/*--------------------------------*/ +/* File/Volume controls */ +/*--------------------------------*/ + +#if FF_VOLUMES < 1 || FF_VOLUMES > 10 +#error Wrong FF_VOLUMES setting +#endif +static FATFS *FatFs[FF_VOLUMES]; /* Pointer to the filesystem objects (logical drives) */ +static WORD Fsid; /* File system mount ID */ + +#if FF_FS_RPATH != 0 && FF_VOLUMES >= 2 +static BYTE CurrVol; /* Current drive */ +#endif + +#if FF_FS_LOCK != 0 +static FILESEM Files[FF_FS_LOCK]; /* Open object lock semaphores */ +#endif + + +/*--------------------------------*/ +/* LFN/Directory working buffer */ +/*--------------------------------*/ + +#if FF_USE_LFN == 0 /* Non-LFN configuration */ +#define DEF_NAMBUF +#define INIT_NAMBUF(fs) +#define FREE_NAMBUF() + +#else /* LFN configurations */ +#if FF_MAX_LFN < 12 || FF_MAX_LFN > 255 +#error Wrong FF_MAX_LFN setting +#endif +static const BYTE LfnOfs[] = {1,3,5,7,9,14,16,18,20,22,24,28,30}; /* FAT: Offset of LFN characters in the directory entry */ +#define MAXDIRB(nc) ((nc + 44U) / 15 * SZDIRE) /* exFAT: Size of directory entry block scratchpad buffer needed for the max name length */ + +#if FF_USE_LFN == 1 /* LFN enabled with static working buffer */ +#if FF_FS_EXFAT +static BYTE DirBuf[MAXDIRB(FF_MAX_LFN)]; /* Directory entry block scratchpad buffer */ +#endif +static WCHAR LfnBuf[FF_MAX_LFN + 1]; /* LFN working buffer */ +#define DEF_NAMBUF +#define INIT_NAMBUF(fs) +#define FREE_NAMBUF() + +#elif FF_USE_LFN == 2 /* LFN enabled with dynamic working buffer on the stack */ +#if FF_FS_EXFAT +#define DEF_NAMBUF WCHAR lbuf[FF_MAX_LFN+1]; BYTE dbuf[MAXDIRB(FF_MAX_LFN)]; /* LFN working buffer and directory entry block scratchpad buffer */ +#define INIT_NAMBUF(fs) { (fs)->lfnbuf = lbuf; (fs)->dirbuf = dbuf; } +#define FREE_NAMBUF() +#else +#define DEF_NAMBUF WCHAR lbuf[FF_MAX_LFN+1]; /* LFN working buffer */ +#define INIT_NAMBUF(fs) { (fs)->lfnbuf = lbuf; } +#define FREE_NAMBUF() +#endif + +#elif FF_USE_LFN == 3 /* LFN enabled with dynamic working buffer on the heap */ +#if FF_FS_EXFAT +#define DEF_NAMBUF WCHAR *lfn; /* Pointer to LFN working buffer and directory entry block scratchpad buffer */ +#define INIT_NAMBUF(fs) { lfn = ff_memalloc((FF_MAX_LFN+1)*2 + MAXDIRB(FF_MAX_LFN)); if (!lfn) LEAVE_FF(fs, FR_NOT_ENOUGH_CORE); (fs)->lfnbuf = lfn; (fs)->dirbuf = (BYTE*)(lfn+FF_MAX_LFN+1); } +#define FREE_NAMBUF() ff_memfree(lfn) +#else +#define DEF_NAMBUF WCHAR *lfn; /* Pointer to LFN working buffer */ +#define INIT_NAMBUF(fs) { lfn = ff_memalloc((FF_MAX_LFN+1)*2); if (!lfn) LEAVE_FF(fs, FR_NOT_ENOUGH_CORE); (fs)->lfnbuf = lfn; } +#define FREE_NAMBUF() ff_memfree(lfn) +#endif + +#else +#error Wrong FF_USE_LFN setting + +#endif +#endif + + +/*--------------------------------*/ +/* Code conversion tables */ +/*--------------------------------*/ + +#if FF_CODE_PAGE == 0 /* Run-time code page configuration */ +#define CODEPAGE CodePage +static WORD CodePage; /* Current code page */ +static const BYTE *ExCvt, *DbcTbl; /* Pointer to current SBCS up-case table and DBCS code range table below */ +static const BYTE Ct437[] = TBL_CT437; +static const BYTE Ct720[] = TBL_CT720; +static const BYTE Ct737[] = TBL_CT737; +static const BYTE Ct771[] = TBL_CT771; +static const BYTE Ct775[] = TBL_CT775; +static const BYTE Ct850[] = TBL_CT850; +static const BYTE Ct852[] = TBL_CT852; +static const BYTE Ct855[] = TBL_CT855; +static const BYTE Ct857[] = TBL_CT857; +static const BYTE Ct860[] = TBL_CT860; +static const BYTE Ct861[] = TBL_CT861; +static const BYTE Ct862[] = TBL_CT862; +static const BYTE Ct863[] = TBL_CT863; +static const BYTE Ct864[] = TBL_CT864; +static const BYTE Ct865[] = TBL_CT865; +static const BYTE Ct866[] = TBL_CT866; +static const BYTE Ct869[] = TBL_CT869; +static const BYTE Dc932[] = TBL_DC932; +static const BYTE Dc936[] = TBL_DC936; +static const BYTE Dc949[] = TBL_DC949; +static const BYTE Dc950[] = TBL_DC950; + +#elif FF_CODE_PAGE < 900 /* Static code page configuration (SBCS) */ +#define CODEPAGE FF_CODE_PAGE +static const BYTE ExCvt[] = MKCVTBL(TBL_CT, FF_CODE_PAGE); + +#else /* Static code page configuration (DBCS) */ +#define CODEPAGE FF_CODE_PAGE +static const BYTE DbcTbl[] = MKCVTBL(TBL_DC, FF_CODE_PAGE); + +#endif + + + + +/*-------------------------------------------------------------------------- + + Module Private Functions + +---------------------------------------------------------------------------*/ + + +/*-----------------------------------------------------------------------*/ +/* Load/Store multi-byte word in the FAT structure */ +/*-----------------------------------------------------------------------*/ + +static +WORD ld_word (const BYTE* ptr) /* Load a 2-byte little-endian word */ +{ + WORD rv; + + rv = ptr[1]; + rv = rv << 8 | ptr[0]; + return rv; +} + +static +DWORD ld_dword (const BYTE* ptr) /* Load a 4-byte little-endian word */ +{ + DWORD rv; + + rv = ptr[3]; + rv = rv << 8 | ptr[2]; + rv = rv << 8 | ptr[1]; + rv = rv << 8 | ptr[0]; + return rv; +} + +#if FF_FS_EXFAT +static +QWORD ld_qword (const BYTE* ptr) /* Load an 8-byte little-endian word */ +{ + QWORD rv; + + rv = ptr[7]; + rv = rv << 8 | ptr[6]; + rv = rv << 8 | ptr[5]; + rv = rv << 8 | ptr[4]; + rv = rv << 8 | ptr[3]; + rv = rv << 8 | ptr[2]; + rv = rv << 8 | ptr[1]; + rv = rv << 8 | ptr[0]; + return rv; +} +#endif + +#if !FF_FS_READONLY +static +void st_word (BYTE* ptr, WORD val) /* Store a 2-byte word in little-endian */ +{ + *ptr++ = (BYTE)val; val >>= 8; + *ptr++ = (BYTE)val; +} + +static +void st_dword (BYTE* ptr, DWORD val) /* Store a 4-byte word in little-endian */ +{ + *ptr++ = (BYTE)val; val >>= 8; + *ptr++ = (BYTE)val; val >>= 8; + *ptr++ = (BYTE)val; val >>= 8; + *ptr++ = (BYTE)val; +} + +#if FF_FS_EXFAT +static +void st_qword (BYTE* ptr, QWORD val) /* Store an 8-byte word in little-endian */ +{ + *ptr++ = (BYTE)val; val >>= 8; + *ptr++ = (BYTE)val; val >>= 8; + *ptr++ = (BYTE)val; val >>= 8; + *ptr++ = (BYTE)val; val >>= 8; + *ptr++ = (BYTE)val; val >>= 8; + *ptr++ = (BYTE)val; val >>= 8; + *ptr++ = (BYTE)val; val >>= 8; + *ptr++ = (BYTE)val; +} +#endif +#endif /* !FF_FS_READONLY */ + + + +/*-----------------------------------------------------------------------*/ +/* String functions */ +/*-----------------------------------------------------------------------*/ + +/* Copy memory to memory */ +static +void mem_cpy (void* dst, const void* src, UINT cnt) +{ + BYTE *d = (BYTE*)dst; + const BYTE *s = (const BYTE*)src; + + if (cnt != 0) { + do { + *d++ = *s++; + } while (--cnt); + } +} + + +/* Fill memory block */ +static +void mem_set (void* dst, int val, UINT cnt) +{ + BYTE *d = (BYTE*)dst; + + do { + *d++ = (BYTE)val; + } while (--cnt); +} + + +/* Compare memory block */ +static +int mem_cmp (const void* dst, const void* src, UINT cnt) /* ZR:same, NZ:different */ +{ + const BYTE *d = (const BYTE *)dst, *s = (const BYTE *)src; + int r = 0; + + do { + r = *d++ - *s++; + } while (--cnt && r == 0); + + return r; +} + + +/* Check if chr is contained in the string */ +static +int chk_chr (const char* str, int chr) /* NZ:contained, ZR:not contained */ +{ + while (*str && *str != chr) str++; + return *str; +} + + +/* Test if the character is DBC 1st byte */ +static +int dbc_1st (BYTE c) +{ +#if FF_CODE_PAGE == 0 /* Variable code page */ + if (DbcTbl && c >= DbcTbl[0]) { + if (c <= DbcTbl[1]) return 1; /* 1st byte range 1 */ + if (c >= DbcTbl[2] && c <= DbcTbl[3]) return 1; /* 1st byte range 2 */ + } +#elif FF_CODE_PAGE >= 900 /* DBCS fixed code page */ + if (c >= DbcTbl[0]) { + if (c <= DbcTbl[1]) return 1; + if (c >= DbcTbl[2] && c <= DbcTbl[3]) return 1; + } +#else /* SBCS fixed code page */ + if (c) return 0; /* Always false */ +#endif + return 0; +} + + +/* Test if the character is DBC 2nd byte */ +static +int dbc_2nd (BYTE c) +{ +#if FF_CODE_PAGE == 0 /* Variable code page */ + if (DbcTbl && c >= DbcTbl[4]) { + if (c <= DbcTbl[5]) return 1; /* 2nd byte range 1 */ + if (c >= DbcTbl[6] && c <= DbcTbl[7]) return 1; /* 2nd byte range 2 */ + if (c >= DbcTbl[8] && c <= DbcTbl[9]) return 1; /* 2nd byte range 3 */ + } +#elif FF_CODE_PAGE >= 900 /* DBCD fixed code page */ + if (c >= DbcTbl[4]) { + if (c <= DbcTbl[5]) return 1; + if (c >= DbcTbl[6] && c <= DbcTbl[7]) return 1; + if (c >= DbcTbl[8] && c <= DbcTbl[9]) return 1; + } +#else /* SBCS fixed code page */ + if (c) return 0; /* Always false */ +#endif + return 0; +} + + + +#if FF_FS_REENTRANT +/*-----------------------------------------------------------------------*/ +/* Request/Release grant to access the volume */ +/*-----------------------------------------------------------------------*/ +static +int lock_fs ( /* 1:Ok, 0:timeout */ + FATFS* fs /* Filesystem object */ +) +{ + return ff_req_grant(fs->sobj); +} + + +static +void unlock_fs ( + FATFS* fs, /* Filesystem object */ + FRESULT res /* Result code to be returned */ +) +{ + if (fs && res != FR_NOT_ENABLED && res != FR_INVALID_DRIVE && res != FR_TIMEOUT) { + ff_rel_grant(fs->sobj); + } +} + +#endif + + + +#if FF_FS_LOCK != 0 +/*-----------------------------------------------------------------------*/ +/* File lock control functions */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT chk_lock ( /* Check if the file can be accessed */ + DIR* dp, /* Directory object pointing the file to be checked */ + int acc /* Desired access type (0:Read mode open, 1:Write mode open, 2:Delete or rename) */ +) +{ + UINT i, be; + + /* Search open object table for the object */ + be = 0; + for (i = 0; i < FF_FS_LOCK; i++) { + if (Files[i].fs) { /* Existing entry */ + if (Files[i].fs == dp->obj.fs && /* Check if the object matches with an open object */ + Files[i].clu == dp->obj.sclust && + Files[i].ofs == dp->dptr) break; + } else { /* Blank entry */ + be = 1; + } + } + if (i == FF_FS_LOCK) { /* The object has not been opened */ + return (!be && acc != 2) ? FR_TOO_MANY_OPEN_FILES : FR_OK; /* Is there a blank entry for new object? */ + } + + /* The object was opened. Reject any open against writing file and all write mode open */ + return (acc != 0 || Files[i].ctr == 0x100) ? FR_LOCKED : FR_OK; +} + + +static +int enq_lock (void) /* Check if an entry is available for a new object */ +{ + UINT i; + + for (i = 0; i < FF_FS_LOCK && Files[i].fs; i++) ; + return (i == FF_FS_LOCK) ? 0 : 1; +} + + +static +UINT inc_lock ( /* Increment object open counter and returns its index (0:Internal error) */ + DIR* dp, /* Directory object pointing the file to register or increment */ + int acc /* Desired access (0:Read, 1:Write, 2:Delete/Rename) */ +) +{ + UINT i; + + + for (i = 0; i < FF_FS_LOCK; i++) { /* Find the object */ + if (Files[i].fs == dp->obj.fs && + Files[i].clu == dp->obj.sclust && + Files[i].ofs == dp->dptr) break; + } + + if (i == FF_FS_LOCK) { /* Not opened. Register it as new. */ + for (i = 0; i < FF_FS_LOCK && Files[i].fs; i++) ; + if (i == FF_FS_LOCK) return 0; /* No free entry to register (int err) */ + Files[i].fs = dp->obj.fs; + Files[i].clu = dp->obj.sclust; + Files[i].ofs = dp->dptr; + Files[i].ctr = 0; + } + + if (acc && Files[i].ctr) return 0; /* Access violation (int err) */ + + Files[i].ctr = acc ? 0x100 : Files[i].ctr + 1; /* Set semaphore value */ + + return i + 1; /* Index number origin from 1 */ +} + + +static +FRESULT dec_lock ( /* Decrement object open counter */ + UINT i /* Semaphore index (1..) */ +) +{ + WORD n; + FRESULT res; + + + if (--i < FF_FS_LOCK) { /* Index number origin from 0 */ + n = Files[i].ctr; + if (n == 0x100) n = 0; /* If write mode open, delete the entry */ + if (n > 0) n--; /* Decrement read mode open count */ + Files[i].ctr = n; + if (n == 0) Files[i].fs = 0; /* Delete the entry if open count gets zero */ + res = FR_OK; + } else { + res = FR_INT_ERR; /* Invalid index nunber */ + } + return res; +} + + +static +void clear_lock ( /* Clear lock entries of the volume */ + FATFS *fs +) +{ + UINT i; + + for (i = 0; i < FF_FS_LOCK; i++) { + if (Files[i].fs == fs) Files[i].fs = 0; + } +} + +#endif /* FF_FS_LOCK != 0 */ + + + +/*-----------------------------------------------------------------------*/ +/* Move/Flush disk access window in the filesystem object */ +/*-----------------------------------------------------------------------*/ +#if !FF_FS_READONLY +static +FRESULT sync_window ( /* Returns FR_OK or FR_DISK_ERR */ + FATFS* fs /* Filesystem object */ +) +{ + FRESULT res = FR_OK; + + + if (fs->wflag) { /* Is the disk access window dirty */ + if (disk_write(fs->pdrv, fs->win, fs->winsect, 1) == RES_OK) { /* Write back the window */ + fs->wflag = 0; /* Clear window dirty flag */ + if (fs->winsect - fs->fatbase < fs->fsize) { /* Is it in the 1st FAT? */ + if (fs->n_fats == 2) disk_write(fs->pdrv, fs->win, fs->winsect + fs->fsize, 1); /* Reflect it to 2nd FAT if needed */ + } + } else { + res = FR_DISK_ERR; + } + } + return res; +} +#endif + + +static +FRESULT move_window ( /* Returns FR_OK or FR_DISK_ERR */ + FATFS* fs, /* Filesystem object */ + DWORD sector /* Sector number to make appearance in the fs->win[] */ +) +{ + FRESULT res = FR_OK; + + + if (sector != fs->winsect) { /* Window offset changed? */ +#if !FF_FS_READONLY + res = sync_window(fs); /* Write-back changes */ +#endif + if (res == FR_OK) { /* Fill sector window with new data */ + if (disk_read(fs->pdrv, fs->win, sector, 1) != RES_OK) { + sector = 0xFFFFFFFF; /* Invalidate window if read data is not valid */ + res = FR_DISK_ERR; + } + fs->winsect = sector; + } + } + return res; +} + + + + +#if !FF_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Synchronize filesystem and data on the storage */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT sync_fs ( /* Returns FR_OK or FR_DISK_ERR */ + FATFS* fs /* Filesystem object */ +) +{ + FRESULT res; + + + res = sync_window(fs); + if (res == FR_OK) { + if (fs->fs_type == FS_FAT32 && fs->fsi_flag == 1) { /* FAT32: Update FSInfo sector if needed */ + /* Create FSInfo structure */ + mem_set(fs->win, 0, SS(fs)); + st_word(fs->win + BS_55AA, 0xAA55); + st_dword(fs->win + FSI_LeadSig, 0x41615252); + st_dword(fs->win + FSI_StrucSig, 0x61417272); + st_dword(fs->win + FSI_Free_Count, fs->free_clst); + st_dword(fs->win + FSI_Nxt_Free, fs->last_clst); + /* Write it into the FSInfo sector */ + fs->winsect = fs->volbase + 1; + disk_write(fs->pdrv, fs->win, fs->winsect, 1); + fs->fsi_flag = 0; + } + /* Make sure that no pending write process in the lower layer */ + if (disk_ioctl(fs->pdrv, CTRL_SYNC, 0) != RES_OK) res = FR_DISK_ERR; + } + + return res; +} + +#endif + + + +/*-----------------------------------------------------------------------*/ +/* Get physical sector number from cluster number */ +/*-----------------------------------------------------------------------*/ + +static +DWORD clst2sect ( /* !=0:Sector number, 0:Failed (invalid cluster#) */ + FATFS* fs, /* Filesystem object */ + DWORD clst /* Cluster# to be converted */ +) +{ + clst -= 2; /* Cluster number is origin from 2 */ + if (clst >= fs->n_fatent - 2) return 0; /* Is it invalid cluster number? */ + return fs->database + fs->csize * clst; /* Start sector number of the cluster */ +} + + + + +/*-----------------------------------------------------------------------*/ +/* FAT access - Read value of a FAT entry */ +/*-----------------------------------------------------------------------*/ + +static +DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, 2..0x7FFFFFFF:Cluster status */ + FFOBJID* obj, /* Corresponding object */ + DWORD clst /* Cluster number to get the value */ +) +{ + UINT wc, bc; + DWORD val; + FATFS *fs = obj->fs; + + + if (clst < 2 || clst >= fs->n_fatent) { /* Check if in valid range */ + val = 1; /* Internal error */ + + } else { + val = 0xFFFFFFFF; /* Default value falls on disk error */ + + switch (fs->fs_type) { + case FS_FAT12 : + bc = (UINT)clst; bc += bc / 2; + if (move_window(fs, fs->fatbase + (bc / SS(fs))) != FR_OK) break; + wc = fs->win[bc++ % SS(fs)]; /* Get 1st byte of the entry */ + if (move_window(fs, fs->fatbase + (bc / SS(fs))) != FR_OK) break; + wc |= fs->win[bc % SS(fs)] << 8; /* Merge 2nd byte of the entry */ + val = (clst & 1) ? (wc >> 4) : (wc & 0xFFF); /* Adjust bit position */ + break; + + case FS_FAT16 : + if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 2))) != FR_OK) break; + val = ld_word(fs->win + clst * 2 % SS(fs)); /* Simple WORD array */ + break; + + case FS_FAT32 : + if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))) != FR_OK) break; + val = ld_dword(fs->win + clst * 4 % SS(fs)) & 0x0FFFFFFF; /* Simple DWORD array but mask out upper 4 bits */ + break; +#if FF_FS_EXFAT + case FS_EXFAT : + if (obj->objsize != 0) { + DWORD cofs = clst - obj->sclust; /* Offset from start cluster */ + DWORD clen = (DWORD)((obj->objsize - 1) / SS(fs)) / fs->csize; /* Number of clusters - 1 */ + + if (obj->stat == 2 && cofs <= clen) { /* Is it a contiguous chain? */ + val = (cofs == clen) ? 0x7FFFFFFF : clst + 1; /* No data on the FAT, generate the value */ + break; + } + if (obj->stat == 3 && cofs < obj->n_cont) { /* Is it in the 1st fragment? */ + val = clst + 1; /* Generate the value */ + break; + } + if (obj->stat != 2) { /* Get value from FAT if FAT chain is valid */ + if (obj->n_frag != 0) { /* Is it on the growing edge? */ + val = 0x7FFFFFFF; /* Generate EOC */ + } else { + if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))) != FR_OK) break; + val = ld_dword(fs->win + clst * 4 % SS(fs)) & 0x7FFFFFFF; + } + break; + } + } + /* go to default */ +#endif + default: + val = 1; /* Internal error */ + } + } + + return val; +} + + + + +#if !FF_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* FAT access - Change value of a FAT entry */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT put_fat ( /* FR_OK(0):succeeded, !=0:error */ + FATFS* fs, /* Corresponding filesystem object */ + DWORD clst, /* FAT index number (cluster number) to be changed */ + DWORD val /* New value to be set to the entry */ +) +{ + UINT bc; + BYTE *p; + FRESULT res = FR_INT_ERR; + + + if (clst >= 2 && clst < fs->n_fatent) { /* Check if in valid range */ + switch (fs->fs_type) { + case FS_FAT12 : + bc = (UINT)clst; bc += bc / 2; /* bc: byte offset of the entry */ + res = move_window(fs, fs->fatbase + (bc / SS(fs))); + if (res != FR_OK) break; + p = fs->win + bc++ % SS(fs); + *p = (clst & 1) ? ((*p & 0x0F) | ((BYTE)val << 4)) : (BYTE)val; /* Put 1st byte */ + fs->wflag = 1; + res = move_window(fs, fs->fatbase + (bc / SS(fs))); + if (res != FR_OK) break; + p = fs->win + bc % SS(fs); + *p = (clst & 1) ? (BYTE)(val >> 4) : ((*p & 0xF0) | ((BYTE)(val >> 8) & 0x0F)); /* Put 2nd byte */ + fs->wflag = 1; + break; + + case FS_FAT16 : + res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 2))); + if (res != FR_OK) break; + st_word(fs->win + clst * 2 % SS(fs), (WORD)val); /* Simple WORD array */ + fs->wflag = 1; + break; + + case FS_FAT32 : +#if FF_FS_EXFAT + case FS_EXFAT : +#endif + res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))); + if (res != FR_OK) break; + if (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) { + val = (val & 0x0FFFFFFF) | (ld_dword(fs->win + clst * 4 % SS(fs)) & 0xF0000000); + } + st_dword(fs->win + clst * 4 % SS(fs), val); + fs->wflag = 1; + break; + } + } + return res; +} + +#endif /* !FF_FS_READONLY */ + + + + +#if FF_FS_EXFAT && !FF_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* exFAT: Accessing FAT and Allocation Bitmap */ +/*-----------------------------------------------------------------------*/ + +/*--------------------------------------*/ +/* Find a contiguous free cluster block */ +/*--------------------------------------*/ + +static +DWORD find_bitmap ( /* 0:Not found, 2..:Cluster block found, 0xFFFFFFFF:Disk error */ + FATFS* fs, /* Filesystem object */ + DWORD clst, /* Cluster number to scan from */ + DWORD ncl /* Number of contiguous clusters to find (1..) */ +) +{ + BYTE bm, bv; + UINT i; + DWORD val, scl, ctr; + + + clst -= 2; /* The first bit in the bitmap corresponds to cluster #2 */ + if (clst >= fs->n_fatent - 2) clst = 0; + scl = val = clst; ctr = 0; + for (;;) { + if (move_window(fs, fs->database + val / 8 / SS(fs)) != FR_OK) return 0xFFFFFFFF; /* (assuming bitmap is located top of the cluster heap) */ + i = val / 8 % SS(fs); bm = 1 << (val % 8); + do { + do { + bv = fs->win[i] & bm; bm <<= 1; /* Get bit value */ + if (++val >= fs->n_fatent - 2) { /* Next cluster (with wrap-around) */ + val = 0; bm = 0; i = SS(fs); + } + if (!bv) { /* Is it a free cluster? */ + if (++ctr == ncl) return scl + 2; /* Check if run length is sufficient for required */ + } else { + scl = val; ctr = 0; /* Encountered a cluster in-use, restart to scan */ + } + if (val == clst) return 0; /* All cluster scanned? */ + } while (bm); + bm = 1; + } while (++i < SS(fs)); + } +} + + +/*----------------------------------------*/ +/* Set/Clear a block of allocation bitmap */ +/*----------------------------------------*/ + +static +FRESULT change_bitmap ( + FATFS* fs, /* Filesystem object */ + DWORD clst, /* Cluster number to change from */ + DWORD ncl, /* Number of clusters to be changed */ + int bv /* bit value to be set (0 or 1) */ +) +{ + BYTE bm; + UINT i; + DWORD sect; + + + clst -= 2; /* The first bit corresponds to cluster #2 */ + sect = fs->database + clst / 8 / SS(fs); /* Sector address (assuming bitmap is located top of the cluster heap) */ + i = clst / 8 % SS(fs); /* Byte offset in the sector */ + bm = 1 << (clst % 8); /* Bit mask in the byte */ + for (;;) { + if (move_window(fs, sect++) != FR_OK) return FR_DISK_ERR; + do { + do { + if (bv == (int)((fs->win[i] & bm) != 0)) return FR_INT_ERR; /* Is the bit expected value? */ + fs->win[i] ^= bm; /* Flip the bit */ + fs->wflag = 1; + if (--ncl == 0) return FR_OK; /* All bits processed? */ + } while (bm <<= 1); /* Next bit */ + bm = 1; + } while (++i < SS(fs)); /* Next byte */ + i = 0; + } +} + + +/*---------------------------------------------*/ +/* Fill the first fragment of the FAT chain */ +/*---------------------------------------------*/ + +static +FRESULT fill_first_frag ( + FFOBJID* obj /* Pointer to the corresponding object */ +) +{ + FRESULT res; + DWORD cl, n; + + + if (obj->stat == 3) { /* Has the object been changed 'fragmented' in this session? */ + for (cl = obj->sclust, n = obj->n_cont; n; cl++, n--) { /* Create cluster chain on the FAT */ + res = put_fat(obj->fs, cl, cl + 1); + if (res != FR_OK) return res; + } + obj->stat = 0; /* Change status 'FAT chain is valid' */ + } + return FR_OK; +} + + +/*---------------------------------------------*/ +/* Fill the last fragment of the FAT chain */ +/*---------------------------------------------*/ + +static +FRESULT fill_last_frag ( + FFOBJID* obj, /* Pointer to the corresponding object */ + DWORD lcl, /* Last cluster of the fragment */ + DWORD term /* Value to set the last FAT entry */ +) +{ + FRESULT res; + + + while (obj->n_frag > 0) { /* Create the last chain on the FAT */ + res = put_fat(obj->fs, lcl - obj->n_frag + 1, (obj->n_frag > 1) ? lcl - obj->n_frag + 2 : term); + if (res != FR_OK) return res; + obj->n_frag--; + } + return FR_OK; +} + +#endif /* FF_FS_EXFAT && !FF_FS_READONLY */ + + + +#if !FF_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* FAT handling - Remove a cluster chain */ +/*-----------------------------------------------------------------------*/ +static +FRESULT remove_chain ( /* FR_OK(0):succeeded, !=0:error */ + FFOBJID* obj, /* Corresponding object */ + DWORD clst, /* Cluster to remove a chain from */ + DWORD pclst /* Previous cluster of clst (0:entire chain) */ +) +{ + FRESULT res = FR_OK; + DWORD nxt; + FATFS *fs = obj->fs; +#if FF_FS_EXFAT || FF_USE_TRIM + DWORD scl = clst, ecl = clst; +#endif +#if FF_USE_TRIM + DWORD rt[2]; +#endif + + if (clst < 2 || clst >= fs->n_fatent) return FR_INT_ERR; /* Check if in valid range */ + + /* Mark the previous cluster 'EOC' on the FAT if it exists */ + if (pclst != 0 && (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT || obj->stat != 2)) { + res = put_fat(fs, pclst, 0xFFFFFFFF); + if (res != FR_OK) return res; + } + + /* Remove the chain */ + do { + nxt = get_fat(obj, clst); /* Get cluster status */ + if (nxt == 0) break; /* Empty cluster? */ + if (nxt == 1) return FR_INT_ERR; /* Internal error? */ + if (nxt == 0xFFFFFFFF) return FR_DISK_ERR; /* Disk error? */ + if (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) { + res = put_fat(fs, clst, 0); /* Mark the cluster 'free' on the FAT */ + if (res != FR_OK) return res; + } + if (fs->free_clst < fs->n_fatent - 2) { /* Update FSINFO */ + fs->free_clst++; + fs->fsi_flag |= 1; + } +#if FF_FS_EXFAT || FF_USE_TRIM + if (ecl + 1 == nxt) { /* Is next cluster contiguous? */ + ecl = nxt; + } else { /* End of contiguous cluster block */ +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { + res = change_bitmap(fs, scl, ecl - scl + 1, 0); /* Mark the cluster block 'free' on the bitmap */ + if (res != FR_OK) return res; + } +#endif +#if FF_USE_TRIM + rt[0] = clst2sect(fs, scl); /* Start of data area freed */ + rt[1] = clst2sect(fs, ecl) + fs->csize - 1; /* End of data area freed */ + disk_ioctl(fs->pdrv, CTRL_TRIM, rt); /* Inform device the data in the block is no longer needed */ +#endif + scl = ecl = nxt; + } +#endif + clst = nxt; /* Next cluster */ + } while (clst < fs->n_fatent); /* Repeat while not the last link */ + +#if FF_FS_EXFAT + /* Some post processes for chain status */ + if (fs->fs_type == FS_EXFAT) { + if (pclst == 0) { /* Has the entire chain been removed? */ + obj->stat = 0; /* Change the chain status 'initial' */ + } else { + if (obj->stat == 0) { /* Is it a fragmented chain from the beginning of this session? */ + clst = obj->sclust; /* Follow the chain to check if it gets contiguous */ + while (clst != pclst) { + nxt = get_fat(obj, clst); + if (nxt < 2) return FR_INT_ERR; + if (nxt == 0xFFFFFFFF) return FR_DISK_ERR; + if (nxt != clst + 1) break; /* Not contiguous? */ + clst++; + } + if (clst == pclst) { /* Has the chain got contiguous again? */ + obj->stat = 2; /* Change the chain status 'contiguous' */ + } + } else { + if (obj->stat == 3 && pclst >= obj->sclust && pclst <= obj->sclust + obj->n_cont) { /* Was the chain fragmented in this session and got contiguous again? */ + obj->stat = 2; /* Change the chain status 'contiguous' */ + } + } + } + } +#endif + return FR_OK; +} + + + + +/*-----------------------------------------------------------------------*/ +/* FAT handling - Stretch a chain or Create a new chain */ +/*-----------------------------------------------------------------------*/ +static +DWORD create_chain ( /* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk error, >=2:New cluster# */ + FFOBJID* obj, /* Corresponding object */ + DWORD clst /* Cluster# to stretch, 0:Create a new chain */ +) +{ + DWORD cs, ncl, scl; + FRESULT res; + FATFS *fs = obj->fs; + + + if (clst == 0) { /* Create a new chain */ + scl = fs->last_clst; /* Suggested cluster to start to find */ + if (scl == 0 || scl >= fs->n_fatent) scl = 1; + } + else { /* Stretch a chain */ + cs = get_fat(obj, clst); /* Check the cluster status */ + if (cs < 2) return 1; /* Test for insanity */ + if (cs == 0xFFFFFFFF) return cs; /* Test for disk error */ + if (cs < fs->n_fatent) return cs; /* It is already followed by next cluster */ + scl = clst; /* Cluster to start to find */ + } + if (fs->free_clst == 0) return 0; /* No free cluster */ + +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ + ncl = find_bitmap(fs, scl, 1); /* Find a free cluster */ + if (ncl == 0 || ncl == 0xFFFFFFFF) return ncl; /* No free cluster or hard error? */ + res = change_bitmap(fs, ncl, 1, 1); /* Mark the cluster 'in use' */ + if (res == FR_INT_ERR) return 1; + if (res == FR_DISK_ERR) return 0xFFFFFFFF; + if (clst == 0) { /* Is it a new chain? */ + obj->stat = 2; /* Set status 'contiguous' */ + } else { /* It is a stretched chain */ + if (obj->stat == 2 && ncl != scl + 1) { /* Is the chain got fragmented? */ + obj->n_cont = scl - obj->sclust; /* Set size of the contiguous part */ + obj->stat = 3; /* Change status 'just fragmented' */ + } + } + if (obj->stat != 2) { /* Is the file non-contiguous? */ + if (ncl == clst + 1) { /* Is the cluster next to previous one? */ + obj->n_frag = obj->n_frag ? obj->n_frag + 1 : 2; /* Increment size of last framgent */ + } else { /* New fragment */ + if (obj->n_frag == 0) obj->n_frag = 1; + res = fill_last_frag(obj, clst, ncl); /* Fill last fragment on the FAT and link it to new one */ + if (res == FR_OK) obj->n_frag = 1; + } + } + } else +#endif + { /* On the FAT/FAT32 volume */ + ncl = 0; + if (scl == clst) { /* Stretching an existing chain? */ + ncl = scl + 1; /* Test if next cluster is free */ + if (ncl >= fs->n_fatent) ncl = 2; + cs = get_fat(obj, ncl); /* Get next cluster status */ + if (cs == 1 || cs == 0xFFFFFFFF) return cs; /* Test for error */ + if (cs != 0) { /* Not free? */ + cs = fs->last_clst; /* Start at suggested cluster if it is valid */ + if (cs >= 2 && cs < fs->n_fatent) scl = cs; + ncl = 0; + } + } + if (ncl == 0) { /* The new cluster cannot be contiguous and find another fragment */ + ncl = scl; /* Start cluster */ + for (;;) { + ncl++; /* Next cluster */ + if (ncl >= fs->n_fatent) { /* Check wrap-around */ + ncl = 2; + if (ncl > scl) return 0; /* No free cluster found? */ + } + cs = get_fat(obj, ncl); /* Get the cluster status */ + if (cs == 0) break; /* Found a free cluster? */ + if (cs == 1 || cs == 0xFFFFFFFF) return cs; /* Test for error */ + if (ncl == scl) return 0; /* No free cluster found? */ + } + } + res = put_fat(fs, ncl, 0xFFFFFFFF); /* Mark the new cluster 'EOC' */ + if (res == FR_OK && clst != 0) { + res = put_fat(fs, clst, ncl); /* Link it from the previous one if needed */ + } + } + + if (res == FR_OK) { /* Update FSINFO if function succeeded. */ + fs->last_clst = ncl; + if (fs->free_clst <= fs->n_fatent - 2) fs->free_clst--; + fs->fsi_flag |= 1; + } else { + ncl = (res == FR_DISK_ERR) ? 0xFFFFFFFF : 1; /* Failed. Generate error status */ + } + + return ncl; /* Return new cluster number or error status */ +} + +#endif /* !FF_FS_READONLY */ + + + + +#if FF_USE_FASTSEEK +/*-----------------------------------------------------------------------*/ +/* FAT handling - Convert offset into cluster with link map table */ +/*-----------------------------------------------------------------------*/ + +static +DWORD clmt_clust ( /* <2:Error, >=2:Cluster number */ + FIL* fp, /* Pointer to the file object */ + FSIZE_t ofs /* File offset to be converted to cluster# */ +) +{ + DWORD cl, ncl, *tbl; + FATFS *fs = fp->obj.fs; + + + tbl = fp->cltbl + 1; /* Top of CLMT */ + cl = (DWORD)(ofs / SS(fs) / fs->csize); /* Cluster order from top of the file */ + for (;;) { + ncl = *tbl++; /* Number of cluters in the fragment */ + if (ncl == 0) return 0; /* End of table? (error) */ + if (cl < ncl) break; /* In this fragment? */ + cl -= ncl; tbl++; /* Next fragment */ + } + return cl + *tbl; /* Return the cluster number */ +} + +#endif /* FF_USE_FASTSEEK */ + + + + +/*-----------------------------------------------------------------------*/ +/* Directory handling - Fill a cluster with zeros */ +/*-----------------------------------------------------------------------*/ + +#if !FF_FS_READONLY +static +FRESULT dir_clear ( /* Returns FR_OK or FR_DISK_ERR */ + FATFS *fs, /* Filesystem object */ + DWORD clst /* Directory table to clear */ +) +{ + DWORD sect; + UINT n, szb; + BYTE *ibuf; + + + if (sync_window(fs) != FR_OK) return FR_DISK_ERR; /* Flush disk access window */ + sect = clst2sect(fs, clst); /* Top of the cluster */ + fs->winsect = sect; /* Set window to top of the cluster */ + mem_set(fs->win, 0, SS(fs)); /* Clear window buffer */ +#if FF_USE_LFN == 3 /* Quick table clear by using multi-secter write */ + /* Allocate a temporary buffer (32 KB max) */ + for (szb = ((DWORD)fs->csize * SS(fs) >= 0x8000) ? 0x8000 : fs->csize * SS(fs); szb > SS(fs) && !(ibuf = ff_memalloc(szb)); szb /= 2) ; + if (szb > SS(fs)) { /* Buffer allocated? */ + mem_set(ibuf, 0, szb); + szb /= SS(fs); /* Bytes -> Sectors */ + for (n = 0; n < fs->csize && disk_write(fs->pdrv, ibuf, sect + n, szb) == RES_OK; n += szb) ; /* Fill the cluster with 0 */ + ff_memfree(ibuf); + } else +#endif + { + ibuf = fs->win; szb = 1; /* Use window buffer (single-sector writes may take a time) */ + for (n = 0; n < fs->csize && disk_write(fs->pdrv, ibuf, sect + n, szb) == RES_OK; n += szb) ; /* Fill the cluster with 0 */ + } + return (n == fs->csize) ? FR_OK : FR_DISK_ERR; +} +#endif /* !FF_FS_READONLY */ + + + + +/*-----------------------------------------------------------------------*/ +/* Directory handling - Set directory index */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT dir_sdi ( /* FR_OK(0):succeeded, !=0:error */ + DIR* dp, /* Pointer to directory object */ + DWORD ofs /* Offset of directory table */ +) +{ + DWORD csz, clst; + FATFS *fs = dp->obj.fs; + + + if (ofs >= (DWORD)((FF_FS_EXFAT && fs->fs_type == FS_EXFAT) ? MAX_DIR_EX : MAX_DIR) || ofs % SZDIRE) { /* Check range of offset and alignment */ + return FR_INT_ERR; + } + dp->dptr = ofs; /* Set current offset */ + clst = dp->obj.sclust; /* Table start cluster (0:root) */ + if (clst == 0 && fs->fs_type >= FS_FAT32) { /* Replace cluster# 0 with root cluster# */ + clst = fs->dirbase; + if (FF_FS_EXFAT) dp->obj.stat = 0; /* exFAT: Root dir has an FAT chain */ + } + + if (clst == 0) { /* Static table (root-directory on the FAT volume) */ + if (ofs / SZDIRE >= fs->n_rootdir) return FR_INT_ERR; /* Is index out of range? */ + dp->sect = fs->dirbase; + + } else { /* Dynamic table (sub-directory or root-directory on the FAT32/exFAT volume) */ + csz = (DWORD)fs->csize * SS(fs); /* Bytes per cluster */ + while (ofs >= csz) { /* Follow cluster chain */ + clst = get_fat(&dp->obj, clst); /* Get next cluster */ + if (clst == 0xFFFFFFFF) return FR_DISK_ERR; /* Disk error */ + if (clst < 2 || clst >= fs->n_fatent) return FR_INT_ERR; /* Reached to end of table or internal error */ + ofs -= csz; + } + dp->sect = clst2sect(fs, clst); + } + dp->clust = clst; /* Current cluster# */ + if (dp->sect == 0) return FR_INT_ERR; + dp->sect += ofs / SS(fs); /* Sector# of the directory entry */ + dp->dir = fs->win + (ofs % SS(fs)); /* Pointer to the entry in the win[] */ + + return FR_OK; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Directory handling - Move directory table index next */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT dir_next ( /* FR_OK(0):succeeded, FR_NO_FILE:End of table, FR_DENIED:Could not stretch */ + DIR* dp, /* Pointer to the directory object */ + int stretch /* 0: Do not stretch table, 1: Stretch table if needed */ +) +{ + DWORD ofs, clst; + FATFS *fs = dp->obj.fs; + + + ofs = dp->dptr + SZDIRE; /* Next entry */ + if (dp->sect == 0 || ofs >= (DWORD)((FF_FS_EXFAT && fs->fs_type == FS_EXFAT) ? MAX_DIR_EX : MAX_DIR)) return FR_NO_FILE; /* Report EOT when offset has reached max value */ + + if (ofs % SS(fs) == 0) { /* Sector changed? */ + dp->sect++; /* Next sector */ + + if (dp->clust == 0) { /* Static table */ + if (ofs / SZDIRE >= fs->n_rootdir) { /* Report EOT if it reached end of static table */ + dp->sect = 0; return FR_NO_FILE; + } + } + else { /* Dynamic table */ + if ((ofs / SS(fs) & (fs->csize - 1)) == 0) { /* Cluster changed? */ + clst = get_fat(&dp->obj, dp->clust); /* Get next cluster */ + if (clst <= 1) return FR_INT_ERR; /* Internal error */ + if (clst == 0xFFFFFFFF) return FR_DISK_ERR; /* Disk error */ + if (clst >= fs->n_fatent) { /* It reached end of dynamic table */ +#if !FF_FS_READONLY + if (!stretch) { /* If no stretch, report EOT */ + dp->sect = 0; return FR_NO_FILE; + } + clst = create_chain(&dp->obj, dp->clust); /* Allocate a cluster */ + if (clst == 0) return FR_DENIED; /* No free cluster */ + if (clst == 1) return FR_INT_ERR; /* Internal error */ + if (clst == 0xFFFFFFFF) return FR_DISK_ERR; /* Disk error */ + if (dir_clear(fs, clst) != FR_OK) return FR_DISK_ERR; /* Clean up the stretched table */ + if (FF_FS_EXFAT) dp->obj.stat |= 4; /* exFAT: The directory has been stretched */ +#else + if (!stretch) dp->sect = 0; /* (this line is to suppress compiler warning) */ + dp->sect = 0; return FR_NO_FILE; /* Report EOT */ +#endif + } + dp->clust = clst; /* Initialize data for new cluster */ + dp->sect = clst2sect(fs, clst); + } + } + } + dp->dptr = ofs; /* Current entry */ + dp->dir = fs->win + ofs % SS(fs); /* Pointer to the entry in the win[] */ + + return FR_OK; +} + + + + +#if !FF_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Directory handling - Reserve a block of directory entries */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT dir_alloc ( /* FR_OK(0):succeeded, !=0:error */ + DIR* dp, /* Pointer to the directory object */ + UINT nent /* Number of contiguous entries to allocate */ +) +{ + FRESULT res; + UINT n; + FATFS *fs = dp->obj.fs; + + + res = dir_sdi(dp, 0); + if (res == FR_OK) { + n = 0; + do { + res = move_window(fs, dp->sect); + if (res != FR_OK) break; +#if FF_FS_EXFAT + if ((fs->fs_type == FS_EXFAT) ? (int)((dp->dir[XDIR_Type] & 0x80) == 0) : (int)(dp->dir[DIR_Name] == DDEM || dp->dir[DIR_Name] == 0)) { +#else + if (dp->dir[DIR_Name] == DDEM || dp->dir[DIR_Name] == 0) { +#endif + if (++n == nent) break; /* A block of contiguous free entries is found */ + } else { + n = 0; /* Not a blank entry. Restart to search */ + } + res = dir_next(dp, 1); + } while (res == FR_OK); /* Next entry with table stretch enabled */ + } + + if (res == FR_NO_FILE) res = FR_DENIED; /* No directory entry to allocate */ + return res; +} + +#endif /* !FF_FS_READONLY */ + + + + +/*-----------------------------------------------------------------------*/ +/* FAT: Directory handling - Load/Store start cluster number */ +/*-----------------------------------------------------------------------*/ + +static +DWORD ld_clust ( /* Returns the top cluster value of the SFN entry */ + FATFS* fs, /* Pointer to the fs object */ + const BYTE* dir /* Pointer to the key entry */ +) +{ + DWORD cl; + + cl = ld_word(dir + DIR_FstClusLO); + if (fs->fs_type == FS_FAT32) { + cl |= (DWORD)ld_word(dir + DIR_FstClusHI) << 16; + } + + return cl; +} + + +#if !FF_FS_READONLY +static +void st_clust ( + FATFS* fs, /* Pointer to the fs object */ + BYTE* dir, /* Pointer to the key entry */ + DWORD cl /* Value to be set */ +) +{ + st_word(dir + DIR_FstClusLO, (WORD)cl); + if (fs->fs_type == FS_FAT32) { + st_word(dir + DIR_FstClusHI, (WORD)(cl >> 16)); + } +} +#endif + + + +#if FF_USE_LFN +/*--------------------------------------------------------*/ +/* FAT-LFN: Compare a part of file name with an LFN entry */ +/*--------------------------------------------------------*/ +static +int cmp_lfn ( /* 1:matched, 0:not matched */ + const WCHAR* lfnbuf, /* Pointer to the LFN working buffer to be compared */ + BYTE* dir /* Pointer to the directory entry containing the part of LFN */ +) +{ + UINT i, s; + WCHAR wc, uc; + + + if (ld_word(dir + LDIR_FstClusLO) != 0) return 0; /* Check LDIR_FstClusLO */ + + i = ((dir[LDIR_Ord] & 0x3F) - 1) * 13; /* Offset in the LFN buffer */ + + for (wc = 1, s = 0; s < 13; s++) { /* Process all characters in the entry */ + uc = ld_word(dir + LfnOfs[s]); /* Pick an LFN character */ + if (wc) { + if (i >= FF_MAX_LFN || ff_wtoupper(uc) != ff_wtoupper(lfnbuf[i++])) { /* Compare it */ + return 0; /* Not matched */ + } + wc = uc; + } else { + if (uc != 0xFFFF) return 0; /* Check filler */ + } + } + + if ((dir[LDIR_Ord] & LLEF) && wc && lfnbuf[i]) return 0; /* Last segment matched but different length */ + + return 1; /* The part of LFN matched */ +} + + +#if FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2 || FF_USE_LABEL || FF_FS_EXFAT +/*-----------------------------------------------------*/ +/* FAT-LFN: Pick a part of file name from an LFN entry */ +/*-----------------------------------------------------*/ +static +int pick_lfn ( /* 1:succeeded, 0:buffer overflow or invalid LFN entry */ + WCHAR* lfnbuf, /* Pointer to the LFN working buffer */ + BYTE* dir /* Pointer to the LFN entry */ +) +{ + UINT i, s; + WCHAR wc, uc; + + + if (ld_word(dir + LDIR_FstClusLO) != 0) return 0; /* Check LDIR_FstClusLO is 0 */ + + i = ((dir[LDIR_Ord] & ~LLEF) - 1) * 13; /* Offset in the LFN buffer */ + + for (wc = 1, s = 0; s < 13; s++) { /* Process all characters in the entry */ + uc = ld_word(dir + LfnOfs[s]); /* Pick an LFN character */ + if (wc) { + if (i >= FF_MAX_LFN) return 0; /* Buffer overflow? */ + lfnbuf[i++] = wc = uc; /* Store it */ + } else { + if (uc != 0xFFFF) return 0; /* Check filler */ + } + } + + if (dir[LDIR_Ord] & LLEF) { /* Put terminator if it is the last LFN part */ + if (i >= FF_MAX_LFN) return 0; /* Buffer overflow? */ + lfnbuf[i] = 0; + } + + return 1; /* The part of LFN is valid */ +} +#endif + + +#if !FF_FS_READONLY +/*-----------------------------------------*/ +/* FAT-LFN: Create an entry of LFN entries */ +/*-----------------------------------------*/ +static +void put_lfn ( + const WCHAR* lfn, /* Pointer to the LFN */ + BYTE* dir, /* Pointer to the LFN entry to be created */ + BYTE ord, /* LFN order (1-20) */ + BYTE sum /* Checksum of the corresponding SFN */ +) +{ + UINT i, s; + WCHAR wc; + + + dir[LDIR_Chksum] = sum; /* Set checksum */ + dir[LDIR_Attr] = AM_LFN; /* Set attribute. LFN entry */ + dir[LDIR_Type] = 0; + st_word(dir + LDIR_FstClusLO, 0); + + i = (ord - 1) * 13; /* Get offset in the LFN working buffer */ + s = wc = 0; + do { + if (wc != 0xFFFF) wc = lfn[i++]; /* Get an effective character */ + st_word(dir + LfnOfs[s], wc); /* Put it */ + if (wc == 0) wc = 0xFFFF; /* Padding characters for left locations */ + } while (++s < 13); + if (wc == 0xFFFF || !lfn[i]) ord |= LLEF; /* Last LFN part is the start of LFN sequence */ + dir[LDIR_Ord] = ord; /* Set the LFN order */ +} + +#endif /* !FF_FS_READONLY */ +#endif /* FF_USE_LFN */ + + + +#if FF_USE_LFN && !FF_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* FAT-LFN: Create a Numbered SFN */ +/*-----------------------------------------------------------------------*/ + +static +void gen_numname ( + BYTE* dst, /* Pointer to the buffer to store numbered SFN */ + const BYTE* src, /* Pointer to SFN */ + const WCHAR* lfn, /* Pointer to LFN */ + UINT seq /* Sequence number */ +) +{ + BYTE ns[8], c; + UINT i, j; + WCHAR wc; + DWORD sr; + + + mem_cpy(dst, src, 11); + + if (seq > 5) { /* In case of many collisions, generate a hash number instead of sequential number */ + sr = seq; + while (*lfn) { /* Create a CRC */ + wc = *lfn++; + for (i = 0; i < 16; i++) { + sr = (sr << 1) + (wc & 1); + wc >>= 1; + if (sr & 0x10000) sr ^= 0x11021; + } + } + seq = (UINT)sr; + } + + /* itoa (hexdecimal) */ + i = 7; + do { + c = (BYTE)((seq % 16) + '0'); + if (c > '9') c += 7; + ns[i--] = c; + seq /= 16; + } while (seq); + ns[i] = '~'; + + /* Append the number to the SFN body */ + for (j = 0; j < i && dst[j] != ' '; j++) { + if (dbc_1st(dst[j])) { + if (j == i - 1) break; + j++; + } + } + do { + dst[j++] = (i < 8) ? ns[i++] : ' '; + } while (j < 8); +} +#endif /* FF_USE_LFN && !FF_FS_READONLY */ + + + +#if FF_USE_LFN +/*-----------------------------------------------------------------------*/ +/* FAT-LFN: Calculate checksum of an SFN entry */ +/*-----------------------------------------------------------------------*/ + +static +BYTE sum_sfn ( + const BYTE* dir /* Pointer to the SFN entry */ +) +{ + BYTE sum = 0; + UINT n = 11; + + do { + sum = (sum >> 1) + (sum << 7) + *dir++; + } while (--n); + return sum; +} + +#endif /* FF_USE_LFN */ + + + +#if FF_FS_EXFAT +/*-----------------------------------------------------------------------*/ +/* exFAT: Checksum */ +/*-----------------------------------------------------------------------*/ + +static +WORD xdir_sum ( /* Get checksum of the directoly entry block */ + const BYTE* dir /* Directory entry block to be calculated */ +) +{ + UINT i, szblk; + WORD sum; + + + szblk = (dir[XDIR_NumSec] + 1) * SZDIRE; + for (i = sum = 0; i < szblk; i++) { + if (i == XDIR_SetSum) { /* Skip sum field */ + i++; + } else { + sum = ((sum & 1) ? 0x8000 : 0) + (sum >> 1) + dir[i]; + } + } + return sum; +} + + + +static +WORD xname_sum ( /* Get check sum (to be used as hash) of the name */ + const WCHAR* name /* File name to be calculated */ +) +{ + WCHAR chr; + WORD sum = 0; + + + while ((chr = *name++) != 0) { + chr = ff_wtoupper(chr); /* File name needs to be upper-case converted */ + sum = ((sum & 1) ? 0x8000 : 0) + (sum >> 1) + (chr & 0xFF); + sum = ((sum & 1) ? 0x8000 : 0) + (sum >> 1) + (chr >> 8); + } + return sum; +} + + +#if !FF_FS_READONLY && FF_USE_MKFS +static +DWORD xsum32 ( + BYTE dat, /* Byte to be calculated */ + DWORD sum /* Previous sum */ +) +{ + sum = ((sum & 1) ? 0x80000000 : 0) + (sum >> 1) + dat; + return sum; +} +#endif + + +#if FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2 +/*------------------------------------------------------*/ +/* exFAT: Get object information from a directory block */ +/*------------------------------------------------------*/ + +static +void get_xdir_info ( + BYTE* dirb, /* Pointer to the direcotry entry block 85+C0+C1s */ + FILINFO* fno /* Buffer to store the extracted file information */ +) +{ + WCHAR w; + UINT di, si, nc; + + /* Get file name */ + for (si = SZDIRE * 2, nc = di = 0; nc < dirb[XDIR_NumName]; si += 2, nc++) { + if ((si % SZDIRE) == 0) si += 2; /* Skip entry type field */ + w = ld_word(dirb + si); /* Get a character */ +#if !FF_LFN_UNICODE /* ANSI/OEM API */ + w = ff_uni2oem(w, CODEPAGE); /* Convert it to OEM code */ + if (w >= 0x100) { /* Is it a double byte char? */ + fno->fname[di++] = (char)(w >> 8); /* Store 1st byte of the DBC */ + } +#endif + +#if FF_BEKEN_FILESCAN + if ( di >= FF_MAX_LFN) { di = 0; break; } /* Invalid char or buffer overflow --> inaccessible object name */ + if(w ==0) + w='?'; +#else + if (w == 0 || di >= FF_MAX_LFN) { di = 0; break; } /* Invalid char or buffer overflow --> inaccessible object name */ +#endif + fno->fname[di++] = (TCHAR)w; /* Store the character */ + } + if (di == 0) fno->fname[di++] = '?'; /* Inaccessible object name? */ + fno->fname[di] = 0; /* Terminate file name */ + + fno->altname[0] = 0; /* No SFN */ + fno->fattrib = dirb[XDIR_Attr]; /* Attribute */ + fno->fsize = (fno->fattrib & AM_DIR) ? 0 : ld_qword(dirb + XDIR_FileSize); /* Size */ + fno->ftime = ld_word(dirb + XDIR_ModTime + 0); /* Time */ + fno->fdate = ld_word(dirb + XDIR_ModTime + 2); /* Date */ +#if FF_BEKEN_FILESCAN + fno->fcluster = ld_dword(dirb + XDIR_FstClus); + fno->ExNoChainFlag = dirb[XDIR_GenFlags]& 2; +// fno->fsize = (fno->fattrib & AM_DIR) ? 0 : ld_qword(dirb + XDIR_ValidFileSize); /* Size */ +#endif +} + +#endif /* FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2 */ + + +/*-----------------------------------*/ +/* exFAT: Get a directry entry block */ +/*-----------------------------------*/ + +static +FRESULT load_xdir ( /* FR_INT_ERR: invalid entry block */ + DIR* dp /* Reading direcotry object pointing top of the entry block to load */ +) +{ + FRESULT res; + UINT i, sz_ent; + BYTE* dirb = dp->obj.fs->dirbuf; /* Pointer to the on-memory direcotry entry block 85+C0+C1s */ + + + /* Load 85 entry */ + res = move_window(dp->obj.fs, dp->sect); + if (res != FR_OK) return res; + if (dp->dir[XDIR_Type] != 0x85) return FR_INT_ERR; /* Invalid order */ + mem_cpy(dirb + 0 * SZDIRE, dp->dir, SZDIRE); + sz_ent = (dirb[XDIR_NumSec] + 1) * SZDIRE; + if (sz_ent < 3 * SZDIRE || sz_ent > 19 * SZDIRE) return FR_INT_ERR; + + /* Load C0 entry */ + res = dir_next(dp, 0); + if (res == FR_NO_FILE) res = FR_INT_ERR; /* It cannot be */ + if (res != FR_OK) return res; + res = move_window(dp->obj.fs, dp->sect); + if (res != FR_OK) return res; + if (dp->dir[XDIR_Type] != 0xC0) return FR_INT_ERR; /* Invalid order */ + mem_cpy(dirb + 1 * SZDIRE, dp->dir, SZDIRE); + if (MAXDIRB(dirb[XDIR_NumName]) > sz_ent) return FR_INT_ERR; + + /* Load C1 entries */ + i = 2 * SZDIRE; /* C1 offset to load */ + do { + res = dir_next(dp, 0); + if (res == FR_NO_FILE) res = FR_INT_ERR; /* It cannot be */ + if (res != FR_OK) return res; + res = move_window(dp->obj.fs, dp->sect); + if (res != FR_OK) return res; + if (dp->dir[XDIR_Type] != 0xC1) return FR_INT_ERR; /* Invalid order */ + if (i < MAXDIRB(FF_MAX_LFN)) mem_cpy(dirb + i, dp->dir, SZDIRE); + } while ((i += SZDIRE) < sz_ent); + + /* Sanity check (do it for only accessible object) */ + if (i <= MAXDIRB(FF_MAX_LFN)) { + if (xdir_sum(dirb) != ld_word(dirb + XDIR_SetSum)) return FR_INT_ERR; + } + return FR_OK; +} + + +#if !FF_FS_READONLY || FF_FS_RPATH != 0 +/*------------------------------------------------*/ +/* exFAT: Load the object's directory entry block */ +/*------------------------------------------------*/ +static +FRESULT load_obj_xdir ( + DIR* dp, /* Blank directory object to be used to access containing direcotry */ + const FFOBJID* obj /* Object with its containing directory information */ +) +{ + FRESULT res; + + /* Open object containing directory */ + dp->obj.fs = obj->fs; + dp->obj.sclust = obj->c_scl; + dp->obj.stat = (BYTE)obj->c_size; + dp->obj.objsize = obj->c_size & 0xFFFFFF00; + dp->obj.n_frag = 0; + dp->blk_ofs = obj->c_ofs; + + res = dir_sdi(dp, dp->blk_ofs); /* Goto object's entry block */ + if (res == FR_OK) { + res = load_xdir(dp); /* Load the object's entry block */ + } + return res; +} +#endif + + +#if !FF_FS_READONLY +/*----------------------------------------*/ +/* exFAT: Store the directory entry block */ +/*----------------------------------------*/ +static +FRESULT store_xdir ( + DIR* dp /* Pointer to the direcotry object */ +) +{ + FRESULT res; + UINT nent; + BYTE* dirb = dp->obj.fs->dirbuf; /* Pointer to the direcotry entry block 85+C0+C1s */ + + /* Create set sum */ + st_word(dirb + XDIR_SetSum, xdir_sum(dirb)); + nent = dirb[XDIR_NumSec] + 1; + + /* Store the direcotry entry block to the directory */ + res = dir_sdi(dp, dp->blk_ofs); + while (res == FR_OK) { + res = move_window(dp->obj.fs, dp->sect); + if (res != FR_OK) break; + mem_cpy(dp->dir, dirb, SZDIRE); + dp->obj.fs->wflag = 1; + if (--nent == 0) break; + dirb += SZDIRE; + res = dir_next(dp, 0); + } + return (res == FR_OK || res == FR_DISK_ERR) ? res : FR_INT_ERR; +} + + + +/*-------------------------------------------*/ +/* exFAT: Create a new directory enrty block */ +/*-------------------------------------------*/ + +static +void create_xdir ( + BYTE* dirb, /* Pointer to the direcotry entry block buffer */ + const WCHAR* lfn /* Pointer to the object name */ +) +{ + UINT i; + BYTE nc1, nlen; + WCHAR chr; + + + /* Create 85+C0 entry */ + mem_set(dirb, 0, 2 * SZDIRE); + dirb[0 * SZDIRE + XDIR_Type] = 0x85; + dirb[1 * SZDIRE + XDIR_Type] = 0xC0; + + /* Create C1 entries */ + nlen = nc1 = 0; chr = 1; i = SZDIRE * 2; + do { + dirb[i++] = 0xC1; dirb[i++] = 0; /* Entry type C1 */ + do { /* Fill name field */ + if (chr && (chr = lfn[nlen]) != 0) nlen++; /* Get a character if exist */ + st_word(dirb + i, chr); /* Store it */ + i += 2; + } while (i % SZDIRE != 0); + nc1++; + } while (lfn[nlen]); /* Fill next entry if any char follows */ + + dirb[XDIR_NumName] = nlen; /* Set name length */ + dirb[XDIR_NumSec] = 1 + nc1; /* Set secondary count */ + st_word(dirb + XDIR_NameHash, xname_sum(lfn)); /* Set name hash */ +} + +#endif /* !FF_FS_READONLY */ +#endif /* FF_FS_EXFAT */ + + + +#if FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2 || FF_USE_LABEL || FF_FS_EXFAT +/*-----------------------------------------------------------------------*/ +/* Read an object from the directory */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT dir_read ( + DIR* dp, /* Pointer to the directory object */ + int vol /* Filtered by 0:file/directory or 1:volume label */ +) +{ + FRESULT res = FR_NO_FILE; + FATFS *fs = dp->obj.fs; + BYTE a, c; +#if FF_USE_LFN + BYTE ord = 0xFF, sum = 0xFF; +#endif + + while (dp->sect) { + res = move_window(fs, dp->sect); + if (res != FR_OK) break; + c = dp->dir[DIR_Name]; /* Test for the entry type */ + if (c == 0) { + res = FR_NO_FILE; break; /* Reached to end of the directory */ + } +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ + if (FF_USE_LABEL && vol) { + if (c == 0x83) break; /* Volume label entry? */ + } else { + if (c == 0x85) { /* Start of the file entry block? */ + dp->blk_ofs = dp->dptr; /* Get location of the block */ + res = load_xdir(dp); /* Load the entry block */ + if (res == FR_OK) { + dp->obj.attr = fs->dirbuf[XDIR_Attr] & AM_MASK; /* Get attribute */ + } + break; + } + } + } else +#endif + { /* On the FAT/FAT32 volume */ + dp->obj.attr = a = dp->dir[DIR_Attr] & AM_MASK; /* Get attribute */ +#if FF_USE_LFN /* LFN configuration */ + if (c == DDEM || c == '.' || (int)((a & ~AM_ARC) == AM_VOL) != vol) { /* An entry without valid data */ + ord = 0xFF; + } else { + if (a == AM_LFN) { /* An LFN entry is found */ + if (c & LLEF) { /* Is it start of an LFN sequence? */ + sum = dp->dir[LDIR_Chksum]; + c &= (BYTE)~LLEF; ord = c; + dp->blk_ofs = dp->dptr; + } + /* Check LFN validity and capture it */ + ord = (c == ord && sum == dp->dir[LDIR_Chksum] && pick_lfn(fs->lfnbuf, dp->dir)) ? ord - 1 : 0xFF; + } else { /* An SFN entry is found */ + if (ord || sum != sum_sfn(dp->dir)) { /* Is there a valid LFN? */ + dp->blk_ofs = 0xFFFFFFFF; /* It has no LFN. */ + } + break; + } + } +#else /* Non LFN configuration */ + if (c != DDEM && c != '.' && a != AM_LFN && (int)((a & ~AM_ARC) == AM_VOL) == vol) { /* Is it a valid entry? */ + break; + } +#endif + } + res = dir_next(dp, 0); /* Next entry */ + if (res != FR_OK) break; + } + + if (res != FR_OK) dp->sect = 0; /* Terminate the read operation on error or EOT */ + return res; +} + +#endif /* FF_FS_MINIMIZE <= 1 || FF_USE_LABEL || FF_FS_RPATH >= 2 */ + + + +/*-----------------------------------------------------------------------*/ +/* Directory handling - Find an object in the directory */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT dir_find ( /* FR_OK(0):succeeded, !=0:error */ + DIR* dp /* Pointer to the directory object with the file name */ +) +{ + FRESULT res; + FATFS *fs = dp->obj.fs; + BYTE c; +#if FF_USE_LFN + BYTE a, ord, sum; +#endif + + res = dir_sdi(dp, 0); /* Rewind directory object */ + if (res != FR_OK) return res; +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ + BYTE nc; + UINT di, ni; + WORD hash = xname_sum(fs->lfnbuf); /* Hash value of the name to find */ + + while ((res = dir_read(dp, 0)) == FR_OK) { /* Read an item */ +#if FF_MAX_LFN < 255 + if (fs->dirbuf[XDIR_NumName] > FF_MAX_LFN) continue; /* Skip comparison if inaccessible object name */ +#endif + if (ld_word(fs->dirbuf + XDIR_NameHash) != hash) continue; /* Skip comparison if hash mismatched */ + for (nc = fs->dirbuf[XDIR_NumName], di = SZDIRE * 2, ni = 0; nc; nc--, di += 2, ni++) { /* Compare the name */ + if ((di % SZDIRE) == 0) di += 2; + if (ff_wtoupper(ld_word(fs->dirbuf + di)) != ff_wtoupper(fs->lfnbuf[ni])) break; + } + if (nc == 0 && !fs->lfnbuf[ni]) break; /* Name matched? */ + } + return res; + } +#endif + /* On the FAT/FAT32 volume */ +#if FF_USE_LFN + ord = sum = 0xFF; dp->blk_ofs = 0xFFFFFFFF; /* Reset LFN sequence */ +#endif + do { + res = move_window(fs, dp->sect); + if (res != FR_OK) break; + c = dp->dir[DIR_Name]; + if (c == 0) { res = FR_NO_FILE; break; } /* Reached to end of table */ +#if FF_USE_LFN /* LFN configuration */ + dp->obj.attr = a = dp->dir[DIR_Attr] & AM_MASK; + if (c == DDEM || ((a & AM_VOL) && a != AM_LFN)) { /* An entry without valid data */ + ord = 0xFF; dp->blk_ofs = 0xFFFFFFFF; /* Reset LFN sequence */ + } else { + if (a == AM_LFN) { /* An LFN entry is found */ + if (!(dp->fn[NSFLAG] & NS_NOLFN)) { + if (c & LLEF) { /* Is it start of LFN sequence? */ + sum = dp->dir[LDIR_Chksum]; + c &= (BYTE)~LLEF; ord = c; /* LFN start order */ + dp->blk_ofs = dp->dptr; /* Start offset of LFN */ + } + /* Check validity of the LFN entry and compare it with given name */ + ord = (c == ord && sum == dp->dir[LDIR_Chksum] && cmp_lfn(fs->lfnbuf, dp->dir)) ? ord - 1 : 0xFF; + } + } else { /* An SFN entry is found */ + if (!ord && sum == sum_sfn(dp->dir)) break; /* LFN matched? */ + if (!(dp->fn[NSFLAG] & NS_LOSS) && !mem_cmp(dp->dir, dp->fn, 11)) break; /* SFN matched? */ + ord = 0xFF; dp->blk_ofs = 0xFFFFFFFF; /* Reset LFN sequence */ + } + } +#else /* Non LFN configuration */ + dp->obj.attr = dp->dir[DIR_Attr] & AM_MASK; + if (!(dp->dir[DIR_Attr] & AM_VOL) && !mem_cmp(dp->dir, dp->fn, 11)) break; /* Is it a valid entry? */ +#endif + res = dir_next(dp, 0); /* Next entry */ + } while (res == FR_OK); + + return res; +} + + + + +#if !FF_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Register an object to the directory */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT dir_register ( /* FR_OK:succeeded, FR_DENIED:no free entry or too many SFN collision, FR_DISK_ERR:disk error */ + DIR* dp /* Target directory with object name to be created */ +) +{ + FRESULT res; + FATFS *fs = dp->obj.fs; +#if FF_USE_LFN /* LFN configuration */ + UINT n, nlen, nent; + BYTE sn[12], sum; + + + if (dp->fn[NSFLAG] & (NS_DOT | NS_NONAME)) return FR_INVALID_NAME; /* Check name validity */ + for (nlen = 0; fs->lfnbuf[nlen]; nlen++) ; /* Get lfn length */ + +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ + nent = (nlen + 14) / 15 + 2; /* Number of entries to allocate (85+C0+C1s) */ + res = dir_alloc(dp, nent); /* Allocate entries */ + if (res != FR_OK) return res; + dp->blk_ofs = dp->dptr - SZDIRE * (nent - 1); /* Set the allocated entry block offset */ + + if (dp->obj.stat & 4) { /* Has the directory been stretched? */ + dp->obj.stat &= ~4; + res = fill_first_frag(&dp->obj); /* Fill the first fragment on the FAT if needed */ + if (res != FR_OK) return res; + res = fill_last_frag(&dp->obj, dp->clust, 0xFFFFFFFF); /* Fill the last fragment on the FAT if needed */ + if (res != FR_OK) return res; + if (dp->obj.sclust != 0) { /* Is it a sub directory? */ + DIR dj; + + res = load_obj_xdir(&dj, &dp->obj); /* Load the object status */ + if (res != FR_OK) return res; + dp->obj.objsize += (DWORD)fs->csize * SS(fs); /* Increase the directory size by cluster size */ + st_qword(fs->dirbuf + XDIR_FileSize, dp->obj.objsize); /* Update the allocation status */ + st_qword(fs->dirbuf + XDIR_ValidFileSize, dp->obj.objsize); + fs->dirbuf[XDIR_GenFlags] = dp->obj.stat | 1; + res = store_xdir(&dj); /* Store the object status */ + if (res != FR_OK) return res; + } + } + + create_xdir(fs->dirbuf, fs->lfnbuf); /* Create on-memory directory block to be written later */ + return FR_OK; + } +#endif + /* On the FAT/FAT32 volume */ + mem_cpy(sn, dp->fn, 12); + if (sn[NSFLAG] & NS_LOSS) { /* When LFN is out of 8.3 format, generate a numbered name */ + dp->fn[NSFLAG] = NS_NOLFN; /* Find only SFN */ + for (n = 1; n < 100; n++) { + gen_numname(dp->fn, sn, fs->lfnbuf, n); /* Generate a numbered name */ + res = dir_find(dp); /* Check if the name collides with existing SFN */ + if (res != FR_OK) break; + } + if (n == 100) return FR_DENIED; /* Abort if too many collisions */ + if (res != FR_NO_FILE) return res; /* Abort if the result is other than 'not collided' */ + dp->fn[NSFLAG] = sn[NSFLAG]; + } + + /* Create an SFN with/without LFNs. */ + nent = (sn[NSFLAG] & NS_LFN) ? (nlen + 12) / 13 + 1 : 1; /* Number of entries to allocate */ + res = dir_alloc(dp, nent); /* Allocate entries */ + if (res == FR_OK && --nent) { /* Set LFN entry if needed */ + res = dir_sdi(dp, dp->dptr - nent * SZDIRE); + if (res == FR_OK) { + sum = sum_sfn(dp->fn); /* Checksum value of the SFN tied to the LFN */ + do { /* Store LFN entries in bottom first */ + res = move_window(fs, dp->sect); + if (res != FR_OK) break; + put_lfn(fs->lfnbuf, dp->dir, (BYTE)nent, sum); + fs->wflag = 1; + res = dir_next(dp, 0); /* Next entry */ + } while (res == FR_OK && --nent); + } + } + +#else /* Non LFN configuration */ + res = dir_alloc(dp, 1); /* Allocate an entry for SFN */ + +#endif + + /* Set SFN entry */ + if (res == FR_OK) { + res = move_window(fs, dp->sect); + if (res == FR_OK) { + mem_set(dp->dir, 0, SZDIRE); /* Clean the entry */ + mem_cpy(dp->dir + DIR_Name, dp->fn, 11); /* Put SFN */ +#if FF_USE_LFN + dp->dir[DIR_NTres] = dp->fn[NSFLAG] & (NS_BODY | NS_EXT); /* Put NT flag */ +#endif + fs->wflag = 1; + } + } + + return res; +} + +#endif /* !FF_FS_READONLY */ + + + +#if !FF_FS_READONLY && FF_FS_MINIMIZE == 0 +/*-----------------------------------------------------------------------*/ +/* Remove an object from the directory */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT dir_remove ( /* FR_OK:Succeeded, FR_DISK_ERR:A disk error */ + DIR* dp /* Directory object pointing the entry to be removed */ +) +{ + FRESULT res; + FATFS *fs = dp->obj.fs; +#if FF_USE_LFN /* LFN configuration */ + DWORD last = dp->dptr; + + res = (dp->blk_ofs == 0xFFFFFFFF) ? FR_OK : dir_sdi(dp, dp->blk_ofs); /* Goto top of the entry block if LFN is exist */ + if (res == FR_OK) { + do { + res = move_window(fs, dp->sect); + if (res != FR_OK) break; + /* Mark an entry 'deleted' */ + if (FF_FS_EXFAT && fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ + dp->dir[XDIR_Type] &= 0x7F; + } else { /* On the FAT/FAT32 volume */ + dp->dir[DIR_Name] = DDEM; + } + fs->wflag = 1; + if (dp->dptr >= last) break; /* If reached last entry then all entries of the object has been deleted. */ + res = dir_next(dp, 0); /* Next entry */ + } while (res == FR_OK); + if (res == FR_NO_FILE) res = FR_INT_ERR; + } +#else /* Non LFN configuration */ + + res = move_window(fs, dp->sect); + if (res == FR_OK) { + dp->dir[DIR_Name] = DDEM; + fs->wflag = 1; + } +#endif + + return res; +} + +#endif /* !FF_FS_READONLY && FF_FS_MINIMIZE == 0 */ + + + +#if FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2 +/*-----------------------------------------------------------------------*/ +/* Get file information from directory entry */ +/*-----------------------------------------------------------------------*/ + +static +void get_fileinfo ( /* No return code */ + DIR* dp, /* Pointer to the directory object */ + FILINFO* fno /* Pointer to the file information to be filled */ +) +{ + UINT i, j; + TCHAR c; + DWORD tm; +#if FF_USE_LFN + WCHAR w, lfv; + FATFS *fs = dp->obj.fs; +#endif + + + fno->fname[0] = 0; /* Invaidate file info */ + if (dp->sect == 0) return; /* Exit if read pointer has reached end of directory */ + +#if FF_USE_LFN /* LFN configuration */ +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ + get_xdir_info(fs->dirbuf, fno); + return; + } else +#endif + { /* On the FAT/FAT32 volume */ + if (dp->blk_ofs != 0xFFFFFFFF) { /* Get LFN if available */ + i = j = 0; + while ((w = fs->lfnbuf[j++]) != 0) { /* Get an LFN character */ +#if !FF_LFN_UNICODE /* ANSI/OEM API */ + w = ff_uni2oem(w, CODEPAGE); /* Unicode -> OEM */ + if (w == 0) { i = 0; break; } /* No LFN if it could not be converted */ + if (w >= 0x100) { /* Put 1st byte if it is a DBC */ + fno->fname[i++] = (char)(w >> 8); + } +#endif + if (i >= FF_MAX_LFN) { i = 0; break; } /* No LFN if buffer overflow */ + fno->fname[i++] = (TCHAR)w; + } + fno->fname[i] = 0; /* Terminate the LFN */ + } + } + + i = j = 0; + lfv = fno->fname[i]; /* LFN is exist if non-zero */ + while (i < 11) { /* Copy name body and extension */ + c = (TCHAR)dp->dir[i++]; + if (c == ' ') continue; /* Skip padding spaces */ + if (c == RDDEM) c = (TCHAR)DDEM; /* Restore replaced DDEM character */ + if (i == 9) { /* Insert a . if extension is exist */ + if (!lfv) fno->fname[j] = '.'; + fno->altname[j++] = '.'; + } +#if FF_LFN_UNICODE /* Unicode API */ + if (dbc_1st((BYTE)c) && i != 8 && i != 11 && dbc_2nd(dp->dir[i])) { + c = c << 8 | dp->dir[i++]; + } + c = ff_oem2uni(c, CODEPAGE); /* OEM -> Unicode */ + if (!c) c = '?'; +#endif + fno->altname[j] = c; + if (!lfv) { + if (IsUpper(c) && (dp->dir[DIR_NTres] & ((i >= 9) ? NS_EXT : NS_BODY))) { + c += 0x20; /* To lower */ + } + fno->fname[j] = c; + } + j++; + } + if (!lfv) { + fno->fname[j] = 0; + if (!dp->dir[DIR_NTres]) j = 0; /* Altname is no longer needed if neither LFN nor case info is exist. */ + } + fno->altname[j] = 0; /* Terminate the SFN */ + +#else /* Non-LFN configuration */ + i = j = 0; + while (i < 11) { /* Copy name body and extension */ + c = (TCHAR)dp->dir[i++]; + if (c == ' ') continue; /* Skip padding spaces */ + if (c == RDDEM) c = (TCHAR)DDEM; /* Restore replaced DDEM character */ + if (i == 9) fno->fname[j++] = '.'; /* Insert a . if extension is exist */ + fno->fname[j++] = c; + } + fno->fname[j] = 0; +#endif + + fno->fattrib = dp->dir[DIR_Attr]; /* Attribute */ + fno->fsize = ld_dword(dp->dir + DIR_FileSize); /* Size */ + tm = ld_dword(dp->dir + DIR_ModTime); /* Timestamp */ + fno->ftime = (WORD)tm; fno->fdate = (WORD)(tm >> 16); +#if FF_BEKEN_FILESCAN + fno->fcluster = (DWORD)((ld_word(dp->dir + DIR_FstClusHI) << 16)|ld_word(dp->dir + DIR_FstClusLO)); +#endif +} + +#endif /* FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2 */ + + + +#if FF_USE_FIND && FF_FS_MINIMIZE <= 1 +/*-----------------------------------------------------------------------*/ +/* Pattern matching */ +/*-----------------------------------------------------------------------*/ + +static +WCHAR get_achar ( /* Get a character and advances ptr 1 or 2 */ + const TCHAR** ptr /* Pointer to pointer to the SBCS/DBCS/Unicode string */ +) +{ + WCHAR chr; + +#if FF_LFN_UNICODE && FF_USE_LFN /* Unicode API */ + chr = ff_wtoupper(*(*ptr)++); /* Get a Unicode char and to upper */ +#else /* ANSI/OEM API */ + chr = (BYTE)*(*ptr)++; /* Get a byte */ + if (IsLower(chr)) chr -= 0x20; /* To upper ASCII char */ +#if FF_CODE_PAGE == 0 + if (ExCvt && chr >= 0x80) chr = ExCvt[chr - 0x80]; /* To upper SBCS extended char */ +#elif FF_CODE_PAGE < 900 + if (chr >= 0x80) chr = ExCvt[chr - 0x80]; /* To upper SBCS extended char */ +#endif +#if FF_CODE_PAGE == 0 || FF_CODE_PAGE >= 900 + if (dbc_1st((BYTE)chr) && dbc_2nd((BYTE)**ptr)) { /* Get DBC 2nd byte if needed */ + chr = chr << 8 | (BYTE)*(*ptr)++; + } +#endif +#endif + return chr; +} + + +static +int pattern_matching ( /* 0:not matched, 1:matched */ + const TCHAR* pat, /* Matching pattern */ + const TCHAR* nam, /* String to be tested */ + int skip, /* Number of pre-skip chars (number of ?s) */ + int inf /* Infinite search (* specified) */ +) +{ + const TCHAR *pp, *np; + WCHAR pc, nc; + int nm, nx; + + + while (skip--) { /* Pre-skip name chars */ + if (!get_achar(&nam)) return 0; /* Branch mismatched if less name chars */ + } + if (!*pat && inf) return 1; /* (short circuit) */ + + do { + pp = pat; np = nam; /* Top of pattern and name to match */ + for (;;) { + if (*pp == '?' || *pp == '*') { /* Wildcard? */ + nm = nx = 0; + do { /* Analyze the wildcard chars */ + if (*pp++ == '?') nm++; else nx = 1; + } while (*pp == '?' || *pp == '*'); + if (pattern_matching(pp, np, nm, nx)) return 1; /* Test new branch (recurs upto number of wildcard blocks in the pattern) */ + nc = *np; break; /* Branch mismatched */ + } + pc = get_achar(&pp); /* Get a pattern char */ + nc = get_achar(&np); /* Get a name char */ + if (pc != nc) break; /* Branch mismatched? */ + if (pc == 0) return 1; /* Branch matched? (matched at end of both strings) */ + } + get_achar(&nam); /* nam++ */ + } while (inf && nc); /* Retry until end of name if infinite search is specified */ + + return 0; +} + +#endif /* FF_USE_FIND && FF_FS_MINIMIZE <= 1 */ + + + +/*-----------------------------------------------------------------------*/ +/* Pick a top segment and create the object name in directory form */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT create_name ( /* FR_OK: successful, FR_INVALID_NAME: could not create */ + DIR* dp, /* Pointer to the directory object */ + const TCHAR** path /* Pointer to pointer to the segment in the path string */ +) +{ +#if FF_USE_LFN /* LFN configuration */ + BYTE b, cf; + WCHAR w, *lfn; + UINT i, ni, si, di; + const TCHAR *p; + + + /* Create LFN in Unicode */ + p = *path; lfn = dp->obj.fs->lfnbuf; si = di = 0; + for (;;) { + w = p[si++]; /* Get a character */ + if (w < ' ') break; /* Break if end of the path name */ + if (w == '/' || w == '\\') { /* Break if a separator is found */ + while (p[si] == '/' || p[si] == '\\') si++; /* Skip duplicated separator if exist */ + break; + } + if (di >= FF_MAX_LFN) return FR_INVALID_NAME; /* Reject too long name */ +#if !FF_LFN_UNICODE /* ANSI/OEM API */ + w &= 0xFF; + if (dbc_1st((BYTE)w)) { /* Check if it is a DBC 1st byte */ + b = (BYTE)p[si++]; /* Get 2nd byte */ + w = (w << 8) + b; /* Create a DBC */ + if (!dbc_2nd(b)) return FR_INVALID_NAME; /* Reject invalid sequence */ + } + w = ff_oem2uni(w, CODEPAGE); /* Convert ANSI/OEM to Unicode */ + if (!w) return FR_INVALID_NAME; /* Reject invalid code */ +#endif + if (w < 0x80 && chk_chr("\"*:<>\?|\x7F", w)) return FR_INVALID_NAME; /* Reject illegal characters for LFN */ + lfn[di++] = w; /* Store the Unicode character */ + } + *path = &p[si]; /* Return pointer to the next segment */ + cf = (w < ' ') ? NS_LAST : 0; /* Set last segment flag if end of the path */ +#if FF_FS_RPATH != 0 + if ((di == 1 && lfn[di - 1] == '.') || + (di == 2 && lfn[di - 1] == '.' && lfn[di - 2] == '.')) { /* Is this segment a dot name? */ + lfn[di] = 0; + for (i = 0; i < 11; i++) /* Create dot name for SFN entry */ + dp->fn[i] = (i < di) ? '.' : ' '; + dp->fn[i] = cf | NS_DOT; /* This is a dot entry */ + return FR_OK; + } +#endif + while (di) { /* Snip off trailing spaces and dots if exist */ + w = lfn[di - 1]; + if (w != ' ' && w != '.') break; + di--; + } + lfn[di] = 0; /* LFN is created */ + if (di == 0) return FR_INVALID_NAME; /* Reject nul name */ + + /* Create SFN in directory form */ + mem_set(dp->fn, ' ', 11); + for (si = 0; lfn[si] == ' ' || lfn[si] == '.'; si++) ; /* Strip leading spaces and dots */ + if (si > 0) cf |= NS_LOSS | NS_LFN; + while (di > 0 && lfn[di - 1] != '.') di--; /* Find extension (di<=si: no extension) */ + + i = b = 0; ni = 8; + for (;;) { + w = lfn[si++]; /* Get an LFN character */ + if (!w) break; /* Break on end of the LFN */ + if (w == ' ' || (w == '.' && si != di)) { /* Remove spaces and dots */ + cf |= NS_LOSS | NS_LFN; + continue; + } + + if (i >= ni || si == di) { /* Entered extension or end of SFN */ + if (ni == 11) { /* Extension fileld overflow? */ + cf |= NS_LOSS | NS_LFN; + break; + } + if (si != di) cf |= NS_LOSS | NS_LFN; /* Out of 8.3 format */ + if (si > di) break; /* No extension */ + si = di; i = 8; ni = 11; /* Enter extension fileld */ + b <<= 2; continue; + } + + if (w >= 0x80) { /* Is this a non-ASCII character? */ + cf |= NS_LFN; /* Force to create LFN entry */ +#if FF_CODE_PAGE == 0 + if (ExCvt) { /* In SBCS */ + w = ff_uni2oem(w, CODEPAGE); /* Unicode -> OEM code */ + if (w & 0x80) w = ExCvt[w & 0x7F]; /* Convert extended character to upper (SBCS) */ + } else { /* In DBCS */ + w = ff_uni2oem(ff_wtoupper(w), CODEPAGE); /* Upper converted Unicode -> OEM code */ + } +#elif FF_CODE_PAGE < 900 /* SBCS cfg */ + w = ff_uni2oem(w, CODEPAGE); /* Unicode -> OEM code */ + if (w & 0x80) w = ExCvt[w & 0x7F]; /* Convert extended character to upper (SBCS) */ +#else /* DBCS cfg */ + w = ff_uni2oem(ff_wtoupper(w), CODEPAGE); /* Upper converted Unicode -> OEM code */ +#endif + } + + if (w >= 0x100) { /* Is this a DBC? */ + if (i >= ni - 1) { /* Field overflow? */ + cf |= NS_LOSS | NS_LFN; + i = ni; continue; /* Next field */ + } + dp->fn[i++] = (BYTE)(w >> 8); /* Put 1st byte */ + } else { /* SBC */ + if (!w || chk_chr("+,;=[]", w)) { /* Replace illegal characters for SFN */ + w = '_'; cf |= NS_LOSS | NS_LFN;/* Lossy conversion */ + } else { + if (IsUpper(w)) { /* ASCII large capital */ + b |= 2; + } else { + if (IsLower(w)) { /* ASCII small capital */ + b |= 1; w -= 0x20; + } + } + } + } + dp->fn[i++] = (BYTE)w; + } + + if (dp->fn[0] == DDEM) dp->fn[0] = RDDEM; /* If the first character collides with DDEM, replace it with RDDEM */ + + if (ni == 8) b <<= 2; + if ((b & 0x0C) == 0x0C || (b & 0x03) == 0x03) cf |= NS_LFN; /* Create LFN entry when there are composite capitals */ + if (!(cf & NS_LFN)) { /* When LFN is in 8.3 format without extended character, NT flags are created */ + if ((b & 0x03) == 0x01) cf |= NS_EXT; /* NT flag (Extension has only small capital) */ + if ((b & 0x0C) == 0x04) cf |= NS_BODY; /* NT flag (Filename has only small capital) */ + } + + dp->fn[NSFLAG] = cf; /* SFN is created */ + + return FR_OK; + + +#else /* FF_USE_LFN : Non-LFN configuration */ + BYTE c, d, *sfn; + UINT ni, si, i; + const char *p; + + /* Create file name in directory form */ + p = *path; sfn = dp->fn; + mem_set(sfn, ' ', 11); + si = i = 0; ni = 8; +#if FF_FS_RPATH != 0 + if (p[si] == '.') { /* Is this a dot entry? */ + for (;;) { + c = (BYTE)p[si++]; + if (c != '.' || si >= 3) break; + sfn[i++] = c; + } + if (c != '/' && c != '\\' && c > ' ') return FR_INVALID_NAME; + *path = p + si; /* Return pointer to the next segment */ + sfn[NSFLAG] = (c <= ' ') ? NS_LAST | NS_DOT : NS_DOT; /* Set last segment flag if end of the path */ + return FR_OK; + } +#endif + for (;;) { + c = (BYTE)p[si++]; + if (c <= ' ') break; /* Break if end of the path name */ + if (c == '/' || c == '\\') { /* Break if a separator is found */ + while (p[si] == '/' || p[si] == '\\') si++; /* Skip duplicated separator if exist */ + break; + } + if (c == '.' || i >= ni) { /* End of body or over size? */ + if (ni == 11 || c != '.') return FR_INVALID_NAME; /* Over size or invalid dot */ + i = 8; ni = 11; /* Goto extension */ + continue; + } +#if FF_CODE_PAGE == 0 + if (ExCvt && c >= 0x80) { /* Is SBC extended character? */ + c = ExCvt[c - 0x80]; /* To upper SBC extended character */ + } +#elif FF_CODE_PAGE < 900 + if (c >= 0x80) { /* Is SBC extended character? */ + c = ExCvt[c - 0x80]; /* To upper SBC extended character */ + } +#endif + if (dbc_1st(c)) { /* Check if it is a DBC 1st byte */ + d = (BYTE)p[si++]; /* Get 2nd byte */ + if (!dbc_2nd(d) || i >= ni - 1) return FR_INVALID_NAME; /* Reject invalid DBC */ + sfn[i++] = c; + sfn[i++] = d; + } else { /* SBC */ + if (chk_chr("\"*+,:;<=>\?[]|\x7F", c)) return FR_INVALID_NAME; /* Reject illegal chrs for SFN */ + if (IsLower(c)) c -= 0x20; /* To upper */ + sfn[i++] = c; + } + } + *path = p + si; /* Return pointer to the next segment */ + if (i == 0) return FR_INVALID_NAME; /* Reject nul string */ + + if (sfn[0] == DDEM) sfn[0] = RDDEM; /* If the first character collides with DDEM, replace it with RDDEM */ + sfn[NSFLAG] = (c <= ' ') ? NS_LAST : 0; /* Set last segment flag if end of the path */ + + return FR_OK; +#endif /* FF_USE_LFN */ +} + + + + +/*-----------------------------------------------------------------------*/ +/* Follow a file path */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */ + DIR* dp, /* Directory object to return last directory and found object */ + const TCHAR* path /* Full-path string to find a file or directory */ +) +{ + FRESULT res; + BYTE ns; + FATFS *fs = dp->obj.fs; + + +#if FF_FS_RPATH != 0 + if (*path != '/' && *path != '\\') { /* Without heading separator */ + dp->obj.sclust = fs->cdir; /* Start from current directory */ + } else +#endif + { /* With heading separator */ + while (*path == '/' || *path == '\\') path++; /* Strip heading separator */ + dp->obj.sclust = 0; /* Start from root directory */ + } +#if FF_FS_EXFAT + dp->obj.n_frag = 0; /* Invalidate last fragment counter of the object */ +#if FF_FS_RPATH != 0 + if (fs->fs_type == FS_EXFAT && dp->obj.sclust) { /* exFAT: Retrieve the sub-directory's status */ + DIR dj; + + dp->obj.c_scl = fs->cdc_scl; + dp->obj.c_size = fs->cdc_size; + dp->obj.c_ofs = fs->cdc_ofs; + res = load_obj_xdir(&dj, &dp->obj); + if (res != FR_OK) return res; + dp->obj.objsize = ld_dword(fs->dirbuf + XDIR_FileSize); + dp->obj.stat = fs->dirbuf[XDIR_GenFlags] & 2; + } +#endif +#endif + + if ((UINT)*path < ' ') { /* Null path name is the origin directory itself */ + dp->fn[NSFLAG] = NS_NONAME; + res = dir_sdi(dp, 0); + + } else { /* Follow path */ + for (;;) { + res = create_name(dp, &path); /* Get a segment name of the path */ + if (res != FR_OK) break; + res = dir_find(dp); /* Find an object with the segment name */ + ns = dp->fn[NSFLAG]; + if (res != FR_OK) { /* Failed to find the object */ + if (res == FR_NO_FILE) { /* Object is not found */ + if (FF_FS_RPATH && (ns & NS_DOT)) { /* If dot entry is not exist, stay there */ + if (!(ns & NS_LAST)) continue; /* Continue to follow if not last segment */ + dp->fn[NSFLAG] = NS_NONAME; + res = FR_OK; + } else { /* Could not find the object */ + if (!(ns & NS_LAST)) res = FR_NO_PATH; /* Adjust error code if not last segment */ + } + } + break; + } + if (ns & NS_LAST) break; /* Last segment matched. Function completed. */ + /* Get into the sub-directory */ + if (!(dp->obj.attr & AM_DIR)) { /* It is not a sub-directory and cannot follow */ + res = FR_NO_PATH; break; + } +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { /* Save containing directory information for next dir */ + dp->obj.c_scl = dp->obj.sclust; + dp->obj.c_size = ((DWORD)dp->obj.objsize & 0xFFFFFF00) | dp->obj.stat; + dp->obj.c_ofs = dp->blk_ofs; + dp->obj.sclust = ld_dword(fs->dirbuf + XDIR_FstClus); /* Open next directory */ + dp->obj.stat = fs->dirbuf[XDIR_GenFlags] & 2; + dp->obj.objsize = ld_qword(fs->dirbuf + XDIR_FileSize); + } else +#endif + { + dp->obj.sclust = ld_clust(fs, fs->win + dp->dptr % SS(fs)); /* Open next directory */ + } + } + } + + return res; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Get logical drive number from path name */ +/*-----------------------------------------------------------------------*/ + +static +int get_ldnumber ( /* Returns logical drive number (-1:invalid drive) */ + const TCHAR** path /* Pointer to pointer to the path name */ +) +{ + const TCHAR *tp, *tt; + UINT i; + int vol = -1; +#if FF_STR_VOLUME_ID /* Find string drive id */ + static const char* const volid[] = {FF_VOLUME_STRS}; + const char *sp; + char c; + TCHAR tc; +#endif + + if (*path) { /* If the pointer is not a null */ + for (tt = *path; (UINT)*tt >= (FF_USE_LFN ? ' ' : '!') && *tt != ':'; tt++) ; /* Find a colon in the path */ + if (*tt == ':') { /* If a colon is exist in the path name */ + tp = *path; + i = *tp++; + if (IsDigit(i) && tp == tt) { /* Is there a numeric drive id + colon? */ + if ((i -= '0') < FF_VOLUMES) { /* If drive id is found, get the value and strip it */ + vol = (int)i; + *path = ++tt; + } + } +#if FF_STR_VOLUME_ID + else { /* No numeric drive number, find string drive id */ + i = 0; tt++; + do { + sp = volid[i]; tp = *path; + do { /* Compare a string drive id with path name */ + c = *sp++; tc = *tp++; + if (IsLower(tc)) tc -= 0x20; + } while (c && (TCHAR)c == tc); + } while ((c || tp != tt) && ++i < FF_VOLUMES); /* Repeat for each id until pattern match */ + if (i < FF_VOLUMES) { /* If a drive id is found, get the value and strip it */ + vol = (int)i; + *path = tt; + } + } +#endif + } else { /* No volume id and use default drive */ +#if FF_FS_RPATH != 0 && FF_VOLUMES >= 2 + vol = CurrVol; /* Current drive */ +#else + vol = 0; /* Drive 0 */ +#endif + } + } + return vol; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Load a sector and check if it is an FAT VBR */ +/*-----------------------------------------------------------------------*/ + +static +BYTE check_fs ( /* 0:FAT, 1:exFAT, 2:Valid BS but not FAT, 3:Not a BS, 4:Disk error */ + FATFS* fs, /* Filesystem object */ + DWORD sect /* Sector# (lba) to load and check if it is an FAT-VBR or not */ +) +{ + fs->wflag = 0; fs->winsect = 0xFFFFFFFF; /* Invaidate window */ + if (move_window(fs, sect) != FR_OK) return 4; /* Load boot record */ + + if (ld_word(fs->win + BS_55AA) != 0xAA55) return 3; /* Check boot record signature (always placed here even if the sector size is >512) */ + +#if FF_FS_EXFAT + if (!mem_cmp(fs->win + BS_JmpBoot, "\xEB\x76\x90" "EXFAT ", 11)) return 1; /* Check if exFAT VBR */ +#endif + if (fs->win[BS_JmpBoot] == 0xE9 || (fs->win[BS_JmpBoot] == 0xEB && fs->win[BS_JmpBoot + 2] == 0x90)) { /* Valid JumpBoot code? */ + if (!mem_cmp(fs->win + BS_FilSysType, "FAT", 3)) return 0; /* Is it an FAT VBR? */ + if (!mem_cmp(fs->win + BS_FilSysType32, "FAT32", 5)) return 0; /* Is it an FAT32 VBR? */ + } + return 2; /* Valid BS but not FAT */ +} + + + + +/*-----------------------------------------------------------------------*/ +/* Find logical drive and check if the volume is mounted */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT find_volume ( /* FR_OK(0): successful, !=0: any error occurred */ + const TCHAR** path, /* Pointer to pointer to the path name (drive number) */ + FATFS** rfs, /* Pointer to pointer to the found filesystem object */ + BYTE mode /* !=0: Check write protection for write access */ +) +{ + BYTE fmt, *pt; + int vol; + DSTATUS stat; + DWORD bsect, fasize, tsect, sysect, nclst, szbfat, br[4]; + WORD nrsv; + FATFS *fs; + UINT i; + + //os_printf("find_volume1\r\n"); + + /* Get logical drive number */ + *rfs = 0; + vol = get_ldnumber(path); + if (vol < 0) return FR_INVALID_DRIVE; + + /* Check if the filesystem object is valid or not */ + fs = FatFs[vol]; /* Get pointer to the filesystem object */ + if (!fs) return FR_NOT_ENABLED; /* Is the filesystem object available? */ +#if FF_FS_REENTRANT + if (!lock_fs(fs)) return FR_TIMEOUT; /* Lock the volume */ +#endif + *rfs = fs; /* Return pointer to the filesystem object */ + + mode &= (BYTE)~FA_READ; /* Desired access mode, write access or not */ + if (fs->fs_type != 0) { /* If the volume has been mounted */ + stat = disk_status(fs->pdrv); + if (!(stat & STA_NOINIT)) { /* and the physical drive is kept initialized */ + if (!FF_FS_READONLY && mode && (stat & STA_PROTECT)) { /* Check write protection if needed */ + return FR_WRITE_PROTECTED; + } + return FR_OK; /* The filesystem object is valid */ + } + } + + /* The filesystem object is not valid. */ + /* Following code attempts to mount the volume. (analyze BPB and initialize the filesystem object) */ + + fs->fs_type = 0; /* Clear the filesystem object */ + fs->pdrv = LD2PD(vol); /* Bind the logical drive and a physical drive */ + stat = disk_initialize(fs->pdrv); /* Initialize the physical drive */ + if (stat & STA_NOINIT) { /* Check if the initialization succeeded */ + return FR_NOT_READY; /* Failed to initialize due to no medium or hard error */ + } + if (!FF_FS_READONLY && mode && (stat & STA_PROTECT)) { /* Check disk write protection if needed */ + return FR_WRITE_PROTECTED; + } +#if FF_MAX_SS != FF_MIN_SS /* Get sector size (multiple sector size cfg only) */ + if (disk_ioctl(fs->pdrv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK) return FR_DISK_ERR; + if (SS(fs) > FF_MAX_SS || SS(fs) < FF_MIN_SS || (SS(fs) & (SS(fs) - 1))) return FR_DISK_ERR; +#endif + + /* Find an FAT partition on the drive. Supports only generic partitioning rules, FDISK and SFD. */ + bsect = 0; + fmt = check_fs(fs, bsect); /* Load sector 0 and check if it is an FAT-VBR as SFD */ + if (fmt == 2 || (fmt < 2 && LD2PT(vol) != 0)) { /* Not an FAT-VBR or forced partition number */ + for (i = 0; i < 4; i++) { /* Get partition offset */ + pt = fs->win + (MBR_Table + i * SZ_PTE); + br[i] = pt[PTE_System] ? ld_dword(pt + PTE_StLba) : 0; + } + i = LD2PT(vol); /* Partition number: 0:auto, 1-4:forced */ + if (i != 0) i--; + do { /* Find an FAT volume */ + bsect = br[i]; + fmt = bsect ? check_fs(fs, bsect) : 3; /* Check the partition */ + } while (LD2PT(vol) == 0 && fmt >= 2 && ++i < 4); + } + if (fmt == 4) return FR_DISK_ERR; /* An error occured in the disk I/O layer */ + if (fmt >= 2) return FR_NO_FILESYSTEM; /* No FAT volume is found */ + + /* An FAT volume is found (bsect). Following code initializes the filesystem object */ + +#if FF_FS_EXFAT + if (fmt == 1) { + QWORD maxlba; + + for (i = BPB_ZeroedEx; i < BPB_ZeroedEx + 53 && fs->win[i] == 0; i++) ; /* Check zero filler */ + if (i < BPB_ZeroedEx + 53) return FR_NO_FILESYSTEM; + + if (ld_word(fs->win + BPB_FSVerEx) != 0x100) return FR_NO_FILESYSTEM; /* Check exFAT version (must be version 1.0) */ + + if (1 << fs->win[BPB_BytsPerSecEx] != SS(fs)) { /* (BPB_BytsPerSecEx must be equal to the physical sector size) */ + return FR_NO_FILESYSTEM; + } + + maxlba = ld_qword(fs->win + BPB_TotSecEx) + bsect; /* Last LBA + 1 of the volume */ + if (maxlba >= 0x100000000) return FR_NO_FILESYSTEM; /* (It cannot be handled in 32-bit LBA) */ + + fs->fsize = ld_dword(fs->win + BPB_FatSzEx); /* Number of sectors per FAT */ + + fs->n_fats = fs->win[BPB_NumFATsEx]; /* Number of FATs */ + if (fs->n_fats != 1) return FR_NO_FILESYSTEM; /* (Supports only 1 FAT) */ + + fs->csize = 1 << fs->win[BPB_SecPerClusEx]; /* Cluster size */ + if (fs->csize == 0) return FR_NO_FILESYSTEM; /* (Must be 1..32768) */ + + nclst = ld_dword(fs->win + BPB_NumClusEx); /* Number of clusters */ + if (nclst > MAX_EXFAT) return FR_NO_FILESYSTEM; /* (Too many clusters) */ + fs->n_fatent = nclst + 2; + + /* Boundaries and Limits */ + fs->volbase = bsect; + fs->database = bsect + ld_dword(fs->win + BPB_DataOfsEx); + fs->fatbase = bsect + ld_dword(fs->win + BPB_FatOfsEx); + if (maxlba < (QWORD)fs->database + nclst * fs->csize) return FR_NO_FILESYSTEM; /* (Volume size must not be smaller than the size requiered) */ + fs->dirbase = ld_dword(fs->win + BPB_RootClusEx); + + /* Check if bitmap location is in assumption (at the first cluster) */ + if (move_window(fs, clst2sect(fs, fs->dirbase)) != FR_OK) return FR_DISK_ERR; + for (i = 0; i < SS(fs); i += SZDIRE) { + if (fs->win[i] == 0x81 && ld_dword(fs->win + i + 20) == 2) break; /* 81 entry with cluster #2? */ + } + if (i == SS(fs)) return FR_NO_FILESYSTEM; +#if !FF_FS_READONLY + fs->last_clst = fs->free_clst = 0xFFFFFFFF; /* Initialize cluster allocation information */ +#endif + fmt = FS_EXFAT; /* FAT sub-type */ + } else +#endif /* FF_FS_EXFAT */ + { + if (ld_word(fs->win + BPB_BytsPerSec) != SS(fs)) return FR_NO_FILESYSTEM; /* (BPB_BytsPerSec must be equal to the physical sector size) */ + + fasize = ld_word(fs->win + BPB_FATSz16); /* Number of sectors per FAT */ + if (fasize == 0) fasize = ld_dword(fs->win + BPB_FATSz32); + fs->fsize = fasize; + + fs->n_fats = fs->win[BPB_NumFATs]; /* Number of FATs */ + if (fs->n_fats != 1 && fs->n_fats != 2) return FR_NO_FILESYSTEM; /* (Must be 1 or 2) */ + fasize *= fs->n_fats; /* Number of sectors for FAT area */ + + fs->csize = fs->win[BPB_SecPerClus]; /* Cluster size */ + if (fs->csize == 0 || (fs->csize & (fs->csize - 1))) return FR_NO_FILESYSTEM; /* (Must be power of 2) */ + + fs->n_rootdir = ld_word(fs->win + BPB_RootEntCnt); /* Number of root directory entries */ + if (fs->n_rootdir % (SS(fs) / SZDIRE)) return FR_NO_FILESYSTEM; /* (Must be sector aligned) */ + + tsect = ld_word(fs->win + BPB_TotSec16); /* Number of sectors on the volume */ + if (tsect == 0) tsect = ld_dword(fs->win + BPB_TotSec32); + + nrsv = ld_word(fs->win + BPB_RsvdSecCnt); /* Number of reserved sectors */ + if (nrsv == 0) return FR_NO_FILESYSTEM; /* (Must not be 0) */ + + /* Determine the FAT sub type */ + sysect = nrsv + fasize + fs->n_rootdir / (SS(fs) / SZDIRE); /* RSV + FAT + DIR */ + if (tsect < sysect) return FR_NO_FILESYSTEM; /* (Invalid volume size) */ + nclst = (tsect - sysect) / fs->csize; /* Number of clusters */ + if (nclst == 0) return FR_NO_FILESYSTEM; /* (Invalid volume size) */ + fmt = 0; + if (nclst <= MAX_FAT32) fmt = FS_FAT32; + if (nclst <= MAX_FAT16) fmt = FS_FAT16; + if (nclst <= MAX_FAT12) fmt = FS_FAT12; + if (fmt == 0) return FR_NO_FILESYSTEM; + + /* Boundaries and Limits */ + fs->n_fatent = nclst + 2; /* Number of FAT entries */ + fs->volbase = bsect; /* Volume start sector */ + fs->fatbase = bsect + nrsv; /* FAT start sector */ + fs->database = bsect + sysect; /* Data start sector */ + if (fmt == FS_FAT32) { + if (ld_word(fs->win + BPB_FSVer32) != 0) return FR_NO_FILESYSTEM; /* (Must be FAT32 revision 0.0) */ + if (fs->n_rootdir != 0) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must be 0) */ + fs->dirbase = ld_dword(fs->win + BPB_RootClus32); /* Root directory start cluster */ + szbfat = fs->n_fatent * 4; /* (Needed FAT size) */ + } else { + if (fs->n_rootdir == 0) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must not be 0) */ + fs->dirbase = fs->fatbase + fasize; /* Root directory start sector */ + szbfat = (fmt == FS_FAT16) ? /* (Needed FAT size) */ + fs->n_fatent * 2 : fs->n_fatent * 3 / 2 + (fs->n_fatent & 1); + } + if (fs->fsize < (szbfat + (SS(fs) - 1)) / SS(fs)) return FR_NO_FILESYSTEM; /* (BPB_FATSz must not be less than the size needed) */ + +#if !FF_FS_READONLY + /* Get FSInfo if available */ + fs->last_clst = fs->free_clst = 0xFFFFFFFF; /* Initialize cluster allocation information */ + fs->fsi_flag = 0x80; +#if (FF_FS_NOFSINFO & 3) != 3 + if (fmt == FS_FAT32 /* Allow to update FSInfo only if BPB_FSInfo32 == 1 */ + && ld_word(fs->win + BPB_FSInfo32) == 1 + && move_window(fs, bsect + 1) == FR_OK) + { + fs->fsi_flag = 0; + if (ld_word(fs->win + BS_55AA) == 0xAA55 /* Load FSInfo data if available */ + && ld_dword(fs->win + FSI_LeadSig) == 0x41615252 + && ld_dword(fs->win + FSI_StrucSig) == 0x61417272) + { +#if (FF_FS_NOFSINFO & 1) == 0 + fs->free_clst = ld_dword(fs->win + FSI_Free_Count); +#endif +#if (FF_FS_NOFSINFO & 2) == 0 + fs->last_clst = ld_dword(fs->win + FSI_Nxt_Free); +#endif + } + } +#endif /* (FF_FS_NOFSINFO & 3) != 3 */ +#endif /* !FF_FS_READONLY */ + } + + fs->fs_type = fmt; /* FAT sub-type */ + fs->id = ++Fsid; /* Volume mount ID */ +#if FF_USE_LFN == 1 + fs->lfnbuf = LfnBuf; /* Static LFN working buffer */ +#if FF_FS_EXFAT + fs->dirbuf = DirBuf; /* Static directory block scratchpad buuffer */ +#endif +#endif +#if FF_FS_RPATH != 0 + fs->cdir = 0; /* Initialize current directory */ +#endif +#if FF_FS_LOCK != 0 /* Clear file lock semaphores */ + clear_lock(fs); +#endif + return FR_OK; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Check if the file/directory object is valid or not */ +/*-----------------------------------------------------------------------*/ + +static +FRESULT validate ( /* Returns FR_OK or FR_INVALID_OBJECT */ + FFOBJID* obj, /* Pointer to the FFOBJID, the 1st member in the FIL/DIR object, to check validity */ + FATFS** rfs /* Pointer to pointer to the owner filesystem object to return */ +) +{ + FRESULT res = FR_INVALID_OBJECT; + + + if (obj && obj->fs && obj->fs->fs_type && obj->id == obj->fs->id) { /* Test if the object is valid */ +#if FF_FS_REENTRANT + if (lock_fs(obj->fs)) { /* Obtain the filesystem object */ + if (!(disk_status(obj->fs->pdrv) & STA_NOINIT)) { /* Test if the phsical drive is kept initialized */ + res = FR_OK; + } else { + unlock_fs(obj->fs, FR_OK); + } + } else { + res = FR_TIMEOUT; + } +#else + if (!(disk_status(obj->fs->pdrv) & STA_NOINIT)) { /* Test if the phsical drive is kept initialized */ + res = FR_OK; + } +#endif + } + *rfs = (res == FR_OK) ? obj->fs : 0; /* Corresponding filesystem object */ + return res; +} + + + + +/*--------------------------------------------------------------------------- + + Public Functions (FatFs API) + +----------------------------------------------------------------------------*/ + + + +/*-----------------------------------------------------------------------*/ +/* Mount/Unmount a Logical Drive */ +/*-----------------------------------------------------------------------*/ +FRESULT f_mount ( + FATFS* fs, /* Pointer to the filesystem object (NULL:unmount)*/ + const TCHAR* path, /* Logical drive number to be mounted/unmounted */ + BYTE opt /* Mode option 0:Do not mount (delayed mount), 1:Mount immediately */ +) +{ + FATFS *cfs; + int vol; + FRESULT res; + const TCHAR *rp = path; + + /* Get logical drive number */ + vol = get_ldnumber(&rp); + if (vol < 0) return FR_INVALID_DRIVE; + cfs = FatFs[vol]; /* Pointer to fs object */ + + if (cfs) { +#if FF_FS_LOCK != 0 + clear_lock(cfs); +#endif +#if FF_FS_REENTRANT /* Discard sync object of the current volume */ + if (!ff_del_syncobj(cfs->sobj)) return FR_INT_ERR; +#endif + cfs->fs_type = 0; /* Clear old fs object */ + } + + if (fs) { + fs->fs_type = 0; /* Clear new fs object */ +#if FF_FS_REENTRANT /* Create sync object for the new volume */ + if (!ff_cre_syncobj((BYTE)vol, &fs->sobj)) return FR_INT_ERR; +#endif + } + FatFs[vol] = fs; /* Register new fs object */ + + if (opt == 0) return FR_OK; /* Do not mount now, it will be mounted later */ + + res = find_volume(&path, &fs, 0); /* Force mounted the volume */ + LEAVE_FF(fs, res); +} + +FRESULT f_unmount (BYTE pdrv,const TCHAR* path,BYTE opt) +{ + FRESULT res = FR_OK; + + res = disk_uninitialize(pdrv); + if(res != FR_OK) + res = FR_DISK_ERR; + else + { + + f_mount(0,path,opt); + } + + return res; +} + +/*-----------------------------------------------------------------------*/ +/* Open or Create a File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_open ( + FIL* fp, /* Pointer to the blank file object */ + const TCHAR* path, /* Pointer to the file name */ + BYTE mode /* Access mode and file open mode flags */ +) +{ + FRESULT res; + DIR dj; + FATFS *fs; +#if !FF_FS_READONLY + DWORD dw, cl, bcs, clst, sc; + FSIZE_t ofs; +#endif + DEF_NAMBUF + + + if (!fp) return FR_INVALID_OBJECT; + + /* Get logical drive */ + mode &= FF_FS_READONLY ? FA_READ : FA_READ | FA_WRITE | FA_CREATE_ALWAYS | FA_CREATE_NEW | FA_OPEN_ALWAYS | FA_OPEN_APPEND | FA_SEEKEND; + res = find_volume(&path, &fs, mode); + if (res == FR_OK) { + dj.obj.fs = fs; + INIT_NAMBUF(fs); + res = follow_path(&dj, path); /* Follow the file path */ +#if !FF_FS_READONLY /* Read/Write configuration */ + if (res == FR_OK) { + if (dj.fn[NSFLAG] & NS_NONAME) { /* Origin directory itself? */ + res = FR_INVALID_NAME; + } +#if FF_FS_LOCK != 0 + else { + res = chk_lock(&dj, (mode & ~FA_READ) ? 1 : 0); /* Check if the file can be used */ + } +#endif + } + /* Create or Open a file */ + if (mode & (FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)) { + if (res != FR_OK) { /* No file, create new */ + if (res == FR_NO_FILE) { /* There is no file to open, create a new entry */ +#if FF_FS_LOCK != 0 + res = enq_lock() ? dir_register(&dj) : FR_TOO_MANY_OPEN_FILES; +#else + res = dir_register(&dj); +#endif + } + mode |= FA_CREATE_ALWAYS; /* File is created */ + } + else { /* Any object with the same name is already existing */ + if (dj.obj.attr & (AM_RDO | AM_DIR)) { /* Cannot overwrite it (R/O or DIR) */ + res = FR_DENIED; + } else { + if (mode & FA_CREATE_NEW) res = FR_EXIST; /* Cannot create as new file */ + } + } + if (res == FR_OK && (mode & FA_CREATE_ALWAYS)) { /* Truncate the file if overwrite mode */ +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { + /* Get current allocation info */ + fp->obj.fs = fs; + fp->obj.sclust = cl = ld_dword(fs->dirbuf + XDIR_FstClus); + fp->obj.objsize = ld_qword(fs->dirbuf + XDIR_FileSize); + fp->obj.stat = fs->dirbuf[XDIR_GenFlags] & 2; + fp->obj.n_frag = 0; + /* Set directory entry block initial state */ + mem_set(fs->dirbuf + 2, 0, 30); /* Clear 85 entry except for NumSec */ + mem_set(fs->dirbuf + 38, 0, 26); /* Clear C0 entry except for NumName and NameHash */ + fs->dirbuf[XDIR_Attr] = AM_ARC; + st_dword(fs->dirbuf + XDIR_CrtTime, GET_FATTIME()); + fs->dirbuf[XDIR_GenFlags] = 1; + res = store_xdir(&dj); + if (res == FR_OK && cl != 0) { /* Remove the cluster chain if exist */ + res = remove_chain(&fp->obj, cl, 0); + fs->last_clst = cl - 1; /* Reuse the cluster hole */ + } + } else +#endif + { + /* Set directory entry initial state */ + cl = ld_clust(fs, dj.dir); /* Get current cluster chain */ + st_dword(dj.dir + DIR_CrtTime, GET_FATTIME()); /* Set created time */ + dj.dir[DIR_Attr] = AM_ARC; /* Reset attribute */ + st_clust(fs, dj.dir, 0); /* Reset file allocation info */ + st_dword(dj.dir + DIR_FileSize, 0); + fs->wflag = 1; + if (cl != 0) { /* Remove the cluster chain if exist */ + dw = fs->winsect; + res = remove_chain(&dj.obj, cl, 0); + if (res == FR_OK) { + res = move_window(fs, dw); + fs->last_clst = cl - 1; /* Reuse the cluster hole */ + } + } + } + } + } + else { /* Open an existing file */ + if (res == FR_OK) { /* Is the object exsiting? */ + if (dj.obj.attr & AM_DIR) { /* File open against a directory */ + res = FR_NO_FILE; + } else { + if ((mode & FA_WRITE) && (dj.obj.attr & AM_RDO)) { /* Write mode open against R/O file */ + res = FR_DENIED; + } + } + } + } + if (res == FR_OK) { + if (mode & FA_CREATE_ALWAYS) mode |= FA_MODIFIED; /* Set file change flag if created or overwritten */ + fp->dir_sect = fs->winsect; /* Pointer to the directory entry */ + fp->dir_ptr = dj.dir; +#if FF_FS_LOCK != 0 + fp->obj.lockid = inc_lock(&dj, (mode & ~FA_READ) ? 1 : 0); /* Lock the file for this session */ + if (!fp->obj.lockid) res = FR_INT_ERR; +#endif + } +#else /* R/O configuration */ + if (res == FR_OK) { + if (dj.fn[NSFLAG] & NS_NONAME) { /* Is it origin directory itself? */ + res = FR_INVALID_NAME; + } else { + if (dj.obj.attr & AM_DIR) { /* Is it a directory? */ + res = FR_NO_FILE; + } + } + } +#endif + + if (res == FR_OK) { +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { + fp->obj.c_scl = dj.obj.sclust; /* Get containing directory info */ + fp->obj.c_size = ((DWORD)dj.obj.objsize & 0xFFFFFF00) | dj.obj.stat; + fp->obj.c_ofs = dj.blk_ofs; + fp->obj.sclust = ld_dword(fs->dirbuf + XDIR_FstClus); /* Get object allocation info */ + fp->obj.objsize = ld_qword(fs->dirbuf + XDIR_FileSize); + fp->obj.stat = fs->dirbuf[XDIR_GenFlags] & 2; + fp->obj.n_frag = 0; + } else +#endif + { + fp->obj.sclust = ld_clust(fs, dj.dir); /* Get object allocation info */ + fp->obj.objsize = ld_dword(dj.dir + DIR_FileSize); + } +#if FF_USE_FASTSEEK + fp->cltbl = 0; /* Disable fast seek mode */ +#endif + fp->obj.fs = fs; /* Validate the file object */ + fp->obj.id = fs->id; + fp->flag = mode; /* Set file access mode */ + fp->err = 0; /* Clear error flag */ + fp->sect = 0; /* Invalidate current data sector */ + fp->fptr = 0; /* Set file pointer top of the file */ +#if !FF_FS_READONLY +#if !FF_FS_TINY + mem_set(fp->buf, 0, FF_MAX_SS); /* Clear sector buffer */ +#endif + if ((mode & FA_SEEKEND) && fp->obj.objsize > 0) { /* Seek to end of file if FA_OPEN_APPEND is specified */ + fp->fptr = fp->obj.objsize; /* Offset to seek */ + bcs = (DWORD)fs->csize * SS(fs); /* Cluster size in byte */ + clst = fp->obj.sclust; /* Follow the cluster chain */ + for (ofs = fp->obj.objsize; res == FR_OK && ofs > bcs; ofs -= bcs) { + clst = get_fat(&fp->obj, clst); + if (clst <= 1) res = FR_INT_ERR; + if (clst == 0xFFFFFFFF) res = FR_DISK_ERR; + } + fp->clust = clst; + if (res == FR_OK && ofs % SS(fs)) { /* Fill sector buffer if not on the sector boundary */ + if ((sc = clst2sect(fs, clst)) == 0) { + res = FR_INT_ERR; + } else { + fp->sect = sc + (DWORD)(ofs / SS(fs)); +#if !FF_FS_TINY + if (disk_read(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) res = FR_DISK_ERR; +#endif + } + } + } +#endif + } + + FREE_NAMBUF(); + } + + if (res != FR_OK) fp->obj.fs = 0; /* Invalidate file object on error */ + + LEAVE_FF(fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Read File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_read ( + FIL* fp, /* Pointer to the file object */ + void* buff, /* Pointer to data buffer */ + UINT btr, /* Number of bytes to read */ + UINT* br /* Pointer to number of bytes read */ +) +{ + FRESULT res; + FATFS *fs; + DWORD clst, sect; + FSIZE_t remain; + UINT rcnt, cc, csect; + BYTE *rbuff = (BYTE*)buff; + + + *br = 0; /* Clear read byte counter */ + res = validate(&fp->obj, &fs); /* Check validity of the file object */ + if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); /* Check validity */ + if (!(fp->flag & FA_READ)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */ + remain = fp->obj.objsize - fp->fptr; + if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */ + + for ( ; btr; /* Repeat until all data read */ + btr -= rcnt, *br += rcnt, rbuff += rcnt, fp->fptr += rcnt) { + if (fp->fptr % SS(fs) == 0) { /* On the sector boundary? */ + csect = (UINT)(fp->fptr / SS(fs) & (fs->csize - 1)); /* Sector offset in the cluster */ + if (csect == 0) { /* On the cluster boundary? */ + if (fp->fptr == 0) { /* On the top of the file? */ + clst = fp->obj.sclust; /* Follow cluster chain from the origin */ + } else { /* Middle or end of the file */ +#if FF_USE_FASTSEEK + if (fp->cltbl) { + clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */ + } else +#endif + { + clst = get_fat(&fp->obj, fp->clust); /* Follow cluster chain on the FAT */ + } + } + if (clst < 2) ABORT(fs, FR_INT_ERR); + if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR); + fp->clust = clst; /* Update current cluster */ + } + sect = clst2sect(fs, fp->clust); /* Get current sector */ + if (sect == 0) ABORT(fs, FR_INT_ERR); + sect += csect; + cc = btr / SS(fs); /* When remaining bytes >= sector size, */ + if (cc > 0) { /* Read maximum contiguous sectors directly */ + if (csect + cc > fs->csize) { /* Clip at cluster boundary */ + cc = fs->csize - csect; + } + if (disk_read(fs->pdrv, rbuff, sect, cc) != RES_OK) ABORT(fs, FR_DISK_ERR); +#if !FF_FS_READONLY && FF_FS_MINIMIZE <= 2 /* Replace one of the read sectors with cached data if it contains a dirty sector */ +#if FF_FS_TINY + if (fs->wflag && fs->winsect - sect < cc) { + mem_cpy(rbuff + ((fs->winsect - sect) * SS(fs)), fs->win, SS(fs)); + } +#else + if ((fp->flag & FA_DIRTY) && fp->sect - sect < cc) { + mem_cpy(rbuff + ((fp->sect - sect) * SS(fs)), fp->buf, SS(fs)); + } +#endif +#endif + rcnt = SS(fs) * cc; /* Number of bytes transferred */ + continue; + } +#if !FF_FS_TINY + if (fp->sect != sect) { /* Load data sector if not in cache */ +#if !FF_FS_READONLY + if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */ + if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); + fp->flag &= (BYTE)~FA_DIRTY; + } +#endif + if (disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); /* Fill sector cache */ + } +#endif + fp->sect = sect; + } + rcnt = SS(fs) - (UINT)fp->fptr % SS(fs); /* Number of bytes left in the sector */ + if (rcnt > btr) rcnt = btr; /* Clip it by btr if needed */ +#if FF_FS_TINY + if (move_window(fs, fp->sect) != FR_OK) ABORT(fs, FR_DISK_ERR); /* Move sector window */ + mem_cpy(rbuff, fs->win + fp->fptr % SS(fs), rcnt); /* Extract partial sector */ +#else + mem_cpy(rbuff, fp->buf + fp->fptr % SS(fs), rcnt); /* Extract partial sector */ +#endif + } + + LEAVE_FF(fs, FR_OK); +} + + + + +#if !FF_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Write File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_write ( + FIL* fp, /* Pointer to the file object */ + const void* buff, /* Pointer to the data to be written */ + UINT btw, /* Number of bytes to write */ + UINT* bw /* Pointer to number of bytes written */ +) +{ + FRESULT res; + FATFS *fs; + DWORD clst, sect; + UINT wcnt, cc, csect; + const BYTE *wbuff = (const BYTE*)buff; + + + *bw = 0; /* Clear write byte counter */ + res = validate(&fp->obj, &fs); /* Check validity of the file object */ + if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); /* Check validity */ + if (!(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */ + + /* Check fptr wrap-around (file size cannot reach 4 GiB at FAT volume) */ + if ((!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) && (DWORD)(fp->fptr + btw) < (DWORD)fp->fptr) { + btw = (UINT)(0xFFFFFFFF - (DWORD)fp->fptr); + } + + for ( ; btw; /* Repeat until all data written */ + btw -= wcnt, *bw += wcnt, wbuff += wcnt, fp->fptr += wcnt, fp->obj.objsize = (fp->fptr > fp->obj.objsize) ? fp->fptr : fp->obj.objsize) { + if (fp->fptr % SS(fs) == 0) { /* On the sector boundary? */ + csect = (UINT)(fp->fptr / SS(fs)) & (fs->csize - 1); /* Sector offset in the cluster */ + if (csect == 0) { /* On the cluster boundary? */ + if (fp->fptr == 0) { /* On the top of the file? */ + clst = fp->obj.sclust; /* Follow from the origin */ + if (clst == 0) { /* If no cluster is allocated, */ + clst = create_chain(&fp->obj, 0); /* create a new cluster chain */ + } + } else { /* On the middle or end of the file */ +#if FF_USE_FASTSEEK + if (fp->cltbl) { + clst = clmt_clust(fp, fp->fptr); /* Get cluster# from the CLMT */ + } else +#endif + { + clst = create_chain(&fp->obj, fp->clust); /* Follow or stretch cluster chain on the FAT */ + } + } + if (clst == 0) break; /* Could not allocate a new cluster (disk full) */ + if (clst == 1) ABORT(fs, FR_INT_ERR); + if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR); + fp->clust = clst; /* Update current cluster */ + if (fp->obj.sclust == 0) fp->obj.sclust = clst; /* Set start cluster if the first write */ + } +#if FF_FS_TINY + if (fs->winsect == fp->sect && sync_window(fs) != FR_OK) ABORT(fs, FR_DISK_ERR); /* Write-back sector cache */ +#else + if (fp->flag & FA_DIRTY) { /* Write-back sector cache */ + if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); + fp->flag &= (BYTE)~FA_DIRTY; + } +#endif + sect = clst2sect(fs, fp->clust); /* Get current sector */ + if (sect == 0) ABORT(fs, FR_INT_ERR); + sect += csect; + cc = btw / SS(fs); /* When remaining bytes >= sector size, */ + if (cc > 0) { /* Write maximum contiguous sectors directly */ + if (csect + cc > fs->csize) { /* Clip at cluster boundary */ + cc = fs->csize - csect; + } + if (disk_write(fs->pdrv, (BYTE*)wbuff, sect, cc) != RES_OK) ABORT(fs, FR_DISK_ERR); +#if FF_FS_MINIMIZE <= 2 +#if FF_FS_TINY + if (fs->winsect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */ + mem_cpy(fs->win, wbuff + ((fs->winsect - sect) * SS(fs)), SS(fs)); + fs->wflag = 0; + } +#else + if (fp->sect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */ + mem_cpy(fp->buf, wbuff + ((fp->sect - sect) * SS(fs)), SS(fs)); + fp->flag &= (BYTE)~FA_DIRTY; + } +#endif +#endif + wcnt = SS(fs) * cc; /* Number of bytes transferred */ + continue; + } +#if FF_FS_TINY + if (fp->fptr >= fp->obj.objsize) { /* Avoid silly cache filling on the growing edge */ + if (sync_window(fs) != FR_OK) ABORT(fs, FR_DISK_ERR); + fs->winsect = sect; + } +#else + if (fp->sect != sect && /* Fill sector cache with file data */ + fp->fptr < fp->obj.objsize && + disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) { + ABORT(fs, FR_DISK_ERR); + } +#endif + fp->sect = sect; + } + wcnt = SS(fs) - (UINT)fp->fptr % SS(fs); /* Number of bytes left in the sector */ + if (wcnt > btw) wcnt = btw; /* Clip it by btw if needed */ +#if FF_FS_TINY + if (move_window(fs, fp->sect) != FR_OK) ABORT(fs, FR_DISK_ERR); /* Move sector window */ + mem_cpy(fs->win + fp->fptr % SS(fs), wbuff, wcnt); /* Fit data to the sector */ + fs->wflag = 1; +#else + mem_cpy(fp->buf + fp->fptr % SS(fs), wbuff, wcnt); /* Fit data to the sector */ + fp->flag |= FA_DIRTY; +#endif + } + + fp->flag |= FA_MODIFIED; /* Set file change flag */ + + LEAVE_FF(fs, FR_OK); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Synchronize the File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_sync ( + FIL* fp /* Pointer to the file object */ +) +{ + FRESULT res; + FATFS *fs; + DWORD tm; + BYTE *dir; + + + res = validate(&fp->obj, &fs); /* Check validity of the file object */ + if (res == FR_OK) { + if (fp->flag & FA_MODIFIED) { /* Is there any change to the file? */ +#if !FF_FS_TINY + if (fp->flag & FA_DIRTY) { /* Write-back cached data if needed */ + if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) LEAVE_FF(fs, FR_DISK_ERR); + fp->flag &= (BYTE)~FA_DIRTY; + } +#endif + /* Update the directory entry */ + tm = GET_FATTIME(); /* Modified time */ +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { + res = fill_first_frag(&fp->obj); /* Fill first fragment on the FAT if needed */ + if (res == FR_OK) { + res = fill_last_frag(&fp->obj, fp->clust, 0xFFFFFFFF); /* Fill last fragment on the FAT if needed */ + } + if (res == FR_OK) { + DIR dj; + DEF_NAMBUF + + INIT_NAMBUF(fs); + res = load_obj_xdir(&dj, &fp->obj); /* Load directory entry block */ + if (res == FR_OK) { + fs->dirbuf[XDIR_Attr] |= AM_ARC; /* Set archive attribute to indicate that the file has been changed */ + fs->dirbuf[XDIR_GenFlags] = fp->obj.stat | 1; /* Update file allocation information */ + st_dword(fs->dirbuf + XDIR_FstClus, fp->obj.sclust); + st_qword(fs->dirbuf + XDIR_FileSize, fp->obj.objsize); + st_qword(fs->dirbuf + XDIR_ValidFileSize, fp->obj.objsize); + st_dword(fs->dirbuf + XDIR_ModTime, tm); /* Update modified time */ + fs->dirbuf[XDIR_ModTime10] = 0; + st_dword(fs->dirbuf + XDIR_AccTime, 0); + res = store_xdir(&dj); /* Restore it to the directory */ + if (res == FR_OK) { + res = sync_fs(fs); + fp->flag &= (BYTE)~FA_MODIFIED; + } + } + FREE_NAMBUF(); + } + } else +#endif + { + res = move_window(fs, fp->dir_sect); + if (res == FR_OK) { + dir = fp->dir_ptr; + dir[DIR_Attr] |= AM_ARC; /* Set archive attribute to indicate that the file has been changed */ + st_clust(fp->obj.fs, dir, fp->obj.sclust); /* Update file allocation information */ + st_dword(dir + DIR_FileSize, (DWORD)fp->obj.objsize); /* Update file size */ + st_dword(dir + DIR_ModTime, tm); /* Update modified time */ + st_word(dir + DIR_LstAccDate, 0); + fs->wflag = 1; + res = sync_fs(fs); /* Restore it to the directory */ + fp->flag &= (BYTE)~FA_MODIFIED; + } + } + } + } + + LEAVE_FF(fs, res); +} + +#endif /* !FF_FS_READONLY */ + + + + +/*-----------------------------------------------------------------------*/ +/* Close File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_close ( + FIL* fp /* Pointer to the file object to be closed */ +) +{ + FRESULT res; + FATFS *fs; + +#if !FF_FS_READONLY + res = f_sync(fp); /* Flush cached data */ + if (res == FR_OK) +#endif + { + res = validate(&fp->obj, &fs); /* Lock volume */ + if (res == FR_OK) { +#if FF_FS_LOCK != 0 + res = dec_lock(fp->obj.lockid); /* Decrement file open counter */ + if (res == FR_OK) fp->obj.fs = 0; /* Invalidate file object */ +#else + fp->obj.fs = 0; /* Invalidate file object */ +#endif +#if FF_FS_REENTRANT + unlock_fs(fs, FR_OK); /* Unlock volume */ +#endif + } + } + return res; +} + + + + +#if FF_FS_RPATH >= 1 +/*-----------------------------------------------------------------------*/ +/* Change Current Directory or Current Drive, Get Current Directory */ +/*-----------------------------------------------------------------------*/ + +#if FF_VOLUMES >= 2 +FRESULT f_chdrive ( + const TCHAR* path /* Drive number */ +) +{ + int vol; + + + /* Get logical drive number */ + vol = get_ldnumber(&path); + if (vol < 0) return FR_INVALID_DRIVE; + + CurrVol = (BYTE)vol; /* Set it as current volume */ + + return FR_OK; +} +#endif + + +FRESULT f_chdir ( + const TCHAR* path /* Pointer to the directory path */ +) +{ + FRESULT res; + DIR dj; + FATFS *fs; + DEF_NAMBUF + + /* Get logical drive */ + res = find_volume(&path, &fs, 0); + if (res == FR_OK) { + dj.obj.fs = fs; + INIT_NAMBUF(fs); + res = follow_path(&dj, path); /* Follow the path */ + if (res == FR_OK) { /* Follow completed */ + if (dj.fn[NSFLAG] & NS_NONAME) { + fs->cdir = dj.obj.sclust; /* It is the start directory itself */ +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { + fs->cdc_scl = dj.obj.c_scl; + fs->cdc_size = dj.obj.c_size; + fs->cdc_ofs = dj.obj.c_ofs; + } +#endif + } else { + if (dj.obj.attr & AM_DIR) { /* It is a sub-directory */ +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { + fs->cdir = ld_dword(fs->dirbuf + XDIR_FstClus); /* Sub-directory cluster */ + fs->cdc_scl = dj.obj.sclust; /* Save containing directory information */ + fs->cdc_size = ((DWORD)dj.obj.objsize & 0xFFFFFF00) | dj.obj.stat; + fs->cdc_ofs = dj.blk_ofs; + } else +#endif + { + fs->cdir = ld_clust(fs, dj.dir); /* Sub-directory cluster */ + } + } else { + res = FR_NO_PATH; /* Reached but a file */ + } + } + } + FREE_NAMBUF(); + if (res == FR_NO_FILE) res = FR_NO_PATH; + } + + LEAVE_FF(fs, res); +} + + +#if FF_FS_RPATH >= 2 +FRESULT f_getcwd ( + TCHAR* buff, /* Pointer to the directory path */ + UINT len /* Size of path */ +) +{ + FRESULT res; + DIR dj; + FATFS *fs; + UINT i, n; + DWORD ccl; + TCHAR *tp; + FILINFO fno; + DEF_NAMBUF + + + *buff = 0; + /* Get logical drive */ + res = find_volume((const TCHAR**)&buff, &fs, 0); /* Get current volume */ + if (res == FR_OK) { + dj.obj.fs = fs; + INIT_NAMBUF(fs); + i = len; /* Bottom of buffer (directory stack base) */ + if (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) { /* (Cannot do getcwd on exFAT and returns root path) */ + dj.obj.sclust = fs->cdir; /* Start to follow upper directory from current directory */ + while ((ccl = dj.obj.sclust) != 0) { /* Repeat while current directory is a sub-directory */ + res = dir_sdi(&dj, 1 * SZDIRE); /* Get parent directory */ + if (res != FR_OK) break; + res = move_window(fs, dj.sect); + if (res != FR_OK) break; + dj.obj.sclust = ld_clust(fs, dj.dir); /* Goto parent directory */ + res = dir_sdi(&dj, 0); + if (res != FR_OK) break; + do { /* Find the entry links to the child directory */ + res = dir_read(&dj, 0); + if (res != FR_OK) break; + if (ccl == ld_clust(fs, dj.dir)) break; /* Found the entry */ + res = dir_next(&dj, 0); + } while (res == FR_OK); + if (res == FR_NO_FILE) res = FR_INT_ERR;/* It cannot be 'not found'. */ + if (res != FR_OK) break; + get_fileinfo(&dj, &fno); /* Get the directory name and push it to the buffer */ + for (n = 0; fno.fname[n]; n++) ; + if (i < n + 3) { + res = FR_NOT_ENOUGH_CORE; break; + } + while (n) buff[--i] = fno.fname[--n]; + buff[--i] = '/'; + } + } + tp = buff; + if (res == FR_OK) { +#if FF_VOLUMES >= 2 + *tp++ = '0' + CurrVol; /* Put drive number */ + *tp++ = ':'; +#endif + if (i == len) { /* Root-directory */ + *tp++ = '/'; + } else { /* Sub-directroy */ + do /* Add stacked path str */ + *tp++ = buff[i++]; + while (i < len); + } + } + *tp = 0; + FREE_NAMBUF(); + } + + LEAVE_FF(fs, res); +} + +#endif /* FF_FS_RPATH >= 2 */ +#endif /* FF_FS_RPATH >= 1 */ + + + +#if FF_FS_MINIMIZE <= 2 +/*-----------------------------------------------------------------------*/ +/* Seek File Read/Write Pointer */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_lseek ( + FIL* fp, /* Pointer to the file object */ + FSIZE_t ofs /* File pointer from top of file */ +) +{ + FRESULT res; + FATFS *fs; + DWORD clst, bcs, nsect; + FSIZE_t ifptr; +#if FF_USE_FASTSEEK + DWORD cl, pcl, ncl, tcl, dsc, tlen, ulen, *tbl; +#endif + + res = validate(&fp->obj, &fs); /* Check validity of the file object */ + if (res == FR_OK) res = (FRESULT)fp->err; +#if FF_FS_EXFAT && !FF_FS_READONLY + if (res == FR_OK && fs->fs_type == FS_EXFAT) { + res = fill_last_frag(&fp->obj, fp->clust, 0xFFFFFFFF); /* Fill last fragment on the FAT if needed */ + } +#endif + if (res != FR_OK) LEAVE_FF(fs, res); + +#if FF_USE_FASTSEEK + if (fp->cltbl) { /* Fast seek */ + if (ofs == CREATE_LINKMAP) { /* Create CLMT */ + tbl = fp->cltbl; + tlen = *tbl++; ulen = 2; /* Given table size and required table size */ + cl = fp->obj.sclust; /* Origin of the chain */ + if (cl != 0) { + do { + /* Get a fragment */ + tcl = cl; ncl = 0; ulen += 2; /* Top, length and used items */ + do { + pcl = cl; ncl++; + cl = get_fat(&fp->obj, cl); + if (cl <= 1) ABORT(fs, FR_INT_ERR); + if (cl == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR); + } while (cl == pcl + 1); + if (ulen <= tlen) { /* Store the length and top of the fragment */ + *tbl++ = ncl; *tbl++ = tcl; + } + } while (cl < fs->n_fatent); /* Repeat until end of chain */ + } + *fp->cltbl = ulen; /* Number of items used */ + if (ulen <= tlen) { + *tbl = 0; /* Terminate table */ + } else { + res = FR_NOT_ENOUGH_CORE; /* Given table size is smaller than required */ + } + } else { /* Fast seek */ + if (ofs > fp->obj.objsize) ofs = fp->obj.objsize; /* Clip offset at the file size */ + fp->fptr = ofs; /* Set file pointer */ + if (ofs > 0) { + fp->clust = clmt_clust(fp, ofs - 1); + dsc = clst2sect(fs, fp->clust); + if (dsc == 0) ABORT(fs, FR_INT_ERR); + dsc += (DWORD)((ofs - 1) / SS(fs)) & (fs->csize - 1); + if (fp->fptr % SS(fs) && dsc != fp->sect) { /* Refill sector cache if needed */ +#if !FF_FS_TINY +#if !FF_FS_READONLY + if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */ + if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); + fp->flag &= (BYTE)~FA_DIRTY; + } +#endif + if (disk_read(fs->pdrv, fp->buf, dsc, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); /* Load current sector */ +#endif + fp->sect = dsc; + } + } + } + } else +#endif + + /* Normal Seek */ + { +#if FF_FS_EXFAT + if (fs->fs_type != FS_EXFAT && ofs >= 0x100000000) ofs = 0xFFFFFFFF; /* Clip at 4 GiB - 1 if at FATxx */ +#endif + if (ofs > fp->obj.objsize && (FF_FS_READONLY || !(fp->flag & FA_WRITE))) { /* In read-only mode, clip offset with the file size */ + ofs = fp->obj.objsize; + } + ifptr = fp->fptr; + fp->fptr = nsect = 0; + if (ofs > 0) { + bcs = (DWORD)fs->csize * SS(fs); /* Cluster size (byte) */ + if (ifptr > 0 && + (ofs - 1) / bcs >= (ifptr - 1) / bcs) { /* When seek to same or following cluster, */ + fp->fptr = (ifptr - 1) & ~(FSIZE_t)(bcs - 1); /* start from the current cluster */ + ofs -= fp->fptr; + clst = fp->clust; + } else { /* When seek to back cluster, */ + clst = fp->obj.sclust; /* start from the first cluster */ +#if !FF_FS_READONLY + if (clst == 0) { /* If no cluster chain, create a new chain */ + clst = create_chain(&fp->obj, 0); + if (clst == 1) ABORT(fs, FR_INT_ERR); + if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR); + fp->obj.sclust = clst; + } +#endif + fp->clust = clst; + } + if (clst != 0) { + while (ofs > bcs) { /* Cluster following loop */ + ofs -= bcs; fp->fptr += bcs; +#if !FF_FS_READONLY + if (fp->flag & FA_WRITE) { /* Check if in write mode or not */ + if (FF_FS_EXFAT && fp->fptr > fp->obj.objsize) { /* No FAT chain object needs correct objsize to generate FAT value */ + fp->obj.objsize = fp->fptr; + fp->flag |= FA_MODIFIED; + } + clst = create_chain(&fp->obj, clst); /* Follow chain with forceed stretch */ + if (clst == 0) { /* Clip file size in case of disk full */ + ofs = 0; break; + } + } else +#endif + { + clst = get_fat(&fp->obj, clst); /* Follow cluster chain if not in write mode */ + } + if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR); + if (clst <= 1 || clst >= fs->n_fatent) ABORT(fs, FR_INT_ERR); + fp->clust = clst; + } + fp->fptr += ofs; + if (ofs % SS(fs)) { + nsect = clst2sect(fs, clst); /* Current sector */ + if (nsect == 0) ABORT(fs, FR_INT_ERR); + nsect += (DWORD)(ofs / SS(fs)); + } + } + } + if (!FF_FS_READONLY && fp->fptr > fp->obj.objsize) { /* Set file change flag if the file size is extended */ + fp->obj.objsize = fp->fptr; + fp->flag |= FA_MODIFIED; + } + if (fp->fptr % SS(fs) && nsect != fp->sect) { /* Fill sector cache if needed */ +#if !FF_FS_TINY +#if !FF_FS_READONLY + if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */ + if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); + fp->flag &= (BYTE)~FA_DIRTY; + } +#endif + if (disk_read(fs->pdrv, fp->buf, nsect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); /* Fill sector cache */ +#endif + fp->sect = nsect; + } + } + + LEAVE_FF(fs, res); +} + + + +#if FF_FS_MINIMIZE <= 1 +/*-----------------------------------------------------------------------*/ +/* Create a Directory Object */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_opendir ( + DIR* dp, /* Pointer to directory object to create */ + const TCHAR* path /* Pointer to the directory path */ +) +{ + FRESULT res; + FATFS *fs; + DEF_NAMBUF + + + if (!dp) return FR_INVALID_OBJECT; + + /* Get logical drive */ + res = find_volume(&path, &fs, 0); + + if (res == FR_OK) { + dp->obj.fs = fs; + INIT_NAMBUF(fs); + res = follow_path(dp, path); /* Follow the path to the directory */ + if (res == FR_OK) { /* Follow completed */ + if (!(dp->fn[NSFLAG] & NS_NONAME)) { /* It is not the origin directory itself */ + if (dp->obj.attr & AM_DIR) { /* This object is a sub-directory */ +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { + dp->obj.c_scl = dp->obj.sclust; /* Get containing directory inforamation */ + dp->obj.c_size = ((DWORD)dp->obj.objsize & 0xFFFFFF00) | dp->obj.stat; + dp->obj.c_ofs = dp->blk_ofs; + dp->obj.sclust = ld_dword(fs->dirbuf + XDIR_FstClus); /* Get object allocation info */ + dp->obj.objsize = ld_qword(fs->dirbuf + XDIR_FileSize); + dp->obj.stat = fs->dirbuf[XDIR_GenFlags] & 2; + } else +#endif + { + dp->obj.sclust = ld_clust(fs, dp->dir); /* Get object allocation info */ + } + } else { /* This object is a file */ + res = FR_NO_PATH; + } + } + if (res == FR_OK) { + dp->obj.id = fs->id; + res = dir_sdi(dp, 0); /* Rewind directory */ +#if FF_FS_LOCK != 0 + if (res == FR_OK) { + if (dp->obj.sclust != 0) { + dp->obj.lockid = inc_lock(dp, 0); /* Lock the sub directory */ + if (!dp->obj.lockid) res = FR_TOO_MANY_OPEN_FILES; + } else { + dp->obj.lockid = 0; /* Root directory need not to be locked */ + } + } +#endif + } + } + FREE_NAMBUF(); + if (res == FR_NO_FILE) res = FR_NO_PATH; + } + if (res != FR_OK) dp->obj.fs = 0; /* Invalidate the directory object if function faild */ + + LEAVE_FF(fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Close Directory */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_closedir ( + DIR *dp /* Pointer to the directory object to be closed */ +) +{ + FRESULT res; + FATFS *fs; + + + res = validate(&dp->obj, &fs); /* Check validity of the file object */ + if (res == FR_OK) { +#if FF_FS_LOCK != 0 + if (dp->obj.lockid) res = dec_lock(dp->obj.lockid); /* Decrement sub-directory open counter */ + if (res == FR_OK) dp->obj.fs = 0; /* Invalidate directory object */ +#else + dp->obj.fs = 0; /* Invalidate directory object */ +#endif +#if FF_FS_REENTRANT + unlock_fs(fs, FR_OK); /* Unlock volume */ +#endif + } + return res; +} + + + + +/*-----------------------------------------------------------------------*/ +/* Read Directory Entries in Sequence */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_readdir ( + DIR* dp, /* Pointer to the open directory object */ + FILINFO* fno /* Pointer to file information to return */ +) +{ + FRESULT res; + FATFS *fs; + DEF_NAMBUF + + res = validate(&dp->obj, &fs); /* Check validity of the directory object */ + if (res == FR_OK) { + if (!fno) { + res = dir_sdi(dp, 0); /* Rewind the directory object */ + } else { + INIT_NAMBUF(fs); + res = dir_read(dp, 0); /* Read an item */ + if (res == FR_NO_FILE) res = FR_OK; /* Ignore end of directory */ + if (res == FR_OK) { /* A valid entry is found */ + get_fileinfo(dp, fno); /* Get the object information */ + res = dir_next(dp, 0); /* Increment index for next */ + if (res == FR_NO_FILE) res = FR_OK; /* Ignore end of directory now */ + } + FREE_NAMBUF(); + } + } + LEAVE_FF(fs, res); +} + + + +#if FF_USE_FIND +/*-----------------------------------------------------------------------*/ +/* Find Next File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_findnext ( + DIR* dp, /* Pointer to the open directory object */ + FILINFO* fno /* Pointer to the file information structure */ +) +{ + FRESULT res; + + + for (;;) { + res = f_readdir(dp, fno); /* Get a directory item */ + if (res != FR_OK || !fno || !fno->fname[0]) break; /* Terminate if any error or end of directory */ + if (pattern_matching(dp->pat, fno->fname, 0, 0)) break; /* Test for the file name */ +#if FF_USE_LFN && FF_USE_FIND == 2 + if (pattern_matching(dp->pat, fno->altname, 0, 0)) break; /* Test for alternative name if exist */ +#endif + } + return res; +} + + + +/*-----------------------------------------------------------------------*/ +/* Find First File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_findfirst ( + DIR* dp, /* Pointer to the blank directory object */ + FILINFO* fno, /* Pointer to the file information structure */ + const TCHAR* path, /* Pointer to the directory to open */ + const TCHAR* pattern /* Pointer to the matching pattern */ +) +{ + FRESULT res; + + + dp->pat = pattern; /* Save pointer to pattern string */ + res = f_opendir(dp, path); /* Open the target directory */ + if (res == FR_OK) { + res = f_findnext(dp, fno); /* Find the first item */ + } + return res; +} + +#endif /* FF_USE_FIND */ + + + +#if FF_FS_MINIMIZE == 0 +/*-----------------------------------------------------------------------*/ +/* Get File Status */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_stat ( + const TCHAR* path, /* Pointer to the file path */ + FILINFO* fno /* Pointer to file information to return */ +) +{ + FRESULT res; + DIR dj; + DEF_NAMBUF + + + /* Get logical drive */ + res = find_volume(&path, &dj.obj.fs, 0); + if (res == FR_OK) { + INIT_NAMBUF(dj.obj.fs); + res = follow_path(&dj, path); /* Follow the file path */ + if (res == FR_OK) { /* Follow completed */ + if (dj.fn[NSFLAG] & NS_NONAME) { /* It is origin directory */ + res = FR_INVALID_NAME; + } else { /* Found an object */ + if (fno) get_fileinfo(&dj, fno); + } + } + FREE_NAMBUF(); + } + + LEAVE_FF(dj.obj.fs, res); +} + + + +#if !FF_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Get Number of Free Clusters */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_getfree ( + const TCHAR* path, /* Path name of the logical drive number */ + DWORD* nclst, /* Pointer to a variable to return number of free clusters */ + FATFS** fatfs /* Pointer to return pointer to corresponding filesystem object */ +) +{ + FRESULT res; + FATFS *fs; + DWORD nfree, clst, sect, stat; + UINT i; + FFOBJID obj; + + + /* Get logical drive */ + res = find_volume(&path, &fs, 0); + if (res == FR_OK) { + *fatfs = fs; /* Return ptr to the fs object */ + /* If free_clst is valid, return it without full FAT scan */ + if (fs->free_clst <= fs->n_fatent - 2) { + *nclst = fs->free_clst; + } else { + /* Scan FAT to obtain number of free clusters */ + nfree = 0; + if (fs->fs_type == FS_FAT12) { /* FAT12: Scan bit field FAT entries */ + clst = 2; obj.fs = fs; + do { + stat = get_fat(&obj, clst); + if (stat == 0xFFFFFFFF) { res = FR_DISK_ERR; break; } + if (stat == 1) { res = FR_INT_ERR; break; } + if (stat == 0) nfree++; + } while (++clst < fs->n_fatent); + } else { +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { /* exFAT: Scan allocation bitmap */ + BYTE bm; + UINT b; + + clst = fs->n_fatent - 2; /* Number of clusters */ + sect = fs->database; /* Assuming bitmap starts at cluster 2 */ + i = 0; /* Offset in the sector */ + do { /* Counts numbuer of bits with zero in the bitmap */ + if (i == 0) { + res = move_window(fs, sect++); + if (res != FR_OK) break; + } + for (b = 8, bm = fs->win[i]; b && clst; b--, clst--) { + if (!(bm & 1)) nfree++; + bm >>= 1; + } + i = (i + 1) % SS(fs); + } while (clst); + } else +#endif + { /* FAT16/32: Scan WORD/DWORD FAT entries */ + clst = fs->n_fatent; /* Number of entries */ + sect = fs->fatbase; /* Top of the FAT */ + i = 0; /* Offset in the sector */ + do { /* Counts numbuer of entries with zero in the FAT */ + if (i == 0) { + res = move_window(fs, sect++); + if (res != FR_OK) break; + } + if (fs->fs_type == FS_FAT16) { + if (ld_word(fs->win + i) == 0) nfree++; + i += 2; + } else { + if ((ld_dword(fs->win + i) & 0x0FFFFFFF) == 0) nfree++; + i += 4; + } + i %= SS(fs); + } while (--clst); + } + } + *nclst = nfree; /* Return the free clusters */ + fs->free_clst = nfree; /* Now free_clst is valid */ + fs->fsi_flag |= 1; /* FAT32: FSInfo is to be updated */ + } + } + + LEAVE_FF(fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Truncate File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_truncate ( + FIL* fp /* Pointer to the file object */ +) +{ + FRESULT res; + FATFS *fs; + DWORD ncl; + + + res = validate(&fp->obj, &fs); /* Check validity of the file object */ + if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); + if (!(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */ + + if (fp->fptr < fp->obj.objsize) { /* Process when fptr is not on the eof */ + if (fp->fptr == 0) { /* When set file size to zero, remove entire cluster chain */ + res = remove_chain(&fp->obj, fp->obj.sclust, 0); + fp->obj.sclust = 0; + } else { /* When truncate a part of the file, remove remaining clusters */ + ncl = get_fat(&fp->obj, fp->clust); + res = FR_OK; + if (ncl == 0xFFFFFFFF) res = FR_DISK_ERR; + if (ncl == 1) res = FR_INT_ERR; + if (res == FR_OK && ncl < fs->n_fatent) { + res = remove_chain(&fp->obj, ncl, fp->clust); + } + } + fp->obj.objsize = fp->fptr; /* Set file size to current read/write point */ + fp->flag |= FA_MODIFIED; +#if !FF_FS_TINY + if (res == FR_OK && (fp->flag & FA_DIRTY)) { + if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) { + res = FR_DISK_ERR; + } else { + fp->flag &= (BYTE)~FA_DIRTY; + } + } +#endif + if (res != FR_OK) ABORT(fs, res); + } + + LEAVE_FF(fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Delete a File/Directory */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_unlink ( + const TCHAR* path /* Pointer to the file or directory path */ +) +{ + FRESULT res; + DIR dj, sdj; + DWORD dclst = 0; + FATFS *fs; +#if FF_FS_EXFAT + FFOBJID obj; +#endif + DEF_NAMBUF + + + /* Get logical drive */ + res = find_volume(&path, &fs, FA_WRITE); + if (res == FR_OK) { + dj.obj.fs = fs; + INIT_NAMBUF(fs); + res = follow_path(&dj, path); /* Follow the file path */ + if (FF_FS_RPATH && res == FR_OK && (dj.fn[NSFLAG] & NS_DOT)) { + res = FR_INVALID_NAME; /* Cannot remove dot entry */ + } +#if FF_FS_LOCK != 0 + if (res == FR_OK) res = chk_lock(&dj, 2); /* Check if it is an open object */ +#endif + if (res == FR_OK) { /* The object is accessible */ + if (dj.fn[NSFLAG] & NS_NONAME) { + res = FR_INVALID_NAME; /* Cannot remove the origin directory */ + } else { + if (dj.obj.attr & AM_RDO) { + res = FR_DENIED; /* Cannot remove R/O object */ + } + } + if (res == FR_OK) { +#if FF_FS_EXFAT + obj.fs = fs; + if (fs->fs_type == FS_EXFAT) { + obj.sclust = dclst = ld_dword(fs->dirbuf + XDIR_FstClus); + obj.objsize = ld_qword(fs->dirbuf + XDIR_FileSize); + obj.stat = fs->dirbuf[XDIR_GenFlags] & 2; + } else +#endif + { + dclst = ld_clust(fs, dj.dir); + } + if (dj.obj.attr & AM_DIR) { /* Is it a sub-directory? */ +#if FF_FS_RPATH != 0 + if (dclst == fs->cdir) { /* Is it the current directory? */ + res = FR_DENIED; + } else +#endif + { + sdj.obj.fs = fs; /* Open the sub-directory */ + sdj.obj.sclust = dclst; +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { + sdj.obj.objsize = obj.objsize; + sdj.obj.stat = obj.stat; + } +#endif + res = dir_sdi(&sdj, 0); + if (res == FR_OK) { + res = dir_read(&sdj, 0); /* Read an item */ + if (res == FR_OK) res = FR_DENIED; /* Not empty? */ + if (res == FR_NO_FILE) res = FR_OK; /* Empty? */ + } + } + } + } + if (res == FR_OK) { + res = dir_remove(&dj); /* Remove the directory entry */ + if (res == FR_OK && dclst) { /* Remove the cluster chain if exist */ +#if FF_FS_EXFAT + res = remove_chain(&obj, dclst, 0); +#else + res = remove_chain(&dj.obj, dclst, 0); +#endif + } + if (res == FR_OK) res = sync_fs(fs); + } + } + FREE_NAMBUF(); + } + + LEAVE_FF(fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Create a Directory */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_mkdir ( + const TCHAR* path /* Pointer to the directory path */ +) +{ + FRESULT res; + DIR dj; + FATFS *fs; + BYTE *dir; + DWORD dcl, pcl, tm; + DEF_NAMBUF + + + /* Get logical drive */ + res = find_volume(&path, &fs, FA_WRITE); + if (res == FR_OK) { + dj.obj.fs = fs; + INIT_NAMBUF(fs); + res = follow_path(&dj, path); /* Follow the file path */ + if (res == FR_OK) res = FR_EXIST; /* Any object with same name is already existing */ + if (FF_FS_RPATH && res == FR_NO_FILE && (dj.fn[NSFLAG] & NS_DOT)) { + res = FR_INVALID_NAME; + } + if (res == FR_NO_FILE) { /* Can create a new directory */ + dcl = create_chain(&dj.obj, 0); /* Allocate a cluster for the new directory table */ + dj.obj.objsize = (DWORD)fs->csize * SS(fs); + res = FR_OK; + if (dcl == 0) res = FR_DENIED; /* No space to allocate a new cluster */ + if (dcl == 1) res = FR_INT_ERR; + if (dcl == 0xFFFFFFFF) res = FR_DISK_ERR; + if (res == FR_OK) res = sync_window(fs); /* Flush FAT */ + tm = GET_FATTIME(); + if (res == FR_OK) { /* Initialize the new directory table */ + res = dir_clear(fs, dcl); /* Clean up the new table */ + if (res == FR_OK && (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT)) { /* Create dot entries (FAT only) */ + dir = fs->win; + mem_set(dir + DIR_Name, ' ', 11); /* Create "." entry */ + dir[DIR_Name] = '.'; + dir[DIR_Attr] = AM_DIR; + st_dword(dir + DIR_ModTime, tm); + st_clust(fs, dir, dcl); + mem_cpy(dir + SZDIRE, dir, SZDIRE); /* Create ".." entry */ + dir[SZDIRE + 1] = '.'; pcl = dj.obj.sclust; + st_clust(fs, dir + SZDIRE, pcl); + fs->wflag = 1; + } + } + if (res == FR_OK) { + res = dir_register(&dj); /* Register the object to the directoy */ + } + if (res == FR_OK) { +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { /* Initialize directory entry block */ + st_dword(fs->dirbuf + XDIR_ModTime, tm); /* Created time */ + st_dword(fs->dirbuf + XDIR_FstClus, dcl); /* Table start cluster */ + st_dword(fs->dirbuf + XDIR_FileSize, (DWORD)dj.obj.objsize); /* File size needs to be valid */ + st_dword(fs->dirbuf + XDIR_ValidFileSize, (DWORD)dj.obj.objsize); + fs->dirbuf[XDIR_GenFlags] = 3; /* Initialize the object flag */ + fs->dirbuf[XDIR_Attr] = AM_DIR; /* Attribute */ + res = store_xdir(&dj); + } else +#endif + { + dir = dj.dir; + st_dword(dir + DIR_ModTime, tm); /* Created time */ + st_clust(fs, dir, dcl); /* Table start cluster */ + dir[DIR_Attr] = AM_DIR; /* Attribute */ + fs->wflag = 1; + } + if (res == FR_OK) { + res = sync_fs(fs); + } + } else { + remove_chain(&dj.obj, dcl, 0); /* Could not register, remove cluster chain */ + } + } + FREE_NAMBUF(); + } + + LEAVE_FF(fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Rename a File/Directory */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_rename ( + const TCHAR* path_old, /* Pointer to the object name to be renamed */ + const TCHAR* path_new /* Pointer to the new name */ +) +{ + FRESULT res; + DIR djo, djn; + FATFS *fs; + BYTE buf[FF_FS_EXFAT ? SZDIRE * 2 : SZDIRE], *dir; + DWORD dw; + DEF_NAMBUF + + + get_ldnumber(&path_new); /* Snip the drive number of new name off */ + res = find_volume(&path_old, &fs, FA_WRITE); /* Get logical drive of the old object */ + if (res == FR_OK) { + djo.obj.fs = fs; + INIT_NAMBUF(fs); + res = follow_path(&djo, path_old); /* Check old object */ + if (res == FR_OK && (djo.fn[NSFLAG] & (NS_DOT | NS_NONAME))) res = FR_INVALID_NAME; /* Check validity of name */ +#if FF_FS_LOCK != 0 + if (res == FR_OK) { + res = chk_lock(&djo, 2); + } +#endif + if (res == FR_OK) { /* Object to be renamed is found */ +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { /* At exFAT volume */ + BYTE nf, nn; + WORD nh; + + mem_cpy(buf, fs->dirbuf, SZDIRE * 2); /* Save 85+C0 entry of old object */ + mem_cpy(&djn, &djo, sizeof djo); + res = follow_path(&djn, path_new); /* Make sure if new object name is not in use */ + if (res == FR_OK) { /* Is new name already in use by any other object? */ + res = (djn.obj.sclust == djo.obj.sclust && djn.dptr == djo.dptr) ? FR_NO_FILE : FR_EXIST; + } + if (res == FR_NO_FILE) { /* It is a valid path and no name collision */ + res = dir_register(&djn); /* Register the new entry */ + if (res == FR_OK) { + nf = fs->dirbuf[XDIR_NumSec]; nn = fs->dirbuf[XDIR_NumName]; + nh = ld_word(fs->dirbuf + XDIR_NameHash); + mem_cpy(fs->dirbuf, buf, SZDIRE * 2); /* Restore 85+C0 entry */ + fs->dirbuf[XDIR_NumSec] = nf; fs->dirbuf[XDIR_NumName] = nn; + st_word(fs->dirbuf + XDIR_NameHash, nh); + if (!(fs->dirbuf[XDIR_Attr] & AM_DIR)) fs->dirbuf[XDIR_Attr] |= AM_ARC; /* Set archive attribute if it is a file */ +/* Start of critical section where an interruption can cause a cross-link */ + res = store_xdir(&djn); + } + } + } else +#endif + { /* At FAT/FAT32 volume */ + mem_cpy(buf, djo.dir, SZDIRE); /* Save directory entry of the object */ + mem_cpy(&djn, &djo, sizeof (DIR)); /* Duplicate the directory object */ + res = follow_path(&djn, path_new); /* Make sure if new object name is not in use */ + if (res == FR_OK) { /* Is new name already in use by any other object? */ + res = (djn.obj.sclust == djo.obj.sclust && djn.dptr == djo.dptr) ? FR_NO_FILE : FR_EXIST; + } + if (res == FR_NO_FILE) { /* It is a valid path and no name collision */ + res = dir_register(&djn); /* Register the new entry */ + if (res == FR_OK) { + dir = djn.dir; /* Copy directory entry of the object except name */ + mem_cpy(dir + 13, buf + 13, SZDIRE - 13); + dir[DIR_Attr] = buf[DIR_Attr]; + if (!(dir[DIR_Attr] & AM_DIR)) dir[DIR_Attr] |= AM_ARC; /* Set archive attribute if it is a file */ + fs->wflag = 1; + if ((dir[DIR_Attr] & AM_DIR) && djo.obj.sclust != djn.obj.sclust) { /* Update .. entry in the sub-directory if needed */ + dw = clst2sect(fs, ld_clust(fs, dir)); + if (dw == 0) { + res = FR_INT_ERR; + } else { +/* Start of critical section where an interruption can cause a cross-link */ + res = move_window(fs, dw); + dir = fs->win + SZDIRE * 1; /* Ptr to .. entry */ + if (res == FR_OK && dir[1] == '.') { + st_clust(fs, dir, djn.obj.sclust); + fs->wflag = 1; + } + } + } + } + } + } + if (res == FR_OK) { + res = dir_remove(&djo); /* Remove old entry */ + if (res == FR_OK) { + res = sync_fs(fs); + } + } +/* End of the critical section */ + } + FREE_NAMBUF(); + } + + LEAVE_FF(fs, res); +} + +#endif /* !FF_FS_READONLY */ +#endif /* FF_FS_MINIMIZE == 0 */ +#endif /* FF_FS_MINIMIZE <= 1 */ +#endif /* FF_FS_MINIMIZE <= 2 */ + + + +#if FF_USE_CHMOD && !FF_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Change Attribute */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_chmod ( + const TCHAR* path, /* Pointer to the file path */ + BYTE attr, /* Attribute bits */ + BYTE mask /* Attribute mask to change */ +) +{ + FRESULT res; + DIR dj; + FATFS *fs; + DEF_NAMBUF + + + res = find_volume(&path, &fs, FA_WRITE); /* Get logical drive */ + if (res == FR_OK) { + dj.obj.fs = fs; + INIT_NAMBUF(fs); + res = follow_path(&dj, path); /* Follow the file path */ + if (res == FR_OK && (dj.fn[NSFLAG] & (NS_DOT | NS_NONAME))) res = FR_INVALID_NAME; /* Check object validity */ + if (res == FR_OK) { + mask &= AM_RDO|AM_HID|AM_SYS|AM_ARC; /* Valid attribute mask */ +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { + fs->dirbuf[XDIR_Attr] = (attr & mask) | (fs->dirbuf[XDIR_Attr] & (BYTE)~mask); /* Apply attribute change */ + res = store_xdir(&dj); + } else +#endif + { + dj.dir[DIR_Attr] = (attr & mask) | (dj.dir[DIR_Attr] & (BYTE)~mask); /* Apply attribute change */ + fs->wflag = 1; + } + if (res == FR_OK) { + res = sync_fs(fs); + } + } + FREE_NAMBUF(); + } + + LEAVE_FF(fs, res); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Change Timestamp */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_utime ( + const TCHAR* path, /* Pointer to the file/directory name */ + const FILINFO* fno /* Pointer to the timestamp to be set */ +) +{ + FRESULT res; + DIR dj; + FATFS *fs; + DEF_NAMBUF + + + res = find_volume(&path, &fs, FA_WRITE); /* Get logical drive */ + if (res == FR_OK) { + dj.obj.fs = fs; + INIT_NAMBUF(fs); + res = follow_path(&dj, path); /* Follow the file path */ + if (res == FR_OK && (dj.fn[NSFLAG] & (NS_DOT | NS_NONAME))) res = FR_INVALID_NAME; /* Check object validity */ + if (res == FR_OK) { +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { + st_dword(fs->dirbuf + XDIR_ModTime, (DWORD)fno->fdate << 16 | fno->ftime); + res = store_xdir(&dj); + } else +#endif + { + st_dword(dj.dir + DIR_ModTime, (DWORD)fno->fdate << 16 | fno->ftime); + fs->wflag = 1; + } + if (res == FR_OK) { + res = sync_fs(fs); + } + } + FREE_NAMBUF(); + } + + LEAVE_FF(fs, res); +} + +#endif /* FF_USE_CHMOD && !FF_FS_READONLY */ + + + +#if FF_USE_LABEL +/*-----------------------------------------------------------------------*/ +/* Get Volume Label */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_getlabel ( + const TCHAR* path, /* Path name of the logical drive number */ + TCHAR* label, /* Pointer to a buffer to store the volume label */ + DWORD* vsn /* Pointer to a variable to store the volume serial number */ +) +{ + FRESULT res; + DIR dj; + FATFS *fs; + UINT si, di; +#if (FF_LFN_UNICODE && FF_USE_LFN) || FF_FS_EXFAT + WCHAR w; +#endif + + /* Get logical drive */ + res = find_volume(&path, &fs, 0); + + /* Get volume label */ + if (res == FR_OK && label) { + dj.obj.fs = fs; dj.obj.sclust = 0; /* Open root directory */ + res = dir_sdi(&dj, 0); + if (res == FR_OK) { + res = dir_read(&dj, 1); /* Find a volume label entry */ + if (res == FR_OK) { +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { + for (si = di = 0; si < dj.dir[XDIR_NumLabel]; si++) { /* Extract volume label from 83 entry */ + w = ld_word(dj.dir + XDIR_Label + si * 2); +#if !FF_LFN_UNICODE /* ANSI/OEM API */ + w = ff_uni2oem(w, CODEPAGE); /* Unicode -> OEM */ + if (w == 0) w = '?'; /* Replace wrong char with '?' */ + if (w >= 0x100) label[di++] = (char)(w >> 8); +#endif + label[di++] = (TCHAR)w; + } + label[di] = 0; + } else +#endif + { + si = di = 0; /* Extract volume label from AM_VOL entry with code comversion */ + do { +#if FF_LFN_UNICODE && FF_USE_LFN /* Unicode API */ + w = (si < 11) ? dj.dir[si++] : ' '; + if (dbc_1st((BYTE)w) && si < 11 && dbc_2nd(dj.dir[si])) { + w = w << 8 | dj.dir[si++]; + } + label[di++] = ff_oem2uni(w, CODEPAGE); /* OEM -> Unicode */ +#else /* ANSI/OEM API */ + label[di++] = dj.dir[si++]; +#endif + } while (di < 11); + do { /* Truncate trailing spaces */ + label[di] = 0; + if (di == 0) break; + } while (label[--di] == ' '); + } + } + } + if (res == FR_NO_FILE) { /* No label entry and return nul string */ + label[0] = 0; + res = FR_OK; + } + } + + /* Get volume serial number */ + if (res == FR_OK && vsn) { + res = move_window(fs, fs->volbase); + if (res == FR_OK) { + switch (fs->fs_type) { + case FS_EXFAT: + di = BPB_VolIDEx; break; + + case FS_FAT32: + di = BS_VolID32; break; + + default: + di = BS_VolID; + } + *vsn = ld_dword(fs->win + di); + } + } + + LEAVE_FF(fs, res); +} + + + +#if !FF_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Set Volume Label */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_setlabel ( + const TCHAR* label /* Pointer to the volume label to set */ +) +{ + FRESULT res; + DIR dj; + FATFS *fs; + BYTE dirvn[22]; + UINT i, j, slen; + WCHAR w; + static const char badchr[] = "\"*+,.:;<=>\?[]|\x7F"; + + + /* Get logical drive */ + res = find_volume(&label, &fs, FA_WRITE); + if (res != FR_OK) LEAVE_FF(fs, res); + dj.obj.fs = fs; + + /* Get length of given volume label */ + for (slen = 0; (UINT)label[slen] >= ' '; slen++) ; /* Get name length */ + +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */ + for (i = j = 0; i < slen; ) { /* Create volume label in directory form */ + w = label[i++]; +#if !FF_LFN_UNICODE /* ANSI/OEM API */ + if (dbc_1st((BYTE)w)) { + w = (i < slen && dbc_2nd((BYTE)label[i])) ? w << 8 | (BYTE)label[i++] : 0; + } + w = ff_oem2uni(w, CODEPAGE); +#endif + if (w == 0 || chk_chr(badchr, w) || j == 22) { /* Check validity check validity of the volume label */ + LEAVE_FF(fs, FR_INVALID_NAME); + } + st_word(dirvn + j, w); j += 2; + } + slen = j; + } else +#endif + { /* On the FAT/FAT32 volume */ + for ( ; slen && label[slen - 1] == ' '; slen--) ; /* Remove trailing spaces */ + if (slen != 0) { /* Is there a volume label to be set? */ + dirvn[0] = 0; i = j = 0; /* Create volume label in directory form */ + do { +#if FF_LFN_UNICODE && FF_USE_LFN /* Unicode API */ + w = ff_uni2oem(ff_wtoupper(label[i++]), CODEPAGE); +#else /* ANSI/OEM API */ + w = (BYTE)label[i++]; + if (dbc_1st((BYTE)w)) { + w = (j < 10 && i < slen && dbc_2nd((BYTE)label[i])) ? w << 8 | (BYTE)label[i++] : 0; + } +#if FF_USE_LFN + w = ff_uni2oem(ff_wtoupper(ff_oem2uni(w, CODEPAGE)), CODEPAGE); +#else + if (IsLower(w)) w -= 0x20; /* To upper ASCII characters */ +#if FF_CODE_PAGE == 0 + if (ExCvt && w >= 0x80) w = ExCvt[w - 0x80]; /* To upper extended characters (SBCS cfg) */ +#elif FF_CODE_PAGE < 900 + if (w >= 0x80) w = ExCvt[w - 0x80]; /* To upper extended characters (SBCS cfg) */ +#endif +#endif +#endif + if (w == 0 || chk_chr(badchr, w) || j >= (UINT)((w >= 0x100) ? 10 : 11)) { /* Reject invalid characters for volume label */ + LEAVE_FF(fs, FR_INVALID_NAME); + } + if (w >= 0x100) dirvn[j++] = (BYTE)(w >> 8); + dirvn[j++] = (BYTE)w; + } while (i < slen); + while (j < 11) dirvn[j++] = ' '; /* Fill remaining name field */ + if (dirvn[0] == DDEM) LEAVE_FF(fs, FR_INVALID_NAME); /* Reject illegal name (heading DDEM) */ + } + } + + /* Set volume label */ + dj.obj.sclust = 0; /* Open root directory */ + res = dir_sdi(&dj, 0); + if (res == FR_OK) { + res = dir_read(&dj, 1); /* Get volume label entry */ + if (res == FR_OK) { + if (FF_FS_EXFAT && fs->fs_type == FS_EXFAT) { + dj.dir[XDIR_NumLabel] = (BYTE)(slen / 2); /* Change the volume label */ + mem_cpy(dj.dir + XDIR_Label, dirvn, slen); + } else { + if (slen != 0) { + mem_cpy(dj.dir, dirvn, 11); /* Change the volume label */ + } else { + dj.dir[DIR_Name] = DDEM; /* Remove the volume label */ + } + } + fs->wflag = 1; + res = sync_fs(fs); + } else { /* No volume label entry or an error */ + if (res == FR_NO_FILE) { + res = FR_OK; + if (slen != 0) { /* Create a volume label entry */ + res = dir_alloc(&dj, 1); /* Allocate an entry */ + if (res == FR_OK) { + mem_set(dj.dir, 0, SZDIRE); /* Clear the entry */ + if (FF_FS_EXFAT && fs->fs_type == FS_EXFAT) { + dj.dir[XDIR_Type] = 0x83; /* Create 83 entry */ + dj.dir[XDIR_NumLabel] = (BYTE)(slen / 2); + mem_cpy(dj.dir + XDIR_Label, dirvn, slen); + } else { + dj.dir[DIR_Attr] = AM_VOL; /* Create volume label entry */ + mem_cpy(dj.dir, dirvn, 11); + } + fs->wflag = 1; + res = sync_fs(fs); + } + } + } + } + } + + LEAVE_FF(fs, res); +} + +#endif /* !FF_FS_READONLY */ +#endif /* FF_USE_LABEL */ + + + +#if FF_USE_EXPAND && !FF_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Allocate a Contiguous Blocks to the File */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_expand ( + FIL* fp, /* Pointer to the file object */ + FSIZE_t fsz, /* File size to be expanded to */ + BYTE opt /* Operation mode 0:Find and prepare or 1:Find and allocate */ +) +{ + FRESULT res; + FATFS *fs; + DWORD n, clst, stcl, scl, ncl, tcl, lclst; + + + res = validate(&fp->obj, &fs); /* Check validity of the file object */ + if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); + if (fsz == 0 || fp->obj.objsize != 0 || !(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED); +#if FF_FS_EXFAT + if (fs->fs_type != FS_EXFAT && fsz >= 0x100000000) LEAVE_FF(fs, FR_DENIED); /* Check if in size limit */ +#endif + n = (DWORD)fs->csize * SS(fs); /* Cluster size */ + tcl = (DWORD)(fsz / n) + ((fsz & (n - 1)) ? 1 : 0); /* Number of clusters required */ + stcl = fs->last_clst; lclst = 0; + if (stcl < 2 || stcl >= fs->n_fatent) stcl = 2; + +#if FF_FS_EXFAT + if (fs->fs_type == FS_EXFAT) { + scl = find_bitmap(fs, stcl, tcl); /* Find a contiguous cluster block */ + if (scl == 0) res = FR_DENIED; /* No contiguous cluster block was found */ + if (scl == 0xFFFFFFFF) res = FR_DISK_ERR; + if (res == FR_OK) { /* A contiguous free area is found */ + if (opt) { /* Allocate it now */ + res = change_bitmap(fs, scl, tcl, 1); /* Mark the cluster block 'in use' */ + lclst = scl + tcl - 1; + } else { /* Set it as suggested point for next allocation */ + lclst = scl - 1; + } + } + } else +#endif + { + scl = clst = stcl; ncl = 0; + for (;;) { /* Find a contiguous cluster block */ + n = get_fat(&fp->obj, clst); + if (++clst >= fs->n_fatent) clst = 2; + if (n == 1) { res = FR_INT_ERR; break; } + if (n == 0xFFFFFFFF) { res = FR_DISK_ERR; break; } + if (n == 0) { /* Is it a free cluster? */ + if (++ncl == tcl) break; /* Break if a contiguous cluster block is found */ + } else { + scl = clst; ncl = 0; /* Not a free cluster */ + } + if (clst == stcl) { res = FR_DENIED; break; } /* No contiguous cluster? */ + } + if (res == FR_OK) { /* A contiguous free area is found */ + if (opt) { /* Allocate it now */ + for (clst = scl, n = tcl; n; clst++, n--) { /* Create a cluster chain on the FAT */ + res = put_fat(fs, clst, (n == 1) ? 0xFFFFFFFF : clst + 1); + if (res != FR_OK) break; + lclst = clst; + } + } else { /* Set it as suggested point for next allocation */ + lclst = scl - 1; + } + } + } + + if (res == FR_OK) { + fs->last_clst = lclst; /* Set suggested start cluster to start next */ + if (opt) { /* Is it allocated now? */ + fp->obj.sclust = scl; /* Update object allocation information */ + fp->obj.objsize = fsz; + if (FF_FS_EXFAT) fp->obj.stat = 2; /* Set status 'contiguous chain' */ + fp->flag |= FA_MODIFIED; + if (fs->free_clst <= fs->n_fatent - 2) { /* Update FSINFO */ + fs->free_clst -= tcl; + fs->fsi_flag |= 1; + } + } + } + + LEAVE_FF(fs, res); +} + +#endif /* FF_USE_EXPAND && !FF_FS_READONLY */ + + + +#if FF_USE_FORWARD +/*-----------------------------------------------------------------------*/ +/* Forward Data to the Stream Directly */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_forward ( + FIL* fp, /* Pointer to the file object */ + UINT (*func)(const BYTE*,UINT), /* Pointer to the streaming function */ + UINT btf, /* Number of bytes to forward */ + UINT* bf /* Pointer to number of bytes forwarded */ +) +{ + FRESULT res; + FATFS *fs; + DWORD clst, sect; + FSIZE_t remain; + UINT rcnt, csect; + BYTE *dbuf; + + + *bf = 0; /* Clear transfer byte counter */ + res = validate(&fp->obj, &fs); /* Check validity of the file object */ + if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); + if (!(fp->flag & FA_READ)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */ + + remain = fp->obj.objsize - fp->fptr; + if (btf > remain) btf = (UINT)remain; /* Truncate btf by remaining bytes */ + + for ( ; btf && (*func)(0, 0); /* Repeat until all data transferred or stream goes busy */ + fp->fptr += rcnt, *bf += rcnt, btf -= rcnt) { + csect = (UINT)(fp->fptr / SS(fs) & (fs->csize - 1)); /* Sector offset in the cluster */ + if (fp->fptr % SS(fs) == 0) { /* On the sector boundary? */ + if (csect == 0) { /* On the cluster boundary? */ + clst = (fp->fptr == 0) ? /* On the top of the file? */ + fp->obj.sclust : get_fat(&fp->obj, fp->clust); + if (clst <= 1) ABORT(fs, FR_INT_ERR); + if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR); + fp->clust = clst; /* Update current cluster */ + } + } + sect = clst2sect(fs, fp->clust); /* Get current data sector */ + if (sect == 0) ABORT(fs, FR_INT_ERR); + sect += csect; +#if FF_FS_TINY + if (move_window(fs, sect) != FR_OK) ABORT(fs, FR_DISK_ERR); /* Move sector window to the file data */ + dbuf = fs->win; +#else + if (fp->sect != sect) { /* Fill sector cache with file data */ +#if !FF_FS_READONLY + if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */ + if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); + fp->flag &= (BYTE)~FA_DIRTY; + } +#endif + if (disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); + } + dbuf = fp->buf; +#endif + fp->sect = sect; + rcnt = SS(fs) - (UINT)fp->fptr % SS(fs); /* Number of bytes left in the sector */ + if (rcnt > btf) rcnt = btf; /* Clip it by btr if needed */ + rcnt = (*func)(dbuf + ((UINT)fp->fptr % SS(fs)), rcnt); /* Forward the file data */ + if (rcnt == 0) ABORT(fs, FR_INT_ERR); + } + + LEAVE_FF(fs, FR_OK); +} +#endif /* FF_USE_FORWARD */ + + + +#if FF_USE_MKFS && !FF_FS_READONLY +/*-----------------------------------------------------------------------*/ +/* Create an FAT/exFAT volume */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_mkfs ( + const TCHAR* path, /* Logical drive number */ + BYTE opt, /* Format option */ + DWORD au, /* Size of allocation unit (cluster) [byte] */ + void* work, /* Pointer to working buffer */ + UINT len /* Size of working buffer */ +) +{ + const UINT n_fats = 1; /* Number of FATs for FAT/FAT32 volume (1 or 2) */ + const UINT n_rootdir = 512; /* Number of root directory entries for FAT volume */ + static const WORD cst[] = {1, 4, 16, 64, 256, 512, 0}; /* Cluster size boundary for FAT volume (4Ks unit) */ + static const WORD cst32[] = {1, 2, 4, 8, 16, 32, 0}; /* Cluster size boundary for FAT32 volume (128Ks unit) */ + BYTE fmt, sys, *buf, *pte, pdrv, part; + WORD ss; + DWORD szb_buf, sz_buf, sz_blk, n_clst, pau, sect, nsect, n; + DWORD b_vol, b_fat, b_data; /* Base LBA for volume, fat, data */ + DWORD sz_vol, sz_rsv, sz_fat, sz_dir; /* Size for volume, fat, dir, data */ + UINT i; + int vol; + DSTATUS stat; +#if FF_USE_TRIM || FF_FS_EXFAT + DWORD tbl[3]; +#endif + + + /* Check mounted drive and clear work area */ + vol = get_ldnumber(&path); /* Get target logical drive */ + if (vol < 0) return FR_INVALID_DRIVE; + if (FatFs[vol]) FatFs[vol]->fs_type = 0; /* Clear the volume */ + pdrv = LD2PD(vol); /* Physical drive */ + part = LD2PT(vol); /* Partition (0:create as new, 1-4:get from partition table) */ + + /* Check physical drive status */ + stat = disk_initialize(pdrv); + if (stat & STA_NOINIT) return FR_NOT_READY; + if (stat & STA_PROTECT) return FR_WRITE_PROTECTED; + if (disk_ioctl(pdrv, GET_BLOCK_SIZE, &sz_blk) != RES_OK || !sz_blk || sz_blk > 32768 || (sz_blk & (sz_blk - 1))) sz_blk = 1; /* Erase block to align data area */ +#if FF_MAX_SS != FF_MIN_SS /* Get sector size of the medium if variable sector size cfg. */ + if (disk_ioctl(pdrv, GET_SECTOR_SIZE, &ss) != RES_OK) return FR_DISK_ERR; + if (ss > FF_MAX_SS || ss < FF_MIN_SS || (ss & (ss - 1))) return FR_DISK_ERR; +#else + ss = FF_MAX_SS; +#endif + if ((au != 0 && au < ss) || au > 0x1000000 || (au & (au - 1))) return FR_INVALID_PARAMETER; /* Check if au is valid */ + au /= ss; /* Cluster size in unit of sector */ + + /* Get working buffer */ + buf = (BYTE*)work; /* Working buffer */ + sz_buf = len / ss; /* Size of working buffer (sector) */ + szb_buf = sz_buf * ss; /* Size of working buffer (byte) */ + if (szb_buf == 0) return FR_MKFS_ABORTED; + + /* Determine where the volume to be located (b_vol, sz_vol) */ + if (FF_MULTI_PARTITION && part != 0) { + /* Get partition information from partition table in the MBR */ + if (disk_read(pdrv, buf, 0, 1) != RES_OK) return FR_DISK_ERR; /* Load MBR */ + if (ld_word(buf + BS_55AA) != 0xAA55) return FR_MKFS_ABORTED; /* Check if MBR is valid */ + pte = buf + (MBR_Table + (part - 1) * SZ_PTE); + if (!pte[PTE_System]) return FR_MKFS_ABORTED; /* No partition? */ + b_vol = ld_dword(pte + PTE_StLba); /* Get volume start sector */ + sz_vol = ld_dword(pte + PTE_SizLba); /* Get volume size */ + } else { + /* Create a single-partition in this function */ + if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_vol) != RES_OK) return FR_DISK_ERR; + b_vol = (opt & FM_SFD) ? 0 : 63; /* Volume start sector */ + if (sz_vol < b_vol) return FR_MKFS_ABORTED; + sz_vol -= b_vol; /* Volume size */ + } + if (sz_vol < 128) return FR_MKFS_ABORTED; /* Check if volume size is >=128s */ + + /* Pre-determine the FAT type */ + do { + if (FF_FS_EXFAT && (opt & FM_EXFAT)) { /* exFAT possible? */ + if ((opt & FM_ANY) == FM_EXFAT || sz_vol >= 0x4000000 || au > 128) { /* exFAT only, vol >= 64Ms or au > 128s ? */ + fmt = FS_EXFAT; break; + } + } + if (au > 128) return FR_INVALID_PARAMETER; /* Too large au for FAT/FAT32 */ + if (opt & FM_FAT32) { /* FAT32 possible? */ + if ((opt & FM_ANY) == FM_FAT32 || !(opt & FM_FAT)) { /* FAT32 only or no-FAT? */ + fmt = FS_FAT32; break; + } + } + if (!(opt & FM_FAT)) return FR_INVALID_PARAMETER; /* no-FAT? */ + fmt = FS_FAT16; + } while (0); + +#if FF_FS_EXFAT + if (fmt == FS_EXFAT) { /* Create an exFAT volume */ + DWORD szb_bit, szb_case, sum, nb, cl; + WCHAR ch, si; + UINT j, st; + BYTE b; + + if (sz_vol < 0x1000) return FR_MKFS_ABORTED; /* Too small volume? */ +#if FF_USE_TRIM + tbl[0] = b_vol; tbl[1] = b_vol + sz_vol - 1; /* Inform the device the volume area may be erased */ + disk_ioctl(pdrv, CTRL_TRIM, tbl); +#endif + /* Determine FAT location, data location and number of clusters */ + if (au == 0) { /* au auto-selection */ + au = 8; + if (sz_vol >= 0x80000) au = 64; /* >= 512Ks */ + if (sz_vol >= 0x4000000) au = 256; /* >= 64Ms */ + } + b_fat = b_vol + 32; /* FAT start at offset 32 */ + sz_fat = ((sz_vol / au + 2) * 4 + ss - 1) / ss; /* Number of FAT sectors */ + b_data = (b_fat + sz_fat + sz_blk - 1) & ~(sz_blk - 1); /* Align data area to the erase block boundary */ + if (b_data >= sz_vol / 2) return FR_MKFS_ABORTED; /* Too small volume? */ + n_clst = (sz_vol - (b_data - b_vol)) / au; /* Number of clusters */ + if (n_clst <16) return FR_MKFS_ABORTED; /* Too few clusters? */ + if (n_clst > MAX_EXFAT) return FR_MKFS_ABORTED; /* Too many clusters? */ + + szb_bit = (n_clst + 7) / 8; /* Size of allocation bitmap */ + tbl[0] = (szb_bit + au * ss - 1) / (au * ss); /* Number of allocation bitmap clusters */ + + /* Create a compressed up-case table */ + sect = b_data + au * tbl[0]; /* Table start sector */ + sum = 0; /* Table checksum to be stored in the 82 entry */ + st = si = i = j = szb_case = 0; + do { + switch (st) { + case 0: + ch = ff_wtoupper(si); /* Get an up-case char */ + if (ch != si) { + si++; break; /* Store the up-case char if exist */ + } + for (j = 1; (WCHAR)(si + j) && (WCHAR)(si + j) == ff_wtoupper((WCHAR)(si + j)); j++) ; /* Get run length of no-case block */ + if (j >= 128) { + ch = 0xFFFF; st = 2; break; /* Compress the no-case block if run is >= 128 */ + } + st = 1; /* Do not compress short run */ + /* go to next case */ + case 1: + ch = si++; /* Fill the short run */ + if (--j == 0) st = 0; + break; + + default: + ch = (WCHAR)j; si += j; /* Number of chars to skip */ + st = 0; + } + sum = xsum32(buf[i + 0] = (BYTE)ch, sum); /* Put it into the write buffer */ + sum = xsum32(buf[i + 1] = (BYTE)(ch >> 8), sum); + i += 2; szb_case += 2; + if (si == 0|| i == szb_buf) { /* Write buffered data when buffer full or end of process */ + n = (i + ss - 1) / ss; + if (disk_write(pdrv, buf, sect, n) != RES_OK) return FR_DISK_ERR; + sect += n; i = 0; + } + } while (si); + tbl[1] = (szb_case + au * ss - 1) / (au * ss); /* Number of up-case table clusters */ + tbl[2] = 1; /* Number of root dir clusters */ + + /* Initialize the allocation bitmap */ + sect = b_data; nsect = (szb_bit + ss - 1) / ss; /* Start of bitmap and number of sectors */ + nb = tbl[0] + tbl[1] + tbl[2]; /* Number of clusters in-use by system */ + do { + mem_set(buf, 0, szb_buf); + for (i = 0; nb >= 8 && i < szb_buf; buf[i++] = 0xFF, nb -= 8) ; + for (b = 1; nb != 0 && i < szb_buf; buf[i] |= b, b <<= 1, nb--) ; + n = (nsect > sz_buf) ? sz_buf : nsect; /* Write the buffered data */ + if (disk_write(pdrv, buf, sect, n) != RES_OK) return FR_DISK_ERR; + sect += n; nsect -= n; + } while (nsect); + + /* Initialize the FAT */ + sect = b_fat; nsect = sz_fat; /* Start of FAT and number of FAT sectors */ + j = nb = cl = 0; + do { + mem_set(buf, 0, szb_buf); i = 0; /* Clear work area and reset write index */ + if (cl == 0) { /* Set entry 0 and 1 */ + st_dword(buf + i, 0xFFFFFFF8); i += 4; cl++; + st_dword(buf + i, 0xFFFFFFFF); i += 4; cl++; + } + do { /* Create chains of bitmap, up-case and root dir */ + while (nb != 0 && i < szb_buf) { /* Create a chain */ + st_dword(buf + i, (nb > 1) ? cl + 1 : 0xFFFFFFFF); + i += 4; cl++; nb--; + } + if (nb == 0 && j < 3) nb = tbl[j++]; /* Next chain */ + } while (nb != 0 && i < szb_buf); + n = (nsect > sz_buf) ? sz_buf : nsect; /* Write the buffered data */ + if (disk_write(pdrv, buf, sect, n) != RES_OK) return FR_DISK_ERR; + sect += n; nsect -= n; + } while (nsect); + + /* Initialize the root directory */ + mem_set(buf, 0, szb_buf); + buf[SZDIRE * 0 + 0] = 0x83; /* 83 entry (volume label) */ + buf[SZDIRE * 1 + 0] = 0x81; /* 81 entry (allocation bitmap) */ + st_dword(buf + SZDIRE * 1 + 20, 2); + st_dword(buf + SZDIRE * 1 + 24, szb_bit); + buf[SZDIRE * 2 + 0] = 0x82; /* 82 entry (up-case table) */ + st_dword(buf + SZDIRE * 2 + 4, sum); + st_dword(buf + SZDIRE * 2 + 20, 2 + tbl[0]); + st_dword(buf + SZDIRE * 2 + 24, szb_case); + sect = b_data + au * (tbl[0] + tbl[1]); nsect = au; /* Start of the root directory and number of sectors */ + do { /* Fill root directory sectors */ + n = (nsect > sz_buf) ? sz_buf : nsect; + if (disk_write(pdrv, buf, sect, n) != RES_OK) return FR_DISK_ERR; + mem_set(buf, 0, ss); + sect += n; nsect -= n; + } while (nsect); + + /* Create two set of the exFAT VBR blocks */ + sect = b_vol; + for (n = 0; n < 2; n++) { + /* Main record (+0) */ + mem_set(buf, 0, ss); + mem_cpy(buf + BS_JmpBoot, "\xEB\x76\x90" "EXFAT ", 11); /* Boot jump code (x86), OEM name */ + st_dword(buf + BPB_VolOfsEx, b_vol); /* Volume offset in the physical drive [sector] */ + st_dword(buf + BPB_TotSecEx, sz_vol); /* Volume size [sector] */ + st_dword(buf + BPB_FatOfsEx, b_fat - b_vol); /* FAT offset [sector] */ + st_dword(buf + BPB_FatSzEx, sz_fat); /* FAT size [sector] */ + st_dword(buf + BPB_DataOfsEx, b_data - b_vol); /* Data offset [sector] */ + st_dword(buf + BPB_NumClusEx, n_clst); /* Number of clusters */ + st_dword(buf + BPB_RootClusEx, 2 + tbl[0] + tbl[1]); /* Root dir cluster # */ + st_dword(buf + BPB_VolIDEx, GET_FATTIME()); /* VSN */ + st_word(buf + BPB_FSVerEx, 0x100); /* Filesystem version (1.00) */ + for (buf[BPB_BytsPerSecEx] = 0, i = ss; i >>= 1; buf[BPB_BytsPerSecEx]++) ; /* Log2 of sector size [byte] */ + for (buf[BPB_SecPerClusEx] = 0, i = au; i >>= 1; buf[BPB_SecPerClusEx]++) ; /* Log2 of cluster size [sector] */ + buf[BPB_NumFATsEx] = 1; /* Number of FATs */ + buf[BPB_DrvNumEx] = 0x80; /* Drive number (for int13) */ + st_word(buf + BS_BootCodeEx, 0xFEEB); /* Boot code (x86) */ + st_word(buf + BS_55AA, 0xAA55); /* Signature (placed here regardless of sector size) */ + for (i = sum = 0; i < ss; i++) { /* VBR checksum */ + if (i != BPB_VolFlagEx && i != BPB_VolFlagEx + 1 && i != BPB_PercInUseEx) sum = xsum32(buf[i], sum); + } + if (disk_write(pdrv, buf, sect++, 1) != RES_OK) return FR_DISK_ERR; + /* Extended bootstrap record (+1..+8) */ + mem_set(buf, 0, ss); + st_word(buf + ss - 2, 0xAA55); /* Signature (placed at end of sector) */ + for (j = 1; j < 9; j++) { + for (i = 0; i < ss; sum = xsum32(buf[i++], sum)) ; /* VBR checksum */ + if (disk_write(pdrv, buf, sect++, 1) != RES_OK) return FR_DISK_ERR; + } + /* OEM/Reserved record (+9..+10) */ + mem_set(buf, 0, ss); + for ( ; j < 11; j++) { + for (i = 0; i < ss; sum = xsum32(buf[i++], sum)) ; /* VBR checksum */ + if (disk_write(pdrv, buf, sect++, 1) != RES_OK) return FR_DISK_ERR; + } + /* Sum record (+11) */ + for (i = 0; i < ss; i += 4) st_dword(buf + i, sum); /* Fill with checksum value */ + if (disk_write(pdrv, buf, sect++, 1) != RES_OK) return FR_DISK_ERR; + } + + } else +#endif /* FF_FS_EXFAT */ + { /* Create an FAT/FAT32 volume */ + do { + pau = au; + /* Pre-determine number of clusters and FAT sub-type */ + if (fmt == FS_FAT32) { /* FAT32 volume */ + if (pau == 0) { /* au auto-selection */ + n = sz_vol / 0x20000; /* Volume size in unit of 128KS */ + for (i = 0, pau = 1; cst32[i] && cst32[i] <= n; i++, pau <<= 1) ; /* Get from table */ + } + n_clst = sz_vol / pau; /* Number of clusters */ + sz_fat = (n_clst * 4 + 8 + ss - 1) / ss; /* FAT size [sector] */ + sz_rsv = 32; /* Number of reserved sectors */ + sz_dir = 0; /* No static directory */ + if (n_clst <= MAX_FAT16 || n_clst > MAX_FAT32) return FR_MKFS_ABORTED; + } else { /* FAT volume */ + if (pau == 0) { /* au auto-selection */ + n = sz_vol / 0x1000; /* Volume size in unit of 4KS */ + for (i = 0, pau = 1; cst[i] && cst[i] <= n; i++, pau <<= 1) ; /* Get from table */ + } + n_clst = sz_vol / pau; + if (n_clst > MAX_FAT12) { + n = n_clst * 2 + 4; /* FAT size [byte] */ + } else { + fmt = FS_FAT12; + n = (n_clst * 3 + 1) / 2 + 3; /* FAT size [byte] */ + } + sz_fat = (n + ss - 1) / ss; /* FAT size [sector] */ + sz_rsv = 1; /* Number of reserved sectors */ + sz_dir = (DWORD)n_rootdir * SZDIRE / ss; /* Rootdir size [sector] */ + } + b_fat = b_vol + sz_rsv; /* FAT base */ + b_data = b_fat + sz_fat * n_fats + sz_dir; /* Data base */ + + /* Align data base to erase block boundary (for flash memory media) */ + n = ((b_data + sz_blk - 1) & ~(sz_blk - 1)) - b_data; /* Next nearest erase block from current data base */ + if (fmt == FS_FAT32) { /* FAT32: Move FAT base */ + sz_rsv += n; b_fat += n; + } else { /* FAT: Expand FAT size */ + sz_fat += n / n_fats; + } + + /* Determine number of clusters and final check of validity of the FAT sub-type */ + if (sz_vol < b_data + pau * 16 - b_vol) return FR_MKFS_ABORTED; /* Too small volume */ + n_clst = (sz_vol - sz_rsv - sz_fat * n_fats - sz_dir) / pau; + if (fmt == FS_FAT32) { + if (n_clst <= MAX_FAT16) { /* Too few clusters for FAT32 */ + if (au == 0 && (au = pau / 2) != 0) continue; /* Adjust cluster size and retry */ + return FR_MKFS_ABORTED; + } + } + if (fmt == FS_FAT16) { + if (n_clst > MAX_FAT16) { /* Too many clusters for FAT16 */ + if (au == 0 && (pau * 2) <= 64) { + au = pau * 2; continue; /* Adjust cluster size and retry */ + } + if ((opt & FM_FAT32)) { + fmt = FS_FAT32; continue; /* Switch type to FAT32 and retry */ + } + if (au == 0 && (au = pau * 2) <= 128) continue; /* Adjust cluster size and retry */ + return FR_MKFS_ABORTED; + } + if (n_clst <= MAX_FAT12) { /* Too few clusters for FAT16 */ + if (au == 0 && (au = pau * 2) <= 128) continue; /* Adjust cluster size and retry */ + return FR_MKFS_ABORTED; + } + } + if (fmt == FS_FAT12 && n_clst > MAX_FAT12) return FR_MKFS_ABORTED; /* Too many clusters for FAT12 */ + + /* Ok, it is the valid cluster configuration */ + break; + } while (1); + +#if FF_USE_TRIM + tbl[0] = b_vol; tbl[1] = b_vol + sz_vol - 1; /* Inform the device the volume area can be erased */ + disk_ioctl(pdrv, CTRL_TRIM, tbl); +#endif + /* Create FAT VBR */ + mem_set(buf, 0, ss); + mem_cpy(buf + BS_JmpBoot, "\xEB\xFE\x90" "MSDOS5.0", 11);/* Boot jump code (x86), OEM name */ + st_word(buf + BPB_BytsPerSec, ss); /* Sector size [byte] */ + buf[BPB_SecPerClus] = (BYTE)pau; /* Cluster size [sector] */ + st_word(buf + BPB_RsvdSecCnt, (WORD)sz_rsv); /* Size of reserved area */ + buf[BPB_NumFATs] = (BYTE)n_fats; /* Number of FATs */ + st_word(buf + BPB_RootEntCnt, (WORD)((fmt == FS_FAT32) ? 0 : n_rootdir)); /* Number of root directory entries */ + if (sz_vol < 0x10000) { + st_word(buf + BPB_TotSec16, (WORD)sz_vol); /* Volume size in 16-bit LBA */ + } else { + st_dword(buf + BPB_TotSec32, sz_vol); /* Volume size in 32-bit LBA */ + } + buf[BPB_Media] = 0xF8; /* Media descriptor byte */ + st_word(buf + BPB_SecPerTrk, 63); /* Number of sectors per track (for int13) */ + st_word(buf + BPB_NumHeads, 255); /* Number of heads (for int13) */ + st_dword(buf + BPB_HiddSec, b_vol); /* Volume offset in the physical drive [sector] */ + if (fmt == FS_FAT32) { + st_dword(buf + BS_VolID32, GET_FATTIME()); /* VSN */ + st_dword(buf + BPB_FATSz32, sz_fat); /* FAT size [sector] */ + st_dword(buf + BPB_RootClus32, 2); /* Root directory cluster # (2) */ + st_word(buf + BPB_FSInfo32, 1); /* Offset of FSINFO sector (VBR + 1) */ + st_word(buf + BPB_BkBootSec32, 6); /* Offset of backup VBR (VBR + 6) */ + buf[BS_DrvNum32] = 0x80; /* Drive number (for int13) */ + buf[BS_BootSig32] = 0x29; /* Extended boot signature */ + mem_cpy(buf + BS_VolLab32, "NO NAME " "FAT32 ", 19); /* Volume label, FAT signature */ + } else { + st_dword(buf + BS_VolID, GET_FATTIME()); /* VSN */ + st_word(buf + BPB_FATSz16, (WORD)sz_fat); /* FAT size [sector] */ + buf[BS_DrvNum] = 0x80; /* Drive number (for int13) */ + buf[BS_BootSig] = 0x29; /* Extended boot signature */ + mem_cpy(buf + BS_VolLab, "NO NAME " "FAT ", 19); /* Volume label, FAT signature */ + } + st_word(buf + BS_55AA, 0xAA55); /* Signature (offset is fixed here regardless of sector size) */ + if (disk_write(pdrv, buf, b_vol, 1) != RES_OK) return FR_DISK_ERR; /* Write it to the VBR sector */ + + /* Create FSINFO record if needed */ + if (fmt == FS_FAT32) { + disk_write(pdrv, buf, b_vol + 6, 1); /* Write backup VBR (VBR + 6) */ + mem_set(buf, 0, ss); + st_dword(buf + FSI_LeadSig, 0x41615252); + st_dword(buf + FSI_StrucSig, 0x61417272); + st_dword(buf + FSI_Free_Count, n_clst - 1); /* Number of free clusters */ + st_dword(buf + FSI_Nxt_Free, 2); /* Last allocated cluster# */ + st_word(buf + BS_55AA, 0xAA55); + disk_write(pdrv, buf, b_vol + 7, 1); /* Write backup FSINFO (VBR + 7) */ + disk_write(pdrv, buf, b_vol + 1, 1); /* Write original FSINFO (VBR + 1) */ + } + + /* Initialize FAT area */ + mem_set(buf, 0, (UINT)szb_buf); + sect = b_fat; /* FAT start sector */ + for (i = 0; i < n_fats; i++) { /* Initialize FATs each */ + if (fmt == FS_FAT32) { + st_dword(buf + 0, 0xFFFFFFF8); /* Entry 0 */ + st_dword(buf + 4, 0xFFFFFFFF); /* Entry 1 */ + st_dword(buf + 8, 0x0FFFFFFF); /* Entry 2 (root directory) */ + } else { + st_dword(buf + 0, (fmt == FS_FAT12) ? 0xFFFFF8 : 0xFFFFFFF8); /* Entry 0 and 1 */ + } + nsect = sz_fat; /* Number of FAT sectors */ + do { /* Fill FAT sectors */ + n = (nsect > sz_buf) ? sz_buf : nsect; + if (disk_write(pdrv, buf, sect, (UINT)n) != RES_OK) return FR_DISK_ERR; + mem_set(buf, 0, ss); + sect += n; nsect -= n; + } while (nsect); + } + + /* Initialize root directory (fill with zero) */ + nsect = (fmt == FS_FAT32) ? pau : sz_dir; /* Number of root directory sectors */ + do { + n = (nsect > sz_buf) ? sz_buf : nsect; + if (disk_write(pdrv, buf, sect, (UINT)n) != RES_OK) return FR_DISK_ERR; + sect += n; nsect -= n; + } while (nsect); + } + + /* Determine system ID in the partition table */ + if (FF_FS_EXFAT && fmt == FS_EXFAT) { + sys = 0x07; /* HPFS/NTFS/exFAT */ + } else { + if (fmt == FS_FAT32) { + sys = 0x0C; /* FAT32X */ + } else { + if (sz_vol >= 0x10000) { + sys = 0x06; /* FAT12/16 (large) */ + } else { + sys = (fmt == FS_FAT16) ? 0x04 : 0x01; /* FAT16 : FAT12 */ + } + } + } + + /* Update partition information */ + if (FF_MULTI_PARTITION && part != 0) { /* Created in the existing partition */ + /* Update system ID in the partition table */ + if (disk_read(pdrv, buf, 0, 1) != RES_OK) return FR_DISK_ERR; /* Read the MBR */ + buf[MBR_Table + (part - 1) * SZ_PTE + PTE_System] = sys; /* Set system ID */ + if (disk_write(pdrv, buf, 0, 1) != RES_OK) return FR_DISK_ERR; /* Write it back to the MBR */ + } else { /* Created as a new single partition */ + if (!(opt & FM_SFD)) { /* Create partition table if in FDISK format */ + mem_set(buf, 0, ss); + st_word(buf + BS_55AA, 0xAA55); /* MBR signature */ + pte = buf + MBR_Table; /* Create partition table for single partition in the drive */ + pte[PTE_Boot] = 0; /* Boot indicator */ + pte[PTE_StHead] = 1; /* Start head */ + pte[PTE_StSec] = 1; /* Start sector */ + pte[PTE_StCyl] = 0; /* Start cylinder */ + pte[PTE_System] = sys; /* System type */ + n = (b_vol + sz_vol) / (63 * 255); /* (End CHS may be invalid) */ + pte[PTE_EdHead] = 254; /* End head */ + pte[PTE_EdSec] = (BYTE)(n >> 2 | 63); /* End sector */ + pte[PTE_EdCyl] = (BYTE)n; /* End cylinder */ + st_dword(pte + PTE_StLba, b_vol); /* Start offset in LBA */ + st_dword(pte + PTE_SizLba, sz_vol); /* Size in sectors */ + if (disk_write(pdrv, buf, 0, 1) != RES_OK) return FR_DISK_ERR; /* Write it to the MBR */ + } + } + + if (disk_ioctl(pdrv, CTRL_SYNC, 0) != RES_OK) return FR_DISK_ERR; + + return FR_OK; +} + + + +#if FF_MULTI_PARTITION +/*-----------------------------------------------------------------------*/ +/* Create Partition Table on the Physical Drive */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_fdisk ( + BYTE pdrv, /* Physical drive number */ + const DWORD* szt, /* Pointer to the size table for each partitions */ + void* work /* Pointer to the working buffer */ +) +{ + UINT i, n, sz_cyl, tot_cyl, b_cyl, e_cyl, p_cyl; + BYTE s_hd, e_hd, *p, *buf = (BYTE*)work; + DSTATUS stat; + DWORD sz_disk, sz_part, s_part; + + stat = disk_initialize(pdrv); + if (stat & STA_NOINIT) return FR_NOT_READY; + if (stat & STA_PROTECT) return FR_WRITE_PROTECTED; + if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_disk)) return FR_DISK_ERR; + + /* Determine the CHS without any consideration of the drive geometry */ + for (n = 16; n < 256 && sz_disk / n / 63 > 1024; n *= 2) ; + if (n == 256) n--; + e_hd = n - 1; + sz_cyl = 63 * n; + tot_cyl = sz_disk / sz_cyl; + + /* Create partition table */ + mem_set(buf, 0, FF_MAX_SS); + p = buf + MBR_Table; b_cyl = 0; + for (i = 0; i < 4; i++, p += SZ_PTE) { + p_cyl = (szt[i] <= 100U) ? (DWORD)tot_cyl * szt[i] / 100 : szt[i] / sz_cyl; /* Number of cylinders */ + if (p_cyl == 0) continue; + s_part = (DWORD)sz_cyl * b_cyl; + sz_part = (DWORD)sz_cyl * p_cyl; + if (i == 0) { /* Exclude first track of cylinder 0 */ + s_hd = 1; + s_part += 63; sz_part -= 63; + } else { + s_hd = 0; + } + e_cyl = b_cyl + p_cyl - 1; /* End cylinder */ + if (e_cyl >= tot_cyl) return FR_INVALID_PARAMETER; + + /* Set partition table */ + p[1] = s_hd; /* Start head */ + p[2] = (BYTE)((b_cyl >> 2) + 1); /* Start sector */ + p[3] = (BYTE)b_cyl; /* Start cylinder */ + p[4] = 0x07; /* System type (temporary setting) */ + p[5] = e_hd; /* End head */ + p[6] = (BYTE)((e_cyl >> 2) + 63); /* End sector */ + p[7] = (BYTE)e_cyl; /* End cylinder */ + st_dword(p + 8, s_part); /* Start sector in LBA */ + st_dword(p + 12, sz_part); /* Number of sectors */ + + /* Next partition */ + b_cyl += p_cyl; + } + st_word(p, 0xAA55); + + /* Write it to the MBR */ + return (disk_write(pdrv, buf, 0, 1) != RES_OK || disk_ioctl(pdrv, CTRL_SYNC, 0) != RES_OK) ? FR_DISK_ERR : FR_OK; +} + +#endif /* FF_MULTI_PARTITION */ +#endif /* FF_USE_MKFS && !FF_FS_READONLY */ + + + + + +#if FF_USE_STRFUNC +/*-----------------------------------------------------------------------*/ +/* Get a String from the File */ +/*-----------------------------------------------------------------------*/ + +TCHAR* f_gets ( + TCHAR* buff, /* Pointer to the string buffer to read */ + int len, /* Size of string buffer (characters) */ + FIL* fp /* Pointer to the file object */ +) +{ + int n = 0; + TCHAR c, *p = buff; + BYTE s[2]; + UINT rc; + + + while (n < len - 1) { /* Read characters until buffer gets filled */ +#if FF_LFN_UNICODE && FF_USE_LFN /* Unicode API */ +#if FF_STRF_ENCODE == 3 /* Read a character in UTF-8 */ + f_read(fp, s, 1, &rc); + if (rc != 1) break; + c = s[0]; + if (c >= 0x80) { + if (c < 0xC0) continue; /* Skip stray trailer */ + if (c < 0xE0) { /* Two-byte sequence (0x80-0x7FF) */ + f_read(fp, s, 1, &rc); + if (rc != 1) break; + c = (c & 0x1F) << 6 | (s[0] & 0x3F); + if (c < 0x80) c = '?'; /* Reject invalid code range */ + } else { + if (c < 0xF0) { /* Three-byte sequence (0x800-0xFFFF) */ + f_read(fp, s, 2, &rc); + if (rc != 2) break; + c = c << 12 | (s[0] & 0x3F) << 6 | (s[1] & 0x3F); + if (c < 0x800) c = '?'; /* Reject invalid code range */ + } else { /* Reject four-byte sequence */ + c = '?'; + } + } + } +#elif FF_STRF_ENCODE == 2 /* Read a character in UTF-16BE */ + f_read(fp, s, 2, &rc); + if (rc != 2) break; + c = s[1] + (s[0] << 8); +#elif FF_STRF_ENCODE == 1 /* Read a character in UTF-16LE */ + f_read(fp, s, 2, &rc); + if (rc != 2) break; + c = s[0] + (s[1] << 8); +#else /* Read a character in ANSI/OEM */ + f_read(fp, s, 1, &rc); + if (rc != 1) break; + c = s[0]; + if (dbc_1st((BYTE)c)) { + f_read(fp, s, 1, &rc); + if (rc != 1) break; + c = (c << 8) + s[0]; + } + c = ff_oem2uni(c, CODEPAGE); /* OEM -> Unicode */ + if (!c) c = '?'; +#endif +#else /* ANSI/OEM API: Read a character without conversion */ + f_read(fp, s, 1, &rc); + if (rc != 1) break; + c = s[0]; +#endif + if (FF_USE_STRFUNC == 2 && c == '\r') continue; /* Strip '\r' */ + *p++ = c; + n++; + if (c == '\n') break; /* Break on EOL */ + } + *p = 0; + return n ? buff : 0; /* When no data read (eof or error), return with error. */ +} + + + + +#if !FF_FS_READONLY +#include +/*-----------------------------------------------------------------------*/ +/* Put a Character to the File */ +/*-----------------------------------------------------------------------*/ + +typedef struct { + FIL *fp; /* Ptr to the writing file */ + int idx, nchr; /* Write index of buf[] (-1:error), number of chars written */ + BYTE buf[64]; /* Write buffer */ +} putbuff; + + +static +void putc_bfd ( /* Buffered write with code conversion */ + putbuff* pb, + TCHAR c +) +{ + UINT bw; + int i; + + + if (FF_USE_STRFUNC == 2 && c == '\n') { /* LF -> CRLF conversion */ + putc_bfd(pb, '\r'); + } + + i = pb->idx; /* Write index of pb->buf[] */ + if (i < 0) return; + +#if FF_LFN_UNICODE && FF_USE_LFN /* Unicode API */ +#if FF_STRF_ENCODE == 3 /* Write a character in UTF-8 */ + if (c < 0x80) { /* 7-bit */ + pb->buf[i++] = (BYTE)c; + } else { + if (c < 0x800) { /* 11-bit */ + pb->buf[i++] = (BYTE)(0xC0 | c >> 6); + } else { /* 16-bit */ + pb->buf[i++] = (BYTE)(0xE0 | c >> 12); + pb->buf[i++] = (BYTE)(0x80 | (c >> 6 & 0x3F)); + } + pb->buf[i++] = (BYTE)(0x80 | (c & 0x3F)); + } +#elif FF_STRF_ENCODE == 2 /* Write a character in UTF-16BE */ + pb->buf[i++] = (BYTE)(c >> 8); + pb->buf[i++] = (BYTE)c; +#elif FF_STRF_ENCODE == 1 /* Write a character in UTF-16LE */ + pb->buf[i++] = (BYTE)c; + pb->buf[i++] = (BYTE)(c >> 8); +#else /* Write a character in ANSI/OEM */ + c = ff_uni2oem(c, CODEPAGE); /* Unicode -> OEM */ + if (!c) c = '?'; + if (c >= 0x100) + pb->buf[i++] = (BYTE)(c >> 8); + pb->buf[i++] = (BYTE)c; +#endif +#else /* ANSI/OEM API: Write a character without conversion */ + pb->buf[i++] = (BYTE)c; +#endif + + if (i >= (int)(sizeof pb->buf) - 3) { /* Write buffered characters to the file */ + f_write(pb->fp, pb->buf, (UINT)i, &bw); + i = (bw == (UINT)i) ? 0 : -1; + } + pb->idx = i; + pb->nchr++; +} + + +static +int putc_flush ( /* Flush left characters in the buffer */ + putbuff* pb +) +{ + UINT nw; + + if ( pb->idx >= 0 /* Flush buffered characters to the file */ + && f_write(pb->fp, pb->buf, (UINT)pb->idx, &nw) == FR_OK + && (UINT)pb->idx == nw) return pb->nchr; + return EOF; +} + + +static +void putc_init ( /* Initialize write buffer */ + putbuff* pb, + FIL* fp +) +{ + pb->fp = fp; + pb->nchr = pb->idx = 0; +} + + + +int f_putc ( + TCHAR c, /* A character to be output */ + FIL* fp /* Pointer to the file object */ +) +{ + putbuff pb; + + + putc_init(&pb, fp); + putc_bfd(&pb, c); /* Put the character */ + return putc_flush(&pb); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Put a String to the File */ +/*-----------------------------------------------------------------------*/ + +int f_puts ( + const TCHAR* str, /* Pointer to the string to be output */ + FIL* fp /* Pointer to the file object */ +) +{ + putbuff pb; + + + putc_init(&pb, fp); + while (*str) putc_bfd(&pb, *str++); /* Put the string */ + return putc_flush(&pb); +} + + + + +/*-----------------------------------------------------------------------*/ +/* Put a Formatted String to the File */ +/*-----------------------------------------------------------------------*/ + +int f_printf ( + FIL* fp, /* Pointer to the file object */ + const TCHAR* fmt, /* Pointer to the format string */ + ... /* Optional arguments... */ +) +{ + va_list arp; + putbuff pb; + BYTE f, r; + UINT i, j, w; + DWORD v; + TCHAR c, d, str[32], *p; + + + putc_init(&pb, fp); + + va_start(arp, fmt); + + for (;;) { + c = *fmt++; + if (c == 0) break; /* End of string */ + if (c != '%') { /* Non escape character */ + putc_bfd(&pb, c); + continue; + } + w = f = 0; + c = *fmt++; + if (c == '0') { /* Flag: '0' padding */ + f = 1; c = *fmt++; + } else { + if (c == '-') { /* Flag: left justified */ + f = 2; c = *fmt++; + } + } + while (IsDigit(c)) { /* Precision */ + w = w * 10 + c - '0'; + c = *fmt++; + } + if (c == 'l' || c == 'L') { /* Prefix: Size is long int */ + f |= 4; c = *fmt++; + } + if (!c) break; + d = c; + if (IsLower(d)) d -= 0x20; + switch (d) { /* Type is... */ + case 'S' : /* String */ + p = va_arg(arp, TCHAR*); + for (j = 0; p[j]; j++) ; + if (!(f & 2)) { /* Right pad */ + while (j++ < w) putc_bfd(&pb, ' '); + } + while (*p) putc_bfd(&pb, *p++); /* String body */ + while (j++ < w) putc_bfd(&pb, ' '); /* Left pad */ + continue; + + case 'C' : /* Character */ + putc_bfd(&pb, (TCHAR)va_arg(arp, int)); continue; + + case 'B' : /* Binary */ + r = 2; break; + + case 'O' : /* Octal */ + r = 8; break; + + case 'D' : /* Signed decimal */ + case 'U' : /* Unsigned decimal */ + r = 10; break; + + case 'X' : /* Hexdecimal */ + r = 16; break; + + default: /* Unknown type (pass-through) */ + putc_bfd(&pb, c); continue; + } + + /* Get an argument and put it in numeral */ + v = (f & 4) ? (DWORD)va_arg(arp, long) : ((d == 'D') ? (DWORD)(long)va_arg(arp, int) : (DWORD)va_arg(arp, unsigned int)); + if (d == 'D' && (v & 0x80000000)) { + v = 0 - v; + f |= 8; + } + i = 0; + do { + d = (TCHAR)(v % r); v /= r; + if (d > 9) d += (c == 'x') ? 0x27 : 0x07; + str[i++] = d + '0'; + } while (v && i < sizeof str / sizeof *str); + if (f & 8) str[i++] = '-'; + j = i; d = (f & 1) ? '0' : ' '; + if (!(f & 2)) { + while (j++ < w) putc_bfd(&pb, d); /* Right pad */ + } + do { + putc_bfd(&pb, str[--i]); /* Number body */ + } while (i); + while (j++ < w) putc_bfd(&pb, d); /* Left pad */ + } + + va_end(arp); + + return putc_flush(&pb); +} + +#endif /* !FF_FS_READONLY */ +#endif /* FF_USE_STRFUNC */ + + + +#if FF_CODE_PAGE == 0 +/*-----------------------------------------------------------------------*/ +/* Set Active Codepage for the Path Name */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_setcp ( + WORD cp /* Value to be set as active code page */ +) +{ + static const WORD validcp[] = { 437, 720, 737, 771, 775, 850, 852, 857, 860, 861, 862, 863, 864, 865, 866, 869, 932, 936, 949, 950, 0}; + static const BYTE *const tables[] = {Ct437, Ct720, Ct737, Ct771, Ct775, Ct850, Ct852, Ct857, Ct860, Ct861, Ct862, Ct863, Ct864, Ct865, Ct866, Ct869, Dc932, Dc936, Dc949, Dc950, 0}; + UINT i; + + + for (i = 0; validcp[i] != 0 && validcp[i] != cp; i++) ; /* Find the code page */ + if (validcp[i] != cp) return FR_INVALID_PARAMETER; + + CodePage = cp; + if (cp >= 900) { /* DBCS */ + ExCvt = 0; + DbcTbl = tables[i]; + } else { /* SBCS */ + ExCvt = tables[i]; + DbcTbl = 0; + } + return FR_OK; +} +#endif /* FF_CODE_PAGE == 0 */ + +FRESULT f_SeekfromCurPos( FIL *fp ,BYTE ff_fb,DWORD bytes) +{ + FRESULT res; + FSIZE_t offset = 0; + + if(ff_fb == 0) + {//forward + if (fp->fptr + bytes > fp->obj.objsize) + { + offset = fp->obj.objsize; + res = FR_FILE_END; + } + else + offset = fp->obj.objsize+ bytes; + } + else + {//backward + if(fp->fptr < bytes) + { + offset = 0; + res = FR_FILE_BEGIN; + } + else + offset = fp->fptr - bytes; + } + if(res!= FR_OK) + return res; + res = f_lseek(fp,offset); + return res; +} + +FRESULT f_EOF(FIL *fp ) +{ + + if(fp->obj.objsize <= fp->fptr) + return FR_FILE_END; + else + return FR_OK; + +} + +FRESULT Beken_dir_sdi( + DIR* dp, /* Pointer to directory object */ + DWORD ofs /* Offset of directory table */ +) +{ + return dir_sdi(dp,ofs); +} +FRESULT Beken_dir_read( + DIR* dp, /* Pointer to the directory object */ + int vol /* Filtered by 0:file/directory or 1:volume label */ +) +{ + return dir_read(dp,vol); +} +FRESULT Beken_dir_next( + DIR* dp, /* Pointer to the directory object */ + int stretch /* 0: Do not stretch table, 1: Stretch table if needed */ +) +{ + return dir_next(dp,stretch); +} +void Beken_get_fileinfo( + DIR* dp, /* Pointer to the directory object */ + FILINFO* fno /* Pointer to the file information to be filled */ +) +{ + get_fileinfo(dp,fno); +} + + +void beken_mem_cpy (void* dst, const void* src, UINT cnt) +{ + mem_cpy ( dst, src, cnt); + +} +FRESULT init_buf(FATFS *fs) +{ + DEF_NAMBUF + INIT_NAMBUF(fs); + return FR_OK; +} +void uninit_buf(FATFS *fs) +{ + ff_memfree(fs->lfnbuf); +} + +void beken_mem_set(void* dst, int val, UINT cnt) +{ + mem_set(dst,val,cnt); +} + +DWORD get_fattime (void) +{ + return ((DWORD)(FF_NORTC_YEAR - 1980) << 25 | (DWORD)FF_NORTC_MON << 21 | (DWORD)FF_NORTC_MDAY << 16); +} diff --git a/beken_os/beken378/func/music_player/fs_fat/ff.h b/beken_os/beken378/func/music_player/fs_fat/ff.h new file mode 100755 index 0000000..be12a7b --- /dev/null +++ b/beken_os/beken378/func/music_player/fs_fat/ff.h @@ -0,0 +1,410 @@ +/*----------------------------------------------------------------------------/ +/ FatFs - Generic FAT Filesystem module R0.13 / +/-----------------------------------------------------------------------------/ +/ +/ Copyright (C) 2017, ChaN, all right reserved. +/ +/ FatFs module is an open source software. Redistribution and use of FatFs in +/ source and binary forms, with or without modification, are permitted provided +/ that the following condition is met: + +/ 1. Redistributions of source code must retain the above copyright notice, +/ this condition and the following disclaimer. +/ +/ This software is provided by the copyright holder and contributors "AS IS" +/ and any warranties related to this software are DISCLAIMED. +/ The copyright owner or contributors be NOT LIABLE for any damages caused +/ by use of this software. +/ +/----------------------------------------------------------------------------*/ +#ifndef FF_DEFINED_H_ +#define FF_DEFINED_H_ + +#define FF_DEFINED 87030 /* Revision ID */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "integer.h" /* Basic integer types */ +#include "ffconf.h" /* FatFs configuration options */ + +#if FF_DEFINED != FFCONF_DEF +#error Wrong configuration file (ffconf.h). +#endif + + + +/* Definitions of volume management */ + +#if FF_MULTI_PARTITION /* Multiple partition configuration */ +typedef struct { + BYTE pd; /* Physical drive number */ + BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */ +} PARTITION; +extern PARTITION VolToPart[]; /* Volume - Partition resolution table */ +#endif + +/* Type of path name strings on FatFs API */ + +#if FF_LFN_UNICODE && FF_USE_LFN /* Unicode (UTF-16) string */ +#ifndef _INC_TCHAR +typedef WCHAR TCHAR; +#define _T(x) L ## x +#define _TEXT(x) L ## x +#define _INC_TCHAR +#endif +#else /* ANSI/OEM string */ +#ifndef _INC_TCHAR +typedef char TCHAR; +#define _T(x) x +#define _TEXT(x) x +#define _INC_TCHAR +#endif +#endif + +/* Type of file size variables */ + +#if FF_FS_EXFAT +#if !FF_USE_LFN +#error LFN must be enabled when enable exFAT +#endif +typedef QWORD FSIZE_t; +#else +typedef DWORD FSIZE_t; +#endif + +typedef struct _fat_file_info_s +{ + BYTE filename[13]; + BYTE ext_name[3]; + DWORD file_start_cluster; + DWORD file_blks; +}fat_file_info_t; + +/* Filesystem object structure (FATFS) */ + +typedef struct { + BYTE fs_type; /* Filesystem type (0:N/A) */ + BYTE pdrv; /* Physical drive number */ + BYTE n_fats; /* Number of FATs (1 or 2) */ + BYTE wflag; /* win[] flag (b0:dirty) */ + BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */ + WORD id; /* Volume mount ID */ + WORD n_rootdir; /* Number of root directory entries (FAT12/16) */ + WORD csize; /* Cluster size [sectors] */ +#if FF_MAX_SS != FF_MIN_SS + WORD ssize; /* Sector size (512, 1024, 2048 or 4096) */ +#endif +#if FF_USE_LFN + WCHAR* lfnbuf; /* LFN working buffer */ +#endif +#if FF_FS_EXFAT + BYTE* dirbuf; /* Directory entry block scratchpad buffer for exFAT */ +#endif +#if FF_FS_REENTRANT + FF_SYNC_t sobj; /* Identifier of sync object */ +#endif +#if !FF_FS_READONLY + DWORD last_clst; /* Last allocated cluster */ + DWORD free_clst; /* Number of free clusters */ +#endif +#if FF_FS_RPATH + DWORD cdir; /* Current directory start cluster (0:root) */ +#if FF_FS_EXFAT + DWORD cdc_scl; /* Containing directory start cluster (invalid when cdir is 0) */ + DWORD cdc_size; /* b31-b8:Size of containing directory, b7-b0: Chain status */ + DWORD cdc_ofs; /* Offset in the containing directory (invalid when cdir is 0) */ +#endif +#endif + DWORD n_fatent; /* Number of FAT entries (number of clusters + 2) */ + DWORD fsize; /* Size of an FAT [sectors] */ + DWORD volbase; /* Volume base sector */ + DWORD fatbase; /* FAT base sector */ + DWORD dirbase; /* Root directory base sector/cluster */ + DWORD database; /* Data base sector */ + DWORD winsect; /* Current sector appearing in the win[] */ + BYTE win[FF_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */ +} FATFS; + + + +/* Object ID and allocation information (FFOBJID) */ + +typedef struct { + FATFS* fs; /* Pointer to the hosting volume of this object */ + WORD id; /* Hosting volume mount ID */ + BYTE attr; /* Object attribute */ + BYTE stat; /* Object chain status (b1-0: =0:not contiguous, =2:contiguous, =3:flagmented in this session, b2:sub-directory stretched) */ + DWORD sclust; /* Object data start cluster (0:no cluster or root directory) */ + FSIZE_t objsize; /* Object size (valid when sclust != 0) */ +#if FF_FS_EXFAT + DWORD n_cont; /* Size of first fragment - 1 (valid when stat == 3) */ + DWORD n_frag; /* Size of last fragment needs to be written to FAT (valid when not zero) */ + DWORD c_scl; /* Containing directory start cluster (valid when sclust != 0) */ + DWORD c_size; /* b31-b8:Size of containing directory, b7-b0: Chain status (valid when c_scl != 0) */ + DWORD c_ofs; /* Offset in the containing directory (valid when file object and sclust != 0) */ +#endif +#if FF_FS_LOCK + UINT lockid; /* File lock ID origin from 1 (index of file semaphore table Files[]) */ +#endif +} FFOBJID; + + + +/* File object structure (FIL) */ + +typedef struct { + FFOBJID obj; /* Object identifier (must be the 1st member to detect invalid object pointer) */ + BYTE flag; /* File status flags */ + BYTE err; /* Abort flag (error code) */ + FSIZE_t fptr; /* File read/write pointer (Zeroed on file open) */ + DWORD clust; /* Current cluster of fpter (invalid when fptr is 0) */ + DWORD sect; /* Sector number appearing in buf[] (0:invalid) */ +#if !FF_FS_READONLY + DWORD dir_sect; /* Sector number containing the directory entry (not used at exFAT) */ + BYTE* dir_ptr; /* Pointer to the directory entry in the win[] (not used at exFAT) */ +#endif +#if FF_USE_FASTSEEK + DWORD* cltbl; /* Pointer to the cluster link map table (nulled on open, set by application) */ +#endif +#if !FF_FS_TINY + BYTE buf[FF_MAX_SS]; /* File private data read/write window */ +#endif +} FIL; + + + +/* Directory object structure (DIR) */ + +typedef struct { + FFOBJID obj; /* Object identifier */ + DWORD dptr; /* Current read/write offset */ + DWORD clust; /* Current cluster */ + DWORD sect; /* Current sector (0:Read operation has terminated) */ + BYTE* dir; /* Pointer to the directory item in the win[] */ + BYTE fn[12]; /* SFN (in/out) {body[8],ext[3],status[1]} */ +#if FF_USE_LFN + DWORD blk_ofs; /* Offset of current entry block being processed (0xFFFFFFFF:Invalid) */ +#endif +#if FF_USE_FIND + const TCHAR* pat; /* Pointer to the name matching pattern */ +#endif +} DIR; + + + +/* File information structure (FILINFO) */ + +typedef struct { + FSIZE_t fsize; /* File size */ + WORD fdate; /* Modified date */ + WORD ftime; /* Modified time */ + BYTE fattrib; /* File attribute */ +#if FF_USE_LFN + TCHAR altname[13]; /* Altenative file name */ + TCHAR fname[FF_MAX_LFN + 1]; /* Primary file name */ +#else + TCHAR fname[13]; /* File name */ +#endif + +#if FF_BEKEN_FILESCAN + BYTE ExNoChainFlag; + UINT fcluster; +#endif +} FILINFO,FILINFOADD,*PFILINFOADD; + + +#if FF_BEKEN_FILESCAN + +typedef struct +{ + UINT fcluster; //ļĴغ + BYTE fname[13]; /* Short file name (8.3 format) */ + BYTE extname[3]; + BYTE fat_ok_flag; +} FILE_INFO; + +/*app struct*/ +typedef struct +{ + UINT first_cluster; + WORD music_total; + BYTE broot_dir; + BYTE ExNoChainFlag; +}FAT_DIR_INFO; + +typedef struct _DIR_QUEUE +{ + UINT cluster_number; + WORD dirlevel; + BYTE broot_dir; + BYTE ExNoChainFlag; + struct _DIR_QUEUE* next; +}DIR_QUEUE; + +#endif + +/* File function return code (FRESULT) */ + +typedef enum { + FR_OK = 0, /* (0) Succeeded */ + FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */ + FR_INT_ERR, /* (2) Assertion failed */ + FR_NOT_READY, /* (3) The physical drive cannot work */ + FR_NO_FILE, /* (4) Could not find the file */ + FR_NO_PATH, /* (5) Could not find the path */ + FR_INVALID_NAME, /* (6) The path name format is invalid */ + FR_DENIED, /* (7) Access denied due to prohibited access or directory full */ + FR_EXIST, /* (8) Access denied due to prohibited access */ + FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */ + FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */ + FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */ + FR_NOT_ENABLED, /* (12) The volume has no work area */ + FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */ + FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any problem */ + FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */ + FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */ + FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */ + FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > FF_FS_LOCK */ + FR_INVALID_PARAMETER, /* (19) Given parameter is invalid */ + FR_FILE_END, /* (20) File end */ + FR_FILE_BEGIN /* (21) File Begin*/ +} FRESULT; + + + +/*--------------------------------------------------------------*/ +/* FatFs module application interface */ + +FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode); /* Open or create a file */ +FRESULT f_close (FIL* fp); /* Close an open file object */ +FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br); /* Read data from the file */ +FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw); /* Write data to the file */ +FRESULT f_lseek (FIL* fp, FSIZE_t ofs); /* Move file pointer of the file object */ +FRESULT f_truncate (FIL* fp); /* Truncate the file */ +FRESULT f_sync (FIL* fp); /* Flush cached data of the writing file */ +FRESULT f_opendir (DIR* dp, const TCHAR* path); /* Open a directory */ +FRESULT f_closedir (DIR* dp); /* Close an open directory */ +FRESULT f_readdir (DIR* dp, FILINFO* fno); /* Read a directory item */ +FRESULT f_findfirst (DIR* dp, FILINFO* fno, const TCHAR* path, const TCHAR* pattern); /* Find first file */ +FRESULT f_findnext (DIR* dp, FILINFO* fno); /* Find next file */ +FRESULT f_mkdir (const TCHAR* path); /* Create a sub directory */ +FRESULT f_unlink (const TCHAR* path); /* Delete an existing file or directory */ +FRESULT f_rename (const TCHAR* path_old, const TCHAR* path_new); /* Rename/Move a file or directory */ +FRESULT f_stat (const TCHAR* path, FILINFO* fno); /* Get file status */ +FRESULT f_chmod (const TCHAR* path, BYTE attr, BYTE mask); /* Change attribute of a file/dir */ +FRESULT f_utime (const TCHAR* path, const FILINFO* fno); /* Change timestamp of a file/dir */ +FRESULT f_chdir (const TCHAR* path); /* Change current directory */ +FRESULT f_chdrive (const TCHAR* path); /* Change current drive */ +FRESULT f_getcwd (TCHAR* buff, UINT len); /* Get current directory */ +FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs); /* Get number of free clusters on the drive */ +FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn); /* Get volume label */ +FRESULT f_setlabel (const TCHAR* label); /* Set volume label */ +FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf); /* Forward data to the stream */ +FRESULT f_expand (FIL* fp, FSIZE_t szf, BYTE opt); /* Allocate a contiguous block to the file */ +FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); /* Mount/Unmount a logical drive */ +FRESULT f_unmount (BYTE pdrv, const TCHAR* path,BYTE opt); +FRESULT f_mkfs (const TCHAR* path, BYTE opt, DWORD au, void* work, UINT len); /* Create a FAT volume */ +FRESULT f_fdisk (BYTE pdrv, const DWORD* szt, void* work); /* Divide a physical drive into some partitions */ +FRESULT f_setcp (WORD cp); /* Set current code page */ +int f_putc (TCHAR c, FIL* fp); /* Put a character to the file */ +int f_puts (const TCHAR* str, FIL* cp); /* Put a string to the file */ +int f_printf (FIL* fp, const TCHAR* str, ...); /* Put a formatted string to the file */ +TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the file */ + +//#define f_eof(fp) ((int)((fp)->fptr == (fp)->obj.objsize)) +#define f_error(fp) ((fp)->err) +#define f_tell(fp) ((fp)->fptr) +#define f_size(fp) ((fp)->obj.objsize) +#define f_rewind(fp) f_lseek((fp), 0) +#define f_rewinddir(dp) f_readdir((dp), 0) +#define f_rmdir(path) f_unlink(path) +//#define f_unmount(path) f_mount(0, path, 0) + +#ifndef EOF +#define EOF (-1) +#endif + + + + +/*--------------------------------------------------------------*/ +/* Additional user defined functions */ + +/* RTC function */ +#if !FF_FS_READONLY && !FF_FS_NORTC +DWORD get_fattime (void); +#endif + +/* LFN support functions */ +#if FF_USE_LFN /* Code conversion (defined in unicode.c) */ +WCHAR ff_oem2uni (WCHAR oem, WORD cp); /* OEM code to Unicode conversion */ +WCHAR ff_uni2oem (WCHAR uni, WORD cp); /* Unicode to OEM code conversion */ +WCHAR ff_wtoupper (WCHAR uni); /* Unicode upper-case conversion */ +#endif +#if FF_USE_LFN == 3 /* Dynamic memory allocation */ +void* ff_memalloc (UINT msize); /* Allocate memory block */ +void ff_memfree (void* mblock); /* Free memory block */ +#endif + +/* Sync functions */ +#if FF_FS_REENTRANT +int ff_cre_syncobj (BYTE vol, FF_SYNC_t* sobj); /* Create a sync object */ +int ff_req_grant (FF_SYNC_t sobj); /* Lock sync object */ +void ff_rel_grant (FF_SYNC_t sobj); /* Unlock sync object */ +int ff_del_syncobj (FF_SYNC_t sobj); /* Delete a sync object */ +#endif + + +FRESULT Beken_dir_sdi(DIR* dp,DWORD ofs); +FRESULT Beken_dir_read(DIR* dp,int vol); +FRESULT Beken_dir_next(DIR* dp,int stretch); +FRESULT init_buf(FATFS *fs); +void uninit_buf(FATFS *fs); +void Beken_get_fileinfo(DIR* dp,FILINFO* fno); +void beken_mem_set(void* dst, int val, UINT cnt); +void beken_mem_cpy (void* dst, const void* src, UINT cnt); +FRESULT f_EOF(FIL *fp ); +/*--------------------------------------------------------------*/ +/* Flags and offset address */ + + +/* File access mode and open method flags (3rd argument of f_open) */ +#define FA_READ 0x01 +#define FA_WRITE 0x02 +#define FA_OPEN_EXISTING 0x00 +#define FA_CREATE_NEW 0x04 +#define FA_CREATE_ALWAYS 0x08 +#define FA_OPEN_ALWAYS 0x10 +#define FA_OPEN_APPEND 0x30 + +/* Fast seek controls (2nd argument of f_lseek) */ +#define CREATE_LINKMAP ((FSIZE_t)0 - 1) + +/* Format options (2nd argument of f_mkfs) */ +#define FM_FAT 0x01 +#define FM_FAT32 0x02 +#define FM_EXFAT 0x04 +#define FM_ANY 0x07 +#define FM_SFD 0x08 + +/* Filesystem type (FATFS.fs_type) */ +#define FS_FAT12 1 +#define FS_FAT16 2 +#define FS_FAT32 3 +#define FS_EXFAT 4 + +/* File attribute bits for directory entry (FILINFO.fattrib) */ +#define AM_RDO 0x01 /* Read only */ +#define AM_HID 0x02 /* Hidden */ +#define AM_SYS 0x04 /* System */ +#define AM_DIR 0x10 /* Directory */ +#define AM_ARC 0x20 /* Archive */ + + +#ifdef __cplusplus +} +#endif + +#endif /* FF_DEFINED_H_ */ diff --git a/beken_os/beken378/func/music_player/fs_fat/ffconf.h b/beken_os/beken378/func/music_player/fs_fat/ffconf.h new file mode 100755 index 0000000..73d7caa --- /dev/null +++ b/beken_os/beken378/func/music_player/fs_fat/ffconf.h @@ -0,0 +1,272 @@ +/*---------------------------------------------------------------------------/ +/ FatFs - Configuration file +/---------------------------------------------------------------------------*/ + +#define FFCONF_DEF 87030 /* Revision ID */ +/*---------------------------------------------------------------------------/ +/ Function Configurations +/---------------------------------------------------------------------------*/ +#define FF_BEKEN_FILESCAN 1 +/* +This option is used for beken file scan +*/ + +#define FF_FS_READONLY 0 +/* This option switches read-only configuration. (0:Read/Write or 1:Read-only) +/ Read-only configuration removes writing API functions, f_write(), f_sync(), +/ f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree() +/ and optional writing functions as well. */ + + +#define FF_FS_MINIMIZE 0 +/* This option defines minimization level to remove some basic API functions. +/ +/ 0: All basic functions are enabled. +/ 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename() +/ are removed. +/ 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1. +/ 3: f_lseek() function is removed in addition to 2. */ + + +#define FF_USE_STRFUNC 0 +/* This option switches string functions, f_gets(), f_putc(), f_puts() and f_printf(). +/ +/ 0: Disable string functions. +/ 1: Enable without LF-CRLF conversion. +/ 2: Enable with LF-CRLF conversion. */ + + +#define FF_USE_FIND 0 +/* This option switches filtered directory read functions, f_findfirst() and +/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */ + +//ָ֧ʽ +#define FF_USE_MKFS 1 +/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */ + + +#define FF_USE_FASTSEEK 0 +/* This option switches fast seek function. (0:Disable or 1:Enable) */ + + +#define FF_USE_EXPAND 1 +/* This option switches f_expand function. (0:Disable or 1:Enable) */ + + +#define FF_USE_CHMOD 0 +/* This option switches attribute manipulation functions, f_chmod() and f_utime(). +/ (0:Disable or 1:Enable) Also FF_FS_READONLY needs to be 0 to enable this option. */ + + +#define FF_USE_LABEL 0 +/* This option switches volume label functions, f_getlabel() and f_setlabel(). +/ (0:Disable or 1:Enable) */ + + +#define FF_USE_FORWARD 0 +/* This option switches f_forward() function. (0:Disable or 1:Enable) */ + + +/*---------------------------------------------------------------------------/ +/ Locale and Namespace Configurations +/---------------------------------------------------------------------------*/ + +#define FF_CODE_PAGE 437 +/* This option specifies the OEM code page to be used on the target system. +/ Incorrect code page setting can cause a file open failure. +/ +/ 437 - U.S. +/ 720 - Arabic +/ 737 - Greek +/ 771 - KBL +/ 775 - Baltic +/ 850 - Latin 1 +/ 852 - Latin 2 +/ 855 - Cyrillic +/ 857 - Turkish +/ 860 - Portuguese +/ 861 - Icelandic +/ 862 - Hebrew +/ 863 - Canadian French +/ 864 - Arabic +/ 865 - Nordic +/ 866 - Russian +/ 869 - Greek 2 +/ 932 - Japanese (DBCS) +/ 936 - Simplified Chinese (DBCS) +/ 949 - Korean (DBCS) +/ 950 - Traditional Chinese (DBCS) +/ 0 - Include all code pages above and configured by f_setcp() +*/ + + +#define FF_USE_LFN 3 +#define FF_MAX_LFN 255 +/* The FF_USE_LFN switches the support for LFN (long file name). +/ +/ 0: Disable LFN. FF_MAX_LFN has no effect. +/ 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe. +/ 2: Enable LFN with dynamic working buffer on the STACK. +/ 3: Enable LFN with dynamic working buffer on the HEAP. +/ +/ To enable the LFN, Unicode handling functions (option/unicode.c) must be added +/ to the project. The working buffer occupies (FF_MAX_LFN + 1) * 2 bytes and +/ additional 608 bytes at exFAT enabled. FF_MAX_LFN can be in range from 12 to 255. +/ It should be set 255 to support full featured LFN operations. +/ When use stack for the working buffer, take care on stack overflow. When use heap +/ memory for the working buffer, memory management functions, ff_memalloc() and +/ ff_memfree(), must be added to the project. */ + + +#define FF_LFN_UNICODE 0 +/* This option switches character encoding on the API, 0:ANSI/OEM or 1:UTF-16, +/ when LFN is enabled. Also behavior of string I/O functions will be affected by +/ this option. When LFN is not enabled, this option has no effect. +*/ + + +#define FF_STRF_ENCODE 3 +/* When FF_LFN_UNICODE = 1 with LFN enabled, string I/O functions, f_gets(), +/ f_putc(), f_puts and f_printf() convert the character encoding in it. +/ This option selects assumption of character encoding ON THE FILE to be +/ read/written via those functions. +/ +/ 0: ANSI/OEM +/ 1: UTF-16LE +/ 2: UTF-16BE +/ 3: UTF-8 +*/ + + +#define FF_FS_RPATH 0 +/* This option configures support for relative path. +/ +/ 0: Disable relative path and remove related functions. +/ 1: Enable relative path. f_chdir() and f_chdrive() are available. +/ 2: f_getcwd() function is available in addition to 1. +*/ + + +/*---------------------------------------------------------------------------/ +/ Drive/Volume Configurations +/---------------------------------------------------------------------------*/ + +#define FF_VOLUMES 2 +/* Number of volumes (logical drives) to be used. (1-10) */ + + +#define FF_STR_VOLUME_ID 0 +#define FF_VOLUME_STRS "RAM","NAND","CF","SD","SD2","USB","USB2","USB3" +/* FF_STR_VOLUME_ID switches string support for volume ID. +/ When FF_STR_VOLUME_ID is set to 1, also pre-defined strings can be used as drive +/ number in the path name. FF_VOLUME_STRS defines the drive ID strings for each +/ logical drives. Number of items must be equal to FF_VOLUMES. Valid characters for +/ the drive ID strings are: A-Z and 0-9. */ + + +#define FF_MULTI_PARTITION 0 +/* This option switches support for multiple volumes on the physical drive. +/ By default (0), each logical drive number is bound to the same physical drive +/ number and only an FAT volume found on the physical drive will be mounted. +/ When this function is enabled (1), each logical drive number can be bound to +/ arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk() +/ funciton will be available. */ + + +#define FF_MIN_SS 512 +#define FF_MAX_SS 512 +/* This set of options configures the range of sector size to be supported. (512, +/ 1024, 2048 or 4096) Always set both 512 for most systems, generic memory card and +/ harddisk. But a larger value may be required for on-board flash memory and some +/ type of optical media. When FF_MAX_SS is larger than FF_MIN_SS, FatFs is configured +/ for variable sector size mode and disk_ioctl() function needs to implement +/ GET_SECTOR_SIZE command. */ + + +#define FF_USE_TRIM 0 +/* This option switches support for ATA-TRIM. (0:Disable or 1:Enable) +/ To enable Trim function, also CTRL_TRIM command should be implemented to the +/ disk_ioctl() function. */ + + +#define FF_FS_NOFSINFO 0 +/* If you need to know correct free space on the FAT32 volume, set bit 0 of this +/ option, and f_getfree() function at first time after volume mount will force +/ a full FAT scan. Bit 1 controls the use of last allocated cluster number. +/ +/ bit0=0: Use free cluster count in the FSINFO if available. +/ bit0=1: Do not trust free cluster count in the FSINFO. +/ bit1=0: Use last allocated cluster number in the FSINFO if available. +/ bit1=1: Do not trust last allocated cluster number in the FSINFO. +*/ + + + +/*---------------------------------------------------------------------------/ +/ System Configurations +/---------------------------------------------------------------------------*/ + +#define FF_FS_TINY 0 +/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny) +/ At the tiny configuration, size of file object (FIL) is shrinked FF_MAX_SS bytes. +/ Instead of private sector buffer eliminated from the file object, common sector +/ buffer in the filesystem object (FATFS) is used for the file data transfer. */ + + +#define FF_FS_EXFAT 1 +/* This option switches support for exFAT filesystem. (0:Disable or 1:Enable) +/ When enable exFAT, also LFN needs to be enabled. +/ Note that enabling exFAT discards ANSI C (C89) compatibility. */ + + +#define FF_FS_NORTC 0 +#define FF_NORTC_MON 5 +#define FF_NORTC_MDAY 1 +#define FF_NORTC_YEAR 2017 +/* The option FF_FS_NORTC switches timestamp functiton. If the system does not have +/ any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable +/ the timestamp function. All objects modified by FatFs will have a fixed timestamp +/ defined by FF_NORTC_MON, FF_NORTC_MDAY and FF_NORTC_YEAR in local time. +/ To enable timestamp function (FF_FS_NORTC = 0), get_fattime() function need to be +/ added to the project to read current time form real-time clock. FF_NORTC_MON, +/ FF_NORTC_MDAY and FF_NORTC_YEAR have no effect. +/ These options have no effect at read-only configuration (FF_FS_READONLY = 1). */ + + +#define FF_FS_LOCK 0 +/* The option FF_FS_LOCK switches file lock function to control duplicated file open +/ and illegal operation to open objects. This option must be 0 when FF_FS_READONLY +/ is 1. +/ +/ 0: Disable file lock function. To avoid volume corruption, application program +/ should avoid illegal open, remove and rename to the open objects. +/ >0: Enable file lock function. The value defines how many files/sub-directories +/ can be opened simultaneously under file lock control. Note that the file +/ lock control is independent of re-entrancy. */ + + +#define FF_FS_REENTRANT 0 +#define FF_FS_TIMEOUT 1000 +#define FF_SYNC_t HANDLE +/* The option FF_FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs +/ module itself. Note that regardless of this option, file access to different +/ volume is always re-entrant and volume control functions, f_mount(), f_mkfs() +/ and f_fdisk() function, are always not re-entrant. Only file/directory access +/ to the same volume is under control of this function. +/ +/ 0: Disable re-entrancy. FF_FS_TIMEOUT and FF_SYNC_t have no effect. +/ 1: Enable re-entrancy. Also user provided synchronization handlers, +/ ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj() +/ function, must be added to the project. Samples are available in +/ option/syscall.c. +/ +/ The FF_FS_TIMEOUT defines timeout period in unit of time tick. +/ The FF_SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*, +/ SemaphoreHandle_t and etc. A header file for O/S definitions needs to be +/ included somewhere in the scope of ff.h. */ + +/* #include // O/S definitions */ + + + +/*--- End of configuration options ---*/ diff --git a/beken_os/beken378/func/music_player/fs_fat/ffsystem.c b/beken_os/beken378/func/music_player/fs_fat/ffsystem.c new file mode 100755 index 0000000..b893dd4 --- /dev/null +++ b/beken_os/beken378/func/music_player/fs_fat/ffsystem.c @@ -0,0 +1,129 @@ +/*------------------------------------------------------------------------*/ +/* Sample code of OS dependent controls for FatFs */ +/* (C)ChaN, 2017 */ +/*------------------------------------------------------------------------*/ + +#include "sys_rtos.h" +#include "ff.h" +#include "semphr.h" +#include "mem_pub.h" + +#if FF_USE_LFN == 3 /* Dynamic memory allocation */ + +/*------------------------------------------------------------------------*/ +/* Allocate a memory block */ +/*------------------------------------------------------------------------*/ +void* ff_memalloc ( /* Returns pointer to the allocated memory block (null on not enough core) */ + UINT msize /* Number of bytes to allocate */ +) +{ + return os_zalloc(msize); /* Allocate a new memory block with POSIX API */ +} + + +/*------------------------------------------------------------------------*/ +/* Free a memory block */ +/*------------------------------------------------------------------------*/ + +void ff_memfree ( + void* mblock /* Pointer to the memory block to free */ +) +{ + os_free(mblock); /* Free the memory block with POSIX API */ +} + +#endif + + + +#if FF_FS_REENTRANT /* Mutal exclusion */ + +/*------------------------------------------------------------------------*/ +/* Create a Synchronization Object +/*------------------------------------------------------------------------*/ +/* This function is called in f_mount() function to create a new +/ synchronization object for the volume, such as semaphore and mutex. +/ When a 0 is returned, the f_mount() function fails with FR_INT_ERR. +*/ + +//const osMutexDef_t Mutex[FF_VOLUMES]; /* CMSIS-RTOS */ + + +int ff_cre_syncobj ( /* 1:Function succeeded, 0:Could not create the sync object */ + BYTE vol, /* Corresponding volume (logical drive number) */ + FF_SYNC_t *sobj /* Pointer to return the created sync object */ +) +{ + /* Win32 */ +// *sobj = CreateMutex(NULL, FALSE, NULL); +// return (int)(*sobj != INVALID_HANDLE_VALUE); + + /* uITRON */ +// T_CSEM csem = {TA_TPRI,1,1}; +// *sobj = acre_sem(&csem); +// return (int)(*sobj > 0); + + /* uC/OS-II */ +// OS_ERR err; +// *sobj = OSMutexCreate(0, &err); +// return (int)(err == OS_NO_ERR); + + /* FreeRTOS */ + *sobj = xSemaphoreCreateMutex(); + return (int)(*sobj != NULL); + + /* CMSIS-RTOS */ +// *sobj = osMutexCreate(Mutex + vol); +// return (int)(*sobj != NULL); +} + + +/*------------------------------------------------------------------------*/ +/* Delete a Synchronization Object */ +/*------------------------------------------------------------------------*/ +/* This function is called in f_mount() function to delete a synchronization +/ object that created with ff_cre_syncobj() function. When a 0 is returned, +/ the f_mount() function fails with FR_INT_ERR. +*/ + +int ff_del_syncobj ( /* 1:Function succeeded, 0:Could not delete due to an error */ + FF_SYNC_t sobj /* Sync object tied to the logical drive to be deleted */ +) +{ + vSemaphoreDelete(sobj); + + return 1; +} + + +/*------------------------------------------------------------------------*/ +/* Request Grant to Access the Volume */ +/*------------------------------------------------------------------------*/ +/* This function is called on entering file functions to lock the volume. +/ When a 0 is returned, the file function fails with FR_TIMEOUT. +*/ + +int ff_req_grant ( /* 1:Got a grant to access the volume, 0:Could not get a grant */ + FF_SYNC_t sobj /* Sync object to wait */ +) +{ + /* FreeRTOS */ + return (int)(xSemaphoreTake(sobj, FF_FS_TIMEOUT) == pdTRUE); +} + + +/*------------------------------------------------------------------------*/ +/* Release Grant to Access the Volume */ +/*------------------------------------------------------------------------*/ +/* This function is called on leaving file functions to unlock the volume. +*/ + +void ff_rel_grant ( + FF_SYNC_t sobj /* Sync object to be signaled */ +) +{ + xSemaphoreGive(sobj); +} + +#endif + diff --git a/beken_os/beken378/func/music_player/fs_fat/ffunicode.c b/beken_os/beken378/func/music_player/fs_fat/ffunicode.c new file mode 100755 index 0000000..cf50e8c --- /dev/null +++ b/beken_os/beken378/func/music_player/fs_fat/ffunicode.c @@ -0,0 +1,15566 @@ +/*------------------------------------------------------------------------*/ +/* Unicode handling functions for FatFs R0.13+ */ +/*------------------------------------------------------------------------*/ +/* This module will occupy a huge memory in the .const section when the / +/ FatFs is configured for LFN with DBCS. If the system has any Unicode / +/ utilitiy for the code conversion, this module should be modified to use / +/ that function to avoid silly memory consumption. / +/-------------------------------------------------------------------------*/ +/* +/ Copyright (C) 2017, ChaN, all right reserved. +/ +/ FatFs module is an open source software. Redistribution and use of FatFs in +/ source and binary forms, with or without modification, are permitted provided +/ that the following condition is met: +/ +/ 1. Redistributions of source code must retain the above copyright notice, +/ this condition and the following disclaimer. +/ +/ This software is provided by the copyright holder and contributors "AS IS" +/ and any warranties related to this software are DISCLAIMED. +/ The copyright owner or contributors be NOT LIABLE for any damages caused +/ by use of this software. +*/ + + +#include "ff.h" + +#if FF_USE_LFN + +#define MERGE2(a, b) a ## b +#define CVTBL(tbl, cp) MERGE2(tbl, cp) + + +/*------------------------------------------------------------------------*/ +/* Code Conversion Tables */ +/*------------------------------------------------------------------------*/ + +#if FF_CODE_PAGE == 932 || FF_CODE_PAGE == 0 /* Japanese */ +static +const WCHAR uni2oem932[] = { /* Unicode --> Shift_JIS pairs */ + 0x00A7, 0x8198, 0x00A8, 0x814E, 0x00B0, 0x818B, 0x00B1, 0x817D, 0x00B4, 0x814C, 0x00B6, 0x81F7, 0x00D7, 0x817E, 0x00F7, 0x8180, + 0x0391, 0x839F, 0x0392, 0x83A0, 0x0393, 0x83A1, 0x0394, 0x83A2, 0x0395, 0x83A3, 0x0396, 0x83A4, 0x0397, 0x83A5, 0x0398, 0x83A6, + 0x0399, 0x83A7, 0x039A, 0x83A8, 0x039B, 0x83A9, 0x039C, 0x83AA, 0x039D, 0x83AB, 0x039E, 0x83AC, 0x039F, 0x83AD, 0x03A0, 0x83AE, + 0x03A1, 0x83AF, 0x03A3, 0x83B0, 0x03A4, 0x83B1, 0x03A5, 0x83B2, 0x03A6, 0x83B3, 0x03A7, 0x83B4, 0x03A8, 0x83B5, 0x03A9, 0x83B6, + 0x03B1, 0x83BF, 0x03B2, 0x83C0, 0x03B3, 0x83C1, 0x03B4, 0x83C2, 0x03B5, 0x83C3, 0x03B6, 0x83C4, 0x03B7, 0x83C5, 0x03B8, 0x83C6, + 0x03B9, 0x83C7, 0x03BA, 0x83C8, 0x03BB, 0x83C9, 0x03BC, 0x83CA, 0x03BD, 0x83CB, 0x03BE, 0x83CC, 0x03BF, 0x83CD, 0x03C0, 0x83CE, + 0x03C1, 0x83CF, 0x03C3, 0x83D0, 0x03C4, 0x83D1, 0x03C5, 0x83D2, 0x03C6, 0x83D3, 0x03C7, 0x83D4, 0x03C8, 0x83D5, 0x03C9, 0x83D6, + 0x0401, 0x8446, 0x0410, 0x8440, 0x0411, 0x8441, 0x0412, 0x8442, 0x0413, 0x8443, 0x0414, 0x8444, 0x0415, 0x8445, 0x0416, 0x8447, + 0x0417, 0x8448, 0x0418, 0x8449, 0x0419, 0x844A, 0x041A, 0x844B, 0x041B, 0x844C, 0x041C, 0x844D, 0x041D, 0x844E, 0x041E, 0x844F, + 0x041F, 0x8450, 0x0420, 0x8451, 0x0421, 0x8452, 0x0422, 0x8453, 0x0423, 0x8454, 0x0424, 0x8455, 0x0425, 0x8456, 0x0426, 0x8457, + 0x0427, 0x8458, 0x0428, 0x8459, 0x0429, 0x845A, 0x042A, 0x845B, 0x042B, 0x845C, 0x042C, 0x845D, 0x042D, 0x845E, 0x042E, 0x845F, + 0x042F, 0x8460, 0x0430, 0x8470, 0x0431, 0x8471, 0x0432, 0x8472, 0x0433, 0x8473, 0x0434, 0x8474, 0x0435, 0x8475, 0x0436, 0x8477, + 0x0437, 0x8478, 0x0438, 0x8479, 0x0439, 0x847A, 0x043A, 0x847B, 0x043B, 0x847C, 0x043C, 0x847D, 0x043D, 0x847E, 0x043E, 0x8480, + 0x043F, 0x8481, 0x0440, 0x8482, 0x0441, 0x8483, 0x0442, 0x8484, 0x0443, 0x8485, 0x0444, 0x8486, 0x0445, 0x8487, 0x0446, 0x8488, + 0x0447, 0x8489, 0x0448, 0x848A, 0x0449, 0x848B, 0x044A, 0x848C, 0x044B, 0x848D, 0x044C, 0x848E, 0x044D, 0x848F, 0x044E, 0x8490, + 0x044F, 0x8491, 0x0451, 0x8476, 0x2010, 0x815D, 0x2015, 0x815C, 0x2018, 0x8165, 0x2019, 0x8166, 0x201C, 0x8167, 0x201D, 0x8168, + 0x2020, 0x81F5, 0x2021, 0x81F6, 0x2025, 0x8164, 0x2026, 0x8163, 0x2030, 0x81F1, 0x2032, 0x818C, 0x2033, 0x818D, 0x203B, 0x81A6, + 0x2103, 0x818E, 0x2116, 0x8782, 0x2121, 0x8784, 0x212B, 0x81F0, 0x2160, 0x8754, 0x2161, 0x8755, 0x2162, 0x8756, 0x2163, 0x8757, + 0x2164, 0x8758, 0x2165, 0x8759, 0x2166, 0x875A, 0x2167, 0x875B, 0x2168, 0x875C, 0x2169, 0x875D, 0x2170, 0xFA40, 0x2171, 0xFA41, + 0x2172, 0xFA42, 0x2173, 0xFA43, 0x2174, 0xFA44, 0x2175, 0xFA45, 0x2176, 0xFA46, 0x2177, 0xFA47, 0x2178, 0xFA48, 0x2179, 0xFA49, + 0x2190, 0x81A9, 0x2191, 0x81AA, 0x2192, 0x81A8, 0x2193, 0x81AB, 0x21D2, 0x81CB, 0x21D4, 0x81CC, 0x2200, 0x81CD, 0x2202, 0x81DD, + 0x2203, 0x81CE, 0x2207, 0x81DE, 0x2208, 0x81B8, 0x220B, 0x81B9, 0x2211, 0x8794, 0x221A, 0x81E3, 0x221D, 0x81E5, 0x221E, 0x8187, + 0x221F, 0x8798, 0x2220, 0x81DA, 0x2225, 0x8161, 0x2227, 0x81C8, 0x2228, 0x81C9, 0x2229, 0x81BF, 0x222A, 0x81BE, 0x222B, 0x81E7, + 0x222C, 0x81E8, 0x222E, 0x8793, 0x2234, 0x8188, 0x2235, 0x81E6, 0x223D, 0x81E4, 0x2252, 0x81E0, 0x2260, 0x8182, 0x2261, 0x81DF, + 0x2266, 0x8185, 0x2267, 0x8186, 0x226A, 0x81E1, 0x226B, 0x81E2, 0x2282, 0x81BC, 0x2283, 0x81BD, 0x2286, 0x81BA, 0x2287, 0x81BB, + 0x22A5, 0x81DB, 0x22BF, 0x8799, 0x2312, 0x81DC, 0x2460, 0x8740, 0x2461, 0x8741, 0x2462, 0x8742, 0x2463, 0x8743, 0x2464, 0x8744, + 0x2465, 0x8745, 0x2466, 0x8746, 0x2467, 0x8747, 0x2468, 0x8748, 0x2469, 0x8749, 0x246A, 0x874A, 0x246B, 0x874B, 0x246C, 0x874C, + 0x246D, 0x874D, 0x246E, 0x874E, 0x246F, 0x874F, 0x2470, 0x8750, 0x2471, 0x8751, 0x2472, 0x8752, 0x2473, 0x8753, 0x2500, 0x849F, + 0x2501, 0x84AA, 0x2502, 0x84A0, 0x2503, 0x84AB, 0x250C, 0x84A1, 0x250F, 0x84AC, 0x2510, 0x84A2, 0x2513, 0x84AD, 0x2514, 0x84A4, + 0x2517, 0x84AF, 0x2518, 0x84A3, 0x251B, 0x84AE, 0x251C, 0x84A5, 0x251D, 0x84BA, 0x2520, 0x84B5, 0x2523, 0x84B0, 0x2524, 0x84A7, + 0x2525, 0x84BC, 0x2528, 0x84B7, 0x252B, 0x84B2, 0x252C, 0x84A6, 0x252F, 0x84B6, 0x2530, 0x84BB, 0x2533, 0x84B1, 0x2534, 0x84A8, + 0x2537, 0x84B8, 0x2538, 0x84BD, 0x253B, 0x84B3, 0x253C, 0x84A9, 0x253F, 0x84B9, 0x2542, 0x84BE, 0x254B, 0x84B4, 0x25A0, 0x81A1, + 0x25A1, 0x81A0, 0x25B2, 0x81A3, 0x25B3, 0x81A2, 0x25BC, 0x81A5, 0x25BD, 0x81A4, 0x25C6, 0x819F, 0x25C7, 0x819E, 0x25CB, 0x819B, + 0x25CE, 0x819D, 0x25CF, 0x819C, 0x25EF, 0x81FC, 0x2605, 0x819A, 0x2606, 0x8199, 0x2640, 0x818A, 0x2642, 0x8189, 0x266A, 0x81F4, + 0x266D, 0x81F3, 0x266F, 0x81F2, 0x3000, 0x8140, 0x3001, 0x8141, 0x3002, 0x8142, 0x3003, 0x8156, 0x3005, 0x8158, 0x3006, 0x8159, + 0x3007, 0x815A, 0x3008, 0x8171, 0x3009, 0x8172, 0x300A, 0x8173, 0x300B, 0x8174, 0x300C, 0x8175, 0x300D, 0x8176, 0x300E, 0x8177, + 0x300F, 0x8178, 0x3010, 0x8179, 0x3011, 0x817A, 0x3012, 0x81A7, 0x3013, 0x81AC, 0x3014, 0x816B, 0x3015, 0x816C, 0x301D, 0x8780, + 0x301F, 0x8781, 0x3041, 0x829F, 0x3042, 0x82A0, 0x3043, 0x82A1, 0x3044, 0x82A2, 0x3045, 0x82A3, 0x3046, 0x82A4, 0x3047, 0x82A5, + 0x3048, 0x82A6, 0x3049, 0x82A7, 0x304A, 0x82A8, 0x304B, 0x82A9, 0x304C, 0x82AA, 0x304D, 0x82AB, 0x304E, 0x82AC, 0x304F, 0x82AD, + 0x3050, 0x82AE, 0x3051, 0x82AF, 0x3052, 0x82B0, 0x3053, 0x82B1, 0x3054, 0x82B2, 0x3055, 0x82B3, 0x3056, 0x82B4, 0x3057, 0x82B5, + 0x3058, 0x82B6, 0x3059, 0x82B7, 0x305A, 0x82B8, 0x305B, 0x82B9, 0x305C, 0x82BA, 0x305D, 0x82BB, 0x305E, 0x82BC, 0x305F, 0x82BD, + 0x3060, 0x82BE, 0x3061, 0x82BF, 0x3062, 0x82C0, 0x3063, 0x82C1, 0x3064, 0x82C2, 0x3065, 0x82C3, 0x3066, 0x82C4, 0x3067, 0x82C5, + 0x3068, 0x82C6, 0x3069, 0x82C7, 0x306A, 0x82C8, 0x306B, 0x82C9, 0x306C, 0x82CA, 0x306D, 0x82CB, 0x306E, 0x82CC, 0x306F, 0x82CD, + 0x3070, 0x82CE, 0x3071, 0x82CF, 0x3072, 0x82D0, 0x3073, 0x82D1, 0x3074, 0x82D2, 0x3075, 0x82D3, 0x3076, 0x82D4, 0x3077, 0x82D5, + 0x3078, 0x82D6, 0x3079, 0x82D7, 0x307A, 0x82D8, 0x307B, 0x82D9, 0x307C, 0x82DA, 0x307D, 0x82DB, 0x307E, 0x82DC, 0x307F, 0x82DD, + 0x3080, 0x82DE, 0x3081, 0x82DF, 0x3082, 0x82E0, 0x3083, 0x82E1, 0x3084, 0x82E2, 0x3085, 0x82E3, 0x3086, 0x82E4, 0x3087, 0x82E5, + 0x3088, 0x82E6, 0x3089, 0x82E7, 0x308A, 0x82E8, 0x308B, 0x82E9, 0x308C, 0x82EA, 0x308D, 0x82EB, 0x308E, 0x82EC, 0x308F, 0x82ED, + 0x3090, 0x82EE, 0x3091, 0x82EF, 0x3092, 0x82F0, 0x3093, 0x82F1, 0x309B, 0x814A, 0x309C, 0x814B, 0x309D, 0x8154, 0x309E, 0x8155, + 0x30A1, 0x8340, 0x30A2, 0x8341, 0x30A3, 0x8342, 0x30A4, 0x8343, 0x30A5, 0x8344, 0x30A6, 0x8345, 0x30A7, 0x8346, 0x30A8, 0x8347, + 0x30A9, 0x8348, 0x30AA, 0x8349, 0x30AB, 0x834A, 0x30AC, 0x834B, 0x30AD, 0x834C, 0x30AE, 0x834D, 0x30AF, 0x834E, 0x30B0, 0x834F, + 0x30B1, 0x8350, 0x30B2, 0x8351, 0x30B3, 0x8352, 0x30B4, 0x8353, 0x30B5, 0x8354, 0x30B6, 0x8355, 0x30B7, 0x8356, 0x30B8, 0x8357, + 0x30B9, 0x8358, 0x30BA, 0x8359, 0x30BB, 0x835A, 0x30BC, 0x835B, 0x30BD, 0x835C, 0x30BE, 0x835D, 0x30BF, 0x835E, 0x30C0, 0x835F, + 0x30C1, 0x8360, 0x30C2, 0x8361, 0x30C3, 0x8362, 0x30C4, 0x8363, 0x30C5, 0x8364, 0x30C6, 0x8365, 0x30C7, 0x8366, 0x30C8, 0x8367, + 0x30C9, 0x8368, 0x30CA, 0x8369, 0x30CB, 0x836A, 0x30CC, 0x836B, 0x30CD, 0x836C, 0x30CE, 0x836D, 0x30CF, 0x836E, 0x30D0, 0x836F, + 0x30D1, 0x8370, 0x30D2, 0x8371, 0x30D3, 0x8372, 0x30D4, 0x8373, 0x30D5, 0x8374, 0x30D6, 0x8375, 0x30D7, 0x8376, 0x30D8, 0x8377, + 0x30D9, 0x8378, 0x30DA, 0x8379, 0x30DB, 0x837A, 0x30DC, 0x837B, 0x30DD, 0x837C, 0x30DE, 0x837D, 0x30DF, 0x837E, 0x30E0, 0x8380, + 0x30E1, 0x8381, 0x30E2, 0x8382, 0x30E3, 0x8383, 0x30E4, 0x8384, 0x30E5, 0x8385, 0x30E6, 0x8386, 0x30E7, 0x8387, 0x30E8, 0x8388, + 0x30E9, 0x8389, 0x30EA, 0x838A, 0x30EB, 0x838B, 0x30EC, 0x838C, 0x30ED, 0x838D, 0x30EE, 0x838E, 0x30EF, 0x838F, 0x30F0, 0x8390, + 0x30F1, 0x8391, 0x30F2, 0x8392, 0x30F3, 0x8393, 0x30F4, 0x8394, 0x30F5, 0x8395, 0x30F6, 0x8396, 0x30FB, 0x8145, 0x30FC, 0x815B, + 0x30FD, 0x8152, 0x30FE, 0x8153, 0x3231, 0x878A, 0x3232, 0x878B, 0x3239, 0x878C, 0x32A4, 0x8785, 0x32A5, 0x8786, 0x32A6, 0x8787, + 0x32A7, 0x8788, 0x32A8, 0x8789, 0x3303, 0x8765, 0x330D, 0x8769, 0x3314, 0x8760, 0x3318, 0x8763, 0x3322, 0x8761, 0x3323, 0x876B, + 0x3326, 0x876A, 0x3327, 0x8764, 0x332B, 0x876C, 0x3336, 0x8766, 0x333B, 0x876E, 0x3349, 0x875F, 0x334A, 0x876D, 0x334D, 0x8762, + 0x3351, 0x8767, 0x3357, 0x8768, 0x337B, 0x877E, 0x337C, 0x878F, 0x337D, 0x878E, 0x337E, 0x878D, 0x338E, 0x8772, 0x338F, 0x8773, + 0x339C, 0x876F, 0x339D, 0x8770, 0x339E, 0x8771, 0x33A1, 0x8775, 0x33C4, 0x8774, 0x33CD, 0x8783, 0x4E00, 0x88EA, 0x4E01, 0x929A, + 0x4E03, 0x8EB5, 0x4E07, 0x969C, 0x4E08, 0x8FE4, 0x4E09, 0x8E4F, 0x4E0A, 0x8FE3, 0x4E0B, 0x89BA, 0x4E0D, 0x9573, 0x4E0E, 0x975E, + 0x4E10, 0x98A0, 0x4E11, 0x894E, 0x4E14, 0x8A8E, 0x4E15, 0x98A1, 0x4E16, 0x90A2, 0x4E17, 0x99C0, 0x4E18, 0x8B75, 0x4E19, 0x95B8, + 0x4E1E, 0x8FE5, 0x4E21, 0x97BC, 0x4E26, 0x95C0, 0x4E28, 0xFA68, 0x4E2A, 0x98A2, 0x4E2D, 0x9286, 0x4E31, 0x98A3, 0x4E32, 0x8BF8, + 0x4E36, 0x98A4, 0x4E38, 0x8ADB, 0x4E39, 0x924F, 0x4E3B, 0x8EE5, 0x4E3C, 0x98A5, 0x4E3F, 0x98A6, 0x4E42, 0x98A7, 0x4E43, 0x9454, + 0x4E45, 0x8B76, 0x4E4B, 0x9456, 0x4E4D, 0x93E1, 0x4E4E, 0x8CC1, 0x4E4F, 0x9652, 0x4E55, 0xE568, 0x4E56, 0x98A8, 0x4E57, 0x8FE6, + 0x4E58, 0x98A9, 0x4E59, 0x89B3, 0x4E5D, 0x8BE3, 0x4E5E, 0x8CEE, 0x4E5F, 0x96E7, 0x4E62, 0x9BA4, 0x4E71, 0x9790, 0x4E73, 0x93FB, + 0x4E7E, 0x8AA3, 0x4E80, 0x8B54, 0x4E82, 0x98AA, 0x4E85, 0x98AB, 0x4E86, 0x97B9, 0x4E88, 0x975C, 0x4E89, 0x9188, 0x4E8A, 0x98AD, + 0x4E8B, 0x8E96, 0x4E8C, 0x93F1, 0x4E8E, 0x98B0, 0x4E91, 0x895D, 0x4E92, 0x8CDD, 0x4E94, 0x8CDC, 0x4E95, 0x88E4, 0x4E98, 0x986A, + 0x4E99, 0x9869, 0x4E9B, 0x8DB1, 0x4E9C, 0x889F, 0x4E9E, 0x98B1, 0x4E9F, 0x98B2, 0x4EA0, 0x98B3, 0x4EA1, 0x9653, 0x4EA2, 0x98B4, + 0x4EA4, 0x8CF0, 0x4EA5, 0x88E5, 0x4EA6, 0x9692, 0x4EA8, 0x8B9C, 0x4EAB, 0x8B9D, 0x4EAC, 0x8B9E, 0x4EAD, 0x92E0, 0x4EAE, 0x97BA, + 0x4EB0, 0x98B5, 0x4EB3, 0x98B6, 0x4EB6, 0x98B7, 0x4EBA, 0x906C, 0x4EC0, 0x8F59, 0x4EC1, 0x906D, 0x4EC2, 0x98BC, 0x4EC4, 0x98BA, + 0x4EC6, 0x98BB, 0x4EC7, 0x8B77, 0x4ECA, 0x8DA1, 0x4ECB, 0x89EE, 0x4ECD, 0x98B9, 0x4ECE, 0x98B8, 0x4ECF, 0x95A7, 0x4ED4, 0x8E65, + 0x4ED5, 0x8E64, 0x4ED6, 0x91BC, 0x4ED7, 0x98BD, 0x4ED8, 0x9574, 0x4ED9, 0x90E5, 0x4EDD, 0x8157, 0x4EDE, 0x98BE, 0x4EDF, 0x98C0, + 0x4EE1, 0xFA69, 0x4EE3, 0x91E3, 0x4EE4, 0x97DF, 0x4EE5, 0x88C8, 0x4EED, 0x98BF, 0x4EEE, 0x89BC, 0x4EF0, 0x8BC2, 0x4EF2, 0x9287, + 0x4EF6, 0x8C8F, 0x4EF7, 0x98C1, 0x4EFB, 0x9443, 0x4EFC, 0xFA6A, 0x4F00, 0xFA6B, 0x4F01, 0x8AE9, 0x4F03, 0xFA6C, 0x4F09, 0x98C2, + 0x4F0A, 0x88C9, 0x4F0D, 0x8CDE, 0x4F0E, 0x8AEA, 0x4F0F, 0x959A, 0x4F10, 0x94B0, 0x4F11, 0x8B78, 0x4F1A, 0x89EF, 0x4F1C, 0x98E5, + 0x4F1D, 0x9360, 0x4F2F, 0x948C, 0x4F30, 0x98C4, 0x4F34, 0x94BA, 0x4F36, 0x97E0, 0x4F38, 0x904C, 0x4F39, 0xFA6D, 0x4F3A, 0x8E66, + 0x4F3C, 0x8E97, 0x4F3D, 0x89BE, 0x4F43, 0x92CF, 0x4F46, 0x9241, 0x4F47, 0x98C8, 0x4F4D, 0x88CA, 0x4F4E, 0x92E1, 0x4F4F, 0x8F5A, + 0x4F50, 0x8DB2, 0x4F51, 0x9743, 0x4F53, 0x91CC, 0x4F55, 0x89BD, 0x4F56, 0xFA6E, 0x4F57, 0x98C7, 0x4F59, 0x975D, 0x4F5A, 0x98C3, + 0x4F5B, 0x98C5, 0x4F5C, 0x8DEC, 0x4F5D, 0x98C6, 0x4F5E, 0x9B43, 0x4F69, 0x98CE, 0x4F6F, 0x98D1, 0x4F70, 0x98CF, 0x4F73, 0x89C0, + 0x4F75, 0x95B9, 0x4F76, 0x98C9, 0x4F7B, 0x98CD, 0x4F7C, 0x8CF1, 0x4F7F, 0x8E67, 0x4F83, 0x8AA4, 0x4F86, 0x98D2, 0x4F88, 0x98CA, + 0x4F8A, 0xFA70, 0x4F8B, 0x97E1, 0x4F8D, 0x8E98, 0x4F8F, 0x98CB, 0x4F91, 0x98D0, 0x4F92, 0xFA6F, 0x4F94, 0xFA72, 0x4F96, 0x98D3, + 0x4F98, 0x98CC, 0x4F9A, 0xFA71, 0x4F9B, 0x8B9F, 0x4F9D, 0x88CB, 0x4FA0, 0x8BA0, 0x4FA1, 0x89BF, 0x4FAB, 0x9B44, 0x4FAD, 0x9699, + 0x4FAE, 0x958E, 0x4FAF, 0x8CF2, 0x4FB5, 0x904E, 0x4FB6, 0x97B5, 0x4FBF, 0x95D6, 0x4FC2, 0x8C57, 0x4FC3, 0x91A3, 0x4FC4, 0x89E2, + 0x4FC9, 0xFA61, 0x4FCA, 0x8F72, 0x4FCD, 0xFA73, 0x4FCE, 0x98D7, 0x4FD0, 0x98DC, 0x4FD1, 0x98DA, 0x4FD4, 0x98D5, 0x4FD7, 0x91AD, + 0x4FD8, 0x98D8, 0x4FDA, 0x98DB, 0x4FDB, 0x98D9, 0x4FDD, 0x95DB, 0x4FDF, 0x98D6, 0x4FE1, 0x904D, 0x4FE3, 0x9693, 0x4FE4, 0x98DD, + 0x4FE5, 0x98DE, 0x4FEE, 0x8F43, 0x4FEF, 0x98EB, 0x4FF3, 0x946F, 0x4FF5, 0x9555, 0x4FF6, 0x98E6, 0x4FF8, 0x95EE, 0x4FFA, 0x89B4, + 0x4FFE, 0x98EA, 0x4FFF, 0xFA76, 0x5005, 0x98E4, 0x5006, 0x98ED, 0x5009, 0x9171, 0x500B, 0x8CC2, 0x500D, 0x947B, 0x500F, 0xE0C5, + 0x5011, 0x98EC, 0x5012, 0x937C, 0x5014, 0x98E1, 0x5016, 0x8CF4, 0x5019, 0x8CF3, 0x501A, 0x98DF, 0x501E, 0xFA77, 0x501F, 0x8ED8, + 0x5021, 0x98E7, 0x5022, 0xFA75, 0x5023, 0x95ED, 0x5024, 0x926C, 0x5025, 0x98E3, 0x5026, 0x8C91, 0x5028, 0x98E0, 0x5029, 0x98E8, + 0x502A, 0x98E2, 0x502B, 0x97CF, 0x502C, 0x98E9, 0x502D, 0x9860, 0x5036, 0x8BE4, 0x5039, 0x8C90, 0x5040, 0xFA74, 0x5042, 0xFA7A, + 0x5043, 0x98EE, 0x5046, 0xFA78, 0x5047, 0x98EF, 0x5048, 0x98F3, 0x5049, 0x88CC, 0x504F, 0x95CE, 0x5050, 0x98F2, 0x5055, 0x98F1, + 0x5056, 0x98F5, 0x505A, 0x98F4, 0x505C, 0x92E2, 0x5065, 0x8C92, 0x506C, 0x98F6, 0x5070, 0xFA79, 0x5072, 0x8EC3, 0x5074, 0x91A4, + 0x5075, 0x92E3, 0x5076, 0x8BF4, 0x5078, 0x98F7, 0x507D, 0x8B55, 0x5080, 0x98F8, 0x5085, 0x98FA, 0x508D, 0x9654, 0x5091, 0x8C86, + 0x5094, 0xFA7B, 0x5098, 0x8E50, 0x5099, 0x94F5, 0x509A, 0x98F9, 0x50AC, 0x8DC3, 0x50AD, 0x9762, 0x50B2, 0x98FC, 0x50B3, 0x9942, + 0x50B4, 0x98FB, 0x50B5, 0x8DC2, 0x50B7, 0x8F9D, 0x50BE, 0x8C58, 0x50C2, 0x9943, 0x50C5, 0x8BCD, 0x50C9, 0x9940, 0x50CA, 0x9941, + 0x50CD, 0x93AD, 0x50CF, 0x919C, 0x50D1, 0x8BA1, 0x50D5, 0x966C, 0x50D6, 0x9944, 0x50D8, 0xFA7D, 0x50DA, 0x97BB, 0x50DE, 0x9945, + 0x50E3, 0x9948, 0x50E5, 0x9946, 0x50E7, 0x916D, 0x50ED, 0x9947, 0x50EE, 0x9949, 0x50F4, 0xFA7C, 0x50F5, 0x994B, 0x50F9, 0x994A, + 0x50FB, 0x95C6, 0x5100, 0x8B56, 0x5101, 0x994D, 0x5102, 0x994E, 0x5104, 0x89AD, 0x5109, 0x994C, 0x5112, 0x8EF2, 0x5114, 0x9951, + 0x5115, 0x9950, 0x5116, 0x994F, 0x5118, 0x98D4, 0x511A, 0x9952, 0x511F, 0x8F9E, 0x5121, 0x9953, 0x512A, 0x9744, 0x5132, 0x96D7, + 0x5137, 0x9955, 0x513A, 0x9954, 0x513B, 0x9957, 0x513C, 0x9956, 0x513F, 0x9958, 0x5140, 0x9959, 0x5141, 0x88F2, 0x5143, 0x8CB3, + 0x5144, 0x8C5A, 0x5145, 0x8F5B, 0x5146, 0x929B, 0x5147, 0x8BA2, 0x5148, 0x90E6, 0x5149, 0x8CF5, 0x514A, 0xFA7E, 0x514B, 0x8D8E, + 0x514C, 0x995B, 0x514D, 0x96C6, 0x514E, 0x9365, 0x5150, 0x8E99, 0x5152, 0x995A, 0x5154, 0x995C, 0x515A, 0x937D, 0x515C, 0x8A95, + 0x5162, 0x995D, 0x5164, 0xFA80, 0x5165, 0x93FC, 0x5168, 0x9153, 0x5169, 0x995F, 0x516A, 0x9960, 0x516B, 0x94AA, 0x516C, 0x8CF6, + 0x516D, 0x985A, 0x516E, 0x9961, 0x5171, 0x8BA4, 0x5175, 0x95BA, 0x5176, 0x91B4, 0x5177, 0x8BEF, 0x5178, 0x9354, 0x517C, 0x8C93, + 0x5180, 0x9962, 0x5182, 0x9963, 0x5185, 0x93E0, 0x5186, 0x897E, 0x5189, 0x9966, 0x518A, 0x8DFB, 0x518C, 0x9965, 0x518D, 0x8DC4, + 0x518F, 0x9967, 0x5190, 0xE3EC, 0x5191, 0x9968, 0x5192, 0x9660, 0x5193, 0x9969, 0x5195, 0x996A, 0x5196, 0x996B, 0x5197, 0x8FE7, + 0x5199, 0x8ECA, 0x519D, 0xFA81, 0x51A0, 0x8AA5, 0x51A2, 0x996E, 0x51A4, 0x996C, 0x51A5, 0x96BB, 0x51A6, 0x996D, 0x51A8, 0x9579, + 0x51A9, 0x996F, 0x51AA, 0x9970, 0x51AB, 0x9971, 0x51AC, 0x937E, 0x51B0, 0x9975, 0x51B1, 0x9973, 0x51B2, 0x9974, 0x51B3, 0x9972, + 0x51B4, 0x8DE1, 0x51B5, 0x9976, 0x51B6, 0x96E8, 0x51B7, 0x97E2, 0x51BD, 0x9977, 0x51BE, 0xFA82, 0x51C4, 0x90A6, 0x51C5, 0x9978, + 0x51C6, 0x8F79, 0x51C9, 0x9979, 0x51CB, 0x929C, 0x51CC, 0x97BD, 0x51CD, 0x9380, 0x51D6, 0x99C3, 0x51DB, 0x997A, 0x51DC, 0xEAA3, + 0x51DD, 0x8BC3, 0x51E0, 0x997B, 0x51E1, 0x967D, 0x51E6, 0x8F88, 0x51E7, 0x91FA, 0x51E9, 0x997D, 0x51EA, 0x93E2, 0x51EC, 0xFA83, + 0x51ED, 0x997E, 0x51F0, 0x9980, 0x51F1, 0x8A4D, 0x51F5, 0x9981, 0x51F6, 0x8BA5, 0x51F8, 0x93CA, 0x51F9, 0x899A, 0x51FA, 0x8F6F, + 0x51FD, 0x949F, 0x51FE, 0x9982, 0x5200, 0x9381, 0x5203, 0x906E, 0x5204, 0x9983, 0x5206, 0x95AA, 0x5207, 0x90D8, 0x5208, 0x8AA0, + 0x520A, 0x8AA7, 0x520B, 0x9984, 0x520E, 0x9986, 0x5211, 0x8C59, 0x5214, 0x9985, 0x5215, 0xFA84, 0x5217, 0x97F1, 0x521D, 0x8F89, + 0x5224, 0x94BB, 0x5225, 0x95CA, 0x5227, 0x9987, 0x5229, 0x9798, 0x522A, 0x9988, 0x522E, 0x9989, 0x5230, 0x939E, 0x5233, 0x998A, + 0x5236, 0x90A7, 0x5237, 0x8DFC, 0x5238, 0x8C94, 0x5239, 0x998B, 0x523A, 0x8E68, 0x523B, 0x8D8F, 0x5243, 0x92E4, 0x5244, 0x998D, + 0x5247, 0x91A5, 0x524A, 0x8DED, 0x524B, 0x998E, 0x524C, 0x998F, 0x524D, 0x914F, 0x524F, 0x998C, 0x5254, 0x9991, 0x5256, 0x9655, + 0x525B, 0x8D84, 0x525E, 0x9990, 0x5263, 0x8C95, 0x5264, 0x8DDC, 0x5265, 0x948D, 0x5269, 0x9994, 0x526A, 0x9992, 0x526F, 0x959B, + 0x5270, 0x8FE8, 0x5271, 0x999B, 0x5272, 0x8A84, 0x5273, 0x9995, 0x5274, 0x9993, 0x5275, 0x916E, 0x527D, 0x9997, 0x527F, 0x9996, + 0x5283, 0x8A63, 0x5287, 0x8C80, 0x5288, 0x999C, 0x5289, 0x97AB, 0x528D, 0x9998, 0x5291, 0x999D, 0x5292, 0x999A, 0x5294, 0x9999, + 0x529B, 0x97CD, 0x529C, 0xFA85, 0x529F, 0x8CF7, 0x52A0, 0x89C1, 0x52A3, 0x97F2, 0x52A6, 0xFA86, 0x52A9, 0x8F95, 0x52AA, 0x9377, + 0x52AB, 0x8D85, 0x52AC, 0x99A0, 0x52AD, 0x99A1, 0x52AF, 0xFB77, 0x52B1, 0x97E3, 0x52B4, 0x984A, 0x52B5, 0x99A3, 0x52B9, 0x8CF8, + 0x52BC, 0x99A2, 0x52BE, 0x8A4E, 0x52C0, 0xFA87, 0x52C1, 0x99A4, 0x52C3, 0x9675, 0x52C5, 0x92BA, 0x52C7, 0x9745, 0x52C9, 0x95D7, + 0x52CD, 0x99A5, 0x52D2, 0xE8D3, 0x52D5, 0x93AE, 0x52D7, 0x99A6, 0x52D8, 0x8AA8, 0x52D9, 0x96B1, 0x52DB, 0xFA88, 0x52DD, 0x8F9F, + 0x52DE, 0x99A7, 0x52DF, 0x95E5, 0x52E0, 0x99AB, 0x52E2, 0x90A8, 0x52E3, 0x99A8, 0x52E4, 0x8BCE, 0x52E6, 0x99A9, 0x52E7, 0x8AA9, + 0x52F2, 0x8C4D, 0x52F3, 0x99AC, 0x52F5, 0x99AD, 0x52F8, 0x99AE, 0x52F9, 0x99AF, 0x52FA, 0x8ED9, 0x52FE, 0x8CF9, 0x52FF, 0x96DC, + 0x5300, 0xFA89, 0x5301, 0x96E6, 0x5302, 0x93F5, 0x5305, 0x95EF, 0x5306, 0x99B0, 0x5307, 0xFA8A, 0x5308, 0x99B1, 0x530D, 0x99B3, + 0x530F, 0x99B5, 0x5310, 0x99B4, 0x5315, 0x99B6, 0x5316, 0x89BB, 0x5317, 0x966B, 0x5319, 0x8DFA, 0x531A, 0x99B7, 0x531D, 0x9178, + 0x5320, 0x8FA0, 0x5321, 0x8BA7, 0x5323, 0x99B8, 0x5324, 0xFA8B, 0x532A, 0x94D9, 0x532F, 0x99B9, 0x5331, 0x99BA, 0x5333, 0x99BB, + 0x5338, 0x99BC, 0x5339, 0x9543, 0x533A, 0x8BE6, 0x533B, 0x88E3, 0x533F, 0x93BD, 0x5340, 0x99BD, 0x5341, 0x8F5C, 0x5343, 0x90E7, + 0x5345, 0x99BF, 0x5346, 0x99BE, 0x5347, 0x8FA1, 0x5348, 0x8CDF, 0x5349, 0x99C1, 0x534A, 0x94BC, 0x534D, 0x99C2, 0x5351, 0x94DA, + 0x5352, 0x91B2, 0x5353, 0x91EC, 0x5354, 0x8BA6, 0x5357, 0x93EC, 0x5358, 0x9250, 0x535A, 0x948E, 0x535C, 0x966D, 0x535E, 0x99C4, + 0x5360, 0x90E8, 0x5366, 0x8C54, 0x5369, 0x99C5, 0x536E, 0x99C6, 0x536F, 0x894B, 0x5370, 0x88F3, 0x5371, 0x8AEB, 0x5372, 0xFA8C, + 0x5373, 0x91A6, 0x5374, 0x8B70, 0x5375, 0x9791, 0x5377, 0x99C9, 0x5378, 0x89B5, 0x537B, 0x99C8, 0x537F, 0x8BA8, 0x5382, 0x99CA, + 0x5384, 0x96EF, 0x5393, 0xFA8D, 0x5396, 0x99CB, 0x5398, 0x97D0, 0x539A, 0x8CFA, 0x539F, 0x8CB4, 0x53A0, 0x99CC, 0x53A5, 0x99CE, + 0x53A6, 0x99CD, 0x53A8, 0x907E, 0x53A9, 0x8958, 0x53AD, 0x897D, 0x53AE, 0x99CF, 0x53B0, 0x99D0, 0x53B2, 0xFA8E, 0x53B3, 0x8CB5, + 0x53B6, 0x99D1, 0x53BB, 0x8B8E, 0x53C2, 0x8E51, 0x53C3, 0x99D2, 0x53C8, 0x9694, 0x53C9, 0x8DB3, 0x53CA, 0x8B79, 0x53CB, 0x9746, + 0x53CC, 0x916F, 0x53CD, 0x94BD, 0x53CE, 0x8EFB, 0x53D4, 0x8F66, 0x53D6, 0x8EE6, 0x53D7, 0x8EF3, 0x53D9, 0x8F96, 0x53DB, 0x94BE, + 0x53DD, 0xFA8F, 0x53DF, 0x99D5, 0x53E1, 0x8962, 0x53E2, 0x9170, 0x53E3, 0x8CFB, 0x53E4, 0x8CC3, 0x53E5, 0x8BE5, 0x53E8, 0x99D9, + 0x53E9, 0x9240, 0x53EA, 0x91FC, 0x53EB, 0x8BA9, 0x53EC, 0x8FA2, 0x53ED, 0x99DA, 0x53EE, 0x99D8, 0x53EF, 0x89C2, 0x53F0, 0x91E4, + 0x53F1, 0x8EB6, 0x53F2, 0x8E6A, 0x53F3, 0x8945, 0x53F6, 0x8A90, 0x53F7, 0x8D86, 0x53F8, 0x8E69, 0x53FA, 0x99DB, 0x5401, 0x99DC, + 0x5403, 0x8B68, 0x5404, 0x8A65, 0x5408, 0x8D87, 0x5409, 0x8B67, 0x540A, 0x92DD, 0x540B, 0x8944, 0x540C, 0x93AF, 0x540D, 0x96BC, + 0x540E, 0x8D40, 0x540F, 0x9799, 0x5410, 0x9366, 0x5411, 0x8CFC, 0x541B, 0x8C4E, 0x541D, 0x99E5, 0x541F, 0x8BE1, 0x5420, 0x9669, + 0x5426, 0x94DB, 0x5429, 0x99E4, 0x542B, 0x8ADC, 0x542C, 0x99DF, 0x542D, 0x99E0, 0x542E, 0x99E2, 0x5436, 0x99E3, 0x5438, 0x8B7A, + 0x5439, 0x9081, 0x543B, 0x95AB, 0x543C, 0x99E1, 0x543D, 0x99DD, 0x543E, 0x8CE1, 0x5440, 0x99DE, 0x5442, 0x9843, 0x5446, 0x95F0, + 0x5448, 0x92E6, 0x5449, 0x8CE0, 0x544A, 0x8D90, 0x544E, 0x99E6, 0x5451, 0x93DB, 0x545F, 0x99EA, 0x5468, 0x8EFC, 0x546A, 0x8EF4, + 0x5470, 0x99ED, 0x5471, 0x99EB, 0x5473, 0x96A1, 0x5475, 0x99E8, 0x5476, 0x99F1, 0x5477, 0x99EC, 0x547B, 0x99EF, 0x547C, 0x8CC4, + 0x547D, 0x96BD, 0x5480, 0x99F0, 0x5484, 0x99F2, 0x5486, 0x99F4, 0x548A, 0xFA92, 0x548B, 0x8DEE, 0x548C, 0x9861, 0x548E, 0x99E9, + 0x548F, 0x99E7, 0x5490, 0x99F3, 0x5492, 0x99EE, 0x549C, 0xFA91, 0x54A2, 0x99F6, 0x54A4, 0x9A42, 0x54A5, 0x99F8, 0x54A8, 0x99FC, + 0x54A9, 0xFA93, 0x54AB, 0x9A40, 0x54AC, 0x99F9, 0x54AF, 0x9A5D, 0x54B2, 0x8DE7, 0x54B3, 0x8A50, 0x54B8, 0x99F7, 0x54BC, 0x9A44, + 0x54BD, 0x88F4, 0x54BE, 0x9A43, 0x54C0, 0x88A3, 0x54C1, 0x9569, 0x54C2, 0x9A41, 0x54C4, 0x99FA, 0x54C7, 0x99F5, 0x54C8, 0x99FB, + 0x54C9, 0x8DC6, 0x54D8, 0x9A45, 0x54E1, 0x88F5, 0x54E2, 0x9A4E, 0x54E5, 0x9A46, 0x54E6, 0x9A47, 0x54E8, 0x8FA3, 0x54E9, 0x9689, + 0x54ED, 0x9A4C, 0x54EE, 0x9A4B, 0x54F2, 0x934E, 0x54FA, 0x9A4D, 0x54FD, 0x9A4A, 0x54FF, 0xFA94, 0x5504, 0x8953, 0x5506, 0x8DB4, + 0x5507, 0x904F, 0x550F, 0x9A48, 0x5510, 0x9382, 0x5514, 0x9A49, 0x5516, 0x88A0, 0x552E, 0x9A53, 0x552F, 0x9742, 0x5531, 0x8FA5, + 0x5533, 0x9A59, 0x5538, 0x9A58, 0x5539, 0x9A4F, 0x553E, 0x91C1, 0x5540, 0x9A50, 0x5544, 0x91ED, 0x5545, 0x9A55, 0x5546, 0x8FA4, + 0x554C, 0x9A52, 0x554F, 0x96E2, 0x5553, 0x8C5B, 0x5556, 0x9A56, 0x5557, 0x9A57, 0x555C, 0x9A54, 0x555D, 0x9A5A, 0x5563, 0x9A51, + 0x557B, 0x9A60, 0x557C, 0x9A65, 0x557E, 0x9A61, 0x5580, 0x9A5C, 0x5583, 0x9A66, 0x5584, 0x9150, 0x5586, 0xFA95, 0x5587, 0x9A68, + 0x5589, 0x8D41, 0x558A, 0x9A5E, 0x558B, 0x929D, 0x5598, 0x9A62, 0x5599, 0x9A5B, 0x559A, 0x8AAB, 0x559C, 0x8AEC, 0x559D, 0x8A85, + 0x559E, 0x9A63, 0x559F, 0x9A5F, 0x55A7, 0x8C96, 0x55A8, 0x9A69, 0x55A9, 0x9A67, 0x55AA, 0x9172, 0x55AB, 0x8B69, 0x55AC, 0x8BAA, + 0x55AE, 0x9A64, 0x55B0, 0x8BF2, 0x55B6, 0x8963, 0x55C4, 0x9A6D, 0x55C5, 0x9A6B, 0x55C7, 0x9AA5, 0x55D4, 0x9A70, 0x55DA, 0x9A6A, + 0x55DC, 0x9A6E, 0x55DF, 0x9A6C, 0x55E3, 0x8E6B, 0x55E4, 0x9A6F, 0x55F7, 0x9A72, 0x55F9, 0x9A77, 0x55FD, 0x9A75, 0x55FE, 0x9A74, + 0x5606, 0x9251, 0x5609, 0x89C3, 0x5614, 0x9A71, 0x5616, 0x9A73, 0x5617, 0x8FA6, 0x5618, 0x8952, 0x561B, 0x9A76, 0x5629, 0x89DC, + 0x562F, 0x9A82, 0x5631, 0x8FFA, 0x5632, 0x9A7D, 0x5634, 0x9A7B, 0x5636, 0x9A7C, 0x5638, 0x9A7E, 0x5642, 0x895C, 0x564C, 0x9158, + 0x564E, 0x9A78, 0x5650, 0x9A79, 0x565B, 0x8A9A, 0x5664, 0x9A81, 0x5668, 0x8AED, 0x566A, 0x9A84, 0x566B, 0x9A80, 0x566C, 0x9A83, + 0x5674, 0x95AC, 0x5678, 0x93D3, 0x567A, 0x94B6, 0x5680, 0x9A86, 0x5686, 0x9A85, 0x5687, 0x8A64, 0x568A, 0x9A87, 0x568F, 0x9A8A, + 0x5694, 0x9A89, 0x56A0, 0x9A88, 0x56A2, 0x9458, 0x56A5, 0x9A8B, 0x56AE, 0x9A8C, 0x56B4, 0x9A8E, 0x56B6, 0x9A8D, 0x56BC, 0x9A90, + 0x56C0, 0x9A93, 0x56C1, 0x9A91, 0x56C2, 0x9A8F, 0x56C3, 0x9A92, 0x56C8, 0x9A94, 0x56CE, 0x9A95, 0x56D1, 0x9A96, 0x56D3, 0x9A97, + 0x56D7, 0x9A98, 0x56D8, 0x9964, 0x56DA, 0x8EFA, 0x56DB, 0x8E6C, 0x56DE, 0x89F1, 0x56E0, 0x88F6, 0x56E3, 0x9263, 0x56EE, 0x9A99, + 0x56F0, 0x8DA2, 0x56F2, 0x88CD, 0x56F3, 0x907D, 0x56F9, 0x9A9A, 0x56FA, 0x8CC5, 0x56FD, 0x8D91, 0x56FF, 0x9A9C, 0x5700, 0x9A9B, + 0x5703, 0x95DE, 0x5704, 0x9A9D, 0x5708, 0x9A9F, 0x5709, 0x9A9E, 0x570B, 0x9AA0, 0x570D, 0x9AA1, 0x570F, 0x8C97, 0x5712, 0x8980, + 0x5713, 0x9AA2, 0x5716, 0x9AA4, 0x5718, 0x9AA3, 0x571C, 0x9AA6, 0x571F, 0x9379, 0x5726, 0x9AA7, 0x5727, 0x88B3, 0x5728, 0x8DDD, + 0x572D, 0x8C5C, 0x5730, 0x926E, 0x5737, 0x9AA8, 0x5738, 0x9AA9, 0x573B, 0x9AAB, 0x5740, 0x9AAC, 0x5742, 0x8DE2, 0x5747, 0x8BCF, + 0x574A, 0x9656, 0x574E, 0x9AAA, 0x574F, 0x9AAD, 0x5750, 0x8DBF, 0x5751, 0x8D42, 0x5759, 0xFA96, 0x5761, 0x9AB1, 0x5764, 0x8DA3, + 0x5765, 0xFA97, 0x5766, 0x9252, 0x5769, 0x9AAE, 0x576A, 0x92D8, 0x577F, 0x9AB2, 0x5782, 0x9082, 0x5788, 0x9AB0, 0x5789, 0x9AB3, + 0x578B, 0x8C5E, 0x5793, 0x9AB4, 0x57A0, 0x9AB5, 0x57A2, 0x8D43, 0x57A3, 0x8A5F, 0x57A4, 0x9AB7, 0x57AA, 0x9AB8, 0x57AC, 0xFA98, + 0x57B0, 0x9AB9, 0x57B3, 0x9AB6, 0x57C0, 0x9AAF, 0x57C3, 0x9ABA, 0x57C6, 0x9ABB, 0x57C7, 0xFA9A, 0x57C8, 0xFA99, 0x57CB, 0x9684, + 0x57CE, 0x8FE9, 0x57D2, 0x9ABD, 0x57D3, 0x9ABE, 0x57D4, 0x9ABC, 0x57D6, 0x9AC0, 0x57DC, 0x9457, 0x57DF, 0x88E6, 0x57E0, 0x9575, + 0x57E3, 0x9AC1, 0x57F4, 0x8FFB, 0x57F7, 0x8EB7, 0x57F9, 0x947C, 0x57FA, 0x8AEE, 0x57FC, 0x8DE9, 0x5800, 0x9678, 0x5802, 0x93B0, + 0x5805, 0x8C98, 0x5806, 0x91CD, 0x580A, 0x9ABF, 0x580B, 0x9AC2, 0x5815, 0x91C2, 0x5819, 0x9AC3, 0x581D, 0x9AC4, 0x5821, 0x9AC6, + 0x5824, 0x92E7, 0x582A, 0x8AAC, 0x582F, 0xEA9F, 0x5830, 0x8981, 0x5831, 0x95F1, 0x5834, 0x8FEA, 0x5835, 0x9367, 0x583A, 0x8DE4, + 0x583D, 0x9ACC, 0x5840, 0x95BB, 0x5841, 0x97DB, 0x584A, 0x89F2, 0x584B, 0x9AC8, 0x5851, 0x9159, 0x5852, 0x9ACB, 0x5854, 0x9383, + 0x5857, 0x9368, 0x5858, 0x9384, 0x5859, 0x94B7, 0x585A, 0x92CB, 0x585E, 0x8DC7, 0x5862, 0x9AC7, 0x5869, 0x8996, 0x586B, 0x9355, + 0x5870, 0x9AC9, 0x5872, 0x9AC5, 0x5875, 0x906F, 0x5879, 0x9ACD, 0x587E, 0x8F6D, 0x5883, 0x8BAB, 0x5885, 0x9ACE, 0x5893, 0x95E6, + 0x5897, 0x919D, 0x589C, 0x92C4, 0x589E, 0xFA9D, 0x589F, 0x9AD0, 0x58A8, 0x966E, 0x58AB, 0x9AD1, 0x58AE, 0x9AD6, 0x58B2, 0xFA9E, + 0x58B3, 0x95AD, 0x58B8, 0x9AD5, 0x58B9, 0x9ACF, 0x58BA, 0x9AD2, 0x58BB, 0x9AD4, 0x58BE, 0x8DA4, 0x58C1, 0x95C7, 0x58C5, 0x9AD7, + 0x58C7, 0x9264, 0x58CA, 0x89F3, 0x58CC, 0x8FEB, 0x58D1, 0x9AD9, 0x58D3, 0x9AD8, 0x58D5, 0x8D88, 0x58D7, 0x9ADA, 0x58D8, 0x9ADC, + 0x58D9, 0x9ADB, 0x58DC, 0x9ADE, 0x58DE, 0x9AD3, 0x58DF, 0x9AE0, 0x58E4, 0x9ADF, 0x58E5, 0x9ADD, 0x58EB, 0x8E6D, 0x58EC, 0x9070, + 0x58EE, 0x9173, 0x58EF, 0x9AE1, 0x58F0, 0x90BA, 0x58F1, 0x88EB, 0x58F2, 0x9484, 0x58F7, 0x92D9, 0x58F9, 0x9AE3, 0x58FA, 0x9AE2, + 0x58FB, 0x9AE4, 0x58FC, 0x9AE5, 0x58FD, 0x9AE6, 0x5902, 0x9AE7, 0x5909, 0x95CF, 0x590A, 0x9AE8, 0x590B, 0xFA9F, 0x590F, 0x89C4, + 0x5910, 0x9AE9, 0x5915, 0x975B, 0x5916, 0x8A4F, 0x5918, 0x99C7, 0x5919, 0x8F67, 0x591A, 0x91BD, 0x591B, 0x9AEA, 0x591C, 0x96E9, + 0x5922, 0x96B2, 0x5925, 0x9AEC, 0x5927, 0x91E5, 0x5929, 0x9356, 0x592A, 0x91BE, 0x592B, 0x9576, 0x592C, 0x9AED, 0x592D, 0x9AEE, + 0x592E, 0x899B, 0x5931, 0x8EB8, 0x5932, 0x9AEF, 0x5937, 0x88CE, 0x5938, 0x9AF0, 0x593E, 0x9AF1, 0x5944, 0x8982, 0x5947, 0x8AEF, + 0x5948, 0x93DE, 0x5949, 0x95F2, 0x594E, 0x9AF5, 0x594F, 0x9174, 0x5950, 0x9AF4, 0x5951, 0x8C5F, 0x5953, 0xFAA0, 0x5954, 0x967A, + 0x5955, 0x9AF3, 0x5957, 0x9385, 0x5958, 0x9AF7, 0x595A, 0x9AF6, 0x595B, 0xFAA1, 0x595D, 0xFAA2, 0x5960, 0x9AF9, 0x5962, 0x9AF8, + 0x5963, 0xFAA3, 0x5965, 0x899C, 0x5967, 0x9AFA, 0x5968, 0x8FA7, 0x5969, 0x9AFC, 0x596A, 0x9244, 0x596C, 0x9AFB, 0x596E, 0x95B1, + 0x5973, 0x8F97, 0x5974, 0x937A, 0x5978, 0x9B40, 0x597D, 0x8D44, 0x5981, 0x9B41, 0x5982, 0x9440, 0x5983, 0x94DC, 0x5984, 0x96CF, + 0x598A, 0x9444, 0x598D, 0x9B4A, 0x5993, 0x8B57, 0x5996, 0x9764, 0x5999, 0x96AD, 0x599B, 0x9BAA, 0x599D, 0x9B42, 0x59A3, 0x9B45, + 0x59A4, 0xFAA4, 0x59A5, 0x91C3, 0x59A8, 0x9657, 0x59AC, 0x9369, 0x59B2, 0x9B46, 0x59B9, 0x9685, 0x59BA, 0xFAA5, 0x59BB, 0x8DC8, + 0x59BE, 0x8FA8, 0x59C6, 0x9B47, 0x59C9, 0x8E6F, 0x59CB, 0x8E6E, 0x59D0, 0x88B7, 0x59D1, 0x8CC6, 0x59D3, 0x90A9, 0x59D4, 0x88CF, + 0x59D9, 0x9B4B, 0x59DA, 0x9B4C, 0x59DC, 0x9B49, 0x59E5, 0x8957, 0x59E6, 0x8AAD, 0x59E8, 0x9B48, 0x59EA, 0x96C3, 0x59EB, 0x9550, + 0x59F6, 0x88A6, 0x59FB, 0x88F7, 0x59FF, 0x8E70, 0x5A01, 0x88D0, 0x5A03, 0x88A1, 0x5A09, 0x9B51, 0x5A11, 0x9B4F, 0x5A18, 0x96BA, + 0x5A1A, 0x9B52, 0x5A1C, 0x9B50, 0x5A1F, 0x9B4E, 0x5A20, 0x9050, 0x5A25, 0x9B4D, 0x5A29, 0x95D8, 0x5A2F, 0x8CE2, 0x5A35, 0x9B56, + 0x5A36, 0x9B57, 0x5A3C, 0x8FA9, 0x5A40, 0x9B53, 0x5A41, 0x984B, 0x5A46, 0x946B, 0x5A49, 0x9B55, 0x5A5A, 0x8DA5, 0x5A62, 0x9B58, + 0x5A66, 0x9577, 0x5A6A, 0x9B59, 0x5A6C, 0x9B54, 0x5A7F, 0x96B9, 0x5A92, 0x947D, 0x5A9A, 0x9B5A, 0x5A9B, 0x9551, 0x5ABC, 0x9B5B, + 0x5ABD, 0x9B5F, 0x5ABE, 0x9B5C, 0x5AC1, 0x89C5, 0x5AC2, 0x9B5E, 0x5AC9, 0x8EB9, 0x5ACB, 0x9B5D, 0x5ACC, 0x8C99, 0x5AD0, 0x9B6B, + 0x5AD6, 0x9B64, 0x5AD7, 0x9B61, 0x5AE1, 0x9284, 0x5AE3, 0x9B60, 0x5AE6, 0x9B62, 0x5AE9, 0x9B63, 0x5AFA, 0x9B65, 0x5AFB, 0x9B66, + 0x5B09, 0x8AF0, 0x5B0B, 0x9B68, 0x5B0C, 0x9B67, 0x5B16, 0x9B69, 0x5B22, 0x8FEC, 0x5B2A, 0x9B6C, 0x5B2C, 0x92DA, 0x5B30, 0x8964, + 0x5B32, 0x9B6A, 0x5B36, 0x9B6D, 0x5B3E, 0x9B6E, 0x5B40, 0x9B71, 0x5B43, 0x9B6F, 0x5B45, 0x9B70, 0x5B50, 0x8E71, 0x5B51, 0x9B72, + 0x5B54, 0x8D45, 0x5B55, 0x9B73, 0x5B56, 0xFAA6, 0x5B57, 0x8E9A, 0x5B58, 0x91B6, 0x5B5A, 0x9B74, 0x5B5B, 0x9B75, 0x5B5C, 0x8E79, + 0x5B5D, 0x8D46, 0x5B5F, 0x96D0, 0x5B63, 0x8B47, 0x5B64, 0x8CC7, 0x5B65, 0x9B76, 0x5B66, 0x8A77, 0x5B69, 0x9B77, 0x5B6B, 0x91B7, + 0x5B70, 0x9B78, 0x5B71, 0x9BA1, 0x5B73, 0x9B79, 0x5B75, 0x9B7A, 0x5B78, 0x9B7B, 0x5B7A, 0x9B7D, 0x5B80, 0x9B7E, 0x5B83, 0x9B80, + 0x5B85, 0x91EE, 0x5B87, 0x8946, 0x5B88, 0x8EE7, 0x5B89, 0x88C0, 0x5B8B, 0x9176, 0x5B8C, 0x8AAE, 0x5B8D, 0x8EB3, 0x5B8F, 0x8D47, + 0x5B95, 0x9386, 0x5B97, 0x8F40, 0x5B98, 0x8AAF, 0x5B99, 0x9288, 0x5B9A, 0x92E8, 0x5B9B, 0x88B6, 0x5B9C, 0x8B58, 0x5B9D, 0x95F3, + 0x5B9F, 0x8EC0, 0x5BA2, 0x8B71, 0x5BA3, 0x90E9, 0x5BA4, 0x8EBA, 0x5BA5, 0x9747, 0x5BA6, 0x9B81, 0x5BAE, 0x8B7B, 0x5BB0, 0x8DC9, + 0x5BB3, 0x8A51, 0x5BB4, 0x8983, 0x5BB5, 0x8FAA, 0x5BB6, 0x89C6, 0x5BB8, 0x9B82, 0x5BB9, 0x9765, 0x5BBF, 0x8F68, 0x5BC0, 0xFAA7, + 0x5BC2, 0x8EE2, 0x5BC3, 0x9B83, 0x5BC4, 0x8AF1, 0x5BC5, 0x93D0, 0x5BC6, 0x96A7, 0x5BC7, 0x9B84, 0x5BC9, 0x9B85, 0x5BCC, 0x9578, + 0x5BD0, 0x9B87, 0x5BD2, 0x8AA6, 0x5BD3, 0x8BF5, 0x5BD4, 0x9B86, 0x5BD8, 0xFAA9, 0x5BDB, 0x8AB0, 0x5BDD, 0x9051, 0x5BDE, 0x9B8B, + 0x5BDF, 0x8E40, 0x5BE1, 0x89C7, 0x5BE2, 0x9B8A, 0x5BE4, 0x9B88, 0x5BE5, 0x9B8C, 0x5BE6, 0x9B89, 0x5BE7, 0x944A, 0x5BE8, 0x9ECB, + 0x5BE9, 0x9052, 0x5BEB, 0x9B8D, 0x5BEC, 0xFAAA, 0x5BEE, 0x97BE, 0x5BF0, 0x9B8E, 0x5BF3, 0x9B90, 0x5BF5, 0x929E, 0x5BF6, 0x9B8F, + 0x5BF8, 0x90A1, 0x5BFA, 0x8E9B, 0x5BFE, 0x91CE, 0x5BFF, 0x8EF5, 0x5C01, 0x9595, 0x5C02, 0x90EA, 0x5C04, 0x8ECB, 0x5C05, 0x9B91, + 0x5C06, 0x8FAB, 0x5C07, 0x9B92, 0x5C08, 0x9B93, 0x5C09, 0x88D1, 0x5C0A, 0x91B8, 0x5C0B, 0x9071, 0x5C0D, 0x9B94, 0x5C0E, 0x93B1, + 0x5C0F, 0x8FAC, 0x5C11, 0x8FAD, 0x5C13, 0x9B95, 0x5C16, 0x90EB, 0x5C1A, 0x8FAE, 0x5C1E, 0xFAAB, 0x5C20, 0x9B96, 0x5C22, 0x9B97, + 0x5C24, 0x96DE, 0x5C28, 0x9B98, 0x5C2D, 0x8BC4, 0x5C31, 0x8F41, 0x5C38, 0x9B99, 0x5C39, 0x9B9A, 0x5C3A, 0x8EDA, 0x5C3B, 0x904B, + 0x5C3C, 0x93F2, 0x5C3D, 0x9073, 0x5C3E, 0x94F6, 0x5C3F, 0x9441, 0x5C40, 0x8BC7, 0x5C41, 0x9B9B, 0x5C45, 0x8B8F, 0x5C46, 0x9B9C, + 0x5C48, 0x8BFC, 0x5C4A, 0x93CD, 0x5C4B, 0x89AE, 0x5C4D, 0x8E72, 0x5C4E, 0x9B9D, 0x5C4F, 0x9BA0, 0x5C50, 0x9B9F, 0x5C51, 0x8BFB, + 0x5C53, 0x9B9E, 0x5C55, 0x9357, 0x5C5E, 0x91AE, 0x5C60, 0x936A, 0x5C61, 0x8EC6, 0x5C64, 0x9177, 0x5C65, 0x979A, 0x5C6C, 0x9BA2, + 0x5C6E, 0x9BA3, 0x5C6F, 0x93D4, 0x5C71, 0x8E52, 0x5C76, 0x9BA5, 0x5C79, 0x9BA6, 0x5C8C, 0x9BA7, 0x5C90, 0x8AF2, 0x5C91, 0x9BA8, + 0x5C94, 0x9BA9, 0x5CA1, 0x89AA, 0x5CA6, 0xFAAC, 0x5CA8, 0x915A, 0x5CA9, 0x8AE2, 0x5CAB, 0x9BAB, 0x5CAC, 0x96A6, 0x5CB1, 0x91D0, + 0x5CB3, 0x8A78, 0x5CB6, 0x9BAD, 0x5CB7, 0x9BAF, 0x5CB8, 0x8ADD, 0x5CBA, 0xFAAD, 0x5CBB, 0x9BAC, 0x5CBC, 0x9BAE, 0x5CBE, 0x9BB1, + 0x5CC5, 0x9BB0, 0x5CC7, 0x9BB2, 0x5CD9, 0x9BB3, 0x5CE0, 0x93BB, 0x5CE1, 0x8BAC, 0x5CE8, 0x89E3, 0x5CE9, 0x9BB4, 0x5CEA, 0x9BB9, + 0x5CED, 0x9BB7, 0x5CEF, 0x95F5, 0x5CF0, 0x95F4, 0x5CF5, 0xFAAE, 0x5CF6, 0x9387, 0x5CFA, 0x9BB6, 0x5CFB, 0x8F73, 0x5CFD, 0x9BB5, + 0x5D07, 0x9092, 0x5D0B, 0x9BBA, 0x5D0E, 0x8DE8, 0x5D11, 0x9BC0, 0x5D14, 0x9BC1, 0x5D15, 0x9BBB, 0x5D16, 0x8A52, 0x5D17, 0x9BBC, + 0x5D18, 0x9BC5, 0x5D19, 0x9BC4, 0x5D1A, 0x9BC3, 0x5D1B, 0x9BBF, 0x5D1F, 0x9BBE, 0x5D22, 0x9BC2, 0x5D27, 0xFAAF, 0x5D29, 0x95F6, + 0x5D42, 0xFAB2, 0x5D4B, 0x9BC9, 0x5D4C, 0x9BC6, 0x5D4E, 0x9BC8, 0x5D50, 0x9792, 0x5D52, 0x9BC7, 0x5D53, 0xFAB0, 0x5D5C, 0x9BBD, + 0x5D69, 0x9093, 0x5D6C, 0x9BCA, 0x5D6D, 0xFAB3, 0x5D6F, 0x8DB5, 0x5D73, 0x9BCB, 0x5D76, 0x9BCC, 0x5D82, 0x9BCF, 0x5D84, 0x9BCE, + 0x5D87, 0x9BCD, 0x5D8B, 0x9388, 0x5D8C, 0x9BB8, 0x5D90, 0x9BD5, 0x5D9D, 0x9BD1, 0x5DA2, 0x9BD0, 0x5DAC, 0x9BD2, 0x5DAE, 0x9BD3, + 0x5DB7, 0x9BD6, 0x5DB8, 0xFAB4, 0x5DB9, 0xFAB5, 0x5DBA, 0x97E4, 0x5DBC, 0x9BD7, 0x5DBD, 0x9BD4, 0x5DC9, 0x9BD8, 0x5DCC, 0x8ADE, + 0x5DCD, 0x9BD9, 0x5DD0, 0xFAB6, 0x5DD2, 0x9BDB, 0x5DD3, 0x9BDA, 0x5DD6, 0x9BDC, 0x5DDB, 0x9BDD, 0x5DDD, 0x90EC, 0x5DDE, 0x8F42, + 0x5DE1, 0x8F84, 0x5DE3, 0x9183, 0x5DE5, 0x8D48, 0x5DE6, 0x8DB6, 0x5DE7, 0x8D49, 0x5DE8, 0x8B90, 0x5DEB, 0x9BDE, 0x5DEE, 0x8DB7, + 0x5DF1, 0x8CC8, 0x5DF2, 0x9BDF, 0x5DF3, 0x96A4, 0x5DF4, 0x9462, 0x5DF5, 0x9BE0, 0x5DF7, 0x8D4A, 0x5DFB, 0x8AAA, 0x5DFD, 0x9246, + 0x5DFE, 0x8BD0, 0x5E02, 0x8E73, 0x5E03, 0x957A, 0x5E06, 0x94BF, 0x5E0B, 0x9BE1, 0x5E0C, 0x8AF3, 0x5E11, 0x9BE4, 0x5E16, 0x929F, + 0x5E19, 0x9BE3, 0x5E1A, 0x9BE2, 0x5E1B, 0x9BE5, 0x5E1D, 0x92E9, 0x5E25, 0x9083, 0x5E2B, 0x8E74, 0x5E2D, 0x90C8, 0x5E2F, 0x91D1, + 0x5E30, 0x8B41, 0x5E33, 0x92A0, 0x5E36, 0x9BE6, 0x5E37, 0x9BE7, 0x5E38, 0x8FED, 0x5E3D, 0x9658, 0x5E40, 0x9BEA, 0x5E43, 0x9BE9, + 0x5E44, 0x9BE8, 0x5E45, 0x959D, 0x5E47, 0x9BF1, 0x5E4C, 0x9679, 0x5E4E, 0x9BEB, 0x5E54, 0x9BED, 0x5E55, 0x968B, 0x5E57, 0x9BEC, + 0x5E5F, 0x9BEE, 0x5E61, 0x94A6, 0x5E62, 0x9BEF, 0x5E63, 0x95BC, 0x5E64, 0x9BF0, 0x5E72, 0x8AB1, 0x5E73, 0x95BD, 0x5E74, 0x944E, + 0x5E75, 0x9BF2, 0x5E76, 0x9BF3, 0x5E78, 0x8D4B, 0x5E79, 0x8AB2, 0x5E7A, 0x9BF4, 0x5E7B, 0x8CB6, 0x5E7C, 0x9763, 0x5E7D, 0x9748, + 0x5E7E, 0x8AF4, 0x5E7F, 0x9BF6, 0x5E81, 0x92A1, 0x5E83, 0x8D4C, 0x5E84, 0x8FAF, 0x5E87, 0x94DD, 0x5E8A, 0x8FB0, 0x5E8F, 0x8F98, + 0x5E95, 0x92EA, 0x5E96, 0x95F7, 0x5E97, 0x9358, 0x5E9A, 0x8D4D, 0x5E9C, 0x957B, 0x5EA0, 0x9BF7, 0x5EA6, 0x9378, 0x5EA7, 0x8DC0, + 0x5EAB, 0x8CC9, 0x5EAD, 0x92EB, 0x5EB5, 0x88C1, 0x5EB6, 0x8F8E, 0x5EB7, 0x8D4E, 0x5EB8, 0x9766, 0x5EC1, 0x9BF8, 0x5EC2, 0x9BF9, + 0x5EC3, 0x9470, 0x5EC8, 0x9BFA, 0x5EC9, 0x97F5, 0x5ECA, 0x984C, 0x5ECF, 0x9BFC, 0x5ED0, 0x9BFB, 0x5ED3, 0x8A66, 0x5ED6, 0x9C40, + 0x5EDA, 0x9C43, 0x5EDB, 0x9C44, 0x5EDD, 0x9C42, 0x5EDF, 0x955F, 0x5EE0, 0x8FB1, 0x5EE1, 0x9C46, 0x5EE2, 0x9C45, 0x5EE3, 0x9C41, + 0x5EE8, 0x9C47, 0x5EE9, 0x9C48, 0x5EEC, 0x9C49, 0x5EF0, 0x9C4C, 0x5EF1, 0x9C4A, 0x5EF3, 0x9C4B, 0x5EF4, 0x9C4D, 0x5EF6, 0x8984, + 0x5EF7, 0x92EC, 0x5EF8, 0x9C4E, 0x5EFA, 0x8C9A, 0x5EFB, 0x89F4, 0x5EFC, 0x9455, 0x5EFE, 0x9C4F, 0x5EFF, 0x93F9, 0x5F01, 0x95D9, + 0x5F03, 0x9C50, 0x5F04, 0x984D, 0x5F09, 0x9C51, 0x5F0A, 0x95BE, 0x5F0B, 0x9C54, 0x5F0C, 0x989F, 0x5F0D, 0x98AF, 0x5F0F, 0x8EAE, + 0x5F10, 0x93F3, 0x5F11, 0x9C55, 0x5F13, 0x8B7C, 0x5F14, 0x92A2, 0x5F15, 0x88F8, 0x5F16, 0x9C56, 0x5F17, 0x95A4, 0x5F18, 0x8D4F, + 0x5F1B, 0x926F, 0x5F1F, 0x92ED, 0x5F21, 0xFAB7, 0x5F25, 0x96ED, 0x5F26, 0x8CB7, 0x5F27, 0x8CCA, 0x5F29, 0x9C57, 0x5F2D, 0x9C58, + 0x5F2F, 0x9C5E, 0x5F31, 0x8EE3, 0x5F34, 0xFAB8, 0x5F35, 0x92A3, 0x5F37, 0x8BAD, 0x5F38, 0x9C59, 0x5F3C, 0x954A, 0x5F3E, 0x9265, + 0x5F41, 0x9C5A, 0x5F45, 0xFA67, 0x5F48, 0x9C5B, 0x5F4A, 0x8BAE, 0x5F4C, 0x9C5C, 0x5F4E, 0x9C5D, 0x5F51, 0x9C5F, 0x5F53, 0x9396, + 0x5F56, 0x9C60, 0x5F57, 0x9C61, 0x5F59, 0x9C62, 0x5F5C, 0x9C53, 0x5F5D, 0x9C52, 0x5F61, 0x9C63, 0x5F62, 0x8C60, 0x5F66, 0x9546, + 0x5F67, 0xFAB9, 0x5F69, 0x8DCA, 0x5F6A, 0x9556, 0x5F6B, 0x92A4, 0x5F6C, 0x956A, 0x5F6D, 0x9C64, 0x5F70, 0x8FB2, 0x5F71, 0x8965, + 0x5F73, 0x9C65, 0x5F77, 0x9C66, 0x5F79, 0x96F0, 0x5F7C, 0x94DE, 0x5F7F, 0x9C69, 0x5F80, 0x899D, 0x5F81, 0x90AA, 0x5F82, 0x9C68, + 0x5F83, 0x9C67, 0x5F84, 0x8C61, 0x5F85, 0x91D2, 0x5F87, 0x9C6D, 0x5F88, 0x9C6B, 0x5F8A, 0x9C6A, 0x5F8B, 0x97A5, 0x5F8C, 0x8CE3, + 0x5F90, 0x8F99, 0x5F91, 0x9C6C, 0x5F92, 0x936B, 0x5F93, 0x8F5D, 0x5F97, 0x93BE, 0x5F98, 0x9C70, 0x5F99, 0x9C6F, 0x5F9E, 0x9C6E, + 0x5FA0, 0x9C71, 0x5FA1, 0x8CE4, 0x5FA8, 0x9C72, 0x5FA9, 0x959C, 0x5FAA, 0x8F7A, 0x5FAD, 0x9C73, 0x5FAE, 0x94F7, 0x5FB3, 0x93BF, + 0x5FB4, 0x92A5, 0x5FB7, 0xFABA, 0x5FB9, 0x934F, 0x5FBC, 0x9C74, 0x5FBD, 0x8B4A, 0x5FC3, 0x9053, 0x5FC5, 0x954B, 0x5FCC, 0x8AF5, + 0x5FCD, 0x9445, 0x5FD6, 0x9C75, 0x5FD7, 0x8E75, 0x5FD8, 0x9659, 0x5FD9, 0x965A, 0x5FDC, 0x899E, 0x5FDD, 0x9C7A, 0x5FDE, 0xFABB, + 0x5FE0, 0x9289, 0x5FE4, 0x9C77, 0x5FEB, 0x89F5, 0x5FF0, 0x9CAB, 0x5FF1, 0x9C79, 0x5FF5, 0x944F, 0x5FF8, 0x9C78, 0x5FFB, 0x9C76, + 0x5FFD, 0x8D9A, 0x5FFF, 0x9C7C, 0x600E, 0x9C83, 0x600F, 0x9C89, 0x6010, 0x9C81, 0x6012, 0x937B, 0x6015, 0x9C86, 0x6016, 0x957C, + 0x6019, 0x9C80, 0x601B, 0x9C85, 0x601C, 0x97E5, 0x601D, 0x8E76, 0x6020, 0x91D3, 0x6021, 0x9C7D, 0x6025, 0x8B7D, 0x6026, 0x9C88, + 0x6027, 0x90AB, 0x6028, 0x8985, 0x6029, 0x9C82, 0x602A, 0x89F6, 0x602B, 0x9C87, 0x602F, 0x8BAF, 0x6031, 0x9C84, 0x603A, 0x9C8A, + 0x6041, 0x9C8C, 0x6042, 0x9C96, 0x6043, 0x9C94, 0x6046, 0x9C91, 0x604A, 0x9C90, 0x604B, 0x97F6, 0x604D, 0x9C92, 0x6050, 0x8BB0, + 0x6052, 0x8D50, 0x6055, 0x8F9A, 0x6059, 0x9C99, 0x605A, 0x9C8B, 0x605D, 0xFABC, 0x605F, 0x9C8F, 0x6060, 0x9C7E, 0x6062, 0x89F8, + 0x6063, 0x9C93, 0x6064, 0x9C95, 0x6065, 0x9270, 0x6068, 0x8DA6, 0x6069, 0x89B6, 0x606A, 0x9C8D, 0x606B, 0x9C98, 0x606C, 0x9C97, + 0x606D, 0x8BB1, 0x606F, 0x91A7, 0x6070, 0x8A86, 0x6075, 0x8C62, 0x6077, 0x9C8E, 0x6081, 0x9C9A, 0x6083, 0x9C9D, 0x6084, 0x9C9F, + 0x6085, 0xFABD, 0x6089, 0x8EBB, 0x608A, 0xFABE, 0x608B, 0x9CA5, 0x608C, 0x92EE, 0x608D, 0x9C9B, 0x6092, 0x9CA3, 0x6094, 0x89F7, + 0x6096, 0x9CA1, 0x6097, 0x9CA2, 0x609A, 0x9C9E, 0x609B, 0x9CA0, 0x609F, 0x8CE5, 0x60A0, 0x9749, 0x60A3, 0x8AB3, 0x60A6, 0x8978, + 0x60A7, 0x9CA4, 0x60A9, 0x9459, 0x60AA, 0x88AB, 0x60B2, 0x94DF, 0x60B3, 0x9C7B, 0x60B4, 0x9CAA, 0x60B5, 0x9CAE, 0x60B6, 0x96E3, + 0x60B8, 0x9CA7, 0x60BC, 0x9389, 0x60BD, 0x9CAC, 0x60C5, 0x8FEE, 0x60C6, 0x9CAD, 0x60C7, 0x93D5, 0x60D1, 0x9866, 0x60D3, 0x9CA9, + 0x60D5, 0xFAC0, 0x60D8, 0x9CAF, 0x60DA, 0x8D9B, 0x60DC, 0x90C9, 0x60DE, 0xFABF, 0x60DF, 0x88D2, 0x60E0, 0x9CA8, 0x60E1, 0x9CA6, + 0x60E3, 0x9179, 0x60E7, 0x9C9C, 0x60E8, 0x8E53, 0x60F0, 0x91C4, 0x60F1, 0x9CBB, 0x60F2, 0xFAC2, 0x60F3, 0x917A, 0x60F4, 0x9CB6, + 0x60F6, 0x9CB3, 0x60F7, 0x9CB4, 0x60F9, 0x8EE4, 0x60FA, 0x9CB7, 0x60FB, 0x9CBA, 0x6100, 0x9CB5, 0x6101, 0x8F44, 0x6103, 0x9CB8, + 0x6106, 0x9CB2, 0x6108, 0x96FA, 0x6109, 0x96F9, 0x610D, 0x9CBC, 0x610E, 0x9CBD, 0x610F, 0x88D3, 0x6111, 0xFAC3, 0x6115, 0x9CB1, + 0x611A, 0x8BF0, 0x611B, 0x88A4, 0x611F, 0x8AB4, 0x6120, 0xFAC1, 0x6121, 0x9CB9, 0x6127, 0x9CC1, 0x6128, 0x9CC0, 0x612C, 0x9CC5, + 0x6130, 0xFAC5, 0x6134, 0x9CC6, 0x6137, 0xFAC4, 0x613C, 0x9CC4, 0x613D, 0x9CC7, 0x613E, 0x9CBF, 0x613F, 0x9CC3, 0x6142, 0x9CC8, + 0x6144, 0x9CC9, 0x6147, 0x9CBE, 0x6148, 0x8E9C, 0x614A, 0x9CC2, 0x614B, 0x91D4, 0x614C, 0x8D51, 0x614D, 0x9CB0, 0x614E, 0x9054, + 0x6153, 0x9CD6, 0x6155, 0x95E7, 0x6158, 0x9CCC, 0x6159, 0x9CCD, 0x615A, 0x9CCE, 0x615D, 0x9CD5, 0x615F, 0x9CD4, 0x6162, 0x969D, + 0x6163, 0x8AB5, 0x6165, 0x9CD2, 0x6167, 0x8C64, 0x6168, 0x8A53, 0x616B, 0x9CCF, 0x616E, 0x97B6, 0x616F, 0x9CD1, 0x6170, 0x88D4, + 0x6171, 0x9CD3, 0x6173, 0x9CCA, 0x6174, 0x9CD0, 0x6175, 0x9CD7, 0x6176, 0x8C63, 0x6177, 0x9CCB, 0x617E, 0x977C, 0x6182, 0x974A, + 0x6187, 0x9CDA, 0x618A, 0x9CDE, 0x618E, 0x919E, 0x6190, 0x97F7, 0x6191, 0x9CDF, 0x6194, 0x9CDC, 0x6196, 0x9CD9, 0x6198, 0xFAC6, + 0x6199, 0x9CD8, 0x619A, 0x9CDD, 0x61A4, 0x95AE, 0x61A7, 0x93B2, 0x61A9, 0x8C65, 0x61AB, 0x9CE0, 0x61AC, 0x9CDB, 0x61AE, 0x9CE1, + 0x61B2, 0x8C9B, 0x61B6, 0x89AF, 0x61BA, 0x9CE9, 0x61BE, 0x8AB6, 0x61C3, 0x9CE7, 0x61C6, 0x9CE8, 0x61C7, 0x8DA7, 0x61C8, 0x9CE6, + 0x61C9, 0x9CE4, 0x61CA, 0x9CE3, 0x61CB, 0x9CEA, 0x61CC, 0x9CE2, 0x61CD, 0x9CEC, 0x61D0, 0x89F9, 0x61E3, 0x9CEE, 0x61E6, 0x9CED, + 0x61F2, 0x92A6, 0x61F4, 0x9CF1, 0x61F6, 0x9CEF, 0x61F7, 0x9CE5, 0x61F8, 0x8C9C, 0x61FA, 0x9CF0, 0x61FC, 0x9CF4, 0x61FD, 0x9CF3, + 0x61FE, 0x9CF5, 0x61FF, 0x9CF2, 0x6200, 0x9CF6, 0x6208, 0x9CF7, 0x6209, 0x9CF8, 0x620A, 0x95E8, 0x620C, 0x9CFA, 0x620D, 0x9CF9, + 0x620E, 0x8F5E, 0x6210, 0x90AC, 0x6211, 0x89E4, 0x6212, 0x89FA, 0x6213, 0xFAC7, 0x6214, 0x9CFB, 0x6216, 0x88BD, 0x621A, 0x90CA, + 0x621B, 0x9CFC, 0x621D, 0xE6C1, 0x621E, 0x9D40, 0x621F, 0x8C81, 0x6221, 0x9D41, 0x6226, 0x90ED, 0x622A, 0x9D42, 0x622E, 0x9D43, + 0x622F, 0x8B59, 0x6230, 0x9D44, 0x6232, 0x9D45, 0x6233, 0x9D46, 0x6234, 0x91D5, 0x6238, 0x8CCB, 0x623B, 0x96DF, 0x623F, 0x965B, + 0x6240, 0x8F8A, 0x6241, 0x9D47, 0x6247, 0x90EE, 0x6248, 0xE7BB, 0x6249, 0x94E0, 0x624B, 0x8EE8, 0x624D, 0x8DCB, 0x624E, 0x9D48, + 0x6253, 0x91C5, 0x6255, 0x95A5, 0x6258, 0x91EF, 0x625B, 0x9D4B, 0x625E, 0x9D49, 0x6260, 0x9D4C, 0x6263, 0x9D4A, 0x6268, 0x9D4D, + 0x626E, 0x95AF, 0x6271, 0x88B5, 0x6276, 0x957D, 0x6279, 0x94E1, 0x627C, 0x9D4E, 0x627E, 0x9D51, 0x627F, 0x8FB3, 0x6280, 0x8B5A, + 0x6282, 0x9D4F, 0x6283, 0x9D56, 0x6284, 0x8FB4, 0x6289, 0x9D50, 0x628A, 0x9463, 0x6291, 0x977D, 0x6292, 0x9D52, 0x6293, 0x9D53, + 0x6294, 0x9D57, 0x6295, 0x938A, 0x6296, 0x9D54, 0x6297, 0x8D52, 0x6298, 0x90DC, 0x629B, 0x9D65, 0x629C, 0x94B2, 0x629E, 0x91F0, + 0x62A6, 0xFAC8, 0x62AB, 0x94E2, 0x62AC, 0x9DAB, 0x62B1, 0x95F8, 0x62B5, 0x92EF, 0x62B9, 0x9695, 0x62BB, 0x9D5A, 0x62BC, 0x899F, + 0x62BD, 0x928A, 0x62C2, 0x9D63, 0x62C5, 0x9253, 0x62C6, 0x9D5D, 0x62C7, 0x9D64, 0x62C8, 0x9D5F, 0x62C9, 0x9D66, 0x62CA, 0x9D62, + 0x62CC, 0x9D61, 0x62CD, 0x948F, 0x62CF, 0x9D5B, 0x62D0, 0x89FB, 0x62D1, 0x9D59, 0x62D2, 0x8B91, 0x62D3, 0x91F1, 0x62D4, 0x9D55, + 0x62D7, 0x9D58, 0x62D8, 0x8D53, 0x62D9, 0x90D9, 0x62DB, 0x8FB5, 0x62DC, 0x9D60, 0x62DD, 0x9471, 0x62E0, 0x8B92, 0x62E1, 0x8A67, + 0x62EC, 0x8A87, 0x62ED, 0x9040, 0x62EE, 0x9D68, 0x62EF, 0x9D6D, 0x62F1, 0x9D69, 0x62F3, 0x8C9D, 0x62F5, 0x9D6E, 0x62F6, 0x8E41, + 0x62F7, 0x8D89, 0x62FE, 0x8F45, 0x62FF, 0x9D5C, 0x6301, 0x8E9D, 0x6302, 0x9D6B, 0x6307, 0x8E77, 0x6308, 0x9D6C, 0x6309, 0x88C2, + 0x630C, 0x9D67, 0x6311, 0x92A7, 0x6319, 0x8B93, 0x631F, 0x8BB2, 0x6327, 0x9D6A, 0x6328, 0x88A5, 0x632B, 0x8DC1, 0x632F, 0x9055, + 0x633A, 0x92F0, 0x633D, 0x94D2, 0x633E, 0x9D70, 0x633F, 0x917D, 0x6349, 0x91A8, 0x634C, 0x8E4A, 0x634D, 0x9D71, 0x634F, 0x9D73, + 0x6350, 0x9D6F, 0x6355, 0x95DF, 0x6357, 0x92BB, 0x635C, 0x917B, 0x6367, 0x95F9, 0x6368, 0x8ECC, 0x6369, 0x9D80, 0x636B, 0x9D7E, + 0x636E, 0x9098, 0x6372, 0x8C9E, 0x6376, 0x9D78, 0x6377, 0x8FB7, 0x637A, 0x93E6, 0x637B, 0x9450, 0x6380, 0x9D76, 0x6383, 0x917C, + 0x6388, 0x8EF6, 0x6389, 0x9D7B, 0x638C, 0x8FB6, 0x638E, 0x9D75, 0x638F, 0x9D7A, 0x6392, 0x9472, 0x6396, 0x9D74, 0x6398, 0x8C40, + 0x639B, 0x8A7C, 0x639F, 0x9D7C, 0x63A0, 0x97A9, 0x63A1, 0x8DCC, 0x63A2, 0x9254, 0x63A3, 0x9D79, 0x63A5, 0x90DA, 0x63A7, 0x8D54, + 0x63A8, 0x9084, 0x63A9, 0x8986, 0x63AA, 0x915B, 0x63AB, 0x9D77, 0x63AC, 0x8B64, 0x63B2, 0x8C66, 0x63B4, 0x92CD, 0x63B5, 0x9D7D, + 0x63BB, 0x917E, 0x63BE, 0x9D81, 0x63C0, 0x9D83, 0x63C3, 0x91B5, 0x63C4, 0x9D89, 0x63C6, 0x9D84, 0x63C9, 0x9D86, 0x63CF, 0x9560, + 0x63D0, 0x92F1, 0x63D2, 0x9D87, 0x63D6, 0x974B, 0x63DA, 0x9767, 0x63DB, 0x8AB7, 0x63E1, 0x88AC, 0x63E3, 0x9D85, 0x63E9, 0x9D82, + 0x63EE, 0x8AF6, 0x63F4, 0x8987, 0x63F5, 0xFAC9, 0x63F6, 0x9D88, 0x63FA, 0x9768, 0x6406, 0x9D8C, 0x640D, 0x91B9, 0x640F, 0x9D93, + 0x6413, 0x9D8D, 0x6416, 0x9D8A, 0x6417, 0x9D91, 0x641C, 0x9D72, 0x6426, 0x9D8E, 0x6428, 0x9D92, 0x642C, 0x94C0, 0x642D, 0x938B, + 0x6434, 0x9D8B, 0x6436, 0x9D8F, 0x643A, 0x8C67, 0x643E, 0x8DEF, 0x6442, 0x90DB, 0x644E, 0x9D97, 0x6458, 0x9345, 0x6460, 0xFACA, + 0x6467, 0x9D94, 0x6469, 0x9680, 0x646F, 0x9D95, 0x6476, 0x9D96, 0x6478, 0x96CC, 0x647A, 0x90A0, 0x6483, 0x8C82, 0x6488, 0x9D9D, + 0x6492, 0x8E54, 0x6493, 0x9D9A, 0x6495, 0x9D99, 0x649A, 0x9451, 0x649D, 0xFACB, 0x649E, 0x93B3, 0x64A4, 0x9350, 0x64A5, 0x9D9B, + 0x64A9, 0x9D9C, 0x64AB, 0x958F, 0x64AD, 0x9464, 0x64AE, 0x8E42, 0x64B0, 0x90EF, 0x64B2, 0x966F, 0x64B9, 0x8A68, 0x64BB, 0x9DA3, + 0x64BC, 0x9D9E, 0x64C1, 0x9769, 0x64C2, 0x9DA5, 0x64C5, 0x9DA1, 0x64C7, 0x9DA2, 0x64CD, 0x9180, 0x64CE, 0xFACC, 0x64D2, 0x9DA0, + 0x64D4, 0x9D5E, 0x64D8, 0x9DA4, 0x64DA, 0x9D9F, 0x64E0, 0x9DA9, 0x64E1, 0x9DAA, 0x64E2, 0x9346, 0x64E3, 0x9DAC, 0x64E6, 0x8E43, + 0x64E7, 0x9DA7, 0x64EC, 0x8B5B, 0x64EF, 0x9DAD, 0x64F1, 0x9DA6, 0x64F2, 0x9DB1, 0x64F4, 0x9DB0, 0x64F6, 0x9DAF, 0x64FA, 0x9DB2, + 0x64FD, 0x9DB4, 0x64FE, 0x8FEF, 0x6500, 0x9DB3, 0x6505, 0x9DB7, 0x6518, 0x9DB5, 0x651C, 0x9DB6, 0x651D, 0x9D90, 0x6523, 0x9DB9, + 0x6524, 0x9DB8, 0x652A, 0x9D98, 0x652B, 0x9DBA, 0x652C, 0x9DAE, 0x652F, 0x8E78, 0x6534, 0x9DBB, 0x6535, 0x9DBC, 0x6536, 0x9DBE, + 0x6537, 0x9DBD, 0x6538, 0x9DBF, 0x6539, 0x89FC, 0x653B, 0x8D55, 0x653E, 0x95FA, 0x653F, 0x90AD, 0x6545, 0x8CCC, 0x6548, 0x9DC1, + 0x654D, 0x9DC4, 0x654E, 0xFACD, 0x654F, 0x9571, 0x6551, 0x8B7E, 0x6555, 0x9DC3, 0x6556, 0x9DC2, 0x6557, 0x9473, 0x6558, 0x9DC5, + 0x6559, 0x8BB3, 0x655D, 0x9DC7, 0x655E, 0x9DC6, 0x6562, 0x8AB8, 0x6563, 0x8E55, 0x6566, 0x93D6, 0x656C, 0x8C68, 0x6570, 0x9094, + 0x6572, 0x9DC8, 0x6574, 0x90AE, 0x6575, 0x9347, 0x6577, 0x957E, 0x6578, 0x9DC9, 0x6582, 0x9DCA, 0x6583, 0x9DCB, 0x6587, 0x95B6, + 0x6588, 0x9B7C, 0x6589, 0x90C4, 0x658C, 0x956B, 0x658E, 0x8DD6, 0x6590, 0x94E3, 0x6591, 0x94C1, 0x6597, 0x936C, 0x6599, 0x97BF, + 0x659B, 0x9DCD, 0x659C, 0x8ECE, 0x659F, 0x9DCE, 0x65A1, 0x88B4, 0x65A4, 0x8BD2, 0x65A5, 0x90CB, 0x65A7, 0x9580, 0x65AB, 0x9DCF, + 0x65AC, 0x8E61, 0x65AD, 0x9266, 0x65AF, 0x8E7A, 0x65B0, 0x9056, 0x65B7, 0x9DD0, 0x65B9, 0x95FB, 0x65BC, 0x8997, 0x65BD, 0x8E7B, + 0x65C1, 0x9DD3, 0x65C3, 0x9DD1, 0x65C4, 0x9DD4, 0x65C5, 0x97B7, 0x65C6, 0x9DD2, 0x65CB, 0x90F9, 0x65CC, 0x9DD5, 0x65CF, 0x91B0, + 0x65D2, 0x9DD6, 0x65D7, 0x8AF8, 0x65D9, 0x9DD8, 0x65DB, 0x9DD7, 0x65E0, 0x9DD9, 0x65E1, 0x9DDA, 0x65E2, 0x8AF9, 0x65E5, 0x93FA, + 0x65E6, 0x9255, 0x65E7, 0x8B8C, 0x65E8, 0x8E7C, 0x65E9, 0x9181, 0x65EC, 0x8F7B, 0x65ED, 0x88AE, 0x65F1, 0x9DDB, 0x65FA, 0x89A0, + 0x65FB, 0x9DDF, 0x6600, 0xFACE, 0x6602, 0x8D56, 0x6603, 0x9DDE, 0x6606, 0x8DA9, 0x6607, 0x8FB8, 0x6609, 0xFAD1, 0x660A, 0x9DDD, + 0x660C, 0x8FB9, 0x660E, 0x96BE, 0x660F, 0x8DA8, 0x6613, 0x88D5, 0x6614, 0x90CC, 0x6615, 0xFACF, 0x661C, 0x9DE4, 0x661E, 0xFAD3, + 0x661F, 0x90AF, 0x6620, 0x8966, 0x6624, 0xFAD4, 0x6625, 0x8F74, 0x6627, 0x9686, 0x6628, 0x8DF0, 0x662D, 0x8FBA, 0x662E, 0xFAD2, + 0x662F, 0x90A5, 0x6631, 0xFA63, 0x6634, 0x9DE3, 0x6635, 0x9DE1, 0x6636, 0x9DE2, 0x663B, 0xFAD0, 0x663C, 0x928B, 0x663F, 0x9E45, + 0x6641, 0x9DE8, 0x6642, 0x8E9E, 0x6643, 0x8D57, 0x6644, 0x9DE6, 0x6649, 0x9DE7, 0x664B, 0x9057, 0x664F, 0x9DE5, 0x6652, 0x8E4E, + 0x6657, 0xFAD6, 0x6659, 0xFAD7, 0x665D, 0x9DEA, 0x665E, 0x9DE9, 0x665F, 0x9DEE, 0x6662, 0x9DEF, 0x6664, 0x9DEB, 0x6665, 0xFAD5, + 0x6666, 0x8A41, 0x6667, 0x9DEC, 0x6668, 0x9DED, 0x6669, 0x94D3, 0x666E, 0x9581, 0x666F, 0x8C69, 0x6670, 0x9DF0, 0x6673, 0xFAD9, + 0x6674, 0x90B0, 0x6676, 0x8FBB, 0x667A, 0x9271, 0x6681, 0x8BC5, 0x6683, 0x9DF1, 0x6684, 0x9DF5, 0x6687, 0x89C9, 0x6688, 0x9DF2, + 0x6689, 0x9DF4, 0x668E, 0x9DF3, 0x6691, 0x8F8B, 0x6696, 0x9267, 0x6697, 0x88C3, 0x6698, 0x9DF6, 0x6699, 0xFADA, 0x669D, 0x9DF7, + 0x66A0, 0xFADB, 0x66A2, 0x92A8, 0x66A6, 0x97EF, 0x66AB, 0x8E62, 0x66AE, 0x95E9, 0x66B2, 0xFADC, 0x66B4, 0x965C, 0x66B8, 0x9E41, + 0x66B9, 0x9DF9, 0x66BC, 0x9DFC, 0x66BE, 0x9DFB, 0x66BF, 0xFADD, 0x66C1, 0x9DF8, 0x66C4, 0x9E40, 0x66C7, 0x93DC, 0x66C9, 0x9DFA, + 0x66D6, 0x9E42, 0x66D9, 0x8F8C, 0x66DA, 0x9E43, 0x66DC, 0x976A, 0x66DD, 0x9498, 0x66E0, 0x9E44, 0x66E6, 0x9E46, 0x66E9, 0x9E47, + 0x66F0, 0x9E48, 0x66F2, 0x8BC8, 0x66F3, 0x8967, 0x66F4, 0x8D58, 0x66F5, 0x9E49, 0x66F7, 0x9E4A, 0x66F8, 0x8F91, 0x66F9, 0x9182, + 0x66FA, 0xFADE, 0x66FB, 0xFA66, 0x66FC, 0x99D6, 0x66FD, 0x915D, 0x66FE, 0x915C, 0x66FF, 0x91D6, 0x6700, 0x8DC5, 0x6703, 0x98F0, + 0x6708, 0x8C8E, 0x6709, 0x974C, 0x670B, 0x95FC, 0x670D, 0x959E, 0x670E, 0xFADF, 0x670F, 0x9E4B, 0x6714, 0x8DF1, 0x6715, 0x92BD, + 0x6716, 0x9E4C, 0x6717, 0x984E, 0x671B, 0x965D, 0x671D, 0x92A9, 0x671E, 0x9E4D, 0x671F, 0x8AFA, 0x6726, 0x9E4E, 0x6727, 0x9E4F, + 0x6728, 0x96D8, 0x672A, 0x96A2, 0x672B, 0x9696, 0x672C, 0x967B, 0x672D, 0x8E44, 0x672E, 0x9E51, 0x6731, 0x8EE9, 0x6734, 0x9670, + 0x6736, 0x9E53, 0x6737, 0x9E56, 0x6738, 0x9E55, 0x673A, 0x8AF7, 0x673D, 0x8B80, 0x673F, 0x9E52, 0x6741, 0x9E54, 0x6746, 0x9E57, + 0x6749, 0x9099, 0x674E, 0x979B, 0x674F, 0x88C7, 0x6750, 0x8DDE, 0x6751, 0x91BA, 0x6753, 0x8EDB, 0x6756, 0x8FF1, 0x6759, 0x9E5A, + 0x675C, 0x936D, 0x675E, 0x9E58, 0x675F, 0x91A9, 0x6760, 0x9E59, 0x6761, 0x8FF0, 0x6762, 0x96DB, 0x6763, 0x9E5B, 0x6764, 0x9E5C, + 0x6765, 0x9788, 0x6766, 0xFAE1, 0x676A, 0x9E61, 0x676D, 0x8D59, 0x676F, 0x9474, 0x6770, 0x9E5E, 0x6771, 0x938C, 0x6772, 0x9DDC, + 0x6773, 0x9DE0, 0x6775, 0x8B6E, 0x6777, 0x9466, 0x677C, 0x9E60, 0x677E, 0x8FBC, 0x677F, 0x94C2, 0x6785, 0x9E66, 0x6787, 0x94F8, + 0x6789, 0x9E5D, 0x678B, 0x9E63, 0x678C, 0x9E62, 0x6790, 0x90CD, 0x6795, 0x968D, 0x6797, 0x97D1, 0x679A, 0x9687, 0x679C, 0x89CA, + 0x679D, 0x8E7D, 0x67A0, 0x9867, 0x67A1, 0x9E65, 0x67A2, 0x9095, 0x67A6, 0x9E64, 0x67A9, 0x9E5F, 0x67AF, 0x8CCD, 0x67B3, 0x9E6B, + 0x67B4, 0x9E69, 0x67B6, 0x89CB, 0x67B7, 0x9E67, 0x67B8, 0x9E6D, 0x67B9, 0x9E73, 0x67BB, 0xFAE2, 0x67C0, 0xFAE4, 0x67C1, 0x91C6, + 0x67C4, 0x95BF, 0x67C6, 0x9E75, 0x67CA, 0x9541, 0x67CE, 0x9E74, 0x67CF, 0x9490, 0x67D0, 0x965E, 0x67D1, 0x8AB9, 0x67D3, 0x90F5, + 0x67D4, 0x8F5F, 0x67D8, 0x92D1, 0x67DA, 0x974D, 0x67DD, 0x9E70, 0x67DE, 0x9E6F, 0x67E2, 0x9E71, 0x67E4, 0x9E6E, 0x67E7, 0x9E76, + 0x67E9, 0x9E6C, 0x67EC, 0x9E6A, 0x67EE, 0x9E72, 0x67EF, 0x9E68, 0x67F1, 0x928C, 0x67F3, 0x96F6, 0x67F4, 0x8EC4, 0x67F5, 0x8DF2, + 0x67FB, 0x8DB8, 0x67FE, 0x968F, 0x67FF, 0x8A60, 0x6801, 0xFAE5, 0x6802, 0x92CC, 0x6803, 0x93C8, 0x6804, 0x8968, 0x6813, 0x90F0, + 0x6816, 0x90B2, 0x6817, 0x8C49, 0x681E, 0x9E78, 0x6821, 0x8D5A, 0x6822, 0x8A9C, 0x6829, 0x9E7A, 0x682A, 0x8A94, 0x682B, 0x9E81, + 0x6832, 0x9E7D, 0x6834, 0x90F1, 0x6838, 0x8A6A, 0x6839, 0x8DAA, 0x683C, 0x8A69, 0x683D, 0x8DCD, 0x6840, 0x9E7B, 0x6841, 0x8C85, + 0x6842, 0x8C6A, 0x6843, 0x938D, 0x6844, 0xFAE6, 0x6846, 0x9E79, 0x6848, 0x88C4, 0x684D, 0x9E7C, 0x684E, 0x9E7E, 0x6850, 0x8BCB, + 0x6851, 0x8C4B, 0x6852, 0xFAE3, 0x6853, 0x8ABA, 0x6854, 0x8B6A, 0x6859, 0x9E82, 0x685C, 0x8DF7, 0x685D, 0x9691, 0x685F, 0x8E56, + 0x6863, 0x9E83, 0x6867, 0x954F, 0x6874, 0x9E8F, 0x6876, 0x89B1, 0x6877, 0x9E84, 0x687E, 0x9E95, 0x687F, 0x9E85, 0x6881, 0x97C0, + 0x6883, 0x9E8C, 0x6885, 0x947E, 0x688D, 0x9E94, 0x688F, 0x9E87, 0x6893, 0x88B2, 0x6894, 0x9E89, 0x6897, 0x8D5B, 0x689B, 0x9E8B, + 0x689D, 0x9E8A, 0x689F, 0x9E86, 0x68A0, 0x9E91, 0x68A2, 0x8FBD, 0x68A6, 0x9AEB, 0x68A7, 0x8CE6, 0x68A8, 0x979C, 0x68AD, 0x9E88, + 0x68AF, 0x92F2, 0x68B0, 0x8A42, 0x68B1, 0x8DAB, 0x68B3, 0x9E80, 0x68B5, 0x9E90, 0x68B6, 0x8A81, 0x68B9, 0x9E8E, 0x68BA, 0x9E92, + 0x68BC, 0x938E, 0x68C4, 0x8AFC, 0x68C6, 0x9EB0, 0x68C8, 0xFA64, 0x68C9, 0x96C7, 0x68CA, 0x9E97, 0x68CB, 0x8AFB, 0x68CD, 0x9E9E, + 0x68CF, 0xFAE7, 0x68D2, 0x965F, 0x68D4, 0x9E9F, 0x68D5, 0x9EA1, 0x68D7, 0x9EA5, 0x68D8, 0x9E99, 0x68DA, 0x9249, 0x68DF, 0x938F, + 0x68E0, 0x9EA9, 0x68E1, 0x9E9C, 0x68E3, 0x9EA6, 0x68E7, 0x9EA0, 0x68EE, 0x9058, 0x68EF, 0x9EAA, 0x68F2, 0x90B1, 0x68F9, 0x9EA8, + 0x68FA, 0x8ABB, 0x6900, 0x986F, 0x6901, 0x9E96, 0x6904, 0x9EA4, 0x6905, 0x88D6, 0x6908, 0x9E98, 0x690B, 0x96B8, 0x690C, 0x9E9D, + 0x690D, 0x9041, 0x690E, 0x92C5, 0x690F, 0x9E93, 0x6912, 0x9EA3, 0x6919, 0x909A, 0x691A, 0x9EAD, 0x691B, 0x8A91, 0x691C, 0x8C9F, + 0x6921, 0x9EAF, 0x6922, 0x9E9A, 0x6923, 0x9EAE, 0x6925, 0x9EA7, 0x6926, 0x9E9B, 0x6928, 0x9EAB, 0x692A, 0x9EAC, 0x6930, 0x9EBD, + 0x6934, 0x93CC, 0x6936, 0x9EA2, 0x6939, 0x9EB9, 0x693D, 0x9EBB, 0x693F, 0x92D6, 0x694A, 0x976B, 0x6953, 0x9596, 0x6954, 0x9EB6, + 0x6955, 0x91C8, 0x6959, 0x9EBC, 0x695A, 0x915E, 0x695C, 0x9EB3, 0x695D, 0x9EC0, 0x695E, 0x9EBF, 0x6960, 0x93ED, 0x6961, 0x9EBE, + 0x6962, 0x93E8, 0x6968, 0xFAE9, 0x696A, 0x9EC2, 0x696B, 0x9EB5, 0x696D, 0x8BC6, 0x696E, 0x9EB8, 0x696F, 0x8F7C, 0x6973, 0x9480, + 0x6974, 0x9EBA, 0x6975, 0x8BC9, 0x6977, 0x9EB2, 0x6978, 0x9EB4, 0x6979, 0x9EB1, 0x697C, 0x984F, 0x697D, 0x8A79, 0x697E, 0x9EB7, + 0x6981, 0x9EC1, 0x6982, 0x8A54, 0x698A, 0x8DE5, 0x698E, 0x897C, 0x6991, 0x9ED2, 0x6994, 0x9850, 0x6995, 0x9ED5, 0x6998, 0xFAEB, + 0x699B, 0x9059, 0x699C, 0x9ED4, 0x69A0, 0x9ED3, 0x69A7, 0x9ED0, 0x69AE, 0x9EC4, 0x69B1, 0x9EE1, 0x69B2, 0x9EC3, 0x69B4, 0x9ED6, + 0x69BB, 0x9ECE, 0x69BE, 0x9EC9, 0x69BF, 0x9EC6, 0x69C1, 0x9EC7, 0x69C3, 0x9ECF, 0x69C7, 0xEAA0, 0x69CA, 0x9ECC, 0x69CB, 0x8D5C, + 0x69CC, 0x92C6, 0x69CD, 0x9184, 0x69CE, 0x9ECA, 0x69D0, 0x9EC5, 0x69D3, 0x9EC8, 0x69D8, 0x976C, 0x69D9, 0x968A, 0x69DD, 0x9ECD, + 0x69DE, 0x9ED7, 0x69E2, 0xFAEC, 0x69E7, 0x9EDF, 0x69E8, 0x9ED8, 0x69EB, 0x9EE5, 0x69ED, 0x9EE3, 0x69F2, 0x9EDE, 0x69F9, 0x9EDD, + 0x69FB, 0x92CE, 0x69FD, 0x9185, 0x69FF, 0x9EDB, 0x6A02, 0x9ED9, 0x6A05, 0x9EE0, 0x6A0A, 0x9EE6, 0x6A0B, 0x94F3, 0x6A0C, 0x9EEC, + 0x6A12, 0x9EE7, 0x6A13, 0x9EEA, 0x6A14, 0x9EE4, 0x6A17, 0x9294, 0x6A19, 0x9557, 0x6A1B, 0x9EDA, 0x6A1E, 0x9EE2, 0x6A1F, 0x8FBE, + 0x6A21, 0x96CD, 0x6A22, 0x9EF6, 0x6A23, 0x9EE9, 0x6A29, 0x8CA0, 0x6A2A, 0x89A1, 0x6A2B, 0x8A7E, 0x6A2E, 0x9ED1, 0x6A30, 0xFAED, + 0x6A35, 0x8FBF, 0x6A36, 0x9EEE, 0x6A38, 0x9EF5, 0x6A39, 0x8EF7, 0x6A3A, 0x8A92, 0x6A3D, 0x924D, 0x6A44, 0x9EEB, 0x6A46, 0xFAEF, + 0x6A47, 0x9EF0, 0x6A48, 0x9EF4, 0x6A4B, 0x8BB4, 0x6A58, 0x8B6B, 0x6A59, 0x9EF2, 0x6A5F, 0x8B40, 0x6A61, 0x93C9, 0x6A62, 0x9EF1, + 0x6A66, 0x9EF3, 0x6A6B, 0xFAEE, 0x6A72, 0x9EED, 0x6A73, 0xFAF0, 0x6A78, 0x9EEF, 0x6A7E, 0xFAF1, 0x6A7F, 0x8A80, 0x6A80, 0x9268, + 0x6A84, 0x9EFA, 0x6A8D, 0x9EF8, 0x6A8E, 0x8CE7, 0x6A90, 0x9EF7, 0x6A97, 0x9F40, 0x6A9C, 0x9E77, 0x6AA0, 0x9EF9, 0x6AA2, 0x9EFB, + 0x6AA3, 0x9EFC, 0x6AAA, 0x9F4B, 0x6AAC, 0x9F47, 0x6AAE, 0x9E8D, 0x6AB3, 0x9F46, 0x6AB8, 0x9F45, 0x6ABB, 0x9F42, 0x6AC1, 0x9EE8, + 0x6AC2, 0x9F44, 0x6AC3, 0x9F43, 0x6AD1, 0x9F49, 0x6AD3, 0x9845, 0x6ADA, 0x9F4C, 0x6ADB, 0x8BF9, 0x6ADE, 0x9F48, 0x6ADF, 0x9F4A, + 0x6AE2, 0xFAF2, 0x6AE4, 0xFAF3, 0x6AE8, 0x94A5, 0x6AEA, 0x9F4D, 0x6AFA, 0x9F51, 0x6AFB, 0x9F4E, 0x6B04, 0x9793, 0x6B05, 0x9F4F, + 0x6B0A, 0x9EDC, 0x6B12, 0x9F52, 0x6B16, 0x9F53, 0x6B1D, 0x8954, 0x6B1F, 0x9F55, 0x6B20, 0x8C87, 0x6B21, 0x8E9F, 0x6B23, 0x8BD3, + 0x6B27, 0x89A2, 0x6B32, 0x977E, 0x6B37, 0x9F57, 0x6B38, 0x9F56, 0x6B39, 0x9F59, 0x6B3A, 0x8B5C, 0x6B3D, 0x8BD4, 0x6B3E, 0x8ABC, + 0x6B43, 0x9F5C, 0x6B47, 0x9F5B, 0x6B49, 0x9F5D, 0x6B4C, 0x89CC, 0x6B4E, 0x9256, 0x6B50, 0x9F5E, 0x6B53, 0x8ABD, 0x6B54, 0x9F60, + 0x6B59, 0x9F5F, 0x6B5B, 0x9F61, 0x6B5F, 0x9F62, 0x6B61, 0x9F63, 0x6B62, 0x8E7E, 0x6B63, 0x90B3, 0x6B64, 0x8D9F, 0x6B66, 0x9590, + 0x6B69, 0x95E0, 0x6B6A, 0x9863, 0x6B6F, 0x8E95, 0x6B73, 0x8DCE, 0x6B74, 0x97F0, 0x6B78, 0x9F64, 0x6B79, 0x9F65, 0x6B7B, 0x8E80, + 0x6B7F, 0x9F66, 0x6B80, 0x9F67, 0x6B83, 0x9F69, 0x6B84, 0x9F68, 0x6B86, 0x9677, 0x6B89, 0x8F7D, 0x6B8A, 0x8EEA, 0x6B8B, 0x8E63, + 0x6B8D, 0x9F6A, 0x6B95, 0x9F6C, 0x6B96, 0x9042, 0x6B98, 0x9F6B, 0x6B9E, 0x9F6D, 0x6BA4, 0x9F6E, 0x6BAA, 0x9F6F, 0x6BAB, 0x9F70, + 0x6BAF, 0x9F71, 0x6BB1, 0x9F73, 0x6BB2, 0x9F72, 0x6BB3, 0x9F74, 0x6BB4, 0x89A3, 0x6BB5, 0x9269, 0x6BB7, 0x9F75, 0x6BBA, 0x8E45, + 0x6BBB, 0x8A6B, 0x6BBC, 0x9F76, 0x6BBF, 0x9361, 0x6BC0, 0x9ACA, 0x6BC5, 0x8B42, 0x6BC6, 0x9F77, 0x6BCB, 0x9F78, 0x6BCD, 0x95EA, + 0x6BCE, 0x9688, 0x6BD2, 0x93C5, 0x6BD3, 0x9F79, 0x6BD4, 0x94E4, 0x6BD6, 0xFAF4, 0x6BD8, 0x94F9, 0x6BDB, 0x96D1, 0x6BDF, 0x9F7A, + 0x6BEB, 0x9F7C, 0x6BEC, 0x9F7B, 0x6BEF, 0x9F7E, 0x6BF3, 0x9F7D, 0x6C08, 0x9F81, 0x6C0F, 0x8E81, 0x6C11, 0x96AF, 0x6C13, 0x9F82, + 0x6C14, 0x9F83, 0x6C17, 0x8B43, 0x6C1B, 0x9F84, 0x6C23, 0x9F86, 0x6C24, 0x9F85, 0x6C34, 0x9085, 0x6C37, 0x9558, 0x6C38, 0x8969, + 0x6C3E, 0x94C3, 0x6C3F, 0xFAF5, 0x6C40, 0x92F3, 0x6C41, 0x8F60, 0x6C42, 0x8B81, 0x6C4E, 0x94C4, 0x6C50, 0x8EAC, 0x6C55, 0x9F88, + 0x6C57, 0x8ABE, 0x6C5A, 0x8998, 0x6C5C, 0xFAF6, 0x6C5D, 0x93F0, 0x6C5E, 0x9F87, 0x6C5F, 0x8D5D, 0x6C60, 0x9272, 0x6C62, 0x9F89, + 0x6C68, 0x9F91, 0x6C6A, 0x9F8A, 0x6C6F, 0xFAF8, 0x6C70, 0x91BF, 0x6C72, 0x8B82, 0x6C73, 0x9F92, 0x6C7A, 0x8C88, 0x6C7D, 0x8B44, + 0x6C7E, 0x9F90, 0x6C81, 0x9F8E, 0x6C82, 0x9F8B, 0x6C83, 0x9780, 0x6C86, 0xFAF7, 0x6C88, 0x92BE, 0x6C8C, 0x93D7, 0x6C8D, 0x9F8C, + 0x6C90, 0x9F94, 0x6C92, 0x9F93, 0x6C93, 0x8C42, 0x6C96, 0x89AB, 0x6C99, 0x8DB9, 0x6C9A, 0x9F8D, 0x6C9B, 0x9F8F, 0x6CA1, 0x9676, + 0x6CA2, 0x91F2, 0x6CAB, 0x9697, 0x6CAE, 0x9F9C, 0x6CB1, 0x9F9D, 0x6CB3, 0x89CD, 0x6CB8, 0x95A6, 0x6CB9, 0x96FB, 0x6CBA, 0x9F9F, + 0x6CBB, 0x8EA1, 0x6CBC, 0x8FC0, 0x6CBD, 0x9F98, 0x6CBE, 0x9F9E, 0x6CBF, 0x8988, 0x6CC1, 0x8BB5, 0x6CC4, 0x9F95, 0x6CC5, 0x9F9A, + 0x6CC9, 0x90F2, 0x6CCA, 0x9491, 0x6CCC, 0x94E5, 0x6CD3, 0x9F97, 0x6CD5, 0x9640, 0x6CD7, 0x9F99, 0x6CD9, 0x9FA2, 0x6CDA, 0xFAF9, + 0x6CDB, 0x9FA0, 0x6CDD, 0x9F9B, 0x6CE1, 0x9641, 0x6CE2, 0x9467, 0x6CE3, 0x8B83, 0x6CE5, 0x9344, 0x6CE8, 0x928D, 0x6CEA, 0x9FA3, + 0x6CEF, 0x9FA1, 0x6CF0, 0x91D7, 0x6CF1, 0x9F96, 0x6CF3, 0x896A, 0x6D04, 0xFAFA, 0x6D0B, 0x976D, 0x6D0C, 0x9FAE, 0x6D12, 0x9FAD, + 0x6D17, 0x90F4, 0x6D19, 0x9FAA, 0x6D1B, 0x978C, 0x6D1E, 0x93B4, 0x6D1F, 0x9FA4, 0x6D25, 0x92C3, 0x6D29, 0x896B, 0x6D2A, 0x8D5E, + 0x6D2B, 0x9FA7, 0x6D32, 0x8F46, 0x6D33, 0x9FAC, 0x6D35, 0x9FAB, 0x6D36, 0x9FA6, 0x6D38, 0x9FA9, 0x6D3B, 0x8A88, 0x6D3D, 0x9FA8, + 0x6D3E, 0x9468, 0x6D41, 0x97AC, 0x6D44, 0x8FF2, 0x6D45, 0x90F3, 0x6D59, 0x9FB4, 0x6D5A, 0x9FB2, 0x6D5C, 0x956C, 0x6D63, 0x9FAF, + 0x6D64, 0x9FB1, 0x6D66, 0x8959, 0x6D69, 0x8D5F, 0x6D6A, 0x9851, 0x6D6C, 0x8A5C, 0x6D6E, 0x9582, 0x6D6F, 0xFAFC, 0x6D74, 0x9781, + 0x6D77, 0x8A43, 0x6D78, 0x905A, 0x6D79, 0x9FB3, 0x6D85, 0x9FB8, 0x6D87, 0xFAFB, 0x6D88, 0x8FC1, 0x6D8C, 0x974F, 0x6D8E, 0x9FB5, + 0x6D93, 0x9FB0, 0x6D95, 0x9FB6, 0x6D96, 0xFB40, 0x6D99, 0x97DC, 0x6D9B, 0x9393, 0x6D9C, 0x93C0, 0x6DAC, 0xFB41, 0x6DAF, 0x8A55, + 0x6DB2, 0x8974, 0x6DB5, 0x9FBC, 0x6DB8, 0x9FBF, 0x6DBC, 0x97C1, 0x6DC0, 0x9784, 0x6DC5, 0x9FC6, 0x6DC6, 0x9FC0, 0x6DC7, 0x9FBD, + 0x6DCB, 0x97D2, 0x6DCC, 0x9FC3, 0x6DCF, 0xFB42, 0x6DD1, 0x8F69, 0x6DD2, 0x9FC5, 0x6DD5, 0x9FCA, 0x6DD8, 0x9391, 0x6DD9, 0x9FC8, + 0x6DDE, 0x9FC2, 0x6DE1, 0x9257, 0x6DE4, 0x9FC9, 0x6DE6, 0x9FBE, 0x6DE8, 0x9FC4, 0x6DEA, 0x9FCB, 0x6DEB, 0x88FA, 0x6DEC, 0x9FC1, + 0x6DEE, 0x9FCC, 0x6DF1, 0x905B, 0x6DF2, 0xFB44, 0x6DF3, 0x8F7E, 0x6DF5, 0x95A3, 0x6DF7, 0x8DAC, 0x6DF8, 0xFB43, 0x6DF9, 0x9FB9, + 0x6DFA, 0x9FC7, 0x6DFB, 0x9359, 0x6DFC, 0xFB45, 0x6E05, 0x90B4, 0x6E07, 0x8A89, 0x6E08, 0x8DCF, 0x6E09, 0x8FC2, 0x6E0A, 0x9FBB, + 0x6E0B, 0x8F61, 0x6E13, 0x8C6B, 0x6E15, 0x9FBA, 0x6E19, 0x9FD0, 0x6E1A, 0x8F8D, 0x6E1B, 0x8CB8, 0x6E1D, 0x9FDF, 0x6E1F, 0x9FD9, + 0x6E20, 0x8B94, 0x6E21, 0x936E, 0x6E23, 0x9FD4, 0x6E24, 0x9FDD, 0x6E25, 0x88AD, 0x6E26, 0x8951, 0x6E27, 0xFB48, 0x6E29, 0x89B7, + 0x6E2B, 0x9FD6, 0x6E2C, 0x91AA, 0x6E2D, 0x9FCD, 0x6E2E, 0x9FCF, 0x6E2F, 0x8D60, 0x6E38, 0x9FE0, 0x6E39, 0xFB46, 0x6E3A, 0x9FDB, + 0x6E3C, 0xFB49, 0x6E3E, 0x9FD3, 0x6E43, 0x9FDA, 0x6E4A, 0x96A9, 0x6E4D, 0x9FD8, 0x6E4E, 0x9FDC, 0x6E56, 0x8CCE, 0x6E58, 0x8FC3, + 0x6E5B, 0x9258, 0x6E5C, 0xFB47, 0x6E5F, 0x9FD2, 0x6E67, 0x974E, 0x6E6B, 0x9FD5, 0x6E6E, 0x9FCE, 0x6E6F, 0x9392, 0x6E72, 0x9FD1, + 0x6E76, 0x9FD7, 0x6E7E, 0x9870, 0x6E7F, 0x8EBC, 0x6E80, 0x969E, 0x6E82, 0x9FE1, 0x6E8C, 0x94AC, 0x6E8F, 0x9FED, 0x6E90, 0x8CB9, + 0x6E96, 0x8F80, 0x6E98, 0x9FE3, 0x6E9C, 0x97AD, 0x6E9D, 0x8D61, 0x6E9F, 0x9FF0, 0x6EA2, 0x88EC, 0x6EA5, 0x9FEE, 0x6EAA, 0x9FE2, + 0x6EAF, 0x9FE8, 0x6EB2, 0x9FEA, 0x6EB6, 0x976E, 0x6EB7, 0x9FE5, 0x6EBA, 0x934D, 0x6EBD, 0x9FE7, 0x6EBF, 0xFB4A, 0x6EC2, 0x9FEF, + 0x6EC4, 0x9FE9, 0x6EC5, 0x96C5, 0x6EC9, 0x9FE4, 0x6ECB, 0x8EA0, 0x6ECC, 0x9FFC, 0x6ED1, 0x8A8A, 0x6ED3, 0x9FE6, 0x6ED4, 0x9FEB, + 0x6ED5, 0x9FEC, 0x6EDD, 0x91EA, 0x6EDE, 0x91D8, 0x6EEC, 0x9FF4, 0x6EEF, 0x9FFA, 0x6EF2, 0x9FF8, 0x6EF4, 0x9348, 0x6EF7, 0xE042, + 0x6EF8, 0x9FF5, 0x6EFE, 0x9FF6, 0x6EFF, 0x9FDE, 0x6F01, 0x8B99, 0x6F02, 0x9559, 0x6F06, 0x8EBD, 0x6F09, 0x8D97, 0x6F0F, 0x9852, + 0x6F11, 0x9FF2, 0x6F13, 0xE041, 0x6F14, 0x8989, 0x6F15, 0x9186, 0x6F20, 0x9499, 0x6F22, 0x8ABF, 0x6F23, 0x97F8, 0x6F2B, 0x969F, + 0x6F2C, 0x92D0, 0x6F31, 0x9FF9, 0x6F32, 0x9FFB, 0x6F38, 0x9151, 0x6F3E, 0xE040, 0x6F3F, 0x9FF7, 0x6F41, 0x9FF1, 0x6F45, 0x8AC1, + 0x6F54, 0x8C89, 0x6F58, 0xE04E, 0x6F5B, 0xE049, 0x6F5C, 0x90F6, 0x6F5F, 0x8A83, 0x6F64, 0x8F81, 0x6F66, 0xE052, 0x6F6D, 0xE04B, + 0x6F6E, 0x92AA, 0x6F6F, 0xE048, 0x6F70, 0x92D7, 0x6F74, 0xE06B, 0x6F78, 0xE045, 0x6F7A, 0xE044, 0x6F7C, 0xE04D, 0x6F80, 0xE047, + 0x6F81, 0xE046, 0x6F82, 0xE04C, 0x6F84, 0x909F, 0x6F86, 0xE043, 0x6F88, 0xFB4B, 0x6F8E, 0xE04F, 0x6F91, 0xE050, 0x6F97, 0x8AC0, + 0x6FA1, 0xE055, 0x6FA3, 0xE054, 0x6FA4, 0xE056, 0x6FAA, 0xE059, 0x6FB1, 0x9362, 0x6FB3, 0xE053, 0x6FB5, 0xFB4C, 0x6FB9, 0xE057, + 0x6FC0, 0x8C83, 0x6FC1, 0x91F7, 0x6FC2, 0xE051, 0x6FC3, 0x945A, 0x6FC6, 0xE058, 0x6FD4, 0xE05D, 0x6FD5, 0xE05B, 0x6FD8, 0xE05E, + 0x6FDB, 0xE061, 0x6FDF, 0xE05A, 0x6FE0, 0x8D8A, 0x6FE1, 0x9447, 0x6FE4, 0x9FB7, 0x6FEB, 0x9794, 0x6FEC, 0xE05C, 0x6FEE, 0xE060, + 0x6FEF, 0x91F3, 0x6FF1, 0xE05F, 0x6FF3, 0xE04A, 0x6FF5, 0xFB4D, 0x6FF6, 0xE889, 0x6FFA, 0xE064, 0x6FFE, 0xE068, 0x7001, 0xE066, + 0x7005, 0xFB4E, 0x7007, 0xFB4F, 0x7009, 0xE062, 0x700B, 0xE063, 0x700F, 0xE067, 0x7011, 0xE065, 0x7015, 0x956D, 0x7018, 0xE06D, + 0x701A, 0xE06A, 0x701B, 0xE069, 0x701D, 0xE06C, 0x701E, 0x93D2, 0x701F, 0xE06E, 0x7026, 0x9295, 0x7027, 0x91EB, 0x7028, 0xFB50, + 0x702C, 0x90A3, 0x7030, 0xE06F, 0x7032, 0xE071, 0x703E, 0xE070, 0x704C, 0x9FF3, 0x7051, 0xE072, 0x7058, 0x93E5, 0x7063, 0xE073, + 0x706B, 0x89CE, 0x706F, 0x9394, 0x7070, 0x8A44, 0x7078, 0x8B84, 0x707C, 0x8EDC, 0x707D, 0x8DD0, 0x7085, 0xFB51, 0x7089, 0x9846, + 0x708A, 0x9086, 0x708E, 0x898A, 0x7092, 0xE075, 0x7099, 0xE074, 0x70AB, 0xFB52, 0x70AC, 0xE078, 0x70AD, 0x9259, 0x70AE, 0xE07B, + 0x70AF, 0xE076, 0x70B3, 0xE07A, 0x70B8, 0xE079, 0x70B9, 0x935F, 0x70BA, 0x88D7, 0x70BB, 0xFA62, 0x70C8, 0x97F3, 0x70CB, 0xE07D, + 0x70CF, 0x8947, 0x70D9, 0xE080, 0x70DD, 0xE07E, 0x70DF, 0xE07C, 0x70F1, 0xE077, 0x70F9, 0x9642, 0x70FD, 0xE082, 0x7104, 0xFB54, + 0x7109, 0xE081, 0x710F, 0xFB53, 0x7114, 0x898B, 0x7119, 0xE084, 0x711A, 0x95B0, 0x711C, 0xE083, 0x7121, 0x96B3, 0x7126, 0x8FC5, + 0x7136, 0x9152, 0x713C, 0x8FC4, 0x7146, 0xFB56, 0x7147, 0xFB57, 0x7149, 0x97F9, 0x714C, 0xE08A, 0x714E, 0x90F7, 0x7155, 0xE086, + 0x7156, 0xE08B, 0x7159, 0x898C, 0x715C, 0xFB55, 0x7162, 0xE089, 0x7164, 0x9481, 0x7165, 0xE085, 0x7166, 0xE088, 0x7167, 0x8FC6, + 0x7169, 0x94CF, 0x716C, 0xE08C, 0x716E, 0x8ECF, 0x717D, 0x90F8, 0x7184, 0xE08F, 0x7188, 0xE087, 0x718A, 0x8C46, 0x718F, 0xE08D, + 0x7194, 0x976F, 0x7195, 0xE090, 0x7199, 0xEAA4, 0x719F, 0x8F6E, 0x71A8, 0xE091, 0x71AC, 0xE092, 0x71B1, 0x944D, 0x71B9, 0xE094, + 0x71BE, 0xE095, 0x71C1, 0xFB59, 0x71C3, 0x9452, 0x71C8, 0x9395, 0x71C9, 0xE097, 0x71CE, 0xE099, 0x71D0, 0x97D3, 0x71D2, 0xE096, + 0x71D4, 0xE098, 0x71D5, 0x898D, 0x71D7, 0xE093, 0x71DF, 0x9A7A, 0x71E0, 0xE09A, 0x71E5, 0x9187, 0x71E6, 0x8E57, 0x71E7, 0xE09C, + 0x71EC, 0xE09B, 0x71ED, 0x9043, 0x71EE, 0x99D7, 0x71F5, 0xE09D, 0x71F9, 0xE09F, 0x71FB, 0xE08E, 0x71FC, 0xE09E, 0x71FE, 0xFB5A, + 0x71FF, 0xE0A0, 0x7206, 0x949A, 0x720D, 0xE0A1, 0x7210, 0xE0A2, 0x721B, 0xE0A3, 0x7228, 0xE0A4, 0x722A, 0x92DC, 0x722C, 0xE0A6, + 0x722D, 0xE0A5, 0x7230, 0xE0A7, 0x7232, 0xE0A8, 0x7235, 0x8EDD, 0x7236, 0x9583, 0x723A, 0x96EA, 0x723B, 0xE0A9, 0x723C, 0xE0AA, + 0x723D, 0x9175, 0x723E, 0x8EA2, 0x723F, 0xE0AB, 0x7240, 0xE0AC, 0x7246, 0xE0AD, 0x7247, 0x95D0, 0x7248, 0x94C5, 0x724B, 0xE0AE, + 0x724C, 0x9476, 0x7252, 0x92AB, 0x7258, 0xE0AF, 0x7259, 0x89E5, 0x725B, 0x8B8D, 0x725D, 0x96C4, 0x725F, 0x96B4, 0x7261, 0x89B2, + 0x7262, 0x9853, 0x7267, 0x9671, 0x7269, 0x95A8, 0x7272, 0x90B5, 0x7274, 0xE0B0, 0x7279, 0x93C1, 0x727D, 0x8CA1, 0x727E, 0xE0B1, + 0x7280, 0x8DD2, 0x7281, 0xE0B3, 0x7282, 0xE0B2, 0x7287, 0xE0B4, 0x7292, 0xE0B5, 0x7296, 0xE0B6, 0x72A0, 0x8B5D, 0x72A2, 0xE0B7, + 0x72A7, 0xE0B8, 0x72AC, 0x8CA2, 0x72AF, 0x94C6, 0x72B1, 0xFB5B, 0x72B2, 0xE0BA, 0x72B6, 0x8FF3, 0x72B9, 0xE0B9, 0x72BE, 0xFB5C, + 0x72C2, 0x8BB6, 0x72C3, 0xE0BB, 0x72C4, 0xE0BD, 0x72C6, 0xE0BC, 0x72CE, 0xE0BE, 0x72D0, 0x8CCF, 0x72D2, 0xE0BF, 0x72D7, 0x8BE7, + 0x72D9, 0x915F, 0x72DB, 0x8D9D, 0x72E0, 0xE0C1, 0x72E1, 0xE0C2, 0x72E2, 0xE0C0, 0x72E9, 0x8EEB, 0x72EC, 0x93C6, 0x72ED, 0x8BB7, + 0x72F7, 0xE0C4, 0x72F8, 0x924B, 0x72F9, 0xE0C3, 0x72FC, 0x9854, 0x72FD, 0x9482, 0x730A, 0xE0C7, 0x7316, 0xE0C9, 0x7317, 0xE0C6, + 0x731B, 0x96D2, 0x731C, 0xE0C8, 0x731D, 0xE0CA, 0x731F, 0x97C2, 0x7324, 0xFB5D, 0x7325, 0xE0CE, 0x7329, 0xE0CD, 0x732A, 0x9296, + 0x732B, 0x944C, 0x732E, 0x8CA3, 0x732F, 0xE0CC, 0x7334, 0xE0CB, 0x7336, 0x9750, 0x7337, 0x9751, 0x733E, 0xE0CF, 0x733F, 0x898E, + 0x7344, 0x8D96, 0x7345, 0x8E82, 0x734E, 0xE0D0, 0x734F, 0xE0D1, 0x7357, 0xE0D3, 0x7363, 0x8F62, 0x7368, 0xE0D5, 0x736A, 0xE0D4, + 0x7370, 0xE0D6, 0x7372, 0x8A6C, 0x7375, 0xE0D8, 0x7377, 0xFB5F, 0x7378, 0xE0D7, 0x737A, 0xE0DA, 0x737B, 0xE0D9, 0x7384, 0x8CBA, + 0x7387, 0x97A6, 0x7389, 0x8BCA, 0x738B, 0x89A4, 0x7396, 0x8BE8, 0x73A9, 0x8ADF, 0x73B2, 0x97E6, 0x73B3, 0xE0DC, 0x73BB, 0xE0DE, + 0x73BD, 0xFB60, 0x73C0, 0xE0DF, 0x73C2, 0x89CF, 0x73C8, 0xE0DB, 0x73C9, 0xFB61, 0x73CA, 0x8E58, 0x73CD, 0x92BF, 0x73CE, 0xE0DD, + 0x73D2, 0xFB64, 0x73D6, 0xFB62, 0x73DE, 0xE0E2, 0x73E0, 0x8EEC, 0x73E3, 0xFB63, 0x73E5, 0xE0E0, 0x73EA, 0x8C5D, 0x73ED, 0x94C7, + 0x73EE, 0xE0E1, 0x73F1, 0xE0FC, 0x73F5, 0xFB66, 0x73F8, 0xE0E7, 0x73FE, 0x8CBB, 0x7403, 0x8B85, 0x7405, 0xE0E4, 0x7406, 0x979D, + 0x7407, 0xFB65, 0x7409, 0x97AE, 0x7422, 0x91F4, 0x7425, 0xE0E6, 0x7426, 0xFB67, 0x7429, 0xFB69, 0x742A, 0xFB68, 0x742E, 0xFB6A, + 0x7432, 0xE0E8, 0x7433, 0x97D4, 0x7434, 0x8BD5, 0x7435, 0x94FA, 0x7436, 0x9469, 0x743A, 0xE0E9, 0x743F, 0xE0EB, 0x7441, 0xE0EE, + 0x7455, 0xE0EA, 0x7459, 0xE0ED, 0x745A, 0x8CE8, 0x745B, 0x896C, 0x745C, 0xE0EF, 0x745E, 0x9090, 0x745F, 0xE0EC, 0x7460, 0x97DA, + 0x7462, 0xFB6B, 0x7463, 0xE0F2, 0x7464, 0xEAA2, 0x7469, 0xE0F0, 0x746A, 0xE0F3, 0x746F, 0xE0E5, 0x7470, 0xE0F1, 0x7473, 0x8DBA, + 0x7476, 0xE0F4, 0x747E, 0xE0F5, 0x7483, 0x979E, 0x7489, 0xFB6C, 0x748B, 0xE0F6, 0x749E, 0xE0F7, 0x749F, 0xFB6D, 0x74A2, 0xE0E3, + 0x74A7, 0xE0F8, 0x74B0, 0x8AC2, 0x74BD, 0x8EA3, 0x74CA, 0xE0F9, 0x74CF, 0xE0FA, 0x74D4, 0xE0FB, 0x74DC, 0x895A, 0x74E0, 0xE140, + 0x74E2, 0x955A, 0x74E3, 0xE141, 0x74E6, 0x8AA2, 0x74E7, 0xE142, 0x74E9, 0xE143, 0x74EE, 0xE144, 0x74F0, 0xE146, 0x74F1, 0xE147, + 0x74F2, 0xE145, 0x74F6, 0x9572, 0x74F7, 0xE149, 0x74F8, 0xE148, 0x7501, 0xFB6E, 0x7503, 0xE14B, 0x7504, 0xE14A, 0x7505, 0xE14C, + 0x750C, 0xE14D, 0x750D, 0xE14F, 0x750E, 0xE14E, 0x7511, 0x8D99, 0x7513, 0xE151, 0x7515, 0xE150, 0x7518, 0x8AC3, 0x751A, 0x9072, + 0x751C, 0x935B, 0x751E, 0xE152, 0x751F, 0x90B6, 0x7523, 0x8E59, 0x7525, 0x8999, 0x7526, 0xE153, 0x7528, 0x9770, 0x752B, 0x95E1, + 0x752C, 0xE154, 0x752F, 0xFAA8, 0x7530, 0x9363, 0x7531, 0x9752, 0x7532, 0x8D62, 0x7533, 0x905C, 0x7537, 0x926A, 0x7538, 0x99B2, + 0x753A, 0x92AC, 0x753B, 0x89E6, 0x753C, 0xE155, 0x7544, 0xE156, 0x7546, 0xE15B, 0x7549, 0xE159, 0x754A, 0xE158, 0x754B, 0x9DC0, + 0x754C, 0x8A45, 0x754D, 0xE157, 0x754F, 0x88D8, 0x7551, 0x94A8, 0x7554, 0x94C8, 0x7559, 0x97AF, 0x755A, 0xE15C, 0x755B, 0xE15A, + 0x755C, 0x927B, 0x755D, 0x90A4, 0x7560, 0x94A9, 0x7562, 0x954C, 0x7564, 0xE15E, 0x7565, 0x97AA, 0x7566, 0x8C6C, 0x7567, 0xE15F, + 0x7569, 0xE15D, 0x756A, 0x94D4, 0x756B, 0xE160, 0x756D, 0xE161, 0x756F, 0xFB6F, 0x7570, 0x88D9, 0x7573, 0x8FF4, 0x7574, 0xE166, + 0x7576, 0xE163, 0x7577, 0x93EB, 0x7578, 0xE162, 0x757F, 0x8B45, 0x7582, 0xE169, 0x7586, 0xE164, 0x7587, 0xE165, 0x7589, 0xE168, + 0x758A, 0xE167, 0x758B, 0x9544, 0x758E, 0x9161, 0x758F, 0x9160, 0x7591, 0x8B5E, 0x7594, 0xE16A, 0x759A, 0xE16B, 0x759D, 0xE16C, + 0x75A3, 0xE16E, 0x75A5, 0xE16D, 0x75AB, 0x8975, 0x75B1, 0xE176, 0x75B2, 0x94E6, 0x75B3, 0xE170, 0x75B5, 0xE172, 0x75B8, 0xE174, + 0x75B9, 0x905D, 0x75BC, 0xE175, 0x75BD, 0xE173, 0x75BE, 0x8EBE, 0x75C2, 0xE16F, 0x75C3, 0xE171, 0x75C5, 0x9561, 0x75C7, 0x8FC7, + 0x75CA, 0xE178, 0x75CD, 0xE177, 0x75D2, 0xE179, 0x75D4, 0x8EA4, 0x75D5, 0x8DAD, 0x75D8, 0x9397, 0x75D9, 0xE17A, 0x75DB, 0x92C9, + 0x75DE, 0xE17C, 0x75E2, 0x979F, 0x75E3, 0xE17B, 0x75E9, 0x9189, 0x75F0, 0xE182, 0x75F2, 0xE184, 0x75F3, 0xE185, 0x75F4, 0x9273, + 0x75FA, 0xE183, 0x75FC, 0xE180, 0x75FE, 0xE17D, 0x75FF, 0xE17E, 0x7601, 0xE181, 0x7609, 0xE188, 0x760B, 0xE186, 0x760D, 0xE187, + 0x761F, 0xE189, 0x7620, 0xE18B, 0x7621, 0xE18C, 0x7622, 0xE18D, 0x7624, 0xE18E, 0x7627, 0xE18A, 0x7630, 0xE190, 0x7634, 0xE18F, + 0x763B, 0xE191, 0x7642, 0x97C3, 0x7646, 0xE194, 0x7647, 0xE192, 0x7648, 0xE193, 0x764C, 0x8AE0, 0x7652, 0x96FC, 0x7656, 0x95C8, + 0x7658, 0xE196, 0x765C, 0xE195, 0x7661, 0xE197, 0x7662, 0xE198, 0x7667, 0xE19C, 0x7668, 0xE199, 0x7669, 0xE19A, 0x766A, 0xE19B, + 0x766C, 0xE19D, 0x7670, 0xE19E, 0x7672, 0xE19F, 0x7676, 0xE1A0, 0x7678, 0xE1A1, 0x767A, 0x94AD, 0x767B, 0x936F, 0x767C, 0xE1A2, + 0x767D, 0x9492, 0x767E, 0x9553, 0x7680, 0xE1A3, 0x7682, 0xFB70, 0x7683, 0xE1A4, 0x7684, 0x9349, 0x7686, 0x8A46, 0x7687, 0x8D63, + 0x7688, 0xE1A5, 0x768B, 0xE1A6, 0x768E, 0xE1A7, 0x7690, 0x8E48, 0x7693, 0xE1A9, 0x7696, 0xE1A8, 0x7699, 0xE1AA, 0x769A, 0xE1AB, + 0x769B, 0xFB73, 0x769C, 0xFB71, 0x769E, 0xFB72, 0x76A6, 0xFB74, 0x76AE, 0x94E7, 0x76B0, 0xE1AC, 0x76B4, 0xE1AD, 0x76B7, 0xEA89, + 0x76B8, 0xE1AE, 0x76B9, 0xE1AF, 0x76BA, 0xE1B0, 0x76BF, 0x8E4D, 0x76C2, 0xE1B1, 0x76C3, 0x9475, 0x76C6, 0x967E, 0x76C8, 0x896D, + 0x76CA, 0x8976, 0x76CD, 0xE1B2, 0x76D2, 0xE1B4, 0x76D6, 0xE1B3, 0x76D7, 0x9390, 0x76DB, 0x90B7, 0x76DC, 0x9F58, 0x76DE, 0xE1B5, + 0x76DF, 0x96BF, 0x76E1, 0xE1B6, 0x76E3, 0x8AC4, 0x76E4, 0x94D5, 0x76E5, 0xE1B7, 0x76E7, 0xE1B8, 0x76EA, 0xE1B9, 0x76EE, 0x96DA, + 0x76F2, 0x96D3, 0x76F4, 0x92BC, 0x76F8, 0x918A, 0x76FB, 0xE1BB, 0x76FE, 0x8F82, 0x7701, 0x8FC8, 0x7704, 0xE1BE, 0x7707, 0xE1BD, + 0x7708, 0xE1BC, 0x7709, 0x94FB, 0x770B, 0x8AC5, 0x770C, 0x8CA7, 0x771B, 0xE1C4, 0x771E, 0xE1C1, 0x771F, 0x905E, 0x7720, 0x96B0, + 0x7724, 0xE1C0, 0x7725, 0xE1C2, 0x7726, 0xE1C3, 0x7729, 0xE1BF, 0x7737, 0xE1C5, 0x7738, 0xE1C6, 0x773A, 0x92AD, 0x773C, 0x8AE1, + 0x7740, 0x9285, 0x7746, 0xFB76, 0x7747, 0xE1C7, 0x775A, 0xE1C8, 0x775B, 0xE1CB, 0x7761, 0x9087, 0x7763, 0x93C2, 0x7765, 0xE1CC, + 0x7766, 0x9672, 0x7768, 0xE1C9, 0x776B, 0xE1CA, 0x7779, 0xE1CF, 0x777E, 0xE1CE, 0x777F, 0xE1CD, 0x778B, 0xE1D1, 0x778E, 0xE1D0, + 0x7791, 0xE1D2, 0x779E, 0xE1D4, 0x77A0, 0xE1D3, 0x77A5, 0x95CB, 0x77AC, 0x8F75, 0x77AD, 0x97C4, 0x77B0, 0xE1D5, 0x77B3, 0x93B5, + 0x77B6, 0xE1D6, 0x77B9, 0xE1D7, 0x77BB, 0xE1DB, 0x77BC, 0xE1D9, 0x77BD, 0xE1DA, 0x77BF, 0xE1D8, 0x77C7, 0xE1DC, 0x77CD, 0xE1DD, + 0x77D7, 0xE1DE, 0x77DA, 0xE1DF, 0x77DB, 0x96B5, 0x77DC, 0xE1E0, 0x77E2, 0x96EE, 0x77E3, 0xE1E1, 0x77E5, 0x926D, 0x77E7, 0x948A, + 0x77E9, 0x8BE9, 0x77ED, 0x925A, 0x77EE, 0xE1E2, 0x77EF, 0x8BB8, 0x77F3, 0x90CE, 0x77FC, 0xE1E3, 0x7802, 0x8DBB, 0x780C, 0xE1E4, + 0x7812, 0xE1E5, 0x7814, 0x8CA4, 0x7815, 0x8DD3, 0x7820, 0xE1E7, 0x7821, 0xFB78, 0x7825, 0x9375, 0x7826, 0x8DD4, 0x7827, 0x8B6D, + 0x7832, 0x9643, 0x7834, 0x946A, 0x783A, 0x9376, 0x783F, 0x8D7B, 0x7845, 0xE1E9, 0x784E, 0xFB79, 0x785D, 0x8FC9, 0x7864, 0xFB7A, + 0x786B, 0x97B0, 0x786C, 0x8D64, 0x786F, 0x8CA5, 0x7872, 0x94A1, 0x7874, 0xE1EB, 0x787A, 0xFB7B, 0x787C, 0xE1ED, 0x7881, 0x8CE9, + 0x7886, 0xE1EC, 0x7887, 0x92F4, 0x788C, 0xE1EF, 0x788D, 0x8A56, 0x788E, 0xE1EA, 0x7891, 0x94E8, 0x7893, 0x894F, 0x7895, 0x8DEA, + 0x7897, 0x9871, 0x789A, 0xE1EE, 0x78A3, 0xE1F0, 0x78A7, 0x95C9, 0x78A9, 0x90D7, 0x78AA, 0xE1F2, 0x78AF, 0xE1F3, 0x78B5, 0xE1F1, + 0x78BA, 0x8A6D, 0x78BC, 0xE1F9, 0x78BE, 0xE1F8, 0x78C1, 0x8EA5, 0x78C5, 0xE1FA, 0x78C6, 0xE1F5, 0x78CA, 0xE1FB, 0x78CB, 0xE1F6, + 0x78D0, 0x94D6, 0x78D1, 0xE1F4, 0x78D4, 0xE1F7, 0x78DA, 0xE241, 0x78E7, 0xE240, 0x78E8, 0x9681, 0x78EC, 0xE1FC, 0x78EF, 0x88E9, + 0x78F4, 0xE243, 0x78FD, 0xE242, 0x7901, 0x8FCA, 0x7907, 0xE244, 0x790E, 0x9162, 0x7911, 0xE246, 0x7912, 0xE245, 0x7919, 0xE247, + 0x7926, 0xE1E6, 0x792A, 0xE1E8, 0x792B, 0xE249, 0x792C, 0xE248, 0x7930, 0xFB7C, 0x793A, 0x8EA6, 0x793C, 0x97E7, 0x793E, 0x8ED0, + 0x7940, 0xE24A, 0x7941, 0x8C56, 0x7947, 0x8B5F, 0x7948, 0x8B46, 0x7949, 0x8E83, 0x7950, 0x9753, 0x7953, 0xE250, 0x7955, 0xE24F, + 0x7956, 0x9163, 0x7957, 0xE24C, 0x795A, 0xE24E, 0x795D, 0x8F6A, 0x795E, 0x905F, 0x795F, 0xE24D, 0x7960, 0xE24B, 0x7962, 0x9449, + 0x7965, 0x8FCB, 0x7968, 0x955B, 0x796D, 0x8DD5, 0x7977, 0x9398, 0x797A, 0xE251, 0x797F, 0xE252, 0x7980, 0xE268, 0x7981, 0x8BD6, + 0x7984, 0x985C, 0x7985, 0x9154, 0x798A, 0xE253, 0x798D, 0x89D0, 0x798E, 0x92F5, 0x798F, 0x959F, 0x7994, 0xFB81, 0x799B, 0xFB83, + 0x799D, 0xE254, 0x79A6, 0x8B9A, 0x79A7, 0xE255, 0x79AA, 0xE257, 0x79AE, 0xE258, 0x79B0, 0x9448, 0x79B3, 0xE259, 0x79B9, 0xE25A, + 0x79BA, 0xE25B, 0x79BD, 0x8BD7, 0x79BE, 0x89D1, 0x79BF, 0x93C3, 0x79C0, 0x8F47, 0x79C1, 0x8E84, 0x79C9, 0xE25C, 0x79CB, 0x8F48, + 0x79D1, 0x89C8, 0x79D2, 0x9562, 0x79D5, 0xE25D, 0x79D8, 0x94E9, 0x79DF, 0x9164, 0x79E1, 0xE260, 0x79E3, 0xE261, 0x79E4, 0x9489, + 0x79E6, 0x9060, 0x79E7, 0xE25E, 0x79E9, 0x9281, 0x79EC, 0xE25F, 0x79F0, 0x8FCC, 0x79FB, 0x88DA, 0x7A00, 0x8B48, 0x7A08, 0xE262, + 0x7A0B, 0x92F6, 0x7A0D, 0xE263, 0x7A0E, 0x90C5, 0x7A14, 0x96AB, 0x7A17, 0x9542, 0x7A18, 0xE264, 0x7A19, 0xE265, 0x7A1A, 0x9274, + 0x7A1C, 0x97C5, 0x7A1F, 0xE267, 0x7A20, 0xE266, 0x7A2E, 0x8EED, 0x7A31, 0xE269, 0x7A32, 0x88EE, 0x7A37, 0xE26C, 0x7A3B, 0xE26A, + 0x7A3C, 0x89D2, 0x7A3D, 0x8C6D, 0x7A3E, 0xE26B, 0x7A3F, 0x8D65, 0x7A40, 0x8D92, 0x7A42, 0x95E4, 0x7A43, 0xE26D, 0x7A46, 0x9673, + 0x7A49, 0xE26F, 0x7A4D, 0x90CF, 0x7A4E, 0x896E, 0x7A4F, 0x89B8, 0x7A50, 0x88AA, 0x7A57, 0xE26E, 0x7A61, 0xE270, 0x7A62, 0xE271, + 0x7A63, 0x8FF5, 0x7A69, 0xE272, 0x7A6B, 0x8A6E, 0x7A70, 0xE274, 0x7A74, 0x8C8A, 0x7A76, 0x8B86, 0x7A79, 0xE275, 0x7A7A, 0x8BF3, + 0x7A7D, 0xE276, 0x7A7F, 0x90FA, 0x7A81, 0x93CB, 0x7A83, 0x90DE, 0x7A84, 0x8DF3, 0x7A88, 0xE277, 0x7A92, 0x9282, 0x7A93, 0x918B, + 0x7A95, 0xE279, 0x7A96, 0xE27B, 0x7A97, 0xE278, 0x7A98, 0xE27A, 0x7A9F, 0x8C41, 0x7AA9, 0xE27C, 0x7AAA, 0x8C45, 0x7AAE, 0x8B87, + 0x7AAF, 0x9771, 0x7AB0, 0xE27E, 0x7AB6, 0xE280, 0x7ABA, 0x894D, 0x7ABF, 0xE283, 0x7AC3, 0x8A96, 0x7AC4, 0xE282, 0x7AC5, 0xE281, + 0x7AC7, 0xE285, 0x7AC8, 0xE27D, 0x7ACA, 0xE286, 0x7ACB, 0x97A7, 0x7ACD, 0xE287, 0x7ACF, 0xE288, 0x7AD1, 0xFB84, 0x7AD2, 0x9AF2, + 0x7AD3, 0xE28A, 0x7AD5, 0xE289, 0x7AD9, 0xE28B, 0x7ADA, 0xE28C, 0x7ADC, 0x97B3, 0x7ADD, 0xE28D, 0x7ADF, 0xE8ED, 0x7AE0, 0x8FCD, + 0x7AE1, 0xE28E, 0x7AE2, 0xE28F, 0x7AE3, 0x8F76, 0x7AE5, 0x93B6, 0x7AE6, 0xE290, 0x7AE7, 0xFB85, 0x7AEA, 0x9247, 0x7AEB, 0xFB87, + 0x7AED, 0xE291, 0x7AEF, 0x925B, 0x7AF0, 0xE292, 0x7AF6, 0x8BA3, 0x7AF8, 0x995E, 0x7AF9, 0x927C, 0x7AFA, 0x8EB1, 0x7AFF, 0x8AC6, + 0x7B02, 0xE293, 0x7B04, 0xE2A0, 0x7B06, 0xE296, 0x7B08, 0x8B88, 0x7B0A, 0xE295, 0x7B0B, 0xE2A2, 0x7B0F, 0xE294, 0x7B11, 0x8FCE, + 0x7B18, 0xE298, 0x7B19, 0xE299, 0x7B1B, 0x934A, 0x7B1E, 0xE29A, 0x7B20, 0x8A7D, 0x7B25, 0x9079, 0x7B26, 0x9584, 0x7B28, 0xE29C, + 0x7B2C, 0x91E6, 0x7B33, 0xE297, 0x7B35, 0xE29B, 0x7B36, 0xE29D, 0x7B39, 0x8DF9, 0x7B45, 0xE2A4, 0x7B46, 0x954D, 0x7B48, 0x94A4, + 0x7B49, 0x9399, 0x7B4B, 0x8BD8, 0x7B4C, 0xE2A3, 0x7B4D, 0xE2A1, 0x7B4F, 0x94B3, 0x7B50, 0xE29E, 0x7B51, 0x927D, 0x7B52, 0x939B, + 0x7B54, 0x939A, 0x7B56, 0x8DF4, 0x7B5D, 0xE2B6, 0x7B65, 0xE2A6, 0x7B67, 0xE2A8, 0x7B6C, 0xE2AB, 0x7B6E, 0xE2AC, 0x7B70, 0xE2A9, + 0x7B71, 0xE2AA, 0x7B74, 0xE2A7, 0x7B75, 0xE2A5, 0x7B7A, 0xE29F, 0x7B86, 0x95CD, 0x7B87, 0x89D3, 0x7B8B, 0xE2B3, 0x7B8D, 0xE2B0, + 0x7B8F, 0xE2B5, 0x7B92, 0xE2B4, 0x7B94, 0x9493, 0x7B95, 0x96A5, 0x7B97, 0x8E5A, 0x7B98, 0xE2AE, 0x7B99, 0xE2B7, 0x7B9A, 0xE2B2, + 0x7B9C, 0xE2B1, 0x7B9D, 0xE2AD, 0x7B9E, 0xFB88, 0x7B9F, 0xE2AF, 0x7BA1, 0x8AC7, 0x7BAA, 0x925C, 0x7BAD, 0x90FB, 0x7BB1, 0x94A0, + 0x7BB4, 0xE2BC, 0x7BB8, 0x94A2, 0x7BC0, 0x90DF, 0x7BC1, 0xE2B9, 0x7BC4, 0x94CD, 0x7BC6, 0xE2BD, 0x7BC7, 0x95D1, 0x7BC9, 0x927A, + 0x7BCB, 0xE2B8, 0x7BCC, 0xE2BA, 0x7BCF, 0xE2BB, 0x7BDD, 0xE2BE, 0x7BE0, 0x8EC2, 0x7BE4, 0x93C4, 0x7BE5, 0xE2C3, 0x7BE6, 0xE2C2, + 0x7BE9, 0xE2BF, 0x7BED, 0x9855, 0x7BF3, 0xE2C8, 0x7BF6, 0xE2CC, 0x7BF7, 0xE2C9, 0x7C00, 0xE2C5, 0x7C07, 0xE2C6, 0x7C0D, 0xE2CB, + 0x7C11, 0xE2C0, 0x7C12, 0x99D3, 0x7C13, 0xE2C7, 0x7C14, 0xE2C1, 0x7C17, 0xE2CA, 0x7C1F, 0xE2D0, 0x7C21, 0x8AC8, 0x7C23, 0xE2CD, + 0x7C27, 0xE2CE, 0x7C2A, 0xE2CF, 0x7C2B, 0xE2D2, 0x7C37, 0xE2D1, 0x7C38, 0x94F4, 0x7C3D, 0xE2D3, 0x7C3E, 0x97FA, 0x7C3F, 0x95EB, + 0x7C40, 0xE2D8, 0x7C43, 0xE2D5, 0x7C4C, 0xE2D4, 0x7C4D, 0x90D0, 0x7C4F, 0xE2D7, 0x7C50, 0xE2D9, 0x7C54, 0xE2D6, 0x7C56, 0xE2DD, + 0x7C58, 0xE2DA, 0x7C5F, 0xE2DB, 0x7C60, 0xE2C4, 0x7C64, 0xE2DC, 0x7C65, 0xE2DE, 0x7C6C, 0xE2DF, 0x7C73, 0x95C4, 0x7C75, 0xE2E0, + 0x7C7E, 0x96E0, 0x7C81, 0x8BCC, 0x7C82, 0x8C48, 0x7C83, 0xE2E1, 0x7C89, 0x95B2, 0x7C8B, 0x9088, 0x7C8D, 0x96AE, 0x7C90, 0xE2E2, + 0x7C92, 0x97B1, 0x7C95, 0x9494, 0x7C97, 0x9165, 0x7C98, 0x9453, 0x7C9B, 0x8F6C, 0x7C9F, 0x88BE, 0x7CA1, 0xE2E7, 0x7CA2, 0xE2E5, + 0x7CA4, 0xE2E3, 0x7CA5, 0x8A9F, 0x7CA7, 0x8FCF, 0x7CA8, 0xE2E8, 0x7CAB, 0xE2E6, 0x7CAD, 0xE2E4, 0x7CAE, 0xE2EC, 0x7CB1, 0xE2EB, + 0x7CB2, 0xE2EA, 0x7CB3, 0xE2E9, 0x7CB9, 0xE2ED, 0x7CBD, 0xE2EE, 0x7CBE, 0x90B8, 0x7CC0, 0xE2EF, 0x7CC2, 0xE2F1, 0x7CC5, 0xE2F0, + 0x7CCA, 0x8CD0, 0x7CCE, 0x9157, 0x7CD2, 0xE2F3, 0x7CD6, 0x939C, 0x7CD8, 0xE2F2, 0x7CDC, 0xE2F4, 0x7CDE, 0x95B3, 0x7CDF, 0x918C, + 0x7CE0, 0x8D66, 0x7CE2, 0xE2F5, 0x7CE7, 0x97C6, 0x7CEF, 0xE2F7, 0x7CF2, 0xE2F8, 0x7CF4, 0xE2F9, 0x7CF6, 0xE2FA, 0x7CF8, 0x8E85, + 0x7CFA, 0xE2FB, 0x7CFB, 0x8C6E, 0x7CFE, 0x8B8A, 0x7D00, 0x8B49, 0x7D02, 0xE340, 0x7D04, 0x96F1, 0x7D05, 0x8D67, 0x7D06, 0xE2FC, + 0x7D0A, 0xE343, 0x7D0B, 0x96E4, 0x7D0D, 0x945B, 0x7D10, 0x9552, 0x7D14, 0x8F83, 0x7D15, 0xE342, 0x7D17, 0x8ED1, 0x7D18, 0x8D68, + 0x7D19, 0x8E86, 0x7D1A, 0x8B89, 0x7D1B, 0x95B4, 0x7D1C, 0xE341, 0x7D20, 0x9166, 0x7D21, 0x9661, 0x7D22, 0x8DF5, 0x7D2B, 0x8E87, + 0x7D2C, 0x92DB, 0x7D2E, 0xE346, 0x7D2F, 0x97DD, 0x7D30, 0x8DD7, 0x7D32, 0xE347, 0x7D33, 0x9061, 0x7D35, 0xE349, 0x7D39, 0x8FD0, + 0x7D3A, 0x8DAE, 0x7D3F, 0xE348, 0x7D42, 0x8F49, 0x7D43, 0x8CBC, 0x7D44, 0x9167, 0x7D45, 0xE344, 0x7D46, 0xE34A, 0x7D48, 0xFB8A, + 0x7D4B, 0xE345, 0x7D4C, 0x8C6F, 0x7D4E, 0xE34D, 0x7D4F, 0xE351, 0x7D50, 0x8C8B, 0x7D56, 0xE34C, 0x7D5B, 0xE355, 0x7D5C, 0xFB8B, + 0x7D5E, 0x8D69, 0x7D61, 0x978D, 0x7D62, 0x88BA, 0x7D63, 0xE352, 0x7D66, 0x8B8B, 0x7D68, 0xE34F, 0x7D6E, 0xE350, 0x7D71, 0x939D, + 0x7D72, 0xE34E, 0x7D73, 0xE34B, 0x7D75, 0x8A47, 0x7D76, 0x90E2, 0x7D79, 0x8CA6, 0x7D7D, 0xE357, 0x7D89, 0xE354, 0x7D8F, 0xE356, + 0x7D93, 0xE353, 0x7D99, 0x8C70, 0x7D9A, 0x91B1, 0x7D9B, 0xE358, 0x7D9C, 0x918E, 0x7D9F, 0xE365, 0x7DA0, 0xFB8D, 0x7DA2, 0xE361, + 0x7DA3, 0xE35B, 0x7DAB, 0xE35F, 0x7DAC, 0x8EF8, 0x7DAD, 0x88DB, 0x7DAE, 0xE35A, 0x7DAF, 0xE362, 0x7DB0, 0xE366, 0x7DB1, 0x8D6A, + 0x7DB2, 0x96D4, 0x7DB4, 0x92D4, 0x7DB5, 0xE35C, 0x7DB7, 0xFB8C, 0x7DB8, 0xE364, 0x7DBA, 0xE359, 0x7DBB, 0x925D, 0x7DBD, 0xE35E, + 0x7DBE, 0x88BB, 0x7DBF, 0x96C8, 0x7DC7, 0xE35D, 0x7DCA, 0x8BD9, 0x7DCB, 0x94EA, 0x7DCF, 0x918D, 0x7DD1, 0x97CE, 0x7DD2, 0x8F8F, + 0x7DD5, 0xE38E, 0x7DD6, 0xFB8E, 0x7DD8, 0xE367, 0x7DDA, 0x90FC, 0x7DDC, 0xE363, 0x7DDD, 0xE368, 0x7DDE, 0xE36A, 0x7DE0, 0x92F7, + 0x7DE1, 0xE36D, 0x7DE4, 0xE369, 0x7DE8, 0x95D2, 0x7DE9, 0x8AC9, 0x7DEC, 0x96C9, 0x7DEF, 0x88DC, 0x7DF2, 0xE36C, 0x7DF4, 0x97FB, + 0x7DFB, 0xE36B, 0x7E01, 0x898F, 0x7E04, 0x93EA, 0x7E05, 0xE36E, 0x7E09, 0xE375, 0x7E0A, 0xE36F, 0x7E0B, 0xE376, 0x7E12, 0xE372, + 0x7E1B, 0x949B, 0x7E1E, 0x8EC8, 0x7E1F, 0xE374, 0x7E21, 0xE371, 0x7E22, 0xE377, 0x7E23, 0xE370, 0x7E26, 0x8F63, 0x7E2B, 0x9644, + 0x7E2E, 0x8F6B, 0x7E31, 0xE373, 0x7E32, 0xE380, 0x7E35, 0xE37B, 0x7E37, 0xE37E, 0x7E39, 0xE37C, 0x7E3A, 0xE381, 0x7E3B, 0xE37A, + 0x7E3D, 0xE360, 0x7E3E, 0x90D1, 0x7E41, 0x94C9, 0x7E43, 0xE37D, 0x7E46, 0xE378, 0x7E4A, 0x9140, 0x7E4B, 0x8C71, 0x7E4D, 0x8F4A, + 0x7E52, 0xFB8F, 0x7E54, 0x9044, 0x7E55, 0x9155, 0x7E56, 0xE384, 0x7E59, 0xE386, 0x7E5A, 0xE387, 0x7E5D, 0xE383, 0x7E5E, 0xE385, + 0x7E66, 0xE379, 0x7E67, 0xE382, 0x7E69, 0xE38A, 0x7E6A, 0xE389, 0x7E6D, 0x969A, 0x7E70, 0x8C4A, 0x7E79, 0xE388, 0x7E7B, 0xE38C, + 0x7E7C, 0xE38B, 0x7E7D, 0xE38F, 0x7E7F, 0xE391, 0x7E82, 0x8E5B, 0x7E83, 0xE38D, 0x7E88, 0xE392, 0x7E89, 0xE393, 0x7E8A, 0xFA5C, + 0x7E8C, 0xE394, 0x7E8E, 0xE39A, 0x7E8F, 0x935A, 0x7E90, 0xE396, 0x7E92, 0xE395, 0x7E93, 0xE397, 0x7E94, 0xE398, 0x7E96, 0xE399, + 0x7E9B, 0xE39B, 0x7E9C, 0xE39C, 0x7F36, 0x8ACA, 0x7F38, 0xE39D, 0x7F3A, 0xE39E, 0x7F45, 0xE39F, 0x7F47, 0xFB90, 0x7F4C, 0xE3A0, + 0x7F4D, 0xE3A1, 0x7F4E, 0xE3A2, 0x7F50, 0xE3A3, 0x7F51, 0xE3A4, 0x7F54, 0xE3A6, 0x7F55, 0xE3A5, 0x7F58, 0xE3A7, 0x7F5F, 0xE3A8, + 0x7F60, 0xE3A9, 0x7F67, 0xE3AC, 0x7F68, 0xE3AA, 0x7F69, 0xE3AB, 0x7F6A, 0x8DDF, 0x7F6B, 0x8C72, 0x7F6E, 0x9275, 0x7F70, 0x94B1, + 0x7F72, 0x8F90, 0x7F75, 0x946C, 0x7F77, 0x94EB, 0x7F78, 0xE3AD, 0x7F79, 0x9CEB, 0x7F82, 0xE3AE, 0x7F83, 0xE3B0, 0x7F85, 0x9785, + 0x7F86, 0xE3AF, 0x7F87, 0xE3B2, 0x7F88, 0xE3B1, 0x7F8A, 0x9772, 0x7F8C, 0xE3B3, 0x7F8E, 0x94FC, 0x7F94, 0xE3B4, 0x7F9A, 0xE3B7, + 0x7F9D, 0xE3B6, 0x7F9E, 0xE3B5, 0x7FA1, 0xFB91, 0x7FA3, 0xE3B8, 0x7FA4, 0x8C51, 0x7FA8, 0x9141, 0x7FA9, 0x8B60, 0x7FAE, 0xE3BC, + 0x7FAF, 0xE3B9, 0x7FB2, 0xE3BA, 0x7FB6, 0xE3BD, 0x7FB8, 0xE3BE, 0x7FB9, 0xE3BB, 0x7FBD, 0x8948, 0x7FC1, 0x89A5, 0x7FC5, 0xE3C0, + 0x7FC6, 0xE3C1, 0x7FCA, 0xE3C2, 0x7FCC, 0x9782, 0x7FD2, 0x8F4B, 0x7FD4, 0xE3C4, 0x7FD5, 0xE3C3, 0x7FE0, 0x9089, 0x7FE1, 0xE3C5, + 0x7FE6, 0xE3C6, 0x7FE9, 0xE3C7, 0x7FEB, 0x8AE3, 0x7FF0, 0x8ACB, 0x7FF3, 0xE3C8, 0x7FF9, 0xE3C9, 0x7FFB, 0x967C, 0x7FFC, 0x9783, + 0x8000, 0x9773, 0x8001, 0x9856, 0x8003, 0x8D6C, 0x8004, 0xE3CC, 0x8005, 0x8ED2, 0x8006, 0xE3CB, 0x800B, 0xE3CD, 0x800C, 0x8EA7, + 0x8010, 0x91CF, 0x8012, 0xE3CE, 0x8015, 0x8D6B, 0x8017, 0x96D5, 0x8018, 0xE3CF, 0x8019, 0xE3D0, 0x801C, 0xE3D1, 0x8021, 0xE3D2, + 0x8028, 0xE3D3, 0x8033, 0x8EA8, 0x8036, 0x96EB, 0x803B, 0xE3D5, 0x803D, 0x925E, 0x803F, 0xE3D4, 0x8046, 0xE3D7, 0x804A, 0xE3D6, + 0x8052, 0xE3D8, 0x8056, 0x90B9, 0x8058, 0xE3D9, 0x805A, 0xE3DA, 0x805E, 0x95B7, 0x805F, 0xE3DB, 0x8061, 0x918F, 0x8062, 0xE3DC, + 0x8068, 0xE3DD, 0x806F, 0x97FC, 0x8070, 0xE3E0, 0x8072, 0xE3DF, 0x8073, 0xE3DE, 0x8074, 0x92AE, 0x8076, 0xE3E1, 0x8077, 0x9045, + 0x8079, 0xE3E2, 0x807D, 0xE3E3, 0x807E, 0x9857, 0x807F, 0xE3E4, 0x8084, 0xE3E5, 0x8085, 0xE3E7, 0x8086, 0xE3E6, 0x8087, 0x94A3, + 0x8089, 0x93F7, 0x808B, 0x985D, 0x808C, 0x94A7, 0x8093, 0xE3E9, 0x8096, 0x8FD1, 0x8098, 0x9549, 0x809A, 0xE3EA, 0x809B, 0xE3E8, + 0x809D, 0x8ACC, 0x80A1, 0x8CD2, 0x80A2, 0x8E88, 0x80A5, 0x94EC, 0x80A9, 0x8CA8, 0x80AA, 0x9662, 0x80AC, 0xE3ED, 0x80AD, 0xE3EB, + 0x80AF, 0x8D6D, 0x80B1, 0x8D6E, 0x80B2, 0x88E7, 0x80B4, 0x8DE6, 0x80BA, 0x9478, 0x80C3, 0x88DD, 0x80C4, 0xE3F2, 0x80C6, 0x925F, + 0x80CC, 0x9477, 0x80CE, 0x91D9, 0x80D6, 0xE3F4, 0x80D9, 0xE3F0, 0x80DA, 0xE3F3, 0x80DB, 0xE3EE, 0x80DD, 0xE3F1, 0x80DE, 0x9645, + 0x80E1, 0x8CD3, 0x80E4, 0x88FB, 0x80E5, 0xE3EF, 0x80EF, 0xE3F6, 0x80F1, 0xE3F7, 0x80F4, 0x93B7, 0x80F8, 0x8BB9, 0x80FC, 0xE445, + 0x80FD, 0x945C, 0x8102, 0x8E89, 0x8105, 0x8BBA, 0x8106, 0x90C6, 0x8107, 0x9865, 0x8108, 0x96AC, 0x8109, 0xE3F5, 0x810A, 0x90D2, + 0x811A, 0x8B72, 0x811B, 0xE3F8, 0x8123, 0xE3FA, 0x8129, 0xE3F9, 0x812F, 0xE3FB, 0x8131, 0x9245, 0x8133, 0x945D, 0x8139, 0x92AF, + 0x813E, 0xE442, 0x8146, 0xE441, 0x814B, 0xE3FC, 0x814E, 0x9074, 0x8150, 0x9585, 0x8151, 0xE444, 0x8153, 0xE443, 0x8154, 0x8D6F, + 0x8155, 0x9872, 0x815F, 0xE454, 0x8165, 0xE448, 0x8166, 0xE449, 0x816B, 0x8EEE, 0x816E, 0xE447, 0x8170, 0x8D98, 0x8171, 0xE446, + 0x8174, 0xE44A, 0x8178, 0x92B0, 0x8179, 0x95A0, 0x817A, 0x9142, 0x817F, 0x91DA, 0x8180, 0xE44E, 0x8182, 0xE44F, 0x8183, 0xE44B, + 0x8188, 0xE44C, 0x818A, 0xE44D, 0x818F, 0x8D70, 0x8193, 0xE455, 0x8195, 0xE451, 0x819A, 0x9586, 0x819C, 0x968C, 0x819D, 0x9547, + 0x81A0, 0xE450, 0x81A3, 0xE453, 0x81A4, 0xE452, 0x81A8, 0x9663, 0x81A9, 0xE456, 0x81B0, 0xE457, 0x81B3, 0x9156, 0x81B5, 0xE458, + 0x81B8, 0xE45A, 0x81BA, 0xE45E, 0x81BD, 0xE45B, 0x81BE, 0xE459, 0x81BF, 0x945E, 0x81C0, 0xE45C, 0x81C2, 0xE45D, 0x81C6, 0x89B0, + 0x81C8, 0xE464, 0x81C9, 0xE45F, 0x81CD, 0xE460, 0x81D1, 0xE461, 0x81D3, 0x919F, 0x81D8, 0xE463, 0x81D9, 0xE462, 0x81DA, 0xE465, + 0x81DF, 0xE466, 0x81E0, 0xE467, 0x81E3, 0x9062, 0x81E5, 0x89E7, 0x81E7, 0xE468, 0x81E8, 0x97D5, 0x81EA, 0x8EA9, 0x81ED, 0x8F4C, + 0x81F3, 0x8E8A, 0x81F4, 0x9276, 0x81FA, 0xE469, 0x81FB, 0xE46A, 0x81FC, 0x8950, 0x81FE, 0xE46B, 0x8201, 0xE46C, 0x8202, 0xE46D, + 0x8205, 0xE46E, 0x8207, 0xE46F, 0x8208, 0x8BBB, 0x8209, 0x9DA8, 0x820A, 0xE470, 0x820C, 0x90E3, 0x820D, 0xE471, 0x820E, 0x8EC9, + 0x8210, 0xE472, 0x8212, 0x98AE, 0x8216, 0xE473, 0x8217, 0x95DC, 0x8218, 0x8ADA, 0x821B, 0x9143, 0x821C, 0x8F77, 0x821E, 0x9591, + 0x821F, 0x8F4D, 0x8229, 0xE474, 0x822A, 0x8D71, 0x822B, 0xE475, 0x822C, 0x94CA, 0x822E, 0xE484, 0x8233, 0xE477, 0x8235, 0x91C7, + 0x8236, 0x9495, 0x8237, 0x8CBD, 0x8238, 0xE476, 0x8239, 0x9144, 0x8240, 0xE478, 0x8247, 0x92F8, 0x8258, 0xE47A, 0x8259, 0xE479, + 0x825A, 0xE47C, 0x825D, 0xE47B, 0x825F, 0xE47D, 0x8262, 0xE480, 0x8264, 0xE47E, 0x8266, 0x8ACD, 0x8268, 0xE481, 0x826A, 0xE482, + 0x826B, 0xE483, 0x826E, 0x8DAF, 0x826F, 0x97C7, 0x8271, 0xE485, 0x8272, 0x9046, 0x8276, 0x8990, 0x8277, 0xE486, 0x8278, 0xE487, + 0x827E, 0xE488, 0x828B, 0x88F0, 0x828D, 0xE489, 0x8292, 0xE48A, 0x8299, 0x9587, 0x829D, 0x8EC5, 0x829F, 0xE48C, 0x82A5, 0x8A48, + 0x82A6, 0x88B0, 0x82AB, 0xE48B, 0x82AC, 0xE48E, 0x82AD, 0x946D, 0x82AF, 0x9063, 0x82B1, 0x89D4, 0x82B3, 0x9646, 0x82B8, 0x8C7C, + 0x82B9, 0x8BDA, 0x82BB, 0xE48D, 0x82BD, 0x89E8, 0x82C5, 0x8AA1, 0x82D1, 0x8991, 0x82D2, 0xE492, 0x82D3, 0x97E8, 0x82D4, 0x91DB, + 0x82D7, 0x9563, 0x82D9, 0xE49E, 0x82DB, 0x89D5, 0x82DC, 0xE49C, 0x82DE, 0xE49A, 0x82DF, 0xE491, 0x82E1, 0xE48F, 0x82E3, 0xE490, + 0x82E5, 0x8EE1, 0x82E6, 0x8BEA, 0x82E7, 0x9297, 0x82EB, 0x93CF, 0x82F1, 0x8970, 0x82F3, 0xE494, 0x82F4, 0xE493, 0x82F9, 0xE499, + 0x82FA, 0xE495, 0x82FB, 0xE498, 0x8301, 0xFB93, 0x8302, 0x96CE, 0x8303, 0xE497, 0x8304, 0x89D6, 0x8305, 0x8A9D, 0x8306, 0xE49B, + 0x8309, 0xE49D, 0x830E, 0x8C73, 0x8316, 0xE4A1, 0x8317, 0xE4AA, 0x8318, 0xE4AB, 0x831C, 0x88A9, 0x8323, 0xE4B2, 0x8328, 0x88EF, + 0x832B, 0xE4A9, 0x832F, 0xE4A8, 0x8331, 0xE4A3, 0x8332, 0xE4A2, 0x8334, 0xE4A0, 0x8335, 0xE49F, 0x8336, 0x9283, 0x8338, 0x91F9, + 0x8339, 0xE4A5, 0x8340, 0xE4A4, 0x8345, 0xE4A7, 0x8349, 0x9190, 0x834A, 0x8C74, 0x834F, 0x8960, 0x8350, 0xE4A6, 0x8352, 0x8D72, + 0x8358, 0x9191, 0x8362, 0xFB94, 0x8373, 0xE4B8, 0x8375, 0xE4B9, 0x8377, 0x89D7, 0x837B, 0x89AC, 0x837C, 0xE4B6, 0x837F, 0xFB95, + 0x8385, 0xE4AC, 0x8387, 0xE4B4, 0x8389, 0xE4BB, 0x838A, 0xE4B5, 0x838E, 0xE4B3, 0x8393, 0xE496, 0x8396, 0xE4B1, 0x839A, 0xE4AD, + 0x839E, 0x8ACE, 0x839F, 0xE4AF, 0x83A0, 0xE4BA, 0x83A2, 0xE4B0, 0x83A8, 0xE4BC, 0x83AA, 0xE4AE, 0x83AB, 0x949C, 0x83B1, 0x9789, + 0x83B5, 0xE4B7, 0x83BD, 0xE4CD, 0x83C1, 0xE4C5, 0x83C5, 0x909B, 0x83C7, 0xFB96, 0x83CA, 0x8B65, 0x83CC, 0x8BDB, 0x83CE, 0xE4C0, + 0x83D3, 0x89D9, 0x83D6, 0x8FD2, 0x83D8, 0xE4C3, 0x83DC, 0x8DD8, 0x83DF, 0x9370, 0x83E0, 0xE4C8, 0x83E9, 0x95EC, 0x83EB, 0xE4BF, + 0x83EF, 0x89D8, 0x83F0, 0x8CD4, 0x83F1, 0x9548, 0x83F2, 0xE4C9, 0x83F4, 0xE4BD, 0x83F6, 0xFB97, 0x83F7, 0xE4C6, 0x83FB, 0xE4D0, + 0x83FD, 0xE4C1, 0x8403, 0xE4C2, 0x8404, 0x93B8, 0x8407, 0xE4C7, 0x840B, 0xE4C4, 0x840C, 0x9647, 0x840D, 0xE4CA, 0x840E, 0x88DE, + 0x8413, 0xE4BE, 0x8420, 0xE4CC, 0x8422, 0xE4CB, 0x8429, 0x948B, 0x842A, 0xE4D2, 0x842C, 0xE4DD, 0x8431, 0x8A9E, 0x8435, 0xE4E0, + 0x8438, 0xE4CE, 0x843C, 0xE4D3, 0x843D, 0x978E, 0x8446, 0xE4DC, 0x8448, 0xFB98, 0x8449, 0x9774, 0x844E, 0x97A8, 0x8457, 0x9298, + 0x845B, 0x8A8B, 0x8461, 0x9592, 0x8462, 0xE4E2, 0x8463, 0x939F, 0x8466, 0x88AF, 0x8469, 0xE4DB, 0x846B, 0xE4D7, 0x846C, 0x9192, + 0x846D, 0xE4D1, 0x846E, 0xE4D9, 0x846F, 0xE4DE, 0x8471, 0x944B, 0x8475, 0x88A8, 0x8477, 0xE4D6, 0x8479, 0xE4DF, 0x847A, 0x9598, + 0x8482, 0xE4DA, 0x8484, 0xE4D5, 0x848B, 0x8FD3, 0x8490, 0x8F4E, 0x8494, 0x8EAA, 0x8499, 0x96D6, 0x849C, 0x9566, 0x849F, 0xE4E5, + 0x84A1, 0xE4EE, 0x84AD, 0xE4D8, 0x84B2, 0x8A97, 0x84B4, 0xFB99, 0x84B8, 0x8FF6, 0x84B9, 0xE4E3, 0x84BB, 0xE4E8, 0x84BC, 0x9193, + 0x84BF, 0xE4E4, 0x84C1, 0xE4EB, 0x84C4, 0x927E, 0x84C6, 0xE4EC, 0x84C9, 0x9775, 0x84CA, 0xE4E1, 0x84CB, 0x8A57, 0x84CD, 0xE4E7, + 0x84D0, 0xE4EA, 0x84D1, 0x96AA, 0x84D6, 0xE4ED, 0x84D9, 0xE4E6, 0x84DA, 0xE4E9, 0x84DC, 0xFA60, 0x84EC, 0x9648, 0x84EE, 0x9840, + 0x84F4, 0xE4F1, 0x84FC, 0xE4F8, 0x84FF, 0xE4F0, 0x8500, 0x8EC1, 0x8506, 0xE4CF, 0x8511, 0x95CC, 0x8513, 0x96A0, 0x8514, 0xE4F7, + 0x8515, 0xE4F6, 0x8517, 0xE4F2, 0x8518, 0xE4F3, 0x851A, 0x8955, 0x851F, 0xE4F5, 0x8521, 0xE4EF, 0x8526, 0x92D3, 0x852C, 0xE4F4, + 0x852D, 0x88FC, 0x8535, 0x91A0, 0x853D, 0x95C1, 0x8540, 0xE4F9, 0x8541, 0xE540, 0x8543, 0x94D7, 0x8548, 0xE4FC, 0x8549, 0x8FD4, + 0x854A, 0x8EC7, 0x854B, 0xE542, 0x854E, 0x8BBC, 0x8553, 0xFB9A, 0x8555, 0xE543, 0x8557, 0x9599, 0x8558, 0xE4FB, 0x8559, 0xFB9B, + 0x855A, 0xE4D4, 0x8563, 0xE4FA, 0x8568, 0x986E, 0x8569, 0x93A0, 0x856A, 0x9593, 0x856B, 0xFB9C, 0x856D, 0xE54A, 0x8577, 0xE550, + 0x857E, 0xE551, 0x8580, 0xE544, 0x8584, 0x9496, 0x8587, 0xE54E, 0x8588, 0xE546, 0x858A, 0xE548, 0x8590, 0xE552, 0x8591, 0xE547, + 0x8594, 0xE54B, 0x8597, 0x8992, 0x8599, 0x93E3, 0x859B, 0xE54C, 0x859C, 0xE54F, 0x85A4, 0xE545, 0x85A6, 0x9145, 0x85A8, 0xE549, + 0x85A9, 0x8E46, 0x85AA, 0x9064, 0x85AB, 0x8C4F, 0x85AC, 0x96F2, 0x85AE, 0x96F7, 0x85AF, 0x8F92, 0x85B0, 0xFB9E, 0x85B9, 0xE556, + 0x85BA, 0xE554, 0x85C1, 0x986D, 0x85C9, 0xE553, 0x85CD, 0x9795, 0x85CF, 0xE555, 0x85D0, 0xE557, 0x85D5, 0xE558, 0x85DC, 0xE55B, + 0x85DD, 0xE559, 0x85E4, 0x93A1, 0x85E5, 0xE55A, 0x85E9, 0x94CB, 0x85EA, 0xE54D, 0x85F7, 0x8F93, 0x85F9, 0xE55C, 0x85FA, 0xE561, + 0x85FB, 0x9194, 0x85FE, 0xE560, 0x8602, 0xE541, 0x8606, 0xE562, 0x8607, 0x9168, 0x860A, 0xE55D, 0x860B, 0xE55F, 0x8613, 0xE55E, + 0x8616, 0x9F50, 0x8617, 0x9F41, 0x861A, 0xE564, 0x8622, 0xE563, 0x862D, 0x9796, 0x862F, 0xE1BA, 0x8630, 0xE565, 0x863F, 0xE566, + 0x864D, 0xE567, 0x864E, 0x8CD5, 0x8650, 0x8B73, 0x8654, 0xE569, 0x8655, 0x997C, 0x865A, 0x8B95, 0x865C, 0x97B8, 0x865E, 0x8BF1, + 0x865F, 0xE56A, 0x8667, 0xE56B, 0x866B, 0x928E, 0x8671, 0xE56C, 0x8679, 0x93F8, 0x867B, 0x88B8, 0x868A, 0x89E1, 0x868B, 0xE571, + 0x868C, 0xE572, 0x8693, 0xE56D, 0x8695, 0x8E5C, 0x86A3, 0xE56E, 0x86A4, 0x9461, 0x86A9, 0xE56F, 0x86AA, 0xE570, 0x86AB, 0xE57A, + 0x86AF, 0xE574, 0x86B0, 0xE577, 0x86B6, 0xE573, 0x86C4, 0xE575, 0x86C6, 0xE576, 0x86C7, 0x8ED6, 0x86C9, 0xE578, 0x86CB, 0x9260, + 0x86CD, 0x8C75, 0x86CE, 0x8A61, 0x86D4, 0xE57B, 0x86D9, 0x8A5E, 0x86DB, 0xE581, 0x86DE, 0xE57C, 0x86DF, 0xE580, 0x86E4, 0x94B8, + 0x86E9, 0xE57D, 0x86EC, 0xE57E, 0x86ED, 0x9567, 0x86EE, 0x94D8, 0x86EF, 0xE582, 0x86F8, 0x91FB, 0x86F9, 0xE58C, 0x86FB, 0xE588, + 0x86FE, 0x89E9, 0x8700, 0xE586, 0x8702, 0x9649, 0x8703, 0xE587, 0x8706, 0xE584, 0x8708, 0xE585, 0x8709, 0xE58A, 0x870A, 0xE58D, + 0x870D, 0xE58B, 0x8711, 0xE589, 0x8712, 0xE583, 0x8718, 0x9277, 0x871A, 0xE594, 0x871C, 0x96A8, 0x8725, 0xE592, 0x8729, 0xE593, + 0x8734, 0xE58E, 0x8737, 0xE590, 0x873B, 0xE591, 0x873F, 0xE58F, 0x8749, 0x90E4, 0x874B, 0x9858, 0x874C, 0xE598, 0x874E, 0xE599, + 0x8753, 0xE59F, 0x8755, 0x9049, 0x8757, 0xE59B, 0x8759, 0xE59E, 0x875F, 0xE596, 0x8760, 0xE595, 0x8763, 0xE5A0, 0x8766, 0x89DA, + 0x8768, 0xE59C, 0x876A, 0xE5A1, 0x876E, 0xE59D, 0x8774, 0xE59A, 0x8776, 0x92B1, 0x8778, 0xE597, 0x877F, 0x9488, 0x8782, 0xE5A5, + 0x878D, 0x975A, 0x879F, 0xE5A4, 0x87A2, 0xE5A3, 0x87AB, 0xE5AC, 0x87AF, 0xE5A6, 0x87B3, 0xE5AE, 0x87BA, 0x9786, 0x87BB, 0xE5B1, + 0x87BD, 0xE5A8, 0x87C0, 0xE5A9, 0x87C4, 0xE5AD, 0x87C6, 0xE5B0, 0x87C7, 0xE5AF, 0x87CB, 0xE5A7, 0x87D0, 0xE5AA, 0x87D2, 0xE5BB, + 0x87E0, 0xE5B4, 0x87EF, 0xE5B2, 0x87F2, 0xE5B3, 0x87F6, 0xE5B8, 0x87F7, 0xE5B9, 0x87F9, 0x8A49, 0x87FB, 0x8B61, 0x87FE, 0xE5B7, + 0x8805, 0xE5A2, 0x8807, 0xFBA1, 0x880D, 0xE5B6, 0x880E, 0xE5BA, 0x880F, 0xE5B5, 0x8811, 0xE5BC, 0x8815, 0xE5BE, 0x8816, 0xE5BD, + 0x8821, 0xE5C0, 0x8822, 0xE5BF, 0x8823, 0xE579, 0x8827, 0xE5C4, 0x8831, 0xE5C1, 0x8836, 0xE5C2, 0x8839, 0xE5C3, 0x883B, 0xE5C5, + 0x8840, 0x8C8C, 0x8842, 0xE5C7, 0x8844, 0xE5C6, 0x8846, 0x8F4F, 0x884C, 0x8D73, 0x884D, 0x9FA5, 0x8852, 0xE5C8, 0x8853, 0x8F70, + 0x8857, 0x8A58, 0x8859, 0xE5C9, 0x885B, 0x8971, 0x885D, 0x8FD5, 0x885E, 0xE5CA, 0x8861, 0x8D74, 0x8862, 0xE5CB, 0x8863, 0x88DF, + 0x8868, 0x955C, 0x886B, 0xE5CC, 0x8870, 0x908A, 0x8872, 0xE5D3, 0x8875, 0xE5D0, 0x8877, 0x928F, 0x887D, 0xE5D1, 0x887E, 0xE5CE, + 0x887F, 0x8BDC, 0x8881, 0xE5CD, 0x8882, 0xE5D4, 0x8888, 0x8C55, 0x888B, 0x91DC, 0x888D, 0xE5DA, 0x8892, 0xE5D6, 0x8896, 0x91B3, + 0x8897, 0xE5D5, 0x8899, 0xE5D8, 0x889E, 0xE5CF, 0x88A2, 0xE5D9, 0x88A4, 0xE5DB, 0x88AB, 0x94ED, 0x88AE, 0xE5D7, 0x88B0, 0xE5DC, + 0x88B1, 0xE5DE, 0x88B4, 0x8CD1, 0x88B5, 0xE5D2, 0x88B7, 0x88BF, 0x88BF, 0xE5DD, 0x88C1, 0x8DD9, 0x88C2, 0x97F4, 0x88C3, 0xE5DF, + 0x88C4, 0xE5E0, 0x88C5, 0x9195, 0x88CF, 0x97A0, 0x88D4, 0xE5E1, 0x88D5, 0x9754, 0x88D8, 0xE5E2, 0x88D9, 0xE5E3, 0x88DC, 0x95E2, + 0x88DD, 0xE5E4, 0x88DF, 0x8DBE, 0x88E1, 0x97A1, 0x88E8, 0xE5E9, 0x88F2, 0xE5EA, 0x88F3, 0x8FD6, 0x88F4, 0xE5E8, 0x88F5, 0xFBA2, + 0x88F8, 0x9787, 0x88F9, 0xE5E5, 0x88FC, 0xE5E7, 0x88FD, 0x90BB, 0x88FE, 0x909E, 0x8902, 0xE5E6, 0x8904, 0xE5EB, 0x8907, 0x95A1, + 0x890A, 0xE5ED, 0x890C, 0xE5EC, 0x8910, 0x8A8C, 0x8912, 0x964A, 0x8913, 0xE5EE, 0x891C, 0xFA5D, 0x891D, 0xE5FA, 0x891E, 0xE5F0, + 0x8925, 0xE5F1, 0x892A, 0xE5F2, 0x892B, 0xE5F3, 0x8936, 0xE5F7, 0x8938, 0xE5F8, 0x893B, 0xE5F6, 0x8941, 0xE5F4, 0x8943, 0xE5EF, + 0x8944, 0xE5F5, 0x894C, 0xE5F9, 0x894D, 0xE8B5, 0x8956, 0x89A6, 0x895E, 0xE5FC, 0x895F, 0x8BDD, 0x8960, 0xE5FB, 0x8964, 0xE641, + 0x8966, 0xE640, 0x896A, 0xE643, 0x896D, 0xE642, 0x896F, 0xE644, 0x8972, 0x8F50, 0x8974, 0xE645, 0x8977, 0xE646, 0x897E, 0xE647, + 0x897F, 0x90BC, 0x8981, 0x9776, 0x8983, 0xE648, 0x8986, 0x95A2, 0x8987, 0x9465, 0x8988, 0xE649, 0x898A, 0xE64A, 0x898B, 0x8CA9, + 0x898F, 0x8B4B, 0x8993, 0xE64B, 0x8996, 0x8E8B, 0x8997, 0x9460, 0x8998, 0xE64C, 0x899A, 0x8A6F, 0x89A1, 0xE64D, 0x89A6, 0xE64F, + 0x89A7, 0x9797, 0x89A9, 0xE64E, 0x89AA, 0x9065, 0x89AC, 0xE650, 0x89AF, 0xE651, 0x89B2, 0xE652, 0x89B3, 0x8ACF, 0x89BA, 0xE653, + 0x89BD, 0xE654, 0x89BF, 0xE655, 0x89C0, 0xE656, 0x89D2, 0x8A70, 0x89DA, 0xE657, 0x89DC, 0xE658, 0x89DD, 0xE659, 0x89E3, 0x89F0, + 0x89E6, 0x9047, 0x89E7, 0xE65A, 0x89F4, 0xE65B, 0x89F8, 0xE65C, 0x8A00, 0x8CBE, 0x8A02, 0x92F9, 0x8A03, 0xE65D, 0x8A08, 0x8C76, + 0x8A0A, 0x9075, 0x8A0C, 0xE660, 0x8A0E, 0x93A2, 0x8A10, 0xE65F, 0x8A12, 0xFBA3, 0x8A13, 0x8C50, 0x8A16, 0xE65E, 0x8A17, 0x91F5, + 0x8A18, 0x8B4C, 0x8A1B, 0xE661, 0x8A1D, 0xE662, 0x8A1F, 0x8FD7, 0x8A23, 0x8C8D, 0x8A25, 0xE663, 0x8A2A, 0x964B, 0x8A2D, 0x90DD, + 0x8A31, 0x8B96, 0x8A33, 0x96F3, 0x8A34, 0x9169, 0x8A36, 0xE664, 0x8A37, 0xFBA4, 0x8A3A, 0x9066, 0x8A3B, 0x9290, 0x8A3C, 0x8FD8, + 0x8A41, 0xE665, 0x8A46, 0xE668, 0x8A48, 0xE669, 0x8A50, 0x8DBC, 0x8A51, 0x91C0, 0x8A52, 0xE667, 0x8A54, 0x8FD9, 0x8A55, 0x955D, + 0x8A5B, 0xE666, 0x8A5E, 0x8E8C, 0x8A60, 0x8972, 0x8A62, 0xE66D, 0x8A63, 0x8C77, 0x8A66, 0x8E8E, 0x8A69, 0x8E8D, 0x8A6B, 0x986C, + 0x8A6C, 0xE66C, 0x8A6D, 0xE66B, 0x8A6E, 0x9146, 0x8A70, 0x8B6C, 0x8A71, 0x9862, 0x8A72, 0x8A59, 0x8A73, 0x8FDA, 0x8A79, 0xFBA5, + 0x8A7C, 0xE66A, 0x8A82, 0xE66F, 0x8A84, 0xE670, 0x8A85, 0xE66E, 0x8A87, 0x8CD6, 0x8A89, 0x975F, 0x8A8C, 0x8E8F, 0x8A8D, 0x9446, + 0x8A91, 0xE673, 0x8A93, 0x90BE, 0x8A95, 0x9261, 0x8A98, 0x9755, 0x8A9A, 0xE676, 0x8A9E, 0x8CEA, 0x8AA0, 0x90BD, 0x8AA1, 0xE672, + 0x8AA3, 0xE677, 0x8AA4, 0x8CEB, 0x8AA5, 0xE674, 0x8AA6, 0xE675, 0x8AA7, 0xFBA6, 0x8AA8, 0xE671, 0x8AAC, 0x90E0, 0x8AAD, 0x93C7, + 0x8AB0, 0x924E, 0x8AB2, 0x89DB, 0x8AB9, 0x94EE, 0x8ABC, 0x8B62, 0x8ABE, 0xFBA7, 0x8ABF, 0x92B2, 0x8AC2, 0xE67A, 0x8AC4, 0xE678, + 0x8AC7, 0x926B, 0x8ACB, 0x90BF, 0x8ACC, 0x8AD0, 0x8ACD, 0xE679, 0x8ACF, 0x907A, 0x8AD2, 0x97C8, 0x8AD6, 0x985F, 0x8ADA, 0xE67B, + 0x8ADB, 0xE687, 0x8ADC, 0x92B3, 0x8ADE, 0xE686, 0x8ADF, 0xFBA8, 0x8AE0, 0xE683, 0x8AE1, 0xE68B, 0x8AE2, 0xE684, 0x8AE4, 0xE680, + 0x8AE6, 0x92FA, 0x8AE7, 0xE67E, 0x8AEB, 0xE67C, 0x8AED, 0x9740, 0x8AEE, 0x8E90, 0x8AF1, 0xE681, 0x8AF3, 0xE67D, 0x8AF6, 0xFBAA, + 0x8AF7, 0xE685, 0x8AF8, 0x8F94, 0x8AFA, 0x8CBF, 0x8AFE, 0x91F8, 0x8B00, 0x9664, 0x8B01, 0x8979, 0x8B02, 0x88E0, 0x8B04, 0x93A3, + 0x8B07, 0xE689, 0x8B0C, 0xE688, 0x8B0E, 0x93E4, 0x8B10, 0xE68D, 0x8B14, 0xE682, 0x8B16, 0xE68C, 0x8B17, 0xE68E, 0x8B19, 0x8CAA, + 0x8B1A, 0xE68A, 0x8B1B, 0x8D75, 0x8B1D, 0x8ED3, 0x8B20, 0xE68F, 0x8B21, 0x9777, 0x8B26, 0xE692, 0x8B28, 0xE695, 0x8B2B, 0xE693, + 0x8B2C, 0x9554, 0x8B33, 0xE690, 0x8B39, 0x8BDE, 0x8B3E, 0xE694, 0x8B41, 0xE696, 0x8B49, 0xE69A, 0x8B4C, 0xE697, 0x8B4E, 0xE699, + 0x8B4F, 0xE698, 0x8B53, 0xFBAB, 0x8B56, 0xE69B, 0x8B58, 0x8EAF, 0x8B5A, 0xE69D, 0x8B5B, 0xE69C, 0x8B5C, 0x9588, 0x8B5F, 0xE69F, + 0x8B66, 0x8C78, 0x8B6B, 0xE69E, 0x8B6C, 0xE6A0, 0x8B6F, 0xE6A1, 0x8B70, 0x8B63, 0x8B71, 0xE3BF, 0x8B72, 0x8FF7, 0x8B74, 0xE6A2, + 0x8B77, 0x8CEC, 0x8B7D, 0xE6A3, 0x8B7F, 0xFBAC, 0x8B80, 0xE6A4, 0x8B83, 0x8E5D, 0x8B8A, 0x9DCC, 0x8B8C, 0xE6A5, 0x8B8E, 0xE6A6, + 0x8B90, 0x8F51, 0x8B92, 0xE6A7, 0x8B93, 0xE6A8, 0x8B96, 0xE6A9, 0x8B99, 0xE6AA, 0x8B9A, 0xE6AB, 0x8C37, 0x924A, 0x8C3A, 0xE6AC, + 0x8C3F, 0xE6AE, 0x8C41, 0xE6AD, 0x8C46, 0x93A4, 0x8C48, 0xE6AF, 0x8C4A, 0x964C, 0x8C4C, 0xE6B0, 0x8C4E, 0xE6B1, 0x8C50, 0xE6B2, + 0x8C55, 0xE6B3, 0x8C5A, 0x93D8, 0x8C61, 0x8FDB, 0x8C62, 0xE6B4, 0x8C6A, 0x8D8B, 0x8C6B, 0x98AC, 0x8C6C, 0xE6B5, 0x8C78, 0xE6B6, + 0x8C79, 0x955E, 0x8C7A, 0xE6B7, 0x8C7C, 0xE6BF, 0x8C82, 0xE6B8, 0x8C85, 0xE6BA, 0x8C89, 0xE6B9, 0x8C8A, 0xE6BB, 0x8C8C, 0x9665, + 0x8C8D, 0xE6BC, 0x8C8E, 0xE6BD, 0x8C94, 0xE6BE, 0x8C98, 0xE6C0, 0x8C9D, 0x8A4C, 0x8C9E, 0x92E5, 0x8CA0, 0x9589, 0x8CA1, 0x8DE0, + 0x8CA2, 0x8D76, 0x8CA7, 0x956E, 0x8CA8, 0x89DD, 0x8CA9, 0x94CC, 0x8CAA, 0xE6C3, 0x8CAB, 0x8AD1, 0x8CAC, 0x90D3, 0x8CAD, 0xE6C2, + 0x8CAE, 0xE6C7, 0x8CAF, 0x9299, 0x8CB0, 0x96E1, 0x8CB2, 0xE6C5, 0x8CB3, 0xE6C6, 0x8CB4, 0x8B4D, 0x8CB6, 0xE6C8, 0x8CB7, 0x9483, + 0x8CB8, 0x91DD, 0x8CBB, 0x94EF, 0x8CBC, 0x935C, 0x8CBD, 0xE6C4, 0x8CBF, 0x9666, 0x8CC0, 0x89EA, 0x8CC1, 0xE6CA, 0x8CC2, 0x9847, + 0x8CC3, 0x92C0, 0x8CC4, 0x9864, 0x8CC7, 0x8E91, 0x8CC8, 0xE6C9, 0x8CCA, 0x91AF, 0x8CCD, 0xE6DA, 0x8CCE, 0x9147, 0x8CD1, 0x93F6, + 0x8CD3, 0x956F, 0x8CDA, 0xE6CD, 0x8CDB, 0x8E5E, 0x8CDC, 0x8E92, 0x8CDE, 0x8FDC, 0x8CE0, 0x9485, 0x8CE2, 0x8CAB, 0x8CE3, 0xE6CC, + 0x8CE4, 0xE6CB, 0x8CE6, 0x958A, 0x8CEA, 0x8EBF, 0x8CED, 0x9371, 0x8CF0, 0xFBAD, 0x8CF4, 0xFBAE, 0x8CFA, 0xE6CF, 0x8CFB, 0xE6D0, + 0x8CFC, 0x8D77, 0x8CFD, 0xE6CE, 0x8D04, 0xE6D1, 0x8D05, 0xE6D2, 0x8D07, 0xE6D4, 0x8D08, 0x91A1, 0x8D0A, 0xE6D3, 0x8D0B, 0x8AE4, + 0x8D0D, 0xE6D6, 0x8D0F, 0xE6D5, 0x8D10, 0xE6D7, 0x8D12, 0xFBAF, 0x8D13, 0xE6D9, 0x8D14, 0xE6DB, 0x8D16, 0xE6DC, 0x8D64, 0x90D4, + 0x8D66, 0x8ECD, 0x8D67, 0xE6DD, 0x8D6B, 0x8A71, 0x8D6D, 0xE6DE, 0x8D70, 0x9196, 0x8D71, 0xE6DF, 0x8D73, 0xE6E0, 0x8D74, 0x958B, + 0x8D76, 0xFBB0, 0x8D77, 0x8B4E, 0x8D81, 0xE6E1, 0x8D85, 0x92B4, 0x8D8A, 0x897A, 0x8D99, 0xE6E2, 0x8DA3, 0x8EEF, 0x8DA8, 0x9096, + 0x8DB3, 0x91AB, 0x8DBA, 0xE6E5, 0x8DBE, 0xE6E4, 0x8DC2, 0xE6E3, 0x8DCB, 0xE6EB, 0x8DCC, 0xE6E9, 0x8DCF, 0xE6E6, 0x8DD6, 0xE6E8, + 0x8DDA, 0xE6E7, 0x8DDB, 0xE6EA, 0x8DDD, 0x8B97, 0x8DDF, 0xE6EE, 0x8DE1, 0x90D5, 0x8DE3, 0xE6EF, 0x8DE8, 0x8CD7, 0x8DEA, 0xE6EC, + 0x8DEB, 0xE6ED, 0x8DEF, 0x9848, 0x8DF3, 0x92B5, 0x8DF5, 0x9148, 0x8DFC, 0xE6F0, 0x8DFF, 0xE6F3, 0x8E08, 0xE6F1, 0x8E09, 0xE6F2, + 0x8E0A, 0x9778, 0x8E0F, 0x93A5, 0x8E10, 0xE6F6, 0x8E1D, 0xE6F4, 0x8E1E, 0xE6F5, 0x8E1F, 0xE6F7, 0x8E2A, 0xE748, 0x8E30, 0xE6FA, + 0x8E34, 0xE6FB, 0x8E35, 0xE6F9, 0x8E42, 0xE6F8, 0x8E44, 0x92FB, 0x8E47, 0xE740, 0x8E48, 0xE744, 0x8E49, 0xE741, 0x8E4A, 0xE6FC, + 0x8E4C, 0xE742, 0x8E50, 0xE743, 0x8E55, 0xE74A, 0x8E59, 0xE745, 0x8E5F, 0x90D6, 0x8E60, 0xE747, 0x8E63, 0xE749, 0x8E64, 0xE746, + 0x8E72, 0xE74C, 0x8E74, 0x8F52, 0x8E76, 0xE74B, 0x8E7C, 0xE74D, 0x8E81, 0xE74E, 0x8E84, 0xE751, 0x8E85, 0xE750, 0x8E87, 0xE74F, + 0x8E8A, 0xE753, 0x8E8B, 0xE752, 0x8E8D, 0x96F4, 0x8E91, 0xE755, 0x8E93, 0xE754, 0x8E94, 0xE756, 0x8E99, 0xE757, 0x8EA1, 0xE759, + 0x8EAA, 0xE758, 0x8EAB, 0x9067, 0x8EAC, 0xE75A, 0x8EAF, 0x8BEB, 0x8EB0, 0xE75B, 0x8EB1, 0xE75D, 0x8EBE, 0xE75E, 0x8EC5, 0xE75F, + 0x8EC6, 0xE75C, 0x8EC8, 0xE760, 0x8ECA, 0x8ED4, 0x8ECB, 0xE761, 0x8ECC, 0x8B4F, 0x8ECD, 0x8C52, 0x8ECF, 0xFBB2, 0x8ED2, 0x8CAC, + 0x8EDB, 0xE762, 0x8EDF, 0x93EE, 0x8EE2, 0x935D, 0x8EE3, 0xE763, 0x8EEB, 0xE766, 0x8EF8, 0x8EB2, 0x8EFB, 0xE765, 0x8EFC, 0xE764, + 0x8EFD, 0x8C79, 0x8EFE, 0xE767, 0x8F03, 0x8A72, 0x8F05, 0xE769, 0x8F09, 0x8DDA, 0x8F0A, 0xE768, 0x8F0C, 0xE771, 0x8F12, 0xE76B, + 0x8F13, 0xE76D, 0x8F14, 0x95E3, 0x8F15, 0xE76A, 0x8F19, 0xE76C, 0x8F1B, 0xE770, 0x8F1C, 0xE76E, 0x8F1D, 0x8B50, 0x8F1F, 0xE76F, + 0x8F26, 0xE772, 0x8F29, 0x9479, 0x8F2A, 0x97D6, 0x8F2F, 0x8F53, 0x8F33, 0xE773, 0x8F38, 0x9741, 0x8F39, 0xE775, 0x8F3B, 0xE774, + 0x8F3E, 0xE778, 0x8F3F, 0x9760, 0x8F42, 0xE777, 0x8F44, 0x8A8D, 0x8F45, 0xE776, 0x8F46, 0xE77B, 0x8F49, 0xE77A, 0x8F4C, 0xE779, + 0x8F4D, 0x9351, 0x8F4E, 0xE77C, 0x8F57, 0xE77D, 0x8F5C, 0xE77E, 0x8F5F, 0x8D8C, 0x8F61, 0x8C44, 0x8F62, 0xE780, 0x8F63, 0xE781, + 0x8F64, 0xE782, 0x8F9B, 0x9068, 0x8F9C, 0xE783, 0x8F9E, 0x8EAB, 0x8F9F, 0xE784, 0x8FA3, 0xE785, 0x8FA7, 0x999F, 0x8FA8, 0x999E, + 0x8FAD, 0xE786, 0x8FAE, 0xE390, 0x8FAF, 0xE787, 0x8FB0, 0x9243, 0x8FB1, 0x904A, 0x8FB2, 0x945F, 0x8FB7, 0xE788, 0x8FBA, 0x95D3, + 0x8FBB, 0x92D2, 0x8FBC, 0x8D9E, 0x8FBF, 0x9248, 0x8FC2, 0x8949, 0x8FC4, 0x9698, 0x8FC5, 0x9076, 0x8FCE, 0x8C7D, 0x8FD1, 0x8BDF, + 0x8FD4, 0x95D4, 0x8FDA, 0xE789, 0x8FE2, 0xE78B, 0x8FE5, 0xE78A, 0x8FE6, 0x89DE, 0x8FE9, 0x93F4, 0x8FEA, 0xE78C, 0x8FEB, 0x9497, + 0x8FED, 0x9352, 0x8FEF, 0xE78D, 0x8FF0, 0x8F71, 0x8FF4, 0xE78F, 0x8FF7, 0x96C0, 0x8FF8, 0xE79E, 0x8FF9, 0xE791, 0x8FFA, 0xE792, + 0x8FFD, 0x92C7, 0x9000, 0x91DE, 0x9001, 0x9197, 0x9003, 0x93A6, 0x9005, 0xE790, 0x9006, 0x8B74, 0x900B, 0xE799, 0x900D, 0xE796, + 0x900E, 0xE7A3, 0x900F, 0x93A7, 0x9010, 0x9280, 0x9011, 0xE793, 0x9013, 0x92FC, 0x9014, 0x9372, 0x9015, 0xE794, 0x9016, 0xE798, + 0x9017, 0x9080, 0x9019, 0x9487, 0x901A, 0x92CA, 0x901D, 0x90C0, 0x901E, 0xE797, 0x901F, 0x91AC, 0x9020, 0x91A2, 0x9021, 0xE795, + 0x9022, 0x88A7, 0x9023, 0x9841, 0x9027, 0xE79A, 0x902E, 0x91DF, 0x9031, 0x8F54, 0x9032, 0x9069, 0x9035, 0xE79C, 0x9036, 0xE79B, + 0x9038, 0x88ED, 0x9039, 0xE79D, 0x903C, 0x954E, 0x903E, 0xE7A5, 0x9041, 0x93D9, 0x9042, 0x908B, 0x9045, 0x9278, 0x9047, 0x8BF6, + 0x9049, 0xE7A4, 0x904A, 0x9756, 0x904B, 0x895E, 0x904D, 0x95D5, 0x904E, 0x89DF, 0x904F, 0xE79F, 0x9050, 0xE7A0, 0x9051, 0xE7A1, + 0x9052, 0xE7A2, 0x9053, 0x93B9, 0x9054, 0x9242, 0x9055, 0x88E1, 0x9056, 0xE7A6, 0x9058, 0xE7A7, 0x9059, 0xEAA1, 0x905C, 0x91BB, + 0x905E, 0xE7A8, 0x9060, 0x8993, 0x9061, 0x916B, 0x9063, 0x8CAD, 0x9065, 0x9779, 0x9067, 0xFBB5, 0x9068, 0xE7A9, 0x9069, 0x934B, + 0x906D, 0x9198, 0x906E, 0x8ED5, 0x906F, 0xE7AA, 0x9072, 0xE7AD, 0x9075, 0x8F85, 0x9076, 0xE7AB, 0x9077, 0x914A, 0x9078, 0x9149, + 0x907A, 0x88E2, 0x907C, 0x97C9, 0x907D, 0xE7AF, 0x907F, 0x94F0, 0x9080, 0xE7B1, 0x9081, 0xE7B0, 0x9082, 0xE7AE, 0x9083, 0xE284, + 0x9084, 0x8AD2, 0x9087, 0xE78E, 0x9089, 0xE7B3, 0x908A, 0xE7B2, 0x908F, 0xE7B4, 0x9091, 0x9757, 0x90A3, 0x93DF, 0x90A6, 0x964D, + 0x90A8, 0xE7B5, 0x90AA, 0x8ED7, 0x90AF, 0xE7B6, 0x90B1, 0xE7B7, 0x90B5, 0xE7B8, 0x90B8, 0x9340, 0x90C1, 0x88E8, 0x90CA, 0x8D78, + 0x90CE, 0x9859, 0x90DB, 0xE7BC, 0x90DE, 0xFBB6, 0x90E1, 0x8C53, 0x90E2, 0xE7B9, 0x90E4, 0xE7BA, 0x90E8, 0x9594, 0x90ED, 0x8A73, + 0x90F5, 0x9758, 0x90F7, 0x8BBD, 0x90FD, 0x9373, 0x9102, 0xE7BD, 0x9112, 0xE7BE, 0x9115, 0xFBB8, 0x9119, 0xE7BF, 0x9127, 0xFBB9, + 0x912D, 0x9341, 0x9130, 0xE7C1, 0x9132, 0xE7C0, 0x9149, 0x93D1, 0x914A, 0xE7C2, 0x914B, 0x8F55, 0x914C, 0x8EDE, 0x914D, 0x947A, + 0x914E, 0x9291, 0x9152, 0x8EF0, 0x9154, 0x908C, 0x9156, 0xE7C3, 0x9158, 0xE7C4, 0x9162, 0x907C, 0x9163, 0xE7C5, 0x9165, 0xE7C6, + 0x9169, 0xE7C7, 0x916A, 0x978F, 0x916C, 0x8F56, 0x9172, 0xE7C9, 0x9173, 0xE7C8, 0x9175, 0x8D79, 0x9177, 0x8D93, 0x9178, 0x8E5F, + 0x9182, 0xE7CC, 0x9187, 0x8F86, 0x9189, 0xE7CB, 0x918B, 0xE7CA, 0x918D, 0x91E7, 0x9190, 0x8CED, 0x9192, 0x90C1, 0x9197, 0x94AE, + 0x919C, 0x8F58, 0x91A2, 0xE7CD, 0x91A4, 0x8FDD, 0x91AA, 0xE7D0, 0x91AB, 0xE7CE, 0x91AF, 0xE7CF, 0x91B4, 0xE7D2, 0x91B5, 0xE7D1, + 0x91B8, 0x8FF8, 0x91BA, 0xE7D3, 0x91C0, 0xE7D4, 0x91C1, 0xE7D5, 0x91C6, 0x94CE, 0x91C7, 0x8DD1, 0x91C8, 0x8EDF, 0x91C9, 0xE7D6, + 0x91CB, 0xE7D7, 0x91CC, 0x97A2, 0x91CD, 0x8F64, 0x91CE, 0x96EC, 0x91CF, 0x97CA, 0x91D0, 0xE7D8, 0x91D1, 0x8BE0, 0x91D6, 0xE7D9, + 0x91D7, 0xFBBB, 0x91D8, 0x9342, 0x91DA, 0xFBBA, 0x91DB, 0xE7DC, 0x91DC, 0x8A98, 0x91DD, 0x906A, 0x91DE, 0xFBBC, 0x91DF, 0xE7DA, + 0x91E1, 0xE7DB, 0x91E3, 0x92DE, 0x91E4, 0xFBBF, 0x91E5, 0xFBC0, 0x91E6, 0x9674, 0x91E7, 0x8BFA, 0x91ED, 0xFBBD, 0x91EE, 0xFBBE, + 0x91F5, 0xE7DE, 0x91F6, 0xE7DF, 0x91FC, 0xE7DD, 0x91FF, 0xE7E1, 0x9206, 0xFBC1, 0x920A, 0xFBC3, 0x920D, 0x93DD, 0x920E, 0x8A62, + 0x9210, 0xFBC2, 0x9211, 0xE7E5, 0x9214, 0xE7E2, 0x9215, 0xE7E4, 0x921E, 0xE7E0, 0x9229, 0xE86E, 0x922C, 0xE7E3, 0x9234, 0x97E9, + 0x9237, 0x8CD8, 0x9239, 0xFBCA, 0x923A, 0xFBC4, 0x923C, 0xFBC6, 0x923F, 0xE7ED, 0x9240, 0xFBC5, 0x9244, 0x9353, 0x9245, 0xE7E8, + 0x9248, 0xE7EB, 0x9249, 0xE7E9, 0x924B, 0xE7EE, 0x924E, 0xFBC7, 0x9250, 0xE7EF, 0x9251, 0xFBC9, 0x9257, 0xE7E7, 0x9259, 0xFBC8, + 0x925A, 0xE7F4, 0x925B, 0x8994, 0x925E, 0xE7E6, 0x9262, 0x94AB, 0x9264, 0xE7EA, 0x9266, 0x8FDE, 0x9267, 0xFBCB, 0x9271, 0x8D7A, + 0x9277, 0xFBCD, 0x9278, 0xFBCE, 0x927E, 0x9667, 0x9280, 0x8BE2, 0x9283, 0x8F65, 0x9285, 0x93BA, 0x9288, 0xFA5F, 0x9291, 0x914C, + 0x9293, 0xE7F2, 0x9295, 0xE7EC, 0x9296, 0xE7F1, 0x9298, 0x96C1, 0x929A, 0x92B6, 0x929B, 0xE7F3, 0x929C, 0xE7F0, 0x92A7, 0xFBCC, + 0x92AD, 0x914B, 0x92B7, 0xE7F7, 0x92B9, 0xE7F6, 0x92CF, 0xE7F5, 0x92D0, 0xFBD2, 0x92D2, 0x964E, 0x92D3, 0xFBD6, 0x92D5, 0xFBD4, + 0x92D7, 0xFBD0, 0x92D9, 0xFBD1, 0x92E0, 0xFBD5, 0x92E4, 0x8F9B, 0x92E7, 0xFBCF, 0x92E9, 0xE7F8, 0x92EA, 0x95DD, 0x92ED, 0x8973, + 0x92F2, 0x9565, 0x92F3, 0x9292, 0x92F8, 0x8B98, 0x92F9, 0xFA65, 0x92FA, 0xE7FA, 0x92FB, 0xFBD9, 0x92FC, 0x8D7C, 0x92FF, 0xFBDC, + 0x9302, 0xFBDE, 0x9306, 0x8E4B, 0x930F, 0xE7F9, 0x9310, 0x908D, 0x9318, 0x908E, 0x9319, 0xE840, 0x931A, 0xE842, 0x931D, 0xFBDD, + 0x931E, 0xFBDB, 0x9320, 0x8FF9, 0x9321, 0xFBD8, 0x9322, 0xE841, 0x9323, 0xE843, 0x9325, 0xFBD7, 0x9326, 0x8BD1, 0x9328, 0x9564, + 0x932B, 0x8EE0, 0x932C, 0x9842, 0x932E, 0xE7FC, 0x932F, 0x8DF6, 0x9332, 0x985E, 0x9335, 0xE845, 0x933A, 0xE844, 0x933B, 0xE846, + 0x9344, 0xE7FB, 0x9348, 0xFA5E, 0x934B, 0x93E7, 0x934D, 0x9374, 0x9354, 0x92D5, 0x9356, 0xE84B, 0x9357, 0xFBE0, 0x935B, 0x9262, + 0x935C, 0xE847, 0x9360, 0xE848, 0x936C, 0x8C4C, 0x936E, 0xE84A, 0x9370, 0xFBDF, 0x9375, 0x8CAE, 0x937C, 0xE849, 0x937E, 0x8FDF, + 0x938C, 0x8A99, 0x9394, 0xE84F, 0x9396, 0x8DBD, 0x9397, 0x9199, 0x939A, 0x92C8, 0x93A4, 0xFBE1, 0x93A7, 0x8A5A, 0x93AC, 0xE84D, + 0x93AD, 0xE84E, 0x93AE, 0x92C1, 0x93B0, 0xE84C, 0x93B9, 0xE850, 0x93C3, 0xE856, 0x93C6, 0xFBE2, 0x93C8, 0xE859, 0x93D0, 0xE858, + 0x93D1, 0x934C, 0x93D6, 0xE851, 0x93D7, 0xE852, 0x93D8, 0xE855, 0x93DD, 0xE857, 0x93DE, 0xFBE3, 0x93E1, 0x8BBE, 0x93E4, 0xE85A, + 0x93E5, 0xE854, 0x93E8, 0xE853, 0x93F8, 0xFBE4, 0x9403, 0xE85E, 0x9407, 0xE85F, 0x9410, 0xE860, 0x9413, 0xE85D, 0x9414, 0xE85C, + 0x9418, 0x8FE0, 0x9419, 0x93A8, 0x941A, 0xE85B, 0x9421, 0xE864, 0x942B, 0xE862, 0x9431, 0xFBE5, 0x9435, 0xE863, 0x9436, 0xE861, + 0x9438, 0x91F6, 0x943A, 0xE865, 0x9441, 0xE866, 0x9444, 0xE868, 0x9445, 0xFBE6, 0x9448, 0xFBE7, 0x9451, 0x8AD3, 0x9452, 0xE867, + 0x9453, 0x96F8, 0x945A, 0xE873, 0x945B, 0xE869, 0x945E, 0xE86C, 0x9460, 0xE86A, 0x9462, 0xE86B, 0x946A, 0xE86D, 0x9470, 0xE86F, + 0x9475, 0xE870, 0x9477, 0xE871, 0x947C, 0xE874, 0x947D, 0xE872, 0x947E, 0xE875, 0x947F, 0xE877, 0x9481, 0xE876, 0x9577, 0x92B7, + 0x9580, 0x96E5, 0x9582, 0xE878, 0x9583, 0x914D, 0x9587, 0xE879, 0x9589, 0x95C2, 0x958A, 0xE87A, 0x958B, 0x8A4A, 0x958F, 0x895B, + 0x9591, 0x8AD5, 0x9592, 0xFBE8, 0x9593, 0x8AD4, 0x9594, 0xE87B, 0x9596, 0xE87C, 0x9598, 0xE87D, 0x9599, 0xE87E, 0x95A0, 0xE880, + 0x95A2, 0x8AD6, 0x95A3, 0x8A74, 0x95A4, 0x8D7D, 0x95A5, 0x94B4, 0x95A7, 0xE882, 0x95A8, 0xE881, 0x95AD, 0xE883, 0x95B2, 0x897B, + 0x95B9, 0xE886, 0x95BB, 0xE885, 0x95BC, 0xE884, 0x95BE, 0xE887, 0x95C3, 0xE88A, 0x95C7, 0x88C5, 0x95CA, 0xE888, 0x95CC, 0xE88C, + 0x95CD, 0xE88B, 0x95D4, 0xE88E, 0x95D5, 0xE88D, 0x95D6, 0xE88F, 0x95D8, 0x93AC, 0x95DC, 0xE890, 0x95E1, 0xE891, 0x95E2, 0xE893, + 0x95E5, 0xE892, 0x961C, 0x958C, 0x9621, 0xE894, 0x9628, 0xE895, 0x962A, 0x8DE3, 0x962E, 0xE896, 0x962F, 0xE897, 0x9632, 0x9668, + 0x963B, 0x916A, 0x963F, 0x88A2, 0x9640, 0x91C9, 0x9642, 0xE898, 0x9644, 0x958D, 0x964B, 0xE89B, 0x964C, 0xE899, 0x964D, 0x8D7E, + 0x964F, 0xE89A, 0x9650, 0x8CC0, 0x965B, 0x95C3, 0x965C, 0xE89D, 0x965D, 0xE89F, 0x965E, 0xE89E, 0x965F, 0xE8A0, 0x9662, 0x8940, + 0x9663, 0x9077, 0x9664, 0x8F9C, 0x9665, 0x8AD7, 0x9666, 0xE8A1, 0x966A, 0x9486, 0x966C, 0xE8A3, 0x9670, 0x8941, 0x9672, 0xE8A2, + 0x9673, 0x92C2, 0x9675, 0x97CB, 0x9676, 0x93A9, 0x9677, 0xE89C, 0x9678, 0x97A4, 0x967A, 0x8CAF, 0x967D, 0x977A, 0x9685, 0x8BF7, + 0x9686, 0x97B2, 0x9688, 0x8C47, 0x968A, 0x91E0, 0x968B, 0xE440, 0x968D, 0xE8A4, 0x968E, 0x8A4B, 0x968F, 0x908F, 0x9694, 0x8A75, + 0x9695, 0xE8A6, 0x9697, 0xE8A7, 0x9698, 0xE8A5, 0x9699, 0x8C84, 0x969B, 0x8DDB, 0x969C, 0x8FE1, 0x969D, 0xFBEB, 0x96A0, 0x8942, + 0x96A3, 0x97D7, 0x96A7, 0xE8A9, 0x96A8, 0xE7AC, 0x96AA, 0xE8A8, 0x96AF, 0xFBEC, 0x96B0, 0xE8AC, 0x96B1, 0xE8AA, 0x96B2, 0xE8AB, + 0x96B4, 0xE8AD, 0x96B6, 0xE8AE, 0x96B7, 0x97EA, 0x96B8, 0xE8AF, 0x96B9, 0xE8B0, 0x96BB, 0x90C7, 0x96BC, 0x94B9, 0x96C0, 0x909D, + 0x96C1, 0x8AE5, 0x96C4, 0x9759, 0x96C5, 0x89EB, 0x96C6, 0x8F57, 0x96C7, 0x8CD9, 0x96C9, 0xE8B3, 0x96CB, 0xE8B2, 0x96CC, 0x8E93, + 0x96CD, 0xE8B4, 0x96CE, 0xE8B1, 0x96D1, 0x8E47, 0x96D5, 0xE8B8, 0x96D6, 0xE5AB, 0x96D9, 0x99D4, 0x96DB, 0x9097, 0x96DC, 0xE8B6, + 0x96E2, 0x97A3, 0x96E3, 0x93EF, 0x96E8, 0x894A, 0x96EA, 0x90E1, 0x96EB, 0x8EB4, 0x96F0, 0x95B5, 0x96F2, 0x895F, 0x96F6, 0x97EB, + 0x96F7, 0x978B, 0x96F9, 0xE8B9, 0x96FB, 0x9364, 0x9700, 0x8EF9, 0x9704, 0xE8BA, 0x9706, 0xE8BB, 0x9707, 0x906B, 0x9708, 0xE8BC, + 0x970A, 0x97EC, 0x970D, 0xE8B7, 0x970E, 0xE8BE, 0x970F, 0xE8C0, 0x9711, 0xE8BF, 0x9713, 0xE8BD, 0x9716, 0xE8C1, 0x9719, 0xE8C2, + 0x971C, 0x919A, 0x971E, 0x89E0, 0x9724, 0xE8C3, 0x9727, 0x96B6, 0x972A, 0xE8C4, 0x9730, 0xE8C5, 0x9732, 0x9849, 0x9733, 0xFBED, + 0x9738, 0x9E50, 0x9739, 0xE8C6, 0x973B, 0xFBEE, 0x973D, 0xE8C7, 0x973E, 0xE8C8, 0x9742, 0xE8CC, 0x9743, 0xFBEF, 0x9744, 0xE8C9, + 0x9746, 0xE8CA, 0x9748, 0xE8CB, 0x9749, 0xE8CD, 0x974D, 0xFBF0, 0x974F, 0xFBF1, 0x9751, 0xFBF2, 0x9752, 0x90C2, 0x9755, 0xFBF3, + 0x9756, 0x96F5, 0x9759, 0x90C3, 0x975C, 0xE8CE, 0x975E, 0x94F1, 0x9760, 0xE8CF, 0x9761, 0xEA72, 0x9762, 0x96CA, 0x9764, 0xE8D0, + 0x9766, 0xE8D1, 0x9768, 0xE8D2, 0x9769, 0x8A76, 0x976B, 0xE8D4, 0x976D, 0x9078, 0x9771, 0xE8D5, 0x9774, 0x8C43, 0x9779, 0xE8D6, + 0x977A, 0xE8DA, 0x977C, 0xE8D8, 0x9781, 0xE8D9, 0x9784, 0x8A93, 0x9785, 0xE8D7, 0x9786, 0xE8DB, 0x978B, 0xE8DC, 0x978D, 0x88C6, + 0x978F, 0xE8DD, 0x9790, 0xE8DE, 0x9798, 0x8FE2, 0x979C, 0xE8DF, 0x97A0, 0x8B66, 0x97A3, 0xE8E2, 0x97A6, 0xE8E1, 0x97A8, 0xE8E0, + 0x97AB, 0xE691, 0x97AD, 0x95DA, 0x97B3, 0xE8E3, 0x97B4, 0xE8E4, 0x97C3, 0xE8E5, 0x97C6, 0xE8E6, 0x97C8, 0xE8E7, 0x97CB, 0xE8E8, + 0x97D3, 0x8AD8, 0x97DC, 0xE8E9, 0x97ED, 0xE8EA, 0x97EE, 0x9442, 0x97F2, 0xE8EC, 0x97F3, 0x89B9, 0x97F5, 0xE8EF, 0x97F6, 0xE8EE, + 0x97FB, 0x8943, 0x97FF, 0x8BBF, 0x9801, 0x95C5, 0x9802, 0x92B8, 0x9803, 0x8DA0, 0x9805, 0x8D80, 0x9806, 0x8F87, 0x9808, 0x907B, + 0x980C, 0xE8F1, 0x980F, 0xE8F0, 0x9810, 0x9761, 0x9811, 0x8AE6, 0x9812, 0x94D0, 0x9813, 0x93DA, 0x9817, 0x909C, 0x9818, 0x97CC, + 0x981A, 0x8C7A, 0x9821, 0xE8F4, 0x9824, 0xE8F3, 0x982C, 0x966A, 0x982D, 0x93AA, 0x9834, 0x896F, 0x9837, 0xE8F5, 0x9838, 0xE8F2, + 0x983B, 0x9570, 0x983C, 0x978A, 0x983D, 0xE8F6, 0x9846, 0xE8F7, 0x984B, 0xE8F9, 0x984C, 0x91E8, 0x984D, 0x8A7A, 0x984E, 0x8A7B, + 0x984F, 0xE8F8, 0x9854, 0x8AE7, 0x9855, 0x8CB0, 0x9857, 0xFBF4, 0x9858, 0x8AE8, 0x985B, 0x935E, 0x985E, 0x97DE, 0x9865, 0xFBF5, + 0x9867, 0x8CDA, 0x986B, 0xE8FA, 0x986F, 0xE8FB, 0x9870, 0xE8FC, 0x9871, 0xE940, 0x9873, 0xE942, 0x9874, 0xE941, 0x98A8, 0x9597, + 0x98AA, 0xE943, 0x98AF, 0xE944, 0x98B1, 0xE945, 0x98B6, 0xE946, 0x98C3, 0xE948, 0x98C4, 0xE947, 0x98C6, 0xE949, 0x98DB, 0x94F2, + 0x98DC, 0xE3CA, 0x98DF, 0x9048, 0x98E2, 0x8B51, 0x98E9, 0xE94A, 0x98EB, 0xE94B, 0x98ED, 0x99AA, 0x98EE, 0x9F5A, 0x98EF, 0x94D1, + 0x98F2, 0x88F9, 0x98F4, 0x88B9, 0x98FC, 0x8E94, 0x98FD, 0x964F, 0x98FE, 0x8FFC, 0x9903, 0xE94C, 0x9905, 0x96DD, 0x9909, 0xE94D, + 0x990A, 0x977B, 0x990C, 0x8961, 0x9910, 0x8E60, 0x9912, 0xE94E, 0x9913, 0x89EC, 0x9914, 0xE94F, 0x9918, 0xE950, 0x991D, 0xE952, + 0x991E, 0xE953, 0x9920, 0xE955, 0x9921, 0xE951, 0x9924, 0xE954, 0x9927, 0xFBF8, 0x9928, 0x8AD9, 0x992C, 0xE956, 0x992E, 0xE957, + 0x993D, 0xE958, 0x993E, 0xE959, 0x9942, 0xE95A, 0x9945, 0xE95C, 0x9949, 0xE95B, 0x994B, 0xE95E, 0x994C, 0xE961, 0x9950, 0xE95D, + 0x9951, 0xE95F, 0x9952, 0xE960, 0x9955, 0xE962, 0x9957, 0x8BC0, 0x9996, 0x8EF1, 0x9997, 0xE963, 0x9998, 0xE964, 0x9999, 0x8D81, + 0x999E, 0xFBFA, 0x99A5, 0xE965, 0x99A8, 0x8A5D, 0x99AC, 0x946E, 0x99AD, 0xE966, 0x99AE, 0xE967, 0x99B3, 0x9279, 0x99B4, 0x93E9, + 0x99BC, 0xE968, 0x99C1, 0x949D, 0x99C4, 0x91CA, 0x99C5, 0x8977, 0x99C6, 0x8BEC, 0x99C8, 0x8BED, 0x99D0, 0x9293, 0x99D1, 0xE96D, + 0x99D2, 0x8BEE, 0x99D5, 0x89ED, 0x99D8, 0xE96C, 0x99DB, 0xE96A, 0x99DD, 0xE96B, 0x99DF, 0xE969, 0x99E2, 0xE977, 0x99ED, 0xE96E, + 0x99EE, 0xE96F, 0x99F1, 0xE970, 0x99F2, 0xE971, 0x99F8, 0xE973, 0x99FB, 0xE972, 0x99FF, 0x8F78, 0x9A01, 0xE974, 0x9A05, 0xE976, + 0x9A0E, 0x8B52, 0x9A0F, 0xE975, 0x9A12, 0x919B, 0x9A13, 0x8CB1, 0x9A19, 0xE978, 0x9A28, 0x91CB, 0x9A2B, 0xE979, 0x9A30, 0x93AB, + 0x9A37, 0xE97A, 0x9A3E, 0xE980, 0x9A40, 0xE97D, 0x9A42, 0xE97C, 0x9A43, 0xE97E, 0x9A45, 0xE97B, 0x9A4D, 0xE982, 0x9A4E, 0xFBFB, + 0x9A55, 0xE981, 0x9A57, 0xE984, 0x9A5A, 0x8BC1, 0x9A5B, 0xE983, 0x9A5F, 0xE985, 0x9A62, 0xE986, 0x9A64, 0xE988, 0x9A65, 0xE987, + 0x9A69, 0xE989, 0x9A6A, 0xE98B, 0x9A6B, 0xE98A, 0x9AA8, 0x8D9C, 0x9AAD, 0xE98C, 0x9AB0, 0xE98D, 0x9AB8, 0x8A5B, 0x9ABC, 0xE98E, + 0x9AC0, 0xE98F, 0x9AC4, 0x9091, 0x9ACF, 0xE990, 0x9AD1, 0xE991, 0x9AD3, 0xE992, 0x9AD4, 0xE993, 0x9AD8, 0x8D82, 0x9AD9, 0xFBFC, + 0x9ADC, 0xFC40, 0x9ADE, 0xE994, 0x9ADF, 0xE995, 0x9AE2, 0xE996, 0x9AE3, 0xE997, 0x9AE6, 0xE998, 0x9AEA, 0x94AF, 0x9AEB, 0xE99A, + 0x9AED, 0x9545, 0x9AEE, 0xE99B, 0x9AEF, 0xE999, 0x9AF1, 0xE99D, 0x9AF4, 0xE99C, 0x9AF7, 0xE99E, 0x9AFB, 0xE99F, 0x9B06, 0xE9A0, + 0x9B18, 0xE9A1, 0x9B1A, 0xE9A2, 0x9B1F, 0xE9A3, 0x9B22, 0xE9A4, 0x9B23, 0xE9A5, 0x9B25, 0xE9A6, 0x9B27, 0xE9A7, 0x9B28, 0xE9A8, + 0x9B29, 0xE9A9, 0x9B2A, 0xE9AA, 0x9B2E, 0xE9AB, 0x9B2F, 0xE9AC, 0x9B31, 0x9F54, 0x9B32, 0xE9AD, 0x9B3B, 0xE2F6, 0x9B3C, 0x8B53, + 0x9B41, 0x8A40, 0x9B42, 0x8DB0, 0x9B43, 0xE9AF, 0x9B44, 0xE9AE, 0x9B45, 0x96A3, 0x9B4D, 0xE9B1, 0x9B4E, 0xE9B2, 0x9B4F, 0xE9B0, + 0x9B51, 0xE9B3, 0x9B54, 0x9682, 0x9B58, 0xE9B4, 0x9B5A, 0x8B9B, 0x9B6F, 0x9844, 0x9B72, 0xFC42, 0x9B74, 0xE9B5, 0x9B75, 0xFC41, + 0x9B83, 0xE9B7, 0x9B8E, 0x88BC, 0x9B8F, 0xFC43, 0x9B91, 0xE9B8, 0x9B92, 0x95A9, 0x9B93, 0xE9B6, 0x9B96, 0xE9B9, 0x9B97, 0xE9BA, + 0x9B9F, 0xE9BB, 0x9BA0, 0xE9BC, 0x9BA8, 0xE9BD, 0x9BAA, 0x968E, 0x9BAB, 0x8E4C, 0x9BAD, 0x8DF8, 0x9BAE, 0x914E, 0x9BB1, 0xFC44, + 0x9BB4, 0xE9BE, 0x9BB9, 0xE9C1, 0x9BBB, 0xFC45, 0x9BC0, 0xE9BF, 0x9BC6, 0xE9C2, 0x9BC9, 0x8CEF, 0x9BCA, 0xE9C0, 0x9BCF, 0xE9C3, + 0x9BD1, 0xE9C4, 0x9BD2, 0xE9C5, 0x9BD4, 0xE9C9, 0x9BD6, 0x8E49, 0x9BDB, 0x91E2, 0x9BE1, 0xE9CA, 0x9BE2, 0xE9C7, 0x9BE3, 0xE9C6, + 0x9BE4, 0xE9C8, 0x9BE8, 0x8C7E, 0x9BF0, 0xE9CE, 0x9BF1, 0xE9CD, 0x9BF2, 0xE9CC, 0x9BF5, 0x88B1, 0x9C00, 0xFC46, 0x9C04, 0xE9D8, + 0x9C06, 0xE9D4, 0x9C08, 0xE9D5, 0x9C09, 0xE9D1, 0x9C0A, 0xE9D7, 0x9C0C, 0xE9D3, 0x9C0D, 0x8A82, 0x9C10, 0x986B, 0x9C12, 0xE9D6, + 0x9C13, 0xE9D2, 0x9C14, 0xE9D0, 0x9C15, 0xE9CF, 0x9C1B, 0xE9DA, 0x9C21, 0xE9DD, 0x9C24, 0xE9DC, 0x9C25, 0xE9DB, 0x9C2D, 0x9568, + 0x9C2E, 0xE9D9, 0x9C2F, 0x88F1, 0x9C30, 0xE9DE, 0x9C32, 0xE9E0, 0x9C39, 0x8A8F, 0x9C3A, 0xE9CB, 0x9C3B, 0x8956, 0x9C3E, 0xE9E2, + 0x9C46, 0xE9E1, 0x9C47, 0xE9DF, 0x9C48, 0x924C, 0x9C52, 0x9690, 0x9C57, 0x97D8, 0x9C5A, 0xE9E3, 0x9C60, 0xE9E4, 0x9C67, 0xE9E5, + 0x9C76, 0xE9E6, 0x9C78, 0xE9E7, 0x9CE5, 0x92B9, 0x9CE7, 0xE9E8, 0x9CE9, 0x94B5, 0x9CEB, 0xE9ED, 0x9CEC, 0xE9E9, 0x9CF0, 0xE9EA, + 0x9CF3, 0x9650, 0x9CF4, 0x96C2, 0x9CF6, 0x93CE, 0x9D03, 0xE9EE, 0x9D06, 0xE9EF, 0x9D07, 0x93BC, 0x9D08, 0xE9EC, 0x9D09, 0xE9EB, + 0x9D0E, 0x89A8, 0x9D12, 0xE9F7, 0x9D15, 0xE9F6, 0x9D1B, 0x8995, 0x9D1F, 0xE9F4, 0x9D23, 0xE9F3, 0x9D26, 0xE9F1, 0x9D28, 0x8A9B, + 0x9D2A, 0xE9F0, 0x9D2B, 0x8EB0, 0x9D2C, 0x89A7, 0x9D3B, 0x8D83, 0x9D3E, 0xE9FA, 0x9D3F, 0xE9F9, 0x9D41, 0xE9F8, 0x9D44, 0xE9F5, + 0x9D46, 0xE9FB, 0x9D48, 0xE9FC, 0x9D50, 0xEA44, 0x9D51, 0xEA43, 0x9D59, 0xEA45, 0x9D5C, 0x894C, 0x9D5D, 0xEA40, 0x9D5E, 0xEA41, + 0x9D60, 0x8D94, 0x9D61, 0x96B7, 0x9D64, 0xEA42, 0x9D6B, 0xFC48, 0x9D6C, 0x9651, 0x9D6F, 0xEA4A, 0x9D70, 0xFC47, 0x9D72, 0xEA46, + 0x9D7A, 0xEA4B, 0x9D87, 0xEA48, 0x9D89, 0xEA47, 0x9D8F, 0x8C7B, 0x9D9A, 0xEA4C, 0x9DA4, 0xEA4D, 0x9DA9, 0xEA4E, 0x9DAB, 0xEA49, + 0x9DAF, 0xE9F2, 0x9DB2, 0xEA4F, 0x9DB4, 0x92DF, 0x9DB8, 0xEA53, 0x9DBA, 0xEA54, 0x9DBB, 0xEA52, 0x9DC1, 0xEA51, 0x9DC2, 0xEA57, + 0x9DC4, 0xEA50, 0x9DC6, 0xEA55, 0x9DCF, 0xEA56, 0x9DD3, 0xEA59, 0x9DD9, 0xEA58, 0x9DE6, 0xEA5B, 0x9DED, 0xEA5C, 0x9DEF, 0xEA5D, + 0x9DF2, 0x9868, 0x9DF8, 0xEA5A, 0x9DF9, 0x91E9, 0x9DFA, 0x8DEB, 0x9DFD, 0xEA5E, 0x9E19, 0xFC4A, 0x9E1A, 0xEA5F, 0x9E1B, 0xEA60, + 0x9E1E, 0xEA61, 0x9E75, 0xEA62, 0x9E78, 0x8CB2, 0x9E79, 0xEA63, 0x9E7D, 0xEA64, 0x9E7F, 0x8EAD, 0x9E81, 0xEA65, 0x9E88, 0xEA66, + 0x9E8B, 0xEA67, 0x9E8C, 0xEA68, 0x9E91, 0xEA6B, 0x9E92, 0xEA69, 0x9E93, 0x985B, 0x9E95, 0xEA6A, 0x9E97, 0x97ED, 0x9E9D, 0xEA6C, + 0x9E9F, 0x97D9, 0x9EA5, 0xEA6D, 0x9EA6, 0x949E, 0x9EA9, 0xEA6E, 0x9EAA, 0xEA70, 0x9EAD, 0xEA71, 0x9EB8, 0xEA6F, 0x9EB9, 0x8D8D, + 0x9EBA, 0x96CB, 0x9EBB, 0x9683, 0x9EBC, 0x9BF5, 0x9EBE, 0x9F80, 0x9EBF, 0x969B, 0x9EC4, 0x89A9, 0x9ECC, 0xEA73, 0x9ECD, 0x8B6F, + 0x9ECE, 0xEA74, 0x9ECF, 0xEA75, 0x9ED0, 0xEA76, 0x9ED1, 0xFC4B, 0x9ED2, 0x8D95, 0x9ED4, 0xEA77, 0x9ED8, 0xE0D2, 0x9ED9, 0x96D9, + 0x9EDB, 0x91E1, 0x9EDC, 0xEA78, 0x9EDD, 0xEA7A, 0x9EDE, 0xEA79, 0x9EE0, 0xEA7B, 0x9EE5, 0xEA7C, 0x9EE8, 0xEA7D, 0x9EEF, 0xEA7E, + 0x9EF4, 0xEA80, 0x9EF6, 0xEA81, 0x9EF7, 0xEA82, 0x9EF9, 0xEA83, 0x9EFB, 0xEA84, 0x9EFC, 0xEA85, 0x9EFD, 0xEA86, 0x9F07, 0xEA87, + 0x9F08, 0xEA88, 0x9F0E, 0x9343, 0x9F13, 0x8CDB, 0x9F15, 0xEA8A, 0x9F20, 0x916C, 0x9F21, 0xEA8B, 0x9F2C, 0xEA8C, 0x9F3B, 0x9540, + 0x9F3E, 0xEA8D, 0x9F4A, 0xEA8E, 0x9F4B, 0xE256, 0x9F4E, 0xE6D8, 0x9F4F, 0xE8EB, 0x9F52, 0xEA8F, 0x9F54, 0xEA90, 0x9F5F, 0xEA92, + 0x9F60, 0xEA93, 0x9F61, 0xEA94, 0x9F62, 0x97EE, 0x9F63, 0xEA91, 0x9F66, 0xEA95, 0x9F67, 0xEA96, 0x9F6A, 0xEA98, 0x9F6C, 0xEA97, + 0x9F72, 0xEA9A, 0x9F76, 0xEA9B, 0x9F77, 0xEA99, 0x9F8D, 0x97B4, 0x9F95, 0xEA9C, 0x9F9C, 0xEA9D, 0x9F9D, 0xE273, 0x9FA0, 0xEA9E, + 0xF929, 0xFAE0, 0xF9DC, 0xFBE9, 0xFA0E, 0xFA90, 0xFA0F, 0xFA9B, 0xFA10, 0xFA9C, 0xFA11, 0xFAB1, 0xFA12, 0xFAD8, 0xFA13, 0xFAE8, + 0xFA14, 0xFAEA, 0xFA15, 0xFB58, 0xFA16, 0xFB5E, 0xFA17, 0xFB75, 0xFA18, 0xFB7D, 0xFA19, 0xFB7E, 0xFA1A, 0xFB80, 0xFA1B, 0xFB82, + 0xFA1C, 0xFB86, 0xFA1D, 0xFB89, 0xFA1E, 0xFB92, 0xFA1F, 0xFB9D, 0xFA20, 0xFB9F, 0xFA21, 0xFBA0, 0xFA22, 0xFBA9, 0xFA23, 0xFBB1, + 0xFA24, 0xFBB3, 0xFA25, 0xFBB4, 0xFA26, 0xFBB7, 0xFA27, 0xFBD3, 0xFA28, 0xFBDA, 0xFA29, 0xFBEA, 0xFA2A, 0xFBF6, 0xFA2B, 0xFBF7, + 0xFA2C, 0xFBF9, 0xFA2D, 0xFC49, 0xFF01, 0x8149, 0xFF02, 0xFA57, 0xFF03, 0x8194, 0xFF04, 0x8190, 0xFF05, 0x8193, 0xFF06, 0x8195, + 0xFF07, 0xFA56, 0xFF08, 0x8169, 0xFF09, 0x816A, 0xFF0A, 0x8196, 0xFF0B, 0x817B, 0xFF0C, 0x8143, 0xFF0D, 0x817C, 0xFF0E, 0x8144, + 0xFF0F, 0x815E, 0xFF10, 0x824F, 0xFF11, 0x8250, 0xFF12, 0x8251, 0xFF13, 0x8252, 0xFF14, 0x8253, 0xFF15, 0x8254, 0xFF16, 0x8255, + 0xFF17, 0x8256, 0xFF18, 0x8257, 0xFF19, 0x8258, 0xFF1A, 0x8146, 0xFF1B, 0x8147, 0xFF1C, 0x8183, 0xFF1D, 0x8181, 0xFF1E, 0x8184, + 0xFF1F, 0x8148, 0xFF20, 0x8197, 0xFF21, 0x8260, 0xFF22, 0x8261, 0xFF23, 0x8262, 0xFF24, 0x8263, 0xFF25, 0x8264, 0xFF26, 0x8265, + 0xFF27, 0x8266, 0xFF28, 0x8267, 0xFF29, 0x8268, 0xFF2A, 0x8269, 0xFF2B, 0x826A, 0xFF2C, 0x826B, 0xFF2D, 0x826C, 0xFF2E, 0x826D, + 0xFF2F, 0x826E, 0xFF30, 0x826F, 0xFF31, 0x8270, 0xFF32, 0x8271, 0xFF33, 0x8272, 0xFF34, 0x8273, 0xFF35, 0x8274, 0xFF36, 0x8275, + 0xFF37, 0x8276, 0xFF38, 0x8277, 0xFF39, 0x8278, 0xFF3A, 0x8279, 0xFF3B, 0x816D, 0xFF3C, 0x815F, 0xFF3D, 0x816E, 0xFF3E, 0x814F, + 0xFF3F, 0x8151, 0xFF40, 0x814D, 0xFF41, 0x8281, 0xFF42, 0x8282, 0xFF43, 0x8283, 0xFF44, 0x8284, 0xFF45, 0x8285, 0xFF46, 0x8286, + 0xFF47, 0x8287, 0xFF48, 0x8288, 0xFF49, 0x8289, 0xFF4A, 0x828A, 0xFF4B, 0x828B, 0xFF4C, 0x828C, 0xFF4D, 0x828D, 0xFF4E, 0x828E, + 0xFF4F, 0x828F, 0xFF50, 0x8290, 0xFF51, 0x8291, 0xFF52, 0x8292, 0xFF53, 0x8293, 0xFF54, 0x8294, 0xFF55, 0x8295, 0xFF56, 0x8296, + 0xFF57, 0x8297, 0xFF58, 0x8298, 0xFF59, 0x8299, 0xFF5A, 0x829A, 0xFF5B, 0x816F, 0xFF5C, 0x8162, 0xFF5D, 0x8170, 0xFF5E, 0x8160, + 0xFF61, 0x00A1, 0xFF62, 0x00A2, 0xFF63, 0x00A3, 0xFF64, 0x00A4, 0xFF65, 0x00A5, 0xFF66, 0x00A6, 0xFF67, 0x00A7, 0xFF68, 0x00A8, + 0xFF69, 0x00A9, 0xFF6A, 0x00AA, 0xFF6B, 0x00AB, 0xFF6C, 0x00AC, 0xFF6D, 0x00AD, 0xFF6E, 0x00AE, 0xFF6F, 0x00AF, 0xFF70, 0x00B0, + 0xFF71, 0x00B1, 0xFF72, 0x00B2, 0xFF73, 0x00B3, 0xFF74, 0x00B4, 0xFF75, 0x00B5, 0xFF76, 0x00B6, 0xFF77, 0x00B7, 0xFF78, 0x00B8, + 0xFF79, 0x00B9, 0xFF7A, 0x00BA, 0xFF7B, 0x00BB, 0xFF7C, 0x00BC, 0xFF7D, 0x00BD, 0xFF7E, 0x00BE, 0xFF7F, 0x00BF, 0xFF80, 0x00C0, + 0xFF81, 0x00C1, 0xFF82, 0x00C2, 0xFF83, 0x00C3, 0xFF84, 0x00C4, 0xFF85, 0x00C5, 0xFF86, 0x00C6, 0xFF87, 0x00C7, 0xFF88, 0x00C8, + 0xFF89, 0x00C9, 0xFF8A, 0x00CA, 0xFF8B, 0x00CB, 0xFF8C, 0x00CC, 0xFF8D, 0x00CD, 0xFF8E, 0x00CE, 0xFF8F, 0x00CF, 0xFF90, 0x00D0, + 0xFF91, 0x00D1, 0xFF92, 0x00D2, 0xFF93, 0x00D3, 0xFF94, 0x00D4, 0xFF95, 0x00D5, 0xFF96, 0x00D6, 0xFF97, 0x00D7, 0xFF98, 0x00D8, + 0xFF99, 0x00D9, 0xFF9A, 0x00DA, 0xFF9B, 0x00DB, 0xFF9C, 0x00DC, 0xFF9D, 0x00DD, 0xFF9E, 0x00DE, 0xFF9F, 0x00DF, 0xFFE0, 0x8191, + 0xFFE1, 0x8192, 0xFFE2, 0x81CA, 0xFFE3, 0x8150, 0xFFE4, 0xFA55, 0xFFE5, 0x818F, 0, 0 +}; + +static +const WCHAR oem2uni932[] = { /* Shift_JIS --> Unicode pairs */ + 0x00A1, 0xFF61, 0x00A2, 0xFF62, 0x00A3, 0xFF63, 0x00A4, 0xFF64, 0x00A5, 0xFF65, 0x00A6, 0xFF66, 0x00A7, 0xFF67, 0x00A8, 0xFF68, + 0x00A9, 0xFF69, 0x00AA, 0xFF6A, 0x00AB, 0xFF6B, 0x00AC, 0xFF6C, 0x00AD, 0xFF6D, 0x00AE, 0xFF6E, 0x00AF, 0xFF6F, 0x00B0, 0xFF70, + 0x00B1, 0xFF71, 0x00B2, 0xFF72, 0x00B3, 0xFF73, 0x00B4, 0xFF74, 0x00B5, 0xFF75, 0x00B6, 0xFF76, 0x00B7, 0xFF77, 0x00B8, 0xFF78, + 0x00B9, 0xFF79, 0x00BA, 0xFF7A, 0x00BB, 0xFF7B, 0x00BC, 0xFF7C, 0x00BD, 0xFF7D, 0x00BE, 0xFF7E, 0x00BF, 0xFF7F, 0x00C0, 0xFF80, + 0x00C1, 0xFF81, 0x00C2, 0xFF82, 0x00C3, 0xFF83, 0x00C4, 0xFF84, 0x00C5, 0xFF85, 0x00C6, 0xFF86, 0x00C7, 0xFF87, 0x00C8, 0xFF88, + 0x00C9, 0xFF89, 0x00CA, 0xFF8A, 0x00CB, 0xFF8B, 0x00CC, 0xFF8C, 0x00CD, 0xFF8D, 0x00CE, 0xFF8E, 0x00CF, 0xFF8F, 0x00D0, 0xFF90, + 0x00D1, 0xFF91, 0x00D2, 0xFF92, 0x00D3, 0xFF93, 0x00D4, 0xFF94, 0x00D5, 0xFF95, 0x00D6, 0xFF96, 0x00D7, 0xFF97, 0x00D8, 0xFF98, + 0x00D9, 0xFF99, 0x00DA, 0xFF9A, 0x00DB, 0xFF9B, 0x00DC, 0xFF9C, 0x00DD, 0xFF9D, 0x00DE, 0xFF9E, 0x00DF, 0xFF9F, 0x8140, 0x3000, + 0x8141, 0x3001, 0x8142, 0x3002, 0x8143, 0xFF0C, 0x8144, 0xFF0E, 0x8145, 0x30FB, 0x8146, 0xFF1A, 0x8147, 0xFF1B, 0x8148, 0xFF1F, + 0x8149, 0xFF01, 0x814A, 0x309B, 0x814B, 0x309C, 0x814C, 0x00B4, 0x814D, 0xFF40, 0x814E, 0x00A8, 0x814F, 0xFF3E, 0x8150, 0xFFE3, + 0x8151, 0xFF3F, 0x8152, 0x30FD, 0x8153, 0x30FE, 0x8154, 0x309D, 0x8155, 0x309E, 0x8156, 0x3003, 0x8157, 0x4EDD, 0x8158, 0x3005, + 0x8159, 0x3006, 0x815A, 0x3007, 0x815B, 0x30FC, 0x815C, 0x2015, 0x815D, 0x2010, 0x815E, 0xFF0F, 0x815F, 0xFF3C, 0x8160, 0xFF5E, + 0x8161, 0x2225, 0x8162, 0xFF5C, 0x8163, 0x2026, 0x8164, 0x2025, 0x8165, 0x2018, 0x8166, 0x2019, 0x8167, 0x201C, 0x8168, 0x201D, + 0x8169, 0xFF08, 0x816A, 0xFF09, 0x816B, 0x3014, 0x816C, 0x3015, 0x816D, 0xFF3B, 0x816E, 0xFF3D, 0x816F, 0xFF5B, 0x8170, 0xFF5D, + 0x8171, 0x3008, 0x8172, 0x3009, 0x8173, 0x300A, 0x8174, 0x300B, 0x8175, 0x300C, 0x8176, 0x300D, 0x8177, 0x300E, 0x8178, 0x300F, + 0x8179, 0x3010, 0x817A, 0x3011, 0x817B, 0xFF0B, 0x817C, 0xFF0D, 0x817D, 0x00B1, 0x817E, 0x00D7, 0x8180, 0x00F7, 0x8181, 0xFF1D, + 0x8182, 0x2260, 0x8183, 0xFF1C, 0x8184, 0xFF1E, 0x8185, 0x2266, 0x8186, 0x2267, 0x8187, 0x221E, 0x8188, 0x2234, 0x8189, 0x2642, + 0x818A, 0x2640, 0x818B, 0x00B0, 0x818C, 0x2032, 0x818D, 0x2033, 0x818E, 0x2103, 0x818F, 0xFFE5, 0x8190, 0xFF04, 0x8191, 0xFFE0, + 0x8192, 0xFFE1, 0x8193, 0xFF05, 0x8194, 0xFF03, 0x8195, 0xFF06, 0x8196, 0xFF0A, 0x8197, 0xFF20, 0x8198, 0x00A7, 0x8199, 0x2606, + 0x819A, 0x2605, 0x819B, 0x25CB, 0x819C, 0x25CF, 0x819D, 0x25CE, 0x819E, 0x25C7, 0x819F, 0x25C6, 0x81A0, 0x25A1, 0x81A1, 0x25A0, + 0x81A2, 0x25B3, 0x81A3, 0x25B2, 0x81A4, 0x25BD, 0x81A5, 0x25BC, 0x81A6, 0x203B, 0x81A7, 0x3012, 0x81A8, 0x2192, 0x81A9, 0x2190, + 0x81AA, 0x2191, 0x81AB, 0x2193, 0x81AC, 0x3013, 0x81B8, 0x2208, 0x81B9, 0x220B, 0x81BA, 0x2286, 0x81BB, 0x2287, 0x81BC, 0x2282, + 0x81BD, 0x2283, 0x81BE, 0x222A, 0x81BF, 0x2229, 0x81C8, 0x2227, 0x81C9, 0x2228, 0x81CA, 0xFFE2, 0x81CB, 0x21D2, 0x81CC, 0x21D4, + 0x81CD, 0x2200, 0x81CE, 0x2203, 0x81DA, 0x2220, 0x81DB, 0x22A5, 0x81DC, 0x2312, 0x81DD, 0x2202, 0x81DE, 0x2207, 0x81DF, 0x2261, + 0x81E0, 0x2252, 0x81E1, 0x226A, 0x81E2, 0x226B, 0x81E3, 0x221A, 0x81E4, 0x223D, 0x81E5, 0x221D, 0x81E6, 0x2235, 0x81E7, 0x222B, + 0x81E8, 0x222C, 0x81F0, 0x212B, 0x81F1, 0x2030, 0x81F2, 0x266F, 0x81F3, 0x266D, 0x81F4, 0x266A, 0x81F5, 0x2020, 0x81F6, 0x2021, + 0x81F7, 0x00B6, 0x81FC, 0x25EF, 0x824F, 0xFF10, 0x8250, 0xFF11, 0x8251, 0xFF12, 0x8252, 0xFF13, 0x8253, 0xFF14, 0x8254, 0xFF15, + 0x8255, 0xFF16, 0x8256, 0xFF17, 0x8257, 0xFF18, 0x8258, 0xFF19, 0x8260, 0xFF21, 0x8261, 0xFF22, 0x8262, 0xFF23, 0x8263, 0xFF24, + 0x8264, 0xFF25, 0x8265, 0xFF26, 0x8266, 0xFF27, 0x8267, 0xFF28, 0x8268, 0xFF29, 0x8269, 0xFF2A, 0x826A, 0xFF2B, 0x826B, 0xFF2C, + 0x826C, 0xFF2D, 0x826D, 0xFF2E, 0x826E, 0xFF2F, 0x826F, 0xFF30, 0x8270, 0xFF31, 0x8271, 0xFF32, 0x8272, 0xFF33, 0x8273, 0xFF34, + 0x8274, 0xFF35, 0x8275, 0xFF36, 0x8276, 0xFF37, 0x8277, 0xFF38, 0x8278, 0xFF39, 0x8279, 0xFF3A, 0x8281, 0xFF41, 0x8282, 0xFF42, + 0x8283, 0xFF43, 0x8284, 0xFF44, 0x8285, 0xFF45, 0x8286, 0xFF46, 0x8287, 0xFF47, 0x8288, 0xFF48, 0x8289, 0xFF49, 0x828A, 0xFF4A, + 0x828B, 0xFF4B, 0x828C, 0xFF4C, 0x828D, 0xFF4D, 0x828E, 0xFF4E, 0x828F, 0xFF4F, 0x8290, 0xFF50, 0x8291, 0xFF51, 0x8292, 0xFF52, + 0x8293, 0xFF53, 0x8294, 0xFF54, 0x8295, 0xFF55, 0x8296, 0xFF56, 0x8297, 0xFF57, 0x8298, 0xFF58, 0x8299, 0xFF59, 0x829A, 0xFF5A, + 0x829F, 0x3041, 0x82A0, 0x3042, 0x82A1, 0x3043, 0x82A2, 0x3044, 0x82A3, 0x3045, 0x82A4, 0x3046, 0x82A5, 0x3047, 0x82A6, 0x3048, + 0x82A7, 0x3049, 0x82A8, 0x304A, 0x82A9, 0x304B, 0x82AA, 0x304C, 0x82AB, 0x304D, 0x82AC, 0x304E, 0x82AD, 0x304F, 0x82AE, 0x3050, + 0x82AF, 0x3051, 0x82B0, 0x3052, 0x82B1, 0x3053, 0x82B2, 0x3054, 0x82B3, 0x3055, 0x82B4, 0x3056, 0x82B5, 0x3057, 0x82B6, 0x3058, + 0x82B7, 0x3059, 0x82B8, 0x305A, 0x82B9, 0x305B, 0x82BA, 0x305C, 0x82BB, 0x305D, 0x82BC, 0x305E, 0x82BD, 0x305F, 0x82BE, 0x3060, + 0x82BF, 0x3061, 0x82C0, 0x3062, 0x82C1, 0x3063, 0x82C2, 0x3064, 0x82C3, 0x3065, 0x82C4, 0x3066, 0x82C5, 0x3067, 0x82C6, 0x3068, + 0x82C7, 0x3069, 0x82C8, 0x306A, 0x82C9, 0x306B, 0x82CA, 0x306C, 0x82CB, 0x306D, 0x82CC, 0x306E, 0x82CD, 0x306F, 0x82CE, 0x3070, + 0x82CF, 0x3071, 0x82D0, 0x3072, 0x82D1, 0x3073, 0x82D2, 0x3074, 0x82D3, 0x3075, 0x82D4, 0x3076, 0x82D5, 0x3077, 0x82D6, 0x3078, + 0x82D7, 0x3079, 0x82D8, 0x307A, 0x82D9, 0x307B, 0x82DA, 0x307C, 0x82DB, 0x307D, 0x82DC, 0x307E, 0x82DD, 0x307F, 0x82DE, 0x3080, + 0x82DF, 0x3081, 0x82E0, 0x3082, 0x82E1, 0x3083, 0x82E2, 0x3084, 0x82E3, 0x3085, 0x82E4, 0x3086, 0x82E5, 0x3087, 0x82E6, 0x3088, + 0x82E7, 0x3089, 0x82E8, 0x308A, 0x82E9, 0x308B, 0x82EA, 0x308C, 0x82EB, 0x308D, 0x82EC, 0x308E, 0x82ED, 0x308F, 0x82EE, 0x3090, + 0x82EF, 0x3091, 0x82F0, 0x3092, 0x82F1, 0x3093, 0x8340, 0x30A1, 0x8341, 0x30A2, 0x8342, 0x30A3, 0x8343, 0x30A4, 0x8344, 0x30A5, + 0x8345, 0x30A6, 0x8346, 0x30A7, 0x8347, 0x30A8, 0x8348, 0x30A9, 0x8349, 0x30AA, 0x834A, 0x30AB, 0x834B, 0x30AC, 0x834C, 0x30AD, + 0x834D, 0x30AE, 0x834E, 0x30AF, 0x834F, 0x30B0, 0x8350, 0x30B1, 0x8351, 0x30B2, 0x8352, 0x30B3, 0x8353, 0x30B4, 0x8354, 0x30B5, + 0x8355, 0x30B6, 0x8356, 0x30B7, 0x8357, 0x30B8, 0x8358, 0x30B9, 0x8359, 0x30BA, 0x835A, 0x30BB, 0x835B, 0x30BC, 0x835C, 0x30BD, + 0x835D, 0x30BE, 0x835E, 0x30BF, 0x835F, 0x30C0, 0x8360, 0x30C1, 0x8361, 0x30C2, 0x8362, 0x30C3, 0x8363, 0x30C4, 0x8364, 0x30C5, + 0x8365, 0x30C6, 0x8366, 0x30C7, 0x8367, 0x30C8, 0x8368, 0x30C9, 0x8369, 0x30CA, 0x836A, 0x30CB, 0x836B, 0x30CC, 0x836C, 0x30CD, + 0x836D, 0x30CE, 0x836E, 0x30CF, 0x836F, 0x30D0, 0x8370, 0x30D1, 0x8371, 0x30D2, 0x8372, 0x30D3, 0x8373, 0x30D4, 0x8374, 0x30D5, + 0x8375, 0x30D6, 0x8376, 0x30D7, 0x8377, 0x30D8, 0x8378, 0x30D9, 0x8379, 0x30DA, 0x837A, 0x30DB, 0x837B, 0x30DC, 0x837C, 0x30DD, + 0x837D, 0x30DE, 0x837E, 0x30DF, 0x8380, 0x30E0, 0x8381, 0x30E1, 0x8382, 0x30E2, 0x8383, 0x30E3, 0x8384, 0x30E4, 0x8385, 0x30E5, + 0x8386, 0x30E6, 0x8387, 0x30E7, 0x8388, 0x30E8, 0x8389, 0x30E9, 0x838A, 0x30EA, 0x838B, 0x30EB, 0x838C, 0x30EC, 0x838D, 0x30ED, + 0x838E, 0x30EE, 0x838F, 0x30EF, 0x8390, 0x30F0, 0x8391, 0x30F1, 0x8392, 0x30F2, 0x8393, 0x30F3, 0x8394, 0x30F4, 0x8395, 0x30F5, + 0x8396, 0x30F6, 0x839F, 0x0391, 0x83A0, 0x0392, 0x83A1, 0x0393, 0x83A2, 0x0394, 0x83A3, 0x0395, 0x83A4, 0x0396, 0x83A5, 0x0397, + 0x83A6, 0x0398, 0x83A7, 0x0399, 0x83A8, 0x039A, 0x83A9, 0x039B, 0x83AA, 0x039C, 0x83AB, 0x039D, 0x83AC, 0x039E, 0x83AD, 0x039F, + 0x83AE, 0x03A0, 0x83AF, 0x03A1, 0x83B0, 0x03A3, 0x83B1, 0x03A4, 0x83B2, 0x03A5, 0x83B3, 0x03A6, 0x83B4, 0x03A7, 0x83B5, 0x03A8, + 0x83B6, 0x03A9, 0x83BF, 0x03B1, 0x83C0, 0x03B2, 0x83C1, 0x03B3, 0x83C2, 0x03B4, 0x83C3, 0x03B5, 0x83C4, 0x03B6, 0x83C5, 0x03B7, + 0x83C6, 0x03B8, 0x83C7, 0x03B9, 0x83C8, 0x03BA, 0x83C9, 0x03BB, 0x83CA, 0x03BC, 0x83CB, 0x03BD, 0x83CC, 0x03BE, 0x83CD, 0x03BF, + 0x83CE, 0x03C0, 0x83CF, 0x03C1, 0x83D0, 0x03C3, 0x83D1, 0x03C4, 0x83D2, 0x03C5, 0x83D3, 0x03C6, 0x83D4, 0x03C7, 0x83D5, 0x03C8, + 0x83D6, 0x03C9, 0x8440, 0x0410, 0x8441, 0x0411, 0x8442, 0x0412, 0x8443, 0x0413, 0x8444, 0x0414, 0x8445, 0x0415, 0x8446, 0x0401, + 0x8447, 0x0416, 0x8448, 0x0417, 0x8449, 0x0418, 0x844A, 0x0419, 0x844B, 0x041A, 0x844C, 0x041B, 0x844D, 0x041C, 0x844E, 0x041D, + 0x844F, 0x041E, 0x8450, 0x041F, 0x8451, 0x0420, 0x8452, 0x0421, 0x8453, 0x0422, 0x8454, 0x0423, 0x8455, 0x0424, 0x8456, 0x0425, + 0x8457, 0x0426, 0x8458, 0x0427, 0x8459, 0x0428, 0x845A, 0x0429, 0x845B, 0x042A, 0x845C, 0x042B, 0x845D, 0x042C, 0x845E, 0x042D, + 0x845F, 0x042E, 0x8460, 0x042F, 0x8470, 0x0430, 0x8471, 0x0431, 0x8472, 0x0432, 0x8473, 0x0433, 0x8474, 0x0434, 0x8475, 0x0435, + 0x8476, 0x0451, 0x8477, 0x0436, 0x8478, 0x0437, 0x8479, 0x0438, 0x847A, 0x0439, 0x847B, 0x043A, 0x847C, 0x043B, 0x847D, 0x043C, + 0x847E, 0x043D, 0x8480, 0x043E, 0x8481, 0x043F, 0x8482, 0x0440, 0x8483, 0x0441, 0x8484, 0x0442, 0x8485, 0x0443, 0x8486, 0x0444, + 0x8487, 0x0445, 0x8488, 0x0446, 0x8489, 0x0447, 0x848A, 0x0448, 0x848B, 0x0449, 0x848C, 0x044A, 0x848D, 0x044B, 0x848E, 0x044C, + 0x848F, 0x044D, 0x8490, 0x044E, 0x8491, 0x044F, 0x849F, 0x2500, 0x84A0, 0x2502, 0x84A1, 0x250C, 0x84A2, 0x2510, 0x84A3, 0x2518, + 0x84A4, 0x2514, 0x84A5, 0x251C, 0x84A6, 0x252C, 0x84A7, 0x2524, 0x84A8, 0x2534, 0x84A9, 0x253C, 0x84AA, 0x2501, 0x84AB, 0x2503, + 0x84AC, 0x250F, 0x84AD, 0x2513, 0x84AE, 0x251B, 0x84AF, 0x2517, 0x84B0, 0x2523, 0x84B1, 0x2533, 0x84B2, 0x252B, 0x84B3, 0x253B, + 0x84B4, 0x254B, 0x84B5, 0x2520, 0x84B6, 0x252F, 0x84B7, 0x2528, 0x84B8, 0x2537, 0x84B9, 0x253F, 0x84BA, 0x251D, 0x84BB, 0x2530, + 0x84BC, 0x2525, 0x84BD, 0x2538, 0x84BE, 0x2542, 0x8740, 0x2460, 0x8741, 0x2461, 0x8742, 0x2462, 0x8743, 0x2463, 0x8744, 0x2464, + 0x8745, 0x2465, 0x8746, 0x2466, 0x8747, 0x2467, 0x8748, 0x2468, 0x8749, 0x2469, 0x874A, 0x246A, 0x874B, 0x246B, 0x874C, 0x246C, + 0x874D, 0x246D, 0x874E, 0x246E, 0x874F, 0x246F, 0x8750, 0x2470, 0x8751, 0x2471, 0x8752, 0x2472, 0x8753, 0x2473, 0x8754, 0x2160, + 0x8755, 0x2161, 0x8756, 0x2162, 0x8757, 0x2163, 0x8758, 0x2164, 0x8759, 0x2165, 0x875A, 0x2166, 0x875B, 0x2167, 0x875C, 0x2168, + 0x875D, 0x2169, 0x875F, 0x3349, 0x8760, 0x3314, 0x8761, 0x3322, 0x8762, 0x334D, 0x8763, 0x3318, 0x8764, 0x3327, 0x8765, 0x3303, + 0x8766, 0x3336, 0x8767, 0x3351, 0x8768, 0x3357, 0x8769, 0x330D, 0x876A, 0x3326, 0x876B, 0x3323, 0x876C, 0x332B, 0x876D, 0x334A, + 0x876E, 0x333B, 0x876F, 0x339C, 0x8770, 0x339D, 0x8771, 0x339E, 0x8772, 0x338E, 0x8773, 0x338F, 0x8774, 0x33C4, 0x8775, 0x33A1, + 0x877E, 0x337B, 0x8780, 0x301D, 0x8781, 0x301F, 0x8782, 0x2116, 0x8783, 0x33CD, 0x8784, 0x2121, 0x8785, 0x32A4, 0x8786, 0x32A5, + 0x8787, 0x32A6, 0x8788, 0x32A7, 0x8789, 0x32A8, 0x878A, 0x3231, 0x878B, 0x3232, 0x878C, 0x3239, 0x878D, 0x337E, 0x878E, 0x337D, + 0x878F, 0x337C, 0x8793, 0x222E, 0x8794, 0x2211, 0x8798, 0x221F, 0x8799, 0x22BF, 0x889F, 0x4E9C, 0x88A0, 0x5516, 0x88A1, 0x5A03, + 0x88A2, 0x963F, 0x88A3, 0x54C0, 0x88A4, 0x611B, 0x88A5, 0x6328, 0x88A6, 0x59F6, 0x88A7, 0x9022, 0x88A8, 0x8475, 0x88A9, 0x831C, + 0x88AA, 0x7A50, 0x88AB, 0x60AA, 0x88AC, 0x63E1, 0x88AD, 0x6E25, 0x88AE, 0x65ED, 0x88AF, 0x8466, 0x88B0, 0x82A6, 0x88B1, 0x9BF5, + 0x88B2, 0x6893, 0x88B3, 0x5727, 0x88B4, 0x65A1, 0x88B5, 0x6271, 0x88B6, 0x5B9B, 0x88B7, 0x59D0, 0x88B8, 0x867B, 0x88B9, 0x98F4, + 0x88BA, 0x7D62, 0x88BB, 0x7DBE, 0x88BC, 0x9B8E, 0x88BD, 0x6216, 0x88BE, 0x7C9F, 0x88BF, 0x88B7, 0x88C0, 0x5B89, 0x88C1, 0x5EB5, + 0x88C2, 0x6309, 0x88C3, 0x6697, 0x88C4, 0x6848, 0x88C5, 0x95C7, 0x88C6, 0x978D, 0x88C7, 0x674F, 0x88C8, 0x4EE5, 0x88C9, 0x4F0A, + 0x88CA, 0x4F4D, 0x88CB, 0x4F9D, 0x88CC, 0x5049, 0x88CD, 0x56F2, 0x88CE, 0x5937, 0x88CF, 0x59D4, 0x88D0, 0x5A01, 0x88D1, 0x5C09, + 0x88D2, 0x60DF, 0x88D3, 0x610F, 0x88D4, 0x6170, 0x88D5, 0x6613, 0x88D6, 0x6905, 0x88D7, 0x70BA, 0x88D8, 0x754F, 0x88D9, 0x7570, + 0x88DA, 0x79FB, 0x88DB, 0x7DAD, 0x88DC, 0x7DEF, 0x88DD, 0x80C3, 0x88DE, 0x840E, 0x88DF, 0x8863, 0x88E0, 0x8B02, 0x88E1, 0x9055, + 0x88E2, 0x907A, 0x88E3, 0x533B, 0x88E4, 0x4E95, 0x88E5, 0x4EA5, 0x88E6, 0x57DF, 0x88E7, 0x80B2, 0x88E8, 0x90C1, 0x88E9, 0x78EF, + 0x88EA, 0x4E00, 0x88EB, 0x58F1, 0x88EC, 0x6EA2, 0x88ED, 0x9038, 0x88EE, 0x7A32, 0x88EF, 0x8328, 0x88F0, 0x828B, 0x88F1, 0x9C2F, + 0x88F2, 0x5141, 0x88F3, 0x5370, 0x88F4, 0x54BD, 0x88F5, 0x54E1, 0x88F6, 0x56E0, 0x88F7, 0x59FB, 0x88F8, 0x5F15, 0x88F9, 0x98F2, + 0x88FA, 0x6DEB, 0x88FB, 0x80E4, 0x88FC, 0x852D, 0x8940, 0x9662, 0x8941, 0x9670, 0x8942, 0x96A0, 0x8943, 0x97FB, 0x8944, 0x540B, + 0x8945, 0x53F3, 0x8946, 0x5B87, 0x8947, 0x70CF, 0x8948, 0x7FBD, 0x8949, 0x8FC2, 0x894A, 0x96E8, 0x894B, 0x536F, 0x894C, 0x9D5C, + 0x894D, 0x7ABA, 0x894E, 0x4E11, 0x894F, 0x7893, 0x8950, 0x81FC, 0x8951, 0x6E26, 0x8952, 0x5618, 0x8953, 0x5504, 0x8954, 0x6B1D, + 0x8955, 0x851A, 0x8956, 0x9C3B, 0x8957, 0x59E5, 0x8958, 0x53A9, 0x8959, 0x6D66, 0x895A, 0x74DC, 0x895B, 0x958F, 0x895C, 0x5642, + 0x895D, 0x4E91, 0x895E, 0x904B, 0x895F, 0x96F2, 0x8960, 0x834F, 0x8961, 0x990C, 0x8962, 0x53E1, 0x8963, 0x55B6, 0x8964, 0x5B30, + 0x8965, 0x5F71, 0x8966, 0x6620, 0x8967, 0x66F3, 0x8968, 0x6804, 0x8969, 0x6C38, 0x896A, 0x6CF3, 0x896B, 0x6D29, 0x896C, 0x745B, + 0x896D, 0x76C8, 0x896E, 0x7A4E, 0x896F, 0x9834, 0x8970, 0x82F1, 0x8971, 0x885B, 0x8972, 0x8A60, 0x8973, 0x92ED, 0x8974, 0x6DB2, + 0x8975, 0x75AB, 0x8976, 0x76CA, 0x8977, 0x99C5, 0x8978, 0x60A6, 0x8979, 0x8B01, 0x897A, 0x8D8A, 0x897B, 0x95B2, 0x897C, 0x698E, + 0x897D, 0x53AD, 0x897E, 0x5186, 0x8980, 0x5712, 0x8981, 0x5830, 0x8982, 0x5944, 0x8983, 0x5BB4, 0x8984, 0x5EF6, 0x8985, 0x6028, + 0x8986, 0x63A9, 0x8987, 0x63F4, 0x8988, 0x6CBF, 0x8989, 0x6F14, 0x898A, 0x708E, 0x898B, 0x7114, 0x898C, 0x7159, 0x898D, 0x71D5, + 0x898E, 0x733F, 0x898F, 0x7E01, 0x8990, 0x8276, 0x8991, 0x82D1, 0x8992, 0x8597, 0x8993, 0x9060, 0x8994, 0x925B, 0x8995, 0x9D1B, + 0x8996, 0x5869, 0x8997, 0x65BC, 0x8998, 0x6C5A, 0x8999, 0x7525, 0x899A, 0x51F9, 0x899B, 0x592E, 0x899C, 0x5965, 0x899D, 0x5F80, + 0x899E, 0x5FDC, 0x899F, 0x62BC, 0x89A0, 0x65FA, 0x89A1, 0x6A2A, 0x89A2, 0x6B27, 0x89A3, 0x6BB4, 0x89A4, 0x738B, 0x89A5, 0x7FC1, + 0x89A6, 0x8956, 0x89A7, 0x9D2C, 0x89A8, 0x9D0E, 0x89A9, 0x9EC4, 0x89AA, 0x5CA1, 0x89AB, 0x6C96, 0x89AC, 0x837B, 0x89AD, 0x5104, + 0x89AE, 0x5C4B, 0x89AF, 0x61B6, 0x89B0, 0x81C6, 0x89B1, 0x6876, 0x89B2, 0x7261, 0x89B3, 0x4E59, 0x89B4, 0x4FFA, 0x89B5, 0x5378, + 0x89B6, 0x6069, 0x89B7, 0x6E29, 0x89B8, 0x7A4F, 0x89B9, 0x97F3, 0x89BA, 0x4E0B, 0x89BB, 0x5316, 0x89BC, 0x4EEE, 0x89BD, 0x4F55, + 0x89BE, 0x4F3D, 0x89BF, 0x4FA1, 0x89C0, 0x4F73, 0x89C1, 0x52A0, 0x89C2, 0x53EF, 0x89C3, 0x5609, 0x89C4, 0x590F, 0x89C5, 0x5AC1, + 0x89C6, 0x5BB6, 0x89C7, 0x5BE1, 0x89C8, 0x79D1, 0x89C9, 0x6687, 0x89CA, 0x679C, 0x89CB, 0x67B6, 0x89CC, 0x6B4C, 0x89CD, 0x6CB3, + 0x89CE, 0x706B, 0x89CF, 0x73C2, 0x89D0, 0x798D, 0x89D1, 0x79BE, 0x89D2, 0x7A3C, 0x89D3, 0x7B87, 0x89D4, 0x82B1, 0x89D5, 0x82DB, + 0x89D6, 0x8304, 0x89D7, 0x8377, 0x89D8, 0x83EF, 0x89D9, 0x83D3, 0x89DA, 0x8766, 0x89DB, 0x8AB2, 0x89DC, 0x5629, 0x89DD, 0x8CA8, + 0x89DE, 0x8FE6, 0x89DF, 0x904E, 0x89E0, 0x971E, 0x89E1, 0x868A, 0x89E2, 0x4FC4, 0x89E3, 0x5CE8, 0x89E4, 0x6211, 0x89E5, 0x7259, + 0x89E6, 0x753B, 0x89E7, 0x81E5, 0x89E8, 0x82BD, 0x89E9, 0x86FE, 0x89EA, 0x8CC0, 0x89EB, 0x96C5, 0x89EC, 0x9913, 0x89ED, 0x99D5, + 0x89EE, 0x4ECB, 0x89EF, 0x4F1A, 0x89F0, 0x89E3, 0x89F1, 0x56DE, 0x89F2, 0x584A, 0x89F3, 0x58CA, 0x89F4, 0x5EFB, 0x89F5, 0x5FEB, + 0x89F6, 0x602A, 0x89F7, 0x6094, 0x89F8, 0x6062, 0x89F9, 0x61D0, 0x89FA, 0x6212, 0x89FB, 0x62D0, 0x89FC, 0x6539, 0x8A40, 0x9B41, + 0x8A41, 0x6666, 0x8A42, 0x68B0, 0x8A43, 0x6D77, 0x8A44, 0x7070, 0x8A45, 0x754C, 0x8A46, 0x7686, 0x8A47, 0x7D75, 0x8A48, 0x82A5, + 0x8A49, 0x87F9, 0x8A4A, 0x958B, 0x8A4B, 0x968E, 0x8A4C, 0x8C9D, 0x8A4D, 0x51F1, 0x8A4E, 0x52BE, 0x8A4F, 0x5916, 0x8A50, 0x54B3, + 0x8A51, 0x5BB3, 0x8A52, 0x5D16, 0x8A53, 0x6168, 0x8A54, 0x6982, 0x8A55, 0x6DAF, 0x8A56, 0x788D, 0x8A57, 0x84CB, 0x8A58, 0x8857, + 0x8A59, 0x8A72, 0x8A5A, 0x93A7, 0x8A5B, 0x9AB8, 0x8A5C, 0x6D6C, 0x8A5D, 0x99A8, 0x8A5E, 0x86D9, 0x8A5F, 0x57A3, 0x8A60, 0x67FF, + 0x8A61, 0x86CE, 0x8A62, 0x920E, 0x8A63, 0x5283, 0x8A64, 0x5687, 0x8A65, 0x5404, 0x8A66, 0x5ED3, 0x8A67, 0x62E1, 0x8A68, 0x64B9, + 0x8A69, 0x683C, 0x8A6A, 0x6838, 0x8A6B, 0x6BBB, 0x8A6C, 0x7372, 0x8A6D, 0x78BA, 0x8A6E, 0x7A6B, 0x8A6F, 0x899A, 0x8A70, 0x89D2, + 0x8A71, 0x8D6B, 0x8A72, 0x8F03, 0x8A73, 0x90ED, 0x8A74, 0x95A3, 0x8A75, 0x9694, 0x8A76, 0x9769, 0x8A77, 0x5B66, 0x8A78, 0x5CB3, + 0x8A79, 0x697D, 0x8A7A, 0x984D, 0x8A7B, 0x984E, 0x8A7C, 0x639B, 0x8A7D, 0x7B20, 0x8A7E, 0x6A2B, 0x8A80, 0x6A7F, 0x8A81, 0x68B6, + 0x8A82, 0x9C0D, 0x8A83, 0x6F5F, 0x8A84, 0x5272, 0x8A85, 0x559D, 0x8A86, 0x6070, 0x8A87, 0x62EC, 0x8A88, 0x6D3B, 0x8A89, 0x6E07, + 0x8A8A, 0x6ED1, 0x8A8B, 0x845B, 0x8A8C, 0x8910, 0x8A8D, 0x8F44, 0x8A8E, 0x4E14, 0x8A8F, 0x9C39, 0x8A90, 0x53F6, 0x8A91, 0x691B, + 0x8A92, 0x6A3A, 0x8A93, 0x9784, 0x8A94, 0x682A, 0x8A95, 0x515C, 0x8A96, 0x7AC3, 0x8A97, 0x84B2, 0x8A98, 0x91DC, 0x8A99, 0x938C, + 0x8A9A, 0x565B, 0x8A9B, 0x9D28, 0x8A9C, 0x6822, 0x8A9D, 0x8305, 0x8A9E, 0x8431, 0x8A9F, 0x7CA5, 0x8AA0, 0x5208, 0x8AA1, 0x82C5, + 0x8AA2, 0x74E6, 0x8AA3, 0x4E7E, 0x8AA4, 0x4F83, 0x8AA5, 0x51A0, 0x8AA6, 0x5BD2, 0x8AA7, 0x520A, 0x8AA8, 0x52D8, 0x8AA9, 0x52E7, + 0x8AAA, 0x5DFB, 0x8AAB, 0x559A, 0x8AAC, 0x582A, 0x8AAD, 0x59E6, 0x8AAE, 0x5B8C, 0x8AAF, 0x5B98, 0x8AB0, 0x5BDB, 0x8AB1, 0x5E72, + 0x8AB2, 0x5E79, 0x8AB3, 0x60A3, 0x8AB4, 0x611F, 0x8AB5, 0x6163, 0x8AB6, 0x61BE, 0x8AB7, 0x63DB, 0x8AB8, 0x6562, 0x8AB9, 0x67D1, + 0x8ABA, 0x6853, 0x8ABB, 0x68FA, 0x8ABC, 0x6B3E, 0x8ABD, 0x6B53, 0x8ABE, 0x6C57, 0x8ABF, 0x6F22, 0x8AC0, 0x6F97, 0x8AC1, 0x6F45, + 0x8AC2, 0x74B0, 0x8AC3, 0x7518, 0x8AC4, 0x76E3, 0x8AC5, 0x770B, 0x8AC6, 0x7AFF, 0x8AC7, 0x7BA1, 0x8AC8, 0x7C21, 0x8AC9, 0x7DE9, + 0x8ACA, 0x7F36, 0x8ACB, 0x7FF0, 0x8ACC, 0x809D, 0x8ACD, 0x8266, 0x8ACE, 0x839E, 0x8ACF, 0x89B3, 0x8AD0, 0x8ACC, 0x8AD1, 0x8CAB, + 0x8AD2, 0x9084, 0x8AD3, 0x9451, 0x8AD4, 0x9593, 0x8AD5, 0x9591, 0x8AD6, 0x95A2, 0x8AD7, 0x9665, 0x8AD8, 0x97D3, 0x8AD9, 0x9928, + 0x8ADA, 0x8218, 0x8ADB, 0x4E38, 0x8ADC, 0x542B, 0x8ADD, 0x5CB8, 0x8ADE, 0x5DCC, 0x8ADF, 0x73A9, 0x8AE0, 0x764C, 0x8AE1, 0x773C, + 0x8AE2, 0x5CA9, 0x8AE3, 0x7FEB, 0x8AE4, 0x8D0B, 0x8AE5, 0x96C1, 0x8AE6, 0x9811, 0x8AE7, 0x9854, 0x8AE8, 0x9858, 0x8AE9, 0x4F01, + 0x8AEA, 0x4F0E, 0x8AEB, 0x5371, 0x8AEC, 0x559C, 0x8AED, 0x5668, 0x8AEE, 0x57FA, 0x8AEF, 0x5947, 0x8AF0, 0x5B09, 0x8AF1, 0x5BC4, + 0x8AF2, 0x5C90, 0x8AF3, 0x5E0C, 0x8AF4, 0x5E7E, 0x8AF5, 0x5FCC, 0x8AF6, 0x63EE, 0x8AF7, 0x673A, 0x8AF8, 0x65D7, 0x8AF9, 0x65E2, + 0x8AFA, 0x671F, 0x8AFB, 0x68CB, 0x8AFC, 0x68C4, 0x8B40, 0x6A5F, 0x8B41, 0x5E30, 0x8B42, 0x6BC5, 0x8B43, 0x6C17, 0x8B44, 0x6C7D, + 0x8B45, 0x757F, 0x8B46, 0x7948, 0x8B47, 0x5B63, 0x8B48, 0x7A00, 0x8B49, 0x7D00, 0x8B4A, 0x5FBD, 0x8B4B, 0x898F, 0x8B4C, 0x8A18, + 0x8B4D, 0x8CB4, 0x8B4E, 0x8D77, 0x8B4F, 0x8ECC, 0x8B50, 0x8F1D, 0x8B51, 0x98E2, 0x8B52, 0x9A0E, 0x8B53, 0x9B3C, 0x8B54, 0x4E80, + 0x8B55, 0x507D, 0x8B56, 0x5100, 0x8B57, 0x5993, 0x8B58, 0x5B9C, 0x8B59, 0x622F, 0x8B5A, 0x6280, 0x8B5B, 0x64EC, 0x8B5C, 0x6B3A, + 0x8B5D, 0x72A0, 0x8B5E, 0x7591, 0x8B5F, 0x7947, 0x8B60, 0x7FA9, 0x8B61, 0x87FB, 0x8B62, 0x8ABC, 0x8B63, 0x8B70, 0x8B64, 0x63AC, + 0x8B65, 0x83CA, 0x8B66, 0x97A0, 0x8B67, 0x5409, 0x8B68, 0x5403, 0x8B69, 0x55AB, 0x8B6A, 0x6854, 0x8B6B, 0x6A58, 0x8B6C, 0x8A70, + 0x8B6D, 0x7827, 0x8B6E, 0x6775, 0x8B6F, 0x9ECD, 0x8B70, 0x5374, 0x8B71, 0x5BA2, 0x8B72, 0x811A, 0x8B73, 0x8650, 0x8B74, 0x9006, + 0x8B75, 0x4E18, 0x8B76, 0x4E45, 0x8B77, 0x4EC7, 0x8B78, 0x4F11, 0x8B79, 0x53CA, 0x8B7A, 0x5438, 0x8B7B, 0x5BAE, 0x8B7C, 0x5F13, + 0x8B7D, 0x6025, 0x8B7E, 0x6551, 0x8B80, 0x673D, 0x8B81, 0x6C42, 0x8B82, 0x6C72, 0x8B83, 0x6CE3, 0x8B84, 0x7078, 0x8B85, 0x7403, + 0x8B86, 0x7A76, 0x8B87, 0x7AAE, 0x8B88, 0x7B08, 0x8B89, 0x7D1A, 0x8B8A, 0x7CFE, 0x8B8B, 0x7D66, 0x8B8C, 0x65E7, 0x8B8D, 0x725B, + 0x8B8E, 0x53BB, 0x8B8F, 0x5C45, 0x8B90, 0x5DE8, 0x8B91, 0x62D2, 0x8B92, 0x62E0, 0x8B93, 0x6319, 0x8B94, 0x6E20, 0x8B95, 0x865A, + 0x8B96, 0x8A31, 0x8B97, 0x8DDD, 0x8B98, 0x92F8, 0x8B99, 0x6F01, 0x8B9A, 0x79A6, 0x8B9B, 0x9B5A, 0x8B9C, 0x4EA8, 0x8B9D, 0x4EAB, + 0x8B9E, 0x4EAC, 0x8B9F, 0x4F9B, 0x8BA0, 0x4FA0, 0x8BA1, 0x50D1, 0x8BA2, 0x5147, 0x8BA3, 0x7AF6, 0x8BA4, 0x5171, 0x8BA5, 0x51F6, + 0x8BA6, 0x5354, 0x8BA7, 0x5321, 0x8BA8, 0x537F, 0x8BA9, 0x53EB, 0x8BAA, 0x55AC, 0x8BAB, 0x5883, 0x8BAC, 0x5CE1, 0x8BAD, 0x5F37, + 0x8BAE, 0x5F4A, 0x8BAF, 0x602F, 0x8BB0, 0x6050, 0x8BB1, 0x606D, 0x8BB2, 0x631F, 0x8BB3, 0x6559, 0x8BB4, 0x6A4B, 0x8BB5, 0x6CC1, + 0x8BB6, 0x72C2, 0x8BB7, 0x72ED, 0x8BB8, 0x77EF, 0x8BB9, 0x80F8, 0x8BBA, 0x8105, 0x8BBB, 0x8208, 0x8BBC, 0x854E, 0x8BBD, 0x90F7, + 0x8BBE, 0x93E1, 0x8BBF, 0x97FF, 0x8BC0, 0x9957, 0x8BC1, 0x9A5A, 0x8BC2, 0x4EF0, 0x8BC3, 0x51DD, 0x8BC4, 0x5C2D, 0x8BC5, 0x6681, + 0x8BC6, 0x696D, 0x8BC7, 0x5C40, 0x8BC8, 0x66F2, 0x8BC9, 0x6975, 0x8BCA, 0x7389, 0x8BCB, 0x6850, 0x8BCC, 0x7C81, 0x8BCD, 0x50C5, + 0x8BCE, 0x52E4, 0x8BCF, 0x5747, 0x8BD0, 0x5DFE, 0x8BD1, 0x9326, 0x8BD2, 0x65A4, 0x8BD3, 0x6B23, 0x8BD4, 0x6B3D, 0x8BD5, 0x7434, + 0x8BD6, 0x7981, 0x8BD7, 0x79BD, 0x8BD8, 0x7B4B, 0x8BD9, 0x7DCA, 0x8BDA, 0x82B9, 0x8BDB, 0x83CC, 0x8BDC, 0x887F, 0x8BDD, 0x895F, + 0x8BDE, 0x8B39, 0x8BDF, 0x8FD1, 0x8BE0, 0x91D1, 0x8BE1, 0x541F, 0x8BE2, 0x9280, 0x8BE3, 0x4E5D, 0x8BE4, 0x5036, 0x8BE5, 0x53E5, + 0x8BE6, 0x533A, 0x8BE7, 0x72D7, 0x8BE8, 0x7396, 0x8BE9, 0x77E9, 0x8BEA, 0x82E6, 0x8BEB, 0x8EAF, 0x8BEC, 0x99C6, 0x8BED, 0x99C8, + 0x8BEE, 0x99D2, 0x8BEF, 0x5177, 0x8BF0, 0x611A, 0x8BF1, 0x865E, 0x8BF2, 0x55B0, 0x8BF3, 0x7A7A, 0x8BF4, 0x5076, 0x8BF5, 0x5BD3, + 0x8BF6, 0x9047, 0x8BF7, 0x9685, 0x8BF8, 0x4E32, 0x8BF9, 0x6ADB, 0x8BFA, 0x91E7, 0x8BFB, 0x5C51, 0x8BFC, 0x5C48, 0x8C40, 0x6398, + 0x8C41, 0x7A9F, 0x8C42, 0x6C93, 0x8C43, 0x9774, 0x8C44, 0x8F61, 0x8C45, 0x7AAA, 0x8C46, 0x718A, 0x8C47, 0x9688, 0x8C48, 0x7C82, + 0x8C49, 0x6817, 0x8C4A, 0x7E70, 0x8C4B, 0x6851, 0x8C4C, 0x936C, 0x8C4D, 0x52F2, 0x8C4E, 0x541B, 0x8C4F, 0x85AB, 0x8C50, 0x8A13, + 0x8C51, 0x7FA4, 0x8C52, 0x8ECD, 0x8C53, 0x90E1, 0x8C54, 0x5366, 0x8C55, 0x8888, 0x8C56, 0x7941, 0x8C57, 0x4FC2, 0x8C58, 0x50BE, + 0x8C59, 0x5211, 0x8C5A, 0x5144, 0x8C5B, 0x5553, 0x8C5C, 0x572D, 0x8C5D, 0x73EA, 0x8C5E, 0x578B, 0x8C5F, 0x5951, 0x8C60, 0x5F62, + 0x8C61, 0x5F84, 0x8C62, 0x6075, 0x8C63, 0x6176, 0x8C64, 0x6167, 0x8C65, 0x61A9, 0x8C66, 0x63B2, 0x8C67, 0x643A, 0x8C68, 0x656C, + 0x8C69, 0x666F, 0x8C6A, 0x6842, 0x8C6B, 0x6E13, 0x8C6C, 0x7566, 0x8C6D, 0x7A3D, 0x8C6E, 0x7CFB, 0x8C6F, 0x7D4C, 0x8C70, 0x7D99, + 0x8C71, 0x7E4B, 0x8C72, 0x7F6B, 0x8C73, 0x830E, 0x8C74, 0x834A, 0x8C75, 0x86CD, 0x8C76, 0x8A08, 0x8C77, 0x8A63, 0x8C78, 0x8B66, + 0x8C79, 0x8EFD, 0x8C7A, 0x981A, 0x8C7B, 0x9D8F, 0x8C7C, 0x82B8, 0x8C7D, 0x8FCE, 0x8C7E, 0x9BE8, 0x8C80, 0x5287, 0x8C81, 0x621F, + 0x8C82, 0x6483, 0x8C83, 0x6FC0, 0x8C84, 0x9699, 0x8C85, 0x6841, 0x8C86, 0x5091, 0x8C87, 0x6B20, 0x8C88, 0x6C7A, 0x8C89, 0x6F54, + 0x8C8A, 0x7A74, 0x8C8B, 0x7D50, 0x8C8C, 0x8840, 0x8C8D, 0x8A23, 0x8C8E, 0x6708, 0x8C8F, 0x4EF6, 0x8C90, 0x5039, 0x8C91, 0x5026, + 0x8C92, 0x5065, 0x8C93, 0x517C, 0x8C94, 0x5238, 0x8C95, 0x5263, 0x8C96, 0x55A7, 0x8C97, 0x570F, 0x8C98, 0x5805, 0x8C99, 0x5ACC, + 0x8C9A, 0x5EFA, 0x8C9B, 0x61B2, 0x8C9C, 0x61F8, 0x8C9D, 0x62F3, 0x8C9E, 0x6372, 0x8C9F, 0x691C, 0x8CA0, 0x6A29, 0x8CA1, 0x727D, + 0x8CA2, 0x72AC, 0x8CA3, 0x732E, 0x8CA4, 0x7814, 0x8CA5, 0x786F, 0x8CA6, 0x7D79, 0x8CA7, 0x770C, 0x8CA8, 0x80A9, 0x8CA9, 0x898B, + 0x8CAA, 0x8B19, 0x8CAB, 0x8CE2, 0x8CAC, 0x8ED2, 0x8CAD, 0x9063, 0x8CAE, 0x9375, 0x8CAF, 0x967A, 0x8CB0, 0x9855, 0x8CB1, 0x9A13, + 0x8CB2, 0x9E78, 0x8CB3, 0x5143, 0x8CB4, 0x539F, 0x8CB5, 0x53B3, 0x8CB6, 0x5E7B, 0x8CB7, 0x5F26, 0x8CB8, 0x6E1B, 0x8CB9, 0x6E90, + 0x8CBA, 0x7384, 0x8CBB, 0x73FE, 0x8CBC, 0x7D43, 0x8CBD, 0x8237, 0x8CBE, 0x8A00, 0x8CBF, 0x8AFA, 0x8CC0, 0x9650, 0x8CC1, 0x4E4E, + 0x8CC2, 0x500B, 0x8CC3, 0x53E4, 0x8CC4, 0x547C, 0x8CC5, 0x56FA, 0x8CC6, 0x59D1, 0x8CC7, 0x5B64, 0x8CC8, 0x5DF1, 0x8CC9, 0x5EAB, + 0x8CCA, 0x5F27, 0x8CCB, 0x6238, 0x8CCC, 0x6545, 0x8CCD, 0x67AF, 0x8CCE, 0x6E56, 0x8CCF, 0x72D0, 0x8CD0, 0x7CCA, 0x8CD1, 0x88B4, + 0x8CD2, 0x80A1, 0x8CD3, 0x80E1, 0x8CD4, 0x83F0, 0x8CD5, 0x864E, 0x8CD6, 0x8A87, 0x8CD7, 0x8DE8, 0x8CD8, 0x9237, 0x8CD9, 0x96C7, + 0x8CDA, 0x9867, 0x8CDB, 0x9F13, 0x8CDC, 0x4E94, 0x8CDD, 0x4E92, 0x8CDE, 0x4F0D, 0x8CDF, 0x5348, 0x8CE0, 0x5449, 0x8CE1, 0x543E, + 0x8CE2, 0x5A2F, 0x8CE3, 0x5F8C, 0x8CE4, 0x5FA1, 0x8CE5, 0x609F, 0x8CE6, 0x68A7, 0x8CE7, 0x6A8E, 0x8CE8, 0x745A, 0x8CE9, 0x7881, + 0x8CEA, 0x8A9E, 0x8CEB, 0x8AA4, 0x8CEC, 0x8B77, 0x8CED, 0x9190, 0x8CEE, 0x4E5E, 0x8CEF, 0x9BC9, 0x8CF0, 0x4EA4, 0x8CF1, 0x4F7C, + 0x8CF2, 0x4FAF, 0x8CF3, 0x5019, 0x8CF4, 0x5016, 0x8CF5, 0x5149, 0x8CF6, 0x516C, 0x8CF7, 0x529F, 0x8CF8, 0x52B9, 0x8CF9, 0x52FE, + 0x8CFA, 0x539A, 0x8CFB, 0x53E3, 0x8CFC, 0x5411, 0x8D40, 0x540E, 0x8D41, 0x5589, 0x8D42, 0x5751, 0x8D43, 0x57A2, 0x8D44, 0x597D, + 0x8D45, 0x5B54, 0x8D46, 0x5B5D, 0x8D47, 0x5B8F, 0x8D48, 0x5DE5, 0x8D49, 0x5DE7, 0x8D4A, 0x5DF7, 0x8D4B, 0x5E78, 0x8D4C, 0x5E83, + 0x8D4D, 0x5E9A, 0x8D4E, 0x5EB7, 0x8D4F, 0x5F18, 0x8D50, 0x6052, 0x8D51, 0x614C, 0x8D52, 0x6297, 0x8D53, 0x62D8, 0x8D54, 0x63A7, + 0x8D55, 0x653B, 0x8D56, 0x6602, 0x8D57, 0x6643, 0x8D58, 0x66F4, 0x8D59, 0x676D, 0x8D5A, 0x6821, 0x8D5B, 0x6897, 0x8D5C, 0x69CB, + 0x8D5D, 0x6C5F, 0x8D5E, 0x6D2A, 0x8D5F, 0x6D69, 0x8D60, 0x6E2F, 0x8D61, 0x6E9D, 0x8D62, 0x7532, 0x8D63, 0x7687, 0x8D64, 0x786C, + 0x8D65, 0x7A3F, 0x8D66, 0x7CE0, 0x8D67, 0x7D05, 0x8D68, 0x7D18, 0x8D69, 0x7D5E, 0x8D6A, 0x7DB1, 0x8D6B, 0x8015, 0x8D6C, 0x8003, + 0x8D6D, 0x80AF, 0x8D6E, 0x80B1, 0x8D6F, 0x8154, 0x8D70, 0x818F, 0x8D71, 0x822A, 0x8D72, 0x8352, 0x8D73, 0x884C, 0x8D74, 0x8861, + 0x8D75, 0x8B1B, 0x8D76, 0x8CA2, 0x8D77, 0x8CFC, 0x8D78, 0x90CA, 0x8D79, 0x9175, 0x8D7A, 0x9271, 0x8D7B, 0x783F, 0x8D7C, 0x92FC, + 0x8D7D, 0x95A4, 0x8D7E, 0x964D, 0x8D80, 0x9805, 0x8D81, 0x9999, 0x8D82, 0x9AD8, 0x8D83, 0x9D3B, 0x8D84, 0x525B, 0x8D85, 0x52AB, + 0x8D86, 0x53F7, 0x8D87, 0x5408, 0x8D88, 0x58D5, 0x8D89, 0x62F7, 0x8D8A, 0x6FE0, 0x8D8B, 0x8C6A, 0x8D8C, 0x8F5F, 0x8D8D, 0x9EB9, + 0x8D8E, 0x514B, 0x8D8F, 0x523B, 0x8D90, 0x544A, 0x8D91, 0x56FD, 0x8D92, 0x7A40, 0x8D93, 0x9177, 0x8D94, 0x9D60, 0x8D95, 0x9ED2, + 0x8D96, 0x7344, 0x8D97, 0x6F09, 0x8D98, 0x8170, 0x8D99, 0x7511, 0x8D9A, 0x5FFD, 0x8D9B, 0x60DA, 0x8D9C, 0x9AA8, 0x8D9D, 0x72DB, + 0x8D9E, 0x8FBC, 0x8D9F, 0x6B64, 0x8DA0, 0x9803, 0x8DA1, 0x4ECA, 0x8DA2, 0x56F0, 0x8DA3, 0x5764, 0x8DA4, 0x58BE, 0x8DA5, 0x5A5A, + 0x8DA6, 0x6068, 0x8DA7, 0x61C7, 0x8DA8, 0x660F, 0x8DA9, 0x6606, 0x8DAA, 0x6839, 0x8DAB, 0x68B1, 0x8DAC, 0x6DF7, 0x8DAD, 0x75D5, + 0x8DAE, 0x7D3A, 0x8DAF, 0x826E, 0x8DB0, 0x9B42, 0x8DB1, 0x4E9B, 0x8DB2, 0x4F50, 0x8DB3, 0x53C9, 0x8DB4, 0x5506, 0x8DB5, 0x5D6F, + 0x8DB6, 0x5DE6, 0x8DB7, 0x5DEE, 0x8DB8, 0x67FB, 0x8DB9, 0x6C99, 0x8DBA, 0x7473, 0x8DBB, 0x7802, 0x8DBC, 0x8A50, 0x8DBD, 0x9396, + 0x8DBE, 0x88DF, 0x8DBF, 0x5750, 0x8DC0, 0x5EA7, 0x8DC1, 0x632B, 0x8DC2, 0x50B5, 0x8DC3, 0x50AC, 0x8DC4, 0x518D, 0x8DC5, 0x6700, + 0x8DC6, 0x54C9, 0x8DC7, 0x585E, 0x8DC8, 0x59BB, 0x8DC9, 0x5BB0, 0x8DCA, 0x5F69, 0x8DCB, 0x624D, 0x8DCC, 0x63A1, 0x8DCD, 0x683D, + 0x8DCE, 0x6B73, 0x8DCF, 0x6E08, 0x8DD0, 0x707D, 0x8DD1, 0x91C7, 0x8DD2, 0x7280, 0x8DD3, 0x7815, 0x8DD4, 0x7826, 0x8DD5, 0x796D, + 0x8DD6, 0x658E, 0x8DD7, 0x7D30, 0x8DD8, 0x83DC, 0x8DD9, 0x88C1, 0x8DDA, 0x8F09, 0x8DDB, 0x969B, 0x8DDC, 0x5264, 0x8DDD, 0x5728, + 0x8DDE, 0x6750, 0x8DDF, 0x7F6A, 0x8DE0, 0x8CA1, 0x8DE1, 0x51B4, 0x8DE2, 0x5742, 0x8DE3, 0x962A, 0x8DE4, 0x583A, 0x8DE5, 0x698A, + 0x8DE6, 0x80B4, 0x8DE7, 0x54B2, 0x8DE8, 0x5D0E, 0x8DE9, 0x57FC, 0x8DEA, 0x7895, 0x8DEB, 0x9DFA, 0x8DEC, 0x4F5C, 0x8DED, 0x524A, + 0x8DEE, 0x548B, 0x8DEF, 0x643E, 0x8DF0, 0x6628, 0x8DF1, 0x6714, 0x8DF2, 0x67F5, 0x8DF3, 0x7A84, 0x8DF4, 0x7B56, 0x8DF5, 0x7D22, + 0x8DF6, 0x932F, 0x8DF7, 0x685C, 0x8DF8, 0x9BAD, 0x8DF9, 0x7B39, 0x8DFA, 0x5319, 0x8DFB, 0x518A, 0x8DFC, 0x5237, 0x8E40, 0x5BDF, + 0x8E41, 0x62F6, 0x8E42, 0x64AE, 0x8E43, 0x64E6, 0x8E44, 0x672D, 0x8E45, 0x6BBA, 0x8E46, 0x85A9, 0x8E47, 0x96D1, 0x8E48, 0x7690, + 0x8E49, 0x9BD6, 0x8E4A, 0x634C, 0x8E4B, 0x9306, 0x8E4C, 0x9BAB, 0x8E4D, 0x76BF, 0x8E4E, 0x6652, 0x8E4F, 0x4E09, 0x8E50, 0x5098, + 0x8E51, 0x53C2, 0x8E52, 0x5C71, 0x8E53, 0x60E8, 0x8E54, 0x6492, 0x8E55, 0x6563, 0x8E56, 0x685F, 0x8E57, 0x71E6, 0x8E58, 0x73CA, + 0x8E59, 0x7523, 0x8E5A, 0x7B97, 0x8E5B, 0x7E82, 0x8E5C, 0x8695, 0x8E5D, 0x8B83, 0x8E5E, 0x8CDB, 0x8E5F, 0x9178, 0x8E60, 0x9910, + 0x8E61, 0x65AC, 0x8E62, 0x66AB, 0x8E63, 0x6B8B, 0x8E64, 0x4ED5, 0x8E65, 0x4ED4, 0x8E66, 0x4F3A, 0x8E67, 0x4F7F, 0x8E68, 0x523A, + 0x8E69, 0x53F8, 0x8E6A, 0x53F2, 0x8E6B, 0x55E3, 0x8E6C, 0x56DB, 0x8E6D, 0x58EB, 0x8E6E, 0x59CB, 0x8E6F, 0x59C9, 0x8E70, 0x59FF, + 0x8E71, 0x5B50, 0x8E72, 0x5C4D, 0x8E73, 0x5E02, 0x8E74, 0x5E2B, 0x8E75, 0x5FD7, 0x8E76, 0x601D, 0x8E77, 0x6307, 0x8E78, 0x652F, + 0x8E79, 0x5B5C, 0x8E7A, 0x65AF, 0x8E7B, 0x65BD, 0x8E7C, 0x65E8, 0x8E7D, 0x679D, 0x8E7E, 0x6B62, 0x8E80, 0x6B7B, 0x8E81, 0x6C0F, + 0x8E82, 0x7345, 0x8E83, 0x7949, 0x8E84, 0x79C1, 0x8E85, 0x7CF8, 0x8E86, 0x7D19, 0x8E87, 0x7D2B, 0x8E88, 0x80A2, 0x8E89, 0x8102, + 0x8E8A, 0x81F3, 0x8E8B, 0x8996, 0x8E8C, 0x8A5E, 0x8E8D, 0x8A69, 0x8E8E, 0x8A66, 0x8E8F, 0x8A8C, 0x8E90, 0x8AEE, 0x8E91, 0x8CC7, + 0x8E92, 0x8CDC, 0x8E93, 0x96CC, 0x8E94, 0x98FC, 0x8E95, 0x6B6F, 0x8E96, 0x4E8B, 0x8E97, 0x4F3C, 0x8E98, 0x4F8D, 0x8E99, 0x5150, + 0x8E9A, 0x5B57, 0x8E9B, 0x5BFA, 0x8E9C, 0x6148, 0x8E9D, 0x6301, 0x8E9E, 0x6642, 0x8E9F, 0x6B21, 0x8EA0, 0x6ECB, 0x8EA1, 0x6CBB, + 0x8EA2, 0x723E, 0x8EA3, 0x74BD, 0x8EA4, 0x75D4, 0x8EA5, 0x78C1, 0x8EA6, 0x793A, 0x8EA7, 0x800C, 0x8EA8, 0x8033, 0x8EA9, 0x81EA, + 0x8EAA, 0x8494, 0x8EAB, 0x8F9E, 0x8EAC, 0x6C50, 0x8EAD, 0x9E7F, 0x8EAE, 0x5F0F, 0x8EAF, 0x8B58, 0x8EB0, 0x9D2B, 0x8EB1, 0x7AFA, + 0x8EB2, 0x8EF8, 0x8EB3, 0x5B8D, 0x8EB4, 0x96EB, 0x8EB5, 0x4E03, 0x8EB6, 0x53F1, 0x8EB7, 0x57F7, 0x8EB8, 0x5931, 0x8EB9, 0x5AC9, + 0x8EBA, 0x5BA4, 0x8EBB, 0x6089, 0x8EBC, 0x6E7F, 0x8EBD, 0x6F06, 0x8EBE, 0x75BE, 0x8EBF, 0x8CEA, 0x8EC0, 0x5B9F, 0x8EC1, 0x8500, + 0x8EC2, 0x7BE0, 0x8EC3, 0x5072, 0x8EC4, 0x67F4, 0x8EC5, 0x829D, 0x8EC6, 0x5C61, 0x8EC7, 0x854A, 0x8EC8, 0x7E1E, 0x8EC9, 0x820E, + 0x8ECA, 0x5199, 0x8ECB, 0x5C04, 0x8ECC, 0x6368, 0x8ECD, 0x8D66, 0x8ECE, 0x659C, 0x8ECF, 0x716E, 0x8ED0, 0x793E, 0x8ED1, 0x7D17, + 0x8ED2, 0x8005, 0x8ED3, 0x8B1D, 0x8ED4, 0x8ECA, 0x8ED5, 0x906E, 0x8ED6, 0x86C7, 0x8ED7, 0x90AA, 0x8ED8, 0x501F, 0x8ED9, 0x52FA, + 0x8EDA, 0x5C3A, 0x8EDB, 0x6753, 0x8EDC, 0x707C, 0x8EDD, 0x7235, 0x8EDE, 0x914C, 0x8EDF, 0x91C8, 0x8EE0, 0x932B, 0x8EE1, 0x82E5, + 0x8EE2, 0x5BC2, 0x8EE3, 0x5F31, 0x8EE4, 0x60F9, 0x8EE5, 0x4E3B, 0x8EE6, 0x53D6, 0x8EE7, 0x5B88, 0x8EE8, 0x624B, 0x8EE9, 0x6731, + 0x8EEA, 0x6B8A, 0x8EEB, 0x72E9, 0x8EEC, 0x73E0, 0x8EED, 0x7A2E, 0x8EEE, 0x816B, 0x8EEF, 0x8DA3, 0x8EF0, 0x9152, 0x8EF1, 0x9996, + 0x8EF2, 0x5112, 0x8EF3, 0x53D7, 0x8EF4, 0x546A, 0x8EF5, 0x5BFF, 0x8EF6, 0x6388, 0x8EF7, 0x6A39, 0x8EF8, 0x7DAC, 0x8EF9, 0x9700, + 0x8EFA, 0x56DA, 0x8EFB, 0x53CE, 0x8EFC, 0x5468, 0x8F40, 0x5B97, 0x8F41, 0x5C31, 0x8F42, 0x5DDE, 0x8F43, 0x4FEE, 0x8F44, 0x6101, + 0x8F45, 0x62FE, 0x8F46, 0x6D32, 0x8F47, 0x79C0, 0x8F48, 0x79CB, 0x8F49, 0x7D42, 0x8F4A, 0x7E4D, 0x8F4B, 0x7FD2, 0x8F4C, 0x81ED, + 0x8F4D, 0x821F, 0x8F4E, 0x8490, 0x8F4F, 0x8846, 0x8F50, 0x8972, 0x8F51, 0x8B90, 0x8F52, 0x8E74, 0x8F53, 0x8F2F, 0x8F54, 0x9031, + 0x8F55, 0x914B, 0x8F56, 0x916C, 0x8F57, 0x96C6, 0x8F58, 0x919C, 0x8F59, 0x4EC0, 0x8F5A, 0x4F4F, 0x8F5B, 0x5145, 0x8F5C, 0x5341, + 0x8F5D, 0x5F93, 0x8F5E, 0x620E, 0x8F5F, 0x67D4, 0x8F60, 0x6C41, 0x8F61, 0x6E0B, 0x8F62, 0x7363, 0x8F63, 0x7E26, 0x8F64, 0x91CD, + 0x8F65, 0x9283, 0x8F66, 0x53D4, 0x8F67, 0x5919, 0x8F68, 0x5BBF, 0x8F69, 0x6DD1, 0x8F6A, 0x795D, 0x8F6B, 0x7E2E, 0x8F6C, 0x7C9B, + 0x8F6D, 0x587E, 0x8F6E, 0x719F, 0x8F6F, 0x51FA, 0x8F70, 0x8853, 0x8F71, 0x8FF0, 0x8F72, 0x4FCA, 0x8F73, 0x5CFB, 0x8F74, 0x6625, + 0x8F75, 0x77AC, 0x8F76, 0x7AE3, 0x8F77, 0x821C, 0x8F78, 0x99FF, 0x8F79, 0x51C6, 0x8F7A, 0x5FAA, 0x8F7B, 0x65EC, 0x8F7C, 0x696F, + 0x8F7D, 0x6B89, 0x8F7E, 0x6DF3, 0x8F80, 0x6E96, 0x8F81, 0x6F64, 0x8F82, 0x76FE, 0x8F83, 0x7D14, 0x8F84, 0x5DE1, 0x8F85, 0x9075, + 0x8F86, 0x9187, 0x8F87, 0x9806, 0x8F88, 0x51E6, 0x8F89, 0x521D, 0x8F8A, 0x6240, 0x8F8B, 0x6691, 0x8F8C, 0x66D9, 0x8F8D, 0x6E1A, + 0x8F8E, 0x5EB6, 0x8F8F, 0x7DD2, 0x8F90, 0x7F72, 0x8F91, 0x66F8, 0x8F92, 0x85AF, 0x8F93, 0x85F7, 0x8F94, 0x8AF8, 0x8F95, 0x52A9, + 0x8F96, 0x53D9, 0x8F97, 0x5973, 0x8F98, 0x5E8F, 0x8F99, 0x5F90, 0x8F9A, 0x6055, 0x8F9B, 0x92E4, 0x8F9C, 0x9664, 0x8F9D, 0x50B7, + 0x8F9E, 0x511F, 0x8F9F, 0x52DD, 0x8FA0, 0x5320, 0x8FA1, 0x5347, 0x8FA2, 0x53EC, 0x8FA3, 0x54E8, 0x8FA4, 0x5546, 0x8FA5, 0x5531, + 0x8FA6, 0x5617, 0x8FA7, 0x5968, 0x8FA8, 0x59BE, 0x8FA9, 0x5A3C, 0x8FAA, 0x5BB5, 0x8FAB, 0x5C06, 0x8FAC, 0x5C0F, 0x8FAD, 0x5C11, + 0x8FAE, 0x5C1A, 0x8FAF, 0x5E84, 0x8FB0, 0x5E8A, 0x8FB1, 0x5EE0, 0x8FB2, 0x5F70, 0x8FB3, 0x627F, 0x8FB4, 0x6284, 0x8FB5, 0x62DB, + 0x8FB6, 0x638C, 0x8FB7, 0x6377, 0x8FB8, 0x6607, 0x8FB9, 0x660C, 0x8FBA, 0x662D, 0x8FBB, 0x6676, 0x8FBC, 0x677E, 0x8FBD, 0x68A2, + 0x8FBE, 0x6A1F, 0x8FBF, 0x6A35, 0x8FC0, 0x6CBC, 0x8FC1, 0x6D88, 0x8FC2, 0x6E09, 0x8FC3, 0x6E58, 0x8FC4, 0x713C, 0x8FC5, 0x7126, + 0x8FC6, 0x7167, 0x8FC7, 0x75C7, 0x8FC8, 0x7701, 0x8FC9, 0x785D, 0x8FCA, 0x7901, 0x8FCB, 0x7965, 0x8FCC, 0x79F0, 0x8FCD, 0x7AE0, + 0x8FCE, 0x7B11, 0x8FCF, 0x7CA7, 0x8FD0, 0x7D39, 0x8FD1, 0x8096, 0x8FD2, 0x83D6, 0x8FD3, 0x848B, 0x8FD4, 0x8549, 0x8FD5, 0x885D, + 0x8FD6, 0x88F3, 0x8FD7, 0x8A1F, 0x8FD8, 0x8A3C, 0x8FD9, 0x8A54, 0x8FDA, 0x8A73, 0x8FDB, 0x8C61, 0x8FDC, 0x8CDE, 0x8FDD, 0x91A4, + 0x8FDE, 0x9266, 0x8FDF, 0x937E, 0x8FE0, 0x9418, 0x8FE1, 0x969C, 0x8FE2, 0x9798, 0x8FE3, 0x4E0A, 0x8FE4, 0x4E08, 0x8FE5, 0x4E1E, + 0x8FE6, 0x4E57, 0x8FE7, 0x5197, 0x8FE8, 0x5270, 0x8FE9, 0x57CE, 0x8FEA, 0x5834, 0x8FEB, 0x58CC, 0x8FEC, 0x5B22, 0x8FED, 0x5E38, + 0x8FEE, 0x60C5, 0x8FEF, 0x64FE, 0x8FF0, 0x6761, 0x8FF1, 0x6756, 0x8FF2, 0x6D44, 0x8FF3, 0x72B6, 0x8FF4, 0x7573, 0x8FF5, 0x7A63, + 0x8FF6, 0x84B8, 0x8FF7, 0x8B72, 0x8FF8, 0x91B8, 0x8FF9, 0x9320, 0x8FFA, 0x5631, 0x8FFB, 0x57F4, 0x8FFC, 0x98FE, 0x9040, 0x62ED, + 0x9041, 0x690D, 0x9042, 0x6B96, 0x9043, 0x71ED, 0x9044, 0x7E54, 0x9045, 0x8077, 0x9046, 0x8272, 0x9047, 0x89E6, 0x9048, 0x98DF, + 0x9049, 0x8755, 0x904A, 0x8FB1, 0x904B, 0x5C3B, 0x904C, 0x4F38, 0x904D, 0x4FE1, 0x904E, 0x4FB5, 0x904F, 0x5507, 0x9050, 0x5A20, + 0x9051, 0x5BDD, 0x9052, 0x5BE9, 0x9053, 0x5FC3, 0x9054, 0x614E, 0x9055, 0x632F, 0x9056, 0x65B0, 0x9057, 0x664B, 0x9058, 0x68EE, + 0x9059, 0x699B, 0x905A, 0x6D78, 0x905B, 0x6DF1, 0x905C, 0x7533, 0x905D, 0x75B9, 0x905E, 0x771F, 0x905F, 0x795E, 0x9060, 0x79E6, + 0x9061, 0x7D33, 0x9062, 0x81E3, 0x9063, 0x82AF, 0x9064, 0x85AA, 0x9065, 0x89AA, 0x9066, 0x8A3A, 0x9067, 0x8EAB, 0x9068, 0x8F9B, + 0x9069, 0x9032, 0x906A, 0x91DD, 0x906B, 0x9707, 0x906C, 0x4EBA, 0x906D, 0x4EC1, 0x906E, 0x5203, 0x906F, 0x5875, 0x9070, 0x58EC, + 0x9071, 0x5C0B, 0x9072, 0x751A, 0x9073, 0x5C3D, 0x9074, 0x814E, 0x9075, 0x8A0A, 0x9076, 0x8FC5, 0x9077, 0x9663, 0x9078, 0x976D, + 0x9079, 0x7B25, 0x907A, 0x8ACF, 0x907B, 0x9808, 0x907C, 0x9162, 0x907D, 0x56F3, 0x907E, 0x53A8, 0x9080, 0x9017, 0x9081, 0x5439, + 0x9082, 0x5782, 0x9083, 0x5E25, 0x9084, 0x63A8, 0x9085, 0x6C34, 0x9086, 0x708A, 0x9087, 0x7761, 0x9088, 0x7C8B, 0x9089, 0x7FE0, + 0x908A, 0x8870, 0x908B, 0x9042, 0x908C, 0x9154, 0x908D, 0x9310, 0x908E, 0x9318, 0x908F, 0x968F, 0x9090, 0x745E, 0x9091, 0x9AC4, + 0x9092, 0x5D07, 0x9093, 0x5D69, 0x9094, 0x6570, 0x9095, 0x67A2, 0x9096, 0x8DA8, 0x9097, 0x96DB, 0x9098, 0x636E, 0x9099, 0x6749, + 0x909A, 0x6919, 0x909B, 0x83C5, 0x909C, 0x9817, 0x909D, 0x96C0, 0x909E, 0x88FE, 0x909F, 0x6F84, 0x90A0, 0x647A, 0x90A1, 0x5BF8, + 0x90A2, 0x4E16, 0x90A3, 0x702C, 0x90A4, 0x755D, 0x90A5, 0x662F, 0x90A6, 0x51C4, 0x90A7, 0x5236, 0x90A8, 0x52E2, 0x90A9, 0x59D3, + 0x90AA, 0x5F81, 0x90AB, 0x6027, 0x90AC, 0x6210, 0x90AD, 0x653F, 0x90AE, 0x6574, 0x90AF, 0x661F, 0x90B0, 0x6674, 0x90B1, 0x68F2, + 0x90B2, 0x6816, 0x90B3, 0x6B63, 0x90B4, 0x6E05, 0x90B5, 0x7272, 0x90B6, 0x751F, 0x90B7, 0x76DB, 0x90B8, 0x7CBE, 0x90B9, 0x8056, + 0x90BA, 0x58F0, 0x90BB, 0x88FD, 0x90BC, 0x897F, 0x90BD, 0x8AA0, 0x90BE, 0x8A93, 0x90BF, 0x8ACB, 0x90C0, 0x901D, 0x90C1, 0x9192, + 0x90C2, 0x9752, 0x90C3, 0x9759, 0x90C4, 0x6589, 0x90C5, 0x7A0E, 0x90C6, 0x8106, 0x90C7, 0x96BB, 0x90C8, 0x5E2D, 0x90C9, 0x60DC, + 0x90CA, 0x621A, 0x90CB, 0x65A5, 0x90CC, 0x6614, 0x90CD, 0x6790, 0x90CE, 0x77F3, 0x90CF, 0x7A4D, 0x90D0, 0x7C4D, 0x90D1, 0x7E3E, + 0x90D2, 0x810A, 0x90D3, 0x8CAC, 0x90D4, 0x8D64, 0x90D5, 0x8DE1, 0x90D6, 0x8E5F, 0x90D7, 0x78A9, 0x90D8, 0x5207, 0x90D9, 0x62D9, + 0x90DA, 0x63A5, 0x90DB, 0x6442, 0x90DC, 0x6298, 0x90DD, 0x8A2D, 0x90DE, 0x7A83, 0x90DF, 0x7BC0, 0x90E0, 0x8AAC, 0x90E1, 0x96EA, + 0x90E2, 0x7D76, 0x90E3, 0x820C, 0x90E4, 0x8749, 0x90E5, 0x4ED9, 0x90E6, 0x5148, 0x90E7, 0x5343, 0x90E8, 0x5360, 0x90E9, 0x5BA3, + 0x90EA, 0x5C02, 0x90EB, 0x5C16, 0x90EC, 0x5DDD, 0x90ED, 0x6226, 0x90EE, 0x6247, 0x90EF, 0x64B0, 0x90F0, 0x6813, 0x90F1, 0x6834, + 0x90F2, 0x6CC9, 0x90F3, 0x6D45, 0x90F4, 0x6D17, 0x90F5, 0x67D3, 0x90F6, 0x6F5C, 0x90F7, 0x714E, 0x90F8, 0x717D, 0x90F9, 0x65CB, + 0x90FA, 0x7A7F, 0x90FB, 0x7BAD, 0x90FC, 0x7DDA, 0x9140, 0x7E4A, 0x9141, 0x7FA8, 0x9142, 0x817A, 0x9143, 0x821B, 0x9144, 0x8239, + 0x9145, 0x85A6, 0x9146, 0x8A6E, 0x9147, 0x8CCE, 0x9148, 0x8DF5, 0x9149, 0x9078, 0x914A, 0x9077, 0x914B, 0x92AD, 0x914C, 0x9291, + 0x914D, 0x9583, 0x914E, 0x9BAE, 0x914F, 0x524D, 0x9150, 0x5584, 0x9151, 0x6F38, 0x9152, 0x7136, 0x9153, 0x5168, 0x9154, 0x7985, + 0x9155, 0x7E55, 0x9156, 0x81B3, 0x9157, 0x7CCE, 0x9158, 0x564C, 0x9159, 0x5851, 0x915A, 0x5CA8, 0x915B, 0x63AA, 0x915C, 0x66FE, + 0x915D, 0x66FD, 0x915E, 0x695A, 0x915F, 0x72D9, 0x9160, 0x758F, 0x9161, 0x758E, 0x9162, 0x790E, 0x9163, 0x7956, 0x9164, 0x79DF, + 0x9165, 0x7C97, 0x9166, 0x7D20, 0x9167, 0x7D44, 0x9168, 0x8607, 0x9169, 0x8A34, 0x916A, 0x963B, 0x916B, 0x9061, 0x916C, 0x9F20, + 0x916D, 0x50E7, 0x916E, 0x5275, 0x916F, 0x53CC, 0x9170, 0x53E2, 0x9171, 0x5009, 0x9172, 0x55AA, 0x9173, 0x58EE, 0x9174, 0x594F, + 0x9175, 0x723D, 0x9176, 0x5B8B, 0x9177, 0x5C64, 0x9178, 0x531D, 0x9179, 0x60E3, 0x917A, 0x60F3, 0x917B, 0x635C, 0x917C, 0x6383, + 0x917D, 0x633F, 0x917E, 0x63BB, 0x9180, 0x64CD, 0x9181, 0x65E9, 0x9182, 0x66F9, 0x9183, 0x5DE3, 0x9184, 0x69CD, 0x9185, 0x69FD, + 0x9186, 0x6F15, 0x9187, 0x71E5, 0x9188, 0x4E89, 0x9189, 0x75E9, 0x918A, 0x76F8, 0x918B, 0x7A93, 0x918C, 0x7CDF, 0x918D, 0x7DCF, + 0x918E, 0x7D9C, 0x918F, 0x8061, 0x9190, 0x8349, 0x9191, 0x8358, 0x9192, 0x846C, 0x9193, 0x84BC, 0x9194, 0x85FB, 0x9195, 0x88C5, + 0x9196, 0x8D70, 0x9197, 0x9001, 0x9198, 0x906D, 0x9199, 0x9397, 0x919A, 0x971C, 0x919B, 0x9A12, 0x919C, 0x50CF, 0x919D, 0x5897, + 0x919E, 0x618E, 0x919F, 0x81D3, 0x91A0, 0x8535, 0x91A1, 0x8D08, 0x91A2, 0x9020, 0x91A3, 0x4FC3, 0x91A4, 0x5074, 0x91A5, 0x5247, + 0x91A6, 0x5373, 0x91A7, 0x606F, 0x91A8, 0x6349, 0x91A9, 0x675F, 0x91AA, 0x6E2C, 0x91AB, 0x8DB3, 0x91AC, 0x901F, 0x91AD, 0x4FD7, + 0x91AE, 0x5C5E, 0x91AF, 0x8CCA, 0x91B0, 0x65CF, 0x91B1, 0x7D9A, 0x91B2, 0x5352, 0x91B3, 0x8896, 0x91B4, 0x5176, 0x91B5, 0x63C3, + 0x91B6, 0x5B58, 0x91B7, 0x5B6B, 0x91B8, 0x5C0A, 0x91B9, 0x640D, 0x91BA, 0x6751, 0x91BB, 0x905C, 0x91BC, 0x4ED6, 0x91BD, 0x591A, + 0x91BE, 0x592A, 0x91BF, 0x6C70, 0x91C0, 0x8A51, 0x91C1, 0x553E, 0x91C2, 0x5815, 0x91C3, 0x59A5, 0x91C4, 0x60F0, 0x91C5, 0x6253, + 0x91C6, 0x67C1, 0x91C7, 0x8235, 0x91C8, 0x6955, 0x91C9, 0x9640, 0x91CA, 0x99C4, 0x91CB, 0x9A28, 0x91CC, 0x4F53, 0x91CD, 0x5806, + 0x91CE, 0x5BFE, 0x91CF, 0x8010, 0x91D0, 0x5CB1, 0x91D1, 0x5E2F, 0x91D2, 0x5F85, 0x91D3, 0x6020, 0x91D4, 0x614B, 0x91D5, 0x6234, + 0x91D6, 0x66FF, 0x91D7, 0x6CF0, 0x91D8, 0x6EDE, 0x91D9, 0x80CE, 0x91DA, 0x817F, 0x91DB, 0x82D4, 0x91DC, 0x888B, 0x91DD, 0x8CB8, + 0x91DE, 0x9000, 0x91DF, 0x902E, 0x91E0, 0x968A, 0x91E1, 0x9EDB, 0x91E2, 0x9BDB, 0x91E3, 0x4EE3, 0x91E4, 0x53F0, 0x91E5, 0x5927, + 0x91E6, 0x7B2C, 0x91E7, 0x918D, 0x91E8, 0x984C, 0x91E9, 0x9DF9, 0x91EA, 0x6EDD, 0x91EB, 0x7027, 0x91EC, 0x5353, 0x91ED, 0x5544, + 0x91EE, 0x5B85, 0x91EF, 0x6258, 0x91F0, 0x629E, 0x91F1, 0x62D3, 0x91F2, 0x6CA2, 0x91F3, 0x6FEF, 0x91F4, 0x7422, 0x91F5, 0x8A17, + 0x91F6, 0x9438, 0x91F7, 0x6FC1, 0x91F8, 0x8AFE, 0x91F9, 0x8338, 0x91FA, 0x51E7, 0x91FB, 0x86F8, 0x91FC, 0x53EA, 0x9240, 0x53E9, + 0x9241, 0x4F46, 0x9242, 0x9054, 0x9243, 0x8FB0, 0x9244, 0x596A, 0x9245, 0x8131, 0x9246, 0x5DFD, 0x9247, 0x7AEA, 0x9248, 0x8FBF, + 0x9249, 0x68DA, 0x924A, 0x8C37, 0x924B, 0x72F8, 0x924C, 0x9C48, 0x924D, 0x6A3D, 0x924E, 0x8AB0, 0x924F, 0x4E39, 0x9250, 0x5358, + 0x9251, 0x5606, 0x9252, 0x5766, 0x9253, 0x62C5, 0x9254, 0x63A2, 0x9255, 0x65E6, 0x9256, 0x6B4E, 0x9257, 0x6DE1, 0x9258, 0x6E5B, + 0x9259, 0x70AD, 0x925A, 0x77ED, 0x925B, 0x7AEF, 0x925C, 0x7BAA, 0x925D, 0x7DBB, 0x925E, 0x803D, 0x925F, 0x80C6, 0x9260, 0x86CB, + 0x9261, 0x8A95, 0x9262, 0x935B, 0x9263, 0x56E3, 0x9264, 0x58C7, 0x9265, 0x5F3E, 0x9266, 0x65AD, 0x9267, 0x6696, 0x9268, 0x6A80, + 0x9269, 0x6BB5, 0x926A, 0x7537, 0x926B, 0x8AC7, 0x926C, 0x5024, 0x926D, 0x77E5, 0x926E, 0x5730, 0x926F, 0x5F1B, 0x9270, 0x6065, + 0x9271, 0x667A, 0x9272, 0x6C60, 0x9273, 0x75F4, 0x9274, 0x7A1A, 0x9275, 0x7F6E, 0x9276, 0x81F4, 0x9277, 0x8718, 0x9278, 0x9045, + 0x9279, 0x99B3, 0x927A, 0x7BC9, 0x927B, 0x755C, 0x927C, 0x7AF9, 0x927D, 0x7B51, 0x927E, 0x84C4, 0x9280, 0x9010, 0x9281, 0x79E9, + 0x9282, 0x7A92, 0x9283, 0x8336, 0x9284, 0x5AE1, 0x9285, 0x7740, 0x9286, 0x4E2D, 0x9287, 0x4EF2, 0x9288, 0x5B99, 0x9289, 0x5FE0, + 0x928A, 0x62BD, 0x928B, 0x663C, 0x928C, 0x67F1, 0x928D, 0x6CE8, 0x928E, 0x866B, 0x928F, 0x8877, 0x9290, 0x8A3B, 0x9291, 0x914E, + 0x9292, 0x92F3, 0x9293, 0x99D0, 0x9294, 0x6A17, 0x9295, 0x7026, 0x9296, 0x732A, 0x9297, 0x82E7, 0x9298, 0x8457, 0x9299, 0x8CAF, + 0x929A, 0x4E01, 0x929B, 0x5146, 0x929C, 0x51CB, 0x929D, 0x558B, 0x929E, 0x5BF5, 0x929F, 0x5E16, 0x92A0, 0x5E33, 0x92A1, 0x5E81, + 0x92A2, 0x5F14, 0x92A3, 0x5F35, 0x92A4, 0x5F6B, 0x92A5, 0x5FB4, 0x92A6, 0x61F2, 0x92A7, 0x6311, 0x92A8, 0x66A2, 0x92A9, 0x671D, + 0x92AA, 0x6F6E, 0x92AB, 0x7252, 0x92AC, 0x753A, 0x92AD, 0x773A, 0x92AE, 0x8074, 0x92AF, 0x8139, 0x92B0, 0x8178, 0x92B1, 0x8776, + 0x92B2, 0x8ABF, 0x92B3, 0x8ADC, 0x92B4, 0x8D85, 0x92B5, 0x8DF3, 0x92B6, 0x929A, 0x92B7, 0x9577, 0x92B8, 0x9802, 0x92B9, 0x9CE5, + 0x92BA, 0x52C5, 0x92BB, 0x6357, 0x92BC, 0x76F4, 0x92BD, 0x6715, 0x92BE, 0x6C88, 0x92BF, 0x73CD, 0x92C0, 0x8CC3, 0x92C1, 0x93AE, + 0x92C2, 0x9673, 0x92C3, 0x6D25, 0x92C4, 0x589C, 0x92C5, 0x690E, 0x92C6, 0x69CC, 0x92C7, 0x8FFD, 0x92C8, 0x939A, 0x92C9, 0x75DB, + 0x92CA, 0x901A, 0x92CB, 0x585A, 0x92CC, 0x6802, 0x92CD, 0x63B4, 0x92CE, 0x69FB, 0x92CF, 0x4F43, 0x92D0, 0x6F2C, 0x92D1, 0x67D8, + 0x92D2, 0x8FBB, 0x92D3, 0x8526, 0x92D4, 0x7DB4, 0x92D5, 0x9354, 0x92D6, 0x693F, 0x92D7, 0x6F70, 0x92D8, 0x576A, 0x92D9, 0x58F7, + 0x92DA, 0x5B2C, 0x92DB, 0x7D2C, 0x92DC, 0x722A, 0x92DD, 0x540A, 0x92DE, 0x91E3, 0x92DF, 0x9DB4, 0x92E0, 0x4EAD, 0x92E1, 0x4F4E, + 0x92E2, 0x505C, 0x92E3, 0x5075, 0x92E4, 0x5243, 0x92E5, 0x8C9E, 0x92E6, 0x5448, 0x92E7, 0x5824, 0x92E8, 0x5B9A, 0x92E9, 0x5E1D, + 0x92EA, 0x5E95, 0x92EB, 0x5EAD, 0x92EC, 0x5EF7, 0x92ED, 0x5F1F, 0x92EE, 0x608C, 0x92EF, 0x62B5, 0x92F0, 0x633A, 0x92F1, 0x63D0, + 0x92F2, 0x68AF, 0x92F3, 0x6C40, 0x92F4, 0x7887, 0x92F5, 0x798E, 0x92F6, 0x7A0B, 0x92F7, 0x7DE0, 0x92F8, 0x8247, 0x92F9, 0x8A02, + 0x92FA, 0x8AE6, 0x92FB, 0x8E44, 0x92FC, 0x9013, 0x9340, 0x90B8, 0x9341, 0x912D, 0x9342, 0x91D8, 0x9343, 0x9F0E, 0x9344, 0x6CE5, + 0x9345, 0x6458, 0x9346, 0x64E2, 0x9347, 0x6575, 0x9348, 0x6EF4, 0x9349, 0x7684, 0x934A, 0x7B1B, 0x934B, 0x9069, 0x934C, 0x93D1, + 0x934D, 0x6EBA, 0x934E, 0x54F2, 0x934F, 0x5FB9, 0x9350, 0x64A4, 0x9351, 0x8F4D, 0x9352, 0x8FED, 0x9353, 0x9244, 0x9354, 0x5178, + 0x9355, 0x586B, 0x9356, 0x5929, 0x9357, 0x5C55, 0x9358, 0x5E97, 0x9359, 0x6DFB, 0x935A, 0x7E8F, 0x935B, 0x751C, 0x935C, 0x8CBC, + 0x935D, 0x8EE2, 0x935E, 0x985B, 0x935F, 0x70B9, 0x9360, 0x4F1D, 0x9361, 0x6BBF, 0x9362, 0x6FB1, 0x9363, 0x7530, 0x9364, 0x96FB, + 0x9365, 0x514E, 0x9366, 0x5410, 0x9367, 0x5835, 0x9368, 0x5857, 0x9369, 0x59AC, 0x936A, 0x5C60, 0x936B, 0x5F92, 0x936C, 0x6597, + 0x936D, 0x675C, 0x936E, 0x6E21, 0x936F, 0x767B, 0x9370, 0x83DF, 0x9371, 0x8CED, 0x9372, 0x9014, 0x9373, 0x90FD, 0x9374, 0x934D, + 0x9375, 0x7825, 0x9376, 0x783A, 0x9377, 0x52AA, 0x9378, 0x5EA6, 0x9379, 0x571F, 0x937A, 0x5974, 0x937B, 0x6012, 0x937C, 0x5012, + 0x937D, 0x515A, 0x937E, 0x51AC, 0x9380, 0x51CD, 0x9381, 0x5200, 0x9382, 0x5510, 0x9383, 0x5854, 0x9384, 0x5858, 0x9385, 0x5957, + 0x9386, 0x5B95, 0x9387, 0x5CF6, 0x9388, 0x5D8B, 0x9389, 0x60BC, 0x938A, 0x6295, 0x938B, 0x642D, 0x938C, 0x6771, 0x938D, 0x6843, + 0x938E, 0x68BC, 0x938F, 0x68DF, 0x9390, 0x76D7, 0x9391, 0x6DD8, 0x9392, 0x6E6F, 0x9393, 0x6D9B, 0x9394, 0x706F, 0x9395, 0x71C8, + 0x9396, 0x5F53, 0x9397, 0x75D8, 0x9398, 0x7977, 0x9399, 0x7B49, 0x939A, 0x7B54, 0x939B, 0x7B52, 0x939C, 0x7CD6, 0x939D, 0x7D71, + 0x939E, 0x5230, 0x939F, 0x8463, 0x93A0, 0x8569, 0x93A1, 0x85E4, 0x93A2, 0x8A0E, 0x93A3, 0x8B04, 0x93A4, 0x8C46, 0x93A5, 0x8E0F, + 0x93A6, 0x9003, 0x93A7, 0x900F, 0x93A8, 0x9419, 0x93A9, 0x9676, 0x93AA, 0x982D, 0x93AB, 0x9A30, 0x93AC, 0x95D8, 0x93AD, 0x50CD, + 0x93AE, 0x52D5, 0x93AF, 0x540C, 0x93B0, 0x5802, 0x93B1, 0x5C0E, 0x93B2, 0x61A7, 0x93B3, 0x649E, 0x93B4, 0x6D1E, 0x93B5, 0x77B3, + 0x93B6, 0x7AE5, 0x93B7, 0x80F4, 0x93B8, 0x8404, 0x93B9, 0x9053, 0x93BA, 0x9285, 0x93BB, 0x5CE0, 0x93BC, 0x9D07, 0x93BD, 0x533F, + 0x93BE, 0x5F97, 0x93BF, 0x5FB3, 0x93C0, 0x6D9C, 0x93C1, 0x7279, 0x93C2, 0x7763, 0x93C3, 0x79BF, 0x93C4, 0x7BE4, 0x93C5, 0x6BD2, + 0x93C6, 0x72EC, 0x93C7, 0x8AAD, 0x93C8, 0x6803, 0x93C9, 0x6A61, 0x93CA, 0x51F8, 0x93CB, 0x7A81, 0x93CC, 0x6934, 0x93CD, 0x5C4A, + 0x93CE, 0x9CF6, 0x93CF, 0x82EB, 0x93D0, 0x5BC5, 0x93D1, 0x9149, 0x93D2, 0x701E, 0x93D3, 0x5678, 0x93D4, 0x5C6F, 0x93D5, 0x60C7, + 0x93D6, 0x6566, 0x93D7, 0x6C8C, 0x93D8, 0x8C5A, 0x93D9, 0x9041, 0x93DA, 0x9813, 0x93DB, 0x5451, 0x93DC, 0x66C7, 0x93DD, 0x920D, + 0x93DE, 0x5948, 0x93DF, 0x90A3, 0x93E0, 0x5185, 0x93E1, 0x4E4D, 0x93E2, 0x51EA, 0x93E3, 0x8599, 0x93E4, 0x8B0E, 0x93E5, 0x7058, + 0x93E6, 0x637A, 0x93E7, 0x934B, 0x93E8, 0x6962, 0x93E9, 0x99B4, 0x93EA, 0x7E04, 0x93EB, 0x7577, 0x93EC, 0x5357, 0x93ED, 0x6960, + 0x93EE, 0x8EDF, 0x93EF, 0x96E3, 0x93F0, 0x6C5D, 0x93F1, 0x4E8C, 0x93F2, 0x5C3C, 0x93F3, 0x5F10, 0x93F4, 0x8FE9, 0x93F5, 0x5302, + 0x93F6, 0x8CD1, 0x93F7, 0x8089, 0x93F8, 0x8679, 0x93F9, 0x5EFF, 0x93FA, 0x65E5, 0x93FB, 0x4E73, 0x93FC, 0x5165, 0x9440, 0x5982, + 0x9441, 0x5C3F, 0x9442, 0x97EE, 0x9443, 0x4EFB, 0x9444, 0x598A, 0x9445, 0x5FCD, 0x9446, 0x8A8D, 0x9447, 0x6FE1, 0x9448, 0x79B0, + 0x9449, 0x7962, 0x944A, 0x5BE7, 0x944B, 0x8471, 0x944C, 0x732B, 0x944D, 0x71B1, 0x944E, 0x5E74, 0x944F, 0x5FF5, 0x9450, 0x637B, + 0x9451, 0x649A, 0x9452, 0x71C3, 0x9453, 0x7C98, 0x9454, 0x4E43, 0x9455, 0x5EFC, 0x9456, 0x4E4B, 0x9457, 0x57DC, 0x9458, 0x56A2, + 0x9459, 0x60A9, 0x945A, 0x6FC3, 0x945B, 0x7D0D, 0x945C, 0x80FD, 0x945D, 0x8133, 0x945E, 0x81BF, 0x945F, 0x8FB2, 0x9460, 0x8997, + 0x9461, 0x86A4, 0x9462, 0x5DF4, 0x9463, 0x628A, 0x9464, 0x64AD, 0x9465, 0x8987, 0x9466, 0x6777, 0x9467, 0x6CE2, 0x9468, 0x6D3E, + 0x9469, 0x7436, 0x946A, 0x7834, 0x946B, 0x5A46, 0x946C, 0x7F75, 0x946D, 0x82AD, 0x946E, 0x99AC, 0x946F, 0x4FF3, 0x9470, 0x5EC3, + 0x9471, 0x62DD, 0x9472, 0x6392, 0x9473, 0x6557, 0x9474, 0x676F, 0x9475, 0x76C3, 0x9476, 0x724C, 0x9477, 0x80CC, 0x9478, 0x80BA, + 0x9479, 0x8F29, 0x947A, 0x914D, 0x947B, 0x500D, 0x947C, 0x57F9, 0x947D, 0x5A92, 0x947E, 0x6885, 0x9480, 0x6973, 0x9481, 0x7164, + 0x9482, 0x72FD, 0x9483, 0x8CB7, 0x9484, 0x58F2, 0x9485, 0x8CE0, 0x9486, 0x966A, 0x9487, 0x9019, 0x9488, 0x877F, 0x9489, 0x79E4, + 0x948A, 0x77E7, 0x948B, 0x8429, 0x948C, 0x4F2F, 0x948D, 0x5265, 0x948E, 0x535A, 0x948F, 0x62CD, 0x9490, 0x67CF, 0x9491, 0x6CCA, + 0x9492, 0x767D, 0x9493, 0x7B94, 0x9494, 0x7C95, 0x9495, 0x8236, 0x9496, 0x8584, 0x9497, 0x8FEB, 0x9498, 0x66DD, 0x9499, 0x6F20, + 0x949A, 0x7206, 0x949B, 0x7E1B, 0x949C, 0x83AB, 0x949D, 0x99C1, 0x949E, 0x9EA6, 0x949F, 0x51FD, 0x94A0, 0x7BB1, 0x94A1, 0x7872, + 0x94A2, 0x7BB8, 0x94A3, 0x8087, 0x94A4, 0x7B48, 0x94A5, 0x6AE8, 0x94A6, 0x5E61, 0x94A7, 0x808C, 0x94A8, 0x7551, 0x94A9, 0x7560, + 0x94AA, 0x516B, 0x94AB, 0x9262, 0x94AC, 0x6E8C, 0x94AD, 0x767A, 0x94AE, 0x9197, 0x94AF, 0x9AEA, 0x94B0, 0x4F10, 0x94B1, 0x7F70, + 0x94B2, 0x629C, 0x94B3, 0x7B4F, 0x94B4, 0x95A5, 0x94B5, 0x9CE9, 0x94B6, 0x567A, 0x94B7, 0x5859, 0x94B8, 0x86E4, 0x94B9, 0x96BC, + 0x94BA, 0x4F34, 0x94BB, 0x5224, 0x94BC, 0x534A, 0x94BD, 0x53CD, 0x94BE, 0x53DB, 0x94BF, 0x5E06, 0x94C0, 0x642C, 0x94C1, 0x6591, + 0x94C2, 0x677F, 0x94C3, 0x6C3E, 0x94C4, 0x6C4E, 0x94C5, 0x7248, 0x94C6, 0x72AF, 0x94C7, 0x73ED, 0x94C8, 0x7554, 0x94C9, 0x7E41, + 0x94CA, 0x822C, 0x94CB, 0x85E9, 0x94CC, 0x8CA9, 0x94CD, 0x7BC4, 0x94CE, 0x91C6, 0x94CF, 0x7169, 0x94D0, 0x9812, 0x94D1, 0x98EF, + 0x94D2, 0x633D, 0x94D3, 0x6669, 0x94D4, 0x756A, 0x94D5, 0x76E4, 0x94D6, 0x78D0, 0x94D7, 0x8543, 0x94D8, 0x86EE, 0x94D9, 0x532A, + 0x94DA, 0x5351, 0x94DB, 0x5426, 0x94DC, 0x5983, 0x94DD, 0x5E87, 0x94DE, 0x5F7C, 0x94DF, 0x60B2, 0x94E0, 0x6249, 0x94E1, 0x6279, + 0x94E2, 0x62AB, 0x94E3, 0x6590, 0x94E4, 0x6BD4, 0x94E5, 0x6CCC, 0x94E6, 0x75B2, 0x94E7, 0x76AE, 0x94E8, 0x7891, 0x94E9, 0x79D8, + 0x94EA, 0x7DCB, 0x94EB, 0x7F77, 0x94EC, 0x80A5, 0x94ED, 0x88AB, 0x94EE, 0x8AB9, 0x94EF, 0x8CBB, 0x94F0, 0x907F, 0x94F1, 0x975E, + 0x94F2, 0x98DB, 0x94F3, 0x6A0B, 0x94F4, 0x7C38, 0x94F5, 0x5099, 0x94F6, 0x5C3E, 0x94F7, 0x5FAE, 0x94F8, 0x6787, 0x94F9, 0x6BD8, + 0x94FA, 0x7435, 0x94FB, 0x7709, 0x94FC, 0x7F8E, 0x9540, 0x9F3B, 0x9541, 0x67CA, 0x9542, 0x7A17, 0x9543, 0x5339, 0x9544, 0x758B, + 0x9545, 0x9AED, 0x9546, 0x5F66, 0x9547, 0x819D, 0x9548, 0x83F1, 0x9549, 0x8098, 0x954A, 0x5F3C, 0x954B, 0x5FC5, 0x954C, 0x7562, + 0x954D, 0x7B46, 0x954E, 0x903C, 0x954F, 0x6867, 0x9550, 0x59EB, 0x9551, 0x5A9B, 0x9552, 0x7D10, 0x9553, 0x767E, 0x9554, 0x8B2C, + 0x9555, 0x4FF5, 0x9556, 0x5F6A, 0x9557, 0x6A19, 0x9558, 0x6C37, 0x9559, 0x6F02, 0x955A, 0x74E2, 0x955B, 0x7968, 0x955C, 0x8868, + 0x955D, 0x8A55, 0x955E, 0x8C79, 0x955F, 0x5EDF, 0x9560, 0x63CF, 0x9561, 0x75C5, 0x9562, 0x79D2, 0x9563, 0x82D7, 0x9564, 0x9328, + 0x9565, 0x92F2, 0x9566, 0x849C, 0x9567, 0x86ED, 0x9568, 0x9C2D, 0x9569, 0x54C1, 0x956A, 0x5F6C, 0x956B, 0x658C, 0x956C, 0x6D5C, + 0x956D, 0x7015, 0x956E, 0x8CA7, 0x956F, 0x8CD3, 0x9570, 0x983B, 0x9571, 0x654F, 0x9572, 0x74F6, 0x9573, 0x4E0D, 0x9574, 0x4ED8, + 0x9575, 0x57E0, 0x9576, 0x592B, 0x9577, 0x5A66, 0x9578, 0x5BCC, 0x9579, 0x51A8, 0x957A, 0x5E03, 0x957B, 0x5E9C, 0x957C, 0x6016, + 0x957D, 0x6276, 0x957E, 0x6577, 0x9580, 0x65A7, 0x9581, 0x666E, 0x9582, 0x6D6E, 0x9583, 0x7236, 0x9584, 0x7B26, 0x9585, 0x8150, + 0x9586, 0x819A, 0x9587, 0x8299, 0x9588, 0x8B5C, 0x9589, 0x8CA0, 0x958A, 0x8CE6, 0x958B, 0x8D74, 0x958C, 0x961C, 0x958D, 0x9644, + 0x958E, 0x4FAE, 0x958F, 0x64AB, 0x9590, 0x6B66, 0x9591, 0x821E, 0x9592, 0x8461, 0x9593, 0x856A, 0x9594, 0x90E8, 0x9595, 0x5C01, + 0x9596, 0x6953, 0x9597, 0x98A8, 0x9598, 0x847A, 0x9599, 0x8557, 0x959A, 0x4F0F, 0x959B, 0x526F, 0x959C, 0x5FA9, 0x959D, 0x5E45, + 0x959E, 0x670D, 0x959F, 0x798F, 0x95A0, 0x8179, 0x95A1, 0x8907, 0x95A2, 0x8986, 0x95A3, 0x6DF5, 0x95A4, 0x5F17, 0x95A5, 0x6255, + 0x95A6, 0x6CB8, 0x95A7, 0x4ECF, 0x95A8, 0x7269, 0x95A9, 0x9B92, 0x95AA, 0x5206, 0x95AB, 0x543B, 0x95AC, 0x5674, 0x95AD, 0x58B3, + 0x95AE, 0x61A4, 0x95AF, 0x626E, 0x95B0, 0x711A, 0x95B1, 0x596E, 0x95B2, 0x7C89, 0x95B3, 0x7CDE, 0x95B4, 0x7D1B, 0x95B5, 0x96F0, + 0x95B6, 0x6587, 0x95B7, 0x805E, 0x95B8, 0x4E19, 0x95B9, 0x4F75, 0x95BA, 0x5175, 0x95BB, 0x5840, 0x95BC, 0x5E63, 0x95BD, 0x5E73, + 0x95BE, 0x5F0A, 0x95BF, 0x67C4, 0x95C0, 0x4E26, 0x95C1, 0x853D, 0x95C2, 0x9589, 0x95C3, 0x965B, 0x95C4, 0x7C73, 0x95C5, 0x9801, + 0x95C6, 0x50FB, 0x95C7, 0x58C1, 0x95C8, 0x7656, 0x95C9, 0x78A7, 0x95CA, 0x5225, 0x95CB, 0x77A5, 0x95CC, 0x8511, 0x95CD, 0x7B86, + 0x95CE, 0x504F, 0x95CF, 0x5909, 0x95D0, 0x7247, 0x95D1, 0x7BC7, 0x95D2, 0x7DE8, 0x95D3, 0x8FBA, 0x95D4, 0x8FD4, 0x95D5, 0x904D, + 0x95D6, 0x4FBF, 0x95D7, 0x52C9, 0x95D8, 0x5A29, 0x95D9, 0x5F01, 0x95DA, 0x97AD, 0x95DB, 0x4FDD, 0x95DC, 0x8217, 0x95DD, 0x92EA, + 0x95DE, 0x5703, 0x95DF, 0x6355, 0x95E0, 0x6B69, 0x95E1, 0x752B, 0x95E2, 0x88DC, 0x95E3, 0x8F14, 0x95E4, 0x7A42, 0x95E5, 0x52DF, + 0x95E6, 0x5893, 0x95E7, 0x6155, 0x95E8, 0x620A, 0x95E9, 0x66AE, 0x95EA, 0x6BCD, 0x95EB, 0x7C3F, 0x95EC, 0x83E9, 0x95ED, 0x5023, + 0x95EE, 0x4FF8, 0x95EF, 0x5305, 0x95F0, 0x5446, 0x95F1, 0x5831, 0x95F2, 0x5949, 0x95F3, 0x5B9D, 0x95F4, 0x5CF0, 0x95F5, 0x5CEF, + 0x95F6, 0x5D29, 0x95F7, 0x5E96, 0x95F8, 0x62B1, 0x95F9, 0x6367, 0x95FA, 0x653E, 0x95FB, 0x65B9, 0x95FC, 0x670B, 0x9640, 0x6CD5, + 0x9641, 0x6CE1, 0x9642, 0x70F9, 0x9643, 0x7832, 0x9644, 0x7E2B, 0x9645, 0x80DE, 0x9646, 0x82B3, 0x9647, 0x840C, 0x9648, 0x84EC, + 0x9649, 0x8702, 0x964A, 0x8912, 0x964B, 0x8A2A, 0x964C, 0x8C4A, 0x964D, 0x90A6, 0x964E, 0x92D2, 0x964F, 0x98FD, 0x9650, 0x9CF3, + 0x9651, 0x9D6C, 0x9652, 0x4E4F, 0x9653, 0x4EA1, 0x9654, 0x508D, 0x9655, 0x5256, 0x9656, 0x574A, 0x9657, 0x59A8, 0x9658, 0x5E3D, + 0x9659, 0x5FD8, 0x965A, 0x5FD9, 0x965B, 0x623F, 0x965C, 0x66B4, 0x965D, 0x671B, 0x965E, 0x67D0, 0x965F, 0x68D2, 0x9660, 0x5192, + 0x9661, 0x7D21, 0x9662, 0x80AA, 0x9663, 0x81A8, 0x9664, 0x8B00, 0x9665, 0x8C8C, 0x9666, 0x8CBF, 0x9667, 0x927E, 0x9668, 0x9632, + 0x9669, 0x5420, 0x966A, 0x982C, 0x966B, 0x5317, 0x966C, 0x50D5, 0x966D, 0x535C, 0x966E, 0x58A8, 0x966F, 0x64B2, 0x9670, 0x6734, + 0x9671, 0x7267, 0x9672, 0x7766, 0x9673, 0x7A46, 0x9674, 0x91E6, 0x9675, 0x52C3, 0x9676, 0x6CA1, 0x9677, 0x6B86, 0x9678, 0x5800, + 0x9679, 0x5E4C, 0x967A, 0x5954, 0x967B, 0x672C, 0x967C, 0x7FFB, 0x967D, 0x51E1, 0x967E, 0x76C6, 0x9680, 0x6469, 0x9681, 0x78E8, + 0x9682, 0x9B54, 0x9683, 0x9EBB, 0x9684, 0x57CB, 0x9685, 0x59B9, 0x9686, 0x6627, 0x9687, 0x679A, 0x9688, 0x6BCE, 0x9689, 0x54E9, + 0x968A, 0x69D9, 0x968B, 0x5E55, 0x968C, 0x819C, 0x968D, 0x6795, 0x968E, 0x9BAA, 0x968F, 0x67FE, 0x9690, 0x9C52, 0x9691, 0x685D, + 0x9692, 0x4EA6, 0x9693, 0x4FE3, 0x9694, 0x53C8, 0x9695, 0x62B9, 0x9696, 0x672B, 0x9697, 0x6CAB, 0x9698, 0x8FC4, 0x9699, 0x4FAD, + 0x969A, 0x7E6D, 0x969B, 0x9EBF, 0x969C, 0x4E07, 0x969D, 0x6162, 0x969E, 0x6E80, 0x969F, 0x6F2B, 0x96A0, 0x8513, 0x96A1, 0x5473, + 0x96A2, 0x672A, 0x96A3, 0x9B45, 0x96A4, 0x5DF3, 0x96A5, 0x7B95, 0x96A6, 0x5CAC, 0x96A7, 0x5BC6, 0x96A8, 0x871C, 0x96A9, 0x6E4A, + 0x96AA, 0x84D1, 0x96AB, 0x7A14, 0x96AC, 0x8108, 0x96AD, 0x5999, 0x96AE, 0x7C8D, 0x96AF, 0x6C11, 0x96B0, 0x7720, 0x96B1, 0x52D9, + 0x96B2, 0x5922, 0x96B3, 0x7121, 0x96B4, 0x725F, 0x96B5, 0x77DB, 0x96B6, 0x9727, 0x96B7, 0x9D61, 0x96B8, 0x690B, 0x96B9, 0x5A7F, + 0x96BA, 0x5A18, 0x96BB, 0x51A5, 0x96BC, 0x540D, 0x96BD, 0x547D, 0x96BE, 0x660E, 0x96BF, 0x76DF, 0x96C0, 0x8FF7, 0x96C1, 0x9298, + 0x96C2, 0x9CF4, 0x96C3, 0x59EA, 0x96C4, 0x725D, 0x96C5, 0x6EC5, 0x96C6, 0x514D, 0x96C7, 0x68C9, 0x96C8, 0x7DBF, 0x96C9, 0x7DEC, + 0x96CA, 0x9762, 0x96CB, 0x9EBA, 0x96CC, 0x6478, 0x96CD, 0x6A21, 0x96CE, 0x8302, 0x96CF, 0x5984, 0x96D0, 0x5B5F, 0x96D1, 0x6BDB, + 0x96D2, 0x731B, 0x96D3, 0x76F2, 0x96D4, 0x7DB2, 0x96D5, 0x8017, 0x96D6, 0x8499, 0x96D7, 0x5132, 0x96D8, 0x6728, 0x96D9, 0x9ED9, + 0x96DA, 0x76EE, 0x96DB, 0x6762, 0x96DC, 0x52FF, 0x96DD, 0x9905, 0x96DE, 0x5C24, 0x96DF, 0x623B, 0x96E0, 0x7C7E, 0x96E1, 0x8CB0, + 0x96E2, 0x554F, 0x96E3, 0x60B6, 0x96E4, 0x7D0B, 0x96E5, 0x9580, 0x96E6, 0x5301, 0x96E7, 0x4E5F, 0x96E8, 0x51B6, 0x96E9, 0x591C, + 0x96EA, 0x723A, 0x96EB, 0x8036, 0x96EC, 0x91CE, 0x96ED, 0x5F25, 0x96EE, 0x77E2, 0x96EF, 0x5384, 0x96F0, 0x5F79, 0x96F1, 0x7D04, + 0x96F2, 0x85AC, 0x96F3, 0x8A33, 0x96F4, 0x8E8D, 0x96F5, 0x9756, 0x96F6, 0x67F3, 0x96F7, 0x85AE, 0x96F8, 0x9453, 0x96F9, 0x6109, + 0x96FA, 0x6108, 0x96FB, 0x6CB9, 0x96FC, 0x7652, 0x9740, 0x8AED, 0x9741, 0x8F38, 0x9742, 0x552F, 0x9743, 0x4F51, 0x9744, 0x512A, + 0x9745, 0x52C7, 0x9746, 0x53CB, 0x9747, 0x5BA5, 0x9748, 0x5E7D, 0x9749, 0x60A0, 0x974A, 0x6182, 0x974B, 0x63D6, 0x974C, 0x6709, + 0x974D, 0x67DA, 0x974E, 0x6E67, 0x974F, 0x6D8C, 0x9750, 0x7336, 0x9751, 0x7337, 0x9752, 0x7531, 0x9753, 0x7950, 0x9754, 0x88D5, + 0x9755, 0x8A98, 0x9756, 0x904A, 0x9757, 0x9091, 0x9758, 0x90F5, 0x9759, 0x96C4, 0x975A, 0x878D, 0x975B, 0x5915, 0x975C, 0x4E88, + 0x975D, 0x4F59, 0x975E, 0x4E0E, 0x975F, 0x8A89, 0x9760, 0x8F3F, 0x9761, 0x9810, 0x9762, 0x50AD, 0x9763, 0x5E7C, 0x9764, 0x5996, + 0x9765, 0x5BB9, 0x9766, 0x5EB8, 0x9767, 0x63DA, 0x9768, 0x63FA, 0x9769, 0x64C1, 0x976A, 0x66DC, 0x976B, 0x694A, 0x976C, 0x69D8, + 0x976D, 0x6D0B, 0x976E, 0x6EB6, 0x976F, 0x7194, 0x9770, 0x7528, 0x9771, 0x7AAF, 0x9772, 0x7F8A, 0x9773, 0x8000, 0x9774, 0x8449, + 0x9775, 0x84C9, 0x9776, 0x8981, 0x9777, 0x8B21, 0x9778, 0x8E0A, 0x9779, 0x9065, 0x977A, 0x967D, 0x977B, 0x990A, 0x977C, 0x617E, + 0x977D, 0x6291, 0x977E, 0x6B32, 0x9780, 0x6C83, 0x9781, 0x6D74, 0x9782, 0x7FCC, 0x9783, 0x7FFC, 0x9784, 0x6DC0, 0x9785, 0x7F85, + 0x9786, 0x87BA, 0x9787, 0x88F8, 0x9788, 0x6765, 0x9789, 0x83B1, 0x978A, 0x983C, 0x978B, 0x96F7, 0x978C, 0x6D1B, 0x978D, 0x7D61, + 0x978E, 0x843D, 0x978F, 0x916A, 0x9790, 0x4E71, 0x9791, 0x5375, 0x9792, 0x5D50, 0x9793, 0x6B04, 0x9794, 0x6FEB, 0x9795, 0x85CD, + 0x9796, 0x862D, 0x9797, 0x89A7, 0x9798, 0x5229, 0x9799, 0x540F, 0x979A, 0x5C65, 0x979B, 0x674E, 0x979C, 0x68A8, 0x979D, 0x7406, + 0x979E, 0x7483, 0x979F, 0x75E2, 0x97A0, 0x88CF, 0x97A1, 0x88E1, 0x97A2, 0x91CC, 0x97A3, 0x96E2, 0x97A4, 0x9678, 0x97A5, 0x5F8B, + 0x97A6, 0x7387, 0x97A7, 0x7ACB, 0x97A8, 0x844E, 0x97A9, 0x63A0, 0x97AA, 0x7565, 0x97AB, 0x5289, 0x97AC, 0x6D41, 0x97AD, 0x6E9C, + 0x97AE, 0x7409, 0x97AF, 0x7559, 0x97B0, 0x786B, 0x97B1, 0x7C92, 0x97B2, 0x9686, 0x97B3, 0x7ADC, 0x97B4, 0x9F8D, 0x97B5, 0x4FB6, + 0x97B6, 0x616E, 0x97B7, 0x65C5, 0x97B8, 0x865C, 0x97B9, 0x4E86, 0x97BA, 0x4EAE, 0x97BB, 0x50DA, 0x97BC, 0x4E21, 0x97BD, 0x51CC, + 0x97BE, 0x5BEE, 0x97BF, 0x6599, 0x97C0, 0x6881, 0x97C1, 0x6DBC, 0x97C2, 0x731F, 0x97C3, 0x7642, 0x97C4, 0x77AD, 0x97C5, 0x7A1C, + 0x97C6, 0x7CE7, 0x97C7, 0x826F, 0x97C8, 0x8AD2, 0x97C9, 0x907C, 0x97CA, 0x91CF, 0x97CB, 0x9675, 0x97CC, 0x9818, 0x97CD, 0x529B, + 0x97CE, 0x7DD1, 0x97CF, 0x502B, 0x97D0, 0x5398, 0x97D1, 0x6797, 0x97D2, 0x6DCB, 0x97D3, 0x71D0, 0x97D4, 0x7433, 0x97D5, 0x81E8, + 0x97D6, 0x8F2A, 0x97D7, 0x96A3, 0x97D8, 0x9C57, 0x97D9, 0x9E9F, 0x97DA, 0x7460, 0x97DB, 0x5841, 0x97DC, 0x6D99, 0x97DD, 0x7D2F, + 0x97DE, 0x985E, 0x97DF, 0x4EE4, 0x97E0, 0x4F36, 0x97E1, 0x4F8B, 0x97E2, 0x51B7, 0x97E3, 0x52B1, 0x97E4, 0x5DBA, 0x97E5, 0x601C, + 0x97E6, 0x73B2, 0x97E7, 0x793C, 0x97E8, 0x82D3, 0x97E9, 0x9234, 0x97EA, 0x96B7, 0x97EB, 0x96F6, 0x97EC, 0x970A, 0x97ED, 0x9E97, + 0x97EE, 0x9F62, 0x97EF, 0x66A6, 0x97F0, 0x6B74, 0x97F1, 0x5217, 0x97F2, 0x52A3, 0x97F3, 0x70C8, 0x97F4, 0x88C2, 0x97F5, 0x5EC9, + 0x97F6, 0x604B, 0x97F7, 0x6190, 0x97F8, 0x6F23, 0x97F9, 0x7149, 0x97FA, 0x7C3E, 0x97FB, 0x7DF4, 0x97FC, 0x806F, 0x9840, 0x84EE, + 0x9841, 0x9023, 0x9842, 0x932C, 0x9843, 0x5442, 0x9844, 0x9B6F, 0x9845, 0x6AD3, 0x9846, 0x7089, 0x9847, 0x8CC2, 0x9848, 0x8DEF, + 0x9849, 0x9732, 0x984A, 0x52B4, 0x984B, 0x5A41, 0x984C, 0x5ECA, 0x984D, 0x5F04, 0x984E, 0x6717, 0x984F, 0x697C, 0x9850, 0x6994, + 0x9851, 0x6D6A, 0x9852, 0x6F0F, 0x9853, 0x7262, 0x9854, 0x72FC, 0x9855, 0x7BED, 0x9856, 0x8001, 0x9857, 0x807E, 0x9858, 0x874B, + 0x9859, 0x90CE, 0x985A, 0x516D, 0x985B, 0x9E93, 0x985C, 0x7984, 0x985D, 0x808B, 0x985E, 0x9332, 0x985F, 0x8AD6, 0x9860, 0x502D, + 0x9861, 0x548C, 0x9862, 0x8A71, 0x9863, 0x6B6A, 0x9864, 0x8CC4, 0x9865, 0x8107, 0x9866, 0x60D1, 0x9867, 0x67A0, 0x9868, 0x9DF2, + 0x9869, 0x4E99, 0x986A, 0x4E98, 0x986B, 0x9C10, 0x986C, 0x8A6B, 0x986D, 0x85C1, 0x986E, 0x8568, 0x986F, 0x6900, 0x9870, 0x6E7E, + 0x9871, 0x7897, 0x9872, 0x8155, 0x989F, 0x5F0C, 0x98A0, 0x4E10, 0x98A1, 0x4E15, 0x98A2, 0x4E2A, 0x98A3, 0x4E31, 0x98A4, 0x4E36, + 0x98A5, 0x4E3C, 0x98A6, 0x4E3F, 0x98A7, 0x4E42, 0x98A8, 0x4E56, 0x98A9, 0x4E58, 0x98AA, 0x4E82, 0x98AB, 0x4E85, 0x98AC, 0x8C6B, + 0x98AD, 0x4E8A, 0x98AE, 0x8212, 0x98AF, 0x5F0D, 0x98B0, 0x4E8E, 0x98B1, 0x4E9E, 0x98B2, 0x4E9F, 0x98B3, 0x4EA0, 0x98B4, 0x4EA2, + 0x98B5, 0x4EB0, 0x98B6, 0x4EB3, 0x98B7, 0x4EB6, 0x98B8, 0x4ECE, 0x98B9, 0x4ECD, 0x98BA, 0x4EC4, 0x98BB, 0x4EC6, 0x98BC, 0x4EC2, + 0x98BD, 0x4ED7, 0x98BE, 0x4EDE, 0x98BF, 0x4EED, 0x98C0, 0x4EDF, 0x98C1, 0x4EF7, 0x98C2, 0x4F09, 0x98C3, 0x4F5A, 0x98C4, 0x4F30, + 0x98C5, 0x4F5B, 0x98C6, 0x4F5D, 0x98C7, 0x4F57, 0x98C8, 0x4F47, 0x98C9, 0x4F76, 0x98CA, 0x4F88, 0x98CB, 0x4F8F, 0x98CC, 0x4F98, + 0x98CD, 0x4F7B, 0x98CE, 0x4F69, 0x98CF, 0x4F70, 0x98D0, 0x4F91, 0x98D1, 0x4F6F, 0x98D2, 0x4F86, 0x98D3, 0x4F96, 0x98D4, 0x5118, + 0x98D5, 0x4FD4, 0x98D6, 0x4FDF, 0x98D7, 0x4FCE, 0x98D8, 0x4FD8, 0x98D9, 0x4FDB, 0x98DA, 0x4FD1, 0x98DB, 0x4FDA, 0x98DC, 0x4FD0, + 0x98DD, 0x4FE4, 0x98DE, 0x4FE5, 0x98DF, 0x501A, 0x98E0, 0x5028, 0x98E1, 0x5014, 0x98E2, 0x502A, 0x98E3, 0x5025, 0x98E4, 0x5005, + 0x98E5, 0x4F1C, 0x98E6, 0x4FF6, 0x98E7, 0x5021, 0x98E8, 0x5029, 0x98E9, 0x502C, 0x98EA, 0x4FFE, 0x98EB, 0x4FEF, 0x98EC, 0x5011, + 0x98ED, 0x5006, 0x98EE, 0x5043, 0x98EF, 0x5047, 0x98F0, 0x6703, 0x98F1, 0x5055, 0x98F2, 0x5050, 0x98F3, 0x5048, 0x98F4, 0x505A, + 0x98F5, 0x5056, 0x98F6, 0x506C, 0x98F7, 0x5078, 0x98F8, 0x5080, 0x98F9, 0x509A, 0x98FA, 0x5085, 0x98FB, 0x50B4, 0x98FC, 0x50B2, + 0x9940, 0x50C9, 0x9941, 0x50CA, 0x9942, 0x50B3, 0x9943, 0x50C2, 0x9944, 0x50D6, 0x9945, 0x50DE, 0x9946, 0x50E5, 0x9947, 0x50ED, + 0x9948, 0x50E3, 0x9949, 0x50EE, 0x994A, 0x50F9, 0x994B, 0x50F5, 0x994C, 0x5109, 0x994D, 0x5101, 0x994E, 0x5102, 0x994F, 0x5116, + 0x9950, 0x5115, 0x9951, 0x5114, 0x9952, 0x511A, 0x9953, 0x5121, 0x9954, 0x513A, 0x9955, 0x5137, 0x9956, 0x513C, 0x9957, 0x513B, + 0x9958, 0x513F, 0x9959, 0x5140, 0x995A, 0x5152, 0x995B, 0x514C, 0x995C, 0x5154, 0x995D, 0x5162, 0x995E, 0x7AF8, 0x995F, 0x5169, + 0x9960, 0x516A, 0x9961, 0x516E, 0x9962, 0x5180, 0x9963, 0x5182, 0x9964, 0x56D8, 0x9965, 0x518C, 0x9966, 0x5189, 0x9967, 0x518F, + 0x9968, 0x5191, 0x9969, 0x5193, 0x996A, 0x5195, 0x996B, 0x5196, 0x996C, 0x51A4, 0x996D, 0x51A6, 0x996E, 0x51A2, 0x996F, 0x51A9, + 0x9970, 0x51AA, 0x9971, 0x51AB, 0x9972, 0x51B3, 0x9973, 0x51B1, 0x9974, 0x51B2, 0x9975, 0x51B0, 0x9976, 0x51B5, 0x9977, 0x51BD, + 0x9978, 0x51C5, 0x9979, 0x51C9, 0x997A, 0x51DB, 0x997B, 0x51E0, 0x997C, 0x8655, 0x997D, 0x51E9, 0x997E, 0x51ED, 0x9980, 0x51F0, + 0x9981, 0x51F5, 0x9982, 0x51FE, 0x9983, 0x5204, 0x9984, 0x520B, 0x9985, 0x5214, 0x9986, 0x520E, 0x9987, 0x5227, 0x9988, 0x522A, + 0x9989, 0x522E, 0x998A, 0x5233, 0x998B, 0x5239, 0x998C, 0x524F, 0x998D, 0x5244, 0x998E, 0x524B, 0x998F, 0x524C, 0x9990, 0x525E, + 0x9991, 0x5254, 0x9992, 0x526A, 0x9993, 0x5274, 0x9994, 0x5269, 0x9995, 0x5273, 0x9996, 0x527F, 0x9997, 0x527D, 0x9998, 0x528D, + 0x9999, 0x5294, 0x999A, 0x5292, 0x999B, 0x5271, 0x999C, 0x5288, 0x999D, 0x5291, 0x999E, 0x8FA8, 0x999F, 0x8FA7, 0x99A0, 0x52AC, + 0x99A1, 0x52AD, 0x99A2, 0x52BC, 0x99A3, 0x52B5, 0x99A4, 0x52C1, 0x99A5, 0x52CD, 0x99A6, 0x52D7, 0x99A7, 0x52DE, 0x99A8, 0x52E3, + 0x99A9, 0x52E6, 0x99AA, 0x98ED, 0x99AB, 0x52E0, 0x99AC, 0x52F3, 0x99AD, 0x52F5, 0x99AE, 0x52F8, 0x99AF, 0x52F9, 0x99B0, 0x5306, + 0x99B1, 0x5308, 0x99B2, 0x7538, 0x99B3, 0x530D, 0x99B4, 0x5310, 0x99B5, 0x530F, 0x99B6, 0x5315, 0x99B7, 0x531A, 0x99B8, 0x5323, + 0x99B9, 0x532F, 0x99BA, 0x5331, 0x99BB, 0x5333, 0x99BC, 0x5338, 0x99BD, 0x5340, 0x99BE, 0x5346, 0x99BF, 0x5345, 0x99C0, 0x4E17, + 0x99C1, 0x5349, 0x99C2, 0x534D, 0x99C3, 0x51D6, 0x99C4, 0x535E, 0x99C5, 0x5369, 0x99C6, 0x536E, 0x99C7, 0x5918, 0x99C8, 0x537B, + 0x99C9, 0x5377, 0x99CA, 0x5382, 0x99CB, 0x5396, 0x99CC, 0x53A0, 0x99CD, 0x53A6, 0x99CE, 0x53A5, 0x99CF, 0x53AE, 0x99D0, 0x53B0, + 0x99D1, 0x53B6, 0x99D2, 0x53C3, 0x99D3, 0x7C12, 0x99D4, 0x96D9, 0x99D5, 0x53DF, 0x99D6, 0x66FC, 0x99D7, 0x71EE, 0x99D8, 0x53EE, + 0x99D9, 0x53E8, 0x99DA, 0x53ED, 0x99DB, 0x53FA, 0x99DC, 0x5401, 0x99DD, 0x543D, 0x99DE, 0x5440, 0x99DF, 0x542C, 0x99E0, 0x542D, + 0x99E1, 0x543C, 0x99E2, 0x542E, 0x99E3, 0x5436, 0x99E4, 0x5429, 0x99E5, 0x541D, 0x99E6, 0x544E, 0x99E7, 0x548F, 0x99E8, 0x5475, + 0x99E9, 0x548E, 0x99EA, 0x545F, 0x99EB, 0x5471, 0x99EC, 0x5477, 0x99ED, 0x5470, 0x99EE, 0x5492, 0x99EF, 0x547B, 0x99F0, 0x5480, + 0x99F1, 0x5476, 0x99F2, 0x5484, 0x99F3, 0x5490, 0x99F4, 0x5486, 0x99F5, 0x54C7, 0x99F6, 0x54A2, 0x99F7, 0x54B8, 0x99F8, 0x54A5, + 0x99F9, 0x54AC, 0x99FA, 0x54C4, 0x99FB, 0x54C8, 0x99FC, 0x54A8, 0x9A40, 0x54AB, 0x9A41, 0x54C2, 0x9A42, 0x54A4, 0x9A43, 0x54BE, + 0x9A44, 0x54BC, 0x9A45, 0x54D8, 0x9A46, 0x54E5, 0x9A47, 0x54E6, 0x9A48, 0x550F, 0x9A49, 0x5514, 0x9A4A, 0x54FD, 0x9A4B, 0x54EE, + 0x9A4C, 0x54ED, 0x9A4D, 0x54FA, 0x9A4E, 0x54E2, 0x9A4F, 0x5539, 0x9A50, 0x5540, 0x9A51, 0x5563, 0x9A52, 0x554C, 0x9A53, 0x552E, + 0x9A54, 0x555C, 0x9A55, 0x5545, 0x9A56, 0x5556, 0x9A57, 0x5557, 0x9A58, 0x5538, 0x9A59, 0x5533, 0x9A5A, 0x555D, 0x9A5B, 0x5599, + 0x9A5C, 0x5580, 0x9A5D, 0x54AF, 0x9A5E, 0x558A, 0x9A5F, 0x559F, 0x9A60, 0x557B, 0x9A61, 0x557E, 0x9A62, 0x5598, 0x9A63, 0x559E, + 0x9A64, 0x55AE, 0x9A65, 0x557C, 0x9A66, 0x5583, 0x9A67, 0x55A9, 0x9A68, 0x5587, 0x9A69, 0x55A8, 0x9A6A, 0x55DA, 0x9A6B, 0x55C5, + 0x9A6C, 0x55DF, 0x9A6D, 0x55C4, 0x9A6E, 0x55DC, 0x9A6F, 0x55E4, 0x9A70, 0x55D4, 0x9A71, 0x5614, 0x9A72, 0x55F7, 0x9A73, 0x5616, + 0x9A74, 0x55FE, 0x9A75, 0x55FD, 0x9A76, 0x561B, 0x9A77, 0x55F9, 0x9A78, 0x564E, 0x9A79, 0x5650, 0x9A7A, 0x71DF, 0x9A7B, 0x5634, + 0x9A7C, 0x5636, 0x9A7D, 0x5632, 0x9A7E, 0x5638, 0x9A80, 0x566B, 0x9A81, 0x5664, 0x9A82, 0x562F, 0x9A83, 0x566C, 0x9A84, 0x566A, + 0x9A85, 0x5686, 0x9A86, 0x5680, 0x9A87, 0x568A, 0x9A88, 0x56A0, 0x9A89, 0x5694, 0x9A8A, 0x568F, 0x9A8B, 0x56A5, 0x9A8C, 0x56AE, + 0x9A8D, 0x56B6, 0x9A8E, 0x56B4, 0x9A8F, 0x56C2, 0x9A90, 0x56BC, 0x9A91, 0x56C1, 0x9A92, 0x56C3, 0x9A93, 0x56C0, 0x9A94, 0x56C8, + 0x9A95, 0x56CE, 0x9A96, 0x56D1, 0x9A97, 0x56D3, 0x9A98, 0x56D7, 0x9A99, 0x56EE, 0x9A9A, 0x56F9, 0x9A9B, 0x5700, 0x9A9C, 0x56FF, + 0x9A9D, 0x5704, 0x9A9E, 0x5709, 0x9A9F, 0x5708, 0x9AA0, 0x570B, 0x9AA1, 0x570D, 0x9AA2, 0x5713, 0x9AA3, 0x5718, 0x9AA4, 0x5716, + 0x9AA5, 0x55C7, 0x9AA6, 0x571C, 0x9AA7, 0x5726, 0x9AA8, 0x5737, 0x9AA9, 0x5738, 0x9AAA, 0x574E, 0x9AAB, 0x573B, 0x9AAC, 0x5740, + 0x9AAD, 0x574F, 0x9AAE, 0x5769, 0x9AAF, 0x57C0, 0x9AB0, 0x5788, 0x9AB1, 0x5761, 0x9AB2, 0x577F, 0x9AB3, 0x5789, 0x9AB4, 0x5793, + 0x9AB5, 0x57A0, 0x9AB6, 0x57B3, 0x9AB7, 0x57A4, 0x9AB8, 0x57AA, 0x9AB9, 0x57B0, 0x9ABA, 0x57C3, 0x9ABB, 0x57C6, 0x9ABC, 0x57D4, + 0x9ABD, 0x57D2, 0x9ABE, 0x57D3, 0x9ABF, 0x580A, 0x9AC0, 0x57D6, 0x9AC1, 0x57E3, 0x9AC2, 0x580B, 0x9AC3, 0x5819, 0x9AC4, 0x581D, + 0x9AC5, 0x5872, 0x9AC6, 0x5821, 0x9AC7, 0x5862, 0x9AC8, 0x584B, 0x9AC9, 0x5870, 0x9ACA, 0x6BC0, 0x9ACB, 0x5852, 0x9ACC, 0x583D, + 0x9ACD, 0x5879, 0x9ACE, 0x5885, 0x9ACF, 0x58B9, 0x9AD0, 0x589F, 0x9AD1, 0x58AB, 0x9AD2, 0x58BA, 0x9AD3, 0x58DE, 0x9AD4, 0x58BB, + 0x9AD5, 0x58B8, 0x9AD6, 0x58AE, 0x9AD7, 0x58C5, 0x9AD8, 0x58D3, 0x9AD9, 0x58D1, 0x9ADA, 0x58D7, 0x9ADB, 0x58D9, 0x9ADC, 0x58D8, + 0x9ADD, 0x58E5, 0x9ADE, 0x58DC, 0x9ADF, 0x58E4, 0x9AE0, 0x58DF, 0x9AE1, 0x58EF, 0x9AE2, 0x58FA, 0x9AE3, 0x58F9, 0x9AE4, 0x58FB, + 0x9AE5, 0x58FC, 0x9AE6, 0x58FD, 0x9AE7, 0x5902, 0x9AE8, 0x590A, 0x9AE9, 0x5910, 0x9AEA, 0x591B, 0x9AEB, 0x68A6, 0x9AEC, 0x5925, + 0x9AED, 0x592C, 0x9AEE, 0x592D, 0x9AEF, 0x5932, 0x9AF0, 0x5938, 0x9AF1, 0x593E, 0x9AF2, 0x7AD2, 0x9AF3, 0x5955, 0x9AF4, 0x5950, + 0x9AF5, 0x594E, 0x9AF6, 0x595A, 0x9AF7, 0x5958, 0x9AF8, 0x5962, 0x9AF9, 0x5960, 0x9AFA, 0x5967, 0x9AFB, 0x596C, 0x9AFC, 0x5969, + 0x9B40, 0x5978, 0x9B41, 0x5981, 0x9B42, 0x599D, 0x9B43, 0x4F5E, 0x9B44, 0x4FAB, 0x9B45, 0x59A3, 0x9B46, 0x59B2, 0x9B47, 0x59C6, + 0x9B48, 0x59E8, 0x9B49, 0x59DC, 0x9B4A, 0x598D, 0x9B4B, 0x59D9, 0x9B4C, 0x59DA, 0x9B4D, 0x5A25, 0x9B4E, 0x5A1F, 0x9B4F, 0x5A11, + 0x9B50, 0x5A1C, 0x9B51, 0x5A09, 0x9B52, 0x5A1A, 0x9B53, 0x5A40, 0x9B54, 0x5A6C, 0x9B55, 0x5A49, 0x9B56, 0x5A35, 0x9B57, 0x5A36, + 0x9B58, 0x5A62, 0x9B59, 0x5A6A, 0x9B5A, 0x5A9A, 0x9B5B, 0x5ABC, 0x9B5C, 0x5ABE, 0x9B5D, 0x5ACB, 0x9B5E, 0x5AC2, 0x9B5F, 0x5ABD, + 0x9B60, 0x5AE3, 0x9B61, 0x5AD7, 0x9B62, 0x5AE6, 0x9B63, 0x5AE9, 0x9B64, 0x5AD6, 0x9B65, 0x5AFA, 0x9B66, 0x5AFB, 0x9B67, 0x5B0C, + 0x9B68, 0x5B0B, 0x9B69, 0x5B16, 0x9B6A, 0x5B32, 0x9B6B, 0x5AD0, 0x9B6C, 0x5B2A, 0x9B6D, 0x5B36, 0x9B6E, 0x5B3E, 0x9B6F, 0x5B43, + 0x9B70, 0x5B45, 0x9B71, 0x5B40, 0x9B72, 0x5B51, 0x9B73, 0x5B55, 0x9B74, 0x5B5A, 0x9B75, 0x5B5B, 0x9B76, 0x5B65, 0x9B77, 0x5B69, + 0x9B78, 0x5B70, 0x9B79, 0x5B73, 0x9B7A, 0x5B75, 0x9B7B, 0x5B78, 0x9B7C, 0x6588, 0x9B7D, 0x5B7A, 0x9B7E, 0x5B80, 0x9B80, 0x5B83, + 0x9B81, 0x5BA6, 0x9B82, 0x5BB8, 0x9B83, 0x5BC3, 0x9B84, 0x5BC7, 0x9B85, 0x5BC9, 0x9B86, 0x5BD4, 0x9B87, 0x5BD0, 0x9B88, 0x5BE4, + 0x9B89, 0x5BE6, 0x9B8A, 0x5BE2, 0x9B8B, 0x5BDE, 0x9B8C, 0x5BE5, 0x9B8D, 0x5BEB, 0x9B8E, 0x5BF0, 0x9B8F, 0x5BF6, 0x9B90, 0x5BF3, + 0x9B91, 0x5C05, 0x9B92, 0x5C07, 0x9B93, 0x5C08, 0x9B94, 0x5C0D, 0x9B95, 0x5C13, 0x9B96, 0x5C20, 0x9B97, 0x5C22, 0x9B98, 0x5C28, + 0x9B99, 0x5C38, 0x9B9A, 0x5C39, 0x9B9B, 0x5C41, 0x9B9C, 0x5C46, 0x9B9D, 0x5C4E, 0x9B9E, 0x5C53, 0x9B9F, 0x5C50, 0x9BA0, 0x5C4F, + 0x9BA1, 0x5B71, 0x9BA2, 0x5C6C, 0x9BA3, 0x5C6E, 0x9BA4, 0x4E62, 0x9BA5, 0x5C76, 0x9BA6, 0x5C79, 0x9BA7, 0x5C8C, 0x9BA8, 0x5C91, + 0x9BA9, 0x5C94, 0x9BAA, 0x599B, 0x9BAB, 0x5CAB, 0x9BAC, 0x5CBB, 0x9BAD, 0x5CB6, 0x9BAE, 0x5CBC, 0x9BAF, 0x5CB7, 0x9BB0, 0x5CC5, + 0x9BB1, 0x5CBE, 0x9BB2, 0x5CC7, 0x9BB3, 0x5CD9, 0x9BB4, 0x5CE9, 0x9BB5, 0x5CFD, 0x9BB6, 0x5CFA, 0x9BB7, 0x5CED, 0x9BB8, 0x5D8C, + 0x9BB9, 0x5CEA, 0x9BBA, 0x5D0B, 0x9BBB, 0x5D15, 0x9BBC, 0x5D17, 0x9BBD, 0x5D5C, 0x9BBE, 0x5D1F, 0x9BBF, 0x5D1B, 0x9BC0, 0x5D11, + 0x9BC1, 0x5D14, 0x9BC2, 0x5D22, 0x9BC3, 0x5D1A, 0x9BC4, 0x5D19, 0x9BC5, 0x5D18, 0x9BC6, 0x5D4C, 0x9BC7, 0x5D52, 0x9BC8, 0x5D4E, + 0x9BC9, 0x5D4B, 0x9BCA, 0x5D6C, 0x9BCB, 0x5D73, 0x9BCC, 0x5D76, 0x9BCD, 0x5D87, 0x9BCE, 0x5D84, 0x9BCF, 0x5D82, 0x9BD0, 0x5DA2, + 0x9BD1, 0x5D9D, 0x9BD2, 0x5DAC, 0x9BD3, 0x5DAE, 0x9BD4, 0x5DBD, 0x9BD5, 0x5D90, 0x9BD6, 0x5DB7, 0x9BD7, 0x5DBC, 0x9BD8, 0x5DC9, + 0x9BD9, 0x5DCD, 0x9BDA, 0x5DD3, 0x9BDB, 0x5DD2, 0x9BDC, 0x5DD6, 0x9BDD, 0x5DDB, 0x9BDE, 0x5DEB, 0x9BDF, 0x5DF2, 0x9BE0, 0x5DF5, + 0x9BE1, 0x5E0B, 0x9BE2, 0x5E1A, 0x9BE3, 0x5E19, 0x9BE4, 0x5E11, 0x9BE5, 0x5E1B, 0x9BE6, 0x5E36, 0x9BE7, 0x5E37, 0x9BE8, 0x5E44, + 0x9BE9, 0x5E43, 0x9BEA, 0x5E40, 0x9BEB, 0x5E4E, 0x9BEC, 0x5E57, 0x9BED, 0x5E54, 0x9BEE, 0x5E5F, 0x9BEF, 0x5E62, 0x9BF0, 0x5E64, + 0x9BF1, 0x5E47, 0x9BF2, 0x5E75, 0x9BF3, 0x5E76, 0x9BF4, 0x5E7A, 0x9BF5, 0x9EBC, 0x9BF6, 0x5E7F, 0x9BF7, 0x5EA0, 0x9BF8, 0x5EC1, + 0x9BF9, 0x5EC2, 0x9BFA, 0x5EC8, 0x9BFB, 0x5ED0, 0x9BFC, 0x5ECF, 0x9C40, 0x5ED6, 0x9C41, 0x5EE3, 0x9C42, 0x5EDD, 0x9C43, 0x5EDA, + 0x9C44, 0x5EDB, 0x9C45, 0x5EE2, 0x9C46, 0x5EE1, 0x9C47, 0x5EE8, 0x9C48, 0x5EE9, 0x9C49, 0x5EEC, 0x9C4A, 0x5EF1, 0x9C4B, 0x5EF3, + 0x9C4C, 0x5EF0, 0x9C4D, 0x5EF4, 0x9C4E, 0x5EF8, 0x9C4F, 0x5EFE, 0x9C50, 0x5F03, 0x9C51, 0x5F09, 0x9C52, 0x5F5D, 0x9C53, 0x5F5C, + 0x9C54, 0x5F0B, 0x9C55, 0x5F11, 0x9C56, 0x5F16, 0x9C57, 0x5F29, 0x9C58, 0x5F2D, 0x9C59, 0x5F38, 0x9C5A, 0x5F41, 0x9C5B, 0x5F48, + 0x9C5C, 0x5F4C, 0x9C5D, 0x5F4E, 0x9C5E, 0x5F2F, 0x9C5F, 0x5F51, 0x9C60, 0x5F56, 0x9C61, 0x5F57, 0x9C62, 0x5F59, 0x9C63, 0x5F61, + 0x9C64, 0x5F6D, 0x9C65, 0x5F73, 0x9C66, 0x5F77, 0x9C67, 0x5F83, 0x9C68, 0x5F82, 0x9C69, 0x5F7F, 0x9C6A, 0x5F8A, 0x9C6B, 0x5F88, + 0x9C6C, 0x5F91, 0x9C6D, 0x5F87, 0x9C6E, 0x5F9E, 0x9C6F, 0x5F99, 0x9C70, 0x5F98, 0x9C71, 0x5FA0, 0x9C72, 0x5FA8, 0x9C73, 0x5FAD, + 0x9C74, 0x5FBC, 0x9C75, 0x5FD6, 0x9C76, 0x5FFB, 0x9C77, 0x5FE4, 0x9C78, 0x5FF8, 0x9C79, 0x5FF1, 0x9C7A, 0x5FDD, 0x9C7B, 0x60B3, + 0x9C7C, 0x5FFF, 0x9C7D, 0x6021, 0x9C7E, 0x6060, 0x9C80, 0x6019, 0x9C81, 0x6010, 0x9C82, 0x6029, 0x9C83, 0x600E, 0x9C84, 0x6031, + 0x9C85, 0x601B, 0x9C86, 0x6015, 0x9C87, 0x602B, 0x9C88, 0x6026, 0x9C89, 0x600F, 0x9C8A, 0x603A, 0x9C8B, 0x605A, 0x9C8C, 0x6041, + 0x9C8D, 0x606A, 0x9C8E, 0x6077, 0x9C8F, 0x605F, 0x9C90, 0x604A, 0x9C91, 0x6046, 0x9C92, 0x604D, 0x9C93, 0x6063, 0x9C94, 0x6043, + 0x9C95, 0x6064, 0x9C96, 0x6042, 0x9C97, 0x606C, 0x9C98, 0x606B, 0x9C99, 0x6059, 0x9C9A, 0x6081, 0x9C9B, 0x608D, 0x9C9C, 0x60E7, + 0x9C9D, 0x6083, 0x9C9E, 0x609A, 0x9C9F, 0x6084, 0x9CA0, 0x609B, 0x9CA1, 0x6096, 0x9CA2, 0x6097, 0x9CA3, 0x6092, 0x9CA4, 0x60A7, + 0x9CA5, 0x608B, 0x9CA6, 0x60E1, 0x9CA7, 0x60B8, 0x9CA8, 0x60E0, 0x9CA9, 0x60D3, 0x9CAA, 0x60B4, 0x9CAB, 0x5FF0, 0x9CAC, 0x60BD, + 0x9CAD, 0x60C6, 0x9CAE, 0x60B5, 0x9CAF, 0x60D8, 0x9CB0, 0x614D, 0x9CB1, 0x6115, 0x9CB2, 0x6106, 0x9CB3, 0x60F6, 0x9CB4, 0x60F7, + 0x9CB5, 0x6100, 0x9CB6, 0x60F4, 0x9CB7, 0x60FA, 0x9CB8, 0x6103, 0x9CB9, 0x6121, 0x9CBA, 0x60FB, 0x9CBB, 0x60F1, 0x9CBC, 0x610D, + 0x9CBD, 0x610E, 0x9CBE, 0x6147, 0x9CBF, 0x613E, 0x9CC0, 0x6128, 0x9CC1, 0x6127, 0x9CC2, 0x614A, 0x9CC3, 0x613F, 0x9CC4, 0x613C, + 0x9CC5, 0x612C, 0x9CC6, 0x6134, 0x9CC7, 0x613D, 0x9CC8, 0x6142, 0x9CC9, 0x6144, 0x9CCA, 0x6173, 0x9CCB, 0x6177, 0x9CCC, 0x6158, + 0x9CCD, 0x6159, 0x9CCE, 0x615A, 0x9CCF, 0x616B, 0x9CD0, 0x6174, 0x9CD1, 0x616F, 0x9CD2, 0x6165, 0x9CD3, 0x6171, 0x9CD4, 0x615F, + 0x9CD5, 0x615D, 0x9CD6, 0x6153, 0x9CD7, 0x6175, 0x9CD8, 0x6199, 0x9CD9, 0x6196, 0x9CDA, 0x6187, 0x9CDB, 0x61AC, 0x9CDC, 0x6194, + 0x9CDD, 0x619A, 0x9CDE, 0x618A, 0x9CDF, 0x6191, 0x9CE0, 0x61AB, 0x9CE1, 0x61AE, 0x9CE2, 0x61CC, 0x9CE3, 0x61CA, 0x9CE4, 0x61C9, + 0x9CE5, 0x61F7, 0x9CE6, 0x61C8, 0x9CE7, 0x61C3, 0x9CE8, 0x61C6, 0x9CE9, 0x61BA, 0x9CEA, 0x61CB, 0x9CEB, 0x7F79, 0x9CEC, 0x61CD, + 0x9CED, 0x61E6, 0x9CEE, 0x61E3, 0x9CEF, 0x61F6, 0x9CF0, 0x61FA, 0x9CF1, 0x61F4, 0x9CF2, 0x61FF, 0x9CF3, 0x61FD, 0x9CF4, 0x61FC, + 0x9CF5, 0x61FE, 0x9CF6, 0x6200, 0x9CF7, 0x6208, 0x9CF8, 0x6209, 0x9CF9, 0x620D, 0x9CFA, 0x620C, 0x9CFB, 0x6214, 0x9CFC, 0x621B, + 0x9D40, 0x621E, 0x9D41, 0x6221, 0x9D42, 0x622A, 0x9D43, 0x622E, 0x9D44, 0x6230, 0x9D45, 0x6232, 0x9D46, 0x6233, 0x9D47, 0x6241, + 0x9D48, 0x624E, 0x9D49, 0x625E, 0x9D4A, 0x6263, 0x9D4B, 0x625B, 0x9D4C, 0x6260, 0x9D4D, 0x6268, 0x9D4E, 0x627C, 0x9D4F, 0x6282, + 0x9D50, 0x6289, 0x9D51, 0x627E, 0x9D52, 0x6292, 0x9D53, 0x6293, 0x9D54, 0x6296, 0x9D55, 0x62D4, 0x9D56, 0x6283, 0x9D57, 0x6294, + 0x9D58, 0x62D7, 0x9D59, 0x62D1, 0x9D5A, 0x62BB, 0x9D5B, 0x62CF, 0x9D5C, 0x62FF, 0x9D5D, 0x62C6, 0x9D5E, 0x64D4, 0x9D5F, 0x62C8, + 0x9D60, 0x62DC, 0x9D61, 0x62CC, 0x9D62, 0x62CA, 0x9D63, 0x62C2, 0x9D64, 0x62C7, 0x9D65, 0x629B, 0x9D66, 0x62C9, 0x9D67, 0x630C, + 0x9D68, 0x62EE, 0x9D69, 0x62F1, 0x9D6A, 0x6327, 0x9D6B, 0x6302, 0x9D6C, 0x6308, 0x9D6D, 0x62EF, 0x9D6E, 0x62F5, 0x9D6F, 0x6350, + 0x9D70, 0x633E, 0x9D71, 0x634D, 0x9D72, 0x641C, 0x9D73, 0x634F, 0x9D74, 0x6396, 0x9D75, 0x638E, 0x9D76, 0x6380, 0x9D77, 0x63AB, + 0x9D78, 0x6376, 0x9D79, 0x63A3, 0x9D7A, 0x638F, 0x9D7B, 0x6389, 0x9D7C, 0x639F, 0x9D7D, 0x63B5, 0x9D7E, 0x636B, 0x9D80, 0x6369, + 0x9D81, 0x63BE, 0x9D82, 0x63E9, 0x9D83, 0x63C0, 0x9D84, 0x63C6, 0x9D85, 0x63E3, 0x9D86, 0x63C9, 0x9D87, 0x63D2, 0x9D88, 0x63F6, + 0x9D89, 0x63C4, 0x9D8A, 0x6416, 0x9D8B, 0x6434, 0x9D8C, 0x6406, 0x9D8D, 0x6413, 0x9D8E, 0x6426, 0x9D8F, 0x6436, 0x9D90, 0x651D, + 0x9D91, 0x6417, 0x9D92, 0x6428, 0x9D93, 0x640F, 0x9D94, 0x6467, 0x9D95, 0x646F, 0x9D96, 0x6476, 0x9D97, 0x644E, 0x9D98, 0x652A, + 0x9D99, 0x6495, 0x9D9A, 0x6493, 0x9D9B, 0x64A5, 0x9D9C, 0x64A9, 0x9D9D, 0x6488, 0x9D9E, 0x64BC, 0x9D9F, 0x64DA, 0x9DA0, 0x64D2, + 0x9DA1, 0x64C5, 0x9DA2, 0x64C7, 0x9DA3, 0x64BB, 0x9DA4, 0x64D8, 0x9DA5, 0x64C2, 0x9DA6, 0x64F1, 0x9DA7, 0x64E7, 0x9DA8, 0x8209, + 0x9DA9, 0x64E0, 0x9DAA, 0x64E1, 0x9DAB, 0x62AC, 0x9DAC, 0x64E3, 0x9DAD, 0x64EF, 0x9DAE, 0x652C, 0x9DAF, 0x64F6, 0x9DB0, 0x64F4, + 0x9DB1, 0x64F2, 0x9DB2, 0x64FA, 0x9DB3, 0x6500, 0x9DB4, 0x64FD, 0x9DB5, 0x6518, 0x9DB6, 0x651C, 0x9DB7, 0x6505, 0x9DB8, 0x6524, + 0x9DB9, 0x6523, 0x9DBA, 0x652B, 0x9DBB, 0x6534, 0x9DBC, 0x6535, 0x9DBD, 0x6537, 0x9DBE, 0x6536, 0x9DBF, 0x6538, 0x9DC0, 0x754B, + 0x9DC1, 0x6548, 0x9DC2, 0x6556, 0x9DC3, 0x6555, 0x9DC4, 0x654D, 0x9DC5, 0x6558, 0x9DC6, 0x655E, 0x9DC7, 0x655D, 0x9DC8, 0x6572, + 0x9DC9, 0x6578, 0x9DCA, 0x6582, 0x9DCB, 0x6583, 0x9DCC, 0x8B8A, 0x9DCD, 0x659B, 0x9DCE, 0x659F, 0x9DCF, 0x65AB, 0x9DD0, 0x65B7, + 0x9DD1, 0x65C3, 0x9DD2, 0x65C6, 0x9DD3, 0x65C1, 0x9DD4, 0x65C4, 0x9DD5, 0x65CC, 0x9DD6, 0x65D2, 0x9DD7, 0x65DB, 0x9DD8, 0x65D9, + 0x9DD9, 0x65E0, 0x9DDA, 0x65E1, 0x9DDB, 0x65F1, 0x9DDC, 0x6772, 0x9DDD, 0x660A, 0x9DDE, 0x6603, 0x9DDF, 0x65FB, 0x9DE0, 0x6773, + 0x9DE1, 0x6635, 0x9DE2, 0x6636, 0x9DE3, 0x6634, 0x9DE4, 0x661C, 0x9DE5, 0x664F, 0x9DE6, 0x6644, 0x9DE7, 0x6649, 0x9DE8, 0x6641, + 0x9DE9, 0x665E, 0x9DEA, 0x665D, 0x9DEB, 0x6664, 0x9DEC, 0x6667, 0x9DED, 0x6668, 0x9DEE, 0x665F, 0x9DEF, 0x6662, 0x9DF0, 0x6670, + 0x9DF1, 0x6683, 0x9DF2, 0x6688, 0x9DF3, 0x668E, 0x9DF4, 0x6689, 0x9DF5, 0x6684, 0x9DF6, 0x6698, 0x9DF7, 0x669D, 0x9DF8, 0x66C1, + 0x9DF9, 0x66B9, 0x9DFA, 0x66C9, 0x9DFB, 0x66BE, 0x9DFC, 0x66BC, 0x9E40, 0x66C4, 0x9E41, 0x66B8, 0x9E42, 0x66D6, 0x9E43, 0x66DA, + 0x9E44, 0x66E0, 0x9E45, 0x663F, 0x9E46, 0x66E6, 0x9E47, 0x66E9, 0x9E48, 0x66F0, 0x9E49, 0x66F5, 0x9E4A, 0x66F7, 0x9E4B, 0x670F, + 0x9E4C, 0x6716, 0x9E4D, 0x671E, 0x9E4E, 0x6726, 0x9E4F, 0x6727, 0x9E50, 0x9738, 0x9E51, 0x672E, 0x9E52, 0x673F, 0x9E53, 0x6736, + 0x9E54, 0x6741, 0x9E55, 0x6738, 0x9E56, 0x6737, 0x9E57, 0x6746, 0x9E58, 0x675E, 0x9E59, 0x6760, 0x9E5A, 0x6759, 0x9E5B, 0x6763, + 0x9E5C, 0x6764, 0x9E5D, 0x6789, 0x9E5E, 0x6770, 0x9E5F, 0x67A9, 0x9E60, 0x677C, 0x9E61, 0x676A, 0x9E62, 0x678C, 0x9E63, 0x678B, + 0x9E64, 0x67A6, 0x9E65, 0x67A1, 0x9E66, 0x6785, 0x9E67, 0x67B7, 0x9E68, 0x67EF, 0x9E69, 0x67B4, 0x9E6A, 0x67EC, 0x9E6B, 0x67B3, + 0x9E6C, 0x67E9, 0x9E6D, 0x67B8, 0x9E6E, 0x67E4, 0x9E6F, 0x67DE, 0x9E70, 0x67DD, 0x9E71, 0x67E2, 0x9E72, 0x67EE, 0x9E73, 0x67B9, + 0x9E74, 0x67CE, 0x9E75, 0x67C6, 0x9E76, 0x67E7, 0x9E77, 0x6A9C, 0x9E78, 0x681E, 0x9E79, 0x6846, 0x9E7A, 0x6829, 0x9E7B, 0x6840, + 0x9E7C, 0x684D, 0x9E7D, 0x6832, 0x9E7E, 0x684E, 0x9E80, 0x68B3, 0x9E81, 0x682B, 0x9E82, 0x6859, 0x9E83, 0x6863, 0x9E84, 0x6877, + 0x9E85, 0x687F, 0x9E86, 0x689F, 0x9E87, 0x688F, 0x9E88, 0x68AD, 0x9E89, 0x6894, 0x9E8A, 0x689D, 0x9E8B, 0x689B, 0x9E8C, 0x6883, + 0x9E8D, 0x6AAE, 0x9E8E, 0x68B9, 0x9E8F, 0x6874, 0x9E90, 0x68B5, 0x9E91, 0x68A0, 0x9E92, 0x68BA, 0x9E93, 0x690F, 0x9E94, 0x688D, + 0x9E95, 0x687E, 0x9E96, 0x6901, 0x9E97, 0x68CA, 0x9E98, 0x6908, 0x9E99, 0x68D8, 0x9E9A, 0x6922, 0x9E9B, 0x6926, 0x9E9C, 0x68E1, + 0x9E9D, 0x690C, 0x9E9E, 0x68CD, 0x9E9F, 0x68D4, 0x9EA0, 0x68E7, 0x9EA1, 0x68D5, 0x9EA2, 0x6936, 0x9EA3, 0x6912, 0x9EA4, 0x6904, + 0x9EA5, 0x68D7, 0x9EA6, 0x68E3, 0x9EA7, 0x6925, 0x9EA8, 0x68F9, 0x9EA9, 0x68E0, 0x9EAA, 0x68EF, 0x9EAB, 0x6928, 0x9EAC, 0x692A, + 0x9EAD, 0x691A, 0x9EAE, 0x6923, 0x9EAF, 0x6921, 0x9EB0, 0x68C6, 0x9EB1, 0x6979, 0x9EB2, 0x6977, 0x9EB3, 0x695C, 0x9EB4, 0x6978, + 0x9EB5, 0x696B, 0x9EB6, 0x6954, 0x9EB7, 0x697E, 0x9EB8, 0x696E, 0x9EB9, 0x6939, 0x9EBA, 0x6974, 0x9EBB, 0x693D, 0x9EBC, 0x6959, + 0x9EBD, 0x6930, 0x9EBE, 0x6961, 0x9EBF, 0x695E, 0x9EC0, 0x695D, 0x9EC1, 0x6981, 0x9EC2, 0x696A, 0x9EC3, 0x69B2, 0x9EC4, 0x69AE, + 0x9EC5, 0x69D0, 0x9EC6, 0x69BF, 0x9EC7, 0x69C1, 0x9EC8, 0x69D3, 0x9EC9, 0x69BE, 0x9ECA, 0x69CE, 0x9ECB, 0x5BE8, 0x9ECC, 0x69CA, + 0x9ECD, 0x69DD, 0x9ECE, 0x69BB, 0x9ECF, 0x69C3, 0x9ED0, 0x69A7, 0x9ED1, 0x6A2E, 0x9ED2, 0x6991, 0x9ED3, 0x69A0, 0x9ED4, 0x699C, + 0x9ED5, 0x6995, 0x9ED6, 0x69B4, 0x9ED7, 0x69DE, 0x9ED8, 0x69E8, 0x9ED9, 0x6A02, 0x9EDA, 0x6A1B, 0x9EDB, 0x69FF, 0x9EDC, 0x6B0A, + 0x9EDD, 0x69F9, 0x9EDE, 0x69F2, 0x9EDF, 0x69E7, 0x9EE0, 0x6A05, 0x9EE1, 0x69B1, 0x9EE2, 0x6A1E, 0x9EE3, 0x69ED, 0x9EE4, 0x6A14, + 0x9EE5, 0x69EB, 0x9EE6, 0x6A0A, 0x9EE7, 0x6A12, 0x9EE8, 0x6AC1, 0x9EE9, 0x6A23, 0x9EEA, 0x6A13, 0x9EEB, 0x6A44, 0x9EEC, 0x6A0C, + 0x9EED, 0x6A72, 0x9EEE, 0x6A36, 0x9EEF, 0x6A78, 0x9EF0, 0x6A47, 0x9EF1, 0x6A62, 0x9EF2, 0x6A59, 0x9EF3, 0x6A66, 0x9EF4, 0x6A48, + 0x9EF5, 0x6A38, 0x9EF6, 0x6A22, 0x9EF7, 0x6A90, 0x9EF8, 0x6A8D, 0x9EF9, 0x6AA0, 0x9EFA, 0x6A84, 0x9EFB, 0x6AA2, 0x9EFC, 0x6AA3, + 0x9F40, 0x6A97, 0x9F41, 0x8617, 0x9F42, 0x6ABB, 0x9F43, 0x6AC3, 0x9F44, 0x6AC2, 0x9F45, 0x6AB8, 0x9F46, 0x6AB3, 0x9F47, 0x6AAC, + 0x9F48, 0x6ADE, 0x9F49, 0x6AD1, 0x9F4A, 0x6ADF, 0x9F4B, 0x6AAA, 0x9F4C, 0x6ADA, 0x9F4D, 0x6AEA, 0x9F4E, 0x6AFB, 0x9F4F, 0x6B05, + 0x9F50, 0x8616, 0x9F51, 0x6AFA, 0x9F52, 0x6B12, 0x9F53, 0x6B16, 0x9F54, 0x9B31, 0x9F55, 0x6B1F, 0x9F56, 0x6B38, 0x9F57, 0x6B37, + 0x9F58, 0x76DC, 0x9F59, 0x6B39, 0x9F5A, 0x98EE, 0x9F5B, 0x6B47, 0x9F5C, 0x6B43, 0x9F5D, 0x6B49, 0x9F5E, 0x6B50, 0x9F5F, 0x6B59, + 0x9F60, 0x6B54, 0x9F61, 0x6B5B, 0x9F62, 0x6B5F, 0x9F63, 0x6B61, 0x9F64, 0x6B78, 0x9F65, 0x6B79, 0x9F66, 0x6B7F, 0x9F67, 0x6B80, + 0x9F68, 0x6B84, 0x9F69, 0x6B83, 0x9F6A, 0x6B8D, 0x9F6B, 0x6B98, 0x9F6C, 0x6B95, 0x9F6D, 0x6B9E, 0x9F6E, 0x6BA4, 0x9F6F, 0x6BAA, + 0x9F70, 0x6BAB, 0x9F71, 0x6BAF, 0x9F72, 0x6BB2, 0x9F73, 0x6BB1, 0x9F74, 0x6BB3, 0x9F75, 0x6BB7, 0x9F76, 0x6BBC, 0x9F77, 0x6BC6, + 0x9F78, 0x6BCB, 0x9F79, 0x6BD3, 0x9F7A, 0x6BDF, 0x9F7B, 0x6BEC, 0x9F7C, 0x6BEB, 0x9F7D, 0x6BF3, 0x9F7E, 0x6BEF, 0x9F80, 0x9EBE, + 0x9F81, 0x6C08, 0x9F82, 0x6C13, 0x9F83, 0x6C14, 0x9F84, 0x6C1B, 0x9F85, 0x6C24, 0x9F86, 0x6C23, 0x9F87, 0x6C5E, 0x9F88, 0x6C55, + 0x9F89, 0x6C62, 0x9F8A, 0x6C6A, 0x9F8B, 0x6C82, 0x9F8C, 0x6C8D, 0x9F8D, 0x6C9A, 0x9F8E, 0x6C81, 0x9F8F, 0x6C9B, 0x9F90, 0x6C7E, + 0x9F91, 0x6C68, 0x9F92, 0x6C73, 0x9F93, 0x6C92, 0x9F94, 0x6C90, 0x9F95, 0x6CC4, 0x9F96, 0x6CF1, 0x9F97, 0x6CD3, 0x9F98, 0x6CBD, + 0x9F99, 0x6CD7, 0x9F9A, 0x6CC5, 0x9F9B, 0x6CDD, 0x9F9C, 0x6CAE, 0x9F9D, 0x6CB1, 0x9F9E, 0x6CBE, 0x9F9F, 0x6CBA, 0x9FA0, 0x6CDB, + 0x9FA1, 0x6CEF, 0x9FA2, 0x6CD9, 0x9FA3, 0x6CEA, 0x9FA4, 0x6D1F, 0x9FA5, 0x884D, 0x9FA6, 0x6D36, 0x9FA7, 0x6D2B, 0x9FA8, 0x6D3D, + 0x9FA9, 0x6D38, 0x9FAA, 0x6D19, 0x9FAB, 0x6D35, 0x9FAC, 0x6D33, 0x9FAD, 0x6D12, 0x9FAE, 0x6D0C, 0x9FAF, 0x6D63, 0x9FB0, 0x6D93, + 0x9FB1, 0x6D64, 0x9FB2, 0x6D5A, 0x9FB3, 0x6D79, 0x9FB4, 0x6D59, 0x9FB5, 0x6D8E, 0x9FB6, 0x6D95, 0x9FB7, 0x6FE4, 0x9FB8, 0x6D85, + 0x9FB9, 0x6DF9, 0x9FBA, 0x6E15, 0x9FBB, 0x6E0A, 0x9FBC, 0x6DB5, 0x9FBD, 0x6DC7, 0x9FBE, 0x6DE6, 0x9FBF, 0x6DB8, 0x9FC0, 0x6DC6, + 0x9FC1, 0x6DEC, 0x9FC2, 0x6DDE, 0x9FC3, 0x6DCC, 0x9FC4, 0x6DE8, 0x9FC5, 0x6DD2, 0x9FC6, 0x6DC5, 0x9FC7, 0x6DFA, 0x9FC8, 0x6DD9, + 0x9FC9, 0x6DE4, 0x9FCA, 0x6DD5, 0x9FCB, 0x6DEA, 0x9FCC, 0x6DEE, 0x9FCD, 0x6E2D, 0x9FCE, 0x6E6E, 0x9FCF, 0x6E2E, 0x9FD0, 0x6E19, + 0x9FD1, 0x6E72, 0x9FD2, 0x6E5F, 0x9FD3, 0x6E3E, 0x9FD4, 0x6E23, 0x9FD5, 0x6E6B, 0x9FD6, 0x6E2B, 0x9FD7, 0x6E76, 0x9FD8, 0x6E4D, + 0x9FD9, 0x6E1F, 0x9FDA, 0x6E43, 0x9FDB, 0x6E3A, 0x9FDC, 0x6E4E, 0x9FDD, 0x6E24, 0x9FDE, 0x6EFF, 0x9FDF, 0x6E1D, 0x9FE0, 0x6E38, + 0x9FE1, 0x6E82, 0x9FE2, 0x6EAA, 0x9FE3, 0x6E98, 0x9FE4, 0x6EC9, 0x9FE5, 0x6EB7, 0x9FE6, 0x6ED3, 0x9FE7, 0x6EBD, 0x9FE8, 0x6EAF, + 0x9FE9, 0x6EC4, 0x9FEA, 0x6EB2, 0x9FEB, 0x6ED4, 0x9FEC, 0x6ED5, 0x9FED, 0x6E8F, 0x9FEE, 0x6EA5, 0x9FEF, 0x6EC2, 0x9FF0, 0x6E9F, + 0x9FF1, 0x6F41, 0x9FF2, 0x6F11, 0x9FF3, 0x704C, 0x9FF4, 0x6EEC, 0x9FF5, 0x6EF8, 0x9FF6, 0x6EFE, 0x9FF7, 0x6F3F, 0x9FF8, 0x6EF2, + 0x9FF9, 0x6F31, 0x9FFA, 0x6EEF, 0x9FFB, 0x6F32, 0x9FFC, 0x6ECC, 0xE040, 0x6F3E, 0xE041, 0x6F13, 0xE042, 0x6EF7, 0xE043, 0x6F86, + 0xE044, 0x6F7A, 0xE045, 0x6F78, 0xE046, 0x6F81, 0xE047, 0x6F80, 0xE048, 0x6F6F, 0xE049, 0x6F5B, 0xE04A, 0x6FF3, 0xE04B, 0x6F6D, + 0xE04C, 0x6F82, 0xE04D, 0x6F7C, 0xE04E, 0x6F58, 0xE04F, 0x6F8E, 0xE050, 0x6F91, 0xE051, 0x6FC2, 0xE052, 0x6F66, 0xE053, 0x6FB3, + 0xE054, 0x6FA3, 0xE055, 0x6FA1, 0xE056, 0x6FA4, 0xE057, 0x6FB9, 0xE058, 0x6FC6, 0xE059, 0x6FAA, 0xE05A, 0x6FDF, 0xE05B, 0x6FD5, + 0xE05C, 0x6FEC, 0xE05D, 0x6FD4, 0xE05E, 0x6FD8, 0xE05F, 0x6FF1, 0xE060, 0x6FEE, 0xE061, 0x6FDB, 0xE062, 0x7009, 0xE063, 0x700B, + 0xE064, 0x6FFA, 0xE065, 0x7011, 0xE066, 0x7001, 0xE067, 0x700F, 0xE068, 0x6FFE, 0xE069, 0x701B, 0xE06A, 0x701A, 0xE06B, 0x6F74, + 0xE06C, 0x701D, 0xE06D, 0x7018, 0xE06E, 0x701F, 0xE06F, 0x7030, 0xE070, 0x703E, 0xE071, 0x7032, 0xE072, 0x7051, 0xE073, 0x7063, + 0xE074, 0x7099, 0xE075, 0x7092, 0xE076, 0x70AF, 0xE077, 0x70F1, 0xE078, 0x70AC, 0xE079, 0x70B8, 0xE07A, 0x70B3, 0xE07B, 0x70AE, + 0xE07C, 0x70DF, 0xE07D, 0x70CB, 0xE07E, 0x70DD, 0xE080, 0x70D9, 0xE081, 0x7109, 0xE082, 0x70FD, 0xE083, 0x711C, 0xE084, 0x7119, + 0xE085, 0x7165, 0xE086, 0x7155, 0xE087, 0x7188, 0xE088, 0x7166, 0xE089, 0x7162, 0xE08A, 0x714C, 0xE08B, 0x7156, 0xE08C, 0x716C, + 0xE08D, 0x718F, 0xE08E, 0x71FB, 0xE08F, 0x7184, 0xE090, 0x7195, 0xE091, 0x71A8, 0xE092, 0x71AC, 0xE093, 0x71D7, 0xE094, 0x71B9, + 0xE095, 0x71BE, 0xE096, 0x71D2, 0xE097, 0x71C9, 0xE098, 0x71D4, 0xE099, 0x71CE, 0xE09A, 0x71E0, 0xE09B, 0x71EC, 0xE09C, 0x71E7, + 0xE09D, 0x71F5, 0xE09E, 0x71FC, 0xE09F, 0x71F9, 0xE0A0, 0x71FF, 0xE0A1, 0x720D, 0xE0A2, 0x7210, 0xE0A3, 0x721B, 0xE0A4, 0x7228, + 0xE0A5, 0x722D, 0xE0A6, 0x722C, 0xE0A7, 0x7230, 0xE0A8, 0x7232, 0xE0A9, 0x723B, 0xE0AA, 0x723C, 0xE0AB, 0x723F, 0xE0AC, 0x7240, + 0xE0AD, 0x7246, 0xE0AE, 0x724B, 0xE0AF, 0x7258, 0xE0B0, 0x7274, 0xE0B1, 0x727E, 0xE0B2, 0x7282, 0xE0B3, 0x7281, 0xE0B4, 0x7287, + 0xE0B5, 0x7292, 0xE0B6, 0x7296, 0xE0B7, 0x72A2, 0xE0B8, 0x72A7, 0xE0B9, 0x72B9, 0xE0BA, 0x72B2, 0xE0BB, 0x72C3, 0xE0BC, 0x72C6, + 0xE0BD, 0x72C4, 0xE0BE, 0x72CE, 0xE0BF, 0x72D2, 0xE0C0, 0x72E2, 0xE0C1, 0x72E0, 0xE0C2, 0x72E1, 0xE0C3, 0x72F9, 0xE0C4, 0x72F7, + 0xE0C5, 0x500F, 0xE0C6, 0x7317, 0xE0C7, 0x730A, 0xE0C8, 0x731C, 0xE0C9, 0x7316, 0xE0CA, 0x731D, 0xE0CB, 0x7334, 0xE0CC, 0x732F, + 0xE0CD, 0x7329, 0xE0CE, 0x7325, 0xE0CF, 0x733E, 0xE0D0, 0x734E, 0xE0D1, 0x734F, 0xE0D2, 0x9ED8, 0xE0D3, 0x7357, 0xE0D4, 0x736A, + 0xE0D5, 0x7368, 0xE0D6, 0x7370, 0xE0D7, 0x7378, 0xE0D8, 0x7375, 0xE0D9, 0x737B, 0xE0DA, 0x737A, 0xE0DB, 0x73C8, 0xE0DC, 0x73B3, + 0xE0DD, 0x73CE, 0xE0DE, 0x73BB, 0xE0DF, 0x73C0, 0xE0E0, 0x73E5, 0xE0E1, 0x73EE, 0xE0E2, 0x73DE, 0xE0E3, 0x74A2, 0xE0E4, 0x7405, + 0xE0E5, 0x746F, 0xE0E6, 0x7425, 0xE0E7, 0x73F8, 0xE0E8, 0x7432, 0xE0E9, 0x743A, 0xE0EA, 0x7455, 0xE0EB, 0x743F, 0xE0EC, 0x745F, + 0xE0ED, 0x7459, 0xE0EE, 0x7441, 0xE0EF, 0x745C, 0xE0F0, 0x7469, 0xE0F1, 0x7470, 0xE0F2, 0x7463, 0xE0F3, 0x746A, 0xE0F4, 0x7476, + 0xE0F5, 0x747E, 0xE0F6, 0x748B, 0xE0F7, 0x749E, 0xE0F8, 0x74A7, 0xE0F9, 0x74CA, 0xE0FA, 0x74CF, 0xE0FB, 0x74D4, 0xE0FC, 0x73F1, + 0xE140, 0x74E0, 0xE141, 0x74E3, 0xE142, 0x74E7, 0xE143, 0x74E9, 0xE144, 0x74EE, 0xE145, 0x74F2, 0xE146, 0x74F0, 0xE147, 0x74F1, + 0xE148, 0x74F8, 0xE149, 0x74F7, 0xE14A, 0x7504, 0xE14B, 0x7503, 0xE14C, 0x7505, 0xE14D, 0x750C, 0xE14E, 0x750E, 0xE14F, 0x750D, + 0xE150, 0x7515, 0xE151, 0x7513, 0xE152, 0x751E, 0xE153, 0x7526, 0xE154, 0x752C, 0xE155, 0x753C, 0xE156, 0x7544, 0xE157, 0x754D, + 0xE158, 0x754A, 0xE159, 0x7549, 0xE15A, 0x755B, 0xE15B, 0x7546, 0xE15C, 0x755A, 0xE15D, 0x7569, 0xE15E, 0x7564, 0xE15F, 0x7567, + 0xE160, 0x756B, 0xE161, 0x756D, 0xE162, 0x7578, 0xE163, 0x7576, 0xE164, 0x7586, 0xE165, 0x7587, 0xE166, 0x7574, 0xE167, 0x758A, + 0xE168, 0x7589, 0xE169, 0x7582, 0xE16A, 0x7594, 0xE16B, 0x759A, 0xE16C, 0x759D, 0xE16D, 0x75A5, 0xE16E, 0x75A3, 0xE16F, 0x75C2, + 0xE170, 0x75B3, 0xE171, 0x75C3, 0xE172, 0x75B5, 0xE173, 0x75BD, 0xE174, 0x75B8, 0xE175, 0x75BC, 0xE176, 0x75B1, 0xE177, 0x75CD, + 0xE178, 0x75CA, 0xE179, 0x75D2, 0xE17A, 0x75D9, 0xE17B, 0x75E3, 0xE17C, 0x75DE, 0xE17D, 0x75FE, 0xE17E, 0x75FF, 0xE180, 0x75FC, + 0xE181, 0x7601, 0xE182, 0x75F0, 0xE183, 0x75FA, 0xE184, 0x75F2, 0xE185, 0x75F3, 0xE186, 0x760B, 0xE187, 0x760D, 0xE188, 0x7609, + 0xE189, 0x761F, 0xE18A, 0x7627, 0xE18B, 0x7620, 0xE18C, 0x7621, 0xE18D, 0x7622, 0xE18E, 0x7624, 0xE18F, 0x7634, 0xE190, 0x7630, + 0xE191, 0x763B, 0xE192, 0x7647, 0xE193, 0x7648, 0xE194, 0x7646, 0xE195, 0x765C, 0xE196, 0x7658, 0xE197, 0x7661, 0xE198, 0x7662, + 0xE199, 0x7668, 0xE19A, 0x7669, 0xE19B, 0x766A, 0xE19C, 0x7667, 0xE19D, 0x766C, 0xE19E, 0x7670, 0xE19F, 0x7672, 0xE1A0, 0x7676, + 0xE1A1, 0x7678, 0xE1A2, 0x767C, 0xE1A3, 0x7680, 0xE1A4, 0x7683, 0xE1A5, 0x7688, 0xE1A6, 0x768B, 0xE1A7, 0x768E, 0xE1A8, 0x7696, + 0xE1A9, 0x7693, 0xE1AA, 0x7699, 0xE1AB, 0x769A, 0xE1AC, 0x76B0, 0xE1AD, 0x76B4, 0xE1AE, 0x76B8, 0xE1AF, 0x76B9, 0xE1B0, 0x76BA, + 0xE1B1, 0x76C2, 0xE1B2, 0x76CD, 0xE1B3, 0x76D6, 0xE1B4, 0x76D2, 0xE1B5, 0x76DE, 0xE1B6, 0x76E1, 0xE1B7, 0x76E5, 0xE1B8, 0x76E7, + 0xE1B9, 0x76EA, 0xE1BA, 0x862F, 0xE1BB, 0x76FB, 0xE1BC, 0x7708, 0xE1BD, 0x7707, 0xE1BE, 0x7704, 0xE1BF, 0x7729, 0xE1C0, 0x7724, + 0xE1C1, 0x771E, 0xE1C2, 0x7725, 0xE1C3, 0x7726, 0xE1C4, 0x771B, 0xE1C5, 0x7737, 0xE1C6, 0x7738, 0xE1C7, 0x7747, 0xE1C8, 0x775A, + 0xE1C9, 0x7768, 0xE1CA, 0x776B, 0xE1CB, 0x775B, 0xE1CC, 0x7765, 0xE1CD, 0x777F, 0xE1CE, 0x777E, 0xE1CF, 0x7779, 0xE1D0, 0x778E, + 0xE1D1, 0x778B, 0xE1D2, 0x7791, 0xE1D3, 0x77A0, 0xE1D4, 0x779E, 0xE1D5, 0x77B0, 0xE1D6, 0x77B6, 0xE1D7, 0x77B9, 0xE1D8, 0x77BF, + 0xE1D9, 0x77BC, 0xE1DA, 0x77BD, 0xE1DB, 0x77BB, 0xE1DC, 0x77C7, 0xE1DD, 0x77CD, 0xE1DE, 0x77D7, 0xE1DF, 0x77DA, 0xE1E0, 0x77DC, + 0xE1E1, 0x77E3, 0xE1E2, 0x77EE, 0xE1E3, 0x77FC, 0xE1E4, 0x780C, 0xE1E5, 0x7812, 0xE1E6, 0x7926, 0xE1E7, 0x7820, 0xE1E8, 0x792A, + 0xE1E9, 0x7845, 0xE1EA, 0x788E, 0xE1EB, 0x7874, 0xE1EC, 0x7886, 0xE1ED, 0x787C, 0xE1EE, 0x789A, 0xE1EF, 0x788C, 0xE1F0, 0x78A3, + 0xE1F1, 0x78B5, 0xE1F2, 0x78AA, 0xE1F3, 0x78AF, 0xE1F4, 0x78D1, 0xE1F5, 0x78C6, 0xE1F6, 0x78CB, 0xE1F7, 0x78D4, 0xE1F8, 0x78BE, + 0xE1F9, 0x78BC, 0xE1FA, 0x78C5, 0xE1FB, 0x78CA, 0xE1FC, 0x78EC, 0xE240, 0x78E7, 0xE241, 0x78DA, 0xE242, 0x78FD, 0xE243, 0x78F4, + 0xE244, 0x7907, 0xE245, 0x7912, 0xE246, 0x7911, 0xE247, 0x7919, 0xE248, 0x792C, 0xE249, 0x792B, 0xE24A, 0x7940, 0xE24B, 0x7960, + 0xE24C, 0x7957, 0xE24D, 0x795F, 0xE24E, 0x795A, 0xE24F, 0x7955, 0xE250, 0x7953, 0xE251, 0x797A, 0xE252, 0x797F, 0xE253, 0x798A, + 0xE254, 0x799D, 0xE255, 0x79A7, 0xE256, 0x9F4B, 0xE257, 0x79AA, 0xE258, 0x79AE, 0xE259, 0x79B3, 0xE25A, 0x79B9, 0xE25B, 0x79BA, + 0xE25C, 0x79C9, 0xE25D, 0x79D5, 0xE25E, 0x79E7, 0xE25F, 0x79EC, 0xE260, 0x79E1, 0xE261, 0x79E3, 0xE262, 0x7A08, 0xE263, 0x7A0D, + 0xE264, 0x7A18, 0xE265, 0x7A19, 0xE266, 0x7A20, 0xE267, 0x7A1F, 0xE268, 0x7980, 0xE269, 0x7A31, 0xE26A, 0x7A3B, 0xE26B, 0x7A3E, + 0xE26C, 0x7A37, 0xE26D, 0x7A43, 0xE26E, 0x7A57, 0xE26F, 0x7A49, 0xE270, 0x7A61, 0xE271, 0x7A62, 0xE272, 0x7A69, 0xE273, 0x9F9D, + 0xE274, 0x7A70, 0xE275, 0x7A79, 0xE276, 0x7A7D, 0xE277, 0x7A88, 0xE278, 0x7A97, 0xE279, 0x7A95, 0xE27A, 0x7A98, 0xE27B, 0x7A96, + 0xE27C, 0x7AA9, 0xE27D, 0x7AC8, 0xE27E, 0x7AB0, 0xE280, 0x7AB6, 0xE281, 0x7AC5, 0xE282, 0x7AC4, 0xE283, 0x7ABF, 0xE284, 0x9083, + 0xE285, 0x7AC7, 0xE286, 0x7ACA, 0xE287, 0x7ACD, 0xE288, 0x7ACF, 0xE289, 0x7AD5, 0xE28A, 0x7AD3, 0xE28B, 0x7AD9, 0xE28C, 0x7ADA, + 0xE28D, 0x7ADD, 0xE28E, 0x7AE1, 0xE28F, 0x7AE2, 0xE290, 0x7AE6, 0xE291, 0x7AED, 0xE292, 0x7AF0, 0xE293, 0x7B02, 0xE294, 0x7B0F, + 0xE295, 0x7B0A, 0xE296, 0x7B06, 0xE297, 0x7B33, 0xE298, 0x7B18, 0xE299, 0x7B19, 0xE29A, 0x7B1E, 0xE29B, 0x7B35, 0xE29C, 0x7B28, + 0xE29D, 0x7B36, 0xE29E, 0x7B50, 0xE29F, 0x7B7A, 0xE2A0, 0x7B04, 0xE2A1, 0x7B4D, 0xE2A2, 0x7B0B, 0xE2A3, 0x7B4C, 0xE2A4, 0x7B45, + 0xE2A5, 0x7B75, 0xE2A6, 0x7B65, 0xE2A7, 0x7B74, 0xE2A8, 0x7B67, 0xE2A9, 0x7B70, 0xE2AA, 0x7B71, 0xE2AB, 0x7B6C, 0xE2AC, 0x7B6E, + 0xE2AD, 0x7B9D, 0xE2AE, 0x7B98, 0xE2AF, 0x7B9F, 0xE2B0, 0x7B8D, 0xE2B1, 0x7B9C, 0xE2B2, 0x7B9A, 0xE2B3, 0x7B8B, 0xE2B4, 0x7B92, + 0xE2B5, 0x7B8F, 0xE2B6, 0x7B5D, 0xE2B7, 0x7B99, 0xE2B8, 0x7BCB, 0xE2B9, 0x7BC1, 0xE2BA, 0x7BCC, 0xE2BB, 0x7BCF, 0xE2BC, 0x7BB4, + 0xE2BD, 0x7BC6, 0xE2BE, 0x7BDD, 0xE2BF, 0x7BE9, 0xE2C0, 0x7C11, 0xE2C1, 0x7C14, 0xE2C2, 0x7BE6, 0xE2C3, 0x7BE5, 0xE2C4, 0x7C60, + 0xE2C5, 0x7C00, 0xE2C6, 0x7C07, 0xE2C7, 0x7C13, 0xE2C8, 0x7BF3, 0xE2C9, 0x7BF7, 0xE2CA, 0x7C17, 0xE2CB, 0x7C0D, 0xE2CC, 0x7BF6, + 0xE2CD, 0x7C23, 0xE2CE, 0x7C27, 0xE2CF, 0x7C2A, 0xE2D0, 0x7C1F, 0xE2D1, 0x7C37, 0xE2D2, 0x7C2B, 0xE2D3, 0x7C3D, 0xE2D4, 0x7C4C, + 0xE2D5, 0x7C43, 0xE2D6, 0x7C54, 0xE2D7, 0x7C4F, 0xE2D8, 0x7C40, 0xE2D9, 0x7C50, 0xE2DA, 0x7C58, 0xE2DB, 0x7C5F, 0xE2DC, 0x7C64, + 0xE2DD, 0x7C56, 0xE2DE, 0x7C65, 0xE2DF, 0x7C6C, 0xE2E0, 0x7C75, 0xE2E1, 0x7C83, 0xE2E2, 0x7C90, 0xE2E3, 0x7CA4, 0xE2E4, 0x7CAD, + 0xE2E5, 0x7CA2, 0xE2E6, 0x7CAB, 0xE2E7, 0x7CA1, 0xE2E8, 0x7CA8, 0xE2E9, 0x7CB3, 0xE2EA, 0x7CB2, 0xE2EB, 0x7CB1, 0xE2EC, 0x7CAE, + 0xE2ED, 0x7CB9, 0xE2EE, 0x7CBD, 0xE2EF, 0x7CC0, 0xE2F0, 0x7CC5, 0xE2F1, 0x7CC2, 0xE2F2, 0x7CD8, 0xE2F3, 0x7CD2, 0xE2F4, 0x7CDC, + 0xE2F5, 0x7CE2, 0xE2F6, 0x9B3B, 0xE2F7, 0x7CEF, 0xE2F8, 0x7CF2, 0xE2F9, 0x7CF4, 0xE2FA, 0x7CF6, 0xE2FB, 0x7CFA, 0xE2FC, 0x7D06, + 0xE340, 0x7D02, 0xE341, 0x7D1C, 0xE342, 0x7D15, 0xE343, 0x7D0A, 0xE344, 0x7D45, 0xE345, 0x7D4B, 0xE346, 0x7D2E, 0xE347, 0x7D32, + 0xE348, 0x7D3F, 0xE349, 0x7D35, 0xE34A, 0x7D46, 0xE34B, 0x7D73, 0xE34C, 0x7D56, 0xE34D, 0x7D4E, 0xE34E, 0x7D72, 0xE34F, 0x7D68, + 0xE350, 0x7D6E, 0xE351, 0x7D4F, 0xE352, 0x7D63, 0xE353, 0x7D93, 0xE354, 0x7D89, 0xE355, 0x7D5B, 0xE356, 0x7D8F, 0xE357, 0x7D7D, + 0xE358, 0x7D9B, 0xE359, 0x7DBA, 0xE35A, 0x7DAE, 0xE35B, 0x7DA3, 0xE35C, 0x7DB5, 0xE35D, 0x7DC7, 0xE35E, 0x7DBD, 0xE35F, 0x7DAB, + 0xE360, 0x7E3D, 0xE361, 0x7DA2, 0xE362, 0x7DAF, 0xE363, 0x7DDC, 0xE364, 0x7DB8, 0xE365, 0x7D9F, 0xE366, 0x7DB0, 0xE367, 0x7DD8, + 0xE368, 0x7DDD, 0xE369, 0x7DE4, 0xE36A, 0x7DDE, 0xE36B, 0x7DFB, 0xE36C, 0x7DF2, 0xE36D, 0x7DE1, 0xE36E, 0x7E05, 0xE36F, 0x7E0A, + 0xE370, 0x7E23, 0xE371, 0x7E21, 0xE372, 0x7E12, 0xE373, 0x7E31, 0xE374, 0x7E1F, 0xE375, 0x7E09, 0xE376, 0x7E0B, 0xE377, 0x7E22, + 0xE378, 0x7E46, 0xE379, 0x7E66, 0xE37A, 0x7E3B, 0xE37B, 0x7E35, 0xE37C, 0x7E39, 0xE37D, 0x7E43, 0xE37E, 0x7E37, 0xE380, 0x7E32, + 0xE381, 0x7E3A, 0xE382, 0x7E67, 0xE383, 0x7E5D, 0xE384, 0x7E56, 0xE385, 0x7E5E, 0xE386, 0x7E59, 0xE387, 0x7E5A, 0xE388, 0x7E79, + 0xE389, 0x7E6A, 0xE38A, 0x7E69, 0xE38B, 0x7E7C, 0xE38C, 0x7E7B, 0xE38D, 0x7E83, 0xE38E, 0x7DD5, 0xE38F, 0x7E7D, 0xE390, 0x8FAE, + 0xE391, 0x7E7F, 0xE392, 0x7E88, 0xE393, 0x7E89, 0xE394, 0x7E8C, 0xE395, 0x7E92, 0xE396, 0x7E90, 0xE397, 0x7E93, 0xE398, 0x7E94, + 0xE399, 0x7E96, 0xE39A, 0x7E8E, 0xE39B, 0x7E9B, 0xE39C, 0x7E9C, 0xE39D, 0x7F38, 0xE39E, 0x7F3A, 0xE39F, 0x7F45, 0xE3A0, 0x7F4C, + 0xE3A1, 0x7F4D, 0xE3A2, 0x7F4E, 0xE3A3, 0x7F50, 0xE3A4, 0x7F51, 0xE3A5, 0x7F55, 0xE3A6, 0x7F54, 0xE3A7, 0x7F58, 0xE3A8, 0x7F5F, + 0xE3A9, 0x7F60, 0xE3AA, 0x7F68, 0xE3AB, 0x7F69, 0xE3AC, 0x7F67, 0xE3AD, 0x7F78, 0xE3AE, 0x7F82, 0xE3AF, 0x7F86, 0xE3B0, 0x7F83, + 0xE3B1, 0x7F88, 0xE3B2, 0x7F87, 0xE3B3, 0x7F8C, 0xE3B4, 0x7F94, 0xE3B5, 0x7F9E, 0xE3B6, 0x7F9D, 0xE3B7, 0x7F9A, 0xE3B8, 0x7FA3, + 0xE3B9, 0x7FAF, 0xE3BA, 0x7FB2, 0xE3BB, 0x7FB9, 0xE3BC, 0x7FAE, 0xE3BD, 0x7FB6, 0xE3BE, 0x7FB8, 0xE3BF, 0x8B71, 0xE3C0, 0x7FC5, + 0xE3C1, 0x7FC6, 0xE3C2, 0x7FCA, 0xE3C3, 0x7FD5, 0xE3C4, 0x7FD4, 0xE3C5, 0x7FE1, 0xE3C6, 0x7FE6, 0xE3C7, 0x7FE9, 0xE3C8, 0x7FF3, + 0xE3C9, 0x7FF9, 0xE3CA, 0x98DC, 0xE3CB, 0x8006, 0xE3CC, 0x8004, 0xE3CD, 0x800B, 0xE3CE, 0x8012, 0xE3CF, 0x8018, 0xE3D0, 0x8019, + 0xE3D1, 0x801C, 0xE3D2, 0x8021, 0xE3D3, 0x8028, 0xE3D4, 0x803F, 0xE3D5, 0x803B, 0xE3D6, 0x804A, 0xE3D7, 0x8046, 0xE3D8, 0x8052, + 0xE3D9, 0x8058, 0xE3DA, 0x805A, 0xE3DB, 0x805F, 0xE3DC, 0x8062, 0xE3DD, 0x8068, 0xE3DE, 0x8073, 0xE3DF, 0x8072, 0xE3E0, 0x8070, + 0xE3E1, 0x8076, 0xE3E2, 0x8079, 0xE3E3, 0x807D, 0xE3E4, 0x807F, 0xE3E5, 0x8084, 0xE3E6, 0x8086, 0xE3E7, 0x8085, 0xE3E8, 0x809B, + 0xE3E9, 0x8093, 0xE3EA, 0x809A, 0xE3EB, 0x80AD, 0xE3EC, 0x5190, 0xE3ED, 0x80AC, 0xE3EE, 0x80DB, 0xE3EF, 0x80E5, 0xE3F0, 0x80D9, + 0xE3F1, 0x80DD, 0xE3F2, 0x80C4, 0xE3F3, 0x80DA, 0xE3F4, 0x80D6, 0xE3F5, 0x8109, 0xE3F6, 0x80EF, 0xE3F7, 0x80F1, 0xE3F8, 0x811B, + 0xE3F9, 0x8129, 0xE3FA, 0x8123, 0xE3FB, 0x812F, 0xE3FC, 0x814B, 0xE440, 0x968B, 0xE441, 0x8146, 0xE442, 0x813E, 0xE443, 0x8153, + 0xE444, 0x8151, 0xE445, 0x80FC, 0xE446, 0x8171, 0xE447, 0x816E, 0xE448, 0x8165, 0xE449, 0x8166, 0xE44A, 0x8174, 0xE44B, 0x8183, + 0xE44C, 0x8188, 0xE44D, 0x818A, 0xE44E, 0x8180, 0xE44F, 0x8182, 0xE450, 0x81A0, 0xE451, 0x8195, 0xE452, 0x81A4, 0xE453, 0x81A3, + 0xE454, 0x815F, 0xE455, 0x8193, 0xE456, 0x81A9, 0xE457, 0x81B0, 0xE458, 0x81B5, 0xE459, 0x81BE, 0xE45A, 0x81B8, 0xE45B, 0x81BD, + 0xE45C, 0x81C0, 0xE45D, 0x81C2, 0xE45E, 0x81BA, 0xE45F, 0x81C9, 0xE460, 0x81CD, 0xE461, 0x81D1, 0xE462, 0x81D9, 0xE463, 0x81D8, + 0xE464, 0x81C8, 0xE465, 0x81DA, 0xE466, 0x81DF, 0xE467, 0x81E0, 0xE468, 0x81E7, 0xE469, 0x81FA, 0xE46A, 0x81FB, 0xE46B, 0x81FE, + 0xE46C, 0x8201, 0xE46D, 0x8202, 0xE46E, 0x8205, 0xE46F, 0x8207, 0xE470, 0x820A, 0xE471, 0x820D, 0xE472, 0x8210, 0xE473, 0x8216, + 0xE474, 0x8229, 0xE475, 0x822B, 0xE476, 0x8238, 0xE477, 0x8233, 0xE478, 0x8240, 0xE479, 0x8259, 0xE47A, 0x8258, 0xE47B, 0x825D, + 0xE47C, 0x825A, 0xE47D, 0x825F, 0xE47E, 0x8264, 0xE480, 0x8262, 0xE481, 0x8268, 0xE482, 0x826A, 0xE483, 0x826B, 0xE484, 0x822E, + 0xE485, 0x8271, 0xE486, 0x8277, 0xE487, 0x8278, 0xE488, 0x827E, 0xE489, 0x828D, 0xE48A, 0x8292, 0xE48B, 0x82AB, 0xE48C, 0x829F, + 0xE48D, 0x82BB, 0xE48E, 0x82AC, 0xE48F, 0x82E1, 0xE490, 0x82E3, 0xE491, 0x82DF, 0xE492, 0x82D2, 0xE493, 0x82F4, 0xE494, 0x82F3, + 0xE495, 0x82FA, 0xE496, 0x8393, 0xE497, 0x8303, 0xE498, 0x82FB, 0xE499, 0x82F9, 0xE49A, 0x82DE, 0xE49B, 0x8306, 0xE49C, 0x82DC, + 0xE49D, 0x8309, 0xE49E, 0x82D9, 0xE49F, 0x8335, 0xE4A0, 0x8334, 0xE4A1, 0x8316, 0xE4A2, 0x8332, 0xE4A3, 0x8331, 0xE4A4, 0x8340, + 0xE4A5, 0x8339, 0xE4A6, 0x8350, 0xE4A7, 0x8345, 0xE4A8, 0x832F, 0xE4A9, 0x832B, 0xE4AA, 0x8317, 0xE4AB, 0x8318, 0xE4AC, 0x8385, + 0xE4AD, 0x839A, 0xE4AE, 0x83AA, 0xE4AF, 0x839F, 0xE4B0, 0x83A2, 0xE4B1, 0x8396, 0xE4B2, 0x8323, 0xE4B3, 0x838E, 0xE4B4, 0x8387, + 0xE4B5, 0x838A, 0xE4B6, 0x837C, 0xE4B7, 0x83B5, 0xE4B8, 0x8373, 0xE4B9, 0x8375, 0xE4BA, 0x83A0, 0xE4BB, 0x8389, 0xE4BC, 0x83A8, + 0xE4BD, 0x83F4, 0xE4BE, 0x8413, 0xE4BF, 0x83EB, 0xE4C0, 0x83CE, 0xE4C1, 0x83FD, 0xE4C2, 0x8403, 0xE4C3, 0x83D8, 0xE4C4, 0x840B, + 0xE4C5, 0x83C1, 0xE4C6, 0x83F7, 0xE4C7, 0x8407, 0xE4C8, 0x83E0, 0xE4C9, 0x83F2, 0xE4CA, 0x840D, 0xE4CB, 0x8422, 0xE4CC, 0x8420, + 0xE4CD, 0x83BD, 0xE4CE, 0x8438, 0xE4CF, 0x8506, 0xE4D0, 0x83FB, 0xE4D1, 0x846D, 0xE4D2, 0x842A, 0xE4D3, 0x843C, 0xE4D4, 0x855A, + 0xE4D5, 0x8484, 0xE4D6, 0x8477, 0xE4D7, 0x846B, 0xE4D8, 0x84AD, 0xE4D9, 0x846E, 0xE4DA, 0x8482, 0xE4DB, 0x8469, 0xE4DC, 0x8446, + 0xE4DD, 0x842C, 0xE4DE, 0x846F, 0xE4DF, 0x8479, 0xE4E0, 0x8435, 0xE4E1, 0x84CA, 0xE4E2, 0x8462, 0xE4E3, 0x84B9, 0xE4E4, 0x84BF, + 0xE4E5, 0x849F, 0xE4E6, 0x84D9, 0xE4E7, 0x84CD, 0xE4E8, 0x84BB, 0xE4E9, 0x84DA, 0xE4EA, 0x84D0, 0xE4EB, 0x84C1, 0xE4EC, 0x84C6, + 0xE4ED, 0x84D6, 0xE4EE, 0x84A1, 0xE4EF, 0x8521, 0xE4F0, 0x84FF, 0xE4F1, 0x84F4, 0xE4F2, 0x8517, 0xE4F3, 0x8518, 0xE4F4, 0x852C, + 0xE4F5, 0x851F, 0xE4F6, 0x8515, 0xE4F7, 0x8514, 0xE4F8, 0x84FC, 0xE4F9, 0x8540, 0xE4FA, 0x8563, 0xE4FB, 0x8558, 0xE4FC, 0x8548, + 0xE540, 0x8541, 0xE541, 0x8602, 0xE542, 0x854B, 0xE543, 0x8555, 0xE544, 0x8580, 0xE545, 0x85A4, 0xE546, 0x8588, 0xE547, 0x8591, + 0xE548, 0x858A, 0xE549, 0x85A8, 0xE54A, 0x856D, 0xE54B, 0x8594, 0xE54C, 0x859B, 0xE54D, 0x85EA, 0xE54E, 0x8587, 0xE54F, 0x859C, + 0xE550, 0x8577, 0xE551, 0x857E, 0xE552, 0x8590, 0xE553, 0x85C9, 0xE554, 0x85BA, 0xE555, 0x85CF, 0xE556, 0x85B9, 0xE557, 0x85D0, + 0xE558, 0x85D5, 0xE559, 0x85DD, 0xE55A, 0x85E5, 0xE55B, 0x85DC, 0xE55C, 0x85F9, 0xE55D, 0x860A, 0xE55E, 0x8613, 0xE55F, 0x860B, + 0xE560, 0x85FE, 0xE561, 0x85FA, 0xE562, 0x8606, 0xE563, 0x8622, 0xE564, 0x861A, 0xE565, 0x8630, 0xE566, 0x863F, 0xE567, 0x864D, + 0xE568, 0x4E55, 0xE569, 0x8654, 0xE56A, 0x865F, 0xE56B, 0x8667, 0xE56C, 0x8671, 0xE56D, 0x8693, 0xE56E, 0x86A3, 0xE56F, 0x86A9, + 0xE570, 0x86AA, 0xE571, 0x868B, 0xE572, 0x868C, 0xE573, 0x86B6, 0xE574, 0x86AF, 0xE575, 0x86C4, 0xE576, 0x86C6, 0xE577, 0x86B0, + 0xE578, 0x86C9, 0xE579, 0x8823, 0xE57A, 0x86AB, 0xE57B, 0x86D4, 0xE57C, 0x86DE, 0xE57D, 0x86E9, 0xE57E, 0x86EC, 0xE580, 0x86DF, + 0xE581, 0x86DB, 0xE582, 0x86EF, 0xE583, 0x8712, 0xE584, 0x8706, 0xE585, 0x8708, 0xE586, 0x8700, 0xE587, 0x8703, 0xE588, 0x86FB, + 0xE589, 0x8711, 0xE58A, 0x8709, 0xE58B, 0x870D, 0xE58C, 0x86F9, 0xE58D, 0x870A, 0xE58E, 0x8734, 0xE58F, 0x873F, 0xE590, 0x8737, + 0xE591, 0x873B, 0xE592, 0x8725, 0xE593, 0x8729, 0xE594, 0x871A, 0xE595, 0x8760, 0xE596, 0x875F, 0xE597, 0x8778, 0xE598, 0x874C, + 0xE599, 0x874E, 0xE59A, 0x8774, 0xE59B, 0x8757, 0xE59C, 0x8768, 0xE59D, 0x876E, 0xE59E, 0x8759, 0xE59F, 0x8753, 0xE5A0, 0x8763, + 0xE5A1, 0x876A, 0xE5A2, 0x8805, 0xE5A3, 0x87A2, 0xE5A4, 0x879F, 0xE5A5, 0x8782, 0xE5A6, 0x87AF, 0xE5A7, 0x87CB, 0xE5A8, 0x87BD, + 0xE5A9, 0x87C0, 0xE5AA, 0x87D0, 0xE5AB, 0x96D6, 0xE5AC, 0x87AB, 0xE5AD, 0x87C4, 0xE5AE, 0x87B3, 0xE5AF, 0x87C7, 0xE5B0, 0x87C6, + 0xE5B1, 0x87BB, 0xE5B2, 0x87EF, 0xE5B3, 0x87F2, 0xE5B4, 0x87E0, 0xE5B5, 0x880F, 0xE5B6, 0x880D, 0xE5B7, 0x87FE, 0xE5B8, 0x87F6, + 0xE5B9, 0x87F7, 0xE5BA, 0x880E, 0xE5BB, 0x87D2, 0xE5BC, 0x8811, 0xE5BD, 0x8816, 0xE5BE, 0x8815, 0xE5BF, 0x8822, 0xE5C0, 0x8821, + 0xE5C1, 0x8831, 0xE5C2, 0x8836, 0xE5C3, 0x8839, 0xE5C4, 0x8827, 0xE5C5, 0x883B, 0xE5C6, 0x8844, 0xE5C7, 0x8842, 0xE5C8, 0x8852, + 0xE5C9, 0x8859, 0xE5CA, 0x885E, 0xE5CB, 0x8862, 0xE5CC, 0x886B, 0xE5CD, 0x8881, 0xE5CE, 0x887E, 0xE5CF, 0x889E, 0xE5D0, 0x8875, + 0xE5D1, 0x887D, 0xE5D2, 0x88B5, 0xE5D3, 0x8872, 0xE5D4, 0x8882, 0xE5D5, 0x8897, 0xE5D6, 0x8892, 0xE5D7, 0x88AE, 0xE5D8, 0x8899, + 0xE5D9, 0x88A2, 0xE5DA, 0x888D, 0xE5DB, 0x88A4, 0xE5DC, 0x88B0, 0xE5DD, 0x88BF, 0xE5DE, 0x88B1, 0xE5DF, 0x88C3, 0xE5E0, 0x88C4, + 0xE5E1, 0x88D4, 0xE5E2, 0x88D8, 0xE5E3, 0x88D9, 0xE5E4, 0x88DD, 0xE5E5, 0x88F9, 0xE5E6, 0x8902, 0xE5E7, 0x88FC, 0xE5E8, 0x88F4, + 0xE5E9, 0x88E8, 0xE5EA, 0x88F2, 0xE5EB, 0x8904, 0xE5EC, 0x890C, 0xE5ED, 0x890A, 0xE5EE, 0x8913, 0xE5EF, 0x8943, 0xE5F0, 0x891E, + 0xE5F1, 0x8925, 0xE5F2, 0x892A, 0xE5F3, 0x892B, 0xE5F4, 0x8941, 0xE5F5, 0x8944, 0xE5F6, 0x893B, 0xE5F7, 0x8936, 0xE5F8, 0x8938, + 0xE5F9, 0x894C, 0xE5FA, 0x891D, 0xE5FB, 0x8960, 0xE5FC, 0x895E, 0xE640, 0x8966, 0xE641, 0x8964, 0xE642, 0x896D, 0xE643, 0x896A, + 0xE644, 0x896F, 0xE645, 0x8974, 0xE646, 0x8977, 0xE647, 0x897E, 0xE648, 0x8983, 0xE649, 0x8988, 0xE64A, 0x898A, 0xE64B, 0x8993, + 0xE64C, 0x8998, 0xE64D, 0x89A1, 0xE64E, 0x89A9, 0xE64F, 0x89A6, 0xE650, 0x89AC, 0xE651, 0x89AF, 0xE652, 0x89B2, 0xE653, 0x89BA, + 0xE654, 0x89BD, 0xE655, 0x89BF, 0xE656, 0x89C0, 0xE657, 0x89DA, 0xE658, 0x89DC, 0xE659, 0x89DD, 0xE65A, 0x89E7, 0xE65B, 0x89F4, + 0xE65C, 0x89F8, 0xE65D, 0x8A03, 0xE65E, 0x8A16, 0xE65F, 0x8A10, 0xE660, 0x8A0C, 0xE661, 0x8A1B, 0xE662, 0x8A1D, 0xE663, 0x8A25, + 0xE664, 0x8A36, 0xE665, 0x8A41, 0xE666, 0x8A5B, 0xE667, 0x8A52, 0xE668, 0x8A46, 0xE669, 0x8A48, 0xE66A, 0x8A7C, 0xE66B, 0x8A6D, + 0xE66C, 0x8A6C, 0xE66D, 0x8A62, 0xE66E, 0x8A85, 0xE66F, 0x8A82, 0xE670, 0x8A84, 0xE671, 0x8AA8, 0xE672, 0x8AA1, 0xE673, 0x8A91, + 0xE674, 0x8AA5, 0xE675, 0x8AA6, 0xE676, 0x8A9A, 0xE677, 0x8AA3, 0xE678, 0x8AC4, 0xE679, 0x8ACD, 0xE67A, 0x8AC2, 0xE67B, 0x8ADA, + 0xE67C, 0x8AEB, 0xE67D, 0x8AF3, 0xE67E, 0x8AE7, 0xE680, 0x8AE4, 0xE681, 0x8AF1, 0xE682, 0x8B14, 0xE683, 0x8AE0, 0xE684, 0x8AE2, + 0xE685, 0x8AF7, 0xE686, 0x8ADE, 0xE687, 0x8ADB, 0xE688, 0x8B0C, 0xE689, 0x8B07, 0xE68A, 0x8B1A, 0xE68B, 0x8AE1, 0xE68C, 0x8B16, + 0xE68D, 0x8B10, 0xE68E, 0x8B17, 0xE68F, 0x8B20, 0xE690, 0x8B33, 0xE691, 0x97AB, 0xE692, 0x8B26, 0xE693, 0x8B2B, 0xE694, 0x8B3E, + 0xE695, 0x8B28, 0xE696, 0x8B41, 0xE697, 0x8B4C, 0xE698, 0x8B4F, 0xE699, 0x8B4E, 0xE69A, 0x8B49, 0xE69B, 0x8B56, 0xE69C, 0x8B5B, + 0xE69D, 0x8B5A, 0xE69E, 0x8B6B, 0xE69F, 0x8B5F, 0xE6A0, 0x8B6C, 0xE6A1, 0x8B6F, 0xE6A2, 0x8B74, 0xE6A3, 0x8B7D, 0xE6A4, 0x8B80, + 0xE6A5, 0x8B8C, 0xE6A6, 0x8B8E, 0xE6A7, 0x8B92, 0xE6A8, 0x8B93, 0xE6A9, 0x8B96, 0xE6AA, 0x8B99, 0xE6AB, 0x8B9A, 0xE6AC, 0x8C3A, + 0xE6AD, 0x8C41, 0xE6AE, 0x8C3F, 0xE6AF, 0x8C48, 0xE6B0, 0x8C4C, 0xE6B1, 0x8C4E, 0xE6B2, 0x8C50, 0xE6B3, 0x8C55, 0xE6B4, 0x8C62, + 0xE6B5, 0x8C6C, 0xE6B6, 0x8C78, 0xE6B7, 0x8C7A, 0xE6B8, 0x8C82, 0xE6B9, 0x8C89, 0xE6BA, 0x8C85, 0xE6BB, 0x8C8A, 0xE6BC, 0x8C8D, + 0xE6BD, 0x8C8E, 0xE6BE, 0x8C94, 0xE6BF, 0x8C7C, 0xE6C0, 0x8C98, 0xE6C1, 0x621D, 0xE6C2, 0x8CAD, 0xE6C3, 0x8CAA, 0xE6C4, 0x8CBD, + 0xE6C5, 0x8CB2, 0xE6C6, 0x8CB3, 0xE6C7, 0x8CAE, 0xE6C8, 0x8CB6, 0xE6C9, 0x8CC8, 0xE6CA, 0x8CC1, 0xE6CB, 0x8CE4, 0xE6CC, 0x8CE3, + 0xE6CD, 0x8CDA, 0xE6CE, 0x8CFD, 0xE6CF, 0x8CFA, 0xE6D0, 0x8CFB, 0xE6D1, 0x8D04, 0xE6D2, 0x8D05, 0xE6D3, 0x8D0A, 0xE6D4, 0x8D07, + 0xE6D5, 0x8D0F, 0xE6D6, 0x8D0D, 0xE6D7, 0x8D10, 0xE6D8, 0x9F4E, 0xE6D9, 0x8D13, 0xE6DA, 0x8CCD, 0xE6DB, 0x8D14, 0xE6DC, 0x8D16, + 0xE6DD, 0x8D67, 0xE6DE, 0x8D6D, 0xE6DF, 0x8D71, 0xE6E0, 0x8D73, 0xE6E1, 0x8D81, 0xE6E2, 0x8D99, 0xE6E3, 0x8DC2, 0xE6E4, 0x8DBE, + 0xE6E5, 0x8DBA, 0xE6E6, 0x8DCF, 0xE6E7, 0x8DDA, 0xE6E8, 0x8DD6, 0xE6E9, 0x8DCC, 0xE6EA, 0x8DDB, 0xE6EB, 0x8DCB, 0xE6EC, 0x8DEA, + 0xE6ED, 0x8DEB, 0xE6EE, 0x8DDF, 0xE6EF, 0x8DE3, 0xE6F0, 0x8DFC, 0xE6F1, 0x8E08, 0xE6F2, 0x8E09, 0xE6F3, 0x8DFF, 0xE6F4, 0x8E1D, + 0xE6F5, 0x8E1E, 0xE6F6, 0x8E10, 0xE6F7, 0x8E1F, 0xE6F8, 0x8E42, 0xE6F9, 0x8E35, 0xE6FA, 0x8E30, 0xE6FB, 0x8E34, 0xE6FC, 0x8E4A, + 0xE740, 0x8E47, 0xE741, 0x8E49, 0xE742, 0x8E4C, 0xE743, 0x8E50, 0xE744, 0x8E48, 0xE745, 0x8E59, 0xE746, 0x8E64, 0xE747, 0x8E60, + 0xE748, 0x8E2A, 0xE749, 0x8E63, 0xE74A, 0x8E55, 0xE74B, 0x8E76, 0xE74C, 0x8E72, 0xE74D, 0x8E7C, 0xE74E, 0x8E81, 0xE74F, 0x8E87, + 0xE750, 0x8E85, 0xE751, 0x8E84, 0xE752, 0x8E8B, 0xE753, 0x8E8A, 0xE754, 0x8E93, 0xE755, 0x8E91, 0xE756, 0x8E94, 0xE757, 0x8E99, + 0xE758, 0x8EAA, 0xE759, 0x8EA1, 0xE75A, 0x8EAC, 0xE75B, 0x8EB0, 0xE75C, 0x8EC6, 0xE75D, 0x8EB1, 0xE75E, 0x8EBE, 0xE75F, 0x8EC5, + 0xE760, 0x8EC8, 0xE761, 0x8ECB, 0xE762, 0x8EDB, 0xE763, 0x8EE3, 0xE764, 0x8EFC, 0xE765, 0x8EFB, 0xE766, 0x8EEB, 0xE767, 0x8EFE, + 0xE768, 0x8F0A, 0xE769, 0x8F05, 0xE76A, 0x8F15, 0xE76B, 0x8F12, 0xE76C, 0x8F19, 0xE76D, 0x8F13, 0xE76E, 0x8F1C, 0xE76F, 0x8F1F, + 0xE770, 0x8F1B, 0xE771, 0x8F0C, 0xE772, 0x8F26, 0xE773, 0x8F33, 0xE774, 0x8F3B, 0xE775, 0x8F39, 0xE776, 0x8F45, 0xE777, 0x8F42, + 0xE778, 0x8F3E, 0xE779, 0x8F4C, 0xE77A, 0x8F49, 0xE77B, 0x8F46, 0xE77C, 0x8F4E, 0xE77D, 0x8F57, 0xE77E, 0x8F5C, 0xE780, 0x8F62, + 0xE781, 0x8F63, 0xE782, 0x8F64, 0xE783, 0x8F9C, 0xE784, 0x8F9F, 0xE785, 0x8FA3, 0xE786, 0x8FAD, 0xE787, 0x8FAF, 0xE788, 0x8FB7, + 0xE789, 0x8FDA, 0xE78A, 0x8FE5, 0xE78B, 0x8FE2, 0xE78C, 0x8FEA, 0xE78D, 0x8FEF, 0xE78E, 0x9087, 0xE78F, 0x8FF4, 0xE790, 0x9005, + 0xE791, 0x8FF9, 0xE792, 0x8FFA, 0xE793, 0x9011, 0xE794, 0x9015, 0xE795, 0x9021, 0xE796, 0x900D, 0xE797, 0x901E, 0xE798, 0x9016, + 0xE799, 0x900B, 0xE79A, 0x9027, 0xE79B, 0x9036, 0xE79C, 0x9035, 0xE79D, 0x9039, 0xE79E, 0x8FF8, 0xE79F, 0x904F, 0xE7A0, 0x9050, + 0xE7A1, 0x9051, 0xE7A2, 0x9052, 0xE7A3, 0x900E, 0xE7A4, 0x9049, 0xE7A5, 0x903E, 0xE7A6, 0x9056, 0xE7A7, 0x9058, 0xE7A8, 0x905E, + 0xE7A9, 0x9068, 0xE7AA, 0x906F, 0xE7AB, 0x9076, 0xE7AC, 0x96A8, 0xE7AD, 0x9072, 0xE7AE, 0x9082, 0xE7AF, 0x907D, 0xE7B0, 0x9081, + 0xE7B1, 0x9080, 0xE7B2, 0x908A, 0xE7B3, 0x9089, 0xE7B4, 0x908F, 0xE7B5, 0x90A8, 0xE7B6, 0x90AF, 0xE7B7, 0x90B1, 0xE7B8, 0x90B5, + 0xE7B9, 0x90E2, 0xE7BA, 0x90E4, 0xE7BB, 0x6248, 0xE7BC, 0x90DB, 0xE7BD, 0x9102, 0xE7BE, 0x9112, 0xE7BF, 0x9119, 0xE7C0, 0x9132, + 0xE7C1, 0x9130, 0xE7C2, 0x914A, 0xE7C3, 0x9156, 0xE7C4, 0x9158, 0xE7C5, 0x9163, 0xE7C6, 0x9165, 0xE7C7, 0x9169, 0xE7C8, 0x9173, + 0xE7C9, 0x9172, 0xE7CA, 0x918B, 0xE7CB, 0x9189, 0xE7CC, 0x9182, 0xE7CD, 0x91A2, 0xE7CE, 0x91AB, 0xE7CF, 0x91AF, 0xE7D0, 0x91AA, + 0xE7D1, 0x91B5, 0xE7D2, 0x91B4, 0xE7D3, 0x91BA, 0xE7D4, 0x91C0, 0xE7D5, 0x91C1, 0xE7D6, 0x91C9, 0xE7D7, 0x91CB, 0xE7D8, 0x91D0, + 0xE7D9, 0x91D6, 0xE7DA, 0x91DF, 0xE7DB, 0x91E1, 0xE7DC, 0x91DB, 0xE7DD, 0x91FC, 0xE7DE, 0x91F5, 0xE7DF, 0x91F6, 0xE7E0, 0x921E, + 0xE7E1, 0x91FF, 0xE7E2, 0x9214, 0xE7E3, 0x922C, 0xE7E4, 0x9215, 0xE7E5, 0x9211, 0xE7E6, 0x925E, 0xE7E7, 0x9257, 0xE7E8, 0x9245, + 0xE7E9, 0x9249, 0xE7EA, 0x9264, 0xE7EB, 0x9248, 0xE7EC, 0x9295, 0xE7ED, 0x923F, 0xE7EE, 0x924B, 0xE7EF, 0x9250, 0xE7F0, 0x929C, + 0xE7F1, 0x9296, 0xE7F2, 0x9293, 0xE7F3, 0x929B, 0xE7F4, 0x925A, 0xE7F5, 0x92CF, 0xE7F6, 0x92B9, 0xE7F7, 0x92B7, 0xE7F8, 0x92E9, + 0xE7F9, 0x930F, 0xE7FA, 0x92FA, 0xE7FB, 0x9344, 0xE7FC, 0x932E, 0xE840, 0x9319, 0xE841, 0x9322, 0xE842, 0x931A, 0xE843, 0x9323, + 0xE844, 0x933A, 0xE845, 0x9335, 0xE846, 0x933B, 0xE847, 0x935C, 0xE848, 0x9360, 0xE849, 0x937C, 0xE84A, 0x936E, 0xE84B, 0x9356, + 0xE84C, 0x93B0, 0xE84D, 0x93AC, 0xE84E, 0x93AD, 0xE84F, 0x9394, 0xE850, 0x93B9, 0xE851, 0x93D6, 0xE852, 0x93D7, 0xE853, 0x93E8, + 0xE854, 0x93E5, 0xE855, 0x93D8, 0xE856, 0x93C3, 0xE857, 0x93DD, 0xE858, 0x93D0, 0xE859, 0x93C8, 0xE85A, 0x93E4, 0xE85B, 0x941A, + 0xE85C, 0x9414, 0xE85D, 0x9413, 0xE85E, 0x9403, 0xE85F, 0x9407, 0xE860, 0x9410, 0xE861, 0x9436, 0xE862, 0x942B, 0xE863, 0x9435, + 0xE864, 0x9421, 0xE865, 0x943A, 0xE866, 0x9441, 0xE867, 0x9452, 0xE868, 0x9444, 0xE869, 0x945B, 0xE86A, 0x9460, 0xE86B, 0x9462, + 0xE86C, 0x945E, 0xE86D, 0x946A, 0xE86E, 0x9229, 0xE86F, 0x9470, 0xE870, 0x9475, 0xE871, 0x9477, 0xE872, 0x947D, 0xE873, 0x945A, + 0xE874, 0x947C, 0xE875, 0x947E, 0xE876, 0x9481, 0xE877, 0x947F, 0xE878, 0x9582, 0xE879, 0x9587, 0xE87A, 0x958A, 0xE87B, 0x9594, + 0xE87C, 0x9596, 0xE87D, 0x9598, 0xE87E, 0x9599, 0xE880, 0x95A0, 0xE881, 0x95A8, 0xE882, 0x95A7, 0xE883, 0x95AD, 0xE884, 0x95BC, + 0xE885, 0x95BB, 0xE886, 0x95B9, 0xE887, 0x95BE, 0xE888, 0x95CA, 0xE889, 0x6FF6, 0xE88A, 0x95C3, 0xE88B, 0x95CD, 0xE88C, 0x95CC, + 0xE88D, 0x95D5, 0xE88E, 0x95D4, 0xE88F, 0x95D6, 0xE890, 0x95DC, 0xE891, 0x95E1, 0xE892, 0x95E5, 0xE893, 0x95E2, 0xE894, 0x9621, + 0xE895, 0x9628, 0xE896, 0x962E, 0xE897, 0x962F, 0xE898, 0x9642, 0xE899, 0x964C, 0xE89A, 0x964F, 0xE89B, 0x964B, 0xE89C, 0x9677, + 0xE89D, 0x965C, 0xE89E, 0x965E, 0xE89F, 0x965D, 0xE8A0, 0x965F, 0xE8A1, 0x9666, 0xE8A2, 0x9672, 0xE8A3, 0x966C, 0xE8A4, 0x968D, + 0xE8A5, 0x9698, 0xE8A6, 0x9695, 0xE8A7, 0x9697, 0xE8A8, 0x96AA, 0xE8A9, 0x96A7, 0xE8AA, 0x96B1, 0xE8AB, 0x96B2, 0xE8AC, 0x96B0, + 0xE8AD, 0x96B4, 0xE8AE, 0x96B6, 0xE8AF, 0x96B8, 0xE8B0, 0x96B9, 0xE8B1, 0x96CE, 0xE8B2, 0x96CB, 0xE8B3, 0x96C9, 0xE8B4, 0x96CD, + 0xE8B5, 0x894D, 0xE8B6, 0x96DC, 0xE8B7, 0x970D, 0xE8B8, 0x96D5, 0xE8B9, 0x96F9, 0xE8BA, 0x9704, 0xE8BB, 0x9706, 0xE8BC, 0x9708, + 0xE8BD, 0x9713, 0xE8BE, 0x970E, 0xE8BF, 0x9711, 0xE8C0, 0x970F, 0xE8C1, 0x9716, 0xE8C2, 0x9719, 0xE8C3, 0x9724, 0xE8C4, 0x972A, + 0xE8C5, 0x9730, 0xE8C6, 0x9739, 0xE8C7, 0x973D, 0xE8C8, 0x973E, 0xE8C9, 0x9744, 0xE8CA, 0x9746, 0xE8CB, 0x9748, 0xE8CC, 0x9742, + 0xE8CD, 0x9749, 0xE8CE, 0x975C, 0xE8CF, 0x9760, 0xE8D0, 0x9764, 0xE8D1, 0x9766, 0xE8D2, 0x9768, 0xE8D3, 0x52D2, 0xE8D4, 0x976B, + 0xE8D5, 0x9771, 0xE8D6, 0x9779, 0xE8D7, 0x9785, 0xE8D8, 0x977C, 0xE8D9, 0x9781, 0xE8DA, 0x977A, 0xE8DB, 0x9786, 0xE8DC, 0x978B, + 0xE8DD, 0x978F, 0xE8DE, 0x9790, 0xE8DF, 0x979C, 0xE8E0, 0x97A8, 0xE8E1, 0x97A6, 0xE8E2, 0x97A3, 0xE8E3, 0x97B3, 0xE8E4, 0x97B4, + 0xE8E5, 0x97C3, 0xE8E6, 0x97C6, 0xE8E7, 0x97C8, 0xE8E8, 0x97CB, 0xE8E9, 0x97DC, 0xE8EA, 0x97ED, 0xE8EB, 0x9F4F, 0xE8EC, 0x97F2, + 0xE8ED, 0x7ADF, 0xE8EE, 0x97F6, 0xE8EF, 0x97F5, 0xE8F0, 0x980F, 0xE8F1, 0x980C, 0xE8F2, 0x9838, 0xE8F3, 0x9824, 0xE8F4, 0x9821, + 0xE8F5, 0x9837, 0xE8F6, 0x983D, 0xE8F7, 0x9846, 0xE8F8, 0x984F, 0xE8F9, 0x984B, 0xE8FA, 0x986B, 0xE8FB, 0x986F, 0xE8FC, 0x9870, + 0xE940, 0x9871, 0xE941, 0x9874, 0xE942, 0x9873, 0xE943, 0x98AA, 0xE944, 0x98AF, 0xE945, 0x98B1, 0xE946, 0x98B6, 0xE947, 0x98C4, + 0xE948, 0x98C3, 0xE949, 0x98C6, 0xE94A, 0x98E9, 0xE94B, 0x98EB, 0xE94C, 0x9903, 0xE94D, 0x9909, 0xE94E, 0x9912, 0xE94F, 0x9914, + 0xE950, 0x9918, 0xE951, 0x9921, 0xE952, 0x991D, 0xE953, 0x991E, 0xE954, 0x9924, 0xE955, 0x9920, 0xE956, 0x992C, 0xE957, 0x992E, + 0xE958, 0x993D, 0xE959, 0x993E, 0xE95A, 0x9942, 0xE95B, 0x9949, 0xE95C, 0x9945, 0xE95D, 0x9950, 0xE95E, 0x994B, 0xE95F, 0x9951, + 0xE960, 0x9952, 0xE961, 0x994C, 0xE962, 0x9955, 0xE963, 0x9997, 0xE964, 0x9998, 0xE965, 0x99A5, 0xE966, 0x99AD, 0xE967, 0x99AE, + 0xE968, 0x99BC, 0xE969, 0x99DF, 0xE96A, 0x99DB, 0xE96B, 0x99DD, 0xE96C, 0x99D8, 0xE96D, 0x99D1, 0xE96E, 0x99ED, 0xE96F, 0x99EE, + 0xE970, 0x99F1, 0xE971, 0x99F2, 0xE972, 0x99FB, 0xE973, 0x99F8, 0xE974, 0x9A01, 0xE975, 0x9A0F, 0xE976, 0x9A05, 0xE977, 0x99E2, + 0xE978, 0x9A19, 0xE979, 0x9A2B, 0xE97A, 0x9A37, 0xE97B, 0x9A45, 0xE97C, 0x9A42, 0xE97D, 0x9A40, 0xE97E, 0x9A43, 0xE980, 0x9A3E, + 0xE981, 0x9A55, 0xE982, 0x9A4D, 0xE983, 0x9A5B, 0xE984, 0x9A57, 0xE985, 0x9A5F, 0xE986, 0x9A62, 0xE987, 0x9A65, 0xE988, 0x9A64, + 0xE989, 0x9A69, 0xE98A, 0x9A6B, 0xE98B, 0x9A6A, 0xE98C, 0x9AAD, 0xE98D, 0x9AB0, 0xE98E, 0x9ABC, 0xE98F, 0x9AC0, 0xE990, 0x9ACF, + 0xE991, 0x9AD1, 0xE992, 0x9AD3, 0xE993, 0x9AD4, 0xE994, 0x9ADE, 0xE995, 0x9ADF, 0xE996, 0x9AE2, 0xE997, 0x9AE3, 0xE998, 0x9AE6, + 0xE999, 0x9AEF, 0xE99A, 0x9AEB, 0xE99B, 0x9AEE, 0xE99C, 0x9AF4, 0xE99D, 0x9AF1, 0xE99E, 0x9AF7, 0xE99F, 0x9AFB, 0xE9A0, 0x9B06, + 0xE9A1, 0x9B18, 0xE9A2, 0x9B1A, 0xE9A3, 0x9B1F, 0xE9A4, 0x9B22, 0xE9A5, 0x9B23, 0xE9A6, 0x9B25, 0xE9A7, 0x9B27, 0xE9A8, 0x9B28, + 0xE9A9, 0x9B29, 0xE9AA, 0x9B2A, 0xE9AB, 0x9B2E, 0xE9AC, 0x9B2F, 0xE9AD, 0x9B32, 0xE9AE, 0x9B44, 0xE9AF, 0x9B43, 0xE9B0, 0x9B4F, + 0xE9B1, 0x9B4D, 0xE9B2, 0x9B4E, 0xE9B3, 0x9B51, 0xE9B4, 0x9B58, 0xE9B5, 0x9B74, 0xE9B6, 0x9B93, 0xE9B7, 0x9B83, 0xE9B8, 0x9B91, + 0xE9B9, 0x9B96, 0xE9BA, 0x9B97, 0xE9BB, 0x9B9F, 0xE9BC, 0x9BA0, 0xE9BD, 0x9BA8, 0xE9BE, 0x9BB4, 0xE9BF, 0x9BC0, 0xE9C0, 0x9BCA, + 0xE9C1, 0x9BB9, 0xE9C2, 0x9BC6, 0xE9C3, 0x9BCF, 0xE9C4, 0x9BD1, 0xE9C5, 0x9BD2, 0xE9C6, 0x9BE3, 0xE9C7, 0x9BE2, 0xE9C8, 0x9BE4, + 0xE9C9, 0x9BD4, 0xE9CA, 0x9BE1, 0xE9CB, 0x9C3A, 0xE9CC, 0x9BF2, 0xE9CD, 0x9BF1, 0xE9CE, 0x9BF0, 0xE9CF, 0x9C15, 0xE9D0, 0x9C14, + 0xE9D1, 0x9C09, 0xE9D2, 0x9C13, 0xE9D3, 0x9C0C, 0xE9D4, 0x9C06, 0xE9D5, 0x9C08, 0xE9D6, 0x9C12, 0xE9D7, 0x9C0A, 0xE9D8, 0x9C04, + 0xE9D9, 0x9C2E, 0xE9DA, 0x9C1B, 0xE9DB, 0x9C25, 0xE9DC, 0x9C24, 0xE9DD, 0x9C21, 0xE9DE, 0x9C30, 0xE9DF, 0x9C47, 0xE9E0, 0x9C32, + 0xE9E1, 0x9C46, 0xE9E2, 0x9C3E, 0xE9E3, 0x9C5A, 0xE9E4, 0x9C60, 0xE9E5, 0x9C67, 0xE9E6, 0x9C76, 0xE9E7, 0x9C78, 0xE9E8, 0x9CE7, + 0xE9E9, 0x9CEC, 0xE9EA, 0x9CF0, 0xE9EB, 0x9D09, 0xE9EC, 0x9D08, 0xE9ED, 0x9CEB, 0xE9EE, 0x9D03, 0xE9EF, 0x9D06, 0xE9F0, 0x9D2A, + 0xE9F1, 0x9D26, 0xE9F2, 0x9DAF, 0xE9F3, 0x9D23, 0xE9F4, 0x9D1F, 0xE9F5, 0x9D44, 0xE9F6, 0x9D15, 0xE9F7, 0x9D12, 0xE9F8, 0x9D41, + 0xE9F9, 0x9D3F, 0xE9FA, 0x9D3E, 0xE9FB, 0x9D46, 0xE9FC, 0x9D48, 0xEA40, 0x9D5D, 0xEA41, 0x9D5E, 0xEA42, 0x9D64, 0xEA43, 0x9D51, + 0xEA44, 0x9D50, 0xEA45, 0x9D59, 0xEA46, 0x9D72, 0xEA47, 0x9D89, 0xEA48, 0x9D87, 0xEA49, 0x9DAB, 0xEA4A, 0x9D6F, 0xEA4B, 0x9D7A, + 0xEA4C, 0x9D9A, 0xEA4D, 0x9DA4, 0xEA4E, 0x9DA9, 0xEA4F, 0x9DB2, 0xEA50, 0x9DC4, 0xEA51, 0x9DC1, 0xEA52, 0x9DBB, 0xEA53, 0x9DB8, + 0xEA54, 0x9DBA, 0xEA55, 0x9DC6, 0xEA56, 0x9DCF, 0xEA57, 0x9DC2, 0xEA58, 0x9DD9, 0xEA59, 0x9DD3, 0xEA5A, 0x9DF8, 0xEA5B, 0x9DE6, + 0xEA5C, 0x9DED, 0xEA5D, 0x9DEF, 0xEA5E, 0x9DFD, 0xEA5F, 0x9E1A, 0xEA60, 0x9E1B, 0xEA61, 0x9E1E, 0xEA62, 0x9E75, 0xEA63, 0x9E79, + 0xEA64, 0x9E7D, 0xEA65, 0x9E81, 0xEA66, 0x9E88, 0xEA67, 0x9E8B, 0xEA68, 0x9E8C, 0xEA69, 0x9E92, 0xEA6A, 0x9E95, 0xEA6B, 0x9E91, + 0xEA6C, 0x9E9D, 0xEA6D, 0x9EA5, 0xEA6E, 0x9EA9, 0xEA6F, 0x9EB8, 0xEA70, 0x9EAA, 0xEA71, 0x9EAD, 0xEA72, 0x9761, 0xEA73, 0x9ECC, + 0xEA74, 0x9ECE, 0xEA75, 0x9ECF, 0xEA76, 0x9ED0, 0xEA77, 0x9ED4, 0xEA78, 0x9EDC, 0xEA79, 0x9EDE, 0xEA7A, 0x9EDD, 0xEA7B, 0x9EE0, + 0xEA7C, 0x9EE5, 0xEA7D, 0x9EE8, 0xEA7E, 0x9EEF, 0xEA80, 0x9EF4, 0xEA81, 0x9EF6, 0xEA82, 0x9EF7, 0xEA83, 0x9EF9, 0xEA84, 0x9EFB, + 0xEA85, 0x9EFC, 0xEA86, 0x9EFD, 0xEA87, 0x9F07, 0xEA88, 0x9F08, 0xEA89, 0x76B7, 0xEA8A, 0x9F15, 0xEA8B, 0x9F21, 0xEA8C, 0x9F2C, + 0xEA8D, 0x9F3E, 0xEA8E, 0x9F4A, 0xEA8F, 0x9F52, 0xEA90, 0x9F54, 0xEA91, 0x9F63, 0xEA92, 0x9F5F, 0xEA93, 0x9F60, 0xEA94, 0x9F61, + 0xEA95, 0x9F66, 0xEA96, 0x9F67, 0xEA97, 0x9F6C, 0xEA98, 0x9F6A, 0xEA99, 0x9F77, 0xEA9A, 0x9F72, 0xEA9B, 0x9F76, 0xEA9C, 0x9F95, + 0xEA9D, 0x9F9C, 0xEA9E, 0x9FA0, 0xEA9F, 0x582F, 0xEAA0, 0x69C7, 0xEAA1, 0x9059, 0xEAA2, 0x7464, 0xEAA3, 0x51DC, 0xEAA4, 0x7199, + 0xFA40, 0x2170, 0xFA41, 0x2171, 0xFA42, 0x2172, 0xFA43, 0x2173, 0xFA44, 0x2174, 0xFA45, 0x2175, 0xFA46, 0x2176, 0xFA47, 0x2177, + 0xFA48, 0x2178, 0xFA49, 0x2179, 0xFA55, 0xFFE4, 0xFA56, 0xFF07, 0xFA57, 0xFF02, 0xFA5C, 0x7E8A, 0xFA5D, 0x891C, 0xFA5E, 0x9348, + 0xFA5F, 0x9288, 0xFA60, 0x84DC, 0xFA61, 0x4FC9, 0xFA62, 0x70BB, 0xFA63, 0x6631, 0xFA64, 0x68C8, 0xFA65, 0x92F9, 0xFA66, 0x66FB, + 0xFA67, 0x5F45, 0xFA68, 0x4E28, 0xFA69, 0x4EE1, 0xFA6A, 0x4EFC, 0xFA6B, 0x4F00, 0xFA6C, 0x4F03, 0xFA6D, 0x4F39, 0xFA6E, 0x4F56, + 0xFA6F, 0x4F92, 0xFA70, 0x4F8A, 0xFA71, 0x4F9A, 0xFA72, 0x4F94, 0xFA73, 0x4FCD, 0xFA74, 0x5040, 0xFA75, 0x5022, 0xFA76, 0x4FFF, + 0xFA77, 0x501E, 0xFA78, 0x5046, 0xFA79, 0x5070, 0xFA7A, 0x5042, 0xFA7B, 0x5094, 0xFA7C, 0x50F4, 0xFA7D, 0x50D8, 0xFA7E, 0x514A, + 0xFA80, 0x5164, 0xFA81, 0x519D, 0xFA82, 0x51BE, 0xFA83, 0x51EC, 0xFA84, 0x5215, 0xFA85, 0x529C, 0xFA86, 0x52A6, 0xFA87, 0x52C0, + 0xFA88, 0x52DB, 0xFA89, 0x5300, 0xFA8A, 0x5307, 0xFA8B, 0x5324, 0xFA8C, 0x5372, 0xFA8D, 0x5393, 0xFA8E, 0x53B2, 0xFA8F, 0x53DD, + 0xFA90, 0xFA0E, 0xFA91, 0x549C, 0xFA92, 0x548A, 0xFA93, 0x54A9, 0xFA94, 0x54FF, 0xFA95, 0x5586, 0xFA96, 0x5759, 0xFA97, 0x5765, + 0xFA98, 0x57AC, 0xFA99, 0x57C8, 0xFA9A, 0x57C7, 0xFA9B, 0xFA0F, 0xFA9C, 0xFA10, 0xFA9D, 0x589E, 0xFA9E, 0x58B2, 0xFA9F, 0x590B, + 0xFAA0, 0x5953, 0xFAA1, 0x595B, 0xFAA2, 0x595D, 0xFAA3, 0x5963, 0xFAA4, 0x59A4, 0xFAA5, 0x59BA, 0xFAA6, 0x5B56, 0xFAA7, 0x5BC0, + 0xFAA8, 0x752F, 0xFAA9, 0x5BD8, 0xFAAA, 0x5BEC, 0xFAAB, 0x5C1E, 0xFAAC, 0x5CA6, 0xFAAD, 0x5CBA, 0xFAAE, 0x5CF5, 0xFAAF, 0x5D27, + 0xFAB0, 0x5D53, 0xFAB1, 0xFA11, 0xFAB2, 0x5D42, 0xFAB3, 0x5D6D, 0xFAB4, 0x5DB8, 0xFAB5, 0x5DB9, 0xFAB6, 0x5DD0, 0xFAB7, 0x5F21, + 0xFAB8, 0x5F34, 0xFAB9, 0x5F67, 0xFABA, 0x5FB7, 0xFABB, 0x5FDE, 0xFABC, 0x605D, 0xFABD, 0x6085, 0xFABE, 0x608A, 0xFABF, 0x60DE, + 0xFAC0, 0x60D5, 0xFAC1, 0x6120, 0xFAC2, 0x60F2, 0xFAC3, 0x6111, 0xFAC4, 0x6137, 0xFAC5, 0x6130, 0xFAC6, 0x6198, 0xFAC7, 0x6213, + 0xFAC8, 0x62A6, 0xFAC9, 0x63F5, 0xFACA, 0x6460, 0xFACB, 0x649D, 0xFACC, 0x64CE, 0xFACD, 0x654E, 0xFACE, 0x6600, 0xFACF, 0x6615, + 0xFAD0, 0x663B, 0xFAD1, 0x6609, 0xFAD2, 0x662E, 0xFAD3, 0x661E, 0xFAD4, 0x6624, 0xFAD5, 0x6665, 0xFAD6, 0x6657, 0xFAD7, 0x6659, + 0xFAD8, 0xFA12, 0xFAD9, 0x6673, 0xFADA, 0x6699, 0xFADB, 0x66A0, 0xFADC, 0x66B2, 0xFADD, 0x66BF, 0xFADE, 0x66FA, 0xFADF, 0x670E, + 0xFAE0, 0xF929, 0xFAE1, 0x6766, 0xFAE2, 0x67BB, 0xFAE3, 0x6852, 0xFAE4, 0x67C0, 0xFAE5, 0x6801, 0xFAE6, 0x6844, 0xFAE7, 0x68CF, + 0xFAE8, 0xFA13, 0xFAE9, 0x6968, 0xFAEA, 0xFA14, 0xFAEB, 0x6998, 0xFAEC, 0x69E2, 0xFAED, 0x6A30, 0xFAEE, 0x6A6B, 0xFAEF, 0x6A46, + 0xFAF0, 0x6A73, 0xFAF1, 0x6A7E, 0xFAF2, 0x6AE2, 0xFAF3, 0x6AE4, 0xFAF4, 0x6BD6, 0xFAF5, 0x6C3F, 0xFAF6, 0x6C5C, 0xFAF7, 0x6C86, + 0xFAF8, 0x6C6F, 0xFAF9, 0x6CDA, 0xFAFA, 0x6D04, 0xFAFB, 0x6D87, 0xFAFC, 0x6D6F, 0xFB40, 0x6D96, 0xFB41, 0x6DAC, 0xFB42, 0x6DCF, + 0xFB43, 0x6DF8, 0xFB44, 0x6DF2, 0xFB45, 0x6DFC, 0xFB46, 0x6E39, 0xFB47, 0x6E5C, 0xFB48, 0x6E27, 0xFB49, 0x6E3C, 0xFB4A, 0x6EBF, + 0xFB4B, 0x6F88, 0xFB4C, 0x6FB5, 0xFB4D, 0x6FF5, 0xFB4E, 0x7005, 0xFB4F, 0x7007, 0xFB50, 0x7028, 0xFB51, 0x7085, 0xFB52, 0x70AB, + 0xFB53, 0x710F, 0xFB54, 0x7104, 0xFB55, 0x715C, 0xFB56, 0x7146, 0xFB57, 0x7147, 0xFB58, 0xFA15, 0xFB59, 0x71C1, 0xFB5A, 0x71FE, + 0xFB5B, 0x72B1, 0xFB5C, 0x72BE, 0xFB5D, 0x7324, 0xFB5E, 0xFA16, 0xFB5F, 0x7377, 0xFB60, 0x73BD, 0xFB61, 0x73C9, 0xFB62, 0x73D6, + 0xFB63, 0x73E3, 0xFB64, 0x73D2, 0xFB65, 0x7407, 0xFB66, 0x73F5, 0xFB67, 0x7426, 0xFB68, 0x742A, 0xFB69, 0x7429, 0xFB6A, 0x742E, + 0xFB6B, 0x7462, 0xFB6C, 0x7489, 0xFB6D, 0x749F, 0xFB6E, 0x7501, 0xFB6F, 0x756F, 0xFB70, 0x7682, 0xFB71, 0x769C, 0xFB72, 0x769E, + 0xFB73, 0x769B, 0xFB74, 0x76A6, 0xFB75, 0xFA17, 0xFB76, 0x7746, 0xFB77, 0x52AF, 0xFB78, 0x7821, 0xFB79, 0x784E, 0xFB7A, 0x7864, + 0xFB7B, 0x787A, 0xFB7C, 0x7930, 0xFB7D, 0xFA18, 0xFB7E, 0xFA19, 0xFB80, 0xFA1A, 0xFB81, 0x7994, 0xFB82, 0xFA1B, 0xFB83, 0x799B, + 0xFB84, 0x7AD1, 0xFB85, 0x7AE7, 0xFB86, 0xFA1C, 0xFB87, 0x7AEB, 0xFB88, 0x7B9E, 0xFB89, 0xFA1D, 0xFB8A, 0x7D48, 0xFB8B, 0x7D5C, + 0xFB8C, 0x7DB7, 0xFB8D, 0x7DA0, 0xFB8E, 0x7DD6, 0xFB8F, 0x7E52, 0xFB90, 0x7F47, 0xFB91, 0x7FA1, 0xFB92, 0xFA1E, 0xFB93, 0x8301, + 0xFB94, 0x8362, 0xFB95, 0x837F, 0xFB96, 0x83C7, 0xFB97, 0x83F6, 0xFB98, 0x8448, 0xFB99, 0x84B4, 0xFB9A, 0x8553, 0xFB9B, 0x8559, + 0xFB9C, 0x856B, 0xFB9D, 0xFA1F, 0xFB9E, 0x85B0, 0xFB9F, 0xFA20, 0xFBA0, 0xFA21, 0xFBA1, 0x8807, 0xFBA2, 0x88F5, 0xFBA3, 0x8A12, + 0xFBA4, 0x8A37, 0xFBA5, 0x8A79, 0xFBA6, 0x8AA7, 0xFBA7, 0x8ABE, 0xFBA8, 0x8ADF, 0xFBA9, 0xFA22, 0xFBAA, 0x8AF6, 0xFBAB, 0x8B53, + 0xFBAC, 0x8B7F, 0xFBAD, 0x8CF0, 0xFBAE, 0x8CF4, 0xFBAF, 0x8D12, 0xFBB0, 0x8D76, 0xFBB1, 0xFA23, 0xFBB2, 0x8ECF, 0xFBB3, 0xFA24, + 0xFBB4, 0xFA25, 0xFBB5, 0x9067, 0xFBB6, 0x90DE, 0xFBB7, 0xFA26, 0xFBB8, 0x9115, 0xFBB9, 0x9127, 0xFBBA, 0x91DA, 0xFBBB, 0x91D7, + 0xFBBC, 0x91DE, 0xFBBD, 0x91ED, 0xFBBE, 0x91EE, 0xFBBF, 0x91E4, 0xFBC0, 0x91E5, 0xFBC1, 0x9206, 0xFBC2, 0x9210, 0xFBC3, 0x920A, + 0xFBC4, 0x923A, 0xFBC5, 0x9240, 0xFBC6, 0x923C, 0xFBC7, 0x924E, 0xFBC8, 0x9259, 0xFBC9, 0x9251, 0xFBCA, 0x9239, 0xFBCB, 0x9267, + 0xFBCC, 0x92A7, 0xFBCD, 0x9277, 0xFBCE, 0x9278, 0xFBCF, 0x92E7, 0xFBD0, 0x92D7, 0xFBD1, 0x92D9, 0xFBD2, 0x92D0, 0xFBD3, 0xFA27, + 0xFBD4, 0x92D5, 0xFBD5, 0x92E0, 0xFBD6, 0x92D3, 0xFBD7, 0x9325, 0xFBD8, 0x9321, 0xFBD9, 0x92FB, 0xFBDA, 0xFA28, 0xFBDB, 0x931E, + 0xFBDC, 0x92FF, 0xFBDD, 0x931D, 0xFBDE, 0x9302, 0xFBDF, 0x9370, 0xFBE0, 0x9357, 0xFBE1, 0x93A4, 0xFBE2, 0x93C6, 0xFBE3, 0x93DE, + 0xFBE4, 0x93F8, 0xFBE5, 0x9431, 0xFBE6, 0x9445, 0xFBE7, 0x9448, 0xFBE8, 0x9592, 0xFBE9, 0xF9DC, 0xFBEA, 0xFA29, 0xFBEB, 0x969D, + 0xFBEC, 0x96AF, 0xFBED, 0x9733, 0xFBEE, 0x973B, 0xFBEF, 0x9743, 0xFBF0, 0x974D, 0xFBF1, 0x974F, 0xFBF2, 0x9751, 0xFBF3, 0x9755, + 0xFBF4, 0x9857, 0xFBF5, 0x9865, 0xFBF6, 0xFA2A, 0xFBF7, 0xFA2B, 0xFBF8, 0x9927, 0xFBF9, 0xFA2C, 0xFBFA, 0x999E, 0xFBFB, 0x9A4E, + 0xFBFC, 0x9AD9, 0xFC40, 0x9ADC, 0xFC41, 0x9B75, 0xFC42, 0x9B72, 0xFC43, 0x9B8F, 0xFC44, 0x9BB1, 0xFC45, 0x9BBB, 0xFC46, 0x9C00, + 0xFC47, 0x9D70, 0xFC48, 0x9D6B, 0xFC49, 0xFA2D, 0xFC4A, 0x9E19, 0xFC4B, 0x9ED1, 0, 0 +}; +#endif + +#if FF_CODE_PAGE == 936 || FF_CODE_PAGE == 0 /* Simplified Chinese */ +static +const WCHAR uni2oem936[] = { /* Unicode --> GBK pairs */ + 0x00A4, 0xA1E8, 0x00A7, 0xA1EC, 0x00A8, 0xA1A7, 0x00B0, 0xA1E3, 0x00B1, 0xA1C0, 0x00B7, 0xA1A4, 0x00D7, 0xA1C1, 0x00E0, 0xA8A4, + 0x00E1, 0xA8A2, 0x00E8, 0xA8A8, 0x00E9, 0xA8A6, 0x00EA, 0xA8BA, 0x00EC, 0xA8AC, 0x00ED, 0xA8AA, 0x00F2, 0xA8B0, 0x00F3, 0xA8AE, + 0x00F7, 0xA1C2, 0x00F9, 0xA8B4, 0x00FA, 0xA8B2, 0x00FC, 0xA8B9, 0x0101, 0xA8A1, 0x0113, 0xA8A5, 0x011B, 0xA8A7, 0x012B, 0xA8A9, + 0x0144, 0xA8BD, 0x0148, 0xA8BE, 0x014D, 0xA8AD, 0x016B, 0xA8B1, 0x01CE, 0xA8A3, 0x01D0, 0xA8AB, 0x01D2, 0xA8AF, 0x01D4, 0xA8B3, + 0x01D6, 0xA8B5, 0x01D8, 0xA8B6, 0x01DA, 0xA8B7, 0x01DC, 0xA8B8, 0x0251, 0xA8BB, 0x0261, 0xA8C0, 0x02C7, 0xA1A6, 0x02C9, 0xA1A5, + 0x02CA, 0xA840, 0x02CB, 0xA841, 0x02D9, 0xA842, 0x0391, 0xA6A1, 0x0392, 0xA6A2, 0x0393, 0xA6A3, 0x0394, 0xA6A4, 0x0395, 0xA6A5, + 0x0396, 0xA6A6, 0x0397, 0xA6A7, 0x0398, 0xA6A8, 0x0399, 0xA6A9, 0x039A, 0xA6AA, 0x039B, 0xA6AB, 0x039C, 0xA6AC, 0x039D, 0xA6AD, + 0x039E, 0xA6AE, 0x039F, 0xA6AF, 0x03A0, 0xA6B0, 0x03A1, 0xA6B1, 0x03A3, 0xA6B2, 0x03A4, 0xA6B3, 0x03A5, 0xA6B4, 0x03A6, 0xA6B5, + 0x03A7, 0xA6B6, 0x03A8, 0xA6B7, 0x03A9, 0xA6B8, 0x03B1, 0xA6C1, 0x03B2, 0xA6C2, 0x03B3, 0xA6C3, 0x03B4, 0xA6C4, 0x03B5, 0xA6C5, + 0x03B6, 0xA6C6, 0x03B7, 0xA6C7, 0x03B8, 0xA6C8, 0x03B9, 0xA6C9, 0x03BA, 0xA6CA, 0x03BB, 0xA6CB, 0x03BC, 0xA6CC, 0x03BD, 0xA6CD, + 0x03BE, 0xA6CE, 0x03BF, 0xA6CF, 0x03C0, 0xA6D0, 0x03C1, 0xA6D1, 0x03C3, 0xA6D2, 0x03C4, 0xA6D3, 0x03C5, 0xA6D4, 0x03C6, 0xA6D5, + 0x03C7, 0xA6D6, 0x03C8, 0xA6D7, 0x03C9, 0xA6D8, 0x0401, 0xA7A7, 0x0410, 0xA7A1, 0x0411, 0xA7A2, 0x0412, 0xA7A3, 0x0413, 0xA7A4, + 0x0414, 0xA7A5, 0x0415, 0xA7A6, 0x0416, 0xA7A8, 0x0417, 0xA7A9, 0x0418, 0xA7AA, 0x0419, 0xA7AB, 0x041A, 0xA7AC, 0x041B, 0xA7AD, + 0x041C, 0xA7AE, 0x041D, 0xA7AF, 0x041E, 0xA7B0, 0x041F, 0xA7B1, 0x0420, 0xA7B2, 0x0421, 0xA7B3, 0x0422, 0xA7B4, 0x0423, 0xA7B5, + 0x0424, 0xA7B6, 0x0425, 0xA7B7, 0x0426, 0xA7B8, 0x0427, 0xA7B9, 0x0428, 0xA7BA, 0x0429, 0xA7BB, 0x042A, 0xA7BC, 0x042B, 0xA7BD, + 0x042C, 0xA7BE, 0x042D, 0xA7BF, 0x042E, 0xA7C0, 0x042F, 0xA7C1, 0x0430, 0xA7D1, 0x0431, 0xA7D2, 0x0432, 0xA7D3, 0x0433, 0xA7D4, + 0x0434, 0xA7D5, 0x0435, 0xA7D6, 0x0436, 0xA7D8, 0x0437, 0xA7D9, 0x0438, 0xA7DA, 0x0439, 0xA7DB, 0x043A, 0xA7DC, 0x043B, 0xA7DD, + 0x043C, 0xA7DE, 0x043D, 0xA7DF, 0x043E, 0xA7E0, 0x043F, 0xA7E1, 0x0440, 0xA7E2, 0x0441, 0xA7E3, 0x0442, 0xA7E4, 0x0443, 0xA7E5, + 0x0444, 0xA7E6, 0x0445, 0xA7E7, 0x0446, 0xA7E8, 0x0447, 0xA7E9, 0x0448, 0xA7EA, 0x0449, 0xA7EB, 0x044A, 0xA7EC, 0x044B, 0xA7ED, + 0x044C, 0xA7EE, 0x044D, 0xA7EF, 0x044E, 0xA7F0, 0x044F, 0xA7F1, 0x0451, 0xA7D7, 0x2010, 0xA95C, 0x2013, 0xA843, 0x2014, 0xA1AA, + 0x2015, 0xA844, 0x2016, 0xA1AC, 0x2018, 0xA1AE, 0x2019, 0xA1AF, 0x201C, 0xA1B0, 0x201D, 0xA1B1, 0x2025, 0xA845, 0x2026, 0xA1AD, + 0x2030, 0xA1EB, 0x2032, 0xA1E4, 0x2033, 0xA1E5, 0x2035, 0xA846, 0x203B, 0xA1F9, 0x20AC, 0x0080, 0x2103, 0xA1E6, 0x2105, 0xA847, + 0x2109, 0xA848, 0x2116, 0xA1ED, 0x2121, 0xA959, 0x2160, 0xA2F1, 0x2161, 0xA2F2, 0x2162, 0xA2F3, 0x2163, 0xA2F4, 0x2164, 0xA2F5, + 0x2165, 0xA2F6, 0x2166, 0xA2F7, 0x2167, 0xA2F8, 0x2168, 0xA2F9, 0x2169, 0xA2FA, 0x216A, 0xA2FB, 0x216B, 0xA2FC, 0x2170, 0xA2A1, + 0x2171, 0xA2A2, 0x2172, 0xA2A3, 0x2173, 0xA2A4, 0x2174, 0xA2A5, 0x2175, 0xA2A6, 0x2176, 0xA2A7, 0x2177, 0xA2A8, 0x2178, 0xA2A9, + 0x2179, 0xA2AA, 0x2190, 0xA1FB, 0x2191, 0xA1FC, 0x2192, 0xA1FA, 0x2193, 0xA1FD, 0x2196, 0xA849, 0x2197, 0xA84A, 0x2198, 0xA84B, + 0x2199, 0xA84C, 0x2208, 0xA1CA, 0x220F, 0xA1C7, 0x2211, 0xA1C6, 0x2215, 0xA84D, 0x221A, 0xA1CC, 0x221D, 0xA1D8, 0x221E, 0xA1DE, + 0x221F, 0xA84E, 0x2220, 0xA1CF, 0x2223, 0xA84F, 0x2225, 0xA1CE, 0x2227, 0xA1C4, 0x2228, 0xA1C5, 0x2229, 0xA1C9, 0x222A, 0xA1C8, + 0x222B, 0xA1D2, 0x222E, 0xA1D3, 0x2234, 0xA1E0, 0x2235, 0xA1DF, 0x2236, 0xA1C3, 0x2237, 0xA1CB, 0x223D, 0xA1D7, 0x2248, 0xA1D6, + 0x224C, 0xA1D5, 0x2252, 0xA850, 0x2260, 0xA1D9, 0x2261, 0xA1D4, 0x2264, 0xA1DC, 0x2265, 0xA1DD, 0x2266, 0xA851, 0x2267, 0xA852, + 0x226E, 0xA1DA, 0x226F, 0xA1DB, 0x2295, 0xA892, 0x2299, 0xA1D1, 0x22A5, 0xA1CD, 0x22BF, 0xA853, 0x2312, 0xA1D0, 0x2460, 0xA2D9, + 0x2461, 0xA2DA, 0x2462, 0xA2DB, 0x2463, 0xA2DC, 0x2464, 0xA2DD, 0x2465, 0xA2DE, 0x2466, 0xA2DF, 0x2467, 0xA2E0, 0x2468, 0xA2E1, + 0x2469, 0xA2E2, 0x2474, 0xA2C5, 0x2475, 0xA2C6, 0x2476, 0xA2C7, 0x2477, 0xA2C8, 0x2478, 0xA2C9, 0x2479, 0xA2CA, 0x247A, 0xA2CB, + 0x247B, 0xA2CC, 0x247C, 0xA2CD, 0x247D, 0xA2CE, 0x247E, 0xA2CF, 0x247F, 0xA2D0, 0x2480, 0xA2D1, 0x2481, 0xA2D2, 0x2482, 0xA2D3, + 0x2483, 0xA2D4, 0x2484, 0xA2D5, 0x2485, 0xA2D6, 0x2486, 0xA2D7, 0x2487, 0xA2D8, 0x2488, 0xA2B1, 0x2489, 0xA2B2, 0x248A, 0xA2B3, + 0x248B, 0xA2B4, 0x248C, 0xA2B5, 0x248D, 0xA2B6, 0x248E, 0xA2B7, 0x248F, 0xA2B8, 0x2490, 0xA2B9, 0x2491, 0xA2BA, 0x2492, 0xA2BB, + 0x2493, 0xA2BC, 0x2494, 0xA2BD, 0x2495, 0xA2BE, 0x2496, 0xA2BF, 0x2497, 0xA2C0, 0x2498, 0xA2C1, 0x2499, 0xA2C2, 0x249A, 0xA2C3, + 0x249B, 0xA2C4, 0x2500, 0xA9A4, 0x2501, 0xA9A5, 0x2502, 0xA9A6, 0x2503, 0xA9A7, 0x2504, 0xA9A8, 0x2505, 0xA9A9, 0x2506, 0xA9AA, + 0x2507, 0xA9AB, 0x2508, 0xA9AC, 0x2509, 0xA9AD, 0x250A, 0xA9AE, 0x250B, 0xA9AF, 0x250C, 0xA9B0, 0x250D, 0xA9B1, 0x250E, 0xA9B2, + 0x250F, 0xA9B3, 0x2510, 0xA9B4, 0x2511, 0xA9B5, 0x2512, 0xA9B6, 0x2513, 0xA9B7, 0x2514, 0xA9B8, 0x2515, 0xA9B9, 0x2516, 0xA9BA, + 0x2517, 0xA9BB, 0x2518, 0xA9BC, 0x2519, 0xA9BD, 0x251A, 0xA9BE, 0x251B, 0xA9BF, 0x251C, 0xA9C0, 0x251D, 0xA9C1, 0x251E, 0xA9C2, + 0x251F, 0xA9C3, 0x2520, 0xA9C4, 0x2521, 0xA9C5, 0x2522, 0xA9C6, 0x2523, 0xA9C7, 0x2524, 0xA9C8, 0x2525, 0xA9C9, 0x2526, 0xA9CA, + 0x2527, 0xA9CB, 0x2528, 0xA9CC, 0x2529, 0xA9CD, 0x252A, 0xA9CE, 0x252B, 0xA9CF, 0x252C, 0xA9D0, 0x252D, 0xA9D1, 0x252E, 0xA9D2, + 0x252F, 0xA9D3, 0x2530, 0xA9D4, 0x2531, 0xA9D5, 0x2532, 0xA9D6, 0x2533, 0xA9D7, 0x2534, 0xA9D8, 0x2535, 0xA9D9, 0x2536, 0xA9DA, + 0x2537, 0xA9DB, 0x2538, 0xA9DC, 0x2539, 0xA9DD, 0x253A, 0xA9DE, 0x253B, 0xA9DF, 0x253C, 0xA9E0, 0x253D, 0xA9E1, 0x253E, 0xA9E2, + 0x253F, 0xA9E3, 0x2540, 0xA9E4, 0x2541, 0xA9E5, 0x2542, 0xA9E6, 0x2543, 0xA9E7, 0x2544, 0xA9E8, 0x2545, 0xA9E9, 0x2546, 0xA9EA, + 0x2547, 0xA9EB, 0x2548, 0xA9EC, 0x2549, 0xA9ED, 0x254A, 0xA9EE, 0x254B, 0xA9EF, 0x2550, 0xA854, 0x2551, 0xA855, 0x2552, 0xA856, + 0x2553, 0xA857, 0x2554, 0xA858, 0x2555, 0xA859, 0x2556, 0xA85A, 0x2557, 0xA85B, 0x2558, 0xA85C, 0x2559, 0xA85D, 0x255A, 0xA85E, + 0x255B, 0xA85F, 0x255C, 0xA860, 0x255D, 0xA861, 0x255E, 0xA862, 0x255F, 0xA863, 0x2560, 0xA864, 0x2561, 0xA865, 0x2562, 0xA866, + 0x2563, 0xA867, 0x2564, 0xA868, 0x2565, 0xA869, 0x2566, 0xA86A, 0x2567, 0xA86B, 0x2568, 0xA86C, 0x2569, 0xA86D, 0x256A, 0xA86E, + 0x256B, 0xA86F, 0x256C, 0xA870, 0x256D, 0xA871, 0x256E, 0xA872, 0x256F, 0xA873, 0x2570, 0xA874, 0x2571, 0xA875, 0x2572, 0xA876, + 0x2573, 0xA877, 0x2581, 0xA878, 0x2582, 0xA879, 0x2583, 0xA87A, 0x2584, 0xA87B, 0x2585, 0xA87C, 0x2586, 0xA87D, 0x2587, 0xA87E, + 0x2588, 0xA880, 0x2589, 0xA881, 0x258A, 0xA882, 0x258B, 0xA883, 0x258C, 0xA884, 0x258D, 0xA885, 0x258E, 0xA886, 0x258F, 0xA887, + 0x2593, 0xA888, 0x2594, 0xA889, 0x2595, 0xA88A, 0x25A0, 0xA1F6, 0x25A1, 0xA1F5, 0x25B2, 0xA1F8, 0x25B3, 0xA1F7, 0x25BC, 0xA88B, + 0x25BD, 0xA88C, 0x25C6, 0xA1F4, 0x25C7, 0xA1F3, 0x25CB, 0xA1F0, 0x25CE, 0xA1F2, 0x25CF, 0xA1F1, 0x25E2, 0xA88D, 0x25E3, 0xA88E, + 0x25E4, 0xA88F, 0x25E5, 0xA890, 0x2605, 0xA1EF, 0x2606, 0xA1EE, 0x2609, 0xA891, 0x2640, 0xA1E2, 0x2642, 0xA1E1, 0x3000, 0xA1A1, + 0x3001, 0xA1A2, 0x3002, 0xA1A3, 0x3003, 0xA1A8, 0x3005, 0xA1A9, 0x3006, 0xA965, 0x3007, 0xA996, 0x3008, 0xA1B4, 0x3009, 0xA1B5, + 0x300A, 0xA1B6, 0x300B, 0xA1B7, 0x300C, 0xA1B8, 0x300D, 0xA1B9, 0x300E, 0xA1BA, 0x300F, 0xA1BB, 0x3010, 0xA1BE, 0x3011, 0xA1BF, + 0x3012, 0xA893, 0x3013, 0xA1FE, 0x3014, 0xA1B2, 0x3015, 0xA1B3, 0x3016, 0xA1BC, 0x3017, 0xA1BD, 0x301D, 0xA894, 0x301E, 0xA895, + 0x3021, 0xA940, 0x3022, 0xA941, 0x3023, 0xA942, 0x3024, 0xA943, 0x3025, 0xA944, 0x3026, 0xA945, 0x3027, 0xA946, 0x3028, 0xA947, + 0x3029, 0xA948, 0x3041, 0xA4A1, 0x3042, 0xA4A2, 0x3043, 0xA4A3, 0x3044, 0xA4A4, 0x3045, 0xA4A5, 0x3046, 0xA4A6, 0x3047, 0xA4A7, + 0x3048, 0xA4A8, 0x3049, 0xA4A9, 0x304A, 0xA4AA, 0x304B, 0xA4AB, 0x304C, 0xA4AC, 0x304D, 0xA4AD, 0x304E, 0xA4AE, 0x304F, 0xA4AF, + 0x3050, 0xA4B0, 0x3051, 0xA4B1, 0x3052, 0xA4B2, 0x3053, 0xA4B3, 0x3054, 0xA4B4, 0x3055, 0xA4B5, 0x3056, 0xA4B6, 0x3057, 0xA4B7, + 0x3058, 0xA4B8, 0x3059, 0xA4B9, 0x305A, 0xA4BA, 0x305B, 0xA4BB, 0x305C, 0xA4BC, 0x305D, 0xA4BD, 0x305E, 0xA4BE, 0x305F, 0xA4BF, + 0x3060, 0xA4C0, 0x3061, 0xA4C1, 0x3062, 0xA4C2, 0x3063, 0xA4C3, 0x3064, 0xA4C4, 0x3065, 0xA4C5, 0x3066, 0xA4C6, 0x3067, 0xA4C7, + 0x3068, 0xA4C8, 0x3069, 0xA4C9, 0x306A, 0xA4CA, 0x306B, 0xA4CB, 0x306C, 0xA4CC, 0x306D, 0xA4CD, 0x306E, 0xA4CE, 0x306F, 0xA4CF, + 0x3070, 0xA4D0, 0x3071, 0xA4D1, 0x3072, 0xA4D2, 0x3073, 0xA4D3, 0x3074, 0xA4D4, 0x3075, 0xA4D5, 0x3076, 0xA4D6, 0x3077, 0xA4D7, + 0x3078, 0xA4D8, 0x3079, 0xA4D9, 0x307A, 0xA4DA, 0x307B, 0xA4DB, 0x307C, 0xA4DC, 0x307D, 0xA4DD, 0x307E, 0xA4DE, 0x307F, 0xA4DF, + 0x3080, 0xA4E0, 0x3081, 0xA4E1, 0x3082, 0xA4E2, 0x3083, 0xA4E3, 0x3084, 0xA4E4, 0x3085, 0xA4E5, 0x3086, 0xA4E6, 0x3087, 0xA4E7, + 0x3088, 0xA4E8, 0x3089, 0xA4E9, 0x308A, 0xA4EA, 0x308B, 0xA4EB, 0x308C, 0xA4EC, 0x308D, 0xA4ED, 0x308E, 0xA4EE, 0x308F, 0xA4EF, + 0x3090, 0xA4F0, 0x3091, 0xA4F1, 0x3092, 0xA4F2, 0x3093, 0xA4F3, 0x309B, 0xA961, 0x309C, 0xA962, 0x309D, 0xA966, 0x309E, 0xA967, + 0x30A1, 0xA5A1, 0x30A2, 0xA5A2, 0x30A3, 0xA5A3, 0x30A4, 0xA5A4, 0x30A5, 0xA5A5, 0x30A6, 0xA5A6, 0x30A7, 0xA5A7, 0x30A8, 0xA5A8, + 0x30A9, 0xA5A9, 0x30AA, 0xA5AA, 0x30AB, 0xA5AB, 0x30AC, 0xA5AC, 0x30AD, 0xA5AD, 0x30AE, 0xA5AE, 0x30AF, 0xA5AF, 0x30B0, 0xA5B0, + 0x30B1, 0xA5B1, 0x30B2, 0xA5B2, 0x30B3, 0xA5B3, 0x30B4, 0xA5B4, 0x30B5, 0xA5B5, 0x30B6, 0xA5B6, 0x30B7, 0xA5B7, 0x30B8, 0xA5B8, + 0x30B9, 0xA5B9, 0x30BA, 0xA5BA, 0x30BB, 0xA5BB, 0x30BC, 0xA5BC, 0x30BD, 0xA5BD, 0x30BE, 0xA5BE, 0x30BF, 0xA5BF, 0x30C0, 0xA5C0, + 0x30C1, 0xA5C1, 0x30C2, 0xA5C2, 0x30C3, 0xA5C3, 0x30C4, 0xA5C4, 0x30C5, 0xA5C5, 0x30C6, 0xA5C6, 0x30C7, 0xA5C7, 0x30C8, 0xA5C8, + 0x30C9, 0xA5C9, 0x30CA, 0xA5CA, 0x30CB, 0xA5CB, 0x30CC, 0xA5CC, 0x30CD, 0xA5CD, 0x30CE, 0xA5CE, 0x30CF, 0xA5CF, 0x30D0, 0xA5D0, + 0x30D1, 0xA5D1, 0x30D2, 0xA5D2, 0x30D3, 0xA5D3, 0x30D4, 0xA5D4, 0x30D5, 0xA5D5, 0x30D6, 0xA5D6, 0x30D7, 0xA5D7, 0x30D8, 0xA5D8, + 0x30D9, 0xA5D9, 0x30DA, 0xA5DA, 0x30DB, 0xA5DB, 0x30DC, 0xA5DC, 0x30DD, 0xA5DD, 0x30DE, 0xA5DE, 0x30DF, 0xA5DF, 0x30E0, 0xA5E0, + 0x30E1, 0xA5E1, 0x30E2, 0xA5E2, 0x30E3, 0xA5E3, 0x30E4, 0xA5E4, 0x30E5, 0xA5E5, 0x30E6, 0xA5E6, 0x30E7, 0xA5E7, 0x30E8, 0xA5E8, + 0x30E9, 0xA5E9, 0x30EA, 0xA5EA, 0x30EB, 0xA5EB, 0x30EC, 0xA5EC, 0x30ED, 0xA5ED, 0x30EE, 0xA5EE, 0x30EF, 0xA5EF, 0x30F0, 0xA5F0, + 0x30F1, 0xA5F1, 0x30F2, 0xA5F2, 0x30F3, 0xA5F3, 0x30F4, 0xA5F4, 0x30F5, 0xA5F5, 0x30F6, 0xA5F6, 0x30FC, 0xA960, 0x30FD, 0xA963, + 0x30FE, 0xA964, 0x3105, 0xA8C5, 0x3106, 0xA8C6, 0x3107, 0xA8C7, 0x3108, 0xA8C8, 0x3109, 0xA8C9, 0x310A, 0xA8CA, 0x310B, 0xA8CB, + 0x310C, 0xA8CC, 0x310D, 0xA8CD, 0x310E, 0xA8CE, 0x310F, 0xA8CF, 0x3110, 0xA8D0, 0x3111, 0xA8D1, 0x3112, 0xA8D2, 0x3113, 0xA8D3, + 0x3114, 0xA8D4, 0x3115, 0xA8D5, 0x3116, 0xA8D6, 0x3117, 0xA8D7, 0x3118, 0xA8D8, 0x3119, 0xA8D9, 0x311A, 0xA8DA, 0x311B, 0xA8DB, + 0x311C, 0xA8DC, 0x311D, 0xA8DD, 0x311E, 0xA8DE, 0x311F, 0xA8DF, 0x3120, 0xA8E0, 0x3121, 0xA8E1, 0x3122, 0xA8E2, 0x3123, 0xA8E3, + 0x3124, 0xA8E4, 0x3125, 0xA8E5, 0x3126, 0xA8E6, 0x3127, 0xA8E7, 0x3128, 0xA8E8, 0x3129, 0xA8E9, 0x3220, 0xA2E5, 0x3221, 0xA2E6, + 0x3222, 0xA2E7, 0x3223, 0xA2E8, 0x3224, 0xA2E9, 0x3225, 0xA2EA, 0x3226, 0xA2EB, 0x3227, 0xA2EC, 0x3228, 0xA2ED, 0x3229, 0xA2EE, + 0x3231, 0xA95A, 0x32A3, 0xA949, 0x338E, 0xA94A, 0x338F, 0xA94B, 0x339C, 0xA94C, 0x339D, 0xA94D, 0x339E, 0xA94E, 0x33A1, 0xA94F, + 0x33C4, 0xA950, 0x33CE, 0xA951, 0x33D1, 0xA952, 0x33D2, 0xA953, 0x33D5, 0xA954, 0x4E00, 0xD2BB, 0x4E01, 0xB6A1, 0x4E02, 0x8140, + 0x4E03, 0xC6DF, 0x4E04, 0x8141, 0x4E05, 0x8142, 0x4E06, 0x8143, 0x4E07, 0xCDF2, 0x4E08, 0xD5C9, 0x4E09, 0xC8FD, 0x4E0A, 0xC9CF, + 0x4E0B, 0xCFC2, 0x4E0C, 0xD8A2, 0x4E0D, 0xB2BB, 0x4E0E, 0xD3EB, 0x4E0F, 0x8144, 0x4E10, 0xD8A4, 0x4E11, 0xB3F3, 0x4E12, 0x8145, + 0x4E13, 0xD7A8, 0x4E14, 0xC7D2, 0x4E15, 0xD8A7, 0x4E16, 0xCAC0, 0x4E17, 0x8146, 0x4E18, 0xC7F0, 0x4E19, 0xB1FB, 0x4E1A, 0xD2B5, + 0x4E1B, 0xB4D4, 0x4E1C, 0xB6AB, 0x4E1D, 0xCBBF, 0x4E1E, 0xD8A9, 0x4E1F, 0x8147, 0x4E20, 0x8148, 0x4E21, 0x8149, 0x4E22, 0xB6AA, + 0x4E23, 0x814A, 0x4E24, 0xC1BD, 0x4E25, 0xD1CF, 0x4E26, 0x814B, 0x4E27, 0xC9A5, 0x4E28, 0xD8AD, 0x4E29, 0x814C, 0x4E2A, 0xB8F6, + 0x4E2B, 0xD1BE, 0x4E2C, 0xE3DC, 0x4E2D, 0xD6D0, 0x4E2E, 0x814D, 0x4E2F, 0x814E, 0x4E30, 0xB7E1, 0x4E31, 0x814F, 0x4E32, 0xB4AE, + 0x4E33, 0x8150, 0x4E34, 0xC1D9, 0x4E35, 0x8151, 0x4E36, 0xD8BC, 0x4E37, 0x8152, 0x4E38, 0xCDE8, 0x4E39, 0xB5A4, 0x4E3A, 0xCEAA, + 0x4E3B, 0xD6F7, 0x4E3C, 0x8153, 0x4E3D, 0xC0F6, 0x4E3E, 0xBED9, 0x4E3F, 0xD8AF, 0x4E40, 0x8154, 0x4E41, 0x8155, 0x4E42, 0x8156, + 0x4E43, 0xC4CB, 0x4E44, 0x8157, 0x4E45, 0xBEC3, 0x4E46, 0x8158, 0x4E47, 0xD8B1, 0x4E48, 0xC3B4, 0x4E49, 0xD2E5, 0x4E4A, 0x8159, + 0x4E4B, 0xD6AE, 0x4E4C, 0xCEDA, 0x4E4D, 0xD5A7, 0x4E4E, 0xBAF5, 0x4E4F, 0xB7A6, 0x4E50, 0xC0D6, 0x4E51, 0x815A, 0x4E52, 0xC6B9, + 0x4E53, 0xC5D2, 0x4E54, 0xC7C7, 0x4E55, 0x815B, 0x4E56, 0xB9D4, 0x4E57, 0x815C, 0x4E58, 0xB3CB, 0x4E59, 0xD2D2, 0x4E5A, 0x815D, + 0x4E5B, 0x815E, 0x4E5C, 0xD8BF, 0x4E5D, 0xBEC5, 0x4E5E, 0xC6F2, 0x4E5F, 0xD2B2, 0x4E60, 0xCFB0, 0x4E61, 0xCFE7, 0x4E62, 0x815F, + 0x4E63, 0x8160, 0x4E64, 0x8161, 0x4E65, 0x8162, 0x4E66, 0xCAE9, 0x4E67, 0x8163, 0x4E68, 0x8164, 0x4E69, 0xD8C0, 0x4E6A, 0x8165, + 0x4E6B, 0x8166, 0x4E6C, 0x8167, 0x4E6D, 0x8168, 0x4E6E, 0x8169, 0x4E6F, 0x816A, 0x4E70, 0xC2F2, 0x4E71, 0xC2D2, 0x4E72, 0x816B, + 0x4E73, 0xC8E9, 0x4E74, 0x816C, 0x4E75, 0x816D, 0x4E76, 0x816E, 0x4E77, 0x816F, 0x4E78, 0x8170, 0x4E79, 0x8171, 0x4E7A, 0x8172, + 0x4E7B, 0x8173, 0x4E7C, 0x8174, 0x4E7D, 0x8175, 0x4E7E, 0xC7AC, 0x4E7F, 0x8176, 0x4E80, 0x8177, 0x4E81, 0x8178, 0x4E82, 0x8179, + 0x4E83, 0x817A, 0x4E84, 0x817B, 0x4E85, 0x817C, 0x4E86, 0xC1CB, 0x4E87, 0x817D, 0x4E88, 0xD3E8, 0x4E89, 0xD5F9, 0x4E8A, 0x817E, + 0x4E8B, 0xCAC2, 0x4E8C, 0xB6FE, 0x4E8D, 0xD8A1, 0x4E8E, 0xD3DA, 0x4E8F, 0xBFF7, 0x4E90, 0x8180, 0x4E91, 0xD4C6, 0x4E92, 0xBBA5, + 0x4E93, 0xD8C1, 0x4E94, 0xCEE5, 0x4E95, 0xBEAE, 0x4E96, 0x8181, 0x4E97, 0x8182, 0x4E98, 0xD8A8, 0x4E99, 0x8183, 0x4E9A, 0xD1C7, + 0x4E9B, 0xD0A9, 0x4E9C, 0x8184, 0x4E9D, 0x8185, 0x4E9E, 0x8186, 0x4E9F, 0xD8BD, 0x4EA0, 0xD9EF, 0x4EA1, 0xCDF6, 0x4EA2, 0xBFBA, + 0x4EA3, 0x8187, 0x4EA4, 0xBDBB, 0x4EA5, 0xBAA5, 0x4EA6, 0xD2E0, 0x4EA7, 0xB2FA, 0x4EA8, 0xBAE0, 0x4EA9, 0xC4B6, 0x4EAA, 0x8188, + 0x4EAB, 0xCFED, 0x4EAC, 0xBEA9, 0x4EAD, 0xCDA4, 0x4EAE, 0xC1C1, 0x4EAF, 0x8189, 0x4EB0, 0x818A, 0x4EB1, 0x818B, 0x4EB2, 0xC7D7, + 0x4EB3, 0xD9F1, 0x4EB4, 0x818C, 0x4EB5, 0xD9F4, 0x4EB6, 0x818D, 0x4EB7, 0x818E, 0x4EB8, 0x818F, 0x4EB9, 0x8190, 0x4EBA, 0xC8CB, + 0x4EBB, 0xD8E9, 0x4EBC, 0x8191, 0x4EBD, 0x8192, 0x4EBE, 0x8193, 0x4EBF, 0xD2DA, 0x4EC0, 0xCAB2, 0x4EC1, 0xC8CA, 0x4EC2, 0xD8EC, + 0x4EC3, 0xD8EA, 0x4EC4, 0xD8C6, 0x4EC5, 0xBDF6, 0x4EC6, 0xC6CD, 0x4EC7, 0xB3F0, 0x4EC8, 0x8194, 0x4EC9, 0xD8EB, 0x4ECA, 0xBDF1, + 0x4ECB, 0xBDE9, 0x4ECC, 0x8195, 0x4ECD, 0xC8D4, 0x4ECE, 0xB4D3, 0x4ECF, 0x8196, 0x4ED0, 0x8197, 0x4ED1, 0xC2D8, 0x4ED2, 0x8198, + 0x4ED3, 0xB2D6, 0x4ED4, 0xD7D0, 0x4ED5, 0xCACB, 0x4ED6, 0xCBFB, 0x4ED7, 0xD5CC, 0x4ED8, 0xB8B6, 0x4ED9, 0xCFC9, 0x4EDA, 0x8199, + 0x4EDB, 0x819A, 0x4EDC, 0x819B, 0x4EDD, 0xD9DA, 0x4EDE, 0xD8F0, 0x4EDF, 0xC7AA, 0x4EE0, 0x819C, 0x4EE1, 0xD8EE, 0x4EE2, 0x819D, + 0x4EE3, 0xB4FA, 0x4EE4, 0xC1EE, 0x4EE5, 0xD2D4, 0x4EE6, 0x819E, 0x4EE7, 0x819F, 0x4EE8, 0xD8ED, 0x4EE9, 0x81A0, 0x4EEA, 0xD2C7, + 0x4EEB, 0xD8EF, 0x4EEC, 0xC3C7, 0x4EED, 0x81A1, 0x4EEE, 0x81A2, 0x4EEF, 0x81A3, 0x4EF0, 0xD1F6, 0x4EF1, 0x81A4, 0x4EF2, 0xD6D9, + 0x4EF3, 0xD8F2, 0x4EF4, 0x81A5, 0x4EF5, 0xD8F5, 0x4EF6, 0xBCFE, 0x4EF7, 0xBCDB, 0x4EF8, 0x81A6, 0x4EF9, 0x81A7, 0x4EFA, 0x81A8, + 0x4EFB, 0xC8CE, 0x4EFC, 0x81A9, 0x4EFD, 0xB7DD, 0x4EFE, 0x81AA, 0x4EFF, 0xB7C2, 0x4F00, 0x81AB, 0x4F01, 0xC6F3, 0x4F02, 0x81AC, + 0x4F03, 0x81AD, 0x4F04, 0x81AE, 0x4F05, 0x81AF, 0x4F06, 0x81B0, 0x4F07, 0x81B1, 0x4F08, 0x81B2, 0x4F09, 0xD8F8, 0x4F0A, 0xD2C1, + 0x4F0B, 0x81B3, 0x4F0C, 0x81B4, 0x4F0D, 0xCEE9, 0x4F0E, 0xBCBF, 0x4F0F, 0xB7FC, 0x4F10, 0xB7A5, 0x4F11, 0xD0DD, 0x4F12, 0x81B5, + 0x4F13, 0x81B6, 0x4F14, 0x81B7, 0x4F15, 0x81B8, 0x4F16, 0x81B9, 0x4F17, 0xD6DA, 0x4F18, 0xD3C5, 0x4F19, 0xBBEF, 0x4F1A, 0xBBE1, + 0x4F1B, 0xD8F1, 0x4F1C, 0x81BA, 0x4F1D, 0x81BB, 0x4F1E, 0xC9A1, 0x4F1F, 0xCEB0, 0x4F20, 0xB4AB, 0x4F21, 0x81BC, 0x4F22, 0xD8F3, + 0x4F23, 0x81BD, 0x4F24, 0xC9CB, 0x4F25, 0xD8F6, 0x4F26, 0xC2D7, 0x4F27, 0xD8F7, 0x4F28, 0x81BE, 0x4F29, 0x81BF, 0x4F2A, 0xCEB1, + 0x4F2B, 0xD8F9, 0x4F2C, 0x81C0, 0x4F2D, 0x81C1, 0x4F2E, 0x81C2, 0x4F2F, 0xB2AE, 0x4F30, 0xB9C0, 0x4F31, 0x81C3, 0x4F32, 0xD9A3, + 0x4F33, 0x81C4, 0x4F34, 0xB0E9, 0x4F35, 0x81C5, 0x4F36, 0xC1E6, 0x4F37, 0x81C6, 0x4F38, 0xC9EC, 0x4F39, 0x81C7, 0x4F3A, 0xCBC5, + 0x4F3B, 0x81C8, 0x4F3C, 0xCBC6, 0x4F3D, 0xD9A4, 0x4F3E, 0x81C9, 0x4F3F, 0x81CA, 0x4F40, 0x81CB, 0x4F41, 0x81CC, 0x4F42, 0x81CD, + 0x4F43, 0xB5E8, 0x4F44, 0x81CE, 0x4F45, 0x81CF, 0x4F46, 0xB5AB, 0x4F47, 0x81D0, 0x4F48, 0x81D1, 0x4F49, 0x81D2, 0x4F4A, 0x81D3, + 0x4F4B, 0x81D4, 0x4F4C, 0x81D5, 0x4F4D, 0xCEBB, 0x4F4E, 0xB5CD, 0x4F4F, 0xD7A1, 0x4F50, 0xD7F4, 0x4F51, 0xD3D3, 0x4F52, 0x81D6, + 0x4F53, 0xCCE5, 0x4F54, 0x81D7, 0x4F55, 0xBACE, 0x4F56, 0x81D8, 0x4F57, 0xD9A2, 0x4F58, 0xD9DC, 0x4F59, 0xD3E0, 0x4F5A, 0xD8FD, + 0x4F5B, 0xB7F0, 0x4F5C, 0xD7F7, 0x4F5D, 0xD8FE, 0x4F5E, 0xD8FA, 0x4F5F, 0xD9A1, 0x4F60, 0xC4E3, 0x4F61, 0x81D9, 0x4F62, 0x81DA, + 0x4F63, 0xD3B6, 0x4F64, 0xD8F4, 0x4F65, 0xD9DD, 0x4F66, 0x81DB, 0x4F67, 0xD8FB, 0x4F68, 0x81DC, 0x4F69, 0xC5E5, 0x4F6A, 0x81DD, + 0x4F6B, 0x81DE, 0x4F6C, 0xC0D0, 0x4F6D, 0x81DF, 0x4F6E, 0x81E0, 0x4F6F, 0xD1F0, 0x4F70, 0xB0DB, 0x4F71, 0x81E1, 0x4F72, 0x81E2, + 0x4F73, 0xBCD1, 0x4F74, 0xD9A6, 0x4F75, 0x81E3, 0x4F76, 0xD9A5, 0x4F77, 0x81E4, 0x4F78, 0x81E5, 0x4F79, 0x81E6, 0x4F7A, 0x81E7, + 0x4F7B, 0xD9AC, 0x4F7C, 0xD9AE, 0x4F7D, 0x81E8, 0x4F7E, 0xD9AB, 0x4F7F, 0xCAB9, 0x4F80, 0x81E9, 0x4F81, 0x81EA, 0x4F82, 0x81EB, + 0x4F83, 0xD9A9, 0x4F84, 0xD6B6, 0x4F85, 0x81EC, 0x4F86, 0x81ED, 0x4F87, 0x81EE, 0x4F88, 0xB3DE, 0x4F89, 0xD9A8, 0x4F8A, 0x81EF, + 0x4F8B, 0xC0FD, 0x4F8C, 0x81F0, 0x4F8D, 0xCACC, 0x4F8E, 0x81F1, 0x4F8F, 0xD9AA, 0x4F90, 0x81F2, 0x4F91, 0xD9A7, 0x4F92, 0x81F3, + 0x4F93, 0x81F4, 0x4F94, 0xD9B0, 0x4F95, 0x81F5, 0x4F96, 0x81F6, 0x4F97, 0xB6B1, 0x4F98, 0x81F7, 0x4F99, 0x81F8, 0x4F9A, 0x81F9, + 0x4F9B, 0xB9A9, 0x4F9C, 0x81FA, 0x4F9D, 0xD2C0, 0x4F9E, 0x81FB, 0x4F9F, 0x81FC, 0x4FA0, 0xCFC0, 0x4FA1, 0x81FD, 0x4FA2, 0x81FE, + 0x4FA3, 0xC2C2, 0x4FA4, 0x8240, 0x4FA5, 0xBDC4, 0x4FA6, 0xD5EC, 0x4FA7, 0xB2E0, 0x4FA8, 0xC7C8, 0x4FA9, 0xBFEB, 0x4FAA, 0xD9AD, + 0x4FAB, 0x8241, 0x4FAC, 0xD9AF, 0x4FAD, 0x8242, 0x4FAE, 0xCEEA, 0x4FAF, 0xBAEE, 0x4FB0, 0x8243, 0x4FB1, 0x8244, 0x4FB2, 0x8245, + 0x4FB3, 0x8246, 0x4FB4, 0x8247, 0x4FB5, 0xC7D6, 0x4FB6, 0x8248, 0x4FB7, 0x8249, 0x4FB8, 0x824A, 0x4FB9, 0x824B, 0x4FBA, 0x824C, + 0x4FBB, 0x824D, 0x4FBC, 0x824E, 0x4FBD, 0x824F, 0x4FBE, 0x8250, 0x4FBF, 0xB1E3, 0x4FC0, 0x8251, 0x4FC1, 0x8252, 0x4FC2, 0x8253, + 0x4FC3, 0xB4D9, 0x4FC4, 0xB6ED, 0x4FC5, 0xD9B4, 0x4FC6, 0x8254, 0x4FC7, 0x8255, 0x4FC8, 0x8256, 0x4FC9, 0x8257, 0x4FCA, 0xBFA1, + 0x4FCB, 0x8258, 0x4FCC, 0x8259, 0x4FCD, 0x825A, 0x4FCE, 0xD9DE, 0x4FCF, 0xC7CE, 0x4FD0, 0xC0FE, 0x4FD1, 0xD9B8, 0x4FD2, 0x825B, + 0x4FD3, 0x825C, 0x4FD4, 0x825D, 0x4FD5, 0x825E, 0x4FD6, 0x825F, 0x4FD7, 0xCBD7, 0x4FD8, 0xB7FD, 0x4FD9, 0x8260, 0x4FDA, 0xD9B5, + 0x4FDB, 0x8261, 0x4FDC, 0xD9B7, 0x4FDD, 0xB1A3, 0x4FDE, 0xD3E1, 0x4FDF, 0xD9B9, 0x4FE0, 0x8262, 0x4FE1, 0xD0C5, 0x4FE2, 0x8263, + 0x4FE3, 0xD9B6, 0x4FE4, 0x8264, 0x4FE5, 0x8265, 0x4FE6, 0xD9B1, 0x4FE7, 0x8266, 0x4FE8, 0xD9B2, 0x4FE9, 0xC1A9, 0x4FEA, 0xD9B3, + 0x4FEB, 0x8267, 0x4FEC, 0x8268, 0x4FED, 0xBCF3, 0x4FEE, 0xD0DE, 0x4FEF, 0xB8A9, 0x4FF0, 0x8269, 0x4FF1, 0xBEE3, 0x4FF2, 0x826A, + 0x4FF3, 0xD9BD, 0x4FF4, 0x826B, 0x4FF5, 0x826C, 0x4FF6, 0x826D, 0x4FF7, 0x826E, 0x4FF8, 0xD9BA, 0x4FF9, 0x826F, 0x4FFA, 0xB0B3, + 0x4FFB, 0x8270, 0x4FFC, 0x8271, 0x4FFD, 0x8272, 0x4FFE, 0xD9C2, 0x4FFF, 0x8273, 0x5000, 0x8274, 0x5001, 0x8275, 0x5002, 0x8276, + 0x5003, 0x8277, 0x5004, 0x8278, 0x5005, 0x8279, 0x5006, 0x827A, 0x5007, 0x827B, 0x5008, 0x827C, 0x5009, 0x827D, 0x500A, 0x827E, + 0x500B, 0x8280, 0x500C, 0xD9C4, 0x500D, 0xB1B6, 0x500E, 0x8281, 0x500F, 0xD9BF, 0x5010, 0x8282, 0x5011, 0x8283, 0x5012, 0xB5B9, + 0x5013, 0x8284, 0x5014, 0xBEF3, 0x5015, 0x8285, 0x5016, 0x8286, 0x5017, 0x8287, 0x5018, 0xCCC8, 0x5019, 0xBAF2, 0x501A, 0xD2D0, + 0x501B, 0x8288, 0x501C, 0xD9C3, 0x501D, 0x8289, 0x501E, 0x828A, 0x501F, 0xBDE8, 0x5020, 0x828B, 0x5021, 0xB3AB, 0x5022, 0x828C, + 0x5023, 0x828D, 0x5024, 0x828E, 0x5025, 0xD9C5, 0x5026, 0xBEEB, 0x5027, 0x828F, 0x5028, 0xD9C6, 0x5029, 0xD9BB, 0x502A, 0xC4DF, + 0x502B, 0x8290, 0x502C, 0xD9BE, 0x502D, 0xD9C1, 0x502E, 0xD9C0, 0x502F, 0x8291, 0x5030, 0x8292, 0x5031, 0x8293, 0x5032, 0x8294, + 0x5033, 0x8295, 0x5034, 0x8296, 0x5035, 0x8297, 0x5036, 0x8298, 0x5037, 0x8299, 0x5038, 0x829A, 0x5039, 0x829B, 0x503A, 0xD5AE, + 0x503B, 0x829C, 0x503C, 0xD6B5, 0x503D, 0x829D, 0x503E, 0xC7E3, 0x503F, 0x829E, 0x5040, 0x829F, 0x5041, 0x82A0, 0x5042, 0x82A1, + 0x5043, 0xD9C8, 0x5044, 0x82A2, 0x5045, 0x82A3, 0x5046, 0x82A4, 0x5047, 0xBCD9, 0x5048, 0xD9CA, 0x5049, 0x82A5, 0x504A, 0x82A6, + 0x504B, 0x82A7, 0x504C, 0xD9BC, 0x504D, 0x82A8, 0x504E, 0xD9CB, 0x504F, 0xC6AB, 0x5050, 0x82A9, 0x5051, 0x82AA, 0x5052, 0x82AB, + 0x5053, 0x82AC, 0x5054, 0x82AD, 0x5055, 0xD9C9, 0x5056, 0x82AE, 0x5057, 0x82AF, 0x5058, 0x82B0, 0x5059, 0x82B1, 0x505A, 0xD7F6, + 0x505B, 0x82B2, 0x505C, 0xCDA3, 0x505D, 0x82B3, 0x505E, 0x82B4, 0x505F, 0x82B5, 0x5060, 0x82B6, 0x5061, 0x82B7, 0x5062, 0x82B8, + 0x5063, 0x82B9, 0x5064, 0x82BA, 0x5065, 0xBDA1, 0x5066, 0x82BB, 0x5067, 0x82BC, 0x5068, 0x82BD, 0x5069, 0x82BE, 0x506A, 0x82BF, + 0x506B, 0x82C0, 0x506C, 0xD9CC, 0x506D, 0x82C1, 0x506E, 0x82C2, 0x506F, 0x82C3, 0x5070, 0x82C4, 0x5071, 0x82C5, 0x5072, 0x82C6, + 0x5073, 0x82C7, 0x5074, 0x82C8, 0x5075, 0x82C9, 0x5076, 0xC5BC, 0x5077, 0xCDB5, 0x5078, 0x82CA, 0x5079, 0x82CB, 0x507A, 0x82CC, + 0x507B, 0xD9CD, 0x507C, 0x82CD, 0x507D, 0x82CE, 0x507E, 0xD9C7, 0x507F, 0xB3A5, 0x5080, 0xBFFE, 0x5081, 0x82CF, 0x5082, 0x82D0, + 0x5083, 0x82D1, 0x5084, 0x82D2, 0x5085, 0xB8B5, 0x5086, 0x82D3, 0x5087, 0x82D4, 0x5088, 0xC0FC, 0x5089, 0x82D5, 0x508A, 0x82D6, + 0x508B, 0x82D7, 0x508C, 0x82D8, 0x508D, 0xB0F8, 0x508E, 0x82D9, 0x508F, 0x82DA, 0x5090, 0x82DB, 0x5091, 0x82DC, 0x5092, 0x82DD, + 0x5093, 0x82DE, 0x5094, 0x82DF, 0x5095, 0x82E0, 0x5096, 0x82E1, 0x5097, 0x82E2, 0x5098, 0x82E3, 0x5099, 0x82E4, 0x509A, 0x82E5, + 0x509B, 0x82E6, 0x509C, 0x82E7, 0x509D, 0x82E8, 0x509E, 0x82E9, 0x509F, 0x82EA, 0x50A0, 0x82EB, 0x50A1, 0x82EC, 0x50A2, 0x82ED, + 0x50A3, 0xB4F6, 0x50A4, 0x82EE, 0x50A5, 0xD9CE, 0x50A6, 0x82EF, 0x50A7, 0xD9CF, 0x50A8, 0xB4A2, 0x50A9, 0xD9D0, 0x50AA, 0x82F0, + 0x50AB, 0x82F1, 0x50AC, 0xB4DF, 0x50AD, 0x82F2, 0x50AE, 0x82F3, 0x50AF, 0x82F4, 0x50B0, 0x82F5, 0x50B1, 0x82F6, 0x50B2, 0xB0C1, + 0x50B3, 0x82F7, 0x50B4, 0x82F8, 0x50B5, 0x82F9, 0x50B6, 0x82FA, 0x50B7, 0x82FB, 0x50B8, 0x82FC, 0x50B9, 0x82FD, 0x50BA, 0xD9D1, + 0x50BB, 0xC9B5, 0x50BC, 0x82FE, 0x50BD, 0x8340, 0x50BE, 0x8341, 0x50BF, 0x8342, 0x50C0, 0x8343, 0x50C1, 0x8344, 0x50C2, 0x8345, + 0x50C3, 0x8346, 0x50C4, 0x8347, 0x50C5, 0x8348, 0x50C6, 0x8349, 0x50C7, 0x834A, 0x50C8, 0x834B, 0x50C9, 0x834C, 0x50CA, 0x834D, + 0x50CB, 0x834E, 0x50CC, 0x834F, 0x50CD, 0x8350, 0x50CE, 0x8351, 0x50CF, 0xCFF1, 0x50D0, 0x8352, 0x50D1, 0x8353, 0x50D2, 0x8354, + 0x50D3, 0x8355, 0x50D4, 0x8356, 0x50D5, 0x8357, 0x50D6, 0xD9D2, 0x50D7, 0x8358, 0x50D8, 0x8359, 0x50D9, 0x835A, 0x50DA, 0xC1C5, + 0x50DB, 0x835B, 0x50DC, 0x835C, 0x50DD, 0x835D, 0x50DE, 0x835E, 0x50DF, 0x835F, 0x50E0, 0x8360, 0x50E1, 0x8361, 0x50E2, 0x8362, + 0x50E3, 0x8363, 0x50E4, 0x8364, 0x50E5, 0x8365, 0x50E6, 0xD9D6, 0x50E7, 0xC9AE, 0x50E8, 0x8366, 0x50E9, 0x8367, 0x50EA, 0x8368, + 0x50EB, 0x8369, 0x50EC, 0xD9D5, 0x50ED, 0xD9D4, 0x50EE, 0xD9D7, 0x50EF, 0x836A, 0x50F0, 0x836B, 0x50F1, 0x836C, 0x50F2, 0x836D, + 0x50F3, 0xCBDB, 0x50F4, 0x836E, 0x50F5, 0xBDA9, 0x50F6, 0x836F, 0x50F7, 0x8370, 0x50F8, 0x8371, 0x50F9, 0x8372, 0x50FA, 0x8373, + 0x50FB, 0xC6A7, 0x50FC, 0x8374, 0x50FD, 0x8375, 0x50FE, 0x8376, 0x50FF, 0x8377, 0x5100, 0x8378, 0x5101, 0x8379, 0x5102, 0x837A, + 0x5103, 0x837B, 0x5104, 0x837C, 0x5105, 0x837D, 0x5106, 0xD9D3, 0x5107, 0xD9D8, 0x5108, 0x837E, 0x5109, 0x8380, 0x510A, 0x8381, + 0x510B, 0xD9D9, 0x510C, 0x8382, 0x510D, 0x8383, 0x510E, 0x8384, 0x510F, 0x8385, 0x5110, 0x8386, 0x5111, 0x8387, 0x5112, 0xC8E5, + 0x5113, 0x8388, 0x5114, 0x8389, 0x5115, 0x838A, 0x5116, 0x838B, 0x5117, 0x838C, 0x5118, 0x838D, 0x5119, 0x838E, 0x511A, 0x838F, + 0x511B, 0x8390, 0x511C, 0x8391, 0x511D, 0x8392, 0x511E, 0x8393, 0x511F, 0x8394, 0x5120, 0x8395, 0x5121, 0xC0DC, 0x5122, 0x8396, + 0x5123, 0x8397, 0x5124, 0x8398, 0x5125, 0x8399, 0x5126, 0x839A, 0x5127, 0x839B, 0x5128, 0x839C, 0x5129, 0x839D, 0x512A, 0x839E, + 0x512B, 0x839F, 0x512C, 0x83A0, 0x512D, 0x83A1, 0x512E, 0x83A2, 0x512F, 0x83A3, 0x5130, 0x83A4, 0x5131, 0x83A5, 0x5132, 0x83A6, + 0x5133, 0x83A7, 0x5134, 0x83A8, 0x5135, 0x83A9, 0x5136, 0x83AA, 0x5137, 0x83AB, 0x5138, 0x83AC, 0x5139, 0x83AD, 0x513A, 0x83AE, + 0x513B, 0x83AF, 0x513C, 0x83B0, 0x513D, 0x83B1, 0x513E, 0x83B2, 0x513F, 0xB6F9, 0x5140, 0xD8A3, 0x5141, 0xD4CA, 0x5142, 0x83B3, + 0x5143, 0xD4AA, 0x5144, 0xD0D6, 0x5145, 0xB3E4, 0x5146, 0xD5D7, 0x5147, 0x83B4, 0x5148, 0xCFC8, 0x5149, 0xB9E2, 0x514A, 0x83B5, + 0x514B, 0xBFCB, 0x514C, 0x83B6, 0x514D, 0xC3E2, 0x514E, 0x83B7, 0x514F, 0x83B8, 0x5150, 0x83B9, 0x5151, 0xB6D2, 0x5152, 0x83BA, + 0x5153, 0x83BB, 0x5154, 0xCDC3, 0x5155, 0xD9EE, 0x5156, 0xD9F0, 0x5157, 0x83BC, 0x5158, 0x83BD, 0x5159, 0x83BE, 0x515A, 0xB5B3, + 0x515B, 0x83BF, 0x515C, 0xB6B5, 0x515D, 0x83C0, 0x515E, 0x83C1, 0x515F, 0x83C2, 0x5160, 0x83C3, 0x5161, 0x83C4, 0x5162, 0xBEA4, + 0x5163, 0x83C5, 0x5164, 0x83C6, 0x5165, 0xC8EB, 0x5166, 0x83C7, 0x5167, 0x83C8, 0x5168, 0xC8AB, 0x5169, 0x83C9, 0x516A, 0x83CA, + 0x516B, 0xB0CB, 0x516C, 0xB9AB, 0x516D, 0xC1F9, 0x516E, 0xD9E2, 0x516F, 0x83CB, 0x5170, 0xC0BC, 0x5171, 0xB9B2, 0x5172, 0x83CC, + 0x5173, 0xB9D8, 0x5174, 0xD0CB, 0x5175, 0xB1F8, 0x5176, 0xC6E4, 0x5177, 0xBEDF, 0x5178, 0xB5E4, 0x5179, 0xD7C8, 0x517A, 0x83CD, + 0x517B, 0xD1F8, 0x517C, 0xBCE6, 0x517D, 0xCADE, 0x517E, 0x83CE, 0x517F, 0x83CF, 0x5180, 0xBCBD, 0x5181, 0xD9E6, 0x5182, 0xD8E7, + 0x5183, 0x83D0, 0x5184, 0x83D1, 0x5185, 0xC4DA, 0x5186, 0x83D2, 0x5187, 0x83D3, 0x5188, 0xB8D4, 0x5189, 0xC8BD, 0x518A, 0x83D4, + 0x518B, 0x83D5, 0x518C, 0xB2E1, 0x518D, 0xD4D9, 0x518E, 0x83D6, 0x518F, 0x83D7, 0x5190, 0x83D8, 0x5191, 0x83D9, 0x5192, 0xC3B0, + 0x5193, 0x83DA, 0x5194, 0x83DB, 0x5195, 0xC3E1, 0x5196, 0xDAA2, 0x5197, 0xC8DF, 0x5198, 0x83DC, 0x5199, 0xD0B4, 0x519A, 0x83DD, + 0x519B, 0xBEFC, 0x519C, 0xC5A9, 0x519D, 0x83DE, 0x519E, 0x83DF, 0x519F, 0x83E0, 0x51A0, 0xB9DA, 0x51A1, 0x83E1, 0x51A2, 0xDAA3, + 0x51A3, 0x83E2, 0x51A4, 0xD4A9, 0x51A5, 0xDAA4, 0x51A6, 0x83E3, 0x51A7, 0x83E4, 0x51A8, 0x83E5, 0x51A9, 0x83E6, 0x51AA, 0x83E7, + 0x51AB, 0xD9FB, 0x51AC, 0xB6AC, 0x51AD, 0x83E8, 0x51AE, 0x83E9, 0x51AF, 0xB7EB, 0x51B0, 0xB1F9, 0x51B1, 0xD9FC, 0x51B2, 0xB3E5, + 0x51B3, 0xBEF6, 0x51B4, 0x83EA, 0x51B5, 0xBFF6, 0x51B6, 0xD2B1, 0x51B7, 0xC0E4, 0x51B8, 0x83EB, 0x51B9, 0x83EC, 0x51BA, 0x83ED, + 0x51BB, 0xB6B3, 0x51BC, 0xD9FE, 0x51BD, 0xD9FD, 0x51BE, 0x83EE, 0x51BF, 0x83EF, 0x51C0, 0xBEBB, 0x51C1, 0x83F0, 0x51C2, 0x83F1, + 0x51C3, 0x83F2, 0x51C4, 0xC6E0, 0x51C5, 0x83F3, 0x51C6, 0xD7BC, 0x51C7, 0xDAA1, 0x51C8, 0x83F4, 0x51C9, 0xC1B9, 0x51CA, 0x83F5, + 0x51CB, 0xB5F2, 0x51CC, 0xC1E8, 0x51CD, 0x83F6, 0x51CE, 0x83F7, 0x51CF, 0xBCF5, 0x51D0, 0x83F8, 0x51D1, 0xB4D5, 0x51D2, 0x83F9, + 0x51D3, 0x83FA, 0x51D4, 0x83FB, 0x51D5, 0x83FC, 0x51D6, 0x83FD, 0x51D7, 0x83FE, 0x51D8, 0x8440, 0x51D9, 0x8441, 0x51DA, 0x8442, + 0x51DB, 0xC1DD, 0x51DC, 0x8443, 0x51DD, 0xC4FD, 0x51DE, 0x8444, 0x51DF, 0x8445, 0x51E0, 0xBCB8, 0x51E1, 0xB7B2, 0x51E2, 0x8446, + 0x51E3, 0x8447, 0x51E4, 0xB7EF, 0x51E5, 0x8448, 0x51E6, 0x8449, 0x51E7, 0x844A, 0x51E8, 0x844B, 0x51E9, 0x844C, 0x51EA, 0x844D, + 0x51EB, 0xD9EC, 0x51EC, 0x844E, 0x51ED, 0xC6BE, 0x51EE, 0x844F, 0x51EF, 0xBFAD, 0x51F0, 0xBBCB, 0x51F1, 0x8450, 0x51F2, 0x8451, + 0x51F3, 0xB5CA, 0x51F4, 0x8452, 0x51F5, 0xDBC9, 0x51F6, 0xD0D7, 0x51F7, 0x8453, 0x51F8, 0xCDB9, 0x51F9, 0xB0BC, 0x51FA, 0xB3F6, + 0x51FB, 0xBBF7, 0x51FC, 0xDBCA, 0x51FD, 0xBAAF, 0x51FE, 0x8454, 0x51FF, 0xD4E4, 0x5200, 0xB5B6, 0x5201, 0xB5F3, 0x5202, 0xD8D6, + 0x5203, 0xC8D0, 0x5204, 0x8455, 0x5205, 0x8456, 0x5206, 0xB7D6, 0x5207, 0xC7D0, 0x5208, 0xD8D7, 0x5209, 0x8457, 0x520A, 0xBFAF, + 0x520B, 0x8458, 0x520C, 0x8459, 0x520D, 0xDBBB, 0x520E, 0xD8D8, 0x520F, 0x845A, 0x5210, 0x845B, 0x5211, 0xD0CC, 0x5212, 0xBBAE, + 0x5213, 0x845C, 0x5214, 0x845D, 0x5215, 0x845E, 0x5216, 0xEBBE, 0x5217, 0xC1D0, 0x5218, 0xC1F5, 0x5219, 0xD4F2, 0x521A, 0xB8D5, + 0x521B, 0xB4B4, 0x521C, 0x845F, 0x521D, 0xB3F5, 0x521E, 0x8460, 0x521F, 0x8461, 0x5220, 0xC9BE, 0x5221, 0x8462, 0x5222, 0x8463, + 0x5223, 0x8464, 0x5224, 0xC5D0, 0x5225, 0x8465, 0x5226, 0x8466, 0x5227, 0x8467, 0x5228, 0xC5D9, 0x5229, 0xC0FB, 0x522A, 0x8468, + 0x522B, 0xB1F0, 0x522C, 0x8469, 0x522D, 0xD8D9, 0x522E, 0xB9CE, 0x522F, 0x846A, 0x5230, 0xB5BD, 0x5231, 0x846B, 0x5232, 0x846C, + 0x5233, 0xD8DA, 0x5234, 0x846D, 0x5235, 0x846E, 0x5236, 0xD6C6, 0x5237, 0xCBA2, 0x5238, 0xC8AF, 0x5239, 0xC9B2, 0x523A, 0xB4CC, + 0x523B, 0xBFCC, 0x523C, 0x846F, 0x523D, 0xB9F4, 0x523E, 0x8470, 0x523F, 0xD8DB, 0x5240, 0xD8DC, 0x5241, 0xB6E7, 0x5242, 0xBCC1, + 0x5243, 0xCCEA, 0x5244, 0x8471, 0x5245, 0x8472, 0x5246, 0x8473, 0x5247, 0x8474, 0x5248, 0x8475, 0x5249, 0x8476, 0x524A, 0xCFF7, + 0x524B, 0x8477, 0x524C, 0xD8DD, 0x524D, 0xC7B0, 0x524E, 0x8478, 0x524F, 0x8479, 0x5250, 0xB9D0, 0x5251, 0xBDA3, 0x5252, 0x847A, + 0x5253, 0x847B, 0x5254, 0xCCDE, 0x5255, 0x847C, 0x5256, 0xC6CA, 0x5257, 0x847D, 0x5258, 0x847E, 0x5259, 0x8480, 0x525A, 0x8481, + 0x525B, 0x8482, 0x525C, 0xD8E0, 0x525D, 0x8483, 0x525E, 0xD8DE, 0x525F, 0x8484, 0x5260, 0x8485, 0x5261, 0xD8DF, 0x5262, 0x8486, + 0x5263, 0x8487, 0x5264, 0x8488, 0x5265, 0xB0FE, 0x5266, 0x8489, 0x5267, 0xBEE7, 0x5268, 0x848A, 0x5269, 0xCAA3, 0x526A, 0xBCF4, + 0x526B, 0x848B, 0x526C, 0x848C, 0x526D, 0x848D, 0x526E, 0x848E, 0x526F, 0xB8B1, 0x5270, 0x848F, 0x5271, 0x8490, 0x5272, 0xB8EE, + 0x5273, 0x8491, 0x5274, 0x8492, 0x5275, 0x8493, 0x5276, 0x8494, 0x5277, 0x8495, 0x5278, 0x8496, 0x5279, 0x8497, 0x527A, 0x8498, + 0x527B, 0x8499, 0x527C, 0x849A, 0x527D, 0xD8E2, 0x527E, 0x849B, 0x527F, 0xBDCB, 0x5280, 0x849C, 0x5281, 0xD8E4, 0x5282, 0xD8E3, + 0x5283, 0x849D, 0x5284, 0x849E, 0x5285, 0x849F, 0x5286, 0x84A0, 0x5287, 0x84A1, 0x5288, 0xC5FC, 0x5289, 0x84A2, 0x528A, 0x84A3, + 0x528B, 0x84A4, 0x528C, 0x84A5, 0x528D, 0x84A6, 0x528E, 0x84A7, 0x528F, 0x84A8, 0x5290, 0xD8E5, 0x5291, 0x84A9, 0x5292, 0x84AA, + 0x5293, 0xD8E6, 0x5294, 0x84AB, 0x5295, 0x84AC, 0x5296, 0x84AD, 0x5297, 0x84AE, 0x5298, 0x84AF, 0x5299, 0x84B0, 0x529A, 0x84B1, + 0x529B, 0xC1A6, 0x529C, 0x84B2, 0x529D, 0xC8B0, 0x529E, 0xB0EC, 0x529F, 0xB9A6, 0x52A0, 0xBCD3, 0x52A1, 0xCEF1, 0x52A2, 0xDBBD, + 0x52A3, 0xC1D3, 0x52A4, 0x84B3, 0x52A5, 0x84B4, 0x52A6, 0x84B5, 0x52A7, 0x84B6, 0x52A8, 0xB6AF, 0x52A9, 0xD6FA, 0x52AA, 0xC5AC, + 0x52AB, 0xBDD9, 0x52AC, 0xDBBE, 0x52AD, 0xDBBF, 0x52AE, 0x84B7, 0x52AF, 0x84B8, 0x52B0, 0x84B9, 0x52B1, 0xC0F8, 0x52B2, 0xBEA2, + 0x52B3, 0xC0CD, 0x52B4, 0x84BA, 0x52B5, 0x84BB, 0x52B6, 0x84BC, 0x52B7, 0x84BD, 0x52B8, 0x84BE, 0x52B9, 0x84BF, 0x52BA, 0x84C0, + 0x52BB, 0x84C1, 0x52BC, 0x84C2, 0x52BD, 0x84C3, 0x52BE, 0xDBC0, 0x52BF, 0xCAC6, 0x52C0, 0x84C4, 0x52C1, 0x84C5, 0x52C2, 0x84C6, + 0x52C3, 0xB2AA, 0x52C4, 0x84C7, 0x52C5, 0x84C8, 0x52C6, 0x84C9, 0x52C7, 0xD3C2, 0x52C8, 0x84CA, 0x52C9, 0xC3E3, 0x52CA, 0x84CB, + 0x52CB, 0xD1AB, 0x52CC, 0x84CC, 0x52CD, 0x84CD, 0x52CE, 0x84CE, 0x52CF, 0x84CF, 0x52D0, 0xDBC2, 0x52D1, 0x84D0, 0x52D2, 0xC0D5, + 0x52D3, 0x84D1, 0x52D4, 0x84D2, 0x52D5, 0x84D3, 0x52D6, 0xDBC3, 0x52D7, 0x84D4, 0x52D8, 0xBFB1, 0x52D9, 0x84D5, 0x52DA, 0x84D6, + 0x52DB, 0x84D7, 0x52DC, 0x84D8, 0x52DD, 0x84D9, 0x52DE, 0x84DA, 0x52DF, 0xC4BC, 0x52E0, 0x84DB, 0x52E1, 0x84DC, 0x52E2, 0x84DD, + 0x52E3, 0x84DE, 0x52E4, 0xC7DA, 0x52E5, 0x84DF, 0x52E6, 0x84E0, 0x52E7, 0x84E1, 0x52E8, 0x84E2, 0x52E9, 0x84E3, 0x52EA, 0x84E4, + 0x52EB, 0x84E5, 0x52EC, 0x84E6, 0x52ED, 0x84E7, 0x52EE, 0x84E8, 0x52EF, 0x84E9, 0x52F0, 0xDBC4, 0x52F1, 0x84EA, 0x52F2, 0x84EB, + 0x52F3, 0x84EC, 0x52F4, 0x84ED, 0x52F5, 0x84EE, 0x52F6, 0x84EF, 0x52F7, 0x84F0, 0x52F8, 0x84F1, 0x52F9, 0xD9E8, 0x52FA, 0xC9D7, + 0x52FB, 0x84F2, 0x52FC, 0x84F3, 0x52FD, 0x84F4, 0x52FE, 0xB9B4, 0x52FF, 0xCEF0, 0x5300, 0xD4C8, 0x5301, 0x84F5, 0x5302, 0x84F6, + 0x5303, 0x84F7, 0x5304, 0x84F8, 0x5305, 0xB0FC, 0x5306, 0xB4D2, 0x5307, 0x84F9, 0x5308, 0xD0D9, 0x5309, 0x84FA, 0x530A, 0x84FB, + 0x530B, 0x84FC, 0x530C, 0x84FD, 0x530D, 0xD9E9, 0x530E, 0x84FE, 0x530F, 0xDECB, 0x5310, 0xD9EB, 0x5311, 0x8540, 0x5312, 0x8541, + 0x5313, 0x8542, 0x5314, 0x8543, 0x5315, 0xD8B0, 0x5316, 0xBBAF, 0x5317, 0xB1B1, 0x5318, 0x8544, 0x5319, 0xB3D7, 0x531A, 0xD8CE, + 0x531B, 0x8545, 0x531C, 0x8546, 0x531D, 0xD4D1, 0x531E, 0x8547, 0x531F, 0x8548, 0x5320, 0xBDB3, 0x5321, 0xBFEF, 0x5322, 0x8549, + 0x5323, 0xCFBB, 0x5324, 0x854A, 0x5325, 0x854B, 0x5326, 0xD8D0, 0x5327, 0x854C, 0x5328, 0x854D, 0x5329, 0x854E, 0x532A, 0xB7CB, + 0x532B, 0x854F, 0x532C, 0x8550, 0x532D, 0x8551, 0x532E, 0xD8D1, 0x532F, 0x8552, 0x5330, 0x8553, 0x5331, 0x8554, 0x5332, 0x8555, + 0x5333, 0x8556, 0x5334, 0x8557, 0x5335, 0x8558, 0x5336, 0x8559, 0x5337, 0x855A, 0x5338, 0x855B, 0x5339, 0xC6A5, 0x533A, 0xC7F8, + 0x533B, 0xD2BD, 0x533C, 0x855C, 0x533D, 0x855D, 0x533E, 0xD8D2, 0x533F, 0xC4E4, 0x5340, 0x855E, 0x5341, 0xCAAE, 0x5342, 0x855F, + 0x5343, 0xC7A7, 0x5344, 0x8560, 0x5345, 0xD8A6, 0x5346, 0x8561, 0x5347, 0xC9FD, 0x5348, 0xCEE7, 0x5349, 0xBBDC, 0x534A, 0xB0EB, + 0x534B, 0x8562, 0x534C, 0x8563, 0x534D, 0x8564, 0x534E, 0xBBAA, 0x534F, 0xD0AD, 0x5350, 0x8565, 0x5351, 0xB1B0, 0x5352, 0xD7E4, + 0x5353, 0xD7BF, 0x5354, 0x8566, 0x5355, 0xB5A5, 0x5356, 0xC2F4, 0x5357, 0xC4CF, 0x5358, 0x8567, 0x5359, 0x8568, 0x535A, 0xB2A9, + 0x535B, 0x8569, 0x535C, 0xB2B7, 0x535D, 0x856A, 0x535E, 0xB1E5, 0x535F, 0xDFB2, 0x5360, 0xD5BC, 0x5361, 0xBFA8, 0x5362, 0xC2AC, + 0x5363, 0xD8D5, 0x5364, 0xC2B1, 0x5365, 0x856B, 0x5366, 0xD8D4, 0x5367, 0xCED4, 0x5368, 0x856C, 0x5369, 0xDAE0, 0x536A, 0x856D, + 0x536B, 0xCEC0, 0x536C, 0x856E, 0x536D, 0x856F, 0x536E, 0xD8B4, 0x536F, 0xC3AE, 0x5370, 0xD3A1, 0x5371, 0xCEA3, 0x5372, 0x8570, + 0x5373, 0xBCB4, 0x5374, 0xC8B4, 0x5375, 0xC2D1, 0x5376, 0x8571, 0x5377, 0xBEED, 0x5378, 0xD0B6, 0x5379, 0x8572, 0x537A, 0xDAE1, + 0x537B, 0x8573, 0x537C, 0x8574, 0x537D, 0x8575, 0x537E, 0x8576, 0x537F, 0xC7E4, 0x5380, 0x8577, 0x5381, 0x8578, 0x5382, 0xB3A7, + 0x5383, 0x8579, 0x5384, 0xB6F2, 0x5385, 0xCCFC, 0x5386, 0xC0FA, 0x5387, 0x857A, 0x5388, 0x857B, 0x5389, 0xC0F7, 0x538A, 0x857C, + 0x538B, 0xD1B9, 0x538C, 0xD1E1, 0x538D, 0xD8C7, 0x538E, 0x857D, 0x538F, 0x857E, 0x5390, 0x8580, 0x5391, 0x8581, 0x5392, 0x8582, + 0x5393, 0x8583, 0x5394, 0x8584, 0x5395, 0xB2DE, 0x5396, 0x8585, 0x5397, 0x8586, 0x5398, 0xC0E5, 0x5399, 0x8587, 0x539A, 0xBAF1, + 0x539B, 0x8588, 0x539C, 0x8589, 0x539D, 0xD8C8, 0x539E, 0x858A, 0x539F, 0xD4AD, 0x53A0, 0x858B, 0x53A1, 0x858C, 0x53A2, 0xCFE1, + 0x53A3, 0xD8C9, 0x53A4, 0x858D, 0x53A5, 0xD8CA, 0x53A6, 0xCFC3, 0x53A7, 0x858E, 0x53A8, 0xB3F8, 0x53A9, 0xBEC7, 0x53AA, 0x858F, + 0x53AB, 0x8590, 0x53AC, 0x8591, 0x53AD, 0x8592, 0x53AE, 0xD8CB, 0x53AF, 0x8593, 0x53B0, 0x8594, 0x53B1, 0x8595, 0x53B2, 0x8596, + 0x53B3, 0x8597, 0x53B4, 0x8598, 0x53B5, 0x8599, 0x53B6, 0xDBCC, 0x53B7, 0x859A, 0x53B8, 0x859B, 0x53B9, 0x859C, 0x53BA, 0x859D, + 0x53BB, 0xC8A5, 0x53BC, 0x859E, 0x53BD, 0x859F, 0x53BE, 0x85A0, 0x53BF, 0xCFD8, 0x53C0, 0x85A1, 0x53C1, 0xC8FE, 0x53C2, 0xB2CE, + 0x53C3, 0x85A2, 0x53C4, 0x85A3, 0x53C5, 0x85A4, 0x53C6, 0x85A5, 0x53C7, 0x85A6, 0x53C8, 0xD3D6, 0x53C9, 0xB2E6, 0x53CA, 0xBCB0, + 0x53CB, 0xD3D1, 0x53CC, 0xCBAB, 0x53CD, 0xB7B4, 0x53CE, 0x85A7, 0x53CF, 0x85A8, 0x53D0, 0x85A9, 0x53D1, 0xB7A2, 0x53D2, 0x85AA, + 0x53D3, 0x85AB, 0x53D4, 0xCAE5, 0x53D5, 0x85AC, 0x53D6, 0xC8A1, 0x53D7, 0xCADC, 0x53D8, 0xB1E4, 0x53D9, 0xD0F0, 0x53DA, 0x85AD, + 0x53DB, 0xC5D1, 0x53DC, 0x85AE, 0x53DD, 0x85AF, 0x53DE, 0x85B0, 0x53DF, 0xDBC5, 0x53E0, 0xB5FE, 0x53E1, 0x85B1, 0x53E2, 0x85B2, + 0x53E3, 0xBFDA, 0x53E4, 0xB9C5, 0x53E5, 0xBEE4, 0x53E6, 0xC1ED, 0x53E7, 0x85B3, 0x53E8, 0xDFB6, 0x53E9, 0xDFB5, 0x53EA, 0xD6BB, + 0x53EB, 0xBDD0, 0x53EC, 0xD5D9, 0x53ED, 0xB0C8, 0x53EE, 0xB6A3, 0x53EF, 0xBFC9, 0x53F0, 0xCCA8, 0x53F1, 0xDFB3, 0x53F2, 0xCAB7, + 0x53F3, 0xD3D2, 0x53F4, 0x85B4, 0x53F5, 0xD8CF, 0x53F6, 0xD2B6, 0x53F7, 0xBAC5, 0x53F8, 0xCBBE, 0x53F9, 0xCCBE, 0x53FA, 0x85B5, + 0x53FB, 0xDFB7, 0x53FC, 0xB5F0, 0x53FD, 0xDFB4, 0x53FE, 0x85B6, 0x53FF, 0x85B7, 0x5400, 0x85B8, 0x5401, 0xD3F5, 0x5402, 0x85B9, + 0x5403, 0xB3D4, 0x5404, 0xB8F7, 0x5405, 0x85BA, 0x5406, 0xDFBA, 0x5407, 0x85BB, 0x5408, 0xBACF, 0x5409, 0xBCAA, 0x540A, 0xB5F5, + 0x540B, 0x85BC, 0x540C, 0xCDAC, 0x540D, 0xC3FB, 0x540E, 0xBAF3, 0x540F, 0xC0F4, 0x5410, 0xCDC2, 0x5411, 0xCFF2, 0x5412, 0xDFB8, + 0x5413, 0xCFC5, 0x5414, 0x85BD, 0x5415, 0xC2C0, 0x5416, 0xDFB9, 0x5417, 0xC2F0, 0x5418, 0x85BE, 0x5419, 0x85BF, 0x541A, 0x85C0, + 0x541B, 0xBEFD, 0x541C, 0x85C1, 0x541D, 0xC1DF, 0x541E, 0xCDCC, 0x541F, 0xD2F7, 0x5420, 0xB7CD, 0x5421, 0xDFC1, 0x5422, 0x85C2, + 0x5423, 0xDFC4, 0x5424, 0x85C3, 0x5425, 0x85C4, 0x5426, 0xB7F1, 0x5427, 0xB0C9, 0x5428, 0xB6D6, 0x5429, 0xB7D4, 0x542A, 0x85C5, + 0x542B, 0xBAAC, 0x542C, 0xCCFD, 0x542D, 0xBFD4, 0x542E, 0xCBB1, 0x542F, 0xC6F4, 0x5430, 0x85C6, 0x5431, 0xD6A8, 0x5432, 0xDFC5, + 0x5433, 0x85C7, 0x5434, 0xCEE2, 0x5435, 0xB3B3, 0x5436, 0x85C8, 0x5437, 0x85C9, 0x5438, 0xCEFC, 0x5439, 0xB4B5, 0x543A, 0x85CA, + 0x543B, 0xCEC7, 0x543C, 0xBAF0, 0x543D, 0x85CB, 0x543E, 0xCEE1, 0x543F, 0x85CC, 0x5440, 0xD1BD, 0x5441, 0x85CD, 0x5442, 0x85CE, + 0x5443, 0xDFC0, 0x5444, 0x85CF, 0x5445, 0x85D0, 0x5446, 0xB4F4, 0x5447, 0x85D1, 0x5448, 0xB3CA, 0x5449, 0x85D2, 0x544A, 0xB8E6, + 0x544B, 0xDFBB, 0x544C, 0x85D3, 0x544D, 0x85D4, 0x544E, 0x85D5, 0x544F, 0x85D6, 0x5450, 0xC4C5, 0x5451, 0x85D7, 0x5452, 0xDFBC, + 0x5453, 0xDFBD, 0x5454, 0xDFBE, 0x5455, 0xC5BB, 0x5456, 0xDFBF, 0x5457, 0xDFC2, 0x5458, 0xD4B1, 0x5459, 0xDFC3, 0x545A, 0x85D8, + 0x545B, 0xC7BA, 0x545C, 0xCED8, 0x545D, 0x85D9, 0x545E, 0x85DA, 0x545F, 0x85DB, 0x5460, 0x85DC, 0x5461, 0x85DD, 0x5462, 0xC4D8, + 0x5463, 0x85DE, 0x5464, 0xDFCA, 0x5465, 0x85DF, 0x5466, 0xDFCF, 0x5467, 0x85E0, 0x5468, 0xD6DC, 0x5469, 0x85E1, 0x546A, 0x85E2, + 0x546B, 0x85E3, 0x546C, 0x85E4, 0x546D, 0x85E5, 0x546E, 0x85E6, 0x546F, 0x85E7, 0x5470, 0x85E8, 0x5471, 0xDFC9, 0x5472, 0xDFDA, + 0x5473, 0xCEB6, 0x5474, 0x85E9, 0x5475, 0xBAC7, 0x5476, 0xDFCE, 0x5477, 0xDFC8, 0x5478, 0xC5DE, 0x5479, 0x85EA, 0x547A, 0x85EB, + 0x547B, 0xC9EB, 0x547C, 0xBAF4, 0x547D, 0xC3FC, 0x547E, 0x85EC, 0x547F, 0x85ED, 0x5480, 0xBED7, 0x5481, 0x85EE, 0x5482, 0xDFC6, + 0x5483, 0x85EF, 0x5484, 0xDFCD, 0x5485, 0x85F0, 0x5486, 0xC5D8, 0x5487, 0x85F1, 0x5488, 0x85F2, 0x5489, 0x85F3, 0x548A, 0x85F4, + 0x548B, 0xD5A6, 0x548C, 0xBACD, 0x548D, 0x85F5, 0x548E, 0xBECC, 0x548F, 0xD3BD, 0x5490, 0xB8C0, 0x5491, 0x85F6, 0x5492, 0xD6E4, + 0x5493, 0x85F7, 0x5494, 0xDFC7, 0x5495, 0xB9BE, 0x5496, 0xBFA7, 0x5497, 0x85F8, 0x5498, 0x85F9, 0x5499, 0xC1FC, 0x549A, 0xDFCB, + 0x549B, 0xDFCC, 0x549C, 0x85FA, 0x549D, 0xDFD0, 0x549E, 0x85FB, 0x549F, 0x85FC, 0x54A0, 0x85FD, 0x54A1, 0x85FE, 0x54A2, 0x8640, + 0x54A3, 0xDFDB, 0x54A4, 0xDFE5, 0x54A5, 0x8641, 0x54A6, 0xDFD7, 0x54A7, 0xDFD6, 0x54A8, 0xD7C9, 0x54A9, 0xDFE3, 0x54AA, 0xDFE4, + 0x54AB, 0xE5EB, 0x54AC, 0xD2A7, 0x54AD, 0xDFD2, 0x54AE, 0x8642, 0x54AF, 0xBFA9, 0x54B0, 0x8643, 0x54B1, 0xD4DB, 0x54B2, 0x8644, + 0x54B3, 0xBFC8, 0x54B4, 0xDFD4, 0x54B5, 0x8645, 0x54B6, 0x8646, 0x54B7, 0x8647, 0x54B8, 0xCFCC, 0x54B9, 0x8648, 0x54BA, 0x8649, + 0x54BB, 0xDFDD, 0x54BC, 0x864A, 0x54BD, 0xD1CA, 0x54BE, 0x864B, 0x54BF, 0xDFDE, 0x54C0, 0xB0A7, 0x54C1, 0xC6B7, 0x54C2, 0xDFD3, + 0x54C3, 0x864C, 0x54C4, 0xBAE5, 0x54C5, 0x864D, 0x54C6, 0xB6DF, 0x54C7, 0xCDDB, 0x54C8, 0xB9FE, 0x54C9, 0xD4D5, 0x54CA, 0x864E, + 0x54CB, 0x864F, 0x54CC, 0xDFDF, 0x54CD, 0xCFEC, 0x54CE, 0xB0A5, 0x54CF, 0xDFE7, 0x54D0, 0xDFD1, 0x54D1, 0xD1C6, 0x54D2, 0xDFD5, + 0x54D3, 0xDFD8, 0x54D4, 0xDFD9, 0x54D5, 0xDFDC, 0x54D6, 0x8650, 0x54D7, 0xBBA9, 0x54D8, 0x8651, 0x54D9, 0xDFE0, 0x54DA, 0xDFE1, + 0x54DB, 0x8652, 0x54DC, 0xDFE2, 0x54DD, 0xDFE6, 0x54DE, 0xDFE8, 0x54DF, 0xD3B4, 0x54E0, 0x8653, 0x54E1, 0x8654, 0x54E2, 0x8655, + 0x54E3, 0x8656, 0x54E4, 0x8657, 0x54E5, 0xB8E7, 0x54E6, 0xC5B6, 0x54E7, 0xDFEA, 0x54E8, 0xC9DA, 0x54E9, 0xC1A8, 0x54EA, 0xC4C4, + 0x54EB, 0x8658, 0x54EC, 0x8659, 0x54ED, 0xBFDE, 0x54EE, 0xCFF8, 0x54EF, 0x865A, 0x54F0, 0x865B, 0x54F1, 0x865C, 0x54F2, 0xD5DC, + 0x54F3, 0xDFEE, 0x54F4, 0x865D, 0x54F5, 0x865E, 0x54F6, 0x865F, 0x54F7, 0x8660, 0x54F8, 0x8661, 0x54F9, 0x8662, 0x54FA, 0xB2B8, + 0x54FB, 0x8663, 0x54FC, 0xBADF, 0x54FD, 0xDFEC, 0x54FE, 0x8664, 0x54FF, 0xDBC1, 0x5500, 0x8665, 0x5501, 0xD1E4, 0x5502, 0x8666, + 0x5503, 0x8667, 0x5504, 0x8668, 0x5505, 0x8669, 0x5506, 0xCBF4, 0x5507, 0xB4BD, 0x5508, 0x866A, 0x5509, 0xB0A6, 0x550A, 0x866B, + 0x550B, 0x866C, 0x550C, 0x866D, 0x550D, 0x866E, 0x550E, 0x866F, 0x550F, 0xDFF1, 0x5510, 0xCCC6, 0x5511, 0xDFF2, 0x5512, 0x8670, + 0x5513, 0x8671, 0x5514, 0xDFED, 0x5515, 0x8672, 0x5516, 0x8673, 0x5517, 0x8674, 0x5518, 0x8675, 0x5519, 0x8676, 0x551A, 0x8677, + 0x551B, 0xDFE9, 0x551C, 0x8678, 0x551D, 0x8679, 0x551E, 0x867A, 0x551F, 0x867B, 0x5520, 0xDFEB, 0x5521, 0x867C, 0x5522, 0xDFEF, + 0x5523, 0xDFF0, 0x5524, 0xBBBD, 0x5525, 0x867D, 0x5526, 0x867E, 0x5527, 0xDFF3, 0x5528, 0x8680, 0x5529, 0x8681, 0x552A, 0xDFF4, + 0x552B, 0x8682, 0x552C, 0xBBA3, 0x552D, 0x8683, 0x552E, 0xCADB, 0x552F, 0xCEA8, 0x5530, 0xE0A7, 0x5531, 0xB3AA, 0x5532, 0x8684, + 0x5533, 0xE0A6, 0x5534, 0x8685, 0x5535, 0x8686, 0x5536, 0x8687, 0x5537, 0xE0A1, 0x5538, 0x8688, 0x5539, 0x8689, 0x553A, 0x868A, + 0x553B, 0x868B, 0x553C, 0xDFFE, 0x553D, 0x868C, 0x553E, 0xCDD9, 0x553F, 0xDFFC, 0x5540, 0x868D, 0x5541, 0xDFFA, 0x5542, 0x868E, + 0x5543, 0xBFD0, 0x5544, 0xD7C4, 0x5545, 0x868F, 0x5546, 0xC9CC, 0x5547, 0x8690, 0x5548, 0x8691, 0x5549, 0xDFF8, 0x554A, 0xB0A1, + 0x554B, 0x8692, 0x554C, 0x8693, 0x554D, 0x8694, 0x554E, 0x8695, 0x554F, 0x8696, 0x5550, 0xDFFD, 0x5551, 0x8697, 0x5552, 0x8698, + 0x5553, 0x8699, 0x5554, 0x869A, 0x5555, 0xDFFB, 0x5556, 0xE0A2, 0x5557, 0x869B, 0x5558, 0x869C, 0x5559, 0x869D, 0x555A, 0x869E, + 0x555B, 0x869F, 0x555C, 0xE0A8, 0x555D, 0x86A0, 0x555E, 0x86A1, 0x555F, 0x86A2, 0x5560, 0x86A3, 0x5561, 0xB7C8, 0x5562, 0x86A4, + 0x5563, 0x86A5, 0x5564, 0xC6A1, 0x5565, 0xC9B6, 0x5566, 0xC0B2, 0x5567, 0xDFF5, 0x5568, 0x86A6, 0x5569, 0x86A7, 0x556A, 0xC5BE, + 0x556B, 0x86A8, 0x556C, 0xD8C4, 0x556D, 0xDFF9, 0x556E, 0xC4F6, 0x556F, 0x86A9, 0x5570, 0x86AA, 0x5571, 0x86AB, 0x5572, 0x86AC, + 0x5573, 0x86AD, 0x5574, 0x86AE, 0x5575, 0xE0A3, 0x5576, 0xE0A4, 0x5577, 0xE0A5, 0x5578, 0xD0A5, 0x5579, 0x86AF, 0x557A, 0x86B0, + 0x557B, 0xE0B4, 0x557C, 0xCCE4, 0x557D, 0x86B1, 0x557E, 0xE0B1, 0x557F, 0x86B2, 0x5580, 0xBFA6, 0x5581, 0xE0AF, 0x5582, 0xCEB9, + 0x5583, 0xE0AB, 0x5584, 0xC9C6, 0x5585, 0x86B3, 0x5586, 0x86B4, 0x5587, 0xC0AE, 0x5588, 0xE0AE, 0x5589, 0xBAED, 0x558A, 0xBAB0, + 0x558B, 0xE0A9, 0x558C, 0x86B5, 0x558D, 0x86B6, 0x558E, 0x86B7, 0x558F, 0xDFF6, 0x5590, 0x86B8, 0x5591, 0xE0B3, 0x5592, 0x86B9, + 0x5593, 0x86BA, 0x5594, 0xE0B8, 0x5595, 0x86BB, 0x5596, 0x86BC, 0x5597, 0x86BD, 0x5598, 0xB4AD, 0x5599, 0xE0B9, 0x559A, 0x86BE, + 0x559B, 0x86BF, 0x559C, 0xCFB2, 0x559D, 0xBAC8, 0x559E, 0x86C0, 0x559F, 0xE0B0, 0x55A0, 0x86C1, 0x55A1, 0x86C2, 0x55A2, 0x86C3, + 0x55A3, 0x86C4, 0x55A4, 0x86C5, 0x55A5, 0x86C6, 0x55A6, 0x86C7, 0x55A7, 0xD0FA, 0x55A8, 0x86C8, 0x55A9, 0x86C9, 0x55AA, 0x86CA, + 0x55AB, 0x86CB, 0x55AC, 0x86CC, 0x55AD, 0x86CD, 0x55AE, 0x86CE, 0x55AF, 0x86CF, 0x55B0, 0x86D0, 0x55B1, 0xE0AC, 0x55B2, 0x86D1, + 0x55B3, 0xD4FB, 0x55B4, 0x86D2, 0x55B5, 0xDFF7, 0x55B6, 0x86D3, 0x55B7, 0xC5E7, 0x55B8, 0x86D4, 0x55B9, 0xE0AD, 0x55BA, 0x86D5, + 0x55BB, 0xD3F7, 0x55BC, 0x86D6, 0x55BD, 0xE0B6, 0x55BE, 0xE0B7, 0x55BF, 0x86D7, 0x55C0, 0x86D8, 0x55C1, 0x86D9, 0x55C2, 0x86DA, + 0x55C3, 0x86DB, 0x55C4, 0xE0C4, 0x55C5, 0xD0E1, 0x55C6, 0x86DC, 0x55C7, 0x86DD, 0x55C8, 0x86DE, 0x55C9, 0xE0BC, 0x55CA, 0x86DF, + 0x55CB, 0x86E0, 0x55CC, 0xE0C9, 0x55CD, 0xE0CA, 0x55CE, 0x86E1, 0x55CF, 0x86E2, 0x55D0, 0x86E3, 0x55D1, 0xE0BE, 0x55D2, 0xE0AA, + 0x55D3, 0xC9A4, 0x55D4, 0xE0C1, 0x55D5, 0x86E4, 0x55D6, 0xE0B2, 0x55D7, 0x86E5, 0x55D8, 0x86E6, 0x55D9, 0x86E7, 0x55DA, 0x86E8, + 0x55DB, 0x86E9, 0x55DC, 0xCAC8, 0x55DD, 0xE0C3, 0x55DE, 0x86EA, 0x55DF, 0xE0B5, 0x55E0, 0x86EB, 0x55E1, 0xCECB, 0x55E2, 0x86EC, + 0x55E3, 0xCBC3, 0x55E4, 0xE0CD, 0x55E5, 0xE0C6, 0x55E6, 0xE0C2, 0x55E7, 0x86ED, 0x55E8, 0xE0CB, 0x55E9, 0x86EE, 0x55EA, 0xE0BA, + 0x55EB, 0xE0BF, 0x55EC, 0xE0C0, 0x55ED, 0x86EF, 0x55EE, 0x86F0, 0x55EF, 0xE0C5, 0x55F0, 0x86F1, 0x55F1, 0x86F2, 0x55F2, 0xE0C7, + 0x55F3, 0xE0C8, 0x55F4, 0x86F3, 0x55F5, 0xE0CC, 0x55F6, 0x86F4, 0x55F7, 0xE0BB, 0x55F8, 0x86F5, 0x55F9, 0x86F6, 0x55FA, 0x86F7, + 0x55FB, 0x86F8, 0x55FC, 0x86F9, 0x55FD, 0xCBD4, 0x55FE, 0xE0D5, 0x55FF, 0x86FA, 0x5600, 0xE0D6, 0x5601, 0xE0D2, 0x5602, 0x86FB, + 0x5603, 0x86FC, 0x5604, 0x86FD, 0x5605, 0x86FE, 0x5606, 0x8740, 0x5607, 0x8741, 0x5608, 0xE0D0, 0x5609, 0xBCCE, 0x560A, 0x8742, + 0x560B, 0x8743, 0x560C, 0xE0D1, 0x560D, 0x8744, 0x560E, 0xB8C2, 0x560F, 0xD8C5, 0x5610, 0x8745, 0x5611, 0x8746, 0x5612, 0x8747, + 0x5613, 0x8748, 0x5614, 0x8749, 0x5615, 0x874A, 0x5616, 0x874B, 0x5617, 0x874C, 0x5618, 0xD0EA, 0x5619, 0x874D, 0x561A, 0x874E, + 0x561B, 0xC2EF, 0x561C, 0x874F, 0x561D, 0x8750, 0x561E, 0xE0CF, 0x561F, 0xE0BD, 0x5620, 0x8751, 0x5621, 0x8752, 0x5622, 0x8753, + 0x5623, 0xE0D4, 0x5624, 0xE0D3, 0x5625, 0x8754, 0x5626, 0x8755, 0x5627, 0xE0D7, 0x5628, 0x8756, 0x5629, 0x8757, 0x562A, 0x8758, + 0x562B, 0x8759, 0x562C, 0xE0DC, 0x562D, 0xE0D8, 0x562E, 0x875A, 0x562F, 0x875B, 0x5630, 0x875C, 0x5631, 0xD6F6, 0x5632, 0xB3B0, + 0x5633, 0x875D, 0x5634, 0xD7EC, 0x5635, 0x875E, 0x5636, 0xCBBB, 0x5637, 0x875F, 0x5638, 0x8760, 0x5639, 0xE0DA, 0x563A, 0x8761, + 0x563B, 0xCEFB, 0x563C, 0x8762, 0x563D, 0x8763, 0x563E, 0x8764, 0x563F, 0xBAD9, 0x5640, 0x8765, 0x5641, 0x8766, 0x5642, 0x8767, + 0x5643, 0x8768, 0x5644, 0x8769, 0x5645, 0x876A, 0x5646, 0x876B, 0x5647, 0x876C, 0x5648, 0x876D, 0x5649, 0x876E, 0x564A, 0x876F, + 0x564B, 0x8770, 0x564C, 0xE0E1, 0x564D, 0xE0DD, 0x564E, 0xD2AD, 0x564F, 0x8771, 0x5650, 0x8772, 0x5651, 0x8773, 0x5652, 0x8774, + 0x5653, 0x8775, 0x5654, 0xE0E2, 0x5655, 0x8776, 0x5656, 0x8777, 0x5657, 0xE0DB, 0x5658, 0xE0D9, 0x5659, 0xE0DF, 0x565A, 0x8778, + 0x565B, 0x8779, 0x565C, 0xE0E0, 0x565D, 0x877A, 0x565E, 0x877B, 0x565F, 0x877C, 0x5660, 0x877D, 0x5661, 0x877E, 0x5662, 0xE0DE, + 0x5663, 0x8780, 0x5664, 0xE0E4, 0x5665, 0x8781, 0x5666, 0x8782, 0x5667, 0x8783, 0x5668, 0xC6F7, 0x5669, 0xD8AC, 0x566A, 0xD4EB, + 0x566B, 0xE0E6, 0x566C, 0xCAC9, 0x566D, 0x8784, 0x566E, 0x8785, 0x566F, 0x8786, 0x5670, 0x8787, 0x5671, 0xE0E5, 0x5672, 0x8788, + 0x5673, 0x8789, 0x5674, 0x878A, 0x5675, 0x878B, 0x5676, 0xB8C1, 0x5677, 0x878C, 0x5678, 0x878D, 0x5679, 0x878E, 0x567A, 0x878F, + 0x567B, 0xE0E7, 0x567C, 0xE0E8, 0x567D, 0x8790, 0x567E, 0x8791, 0x567F, 0x8792, 0x5680, 0x8793, 0x5681, 0x8794, 0x5682, 0x8795, + 0x5683, 0x8796, 0x5684, 0x8797, 0x5685, 0xE0E9, 0x5686, 0xE0E3, 0x5687, 0x8798, 0x5688, 0x8799, 0x5689, 0x879A, 0x568A, 0x879B, + 0x568B, 0x879C, 0x568C, 0x879D, 0x568D, 0x879E, 0x568E, 0xBABF, 0x568F, 0xCCE7, 0x5690, 0x879F, 0x5691, 0x87A0, 0x5692, 0x87A1, + 0x5693, 0xE0EA, 0x5694, 0x87A2, 0x5695, 0x87A3, 0x5696, 0x87A4, 0x5697, 0x87A5, 0x5698, 0x87A6, 0x5699, 0x87A7, 0x569A, 0x87A8, + 0x569B, 0x87A9, 0x569C, 0x87AA, 0x569D, 0x87AB, 0x569E, 0x87AC, 0x569F, 0x87AD, 0x56A0, 0x87AE, 0x56A1, 0x87AF, 0x56A2, 0x87B0, + 0x56A3, 0xCFF9, 0x56A4, 0x87B1, 0x56A5, 0x87B2, 0x56A6, 0x87B3, 0x56A7, 0x87B4, 0x56A8, 0x87B5, 0x56A9, 0x87B6, 0x56AA, 0x87B7, + 0x56AB, 0x87B8, 0x56AC, 0x87B9, 0x56AD, 0x87BA, 0x56AE, 0x87BB, 0x56AF, 0xE0EB, 0x56B0, 0x87BC, 0x56B1, 0x87BD, 0x56B2, 0x87BE, + 0x56B3, 0x87BF, 0x56B4, 0x87C0, 0x56B5, 0x87C1, 0x56B6, 0x87C2, 0x56B7, 0xC8C2, 0x56B8, 0x87C3, 0x56B9, 0x87C4, 0x56BA, 0x87C5, + 0x56BB, 0x87C6, 0x56BC, 0xBDC0, 0x56BD, 0x87C7, 0x56BE, 0x87C8, 0x56BF, 0x87C9, 0x56C0, 0x87CA, 0x56C1, 0x87CB, 0x56C2, 0x87CC, + 0x56C3, 0x87CD, 0x56C4, 0x87CE, 0x56C5, 0x87CF, 0x56C6, 0x87D0, 0x56C7, 0x87D1, 0x56C8, 0x87D2, 0x56C9, 0x87D3, 0x56CA, 0xC4D2, + 0x56CB, 0x87D4, 0x56CC, 0x87D5, 0x56CD, 0x87D6, 0x56CE, 0x87D7, 0x56CF, 0x87D8, 0x56D0, 0x87D9, 0x56D1, 0x87DA, 0x56D2, 0x87DB, + 0x56D3, 0x87DC, 0x56D4, 0xE0EC, 0x56D5, 0x87DD, 0x56D6, 0x87DE, 0x56D7, 0xE0ED, 0x56D8, 0x87DF, 0x56D9, 0x87E0, 0x56DA, 0xC7F4, + 0x56DB, 0xCBC4, 0x56DC, 0x87E1, 0x56DD, 0xE0EE, 0x56DE, 0xBBD8, 0x56DF, 0xD8B6, 0x56E0, 0xD2F2, 0x56E1, 0xE0EF, 0x56E2, 0xCDC5, + 0x56E3, 0x87E2, 0x56E4, 0xB6DA, 0x56E5, 0x87E3, 0x56E6, 0x87E4, 0x56E7, 0x87E5, 0x56E8, 0x87E6, 0x56E9, 0x87E7, 0x56EA, 0x87E8, + 0x56EB, 0xE0F1, 0x56EC, 0x87E9, 0x56ED, 0xD4B0, 0x56EE, 0x87EA, 0x56EF, 0x87EB, 0x56F0, 0xC0A7, 0x56F1, 0xB4D1, 0x56F2, 0x87EC, + 0x56F3, 0x87ED, 0x56F4, 0xCEA7, 0x56F5, 0xE0F0, 0x56F6, 0x87EE, 0x56F7, 0x87EF, 0x56F8, 0x87F0, 0x56F9, 0xE0F2, 0x56FA, 0xB9CC, + 0x56FB, 0x87F1, 0x56FC, 0x87F2, 0x56FD, 0xB9FA, 0x56FE, 0xCDBC, 0x56FF, 0xE0F3, 0x5700, 0x87F3, 0x5701, 0x87F4, 0x5702, 0x87F5, + 0x5703, 0xC6D4, 0x5704, 0xE0F4, 0x5705, 0x87F6, 0x5706, 0xD4B2, 0x5707, 0x87F7, 0x5708, 0xC8A6, 0x5709, 0xE0F6, 0x570A, 0xE0F5, + 0x570B, 0x87F8, 0x570C, 0x87F9, 0x570D, 0x87FA, 0x570E, 0x87FB, 0x570F, 0x87FC, 0x5710, 0x87FD, 0x5711, 0x87FE, 0x5712, 0x8840, + 0x5713, 0x8841, 0x5714, 0x8842, 0x5715, 0x8843, 0x5716, 0x8844, 0x5717, 0x8845, 0x5718, 0x8846, 0x5719, 0x8847, 0x571A, 0x8848, + 0x571B, 0x8849, 0x571C, 0xE0F7, 0x571D, 0x884A, 0x571E, 0x884B, 0x571F, 0xCDC1, 0x5720, 0x884C, 0x5721, 0x884D, 0x5722, 0x884E, + 0x5723, 0xCAA5, 0x5724, 0x884F, 0x5725, 0x8850, 0x5726, 0x8851, 0x5727, 0x8852, 0x5728, 0xD4DA, 0x5729, 0xDBD7, 0x572A, 0xDBD9, + 0x572B, 0x8853, 0x572C, 0xDBD8, 0x572D, 0xB9E7, 0x572E, 0xDBDC, 0x572F, 0xDBDD, 0x5730, 0xB5D8, 0x5731, 0x8854, 0x5732, 0x8855, + 0x5733, 0xDBDA, 0x5734, 0x8856, 0x5735, 0x8857, 0x5736, 0x8858, 0x5737, 0x8859, 0x5738, 0x885A, 0x5739, 0xDBDB, 0x573A, 0xB3A1, + 0x573B, 0xDBDF, 0x573C, 0x885B, 0x573D, 0x885C, 0x573E, 0xBBF8, 0x573F, 0x885D, 0x5740, 0xD6B7, 0x5741, 0x885E, 0x5742, 0xDBE0, + 0x5743, 0x885F, 0x5744, 0x8860, 0x5745, 0x8861, 0x5746, 0x8862, 0x5747, 0xBEF9, 0x5748, 0x8863, 0x5749, 0x8864, 0x574A, 0xB7BB, + 0x574B, 0x8865, 0x574C, 0xDBD0, 0x574D, 0xCCAE, 0x574E, 0xBFB2, 0x574F, 0xBBB5, 0x5750, 0xD7F8, 0x5751, 0xBFD3, 0x5752, 0x8866, + 0x5753, 0x8867, 0x5754, 0x8868, 0x5755, 0x8869, 0x5756, 0x886A, 0x5757, 0xBFE9, 0x5758, 0x886B, 0x5759, 0x886C, 0x575A, 0xBCE1, + 0x575B, 0xCCB3, 0x575C, 0xDBDE, 0x575D, 0xB0D3, 0x575E, 0xCEEB, 0x575F, 0xB7D8, 0x5760, 0xD7B9, 0x5761, 0xC6C2, 0x5762, 0x886D, + 0x5763, 0x886E, 0x5764, 0xC0A4, 0x5765, 0x886F, 0x5766, 0xCCB9, 0x5767, 0x8870, 0x5768, 0xDBE7, 0x5769, 0xDBE1, 0x576A, 0xC6BA, + 0x576B, 0xDBE3, 0x576C, 0x8871, 0x576D, 0xDBE8, 0x576E, 0x8872, 0x576F, 0xC5F7, 0x5770, 0x8873, 0x5771, 0x8874, 0x5772, 0x8875, + 0x5773, 0xDBEA, 0x5774, 0x8876, 0x5775, 0x8877, 0x5776, 0xDBE9, 0x5777, 0xBFC0, 0x5778, 0x8878, 0x5779, 0x8879, 0x577A, 0x887A, + 0x577B, 0xDBE6, 0x577C, 0xDBE5, 0x577D, 0x887B, 0x577E, 0x887C, 0x577F, 0x887D, 0x5780, 0x887E, 0x5781, 0x8880, 0x5782, 0xB4B9, + 0x5783, 0xC0AC, 0x5784, 0xC2A2, 0x5785, 0xDBE2, 0x5786, 0xDBE4, 0x5787, 0x8881, 0x5788, 0x8882, 0x5789, 0x8883, 0x578A, 0x8884, + 0x578B, 0xD0CD, 0x578C, 0xDBED, 0x578D, 0x8885, 0x578E, 0x8886, 0x578F, 0x8887, 0x5790, 0x8888, 0x5791, 0x8889, 0x5792, 0xC0DD, + 0x5793, 0xDBF2, 0x5794, 0x888A, 0x5795, 0x888B, 0x5796, 0x888C, 0x5797, 0x888D, 0x5798, 0x888E, 0x5799, 0x888F, 0x579A, 0x8890, + 0x579B, 0xB6E2, 0x579C, 0x8891, 0x579D, 0x8892, 0x579E, 0x8893, 0x579F, 0x8894, 0x57A0, 0xDBF3, 0x57A1, 0xDBD2, 0x57A2, 0xB9B8, + 0x57A3, 0xD4AB, 0x57A4, 0xDBEC, 0x57A5, 0x8895, 0x57A6, 0xBFD1, 0x57A7, 0xDBF0, 0x57A8, 0x8896, 0x57A9, 0xDBD1, 0x57AA, 0x8897, + 0x57AB, 0xB5E6, 0x57AC, 0x8898, 0x57AD, 0xDBEB, 0x57AE, 0xBFE5, 0x57AF, 0x8899, 0x57B0, 0x889A, 0x57B1, 0x889B, 0x57B2, 0xDBEE, + 0x57B3, 0x889C, 0x57B4, 0xDBF1, 0x57B5, 0x889D, 0x57B6, 0x889E, 0x57B7, 0x889F, 0x57B8, 0xDBF9, 0x57B9, 0x88A0, 0x57BA, 0x88A1, + 0x57BB, 0x88A2, 0x57BC, 0x88A3, 0x57BD, 0x88A4, 0x57BE, 0x88A5, 0x57BF, 0x88A6, 0x57C0, 0x88A7, 0x57C1, 0x88A8, 0x57C2, 0xB9A1, + 0x57C3, 0xB0A3, 0x57C4, 0x88A9, 0x57C5, 0x88AA, 0x57C6, 0x88AB, 0x57C7, 0x88AC, 0x57C8, 0x88AD, 0x57C9, 0x88AE, 0x57CA, 0x88AF, + 0x57CB, 0xC2F1, 0x57CC, 0x88B0, 0x57CD, 0x88B1, 0x57CE, 0xB3C7, 0x57CF, 0xDBEF, 0x57D0, 0x88B2, 0x57D1, 0x88B3, 0x57D2, 0xDBF8, + 0x57D3, 0x88B4, 0x57D4, 0xC6D2, 0x57D5, 0xDBF4, 0x57D6, 0x88B5, 0x57D7, 0x88B6, 0x57D8, 0xDBF5, 0x57D9, 0xDBF7, 0x57DA, 0xDBF6, + 0x57DB, 0x88B7, 0x57DC, 0x88B8, 0x57DD, 0xDBFE, 0x57DE, 0x88B9, 0x57DF, 0xD3F2, 0x57E0, 0xB2BA, 0x57E1, 0x88BA, 0x57E2, 0x88BB, + 0x57E3, 0x88BC, 0x57E4, 0xDBFD, 0x57E5, 0x88BD, 0x57E6, 0x88BE, 0x57E7, 0x88BF, 0x57E8, 0x88C0, 0x57E9, 0x88C1, 0x57EA, 0x88C2, + 0x57EB, 0x88C3, 0x57EC, 0x88C4, 0x57ED, 0xDCA4, 0x57EE, 0x88C5, 0x57EF, 0xDBFB, 0x57F0, 0x88C6, 0x57F1, 0x88C7, 0x57F2, 0x88C8, + 0x57F3, 0x88C9, 0x57F4, 0xDBFA, 0x57F5, 0x88CA, 0x57F6, 0x88CB, 0x57F7, 0x88CC, 0x57F8, 0xDBFC, 0x57F9, 0xC5E0, 0x57FA, 0xBBF9, + 0x57FB, 0x88CD, 0x57FC, 0x88CE, 0x57FD, 0xDCA3, 0x57FE, 0x88CF, 0x57FF, 0x88D0, 0x5800, 0xDCA5, 0x5801, 0x88D1, 0x5802, 0xCCC3, + 0x5803, 0x88D2, 0x5804, 0x88D3, 0x5805, 0x88D4, 0x5806, 0xB6D1, 0x5807, 0xDDC0, 0x5808, 0x88D5, 0x5809, 0x88D6, 0x580A, 0x88D7, + 0x580B, 0xDCA1, 0x580C, 0x88D8, 0x580D, 0xDCA2, 0x580E, 0x88D9, 0x580F, 0x88DA, 0x5810, 0x88DB, 0x5811, 0xC7B5, 0x5812, 0x88DC, + 0x5813, 0x88DD, 0x5814, 0x88DE, 0x5815, 0xB6E9, 0x5816, 0x88DF, 0x5817, 0x88E0, 0x5818, 0x88E1, 0x5819, 0xDCA7, 0x581A, 0x88E2, + 0x581B, 0x88E3, 0x581C, 0x88E4, 0x581D, 0x88E5, 0x581E, 0xDCA6, 0x581F, 0x88E6, 0x5820, 0xDCA9, 0x5821, 0xB1A4, 0x5822, 0x88E7, + 0x5823, 0x88E8, 0x5824, 0xB5CC, 0x5825, 0x88E9, 0x5826, 0x88EA, 0x5827, 0x88EB, 0x5828, 0x88EC, 0x5829, 0x88ED, 0x582A, 0xBFB0, + 0x582B, 0x88EE, 0x582C, 0x88EF, 0x582D, 0x88F0, 0x582E, 0x88F1, 0x582F, 0x88F2, 0x5830, 0xD1DF, 0x5831, 0x88F3, 0x5832, 0x88F4, + 0x5833, 0x88F5, 0x5834, 0x88F6, 0x5835, 0xB6C2, 0x5836, 0x88F7, 0x5837, 0x88F8, 0x5838, 0x88F9, 0x5839, 0x88FA, 0x583A, 0x88FB, + 0x583B, 0x88FC, 0x583C, 0x88FD, 0x583D, 0x88FE, 0x583E, 0x8940, 0x583F, 0x8941, 0x5840, 0x8942, 0x5841, 0x8943, 0x5842, 0x8944, + 0x5843, 0x8945, 0x5844, 0xDCA8, 0x5845, 0x8946, 0x5846, 0x8947, 0x5847, 0x8948, 0x5848, 0x8949, 0x5849, 0x894A, 0x584A, 0x894B, + 0x584B, 0x894C, 0x584C, 0xCBFA, 0x584D, 0xEBF3, 0x584E, 0x894D, 0x584F, 0x894E, 0x5850, 0x894F, 0x5851, 0xCBDC, 0x5852, 0x8950, + 0x5853, 0x8951, 0x5854, 0xCBFE, 0x5855, 0x8952, 0x5856, 0x8953, 0x5857, 0x8954, 0x5858, 0xCCC1, 0x5859, 0x8955, 0x585A, 0x8956, + 0x585B, 0x8957, 0x585C, 0x8958, 0x585D, 0x8959, 0x585E, 0xC8FB, 0x585F, 0x895A, 0x5860, 0x895B, 0x5861, 0x895C, 0x5862, 0x895D, + 0x5863, 0x895E, 0x5864, 0x895F, 0x5865, 0xDCAA, 0x5866, 0x8960, 0x5867, 0x8961, 0x5868, 0x8962, 0x5869, 0x8963, 0x586A, 0x8964, + 0x586B, 0xCCEE, 0x586C, 0xDCAB, 0x586D, 0x8965, 0x586E, 0x8966, 0x586F, 0x8967, 0x5870, 0x8968, 0x5871, 0x8969, 0x5872, 0x896A, + 0x5873, 0x896B, 0x5874, 0x896C, 0x5875, 0x896D, 0x5876, 0x896E, 0x5877, 0x896F, 0x5878, 0x8970, 0x5879, 0x8971, 0x587A, 0x8972, + 0x587B, 0x8973, 0x587C, 0x8974, 0x587D, 0x8975, 0x587E, 0xDBD3, 0x587F, 0x8976, 0x5880, 0xDCAF, 0x5881, 0xDCAC, 0x5882, 0x8977, + 0x5883, 0xBEB3, 0x5884, 0x8978, 0x5885, 0xCAFB, 0x5886, 0x8979, 0x5887, 0x897A, 0x5888, 0x897B, 0x5889, 0xDCAD, 0x588A, 0x897C, + 0x588B, 0x897D, 0x588C, 0x897E, 0x588D, 0x8980, 0x588E, 0x8981, 0x588F, 0x8982, 0x5890, 0x8983, 0x5891, 0x8984, 0x5892, 0xC9CA, + 0x5893, 0xC4B9, 0x5894, 0x8985, 0x5895, 0x8986, 0x5896, 0x8987, 0x5897, 0x8988, 0x5898, 0x8989, 0x5899, 0xC7BD, 0x589A, 0xDCAE, + 0x589B, 0x898A, 0x589C, 0x898B, 0x589D, 0x898C, 0x589E, 0xD4F6, 0x589F, 0xD0E6, 0x58A0, 0x898D, 0x58A1, 0x898E, 0x58A2, 0x898F, + 0x58A3, 0x8990, 0x58A4, 0x8991, 0x58A5, 0x8992, 0x58A6, 0x8993, 0x58A7, 0x8994, 0x58A8, 0xC4AB, 0x58A9, 0xB6D5, 0x58AA, 0x8995, + 0x58AB, 0x8996, 0x58AC, 0x8997, 0x58AD, 0x8998, 0x58AE, 0x8999, 0x58AF, 0x899A, 0x58B0, 0x899B, 0x58B1, 0x899C, 0x58B2, 0x899D, + 0x58B3, 0x899E, 0x58B4, 0x899F, 0x58B5, 0x89A0, 0x58B6, 0x89A1, 0x58B7, 0x89A2, 0x58B8, 0x89A3, 0x58B9, 0x89A4, 0x58BA, 0x89A5, + 0x58BB, 0x89A6, 0x58BC, 0xDBD4, 0x58BD, 0x89A7, 0x58BE, 0x89A8, 0x58BF, 0x89A9, 0x58C0, 0x89AA, 0x58C1, 0xB1DA, 0x58C2, 0x89AB, + 0x58C3, 0x89AC, 0x58C4, 0x89AD, 0x58C5, 0xDBD5, 0x58C6, 0x89AE, 0x58C7, 0x89AF, 0x58C8, 0x89B0, 0x58C9, 0x89B1, 0x58CA, 0x89B2, + 0x58CB, 0x89B3, 0x58CC, 0x89B4, 0x58CD, 0x89B5, 0x58CE, 0x89B6, 0x58CF, 0x89B7, 0x58D0, 0x89B8, 0x58D1, 0xDBD6, 0x58D2, 0x89B9, + 0x58D3, 0x89BA, 0x58D4, 0x89BB, 0x58D5, 0xBABE, 0x58D6, 0x89BC, 0x58D7, 0x89BD, 0x58D8, 0x89BE, 0x58D9, 0x89BF, 0x58DA, 0x89C0, + 0x58DB, 0x89C1, 0x58DC, 0x89C2, 0x58DD, 0x89C3, 0x58DE, 0x89C4, 0x58DF, 0x89C5, 0x58E0, 0x89C6, 0x58E1, 0x89C7, 0x58E2, 0x89C8, + 0x58E3, 0x89C9, 0x58E4, 0xC8C0, 0x58E5, 0x89CA, 0x58E6, 0x89CB, 0x58E7, 0x89CC, 0x58E8, 0x89CD, 0x58E9, 0x89CE, 0x58EA, 0x89CF, + 0x58EB, 0xCABF, 0x58EC, 0xC8C9, 0x58ED, 0x89D0, 0x58EE, 0xD7B3, 0x58EF, 0x89D1, 0x58F0, 0xC9F9, 0x58F1, 0x89D2, 0x58F2, 0x89D3, + 0x58F3, 0xBFC7, 0x58F4, 0x89D4, 0x58F5, 0x89D5, 0x58F6, 0xBAF8, 0x58F7, 0x89D6, 0x58F8, 0x89D7, 0x58F9, 0xD2BC, 0x58FA, 0x89D8, + 0x58FB, 0x89D9, 0x58FC, 0x89DA, 0x58FD, 0x89DB, 0x58FE, 0x89DC, 0x58FF, 0x89DD, 0x5900, 0x89DE, 0x5901, 0x89DF, 0x5902, 0xE2BA, + 0x5903, 0x89E0, 0x5904, 0xB4A6, 0x5905, 0x89E1, 0x5906, 0x89E2, 0x5907, 0xB1B8, 0x5908, 0x89E3, 0x5909, 0x89E4, 0x590A, 0x89E5, + 0x590B, 0x89E6, 0x590C, 0x89E7, 0x590D, 0xB8B4, 0x590E, 0x89E8, 0x590F, 0xCFC4, 0x5910, 0x89E9, 0x5911, 0x89EA, 0x5912, 0x89EB, + 0x5913, 0x89EC, 0x5914, 0xD9E7, 0x5915, 0xCFA6, 0x5916, 0xCDE2, 0x5917, 0x89ED, 0x5918, 0x89EE, 0x5919, 0xD9ED, 0x591A, 0xB6E0, + 0x591B, 0x89EF, 0x591C, 0xD2B9, 0x591D, 0x89F0, 0x591E, 0x89F1, 0x591F, 0xB9BB, 0x5920, 0x89F2, 0x5921, 0x89F3, 0x5922, 0x89F4, + 0x5923, 0x89F5, 0x5924, 0xE2B9, 0x5925, 0xE2B7, 0x5926, 0x89F6, 0x5927, 0xB4F3, 0x5928, 0x89F7, 0x5929, 0xCCEC, 0x592A, 0xCCAB, + 0x592B, 0xB7F2, 0x592C, 0x89F8, 0x592D, 0xD8B2, 0x592E, 0xD1EB, 0x592F, 0xBABB, 0x5930, 0x89F9, 0x5931, 0xCAA7, 0x5932, 0x89FA, + 0x5933, 0x89FB, 0x5934, 0xCDB7, 0x5935, 0x89FC, 0x5936, 0x89FD, 0x5937, 0xD2C4, 0x5938, 0xBFE4, 0x5939, 0xBCD0, 0x593A, 0xB6E1, + 0x593B, 0x89FE, 0x593C, 0xDEC5, 0x593D, 0x8A40, 0x593E, 0x8A41, 0x593F, 0x8A42, 0x5940, 0x8A43, 0x5941, 0xDEC6, 0x5942, 0xDBBC, + 0x5943, 0x8A44, 0x5944, 0xD1D9, 0x5945, 0x8A45, 0x5946, 0x8A46, 0x5947, 0xC6E6, 0x5948, 0xC4CE, 0x5949, 0xB7EE, 0x594A, 0x8A47, + 0x594B, 0xB7DC, 0x594C, 0x8A48, 0x594D, 0x8A49, 0x594E, 0xBFFC, 0x594F, 0xD7E0, 0x5950, 0x8A4A, 0x5951, 0xC6F5, 0x5952, 0x8A4B, + 0x5953, 0x8A4C, 0x5954, 0xB1BC, 0x5955, 0xDEC8, 0x5956, 0xBDB1, 0x5957, 0xCCD7, 0x5958, 0xDECA, 0x5959, 0x8A4D, 0x595A, 0xDEC9, + 0x595B, 0x8A4E, 0x595C, 0x8A4F, 0x595D, 0x8A50, 0x595E, 0x8A51, 0x595F, 0x8A52, 0x5960, 0xB5EC, 0x5961, 0x8A53, 0x5962, 0xC9DD, + 0x5963, 0x8A54, 0x5964, 0x8A55, 0x5965, 0xB0C2, 0x5966, 0x8A56, 0x5967, 0x8A57, 0x5968, 0x8A58, 0x5969, 0x8A59, 0x596A, 0x8A5A, + 0x596B, 0x8A5B, 0x596C, 0x8A5C, 0x596D, 0x8A5D, 0x596E, 0x8A5E, 0x596F, 0x8A5F, 0x5970, 0x8A60, 0x5971, 0x8A61, 0x5972, 0x8A62, + 0x5973, 0xC5AE, 0x5974, 0xC5AB, 0x5975, 0x8A63, 0x5976, 0xC4CC, 0x5977, 0x8A64, 0x5978, 0xBCE9, 0x5979, 0xCBFD, 0x597A, 0x8A65, + 0x597B, 0x8A66, 0x597C, 0x8A67, 0x597D, 0xBAC3, 0x597E, 0x8A68, 0x597F, 0x8A69, 0x5980, 0x8A6A, 0x5981, 0xE5F9, 0x5982, 0xC8E7, + 0x5983, 0xE5FA, 0x5984, 0xCDFD, 0x5985, 0x8A6B, 0x5986, 0xD7B1, 0x5987, 0xB8BE, 0x5988, 0xC2E8, 0x5989, 0x8A6C, 0x598A, 0xC8D1, + 0x598B, 0x8A6D, 0x598C, 0x8A6E, 0x598D, 0xE5FB, 0x598E, 0x8A6F, 0x598F, 0x8A70, 0x5990, 0x8A71, 0x5991, 0x8A72, 0x5992, 0xB6CA, + 0x5993, 0xBCCB, 0x5994, 0x8A73, 0x5995, 0x8A74, 0x5996, 0xD1FD, 0x5997, 0xE6A1, 0x5998, 0x8A75, 0x5999, 0xC3EE, 0x599A, 0x8A76, + 0x599B, 0x8A77, 0x599C, 0x8A78, 0x599D, 0x8A79, 0x599E, 0xE6A4, 0x599F, 0x8A7A, 0x59A0, 0x8A7B, 0x59A1, 0x8A7C, 0x59A2, 0x8A7D, + 0x59A3, 0xE5FE, 0x59A4, 0xE6A5, 0x59A5, 0xCDD7, 0x59A6, 0x8A7E, 0x59A7, 0x8A80, 0x59A8, 0xB7C1, 0x59A9, 0xE5FC, 0x59AA, 0xE5FD, + 0x59AB, 0xE6A3, 0x59AC, 0x8A81, 0x59AD, 0x8A82, 0x59AE, 0xC4DD, 0x59AF, 0xE6A8, 0x59B0, 0x8A83, 0x59B1, 0x8A84, 0x59B2, 0xE6A7, + 0x59B3, 0x8A85, 0x59B4, 0x8A86, 0x59B5, 0x8A87, 0x59B6, 0x8A88, 0x59B7, 0x8A89, 0x59B8, 0x8A8A, 0x59B9, 0xC3C3, 0x59BA, 0x8A8B, + 0x59BB, 0xC6DE, 0x59BC, 0x8A8C, 0x59BD, 0x8A8D, 0x59BE, 0xE6AA, 0x59BF, 0x8A8E, 0x59C0, 0x8A8F, 0x59C1, 0x8A90, 0x59C2, 0x8A91, + 0x59C3, 0x8A92, 0x59C4, 0x8A93, 0x59C5, 0x8A94, 0x59C6, 0xC4B7, 0x59C7, 0x8A95, 0x59C8, 0x8A96, 0x59C9, 0x8A97, 0x59CA, 0xE6A2, + 0x59CB, 0xCABC, 0x59CC, 0x8A98, 0x59CD, 0x8A99, 0x59CE, 0x8A9A, 0x59CF, 0x8A9B, 0x59D0, 0xBDE3, 0x59D1, 0xB9C3, 0x59D2, 0xE6A6, + 0x59D3, 0xD0D5, 0x59D4, 0xCEAF, 0x59D5, 0x8A9C, 0x59D6, 0x8A9D, 0x59D7, 0xE6A9, 0x59D8, 0xE6B0, 0x59D9, 0x8A9E, 0x59DA, 0xD2A6, + 0x59DB, 0x8A9F, 0x59DC, 0xBDAA, 0x59DD, 0xE6AD, 0x59DE, 0x8AA0, 0x59DF, 0x8AA1, 0x59E0, 0x8AA2, 0x59E1, 0x8AA3, 0x59E2, 0x8AA4, + 0x59E3, 0xE6AF, 0x59E4, 0x8AA5, 0x59E5, 0xC0D1, 0x59E6, 0x8AA6, 0x59E7, 0x8AA7, 0x59E8, 0xD2CC, 0x59E9, 0x8AA8, 0x59EA, 0x8AA9, + 0x59EB, 0x8AAA, 0x59EC, 0xBCA7, 0x59ED, 0x8AAB, 0x59EE, 0x8AAC, 0x59EF, 0x8AAD, 0x59F0, 0x8AAE, 0x59F1, 0x8AAF, 0x59F2, 0x8AB0, + 0x59F3, 0x8AB1, 0x59F4, 0x8AB2, 0x59F5, 0x8AB3, 0x59F6, 0x8AB4, 0x59F7, 0x8AB5, 0x59F8, 0x8AB6, 0x59F9, 0xE6B1, 0x59FA, 0x8AB7, + 0x59FB, 0xD2F6, 0x59FC, 0x8AB8, 0x59FD, 0x8AB9, 0x59FE, 0x8ABA, 0x59FF, 0xD7CB, 0x5A00, 0x8ABB, 0x5A01, 0xCDFE, 0x5A02, 0x8ABC, + 0x5A03, 0xCDDE, 0x5A04, 0xC2A6, 0x5A05, 0xE6AB, 0x5A06, 0xE6AC, 0x5A07, 0xBDBF, 0x5A08, 0xE6AE, 0x5A09, 0xE6B3, 0x5A0A, 0x8ABD, + 0x5A0B, 0x8ABE, 0x5A0C, 0xE6B2, 0x5A0D, 0x8ABF, 0x5A0E, 0x8AC0, 0x5A0F, 0x8AC1, 0x5A10, 0x8AC2, 0x5A11, 0xE6B6, 0x5A12, 0x8AC3, + 0x5A13, 0xE6B8, 0x5A14, 0x8AC4, 0x5A15, 0x8AC5, 0x5A16, 0x8AC6, 0x5A17, 0x8AC7, 0x5A18, 0xC4EF, 0x5A19, 0x8AC8, 0x5A1A, 0x8AC9, + 0x5A1B, 0x8ACA, 0x5A1C, 0xC4C8, 0x5A1D, 0x8ACB, 0x5A1E, 0x8ACC, 0x5A1F, 0xBEEA, 0x5A20, 0xC9EF, 0x5A21, 0x8ACD, 0x5A22, 0x8ACE, + 0x5A23, 0xE6B7, 0x5A24, 0x8ACF, 0x5A25, 0xB6F0, 0x5A26, 0x8AD0, 0x5A27, 0x8AD1, 0x5A28, 0x8AD2, 0x5A29, 0xC3E4, 0x5A2A, 0x8AD3, + 0x5A2B, 0x8AD4, 0x5A2C, 0x8AD5, 0x5A2D, 0x8AD6, 0x5A2E, 0x8AD7, 0x5A2F, 0x8AD8, 0x5A30, 0x8AD9, 0x5A31, 0xD3E9, 0x5A32, 0xE6B4, + 0x5A33, 0x8ADA, 0x5A34, 0xE6B5, 0x5A35, 0x8ADB, 0x5A36, 0xC8A2, 0x5A37, 0x8ADC, 0x5A38, 0x8ADD, 0x5A39, 0x8ADE, 0x5A3A, 0x8ADF, + 0x5A3B, 0x8AE0, 0x5A3C, 0xE6BD, 0x5A3D, 0x8AE1, 0x5A3E, 0x8AE2, 0x5A3F, 0x8AE3, 0x5A40, 0xE6B9, 0x5A41, 0x8AE4, 0x5A42, 0x8AE5, + 0x5A43, 0x8AE6, 0x5A44, 0x8AE7, 0x5A45, 0x8AE8, 0x5A46, 0xC6C5, 0x5A47, 0x8AE9, 0x5A48, 0x8AEA, 0x5A49, 0xCDF1, 0x5A4A, 0xE6BB, + 0x5A4B, 0x8AEB, 0x5A4C, 0x8AEC, 0x5A4D, 0x8AED, 0x5A4E, 0x8AEE, 0x5A4F, 0x8AEF, 0x5A50, 0x8AF0, 0x5A51, 0x8AF1, 0x5A52, 0x8AF2, + 0x5A53, 0x8AF3, 0x5A54, 0x8AF4, 0x5A55, 0xE6BC, 0x5A56, 0x8AF5, 0x5A57, 0x8AF6, 0x5A58, 0x8AF7, 0x5A59, 0x8AF8, 0x5A5A, 0xBBE9, + 0x5A5B, 0x8AF9, 0x5A5C, 0x8AFA, 0x5A5D, 0x8AFB, 0x5A5E, 0x8AFC, 0x5A5F, 0x8AFD, 0x5A60, 0x8AFE, 0x5A61, 0x8B40, 0x5A62, 0xE6BE, + 0x5A63, 0x8B41, 0x5A64, 0x8B42, 0x5A65, 0x8B43, 0x5A66, 0x8B44, 0x5A67, 0xE6BA, 0x5A68, 0x8B45, 0x5A69, 0x8B46, 0x5A6A, 0xC0B7, + 0x5A6B, 0x8B47, 0x5A6C, 0x8B48, 0x5A6D, 0x8B49, 0x5A6E, 0x8B4A, 0x5A6F, 0x8B4B, 0x5A70, 0x8B4C, 0x5A71, 0x8B4D, 0x5A72, 0x8B4E, + 0x5A73, 0x8B4F, 0x5A74, 0xD3A4, 0x5A75, 0xE6BF, 0x5A76, 0xC9F4, 0x5A77, 0xE6C3, 0x5A78, 0x8B50, 0x5A79, 0x8B51, 0x5A7A, 0xE6C4, + 0x5A7B, 0x8B52, 0x5A7C, 0x8B53, 0x5A7D, 0x8B54, 0x5A7E, 0x8B55, 0x5A7F, 0xD0F6, 0x5A80, 0x8B56, 0x5A81, 0x8B57, 0x5A82, 0x8B58, + 0x5A83, 0x8B59, 0x5A84, 0x8B5A, 0x5A85, 0x8B5B, 0x5A86, 0x8B5C, 0x5A87, 0x8B5D, 0x5A88, 0x8B5E, 0x5A89, 0x8B5F, 0x5A8A, 0x8B60, + 0x5A8B, 0x8B61, 0x5A8C, 0x8B62, 0x5A8D, 0x8B63, 0x5A8E, 0x8B64, 0x5A8F, 0x8B65, 0x5A90, 0x8B66, 0x5A91, 0x8B67, 0x5A92, 0xC3BD, + 0x5A93, 0x8B68, 0x5A94, 0x8B69, 0x5A95, 0x8B6A, 0x5A96, 0x8B6B, 0x5A97, 0x8B6C, 0x5A98, 0x8B6D, 0x5A99, 0x8B6E, 0x5A9A, 0xC3C4, + 0x5A9B, 0xE6C2, 0x5A9C, 0x8B6F, 0x5A9D, 0x8B70, 0x5A9E, 0x8B71, 0x5A9F, 0x8B72, 0x5AA0, 0x8B73, 0x5AA1, 0x8B74, 0x5AA2, 0x8B75, + 0x5AA3, 0x8B76, 0x5AA4, 0x8B77, 0x5AA5, 0x8B78, 0x5AA6, 0x8B79, 0x5AA7, 0x8B7A, 0x5AA8, 0x8B7B, 0x5AA9, 0x8B7C, 0x5AAA, 0xE6C1, + 0x5AAB, 0x8B7D, 0x5AAC, 0x8B7E, 0x5AAD, 0x8B80, 0x5AAE, 0x8B81, 0x5AAF, 0x8B82, 0x5AB0, 0x8B83, 0x5AB1, 0x8B84, 0x5AB2, 0xE6C7, + 0x5AB3, 0xCFB1, 0x5AB4, 0x8B85, 0x5AB5, 0xEBF4, 0x5AB6, 0x8B86, 0x5AB7, 0x8B87, 0x5AB8, 0xE6CA, 0x5AB9, 0x8B88, 0x5ABA, 0x8B89, + 0x5ABB, 0x8B8A, 0x5ABC, 0x8B8B, 0x5ABD, 0x8B8C, 0x5ABE, 0xE6C5, 0x5ABF, 0x8B8D, 0x5AC0, 0x8B8E, 0x5AC1, 0xBCDE, 0x5AC2, 0xC9A9, + 0x5AC3, 0x8B8F, 0x5AC4, 0x8B90, 0x5AC5, 0x8B91, 0x5AC6, 0x8B92, 0x5AC7, 0x8B93, 0x5AC8, 0x8B94, 0x5AC9, 0xBCB5, 0x5ACA, 0x8B95, + 0x5ACB, 0x8B96, 0x5ACC, 0xCFD3, 0x5ACD, 0x8B97, 0x5ACE, 0x8B98, 0x5ACF, 0x8B99, 0x5AD0, 0x8B9A, 0x5AD1, 0x8B9B, 0x5AD2, 0xE6C8, + 0x5AD3, 0x8B9C, 0x5AD4, 0xE6C9, 0x5AD5, 0x8B9D, 0x5AD6, 0xE6CE, 0x5AD7, 0x8B9E, 0x5AD8, 0xE6D0, 0x5AD9, 0x8B9F, 0x5ADA, 0x8BA0, + 0x5ADB, 0x8BA1, 0x5ADC, 0xE6D1, 0x5ADD, 0x8BA2, 0x5ADE, 0x8BA3, 0x5ADF, 0x8BA4, 0x5AE0, 0xE6CB, 0x5AE1, 0xB5D5, 0x5AE2, 0x8BA5, + 0x5AE3, 0xE6CC, 0x5AE4, 0x8BA6, 0x5AE5, 0x8BA7, 0x5AE6, 0xE6CF, 0x5AE7, 0x8BA8, 0x5AE8, 0x8BA9, 0x5AE9, 0xC4DB, 0x5AEA, 0x8BAA, + 0x5AEB, 0xE6C6, 0x5AEC, 0x8BAB, 0x5AED, 0x8BAC, 0x5AEE, 0x8BAD, 0x5AEF, 0x8BAE, 0x5AF0, 0x8BAF, 0x5AF1, 0xE6CD, 0x5AF2, 0x8BB0, + 0x5AF3, 0x8BB1, 0x5AF4, 0x8BB2, 0x5AF5, 0x8BB3, 0x5AF6, 0x8BB4, 0x5AF7, 0x8BB5, 0x5AF8, 0x8BB6, 0x5AF9, 0x8BB7, 0x5AFA, 0x8BB8, + 0x5AFB, 0x8BB9, 0x5AFC, 0x8BBA, 0x5AFD, 0x8BBB, 0x5AFE, 0x8BBC, 0x5AFF, 0x8BBD, 0x5B00, 0x8BBE, 0x5B01, 0x8BBF, 0x5B02, 0x8BC0, + 0x5B03, 0x8BC1, 0x5B04, 0x8BC2, 0x5B05, 0x8BC3, 0x5B06, 0x8BC4, 0x5B07, 0x8BC5, 0x5B08, 0x8BC6, 0x5B09, 0xE6D2, 0x5B0A, 0x8BC7, + 0x5B0B, 0x8BC8, 0x5B0C, 0x8BC9, 0x5B0D, 0x8BCA, 0x5B0E, 0x8BCB, 0x5B0F, 0x8BCC, 0x5B10, 0x8BCD, 0x5B11, 0x8BCE, 0x5B12, 0x8BCF, + 0x5B13, 0x8BD0, 0x5B14, 0x8BD1, 0x5B15, 0x8BD2, 0x5B16, 0xE6D4, 0x5B17, 0xE6D3, 0x5B18, 0x8BD3, 0x5B19, 0x8BD4, 0x5B1A, 0x8BD5, + 0x5B1B, 0x8BD6, 0x5B1C, 0x8BD7, 0x5B1D, 0x8BD8, 0x5B1E, 0x8BD9, 0x5B1F, 0x8BDA, 0x5B20, 0x8BDB, 0x5B21, 0x8BDC, 0x5B22, 0x8BDD, + 0x5B23, 0x8BDE, 0x5B24, 0x8BDF, 0x5B25, 0x8BE0, 0x5B26, 0x8BE1, 0x5B27, 0x8BE2, 0x5B28, 0x8BE3, 0x5B29, 0x8BE4, 0x5B2A, 0x8BE5, + 0x5B2B, 0x8BE6, 0x5B2C, 0x8BE7, 0x5B2D, 0x8BE8, 0x5B2E, 0x8BE9, 0x5B2F, 0x8BEA, 0x5B30, 0x8BEB, 0x5B31, 0x8BEC, 0x5B32, 0xE6D5, + 0x5B33, 0x8BED, 0x5B34, 0xD9F8, 0x5B35, 0x8BEE, 0x5B36, 0x8BEF, 0x5B37, 0xE6D6, 0x5B38, 0x8BF0, 0x5B39, 0x8BF1, 0x5B3A, 0x8BF2, + 0x5B3B, 0x8BF3, 0x5B3C, 0x8BF4, 0x5B3D, 0x8BF5, 0x5B3E, 0x8BF6, 0x5B3F, 0x8BF7, 0x5B40, 0xE6D7, 0x5B41, 0x8BF8, 0x5B42, 0x8BF9, + 0x5B43, 0x8BFA, 0x5B44, 0x8BFB, 0x5B45, 0x8BFC, 0x5B46, 0x8BFD, 0x5B47, 0x8BFE, 0x5B48, 0x8C40, 0x5B49, 0x8C41, 0x5B4A, 0x8C42, + 0x5B4B, 0x8C43, 0x5B4C, 0x8C44, 0x5B4D, 0x8C45, 0x5B4E, 0x8C46, 0x5B4F, 0x8C47, 0x5B50, 0xD7D3, 0x5B51, 0xE6DD, 0x5B52, 0x8C48, + 0x5B53, 0xE6DE, 0x5B54, 0xBFD7, 0x5B55, 0xD4D0, 0x5B56, 0x8C49, 0x5B57, 0xD7D6, 0x5B58, 0xB4E6, 0x5B59, 0xCBEF, 0x5B5A, 0xE6DA, + 0x5B5B, 0xD8C3, 0x5B5C, 0xD7CE, 0x5B5D, 0xD0A2, 0x5B5E, 0x8C4A, 0x5B5F, 0xC3CF, 0x5B60, 0x8C4B, 0x5B61, 0x8C4C, 0x5B62, 0xE6DF, + 0x5B63, 0xBCBE, 0x5B64, 0xB9C2, 0x5B65, 0xE6DB, 0x5B66, 0xD1A7, 0x5B67, 0x8C4D, 0x5B68, 0x8C4E, 0x5B69, 0xBAA2, 0x5B6A, 0xC2CF, + 0x5B6B, 0x8C4F, 0x5B6C, 0xD8AB, 0x5B6D, 0x8C50, 0x5B6E, 0x8C51, 0x5B6F, 0x8C52, 0x5B70, 0xCAEB, 0x5B71, 0xE5EE, 0x5B72, 0x8C53, + 0x5B73, 0xE6DC, 0x5B74, 0x8C54, 0x5B75, 0xB7F5, 0x5B76, 0x8C55, 0x5B77, 0x8C56, 0x5B78, 0x8C57, 0x5B79, 0x8C58, 0x5B7A, 0xC8E6, + 0x5B7B, 0x8C59, 0x5B7C, 0x8C5A, 0x5B7D, 0xC4F5, 0x5B7E, 0x8C5B, 0x5B7F, 0x8C5C, 0x5B80, 0xE5B2, 0x5B81, 0xC4FE, 0x5B82, 0x8C5D, + 0x5B83, 0xCBFC, 0x5B84, 0xE5B3, 0x5B85, 0xD5AC, 0x5B86, 0x8C5E, 0x5B87, 0xD3EE, 0x5B88, 0xCAD8, 0x5B89, 0xB0B2, 0x5B8A, 0x8C5F, + 0x5B8B, 0xCBCE, 0x5B8C, 0xCDEA, 0x5B8D, 0x8C60, 0x5B8E, 0x8C61, 0x5B8F, 0xBAEA, 0x5B90, 0x8C62, 0x5B91, 0x8C63, 0x5B92, 0x8C64, + 0x5B93, 0xE5B5, 0x5B94, 0x8C65, 0x5B95, 0xE5B4, 0x5B96, 0x8C66, 0x5B97, 0xD7DA, 0x5B98, 0xB9D9, 0x5B99, 0xD6E6, 0x5B9A, 0xB6A8, + 0x5B9B, 0xCDF0, 0x5B9C, 0xD2CB, 0x5B9D, 0xB1A6, 0x5B9E, 0xCAB5, 0x5B9F, 0x8C67, 0x5BA0, 0xB3E8, 0x5BA1, 0xC9F3, 0x5BA2, 0xBFCD, + 0x5BA3, 0xD0FB, 0x5BA4, 0xCAD2, 0x5BA5, 0xE5B6, 0x5BA6, 0xBBC2, 0x5BA7, 0x8C68, 0x5BA8, 0x8C69, 0x5BA9, 0x8C6A, 0x5BAA, 0xCFDC, + 0x5BAB, 0xB9AC, 0x5BAC, 0x8C6B, 0x5BAD, 0x8C6C, 0x5BAE, 0x8C6D, 0x5BAF, 0x8C6E, 0x5BB0, 0xD4D7, 0x5BB1, 0x8C6F, 0x5BB2, 0x8C70, + 0x5BB3, 0xBAA6, 0x5BB4, 0xD1E7, 0x5BB5, 0xCFFC, 0x5BB6, 0xBCD2, 0x5BB7, 0x8C71, 0x5BB8, 0xE5B7, 0x5BB9, 0xC8DD, 0x5BBA, 0x8C72, + 0x5BBB, 0x8C73, 0x5BBC, 0x8C74, 0x5BBD, 0xBFED, 0x5BBE, 0xB1F6, 0x5BBF, 0xCBDE, 0x5BC0, 0x8C75, 0x5BC1, 0x8C76, 0x5BC2, 0xBCC5, + 0x5BC3, 0x8C77, 0x5BC4, 0xBCC4, 0x5BC5, 0xD2FA, 0x5BC6, 0xC3DC, 0x5BC7, 0xBFDC, 0x5BC8, 0x8C78, 0x5BC9, 0x8C79, 0x5BCA, 0x8C7A, + 0x5BCB, 0x8C7B, 0x5BCC, 0xB8BB, 0x5BCD, 0x8C7C, 0x5BCE, 0x8C7D, 0x5BCF, 0x8C7E, 0x5BD0, 0xC3C2, 0x5BD1, 0x8C80, 0x5BD2, 0xBAAE, + 0x5BD3, 0xD4A2, 0x5BD4, 0x8C81, 0x5BD5, 0x8C82, 0x5BD6, 0x8C83, 0x5BD7, 0x8C84, 0x5BD8, 0x8C85, 0x5BD9, 0x8C86, 0x5BDA, 0x8C87, + 0x5BDB, 0x8C88, 0x5BDC, 0x8C89, 0x5BDD, 0xC7DE, 0x5BDE, 0xC4AF, 0x5BDF, 0xB2EC, 0x5BE0, 0x8C8A, 0x5BE1, 0xB9D1, 0x5BE2, 0x8C8B, + 0x5BE3, 0x8C8C, 0x5BE4, 0xE5BB, 0x5BE5, 0xC1C8, 0x5BE6, 0x8C8D, 0x5BE7, 0x8C8E, 0x5BE8, 0xD5AF, 0x5BE9, 0x8C8F, 0x5BEA, 0x8C90, + 0x5BEB, 0x8C91, 0x5BEC, 0x8C92, 0x5BED, 0x8C93, 0x5BEE, 0xE5BC, 0x5BEF, 0x8C94, 0x5BF0, 0xE5BE, 0x5BF1, 0x8C95, 0x5BF2, 0x8C96, + 0x5BF3, 0x8C97, 0x5BF4, 0x8C98, 0x5BF5, 0x8C99, 0x5BF6, 0x8C9A, 0x5BF7, 0x8C9B, 0x5BF8, 0xB4E7, 0x5BF9, 0xB6D4, 0x5BFA, 0xCBC2, + 0x5BFB, 0xD1B0, 0x5BFC, 0xB5BC, 0x5BFD, 0x8C9C, 0x5BFE, 0x8C9D, 0x5BFF, 0xCAD9, 0x5C00, 0x8C9E, 0x5C01, 0xB7E2, 0x5C02, 0x8C9F, + 0x5C03, 0x8CA0, 0x5C04, 0xC9E4, 0x5C05, 0x8CA1, 0x5C06, 0xBDAB, 0x5C07, 0x8CA2, 0x5C08, 0x8CA3, 0x5C09, 0xCEBE, 0x5C0A, 0xD7F0, + 0x5C0B, 0x8CA4, 0x5C0C, 0x8CA5, 0x5C0D, 0x8CA6, 0x5C0E, 0x8CA7, 0x5C0F, 0xD0A1, 0x5C10, 0x8CA8, 0x5C11, 0xC9D9, 0x5C12, 0x8CA9, + 0x5C13, 0x8CAA, 0x5C14, 0xB6FB, 0x5C15, 0xE6D8, 0x5C16, 0xBCE2, 0x5C17, 0x8CAB, 0x5C18, 0xB3BE, 0x5C19, 0x8CAC, 0x5C1A, 0xC9D0, + 0x5C1B, 0x8CAD, 0x5C1C, 0xE6D9, 0x5C1D, 0xB3A2, 0x5C1E, 0x8CAE, 0x5C1F, 0x8CAF, 0x5C20, 0x8CB0, 0x5C21, 0x8CB1, 0x5C22, 0xDECC, + 0x5C23, 0x8CB2, 0x5C24, 0xD3C8, 0x5C25, 0xDECD, 0x5C26, 0x8CB3, 0x5C27, 0xD2A2, 0x5C28, 0x8CB4, 0x5C29, 0x8CB5, 0x5C2A, 0x8CB6, + 0x5C2B, 0x8CB7, 0x5C2C, 0xDECE, 0x5C2D, 0x8CB8, 0x5C2E, 0x8CB9, 0x5C2F, 0x8CBA, 0x5C30, 0x8CBB, 0x5C31, 0xBECD, 0x5C32, 0x8CBC, + 0x5C33, 0x8CBD, 0x5C34, 0xDECF, 0x5C35, 0x8CBE, 0x5C36, 0x8CBF, 0x5C37, 0x8CC0, 0x5C38, 0xCAAC, 0x5C39, 0xD2FC, 0x5C3A, 0xB3DF, + 0x5C3B, 0xE5EA, 0x5C3C, 0xC4E1, 0x5C3D, 0xBEA1, 0x5C3E, 0xCEB2, 0x5C3F, 0xC4F2, 0x5C40, 0xBED6, 0x5C41, 0xC6A8, 0x5C42, 0xB2E3, + 0x5C43, 0x8CC1, 0x5C44, 0x8CC2, 0x5C45, 0xBED3, 0x5C46, 0x8CC3, 0x5C47, 0x8CC4, 0x5C48, 0xC7FC, 0x5C49, 0xCCEB, 0x5C4A, 0xBDEC, + 0x5C4B, 0xCEDD, 0x5C4C, 0x8CC5, 0x5C4D, 0x8CC6, 0x5C4E, 0xCABA, 0x5C4F, 0xC6C1, 0x5C50, 0xE5EC, 0x5C51, 0xD0BC, 0x5C52, 0x8CC7, + 0x5C53, 0x8CC8, 0x5C54, 0x8CC9, 0x5C55, 0xD5B9, 0x5C56, 0x8CCA, 0x5C57, 0x8CCB, 0x5C58, 0x8CCC, 0x5C59, 0xE5ED, 0x5C5A, 0x8CCD, + 0x5C5B, 0x8CCE, 0x5C5C, 0x8CCF, 0x5C5D, 0x8CD0, 0x5C5E, 0xCAF4, 0x5C5F, 0x8CD1, 0x5C60, 0xCDC0, 0x5C61, 0xC2C5, 0x5C62, 0x8CD2, + 0x5C63, 0xE5EF, 0x5C64, 0x8CD3, 0x5C65, 0xC2C4, 0x5C66, 0xE5F0, 0x5C67, 0x8CD4, 0x5C68, 0x8CD5, 0x5C69, 0x8CD6, 0x5C6A, 0x8CD7, + 0x5C6B, 0x8CD8, 0x5C6C, 0x8CD9, 0x5C6D, 0x8CDA, 0x5C6E, 0xE5F8, 0x5C6F, 0xCDCD, 0x5C70, 0x8CDB, 0x5C71, 0xC9BD, 0x5C72, 0x8CDC, + 0x5C73, 0x8CDD, 0x5C74, 0x8CDE, 0x5C75, 0x8CDF, 0x5C76, 0x8CE0, 0x5C77, 0x8CE1, 0x5C78, 0x8CE2, 0x5C79, 0xD2D9, 0x5C7A, 0xE1A8, + 0x5C7B, 0x8CE3, 0x5C7C, 0x8CE4, 0x5C7D, 0x8CE5, 0x5C7E, 0x8CE6, 0x5C7F, 0xD3EC, 0x5C80, 0x8CE7, 0x5C81, 0xCBEA, 0x5C82, 0xC6F1, + 0x5C83, 0x8CE8, 0x5C84, 0x8CE9, 0x5C85, 0x8CEA, 0x5C86, 0x8CEB, 0x5C87, 0x8CEC, 0x5C88, 0xE1AC, 0x5C89, 0x8CED, 0x5C8A, 0x8CEE, + 0x5C8B, 0x8CEF, 0x5C8C, 0xE1A7, 0x5C8D, 0xE1A9, 0x5C8E, 0x8CF0, 0x5C8F, 0x8CF1, 0x5C90, 0xE1AA, 0x5C91, 0xE1AF, 0x5C92, 0x8CF2, + 0x5C93, 0x8CF3, 0x5C94, 0xB2ED, 0x5C95, 0x8CF4, 0x5C96, 0xE1AB, 0x5C97, 0xB8DA, 0x5C98, 0xE1AD, 0x5C99, 0xE1AE, 0x5C9A, 0xE1B0, + 0x5C9B, 0xB5BA, 0x5C9C, 0xE1B1, 0x5C9D, 0x8CF5, 0x5C9E, 0x8CF6, 0x5C9F, 0x8CF7, 0x5CA0, 0x8CF8, 0x5CA1, 0x8CF9, 0x5CA2, 0xE1B3, + 0x5CA3, 0xE1B8, 0x5CA4, 0x8CFA, 0x5CA5, 0x8CFB, 0x5CA6, 0x8CFC, 0x5CA7, 0x8CFD, 0x5CA8, 0x8CFE, 0x5CA9, 0xD1D2, 0x5CAA, 0x8D40, + 0x5CAB, 0xE1B6, 0x5CAC, 0xE1B5, 0x5CAD, 0xC1EB, 0x5CAE, 0x8D41, 0x5CAF, 0x8D42, 0x5CB0, 0x8D43, 0x5CB1, 0xE1B7, 0x5CB2, 0x8D44, + 0x5CB3, 0xD4C0, 0x5CB4, 0x8D45, 0x5CB5, 0xE1B2, 0x5CB6, 0x8D46, 0x5CB7, 0xE1BA, 0x5CB8, 0xB0B6, 0x5CB9, 0x8D47, 0x5CBA, 0x8D48, + 0x5CBB, 0x8D49, 0x5CBC, 0x8D4A, 0x5CBD, 0xE1B4, 0x5CBE, 0x8D4B, 0x5CBF, 0xBFF9, 0x5CC0, 0x8D4C, 0x5CC1, 0xE1B9, 0x5CC2, 0x8D4D, + 0x5CC3, 0x8D4E, 0x5CC4, 0xE1BB, 0x5CC5, 0x8D4F, 0x5CC6, 0x8D50, 0x5CC7, 0x8D51, 0x5CC8, 0x8D52, 0x5CC9, 0x8D53, 0x5CCA, 0x8D54, + 0x5CCB, 0xE1BE, 0x5CCC, 0x8D55, 0x5CCD, 0x8D56, 0x5CCE, 0x8D57, 0x5CCF, 0x8D58, 0x5CD0, 0x8D59, 0x5CD1, 0x8D5A, 0x5CD2, 0xE1BC, + 0x5CD3, 0x8D5B, 0x5CD4, 0x8D5C, 0x5CD5, 0x8D5D, 0x5CD6, 0x8D5E, 0x5CD7, 0x8D5F, 0x5CD8, 0x8D60, 0x5CD9, 0xD6C5, 0x5CDA, 0x8D61, + 0x5CDB, 0x8D62, 0x5CDC, 0x8D63, 0x5CDD, 0x8D64, 0x5CDE, 0x8D65, 0x5CDF, 0x8D66, 0x5CE0, 0x8D67, 0x5CE1, 0xCFBF, 0x5CE2, 0x8D68, + 0x5CE3, 0x8D69, 0x5CE4, 0xE1BD, 0x5CE5, 0xE1BF, 0x5CE6, 0xC2CD, 0x5CE7, 0x8D6A, 0x5CE8, 0xB6EB, 0x5CE9, 0x8D6B, 0x5CEA, 0xD3F8, + 0x5CEB, 0x8D6C, 0x5CEC, 0x8D6D, 0x5CED, 0xC7CD, 0x5CEE, 0x8D6E, 0x5CEF, 0x8D6F, 0x5CF0, 0xB7E5, 0x5CF1, 0x8D70, 0x5CF2, 0x8D71, + 0x5CF3, 0x8D72, 0x5CF4, 0x8D73, 0x5CF5, 0x8D74, 0x5CF6, 0x8D75, 0x5CF7, 0x8D76, 0x5CF8, 0x8D77, 0x5CF9, 0x8D78, 0x5CFA, 0x8D79, + 0x5CFB, 0xBEFE, 0x5CFC, 0x8D7A, 0x5CFD, 0x8D7B, 0x5CFE, 0x8D7C, 0x5CFF, 0x8D7D, 0x5D00, 0x8D7E, 0x5D01, 0x8D80, 0x5D02, 0xE1C0, + 0x5D03, 0xE1C1, 0x5D04, 0x8D81, 0x5D05, 0x8D82, 0x5D06, 0xE1C7, 0x5D07, 0xB3E7, 0x5D08, 0x8D83, 0x5D09, 0x8D84, 0x5D0A, 0x8D85, + 0x5D0B, 0x8D86, 0x5D0C, 0x8D87, 0x5D0D, 0x8D88, 0x5D0E, 0xC6E9, 0x5D0F, 0x8D89, 0x5D10, 0x8D8A, 0x5D11, 0x8D8B, 0x5D12, 0x8D8C, + 0x5D13, 0x8D8D, 0x5D14, 0xB4DE, 0x5D15, 0x8D8E, 0x5D16, 0xD1C2, 0x5D17, 0x8D8F, 0x5D18, 0x8D90, 0x5D19, 0x8D91, 0x5D1A, 0x8D92, + 0x5D1B, 0xE1C8, 0x5D1C, 0x8D93, 0x5D1D, 0x8D94, 0x5D1E, 0xE1C6, 0x5D1F, 0x8D95, 0x5D20, 0x8D96, 0x5D21, 0x8D97, 0x5D22, 0x8D98, + 0x5D23, 0x8D99, 0x5D24, 0xE1C5, 0x5D25, 0x8D9A, 0x5D26, 0xE1C3, 0x5D27, 0xE1C2, 0x5D28, 0x8D9B, 0x5D29, 0xB1C0, 0x5D2A, 0x8D9C, + 0x5D2B, 0x8D9D, 0x5D2C, 0x8D9E, 0x5D2D, 0xD5B8, 0x5D2E, 0xE1C4, 0x5D2F, 0x8D9F, 0x5D30, 0x8DA0, 0x5D31, 0x8DA1, 0x5D32, 0x8DA2, + 0x5D33, 0x8DA3, 0x5D34, 0xE1CB, 0x5D35, 0x8DA4, 0x5D36, 0x8DA5, 0x5D37, 0x8DA6, 0x5D38, 0x8DA7, 0x5D39, 0x8DA8, 0x5D3A, 0x8DA9, + 0x5D3B, 0x8DAA, 0x5D3C, 0x8DAB, 0x5D3D, 0xE1CC, 0x5D3E, 0xE1CA, 0x5D3F, 0x8DAC, 0x5D40, 0x8DAD, 0x5D41, 0x8DAE, 0x5D42, 0x8DAF, + 0x5D43, 0x8DB0, 0x5D44, 0x8DB1, 0x5D45, 0x8DB2, 0x5D46, 0x8DB3, 0x5D47, 0xEFFA, 0x5D48, 0x8DB4, 0x5D49, 0x8DB5, 0x5D4A, 0xE1D3, + 0x5D4B, 0xE1D2, 0x5D4C, 0xC7B6, 0x5D4D, 0x8DB6, 0x5D4E, 0x8DB7, 0x5D4F, 0x8DB8, 0x5D50, 0x8DB9, 0x5D51, 0x8DBA, 0x5D52, 0x8DBB, + 0x5D53, 0x8DBC, 0x5D54, 0x8DBD, 0x5D55, 0x8DBE, 0x5D56, 0x8DBF, 0x5D57, 0x8DC0, 0x5D58, 0xE1C9, 0x5D59, 0x8DC1, 0x5D5A, 0x8DC2, + 0x5D5B, 0xE1CE, 0x5D5C, 0x8DC3, 0x5D5D, 0xE1D0, 0x5D5E, 0x8DC4, 0x5D5F, 0x8DC5, 0x5D60, 0x8DC6, 0x5D61, 0x8DC7, 0x5D62, 0x8DC8, + 0x5D63, 0x8DC9, 0x5D64, 0x8DCA, 0x5D65, 0x8DCB, 0x5D66, 0x8DCC, 0x5D67, 0x8DCD, 0x5D68, 0x8DCE, 0x5D69, 0xE1D4, 0x5D6A, 0x8DCF, + 0x5D6B, 0xE1D1, 0x5D6C, 0xE1CD, 0x5D6D, 0x8DD0, 0x5D6E, 0x8DD1, 0x5D6F, 0xE1CF, 0x5D70, 0x8DD2, 0x5D71, 0x8DD3, 0x5D72, 0x8DD4, + 0x5D73, 0x8DD5, 0x5D74, 0xE1D5, 0x5D75, 0x8DD6, 0x5D76, 0x8DD7, 0x5D77, 0x8DD8, 0x5D78, 0x8DD9, 0x5D79, 0x8DDA, 0x5D7A, 0x8DDB, + 0x5D7B, 0x8DDC, 0x5D7C, 0x8DDD, 0x5D7D, 0x8DDE, 0x5D7E, 0x8DDF, 0x5D7F, 0x8DE0, 0x5D80, 0x8DE1, 0x5D81, 0x8DE2, 0x5D82, 0xE1D6, + 0x5D83, 0x8DE3, 0x5D84, 0x8DE4, 0x5D85, 0x8DE5, 0x5D86, 0x8DE6, 0x5D87, 0x8DE7, 0x5D88, 0x8DE8, 0x5D89, 0x8DE9, 0x5D8A, 0x8DEA, + 0x5D8B, 0x8DEB, 0x5D8C, 0x8DEC, 0x5D8D, 0x8DED, 0x5D8E, 0x8DEE, 0x5D8F, 0x8DEF, 0x5D90, 0x8DF0, 0x5D91, 0x8DF1, 0x5D92, 0x8DF2, + 0x5D93, 0x8DF3, 0x5D94, 0x8DF4, 0x5D95, 0x8DF5, 0x5D96, 0x8DF6, 0x5D97, 0x8DF7, 0x5D98, 0x8DF8, 0x5D99, 0xE1D7, 0x5D9A, 0x8DF9, + 0x5D9B, 0x8DFA, 0x5D9C, 0x8DFB, 0x5D9D, 0xE1D8, 0x5D9E, 0x8DFC, 0x5D9F, 0x8DFD, 0x5DA0, 0x8DFE, 0x5DA1, 0x8E40, 0x5DA2, 0x8E41, + 0x5DA3, 0x8E42, 0x5DA4, 0x8E43, 0x5DA5, 0x8E44, 0x5DA6, 0x8E45, 0x5DA7, 0x8E46, 0x5DA8, 0x8E47, 0x5DA9, 0x8E48, 0x5DAA, 0x8E49, + 0x5DAB, 0x8E4A, 0x5DAC, 0x8E4B, 0x5DAD, 0x8E4C, 0x5DAE, 0x8E4D, 0x5DAF, 0x8E4E, 0x5DB0, 0x8E4F, 0x5DB1, 0x8E50, 0x5DB2, 0x8E51, + 0x5DB3, 0x8E52, 0x5DB4, 0x8E53, 0x5DB5, 0x8E54, 0x5DB6, 0x8E55, 0x5DB7, 0xE1DA, 0x5DB8, 0x8E56, 0x5DB9, 0x8E57, 0x5DBA, 0x8E58, + 0x5DBB, 0x8E59, 0x5DBC, 0x8E5A, 0x5DBD, 0x8E5B, 0x5DBE, 0x8E5C, 0x5DBF, 0x8E5D, 0x5DC0, 0x8E5E, 0x5DC1, 0x8E5F, 0x5DC2, 0x8E60, + 0x5DC3, 0x8E61, 0x5DC4, 0x8E62, 0x5DC5, 0xE1DB, 0x5DC6, 0x8E63, 0x5DC7, 0x8E64, 0x5DC8, 0x8E65, 0x5DC9, 0x8E66, 0x5DCA, 0x8E67, + 0x5DCB, 0x8E68, 0x5DCC, 0x8E69, 0x5DCD, 0xCEA1, 0x5DCE, 0x8E6A, 0x5DCF, 0x8E6B, 0x5DD0, 0x8E6C, 0x5DD1, 0x8E6D, 0x5DD2, 0x8E6E, + 0x5DD3, 0x8E6F, 0x5DD4, 0x8E70, 0x5DD5, 0x8E71, 0x5DD6, 0x8E72, 0x5DD7, 0x8E73, 0x5DD8, 0x8E74, 0x5DD9, 0x8E75, 0x5DDA, 0x8E76, + 0x5DDB, 0xE7DD, 0x5DDC, 0x8E77, 0x5DDD, 0xB4A8, 0x5DDE, 0xD6DD, 0x5DDF, 0x8E78, 0x5DE0, 0x8E79, 0x5DE1, 0xD1B2, 0x5DE2, 0xB3B2, + 0x5DE3, 0x8E7A, 0x5DE4, 0x8E7B, 0x5DE5, 0xB9A4, 0x5DE6, 0xD7F3, 0x5DE7, 0xC7C9, 0x5DE8, 0xBEDE, 0x5DE9, 0xB9AE, 0x5DEA, 0x8E7C, + 0x5DEB, 0xCED7, 0x5DEC, 0x8E7D, 0x5DED, 0x8E7E, 0x5DEE, 0xB2EE, 0x5DEF, 0xDBCF, 0x5DF0, 0x8E80, 0x5DF1, 0xBCBA, 0x5DF2, 0xD2D1, + 0x5DF3, 0xCBC8, 0x5DF4, 0xB0CD, 0x5DF5, 0x8E81, 0x5DF6, 0x8E82, 0x5DF7, 0xCFEF, 0x5DF8, 0x8E83, 0x5DF9, 0x8E84, 0x5DFA, 0x8E85, + 0x5DFB, 0x8E86, 0x5DFC, 0x8E87, 0x5DFD, 0xD9E3, 0x5DFE, 0xBDED, 0x5DFF, 0x8E88, 0x5E00, 0x8E89, 0x5E01, 0xB1D2, 0x5E02, 0xCAD0, + 0x5E03, 0xB2BC, 0x5E04, 0x8E8A, 0x5E05, 0xCBA7, 0x5E06, 0xB7AB, 0x5E07, 0x8E8B, 0x5E08, 0xCAA6, 0x5E09, 0x8E8C, 0x5E0A, 0x8E8D, + 0x5E0B, 0x8E8E, 0x5E0C, 0xCFA3, 0x5E0D, 0x8E8F, 0x5E0E, 0x8E90, 0x5E0F, 0xE0F8, 0x5E10, 0xD5CA, 0x5E11, 0xE0FB, 0x5E12, 0x8E91, + 0x5E13, 0x8E92, 0x5E14, 0xE0FA, 0x5E15, 0xC5C1, 0x5E16, 0xCCFB, 0x5E17, 0x8E93, 0x5E18, 0xC1B1, 0x5E19, 0xE0F9, 0x5E1A, 0xD6E3, + 0x5E1B, 0xB2AF, 0x5E1C, 0xD6C4, 0x5E1D, 0xB5DB, 0x5E1E, 0x8E94, 0x5E1F, 0x8E95, 0x5E20, 0x8E96, 0x5E21, 0x8E97, 0x5E22, 0x8E98, + 0x5E23, 0x8E99, 0x5E24, 0x8E9A, 0x5E25, 0x8E9B, 0x5E26, 0xB4F8, 0x5E27, 0xD6A1, 0x5E28, 0x8E9C, 0x5E29, 0x8E9D, 0x5E2A, 0x8E9E, + 0x5E2B, 0x8E9F, 0x5E2C, 0x8EA0, 0x5E2D, 0xCFAF, 0x5E2E, 0xB0EF, 0x5E2F, 0x8EA1, 0x5E30, 0x8EA2, 0x5E31, 0xE0FC, 0x5E32, 0x8EA3, + 0x5E33, 0x8EA4, 0x5E34, 0x8EA5, 0x5E35, 0x8EA6, 0x5E36, 0x8EA7, 0x5E37, 0xE1A1, 0x5E38, 0xB3A3, 0x5E39, 0x8EA8, 0x5E3A, 0x8EA9, + 0x5E3B, 0xE0FD, 0x5E3C, 0xE0FE, 0x5E3D, 0xC3B1, 0x5E3E, 0x8EAA, 0x5E3F, 0x8EAB, 0x5E40, 0x8EAC, 0x5E41, 0x8EAD, 0x5E42, 0xC3DD, + 0x5E43, 0x8EAE, 0x5E44, 0xE1A2, 0x5E45, 0xB7F9, 0x5E46, 0x8EAF, 0x5E47, 0x8EB0, 0x5E48, 0x8EB1, 0x5E49, 0x8EB2, 0x5E4A, 0x8EB3, + 0x5E4B, 0x8EB4, 0x5E4C, 0xBBCF, 0x5E4D, 0x8EB5, 0x5E4E, 0x8EB6, 0x5E4F, 0x8EB7, 0x5E50, 0x8EB8, 0x5E51, 0x8EB9, 0x5E52, 0x8EBA, + 0x5E53, 0x8EBB, 0x5E54, 0xE1A3, 0x5E55, 0xC4BB, 0x5E56, 0x8EBC, 0x5E57, 0x8EBD, 0x5E58, 0x8EBE, 0x5E59, 0x8EBF, 0x5E5A, 0x8EC0, + 0x5E5B, 0xE1A4, 0x5E5C, 0x8EC1, 0x5E5D, 0x8EC2, 0x5E5E, 0xE1A5, 0x5E5F, 0x8EC3, 0x5E60, 0x8EC4, 0x5E61, 0xE1A6, 0x5E62, 0xB4B1, + 0x5E63, 0x8EC5, 0x5E64, 0x8EC6, 0x5E65, 0x8EC7, 0x5E66, 0x8EC8, 0x5E67, 0x8EC9, 0x5E68, 0x8ECA, 0x5E69, 0x8ECB, 0x5E6A, 0x8ECC, + 0x5E6B, 0x8ECD, 0x5E6C, 0x8ECE, 0x5E6D, 0x8ECF, 0x5E6E, 0x8ED0, 0x5E6F, 0x8ED1, 0x5E70, 0x8ED2, 0x5E71, 0x8ED3, 0x5E72, 0xB8C9, + 0x5E73, 0xC6BD, 0x5E74, 0xC4EA, 0x5E75, 0x8ED4, 0x5E76, 0xB2A2, 0x5E77, 0x8ED5, 0x5E78, 0xD0D2, 0x5E79, 0x8ED6, 0x5E7A, 0xE7DB, + 0x5E7B, 0xBBC3, 0x5E7C, 0xD3D7, 0x5E7D, 0xD3C4, 0x5E7E, 0x8ED7, 0x5E7F, 0xB9E3, 0x5E80, 0xE2CF, 0x5E81, 0x8ED8, 0x5E82, 0x8ED9, + 0x5E83, 0x8EDA, 0x5E84, 0xD7AF, 0x5E85, 0x8EDB, 0x5E86, 0xC7EC, 0x5E87, 0xB1D3, 0x5E88, 0x8EDC, 0x5E89, 0x8EDD, 0x5E8A, 0xB4B2, + 0x5E8B, 0xE2D1, 0x5E8C, 0x8EDE, 0x5E8D, 0x8EDF, 0x5E8E, 0x8EE0, 0x5E8F, 0xD0F2, 0x5E90, 0xC2AE, 0x5E91, 0xE2D0, 0x5E92, 0x8EE1, + 0x5E93, 0xBFE2, 0x5E94, 0xD3A6, 0x5E95, 0xB5D7, 0x5E96, 0xE2D2, 0x5E97, 0xB5EA, 0x5E98, 0x8EE2, 0x5E99, 0xC3ED, 0x5E9A, 0xB8FD, + 0x5E9B, 0x8EE3, 0x5E9C, 0xB8AE, 0x5E9D, 0x8EE4, 0x5E9E, 0xC5D3, 0x5E9F, 0xB7CF, 0x5EA0, 0xE2D4, 0x5EA1, 0x8EE5, 0x5EA2, 0x8EE6, + 0x5EA3, 0x8EE7, 0x5EA4, 0x8EE8, 0x5EA5, 0xE2D3, 0x5EA6, 0xB6C8, 0x5EA7, 0xD7F9, 0x5EA8, 0x8EE9, 0x5EA9, 0x8EEA, 0x5EAA, 0x8EEB, + 0x5EAB, 0x8EEC, 0x5EAC, 0x8EED, 0x5EAD, 0xCDA5, 0x5EAE, 0x8EEE, 0x5EAF, 0x8EEF, 0x5EB0, 0x8EF0, 0x5EB1, 0x8EF1, 0x5EB2, 0x8EF2, + 0x5EB3, 0xE2D8, 0x5EB4, 0x8EF3, 0x5EB5, 0xE2D6, 0x5EB6, 0xCAFC, 0x5EB7, 0xBFB5, 0x5EB8, 0xD3B9, 0x5EB9, 0xE2D5, 0x5EBA, 0x8EF4, + 0x5EBB, 0x8EF5, 0x5EBC, 0x8EF6, 0x5EBD, 0x8EF7, 0x5EBE, 0xE2D7, 0x5EBF, 0x8EF8, 0x5EC0, 0x8EF9, 0x5EC1, 0x8EFA, 0x5EC2, 0x8EFB, + 0x5EC3, 0x8EFC, 0x5EC4, 0x8EFD, 0x5EC5, 0x8EFE, 0x5EC6, 0x8F40, 0x5EC7, 0x8F41, 0x5EC8, 0x8F42, 0x5EC9, 0xC1AE, 0x5ECA, 0xC0C8, + 0x5ECB, 0x8F43, 0x5ECC, 0x8F44, 0x5ECD, 0x8F45, 0x5ECE, 0x8F46, 0x5ECF, 0x8F47, 0x5ED0, 0x8F48, 0x5ED1, 0xE2DB, 0x5ED2, 0xE2DA, + 0x5ED3, 0xC0AA, 0x5ED4, 0x8F49, 0x5ED5, 0x8F4A, 0x5ED6, 0xC1CE, 0x5ED7, 0x8F4B, 0x5ED8, 0x8F4C, 0x5ED9, 0x8F4D, 0x5EDA, 0x8F4E, + 0x5EDB, 0xE2DC, 0x5EDC, 0x8F4F, 0x5EDD, 0x8F50, 0x5EDE, 0x8F51, 0x5EDF, 0x8F52, 0x5EE0, 0x8F53, 0x5EE1, 0x8F54, 0x5EE2, 0x8F55, + 0x5EE3, 0x8F56, 0x5EE4, 0x8F57, 0x5EE5, 0x8F58, 0x5EE6, 0x8F59, 0x5EE7, 0x8F5A, 0x5EE8, 0xE2DD, 0x5EE9, 0x8F5B, 0x5EEA, 0xE2DE, + 0x5EEB, 0x8F5C, 0x5EEC, 0x8F5D, 0x5EED, 0x8F5E, 0x5EEE, 0x8F5F, 0x5EEF, 0x8F60, 0x5EF0, 0x8F61, 0x5EF1, 0x8F62, 0x5EF2, 0x8F63, + 0x5EF3, 0x8F64, 0x5EF4, 0xDBC8, 0x5EF5, 0x8F65, 0x5EF6, 0xD1D3, 0x5EF7, 0xCDA2, 0x5EF8, 0x8F66, 0x5EF9, 0x8F67, 0x5EFA, 0xBDA8, + 0x5EFB, 0x8F68, 0x5EFC, 0x8F69, 0x5EFD, 0x8F6A, 0x5EFE, 0xDEC3, 0x5EFF, 0xD8A5, 0x5F00, 0xBFAA, 0x5F01, 0xDBCD, 0x5F02, 0xD2EC, + 0x5F03, 0xC6FA, 0x5F04, 0xC5AA, 0x5F05, 0x8F6B, 0x5F06, 0x8F6C, 0x5F07, 0x8F6D, 0x5F08, 0xDEC4, 0x5F09, 0x8F6E, 0x5F0A, 0xB1D7, + 0x5F0B, 0xDFAE, 0x5F0C, 0x8F6F, 0x5F0D, 0x8F70, 0x5F0E, 0x8F71, 0x5F0F, 0xCABD, 0x5F10, 0x8F72, 0x5F11, 0xDFB1, 0x5F12, 0x8F73, + 0x5F13, 0xB9AD, 0x5F14, 0x8F74, 0x5F15, 0xD2FD, 0x5F16, 0x8F75, 0x5F17, 0xB8A5, 0x5F18, 0xBAEB, 0x5F19, 0x8F76, 0x5F1A, 0x8F77, + 0x5F1B, 0xB3DA, 0x5F1C, 0x8F78, 0x5F1D, 0x8F79, 0x5F1E, 0x8F7A, 0x5F1F, 0xB5DC, 0x5F20, 0xD5C5, 0x5F21, 0x8F7B, 0x5F22, 0x8F7C, + 0x5F23, 0x8F7D, 0x5F24, 0x8F7E, 0x5F25, 0xC3D6, 0x5F26, 0xCFD2, 0x5F27, 0xBBA1, 0x5F28, 0x8F80, 0x5F29, 0xE5F3, 0x5F2A, 0xE5F2, + 0x5F2B, 0x8F81, 0x5F2C, 0x8F82, 0x5F2D, 0xE5F4, 0x5F2E, 0x8F83, 0x5F2F, 0xCDE4, 0x5F30, 0x8F84, 0x5F31, 0xC8F5, 0x5F32, 0x8F85, + 0x5F33, 0x8F86, 0x5F34, 0x8F87, 0x5F35, 0x8F88, 0x5F36, 0x8F89, 0x5F37, 0x8F8A, 0x5F38, 0x8F8B, 0x5F39, 0xB5AF, 0x5F3A, 0xC7BF, + 0x5F3B, 0x8F8C, 0x5F3C, 0xE5F6, 0x5F3D, 0x8F8D, 0x5F3E, 0x8F8E, 0x5F3F, 0x8F8F, 0x5F40, 0xECB0, 0x5F41, 0x8F90, 0x5F42, 0x8F91, + 0x5F43, 0x8F92, 0x5F44, 0x8F93, 0x5F45, 0x8F94, 0x5F46, 0x8F95, 0x5F47, 0x8F96, 0x5F48, 0x8F97, 0x5F49, 0x8F98, 0x5F4A, 0x8F99, + 0x5F4B, 0x8F9A, 0x5F4C, 0x8F9B, 0x5F4D, 0x8F9C, 0x5F4E, 0x8F9D, 0x5F4F, 0x8F9E, 0x5F50, 0xE5E6, 0x5F51, 0x8F9F, 0x5F52, 0xB9E9, + 0x5F53, 0xB5B1, 0x5F54, 0x8FA0, 0x5F55, 0xC2BC, 0x5F56, 0xE5E8, 0x5F57, 0xE5E7, 0x5F58, 0xE5E9, 0x5F59, 0x8FA1, 0x5F5A, 0x8FA2, + 0x5F5B, 0x8FA3, 0x5F5C, 0x8FA4, 0x5F5D, 0xD2CD, 0x5F5E, 0x8FA5, 0x5F5F, 0x8FA6, 0x5F60, 0x8FA7, 0x5F61, 0xE1EA, 0x5F62, 0xD0CE, + 0x5F63, 0x8FA8, 0x5F64, 0xCDAE, 0x5F65, 0x8FA9, 0x5F66, 0xD1E5, 0x5F67, 0x8FAA, 0x5F68, 0x8FAB, 0x5F69, 0xB2CA, 0x5F6A, 0xB1EB, + 0x5F6B, 0x8FAC, 0x5F6C, 0xB1F2, 0x5F6D, 0xC5ED, 0x5F6E, 0x8FAD, 0x5F6F, 0x8FAE, 0x5F70, 0xD5C3, 0x5F71, 0xD3B0, 0x5F72, 0x8FAF, + 0x5F73, 0xE1DC, 0x5F74, 0x8FB0, 0x5F75, 0x8FB1, 0x5F76, 0x8FB2, 0x5F77, 0xE1DD, 0x5F78, 0x8FB3, 0x5F79, 0xD2DB, 0x5F7A, 0x8FB4, + 0x5F7B, 0xB3B9, 0x5F7C, 0xB1CB, 0x5F7D, 0x8FB5, 0x5F7E, 0x8FB6, 0x5F7F, 0x8FB7, 0x5F80, 0xCDF9, 0x5F81, 0xD5F7, 0x5F82, 0xE1DE, + 0x5F83, 0x8FB8, 0x5F84, 0xBEB6, 0x5F85, 0xB4FD, 0x5F86, 0x8FB9, 0x5F87, 0xE1DF, 0x5F88, 0xBADC, 0x5F89, 0xE1E0, 0x5F8A, 0xBBB2, + 0x5F8B, 0xC2C9, 0x5F8C, 0xE1E1, 0x5F8D, 0x8FBA, 0x5F8E, 0x8FBB, 0x5F8F, 0x8FBC, 0x5F90, 0xD0EC, 0x5F91, 0x8FBD, 0x5F92, 0xCDBD, + 0x5F93, 0x8FBE, 0x5F94, 0x8FBF, 0x5F95, 0xE1E2, 0x5F96, 0x8FC0, 0x5F97, 0xB5C3, 0x5F98, 0xC5C7, 0x5F99, 0xE1E3, 0x5F9A, 0x8FC1, + 0x5F9B, 0x8FC2, 0x5F9C, 0xE1E4, 0x5F9D, 0x8FC3, 0x5F9E, 0x8FC4, 0x5F9F, 0x8FC5, 0x5FA0, 0x8FC6, 0x5FA1, 0xD3F9, 0x5FA2, 0x8FC7, + 0x5FA3, 0x8FC8, 0x5FA4, 0x8FC9, 0x5FA5, 0x8FCA, 0x5FA6, 0x8FCB, 0x5FA7, 0x8FCC, 0x5FA8, 0xE1E5, 0x5FA9, 0x8FCD, 0x5FAA, 0xD1AD, + 0x5FAB, 0x8FCE, 0x5FAC, 0x8FCF, 0x5FAD, 0xE1E6, 0x5FAE, 0xCEA2, 0x5FAF, 0x8FD0, 0x5FB0, 0x8FD1, 0x5FB1, 0x8FD2, 0x5FB2, 0x8FD3, + 0x5FB3, 0x8FD4, 0x5FB4, 0x8FD5, 0x5FB5, 0xE1E7, 0x5FB6, 0x8FD6, 0x5FB7, 0xB5C2, 0x5FB8, 0x8FD7, 0x5FB9, 0x8FD8, 0x5FBA, 0x8FD9, + 0x5FBB, 0x8FDA, 0x5FBC, 0xE1E8, 0x5FBD, 0xBBD5, 0x5FBE, 0x8FDB, 0x5FBF, 0x8FDC, 0x5FC0, 0x8FDD, 0x5FC1, 0x8FDE, 0x5FC2, 0x8FDF, + 0x5FC3, 0xD0C4, 0x5FC4, 0xE2E0, 0x5FC5, 0xB1D8, 0x5FC6, 0xD2E4, 0x5FC7, 0x8FE0, 0x5FC8, 0x8FE1, 0x5FC9, 0xE2E1, 0x5FCA, 0x8FE2, + 0x5FCB, 0x8FE3, 0x5FCC, 0xBCC9, 0x5FCD, 0xC8CC, 0x5FCE, 0x8FE4, 0x5FCF, 0xE2E3, 0x5FD0, 0xECFE, 0x5FD1, 0xECFD, 0x5FD2, 0xDFAF, + 0x5FD3, 0x8FE5, 0x5FD4, 0x8FE6, 0x5FD5, 0x8FE7, 0x5FD6, 0xE2E2, 0x5FD7, 0xD6BE, 0x5FD8, 0xCDFC, 0x5FD9, 0xC3A6, 0x5FDA, 0x8FE8, + 0x5FDB, 0x8FE9, 0x5FDC, 0x8FEA, 0x5FDD, 0xE3C3, 0x5FDE, 0x8FEB, 0x5FDF, 0x8FEC, 0x5FE0, 0xD6D2, 0x5FE1, 0xE2E7, 0x5FE2, 0x8FED, + 0x5FE3, 0x8FEE, 0x5FE4, 0xE2E8, 0x5FE5, 0x8FEF, 0x5FE6, 0x8FF0, 0x5FE7, 0xD3C7, 0x5FE8, 0x8FF1, 0x5FE9, 0x8FF2, 0x5FEA, 0xE2EC, + 0x5FEB, 0xBFEC, 0x5FEC, 0x8FF3, 0x5FED, 0xE2ED, 0x5FEE, 0xE2E5, 0x5FEF, 0x8FF4, 0x5FF0, 0x8FF5, 0x5FF1, 0xB3C0, 0x5FF2, 0x8FF6, + 0x5FF3, 0x8FF7, 0x5FF4, 0x8FF8, 0x5FF5, 0xC4EE, 0x5FF6, 0x8FF9, 0x5FF7, 0x8FFA, 0x5FF8, 0xE2EE, 0x5FF9, 0x8FFB, 0x5FFA, 0x8FFC, + 0x5FFB, 0xD0C3, 0x5FFC, 0x8FFD, 0x5FFD, 0xBAF6, 0x5FFE, 0xE2E9, 0x5FFF, 0xB7DE, 0x6000, 0xBBB3, 0x6001, 0xCCAC, 0x6002, 0xCBCB, + 0x6003, 0xE2E4, 0x6004, 0xE2E6, 0x6005, 0xE2EA, 0x6006, 0xE2EB, 0x6007, 0x8FFE, 0x6008, 0x9040, 0x6009, 0x9041, 0x600A, 0xE2F7, + 0x600B, 0x9042, 0x600C, 0x9043, 0x600D, 0xE2F4, 0x600E, 0xD4F5, 0x600F, 0xE2F3, 0x6010, 0x9044, 0x6011, 0x9045, 0x6012, 0xC5AD, + 0x6013, 0x9046, 0x6014, 0xD5FA, 0x6015, 0xC5C2, 0x6016, 0xB2C0, 0x6017, 0x9047, 0x6018, 0x9048, 0x6019, 0xE2EF, 0x601A, 0x9049, + 0x601B, 0xE2F2, 0x601C, 0xC1AF, 0x601D, 0xCBBC, 0x601E, 0x904A, 0x601F, 0x904B, 0x6020, 0xB5A1, 0x6021, 0xE2F9, 0x6022, 0x904C, + 0x6023, 0x904D, 0x6024, 0x904E, 0x6025, 0xBCB1, 0x6026, 0xE2F1, 0x6027, 0xD0D4, 0x6028, 0xD4B9, 0x6029, 0xE2F5, 0x602A, 0xB9D6, + 0x602B, 0xE2F6, 0x602C, 0x904F, 0x602D, 0x9050, 0x602E, 0x9051, 0x602F, 0xC7D3, 0x6030, 0x9052, 0x6031, 0x9053, 0x6032, 0x9054, + 0x6033, 0x9055, 0x6034, 0x9056, 0x6035, 0xE2F0, 0x6036, 0x9057, 0x6037, 0x9058, 0x6038, 0x9059, 0x6039, 0x905A, 0x603A, 0x905B, + 0x603B, 0xD7DC, 0x603C, 0xEDA1, 0x603D, 0x905C, 0x603E, 0x905D, 0x603F, 0xE2F8, 0x6040, 0x905E, 0x6041, 0xEDA5, 0x6042, 0xE2FE, + 0x6043, 0xCAD1, 0x6044, 0x905F, 0x6045, 0x9060, 0x6046, 0x9061, 0x6047, 0x9062, 0x6048, 0x9063, 0x6049, 0x9064, 0x604A, 0x9065, + 0x604B, 0xC1B5, 0x604C, 0x9066, 0x604D, 0xBBD0, 0x604E, 0x9067, 0x604F, 0x9068, 0x6050, 0xBFD6, 0x6051, 0x9069, 0x6052, 0xBAE3, + 0x6053, 0x906A, 0x6054, 0x906B, 0x6055, 0xCBA1, 0x6056, 0x906C, 0x6057, 0x906D, 0x6058, 0x906E, 0x6059, 0xEDA6, 0x605A, 0xEDA3, + 0x605B, 0x906F, 0x605C, 0x9070, 0x605D, 0xEDA2, 0x605E, 0x9071, 0x605F, 0x9072, 0x6060, 0x9073, 0x6061, 0x9074, 0x6062, 0xBBD6, + 0x6063, 0xEDA7, 0x6064, 0xD0F4, 0x6065, 0x9075, 0x6066, 0x9076, 0x6067, 0xEDA4, 0x6068, 0xBADE, 0x6069, 0xB6F7, 0x606A, 0xE3A1, + 0x606B, 0xB6B2, 0x606C, 0xCCF1, 0x606D, 0xB9A7, 0x606E, 0x9077, 0x606F, 0xCFA2, 0x6070, 0xC7A1, 0x6071, 0x9078, 0x6072, 0x9079, + 0x6073, 0xBFD2, 0x6074, 0x907A, 0x6075, 0x907B, 0x6076, 0xB6F1, 0x6077, 0x907C, 0x6078, 0xE2FA, 0x6079, 0xE2FB, 0x607A, 0xE2FD, + 0x607B, 0xE2FC, 0x607C, 0xC4D5, 0x607D, 0xE3A2, 0x607E, 0x907D, 0x607F, 0xD3C1, 0x6080, 0x907E, 0x6081, 0x9080, 0x6082, 0x9081, + 0x6083, 0xE3A7, 0x6084, 0xC7C4, 0x6085, 0x9082, 0x6086, 0x9083, 0x6087, 0x9084, 0x6088, 0x9085, 0x6089, 0xCFA4, 0x608A, 0x9086, + 0x608B, 0x9087, 0x608C, 0xE3A9, 0x608D, 0xBAB7, 0x608E, 0x9088, 0x608F, 0x9089, 0x6090, 0x908A, 0x6091, 0x908B, 0x6092, 0xE3A8, + 0x6093, 0x908C, 0x6094, 0xBBDA, 0x6095, 0x908D, 0x6096, 0xE3A3, 0x6097, 0x908E, 0x6098, 0x908F, 0x6099, 0x9090, 0x609A, 0xE3A4, + 0x609B, 0xE3AA, 0x609C, 0x9091, 0x609D, 0xE3A6, 0x609E, 0x9092, 0x609F, 0xCEF2, 0x60A0, 0xD3C6, 0x60A1, 0x9093, 0x60A2, 0x9094, + 0x60A3, 0xBBBC, 0x60A4, 0x9095, 0x60A5, 0x9096, 0x60A6, 0xD4C3, 0x60A7, 0x9097, 0x60A8, 0xC4FA, 0x60A9, 0x9098, 0x60AA, 0x9099, + 0x60AB, 0xEDA8, 0x60AC, 0xD0FC, 0x60AD, 0xE3A5, 0x60AE, 0x909A, 0x60AF, 0xC3F5, 0x60B0, 0x909B, 0x60B1, 0xE3AD, 0x60B2, 0xB1AF, + 0x60B3, 0x909C, 0x60B4, 0xE3B2, 0x60B5, 0x909D, 0x60B6, 0x909E, 0x60B7, 0x909F, 0x60B8, 0xBCC2, 0x60B9, 0x90A0, 0x60BA, 0x90A1, + 0x60BB, 0xE3AC, 0x60BC, 0xB5BF, 0x60BD, 0x90A2, 0x60BE, 0x90A3, 0x60BF, 0x90A4, 0x60C0, 0x90A5, 0x60C1, 0x90A6, 0x60C2, 0x90A7, + 0x60C3, 0x90A8, 0x60C4, 0x90A9, 0x60C5, 0xC7E9, 0x60C6, 0xE3B0, 0x60C7, 0x90AA, 0x60C8, 0x90AB, 0x60C9, 0x90AC, 0x60CA, 0xBEAA, + 0x60CB, 0xCDEF, 0x60CC, 0x90AD, 0x60CD, 0x90AE, 0x60CE, 0x90AF, 0x60CF, 0x90B0, 0x60D0, 0x90B1, 0x60D1, 0xBBF3, 0x60D2, 0x90B2, + 0x60D3, 0x90B3, 0x60D4, 0x90B4, 0x60D5, 0xCCE8, 0x60D6, 0x90B5, 0x60D7, 0x90B6, 0x60D8, 0xE3AF, 0x60D9, 0x90B7, 0x60DA, 0xE3B1, + 0x60DB, 0x90B8, 0x60DC, 0xCFA7, 0x60DD, 0xE3AE, 0x60DE, 0x90B9, 0x60DF, 0xCEA9, 0x60E0, 0xBBDD, 0x60E1, 0x90BA, 0x60E2, 0x90BB, + 0x60E3, 0x90BC, 0x60E4, 0x90BD, 0x60E5, 0x90BE, 0x60E6, 0xB5EB, 0x60E7, 0xBEE5, 0x60E8, 0xB2D2, 0x60E9, 0xB3CD, 0x60EA, 0x90BF, + 0x60EB, 0xB1B9, 0x60EC, 0xE3AB, 0x60ED, 0xB2D1, 0x60EE, 0xB5AC, 0x60EF, 0xB9DF, 0x60F0, 0xB6E8, 0x60F1, 0x90C0, 0x60F2, 0x90C1, + 0x60F3, 0xCFEB, 0x60F4, 0xE3B7, 0x60F5, 0x90C2, 0x60F6, 0xBBCC, 0x60F7, 0x90C3, 0x60F8, 0x90C4, 0x60F9, 0xC8C7, 0x60FA, 0xD0CA, + 0x60FB, 0x90C5, 0x60FC, 0x90C6, 0x60FD, 0x90C7, 0x60FE, 0x90C8, 0x60FF, 0x90C9, 0x6100, 0xE3B8, 0x6101, 0xB3EE, 0x6102, 0x90CA, + 0x6103, 0x90CB, 0x6104, 0x90CC, 0x6105, 0x90CD, 0x6106, 0xEDA9, 0x6107, 0x90CE, 0x6108, 0xD3FA, 0x6109, 0xD3E4, 0x610A, 0x90CF, + 0x610B, 0x90D0, 0x610C, 0x90D1, 0x610D, 0xEDAA, 0x610E, 0xE3B9, 0x610F, 0xD2E2, 0x6110, 0x90D2, 0x6111, 0x90D3, 0x6112, 0x90D4, + 0x6113, 0x90D5, 0x6114, 0x90D6, 0x6115, 0xE3B5, 0x6116, 0x90D7, 0x6117, 0x90D8, 0x6118, 0x90D9, 0x6119, 0x90DA, 0x611A, 0xD3DE, + 0x611B, 0x90DB, 0x611C, 0x90DC, 0x611D, 0x90DD, 0x611E, 0x90DE, 0x611F, 0xB8D0, 0x6120, 0xE3B3, 0x6121, 0x90DF, 0x6122, 0x90E0, + 0x6123, 0xE3B6, 0x6124, 0xB7DF, 0x6125, 0x90E1, 0x6126, 0xE3B4, 0x6127, 0xC0A2, 0x6128, 0x90E2, 0x6129, 0x90E3, 0x612A, 0x90E4, + 0x612B, 0xE3BA, 0x612C, 0x90E5, 0x612D, 0x90E6, 0x612E, 0x90E7, 0x612F, 0x90E8, 0x6130, 0x90E9, 0x6131, 0x90EA, 0x6132, 0x90EB, + 0x6133, 0x90EC, 0x6134, 0x90ED, 0x6135, 0x90EE, 0x6136, 0x90EF, 0x6137, 0x90F0, 0x6138, 0x90F1, 0x6139, 0x90F2, 0x613A, 0x90F3, + 0x613B, 0x90F4, 0x613C, 0x90F5, 0x613D, 0x90F6, 0x613E, 0x90F7, 0x613F, 0xD4B8, 0x6140, 0x90F8, 0x6141, 0x90F9, 0x6142, 0x90FA, + 0x6143, 0x90FB, 0x6144, 0x90FC, 0x6145, 0x90FD, 0x6146, 0x90FE, 0x6147, 0x9140, 0x6148, 0xB4C8, 0x6149, 0x9141, 0x614A, 0xE3BB, + 0x614B, 0x9142, 0x614C, 0xBBC5, 0x614D, 0x9143, 0x614E, 0xC9F7, 0x614F, 0x9144, 0x6150, 0x9145, 0x6151, 0xC9E5, 0x6152, 0x9146, + 0x6153, 0x9147, 0x6154, 0x9148, 0x6155, 0xC4BD, 0x6156, 0x9149, 0x6157, 0x914A, 0x6158, 0x914B, 0x6159, 0x914C, 0x615A, 0x914D, + 0x615B, 0x914E, 0x615C, 0x914F, 0x615D, 0xEDAB, 0x615E, 0x9150, 0x615F, 0x9151, 0x6160, 0x9152, 0x6161, 0x9153, 0x6162, 0xC2FD, + 0x6163, 0x9154, 0x6164, 0x9155, 0x6165, 0x9156, 0x6166, 0x9157, 0x6167, 0xBBDB, 0x6168, 0xBFAE, 0x6169, 0x9158, 0x616A, 0x9159, + 0x616B, 0x915A, 0x616C, 0x915B, 0x616D, 0x915C, 0x616E, 0x915D, 0x616F, 0x915E, 0x6170, 0xCEBF, 0x6171, 0x915F, 0x6172, 0x9160, + 0x6173, 0x9161, 0x6174, 0x9162, 0x6175, 0xE3BC, 0x6176, 0x9163, 0x6177, 0xBFB6, 0x6178, 0x9164, 0x6179, 0x9165, 0x617A, 0x9166, + 0x617B, 0x9167, 0x617C, 0x9168, 0x617D, 0x9169, 0x617E, 0x916A, 0x617F, 0x916B, 0x6180, 0x916C, 0x6181, 0x916D, 0x6182, 0x916E, + 0x6183, 0x916F, 0x6184, 0x9170, 0x6185, 0x9171, 0x6186, 0x9172, 0x6187, 0x9173, 0x6188, 0x9174, 0x6189, 0x9175, 0x618A, 0x9176, + 0x618B, 0xB1EF, 0x618C, 0x9177, 0x618D, 0x9178, 0x618E, 0xD4F7, 0x618F, 0x9179, 0x6190, 0x917A, 0x6191, 0x917B, 0x6192, 0x917C, + 0x6193, 0x917D, 0x6194, 0xE3BE, 0x6195, 0x917E, 0x6196, 0x9180, 0x6197, 0x9181, 0x6198, 0x9182, 0x6199, 0x9183, 0x619A, 0x9184, + 0x619B, 0x9185, 0x619C, 0x9186, 0x619D, 0xEDAD, 0x619E, 0x9187, 0x619F, 0x9188, 0x61A0, 0x9189, 0x61A1, 0x918A, 0x61A2, 0x918B, + 0x61A3, 0x918C, 0x61A4, 0x918D, 0x61A5, 0x918E, 0x61A6, 0x918F, 0x61A7, 0xE3BF, 0x61A8, 0xBAA9, 0x61A9, 0xEDAC, 0x61AA, 0x9190, + 0x61AB, 0x9191, 0x61AC, 0xE3BD, 0x61AD, 0x9192, 0x61AE, 0x9193, 0x61AF, 0x9194, 0x61B0, 0x9195, 0x61B1, 0x9196, 0x61B2, 0x9197, + 0x61B3, 0x9198, 0x61B4, 0x9199, 0x61B5, 0x919A, 0x61B6, 0x919B, 0x61B7, 0xE3C0, 0x61B8, 0x919C, 0x61B9, 0x919D, 0x61BA, 0x919E, + 0x61BB, 0x919F, 0x61BC, 0x91A0, 0x61BD, 0x91A1, 0x61BE, 0xBAB6, 0x61BF, 0x91A2, 0x61C0, 0x91A3, 0x61C1, 0x91A4, 0x61C2, 0xB6AE, + 0x61C3, 0x91A5, 0x61C4, 0x91A6, 0x61C5, 0x91A7, 0x61C6, 0x91A8, 0x61C7, 0x91A9, 0x61C8, 0xD0B8, 0x61C9, 0x91AA, 0x61CA, 0xB0C3, + 0x61CB, 0xEDAE, 0x61CC, 0x91AB, 0x61CD, 0x91AC, 0x61CE, 0x91AD, 0x61CF, 0x91AE, 0x61D0, 0x91AF, 0x61D1, 0xEDAF, 0x61D2, 0xC0C1, + 0x61D3, 0x91B0, 0x61D4, 0xE3C1, 0x61D5, 0x91B1, 0x61D6, 0x91B2, 0x61D7, 0x91B3, 0x61D8, 0x91B4, 0x61D9, 0x91B5, 0x61DA, 0x91B6, + 0x61DB, 0x91B7, 0x61DC, 0x91B8, 0x61DD, 0x91B9, 0x61DE, 0x91BA, 0x61DF, 0x91BB, 0x61E0, 0x91BC, 0x61E1, 0x91BD, 0x61E2, 0x91BE, + 0x61E3, 0x91BF, 0x61E4, 0x91C0, 0x61E5, 0x91C1, 0x61E6, 0xC5B3, 0x61E7, 0x91C2, 0x61E8, 0x91C3, 0x61E9, 0x91C4, 0x61EA, 0x91C5, + 0x61EB, 0x91C6, 0x61EC, 0x91C7, 0x61ED, 0x91C8, 0x61EE, 0x91C9, 0x61EF, 0x91CA, 0x61F0, 0x91CB, 0x61F1, 0x91CC, 0x61F2, 0x91CD, + 0x61F3, 0x91CE, 0x61F4, 0x91CF, 0x61F5, 0xE3C2, 0x61F6, 0x91D0, 0x61F7, 0x91D1, 0x61F8, 0x91D2, 0x61F9, 0x91D3, 0x61FA, 0x91D4, + 0x61FB, 0x91D5, 0x61FC, 0x91D6, 0x61FD, 0x91D7, 0x61FE, 0x91D8, 0x61FF, 0xDCB2, 0x6200, 0x91D9, 0x6201, 0x91DA, 0x6202, 0x91DB, + 0x6203, 0x91DC, 0x6204, 0x91DD, 0x6205, 0x91DE, 0x6206, 0xEDB0, 0x6207, 0x91DF, 0x6208, 0xB8EA, 0x6209, 0x91E0, 0x620A, 0xCEEC, + 0x620B, 0xEAA7, 0x620C, 0xD0E7, 0x620D, 0xCAF9, 0x620E, 0xC8D6, 0x620F, 0xCFB7, 0x6210, 0xB3C9, 0x6211, 0xCED2, 0x6212, 0xBDE4, + 0x6213, 0x91E1, 0x6214, 0x91E2, 0x6215, 0xE3DE, 0x6216, 0xBBF2, 0x6217, 0xEAA8, 0x6218, 0xD5BD, 0x6219, 0x91E3, 0x621A, 0xC6DD, + 0x621B, 0xEAA9, 0x621C, 0x91E4, 0x621D, 0x91E5, 0x621E, 0x91E6, 0x621F, 0xEAAA, 0x6220, 0x91E7, 0x6221, 0xEAAC, 0x6222, 0xEAAB, + 0x6223, 0x91E8, 0x6224, 0xEAAE, 0x6225, 0xEAAD, 0x6226, 0x91E9, 0x6227, 0x91EA, 0x6228, 0x91EB, 0x6229, 0x91EC, 0x622A, 0xBDD8, + 0x622B, 0x91ED, 0x622C, 0xEAAF, 0x622D, 0x91EE, 0x622E, 0xC2BE, 0x622F, 0x91EF, 0x6230, 0x91F0, 0x6231, 0x91F1, 0x6232, 0x91F2, + 0x6233, 0xB4C1, 0x6234, 0xB4F7, 0x6235, 0x91F3, 0x6236, 0x91F4, 0x6237, 0xBBA7, 0x6238, 0x91F5, 0x6239, 0x91F6, 0x623A, 0x91F7, + 0x623B, 0x91F8, 0x623C, 0x91F9, 0x623D, 0xECE6, 0x623E, 0xECE5, 0x623F, 0xB7BF, 0x6240, 0xCBF9, 0x6241, 0xB1E2, 0x6242, 0x91FA, + 0x6243, 0xECE7, 0x6244, 0x91FB, 0x6245, 0x91FC, 0x6246, 0x91FD, 0x6247, 0xC9C8, 0x6248, 0xECE8, 0x6249, 0xECE9, 0x624A, 0x91FE, + 0x624B, 0xCAD6, 0x624C, 0xDED0, 0x624D, 0xB2C5, 0x624E, 0xD4FA, 0x624F, 0x9240, 0x6250, 0x9241, 0x6251, 0xC6CB, 0x6252, 0xB0C7, + 0x6253, 0xB4F2, 0x6254, 0xC8D3, 0x6255, 0x9242, 0x6256, 0x9243, 0x6257, 0x9244, 0x6258, 0xCDD0, 0x6259, 0x9245, 0x625A, 0x9246, + 0x625B, 0xBFB8, 0x625C, 0x9247, 0x625D, 0x9248, 0x625E, 0x9249, 0x625F, 0x924A, 0x6260, 0x924B, 0x6261, 0x924C, 0x6262, 0x924D, + 0x6263, 0xBFDB, 0x6264, 0x924E, 0x6265, 0x924F, 0x6266, 0xC7A4, 0x6267, 0xD6B4, 0x6268, 0x9250, 0x6269, 0xC0A9, 0x626A, 0xDED1, + 0x626B, 0xC9A8, 0x626C, 0xD1EF, 0x626D, 0xC5A4, 0x626E, 0xB0E7, 0x626F, 0xB3B6, 0x6270, 0xC8C5, 0x6271, 0x9251, 0x6272, 0x9252, + 0x6273, 0xB0E2, 0x6274, 0x9253, 0x6275, 0x9254, 0x6276, 0xB7F6, 0x6277, 0x9255, 0x6278, 0x9256, 0x6279, 0xC5FA, 0x627A, 0x9257, + 0x627B, 0x9258, 0x627C, 0xB6F3, 0x627D, 0x9259, 0x627E, 0xD5D2, 0x627F, 0xB3D0, 0x6280, 0xBCBC, 0x6281, 0x925A, 0x6282, 0x925B, + 0x6283, 0x925C, 0x6284, 0xB3AD, 0x6285, 0x925D, 0x6286, 0x925E, 0x6287, 0x925F, 0x6288, 0x9260, 0x6289, 0xBEF1, 0x628A, 0xB0D1, + 0x628B, 0x9261, 0x628C, 0x9262, 0x628D, 0x9263, 0x628E, 0x9264, 0x628F, 0x9265, 0x6290, 0x9266, 0x6291, 0xD2D6, 0x6292, 0xCAE3, + 0x6293, 0xD7A5, 0x6294, 0x9267, 0x6295, 0xCDB6, 0x6296, 0xB6B6, 0x6297, 0xBFB9, 0x6298, 0xD5DB, 0x6299, 0x9268, 0x629A, 0xB8A7, + 0x629B, 0xC5D7, 0x629C, 0x9269, 0x629D, 0x926A, 0x629E, 0x926B, 0x629F, 0xDED2, 0x62A0, 0xBFD9, 0x62A1, 0xC2D5, 0x62A2, 0xC7C0, + 0x62A3, 0x926C, 0x62A4, 0xBBA4, 0x62A5, 0xB1A8, 0x62A6, 0x926D, 0x62A7, 0x926E, 0x62A8, 0xC5EA, 0x62A9, 0x926F, 0x62AA, 0x9270, + 0x62AB, 0xC5FB, 0x62AC, 0xCCA7, 0x62AD, 0x9271, 0x62AE, 0x9272, 0x62AF, 0x9273, 0x62B0, 0x9274, 0x62B1, 0xB1A7, 0x62B2, 0x9275, + 0x62B3, 0x9276, 0x62B4, 0x9277, 0x62B5, 0xB5D6, 0x62B6, 0x9278, 0x62B7, 0x9279, 0x62B8, 0x927A, 0x62B9, 0xC4A8, 0x62BA, 0x927B, + 0x62BB, 0xDED3, 0x62BC, 0xD1BA, 0x62BD, 0xB3E9, 0x62BE, 0x927C, 0x62BF, 0xC3F2, 0x62C0, 0x927D, 0x62C1, 0x927E, 0x62C2, 0xB7F7, + 0x62C3, 0x9280, 0x62C4, 0xD6F4, 0x62C5, 0xB5A3, 0x62C6, 0xB2F0, 0x62C7, 0xC4B4, 0x62C8, 0xC4E9, 0x62C9, 0xC0AD, 0x62CA, 0xDED4, + 0x62CB, 0x9281, 0x62CC, 0xB0E8, 0x62CD, 0xC5C4, 0x62CE, 0xC1E0, 0x62CF, 0x9282, 0x62D0, 0xB9D5, 0x62D1, 0x9283, 0x62D2, 0xBEDC, + 0x62D3, 0xCDD8, 0x62D4, 0xB0CE, 0x62D5, 0x9284, 0x62D6, 0xCDCF, 0x62D7, 0xDED6, 0x62D8, 0xBED0, 0x62D9, 0xD7BE, 0x62DA, 0xDED5, + 0x62DB, 0xD5D0, 0x62DC, 0xB0DD, 0x62DD, 0x9285, 0x62DE, 0x9286, 0x62DF, 0xC4E2, 0x62E0, 0x9287, 0x62E1, 0x9288, 0x62E2, 0xC2A3, + 0x62E3, 0xBCF0, 0x62E4, 0x9289, 0x62E5, 0xD3B5, 0x62E6, 0xC0B9, 0x62E7, 0xC5A1, 0x62E8, 0xB2A6, 0x62E9, 0xD4F1, 0x62EA, 0x928A, + 0x62EB, 0x928B, 0x62EC, 0xC0A8, 0x62ED, 0xCAC3, 0x62EE, 0xDED7, 0x62EF, 0xD5FC, 0x62F0, 0x928C, 0x62F1, 0xB9B0, 0x62F2, 0x928D, + 0x62F3, 0xC8AD, 0x62F4, 0xCBA9, 0x62F5, 0x928E, 0x62F6, 0xDED9, 0x62F7, 0xBFBD, 0x62F8, 0x928F, 0x62F9, 0x9290, 0x62FA, 0x9291, + 0x62FB, 0x9292, 0x62FC, 0xC6B4, 0x62FD, 0xD7A7, 0x62FE, 0xCAB0, 0x62FF, 0xC4C3, 0x6300, 0x9293, 0x6301, 0xB3D6, 0x6302, 0xB9D2, + 0x6303, 0x9294, 0x6304, 0x9295, 0x6305, 0x9296, 0x6306, 0x9297, 0x6307, 0xD6B8, 0x6308, 0xEAFC, 0x6309, 0xB0B4, 0x630A, 0x9298, + 0x630B, 0x9299, 0x630C, 0x929A, 0x630D, 0x929B, 0x630E, 0xBFE6, 0x630F, 0x929C, 0x6310, 0x929D, 0x6311, 0xCCF4, 0x6312, 0x929E, + 0x6313, 0x929F, 0x6314, 0x92A0, 0x6315, 0x92A1, 0x6316, 0xCDDA, 0x6317, 0x92A2, 0x6318, 0x92A3, 0x6319, 0x92A4, 0x631A, 0xD6BF, + 0x631B, 0xC2CE, 0x631C, 0x92A5, 0x631D, 0xCECE, 0x631E, 0xCCA2, 0x631F, 0xD0AE, 0x6320, 0xC4D3, 0x6321, 0xB5B2, 0x6322, 0xDED8, + 0x6323, 0xD5F5, 0x6324, 0xBCB7, 0x6325, 0xBBD3, 0x6326, 0x92A6, 0x6327, 0x92A7, 0x6328, 0xB0A4, 0x6329, 0x92A8, 0x632A, 0xC5B2, + 0x632B, 0xB4EC, 0x632C, 0x92A9, 0x632D, 0x92AA, 0x632E, 0x92AB, 0x632F, 0xD5F1, 0x6330, 0x92AC, 0x6331, 0x92AD, 0x6332, 0xEAFD, + 0x6333, 0x92AE, 0x6334, 0x92AF, 0x6335, 0x92B0, 0x6336, 0x92B1, 0x6337, 0x92B2, 0x6338, 0x92B3, 0x6339, 0xDEDA, 0x633A, 0xCDA6, + 0x633B, 0x92B4, 0x633C, 0x92B5, 0x633D, 0xCDEC, 0x633E, 0x92B6, 0x633F, 0x92B7, 0x6340, 0x92B8, 0x6341, 0x92B9, 0x6342, 0xCEE6, + 0x6343, 0xDEDC, 0x6344, 0x92BA, 0x6345, 0xCDB1, 0x6346, 0xC0A6, 0x6347, 0x92BB, 0x6348, 0x92BC, 0x6349, 0xD7BD, 0x634A, 0x92BD, + 0x634B, 0xDEDB, 0x634C, 0xB0C6, 0x634D, 0xBAB4, 0x634E, 0xC9D3, 0x634F, 0xC4F3, 0x6350, 0xBEE8, 0x6351, 0x92BE, 0x6352, 0x92BF, + 0x6353, 0x92C0, 0x6354, 0x92C1, 0x6355, 0xB2B6, 0x6356, 0x92C2, 0x6357, 0x92C3, 0x6358, 0x92C4, 0x6359, 0x92C5, 0x635A, 0x92C6, + 0x635B, 0x92C7, 0x635C, 0x92C8, 0x635D, 0x92C9, 0x635E, 0xC0CC, 0x635F, 0xCBF0, 0x6360, 0x92CA, 0x6361, 0xBCF1, 0x6362, 0xBBBB, + 0x6363, 0xB5B7, 0x6364, 0x92CB, 0x6365, 0x92CC, 0x6366, 0x92CD, 0x6367, 0xC5F5, 0x6368, 0x92CE, 0x6369, 0xDEE6, 0x636A, 0x92CF, + 0x636B, 0x92D0, 0x636C, 0x92D1, 0x636D, 0xDEE3, 0x636E, 0xBEDD, 0x636F, 0x92D2, 0x6370, 0x92D3, 0x6371, 0xDEDF, 0x6372, 0x92D4, + 0x6373, 0x92D5, 0x6374, 0x92D6, 0x6375, 0x92D7, 0x6376, 0xB4B7, 0x6377, 0xBDDD, 0x6378, 0x92D8, 0x6379, 0x92D9, 0x637A, 0xDEE0, + 0x637B, 0xC4ED, 0x637C, 0x92DA, 0x637D, 0x92DB, 0x637E, 0x92DC, 0x637F, 0x92DD, 0x6380, 0xCFC6, 0x6381, 0x92DE, 0x6382, 0xB5E0, + 0x6383, 0x92DF, 0x6384, 0x92E0, 0x6385, 0x92E1, 0x6386, 0x92E2, 0x6387, 0xB6DE, 0x6388, 0xCADA, 0x6389, 0xB5F4, 0x638A, 0xDEE5, + 0x638B, 0x92E3, 0x638C, 0xD5C6, 0x638D, 0x92E4, 0x638E, 0xDEE1, 0x638F, 0xCCCD, 0x6390, 0xC6FE, 0x6391, 0x92E5, 0x6392, 0xC5C5, + 0x6393, 0x92E6, 0x6394, 0x92E7, 0x6395, 0x92E8, 0x6396, 0xD2B4, 0x6397, 0x92E9, 0x6398, 0xBEF2, 0x6399, 0x92EA, 0x639A, 0x92EB, + 0x639B, 0x92EC, 0x639C, 0x92ED, 0x639D, 0x92EE, 0x639E, 0x92EF, 0x639F, 0x92F0, 0x63A0, 0xC2D3, 0x63A1, 0x92F1, 0x63A2, 0xCCBD, + 0x63A3, 0xB3B8, 0x63A4, 0x92F2, 0x63A5, 0xBDD3, 0x63A6, 0x92F3, 0x63A7, 0xBFD8, 0x63A8, 0xCDC6, 0x63A9, 0xD1DA, 0x63AA, 0xB4EB, + 0x63AB, 0x92F4, 0x63AC, 0xDEE4, 0x63AD, 0xDEDD, 0x63AE, 0xDEE7, 0x63AF, 0x92F5, 0x63B0, 0xEAFE, 0x63B1, 0x92F6, 0x63B2, 0x92F7, + 0x63B3, 0xC2B0, 0x63B4, 0xDEE2, 0x63B5, 0x92F8, 0x63B6, 0x92F9, 0x63B7, 0xD6C0, 0x63B8, 0xB5A7, 0x63B9, 0x92FA, 0x63BA, 0xB2F4, + 0x63BB, 0x92FB, 0x63BC, 0xDEE8, 0x63BD, 0x92FC, 0x63BE, 0xDEF2, 0x63BF, 0x92FD, 0x63C0, 0x92FE, 0x63C1, 0x9340, 0x63C2, 0x9341, + 0x63C3, 0x9342, 0x63C4, 0xDEED, 0x63C5, 0x9343, 0x63C6, 0xDEF1, 0x63C7, 0x9344, 0x63C8, 0x9345, 0x63C9, 0xC8E0, 0x63CA, 0x9346, + 0x63CB, 0x9347, 0x63CC, 0x9348, 0x63CD, 0xD7E1, 0x63CE, 0xDEEF, 0x63CF, 0xC3E8, 0x63D0, 0xCCE1, 0x63D1, 0x9349, 0x63D2, 0xB2E5, + 0x63D3, 0x934A, 0x63D4, 0x934B, 0x63D5, 0x934C, 0x63D6, 0xD2BE, 0x63D7, 0x934D, 0x63D8, 0x934E, 0x63D9, 0x934F, 0x63DA, 0x9350, + 0x63DB, 0x9351, 0x63DC, 0x9352, 0x63DD, 0x9353, 0x63DE, 0xDEEE, 0x63DF, 0x9354, 0x63E0, 0xDEEB, 0x63E1, 0xCED5, 0x63E2, 0x9355, + 0x63E3, 0xB4A7, 0x63E4, 0x9356, 0x63E5, 0x9357, 0x63E6, 0x9358, 0x63E7, 0x9359, 0x63E8, 0x935A, 0x63E9, 0xBFAB, 0x63EA, 0xBEBE, + 0x63EB, 0x935B, 0x63EC, 0x935C, 0x63ED, 0xBDD2, 0x63EE, 0x935D, 0x63EF, 0x935E, 0x63F0, 0x935F, 0x63F1, 0x9360, 0x63F2, 0xDEE9, + 0x63F3, 0x9361, 0x63F4, 0xD4AE, 0x63F5, 0x9362, 0x63F6, 0xDEDE, 0x63F7, 0x9363, 0x63F8, 0xDEEA, 0x63F9, 0x9364, 0x63FA, 0x9365, + 0x63FB, 0x9366, 0x63FC, 0x9367, 0x63FD, 0xC0BF, 0x63FE, 0x9368, 0x63FF, 0xDEEC, 0x6400, 0xB2F3, 0x6401, 0xB8E9, 0x6402, 0xC2A7, + 0x6403, 0x9369, 0x6404, 0x936A, 0x6405, 0xBDC1, 0x6406, 0x936B, 0x6407, 0x936C, 0x6408, 0x936D, 0x6409, 0x936E, 0x640A, 0x936F, + 0x640B, 0xDEF5, 0x640C, 0xDEF8, 0x640D, 0x9370, 0x640E, 0x9371, 0x640F, 0xB2AB, 0x6410, 0xB4A4, 0x6411, 0x9372, 0x6412, 0x9373, + 0x6413, 0xB4EA, 0x6414, 0xC9A6, 0x6415, 0x9374, 0x6416, 0x9375, 0x6417, 0x9376, 0x6418, 0x9377, 0x6419, 0x9378, 0x641A, 0x9379, + 0x641B, 0xDEF6, 0x641C, 0xCBD1, 0x641D, 0x937A, 0x641E, 0xB8E3, 0x641F, 0x937B, 0x6420, 0xDEF7, 0x6421, 0xDEFA, 0x6422, 0x937C, + 0x6423, 0x937D, 0x6424, 0x937E, 0x6425, 0x9380, 0x6426, 0xDEF9, 0x6427, 0x9381, 0x6428, 0x9382, 0x6429, 0x9383, 0x642A, 0xCCC2, + 0x642B, 0x9384, 0x642C, 0xB0E1, 0x642D, 0xB4EE, 0x642E, 0x9385, 0x642F, 0x9386, 0x6430, 0x9387, 0x6431, 0x9388, 0x6432, 0x9389, + 0x6433, 0x938A, 0x6434, 0xE5BA, 0x6435, 0x938B, 0x6436, 0x938C, 0x6437, 0x938D, 0x6438, 0x938E, 0x6439, 0x938F, 0x643A, 0xD0AF, + 0x643B, 0x9390, 0x643C, 0x9391, 0x643D, 0xB2EB, 0x643E, 0x9392, 0x643F, 0xEBA1, 0x6440, 0x9393, 0x6441, 0xDEF4, 0x6442, 0x9394, + 0x6443, 0x9395, 0x6444, 0xC9E3, 0x6445, 0xDEF3, 0x6446, 0xB0DA, 0x6447, 0xD2A1, 0x6448, 0xB1F7, 0x6449, 0x9396, 0x644A, 0xCCAF, + 0x644B, 0x9397, 0x644C, 0x9398, 0x644D, 0x9399, 0x644E, 0x939A, 0x644F, 0x939B, 0x6450, 0x939C, 0x6451, 0x939D, 0x6452, 0xDEF0, + 0x6453, 0x939E, 0x6454, 0xCBA4, 0x6455, 0x939F, 0x6456, 0x93A0, 0x6457, 0x93A1, 0x6458, 0xD5AA, 0x6459, 0x93A2, 0x645A, 0x93A3, + 0x645B, 0x93A4, 0x645C, 0x93A5, 0x645D, 0x93A6, 0x645E, 0xDEFB, 0x645F, 0x93A7, 0x6460, 0x93A8, 0x6461, 0x93A9, 0x6462, 0x93AA, + 0x6463, 0x93AB, 0x6464, 0x93AC, 0x6465, 0x93AD, 0x6466, 0x93AE, 0x6467, 0xB4DD, 0x6468, 0x93AF, 0x6469, 0xC4A6, 0x646A, 0x93B0, + 0x646B, 0x93B1, 0x646C, 0x93B2, 0x646D, 0xDEFD, 0x646E, 0x93B3, 0x646F, 0x93B4, 0x6470, 0x93B5, 0x6471, 0x93B6, 0x6472, 0x93B7, + 0x6473, 0x93B8, 0x6474, 0x93B9, 0x6475, 0x93BA, 0x6476, 0x93BB, 0x6477, 0x93BC, 0x6478, 0xC3FE, 0x6479, 0xC4A1, 0x647A, 0xDFA1, + 0x647B, 0x93BD, 0x647C, 0x93BE, 0x647D, 0x93BF, 0x647E, 0x93C0, 0x647F, 0x93C1, 0x6480, 0x93C2, 0x6481, 0x93C3, 0x6482, 0xC1CC, + 0x6483, 0x93C4, 0x6484, 0xDEFC, 0x6485, 0xBEEF, 0x6486, 0x93C5, 0x6487, 0xC6B2, 0x6488, 0x93C6, 0x6489, 0x93C7, 0x648A, 0x93C8, + 0x648B, 0x93C9, 0x648C, 0x93CA, 0x648D, 0x93CB, 0x648E, 0x93CC, 0x648F, 0x93CD, 0x6490, 0x93CE, 0x6491, 0xB3C5, 0x6492, 0xC8F6, + 0x6493, 0x93CF, 0x6494, 0x93D0, 0x6495, 0xCBBA, 0x6496, 0xDEFE, 0x6497, 0x93D1, 0x6498, 0x93D2, 0x6499, 0xDFA4, 0x649A, 0x93D3, + 0x649B, 0x93D4, 0x649C, 0x93D5, 0x649D, 0x93D6, 0x649E, 0xD7B2, 0x649F, 0x93D7, 0x64A0, 0x93D8, 0x64A1, 0x93D9, 0x64A2, 0x93DA, + 0x64A3, 0x93DB, 0x64A4, 0xB3B7, 0x64A5, 0x93DC, 0x64A6, 0x93DD, 0x64A7, 0x93DE, 0x64A8, 0x93DF, 0x64A9, 0xC1C3, 0x64AA, 0x93E0, + 0x64AB, 0x93E1, 0x64AC, 0xC7CB, 0x64AD, 0xB2A5, 0x64AE, 0xB4E9, 0x64AF, 0x93E2, 0x64B0, 0xD7AB, 0x64B1, 0x93E3, 0x64B2, 0x93E4, + 0x64B3, 0x93E5, 0x64B4, 0x93E6, 0x64B5, 0xC4EC, 0x64B6, 0x93E7, 0x64B7, 0xDFA2, 0x64B8, 0xDFA3, 0x64B9, 0x93E8, 0x64BA, 0xDFA5, + 0x64BB, 0x93E9, 0x64BC, 0xBAB3, 0x64BD, 0x93EA, 0x64BE, 0x93EB, 0x64BF, 0x93EC, 0x64C0, 0xDFA6, 0x64C1, 0x93ED, 0x64C2, 0xC0DE, + 0x64C3, 0x93EE, 0x64C4, 0x93EF, 0x64C5, 0xC9C3, 0x64C6, 0x93F0, 0x64C7, 0x93F1, 0x64C8, 0x93F2, 0x64C9, 0x93F3, 0x64CA, 0x93F4, + 0x64CB, 0x93F5, 0x64CC, 0x93F6, 0x64CD, 0xB2D9, 0x64CE, 0xC7E6, 0x64CF, 0x93F7, 0x64D0, 0xDFA7, 0x64D1, 0x93F8, 0x64D2, 0xC7DC, + 0x64D3, 0x93F9, 0x64D4, 0x93FA, 0x64D5, 0x93FB, 0x64D6, 0x93FC, 0x64D7, 0xDFA8, 0x64D8, 0xEBA2, 0x64D9, 0x93FD, 0x64DA, 0x93FE, + 0x64DB, 0x9440, 0x64DC, 0x9441, 0x64DD, 0x9442, 0x64DE, 0xCBD3, 0x64DF, 0x9443, 0x64E0, 0x9444, 0x64E1, 0x9445, 0x64E2, 0xDFAA, + 0x64E3, 0x9446, 0x64E4, 0xDFA9, 0x64E5, 0x9447, 0x64E6, 0xB2C1, 0x64E7, 0x9448, 0x64E8, 0x9449, 0x64E9, 0x944A, 0x64EA, 0x944B, + 0x64EB, 0x944C, 0x64EC, 0x944D, 0x64ED, 0x944E, 0x64EE, 0x944F, 0x64EF, 0x9450, 0x64F0, 0x9451, 0x64F1, 0x9452, 0x64F2, 0x9453, + 0x64F3, 0x9454, 0x64F4, 0x9455, 0x64F5, 0x9456, 0x64F6, 0x9457, 0x64F7, 0x9458, 0x64F8, 0x9459, 0x64F9, 0x945A, 0x64FA, 0x945B, + 0x64FB, 0x945C, 0x64FC, 0x945D, 0x64FD, 0x945E, 0x64FE, 0x945F, 0x64FF, 0x9460, 0x6500, 0xC5CA, 0x6501, 0x9461, 0x6502, 0x9462, + 0x6503, 0x9463, 0x6504, 0x9464, 0x6505, 0x9465, 0x6506, 0x9466, 0x6507, 0x9467, 0x6508, 0x9468, 0x6509, 0xDFAB, 0x650A, 0x9469, + 0x650B, 0x946A, 0x650C, 0x946B, 0x650D, 0x946C, 0x650E, 0x946D, 0x650F, 0x946E, 0x6510, 0x946F, 0x6511, 0x9470, 0x6512, 0xD4DC, + 0x6513, 0x9471, 0x6514, 0x9472, 0x6515, 0x9473, 0x6516, 0x9474, 0x6517, 0x9475, 0x6518, 0xC8C1, 0x6519, 0x9476, 0x651A, 0x9477, + 0x651B, 0x9478, 0x651C, 0x9479, 0x651D, 0x947A, 0x651E, 0x947B, 0x651F, 0x947C, 0x6520, 0x947D, 0x6521, 0x947E, 0x6522, 0x9480, + 0x6523, 0x9481, 0x6524, 0x9482, 0x6525, 0xDFAC, 0x6526, 0x9483, 0x6527, 0x9484, 0x6528, 0x9485, 0x6529, 0x9486, 0x652A, 0x9487, + 0x652B, 0xBEF0, 0x652C, 0x9488, 0x652D, 0x9489, 0x652E, 0xDFAD, 0x652F, 0xD6A7, 0x6530, 0x948A, 0x6531, 0x948B, 0x6532, 0x948C, + 0x6533, 0x948D, 0x6534, 0xEAB7, 0x6535, 0xEBB6, 0x6536, 0xCAD5, 0x6537, 0x948E, 0x6538, 0xD8FC, 0x6539, 0xB8C4, 0x653A, 0x948F, + 0x653B, 0xB9A5, 0x653C, 0x9490, 0x653D, 0x9491, 0x653E, 0xB7C5, 0x653F, 0xD5FE, 0x6540, 0x9492, 0x6541, 0x9493, 0x6542, 0x9494, + 0x6543, 0x9495, 0x6544, 0x9496, 0x6545, 0xB9CA, 0x6546, 0x9497, 0x6547, 0x9498, 0x6548, 0xD0A7, 0x6549, 0xF4CD, 0x654A, 0x9499, + 0x654B, 0x949A, 0x654C, 0xB5D0, 0x654D, 0x949B, 0x654E, 0x949C, 0x654F, 0xC3F4, 0x6550, 0x949D, 0x6551, 0xBEC8, 0x6552, 0x949E, + 0x6553, 0x949F, 0x6554, 0x94A0, 0x6555, 0xEBB7, 0x6556, 0xB0BD, 0x6557, 0x94A1, 0x6558, 0x94A2, 0x6559, 0xBDCC, 0x655A, 0x94A3, + 0x655B, 0xC1B2, 0x655C, 0x94A4, 0x655D, 0xB1D6, 0x655E, 0xB3A8, 0x655F, 0x94A5, 0x6560, 0x94A6, 0x6561, 0x94A7, 0x6562, 0xB8D2, + 0x6563, 0xC9A2, 0x6564, 0x94A8, 0x6565, 0x94A9, 0x6566, 0xB6D8, 0x6567, 0x94AA, 0x6568, 0x94AB, 0x6569, 0x94AC, 0x656A, 0x94AD, + 0x656B, 0xEBB8, 0x656C, 0xBEB4, 0x656D, 0x94AE, 0x656E, 0x94AF, 0x656F, 0x94B0, 0x6570, 0xCAFD, 0x6571, 0x94B1, 0x6572, 0xC7C3, + 0x6573, 0x94B2, 0x6574, 0xD5FB, 0x6575, 0x94B3, 0x6576, 0x94B4, 0x6577, 0xB7F3, 0x6578, 0x94B5, 0x6579, 0x94B6, 0x657A, 0x94B7, + 0x657B, 0x94B8, 0x657C, 0x94B9, 0x657D, 0x94BA, 0x657E, 0x94BB, 0x657F, 0x94BC, 0x6580, 0x94BD, 0x6581, 0x94BE, 0x6582, 0x94BF, + 0x6583, 0x94C0, 0x6584, 0x94C1, 0x6585, 0x94C2, 0x6586, 0x94C3, 0x6587, 0xCEC4, 0x6588, 0x94C4, 0x6589, 0x94C5, 0x658A, 0x94C6, + 0x658B, 0xD5AB, 0x658C, 0xB1F3, 0x658D, 0x94C7, 0x658E, 0x94C8, 0x658F, 0x94C9, 0x6590, 0xECB3, 0x6591, 0xB0DF, 0x6592, 0x94CA, + 0x6593, 0xECB5, 0x6594, 0x94CB, 0x6595, 0x94CC, 0x6596, 0x94CD, 0x6597, 0xB6B7, 0x6598, 0x94CE, 0x6599, 0xC1CF, 0x659A, 0x94CF, + 0x659B, 0xF5FA, 0x659C, 0xD0B1, 0x659D, 0x94D0, 0x659E, 0x94D1, 0x659F, 0xD5E5, 0x65A0, 0x94D2, 0x65A1, 0xCED3, 0x65A2, 0x94D3, + 0x65A3, 0x94D4, 0x65A4, 0xBDEF, 0x65A5, 0xB3E2, 0x65A6, 0x94D5, 0x65A7, 0xB8AB, 0x65A8, 0x94D6, 0x65A9, 0xD5B6, 0x65AA, 0x94D7, + 0x65AB, 0xEDBD, 0x65AC, 0x94D8, 0x65AD, 0xB6CF, 0x65AE, 0x94D9, 0x65AF, 0xCBB9, 0x65B0, 0xD0C2, 0x65B1, 0x94DA, 0x65B2, 0x94DB, + 0x65B3, 0x94DC, 0x65B4, 0x94DD, 0x65B5, 0x94DE, 0x65B6, 0x94DF, 0x65B7, 0x94E0, 0x65B8, 0x94E1, 0x65B9, 0xB7BD, 0x65BA, 0x94E2, + 0x65BB, 0x94E3, 0x65BC, 0xECB6, 0x65BD, 0xCAA9, 0x65BE, 0x94E4, 0x65BF, 0x94E5, 0x65C0, 0x94E6, 0x65C1, 0xC5D4, 0x65C2, 0x94E7, + 0x65C3, 0xECB9, 0x65C4, 0xECB8, 0x65C5, 0xC2C3, 0x65C6, 0xECB7, 0x65C7, 0x94E8, 0x65C8, 0x94E9, 0x65C9, 0x94EA, 0x65CA, 0x94EB, + 0x65CB, 0xD0FD, 0x65CC, 0xECBA, 0x65CD, 0x94EC, 0x65CE, 0xECBB, 0x65CF, 0xD7E5, 0x65D0, 0x94ED, 0x65D1, 0x94EE, 0x65D2, 0xECBC, + 0x65D3, 0x94EF, 0x65D4, 0x94F0, 0x65D5, 0x94F1, 0x65D6, 0xECBD, 0x65D7, 0xC6EC, 0x65D8, 0x94F2, 0x65D9, 0x94F3, 0x65DA, 0x94F4, + 0x65DB, 0x94F5, 0x65DC, 0x94F6, 0x65DD, 0x94F7, 0x65DE, 0x94F8, 0x65DF, 0x94F9, 0x65E0, 0xCEDE, 0x65E1, 0x94FA, 0x65E2, 0xBCC8, + 0x65E3, 0x94FB, 0x65E4, 0x94FC, 0x65E5, 0xC8D5, 0x65E6, 0xB5A9, 0x65E7, 0xBEC9, 0x65E8, 0xD6BC, 0x65E9, 0xD4E7, 0x65EA, 0x94FD, + 0x65EB, 0x94FE, 0x65EC, 0xD1AE, 0x65ED, 0xD0F1, 0x65EE, 0xEAB8, 0x65EF, 0xEAB9, 0x65F0, 0xEABA, 0x65F1, 0xBAB5, 0x65F2, 0x9540, + 0x65F3, 0x9541, 0x65F4, 0x9542, 0x65F5, 0x9543, 0x65F6, 0xCAB1, 0x65F7, 0xBFF5, 0x65F8, 0x9544, 0x65F9, 0x9545, 0x65FA, 0xCDFA, + 0x65FB, 0x9546, 0x65FC, 0x9547, 0x65FD, 0x9548, 0x65FE, 0x9549, 0x65FF, 0x954A, 0x6600, 0xEAC0, 0x6601, 0x954B, 0x6602, 0xB0BA, + 0x6603, 0xEABE, 0x6604, 0x954C, 0x6605, 0x954D, 0x6606, 0xC0A5, 0x6607, 0x954E, 0x6608, 0x954F, 0x6609, 0x9550, 0x660A, 0xEABB, + 0x660B, 0x9551, 0x660C, 0xB2FD, 0x660D, 0x9552, 0x660E, 0xC3F7, 0x660F, 0xBBE8, 0x6610, 0x9553, 0x6611, 0x9554, 0x6612, 0x9555, + 0x6613, 0xD2D7, 0x6614, 0xCEF4, 0x6615, 0xEABF, 0x6616, 0x9556, 0x6617, 0x9557, 0x6618, 0x9558, 0x6619, 0xEABC, 0x661A, 0x9559, + 0x661B, 0x955A, 0x661C, 0x955B, 0x661D, 0xEAC3, 0x661E, 0x955C, 0x661F, 0xD0C7, 0x6620, 0xD3B3, 0x6621, 0x955D, 0x6622, 0x955E, + 0x6623, 0x955F, 0x6624, 0x9560, 0x6625, 0xB4BA, 0x6626, 0x9561, 0x6627, 0xC3C1, 0x6628, 0xD7F2, 0x6629, 0x9562, 0x662A, 0x9563, + 0x662B, 0x9564, 0x662C, 0x9565, 0x662D, 0xD5D1, 0x662E, 0x9566, 0x662F, 0xCAC7, 0x6630, 0x9567, 0x6631, 0xEAC5, 0x6632, 0x9568, + 0x6633, 0x9569, 0x6634, 0xEAC4, 0x6635, 0xEAC7, 0x6636, 0xEAC6, 0x6637, 0x956A, 0x6638, 0x956B, 0x6639, 0x956C, 0x663A, 0x956D, + 0x663B, 0x956E, 0x663C, 0xD6E7, 0x663D, 0x956F, 0x663E, 0xCFD4, 0x663F, 0x9570, 0x6640, 0x9571, 0x6641, 0xEACB, 0x6642, 0x9572, + 0x6643, 0xBBCE, 0x6644, 0x9573, 0x6645, 0x9574, 0x6646, 0x9575, 0x6647, 0x9576, 0x6648, 0x9577, 0x6649, 0x9578, 0x664A, 0x9579, + 0x664B, 0xBDFA, 0x664C, 0xC9CE, 0x664D, 0x957A, 0x664E, 0x957B, 0x664F, 0xEACC, 0x6650, 0x957C, 0x6651, 0x957D, 0x6652, 0xC9B9, + 0x6653, 0xCFFE, 0x6654, 0xEACA, 0x6655, 0xD4CE, 0x6656, 0xEACD, 0x6657, 0xEACF, 0x6658, 0x957E, 0x6659, 0x9580, 0x665A, 0xCDED, + 0x665B, 0x9581, 0x665C, 0x9582, 0x665D, 0x9583, 0x665E, 0x9584, 0x665F, 0xEAC9, 0x6660, 0x9585, 0x6661, 0xEACE, 0x6662, 0x9586, + 0x6663, 0x9587, 0x6664, 0xCEEE, 0x6665, 0x9588, 0x6666, 0xBBDE, 0x6667, 0x9589, 0x6668, 0xB3BF, 0x6669, 0x958A, 0x666A, 0x958B, + 0x666B, 0x958C, 0x666C, 0x958D, 0x666D, 0x958E, 0x666E, 0xC6D5, 0x666F, 0xBEB0, 0x6670, 0xCEFA, 0x6671, 0x958F, 0x6672, 0x9590, + 0x6673, 0x9591, 0x6674, 0xC7E7, 0x6675, 0x9592, 0x6676, 0xBEA7, 0x6677, 0xEAD0, 0x6678, 0x9593, 0x6679, 0x9594, 0x667A, 0xD6C7, + 0x667B, 0x9595, 0x667C, 0x9596, 0x667D, 0x9597, 0x667E, 0xC1C0, 0x667F, 0x9598, 0x6680, 0x9599, 0x6681, 0x959A, 0x6682, 0xD4DD, + 0x6683, 0x959B, 0x6684, 0xEAD1, 0x6685, 0x959C, 0x6686, 0x959D, 0x6687, 0xCFBE, 0x6688, 0x959E, 0x6689, 0x959F, 0x668A, 0x95A0, + 0x668B, 0x95A1, 0x668C, 0xEAD2, 0x668D, 0x95A2, 0x668E, 0x95A3, 0x668F, 0x95A4, 0x6690, 0x95A5, 0x6691, 0xCAEE, 0x6692, 0x95A6, + 0x6693, 0x95A7, 0x6694, 0x95A8, 0x6695, 0x95A9, 0x6696, 0xC5AF, 0x6697, 0xB0B5, 0x6698, 0x95AA, 0x6699, 0x95AB, 0x669A, 0x95AC, + 0x669B, 0x95AD, 0x669C, 0x95AE, 0x669D, 0xEAD4, 0x669E, 0x95AF, 0x669F, 0x95B0, 0x66A0, 0x95B1, 0x66A1, 0x95B2, 0x66A2, 0x95B3, + 0x66A3, 0x95B4, 0x66A4, 0x95B5, 0x66A5, 0x95B6, 0x66A6, 0x95B7, 0x66A7, 0xEAD3, 0x66A8, 0xF4DF, 0x66A9, 0x95B8, 0x66AA, 0x95B9, + 0x66AB, 0x95BA, 0x66AC, 0x95BB, 0x66AD, 0x95BC, 0x66AE, 0xC4BA, 0x66AF, 0x95BD, 0x66B0, 0x95BE, 0x66B1, 0x95BF, 0x66B2, 0x95C0, + 0x66B3, 0x95C1, 0x66B4, 0xB1A9, 0x66B5, 0x95C2, 0x66B6, 0x95C3, 0x66B7, 0x95C4, 0x66B8, 0x95C5, 0x66B9, 0xE5DF, 0x66BA, 0x95C6, + 0x66BB, 0x95C7, 0x66BC, 0x95C8, 0x66BD, 0x95C9, 0x66BE, 0xEAD5, 0x66BF, 0x95CA, 0x66C0, 0x95CB, 0x66C1, 0x95CC, 0x66C2, 0x95CD, + 0x66C3, 0x95CE, 0x66C4, 0x95CF, 0x66C5, 0x95D0, 0x66C6, 0x95D1, 0x66C7, 0x95D2, 0x66C8, 0x95D3, 0x66C9, 0x95D4, 0x66CA, 0x95D5, + 0x66CB, 0x95D6, 0x66CC, 0x95D7, 0x66CD, 0x95D8, 0x66CE, 0x95D9, 0x66CF, 0x95DA, 0x66D0, 0x95DB, 0x66D1, 0x95DC, 0x66D2, 0x95DD, + 0x66D3, 0x95DE, 0x66D4, 0x95DF, 0x66D5, 0x95E0, 0x66D6, 0x95E1, 0x66D7, 0x95E2, 0x66D8, 0x95E3, 0x66D9, 0xCAEF, 0x66DA, 0x95E4, + 0x66DB, 0xEAD6, 0x66DC, 0xEAD7, 0x66DD, 0xC6D8, 0x66DE, 0x95E5, 0x66DF, 0x95E6, 0x66E0, 0x95E7, 0x66E1, 0x95E8, 0x66E2, 0x95E9, + 0x66E3, 0x95EA, 0x66E4, 0x95EB, 0x66E5, 0x95EC, 0x66E6, 0xEAD8, 0x66E7, 0x95ED, 0x66E8, 0x95EE, 0x66E9, 0xEAD9, 0x66EA, 0x95EF, + 0x66EB, 0x95F0, 0x66EC, 0x95F1, 0x66ED, 0x95F2, 0x66EE, 0x95F3, 0x66EF, 0x95F4, 0x66F0, 0xD4BB, 0x66F1, 0x95F5, 0x66F2, 0xC7FA, + 0x66F3, 0xD2B7, 0x66F4, 0xB8FC, 0x66F5, 0x95F6, 0x66F6, 0x95F7, 0x66F7, 0xEAC2, 0x66F8, 0x95F8, 0x66F9, 0xB2DC, 0x66FA, 0x95F9, + 0x66FB, 0x95FA, 0x66FC, 0xC2FC, 0x66FD, 0x95FB, 0x66FE, 0xD4F8, 0x66FF, 0xCCE6, 0x6700, 0xD7EE, 0x6701, 0x95FC, 0x6702, 0x95FD, + 0x6703, 0x95FE, 0x6704, 0x9640, 0x6705, 0x9641, 0x6706, 0x9642, 0x6707, 0x9643, 0x6708, 0xD4C2, 0x6709, 0xD3D0, 0x670A, 0xEBC3, + 0x670B, 0xC5F3, 0x670C, 0x9644, 0x670D, 0xB7FE, 0x670E, 0x9645, 0x670F, 0x9646, 0x6710, 0xEBD4, 0x6711, 0x9647, 0x6712, 0x9648, + 0x6713, 0x9649, 0x6714, 0xCBB7, 0x6715, 0xEBDE, 0x6716, 0x964A, 0x6717, 0xC0CA, 0x6718, 0x964B, 0x6719, 0x964C, 0x671A, 0x964D, + 0x671B, 0xCDFB, 0x671C, 0x964E, 0x671D, 0xB3AF, 0x671E, 0x964F, 0x671F, 0xC6DA, 0x6720, 0x9650, 0x6721, 0x9651, 0x6722, 0x9652, + 0x6723, 0x9653, 0x6724, 0x9654, 0x6725, 0x9655, 0x6726, 0xEBFC, 0x6727, 0x9656, 0x6728, 0xC4BE, 0x6729, 0x9657, 0x672A, 0xCEB4, + 0x672B, 0xC4A9, 0x672C, 0xB1BE, 0x672D, 0xD4FD, 0x672E, 0x9658, 0x672F, 0xCAF5, 0x6730, 0x9659, 0x6731, 0xD6EC, 0x6732, 0x965A, + 0x6733, 0x965B, 0x6734, 0xC6D3, 0x6735, 0xB6E4, 0x6736, 0x965C, 0x6737, 0x965D, 0x6738, 0x965E, 0x6739, 0x965F, 0x673A, 0xBBFA, + 0x673B, 0x9660, 0x673C, 0x9661, 0x673D, 0xD0E0, 0x673E, 0x9662, 0x673F, 0x9663, 0x6740, 0xC9B1, 0x6741, 0x9664, 0x6742, 0xD4D3, + 0x6743, 0xC8A8, 0x6744, 0x9665, 0x6745, 0x9666, 0x6746, 0xB8CB, 0x6747, 0x9667, 0x6748, 0xE8BE, 0x6749, 0xC9BC, 0x674A, 0x9668, + 0x674B, 0x9669, 0x674C, 0xE8BB, 0x674D, 0x966A, 0x674E, 0xC0EE, 0x674F, 0xD0D3, 0x6750, 0xB2C4, 0x6751, 0xB4E5, 0x6752, 0x966B, + 0x6753, 0xE8BC, 0x6754, 0x966C, 0x6755, 0x966D, 0x6756, 0xD5C8, 0x6757, 0x966E, 0x6758, 0x966F, 0x6759, 0x9670, 0x675A, 0x9671, + 0x675B, 0x9672, 0x675C, 0xB6C5, 0x675D, 0x9673, 0x675E, 0xE8BD, 0x675F, 0xCAF8, 0x6760, 0xB8DC, 0x6761, 0xCCF5, 0x6762, 0x9674, + 0x6763, 0x9675, 0x6764, 0x9676, 0x6765, 0xC0B4, 0x6766, 0x9677, 0x6767, 0x9678, 0x6768, 0xD1EE, 0x6769, 0xE8BF, 0x676A, 0xE8C2, + 0x676B, 0x9679, 0x676C, 0x967A, 0x676D, 0xBABC, 0x676E, 0x967B, 0x676F, 0xB1AD, 0x6770, 0xBDDC, 0x6771, 0x967C, 0x6772, 0xEABD, + 0x6773, 0xE8C3, 0x6774, 0x967D, 0x6775, 0xE8C6, 0x6776, 0x967E, 0x6777, 0xE8CB, 0x6778, 0x9680, 0x6779, 0x9681, 0x677A, 0x9682, + 0x677B, 0x9683, 0x677C, 0xE8CC, 0x677D, 0x9684, 0x677E, 0xCBC9, 0x677F, 0xB0E5, 0x6780, 0x9685, 0x6781, 0xBCAB, 0x6782, 0x9686, + 0x6783, 0x9687, 0x6784, 0xB9B9, 0x6785, 0x9688, 0x6786, 0x9689, 0x6787, 0xE8C1, 0x6788, 0x968A, 0x6789, 0xCDF7, 0x678A, 0x968B, + 0x678B, 0xE8CA, 0x678C, 0x968C, 0x678D, 0x968D, 0x678E, 0x968E, 0x678F, 0x968F, 0x6790, 0xCEF6, 0x6791, 0x9690, 0x6792, 0x9691, + 0x6793, 0x9692, 0x6794, 0x9693, 0x6795, 0xD5ED, 0x6796, 0x9694, 0x6797, 0xC1D6, 0x6798, 0xE8C4, 0x6799, 0x9695, 0x679A, 0xC3B6, + 0x679B, 0x9696, 0x679C, 0xB9FB, 0x679D, 0xD6A6, 0x679E, 0xE8C8, 0x679F, 0x9697, 0x67A0, 0x9698, 0x67A1, 0x9699, 0x67A2, 0xCAE0, + 0x67A3, 0xD4E6, 0x67A4, 0x969A, 0x67A5, 0xE8C0, 0x67A6, 0x969B, 0x67A7, 0xE8C5, 0x67A8, 0xE8C7, 0x67A9, 0x969C, 0x67AA, 0xC7B9, + 0x67AB, 0xB7E3, 0x67AC, 0x969D, 0x67AD, 0xE8C9, 0x67AE, 0x969E, 0x67AF, 0xBFDD, 0x67B0, 0xE8D2, 0x67B1, 0x969F, 0x67B2, 0x96A0, + 0x67B3, 0xE8D7, 0x67B4, 0x96A1, 0x67B5, 0xE8D5, 0x67B6, 0xBCDC, 0x67B7, 0xBCCF, 0x67B8, 0xE8DB, 0x67B9, 0x96A2, 0x67BA, 0x96A3, + 0x67BB, 0x96A4, 0x67BC, 0x96A5, 0x67BD, 0x96A6, 0x67BE, 0x96A7, 0x67BF, 0x96A8, 0x67C0, 0x96A9, 0x67C1, 0xE8DE, 0x67C2, 0x96AA, + 0x67C3, 0xE8DA, 0x67C4, 0xB1FA, 0x67C5, 0x96AB, 0x67C6, 0x96AC, 0x67C7, 0x96AD, 0x67C8, 0x96AE, 0x67C9, 0x96AF, 0x67CA, 0x96B0, + 0x67CB, 0x96B1, 0x67CC, 0x96B2, 0x67CD, 0x96B3, 0x67CE, 0x96B4, 0x67CF, 0xB0D8, 0x67D0, 0xC4B3, 0x67D1, 0xB8CC, 0x67D2, 0xC6E2, + 0x67D3, 0xC8BE, 0x67D4, 0xC8E1, 0x67D5, 0x96B5, 0x67D6, 0x96B6, 0x67D7, 0x96B7, 0x67D8, 0xE8CF, 0x67D9, 0xE8D4, 0x67DA, 0xE8D6, + 0x67DB, 0x96B8, 0x67DC, 0xB9F1, 0x67DD, 0xE8D8, 0x67DE, 0xD7F5, 0x67DF, 0x96B9, 0x67E0, 0xC4FB, 0x67E1, 0x96BA, 0x67E2, 0xE8DC, + 0x67E3, 0x96BB, 0x67E4, 0x96BC, 0x67E5, 0xB2E9, 0x67E6, 0x96BD, 0x67E7, 0x96BE, 0x67E8, 0x96BF, 0x67E9, 0xE8D1, 0x67EA, 0x96C0, + 0x67EB, 0x96C1, 0x67EC, 0xBCED, 0x67ED, 0x96C2, 0x67EE, 0x96C3, 0x67EF, 0xBFC2, 0x67F0, 0xE8CD, 0x67F1, 0xD6F9, 0x67F2, 0x96C4, + 0x67F3, 0xC1F8, 0x67F4, 0xB2F1, 0x67F5, 0x96C5, 0x67F6, 0x96C6, 0x67F7, 0x96C7, 0x67F8, 0x96C8, 0x67F9, 0x96C9, 0x67FA, 0x96CA, + 0x67FB, 0x96CB, 0x67FC, 0x96CC, 0x67FD, 0xE8DF, 0x67FE, 0x96CD, 0x67FF, 0xCAC1, 0x6800, 0xE8D9, 0x6801, 0x96CE, 0x6802, 0x96CF, + 0x6803, 0x96D0, 0x6804, 0x96D1, 0x6805, 0xD5A4, 0x6806, 0x96D2, 0x6807, 0xB1EA, 0x6808, 0xD5BB, 0x6809, 0xE8CE, 0x680A, 0xE8D0, + 0x680B, 0xB6B0, 0x680C, 0xE8D3, 0x680D, 0x96D3, 0x680E, 0xE8DD, 0x680F, 0xC0B8, 0x6810, 0x96D4, 0x6811, 0xCAF7, 0x6812, 0x96D5, + 0x6813, 0xCBA8, 0x6814, 0x96D6, 0x6815, 0x96D7, 0x6816, 0xC6DC, 0x6817, 0xC0F5, 0x6818, 0x96D8, 0x6819, 0x96D9, 0x681A, 0x96DA, + 0x681B, 0x96DB, 0x681C, 0x96DC, 0x681D, 0xE8E9, 0x681E, 0x96DD, 0x681F, 0x96DE, 0x6820, 0x96DF, 0x6821, 0xD0A3, 0x6822, 0x96E0, + 0x6823, 0x96E1, 0x6824, 0x96E2, 0x6825, 0x96E3, 0x6826, 0x96E4, 0x6827, 0x96E5, 0x6828, 0x96E6, 0x6829, 0xE8F2, 0x682A, 0xD6EA, + 0x682B, 0x96E7, 0x682C, 0x96E8, 0x682D, 0x96E9, 0x682E, 0x96EA, 0x682F, 0x96EB, 0x6830, 0x96EC, 0x6831, 0x96ED, 0x6832, 0xE8E0, + 0x6833, 0xE8E1, 0x6834, 0x96EE, 0x6835, 0x96EF, 0x6836, 0x96F0, 0x6837, 0xD1F9, 0x6838, 0xBACB, 0x6839, 0xB8F9, 0x683A, 0x96F1, + 0x683B, 0x96F2, 0x683C, 0xB8F1, 0x683D, 0xD4D4, 0x683E, 0xE8EF, 0x683F, 0x96F3, 0x6840, 0xE8EE, 0x6841, 0xE8EC, 0x6842, 0xB9F0, + 0x6843, 0xCCD2, 0x6844, 0xE8E6, 0x6845, 0xCEA6, 0x6846, 0xBFF2, 0x6847, 0x96F4, 0x6848, 0xB0B8, 0x6849, 0xE8F1, 0x684A, 0xE8F0, + 0x684B, 0x96F5, 0x684C, 0xD7C0, 0x684D, 0x96F6, 0x684E, 0xE8E4, 0x684F, 0x96F7, 0x6850, 0xCDA9, 0x6851, 0xC9A3, 0x6852, 0x96F8, + 0x6853, 0xBBB8, 0x6854, 0xBDDB, 0x6855, 0xE8EA, 0x6856, 0x96F9, 0x6857, 0x96FA, 0x6858, 0x96FB, 0x6859, 0x96FC, 0x685A, 0x96FD, + 0x685B, 0x96FE, 0x685C, 0x9740, 0x685D, 0x9741, 0x685E, 0x9742, 0x685F, 0x9743, 0x6860, 0xE8E2, 0x6861, 0xE8E3, 0x6862, 0xE8E5, + 0x6863, 0xB5B5, 0x6864, 0xE8E7, 0x6865, 0xC7C5, 0x6866, 0xE8EB, 0x6867, 0xE8ED, 0x6868, 0xBDB0, 0x6869, 0xD7AE, 0x686A, 0x9744, + 0x686B, 0xE8F8, 0x686C, 0x9745, 0x686D, 0x9746, 0x686E, 0x9747, 0x686F, 0x9748, 0x6870, 0x9749, 0x6871, 0x974A, 0x6872, 0x974B, + 0x6873, 0x974C, 0x6874, 0xE8F5, 0x6875, 0x974D, 0x6876, 0xCDB0, 0x6877, 0xE8F6, 0x6878, 0x974E, 0x6879, 0x974F, 0x687A, 0x9750, + 0x687B, 0x9751, 0x687C, 0x9752, 0x687D, 0x9753, 0x687E, 0x9754, 0x687F, 0x9755, 0x6880, 0x9756, 0x6881, 0xC1BA, 0x6882, 0x9757, + 0x6883, 0xE8E8, 0x6884, 0x9758, 0x6885, 0xC3B7, 0x6886, 0xB0F0, 0x6887, 0x9759, 0x6888, 0x975A, 0x6889, 0x975B, 0x688A, 0x975C, + 0x688B, 0x975D, 0x688C, 0x975E, 0x688D, 0x975F, 0x688E, 0x9760, 0x688F, 0xE8F4, 0x6890, 0x9761, 0x6891, 0x9762, 0x6892, 0x9763, + 0x6893, 0xE8F7, 0x6894, 0x9764, 0x6895, 0x9765, 0x6896, 0x9766, 0x6897, 0xB9A3, 0x6898, 0x9767, 0x6899, 0x9768, 0x689A, 0x9769, + 0x689B, 0x976A, 0x689C, 0x976B, 0x689D, 0x976C, 0x689E, 0x976D, 0x689F, 0x976E, 0x68A0, 0x976F, 0x68A1, 0x9770, 0x68A2, 0xC9D2, + 0x68A3, 0x9771, 0x68A4, 0x9772, 0x68A5, 0x9773, 0x68A6, 0xC3CE, 0x68A7, 0xCEE0, 0x68A8, 0xC0E6, 0x68A9, 0x9774, 0x68AA, 0x9775, + 0x68AB, 0x9776, 0x68AC, 0x9777, 0x68AD, 0xCBF3, 0x68AE, 0x9778, 0x68AF, 0xCCDD, 0x68B0, 0xD0B5, 0x68B1, 0x9779, 0x68B2, 0x977A, + 0x68B3, 0xCAE1, 0x68B4, 0x977B, 0x68B5, 0xE8F3, 0x68B6, 0x977C, 0x68B7, 0x977D, 0x68B8, 0x977E, 0x68B9, 0x9780, 0x68BA, 0x9781, + 0x68BB, 0x9782, 0x68BC, 0x9783, 0x68BD, 0x9784, 0x68BE, 0x9785, 0x68BF, 0x9786, 0x68C0, 0xBCEC, 0x68C1, 0x9787, 0x68C2, 0xE8F9, + 0x68C3, 0x9788, 0x68C4, 0x9789, 0x68C5, 0x978A, 0x68C6, 0x978B, 0x68C7, 0x978C, 0x68C8, 0x978D, 0x68C9, 0xC3DE, 0x68CA, 0x978E, + 0x68CB, 0xC6E5, 0x68CC, 0x978F, 0x68CD, 0xB9F7, 0x68CE, 0x9790, 0x68CF, 0x9791, 0x68D0, 0x9792, 0x68D1, 0x9793, 0x68D2, 0xB0F4, + 0x68D3, 0x9794, 0x68D4, 0x9795, 0x68D5, 0xD7D8, 0x68D6, 0x9796, 0x68D7, 0x9797, 0x68D8, 0xBCAC, 0x68D9, 0x9798, 0x68DA, 0xC5EF, + 0x68DB, 0x9799, 0x68DC, 0x979A, 0x68DD, 0x979B, 0x68DE, 0x979C, 0x68DF, 0x979D, 0x68E0, 0xCCC4, 0x68E1, 0x979E, 0x68E2, 0x979F, + 0x68E3, 0xE9A6, 0x68E4, 0x97A0, 0x68E5, 0x97A1, 0x68E6, 0x97A2, 0x68E7, 0x97A3, 0x68E8, 0x97A4, 0x68E9, 0x97A5, 0x68EA, 0x97A6, + 0x68EB, 0x97A7, 0x68EC, 0x97A8, 0x68ED, 0x97A9, 0x68EE, 0xC9AD, 0x68EF, 0x97AA, 0x68F0, 0xE9A2, 0x68F1, 0xC0E2, 0x68F2, 0x97AB, + 0x68F3, 0x97AC, 0x68F4, 0x97AD, 0x68F5, 0xBFC3, 0x68F6, 0x97AE, 0x68F7, 0x97AF, 0x68F8, 0x97B0, 0x68F9, 0xE8FE, 0x68FA, 0xB9D7, + 0x68FB, 0x97B1, 0x68FC, 0xE8FB, 0x68FD, 0x97B2, 0x68FE, 0x97B3, 0x68FF, 0x97B4, 0x6900, 0x97B5, 0x6901, 0xE9A4, 0x6902, 0x97B6, + 0x6903, 0x97B7, 0x6904, 0x97B8, 0x6905, 0xD2CE, 0x6906, 0x97B9, 0x6907, 0x97BA, 0x6908, 0x97BB, 0x6909, 0x97BC, 0x690A, 0x97BD, + 0x690B, 0xE9A3, 0x690C, 0x97BE, 0x690D, 0xD6B2, 0x690E, 0xD7B5, 0x690F, 0x97BF, 0x6910, 0xE9A7, 0x6911, 0x97C0, 0x6912, 0xBDB7, + 0x6913, 0x97C1, 0x6914, 0x97C2, 0x6915, 0x97C3, 0x6916, 0x97C4, 0x6917, 0x97C5, 0x6918, 0x97C6, 0x6919, 0x97C7, 0x691A, 0x97C8, + 0x691B, 0x97C9, 0x691C, 0x97CA, 0x691D, 0x97CB, 0x691E, 0x97CC, 0x691F, 0xE8FC, 0x6920, 0xE8FD, 0x6921, 0x97CD, 0x6922, 0x97CE, + 0x6923, 0x97CF, 0x6924, 0xE9A1, 0x6925, 0x97D0, 0x6926, 0x97D1, 0x6927, 0x97D2, 0x6928, 0x97D3, 0x6929, 0x97D4, 0x692A, 0x97D5, + 0x692B, 0x97D6, 0x692C, 0x97D7, 0x692D, 0xCDD6, 0x692E, 0x97D8, 0x692F, 0x97D9, 0x6930, 0xD2AC, 0x6931, 0x97DA, 0x6932, 0x97DB, + 0x6933, 0x97DC, 0x6934, 0xE9B2, 0x6935, 0x97DD, 0x6936, 0x97DE, 0x6937, 0x97DF, 0x6938, 0x97E0, 0x6939, 0xE9A9, 0x693A, 0x97E1, + 0x693B, 0x97E2, 0x693C, 0x97E3, 0x693D, 0xB4AA, 0x693E, 0x97E4, 0x693F, 0xB4BB, 0x6940, 0x97E5, 0x6941, 0x97E6, 0x6942, 0xE9AB, + 0x6943, 0x97E7, 0x6944, 0x97E8, 0x6945, 0x97E9, 0x6946, 0x97EA, 0x6947, 0x97EB, 0x6948, 0x97EC, 0x6949, 0x97ED, 0x694A, 0x97EE, + 0x694B, 0x97EF, 0x694C, 0x97F0, 0x694D, 0x97F1, 0x694E, 0x97F2, 0x694F, 0x97F3, 0x6950, 0x97F4, 0x6951, 0x97F5, 0x6952, 0x97F6, + 0x6953, 0x97F7, 0x6954, 0xD0A8, 0x6955, 0x97F8, 0x6956, 0x97F9, 0x6957, 0xE9A5, 0x6958, 0x97FA, 0x6959, 0x97FB, 0x695A, 0xB3FE, + 0x695B, 0x97FC, 0x695C, 0x97FD, 0x695D, 0xE9AC, 0x695E, 0xC0E3, 0x695F, 0x97FE, 0x6960, 0xE9AA, 0x6961, 0x9840, 0x6962, 0x9841, + 0x6963, 0xE9B9, 0x6964, 0x9842, 0x6965, 0x9843, 0x6966, 0xE9B8, 0x6967, 0x9844, 0x6968, 0x9845, 0x6969, 0x9846, 0x696A, 0x9847, + 0x696B, 0xE9AE, 0x696C, 0x9848, 0x696D, 0x9849, 0x696E, 0xE8FA, 0x696F, 0x984A, 0x6970, 0x984B, 0x6971, 0xE9A8, 0x6972, 0x984C, + 0x6973, 0x984D, 0x6974, 0x984E, 0x6975, 0x984F, 0x6976, 0x9850, 0x6977, 0xBFAC, 0x6978, 0xE9B1, 0x6979, 0xE9BA, 0x697A, 0x9851, + 0x697B, 0x9852, 0x697C, 0xC2A5, 0x697D, 0x9853, 0x697E, 0x9854, 0x697F, 0x9855, 0x6980, 0xE9AF, 0x6981, 0x9856, 0x6982, 0xB8C5, + 0x6983, 0x9857, 0x6984, 0xE9AD, 0x6985, 0x9858, 0x6986, 0xD3DC, 0x6987, 0xE9B4, 0x6988, 0xE9B5, 0x6989, 0xE9B7, 0x698A, 0x9859, + 0x698B, 0x985A, 0x698C, 0x985B, 0x698D, 0xE9C7, 0x698E, 0x985C, 0x698F, 0x985D, 0x6990, 0x985E, 0x6991, 0x985F, 0x6992, 0x9860, + 0x6993, 0x9861, 0x6994, 0xC0C6, 0x6995, 0xE9C5, 0x6996, 0x9862, 0x6997, 0x9863, 0x6998, 0xE9B0, 0x6999, 0x9864, 0x699A, 0x9865, + 0x699B, 0xE9BB, 0x699C, 0xB0F1, 0x699D, 0x9866, 0x699E, 0x9867, 0x699F, 0x9868, 0x69A0, 0x9869, 0x69A1, 0x986A, 0x69A2, 0x986B, + 0x69A3, 0x986C, 0x69A4, 0x986D, 0x69A5, 0x986E, 0x69A6, 0x986F, 0x69A7, 0xE9BC, 0x69A8, 0xD5A5, 0x69A9, 0x9870, 0x69AA, 0x9871, + 0x69AB, 0xE9BE, 0x69AC, 0x9872, 0x69AD, 0xE9BF, 0x69AE, 0x9873, 0x69AF, 0x9874, 0x69B0, 0x9875, 0x69B1, 0xE9C1, 0x69B2, 0x9876, + 0x69B3, 0x9877, 0x69B4, 0xC1F1, 0x69B5, 0x9878, 0x69B6, 0x9879, 0x69B7, 0xC8B6, 0x69B8, 0x987A, 0x69B9, 0x987B, 0x69BA, 0x987C, + 0x69BB, 0xE9BD, 0x69BC, 0x987D, 0x69BD, 0x987E, 0x69BE, 0x9880, 0x69BF, 0x9881, 0x69C0, 0x9882, 0x69C1, 0xE9C2, 0x69C2, 0x9883, + 0x69C3, 0x9884, 0x69C4, 0x9885, 0x69C5, 0x9886, 0x69C6, 0x9887, 0x69C7, 0x9888, 0x69C8, 0x9889, 0x69C9, 0x988A, 0x69CA, 0xE9C3, + 0x69CB, 0x988B, 0x69CC, 0xE9B3, 0x69CD, 0x988C, 0x69CE, 0xE9B6, 0x69CF, 0x988D, 0x69D0, 0xBBB1, 0x69D1, 0x988E, 0x69D2, 0x988F, + 0x69D3, 0x9890, 0x69D4, 0xE9C0, 0x69D5, 0x9891, 0x69D6, 0x9892, 0x69D7, 0x9893, 0x69D8, 0x9894, 0x69D9, 0x9895, 0x69DA, 0x9896, + 0x69DB, 0xBCF7, 0x69DC, 0x9897, 0x69DD, 0x9898, 0x69DE, 0x9899, 0x69DF, 0xE9C4, 0x69E0, 0xE9C6, 0x69E1, 0x989A, 0x69E2, 0x989B, + 0x69E3, 0x989C, 0x69E4, 0x989D, 0x69E5, 0x989E, 0x69E6, 0x989F, 0x69E7, 0x98A0, 0x69E8, 0x98A1, 0x69E9, 0x98A2, 0x69EA, 0x98A3, + 0x69EB, 0x98A4, 0x69EC, 0x98A5, 0x69ED, 0xE9CA, 0x69EE, 0x98A6, 0x69EF, 0x98A7, 0x69F0, 0x98A8, 0x69F1, 0x98A9, 0x69F2, 0xE9CE, + 0x69F3, 0x98AA, 0x69F4, 0x98AB, 0x69F5, 0x98AC, 0x69F6, 0x98AD, 0x69F7, 0x98AE, 0x69F8, 0x98AF, 0x69F9, 0x98B0, 0x69FA, 0x98B1, + 0x69FB, 0x98B2, 0x69FC, 0x98B3, 0x69FD, 0xB2DB, 0x69FE, 0x98B4, 0x69FF, 0xE9C8, 0x6A00, 0x98B5, 0x6A01, 0x98B6, 0x6A02, 0x98B7, + 0x6A03, 0x98B8, 0x6A04, 0x98B9, 0x6A05, 0x98BA, 0x6A06, 0x98BB, 0x6A07, 0x98BC, 0x6A08, 0x98BD, 0x6A09, 0x98BE, 0x6A0A, 0xB7AE, + 0x6A0B, 0x98BF, 0x6A0C, 0x98C0, 0x6A0D, 0x98C1, 0x6A0E, 0x98C2, 0x6A0F, 0x98C3, 0x6A10, 0x98C4, 0x6A11, 0x98C5, 0x6A12, 0x98C6, + 0x6A13, 0x98C7, 0x6A14, 0x98C8, 0x6A15, 0x98C9, 0x6A16, 0x98CA, 0x6A17, 0xE9CB, 0x6A18, 0xE9CC, 0x6A19, 0x98CB, 0x6A1A, 0x98CC, + 0x6A1B, 0x98CD, 0x6A1C, 0x98CE, 0x6A1D, 0x98CF, 0x6A1E, 0x98D0, 0x6A1F, 0xD5C1, 0x6A20, 0x98D1, 0x6A21, 0xC4A3, 0x6A22, 0x98D2, + 0x6A23, 0x98D3, 0x6A24, 0x98D4, 0x6A25, 0x98D5, 0x6A26, 0x98D6, 0x6A27, 0x98D7, 0x6A28, 0xE9D8, 0x6A29, 0x98D8, 0x6A2A, 0xBAE1, + 0x6A2B, 0x98D9, 0x6A2C, 0x98DA, 0x6A2D, 0x98DB, 0x6A2E, 0x98DC, 0x6A2F, 0xE9C9, 0x6A30, 0x98DD, 0x6A31, 0xD3A3, 0x6A32, 0x98DE, + 0x6A33, 0x98DF, 0x6A34, 0x98E0, 0x6A35, 0xE9D4, 0x6A36, 0x98E1, 0x6A37, 0x98E2, 0x6A38, 0x98E3, 0x6A39, 0x98E4, 0x6A3A, 0x98E5, + 0x6A3B, 0x98E6, 0x6A3C, 0x98E7, 0x6A3D, 0xE9D7, 0x6A3E, 0xE9D0, 0x6A3F, 0x98E8, 0x6A40, 0x98E9, 0x6A41, 0x98EA, 0x6A42, 0x98EB, + 0x6A43, 0x98EC, 0x6A44, 0xE9CF, 0x6A45, 0x98ED, 0x6A46, 0x98EE, 0x6A47, 0xC7C1, 0x6A48, 0x98EF, 0x6A49, 0x98F0, 0x6A4A, 0x98F1, + 0x6A4B, 0x98F2, 0x6A4C, 0x98F3, 0x6A4D, 0x98F4, 0x6A4E, 0x98F5, 0x6A4F, 0x98F6, 0x6A50, 0xE9D2, 0x6A51, 0x98F7, 0x6A52, 0x98F8, + 0x6A53, 0x98F9, 0x6A54, 0x98FA, 0x6A55, 0x98FB, 0x6A56, 0x98FC, 0x6A57, 0x98FD, 0x6A58, 0xE9D9, 0x6A59, 0xB3C8, 0x6A5A, 0x98FE, + 0x6A5B, 0xE9D3, 0x6A5C, 0x9940, 0x6A5D, 0x9941, 0x6A5E, 0x9942, 0x6A5F, 0x9943, 0x6A60, 0x9944, 0x6A61, 0xCFF0, 0x6A62, 0x9945, + 0x6A63, 0x9946, 0x6A64, 0x9947, 0x6A65, 0xE9CD, 0x6A66, 0x9948, 0x6A67, 0x9949, 0x6A68, 0x994A, 0x6A69, 0x994B, 0x6A6A, 0x994C, + 0x6A6B, 0x994D, 0x6A6C, 0x994E, 0x6A6D, 0x994F, 0x6A6E, 0x9950, 0x6A6F, 0x9951, 0x6A70, 0x9952, 0x6A71, 0xB3F7, 0x6A72, 0x9953, + 0x6A73, 0x9954, 0x6A74, 0x9955, 0x6A75, 0x9956, 0x6A76, 0x9957, 0x6A77, 0x9958, 0x6A78, 0x9959, 0x6A79, 0xE9D6, 0x6A7A, 0x995A, + 0x6A7B, 0x995B, 0x6A7C, 0xE9DA, 0x6A7D, 0x995C, 0x6A7E, 0x995D, 0x6A7F, 0x995E, 0x6A80, 0xCCB4, 0x6A81, 0x995F, 0x6A82, 0x9960, + 0x6A83, 0x9961, 0x6A84, 0xCFAD, 0x6A85, 0x9962, 0x6A86, 0x9963, 0x6A87, 0x9964, 0x6A88, 0x9965, 0x6A89, 0x9966, 0x6A8A, 0x9967, + 0x6A8B, 0x9968, 0x6A8C, 0x9969, 0x6A8D, 0x996A, 0x6A8E, 0xE9D5, 0x6A8F, 0x996B, 0x6A90, 0xE9DC, 0x6A91, 0xE9DB, 0x6A92, 0x996C, + 0x6A93, 0x996D, 0x6A94, 0x996E, 0x6A95, 0x996F, 0x6A96, 0x9970, 0x6A97, 0xE9DE, 0x6A98, 0x9971, 0x6A99, 0x9972, 0x6A9A, 0x9973, + 0x6A9B, 0x9974, 0x6A9C, 0x9975, 0x6A9D, 0x9976, 0x6A9E, 0x9977, 0x6A9F, 0x9978, 0x6AA0, 0xE9D1, 0x6AA1, 0x9979, 0x6AA2, 0x997A, + 0x6AA3, 0x997B, 0x6AA4, 0x997C, 0x6AA5, 0x997D, 0x6AA6, 0x997E, 0x6AA7, 0x9980, 0x6AA8, 0x9981, 0x6AA9, 0xE9DD, 0x6AAA, 0x9982, + 0x6AAB, 0xE9DF, 0x6AAC, 0xC3CA, 0x6AAD, 0x9983, 0x6AAE, 0x9984, 0x6AAF, 0x9985, 0x6AB0, 0x9986, 0x6AB1, 0x9987, 0x6AB2, 0x9988, + 0x6AB3, 0x9989, 0x6AB4, 0x998A, 0x6AB5, 0x998B, 0x6AB6, 0x998C, 0x6AB7, 0x998D, 0x6AB8, 0x998E, 0x6AB9, 0x998F, 0x6ABA, 0x9990, + 0x6ABB, 0x9991, 0x6ABC, 0x9992, 0x6ABD, 0x9993, 0x6ABE, 0x9994, 0x6ABF, 0x9995, 0x6AC0, 0x9996, 0x6AC1, 0x9997, 0x6AC2, 0x9998, + 0x6AC3, 0x9999, 0x6AC4, 0x999A, 0x6AC5, 0x999B, 0x6AC6, 0x999C, 0x6AC7, 0x999D, 0x6AC8, 0x999E, 0x6AC9, 0x999F, 0x6ACA, 0x99A0, + 0x6ACB, 0x99A1, 0x6ACC, 0x99A2, 0x6ACD, 0x99A3, 0x6ACE, 0x99A4, 0x6ACF, 0x99A5, 0x6AD0, 0x99A6, 0x6AD1, 0x99A7, 0x6AD2, 0x99A8, + 0x6AD3, 0x99A9, 0x6AD4, 0x99AA, 0x6AD5, 0x99AB, 0x6AD6, 0x99AC, 0x6AD7, 0x99AD, 0x6AD8, 0x99AE, 0x6AD9, 0x99AF, 0x6ADA, 0x99B0, + 0x6ADB, 0x99B1, 0x6ADC, 0x99B2, 0x6ADD, 0x99B3, 0x6ADE, 0x99B4, 0x6ADF, 0x99B5, 0x6AE0, 0x99B6, 0x6AE1, 0x99B7, 0x6AE2, 0x99B8, + 0x6AE3, 0x99B9, 0x6AE4, 0x99BA, 0x6AE5, 0x99BB, 0x6AE6, 0x99BC, 0x6AE7, 0x99BD, 0x6AE8, 0x99BE, 0x6AE9, 0x99BF, 0x6AEA, 0x99C0, + 0x6AEB, 0x99C1, 0x6AEC, 0x99C2, 0x6AED, 0x99C3, 0x6AEE, 0x99C4, 0x6AEF, 0x99C5, 0x6AF0, 0x99C6, 0x6AF1, 0x99C7, 0x6AF2, 0x99C8, + 0x6AF3, 0x99C9, 0x6AF4, 0x99CA, 0x6AF5, 0x99CB, 0x6AF6, 0x99CC, 0x6AF7, 0x99CD, 0x6AF8, 0x99CE, 0x6AF9, 0x99CF, 0x6AFA, 0x99D0, + 0x6AFB, 0x99D1, 0x6AFC, 0x99D2, 0x6AFD, 0x99D3, 0x6AFE, 0x99D4, 0x6AFF, 0x99D5, 0x6B00, 0x99D6, 0x6B01, 0x99D7, 0x6B02, 0x99D8, + 0x6B03, 0x99D9, 0x6B04, 0x99DA, 0x6B05, 0x99DB, 0x6B06, 0x99DC, 0x6B07, 0x99DD, 0x6B08, 0x99DE, 0x6B09, 0x99DF, 0x6B0A, 0x99E0, + 0x6B0B, 0x99E1, 0x6B0C, 0x99E2, 0x6B0D, 0x99E3, 0x6B0E, 0x99E4, 0x6B0F, 0x99E5, 0x6B10, 0x99E6, 0x6B11, 0x99E7, 0x6B12, 0x99E8, + 0x6B13, 0x99E9, 0x6B14, 0x99EA, 0x6B15, 0x99EB, 0x6B16, 0x99EC, 0x6B17, 0x99ED, 0x6B18, 0x99EE, 0x6B19, 0x99EF, 0x6B1A, 0x99F0, + 0x6B1B, 0x99F1, 0x6B1C, 0x99F2, 0x6B1D, 0x99F3, 0x6B1E, 0x99F4, 0x6B1F, 0x99F5, 0x6B20, 0xC7B7, 0x6B21, 0xB4CE, 0x6B22, 0xBBB6, + 0x6B23, 0xD0C0, 0x6B24, 0xECA3, 0x6B25, 0x99F6, 0x6B26, 0x99F7, 0x6B27, 0xC5B7, 0x6B28, 0x99F8, 0x6B29, 0x99F9, 0x6B2A, 0x99FA, + 0x6B2B, 0x99FB, 0x6B2C, 0x99FC, 0x6B2D, 0x99FD, 0x6B2E, 0x99FE, 0x6B2F, 0x9A40, 0x6B30, 0x9A41, 0x6B31, 0x9A42, 0x6B32, 0xD3FB, + 0x6B33, 0x9A43, 0x6B34, 0x9A44, 0x6B35, 0x9A45, 0x6B36, 0x9A46, 0x6B37, 0xECA4, 0x6B38, 0x9A47, 0x6B39, 0xECA5, 0x6B3A, 0xC6DB, + 0x6B3B, 0x9A48, 0x6B3C, 0x9A49, 0x6B3D, 0x9A4A, 0x6B3E, 0xBFEE, 0x6B3F, 0x9A4B, 0x6B40, 0x9A4C, 0x6B41, 0x9A4D, 0x6B42, 0x9A4E, + 0x6B43, 0xECA6, 0x6B44, 0x9A4F, 0x6B45, 0x9A50, 0x6B46, 0xECA7, 0x6B47, 0xD0AA, 0x6B48, 0x9A51, 0x6B49, 0xC7B8, 0x6B4A, 0x9A52, + 0x6B4B, 0x9A53, 0x6B4C, 0xB8E8, 0x6B4D, 0x9A54, 0x6B4E, 0x9A55, 0x6B4F, 0x9A56, 0x6B50, 0x9A57, 0x6B51, 0x9A58, 0x6B52, 0x9A59, + 0x6B53, 0x9A5A, 0x6B54, 0x9A5B, 0x6B55, 0x9A5C, 0x6B56, 0x9A5D, 0x6B57, 0x9A5E, 0x6B58, 0x9A5F, 0x6B59, 0xECA8, 0x6B5A, 0x9A60, + 0x6B5B, 0x9A61, 0x6B5C, 0x9A62, 0x6B5D, 0x9A63, 0x6B5E, 0x9A64, 0x6B5F, 0x9A65, 0x6B60, 0x9A66, 0x6B61, 0x9A67, 0x6B62, 0xD6B9, + 0x6B63, 0xD5FD, 0x6B64, 0xB4CB, 0x6B65, 0xB2BD, 0x6B66, 0xCEE4, 0x6B67, 0xC6E7, 0x6B68, 0x9A68, 0x6B69, 0x9A69, 0x6B6A, 0xCDE1, + 0x6B6B, 0x9A6A, 0x6B6C, 0x9A6B, 0x6B6D, 0x9A6C, 0x6B6E, 0x9A6D, 0x6B6F, 0x9A6E, 0x6B70, 0x9A6F, 0x6B71, 0x9A70, 0x6B72, 0x9A71, + 0x6B73, 0x9A72, 0x6B74, 0x9A73, 0x6B75, 0x9A74, 0x6B76, 0x9A75, 0x6B77, 0x9A76, 0x6B78, 0x9A77, 0x6B79, 0xB4F5, 0x6B7A, 0x9A78, + 0x6B7B, 0xCBC0, 0x6B7C, 0xBCDF, 0x6B7D, 0x9A79, 0x6B7E, 0x9A7A, 0x6B7F, 0x9A7B, 0x6B80, 0x9A7C, 0x6B81, 0xE9E2, 0x6B82, 0xE9E3, + 0x6B83, 0xD1EA, 0x6B84, 0xE9E5, 0x6B85, 0x9A7D, 0x6B86, 0xB4F9, 0x6B87, 0xE9E4, 0x6B88, 0x9A7E, 0x6B89, 0xD1B3, 0x6B8A, 0xCAE2, + 0x6B8B, 0xB2D0, 0x6B8C, 0x9A80, 0x6B8D, 0xE9E8, 0x6B8E, 0x9A81, 0x6B8F, 0x9A82, 0x6B90, 0x9A83, 0x6B91, 0x9A84, 0x6B92, 0xE9E6, + 0x6B93, 0xE9E7, 0x6B94, 0x9A85, 0x6B95, 0x9A86, 0x6B96, 0xD6B3, 0x6B97, 0x9A87, 0x6B98, 0x9A88, 0x6B99, 0x9A89, 0x6B9A, 0xE9E9, + 0x6B9B, 0xE9EA, 0x6B9C, 0x9A8A, 0x6B9D, 0x9A8B, 0x6B9E, 0x9A8C, 0x6B9F, 0x9A8D, 0x6BA0, 0x9A8E, 0x6BA1, 0xE9EB, 0x6BA2, 0x9A8F, + 0x6BA3, 0x9A90, 0x6BA4, 0x9A91, 0x6BA5, 0x9A92, 0x6BA6, 0x9A93, 0x6BA7, 0x9A94, 0x6BA8, 0x9A95, 0x6BA9, 0x9A96, 0x6BAA, 0xE9EC, + 0x6BAB, 0x9A97, 0x6BAC, 0x9A98, 0x6BAD, 0x9A99, 0x6BAE, 0x9A9A, 0x6BAF, 0x9A9B, 0x6BB0, 0x9A9C, 0x6BB1, 0x9A9D, 0x6BB2, 0x9A9E, + 0x6BB3, 0xECAF, 0x6BB4, 0xC5B9, 0x6BB5, 0xB6CE, 0x6BB6, 0x9A9F, 0x6BB7, 0xD2F3, 0x6BB8, 0x9AA0, 0x6BB9, 0x9AA1, 0x6BBA, 0x9AA2, + 0x6BBB, 0x9AA3, 0x6BBC, 0x9AA4, 0x6BBD, 0x9AA5, 0x6BBE, 0x9AA6, 0x6BBF, 0xB5EE, 0x6BC0, 0x9AA7, 0x6BC1, 0xBBD9, 0x6BC2, 0xECB1, + 0x6BC3, 0x9AA8, 0x6BC4, 0x9AA9, 0x6BC5, 0xD2E3, 0x6BC6, 0x9AAA, 0x6BC7, 0x9AAB, 0x6BC8, 0x9AAC, 0x6BC9, 0x9AAD, 0x6BCA, 0x9AAE, + 0x6BCB, 0xCEE3, 0x6BCC, 0x9AAF, 0x6BCD, 0xC4B8, 0x6BCE, 0x9AB0, 0x6BCF, 0xC3BF, 0x6BD0, 0x9AB1, 0x6BD1, 0x9AB2, 0x6BD2, 0xB6BE, + 0x6BD3, 0xD8B9, 0x6BD4, 0xB1C8, 0x6BD5, 0xB1CF, 0x6BD6, 0xB1D1, 0x6BD7, 0xC5FE, 0x6BD8, 0x9AB3, 0x6BD9, 0xB1D0, 0x6BDA, 0x9AB4, + 0x6BDB, 0xC3AB, 0x6BDC, 0x9AB5, 0x6BDD, 0x9AB6, 0x6BDE, 0x9AB7, 0x6BDF, 0x9AB8, 0x6BE0, 0x9AB9, 0x6BE1, 0xD5B1, 0x6BE2, 0x9ABA, + 0x6BE3, 0x9ABB, 0x6BE4, 0x9ABC, 0x6BE5, 0x9ABD, 0x6BE6, 0x9ABE, 0x6BE7, 0x9ABF, 0x6BE8, 0x9AC0, 0x6BE9, 0x9AC1, 0x6BEA, 0xEBA4, + 0x6BEB, 0xBAC1, 0x6BEC, 0x9AC2, 0x6BED, 0x9AC3, 0x6BEE, 0x9AC4, 0x6BEF, 0xCCBA, 0x6BF0, 0x9AC5, 0x6BF1, 0x9AC6, 0x6BF2, 0x9AC7, + 0x6BF3, 0xEBA5, 0x6BF4, 0x9AC8, 0x6BF5, 0xEBA7, 0x6BF6, 0x9AC9, 0x6BF7, 0x9ACA, 0x6BF8, 0x9ACB, 0x6BF9, 0xEBA8, 0x6BFA, 0x9ACC, + 0x6BFB, 0x9ACD, 0x6BFC, 0x9ACE, 0x6BFD, 0xEBA6, 0x6BFE, 0x9ACF, 0x6BFF, 0x9AD0, 0x6C00, 0x9AD1, 0x6C01, 0x9AD2, 0x6C02, 0x9AD3, + 0x6C03, 0x9AD4, 0x6C04, 0x9AD5, 0x6C05, 0xEBA9, 0x6C06, 0xEBAB, 0x6C07, 0xEBAA, 0x6C08, 0x9AD6, 0x6C09, 0x9AD7, 0x6C0A, 0x9AD8, + 0x6C0B, 0x9AD9, 0x6C0C, 0x9ADA, 0x6C0D, 0xEBAC, 0x6C0E, 0x9ADB, 0x6C0F, 0xCACF, 0x6C10, 0xD8B5, 0x6C11, 0xC3F1, 0x6C12, 0x9ADC, + 0x6C13, 0xC3A5, 0x6C14, 0xC6F8, 0x6C15, 0xEBAD, 0x6C16, 0xC4CA, 0x6C17, 0x9ADD, 0x6C18, 0xEBAE, 0x6C19, 0xEBAF, 0x6C1A, 0xEBB0, + 0x6C1B, 0xB7D5, 0x6C1C, 0x9ADE, 0x6C1D, 0x9ADF, 0x6C1E, 0x9AE0, 0x6C1F, 0xB7FA, 0x6C20, 0x9AE1, 0x6C21, 0xEBB1, 0x6C22, 0xC7E2, + 0x6C23, 0x9AE2, 0x6C24, 0xEBB3, 0x6C25, 0x9AE3, 0x6C26, 0xBAA4, 0x6C27, 0xD1F5, 0x6C28, 0xB0B1, 0x6C29, 0xEBB2, 0x6C2A, 0xEBB4, + 0x6C2B, 0x9AE4, 0x6C2C, 0x9AE5, 0x6C2D, 0x9AE6, 0x6C2E, 0xB5AA, 0x6C2F, 0xC2C8, 0x6C30, 0xC7E8, 0x6C31, 0x9AE7, 0x6C32, 0xEBB5, + 0x6C33, 0x9AE8, 0x6C34, 0xCBAE, 0x6C35, 0xE3DF, 0x6C36, 0x9AE9, 0x6C37, 0x9AEA, 0x6C38, 0xD3C0, 0x6C39, 0x9AEB, 0x6C3A, 0x9AEC, + 0x6C3B, 0x9AED, 0x6C3C, 0x9AEE, 0x6C3D, 0xD9DB, 0x6C3E, 0x9AEF, 0x6C3F, 0x9AF0, 0x6C40, 0xCDA1, 0x6C41, 0xD6AD, 0x6C42, 0xC7F3, + 0x6C43, 0x9AF1, 0x6C44, 0x9AF2, 0x6C45, 0x9AF3, 0x6C46, 0xD9E0, 0x6C47, 0xBBE3, 0x6C48, 0x9AF4, 0x6C49, 0xBABA, 0x6C4A, 0xE3E2, + 0x6C4B, 0x9AF5, 0x6C4C, 0x9AF6, 0x6C4D, 0x9AF7, 0x6C4E, 0x9AF8, 0x6C4F, 0x9AF9, 0x6C50, 0xCFAB, 0x6C51, 0x9AFA, 0x6C52, 0x9AFB, + 0x6C53, 0x9AFC, 0x6C54, 0xE3E0, 0x6C55, 0xC9C7, 0x6C56, 0x9AFD, 0x6C57, 0xBAB9, 0x6C58, 0x9AFE, 0x6C59, 0x9B40, 0x6C5A, 0x9B41, + 0x6C5B, 0xD1B4, 0x6C5C, 0xE3E1, 0x6C5D, 0xC8EA, 0x6C5E, 0xB9AF, 0x6C5F, 0xBDAD, 0x6C60, 0xB3D8, 0x6C61, 0xCEDB, 0x6C62, 0x9B42, + 0x6C63, 0x9B43, 0x6C64, 0xCCC0, 0x6C65, 0x9B44, 0x6C66, 0x9B45, 0x6C67, 0x9B46, 0x6C68, 0xE3E8, 0x6C69, 0xE3E9, 0x6C6A, 0xCDF4, + 0x6C6B, 0x9B47, 0x6C6C, 0x9B48, 0x6C6D, 0x9B49, 0x6C6E, 0x9B4A, 0x6C6F, 0x9B4B, 0x6C70, 0xCCAD, 0x6C71, 0x9B4C, 0x6C72, 0xBCB3, + 0x6C73, 0x9B4D, 0x6C74, 0xE3EA, 0x6C75, 0x9B4E, 0x6C76, 0xE3EB, 0x6C77, 0x9B4F, 0x6C78, 0x9B50, 0x6C79, 0xD0DA, 0x6C7A, 0x9B51, + 0x6C7B, 0x9B52, 0x6C7C, 0x9B53, 0x6C7D, 0xC6FB, 0x6C7E, 0xB7DA, 0x6C7F, 0x9B54, 0x6C80, 0x9B55, 0x6C81, 0xC7DF, 0x6C82, 0xD2CA, + 0x6C83, 0xCED6, 0x6C84, 0x9B56, 0x6C85, 0xE3E4, 0x6C86, 0xE3EC, 0x6C87, 0x9B57, 0x6C88, 0xC9F2, 0x6C89, 0xB3C1, 0x6C8A, 0x9B58, + 0x6C8B, 0x9B59, 0x6C8C, 0xE3E7, 0x6C8D, 0x9B5A, 0x6C8E, 0x9B5B, 0x6C8F, 0xC6E3, 0x6C90, 0xE3E5, 0x6C91, 0x9B5C, 0x6C92, 0x9B5D, + 0x6C93, 0xEDB3, 0x6C94, 0xE3E6, 0x6C95, 0x9B5E, 0x6C96, 0x9B5F, 0x6C97, 0x9B60, 0x6C98, 0x9B61, 0x6C99, 0xC9B3, 0x6C9A, 0x9B62, + 0x6C9B, 0xC5E6, 0x6C9C, 0x9B63, 0x6C9D, 0x9B64, 0x6C9E, 0x9B65, 0x6C9F, 0xB9B5, 0x6CA0, 0x9B66, 0x6CA1, 0xC3BB, 0x6CA2, 0x9B67, + 0x6CA3, 0xE3E3, 0x6CA4, 0xC5BD, 0x6CA5, 0xC1A4, 0x6CA6, 0xC2D9, 0x6CA7, 0xB2D7, 0x6CA8, 0x9B68, 0x6CA9, 0xE3ED, 0x6CAA, 0xBBA6, + 0x6CAB, 0xC4AD, 0x6CAC, 0x9B69, 0x6CAD, 0xE3F0, 0x6CAE, 0xBEDA, 0x6CAF, 0x9B6A, 0x6CB0, 0x9B6B, 0x6CB1, 0xE3FB, 0x6CB2, 0xE3F5, + 0x6CB3, 0xBAD3, 0x6CB4, 0x9B6C, 0x6CB5, 0x9B6D, 0x6CB6, 0x9B6E, 0x6CB7, 0x9B6F, 0x6CB8, 0xB7D0, 0x6CB9, 0xD3CD, 0x6CBA, 0x9B70, + 0x6CBB, 0xD6CE, 0x6CBC, 0xD5D3, 0x6CBD, 0xB9C1, 0x6CBE, 0xD5B4, 0x6CBF, 0xD1D8, 0x6CC0, 0x9B71, 0x6CC1, 0x9B72, 0x6CC2, 0x9B73, + 0x6CC3, 0x9B74, 0x6CC4, 0xD0B9, 0x6CC5, 0xC7F6, 0x6CC6, 0x9B75, 0x6CC7, 0x9B76, 0x6CC8, 0x9B77, 0x6CC9, 0xC8AA, 0x6CCA, 0xB2B4, + 0x6CCB, 0x9B78, 0x6CCC, 0xC3DA, 0x6CCD, 0x9B79, 0x6CCE, 0x9B7A, 0x6CCF, 0x9B7B, 0x6CD0, 0xE3EE, 0x6CD1, 0x9B7C, 0x6CD2, 0x9B7D, + 0x6CD3, 0xE3FC, 0x6CD4, 0xE3EF, 0x6CD5, 0xB7A8, 0x6CD6, 0xE3F7, 0x6CD7, 0xE3F4, 0x6CD8, 0x9B7E, 0x6CD9, 0x9B80, 0x6CDA, 0x9B81, + 0x6CDB, 0xB7BA, 0x6CDC, 0x9B82, 0x6CDD, 0x9B83, 0x6CDE, 0xC5A2, 0x6CDF, 0x9B84, 0x6CE0, 0xE3F6, 0x6CE1, 0xC5DD, 0x6CE2, 0xB2A8, + 0x6CE3, 0xC6FC, 0x6CE4, 0x9B85, 0x6CE5, 0xC4E0, 0x6CE6, 0x9B86, 0x6CE7, 0x9B87, 0x6CE8, 0xD7A2, 0x6CE9, 0x9B88, 0x6CEA, 0xC0E1, + 0x6CEB, 0xE3F9, 0x6CEC, 0x9B89, 0x6CED, 0x9B8A, 0x6CEE, 0xE3FA, 0x6CEF, 0xE3FD, 0x6CF0, 0xCCA9, 0x6CF1, 0xE3F3, 0x6CF2, 0x9B8B, + 0x6CF3, 0xD3BE, 0x6CF4, 0x9B8C, 0x6CF5, 0xB1C3, 0x6CF6, 0xEDB4, 0x6CF7, 0xE3F1, 0x6CF8, 0xE3F2, 0x6CF9, 0x9B8D, 0x6CFA, 0xE3F8, + 0x6CFB, 0xD0BA, 0x6CFC, 0xC6C3, 0x6CFD, 0xD4F3, 0x6CFE, 0xE3FE, 0x6CFF, 0x9B8E, 0x6D00, 0x9B8F, 0x6D01, 0xBDE0, 0x6D02, 0x9B90, + 0x6D03, 0x9B91, 0x6D04, 0xE4A7, 0x6D05, 0x9B92, 0x6D06, 0x9B93, 0x6D07, 0xE4A6, 0x6D08, 0x9B94, 0x6D09, 0x9B95, 0x6D0A, 0x9B96, + 0x6D0B, 0xD1F3, 0x6D0C, 0xE4A3, 0x6D0D, 0x9B97, 0x6D0E, 0xE4A9, 0x6D0F, 0x9B98, 0x6D10, 0x9B99, 0x6D11, 0x9B9A, 0x6D12, 0xC8F7, + 0x6D13, 0x9B9B, 0x6D14, 0x9B9C, 0x6D15, 0x9B9D, 0x6D16, 0x9B9E, 0x6D17, 0xCFB4, 0x6D18, 0x9B9F, 0x6D19, 0xE4A8, 0x6D1A, 0xE4AE, + 0x6D1B, 0xC2E5, 0x6D1C, 0x9BA0, 0x6D1D, 0x9BA1, 0x6D1E, 0xB6B4, 0x6D1F, 0x9BA2, 0x6D20, 0x9BA3, 0x6D21, 0x9BA4, 0x6D22, 0x9BA5, + 0x6D23, 0x9BA6, 0x6D24, 0x9BA7, 0x6D25, 0xBDF2, 0x6D26, 0x9BA8, 0x6D27, 0xE4A2, 0x6D28, 0x9BA9, 0x6D29, 0x9BAA, 0x6D2A, 0xBAE9, + 0x6D2B, 0xE4AA, 0x6D2C, 0x9BAB, 0x6D2D, 0x9BAC, 0x6D2E, 0xE4AC, 0x6D2F, 0x9BAD, 0x6D30, 0x9BAE, 0x6D31, 0xB6FD, 0x6D32, 0xD6DE, + 0x6D33, 0xE4B2, 0x6D34, 0x9BAF, 0x6D35, 0xE4AD, 0x6D36, 0x9BB0, 0x6D37, 0x9BB1, 0x6D38, 0x9BB2, 0x6D39, 0xE4A1, 0x6D3A, 0x9BB3, + 0x6D3B, 0xBBEE, 0x6D3C, 0xCDDD, 0x6D3D, 0xC7A2, 0x6D3E, 0xC5C9, 0x6D3F, 0x9BB4, 0x6D40, 0x9BB5, 0x6D41, 0xC1F7, 0x6D42, 0x9BB6, + 0x6D43, 0xE4A4, 0x6D44, 0x9BB7, 0x6D45, 0xC7B3, 0x6D46, 0xBDAC, 0x6D47, 0xBDBD, 0x6D48, 0xE4A5, 0x6D49, 0x9BB8, 0x6D4A, 0xD7C7, + 0x6D4B, 0xB2E2, 0x6D4C, 0x9BB9, 0x6D4D, 0xE4AB, 0x6D4E, 0xBCC3, 0x6D4F, 0xE4AF, 0x6D50, 0x9BBA, 0x6D51, 0xBBEB, 0x6D52, 0xE4B0, + 0x6D53, 0xC5A8, 0x6D54, 0xE4B1, 0x6D55, 0x9BBB, 0x6D56, 0x9BBC, 0x6D57, 0x9BBD, 0x6D58, 0x9BBE, 0x6D59, 0xD5E3, 0x6D5A, 0xBFA3, + 0x6D5B, 0x9BBF, 0x6D5C, 0xE4BA, 0x6D5D, 0x9BC0, 0x6D5E, 0xE4B7, 0x6D5F, 0x9BC1, 0x6D60, 0xE4BB, 0x6D61, 0x9BC2, 0x6D62, 0x9BC3, + 0x6D63, 0xE4BD, 0x6D64, 0x9BC4, 0x6D65, 0x9BC5, 0x6D66, 0xC6D6, 0x6D67, 0x9BC6, 0x6D68, 0x9BC7, 0x6D69, 0xBAC6, 0x6D6A, 0xC0CB, + 0x6D6B, 0x9BC8, 0x6D6C, 0x9BC9, 0x6D6D, 0x9BCA, 0x6D6E, 0xB8A1, 0x6D6F, 0xE4B4, 0x6D70, 0x9BCB, 0x6D71, 0x9BCC, 0x6D72, 0x9BCD, + 0x6D73, 0x9BCE, 0x6D74, 0xD4A1, 0x6D75, 0x9BCF, 0x6D76, 0x9BD0, 0x6D77, 0xBAA3, 0x6D78, 0xBDFE, 0x6D79, 0x9BD1, 0x6D7A, 0x9BD2, + 0x6D7B, 0x9BD3, 0x6D7C, 0xE4BC, 0x6D7D, 0x9BD4, 0x6D7E, 0x9BD5, 0x6D7F, 0x9BD6, 0x6D80, 0x9BD7, 0x6D81, 0x9BD8, 0x6D82, 0xCDBF, + 0x6D83, 0x9BD9, 0x6D84, 0x9BDA, 0x6D85, 0xC4F9, 0x6D86, 0x9BDB, 0x6D87, 0x9BDC, 0x6D88, 0xCFFB, 0x6D89, 0xC9E6, 0x6D8A, 0x9BDD, + 0x6D8B, 0x9BDE, 0x6D8C, 0xD3BF, 0x6D8D, 0x9BDF, 0x6D8E, 0xCFD1, 0x6D8F, 0x9BE0, 0x6D90, 0x9BE1, 0x6D91, 0xE4B3, 0x6D92, 0x9BE2, + 0x6D93, 0xE4B8, 0x6D94, 0xE4B9, 0x6D95, 0xCCE9, 0x6D96, 0x9BE3, 0x6D97, 0x9BE4, 0x6D98, 0x9BE5, 0x6D99, 0x9BE6, 0x6D9A, 0x9BE7, + 0x6D9B, 0xCCCE, 0x6D9C, 0x9BE8, 0x6D9D, 0xC0D4, 0x6D9E, 0xE4B5, 0x6D9F, 0xC1B0, 0x6DA0, 0xE4B6, 0x6DA1, 0xCED0, 0x6DA2, 0x9BE9, + 0x6DA3, 0xBBC1, 0x6DA4, 0xB5D3, 0x6DA5, 0x9BEA, 0x6DA6, 0xC8F3, 0x6DA7, 0xBDA7, 0x6DA8, 0xD5C7, 0x6DA9, 0xC9AC, 0x6DAA, 0xB8A2, + 0x6DAB, 0xE4CA, 0x6DAC, 0x9BEB, 0x6DAD, 0x9BEC, 0x6DAE, 0xE4CC, 0x6DAF, 0xD1C4, 0x6DB0, 0x9BED, 0x6DB1, 0x9BEE, 0x6DB2, 0xD2BA, + 0x6DB3, 0x9BEF, 0x6DB4, 0x9BF0, 0x6DB5, 0xBAAD, 0x6DB6, 0x9BF1, 0x6DB7, 0x9BF2, 0x6DB8, 0xBAD4, 0x6DB9, 0x9BF3, 0x6DBA, 0x9BF4, + 0x6DBB, 0x9BF5, 0x6DBC, 0x9BF6, 0x6DBD, 0x9BF7, 0x6DBE, 0x9BF8, 0x6DBF, 0xE4C3, 0x6DC0, 0xB5ED, 0x6DC1, 0x9BF9, 0x6DC2, 0x9BFA, + 0x6DC3, 0x9BFB, 0x6DC4, 0xD7CD, 0x6DC5, 0xE4C0, 0x6DC6, 0xCFFD, 0x6DC7, 0xE4BF, 0x6DC8, 0x9BFC, 0x6DC9, 0x9BFD, 0x6DCA, 0x9BFE, + 0x6DCB, 0xC1DC, 0x6DCC, 0xCCCA, 0x6DCD, 0x9C40, 0x6DCE, 0x9C41, 0x6DCF, 0x9C42, 0x6DD0, 0x9C43, 0x6DD1, 0xCAE7, 0x6DD2, 0x9C44, + 0x6DD3, 0x9C45, 0x6DD4, 0x9C46, 0x6DD5, 0x9C47, 0x6DD6, 0xC4D7, 0x6DD7, 0x9C48, 0x6DD8, 0xCCD4, 0x6DD9, 0xE4C8, 0x6DDA, 0x9C49, + 0x6DDB, 0x9C4A, 0x6DDC, 0x9C4B, 0x6DDD, 0xE4C7, 0x6DDE, 0xE4C1, 0x6DDF, 0x9C4C, 0x6DE0, 0xE4C4, 0x6DE1, 0xB5AD, 0x6DE2, 0x9C4D, + 0x6DE3, 0x9C4E, 0x6DE4, 0xD3D9, 0x6DE5, 0x9C4F, 0x6DE6, 0xE4C6, 0x6DE7, 0x9C50, 0x6DE8, 0x9C51, 0x6DE9, 0x9C52, 0x6DEA, 0x9C53, + 0x6DEB, 0xD2F9, 0x6DEC, 0xB4E3, 0x6DED, 0x9C54, 0x6DEE, 0xBBB4, 0x6DEF, 0x9C55, 0x6DF0, 0x9C56, 0x6DF1, 0xC9EE, 0x6DF2, 0x9C57, + 0x6DF3, 0xB4BE, 0x6DF4, 0x9C58, 0x6DF5, 0x9C59, 0x6DF6, 0x9C5A, 0x6DF7, 0xBBEC, 0x6DF8, 0x9C5B, 0x6DF9, 0xD1CD, 0x6DFA, 0x9C5C, + 0x6DFB, 0xCCED, 0x6DFC, 0xEDB5, 0x6DFD, 0x9C5D, 0x6DFE, 0x9C5E, 0x6DFF, 0x9C5F, 0x6E00, 0x9C60, 0x6E01, 0x9C61, 0x6E02, 0x9C62, + 0x6E03, 0x9C63, 0x6E04, 0x9C64, 0x6E05, 0xC7E5, 0x6E06, 0x9C65, 0x6E07, 0x9C66, 0x6E08, 0x9C67, 0x6E09, 0x9C68, 0x6E0A, 0xD4A8, + 0x6E0B, 0x9C69, 0x6E0C, 0xE4CB, 0x6E0D, 0xD7D5, 0x6E0E, 0xE4C2, 0x6E0F, 0x9C6A, 0x6E10, 0xBDA5, 0x6E11, 0xE4C5, 0x6E12, 0x9C6B, + 0x6E13, 0x9C6C, 0x6E14, 0xD3E6, 0x6E15, 0x9C6D, 0x6E16, 0xE4C9, 0x6E17, 0xC9F8, 0x6E18, 0x9C6E, 0x6E19, 0x9C6F, 0x6E1A, 0xE4BE, + 0x6E1B, 0x9C70, 0x6E1C, 0x9C71, 0x6E1D, 0xD3E5, 0x6E1E, 0x9C72, 0x6E1F, 0x9C73, 0x6E20, 0xC7FE, 0x6E21, 0xB6C9, 0x6E22, 0x9C74, + 0x6E23, 0xD4FC, 0x6E24, 0xB2B3, 0x6E25, 0xE4D7, 0x6E26, 0x9C75, 0x6E27, 0x9C76, 0x6E28, 0x9C77, 0x6E29, 0xCEC2, 0x6E2A, 0x9C78, + 0x6E2B, 0xE4CD, 0x6E2C, 0x9C79, 0x6E2D, 0xCEBC, 0x6E2E, 0x9C7A, 0x6E2F, 0xB8DB, 0x6E30, 0x9C7B, 0x6E31, 0x9C7C, 0x6E32, 0xE4D6, + 0x6E33, 0x9C7D, 0x6E34, 0xBFCA, 0x6E35, 0x9C7E, 0x6E36, 0x9C80, 0x6E37, 0x9C81, 0x6E38, 0xD3CE, 0x6E39, 0x9C82, 0x6E3A, 0xC3EC, + 0x6E3B, 0x9C83, 0x6E3C, 0x9C84, 0x6E3D, 0x9C85, 0x6E3E, 0x9C86, 0x6E3F, 0x9C87, 0x6E40, 0x9C88, 0x6E41, 0x9C89, 0x6E42, 0x9C8A, + 0x6E43, 0xC5C8, 0x6E44, 0xE4D8, 0x6E45, 0x9C8B, 0x6E46, 0x9C8C, 0x6E47, 0x9C8D, 0x6E48, 0x9C8E, 0x6E49, 0x9C8F, 0x6E4A, 0x9C90, + 0x6E4B, 0x9C91, 0x6E4C, 0x9C92, 0x6E4D, 0xCDC4, 0x6E4E, 0xE4CF, 0x6E4F, 0x9C93, 0x6E50, 0x9C94, 0x6E51, 0x9C95, 0x6E52, 0x9C96, + 0x6E53, 0xE4D4, 0x6E54, 0xE4D5, 0x6E55, 0x9C97, 0x6E56, 0xBAFE, 0x6E57, 0x9C98, 0x6E58, 0xCFE6, 0x6E59, 0x9C99, 0x6E5A, 0x9C9A, + 0x6E5B, 0xD5BF, 0x6E5C, 0x9C9B, 0x6E5D, 0x9C9C, 0x6E5E, 0x9C9D, 0x6E5F, 0xE4D2, 0x6E60, 0x9C9E, 0x6E61, 0x9C9F, 0x6E62, 0x9CA0, + 0x6E63, 0x9CA1, 0x6E64, 0x9CA2, 0x6E65, 0x9CA3, 0x6E66, 0x9CA4, 0x6E67, 0x9CA5, 0x6E68, 0x9CA6, 0x6E69, 0x9CA7, 0x6E6A, 0x9CA8, + 0x6E6B, 0xE4D0, 0x6E6C, 0x9CA9, 0x6E6D, 0x9CAA, 0x6E6E, 0xE4CE, 0x6E6F, 0x9CAB, 0x6E70, 0x9CAC, 0x6E71, 0x9CAD, 0x6E72, 0x9CAE, + 0x6E73, 0x9CAF, 0x6E74, 0x9CB0, 0x6E75, 0x9CB1, 0x6E76, 0x9CB2, 0x6E77, 0x9CB3, 0x6E78, 0x9CB4, 0x6E79, 0x9CB5, 0x6E7A, 0x9CB6, + 0x6E7B, 0x9CB7, 0x6E7C, 0x9CB8, 0x6E7D, 0x9CB9, 0x6E7E, 0xCDE5, 0x6E7F, 0xCAAA, 0x6E80, 0x9CBA, 0x6E81, 0x9CBB, 0x6E82, 0x9CBC, + 0x6E83, 0xC0A3, 0x6E84, 0x9CBD, 0x6E85, 0xBDA6, 0x6E86, 0xE4D3, 0x6E87, 0x9CBE, 0x6E88, 0x9CBF, 0x6E89, 0xB8C8, 0x6E8A, 0x9CC0, + 0x6E8B, 0x9CC1, 0x6E8C, 0x9CC2, 0x6E8D, 0x9CC3, 0x6E8E, 0x9CC4, 0x6E8F, 0xE4E7, 0x6E90, 0xD4B4, 0x6E91, 0x9CC5, 0x6E92, 0x9CC6, + 0x6E93, 0x9CC7, 0x6E94, 0x9CC8, 0x6E95, 0x9CC9, 0x6E96, 0x9CCA, 0x6E97, 0x9CCB, 0x6E98, 0xE4DB, 0x6E99, 0x9CCC, 0x6E9A, 0x9CCD, + 0x6E9B, 0x9CCE, 0x6E9C, 0xC1EF, 0x6E9D, 0x9CCF, 0x6E9E, 0x9CD0, 0x6E9F, 0xE4E9, 0x6EA0, 0x9CD1, 0x6EA1, 0x9CD2, 0x6EA2, 0xD2E7, + 0x6EA3, 0x9CD3, 0x6EA4, 0x9CD4, 0x6EA5, 0xE4DF, 0x6EA6, 0x9CD5, 0x6EA7, 0xE4E0, 0x6EA8, 0x9CD6, 0x6EA9, 0x9CD7, 0x6EAA, 0xCFAA, + 0x6EAB, 0x9CD8, 0x6EAC, 0x9CD9, 0x6EAD, 0x9CDA, 0x6EAE, 0x9CDB, 0x6EAF, 0xCBDD, 0x6EB0, 0x9CDC, 0x6EB1, 0xE4DA, 0x6EB2, 0xE4D1, + 0x6EB3, 0x9CDD, 0x6EB4, 0xE4E5, 0x6EB5, 0x9CDE, 0x6EB6, 0xC8DC, 0x6EB7, 0xE4E3, 0x6EB8, 0x9CDF, 0x6EB9, 0x9CE0, 0x6EBA, 0xC4E7, + 0x6EBB, 0xE4E2, 0x6EBC, 0x9CE1, 0x6EBD, 0xE4E1, 0x6EBE, 0x9CE2, 0x6EBF, 0x9CE3, 0x6EC0, 0x9CE4, 0x6EC1, 0xB3FC, 0x6EC2, 0xE4E8, + 0x6EC3, 0x9CE5, 0x6EC4, 0x9CE6, 0x6EC5, 0x9CE7, 0x6EC6, 0x9CE8, 0x6EC7, 0xB5E1, 0x6EC8, 0x9CE9, 0x6EC9, 0x9CEA, 0x6ECA, 0x9CEB, + 0x6ECB, 0xD7CC, 0x6ECC, 0x9CEC, 0x6ECD, 0x9CED, 0x6ECE, 0x9CEE, 0x6ECF, 0xE4E6, 0x6ED0, 0x9CEF, 0x6ED1, 0xBBAC, 0x6ED2, 0x9CF0, + 0x6ED3, 0xD7D2, 0x6ED4, 0xCCCF, 0x6ED5, 0xEBF8, 0x6ED6, 0x9CF1, 0x6ED7, 0xE4E4, 0x6ED8, 0x9CF2, 0x6ED9, 0x9CF3, 0x6EDA, 0xB9F6, + 0x6EDB, 0x9CF4, 0x6EDC, 0x9CF5, 0x6EDD, 0x9CF6, 0x6EDE, 0xD6CD, 0x6EDF, 0xE4D9, 0x6EE0, 0xE4DC, 0x6EE1, 0xC2FA, 0x6EE2, 0xE4DE, + 0x6EE3, 0x9CF7, 0x6EE4, 0xC2CB, 0x6EE5, 0xC0C4, 0x6EE6, 0xC2D0, 0x6EE7, 0x9CF8, 0x6EE8, 0xB1F5, 0x6EE9, 0xCCB2, 0x6EEA, 0x9CF9, + 0x6EEB, 0x9CFA, 0x6EEC, 0x9CFB, 0x6EED, 0x9CFC, 0x6EEE, 0x9CFD, 0x6EEF, 0x9CFE, 0x6EF0, 0x9D40, 0x6EF1, 0x9D41, 0x6EF2, 0x9D42, + 0x6EF3, 0x9D43, 0x6EF4, 0xB5CE, 0x6EF5, 0x9D44, 0x6EF6, 0x9D45, 0x6EF7, 0x9D46, 0x6EF8, 0x9D47, 0x6EF9, 0xE4EF, 0x6EFA, 0x9D48, + 0x6EFB, 0x9D49, 0x6EFC, 0x9D4A, 0x6EFD, 0x9D4B, 0x6EFE, 0x9D4C, 0x6EFF, 0x9D4D, 0x6F00, 0x9D4E, 0x6F01, 0x9D4F, 0x6F02, 0xC6AF, + 0x6F03, 0x9D50, 0x6F04, 0x9D51, 0x6F05, 0x9D52, 0x6F06, 0xC6E1, 0x6F07, 0x9D53, 0x6F08, 0x9D54, 0x6F09, 0xE4F5, 0x6F0A, 0x9D55, + 0x6F0B, 0x9D56, 0x6F0C, 0x9D57, 0x6F0D, 0x9D58, 0x6F0E, 0x9D59, 0x6F0F, 0xC2A9, 0x6F10, 0x9D5A, 0x6F11, 0x9D5B, 0x6F12, 0x9D5C, + 0x6F13, 0xC0EC, 0x6F14, 0xD1DD, 0x6F15, 0xE4EE, 0x6F16, 0x9D5D, 0x6F17, 0x9D5E, 0x6F18, 0x9D5F, 0x6F19, 0x9D60, 0x6F1A, 0x9D61, + 0x6F1B, 0x9D62, 0x6F1C, 0x9D63, 0x6F1D, 0x9D64, 0x6F1E, 0x9D65, 0x6F1F, 0x9D66, 0x6F20, 0xC4AE, 0x6F21, 0x9D67, 0x6F22, 0x9D68, + 0x6F23, 0x9D69, 0x6F24, 0xE4ED, 0x6F25, 0x9D6A, 0x6F26, 0x9D6B, 0x6F27, 0x9D6C, 0x6F28, 0x9D6D, 0x6F29, 0xE4F6, 0x6F2A, 0xE4F4, + 0x6F2B, 0xC2FE, 0x6F2C, 0x9D6E, 0x6F2D, 0xE4DD, 0x6F2E, 0x9D6F, 0x6F2F, 0xE4F0, 0x6F30, 0x9D70, 0x6F31, 0xCAFE, 0x6F32, 0x9D71, + 0x6F33, 0xD5C4, 0x6F34, 0x9D72, 0x6F35, 0x9D73, 0x6F36, 0xE4F1, 0x6F37, 0x9D74, 0x6F38, 0x9D75, 0x6F39, 0x9D76, 0x6F3A, 0x9D77, + 0x6F3B, 0x9D78, 0x6F3C, 0x9D79, 0x6F3D, 0x9D7A, 0x6F3E, 0xD1FA, 0x6F3F, 0x9D7B, 0x6F40, 0x9D7C, 0x6F41, 0x9D7D, 0x6F42, 0x9D7E, + 0x6F43, 0x9D80, 0x6F44, 0x9D81, 0x6F45, 0x9D82, 0x6F46, 0xE4EB, 0x6F47, 0xE4EC, 0x6F48, 0x9D83, 0x6F49, 0x9D84, 0x6F4A, 0x9D85, + 0x6F4B, 0xE4F2, 0x6F4C, 0x9D86, 0x6F4D, 0xCEAB, 0x6F4E, 0x9D87, 0x6F4F, 0x9D88, 0x6F50, 0x9D89, 0x6F51, 0x9D8A, 0x6F52, 0x9D8B, + 0x6F53, 0x9D8C, 0x6F54, 0x9D8D, 0x6F55, 0x9D8E, 0x6F56, 0x9D8F, 0x6F57, 0x9D90, 0x6F58, 0xC5CB, 0x6F59, 0x9D91, 0x6F5A, 0x9D92, + 0x6F5B, 0x9D93, 0x6F5C, 0xC7B1, 0x6F5D, 0x9D94, 0x6F5E, 0xC2BA, 0x6F5F, 0x9D95, 0x6F60, 0x9D96, 0x6F61, 0x9D97, 0x6F62, 0xE4EA, + 0x6F63, 0x9D98, 0x6F64, 0x9D99, 0x6F65, 0x9D9A, 0x6F66, 0xC1CA, 0x6F67, 0x9D9B, 0x6F68, 0x9D9C, 0x6F69, 0x9D9D, 0x6F6A, 0x9D9E, + 0x6F6B, 0x9D9F, 0x6F6C, 0x9DA0, 0x6F6D, 0xCCB6, 0x6F6E, 0xB3B1, 0x6F6F, 0x9DA1, 0x6F70, 0x9DA2, 0x6F71, 0x9DA3, 0x6F72, 0xE4FB, + 0x6F73, 0x9DA4, 0x6F74, 0xE4F3, 0x6F75, 0x9DA5, 0x6F76, 0x9DA6, 0x6F77, 0x9DA7, 0x6F78, 0xE4FA, 0x6F79, 0x9DA8, 0x6F7A, 0xE4FD, + 0x6F7B, 0x9DA9, 0x6F7C, 0xE4FC, 0x6F7D, 0x9DAA, 0x6F7E, 0x9DAB, 0x6F7F, 0x9DAC, 0x6F80, 0x9DAD, 0x6F81, 0x9DAE, 0x6F82, 0x9DAF, + 0x6F83, 0x9DB0, 0x6F84, 0xB3CE, 0x6F85, 0x9DB1, 0x6F86, 0x9DB2, 0x6F87, 0x9DB3, 0x6F88, 0xB3BA, 0x6F89, 0xE4F7, 0x6F8A, 0x9DB4, + 0x6F8B, 0x9DB5, 0x6F8C, 0xE4F9, 0x6F8D, 0xE4F8, 0x6F8E, 0xC5EC, 0x6F8F, 0x9DB6, 0x6F90, 0x9DB7, 0x6F91, 0x9DB8, 0x6F92, 0x9DB9, + 0x6F93, 0x9DBA, 0x6F94, 0x9DBB, 0x6F95, 0x9DBC, 0x6F96, 0x9DBD, 0x6F97, 0x9DBE, 0x6F98, 0x9DBF, 0x6F99, 0x9DC0, 0x6F9A, 0x9DC1, + 0x6F9B, 0x9DC2, 0x6F9C, 0xC0BD, 0x6F9D, 0x9DC3, 0x6F9E, 0x9DC4, 0x6F9F, 0x9DC5, 0x6FA0, 0x9DC6, 0x6FA1, 0xD4E8, 0x6FA2, 0x9DC7, + 0x6FA3, 0x9DC8, 0x6FA4, 0x9DC9, 0x6FA5, 0x9DCA, 0x6FA6, 0x9DCB, 0x6FA7, 0xE5A2, 0x6FA8, 0x9DCC, 0x6FA9, 0x9DCD, 0x6FAA, 0x9DCE, + 0x6FAB, 0x9DCF, 0x6FAC, 0x9DD0, 0x6FAD, 0x9DD1, 0x6FAE, 0x9DD2, 0x6FAF, 0x9DD3, 0x6FB0, 0x9DD4, 0x6FB1, 0x9DD5, 0x6FB2, 0x9DD6, + 0x6FB3, 0xB0C4, 0x6FB4, 0x9DD7, 0x6FB5, 0x9DD8, 0x6FB6, 0xE5A4, 0x6FB7, 0x9DD9, 0x6FB8, 0x9DDA, 0x6FB9, 0xE5A3, 0x6FBA, 0x9DDB, + 0x6FBB, 0x9DDC, 0x6FBC, 0x9DDD, 0x6FBD, 0x9DDE, 0x6FBE, 0x9DDF, 0x6FBF, 0x9DE0, 0x6FC0, 0xBCA4, 0x6FC1, 0x9DE1, 0x6FC2, 0xE5A5, + 0x6FC3, 0x9DE2, 0x6FC4, 0x9DE3, 0x6FC5, 0x9DE4, 0x6FC6, 0x9DE5, 0x6FC7, 0x9DE6, 0x6FC8, 0x9DE7, 0x6FC9, 0xE5A1, 0x6FCA, 0x9DE8, + 0x6FCB, 0x9DE9, 0x6FCC, 0x9DEA, 0x6FCD, 0x9DEB, 0x6FCE, 0x9DEC, 0x6FCF, 0x9DED, 0x6FD0, 0x9DEE, 0x6FD1, 0xE4FE, 0x6FD2, 0xB1F4, + 0x6FD3, 0x9DEF, 0x6FD4, 0x9DF0, 0x6FD5, 0x9DF1, 0x6FD6, 0x9DF2, 0x6FD7, 0x9DF3, 0x6FD8, 0x9DF4, 0x6FD9, 0x9DF5, 0x6FDA, 0x9DF6, + 0x6FDB, 0x9DF7, 0x6FDC, 0x9DF8, 0x6FDD, 0x9DF9, 0x6FDE, 0xE5A8, 0x6FDF, 0x9DFA, 0x6FE0, 0xE5A9, 0x6FE1, 0xE5A6, 0x6FE2, 0x9DFB, + 0x6FE3, 0x9DFC, 0x6FE4, 0x9DFD, 0x6FE5, 0x9DFE, 0x6FE6, 0x9E40, 0x6FE7, 0x9E41, 0x6FE8, 0x9E42, 0x6FE9, 0x9E43, 0x6FEA, 0x9E44, + 0x6FEB, 0x9E45, 0x6FEC, 0x9E46, 0x6FED, 0x9E47, 0x6FEE, 0xE5A7, 0x6FEF, 0xE5AA, 0x6FF0, 0x9E48, 0x6FF1, 0x9E49, 0x6FF2, 0x9E4A, + 0x6FF3, 0x9E4B, 0x6FF4, 0x9E4C, 0x6FF5, 0x9E4D, 0x6FF6, 0x9E4E, 0x6FF7, 0x9E4F, 0x6FF8, 0x9E50, 0x6FF9, 0x9E51, 0x6FFA, 0x9E52, + 0x6FFB, 0x9E53, 0x6FFC, 0x9E54, 0x6FFD, 0x9E55, 0x6FFE, 0x9E56, 0x6FFF, 0x9E57, 0x7000, 0x9E58, 0x7001, 0x9E59, 0x7002, 0x9E5A, + 0x7003, 0x9E5B, 0x7004, 0x9E5C, 0x7005, 0x9E5D, 0x7006, 0x9E5E, 0x7007, 0x9E5F, 0x7008, 0x9E60, 0x7009, 0x9E61, 0x700A, 0x9E62, + 0x700B, 0x9E63, 0x700C, 0x9E64, 0x700D, 0x9E65, 0x700E, 0x9E66, 0x700F, 0x9E67, 0x7010, 0x9E68, 0x7011, 0xC6D9, 0x7012, 0x9E69, + 0x7013, 0x9E6A, 0x7014, 0x9E6B, 0x7015, 0x9E6C, 0x7016, 0x9E6D, 0x7017, 0x9E6E, 0x7018, 0x9E6F, 0x7019, 0x9E70, 0x701A, 0xE5AB, + 0x701B, 0xE5AD, 0x701C, 0x9E71, 0x701D, 0x9E72, 0x701E, 0x9E73, 0x701F, 0x9E74, 0x7020, 0x9E75, 0x7021, 0x9E76, 0x7022, 0x9E77, + 0x7023, 0xE5AC, 0x7024, 0x9E78, 0x7025, 0x9E79, 0x7026, 0x9E7A, 0x7027, 0x9E7B, 0x7028, 0x9E7C, 0x7029, 0x9E7D, 0x702A, 0x9E7E, + 0x702B, 0x9E80, 0x702C, 0x9E81, 0x702D, 0x9E82, 0x702E, 0x9E83, 0x702F, 0x9E84, 0x7030, 0x9E85, 0x7031, 0x9E86, 0x7032, 0x9E87, + 0x7033, 0x9E88, 0x7034, 0x9E89, 0x7035, 0xE5AF, 0x7036, 0x9E8A, 0x7037, 0x9E8B, 0x7038, 0x9E8C, 0x7039, 0xE5AE, 0x703A, 0x9E8D, + 0x703B, 0x9E8E, 0x703C, 0x9E8F, 0x703D, 0x9E90, 0x703E, 0x9E91, 0x703F, 0x9E92, 0x7040, 0x9E93, 0x7041, 0x9E94, 0x7042, 0x9E95, + 0x7043, 0x9E96, 0x7044, 0x9E97, 0x7045, 0x9E98, 0x7046, 0x9E99, 0x7047, 0x9E9A, 0x7048, 0x9E9B, 0x7049, 0x9E9C, 0x704A, 0x9E9D, + 0x704B, 0x9E9E, 0x704C, 0xB9E0, 0x704D, 0x9E9F, 0x704E, 0x9EA0, 0x704F, 0xE5B0, 0x7050, 0x9EA1, 0x7051, 0x9EA2, 0x7052, 0x9EA3, + 0x7053, 0x9EA4, 0x7054, 0x9EA5, 0x7055, 0x9EA6, 0x7056, 0x9EA7, 0x7057, 0x9EA8, 0x7058, 0x9EA9, 0x7059, 0x9EAA, 0x705A, 0x9EAB, + 0x705B, 0x9EAC, 0x705C, 0x9EAD, 0x705D, 0x9EAE, 0x705E, 0xE5B1, 0x705F, 0x9EAF, 0x7060, 0x9EB0, 0x7061, 0x9EB1, 0x7062, 0x9EB2, + 0x7063, 0x9EB3, 0x7064, 0x9EB4, 0x7065, 0x9EB5, 0x7066, 0x9EB6, 0x7067, 0x9EB7, 0x7068, 0x9EB8, 0x7069, 0x9EB9, 0x706A, 0x9EBA, + 0x706B, 0xBBF0, 0x706C, 0xECE1, 0x706D, 0xC3F0, 0x706E, 0x9EBB, 0x706F, 0xB5C6, 0x7070, 0xBBD2, 0x7071, 0x9EBC, 0x7072, 0x9EBD, + 0x7073, 0x9EBE, 0x7074, 0x9EBF, 0x7075, 0xC1E9, 0x7076, 0xD4EE, 0x7077, 0x9EC0, 0x7078, 0xBEC4, 0x7079, 0x9EC1, 0x707A, 0x9EC2, + 0x707B, 0x9EC3, 0x707C, 0xD7C6, 0x707D, 0x9EC4, 0x707E, 0xD4D6, 0x707F, 0xB2D3, 0x7080, 0xECBE, 0x7081, 0x9EC5, 0x7082, 0x9EC6, + 0x7083, 0x9EC7, 0x7084, 0x9EC8, 0x7085, 0xEAC1, 0x7086, 0x9EC9, 0x7087, 0x9ECA, 0x7088, 0x9ECB, 0x7089, 0xC2AF, 0x708A, 0xB4B6, + 0x708B, 0x9ECC, 0x708C, 0x9ECD, 0x708D, 0x9ECE, 0x708E, 0xD1D7, 0x708F, 0x9ECF, 0x7090, 0x9ED0, 0x7091, 0x9ED1, 0x7092, 0xB3B4, + 0x7093, 0x9ED2, 0x7094, 0xC8B2, 0x7095, 0xBFBB, 0x7096, 0xECC0, 0x7097, 0x9ED3, 0x7098, 0x9ED4, 0x7099, 0xD6CB, 0x709A, 0x9ED5, + 0x709B, 0x9ED6, 0x709C, 0xECBF, 0x709D, 0xECC1, 0x709E, 0x9ED7, 0x709F, 0x9ED8, 0x70A0, 0x9ED9, 0x70A1, 0x9EDA, 0x70A2, 0x9EDB, + 0x70A3, 0x9EDC, 0x70A4, 0x9EDD, 0x70A5, 0x9EDE, 0x70A6, 0x9EDF, 0x70A7, 0x9EE0, 0x70A8, 0x9EE1, 0x70A9, 0x9EE2, 0x70AA, 0x9EE3, + 0x70AB, 0xECC5, 0x70AC, 0xBEE6, 0x70AD, 0xCCBF, 0x70AE, 0xC5DA, 0x70AF, 0xBEBC, 0x70B0, 0x9EE4, 0x70B1, 0xECC6, 0x70B2, 0x9EE5, + 0x70B3, 0xB1FE, 0x70B4, 0x9EE6, 0x70B5, 0x9EE7, 0x70B6, 0x9EE8, 0x70B7, 0xECC4, 0x70B8, 0xD5A8, 0x70B9, 0xB5E3, 0x70BA, 0x9EE9, + 0x70BB, 0xECC2, 0x70BC, 0xC1B6, 0x70BD, 0xB3E3, 0x70BE, 0x9EEA, 0x70BF, 0x9EEB, 0x70C0, 0xECC3, 0x70C1, 0xCBB8, 0x70C2, 0xC0C3, + 0x70C3, 0xCCFE, 0x70C4, 0x9EEC, 0x70C5, 0x9EED, 0x70C6, 0x9EEE, 0x70C7, 0x9EEF, 0x70C8, 0xC1D2, 0x70C9, 0x9EF0, 0x70CA, 0xECC8, + 0x70CB, 0x9EF1, 0x70CC, 0x9EF2, 0x70CD, 0x9EF3, 0x70CE, 0x9EF4, 0x70CF, 0x9EF5, 0x70D0, 0x9EF6, 0x70D1, 0x9EF7, 0x70D2, 0x9EF8, + 0x70D3, 0x9EF9, 0x70D4, 0x9EFA, 0x70D5, 0x9EFB, 0x70D6, 0x9EFC, 0x70D7, 0x9EFD, 0x70D8, 0xBAE6, 0x70D9, 0xC0D3, 0x70DA, 0x9EFE, + 0x70DB, 0xD6F2, 0x70DC, 0x9F40, 0x70DD, 0x9F41, 0x70DE, 0x9F42, 0x70DF, 0xD1CC, 0x70E0, 0x9F43, 0x70E1, 0x9F44, 0x70E2, 0x9F45, + 0x70E3, 0x9F46, 0x70E4, 0xBFBE, 0x70E5, 0x9F47, 0x70E6, 0xB7B3, 0x70E7, 0xC9D5, 0x70E8, 0xECC7, 0x70E9, 0xBBE2, 0x70EA, 0x9F48, + 0x70EB, 0xCCCC, 0x70EC, 0xBDFD, 0x70ED, 0xC8C8, 0x70EE, 0x9F49, 0x70EF, 0xCFA9, 0x70F0, 0x9F4A, 0x70F1, 0x9F4B, 0x70F2, 0x9F4C, + 0x70F3, 0x9F4D, 0x70F4, 0x9F4E, 0x70F5, 0x9F4F, 0x70F6, 0x9F50, 0x70F7, 0xCDE9, 0x70F8, 0x9F51, 0x70F9, 0xC5EB, 0x70FA, 0x9F52, + 0x70FB, 0x9F53, 0x70FC, 0x9F54, 0x70FD, 0xB7E9, 0x70FE, 0x9F55, 0x70FF, 0x9F56, 0x7100, 0x9F57, 0x7101, 0x9F58, 0x7102, 0x9F59, + 0x7103, 0x9F5A, 0x7104, 0x9F5B, 0x7105, 0x9F5C, 0x7106, 0x9F5D, 0x7107, 0x9F5E, 0x7108, 0x9F5F, 0x7109, 0xD1C9, 0x710A, 0xBAB8, + 0x710B, 0x9F60, 0x710C, 0x9F61, 0x710D, 0x9F62, 0x710E, 0x9F63, 0x710F, 0x9F64, 0x7110, 0xECC9, 0x7111, 0x9F65, 0x7112, 0x9F66, + 0x7113, 0xECCA, 0x7114, 0x9F67, 0x7115, 0xBBC0, 0x7116, 0xECCB, 0x7117, 0x9F68, 0x7118, 0xECE2, 0x7119, 0xB1BA, 0x711A, 0xB7D9, + 0x711B, 0x9F69, 0x711C, 0x9F6A, 0x711D, 0x9F6B, 0x711E, 0x9F6C, 0x711F, 0x9F6D, 0x7120, 0x9F6E, 0x7121, 0x9F6F, 0x7122, 0x9F70, + 0x7123, 0x9F71, 0x7124, 0x9F72, 0x7125, 0x9F73, 0x7126, 0xBDB9, 0x7127, 0x9F74, 0x7128, 0x9F75, 0x7129, 0x9F76, 0x712A, 0x9F77, + 0x712B, 0x9F78, 0x712C, 0x9F79, 0x712D, 0x9F7A, 0x712E, 0x9F7B, 0x712F, 0xECCC, 0x7130, 0xD1E6, 0x7131, 0xECCD, 0x7132, 0x9F7C, + 0x7133, 0x9F7D, 0x7134, 0x9F7E, 0x7135, 0x9F80, 0x7136, 0xC8BB, 0x7137, 0x9F81, 0x7138, 0x9F82, 0x7139, 0x9F83, 0x713A, 0x9F84, + 0x713B, 0x9F85, 0x713C, 0x9F86, 0x713D, 0x9F87, 0x713E, 0x9F88, 0x713F, 0x9F89, 0x7140, 0x9F8A, 0x7141, 0x9F8B, 0x7142, 0x9F8C, + 0x7143, 0x9F8D, 0x7144, 0x9F8E, 0x7145, 0xECD1, 0x7146, 0x9F8F, 0x7147, 0x9F90, 0x7148, 0x9F91, 0x7149, 0x9F92, 0x714A, 0xECD3, + 0x714B, 0x9F93, 0x714C, 0xBBCD, 0x714D, 0x9F94, 0x714E, 0xBCE5, 0x714F, 0x9F95, 0x7150, 0x9F96, 0x7151, 0x9F97, 0x7152, 0x9F98, + 0x7153, 0x9F99, 0x7154, 0x9F9A, 0x7155, 0x9F9B, 0x7156, 0x9F9C, 0x7157, 0x9F9D, 0x7158, 0x9F9E, 0x7159, 0x9F9F, 0x715A, 0x9FA0, + 0x715B, 0x9FA1, 0x715C, 0xECCF, 0x715D, 0x9FA2, 0x715E, 0xC9B7, 0x715F, 0x9FA3, 0x7160, 0x9FA4, 0x7161, 0x9FA5, 0x7162, 0x9FA6, + 0x7163, 0x9FA7, 0x7164, 0xC3BA, 0x7165, 0x9FA8, 0x7166, 0xECE3, 0x7167, 0xD5D5, 0x7168, 0xECD0, 0x7169, 0x9FA9, 0x716A, 0x9FAA, + 0x716B, 0x9FAB, 0x716C, 0x9FAC, 0x716D, 0x9FAD, 0x716E, 0xD6F3, 0x716F, 0x9FAE, 0x7170, 0x9FAF, 0x7171, 0x9FB0, 0x7172, 0xECD2, + 0x7173, 0xECCE, 0x7174, 0x9FB1, 0x7175, 0x9FB2, 0x7176, 0x9FB3, 0x7177, 0x9FB4, 0x7178, 0xECD4, 0x7179, 0x9FB5, 0x717A, 0xECD5, + 0x717B, 0x9FB6, 0x717C, 0x9FB7, 0x717D, 0xC9BF, 0x717E, 0x9FB8, 0x717F, 0x9FB9, 0x7180, 0x9FBA, 0x7181, 0x9FBB, 0x7182, 0x9FBC, + 0x7183, 0x9FBD, 0x7184, 0xCFA8, 0x7185, 0x9FBE, 0x7186, 0x9FBF, 0x7187, 0x9FC0, 0x7188, 0x9FC1, 0x7189, 0x9FC2, 0x718A, 0xD0DC, + 0x718B, 0x9FC3, 0x718C, 0x9FC4, 0x718D, 0x9FC5, 0x718E, 0x9FC6, 0x718F, 0xD1AC, 0x7190, 0x9FC7, 0x7191, 0x9FC8, 0x7192, 0x9FC9, + 0x7193, 0x9FCA, 0x7194, 0xC8DB, 0x7195, 0x9FCB, 0x7196, 0x9FCC, 0x7197, 0x9FCD, 0x7198, 0xECD6, 0x7199, 0xCEF5, 0x719A, 0x9FCE, + 0x719B, 0x9FCF, 0x719C, 0x9FD0, 0x719D, 0x9FD1, 0x719E, 0x9FD2, 0x719F, 0xCAEC, 0x71A0, 0xECDA, 0x71A1, 0x9FD3, 0x71A2, 0x9FD4, + 0x71A3, 0x9FD5, 0x71A4, 0x9FD6, 0x71A5, 0x9FD7, 0x71A6, 0x9FD8, 0x71A7, 0x9FD9, 0x71A8, 0xECD9, 0x71A9, 0x9FDA, 0x71AA, 0x9FDB, + 0x71AB, 0x9FDC, 0x71AC, 0xB0BE, 0x71AD, 0x9FDD, 0x71AE, 0x9FDE, 0x71AF, 0x9FDF, 0x71B0, 0x9FE0, 0x71B1, 0x9FE1, 0x71B2, 0x9FE2, + 0x71B3, 0xECD7, 0x71B4, 0x9FE3, 0x71B5, 0xECD8, 0x71B6, 0x9FE4, 0x71B7, 0x9FE5, 0x71B8, 0x9FE6, 0x71B9, 0xECE4, 0x71BA, 0x9FE7, + 0x71BB, 0x9FE8, 0x71BC, 0x9FE9, 0x71BD, 0x9FEA, 0x71BE, 0x9FEB, 0x71BF, 0x9FEC, 0x71C0, 0x9FED, 0x71C1, 0x9FEE, 0x71C2, 0x9FEF, + 0x71C3, 0xC8BC, 0x71C4, 0x9FF0, 0x71C5, 0x9FF1, 0x71C6, 0x9FF2, 0x71C7, 0x9FF3, 0x71C8, 0x9FF4, 0x71C9, 0x9FF5, 0x71CA, 0x9FF6, + 0x71CB, 0x9FF7, 0x71CC, 0x9FF8, 0x71CD, 0x9FF9, 0x71CE, 0xC1C7, 0x71CF, 0x9FFA, 0x71D0, 0x9FFB, 0x71D1, 0x9FFC, 0x71D2, 0x9FFD, + 0x71D3, 0x9FFE, 0x71D4, 0xECDC, 0x71D5, 0xD1E0, 0x71D6, 0xA040, 0x71D7, 0xA041, 0x71D8, 0xA042, 0x71D9, 0xA043, 0x71DA, 0xA044, + 0x71DB, 0xA045, 0x71DC, 0xA046, 0x71DD, 0xA047, 0x71DE, 0xA048, 0x71DF, 0xA049, 0x71E0, 0xECDB, 0x71E1, 0xA04A, 0x71E2, 0xA04B, + 0x71E3, 0xA04C, 0x71E4, 0xA04D, 0x71E5, 0xD4EF, 0x71E6, 0xA04E, 0x71E7, 0xECDD, 0x71E8, 0xA04F, 0x71E9, 0xA050, 0x71EA, 0xA051, + 0x71EB, 0xA052, 0x71EC, 0xA053, 0x71ED, 0xA054, 0x71EE, 0xDBC6, 0x71EF, 0xA055, 0x71F0, 0xA056, 0x71F1, 0xA057, 0x71F2, 0xA058, + 0x71F3, 0xA059, 0x71F4, 0xA05A, 0x71F5, 0xA05B, 0x71F6, 0xA05C, 0x71F7, 0xA05D, 0x71F8, 0xA05E, 0x71F9, 0xECDE, 0x71FA, 0xA05F, + 0x71FB, 0xA060, 0x71FC, 0xA061, 0x71FD, 0xA062, 0x71FE, 0xA063, 0x71FF, 0xA064, 0x7200, 0xA065, 0x7201, 0xA066, 0x7202, 0xA067, + 0x7203, 0xA068, 0x7204, 0xA069, 0x7205, 0xA06A, 0x7206, 0xB1AC, 0x7207, 0xA06B, 0x7208, 0xA06C, 0x7209, 0xA06D, 0x720A, 0xA06E, + 0x720B, 0xA06F, 0x720C, 0xA070, 0x720D, 0xA071, 0x720E, 0xA072, 0x720F, 0xA073, 0x7210, 0xA074, 0x7211, 0xA075, 0x7212, 0xA076, + 0x7213, 0xA077, 0x7214, 0xA078, 0x7215, 0xA079, 0x7216, 0xA07A, 0x7217, 0xA07B, 0x7218, 0xA07C, 0x7219, 0xA07D, 0x721A, 0xA07E, + 0x721B, 0xA080, 0x721C, 0xA081, 0x721D, 0xECDF, 0x721E, 0xA082, 0x721F, 0xA083, 0x7220, 0xA084, 0x7221, 0xA085, 0x7222, 0xA086, + 0x7223, 0xA087, 0x7224, 0xA088, 0x7225, 0xA089, 0x7226, 0xA08A, 0x7227, 0xA08B, 0x7228, 0xECE0, 0x7229, 0xA08C, 0x722A, 0xD7A6, + 0x722B, 0xA08D, 0x722C, 0xC5C0, 0x722D, 0xA08E, 0x722E, 0xA08F, 0x722F, 0xA090, 0x7230, 0xEBBC, 0x7231, 0xB0AE, 0x7232, 0xA091, + 0x7233, 0xA092, 0x7234, 0xA093, 0x7235, 0xBEF4, 0x7236, 0xB8B8, 0x7237, 0xD2AF, 0x7238, 0xB0D6, 0x7239, 0xB5F9, 0x723A, 0xA094, + 0x723B, 0xD8B3, 0x723C, 0xA095, 0x723D, 0xCBAC, 0x723E, 0xA096, 0x723F, 0xE3DD, 0x7240, 0xA097, 0x7241, 0xA098, 0x7242, 0xA099, + 0x7243, 0xA09A, 0x7244, 0xA09B, 0x7245, 0xA09C, 0x7246, 0xA09D, 0x7247, 0xC6AC, 0x7248, 0xB0E6, 0x7249, 0xA09E, 0x724A, 0xA09F, + 0x724B, 0xA0A0, 0x724C, 0xC5C6, 0x724D, 0xEBB9, 0x724E, 0xA0A1, 0x724F, 0xA0A2, 0x7250, 0xA0A3, 0x7251, 0xA0A4, 0x7252, 0xEBBA, + 0x7253, 0xA0A5, 0x7254, 0xA0A6, 0x7255, 0xA0A7, 0x7256, 0xEBBB, 0x7257, 0xA0A8, 0x7258, 0xA0A9, 0x7259, 0xD1C0, 0x725A, 0xA0AA, + 0x725B, 0xC5A3, 0x725C, 0xA0AB, 0x725D, 0xEAF2, 0x725E, 0xA0AC, 0x725F, 0xC4B2, 0x7260, 0xA0AD, 0x7261, 0xC4B5, 0x7262, 0xC0CE, + 0x7263, 0xA0AE, 0x7264, 0xA0AF, 0x7265, 0xA0B0, 0x7266, 0xEAF3, 0x7267, 0xC4C1, 0x7268, 0xA0B1, 0x7269, 0xCEEF, 0x726A, 0xA0B2, + 0x726B, 0xA0B3, 0x726C, 0xA0B4, 0x726D, 0xA0B5, 0x726E, 0xEAF0, 0x726F, 0xEAF4, 0x7270, 0xA0B6, 0x7271, 0xA0B7, 0x7272, 0xC9FC, + 0x7273, 0xA0B8, 0x7274, 0xA0B9, 0x7275, 0xC7A3, 0x7276, 0xA0BA, 0x7277, 0xA0BB, 0x7278, 0xA0BC, 0x7279, 0xCCD8, 0x727A, 0xCEFE, + 0x727B, 0xA0BD, 0x727C, 0xA0BE, 0x727D, 0xA0BF, 0x727E, 0xEAF5, 0x727F, 0xEAF6, 0x7280, 0xCFAC, 0x7281, 0xC0E7, 0x7282, 0xA0C0, + 0x7283, 0xA0C1, 0x7284, 0xEAF7, 0x7285, 0xA0C2, 0x7286, 0xA0C3, 0x7287, 0xA0C4, 0x7288, 0xA0C5, 0x7289, 0xA0C6, 0x728A, 0xB6BF, + 0x728B, 0xEAF8, 0x728C, 0xA0C7, 0x728D, 0xEAF9, 0x728E, 0xA0C8, 0x728F, 0xEAFA, 0x7290, 0xA0C9, 0x7291, 0xA0CA, 0x7292, 0xEAFB, + 0x7293, 0xA0CB, 0x7294, 0xA0CC, 0x7295, 0xA0CD, 0x7296, 0xA0CE, 0x7297, 0xA0CF, 0x7298, 0xA0D0, 0x7299, 0xA0D1, 0x729A, 0xA0D2, + 0x729B, 0xA0D3, 0x729C, 0xA0D4, 0x729D, 0xA0D5, 0x729E, 0xA0D6, 0x729F, 0xEAF1, 0x72A0, 0xA0D7, 0x72A1, 0xA0D8, 0x72A2, 0xA0D9, + 0x72A3, 0xA0DA, 0x72A4, 0xA0DB, 0x72A5, 0xA0DC, 0x72A6, 0xA0DD, 0x72A7, 0xA0DE, 0x72A8, 0xA0DF, 0x72A9, 0xA0E0, 0x72AA, 0xA0E1, + 0x72AB, 0xA0E2, 0x72AC, 0xC8AE, 0x72AD, 0xE1EB, 0x72AE, 0xA0E3, 0x72AF, 0xB7B8, 0x72B0, 0xE1EC, 0x72B1, 0xA0E4, 0x72B2, 0xA0E5, + 0x72B3, 0xA0E6, 0x72B4, 0xE1ED, 0x72B5, 0xA0E7, 0x72B6, 0xD7B4, 0x72B7, 0xE1EE, 0x72B8, 0xE1EF, 0x72B9, 0xD3CC, 0x72BA, 0xA0E8, + 0x72BB, 0xA0E9, 0x72BC, 0xA0EA, 0x72BD, 0xA0EB, 0x72BE, 0xA0EC, 0x72BF, 0xA0ED, 0x72C0, 0xA0EE, 0x72C1, 0xE1F1, 0x72C2, 0xBFF1, + 0x72C3, 0xE1F0, 0x72C4, 0xB5D2, 0x72C5, 0xA0EF, 0x72C6, 0xA0F0, 0x72C7, 0xA0F1, 0x72C8, 0xB1B7, 0x72C9, 0xA0F2, 0x72CA, 0xA0F3, + 0x72CB, 0xA0F4, 0x72CC, 0xA0F5, 0x72CD, 0xE1F3, 0x72CE, 0xE1F2, 0x72CF, 0xA0F6, 0x72D0, 0xBAFC, 0x72D1, 0xA0F7, 0x72D2, 0xE1F4, + 0x72D3, 0xA0F8, 0x72D4, 0xA0F9, 0x72D5, 0xA0FA, 0x72D6, 0xA0FB, 0x72D7, 0xB9B7, 0x72D8, 0xA0FC, 0x72D9, 0xBED1, 0x72DA, 0xA0FD, + 0x72DB, 0xA0FE, 0x72DC, 0xAA40, 0x72DD, 0xAA41, 0x72DE, 0xC4FC, 0x72DF, 0xAA42, 0x72E0, 0xBADD, 0x72E1, 0xBDC6, 0x72E2, 0xAA43, + 0x72E3, 0xAA44, 0x72E4, 0xAA45, 0x72E5, 0xAA46, 0x72E6, 0xAA47, 0x72E7, 0xAA48, 0x72E8, 0xE1F5, 0x72E9, 0xE1F7, 0x72EA, 0xAA49, + 0x72EB, 0xAA4A, 0x72EC, 0xB6C0, 0x72ED, 0xCFC1, 0x72EE, 0xCAA8, 0x72EF, 0xE1F6, 0x72F0, 0xD5F8, 0x72F1, 0xD3FC, 0x72F2, 0xE1F8, + 0x72F3, 0xE1FC, 0x72F4, 0xE1F9, 0x72F5, 0xAA4B, 0x72F6, 0xAA4C, 0x72F7, 0xE1FA, 0x72F8, 0xC0EA, 0x72F9, 0xAA4D, 0x72FA, 0xE1FE, + 0x72FB, 0xE2A1, 0x72FC, 0xC0C7, 0x72FD, 0xAA4E, 0x72FE, 0xAA4F, 0x72FF, 0xAA50, 0x7300, 0xAA51, 0x7301, 0xE1FB, 0x7302, 0xAA52, + 0x7303, 0xE1FD, 0x7304, 0xAA53, 0x7305, 0xAA54, 0x7306, 0xAA55, 0x7307, 0xAA56, 0x7308, 0xAA57, 0x7309, 0xAA58, 0x730A, 0xE2A5, + 0x730B, 0xAA59, 0x730C, 0xAA5A, 0x730D, 0xAA5B, 0x730E, 0xC1D4, 0x730F, 0xAA5C, 0x7310, 0xAA5D, 0x7311, 0xAA5E, 0x7312, 0xAA5F, + 0x7313, 0xE2A3, 0x7314, 0xAA60, 0x7315, 0xE2A8, 0x7316, 0xB2FE, 0x7317, 0xE2A2, 0x7318, 0xAA61, 0x7319, 0xAA62, 0x731A, 0xAA63, + 0x731B, 0xC3CD, 0x731C, 0xB2C2, 0x731D, 0xE2A7, 0x731E, 0xE2A6, 0x731F, 0xAA64, 0x7320, 0xAA65, 0x7321, 0xE2A4, 0x7322, 0xE2A9, + 0x7323, 0xAA66, 0x7324, 0xAA67, 0x7325, 0xE2AB, 0x7326, 0xAA68, 0x7327, 0xAA69, 0x7328, 0xAA6A, 0x7329, 0xD0C9, 0x732A, 0xD6ED, + 0x732B, 0xC3A8, 0x732C, 0xE2AC, 0x732D, 0xAA6B, 0x732E, 0xCFD7, 0x732F, 0xAA6C, 0x7330, 0xAA6D, 0x7331, 0xE2AE, 0x7332, 0xAA6E, + 0x7333, 0xAA6F, 0x7334, 0xBAEF, 0x7335, 0xAA70, 0x7336, 0xAA71, 0x7337, 0xE9E0, 0x7338, 0xE2AD, 0x7339, 0xE2AA, 0x733A, 0xAA72, + 0x733B, 0xAA73, 0x733C, 0xAA74, 0x733D, 0xAA75, 0x733E, 0xBBAB, 0x733F, 0xD4B3, 0x7340, 0xAA76, 0x7341, 0xAA77, 0x7342, 0xAA78, + 0x7343, 0xAA79, 0x7344, 0xAA7A, 0x7345, 0xAA7B, 0x7346, 0xAA7C, 0x7347, 0xAA7D, 0x7348, 0xAA7E, 0x7349, 0xAA80, 0x734A, 0xAA81, + 0x734B, 0xAA82, 0x734C, 0xAA83, 0x734D, 0xE2B0, 0x734E, 0xAA84, 0x734F, 0xAA85, 0x7350, 0xE2AF, 0x7351, 0xAA86, 0x7352, 0xE9E1, + 0x7353, 0xAA87, 0x7354, 0xAA88, 0x7355, 0xAA89, 0x7356, 0xAA8A, 0x7357, 0xE2B1, 0x7358, 0xAA8B, 0x7359, 0xAA8C, 0x735A, 0xAA8D, + 0x735B, 0xAA8E, 0x735C, 0xAA8F, 0x735D, 0xAA90, 0x735E, 0xAA91, 0x735F, 0xAA92, 0x7360, 0xE2B2, 0x7361, 0xAA93, 0x7362, 0xAA94, + 0x7363, 0xAA95, 0x7364, 0xAA96, 0x7365, 0xAA97, 0x7366, 0xAA98, 0x7367, 0xAA99, 0x7368, 0xAA9A, 0x7369, 0xAA9B, 0x736A, 0xAA9C, + 0x736B, 0xAA9D, 0x736C, 0xE2B3, 0x736D, 0xCCA1, 0x736E, 0xAA9E, 0x736F, 0xE2B4, 0x7370, 0xAA9F, 0x7371, 0xAAA0, 0x7372, 0xAB40, + 0x7373, 0xAB41, 0x7374, 0xAB42, 0x7375, 0xAB43, 0x7376, 0xAB44, 0x7377, 0xAB45, 0x7378, 0xAB46, 0x7379, 0xAB47, 0x737A, 0xAB48, + 0x737B, 0xAB49, 0x737C, 0xAB4A, 0x737D, 0xAB4B, 0x737E, 0xE2B5, 0x737F, 0xAB4C, 0x7380, 0xAB4D, 0x7381, 0xAB4E, 0x7382, 0xAB4F, + 0x7383, 0xAB50, 0x7384, 0xD0FE, 0x7385, 0xAB51, 0x7386, 0xAB52, 0x7387, 0xC2CA, 0x7388, 0xAB53, 0x7389, 0xD3F1, 0x738A, 0xAB54, + 0x738B, 0xCDF5, 0x738C, 0xAB55, 0x738D, 0xAB56, 0x738E, 0xE7E0, 0x738F, 0xAB57, 0x7390, 0xAB58, 0x7391, 0xE7E1, 0x7392, 0xAB59, + 0x7393, 0xAB5A, 0x7394, 0xAB5B, 0x7395, 0xAB5C, 0x7396, 0xBEC1, 0x7397, 0xAB5D, 0x7398, 0xAB5E, 0x7399, 0xAB5F, 0x739A, 0xAB60, + 0x739B, 0xC2EA, 0x739C, 0xAB61, 0x739D, 0xAB62, 0x739E, 0xAB63, 0x739F, 0xE7E4, 0x73A0, 0xAB64, 0x73A1, 0xAB65, 0x73A2, 0xE7E3, + 0x73A3, 0xAB66, 0x73A4, 0xAB67, 0x73A5, 0xAB68, 0x73A6, 0xAB69, 0x73A7, 0xAB6A, 0x73A8, 0xAB6B, 0x73A9, 0xCDE6, 0x73AA, 0xAB6C, + 0x73AB, 0xC3B5, 0x73AC, 0xAB6D, 0x73AD, 0xAB6E, 0x73AE, 0xE7E2, 0x73AF, 0xBBB7, 0x73B0, 0xCFD6, 0x73B1, 0xAB6F, 0x73B2, 0xC1E1, + 0x73B3, 0xE7E9, 0x73B4, 0xAB70, 0x73B5, 0xAB71, 0x73B6, 0xAB72, 0x73B7, 0xE7E8, 0x73B8, 0xAB73, 0x73B9, 0xAB74, 0x73BA, 0xE7F4, + 0x73BB, 0xB2A3, 0x73BC, 0xAB75, 0x73BD, 0xAB76, 0x73BE, 0xAB77, 0x73BF, 0xAB78, 0x73C0, 0xE7EA, 0x73C1, 0xAB79, 0x73C2, 0xE7E6, + 0x73C3, 0xAB7A, 0x73C4, 0xAB7B, 0x73C5, 0xAB7C, 0x73C6, 0xAB7D, 0x73C7, 0xAB7E, 0x73C8, 0xE7EC, 0x73C9, 0xE7EB, 0x73CA, 0xC9BA, + 0x73CB, 0xAB80, 0x73CC, 0xAB81, 0x73CD, 0xD5E4, 0x73CE, 0xAB82, 0x73CF, 0xE7E5, 0x73D0, 0xB7A9, 0x73D1, 0xE7E7, 0x73D2, 0xAB83, + 0x73D3, 0xAB84, 0x73D4, 0xAB85, 0x73D5, 0xAB86, 0x73D6, 0xAB87, 0x73D7, 0xAB88, 0x73D8, 0xAB89, 0x73D9, 0xE7EE, 0x73DA, 0xAB8A, + 0x73DB, 0xAB8B, 0x73DC, 0xAB8C, 0x73DD, 0xAB8D, 0x73DE, 0xE7F3, 0x73DF, 0xAB8E, 0x73E0, 0xD6E9, 0x73E1, 0xAB8F, 0x73E2, 0xAB90, + 0x73E3, 0xAB91, 0x73E4, 0xAB92, 0x73E5, 0xE7ED, 0x73E6, 0xAB93, 0x73E7, 0xE7F2, 0x73E8, 0xAB94, 0x73E9, 0xE7F1, 0x73EA, 0xAB95, + 0x73EB, 0xAB96, 0x73EC, 0xAB97, 0x73ED, 0xB0E0, 0x73EE, 0xAB98, 0x73EF, 0xAB99, 0x73F0, 0xAB9A, 0x73F1, 0xAB9B, 0x73F2, 0xE7F5, + 0x73F3, 0xAB9C, 0x73F4, 0xAB9D, 0x73F5, 0xAB9E, 0x73F6, 0xAB9F, 0x73F7, 0xABA0, 0x73F8, 0xAC40, 0x73F9, 0xAC41, 0x73FA, 0xAC42, + 0x73FB, 0xAC43, 0x73FC, 0xAC44, 0x73FD, 0xAC45, 0x73FE, 0xAC46, 0x73FF, 0xAC47, 0x7400, 0xAC48, 0x7401, 0xAC49, 0x7402, 0xAC4A, + 0x7403, 0xC7F2, 0x7404, 0xAC4B, 0x7405, 0xC0C5, 0x7406, 0xC0ED, 0x7407, 0xAC4C, 0x7408, 0xAC4D, 0x7409, 0xC1F0, 0x740A, 0xE7F0, + 0x740B, 0xAC4E, 0x740C, 0xAC4F, 0x740D, 0xAC50, 0x740E, 0xAC51, 0x740F, 0xE7F6, 0x7410, 0xCBF6, 0x7411, 0xAC52, 0x7412, 0xAC53, + 0x7413, 0xAC54, 0x7414, 0xAC55, 0x7415, 0xAC56, 0x7416, 0xAC57, 0x7417, 0xAC58, 0x7418, 0xAC59, 0x7419, 0xAC5A, 0x741A, 0xE8A2, + 0x741B, 0xE8A1, 0x741C, 0xAC5B, 0x741D, 0xAC5C, 0x741E, 0xAC5D, 0x741F, 0xAC5E, 0x7420, 0xAC5F, 0x7421, 0xAC60, 0x7422, 0xD7C1, + 0x7423, 0xAC61, 0x7424, 0xAC62, 0x7425, 0xE7FA, 0x7426, 0xE7F9, 0x7427, 0xAC63, 0x7428, 0xE7FB, 0x7429, 0xAC64, 0x742A, 0xE7F7, + 0x742B, 0xAC65, 0x742C, 0xE7FE, 0x742D, 0xAC66, 0x742E, 0xE7FD, 0x742F, 0xAC67, 0x7430, 0xE7FC, 0x7431, 0xAC68, 0x7432, 0xAC69, + 0x7433, 0xC1D5, 0x7434, 0xC7D9, 0x7435, 0xC5FD, 0x7436, 0xC5C3, 0x7437, 0xAC6A, 0x7438, 0xAC6B, 0x7439, 0xAC6C, 0x743A, 0xAC6D, + 0x743B, 0xAC6E, 0x743C, 0xC7ED, 0x743D, 0xAC6F, 0x743E, 0xAC70, 0x743F, 0xAC71, 0x7440, 0xAC72, 0x7441, 0xE8A3, 0x7442, 0xAC73, + 0x7443, 0xAC74, 0x7444, 0xAC75, 0x7445, 0xAC76, 0x7446, 0xAC77, 0x7447, 0xAC78, 0x7448, 0xAC79, 0x7449, 0xAC7A, 0x744A, 0xAC7B, + 0x744B, 0xAC7C, 0x744C, 0xAC7D, 0x744D, 0xAC7E, 0x744E, 0xAC80, 0x744F, 0xAC81, 0x7450, 0xAC82, 0x7451, 0xAC83, 0x7452, 0xAC84, + 0x7453, 0xAC85, 0x7454, 0xAC86, 0x7455, 0xE8A6, 0x7456, 0xAC87, 0x7457, 0xE8A5, 0x7458, 0xAC88, 0x7459, 0xE8A7, 0x745A, 0xBAF7, + 0x745B, 0xE7F8, 0x745C, 0xE8A4, 0x745D, 0xAC89, 0x745E, 0xC8F0, 0x745F, 0xC9AA, 0x7460, 0xAC8A, 0x7461, 0xAC8B, 0x7462, 0xAC8C, + 0x7463, 0xAC8D, 0x7464, 0xAC8E, 0x7465, 0xAC8F, 0x7466, 0xAC90, 0x7467, 0xAC91, 0x7468, 0xAC92, 0x7469, 0xAC93, 0x746A, 0xAC94, + 0x746B, 0xAC95, 0x746C, 0xAC96, 0x746D, 0xE8A9, 0x746E, 0xAC97, 0x746F, 0xAC98, 0x7470, 0xB9E5, 0x7471, 0xAC99, 0x7472, 0xAC9A, + 0x7473, 0xAC9B, 0x7474, 0xAC9C, 0x7475, 0xAC9D, 0x7476, 0xD1FE, 0x7477, 0xE8A8, 0x7478, 0xAC9E, 0x7479, 0xAC9F, 0x747A, 0xACA0, + 0x747B, 0xAD40, 0x747C, 0xAD41, 0x747D, 0xAD42, 0x747E, 0xE8AA, 0x747F, 0xAD43, 0x7480, 0xE8AD, 0x7481, 0xE8AE, 0x7482, 0xAD44, + 0x7483, 0xC1A7, 0x7484, 0xAD45, 0x7485, 0xAD46, 0x7486, 0xAD47, 0x7487, 0xE8AF, 0x7488, 0xAD48, 0x7489, 0xAD49, 0x748A, 0xAD4A, + 0x748B, 0xE8B0, 0x748C, 0xAD4B, 0x748D, 0xAD4C, 0x748E, 0xE8AC, 0x748F, 0xAD4D, 0x7490, 0xE8B4, 0x7491, 0xAD4E, 0x7492, 0xAD4F, + 0x7493, 0xAD50, 0x7494, 0xAD51, 0x7495, 0xAD52, 0x7496, 0xAD53, 0x7497, 0xAD54, 0x7498, 0xAD55, 0x7499, 0xAD56, 0x749A, 0xAD57, + 0x749B, 0xAD58, 0x749C, 0xE8AB, 0x749D, 0xAD59, 0x749E, 0xE8B1, 0x749F, 0xAD5A, 0x74A0, 0xAD5B, 0x74A1, 0xAD5C, 0x74A2, 0xAD5D, + 0x74A3, 0xAD5E, 0x74A4, 0xAD5F, 0x74A5, 0xAD60, 0x74A6, 0xAD61, 0x74A7, 0xE8B5, 0x74A8, 0xE8B2, 0x74A9, 0xE8B3, 0x74AA, 0xAD62, + 0x74AB, 0xAD63, 0x74AC, 0xAD64, 0x74AD, 0xAD65, 0x74AE, 0xAD66, 0x74AF, 0xAD67, 0x74B0, 0xAD68, 0x74B1, 0xAD69, 0x74B2, 0xAD6A, + 0x74B3, 0xAD6B, 0x74B4, 0xAD6C, 0x74B5, 0xAD6D, 0x74B6, 0xAD6E, 0x74B7, 0xAD6F, 0x74B8, 0xAD70, 0x74B9, 0xAD71, 0x74BA, 0xE8B7, + 0x74BB, 0xAD72, 0x74BC, 0xAD73, 0x74BD, 0xAD74, 0x74BE, 0xAD75, 0x74BF, 0xAD76, 0x74C0, 0xAD77, 0x74C1, 0xAD78, 0x74C2, 0xAD79, + 0x74C3, 0xAD7A, 0x74C4, 0xAD7B, 0x74C5, 0xAD7C, 0x74C6, 0xAD7D, 0x74C7, 0xAD7E, 0x74C8, 0xAD80, 0x74C9, 0xAD81, 0x74CA, 0xAD82, + 0x74CB, 0xAD83, 0x74CC, 0xAD84, 0x74CD, 0xAD85, 0x74CE, 0xAD86, 0x74CF, 0xAD87, 0x74D0, 0xAD88, 0x74D1, 0xAD89, 0x74D2, 0xE8B6, + 0x74D3, 0xAD8A, 0x74D4, 0xAD8B, 0x74D5, 0xAD8C, 0x74D6, 0xAD8D, 0x74D7, 0xAD8E, 0x74D8, 0xAD8F, 0x74D9, 0xAD90, 0x74DA, 0xAD91, + 0x74DB, 0xAD92, 0x74DC, 0xB9CF, 0x74DD, 0xAD93, 0x74DE, 0xF0AC, 0x74DF, 0xAD94, 0x74E0, 0xF0AD, 0x74E1, 0xAD95, 0x74E2, 0xC6B0, + 0x74E3, 0xB0EA, 0x74E4, 0xC8BF, 0x74E5, 0xAD96, 0x74E6, 0xCDDF, 0x74E7, 0xAD97, 0x74E8, 0xAD98, 0x74E9, 0xAD99, 0x74EA, 0xAD9A, + 0x74EB, 0xAD9B, 0x74EC, 0xAD9C, 0x74ED, 0xAD9D, 0x74EE, 0xCECD, 0x74EF, 0xEAB1, 0x74F0, 0xAD9E, 0x74F1, 0xAD9F, 0x74F2, 0xADA0, + 0x74F3, 0xAE40, 0x74F4, 0xEAB2, 0x74F5, 0xAE41, 0x74F6, 0xC6BF, 0x74F7, 0xB4C9, 0x74F8, 0xAE42, 0x74F9, 0xAE43, 0x74FA, 0xAE44, + 0x74FB, 0xAE45, 0x74FC, 0xAE46, 0x74FD, 0xAE47, 0x74FE, 0xAE48, 0x74FF, 0xEAB3, 0x7500, 0xAE49, 0x7501, 0xAE4A, 0x7502, 0xAE4B, + 0x7503, 0xAE4C, 0x7504, 0xD5E7, 0x7505, 0xAE4D, 0x7506, 0xAE4E, 0x7507, 0xAE4F, 0x7508, 0xAE50, 0x7509, 0xAE51, 0x750A, 0xAE52, + 0x750B, 0xAE53, 0x750C, 0xAE54, 0x750D, 0xDDF9, 0x750E, 0xAE55, 0x750F, 0xEAB4, 0x7510, 0xAE56, 0x7511, 0xEAB5, 0x7512, 0xAE57, + 0x7513, 0xEAB6, 0x7514, 0xAE58, 0x7515, 0xAE59, 0x7516, 0xAE5A, 0x7517, 0xAE5B, 0x7518, 0xB8CA, 0x7519, 0xDFB0, 0x751A, 0xC9F5, + 0x751B, 0xAE5C, 0x751C, 0xCCF0, 0x751D, 0xAE5D, 0x751E, 0xAE5E, 0x751F, 0xC9FA, 0x7520, 0xAE5F, 0x7521, 0xAE60, 0x7522, 0xAE61, + 0x7523, 0xAE62, 0x7524, 0xAE63, 0x7525, 0xC9FB, 0x7526, 0xAE64, 0x7527, 0xAE65, 0x7528, 0xD3C3, 0x7529, 0xCBA6, 0x752A, 0xAE66, + 0x752B, 0xB8A6, 0x752C, 0xF0AE, 0x752D, 0xB1C2, 0x752E, 0xAE67, 0x752F, 0xE5B8, 0x7530, 0xCCEF, 0x7531, 0xD3C9, 0x7532, 0xBCD7, + 0x7533, 0xC9EA, 0x7534, 0xAE68, 0x7535, 0xB5E7, 0x7536, 0xAE69, 0x7537, 0xC4D0, 0x7538, 0xB5E9, 0x7539, 0xAE6A, 0x753A, 0xEEAE, + 0x753B, 0xBBAD, 0x753C, 0xAE6B, 0x753D, 0xAE6C, 0x753E, 0xE7DE, 0x753F, 0xAE6D, 0x7540, 0xEEAF, 0x7541, 0xAE6E, 0x7542, 0xAE6F, + 0x7543, 0xAE70, 0x7544, 0xAE71, 0x7545, 0xB3A9, 0x7546, 0xAE72, 0x7547, 0xAE73, 0x7548, 0xEEB2, 0x7549, 0xAE74, 0x754A, 0xAE75, + 0x754B, 0xEEB1, 0x754C, 0xBDE7, 0x754D, 0xAE76, 0x754E, 0xEEB0, 0x754F, 0xCEB7, 0x7550, 0xAE77, 0x7551, 0xAE78, 0x7552, 0xAE79, + 0x7553, 0xAE7A, 0x7554, 0xC5CF, 0x7555, 0xAE7B, 0x7556, 0xAE7C, 0x7557, 0xAE7D, 0x7558, 0xAE7E, 0x7559, 0xC1F4, 0x755A, 0xDBCE, + 0x755B, 0xEEB3, 0x755C, 0xD0F3, 0x755D, 0xAE80, 0x755E, 0xAE81, 0x755F, 0xAE82, 0x7560, 0xAE83, 0x7561, 0xAE84, 0x7562, 0xAE85, + 0x7563, 0xAE86, 0x7564, 0xAE87, 0x7565, 0xC2D4, 0x7566, 0xC6E8, 0x7567, 0xAE88, 0x7568, 0xAE89, 0x7569, 0xAE8A, 0x756A, 0xB7AC, + 0x756B, 0xAE8B, 0x756C, 0xAE8C, 0x756D, 0xAE8D, 0x756E, 0xAE8E, 0x756F, 0xAE8F, 0x7570, 0xAE90, 0x7571, 0xAE91, 0x7572, 0xEEB4, + 0x7573, 0xAE92, 0x7574, 0xB3EB, 0x7575, 0xAE93, 0x7576, 0xAE94, 0x7577, 0xAE95, 0x7578, 0xBBFB, 0x7579, 0xEEB5, 0x757A, 0xAE96, + 0x757B, 0xAE97, 0x757C, 0xAE98, 0x757D, 0xAE99, 0x757E, 0xAE9A, 0x757F, 0xE7DC, 0x7580, 0xAE9B, 0x7581, 0xAE9C, 0x7582, 0xAE9D, + 0x7583, 0xEEB6, 0x7584, 0xAE9E, 0x7585, 0xAE9F, 0x7586, 0xBDAE, 0x7587, 0xAEA0, 0x7588, 0xAF40, 0x7589, 0xAF41, 0x758A, 0xAF42, + 0x758B, 0xF1E2, 0x758C, 0xAF43, 0x758D, 0xAF44, 0x758E, 0xAF45, 0x758F, 0xCAE8, 0x7590, 0xAF46, 0x7591, 0xD2C9, 0x7592, 0xF0DA, + 0x7593, 0xAF47, 0x7594, 0xF0DB, 0x7595, 0xAF48, 0x7596, 0xF0DC, 0x7597, 0xC1C6, 0x7598, 0xAF49, 0x7599, 0xB8ED, 0x759A, 0xBECE, + 0x759B, 0xAF4A, 0x759C, 0xAF4B, 0x759D, 0xF0DE, 0x759E, 0xAF4C, 0x759F, 0xC5B1, 0x75A0, 0xF0DD, 0x75A1, 0xD1F1, 0x75A2, 0xAF4D, + 0x75A3, 0xF0E0, 0x75A4, 0xB0CC, 0x75A5, 0xBDEA, 0x75A6, 0xAF4E, 0x75A7, 0xAF4F, 0x75A8, 0xAF50, 0x75A9, 0xAF51, 0x75AA, 0xAF52, + 0x75AB, 0xD2DF, 0x75AC, 0xF0DF, 0x75AD, 0xAF53, 0x75AE, 0xB4AF, 0x75AF, 0xB7E8, 0x75B0, 0xF0E6, 0x75B1, 0xF0E5, 0x75B2, 0xC6A3, + 0x75B3, 0xF0E1, 0x75B4, 0xF0E2, 0x75B5, 0xB4C3, 0x75B6, 0xAF54, 0x75B7, 0xAF55, 0x75B8, 0xF0E3, 0x75B9, 0xD5EE, 0x75BA, 0xAF56, + 0x75BB, 0xAF57, 0x75BC, 0xCCDB, 0x75BD, 0xBED2, 0x75BE, 0xBCB2, 0x75BF, 0xAF58, 0x75C0, 0xAF59, 0x75C1, 0xAF5A, 0x75C2, 0xF0E8, + 0x75C3, 0xF0E7, 0x75C4, 0xF0E4, 0x75C5, 0xB2A1, 0x75C6, 0xAF5B, 0x75C7, 0xD6A2, 0x75C8, 0xD3B8, 0x75C9, 0xBEB7, 0x75CA, 0xC8AC, + 0x75CB, 0xAF5C, 0x75CC, 0xAF5D, 0x75CD, 0xF0EA, 0x75CE, 0xAF5E, 0x75CF, 0xAF5F, 0x75D0, 0xAF60, 0x75D1, 0xAF61, 0x75D2, 0xD1F7, + 0x75D3, 0xAF62, 0x75D4, 0xD6CC, 0x75D5, 0xBADB, 0x75D6, 0xF0E9, 0x75D7, 0xAF63, 0x75D8, 0xB6BB, 0x75D9, 0xAF64, 0x75DA, 0xAF65, + 0x75DB, 0xCDB4, 0x75DC, 0xAF66, 0x75DD, 0xAF67, 0x75DE, 0xC6A6, 0x75DF, 0xAF68, 0x75E0, 0xAF69, 0x75E1, 0xAF6A, 0x75E2, 0xC1A1, + 0x75E3, 0xF0EB, 0x75E4, 0xF0EE, 0x75E5, 0xAF6B, 0x75E6, 0xF0ED, 0x75E7, 0xF0F0, 0x75E8, 0xF0EC, 0x75E9, 0xAF6C, 0x75EA, 0xBBBE, + 0x75EB, 0xF0EF, 0x75EC, 0xAF6D, 0x75ED, 0xAF6E, 0x75EE, 0xAF6F, 0x75EF, 0xAF70, 0x75F0, 0xCCB5, 0x75F1, 0xF0F2, 0x75F2, 0xAF71, + 0x75F3, 0xAF72, 0x75F4, 0xB3D5, 0x75F5, 0xAF73, 0x75F6, 0xAF74, 0x75F7, 0xAF75, 0x75F8, 0xAF76, 0x75F9, 0xB1D4, 0x75FA, 0xAF77, + 0x75FB, 0xAF78, 0x75FC, 0xF0F3, 0x75FD, 0xAF79, 0x75FE, 0xAF7A, 0x75FF, 0xF0F4, 0x7600, 0xF0F6, 0x7601, 0xB4E1, 0x7602, 0xAF7B, + 0x7603, 0xF0F1, 0x7604, 0xAF7C, 0x7605, 0xF0F7, 0x7606, 0xAF7D, 0x7607, 0xAF7E, 0x7608, 0xAF80, 0x7609, 0xAF81, 0x760A, 0xF0FA, + 0x760B, 0xAF82, 0x760C, 0xF0F8, 0x760D, 0xAF83, 0x760E, 0xAF84, 0x760F, 0xAF85, 0x7610, 0xF0F5, 0x7611, 0xAF86, 0x7612, 0xAF87, + 0x7613, 0xAF88, 0x7614, 0xAF89, 0x7615, 0xF0FD, 0x7616, 0xAF8A, 0x7617, 0xF0F9, 0x7618, 0xF0FC, 0x7619, 0xF0FE, 0x761A, 0xAF8B, + 0x761B, 0xF1A1, 0x761C, 0xAF8C, 0x761D, 0xAF8D, 0x761E, 0xAF8E, 0x761F, 0xCEC1, 0x7620, 0xF1A4, 0x7621, 0xAF8F, 0x7622, 0xF1A3, + 0x7623, 0xAF90, 0x7624, 0xC1F6, 0x7625, 0xF0FB, 0x7626, 0xCADD, 0x7627, 0xAF91, 0x7628, 0xAF92, 0x7629, 0xB4F1, 0x762A, 0xB1F1, + 0x762B, 0xCCB1, 0x762C, 0xAF93, 0x762D, 0xF1A6, 0x762E, 0xAF94, 0x762F, 0xAF95, 0x7630, 0xF1A7, 0x7631, 0xAF96, 0x7632, 0xAF97, + 0x7633, 0xF1AC, 0x7634, 0xD5CE, 0x7635, 0xF1A9, 0x7636, 0xAF98, 0x7637, 0xAF99, 0x7638, 0xC8B3, 0x7639, 0xAF9A, 0x763A, 0xAF9B, + 0x763B, 0xAF9C, 0x763C, 0xF1A2, 0x763D, 0xAF9D, 0x763E, 0xF1AB, 0x763F, 0xF1A8, 0x7640, 0xF1A5, 0x7641, 0xAF9E, 0x7642, 0xAF9F, + 0x7643, 0xF1AA, 0x7644, 0xAFA0, 0x7645, 0xB040, 0x7646, 0xB041, 0x7647, 0xB042, 0x7648, 0xB043, 0x7649, 0xB044, 0x764A, 0xB045, + 0x764B, 0xB046, 0x764C, 0xB0A9, 0x764D, 0xF1AD, 0x764E, 0xB047, 0x764F, 0xB048, 0x7650, 0xB049, 0x7651, 0xB04A, 0x7652, 0xB04B, + 0x7653, 0xB04C, 0x7654, 0xF1AF, 0x7655, 0xB04D, 0x7656, 0xF1B1, 0x7657, 0xB04E, 0x7658, 0xB04F, 0x7659, 0xB050, 0x765A, 0xB051, + 0x765B, 0xB052, 0x765C, 0xF1B0, 0x765D, 0xB053, 0x765E, 0xF1AE, 0x765F, 0xB054, 0x7660, 0xB055, 0x7661, 0xB056, 0x7662, 0xB057, + 0x7663, 0xD1A2, 0x7664, 0xB058, 0x7665, 0xB059, 0x7666, 0xB05A, 0x7667, 0xB05B, 0x7668, 0xB05C, 0x7669, 0xB05D, 0x766A, 0xB05E, + 0x766B, 0xF1B2, 0x766C, 0xB05F, 0x766D, 0xB060, 0x766E, 0xB061, 0x766F, 0xF1B3, 0x7670, 0xB062, 0x7671, 0xB063, 0x7672, 0xB064, + 0x7673, 0xB065, 0x7674, 0xB066, 0x7675, 0xB067, 0x7676, 0xB068, 0x7677, 0xB069, 0x7678, 0xB9EF, 0x7679, 0xB06A, 0x767A, 0xB06B, + 0x767B, 0xB5C7, 0x767C, 0xB06C, 0x767D, 0xB0D7, 0x767E, 0xB0D9, 0x767F, 0xB06D, 0x7680, 0xB06E, 0x7681, 0xB06F, 0x7682, 0xD4ED, + 0x7683, 0xB070, 0x7684, 0xB5C4, 0x7685, 0xB071, 0x7686, 0xBDD4, 0x7687, 0xBBCA, 0x7688, 0xF0A7, 0x7689, 0xB072, 0x768A, 0xB073, + 0x768B, 0xB8DE, 0x768C, 0xB074, 0x768D, 0xB075, 0x768E, 0xF0A8, 0x768F, 0xB076, 0x7690, 0xB077, 0x7691, 0xB0A8, 0x7692, 0xB078, + 0x7693, 0xF0A9, 0x7694, 0xB079, 0x7695, 0xB07A, 0x7696, 0xCDEE, 0x7697, 0xB07B, 0x7698, 0xB07C, 0x7699, 0xF0AA, 0x769A, 0xB07D, + 0x769B, 0xB07E, 0x769C, 0xB080, 0x769D, 0xB081, 0x769E, 0xB082, 0x769F, 0xB083, 0x76A0, 0xB084, 0x76A1, 0xB085, 0x76A2, 0xB086, + 0x76A3, 0xB087, 0x76A4, 0xF0AB, 0x76A5, 0xB088, 0x76A6, 0xB089, 0x76A7, 0xB08A, 0x76A8, 0xB08B, 0x76A9, 0xB08C, 0x76AA, 0xB08D, + 0x76AB, 0xB08E, 0x76AC, 0xB08F, 0x76AD, 0xB090, 0x76AE, 0xC6A4, 0x76AF, 0xB091, 0x76B0, 0xB092, 0x76B1, 0xD6E5, 0x76B2, 0xF1E4, + 0x76B3, 0xB093, 0x76B4, 0xF1E5, 0x76B5, 0xB094, 0x76B6, 0xB095, 0x76B7, 0xB096, 0x76B8, 0xB097, 0x76B9, 0xB098, 0x76BA, 0xB099, + 0x76BB, 0xB09A, 0x76BC, 0xB09B, 0x76BD, 0xB09C, 0x76BE, 0xB09D, 0x76BF, 0xC3F3, 0x76C0, 0xB09E, 0x76C1, 0xB09F, 0x76C2, 0xD3DB, + 0x76C3, 0xB0A0, 0x76C4, 0xB140, 0x76C5, 0xD6D1, 0x76C6, 0xC5E8, 0x76C7, 0xB141, 0x76C8, 0xD3AF, 0x76C9, 0xB142, 0x76CA, 0xD2E6, + 0x76CB, 0xB143, 0x76CC, 0xB144, 0x76CD, 0xEEC1, 0x76CE, 0xB0BB, 0x76CF, 0xD5B5, 0x76D0, 0xD1CE, 0x76D1, 0xBCE0, 0x76D2, 0xBAD0, + 0x76D3, 0xB145, 0x76D4, 0xBFF8, 0x76D5, 0xB146, 0x76D6, 0xB8C7, 0x76D7, 0xB5C1, 0x76D8, 0xC5CC, 0x76D9, 0xB147, 0x76DA, 0xB148, + 0x76DB, 0xCAA2, 0x76DC, 0xB149, 0x76DD, 0xB14A, 0x76DE, 0xB14B, 0x76DF, 0xC3CB, 0x76E0, 0xB14C, 0x76E1, 0xB14D, 0x76E2, 0xB14E, + 0x76E3, 0xB14F, 0x76E4, 0xB150, 0x76E5, 0xEEC2, 0x76E6, 0xB151, 0x76E7, 0xB152, 0x76E8, 0xB153, 0x76E9, 0xB154, 0x76EA, 0xB155, + 0x76EB, 0xB156, 0x76EC, 0xB157, 0x76ED, 0xB158, 0x76EE, 0xC4BF, 0x76EF, 0xB6A2, 0x76F0, 0xB159, 0x76F1, 0xEDEC, 0x76F2, 0xC3A4, + 0x76F3, 0xB15A, 0x76F4, 0xD6B1, 0x76F5, 0xB15B, 0x76F6, 0xB15C, 0x76F7, 0xB15D, 0x76F8, 0xCFE0, 0x76F9, 0xEDEF, 0x76FA, 0xB15E, + 0x76FB, 0xB15F, 0x76FC, 0xC5CE, 0x76FD, 0xB160, 0x76FE, 0xB6DC, 0x76FF, 0xB161, 0x7700, 0xB162, 0x7701, 0xCAA1, 0x7702, 0xB163, + 0x7703, 0xB164, 0x7704, 0xEDED, 0x7705, 0xB165, 0x7706, 0xB166, 0x7707, 0xEDF0, 0x7708, 0xEDF1, 0x7709, 0xC3BC, 0x770A, 0xB167, + 0x770B, 0xBFB4, 0x770C, 0xB168, 0x770D, 0xEDEE, 0x770E, 0xB169, 0x770F, 0xB16A, 0x7710, 0xB16B, 0x7711, 0xB16C, 0x7712, 0xB16D, + 0x7713, 0xB16E, 0x7714, 0xB16F, 0x7715, 0xB170, 0x7716, 0xB171, 0x7717, 0xB172, 0x7718, 0xB173, 0x7719, 0xEDF4, 0x771A, 0xEDF2, + 0x771B, 0xB174, 0x771C, 0xB175, 0x771D, 0xB176, 0x771E, 0xB177, 0x771F, 0xD5E6, 0x7720, 0xC3DF, 0x7721, 0xB178, 0x7722, 0xEDF3, + 0x7723, 0xB179, 0x7724, 0xB17A, 0x7725, 0xB17B, 0x7726, 0xEDF6, 0x7727, 0xB17C, 0x7728, 0xD5A3, 0x7729, 0xD1A3, 0x772A, 0xB17D, + 0x772B, 0xB17E, 0x772C, 0xB180, 0x772D, 0xEDF5, 0x772E, 0xB181, 0x772F, 0xC3D0, 0x7730, 0xB182, 0x7731, 0xB183, 0x7732, 0xB184, + 0x7733, 0xB185, 0x7734, 0xB186, 0x7735, 0xEDF7, 0x7736, 0xBFF4, 0x7737, 0xBEEC, 0x7738, 0xEDF8, 0x7739, 0xB187, 0x773A, 0xCCF7, + 0x773B, 0xB188, 0x773C, 0xD1DB, 0x773D, 0xB189, 0x773E, 0xB18A, 0x773F, 0xB18B, 0x7740, 0xD7C5, 0x7741, 0xD5F6, 0x7742, 0xB18C, + 0x7743, 0xEDFC, 0x7744, 0xB18D, 0x7745, 0xB18E, 0x7746, 0xB18F, 0x7747, 0xEDFB, 0x7748, 0xB190, 0x7749, 0xB191, 0x774A, 0xB192, + 0x774B, 0xB193, 0x774C, 0xB194, 0x774D, 0xB195, 0x774E, 0xB196, 0x774F, 0xB197, 0x7750, 0xEDF9, 0x7751, 0xEDFA, 0x7752, 0xB198, + 0x7753, 0xB199, 0x7754, 0xB19A, 0x7755, 0xB19B, 0x7756, 0xB19C, 0x7757, 0xB19D, 0x7758, 0xB19E, 0x7759, 0xB19F, 0x775A, 0xEDFD, + 0x775B, 0xBEA6, 0x775C, 0xB1A0, 0x775D, 0xB240, 0x775E, 0xB241, 0x775F, 0xB242, 0x7760, 0xB243, 0x7761, 0xCBAF, 0x7762, 0xEEA1, + 0x7763, 0xB6BD, 0x7764, 0xB244, 0x7765, 0xEEA2, 0x7766, 0xC4C0, 0x7767, 0xB245, 0x7768, 0xEDFE, 0x7769, 0xB246, 0x776A, 0xB247, + 0x776B, 0xBDDE, 0x776C, 0xB2C7, 0x776D, 0xB248, 0x776E, 0xB249, 0x776F, 0xB24A, 0x7770, 0xB24B, 0x7771, 0xB24C, 0x7772, 0xB24D, + 0x7773, 0xB24E, 0x7774, 0xB24F, 0x7775, 0xB250, 0x7776, 0xB251, 0x7777, 0xB252, 0x7778, 0xB253, 0x7779, 0xB6C3, 0x777A, 0xB254, + 0x777B, 0xB255, 0x777C, 0xB256, 0x777D, 0xEEA5, 0x777E, 0xD8BA, 0x777F, 0xEEA3, 0x7780, 0xEEA6, 0x7781, 0xB257, 0x7782, 0xB258, + 0x7783, 0xB259, 0x7784, 0xC3E9, 0x7785, 0xB3F2, 0x7786, 0xB25A, 0x7787, 0xB25B, 0x7788, 0xB25C, 0x7789, 0xB25D, 0x778A, 0xB25E, + 0x778B, 0xB25F, 0x778C, 0xEEA7, 0x778D, 0xEEA4, 0x778E, 0xCFB9, 0x778F, 0xB260, 0x7790, 0xB261, 0x7791, 0xEEA8, 0x7792, 0xC2F7, + 0x7793, 0xB262, 0x7794, 0xB263, 0x7795, 0xB264, 0x7796, 0xB265, 0x7797, 0xB266, 0x7798, 0xB267, 0x7799, 0xB268, 0x779A, 0xB269, + 0x779B, 0xB26A, 0x779C, 0xB26B, 0x779D, 0xB26C, 0x779E, 0xB26D, 0x779F, 0xEEA9, 0x77A0, 0xEEAA, 0x77A1, 0xB26E, 0x77A2, 0xDEAB, + 0x77A3, 0xB26F, 0x77A4, 0xB270, 0x77A5, 0xC6B3, 0x77A6, 0xB271, 0x77A7, 0xC7C6, 0x77A8, 0xB272, 0x77A9, 0xD6F5, 0x77AA, 0xB5C9, + 0x77AB, 0xB273, 0x77AC, 0xCBB2, 0x77AD, 0xB274, 0x77AE, 0xB275, 0x77AF, 0xB276, 0x77B0, 0xEEAB, 0x77B1, 0xB277, 0x77B2, 0xB278, + 0x77B3, 0xCDAB, 0x77B4, 0xB279, 0x77B5, 0xEEAC, 0x77B6, 0xB27A, 0x77B7, 0xB27B, 0x77B8, 0xB27C, 0x77B9, 0xB27D, 0x77BA, 0xB27E, + 0x77BB, 0xD5B0, 0x77BC, 0xB280, 0x77BD, 0xEEAD, 0x77BE, 0xB281, 0x77BF, 0xF6C4, 0x77C0, 0xB282, 0x77C1, 0xB283, 0x77C2, 0xB284, + 0x77C3, 0xB285, 0x77C4, 0xB286, 0x77C5, 0xB287, 0x77C6, 0xB288, 0x77C7, 0xB289, 0x77C8, 0xB28A, 0x77C9, 0xB28B, 0x77CA, 0xB28C, + 0x77CB, 0xB28D, 0x77CC, 0xB28E, 0x77CD, 0xDBC7, 0x77CE, 0xB28F, 0x77CF, 0xB290, 0x77D0, 0xB291, 0x77D1, 0xB292, 0x77D2, 0xB293, + 0x77D3, 0xB294, 0x77D4, 0xB295, 0x77D5, 0xB296, 0x77D6, 0xB297, 0x77D7, 0xB4A3, 0x77D8, 0xB298, 0x77D9, 0xB299, 0x77DA, 0xB29A, + 0x77DB, 0xC3AC, 0x77DC, 0xF1E6, 0x77DD, 0xB29B, 0x77DE, 0xB29C, 0x77DF, 0xB29D, 0x77E0, 0xB29E, 0x77E1, 0xB29F, 0x77E2, 0xCAB8, + 0x77E3, 0xD2D3, 0x77E4, 0xB2A0, 0x77E5, 0xD6AA, 0x77E6, 0xB340, 0x77E7, 0xEFF2, 0x77E8, 0xB341, 0x77E9, 0xBED8, 0x77EA, 0xB342, + 0x77EB, 0xBDC3, 0x77EC, 0xEFF3, 0x77ED, 0xB6CC, 0x77EE, 0xB0AB, 0x77EF, 0xB343, 0x77F0, 0xB344, 0x77F1, 0xB345, 0x77F2, 0xB346, + 0x77F3, 0xCAAF, 0x77F4, 0xB347, 0x77F5, 0xB348, 0x77F6, 0xEDB6, 0x77F7, 0xB349, 0x77F8, 0xEDB7, 0x77F9, 0xB34A, 0x77FA, 0xB34B, + 0x77FB, 0xB34C, 0x77FC, 0xB34D, 0x77FD, 0xCEF9, 0x77FE, 0xB7AF, 0x77FF, 0xBFF3, 0x7800, 0xEDB8, 0x7801, 0xC2EB, 0x7802, 0xC9B0, + 0x7803, 0xB34E, 0x7804, 0xB34F, 0x7805, 0xB350, 0x7806, 0xB351, 0x7807, 0xB352, 0x7808, 0xB353, 0x7809, 0xEDB9, 0x780A, 0xB354, + 0x780B, 0xB355, 0x780C, 0xC6F6, 0x780D, 0xBFB3, 0x780E, 0xB356, 0x780F, 0xB357, 0x7810, 0xB358, 0x7811, 0xEDBC, 0x7812, 0xC5F8, + 0x7813, 0xB359, 0x7814, 0xD1D0, 0x7815, 0xB35A, 0x7816, 0xD7A9, 0x7817, 0xEDBA, 0x7818, 0xEDBB, 0x7819, 0xB35B, 0x781A, 0xD1E2, + 0x781B, 0xB35C, 0x781C, 0xEDBF, 0x781D, 0xEDC0, 0x781E, 0xB35D, 0x781F, 0xEDC4, 0x7820, 0xB35E, 0x7821, 0xB35F, 0x7822, 0xB360, + 0x7823, 0xEDC8, 0x7824, 0xB361, 0x7825, 0xEDC6, 0x7826, 0xEDCE, 0x7827, 0xD5E8, 0x7828, 0xB362, 0x7829, 0xEDC9, 0x782A, 0xB363, + 0x782B, 0xB364, 0x782C, 0xEDC7, 0x782D, 0xEDBE, 0x782E, 0xB365, 0x782F, 0xB366, 0x7830, 0xC5E9, 0x7831, 0xB367, 0x7832, 0xB368, + 0x7833, 0xB369, 0x7834, 0xC6C6, 0x7835, 0xB36A, 0x7836, 0xB36B, 0x7837, 0xC9E9, 0x7838, 0xD4D2, 0x7839, 0xEDC1, 0x783A, 0xEDC2, + 0x783B, 0xEDC3, 0x783C, 0xEDC5, 0x783D, 0xB36C, 0x783E, 0xC0F9, 0x783F, 0xB36D, 0x7840, 0xB4A1, 0x7841, 0xB36E, 0x7842, 0xB36F, + 0x7843, 0xB370, 0x7844, 0xB371, 0x7845, 0xB9E8, 0x7846, 0xB372, 0x7847, 0xEDD0, 0x7848, 0xB373, 0x7849, 0xB374, 0x784A, 0xB375, + 0x784B, 0xB376, 0x784C, 0xEDD1, 0x784D, 0xB377, 0x784E, 0xEDCA, 0x784F, 0xB378, 0x7850, 0xEDCF, 0x7851, 0xB379, 0x7852, 0xCEF8, + 0x7853, 0xB37A, 0x7854, 0xB37B, 0x7855, 0xCBB6, 0x7856, 0xEDCC, 0x7857, 0xEDCD, 0x7858, 0xB37C, 0x7859, 0xB37D, 0x785A, 0xB37E, + 0x785B, 0xB380, 0x785C, 0xB381, 0x785D, 0xCFF5, 0x785E, 0xB382, 0x785F, 0xB383, 0x7860, 0xB384, 0x7861, 0xB385, 0x7862, 0xB386, + 0x7863, 0xB387, 0x7864, 0xB388, 0x7865, 0xB389, 0x7866, 0xB38A, 0x7867, 0xB38B, 0x7868, 0xB38C, 0x7869, 0xB38D, 0x786A, 0xEDD2, + 0x786B, 0xC1F2, 0x786C, 0xD3B2, 0x786D, 0xEDCB, 0x786E, 0xC8B7, 0x786F, 0xB38E, 0x7870, 0xB38F, 0x7871, 0xB390, 0x7872, 0xB391, + 0x7873, 0xB392, 0x7874, 0xB393, 0x7875, 0xB394, 0x7876, 0xB395, 0x7877, 0xBCEF, 0x7878, 0xB396, 0x7879, 0xB397, 0x787A, 0xB398, + 0x787B, 0xB399, 0x787C, 0xC5F0, 0x787D, 0xB39A, 0x787E, 0xB39B, 0x787F, 0xB39C, 0x7880, 0xB39D, 0x7881, 0xB39E, 0x7882, 0xB39F, + 0x7883, 0xB3A0, 0x7884, 0xB440, 0x7885, 0xB441, 0x7886, 0xB442, 0x7887, 0xEDD6, 0x7888, 0xB443, 0x7889, 0xB5EF, 0x788A, 0xB444, + 0x788B, 0xB445, 0x788C, 0xC2B5, 0x788D, 0xB0AD, 0x788E, 0xCBE9, 0x788F, 0xB446, 0x7890, 0xB447, 0x7891, 0xB1AE, 0x7892, 0xB448, + 0x7893, 0xEDD4, 0x7894, 0xB449, 0x7895, 0xB44A, 0x7896, 0xB44B, 0x7897, 0xCDEB, 0x7898, 0xB5E2, 0x7899, 0xB44C, 0x789A, 0xEDD5, + 0x789B, 0xEDD3, 0x789C, 0xEDD7, 0x789D, 0xB44D, 0x789E, 0xB44E, 0x789F, 0xB5FA, 0x78A0, 0xB44F, 0x78A1, 0xEDD8, 0x78A2, 0xB450, + 0x78A3, 0xEDD9, 0x78A4, 0xB451, 0x78A5, 0xEDDC, 0x78A6, 0xB452, 0x78A7, 0xB1CC, 0x78A8, 0xB453, 0x78A9, 0xB454, 0x78AA, 0xB455, + 0x78AB, 0xB456, 0x78AC, 0xB457, 0x78AD, 0xB458, 0x78AE, 0xB459, 0x78AF, 0xB45A, 0x78B0, 0xC5F6, 0x78B1, 0xBCEE, 0x78B2, 0xEDDA, + 0x78B3, 0xCCBC, 0x78B4, 0xB2EA, 0x78B5, 0xB45B, 0x78B6, 0xB45C, 0x78B7, 0xB45D, 0x78B8, 0xB45E, 0x78B9, 0xEDDB, 0x78BA, 0xB45F, + 0x78BB, 0xB460, 0x78BC, 0xB461, 0x78BD, 0xB462, 0x78BE, 0xC4EB, 0x78BF, 0xB463, 0x78C0, 0xB464, 0x78C1, 0xB4C5, 0x78C2, 0xB465, + 0x78C3, 0xB466, 0x78C4, 0xB467, 0x78C5, 0xB0F5, 0x78C6, 0xB468, 0x78C7, 0xB469, 0x78C8, 0xB46A, 0x78C9, 0xEDDF, 0x78CA, 0xC0DA, + 0x78CB, 0xB4E8, 0x78CC, 0xB46B, 0x78CD, 0xB46C, 0x78CE, 0xB46D, 0x78CF, 0xB46E, 0x78D0, 0xC5CD, 0x78D1, 0xB46F, 0x78D2, 0xB470, + 0x78D3, 0xB471, 0x78D4, 0xEDDD, 0x78D5, 0xBFC4, 0x78D6, 0xB472, 0x78D7, 0xB473, 0x78D8, 0xB474, 0x78D9, 0xEDDE, 0x78DA, 0xB475, + 0x78DB, 0xB476, 0x78DC, 0xB477, 0x78DD, 0xB478, 0x78DE, 0xB479, 0x78DF, 0xB47A, 0x78E0, 0xB47B, 0x78E1, 0xB47C, 0x78E2, 0xB47D, + 0x78E3, 0xB47E, 0x78E4, 0xB480, 0x78E5, 0xB481, 0x78E6, 0xB482, 0x78E7, 0xB483, 0x78E8, 0xC4A5, 0x78E9, 0xB484, 0x78EA, 0xB485, + 0x78EB, 0xB486, 0x78EC, 0xEDE0, 0x78ED, 0xB487, 0x78EE, 0xB488, 0x78EF, 0xB489, 0x78F0, 0xB48A, 0x78F1, 0xB48B, 0x78F2, 0xEDE1, + 0x78F3, 0xB48C, 0x78F4, 0xEDE3, 0x78F5, 0xB48D, 0x78F6, 0xB48E, 0x78F7, 0xC1D7, 0x78F8, 0xB48F, 0x78F9, 0xB490, 0x78FA, 0xBBC7, + 0x78FB, 0xB491, 0x78FC, 0xB492, 0x78FD, 0xB493, 0x78FE, 0xB494, 0x78FF, 0xB495, 0x7900, 0xB496, 0x7901, 0xBDB8, 0x7902, 0xB497, + 0x7903, 0xB498, 0x7904, 0xB499, 0x7905, 0xEDE2, 0x7906, 0xB49A, 0x7907, 0xB49B, 0x7908, 0xB49C, 0x7909, 0xB49D, 0x790A, 0xB49E, + 0x790B, 0xB49F, 0x790C, 0xB4A0, 0x790D, 0xB540, 0x790E, 0xB541, 0x790F, 0xB542, 0x7910, 0xB543, 0x7911, 0xB544, 0x7912, 0xB545, + 0x7913, 0xEDE4, 0x7914, 0xB546, 0x7915, 0xB547, 0x7916, 0xB548, 0x7917, 0xB549, 0x7918, 0xB54A, 0x7919, 0xB54B, 0x791A, 0xB54C, + 0x791B, 0xB54D, 0x791C, 0xB54E, 0x791D, 0xB54F, 0x791E, 0xEDE6, 0x791F, 0xB550, 0x7920, 0xB551, 0x7921, 0xB552, 0x7922, 0xB553, + 0x7923, 0xB554, 0x7924, 0xEDE5, 0x7925, 0xB555, 0x7926, 0xB556, 0x7927, 0xB557, 0x7928, 0xB558, 0x7929, 0xB559, 0x792A, 0xB55A, + 0x792B, 0xB55B, 0x792C, 0xB55C, 0x792D, 0xB55D, 0x792E, 0xB55E, 0x792F, 0xB55F, 0x7930, 0xB560, 0x7931, 0xB561, 0x7932, 0xB562, + 0x7933, 0xB563, 0x7934, 0xEDE7, 0x7935, 0xB564, 0x7936, 0xB565, 0x7937, 0xB566, 0x7938, 0xB567, 0x7939, 0xB568, 0x793A, 0xCABE, + 0x793B, 0xECEA, 0x793C, 0xC0F1, 0x793D, 0xB569, 0x793E, 0xC9E7, 0x793F, 0xB56A, 0x7940, 0xECEB, 0x7941, 0xC6EE, 0x7942, 0xB56B, + 0x7943, 0xB56C, 0x7944, 0xB56D, 0x7945, 0xB56E, 0x7946, 0xECEC, 0x7947, 0xB56F, 0x7948, 0xC6ED, 0x7949, 0xECED, 0x794A, 0xB570, + 0x794B, 0xB571, 0x794C, 0xB572, 0x794D, 0xB573, 0x794E, 0xB574, 0x794F, 0xB575, 0x7950, 0xB576, 0x7951, 0xB577, 0x7952, 0xB578, + 0x7953, 0xECF0, 0x7954, 0xB579, 0x7955, 0xB57A, 0x7956, 0xD7E6, 0x7957, 0xECF3, 0x7958, 0xB57B, 0x7959, 0xB57C, 0x795A, 0xECF1, + 0x795B, 0xECEE, 0x795C, 0xECEF, 0x795D, 0xD7A3, 0x795E, 0xC9F1, 0x795F, 0xCBEE, 0x7960, 0xECF4, 0x7961, 0xB57D, 0x7962, 0xECF2, + 0x7963, 0xB57E, 0x7964, 0xB580, 0x7965, 0xCFE9, 0x7966, 0xB581, 0x7967, 0xECF6, 0x7968, 0xC6B1, 0x7969, 0xB582, 0x796A, 0xB583, + 0x796B, 0xB584, 0x796C, 0xB585, 0x796D, 0xBCC0, 0x796E, 0xB586, 0x796F, 0xECF5, 0x7970, 0xB587, 0x7971, 0xB588, 0x7972, 0xB589, + 0x7973, 0xB58A, 0x7974, 0xB58B, 0x7975, 0xB58C, 0x7976, 0xB58D, 0x7977, 0xB5BB, 0x7978, 0xBBF6, 0x7979, 0xB58E, 0x797A, 0xECF7, + 0x797B, 0xB58F, 0x797C, 0xB590, 0x797D, 0xB591, 0x797E, 0xB592, 0x797F, 0xB593, 0x7980, 0xD9F7, 0x7981, 0xBDFB, 0x7982, 0xB594, + 0x7983, 0xB595, 0x7984, 0xC2BB, 0x7985, 0xECF8, 0x7986, 0xB596, 0x7987, 0xB597, 0x7988, 0xB598, 0x7989, 0xB599, 0x798A, 0xECF9, + 0x798B, 0xB59A, 0x798C, 0xB59B, 0x798D, 0xB59C, 0x798E, 0xB59D, 0x798F, 0xB8A3, 0x7990, 0xB59E, 0x7991, 0xB59F, 0x7992, 0xB5A0, + 0x7993, 0xB640, 0x7994, 0xB641, 0x7995, 0xB642, 0x7996, 0xB643, 0x7997, 0xB644, 0x7998, 0xB645, 0x7999, 0xB646, 0x799A, 0xECFA, + 0x799B, 0xB647, 0x799C, 0xB648, 0x799D, 0xB649, 0x799E, 0xB64A, 0x799F, 0xB64B, 0x79A0, 0xB64C, 0x79A1, 0xB64D, 0x79A2, 0xB64E, + 0x79A3, 0xB64F, 0x79A4, 0xB650, 0x79A5, 0xB651, 0x79A6, 0xB652, 0x79A7, 0xECFB, 0x79A8, 0xB653, 0x79A9, 0xB654, 0x79AA, 0xB655, + 0x79AB, 0xB656, 0x79AC, 0xB657, 0x79AD, 0xB658, 0x79AE, 0xB659, 0x79AF, 0xB65A, 0x79B0, 0xB65B, 0x79B1, 0xB65C, 0x79B2, 0xB65D, + 0x79B3, 0xECFC, 0x79B4, 0xB65E, 0x79B5, 0xB65F, 0x79B6, 0xB660, 0x79B7, 0xB661, 0x79B8, 0xB662, 0x79B9, 0xD3ED, 0x79BA, 0xD8AE, + 0x79BB, 0xC0EB, 0x79BC, 0xB663, 0x79BD, 0xC7DD, 0x79BE, 0xBACC, 0x79BF, 0xB664, 0x79C0, 0xD0E3, 0x79C1, 0xCBBD, 0x79C2, 0xB665, + 0x79C3, 0xCDBA, 0x79C4, 0xB666, 0x79C5, 0xB667, 0x79C6, 0xB8D1, 0x79C7, 0xB668, 0x79C8, 0xB669, 0x79C9, 0xB1FC, 0x79CA, 0xB66A, + 0x79CB, 0xC7EF, 0x79CC, 0xB66B, 0x79CD, 0xD6D6, 0x79CE, 0xB66C, 0x79CF, 0xB66D, 0x79D0, 0xB66E, 0x79D1, 0xBFC6, 0x79D2, 0xC3EB, + 0x79D3, 0xB66F, 0x79D4, 0xB670, 0x79D5, 0xEFF5, 0x79D6, 0xB671, 0x79D7, 0xB672, 0x79D8, 0xC3D8, 0x79D9, 0xB673, 0x79DA, 0xB674, + 0x79DB, 0xB675, 0x79DC, 0xB676, 0x79DD, 0xB677, 0x79DE, 0xB678, 0x79DF, 0xD7E2, 0x79E0, 0xB679, 0x79E1, 0xB67A, 0x79E2, 0xB67B, + 0x79E3, 0xEFF7, 0x79E4, 0xB3D3, 0x79E5, 0xB67C, 0x79E6, 0xC7D8, 0x79E7, 0xD1ED, 0x79E8, 0xB67D, 0x79E9, 0xD6C8, 0x79EA, 0xB67E, + 0x79EB, 0xEFF8, 0x79EC, 0xB680, 0x79ED, 0xEFF6, 0x79EE, 0xB681, 0x79EF, 0xBBFD, 0x79F0, 0xB3C6, 0x79F1, 0xB682, 0x79F2, 0xB683, + 0x79F3, 0xB684, 0x79F4, 0xB685, 0x79F5, 0xB686, 0x79F6, 0xB687, 0x79F7, 0xB688, 0x79F8, 0xBDD5, 0x79F9, 0xB689, 0x79FA, 0xB68A, + 0x79FB, 0xD2C6, 0x79FC, 0xB68B, 0x79FD, 0xBBE0, 0x79FE, 0xB68C, 0x79FF, 0xB68D, 0x7A00, 0xCFA1, 0x7A01, 0xB68E, 0x7A02, 0xEFFC, + 0x7A03, 0xEFFB, 0x7A04, 0xB68F, 0x7A05, 0xB690, 0x7A06, 0xEFF9, 0x7A07, 0xB691, 0x7A08, 0xB692, 0x7A09, 0xB693, 0x7A0A, 0xB694, + 0x7A0B, 0xB3CC, 0x7A0C, 0xB695, 0x7A0D, 0xC9D4, 0x7A0E, 0xCBB0, 0x7A0F, 0xB696, 0x7A10, 0xB697, 0x7A11, 0xB698, 0x7A12, 0xB699, + 0x7A13, 0xB69A, 0x7A14, 0xEFFE, 0x7A15, 0xB69B, 0x7A16, 0xB69C, 0x7A17, 0xB0DE, 0x7A18, 0xB69D, 0x7A19, 0xB69E, 0x7A1A, 0xD6C9, + 0x7A1B, 0xB69F, 0x7A1C, 0xB6A0, 0x7A1D, 0xB740, 0x7A1E, 0xEFFD, 0x7A1F, 0xB741, 0x7A20, 0xB3ED, 0x7A21, 0xB742, 0x7A22, 0xB743, + 0x7A23, 0xF6D5, 0x7A24, 0xB744, 0x7A25, 0xB745, 0x7A26, 0xB746, 0x7A27, 0xB747, 0x7A28, 0xB748, 0x7A29, 0xB749, 0x7A2A, 0xB74A, + 0x7A2B, 0xB74B, 0x7A2C, 0xB74C, 0x7A2D, 0xB74D, 0x7A2E, 0xB74E, 0x7A2F, 0xB74F, 0x7A30, 0xB750, 0x7A31, 0xB751, 0x7A32, 0xB752, + 0x7A33, 0xCEC8, 0x7A34, 0xB753, 0x7A35, 0xB754, 0x7A36, 0xB755, 0x7A37, 0xF0A2, 0x7A38, 0xB756, 0x7A39, 0xF0A1, 0x7A3A, 0xB757, + 0x7A3B, 0xB5BE, 0x7A3C, 0xBCDA, 0x7A3D, 0xBBFC, 0x7A3E, 0xB758, 0x7A3F, 0xB8E5, 0x7A40, 0xB759, 0x7A41, 0xB75A, 0x7A42, 0xB75B, + 0x7A43, 0xB75C, 0x7A44, 0xB75D, 0x7A45, 0xB75E, 0x7A46, 0xC4C2, 0x7A47, 0xB75F, 0x7A48, 0xB760, 0x7A49, 0xB761, 0x7A4A, 0xB762, + 0x7A4B, 0xB763, 0x7A4C, 0xB764, 0x7A4D, 0xB765, 0x7A4E, 0xB766, 0x7A4F, 0xB767, 0x7A50, 0xB768, 0x7A51, 0xF0A3, 0x7A52, 0xB769, + 0x7A53, 0xB76A, 0x7A54, 0xB76B, 0x7A55, 0xB76C, 0x7A56, 0xB76D, 0x7A57, 0xCBEB, 0x7A58, 0xB76E, 0x7A59, 0xB76F, 0x7A5A, 0xB770, + 0x7A5B, 0xB771, 0x7A5C, 0xB772, 0x7A5D, 0xB773, 0x7A5E, 0xB774, 0x7A5F, 0xB775, 0x7A60, 0xB776, 0x7A61, 0xB777, 0x7A62, 0xB778, + 0x7A63, 0xB779, 0x7A64, 0xB77A, 0x7A65, 0xB77B, 0x7A66, 0xB77C, 0x7A67, 0xB77D, 0x7A68, 0xB77E, 0x7A69, 0xB780, 0x7A6A, 0xB781, + 0x7A6B, 0xB782, 0x7A6C, 0xB783, 0x7A6D, 0xB784, 0x7A6E, 0xB785, 0x7A6F, 0xB786, 0x7A70, 0xF0A6, 0x7A71, 0xB787, 0x7A72, 0xB788, + 0x7A73, 0xB789, 0x7A74, 0xD1A8, 0x7A75, 0xB78A, 0x7A76, 0xBEBF, 0x7A77, 0xC7EE, 0x7A78, 0xF1B6, 0x7A79, 0xF1B7, 0x7A7A, 0xBFD5, + 0x7A7B, 0xB78B, 0x7A7C, 0xB78C, 0x7A7D, 0xB78D, 0x7A7E, 0xB78E, 0x7A7F, 0xB4A9, 0x7A80, 0xF1B8, 0x7A81, 0xCDBB, 0x7A82, 0xB78F, + 0x7A83, 0xC7D4, 0x7A84, 0xD5AD, 0x7A85, 0xB790, 0x7A86, 0xF1B9, 0x7A87, 0xB791, 0x7A88, 0xF1BA, 0x7A89, 0xB792, 0x7A8A, 0xB793, + 0x7A8B, 0xB794, 0x7A8C, 0xB795, 0x7A8D, 0xC7CF, 0x7A8E, 0xB796, 0x7A8F, 0xB797, 0x7A90, 0xB798, 0x7A91, 0xD2A4, 0x7A92, 0xD6CF, + 0x7A93, 0xB799, 0x7A94, 0xB79A, 0x7A95, 0xF1BB, 0x7A96, 0xBDD1, 0x7A97, 0xB4B0, 0x7A98, 0xBEBD, 0x7A99, 0xB79B, 0x7A9A, 0xB79C, + 0x7A9B, 0xB79D, 0x7A9C, 0xB4DC, 0x7A9D, 0xCED1, 0x7A9E, 0xB79E, 0x7A9F, 0xBFDF, 0x7AA0, 0xF1BD, 0x7AA1, 0xB79F, 0x7AA2, 0xB7A0, + 0x7AA3, 0xB840, 0x7AA4, 0xB841, 0x7AA5, 0xBFFA, 0x7AA6, 0xF1BC, 0x7AA7, 0xB842, 0x7AA8, 0xF1BF, 0x7AA9, 0xB843, 0x7AAA, 0xB844, + 0x7AAB, 0xB845, 0x7AAC, 0xF1BE, 0x7AAD, 0xF1C0, 0x7AAE, 0xB846, 0x7AAF, 0xB847, 0x7AB0, 0xB848, 0x7AB1, 0xB849, 0x7AB2, 0xB84A, + 0x7AB3, 0xF1C1, 0x7AB4, 0xB84B, 0x7AB5, 0xB84C, 0x7AB6, 0xB84D, 0x7AB7, 0xB84E, 0x7AB8, 0xB84F, 0x7AB9, 0xB850, 0x7ABA, 0xB851, + 0x7ABB, 0xB852, 0x7ABC, 0xB853, 0x7ABD, 0xB854, 0x7ABE, 0xB855, 0x7ABF, 0xC1FE, 0x7AC0, 0xB856, 0x7AC1, 0xB857, 0x7AC2, 0xB858, + 0x7AC3, 0xB859, 0x7AC4, 0xB85A, 0x7AC5, 0xB85B, 0x7AC6, 0xB85C, 0x7AC7, 0xB85D, 0x7AC8, 0xB85E, 0x7AC9, 0xB85F, 0x7ACA, 0xB860, + 0x7ACB, 0xC1A2, 0x7ACC, 0xB861, 0x7ACD, 0xB862, 0x7ACE, 0xB863, 0x7ACF, 0xB864, 0x7AD0, 0xB865, 0x7AD1, 0xB866, 0x7AD2, 0xB867, + 0x7AD3, 0xB868, 0x7AD4, 0xB869, 0x7AD5, 0xB86A, 0x7AD6, 0xCAFA, 0x7AD7, 0xB86B, 0x7AD8, 0xB86C, 0x7AD9, 0xD5BE, 0x7ADA, 0xB86D, + 0x7ADB, 0xB86E, 0x7ADC, 0xB86F, 0x7ADD, 0xB870, 0x7ADE, 0xBEBA, 0x7ADF, 0xBEB9, 0x7AE0, 0xD5C2, 0x7AE1, 0xB871, 0x7AE2, 0xB872, + 0x7AE3, 0xBFA2, 0x7AE4, 0xB873, 0x7AE5, 0xCDAF, 0x7AE6, 0xF1B5, 0x7AE7, 0xB874, 0x7AE8, 0xB875, 0x7AE9, 0xB876, 0x7AEA, 0xB877, + 0x7AEB, 0xB878, 0x7AEC, 0xB879, 0x7AED, 0xBDDF, 0x7AEE, 0xB87A, 0x7AEF, 0xB6CB, 0x7AF0, 0xB87B, 0x7AF1, 0xB87C, 0x7AF2, 0xB87D, + 0x7AF3, 0xB87E, 0x7AF4, 0xB880, 0x7AF5, 0xB881, 0x7AF6, 0xB882, 0x7AF7, 0xB883, 0x7AF8, 0xB884, 0x7AF9, 0xD6F1, 0x7AFA, 0xF3C3, + 0x7AFB, 0xB885, 0x7AFC, 0xB886, 0x7AFD, 0xF3C4, 0x7AFE, 0xB887, 0x7AFF, 0xB8CD, 0x7B00, 0xB888, 0x7B01, 0xB889, 0x7B02, 0xB88A, + 0x7B03, 0xF3C6, 0x7B04, 0xF3C7, 0x7B05, 0xB88B, 0x7B06, 0xB0CA, 0x7B07, 0xB88C, 0x7B08, 0xF3C5, 0x7B09, 0xB88D, 0x7B0A, 0xF3C9, + 0x7B0B, 0xCBF1, 0x7B0C, 0xB88E, 0x7B0D, 0xB88F, 0x7B0E, 0xB890, 0x7B0F, 0xF3CB, 0x7B10, 0xB891, 0x7B11, 0xD0A6, 0x7B12, 0xB892, + 0x7B13, 0xB893, 0x7B14, 0xB1CA, 0x7B15, 0xF3C8, 0x7B16, 0xB894, 0x7B17, 0xB895, 0x7B18, 0xB896, 0x7B19, 0xF3CF, 0x7B1A, 0xB897, + 0x7B1B, 0xB5D1, 0x7B1C, 0xB898, 0x7B1D, 0xB899, 0x7B1E, 0xF3D7, 0x7B1F, 0xB89A, 0x7B20, 0xF3D2, 0x7B21, 0xB89B, 0x7B22, 0xB89C, + 0x7B23, 0xB89D, 0x7B24, 0xF3D4, 0x7B25, 0xF3D3, 0x7B26, 0xB7FB, 0x7B27, 0xB89E, 0x7B28, 0xB1BF, 0x7B29, 0xB89F, 0x7B2A, 0xF3CE, + 0x7B2B, 0xF3CA, 0x7B2C, 0xB5DA, 0x7B2D, 0xB8A0, 0x7B2E, 0xF3D0, 0x7B2F, 0xB940, 0x7B30, 0xB941, 0x7B31, 0xF3D1, 0x7B32, 0xB942, + 0x7B33, 0xF3D5, 0x7B34, 0xB943, 0x7B35, 0xB944, 0x7B36, 0xB945, 0x7B37, 0xB946, 0x7B38, 0xF3CD, 0x7B39, 0xB947, 0x7B3A, 0xBCE3, + 0x7B3B, 0xB948, 0x7B3C, 0xC1FD, 0x7B3D, 0xB949, 0x7B3E, 0xF3D6, 0x7B3F, 0xB94A, 0x7B40, 0xB94B, 0x7B41, 0xB94C, 0x7B42, 0xB94D, + 0x7B43, 0xB94E, 0x7B44, 0xB94F, 0x7B45, 0xF3DA, 0x7B46, 0xB950, 0x7B47, 0xF3CC, 0x7B48, 0xB951, 0x7B49, 0xB5C8, 0x7B4A, 0xB952, + 0x7B4B, 0xBDEE, 0x7B4C, 0xF3DC, 0x7B4D, 0xB953, 0x7B4E, 0xB954, 0x7B4F, 0xB7A4, 0x7B50, 0xBFF0, 0x7B51, 0xD6FE, 0x7B52, 0xCDB2, + 0x7B53, 0xB955, 0x7B54, 0xB4F0, 0x7B55, 0xB956, 0x7B56, 0xB2DF, 0x7B57, 0xB957, 0x7B58, 0xF3D8, 0x7B59, 0xB958, 0x7B5A, 0xF3D9, + 0x7B5B, 0xC9B8, 0x7B5C, 0xB959, 0x7B5D, 0xF3DD, 0x7B5E, 0xB95A, 0x7B5F, 0xB95B, 0x7B60, 0xF3DE, 0x7B61, 0xB95C, 0x7B62, 0xF3E1, + 0x7B63, 0xB95D, 0x7B64, 0xB95E, 0x7B65, 0xB95F, 0x7B66, 0xB960, 0x7B67, 0xB961, 0x7B68, 0xB962, 0x7B69, 0xB963, 0x7B6A, 0xB964, + 0x7B6B, 0xB965, 0x7B6C, 0xB966, 0x7B6D, 0xB967, 0x7B6E, 0xF3DF, 0x7B6F, 0xB968, 0x7B70, 0xB969, 0x7B71, 0xF3E3, 0x7B72, 0xF3E2, + 0x7B73, 0xB96A, 0x7B74, 0xB96B, 0x7B75, 0xF3DB, 0x7B76, 0xB96C, 0x7B77, 0xBFEA, 0x7B78, 0xB96D, 0x7B79, 0xB3EF, 0x7B7A, 0xB96E, + 0x7B7B, 0xF3E0, 0x7B7C, 0xB96F, 0x7B7D, 0xB970, 0x7B7E, 0xC7A9, 0x7B7F, 0xB971, 0x7B80, 0xBCF2, 0x7B81, 0xB972, 0x7B82, 0xB973, + 0x7B83, 0xB974, 0x7B84, 0xB975, 0x7B85, 0xF3EB, 0x7B86, 0xB976, 0x7B87, 0xB977, 0x7B88, 0xB978, 0x7B89, 0xB979, 0x7B8A, 0xB97A, + 0x7B8B, 0xB97B, 0x7B8C, 0xB97C, 0x7B8D, 0xB9BF, 0x7B8E, 0xB97D, 0x7B8F, 0xB97E, 0x7B90, 0xF3E4, 0x7B91, 0xB980, 0x7B92, 0xB981, + 0x7B93, 0xB982, 0x7B94, 0xB2AD, 0x7B95, 0xBBFE, 0x7B96, 0xB983, 0x7B97, 0xCBE3, 0x7B98, 0xB984, 0x7B99, 0xB985, 0x7B9A, 0xB986, + 0x7B9B, 0xB987, 0x7B9C, 0xF3ED, 0x7B9D, 0xF3E9, 0x7B9E, 0xB988, 0x7B9F, 0xB989, 0x7BA0, 0xB98A, 0x7BA1, 0xB9DC, 0x7BA2, 0xF3EE, + 0x7BA3, 0xB98B, 0x7BA4, 0xB98C, 0x7BA5, 0xB98D, 0x7BA6, 0xF3E5, 0x7BA7, 0xF3E6, 0x7BA8, 0xF3EA, 0x7BA9, 0xC2E1, 0x7BAA, 0xF3EC, + 0x7BAB, 0xF3EF, 0x7BAC, 0xF3E8, 0x7BAD, 0xBCFD, 0x7BAE, 0xB98E, 0x7BAF, 0xB98F, 0x7BB0, 0xB990, 0x7BB1, 0xCFE4, 0x7BB2, 0xB991, + 0x7BB3, 0xB992, 0x7BB4, 0xF3F0, 0x7BB5, 0xB993, 0x7BB6, 0xB994, 0x7BB7, 0xB995, 0x7BB8, 0xF3E7, 0x7BB9, 0xB996, 0x7BBA, 0xB997, + 0x7BBB, 0xB998, 0x7BBC, 0xB999, 0x7BBD, 0xB99A, 0x7BBE, 0xB99B, 0x7BBF, 0xB99C, 0x7BC0, 0xB99D, 0x7BC1, 0xF3F2, 0x7BC2, 0xB99E, + 0x7BC3, 0xB99F, 0x7BC4, 0xB9A0, 0x7BC5, 0xBA40, 0x7BC6, 0xD7AD, 0x7BC7, 0xC6AA, 0x7BC8, 0xBA41, 0x7BC9, 0xBA42, 0x7BCA, 0xBA43, + 0x7BCB, 0xBA44, 0x7BCC, 0xF3F3, 0x7BCD, 0xBA45, 0x7BCE, 0xBA46, 0x7BCF, 0xBA47, 0x7BD0, 0xBA48, 0x7BD1, 0xF3F1, 0x7BD2, 0xBA49, + 0x7BD3, 0xC2A8, 0x7BD4, 0xBA4A, 0x7BD5, 0xBA4B, 0x7BD6, 0xBA4C, 0x7BD7, 0xBA4D, 0x7BD8, 0xBA4E, 0x7BD9, 0xB8DD, 0x7BDA, 0xF3F5, + 0x7BDB, 0xBA4F, 0x7BDC, 0xBA50, 0x7BDD, 0xF3F4, 0x7BDE, 0xBA51, 0x7BDF, 0xBA52, 0x7BE0, 0xBA53, 0x7BE1, 0xB4DB, 0x7BE2, 0xBA54, + 0x7BE3, 0xBA55, 0x7BE4, 0xBA56, 0x7BE5, 0xF3F6, 0x7BE6, 0xF3F7, 0x7BE7, 0xBA57, 0x7BE8, 0xBA58, 0x7BE9, 0xBA59, 0x7BEA, 0xF3F8, + 0x7BEB, 0xBA5A, 0x7BEC, 0xBA5B, 0x7BED, 0xBA5C, 0x7BEE, 0xC0BA, 0x7BEF, 0xBA5D, 0x7BF0, 0xBA5E, 0x7BF1, 0xC0E9, 0x7BF2, 0xBA5F, + 0x7BF3, 0xBA60, 0x7BF4, 0xBA61, 0x7BF5, 0xBA62, 0x7BF6, 0xBA63, 0x7BF7, 0xC5F1, 0x7BF8, 0xBA64, 0x7BF9, 0xBA65, 0x7BFA, 0xBA66, + 0x7BFB, 0xBA67, 0x7BFC, 0xF3FB, 0x7BFD, 0xBA68, 0x7BFE, 0xF3FA, 0x7BFF, 0xBA69, 0x7C00, 0xBA6A, 0x7C01, 0xBA6B, 0x7C02, 0xBA6C, + 0x7C03, 0xBA6D, 0x7C04, 0xBA6E, 0x7C05, 0xBA6F, 0x7C06, 0xBA70, 0x7C07, 0xB4D8, 0x7C08, 0xBA71, 0x7C09, 0xBA72, 0x7C0A, 0xBA73, + 0x7C0B, 0xF3FE, 0x7C0C, 0xF3F9, 0x7C0D, 0xBA74, 0x7C0E, 0xBA75, 0x7C0F, 0xF3FC, 0x7C10, 0xBA76, 0x7C11, 0xBA77, 0x7C12, 0xBA78, + 0x7C13, 0xBA79, 0x7C14, 0xBA7A, 0x7C15, 0xBA7B, 0x7C16, 0xF3FD, 0x7C17, 0xBA7C, 0x7C18, 0xBA7D, 0x7C19, 0xBA7E, 0x7C1A, 0xBA80, + 0x7C1B, 0xBA81, 0x7C1C, 0xBA82, 0x7C1D, 0xBA83, 0x7C1E, 0xBA84, 0x7C1F, 0xF4A1, 0x7C20, 0xBA85, 0x7C21, 0xBA86, 0x7C22, 0xBA87, + 0x7C23, 0xBA88, 0x7C24, 0xBA89, 0x7C25, 0xBA8A, 0x7C26, 0xF4A3, 0x7C27, 0xBBC9, 0x7C28, 0xBA8B, 0x7C29, 0xBA8C, 0x7C2A, 0xF4A2, + 0x7C2B, 0xBA8D, 0x7C2C, 0xBA8E, 0x7C2D, 0xBA8F, 0x7C2E, 0xBA90, 0x7C2F, 0xBA91, 0x7C30, 0xBA92, 0x7C31, 0xBA93, 0x7C32, 0xBA94, + 0x7C33, 0xBA95, 0x7C34, 0xBA96, 0x7C35, 0xBA97, 0x7C36, 0xBA98, 0x7C37, 0xBA99, 0x7C38, 0xF4A4, 0x7C39, 0xBA9A, 0x7C3A, 0xBA9B, + 0x7C3B, 0xBA9C, 0x7C3C, 0xBA9D, 0x7C3D, 0xBA9E, 0x7C3E, 0xBA9F, 0x7C3F, 0xB2BE, 0x7C40, 0xF4A6, 0x7C41, 0xF4A5, 0x7C42, 0xBAA0, + 0x7C43, 0xBB40, 0x7C44, 0xBB41, 0x7C45, 0xBB42, 0x7C46, 0xBB43, 0x7C47, 0xBB44, 0x7C48, 0xBB45, 0x7C49, 0xBB46, 0x7C4A, 0xBB47, + 0x7C4B, 0xBB48, 0x7C4C, 0xBB49, 0x7C4D, 0xBCAE, 0x7C4E, 0xBB4A, 0x7C4F, 0xBB4B, 0x7C50, 0xBB4C, 0x7C51, 0xBB4D, 0x7C52, 0xBB4E, + 0x7C53, 0xBB4F, 0x7C54, 0xBB50, 0x7C55, 0xBB51, 0x7C56, 0xBB52, 0x7C57, 0xBB53, 0x7C58, 0xBB54, 0x7C59, 0xBB55, 0x7C5A, 0xBB56, + 0x7C5B, 0xBB57, 0x7C5C, 0xBB58, 0x7C5D, 0xBB59, 0x7C5E, 0xBB5A, 0x7C5F, 0xBB5B, 0x7C60, 0xBB5C, 0x7C61, 0xBB5D, 0x7C62, 0xBB5E, + 0x7C63, 0xBB5F, 0x7C64, 0xBB60, 0x7C65, 0xBB61, 0x7C66, 0xBB62, 0x7C67, 0xBB63, 0x7C68, 0xBB64, 0x7C69, 0xBB65, 0x7C6A, 0xBB66, + 0x7C6B, 0xBB67, 0x7C6C, 0xBB68, 0x7C6D, 0xBB69, 0x7C6E, 0xBB6A, 0x7C6F, 0xBB6B, 0x7C70, 0xBB6C, 0x7C71, 0xBB6D, 0x7C72, 0xBB6E, + 0x7C73, 0xC3D7, 0x7C74, 0xD9E1, 0x7C75, 0xBB6F, 0x7C76, 0xBB70, 0x7C77, 0xBB71, 0x7C78, 0xBB72, 0x7C79, 0xBB73, 0x7C7A, 0xBB74, + 0x7C7B, 0xC0E0, 0x7C7C, 0xF4CC, 0x7C7D, 0xD7D1, 0x7C7E, 0xBB75, 0x7C7F, 0xBB76, 0x7C80, 0xBB77, 0x7C81, 0xBB78, 0x7C82, 0xBB79, + 0x7C83, 0xBB7A, 0x7C84, 0xBB7B, 0x7C85, 0xBB7C, 0x7C86, 0xBB7D, 0x7C87, 0xBB7E, 0x7C88, 0xBB80, 0x7C89, 0xB7DB, 0x7C8A, 0xBB81, + 0x7C8B, 0xBB82, 0x7C8C, 0xBB83, 0x7C8D, 0xBB84, 0x7C8E, 0xBB85, 0x7C8F, 0xBB86, 0x7C90, 0xBB87, 0x7C91, 0xF4CE, 0x7C92, 0xC1A3, + 0x7C93, 0xBB88, 0x7C94, 0xBB89, 0x7C95, 0xC6C9, 0x7C96, 0xBB8A, 0x7C97, 0xB4D6, 0x7C98, 0xD5B3, 0x7C99, 0xBB8B, 0x7C9A, 0xBB8C, + 0x7C9B, 0xBB8D, 0x7C9C, 0xF4D0, 0x7C9D, 0xF4CF, 0x7C9E, 0xF4D1, 0x7C9F, 0xCBDA, 0x7CA0, 0xBB8E, 0x7CA1, 0xBB8F, 0x7CA2, 0xF4D2, + 0x7CA3, 0xBB90, 0x7CA4, 0xD4C1, 0x7CA5, 0xD6E0, 0x7CA6, 0xBB91, 0x7CA7, 0xBB92, 0x7CA8, 0xBB93, 0x7CA9, 0xBB94, 0x7CAA, 0xB7E0, + 0x7CAB, 0xBB95, 0x7CAC, 0xBB96, 0x7CAD, 0xBB97, 0x7CAE, 0xC1B8, 0x7CAF, 0xBB98, 0x7CB0, 0xBB99, 0x7CB1, 0xC1BB, 0x7CB2, 0xF4D3, + 0x7CB3, 0xBEAC, 0x7CB4, 0xBB9A, 0x7CB5, 0xBB9B, 0x7CB6, 0xBB9C, 0x7CB7, 0xBB9D, 0x7CB8, 0xBB9E, 0x7CB9, 0xB4E2, 0x7CBA, 0xBB9F, + 0x7CBB, 0xBBA0, 0x7CBC, 0xF4D4, 0x7CBD, 0xF4D5, 0x7CBE, 0xBEAB, 0x7CBF, 0xBC40, 0x7CC0, 0xBC41, 0x7CC1, 0xF4D6, 0x7CC2, 0xBC42, + 0x7CC3, 0xBC43, 0x7CC4, 0xBC44, 0x7CC5, 0xF4DB, 0x7CC6, 0xBC45, 0x7CC7, 0xF4D7, 0x7CC8, 0xF4DA, 0x7CC9, 0xBC46, 0x7CCA, 0xBAFD, + 0x7CCB, 0xBC47, 0x7CCC, 0xF4D8, 0x7CCD, 0xF4D9, 0x7CCE, 0xBC48, 0x7CCF, 0xBC49, 0x7CD0, 0xBC4A, 0x7CD1, 0xBC4B, 0x7CD2, 0xBC4C, + 0x7CD3, 0xBC4D, 0x7CD4, 0xBC4E, 0x7CD5, 0xB8E2, 0x7CD6, 0xCCC7, 0x7CD7, 0xF4DC, 0x7CD8, 0xBC4F, 0x7CD9, 0xB2DA, 0x7CDA, 0xBC50, + 0x7CDB, 0xBC51, 0x7CDC, 0xC3D3, 0x7CDD, 0xBC52, 0x7CDE, 0xBC53, 0x7CDF, 0xD4E3, 0x7CE0, 0xBFB7, 0x7CE1, 0xBC54, 0x7CE2, 0xBC55, + 0x7CE3, 0xBC56, 0x7CE4, 0xBC57, 0x7CE5, 0xBC58, 0x7CE6, 0xBC59, 0x7CE7, 0xBC5A, 0x7CE8, 0xF4DD, 0x7CE9, 0xBC5B, 0x7CEA, 0xBC5C, + 0x7CEB, 0xBC5D, 0x7CEC, 0xBC5E, 0x7CED, 0xBC5F, 0x7CEE, 0xBC60, 0x7CEF, 0xC5B4, 0x7CF0, 0xBC61, 0x7CF1, 0xBC62, 0x7CF2, 0xBC63, + 0x7CF3, 0xBC64, 0x7CF4, 0xBC65, 0x7CF5, 0xBC66, 0x7CF6, 0xBC67, 0x7CF7, 0xBC68, 0x7CF8, 0xF4E9, 0x7CF9, 0xBC69, 0x7CFA, 0xBC6A, + 0x7CFB, 0xCFB5, 0x7CFC, 0xBC6B, 0x7CFD, 0xBC6C, 0x7CFE, 0xBC6D, 0x7CFF, 0xBC6E, 0x7D00, 0xBC6F, 0x7D01, 0xBC70, 0x7D02, 0xBC71, + 0x7D03, 0xBC72, 0x7D04, 0xBC73, 0x7D05, 0xBC74, 0x7D06, 0xBC75, 0x7D07, 0xBC76, 0x7D08, 0xBC77, 0x7D09, 0xBC78, 0x7D0A, 0xCEC9, + 0x7D0B, 0xBC79, 0x7D0C, 0xBC7A, 0x7D0D, 0xBC7B, 0x7D0E, 0xBC7C, 0x7D0F, 0xBC7D, 0x7D10, 0xBC7E, 0x7D11, 0xBC80, 0x7D12, 0xBC81, + 0x7D13, 0xBC82, 0x7D14, 0xBC83, 0x7D15, 0xBC84, 0x7D16, 0xBC85, 0x7D17, 0xBC86, 0x7D18, 0xBC87, 0x7D19, 0xBC88, 0x7D1A, 0xBC89, + 0x7D1B, 0xBC8A, 0x7D1C, 0xBC8B, 0x7D1D, 0xBC8C, 0x7D1E, 0xBC8D, 0x7D1F, 0xBC8E, 0x7D20, 0xCBD8, 0x7D21, 0xBC8F, 0x7D22, 0xCBF7, + 0x7D23, 0xBC90, 0x7D24, 0xBC91, 0x7D25, 0xBC92, 0x7D26, 0xBC93, 0x7D27, 0xBDF4, 0x7D28, 0xBC94, 0x7D29, 0xBC95, 0x7D2A, 0xBC96, + 0x7D2B, 0xD7CF, 0x7D2C, 0xBC97, 0x7D2D, 0xBC98, 0x7D2E, 0xBC99, 0x7D2F, 0xC0DB, 0x7D30, 0xBC9A, 0x7D31, 0xBC9B, 0x7D32, 0xBC9C, + 0x7D33, 0xBC9D, 0x7D34, 0xBC9E, 0x7D35, 0xBC9F, 0x7D36, 0xBCA0, 0x7D37, 0xBD40, 0x7D38, 0xBD41, 0x7D39, 0xBD42, 0x7D3A, 0xBD43, + 0x7D3B, 0xBD44, 0x7D3C, 0xBD45, 0x7D3D, 0xBD46, 0x7D3E, 0xBD47, 0x7D3F, 0xBD48, 0x7D40, 0xBD49, 0x7D41, 0xBD4A, 0x7D42, 0xBD4B, + 0x7D43, 0xBD4C, 0x7D44, 0xBD4D, 0x7D45, 0xBD4E, 0x7D46, 0xBD4F, 0x7D47, 0xBD50, 0x7D48, 0xBD51, 0x7D49, 0xBD52, 0x7D4A, 0xBD53, + 0x7D4B, 0xBD54, 0x7D4C, 0xBD55, 0x7D4D, 0xBD56, 0x7D4E, 0xBD57, 0x7D4F, 0xBD58, 0x7D50, 0xBD59, 0x7D51, 0xBD5A, 0x7D52, 0xBD5B, + 0x7D53, 0xBD5C, 0x7D54, 0xBD5D, 0x7D55, 0xBD5E, 0x7D56, 0xBD5F, 0x7D57, 0xBD60, 0x7D58, 0xBD61, 0x7D59, 0xBD62, 0x7D5A, 0xBD63, + 0x7D5B, 0xBD64, 0x7D5C, 0xBD65, 0x7D5D, 0xBD66, 0x7D5E, 0xBD67, 0x7D5F, 0xBD68, 0x7D60, 0xBD69, 0x7D61, 0xBD6A, 0x7D62, 0xBD6B, + 0x7D63, 0xBD6C, 0x7D64, 0xBD6D, 0x7D65, 0xBD6E, 0x7D66, 0xBD6F, 0x7D67, 0xBD70, 0x7D68, 0xBD71, 0x7D69, 0xBD72, 0x7D6A, 0xBD73, + 0x7D6B, 0xBD74, 0x7D6C, 0xBD75, 0x7D6D, 0xBD76, 0x7D6E, 0xD0F5, 0x7D6F, 0xBD77, 0x7D70, 0xBD78, 0x7D71, 0xBD79, 0x7D72, 0xBD7A, + 0x7D73, 0xBD7B, 0x7D74, 0xBD7C, 0x7D75, 0xBD7D, 0x7D76, 0xBD7E, 0x7D77, 0xF4EA, 0x7D78, 0xBD80, 0x7D79, 0xBD81, 0x7D7A, 0xBD82, + 0x7D7B, 0xBD83, 0x7D7C, 0xBD84, 0x7D7D, 0xBD85, 0x7D7E, 0xBD86, 0x7D7F, 0xBD87, 0x7D80, 0xBD88, 0x7D81, 0xBD89, 0x7D82, 0xBD8A, + 0x7D83, 0xBD8B, 0x7D84, 0xBD8C, 0x7D85, 0xBD8D, 0x7D86, 0xBD8E, 0x7D87, 0xBD8F, 0x7D88, 0xBD90, 0x7D89, 0xBD91, 0x7D8A, 0xBD92, + 0x7D8B, 0xBD93, 0x7D8C, 0xBD94, 0x7D8D, 0xBD95, 0x7D8E, 0xBD96, 0x7D8F, 0xBD97, 0x7D90, 0xBD98, 0x7D91, 0xBD99, 0x7D92, 0xBD9A, + 0x7D93, 0xBD9B, 0x7D94, 0xBD9C, 0x7D95, 0xBD9D, 0x7D96, 0xBD9E, 0x7D97, 0xBD9F, 0x7D98, 0xBDA0, 0x7D99, 0xBE40, 0x7D9A, 0xBE41, + 0x7D9B, 0xBE42, 0x7D9C, 0xBE43, 0x7D9D, 0xBE44, 0x7D9E, 0xBE45, 0x7D9F, 0xBE46, 0x7DA0, 0xBE47, 0x7DA1, 0xBE48, 0x7DA2, 0xBE49, + 0x7DA3, 0xBE4A, 0x7DA4, 0xBE4B, 0x7DA5, 0xBE4C, 0x7DA6, 0xF4EB, 0x7DA7, 0xBE4D, 0x7DA8, 0xBE4E, 0x7DA9, 0xBE4F, 0x7DAA, 0xBE50, + 0x7DAB, 0xBE51, 0x7DAC, 0xBE52, 0x7DAD, 0xBE53, 0x7DAE, 0xF4EC, 0x7DAF, 0xBE54, 0x7DB0, 0xBE55, 0x7DB1, 0xBE56, 0x7DB2, 0xBE57, + 0x7DB3, 0xBE58, 0x7DB4, 0xBE59, 0x7DB5, 0xBE5A, 0x7DB6, 0xBE5B, 0x7DB7, 0xBE5C, 0x7DB8, 0xBE5D, 0x7DB9, 0xBE5E, 0x7DBA, 0xBE5F, + 0x7DBB, 0xBE60, 0x7DBC, 0xBE61, 0x7DBD, 0xBE62, 0x7DBE, 0xBE63, 0x7DBF, 0xBE64, 0x7DC0, 0xBE65, 0x7DC1, 0xBE66, 0x7DC2, 0xBE67, + 0x7DC3, 0xBE68, 0x7DC4, 0xBE69, 0x7DC5, 0xBE6A, 0x7DC6, 0xBE6B, 0x7DC7, 0xBE6C, 0x7DC8, 0xBE6D, 0x7DC9, 0xBE6E, 0x7DCA, 0xBE6F, + 0x7DCB, 0xBE70, 0x7DCC, 0xBE71, 0x7DCD, 0xBE72, 0x7DCE, 0xBE73, 0x7DCF, 0xBE74, 0x7DD0, 0xBE75, 0x7DD1, 0xBE76, 0x7DD2, 0xBE77, + 0x7DD3, 0xBE78, 0x7DD4, 0xBE79, 0x7DD5, 0xBE7A, 0x7DD6, 0xBE7B, 0x7DD7, 0xBE7C, 0x7DD8, 0xBE7D, 0x7DD9, 0xBE7E, 0x7DDA, 0xBE80, + 0x7DDB, 0xBE81, 0x7DDC, 0xBE82, 0x7DDD, 0xBE83, 0x7DDE, 0xBE84, 0x7DDF, 0xBE85, 0x7DE0, 0xBE86, 0x7DE1, 0xBE87, 0x7DE2, 0xBE88, + 0x7DE3, 0xBE89, 0x7DE4, 0xBE8A, 0x7DE5, 0xBE8B, 0x7DE6, 0xBE8C, 0x7DE7, 0xBE8D, 0x7DE8, 0xBE8E, 0x7DE9, 0xBE8F, 0x7DEA, 0xBE90, + 0x7DEB, 0xBE91, 0x7DEC, 0xBE92, 0x7DED, 0xBE93, 0x7DEE, 0xBE94, 0x7DEF, 0xBE95, 0x7DF0, 0xBE96, 0x7DF1, 0xBE97, 0x7DF2, 0xBE98, + 0x7DF3, 0xBE99, 0x7DF4, 0xBE9A, 0x7DF5, 0xBE9B, 0x7DF6, 0xBE9C, 0x7DF7, 0xBE9D, 0x7DF8, 0xBE9E, 0x7DF9, 0xBE9F, 0x7DFA, 0xBEA0, + 0x7DFB, 0xBF40, 0x7DFC, 0xBF41, 0x7DFD, 0xBF42, 0x7DFE, 0xBF43, 0x7DFF, 0xBF44, 0x7E00, 0xBF45, 0x7E01, 0xBF46, 0x7E02, 0xBF47, + 0x7E03, 0xBF48, 0x7E04, 0xBF49, 0x7E05, 0xBF4A, 0x7E06, 0xBF4B, 0x7E07, 0xBF4C, 0x7E08, 0xBF4D, 0x7E09, 0xBF4E, 0x7E0A, 0xBF4F, + 0x7E0B, 0xBF50, 0x7E0C, 0xBF51, 0x7E0D, 0xBF52, 0x7E0E, 0xBF53, 0x7E0F, 0xBF54, 0x7E10, 0xBF55, 0x7E11, 0xBF56, 0x7E12, 0xBF57, + 0x7E13, 0xBF58, 0x7E14, 0xBF59, 0x7E15, 0xBF5A, 0x7E16, 0xBF5B, 0x7E17, 0xBF5C, 0x7E18, 0xBF5D, 0x7E19, 0xBF5E, 0x7E1A, 0xBF5F, + 0x7E1B, 0xBF60, 0x7E1C, 0xBF61, 0x7E1D, 0xBF62, 0x7E1E, 0xBF63, 0x7E1F, 0xBF64, 0x7E20, 0xBF65, 0x7E21, 0xBF66, 0x7E22, 0xBF67, + 0x7E23, 0xBF68, 0x7E24, 0xBF69, 0x7E25, 0xBF6A, 0x7E26, 0xBF6B, 0x7E27, 0xBF6C, 0x7E28, 0xBF6D, 0x7E29, 0xBF6E, 0x7E2A, 0xBF6F, + 0x7E2B, 0xBF70, 0x7E2C, 0xBF71, 0x7E2D, 0xBF72, 0x7E2E, 0xBF73, 0x7E2F, 0xBF74, 0x7E30, 0xBF75, 0x7E31, 0xBF76, 0x7E32, 0xBF77, + 0x7E33, 0xBF78, 0x7E34, 0xBF79, 0x7E35, 0xBF7A, 0x7E36, 0xBF7B, 0x7E37, 0xBF7C, 0x7E38, 0xBF7D, 0x7E39, 0xBF7E, 0x7E3A, 0xBF80, + 0x7E3B, 0xF7E3, 0x7E3C, 0xBF81, 0x7E3D, 0xBF82, 0x7E3E, 0xBF83, 0x7E3F, 0xBF84, 0x7E40, 0xBF85, 0x7E41, 0xB7B1, 0x7E42, 0xBF86, + 0x7E43, 0xBF87, 0x7E44, 0xBF88, 0x7E45, 0xBF89, 0x7E46, 0xBF8A, 0x7E47, 0xF4ED, 0x7E48, 0xBF8B, 0x7E49, 0xBF8C, 0x7E4A, 0xBF8D, + 0x7E4B, 0xBF8E, 0x7E4C, 0xBF8F, 0x7E4D, 0xBF90, 0x7E4E, 0xBF91, 0x7E4F, 0xBF92, 0x7E50, 0xBF93, 0x7E51, 0xBF94, 0x7E52, 0xBF95, + 0x7E53, 0xBF96, 0x7E54, 0xBF97, 0x7E55, 0xBF98, 0x7E56, 0xBF99, 0x7E57, 0xBF9A, 0x7E58, 0xBF9B, 0x7E59, 0xBF9C, 0x7E5A, 0xBF9D, + 0x7E5B, 0xBF9E, 0x7E5C, 0xBF9F, 0x7E5D, 0xBFA0, 0x7E5E, 0xC040, 0x7E5F, 0xC041, 0x7E60, 0xC042, 0x7E61, 0xC043, 0x7E62, 0xC044, + 0x7E63, 0xC045, 0x7E64, 0xC046, 0x7E65, 0xC047, 0x7E66, 0xC048, 0x7E67, 0xC049, 0x7E68, 0xC04A, 0x7E69, 0xC04B, 0x7E6A, 0xC04C, + 0x7E6B, 0xC04D, 0x7E6C, 0xC04E, 0x7E6D, 0xC04F, 0x7E6E, 0xC050, 0x7E6F, 0xC051, 0x7E70, 0xC052, 0x7E71, 0xC053, 0x7E72, 0xC054, + 0x7E73, 0xC055, 0x7E74, 0xC056, 0x7E75, 0xC057, 0x7E76, 0xC058, 0x7E77, 0xC059, 0x7E78, 0xC05A, 0x7E79, 0xC05B, 0x7E7A, 0xC05C, + 0x7E7B, 0xC05D, 0x7E7C, 0xC05E, 0x7E7D, 0xC05F, 0x7E7E, 0xC060, 0x7E7F, 0xC061, 0x7E80, 0xC062, 0x7E81, 0xC063, 0x7E82, 0xD7EB, + 0x7E83, 0xC064, 0x7E84, 0xC065, 0x7E85, 0xC066, 0x7E86, 0xC067, 0x7E87, 0xC068, 0x7E88, 0xC069, 0x7E89, 0xC06A, 0x7E8A, 0xC06B, + 0x7E8B, 0xC06C, 0x7E8C, 0xC06D, 0x7E8D, 0xC06E, 0x7E8E, 0xC06F, 0x7E8F, 0xC070, 0x7E90, 0xC071, 0x7E91, 0xC072, 0x7E92, 0xC073, + 0x7E93, 0xC074, 0x7E94, 0xC075, 0x7E95, 0xC076, 0x7E96, 0xC077, 0x7E97, 0xC078, 0x7E98, 0xC079, 0x7E99, 0xC07A, 0x7E9A, 0xC07B, + 0x7E9B, 0xF4EE, 0x7E9C, 0xC07C, 0x7E9D, 0xC07D, 0x7E9E, 0xC07E, 0x7E9F, 0xE6F9, 0x7EA0, 0xBEC0, 0x7EA1, 0xE6FA, 0x7EA2, 0xBAEC, + 0x7EA3, 0xE6FB, 0x7EA4, 0xCFCB, 0x7EA5, 0xE6FC, 0x7EA6, 0xD4BC, 0x7EA7, 0xBCB6, 0x7EA8, 0xE6FD, 0x7EA9, 0xE6FE, 0x7EAA, 0xBCCD, + 0x7EAB, 0xC8D2, 0x7EAC, 0xCEB3, 0x7EAD, 0xE7A1, 0x7EAE, 0xC080, 0x7EAF, 0xB4BF, 0x7EB0, 0xE7A2, 0x7EB1, 0xC9B4, 0x7EB2, 0xB8D9, + 0x7EB3, 0xC4C9, 0x7EB4, 0xC081, 0x7EB5, 0xD7DD, 0x7EB6, 0xC2DA, 0x7EB7, 0xB7D7, 0x7EB8, 0xD6BD, 0x7EB9, 0xCEC6, 0x7EBA, 0xB7C4, + 0x7EBB, 0xC082, 0x7EBC, 0xC083, 0x7EBD, 0xC5A6, 0x7EBE, 0xE7A3, 0x7EBF, 0xCFDF, 0x7EC0, 0xE7A4, 0x7EC1, 0xE7A5, 0x7EC2, 0xE7A6, + 0x7EC3, 0xC1B7, 0x7EC4, 0xD7E9, 0x7EC5, 0xC9F0, 0x7EC6, 0xCFB8, 0x7EC7, 0xD6AF, 0x7EC8, 0xD6D5, 0x7EC9, 0xE7A7, 0x7ECA, 0xB0ED, + 0x7ECB, 0xE7A8, 0x7ECC, 0xE7A9, 0x7ECD, 0xC9DC, 0x7ECE, 0xD2EF, 0x7ECF, 0xBEAD, 0x7ED0, 0xE7AA, 0x7ED1, 0xB0F3, 0x7ED2, 0xC8DE, + 0x7ED3, 0xBDE1, 0x7ED4, 0xE7AB, 0x7ED5, 0xC8C6, 0x7ED6, 0xC084, 0x7ED7, 0xE7AC, 0x7ED8, 0xBBE6, 0x7ED9, 0xB8F8, 0x7EDA, 0xD1A4, + 0x7EDB, 0xE7AD, 0x7EDC, 0xC2E7, 0x7EDD, 0xBEF8, 0x7EDE, 0xBDCA, 0x7EDF, 0xCDB3, 0x7EE0, 0xE7AE, 0x7EE1, 0xE7AF, 0x7EE2, 0xBEEE, + 0x7EE3, 0xD0E5, 0x7EE4, 0xC085, 0x7EE5, 0xCBE7, 0x7EE6, 0xCCD0, 0x7EE7, 0xBCCC, 0x7EE8, 0xE7B0, 0x7EE9, 0xBCA8, 0x7EEA, 0xD0F7, + 0x7EEB, 0xE7B1, 0x7EEC, 0xC086, 0x7EED, 0xD0F8, 0x7EEE, 0xE7B2, 0x7EEF, 0xE7B3, 0x7EF0, 0xB4C2, 0x7EF1, 0xE7B4, 0x7EF2, 0xE7B5, + 0x7EF3, 0xC9FE, 0x7EF4, 0xCEAC, 0x7EF5, 0xC3E0, 0x7EF6, 0xE7B7, 0x7EF7, 0xB1C1, 0x7EF8, 0xB3F1, 0x7EF9, 0xC087, 0x7EFA, 0xE7B8, + 0x7EFB, 0xE7B9, 0x7EFC, 0xD7DB, 0x7EFD, 0xD5C0, 0x7EFE, 0xE7BA, 0x7EFF, 0xC2CC, 0x7F00, 0xD7BA, 0x7F01, 0xE7BB, 0x7F02, 0xE7BC, + 0x7F03, 0xE7BD, 0x7F04, 0xBCEA, 0x7F05, 0xC3E5, 0x7F06, 0xC0C2, 0x7F07, 0xE7BE, 0x7F08, 0xE7BF, 0x7F09, 0xBCA9, 0x7F0A, 0xC088, + 0x7F0B, 0xE7C0, 0x7F0C, 0xE7C1, 0x7F0D, 0xE7B6, 0x7F0E, 0xB6D0, 0x7F0F, 0xE7C2, 0x7F10, 0xC089, 0x7F11, 0xE7C3, 0x7F12, 0xE7C4, + 0x7F13, 0xBBBA, 0x7F14, 0xB5DE, 0x7F15, 0xC2C6, 0x7F16, 0xB1E0, 0x7F17, 0xE7C5, 0x7F18, 0xD4B5, 0x7F19, 0xE7C6, 0x7F1A, 0xB8BF, + 0x7F1B, 0xE7C8, 0x7F1C, 0xE7C7, 0x7F1D, 0xB7EC, 0x7F1E, 0xC08A, 0x7F1F, 0xE7C9, 0x7F20, 0xB2F8, 0x7F21, 0xE7CA, 0x7F22, 0xE7CB, + 0x7F23, 0xE7CC, 0x7F24, 0xE7CD, 0x7F25, 0xE7CE, 0x7F26, 0xE7CF, 0x7F27, 0xE7D0, 0x7F28, 0xD3A7, 0x7F29, 0xCBF5, 0x7F2A, 0xE7D1, + 0x7F2B, 0xE7D2, 0x7F2C, 0xE7D3, 0x7F2D, 0xE7D4, 0x7F2E, 0xC9C9, 0x7F2F, 0xE7D5, 0x7F30, 0xE7D6, 0x7F31, 0xE7D7, 0x7F32, 0xE7D8, + 0x7F33, 0xE7D9, 0x7F34, 0xBDC9, 0x7F35, 0xE7DA, 0x7F36, 0xF3BE, 0x7F37, 0xC08B, 0x7F38, 0xB8D7, 0x7F39, 0xC08C, 0x7F3A, 0xC8B1, + 0x7F3B, 0xC08D, 0x7F3C, 0xC08E, 0x7F3D, 0xC08F, 0x7F3E, 0xC090, 0x7F3F, 0xC091, 0x7F40, 0xC092, 0x7F41, 0xC093, 0x7F42, 0xF3BF, + 0x7F43, 0xC094, 0x7F44, 0xF3C0, 0x7F45, 0xF3C1, 0x7F46, 0xC095, 0x7F47, 0xC096, 0x7F48, 0xC097, 0x7F49, 0xC098, 0x7F4A, 0xC099, + 0x7F4B, 0xC09A, 0x7F4C, 0xC09B, 0x7F4D, 0xC09C, 0x7F4E, 0xC09D, 0x7F4F, 0xC09E, 0x7F50, 0xB9DE, 0x7F51, 0xCDF8, 0x7F52, 0xC09F, + 0x7F53, 0xC0A0, 0x7F54, 0xD8E8, 0x7F55, 0xBAB1, 0x7F56, 0xC140, 0x7F57, 0xC2DE, 0x7F58, 0xEEB7, 0x7F59, 0xC141, 0x7F5A, 0xB7A3, + 0x7F5B, 0xC142, 0x7F5C, 0xC143, 0x7F5D, 0xC144, 0x7F5E, 0xC145, 0x7F5F, 0xEEB9, 0x7F60, 0xC146, 0x7F61, 0xEEB8, 0x7F62, 0xB0D5, + 0x7F63, 0xC147, 0x7F64, 0xC148, 0x7F65, 0xC149, 0x7F66, 0xC14A, 0x7F67, 0xC14B, 0x7F68, 0xEEBB, 0x7F69, 0xD5D6, 0x7F6A, 0xD7EF, + 0x7F6B, 0xC14C, 0x7F6C, 0xC14D, 0x7F6D, 0xC14E, 0x7F6E, 0xD6C3, 0x7F6F, 0xC14F, 0x7F70, 0xC150, 0x7F71, 0xEEBD, 0x7F72, 0xCAF0, + 0x7F73, 0xC151, 0x7F74, 0xEEBC, 0x7F75, 0xC152, 0x7F76, 0xC153, 0x7F77, 0xC154, 0x7F78, 0xC155, 0x7F79, 0xEEBE, 0x7F7A, 0xC156, + 0x7F7B, 0xC157, 0x7F7C, 0xC158, 0x7F7D, 0xC159, 0x7F7E, 0xEEC0, 0x7F7F, 0xC15A, 0x7F80, 0xC15B, 0x7F81, 0xEEBF, 0x7F82, 0xC15C, + 0x7F83, 0xC15D, 0x7F84, 0xC15E, 0x7F85, 0xC15F, 0x7F86, 0xC160, 0x7F87, 0xC161, 0x7F88, 0xC162, 0x7F89, 0xC163, 0x7F8A, 0xD1F2, + 0x7F8B, 0xC164, 0x7F8C, 0xC7BC, 0x7F8D, 0xC165, 0x7F8E, 0xC3C0, 0x7F8F, 0xC166, 0x7F90, 0xC167, 0x7F91, 0xC168, 0x7F92, 0xC169, + 0x7F93, 0xC16A, 0x7F94, 0xB8E1, 0x7F95, 0xC16B, 0x7F96, 0xC16C, 0x7F97, 0xC16D, 0x7F98, 0xC16E, 0x7F99, 0xC16F, 0x7F9A, 0xC1E7, + 0x7F9B, 0xC170, 0x7F9C, 0xC171, 0x7F9D, 0xF4C6, 0x7F9E, 0xD0DF, 0x7F9F, 0xF4C7, 0x7FA0, 0xC172, 0x7FA1, 0xCFDB, 0x7FA2, 0xC173, + 0x7FA3, 0xC174, 0x7FA4, 0xC8BA, 0x7FA5, 0xC175, 0x7FA6, 0xC176, 0x7FA7, 0xF4C8, 0x7FA8, 0xC177, 0x7FA9, 0xC178, 0x7FAA, 0xC179, + 0x7FAB, 0xC17A, 0x7FAC, 0xC17B, 0x7FAD, 0xC17C, 0x7FAE, 0xC17D, 0x7FAF, 0xF4C9, 0x7FB0, 0xF4CA, 0x7FB1, 0xC17E, 0x7FB2, 0xF4CB, + 0x7FB3, 0xC180, 0x7FB4, 0xC181, 0x7FB5, 0xC182, 0x7FB6, 0xC183, 0x7FB7, 0xC184, 0x7FB8, 0xD9FA, 0x7FB9, 0xB8FE, 0x7FBA, 0xC185, + 0x7FBB, 0xC186, 0x7FBC, 0xE5F1, 0x7FBD, 0xD3F0, 0x7FBE, 0xC187, 0x7FBF, 0xF4E0, 0x7FC0, 0xC188, 0x7FC1, 0xCECC, 0x7FC2, 0xC189, + 0x7FC3, 0xC18A, 0x7FC4, 0xC18B, 0x7FC5, 0xB3E1, 0x7FC6, 0xC18C, 0x7FC7, 0xC18D, 0x7FC8, 0xC18E, 0x7FC9, 0xC18F, 0x7FCA, 0xF1B4, + 0x7FCB, 0xC190, 0x7FCC, 0xD2EE, 0x7FCD, 0xC191, 0x7FCE, 0xF4E1, 0x7FCF, 0xC192, 0x7FD0, 0xC193, 0x7FD1, 0xC194, 0x7FD2, 0xC195, + 0x7FD3, 0xC196, 0x7FD4, 0xCFE8, 0x7FD5, 0xF4E2, 0x7FD6, 0xC197, 0x7FD7, 0xC198, 0x7FD8, 0xC7CC, 0x7FD9, 0xC199, 0x7FDA, 0xC19A, + 0x7FDB, 0xC19B, 0x7FDC, 0xC19C, 0x7FDD, 0xC19D, 0x7FDE, 0xC19E, 0x7FDF, 0xB5D4, 0x7FE0, 0xB4E4, 0x7FE1, 0xF4E4, 0x7FE2, 0xC19F, + 0x7FE3, 0xC1A0, 0x7FE4, 0xC240, 0x7FE5, 0xF4E3, 0x7FE6, 0xF4E5, 0x7FE7, 0xC241, 0x7FE8, 0xC242, 0x7FE9, 0xF4E6, 0x7FEA, 0xC243, + 0x7FEB, 0xC244, 0x7FEC, 0xC245, 0x7FED, 0xC246, 0x7FEE, 0xF4E7, 0x7FEF, 0xC247, 0x7FF0, 0xBAB2, 0x7FF1, 0xB0BF, 0x7FF2, 0xC248, + 0x7FF3, 0xF4E8, 0x7FF4, 0xC249, 0x7FF5, 0xC24A, 0x7FF6, 0xC24B, 0x7FF7, 0xC24C, 0x7FF8, 0xC24D, 0x7FF9, 0xC24E, 0x7FFA, 0xC24F, + 0x7FFB, 0xB7AD, 0x7FFC, 0xD2ED, 0x7FFD, 0xC250, 0x7FFE, 0xC251, 0x7FFF, 0xC252, 0x8000, 0xD2AB, 0x8001, 0xC0CF, 0x8002, 0xC253, + 0x8003, 0xBFBC, 0x8004, 0xEBA3, 0x8005, 0xD5DF, 0x8006, 0xEAC8, 0x8007, 0xC254, 0x8008, 0xC255, 0x8009, 0xC256, 0x800A, 0xC257, + 0x800B, 0xF1F3, 0x800C, 0xB6F8, 0x800D, 0xCBA3, 0x800E, 0xC258, 0x800F, 0xC259, 0x8010, 0xC4CD, 0x8011, 0xC25A, 0x8012, 0xF1E7, + 0x8013, 0xC25B, 0x8014, 0xF1E8, 0x8015, 0xB8FB, 0x8016, 0xF1E9, 0x8017, 0xBAC4, 0x8018, 0xD4C5, 0x8019, 0xB0D2, 0x801A, 0xC25C, + 0x801B, 0xC25D, 0x801C, 0xF1EA, 0x801D, 0xC25E, 0x801E, 0xC25F, 0x801F, 0xC260, 0x8020, 0xF1EB, 0x8021, 0xC261, 0x8022, 0xF1EC, + 0x8023, 0xC262, 0x8024, 0xC263, 0x8025, 0xF1ED, 0x8026, 0xF1EE, 0x8027, 0xF1EF, 0x8028, 0xF1F1, 0x8029, 0xF1F0, 0x802A, 0xC5D5, + 0x802B, 0xC264, 0x802C, 0xC265, 0x802D, 0xC266, 0x802E, 0xC267, 0x802F, 0xC268, 0x8030, 0xC269, 0x8031, 0xF1F2, 0x8032, 0xC26A, + 0x8033, 0xB6FA, 0x8034, 0xC26B, 0x8035, 0xF1F4, 0x8036, 0xD2AE, 0x8037, 0xDEC7, 0x8038, 0xCBCA, 0x8039, 0xC26C, 0x803A, 0xC26D, + 0x803B, 0xB3DC, 0x803C, 0xC26E, 0x803D, 0xB5A2, 0x803E, 0xC26F, 0x803F, 0xB9A2, 0x8040, 0xC270, 0x8041, 0xC271, 0x8042, 0xC4F4, + 0x8043, 0xF1F5, 0x8044, 0xC272, 0x8045, 0xC273, 0x8046, 0xF1F6, 0x8047, 0xC274, 0x8048, 0xC275, 0x8049, 0xC276, 0x804A, 0xC1C4, + 0x804B, 0xC1FB, 0x804C, 0xD6B0, 0x804D, 0xF1F7, 0x804E, 0xC277, 0x804F, 0xC278, 0x8050, 0xC279, 0x8051, 0xC27A, 0x8052, 0xF1F8, + 0x8053, 0xC27B, 0x8054, 0xC1AA, 0x8055, 0xC27C, 0x8056, 0xC27D, 0x8057, 0xC27E, 0x8058, 0xC6B8, 0x8059, 0xC280, 0x805A, 0xBEDB, + 0x805B, 0xC281, 0x805C, 0xC282, 0x805D, 0xC283, 0x805E, 0xC284, 0x805F, 0xC285, 0x8060, 0xC286, 0x8061, 0xC287, 0x8062, 0xC288, + 0x8063, 0xC289, 0x8064, 0xC28A, 0x8065, 0xC28B, 0x8066, 0xC28C, 0x8067, 0xC28D, 0x8068, 0xC28E, 0x8069, 0xF1F9, 0x806A, 0xB4CF, + 0x806B, 0xC28F, 0x806C, 0xC290, 0x806D, 0xC291, 0x806E, 0xC292, 0x806F, 0xC293, 0x8070, 0xC294, 0x8071, 0xF1FA, 0x8072, 0xC295, + 0x8073, 0xC296, 0x8074, 0xC297, 0x8075, 0xC298, 0x8076, 0xC299, 0x8077, 0xC29A, 0x8078, 0xC29B, 0x8079, 0xC29C, 0x807A, 0xC29D, + 0x807B, 0xC29E, 0x807C, 0xC29F, 0x807D, 0xC2A0, 0x807E, 0xC340, 0x807F, 0xEDB2, 0x8080, 0xEDB1, 0x8081, 0xC341, 0x8082, 0xC342, + 0x8083, 0xCBE0, 0x8084, 0xD2DE, 0x8085, 0xC343, 0x8086, 0xCBC1, 0x8087, 0xD5D8, 0x8088, 0xC344, 0x8089, 0xC8E2, 0x808A, 0xC345, + 0x808B, 0xC0DF, 0x808C, 0xBCA1, 0x808D, 0xC346, 0x808E, 0xC347, 0x808F, 0xC348, 0x8090, 0xC349, 0x8091, 0xC34A, 0x8092, 0xC34B, + 0x8093, 0xEBC1, 0x8094, 0xC34C, 0x8095, 0xC34D, 0x8096, 0xD0A4, 0x8097, 0xC34E, 0x8098, 0xD6E2, 0x8099, 0xC34F, 0x809A, 0xB6C7, + 0x809B, 0xB8D8, 0x809C, 0xEBC0, 0x809D, 0xB8CE, 0x809E, 0xC350, 0x809F, 0xEBBF, 0x80A0, 0xB3A6, 0x80A1, 0xB9C9, 0x80A2, 0xD6AB, + 0x80A3, 0xC351, 0x80A4, 0xB7F4, 0x80A5, 0xB7CA, 0x80A6, 0xC352, 0x80A7, 0xC353, 0x80A8, 0xC354, 0x80A9, 0xBCE7, 0x80AA, 0xB7BE, + 0x80AB, 0xEBC6, 0x80AC, 0xC355, 0x80AD, 0xEBC7, 0x80AE, 0xB0B9, 0x80AF, 0xBFCF, 0x80B0, 0xC356, 0x80B1, 0xEBC5, 0x80B2, 0xD3FD, + 0x80B3, 0xC357, 0x80B4, 0xEBC8, 0x80B5, 0xC358, 0x80B6, 0xC359, 0x80B7, 0xEBC9, 0x80B8, 0xC35A, 0x80B9, 0xC35B, 0x80BA, 0xB7CE, + 0x80BB, 0xC35C, 0x80BC, 0xEBC2, 0x80BD, 0xEBC4, 0x80BE, 0xC9F6, 0x80BF, 0xD6D7, 0x80C0, 0xD5CD, 0x80C1, 0xD0B2, 0x80C2, 0xEBCF, + 0x80C3, 0xCEB8, 0x80C4, 0xEBD0, 0x80C5, 0xC35D, 0x80C6, 0xB5A8, 0x80C7, 0xC35E, 0x80C8, 0xC35F, 0x80C9, 0xC360, 0x80CA, 0xC361, + 0x80CB, 0xC362, 0x80CC, 0xB1B3, 0x80CD, 0xEBD2, 0x80CE, 0xCCA5, 0x80CF, 0xC363, 0x80D0, 0xC364, 0x80D1, 0xC365, 0x80D2, 0xC366, + 0x80D3, 0xC367, 0x80D4, 0xC368, 0x80D5, 0xC369, 0x80D6, 0xC5D6, 0x80D7, 0xEBD3, 0x80D8, 0xC36A, 0x80D9, 0xEBD1, 0x80DA, 0xC5DF, + 0x80DB, 0xEBCE, 0x80DC, 0xCAA4, 0x80DD, 0xEBD5, 0x80DE, 0xB0FB, 0x80DF, 0xC36B, 0x80E0, 0xC36C, 0x80E1, 0xBAFA, 0x80E2, 0xC36D, + 0x80E3, 0xC36E, 0x80E4, 0xD8B7, 0x80E5, 0xF1E3, 0x80E6, 0xC36F, 0x80E7, 0xEBCA, 0x80E8, 0xEBCB, 0x80E9, 0xEBCC, 0x80EA, 0xEBCD, + 0x80EB, 0xEBD6, 0x80EC, 0xE6C0, 0x80ED, 0xEBD9, 0x80EE, 0xC370, 0x80EF, 0xBFE8, 0x80F0, 0xD2C8, 0x80F1, 0xEBD7, 0x80F2, 0xEBDC, + 0x80F3, 0xB8EC, 0x80F4, 0xEBD8, 0x80F5, 0xC371, 0x80F6, 0xBDBA, 0x80F7, 0xC372, 0x80F8, 0xD0D8, 0x80F9, 0xC373, 0x80FA, 0xB0B7, + 0x80FB, 0xC374, 0x80FC, 0xEBDD, 0x80FD, 0xC4DC, 0x80FE, 0xC375, 0x80FF, 0xC376, 0x8100, 0xC377, 0x8101, 0xC378, 0x8102, 0xD6AC, + 0x8103, 0xC379, 0x8104, 0xC37A, 0x8105, 0xC37B, 0x8106, 0xB4E0, 0x8107, 0xC37C, 0x8108, 0xC37D, 0x8109, 0xC2F6, 0x810A, 0xBCB9, + 0x810B, 0xC37E, 0x810C, 0xC380, 0x810D, 0xEBDA, 0x810E, 0xEBDB, 0x810F, 0xD4E0, 0x8110, 0xC6EA, 0x8111, 0xC4D4, 0x8112, 0xEBDF, + 0x8113, 0xC5A7, 0x8114, 0xD9F5, 0x8115, 0xC381, 0x8116, 0xB2B1, 0x8117, 0xC382, 0x8118, 0xEBE4, 0x8119, 0xC383, 0x811A, 0xBDC5, + 0x811B, 0xC384, 0x811C, 0xC385, 0x811D, 0xC386, 0x811E, 0xEBE2, 0x811F, 0xC387, 0x8120, 0xC388, 0x8121, 0xC389, 0x8122, 0xC38A, + 0x8123, 0xC38B, 0x8124, 0xC38C, 0x8125, 0xC38D, 0x8126, 0xC38E, 0x8127, 0xC38F, 0x8128, 0xC390, 0x8129, 0xC391, 0x812A, 0xC392, + 0x812B, 0xC393, 0x812C, 0xEBE3, 0x812D, 0xC394, 0x812E, 0xC395, 0x812F, 0xB8AC, 0x8130, 0xC396, 0x8131, 0xCDD1, 0x8132, 0xEBE5, + 0x8133, 0xC397, 0x8134, 0xC398, 0x8135, 0xC399, 0x8136, 0xEBE1, 0x8137, 0xC39A, 0x8138, 0xC1B3, 0x8139, 0xC39B, 0x813A, 0xC39C, + 0x813B, 0xC39D, 0x813C, 0xC39E, 0x813D, 0xC39F, 0x813E, 0xC6A2, 0x813F, 0xC3A0, 0x8140, 0xC440, 0x8141, 0xC441, 0x8142, 0xC442, + 0x8143, 0xC443, 0x8144, 0xC444, 0x8145, 0xC445, 0x8146, 0xCCF3, 0x8147, 0xC446, 0x8148, 0xEBE6, 0x8149, 0xC447, 0x814A, 0xC0B0, + 0x814B, 0xD2B8, 0x814C, 0xEBE7, 0x814D, 0xC448, 0x814E, 0xC449, 0x814F, 0xC44A, 0x8150, 0xB8AF, 0x8151, 0xB8AD, 0x8152, 0xC44B, + 0x8153, 0xEBE8, 0x8154, 0xC7BB, 0x8155, 0xCDF3, 0x8156, 0xC44C, 0x8157, 0xC44D, 0x8158, 0xC44E, 0x8159, 0xEBEA, 0x815A, 0xEBEB, + 0x815B, 0xC44F, 0x815C, 0xC450, 0x815D, 0xC451, 0x815E, 0xC452, 0x815F, 0xC453, 0x8160, 0xEBED, 0x8161, 0xC454, 0x8162, 0xC455, + 0x8163, 0xC456, 0x8164, 0xC457, 0x8165, 0xD0C8, 0x8166, 0xC458, 0x8167, 0xEBF2, 0x8168, 0xC459, 0x8169, 0xEBEE, 0x816A, 0xC45A, + 0x816B, 0xC45B, 0x816C, 0xC45C, 0x816D, 0xEBF1, 0x816E, 0xC8F9, 0x816F, 0xC45D, 0x8170, 0xD1FC, 0x8171, 0xEBEC, 0x8172, 0xC45E, + 0x8173, 0xC45F, 0x8174, 0xEBE9, 0x8175, 0xC460, 0x8176, 0xC461, 0x8177, 0xC462, 0x8178, 0xC463, 0x8179, 0xB8B9, 0x817A, 0xCFD9, + 0x817B, 0xC4E5, 0x817C, 0xEBEF, 0x817D, 0xEBF0, 0x817E, 0xCCDA, 0x817F, 0xCDC8, 0x8180, 0xB0F2, 0x8181, 0xC464, 0x8182, 0xEBF6, + 0x8183, 0xC465, 0x8184, 0xC466, 0x8185, 0xC467, 0x8186, 0xC468, 0x8187, 0xC469, 0x8188, 0xEBF5, 0x8189, 0xC46A, 0x818A, 0xB2B2, + 0x818B, 0xC46B, 0x818C, 0xC46C, 0x818D, 0xC46D, 0x818E, 0xC46E, 0x818F, 0xB8E0, 0x8190, 0xC46F, 0x8191, 0xEBF7, 0x8192, 0xC470, + 0x8193, 0xC471, 0x8194, 0xC472, 0x8195, 0xC473, 0x8196, 0xC474, 0x8197, 0xC475, 0x8198, 0xB1EC, 0x8199, 0xC476, 0x819A, 0xC477, + 0x819B, 0xCCC5, 0x819C, 0xC4A4, 0x819D, 0xCFA5, 0x819E, 0xC478, 0x819F, 0xC479, 0x81A0, 0xC47A, 0x81A1, 0xC47B, 0x81A2, 0xC47C, + 0x81A3, 0xEBF9, 0x81A4, 0xC47D, 0x81A5, 0xC47E, 0x81A6, 0xECA2, 0x81A7, 0xC480, 0x81A8, 0xC5F2, 0x81A9, 0xC481, 0x81AA, 0xEBFA, + 0x81AB, 0xC482, 0x81AC, 0xC483, 0x81AD, 0xC484, 0x81AE, 0xC485, 0x81AF, 0xC486, 0x81B0, 0xC487, 0x81B1, 0xC488, 0x81B2, 0xC489, + 0x81B3, 0xC9C5, 0x81B4, 0xC48A, 0x81B5, 0xC48B, 0x81B6, 0xC48C, 0x81B7, 0xC48D, 0x81B8, 0xC48E, 0x81B9, 0xC48F, 0x81BA, 0xE2DF, + 0x81BB, 0xEBFE, 0x81BC, 0xC490, 0x81BD, 0xC491, 0x81BE, 0xC492, 0x81BF, 0xC493, 0x81C0, 0xCDCE, 0x81C1, 0xECA1, 0x81C2, 0xB1DB, + 0x81C3, 0xD3B7, 0x81C4, 0xC494, 0x81C5, 0xC495, 0x81C6, 0xD2DC, 0x81C7, 0xC496, 0x81C8, 0xC497, 0x81C9, 0xC498, 0x81CA, 0xEBFD, + 0x81CB, 0xC499, 0x81CC, 0xEBFB, 0x81CD, 0xC49A, 0x81CE, 0xC49B, 0x81CF, 0xC49C, 0x81D0, 0xC49D, 0x81D1, 0xC49E, 0x81D2, 0xC49F, + 0x81D3, 0xC4A0, 0x81D4, 0xC540, 0x81D5, 0xC541, 0x81D6, 0xC542, 0x81D7, 0xC543, 0x81D8, 0xC544, 0x81D9, 0xC545, 0x81DA, 0xC546, + 0x81DB, 0xC547, 0x81DC, 0xC548, 0x81DD, 0xC549, 0x81DE, 0xC54A, 0x81DF, 0xC54B, 0x81E0, 0xC54C, 0x81E1, 0xC54D, 0x81E2, 0xC54E, + 0x81E3, 0xB3BC, 0x81E4, 0xC54F, 0x81E5, 0xC550, 0x81E6, 0xC551, 0x81E7, 0xEAB0, 0x81E8, 0xC552, 0x81E9, 0xC553, 0x81EA, 0xD7D4, + 0x81EB, 0xC554, 0x81EC, 0xF4AB, 0x81ED, 0xB3F4, 0x81EE, 0xC555, 0x81EF, 0xC556, 0x81F0, 0xC557, 0x81F1, 0xC558, 0x81F2, 0xC559, + 0x81F3, 0xD6C1, 0x81F4, 0xD6C2, 0x81F5, 0xC55A, 0x81F6, 0xC55B, 0x81F7, 0xC55C, 0x81F8, 0xC55D, 0x81F9, 0xC55E, 0x81FA, 0xC55F, + 0x81FB, 0xD5E9, 0x81FC, 0xBECA, 0x81FD, 0xC560, 0x81FE, 0xF4A7, 0x81FF, 0xC561, 0x8200, 0xD2A8, 0x8201, 0xF4A8, 0x8202, 0xF4A9, + 0x8203, 0xC562, 0x8204, 0xF4AA, 0x8205, 0xBECB, 0x8206, 0xD3DF, 0x8207, 0xC563, 0x8208, 0xC564, 0x8209, 0xC565, 0x820A, 0xC566, + 0x820B, 0xC567, 0x820C, 0xC9E0, 0x820D, 0xC9E1, 0x820E, 0xC568, 0x820F, 0xC569, 0x8210, 0xF3C2, 0x8211, 0xC56A, 0x8212, 0xCAE6, + 0x8213, 0xC56B, 0x8214, 0xCCF2, 0x8215, 0xC56C, 0x8216, 0xC56D, 0x8217, 0xC56E, 0x8218, 0xC56F, 0x8219, 0xC570, 0x821A, 0xC571, + 0x821B, 0xE2B6, 0x821C, 0xCBB4, 0x821D, 0xC572, 0x821E, 0xCEE8, 0x821F, 0xD6DB, 0x8220, 0xC573, 0x8221, 0xF4AD, 0x8222, 0xF4AE, + 0x8223, 0xF4AF, 0x8224, 0xC574, 0x8225, 0xC575, 0x8226, 0xC576, 0x8227, 0xC577, 0x8228, 0xF4B2, 0x8229, 0xC578, 0x822A, 0xBABD, + 0x822B, 0xF4B3, 0x822C, 0xB0E3, 0x822D, 0xF4B0, 0x822E, 0xC579, 0x822F, 0xF4B1, 0x8230, 0xBDA2, 0x8231, 0xB2D5, 0x8232, 0xC57A, + 0x8233, 0xF4B6, 0x8234, 0xF4B7, 0x8235, 0xB6E6, 0x8236, 0xB2B0, 0x8237, 0xCFCF, 0x8238, 0xF4B4, 0x8239, 0xB4AC, 0x823A, 0xC57B, + 0x823B, 0xF4B5, 0x823C, 0xC57C, 0x823D, 0xC57D, 0x823E, 0xF4B8, 0x823F, 0xC57E, 0x8240, 0xC580, 0x8241, 0xC581, 0x8242, 0xC582, + 0x8243, 0xC583, 0x8244, 0xF4B9, 0x8245, 0xC584, 0x8246, 0xC585, 0x8247, 0xCDA7, 0x8248, 0xC586, 0x8249, 0xF4BA, 0x824A, 0xC587, + 0x824B, 0xF4BB, 0x824C, 0xC588, 0x824D, 0xC589, 0x824E, 0xC58A, 0x824F, 0xF4BC, 0x8250, 0xC58B, 0x8251, 0xC58C, 0x8252, 0xC58D, + 0x8253, 0xC58E, 0x8254, 0xC58F, 0x8255, 0xC590, 0x8256, 0xC591, 0x8257, 0xC592, 0x8258, 0xCBD2, 0x8259, 0xC593, 0x825A, 0xF4BD, + 0x825B, 0xC594, 0x825C, 0xC595, 0x825D, 0xC596, 0x825E, 0xC597, 0x825F, 0xF4BE, 0x8260, 0xC598, 0x8261, 0xC599, 0x8262, 0xC59A, + 0x8263, 0xC59B, 0x8264, 0xC59C, 0x8265, 0xC59D, 0x8266, 0xC59E, 0x8267, 0xC59F, 0x8268, 0xF4BF, 0x8269, 0xC5A0, 0x826A, 0xC640, + 0x826B, 0xC641, 0x826C, 0xC642, 0x826D, 0xC643, 0x826E, 0xF4DE, 0x826F, 0xC1BC, 0x8270, 0xBCE8, 0x8271, 0xC644, 0x8272, 0xC9AB, + 0x8273, 0xD1DE, 0x8274, 0xE5F5, 0x8275, 0xC645, 0x8276, 0xC646, 0x8277, 0xC647, 0x8278, 0xC648, 0x8279, 0xDCB3, 0x827A, 0xD2D5, + 0x827B, 0xC649, 0x827C, 0xC64A, 0x827D, 0xDCB4, 0x827E, 0xB0AC, 0x827F, 0xDCB5, 0x8280, 0xC64B, 0x8281, 0xC64C, 0x8282, 0xBDDA, + 0x8283, 0xC64D, 0x8284, 0xDCB9, 0x8285, 0xC64E, 0x8286, 0xC64F, 0x8287, 0xC650, 0x8288, 0xD8C2, 0x8289, 0xC651, 0x828A, 0xDCB7, + 0x828B, 0xD3F3, 0x828C, 0xC652, 0x828D, 0xC9D6, 0x828E, 0xDCBA, 0x828F, 0xDCB6, 0x8290, 0xC653, 0x8291, 0xDCBB, 0x8292, 0xC3A2, + 0x8293, 0xC654, 0x8294, 0xC655, 0x8295, 0xC656, 0x8296, 0xC657, 0x8297, 0xDCBC, 0x8298, 0xDCC5, 0x8299, 0xDCBD, 0x829A, 0xC658, + 0x829B, 0xC659, 0x829C, 0xCEDF, 0x829D, 0xD6A5, 0x829E, 0xC65A, 0x829F, 0xDCCF, 0x82A0, 0xC65B, 0x82A1, 0xDCCD, 0x82A2, 0xC65C, + 0x82A3, 0xC65D, 0x82A4, 0xDCD2, 0x82A5, 0xBDE6, 0x82A6, 0xC2AB, 0x82A7, 0xC65E, 0x82A8, 0xDCB8, 0x82A9, 0xDCCB, 0x82AA, 0xDCCE, + 0x82AB, 0xDCBE, 0x82AC, 0xB7D2, 0x82AD, 0xB0C5, 0x82AE, 0xDCC7, 0x82AF, 0xD0BE, 0x82B0, 0xDCC1, 0x82B1, 0xBBA8, 0x82B2, 0xC65F, + 0x82B3, 0xB7BC, 0x82B4, 0xDCCC, 0x82B5, 0xC660, 0x82B6, 0xC661, 0x82B7, 0xDCC6, 0x82B8, 0xDCBF, 0x82B9, 0xC7DB, 0x82BA, 0xC662, + 0x82BB, 0xC663, 0x82BC, 0xC664, 0x82BD, 0xD1BF, 0x82BE, 0xDCC0, 0x82BF, 0xC665, 0x82C0, 0xC666, 0x82C1, 0xDCCA, 0x82C2, 0xC667, + 0x82C3, 0xC668, 0x82C4, 0xDCD0, 0x82C5, 0xC669, 0x82C6, 0xC66A, 0x82C7, 0xCEAD, 0x82C8, 0xDCC2, 0x82C9, 0xC66B, 0x82CA, 0xDCC3, + 0x82CB, 0xDCC8, 0x82CC, 0xDCC9, 0x82CD, 0xB2D4, 0x82CE, 0xDCD1, 0x82CF, 0xCBD5, 0x82D0, 0xC66C, 0x82D1, 0xD4B7, 0x82D2, 0xDCDB, + 0x82D3, 0xDCDF, 0x82D4, 0xCCA6, 0x82D5, 0xDCE6, 0x82D6, 0xC66D, 0x82D7, 0xC3E7, 0x82D8, 0xDCDC, 0x82D9, 0xC66E, 0x82DA, 0xC66F, + 0x82DB, 0xBFC1, 0x82DC, 0xDCD9, 0x82DD, 0xC670, 0x82DE, 0xB0FA, 0x82DF, 0xB9B6, 0x82E0, 0xDCE5, 0x82E1, 0xDCD3, 0x82E2, 0xC671, + 0x82E3, 0xDCC4, 0x82E4, 0xDCD6, 0x82E5, 0xC8F4, 0x82E6, 0xBFE0, 0x82E7, 0xC672, 0x82E8, 0xC673, 0x82E9, 0xC674, 0x82EA, 0xC675, + 0x82EB, 0xC9BB, 0x82EC, 0xC676, 0x82ED, 0xC677, 0x82EE, 0xC678, 0x82EF, 0xB1BD, 0x82F0, 0xC679, 0x82F1, 0xD3A2, 0x82F2, 0xC67A, + 0x82F3, 0xC67B, 0x82F4, 0xDCDA, 0x82F5, 0xC67C, 0x82F6, 0xC67D, 0x82F7, 0xDCD5, 0x82F8, 0xC67E, 0x82F9, 0xC6BB, 0x82FA, 0xC680, + 0x82FB, 0xDCDE, 0x82FC, 0xC681, 0x82FD, 0xC682, 0x82FE, 0xC683, 0x82FF, 0xC684, 0x8300, 0xC685, 0x8301, 0xD7C2, 0x8302, 0xC3AF, + 0x8303, 0xB7B6, 0x8304, 0xC7D1, 0x8305, 0xC3A9, 0x8306, 0xDCE2, 0x8307, 0xDCD8, 0x8308, 0xDCEB, 0x8309, 0xDCD4, 0x830A, 0xC686, + 0x830B, 0xC687, 0x830C, 0xDCDD, 0x830D, 0xC688, 0x830E, 0xBEA5, 0x830F, 0xDCD7, 0x8310, 0xC689, 0x8311, 0xDCE0, 0x8312, 0xC68A, + 0x8313, 0xC68B, 0x8314, 0xDCE3, 0x8315, 0xDCE4, 0x8316, 0xC68C, 0x8317, 0xDCF8, 0x8318, 0xC68D, 0x8319, 0xC68E, 0x831A, 0xDCE1, + 0x831B, 0xDDA2, 0x831C, 0xDCE7, 0x831D, 0xC68F, 0x831E, 0xC690, 0x831F, 0xC691, 0x8320, 0xC692, 0x8321, 0xC693, 0x8322, 0xC694, + 0x8323, 0xC695, 0x8324, 0xC696, 0x8325, 0xC697, 0x8326, 0xC698, 0x8327, 0xBCEB, 0x8328, 0xB4C4, 0x8329, 0xC699, 0x832A, 0xC69A, + 0x832B, 0xC3A3, 0x832C, 0xB2E7, 0x832D, 0xDCFA, 0x832E, 0xC69B, 0x832F, 0xDCF2, 0x8330, 0xC69C, 0x8331, 0xDCEF, 0x8332, 0xC69D, + 0x8333, 0xDCFC, 0x8334, 0xDCEE, 0x8335, 0xD2F0, 0x8336, 0xB2E8, 0x8337, 0xC69E, 0x8338, 0xC8D7, 0x8339, 0xC8E3, 0x833A, 0xDCFB, + 0x833B, 0xC69F, 0x833C, 0xDCED, 0x833D, 0xC6A0, 0x833E, 0xC740, 0x833F, 0xC741, 0x8340, 0xDCF7, 0x8341, 0xC742, 0x8342, 0xC743, + 0x8343, 0xDCF5, 0x8344, 0xC744, 0x8345, 0xC745, 0x8346, 0xBEA3, 0x8347, 0xDCF4, 0x8348, 0xC746, 0x8349, 0xB2DD, 0x834A, 0xC747, + 0x834B, 0xC748, 0x834C, 0xC749, 0x834D, 0xC74A, 0x834E, 0xC74B, 0x834F, 0xDCF3, 0x8350, 0xBCF6, 0x8351, 0xDCE8, 0x8352, 0xBBC4, + 0x8353, 0xC74C, 0x8354, 0xC0F3, 0x8355, 0xC74D, 0x8356, 0xC74E, 0x8357, 0xC74F, 0x8358, 0xC750, 0x8359, 0xC751, 0x835A, 0xBCD4, + 0x835B, 0xDCE9, 0x835C, 0xDCEA, 0x835D, 0xC752, 0x835E, 0xDCF1, 0x835F, 0xDCF6, 0x8360, 0xDCF9, 0x8361, 0xB5B4, 0x8362, 0xC753, + 0x8363, 0xC8D9, 0x8364, 0xBBE7, 0x8365, 0xDCFE, 0x8366, 0xDCFD, 0x8367, 0xD3AB, 0x8368, 0xDDA1, 0x8369, 0xDDA3, 0x836A, 0xDDA5, + 0x836B, 0xD2F1, 0x836C, 0xDDA4, 0x836D, 0xDDA6, 0x836E, 0xDDA7, 0x836F, 0xD2A9, 0x8370, 0xC754, 0x8371, 0xC755, 0x8372, 0xC756, + 0x8373, 0xC757, 0x8374, 0xC758, 0x8375, 0xC759, 0x8376, 0xC75A, 0x8377, 0xBAC9, 0x8378, 0xDDA9, 0x8379, 0xC75B, 0x837A, 0xC75C, + 0x837B, 0xDDB6, 0x837C, 0xDDB1, 0x837D, 0xDDB4, 0x837E, 0xC75D, 0x837F, 0xC75E, 0x8380, 0xC75F, 0x8381, 0xC760, 0x8382, 0xC761, + 0x8383, 0xC762, 0x8384, 0xC763, 0x8385, 0xDDB0, 0x8386, 0xC6CE, 0x8387, 0xC764, 0x8388, 0xC765, 0x8389, 0xC0F2, 0x838A, 0xC766, + 0x838B, 0xC767, 0x838C, 0xC768, 0x838D, 0xC769, 0x838E, 0xC9AF, 0x838F, 0xC76A, 0x8390, 0xC76B, 0x8391, 0xC76C, 0x8392, 0xDCEC, + 0x8393, 0xDDAE, 0x8394, 0xC76D, 0x8395, 0xC76E, 0x8396, 0xC76F, 0x8397, 0xC770, 0x8398, 0xDDB7, 0x8399, 0xC771, 0x839A, 0xC772, + 0x839B, 0xDCF0, 0x839C, 0xDDAF, 0x839D, 0xC773, 0x839E, 0xDDB8, 0x839F, 0xC774, 0x83A0, 0xDDAC, 0x83A1, 0xC775, 0x83A2, 0xC776, + 0x83A3, 0xC777, 0x83A4, 0xC778, 0x83A5, 0xC779, 0x83A6, 0xC77A, 0x83A7, 0xC77B, 0x83A8, 0xDDB9, 0x83A9, 0xDDB3, 0x83AA, 0xDDAD, + 0x83AB, 0xC4AA, 0x83AC, 0xC77C, 0x83AD, 0xC77D, 0x83AE, 0xC77E, 0x83AF, 0xC780, 0x83B0, 0xDDA8, 0x83B1, 0xC0B3, 0x83B2, 0xC1AB, + 0x83B3, 0xDDAA, 0x83B4, 0xDDAB, 0x83B5, 0xC781, 0x83B6, 0xDDB2, 0x83B7, 0xBBF1, 0x83B8, 0xDDB5, 0x83B9, 0xD3A8, 0x83BA, 0xDDBA, + 0x83BB, 0xC782, 0x83BC, 0xDDBB, 0x83BD, 0xC3A7, 0x83BE, 0xC783, 0x83BF, 0xC784, 0x83C0, 0xDDD2, 0x83C1, 0xDDBC, 0x83C2, 0xC785, + 0x83C3, 0xC786, 0x83C4, 0xC787, 0x83C5, 0xDDD1, 0x83C6, 0xC788, 0x83C7, 0xB9BD, 0x83C8, 0xC789, 0x83C9, 0xC78A, 0x83CA, 0xBED5, + 0x83CB, 0xC78B, 0x83CC, 0xBEFA, 0x83CD, 0xC78C, 0x83CE, 0xC78D, 0x83CF, 0xBACA, 0x83D0, 0xC78E, 0x83D1, 0xC78F, 0x83D2, 0xC790, + 0x83D3, 0xC791, 0x83D4, 0xDDCA, 0x83D5, 0xC792, 0x83D6, 0xDDC5, 0x83D7, 0xC793, 0x83D8, 0xDDBF, 0x83D9, 0xC794, 0x83DA, 0xC795, + 0x83DB, 0xC796, 0x83DC, 0xB2CB, 0x83DD, 0xDDC3, 0x83DE, 0xC797, 0x83DF, 0xDDCB, 0x83E0, 0xB2A4, 0x83E1, 0xDDD5, 0x83E2, 0xC798, + 0x83E3, 0xC799, 0x83E4, 0xC79A, 0x83E5, 0xDDBE, 0x83E6, 0xC79B, 0x83E7, 0xC79C, 0x83E8, 0xC79D, 0x83E9, 0xC6D0, 0x83EA, 0xDDD0, + 0x83EB, 0xC79E, 0x83EC, 0xC79F, 0x83ED, 0xC7A0, 0x83EE, 0xC840, 0x83EF, 0xC841, 0x83F0, 0xDDD4, 0x83F1, 0xC1E2, 0x83F2, 0xB7C6, + 0x83F3, 0xC842, 0x83F4, 0xC843, 0x83F5, 0xC844, 0x83F6, 0xC845, 0x83F7, 0xC846, 0x83F8, 0xDDCE, 0x83F9, 0xDDCF, 0x83FA, 0xC847, + 0x83FB, 0xC848, 0x83FC, 0xC849, 0x83FD, 0xDDC4, 0x83FE, 0xC84A, 0x83FF, 0xC84B, 0x8400, 0xC84C, 0x8401, 0xDDBD, 0x8402, 0xC84D, + 0x8403, 0xDDCD, 0x8404, 0xCCD1, 0x8405, 0xC84E, 0x8406, 0xDDC9, 0x8407, 0xC84F, 0x8408, 0xC850, 0x8409, 0xC851, 0x840A, 0xC852, + 0x840B, 0xDDC2, 0x840C, 0xC3C8, 0x840D, 0xC6BC, 0x840E, 0xCEAE, 0x840F, 0xDDCC, 0x8410, 0xC853, 0x8411, 0xDDC8, 0x8412, 0xC854, + 0x8413, 0xC855, 0x8414, 0xC856, 0x8415, 0xC857, 0x8416, 0xC858, 0x8417, 0xC859, 0x8418, 0xDDC1, 0x8419, 0xC85A, 0x841A, 0xC85B, + 0x841B, 0xC85C, 0x841C, 0xDDC6, 0x841D, 0xC2DC, 0x841E, 0xC85D, 0x841F, 0xC85E, 0x8420, 0xC85F, 0x8421, 0xC860, 0x8422, 0xC861, + 0x8423, 0xC862, 0x8424, 0xD3A9, 0x8425, 0xD3AA, 0x8426, 0xDDD3, 0x8427, 0xCFF4, 0x8428, 0xC8F8, 0x8429, 0xC863, 0x842A, 0xC864, + 0x842B, 0xC865, 0x842C, 0xC866, 0x842D, 0xC867, 0x842E, 0xC868, 0x842F, 0xC869, 0x8430, 0xC86A, 0x8431, 0xDDE6, 0x8432, 0xC86B, + 0x8433, 0xC86C, 0x8434, 0xC86D, 0x8435, 0xC86E, 0x8436, 0xC86F, 0x8437, 0xC870, 0x8438, 0xDDC7, 0x8439, 0xC871, 0x843A, 0xC872, + 0x843B, 0xC873, 0x843C, 0xDDE0, 0x843D, 0xC2E4, 0x843E, 0xC874, 0x843F, 0xC875, 0x8440, 0xC876, 0x8441, 0xC877, 0x8442, 0xC878, + 0x8443, 0xC879, 0x8444, 0xC87A, 0x8445, 0xC87B, 0x8446, 0xDDE1, 0x8447, 0xC87C, 0x8448, 0xC87D, 0x8449, 0xC87E, 0x844A, 0xC880, + 0x844B, 0xC881, 0x844C, 0xC882, 0x844D, 0xC883, 0x844E, 0xC884, 0x844F, 0xC885, 0x8450, 0xC886, 0x8451, 0xDDD7, 0x8452, 0xC887, + 0x8453, 0xC888, 0x8454, 0xC889, 0x8455, 0xC88A, 0x8456, 0xC88B, 0x8457, 0xD6F8, 0x8458, 0xC88C, 0x8459, 0xDDD9, 0x845A, 0xDDD8, + 0x845B, 0xB8F0, 0x845C, 0xDDD6, 0x845D, 0xC88D, 0x845E, 0xC88E, 0x845F, 0xC88F, 0x8460, 0xC890, 0x8461, 0xC6CF, 0x8462, 0xC891, + 0x8463, 0xB6AD, 0x8464, 0xC892, 0x8465, 0xC893, 0x8466, 0xC894, 0x8467, 0xC895, 0x8468, 0xC896, 0x8469, 0xDDE2, 0x846A, 0xC897, + 0x846B, 0xBAF9, 0x846C, 0xD4E1, 0x846D, 0xDDE7, 0x846E, 0xC898, 0x846F, 0xC899, 0x8470, 0xC89A, 0x8471, 0xB4D0, 0x8472, 0xC89B, + 0x8473, 0xDDDA, 0x8474, 0xC89C, 0x8475, 0xBFFB, 0x8476, 0xDDE3, 0x8477, 0xC89D, 0x8478, 0xDDDF, 0x8479, 0xC89E, 0x847A, 0xDDDD, + 0x847B, 0xC89F, 0x847C, 0xC8A0, 0x847D, 0xC940, 0x847E, 0xC941, 0x847F, 0xC942, 0x8480, 0xC943, 0x8481, 0xC944, 0x8482, 0xB5D9, + 0x8483, 0xC945, 0x8484, 0xC946, 0x8485, 0xC947, 0x8486, 0xC948, 0x8487, 0xDDDB, 0x8488, 0xDDDC, 0x8489, 0xDDDE, 0x848A, 0xC949, + 0x848B, 0xBDAF, 0x848C, 0xDDE4, 0x848D, 0xC94A, 0x848E, 0xDDE5, 0x848F, 0xC94B, 0x8490, 0xC94C, 0x8491, 0xC94D, 0x8492, 0xC94E, + 0x8493, 0xC94F, 0x8494, 0xC950, 0x8495, 0xC951, 0x8496, 0xC952, 0x8497, 0xDDF5, 0x8498, 0xC953, 0x8499, 0xC3C9, 0x849A, 0xC954, + 0x849B, 0xC955, 0x849C, 0xCBE2, 0x849D, 0xC956, 0x849E, 0xC957, 0x849F, 0xC958, 0x84A0, 0xC959, 0x84A1, 0xDDF2, 0x84A2, 0xC95A, + 0x84A3, 0xC95B, 0x84A4, 0xC95C, 0x84A5, 0xC95D, 0x84A6, 0xC95E, 0x84A7, 0xC95F, 0x84A8, 0xC960, 0x84A9, 0xC961, 0x84AA, 0xC962, + 0x84AB, 0xC963, 0x84AC, 0xC964, 0x84AD, 0xC965, 0x84AE, 0xC966, 0x84AF, 0xD8E1, 0x84B0, 0xC967, 0x84B1, 0xC968, 0x84B2, 0xC6D1, + 0x84B3, 0xC969, 0x84B4, 0xDDF4, 0x84B5, 0xC96A, 0x84B6, 0xC96B, 0x84B7, 0xC96C, 0x84B8, 0xD5F4, 0x84B9, 0xDDF3, 0x84BA, 0xDDF0, + 0x84BB, 0xC96D, 0x84BC, 0xC96E, 0x84BD, 0xDDEC, 0x84BE, 0xC96F, 0x84BF, 0xDDEF, 0x84C0, 0xC970, 0x84C1, 0xDDE8, 0x84C2, 0xC971, + 0x84C3, 0xC972, 0x84C4, 0xD0EE, 0x84C5, 0xC973, 0x84C6, 0xC974, 0x84C7, 0xC975, 0x84C8, 0xC976, 0x84C9, 0xC8D8, 0x84CA, 0xDDEE, + 0x84CB, 0xC977, 0x84CC, 0xC978, 0x84CD, 0xDDE9, 0x84CE, 0xC979, 0x84CF, 0xC97A, 0x84D0, 0xDDEA, 0x84D1, 0xCBF2, 0x84D2, 0xC97B, + 0x84D3, 0xDDED, 0x84D4, 0xC97C, 0x84D5, 0xC97D, 0x84D6, 0xB1CD, 0x84D7, 0xC97E, 0x84D8, 0xC980, 0x84D9, 0xC981, 0x84DA, 0xC982, + 0x84DB, 0xC983, 0x84DC, 0xC984, 0x84DD, 0xC0B6, 0x84DE, 0xC985, 0x84DF, 0xBCBB, 0x84E0, 0xDDF1, 0x84E1, 0xC986, 0x84E2, 0xC987, + 0x84E3, 0xDDF7, 0x84E4, 0xC988, 0x84E5, 0xDDF6, 0x84E6, 0xDDEB, 0x84E7, 0xC989, 0x84E8, 0xC98A, 0x84E9, 0xC98B, 0x84EA, 0xC98C, + 0x84EB, 0xC98D, 0x84EC, 0xC5EE, 0x84ED, 0xC98E, 0x84EE, 0xC98F, 0x84EF, 0xC990, 0x84F0, 0xDDFB, 0x84F1, 0xC991, 0x84F2, 0xC992, + 0x84F3, 0xC993, 0x84F4, 0xC994, 0x84F5, 0xC995, 0x84F6, 0xC996, 0x84F7, 0xC997, 0x84F8, 0xC998, 0x84F9, 0xC999, 0x84FA, 0xC99A, + 0x84FB, 0xC99B, 0x84FC, 0xDEA4, 0x84FD, 0xC99C, 0x84FE, 0xC99D, 0x84FF, 0xDEA3, 0x8500, 0xC99E, 0x8501, 0xC99F, 0x8502, 0xC9A0, + 0x8503, 0xCA40, 0x8504, 0xCA41, 0x8505, 0xCA42, 0x8506, 0xCA43, 0x8507, 0xCA44, 0x8508, 0xCA45, 0x8509, 0xCA46, 0x850A, 0xCA47, + 0x850B, 0xCA48, 0x850C, 0xDDF8, 0x850D, 0xCA49, 0x850E, 0xCA4A, 0x850F, 0xCA4B, 0x8510, 0xCA4C, 0x8511, 0xC3EF, 0x8512, 0xCA4D, + 0x8513, 0xC2FB, 0x8514, 0xCA4E, 0x8515, 0xCA4F, 0x8516, 0xCA50, 0x8517, 0xD5E1, 0x8518, 0xCA51, 0x8519, 0xCA52, 0x851A, 0xCEB5, + 0x851B, 0xCA53, 0x851C, 0xCA54, 0x851D, 0xCA55, 0x851E, 0xCA56, 0x851F, 0xDDFD, 0x8520, 0xCA57, 0x8521, 0xB2CC, 0x8522, 0xCA58, + 0x8523, 0xCA59, 0x8524, 0xCA5A, 0x8525, 0xCA5B, 0x8526, 0xCA5C, 0x8527, 0xCA5D, 0x8528, 0xCA5E, 0x8529, 0xCA5F, 0x852A, 0xCA60, + 0x852B, 0xC4E8, 0x852C, 0xCADF, 0x852D, 0xCA61, 0x852E, 0xCA62, 0x852F, 0xCA63, 0x8530, 0xCA64, 0x8531, 0xCA65, 0x8532, 0xCA66, + 0x8533, 0xCA67, 0x8534, 0xCA68, 0x8535, 0xCA69, 0x8536, 0xCA6A, 0x8537, 0xC7BE, 0x8538, 0xDDFA, 0x8539, 0xDDFC, 0x853A, 0xDDFE, + 0x853B, 0xDEA2, 0x853C, 0xB0AA, 0x853D, 0xB1CE, 0x853E, 0xCA6B, 0x853F, 0xCA6C, 0x8540, 0xCA6D, 0x8541, 0xCA6E, 0x8542, 0xCA6F, + 0x8543, 0xDEAC, 0x8544, 0xCA70, 0x8545, 0xCA71, 0x8546, 0xCA72, 0x8547, 0xCA73, 0x8548, 0xDEA6, 0x8549, 0xBDB6, 0x854A, 0xC8EF, + 0x854B, 0xCA74, 0x854C, 0xCA75, 0x854D, 0xCA76, 0x854E, 0xCA77, 0x854F, 0xCA78, 0x8550, 0xCA79, 0x8551, 0xCA7A, 0x8552, 0xCA7B, + 0x8553, 0xCA7C, 0x8554, 0xCA7D, 0x8555, 0xCA7E, 0x8556, 0xDEA1, 0x8557, 0xCA80, 0x8558, 0xCA81, 0x8559, 0xDEA5, 0x855A, 0xCA82, + 0x855B, 0xCA83, 0x855C, 0xCA84, 0x855D, 0xCA85, 0x855E, 0xDEA9, 0x855F, 0xCA86, 0x8560, 0xCA87, 0x8561, 0xCA88, 0x8562, 0xCA89, + 0x8563, 0xCA8A, 0x8564, 0xDEA8, 0x8565, 0xCA8B, 0x8566, 0xCA8C, 0x8567, 0xCA8D, 0x8568, 0xDEA7, 0x8569, 0xCA8E, 0x856A, 0xCA8F, + 0x856B, 0xCA90, 0x856C, 0xCA91, 0x856D, 0xCA92, 0x856E, 0xCA93, 0x856F, 0xCA94, 0x8570, 0xCA95, 0x8571, 0xCA96, 0x8572, 0xDEAD, + 0x8573, 0xCA97, 0x8574, 0xD4CC, 0x8575, 0xCA98, 0x8576, 0xCA99, 0x8577, 0xCA9A, 0x8578, 0xCA9B, 0x8579, 0xDEB3, 0x857A, 0xDEAA, + 0x857B, 0xDEAE, 0x857C, 0xCA9C, 0x857D, 0xCA9D, 0x857E, 0xC0D9, 0x857F, 0xCA9E, 0x8580, 0xCA9F, 0x8581, 0xCAA0, 0x8582, 0xCB40, + 0x8583, 0xCB41, 0x8584, 0xB1A1, 0x8585, 0xDEB6, 0x8586, 0xCB42, 0x8587, 0xDEB1, 0x8588, 0xCB43, 0x8589, 0xCB44, 0x858A, 0xCB45, + 0x858B, 0xCB46, 0x858C, 0xCB47, 0x858D, 0xCB48, 0x858E, 0xCB49, 0x858F, 0xDEB2, 0x8590, 0xCB4A, 0x8591, 0xCB4B, 0x8592, 0xCB4C, + 0x8593, 0xCB4D, 0x8594, 0xCB4E, 0x8595, 0xCB4F, 0x8596, 0xCB50, 0x8597, 0xCB51, 0x8598, 0xCB52, 0x8599, 0xCB53, 0x859A, 0xCB54, + 0x859B, 0xD1A6, 0x859C, 0xDEB5, 0x859D, 0xCB55, 0x859E, 0xCB56, 0x859F, 0xCB57, 0x85A0, 0xCB58, 0x85A1, 0xCB59, 0x85A2, 0xCB5A, + 0x85A3, 0xCB5B, 0x85A4, 0xDEAF, 0x85A5, 0xCB5C, 0x85A6, 0xCB5D, 0x85A7, 0xCB5E, 0x85A8, 0xDEB0, 0x85A9, 0xCB5F, 0x85AA, 0xD0BD, + 0x85AB, 0xCB60, 0x85AC, 0xCB61, 0x85AD, 0xCB62, 0x85AE, 0xDEB4, 0x85AF, 0xCAED, 0x85B0, 0xDEB9, 0x85B1, 0xCB63, 0x85B2, 0xCB64, + 0x85B3, 0xCB65, 0x85B4, 0xCB66, 0x85B5, 0xCB67, 0x85B6, 0xCB68, 0x85B7, 0xDEB8, 0x85B8, 0xCB69, 0x85B9, 0xDEB7, 0x85BA, 0xCB6A, + 0x85BB, 0xCB6B, 0x85BC, 0xCB6C, 0x85BD, 0xCB6D, 0x85BE, 0xCB6E, 0x85BF, 0xCB6F, 0x85C0, 0xCB70, 0x85C1, 0xDEBB, 0x85C2, 0xCB71, + 0x85C3, 0xCB72, 0x85C4, 0xCB73, 0x85C5, 0xCB74, 0x85C6, 0xCB75, 0x85C7, 0xCB76, 0x85C8, 0xCB77, 0x85C9, 0xBDE5, 0x85CA, 0xCB78, + 0x85CB, 0xCB79, 0x85CC, 0xCB7A, 0x85CD, 0xCB7B, 0x85CE, 0xCB7C, 0x85CF, 0xB2D8, 0x85D0, 0xC3EA, 0x85D1, 0xCB7D, 0x85D2, 0xCB7E, + 0x85D3, 0xDEBA, 0x85D4, 0xCB80, 0x85D5, 0xC5BA, 0x85D6, 0xCB81, 0x85D7, 0xCB82, 0x85D8, 0xCB83, 0x85D9, 0xCB84, 0x85DA, 0xCB85, + 0x85DB, 0xCB86, 0x85DC, 0xDEBC, 0x85DD, 0xCB87, 0x85DE, 0xCB88, 0x85DF, 0xCB89, 0x85E0, 0xCB8A, 0x85E1, 0xCB8B, 0x85E2, 0xCB8C, + 0x85E3, 0xCB8D, 0x85E4, 0xCCD9, 0x85E5, 0xCB8E, 0x85E6, 0xCB8F, 0x85E7, 0xCB90, 0x85E8, 0xCB91, 0x85E9, 0xB7AA, 0x85EA, 0xCB92, + 0x85EB, 0xCB93, 0x85EC, 0xCB94, 0x85ED, 0xCB95, 0x85EE, 0xCB96, 0x85EF, 0xCB97, 0x85F0, 0xCB98, 0x85F1, 0xCB99, 0x85F2, 0xCB9A, + 0x85F3, 0xCB9B, 0x85F4, 0xCB9C, 0x85F5, 0xCB9D, 0x85F6, 0xCB9E, 0x85F7, 0xCB9F, 0x85F8, 0xCBA0, 0x85F9, 0xCC40, 0x85FA, 0xCC41, + 0x85FB, 0xD4E5, 0x85FC, 0xCC42, 0x85FD, 0xCC43, 0x85FE, 0xCC44, 0x85FF, 0xDEBD, 0x8600, 0xCC45, 0x8601, 0xCC46, 0x8602, 0xCC47, + 0x8603, 0xCC48, 0x8604, 0xCC49, 0x8605, 0xDEBF, 0x8606, 0xCC4A, 0x8607, 0xCC4B, 0x8608, 0xCC4C, 0x8609, 0xCC4D, 0x860A, 0xCC4E, + 0x860B, 0xCC4F, 0x860C, 0xCC50, 0x860D, 0xCC51, 0x860E, 0xCC52, 0x860F, 0xCC53, 0x8610, 0xCC54, 0x8611, 0xC4A2, 0x8612, 0xCC55, + 0x8613, 0xCC56, 0x8614, 0xCC57, 0x8615, 0xCC58, 0x8616, 0xDEC1, 0x8617, 0xCC59, 0x8618, 0xCC5A, 0x8619, 0xCC5B, 0x861A, 0xCC5C, + 0x861B, 0xCC5D, 0x861C, 0xCC5E, 0x861D, 0xCC5F, 0x861E, 0xCC60, 0x861F, 0xCC61, 0x8620, 0xCC62, 0x8621, 0xCC63, 0x8622, 0xCC64, + 0x8623, 0xCC65, 0x8624, 0xCC66, 0x8625, 0xCC67, 0x8626, 0xCC68, 0x8627, 0xDEBE, 0x8628, 0xCC69, 0x8629, 0xDEC0, 0x862A, 0xCC6A, + 0x862B, 0xCC6B, 0x862C, 0xCC6C, 0x862D, 0xCC6D, 0x862E, 0xCC6E, 0x862F, 0xCC6F, 0x8630, 0xCC70, 0x8631, 0xCC71, 0x8632, 0xCC72, + 0x8633, 0xCC73, 0x8634, 0xCC74, 0x8635, 0xCC75, 0x8636, 0xCC76, 0x8637, 0xCC77, 0x8638, 0xD5BA, 0x8639, 0xCC78, 0x863A, 0xCC79, + 0x863B, 0xCC7A, 0x863C, 0xDEC2, 0x863D, 0xCC7B, 0x863E, 0xCC7C, 0x863F, 0xCC7D, 0x8640, 0xCC7E, 0x8641, 0xCC80, 0x8642, 0xCC81, + 0x8643, 0xCC82, 0x8644, 0xCC83, 0x8645, 0xCC84, 0x8646, 0xCC85, 0x8647, 0xCC86, 0x8648, 0xCC87, 0x8649, 0xCC88, 0x864A, 0xCC89, + 0x864B, 0xCC8A, 0x864C, 0xCC8B, 0x864D, 0xF2AE, 0x864E, 0xBBA2, 0x864F, 0xC2B2, 0x8650, 0xC5B0, 0x8651, 0xC2C7, 0x8652, 0xCC8C, + 0x8653, 0xCC8D, 0x8654, 0xF2AF, 0x8655, 0xCC8E, 0x8656, 0xCC8F, 0x8657, 0xCC90, 0x8658, 0xCC91, 0x8659, 0xCC92, 0x865A, 0xD0E9, + 0x865B, 0xCC93, 0x865C, 0xCC94, 0x865D, 0xCC95, 0x865E, 0xD3DD, 0x865F, 0xCC96, 0x8660, 0xCC97, 0x8661, 0xCC98, 0x8662, 0xEBBD, + 0x8663, 0xCC99, 0x8664, 0xCC9A, 0x8665, 0xCC9B, 0x8666, 0xCC9C, 0x8667, 0xCC9D, 0x8668, 0xCC9E, 0x8669, 0xCC9F, 0x866A, 0xCCA0, + 0x866B, 0xB3E6, 0x866C, 0xF2B0, 0x866D, 0xCD40, 0x866E, 0xF2B1, 0x866F, 0xCD41, 0x8670, 0xCD42, 0x8671, 0xCAAD, 0x8672, 0xCD43, + 0x8673, 0xCD44, 0x8674, 0xCD45, 0x8675, 0xCD46, 0x8676, 0xCD47, 0x8677, 0xCD48, 0x8678, 0xCD49, 0x8679, 0xBAE7, 0x867A, 0xF2B3, + 0x867B, 0xF2B5, 0x867C, 0xF2B4, 0x867D, 0xCBE4, 0x867E, 0xCFBA, 0x867F, 0xF2B2, 0x8680, 0xCAB4, 0x8681, 0xD2CF, 0x8682, 0xC2EC, + 0x8683, 0xCD4A, 0x8684, 0xCD4B, 0x8685, 0xCD4C, 0x8686, 0xCD4D, 0x8687, 0xCD4E, 0x8688, 0xCD4F, 0x8689, 0xCD50, 0x868A, 0xCEC3, + 0x868B, 0xF2B8, 0x868C, 0xB0F6, 0x868D, 0xF2B7, 0x868E, 0xCD51, 0x868F, 0xCD52, 0x8690, 0xCD53, 0x8691, 0xCD54, 0x8692, 0xCD55, + 0x8693, 0xF2BE, 0x8694, 0xCD56, 0x8695, 0xB2CF, 0x8696, 0xCD57, 0x8697, 0xCD58, 0x8698, 0xCD59, 0x8699, 0xCD5A, 0x869A, 0xCD5B, + 0x869B, 0xCD5C, 0x869C, 0xD1C1, 0x869D, 0xF2BA, 0x869E, 0xCD5D, 0x869F, 0xCD5E, 0x86A0, 0xCD5F, 0x86A1, 0xCD60, 0x86A2, 0xCD61, + 0x86A3, 0xF2BC, 0x86A4, 0xD4E9, 0x86A5, 0xCD62, 0x86A6, 0xCD63, 0x86A7, 0xF2BB, 0x86A8, 0xF2B6, 0x86A9, 0xF2BF, 0x86AA, 0xF2BD, + 0x86AB, 0xCD64, 0x86AC, 0xF2B9, 0x86AD, 0xCD65, 0x86AE, 0xCD66, 0x86AF, 0xF2C7, 0x86B0, 0xF2C4, 0x86B1, 0xF2C6, 0x86B2, 0xCD67, + 0x86B3, 0xCD68, 0x86B4, 0xF2CA, 0x86B5, 0xF2C2, 0x86B6, 0xF2C0, 0x86B7, 0xCD69, 0x86B8, 0xCD6A, 0x86B9, 0xCD6B, 0x86BA, 0xF2C5, + 0x86BB, 0xCD6C, 0x86BC, 0xCD6D, 0x86BD, 0xCD6E, 0x86BE, 0xCD6F, 0x86BF, 0xCD70, 0x86C0, 0xD6FB, 0x86C1, 0xCD71, 0x86C2, 0xCD72, + 0x86C3, 0xCD73, 0x86C4, 0xF2C1, 0x86C5, 0xCD74, 0x86C6, 0xC7F9, 0x86C7, 0xC9DF, 0x86C8, 0xCD75, 0x86C9, 0xF2C8, 0x86CA, 0xB9C6, + 0x86CB, 0xB5B0, 0x86CC, 0xCD76, 0x86CD, 0xCD77, 0x86CE, 0xF2C3, 0x86CF, 0xF2C9, 0x86D0, 0xF2D0, 0x86D1, 0xF2D6, 0x86D2, 0xCD78, + 0x86D3, 0xCD79, 0x86D4, 0xBBD7, 0x86D5, 0xCD7A, 0x86D6, 0xCD7B, 0x86D7, 0xCD7C, 0x86D8, 0xF2D5, 0x86D9, 0xCDDC, 0x86DA, 0xCD7D, + 0x86DB, 0xD6EB, 0x86DC, 0xCD7E, 0x86DD, 0xCD80, 0x86DE, 0xF2D2, 0x86DF, 0xF2D4, 0x86E0, 0xCD81, 0x86E1, 0xCD82, 0x86E2, 0xCD83, + 0x86E3, 0xCD84, 0x86E4, 0xB8F2, 0x86E5, 0xCD85, 0x86E6, 0xCD86, 0x86E7, 0xCD87, 0x86E8, 0xCD88, 0x86E9, 0xF2CB, 0x86EA, 0xCD89, + 0x86EB, 0xCD8A, 0x86EC, 0xCD8B, 0x86ED, 0xF2CE, 0x86EE, 0xC2F9, 0x86EF, 0xCD8C, 0x86F0, 0xD5DD, 0x86F1, 0xF2CC, 0x86F2, 0xF2CD, + 0x86F3, 0xF2CF, 0x86F4, 0xF2D3, 0x86F5, 0xCD8D, 0x86F6, 0xCD8E, 0x86F7, 0xCD8F, 0x86F8, 0xF2D9, 0x86F9, 0xD3BC, 0x86FA, 0xCD90, + 0x86FB, 0xCD91, 0x86FC, 0xCD92, 0x86FD, 0xCD93, 0x86FE, 0xB6EA, 0x86FF, 0xCD94, 0x8700, 0xCAF1, 0x8701, 0xCD95, 0x8702, 0xB7E4, + 0x8703, 0xF2D7, 0x8704, 0xCD96, 0x8705, 0xCD97, 0x8706, 0xCD98, 0x8707, 0xF2D8, 0x8708, 0xF2DA, 0x8709, 0xF2DD, 0x870A, 0xF2DB, + 0x870B, 0xCD99, 0x870C, 0xCD9A, 0x870D, 0xF2DC, 0x870E, 0xCD9B, 0x870F, 0xCD9C, 0x8710, 0xCD9D, 0x8711, 0xCD9E, 0x8712, 0xD1D1, + 0x8713, 0xF2D1, 0x8714, 0xCD9F, 0x8715, 0xCDC9, 0x8716, 0xCDA0, 0x8717, 0xCECF, 0x8718, 0xD6A9, 0x8719, 0xCE40, 0x871A, 0xF2E3, + 0x871B, 0xCE41, 0x871C, 0xC3DB, 0x871D, 0xCE42, 0x871E, 0xF2E0, 0x871F, 0xCE43, 0x8720, 0xCE44, 0x8721, 0xC0AF, 0x8722, 0xF2EC, + 0x8723, 0xF2DE, 0x8724, 0xCE45, 0x8725, 0xF2E1, 0x8726, 0xCE46, 0x8727, 0xCE47, 0x8728, 0xCE48, 0x8729, 0xF2E8, 0x872A, 0xCE49, + 0x872B, 0xCE4A, 0x872C, 0xCE4B, 0x872D, 0xCE4C, 0x872E, 0xF2E2, 0x872F, 0xCE4D, 0x8730, 0xCE4E, 0x8731, 0xF2E7, 0x8732, 0xCE4F, + 0x8733, 0xCE50, 0x8734, 0xF2E6, 0x8735, 0xCE51, 0x8736, 0xCE52, 0x8737, 0xF2E9, 0x8738, 0xCE53, 0x8739, 0xCE54, 0x873A, 0xCE55, + 0x873B, 0xF2DF, 0x873C, 0xCE56, 0x873D, 0xCE57, 0x873E, 0xF2E4, 0x873F, 0xF2EA, 0x8740, 0xCE58, 0x8741, 0xCE59, 0x8742, 0xCE5A, + 0x8743, 0xCE5B, 0x8744, 0xCE5C, 0x8745, 0xCE5D, 0x8746, 0xCE5E, 0x8747, 0xD3AC, 0x8748, 0xF2E5, 0x8749, 0xB2F5, 0x874A, 0xCE5F, + 0x874B, 0xCE60, 0x874C, 0xF2F2, 0x874D, 0xCE61, 0x874E, 0xD0AB, 0x874F, 0xCE62, 0x8750, 0xCE63, 0x8751, 0xCE64, 0x8752, 0xCE65, + 0x8753, 0xF2F5, 0x8754, 0xCE66, 0x8755, 0xCE67, 0x8756, 0xCE68, 0x8757, 0xBBC8, 0x8758, 0xCE69, 0x8759, 0xF2F9, 0x875A, 0xCE6A, + 0x875B, 0xCE6B, 0x875C, 0xCE6C, 0x875D, 0xCE6D, 0x875E, 0xCE6E, 0x875F, 0xCE6F, 0x8760, 0xF2F0, 0x8761, 0xCE70, 0x8762, 0xCE71, + 0x8763, 0xF2F6, 0x8764, 0xF2F8, 0x8765, 0xF2FA, 0x8766, 0xCE72, 0x8767, 0xCE73, 0x8768, 0xCE74, 0x8769, 0xCE75, 0x876A, 0xCE76, + 0x876B, 0xCE77, 0x876C, 0xCE78, 0x876D, 0xCE79, 0x876E, 0xF2F3, 0x876F, 0xCE7A, 0x8770, 0xF2F1, 0x8771, 0xCE7B, 0x8772, 0xCE7C, + 0x8773, 0xCE7D, 0x8774, 0xBAFB, 0x8775, 0xCE7E, 0x8776, 0xB5FB, 0x8777, 0xCE80, 0x8778, 0xCE81, 0x8779, 0xCE82, 0x877A, 0xCE83, + 0x877B, 0xF2EF, 0x877C, 0xF2F7, 0x877D, 0xF2ED, 0x877E, 0xF2EE, 0x877F, 0xCE84, 0x8780, 0xCE85, 0x8781, 0xCE86, 0x8782, 0xF2EB, + 0x8783, 0xF3A6, 0x8784, 0xCE87, 0x8785, 0xF3A3, 0x8786, 0xCE88, 0x8787, 0xCE89, 0x8788, 0xF3A2, 0x8789, 0xCE8A, 0x878A, 0xCE8B, + 0x878B, 0xF2F4, 0x878C, 0xCE8C, 0x878D, 0xC8DA, 0x878E, 0xCE8D, 0x878F, 0xCE8E, 0x8790, 0xCE8F, 0x8791, 0xCE90, 0x8792, 0xCE91, + 0x8793, 0xF2FB, 0x8794, 0xCE92, 0x8795, 0xCE93, 0x8796, 0xCE94, 0x8797, 0xF3A5, 0x8798, 0xCE95, 0x8799, 0xCE96, 0x879A, 0xCE97, + 0x879B, 0xCE98, 0x879C, 0xCE99, 0x879D, 0xCE9A, 0x879E, 0xCE9B, 0x879F, 0xC3F8, 0x87A0, 0xCE9C, 0x87A1, 0xCE9D, 0x87A2, 0xCE9E, + 0x87A3, 0xCE9F, 0x87A4, 0xCEA0, 0x87A5, 0xCF40, 0x87A6, 0xCF41, 0x87A7, 0xCF42, 0x87A8, 0xF2FD, 0x87A9, 0xCF43, 0x87AA, 0xCF44, + 0x87AB, 0xF3A7, 0x87AC, 0xF3A9, 0x87AD, 0xF3A4, 0x87AE, 0xCF45, 0x87AF, 0xF2FC, 0x87B0, 0xCF46, 0x87B1, 0xCF47, 0x87B2, 0xCF48, + 0x87B3, 0xF3AB, 0x87B4, 0xCF49, 0x87B5, 0xF3AA, 0x87B6, 0xCF4A, 0x87B7, 0xCF4B, 0x87B8, 0xCF4C, 0x87B9, 0xCF4D, 0x87BA, 0xC2DD, + 0x87BB, 0xCF4E, 0x87BC, 0xCF4F, 0x87BD, 0xF3AE, 0x87BE, 0xCF50, 0x87BF, 0xCF51, 0x87C0, 0xF3B0, 0x87C1, 0xCF52, 0x87C2, 0xCF53, + 0x87C3, 0xCF54, 0x87C4, 0xCF55, 0x87C5, 0xCF56, 0x87C6, 0xF3A1, 0x87C7, 0xCF57, 0x87C8, 0xCF58, 0x87C9, 0xCF59, 0x87CA, 0xF3B1, + 0x87CB, 0xF3AC, 0x87CC, 0xCF5A, 0x87CD, 0xCF5B, 0x87CE, 0xCF5C, 0x87CF, 0xCF5D, 0x87D0, 0xCF5E, 0x87D1, 0xF3AF, 0x87D2, 0xF2FE, + 0x87D3, 0xF3AD, 0x87D4, 0xCF5F, 0x87D5, 0xCF60, 0x87D6, 0xCF61, 0x87D7, 0xCF62, 0x87D8, 0xCF63, 0x87D9, 0xCF64, 0x87DA, 0xCF65, + 0x87DB, 0xF3B2, 0x87DC, 0xCF66, 0x87DD, 0xCF67, 0x87DE, 0xCF68, 0x87DF, 0xCF69, 0x87E0, 0xF3B4, 0x87E1, 0xCF6A, 0x87E2, 0xCF6B, + 0x87E3, 0xCF6C, 0x87E4, 0xCF6D, 0x87E5, 0xF3A8, 0x87E6, 0xCF6E, 0x87E7, 0xCF6F, 0x87E8, 0xCF70, 0x87E9, 0xCF71, 0x87EA, 0xF3B3, + 0x87EB, 0xCF72, 0x87EC, 0xCF73, 0x87ED, 0xCF74, 0x87EE, 0xF3B5, 0x87EF, 0xCF75, 0x87F0, 0xCF76, 0x87F1, 0xCF77, 0x87F2, 0xCF78, + 0x87F3, 0xCF79, 0x87F4, 0xCF7A, 0x87F5, 0xCF7B, 0x87F6, 0xCF7C, 0x87F7, 0xCF7D, 0x87F8, 0xCF7E, 0x87F9, 0xD0B7, 0x87FA, 0xCF80, + 0x87FB, 0xCF81, 0x87FC, 0xCF82, 0x87FD, 0xCF83, 0x87FE, 0xF3B8, 0x87FF, 0xCF84, 0x8800, 0xCF85, 0x8801, 0xCF86, 0x8802, 0xCF87, + 0x8803, 0xD9F9, 0x8804, 0xCF88, 0x8805, 0xCF89, 0x8806, 0xCF8A, 0x8807, 0xCF8B, 0x8808, 0xCF8C, 0x8809, 0xCF8D, 0x880A, 0xF3B9, + 0x880B, 0xCF8E, 0x880C, 0xCF8F, 0x880D, 0xCF90, 0x880E, 0xCF91, 0x880F, 0xCF92, 0x8810, 0xCF93, 0x8811, 0xCF94, 0x8812, 0xCF95, + 0x8813, 0xF3B7, 0x8814, 0xCF96, 0x8815, 0xC8E4, 0x8816, 0xF3B6, 0x8817, 0xCF97, 0x8818, 0xCF98, 0x8819, 0xCF99, 0x881A, 0xCF9A, + 0x881B, 0xF3BA, 0x881C, 0xCF9B, 0x881D, 0xCF9C, 0x881E, 0xCF9D, 0x881F, 0xCF9E, 0x8820, 0xCF9F, 0x8821, 0xF3BB, 0x8822, 0xB4C0, + 0x8823, 0xCFA0, 0x8824, 0xD040, 0x8825, 0xD041, 0x8826, 0xD042, 0x8827, 0xD043, 0x8828, 0xD044, 0x8829, 0xD045, 0x882A, 0xD046, + 0x882B, 0xD047, 0x882C, 0xD048, 0x882D, 0xD049, 0x882E, 0xD04A, 0x882F, 0xD04B, 0x8830, 0xD04C, 0x8831, 0xD04D, 0x8832, 0xEEC3, + 0x8833, 0xD04E, 0x8834, 0xD04F, 0x8835, 0xD050, 0x8836, 0xD051, 0x8837, 0xD052, 0x8838, 0xD053, 0x8839, 0xF3BC, 0x883A, 0xD054, + 0x883B, 0xD055, 0x883C, 0xF3BD, 0x883D, 0xD056, 0x883E, 0xD057, 0x883F, 0xD058, 0x8840, 0xD1AA, 0x8841, 0xD059, 0x8842, 0xD05A, + 0x8843, 0xD05B, 0x8844, 0xF4AC, 0x8845, 0xD0C6, 0x8846, 0xD05C, 0x8847, 0xD05D, 0x8848, 0xD05E, 0x8849, 0xD05F, 0x884A, 0xD060, + 0x884B, 0xD061, 0x884C, 0xD0D0, 0x884D, 0xD1DC, 0x884E, 0xD062, 0x884F, 0xD063, 0x8850, 0xD064, 0x8851, 0xD065, 0x8852, 0xD066, + 0x8853, 0xD067, 0x8854, 0xCFCE, 0x8855, 0xD068, 0x8856, 0xD069, 0x8857, 0xBDD6, 0x8858, 0xD06A, 0x8859, 0xD1C3, 0x885A, 0xD06B, + 0x885B, 0xD06C, 0x885C, 0xD06D, 0x885D, 0xD06E, 0x885E, 0xD06F, 0x885F, 0xD070, 0x8860, 0xD071, 0x8861, 0xBAE2, 0x8862, 0xE1E9, + 0x8863, 0xD2C2, 0x8864, 0xF1C2, 0x8865, 0xB2B9, 0x8866, 0xD072, 0x8867, 0xD073, 0x8868, 0xB1ED, 0x8869, 0xF1C3, 0x886A, 0xD074, + 0x886B, 0xC9C0, 0x886C, 0xB3C4, 0x886D, 0xD075, 0x886E, 0xD9F2, 0x886F, 0xD076, 0x8870, 0xCBA5, 0x8871, 0xD077, 0x8872, 0xF1C4, + 0x8873, 0xD078, 0x8874, 0xD079, 0x8875, 0xD07A, 0x8876, 0xD07B, 0x8877, 0xD6D4, 0x8878, 0xD07C, 0x8879, 0xD07D, 0x887A, 0xD07E, + 0x887B, 0xD080, 0x887C, 0xD081, 0x887D, 0xF1C5, 0x887E, 0xF4C0, 0x887F, 0xF1C6, 0x8880, 0xD082, 0x8881, 0xD4AC, 0x8882, 0xF1C7, + 0x8883, 0xD083, 0x8884, 0xB0C0, 0x8885, 0xF4C1, 0x8886, 0xD084, 0x8887, 0xD085, 0x8888, 0xF4C2, 0x8889, 0xD086, 0x888A, 0xD087, + 0x888B, 0xB4FC, 0x888C, 0xD088, 0x888D, 0xC5DB, 0x888E, 0xD089, 0x888F, 0xD08A, 0x8890, 0xD08B, 0x8891, 0xD08C, 0x8892, 0xCCBB, + 0x8893, 0xD08D, 0x8894, 0xD08E, 0x8895, 0xD08F, 0x8896, 0xD0E4, 0x8897, 0xD090, 0x8898, 0xD091, 0x8899, 0xD092, 0x889A, 0xD093, + 0x889B, 0xD094, 0x889C, 0xCDE0, 0x889D, 0xD095, 0x889E, 0xD096, 0x889F, 0xD097, 0x88A0, 0xD098, 0x88A1, 0xD099, 0x88A2, 0xF1C8, + 0x88A3, 0xD09A, 0x88A4, 0xD9F3, 0x88A5, 0xD09B, 0x88A6, 0xD09C, 0x88A7, 0xD09D, 0x88A8, 0xD09E, 0x88A9, 0xD09F, 0x88AA, 0xD0A0, + 0x88AB, 0xB1BB, 0x88AC, 0xD140, 0x88AD, 0xCFAE, 0x88AE, 0xD141, 0x88AF, 0xD142, 0x88B0, 0xD143, 0x88B1, 0xB8A4, 0x88B2, 0xD144, + 0x88B3, 0xD145, 0x88B4, 0xD146, 0x88B5, 0xD147, 0x88B6, 0xD148, 0x88B7, 0xF1CA, 0x88B8, 0xD149, 0x88B9, 0xD14A, 0x88BA, 0xD14B, + 0x88BB, 0xD14C, 0x88BC, 0xF1CB, 0x88BD, 0xD14D, 0x88BE, 0xD14E, 0x88BF, 0xD14F, 0x88C0, 0xD150, 0x88C1, 0xB2C3, 0x88C2, 0xC1D1, + 0x88C3, 0xD151, 0x88C4, 0xD152, 0x88C5, 0xD7B0, 0x88C6, 0xF1C9, 0x88C7, 0xD153, 0x88C8, 0xD154, 0x88C9, 0xF1CC, 0x88CA, 0xD155, + 0x88CB, 0xD156, 0x88CC, 0xD157, 0x88CD, 0xD158, 0x88CE, 0xF1CE, 0x88CF, 0xD159, 0x88D0, 0xD15A, 0x88D1, 0xD15B, 0x88D2, 0xD9F6, + 0x88D3, 0xD15C, 0x88D4, 0xD2E1, 0x88D5, 0xD4A3, 0x88D6, 0xD15D, 0x88D7, 0xD15E, 0x88D8, 0xF4C3, 0x88D9, 0xC8B9, 0x88DA, 0xD15F, + 0x88DB, 0xD160, 0x88DC, 0xD161, 0x88DD, 0xD162, 0x88DE, 0xD163, 0x88DF, 0xF4C4, 0x88E0, 0xD164, 0x88E1, 0xD165, 0x88E2, 0xF1CD, + 0x88E3, 0xF1CF, 0x88E4, 0xBFE3, 0x88E5, 0xF1D0, 0x88E6, 0xD166, 0x88E7, 0xD167, 0x88E8, 0xF1D4, 0x88E9, 0xD168, 0x88EA, 0xD169, + 0x88EB, 0xD16A, 0x88EC, 0xD16B, 0x88ED, 0xD16C, 0x88EE, 0xD16D, 0x88EF, 0xD16E, 0x88F0, 0xF1D6, 0x88F1, 0xF1D1, 0x88F2, 0xD16F, + 0x88F3, 0xC9D1, 0x88F4, 0xC5E1, 0x88F5, 0xD170, 0x88F6, 0xD171, 0x88F7, 0xD172, 0x88F8, 0xC2E3, 0x88F9, 0xB9FC, 0x88FA, 0xD173, + 0x88FB, 0xD174, 0x88FC, 0xF1D3, 0x88FD, 0xD175, 0x88FE, 0xF1D5, 0x88FF, 0xD176, 0x8900, 0xD177, 0x8901, 0xD178, 0x8902, 0xB9D3, + 0x8903, 0xD179, 0x8904, 0xD17A, 0x8905, 0xD17B, 0x8906, 0xD17C, 0x8907, 0xD17D, 0x8908, 0xD17E, 0x8909, 0xD180, 0x890A, 0xF1DB, + 0x890B, 0xD181, 0x890C, 0xD182, 0x890D, 0xD183, 0x890E, 0xD184, 0x890F, 0xD185, 0x8910, 0xBAD6, 0x8911, 0xD186, 0x8912, 0xB0FD, + 0x8913, 0xF1D9, 0x8914, 0xD187, 0x8915, 0xD188, 0x8916, 0xD189, 0x8917, 0xD18A, 0x8918, 0xD18B, 0x8919, 0xF1D8, 0x891A, 0xF1D2, + 0x891B, 0xF1DA, 0x891C, 0xD18C, 0x891D, 0xD18D, 0x891E, 0xD18E, 0x891F, 0xD18F, 0x8920, 0xD190, 0x8921, 0xF1D7, 0x8922, 0xD191, + 0x8923, 0xD192, 0x8924, 0xD193, 0x8925, 0xC8EC, 0x8926, 0xD194, 0x8927, 0xD195, 0x8928, 0xD196, 0x8929, 0xD197, 0x892A, 0xCDCA, + 0x892B, 0xF1DD, 0x892C, 0xD198, 0x892D, 0xD199, 0x892E, 0xD19A, 0x892F, 0xD19B, 0x8930, 0xE5BD, 0x8931, 0xD19C, 0x8932, 0xD19D, + 0x8933, 0xD19E, 0x8934, 0xF1DC, 0x8935, 0xD19F, 0x8936, 0xF1DE, 0x8937, 0xD1A0, 0x8938, 0xD240, 0x8939, 0xD241, 0x893A, 0xD242, + 0x893B, 0xD243, 0x893C, 0xD244, 0x893D, 0xD245, 0x893E, 0xD246, 0x893F, 0xD247, 0x8940, 0xD248, 0x8941, 0xF1DF, 0x8942, 0xD249, + 0x8943, 0xD24A, 0x8944, 0xCFE5, 0x8945, 0xD24B, 0x8946, 0xD24C, 0x8947, 0xD24D, 0x8948, 0xD24E, 0x8949, 0xD24F, 0x894A, 0xD250, + 0x894B, 0xD251, 0x894C, 0xD252, 0x894D, 0xD253, 0x894E, 0xD254, 0x894F, 0xD255, 0x8950, 0xD256, 0x8951, 0xD257, 0x8952, 0xD258, + 0x8953, 0xD259, 0x8954, 0xD25A, 0x8955, 0xD25B, 0x8956, 0xD25C, 0x8957, 0xD25D, 0x8958, 0xD25E, 0x8959, 0xD25F, 0x895A, 0xD260, + 0x895B, 0xD261, 0x895C, 0xD262, 0x895D, 0xD263, 0x895E, 0xF4C5, 0x895F, 0xBDF3, 0x8960, 0xD264, 0x8961, 0xD265, 0x8962, 0xD266, + 0x8963, 0xD267, 0x8964, 0xD268, 0x8965, 0xD269, 0x8966, 0xF1E0, 0x8967, 0xD26A, 0x8968, 0xD26B, 0x8969, 0xD26C, 0x896A, 0xD26D, + 0x896B, 0xD26E, 0x896C, 0xD26F, 0x896D, 0xD270, 0x896E, 0xD271, 0x896F, 0xD272, 0x8970, 0xD273, 0x8971, 0xD274, 0x8972, 0xD275, + 0x8973, 0xD276, 0x8974, 0xD277, 0x8975, 0xD278, 0x8976, 0xD279, 0x8977, 0xD27A, 0x8978, 0xD27B, 0x8979, 0xD27C, 0x897A, 0xD27D, + 0x897B, 0xF1E1, 0x897C, 0xD27E, 0x897D, 0xD280, 0x897E, 0xD281, 0x897F, 0xCEF7, 0x8980, 0xD282, 0x8981, 0xD2AA, 0x8982, 0xD283, + 0x8983, 0xF1FB, 0x8984, 0xD284, 0x8985, 0xD285, 0x8986, 0xB8B2, 0x8987, 0xD286, 0x8988, 0xD287, 0x8989, 0xD288, 0x898A, 0xD289, + 0x898B, 0xD28A, 0x898C, 0xD28B, 0x898D, 0xD28C, 0x898E, 0xD28D, 0x898F, 0xD28E, 0x8990, 0xD28F, 0x8991, 0xD290, 0x8992, 0xD291, + 0x8993, 0xD292, 0x8994, 0xD293, 0x8995, 0xD294, 0x8996, 0xD295, 0x8997, 0xD296, 0x8998, 0xD297, 0x8999, 0xD298, 0x899A, 0xD299, + 0x899B, 0xD29A, 0x899C, 0xD29B, 0x899D, 0xD29C, 0x899E, 0xD29D, 0x899F, 0xD29E, 0x89A0, 0xD29F, 0x89A1, 0xD2A0, 0x89A2, 0xD340, + 0x89A3, 0xD341, 0x89A4, 0xD342, 0x89A5, 0xD343, 0x89A6, 0xD344, 0x89A7, 0xD345, 0x89A8, 0xD346, 0x89A9, 0xD347, 0x89AA, 0xD348, + 0x89AB, 0xD349, 0x89AC, 0xD34A, 0x89AD, 0xD34B, 0x89AE, 0xD34C, 0x89AF, 0xD34D, 0x89B0, 0xD34E, 0x89B1, 0xD34F, 0x89B2, 0xD350, + 0x89B3, 0xD351, 0x89B4, 0xD352, 0x89B5, 0xD353, 0x89B6, 0xD354, 0x89B7, 0xD355, 0x89B8, 0xD356, 0x89B9, 0xD357, 0x89BA, 0xD358, + 0x89BB, 0xD359, 0x89BC, 0xD35A, 0x89BD, 0xD35B, 0x89BE, 0xD35C, 0x89BF, 0xD35D, 0x89C0, 0xD35E, 0x89C1, 0xBCFB, 0x89C2, 0xB9DB, + 0x89C3, 0xD35F, 0x89C4, 0xB9E6, 0x89C5, 0xC3D9, 0x89C6, 0xCAD3, 0x89C7, 0xEAE8, 0x89C8, 0xC0C0, 0x89C9, 0xBEF5, 0x89CA, 0xEAE9, + 0x89CB, 0xEAEA, 0x89CC, 0xEAEB, 0x89CD, 0xD360, 0x89CE, 0xEAEC, 0x89CF, 0xEAED, 0x89D0, 0xEAEE, 0x89D1, 0xEAEF, 0x89D2, 0xBDC7, + 0x89D3, 0xD361, 0x89D4, 0xD362, 0x89D5, 0xD363, 0x89D6, 0xF5FB, 0x89D7, 0xD364, 0x89D8, 0xD365, 0x89D9, 0xD366, 0x89DA, 0xF5FD, + 0x89DB, 0xD367, 0x89DC, 0xF5FE, 0x89DD, 0xD368, 0x89DE, 0xF5FC, 0x89DF, 0xD369, 0x89E0, 0xD36A, 0x89E1, 0xD36B, 0x89E2, 0xD36C, + 0x89E3, 0xBDE2, 0x89E4, 0xD36D, 0x89E5, 0xF6A1, 0x89E6, 0xB4A5, 0x89E7, 0xD36E, 0x89E8, 0xD36F, 0x89E9, 0xD370, 0x89EA, 0xD371, + 0x89EB, 0xF6A2, 0x89EC, 0xD372, 0x89ED, 0xD373, 0x89EE, 0xD374, 0x89EF, 0xF6A3, 0x89F0, 0xD375, 0x89F1, 0xD376, 0x89F2, 0xD377, + 0x89F3, 0xECB2, 0x89F4, 0xD378, 0x89F5, 0xD379, 0x89F6, 0xD37A, 0x89F7, 0xD37B, 0x89F8, 0xD37C, 0x89F9, 0xD37D, 0x89FA, 0xD37E, + 0x89FB, 0xD380, 0x89FC, 0xD381, 0x89FD, 0xD382, 0x89FE, 0xD383, 0x89FF, 0xD384, 0x8A00, 0xD1D4, 0x8A01, 0xD385, 0x8A02, 0xD386, + 0x8A03, 0xD387, 0x8A04, 0xD388, 0x8A05, 0xD389, 0x8A06, 0xD38A, 0x8A07, 0xD9EA, 0x8A08, 0xD38B, 0x8A09, 0xD38C, 0x8A0A, 0xD38D, + 0x8A0B, 0xD38E, 0x8A0C, 0xD38F, 0x8A0D, 0xD390, 0x8A0E, 0xD391, 0x8A0F, 0xD392, 0x8A10, 0xD393, 0x8A11, 0xD394, 0x8A12, 0xD395, + 0x8A13, 0xD396, 0x8A14, 0xD397, 0x8A15, 0xD398, 0x8A16, 0xD399, 0x8A17, 0xD39A, 0x8A18, 0xD39B, 0x8A19, 0xD39C, 0x8A1A, 0xD39D, + 0x8A1B, 0xD39E, 0x8A1C, 0xD39F, 0x8A1D, 0xD3A0, 0x8A1E, 0xD440, 0x8A1F, 0xD441, 0x8A20, 0xD442, 0x8A21, 0xD443, 0x8A22, 0xD444, + 0x8A23, 0xD445, 0x8A24, 0xD446, 0x8A25, 0xD447, 0x8A26, 0xD448, 0x8A27, 0xD449, 0x8A28, 0xD44A, 0x8A29, 0xD44B, 0x8A2A, 0xD44C, + 0x8A2B, 0xD44D, 0x8A2C, 0xD44E, 0x8A2D, 0xD44F, 0x8A2E, 0xD450, 0x8A2F, 0xD451, 0x8A30, 0xD452, 0x8A31, 0xD453, 0x8A32, 0xD454, + 0x8A33, 0xD455, 0x8A34, 0xD456, 0x8A35, 0xD457, 0x8A36, 0xD458, 0x8A37, 0xD459, 0x8A38, 0xD45A, 0x8A39, 0xD45B, 0x8A3A, 0xD45C, + 0x8A3B, 0xD45D, 0x8A3C, 0xD45E, 0x8A3D, 0xD45F, 0x8A3E, 0xF6A4, 0x8A3F, 0xD460, 0x8A40, 0xD461, 0x8A41, 0xD462, 0x8A42, 0xD463, + 0x8A43, 0xD464, 0x8A44, 0xD465, 0x8A45, 0xD466, 0x8A46, 0xD467, 0x8A47, 0xD468, 0x8A48, 0xEEBA, 0x8A49, 0xD469, 0x8A4A, 0xD46A, + 0x8A4B, 0xD46B, 0x8A4C, 0xD46C, 0x8A4D, 0xD46D, 0x8A4E, 0xD46E, 0x8A4F, 0xD46F, 0x8A50, 0xD470, 0x8A51, 0xD471, 0x8A52, 0xD472, + 0x8A53, 0xD473, 0x8A54, 0xD474, 0x8A55, 0xD475, 0x8A56, 0xD476, 0x8A57, 0xD477, 0x8A58, 0xD478, 0x8A59, 0xD479, 0x8A5A, 0xD47A, + 0x8A5B, 0xD47B, 0x8A5C, 0xD47C, 0x8A5D, 0xD47D, 0x8A5E, 0xD47E, 0x8A5F, 0xD480, 0x8A60, 0xD481, 0x8A61, 0xD482, 0x8A62, 0xD483, + 0x8A63, 0xD484, 0x8A64, 0xD485, 0x8A65, 0xD486, 0x8A66, 0xD487, 0x8A67, 0xD488, 0x8A68, 0xD489, 0x8A69, 0xD48A, 0x8A6A, 0xD48B, + 0x8A6B, 0xD48C, 0x8A6C, 0xD48D, 0x8A6D, 0xD48E, 0x8A6E, 0xD48F, 0x8A6F, 0xD490, 0x8A70, 0xD491, 0x8A71, 0xD492, 0x8A72, 0xD493, + 0x8A73, 0xD494, 0x8A74, 0xD495, 0x8A75, 0xD496, 0x8A76, 0xD497, 0x8A77, 0xD498, 0x8A78, 0xD499, 0x8A79, 0xD5B2, 0x8A7A, 0xD49A, + 0x8A7B, 0xD49B, 0x8A7C, 0xD49C, 0x8A7D, 0xD49D, 0x8A7E, 0xD49E, 0x8A7F, 0xD49F, 0x8A80, 0xD4A0, 0x8A81, 0xD540, 0x8A82, 0xD541, + 0x8A83, 0xD542, 0x8A84, 0xD543, 0x8A85, 0xD544, 0x8A86, 0xD545, 0x8A87, 0xD546, 0x8A88, 0xD547, 0x8A89, 0xD3FE, 0x8A8A, 0xCCDC, + 0x8A8B, 0xD548, 0x8A8C, 0xD549, 0x8A8D, 0xD54A, 0x8A8E, 0xD54B, 0x8A8F, 0xD54C, 0x8A90, 0xD54D, 0x8A91, 0xD54E, 0x8A92, 0xD54F, + 0x8A93, 0xCAC4, 0x8A94, 0xD550, 0x8A95, 0xD551, 0x8A96, 0xD552, 0x8A97, 0xD553, 0x8A98, 0xD554, 0x8A99, 0xD555, 0x8A9A, 0xD556, + 0x8A9B, 0xD557, 0x8A9C, 0xD558, 0x8A9D, 0xD559, 0x8A9E, 0xD55A, 0x8A9F, 0xD55B, 0x8AA0, 0xD55C, 0x8AA1, 0xD55D, 0x8AA2, 0xD55E, + 0x8AA3, 0xD55F, 0x8AA4, 0xD560, 0x8AA5, 0xD561, 0x8AA6, 0xD562, 0x8AA7, 0xD563, 0x8AA8, 0xD564, 0x8AA9, 0xD565, 0x8AAA, 0xD566, + 0x8AAB, 0xD567, 0x8AAC, 0xD568, 0x8AAD, 0xD569, 0x8AAE, 0xD56A, 0x8AAF, 0xD56B, 0x8AB0, 0xD56C, 0x8AB1, 0xD56D, 0x8AB2, 0xD56E, + 0x8AB3, 0xD56F, 0x8AB4, 0xD570, 0x8AB5, 0xD571, 0x8AB6, 0xD572, 0x8AB7, 0xD573, 0x8AB8, 0xD574, 0x8AB9, 0xD575, 0x8ABA, 0xD576, + 0x8ABB, 0xD577, 0x8ABC, 0xD578, 0x8ABD, 0xD579, 0x8ABE, 0xD57A, 0x8ABF, 0xD57B, 0x8AC0, 0xD57C, 0x8AC1, 0xD57D, 0x8AC2, 0xD57E, + 0x8AC3, 0xD580, 0x8AC4, 0xD581, 0x8AC5, 0xD582, 0x8AC6, 0xD583, 0x8AC7, 0xD584, 0x8AC8, 0xD585, 0x8AC9, 0xD586, 0x8ACA, 0xD587, + 0x8ACB, 0xD588, 0x8ACC, 0xD589, 0x8ACD, 0xD58A, 0x8ACE, 0xD58B, 0x8ACF, 0xD58C, 0x8AD0, 0xD58D, 0x8AD1, 0xD58E, 0x8AD2, 0xD58F, + 0x8AD3, 0xD590, 0x8AD4, 0xD591, 0x8AD5, 0xD592, 0x8AD6, 0xD593, 0x8AD7, 0xD594, 0x8AD8, 0xD595, 0x8AD9, 0xD596, 0x8ADA, 0xD597, + 0x8ADB, 0xD598, 0x8ADC, 0xD599, 0x8ADD, 0xD59A, 0x8ADE, 0xD59B, 0x8ADF, 0xD59C, 0x8AE0, 0xD59D, 0x8AE1, 0xD59E, 0x8AE2, 0xD59F, + 0x8AE3, 0xD5A0, 0x8AE4, 0xD640, 0x8AE5, 0xD641, 0x8AE6, 0xD642, 0x8AE7, 0xD643, 0x8AE8, 0xD644, 0x8AE9, 0xD645, 0x8AEA, 0xD646, + 0x8AEB, 0xD647, 0x8AEC, 0xD648, 0x8AED, 0xD649, 0x8AEE, 0xD64A, 0x8AEF, 0xD64B, 0x8AF0, 0xD64C, 0x8AF1, 0xD64D, 0x8AF2, 0xD64E, + 0x8AF3, 0xD64F, 0x8AF4, 0xD650, 0x8AF5, 0xD651, 0x8AF6, 0xD652, 0x8AF7, 0xD653, 0x8AF8, 0xD654, 0x8AF9, 0xD655, 0x8AFA, 0xD656, + 0x8AFB, 0xD657, 0x8AFC, 0xD658, 0x8AFD, 0xD659, 0x8AFE, 0xD65A, 0x8AFF, 0xD65B, 0x8B00, 0xD65C, 0x8B01, 0xD65D, 0x8B02, 0xD65E, + 0x8B03, 0xD65F, 0x8B04, 0xD660, 0x8B05, 0xD661, 0x8B06, 0xD662, 0x8B07, 0xE5C0, 0x8B08, 0xD663, 0x8B09, 0xD664, 0x8B0A, 0xD665, + 0x8B0B, 0xD666, 0x8B0C, 0xD667, 0x8B0D, 0xD668, 0x8B0E, 0xD669, 0x8B0F, 0xD66A, 0x8B10, 0xD66B, 0x8B11, 0xD66C, 0x8B12, 0xD66D, + 0x8B13, 0xD66E, 0x8B14, 0xD66F, 0x8B15, 0xD670, 0x8B16, 0xD671, 0x8B17, 0xD672, 0x8B18, 0xD673, 0x8B19, 0xD674, 0x8B1A, 0xD675, + 0x8B1B, 0xD676, 0x8B1C, 0xD677, 0x8B1D, 0xD678, 0x8B1E, 0xD679, 0x8B1F, 0xD67A, 0x8B20, 0xD67B, 0x8B21, 0xD67C, 0x8B22, 0xD67D, + 0x8B23, 0xD67E, 0x8B24, 0xD680, 0x8B25, 0xD681, 0x8B26, 0xF6A5, 0x8B27, 0xD682, 0x8B28, 0xD683, 0x8B29, 0xD684, 0x8B2A, 0xD685, + 0x8B2B, 0xD686, 0x8B2C, 0xD687, 0x8B2D, 0xD688, 0x8B2E, 0xD689, 0x8B2F, 0xD68A, 0x8B30, 0xD68B, 0x8B31, 0xD68C, 0x8B32, 0xD68D, + 0x8B33, 0xD68E, 0x8B34, 0xD68F, 0x8B35, 0xD690, 0x8B36, 0xD691, 0x8B37, 0xD692, 0x8B38, 0xD693, 0x8B39, 0xD694, 0x8B3A, 0xD695, + 0x8B3B, 0xD696, 0x8B3C, 0xD697, 0x8B3D, 0xD698, 0x8B3E, 0xD699, 0x8B3F, 0xD69A, 0x8B40, 0xD69B, 0x8B41, 0xD69C, 0x8B42, 0xD69D, + 0x8B43, 0xD69E, 0x8B44, 0xD69F, 0x8B45, 0xD6A0, 0x8B46, 0xD740, 0x8B47, 0xD741, 0x8B48, 0xD742, 0x8B49, 0xD743, 0x8B4A, 0xD744, + 0x8B4B, 0xD745, 0x8B4C, 0xD746, 0x8B4D, 0xD747, 0x8B4E, 0xD748, 0x8B4F, 0xD749, 0x8B50, 0xD74A, 0x8B51, 0xD74B, 0x8B52, 0xD74C, + 0x8B53, 0xD74D, 0x8B54, 0xD74E, 0x8B55, 0xD74F, 0x8B56, 0xD750, 0x8B57, 0xD751, 0x8B58, 0xD752, 0x8B59, 0xD753, 0x8B5A, 0xD754, + 0x8B5B, 0xD755, 0x8B5C, 0xD756, 0x8B5D, 0xD757, 0x8B5E, 0xD758, 0x8B5F, 0xD759, 0x8B60, 0xD75A, 0x8B61, 0xD75B, 0x8B62, 0xD75C, + 0x8B63, 0xD75D, 0x8B64, 0xD75E, 0x8B65, 0xD75F, 0x8B66, 0xBEAF, 0x8B67, 0xD760, 0x8B68, 0xD761, 0x8B69, 0xD762, 0x8B6A, 0xD763, + 0x8B6B, 0xD764, 0x8B6C, 0xC6A9, 0x8B6D, 0xD765, 0x8B6E, 0xD766, 0x8B6F, 0xD767, 0x8B70, 0xD768, 0x8B71, 0xD769, 0x8B72, 0xD76A, + 0x8B73, 0xD76B, 0x8B74, 0xD76C, 0x8B75, 0xD76D, 0x8B76, 0xD76E, 0x8B77, 0xD76F, 0x8B78, 0xD770, 0x8B79, 0xD771, 0x8B7A, 0xD772, + 0x8B7B, 0xD773, 0x8B7C, 0xD774, 0x8B7D, 0xD775, 0x8B7E, 0xD776, 0x8B7F, 0xD777, 0x8B80, 0xD778, 0x8B81, 0xD779, 0x8B82, 0xD77A, + 0x8B83, 0xD77B, 0x8B84, 0xD77C, 0x8B85, 0xD77D, 0x8B86, 0xD77E, 0x8B87, 0xD780, 0x8B88, 0xD781, 0x8B89, 0xD782, 0x8B8A, 0xD783, + 0x8B8B, 0xD784, 0x8B8C, 0xD785, 0x8B8D, 0xD786, 0x8B8E, 0xD787, 0x8B8F, 0xD788, 0x8B90, 0xD789, 0x8B91, 0xD78A, 0x8B92, 0xD78B, + 0x8B93, 0xD78C, 0x8B94, 0xD78D, 0x8B95, 0xD78E, 0x8B96, 0xD78F, 0x8B97, 0xD790, 0x8B98, 0xD791, 0x8B99, 0xD792, 0x8B9A, 0xD793, + 0x8B9B, 0xD794, 0x8B9C, 0xD795, 0x8B9D, 0xD796, 0x8B9E, 0xD797, 0x8B9F, 0xD798, 0x8BA0, 0xDAA5, 0x8BA1, 0xBCC6, 0x8BA2, 0xB6A9, + 0x8BA3, 0xB8BC, 0x8BA4, 0xC8CF, 0x8BA5, 0xBCA5, 0x8BA6, 0xDAA6, 0x8BA7, 0xDAA7, 0x8BA8, 0xCCD6, 0x8BA9, 0xC8C3, 0x8BAA, 0xDAA8, + 0x8BAB, 0xC6FD, 0x8BAC, 0xD799, 0x8BAD, 0xD1B5, 0x8BAE, 0xD2E9, 0x8BAF, 0xD1B6, 0x8BB0, 0xBCC7, 0x8BB1, 0xD79A, 0x8BB2, 0xBDB2, + 0x8BB3, 0xBBE4, 0x8BB4, 0xDAA9, 0x8BB5, 0xDAAA, 0x8BB6, 0xD1C8, 0x8BB7, 0xDAAB, 0x8BB8, 0xD0ED, 0x8BB9, 0xB6EF, 0x8BBA, 0xC2DB, + 0x8BBB, 0xD79B, 0x8BBC, 0xCBCF, 0x8BBD, 0xB7ED, 0x8BBE, 0xC9E8, 0x8BBF, 0xB7C3, 0x8BC0, 0xBEF7, 0x8BC1, 0xD6A4, 0x8BC2, 0xDAAC, + 0x8BC3, 0xDAAD, 0x8BC4, 0xC6C0, 0x8BC5, 0xD7E7, 0x8BC6, 0xCAB6, 0x8BC7, 0xD79C, 0x8BC8, 0xD5A9, 0x8BC9, 0xCBDF, 0x8BCA, 0xD5EF, + 0x8BCB, 0xDAAE, 0x8BCC, 0xD6DF, 0x8BCD, 0xB4CA, 0x8BCE, 0xDAB0, 0x8BCF, 0xDAAF, 0x8BD0, 0xD79D, 0x8BD1, 0xD2EB, 0x8BD2, 0xDAB1, + 0x8BD3, 0xDAB2, 0x8BD4, 0xDAB3, 0x8BD5, 0xCAD4, 0x8BD6, 0xDAB4, 0x8BD7, 0xCAAB, 0x8BD8, 0xDAB5, 0x8BD9, 0xDAB6, 0x8BDA, 0xB3CF, + 0x8BDB, 0xD6EF, 0x8BDC, 0xDAB7, 0x8BDD, 0xBBB0, 0x8BDE, 0xB5AE, 0x8BDF, 0xDAB8, 0x8BE0, 0xDAB9, 0x8BE1, 0xB9EE, 0x8BE2, 0xD1AF, + 0x8BE3, 0xD2E8, 0x8BE4, 0xDABA, 0x8BE5, 0xB8C3, 0x8BE6, 0xCFEA, 0x8BE7, 0xB2EF, 0x8BE8, 0xDABB, 0x8BE9, 0xDABC, 0x8BEA, 0xD79E, + 0x8BEB, 0xBDEB, 0x8BEC, 0xCEDC, 0x8BED, 0xD3EF, 0x8BEE, 0xDABD, 0x8BEF, 0xCEF3, 0x8BF0, 0xDABE, 0x8BF1, 0xD3D5, 0x8BF2, 0xBBE5, + 0x8BF3, 0xDABF, 0x8BF4, 0xCBB5, 0x8BF5, 0xCBD0, 0x8BF6, 0xDAC0, 0x8BF7, 0xC7EB, 0x8BF8, 0xD6EE, 0x8BF9, 0xDAC1, 0x8BFA, 0xC5B5, + 0x8BFB, 0xB6C1, 0x8BFC, 0xDAC2, 0x8BFD, 0xB7CC, 0x8BFE, 0xBFCE, 0x8BFF, 0xDAC3, 0x8C00, 0xDAC4, 0x8C01, 0xCBAD, 0x8C02, 0xDAC5, + 0x8C03, 0xB5F7, 0x8C04, 0xDAC6, 0x8C05, 0xC1C2, 0x8C06, 0xD7BB, 0x8C07, 0xDAC7, 0x8C08, 0xCCB8, 0x8C09, 0xD79F, 0x8C0A, 0xD2EA, + 0x8C0B, 0xC4B1, 0x8C0C, 0xDAC8, 0x8C0D, 0xB5FD, 0x8C0E, 0xBBD1, 0x8C0F, 0xDAC9, 0x8C10, 0xD0B3, 0x8C11, 0xDACA, 0x8C12, 0xDACB, + 0x8C13, 0xCEBD, 0x8C14, 0xDACC, 0x8C15, 0xDACD, 0x8C16, 0xDACE, 0x8C17, 0xB2F7, 0x8C18, 0xDAD1, 0x8C19, 0xDACF, 0x8C1A, 0xD1E8, + 0x8C1B, 0xDAD0, 0x8C1C, 0xC3D5, 0x8C1D, 0xDAD2, 0x8C1E, 0xD7A0, 0x8C1F, 0xDAD3, 0x8C20, 0xDAD4, 0x8C21, 0xDAD5, 0x8C22, 0xD0BB, + 0x8C23, 0xD2A5, 0x8C24, 0xB0F9, 0x8C25, 0xDAD6, 0x8C26, 0xC7AB, 0x8C27, 0xDAD7, 0x8C28, 0xBDF7, 0x8C29, 0xC3A1, 0x8C2A, 0xDAD8, + 0x8C2B, 0xDAD9, 0x8C2C, 0xC3FD, 0x8C2D, 0xCCB7, 0x8C2E, 0xDADA, 0x8C2F, 0xDADB, 0x8C30, 0xC0BE, 0x8C31, 0xC6D7, 0x8C32, 0xDADC, + 0x8C33, 0xDADD, 0x8C34, 0xC7B4, 0x8C35, 0xDADE, 0x8C36, 0xDADF, 0x8C37, 0xB9C8, 0x8C38, 0xD840, 0x8C39, 0xD841, 0x8C3A, 0xD842, + 0x8C3B, 0xD843, 0x8C3C, 0xD844, 0x8C3D, 0xD845, 0x8C3E, 0xD846, 0x8C3F, 0xD847, 0x8C40, 0xD848, 0x8C41, 0xBBED, 0x8C42, 0xD849, + 0x8C43, 0xD84A, 0x8C44, 0xD84B, 0x8C45, 0xD84C, 0x8C46, 0xB6B9, 0x8C47, 0xF4F8, 0x8C48, 0xD84D, 0x8C49, 0xF4F9, 0x8C4A, 0xD84E, + 0x8C4B, 0xD84F, 0x8C4C, 0xCDE3, 0x8C4D, 0xD850, 0x8C4E, 0xD851, 0x8C4F, 0xD852, 0x8C50, 0xD853, 0x8C51, 0xD854, 0x8C52, 0xD855, + 0x8C53, 0xD856, 0x8C54, 0xD857, 0x8C55, 0xF5B9, 0x8C56, 0xD858, 0x8C57, 0xD859, 0x8C58, 0xD85A, 0x8C59, 0xD85B, 0x8C5A, 0xEBE0, + 0x8C5B, 0xD85C, 0x8C5C, 0xD85D, 0x8C5D, 0xD85E, 0x8C5E, 0xD85F, 0x8C5F, 0xD860, 0x8C60, 0xD861, 0x8C61, 0xCFF3, 0x8C62, 0xBBBF, + 0x8C63, 0xD862, 0x8C64, 0xD863, 0x8C65, 0xD864, 0x8C66, 0xD865, 0x8C67, 0xD866, 0x8C68, 0xD867, 0x8C69, 0xD868, 0x8C6A, 0xBAC0, + 0x8C6B, 0xD4A5, 0x8C6C, 0xD869, 0x8C6D, 0xD86A, 0x8C6E, 0xD86B, 0x8C6F, 0xD86C, 0x8C70, 0xD86D, 0x8C71, 0xD86E, 0x8C72, 0xD86F, + 0x8C73, 0xE1D9, 0x8C74, 0xD870, 0x8C75, 0xD871, 0x8C76, 0xD872, 0x8C77, 0xD873, 0x8C78, 0xF5F4, 0x8C79, 0xB1AA, 0x8C7A, 0xB2F2, + 0x8C7B, 0xD874, 0x8C7C, 0xD875, 0x8C7D, 0xD876, 0x8C7E, 0xD877, 0x8C7F, 0xD878, 0x8C80, 0xD879, 0x8C81, 0xD87A, 0x8C82, 0xF5F5, + 0x8C83, 0xD87B, 0x8C84, 0xD87C, 0x8C85, 0xF5F7, 0x8C86, 0xD87D, 0x8C87, 0xD87E, 0x8C88, 0xD880, 0x8C89, 0xBAD1, 0x8C8A, 0xF5F6, + 0x8C8B, 0xD881, 0x8C8C, 0xC3B2, 0x8C8D, 0xD882, 0x8C8E, 0xD883, 0x8C8F, 0xD884, 0x8C90, 0xD885, 0x8C91, 0xD886, 0x8C92, 0xD887, + 0x8C93, 0xD888, 0x8C94, 0xF5F9, 0x8C95, 0xD889, 0x8C96, 0xD88A, 0x8C97, 0xD88B, 0x8C98, 0xF5F8, 0x8C99, 0xD88C, 0x8C9A, 0xD88D, + 0x8C9B, 0xD88E, 0x8C9C, 0xD88F, 0x8C9D, 0xD890, 0x8C9E, 0xD891, 0x8C9F, 0xD892, 0x8CA0, 0xD893, 0x8CA1, 0xD894, 0x8CA2, 0xD895, + 0x8CA3, 0xD896, 0x8CA4, 0xD897, 0x8CA5, 0xD898, 0x8CA6, 0xD899, 0x8CA7, 0xD89A, 0x8CA8, 0xD89B, 0x8CA9, 0xD89C, 0x8CAA, 0xD89D, + 0x8CAB, 0xD89E, 0x8CAC, 0xD89F, 0x8CAD, 0xD8A0, 0x8CAE, 0xD940, 0x8CAF, 0xD941, 0x8CB0, 0xD942, 0x8CB1, 0xD943, 0x8CB2, 0xD944, + 0x8CB3, 0xD945, 0x8CB4, 0xD946, 0x8CB5, 0xD947, 0x8CB6, 0xD948, 0x8CB7, 0xD949, 0x8CB8, 0xD94A, 0x8CB9, 0xD94B, 0x8CBA, 0xD94C, + 0x8CBB, 0xD94D, 0x8CBC, 0xD94E, 0x8CBD, 0xD94F, 0x8CBE, 0xD950, 0x8CBF, 0xD951, 0x8CC0, 0xD952, 0x8CC1, 0xD953, 0x8CC2, 0xD954, + 0x8CC3, 0xD955, 0x8CC4, 0xD956, 0x8CC5, 0xD957, 0x8CC6, 0xD958, 0x8CC7, 0xD959, 0x8CC8, 0xD95A, 0x8CC9, 0xD95B, 0x8CCA, 0xD95C, + 0x8CCB, 0xD95D, 0x8CCC, 0xD95E, 0x8CCD, 0xD95F, 0x8CCE, 0xD960, 0x8CCF, 0xD961, 0x8CD0, 0xD962, 0x8CD1, 0xD963, 0x8CD2, 0xD964, + 0x8CD3, 0xD965, 0x8CD4, 0xD966, 0x8CD5, 0xD967, 0x8CD6, 0xD968, 0x8CD7, 0xD969, 0x8CD8, 0xD96A, 0x8CD9, 0xD96B, 0x8CDA, 0xD96C, + 0x8CDB, 0xD96D, 0x8CDC, 0xD96E, 0x8CDD, 0xD96F, 0x8CDE, 0xD970, 0x8CDF, 0xD971, 0x8CE0, 0xD972, 0x8CE1, 0xD973, 0x8CE2, 0xD974, + 0x8CE3, 0xD975, 0x8CE4, 0xD976, 0x8CE5, 0xD977, 0x8CE6, 0xD978, 0x8CE7, 0xD979, 0x8CE8, 0xD97A, 0x8CE9, 0xD97B, 0x8CEA, 0xD97C, + 0x8CEB, 0xD97D, 0x8CEC, 0xD97E, 0x8CED, 0xD980, 0x8CEE, 0xD981, 0x8CEF, 0xD982, 0x8CF0, 0xD983, 0x8CF1, 0xD984, 0x8CF2, 0xD985, + 0x8CF3, 0xD986, 0x8CF4, 0xD987, 0x8CF5, 0xD988, 0x8CF6, 0xD989, 0x8CF7, 0xD98A, 0x8CF8, 0xD98B, 0x8CF9, 0xD98C, 0x8CFA, 0xD98D, + 0x8CFB, 0xD98E, 0x8CFC, 0xD98F, 0x8CFD, 0xD990, 0x8CFE, 0xD991, 0x8CFF, 0xD992, 0x8D00, 0xD993, 0x8D01, 0xD994, 0x8D02, 0xD995, + 0x8D03, 0xD996, 0x8D04, 0xD997, 0x8D05, 0xD998, 0x8D06, 0xD999, 0x8D07, 0xD99A, 0x8D08, 0xD99B, 0x8D09, 0xD99C, 0x8D0A, 0xD99D, + 0x8D0B, 0xD99E, 0x8D0C, 0xD99F, 0x8D0D, 0xD9A0, 0x8D0E, 0xDA40, 0x8D0F, 0xDA41, 0x8D10, 0xDA42, 0x8D11, 0xDA43, 0x8D12, 0xDA44, + 0x8D13, 0xDA45, 0x8D14, 0xDA46, 0x8D15, 0xDA47, 0x8D16, 0xDA48, 0x8D17, 0xDA49, 0x8D18, 0xDA4A, 0x8D19, 0xDA4B, 0x8D1A, 0xDA4C, + 0x8D1B, 0xDA4D, 0x8D1C, 0xDA4E, 0x8D1D, 0xB1B4, 0x8D1E, 0xD5EA, 0x8D1F, 0xB8BA, 0x8D20, 0xDA4F, 0x8D21, 0xB9B1, 0x8D22, 0xB2C6, + 0x8D23, 0xD4F0, 0x8D24, 0xCFCD, 0x8D25, 0xB0DC, 0x8D26, 0xD5CB, 0x8D27, 0xBBF5, 0x8D28, 0xD6CA, 0x8D29, 0xB7B7, 0x8D2A, 0xCCB0, + 0x8D2B, 0xC6B6, 0x8D2C, 0xB1E1, 0x8D2D, 0xB9BA, 0x8D2E, 0xD6FC, 0x8D2F, 0xB9E1, 0x8D30, 0xB7A1, 0x8D31, 0xBCFA, 0x8D32, 0xEADA, + 0x8D33, 0xEADB, 0x8D34, 0xCCF9, 0x8D35, 0xB9F3, 0x8D36, 0xEADC, 0x8D37, 0xB4FB, 0x8D38, 0xC3B3, 0x8D39, 0xB7D1, 0x8D3A, 0xBAD8, + 0x8D3B, 0xEADD, 0x8D3C, 0xD4F4, 0x8D3D, 0xEADE, 0x8D3E, 0xBCD6, 0x8D3F, 0xBBDF, 0x8D40, 0xEADF, 0x8D41, 0xC1DE, 0x8D42, 0xC2B8, + 0x8D43, 0xD4DF, 0x8D44, 0xD7CA, 0x8D45, 0xEAE0, 0x8D46, 0xEAE1, 0x8D47, 0xEAE4, 0x8D48, 0xEAE2, 0x8D49, 0xEAE3, 0x8D4A, 0xC9DE, + 0x8D4B, 0xB8B3, 0x8D4C, 0xB6C4, 0x8D4D, 0xEAE5, 0x8D4E, 0xCAEA, 0x8D4F, 0xC9CD, 0x8D50, 0xB4CD, 0x8D51, 0xDA50, 0x8D52, 0xDA51, + 0x8D53, 0xE2D9, 0x8D54, 0xC5E2, 0x8D55, 0xEAE6, 0x8D56, 0xC0B5, 0x8D57, 0xDA52, 0x8D58, 0xD7B8, 0x8D59, 0xEAE7, 0x8D5A, 0xD7AC, + 0x8D5B, 0xC8FC, 0x8D5C, 0xD8D3, 0x8D5D, 0xD8CD, 0x8D5E, 0xD4DE, 0x8D5F, 0xDA53, 0x8D60, 0xD4F9, 0x8D61, 0xC9C4, 0x8D62, 0xD3AE, + 0x8D63, 0xB8D3, 0x8D64, 0xB3E0, 0x8D65, 0xDA54, 0x8D66, 0xC9E2, 0x8D67, 0xF4F6, 0x8D68, 0xDA55, 0x8D69, 0xDA56, 0x8D6A, 0xDA57, + 0x8D6B, 0xBAD5, 0x8D6C, 0xDA58, 0x8D6D, 0xF4F7, 0x8D6E, 0xDA59, 0x8D6F, 0xDA5A, 0x8D70, 0xD7DF, 0x8D71, 0xDA5B, 0x8D72, 0xDA5C, + 0x8D73, 0xF4F1, 0x8D74, 0xB8B0, 0x8D75, 0xD5D4, 0x8D76, 0xB8CF, 0x8D77, 0xC6F0, 0x8D78, 0xDA5D, 0x8D79, 0xDA5E, 0x8D7A, 0xDA5F, + 0x8D7B, 0xDA60, 0x8D7C, 0xDA61, 0x8D7D, 0xDA62, 0x8D7E, 0xDA63, 0x8D7F, 0xDA64, 0x8D80, 0xDA65, 0x8D81, 0xB3C3, 0x8D82, 0xDA66, + 0x8D83, 0xDA67, 0x8D84, 0xF4F2, 0x8D85, 0xB3AC, 0x8D86, 0xDA68, 0x8D87, 0xDA69, 0x8D88, 0xDA6A, 0x8D89, 0xDA6B, 0x8D8A, 0xD4BD, + 0x8D8B, 0xC7F7, 0x8D8C, 0xDA6C, 0x8D8D, 0xDA6D, 0x8D8E, 0xDA6E, 0x8D8F, 0xDA6F, 0x8D90, 0xDA70, 0x8D91, 0xF4F4, 0x8D92, 0xDA71, + 0x8D93, 0xDA72, 0x8D94, 0xF4F3, 0x8D95, 0xDA73, 0x8D96, 0xDA74, 0x8D97, 0xDA75, 0x8D98, 0xDA76, 0x8D99, 0xDA77, 0x8D9A, 0xDA78, + 0x8D9B, 0xDA79, 0x8D9C, 0xDA7A, 0x8D9D, 0xDA7B, 0x8D9E, 0xDA7C, 0x8D9F, 0xCCCB, 0x8DA0, 0xDA7D, 0x8DA1, 0xDA7E, 0x8DA2, 0xDA80, + 0x8DA3, 0xC8A4, 0x8DA4, 0xDA81, 0x8DA5, 0xDA82, 0x8DA6, 0xDA83, 0x8DA7, 0xDA84, 0x8DA8, 0xDA85, 0x8DA9, 0xDA86, 0x8DAA, 0xDA87, + 0x8DAB, 0xDA88, 0x8DAC, 0xDA89, 0x8DAD, 0xDA8A, 0x8DAE, 0xDA8B, 0x8DAF, 0xDA8C, 0x8DB0, 0xDA8D, 0x8DB1, 0xF4F5, 0x8DB2, 0xDA8E, + 0x8DB3, 0xD7E3, 0x8DB4, 0xC5BF, 0x8DB5, 0xF5C0, 0x8DB6, 0xDA8F, 0x8DB7, 0xDA90, 0x8DB8, 0xF5BB, 0x8DB9, 0xDA91, 0x8DBA, 0xF5C3, + 0x8DBB, 0xDA92, 0x8DBC, 0xF5C2, 0x8DBD, 0xDA93, 0x8DBE, 0xD6BA, 0x8DBF, 0xF5C1, 0x8DC0, 0xDA94, 0x8DC1, 0xDA95, 0x8DC2, 0xDA96, + 0x8DC3, 0xD4BE, 0x8DC4, 0xF5C4, 0x8DC5, 0xDA97, 0x8DC6, 0xF5CC, 0x8DC7, 0xDA98, 0x8DC8, 0xDA99, 0x8DC9, 0xDA9A, 0x8DCA, 0xDA9B, + 0x8DCB, 0xB0CF, 0x8DCC, 0xB5F8, 0x8DCD, 0xDA9C, 0x8DCE, 0xF5C9, 0x8DCF, 0xF5CA, 0x8DD0, 0xDA9D, 0x8DD1, 0xC5DC, 0x8DD2, 0xDA9E, + 0x8DD3, 0xDA9F, 0x8DD4, 0xDAA0, 0x8DD5, 0xDB40, 0x8DD6, 0xF5C5, 0x8DD7, 0xF5C6, 0x8DD8, 0xDB41, 0x8DD9, 0xDB42, 0x8DDA, 0xF5C7, + 0x8DDB, 0xF5CB, 0x8DDC, 0xDB43, 0x8DDD, 0xBEE0, 0x8DDE, 0xF5C8, 0x8DDF, 0xB8FA, 0x8DE0, 0xDB44, 0x8DE1, 0xDB45, 0x8DE2, 0xDB46, + 0x8DE3, 0xF5D0, 0x8DE4, 0xF5D3, 0x8DE5, 0xDB47, 0x8DE6, 0xDB48, 0x8DE7, 0xDB49, 0x8DE8, 0xBFE7, 0x8DE9, 0xDB4A, 0x8DEA, 0xB9F2, + 0x8DEB, 0xF5BC, 0x8DEC, 0xF5CD, 0x8DED, 0xDB4B, 0x8DEE, 0xDB4C, 0x8DEF, 0xC2B7, 0x8DF0, 0xDB4D, 0x8DF1, 0xDB4E, 0x8DF2, 0xDB4F, + 0x8DF3, 0xCCF8, 0x8DF4, 0xDB50, 0x8DF5, 0xBCF9, 0x8DF6, 0xDB51, 0x8DF7, 0xF5CE, 0x8DF8, 0xF5CF, 0x8DF9, 0xF5D1, 0x8DFA, 0xB6E5, + 0x8DFB, 0xF5D2, 0x8DFC, 0xDB52, 0x8DFD, 0xF5D5, 0x8DFE, 0xDB53, 0x8DFF, 0xDB54, 0x8E00, 0xDB55, 0x8E01, 0xDB56, 0x8E02, 0xDB57, + 0x8E03, 0xDB58, 0x8E04, 0xDB59, 0x8E05, 0xF5BD, 0x8E06, 0xDB5A, 0x8E07, 0xDB5B, 0x8E08, 0xDB5C, 0x8E09, 0xF5D4, 0x8E0A, 0xD3BB, + 0x8E0B, 0xDB5D, 0x8E0C, 0xB3EC, 0x8E0D, 0xDB5E, 0x8E0E, 0xDB5F, 0x8E0F, 0xCCA4, 0x8E10, 0xDB60, 0x8E11, 0xDB61, 0x8E12, 0xDB62, + 0x8E13, 0xDB63, 0x8E14, 0xF5D6, 0x8E15, 0xDB64, 0x8E16, 0xDB65, 0x8E17, 0xDB66, 0x8E18, 0xDB67, 0x8E19, 0xDB68, 0x8E1A, 0xDB69, + 0x8E1B, 0xDB6A, 0x8E1C, 0xDB6B, 0x8E1D, 0xF5D7, 0x8E1E, 0xBEE1, 0x8E1F, 0xF5D8, 0x8E20, 0xDB6C, 0x8E21, 0xDB6D, 0x8E22, 0xCCDF, + 0x8E23, 0xF5DB, 0x8E24, 0xDB6E, 0x8E25, 0xDB6F, 0x8E26, 0xDB70, 0x8E27, 0xDB71, 0x8E28, 0xDB72, 0x8E29, 0xB2C8, 0x8E2A, 0xD7D9, + 0x8E2B, 0xDB73, 0x8E2C, 0xF5D9, 0x8E2D, 0xDB74, 0x8E2E, 0xF5DA, 0x8E2F, 0xF5DC, 0x8E30, 0xDB75, 0x8E31, 0xF5E2, 0x8E32, 0xDB76, + 0x8E33, 0xDB77, 0x8E34, 0xDB78, 0x8E35, 0xF5E0, 0x8E36, 0xDB79, 0x8E37, 0xDB7A, 0x8E38, 0xDB7B, 0x8E39, 0xF5DF, 0x8E3A, 0xF5DD, + 0x8E3B, 0xDB7C, 0x8E3C, 0xDB7D, 0x8E3D, 0xF5E1, 0x8E3E, 0xDB7E, 0x8E3F, 0xDB80, 0x8E40, 0xF5DE, 0x8E41, 0xF5E4, 0x8E42, 0xF5E5, + 0x8E43, 0xDB81, 0x8E44, 0xCCE3, 0x8E45, 0xDB82, 0x8E46, 0xDB83, 0x8E47, 0xE5BF, 0x8E48, 0xB5B8, 0x8E49, 0xF5E3, 0x8E4A, 0xF5E8, + 0x8E4B, 0xCCA3, 0x8E4C, 0xDB84, 0x8E4D, 0xDB85, 0x8E4E, 0xDB86, 0x8E4F, 0xDB87, 0x8E50, 0xDB88, 0x8E51, 0xF5E6, 0x8E52, 0xF5E7, + 0x8E53, 0xDB89, 0x8E54, 0xDB8A, 0x8E55, 0xDB8B, 0x8E56, 0xDB8C, 0x8E57, 0xDB8D, 0x8E58, 0xDB8E, 0x8E59, 0xF5BE, 0x8E5A, 0xDB8F, + 0x8E5B, 0xDB90, 0x8E5C, 0xDB91, 0x8E5D, 0xDB92, 0x8E5E, 0xDB93, 0x8E5F, 0xDB94, 0x8E60, 0xDB95, 0x8E61, 0xDB96, 0x8E62, 0xDB97, + 0x8E63, 0xDB98, 0x8E64, 0xDB99, 0x8E65, 0xDB9A, 0x8E66, 0xB1C4, 0x8E67, 0xDB9B, 0x8E68, 0xDB9C, 0x8E69, 0xF5BF, 0x8E6A, 0xDB9D, + 0x8E6B, 0xDB9E, 0x8E6C, 0xB5C5, 0x8E6D, 0xB2E4, 0x8E6E, 0xDB9F, 0x8E6F, 0xF5EC, 0x8E70, 0xF5E9, 0x8E71, 0xDBA0, 0x8E72, 0xB6D7, + 0x8E73, 0xDC40, 0x8E74, 0xF5ED, 0x8E75, 0xDC41, 0x8E76, 0xF5EA, 0x8E77, 0xDC42, 0x8E78, 0xDC43, 0x8E79, 0xDC44, 0x8E7A, 0xDC45, + 0x8E7B, 0xDC46, 0x8E7C, 0xF5EB, 0x8E7D, 0xDC47, 0x8E7E, 0xDC48, 0x8E7F, 0xB4DA, 0x8E80, 0xDC49, 0x8E81, 0xD4EA, 0x8E82, 0xDC4A, + 0x8E83, 0xDC4B, 0x8E84, 0xDC4C, 0x8E85, 0xF5EE, 0x8E86, 0xDC4D, 0x8E87, 0xB3F9, 0x8E88, 0xDC4E, 0x8E89, 0xDC4F, 0x8E8A, 0xDC50, + 0x8E8B, 0xDC51, 0x8E8C, 0xDC52, 0x8E8D, 0xDC53, 0x8E8E, 0xDC54, 0x8E8F, 0xF5EF, 0x8E90, 0xF5F1, 0x8E91, 0xDC55, 0x8E92, 0xDC56, + 0x8E93, 0xDC57, 0x8E94, 0xF5F0, 0x8E95, 0xDC58, 0x8E96, 0xDC59, 0x8E97, 0xDC5A, 0x8E98, 0xDC5B, 0x8E99, 0xDC5C, 0x8E9A, 0xDC5D, + 0x8E9B, 0xDC5E, 0x8E9C, 0xF5F2, 0x8E9D, 0xDC5F, 0x8E9E, 0xF5F3, 0x8E9F, 0xDC60, 0x8EA0, 0xDC61, 0x8EA1, 0xDC62, 0x8EA2, 0xDC63, + 0x8EA3, 0xDC64, 0x8EA4, 0xDC65, 0x8EA5, 0xDC66, 0x8EA6, 0xDC67, 0x8EA7, 0xDC68, 0x8EA8, 0xDC69, 0x8EA9, 0xDC6A, 0x8EAA, 0xDC6B, + 0x8EAB, 0xC9ED, 0x8EAC, 0xB9AA, 0x8EAD, 0xDC6C, 0x8EAE, 0xDC6D, 0x8EAF, 0xC7FB, 0x8EB0, 0xDC6E, 0x8EB1, 0xDC6F, 0x8EB2, 0xB6E3, + 0x8EB3, 0xDC70, 0x8EB4, 0xDC71, 0x8EB5, 0xDC72, 0x8EB6, 0xDC73, 0x8EB7, 0xDC74, 0x8EB8, 0xDC75, 0x8EB9, 0xDC76, 0x8EBA, 0xCCC9, + 0x8EBB, 0xDC77, 0x8EBC, 0xDC78, 0x8EBD, 0xDC79, 0x8EBE, 0xDC7A, 0x8EBF, 0xDC7B, 0x8EC0, 0xDC7C, 0x8EC1, 0xDC7D, 0x8EC2, 0xDC7E, + 0x8EC3, 0xDC80, 0x8EC4, 0xDC81, 0x8EC5, 0xDC82, 0x8EC6, 0xDC83, 0x8EC7, 0xDC84, 0x8EC8, 0xDC85, 0x8EC9, 0xDC86, 0x8ECA, 0xDC87, + 0x8ECB, 0xDC88, 0x8ECC, 0xDC89, 0x8ECD, 0xDC8A, 0x8ECE, 0xEAA6, 0x8ECF, 0xDC8B, 0x8ED0, 0xDC8C, 0x8ED1, 0xDC8D, 0x8ED2, 0xDC8E, + 0x8ED3, 0xDC8F, 0x8ED4, 0xDC90, 0x8ED5, 0xDC91, 0x8ED6, 0xDC92, 0x8ED7, 0xDC93, 0x8ED8, 0xDC94, 0x8ED9, 0xDC95, 0x8EDA, 0xDC96, + 0x8EDB, 0xDC97, 0x8EDC, 0xDC98, 0x8EDD, 0xDC99, 0x8EDE, 0xDC9A, 0x8EDF, 0xDC9B, 0x8EE0, 0xDC9C, 0x8EE1, 0xDC9D, 0x8EE2, 0xDC9E, + 0x8EE3, 0xDC9F, 0x8EE4, 0xDCA0, 0x8EE5, 0xDD40, 0x8EE6, 0xDD41, 0x8EE7, 0xDD42, 0x8EE8, 0xDD43, 0x8EE9, 0xDD44, 0x8EEA, 0xDD45, + 0x8EEB, 0xDD46, 0x8EEC, 0xDD47, 0x8EED, 0xDD48, 0x8EEE, 0xDD49, 0x8EEF, 0xDD4A, 0x8EF0, 0xDD4B, 0x8EF1, 0xDD4C, 0x8EF2, 0xDD4D, + 0x8EF3, 0xDD4E, 0x8EF4, 0xDD4F, 0x8EF5, 0xDD50, 0x8EF6, 0xDD51, 0x8EF7, 0xDD52, 0x8EF8, 0xDD53, 0x8EF9, 0xDD54, 0x8EFA, 0xDD55, + 0x8EFB, 0xDD56, 0x8EFC, 0xDD57, 0x8EFD, 0xDD58, 0x8EFE, 0xDD59, 0x8EFF, 0xDD5A, 0x8F00, 0xDD5B, 0x8F01, 0xDD5C, 0x8F02, 0xDD5D, + 0x8F03, 0xDD5E, 0x8F04, 0xDD5F, 0x8F05, 0xDD60, 0x8F06, 0xDD61, 0x8F07, 0xDD62, 0x8F08, 0xDD63, 0x8F09, 0xDD64, 0x8F0A, 0xDD65, + 0x8F0B, 0xDD66, 0x8F0C, 0xDD67, 0x8F0D, 0xDD68, 0x8F0E, 0xDD69, 0x8F0F, 0xDD6A, 0x8F10, 0xDD6B, 0x8F11, 0xDD6C, 0x8F12, 0xDD6D, + 0x8F13, 0xDD6E, 0x8F14, 0xDD6F, 0x8F15, 0xDD70, 0x8F16, 0xDD71, 0x8F17, 0xDD72, 0x8F18, 0xDD73, 0x8F19, 0xDD74, 0x8F1A, 0xDD75, + 0x8F1B, 0xDD76, 0x8F1C, 0xDD77, 0x8F1D, 0xDD78, 0x8F1E, 0xDD79, 0x8F1F, 0xDD7A, 0x8F20, 0xDD7B, 0x8F21, 0xDD7C, 0x8F22, 0xDD7D, + 0x8F23, 0xDD7E, 0x8F24, 0xDD80, 0x8F25, 0xDD81, 0x8F26, 0xDD82, 0x8F27, 0xDD83, 0x8F28, 0xDD84, 0x8F29, 0xDD85, 0x8F2A, 0xDD86, + 0x8F2B, 0xDD87, 0x8F2C, 0xDD88, 0x8F2D, 0xDD89, 0x8F2E, 0xDD8A, 0x8F2F, 0xDD8B, 0x8F30, 0xDD8C, 0x8F31, 0xDD8D, 0x8F32, 0xDD8E, + 0x8F33, 0xDD8F, 0x8F34, 0xDD90, 0x8F35, 0xDD91, 0x8F36, 0xDD92, 0x8F37, 0xDD93, 0x8F38, 0xDD94, 0x8F39, 0xDD95, 0x8F3A, 0xDD96, + 0x8F3B, 0xDD97, 0x8F3C, 0xDD98, 0x8F3D, 0xDD99, 0x8F3E, 0xDD9A, 0x8F3F, 0xDD9B, 0x8F40, 0xDD9C, 0x8F41, 0xDD9D, 0x8F42, 0xDD9E, + 0x8F43, 0xDD9F, 0x8F44, 0xDDA0, 0x8F45, 0xDE40, 0x8F46, 0xDE41, 0x8F47, 0xDE42, 0x8F48, 0xDE43, 0x8F49, 0xDE44, 0x8F4A, 0xDE45, + 0x8F4B, 0xDE46, 0x8F4C, 0xDE47, 0x8F4D, 0xDE48, 0x8F4E, 0xDE49, 0x8F4F, 0xDE4A, 0x8F50, 0xDE4B, 0x8F51, 0xDE4C, 0x8F52, 0xDE4D, + 0x8F53, 0xDE4E, 0x8F54, 0xDE4F, 0x8F55, 0xDE50, 0x8F56, 0xDE51, 0x8F57, 0xDE52, 0x8F58, 0xDE53, 0x8F59, 0xDE54, 0x8F5A, 0xDE55, + 0x8F5B, 0xDE56, 0x8F5C, 0xDE57, 0x8F5D, 0xDE58, 0x8F5E, 0xDE59, 0x8F5F, 0xDE5A, 0x8F60, 0xDE5B, 0x8F61, 0xDE5C, 0x8F62, 0xDE5D, + 0x8F63, 0xDE5E, 0x8F64, 0xDE5F, 0x8F65, 0xDE60, 0x8F66, 0xB3B5, 0x8F67, 0xD4FE, 0x8F68, 0xB9EC, 0x8F69, 0xD0F9, 0x8F6A, 0xDE61, + 0x8F6B, 0xE9ED, 0x8F6C, 0xD7AA, 0x8F6D, 0xE9EE, 0x8F6E, 0xC2D6, 0x8F6F, 0xC8ED, 0x8F70, 0xBAE4, 0x8F71, 0xE9EF, 0x8F72, 0xE9F0, + 0x8F73, 0xE9F1, 0x8F74, 0xD6E1, 0x8F75, 0xE9F2, 0x8F76, 0xE9F3, 0x8F77, 0xE9F5, 0x8F78, 0xE9F4, 0x8F79, 0xE9F6, 0x8F7A, 0xE9F7, + 0x8F7B, 0xC7E1, 0x8F7C, 0xE9F8, 0x8F7D, 0xD4D8, 0x8F7E, 0xE9F9, 0x8F7F, 0xBDCE, 0x8F80, 0xDE62, 0x8F81, 0xE9FA, 0x8F82, 0xE9FB, + 0x8F83, 0xBDCF, 0x8F84, 0xE9FC, 0x8F85, 0xB8A8, 0x8F86, 0xC1BE, 0x8F87, 0xE9FD, 0x8F88, 0xB1B2, 0x8F89, 0xBBD4, 0x8F8A, 0xB9F5, + 0x8F8B, 0xE9FE, 0x8F8C, 0xDE63, 0x8F8D, 0xEAA1, 0x8F8E, 0xEAA2, 0x8F8F, 0xEAA3, 0x8F90, 0xB7F8, 0x8F91, 0xBCAD, 0x8F92, 0xDE64, + 0x8F93, 0xCAE4, 0x8F94, 0xE0CE, 0x8F95, 0xD4AF, 0x8F96, 0xCFBD, 0x8F97, 0xD5B7, 0x8F98, 0xEAA4, 0x8F99, 0xD5DE, 0x8F9A, 0xEAA5, + 0x8F9B, 0xD0C1, 0x8F9C, 0xB9BC, 0x8F9D, 0xDE65, 0x8F9E, 0xB4C7, 0x8F9F, 0xB1D9, 0x8FA0, 0xDE66, 0x8FA1, 0xDE67, 0x8FA2, 0xDE68, + 0x8FA3, 0xC0B1, 0x8FA4, 0xDE69, 0x8FA5, 0xDE6A, 0x8FA6, 0xDE6B, 0x8FA7, 0xDE6C, 0x8FA8, 0xB1E6, 0x8FA9, 0xB1E7, 0x8FAA, 0xDE6D, + 0x8FAB, 0xB1E8, 0x8FAC, 0xDE6E, 0x8FAD, 0xDE6F, 0x8FAE, 0xDE70, 0x8FAF, 0xDE71, 0x8FB0, 0xB3BD, 0x8FB1, 0xC8E8, 0x8FB2, 0xDE72, + 0x8FB3, 0xDE73, 0x8FB4, 0xDE74, 0x8FB5, 0xDE75, 0x8FB6, 0xE5C1, 0x8FB7, 0xDE76, 0x8FB8, 0xDE77, 0x8FB9, 0xB1DF, 0x8FBA, 0xDE78, + 0x8FBB, 0xDE79, 0x8FBC, 0xDE7A, 0x8FBD, 0xC1C9, 0x8FBE, 0xB4EF, 0x8FBF, 0xDE7B, 0x8FC0, 0xDE7C, 0x8FC1, 0xC7A8, 0x8FC2, 0xD3D8, + 0x8FC3, 0xDE7D, 0x8FC4, 0xC6F9, 0x8FC5, 0xD1B8, 0x8FC6, 0xDE7E, 0x8FC7, 0xB9FD, 0x8FC8, 0xC2F5, 0x8FC9, 0xDE80, 0x8FCA, 0xDE81, + 0x8FCB, 0xDE82, 0x8FCC, 0xDE83, 0x8FCD, 0xDE84, 0x8FCE, 0xD3AD, 0x8FCF, 0xDE85, 0x8FD0, 0xD4CB, 0x8FD1, 0xBDFC, 0x8FD2, 0xDE86, + 0x8FD3, 0xE5C2, 0x8FD4, 0xB7B5, 0x8FD5, 0xE5C3, 0x8FD6, 0xDE87, 0x8FD7, 0xDE88, 0x8FD8, 0xBBB9, 0x8FD9, 0xD5E2, 0x8FDA, 0xDE89, + 0x8FDB, 0xBDF8, 0x8FDC, 0xD4B6, 0x8FDD, 0xCEA5, 0x8FDE, 0xC1AC, 0x8FDF, 0xB3D9, 0x8FE0, 0xDE8A, 0x8FE1, 0xDE8B, 0x8FE2, 0xCCF6, + 0x8FE3, 0xDE8C, 0x8FE4, 0xE5C6, 0x8FE5, 0xE5C4, 0x8FE6, 0xE5C8, 0x8FE7, 0xDE8D, 0x8FE8, 0xE5CA, 0x8FE9, 0xE5C7, 0x8FEA, 0xB5CF, + 0x8FEB, 0xC6C8, 0x8FEC, 0xDE8E, 0x8FED, 0xB5FC, 0x8FEE, 0xE5C5, 0x8FEF, 0xDE8F, 0x8FF0, 0xCAF6, 0x8FF1, 0xDE90, 0x8FF2, 0xDE91, + 0x8FF3, 0xE5C9, 0x8FF4, 0xDE92, 0x8FF5, 0xDE93, 0x8FF6, 0xDE94, 0x8FF7, 0xC3D4, 0x8FF8, 0xB1C5, 0x8FF9, 0xBCA3, 0x8FFA, 0xDE95, + 0x8FFB, 0xDE96, 0x8FFC, 0xDE97, 0x8FFD, 0xD7B7, 0x8FFE, 0xDE98, 0x8FFF, 0xDE99, 0x9000, 0xCDCB, 0x9001, 0xCBCD, 0x9002, 0xCACA, + 0x9003, 0xCCD3, 0x9004, 0xE5CC, 0x9005, 0xE5CB, 0x9006, 0xC4E6, 0x9007, 0xDE9A, 0x9008, 0xDE9B, 0x9009, 0xD1A1, 0x900A, 0xD1B7, + 0x900B, 0xE5CD, 0x900C, 0xDE9C, 0x900D, 0xE5D0, 0x900E, 0xDE9D, 0x900F, 0xCDB8, 0x9010, 0xD6F0, 0x9011, 0xE5CF, 0x9012, 0xB5DD, + 0x9013, 0xDE9E, 0x9014, 0xCDBE, 0x9015, 0xDE9F, 0x9016, 0xE5D1, 0x9017, 0xB6BA, 0x9018, 0xDEA0, 0x9019, 0xDF40, 0x901A, 0xCDA8, + 0x901B, 0xB9E4, 0x901C, 0xDF41, 0x901D, 0xCAC5, 0x901E, 0xB3D1, 0x901F, 0xCBD9, 0x9020, 0xD4EC, 0x9021, 0xE5D2, 0x9022, 0xB7EA, + 0x9023, 0xDF42, 0x9024, 0xDF43, 0x9025, 0xDF44, 0x9026, 0xE5CE, 0x9027, 0xDF45, 0x9028, 0xDF46, 0x9029, 0xDF47, 0x902A, 0xDF48, + 0x902B, 0xDF49, 0x902C, 0xDF4A, 0x902D, 0xE5D5, 0x902E, 0xB4FE, 0x902F, 0xE5D6, 0x9030, 0xDF4B, 0x9031, 0xDF4C, 0x9032, 0xDF4D, + 0x9033, 0xDF4E, 0x9034, 0xDF4F, 0x9035, 0xE5D3, 0x9036, 0xE5D4, 0x9037, 0xDF50, 0x9038, 0xD2DD, 0x9039, 0xDF51, 0x903A, 0xDF52, + 0x903B, 0xC2DF, 0x903C, 0xB1C6, 0x903D, 0xDF53, 0x903E, 0xD3E2, 0x903F, 0xDF54, 0x9040, 0xDF55, 0x9041, 0xB6DD, 0x9042, 0xCBEC, + 0x9043, 0xDF56, 0x9044, 0xE5D7, 0x9045, 0xDF57, 0x9046, 0xDF58, 0x9047, 0xD3F6, 0x9048, 0xDF59, 0x9049, 0xDF5A, 0x904A, 0xDF5B, + 0x904B, 0xDF5C, 0x904C, 0xDF5D, 0x904D, 0xB1E9, 0x904E, 0xDF5E, 0x904F, 0xB6F4, 0x9050, 0xE5DA, 0x9051, 0xE5D8, 0x9052, 0xE5D9, + 0x9053, 0xB5C0, 0x9054, 0xDF5F, 0x9055, 0xDF60, 0x9056, 0xDF61, 0x9057, 0xD2C5, 0x9058, 0xE5DC, 0x9059, 0xDF62, 0x905A, 0xDF63, + 0x905B, 0xE5DE, 0x905C, 0xDF64, 0x905D, 0xDF65, 0x905E, 0xDF66, 0x905F, 0xDF67, 0x9060, 0xDF68, 0x9061, 0xDF69, 0x9062, 0xE5DD, + 0x9063, 0xC7B2, 0x9064, 0xDF6A, 0x9065, 0xD2A3, 0x9066, 0xDF6B, 0x9067, 0xDF6C, 0x9068, 0xE5DB, 0x9069, 0xDF6D, 0x906A, 0xDF6E, + 0x906B, 0xDF6F, 0x906C, 0xDF70, 0x906D, 0xD4E2, 0x906E, 0xD5DA, 0x906F, 0xDF71, 0x9070, 0xDF72, 0x9071, 0xDF73, 0x9072, 0xDF74, + 0x9073, 0xDF75, 0x9074, 0xE5E0, 0x9075, 0xD7F1, 0x9076, 0xDF76, 0x9077, 0xDF77, 0x9078, 0xDF78, 0x9079, 0xDF79, 0x907A, 0xDF7A, + 0x907B, 0xDF7B, 0x907C, 0xDF7C, 0x907D, 0xE5E1, 0x907E, 0xDF7D, 0x907F, 0xB1DC, 0x9080, 0xD1FB, 0x9081, 0xDF7E, 0x9082, 0xE5E2, + 0x9083, 0xE5E4, 0x9084, 0xDF80, 0x9085, 0xDF81, 0x9086, 0xDF82, 0x9087, 0xDF83, 0x9088, 0xE5E3, 0x9089, 0xDF84, 0x908A, 0xDF85, + 0x908B, 0xE5E5, 0x908C, 0xDF86, 0x908D, 0xDF87, 0x908E, 0xDF88, 0x908F, 0xDF89, 0x9090, 0xDF8A, 0x9091, 0xD2D8, 0x9092, 0xDF8B, + 0x9093, 0xB5CB, 0x9094, 0xDF8C, 0x9095, 0xE7DF, 0x9096, 0xDF8D, 0x9097, 0xDAF5, 0x9098, 0xDF8E, 0x9099, 0xDAF8, 0x909A, 0xDF8F, + 0x909B, 0xDAF6, 0x909C, 0xDF90, 0x909D, 0xDAF7, 0x909E, 0xDF91, 0x909F, 0xDF92, 0x90A0, 0xDF93, 0x90A1, 0xDAFA, 0x90A2, 0xD0CF, + 0x90A3, 0xC4C7, 0x90A4, 0xDF94, 0x90A5, 0xDF95, 0x90A6, 0xB0EE, 0x90A7, 0xDF96, 0x90A8, 0xDF97, 0x90A9, 0xDF98, 0x90AA, 0xD0B0, + 0x90AB, 0xDF99, 0x90AC, 0xDAF9, 0x90AD, 0xDF9A, 0x90AE, 0xD3CA, 0x90AF, 0xBAAA, 0x90B0, 0xDBA2, 0x90B1, 0xC7F1, 0x90B2, 0xDF9B, + 0x90B3, 0xDAFC, 0x90B4, 0xDAFB, 0x90B5, 0xC9DB, 0x90B6, 0xDAFD, 0x90B7, 0xDF9C, 0x90B8, 0xDBA1, 0x90B9, 0xD7DE, 0x90BA, 0xDAFE, + 0x90BB, 0xC1DA, 0x90BC, 0xDF9D, 0x90BD, 0xDF9E, 0x90BE, 0xDBA5, 0x90BF, 0xDF9F, 0x90C0, 0xDFA0, 0x90C1, 0xD3F4, 0x90C2, 0xE040, + 0x90C3, 0xE041, 0x90C4, 0xDBA7, 0x90C5, 0xDBA4, 0x90C6, 0xE042, 0x90C7, 0xDBA8, 0x90C8, 0xE043, 0x90C9, 0xE044, 0x90CA, 0xBDBC, + 0x90CB, 0xE045, 0x90CC, 0xE046, 0x90CD, 0xE047, 0x90CE, 0xC0C9, 0x90CF, 0xDBA3, 0x90D0, 0xDBA6, 0x90D1, 0xD6A3, 0x90D2, 0xE048, + 0x90D3, 0xDBA9, 0x90D4, 0xE049, 0x90D5, 0xE04A, 0x90D6, 0xE04B, 0x90D7, 0xDBAD, 0x90D8, 0xE04C, 0x90D9, 0xE04D, 0x90DA, 0xE04E, + 0x90DB, 0xDBAE, 0x90DC, 0xDBAC, 0x90DD, 0xBAC2, 0x90DE, 0xE04F, 0x90DF, 0xE050, 0x90E0, 0xE051, 0x90E1, 0xBFA4, 0x90E2, 0xDBAB, + 0x90E3, 0xE052, 0x90E4, 0xE053, 0x90E5, 0xE054, 0x90E6, 0xDBAA, 0x90E7, 0xD4C7, 0x90E8, 0xB2BF, 0x90E9, 0xE055, 0x90EA, 0xE056, + 0x90EB, 0xDBAF, 0x90EC, 0xE057, 0x90ED, 0xB9F9, 0x90EE, 0xE058, 0x90EF, 0xDBB0, 0x90F0, 0xE059, 0x90F1, 0xE05A, 0x90F2, 0xE05B, + 0x90F3, 0xE05C, 0x90F4, 0xB3BB, 0x90F5, 0xE05D, 0x90F6, 0xE05E, 0x90F7, 0xE05F, 0x90F8, 0xB5A6, 0x90F9, 0xE060, 0x90FA, 0xE061, + 0x90FB, 0xE062, 0x90FC, 0xE063, 0x90FD, 0xB6BC, 0x90FE, 0xDBB1, 0x90FF, 0xE064, 0x9100, 0xE065, 0x9101, 0xE066, 0x9102, 0xB6F5, + 0x9103, 0xE067, 0x9104, 0xDBB2, 0x9105, 0xE068, 0x9106, 0xE069, 0x9107, 0xE06A, 0x9108, 0xE06B, 0x9109, 0xE06C, 0x910A, 0xE06D, + 0x910B, 0xE06E, 0x910C, 0xE06F, 0x910D, 0xE070, 0x910E, 0xE071, 0x910F, 0xE072, 0x9110, 0xE073, 0x9111, 0xE074, 0x9112, 0xE075, + 0x9113, 0xE076, 0x9114, 0xE077, 0x9115, 0xE078, 0x9116, 0xE079, 0x9117, 0xE07A, 0x9118, 0xE07B, 0x9119, 0xB1C9, 0x911A, 0xE07C, + 0x911B, 0xE07D, 0x911C, 0xE07E, 0x911D, 0xE080, 0x911E, 0xDBB4, 0x911F, 0xE081, 0x9120, 0xE082, 0x9121, 0xE083, 0x9122, 0xDBB3, + 0x9123, 0xDBB5, 0x9124, 0xE084, 0x9125, 0xE085, 0x9126, 0xE086, 0x9127, 0xE087, 0x9128, 0xE088, 0x9129, 0xE089, 0x912A, 0xE08A, + 0x912B, 0xE08B, 0x912C, 0xE08C, 0x912D, 0xE08D, 0x912E, 0xE08E, 0x912F, 0xDBB7, 0x9130, 0xE08F, 0x9131, 0xDBB6, 0x9132, 0xE090, + 0x9133, 0xE091, 0x9134, 0xE092, 0x9135, 0xE093, 0x9136, 0xE094, 0x9137, 0xE095, 0x9138, 0xE096, 0x9139, 0xDBB8, 0x913A, 0xE097, + 0x913B, 0xE098, 0x913C, 0xE099, 0x913D, 0xE09A, 0x913E, 0xE09B, 0x913F, 0xE09C, 0x9140, 0xE09D, 0x9141, 0xE09E, 0x9142, 0xE09F, + 0x9143, 0xDBB9, 0x9144, 0xE0A0, 0x9145, 0xE140, 0x9146, 0xDBBA, 0x9147, 0xE141, 0x9148, 0xE142, 0x9149, 0xD3CF, 0x914A, 0xF4FA, + 0x914B, 0xC7F5, 0x914C, 0xD7C3, 0x914D, 0xC5E4, 0x914E, 0xF4FC, 0x914F, 0xF4FD, 0x9150, 0xF4FB, 0x9151, 0xE143, 0x9152, 0xBEC6, + 0x9153, 0xE144, 0x9154, 0xE145, 0x9155, 0xE146, 0x9156, 0xE147, 0x9157, 0xD0EF, 0x9158, 0xE148, 0x9159, 0xE149, 0x915A, 0xB7D3, + 0x915B, 0xE14A, 0x915C, 0xE14B, 0x915D, 0xD4CD, 0x915E, 0xCCAA, 0x915F, 0xE14C, 0x9160, 0xE14D, 0x9161, 0xF5A2, 0x9162, 0xF5A1, + 0x9163, 0xBAA8, 0x9164, 0xF4FE, 0x9165, 0xCBD6, 0x9166, 0xE14E, 0x9167, 0xE14F, 0x9168, 0xE150, 0x9169, 0xF5A4, 0x916A, 0xC0D2, + 0x916B, 0xE151, 0x916C, 0xB3EA, 0x916D, 0xE152, 0x916E, 0xCDAA, 0x916F, 0xF5A5, 0x9170, 0xF5A3, 0x9171, 0xBDB4, 0x9172, 0xF5A8, + 0x9173, 0xE153, 0x9174, 0xF5A9, 0x9175, 0xBDCD, 0x9176, 0xC3B8, 0x9177, 0xBFE1, 0x9178, 0xCBE1, 0x9179, 0xF5AA, 0x917A, 0xE154, + 0x917B, 0xE155, 0x917C, 0xE156, 0x917D, 0xF5A6, 0x917E, 0xF5A7, 0x917F, 0xC4F0, 0x9180, 0xE157, 0x9181, 0xE158, 0x9182, 0xE159, + 0x9183, 0xE15A, 0x9184, 0xE15B, 0x9185, 0xF5AC, 0x9186, 0xE15C, 0x9187, 0xB4BC, 0x9188, 0xE15D, 0x9189, 0xD7ED, 0x918A, 0xE15E, + 0x918B, 0xB4D7, 0x918C, 0xF5AB, 0x918D, 0xF5AE, 0x918E, 0xE15F, 0x918F, 0xE160, 0x9190, 0xF5AD, 0x9191, 0xF5AF, 0x9192, 0xD0D1, + 0x9193, 0xE161, 0x9194, 0xE162, 0x9195, 0xE163, 0x9196, 0xE164, 0x9197, 0xE165, 0x9198, 0xE166, 0x9199, 0xE167, 0x919A, 0xC3D1, + 0x919B, 0xC8A9, 0x919C, 0xE168, 0x919D, 0xE169, 0x919E, 0xE16A, 0x919F, 0xE16B, 0x91A0, 0xE16C, 0x91A1, 0xE16D, 0x91A2, 0xF5B0, + 0x91A3, 0xF5B1, 0x91A4, 0xE16E, 0x91A5, 0xE16F, 0x91A6, 0xE170, 0x91A7, 0xE171, 0x91A8, 0xE172, 0x91A9, 0xE173, 0x91AA, 0xF5B2, + 0x91AB, 0xE174, 0x91AC, 0xE175, 0x91AD, 0xF5B3, 0x91AE, 0xF5B4, 0x91AF, 0xF5B5, 0x91B0, 0xE176, 0x91B1, 0xE177, 0x91B2, 0xE178, + 0x91B3, 0xE179, 0x91B4, 0xF5B7, 0x91B5, 0xF5B6, 0x91B6, 0xE17A, 0x91B7, 0xE17B, 0x91B8, 0xE17C, 0x91B9, 0xE17D, 0x91BA, 0xF5B8, + 0x91BB, 0xE17E, 0x91BC, 0xE180, 0x91BD, 0xE181, 0x91BE, 0xE182, 0x91BF, 0xE183, 0x91C0, 0xE184, 0x91C1, 0xE185, 0x91C2, 0xE186, + 0x91C3, 0xE187, 0x91C4, 0xE188, 0x91C5, 0xE189, 0x91C6, 0xE18A, 0x91C7, 0xB2C9, 0x91C8, 0xE18B, 0x91C9, 0xD3D4, 0x91CA, 0xCACD, + 0x91CB, 0xE18C, 0x91CC, 0xC0EF, 0x91CD, 0xD6D8, 0x91CE, 0xD2B0, 0x91CF, 0xC1BF, 0x91D0, 0xE18D, 0x91D1, 0xBDF0, 0x91D2, 0xE18E, + 0x91D3, 0xE18F, 0x91D4, 0xE190, 0x91D5, 0xE191, 0x91D6, 0xE192, 0x91D7, 0xE193, 0x91D8, 0xE194, 0x91D9, 0xE195, 0x91DA, 0xE196, + 0x91DB, 0xE197, 0x91DC, 0xB8AA, 0x91DD, 0xE198, 0x91DE, 0xE199, 0x91DF, 0xE19A, 0x91E0, 0xE19B, 0x91E1, 0xE19C, 0x91E2, 0xE19D, + 0x91E3, 0xE19E, 0x91E4, 0xE19F, 0x91E5, 0xE1A0, 0x91E6, 0xE240, 0x91E7, 0xE241, 0x91E8, 0xE242, 0x91E9, 0xE243, 0x91EA, 0xE244, + 0x91EB, 0xE245, 0x91EC, 0xE246, 0x91ED, 0xE247, 0x91EE, 0xE248, 0x91EF, 0xE249, 0x91F0, 0xE24A, 0x91F1, 0xE24B, 0x91F2, 0xE24C, + 0x91F3, 0xE24D, 0x91F4, 0xE24E, 0x91F5, 0xE24F, 0x91F6, 0xE250, 0x91F7, 0xE251, 0x91F8, 0xE252, 0x91F9, 0xE253, 0x91FA, 0xE254, + 0x91FB, 0xE255, 0x91FC, 0xE256, 0x91FD, 0xE257, 0x91FE, 0xE258, 0x91FF, 0xE259, 0x9200, 0xE25A, 0x9201, 0xE25B, 0x9202, 0xE25C, + 0x9203, 0xE25D, 0x9204, 0xE25E, 0x9205, 0xE25F, 0x9206, 0xE260, 0x9207, 0xE261, 0x9208, 0xE262, 0x9209, 0xE263, 0x920A, 0xE264, + 0x920B, 0xE265, 0x920C, 0xE266, 0x920D, 0xE267, 0x920E, 0xE268, 0x920F, 0xE269, 0x9210, 0xE26A, 0x9211, 0xE26B, 0x9212, 0xE26C, + 0x9213, 0xE26D, 0x9214, 0xE26E, 0x9215, 0xE26F, 0x9216, 0xE270, 0x9217, 0xE271, 0x9218, 0xE272, 0x9219, 0xE273, 0x921A, 0xE274, + 0x921B, 0xE275, 0x921C, 0xE276, 0x921D, 0xE277, 0x921E, 0xE278, 0x921F, 0xE279, 0x9220, 0xE27A, 0x9221, 0xE27B, 0x9222, 0xE27C, + 0x9223, 0xE27D, 0x9224, 0xE27E, 0x9225, 0xE280, 0x9226, 0xE281, 0x9227, 0xE282, 0x9228, 0xE283, 0x9229, 0xE284, 0x922A, 0xE285, + 0x922B, 0xE286, 0x922C, 0xE287, 0x922D, 0xE288, 0x922E, 0xE289, 0x922F, 0xE28A, 0x9230, 0xE28B, 0x9231, 0xE28C, 0x9232, 0xE28D, + 0x9233, 0xE28E, 0x9234, 0xE28F, 0x9235, 0xE290, 0x9236, 0xE291, 0x9237, 0xE292, 0x9238, 0xE293, 0x9239, 0xE294, 0x923A, 0xE295, + 0x923B, 0xE296, 0x923C, 0xE297, 0x923D, 0xE298, 0x923E, 0xE299, 0x923F, 0xE29A, 0x9240, 0xE29B, 0x9241, 0xE29C, 0x9242, 0xE29D, + 0x9243, 0xE29E, 0x9244, 0xE29F, 0x9245, 0xE2A0, 0x9246, 0xE340, 0x9247, 0xE341, 0x9248, 0xE342, 0x9249, 0xE343, 0x924A, 0xE344, + 0x924B, 0xE345, 0x924C, 0xE346, 0x924D, 0xE347, 0x924E, 0xE348, 0x924F, 0xE349, 0x9250, 0xE34A, 0x9251, 0xE34B, 0x9252, 0xE34C, + 0x9253, 0xE34D, 0x9254, 0xE34E, 0x9255, 0xE34F, 0x9256, 0xE350, 0x9257, 0xE351, 0x9258, 0xE352, 0x9259, 0xE353, 0x925A, 0xE354, + 0x925B, 0xE355, 0x925C, 0xE356, 0x925D, 0xE357, 0x925E, 0xE358, 0x925F, 0xE359, 0x9260, 0xE35A, 0x9261, 0xE35B, 0x9262, 0xE35C, + 0x9263, 0xE35D, 0x9264, 0xE35E, 0x9265, 0xE35F, 0x9266, 0xE360, 0x9267, 0xE361, 0x9268, 0xE362, 0x9269, 0xE363, 0x926A, 0xE364, + 0x926B, 0xE365, 0x926C, 0xE366, 0x926D, 0xE367, 0x926E, 0xE368, 0x926F, 0xE369, 0x9270, 0xE36A, 0x9271, 0xE36B, 0x9272, 0xE36C, + 0x9273, 0xE36D, 0x9274, 0xBCF8, 0x9275, 0xE36E, 0x9276, 0xE36F, 0x9277, 0xE370, 0x9278, 0xE371, 0x9279, 0xE372, 0x927A, 0xE373, + 0x927B, 0xE374, 0x927C, 0xE375, 0x927D, 0xE376, 0x927E, 0xE377, 0x927F, 0xE378, 0x9280, 0xE379, 0x9281, 0xE37A, 0x9282, 0xE37B, + 0x9283, 0xE37C, 0x9284, 0xE37D, 0x9285, 0xE37E, 0x9286, 0xE380, 0x9287, 0xE381, 0x9288, 0xE382, 0x9289, 0xE383, 0x928A, 0xE384, + 0x928B, 0xE385, 0x928C, 0xE386, 0x928D, 0xE387, 0x928E, 0xF6C6, 0x928F, 0xE388, 0x9290, 0xE389, 0x9291, 0xE38A, 0x9292, 0xE38B, + 0x9293, 0xE38C, 0x9294, 0xE38D, 0x9295, 0xE38E, 0x9296, 0xE38F, 0x9297, 0xE390, 0x9298, 0xE391, 0x9299, 0xE392, 0x929A, 0xE393, + 0x929B, 0xE394, 0x929C, 0xE395, 0x929D, 0xE396, 0x929E, 0xE397, 0x929F, 0xE398, 0x92A0, 0xE399, 0x92A1, 0xE39A, 0x92A2, 0xE39B, + 0x92A3, 0xE39C, 0x92A4, 0xE39D, 0x92A5, 0xE39E, 0x92A6, 0xE39F, 0x92A7, 0xE3A0, 0x92A8, 0xE440, 0x92A9, 0xE441, 0x92AA, 0xE442, + 0x92AB, 0xE443, 0x92AC, 0xE444, 0x92AD, 0xE445, 0x92AE, 0xF6C7, 0x92AF, 0xE446, 0x92B0, 0xE447, 0x92B1, 0xE448, 0x92B2, 0xE449, + 0x92B3, 0xE44A, 0x92B4, 0xE44B, 0x92B5, 0xE44C, 0x92B6, 0xE44D, 0x92B7, 0xE44E, 0x92B8, 0xE44F, 0x92B9, 0xE450, 0x92BA, 0xE451, + 0x92BB, 0xE452, 0x92BC, 0xE453, 0x92BD, 0xE454, 0x92BE, 0xE455, 0x92BF, 0xE456, 0x92C0, 0xE457, 0x92C1, 0xE458, 0x92C2, 0xE459, + 0x92C3, 0xE45A, 0x92C4, 0xE45B, 0x92C5, 0xE45C, 0x92C6, 0xE45D, 0x92C7, 0xE45E, 0x92C8, 0xF6C8, 0x92C9, 0xE45F, 0x92CA, 0xE460, + 0x92CB, 0xE461, 0x92CC, 0xE462, 0x92CD, 0xE463, 0x92CE, 0xE464, 0x92CF, 0xE465, 0x92D0, 0xE466, 0x92D1, 0xE467, 0x92D2, 0xE468, + 0x92D3, 0xE469, 0x92D4, 0xE46A, 0x92D5, 0xE46B, 0x92D6, 0xE46C, 0x92D7, 0xE46D, 0x92D8, 0xE46E, 0x92D9, 0xE46F, 0x92DA, 0xE470, + 0x92DB, 0xE471, 0x92DC, 0xE472, 0x92DD, 0xE473, 0x92DE, 0xE474, 0x92DF, 0xE475, 0x92E0, 0xE476, 0x92E1, 0xE477, 0x92E2, 0xE478, + 0x92E3, 0xE479, 0x92E4, 0xE47A, 0x92E5, 0xE47B, 0x92E6, 0xE47C, 0x92E7, 0xE47D, 0x92E8, 0xE47E, 0x92E9, 0xE480, 0x92EA, 0xE481, + 0x92EB, 0xE482, 0x92EC, 0xE483, 0x92ED, 0xE484, 0x92EE, 0xE485, 0x92EF, 0xE486, 0x92F0, 0xE487, 0x92F1, 0xE488, 0x92F2, 0xE489, + 0x92F3, 0xE48A, 0x92F4, 0xE48B, 0x92F5, 0xE48C, 0x92F6, 0xE48D, 0x92F7, 0xE48E, 0x92F8, 0xE48F, 0x92F9, 0xE490, 0x92FA, 0xE491, + 0x92FB, 0xE492, 0x92FC, 0xE493, 0x92FD, 0xE494, 0x92FE, 0xE495, 0x92FF, 0xE496, 0x9300, 0xE497, 0x9301, 0xE498, 0x9302, 0xE499, + 0x9303, 0xE49A, 0x9304, 0xE49B, 0x9305, 0xE49C, 0x9306, 0xE49D, 0x9307, 0xE49E, 0x9308, 0xE49F, 0x9309, 0xE4A0, 0x930A, 0xE540, + 0x930B, 0xE541, 0x930C, 0xE542, 0x930D, 0xE543, 0x930E, 0xE544, 0x930F, 0xE545, 0x9310, 0xE546, 0x9311, 0xE547, 0x9312, 0xE548, + 0x9313, 0xE549, 0x9314, 0xE54A, 0x9315, 0xE54B, 0x9316, 0xE54C, 0x9317, 0xE54D, 0x9318, 0xE54E, 0x9319, 0xE54F, 0x931A, 0xE550, + 0x931B, 0xE551, 0x931C, 0xE552, 0x931D, 0xE553, 0x931E, 0xE554, 0x931F, 0xE555, 0x9320, 0xE556, 0x9321, 0xE557, 0x9322, 0xE558, + 0x9323, 0xE559, 0x9324, 0xE55A, 0x9325, 0xE55B, 0x9326, 0xE55C, 0x9327, 0xE55D, 0x9328, 0xE55E, 0x9329, 0xE55F, 0x932A, 0xE560, + 0x932B, 0xE561, 0x932C, 0xE562, 0x932D, 0xE563, 0x932E, 0xE564, 0x932F, 0xE565, 0x9330, 0xE566, 0x9331, 0xE567, 0x9332, 0xE568, + 0x9333, 0xE569, 0x9334, 0xE56A, 0x9335, 0xE56B, 0x9336, 0xE56C, 0x9337, 0xE56D, 0x9338, 0xE56E, 0x9339, 0xE56F, 0x933A, 0xE570, + 0x933B, 0xE571, 0x933C, 0xE572, 0x933D, 0xE573, 0x933E, 0xF6C9, 0x933F, 0xE574, 0x9340, 0xE575, 0x9341, 0xE576, 0x9342, 0xE577, + 0x9343, 0xE578, 0x9344, 0xE579, 0x9345, 0xE57A, 0x9346, 0xE57B, 0x9347, 0xE57C, 0x9348, 0xE57D, 0x9349, 0xE57E, 0x934A, 0xE580, + 0x934B, 0xE581, 0x934C, 0xE582, 0x934D, 0xE583, 0x934E, 0xE584, 0x934F, 0xE585, 0x9350, 0xE586, 0x9351, 0xE587, 0x9352, 0xE588, + 0x9353, 0xE589, 0x9354, 0xE58A, 0x9355, 0xE58B, 0x9356, 0xE58C, 0x9357, 0xE58D, 0x9358, 0xE58E, 0x9359, 0xE58F, 0x935A, 0xE590, + 0x935B, 0xE591, 0x935C, 0xE592, 0x935D, 0xE593, 0x935E, 0xE594, 0x935F, 0xE595, 0x9360, 0xE596, 0x9361, 0xE597, 0x9362, 0xE598, + 0x9363, 0xE599, 0x9364, 0xE59A, 0x9365, 0xE59B, 0x9366, 0xE59C, 0x9367, 0xE59D, 0x9368, 0xE59E, 0x9369, 0xE59F, 0x936A, 0xF6CA, + 0x936B, 0xE5A0, 0x936C, 0xE640, 0x936D, 0xE641, 0x936E, 0xE642, 0x936F, 0xE643, 0x9370, 0xE644, 0x9371, 0xE645, 0x9372, 0xE646, + 0x9373, 0xE647, 0x9374, 0xE648, 0x9375, 0xE649, 0x9376, 0xE64A, 0x9377, 0xE64B, 0x9378, 0xE64C, 0x9379, 0xE64D, 0x937A, 0xE64E, + 0x937B, 0xE64F, 0x937C, 0xE650, 0x937D, 0xE651, 0x937E, 0xE652, 0x937F, 0xE653, 0x9380, 0xE654, 0x9381, 0xE655, 0x9382, 0xE656, + 0x9383, 0xE657, 0x9384, 0xE658, 0x9385, 0xE659, 0x9386, 0xE65A, 0x9387, 0xE65B, 0x9388, 0xE65C, 0x9389, 0xE65D, 0x938A, 0xE65E, + 0x938B, 0xE65F, 0x938C, 0xE660, 0x938D, 0xE661, 0x938E, 0xE662, 0x938F, 0xF6CC, 0x9390, 0xE663, 0x9391, 0xE664, 0x9392, 0xE665, + 0x9393, 0xE666, 0x9394, 0xE667, 0x9395, 0xE668, 0x9396, 0xE669, 0x9397, 0xE66A, 0x9398, 0xE66B, 0x9399, 0xE66C, 0x939A, 0xE66D, + 0x939B, 0xE66E, 0x939C, 0xE66F, 0x939D, 0xE670, 0x939E, 0xE671, 0x939F, 0xE672, 0x93A0, 0xE673, 0x93A1, 0xE674, 0x93A2, 0xE675, + 0x93A3, 0xE676, 0x93A4, 0xE677, 0x93A5, 0xE678, 0x93A6, 0xE679, 0x93A7, 0xE67A, 0x93A8, 0xE67B, 0x93A9, 0xE67C, 0x93AA, 0xE67D, + 0x93AB, 0xE67E, 0x93AC, 0xE680, 0x93AD, 0xE681, 0x93AE, 0xE682, 0x93AF, 0xE683, 0x93B0, 0xE684, 0x93B1, 0xE685, 0x93B2, 0xE686, + 0x93B3, 0xE687, 0x93B4, 0xE688, 0x93B5, 0xE689, 0x93B6, 0xE68A, 0x93B7, 0xE68B, 0x93B8, 0xE68C, 0x93B9, 0xE68D, 0x93BA, 0xE68E, + 0x93BB, 0xE68F, 0x93BC, 0xE690, 0x93BD, 0xE691, 0x93BE, 0xE692, 0x93BF, 0xE693, 0x93C0, 0xE694, 0x93C1, 0xE695, 0x93C2, 0xE696, + 0x93C3, 0xE697, 0x93C4, 0xE698, 0x93C5, 0xE699, 0x93C6, 0xE69A, 0x93C7, 0xE69B, 0x93C8, 0xE69C, 0x93C9, 0xE69D, 0x93CA, 0xF6CB, + 0x93CB, 0xE69E, 0x93CC, 0xE69F, 0x93CD, 0xE6A0, 0x93CE, 0xE740, 0x93CF, 0xE741, 0x93D0, 0xE742, 0x93D1, 0xE743, 0x93D2, 0xE744, + 0x93D3, 0xE745, 0x93D4, 0xE746, 0x93D5, 0xE747, 0x93D6, 0xF7E9, 0x93D7, 0xE748, 0x93D8, 0xE749, 0x93D9, 0xE74A, 0x93DA, 0xE74B, + 0x93DB, 0xE74C, 0x93DC, 0xE74D, 0x93DD, 0xE74E, 0x93DE, 0xE74F, 0x93DF, 0xE750, 0x93E0, 0xE751, 0x93E1, 0xE752, 0x93E2, 0xE753, + 0x93E3, 0xE754, 0x93E4, 0xE755, 0x93E5, 0xE756, 0x93E6, 0xE757, 0x93E7, 0xE758, 0x93E8, 0xE759, 0x93E9, 0xE75A, 0x93EA, 0xE75B, + 0x93EB, 0xE75C, 0x93EC, 0xE75D, 0x93ED, 0xE75E, 0x93EE, 0xE75F, 0x93EF, 0xE760, 0x93F0, 0xE761, 0x93F1, 0xE762, 0x93F2, 0xE763, + 0x93F3, 0xE764, 0x93F4, 0xE765, 0x93F5, 0xE766, 0x93F6, 0xE767, 0x93F7, 0xE768, 0x93F8, 0xE769, 0x93F9, 0xE76A, 0x93FA, 0xE76B, + 0x93FB, 0xE76C, 0x93FC, 0xE76D, 0x93FD, 0xE76E, 0x93FE, 0xE76F, 0x93FF, 0xE770, 0x9400, 0xE771, 0x9401, 0xE772, 0x9402, 0xE773, + 0x9403, 0xE774, 0x9404, 0xE775, 0x9405, 0xE776, 0x9406, 0xE777, 0x9407, 0xE778, 0x9408, 0xE779, 0x9409, 0xE77A, 0x940A, 0xE77B, + 0x940B, 0xE77C, 0x940C, 0xE77D, 0x940D, 0xE77E, 0x940E, 0xE780, 0x940F, 0xE781, 0x9410, 0xE782, 0x9411, 0xE783, 0x9412, 0xE784, + 0x9413, 0xE785, 0x9414, 0xE786, 0x9415, 0xE787, 0x9416, 0xE788, 0x9417, 0xE789, 0x9418, 0xE78A, 0x9419, 0xE78B, 0x941A, 0xE78C, + 0x941B, 0xE78D, 0x941C, 0xE78E, 0x941D, 0xE78F, 0x941E, 0xE790, 0x941F, 0xE791, 0x9420, 0xE792, 0x9421, 0xE793, 0x9422, 0xE794, + 0x9423, 0xE795, 0x9424, 0xE796, 0x9425, 0xE797, 0x9426, 0xE798, 0x9427, 0xE799, 0x9428, 0xE79A, 0x9429, 0xE79B, 0x942A, 0xE79C, + 0x942B, 0xE79D, 0x942C, 0xE79E, 0x942D, 0xE79F, 0x942E, 0xE7A0, 0x942F, 0xE840, 0x9430, 0xE841, 0x9431, 0xE842, 0x9432, 0xE843, + 0x9433, 0xE844, 0x9434, 0xE845, 0x9435, 0xE846, 0x9436, 0xE847, 0x9437, 0xE848, 0x9438, 0xE849, 0x9439, 0xE84A, 0x943A, 0xE84B, + 0x943B, 0xE84C, 0x943C, 0xE84D, 0x943D, 0xE84E, 0x943E, 0xF6CD, 0x943F, 0xE84F, 0x9440, 0xE850, 0x9441, 0xE851, 0x9442, 0xE852, + 0x9443, 0xE853, 0x9444, 0xE854, 0x9445, 0xE855, 0x9446, 0xE856, 0x9447, 0xE857, 0x9448, 0xE858, 0x9449, 0xE859, 0x944A, 0xE85A, + 0x944B, 0xE85B, 0x944C, 0xE85C, 0x944D, 0xE85D, 0x944E, 0xE85E, 0x944F, 0xE85F, 0x9450, 0xE860, 0x9451, 0xE861, 0x9452, 0xE862, + 0x9453, 0xE863, 0x9454, 0xE864, 0x9455, 0xE865, 0x9456, 0xE866, 0x9457, 0xE867, 0x9458, 0xE868, 0x9459, 0xE869, 0x945A, 0xE86A, + 0x945B, 0xE86B, 0x945C, 0xE86C, 0x945D, 0xE86D, 0x945E, 0xE86E, 0x945F, 0xE86F, 0x9460, 0xE870, 0x9461, 0xE871, 0x9462, 0xE872, + 0x9463, 0xE873, 0x9464, 0xE874, 0x9465, 0xE875, 0x9466, 0xE876, 0x9467, 0xE877, 0x9468, 0xE878, 0x9469, 0xE879, 0x946A, 0xE87A, + 0x946B, 0xF6CE, 0x946C, 0xE87B, 0x946D, 0xE87C, 0x946E, 0xE87D, 0x946F, 0xE87E, 0x9470, 0xE880, 0x9471, 0xE881, 0x9472, 0xE882, + 0x9473, 0xE883, 0x9474, 0xE884, 0x9475, 0xE885, 0x9476, 0xE886, 0x9477, 0xE887, 0x9478, 0xE888, 0x9479, 0xE889, 0x947A, 0xE88A, + 0x947B, 0xE88B, 0x947C, 0xE88C, 0x947D, 0xE88D, 0x947E, 0xE88E, 0x947F, 0xE88F, 0x9480, 0xE890, 0x9481, 0xE891, 0x9482, 0xE892, + 0x9483, 0xE893, 0x9484, 0xE894, 0x9485, 0xEEC4, 0x9486, 0xEEC5, 0x9487, 0xEEC6, 0x9488, 0xD5EB, 0x9489, 0xB6A4, 0x948A, 0xEEC8, + 0x948B, 0xEEC7, 0x948C, 0xEEC9, 0x948D, 0xEECA, 0x948E, 0xC7A5, 0x948F, 0xEECB, 0x9490, 0xEECC, 0x9491, 0xE895, 0x9492, 0xB7B0, + 0x9493, 0xB5F6, 0x9494, 0xEECD, 0x9495, 0xEECF, 0x9496, 0xE896, 0x9497, 0xEECE, 0x9498, 0xE897, 0x9499, 0xB8C6, 0x949A, 0xEED0, + 0x949B, 0xEED1, 0x949C, 0xEED2, 0x949D, 0xB6DB, 0x949E, 0xB3AE, 0x949F, 0xD6D3, 0x94A0, 0xC4C6, 0x94A1, 0xB1B5, 0x94A2, 0xB8D6, + 0x94A3, 0xEED3, 0x94A4, 0xEED4, 0x94A5, 0xD4BF, 0x94A6, 0xC7D5, 0x94A7, 0xBEFB, 0x94A8, 0xCED9, 0x94A9, 0xB9B3, 0x94AA, 0xEED6, + 0x94AB, 0xEED5, 0x94AC, 0xEED8, 0x94AD, 0xEED7, 0x94AE, 0xC5A5, 0x94AF, 0xEED9, 0x94B0, 0xEEDA, 0x94B1, 0xC7AE, 0x94B2, 0xEEDB, + 0x94B3, 0xC7AF, 0x94B4, 0xEEDC, 0x94B5, 0xB2A7, 0x94B6, 0xEEDD, 0x94B7, 0xEEDE, 0x94B8, 0xEEDF, 0x94B9, 0xEEE0, 0x94BA, 0xEEE1, + 0x94BB, 0xD7EA, 0x94BC, 0xEEE2, 0x94BD, 0xEEE3, 0x94BE, 0xBCD8, 0x94BF, 0xEEE4, 0x94C0, 0xD3CB, 0x94C1, 0xCCFA, 0x94C2, 0xB2AC, + 0x94C3, 0xC1E5, 0x94C4, 0xEEE5, 0x94C5, 0xC7A6, 0x94C6, 0xC3AD, 0x94C7, 0xE898, 0x94C8, 0xEEE6, 0x94C9, 0xEEE7, 0x94CA, 0xEEE8, + 0x94CB, 0xEEE9, 0x94CC, 0xEEEA, 0x94CD, 0xEEEB, 0x94CE, 0xEEEC, 0x94CF, 0xE899, 0x94D0, 0xEEED, 0x94D1, 0xEEEE, 0x94D2, 0xEEEF, + 0x94D3, 0xE89A, 0x94D4, 0xE89B, 0x94D5, 0xEEF0, 0x94D6, 0xEEF1, 0x94D7, 0xEEF2, 0x94D8, 0xEEF4, 0x94D9, 0xEEF3, 0x94DA, 0xE89C, + 0x94DB, 0xEEF5, 0x94DC, 0xCDAD, 0x94DD, 0xC2C1, 0x94DE, 0xEEF6, 0x94DF, 0xEEF7, 0x94E0, 0xEEF8, 0x94E1, 0xD5A1, 0x94E2, 0xEEF9, + 0x94E3, 0xCFB3, 0x94E4, 0xEEFA, 0x94E5, 0xEEFB, 0x94E6, 0xE89D, 0x94E7, 0xEEFC, 0x94E8, 0xEEFD, 0x94E9, 0xEFA1, 0x94EA, 0xEEFE, + 0x94EB, 0xEFA2, 0x94EC, 0xB8F5, 0x94ED, 0xC3FA, 0x94EE, 0xEFA3, 0x94EF, 0xEFA4, 0x94F0, 0xBDC2, 0x94F1, 0xD2BF, 0x94F2, 0xB2F9, + 0x94F3, 0xEFA5, 0x94F4, 0xEFA6, 0x94F5, 0xEFA7, 0x94F6, 0xD2F8, 0x94F7, 0xEFA8, 0x94F8, 0xD6FD, 0x94F9, 0xEFA9, 0x94FA, 0xC6CC, + 0x94FB, 0xE89E, 0x94FC, 0xEFAA, 0x94FD, 0xEFAB, 0x94FE, 0xC1B4, 0x94FF, 0xEFAC, 0x9500, 0xCFFA, 0x9501, 0xCBF8, 0x9502, 0xEFAE, + 0x9503, 0xEFAD, 0x9504, 0xB3FA, 0x9505, 0xB9F8, 0x9506, 0xEFAF, 0x9507, 0xEFB0, 0x9508, 0xD0E2, 0x9509, 0xEFB1, 0x950A, 0xEFB2, + 0x950B, 0xB7E6, 0x950C, 0xD0BF, 0x950D, 0xEFB3, 0x950E, 0xEFB4, 0x950F, 0xEFB5, 0x9510, 0xC8F1, 0x9511, 0xCCE0, 0x9512, 0xEFB6, + 0x9513, 0xEFB7, 0x9514, 0xEFB8, 0x9515, 0xEFB9, 0x9516, 0xEFBA, 0x9517, 0xD5E0, 0x9518, 0xEFBB, 0x9519, 0xB4ED, 0x951A, 0xC3AA, + 0x951B, 0xEFBC, 0x951C, 0xE89F, 0x951D, 0xEFBD, 0x951E, 0xEFBE, 0x951F, 0xEFBF, 0x9520, 0xE8A0, 0x9521, 0xCEFD, 0x9522, 0xEFC0, + 0x9523, 0xC2E0, 0x9524, 0xB4B8, 0x9525, 0xD7B6, 0x9526, 0xBDF5, 0x9527, 0xE940, 0x9528, 0xCFC7, 0x9529, 0xEFC3, 0x952A, 0xEFC1, + 0x952B, 0xEFC2, 0x952C, 0xEFC4, 0x952D, 0xB6A7, 0x952E, 0xBCFC, 0x952F, 0xBEE2, 0x9530, 0xC3CC, 0x9531, 0xEFC5, 0x9532, 0xEFC6, + 0x9533, 0xE941, 0x9534, 0xEFC7, 0x9535, 0xEFCF, 0x9536, 0xEFC8, 0x9537, 0xEFC9, 0x9538, 0xEFCA, 0x9539, 0xC7C2, 0x953A, 0xEFF1, + 0x953B, 0xB6CD, 0x953C, 0xEFCB, 0x953D, 0xE942, 0x953E, 0xEFCC, 0x953F, 0xEFCD, 0x9540, 0xB6C6, 0x9541, 0xC3BE, 0x9542, 0xEFCE, + 0x9543, 0xE943, 0x9544, 0xEFD0, 0x9545, 0xEFD1, 0x9546, 0xEFD2, 0x9547, 0xD5F2, 0x9548, 0xE944, 0x9549, 0xEFD3, 0x954A, 0xC4F7, + 0x954B, 0xE945, 0x954C, 0xEFD4, 0x954D, 0xC4F8, 0x954E, 0xEFD5, 0x954F, 0xEFD6, 0x9550, 0xB8E4, 0x9551, 0xB0F7, 0x9552, 0xEFD7, + 0x9553, 0xEFD8, 0x9554, 0xEFD9, 0x9555, 0xE946, 0x9556, 0xEFDA, 0x9557, 0xEFDB, 0x9558, 0xEFDC, 0x9559, 0xEFDD, 0x955A, 0xE947, + 0x955B, 0xEFDE, 0x955C, 0xBEB5, 0x955D, 0xEFE1, 0x955E, 0xEFDF, 0x955F, 0xEFE0, 0x9560, 0xE948, 0x9561, 0xEFE2, 0x9562, 0xEFE3, + 0x9563, 0xC1CD, 0x9564, 0xEFE4, 0x9565, 0xEFE5, 0x9566, 0xEFE6, 0x9567, 0xEFE7, 0x9568, 0xEFE8, 0x9569, 0xEFE9, 0x956A, 0xEFEA, + 0x956B, 0xEFEB, 0x956C, 0xEFEC, 0x956D, 0xC0D8, 0x956E, 0xE949, 0x956F, 0xEFED, 0x9570, 0xC1AD, 0x9571, 0xEFEE, 0x9572, 0xEFEF, + 0x9573, 0xEFF0, 0x9574, 0xE94A, 0x9575, 0xE94B, 0x9576, 0xCFE2, 0x9577, 0xE94C, 0x9578, 0xE94D, 0x9579, 0xE94E, 0x957A, 0xE94F, + 0x957B, 0xE950, 0x957C, 0xE951, 0x957D, 0xE952, 0x957E, 0xE953, 0x957F, 0xB3A4, 0x9580, 0xE954, 0x9581, 0xE955, 0x9582, 0xE956, + 0x9583, 0xE957, 0x9584, 0xE958, 0x9585, 0xE959, 0x9586, 0xE95A, 0x9587, 0xE95B, 0x9588, 0xE95C, 0x9589, 0xE95D, 0x958A, 0xE95E, + 0x958B, 0xE95F, 0x958C, 0xE960, 0x958D, 0xE961, 0x958E, 0xE962, 0x958F, 0xE963, 0x9590, 0xE964, 0x9591, 0xE965, 0x9592, 0xE966, + 0x9593, 0xE967, 0x9594, 0xE968, 0x9595, 0xE969, 0x9596, 0xE96A, 0x9597, 0xE96B, 0x9598, 0xE96C, 0x9599, 0xE96D, 0x959A, 0xE96E, + 0x959B, 0xE96F, 0x959C, 0xE970, 0x959D, 0xE971, 0x959E, 0xE972, 0x959F, 0xE973, 0x95A0, 0xE974, 0x95A1, 0xE975, 0x95A2, 0xE976, + 0x95A3, 0xE977, 0x95A4, 0xE978, 0x95A5, 0xE979, 0x95A6, 0xE97A, 0x95A7, 0xE97B, 0x95A8, 0xE97C, 0x95A9, 0xE97D, 0x95AA, 0xE97E, + 0x95AB, 0xE980, 0x95AC, 0xE981, 0x95AD, 0xE982, 0x95AE, 0xE983, 0x95AF, 0xE984, 0x95B0, 0xE985, 0x95B1, 0xE986, 0x95B2, 0xE987, + 0x95B3, 0xE988, 0x95B4, 0xE989, 0x95B5, 0xE98A, 0x95B6, 0xE98B, 0x95B7, 0xE98C, 0x95B8, 0xE98D, 0x95B9, 0xE98E, 0x95BA, 0xE98F, + 0x95BB, 0xE990, 0x95BC, 0xE991, 0x95BD, 0xE992, 0x95BE, 0xE993, 0x95BF, 0xE994, 0x95C0, 0xE995, 0x95C1, 0xE996, 0x95C2, 0xE997, + 0x95C3, 0xE998, 0x95C4, 0xE999, 0x95C5, 0xE99A, 0x95C6, 0xE99B, 0x95C7, 0xE99C, 0x95C8, 0xE99D, 0x95C9, 0xE99E, 0x95CA, 0xE99F, + 0x95CB, 0xE9A0, 0x95CC, 0xEA40, 0x95CD, 0xEA41, 0x95CE, 0xEA42, 0x95CF, 0xEA43, 0x95D0, 0xEA44, 0x95D1, 0xEA45, 0x95D2, 0xEA46, + 0x95D3, 0xEA47, 0x95D4, 0xEA48, 0x95D5, 0xEA49, 0x95D6, 0xEA4A, 0x95D7, 0xEA4B, 0x95D8, 0xEA4C, 0x95D9, 0xEA4D, 0x95DA, 0xEA4E, + 0x95DB, 0xEA4F, 0x95DC, 0xEA50, 0x95DD, 0xEA51, 0x95DE, 0xEA52, 0x95DF, 0xEA53, 0x95E0, 0xEA54, 0x95E1, 0xEA55, 0x95E2, 0xEA56, + 0x95E3, 0xEA57, 0x95E4, 0xEA58, 0x95E5, 0xEA59, 0x95E6, 0xEA5A, 0x95E7, 0xEA5B, 0x95E8, 0xC3C5, 0x95E9, 0xE3C5, 0x95EA, 0xC9C1, + 0x95EB, 0xE3C6, 0x95EC, 0xEA5C, 0x95ED, 0xB1D5, 0x95EE, 0xCECA, 0x95EF, 0xB4B3, 0x95F0, 0xC8F2, 0x95F1, 0xE3C7, 0x95F2, 0xCFD0, + 0x95F3, 0xE3C8, 0x95F4, 0xBCE4, 0x95F5, 0xE3C9, 0x95F6, 0xE3CA, 0x95F7, 0xC3C6, 0x95F8, 0xD5A2, 0x95F9, 0xC4D6, 0x95FA, 0xB9EB, + 0x95FB, 0xCEC5, 0x95FC, 0xE3CB, 0x95FD, 0xC3F6, 0x95FE, 0xE3CC, 0x95FF, 0xEA5D, 0x9600, 0xB7A7, 0x9601, 0xB8F3, 0x9602, 0xBAD2, + 0x9603, 0xE3CD, 0x9604, 0xE3CE, 0x9605, 0xD4C4, 0x9606, 0xE3CF, 0x9607, 0xEA5E, 0x9608, 0xE3D0, 0x9609, 0xD1CB, 0x960A, 0xE3D1, + 0x960B, 0xE3D2, 0x960C, 0xE3D3, 0x960D, 0xE3D4, 0x960E, 0xD1D6, 0x960F, 0xE3D5, 0x9610, 0xB2FB, 0x9611, 0xC0BB, 0x9612, 0xE3D6, + 0x9613, 0xEA5F, 0x9614, 0xC0AB, 0x9615, 0xE3D7, 0x9616, 0xE3D8, 0x9617, 0xE3D9, 0x9618, 0xEA60, 0x9619, 0xE3DA, 0x961A, 0xE3DB, + 0x961B, 0xEA61, 0x961C, 0xB8B7, 0x961D, 0xDAE2, 0x961E, 0xEA62, 0x961F, 0xB6D3, 0x9620, 0xEA63, 0x9621, 0xDAE4, 0x9622, 0xDAE3, + 0x9623, 0xEA64, 0x9624, 0xEA65, 0x9625, 0xEA66, 0x9626, 0xEA67, 0x9627, 0xEA68, 0x9628, 0xEA69, 0x9629, 0xEA6A, 0x962A, 0xDAE6, + 0x962B, 0xEA6B, 0x962C, 0xEA6C, 0x962D, 0xEA6D, 0x962E, 0xC8EE, 0x962F, 0xEA6E, 0x9630, 0xEA6F, 0x9631, 0xDAE5, 0x9632, 0xB7C0, + 0x9633, 0xD1F4, 0x9634, 0xD2F5, 0x9635, 0xD5F3, 0x9636, 0xBDD7, 0x9637, 0xEA70, 0x9638, 0xEA71, 0x9639, 0xEA72, 0x963A, 0xEA73, + 0x963B, 0xD7E8, 0x963C, 0xDAE8, 0x963D, 0xDAE7, 0x963E, 0xEA74, 0x963F, 0xB0A2, 0x9640, 0xCDD3, 0x9641, 0xEA75, 0x9642, 0xDAE9, + 0x9643, 0xEA76, 0x9644, 0xB8BD, 0x9645, 0xBCCA, 0x9646, 0xC2BD, 0x9647, 0xC2A4, 0x9648, 0xB3C2, 0x9649, 0xDAEA, 0x964A, 0xEA77, + 0x964B, 0xC2AA, 0x964C, 0xC4B0, 0x964D, 0xBDB5, 0x964E, 0xEA78, 0x964F, 0xEA79, 0x9650, 0xCFDE, 0x9651, 0xEA7A, 0x9652, 0xEA7B, + 0x9653, 0xEA7C, 0x9654, 0xDAEB, 0x9655, 0xC9C2, 0x9656, 0xEA7D, 0x9657, 0xEA7E, 0x9658, 0xEA80, 0x9659, 0xEA81, 0x965A, 0xEA82, + 0x965B, 0xB1DD, 0x965C, 0xEA83, 0x965D, 0xEA84, 0x965E, 0xEA85, 0x965F, 0xDAEC, 0x9660, 0xEA86, 0x9661, 0xB6B8, 0x9662, 0xD4BA, + 0x9663, 0xEA87, 0x9664, 0xB3FD, 0x9665, 0xEA88, 0x9666, 0xEA89, 0x9667, 0xDAED, 0x9668, 0xD4C9, 0x9669, 0xCFD5, 0x966A, 0xC5E3, + 0x966B, 0xEA8A, 0x966C, 0xDAEE, 0x966D, 0xEA8B, 0x966E, 0xEA8C, 0x966F, 0xEA8D, 0x9670, 0xEA8E, 0x9671, 0xEA8F, 0x9672, 0xDAEF, + 0x9673, 0xEA90, 0x9674, 0xDAF0, 0x9675, 0xC1EA, 0x9676, 0xCCD5, 0x9677, 0xCFDD, 0x9678, 0xEA91, 0x9679, 0xEA92, 0x967A, 0xEA93, + 0x967B, 0xEA94, 0x967C, 0xEA95, 0x967D, 0xEA96, 0x967E, 0xEA97, 0x967F, 0xEA98, 0x9680, 0xEA99, 0x9681, 0xEA9A, 0x9682, 0xEA9B, + 0x9683, 0xEA9C, 0x9684, 0xEA9D, 0x9685, 0xD3E7, 0x9686, 0xC2A1, 0x9687, 0xEA9E, 0x9688, 0xDAF1, 0x9689, 0xEA9F, 0x968A, 0xEAA0, + 0x968B, 0xCBE5, 0x968C, 0xEB40, 0x968D, 0xDAF2, 0x968E, 0xEB41, 0x968F, 0xCBE6, 0x9690, 0xD2FE, 0x9691, 0xEB42, 0x9692, 0xEB43, + 0x9693, 0xEB44, 0x9694, 0xB8F4, 0x9695, 0xEB45, 0x9696, 0xEB46, 0x9697, 0xDAF3, 0x9698, 0xB0AF, 0x9699, 0xCFB6, 0x969A, 0xEB47, + 0x969B, 0xEB48, 0x969C, 0xD5CF, 0x969D, 0xEB49, 0x969E, 0xEB4A, 0x969F, 0xEB4B, 0x96A0, 0xEB4C, 0x96A1, 0xEB4D, 0x96A2, 0xEB4E, + 0x96A3, 0xEB4F, 0x96A4, 0xEB50, 0x96A5, 0xEB51, 0x96A6, 0xEB52, 0x96A7, 0xCBED, 0x96A8, 0xEB53, 0x96A9, 0xEB54, 0x96AA, 0xEB55, + 0x96AB, 0xEB56, 0x96AC, 0xEB57, 0x96AD, 0xEB58, 0x96AE, 0xEB59, 0x96AF, 0xEB5A, 0x96B0, 0xDAF4, 0x96B1, 0xEB5B, 0x96B2, 0xEB5C, + 0x96B3, 0xE3C4, 0x96B4, 0xEB5D, 0x96B5, 0xEB5E, 0x96B6, 0xC1A5, 0x96B7, 0xEB5F, 0x96B8, 0xEB60, 0x96B9, 0xF6BF, 0x96BA, 0xEB61, + 0x96BB, 0xEB62, 0x96BC, 0xF6C0, 0x96BD, 0xF6C1, 0x96BE, 0xC4D1, 0x96BF, 0xEB63, 0x96C0, 0xC8B8, 0x96C1, 0xD1E3, 0x96C2, 0xEB64, + 0x96C3, 0xEB65, 0x96C4, 0xD0DB, 0x96C5, 0xD1C5, 0x96C6, 0xBCAF, 0x96C7, 0xB9CD, 0x96C8, 0xEB66, 0x96C9, 0xEFF4, 0x96CA, 0xEB67, + 0x96CB, 0xEB68, 0x96CC, 0xB4C6, 0x96CD, 0xD3BA, 0x96CE, 0xF6C2, 0x96CF, 0xB3FB, 0x96D0, 0xEB69, 0x96D1, 0xEB6A, 0x96D2, 0xF6C3, + 0x96D3, 0xEB6B, 0x96D4, 0xEB6C, 0x96D5, 0xB5F1, 0x96D6, 0xEB6D, 0x96D7, 0xEB6E, 0x96D8, 0xEB6F, 0x96D9, 0xEB70, 0x96DA, 0xEB71, + 0x96DB, 0xEB72, 0x96DC, 0xEB73, 0x96DD, 0xEB74, 0x96DE, 0xEB75, 0x96DF, 0xEB76, 0x96E0, 0xF6C5, 0x96E1, 0xEB77, 0x96E2, 0xEB78, + 0x96E3, 0xEB79, 0x96E4, 0xEB7A, 0x96E5, 0xEB7B, 0x96E6, 0xEB7C, 0x96E7, 0xEB7D, 0x96E8, 0xD3EA, 0x96E9, 0xF6A7, 0x96EA, 0xD1A9, + 0x96EB, 0xEB7E, 0x96EC, 0xEB80, 0x96ED, 0xEB81, 0x96EE, 0xEB82, 0x96EF, 0xF6A9, 0x96F0, 0xEB83, 0x96F1, 0xEB84, 0x96F2, 0xEB85, + 0x96F3, 0xF6A8, 0x96F4, 0xEB86, 0x96F5, 0xEB87, 0x96F6, 0xC1E3, 0x96F7, 0xC0D7, 0x96F8, 0xEB88, 0x96F9, 0xB1A2, 0x96FA, 0xEB89, + 0x96FB, 0xEB8A, 0x96FC, 0xEB8B, 0x96FD, 0xEB8C, 0x96FE, 0xCEED, 0x96FF, 0xEB8D, 0x9700, 0xD0E8, 0x9701, 0xF6AB, 0x9702, 0xEB8E, + 0x9703, 0xEB8F, 0x9704, 0xCFF6, 0x9705, 0xEB90, 0x9706, 0xF6AA, 0x9707, 0xD5F0, 0x9708, 0xF6AC, 0x9709, 0xC3B9, 0x970A, 0xEB91, + 0x970B, 0xEB92, 0x970C, 0xEB93, 0x970D, 0xBBF4, 0x970E, 0xF6AE, 0x970F, 0xF6AD, 0x9710, 0xEB94, 0x9711, 0xEB95, 0x9712, 0xEB96, + 0x9713, 0xC4DE, 0x9714, 0xEB97, 0x9715, 0xEB98, 0x9716, 0xC1D8, 0x9717, 0xEB99, 0x9718, 0xEB9A, 0x9719, 0xEB9B, 0x971A, 0xEB9C, + 0x971B, 0xEB9D, 0x971C, 0xCBAA, 0x971D, 0xEB9E, 0x971E, 0xCFBC, 0x971F, 0xEB9F, 0x9720, 0xEBA0, 0x9721, 0xEC40, 0x9722, 0xEC41, + 0x9723, 0xEC42, 0x9724, 0xEC43, 0x9725, 0xEC44, 0x9726, 0xEC45, 0x9727, 0xEC46, 0x9728, 0xEC47, 0x9729, 0xEC48, 0x972A, 0xF6AF, + 0x972B, 0xEC49, 0x972C, 0xEC4A, 0x972D, 0xF6B0, 0x972E, 0xEC4B, 0x972F, 0xEC4C, 0x9730, 0xF6B1, 0x9731, 0xEC4D, 0x9732, 0xC2B6, + 0x9733, 0xEC4E, 0x9734, 0xEC4F, 0x9735, 0xEC50, 0x9736, 0xEC51, 0x9737, 0xEC52, 0x9738, 0xB0D4, 0x9739, 0xC5F9, 0x973A, 0xEC53, + 0x973B, 0xEC54, 0x973C, 0xEC55, 0x973D, 0xEC56, 0x973E, 0xF6B2, 0x973F, 0xEC57, 0x9740, 0xEC58, 0x9741, 0xEC59, 0x9742, 0xEC5A, + 0x9743, 0xEC5B, 0x9744, 0xEC5C, 0x9745, 0xEC5D, 0x9746, 0xEC5E, 0x9747, 0xEC5F, 0x9748, 0xEC60, 0x9749, 0xEC61, 0x974A, 0xEC62, + 0x974B, 0xEC63, 0x974C, 0xEC64, 0x974D, 0xEC65, 0x974E, 0xEC66, 0x974F, 0xEC67, 0x9750, 0xEC68, 0x9751, 0xEC69, 0x9752, 0xC7E0, + 0x9753, 0xF6A6, 0x9754, 0xEC6A, 0x9755, 0xEC6B, 0x9756, 0xBEB8, 0x9757, 0xEC6C, 0x9758, 0xEC6D, 0x9759, 0xBEB2, 0x975A, 0xEC6E, + 0x975B, 0xB5E5, 0x975C, 0xEC6F, 0x975D, 0xEC70, 0x975E, 0xB7C7, 0x975F, 0xEC71, 0x9760, 0xBFBF, 0x9761, 0xC3D2, 0x9762, 0xC3E6, + 0x9763, 0xEC72, 0x9764, 0xEC73, 0x9765, 0xD8CC, 0x9766, 0xEC74, 0x9767, 0xEC75, 0x9768, 0xEC76, 0x9769, 0xB8EF, 0x976A, 0xEC77, + 0x976B, 0xEC78, 0x976C, 0xEC79, 0x976D, 0xEC7A, 0x976E, 0xEC7B, 0x976F, 0xEC7C, 0x9770, 0xEC7D, 0x9771, 0xEC7E, 0x9772, 0xEC80, + 0x9773, 0xBDF9, 0x9774, 0xD1A5, 0x9775, 0xEC81, 0x9776, 0xB0D0, 0x9777, 0xEC82, 0x9778, 0xEC83, 0x9779, 0xEC84, 0x977A, 0xEC85, + 0x977B, 0xEC86, 0x977C, 0xF7B0, 0x977D, 0xEC87, 0x977E, 0xEC88, 0x977F, 0xEC89, 0x9780, 0xEC8A, 0x9781, 0xEC8B, 0x9782, 0xEC8C, + 0x9783, 0xEC8D, 0x9784, 0xEC8E, 0x9785, 0xF7B1, 0x9786, 0xEC8F, 0x9787, 0xEC90, 0x9788, 0xEC91, 0x9789, 0xEC92, 0x978A, 0xEC93, + 0x978B, 0xD0AC, 0x978C, 0xEC94, 0x978D, 0xB0B0, 0x978E, 0xEC95, 0x978F, 0xEC96, 0x9790, 0xEC97, 0x9791, 0xF7B2, 0x9792, 0xF7B3, + 0x9793, 0xEC98, 0x9794, 0xF7B4, 0x9795, 0xEC99, 0x9796, 0xEC9A, 0x9797, 0xEC9B, 0x9798, 0xC7CA, 0x9799, 0xEC9C, 0x979A, 0xEC9D, + 0x979B, 0xEC9E, 0x979C, 0xEC9F, 0x979D, 0xECA0, 0x979E, 0xED40, 0x979F, 0xED41, 0x97A0, 0xBECF, 0x97A1, 0xED42, 0x97A2, 0xED43, + 0x97A3, 0xF7B7, 0x97A4, 0xED44, 0x97A5, 0xED45, 0x97A6, 0xED46, 0x97A7, 0xED47, 0x97A8, 0xED48, 0x97A9, 0xED49, 0x97AA, 0xED4A, + 0x97AB, 0xF7B6, 0x97AC, 0xED4B, 0x97AD, 0xB1DE, 0x97AE, 0xED4C, 0x97AF, 0xF7B5, 0x97B0, 0xED4D, 0x97B1, 0xED4E, 0x97B2, 0xF7B8, + 0x97B3, 0xED4F, 0x97B4, 0xF7B9, 0x97B5, 0xED50, 0x97B6, 0xED51, 0x97B7, 0xED52, 0x97B8, 0xED53, 0x97B9, 0xED54, 0x97BA, 0xED55, + 0x97BB, 0xED56, 0x97BC, 0xED57, 0x97BD, 0xED58, 0x97BE, 0xED59, 0x97BF, 0xED5A, 0x97C0, 0xED5B, 0x97C1, 0xED5C, 0x97C2, 0xED5D, + 0x97C3, 0xED5E, 0x97C4, 0xED5F, 0x97C5, 0xED60, 0x97C6, 0xED61, 0x97C7, 0xED62, 0x97C8, 0xED63, 0x97C9, 0xED64, 0x97CA, 0xED65, + 0x97CB, 0xED66, 0x97CC, 0xED67, 0x97CD, 0xED68, 0x97CE, 0xED69, 0x97CF, 0xED6A, 0x97D0, 0xED6B, 0x97D1, 0xED6C, 0x97D2, 0xED6D, + 0x97D3, 0xED6E, 0x97D4, 0xED6F, 0x97D5, 0xED70, 0x97D6, 0xED71, 0x97D7, 0xED72, 0x97D8, 0xED73, 0x97D9, 0xED74, 0x97DA, 0xED75, + 0x97DB, 0xED76, 0x97DC, 0xED77, 0x97DD, 0xED78, 0x97DE, 0xED79, 0x97DF, 0xED7A, 0x97E0, 0xED7B, 0x97E1, 0xED7C, 0x97E2, 0xED7D, + 0x97E3, 0xED7E, 0x97E4, 0xED80, 0x97E5, 0xED81, 0x97E6, 0xCEA4, 0x97E7, 0xC8CD, 0x97E8, 0xED82, 0x97E9, 0xBAAB, 0x97EA, 0xE8B8, + 0x97EB, 0xE8B9, 0x97EC, 0xE8BA, 0x97ED, 0xBEC2, 0x97EE, 0xED83, 0x97EF, 0xED84, 0x97F0, 0xED85, 0x97F1, 0xED86, 0x97F2, 0xED87, + 0x97F3, 0xD2F4, 0x97F4, 0xED88, 0x97F5, 0xD4CF, 0x97F6, 0xC9D8, 0x97F7, 0xED89, 0x97F8, 0xED8A, 0x97F9, 0xED8B, 0x97FA, 0xED8C, + 0x97FB, 0xED8D, 0x97FC, 0xED8E, 0x97FD, 0xED8F, 0x97FE, 0xED90, 0x97FF, 0xED91, 0x9800, 0xED92, 0x9801, 0xED93, 0x9802, 0xED94, + 0x9803, 0xED95, 0x9804, 0xED96, 0x9805, 0xED97, 0x9806, 0xED98, 0x9807, 0xED99, 0x9808, 0xED9A, 0x9809, 0xED9B, 0x980A, 0xED9C, + 0x980B, 0xED9D, 0x980C, 0xED9E, 0x980D, 0xED9F, 0x980E, 0xEDA0, 0x980F, 0xEE40, 0x9810, 0xEE41, 0x9811, 0xEE42, 0x9812, 0xEE43, + 0x9813, 0xEE44, 0x9814, 0xEE45, 0x9815, 0xEE46, 0x9816, 0xEE47, 0x9817, 0xEE48, 0x9818, 0xEE49, 0x9819, 0xEE4A, 0x981A, 0xEE4B, + 0x981B, 0xEE4C, 0x981C, 0xEE4D, 0x981D, 0xEE4E, 0x981E, 0xEE4F, 0x981F, 0xEE50, 0x9820, 0xEE51, 0x9821, 0xEE52, 0x9822, 0xEE53, + 0x9823, 0xEE54, 0x9824, 0xEE55, 0x9825, 0xEE56, 0x9826, 0xEE57, 0x9827, 0xEE58, 0x9828, 0xEE59, 0x9829, 0xEE5A, 0x982A, 0xEE5B, + 0x982B, 0xEE5C, 0x982C, 0xEE5D, 0x982D, 0xEE5E, 0x982E, 0xEE5F, 0x982F, 0xEE60, 0x9830, 0xEE61, 0x9831, 0xEE62, 0x9832, 0xEE63, + 0x9833, 0xEE64, 0x9834, 0xEE65, 0x9835, 0xEE66, 0x9836, 0xEE67, 0x9837, 0xEE68, 0x9838, 0xEE69, 0x9839, 0xEE6A, 0x983A, 0xEE6B, + 0x983B, 0xEE6C, 0x983C, 0xEE6D, 0x983D, 0xEE6E, 0x983E, 0xEE6F, 0x983F, 0xEE70, 0x9840, 0xEE71, 0x9841, 0xEE72, 0x9842, 0xEE73, + 0x9843, 0xEE74, 0x9844, 0xEE75, 0x9845, 0xEE76, 0x9846, 0xEE77, 0x9847, 0xEE78, 0x9848, 0xEE79, 0x9849, 0xEE7A, 0x984A, 0xEE7B, + 0x984B, 0xEE7C, 0x984C, 0xEE7D, 0x984D, 0xEE7E, 0x984E, 0xEE80, 0x984F, 0xEE81, 0x9850, 0xEE82, 0x9851, 0xEE83, 0x9852, 0xEE84, + 0x9853, 0xEE85, 0x9854, 0xEE86, 0x9855, 0xEE87, 0x9856, 0xEE88, 0x9857, 0xEE89, 0x9858, 0xEE8A, 0x9859, 0xEE8B, 0x985A, 0xEE8C, + 0x985B, 0xEE8D, 0x985C, 0xEE8E, 0x985D, 0xEE8F, 0x985E, 0xEE90, 0x985F, 0xEE91, 0x9860, 0xEE92, 0x9861, 0xEE93, 0x9862, 0xEE94, + 0x9863, 0xEE95, 0x9864, 0xEE96, 0x9865, 0xEE97, 0x9866, 0xEE98, 0x9867, 0xEE99, 0x9868, 0xEE9A, 0x9869, 0xEE9B, 0x986A, 0xEE9C, + 0x986B, 0xEE9D, 0x986C, 0xEE9E, 0x986D, 0xEE9F, 0x986E, 0xEEA0, 0x986F, 0xEF40, 0x9870, 0xEF41, 0x9871, 0xEF42, 0x9872, 0xEF43, + 0x9873, 0xEF44, 0x9874, 0xEF45, 0x9875, 0xD2B3, 0x9876, 0xB6A5, 0x9877, 0xC7EA, 0x9878, 0xF1FC, 0x9879, 0xCFEE, 0x987A, 0xCBB3, + 0x987B, 0xD0EB, 0x987C, 0xE7EF, 0x987D, 0xCDE7, 0x987E, 0xB9CB, 0x987F, 0xB6D9, 0x9880, 0xF1FD, 0x9881, 0xB0E4, 0x9882, 0xCBCC, + 0x9883, 0xF1FE, 0x9884, 0xD4A4, 0x9885, 0xC2AD, 0x9886, 0xC1EC, 0x9887, 0xC6C4, 0x9888, 0xBEB1, 0x9889, 0xF2A1, 0x988A, 0xBCD5, + 0x988B, 0xEF46, 0x988C, 0xF2A2, 0x988D, 0xF2A3, 0x988E, 0xEF47, 0x988F, 0xF2A4, 0x9890, 0xD2C3, 0x9891, 0xC6B5, 0x9892, 0xEF48, + 0x9893, 0xCDC7, 0x9894, 0xF2A5, 0x9895, 0xEF49, 0x9896, 0xD3B1, 0x9897, 0xBFC5, 0x9898, 0xCCE2, 0x9899, 0xEF4A, 0x989A, 0xF2A6, + 0x989B, 0xF2A7, 0x989C, 0xD1D5, 0x989D, 0xB6EE, 0x989E, 0xF2A8, 0x989F, 0xF2A9, 0x98A0, 0xB5DF, 0x98A1, 0xF2AA, 0x98A2, 0xF2AB, + 0x98A3, 0xEF4B, 0x98A4, 0xB2FC, 0x98A5, 0xF2AC, 0x98A6, 0xF2AD, 0x98A7, 0xC8A7, 0x98A8, 0xEF4C, 0x98A9, 0xEF4D, 0x98AA, 0xEF4E, + 0x98AB, 0xEF4F, 0x98AC, 0xEF50, 0x98AD, 0xEF51, 0x98AE, 0xEF52, 0x98AF, 0xEF53, 0x98B0, 0xEF54, 0x98B1, 0xEF55, 0x98B2, 0xEF56, + 0x98B3, 0xEF57, 0x98B4, 0xEF58, 0x98B5, 0xEF59, 0x98B6, 0xEF5A, 0x98B7, 0xEF5B, 0x98B8, 0xEF5C, 0x98B9, 0xEF5D, 0x98BA, 0xEF5E, + 0x98BB, 0xEF5F, 0x98BC, 0xEF60, 0x98BD, 0xEF61, 0x98BE, 0xEF62, 0x98BF, 0xEF63, 0x98C0, 0xEF64, 0x98C1, 0xEF65, 0x98C2, 0xEF66, + 0x98C3, 0xEF67, 0x98C4, 0xEF68, 0x98C5, 0xEF69, 0x98C6, 0xEF6A, 0x98C7, 0xEF6B, 0x98C8, 0xEF6C, 0x98C9, 0xEF6D, 0x98CA, 0xEF6E, + 0x98CB, 0xEF6F, 0x98CC, 0xEF70, 0x98CD, 0xEF71, 0x98CE, 0xB7E7, 0x98CF, 0xEF72, 0x98D0, 0xEF73, 0x98D1, 0xECA9, 0x98D2, 0xECAA, + 0x98D3, 0xECAB, 0x98D4, 0xEF74, 0x98D5, 0xECAC, 0x98D6, 0xEF75, 0x98D7, 0xEF76, 0x98D8, 0xC6AE, 0x98D9, 0xECAD, 0x98DA, 0xECAE, + 0x98DB, 0xEF77, 0x98DC, 0xEF78, 0x98DD, 0xEF79, 0x98DE, 0xB7C9, 0x98DF, 0xCAB3, 0x98E0, 0xEF7A, 0x98E1, 0xEF7B, 0x98E2, 0xEF7C, + 0x98E3, 0xEF7D, 0x98E4, 0xEF7E, 0x98E5, 0xEF80, 0x98E6, 0xEF81, 0x98E7, 0xE2B8, 0x98E8, 0xF7CF, 0x98E9, 0xEF82, 0x98EA, 0xEF83, + 0x98EB, 0xEF84, 0x98EC, 0xEF85, 0x98ED, 0xEF86, 0x98EE, 0xEF87, 0x98EF, 0xEF88, 0x98F0, 0xEF89, 0x98F1, 0xEF8A, 0x98F2, 0xEF8B, + 0x98F3, 0xEF8C, 0x98F4, 0xEF8D, 0x98F5, 0xEF8E, 0x98F6, 0xEF8F, 0x98F7, 0xEF90, 0x98F8, 0xEF91, 0x98F9, 0xEF92, 0x98FA, 0xEF93, + 0x98FB, 0xEF94, 0x98FC, 0xEF95, 0x98FD, 0xEF96, 0x98FE, 0xEF97, 0x98FF, 0xEF98, 0x9900, 0xEF99, 0x9901, 0xEF9A, 0x9902, 0xEF9B, + 0x9903, 0xEF9C, 0x9904, 0xEF9D, 0x9905, 0xEF9E, 0x9906, 0xEF9F, 0x9907, 0xEFA0, 0x9908, 0xF040, 0x9909, 0xF041, 0x990A, 0xF042, + 0x990B, 0xF043, 0x990C, 0xF044, 0x990D, 0xF7D0, 0x990E, 0xF045, 0x990F, 0xF046, 0x9910, 0xB2CD, 0x9911, 0xF047, 0x9912, 0xF048, + 0x9913, 0xF049, 0x9914, 0xF04A, 0x9915, 0xF04B, 0x9916, 0xF04C, 0x9917, 0xF04D, 0x9918, 0xF04E, 0x9919, 0xF04F, 0x991A, 0xF050, + 0x991B, 0xF051, 0x991C, 0xF052, 0x991D, 0xF053, 0x991E, 0xF054, 0x991F, 0xF055, 0x9920, 0xF056, 0x9921, 0xF057, 0x9922, 0xF058, + 0x9923, 0xF059, 0x9924, 0xF05A, 0x9925, 0xF05B, 0x9926, 0xF05C, 0x9927, 0xF05D, 0x9928, 0xF05E, 0x9929, 0xF05F, 0x992A, 0xF060, + 0x992B, 0xF061, 0x992C, 0xF062, 0x992D, 0xF063, 0x992E, 0xF7D1, 0x992F, 0xF064, 0x9930, 0xF065, 0x9931, 0xF066, 0x9932, 0xF067, + 0x9933, 0xF068, 0x9934, 0xF069, 0x9935, 0xF06A, 0x9936, 0xF06B, 0x9937, 0xF06C, 0x9938, 0xF06D, 0x9939, 0xF06E, 0x993A, 0xF06F, + 0x993B, 0xF070, 0x993C, 0xF071, 0x993D, 0xF072, 0x993E, 0xF073, 0x993F, 0xF074, 0x9940, 0xF075, 0x9941, 0xF076, 0x9942, 0xF077, + 0x9943, 0xF078, 0x9944, 0xF079, 0x9945, 0xF07A, 0x9946, 0xF07B, 0x9947, 0xF07C, 0x9948, 0xF07D, 0x9949, 0xF07E, 0x994A, 0xF080, + 0x994B, 0xF081, 0x994C, 0xF082, 0x994D, 0xF083, 0x994E, 0xF084, 0x994F, 0xF085, 0x9950, 0xF086, 0x9951, 0xF087, 0x9952, 0xF088, + 0x9953, 0xF089, 0x9954, 0xF7D3, 0x9955, 0xF7D2, 0x9956, 0xF08A, 0x9957, 0xF08B, 0x9958, 0xF08C, 0x9959, 0xF08D, 0x995A, 0xF08E, + 0x995B, 0xF08F, 0x995C, 0xF090, 0x995D, 0xF091, 0x995E, 0xF092, 0x995F, 0xF093, 0x9960, 0xF094, 0x9961, 0xF095, 0x9962, 0xF096, + 0x9963, 0xE2BB, 0x9964, 0xF097, 0x9965, 0xBCA2, 0x9966, 0xF098, 0x9967, 0xE2BC, 0x9968, 0xE2BD, 0x9969, 0xE2BE, 0x996A, 0xE2BF, + 0x996B, 0xE2C0, 0x996C, 0xE2C1, 0x996D, 0xB7B9, 0x996E, 0xD2FB, 0x996F, 0xBDA4, 0x9970, 0xCACE, 0x9971, 0xB1A5, 0x9972, 0xCBC7, + 0x9973, 0xF099, 0x9974, 0xE2C2, 0x9975, 0xB6FC, 0x9976, 0xC8C4, 0x9977, 0xE2C3, 0x9978, 0xF09A, 0x9979, 0xF09B, 0x997A, 0xBDC8, + 0x997B, 0xF09C, 0x997C, 0xB1FD, 0x997D, 0xE2C4, 0x997E, 0xF09D, 0x997F, 0xB6F6, 0x9980, 0xE2C5, 0x9981, 0xC4D9, 0x9982, 0xF09E, + 0x9983, 0xF09F, 0x9984, 0xE2C6, 0x9985, 0xCFDA, 0x9986, 0xB9DD, 0x9987, 0xE2C7, 0x9988, 0xC0A1, 0x9989, 0xF0A0, 0x998A, 0xE2C8, + 0x998B, 0xB2F6, 0x998C, 0xF140, 0x998D, 0xE2C9, 0x998E, 0xF141, 0x998F, 0xC1F3, 0x9990, 0xE2CA, 0x9991, 0xE2CB, 0x9992, 0xC2F8, + 0x9993, 0xE2CC, 0x9994, 0xE2CD, 0x9995, 0xE2CE, 0x9996, 0xCAD7, 0x9997, 0xD8B8, 0x9998, 0xD9E5, 0x9999, 0xCFE3, 0x999A, 0xF142, + 0x999B, 0xF143, 0x999C, 0xF144, 0x999D, 0xF145, 0x999E, 0xF146, 0x999F, 0xF147, 0x99A0, 0xF148, 0x99A1, 0xF149, 0x99A2, 0xF14A, + 0x99A3, 0xF14B, 0x99A4, 0xF14C, 0x99A5, 0xF0A5, 0x99A6, 0xF14D, 0x99A7, 0xF14E, 0x99A8, 0xDCB0, 0x99A9, 0xF14F, 0x99AA, 0xF150, + 0x99AB, 0xF151, 0x99AC, 0xF152, 0x99AD, 0xF153, 0x99AE, 0xF154, 0x99AF, 0xF155, 0x99B0, 0xF156, 0x99B1, 0xF157, 0x99B2, 0xF158, + 0x99B3, 0xF159, 0x99B4, 0xF15A, 0x99B5, 0xF15B, 0x99B6, 0xF15C, 0x99B7, 0xF15D, 0x99B8, 0xF15E, 0x99B9, 0xF15F, 0x99BA, 0xF160, + 0x99BB, 0xF161, 0x99BC, 0xF162, 0x99BD, 0xF163, 0x99BE, 0xF164, 0x99BF, 0xF165, 0x99C0, 0xF166, 0x99C1, 0xF167, 0x99C2, 0xF168, + 0x99C3, 0xF169, 0x99C4, 0xF16A, 0x99C5, 0xF16B, 0x99C6, 0xF16C, 0x99C7, 0xF16D, 0x99C8, 0xF16E, 0x99C9, 0xF16F, 0x99CA, 0xF170, + 0x99CB, 0xF171, 0x99CC, 0xF172, 0x99CD, 0xF173, 0x99CE, 0xF174, 0x99CF, 0xF175, 0x99D0, 0xF176, 0x99D1, 0xF177, 0x99D2, 0xF178, + 0x99D3, 0xF179, 0x99D4, 0xF17A, 0x99D5, 0xF17B, 0x99D6, 0xF17C, 0x99D7, 0xF17D, 0x99D8, 0xF17E, 0x99D9, 0xF180, 0x99DA, 0xF181, + 0x99DB, 0xF182, 0x99DC, 0xF183, 0x99DD, 0xF184, 0x99DE, 0xF185, 0x99DF, 0xF186, 0x99E0, 0xF187, 0x99E1, 0xF188, 0x99E2, 0xF189, + 0x99E3, 0xF18A, 0x99E4, 0xF18B, 0x99E5, 0xF18C, 0x99E6, 0xF18D, 0x99E7, 0xF18E, 0x99E8, 0xF18F, 0x99E9, 0xF190, 0x99EA, 0xF191, + 0x99EB, 0xF192, 0x99EC, 0xF193, 0x99ED, 0xF194, 0x99EE, 0xF195, 0x99EF, 0xF196, 0x99F0, 0xF197, 0x99F1, 0xF198, 0x99F2, 0xF199, + 0x99F3, 0xF19A, 0x99F4, 0xF19B, 0x99F5, 0xF19C, 0x99F6, 0xF19D, 0x99F7, 0xF19E, 0x99F8, 0xF19F, 0x99F9, 0xF1A0, 0x99FA, 0xF240, + 0x99FB, 0xF241, 0x99FC, 0xF242, 0x99FD, 0xF243, 0x99FE, 0xF244, 0x99FF, 0xF245, 0x9A00, 0xF246, 0x9A01, 0xF247, 0x9A02, 0xF248, + 0x9A03, 0xF249, 0x9A04, 0xF24A, 0x9A05, 0xF24B, 0x9A06, 0xF24C, 0x9A07, 0xF24D, 0x9A08, 0xF24E, 0x9A09, 0xF24F, 0x9A0A, 0xF250, + 0x9A0B, 0xF251, 0x9A0C, 0xF252, 0x9A0D, 0xF253, 0x9A0E, 0xF254, 0x9A0F, 0xF255, 0x9A10, 0xF256, 0x9A11, 0xF257, 0x9A12, 0xF258, + 0x9A13, 0xF259, 0x9A14, 0xF25A, 0x9A15, 0xF25B, 0x9A16, 0xF25C, 0x9A17, 0xF25D, 0x9A18, 0xF25E, 0x9A19, 0xF25F, 0x9A1A, 0xF260, + 0x9A1B, 0xF261, 0x9A1C, 0xF262, 0x9A1D, 0xF263, 0x9A1E, 0xF264, 0x9A1F, 0xF265, 0x9A20, 0xF266, 0x9A21, 0xF267, 0x9A22, 0xF268, + 0x9A23, 0xF269, 0x9A24, 0xF26A, 0x9A25, 0xF26B, 0x9A26, 0xF26C, 0x9A27, 0xF26D, 0x9A28, 0xF26E, 0x9A29, 0xF26F, 0x9A2A, 0xF270, + 0x9A2B, 0xF271, 0x9A2C, 0xF272, 0x9A2D, 0xF273, 0x9A2E, 0xF274, 0x9A2F, 0xF275, 0x9A30, 0xF276, 0x9A31, 0xF277, 0x9A32, 0xF278, + 0x9A33, 0xF279, 0x9A34, 0xF27A, 0x9A35, 0xF27B, 0x9A36, 0xF27C, 0x9A37, 0xF27D, 0x9A38, 0xF27E, 0x9A39, 0xF280, 0x9A3A, 0xF281, + 0x9A3B, 0xF282, 0x9A3C, 0xF283, 0x9A3D, 0xF284, 0x9A3E, 0xF285, 0x9A3F, 0xF286, 0x9A40, 0xF287, 0x9A41, 0xF288, 0x9A42, 0xF289, + 0x9A43, 0xF28A, 0x9A44, 0xF28B, 0x9A45, 0xF28C, 0x9A46, 0xF28D, 0x9A47, 0xF28E, 0x9A48, 0xF28F, 0x9A49, 0xF290, 0x9A4A, 0xF291, + 0x9A4B, 0xF292, 0x9A4C, 0xF293, 0x9A4D, 0xF294, 0x9A4E, 0xF295, 0x9A4F, 0xF296, 0x9A50, 0xF297, 0x9A51, 0xF298, 0x9A52, 0xF299, + 0x9A53, 0xF29A, 0x9A54, 0xF29B, 0x9A55, 0xF29C, 0x9A56, 0xF29D, 0x9A57, 0xF29E, 0x9A58, 0xF29F, 0x9A59, 0xF2A0, 0x9A5A, 0xF340, + 0x9A5B, 0xF341, 0x9A5C, 0xF342, 0x9A5D, 0xF343, 0x9A5E, 0xF344, 0x9A5F, 0xF345, 0x9A60, 0xF346, 0x9A61, 0xF347, 0x9A62, 0xF348, + 0x9A63, 0xF349, 0x9A64, 0xF34A, 0x9A65, 0xF34B, 0x9A66, 0xF34C, 0x9A67, 0xF34D, 0x9A68, 0xF34E, 0x9A69, 0xF34F, 0x9A6A, 0xF350, + 0x9A6B, 0xF351, 0x9A6C, 0xC2ED, 0x9A6D, 0xD4A6, 0x9A6E, 0xCDD4, 0x9A6F, 0xD1B1, 0x9A70, 0xB3DB, 0x9A71, 0xC7FD, 0x9A72, 0xF352, + 0x9A73, 0xB2B5, 0x9A74, 0xC2BF, 0x9A75, 0xE6E0, 0x9A76, 0xCABB, 0x9A77, 0xE6E1, 0x9A78, 0xE6E2, 0x9A79, 0xBED4, 0x9A7A, 0xE6E3, + 0x9A7B, 0xD7A4, 0x9A7C, 0xCDD5, 0x9A7D, 0xE6E5, 0x9A7E, 0xBCDD, 0x9A7F, 0xE6E4, 0x9A80, 0xE6E6, 0x9A81, 0xE6E7, 0x9A82, 0xC2EE, + 0x9A83, 0xF353, 0x9A84, 0xBDBE, 0x9A85, 0xE6E8, 0x9A86, 0xC2E6, 0x9A87, 0xBAA7, 0x9A88, 0xE6E9, 0x9A89, 0xF354, 0x9A8A, 0xE6EA, + 0x9A8B, 0xB3D2, 0x9A8C, 0xD1E9, 0x9A8D, 0xF355, 0x9A8E, 0xF356, 0x9A8F, 0xBFA5, 0x9A90, 0xE6EB, 0x9A91, 0xC6EF, 0x9A92, 0xE6EC, + 0x9A93, 0xE6ED, 0x9A94, 0xF357, 0x9A95, 0xF358, 0x9A96, 0xE6EE, 0x9A97, 0xC6AD, 0x9A98, 0xE6EF, 0x9A99, 0xF359, 0x9A9A, 0xC9A7, + 0x9A9B, 0xE6F0, 0x9A9C, 0xE6F1, 0x9A9D, 0xE6F2, 0x9A9E, 0xE5B9, 0x9A9F, 0xE6F3, 0x9AA0, 0xE6F4, 0x9AA1, 0xC2E2, 0x9AA2, 0xE6F5, + 0x9AA3, 0xE6F6, 0x9AA4, 0xD6E8, 0x9AA5, 0xE6F7, 0x9AA6, 0xF35A, 0x9AA7, 0xE6F8, 0x9AA8, 0xB9C7, 0x9AA9, 0xF35B, 0x9AAA, 0xF35C, + 0x9AAB, 0xF35D, 0x9AAC, 0xF35E, 0x9AAD, 0xF35F, 0x9AAE, 0xF360, 0x9AAF, 0xF361, 0x9AB0, 0xF7BB, 0x9AB1, 0xF7BA, 0x9AB2, 0xF362, + 0x9AB3, 0xF363, 0x9AB4, 0xF364, 0x9AB5, 0xF365, 0x9AB6, 0xF7BE, 0x9AB7, 0xF7BC, 0x9AB8, 0xBAA1, 0x9AB9, 0xF366, 0x9ABA, 0xF7BF, + 0x9ABB, 0xF367, 0x9ABC, 0xF7C0, 0x9ABD, 0xF368, 0x9ABE, 0xF369, 0x9ABF, 0xF36A, 0x9AC0, 0xF7C2, 0x9AC1, 0xF7C1, 0x9AC2, 0xF7C4, + 0x9AC3, 0xF36B, 0x9AC4, 0xF36C, 0x9AC5, 0xF7C3, 0x9AC6, 0xF36D, 0x9AC7, 0xF36E, 0x9AC8, 0xF36F, 0x9AC9, 0xF370, 0x9ACA, 0xF371, + 0x9ACB, 0xF7C5, 0x9ACC, 0xF7C6, 0x9ACD, 0xF372, 0x9ACE, 0xF373, 0x9ACF, 0xF374, 0x9AD0, 0xF375, 0x9AD1, 0xF7C7, 0x9AD2, 0xF376, + 0x9AD3, 0xCBE8, 0x9AD4, 0xF377, 0x9AD5, 0xF378, 0x9AD6, 0xF379, 0x9AD7, 0xF37A, 0x9AD8, 0xB8DF, 0x9AD9, 0xF37B, 0x9ADA, 0xF37C, + 0x9ADB, 0xF37D, 0x9ADC, 0xF37E, 0x9ADD, 0xF380, 0x9ADE, 0xF381, 0x9ADF, 0xF7D4, 0x9AE0, 0xF382, 0x9AE1, 0xF7D5, 0x9AE2, 0xF383, + 0x9AE3, 0xF384, 0x9AE4, 0xF385, 0x9AE5, 0xF386, 0x9AE6, 0xF7D6, 0x9AE7, 0xF387, 0x9AE8, 0xF388, 0x9AE9, 0xF389, 0x9AEA, 0xF38A, + 0x9AEB, 0xF7D8, 0x9AEC, 0xF38B, 0x9AED, 0xF7DA, 0x9AEE, 0xF38C, 0x9AEF, 0xF7D7, 0x9AF0, 0xF38D, 0x9AF1, 0xF38E, 0x9AF2, 0xF38F, + 0x9AF3, 0xF390, 0x9AF4, 0xF391, 0x9AF5, 0xF392, 0x9AF6, 0xF393, 0x9AF7, 0xF394, 0x9AF8, 0xF395, 0x9AF9, 0xF7DB, 0x9AFA, 0xF396, + 0x9AFB, 0xF7D9, 0x9AFC, 0xF397, 0x9AFD, 0xF398, 0x9AFE, 0xF399, 0x9AFF, 0xF39A, 0x9B00, 0xF39B, 0x9B01, 0xF39C, 0x9B02, 0xF39D, + 0x9B03, 0xD7D7, 0x9B04, 0xF39E, 0x9B05, 0xF39F, 0x9B06, 0xF3A0, 0x9B07, 0xF440, 0x9B08, 0xF7DC, 0x9B09, 0xF441, 0x9B0A, 0xF442, + 0x9B0B, 0xF443, 0x9B0C, 0xF444, 0x9B0D, 0xF445, 0x9B0E, 0xF446, 0x9B0F, 0xF7DD, 0x9B10, 0xF447, 0x9B11, 0xF448, 0x9B12, 0xF449, + 0x9B13, 0xF7DE, 0x9B14, 0xF44A, 0x9B15, 0xF44B, 0x9B16, 0xF44C, 0x9B17, 0xF44D, 0x9B18, 0xF44E, 0x9B19, 0xF44F, 0x9B1A, 0xF450, + 0x9B1B, 0xF451, 0x9B1C, 0xF452, 0x9B1D, 0xF453, 0x9B1E, 0xF454, 0x9B1F, 0xF7DF, 0x9B20, 0xF455, 0x9B21, 0xF456, 0x9B22, 0xF457, + 0x9B23, 0xF7E0, 0x9B24, 0xF458, 0x9B25, 0xF459, 0x9B26, 0xF45A, 0x9B27, 0xF45B, 0x9B28, 0xF45C, 0x9B29, 0xF45D, 0x9B2A, 0xF45E, + 0x9B2B, 0xF45F, 0x9B2C, 0xF460, 0x9B2D, 0xF461, 0x9B2E, 0xF462, 0x9B2F, 0xDBCB, 0x9B30, 0xF463, 0x9B31, 0xF464, 0x9B32, 0xD8AA, + 0x9B33, 0xF465, 0x9B34, 0xF466, 0x9B35, 0xF467, 0x9B36, 0xF468, 0x9B37, 0xF469, 0x9B38, 0xF46A, 0x9B39, 0xF46B, 0x9B3A, 0xF46C, + 0x9B3B, 0xE5F7, 0x9B3C, 0xB9ED, 0x9B3D, 0xF46D, 0x9B3E, 0xF46E, 0x9B3F, 0xF46F, 0x9B40, 0xF470, 0x9B41, 0xBFFD, 0x9B42, 0xBBEA, + 0x9B43, 0xF7C9, 0x9B44, 0xC6C7, 0x9B45, 0xF7C8, 0x9B46, 0xF471, 0x9B47, 0xF7CA, 0x9B48, 0xF7CC, 0x9B49, 0xF7CB, 0x9B4A, 0xF472, + 0x9B4B, 0xF473, 0x9B4C, 0xF474, 0x9B4D, 0xF7CD, 0x9B4E, 0xF475, 0x9B4F, 0xCEBA, 0x9B50, 0xF476, 0x9B51, 0xF7CE, 0x9B52, 0xF477, + 0x9B53, 0xF478, 0x9B54, 0xC4A7, 0x9B55, 0xF479, 0x9B56, 0xF47A, 0x9B57, 0xF47B, 0x9B58, 0xF47C, 0x9B59, 0xF47D, 0x9B5A, 0xF47E, + 0x9B5B, 0xF480, 0x9B5C, 0xF481, 0x9B5D, 0xF482, 0x9B5E, 0xF483, 0x9B5F, 0xF484, 0x9B60, 0xF485, 0x9B61, 0xF486, 0x9B62, 0xF487, + 0x9B63, 0xF488, 0x9B64, 0xF489, 0x9B65, 0xF48A, 0x9B66, 0xF48B, 0x9B67, 0xF48C, 0x9B68, 0xF48D, 0x9B69, 0xF48E, 0x9B6A, 0xF48F, + 0x9B6B, 0xF490, 0x9B6C, 0xF491, 0x9B6D, 0xF492, 0x9B6E, 0xF493, 0x9B6F, 0xF494, 0x9B70, 0xF495, 0x9B71, 0xF496, 0x9B72, 0xF497, + 0x9B73, 0xF498, 0x9B74, 0xF499, 0x9B75, 0xF49A, 0x9B76, 0xF49B, 0x9B77, 0xF49C, 0x9B78, 0xF49D, 0x9B79, 0xF49E, 0x9B7A, 0xF49F, + 0x9B7B, 0xF4A0, 0x9B7C, 0xF540, 0x9B7D, 0xF541, 0x9B7E, 0xF542, 0x9B7F, 0xF543, 0x9B80, 0xF544, 0x9B81, 0xF545, 0x9B82, 0xF546, + 0x9B83, 0xF547, 0x9B84, 0xF548, 0x9B85, 0xF549, 0x9B86, 0xF54A, 0x9B87, 0xF54B, 0x9B88, 0xF54C, 0x9B89, 0xF54D, 0x9B8A, 0xF54E, + 0x9B8B, 0xF54F, 0x9B8C, 0xF550, 0x9B8D, 0xF551, 0x9B8E, 0xF552, 0x9B8F, 0xF553, 0x9B90, 0xF554, 0x9B91, 0xF555, 0x9B92, 0xF556, + 0x9B93, 0xF557, 0x9B94, 0xF558, 0x9B95, 0xF559, 0x9B96, 0xF55A, 0x9B97, 0xF55B, 0x9B98, 0xF55C, 0x9B99, 0xF55D, 0x9B9A, 0xF55E, + 0x9B9B, 0xF55F, 0x9B9C, 0xF560, 0x9B9D, 0xF561, 0x9B9E, 0xF562, 0x9B9F, 0xF563, 0x9BA0, 0xF564, 0x9BA1, 0xF565, 0x9BA2, 0xF566, + 0x9BA3, 0xF567, 0x9BA4, 0xF568, 0x9BA5, 0xF569, 0x9BA6, 0xF56A, 0x9BA7, 0xF56B, 0x9BA8, 0xF56C, 0x9BA9, 0xF56D, 0x9BAA, 0xF56E, + 0x9BAB, 0xF56F, 0x9BAC, 0xF570, 0x9BAD, 0xF571, 0x9BAE, 0xF572, 0x9BAF, 0xF573, 0x9BB0, 0xF574, 0x9BB1, 0xF575, 0x9BB2, 0xF576, + 0x9BB3, 0xF577, 0x9BB4, 0xF578, 0x9BB5, 0xF579, 0x9BB6, 0xF57A, 0x9BB7, 0xF57B, 0x9BB8, 0xF57C, 0x9BB9, 0xF57D, 0x9BBA, 0xF57E, + 0x9BBB, 0xF580, 0x9BBC, 0xF581, 0x9BBD, 0xF582, 0x9BBE, 0xF583, 0x9BBF, 0xF584, 0x9BC0, 0xF585, 0x9BC1, 0xF586, 0x9BC2, 0xF587, + 0x9BC3, 0xF588, 0x9BC4, 0xF589, 0x9BC5, 0xF58A, 0x9BC6, 0xF58B, 0x9BC7, 0xF58C, 0x9BC8, 0xF58D, 0x9BC9, 0xF58E, 0x9BCA, 0xF58F, + 0x9BCB, 0xF590, 0x9BCC, 0xF591, 0x9BCD, 0xF592, 0x9BCE, 0xF593, 0x9BCF, 0xF594, 0x9BD0, 0xF595, 0x9BD1, 0xF596, 0x9BD2, 0xF597, + 0x9BD3, 0xF598, 0x9BD4, 0xF599, 0x9BD5, 0xF59A, 0x9BD6, 0xF59B, 0x9BD7, 0xF59C, 0x9BD8, 0xF59D, 0x9BD9, 0xF59E, 0x9BDA, 0xF59F, + 0x9BDB, 0xF5A0, 0x9BDC, 0xF640, 0x9BDD, 0xF641, 0x9BDE, 0xF642, 0x9BDF, 0xF643, 0x9BE0, 0xF644, 0x9BE1, 0xF645, 0x9BE2, 0xF646, + 0x9BE3, 0xF647, 0x9BE4, 0xF648, 0x9BE5, 0xF649, 0x9BE6, 0xF64A, 0x9BE7, 0xF64B, 0x9BE8, 0xF64C, 0x9BE9, 0xF64D, 0x9BEA, 0xF64E, + 0x9BEB, 0xF64F, 0x9BEC, 0xF650, 0x9BED, 0xF651, 0x9BEE, 0xF652, 0x9BEF, 0xF653, 0x9BF0, 0xF654, 0x9BF1, 0xF655, 0x9BF2, 0xF656, + 0x9BF3, 0xF657, 0x9BF4, 0xF658, 0x9BF5, 0xF659, 0x9BF6, 0xF65A, 0x9BF7, 0xF65B, 0x9BF8, 0xF65C, 0x9BF9, 0xF65D, 0x9BFA, 0xF65E, + 0x9BFB, 0xF65F, 0x9BFC, 0xF660, 0x9BFD, 0xF661, 0x9BFE, 0xF662, 0x9BFF, 0xF663, 0x9C00, 0xF664, 0x9C01, 0xF665, 0x9C02, 0xF666, + 0x9C03, 0xF667, 0x9C04, 0xF668, 0x9C05, 0xF669, 0x9C06, 0xF66A, 0x9C07, 0xF66B, 0x9C08, 0xF66C, 0x9C09, 0xF66D, 0x9C0A, 0xF66E, + 0x9C0B, 0xF66F, 0x9C0C, 0xF670, 0x9C0D, 0xF671, 0x9C0E, 0xF672, 0x9C0F, 0xF673, 0x9C10, 0xF674, 0x9C11, 0xF675, 0x9C12, 0xF676, + 0x9C13, 0xF677, 0x9C14, 0xF678, 0x9C15, 0xF679, 0x9C16, 0xF67A, 0x9C17, 0xF67B, 0x9C18, 0xF67C, 0x9C19, 0xF67D, 0x9C1A, 0xF67E, + 0x9C1B, 0xF680, 0x9C1C, 0xF681, 0x9C1D, 0xF682, 0x9C1E, 0xF683, 0x9C1F, 0xF684, 0x9C20, 0xF685, 0x9C21, 0xF686, 0x9C22, 0xF687, + 0x9C23, 0xF688, 0x9C24, 0xF689, 0x9C25, 0xF68A, 0x9C26, 0xF68B, 0x9C27, 0xF68C, 0x9C28, 0xF68D, 0x9C29, 0xF68E, 0x9C2A, 0xF68F, + 0x9C2B, 0xF690, 0x9C2C, 0xF691, 0x9C2D, 0xF692, 0x9C2E, 0xF693, 0x9C2F, 0xF694, 0x9C30, 0xF695, 0x9C31, 0xF696, 0x9C32, 0xF697, + 0x9C33, 0xF698, 0x9C34, 0xF699, 0x9C35, 0xF69A, 0x9C36, 0xF69B, 0x9C37, 0xF69C, 0x9C38, 0xF69D, 0x9C39, 0xF69E, 0x9C3A, 0xF69F, + 0x9C3B, 0xF6A0, 0x9C3C, 0xF740, 0x9C3D, 0xF741, 0x9C3E, 0xF742, 0x9C3F, 0xF743, 0x9C40, 0xF744, 0x9C41, 0xF745, 0x9C42, 0xF746, + 0x9C43, 0xF747, 0x9C44, 0xF748, 0x9C45, 0xF749, 0x9C46, 0xF74A, 0x9C47, 0xF74B, 0x9C48, 0xF74C, 0x9C49, 0xF74D, 0x9C4A, 0xF74E, + 0x9C4B, 0xF74F, 0x9C4C, 0xF750, 0x9C4D, 0xF751, 0x9C4E, 0xF752, 0x9C4F, 0xF753, 0x9C50, 0xF754, 0x9C51, 0xF755, 0x9C52, 0xF756, + 0x9C53, 0xF757, 0x9C54, 0xF758, 0x9C55, 0xF759, 0x9C56, 0xF75A, 0x9C57, 0xF75B, 0x9C58, 0xF75C, 0x9C59, 0xF75D, 0x9C5A, 0xF75E, + 0x9C5B, 0xF75F, 0x9C5C, 0xF760, 0x9C5D, 0xF761, 0x9C5E, 0xF762, 0x9C5F, 0xF763, 0x9C60, 0xF764, 0x9C61, 0xF765, 0x9C62, 0xF766, + 0x9C63, 0xF767, 0x9C64, 0xF768, 0x9C65, 0xF769, 0x9C66, 0xF76A, 0x9C67, 0xF76B, 0x9C68, 0xF76C, 0x9C69, 0xF76D, 0x9C6A, 0xF76E, + 0x9C6B, 0xF76F, 0x9C6C, 0xF770, 0x9C6D, 0xF771, 0x9C6E, 0xF772, 0x9C6F, 0xF773, 0x9C70, 0xF774, 0x9C71, 0xF775, 0x9C72, 0xF776, + 0x9C73, 0xF777, 0x9C74, 0xF778, 0x9C75, 0xF779, 0x9C76, 0xF77A, 0x9C77, 0xF77B, 0x9C78, 0xF77C, 0x9C79, 0xF77D, 0x9C7A, 0xF77E, + 0x9C7B, 0xF780, 0x9C7C, 0xD3E3, 0x9C7D, 0xF781, 0x9C7E, 0xF782, 0x9C7F, 0xF6CF, 0x9C80, 0xF783, 0x9C81, 0xC2B3, 0x9C82, 0xF6D0, + 0x9C83, 0xF784, 0x9C84, 0xF785, 0x9C85, 0xF6D1, 0x9C86, 0xF6D2, 0x9C87, 0xF6D3, 0x9C88, 0xF6D4, 0x9C89, 0xF786, 0x9C8A, 0xF787, + 0x9C8B, 0xF6D6, 0x9C8C, 0xF788, 0x9C8D, 0xB1AB, 0x9C8E, 0xF6D7, 0x9C8F, 0xF789, 0x9C90, 0xF6D8, 0x9C91, 0xF6D9, 0x9C92, 0xF6DA, + 0x9C93, 0xF78A, 0x9C94, 0xF6DB, 0x9C95, 0xF6DC, 0x9C96, 0xF78B, 0x9C97, 0xF78C, 0x9C98, 0xF78D, 0x9C99, 0xF78E, 0x9C9A, 0xF6DD, + 0x9C9B, 0xF6DE, 0x9C9C, 0xCFCA, 0x9C9D, 0xF78F, 0x9C9E, 0xF6DF, 0x9C9F, 0xF6E0, 0x9CA0, 0xF6E1, 0x9CA1, 0xF6E2, 0x9CA2, 0xF6E3, + 0x9CA3, 0xF6E4, 0x9CA4, 0xC0F0, 0x9CA5, 0xF6E5, 0x9CA6, 0xF6E6, 0x9CA7, 0xF6E7, 0x9CA8, 0xF6E8, 0x9CA9, 0xF6E9, 0x9CAA, 0xF790, + 0x9CAB, 0xF6EA, 0x9CAC, 0xF791, 0x9CAD, 0xF6EB, 0x9CAE, 0xF6EC, 0x9CAF, 0xF792, 0x9CB0, 0xF6ED, 0x9CB1, 0xF6EE, 0x9CB2, 0xF6EF, + 0x9CB3, 0xF6F0, 0x9CB4, 0xF6F1, 0x9CB5, 0xF6F2, 0x9CB6, 0xF6F3, 0x9CB7, 0xF6F4, 0x9CB8, 0xBEA8, 0x9CB9, 0xF793, 0x9CBA, 0xF6F5, + 0x9CBB, 0xF6F6, 0x9CBC, 0xF6F7, 0x9CBD, 0xF6F8, 0x9CBE, 0xF794, 0x9CBF, 0xF795, 0x9CC0, 0xF796, 0x9CC1, 0xF797, 0x9CC2, 0xF798, + 0x9CC3, 0xC8FA, 0x9CC4, 0xF6F9, 0x9CC5, 0xF6FA, 0x9CC6, 0xF6FB, 0x9CC7, 0xF6FC, 0x9CC8, 0xF799, 0x9CC9, 0xF79A, 0x9CCA, 0xF6FD, + 0x9CCB, 0xF6FE, 0x9CCC, 0xF7A1, 0x9CCD, 0xF7A2, 0x9CCE, 0xF7A3, 0x9CCF, 0xF7A4, 0x9CD0, 0xF7A5, 0x9CD1, 0xF79B, 0x9CD2, 0xF79C, + 0x9CD3, 0xF7A6, 0x9CD4, 0xF7A7, 0x9CD5, 0xF7A8, 0x9CD6, 0xB1EE, 0x9CD7, 0xF7A9, 0x9CD8, 0xF7AA, 0x9CD9, 0xF7AB, 0x9CDA, 0xF79D, + 0x9CDB, 0xF79E, 0x9CDC, 0xF7AC, 0x9CDD, 0xF7AD, 0x9CDE, 0xC1DB, 0x9CDF, 0xF7AE, 0x9CE0, 0xF79F, 0x9CE1, 0xF7A0, 0x9CE2, 0xF7AF, + 0x9CE3, 0xF840, 0x9CE4, 0xF841, 0x9CE5, 0xF842, 0x9CE6, 0xF843, 0x9CE7, 0xF844, 0x9CE8, 0xF845, 0x9CE9, 0xF846, 0x9CEA, 0xF847, + 0x9CEB, 0xF848, 0x9CEC, 0xF849, 0x9CED, 0xF84A, 0x9CEE, 0xF84B, 0x9CEF, 0xF84C, 0x9CF0, 0xF84D, 0x9CF1, 0xF84E, 0x9CF2, 0xF84F, + 0x9CF3, 0xF850, 0x9CF4, 0xF851, 0x9CF5, 0xF852, 0x9CF6, 0xF853, 0x9CF7, 0xF854, 0x9CF8, 0xF855, 0x9CF9, 0xF856, 0x9CFA, 0xF857, + 0x9CFB, 0xF858, 0x9CFC, 0xF859, 0x9CFD, 0xF85A, 0x9CFE, 0xF85B, 0x9CFF, 0xF85C, 0x9D00, 0xF85D, 0x9D01, 0xF85E, 0x9D02, 0xF85F, + 0x9D03, 0xF860, 0x9D04, 0xF861, 0x9D05, 0xF862, 0x9D06, 0xF863, 0x9D07, 0xF864, 0x9D08, 0xF865, 0x9D09, 0xF866, 0x9D0A, 0xF867, + 0x9D0B, 0xF868, 0x9D0C, 0xF869, 0x9D0D, 0xF86A, 0x9D0E, 0xF86B, 0x9D0F, 0xF86C, 0x9D10, 0xF86D, 0x9D11, 0xF86E, 0x9D12, 0xF86F, + 0x9D13, 0xF870, 0x9D14, 0xF871, 0x9D15, 0xF872, 0x9D16, 0xF873, 0x9D17, 0xF874, 0x9D18, 0xF875, 0x9D19, 0xF876, 0x9D1A, 0xF877, + 0x9D1B, 0xF878, 0x9D1C, 0xF879, 0x9D1D, 0xF87A, 0x9D1E, 0xF87B, 0x9D1F, 0xF87C, 0x9D20, 0xF87D, 0x9D21, 0xF87E, 0x9D22, 0xF880, + 0x9D23, 0xF881, 0x9D24, 0xF882, 0x9D25, 0xF883, 0x9D26, 0xF884, 0x9D27, 0xF885, 0x9D28, 0xF886, 0x9D29, 0xF887, 0x9D2A, 0xF888, + 0x9D2B, 0xF889, 0x9D2C, 0xF88A, 0x9D2D, 0xF88B, 0x9D2E, 0xF88C, 0x9D2F, 0xF88D, 0x9D30, 0xF88E, 0x9D31, 0xF88F, 0x9D32, 0xF890, + 0x9D33, 0xF891, 0x9D34, 0xF892, 0x9D35, 0xF893, 0x9D36, 0xF894, 0x9D37, 0xF895, 0x9D38, 0xF896, 0x9D39, 0xF897, 0x9D3A, 0xF898, + 0x9D3B, 0xF899, 0x9D3C, 0xF89A, 0x9D3D, 0xF89B, 0x9D3E, 0xF89C, 0x9D3F, 0xF89D, 0x9D40, 0xF89E, 0x9D41, 0xF89F, 0x9D42, 0xF8A0, + 0x9D43, 0xF940, 0x9D44, 0xF941, 0x9D45, 0xF942, 0x9D46, 0xF943, 0x9D47, 0xF944, 0x9D48, 0xF945, 0x9D49, 0xF946, 0x9D4A, 0xF947, + 0x9D4B, 0xF948, 0x9D4C, 0xF949, 0x9D4D, 0xF94A, 0x9D4E, 0xF94B, 0x9D4F, 0xF94C, 0x9D50, 0xF94D, 0x9D51, 0xF94E, 0x9D52, 0xF94F, + 0x9D53, 0xF950, 0x9D54, 0xF951, 0x9D55, 0xF952, 0x9D56, 0xF953, 0x9D57, 0xF954, 0x9D58, 0xF955, 0x9D59, 0xF956, 0x9D5A, 0xF957, + 0x9D5B, 0xF958, 0x9D5C, 0xF959, 0x9D5D, 0xF95A, 0x9D5E, 0xF95B, 0x9D5F, 0xF95C, 0x9D60, 0xF95D, 0x9D61, 0xF95E, 0x9D62, 0xF95F, + 0x9D63, 0xF960, 0x9D64, 0xF961, 0x9D65, 0xF962, 0x9D66, 0xF963, 0x9D67, 0xF964, 0x9D68, 0xF965, 0x9D69, 0xF966, 0x9D6A, 0xF967, + 0x9D6B, 0xF968, 0x9D6C, 0xF969, 0x9D6D, 0xF96A, 0x9D6E, 0xF96B, 0x9D6F, 0xF96C, 0x9D70, 0xF96D, 0x9D71, 0xF96E, 0x9D72, 0xF96F, + 0x9D73, 0xF970, 0x9D74, 0xF971, 0x9D75, 0xF972, 0x9D76, 0xF973, 0x9D77, 0xF974, 0x9D78, 0xF975, 0x9D79, 0xF976, 0x9D7A, 0xF977, + 0x9D7B, 0xF978, 0x9D7C, 0xF979, 0x9D7D, 0xF97A, 0x9D7E, 0xF97B, 0x9D7F, 0xF97C, 0x9D80, 0xF97D, 0x9D81, 0xF97E, 0x9D82, 0xF980, + 0x9D83, 0xF981, 0x9D84, 0xF982, 0x9D85, 0xF983, 0x9D86, 0xF984, 0x9D87, 0xF985, 0x9D88, 0xF986, 0x9D89, 0xF987, 0x9D8A, 0xF988, + 0x9D8B, 0xF989, 0x9D8C, 0xF98A, 0x9D8D, 0xF98B, 0x9D8E, 0xF98C, 0x9D8F, 0xF98D, 0x9D90, 0xF98E, 0x9D91, 0xF98F, 0x9D92, 0xF990, + 0x9D93, 0xF991, 0x9D94, 0xF992, 0x9D95, 0xF993, 0x9D96, 0xF994, 0x9D97, 0xF995, 0x9D98, 0xF996, 0x9D99, 0xF997, 0x9D9A, 0xF998, + 0x9D9B, 0xF999, 0x9D9C, 0xF99A, 0x9D9D, 0xF99B, 0x9D9E, 0xF99C, 0x9D9F, 0xF99D, 0x9DA0, 0xF99E, 0x9DA1, 0xF99F, 0x9DA2, 0xF9A0, + 0x9DA3, 0xFA40, 0x9DA4, 0xFA41, 0x9DA5, 0xFA42, 0x9DA6, 0xFA43, 0x9DA7, 0xFA44, 0x9DA8, 0xFA45, 0x9DA9, 0xFA46, 0x9DAA, 0xFA47, + 0x9DAB, 0xFA48, 0x9DAC, 0xFA49, 0x9DAD, 0xFA4A, 0x9DAE, 0xFA4B, 0x9DAF, 0xFA4C, 0x9DB0, 0xFA4D, 0x9DB1, 0xFA4E, 0x9DB2, 0xFA4F, + 0x9DB3, 0xFA50, 0x9DB4, 0xFA51, 0x9DB5, 0xFA52, 0x9DB6, 0xFA53, 0x9DB7, 0xFA54, 0x9DB8, 0xFA55, 0x9DB9, 0xFA56, 0x9DBA, 0xFA57, + 0x9DBB, 0xFA58, 0x9DBC, 0xFA59, 0x9DBD, 0xFA5A, 0x9DBE, 0xFA5B, 0x9DBF, 0xFA5C, 0x9DC0, 0xFA5D, 0x9DC1, 0xFA5E, 0x9DC2, 0xFA5F, + 0x9DC3, 0xFA60, 0x9DC4, 0xFA61, 0x9DC5, 0xFA62, 0x9DC6, 0xFA63, 0x9DC7, 0xFA64, 0x9DC8, 0xFA65, 0x9DC9, 0xFA66, 0x9DCA, 0xFA67, + 0x9DCB, 0xFA68, 0x9DCC, 0xFA69, 0x9DCD, 0xFA6A, 0x9DCE, 0xFA6B, 0x9DCF, 0xFA6C, 0x9DD0, 0xFA6D, 0x9DD1, 0xFA6E, 0x9DD2, 0xFA6F, + 0x9DD3, 0xFA70, 0x9DD4, 0xFA71, 0x9DD5, 0xFA72, 0x9DD6, 0xFA73, 0x9DD7, 0xFA74, 0x9DD8, 0xFA75, 0x9DD9, 0xFA76, 0x9DDA, 0xFA77, + 0x9DDB, 0xFA78, 0x9DDC, 0xFA79, 0x9DDD, 0xFA7A, 0x9DDE, 0xFA7B, 0x9DDF, 0xFA7C, 0x9DE0, 0xFA7D, 0x9DE1, 0xFA7E, 0x9DE2, 0xFA80, + 0x9DE3, 0xFA81, 0x9DE4, 0xFA82, 0x9DE5, 0xFA83, 0x9DE6, 0xFA84, 0x9DE7, 0xFA85, 0x9DE8, 0xFA86, 0x9DE9, 0xFA87, 0x9DEA, 0xFA88, + 0x9DEB, 0xFA89, 0x9DEC, 0xFA8A, 0x9DED, 0xFA8B, 0x9DEE, 0xFA8C, 0x9DEF, 0xFA8D, 0x9DF0, 0xFA8E, 0x9DF1, 0xFA8F, 0x9DF2, 0xFA90, + 0x9DF3, 0xFA91, 0x9DF4, 0xFA92, 0x9DF5, 0xFA93, 0x9DF6, 0xFA94, 0x9DF7, 0xFA95, 0x9DF8, 0xFA96, 0x9DF9, 0xFA97, 0x9DFA, 0xFA98, + 0x9DFB, 0xFA99, 0x9DFC, 0xFA9A, 0x9DFD, 0xFA9B, 0x9DFE, 0xFA9C, 0x9DFF, 0xFA9D, 0x9E00, 0xFA9E, 0x9E01, 0xFA9F, 0x9E02, 0xFAA0, + 0x9E03, 0xFB40, 0x9E04, 0xFB41, 0x9E05, 0xFB42, 0x9E06, 0xFB43, 0x9E07, 0xFB44, 0x9E08, 0xFB45, 0x9E09, 0xFB46, 0x9E0A, 0xFB47, + 0x9E0B, 0xFB48, 0x9E0C, 0xFB49, 0x9E0D, 0xFB4A, 0x9E0E, 0xFB4B, 0x9E0F, 0xFB4C, 0x9E10, 0xFB4D, 0x9E11, 0xFB4E, 0x9E12, 0xFB4F, + 0x9E13, 0xFB50, 0x9E14, 0xFB51, 0x9E15, 0xFB52, 0x9E16, 0xFB53, 0x9E17, 0xFB54, 0x9E18, 0xFB55, 0x9E19, 0xFB56, 0x9E1A, 0xFB57, + 0x9E1B, 0xFB58, 0x9E1C, 0xFB59, 0x9E1D, 0xFB5A, 0x9E1E, 0xFB5B, 0x9E1F, 0xC4F1, 0x9E20, 0xF0AF, 0x9E21, 0xBCA6, 0x9E22, 0xF0B0, + 0x9E23, 0xC3F9, 0x9E24, 0xFB5C, 0x9E25, 0xC5B8, 0x9E26, 0xD1BB, 0x9E27, 0xFB5D, 0x9E28, 0xF0B1, 0x9E29, 0xF0B2, 0x9E2A, 0xF0B3, + 0x9E2B, 0xF0B4, 0x9E2C, 0xF0B5, 0x9E2D, 0xD1BC, 0x9E2E, 0xFB5E, 0x9E2F, 0xD1EC, 0x9E30, 0xFB5F, 0x9E31, 0xF0B7, 0x9E32, 0xF0B6, + 0x9E33, 0xD4A7, 0x9E34, 0xFB60, 0x9E35, 0xCDD2, 0x9E36, 0xF0B8, 0x9E37, 0xF0BA, 0x9E38, 0xF0B9, 0x9E39, 0xF0BB, 0x9E3A, 0xF0BC, + 0x9E3B, 0xFB61, 0x9E3C, 0xFB62, 0x9E3D, 0xB8EB, 0x9E3E, 0xF0BD, 0x9E3F, 0xBAE8, 0x9E40, 0xFB63, 0x9E41, 0xF0BE, 0x9E42, 0xF0BF, + 0x9E43, 0xBEE9, 0x9E44, 0xF0C0, 0x9E45, 0xB6EC, 0x9E46, 0xF0C1, 0x9E47, 0xF0C2, 0x9E48, 0xF0C3, 0x9E49, 0xF0C4, 0x9E4A, 0xC8B5, + 0x9E4B, 0xF0C5, 0x9E4C, 0xF0C6, 0x9E4D, 0xFB64, 0x9E4E, 0xF0C7, 0x9E4F, 0xC5F4, 0x9E50, 0xFB65, 0x9E51, 0xF0C8, 0x9E52, 0xFB66, + 0x9E53, 0xFB67, 0x9E54, 0xFB68, 0x9E55, 0xF0C9, 0x9E56, 0xFB69, 0x9E57, 0xF0CA, 0x9E58, 0xF7BD, 0x9E59, 0xFB6A, 0x9E5A, 0xF0CB, + 0x9E5B, 0xF0CC, 0x9E5C, 0xF0CD, 0x9E5D, 0xFB6B, 0x9E5E, 0xF0CE, 0x9E5F, 0xFB6C, 0x9E60, 0xFB6D, 0x9E61, 0xFB6E, 0x9E62, 0xFB6F, + 0x9E63, 0xF0CF, 0x9E64, 0xBAD7, 0x9E65, 0xFB70, 0x9E66, 0xF0D0, 0x9E67, 0xF0D1, 0x9E68, 0xF0D2, 0x9E69, 0xF0D3, 0x9E6A, 0xF0D4, + 0x9E6B, 0xF0D5, 0x9E6C, 0xF0D6, 0x9E6D, 0xF0D8, 0x9E6E, 0xFB71, 0x9E6F, 0xFB72, 0x9E70, 0xD3A5, 0x9E71, 0xF0D7, 0x9E72, 0xFB73, + 0x9E73, 0xF0D9, 0x9E74, 0xFB74, 0x9E75, 0xFB75, 0x9E76, 0xFB76, 0x9E77, 0xFB77, 0x9E78, 0xFB78, 0x9E79, 0xFB79, 0x9E7A, 0xFB7A, + 0x9E7B, 0xFB7B, 0x9E7C, 0xFB7C, 0x9E7D, 0xFB7D, 0x9E7E, 0xF5BA, 0x9E7F, 0xC2B9, 0x9E80, 0xFB7E, 0x9E81, 0xFB80, 0x9E82, 0xF7E4, + 0x9E83, 0xFB81, 0x9E84, 0xFB82, 0x9E85, 0xFB83, 0x9E86, 0xFB84, 0x9E87, 0xF7E5, 0x9E88, 0xF7E6, 0x9E89, 0xFB85, 0x9E8A, 0xFB86, + 0x9E8B, 0xF7E7, 0x9E8C, 0xFB87, 0x9E8D, 0xFB88, 0x9E8E, 0xFB89, 0x9E8F, 0xFB8A, 0x9E90, 0xFB8B, 0x9E91, 0xFB8C, 0x9E92, 0xF7E8, + 0x9E93, 0xC2B4, 0x9E94, 0xFB8D, 0x9E95, 0xFB8E, 0x9E96, 0xFB8F, 0x9E97, 0xFB90, 0x9E98, 0xFB91, 0x9E99, 0xFB92, 0x9E9A, 0xFB93, + 0x9E9B, 0xFB94, 0x9E9C, 0xFB95, 0x9E9D, 0xF7EA, 0x9E9E, 0xFB96, 0x9E9F, 0xF7EB, 0x9EA0, 0xFB97, 0x9EA1, 0xFB98, 0x9EA2, 0xFB99, + 0x9EA3, 0xFB9A, 0x9EA4, 0xFB9B, 0x9EA5, 0xFB9C, 0x9EA6, 0xC2F3, 0x9EA7, 0xFB9D, 0x9EA8, 0xFB9E, 0x9EA9, 0xFB9F, 0x9EAA, 0xFBA0, + 0x9EAB, 0xFC40, 0x9EAC, 0xFC41, 0x9EAD, 0xFC42, 0x9EAE, 0xFC43, 0x9EAF, 0xFC44, 0x9EB0, 0xFC45, 0x9EB1, 0xFC46, 0x9EB2, 0xFC47, + 0x9EB3, 0xFC48, 0x9EB4, 0xF4F0, 0x9EB5, 0xFC49, 0x9EB6, 0xFC4A, 0x9EB7, 0xFC4B, 0x9EB8, 0xF4EF, 0x9EB9, 0xFC4C, 0x9EBA, 0xFC4D, + 0x9EBB, 0xC2E9, 0x9EBC, 0xFC4E, 0x9EBD, 0xF7E1, 0x9EBE, 0xF7E2, 0x9EBF, 0xFC4F, 0x9EC0, 0xFC50, 0x9EC1, 0xFC51, 0x9EC2, 0xFC52, + 0x9EC3, 0xFC53, 0x9EC4, 0xBBC6, 0x9EC5, 0xFC54, 0x9EC6, 0xFC55, 0x9EC7, 0xFC56, 0x9EC8, 0xFC57, 0x9EC9, 0xD9E4, 0x9ECA, 0xFC58, + 0x9ECB, 0xFC59, 0x9ECC, 0xFC5A, 0x9ECD, 0xCAF2, 0x9ECE, 0xC0E8, 0x9ECF, 0xF0A4, 0x9ED0, 0xFC5B, 0x9ED1, 0xBADA, 0x9ED2, 0xFC5C, + 0x9ED3, 0xFC5D, 0x9ED4, 0xC7AD, 0x9ED5, 0xFC5E, 0x9ED6, 0xFC5F, 0x9ED7, 0xFC60, 0x9ED8, 0xC4AC, 0x9ED9, 0xFC61, 0x9EDA, 0xFC62, + 0x9EDB, 0xF7EC, 0x9EDC, 0xF7ED, 0x9EDD, 0xF7EE, 0x9EDE, 0xFC63, 0x9EDF, 0xF7F0, 0x9EE0, 0xF7EF, 0x9EE1, 0xFC64, 0x9EE2, 0xF7F1, + 0x9EE3, 0xFC65, 0x9EE4, 0xFC66, 0x9EE5, 0xF7F4, 0x9EE6, 0xFC67, 0x9EE7, 0xF7F3, 0x9EE8, 0xFC68, 0x9EE9, 0xF7F2, 0x9EEA, 0xF7F5, + 0x9EEB, 0xFC69, 0x9EEC, 0xFC6A, 0x9EED, 0xFC6B, 0x9EEE, 0xFC6C, 0x9EEF, 0xF7F6, 0x9EF0, 0xFC6D, 0x9EF1, 0xFC6E, 0x9EF2, 0xFC6F, + 0x9EF3, 0xFC70, 0x9EF4, 0xFC71, 0x9EF5, 0xFC72, 0x9EF6, 0xFC73, 0x9EF7, 0xFC74, 0x9EF8, 0xFC75, 0x9EF9, 0xEDE9, 0x9EFA, 0xFC76, + 0x9EFB, 0xEDEA, 0x9EFC, 0xEDEB, 0x9EFD, 0xFC77, 0x9EFE, 0xF6BC, 0x9EFF, 0xFC78, 0x9F00, 0xFC79, 0x9F01, 0xFC7A, 0x9F02, 0xFC7B, + 0x9F03, 0xFC7C, 0x9F04, 0xFC7D, 0x9F05, 0xFC7E, 0x9F06, 0xFC80, 0x9F07, 0xFC81, 0x9F08, 0xFC82, 0x9F09, 0xFC83, 0x9F0A, 0xFC84, + 0x9F0B, 0xF6BD, 0x9F0C, 0xFC85, 0x9F0D, 0xF6BE, 0x9F0E, 0xB6A6, 0x9F0F, 0xFC86, 0x9F10, 0xD8BE, 0x9F11, 0xFC87, 0x9F12, 0xFC88, + 0x9F13, 0xB9C4, 0x9F14, 0xFC89, 0x9F15, 0xFC8A, 0x9F16, 0xFC8B, 0x9F17, 0xD8BB, 0x9F18, 0xFC8C, 0x9F19, 0xDCB1, 0x9F1A, 0xFC8D, + 0x9F1B, 0xFC8E, 0x9F1C, 0xFC8F, 0x9F1D, 0xFC90, 0x9F1E, 0xFC91, 0x9F1F, 0xFC92, 0x9F20, 0xCAF3, 0x9F21, 0xFC93, 0x9F22, 0xF7F7, + 0x9F23, 0xFC94, 0x9F24, 0xFC95, 0x9F25, 0xFC96, 0x9F26, 0xFC97, 0x9F27, 0xFC98, 0x9F28, 0xFC99, 0x9F29, 0xFC9A, 0x9F2A, 0xFC9B, + 0x9F2B, 0xFC9C, 0x9F2C, 0xF7F8, 0x9F2D, 0xFC9D, 0x9F2E, 0xFC9E, 0x9F2F, 0xF7F9, 0x9F30, 0xFC9F, 0x9F31, 0xFCA0, 0x9F32, 0xFD40, + 0x9F33, 0xFD41, 0x9F34, 0xFD42, 0x9F35, 0xFD43, 0x9F36, 0xFD44, 0x9F37, 0xF7FB, 0x9F38, 0xFD45, 0x9F39, 0xF7FA, 0x9F3A, 0xFD46, + 0x9F3B, 0xB1C7, 0x9F3C, 0xFD47, 0x9F3D, 0xF7FC, 0x9F3E, 0xF7FD, 0x9F3F, 0xFD48, 0x9F40, 0xFD49, 0x9F41, 0xFD4A, 0x9F42, 0xFD4B, + 0x9F43, 0xFD4C, 0x9F44, 0xF7FE, 0x9F45, 0xFD4D, 0x9F46, 0xFD4E, 0x9F47, 0xFD4F, 0x9F48, 0xFD50, 0x9F49, 0xFD51, 0x9F4A, 0xFD52, + 0x9F4B, 0xFD53, 0x9F4C, 0xFD54, 0x9F4D, 0xFD55, 0x9F4E, 0xFD56, 0x9F4F, 0xFD57, 0x9F50, 0xC6EB, 0x9F51, 0xECB4, 0x9F52, 0xFD58, + 0x9F53, 0xFD59, 0x9F54, 0xFD5A, 0x9F55, 0xFD5B, 0x9F56, 0xFD5C, 0x9F57, 0xFD5D, 0x9F58, 0xFD5E, 0x9F59, 0xFD5F, 0x9F5A, 0xFD60, + 0x9F5B, 0xFD61, 0x9F5C, 0xFD62, 0x9F5D, 0xFD63, 0x9F5E, 0xFD64, 0x9F5F, 0xFD65, 0x9F60, 0xFD66, 0x9F61, 0xFD67, 0x9F62, 0xFD68, + 0x9F63, 0xFD69, 0x9F64, 0xFD6A, 0x9F65, 0xFD6B, 0x9F66, 0xFD6C, 0x9F67, 0xFD6D, 0x9F68, 0xFD6E, 0x9F69, 0xFD6F, 0x9F6A, 0xFD70, + 0x9F6B, 0xFD71, 0x9F6C, 0xFD72, 0x9F6D, 0xFD73, 0x9F6E, 0xFD74, 0x9F6F, 0xFD75, 0x9F70, 0xFD76, 0x9F71, 0xFD77, 0x9F72, 0xFD78, + 0x9F73, 0xFD79, 0x9F74, 0xFD7A, 0x9F75, 0xFD7B, 0x9F76, 0xFD7C, 0x9F77, 0xFD7D, 0x9F78, 0xFD7E, 0x9F79, 0xFD80, 0x9F7A, 0xFD81, + 0x9F7B, 0xFD82, 0x9F7C, 0xFD83, 0x9F7D, 0xFD84, 0x9F7E, 0xFD85, 0x9F7F, 0xB3DD, 0x9F80, 0xF6B3, 0x9F81, 0xFD86, 0x9F82, 0xFD87, + 0x9F83, 0xF6B4, 0x9F84, 0xC1E4, 0x9F85, 0xF6B5, 0x9F86, 0xF6B6, 0x9F87, 0xF6B7, 0x9F88, 0xF6B8, 0x9F89, 0xF6B9, 0x9F8A, 0xF6BA, + 0x9F8B, 0xC8A3, 0x9F8C, 0xF6BB, 0x9F8D, 0xFD88, 0x9F8E, 0xFD89, 0x9F8F, 0xFD8A, 0x9F90, 0xFD8B, 0x9F91, 0xFD8C, 0x9F92, 0xFD8D, + 0x9F93, 0xFD8E, 0x9F94, 0xFD8F, 0x9F95, 0xFD90, 0x9F96, 0xFD91, 0x9F97, 0xFD92, 0x9F98, 0xFD93, 0x9F99, 0xC1FA, 0x9F9A, 0xB9A8, + 0x9F9B, 0xEDE8, 0x9F9C, 0xFD94, 0x9F9D, 0xFD95, 0x9F9E, 0xFD96, 0x9F9F, 0xB9EA, 0x9FA0, 0xD9DF, 0x9FA1, 0xFD97, 0x9FA2, 0xFD98, + 0x9FA3, 0xFD99, 0x9FA4, 0xFD9A, 0x9FA5, 0xFD9B, 0xF92C, 0xFD9C, 0xF979, 0xFD9D, 0xF995, 0xFD9E, 0xF9E7, 0xFD9F, 0xF9F1, 0xFDA0, + 0xFA0C, 0xFE40, 0xFA0D, 0xFE41, 0xFA0E, 0xFE42, 0xFA0F, 0xFE43, 0xFA11, 0xFE44, 0xFA13, 0xFE45, 0xFA14, 0xFE46, 0xFA18, 0xFE47, + 0xFA1F, 0xFE48, 0xFA20, 0xFE49, 0xFA21, 0xFE4A, 0xFA23, 0xFE4B, 0xFA24, 0xFE4C, 0xFA27, 0xFE4D, 0xFA28, 0xFE4E, 0xFA29, 0xFE4F, + 0xFE30, 0xA955, 0xFE31, 0xA6F2, 0xFE33, 0xA6F4, 0xFE34, 0xA6F5, 0xFE35, 0xA6E0, 0xFE36, 0xA6E1, 0xFE37, 0xA6F0, 0xFE38, 0xA6F1, + 0xFE39, 0xA6E2, 0xFE3A, 0xA6E3, 0xFE3B, 0xA6EE, 0xFE3C, 0xA6EF, 0xFE3D, 0xA6E6, 0xFE3E, 0xA6E7, 0xFE3F, 0xA6E4, 0xFE40, 0xA6E5, + 0xFE41, 0xA6E8, 0xFE42, 0xA6E9, 0xFE43, 0xA6EA, 0xFE44, 0xA6EB, 0xFE49, 0xA968, 0xFE4A, 0xA969, 0xFE4B, 0xA96A, 0xFE4C, 0xA96B, + 0xFE4D, 0xA96C, 0xFE4E, 0xA96D, 0xFE4F, 0xA96E, 0xFE50, 0xA96F, 0xFE51, 0xA970, 0xFE52, 0xA971, 0xFE54, 0xA972, 0xFE55, 0xA973, + 0xFE56, 0xA974, 0xFE57, 0xA975, 0xFE59, 0xA976, 0xFE5A, 0xA977, 0xFE5B, 0xA978, 0xFE5C, 0xA979, 0xFE5D, 0xA97A, 0xFE5E, 0xA97B, + 0xFE5F, 0xA97C, 0xFE60, 0xA97D, 0xFE61, 0xA97E, 0xFE62, 0xA980, 0xFE63, 0xA981, 0xFE64, 0xA982, 0xFE65, 0xA983, 0xFE66, 0xA984, + 0xFE68, 0xA985, 0xFE69, 0xA986, 0xFE6A, 0xA987, 0xFE6B, 0xA988, 0xFF01, 0xA3A1, 0xFF02, 0xA3A2, 0xFF03, 0xA3A3, 0xFF04, 0xA1E7, + 0xFF05, 0xA3A5, 0xFF06, 0xA3A6, 0xFF07, 0xA3A7, 0xFF08, 0xA3A8, 0xFF09, 0xA3A9, 0xFF0A, 0xA3AA, 0xFF0B, 0xA3AB, 0xFF0C, 0xA3AC, + 0xFF0D, 0xA3AD, 0xFF0E, 0xA3AE, 0xFF0F, 0xA3AF, 0xFF10, 0xA3B0, 0xFF11, 0xA3B1, 0xFF12, 0xA3B2, 0xFF13, 0xA3B3, 0xFF14, 0xA3B4, + 0xFF15, 0xA3B5, 0xFF16, 0xA3B6, 0xFF17, 0xA3B7, 0xFF18, 0xA3B8, 0xFF19, 0xA3B9, 0xFF1A, 0xA3BA, 0xFF1B, 0xA3BB, 0xFF1C, 0xA3BC, + 0xFF1D, 0xA3BD, 0xFF1E, 0xA3BE, 0xFF1F, 0xA3BF, 0xFF20, 0xA3C0, 0xFF21, 0xA3C1, 0xFF22, 0xA3C2, 0xFF23, 0xA3C3, 0xFF24, 0xA3C4, + 0xFF25, 0xA3C5, 0xFF26, 0xA3C6, 0xFF27, 0xA3C7, 0xFF28, 0xA3C8, 0xFF29, 0xA3C9, 0xFF2A, 0xA3CA, 0xFF2B, 0xA3CB, 0xFF2C, 0xA3CC, + 0xFF2D, 0xA3CD, 0xFF2E, 0xA3CE, 0xFF2F, 0xA3CF, 0xFF30, 0xA3D0, 0xFF31, 0xA3D1, 0xFF32, 0xA3D2, 0xFF33, 0xA3D3, 0xFF34, 0xA3D4, + 0xFF35, 0xA3D5, 0xFF36, 0xA3D6, 0xFF37, 0xA3D7, 0xFF38, 0xA3D8, 0xFF39, 0xA3D9, 0xFF3A, 0xA3DA, 0xFF3B, 0xA3DB, 0xFF3C, 0xA3DC, + 0xFF3D, 0xA3DD, 0xFF3E, 0xA3DE, 0xFF3F, 0xA3DF, 0xFF40, 0xA3E0, 0xFF41, 0xA3E1, 0xFF42, 0xA3E2, 0xFF43, 0xA3E3, 0xFF44, 0xA3E4, + 0xFF45, 0xA3E5, 0xFF46, 0xA3E6, 0xFF47, 0xA3E7, 0xFF48, 0xA3E8, 0xFF49, 0xA3E9, 0xFF4A, 0xA3EA, 0xFF4B, 0xA3EB, 0xFF4C, 0xA3EC, + 0xFF4D, 0xA3ED, 0xFF4E, 0xA3EE, 0xFF4F, 0xA3EF, 0xFF50, 0xA3F0, 0xFF51, 0xA3F1, 0xFF52, 0xA3F2, 0xFF53, 0xA3F3, 0xFF54, 0xA3F4, + 0xFF55, 0xA3F5, 0xFF56, 0xA3F6, 0xFF57, 0xA3F7, 0xFF58, 0xA3F8, 0xFF59, 0xA3F9, 0xFF5A, 0xA3FA, 0xFF5B, 0xA3FB, 0xFF5C, 0xA3FC, + 0xFF5D, 0xA3FD, 0xFF5E, 0xA1AB, 0xFFE0, 0xA1E9, 0xFFE1, 0xA1EA, 0xFFE2, 0xA956, 0xFFE3, 0xA3FE, 0xFFE4, 0xA957, 0xFFE5, 0xA3A4, + 0, 0 +}; + +static +const WCHAR oem2uni936[] = { /* GBK --> Unicode pairs */ + 0x0080, 0x20AC, 0x8140, 0x4E02, 0x8141, 0x4E04, 0x8142, 0x4E05, 0x8143, 0x4E06, 0x8144, 0x4E0F, 0x8145, 0x4E12, 0x8146, 0x4E17, + 0x8147, 0x4E1F, 0x8148, 0x4E20, 0x8149, 0x4E21, 0x814A, 0x4E23, 0x814B, 0x4E26, 0x814C, 0x4E29, 0x814D, 0x4E2E, 0x814E, 0x4E2F, + 0x814F, 0x4E31, 0x8150, 0x4E33, 0x8151, 0x4E35, 0x8152, 0x4E37, 0x8153, 0x4E3C, 0x8154, 0x4E40, 0x8155, 0x4E41, 0x8156, 0x4E42, + 0x8157, 0x4E44, 0x8158, 0x4E46, 0x8159, 0x4E4A, 0x815A, 0x4E51, 0x815B, 0x4E55, 0x815C, 0x4E57, 0x815D, 0x4E5A, 0x815E, 0x4E5B, + 0x815F, 0x4E62, 0x8160, 0x4E63, 0x8161, 0x4E64, 0x8162, 0x4E65, 0x8163, 0x4E67, 0x8164, 0x4E68, 0x8165, 0x4E6A, 0x8166, 0x4E6B, + 0x8167, 0x4E6C, 0x8168, 0x4E6D, 0x8169, 0x4E6E, 0x816A, 0x4E6F, 0x816B, 0x4E72, 0x816C, 0x4E74, 0x816D, 0x4E75, 0x816E, 0x4E76, + 0x816F, 0x4E77, 0x8170, 0x4E78, 0x8171, 0x4E79, 0x8172, 0x4E7A, 0x8173, 0x4E7B, 0x8174, 0x4E7C, 0x8175, 0x4E7D, 0x8176, 0x4E7F, + 0x8177, 0x4E80, 0x8178, 0x4E81, 0x8179, 0x4E82, 0x817A, 0x4E83, 0x817B, 0x4E84, 0x817C, 0x4E85, 0x817D, 0x4E87, 0x817E, 0x4E8A, + 0x8180, 0x4E90, 0x8181, 0x4E96, 0x8182, 0x4E97, 0x8183, 0x4E99, 0x8184, 0x4E9C, 0x8185, 0x4E9D, 0x8186, 0x4E9E, 0x8187, 0x4EA3, + 0x8188, 0x4EAA, 0x8189, 0x4EAF, 0x818A, 0x4EB0, 0x818B, 0x4EB1, 0x818C, 0x4EB4, 0x818D, 0x4EB6, 0x818E, 0x4EB7, 0x818F, 0x4EB8, + 0x8190, 0x4EB9, 0x8191, 0x4EBC, 0x8192, 0x4EBD, 0x8193, 0x4EBE, 0x8194, 0x4EC8, 0x8195, 0x4ECC, 0x8196, 0x4ECF, 0x8197, 0x4ED0, + 0x8198, 0x4ED2, 0x8199, 0x4EDA, 0x819A, 0x4EDB, 0x819B, 0x4EDC, 0x819C, 0x4EE0, 0x819D, 0x4EE2, 0x819E, 0x4EE6, 0x819F, 0x4EE7, + 0x81A0, 0x4EE9, 0x81A1, 0x4EED, 0x81A2, 0x4EEE, 0x81A3, 0x4EEF, 0x81A4, 0x4EF1, 0x81A5, 0x4EF4, 0x81A6, 0x4EF8, 0x81A7, 0x4EF9, + 0x81A8, 0x4EFA, 0x81A9, 0x4EFC, 0x81AA, 0x4EFE, 0x81AB, 0x4F00, 0x81AC, 0x4F02, 0x81AD, 0x4F03, 0x81AE, 0x4F04, 0x81AF, 0x4F05, + 0x81B0, 0x4F06, 0x81B1, 0x4F07, 0x81B2, 0x4F08, 0x81B3, 0x4F0B, 0x81B4, 0x4F0C, 0x81B5, 0x4F12, 0x81B6, 0x4F13, 0x81B7, 0x4F14, + 0x81B8, 0x4F15, 0x81B9, 0x4F16, 0x81BA, 0x4F1C, 0x81BB, 0x4F1D, 0x81BC, 0x4F21, 0x81BD, 0x4F23, 0x81BE, 0x4F28, 0x81BF, 0x4F29, + 0x81C0, 0x4F2C, 0x81C1, 0x4F2D, 0x81C2, 0x4F2E, 0x81C3, 0x4F31, 0x81C4, 0x4F33, 0x81C5, 0x4F35, 0x81C6, 0x4F37, 0x81C7, 0x4F39, + 0x81C8, 0x4F3B, 0x81C9, 0x4F3E, 0x81CA, 0x4F3F, 0x81CB, 0x4F40, 0x81CC, 0x4F41, 0x81CD, 0x4F42, 0x81CE, 0x4F44, 0x81CF, 0x4F45, + 0x81D0, 0x4F47, 0x81D1, 0x4F48, 0x81D2, 0x4F49, 0x81D3, 0x4F4A, 0x81D4, 0x4F4B, 0x81D5, 0x4F4C, 0x81D6, 0x4F52, 0x81D7, 0x4F54, + 0x81D8, 0x4F56, 0x81D9, 0x4F61, 0x81DA, 0x4F62, 0x81DB, 0x4F66, 0x81DC, 0x4F68, 0x81DD, 0x4F6A, 0x81DE, 0x4F6B, 0x81DF, 0x4F6D, + 0x81E0, 0x4F6E, 0x81E1, 0x4F71, 0x81E2, 0x4F72, 0x81E3, 0x4F75, 0x81E4, 0x4F77, 0x81E5, 0x4F78, 0x81E6, 0x4F79, 0x81E7, 0x4F7A, + 0x81E8, 0x4F7D, 0x81E9, 0x4F80, 0x81EA, 0x4F81, 0x81EB, 0x4F82, 0x81EC, 0x4F85, 0x81ED, 0x4F86, 0x81EE, 0x4F87, 0x81EF, 0x4F8A, + 0x81F0, 0x4F8C, 0x81F1, 0x4F8E, 0x81F2, 0x4F90, 0x81F3, 0x4F92, 0x81F4, 0x4F93, 0x81F5, 0x4F95, 0x81F6, 0x4F96, 0x81F7, 0x4F98, + 0x81F8, 0x4F99, 0x81F9, 0x4F9A, 0x81FA, 0x4F9C, 0x81FB, 0x4F9E, 0x81FC, 0x4F9F, 0x81FD, 0x4FA1, 0x81FE, 0x4FA2, 0x8240, 0x4FA4, + 0x8241, 0x4FAB, 0x8242, 0x4FAD, 0x8243, 0x4FB0, 0x8244, 0x4FB1, 0x8245, 0x4FB2, 0x8246, 0x4FB3, 0x8247, 0x4FB4, 0x8248, 0x4FB6, + 0x8249, 0x4FB7, 0x824A, 0x4FB8, 0x824B, 0x4FB9, 0x824C, 0x4FBA, 0x824D, 0x4FBB, 0x824E, 0x4FBC, 0x824F, 0x4FBD, 0x8250, 0x4FBE, + 0x8251, 0x4FC0, 0x8252, 0x4FC1, 0x8253, 0x4FC2, 0x8254, 0x4FC6, 0x8255, 0x4FC7, 0x8256, 0x4FC8, 0x8257, 0x4FC9, 0x8258, 0x4FCB, + 0x8259, 0x4FCC, 0x825A, 0x4FCD, 0x825B, 0x4FD2, 0x825C, 0x4FD3, 0x825D, 0x4FD4, 0x825E, 0x4FD5, 0x825F, 0x4FD6, 0x8260, 0x4FD9, + 0x8261, 0x4FDB, 0x8262, 0x4FE0, 0x8263, 0x4FE2, 0x8264, 0x4FE4, 0x8265, 0x4FE5, 0x8266, 0x4FE7, 0x8267, 0x4FEB, 0x8268, 0x4FEC, + 0x8269, 0x4FF0, 0x826A, 0x4FF2, 0x826B, 0x4FF4, 0x826C, 0x4FF5, 0x826D, 0x4FF6, 0x826E, 0x4FF7, 0x826F, 0x4FF9, 0x8270, 0x4FFB, + 0x8271, 0x4FFC, 0x8272, 0x4FFD, 0x8273, 0x4FFF, 0x8274, 0x5000, 0x8275, 0x5001, 0x8276, 0x5002, 0x8277, 0x5003, 0x8278, 0x5004, + 0x8279, 0x5005, 0x827A, 0x5006, 0x827B, 0x5007, 0x827C, 0x5008, 0x827D, 0x5009, 0x827E, 0x500A, 0x8280, 0x500B, 0x8281, 0x500E, + 0x8282, 0x5010, 0x8283, 0x5011, 0x8284, 0x5013, 0x8285, 0x5015, 0x8286, 0x5016, 0x8287, 0x5017, 0x8288, 0x501B, 0x8289, 0x501D, + 0x828A, 0x501E, 0x828B, 0x5020, 0x828C, 0x5022, 0x828D, 0x5023, 0x828E, 0x5024, 0x828F, 0x5027, 0x8290, 0x502B, 0x8291, 0x502F, + 0x8292, 0x5030, 0x8293, 0x5031, 0x8294, 0x5032, 0x8295, 0x5033, 0x8296, 0x5034, 0x8297, 0x5035, 0x8298, 0x5036, 0x8299, 0x5037, + 0x829A, 0x5038, 0x829B, 0x5039, 0x829C, 0x503B, 0x829D, 0x503D, 0x829E, 0x503F, 0x829F, 0x5040, 0x82A0, 0x5041, 0x82A1, 0x5042, + 0x82A2, 0x5044, 0x82A3, 0x5045, 0x82A4, 0x5046, 0x82A5, 0x5049, 0x82A6, 0x504A, 0x82A7, 0x504B, 0x82A8, 0x504D, 0x82A9, 0x5050, + 0x82AA, 0x5051, 0x82AB, 0x5052, 0x82AC, 0x5053, 0x82AD, 0x5054, 0x82AE, 0x5056, 0x82AF, 0x5057, 0x82B0, 0x5058, 0x82B1, 0x5059, + 0x82B2, 0x505B, 0x82B3, 0x505D, 0x82B4, 0x505E, 0x82B5, 0x505F, 0x82B6, 0x5060, 0x82B7, 0x5061, 0x82B8, 0x5062, 0x82B9, 0x5063, + 0x82BA, 0x5064, 0x82BB, 0x5066, 0x82BC, 0x5067, 0x82BD, 0x5068, 0x82BE, 0x5069, 0x82BF, 0x506A, 0x82C0, 0x506B, 0x82C1, 0x506D, + 0x82C2, 0x506E, 0x82C3, 0x506F, 0x82C4, 0x5070, 0x82C5, 0x5071, 0x82C6, 0x5072, 0x82C7, 0x5073, 0x82C8, 0x5074, 0x82C9, 0x5075, + 0x82CA, 0x5078, 0x82CB, 0x5079, 0x82CC, 0x507A, 0x82CD, 0x507C, 0x82CE, 0x507D, 0x82CF, 0x5081, 0x82D0, 0x5082, 0x82D1, 0x5083, + 0x82D2, 0x5084, 0x82D3, 0x5086, 0x82D4, 0x5087, 0x82D5, 0x5089, 0x82D6, 0x508A, 0x82D7, 0x508B, 0x82D8, 0x508C, 0x82D9, 0x508E, + 0x82DA, 0x508F, 0x82DB, 0x5090, 0x82DC, 0x5091, 0x82DD, 0x5092, 0x82DE, 0x5093, 0x82DF, 0x5094, 0x82E0, 0x5095, 0x82E1, 0x5096, + 0x82E2, 0x5097, 0x82E3, 0x5098, 0x82E4, 0x5099, 0x82E5, 0x509A, 0x82E6, 0x509B, 0x82E7, 0x509C, 0x82E8, 0x509D, 0x82E9, 0x509E, + 0x82EA, 0x509F, 0x82EB, 0x50A0, 0x82EC, 0x50A1, 0x82ED, 0x50A2, 0x82EE, 0x50A4, 0x82EF, 0x50A6, 0x82F0, 0x50AA, 0x82F1, 0x50AB, + 0x82F2, 0x50AD, 0x82F3, 0x50AE, 0x82F4, 0x50AF, 0x82F5, 0x50B0, 0x82F6, 0x50B1, 0x82F7, 0x50B3, 0x82F8, 0x50B4, 0x82F9, 0x50B5, + 0x82FA, 0x50B6, 0x82FB, 0x50B7, 0x82FC, 0x50B8, 0x82FD, 0x50B9, 0x82FE, 0x50BC, 0x8340, 0x50BD, 0x8341, 0x50BE, 0x8342, 0x50BF, + 0x8343, 0x50C0, 0x8344, 0x50C1, 0x8345, 0x50C2, 0x8346, 0x50C3, 0x8347, 0x50C4, 0x8348, 0x50C5, 0x8349, 0x50C6, 0x834A, 0x50C7, + 0x834B, 0x50C8, 0x834C, 0x50C9, 0x834D, 0x50CA, 0x834E, 0x50CB, 0x834F, 0x50CC, 0x8350, 0x50CD, 0x8351, 0x50CE, 0x8352, 0x50D0, + 0x8353, 0x50D1, 0x8354, 0x50D2, 0x8355, 0x50D3, 0x8356, 0x50D4, 0x8357, 0x50D5, 0x8358, 0x50D7, 0x8359, 0x50D8, 0x835A, 0x50D9, + 0x835B, 0x50DB, 0x835C, 0x50DC, 0x835D, 0x50DD, 0x835E, 0x50DE, 0x835F, 0x50DF, 0x8360, 0x50E0, 0x8361, 0x50E1, 0x8362, 0x50E2, + 0x8363, 0x50E3, 0x8364, 0x50E4, 0x8365, 0x50E5, 0x8366, 0x50E8, 0x8367, 0x50E9, 0x8368, 0x50EA, 0x8369, 0x50EB, 0x836A, 0x50EF, + 0x836B, 0x50F0, 0x836C, 0x50F1, 0x836D, 0x50F2, 0x836E, 0x50F4, 0x836F, 0x50F6, 0x8370, 0x50F7, 0x8371, 0x50F8, 0x8372, 0x50F9, + 0x8373, 0x50FA, 0x8374, 0x50FC, 0x8375, 0x50FD, 0x8376, 0x50FE, 0x8377, 0x50FF, 0x8378, 0x5100, 0x8379, 0x5101, 0x837A, 0x5102, + 0x837B, 0x5103, 0x837C, 0x5104, 0x837D, 0x5105, 0x837E, 0x5108, 0x8380, 0x5109, 0x8381, 0x510A, 0x8382, 0x510C, 0x8383, 0x510D, + 0x8384, 0x510E, 0x8385, 0x510F, 0x8386, 0x5110, 0x8387, 0x5111, 0x8388, 0x5113, 0x8389, 0x5114, 0x838A, 0x5115, 0x838B, 0x5116, + 0x838C, 0x5117, 0x838D, 0x5118, 0x838E, 0x5119, 0x838F, 0x511A, 0x8390, 0x511B, 0x8391, 0x511C, 0x8392, 0x511D, 0x8393, 0x511E, + 0x8394, 0x511F, 0x8395, 0x5120, 0x8396, 0x5122, 0x8397, 0x5123, 0x8398, 0x5124, 0x8399, 0x5125, 0x839A, 0x5126, 0x839B, 0x5127, + 0x839C, 0x5128, 0x839D, 0x5129, 0x839E, 0x512A, 0x839F, 0x512B, 0x83A0, 0x512C, 0x83A1, 0x512D, 0x83A2, 0x512E, 0x83A3, 0x512F, + 0x83A4, 0x5130, 0x83A5, 0x5131, 0x83A6, 0x5132, 0x83A7, 0x5133, 0x83A8, 0x5134, 0x83A9, 0x5135, 0x83AA, 0x5136, 0x83AB, 0x5137, + 0x83AC, 0x5138, 0x83AD, 0x5139, 0x83AE, 0x513A, 0x83AF, 0x513B, 0x83B0, 0x513C, 0x83B1, 0x513D, 0x83B2, 0x513E, 0x83B3, 0x5142, + 0x83B4, 0x5147, 0x83B5, 0x514A, 0x83B6, 0x514C, 0x83B7, 0x514E, 0x83B8, 0x514F, 0x83B9, 0x5150, 0x83BA, 0x5152, 0x83BB, 0x5153, + 0x83BC, 0x5157, 0x83BD, 0x5158, 0x83BE, 0x5159, 0x83BF, 0x515B, 0x83C0, 0x515D, 0x83C1, 0x515E, 0x83C2, 0x515F, 0x83C3, 0x5160, + 0x83C4, 0x5161, 0x83C5, 0x5163, 0x83C6, 0x5164, 0x83C7, 0x5166, 0x83C8, 0x5167, 0x83C9, 0x5169, 0x83CA, 0x516A, 0x83CB, 0x516F, + 0x83CC, 0x5172, 0x83CD, 0x517A, 0x83CE, 0x517E, 0x83CF, 0x517F, 0x83D0, 0x5183, 0x83D1, 0x5184, 0x83D2, 0x5186, 0x83D3, 0x5187, + 0x83D4, 0x518A, 0x83D5, 0x518B, 0x83D6, 0x518E, 0x83D7, 0x518F, 0x83D8, 0x5190, 0x83D9, 0x5191, 0x83DA, 0x5193, 0x83DB, 0x5194, + 0x83DC, 0x5198, 0x83DD, 0x519A, 0x83DE, 0x519D, 0x83DF, 0x519E, 0x83E0, 0x519F, 0x83E1, 0x51A1, 0x83E2, 0x51A3, 0x83E3, 0x51A6, + 0x83E4, 0x51A7, 0x83E5, 0x51A8, 0x83E6, 0x51A9, 0x83E7, 0x51AA, 0x83E8, 0x51AD, 0x83E9, 0x51AE, 0x83EA, 0x51B4, 0x83EB, 0x51B8, + 0x83EC, 0x51B9, 0x83ED, 0x51BA, 0x83EE, 0x51BE, 0x83EF, 0x51BF, 0x83F0, 0x51C1, 0x83F1, 0x51C2, 0x83F2, 0x51C3, 0x83F3, 0x51C5, + 0x83F4, 0x51C8, 0x83F5, 0x51CA, 0x83F6, 0x51CD, 0x83F7, 0x51CE, 0x83F8, 0x51D0, 0x83F9, 0x51D2, 0x83FA, 0x51D3, 0x83FB, 0x51D4, + 0x83FC, 0x51D5, 0x83FD, 0x51D6, 0x83FE, 0x51D7, 0x8440, 0x51D8, 0x8441, 0x51D9, 0x8442, 0x51DA, 0x8443, 0x51DC, 0x8444, 0x51DE, + 0x8445, 0x51DF, 0x8446, 0x51E2, 0x8447, 0x51E3, 0x8448, 0x51E5, 0x8449, 0x51E6, 0x844A, 0x51E7, 0x844B, 0x51E8, 0x844C, 0x51E9, + 0x844D, 0x51EA, 0x844E, 0x51EC, 0x844F, 0x51EE, 0x8450, 0x51F1, 0x8451, 0x51F2, 0x8452, 0x51F4, 0x8453, 0x51F7, 0x8454, 0x51FE, + 0x8455, 0x5204, 0x8456, 0x5205, 0x8457, 0x5209, 0x8458, 0x520B, 0x8459, 0x520C, 0x845A, 0x520F, 0x845B, 0x5210, 0x845C, 0x5213, + 0x845D, 0x5214, 0x845E, 0x5215, 0x845F, 0x521C, 0x8460, 0x521E, 0x8461, 0x521F, 0x8462, 0x5221, 0x8463, 0x5222, 0x8464, 0x5223, + 0x8465, 0x5225, 0x8466, 0x5226, 0x8467, 0x5227, 0x8468, 0x522A, 0x8469, 0x522C, 0x846A, 0x522F, 0x846B, 0x5231, 0x846C, 0x5232, + 0x846D, 0x5234, 0x846E, 0x5235, 0x846F, 0x523C, 0x8470, 0x523E, 0x8471, 0x5244, 0x8472, 0x5245, 0x8473, 0x5246, 0x8474, 0x5247, + 0x8475, 0x5248, 0x8476, 0x5249, 0x8477, 0x524B, 0x8478, 0x524E, 0x8479, 0x524F, 0x847A, 0x5252, 0x847B, 0x5253, 0x847C, 0x5255, + 0x847D, 0x5257, 0x847E, 0x5258, 0x8480, 0x5259, 0x8481, 0x525A, 0x8482, 0x525B, 0x8483, 0x525D, 0x8484, 0x525F, 0x8485, 0x5260, + 0x8486, 0x5262, 0x8487, 0x5263, 0x8488, 0x5264, 0x8489, 0x5266, 0x848A, 0x5268, 0x848B, 0x526B, 0x848C, 0x526C, 0x848D, 0x526D, + 0x848E, 0x526E, 0x848F, 0x5270, 0x8490, 0x5271, 0x8491, 0x5273, 0x8492, 0x5274, 0x8493, 0x5275, 0x8494, 0x5276, 0x8495, 0x5277, + 0x8496, 0x5278, 0x8497, 0x5279, 0x8498, 0x527A, 0x8499, 0x527B, 0x849A, 0x527C, 0x849B, 0x527E, 0x849C, 0x5280, 0x849D, 0x5283, + 0x849E, 0x5284, 0x849F, 0x5285, 0x84A0, 0x5286, 0x84A1, 0x5287, 0x84A2, 0x5289, 0x84A3, 0x528A, 0x84A4, 0x528B, 0x84A5, 0x528C, + 0x84A6, 0x528D, 0x84A7, 0x528E, 0x84A8, 0x528F, 0x84A9, 0x5291, 0x84AA, 0x5292, 0x84AB, 0x5294, 0x84AC, 0x5295, 0x84AD, 0x5296, + 0x84AE, 0x5297, 0x84AF, 0x5298, 0x84B0, 0x5299, 0x84B1, 0x529A, 0x84B2, 0x529C, 0x84B3, 0x52A4, 0x84B4, 0x52A5, 0x84B5, 0x52A6, + 0x84B6, 0x52A7, 0x84B7, 0x52AE, 0x84B8, 0x52AF, 0x84B9, 0x52B0, 0x84BA, 0x52B4, 0x84BB, 0x52B5, 0x84BC, 0x52B6, 0x84BD, 0x52B7, + 0x84BE, 0x52B8, 0x84BF, 0x52B9, 0x84C0, 0x52BA, 0x84C1, 0x52BB, 0x84C2, 0x52BC, 0x84C3, 0x52BD, 0x84C4, 0x52C0, 0x84C5, 0x52C1, + 0x84C6, 0x52C2, 0x84C7, 0x52C4, 0x84C8, 0x52C5, 0x84C9, 0x52C6, 0x84CA, 0x52C8, 0x84CB, 0x52CA, 0x84CC, 0x52CC, 0x84CD, 0x52CD, + 0x84CE, 0x52CE, 0x84CF, 0x52CF, 0x84D0, 0x52D1, 0x84D1, 0x52D3, 0x84D2, 0x52D4, 0x84D3, 0x52D5, 0x84D4, 0x52D7, 0x84D5, 0x52D9, + 0x84D6, 0x52DA, 0x84D7, 0x52DB, 0x84D8, 0x52DC, 0x84D9, 0x52DD, 0x84DA, 0x52DE, 0x84DB, 0x52E0, 0x84DC, 0x52E1, 0x84DD, 0x52E2, + 0x84DE, 0x52E3, 0x84DF, 0x52E5, 0x84E0, 0x52E6, 0x84E1, 0x52E7, 0x84E2, 0x52E8, 0x84E3, 0x52E9, 0x84E4, 0x52EA, 0x84E5, 0x52EB, + 0x84E6, 0x52EC, 0x84E7, 0x52ED, 0x84E8, 0x52EE, 0x84E9, 0x52EF, 0x84EA, 0x52F1, 0x84EB, 0x52F2, 0x84EC, 0x52F3, 0x84ED, 0x52F4, + 0x84EE, 0x52F5, 0x84EF, 0x52F6, 0x84F0, 0x52F7, 0x84F1, 0x52F8, 0x84F2, 0x52FB, 0x84F3, 0x52FC, 0x84F4, 0x52FD, 0x84F5, 0x5301, + 0x84F6, 0x5302, 0x84F7, 0x5303, 0x84F8, 0x5304, 0x84F9, 0x5307, 0x84FA, 0x5309, 0x84FB, 0x530A, 0x84FC, 0x530B, 0x84FD, 0x530C, + 0x84FE, 0x530E, 0x8540, 0x5311, 0x8541, 0x5312, 0x8542, 0x5313, 0x8543, 0x5314, 0x8544, 0x5318, 0x8545, 0x531B, 0x8546, 0x531C, + 0x8547, 0x531E, 0x8548, 0x531F, 0x8549, 0x5322, 0x854A, 0x5324, 0x854B, 0x5325, 0x854C, 0x5327, 0x854D, 0x5328, 0x854E, 0x5329, + 0x854F, 0x532B, 0x8550, 0x532C, 0x8551, 0x532D, 0x8552, 0x532F, 0x8553, 0x5330, 0x8554, 0x5331, 0x8555, 0x5332, 0x8556, 0x5333, + 0x8557, 0x5334, 0x8558, 0x5335, 0x8559, 0x5336, 0x855A, 0x5337, 0x855B, 0x5338, 0x855C, 0x533C, 0x855D, 0x533D, 0x855E, 0x5340, + 0x855F, 0x5342, 0x8560, 0x5344, 0x8561, 0x5346, 0x8562, 0x534B, 0x8563, 0x534C, 0x8564, 0x534D, 0x8565, 0x5350, 0x8566, 0x5354, + 0x8567, 0x5358, 0x8568, 0x5359, 0x8569, 0x535B, 0x856A, 0x535D, 0x856B, 0x5365, 0x856C, 0x5368, 0x856D, 0x536A, 0x856E, 0x536C, + 0x856F, 0x536D, 0x8570, 0x5372, 0x8571, 0x5376, 0x8572, 0x5379, 0x8573, 0x537B, 0x8574, 0x537C, 0x8575, 0x537D, 0x8576, 0x537E, + 0x8577, 0x5380, 0x8578, 0x5381, 0x8579, 0x5383, 0x857A, 0x5387, 0x857B, 0x5388, 0x857C, 0x538A, 0x857D, 0x538E, 0x857E, 0x538F, + 0x8580, 0x5390, 0x8581, 0x5391, 0x8582, 0x5392, 0x8583, 0x5393, 0x8584, 0x5394, 0x8585, 0x5396, 0x8586, 0x5397, 0x8587, 0x5399, + 0x8588, 0x539B, 0x8589, 0x539C, 0x858A, 0x539E, 0x858B, 0x53A0, 0x858C, 0x53A1, 0x858D, 0x53A4, 0x858E, 0x53A7, 0x858F, 0x53AA, + 0x8590, 0x53AB, 0x8591, 0x53AC, 0x8592, 0x53AD, 0x8593, 0x53AF, 0x8594, 0x53B0, 0x8595, 0x53B1, 0x8596, 0x53B2, 0x8597, 0x53B3, + 0x8598, 0x53B4, 0x8599, 0x53B5, 0x859A, 0x53B7, 0x859B, 0x53B8, 0x859C, 0x53B9, 0x859D, 0x53BA, 0x859E, 0x53BC, 0x859F, 0x53BD, + 0x85A0, 0x53BE, 0x85A1, 0x53C0, 0x85A2, 0x53C3, 0x85A3, 0x53C4, 0x85A4, 0x53C5, 0x85A5, 0x53C6, 0x85A6, 0x53C7, 0x85A7, 0x53CE, + 0x85A8, 0x53CF, 0x85A9, 0x53D0, 0x85AA, 0x53D2, 0x85AB, 0x53D3, 0x85AC, 0x53D5, 0x85AD, 0x53DA, 0x85AE, 0x53DC, 0x85AF, 0x53DD, + 0x85B0, 0x53DE, 0x85B1, 0x53E1, 0x85B2, 0x53E2, 0x85B3, 0x53E7, 0x85B4, 0x53F4, 0x85B5, 0x53FA, 0x85B6, 0x53FE, 0x85B7, 0x53FF, + 0x85B8, 0x5400, 0x85B9, 0x5402, 0x85BA, 0x5405, 0x85BB, 0x5407, 0x85BC, 0x540B, 0x85BD, 0x5414, 0x85BE, 0x5418, 0x85BF, 0x5419, + 0x85C0, 0x541A, 0x85C1, 0x541C, 0x85C2, 0x5422, 0x85C3, 0x5424, 0x85C4, 0x5425, 0x85C5, 0x542A, 0x85C6, 0x5430, 0x85C7, 0x5433, + 0x85C8, 0x5436, 0x85C9, 0x5437, 0x85CA, 0x543A, 0x85CB, 0x543D, 0x85CC, 0x543F, 0x85CD, 0x5441, 0x85CE, 0x5442, 0x85CF, 0x5444, + 0x85D0, 0x5445, 0x85D1, 0x5447, 0x85D2, 0x5449, 0x85D3, 0x544C, 0x85D4, 0x544D, 0x85D5, 0x544E, 0x85D6, 0x544F, 0x85D7, 0x5451, + 0x85D8, 0x545A, 0x85D9, 0x545D, 0x85DA, 0x545E, 0x85DB, 0x545F, 0x85DC, 0x5460, 0x85DD, 0x5461, 0x85DE, 0x5463, 0x85DF, 0x5465, + 0x85E0, 0x5467, 0x85E1, 0x5469, 0x85E2, 0x546A, 0x85E3, 0x546B, 0x85E4, 0x546C, 0x85E5, 0x546D, 0x85E6, 0x546E, 0x85E7, 0x546F, + 0x85E8, 0x5470, 0x85E9, 0x5474, 0x85EA, 0x5479, 0x85EB, 0x547A, 0x85EC, 0x547E, 0x85ED, 0x547F, 0x85EE, 0x5481, 0x85EF, 0x5483, + 0x85F0, 0x5485, 0x85F1, 0x5487, 0x85F2, 0x5488, 0x85F3, 0x5489, 0x85F4, 0x548A, 0x85F5, 0x548D, 0x85F6, 0x5491, 0x85F7, 0x5493, + 0x85F8, 0x5497, 0x85F9, 0x5498, 0x85FA, 0x549C, 0x85FB, 0x549E, 0x85FC, 0x549F, 0x85FD, 0x54A0, 0x85FE, 0x54A1, 0x8640, 0x54A2, + 0x8641, 0x54A5, 0x8642, 0x54AE, 0x8643, 0x54B0, 0x8644, 0x54B2, 0x8645, 0x54B5, 0x8646, 0x54B6, 0x8647, 0x54B7, 0x8648, 0x54B9, + 0x8649, 0x54BA, 0x864A, 0x54BC, 0x864B, 0x54BE, 0x864C, 0x54C3, 0x864D, 0x54C5, 0x864E, 0x54CA, 0x864F, 0x54CB, 0x8650, 0x54D6, + 0x8651, 0x54D8, 0x8652, 0x54DB, 0x8653, 0x54E0, 0x8654, 0x54E1, 0x8655, 0x54E2, 0x8656, 0x54E3, 0x8657, 0x54E4, 0x8658, 0x54EB, + 0x8659, 0x54EC, 0x865A, 0x54EF, 0x865B, 0x54F0, 0x865C, 0x54F1, 0x865D, 0x54F4, 0x865E, 0x54F5, 0x865F, 0x54F6, 0x8660, 0x54F7, + 0x8661, 0x54F8, 0x8662, 0x54F9, 0x8663, 0x54FB, 0x8664, 0x54FE, 0x8665, 0x5500, 0x8666, 0x5502, 0x8667, 0x5503, 0x8668, 0x5504, + 0x8669, 0x5505, 0x866A, 0x5508, 0x866B, 0x550A, 0x866C, 0x550B, 0x866D, 0x550C, 0x866E, 0x550D, 0x866F, 0x550E, 0x8670, 0x5512, + 0x8671, 0x5513, 0x8672, 0x5515, 0x8673, 0x5516, 0x8674, 0x5517, 0x8675, 0x5518, 0x8676, 0x5519, 0x8677, 0x551A, 0x8678, 0x551C, + 0x8679, 0x551D, 0x867A, 0x551E, 0x867B, 0x551F, 0x867C, 0x5521, 0x867D, 0x5525, 0x867E, 0x5526, 0x8680, 0x5528, 0x8681, 0x5529, + 0x8682, 0x552B, 0x8683, 0x552D, 0x8684, 0x5532, 0x8685, 0x5534, 0x8686, 0x5535, 0x8687, 0x5536, 0x8688, 0x5538, 0x8689, 0x5539, + 0x868A, 0x553A, 0x868B, 0x553B, 0x868C, 0x553D, 0x868D, 0x5540, 0x868E, 0x5542, 0x868F, 0x5545, 0x8690, 0x5547, 0x8691, 0x5548, + 0x8692, 0x554B, 0x8693, 0x554C, 0x8694, 0x554D, 0x8695, 0x554E, 0x8696, 0x554F, 0x8697, 0x5551, 0x8698, 0x5552, 0x8699, 0x5553, + 0x869A, 0x5554, 0x869B, 0x5557, 0x869C, 0x5558, 0x869D, 0x5559, 0x869E, 0x555A, 0x869F, 0x555B, 0x86A0, 0x555D, 0x86A1, 0x555E, + 0x86A2, 0x555F, 0x86A3, 0x5560, 0x86A4, 0x5562, 0x86A5, 0x5563, 0x86A6, 0x5568, 0x86A7, 0x5569, 0x86A8, 0x556B, 0x86A9, 0x556F, + 0x86AA, 0x5570, 0x86AB, 0x5571, 0x86AC, 0x5572, 0x86AD, 0x5573, 0x86AE, 0x5574, 0x86AF, 0x5579, 0x86B0, 0x557A, 0x86B1, 0x557D, + 0x86B2, 0x557F, 0x86B3, 0x5585, 0x86B4, 0x5586, 0x86B5, 0x558C, 0x86B6, 0x558D, 0x86B7, 0x558E, 0x86B8, 0x5590, 0x86B9, 0x5592, + 0x86BA, 0x5593, 0x86BB, 0x5595, 0x86BC, 0x5596, 0x86BD, 0x5597, 0x86BE, 0x559A, 0x86BF, 0x559B, 0x86C0, 0x559E, 0x86C1, 0x55A0, + 0x86C2, 0x55A1, 0x86C3, 0x55A2, 0x86C4, 0x55A3, 0x86C5, 0x55A4, 0x86C6, 0x55A5, 0x86C7, 0x55A6, 0x86C8, 0x55A8, 0x86C9, 0x55A9, + 0x86CA, 0x55AA, 0x86CB, 0x55AB, 0x86CC, 0x55AC, 0x86CD, 0x55AD, 0x86CE, 0x55AE, 0x86CF, 0x55AF, 0x86D0, 0x55B0, 0x86D1, 0x55B2, + 0x86D2, 0x55B4, 0x86D3, 0x55B6, 0x86D4, 0x55B8, 0x86D5, 0x55BA, 0x86D6, 0x55BC, 0x86D7, 0x55BF, 0x86D8, 0x55C0, 0x86D9, 0x55C1, + 0x86DA, 0x55C2, 0x86DB, 0x55C3, 0x86DC, 0x55C6, 0x86DD, 0x55C7, 0x86DE, 0x55C8, 0x86DF, 0x55CA, 0x86E0, 0x55CB, 0x86E1, 0x55CE, + 0x86E2, 0x55CF, 0x86E3, 0x55D0, 0x86E4, 0x55D5, 0x86E5, 0x55D7, 0x86E6, 0x55D8, 0x86E7, 0x55D9, 0x86E8, 0x55DA, 0x86E9, 0x55DB, + 0x86EA, 0x55DE, 0x86EB, 0x55E0, 0x86EC, 0x55E2, 0x86ED, 0x55E7, 0x86EE, 0x55E9, 0x86EF, 0x55ED, 0x86F0, 0x55EE, 0x86F1, 0x55F0, + 0x86F2, 0x55F1, 0x86F3, 0x55F4, 0x86F4, 0x55F6, 0x86F5, 0x55F8, 0x86F6, 0x55F9, 0x86F7, 0x55FA, 0x86F8, 0x55FB, 0x86F9, 0x55FC, + 0x86FA, 0x55FF, 0x86FB, 0x5602, 0x86FC, 0x5603, 0x86FD, 0x5604, 0x86FE, 0x5605, 0x8740, 0x5606, 0x8741, 0x5607, 0x8742, 0x560A, + 0x8743, 0x560B, 0x8744, 0x560D, 0x8745, 0x5610, 0x8746, 0x5611, 0x8747, 0x5612, 0x8748, 0x5613, 0x8749, 0x5614, 0x874A, 0x5615, + 0x874B, 0x5616, 0x874C, 0x5617, 0x874D, 0x5619, 0x874E, 0x561A, 0x874F, 0x561C, 0x8750, 0x561D, 0x8751, 0x5620, 0x8752, 0x5621, + 0x8753, 0x5622, 0x8754, 0x5625, 0x8755, 0x5626, 0x8756, 0x5628, 0x8757, 0x5629, 0x8758, 0x562A, 0x8759, 0x562B, 0x875A, 0x562E, + 0x875B, 0x562F, 0x875C, 0x5630, 0x875D, 0x5633, 0x875E, 0x5635, 0x875F, 0x5637, 0x8760, 0x5638, 0x8761, 0x563A, 0x8762, 0x563C, + 0x8763, 0x563D, 0x8764, 0x563E, 0x8765, 0x5640, 0x8766, 0x5641, 0x8767, 0x5642, 0x8768, 0x5643, 0x8769, 0x5644, 0x876A, 0x5645, + 0x876B, 0x5646, 0x876C, 0x5647, 0x876D, 0x5648, 0x876E, 0x5649, 0x876F, 0x564A, 0x8770, 0x564B, 0x8771, 0x564F, 0x8772, 0x5650, + 0x8773, 0x5651, 0x8774, 0x5652, 0x8775, 0x5653, 0x8776, 0x5655, 0x8777, 0x5656, 0x8778, 0x565A, 0x8779, 0x565B, 0x877A, 0x565D, + 0x877B, 0x565E, 0x877C, 0x565F, 0x877D, 0x5660, 0x877E, 0x5661, 0x8780, 0x5663, 0x8781, 0x5665, 0x8782, 0x5666, 0x8783, 0x5667, + 0x8784, 0x566D, 0x8785, 0x566E, 0x8786, 0x566F, 0x8787, 0x5670, 0x8788, 0x5672, 0x8789, 0x5673, 0x878A, 0x5674, 0x878B, 0x5675, + 0x878C, 0x5677, 0x878D, 0x5678, 0x878E, 0x5679, 0x878F, 0x567A, 0x8790, 0x567D, 0x8791, 0x567E, 0x8792, 0x567F, 0x8793, 0x5680, + 0x8794, 0x5681, 0x8795, 0x5682, 0x8796, 0x5683, 0x8797, 0x5684, 0x8798, 0x5687, 0x8799, 0x5688, 0x879A, 0x5689, 0x879B, 0x568A, + 0x879C, 0x568B, 0x879D, 0x568C, 0x879E, 0x568D, 0x879F, 0x5690, 0x87A0, 0x5691, 0x87A1, 0x5692, 0x87A2, 0x5694, 0x87A3, 0x5695, + 0x87A4, 0x5696, 0x87A5, 0x5697, 0x87A6, 0x5698, 0x87A7, 0x5699, 0x87A8, 0x569A, 0x87A9, 0x569B, 0x87AA, 0x569C, 0x87AB, 0x569D, + 0x87AC, 0x569E, 0x87AD, 0x569F, 0x87AE, 0x56A0, 0x87AF, 0x56A1, 0x87B0, 0x56A2, 0x87B1, 0x56A4, 0x87B2, 0x56A5, 0x87B3, 0x56A6, + 0x87B4, 0x56A7, 0x87B5, 0x56A8, 0x87B6, 0x56A9, 0x87B7, 0x56AA, 0x87B8, 0x56AB, 0x87B9, 0x56AC, 0x87BA, 0x56AD, 0x87BB, 0x56AE, + 0x87BC, 0x56B0, 0x87BD, 0x56B1, 0x87BE, 0x56B2, 0x87BF, 0x56B3, 0x87C0, 0x56B4, 0x87C1, 0x56B5, 0x87C2, 0x56B6, 0x87C3, 0x56B8, + 0x87C4, 0x56B9, 0x87C5, 0x56BA, 0x87C6, 0x56BB, 0x87C7, 0x56BD, 0x87C8, 0x56BE, 0x87C9, 0x56BF, 0x87CA, 0x56C0, 0x87CB, 0x56C1, + 0x87CC, 0x56C2, 0x87CD, 0x56C3, 0x87CE, 0x56C4, 0x87CF, 0x56C5, 0x87D0, 0x56C6, 0x87D1, 0x56C7, 0x87D2, 0x56C8, 0x87D3, 0x56C9, + 0x87D4, 0x56CB, 0x87D5, 0x56CC, 0x87D6, 0x56CD, 0x87D7, 0x56CE, 0x87D8, 0x56CF, 0x87D9, 0x56D0, 0x87DA, 0x56D1, 0x87DB, 0x56D2, + 0x87DC, 0x56D3, 0x87DD, 0x56D5, 0x87DE, 0x56D6, 0x87DF, 0x56D8, 0x87E0, 0x56D9, 0x87E1, 0x56DC, 0x87E2, 0x56E3, 0x87E3, 0x56E5, + 0x87E4, 0x56E6, 0x87E5, 0x56E7, 0x87E6, 0x56E8, 0x87E7, 0x56E9, 0x87E8, 0x56EA, 0x87E9, 0x56EC, 0x87EA, 0x56EE, 0x87EB, 0x56EF, + 0x87EC, 0x56F2, 0x87ED, 0x56F3, 0x87EE, 0x56F6, 0x87EF, 0x56F7, 0x87F0, 0x56F8, 0x87F1, 0x56FB, 0x87F2, 0x56FC, 0x87F3, 0x5700, + 0x87F4, 0x5701, 0x87F5, 0x5702, 0x87F6, 0x5705, 0x87F7, 0x5707, 0x87F8, 0x570B, 0x87F9, 0x570C, 0x87FA, 0x570D, 0x87FB, 0x570E, + 0x87FC, 0x570F, 0x87FD, 0x5710, 0x87FE, 0x5711, 0x8840, 0x5712, 0x8841, 0x5713, 0x8842, 0x5714, 0x8843, 0x5715, 0x8844, 0x5716, + 0x8845, 0x5717, 0x8846, 0x5718, 0x8847, 0x5719, 0x8848, 0x571A, 0x8849, 0x571B, 0x884A, 0x571D, 0x884B, 0x571E, 0x884C, 0x5720, + 0x884D, 0x5721, 0x884E, 0x5722, 0x884F, 0x5724, 0x8850, 0x5725, 0x8851, 0x5726, 0x8852, 0x5727, 0x8853, 0x572B, 0x8854, 0x5731, + 0x8855, 0x5732, 0x8856, 0x5734, 0x8857, 0x5735, 0x8858, 0x5736, 0x8859, 0x5737, 0x885A, 0x5738, 0x885B, 0x573C, 0x885C, 0x573D, + 0x885D, 0x573F, 0x885E, 0x5741, 0x885F, 0x5743, 0x8860, 0x5744, 0x8861, 0x5745, 0x8862, 0x5746, 0x8863, 0x5748, 0x8864, 0x5749, + 0x8865, 0x574B, 0x8866, 0x5752, 0x8867, 0x5753, 0x8868, 0x5754, 0x8869, 0x5755, 0x886A, 0x5756, 0x886B, 0x5758, 0x886C, 0x5759, + 0x886D, 0x5762, 0x886E, 0x5763, 0x886F, 0x5765, 0x8870, 0x5767, 0x8871, 0x576C, 0x8872, 0x576E, 0x8873, 0x5770, 0x8874, 0x5771, + 0x8875, 0x5772, 0x8876, 0x5774, 0x8877, 0x5775, 0x8878, 0x5778, 0x8879, 0x5779, 0x887A, 0x577A, 0x887B, 0x577D, 0x887C, 0x577E, + 0x887D, 0x577F, 0x887E, 0x5780, 0x8880, 0x5781, 0x8881, 0x5787, 0x8882, 0x5788, 0x8883, 0x5789, 0x8884, 0x578A, 0x8885, 0x578D, + 0x8886, 0x578E, 0x8887, 0x578F, 0x8888, 0x5790, 0x8889, 0x5791, 0x888A, 0x5794, 0x888B, 0x5795, 0x888C, 0x5796, 0x888D, 0x5797, + 0x888E, 0x5798, 0x888F, 0x5799, 0x8890, 0x579A, 0x8891, 0x579C, 0x8892, 0x579D, 0x8893, 0x579E, 0x8894, 0x579F, 0x8895, 0x57A5, + 0x8896, 0x57A8, 0x8897, 0x57AA, 0x8898, 0x57AC, 0x8899, 0x57AF, 0x889A, 0x57B0, 0x889B, 0x57B1, 0x889C, 0x57B3, 0x889D, 0x57B5, + 0x889E, 0x57B6, 0x889F, 0x57B7, 0x88A0, 0x57B9, 0x88A1, 0x57BA, 0x88A2, 0x57BB, 0x88A3, 0x57BC, 0x88A4, 0x57BD, 0x88A5, 0x57BE, + 0x88A6, 0x57BF, 0x88A7, 0x57C0, 0x88A8, 0x57C1, 0x88A9, 0x57C4, 0x88AA, 0x57C5, 0x88AB, 0x57C6, 0x88AC, 0x57C7, 0x88AD, 0x57C8, + 0x88AE, 0x57C9, 0x88AF, 0x57CA, 0x88B0, 0x57CC, 0x88B1, 0x57CD, 0x88B2, 0x57D0, 0x88B3, 0x57D1, 0x88B4, 0x57D3, 0x88B5, 0x57D6, + 0x88B6, 0x57D7, 0x88B7, 0x57DB, 0x88B8, 0x57DC, 0x88B9, 0x57DE, 0x88BA, 0x57E1, 0x88BB, 0x57E2, 0x88BC, 0x57E3, 0x88BD, 0x57E5, + 0x88BE, 0x57E6, 0x88BF, 0x57E7, 0x88C0, 0x57E8, 0x88C1, 0x57E9, 0x88C2, 0x57EA, 0x88C3, 0x57EB, 0x88C4, 0x57EC, 0x88C5, 0x57EE, + 0x88C6, 0x57F0, 0x88C7, 0x57F1, 0x88C8, 0x57F2, 0x88C9, 0x57F3, 0x88CA, 0x57F5, 0x88CB, 0x57F6, 0x88CC, 0x57F7, 0x88CD, 0x57FB, + 0x88CE, 0x57FC, 0x88CF, 0x57FE, 0x88D0, 0x57FF, 0x88D1, 0x5801, 0x88D2, 0x5803, 0x88D3, 0x5804, 0x88D4, 0x5805, 0x88D5, 0x5808, + 0x88D6, 0x5809, 0x88D7, 0x580A, 0x88D8, 0x580C, 0x88D9, 0x580E, 0x88DA, 0x580F, 0x88DB, 0x5810, 0x88DC, 0x5812, 0x88DD, 0x5813, + 0x88DE, 0x5814, 0x88DF, 0x5816, 0x88E0, 0x5817, 0x88E1, 0x5818, 0x88E2, 0x581A, 0x88E3, 0x581B, 0x88E4, 0x581C, 0x88E5, 0x581D, + 0x88E6, 0x581F, 0x88E7, 0x5822, 0x88E8, 0x5823, 0x88E9, 0x5825, 0x88EA, 0x5826, 0x88EB, 0x5827, 0x88EC, 0x5828, 0x88ED, 0x5829, + 0x88EE, 0x582B, 0x88EF, 0x582C, 0x88F0, 0x582D, 0x88F1, 0x582E, 0x88F2, 0x582F, 0x88F3, 0x5831, 0x88F4, 0x5832, 0x88F5, 0x5833, + 0x88F6, 0x5834, 0x88F7, 0x5836, 0x88F8, 0x5837, 0x88F9, 0x5838, 0x88FA, 0x5839, 0x88FB, 0x583A, 0x88FC, 0x583B, 0x88FD, 0x583C, + 0x88FE, 0x583D, 0x8940, 0x583E, 0x8941, 0x583F, 0x8942, 0x5840, 0x8943, 0x5841, 0x8944, 0x5842, 0x8945, 0x5843, 0x8946, 0x5845, + 0x8947, 0x5846, 0x8948, 0x5847, 0x8949, 0x5848, 0x894A, 0x5849, 0x894B, 0x584A, 0x894C, 0x584B, 0x894D, 0x584E, 0x894E, 0x584F, + 0x894F, 0x5850, 0x8950, 0x5852, 0x8951, 0x5853, 0x8952, 0x5855, 0x8953, 0x5856, 0x8954, 0x5857, 0x8955, 0x5859, 0x8956, 0x585A, + 0x8957, 0x585B, 0x8958, 0x585C, 0x8959, 0x585D, 0x895A, 0x585F, 0x895B, 0x5860, 0x895C, 0x5861, 0x895D, 0x5862, 0x895E, 0x5863, + 0x895F, 0x5864, 0x8960, 0x5866, 0x8961, 0x5867, 0x8962, 0x5868, 0x8963, 0x5869, 0x8964, 0x586A, 0x8965, 0x586D, 0x8966, 0x586E, + 0x8967, 0x586F, 0x8968, 0x5870, 0x8969, 0x5871, 0x896A, 0x5872, 0x896B, 0x5873, 0x896C, 0x5874, 0x896D, 0x5875, 0x896E, 0x5876, + 0x896F, 0x5877, 0x8970, 0x5878, 0x8971, 0x5879, 0x8972, 0x587A, 0x8973, 0x587B, 0x8974, 0x587C, 0x8975, 0x587D, 0x8976, 0x587F, + 0x8977, 0x5882, 0x8978, 0x5884, 0x8979, 0x5886, 0x897A, 0x5887, 0x897B, 0x5888, 0x897C, 0x588A, 0x897D, 0x588B, 0x897E, 0x588C, + 0x8980, 0x588D, 0x8981, 0x588E, 0x8982, 0x588F, 0x8983, 0x5890, 0x8984, 0x5891, 0x8985, 0x5894, 0x8986, 0x5895, 0x8987, 0x5896, + 0x8988, 0x5897, 0x8989, 0x5898, 0x898A, 0x589B, 0x898B, 0x589C, 0x898C, 0x589D, 0x898D, 0x58A0, 0x898E, 0x58A1, 0x898F, 0x58A2, + 0x8990, 0x58A3, 0x8991, 0x58A4, 0x8992, 0x58A5, 0x8993, 0x58A6, 0x8994, 0x58A7, 0x8995, 0x58AA, 0x8996, 0x58AB, 0x8997, 0x58AC, + 0x8998, 0x58AD, 0x8999, 0x58AE, 0x899A, 0x58AF, 0x899B, 0x58B0, 0x899C, 0x58B1, 0x899D, 0x58B2, 0x899E, 0x58B3, 0x899F, 0x58B4, + 0x89A0, 0x58B5, 0x89A1, 0x58B6, 0x89A2, 0x58B7, 0x89A3, 0x58B8, 0x89A4, 0x58B9, 0x89A5, 0x58BA, 0x89A6, 0x58BB, 0x89A7, 0x58BD, + 0x89A8, 0x58BE, 0x89A9, 0x58BF, 0x89AA, 0x58C0, 0x89AB, 0x58C2, 0x89AC, 0x58C3, 0x89AD, 0x58C4, 0x89AE, 0x58C6, 0x89AF, 0x58C7, + 0x89B0, 0x58C8, 0x89B1, 0x58C9, 0x89B2, 0x58CA, 0x89B3, 0x58CB, 0x89B4, 0x58CC, 0x89B5, 0x58CD, 0x89B6, 0x58CE, 0x89B7, 0x58CF, + 0x89B8, 0x58D0, 0x89B9, 0x58D2, 0x89BA, 0x58D3, 0x89BB, 0x58D4, 0x89BC, 0x58D6, 0x89BD, 0x58D7, 0x89BE, 0x58D8, 0x89BF, 0x58D9, + 0x89C0, 0x58DA, 0x89C1, 0x58DB, 0x89C2, 0x58DC, 0x89C3, 0x58DD, 0x89C4, 0x58DE, 0x89C5, 0x58DF, 0x89C6, 0x58E0, 0x89C7, 0x58E1, + 0x89C8, 0x58E2, 0x89C9, 0x58E3, 0x89CA, 0x58E5, 0x89CB, 0x58E6, 0x89CC, 0x58E7, 0x89CD, 0x58E8, 0x89CE, 0x58E9, 0x89CF, 0x58EA, + 0x89D0, 0x58ED, 0x89D1, 0x58EF, 0x89D2, 0x58F1, 0x89D3, 0x58F2, 0x89D4, 0x58F4, 0x89D5, 0x58F5, 0x89D6, 0x58F7, 0x89D7, 0x58F8, + 0x89D8, 0x58FA, 0x89D9, 0x58FB, 0x89DA, 0x58FC, 0x89DB, 0x58FD, 0x89DC, 0x58FE, 0x89DD, 0x58FF, 0x89DE, 0x5900, 0x89DF, 0x5901, + 0x89E0, 0x5903, 0x89E1, 0x5905, 0x89E2, 0x5906, 0x89E3, 0x5908, 0x89E4, 0x5909, 0x89E5, 0x590A, 0x89E6, 0x590B, 0x89E7, 0x590C, + 0x89E8, 0x590E, 0x89E9, 0x5910, 0x89EA, 0x5911, 0x89EB, 0x5912, 0x89EC, 0x5913, 0x89ED, 0x5917, 0x89EE, 0x5918, 0x89EF, 0x591B, + 0x89F0, 0x591D, 0x89F1, 0x591E, 0x89F2, 0x5920, 0x89F3, 0x5921, 0x89F4, 0x5922, 0x89F5, 0x5923, 0x89F6, 0x5926, 0x89F7, 0x5928, + 0x89F8, 0x592C, 0x89F9, 0x5930, 0x89FA, 0x5932, 0x89FB, 0x5933, 0x89FC, 0x5935, 0x89FD, 0x5936, 0x89FE, 0x593B, 0x8A40, 0x593D, + 0x8A41, 0x593E, 0x8A42, 0x593F, 0x8A43, 0x5940, 0x8A44, 0x5943, 0x8A45, 0x5945, 0x8A46, 0x5946, 0x8A47, 0x594A, 0x8A48, 0x594C, + 0x8A49, 0x594D, 0x8A4A, 0x5950, 0x8A4B, 0x5952, 0x8A4C, 0x5953, 0x8A4D, 0x5959, 0x8A4E, 0x595B, 0x8A4F, 0x595C, 0x8A50, 0x595D, + 0x8A51, 0x595E, 0x8A52, 0x595F, 0x8A53, 0x5961, 0x8A54, 0x5963, 0x8A55, 0x5964, 0x8A56, 0x5966, 0x8A57, 0x5967, 0x8A58, 0x5968, + 0x8A59, 0x5969, 0x8A5A, 0x596A, 0x8A5B, 0x596B, 0x8A5C, 0x596C, 0x8A5D, 0x596D, 0x8A5E, 0x596E, 0x8A5F, 0x596F, 0x8A60, 0x5970, + 0x8A61, 0x5971, 0x8A62, 0x5972, 0x8A63, 0x5975, 0x8A64, 0x5977, 0x8A65, 0x597A, 0x8A66, 0x597B, 0x8A67, 0x597C, 0x8A68, 0x597E, + 0x8A69, 0x597F, 0x8A6A, 0x5980, 0x8A6B, 0x5985, 0x8A6C, 0x5989, 0x8A6D, 0x598B, 0x8A6E, 0x598C, 0x8A6F, 0x598E, 0x8A70, 0x598F, + 0x8A71, 0x5990, 0x8A72, 0x5991, 0x8A73, 0x5994, 0x8A74, 0x5995, 0x8A75, 0x5998, 0x8A76, 0x599A, 0x8A77, 0x599B, 0x8A78, 0x599C, + 0x8A79, 0x599D, 0x8A7A, 0x599F, 0x8A7B, 0x59A0, 0x8A7C, 0x59A1, 0x8A7D, 0x59A2, 0x8A7E, 0x59A6, 0x8A80, 0x59A7, 0x8A81, 0x59AC, + 0x8A82, 0x59AD, 0x8A83, 0x59B0, 0x8A84, 0x59B1, 0x8A85, 0x59B3, 0x8A86, 0x59B4, 0x8A87, 0x59B5, 0x8A88, 0x59B6, 0x8A89, 0x59B7, + 0x8A8A, 0x59B8, 0x8A8B, 0x59BA, 0x8A8C, 0x59BC, 0x8A8D, 0x59BD, 0x8A8E, 0x59BF, 0x8A8F, 0x59C0, 0x8A90, 0x59C1, 0x8A91, 0x59C2, + 0x8A92, 0x59C3, 0x8A93, 0x59C4, 0x8A94, 0x59C5, 0x8A95, 0x59C7, 0x8A96, 0x59C8, 0x8A97, 0x59C9, 0x8A98, 0x59CC, 0x8A99, 0x59CD, + 0x8A9A, 0x59CE, 0x8A9B, 0x59CF, 0x8A9C, 0x59D5, 0x8A9D, 0x59D6, 0x8A9E, 0x59D9, 0x8A9F, 0x59DB, 0x8AA0, 0x59DE, 0x8AA1, 0x59DF, + 0x8AA2, 0x59E0, 0x8AA3, 0x59E1, 0x8AA4, 0x59E2, 0x8AA5, 0x59E4, 0x8AA6, 0x59E6, 0x8AA7, 0x59E7, 0x8AA8, 0x59E9, 0x8AA9, 0x59EA, + 0x8AAA, 0x59EB, 0x8AAB, 0x59ED, 0x8AAC, 0x59EE, 0x8AAD, 0x59EF, 0x8AAE, 0x59F0, 0x8AAF, 0x59F1, 0x8AB0, 0x59F2, 0x8AB1, 0x59F3, + 0x8AB2, 0x59F4, 0x8AB3, 0x59F5, 0x8AB4, 0x59F6, 0x8AB5, 0x59F7, 0x8AB6, 0x59F8, 0x8AB7, 0x59FA, 0x8AB8, 0x59FC, 0x8AB9, 0x59FD, + 0x8ABA, 0x59FE, 0x8ABB, 0x5A00, 0x8ABC, 0x5A02, 0x8ABD, 0x5A0A, 0x8ABE, 0x5A0B, 0x8ABF, 0x5A0D, 0x8AC0, 0x5A0E, 0x8AC1, 0x5A0F, + 0x8AC2, 0x5A10, 0x8AC3, 0x5A12, 0x8AC4, 0x5A14, 0x8AC5, 0x5A15, 0x8AC6, 0x5A16, 0x8AC7, 0x5A17, 0x8AC8, 0x5A19, 0x8AC9, 0x5A1A, + 0x8ACA, 0x5A1B, 0x8ACB, 0x5A1D, 0x8ACC, 0x5A1E, 0x8ACD, 0x5A21, 0x8ACE, 0x5A22, 0x8ACF, 0x5A24, 0x8AD0, 0x5A26, 0x8AD1, 0x5A27, + 0x8AD2, 0x5A28, 0x8AD3, 0x5A2A, 0x8AD4, 0x5A2B, 0x8AD5, 0x5A2C, 0x8AD6, 0x5A2D, 0x8AD7, 0x5A2E, 0x8AD8, 0x5A2F, 0x8AD9, 0x5A30, + 0x8ADA, 0x5A33, 0x8ADB, 0x5A35, 0x8ADC, 0x5A37, 0x8ADD, 0x5A38, 0x8ADE, 0x5A39, 0x8ADF, 0x5A3A, 0x8AE0, 0x5A3B, 0x8AE1, 0x5A3D, + 0x8AE2, 0x5A3E, 0x8AE3, 0x5A3F, 0x8AE4, 0x5A41, 0x8AE5, 0x5A42, 0x8AE6, 0x5A43, 0x8AE7, 0x5A44, 0x8AE8, 0x5A45, 0x8AE9, 0x5A47, + 0x8AEA, 0x5A48, 0x8AEB, 0x5A4B, 0x8AEC, 0x5A4C, 0x8AED, 0x5A4D, 0x8AEE, 0x5A4E, 0x8AEF, 0x5A4F, 0x8AF0, 0x5A50, 0x8AF1, 0x5A51, + 0x8AF2, 0x5A52, 0x8AF3, 0x5A53, 0x8AF4, 0x5A54, 0x8AF5, 0x5A56, 0x8AF6, 0x5A57, 0x8AF7, 0x5A58, 0x8AF8, 0x5A59, 0x8AF9, 0x5A5B, + 0x8AFA, 0x5A5C, 0x8AFB, 0x5A5D, 0x8AFC, 0x5A5E, 0x8AFD, 0x5A5F, 0x8AFE, 0x5A60, 0x8B40, 0x5A61, 0x8B41, 0x5A63, 0x8B42, 0x5A64, + 0x8B43, 0x5A65, 0x8B44, 0x5A66, 0x8B45, 0x5A68, 0x8B46, 0x5A69, 0x8B47, 0x5A6B, 0x8B48, 0x5A6C, 0x8B49, 0x5A6D, 0x8B4A, 0x5A6E, + 0x8B4B, 0x5A6F, 0x8B4C, 0x5A70, 0x8B4D, 0x5A71, 0x8B4E, 0x5A72, 0x8B4F, 0x5A73, 0x8B50, 0x5A78, 0x8B51, 0x5A79, 0x8B52, 0x5A7B, + 0x8B53, 0x5A7C, 0x8B54, 0x5A7D, 0x8B55, 0x5A7E, 0x8B56, 0x5A80, 0x8B57, 0x5A81, 0x8B58, 0x5A82, 0x8B59, 0x5A83, 0x8B5A, 0x5A84, + 0x8B5B, 0x5A85, 0x8B5C, 0x5A86, 0x8B5D, 0x5A87, 0x8B5E, 0x5A88, 0x8B5F, 0x5A89, 0x8B60, 0x5A8A, 0x8B61, 0x5A8B, 0x8B62, 0x5A8C, + 0x8B63, 0x5A8D, 0x8B64, 0x5A8E, 0x8B65, 0x5A8F, 0x8B66, 0x5A90, 0x8B67, 0x5A91, 0x8B68, 0x5A93, 0x8B69, 0x5A94, 0x8B6A, 0x5A95, + 0x8B6B, 0x5A96, 0x8B6C, 0x5A97, 0x8B6D, 0x5A98, 0x8B6E, 0x5A99, 0x8B6F, 0x5A9C, 0x8B70, 0x5A9D, 0x8B71, 0x5A9E, 0x8B72, 0x5A9F, + 0x8B73, 0x5AA0, 0x8B74, 0x5AA1, 0x8B75, 0x5AA2, 0x8B76, 0x5AA3, 0x8B77, 0x5AA4, 0x8B78, 0x5AA5, 0x8B79, 0x5AA6, 0x8B7A, 0x5AA7, + 0x8B7B, 0x5AA8, 0x8B7C, 0x5AA9, 0x8B7D, 0x5AAB, 0x8B7E, 0x5AAC, 0x8B80, 0x5AAD, 0x8B81, 0x5AAE, 0x8B82, 0x5AAF, 0x8B83, 0x5AB0, + 0x8B84, 0x5AB1, 0x8B85, 0x5AB4, 0x8B86, 0x5AB6, 0x8B87, 0x5AB7, 0x8B88, 0x5AB9, 0x8B89, 0x5ABA, 0x8B8A, 0x5ABB, 0x8B8B, 0x5ABC, + 0x8B8C, 0x5ABD, 0x8B8D, 0x5ABF, 0x8B8E, 0x5AC0, 0x8B8F, 0x5AC3, 0x8B90, 0x5AC4, 0x8B91, 0x5AC5, 0x8B92, 0x5AC6, 0x8B93, 0x5AC7, + 0x8B94, 0x5AC8, 0x8B95, 0x5ACA, 0x8B96, 0x5ACB, 0x8B97, 0x5ACD, 0x8B98, 0x5ACE, 0x8B99, 0x5ACF, 0x8B9A, 0x5AD0, 0x8B9B, 0x5AD1, + 0x8B9C, 0x5AD3, 0x8B9D, 0x5AD5, 0x8B9E, 0x5AD7, 0x8B9F, 0x5AD9, 0x8BA0, 0x5ADA, 0x8BA1, 0x5ADB, 0x8BA2, 0x5ADD, 0x8BA3, 0x5ADE, + 0x8BA4, 0x5ADF, 0x8BA5, 0x5AE2, 0x8BA6, 0x5AE4, 0x8BA7, 0x5AE5, 0x8BA8, 0x5AE7, 0x8BA9, 0x5AE8, 0x8BAA, 0x5AEA, 0x8BAB, 0x5AEC, + 0x8BAC, 0x5AED, 0x8BAD, 0x5AEE, 0x8BAE, 0x5AEF, 0x8BAF, 0x5AF0, 0x8BB0, 0x5AF2, 0x8BB1, 0x5AF3, 0x8BB2, 0x5AF4, 0x8BB3, 0x5AF5, + 0x8BB4, 0x5AF6, 0x8BB5, 0x5AF7, 0x8BB6, 0x5AF8, 0x8BB7, 0x5AF9, 0x8BB8, 0x5AFA, 0x8BB9, 0x5AFB, 0x8BBA, 0x5AFC, 0x8BBB, 0x5AFD, + 0x8BBC, 0x5AFE, 0x8BBD, 0x5AFF, 0x8BBE, 0x5B00, 0x8BBF, 0x5B01, 0x8BC0, 0x5B02, 0x8BC1, 0x5B03, 0x8BC2, 0x5B04, 0x8BC3, 0x5B05, + 0x8BC4, 0x5B06, 0x8BC5, 0x5B07, 0x8BC6, 0x5B08, 0x8BC7, 0x5B0A, 0x8BC8, 0x5B0B, 0x8BC9, 0x5B0C, 0x8BCA, 0x5B0D, 0x8BCB, 0x5B0E, + 0x8BCC, 0x5B0F, 0x8BCD, 0x5B10, 0x8BCE, 0x5B11, 0x8BCF, 0x5B12, 0x8BD0, 0x5B13, 0x8BD1, 0x5B14, 0x8BD2, 0x5B15, 0x8BD3, 0x5B18, + 0x8BD4, 0x5B19, 0x8BD5, 0x5B1A, 0x8BD6, 0x5B1B, 0x8BD7, 0x5B1C, 0x8BD8, 0x5B1D, 0x8BD9, 0x5B1E, 0x8BDA, 0x5B1F, 0x8BDB, 0x5B20, + 0x8BDC, 0x5B21, 0x8BDD, 0x5B22, 0x8BDE, 0x5B23, 0x8BDF, 0x5B24, 0x8BE0, 0x5B25, 0x8BE1, 0x5B26, 0x8BE2, 0x5B27, 0x8BE3, 0x5B28, + 0x8BE4, 0x5B29, 0x8BE5, 0x5B2A, 0x8BE6, 0x5B2B, 0x8BE7, 0x5B2C, 0x8BE8, 0x5B2D, 0x8BE9, 0x5B2E, 0x8BEA, 0x5B2F, 0x8BEB, 0x5B30, + 0x8BEC, 0x5B31, 0x8BED, 0x5B33, 0x8BEE, 0x5B35, 0x8BEF, 0x5B36, 0x8BF0, 0x5B38, 0x8BF1, 0x5B39, 0x8BF2, 0x5B3A, 0x8BF3, 0x5B3B, + 0x8BF4, 0x5B3C, 0x8BF5, 0x5B3D, 0x8BF6, 0x5B3E, 0x8BF7, 0x5B3F, 0x8BF8, 0x5B41, 0x8BF9, 0x5B42, 0x8BFA, 0x5B43, 0x8BFB, 0x5B44, + 0x8BFC, 0x5B45, 0x8BFD, 0x5B46, 0x8BFE, 0x5B47, 0x8C40, 0x5B48, 0x8C41, 0x5B49, 0x8C42, 0x5B4A, 0x8C43, 0x5B4B, 0x8C44, 0x5B4C, + 0x8C45, 0x5B4D, 0x8C46, 0x5B4E, 0x8C47, 0x5B4F, 0x8C48, 0x5B52, 0x8C49, 0x5B56, 0x8C4A, 0x5B5E, 0x8C4B, 0x5B60, 0x8C4C, 0x5B61, + 0x8C4D, 0x5B67, 0x8C4E, 0x5B68, 0x8C4F, 0x5B6B, 0x8C50, 0x5B6D, 0x8C51, 0x5B6E, 0x8C52, 0x5B6F, 0x8C53, 0x5B72, 0x8C54, 0x5B74, + 0x8C55, 0x5B76, 0x8C56, 0x5B77, 0x8C57, 0x5B78, 0x8C58, 0x5B79, 0x8C59, 0x5B7B, 0x8C5A, 0x5B7C, 0x8C5B, 0x5B7E, 0x8C5C, 0x5B7F, + 0x8C5D, 0x5B82, 0x8C5E, 0x5B86, 0x8C5F, 0x5B8A, 0x8C60, 0x5B8D, 0x8C61, 0x5B8E, 0x8C62, 0x5B90, 0x8C63, 0x5B91, 0x8C64, 0x5B92, + 0x8C65, 0x5B94, 0x8C66, 0x5B96, 0x8C67, 0x5B9F, 0x8C68, 0x5BA7, 0x8C69, 0x5BA8, 0x8C6A, 0x5BA9, 0x8C6B, 0x5BAC, 0x8C6C, 0x5BAD, + 0x8C6D, 0x5BAE, 0x8C6E, 0x5BAF, 0x8C6F, 0x5BB1, 0x8C70, 0x5BB2, 0x8C71, 0x5BB7, 0x8C72, 0x5BBA, 0x8C73, 0x5BBB, 0x8C74, 0x5BBC, + 0x8C75, 0x5BC0, 0x8C76, 0x5BC1, 0x8C77, 0x5BC3, 0x8C78, 0x5BC8, 0x8C79, 0x5BC9, 0x8C7A, 0x5BCA, 0x8C7B, 0x5BCB, 0x8C7C, 0x5BCD, + 0x8C7D, 0x5BCE, 0x8C7E, 0x5BCF, 0x8C80, 0x5BD1, 0x8C81, 0x5BD4, 0x8C82, 0x5BD5, 0x8C83, 0x5BD6, 0x8C84, 0x5BD7, 0x8C85, 0x5BD8, + 0x8C86, 0x5BD9, 0x8C87, 0x5BDA, 0x8C88, 0x5BDB, 0x8C89, 0x5BDC, 0x8C8A, 0x5BE0, 0x8C8B, 0x5BE2, 0x8C8C, 0x5BE3, 0x8C8D, 0x5BE6, + 0x8C8E, 0x5BE7, 0x8C8F, 0x5BE9, 0x8C90, 0x5BEA, 0x8C91, 0x5BEB, 0x8C92, 0x5BEC, 0x8C93, 0x5BED, 0x8C94, 0x5BEF, 0x8C95, 0x5BF1, + 0x8C96, 0x5BF2, 0x8C97, 0x5BF3, 0x8C98, 0x5BF4, 0x8C99, 0x5BF5, 0x8C9A, 0x5BF6, 0x8C9B, 0x5BF7, 0x8C9C, 0x5BFD, 0x8C9D, 0x5BFE, + 0x8C9E, 0x5C00, 0x8C9F, 0x5C02, 0x8CA0, 0x5C03, 0x8CA1, 0x5C05, 0x8CA2, 0x5C07, 0x8CA3, 0x5C08, 0x8CA4, 0x5C0B, 0x8CA5, 0x5C0C, + 0x8CA6, 0x5C0D, 0x8CA7, 0x5C0E, 0x8CA8, 0x5C10, 0x8CA9, 0x5C12, 0x8CAA, 0x5C13, 0x8CAB, 0x5C17, 0x8CAC, 0x5C19, 0x8CAD, 0x5C1B, + 0x8CAE, 0x5C1E, 0x8CAF, 0x5C1F, 0x8CB0, 0x5C20, 0x8CB1, 0x5C21, 0x8CB2, 0x5C23, 0x8CB3, 0x5C26, 0x8CB4, 0x5C28, 0x8CB5, 0x5C29, + 0x8CB6, 0x5C2A, 0x8CB7, 0x5C2B, 0x8CB8, 0x5C2D, 0x8CB9, 0x5C2E, 0x8CBA, 0x5C2F, 0x8CBB, 0x5C30, 0x8CBC, 0x5C32, 0x8CBD, 0x5C33, + 0x8CBE, 0x5C35, 0x8CBF, 0x5C36, 0x8CC0, 0x5C37, 0x8CC1, 0x5C43, 0x8CC2, 0x5C44, 0x8CC3, 0x5C46, 0x8CC4, 0x5C47, 0x8CC5, 0x5C4C, + 0x8CC6, 0x5C4D, 0x8CC7, 0x5C52, 0x8CC8, 0x5C53, 0x8CC9, 0x5C54, 0x8CCA, 0x5C56, 0x8CCB, 0x5C57, 0x8CCC, 0x5C58, 0x8CCD, 0x5C5A, + 0x8CCE, 0x5C5B, 0x8CCF, 0x5C5C, 0x8CD0, 0x5C5D, 0x8CD1, 0x5C5F, 0x8CD2, 0x5C62, 0x8CD3, 0x5C64, 0x8CD4, 0x5C67, 0x8CD5, 0x5C68, + 0x8CD6, 0x5C69, 0x8CD7, 0x5C6A, 0x8CD8, 0x5C6B, 0x8CD9, 0x5C6C, 0x8CDA, 0x5C6D, 0x8CDB, 0x5C70, 0x8CDC, 0x5C72, 0x8CDD, 0x5C73, + 0x8CDE, 0x5C74, 0x8CDF, 0x5C75, 0x8CE0, 0x5C76, 0x8CE1, 0x5C77, 0x8CE2, 0x5C78, 0x8CE3, 0x5C7B, 0x8CE4, 0x5C7C, 0x8CE5, 0x5C7D, + 0x8CE6, 0x5C7E, 0x8CE7, 0x5C80, 0x8CE8, 0x5C83, 0x8CE9, 0x5C84, 0x8CEA, 0x5C85, 0x8CEB, 0x5C86, 0x8CEC, 0x5C87, 0x8CED, 0x5C89, + 0x8CEE, 0x5C8A, 0x8CEF, 0x5C8B, 0x8CF0, 0x5C8E, 0x8CF1, 0x5C8F, 0x8CF2, 0x5C92, 0x8CF3, 0x5C93, 0x8CF4, 0x5C95, 0x8CF5, 0x5C9D, + 0x8CF6, 0x5C9E, 0x8CF7, 0x5C9F, 0x8CF8, 0x5CA0, 0x8CF9, 0x5CA1, 0x8CFA, 0x5CA4, 0x8CFB, 0x5CA5, 0x8CFC, 0x5CA6, 0x8CFD, 0x5CA7, + 0x8CFE, 0x5CA8, 0x8D40, 0x5CAA, 0x8D41, 0x5CAE, 0x8D42, 0x5CAF, 0x8D43, 0x5CB0, 0x8D44, 0x5CB2, 0x8D45, 0x5CB4, 0x8D46, 0x5CB6, + 0x8D47, 0x5CB9, 0x8D48, 0x5CBA, 0x8D49, 0x5CBB, 0x8D4A, 0x5CBC, 0x8D4B, 0x5CBE, 0x8D4C, 0x5CC0, 0x8D4D, 0x5CC2, 0x8D4E, 0x5CC3, + 0x8D4F, 0x5CC5, 0x8D50, 0x5CC6, 0x8D51, 0x5CC7, 0x8D52, 0x5CC8, 0x8D53, 0x5CC9, 0x8D54, 0x5CCA, 0x8D55, 0x5CCC, 0x8D56, 0x5CCD, + 0x8D57, 0x5CCE, 0x8D58, 0x5CCF, 0x8D59, 0x5CD0, 0x8D5A, 0x5CD1, 0x8D5B, 0x5CD3, 0x8D5C, 0x5CD4, 0x8D5D, 0x5CD5, 0x8D5E, 0x5CD6, + 0x8D5F, 0x5CD7, 0x8D60, 0x5CD8, 0x8D61, 0x5CDA, 0x8D62, 0x5CDB, 0x8D63, 0x5CDC, 0x8D64, 0x5CDD, 0x8D65, 0x5CDE, 0x8D66, 0x5CDF, + 0x8D67, 0x5CE0, 0x8D68, 0x5CE2, 0x8D69, 0x5CE3, 0x8D6A, 0x5CE7, 0x8D6B, 0x5CE9, 0x8D6C, 0x5CEB, 0x8D6D, 0x5CEC, 0x8D6E, 0x5CEE, + 0x8D6F, 0x5CEF, 0x8D70, 0x5CF1, 0x8D71, 0x5CF2, 0x8D72, 0x5CF3, 0x8D73, 0x5CF4, 0x8D74, 0x5CF5, 0x8D75, 0x5CF6, 0x8D76, 0x5CF7, + 0x8D77, 0x5CF8, 0x8D78, 0x5CF9, 0x8D79, 0x5CFA, 0x8D7A, 0x5CFC, 0x8D7B, 0x5CFD, 0x8D7C, 0x5CFE, 0x8D7D, 0x5CFF, 0x8D7E, 0x5D00, + 0x8D80, 0x5D01, 0x8D81, 0x5D04, 0x8D82, 0x5D05, 0x8D83, 0x5D08, 0x8D84, 0x5D09, 0x8D85, 0x5D0A, 0x8D86, 0x5D0B, 0x8D87, 0x5D0C, + 0x8D88, 0x5D0D, 0x8D89, 0x5D0F, 0x8D8A, 0x5D10, 0x8D8B, 0x5D11, 0x8D8C, 0x5D12, 0x8D8D, 0x5D13, 0x8D8E, 0x5D15, 0x8D8F, 0x5D17, + 0x8D90, 0x5D18, 0x8D91, 0x5D19, 0x8D92, 0x5D1A, 0x8D93, 0x5D1C, 0x8D94, 0x5D1D, 0x8D95, 0x5D1F, 0x8D96, 0x5D20, 0x8D97, 0x5D21, + 0x8D98, 0x5D22, 0x8D99, 0x5D23, 0x8D9A, 0x5D25, 0x8D9B, 0x5D28, 0x8D9C, 0x5D2A, 0x8D9D, 0x5D2B, 0x8D9E, 0x5D2C, 0x8D9F, 0x5D2F, + 0x8DA0, 0x5D30, 0x8DA1, 0x5D31, 0x8DA2, 0x5D32, 0x8DA3, 0x5D33, 0x8DA4, 0x5D35, 0x8DA5, 0x5D36, 0x8DA6, 0x5D37, 0x8DA7, 0x5D38, + 0x8DA8, 0x5D39, 0x8DA9, 0x5D3A, 0x8DAA, 0x5D3B, 0x8DAB, 0x5D3C, 0x8DAC, 0x5D3F, 0x8DAD, 0x5D40, 0x8DAE, 0x5D41, 0x8DAF, 0x5D42, + 0x8DB0, 0x5D43, 0x8DB1, 0x5D44, 0x8DB2, 0x5D45, 0x8DB3, 0x5D46, 0x8DB4, 0x5D48, 0x8DB5, 0x5D49, 0x8DB6, 0x5D4D, 0x8DB7, 0x5D4E, + 0x8DB8, 0x5D4F, 0x8DB9, 0x5D50, 0x8DBA, 0x5D51, 0x8DBB, 0x5D52, 0x8DBC, 0x5D53, 0x8DBD, 0x5D54, 0x8DBE, 0x5D55, 0x8DBF, 0x5D56, + 0x8DC0, 0x5D57, 0x8DC1, 0x5D59, 0x8DC2, 0x5D5A, 0x8DC3, 0x5D5C, 0x8DC4, 0x5D5E, 0x8DC5, 0x5D5F, 0x8DC6, 0x5D60, 0x8DC7, 0x5D61, + 0x8DC8, 0x5D62, 0x8DC9, 0x5D63, 0x8DCA, 0x5D64, 0x8DCB, 0x5D65, 0x8DCC, 0x5D66, 0x8DCD, 0x5D67, 0x8DCE, 0x5D68, 0x8DCF, 0x5D6A, + 0x8DD0, 0x5D6D, 0x8DD1, 0x5D6E, 0x8DD2, 0x5D70, 0x8DD3, 0x5D71, 0x8DD4, 0x5D72, 0x8DD5, 0x5D73, 0x8DD6, 0x5D75, 0x8DD7, 0x5D76, + 0x8DD8, 0x5D77, 0x8DD9, 0x5D78, 0x8DDA, 0x5D79, 0x8DDB, 0x5D7A, 0x8DDC, 0x5D7B, 0x8DDD, 0x5D7C, 0x8DDE, 0x5D7D, 0x8DDF, 0x5D7E, + 0x8DE0, 0x5D7F, 0x8DE1, 0x5D80, 0x8DE2, 0x5D81, 0x8DE3, 0x5D83, 0x8DE4, 0x5D84, 0x8DE5, 0x5D85, 0x8DE6, 0x5D86, 0x8DE7, 0x5D87, + 0x8DE8, 0x5D88, 0x8DE9, 0x5D89, 0x8DEA, 0x5D8A, 0x8DEB, 0x5D8B, 0x8DEC, 0x5D8C, 0x8DED, 0x5D8D, 0x8DEE, 0x5D8E, 0x8DEF, 0x5D8F, + 0x8DF0, 0x5D90, 0x8DF1, 0x5D91, 0x8DF2, 0x5D92, 0x8DF3, 0x5D93, 0x8DF4, 0x5D94, 0x8DF5, 0x5D95, 0x8DF6, 0x5D96, 0x8DF7, 0x5D97, + 0x8DF8, 0x5D98, 0x8DF9, 0x5D9A, 0x8DFA, 0x5D9B, 0x8DFB, 0x5D9C, 0x8DFC, 0x5D9E, 0x8DFD, 0x5D9F, 0x8DFE, 0x5DA0, 0x8E40, 0x5DA1, + 0x8E41, 0x5DA2, 0x8E42, 0x5DA3, 0x8E43, 0x5DA4, 0x8E44, 0x5DA5, 0x8E45, 0x5DA6, 0x8E46, 0x5DA7, 0x8E47, 0x5DA8, 0x8E48, 0x5DA9, + 0x8E49, 0x5DAA, 0x8E4A, 0x5DAB, 0x8E4B, 0x5DAC, 0x8E4C, 0x5DAD, 0x8E4D, 0x5DAE, 0x8E4E, 0x5DAF, 0x8E4F, 0x5DB0, 0x8E50, 0x5DB1, + 0x8E51, 0x5DB2, 0x8E52, 0x5DB3, 0x8E53, 0x5DB4, 0x8E54, 0x5DB5, 0x8E55, 0x5DB6, 0x8E56, 0x5DB8, 0x8E57, 0x5DB9, 0x8E58, 0x5DBA, + 0x8E59, 0x5DBB, 0x8E5A, 0x5DBC, 0x8E5B, 0x5DBD, 0x8E5C, 0x5DBE, 0x8E5D, 0x5DBF, 0x8E5E, 0x5DC0, 0x8E5F, 0x5DC1, 0x8E60, 0x5DC2, + 0x8E61, 0x5DC3, 0x8E62, 0x5DC4, 0x8E63, 0x5DC6, 0x8E64, 0x5DC7, 0x8E65, 0x5DC8, 0x8E66, 0x5DC9, 0x8E67, 0x5DCA, 0x8E68, 0x5DCB, + 0x8E69, 0x5DCC, 0x8E6A, 0x5DCE, 0x8E6B, 0x5DCF, 0x8E6C, 0x5DD0, 0x8E6D, 0x5DD1, 0x8E6E, 0x5DD2, 0x8E6F, 0x5DD3, 0x8E70, 0x5DD4, + 0x8E71, 0x5DD5, 0x8E72, 0x5DD6, 0x8E73, 0x5DD7, 0x8E74, 0x5DD8, 0x8E75, 0x5DD9, 0x8E76, 0x5DDA, 0x8E77, 0x5DDC, 0x8E78, 0x5DDF, + 0x8E79, 0x5DE0, 0x8E7A, 0x5DE3, 0x8E7B, 0x5DE4, 0x8E7C, 0x5DEA, 0x8E7D, 0x5DEC, 0x8E7E, 0x5DED, 0x8E80, 0x5DF0, 0x8E81, 0x5DF5, + 0x8E82, 0x5DF6, 0x8E83, 0x5DF8, 0x8E84, 0x5DF9, 0x8E85, 0x5DFA, 0x8E86, 0x5DFB, 0x8E87, 0x5DFC, 0x8E88, 0x5DFF, 0x8E89, 0x5E00, + 0x8E8A, 0x5E04, 0x8E8B, 0x5E07, 0x8E8C, 0x5E09, 0x8E8D, 0x5E0A, 0x8E8E, 0x5E0B, 0x8E8F, 0x5E0D, 0x8E90, 0x5E0E, 0x8E91, 0x5E12, + 0x8E92, 0x5E13, 0x8E93, 0x5E17, 0x8E94, 0x5E1E, 0x8E95, 0x5E1F, 0x8E96, 0x5E20, 0x8E97, 0x5E21, 0x8E98, 0x5E22, 0x8E99, 0x5E23, + 0x8E9A, 0x5E24, 0x8E9B, 0x5E25, 0x8E9C, 0x5E28, 0x8E9D, 0x5E29, 0x8E9E, 0x5E2A, 0x8E9F, 0x5E2B, 0x8EA0, 0x5E2C, 0x8EA1, 0x5E2F, + 0x8EA2, 0x5E30, 0x8EA3, 0x5E32, 0x8EA4, 0x5E33, 0x8EA5, 0x5E34, 0x8EA6, 0x5E35, 0x8EA7, 0x5E36, 0x8EA8, 0x5E39, 0x8EA9, 0x5E3A, + 0x8EAA, 0x5E3E, 0x8EAB, 0x5E3F, 0x8EAC, 0x5E40, 0x8EAD, 0x5E41, 0x8EAE, 0x5E43, 0x8EAF, 0x5E46, 0x8EB0, 0x5E47, 0x8EB1, 0x5E48, + 0x8EB2, 0x5E49, 0x8EB3, 0x5E4A, 0x8EB4, 0x5E4B, 0x8EB5, 0x5E4D, 0x8EB6, 0x5E4E, 0x8EB7, 0x5E4F, 0x8EB8, 0x5E50, 0x8EB9, 0x5E51, + 0x8EBA, 0x5E52, 0x8EBB, 0x5E53, 0x8EBC, 0x5E56, 0x8EBD, 0x5E57, 0x8EBE, 0x5E58, 0x8EBF, 0x5E59, 0x8EC0, 0x5E5A, 0x8EC1, 0x5E5C, + 0x8EC2, 0x5E5D, 0x8EC3, 0x5E5F, 0x8EC4, 0x5E60, 0x8EC5, 0x5E63, 0x8EC6, 0x5E64, 0x8EC7, 0x5E65, 0x8EC8, 0x5E66, 0x8EC9, 0x5E67, + 0x8ECA, 0x5E68, 0x8ECB, 0x5E69, 0x8ECC, 0x5E6A, 0x8ECD, 0x5E6B, 0x8ECE, 0x5E6C, 0x8ECF, 0x5E6D, 0x8ED0, 0x5E6E, 0x8ED1, 0x5E6F, + 0x8ED2, 0x5E70, 0x8ED3, 0x5E71, 0x8ED4, 0x5E75, 0x8ED5, 0x5E77, 0x8ED6, 0x5E79, 0x8ED7, 0x5E7E, 0x8ED8, 0x5E81, 0x8ED9, 0x5E82, + 0x8EDA, 0x5E83, 0x8EDB, 0x5E85, 0x8EDC, 0x5E88, 0x8EDD, 0x5E89, 0x8EDE, 0x5E8C, 0x8EDF, 0x5E8D, 0x8EE0, 0x5E8E, 0x8EE1, 0x5E92, + 0x8EE2, 0x5E98, 0x8EE3, 0x5E9B, 0x8EE4, 0x5E9D, 0x8EE5, 0x5EA1, 0x8EE6, 0x5EA2, 0x8EE7, 0x5EA3, 0x8EE8, 0x5EA4, 0x8EE9, 0x5EA8, + 0x8EEA, 0x5EA9, 0x8EEB, 0x5EAA, 0x8EEC, 0x5EAB, 0x8EED, 0x5EAC, 0x8EEE, 0x5EAE, 0x8EEF, 0x5EAF, 0x8EF0, 0x5EB0, 0x8EF1, 0x5EB1, + 0x8EF2, 0x5EB2, 0x8EF3, 0x5EB4, 0x8EF4, 0x5EBA, 0x8EF5, 0x5EBB, 0x8EF6, 0x5EBC, 0x8EF7, 0x5EBD, 0x8EF8, 0x5EBF, 0x8EF9, 0x5EC0, + 0x8EFA, 0x5EC1, 0x8EFB, 0x5EC2, 0x8EFC, 0x5EC3, 0x8EFD, 0x5EC4, 0x8EFE, 0x5EC5, 0x8F40, 0x5EC6, 0x8F41, 0x5EC7, 0x8F42, 0x5EC8, + 0x8F43, 0x5ECB, 0x8F44, 0x5ECC, 0x8F45, 0x5ECD, 0x8F46, 0x5ECE, 0x8F47, 0x5ECF, 0x8F48, 0x5ED0, 0x8F49, 0x5ED4, 0x8F4A, 0x5ED5, + 0x8F4B, 0x5ED7, 0x8F4C, 0x5ED8, 0x8F4D, 0x5ED9, 0x8F4E, 0x5EDA, 0x8F4F, 0x5EDC, 0x8F50, 0x5EDD, 0x8F51, 0x5EDE, 0x8F52, 0x5EDF, + 0x8F53, 0x5EE0, 0x8F54, 0x5EE1, 0x8F55, 0x5EE2, 0x8F56, 0x5EE3, 0x8F57, 0x5EE4, 0x8F58, 0x5EE5, 0x8F59, 0x5EE6, 0x8F5A, 0x5EE7, + 0x8F5B, 0x5EE9, 0x8F5C, 0x5EEB, 0x8F5D, 0x5EEC, 0x8F5E, 0x5EED, 0x8F5F, 0x5EEE, 0x8F60, 0x5EEF, 0x8F61, 0x5EF0, 0x8F62, 0x5EF1, + 0x8F63, 0x5EF2, 0x8F64, 0x5EF3, 0x8F65, 0x5EF5, 0x8F66, 0x5EF8, 0x8F67, 0x5EF9, 0x8F68, 0x5EFB, 0x8F69, 0x5EFC, 0x8F6A, 0x5EFD, + 0x8F6B, 0x5F05, 0x8F6C, 0x5F06, 0x8F6D, 0x5F07, 0x8F6E, 0x5F09, 0x8F6F, 0x5F0C, 0x8F70, 0x5F0D, 0x8F71, 0x5F0E, 0x8F72, 0x5F10, + 0x8F73, 0x5F12, 0x8F74, 0x5F14, 0x8F75, 0x5F16, 0x8F76, 0x5F19, 0x8F77, 0x5F1A, 0x8F78, 0x5F1C, 0x8F79, 0x5F1D, 0x8F7A, 0x5F1E, + 0x8F7B, 0x5F21, 0x8F7C, 0x5F22, 0x8F7D, 0x5F23, 0x8F7E, 0x5F24, 0x8F80, 0x5F28, 0x8F81, 0x5F2B, 0x8F82, 0x5F2C, 0x8F83, 0x5F2E, + 0x8F84, 0x5F30, 0x8F85, 0x5F32, 0x8F86, 0x5F33, 0x8F87, 0x5F34, 0x8F88, 0x5F35, 0x8F89, 0x5F36, 0x8F8A, 0x5F37, 0x8F8B, 0x5F38, + 0x8F8C, 0x5F3B, 0x8F8D, 0x5F3D, 0x8F8E, 0x5F3E, 0x8F8F, 0x5F3F, 0x8F90, 0x5F41, 0x8F91, 0x5F42, 0x8F92, 0x5F43, 0x8F93, 0x5F44, + 0x8F94, 0x5F45, 0x8F95, 0x5F46, 0x8F96, 0x5F47, 0x8F97, 0x5F48, 0x8F98, 0x5F49, 0x8F99, 0x5F4A, 0x8F9A, 0x5F4B, 0x8F9B, 0x5F4C, + 0x8F9C, 0x5F4D, 0x8F9D, 0x5F4E, 0x8F9E, 0x5F4F, 0x8F9F, 0x5F51, 0x8FA0, 0x5F54, 0x8FA1, 0x5F59, 0x8FA2, 0x5F5A, 0x8FA3, 0x5F5B, + 0x8FA4, 0x5F5C, 0x8FA5, 0x5F5E, 0x8FA6, 0x5F5F, 0x8FA7, 0x5F60, 0x8FA8, 0x5F63, 0x8FA9, 0x5F65, 0x8FAA, 0x5F67, 0x8FAB, 0x5F68, + 0x8FAC, 0x5F6B, 0x8FAD, 0x5F6E, 0x8FAE, 0x5F6F, 0x8FAF, 0x5F72, 0x8FB0, 0x5F74, 0x8FB1, 0x5F75, 0x8FB2, 0x5F76, 0x8FB3, 0x5F78, + 0x8FB4, 0x5F7A, 0x8FB5, 0x5F7D, 0x8FB6, 0x5F7E, 0x8FB7, 0x5F7F, 0x8FB8, 0x5F83, 0x8FB9, 0x5F86, 0x8FBA, 0x5F8D, 0x8FBB, 0x5F8E, + 0x8FBC, 0x5F8F, 0x8FBD, 0x5F91, 0x8FBE, 0x5F93, 0x8FBF, 0x5F94, 0x8FC0, 0x5F96, 0x8FC1, 0x5F9A, 0x8FC2, 0x5F9B, 0x8FC3, 0x5F9D, + 0x8FC4, 0x5F9E, 0x8FC5, 0x5F9F, 0x8FC6, 0x5FA0, 0x8FC7, 0x5FA2, 0x8FC8, 0x5FA3, 0x8FC9, 0x5FA4, 0x8FCA, 0x5FA5, 0x8FCB, 0x5FA6, + 0x8FCC, 0x5FA7, 0x8FCD, 0x5FA9, 0x8FCE, 0x5FAB, 0x8FCF, 0x5FAC, 0x8FD0, 0x5FAF, 0x8FD1, 0x5FB0, 0x8FD2, 0x5FB1, 0x8FD3, 0x5FB2, + 0x8FD4, 0x5FB3, 0x8FD5, 0x5FB4, 0x8FD6, 0x5FB6, 0x8FD7, 0x5FB8, 0x8FD8, 0x5FB9, 0x8FD9, 0x5FBA, 0x8FDA, 0x5FBB, 0x8FDB, 0x5FBE, + 0x8FDC, 0x5FBF, 0x8FDD, 0x5FC0, 0x8FDE, 0x5FC1, 0x8FDF, 0x5FC2, 0x8FE0, 0x5FC7, 0x8FE1, 0x5FC8, 0x8FE2, 0x5FCA, 0x8FE3, 0x5FCB, + 0x8FE4, 0x5FCE, 0x8FE5, 0x5FD3, 0x8FE6, 0x5FD4, 0x8FE7, 0x5FD5, 0x8FE8, 0x5FDA, 0x8FE9, 0x5FDB, 0x8FEA, 0x5FDC, 0x8FEB, 0x5FDE, + 0x8FEC, 0x5FDF, 0x8FED, 0x5FE2, 0x8FEE, 0x5FE3, 0x8FEF, 0x5FE5, 0x8FF0, 0x5FE6, 0x8FF1, 0x5FE8, 0x8FF2, 0x5FE9, 0x8FF3, 0x5FEC, + 0x8FF4, 0x5FEF, 0x8FF5, 0x5FF0, 0x8FF6, 0x5FF2, 0x8FF7, 0x5FF3, 0x8FF8, 0x5FF4, 0x8FF9, 0x5FF6, 0x8FFA, 0x5FF7, 0x8FFB, 0x5FF9, + 0x8FFC, 0x5FFA, 0x8FFD, 0x5FFC, 0x8FFE, 0x6007, 0x9040, 0x6008, 0x9041, 0x6009, 0x9042, 0x600B, 0x9043, 0x600C, 0x9044, 0x6010, + 0x9045, 0x6011, 0x9046, 0x6013, 0x9047, 0x6017, 0x9048, 0x6018, 0x9049, 0x601A, 0x904A, 0x601E, 0x904B, 0x601F, 0x904C, 0x6022, + 0x904D, 0x6023, 0x904E, 0x6024, 0x904F, 0x602C, 0x9050, 0x602D, 0x9051, 0x602E, 0x9052, 0x6030, 0x9053, 0x6031, 0x9054, 0x6032, + 0x9055, 0x6033, 0x9056, 0x6034, 0x9057, 0x6036, 0x9058, 0x6037, 0x9059, 0x6038, 0x905A, 0x6039, 0x905B, 0x603A, 0x905C, 0x603D, + 0x905D, 0x603E, 0x905E, 0x6040, 0x905F, 0x6044, 0x9060, 0x6045, 0x9061, 0x6046, 0x9062, 0x6047, 0x9063, 0x6048, 0x9064, 0x6049, + 0x9065, 0x604A, 0x9066, 0x604C, 0x9067, 0x604E, 0x9068, 0x604F, 0x9069, 0x6051, 0x906A, 0x6053, 0x906B, 0x6054, 0x906C, 0x6056, + 0x906D, 0x6057, 0x906E, 0x6058, 0x906F, 0x605B, 0x9070, 0x605C, 0x9071, 0x605E, 0x9072, 0x605F, 0x9073, 0x6060, 0x9074, 0x6061, + 0x9075, 0x6065, 0x9076, 0x6066, 0x9077, 0x606E, 0x9078, 0x6071, 0x9079, 0x6072, 0x907A, 0x6074, 0x907B, 0x6075, 0x907C, 0x6077, + 0x907D, 0x607E, 0x907E, 0x6080, 0x9080, 0x6081, 0x9081, 0x6082, 0x9082, 0x6085, 0x9083, 0x6086, 0x9084, 0x6087, 0x9085, 0x6088, + 0x9086, 0x608A, 0x9087, 0x608B, 0x9088, 0x608E, 0x9089, 0x608F, 0x908A, 0x6090, 0x908B, 0x6091, 0x908C, 0x6093, 0x908D, 0x6095, + 0x908E, 0x6097, 0x908F, 0x6098, 0x9090, 0x6099, 0x9091, 0x609C, 0x9092, 0x609E, 0x9093, 0x60A1, 0x9094, 0x60A2, 0x9095, 0x60A4, + 0x9096, 0x60A5, 0x9097, 0x60A7, 0x9098, 0x60A9, 0x9099, 0x60AA, 0x909A, 0x60AE, 0x909B, 0x60B0, 0x909C, 0x60B3, 0x909D, 0x60B5, + 0x909E, 0x60B6, 0x909F, 0x60B7, 0x90A0, 0x60B9, 0x90A1, 0x60BA, 0x90A2, 0x60BD, 0x90A3, 0x60BE, 0x90A4, 0x60BF, 0x90A5, 0x60C0, + 0x90A6, 0x60C1, 0x90A7, 0x60C2, 0x90A8, 0x60C3, 0x90A9, 0x60C4, 0x90AA, 0x60C7, 0x90AB, 0x60C8, 0x90AC, 0x60C9, 0x90AD, 0x60CC, + 0x90AE, 0x60CD, 0x90AF, 0x60CE, 0x90B0, 0x60CF, 0x90B1, 0x60D0, 0x90B2, 0x60D2, 0x90B3, 0x60D3, 0x90B4, 0x60D4, 0x90B5, 0x60D6, + 0x90B6, 0x60D7, 0x90B7, 0x60D9, 0x90B8, 0x60DB, 0x90B9, 0x60DE, 0x90BA, 0x60E1, 0x90BB, 0x60E2, 0x90BC, 0x60E3, 0x90BD, 0x60E4, + 0x90BE, 0x60E5, 0x90BF, 0x60EA, 0x90C0, 0x60F1, 0x90C1, 0x60F2, 0x90C2, 0x60F5, 0x90C3, 0x60F7, 0x90C4, 0x60F8, 0x90C5, 0x60FB, + 0x90C6, 0x60FC, 0x90C7, 0x60FD, 0x90C8, 0x60FE, 0x90C9, 0x60FF, 0x90CA, 0x6102, 0x90CB, 0x6103, 0x90CC, 0x6104, 0x90CD, 0x6105, + 0x90CE, 0x6107, 0x90CF, 0x610A, 0x90D0, 0x610B, 0x90D1, 0x610C, 0x90D2, 0x6110, 0x90D3, 0x6111, 0x90D4, 0x6112, 0x90D5, 0x6113, + 0x90D6, 0x6114, 0x90D7, 0x6116, 0x90D8, 0x6117, 0x90D9, 0x6118, 0x90DA, 0x6119, 0x90DB, 0x611B, 0x90DC, 0x611C, 0x90DD, 0x611D, + 0x90DE, 0x611E, 0x90DF, 0x6121, 0x90E0, 0x6122, 0x90E1, 0x6125, 0x90E2, 0x6128, 0x90E3, 0x6129, 0x90E4, 0x612A, 0x90E5, 0x612C, + 0x90E6, 0x612D, 0x90E7, 0x612E, 0x90E8, 0x612F, 0x90E9, 0x6130, 0x90EA, 0x6131, 0x90EB, 0x6132, 0x90EC, 0x6133, 0x90ED, 0x6134, + 0x90EE, 0x6135, 0x90EF, 0x6136, 0x90F0, 0x6137, 0x90F1, 0x6138, 0x90F2, 0x6139, 0x90F3, 0x613A, 0x90F4, 0x613B, 0x90F5, 0x613C, + 0x90F6, 0x613D, 0x90F7, 0x613E, 0x90F8, 0x6140, 0x90F9, 0x6141, 0x90FA, 0x6142, 0x90FB, 0x6143, 0x90FC, 0x6144, 0x90FD, 0x6145, + 0x90FE, 0x6146, 0x9140, 0x6147, 0x9141, 0x6149, 0x9142, 0x614B, 0x9143, 0x614D, 0x9144, 0x614F, 0x9145, 0x6150, 0x9146, 0x6152, + 0x9147, 0x6153, 0x9148, 0x6154, 0x9149, 0x6156, 0x914A, 0x6157, 0x914B, 0x6158, 0x914C, 0x6159, 0x914D, 0x615A, 0x914E, 0x615B, + 0x914F, 0x615C, 0x9150, 0x615E, 0x9151, 0x615F, 0x9152, 0x6160, 0x9153, 0x6161, 0x9154, 0x6163, 0x9155, 0x6164, 0x9156, 0x6165, + 0x9157, 0x6166, 0x9158, 0x6169, 0x9159, 0x616A, 0x915A, 0x616B, 0x915B, 0x616C, 0x915C, 0x616D, 0x915D, 0x616E, 0x915E, 0x616F, + 0x915F, 0x6171, 0x9160, 0x6172, 0x9161, 0x6173, 0x9162, 0x6174, 0x9163, 0x6176, 0x9164, 0x6178, 0x9165, 0x6179, 0x9166, 0x617A, + 0x9167, 0x617B, 0x9168, 0x617C, 0x9169, 0x617D, 0x916A, 0x617E, 0x916B, 0x617F, 0x916C, 0x6180, 0x916D, 0x6181, 0x916E, 0x6182, + 0x916F, 0x6183, 0x9170, 0x6184, 0x9171, 0x6185, 0x9172, 0x6186, 0x9173, 0x6187, 0x9174, 0x6188, 0x9175, 0x6189, 0x9176, 0x618A, + 0x9177, 0x618C, 0x9178, 0x618D, 0x9179, 0x618F, 0x917A, 0x6190, 0x917B, 0x6191, 0x917C, 0x6192, 0x917D, 0x6193, 0x917E, 0x6195, + 0x9180, 0x6196, 0x9181, 0x6197, 0x9182, 0x6198, 0x9183, 0x6199, 0x9184, 0x619A, 0x9185, 0x619B, 0x9186, 0x619C, 0x9187, 0x619E, + 0x9188, 0x619F, 0x9189, 0x61A0, 0x918A, 0x61A1, 0x918B, 0x61A2, 0x918C, 0x61A3, 0x918D, 0x61A4, 0x918E, 0x61A5, 0x918F, 0x61A6, + 0x9190, 0x61AA, 0x9191, 0x61AB, 0x9192, 0x61AD, 0x9193, 0x61AE, 0x9194, 0x61AF, 0x9195, 0x61B0, 0x9196, 0x61B1, 0x9197, 0x61B2, + 0x9198, 0x61B3, 0x9199, 0x61B4, 0x919A, 0x61B5, 0x919B, 0x61B6, 0x919C, 0x61B8, 0x919D, 0x61B9, 0x919E, 0x61BA, 0x919F, 0x61BB, + 0x91A0, 0x61BC, 0x91A1, 0x61BD, 0x91A2, 0x61BF, 0x91A3, 0x61C0, 0x91A4, 0x61C1, 0x91A5, 0x61C3, 0x91A6, 0x61C4, 0x91A7, 0x61C5, + 0x91A8, 0x61C6, 0x91A9, 0x61C7, 0x91AA, 0x61C9, 0x91AB, 0x61CC, 0x91AC, 0x61CD, 0x91AD, 0x61CE, 0x91AE, 0x61CF, 0x91AF, 0x61D0, + 0x91B0, 0x61D3, 0x91B1, 0x61D5, 0x91B2, 0x61D6, 0x91B3, 0x61D7, 0x91B4, 0x61D8, 0x91B5, 0x61D9, 0x91B6, 0x61DA, 0x91B7, 0x61DB, + 0x91B8, 0x61DC, 0x91B9, 0x61DD, 0x91BA, 0x61DE, 0x91BB, 0x61DF, 0x91BC, 0x61E0, 0x91BD, 0x61E1, 0x91BE, 0x61E2, 0x91BF, 0x61E3, + 0x91C0, 0x61E4, 0x91C1, 0x61E5, 0x91C2, 0x61E7, 0x91C3, 0x61E8, 0x91C4, 0x61E9, 0x91C5, 0x61EA, 0x91C6, 0x61EB, 0x91C7, 0x61EC, + 0x91C8, 0x61ED, 0x91C9, 0x61EE, 0x91CA, 0x61EF, 0x91CB, 0x61F0, 0x91CC, 0x61F1, 0x91CD, 0x61F2, 0x91CE, 0x61F3, 0x91CF, 0x61F4, + 0x91D0, 0x61F6, 0x91D1, 0x61F7, 0x91D2, 0x61F8, 0x91D3, 0x61F9, 0x91D4, 0x61FA, 0x91D5, 0x61FB, 0x91D6, 0x61FC, 0x91D7, 0x61FD, + 0x91D8, 0x61FE, 0x91D9, 0x6200, 0x91DA, 0x6201, 0x91DB, 0x6202, 0x91DC, 0x6203, 0x91DD, 0x6204, 0x91DE, 0x6205, 0x91DF, 0x6207, + 0x91E0, 0x6209, 0x91E1, 0x6213, 0x91E2, 0x6214, 0x91E3, 0x6219, 0x91E4, 0x621C, 0x91E5, 0x621D, 0x91E6, 0x621E, 0x91E7, 0x6220, + 0x91E8, 0x6223, 0x91E9, 0x6226, 0x91EA, 0x6227, 0x91EB, 0x6228, 0x91EC, 0x6229, 0x91ED, 0x622B, 0x91EE, 0x622D, 0x91EF, 0x622F, + 0x91F0, 0x6230, 0x91F1, 0x6231, 0x91F2, 0x6232, 0x91F3, 0x6235, 0x91F4, 0x6236, 0x91F5, 0x6238, 0x91F6, 0x6239, 0x91F7, 0x623A, + 0x91F8, 0x623B, 0x91F9, 0x623C, 0x91FA, 0x6242, 0x91FB, 0x6244, 0x91FC, 0x6245, 0x91FD, 0x6246, 0x91FE, 0x624A, 0x9240, 0x624F, + 0x9241, 0x6250, 0x9242, 0x6255, 0x9243, 0x6256, 0x9244, 0x6257, 0x9245, 0x6259, 0x9246, 0x625A, 0x9247, 0x625C, 0x9248, 0x625D, + 0x9249, 0x625E, 0x924A, 0x625F, 0x924B, 0x6260, 0x924C, 0x6261, 0x924D, 0x6262, 0x924E, 0x6264, 0x924F, 0x6265, 0x9250, 0x6268, + 0x9251, 0x6271, 0x9252, 0x6272, 0x9253, 0x6274, 0x9254, 0x6275, 0x9255, 0x6277, 0x9256, 0x6278, 0x9257, 0x627A, 0x9258, 0x627B, + 0x9259, 0x627D, 0x925A, 0x6281, 0x925B, 0x6282, 0x925C, 0x6283, 0x925D, 0x6285, 0x925E, 0x6286, 0x925F, 0x6287, 0x9260, 0x6288, + 0x9261, 0x628B, 0x9262, 0x628C, 0x9263, 0x628D, 0x9264, 0x628E, 0x9265, 0x628F, 0x9266, 0x6290, 0x9267, 0x6294, 0x9268, 0x6299, + 0x9269, 0x629C, 0x926A, 0x629D, 0x926B, 0x629E, 0x926C, 0x62A3, 0x926D, 0x62A6, 0x926E, 0x62A7, 0x926F, 0x62A9, 0x9270, 0x62AA, + 0x9271, 0x62AD, 0x9272, 0x62AE, 0x9273, 0x62AF, 0x9274, 0x62B0, 0x9275, 0x62B2, 0x9276, 0x62B3, 0x9277, 0x62B4, 0x9278, 0x62B6, + 0x9279, 0x62B7, 0x927A, 0x62B8, 0x927B, 0x62BA, 0x927C, 0x62BE, 0x927D, 0x62C0, 0x927E, 0x62C1, 0x9280, 0x62C3, 0x9281, 0x62CB, + 0x9282, 0x62CF, 0x9283, 0x62D1, 0x9284, 0x62D5, 0x9285, 0x62DD, 0x9286, 0x62DE, 0x9287, 0x62E0, 0x9288, 0x62E1, 0x9289, 0x62E4, + 0x928A, 0x62EA, 0x928B, 0x62EB, 0x928C, 0x62F0, 0x928D, 0x62F2, 0x928E, 0x62F5, 0x928F, 0x62F8, 0x9290, 0x62F9, 0x9291, 0x62FA, + 0x9292, 0x62FB, 0x9293, 0x6300, 0x9294, 0x6303, 0x9295, 0x6304, 0x9296, 0x6305, 0x9297, 0x6306, 0x9298, 0x630A, 0x9299, 0x630B, + 0x929A, 0x630C, 0x929B, 0x630D, 0x929C, 0x630F, 0x929D, 0x6310, 0x929E, 0x6312, 0x929F, 0x6313, 0x92A0, 0x6314, 0x92A1, 0x6315, + 0x92A2, 0x6317, 0x92A3, 0x6318, 0x92A4, 0x6319, 0x92A5, 0x631C, 0x92A6, 0x6326, 0x92A7, 0x6327, 0x92A8, 0x6329, 0x92A9, 0x632C, + 0x92AA, 0x632D, 0x92AB, 0x632E, 0x92AC, 0x6330, 0x92AD, 0x6331, 0x92AE, 0x6333, 0x92AF, 0x6334, 0x92B0, 0x6335, 0x92B1, 0x6336, + 0x92B2, 0x6337, 0x92B3, 0x6338, 0x92B4, 0x633B, 0x92B5, 0x633C, 0x92B6, 0x633E, 0x92B7, 0x633F, 0x92B8, 0x6340, 0x92B9, 0x6341, + 0x92BA, 0x6344, 0x92BB, 0x6347, 0x92BC, 0x6348, 0x92BD, 0x634A, 0x92BE, 0x6351, 0x92BF, 0x6352, 0x92C0, 0x6353, 0x92C1, 0x6354, + 0x92C2, 0x6356, 0x92C3, 0x6357, 0x92C4, 0x6358, 0x92C5, 0x6359, 0x92C6, 0x635A, 0x92C7, 0x635B, 0x92C8, 0x635C, 0x92C9, 0x635D, + 0x92CA, 0x6360, 0x92CB, 0x6364, 0x92CC, 0x6365, 0x92CD, 0x6366, 0x92CE, 0x6368, 0x92CF, 0x636A, 0x92D0, 0x636B, 0x92D1, 0x636C, + 0x92D2, 0x636F, 0x92D3, 0x6370, 0x92D4, 0x6372, 0x92D5, 0x6373, 0x92D6, 0x6374, 0x92D7, 0x6375, 0x92D8, 0x6378, 0x92D9, 0x6379, + 0x92DA, 0x637C, 0x92DB, 0x637D, 0x92DC, 0x637E, 0x92DD, 0x637F, 0x92DE, 0x6381, 0x92DF, 0x6383, 0x92E0, 0x6384, 0x92E1, 0x6385, + 0x92E2, 0x6386, 0x92E3, 0x638B, 0x92E4, 0x638D, 0x92E5, 0x6391, 0x92E6, 0x6393, 0x92E7, 0x6394, 0x92E8, 0x6395, 0x92E9, 0x6397, + 0x92EA, 0x6399, 0x92EB, 0x639A, 0x92EC, 0x639B, 0x92ED, 0x639C, 0x92EE, 0x639D, 0x92EF, 0x639E, 0x92F0, 0x639F, 0x92F1, 0x63A1, + 0x92F2, 0x63A4, 0x92F3, 0x63A6, 0x92F4, 0x63AB, 0x92F5, 0x63AF, 0x92F6, 0x63B1, 0x92F7, 0x63B2, 0x92F8, 0x63B5, 0x92F9, 0x63B6, + 0x92FA, 0x63B9, 0x92FB, 0x63BB, 0x92FC, 0x63BD, 0x92FD, 0x63BF, 0x92FE, 0x63C0, 0x9340, 0x63C1, 0x9341, 0x63C2, 0x9342, 0x63C3, + 0x9343, 0x63C5, 0x9344, 0x63C7, 0x9345, 0x63C8, 0x9346, 0x63CA, 0x9347, 0x63CB, 0x9348, 0x63CC, 0x9349, 0x63D1, 0x934A, 0x63D3, + 0x934B, 0x63D4, 0x934C, 0x63D5, 0x934D, 0x63D7, 0x934E, 0x63D8, 0x934F, 0x63D9, 0x9350, 0x63DA, 0x9351, 0x63DB, 0x9352, 0x63DC, + 0x9353, 0x63DD, 0x9354, 0x63DF, 0x9355, 0x63E2, 0x9356, 0x63E4, 0x9357, 0x63E5, 0x9358, 0x63E6, 0x9359, 0x63E7, 0x935A, 0x63E8, + 0x935B, 0x63EB, 0x935C, 0x63EC, 0x935D, 0x63EE, 0x935E, 0x63EF, 0x935F, 0x63F0, 0x9360, 0x63F1, 0x9361, 0x63F3, 0x9362, 0x63F5, + 0x9363, 0x63F7, 0x9364, 0x63F9, 0x9365, 0x63FA, 0x9366, 0x63FB, 0x9367, 0x63FC, 0x9368, 0x63FE, 0x9369, 0x6403, 0x936A, 0x6404, + 0x936B, 0x6406, 0x936C, 0x6407, 0x936D, 0x6408, 0x936E, 0x6409, 0x936F, 0x640A, 0x9370, 0x640D, 0x9371, 0x640E, 0x9372, 0x6411, + 0x9373, 0x6412, 0x9374, 0x6415, 0x9375, 0x6416, 0x9376, 0x6417, 0x9377, 0x6418, 0x9378, 0x6419, 0x9379, 0x641A, 0x937A, 0x641D, + 0x937B, 0x641F, 0x937C, 0x6422, 0x937D, 0x6423, 0x937E, 0x6424, 0x9380, 0x6425, 0x9381, 0x6427, 0x9382, 0x6428, 0x9383, 0x6429, + 0x9384, 0x642B, 0x9385, 0x642E, 0x9386, 0x642F, 0x9387, 0x6430, 0x9388, 0x6431, 0x9389, 0x6432, 0x938A, 0x6433, 0x938B, 0x6435, + 0x938C, 0x6436, 0x938D, 0x6437, 0x938E, 0x6438, 0x938F, 0x6439, 0x9390, 0x643B, 0x9391, 0x643C, 0x9392, 0x643E, 0x9393, 0x6440, + 0x9394, 0x6442, 0x9395, 0x6443, 0x9396, 0x6449, 0x9397, 0x644B, 0x9398, 0x644C, 0x9399, 0x644D, 0x939A, 0x644E, 0x939B, 0x644F, + 0x939C, 0x6450, 0x939D, 0x6451, 0x939E, 0x6453, 0x939F, 0x6455, 0x93A0, 0x6456, 0x93A1, 0x6457, 0x93A2, 0x6459, 0x93A3, 0x645A, + 0x93A4, 0x645B, 0x93A5, 0x645C, 0x93A6, 0x645D, 0x93A7, 0x645F, 0x93A8, 0x6460, 0x93A9, 0x6461, 0x93AA, 0x6462, 0x93AB, 0x6463, + 0x93AC, 0x6464, 0x93AD, 0x6465, 0x93AE, 0x6466, 0x93AF, 0x6468, 0x93B0, 0x646A, 0x93B1, 0x646B, 0x93B2, 0x646C, 0x93B3, 0x646E, + 0x93B4, 0x646F, 0x93B5, 0x6470, 0x93B6, 0x6471, 0x93B7, 0x6472, 0x93B8, 0x6473, 0x93B9, 0x6474, 0x93BA, 0x6475, 0x93BB, 0x6476, + 0x93BC, 0x6477, 0x93BD, 0x647B, 0x93BE, 0x647C, 0x93BF, 0x647D, 0x93C0, 0x647E, 0x93C1, 0x647F, 0x93C2, 0x6480, 0x93C3, 0x6481, + 0x93C4, 0x6483, 0x93C5, 0x6486, 0x93C6, 0x6488, 0x93C7, 0x6489, 0x93C8, 0x648A, 0x93C9, 0x648B, 0x93CA, 0x648C, 0x93CB, 0x648D, + 0x93CC, 0x648E, 0x93CD, 0x648F, 0x93CE, 0x6490, 0x93CF, 0x6493, 0x93D0, 0x6494, 0x93D1, 0x6497, 0x93D2, 0x6498, 0x93D3, 0x649A, + 0x93D4, 0x649B, 0x93D5, 0x649C, 0x93D6, 0x649D, 0x93D7, 0x649F, 0x93D8, 0x64A0, 0x93D9, 0x64A1, 0x93DA, 0x64A2, 0x93DB, 0x64A3, + 0x93DC, 0x64A5, 0x93DD, 0x64A6, 0x93DE, 0x64A7, 0x93DF, 0x64A8, 0x93E0, 0x64AA, 0x93E1, 0x64AB, 0x93E2, 0x64AF, 0x93E3, 0x64B1, + 0x93E4, 0x64B2, 0x93E5, 0x64B3, 0x93E6, 0x64B4, 0x93E7, 0x64B6, 0x93E8, 0x64B9, 0x93E9, 0x64BB, 0x93EA, 0x64BD, 0x93EB, 0x64BE, + 0x93EC, 0x64BF, 0x93ED, 0x64C1, 0x93EE, 0x64C3, 0x93EF, 0x64C4, 0x93F0, 0x64C6, 0x93F1, 0x64C7, 0x93F2, 0x64C8, 0x93F3, 0x64C9, + 0x93F4, 0x64CA, 0x93F5, 0x64CB, 0x93F6, 0x64CC, 0x93F7, 0x64CF, 0x93F8, 0x64D1, 0x93F9, 0x64D3, 0x93FA, 0x64D4, 0x93FB, 0x64D5, + 0x93FC, 0x64D6, 0x93FD, 0x64D9, 0x93FE, 0x64DA, 0x9440, 0x64DB, 0x9441, 0x64DC, 0x9442, 0x64DD, 0x9443, 0x64DF, 0x9444, 0x64E0, + 0x9445, 0x64E1, 0x9446, 0x64E3, 0x9447, 0x64E5, 0x9448, 0x64E7, 0x9449, 0x64E8, 0x944A, 0x64E9, 0x944B, 0x64EA, 0x944C, 0x64EB, + 0x944D, 0x64EC, 0x944E, 0x64ED, 0x944F, 0x64EE, 0x9450, 0x64EF, 0x9451, 0x64F0, 0x9452, 0x64F1, 0x9453, 0x64F2, 0x9454, 0x64F3, + 0x9455, 0x64F4, 0x9456, 0x64F5, 0x9457, 0x64F6, 0x9458, 0x64F7, 0x9459, 0x64F8, 0x945A, 0x64F9, 0x945B, 0x64FA, 0x945C, 0x64FB, + 0x945D, 0x64FC, 0x945E, 0x64FD, 0x945F, 0x64FE, 0x9460, 0x64FF, 0x9461, 0x6501, 0x9462, 0x6502, 0x9463, 0x6503, 0x9464, 0x6504, + 0x9465, 0x6505, 0x9466, 0x6506, 0x9467, 0x6507, 0x9468, 0x6508, 0x9469, 0x650A, 0x946A, 0x650B, 0x946B, 0x650C, 0x946C, 0x650D, + 0x946D, 0x650E, 0x946E, 0x650F, 0x946F, 0x6510, 0x9470, 0x6511, 0x9471, 0x6513, 0x9472, 0x6514, 0x9473, 0x6515, 0x9474, 0x6516, + 0x9475, 0x6517, 0x9476, 0x6519, 0x9477, 0x651A, 0x9478, 0x651B, 0x9479, 0x651C, 0x947A, 0x651D, 0x947B, 0x651E, 0x947C, 0x651F, + 0x947D, 0x6520, 0x947E, 0x6521, 0x9480, 0x6522, 0x9481, 0x6523, 0x9482, 0x6524, 0x9483, 0x6526, 0x9484, 0x6527, 0x9485, 0x6528, + 0x9486, 0x6529, 0x9487, 0x652A, 0x9488, 0x652C, 0x9489, 0x652D, 0x948A, 0x6530, 0x948B, 0x6531, 0x948C, 0x6532, 0x948D, 0x6533, + 0x948E, 0x6537, 0x948F, 0x653A, 0x9490, 0x653C, 0x9491, 0x653D, 0x9492, 0x6540, 0x9493, 0x6541, 0x9494, 0x6542, 0x9495, 0x6543, + 0x9496, 0x6544, 0x9497, 0x6546, 0x9498, 0x6547, 0x9499, 0x654A, 0x949A, 0x654B, 0x949B, 0x654D, 0x949C, 0x654E, 0x949D, 0x6550, + 0x949E, 0x6552, 0x949F, 0x6553, 0x94A0, 0x6554, 0x94A1, 0x6557, 0x94A2, 0x6558, 0x94A3, 0x655A, 0x94A4, 0x655C, 0x94A5, 0x655F, + 0x94A6, 0x6560, 0x94A7, 0x6561, 0x94A8, 0x6564, 0x94A9, 0x6565, 0x94AA, 0x6567, 0x94AB, 0x6568, 0x94AC, 0x6569, 0x94AD, 0x656A, + 0x94AE, 0x656D, 0x94AF, 0x656E, 0x94B0, 0x656F, 0x94B1, 0x6571, 0x94B2, 0x6573, 0x94B3, 0x6575, 0x94B4, 0x6576, 0x94B5, 0x6578, + 0x94B6, 0x6579, 0x94B7, 0x657A, 0x94B8, 0x657B, 0x94B9, 0x657C, 0x94BA, 0x657D, 0x94BB, 0x657E, 0x94BC, 0x657F, 0x94BD, 0x6580, + 0x94BE, 0x6581, 0x94BF, 0x6582, 0x94C0, 0x6583, 0x94C1, 0x6584, 0x94C2, 0x6585, 0x94C3, 0x6586, 0x94C4, 0x6588, 0x94C5, 0x6589, + 0x94C6, 0x658A, 0x94C7, 0x658D, 0x94C8, 0x658E, 0x94C9, 0x658F, 0x94CA, 0x6592, 0x94CB, 0x6594, 0x94CC, 0x6595, 0x94CD, 0x6596, + 0x94CE, 0x6598, 0x94CF, 0x659A, 0x94D0, 0x659D, 0x94D1, 0x659E, 0x94D2, 0x65A0, 0x94D3, 0x65A2, 0x94D4, 0x65A3, 0x94D5, 0x65A6, + 0x94D6, 0x65A8, 0x94D7, 0x65AA, 0x94D8, 0x65AC, 0x94D9, 0x65AE, 0x94DA, 0x65B1, 0x94DB, 0x65B2, 0x94DC, 0x65B3, 0x94DD, 0x65B4, + 0x94DE, 0x65B5, 0x94DF, 0x65B6, 0x94E0, 0x65B7, 0x94E1, 0x65B8, 0x94E2, 0x65BA, 0x94E3, 0x65BB, 0x94E4, 0x65BE, 0x94E5, 0x65BF, + 0x94E6, 0x65C0, 0x94E7, 0x65C2, 0x94E8, 0x65C7, 0x94E9, 0x65C8, 0x94EA, 0x65C9, 0x94EB, 0x65CA, 0x94EC, 0x65CD, 0x94ED, 0x65D0, + 0x94EE, 0x65D1, 0x94EF, 0x65D3, 0x94F0, 0x65D4, 0x94F1, 0x65D5, 0x94F2, 0x65D8, 0x94F3, 0x65D9, 0x94F4, 0x65DA, 0x94F5, 0x65DB, + 0x94F6, 0x65DC, 0x94F7, 0x65DD, 0x94F8, 0x65DE, 0x94F9, 0x65DF, 0x94FA, 0x65E1, 0x94FB, 0x65E3, 0x94FC, 0x65E4, 0x94FD, 0x65EA, + 0x94FE, 0x65EB, 0x9540, 0x65F2, 0x9541, 0x65F3, 0x9542, 0x65F4, 0x9543, 0x65F5, 0x9544, 0x65F8, 0x9545, 0x65F9, 0x9546, 0x65FB, + 0x9547, 0x65FC, 0x9548, 0x65FD, 0x9549, 0x65FE, 0x954A, 0x65FF, 0x954B, 0x6601, 0x954C, 0x6604, 0x954D, 0x6605, 0x954E, 0x6607, + 0x954F, 0x6608, 0x9550, 0x6609, 0x9551, 0x660B, 0x9552, 0x660D, 0x9553, 0x6610, 0x9554, 0x6611, 0x9555, 0x6612, 0x9556, 0x6616, + 0x9557, 0x6617, 0x9558, 0x6618, 0x9559, 0x661A, 0x955A, 0x661B, 0x955B, 0x661C, 0x955C, 0x661E, 0x955D, 0x6621, 0x955E, 0x6622, + 0x955F, 0x6623, 0x9560, 0x6624, 0x9561, 0x6626, 0x9562, 0x6629, 0x9563, 0x662A, 0x9564, 0x662B, 0x9565, 0x662C, 0x9566, 0x662E, + 0x9567, 0x6630, 0x9568, 0x6632, 0x9569, 0x6633, 0x956A, 0x6637, 0x956B, 0x6638, 0x956C, 0x6639, 0x956D, 0x663A, 0x956E, 0x663B, + 0x956F, 0x663D, 0x9570, 0x663F, 0x9571, 0x6640, 0x9572, 0x6642, 0x9573, 0x6644, 0x9574, 0x6645, 0x9575, 0x6646, 0x9576, 0x6647, + 0x9577, 0x6648, 0x9578, 0x6649, 0x9579, 0x664A, 0x957A, 0x664D, 0x957B, 0x664E, 0x957C, 0x6650, 0x957D, 0x6651, 0x957E, 0x6658, + 0x9580, 0x6659, 0x9581, 0x665B, 0x9582, 0x665C, 0x9583, 0x665D, 0x9584, 0x665E, 0x9585, 0x6660, 0x9586, 0x6662, 0x9587, 0x6663, + 0x9588, 0x6665, 0x9589, 0x6667, 0x958A, 0x6669, 0x958B, 0x666A, 0x958C, 0x666B, 0x958D, 0x666C, 0x958E, 0x666D, 0x958F, 0x6671, + 0x9590, 0x6672, 0x9591, 0x6673, 0x9592, 0x6675, 0x9593, 0x6678, 0x9594, 0x6679, 0x9595, 0x667B, 0x9596, 0x667C, 0x9597, 0x667D, + 0x9598, 0x667F, 0x9599, 0x6680, 0x959A, 0x6681, 0x959B, 0x6683, 0x959C, 0x6685, 0x959D, 0x6686, 0x959E, 0x6688, 0x959F, 0x6689, + 0x95A0, 0x668A, 0x95A1, 0x668B, 0x95A2, 0x668D, 0x95A3, 0x668E, 0x95A4, 0x668F, 0x95A5, 0x6690, 0x95A6, 0x6692, 0x95A7, 0x6693, + 0x95A8, 0x6694, 0x95A9, 0x6695, 0x95AA, 0x6698, 0x95AB, 0x6699, 0x95AC, 0x669A, 0x95AD, 0x669B, 0x95AE, 0x669C, 0x95AF, 0x669E, + 0x95B0, 0x669F, 0x95B1, 0x66A0, 0x95B2, 0x66A1, 0x95B3, 0x66A2, 0x95B4, 0x66A3, 0x95B5, 0x66A4, 0x95B6, 0x66A5, 0x95B7, 0x66A6, + 0x95B8, 0x66A9, 0x95B9, 0x66AA, 0x95BA, 0x66AB, 0x95BB, 0x66AC, 0x95BC, 0x66AD, 0x95BD, 0x66AF, 0x95BE, 0x66B0, 0x95BF, 0x66B1, + 0x95C0, 0x66B2, 0x95C1, 0x66B3, 0x95C2, 0x66B5, 0x95C3, 0x66B6, 0x95C4, 0x66B7, 0x95C5, 0x66B8, 0x95C6, 0x66BA, 0x95C7, 0x66BB, + 0x95C8, 0x66BC, 0x95C9, 0x66BD, 0x95CA, 0x66BF, 0x95CB, 0x66C0, 0x95CC, 0x66C1, 0x95CD, 0x66C2, 0x95CE, 0x66C3, 0x95CF, 0x66C4, + 0x95D0, 0x66C5, 0x95D1, 0x66C6, 0x95D2, 0x66C7, 0x95D3, 0x66C8, 0x95D4, 0x66C9, 0x95D5, 0x66CA, 0x95D6, 0x66CB, 0x95D7, 0x66CC, + 0x95D8, 0x66CD, 0x95D9, 0x66CE, 0x95DA, 0x66CF, 0x95DB, 0x66D0, 0x95DC, 0x66D1, 0x95DD, 0x66D2, 0x95DE, 0x66D3, 0x95DF, 0x66D4, + 0x95E0, 0x66D5, 0x95E1, 0x66D6, 0x95E2, 0x66D7, 0x95E3, 0x66D8, 0x95E4, 0x66DA, 0x95E5, 0x66DE, 0x95E6, 0x66DF, 0x95E7, 0x66E0, + 0x95E8, 0x66E1, 0x95E9, 0x66E2, 0x95EA, 0x66E3, 0x95EB, 0x66E4, 0x95EC, 0x66E5, 0x95ED, 0x66E7, 0x95EE, 0x66E8, 0x95EF, 0x66EA, + 0x95F0, 0x66EB, 0x95F1, 0x66EC, 0x95F2, 0x66ED, 0x95F3, 0x66EE, 0x95F4, 0x66EF, 0x95F5, 0x66F1, 0x95F6, 0x66F5, 0x95F7, 0x66F6, + 0x95F8, 0x66F8, 0x95F9, 0x66FA, 0x95FA, 0x66FB, 0x95FB, 0x66FD, 0x95FC, 0x6701, 0x95FD, 0x6702, 0x95FE, 0x6703, 0x9640, 0x6704, + 0x9641, 0x6705, 0x9642, 0x6706, 0x9643, 0x6707, 0x9644, 0x670C, 0x9645, 0x670E, 0x9646, 0x670F, 0x9647, 0x6711, 0x9648, 0x6712, + 0x9649, 0x6713, 0x964A, 0x6716, 0x964B, 0x6718, 0x964C, 0x6719, 0x964D, 0x671A, 0x964E, 0x671C, 0x964F, 0x671E, 0x9650, 0x6720, + 0x9651, 0x6721, 0x9652, 0x6722, 0x9653, 0x6723, 0x9654, 0x6724, 0x9655, 0x6725, 0x9656, 0x6727, 0x9657, 0x6729, 0x9658, 0x672E, + 0x9659, 0x6730, 0x965A, 0x6732, 0x965B, 0x6733, 0x965C, 0x6736, 0x965D, 0x6737, 0x965E, 0x6738, 0x965F, 0x6739, 0x9660, 0x673B, + 0x9661, 0x673C, 0x9662, 0x673E, 0x9663, 0x673F, 0x9664, 0x6741, 0x9665, 0x6744, 0x9666, 0x6745, 0x9667, 0x6747, 0x9668, 0x674A, + 0x9669, 0x674B, 0x966A, 0x674D, 0x966B, 0x6752, 0x966C, 0x6754, 0x966D, 0x6755, 0x966E, 0x6757, 0x966F, 0x6758, 0x9670, 0x6759, + 0x9671, 0x675A, 0x9672, 0x675B, 0x9673, 0x675D, 0x9674, 0x6762, 0x9675, 0x6763, 0x9676, 0x6764, 0x9677, 0x6766, 0x9678, 0x6767, + 0x9679, 0x676B, 0x967A, 0x676C, 0x967B, 0x676E, 0x967C, 0x6771, 0x967D, 0x6774, 0x967E, 0x6776, 0x9680, 0x6778, 0x9681, 0x6779, + 0x9682, 0x677A, 0x9683, 0x677B, 0x9684, 0x677D, 0x9685, 0x6780, 0x9686, 0x6782, 0x9687, 0x6783, 0x9688, 0x6785, 0x9689, 0x6786, + 0x968A, 0x6788, 0x968B, 0x678A, 0x968C, 0x678C, 0x968D, 0x678D, 0x968E, 0x678E, 0x968F, 0x678F, 0x9690, 0x6791, 0x9691, 0x6792, + 0x9692, 0x6793, 0x9693, 0x6794, 0x9694, 0x6796, 0x9695, 0x6799, 0x9696, 0x679B, 0x9697, 0x679F, 0x9698, 0x67A0, 0x9699, 0x67A1, + 0x969A, 0x67A4, 0x969B, 0x67A6, 0x969C, 0x67A9, 0x969D, 0x67AC, 0x969E, 0x67AE, 0x969F, 0x67B1, 0x96A0, 0x67B2, 0x96A1, 0x67B4, + 0x96A2, 0x67B9, 0x96A3, 0x67BA, 0x96A4, 0x67BB, 0x96A5, 0x67BC, 0x96A6, 0x67BD, 0x96A7, 0x67BE, 0x96A8, 0x67BF, 0x96A9, 0x67C0, + 0x96AA, 0x67C2, 0x96AB, 0x67C5, 0x96AC, 0x67C6, 0x96AD, 0x67C7, 0x96AE, 0x67C8, 0x96AF, 0x67C9, 0x96B0, 0x67CA, 0x96B1, 0x67CB, + 0x96B2, 0x67CC, 0x96B3, 0x67CD, 0x96B4, 0x67CE, 0x96B5, 0x67D5, 0x96B6, 0x67D6, 0x96B7, 0x67D7, 0x96B8, 0x67DB, 0x96B9, 0x67DF, + 0x96BA, 0x67E1, 0x96BB, 0x67E3, 0x96BC, 0x67E4, 0x96BD, 0x67E6, 0x96BE, 0x67E7, 0x96BF, 0x67E8, 0x96C0, 0x67EA, 0x96C1, 0x67EB, + 0x96C2, 0x67ED, 0x96C3, 0x67EE, 0x96C4, 0x67F2, 0x96C5, 0x67F5, 0x96C6, 0x67F6, 0x96C7, 0x67F7, 0x96C8, 0x67F8, 0x96C9, 0x67F9, + 0x96CA, 0x67FA, 0x96CB, 0x67FB, 0x96CC, 0x67FC, 0x96CD, 0x67FE, 0x96CE, 0x6801, 0x96CF, 0x6802, 0x96D0, 0x6803, 0x96D1, 0x6804, + 0x96D2, 0x6806, 0x96D3, 0x680D, 0x96D4, 0x6810, 0x96D5, 0x6812, 0x96D6, 0x6814, 0x96D7, 0x6815, 0x96D8, 0x6818, 0x96D9, 0x6819, + 0x96DA, 0x681A, 0x96DB, 0x681B, 0x96DC, 0x681C, 0x96DD, 0x681E, 0x96DE, 0x681F, 0x96DF, 0x6820, 0x96E0, 0x6822, 0x96E1, 0x6823, + 0x96E2, 0x6824, 0x96E3, 0x6825, 0x96E4, 0x6826, 0x96E5, 0x6827, 0x96E6, 0x6828, 0x96E7, 0x682B, 0x96E8, 0x682C, 0x96E9, 0x682D, + 0x96EA, 0x682E, 0x96EB, 0x682F, 0x96EC, 0x6830, 0x96ED, 0x6831, 0x96EE, 0x6834, 0x96EF, 0x6835, 0x96F0, 0x6836, 0x96F1, 0x683A, + 0x96F2, 0x683B, 0x96F3, 0x683F, 0x96F4, 0x6847, 0x96F5, 0x684B, 0x96F6, 0x684D, 0x96F7, 0x684F, 0x96F8, 0x6852, 0x96F9, 0x6856, + 0x96FA, 0x6857, 0x96FB, 0x6858, 0x96FC, 0x6859, 0x96FD, 0x685A, 0x96FE, 0x685B, 0x9740, 0x685C, 0x9741, 0x685D, 0x9742, 0x685E, + 0x9743, 0x685F, 0x9744, 0x686A, 0x9745, 0x686C, 0x9746, 0x686D, 0x9747, 0x686E, 0x9748, 0x686F, 0x9749, 0x6870, 0x974A, 0x6871, + 0x974B, 0x6872, 0x974C, 0x6873, 0x974D, 0x6875, 0x974E, 0x6878, 0x974F, 0x6879, 0x9750, 0x687A, 0x9751, 0x687B, 0x9752, 0x687C, + 0x9753, 0x687D, 0x9754, 0x687E, 0x9755, 0x687F, 0x9756, 0x6880, 0x9757, 0x6882, 0x9758, 0x6884, 0x9759, 0x6887, 0x975A, 0x6888, + 0x975B, 0x6889, 0x975C, 0x688A, 0x975D, 0x688B, 0x975E, 0x688C, 0x975F, 0x688D, 0x9760, 0x688E, 0x9761, 0x6890, 0x9762, 0x6891, + 0x9763, 0x6892, 0x9764, 0x6894, 0x9765, 0x6895, 0x9766, 0x6896, 0x9767, 0x6898, 0x9768, 0x6899, 0x9769, 0x689A, 0x976A, 0x689B, + 0x976B, 0x689C, 0x976C, 0x689D, 0x976D, 0x689E, 0x976E, 0x689F, 0x976F, 0x68A0, 0x9770, 0x68A1, 0x9771, 0x68A3, 0x9772, 0x68A4, + 0x9773, 0x68A5, 0x9774, 0x68A9, 0x9775, 0x68AA, 0x9776, 0x68AB, 0x9777, 0x68AC, 0x9778, 0x68AE, 0x9779, 0x68B1, 0x977A, 0x68B2, + 0x977B, 0x68B4, 0x977C, 0x68B6, 0x977D, 0x68B7, 0x977E, 0x68B8, 0x9780, 0x68B9, 0x9781, 0x68BA, 0x9782, 0x68BB, 0x9783, 0x68BC, + 0x9784, 0x68BD, 0x9785, 0x68BE, 0x9786, 0x68BF, 0x9787, 0x68C1, 0x9788, 0x68C3, 0x9789, 0x68C4, 0x978A, 0x68C5, 0x978B, 0x68C6, + 0x978C, 0x68C7, 0x978D, 0x68C8, 0x978E, 0x68CA, 0x978F, 0x68CC, 0x9790, 0x68CE, 0x9791, 0x68CF, 0x9792, 0x68D0, 0x9793, 0x68D1, + 0x9794, 0x68D3, 0x9795, 0x68D4, 0x9796, 0x68D6, 0x9797, 0x68D7, 0x9798, 0x68D9, 0x9799, 0x68DB, 0x979A, 0x68DC, 0x979B, 0x68DD, + 0x979C, 0x68DE, 0x979D, 0x68DF, 0x979E, 0x68E1, 0x979F, 0x68E2, 0x97A0, 0x68E4, 0x97A1, 0x68E5, 0x97A2, 0x68E6, 0x97A3, 0x68E7, + 0x97A4, 0x68E8, 0x97A5, 0x68E9, 0x97A6, 0x68EA, 0x97A7, 0x68EB, 0x97A8, 0x68EC, 0x97A9, 0x68ED, 0x97AA, 0x68EF, 0x97AB, 0x68F2, + 0x97AC, 0x68F3, 0x97AD, 0x68F4, 0x97AE, 0x68F6, 0x97AF, 0x68F7, 0x97B0, 0x68F8, 0x97B1, 0x68FB, 0x97B2, 0x68FD, 0x97B3, 0x68FE, + 0x97B4, 0x68FF, 0x97B5, 0x6900, 0x97B6, 0x6902, 0x97B7, 0x6903, 0x97B8, 0x6904, 0x97B9, 0x6906, 0x97BA, 0x6907, 0x97BB, 0x6908, + 0x97BC, 0x6909, 0x97BD, 0x690A, 0x97BE, 0x690C, 0x97BF, 0x690F, 0x97C0, 0x6911, 0x97C1, 0x6913, 0x97C2, 0x6914, 0x97C3, 0x6915, + 0x97C4, 0x6916, 0x97C5, 0x6917, 0x97C6, 0x6918, 0x97C7, 0x6919, 0x97C8, 0x691A, 0x97C9, 0x691B, 0x97CA, 0x691C, 0x97CB, 0x691D, + 0x97CC, 0x691E, 0x97CD, 0x6921, 0x97CE, 0x6922, 0x97CF, 0x6923, 0x97D0, 0x6925, 0x97D1, 0x6926, 0x97D2, 0x6927, 0x97D3, 0x6928, + 0x97D4, 0x6929, 0x97D5, 0x692A, 0x97D6, 0x692B, 0x97D7, 0x692C, 0x97D8, 0x692E, 0x97D9, 0x692F, 0x97DA, 0x6931, 0x97DB, 0x6932, + 0x97DC, 0x6933, 0x97DD, 0x6935, 0x97DE, 0x6936, 0x97DF, 0x6937, 0x97E0, 0x6938, 0x97E1, 0x693A, 0x97E2, 0x693B, 0x97E3, 0x693C, + 0x97E4, 0x693E, 0x97E5, 0x6940, 0x97E6, 0x6941, 0x97E7, 0x6943, 0x97E8, 0x6944, 0x97E9, 0x6945, 0x97EA, 0x6946, 0x97EB, 0x6947, + 0x97EC, 0x6948, 0x97ED, 0x6949, 0x97EE, 0x694A, 0x97EF, 0x694B, 0x97F0, 0x694C, 0x97F1, 0x694D, 0x97F2, 0x694E, 0x97F3, 0x694F, + 0x97F4, 0x6950, 0x97F5, 0x6951, 0x97F6, 0x6952, 0x97F7, 0x6953, 0x97F8, 0x6955, 0x97F9, 0x6956, 0x97FA, 0x6958, 0x97FB, 0x6959, + 0x97FC, 0x695B, 0x97FD, 0x695C, 0x97FE, 0x695F, 0x9840, 0x6961, 0x9841, 0x6962, 0x9842, 0x6964, 0x9843, 0x6965, 0x9844, 0x6967, + 0x9845, 0x6968, 0x9846, 0x6969, 0x9847, 0x696A, 0x9848, 0x696C, 0x9849, 0x696D, 0x984A, 0x696F, 0x984B, 0x6970, 0x984C, 0x6972, + 0x984D, 0x6973, 0x984E, 0x6974, 0x984F, 0x6975, 0x9850, 0x6976, 0x9851, 0x697A, 0x9852, 0x697B, 0x9853, 0x697D, 0x9854, 0x697E, + 0x9855, 0x697F, 0x9856, 0x6981, 0x9857, 0x6983, 0x9858, 0x6985, 0x9859, 0x698A, 0x985A, 0x698B, 0x985B, 0x698C, 0x985C, 0x698E, + 0x985D, 0x698F, 0x985E, 0x6990, 0x985F, 0x6991, 0x9860, 0x6992, 0x9861, 0x6993, 0x9862, 0x6996, 0x9863, 0x6997, 0x9864, 0x6999, + 0x9865, 0x699A, 0x9866, 0x699D, 0x9867, 0x699E, 0x9868, 0x699F, 0x9869, 0x69A0, 0x986A, 0x69A1, 0x986B, 0x69A2, 0x986C, 0x69A3, + 0x986D, 0x69A4, 0x986E, 0x69A5, 0x986F, 0x69A6, 0x9870, 0x69A9, 0x9871, 0x69AA, 0x9872, 0x69AC, 0x9873, 0x69AE, 0x9874, 0x69AF, + 0x9875, 0x69B0, 0x9876, 0x69B2, 0x9877, 0x69B3, 0x9878, 0x69B5, 0x9879, 0x69B6, 0x987A, 0x69B8, 0x987B, 0x69B9, 0x987C, 0x69BA, + 0x987D, 0x69BC, 0x987E, 0x69BD, 0x9880, 0x69BE, 0x9881, 0x69BF, 0x9882, 0x69C0, 0x9883, 0x69C2, 0x9884, 0x69C3, 0x9885, 0x69C4, + 0x9886, 0x69C5, 0x9887, 0x69C6, 0x9888, 0x69C7, 0x9889, 0x69C8, 0x988A, 0x69C9, 0x988B, 0x69CB, 0x988C, 0x69CD, 0x988D, 0x69CF, + 0x988E, 0x69D1, 0x988F, 0x69D2, 0x9890, 0x69D3, 0x9891, 0x69D5, 0x9892, 0x69D6, 0x9893, 0x69D7, 0x9894, 0x69D8, 0x9895, 0x69D9, + 0x9896, 0x69DA, 0x9897, 0x69DC, 0x9898, 0x69DD, 0x9899, 0x69DE, 0x989A, 0x69E1, 0x989B, 0x69E2, 0x989C, 0x69E3, 0x989D, 0x69E4, + 0x989E, 0x69E5, 0x989F, 0x69E6, 0x98A0, 0x69E7, 0x98A1, 0x69E8, 0x98A2, 0x69E9, 0x98A3, 0x69EA, 0x98A4, 0x69EB, 0x98A5, 0x69EC, + 0x98A6, 0x69EE, 0x98A7, 0x69EF, 0x98A8, 0x69F0, 0x98A9, 0x69F1, 0x98AA, 0x69F3, 0x98AB, 0x69F4, 0x98AC, 0x69F5, 0x98AD, 0x69F6, + 0x98AE, 0x69F7, 0x98AF, 0x69F8, 0x98B0, 0x69F9, 0x98B1, 0x69FA, 0x98B2, 0x69FB, 0x98B3, 0x69FC, 0x98B4, 0x69FE, 0x98B5, 0x6A00, + 0x98B6, 0x6A01, 0x98B7, 0x6A02, 0x98B8, 0x6A03, 0x98B9, 0x6A04, 0x98BA, 0x6A05, 0x98BB, 0x6A06, 0x98BC, 0x6A07, 0x98BD, 0x6A08, + 0x98BE, 0x6A09, 0x98BF, 0x6A0B, 0x98C0, 0x6A0C, 0x98C1, 0x6A0D, 0x98C2, 0x6A0E, 0x98C3, 0x6A0F, 0x98C4, 0x6A10, 0x98C5, 0x6A11, + 0x98C6, 0x6A12, 0x98C7, 0x6A13, 0x98C8, 0x6A14, 0x98C9, 0x6A15, 0x98CA, 0x6A16, 0x98CB, 0x6A19, 0x98CC, 0x6A1A, 0x98CD, 0x6A1B, + 0x98CE, 0x6A1C, 0x98CF, 0x6A1D, 0x98D0, 0x6A1E, 0x98D1, 0x6A20, 0x98D2, 0x6A22, 0x98D3, 0x6A23, 0x98D4, 0x6A24, 0x98D5, 0x6A25, + 0x98D6, 0x6A26, 0x98D7, 0x6A27, 0x98D8, 0x6A29, 0x98D9, 0x6A2B, 0x98DA, 0x6A2C, 0x98DB, 0x6A2D, 0x98DC, 0x6A2E, 0x98DD, 0x6A30, + 0x98DE, 0x6A32, 0x98DF, 0x6A33, 0x98E0, 0x6A34, 0x98E1, 0x6A36, 0x98E2, 0x6A37, 0x98E3, 0x6A38, 0x98E4, 0x6A39, 0x98E5, 0x6A3A, + 0x98E6, 0x6A3B, 0x98E7, 0x6A3C, 0x98E8, 0x6A3F, 0x98E9, 0x6A40, 0x98EA, 0x6A41, 0x98EB, 0x6A42, 0x98EC, 0x6A43, 0x98ED, 0x6A45, + 0x98EE, 0x6A46, 0x98EF, 0x6A48, 0x98F0, 0x6A49, 0x98F1, 0x6A4A, 0x98F2, 0x6A4B, 0x98F3, 0x6A4C, 0x98F4, 0x6A4D, 0x98F5, 0x6A4E, + 0x98F6, 0x6A4F, 0x98F7, 0x6A51, 0x98F8, 0x6A52, 0x98F9, 0x6A53, 0x98FA, 0x6A54, 0x98FB, 0x6A55, 0x98FC, 0x6A56, 0x98FD, 0x6A57, + 0x98FE, 0x6A5A, 0x9940, 0x6A5C, 0x9941, 0x6A5D, 0x9942, 0x6A5E, 0x9943, 0x6A5F, 0x9944, 0x6A60, 0x9945, 0x6A62, 0x9946, 0x6A63, + 0x9947, 0x6A64, 0x9948, 0x6A66, 0x9949, 0x6A67, 0x994A, 0x6A68, 0x994B, 0x6A69, 0x994C, 0x6A6A, 0x994D, 0x6A6B, 0x994E, 0x6A6C, + 0x994F, 0x6A6D, 0x9950, 0x6A6E, 0x9951, 0x6A6F, 0x9952, 0x6A70, 0x9953, 0x6A72, 0x9954, 0x6A73, 0x9955, 0x6A74, 0x9956, 0x6A75, + 0x9957, 0x6A76, 0x9958, 0x6A77, 0x9959, 0x6A78, 0x995A, 0x6A7A, 0x995B, 0x6A7B, 0x995C, 0x6A7D, 0x995D, 0x6A7E, 0x995E, 0x6A7F, + 0x995F, 0x6A81, 0x9960, 0x6A82, 0x9961, 0x6A83, 0x9962, 0x6A85, 0x9963, 0x6A86, 0x9964, 0x6A87, 0x9965, 0x6A88, 0x9966, 0x6A89, + 0x9967, 0x6A8A, 0x9968, 0x6A8B, 0x9969, 0x6A8C, 0x996A, 0x6A8D, 0x996B, 0x6A8F, 0x996C, 0x6A92, 0x996D, 0x6A93, 0x996E, 0x6A94, + 0x996F, 0x6A95, 0x9970, 0x6A96, 0x9971, 0x6A98, 0x9972, 0x6A99, 0x9973, 0x6A9A, 0x9974, 0x6A9B, 0x9975, 0x6A9C, 0x9976, 0x6A9D, + 0x9977, 0x6A9E, 0x9978, 0x6A9F, 0x9979, 0x6AA1, 0x997A, 0x6AA2, 0x997B, 0x6AA3, 0x997C, 0x6AA4, 0x997D, 0x6AA5, 0x997E, 0x6AA6, + 0x9980, 0x6AA7, 0x9981, 0x6AA8, 0x9982, 0x6AAA, 0x9983, 0x6AAD, 0x9984, 0x6AAE, 0x9985, 0x6AAF, 0x9986, 0x6AB0, 0x9987, 0x6AB1, + 0x9988, 0x6AB2, 0x9989, 0x6AB3, 0x998A, 0x6AB4, 0x998B, 0x6AB5, 0x998C, 0x6AB6, 0x998D, 0x6AB7, 0x998E, 0x6AB8, 0x998F, 0x6AB9, + 0x9990, 0x6ABA, 0x9991, 0x6ABB, 0x9992, 0x6ABC, 0x9993, 0x6ABD, 0x9994, 0x6ABE, 0x9995, 0x6ABF, 0x9996, 0x6AC0, 0x9997, 0x6AC1, + 0x9998, 0x6AC2, 0x9999, 0x6AC3, 0x999A, 0x6AC4, 0x999B, 0x6AC5, 0x999C, 0x6AC6, 0x999D, 0x6AC7, 0x999E, 0x6AC8, 0x999F, 0x6AC9, + 0x99A0, 0x6ACA, 0x99A1, 0x6ACB, 0x99A2, 0x6ACC, 0x99A3, 0x6ACD, 0x99A4, 0x6ACE, 0x99A5, 0x6ACF, 0x99A6, 0x6AD0, 0x99A7, 0x6AD1, + 0x99A8, 0x6AD2, 0x99A9, 0x6AD3, 0x99AA, 0x6AD4, 0x99AB, 0x6AD5, 0x99AC, 0x6AD6, 0x99AD, 0x6AD7, 0x99AE, 0x6AD8, 0x99AF, 0x6AD9, + 0x99B0, 0x6ADA, 0x99B1, 0x6ADB, 0x99B2, 0x6ADC, 0x99B3, 0x6ADD, 0x99B4, 0x6ADE, 0x99B5, 0x6ADF, 0x99B6, 0x6AE0, 0x99B7, 0x6AE1, + 0x99B8, 0x6AE2, 0x99B9, 0x6AE3, 0x99BA, 0x6AE4, 0x99BB, 0x6AE5, 0x99BC, 0x6AE6, 0x99BD, 0x6AE7, 0x99BE, 0x6AE8, 0x99BF, 0x6AE9, + 0x99C0, 0x6AEA, 0x99C1, 0x6AEB, 0x99C2, 0x6AEC, 0x99C3, 0x6AED, 0x99C4, 0x6AEE, 0x99C5, 0x6AEF, 0x99C6, 0x6AF0, 0x99C7, 0x6AF1, + 0x99C8, 0x6AF2, 0x99C9, 0x6AF3, 0x99CA, 0x6AF4, 0x99CB, 0x6AF5, 0x99CC, 0x6AF6, 0x99CD, 0x6AF7, 0x99CE, 0x6AF8, 0x99CF, 0x6AF9, + 0x99D0, 0x6AFA, 0x99D1, 0x6AFB, 0x99D2, 0x6AFC, 0x99D3, 0x6AFD, 0x99D4, 0x6AFE, 0x99D5, 0x6AFF, 0x99D6, 0x6B00, 0x99D7, 0x6B01, + 0x99D8, 0x6B02, 0x99D9, 0x6B03, 0x99DA, 0x6B04, 0x99DB, 0x6B05, 0x99DC, 0x6B06, 0x99DD, 0x6B07, 0x99DE, 0x6B08, 0x99DF, 0x6B09, + 0x99E0, 0x6B0A, 0x99E1, 0x6B0B, 0x99E2, 0x6B0C, 0x99E3, 0x6B0D, 0x99E4, 0x6B0E, 0x99E5, 0x6B0F, 0x99E6, 0x6B10, 0x99E7, 0x6B11, + 0x99E8, 0x6B12, 0x99E9, 0x6B13, 0x99EA, 0x6B14, 0x99EB, 0x6B15, 0x99EC, 0x6B16, 0x99ED, 0x6B17, 0x99EE, 0x6B18, 0x99EF, 0x6B19, + 0x99F0, 0x6B1A, 0x99F1, 0x6B1B, 0x99F2, 0x6B1C, 0x99F3, 0x6B1D, 0x99F4, 0x6B1E, 0x99F5, 0x6B1F, 0x99F6, 0x6B25, 0x99F7, 0x6B26, + 0x99F8, 0x6B28, 0x99F9, 0x6B29, 0x99FA, 0x6B2A, 0x99FB, 0x6B2B, 0x99FC, 0x6B2C, 0x99FD, 0x6B2D, 0x99FE, 0x6B2E, 0x9A40, 0x6B2F, + 0x9A41, 0x6B30, 0x9A42, 0x6B31, 0x9A43, 0x6B33, 0x9A44, 0x6B34, 0x9A45, 0x6B35, 0x9A46, 0x6B36, 0x9A47, 0x6B38, 0x9A48, 0x6B3B, + 0x9A49, 0x6B3C, 0x9A4A, 0x6B3D, 0x9A4B, 0x6B3F, 0x9A4C, 0x6B40, 0x9A4D, 0x6B41, 0x9A4E, 0x6B42, 0x9A4F, 0x6B44, 0x9A50, 0x6B45, + 0x9A51, 0x6B48, 0x9A52, 0x6B4A, 0x9A53, 0x6B4B, 0x9A54, 0x6B4D, 0x9A55, 0x6B4E, 0x9A56, 0x6B4F, 0x9A57, 0x6B50, 0x9A58, 0x6B51, + 0x9A59, 0x6B52, 0x9A5A, 0x6B53, 0x9A5B, 0x6B54, 0x9A5C, 0x6B55, 0x9A5D, 0x6B56, 0x9A5E, 0x6B57, 0x9A5F, 0x6B58, 0x9A60, 0x6B5A, + 0x9A61, 0x6B5B, 0x9A62, 0x6B5C, 0x9A63, 0x6B5D, 0x9A64, 0x6B5E, 0x9A65, 0x6B5F, 0x9A66, 0x6B60, 0x9A67, 0x6B61, 0x9A68, 0x6B68, + 0x9A69, 0x6B69, 0x9A6A, 0x6B6B, 0x9A6B, 0x6B6C, 0x9A6C, 0x6B6D, 0x9A6D, 0x6B6E, 0x9A6E, 0x6B6F, 0x9A6F, 0x6B70, 0x9A70, 0x6B71, + 0x9A71, 0x6B72, 0x9A72, 0x6B73, 0x9A73, 0x6B74, 0x9A74, 0x6B75, 0x9A75, 0x6B76, 0x9A76, 0x6B77, 0x9A77, 0x6B78, 0x9A78, 0x6B7A, + 0x9A79, 0x6B7D, 0x9A7A, 0x6B7E, 0x9A7B, 0x6B7F, 0x9A7C, 0x6B80, 0x9A7D, 0x6B85, 0x9A7E, 0x6B88, 0x9A80, 0x6B8C, 0x9A81, 0x6B8E, + 0x9A82, 0x6B8F, 0x9A83, 0x6B90, 0x9A84, 0x6B91, 0x9A85, 0x6B94, 0x9A86, 0x6B95, 0x9A87, 0x6B97, 0x9A88, 0x6B98, 0x9A89, 0x6B99, + 0x9A8A, 0x6B9C, 0x9A8B, 0x6B9D, 0x9A8C, 0x6B9E, 0x9A8D, 0x6B9F, 0x9A8E, 0x6BA0, 0x9A8F, 0x6BA2, 0x9A90, 0x6BA3, 0x9A91, 0x6BA4, + 0x9A92, 0x6BA5, 0x9A93, 0x6BA6, 0x9A94, 0x6BA7, 0x9A95, 0x6BA8, 0x9A96, 0x6BA9, 0x9A97, 0x6BAB, 0x9A98, 0x6BAC, 0x9A99, 0x6BAD, + 0x9A9A, 0x6BAE, 0x9A9B, 0x6BAF, 0x9A9C, 0x6BB0, 0x9A9D, 0x6BB1, 0x9A9E, 0x6BB2, 0x9A9F, 0x6BB6, 0x9AA0, 0x6BB8, 0x9AA1, 0x6BB9, + 0x9AA2, 0x6BBA, 0x9AA3, 0x6BBB, 0x9AA4, 0x6BBC, 0x9AA5, 0x6BBD, 0x9AA6, 0x6BBE, 0x9AA7, 0x6BC0, 0x9AA8, 0x6BC3, 0x9AA9, 0x6BC4, + 0x9AAA, 0x6BC6, 0x9AAB, 0x6BC7, 0x9AAC, 0x6BC8, 0x9AAD, 0x6BC9, 0x9AAE, 0x6BCA, 0x9AAF, 0x6BCC, 0x9AB0, 0x6BCE, 0x9AB1, 0x6BD0, + 0x9AB2, 0x6BD1, 0x9AB3, 0x6BD8, 0x9AB4, 0x6BDA, 0x9AB5, 0x6BDC, 0x9AB6, 0x6BDD, 0x9AB7, 0x6BDE, 0x9AB8, 0x6BDF, 0x9AB9, 0x6BE0, + 0x9ABA, 0x6BE2, 0x9ABB, 0x6BE3, 0x9ABC, 0x6BE4, 0x9ABD, 0x6BE5, 0x9ABE, 0x6BE6, 0x9ABF, 0x6BE7, 0x9AC0, 0x6BE8, 0x9AC1, 0x6BE9, + 0x9AC2, 0x6BEC, 0x9AC3, 0x6BED, 0x9AC4, 0x6BEE, 0x9AC5, 0x6BF0, 0x9AC6, 0x6BF1, 0x9AC7, 0x6BF2, 0x9AC8, 0x6BF4, 0x9AC9, 0x6BF6, + 0x9ACA, 0x6BF7, 0x9ACB, 0x6BF8, 0x9ACC, 0x6BFA, 0x9ACD, 0x6BFB, 0x9ACE, 0x6BFC, 0x9ACF, 0x6BFE, 0x9AD0, 0x6BFF, 0x9AD1, 0x6C00, + 0x9AD2, 0x6C01, 0x9AD3, 0x6C02, 0x9AD4, 0x6C03, 0x9AD5, 0x6C04, 0x9AD6, 0x6C08, 0x9AD7, 0x6C09, 0x9AD8, 0x6C0A, 0x9AD9, 0x6C0B, + 0x9ADA, 0x6C0C, 0x9ADB, 0x6C0E, 0x9ADC, 0x6C12, 0x9ADD, 0x6C17, 0x9ADE, 0x6C1C, 0x9ADF, 0x6C1D, 0x9AE0, 0x6C1E, 0x9AE1, 0x6C20, + 0x9AE2, 0x6C23, 0x9AE3, 0x6C25, 0x9AE4, 0x6C2B, 0x9AE5, 0x6C2C, 0x9AE6, 0x6C2D, 0x9AE7, 0x6C31, 0x9AE8, 0x6C33, 0x9AE9, 0x6C36, + 0x9AEA, 0x6C37, 0x9AEB, 0x6C39, 0x9AEC, 0x6C3A, 0x9AED, 0x6C3B, 0x9AEE, 0x6C3C, 0x9AEF, 0x6C3E, 0x9AF0, 0x6C3F, 0x9AF1, 0x6C43, + 0x9AF2, 0x6C44, 0x9AF3, 0x6C45, 0x9AF4, 0x6C48, 0x9AF5, 0x6C4B, 0x9AF6, 0x6C4C, 0x9AF7, 0x6C4D, 0x9AF8, 0x6C4E, 0x9AF9, 0x6C4F, + 0x9AFA, 0x6C51, 0x9AFB, 0x6C52, 0x9AFC, 0x6C53, 0x9AFD, 0x6C56, 0x9AFE, 0x6C58, 0x9B40, 0x6C59, 0x9B41, 0x6C5A, 0x9B42, 0x6C62, + 0x9B43, 0x6C63, 0x9B44, 0x6C65, 0x9B45, 0x6C66, 0x9B46, 0x6C67, 0x9B47, 0x6C6B, 0x9B48, 0x6C6C, 0x9B49, 0x6C6D, 0x9B4A, 0x6C6E, + 0x9B4B, 0x6C6F, 0x9B4C, 0x6C71, 0x9B4D, 0x6C73, 0x9B4E, 0x6C75, 0x9B4F, 0x6C77, 0x9B50, 0x6C78, 0x9B51, 0x6C7A, 0x9B52, 0x6C7B, + 0x9B53, 0x6C7C, 0x9B54, 0x6C7F, 0x9B55, 0x6C80, 0x9B56, 0x6C84, 0x9B57, 0x6C87, 0x9B58, 0x6C8A, 0x9B59, 0x6C8B, 0x9B5A, 0x6C8D, + 0x9B5B, 0x6C8E, 0x9B5C, 0x6C91, 0x9B5D, 0x6C92, 0x9B5E, 0x6C95, 0x9B5F, 0x6C96, 0x9B60, 0x6C97, 0x9B61, 0x6C98, 0x9B62, 0x6C9A, + 0x9B63, 0x6C9C, 0x9B64, 0x6C9D, 0x9B65, 0x6C9E, 0x9B66, 0x6CA0, 0x9B67, 0x6CA2, 0x9B68, 0x6CA8, 0x9B69, 0x6CAC, 0x9B6A, 0x6CAF, + 0x9B6B, 0x6CB0, 0x9B6C, 0x6CB4, 0x9B6D, 0x6CB5, 0x9B6E, 0x6CB6, 0x9B6F, 0x6CB7, 0x9B70, 0x6CBA, 0x9B71, 0x6CC0, 0x9B72, 0x6CC1, + 0x9B73, 0x6CC2, 0x9B74, 0x6CC3, 0x9B75, 0x6CC6, 0x9B76, 0x6CC7, 0x9B77, 0x6CC8, 0x9B78, 0x6CCB, 0x9B79, 0x6CCD, 0x9B7A, 0x6CCE, + 0x9B7B, 0x6CCF, 0x9B7C, 0x6CD1, 0x9B7D, 0x6CD2, 0x9B7E, 0x6CD8, 0x9B80, 0x6CD9, 0x9B81, 0x6CDA, 0x9B82, 0x6CDC, 0x9B83, 0x6CDD, + 0x9B84, 0x6CDF, 0x9B85, 0x6CE4, 0x9B86, 0x6CE6, 0x9B87, 0x6CE7, 0x9B88, 0x6CE9, 0x9B89, 0x6CEC, 0x9B8A, 0x6CED, 0x9B8B, 0x6CF2, + 0x9B8C, 0x6CF4, 0x9B8D, 0x6CF9, 0x9B8E, 0x6CFF, 0x9B8F, 0x6D00, 0x9B90, 0x6D02, 0x9B91, 0x6D03, 0x9B92, 0x6D05, 0x9B93, 0x6D06, + 0x9B94, 0x6D08, 0x9B95, 0x6D09, 0x9B96, 0x6D0A, 0x9B97, 0x6D0D, 0x9B98, 0x6D0F, 0x9B99, 0x6D10, 0x9B9A, 0x6D11, 0x9B9B, 0x6D13, + 0x9B9C, 0x6D14, 0x9B9D, 0x6D15, 0x9B9E, 0x6D16, 0x9B9F, 0x6D18, 0x9BA0, 0x6D1C, 0x9BA1, 0x6D1D, 0x9BA2, 0x6D1F, 0x9BA3, 0x6D20, + 0x9BA4, 0x6D21, 0x9BA5, 0x6D22, 0x9BA6, 0x6D23, 0x9BA7, 0x6D24, 0x9BA8, 0x6D26, 0x9BA9, 0x6D28, 0x9BAA, 0x6D29, 0x9BAB, 0x6D2C, + 0x9BAC, 0x6D2D, 0x9BAD, 0x6D2F, 0x9BAE, 0x6D30, 0x9BAF, 0x6D34, 0x9BB0, 0x6D36, 0x9BB1, 0x6D37, 0x9BB2, 0x6D38, 0x9BB3, 0x6D3A, + 0x9BB4, 0x6D3F, 0x9BB5, 0x6D40, 0x9BB6, 0x6D42, 0x9BB7, 0x6D44, 0x9BB8, 0x6D49, 0x9BB9, 0x6D4C, 0x9BBA, 0x6D50, 0x9BBB, 0x6D55, + 0x9BBC, 0x6D56, 0x9BBD, 0x6D57, 0x9BBE, 0x6D58, 0x9BBF, 0x6D5B, 0x9BC0, 0x6D5D, 0x9BC1, 0x6D5F, 0x9BC2, 0x6D61, 0x9BC3, 0x6D62, + 0x9BC4, 0x6D64, 0x9BC5, 0x6D65, 0x9BC6, 0x6D67, 0x9BC7, 0x6D68, 0x9BC8, 0x6D6B, 0x9BC9, 0x6D6C, 0x9BCA, 0x6D6D, 0x9BCB, 0x6D70, + 0x9BCC, 0x6D71, 0x9BCD, 0x6D72, 0x9BCE, 0x6D73, 0x9BCF, 0x6D75, 0x9BD0, 0x6D76, 0x9BD1, 0x6D79, 0x9BD2, 0x6D7A, 0x9BD3, 0x6D7B, + 0x9BD4, 0x6D7D, 0x9BD5, 0x6D7E, 0x9BD6, 0x6D7F, 0x9BD7, 0x6D80, 0x9BD8, 0x6D81, 0x9BD9, 0x6D83, 0x9BDA, 0x6D84, 0x9BDB, 0x6D86, + 0x9BDC, 0x6D87, 0x9BDD, 0x6D8A, 0x9BDE, 0x6D8B, 0x9BDF, 0x6D8D, 0x9BE0, 0x6D8F, 0x9BE1, 0x6D90, 0x9BE2, 0x6D92, 0x9BE3, 0x6D96, + 0x9BE4, 0x6D97, 0x9BE5, 0x6D98, 0x9BE6, 0x6D99, 0x9BE7, 0x6D9A, 0x9BE8, 0x6D9C, 0x9BE9, 0x6DA2, 0x9BEA, 0x6DA5, 0x9BEB, 0x6DAC, + 0x9BEC, 0x6DAD, 0x9BED, 0x6DB0, 0x9BEE, 0x6DB1, 0x9BEF, 0x6DB3, 0x9BF0, 0x6DB4, 0x9BF1, 0x6DB6, 0x9BF2, 0x6DB7, 0x9BF3, 0x6DB9, + 0x9BF4, 0x6DBA, 0x9BF5, 0x6DBB, 0x9BF6, 0x6DBC, 0x9BF7, 0x6DBD, 0x9BF8, 0x6DBE, 0x9BF9, 0x6DC1, 0x9BFA, 0x6DC2, 0x9BFB, 0x6DC3, + 0x9BFC, 0x6DC8, 0x9BFD, 0x6DC9, 0x9BFE, 0x6DCA, 0x9C40, 0x6DCD, 0x9C41, 0x6DCE, 0x9C42, 0x6DCF, 0x9C43, 0x6DD0, 0x9C44, 0x6DD2, + 0x9C45, 0x6DD3, 0x9C46, 0x6DD4, 0x9C47, 0x6DD5, 0x9C48, 0x6DD7, 0x9C49, 0x6DDA, 0x9C4A, 0x6DDB, 0x9C4B, 0x6DDC, 0x9C4C, 0x6DDF, + 0x9C4D, 0x6DE2, 0x9C4E, 0x6DE3, 0x9C4F, 0x6DE5, 0x9C50, 0x6DE7, 0x9C51, 0x6DE8, 0x9C52, 0x6DE9, 0x9C53, 0x6DEA, 0x9C54, 0x6DED, + 0x9C55, 0x6DEF, 0x9C56, 0x6DF0, 0x9C57, 0x6DF2, 0x9C58, 0x6DF4, 0x9C59, 0x6DF5, 0x9C5A, 0x6DF6, 0x9C5B, 0x6DF8, 0x9C5C, 0x6DFA, + 0x9C5D, 0x6DFD, 0x9C5E, 0x6DFE, 0x9C5F, 0x6DFF, 0x9C60, 0x6E00, 0x9C61, 0x6E01, 0x9C62, 0x6E02, 0x9C63, 0x6E03, 0x9C64, 0x6E04, + 0x9C65, 0x6E06, 0x9C66, 0x6E07, 0x9C67, 0x6E08, 0x9C68, 0x6E09, 0x9C69, 0x6E0B, 0x9C6A, 0x6E0F, 0x9C6B, 0x6E12, 0x9C6C, 0x6E13, + 0x9C6D, 0x6E15, 0x9C6E, 0x6E18, 0x9C6F, 0x6E19, 0x9C70, 0x6E1B, 0x9C71, 0x6E1C, 0x9C72, 0x6E1E, 0x9C73, 0x6E1F, 0x9C74, 0x6E22, + 0x9C75, 0x6E26, 0x9C76, 0x6E27, 0x9C77, 0x6E28, 0x9C78, 0x6E2A, 0x9C79, 0x6E2C, 0x9C7A, 0x6E2E, 0x9C7B, 0x6E30, 0x9C7C, 0x6E31, + 0x9C7D, 0x6E33, 0x9C7E, 0x6E35, 0x9C80, 0x6E36, 0x9C81, 0x6E37, 0x9C82, 0x6E39, 0x9C83, 0x6E3B, 0x9C84, 0x6E3C, 0x9C85, 0x6E3D, + 0x9C86, 0x6E3E, 0x9C87, 0x6E3F, 0x9C88, 0x6E40, 0x9C89, 0x6E41, 0x9C8A, 0x6E42, 0x9C8B, 0x6E45, 0x9C8C, 0x6E46, 0x9C8D, 0x6E47, + 0x9C8E, 0x6E48, 0x9C8F, 0x6E49, 0x9C90, 0x6E4A, 0x9C91, 0x6E4B, 0x9C92, 0x6E4C, 0x9C93, 0x6E4F, 0x9C94, 0x6E50, 0x9C95, 0x6E51, + 0x9C96, 0x6E52, 0x9C97, 0x6E55, 0x9C98, 0x6E57, 0x9C99, 0x6E59, 0x9C9A, 0x6E5A, 0x9C9B, 0x6E5C, 0x9C9C, 0x6E5D, 0x9C9D, 0x6E5E, + 0x9C9E, 0x6E60, 0x9C9F, 0x6E61, 0x9CA0, 0x6E62, 0x9CA1, 0x6E63, 0x9CA2, 0x6E64, 0x9CA3, 0x6E65, 0x9CA4, 0x6E66, 0x9CA5, 0x6E67, + 0x9CA6, 0x6E68, 0x9CA7, 0x6E69, 0x9CA8, 0x6E6A, 0x9CA9, 0x6E6C, 0x9CAA, 0x6E6D, 0x9CAB, 0x6E6F, 0x9CAC, 0x6E70, 0x9CAD, 0x6E71, + 0x9CAE, 0x6E72, 0x9CAF, 0x6E73, 0x9CB0, 0x6E74, 0x9CB1, 0x6E75, 0x9CB2, 0x6E76, 0x9CB3, 0x6E77, 0x9CB4, 0x6E78, 0x9CB5, 0x6E79, + 0x9CB6, 0x6E7A, 0x9CB7, 0x6E7B, 0x9CB8, 0x6E7C, 0x9CB9, 0x6E7D, 0x9CBA, 0x6E80, 0x9CBB, 0x6E81, 0x9CBC, 0x6E82, 0x9CBD, 0x6E84, + 0x9CBE, 0x6E87, 0x9CBF, 0x6E88, 0x9CC0, 0x6E8A, 0x9CC1, 0x6E8B, 0x9CC2, 0x6E8C, 0x9CC3, 0x6E8D, 0x9CC4, 0x6E8E, 0x9CC5, 0x6E91, + 0x9CC6, 0x6E92, 0x9CC7, 0x6E93, 0x9CC8, 0x6E94, 0x9CC9, 0x6E95, 0x9CCA, 0x6E96, 0x9CCB, 0x6E97, 0x9CCC, 0x6E99, 0x9CCD, 0x6E9A, + 0x9CCE, 0x6E9B, 0x9CCF, 0x6E9D, 0x9CD0, 0x6E9E, 0x9CD1, 0x6EA0, 0x9CD2, 0x6EA1, 0x9CD3, 0x6EA3, 0x9CD4, 0x6EA4, 0x9CD5, 0x6EA6, + 0x9CD6, 0x6EA8, 0x9CD7, 0x6EA9, 0x9CD8, 0x6EAB, 0x9CD9, 0x6EAC, 0x9CDA, 0x6EAD, 0x9CDB, 0x6EAE, 0x9CDC, 0x6EB0, 0x9CDD, 0x6EB3, + 0x9CDE, 0x6EB5, 0x9CDF, 0x6EB8, 0x9CE0, 0x6EB9, 0x9CE1, 0x6EBC, 0x9CE2, 0x6EBE, 0x9CE3, 0x6EBF, 0x9CE4, 0x6EC0, 0x9CE5, 0x6EC3, + 0x9CE6, 0x6EC4, 0x9CE7, 0x6EC5, 0x9CE8, 0x6EC6, 0x9CE9, 0x6EC8, 0x9CEA, 0x6EC9, 0x9CEB, 0x6ECA, 0x9CEC, 0x6ECC, 0x9CED, 0x6ECD, + 0x9CEE, 0x6ECE, 0x9CEF, 0x6ED0, 0x9CF0, 0x6ED2, 0x9CF1, 0x6ED6, 0x9CF2, 0x6ED8, 0x9CF3, 0x6ED9, 0x9CF4, 0x6EDB, 0x9CF5, 0x6EDC, + 0x9CF6, 0x6EDD, 0x9CF7, 0x6EE3, 0x9CF8, 0x6EE7, 0x9CF9, 0x6EEA, 0x9CFA, 0x6EEB, 0x9CFB, 0x6EEC, 0x9CFC, 0x6EED, 0x9CFD, 0x6EEE, + 0x9CFE, 0x6EEF, 0x9D40, 0x6EF0, 0x9D41, 0x6EF1, 0x9D42, 0x6EF2, 0x9D43, 0x6EF3, 0x9D44, 0x6EF5, 0x9D45, 0x6EF6, 0x9D46, 0x6EF7, + 0x9D47, 0x6EF8, 0x9D48, 0x6EFA, 0x9D49, 0x6EFB, 0x9D4A, 0x6EFC, 0x9D4B, 0x6EFD, 0x9D4C, 0x6EFE, 0x9D4D, 0x6EFF, 0x9D4E, 0x6F00, + 0x9D4F, 0x6F01, 0x9D50, 0x6F03, 0x9D51, 0x6F04, 0x9D52, 0x6F05, 0x9D53, 0x6F07, 0x9D54, 0x6F08, 0x9D55, 0x6F0A, 0x9D56, 0x6F0B, + 0x9D57, 0x6F0C, 0x9D58, 0x6F0D, 0x9D59, 0x6F0E, 0x9D5A, 0x6F10, 0x9D5B, 0x6F11, 0x9D5C, 0x6F12, 0x9D5D, 0x6F16, 0x9D5E, 0x6F17, + 0x9D5F, 0x6F18, 0x9D60, 0x6F19, 0x9D61, 0x6F1A, 0x9D62, 0x6F1B, 0x9D63, 0x6F1C, 0x9D64, 0x6F1D, 0x9D65, 0x6F1E, 0x9D66, 0x6F1F, + 0x9D67, 0x6F21, 0x9D68, 0x6F22, 0x9D69, 0x6F23, 0x9D6A, 0x6F25, 0x9D6B, 0x6F26, 0x9D6C, 0x6F27, 0x9D6D, 0x6F28, 0x9D6E, 0x6F2C, + 0x9D6F, 0x6F2E, 0x9D70, 0x6F30, 0x9D71, 0x6F32, 0x9D72, 0x6F34, 0x9D73, 0x6F35, 0x9D74, 0x6F37, 0x9D75, 0x6F38, 0x9D76, 0x6F39, + 0x9D77, 0x6F3A, 0x9D78, 0x6F3B, 0x9D79, 0x6F3C, 0x9D7A, 0x6F3D, 0x9D7B, 0x6F3F, 0x9D7C, 0x6F40, 0x9D7D, 0x6F41, 0x9D7E, 0x6F42, + 0x9D80, 0x6F43, 0x9D81, 0x6F44, 0x9D82, 0x6F45, 0x9D83, 0x6F48, 0x9D84, 0x6F49, 0x9D85, 0x6F4A, 0x9D86, 0x6F4C, 0x9D87, 0x6F4E, + 0x9D88, 0x6F4F, 0x9D89, 0x6F50, 0x9D8A, 0x6F51, 0x9D8B, 0x6F52, 0x9D8C, 0x6F53, 0x9D8D, 0x6F54, 0x9D8E, 0x6F55, 0x9D8F, 0x6F56, + 0x9D90, 0x6F57, 0x9D91, 0x6F59, 0x9D92, 0x6F5A, 0x9D93, 0x6F5B, 0x9D94, 0x6F5D, 0x9D95, 0x6F5F, 0x9D96, 0x6F60, 0x9D97, 0x6F61, + 0x9D98, 0x6F63, 0x9D99, 0x6F64, 0x9D9A, 0x6F65, 0x9D9B, 0x6F67, 0x9D9C, 0x6F68, 0x9D9D, 0x6F69, 0x9D9E, 0x6F6A, 0x9D9F, 0x6F6B, + 0x9DA0, 0x6F6C, 0x9DA1, 0x6F6F, 0x9DA2, 0x6F70, 0x9DA3, 0x6F71, 0x9DA4, 0x6F73, 0x9DA5, 0x6F75, 0x9DA6, 0x6F76, 0x9DA7, 0x6F77, + 0x9DA8, 0x6F79, 0x9DA9, 0x6F7B, 0x9DAA, 0x6F7D, 0x9DAB, 0x6F7E, 0x9DAC, 0x6F7F, 0x9DAD, 0x6F80, 0x9DAE, 0x6F81, 0x9DAF, 0x6F82, + 0x9DB0, 0x6F83, 0x9DB1, 0x6F85, 0x9DB2, 0x6F86, 0x9DB3, 0x6F87, 0x9DB4, 0x6F8A, 0x9DB5, 0x6F8B, 0x9DB6, 0x6F8F, 0x9DB7, 0x6F90, + 0x9DB8, 0x6F91, 0x9DB9, 0x6F92, 0x9DBA, 0x6F93, 0x9DBB, 0x6F94, 0x9DBC, 0x6F95, 0x9DBD, 0x6F96, 0x9DBE, 0x6F97, 0x9DBF, 0x6F98, + 0x9DC0, 0x6F99, 0x9DC1, 0x6F9A, 0x9DC2, 0x6F9B, 0x9DC3, 0x6F9D, 0x9DC4, 0x6F9E, 0x9DC5, 0x6F9F, 0x9DC6, 0x6FA0, 0x9DC7, 0x6FA2, + 0x9DC8, 0x6FA3, 0x9DC9, 0x6FA4, 0x9DCA, 0x6FA5, 0x9DCB, 0x6FA6, 0x9DCC, 0x6FA8, 0x9DCD, 0x6FA9, 0x9DCE, 0x6FAA, 0x9DCF, 0x6FAB, + 0x9DD0, 0x6FAC, 0x9DD1, 0x6FAD, 0x9DD2, 0x6FAE, 0x9DD3, 0x6FAF, 0x9DD4, 0x6FB0, 0x9DD5, 0x6FB1, 0x9DD6, 0x6FB2, 0x9DD7, 0x6FB4, + 0x9DD8, 0x6FB5, 0x9DD9, 0x6FB7, 0x9DDA, 0x6FB8, 0x9DDB, 0x6FBA, 0x9DDC, 0x6FBB, 0x9DDD, 0x6FBC, 0x9DDE, 0x6FBD, 0x9DDF, 0x6FBE, + 0x9DE0, 0x6FBF, 0x9DE1, 0x6FC1, 0x9DE2, 0x6FC3, 0x9DE3, 0x6FC4, 0x9DE4, 0x6FC5, 0x9DE5, 0x6FC6, 0x9DE6, 0x6FC7, 0x9DE7, 0x6FC8, + 0x9DE8, 0x6FCA, 0x9DE9, 0x6FCB, 0x9DEA, 0x6FCC, 0x9DEB, 0x6FCD, 0x9DEC, 0x6FCE, 0x9DED, 0x6FCF, 0x9DEE, 0x6FD0, 0x9DEF, 0x6FD3, + 0x9DF0, 0x6FD4, 0x9DF1, 0x6FD5, 0x9DF2, 0x6FD6, 0x9DF3, 0x6FD7, 0x9DF4, 0x6FD8, 0x9DF5, 0x6FD9, 0x9DF6, 0x6FDA, 0x9DF7, 0x6FDB, + 0x9DF8, 0x6FDC, 0x9DF9, 0x6FDD, 0x9DFA, 0x6FDF, 0x9DFB, 0x6FE2, 0x9DFC, 0x6FE3, 0x9DFD, 0x6FE4, 0x9DFE, 0x6FE5, 0x9E40, 0x6FE6, + 0x9E41, 0x6FE7, 0x9E42, 0x6FE8, 0x9E43, 0x6FE9, 0x9E44, 0x6FEA, 0x9E45, 0x6FEB, 0x9E46, 0x6FEC, 0x9E47, 0x6FED, 0x9E48, 0x6FF0, + 0x9E49, 0x6FF1, 0x9E4A, 0x6FF2, 0x9E4B, 0x6FF3, 0x9E4C, 0x6FF4, 0x9E4D, 0x6FF5, 0x9E4E, 0x6FF6, 0x9E4F, 0x6FF7, 0x9E50, 0x6FF8, + 0x9E51, 0x6FF9, 0x9E52, 0x6FFA, 0x9E53, 0x6FFB, 0x9E54, 0x6FFC, 0x9E55, 0x6FFD, 0x9E56, 0x6FFE, 0x9E57, 0x6FFF, 0x9E58, 0x7000, + 0x9E59, 0x7001, 0x9E5A, 0x7002, 0x9E5B, 0x7003, 0x9E5C, 0x7004, 0x9E5D, 0x7005, 0x9E5E, 0x7006, 0x9E5F, 0x7007, 0x9E60, 0x7008, + 0x9E61, 0x7009, 0x9E62, 0x700A, 0x9E63, 0x700B, 0x9E64, 0x700C, 0x9E65, 0x700D, 0x9E66, 0x700E, 0x9E67, 0x700F, 0x9E68, 0x7010, + 0x9E69, 0x7012, 0x9E6A, 0x7013, 0x9E6B, 0x7014, 0x9E6C, 0x7015, 0x9E6D, 0x7016, 0x9E6E, 0x7017, 0x9E6F, 0x7018, 0x9E70, 0x7019, + 0x9E71, 0x701C, 0x9E72, 0x701D, 0x9E73, 0x701E, 0x9E74, 0x701F, 0x9E75, 0x7020, 0x9E76, 0x7021, 0x9E77, 0x7022, 0x9E78, 0x7024, + 0x9E79, 0x7025, 0x9E7A, 0x7026, 0x9E7B, 0x7027, 0x9E7C, 0x7028, 0x9E7D, 0x7029, 0x9E7E, 0x702A, 0x9E80, 0x702B, 0x9E81, 0x702C, + 0x9E82, 0x702D, 0x9E83, 0x702E, 0x9E84, 0x702F, 0x9E85, 0x7030, 0x9E86, 0x7031, 0x9E87, 0x7032, 0x9E88, 0x7033, 0x9E89, 0x7034, + 0x9E8A, 0x7036, 0x9E8B, 0x7037, 0x9E8C, 0x7038, 0x9E8D, 0x703A, 0x9E8E, 0x703B, 0x9E8F, 0x703C, 0x9E90, 0x703D, 0x9E91, 0x703E, + 0x9E92, 0x703F, 0x9E93, 0x7040, 0x9E94, 0x7041, 0x9E95, 0x7042, 0x9E96, 0x7043, 0x9E97, 0x7044, 0x9E98, 0x7045, 0x9E99, 0x7046, + 0x9E9A, 0x7047, 0x9E9B, 0x7048, 0x9E9C, 0x7049, 0x9E9D, 0x704A, 0x9E9E, 0x704B, 0x9E9F, 0x704D, 0x9EA0, 0x704E, 0x9EA1, 0x7050, + 0x9EA2, 0x7051, 0x9EA3, 0x7052, 0x9EA4, 0x7053, 0x9EA5, 0x7054, 0x9EA6, 0x7055, 0x9EA7, 0x7056, 0x9EA8, 0x7057, 0x9EA9, 0x7058, + 0x9EAA, 0x7059, 0x9EAB, 0x705A, 0x9EAC, 0x705B, 0x9EAD, 0x705C, 0x9EAE, 0x705D, 0x9EAF, 0x705F, 0x9EB0, 0x7060, 0x9EB1, 0x7061, + 0x9EB2, 0x7062, 0x9EB3, 0x7063, 0x9EB4, 0x7064, 0x9EB5, 0x7065, 0x9EB6, 0x7066, 0x9EB7, 0x7067, 0x9EB8, 0x7068, 0x9EB9, 0x7069, + 0x9EBA, 0x706A, 0x9EBB, 0x706E, 0x9EBC, 0x7071, 0x9EBD, 0x7072, 0x9EBE, 0x7073, 0x9EBF, 0x7074, 0x9EC0, 0x7077, 0x9EC1, 0x7079, + 0x9EC2, 0x707A, 0x9EC3, 0x707B, 0x9EC4, 0x707D, 0x9EC5, 0x7081, 0x9EC6, 0x7082, 0x9EC7, 0x7083, 0x9EC8, 0x7084, 0x9EC9, 0x7086, + 0x9ECA, 0x7087, 0x9ECB, 0x7088, 0x9ECC, 0x708B, 0x9ECD, 0x708C, 0x9ECE, 0x708D, 0x9ECF, 0x708F, 0x9ED0, 0x7090, 0x9ED1, 0x7091, + 0x9ED2, 0x7093, 0x9ED3, 0x7097, 0x9ED4, 0x7098, 0x9ED5, 0x709A, 0x9ED6, 0x709B, 0x9ED7, 0x709E, 0x9ED8, 0x709F, 0x9ED9, 0x70A0, + 0x9EDA, 0x70A1, 0x9EDB, 0x70A2, 0x9EDC, 0x70A3, 0x9EDD, 0x70A4, 0x9EDE, 0x70A5, 0x9EDF, 0x70A6, 0x9EE0, 0x70A7, 0x9EE1, 0x70A8, + 0x9EE2, 0x70A9, 0x9EE3, 0x70AA, 0x9EE4, 0x70B0, 0x9EE5, 0x70B2, 0x9EE6, 0x70B4, 0x9EE7, 0x70B5, 0x9EE8, 0x70B6, 0x9EE9, 0x70BA, + 0x9EEA, 0x70BE, 0x9EEB, 0x70BF, 0x9EEC, 0x70C4, 0x9EED, 0x70C5, 0x9EEE, 0x70C6, 0x9EEF, 0x70C7, 0x9EF0, 0x70C9, 0x9EF1, 0x70CB, + 0x9EF2, 0x70CC, 0x9EF3, 0x70CD, 0x9EF4, 0x70CE, 0x9EF5, 0x70CF, 0x9EF6, 0x70D0, 0x9EF7, 0x70D1, 0x9EF8, 0x70D2, 0x9EF9, 0x70D3, + 0x9EFA, 0x70D4, 0x9EFB, 0x70D5, 0x9EFC, 0x70D6, 0x9EFD, 0x70D7, 0x9EFE, 0x70DA, 0x9F40, 0x70DC, 0x9F41, 0x70DD, 0x9F42, 0x70DE, + 0x9F43, 0x70E0, 0x9F44, 0x70E1, 0x9F45, 0x70E2, 0x9F46, 0x70E3, 0x9F47, 0x70E5, 0x9F48, 0x70EA, 0x9F49, 0x70EE, 0x9F4A, 0x70F0, + 0x9F4B, 0x70F1, 0x9F4C, 0x70F2, 0x9F4D, 0x70F3, 0x9F4E, 0x70F4, 0x9F4F, 0x70F5, 0x9F50, 0x70F6, 0x9F51, 0x70F8, 0x9F52, 0x70FA, + 0x9F53, 0x70FB, 0x9F54, 0x70FC, 0x9F55, 0x70FE, 0x9F56, 0x70FF, 0x9F57, 0x7100, 0x9F58, 0x7101, 0x9F59, 0x7102, 0x9F5A, 0x7103, + 0x9F5B, 0x7104, 0x9F5C, 0x7105, 0x9F5D, 0x7106, 0x9F5E, 0x7107, 0x9F5F, 0x7108, 0x9F60, 0x710B, 0x9F61, 0x710C, 0x9F62, 0x710D, + 0x9F63, 0x710E, 0x9F64, 0x710F, 0x9F65, 0x7111, 0x9F66, 0x7112, 0x9F67, 0x7114, 0x9F68, 0x7117, 0x9F69, 0x711B, 0x9F6A, 0x711C, + 0x9F6B, 0x711D, 0x9F6C, 0x711E, 0x9F6D, 0x711F, 0x9F6E, 0x7120, 0x9F6F, 0x7121, 0x9F70, 0x7122, 0x9F71, 0x7123, 0x9F72, 0x7124, + 0x9F73, 0x7125, 0x9F74, 0x7127, 0x9F75, 0x7128, 0x9F76, 0x7129, 0x9F77, 0x712A, 0x9F78, 0x712B, 0x9F79, 0x712C, 0x9F7A, 0x712D, + 0x9F7B, 0x712E, 0x9F7C, 0x7132, 0x9F7D, 0x7133, 0x9F7E, 0x7134, 0x9F80, 0x7135, 0x9F81, 0x7137, 0x9F82, 0x7138, 0x9F83, 0x7139, + 0x9F84, 0x713A, 0x9F85, 0x713B, 0x9F86, 0x713C, 0x9F87, 0x713D, 0x9F88, 0x713E, 0x9F89, 0x713F, 0x9F8A, 0x7140, 0x9F8B, 0x7141, + 0x9F8C, 0x7142, 0x9F8D, 0x7143, 0x9F8E, 0x7144, 0x9F8F, 0x7146, 0x9F90, 0x7147, 0x9F91, 0x7148, 0x9F92, 0x7149, 0x9F93, 0x714B, + 0x9F94, 0x714D, 0x9F95, 0x714F, 0x9F96, 0x7150, 0x9F97, 0x7151, 0x9F98, 0x7152, 0x9F99, 0x7153, 0x9F9A, 0x7154, 0x9F9B, 0x7155, + 0x9F9C, 0x7156, 0x9F9D, 0x7157, 0x9F9E, 0x7158, 0x9F9F, 0x7159, 0x9FA0, 0x715A, 0x9FA1, 0x715B, 0x9FA2, 0x715D, 0x9FA3, 0x715F, + 0x9FA4, 0x7160, 0x9FA5, 0x7161, 0x9FA6, 0x7162, 0x9FA7, 0x7163, 0x9FA8, 0x7165, 0x9FA9, 0x7169, 0x9FAA, 0x716A, 0x9FAB, 0x716B, + 0x9FAC, 0x716C, 0x9FAD, 0x716D, 0x9FAE, 0x716F, 0x9FAF, 0x7170, 0x9FB0, 0x7171, 0x9FB1, 0x7174, 0x9FB2, 0x7175, 0x9FB3, 0x7176, + 0x9FB4, 0x7177, 0x9FB5, 0x7179, 0x9FB6, 0x717B, 0x9FB7, 0x717C, 0x9FB8, 0x717E, 0x9FB9, 0x717F, 0x9FBA, 0x7180, 0x9FBB, 0x7181, + 0x9FBC, 0x7182, 0x9FBD, 0x7183, 0x9FBE, 0x7185, 0x9FBF, 0x7186, 0x9FC0, 0x7187, 0x9FC1, 0x7188, 0x9FC2, 0x7189, 0x9FC3, 0x718B, + 0x9FC4, 0x718C, 0x9FC5, 0x718D, 0x9FC6, 0x718E, 0x9FC7, 0x7190, 0x9FC8, 0x7191, 0x9FC9, 0x7192, 0x9FCA, 0x7193, 0x9FCB, 0x7195, + 0x9FCC, 0x7196, 0x9FCD, 0x7197, 0x9FCE, 0x719A, 0x9FCF, 0x719B, 0x9FD0, 0x719C, 0x9FD1, 0x719D, 0x9FD2, 0x719E, 0x9FD3, 0x71A1, + 0x9FD4, 0x71A2, 0x9FD5, 0x71A3, 0x9FD6, 0x71A4, 0x9FD7, 0x71A5, 0x9FD8, 0x71A6, 0x9FD9, 0x71A7, 0x9FDA, 0x71A9, 0x9FDB, 0x71AA, + 0x9FDC, 0x71AB, 0x9FDD, 0x71AD, 0x9FDE, 0x71AE, 0x9FDF, 0x71AF, 0x9FE0, 0x71B0, 0x9FE1, 0x71B1, 0x9FE2, 0x71B2, 0x9FE3, 0x71B4, + 0x9FE4, 0x71B6, 0x9FE5, 0x71B7, 0x9FE6, 0x71B8, 0x9FE7, 0x71BA, 0x9FE8, 0x71BB, 0x9FE9, 0x71BC, 0x9FEA, 0x71BD, 0x9FEB, 0x71BE, + 0x9FEC, 0x71BF, 0x9FED, 0x71C0, 0x9FEE, 0x71C1, 0x9FEF, 0x71C2, 0x9FF0, 0x71C4, 0x9FF1, 0x71C5, 0x9FF2, 0x71C6, 0x9FF3, 0x71C7, + 0x9FF4, 0x71C8, 0x9FF5, 0x71C9, 0x9FF6, 0x71CA, 0x9FF7, 0x71CB, 0x9FF8, 0x71CC, 0x9FF9, 0x71CD, 0x9FFA, 0x71CF, 0x9FFB, 0x71D0, + 0x9FFC, 0x71D1, 0x9FFD, 0x71D2, 0x9FFE, 0x71D3, 0xA040, 0x71D6, 0xA041, 0x71D7, 0xA042, 0x71D8, 0xA043, 0x71D9, 0xA044, 0x71DA, + 0xA045, 0x71DB, 0xA046, 0x71DC, 0xA047, 0x71DD, 0xA048, 0x71DE, 0xA049, 0x71DF, 0xA04A, 0x71E1, 0xA04B, 0x71E2, 0xA04C, 0x71E3, + 0xA04D, 0x71E4, 0xA04E, 0x71E6, 0xA04F, 0x71E8, 0xA050, 0x71E9, 0xA051, 0x71EA, 0xA052, 0x71EB, 0xA053, 0x71EC, 0xA054, 0x71ED, + 0xA055, 0x71EF, 0xA056, 0x71F0, 0xA057, 0x71F1, 0xA058, 0x71F2, 0xA059, 0x71F3, 0xA05A, 0x71F4, 0xA05B, 0x71F5, 0xA05C, 0x71F6, + 0xA05D, 0x71F7, 0xA05E, 0x71F8, 0xA05F, 0x71FA, 0xA060, 0x71FB, 0xA061, 0x71FC, 0xA062, 0x71FD, 0xA063, 0x71FE, 0xA064, 0x71FF, + 0xA065, 0x7200, 0xA066, 0x7201, 0xA067, 0x7202, 0xA068, 0x7203, 0xA069, 0x7204, 0xA06A, 0x7205, 0xA06B, 0x7207, 0xA06C, 0x7208, + 0xA06D, 0x7209, 0xA06E, 0x720A, 0xA06F, 0x720B, 0xA070, 0x720C, 0xA071, 0x720D, 0xA072, 0x720E, 0xA073, 0x720F, 0xA074, 0x7210, + 0xA075, 0x7211, 0xA076, 0x7212, 0xA077, 0x7213, 0xA078, 0x7214, 0xA079, 0x7215, 0xA07A, 0x7216, 0xA07B, 0x7217, 0xA07C, 0x7218, + 0xA07D, 0x7219, 0xA07E, 0x721A, 0xA080, 0x721B, 0xA081, 0x721C, 0xA082, 0x721E, 0xA083, 0x721F, 0xA084, 0x7220, 0xA085, 0x7221, + 0xA086, 0x7222, 0xA087, 0x7223, 0xA088, 0x7224, 0xA089, 0x7225, 0xA08A, 0x7226, 0xA08B, 0x7227, 0xA08C, 0x7229, 0xA08D, 0x722B, + 0xA08E, 0x722D, 0xA08F, 0x722E, 0xA090, 0x722F, 0xA091, 0x7232, 0xA092, 0x7233, 0xA093, 0x7234, 0xA094, 0x723A, 0xA095, 0x723C, + 0xA096, 0x723E, 0xA097, 0x7240, 0xA098, 0x7241, 0xA099, 0x7242, 0xA09A, 0x7243, 0xA09B, 0x7244, 0xA09C, 0x7245, 0xA09D, 0x7246, + 0xA09E, 0x7249, 0xA09F, 0x724A, 0xA0A0, 0x724B, 0xA0A1, 0x724E, 0xA0A2, 0x724F, 0xA0A3, 0x7250, 0xA0A4, 0x7251, 0xA0A5, 0x7253, + 0xA0A6, 0x7254, 0xA0A7, 0x7255, 0xA0A8, 0x7257, 0xA0A9, 0x7258, 0xA0AA, 0x725A, 0xA0AB, 0x725C, 0xA0AC, 0x725E, 0xA0AD, 0x7260, + 0xA0AE, 0x7263, 0xA0AF, 0x7264, 0xA0B0, 0x7265, 0xA0B1, 0x7268, 0xA0B2, 0x726A, 0xA0B3, 0x726B, 0xA0B4, 0x726C, 0xA0B5, 0x726D, + 0xA0B6, 0x7270, 0xA0B7, 0x7271, 0xA0B8, 0x7273, 0xA0B9, 0x7274, 0xA0BA, 0x7276, 0xA0BB, 0x7277, 0xA0BC, 0x7278, 0xA0BD, 0x727B, + 0xA0BE, 0x727C, 0xA0BF, 0x727D, 0xA0C0, 0x7282, 0xA0C1, 0x7283, 0xA0C2, 0x7285, 0xA0C3, 0x7286, 0xA0C4, 0x7287, 0xA0C5, 0x7288, + 0xA0C6, 0x7289, 0xA0C7, 0x728C, 0xA0C8, 0x728E, 0xA0C9, 0x7290, 0xA0CA, 0x7291, 0xA0CB, 0x7293, 0xA0CC, 0x7294, 0xA0CD, 0x7295, + 0xA0CE, 0x7296, 0xA0CF, 0x7297, 0xA0D0, 0x7298, 0xA0D1, 0x7299, 0xA0D2, 0x729A, 0xA0D3, 0x729B, 0xA0D4, 0x729C, 0xA0D5, 0x729D, + 0xA0D6, 0x729E, 0xA0D7, 0x72A0, 0xA0D8, 0x72A1, 0xA0D9, 0x72A2, 0xA0DA, 0x72A3, 0xA0DB, 0x72A4, 0xA0DC, 0x72A5, 0xA0DD, 0x72A6, + 0xA0DE, 0x72A7, 0xA0DF, 0x72A8, 0xA0E0, 0x72A9, 0xA0E1, 0x72AA, 0xA0E2, 0x72AB, 0xA0E3, 0x72AE, 0xA0E4, 0x72B1, 0xA0E5, 0x72B2, + 0xA0E6, 0x72B3, 0xA0E7, 0x72B5, 0xA0E8, 0x72BA, 0xA0E9, 0x72BB, 0xA0EA, 0x72BC, 0xA0EB, 0x72BD, 0xA0EC, 0x72BE, 0xA0ED, 0x72BF, + 0xA0EE, 0x72C0, 0xA0EF, 0x72C5, 0xA0F0, 0x72C6, 0xA0F1, 0x72C7, 0xA0F2, 0x72C9, 0xA0F3, 0x72CA, 0xA0F4, 0x72CB, 0xA0F5, 0x72CC, + 0xA0F6, 0x72CF, 0xA0F7, 0x72D1, 0xA0F8, 0x72D3, 0xA0F9, 0x72D4, 0xA0FA, 0x72D5, 0xA0FB, 0x72D6, 0xA0FC, 0x72D8, 0xA0FD, 0x72DA, + 0xA0FE, 0x72DB, 0xA1A1, 0x3000, 0xA1A2, 0x3001, 0xA1A3, 0x3002, 0xA1A4, 0x00B7, 0xA1A5, 0x02C9, 0xA1A6, 0x02C7, 0xA1A7, 0x00A8, + 0xA1A8, 0x3003, 0xA1A9, 0x3005, 0xA1AA, 0x2014, 0xA1AB, 0xFF5E, 0xA1AC, 0x2016, 0xA1AD, 0x2026, 0xA1AE, 0x2018, 0xA1AF, 0x2019, + 0xA1B0, 0x201C, 0xA1B1, 0x201D, 0xA1B2, 0x3014, 0xA1B3, 0x3015, 0xA1B4, 0x3008, 0xA1B5, 0x3009, 0xA1B6, 0x300A, 0xA1B7, 0x300B, + 0xA1B8, 0x300C, 0xA1B9, 0x300D, 0xA1BA, 0x300E, 0xA1BB, 0x300F, 0xA1BC, 0x3016, 0xA1BD, 0x3017, 0xA1BE, 0x3010, 0xA1BF, 0x3011, + 0xA1C0, 0x00B1, 0xA1C1, 0x00D7, 0xA1C2, 0x00F7, 0xA1C3, 0x2236, 0xA1C4, 0x2227, 0xA1C5, 0x2228, 0xA1C6, 0x2211, 0xA1C7, 0x220F, + 0xA1C8, 0x222A, 0xA1C9, 0x2229, 0xA1CA, 0x2208, 0xA1CB, 0x2237, 0xA1CC, 0x221A, 0xA1CD, 0x22A5, 0xA1CE, 0x2225, 0xA1CF, 0x2220, + 0xA1D0, 0x2312, 0xA1D1, 0x2299, 0xA1D2, 0x222B, 0xA1D3, 0x222E, 0xA1D4, 0x2261, 0xA1D5, 0x224C, 0xA1D6, 0x2248, 0xA1D7, 0x223D, + 0xA1D8, 0x221D, 0xA1D9, 0x2260, 0xA1DA, 0x226E, 0xA1DB, 0x226F, 0xA1DC, 0x2264, 0xA1DD, 0x2265, 0xA1DE, 0x221E, 0xA1DF, 0x2235, + 0xA1E0, 0x2234, 0xA1E1, 0x2642, 0xA1E2, 0x2640, 0xA1E3, 0x00B0, 0xA1E4, 0x2032, 0xA1E5, 0x2033, 0xA1E6, 0x2103, 0xA1E7, 0xFF04, + 0xA1E8, 0x00A4, 0xA1E9, 0xFFE0, 0xA1EA, 0xFFE1, 0xA1EB, 0x2030, 0xA1EC, 0x00A7, 0xA1ED, 0x2116, 0xA1EE, 0x2606, 0xA1EF, 0x2605, + 0xA1F0, 0x25CB, 0xA1F1, 0x25CF, 0xA1F2, 0x25CE, 0xA1F3, 0x25C7, 0xA1F4, 0x25C6, 0xA1F5, 0x25A1, 0xA1F6, 0x25A0, 0xA1F7, 0x25B3, + 0xA1F8, 0x25B2, 0xA1F9, 0x203B, 0xA1FA, 0x2192, 0xA1FB, 0x2190, 0xA1FC, 0x2191, 0xA1FD, 0x2193, 0xA1FE, 0x3013, 0xA2A1, 0x2170, + 0xA2A2, 0x2171, 0xA2A3, 0x2172, 0xA2A4, 0x2173, 0xA2A5, 0x2174, 0xA2A6, 0x2175, 0xA2A7, 0x2176, 0xA2A8, 0x2177, 0xA2A9, 0x2178, + 0xA2AA, 0x2179, 0xA2B1, 0x2488, 0xA2B2, 0x2489, 0xA2B3, 0x248A, 0xA2B4, 0x248B, 0xA2B5, 0x248C, 0xA2B6, 0x248D, 0xA2B7, 0x248E, + 0xA2B8, 0x248F, 0xA2B9, 0x2490, 0xA2BA, 0x2491, 0xA2BB, 0x2492, 0xA2BC, 0x2493, 0xA2BD, 0x2494, 0xA2BE, 0x2495, 0xA2BF, 0x2496, + 0xA2C0, 0x2497, 0xA2C1, 0x2498, 0xA2C2, 0x2499, 0xA2C3, 0x249A, 0xA2C4, 0x249B, 0xA2C5, 0x2474, 0xA2C6, 0x2475, 0xA2C7, 0x2476, + 0xA2C8, 0x2477, 0xA2C9, 0x2478, 0xA2CA, 0x2479, 0xA2CB, 0x247A, 0xA2CC, 0x247B, 0xA2CD, 0x247C, 0xA2CE, 0x247D, 0xA2CF, 0x247E, + 0xA2D0, 0x247F, 0xA2D1, 0x2480, 0xA2D2, 0x2481, 0xA2D3, 0x2482, 0xA2D4, 0x2483, 0xA2D5, 0x2484, 0xA2D6, 0x2485, 0xA2D7, 0x2486, + 0xA2D8, 0x2487, 0xA2D9, 0x2460, 0xA2DA, 0x2461, 0xA2DB, 0x2462, 0xA2DC, 0x2463, 0xA2DD, 0x2464, 0xA2DE, 0x2465, 0xA2DF, 0x2466, + 0xA2E0, 0x2467, 0xA2E1, 0x2468, 0xA2E2, 0x2469, 0xA2E5, 0x3220, 0xA2E6, 0x3221, 0xA2E7, 0x3222, 0xA2E8, 0x3223, 0xA2E9, 0x3224, + 0xA2EA, 0x3225, 0xA2EB, 0x3226, 0xA2EC, 0x3227, 0xA2ED, 0x3228, 0xA2EE, 0x3229, 0xA2F1, 0x2160, 0xA2F2, 0x2161, 0xA2F3, 0x2162, + 0xA2F4, 0x2163, 0xA2F5, 0x2164, 0xA2F6, 0x2165, 0xA2F7, 0x2166, 0xA2F8, 0x2167, 0xA2F9, 0x2168, 0xA2FA, 0x2169, 0xA2FB, 0x216A, + 0xA2FC, 0x216B, 0xA3A1, 0xFF01, 0xA3A2, 0xFF02, 0xA3A3, 0xFF03, 0xA3A4, 0xFFE5, 0xA3A5, 0xFF05, 0xA3A6, 0xFF06, 0xA3A7, 0xFF07, + 0xA3A8, 0xFF08, 0xA3A9, 0xFF09, 0xA3AA, 0xFF0A, 0xA3AB, 0xFF0B, 0xA3AC, 0xFF0C, 0xA3AD, 0xFF0D, 0xA3AE, 0xFF0E, 0xA3AF, 0xFF0F, + 0xA3B0, 0xFF10, 0xA3B1, 0xFF11, 0xA3B2, 0xFF12, 0xA3B3, 0xFF13, 0xA3B4, 0xFF14, 0xA3B5, 0xFF15, 0xA3B6, 0xFF16, 0xA3B7, 0xFF17, + 0xA3B8, 0xFF18, 0xA3B9, 0xFF19, 0xA3BA, 0xFF1A, 0xA3BB, 0xFF1B, 0xA3BC, 0xFF1C, 0xA3BD, 0xFF1D, 0xA3BE, 0xFF1E, 0xA3BF, 0xFF1F, + 0xA3C0, 0xFF20, 0xA3C1, 0xFF21, 0xA3C2, 0xFF22, 0xA3C3, 0xFF23, 0xA3C4, 0xFF24, 0xA3C5, 0xFF25, 0xA3C6, 0xFF26, 0xA3C7, 0xFF27, + 0xA3C8, 0xFF28, 0xA3C9, 0xFF29, 0xA3CA, 0xFF2A, 0xA3CB, 0xFF2B, 0xA3CC, 0xFF2C, 0xA3CD, 0xFF2D, 0xA3CE, 0xFF2E, 0xA3CF, 0xFF2F, + 0xA3D0, 0xFF30, 0xA3D1, 0xFF31, 0xA3D2, 0xFF32, 0xA3D3, 0xFF33, 0xA3D4, 0xFF34, 0xA3D5, 0xFF35, 0xA3D6, 0xFF36, 0xA3D7, 0xFF37, + 0xA3D8, 0xFF38, 0xA3D9, 0xFF39, 0xA3DA, 0xFF3A, 0xA3DB, 0xFF3B, 0xA3DC, 0xFF3C, 0xA3DD, 0xFF3D, 0xA3DE, 0xFF3E, 0xA3DF, 0xFF3F, + 0xA3E0, 0xFF40, 0xA3E1, 0xFF41, 0xA3E2, 0xFF42, 0xA3E3, 0xFF43, 0xA3E4, 0xFF44, 0xA3E5, 0xFF45, 0xA3E6, 0xFF46, 0xA3E7, 0xFF47, + 0xA3E8, 0xFF48, 0xA3E9, 0xFF49, 0xA3EA, 0xFF4A, 0xA3EB, 0xFF4B, 0xA3EC, 0xFF4C, 0xA3ED, 0xFF4D, 0xA3EE, 0xFF4E, 0xA3EF, 0xFF4F, + 0xA3F0, 0xFF50, 0xA3F1, 0xFF51, 0xA3F2, 0xFF52, 0xA3F3, 0xFF53, 0xA3F4, 0xFF54, 0xA3F5, 0xFF55, 0xA3F6, 0xFF56, 0xA3F7, 0xFF57, + 0xA3F8, 0xFF58, 0xA3F9, 0xFF59, 0xA3FA, 0xFF5A, 0xA3FB, 0xFF5B, 0xA3FC, 0xFF5C, 0xA3FD, 0xFF5D, 0xA3FE, 0xFFE3, 0xA4A1, 0x3041, + 0xA4A2, 0x3042, 0xA4A3, 0x3043, 0xA4A4, 0x3044, 0xA4A5, 0x3045, 0xA4A6, 0x3046, 0xA4A7, 0x3047, 0xA4A8, 0x3048, 0xA4A9, 0x3049, + 0xA4AA, 0x304A, 0xA4AB, 0x304B, 0xA4AC, 0x304C, 0xA4AD, 0x304D, 0xA4AE, 0x304E, 0xA4AF, 0x304F, 0xA4B0, 0x3050, 0xA4B1, 0x3051, + 0xA4B2, 0x3052, 0xA4B3, 0x3053, 0xA4B4, 0x3054, 0xA4B5, 0x3055, 0xA4B6, 0x3056, 0xA4B7, 0x3057, 0xA4B8, 0x3058, 0xA4B9, 0x3059, + 0xA4BA, 0x305A, 0xA4BB, 0x305B, 0xA4BC, 0x305C, 0xA4BD, 0x305D, 0xA4BE, 0x305E, 0xA4BF, 0x305F, 0xA4C0, 0x3060, 0xA4C1, 0x3061, + 0xA4C2, 0x3062, 0xA4C3, 0x3063, 0xA4C4, 0x3064, 0xA4C5, 0x3065, 0xA4C6, 0x3066, 0xA4C7, 0x3067, 0xA4C8, 0x3068, 0xA4C9, 0x3069, + 0xA4CA, 0x306A, 0xA4CB, 0x306B, 0xA4CC, 0x306C, 0xA4CD, 0x306D, 0xA4CE, 0x306E, 0xA4CF, 0x306F, 0xA4D0, 0x3070, 0xA4D1, 0x3071, + 0xA4D2, 0x3072, 0xA4D3, 0x3073, 0xA4D4, 0x3074, 0xA4D5, 0x3075, 0xA4D6, 0x3076, 0xA4D7, 0x3077, 0xA4D8, 0x3078, 0xA4D9, 0x3079, + 0xA4DA, 0x307A, 0xA4DB, 0x307B, 0xA4DC, 0x307C, 0xA4DD, 0x307D, 0xA4DE, 0x307E, 0xA4DF, 0x307F, 0xA4E0, 0x3080, 0xA4E1, 0x3081, + 0xA4E2, 0x3082, 0xA4E3, 0x3083, 0xA4E4, 0x3084, 0xA4E5, 0x3085, 0xA4E6, 0x3086, 0xA4E7, 0x3087, 0xA4E8, 0x3088, 0xA4E9, 0x3089, + 0xA4EA, 0x308A, 0xA4EB, 0x308B, 0xA4EC, 0x308C, 0xA4ED, 0x308D, 0xA4EE, 0x308E, 0xA4EF, 0x308F, 0xA4F0, 0x3090, 0xA4F1, 0x3091, + 0xA4F2, 0x3092, 0xA4F3, 0x3093, 0xA5A1, 0x30A1, 0xA5A2, 0x30A2, 0xA5A3, 0x30A3, 0xA5A4, 0x30A4, 0xA5A5, 0x30A5, 0xA5A6, 0x30A6, + 0xA5A7, 0x30A7, 0xA5A8, 0x30A8, 0xA5A9, 0x30A9, 0xA5AA, 0x30AA, 0xA5AB, 0x30AB, 0xA5AC, 0x30AC, 0xA5AD, 0x30AD, 0xA5AE, 0x30AE, + 0xA5AF, 0x30AF, 0xA5B0, 0x30B0, 0xA5B1, 0x30B1, 0xA5B2, 0x30B2, 0xA5B3, 0x30B3, 0xA5B4, 0x30B4, 0xA5B5, 0x30B5, 0xA5B6, 0x30B6, + 0xA5B7, 0x30B7, 0xA5B8, 0x30B8, 0xA5B9, 0x30B9, 0xA5BA, 0x30BA, 0xA5BB, 0x30BB, 0xA5BC, 0x30BC, 0xA5BD, 0x30BD, 0xA5BE, 0x30BE, + 0xA5BF, 0x30BF, 0xA5C0, 0x30C0, 0xA5C1, 0x30C1, 0xA5C2, 0x30C2, 0xA5C3, 0x30C3, 0xA5C4, 0x30C4, 0xA5C5, 0x30C5, 0xA5C6, 0x30C6, + 0xA5C7, 0x30C7, 0xA5C8, 0x30C8, 0xA5C9, 0x30C9, 0xA5CA, 0x30CA, 0xA5CB, 0x30CB, 0xA5CC, 0x30CC, 0xA5CD, 0x30CD, 0xA5CE, 0x30CE, + 0xA5CF, 0x30CF, 0xA5D0, 0x30D0, 0xA5D1, 0x30D1, 0xA5D2, 0x30D2, 0xA5D3, 0x30D3, 0xA5D4, 0x30D4, 0xA5D5, 0x30D5, 0xA5D6, 0x30D6, + 0xA5D7, 0x30D7, 0xA5D8, 0x30D8, 0xA5D9, 0x30D9, 0xA5DA, 0x30DA, 0xA5DB, 0x30DB, 0xA5DC, 0x30DC, 0xA5DD, 0x30DD, 0xA5DE, 0x30DE, + 0xA5DF, 0x30DF, 0xA5E0, 0x30E0, 0xA5E1, 0x30E1, 0xA5E2, 0x30E2, 0xA5E3, 0x30E3, 0xA5E4, 0x30E4, 0xA5E5, 0x30E5, 0xA5E6, 0x30E6, + 0xA5E7, 0x30E7, 0xA5E8, 0x30E8, 0xA5E9, 0x30E9, 0xA5EA, 0x30EA, 0xA5EB, 0x30EB, 0xA5EC, 0x30EC, 0xA5ED, 0x30ED, 0xA5EE, 0x30EE, + 0xA5EF, 0x30EF, 0xA5F0, 0x30F0, 0xA5F1, 0x30F1, 0xA5F2, 0x30F2, 0xA5F3, 0x30F3, 0xA5F4, 0x30F4, 0xA5F5, 0x30F5, 0xA5F6, 0x30F6, + 0xA6A1, 0x0391, 0xA6A2, 0x0392, 0xA6A3, 0x0393, 0xA6A4, 0x0394, 0xA6A5, 0x0395, 0xA6A6, 0x0396, 0xA6A7, 0x0397, 0xA6A8, 0x0398, + 0xA6A9, 0x0399, 0xA6AA, 0x039A, 0xA6AB, 0x039B, 0xA6AC, 0x039C, 0xA6AD, 0x039D, 0xA6AE, 0x039E, 0xA6AF, 0x039F, 0xA6B0, 0x03A0, + 0xA6B1, 0x03A1, 0xA6B2, 0x03A3, 0xA6B3, 0x03A4, 0xA6B4, 0x03A5, 0xA6B5, 0x03A6, 0xA6B6, 0x03A7, 0xA6B7, 0x03A8, 0xA6B8, 0x03A9, + 0xA6C1, 0x03B1, 0xA6C2, 0x03B2, 0xA6C3, 0x03B3, 0xA6C4, 0x03B4, 0xA6C5, 0x03B5, 0xA6C6, 0x03B6, 0xA6C7, 0x03B7, 0xA6C8, 0x03B8, + 0xA6C9, 0x03B9, 0xA6CA, 0x03BA, 0xA6CB, 0x03BB, 0xA6CC, 0x03BC, 0xA6CD, 0x03BD, 0xA6CE, 0x03BE, 0xA6CF, 0x03BF, 0xA6D0, 0x03C0, + 0xA6D1, 0x03C1, 0xA6D2, 0x03C3, 0xA6D3, 0x03C4, 0xA6D4, 0x03C5, 0xA6D5, 0x03C6, 0xA6D6, 0x03C7, 0xA6D7, 0x03C8, 0xA6D8, 0x03C9, + 0xA6E0, 0xFE35, 0xA6E1, 0xFE36, 0xA6E2, 0xFE39, 0xA6E3, 0xFE3A, 0xA6E4, 0xFE3F, 0xA6E5, 0xFE40, 0xA6E6, 0xFE3D, 0xA6E7, 0xFE3E, + 0xA6E8, 0xFE41, 0xA6E9, 0xFE42, 0xA6EA, 0xFE43, 0xA6EB, 0xFE44, 0xA6EE, 0xFE3B, 0xA6EF, 0xFE3C, 0xA6F0, 0xFE37, 0xA6F1, 0xFE38, + 0xA6F2, 0xFE31, 0xA6F4, 0xFE33, 0xA6F5, 0xFE34, 0xA7A1, 0x0410, 0xA7A2, 0x0411, 0xA7A3, 0x0412, 0xA7A4, 0x0413, 0xA7A5, 0x0414, + 0xA7A6, 0x0415, 0xA7A7, 0x0401, 0xA7A8, 0x0416, 0xA7A9, 0x0417, 0xA7AA, 0x0418, 0xA7AB, 0x0419, 0xA7AC, 0x041A, 0xA7AD, 0x041B, + 0xA7AE, 0x041C, 0xA7AF, 0x041D, 0xA7B0, 0x041E, 0xA7B1, 0x041F, 0xA7B2, 0x0420, 0xA7B3, 0x0421, 0xA7B4, 0x0422, 0xA7B5, 0x0423, + 0xA7B6, 0x0424, 0xA7B7, 0x0425, 0xA7B8, 0x0426, 0xA7B9, 0x0427, 0xA7BA, 0x0428, 0xA7BB, 0x0429, 0xA7BC, 0x042A, 0xA7BD, 0x042B, + 0xA7BE, 0x042C, 0xA7BF, 0x042D, 0xA7C0, 0x042E, 0xA7C1, 0x042F, 0xA7D1, 0x0430, 0xA7D2, 0x0431, 0xA7D3, 0x0432, 0xA7D4, 0x0433, + 0xA7D5, 0x0434, 0xA7D6, 0x0435, 0xA7D7, 0x0451, 0xA7D8, 0x0436, 0xA7D9, 0x0437, 0xA7DA, 0x0438, 0xA7DB, 0x0439, 0xA7DC, 0x043A, + 0xA7DD, 0x043B, 0xA7DE, 0x043C, 0xA7DF, 0x043D, 0xA7E0, 0x043E, 0xA7E1, 0x043F, 0xA7E2, 0x0440, 0xA7E3, 0x0441, 0xA7E4, 0x0442, + 0xA7E5, 0x0443, 0xA7E6, 0x0444, 0xA7E7, 0x0445, 0xA7E8, 0x0446, 0xA7E9, 0x0447, 0xA7EA, 0x0448, 0xA7EB, 0x0449, 0xA7EC, 0x044A, + 0xA7ED, 0x044B, 0xA7EE, 0x044C, 0xA7EF, 0x044D, 0xA7F0, 0x044E, 0xA7F1, 0x044F, 0xA840, 0x02CA, 0xA841, 0x02CB, 0xA842, 0x02D9, + 0xA843, 0x2013, 0xA844, 0x2015, 0xA845, 0x2025, 0xA846, 0x2035, 0xA847, 0x2105, 0xA848, 0x2109, 0xA849, 0x2196, 0xA84A, 0x2197, + 0xA84B, 0x2198, 0xA84C, 0x2199, 0xA84D, 0x2215, 0xA84E, 0x221F, 0xA84F, 0x2223, 0xA850, 0x2252, 0xA851, 0x2266, 0xA852, 0x2267, + 0xA853, 0x22BF, 0xA854, 0x2550, 0xA855, 0x2551, 0xA856, 0x2552, 0xA857, 0x2553, 0xA858, 0x2554, 0xA859, 0x2555, 0xA85A, 0x2556, + 0xA85B, 0x2557, 0xA85C, 0x2558, 0xA85D, 0x2559, 0xA85E, 0x255A, 0xA85F, 0x255B, 0xA860, 0x255C, 0xA861, 0x255D, 0xA862, 0x255E, + 0xA863, 0x255F, 0xA864, 0x2560, 0xA865, 0x2561, 0xA866, 0x2562, 0xA867, 0x2563, 0xA868, 0x2564, 0xA869, 0x2565, 0xA86A, 0x2566, + 0xA86B, 0x2567, 0xA86C, 0x2568, 0xA86D, 0x2569, 0xA86E, 0x256A, 0xA86F, 0x256B, 0xA870, 0x256C, 0xA871, 0x256D, 0xA872, 0x256E, + 0xA873, 0x256F, 0xA874, 0x2570, 0xA875, 0x2571, 0xA876, 0x2572, 0xA877, 0x2573, 0xA878, 0x2581, 0xA879, 0x2582, 0xA87A, 0x2583, + 0xA87B, 0x2584, 0xA87C, 0x2585, 0xA87D, 0x2586, 0xA87E, 0x2587, 0xA880, 0x2588, 0xA881, 0x2589, 0xA882, 0x258A, 0xA883, 0x258B, + 0xA884, 0x258C, 0xA885, 0x258D, 0xA886, 0x258E, 0xA887, 0x258F, 0xA888, 0x2593, 0xA889, 0x2594, 0xA88A, 0x2595, 0xA88B, 0x25BC, + 0xA88C, 0x25BD, 0xA88D, 0x25E2, 0xA88E, 0x25E3, 0xA88F, 0x25E4, 0xA890, 0x25E5, 0xA891, 0x2609, 0xA892, 0x2295, 0xA893, 0x3012, + 0xA894, 0x301D, 0xA895, 0x301E, 0xA8A1, 0x0101, 0xA8A2, 0x00E1, 0xA8A3, 0x01CE, 0xA8A4, 0x00E0, 0xA8A5, 0x0113, 0xA8A6, 0x00E9, + 0xA8A7, 0x011B, 0xA8A8, 0x00E8, 0xA8A9, 0x012B, 0xA8AA, 0x00ED, 0xA8AB, 0x01D0, 0xA8AC, 0x00EC, 0xA8AD, 0x014D, 0xA8AE, 0x00F3, + 0xA8AF, 0x01D2, 0xA8B0, 0x00F2, 0xA8B1, 0x016B, 0xA8B2, 0x00FA, 0xA8B3, 0x01D4, 0xA8B4, 0x00F9, 0xA8B5, 0x01D6, 0xA8B6, 0x01D8, + 0xA8B7, 0x01DA, 0xA8B8, 0x01DC, 0xA8B9, 0x00FC, 0xA8BA, 0x00EA, 0xA8BB, 0x0251, 0xA8BD, 0x0144, 0xA8BE, 0x0148, 0xA8C0, 0x0261, + 0xA8C5, 0x3105, 0xA8C6, 0x3106, 0xA8C7, 0x3107, 0xA8C8, 0x3108, 0xA8C9, 0x3109, 0xA8CA, 0x310A, 0xA8CB, 0x310B, 0xA8CC, 0x310C, + 0xA8CD, 0x310D, 0xA8CE, 0x310E, 0xA8CF, 0x310F, 0xA8D0, 0x3110, 0xA8D1, 0x3111, 0xA8D2, 0x3112, 0xA8D3, 0x3113, 0xA8D4, 0x3114, + 0xA8D5, 0x3115, 0xA8D6, 0x3116, 0xA8D7, 0x3117, 0xA8D8, 0x3118, 0xA8D9, 0x3119, 0xA8DA, 0x311A, 0xA8DB, 0x311B, 0xA8DC, 0x311C, + 0xA8DD, 0x311D, 0xA8DE, 0x311E, 0xA8DF, 0x311F, 0xA8E0, 0x3120, 0xA8E1, 0x3121, 0xA8E2, 0x3122, 0xA8E3, 0x3123, 0xA8E4, 0x3124, + 0xA8E5, 0x3125, 0xA8E6, 0x3126, 0xA8E7, 0x3127, 0xA8E8, 0x3128, 0xA8E9, 0x3129, 0xA940, 0x3021, 0xA941, 0x3022, 0xA942, 0x3023, + 0xA943, 0x3024, 0xA944, 0x3025, 0xA945, 0x3026, 0xA946, 0x3027, 0xA947, 0x3028, 0xA948, 0x3029, 0xA949, 0x32A3, 0xA94A, 0x338E, + 0xA94B, 0x338F, 0xA94C, 0x339C, 0xA94D, 0x339D, 0xA94E, 0x339E, 0xA94F, 0x33A1, 0xA950, 0x33C4, 0xA951, 0x33CE, 0xA952, 0x33D1, + 0xA953, 0x33D2, 0xA954, 0x33D5, 0xA955, 0xFE30, 0xA956, 0xFFE2, 0xA957, 0xFFE4, 0xA959, 0x2121, 0xA95A, 0x3231, 0xA95C, 0x2010, + 0xA960, 0x30FC, 0xA961, 0x309B, 0xA962, 0x309C, 0xA963, 0x30FD, 0xA964, 0x30FE, 0xA965, 0x3006, 0xA966, 0x309D, 0xA967, 0x309E, + 0xA968, 0xFE49, 0xA969, 0xFE4A, 0xA96A, 0xFE4B, 0xA96B, 0xFE4C, 0xA96C, 0xFE4D, 0xA96D, 0xFE4E, 0xA96E, 0xFE4F, 0xA96F, 0xFE50, + 0xA970, 0xFE51, 0xA971, 0xFE52, 0xA972, 0xFE54, 0xA973, 0xFE55, 0xA974, 0xFE56, 0xA975, 0xFE57, 0xA976, 0xFE59, 0xA977, 0xFE5A, + 0xA978, 0xFE5B, 0xA979, 0xFE5C, 0xA97A, 0xFE5D, 0xA97B, 0xFE5E, 0xA97C, 0xFE5F, 0xA97D, 0xFE60, 0xA97E, 0xFE61, 0xA980, 0xFE62, + 0xA981, 0xFE63, 0xA982, 0xFE64, 0xA983, 0xFE65, 0xA984, 0xFE66, 0xA985, 0xFE68, 0xA986, 0xFE69, 0xA987, 0xFE6A, 0xA988, 0xFE6B, + 0xA996, 0x3007, 0xA9A4, 0x2500, 0xA9A5, 0x2501, 0xA9A6, 0x2502, 0xA9A7, 0x2503, 0xA9A8, 0x2504, 0xA9A9, 0x2505, 0xA9AA, 0x2506, + 0xA9AB, 0x2507, 0xA9AC, 0x2508, 0xA9AD, 0x2509, 0xA9AE, 0x250A, 0xA9AF, 0x250B, 0xA9B0, 0x250C, 0xA9B1, 0x250D, 0xA9B2, 0x250E, + 0xA9B3, 0x250F, 0xA9B4, 0x2510, 0xA9B5, 0x2511, 0xA9B6, 0x2512, 0xA9B7, 0x2513, 0xA9B8, 0x2514, 0xA9B9, 0x2515, 0xA9BA, 0x2516, + 0xA9BB, 0x2517, 0xA9BC, 0x2518, 0xA9BD, 0x2519, 0xA9BE, 0x251A, 0xA9BF, 0x251B, 0xA9C0, 0x251C, 0xA9C1, 0x251D, 0xA9C2, 0x251E, + 0xA9C3, 0x251F, 0xA9C4, 0x2520, 0xA9C5, 0x2521, 0xA9C6, 0x2522, 0xA9C7, 0x2523, 0xA9C8, 0x2524, 0xA9C9, 0x2525, 0xA9CA, 0x2526, + 0xA9CB, 0x2527, 0xA9CC, 0x2528, 0xA9CD, 0x2529, 0xA9CE, 0x252A, 0xA9CF, 0x252B, 0xA9D0, 0x252C, 0xA9D1, 0x252D, 0xA9D2, 0x252E, + 0xA9D3, 0x252F, 0xA9D4, 0x2530, 0xA9D5, 0x2531, 0xA9D6, 0x2532, 0xA9D7, 0x2533, 0xA9D8, 0x2534, 0xA9D9, 0x2535, 0xA9DA, 0x2536, + 0xA9DB, 0x2537, 0xA9DC, 0x2538, 0xA9DD, 0x2539, 0xA9DE, 0x253A, 0xA9DF, 0x253B, 0xA9E0, 0x253C, 0xA9E1, 0x253D, 0xA9E2, 0x253E, + 0xA9E3, 0x253F, 0xA9E4, 0x2540, 0xA9E5, 0x2541, 0xA9E6, 0x2542, 0xA9E7, 0x2543, 0xA9E8, 0x2544, 0xA9E9, 0x2545, 0xA9EA, 0x2546, + 0xA9EB, 0x2547, 0xA9EC, 0x2548, 0xA9ED, 0x2549, 0xA9EE, 0x254A, 0xA9EF, 0x254B, 0xAA40, 0x72DC, 0xAA41, 0x72DD, 0xAA42, 0x72DF, + 0xAA43, 0x72E2, 0xAA44, 0x72E3, 0xAA45, 0x72E4, 0xAA46, 0x72E5, 0xAA47, 0x72E6, 0xAA48, 0x72E7, 0xAA49, 0x72EA, 0xAA4A, 0x72EB, + 0xAA4B, 0x72F5, 0xAA4C, 0x72F6, 0xAA4D, 0x72F9, 0xAA4E, 0x72FD, 0xAA4F, 0x72FE, 0xAA50, 0x72FF, 0xAA51, 0x7300, 0xAA52, 0x7302, + 0xAA53, 0x7304, 0xAA54, 0x7305, 0xAA55, 0x7306, 0xAA56, 0x7307, 0xAA57, 0x7308, 0xAA58, 0x7309, 0xAA59, 0x730B, 0xAA5A, 0x730C, + 0xAA5B, 0x730D, 0xAA5C, 0x730F, 0xAA5D, 0x7310, 0xAA5E, 0x7311, 0xAA5F, 0x7312, 0xAA60, 0x7314, 0xAA61, 0x7318, 0xAA62, 0x7319, + 0xAA63, 0x731A, 0xAA64, 0x731F, 0xAA65, 0x7320, 0xAA66, 0x7323, 0xAA67, 0x7324, 0xAA68, 0x7326, 0xAA69, 0x7327, 0xAA6A, 0x7328, + 0xAA6B, 0x732D, 0xAA6C, 0x732F, 0xAA6D, 0x7330, 0xAA6E, 0x7332, 0xAA6F, 0x7333, 0xAA70, 0x7335, 0xAA71, 0x7336, 0xAA72, 0x733A, + 0xAA73, 0x733B, 0xAA74, 0x733C, 0xAA75, 0x733D, 0xAA76, 0x7340, 0xAA77, 0x7341, 0xAA78, 0x7342, 0xAA79, 0x7343, 0xAA7A, 0x7344, + 0xAA7B, 0x7345, 0xAA7C, 0x7346, 0xAA7D, 0x7347, 0xAA7E, 0x7348, 0xAA80, 0x7349, 0xAA81, 0x734A, 0xAA82, 0x734B, 0xAA83, 0x734C, + 0xAA84, 0x734E, 0xAA85, 0x734F, 0xAA86, 0x7351, 0xAA87, 0x7353, 0xAA88, 0x7354, 0xAA89, 0x7355, 0xAA8A, 0x7356, 0xAA8B, 0x7358, + 0xAA8C, 0x7359, 0xAA8D, 0x735A, 0xAA8E, 0x735B, 0xAA8F, 0x735C, 0xAA90, 0x735D, 0xAA91, 0x735E, 0xAA92, 0x735F, 0xAA93, 0x7361, + 0xAA94, 0x7362, 0xAA95, 0x7363, 0xAA96, 0x7364, 0xAA97, 0x7365, 0xAA98, 0x7366, 0xAA99, 0x7367, 0xAA9A, 0x7368, 0xAA9B, 0x7369, + 0xAA9C, 0x736A, 0xAA9D, 0x736B, 0xAA9E, 0x736E, 0xAA9F, 0x7370, 0xAAA0, 0x7371, 0xAB40, 0x7372, 0xAB41, 0x7373, 0xAB42, 0x7374, + 0xAB43, 0x7375, 0xAB44, 0x7376, 0xAB45, 0x7377, 0xAB46, 0x7378, 0xAB47, 0x7379, 0xAB48, 0x737A, 0xAB49, 0x737B, 0xAB4A, 0x737C, + 0xAB4B, 0x737D, 0xAB4C, 0x737F, 0xAB4D, 0x7380, 0xAB4E, 0x7381, 0xAB4F, 0x7382, 0xAB50, 0x7383, 0xAB51, 0x7385, 0xAB52, 0x7386, + 0xAB53, 0x7388, 0xAB54, 0x738A, 0xAB55, 0x738C, 0xAB56, 0x738D, 0xAB57, 0x738F, 0xAB58, 0x7390, 0xAB59, 0x7392, 0xAB5A, 0x7393, + 0xAB5B, 0x7394, 0xAB5C, 0x7395, 0xAB5D, 0x7397, 0xAB5E, 0x7398, 0xAB5F, 0x7399, 0xAB60, 0x739A, 0xAB61, 0x739C, 0xAB62, 0x739D, + 0xAB63, 0x739E, 0xAB64, 0x73A0, 0xAB65, 0x73A1, 0xAB66, 0x73A3, 0xAB67, 0x73A4, 0xAB68, 0x73A5, 0xAB69, 0x73A6, 0xAB6A, 0x73A7, + 0xAB6B, 0x73A8, 0xAB6C, 0x73AA, 0xAB6D, 0x73AC, 0xAB6E, 0x73AD, 0xAB6F, 0x73B1, 0xAB70, 0x73B4, 0xAB71, 0x73B5, 0xAB72, 0x73B6, + 0xAB73, 0x73B8, 0xAB74, 0x73B9, 0xAB75, 0x73BC, 0xAB76, 0x73BD, 0xAB77, 0x73BE, 0xAB78, 0x73BF, 0xAB79, 0x73C1, 0xAB7A, 0x73C3, + 0xAB7B, 0x73C4, 0xAB7C, 0x73C5, 0xAB7D, 0x73C6, 0xAB7E, 0x73C7, 0xAB80, 0x73CB, 0xAB81, 0x73CC, 0xAB82, 0x73CE, 0xAB83, 0x73D2, + 0xAB84, 0x73D3, 0xAB85, 0x73D4, 0xAB86, 0x73D5, 0xAB87, 0x73D6, 0xAB88, 0x73D7, 0xAB89, 0x73D8, 0xAB8A, 0x73DA, 0xAB8B, 0x73DB, + 0xAB8C, 0x73DC, 0xAB8D, 0x73DD, 0xAB8E, 0x73DF, 0xAB8F, 0x73E1, 0xAB90, 0x73E2, 0xAB91, 0x73E3, 0xAB92, 0x73E4, 0xAB93, 0x73E6, + 0xAB94, 0x73E8, 0xAB95, 0x73EA, 0xAB96, 0x73EB, 0xAB97, 0x73EC, 0xAB98, 0x73EE, 0xAB99, 0x73EF, 0xAB9A, 0x73F0, 0xAB9B, 0x73F1, + 0xAB9C, 0x73F3, 0xAB9D, 0x73F4, 0xAB9E, 0x73F5, 0xAB9F, 0x73F6, 0xABA0, 0x73F7, 0xAC40, 0x73F8, 0xAC41, 0x73F9, 0xAC42, 0x73FA, + 0xAC43, 0x73FB, 0xAC44, 0x73FC, 0xAC45, 0x73FD, 0xAC46, 0x73FE, 0xAC47, 0x73FF, 0xAC48, 0x7400, 0xAC49, 0x7401, 0xAC4A, 0x7402, + 0xAC4B, 0x7404, 0xAC4C, 0x7407, 0xAC4D, 0x7408, 0xAC4E, 0x740B, 0xAC4F, 0x740C, 0xAC50, 0x740D, 0xAC51, 0x740E, 0xAC52, 0x7411, + 0xAC53, 0x7412, 0xAC54, 0x7413, 0xAC55, 0x7414, 0xAC56, 0x7415, 0xAC57, 0x7416, 0xAC58, 0x7417, 0xAC59, 0x7418, 0xAC5A, 0x7419, + 0xAC5B, 0x741C, 0xAC5C, 0x741D, 0xAC5D, 0x741E, 0xAC5E, 0x741F, 0xAC5F, 0x7420, 0xAC60, 0x7421, 0xAC61, 0x7423, 0xAC62, 0x7424, + 0xAC63, 0x7427, 0xAC64, 0x7429, 0xAC65, 0x742B, 0xAC66, 0x742D, 0xAC67, 0x742F, 0xAC68, 0x7431, 0xAC69, 0x7432, 0xAC6A, 0x7437, + 0xAC6B, 0x7438, 0xAC6C, 0x7439, 0xAC6D, 0x743A, 0xAC6E, 0x743B, 0xAC6F, 0x743D, 0xAC70, 0x743E, 0xAC71, 0x743F, 0xAC72, 0x7440, + 0xAC73, 0x7442, 0xAC74, 0x7443, 0xAC75, 0x7444, 0xAC76, 0x7445, 0xAC77, 0x7446, 0xAC78, 0x7447, 0xAC79, 0x7448, 0xAC7A, 0x7449, + 0xAC7B, 0x744A, 0xAC7C, 0x744B, 0xAC7D, 0x744C, 0xAC7E, 0x744D, 0xAC80, 0x744E, 0xAC81, 0x744F, 0xAC82, 0x7450, 0xAC83, 0x7451, + 0xAC84, 0x7452, 0xAC85, 0x7453, 0xAC86, 0x7454, 0xAC87, 0x7456, 0xAC88, 0x7458, 0xAC89, 0x745D, 0xAC8A, 0x7460, 0xAC8B, 0x7461, + 0xAC8C, 0x7462, 0xAC8D, 0x7463, 0xAC8E, 0x7464, 0xAC8F, 0x7465, 0xAC90, 0x7466, 0xAC91, 0x7467, 0xAC92, 0x7468, 0xAC93, 0x7469, + 0xAC94, 0x746A, 0xAC95, 0x746B, 0xAC96, 0x746C, 0xAC97, 0x746E, 0xAC98, 0x746F, 0xAC99, 0x7471, 0xAC9A, 0x7472, 0xAC9B, 0x7473, + 0xAC9C, 0x7474, 0xAC9D, 0x7475, 0xAC9E, 0x7478, 0xAC9F, 0x7479, 0xACA0, 0x747A, 0xAD40, 0x747B, 0xAD41, 0x747C, 0xAD42, 0x747D, + 0xAD43, 0x747F, 0xAD44, 0x7482, 0xAD45, 0x7484, 0xAD46, 0x7485, 0xAD47, 0x7486, 0xAD48, 0x7488, 0xAD49, 0x7489, 0xAD4A, 0x748A, + 0xAD4B, 0x748C, 0xAD4C, 0x748D, 0xAD4D, 0x748F, 0xAD4E, 0x7491, 0xAD4F, 0x7492, 0xAD50, 0x7493, 0xAD51, 0x7494, 0xAD52, 0x7495, + 0xAD53, 0x7496, 0xAD54, 0x7497, 0xAD55, 0x7498, 0xAD56, 0x7499, 0xAD57, 0x749A, 0xAD58, 0x749B, 0xAD59, 0x749D, 0xAD5A, 0x749F, + 0xAD5B, 0x74A0, 0xAD5C, 0x74A1, 0xAD5D, 0x74A2, 0xAD5E, 0x74A3, 0xAD5F, 0x74A4, 0xAD60, 0x74A5, 0xAD61, 0x74A6, 0xAD62, 0x74AA, + 0xAD63, 0x74AB, 0xAD64, 0x74AC, 0xAD65, 0x74AD, 0xAD66, 0x74AE, 0xAD67, 0x74AF, 0xAD68, 0x74B0, 0xAD69, 0x74B1, 0xAD6A, 0x74B2, + 0xAD6B, 0x74B3, 0xAD6C, 0x74B4, 0xAD6D, 0x74B5, 0xAD6E, 0x74B6, 0xAD6F, 0x74B7, 0xAD70, 0x74B8, 0xAD71, 0x74B9, 0xAD72, 0x74BB, + 0xAD73, 0x74BC, 0xAD74, 0x74BD, 0xAD75, 0x74BE, 0xAD76, 0x74BF, 0xAD77, 0x74C0, 0xAD78, 0x74C1, 0xAD79, 0x74C2, 0xAD7A, 0x74C3, + 0xAD7B, 0x74C4, 0xAD7C, 0x74C5, 0xAD7D, 0x74C6, 0xAD7E, 0x74C7, 0xAD80, 0x74C8, 0xAD81, 0x74C9, 0xAD82, 0x74CA, 0xAD83, 0x74CB, + 0xAD84, 0x74CC, 0xAD85, 0x74CD, 0xAD86, 0x74CE, 0xAD87, 0x74CF, 0xAD88, 0x74D0, 0xAD89, 0x74D1, 0xAD8A, 0x74D3, 0xAD8B, 0x74D4, + 0xAD8C, 0x74D5, 0xAD8D, 0x74D6, 0xAD8E, 0x74D7, 0xAD8F, 0x74D8, 0xAD90, 0x74D9, 0xAD91, 0x74DA, 0xAD92, 0x74DB, 0xAD93, 0x74DD, + 0xAD94, 0x74DF, 0xAD95, 0x74E1, 0xAD96, 0x74E5, 0xAD97, 0x74E7, 0xAD98, 0x74E8, 0xAD99, 0x74E9, 0xAD9A, 0x74EA, 0xAD9B, 0x74EB, + 0xAD9C, 0x74EC, 0xAD9D, 0x74ED, 0xAD9E, 0x74F0, 0xAD9F, 0x74F1, 0xADA0, 0x74F2, 0xAE40, 0x74F3, 0xAE41, 0x74F5, 0xAE42, 0x74F8, + 0xAE43, 0x74F9, 0xAE44, 0x74FA, 0xAE45, 0x74FB, 0xAE46, 0x74FC, 0xAE47, 0x74FD, 0xAE48, 0x74FE, 0xAE49, 0x7500, 0xAE4A, 0x7501, + 0xAE4B, 0x7502, 0xAE4C, 0x7503, 0xAE4D, 0x7505, 0xAE4E, 0x7506, 0xAE4F, 0x7507, 0xAE50, 0x7508, 0xAE51, 0x7509, 0xAE52, 0x750A, + 0xAE53, 0x750B, 0xAE54, 0x750C, 0xAE55, 0x750E, 0xAE56, 0x7510, 0xAE57, 0x7512, 0xAE58, 0x7514, 0xAE59, 0x7515, 0xAE5A, 0x7516, + 0xAE5B, 0x7517, 0xAE5C, 0x751B, 0xAE5D, 0x751D, 0xAE5E, 0x751E, 0xAE5F, 0x7520, 0xAE60, 0x7521, 0xAE61, 0x7522, 0xAE62, 0x7523, + 0xAE63, 0x7524, 0xAE64, 0x7526, 0xAE65, 0x7527, 0xAE66, 0x752A, 0xAE67, 0x752E, 0xAE68, 0x7534, 0xAE69, 0x7536, 0xAE6A, 0x7539, + 0xAE6B, 0x753C, 0xAE6C, 0x753D, 0xAE6D, 0x753F, 0xAE6E, 0x7541, 0xAE6F, 0x7542, 0xAE70, 0x7543, 0xAE71, 0x7544, 0xAE72, 0x7546, + 0xAE73, 0x7547, 0xAE74, 0x7549, 0xAE75, 0x754A, 0xAE76, 0x754D, 0xAE77, 0x7550, 0xAE78, 0x7551, 0xAE79, 0x7552, 0xAE7A, 0x7553, + 0xAE7B, 0x7555, 0xAE7C, 0x7556, 0xAE7D, 0x7557, 0xAE7E, 0x7558, 0xAE80, 0x755D, 0xAE81, 0x755E, 0xAE82, 0x755F, 0xAE83, 0x7560, + 0xAE84, 0x7561, 0xAE85, 0x7562, 0xAE86, 0x7563, 0xAE87, 0x7564, 0xAE88, 0x7567, 0xAE89, 0x7568, 0xAE8A, 0x7569, 0xAE8B, 0x756B, + 0xAE8C, 0x756C, 0xAE8D, 0x756D, 0xAE8E, 0x756E, 0xAE8F, 0x756F, 0xAE90, 0x7570, 0xAE91, 0x7571, 0xAE92, 0x7573, 0xAE93, 0x7575, + 0xAE94, 0x7576, 0xAE95, 0x7577, 0xAE96, 0x757A, 0xAE97, 0x757B, 0xAE98, 0x757C, 0xAE99, 0x757D, 0xAE9A, 0x757E, 0xAE9B, 0x7580, + 0xAE9C, 0x7581, 0xAE9D, 0x7582, 0xAE9E, 0x7584, 0xAE9F, 0x7585, 0xAEA0, 0x7587, 0xAF40, 0x7588, 0xAF41, 0x7589, 0xAF42, 0x758A, + 0xAF43, 0x758C, 0xAF44, 0x758D, 0xAF45, 0x758E, 0xAF46, 0x7590, 0xAF47, 0x7593, 0xAF48, 0x7595, 0xAF49, 0x7598, 0xAF4A, 0x759B, + 0xAF4B, 0x759C, 0xAF4C, 0x759E, 0xAF4D, 0x75A2, 0xAF4E, 0x75A6, 0xAF4F, 0x75A7, 0xAF50, 0x75A8, 0xAF51, 0x75A9, 0xAF52, 0x75AA, + 0xAF53, 0x75AD, 0xAF54, 0x75B6, 0xAF55, 0x75B7, 0xAF56, 0x75BA, 0xAF57, 0x75BB, 0xAF58, 0x75BF, 0xAF59, 0x75C0, 0xAF5A, 0x75C1, + 0xAF5B, 0x75C6, 0xAF5C, 0x75CB, 0xAF5D, 0x75CC, 0xAF5E, 0x75CE, 0xAF5F, 0x75CF, 0xAF60, 0x75D0, 0xAF61, 0x75D1, 0xAF62, 0x75D3, + 0xAF63, 0x75D7, 0xAF64, 0x75D9, 0xAF65, 0x75DA, 0xAF66, 0x75DC, 0xAF67, 0x75DD, 0xAF68, 0x75DF, 0xAF69, 0x75E0, 0xAF6A, 0x75E1, + 0xAF6B, 0x75E5, 0xAF6C, 0x75E9, 0xAF6D, 0x75EC, 0xAF6E, 0x75ED, 0xAF6F, 0x75EE, 0xAF70, 0x75EF, 0xAF71, 0x75F2, 0xAF72, 0x75F3, + 0xAF73, 0x75F5, 0xAF74, 0x75F6, 0xAF75, 0x75F7, 0xAF76, 0x75F8, 0xAF77, 0x75FA, 0xAF78, 0x75FB, 0xAF79, 0x75FD, 0xAF7A, 0x75FE, + 0xAF7B, 0x7602, 0xAF7C, 0x7604, 0xAF7D, 0x7606, 0xAF7E, 0x7607, 0xAF80, 0x7608, 0xAF81, 0x7609, 0xAF82, 0x760B, 0xAF83, 0x760D, + 0xAF84, 0x760E, 0xAF85, 0x760F, 0xAF86, 0x7611, 0xAF87, 0x7612, 0xAF88, 0x7613, 0xAF89, 0x7614, 0xAF8A, 0x7616, 0xAF8B, 0x761A, + 0xAF8C, 0x761C, 0xAF8D, 0x761D, 0xAF8E, 0x761E, 0xAF8F, 0x7621, 0xAF90, 0x7623, 0xAF91, 0x7627, 0xAF92, 0x7628, 0xAF93, 0x762C, + 0xAF94, 0x762E, 0xAF95, 0x762F, 0xAF96, 0x7631, 0xAF97, 0x7632, 0xAF98, 0x7636, 0xAF99, 0x7637, 0xAF9A, 0x7639, 0xAF9B, 0x763A, + 0xAF9C, 0x763B, 0xAF9D, 0x763D, 0xAF9E, 0x7641, 0xAF9F, 0x7642, 0xAFA0, 0x7644, 0xB040, 0x7645, 0xB041, 0x7646, 0xB042, 0x7647, + 0xB043, 0x7648, 0xB044, 0x7649, 0xB045, 0x764A, 0xB046, 0x764B, 0xB047, 0x764E, 0xB048, 0x764F, 0xB049, 0x7650, 0xB04A, 0x7651, + 0xB04B, 0x7652, 0xB04C, 0x7653, 0xB04D, 0x7655, 0xB04E, 0x7657, 0xB04F, 0x7658, 0xB050, 0x7659, 0xB051, 0x765A, 0xB052, 0x765B, + 0xB053, 0x765D, 0xB054, 0x765F, 0xB055, 0x7660, 0xB056, 0x7661, 0xB057, 0x7662, 0xB058, 0x7664, 0xB059, 0x7665, 0xB05A, 0x7666, + 0xB05B, 0x7667, 0xB05C, 0x7668, 0xB05D, 0x7669, 0xB05E, 0x766A, 0xB05F, 0x766C, 0xB060, 0x766D, 0xB061, 0x766E, 0xB062, 0x7670, + 0xB063, 0x7671, 0xB064, 0x7672, 0xB065, 0x7673, 0xB066, 0x7674, 0xB067, 0x7675, 0xB068, 0x7676, 0xB069, 0x7677, 0xB06A, 0x7679, + 0xB06B, 0x767A, 0xB06C, 0x767C, 0xB06D, 0x767F, 0xB06E, 0x7680, 0xB06F, 0x7681, 0xB070, 0x7683, 0xB071, 0x7685, 0xB072, 0x7689, + 0xB073, 0x768A, 0xB074, 0x768C, 0xB075, 0x768D, 0xB076, 0x768F, 0xB077, 0x7690, 0xB078, 0x7692, 0xB079, 0x7694, 0xB07A, 0x7695, + 0xB07B, 0x7697, 0xB07C, 0x7698, 0xB07D, 0x769A, 0xB07E, 0x769B, 0xB080, 0x769C, 0xB081, 0x769D, 0xB082, 0x769E, 0xB083, 0x769F, + 0xB084, 0x76A0, 0xB085, 0x76A1, 0xB086, 0x76A2, 0xB087, 0x76A3, 0xB088, 0x76A5, 0xB089, 0x76A6, 0xB08A, 0x76A7, 0xB08B, 0x76A8, + 0xB08C, 0x76A9, 0xB08D, 0x76AA, 0xB08E, 0x76AB, 0xB08F, 0x76AC, 0xB090, 0x76AD, 0xB091, 0x76AF, 0xB092, 0x76B0, 0xB093, 0x76B3, + 0xB094, 0x76B5, 0xB095, 0x76B6, 0xB096, 0x76B7, 0xB097, 0x76B8, 0xB098, 0x76B9, 0xB099, 0x76BA, 0xB09A, 0x76BB, 0xB09B, 0x76BC, + 0xB09C, 0x76BD, 0xB09D, 0x76BE, 0xB09E, 0x76C0, 0xB09F, 0x76C1, 0xB0A0, 0x76C3, 0xB0A1, 0x554A, 0xB0A2, 0x963F, 0xB0A3, 0x57C3, + 0xB0A4, 0x6328, 0xB0A5, 0x54CE, 0xB0A6, 0x5509, 0xB0A7, 0x54C0, 0xB0A8, 0x7691, 0xB0A9, 0x764C, 0xB0AA, 0x853C, 0xB0AB, 0x77EE, + 0xB0AC, 0x827E, 0xB0AD, 0x788D, 0xB0AE, 0x7231, 0xB0AF, 0x9698, 0xB0B0, 0x978D, 0xB0B1, 0x6C28, 0xB0B2, 0x5B89, 0xB0B3, 0x4FFA, + 0xB0B4, 0x6309, 0xB0B5, 0x6697, 0xB0B6, 0x5CB8, 0xB0B7, 0x80FA, 0xB0B8, 0x6848, 0xB0B9, 0x80AE, 0xB0BA, 0x6602, 0xB0BB, 0x76CE, + 0xB0BC, 0x51F9, 0xB0BD, 0x6556, 0xB0BE, 0x71AC, 0xB0BF, 0x7FF1, 0xB0C0, 0x8884, 0xB0C1, 0x50B2, 0xB0C2, 0x5965, 0xB0C3, 0x61CA, + 0xB0C4, 0x6FB3, 0xB0C5, 0x82AD, 0xB0C6, 0x634C, 0xB0C7, 0x6252, 0xB0C8, 0x53ED, 0xB0C9, 0x5427, 0xB0CA, 0x7B06, 0xB0CB, 0x516B, + 0xB0CC, 0x75A4, 0xB0CD, 0x5DF4, 0xB0CE, 0x62D4, 0xB0CF, 0x8DCB, 0xB0D0, 0x9776, 0xB0D1, 0x628A, 0xB0D2, 0x8019, 0xB0D3, 0x575D, + 0xB0D4, 0x9738, 0xB0D5, 0x7F62, 0xB0D6, 0x7238, 0xB0D7, 0x767D, 0xB0D8, 0x67CF, 0xB0D9, 0x767E, 0xB0DA, 0x6446, 0xB0DB, 0x4F70, + 0xB0DC, 0x8D25, 0xB0DD, 0x62DC, 0xB0DE, 0x7A17, 0xB0DF, 0x6591, 0xB0E0, 0x73ED, 0xB0E1, 0x642C, 0xB0E2, 0x6273, 0xB0E3, 0x822C, + 0xB0E4, 0x9881, 0xB0E5, 0x677F, 0xB0E6, 0x7248, 0xB0E7, 0x626E, 0xB0E8, 0x62CC, 0xB0E9, 0x4F34, 0xB0EA, 0x74E3, 0xB0EB, 0x534A, + 0xB0EC, 0x529E, 0xB0ED, 0x7ECA, 0xB0EE, 0x90A6, 0xB0EF, 0x5E2E, 0xB0F0, 0x6886, 0xB0F1, 0x699C, 0xB0F2, 0x8180, 0xB0F3, 0x7ED1, + 0xB0F4, 0x68D2, 0xB0F5, 0x78C5, 0xB0F6, 0x868C, 0xB0F7, 0x9551, 0xB0F8, 0x508D, 0xB0F9, 0x8C24, 0xB0FA, 0x82DE, 0xB0FB, 0x80DE, + 0xB0FC, 0x5305, 0xB0FD, 0x8912, 0xB0FE, 0x5265, 0xB140, 0x76C4, 0xB141, 0x76C7, 0xB142, 0x76C9, 0xB143, 0x76CB, 0xB144, 0x76CC, + 0xB145, 0x76D3, 0xB146, 0x76D5, 0xB147, 0x76D9, 0xB148, 0x76DA, 0xB149, 0x76DC, 0xB14A, 0x76DD, 0xB14B, 0x76DE, 0xB14C, 0x76E0, + 0xB14D, 0x76E1, 0xB14E, 0x76E2, 0xB14F, 0x76E3, 0xB150, 0x76E4, 0xB151, 0x76E6, 0xB152, 0x76E7, 0xB153, 0x76E8, 0xB154, 0x76E9, + 0xB155, 0x76EA, 0xB156, 0x76EB, 0xB157, 0x76EC, 0xB158, 0x76ED, 0xB159, 0x76F0, 0xB15A, 0x76F3, 0xB15B, 0x76F5, 0xB15C, 0x76F6, + 0xB15D, 0x76F7, 0xB15E, 0x76FA, 0xB15F, 0x76FB, 0xB160, 0x76FD, 0xB161, 0x76FF, 0xB162, 0x7700, 0xB163, 0x7702, 0xB164, 0x7703, + 0xB165, 0x7705, 0xB166, 0x7706, 0xB167, 0x770A, 0xB168, 0x770C, 0xB169, 0x770E, 0xB16A, 0x770F, 0xB16B, 0x7710, 0xB16C, 0x7711, + 0xB16D, 0x7712, 0xB16E, 0x7713, 0xB16F, 0x7714, 0xB170, 0x7715, 0xB171, 0x7716, 0xB172, 0x7717, 0xB173, 0x7718, 0xB174, 0x771B, + 0xB175, 0x771C, 0xB176, 0x771D, 0xB177, 0x771E, 0xB178, 0x7721, 0xB179, 0x7723, 0xB17A, 0x7724, 0xB17B, 0x7725, 0xB17C, 0x7727, + 0xB17D, 0x772A, 0xB17E, 0x772B, 0xB180, 0x772C, 0xB181, 0x772E, 0xB182, 0x7730, 0xB183, 0x7731, 0xB184, 0x7732, 0xB185, 0x7733, + 0xB186, 0x7734, 0xB187, 0x7739, 0xB188, 0x773B, 0xB189, 0x773D, 0xB18A, 0x773E, 0xB18B, 0x773F, 0xB18C, 0x7742, 0xB18D, 0x7744, + 0xB18E, 0x7745, 0xB18F, 0x7746, 0xB190, 0x7748, 0xB191, 0x7749, 0xB192, 0x774A, 0xB193, 0x774B, 0xB194, 0x774C, 0xB195, 0x774D, + 0xB196, 0x774E, 0xB197, 0x774F, 0xB198, 0x7752, 0xB199, 0x7753, 0xB19A, 0x7754, 0xB19B, 0x7755, 0xB19C, 0x7756, 0xB19D, 0x7757, + 0xB19E, 0x7758, 0xB19F, 0x7759, 0xB1A0, 0x775C, 0xB1A1, 0x8584, 0xB1A2, 0x96F9, 0xB1A3, 0x4FDD, 0xB1A4, 0x5821, 0xB1A5, 0x9971, + 0xB1A6, 0x5B9D, 0xB1A7, 0x62B1, 0xB1A8, 0x62A5, 0xB1A9, 0x66B4, 0xB1AA, 0x8C79, 0xB1AB, 0x9C8D, 0xB1AC, 0x7206, 0xB1AD, 0x676F, + 0xB1AE, 0x7891, 0xB1AF, 0x60B2, 0xB1B0, 0x5351, 0xB1B1, 0x5317, 0xB1B2, 0x8F88, 0xB1B3, 0x80CC, 0xB1B4, 0x8D1D, 0xB1B5, 0x94A1, + 0xB1B6, 0x500D, 0xB1B7, 0x72C8, 0xB1B8, 0x5907, 0xB1B9, 0x60EB, 0xB1BA, 0x7119, 0xB1BB, 0x88AB, 0xB1BC, 0x5954, 0xB1BD, 0x82EF, + 0xB1BE, 0x672C, 0xB1BF, 0x7B28, 0xB1C0, 0x5D29, 0xB1C1, 0x7EF7, 0xB1C2, 0x752D, 0xB1C3, 0x6CF5, 0xB1C4, 0x8E66, 0xB1C5, 0x8FF8, + 0xB1C6, 0x903C, 0xB1C7, 0x9F3B, 0xB1C8, 0x6BD4, 0xB1C9, 0x9119, 0xB1CA, 0x7B14, 0xB1CB, 0x5F7C, 0xB1CC, 0x78A7, 0xB1CD, 0x84D6, + 0xB1CE, 0x853D, 0xB1CF, 0x6BD5, 0xB1D0, 0x6BD9, 0xB1D1, 0x6BD6, 0xB1D2, 0x5E01, 0xB1D3, 0x5E87, 0xB1D4, 0x75F9, 0xB1D5, 0x95ED, + 0xB1D6, 0x655D, 0xB1D7, 0x5F0A, 0xB1D8, 0x5FC5, 0xB1D9, 0x8F9F, 0xB1DA, 0x58C1, 0xB1DB, 0x81C2, 0xB1DC, 0x907F, 0xB1DD, 0x965B, + 0xB1DE, 0x97AD, 0xB1DF, 0x8FB9, 0xB1E0, 0x7F16, 0xB1E1, 0x8D2C, 0xB1E2, 0x6241, 0xB1E3, 0x4FBF, 0xB1E4, 0x53D8, 0xB1E5, 0x535E, + 0xB1E6, 0x8FA8, 0xB1E7, 0x8FA9, 0xB1E8, 0x8FAB, 0xB1E9, 0x904D, 0xB1EA, 0x6807, 0xB1EB, 0x5F6A, 0xB1EC, 0x8198, 0xB1ED, 0x8868, + 0xB1EE, 0x9CD6, 0xB1EF, 0x618B, 0xB1F0, 0x522B, 0xB1F1, 0x762A, 0xB1F2, 0x5F6C, 0xB1F3, 0x658C, 0xB1F4, 0x6FD2, 0xB1F5, 0x6EE8, + 0xB1F6, 0x5BBE, 0xB1F7, 0x6448, 0xB1F8, 0x5175, 0xB1F9, 0x51B0, 0xB1FA, 0x67C4, 0xB1FB, 0x4E19, 0xB1FC, 0x79C9, 0xB1FD, 0x997C, + 0xB1FE, 0x70B3, 0xB240, 0x775D, 0xB241, 0x775E, 0xB242, 0x775F, 0xB243, 0x7760, 0xB244, 0x7764, 0xB245, 0x7767, 0xB246, 0x7769, + 0xB247, 0x776A, 0xB248, 0x776D, 0xB249, 0x776E, 0xB24A, 0x776F, 0xB24B, 0x7770, 0xB24C, 0x7771, 0xB24D, 0x7772, 0xB24E, 0x7773, + 0xB24F, 0x7774, 0xB250, 0x7775, 0xB251, 0x7776, 0xB252, 0x7777, 0xB253, 0x7778, 0xB254, 0x777A, 0xB255, 0x777B, 0xB256, 0x777C, + 0xB257, 0x7781, 0xB258, 0x7782, 0xB259, 0x7783, 0xB25A, 0x7786, 0xB25B, 0x7787, 0xB25C, 0x7788, 0xB25D, 0x7789, 0xB25E, 0x778A, + 0xB25F, 0x778B, 0xB260, 0x778F, 0xB261, 0x7790, 0xB262, 0x7793, 0xB263, 0x7794, 0xB264, 0x7795, 0xB265, 0x7796, 0xB266, 0x7797, + 0xB267, 0x7798, 0xB268, 0x7799, 0xB269, 0x779A, 0xB26A, 0x779B, 0xB26B, 0x779C, 0xB26C, 0x779D, 0xB26D, 0x779E, 0xB26E, 0x77A1, + 0xB26F, 0x77A3, 0xB270, 0x77A4, 0xB271, 0x77A6, 0xB272, 0x77A8, 0xB273, 0x77AB, 0xB274, 0x77AD, 0xB275, 0x77AE, 0xB276, 0x77AF, + 0xB277, 0x77B1, 0xB278, 0x77B2, 0xB279, 0x77B4, 0xB27A, 0x77B6, 0xB27B, 0x77B7, 0xB27C, 0x77B8, 0xB27D, 0x77B9, 0xB27E, 0x77BA, + 0xB280, 0x77BC, 0xB281, 0x77BE, 0xB282, 0x77C0, 0xB283, 0x77C1, 0xB284, 0x77C2, 0xB285, 0x77C3, 0xB286, 0x77C4, 0xB287, 0x77C5, + 0xB288, 0x77C6, 0xB289, 0x77C7, 0xB28A, 0x77C8, 0xB28B, 0x77C9, 0xB28C, 0x77CA, 0xB28D, 0x77CB, 0xB28E, 0x77CC, 0xB28F, 0x77CE, + 0xB290, 0x77CF, 0xB291, 0x77D0, 0xB292, 0x77D1, 0xB293, 0x77D2, 0xB294, 0x77D3, 0xB295, 0x77D4, 0xB296, 0x77D5, 0xB297, 0x77D6, + 0xB298, 0x77D8, 0xB299, 0x77D9, 0xB29A, 0x77DA, 0xB29B, 0x77DD, 0xB29C, 0x77DE, 0xB29D, 0x77DF, 0xB29E, 0x77E0, 0xB29F, 0x77E1, + 0xB2A0, 0x77E4, 0xB2A1, 0x75C5, 0xB2A2, 0x5E76, 0xB2A3, 0x73BB, 0xB2A4, 0x83E0, 0xB2A5, 0x64AD, 0xB2A6, 0x62E8, 0xB2A7, 0x94B5, + 0xB2A8, 0x6CE2, 0xB2A9, 0x535A, 0xB2AA, 0x52C3, 0xB2AB, 0x640F, 0xB2AC, 0x94C2, 0xB2AD, 0x7B94, 0xB2AE, 0x4F2F, 0xB2AF, 0x5E1B, + 0xB2B0, 0x8236, 0xB2B1, 0x8116, 0xB2B2, 0x818A, 0xB2B3, 0x6E24, 0xB2B4, 0x6CCA, 0xB2B5, 0x9A73, 0xB2B6, 0x6355, 0xB2B7, 0x535C, + 0xB2B8, 0x54FA, 0xB2B9, 0x8865, 0xB2BA, 0x57E0, 0xB2BB, 0x4E0D, 0xB2BC, 0x5E03, 0xB2BD, 0x6B65, 0xB2BE, 0x7C3F, 0xB2BF, 0x90E8, + 0xB2C0, 0x6016, 0xB2C1, 0x64E6, 0xB2C2, 0x731C, 0xB2C3, 0x88C1, 0xB2C4, 0x6750, 0xB2C5, 0x624D, 0xB2C6, 0x8D22, 0xB2C7, 0x776C, + 0xB2C8, 0x8E29, 0xB2C9, 0x91C7, 0xB2CA, 0x5F69, 0xB2CB, 0x83DC, 0xB2CC, 0x8521, 0xB2CD, 0x9910, 0xB2CE, 0x53C2, 0xB2CF, 0x8695, + 0xB2D0, 0x6B8B, 0xB2D1, 0x60ED, 0xB2D2, 0x60E8, 0xB2D3, 0x707F, 0xB2D4, 0x82CD, 0xB2D5, 0x8231, 0xB2D6, 0x4ED3, 0xB2D7, 0x6CA7, + 0xB2D8, 0x85CF, 0xB2D9, 0x64CD, 0xB2DA, 0x7CD9, 0xB2DB, 0x69FD, 0xB2DC, 0x66F9, 0xB2DD, 0x8349, 0xB2DE, 0x5395, 0xB2DF, 0x7B56, + 0xB2E0, 0x4FA7, 0xB2E1, 0x518C, 0xB2E2, 0x6D4B, 0xB2E3, 0x5C42, 0xB2E4, 0x8E6D, 0xB2E5, 0x63D2, 0xB2E6, 0x53C9, 0xB2E7, 0x832C, + 0xB2E8, 0x8336, 0xB2E9, 0x67E5, 0xB2EA, 0x78B4, 0xB2EB, 0x643D, 0xB2EC, 0x5BDF, 0xB2ED, 0x5C94, 0xB2EE, 0x5DEE, 0xB2EF, 0x8BE7, + 0xB2F0, 0x62C6, 0xB2F1, 0x67F4, 0xB2F2, 0x8C7A, 0xB2F3, 0x6400, 0xB2F4, 0x63BA, 0xB2F5, 0x8749, 0xB2F6, 0x998B, 0xB2F7, 0x8C17, + 0xB2F8, 0x7F20, 0xB2F9, 0x94F2, 0xB2FA, 0x4EA7, 0xB2FB, 0x9610, 0xB2FC, 0x98A4, 0xB2FD, 0x660C, 0xB2FE, 0x7316, 0xB340, 0x77E6, + 0xB341, 0x77E8, 0xB342, 0x77EA, 0xB343, 0x77EF, 0xB344, 0x77F0, 0xB345, 0x77F1, 0xB346, 0x77F2, 0xB347, 0x77F4, 0xB348, 0x77F5, + 0xB349, 0x77F7, 0xB34A, 0x77F9, 0xB34B, 0x77FA, 0xB34C, 0x77FB, 0xB34D, 0x77FC, 0xB34E, 0x7803, 0xB34F, 0x7804, 0xB350, 0x7805, + 0xB351, 0x7806, 0xB352, 0x7807, 0xB353, 0x7808, 0xB354, 0x780A, 0xB355, 0x780B, 0xB356, 0x780E, 0xB357, 0x780F, 0xB358, 0x7810, + 0xB359, 0x7813, 0xB35A, 0x7815, 0xB35B, 0x7819, 0xB35C, 0x781B, 0xB35D, 0x781E, 0xB35E, 0x7820, 0xB35F, 0x7821, 0xB360, 0x7822, + 0xB361, 0x7824, 0xB362, 0x7828, 0xB363, 0x782A, 0xB364, 0x782B, 0xB365, 0x782E, 0xB366, 0x782F, 0xB367, 0x7831, 0xB368, 0x7832, + 0xB369, 0x7833, 0xB36A, 0x7835, 0xB36B, 0x7836, 0xB36C, 0x783D, 0xB36D, 0x783F, 0xB36E, 0x7841, 0xB36F, 0x7842, 0xB370, 0x7843, + 0xB371, 0x7844, 0xB372, 0x7846, 0xB373, 0x7848, 0xB374, 0x7849, 0xB375, 0x784A, 0xB376, 0x784B, 0xB377, 0x784D, 0xB378, 0x784F, + 0xB379, 0x7851, 0xB37A, 0x7853, 0xB37B, 0x7854, 0xB37C, 0x7858, 0xB37D, 0x7859, 0xB37E, 0x785A, 0xB380, 0x785B, 0xB381, 0x785C, + 0xB382, 0x785E, 0xB383, 0x785F, 0xB384, 0x7860, 0xB385, 0x7861, 0xB386, 0x7862, 0xB387, 0x7863, 0xB388, 0x7864, 0xB389, 0x7865, + 0xB38A, 0x7866, 0xB38B, 0x7867, 0xB38C, 0x7868, 0xB38D, 0x7869, 0xB38E, 0x786F, 0xB38F, 0x7870, 0xB390, 0x7871, 0xB391, 0x7872, + 0xB392, 0x7873, 0xB393, 0x7874, 0xB394, 0x7875, 0xB395, 0x7876, 0xB396, 0x7878, 0xB397, 0x7879, 0xB398, 0x787A, 0xB399, 0x787B, + 0xB39A, 0x787D, 0xB39B, 0x787E, 0xB39C, 0x787F, 0xB39D, 0x7880, 0xB39E, 0x7881, 0xB39F, 0x7882, 0xB3A0, 0x7883, 0xB3A1, 0x573A, + 0xB3A2, 0x5C1D, 0xB3A3, 0x5E38, 0xB3A4, 0x957F, 0xB3A5, 0x507F, 0xB3A6, 0x80A0, 0xB3A7, 0x5382, 0xB3A8, 0x655E, 0xB3A9, 0x7545, + 0xB3AA, 0x5531, 0xB3AB, 0x5021, 0xB3AC, 0x8D85, 0xB3AD, 0x6284, 0xB3AE, 0x949E, 0xB3AF, 0x671D, 0xB3B0, 0x5632, 0xB3B1, 0x6F6E, + 0xB3B2, 0x5DE2, 0xB3B3, 0x5435, 0xB3B4, 0x7092, 0xB3B5, 0x8F66, 0xB3B6, 0x626F, 0xB3B7, 0x64A4, 0xB3B8, 0x63A3, 0xB3B9, 0x5F7B, + 0xB3BA, 0x6F88, 0xB3BB, 0x90F4, 0xB3BC, 0x81E3, 0xB3BD, 0x8FB0, 0xB3BE, 0x5C18, 0xB3BF, 0x6668, 0xB3C0, 0x5FF1, 0xB3C1, 0x6C89, + 0xB3C2, 0x9648, 0xB3C3, 0x8D81, 0xB3C4, 0x886C, 0xB3C5, 0x6491, 0xB3C6, 0x79F0, 0xB3C7, 0x57CE, 0xB3C8, 0x6A59, 0xB3C9, 0x6210, + 0xB3CA, 0x5448, 0xB3CB, 0x4E58, 0xB3CC, 0x7A0B, 0xB3CD, 0x60E9, 0xB3CE, 0x6F84, 0xB3CF, 0x8BDA, 0xB3D0, 0x627F, 0xB3D1, 0x901E, + 0xB3D2, 0x9A8B, 0xB3D3, 0x79E4, 0xB3D4, 0x5403, 0xB3D5, 0x75F4, 0xB3D6, 0x6301, 0xB3D7, 0x5319, 0xB3D8, 0x6C60, 0xB3D9, 0x8FDF, + 0xB3DA, 0x5F1B, 0xB3DB, 0x9A70, 0xB3DC, 0x803B, 0xB3DD, 0x9F7F, 0xB3DE, 0x4F88, 0xB3DF, 0x5C3A, 0xB3E0, 0x8D64, 0xB3E1, 0x7FC5, + 0xB3E2, 0x65A5, 0xB3E3, 0x70BD, 0xB3E4, 0x5145, 0xB3E5, 0x51B2, 0xB3E6, 0x866B, 0xB3E7, 0x5D07, 0xB3E8, 0x5BA0, 0xB3E9, 0x62BD, + 0xB3EA, 0x916C, 0xB3EB, 0x7574, 0xB3EC, 0x8E0C, 0xB3ED, 0x7A20, 0xB3EE, 0x6101, 0xB3EF, 0x7B79, 0xB3F0, 0x4EC7, 0xB3F1, 0x7EF8, + 0xB3F2, 0x7785, 0xB3F3, 0x4E11, 0xB3F4, 0x81ED, 0xB3F5, 0x521D, 0xB3F6, 0x51FA, 0xB3F7, 0x6A71, 0xB3F8, 0x53A8, 0xB3F9, 0x8E87, + 0xB3FA, 0x9504, 0xB3FB, 0x96CF, 0xB3FC, 0x6EC1, 0xB3FD, 0x9664, 0xB3FE, 0x695A, 0xB440, 0x7884, 0xB441, 0x7885, 0xB442, 0x7886, + 0xB443, 0x7888, 0xB444, 0x788A, 0xB445, 0x788B, 0xB446, 0x788F, 0xB447, 0x7890, 0xB448, 0x7892, 0xB449, 0x7894, 0xB44A, 0x7895, + 0xB44B, 0x7896, 0xB44C, 0x7899, 0xB44D, 0x789D, 0xB44E, 0x789E, 0xB44F, 0x78A0, 0xB450, 0x78A2, 0xB451, 0x78A4, 0xB452, 0x78A6, + 0xB453, 0x78A8, 0xB454, 0x78A9, 0xB455, 0x78AA, 0xB456, 0x78AB, 0xB457, 0x78AC, 0xB458, 0x78AD, 0xB459, 0x78AE, 0xB45A, 0x78AF, + 0xB45B, 0x78B5, 0xB45C, 0x78B6, 0xB45D, 0x78B7, 0xB45E, 0x78B8, 0xB45F, 0x78BA, 0xB460, 0x78BB, 0xB461, 0x78BC, 0xB462, 0x78BD, + 0xB463, 0x78BF, 0xB464, 0x78C0, 0xB465, 0x78C2, 0xB466, 0x78C3, 0xB467, 0x78C4, 0xB468, 0x78C6, 0xB469, 0x78C7, 0xB46A, 0x78C8, + 0xB46B, 0x78CC, 0xB46C, 0x78CD, 0xB46D, 0x78CE, 0xB46E, 0x78CF, 0xB46F, 0x78D1, 0xB470, 0x78D2, 0xB471, 0x78D3, 0xB472, 0x78D6, + 0xB473, 0x78D7, 0xB474, 0x78D8, 0xB475, 0x78DA, 0xB476, 0x78DB, 0xB477, 0x78DC, 0xB478, 0x78DD, 0xB479, 0x78DE, 0xB47A, 0x78DF, + 0xB47B, 0x78E0, 0xB47C, 0x78E1, 0xB47D, 0x78E2, 0xB47E, 0x78E3, 0xB480, 0x78E4, 0xB481, 0x78E5, 0xB482, 0x78E6, 0xB483, 0x78E7, + 0xB484, 0x78E9, 0xB485, 0x78EA, 0xB486, 0x78EB, 0xB487, 0x78ED, 0xB488, 0x78EE, 0xB489, 0x78EF, 0xB48A, 0x78F0, 0xB48B, 0x78F1, + 0xB48C, 0x78F3, 0xB48D, 0x78F5, 0xB48E, 0x78F6, 0xB48F, 0x78F8, 0xB490, 0x78F9, 0xB491, 0x78FB, 0xB492, 0x78FC, 0xB493, 0x78FD, + 0xB494, 0x78FE, 0xB495, 0x78FF, 0xB496, 0x7900, 0xB497, 0x7902, 0xB498, 0x7903, 0xB499, 0x7904, 0xB49A, 0x7906, 0xB49B, 0x7907, + 0xB49C, 0x7908, 0xB49D, 0x7909, 0xB49E, 0x790A, 0xB49F, 0x790B, 0xB4A0, 0x790C, 0xB4A1, 0x7840, 0xB4A2, 0x50A8, 0xB4A3, 0x77D7, + 0xB4A4, 0x6410, 0xB4A5, 0x89E6, 0xB4A6, 0x5904, 0xB4A7, 0x63E3, 0xB4A8, 0x5DDD, 0xB4A9, 0x7A7F, 0xB4AA, 0x693D, 0xB4AB, 0x4F20, + 0xB4AC, 0x8239, 0xB4AD, 0x5598, 0xB4AE, 0x4E32, 0xB4AF, 0x75AE, 0xB4B0, 0x7A97, 0xB4B1, 0x5E62, 0xB4B2, 0x5E8A, 0xB4B3, 0x95EF, + 0xB4B4, 0x521B, 0xB4B5, 0x5439, 0xB4B6, 0x708A, 0xB4B7, 0x6376, 0xB4B8, 0x9524, 0xB4B9, 0x5782, 0xB4BA, 0x6625, 0xB4BB, 0x693F, + 0xB4BC, 0x9187, 0xB4BD, 0x5507, 0xB4BE, 0x6DF3, 0xB4BF, 0x7EAF, 0xB4C0, 0x8822, 0xB4C1, 0x6233, 0xB4C2, 0x7EF0, 0xB4C3, 0x75B5, + 0xB4C4, 0x8328, 0xB4C5, 0x78C1, 0xB4C6, 0x96CC, 0xB4C7, 0x8F9E, 0xB4C8, 0x6148, 0xB4C9, 0x74F7, 0xB4CA, 0x8BCD, 0xB4CB, 0x6B64, + 0xB4CC, 0x523A, 0xB4CD, 0x8D50, 0xB4CE, 0x6B21, 0xB4CF, 0x806A, 0xB4D0, 0x8471, 0xB4D1, 0x56F1, 0xB4D2, 0x5306, 0xB4D3, 0x4ECE, + 0xB4D4, 0x4E1B, 0xB4D5, 0x51D1, 0xB4D6, 0x7C97, 0xB4D7, 0x918B, 0xB4D8, 0x7C07, 0xB4D9, 0x4FC3, 0xB4DA, 0x8E7F, 0xB4DB, 0x7BE1, + 0xB4DC, 0x7A9C, 0xB4DD, 0x6467, 0xB4DE, 0x5D14, 0xB4DF, 0x50AC, 0xB4E0, 0x8106, 0xB4E1, 0x7601, 0xB4E2, 0x7CB9, 0xB4E3, 0x6DEC, + 0xB4E4, 0x7FE0, 0xB4E5, 0x6751, 0xB4E6, 0x5B58, 0xB4E7, 0x5BF8, 0xB4E8, 0x78CB, 0xB4E9, 0x64AE, 0xB4EA, 0x6413, 0xB4EB, 0x63AA, + 0xB4EC, 0x632B, 0xB4ED, 0x9519, 0xB4EE, 0x642D, 0xB4EF, 0x8FBE, 0xB4F0, 0x7B54, 0xB4F1, 0x7629, 0xB4F2, 0x6253, 0xB4F3, 0x5927, + 0xB4F4, 0x5446, 0xB4F5, 0x6B79, 0xB4F6, 0x50A3, 0xB4F7, 0x6234, 0xB4F8, 0x5E26, 0xB4F9, 0x6B86, 0xB4FA, 0x4EE3, 0xB4FB, 0x8D37, + 0xB4FC, 0x888B, 0xB4FD, 0x5F85, 0xB4FE, 0x902E, 0xB540, 0x790D, 0xB541, 0x790E, 0xB542, 0x790F, 0xB543, 0x7910, 0xB544, 0x7911, + 0xB545, 0x7912, 0xB546, 0x7914, 0xB547, 0x7915, 0xB548, 0x7916, 0xB549, 0x7917, 0xB54A, 0x7918, 0xB54B, 0x7919, 0xB54C, 0x791A, + 0xB54D, 0x791B, 0xB54E, 0x791C, 0xB54F, 0x791D, 0xB550, 0x791F, 0xB551, 0x7920, 0xB552, 0x7921, 0xB553, 0x7922, 0xB554, 0x7923, + 0xB555, 0x7925, 0xB556, 0x7926, 0xB557, 0x7927, 0xB558, 0x7928, 0xB559, 0x7929, 0xB55A, 0x792A, 0xB55B, 0x792B, 0xB55C, 0x792C, + 0xB55D, 0x792D, 0xB55E, 0x792E, 0xB55F, 0x792F, 0xB560, 0x7930, 0xB561, 0x7931, 0xB562, 0x7932, 0xB563, 0x7933, 0xB564, 0x7935, + 0xB565, 0x7936, 0xB566, 0x7937, 0xB567, 0x7938, 0xB568, 0x7939, 0xB569, 0x793D, 0xB56A, 0x793F, 0xB56B, 0x7942, 0xB56C, 0x7943, + 0xB56D, 0x7944, 0xB56E, 0x7945, 0xB56F, 0x7947, 0xB570, 0x794A, 0xB571, 0x794B, 0xB572, 0x794C, 0xB573, 0x794D, 0xB574, 0x794E, + 0xB575, 0x794F, 0xB576, 0x7950, 0xB577, 0x7951, 0xB578, 0x7952, 0xB579, 0x7954, 0xB57A, 0x7955, 0xB57B, 0x7958, 0xB57C, 0x7959, + 0xB57D, 0x7961, 0xB57E, 0x7963, 0xB580, 0x7964, 0xB581, 0x7966, 0xB582, 0x7969, 0xB583, 0x796A, 0xB584, 0x796B, 0xB585, 0x796C, + 0xB586, 0x796E, 0xB587, 0x7970, 0xB588, 0x7971, 0xB589, 0x7972, 0xB58A, 0x7973, 0xB58B, 0x7974, 0xB58C, 0x7975, 0xB58D, 0x7976, + 0xB58E, 0x7979, 0xB58F, 0x797B, 0xB590, 0x797C, 0xB591, 0x797D, 0xB592, 0x797E, 0xB593, 0x797F, 0xB594, 0x7982, 0xB595, 0x7983, + 0xB596, 0x7986, 0xB597, 0x7987, 0xB598, 0x7988, 0xB599, 0x7989, 0xB59A, 0x798B, 0xB59B, 0x798C, 0xB59C, 0x798D, 0xB59D, 0x798E, + 0xB59E, 0x7990, 0xB59F, 0x7991, 0xB5A0, 0x7992, 0xB5A1, 0x6020, 0xB5A2, 0x803D, 0xB5A3, 0x62C5, 0xB5A4, 0x4E39, 0xB5A5, 0x5355, + 0xB5A6, 0x90F8, 0xB5A7, 0x63B8, 0xB5A8, 0x80C6, 0xB5A9, 0x65E6, 0xB5AA, 0x6C2E, 0xB5AB, 0x4F46, 0xB5AC, 0x60EE, 0xB5AD, 0x6DE1, + 0xB5AE, 0x8BDE, 0xB5AF, 0x5F39, 0xB5B0, 0x86CB, 0xB5B1, 0x5F53, 0xB5B2, 0x6321, 0xB5B3, 0x515A, 0xB5B4, 0x8361, 0xB5B5, 0x6863, + 0xB5B6, 0x5200, 0xB5B7, 0x6363, 0xB5B8, 0x8E48, 0xB5B9, 0x5012, 0xB5BA, 0x5C9B, 0xB5BB, 0x7977, 0xB5BC, 0x5BFC, 0xB5BD, 0x5230, + 0xB5BE, 0x7A3B, 0xB5BF, 0x60BC, 0xB5C0, 0x9053, 0xB5C1, 0x76D7, 0xB5C2, 0x5FB7, 0xB5C3, 0x5F97, 0xB5C4, 0x7684, 0xB5C5, 0x8E6C, + 0xB5C6, 0x706F, 0xB5C7, 0x767B, 0xB5C8, 0x7B49, 0xB5C9, 0x77AA, 0xB5CA, 0x51F3, 0xB5CB, 0x9093, 0xB5CC, 0x5824, 0xB5CD, 0x4F4E, + 0xB5CE, 0x6EF4, 0xB5CF, 0x8FEA, 0xB5D0, 0x654C, 0xB5D1, 0x7B1B, 0xB5D2, 0x72C4, 0xB5D3, 0x6DA4, 0xB5D4, 0x7FDF, 0xB5D5, 0x5AE1, + 0xB5D6, 0x62B5, 0xB5D7, 0x5E95, 0xB5D8, 0x5730, 0xB5D9, 0x8482, 0xB5DA, 0x7B2C, 0xB5DB, 0x5E1D, 0xB5DC, 0x5F1F, 0xB5DD, 0x9012, + 0xB5DE, 0x7F14, 0xB5DF, 0x98A0, 0xB5E0, 0x6382, 0xB5E1, 0x6EC7, 0xB5E2, 0x7898, 0xB5E3, 0x70B9, 0xB5E4, 0x5178, 0xB5E5, 0x975B, + 0xB5E6, 0x57AB, 0xB5E7, 0x7535, 0xB5E8, 0x4F43, 0xB5E9, 0x7538, 0xB5EA, 0x5E97, 0xB5EB, 0x60E6, 0xB5EC, 0x5960, 0xB5ED, 0x6DC0, + 0xB5EE, 0x6BBF, 0xB5EF, 0x7889, 0xB5F0, 0x53FC, 0xB5F1, 0x96D5, 0xB5F2, 0x51CB, 0xB5F3, 0x5201, 0xB5F4, 0x6389, 0xB5F5, 0x540A, + 0xB5F6, 0x9493, 0xB5F7, 0x8C03, 0xB5F8, 0x8DCC, 0xB5F9, 0x7239, 0xB5FA, 0x789F, 0xB5FB, 0x8776, 0xB5FC, 0x8FED, 0xB5FD, 0x8C0D, + 0xB5FE, 0x53E0, 0xB640, 0x7993, 0xB641, 0x7994, 0xB642, 0x7995, 0xB643, 0x7996, 0xB644, 0x7997, 0xB645, 0x7998, 0xB646, 0x7999, + 0xB647, 0x799B, 0xB648, 0x799C, 0xB649, 0x799D, 0xB64A, 0x799E, 0xB64B, 0x799F, 0xB64C, 0x79A0, 0xB64D, 0x79A1, 0xB64E, 0x79A2, + 0xB64F, 0x79A3, 0xB650, 0x79A4, 0xB651, 0x79A5, 0xB652, 0x79A6, 0xB653, 0x79A8, 0xB654, 0x79A9, 0xB655, 0x79AA, 0xB656, 0x79AB, + 0xB657, 0x79AC, 0xB658, 0x79AD, 0xB659, 0x79AE, 0xB65A, 0x79AF, 0xB65B, 0x79B0, 0xB65C, 0x79B1, 0xB65D, 0x79B2, 0xB65E, 0x79B4, + 0xB65F, 0x79B5, 0xB660, 0x79B6, 0xB661, 0x79B7, 0xB662, 0x79B8, 0xB663, 0x79BC, 0xB664, 0x79BF, 0xB665, 0x79C2, 0xB666, 0x79C4, + 0xB667, 0x79C5, 0xB668, 0x79C7, 0xB669, 0x79C8, 0xB66A, 0x79CA, 0xB66B, 0x79CC, 0xB66C, 0x79CE, 0xB66D, 0x79CF, 0xB66E, 0x79D0, + 0xB66F, 0x79D3, 0xB670, 0x79D4, 0xB671, 0x79D6, 0xB672, 0x79D7, 0xB673, 0x79D9, 0xB674, 0x79DA, 0xB675, 0x79DB, 0xB676, 0x79DC, + 0xB677, 0x79DD, 0xB678, 0x79DE, 0xB679, 0x79E0, 0xB67A, 0x79E1, 0xB67B, 0x79E2, 0xB67C, 0x79E5, 0xB67D, 0x79E8, 0xB67E, 0x79EA, + 0xB680, 0x79EC, 0xB681, 0x79EE, 0xB682, 0x79F1, 0xB683, 0x79F2, 0xB684, 0x79F3, 0xB685, 0x79F4, 0xB686, 0x79F5, 0xB687, 0x79F6, + 0xB688, 0x79F7, 0xB689, 0x79F9, 0xB68A, 0x79FA, 0xB68B, 0x79FC, 0xB68C, 0x79FE, 0xB68D, 0x79FF, 0xB68E, 0x7A01, 0xB68F, 0x7A04, + 0xB690, 0x7A05, 0xB691, 0x7A07, 0xB692, 0x7A08, 0xB693, 0x7A09, 0xB694, 0x7A0A, 0xB695, 0x7A0C, 0xB696, 0x7A0F, 0xB697, 0x7A10, + 0xB698, 0x7A11, 0xB699, 0x7A12, 0xB69A, 0x7A13, 0xB69B, 0x7A15, 0xB69C, 0x7A16, 0xB69D, 0x7A18, 0xB69E, 0x7A19, 0xB69F, 0x7A1B, + 0xB6A0, 0x7A1C, 0xB6A1, 0x4E01, 0xB6A2, 0x76EF, 0xB6A3, 0x53EE, 0xB6A4, 0x9489, 0xB6A5, 0x9876, 0xB6A6, 0x9F0E, 0xB6A7, 0x952D, + 0xB6A8, 0x5B9A, 0xB6A9, 0x8BA2, 0xB6AA, 0x4E22, 0xB6AB, 0x4E1C, 0xB6AC, 0x51AC, 0xB6AD, 0x8463, 0xB6AE, 0x61C2, 0xB6AF, 0x52A8, + 0xB6B0, 0x680B, 0xB6B1, 0x4F97, 0xB6B2, 0x606B, 0xB6B3, 0x51BB, 0xB6B4, 0x6D1E, 0xB6B5, 0x515C, 0xB6B6, 0x6296, 0xB6B7, 0x6597, + 0xB6B8, 0x9661, 0xB6B9, 0x8C46, 0xB6BA, 0x9017, 0xB6BB, 0x75D8, 0xB6BC, 0x90FD, 0xB6BD, 0x7763, 0xB6BE, 0x6BD2, 0xB6BF, 0x728A, + 0xB6C0, 0x72EC, 0xB6C1, 0x8BFB, 0xB6C2, 0x5835, 0xB6C3, 0x7779, 0xB6C4, 0x8D4C, 0xB6C5, 0x675C, 0xB6C6, 0x9540, 0xB6C7, 0x809A, + 0xB6C8, 0x5EA6, 0xB6C9, 0x6E21, 0xB6CA, 0x5992, 0xB6CB, 0x7AEF, 0xB6CC, 0x77ED, 0xB6CD, 0x953B, 0xB6CE, 0x6BB5, 0xB6CF, 0x65AD, + 0xB6D0, 0x7F0E, 0xB6D1, 0x5806, 0xB6D2, 0x5151, 0xB6D3, 0x961F, 0xB6D4, 0x5BF9, 0xB6D5, 0x58A9, 0xB6D6, 0x5428, 0xB6D7, 0x8E72, + 0xB6D8, 0x6566, 0xB6D9, 0x987F, 0xB6DA, 0x56E4, 0xB6DB, 0x949D, 0xB6DC, 0x76FE, 0xB6DD, 0x9041, 0xB6DE, 0x6387, 0xB6DF, 0x54C6, + 0xB6E0, 0x591A, 0xB6E1, 0x593A, 0xB6E2, 0x579B, 0xB6E3, 0x8EB2, 0xB6E4, 0x6735, 0xB6E5, 0x8DFA, 0xB6E6, 0x8235, 0xB6E7, 0x5241, + 0xB6E8, 0x60F0, 0xB6E9, 0x5815, 0xB6EA, 0x86FE, 0xB6EB, 0x5CE8, 0xB6EC, 0x9E45, 0xB6ED, 0x4FC4, 0xB6EE, 0x989D, 0xB6EF, 0x8BB9, + 0xB6F0, 0x5A25, 0xB6F1, 0x6076, 0xB6F2, 0x5384, 0xB6F3, 0x627C, 0xB6F4, 0x904F, 0xB6F5, 0x9102, 0xB6F6, 0x997F, 0xB6F7, 0x6069, + 0xB6F8, 0x800C, 0xB6F9, 0x513F, 0xB6FA, 0x8033, 0xB6FB, 0x5C14, 0xB6FC, 0x9975, 0xB6FD, 0x6D31, 0xB6FE, 0x4E8C, 0xB740, 0x7A1D, + 0xB741, 0x7A1F, 0xB742, 0x7A21, 0xB743, 0x7A22, 0xB744, 0x7A24, 0xB745, 0x7A25, 0xB746, 0x7A26, 0xB747, 0x7A27, 0xB748, 0x7A28, + 0xB749, 0x7A29, 0xB74A, 0x7A2A, 0xB74B, 0x7A2B, 0xB74C, 0x7A2C, 0xB74D, 0x7A2D, 0xB74E, 0x7A2E, 0xB74F, 0x7A2F, 0xB750, 0x7A30, + 0xB751, 0x7A31, 0xB752, 0x7A32, 0xB753, 0x7A34, 0xB754, 0x7A35, 0xB755, 0x7A36, 0xB756, 0x7A38, 0xB757, 0x7A3A, 0xB758, 0x7A3E, + 0xB759, 0x7A40, 0xB75A, 0x7A41, 0xB75B, 0x7A42, 0xB75C, 0x7A43, 0xB75D, 0x7A44, 0xB75E, 0x7A45, 0xB75F, 0x7A47, 0xB760, 0x7A48, + 0xB761, 0x7A49, 0xB762, 0x7A4A, 0xB763, 0x7A4B, 0xB764, 0x7A4C, 0xB765, 0x7A4D, 0xB766, 0x7A4E, 0xB767, 0x7A4F, 0xB768, 0x7A50, + 0xB769, 0x7A52, 0xB76A, 0x7A53, 0xB76B, 0x7A54, 0xB76C, 0x7A55, 0xB76D, 0x7A56, 0xB76E, 0x7A58, 0xB76F, 0x7A59, 0xB770, 0x7A5A, + 0xB771, 0x7A5B, 0xB772, 0x7A5C, 0xB773, 0x7A5D, 0xB774, 0x7A5E, 0xB775, 0x7A5F, 0xB776, 0x7A60, 0xB777, 0x7A61, 0xB778, 0x7A62, + 0xB779, 0x7A63, 0xB77A, 0x7A64, 0xB77B, 0x7A65, 0xB77C, 0x7A66, 0xB77D, 0x7A67, 0xB77E, 0x7A68, 0xB780, 0x7A69, 0xB781, 0x7A6A, + 0xB782, 0x7A6B, 0xB783, 0x7A6C, 0xB784, 0x7A6D, 0xB785, 0x7A6E, 0xB786, 0x7A6F, 0xB787, 0x7A71, 0xB788, 0x7A72, 0xB789, 0x7A73, + 0xB78A, 0x7A75, 0xB78B, 0x7A7B, 0xB78C, 0x7A7C, 0xB78D, 0x7A7D, 0xB78E, 0x7A7E, 0xB78F, 0x7A82, 0xB790, 0x7A85, 0xB791, 0x7A87, + 0xB792, 0x7A89, 0xB793, 0x7A8A, 0xB794, 0x7A8B, 0xB795, 0x7A8C, 0xB796, 0x7A8E, 0xB797, 0x7A8F, 0xB798, 0x7A90, 0xB799, 0x7A93, + 0xB79A, 0x7A94, 0xB79B, 0x7A99, 0xB79C, 0x7A9A, 0xB79D, 0x7A9B, 0xB79E, 0x7A9E, 0xB79F, 0x7AA1, 0xB7A0, 0x7AA2, 0xB7A1, 0x8D30, + 0xB7A2, 0x53D1, 0xB7A3, 0x7F5A, 0xB7A4, 0x7B4F, 0xB7A5, 0x4F10, 0xB7A6, 0x4E4F, 0xB7A7, 0x9600, 0xB7A8, 0x6CD5, 0xB7A9, 0x73D0, + 0xB7AA, 0x85E9, 0xB7AB, 0x5E06, 0xB7AC, 0x756A, 0xB7AD, 0x7FFB, 0xB7AE, 0x6A0A, 0xB7AF, 0x77FE, 0xB7B0, 0x9492, 0xB7B1, 0x7E41, + 0xB7B2, 0x51E1, 0xB7B3, 0x70E6, 0xB7B4, 0x53CD, 0xB7B5, 0x8FD4, 0xB7B6, 0x8303, 0xB7B7, 0x8D29, 0xB7B8, 0x72AF, 0xB7B9, 0x996D, + 0xB7BA, 0x6CDB, 0xB7BB, 0x574A, 0xB7BC, 0x82B3, 0xB7BD, 0x65B9, 0xB7BE, 0x80AA, 0xB7BF, 0x623F, 0xB7C0, 0x9632, 0xB7C1, 0x59A8, + 0xB7C2, 0x4EFF, 0xB7C3, 0x8BBF, 0xB7C4, 0x7EBA, 0xB7C5, 0x653E, 0xB7C6, 0x83F2, 0xB7C7, 0x975E, 0xB7C8, 0x5561, 0xB7C9, 0x98DE, + 0xB7CA, 0x80A5, 0xB7CB, 0x532A, 0xB7CC, 0x8BFD, 0xB7CD, 0x5420, 0xB7CE, 0x80BA, 0xB7CF, 0x5E9F, 0xB7D0, 0x6CB8, 0xB7D1, 0x8D39, + 0xB7D2, 0x82AC, 0xB7D3, 0x915A, 0xB7D4, 0x5429, 0xB7D5, 0x6C1B, 0xB7D6, 0x5206, 0xB7D7, 0x7EB7, 0xB7D8, 0x575F, 0xB7D9, 0x711A, + 0xB7DA, 0x6C7E, 0xB7DB, 0x7C89, 0xB7DC, 0x594B, 0xB7DD, 0x4EFD, 0xB7DE, 0x5FFF, 0xB7DF, 0x6124, 0xB7E0, 0x7CAA, 0xB7E1, 0x4E30, + 0xB7E2, 0x5C01, 0xB7E3, 0x67AB, 0xB7E4, 0x8702, 0xB7E5, 0x5CF0, 0xB7E6, 0x950B, 0xB7E7, 0x98CE, 0xB7E8, 0x75AF, 0xB7E9, 0x70FD, + 0xB7EA, 0x9022, 0xB7EB, 0x51AF, 0xB7EC, 0x7F1D, 0xB7ED, 0x8BBD, 0xB7EE, 0x5949, 0xB7EF, 0x51E4, 0xB7F0, 0x4F5B, 0xB7F1, 0x5426, + 0xB7F2, 0x592B, 0xB7F3, 0x6577, 0xB7F4, 0x80A4, 0xB7F5, 0x5B75, 0xB7F6, 0x6276, 0xB7F7, 0x62C2, 0xB7F8, 0x8F90, 0xB7F9, 0x5E45, + 0xB7FA, 0x6C1F, 0xB7FB, 0x7B26, 0xB7FC, 0x4F0F, 0xB7FD, 0x4FD8, 0xB7FE, 0x670D, 0xB840, 0x7AA3, 0xB841, 0x7AA4, 0xB842, 0x7AA7, + 0xB843, 0x7AA9, 0xB844, 0x7AAA, 0xB845, 0x7AAB, 0xB846, 0x7AAE, 0xB847, 0x7AAF, 0xB848, 0x7AB0, 0xB849, 0x7AB1, 0xB84A, 0x7AB2, + 0xB84B, 0x7AB4, 0xB84C, 0x7AB5, 0xB84D, 0x7AB6, 0xB84E, 0x7AB7, 0xB84F, 0x7AB8, 0xB850, 0x7AB9, 0xB851, 0x7ABA, 0xB852, 0x7ABB, + 0xB853, 0x7ABC, 0xB854, 0x7ABD, 0xB855, 0x7ABE, 0xB856, 0x7AC0, 0xB857, 0x7AC1, 0xB858, 0x7AC2, 0xB859, 0x7AC3, 0xB85A, 0x7AC4, + 0xB85B, 0x7AC5, 0xB85C, 0x7AC6, 0xB85D, 0x7AC7, 0xB85E, 0x7AC8, 0xB85F, 0x7AC9, 0xB860, 0x7ACA, 0xB861, 0x7ACC, 0xB862, 0x7ACD, + 0xB863, 0x7ACE, 0xB864, 0x7ACF, 0xB865, 0x7AD0, 0xB866, 0x7AD1, 0xB867, 0x7AD2, 0xB868, 0x7AD3, 0xB869, 0x7AD4, 0xB86A, 0x7AD5, + 0xB86B, 0x7AD7, 0xB86C, 0x7AD8, 0xB86D, 0x7ADA, 0xB86E, 0x7ADB, 0xB86F, 0x7ADC, 0xB870, 0x7ADD, 0xB871, 0x7AE1, 0xB872, 0x7AE2, + 0xB873, 0x7AE4, 0xB874, 0x7AE7, 0xB875, 0x7AE8, 0xB876, 0x7AE9, 0xB877, 0x7AEA, 0xB878, 0x7AEB, 0xB879, 0x7AEC, 0xB87A, 0x7AEE, + 0xB87B, 0x7AF0, 0xB87C, 0x7AF1, 0xB87D, 0x7AF2, 0xB87E, 0x7AF3, 0xB880, 0x7AF4, 0xB881, 0x7AF5, 0xB882, 0x7AF6, 0xB883, 0x7AF7, + 0xB884, 0x7AF8, 0xB885, 0x7AFB, 0xB886, 0x7AFC, 0xB887, 0x7AFE, 0xB888, 0x7B00, 0xB889, 0x7B01, 0xB88A, 0x7B02, 0xB88B, 0x7B05, + 0xB88C, 0x7B07, 0xB88D, 0x7B09, 0xB88E, 0x7B0C, 0xB88F, 0x7B0D, 0xB890, 0x7B0E, 0xB891, 0x7B10, 0xB892, 0x7B12, 0xB893, 0x7B13, + 0xB894, 0x7B16, 0xB895, 0x7B17, 0xB896, 0x7B18, 0xB897, 0x7B1A, 0xB898, 0x7B1C, 0xB899, 0x7B1D, 0xB89A, 0x7B1F, 0xB89B, 0x7B21, + 0xB89C, 0x7B22, 0xB89D, 0x7B23, 0xB89E, 0x7B27, 0xB89F, 0x7B29, 0xB8A0, 0x7B2D, 0xB8A1, 0x6D6E, 0xB8A2, 0x6DAA, 0xB8A3, 0x798F, + 0xB8A4, 0x88B1, 0xB8A5, 0x5F17, 0xB8A6, 0x752B, 0xB8A7, 0x629A, 0xB8A8, 0x8F85, 0xB8A9, 0x4FEF, 0xB8AA, 0x91DC, 0xB8AB, 0x65A7, + 0xB8AC, 0x812F, 0xB8AD, 0x8151, 0xB8AE, 0x5E9C, 0xB8AF, 0x8150, 0xB8B0, 0x8D74, 0xB8B1, 0x526F, 0xB8B2, 0x8986, 0xB8B3, 0x8D4B, + 0xB8B4, 0x590D, 0xB8B5, 0x5085, 0xB8B6, 0x4ED8, 0xB8B7, 0x961C, 0xB8B8, 0x7236, 0xB8B9, 0x8179, 0xB8BA, 0x8D1F, 0xB8BB, 0x5BCC, + 0xB8BC, 0x8BA3, 0xB8BD, 0x9644, 0xB8BE, 0x5987, 0xB8BF, 0x7F1A, 0xB8C0, 0x5490, 0xB8C1, 0x5676, 0xB8C2, 0x560E, 0xB8C3, 0x8BE5, + 0xB8C4, 0x6539, 0xB8C5, 0x6982, 0xB8C6, 0x9499, 0xB8C7, 0x76D6, 0xB8C8, 0x6E89, 0xB8C9, 0x5E72, 0xB8CA, 0x7518, 0xB8CB, 0x6746, + 0xB8CC, 0x67D1, 0xB8CD, 0x7AFF, 0xB8CE, 0x809D, 0xB8CF, 0x8D76, 0xB8D0, 0x611F, 0xB8D1, 0x79C6, 0xB8D2, 0x6562, 0xB8D3, 0x8D63, + 0xB8D4, 0x5188, 0xB8D5, 0x521A, 0xB8D6, 0x94A2, 0xB8D7, 0x7F38, 0xB8D8, 0x809B, 0xB8D9, 0x7EB2, 0xB8DA, 0x5C97, 0xB8DB, 0x6E2F, + 0xB8DC, 0x6760, 0xB8DD, 0x7BD9, 0xB8DE, 0x768B, 0xB8DF, 0x9AD8, 0xB8E0, 0x818F, 0xB8E1, 0x7F94, 0xB8E2, 0x7CD5, 0xB8E3, 0x641E, + 0xB8E4, 0x9550, 0xB8E5, 0x7A3F, 0xB8E6, 0x544A, 0xB8E7, 0x54E5, 0xB8E8, 0x6B4C, 0xB8E9, 0x6401, 0xB8EA, 0x6208, 0xB8EB, 0x9E3D, + 0xB8EC, 0x80F3, 0xB8ED, 0x7599, 0xB8EE, 0x5272, 0xB8EF, 0x9769, 0xB8F0, 0x845B, 0xB8F1, 0x683C, 0xB8F2, 0x86E4, 0xB8F3, 0x9601, + 0xB8F4, 0x9694, 0xB8F5, 0x94EC, 0xB8F6, 0x4E2A, 0xB8F7, 0x5404, 0xB8F8, 0x7ED9, 0xB8F9, 0x6839, 0xB8FA, 0x8DDF, 0xB8FB, 0x8015, + 0xB8FC, 0x66F4, 0xB8FD, 0x5E9A, 0xB8FE, 0x7FB9, 0xB940, 0x7B2F, 0xB941, 0x7B30, 0xB942, 0x7B32, 0xB943, 0x7B34, 0xB944, 0x7B35, + 0xB945, 0x7B36, 0xB946, 0x7B37, 0xB947, 0x7B39, 0xB948, 0x7B3B, 0xB949, 0x7B3D, 0xB94A, 0x7B3F, 0xB94B, 0x7B40, 0xB94C, 0x7B41, + 0xB94D, 0x7B42, 0xB94E, 0x7B43, 0xB94F, 0x7B44, 0xB950, 0x7B46, 0xB951, 0x7B48, 0xB952, 0x7B4A, 0xB953, 0x7B4D, 0xB954, 0x7B4E, + 0xB955, 0x7B53, 0xB956, 0x7B55, 0xB957, 0x7B57, 0xB958, 0x7B59, 0xB959, 0x7B5C, 0xB95A, 0x7B5E, 0xB95B, 0x7B5F, 0xB95C, 0x7B61, + 0xB95D, 0x7B63, 0xB95E, 0x7B64, 0xB95F, 0x7B65, 0xB960, 0x7B66, 0xB961, 0x7B67, 0xB962, 0x7B68, 0xB963, 0x7B69, 0xB964, 0x7B6A, + 0xB965, 0x7B6B, 0xB966, 0x7B6C, 0xB967, 0x7B6D, 0xB968, 0x7B6F, 0xB969, 0x7B70, 0xB96A, 0x7B73, 0xB96B, 0x7B74, 0xB96C, 0x7B76, + 0xB96D, 0x7B78, 0xB96E, 0x7B7A, 0xB96F, 0x7B7C, 0xB970, 0x7B7D, 0xB971, 0x7B7F, 0xB972, 0x7B81, 0xB973, 0x7B82, 0xB974, 0x7B83, + 0xB975, 0x7B84, 0xB976, 0x7B86, 0xB977, 0x7B87, 0xB978, 0x7B88, 0xB979, 0x7B89, 0xB97A, 0x7B8A, 0xB97B, 0x7B8B, 0xB97C, 0x7B8C, + 0xB97D, 0x7B8E, 0xB97E, 0x7B8F, 0xB980, 0x7B91, 0xB981, 0x7B92, 0xB982, 0x7B93, 0xB983, 0x7B96, 0xB984, 0x7B98, 0xB985, 0x7B99, + 0xB986, 0x7B9A, 0xB987, 0x7B9B, 0xB988, 0x7B9E, 0xB989, 0x7B9F, 0xB98A, 0x7BA0, 0xB98B, 0x7BA3, 0xB98C, 0x7BA4, 0xB98D, 0x7BA5, + 0xB98E, 0x7BAE, 0xB98F, 0x7BAF, 0xB990, 0x7BB0, 0xB991, 0x7BB2, 0xB992, 0x7BB3, 0xB993, 0x7BB5, 0xB994, 0x7BB6, 0xB995, 0x7BB7, + 0xB996, 0x7BB9, 0xB997, 0x7BBA, 0xB998, 0x7BBB, 0xB999, 0x7BBC, 0xB99A, 0x7BBD, 0xB99B, 0x7BBE, 0xB99C, 0x7BBF, 0xB99D, 0x7BC0, + 0xB99E, 0x7BC2, 0xB99F, 0x7BC3, 0xB9A0, 0x7BC4, 0xB9A1, 0x57C2, 0xB9A2, 0x803F, 0xB9A3, 0x6897, 0xB9A4, 0x5DE5, 0xB9A5, 0x653B, + 0xB9A6, 0x529F, 0xB9A7, 0x606D, 0xB9A8, 0x9F9A, 0xB9A9, 0x4F9B, 0xB9AA, 0x8EAC, 0xB9AB, 0x516C, 0xB9AC, 0x5BAB, 0xB9AD, 0x5F13, + 0xB9AE, 0x5DE9, 0xB9AF, 0x6C5E, 0xB9B0, 0x62F1, 0xB9B1, 0x8D21, 0xB9B2, 0x5171, 0xB9B3, 0x94A9, 0xB9B4, 0x52FE, 0xB9B5, 0x6C9F, + 0xB9B6, 0x82DF, 0xB9B7, 0x72D7, 0xB9B8, 0x57A2, 0xB9B9, 0x6784, 0xB9BA, 0x8D2D, 0xB9BB, 0x591F, 0xB9BC, 0x8F9C, 0xB9BD, 0x83C7, + 0xB9BE, 0x5495, 0xB9BF, 0x7B8D, 0xB9C0, 0x4F30, 0xB9C1, 0x6CBD, 0xB9C2, 0x5B64, 0xB9C3, 0x59D1, 0xB9C4, 0x9F13, 0xB9C5, 0x53E4, + 0xB9C6, 0x86CA, 0xB9C7, 0x9AA8, 0xB9C8, 0x8C37, 0xB9C9, 0x80A1, 0xB9CA, 0x6545, 0xB9CB, 0x987E, 0xB9CC, 0x56FA, 0xB9CD, 0x96C7, + 0xB9CE, 0x522E, 0xB9CF, 0x74DC, 0xB9D0, 0x5250, 0xB9D1, 0x5BE1, 0xB9D2, 0x6302, 0xB9D3, 0x8902, 0xB9D4, 0x4E56, 0xB9D5, 0x62D0, + 0xB9D6, 0x602A, 0xB9D7, 0x68FA, 0xB9D8, 0x5173, 0xB9D9, 0x5B98, 0xB9DA, 0x51A0, 0xB9DB, 0x89C2, 0xB9DC, 0x7BA1, 0xB9DD, 0x9986, + 0xB9DE, 0x7F50, 0xB9DF, 0x60EF, 0xB9E0, 0x704C, 0xB9E1, 0x8D2F, 0xB9E2, 0x5149, 0xB9E3, 0x5E7F, 0xB9E4, 0x901B, 0xB9E5, 0x7470, + 0xB9E6, 0x89C4, 0xB9E7, 0x572D, 0xB9E8, 0x7845, 0xB9E9, 0x5F52, 0xB9EA, 0x9F9F, 0xB9EB, 0x95FA, 0xB9EC, 0x8F68, 0xB9ED, 0x9B3C, + 0xB9EE, 0x8BE1, 0xB9EF, 0x7678, 0xB9F0, 0x6842, 0xB9F1, 0x67DC, 0xB9F2, 0x8DEA, 0xB9F3, 0x8D35, 0xB9F4, 0x523D, 0xB9F5, 0x8F8A, + 0xB9F6, 0x6EDA, 0xB9F7, 0x68CD, 0xB9F8, 0x9505, 0xB9F9, 0x90ED, 0xB9FA, 0x56FD, 0xB9FB, 0x679C, 0xB9FC, 0x88F9, 0xB9FD, 0x8FC7, + 0xB9FE, 0x54C8, 0xBA40, 0x7BC5, 0xBA41, 0x7BC8, 0xBA42, 0x7BC9, 0xBA43, 0x7BCA, 0xBA44, 0x7BCB, 0xBA45, 0x7BCD, 0xBA46, 0x7BCE, + 0xBA47, 0x7BCF, 0xBA48, 0x7BD0, 0xBA49, 0x7BD2, 0xBA4A, 0x7BD4, 0xBA4B, 0x7BD5, 0xBA4C, 0x7BD6, 0xBA4D, 0x7BD7, 0xBA4E, 0x7BD8, + 0xBA4F, 0x7BDB, 0xBA50, 0x7BDC, 0xBA51, 0x7BDE, 0xBA52, 0x7BDF, 0xBA53, 0x7BE0, 0xBA54, 0x7BE2, 0xBA55, 0x7BE3, 0xBA56, 0x7BE4, + 0xBA57, 0x7BE7, 0xBA58, 0x7BE8, 0xBA59, 0x7BE9, 0xBA5A, 0x7BEB, 0xBA5B, 0x7BEC, 0xBA5C, 0x7BED, 0xBA5D, 0x7BEF, 0xBA5E, 0x7BF0, + 0xBA5F, 0x7BF2, 0xBA60, 0x7BF3, 0xBA61, 0x7BF4, 0xBA62, 0x7BF5, 0xBA63, 0x7BF6, 0xBA64, 0x7BF8, 0xBA65, 0x7BF9, 0xBA66, 0x7BFA, + 0xBA67, 0x7BFB, 0xBA68, 0x7BFD, 0xBA69, 0x7BFF, 0xBA6A, 0x7C00, 0xBA6B, 0x7C01, 0xBA6C, 0x7C02, 0xBA6D, 0x7C03, 0xBA6E, 0x7C04, + 0xBA6F, 0x7C05, 0xBA70, 0x7C06, 0xBA71, 0x7C08, 0xBA72, 0x7C09, 0xBA73, 0x7C0A, 0xBA74, 0x7C0D, 0xBA75, 0x7C0E, 0xBA76, 0x7C10, + 0xBA77, 0x7C11, 0xBA78, 0x7C12, 0xBA79, 0x7C13, 0xBA7A, 0x7C14, 0xBA7B, 0x7C15, 0xBA7C, 0x7C17, 0xBA7D, 0x7C18, 0xBA7E, 0x7C19, + 0xBA80, 0x7C1A, 0xBA81, 0x7C1B, 0xBA82, 0x7C1C, 0xBA83, 0x7C1D, 0xBA84, 0x7C1E, 0xBA85, 0x7C20, 0xBA86, 0x7C21, 0xBA87, 0x7C22, + 0xBA88, 0x7C23, 0xBA89, 0x7C24, 0xBA8A, 0x7C25, 0xBA8B, 0x7C28, 0xBA8C, 0x7C29, 0xBA8D, 0x7C2B, 0xBA8E, 0x7C2C, 0xBA8F, 0x7C2D, + 0xBA90, 0x7C2E, 0xBA91, 0x7C2F, 0xBA92, 0x7C30, 0xBA93, 0x7C31, 0xBA94, 0x7C32, 0xBA95, 0x7C33, 0xBA96, 0x7C34, 0xBA97, 0x7C35, + 0xBA98, 0x7C36, 0xBA99, 0x7C37, 0xBA9A, 0x7C39, 0xBA9B, 0x7C3A, 0xBA9C, 0x7C3B, 0xBA9D, 0x7C3C, 0xBA9E, 0x7C3D, 0xBA9F, 0x7C3E, + 0xBAA0, 0x7C42, 0xBAA1, 0x9AB8, 0xBAA2, 0x5B69, 0xBAA3, 0x6D77, 0xBAA4, 0x6C26, 0xBAA5, 0x4EA5, 0xBAA6, 0x5BB3, 0xBAA7, 0x9A87, + 0xBAA8, 0x9163, 0xBAA9, 0x61A8, 0xBAAA, 0x90AF, 0xBAAB, 0x97E9, 0xBAAC, 0x542B, 0xBAAD, 0x6DB5, 0xBAAE, 0x5BD2, 0xBAAF, 0x51FD, + 0xBAB0, 0x558A, 0xBAB1, 0x7F55, 0xBAB2, 0x7FF0, 0xBAB3, 0x64BC, 0xBAB4, 0x634D, 0xBAB5, 0x65F1, 0xBAB6, 0x61BE, 0xBAB7, 0x608D, + 0xBAB8, 0x710A, 0xBAB9, 0x6C57, 0xBABA, 0x6C49, 0xBABB, 0x592F, 0xBABC, 0x676D, 0xBABD, 0x822A, 0xBABE, 0x58D5, 0xBABF, 0x568E, + 0xBAC0, 0x8C6A, 0xBAC1, 0x6BEB, 0xBAC2, 0x90DD, 0xBAC3, 0x597D, 0xBAC4, 0x8017, 0xBAC5, 0x53F7, 0xBAC6, 0x6D69, 0xBAC7, 0x5475, + 0xBAC8, 0x559D, 0xBAC9, 0x8377, 0xBACA, 0x83CF, 0xBACB, 0x6838, 0xBACC, 0x79BE, 0xBACD, 0x548C, 0xBACE, 0x4F55, 0xBACF, 0x5408, + 0xBAD0, 0x76D2, 0xBAD1, 0x8C89, 0xBAD2, 0x9602, 0xBAD3, 0x6CB3, 0xBAD4, 0x6DB8, 0xBAD5, 0x8D6B, 0xBAD6, 0x8910, 0xBAD7, 0x9E64, + 0xBAD8, 0x8D3A, 0xBAD9, 0x563F, 0xBADA, 0x9ED1, 0xBADB, 0x75D5, 0xBADC, 0x5F88, 0xBADD, 0x72E0, 0xBADE, 0x6068, 0xBADF, 0x54FC, + 0xBAE0, 0x4EA8, 0xBAE1, 0x6A2A, 0xBAE2, 0x8861, 0xBAE3, 0x6052, 0xBAE4, 0x8F70, 0xBAE5, 0x54C4, 0xBAE6, 0x70D8, 0xBAE7, 0x8679, + 0xBAE8, 0x9E3F, 0xBAE9, 0x6D2A, 0xBAEA, 0x5B8F, 0xBAEB, 0x5F18, 0xBAEC, 0x7EA2, 0xBAED, 0x5589, 0xBAEE, 0x4FAF, 0xBAEF, 0x7334, + 0xBAF0, 0x543C, 0xBAF1, 0x539A, 0xBAF2, 0x5019, 0xBAF3, 0x540E, 0xBAF4, 0x547C, 0xBAF5, 0x4E4E, 0xBAF6, 0x5FFD, 0xBAF7, 0x745A, + 0xBAF8, 0x58F6, 0xBAF9, 0x846B, 0xBAFA, 0x80E1, 0xBAFB, 0x8774, 0xBAFC, 0x72D0, 0xBAFD, 0x7CCA, 0xBAFE, 0x6E56, 0xBB40, 0x7C43, + 0xBB41, 0x7C44, 0xBB42, 0x7C45, 0xBB43, 0x7C46, 0xBB44, 0x7C47, 0xBB45, 0x7C48, 0xBB46, 0x7C49, 0xBB47, 0x7C4A, 0xBB48, 0x7C4B, + 0xBB49, 0x7C4C, 0xBB4A, 0x7C4E, 0xBB4B, 0x7C4F, 0xBB4C, 0x7C50, 0xBB4D, 0x7C51, 0xBB4E, 0x7C52, 0xBB4F, 0x7C53, 0xBB50, 0x7C54, + 0xBB51, 0x7C55, 0xBB52, 0x7C56, 0xBB53, 0x7C57, 0xBB54, 0x7C58, 0xBB55, 0x7C59, 0xBB56, 0x7C5A, 0xBB57, 0x7C5B, 0xBB58, 0x7C5C, + 0xBB59, 0x7C5D, 0xBB5A, 0x7C5E, 0xBB5B, 0x7C5F, 0xBB5C, 0x7C60, 0xBB5D, 0x7C61, 0xBB5E, 0x7C62, 0xBB5F, 0x7C63, 0xBB60, 0x7C64, + 0xBB61, 0x7C65, 0xBB62, 0x7C66, 0xBB63, 0x7C67, 0xBB64, 0x7C68, 0xBB65, 0x7C69, 0xBB66, 0x7C6A, 0xBB67, 0x7C6B, 0xBB68, 0x7C6C, + 0xBB69, 0x7C6D, 0xBB6A, 0x7C6E, 0xBB6B, 0x7C6F, 0xBB6C, 0x7C70, 0xBB6D, 0x7C71, 0xBB6E, 0x7C72, 0xBB6F, 0x7C75, 0xBB70, 0x7C76, + 0xBB71, 0x7C77, 0xBB72, 0x7C78, 0xBB73, 0x7C79, 0xBB74, 0x7C7A, 0xBB75, 0x7C7E, 0xBB76, 0x7C7F, 0xBB77, 0x7C80, 0xBB78, 0x7C81, + 0xBB79, 0x7C82, 0xBB7A, 0x7C83, 0xBB7B, 0x7C84, 0xBB7C, 0x7C85, 0xBB7D, 0x7C86, 0xBB7E, 0x7C87, 0xBB80, 0x7C88, 0xBB81, 0x7C8A, + 0xBB82, 0x7C8B, 0xBB83, 0x7C8C, 0xBB84, 0x7C8D, 0xBB85, 0x7C8E, 0xBB86, 0x7C8F, 0xBB87, 0x7C90, 0xBB88, 0x7C93, 0xBB89, 0x7C94, + 0xBB8A, 0x7C96, 0xBB8B, 0x7C99, 0xBB8C, 0x7C9A, 0xBB8D, 0x7C9B, 0xBB8E, 0x7CA0, 0xBB8F, 0x7CA1, 0xBB90, 0x7CA3, 0xBB91, 0x7CA6, + 0xBB92, 0x7CA7, 0xBB93, 0x7CA8, 0xBB94, 0x7CA9, 0xBB95, 0x7CAB, 0xBB96, 0x7CAC, 0xBB97, 0x7CAD, 0xBB98, 0x7CAF, 0xBB99, 0x7CB0, + 0xBB9A, 0x7CB4, 0xBB9B, 0x7CB5, 0xBB9C, 0x7CB6, 0xBB9D, 0x7CB7, 0xBB9E, 0x7CB8, 0xBB9F, 0x7CBA, 0xBBA0, 0x7CBB, 0xBBA1, 0x5F27, + 0xBBA2, 0x864E, 0xBBA3, 0x552C, 0xBBA4, 0x62A4, 0xBBA5, 0x4E92, 0xBBA6, 0x6CAA, 0xBBA7, 0x6237, 0xBBA8, 0x82B1, 0xBBA9, 0x54D7, + 0xBBAA, 0x534E, 0xBBAB, 0x733E, 0xBBAC, 0x6ED1, 0xBBAD, 0x753B, 0xBBAE, 0x5212, 0xBBAF, 0x5316, 0xBBB0, 0x8BDD, 0xBBB1, 0x69D0, + 0xBBB2, 0x5F8A, 0xBBB3, 0x6000, 0xBBB4, 0x6DEE, 0xBBB5, 0x574F, 0xBBB6, 0x6B22, 0xBBB7, 0x73AF, 0xBBB8, 0x6853, 0xBBB9, 0x8FD8, + 0xBBBA, 0x7F13, 0xBBBB, 0x6362, 0xBBBC, 0x60A3, 0xBBBD, 0x5524, 0xBBBE, 0x75EA, 0xBBBF, 0x8C62, 0xBBC0, 0x7115, 0xBBC1, 0x6DA3, + 0xBBC2, 0x5BA6, 0xBBC3, 0x5E7B, 0xBBC4, 0x8352, 0xBBC5, 0x614C, 0xBBC6, 0x9EC4, 0xBBC7, 0x78FA, 0xBBC8, 0x8757, 0xBBC9, 0x7C27, + 0xBBCA, 0x7687, 0xBBCB, 0x51F0, 0xBBCC, 0x60F6, 0xBBCD, 0x714C, 0xBBCE, 0x6643, 0xBBCF, 0x5E4C, 0xBBD0, 0x604D, 0xBBD1, 0x8C0E, + 0xBBD2, 0x7070, 0xBBD3, 0x6325, 0xBBD4, 0x8F89, 0xBBD5, 0x5FBD, 0xBBD6, 0x6062, 0xBBD7, 0x86D4, 0xBBD8, 0x56DE, 0xBBD9, 0x6BC1, + 0xBBDA, 0x6094, 0xBBDB, 0x6167, 0xBBDC, 0x5349, 0xBBDD, 0x60E0, 0xBBDE, 0x6666, 0xBBDF, 0x8D3F, 0xBBE0, 0x79FD, 0xBBE1, 0x4F1A, + 0xBBE2, 0x70E9, 0xBBE3, 0x6C47, 0xBBE4, 0x8BB3, 0xBBE5, 0x8BF2, 0xBBE6, 0x7ED8, 0xBBE7, 0x8364, 0xBBE8, 0x660F, 0xBBE9, 0x5A5A, + 0xBBEA, 0x9B42, 0xBBEB, 0x6D51, 0xBBEC, 0x6DF7, 0xBBED, 0x8C41, 0xBBEE, 0x6D3B, 0xBBEF, 0x4F19, 0xBBF0, 0x706B, 0xBBF1, 0x83B7, + 0xBBF2, 0x6216, 0xBBF3, 0x60D1, 0xBBF4, 0x970D, 0xBBF5, 0x8D27, 0xBBF6, 0x7978, 0xBBF7, 0x51FB, 0xBBF8, 0x573E, 0xBBF9, 0x57FA, + 0xBBFA, 0x673A, 0xBBFB, 0x7578, 0xBBFC, 0x7A3D, 0xBBFD, 0x79EF, 0xBBFE, 0x7B95, 0xBC40, 0x7CBF, 0xBC41, 0x7CC0, 0xBC42, 0x7CC2, + 0xBC43, 0x7CC3, 0xBC44, 0x7CC4, 0xBC45, 0x7CC6, 0xBC46, 0x7CC9, 0xBC47, 0x7CCB, 0xBC48, 0x7CCE, 0xBC49, 0x7CCF, 0xBC4A, 0x7CD0, + 0xBC4B, 0x7CD1, 0xBC4C, 0x7CD2, 0xBC4D, 0x7CD3, 0xBC4E, 0x7CD4, 0xBC4F, 0x7CD8, 0xBC50, 0x7CDA, 0xBC51, 0x7CDB, 0xBC52, 0x7CDD, + 0xBC53, 0x7CDE, 0xBC54, 0x7CE1, 0xBC55, 0x7CE2, 0xBC56, 0x7CE3, 0xBC57, 0x7CE4, 0xBC58, 0x7CE5, 0xBC59, 0x7CE6, 0xBC5A, 0x7CE7, + 0xBC5B, 0x7CE9, 0xBC5C, 0x7CEA, 0xBC5D, 0x7CEB, 0xBC5E, 0x7CEC, 0xBC5F, 0x7CED, 0xBC60, 0x7CEE, 0xBC61, 0x7CF0, 0xBC62, 0x7CF1, + 0xBC63, 0x7CF2, 0xBC64, 0x7CF3, 0xBC65, 0x7CF4, 0xBC66, 0x7CF5, 0xBC67, 0x7CF6, 0xBC68, 0x7CF7, 0xBC69, 0x7CF9, 0xBC6A, 0x7CFA, + 0xBC6B, 0x7CFC, 0xBC6C, 0x7CFD, 0xBC6D, 0x7CFE, 0xBC6E, 0x7CFF, 0xBC6F, 0x7D00, 0xBC70, 0x7D01, 0xBC71, 0x7D02, 0xBC72, 0x7D03, + 0xBC73, 0x7D04, 0xBC74, 0x7D05, 0xBC75, 0x7D06, 0xBC76, 0x7D07, 0xBC77, 0x7D08, 0xBC78, 0x7D09, 0xBC79, 0x7D0B, 0xBC7A, 0x7D0C, + 0xBC7B, 0x7D0D, 0xBC7C, 0x7D0E, 0xBC7D, 0x7D0F, 0xBC7E, 0x7D10, 0xBC80, 0x7D11, 0xBC81, 0x7D12, 0xBC82, 0x7D13, 0xBC83, 0x7D14, + 0xBC84, 0x7D15, 0xBC85, 0x7D16, 0xBC86, 0x7D17, 0xBC87, 0x7D18, 0xBC88, 0x7D19, 0xBC89, 0x7D1A, 0xBC8A, 0x7D1B, 0xBC8B, 0x7D1C, + 0xBC8C, 0x7D1D, 0xBC8D, 0x7D1E, 0xBC8E, 0x7D1F, 0xBC8F, 0x7D21, 0xBC90, 0x7D23, 0xBC91, 0x7D24, 0xBC92, 0x7D25, 0xBC93, 0x7D26, + 0xBC94, 0x7D28, 0xBC95, 0x7D29, 0xBC96, 0x7D2A, 0xBC97, 0x7D2C, 0xBC98, 0x7D2D, 0xBC99, 0x7D2E, 0xBC9A, 0x7D30, 0xBC9B, 0x7D31, + 0xBC9C, 0x7D32, 0xBC9D, 0x7D33, 0xBC9E, 0x7D34, 0xBC9F, 0x7D35, 0xBCA0, 0x7D36, 0xBCA1, 0x808C, 0xBCA2, 0x9965, 0xBCA3, 0x8FF9, + 0xBCA4, 0x6FC0, 0xBCA5, 0x8BA5, 0xBCA6, 0x9E21, 0xBCA7, 0x59EC, 0xBCA8, 0x7EE9, 0xBCA9, 0x7F09, 0xBCAA, 0x5409, 0xBCAB, 0x6781, + 0xBCAC, 0x68D8, 0xBCAD, 0x8F91, 0xBCAE, 0x7C4D, 0xBCAF, 0x96C6, 0xBCB0, 0x53CA, 0xBCB1, 0x6025, 0xBCB2, 0x75BE, 0xBCB3, 0x6C72, + 0xBCB4, 0x5373, 0xBCB5, 0x5AC9, 0xBCB6, 0x7EA7, 0xBCB7, 0x6324, 0xBCB8, 0x51E0, 0xBCB9, 0x810A, 0xBCBA, 0x5DF1, 0xBCBB, 0x84DF, + 0xBCBC, 0x6280, 0xBCBD, 0x5180, 0xBCBE, 0x5B63, 0xBCBF, 0x4F0E, 0xBCC0, 0x796D, 0xBCC1, 0x5242, 0xBCC2, 0x60B8, 0xBCC3, 0x6D4E, + 0xBCC4, 0x5BC4, 0xBCC5, 0x5BC2, 0xBCC6, 0x8BA1, 0xBCC7, 0x8BB0, 0xBCC8, 0x65E2, 0xBCC9, 0x5FCC, 0xBCCA, 0x9645, 0xBCCB, 0x5993, + 0xBCCC, 0x7EE7, 0xBCCD, 0x7EAA, 0xBCCE, 0x5609, 0xBCCF, 0x67B7, 0xBCD0, 0x5939, 0xBCD1, 0x4F73, 0xBCD2, 0x5BB6, 0xBCD3, 0x52A0, + 0xBCD4, 0x835A, 0xBCD5, 0x988A, 0xBCD6, 0x8D3E, 0xBCD7, 0x7532, 0xBCD8, 0x94BE, 0xBCD9, 0x5047, 0xBCDA, 0x7A3C, 0xBCDB, 0x4EF7, + 0xBCDC, 0x67B6, 0xBCDD, 0x9A7E, 0xBCDE, 0x5AC1, 0xBCDF, 0x6B7C, 0xBCE0, 0x76D1, 0xBCE1, 0x575A, 0xBCE2, 0x5C16, 0xBCE3, 0x7B3A, + 0xBCE4, 0x95F4, 0xBCE5, 0x714E, 0xBCE6, 0x517C, 0xBCE7, 0x80A9, 0xBCE8, 0x8270, 0xBCE9, 0x5978, 0xBCEA, 0x7F04, 0xBCEB, 0x8327, + 0xBCEC, 0x68C0, 0xBCED, 0x67EC, 0xBCEE, 0x78B1, 0xBCEF, 0x7877, 0xBCF0, 0x62E3, 0xBCF1, 0x6361, 0xBCF2, 0x7B80, 0xBCF3, 0x4FED, + 0xBCF4, 0x526A, 0xBCF5, 0x51CF, 0xBCF6, 0x8350, 0xBCF7, 0x69DB, 0xBCF8, 0x9274, 0xBCF9, 0x8DF5, 0xBCFA, 0x8D31, 0xBCFB, 0x89C1, + 0xBCFC, 0x952E, 0xBCFD, 0x7BAD, 0xBCFE, 0x4EF6, 0xBD40, 0x7D37, 0xBD41, 0x7D38, 0xBD42, 0x7D39, 0xBD43, 0x7D3A, 0xBD44, 0x7D3B, + 0xBD45, 0x7D3C, 0xBD46, 0x7D3D, 0xBD47, 0x7D3E, 0xBD48, 0x7D3F, 0xBD49, 0x7D40, 0xBD4A, 0x7D41, 0xBD4B, 0x7D42, 0xBD4C, 0x7D43, + 0xBD4D, 0x7D44, 0xBD4E, 0x7D45, 0xBD4F, 0x7D46, 0xBD50, 0x7D47, 0xBD51, 0x7D48, 0xBD52, 0x7D49, 0xBD53, 0x7D4A, 0xBD54, 0x7D4B, + 0xBD55, 0x7D4C, 0xBD56, 0x7D4D, 0xBD57, 0x7D4E, 0xBD58, 0x7D4F, 0xBD59, 0x7D50, 0xBD5A, 0x7D51, 0xBD5B, 0x7D52, 0xBD5C, 0x7D53, + 0xBD5D, 0x7D54, 0xBD5E, 0x7D55, 0xBD5F, 0x7D56, 0xBD60, 0x7D57, 0xBD61, 0x7D58, 0xBD62, 0x7D59, 0xBD63, 0x7D5A, 0xBD64, 0x7D5B, + 0xBD65, 0x7D5C, 0xBD66, 0x7D5D, 0xBD67, 0x7D5E, 0xBD68, 0x7D5F, 0xBD69, 0x7D60, 0xBD6A, 0x7D61, 0xBD6B, 0x7D62, 0xBD6C, 0x7D63, + 0xBD6D, 0x7D64, 0xBD6E, 0x7D65, 0xBD6F, 0x7D66, 0xBD70, 0x7D67, 0xBD71, 0x7D68, 0xBD72, 0x7D69, 0xBD73, 0x7D6A, 0xBD74, 0x7D6B, + 0xBD75, 0x7D6C, 0xBD76, 0x7D6D, 0xBD77, 0x7D6F, 0xBD78, 0x7D70, 0xBD79, 0x7D71, 0xBD7A, 0x7D72, 0xBD7B, 0x7D73, 0xBD7C, 0x7D74, + 0xBD7D, 0x7D75, 0xBD7E, 0x7D76, 0xBD80, 0x7D78, 0xBD81, 0x7D79, 0xBD82, 0x7D7A, 0xBD83, 0x7D7B, 0xBD84, 0x7D7C, 0xBD85, 0x7D7D, + 0xBD86, 0x7D7E, 0xBD87, 0x7D7F, 0xBD88, 0x7D80, 0xBD89, 0x7D81, 0xBD8A, 0x7D82, 0xBD8B, 0x7D83, 0xBD8C, 0x7D84, 0xBD8D, 0x7D85, + 0xBD8E, 0x7D86, 0xBD8F, 0x7D87, 0xBD90, 0x7D88, 0xBD91, 0x7D89, 0xBD92, 0x7D8A, 0xBD93, 0x7D8B, 0xBD94, 0x7D8C, 0xBD95, 0x7D8D, + 0xBD96, 0x7D8E, 0xBD97, 0x7D8F, 0xBD98, 0x7D90, 0xBD99, 0x7D91, 0xBD9A, 0x7D92, 0xBD9B, 0x7D93, 0xBD9C, 0x7D94, 0xBD9D, 0x7D95, + 0xBD9E, 0x7D96, 0xBD9F, 0x7D97, 0xBDA0, 0x7D98, 0xBDA1, 0x5065, 0xBDA2, 0x8230, 0xBDA3, 0x5251, 0xBDA4, 0x996F, 0xBDA5, 0x6E10, + 0xBDA6, 0x6E85, 0xBDA7, 0x6DA7, 0xBDA8, 0x5EFA, 0xBDA9, 0x50F5, 0xBDAA, 0x59DC, 0xBDAB, 0x5C06, 0xBDAC, 0x6D46, 0xBDAD, 0x6C5F, + 0xBDAE, 0x7586, 0xBDAF, 0x848B, 0xBDB0, 0x6868, 0xBDB1, 0x5956, 0xBDB2, 0x8BB2, 0xBDB3, 0x5320, 0xBDB4, 0x9171, 0xBDB5, 0x964D, + 0xBDB6, 0x8549, 0xBDB7, 0x6912, 0xBDB8, 0x7901, 0xBDB9, 0x7126, 0xBDBA, 0x80F6, 0xBDBB, 0x4EA4, 0xBDBC, 0x90CA, 0xBDBD, 0x6D47, + 0xBDBE, 0x9A84, 0xBDBF, 0x5A07, 0xBDC0, 0x56BC, 0xBDC1, 0x6405, 0xBDC2, 0x94F0, 0xBDC3, 0x77EB, 0xBDC4, 0x4FA5, 0xBDC5, 0x811A, + 0xBDC6, 0x72E1, 0xBDC7, 0x89D2, 0xBDC8, 0x997A, 0xBDC9, 0x7F34, 0xBDCA, 0x7EDE, 0xBDCB, 0x527F, 0xBDCC, 0x6559, 0xBDCD, 0x9175, + 0xBDCE, 0x8F7F, 0xBDCF, 0x8F83, 0xBDD0, 0x53EB, 0xBDD1, 0x7A96, 0xBDD2, 0x63ED, 0xBDD3, 0x63A5, 0xBDD4, 0x7686, 0xBDD5, 0x79F8, + 0xBDD6, 0x8857, 0xBDD7, 0x9636, 0xBDD8, 0x622A, 0xBDD9, 0x52AB, 0xBDDA, 0x8282, 0xBDDB, 0x6854, 0xBDDC, 0x6770, 0xBDDD, 0x6377, + 0xBDDE, 0x776B, 0xBDDF, 0x7AED, 0xBDE0, 0x6D01, 0xBDE1, 0x7ED3, 0xBDE2, 0x89E3, 0xBDE3, 0x59D0, 0xBDE4, 0x6212, 0xBDE5, 0x85C9, + 0xBDE6, 0x82A5, 0xBDE7, 0x754C, 0xBDE8, 0x501F, 0xBDE9, 0x4ECB, 0xBDEA, 0x75A5, 0xBDEB, 0x8BEB, 0xBDEC, 0x5C4A, 0xBDED, 0x5DFE, + 0xBDEE, 0x7B4B, 0xBDEF, 0x65A4, 0xBDF0, 0x91D1, 0xBDF1, 0x4ECA, 0xBDF2, 0x6D25, 0xBDF3, 0x895F, 0xBDF4, 0x7D27, 0xBDF5, 0x9526, + 0xBDF6, 0x4EC5, 0xBDF7, 0x8C28, 0xBDF8, 0x8FDB, 0xBDF9, 0x9773, 0xBDFA, 0x664B, 0xBDFB, 0x7981, 0xBDFC, 0x8FD1, 0xBDFD, 0x70EC, + 0xBDFE, 0x6D78, 0xBE40, 0x7D99, 0xBE41, 0x7D9A, 0xBE42, 0x7D9B, 0xBE43, 0x7D9C, 0xBE44, 0x7D9D, 0xBE45, 0x7D9E, 0xBE46, 0x7D9F, + 0xBE47, 0x7DA0, 0xBE48, 0x7DA1, 0xBE49, 0x7DA2, 0xBE4A, 0x7DA3, 0xBE4B, 0x7DA4, 0xBE4C, 0x7DA5, 0xBE4D, 0x7DA7, 0xBE4E, 0x7DA8, + 0xBE4F, 0x7DA9, 0xBE50, 0x7DAA, 0xBE51, 0x7DAB, 0xBE52, 0x7DAC, 0xBE53, 0x7DAD, 0xBE54, 0x7DAF, 0xBE55, 0x7DB0, 0xBE56, 0x7DB1, + 0xBE57, 0x7DB2, 0xBE58, 0x7DB3, 0xBE59, 0x7DB4, 0xBE5A, 0x7DB5, 0xBE5B, 0x7DB6, 0xBE5C, 0x7DB7, 0xBE5D, 0x7DB8, 0xBE5E, 0x7DB9, + 0xBE5F, 0x7DBA, 0xBE60, 0x7DBB, 0xBE61, 0x7DBC, 0xBE62, 0x7DBD, 0xBE63, 0x7DBE, 0xBE64, 0x7DBF, 0xBE65, 0x7DC0, 0xBE66, 0x7DC1, + 0xBE67, 0x7DC2, 0xBE68, 0x7DC3, 0xBE69, 0x7DC4, 0xBE6A, 0x7DC5, 0xBE6B, 0x7DC6, 0xBE6C, 0x7DC7, 0xBE6D, 0x7DC8, 0xBE6E, 0x7DC9, + 0xBE6F, 0x7DCA, 0xBE70, 0x7DCB, 0xBE71, 0x7DCC, 0xBE72, 0x7DCD, 0xBE73, 0x7DCE, 0xBE74, 0x7DCF, 0xBE75, 0x7DD0, 0xBE76, 0x7DD1, + 0xBE77, 0x7DD2, 0xBE78, 0x7DD3, 0xBE79, 0x7DD4, 0xBE7A, 0x7DD5, 0xBE7B, 0x7DD6, 0xBE7C, 0x7DD7, 0xBE7D, 0x7DD8, 0xBE7E, 0x7DD9, + 0xBE80, 0x7DDA, 0xBE81, 0x7DDB, 0xBE82, 0x7DDC, 0xBE83, 0x7DDD, 0xBE84, 0x7DDE, 0xBE85, 0x7DDF, 0xBE86, 0x7DE0, 0xBE87, 0x7DE1, + 0xBE88, 0x7DE2, 0xBE89, 0x7DE3, 0xBE8A, 0x7DE4, 0xBE8B, 0x7DE5, 0xBE8C, 0x7DE6, 0xBE8D, 0x7DE7, 0xBE8E, 0x7DE8, 0xBE8F, 0x7DE9, + 0xBE90, 0x7DEA, 0xBE91, 0x7DEB, 0xBE92, 0x7DEC, 0xBE93, 0x7DED, 0xBE94, 0x7DEE, 0xBE95, 0x7DEF, 0xBE96, 0x7DF0, 0xBE97, 0x7DF1, + 0xBE98, 0x7DF2, 0xBE99, 0x7DF3, 0xBE9A, 0x7DF4, 0xBE9B, 0x7DF5, 0xBE9C, 0x7DF6, 0xBE9D, 0x7DF7, 0xBE9E, 0x7DF8, 0xBE9F, 0x7DF9, + 0xBEA0, 0x7DFA, 0xBEA1, 0x5C3D, 0xBEA2, 0x52B2, 0xBEA3, 0x8346, 0xBEA4, 0x5162, 0xBEA5, 0x830E, 0xBEA6, 0x775B, 0xBEA7, 0x6676, + 0xBEA8, 0x9CB8, 0xBEA9, 0x4EAC, 0xBEAA, 0x60CA, 0xBEAB, 0x7CBE, 0xBEAC, 0x7CB3, 0xBEAD, 0x7ECF, 0xBEAE, 0x4E95, 0xBEAF, 0x8B66, + 0xBEB0, 0x666F, 0xBEB1, 0x9888, 0xBEB2, 0x9759, 0xBEB3, 0x5883, 0xBEB4, 0x656C, 0xBEB5, 0x955C, 0xBEB6, 0x5F84, 0xBEB7, 0x75C9, + 0xBEB8, 0x9756, 0xBEB9, 0x7ADF, 0xBEBA, 0x7ADE, 0xBEBB, 0x51C0, 0xBEBC, 0x70AF, 0xBEBD, 0x7A98, 0xBEBE, 0x63EA, 0xBEBF, 0x7A76, + 0xBEC0, 0x7EA0, 0xBEC1, 0x7396, 0xBEC2, 0x97ED, 0xBEC3, 0x4E45, 0xBEC4, 0x7078, 0xBEC5, 0x4E5D, 0xBEC6, 0x9152, 0xBEC7, 0x53A9, + 0xBEC8, 0x6551, 0xBEC9, 0x65E7, 0xBECA, 0x81FC, 0xBECB, 0x8205, 0xBECC, 0x548E, 0xBECD, 0x5C31, 0xBECE, 0x759A, 0xBECF, 0x97A0, + 0xBED0, 0x62D8, 0xBED1, 0x72D9, 0xBED2, 0x75BD, 0xBED3, 0x5C45, 0xBED4, 0x9A79, 0xBED5, 0x83CA, 0xBED6, 0x5C40, 0xBED7, 0x5480, + 0xBED8, 0x77E9, 0xBED9, 0x4E3E, 0xBEDA, 0x6CAE, 0xBEDB, 0x805A, 0xBEDC, 0x62D2, 0xBEDD, 0x636E, 0xBEDE, 0x5DE8, 0xBEDF, 0x5177, + 0xBEE0, 0x8DDD, 0xBEE1, 0x8E1E, 0xBEE2, 0x952F, 0xBEE3, 0x4FF1, 0xBEE4, 0x53E5, 0xBEE5, 0x60E7, 0xBEE6, 0x70AC, 0xBEE7, 0x5267, + 0xBEE8, 0x6350, 0xBEE9, 0x9E43, 0xBEEA, 0x5A1F, 0xBEEB, 0x5026, 0xBEEC, 0x7737, 0xBEED, 0x5377, 0xBEEE, 0x7EE2, 0xBEEF, 0x6485, + 0xBEF0, 0x652B, 0xBEF1, 0x6289, 0xBEF2, 0x6398, 0xBEF3, 0x5014, 0xBEF4, 0x7235, 0xBEF5, 0x89C9, 0xBEF6, 0x51B3, 0xBEF7, 0x8BC0, + 0xBEF8, 0x7EDD, 0xBEF9, 0x5747, 0xBEFA, 0x83CC, 0xBEFB, 0x94A7, 0xBEFC, 0x519B, 0xBEFD, 0x541B, 0xBEFE, 0x5CFB, 0xBF40, 0x7DFB, + 0xBF41, 0x7DFC, 0xBF42, 0x7DFD, 0xBF43, 0x7DFE, 0xBF44, 0x7DFF, 0xBF45, 0x7E00, 0xBF46, 0x7E01, 0xBF47, 0x7E02, 0xBF48, 0x7E03, + 0xBF49, 0x7E04, 0xBF4A, 0x7E05, 0xBF4B, 0x7E06, 0xBF4C, 0x7E07, 0xBF4D, 0x7E08, 0xBF4E, 0x7E09, 0xBF4F, 0x7E0A, 0xBF50, 0x7E0B, + 0xBF51, 0x7E0C, 0xBF52, 0x7E0D, 0xBF53, 0x7E0E, 0xBF54, 0x7E0F, 0xBF55, 0x7E10, 0xBF56, 0x7E11, 0xBF57, 0x7E12, 0xBF58, 0x7E13, + 0xBF59, 0x7E14, 0xBF5A, 0x7E15, 0xBF5B, 0x7E16, 0xBF5C, 0x7E17, 0xBF5D, 0x7E18, 0xBF5E, 0x7E19, 0xBF5F, 0x7E1A, 0xBF60, 0x7E1B, + 0xBF61, 0x7E1C, 0xBF62, 0x7E1D, 0xBF63, 0x7E1E, 0xBF64, 0x7E1F, 0xBF65, 0x7E20, 0xBF66, 0x7E21, 0xBF67, 0x7E22, 0xBF68, 0x7E23, + 0xBF69, 0x7E24, 0xBF6A, 0x7E25, 0xBF6B, 0x7E26, 0xBF6C, 0x7E27, 0xBF6D, 0x7E28, 0xBF6E, 0x7E29, 0xBF6F, 0x7E2A, 0xBF70, 0x7E2B, + 0xBF71, 0x7E2C, 0xBF72, 0x7E2D, 0xBF73, 0x7E2E, 0xBF74, 0x7E2F, 0xBF75, 0x7E30, 0xBF76, 0x7E31, 0xBF77, 0x7E32, 0xBF78, 0x7E33, + 0xBF79, 0x7E34, 0xBF7A, 0x7E35, 0xBF7B, 0x7E36, 0xBF7C, 0x7E37, 0xBF7D, 0x7E38, 0xBF7E, 0x7E39, 0xBF80, 0x7E3A, 0xBF81, 0x7E3C, + 0xBF82, 0x7E3D, 0xBF83, 0x7E3E, 0xBF84, 0x7E3F, 0xBF85, 0x7E40, 0xBF86, 0x7E42, 0xBF87, 0x7E43, 0xBF88, 0x7E44, 0xBF89, 0x7E45, + 0xBF8A, 0x7E46, 0xBF8B, 0x7E48, 0xBF8C, 0x7E49, 0xBF8D, 0x7E4A, 0xBF8E, 0x7E4B, 0xBF8F, 0x7E4C, 0xBF90, 0x7E4D, 0xBF91, 0x7E4E, + 0xBF92, 0x7E4F, 0xBF93, 0x7E50, 0xBF94, 0x7E51, 0xBF95, 0x7E52, 0xBF96, 0x7E53, 0xBF97, 0x7E54, 0xBF98, 0x7E55, 0xBF99, 0x7E56, + 0xBF9A, 0x7E57, 0xBF9B, 0x7E58, 0xBF9C, 0x7E59, 0xBF9D, 0x7E5A, 0xBF9E, 0x7E5B, 0xBF9F, 0x7E5C, 0xBFA0, 0x7E5D, 0xBFA1, 0x4FCA, + 0xBFA2, 0x7AE3, 0xBFA3, 0x6D5A, 0xBFA4, 0x90E1, 0xBFA5, 0x9A8F, 0xBFA6, 0x5580, 0xBFA7, 0x5496, 0xBFA8, 0x5361, 0xBFA9, 0x54AF, + 0xBFAA, 0x5F00, 0xBFAB, 0x63E9, 0xBFAC, 0x6977, 0xBFAD, 0x51EF, 0xBFAE, 0x6168, 0xBFAF, 0x520A, 0xBFB0, 0x582A, 0xBFB1, 0x52D8, + 0xBFB2, 0x574E, 0xBFB3, 0x780D, 0xBFB4, 0x770B, 0xBFB5, 0x5EB7, 0xBFB6, 0x6177, 0xBFB7, 0x7CE0, 0xBFB8, 0x625B, 0xBFB9, 0x6297, + 0xBFBA, 0x4EA2, 0xBFBB, 0x7095, 0xBFBC, 0x8003, 0xBFBD, 0x62F7, 0xBFBE, 0x70E4, 0xBFBF, 0x9760, 0xBFC0, 0x5777, 0xBFC1, 0x82DB, + 0xBFC2, 0x67EF, 0xBFC3, 0x68F5, 0xBFC4, 0x78D5, 0xBFC5, 0x9897, 0xBFC6, 0x79D1, 0xBFC7, 0x58F3, 0xBFC8, 0x54B3, 0xBFC9, 0x53EF, + 0xBFCA, 0x6E34, 0xBFCB, 0x514B, 0xBFCC, 0x523B, 0xBFCD, 0x5BA2, 0xBFCE, 0x8BFE, 0xBFCF, 0x80AF, 0xBFD0, 0x5543, 0xBFD1, 0x57A6, + 0xBFD2, 0x6073, 0xBFD3, 0x5751, 0xBFD4, 0x542D, 0xBFD5, 0x7A7A, 0xBFD6, 0x6050, 0xBFD7, 0x5B54, 0xBFD8, 0x63A7, 0xBFD9, 0x62A0, + 0xBFDA, 0x53E3, 0xBFDB, 0x6263, 0xBFDC, 0x5BC7, 0xBFDD, 0x67AF, 0xBFDE, 0x54ED, 0xBFDF, 0x7A9F, 0xBFE0, 0x82E6, 0xBFE1, 0x9177, + 0xBFE2, 0x5E93, 0xBFE3, 0x88E4, 0xBFE4, 0x5938, 0xBFE5, 0x57AE, 0xBFE6, 0x630E, 0xBFE7, 0x8DE8, 0xBFE8, 0x80EF, 0xBFE9, 0x5757, + 0xBFEA, 0x7B77, 0xBFEB, 0x4FA9, 0xBFEC, 0x5FEB, 0xBFED, 0x5BBD, 0xBFEE, 0x6B3E, 0xBFEF, 0x5321, 0xBFF0, 0x7B50, 0xBFF1, 0x72C2, + 0xBFF2, 0x6846, 0xBFF3, 0x77FF, 0xBFF4, 0x7736, 0xBFF5, 0x65F7, 0xBFF6, 0x51B5, 0xBFF7, 0x4E8F, 0xBFF8, 0x76D4, 0xBFF9, 0x5CBF, + 0xBFFA, 0x7AA5, 0xBFFB, 0x8475, 0xBFFC, 0x594E, 0xBFFD, 0x9B41, 0xBFFE, 0x5080, 0xC040, 0x7E5E, 0xC041, 0x7E5F, 0xC042, 0x7E60, + 0xC043, 0x7E61, 0xC044, 0x7E62, 0xC045, 0x7E63, 0xC046, 0x7E64, 0xC047, 0x7E65, 0xC048, 0x7E66, 0xC049, 0x7E67, 0xC04A, 0x7E68, + 0xC04B, 0x7E69, 0xC04C, 0x7E6A, 0xC04D, 0x7E6B, 0xC04E, 0x7E6C, 0xC04F, 0x7E6D, 0xC050, 0x7E6E, 0xC051, 0x7E6F, 0xC052, 0x7E70, + 0xC053, 0x7E71, 0xC054, 0x7E72, 0xC055, 0x7E73, 0xC056, 0x7E74, 0xC057, 0x7E75, 0xC058, 0x7E76, 0xC059, 0x7E77, 0xC05A, 0x7E78, + 0xC05B, 0x7E79, 0xC05C, 0x7E7A, 0xC05D, 0x7E7B, 0xC05E, 0x7E7C, 0xC05F, 0x7E7D, 0xC060, 0x7E7E, 0xC061, 0x7E7F, 0xC062, 0x7E80, + 0xC063, 0x7E81, 0xC064, 0x7E83, 0xC065, 0x7E84, 0xC066, 0x7E85, 0xC067, 0x7E86, 0xC068, 0x7E87, 0xC069, 0x7E88, 0xC06A, 0x7E89, + 0xC06B, 0x7E8A, 0xC06C, 0x7E8B, 0xC06D, 0x7E8C, 0xC06E, 0x7E8D, 0xC06F, 0x7E8E, 0xC070, 0x7E8F, 0xC071, 0x7E90, 0xC072, 0x7E91, + 0xC073, 0x7E92, 0xC074, 0x7E93, 0xC075, 0x7E94, 0xC076, 0x7E95, 0xC077, 0x7E96, 0xC078, 0x7E97, 0xC079, 0x7E98, 0xC07A, 0x7E99, + 0xC07B, 0x7E9A, 0xC07C, 0x7E9C, 0xC07D, 0x7E9D, 0xC07E, 0x7E9E, 0xC080, 0x7EAE, 0xC081, 0x7EB4, 0xC082, 0x7EBB, 0xC083, 0x7EBC, + 0xC084, 0x7ED6, 0xC085, 0x7EE4, 0xC086, 0x7EEC, 0xC087, 0x7EF9, 0xC088, 0x7F0A, 0xC089, 0x7F10, 0xC08A, 0x7F1E, 0xC08B, 0x7F37, + 0xC08C, 0x7F39, 0xC08D, 0x7F3B, 0xC08E, 0x7F3C, 0xC08F, 0x7F3D, 0xC090, 0x7F3E, 0xC091, 0x7F3F, 0xC092, 0x7F40, 0xC093, 0x7F41, + 0xC094, 0x7F43, 0xC095, 0x7F46, 0xC096, 0x7F47, 0xC097, 0x7F48, 0xC098, 0x7F49, 0xC099, 0x7F4A, 0xC09A, 0x7F4B, 0xC09B, 0x7F4C, + 0xC09C, 0x7F4D, 0xC09D, 0x7F4E, 0xC09E, 0x7F4F, 0xC09F, 0x7F52, 0xC0A0, 0x7F53, 0xC0A1, 0x9988, 0xC0A2, 0x6127, 0xC0A3, 0x6E83, + 0xC0A4, 0x5764, 0xC0A5, 0x6606, 0xC0A6, 0x6346, 0xC0A7, 0x56F0, 0xC0A8, 0x62EC, 0xC0A9, 0x6269, 0xC0AA, 0x5ED3, 0xC0AB, 0x9614, + 0xC0AC, 0x5783, 0xC0AD, 0x62C9, 0xC0AE, 0x5587, 0xC0AF, 0x8721, 0xC0B0, 0x814A, 0xC0B1, 0x8FA3, 0xC0B2, 0x5566, 0xC0B3, 0x83B1, + 0xC0B4, 0x6765, 0xC0B5, 0x8D56, 0xC0B6, 0x84DD, 0xC0B7, 0x5A6A, 0xC0B8, 0x680F, 0xC0B9, 0x62E6, 0xC0BA, 0x7BEE, 0xC0BB, 0x9611, + 0xC0BC, 0x5170, 0xC0BD, 0x6F9C, 0xC0BE, 0x8C30, 0xC0BF, 0x63FD, 0xC0C0, 0x89C8, 0xC0C1, 0x61D2, 0xC0C2, 0x7F06, 0xC0C3, 0x70C2, + 0xC0C4, 0x6EE5, 0xC0C5, 0x7405, 0xC0C6, 0x6994, 0xC0C7, 0x72FC, 0xC0C8, 0x5ECA, 0xC0C9, 0x90CE, 0xC0CA, 0x6717, 0xC0CB, 0x6D6A, + 0xC0CC, 0x635E, 0xC0CD, 0x52B3, 0xC0CE, 0x7262, 0xC0CF, 0x8001, 0xC0D0, 0x4F6C, 0xC0D1, 0x59E5, 0xC0D2, 0x916A, 0xC0D3, 0x70D9, + 0xC0D4, 0x6D9D, 0xC0D5, 0x52D2, 0xC0D6, 0x4E50, 0xC0D7, 0x96F7, 0xC0D8, 0x956D, 0xC0D9, 0x857E, 0xC0DA, 0x78CA, 0xC0DB, 0x7D2F, + 0xC0DC, 0x5121, 0xC0DD, 0x5792, 0xC0DE, 0x64C2, 0xC0DF, 0x808B, 0xC0E0, 0x7C7B, 0xC0E1, 0x6CEA, 0xC0E2, 0x68F1, 0xC0E3, 0x695E, + 0xC0E4, 0x51B7, 0xC0E5, 0x5398, 0xC0E6, 0x68A8, 0xC0E7, 0x7281, 0xC0E8, 0x9ECE, 0xC0E9, 0x7BF1, 0xC0EA, 0x72F8, 0xC0EB, 0x79BB, + 0xC0EC, 0x6F13, 0xC0ED, 0x7406, 0xC0EE, 0x674E, 0xC0EF, 0x91CC, 0xC0F0, 0x9CA4, 0xC0F1, 0x793C, 0xC0F2, 0x8389, 0xC0F3, 0x8354, + 0xC0F4, 0x540F, 0xC0F5, 0x6817, 0xC0F6, 0x4E3D, 0xC0F7, 0x5389, 0xC0F8, 0x52B1, 0xC0F9, 0x783E, 0xC0FA, 0x5386, 0xC0FB, 0x5229, + 0xC0FC, 0x5088, 0xC0FD, 0x4F8B, 0xC0FE, 0x4FD0, 0xC140, 0x7F56, 0xC141, 0x7F59, 0xC142, 0x7F5B, 0xC143, 0x7F5C, 0xC144, 0x7F5D, + 0xC145, 0x7F5E, 0xC146, 0x7F60, 0xC147, 0x7F63, 0xC148, 0x7F64, 0xC149, 0x7F65, 0xC14A, 0x7F66, 0xC14B, 0x7F67, 0xC14C, 0x7F6B, + 0xC14D, 0x7F6C, 0xC14E, 0x7F6D, 0xC14F, 0x7F6F, 0xC150, 0x7F70, 0xC151, 0x7F73, 0xC152, 0x7F75, 0xC153, 0x7F76, 0xC154, 0x7F77, + 0xC155, 0x7F78, 0xC156, 0x7F7A, 0xC157, 0x7F7B, 0xC158, 0x7F7C, 0xC159, 0x7F7D, 0xC15A, 0x7F7F, 0xC15B, 0x7F80, 0xC15C, 0x7F82, + 0xC15D, 0x7F83, 0xC15E, 0x7F84, 0xC15F, 0x7F85, 0xC160, 0x7F86, 0xC161, 0x7F87, 0xC162, 0x7F88, 0xC163, 0x7F89, 0xC164, 0x7F8B, + 0xC165, 0x7F8D, 0xC166, 0x7F8F, 0xC167, 0x7F90, 0xC168, 0x7F91, 0xC169, 0x7F92, 0xC16A, 0x7F93, 0xC16B, 0x7F95, 0xC16C, 0x7F96, + 0xC16D, 0x7F97, 0xC16E, 0x7F98, 0xC16F, 0x7F99, 0xC170, 0x7F9B, 0xC171, 0x7F9C, 0xC172, 0x7FA0, 0xC173, 0x7FA2, 0xC174, 0x7FA3, + 0xC175, 0x7FA5, 0xC176, 0x7FA6, 0xC177, 0x7FA8, 0xC178, 0x7FA9, 0xC179, 0x7FAA, 0xC17A, 0x7FAB, 0xC17B, 0x7FAC, 0xC17C, 0x7FAD, + 0xC17D, 0x7FAE, 0xC17E, 0x7FB1, 0xC180, 0x7FB3, 0xC181, 0x7FB4, 0xC182, 0x7FB5, 0xC183, 0x7FB6, 0xC184, 0x7FB7, 0xC185, 0x7FBA, + 0xC186, 0x7FBB, 0xC187, 0x7FBE, 0xC188, 0x7FC0, 0xC189, 0x7FC2, 0xC18A, 0x7FC3, 0xC18B, 0x7FC4, 0xC18C, 0x7FC6, 0xC18D, 0x7FC7, + 0xC18E, 0x7FC8, 0xC18F, 0x7FC9, 0xC190, 0x7FCB, 0xC191, 0x7FCD, 0xC192, 0x7FCF, 0xC193, 0x7FD0, 0xC194, 0x7FD1, 0xC195, 0x7FD2, + 0xC196, 0x7FD3, 0xC197, 0x7FD6, 0xC198, 0x7FD7, 0xC199, 0x7FD9, 0xC19A, 0x7FDA, 0xC19B, 0x7FDB, 0xC19C, 0x7FDC, 0xC19D, 0x7FDD, + 0xC19E, 0x7FDE, 0xC19F, 0x7FE2, 0xC1A0, 0x7FE3, 0xC1A1, 0x75E2, 0xC1A2, 0x7ACB, 0xC1A3, 0x7C92, 0xC1A4, 0x6CA5, 0xC1A5, 0x96B6, + 0xC1A6, 0x529B, 0xC1A7, 0x7483, 0xC1A8, 0x54E9, 0xC1A9, 0x4FE9, 0xC1AA, 0x8054, 0xC1AB, 0x83B2, 0xC1AC, 0x8FDE, 0xC1AD, 0x9570, + 0xC1AE, 0x5EC9, 0xC1AF, 0x601C, 0xC1B0, 0x6D9F, 0xC1B1, 0x5E18, 0xC1B2, 0x655B, 0xC1B3, 0x8138, 0xC1B4, 0x94FE, 0xC1B5, 0x604B, + 0xC1B6, 0x70BC, 0xC1B7, 0x7EC3, 0xC1B8, 0x7CAE, 0xC1B9, 0x51C9, 0xC1BA, 0x6881, 0xC1BB, 0x7CB1, 0xC1BC, 0x826F, 0xC1BD, 0x4E24, + 0xC1BE, 0x8F86, 0xC1BF, 0x91CF, 0xC1C0, 0x667E, 0xC1C1, 0x4EAE, 0xC1C2, 0x8C05, 0xC1C3, 0x64A9, 0xC1C4, 0x804A, 0xC1C5, 0x50DA, + 0xC1C6, 0x7597, 0xC1C7, 0x71CE, 0xC1C8, 0x5BE5, 0xC1C9, 0x8FBD, 0xC1CA, 0x6F66, 0xC1CB, 0x4E86, 0xC1CC, 0x6482, 0xC1CD, 0x9563, + 0xC1CE, 0x5ED6, 0xC1CF, 0x6599, 0xC1D0, 0x5217, 0xC1D1, 0x88C2, 0xC1D2, 0x70C8, 0xC1D3, 0x52A3, 0xC1D4, 0x730E, 0xC1D5, 0x7433, + 0xC1D6, 0x6797, 0xC1D7, 0x78F7, 0xC1D8, 0x9716, 0xC1D9, 0x4E34, 0xC1DA, 0x90BB, 0xC1DB, 0x9CDE, 0xC1DC, 0x6DCB, 0xC1DD, 0x51DB, + 0xC1DE, 0x8D41, 0xC1DF, 0x541D, 0xC1E0, 0x62CE, 0xC1E1, 0x73B2, 0xC1E2, 0x83F1, 0xC1E3, 0x96F6, 0xC1E4, 0x9F84, 0xC1E5, 0x94C3, + 0xC1E6, 0x4F36, 0xC1E7, 0x7F9A, 0xC1E8, 0x51CC, 0xC1E9, 0x7075, 0xC1EA, 0x9675, 0xC1EB, 0x5CAD, 0xC1EC, 0x9886, 0xC1ED, 0x53E6, + 0xC1EE, 0x4EE4, 0xC1EF, 0x6E9C, 0xC1F0, 0x7409, 0xC1F1, 0x69B4, 0xC1F2, 0x786B, 0xC1F3, 0x998F, 0xC1F4, 0x7559, 0xC1F5, 0x5218, + 0xC1F6, 0x7624, 0xC1F7, 0x6D41, 0xC1F8, 0x67F3, 0xC1F9, 0x516D, 0xC1FA, 0x9F99, 0xC1FB, 0x804B, 0xC1FC, 0x5499, 0xC1FD, 0x7B3C, + 0xC1FE, 0x7ABF, 0xC240, 0x7FE4, 0xC241, 0x7FE7, 0xC242, 0x7FE8, 0xC243, 0x7FEA, 0xC244, 0x7FEB, 0xC245, 0x7FEC, 0xC246, 0x7FED, + 0xC247, 0x7FEF, 0xC248, 0x7FF2, 0xC249, 0x7FF4, 0xC24A, 0x7FF5, 0xC24B, 0x7FF6, 0xC24C, 0x7FF7, 0xC24D, 0x7FF8, 0xC24E, 0x7FF9, + 0xC24F, 0x7FFA, 0xC250, 0x7FFD, 0xC251, 0x7FFE, 0xC252, 0x7FFF, 0xC253, 0x8002, 0xC254, 0x8007, 0xC255, 0x8008, 0xC256, 0x8009, + 0xC257, 0x800A, 0xC258, 0x800E, 0xC259, 0x800F, 0xC25A, 0x8011, 0xC25B, 0x8013, 0xC25C, 0x801A, 0xC25D, 0x801B, 0xC25E, 0x801D, + 0xC25F, 0x801E, 0xC260, 0x801F, 0xC261, 0x8021, 0xC262, 0x8023, 0xC263, 0x8024, 0xC264, 0x802B, 0xC265, 0x802C, 0xC266, 0x802D, + 0xC267, 0x802E, 0xC268, 0x802F, 0xC269, 0x8030, 0xC26A, 0x8032, 0xC26B, 0x8034, 0xC26C, 0x8039, 0xC26D, 0x803A, 0xC26E, 0x803C, + 0xC26F, 0x803E, 0xC270, 0x8040, 0xC271, 0x8041, 0xC272, 0x8044, 0xC273, 0x8045, 0xC274, 0x8047, 0xC275, 0x8048, 0xC276, 0x8049, + 0xC277, 0x804E, 0xC278, 0x804F, 0xC279, 0x8050, 0xC27A, 0x8051, 0xC27B, 0x8053, 0xC27C, 0x8055, 0xC27D, 0x8056, 0xC27E, 0x8057, + 0xC280, 0x8059, 0xC281, 0x805B, 0xC282, 0x805C, 0xC283, 0x805D, 0xC284, 0x805E, 0xC285, 0x805F, 0xC286, 0x8060, 0xC287, 0x8061, + 0xC288, 0x8062, 0xC289, 0x8063, 0xC28A, 0x8064, 0xC28B, 0x8065, 0xC28C, 0x8066, 0xC28D, 0x8067, 0xC28E, 0x8068, 0xC28F, 0x806B, + 0xC290, 0x806C, 0xC291, 0x806D, 0xC292, 0x806E, 0xC293, 0x806F, 0xC294, 0x8070, 0xC295, 0x8072, 0xC296, 0x8073, 0xC297, 0x8074, + 0xC298, 0x8075, 0xC299, 0x8076, 0xC29A, 0x8077, 0xC29B, 0x8078, 0xC29C, 0x8079, 0xC29D, 0x807A, 0xC29E, 0x807B, 0xC29F, 0x807C, + 0xC2A0, 0x807D, 0xC2A1, 0x9686, 0xC2A2, 0x5784, 0xC2A3, 0x62E2, 0xC2A4, 0x9647, 0xC2A5, 0x697C, 0xC2A6, 0x5A04, 0xC2A7, 0x6402, + 0xC2A8, 0x7BD3, 0xC2A9, 0x6F0F, 0xC2AA, 0x964B, 0xC2AB, 0x82A6, 0xC2AC, 0x5362, 0xC2AD, 0x9885, 0xC2AE, 0x5E90, 0xC2AF, 0x7089, + 0xC2B0, 0x63B3, 0xC2B1, 0x5364, 0xC2B2, 0x864F, 0xC2B3, 0x9C81, 0xC2B4, 0x9E93, 0xC2B5, 0x788C, 0xC2B6, 0x9732, 0xC2B7, 0x8DEF, + 0xC2B8, 0x8D42, 0xC2B9, 0x9E7F, 0xC2BA, 0x6F5E, 0xC2BB, 0x7984, 0xC2BC, 0x5F55, 0xC2BD, 0x9646, 0xC2BE, 0x622E, 0xC2BF, 0x9A74, + 0xC2C0, 0x5415, 0xC2C1, 0x94DD, 0xC2C2, 0x4FA3, 0xC2C3, 0x65C5, 0xC2C4, 0x5C65, 0xC2C5, 0x5C61, 0xC2C6, 0x7F15, 0xC2C7, 0x8651, + 0xC2C8, 0x6C2F, 0xC2C9, 0x5F8B, 0xC2CA, 0x7387, 0xC2CB, 0x6EE4, 0xC2CC, 0x7EFF, 0xC2CD, 0x5CE6, 0xC2CE, 0x631B, 0xC2CF, 0x5B6A, + 0xC2D0, 0x6EE6, 0xC2D1, 0x5375, 0xC2D2, 0x4E71, 0xC2D3, 0x63A0, 0xC2D4, 0x7565, 0xC2D5, 0x62A1, 0xC2D6, 0x8F6E, 0xC2D7, 0x4F26, + 0xC2D8, 0x4ED1, 0xC2D9, 0x6CA6, 0xC2DA, 0x7EB6, 0xC2DB, 0x8BBA, 0xC2DC, 0x841D, 0xC2DD, 0x87BA, 0xC2DE, 0x7F57, 0xC2DF, 0x903B, + 0xC2E0, 0x9523, 0xC2E1, 0x7BA9, 0xC2E2, 0x9AA1, 0xC2E3, 0x88F8, 0xC2E4, 0x843D, 0xC2E5, 0x6D1B, 0xC2E6, 0x9A86, 0xC2E7, 0x7EDC, + 0xC2E8, 0x5988, 0xC2E9, 0x9EBB, 0xC2EA, 0x739B, 0xC2EB, 0x7801, 0xC2EC, 0x8682, 0xC2ED, 0x9A6C, 0xC2EE, 0x9A82, 0xC2EF, 0x561B, + 0xC2F0, 0x5417, 0xC2F1, 0x57CB, 0xC2F2, 0x4E70, 0xC2F3, 0x9EA6, 0xC2F4, 0x5356, 0xC2F5, 0x8FC8, 0xC2F6, 0x8109, 0xC2F7, 0x7792, + 0xC2F8, 0x9992, 0xC2F9, 0x86EE, 0xC2FA, 0x6EE1, 0xC2FB, 0x8513, 0xC2FC, 0x66FC, 0xC2FD, 0x6162, 0xC2FE, 0x6F2B, 0xC340, 0x807E, + 0xC341, 0x8081, 0xC342, 0x8082, 0xC343, 0x8085, 0xC344, 0x8088, 0xC345, 0x808A, 0xC346, 0x808D, 0xC347, 0x808E, 0xC348, 0x808F, + 0xC349, 0x8090, 0xC34A, 0x8091, 0xC34B, 0x8092, 0xC34C, 0x8094, 0xC34D, 0x8095, 0xC34E, 0x8097, 0xC34F, 0x8099, 0xC350, 0x809E, + 0xC351, 0x80A3, 0xC352, 0x80A6, 0xC353, 0x80A7, 0xC354, 0x80A8, 0xC355, 0x80AC, 0xC356, 0x80B0, 0xC357, 0x80B3, 0xC358, 0x80B5, + 0xC359, 0x80B6, 0xC35A, 0x80B8, 0xC35B, 0x80B9, 0xC35C, 0x80BB, 0xC35D, 0x80C5, 0xC35E, 0x80C7, 0xC35F, 0x80C8, 0xC360, 0x80C9, + 0xC361, 0x80CA, 0xC362, 0x80CB, 0xC363, 0x80CF, 0xC364, 0x80D0, 0xC365, 0x80D1, 0xC366, 0x80D2, 0xC367, 0x80D3, 0xC368, 0x80D4, + 0xC369, 0x80D5, 0xC36A, 0x80D8, 0xC36B, 0x80DF, 0xC36C, 0x80E0, 0xC36D, 0x80E2, 0xC36E, 0x80E3, 0xC36F, 0x80E6, 0xC370, 0x80EE, + 0xC371, 0x80F5, 0xC372, 0x80F7, 0xC373, 0x80F9, 0xC374, 0x80FB, 0xC375, 0x80FE, 0xC376, 0x80FF, 0xC377, 0x8100, 0xC378, 0x8101, + 0xC379, 0x8103, 0xC37A, 0x8104, 0xC37B, 0x8105, 0xC37C, 0x8107, 0xC37D, 0x8108, 0xC37E, 0x810B, 0xC380, 0x810C, 0xC381, 0x8115, + 0xC382, 0x8117, 0xC383, 0x8119, 0xC384, 0x811B, 0xC385, 0x811C, 0xC386, 0x811D, 0xC387, 0x811F, 0xC388, 0x8120, 0xC389, 0x8121, + 0xC38A, 0x8122, 0xC38B, 0x8123, 0xC38C, 0x8124, 0xC38D, 0x8125, 0xC38E, 0x8126, 0xC38F, 0x8127, 0xC390, 0x8128, 0xC391, 0x8129, + 0xC392, 0x812A, 0xC393, 0x812B, 0xC394, 0x812D, 0xC395, 0x812E, 0xC396, 0x8130, 0xC397, 0x8133, 0xC398, 0x8134, 0xC399, 0x8135, + 0xC39A, 0x8137, 0xC39B, 0x8139, 0xC39C, 0x813A, 0xC39D, 0x813B, 0xC39E, 0x813C, 0xC39F, 0x813D, 0xC3A0, 0x813F, 0xC3A1, 0x8C29, + 0xC3A2, 0x8292, 0xC3A3, 0x832B, 0xC3A4, 0x76F2, 0xC3A5, 0x6C13, 0xC3A6, 0x5FD9, 0xC3A7, 0x83BD, 0xC3A8, 0x732B, 0xC3A9, 0x8305, + 0xC3AA, 0x951A, 0xC3AB, 0x6BDB, 0xC3AC, 0x77DB, 0xC3AD, 0x94C6, 0xC3AE, 0x536F, 0xC3AF, 0x8302, 0xC3B0, 0x5192, 0xC3B1, 0x5E3D, + 0xC3B2, 0x8C8C, 0xC3B3, 0x8D38, 0xC3B4, 0x4E48, 0xC3B5, 0x73AB, 0xC3B6, 0x679A, 0xC3B7, 0x6885, 0xC3B8, 0x9176, 0xC3B9, 0x9709, + 0xC3BA, 0x7164, 0xC3BB, 0x6CA1, 0xC3BC, 0x7709, 0xC3BD, 0x5A92, 0xC3BE, 0x9541, 0xC3BF, 0x6BCF, 0xC3C0, 0x7F8E, 0xC3C1, 0x6627, + 0xC3C2, 0x5BD0, 0xC3C3, 0x59B9, 0xC3C4, 0x5A9A, 0xC3C5, 0x95E8, 0xC3C6, 0x95F7, 0xC3C7, 0x4EEC, 0xC3C8, 0x840C, 0xC3C9, 0x8499, + 0xC3CA, 0x6AAC, 0xC3CB, 0x76DF, 0xC3CC, 0x9530, 0xC3CD, 0x731B, 0xC3CE, 0x68A6, 0xC3CF, 0x5B5F, 0xC3D0, 0x772F, 0xC3D1, 0x919A, + 0xC3D2, 0x9761, 0xC3D3, 0x7CDC, 0xC3D4, 0x8FF7, 0xC3D5, 0x8C1C, 0xC3D6, 0x5F25, 0xC3D7, 0x7C73, 0xC3D8, 0x79D8, 0xC3D9, 0x89C5, + 0xC3DA, 0x6CCC, 0xC3DB, 0x871C, 0xC3DC, 0x5BC6, 0xC3DD, 0x5E42, 0xC3DE, 0x68C9, 0xC3DF, 0x7720, 0xC3E0, 0x7EF5, 0xC3E1, 0x5195, + 0xC3E2, 0x514D, 0xC3E3, 0x52C9, 0xC3E4, 0x5A29, 0xC3E5, 0x7F05, 0xC3E6, 0x9762, 0xC3E7, 0x82D7, 0xC3E8, 0x63CF, 0xC3E9, 0x7784, + 0xC3EA, 0x85D0, 0xC3EB, 0x79D2, 0xC3EC, 0x6E3A, 0xC3ED, 0x5E99, 0xC3EE, 0x5999, 0xC3EF, 0x8511, 0xC3F0, 0x706D, 0xC3F1, 0x6C11, + 0xC3F2, 0x62BF, 0xC3F3, 0x76BF, 0xC3F4, 0x654F, 0xC3F5, 0x60AF, 0xC3F6, 0x95FD, 0xC3F7, 0x660E, 0xC3F8, 0x879F, 0xC3F9, 0x9E23, + 0xC3FA, 0x94ED, 0xC3FB, 0x540D, 0xC3FC, 0x547D, 0xC3FD, 0x8C2C, 0xC3FE, 0x6478, 0xC440, 0x8140, 0xC441, 0x8141, 0xC442, 0x8142, + 0xC443, 0x8143, 0xC444, 0x8144, 0xC445, 0x8145, 0xC446, 0x8147, 0xC447, 0x8149, 0xC448, 0x814D, 0xC449, 0x814E, 0xC44A, 0x814F, + 0xC44B, 0x8152, 0xC44C, 0x8156, 0xC44D, 0x8157, 0xC44E, 0x8158, 0xC44F, 0x815B, 0xC450, 0x815C, 0xC451, 0x815D, 0xC452, 0x815E, + 0xC453, 0x815F, 0xC454, 0x8161, 0xC455, 0x8162, 0xC456, 0x8163, 0xC457, 0x8164, 0xC458, 0x8166, 0xC459, 0x8168, 0xC45A, 0x816A, + 0xC45B, 0x816B, 0xC45C, 0x816C, 0xC45D, 0x816F, 0xC45E, 0x8172, 0xC45F, 0x8173, 0xC460, 0x8175, 0xC461, 0x8176, 0xC462, 0x8177, + 0xC463, 0x8178, 0xC464, 0x8181, 0xC465, 0x8183, 0xC466, 0x8184, 0xC467, 0x8185, 0xC468, 0x8186, 0xC469, 0x8187, 0xC46A, 0x8189, + 0xC46B, 0x818B, 0xC46C, 0x818C, 0xC46D, 0x818D, 0xC46E, 0x818E, 0xC46F, 0x8190, 0xC470, 0x8192, 0xC471, 0x8193, 0xC472, 0x8194, + 0xC473, 0x8195, 0xC474, 0x8196, 0xC475, 0x8197, 0xC476, 0x8199, 0xC477, 0x819A, 0xC478, 0x819E, 0xC479, 0x819F, 0xC47A, 0x81A0, + 0xC47B, 0x81A1, 0xC47C, 0x81A2, 0xC47D, 0x81A4, 0xC47E, 0x81A5, 0xC480, 0x81A7, 0xC481, 0x81A9, 0xC482, 0x81AB, 0xC483, 0x81AC, + 0xC484, 0x81AD, 0xC485, 0x81AE, 0xC486, 0x81AF, 0xC487, 0x81B0, 0xC488, 0x81B1, 0xC489, 0x81B2, 0xC48A, 0x81B4, 0xC48B, 0x81B5, + 0xC48C, 0x81B6, 0xC48D, 0x81B7, 0xC48E, 0x81B8, 0xC48F, 0x81B9, 0xC490, 0x81BC, 0xC491, 0x81BD, 0xC492, 0x81BE, 0xC493, 0x81BF, + 0xC494, 0x81C4, 0xC495, 0x81C5, 0xC496, 0x81C7, 0xC497, 0x81C8, 0xC498, 0x81C9, 0xC499, 0x81CB, 0xC49A, 0x81CD, 0xC49B, 0x81CE, + 0xC49C, 0x81CF, 0xC49D, 0x81D0, 0xC49E, 0x81D1, 0xC49F, 0x81D2, 0xC4A0, 0x81D3, 0xC4A1, 0x6479, 0xC4A2, 0x8611, 0xC4A3, 0x6A21, + 0xC4A4, 0x819C, 0xC4A5, 0x78E8, 0xC4A6, 0x6469, 0xC4A7, 0x9B54, 0xC4A8, 0x62B9, 0xC4A9, 0x672B, 0xC4AA, 0x83AB, 0xC4AB, 0x58A8, + 0xC4AC, 0x9ED8, 0xC4AD, 0x6CAB, 0xC4AE, 0x6F20, 0xC4AF, 0x5BDE, 0xC4B0, 0x964C, 0xC4B1, 0x8C0B, 0xC4B2, 0x725F, 0xC4B3, 0x67D0, + 0xC4B4, 0x62C7, 0xC4B5, 0x7261, 0xC4B6, 0x4EA9, 0xC4B7, 0x59C6, 0xC4B8, 0x6BCD, 0xC4B9, 0x5893, 0xC4BA, 0x66AE, 0xC4BB, 0x5E55, + 0xC4BC, 0x52DF, 0xC4BD, 0x6155, 0xC4BE, 0x6728, 0xC4BF, 0x76EE, 0xC4C0, 0x7766, 0xC4C1, 0x7267, 0xC4C2, 0x7A46, 0xC4C3, 0x62FF, + 0xC4C4, 0x54EA, 0xC4C5, 0x5450, 0xC4C6, 0x94A0, 0xC4C7, 0x90A3, 0xC4C8, 0x5A1C, 0xC4C9, 0x7EB3, 0xC4CA, 0x6C16, 0xC4CB, 0x4E43, + 0xC4CC, 0x5976, 0xC4CD, 0x8010, 0xC4CE, 0x5948, 0xC4CF, 0x5357, 0xC4D0, 0x7537, 0xC4D1, 0x96BE, 0xC4D2, 0x56CA, 0xC4D3, 0x6320, + 0xC4D4, 0x8111, 0xC4D5, 0x607C, 0xC4D6, 0x95F9, 0xC4D7, 0x6DD6, 0xC4D8, 0x5462, 0xC4D9, 0x9981, 0xC4DA, 0x5185, 0xC4DB, 0x5AE9, + 0xC4DC, 0x80FD, 0xC4DD, 0x59AE, 0xC4DE, 0x9713, 0xC4DF, 0x502A, 0xC4E0, 0x6CE5, 0xC4E1, 0x5C3C, 0xC4E2, 0x62DF, 0xC4E3, 0x4F60, + 0xC4E4, 0x533F, 0xC4E5, 0x817B, 0xC4E6, 0x9006, 0xC4E7, 0x6EBA, 0xC4E8, 0x852B, 0xC4E9, 0x62C8, 0xC4EA, 0x5E74, 0xC4EB, 0x78BE, + 0xC4EC, 0x64B5, 0xC4ED, 0x637B, 0xC4EE, 0x5FF5, 0xC4EF, 0x5A18, 0xC4F0, 0x917F, 0xC4F1, 0x9E1F, 0xC4F2, 0x5C3F, 0xC4F3, 0x634F, + 0xC4F4, 0x8042, 0xC4F5, 0x5B7D, 0xC4F6, 0x556E, 0xC4F7, 0x954A, 0xC4F8, 0x954D, 0xC4F9, 0x6D85, 0xC4FA, 0x60A8, 0xC4FB, 0x67E0, + 0xC4FC, 0x72DE, 0xC4FD, 0x51DD, 0xC4FE, 0x5B81, 0xC540, 0x81D4, 0xC541, 0x81D5, 0xC542, 0x81D6, 0xC543, 0x81D7, 0xC544, 0x81D8, + 0xC545, 0x81D9, 0xC546, 0x81DA, 0xC547, 0x81DB, 0xC548, 0x81DC, 0xC549, 0x81DD, 0xC54A, 0x81DE, 0xC54B, 0x81DF, 0xC54C, 0x81E0, + 0xC54D, 0x81E1, 0xC54E, 0x81E2, 0xC54F, 0x81E4, 0xC550, 0x81E5, 0xC551, 0x81E6, 0xC552, 0x81E8, 0xC553, 0x81E9, 0xC554, 0x81EB, + 0xC555, 0x81EE, 0xC556, 0x81EF, 0xC557, 0x81F0, 0xC558, 0x81F1, 0xC559, 0x81F2, 0xC55A, 0x81F5, 0xC55B, 0x81F6, 0xC55C, 0x81F7, + 0xC55D, 0x81F8, 0xC55E, 0x81F9, 0xC55F, 0x81FA, 0xC560, 0x81FD, 0xC561, 0x81FF, 0xC562, 0x8203, 0xC563, 0x8207, 0xC564, 0x8208, + 0xC565, 0x8209, 0xC566, 0x820A, 0xC567, 0x820B, 0xC568, 0x820E, 0xC569, 0x820F, 0xC56A, 0x8211, 0xC56B, 0x8213, 0xC56C, 0x8215, + 0xC56D, 0x8216, 0xC56E, 0x8217, 0xC56F, 0x8218, 0xC570, 0x8219, 0xC571, 0x821A, 0xC572, 0x821D, 0xC573, 0x8220, 0xC574, 0x8224, + 0xC575, 0x8225, 0xC576, 0x8226, 0xC577, 0x8227, 0xC578, 0x8229, 0xC579, 0x822E, 0xC57A, 0x8232, 0xC57B, 0x823A, 0xC57C, 0x823C, + 0xC57D, 0x823D, 0xC57E, 0x823F, 0xC580, 0x8240, 0xC581, 0x8241, 0xC582, 0x8242, 0xC583, 0x8243, 0xC584, 0x8245, 0xC585, 0x8246, + 0xC586, 0x8248, 0xC587, 0x824A, 0xC588, 0x824C, 0xC589, 0x824D, 0xC58A, 0x824E, 0xC58B, 0x8250, 0xC58C, 0x8251, 0xC58D, 0x8252, + 0xC58E, 0x8253, 0xC58F, 0x8254, 0xC590, 0x8255, 0xC591, 0x8256, 0xC592, 0x8257, 0xC593, 0x8259, 0xC594, 0x825B, 0xC595, 0x825C, + 0xC596, 0x825D, 0xC597, 0x825E, 0xC598, 0x8260, 0xC599, 0x8261, 0xC59A, 0x8262, 0xC59B, 0x8263, 0xC59C, 0x8264, 0xC59D, 0x8265, + 0xC59E, 0x8266, 0xC59F, 0x8267, 0xC5A0, 0x8269, 0xC5A1, 0x62E7, 0xC5A2, 0x6CDE, 0xC5A3, 0x725B, 0xC5A4, 0x626D, 0xC5A5, 0x94AE, + 0xC5A6, 0x7EBD, 0xC5A7, 0x8113, 0xC5A8, 0x6D53, 0xC5A9, 0x519C, 0xC5AA, 0x5F04, 0xC5AB, 0x5974, 0xC5AC, 0x52AA, 0xC5AD, 0x6012, + 0xC5AE, 0x5973, 0xC5AF, 0x6696, 0xC5B0, 0x8650, 0xC5B1, 0x759F, 0xC5B2, 0x632A, 0xC5B3, 0x61E6, 0xC5B4, 0x7CEF, 0xC5B5, 0x8BFA, + 0xC5B6, 0x54E6, 0xC5B7, 0x6B27, 0xC5B8, 0x9E25, 0xC5B9, 0x6BB4, 0xC5BA, 0x85D5, 0xC5BB, 0x5455, 0xC5BC, 0x5076, 0xC5BD, 0x6CA4, + 0xC5BE, 0x556A, 0xC5BF, 0x8DB4, 0xC5C0, 0x722C, 0xC5C1, 0x5E15, 0xC5C2, 0x6015, 0xC5C3, 0x7436, 0xC5C4, 0x62CD, 0xC5C5, 0x6392, + 0xC5C6, 0x724C, 0xC5C7, 0x5F98, 0xC5C8, 0x6E43, 0xC5C9, 0x6D3E, 0xC5CA, 0x6500, 0xC5CB, 0x6F58, 0xC5CC, 0x76D8, 0xC5CD, 0x78D0, + 0xC5CE, 0x76FC, 0xC5CF, 0x7554, 0xC5D0, 0x5224, 0xC5D1, 0x53DB, 0xC5D2, 0x4E53, 0xC5D3, 0x5E9E, 0xC5D4, 0x65C1, 0xC5D5, 0x802A, + 0xC5D6, 0x80D6, 0xC5D7, 0x629B, 0xC5D8, 0x5486, 0xC5D9, 0x5228, 0xC5DA, 0x70AE, 0xC5DB, 0x888D, 0xC5DC, 0x8DD1, 0xC5DD, 0x6CE1, + 0xC5DE, 0x5478, 0xC5DF, 0x80DA, 0xC5E0, 0x57F9, 0xC5E1, 0x88F4, 0xC5E2, 0x8D54, 0xC5E3, 0x966A, 0xC5E4, 0x914D, 0xC5E5, 0x4F69, + 0xC5E6, 0x6C9B, 0xC5E7, 0x55B7, 0xC5E8, 0x76C6, 0xC5E9, 0x7830, 0xC5EA, 0x62A8, 0xC5EB, 0x70F9, 0xC5EC, 0x6F8E, 0xC5ED, 0x5F6D, + 0xC5EE, 0x84EC, 0xC5EF, 0x68DA, 0xC5F0, 0x787C, 0xC5F1, 0x7BF7, 0xC5F2, 0x81A8, 0xC5F3, 0x670B, 0xC5F4, 0x9E4F, 0xC5F5, 0x6367, + 0xC5F6, 0x78B0, 0xC5F7, 0x576F, 0xC5F8, 0x7812, 0xC5F9, 0x9739, 0xC5FA, 0x6279, 0xC5FB, 0x62AB, 0xC5FC, 0x5288, 0xC5FD, 0x7435, + 0xC5FE, 0x6BD7, 0xC640, 0x826A, 0xC641, 0x826B, 0xC642, 0x826C, 0xC643, 0x826D, 0xC644, 0x8271, 0xC645, 0x8275, 0xC646, 0x8276, + 0xC647, 0x8277, 0xC648, 0x8278, 0xC649, 0x827B, 0xC64A, 0x827C, 0xC64B, 0x8280, 0xC64C, 0x8281, 0xC64D, 0x8283, 0xC64E, 0x8285, + 0xC64F, 0x8286, 0xC650, 0x8287, 0xC651, 0x8289, 0xC652, 0x828C, 0xC653, 0x8290, 0xC654, 0x8293, 0xC655, 0x8294, 0xC656, 0x8295, + 0xC657, 0x8296, 0xC658, 0x829A, 0xC659, 0x829B, 0xC65A, 0x829E, 0xC65B, 0x82A0, 0xC65C, 0x82A2, 0xC65D, 0x82A3, 0xC65E, 0x82A7, + 0xC65F, 0x82B2, 0xC660, 0x82B5, 0xC661, 0x82B6, 0xC662, 0x82BA, 0xC663, 0x82BB, 0xC664, 0x82BC, 0xC665, 0x82BF, 0xC666, 0x82C0, + 0xC667, 0x82C2, 0xC668, 0x82C3, 0xC669, 0x82C5, 0xC66A, 0x82C6, 0xC66B, 0x82C9, 0xC66C, 0x82D0, 0xC66D, 0x82D6, 0xC66E, 0x82D9, + 0xC66F, 0x82DA, 0xC670, 0x82DD, 0xC671, 0x82E2, 0xC672, 0x82E7, 0xC673, 0x82E8, 0xC674, 0x82E9, 0xC675, 0x82EA, 0xC676, 0x82EC, + 0xC677, 0x82ED, 0xC678, 0x82EE, 0xC679, 0x82F0, 0xC67A, 0x82F2, 0xC67B, 0x82F3, 0xC67C, 0x82F5, 0xC67D, 0x82F6, 0xC67E, 0x82F8, + 0xC680, 0x82FA, 0xC681, 0x82FC, 0xC682, 0x82FD, 0xC683, 0x82FE, 0xC684, 0x82FF, 0xC685, 0x8300, 0xC686, 0x830A, 0xC687, 0x830B, + 0xC688, 0x830D, 0xC689, 0x8310, 0xC68A, 0x8312, 0xC68B, 0x8313, 0xC68C, 0x8316, 0xC68D, 0x8318, 0xC68E, 0x8319, 0xC68F, 0x831D, + 0xC690, 0x831E, 0xC691, 0x831F, 0xC692, 0x8320, 0xC693, 0x8321, 0xC694, 0x8322, 0xC695, 0x8323, 0xC696, 0x8324, 0xC697, 0x8325, + 0xC698, 0x8326, 0xC699, 0x8329, 0xC69A, 0x832A, 0xC69B, 0x832E, 0xC69C, 0x8330, 0xC69D, 0x8332, 0xC69E, 0x8337, 0xC69F, 0x833B, + 0xC6A0, 0x833D, 0xC6A1, 0x5564, 0xC6A2, 0x813E, 0xC6A3, 0x75B2, 0xC6A4, 0x76AE, 0xC6A5, 0x5339, 0xC6A6, 0x75DE, 0xC6A7, 0x50FB, + 0xC6A8, 0x5C41, 0xC6A9, 0x8B6C, 0xC6AA, 0x7BC7, 0xC6AB, 0x504F, 0xC6AC, 0x7247, 0xC6AD, 0x9A97, 0xC6AE, 0x98D8, 0xC6AF, 0x6F02, + 0xC6B0, 0x74E2, 0xC6B1, 0x7968, 0xC6B2, 0x6487, 0xC6B3, 0x77A5, 0xC6B4, 0x62FC, 0xC6B5, 0x9891, 0xC6B6, 0x8D2B, 0xC6B7, 0x54C1, + 0xC6B8, 0x8058, 0xC6B9, 0x4E52, 0xC6BA, 0x576A, 0xC6BB, 0x82F9, 0xC6BC, 0x840D, 0xC6BD, 0x5E73, 0xC6BE, 0x51ED, 0xC6BF, 0x74F6, + 0xC6C0, 0x8BC4, 0xC6C1, 0x5C4F, 0xC6C2, 0x5761, 0xC6C3, 0x6CFC, 0xC6C4, 0x9887, 0xC6C5, 0x5A46, 0xC6C6, 0x7834, 0xC6C7, 0x9B44, + 0xC6C8, 0x8FEB, 0xC6C9, 0x7C95, 0xC6CA, 0x5256, 0xC6CB, 0x6251, 0xC6CC, 0x94FA, 0xC6CD, 0x4EC6, 0xC6CE, 0x8386, 0xC6CF, 0x8461, + 0xC6D0, 0x83E9, 0xC6D1, 0x84B2, 0xC6D2, 0x57D4, 0xC6D3, 0x6734, 0xC6D4, 0x5703, 0xC6D5, 0x666E, 0xC6D6, 0x6D66, 0xC6D7, 0x8C31, + 0xC6D8, 0x66DD, 0xC6D9, 0x7011, 0xC6DA, 0x671F, 0xC6DB, 0x6B3A, 0xC6DC, 0x6816, 0xC6DD, 0x621A, 0xC6DE, 0x59BB, 0xC6DF, 0x4E03, + 0xC6E0, 0x51C4, 0xC6E1, 0x6F06, 0xC6E2, 0x67D2, 0xC6E3, 0x6C8F, 0xC6E4, 0x5176, 0xC6E5, 0x68CB, 0xC6E6, 0x5947, 0xC6E7, 0x6B67, + 0xC6E8, 0x7566, 0xC6E9, 0x5D0E, 0xC6EA, 0x8110, 0xC6EB, 0x9F50, 0xC6EC, 0x65D7, 0xC6ED, 0x7948, 0xC6EE, 0x7941, 0xC6EF, 0x9A91, + 0xC6F0, 0x8D77, 0xC6F1, 0x5C82, 0xC6F2, 0x4E5E, 0xC6F3, 0x4F01, 0xC6F4, 0x542F, 0xC6F5, 0x5951, 0xC6F6, 0x780C, 0xC6F7, 0x5668, + 0xC6F8, 0x6C14, 0xC6F9, 0x8FC4, 0xC6FA, 0x5F03, 0xC6FB, 0x6C7D, 0xC6FC, 0x6CE3, 0xC6FD, 0x8BAB, 0xC6FE, 0x6390, 0xC740, 0x833E, + 0xC741, 0x833F, 0xC742, 0x8341, 0xC743, 0x8342, 0xC744, 0x8344, 0xC745, 0x8345, 0xC746, 0x8348, 0xC747, 0x834A, 0xC748, 0x834B, + 0xC749, 0x834C, 0xC74A, 0x834D, 0xC74B, 0x834E, 0xC74C, 0x8353, 0xC74D, 0x8355, 0xC74E, 0x8356, 0xC74F, 0x8357, 0xC750, 0x8358, + 0xC751, 0x8359, 0xC752, 0x835D, 0xC753, 0x8362, 0xC754, 0x8370, 0xC755, 0x8371, 0xC756, 0x8372, 0xC757, 0x8373, 0xC758, 0x8374, + 0xC759, 0x8375, 0xC75A, 0x8376, 0xC75B, 0x8379, 0xC75C, 0x837A, 0xC75D, 0x837E, 0xC75E, 0x837F, 0xC75F, 0x8380, 0xC760, 0x8381, + 0xC761, 0x8382, 0xC762, 0x8383, 0xC763, 0x8384, 0xC764, 0x8387, 0xC765, 0x8388, 0xC766, 0x838A, 0xC767, 0x838B, 0xC768, 0x838C, + 0xC769, 0x838D, 0xC76A, 0x838F, 0xC76B, 0x8390, 0xC76C, 0x8391, 0xC76D, 0x8394, 0xC76E, 0x8395, 0xC76F, 0x8396, 0xC770, 0x8397, + 0xC771, 0x8399, 0xC772, 0x839A, 0xC773, 0x839D, 0xC774, 0x839F, 0xC775, 0x83A1, 0xC776, 0x83A2, 0xC777, 0x83A3, 0xC778, 0x83A4, + 0xC779, 0x83A5, 0xC77A, 0x83A6, 0xC77B, 0x83A7, 0xC77C, 0x83AC, 0xC77D, 0x83AD, 0xC77E, 0x83AE, 0xC780, 0x83AF, 0xC781, 0x83B5, + 0xC782, 0x83BB, 0xC783, 0x83BE, 0xC784, 0x83BF, 0xC785, 0x83C2, 0xC786, 0x83C3, 0xC787, 0x83C4, 0xC788, 0x83C6, 0xC789, 0x83C8, + 0xC78A, 0x83C9, 0xC78B, 0x83CB, 0xC78C, 0x83CD, 0xC78D, 0x83CE, 0xC78E, 0x83D0, 0xC78F, 0x83D1, 0xC790, 0x83D2, 0xC791, 0x83D3, + 0xC792, 0x83D5, 0xC793, 0x83D7, 0xC794, 0x83D9, 0xC795, 0x83DA, 0xC796, 0x83DB, 0xC797, 0x83DE, 0xC798, 0x83E2, 0xC799, 0x83E3, + 0xC79A, 0x83E4, 0xC79B, 0x83E6, 0xC79C, 0x83E7, 0xC79D, 0x83E8, 0xC79E, 0x83EB, 0xC79F, 0x83EC, 0xC7A0, 0x83ED, 0xC7A1, 0x6070, + 0xC7A2, 0x6D3D, 0xC7A3, 0x7275, 0xC7A4, 0x6266, 0xC7A5, 0x948E, 0xC7A6, 0x94C5, 0xC7A7, 0x5343, 0xC7A8, 0x8FC1, 0xC7A9, 0x7B7E, + 0xC7AA, 0x4EDF, 0xC7AB, 0x8C26, 0xC7AC, 0x4E7E, 0xC7AD, 0x9ED4, 0xC7AE, 0x94B1, 0xC7AF, 0x94B3, 0xC7B0, 0x524D, 0xC7B1, 0x6F5C, + 0xC7B2, 0x9063, 0xC7B3, 0x6D45, 0xC7B4, 0x8C34, 0xC7B5, 0x5811, 0xC7B6, 0x5D4C, 0xC7B7, 0x6B20, 0xC7B8, 0x6B49, 0xC7B9, 0x67AA, + 0xC7BA, 0x545B, 0xC7BB, 0x8154, 0xC7BC, 0x7F8C, 0xC7BD, 0x5899, 0xC7BE, 0x8537, 0xC7BF, 0x5F3A, 0xC7C0, 0x62A2, 0xC7C1, 0x6A47, + 0xC7C2, 0x9539, 0xC7C3, 0x6572, 0xC7C4, 0x6084, 0xC7C5, 0x6865, 0xC7C6, 0x77A7, 0xC7C7, 0x4E54, 0xC7C8, 0x4FA8, 0xC7C9, 0x5DE7, + 0xC7CA, 0x9798, 0xC7CB, 0x64AC, 0xC7CC, 0x7FD8, 0xC7CD, 0x5CED, 0xC7CE, 0x4FCF, 0xC7CF, 0x7A8D, 0xC7D0, 0x5207, 0xC7D1, 0x8304, + 0xC7D2, 0x4E14, 0xC7D3, 0x602F, 0xC7D4, 0x7A83, 0xC7D5, 0x94A6, 0xC7D6, 0x4FB5, 0xC7D7, 0x4EB2, 0xC7D8, 0x79E6, 0xC7D9, 0x7434, + 0xC7DA, 0x52E4, 0xC7DB, 0x82B9, 0xC7DC, 0x64D2, 0xC7DD, 0x79BD, 0xC7DE, 0x5BDD, 0xC7DF, 0x6C81, 0xC7E0, 0x9752, 0xC7E1, 0x8F7B, + 0xC7E2, 0x6C22, 0xC7E3, 0x503E, 0xC7E4, 0x537F, 0xC7E5, 0x6E05, 0xC7E6, 0x64CE, 0xC7E7, 0x6674, 0xC7E8, 0x6C30, 0xC7E9, 0x60C5, + 0xC7EA, 0x9877, 0xC7EB, 0x8BF7, 0xC7EC, 0x5E86, 0xC7ED, 0x743C, 0xC7EE, 0x7A77, 0xC7EF, 0x79CB, 0xC7F0, 0x4E18, 0xC7F1, 0x90B1, + 0xC7F2, 0x7403, 0xC7F3, 0x6C42, 0xC7F4, 0x56DA, 0xC7F5, 0x914B, 0xC7F6, 0x6CC5, 0xC7F7, 0x8D8B, 0xC7F8, 0x533A, 0xC7F9, 0x86C6, + 0xC7FA, 0x66F2, 0xC7FB, 0x8EAF, 0xC7FC, 0x5C48, 0xC7FD, 0x9A71, 0xC7FE, 0x6E20, 0xC840, 0x83EE, 0xC841, 0x83EF, 0xC842, 0x83F3, + 0xC843, 0x83F4, 0xC844, 0x83F5, 0xC845, 0x83F6, 0xC846, 0x83F7, 0xC847, 0x83FA, 0xC848, 0x83FB, 0xC849, 0x83FC, 0xC84A, 0x83FE, + 0xC84B, 0x83FF, 0xC84C, 0x8400, 0xC84D, 0x8402, 0xC84E, 0x8405, 0xC84F, 0x8407, 0xC850, 0x8408, 0xC851, 0x8409, 0xC852, 0x840A, + 0xC853, 0x8410, 0xC854, 0x8412, 0xC855, 0x8413, 0xC856, 0x8414, 0xC857, 0x8415, 0xC858, 0x8416, 0xC859, 0x8417, 0xC85A, 0x8419, + 0xC85B, 0x841A, 0xC85C, 0x841B, 0xC85D, 0x841E, 0xC85E, 0x841F, 0xC85F, 0x8420, 0xC860, 0x8421, 0xC861, 0x8422, 0xC862, 0x8423, + 0xC863, 0x8429, 0xC864, 0x842A, 0xC865, 0x842B, 0xC866, 0x842C, 0xC867, 0x842D, 0xC868, 0x842E, 0xC869, 0x842F, 0xC86A, 0x8430, + 0xC86B, 0x8432, 0xC86C, 0x8433, 0xC86D, 0x8434, 0xC86E, 0x8435, 0xC86F, 0x8436, 0xC870, 0x8437, 0xC871, 0x8439, 0xC872, 0x843A, + 0xC873, 0x843B, 0xC874, 0x843E, 0xC875, 0x843F, 0xC876, 0x8440, 0xC877, 0x8441, 0xC878, 0x8442, 0xC879, 0x8443, 0xC87A, 0x8444, + 0xC87B, 0x8445, 0xC87C, 0x8447, 0xC87D, 0x8448, 0xC87E, 0x8449, 0xC880, 0x844A, 0xC881, 0x844B, 0xC882, 0x844C, 0xC883, 0x844D, + 0xC884, 0x844E, 0xC885, 0x844F, 0xC886, 0x8450, 0xC887, 0x8452, 0xC888, 0x8453, 0xC889, 0x8454, 0xC88A, 0x8455, 0xC88B, 0x8456, + 0xC88C, 0x8458, 0xC88D, 0x845D, 0xC88E, 0x845E, 0xC88F, 0x845F, 0xC890, 0x8460, 0xC891, 0x8462, 0xC892, 0x8464, 0xC893, 0x8465, + 0xC894, 0x8466, 0xC895, 0x8467, 0xC896, 0x8468, 0xC897, 0x846A, 0xC898, 0x846E, 0xC899, 0x846F, 0xC89A, 0x8470, 0xC89B, 0x8472, + 0xC89C, 0x8474, 0xC89D, 0x8477, 0xC89E, 0x8479, 0xC89F, 0x847B, 0xC8A0, 0x847C, 0xC8A1, 0x53D6, 0xC8A2, 0x5A36, 0xC8A3, 0x9F8B, + 0xC8A4, 0x8DA3, 0xC8A5, 0x53BB, 0xC8A6, 0x5708, 0xC8A7, 0x98A7, 0xC8A8, 0x6743, 0xC8A9, 0x919B, 0xC8AA, 0x6CC9, 0xC8AB, 0x5168, + 0xC8AC, 0x75CA, 0xC8AD, 0x62F3, 0xC8AE, 0x72AC, 0xC8AF, 0x5238, 0xC8B0, 0x529D, 0xC8B1, 0x7F3A, 0xC8B2, 0x7094, 0xC8B3, 0x7638, + 0xC8B4, 0x5374, 0xC8B5, 0x9E4A, 0xC8B6, 0x69B7, 0xC8B7, 0x786E, 0xC8B8, 0x96C0, 0xC8B9, 0x88D9, 0xC8BA, 0x7FA4, 0xC8BB, 0x7136, + 0xC8BC, 0x71C3, 0xC8BD, 0x5189, 0xC8BE, 0x67D3, 0xC8BF, 0x74E4, 0xC8C0, 0x58E4, 0xC8C1, 0x6518, 0xC8C2, 0x56B7, 0xC8C3, 0x8BA9, + 0xC8C4, 0x9976, 0xC8C5, 0x6270, 0xC8C6, 0x7ED5, 0xC8C7, 0x60F9, 0xC8C8, 0x70ED, 0xC8C9, 0x58EC, 0xC8CA, 0x4EC1, 0xC8CB, 0x4EBA, + 0xC8CC, 0x5FCD, 0xC8CD, 0x97E7, 0xC8CE, 0x4EFB, 0xC8CF, 0x8BA4, 0xC8D0, 0x5203, 0xC8D1, 0x598A, 0xC8D2, 0x7EAB, 0xC8D3, 0x6254, + 0xC8D4, 0x4ECD, 0xC8D5, 0x65E5, 0xC8D6, 0x620E, 0xC8D7, 0x8338, 0xC8D8, 0x84C9, 0xC8D9, 0x8363, 0xC8DA, 0x878D, 0xC8DB, 0x7194, + 0xC8DC, 0x6EB6, 0xC8DD, 0x5BB9, 0xC8DE, 0x7ED2, 0xC8DF, 0x5197, 0xC8E0, 0x63C9, 0xC8E1, 0x67D4, 0xC8E2, 0x8089, 0xC8E3, 0x8339, + 0xC8E4, 0x8815, 0xC8E5, 0x5112, 0xC8E6, 0x5B7A, 0xC8E7, 0x5982, 0xC8E8, 0x8FB1, 0xC8E9, 0x4E73, 0xC8EA, 0x6C5D, 0xC8EB, 0x5165, + 0xC8EC, 0x8925, 0xC8ED, 0x8F6F, 0xC8EE, 0x962E, 0xC8EF, 0x854A, 0xC8F0, 0x745E, 0xC8F1, 0x9510, 0xC8F2, 0x95F0, 0xC8F3, 0x6DA6, + 0xC8F4, 0x82E5, 0xC8F5, 0x5F31, 0xC8F6, 0x6492, 0xC8F7, 0x6D12, 0xC8F8, 0x8428, 0xC8F9, 0x816E, 0xC8FA, 0x9CC3, 0xC8FB, 0x585E, + 0xC8FC, 0x8D5B, 0xC8FD, 0x4E09, 0xC8FE, 0x53C1, 0xC940, 0x847D, 0xC941, 0x847E, 0xC942, 0x847F, 0xC943, 0x8480, 0xC944, 0x8481, + 0xC945, 0x8483, 0xC946, 0x8484, 0xC947, 0x8485, 0xC948, 0x8486, 0xC949, 0x848A, 0xC94A, 0x848D, 0xC94B, 0x848F, 0xC94C, 0x8490, + 0xC94D, 0x8491, 0xC94E, 0x8492, 0xC94F, 0x8493, 0xC950, 0x8494, 0xC951, 0x8495, 0xC952, 0x8496, 0xC953, 0x8498, 0xC954, 0x849A, + 0xC955, 0x849B, 0xC956, 0x849D, 0xC957, 0x849E, 0xC958, 0x849F, 0xC959, 0x84A0, 0xC95A, 0x84A2, 0xC95B, 0x84A3, 0xC95C, 0x84A4, + 0xC95D, 0x84A5, 0xC95E, 0x84A6, 0xC95F, 0x84A7, 0xC960, 0x84A8, 0xC961, 0x84A9, 0xC962, 0x84AA, 0xC963, 0x84AB, 0xC964, 0x84AC, + 0xC965, 0x84AD, 0xC966, 0x84AE, 0xC967, 0x84B0, 0xC968, 0x84B1, 0xC969, 0x84B3, 0xC96A, 0x84B5, 0xC96B, 0x84B6, 0xC96C, 0x84B7, + 0xC96D, 0x84BB, 0xC96E, 0x84BC, 0xC96F, 0x84BE, 0xC970, 0x84C0, 0xC971, 0x84C2, 0xC972, 0x84C3, 0xC973, 0x84C5, 0xC974, 0x84C6, + 0xC975, 0x84C7, 0xC976, 0x84C8, 0xC977, 0x84CB, 0xC978, 0x84CC, 0xC979, 0x84CE, 0xC97A, 0x84CF, 0xC97B, 0x84D2, 0xC97C, 0x84D4, + 0xC97D, 0x84D5, 0xC97E, 0x84D7, 0xC980, 0x84D8, 0xC981, 0x84D9, 0xC982, 0x84DA, 0xC983, 0x84DB, 0xC984, 0x84DC, 0xC985, 0x84DE, + 0xC986, 0x84E1, 0xC987, 0x84E2, 0xC988, 0x84E4, 0xC989, 0x84E7, 0xC98A, 0x84E8, 0xC98B, 0x84E9, 0xC98C, 0x84EA, 0xC98D, 0x84EB, + 0xC98E, 0x84ED, 0xC98F, 0x84EE, 0xC990, 0x84EF, 0xC991, 0x84F1, 0xC992, 0x84F2, 0xC993, 0x84F3, 0xC994, 0x84F4, 0xC995, 0x84F5, + 0xC996, 0x84F6, 0xC997, 0x84F7, 0xC998, 0x84F8, 0xC999, 0x84F9, 0xC99A, 0x84FA, 0xC99B, 0x84FB, 0xC99C, 0x84FD, 0xC99D, 0x84FE, + 0xC99E, 0x8500, 0xC99F, 0x8501, 0xC9A0, 0x8502, 0xC9A1, 0x4F1E, 0xC9A2, 0x6563, 0xC9A3, 0x6851, 0xC9A4, 0x55D3, 0xC9A5, 0x4E27, + 0xC9A6, 0x6414, 0xC9A7, 0x9A9A, 0xC9A8, 0x626B, 0xC9A9, 0x5AC2, 0xC9AA, 0x745F, 0xC9AB, 0x8272, 0xC9AC, 0x6DA9, 0xC9AD, 0x68EE, + 0xC9AE, 0x50E7, 0xC9AF, 0x838E, 0xC9B0, 0x7802, 0xC9B1, 0x6740, 0xC9B2, 0x5239, 0xC9B3, 0x6C99, 0xC9B4, 0x7EB1, 0xC9B5, 0x50BB, + 0xC9B6, 0x5565, 0xC9B7, 0x715E, 0xC9B8, 0x7B5B, 0xC9B9, 0x6652, 0xC9BA, 0x73CA, 0xC9BB, 0x82EB, 0xC9BC, 0x6749, 0xC9BD, 0x5C71, + 0xC9BE, 0x5220, 0xC9BF, 0x717D, 0xC9C0, 0x886B, 0xC9C1, 0x95EA, 0xC9C2, 0x9655, 0xC9C3, 0x64C5, 0xC9C4, 0x8D61, 0xC9C5, 0x81B3, + 0xC9C6, 0x5584, 0xC9C7, 0x6C55, 0xC9C8, 0x6247, 0xC9C9, 0x7F2E, 0xC9CA, 0x5892, 0xC9CB, 0x4F24, 0xC9CC, 0x5546, 0xC9CD, 0x8D4F, + 0xC9CE, 0x664C, 0xC9CF, 0x4E0A, 0xC9D0, 0x5C1A, 0xC9D1, 0x88F3, 0xC9D2, 0x68A2, 0xC9D3, 0x634E, 0xC9D4, 0x7A0D, 0xC9D5, 0x70E7, + 0xC9D6, 0x828D, 0xC9D7, 0x52FA, 0xC9D8, 0x97F6, 0xC9D9, 0x5C11, 0xC9DA, 0x54E8, 0xC9DB, 0x90B5, 0xC9DC, 0x7ECD, 0xC9DD, 0x5962, + 0xC9DE, 0x8D4A, 0xC9DF, 0x86C7, 0xC9E0, 0x820C, 0xC9E1, 0x820D, 0xC9E2, 0x8D66, 0xC9E3, 0x6444, 0xC9E4, 0x5C04, 0xC9E5, 0x6151, + 0xC9E6, 0x6D89, 0xC9E7, 0x793E, 0xC9E8, 0x8BBE, 0xC9E9, 0x7837, 0xC9EA, 0x7533, 0xC9EB, 0x547B, 0xC9EC, 0x4F38, 0xC9ED, 0x8EAB, + 0xC9EE, 0x6DF1, 0xC9EF, 0x5A20, 0xC9F0, 0x7EC5, 0xC9F1, 0x795E, 0xC9F2, 0x6C88, 0xC9F3, 0x5BA1, 0xC9F4, 0x5A76, 0xC9F5, 0x751A, + 0xC9F6, 0x80BE, 0xC9F7, 0x614E, 0xC9F8, 0x6E17, 0xC9F9, 0x58F0, 0xC9FA, 0x751F, 0xC9FB, 0x7525, 0xC9FC, 0x7272, 0xC9FD, 0x5347, + 0xC9FE, 0x7EF3, 0xCA40, 0x8503, 0xCA41, 0x8504, 0xCA42, 0x8505, 0xCA43, 0x8506, 0xCA44, 0x8507, 0xCA45, 0x8508, 0xCA46, 0x8509, + 0xCA47, 0x850A, 0xCA48, 0x850B, 0xCA49, 0x850D, 0xCA4A, 0x850E, 0xCA4B, 0x850F, 0xCA4C, 0x8510, 0xCA4D, 0x8512, 0xCA4E, 0x8514, + 0xCA4F, 0x8515, 0xCA50, 0x8516, 0xCA51, 0x8518, 0xCA52, 0x8519, 0xCA53, 0x851B, 0xCA54, 0x851C, 0xCA55, 0x851D, 0xCA56, 0x851E, + 0xCA57, 0x8520, 0xCA58, 0x8522, 0xCA59, 0x8523, 0xCA5A, 0x8524, 0xCA5B, 0x8525, 0xCA5C, 0x8526, 0xCA5D, 0x8527, 0xCA5E, 0x8528, + 0xCA5F, 0x8529, 0xCA60, 0x852A, 0xCA61, 0x852D, 0xCA62, 0x852E, 0xCA63, 0x852F, 0xCA64, 0x8530, 0xCA65, 0x8531, 0xCA66, 0x8532, + 0xCA67, 0x8533, 0xCA68, 0x8534, 0xCA69, 0x8535, 0xCA6A, 0x8536, 0xCA6B, 0x853E, 0xCA6C, 0x853F, 0xCA6D, 0x8540, 0xCA6E, 0x8541, + 0xCA6F, 0x8542, 0xCA70, 0x8544, 0xCA71, 0x8545, 0xCA72, 0x8546, 0xCA73, 0x8547, 0xCA74, 0x854B, 0xCA75, 0x854C, 0xCA76, 0x854D, + 0xCA77, 0x854E, 0xCA78, 0x854F, 0xCA79, 0x8550, 0xCA7A, 0x8551, 0xCA7B, 0x8552, 0xCA7C, 0x8553, 0xCA7D, 0x8554, 0xCA7E, 0x8555, + 0xCA80, 0x8557, 0xCA81, 0x8558, 0xCA82, 0x855A, 0xCA83, 0x855B, 0xCA84, 0x855C, 0xCA85, 0x855D, 0xCA86, 0x855F, 0xCA87, 0x8560, + 0xCA88, 0x8561, 0xCA89, 0x8562, 0xCA8A, 0x8563, 0xCA8B, 0x8565, 0xCA8C, 0x8566, 0xCA8D, 0x8567, 0xCA8E, 0x8569, 0xCA8F, 0x856A, + 0xCA90, 0x856B, 0xCA91, 0x856C, 0xCA92, 0x856D, 0xCA93, 0x856E, 0xCA94, 0x856F, 0xCA95, 0x8570, 0xCA96, 0x8571, 0xCA97, 0x8573, + 0xCA98, 0x8575, 0xCA99, 0x8576, 0xCA9A, 0x8577, 0xCA9B, 0x8578, 0xCA9C, 0x857C, 0xCA9D, 0x857D, 0xCA9E, 0x857F, 0xCA9F, 0x8580, + 0xCAA0, 0x8581, 0xCAA1, 0x7701, 0xCAA2, 0x76DB, 0xCAA3, 0x5269, 0xCAA4, 0x80DC, 0xCAA5, 0x5723, 0xCAA6, 0x5E08, 0xCAA7, 0x5931, + 0xCAA8, 0x72EE, 0xCAA9, 0x65BD, 0xCAAA, 0x6E7F, 0xCAAB, 0x8BD7, 0xCAAC, 0x5C38, 0xCAAD, 0x8671, 0xCAAE, 0x5341, 0xCAAF, 0x77F3, + 0xCAB0, 0x62FE, 0xCAB1, 0x65F6, 0xCAB2, 0x4EC0, 0xCAB3, 0x98DF, 0xCAB4, 0x8680, 0xCAB5, 0x5B9E, 0xCAB6, 0x8BC6, 0xCAB7, 0x53F2, + 0xCAB8, 0x77E2, 0xCAB9, 0x4F7F, 0xCABA, 0x5C4E, 0xCABB, 0x9A76, 0xCABC, 0x59CB, 0xCABD, 0x5F0F, 0xCABE, 0x793A, 0xCABF, 0x58EB, + 0xCAC0, 0x4E16, 0xCAC1, 0x67FF, 0xCAC2, 0x4E8B, 0xCAC3, 0x62ED, 0xCAC4, 0x8A93, 0xCAC5, 0x901D, 0xCAC6, 0x52BF, 0xCAC7, 0x662F, + 0xCAC8, 0x55DC, 0xCAC9, 0x566C, 0xCACA, 0x9002, 0xCACB, 0x4ED5, 0xCACC, 0x4F8D, 0xCACD, 0x91CA, 0xCACE, 0x9970, 0xCACF, 0x6C0F, + 0xCAD0, 0x5E02, 0xCAD1, 0x6043, 0xCAD2, 0x5BA4, 0xCAD3, 0x89C6, 0xCAD4, 0x8BD5, 0xCAD5, 0x6536, 0xCAD6, 0x624B, 0xCAD7, 0x9996, + 0xCAD8, 0x5B88, 0xCAD9, 0x5BFF, 0xCADA, 0x6388, 0xCADB, 0x552E, 0xCADC, 0x53D7, 0xCADD, 0x7626, 0xCADE, 0x517D, 0xCADF, 0x852C, + 0xCAE0, 0x67A2, 0xCAE1, 0x68B3, 0xCAE2, 0x6B8A, 0xCAE3, 0x6292, 0xCAE4, 0x8F93, 0xCAE5, 0x53D4, 0xCAE6, 0x8212, 0xCAE7, 0x6DD1, + 0xCAE8, 0x758F, 0xCAE9, 0x4E66, 0xCAEA, 0x8D4E, 0xCAEB, 0x5B70, 0xCAEC, 0x719F, 0xCAED, 0x85AF, 0xCAEE, 0x6691, 0xCAEF, 0x66D9, + 0xCAF0, 0x7F72, 0xCAF1, 0x8700, 0xCAF2, 0x9ECD, 0xCAF3, 0x9F20, 0xCAF4, 0x5C5E, 0xCAF5, 0x672F, 0xCAF6, 0x8FF0, 0xCAF7, 0x6811, + 0xCAF8, 0x675F, 0xCAF9, 0x620D, 0xCAFA, 0x7AD6, 0xCAFB, 0x5885, 0xCAFC, 0x5EB6, 0xCAFD, 0x6570, 0xCAFE, 0x6F31, 0xCB40, 0x8582, + 0xCB41, 0x8583, 0xCB42, 0x8586, 0xCB43, 0x8588, 0xCB44, 0x8589, 0xCB45, 0x858A, 0xCB46, 0x858B, 0xCB47, 0x858C, 0xCB48, 0x858D, + 0xCB49, 0x858E, 0xCB4A, 0x8590, 0xCB4B, 0x8591, 0xCB4C, 0x8592, 0xCB4D, 0x8593, 0xCB4E, 0x8594, 0xCB4F, 0x8595, 0xCB50, 0x8596, + 0xCB51, 0x8597, 0xCB52, 0x8598, 0xCB53, 0x8599, 0xCB54, 0x859A, 0xCB55, 0x859D, 0xCB56, 0x859E, 0xCB57, 0x859F, 0xCB58, 0x85A0, + 0xCB59, 0x85A1, 0xCB5A, 0x85A2, 0xCB5B, 0x85A3, 0xCB5C, 0x85A5, 0xCB5D, 0x85A6, 0xCB5E, 0x85A7, 0xCB5F, 0x85A9, 0xCB60, 0x85AB, + 0xCB61, 0x85AC, 0xCB62, 0x85AD, 0xCB63, 0x85B1, 0xCB64, 0x85B2, 0xCB65, 0x85B3, 0xCB66, 0x85B4, 0xCB67, 0x85B5, 0xCB68, 0x85B6, + 0xCB69, 0x85B8, 0xCB6A, 0x85BA, 0xCB6B, 0x85BB, 0xCB6C, 0x85BC, 0xCB6D, 0x85BD, 0xCB6E, 0x85BE, 0xCB6F, 0x85BF, 0xCB70, 0x85C0, + 0xCB71, 0x85C2, 0xCB72, 0x85C3, 0xCB73, 0x85C4, 0xCB74, 0x85C5, 0xCB75, 0x85C6, 0xCB76, 0x85C7, 0xCB77, 0x85C8, 0xCB78, 0x85CA, + 0xCB79, 0x85CB, 0xCB7A, 0x85CC, 0xCB7B, 0x85CD, 0xCB7C, 0x85CE, 0xCB7D, 0x85D1, 0xCB7E, 0x85D2, 0xCB80, 0x85D4, 0xCB81, 0x85D6, + 0xCB82, 0x85D7, 0xCB83, 0x85D8, 0xCB84, 0x85D9, 0xCB85, 0x85DA, 0xCB86, 0x85DB, 0xCB87, 0x85DD, 0xCB88, 0x85DE, 0xCB89, 0x85DF, + 0xCB8A, 0x85E0, 0xCB8B, 0x85E1, 0xCB8C, 0x85E2, 0xCB8D, 0x85E3, 0xCB8E, 0x85E5, 0xCB8F, 0x85E6, 0xCB90, 0x85E7, 0xCB91, 0x85E8, + 0xCB92, 0x85EA, 0xCB93, 0x85EB, 0xCB94, 0x85EC, 0xCB95, 0x85ED, 0xCB96, 0x85EE, 0xCB97, 0x85EF, 0xCB98, 0x85F0, 0xCB99, 0x85F1, + 0xCB9A, 0x85F2, 0xCB9B, 0x85F3, 0xCB9C, 0x85F4, 0xCB9D, 0x85F5, 0xCB9E, 0x85F6, 0xCB9F, 0x85F7, 0xCBA0, 0x85F8, 0xCBA1, 0x6055, + 0xCBA2, 0x5237, 0xCBA3, 0x800D, 0xCBA4, 0x6454, 0xCBA5, 0x8870, 0xCBA6, 0x7529, 0xCBA7, 0x5E05, 0xCBA8, 0x6813, 0xCBA9, 0x62F4, + 0xCBAA, 0x971C, 0xCBAB, 0x53CC, 0xCBAC, 0x723D, 0xCBAD, 0x8C01, 0xCBAE, 0x6C34, 0xCBAF, 0x7761, 0xCBB0, 0x7A0E, 0xCBB1, 0x542E, + 0xCBB2, 0x77AC, 0xCBB3, 0x987A, 0xCBB4, 0x821C, 0xCBB5, 0x8BF4, 0xCBB6, 0x7855, 0xCBB7, 0x6714, 0xCBB8, 0x70C1, 0xCBB9, 0x65AF, + 0xCBBA, 0x6495, 0xCBBB, 0x5636, 0xCBBC, 0x601D, 0xCBBD, 0x79C1, 0xCBBE, 0x53F8, 0xCBBF, 0x4E1D, 0xCBC0, 0x6B7B, 0xCBC1, 0x8086, + 0xCBC2, 0x5BFA, 0xCBC3, 0x55E3, 0xCBC4, 0x56DB, 0xCBC5, 0x4F3A, 0xCBC6, 0x4F3C, 0xCBC7, 0x9972, 0xCBC8, 0x5DF3, 0xCBC9, 0x677E, + 0xCBCA, 0x8038, 0xCBCB, 0x6002, 0xCBCC, 0x9882, 0xCBCD, 0x9001, 0xCBCE, 0x5B8B, 0xCBCF, 0x8BBC, 0xCBD0, 0x8BF5, 0xCBD1, 0x641C, + 0xCBD2, 0x8258, 0xCBD3, 0x64DE, 0xCBD4, 0x55FD, 0xCBD5, 0x82CF, 0xCBD6, 0x9165, 0xCBD7, 0x4FD7, 0xCBD8, 0x7D20, 0xCBD9, 0x901F, + 0xCBDA, 0x7C9F, 0xCBDB, 0x50F3, 0xCBDC, 0x5851, 0xCBDD, 0x6EAF, 0xCBDE, 0x5BBF, 0xCBDF, 0x8BC9, 0xCBE0, 0x8083, 0xCBE1, 0x9178, + 0xCBE2, 0x849C, 0xCBE3, 0x7B97, 0xCBE4, 0x867D, 0xCBE5, 0x968B, 0xCBE6, 0x968F, 0xCBE7, 0x7EE5, 0xCBE8, 0x9AD3, 0xCBE9, 0x788E, + 0xCBEA, 0x5C81, 0xCBEB, 0x7A57, 0xCBEC, 0x9042, 0xCBED, 0x96A7, 0xCBEE, 0x795F, 0xCBEF, 0x5B59, 0xCBF0, 0x635F, 0xCBF1, 0x7B0B, + 0xCBF2, 0x84D1, 0xCBF3, 0x68AD, 0xCBF4, 0x5506, 0xCBF5, 0x7F29, 0xCBF6, 0x7410, 0xCBF7, 0x7D22, 0xCBF8, 0x9501, 0xCBF9, 0x6240, + 0xCBFA, 0x584C, 0xCBFB, 0x4ED6, 0xCBFC, 0x5B83, 0xCBFD, 0x5979, 0xCBFE, 0x5854, 0xCC40, 0x85F9, 0xCC41, 0x85FA, 0xCC42, 0x85FC, + 0xCC43, 0x85FD, 0xCC44, 0x85FE, 0xCC45, 0x8600, 0xCC46, 0x8601, 0xCC47, 0x8602, 0xCC48, 0x8603, 0xCC49, 0x8604, 0xCC4A, 0x8606, + 0xCC4B, 0x8607, 0xCC4C, 0x8608, 0xCC4D, 0x8609, 0xCC4E, 0x860A, 0xCC4F, 0x860B, 0xCC50, 0x860C, 0xCC51, 0x860D, 0xCC52, 0x860E, + 0xCC53, 0x860F, 0xCC54, 0x8610, 0xCC55, 0x8612, 0xCC56, 0x8613, 0xCC57, 0x8614, 0xCC58, 0x8615, 0xCC59, 0x8617, 0xCC5A, 0x8618, + 0xCC5B, 0x8619, 0xCC5C, 0x861A, 0xCC5D, 0x861B, 0xCC5E, 0x861C, 0xCC5F, 0x861D, 0xCC60, 0x861E, 0xCC61, 0x861F, 0xCC62, 0x8620, + 0xCC63, 0x8621, 0xCC64, 0x8622, 0xCC65, 0x8623, 0xCC66, 0x8624, 0xCC67, 0x8625, 0xCC68, 0x8626, 0xCC69, 0x8628, 0xCC6A, 0x862A, + 0xCC6B, 0x862B, 0xCC6C, 0x862C, 0xCC6D, 0x862D, 0xCC6E, 0x862E, 0xCC6F, 0x862F, 0xCC70, 0x8630, 0xCC71, 0x8631, 0xCC72, 0x8632, + 0xCC73, 0x8633, 0xCC74, 0x8634, 0xCC75, 0x8635, 0xCC76, 0x8636, 0xCC77, 0x8637, 0xCC78, 0x8639, 0xCC79, 0x863A, 0xCC7A, 0x863B, + 0xCC7B, 0x863D, 0xCC7C, 0x863E, 0xCC7D, 0x863F, 0xCC7E, 0x8640, 0xCC80, 0x8641, 0xCC81, 0x8642, 0xCC82, 0x8643, 0xCC83, 0x8644, + 0xCC84, 0x8645, 0xCC85, 0x8646, 0xCC86, 0x8647, 0xCC87, 0x8648, 0xCC88, 0x8649, 0xCC89, 0x864A, 0xCC8A, 0x864B, 0xCC8B, 0x864C, + 0xCC8C, 0x8652, 0xCC8D, 0x8653, 0xCC8E, 0x8655, 0xCC8F, 0x8656, 0xCC90, 0x8657, 0xCC91, 0x8658, 0xCC92, 0x8659, 0xCC93, 0x865B, + 0xCC94, 0x865C, 0xCC95, 0x865D, 0xCC96, 0x865F, 0xCC97, 0x8660, 0xCC98, 0x8661, 0xCC99, 0x8663, 0xCC9A, 0x8664, 0xCC9B, 0x8665, + 0xCC9C, 0x8666, 0xCC9D, 0x8667, 0xCC9E, 0x8668, 0xCC9F, 0x8669, 0xCCA0, 0x866A, 0xCCA1, 0x736D, 0xCCA2, 0x631E, 0xCCA3, 0x8E4B, + 0xCCA4, 0x8E0F, 0xCCA5, 0x80CE, 0xCCA6, 0x82D4, 0xCCA7, 0x62AC, 0xCCA8, 0x53F0, 0xCCA9, 0x6CF0, 0xCCAA, 0x915E, 0xCCAB, 0x592A, + 0xCCAC, 0x6001, 0xCCAD, 0x6C70, 0xCCAE, 0x574D, 0xCCAF, 0x644A, 0xCCB0, 0x8D2A, 0xCCB1, 0x762B, 0xCCB2, 0x6EE9, 0xCCB3, 0x575B, + 0xCCB4, 0x6A80, 0xCCB5, 0x75F0, 0xCCB6, 0x6F6D, 0xCCB7, 0x8C2D, 0xCCB8, 0x8C08, 0xCCB9, 0x5766, 0xCCBA, 0x6BEF, 0xCCBB, 0x8892, + 0xCCBC, 0x78B3, 0xCCBD, 0x63A2, 0xCCBE, 0x53F9, 0xCCBF, 0x70AD, 0xCCC0, 0x6C64, 0xCCC1, 0x5858, 0xCCC2, 0x642A, 0xCCC3, 0x5802, + 0xCCC4, 0x68E0, 0xCCC5, 0x819B, 0xCCC6, 0x5510, 0xCCC7, 0x7CD6, 0xCCC8, 0x5018, 0xCCC9, 0x8EBA, 0xCCCA, 0x6DCC, 0xCCCB, 0x8D9F, + 0xCCCC, 0x70EB, 0xCCCD, 0x638F, 0xCCCE, 0x6D9B, 0xCCCF, 0x6ED4, 0xCCD0, 0x7EE6, 0xCCD1, 0x8404, 0xCCD2, 0x6843, 0xCCD3, 0x9003, + 0xCCD4, 0x6DD8, 0xCCD5, 0x9676, 0xCCD6, 0x8BA8, 0xCCD7, 0x5957, 0xCCD8, 0x7279, 0xCCD9, 0x85E4, 0xCCDA, 0x817E, 0xCCDB, 0x75BC, + 0xCCDC, 0x8A8A, 0xCCDD, 0x68AF, 0xCCDE, 0x5254, 0xCCDF, 0x8E22, 0xCCE0, 0x9511, 0xCCE1, 0x63D0, 0xCCE2, 0x9898, 0xCCE3, 0x8E44, + 0xCCE4, 0x557C, 0xCCE5, 0x4F53, 0xCCE6, 0x66FF, 0xCCE7, 0x568F, 0xCCE8, 0x60D5, 0xCCE9, 0x6D95, 0xCCEA, 0x5243, 0xCCEB, 0x5C49, + 0xCCEC, 0x5929, 0xCCED, 0x6DFB, 0xCCEE, 0x586B, 0xCCEF, 0x7530, 0xCCF0, 0x751C, 0xCCF1, 0x606C, 0xCCF2, 0x8214, 0xCCF3, 0x8146, + 0xCCF4, 0x6311, 0xCCF5, 0x6761, 0xCCF6, 0x8FE2, 0xCCF7, 0x773A, 0xCCF8, 0x8DF3, 0xCCF9, 0x8D34, 0xCCFA, 0x94C1, 0xCCFB, 0x5E16, + 0xCCFC, 0x5385, 0xCCFD, 0x542C, 0xCCFE, 0x70C3, 0xCD40, 0x866D, 0xCD41, 0x866F, 0xCD42, 0x8670, 0xCD43, 0x8672, 0xCD44, 0x8673, + 0xCD45, 0x8674, 0xCD46, 0x8675, 0xCD47, 0x8676, 0xCD48, 0x8677, 0xCD49, 0x8678, 0xCD4A, 0x8683, 0xCD4B, 0x8684, 0xCD4C, 0x8685, + 0xCD4D, 0x8686, 0xCD4E, 0x8687, 0xCD4F, 0x8688, 0xCD50, 0x8689, 0xCD51, 0x868E, 0xCD52, 0x868F, 0xCD53, 0x8690, 0xCD54, 0x8691, + 0xCD55, 0x8692, 0xCD56, 0x8694, 0xCD57, 0x8696, 0xCD58, 0x8697, 0xCD59, 0x8698, 0xCD5A, 0x8699, 0xCD5B, 0x869A, 0xCD5C, 0x869B, + 0xCD5D, 0x869E, 0xCD5E, 0x869F, 0xCD5F, 0x86A0, 0xCD60, 0x86A1, 0xCD61, 0x86A2, 0xCD62, 0x86A5, 0xCD63, 0x86A6, 0xCD64, 0x86AB, + 0xCD65, 0x86AD, 0xCD66, 0x86AE, 0xCD67, 0x86B2, 0xCD68, 0x86B3, 0xCD69, 0x86B7, 0xCD6A, 0x86B8, 0xCD6B, 0x86B9, 0xCD6C, 0x86BB, + 0xCD6D, 0x86BC, 0xCD6E, 0x86BD, 0xCD6F, 0x86BE, 0xCD70, 0x86BF, 0xCD71, 0x86C1, 0xCD72, 0x86C2, 0xCD73, 0x86C3, 0xCD74, 0x86C5, + 0xCD75, 0x86C8, 0xCD76, 0x86CC, 0xCD77, 0x86CD, 0xCD78, 0x86D2, 0xCD79, 0x86D3, 0xCD7A, 0x86D5, 0xCD7B, 0x86D6, 0xCD7C, 0x86D7, + 0xCD7D, 0x86DA, 0xCD7E, 0x86DC, 0xCD80, 0x86DD, 0xCD81, 0x86E0, 0xCD82, 0x86E1, 0xCD83, 0x86E2, 0xCD84, 0x86E3, 0xCD85, 0x86E5, + 0xCD86, 0x86E6, 0xCD87, 0x86E7, 0xCD88, 0x86E8, 0xCD89, 0x86EA, 0xCD8A, 0x86EB, 0xCD8B, 0x86EC, 0xCD8C, 0x86EF, 0xCD8D, 0x86F5, + 0xCD8E, 0x86F6, 0xCD8F, 0x86F7, 0xCD90, 0x86FA, 0xCD91, 0x86FB, 0xCD92, 0x86FC, 0xCD93, 0x86FD, 0xCD94, 0x86FF, 0xCD95, 0x8701, + 0xCD96, 0x8704, 0xCD97, 0x8705, 0xCD98, 0x8706, 0xCD99, 0x870B, 0xCD9A, 0x870C, 0xCD9B, 0x870E, 0xCD9C, 0x870F, 0xCD9D, 0x8710, + 0xCD9E, 0x8711, 0xCD9F, 0x8714, 0xCDA0, 0x8716, 0xCDA1, 0x6C40, 0xCDA2, 0x5EF7, 0xCDA3, 0x505C, 0xCDA4, 0x4EAD, 0xCDA5, 0x5EAD, + 0xCDA6, 0x633A, 0xCDA7, 0x8247, 0xCDA8, 0x901A, 0xCDA9, 0x6850, 0xCDAA, 0x916E, 0xCDAB, 0x77B3, 0xCDAC, 0x540C, 0xCDAD, 0x94DC, + 0xCDAE, 0x5F64, 0xCDAF, 0x7AE5, 0xCDB0, 0x6876, 0xCDB1, 0x6345, 0xCDB2, 0x7B52, 0xCDB3, 0x7EDF, 0xCDB4, 0x75DB, 0xCDB5, 0x5077, + 0xCDB6, 0x6295, 0xCDB7, 0x5934, 0xCDB8, 0x900F, 0xCDB9, 0x51F8, 0xCDBA, 0x79C3, 0xCDBB, 0x7A81, 0xCDBC, 0x56FE, 0xCDBD, 0x5F92, + 0xCDBE, 0x9014, 0xCDBF, 0x6D82, 0xCDC0, 0x5C60, 0xCDC1, 0x571F, 0xCDC2, 0x5410, 0xCDC3, 0x5154, 0xCDC4, 0x6E4D, 0xCDC5, 0x56E2, + 0xCDC6, 0x63A8, 0xCDC7, 0x9893, 0xCDC8, 0x817F, 0xCDC9, 0x8715, 0xCDCA, 0x892A, 0xCDCB, 0x9000, 0xCDCC, 0x541E, 0xCDCD, 0x5C6F, + 0xCDCE, 0x81C0, 0xCDCF, 0x62D6, 0xCDD0, 0x6258, 0xCDD1, 0x8131, 0xCDD2, 0x9E35, 0xCDD3, 0x9640, 0xCDD4, 0x9A6E, 0xCDD5, 0x9A7C, + 0xCDD6, 0x692D, 0xCDD7, 0x59A5, 0xCDD8, 0x62D3, 0xCDD9, 0x553E, 0xCDDA, 0x6316, 0xCDDB, 0x54C7, 0xCDDC, 0x86D9, 0xCDDD, 0x6D3C, + 0xCDDE, 0x5A03, 0xCDDF, 0x74E6, 0xCDE0, 0x889C, 0xCDE1, 0x6B6A, 0xCDE2, 0x5916, 0xCDE3, 0x8C4C, 0xCDE4, 0x5F2F, 0xCDE5, 0x6E7E, + 0xCDE6, 0x73A9, 0xCDE7, 0x987D, 0xCDE8, 0x4E38, 0xCDE9, 0x70F7, 0xCDEA, 0x5B8C, 0xCDEB, 0x7897, 0xCDEC, 0x633D, 0xCDED, 0x665A, + 0xCDEE, 0x7696, 0xCDEF, 0x60CB, 0xCDF0, 0x5B9B, 0xCDF1, 0x5A49, 0xCDF2, 0x4E07, 0xCDF3, 0x8155, 0xCDF4, 0x6C6A, 0xCDF5, 0x738B, + 0xCDF6, 0x4EA1, 0xCDF7, 0x6789, 0xCDF8, 0x7F51, 0xCDF9, 0x5F80, 0xCDFA, 0x65FA, 0xCDFB, 0x671B, 0xCDFC, 0x5FD8, 0xCDFD, 0x5984, + 0xCDFE, 0x5A01, 0xCE40, 0x8719, 0xCE41, 0x871B, 0xCE42, 0x871D, 0xCE43, 0x871F, 0xCE44, 0x8720, 0xCE45, 0x8724, 0xCE46, 0x8726, + 0xCE47, 0x8727, 0xCE48, 0x8728, 0xCE49, 0x872A, 0xCE4A, 0x872B, 0xCE4B, 0x872C, 0xCE4C, 0x872D, 0xCE4D, 0x872F, 0xCE4E, 0x8730, + 0xCE4F, 0x8732, 0xCE50, 0x8733, 0xCE51, 0x8735, 0xCE52, 0x8736, 0xCE53, 0x8738, 0xCE54, 0x8739, 0xCE55, 0x873A, 0xCE56, 0x873C, + 0xCE57, 0x873D, 0xCE58, 0x8740, 0xCE59, 0x8741, 0xCE5A, 0x8742, 0xCE5B, 0x8743, 0xCE5C, 0x8744, 0xCE5D, 0x8745, 0xCE5E, 0x8746, + 0xCE5F, 0x874A, 0xCE60, 0x874B, 0xCE61, 0x874D, 0xCE62, 0x874F, 0xCE63, 0x8750, 0xCE64, 0x8751, 0xCE65, 0x8752, 0xCE66, 0x8754, + 0xCE67, 0x8755, 0xCE68, 0x8756, 0xCE69, 0x8758, 0xCE6A, 0x875A, 0xCE6B, 0x875B, 0xCE6C, 0x875C, 0xCE6D, 0x875D, 0xCE6E, 0x875E, + 0xCE6F, 0x875F, 0xCE70, 0x8761, 0xCE71, 0x8762, 0xCE72, 0x8766, 0xCE73, 0x8767, 0xCE74, 0x8768, 0xCE75, 0x8769, 0xCE76, 0x876A, + 0xCE77, 0x876B, 0xCE78, 0x876C, 0xCE79, 0x876D, 0xCE7A, 0x876F, 0xCE7B, 0x8771, 0xCE7C, 0x8772, 0xCE7D, 0x8773, 0xCE7E, 0x8775, + 0xCE80, 0x8777, 0xCE81, 0x8778, 0xCE82, 0x8779, 0xCE83, 0x877A, 0xCE84, 0x877F, 0xCE85, 0x8780, 0xCE86, 0x8781, 0xCE87, 0x8784, + 0xCE88, 0x8786, 0xCE89, 0x8787, 0xCE8A, 0x8789, 0xCE8B, 0x878A, 0xCE8C, 0x878C, 0xCE8D, 0x878E, 0xCE8E, 0x878F, 0xCE8F, 0x8790, + 0xCE90, 0x8791, 0xCE91, 0x8792, 0xCE92, 0x8794, 0xCE93, 0x8795, 0xCE94, 0x8796, 0xCE95, 0x8798, 0xCE96, 0x8799, 0xCE97, 0x879A, + 0xCE98, 0x879B, 0xCE99, 0x879C, 0xCE9A, 0x879D, 0xCE9B, 0x879E, 0xCE9C, 0x87A0, 0xCE9D, 0x87A1, 0xCE9E, 0x87A2, 0xCE9F, 0x87A3, + 0xCEA0, 0x87A4, 0xCEA1, 0x5DCD, 0xCEA2, 0x5FAE, 0xCEA3, 0x5371, 0xCEA4, 0x97E6, 0xCEA5, 0x8FDD, 0xCEA6, 0x6845, 0xCEA7, 0x56F4, + 0xCEA8, 0x552F, 0xCEA9, 0x60DF, 0xCEAA, 0x4E3A, 0xCEAB, 0x6F4D, 0xCEAC, 0x7EF4, 0xCEAD, 0x82C7, 0xCEAE, 0x840E, 0xCEAF, 0x59D4, + 0xCEB0, 0x4F1F, 0xCEB1, 0x4F2A, 0xCEB2, 0x5C3E, 0xCEB3, 0x7EAC, 0xCEB4, 0x672A, 0xCEB5, 0x851A, 0xCEB6, 0x5473, 0xCEB7, 0x754F, + 0xCEB8, 0x80C3, 0xCEB9, 0x5582, 0xCEBA, 0x9B4F, 0xCEBB, 0x4F4D, 0xCEBC, 0x6E2D, 0xCEBD, 0x8C13, 0xCEBE, 0x5C09, 0xCEBF, 0x6170, + 0xCEC0, 0x536B, 0xCEC1, 0x761F, 0xCEC2, 0x6E29, 0xCEC3, 0x868A, 0xCEC4, 0x6587, 0xCEC5, 0x95FB, 0xCEC6, 0x7EB9, 0xCEC7, 0x543B, + 0xCEC8, 0x7A33, 0xCEC9, 0x7D0A, 0xCECA, 0x95EE, 0xCECB, 0x55E1, 0xCECC, 0x7FC1, 0xCECD, 0x74EE, 0xCECE, 0x631D, 0xCECF, 0x8717, + 0xCED0, 0x6DA1, 0xCED1, 0x7A9D, 0xCED2, 0x6211, 0xCED3, 0x65A1, 0xCED4, 0x5367, 0xCED5, 0x63E1, 0xCED6, 0x6C83, 0xCED7, 0x5DEB, + 0xCED8, 0x545C, 0xCED9, 0x94A8, 0xCEDA, 0x4E4C, 0xCEDB, 0x6C61, 0xCEDC, 0x8BEC, 0xCEDD, 0x5C4B, 0xCEDE, 0x65E0, 0xCEDF, 0x829C, + 0xCEE0, 0x68A7, 0xCEE1, 0x543E, 0xCEE2, 0x5434, 0xCEE3, 0x6BCB, 0xCEE4, 0x6B66, 0xCEE5, 0x4E94, 0xCEE6, 0x6342, 0xCEE7, 0x5348, + 0xCEE8, 0x821E, 0xCEE9, 0x4F0D, 0xCEEA, 0x4FAE, 0xCEEB, 0x575E, 0xCEEC, 0x620A, 0xCEED, 0x96FE, 0xCEEE, 0x6664, 0xCEEF, 0x7269, + 0xCEF0, 0x52FF, 0xCEF1, 0x52A1, 0xCEF2, 0x609F, 0xCEF3, 0x8BEF, 0xCEF4, 0x6614, 0xCEF5, 0x7199, 0xCEF6, 0x6790, 0xCEF7, 0x897F, + 0xCEF8, 0x7852, 0xCEF9, 0x77FD, 0xCEFA, 0x6670, 0xCEFB, 0x563B, 0xCEFC, 0x5438, 0xCEFD, 0x9521, 0xCEFE, 0x727A, 0xCF40, 0x87A5, + 0xCF41, 0x87A6, 0xCF42, 0x87A7, 0xCF43, 0x87A9, 0xCF44, 0x87AA, 0xCF45, 0x87AE, 0xCF46, 0x87B0, 0xCF47, 0x87B1, 0xCF48, 0x87B2, + 0xCF49, 0x87B4, 0xCF4A, 0x87B6, 0xCF4B, 0x87B7, 0xCF4C, 0x87B8, 0xCF4D, 0x87B9, 0xCF4E, 0x87BB, 0xCF4F, 0x87BC, 0xCF50, 0x87BE, + 0xCF51, 0x87BF, 0xCF52, 0x87C1, 0xCF53, 0x87C2, 0xCF54, 0x87C3, 0xCF55, 0x87C4, 0xCF56, 0x87C5, 0xCF57, 0x87C7, 0xCF58, 0x87C8, + 0xCF59, 0x87C9, 0xCF5A, 0x87CC, 0xCF5B, 0x87CD, 0xCF5C, 0x87CE, 0xCF5D, 0x87CF, 0xCF5E, 0x87D0, 0xCF5F, 0x87D4, 0xCF60, 0x87D5, + 0xCF61, 0x87D6, 0xCF62, 0x87D7, 0xCF63, 0x87D8, 0xCF64, 0x87D9, 0xCF65, 0x87DA, 0xCF66, 0x87DC, 0xCF67, 0x87DD, 0xCF68, 0x87DE, + 0xCF69, 0x87DF, 0xCF6A, 0x87E1, 0xCF6B, 0x87E2, 0xCF6C, 0x87E3, 0xCF6D, 0x87E4, 0xCF6E, 0x87E6, 0xCF6F, 0x87E7, 0xCF70, 0x87E8, + 0xCF71, 0x87E9, 0xCF72, 0x87EB, 0xCF73, 0x87EC, 0xCF74, 0x87ED, 0xCF75, 0x87EF, 0xCF76, 0x87F0, 0xCF77, 0x87F1, 0xCF78, 0x87F2, + 0xCF79, 0x87F3, 0xCF7A, 0x87F4, 0xCF7B, 0x87F5, 0xCF7C, 0x87F6, 0xCF7D, 0x87F7, 0xCF7E, 0x87F8, 0xCF80, 0x87FA, 0xCF81, 0x87FB, + 0xCF82, 0x87FC, 0xCF83, 0x87FD, 0xCF84, 0x87FF, 0xCF85, 0x8800, 0xCF86, 0x8801, 0xCF87, 0x8802, 0xCF88, 0x8804, 0xCF89, 0x8805, + 0xCF8A, 0x8806, 0xCF8B, 0x8807, 0xCF8C, 0x8808, 0xCF8D, 0x8809, 0xCF8E, 0x880B, 0xCF8F, 0x880C, 0xCF90, 0x880D, 0xCF91, 0x880E, + 0xCF92, 0x880F, 0xCF93, 0x8810, 0xCF94, 0x8811, 0xCF95, 0x8812, 0xCF96, 0x8814, 0xCF97, 0x8817, 0xCF98, 0x8818, 0xCF99, 0x8819, + 0xCF9A, 0x881A, 0xCF9B, 0x881C, 0xCF9C, 0x881D, 0xCF9D, 0x881E, 0xCF9E, 0x881F, 0xCF9F, 0x8820, 0xCFA0, 0x8823, 0xCFA1, 0x7A00, + 0xCFA2, 0x606F, 0xCFA3, 0x5E0C, 0xCFA4, 0x6089, 0xCFA5, 0x819D, 0xCFA6, 0x5915, 0xCFA7, 0x60DC, 0xCFA8, 0x7184, 0xCFA9, 0x70EF, + 0xCFAA, 0x6EAA, 0xCFAB, 0x6C50, 0xCFAC, 0x7280, 0xCFAD, 0x6A84, 0xCFAE, 0x88AD, 0xCFAF, 0x5E2D, 0xCFB0, 0x4E60, 0xCFB1, 0x5AB3, + 0xCFB2, 0x559C, 0xCFB3, 0x94E3, 0xCFB4, 0x6D17, 0xCFB5, 0x7CFB, 0xCFB6, 0x9699, 0xCFB7, 0x620F, 0xCFB8, 0x7EC6, 0xCFB9, 0x778E, + 0xCFBA, 0x867E, 0xCFBB, 0x5323, 0xCFBC, 0x971E, 0xCFBD, 0x8F96, 0xCFBE, 0x6687, 0xCFBF, 0x5CE1, 0xCFC0, 0x4FA0, 0xCFC1, 0x72ED, + 0xCFC2, 0x4E0B, 0xCFC3, 0x53A6, 0xCFC4, 0x590F, 0xCFC5, 0x5413, 0xCFC6, 0x6380, 0xCFC7, 0x9528, 0xCFC8, 0x5148, 0xCFC9, 0x4ED9, + 0xCFCA, 0x9C9C, 0xCFCB, 0x7EA4, 0xCFCC, 0x54B8, 0xCFCD, 0x8D24, 0xCFCE, 0x8854, 0xCFCF, 0x8237, 0xCFD0, 0x95F2, 0xCFD1, 0x6D8E, + 0xCFD2, 0x5F26, 0xCFD3, 0x5ACC, 0xCFD4, 0x663E, 0xCFD5, 0x9669, 0xCFD6, 0x73B0, 0xCFD7, 0x732E, 0xCFD8, 0x53BF, 0xCFD9, 0x817A, + 0xCFDA, 0x9985, 0xCFDB, 0x7FA1, 0xCFDC, 0x5BAA, 0xCFDD, 0x9677, 0xCFDE, 0x9650, 0xCFDF, 0x7EBF, 0xCFE0, 0x76F8, 0xCFE1, 0x53A2, + 0xCFE2, 0x9576, 0xCFE3, 0x9999, 0xCFE4, 0x7BB1, 0xCFE5, 0x8944, 0xCFE6, 0x6E58, 0xCFE7, 0x4E61, 0xCFE8, 0x7FD4, 0xCFE9, 0x7965, + 0xCFEA, 0x8BE6, 0xCFEB, 0x60F3, 0xCFEC, 0x54CD, 0xCFED, 0x4EAB, 0xCFEE, 0x9879, 0xCFEF, 0x5DF7, 0xCFF0, 0x6A61, 0xCFF1, 0x50CF, + 0xCFF2, 0x5411, 0xCFF3, 0x8C61, 0xCFF4, 0x8427, 0xCFF5, 0x785D, 0xCFF6, 0x9704, 0xCFF7, 0x524A, 0xCFF8, 0x54EE, 0xCFF9, 0x56A3, + 0xCFFA, 0x9500, 0xCFFB, 0x6D88, 0xCFFC, 0x5BB5, 0xCFFD, 0x6DC6, 0xCFFE, 0x6653, 0xD040, 0x8824, 0xD041, 0x8825, 0xD042, 0x8826, + 0xD043, 0x8827, 0xD044, 0x8828, 0xD045, 0x8829, 0xD046, 0x882A, 0xD047, 0x882B, 0xD048, 0x882C, 0xD049, 0x882D, 0xD04A, 0x882E, + 0xD04B, 0x882F, 0xD04C, 0x8830, 0xD04D, 0x8831, 0xD04E, 0x8833, 0xD04F, 0x8834, 0xD050, 0x8835, 0xD051, 0x8836, 0xD052, 0x8837, + 0xD053, 0x8838, 0xD054, 0x883A, 0xD055, 0x883B, 0xD056, 0x883D, 0xD057, 0x883E, 0xD058, 0x883F, 0xD059, 0x8841, 0xD05A, 0x8842, + 0xD05B, 0x8843, 0xD05C, 0x8846, 0xD05D, 0x8847, 0xD05E, 0x8848, 0xD05F, 0x8849, 0xD060, 0x884A, 0xD061, 0x884B, 0xD062, 0x884E, + 0xD063, 0x884F, 0xD064, 0x8850, 0xD065, 0x8851, 0xD066, 0x8852, 0xD067, 0x8853, 0xD068, 0x8855, 0xD069, 0x8856, 0xD06A, 0x8858, + 0xD06B, 0x885A, 0xD06C, 0x885B, 0xD06D, 0x885C, 0xD06E, 0x885D, 0xD06F, 0x885E, 0xD070, 0x885F, 0xD071, 0x8860, 0xD072, 0x8866, + 0xD073, 0x8867, 0xD074, 0x886A, 0xD075, 0x886D, 0xD076, 0x886F, 0xD077, 0x8871, 0xD078, 0x8873, 0xD079, 0x8874, 0xD07A, 0x8875, + 0xD07B, 0x8876, 0xD07C, 0x8878, 0xD07D, 0x8879, 0xD07E, 0x887A, 0xD080, 0x887B, 0xD081, 0x887C, 0xD082, 0x8880, 0xD083, 0x8883, + 0xD084, 0x8886, 0xD085, 0x8887, 0xD086, 0x8889, 0xD087, 0x888A, 0xD088, 0x888C, 0xD089, 0x888E, 0xD08A, 0x888F, 0xD08B, 0x8890, + 0xD08C, 0x8891, 0xD08D, 0x8893, 0xD08E, 0x8894, 0xD08F, 0x8895, 0xD090, 0x8897, 0xD091, 0x8898, 0xD092, 0x8899, 0xD093, 0x889A, + 0xD094, 0x889B, 0xD095, 0x889D, 0xD096, 0x889E, 0xD097, 0x889F, 0xD098, 0x88A0, 0xD099, 0x88A1, 0xD09A, 0x88A3, 0xD09B, 0x88A5, + 0xD09C, 0x88A6, 0xD09D, 0x88A7, 0xD09E, 0x88A8, 0xD09F, 0x88A9, 0xD0A0, 0x88AA, 0xD0A1, 0x5C0F, 0xD0A2, 0x5B5D, 0xD0A3, 0x6821, + 0xD0A4, 0x8096, 0xD0A5, 0x5578, 0xD0A6, 0x7B11, 0xD0A7, 0x6548, 0xD0A8, 0x6954, 0xD0A9, 0x4E9B, 0xD0AA, 0x6B47, 0xD0AB, 0x874E, + 0xD0AC, 0x978B, 0xD0AD, 0x534F, 0xD0AE, 0x631F, 0xD0AF, 0x643A, 0xD0B0, 0x90AA, 0xD0B1, 0x659C, 0xD0B2, 0x80C1, 0xD0B3, 0x8C10, + 0xD0B4, 0x5199, 0xD0B5, 0x68B0, 0xD0B6, 0x5378, 0xD0B7, 0x87F9, 0xD0B8, 0x61C8, 0xD0B9, 0x6CC4, 0xD0BA, 0x6CFB, 0xD0BB, 0x8C22, + 0xD0BC, 0x5C51, 0xD0BD, 0x85AA, 0xD0BE, 0x82AF, 0xD0BF, 0x950C, 0xD0C0, 0x6B23, 0xD0C1, 0x8F9B, 0xD0C2, 0x65B0, 0xD0C3, 0x5FFB, + 0xD0C4, 0x5FC3, 0xD0C5, 0x4FE1, 0xD0C6, 0x8845, 0xD0C7, 0x661F, 0xD0C8, 0x8165, 0xD0C9, 0x7329, 0xD0CA, 0x60FA, 0xD0CB, 0x5174, + 0xD0CC, 0x5211, 0xD0CD, 0x578B, 0xD0CE, 0x5F62, 0xD0CF, 0x90A2, 0xD0D0, 0x884C, 0xD0D1, 0x9192, 0xD0D2, 0x5E78, 0xD0D3, 0x674F, + 0xD0D4, 0x6027, 0xD0D5, 0x59D3, 0xD0D6, 0x5144, 0xD0D7, 0x51F6, 0xD0D8, 0x80F8, 0xD0D9, 0x5308, 0xD0DA, 0x6C79, 0xD0DB, 0x96C4, + 0xD0DC, 0x718A, 0xD0DD, 0x4F11, 0xD0DE, 0x4FEE, 0xD0DF, 0x7F9E, 0xD0E0, 0x673D, 0xD0E1, 0x55C5, 0xD0E2, 0x9508, 0xD0E3, 0x79C0, + 0xD0E4, 0x8896, 0xD0E5, 0x7EE3, 0xD0E6, 0x589F, 0xD0E7, 0x620C, 0xD0E8, 0x9700, 0xD0E9, 0x865A, 0xD0EA, 0x5618, 0xD0EB, 0x987B, + 0xD0EC, 0x5F90, 0xD0ED, 0x8BB8, 0xD0EE, 0x84C4, 0xD0EF, 0x9157, 0xD0F0, 0x53D9, 0xD0F1, 0x65ED, 0xD0F2, 0x5E8F, 0xD0F3, 0x755C, + 0xD0F4, 0x6064, 0xD0F5, 0x7D6E, 0xD0F6, 0x5A7F, 0xD0F7, 0x7EEA, 0xD0F8, 0x7EED, 0xD0F9, 0x8F69, 0xD0FA, 0x55A7, 0xD0FB, 0x5BA3, + 0xD0FC, 0x60AC, 0xD0FD, 0x65CB, 0xD0FE, 0x7384, 0xD140, 0x88AC, 0xD141, 0x88AE, 0xD142, 0x88AF, 0xD143, 0x88B0, 0xD144, 0x88B2, + 0xD145, 0x88B3, 0xD146, 0x88B4, 0xD147, 0x88B5, 0xD148, 0x88B6, 0xD149, 0x88B8, 0xD14A, 0x88B9, 0xD14B, 0x88BA, 0xD14C, 0x88BB, + 0xD14D, 0x88BD, 0xD14E, 0x88BE, 0xD14F, 0x88BF, 0xD150, 0x88C0, 0xD151, 0x88C3, 0xD152, 0x88C4, 0xD153, 0x88C7, 0xD154, 0x88C8, + 0xD155, 0x88CA, 0xD156, 0x88CB, 0xD157, 0x88CC, 0xD158, 0x88CD, 0xD159, 0x88CF, 0xD15A, 0x88D0, 0xD15B, 0x88D1, 0xD15C, 0x88D3, + 0xD15D, 0x88D6, 0xD15E, 0x88D7, 0xD15F, 0x88DA, 0xD160, 0x88DB, 0xD161, 0x88DC, 0xD162, 0x88DD, 0xD163, 0x88DE, 0xD164, 0x88E0, + 0xD165, 0x88E1, 0xD166, 0x88E6, 0xD167, 0x88E7, 0xD168, 0x88E9, 0xD169, 0x88EA, 0xD16A, 0x88EB, 0xD16B, 0x88EC, 0xD16C, 0x88ED, + 0xD16D, 0x88EE, 0xD16E, 0x88EF, 0xD16F, 0x88F2, 0xD170, 0x88F5, 0xD171, 0x88F6, 0xD172, 0x88F7, 0xD173, 0x88FA, 0xD174, 0x88FB, + 0xD175, 0x88FD, 0xD176, 0x88FF, 0xD177, 0x8900, 0xD178, 0x8901, 0xD179, 0x8903, 0xD17A, 0x8904, 0xD17B, 0x8905, 0xD17C, 0x8906, + 0xD17D, 0x8907, 0xD17E, 0x8908, 0xD180, 0x8909, 0xD181, 0x890B, 0xD182, 0x890C, 0xD183, 0x890D, 0xD184, 0x890E, 0xD185, 0x890F, + 0xD186, 0x8911, 0xD187, 0x8914, 0xD188, 0x8915, 0xD189, 0x8916, 0xD18A, 0x8917, 0xD18B, 0x8918, 0xD18C, 0x891C, 0xD18D, 0x891D, + 0xD18E, 0x891E, 0xD18F, 0x891F, 0xD190, 0x8920, 0xD191, 0x8922, 0xD192, 0x8923, 0xD193, 0x8924, 0xD194, 0x8926, 0xD195, 0x8927, + 0xD196, 0x8928, 0xD197, 0x8929, 0xD198, 0x892C, 0xD199, 0x892D, 0xD19A, 0x892E, 0xD19B, 0x892F, 0xD19C, 0x8931, 0xD19D, 0x8932, + 0xD19E, 0x8933, 0xD19F, 0x8935, 0xD1A0, 0x8937, 0xD1A1, 0x9009, 0xD1A2, 0x7663, 0xD1A3, 0x7729, 0xD1A4, 0x7EDA, 0xD1A5, 0x9774, + 0xD1A6, 0x859B, 0xD1A7, 0x5B66, 0xD1A8, 0x7A74, 0xD1A9, 0x96EA, 0xD1AA, 0x8840, 0xD1AB, 0x52CB, 0xD1AC, 0x718F, 0xD1AD, 0x5FAA, + 0xD1AE, 0x65EC, 0xD1AF, 0x8BE2, 0xD1B0, 0x5BFB, 0xD1B1, 0x9A6F, 0xD1B2, 0x5DE1, 0xD1B3, 0x6B89, 0xD1B4, 0x6C5B, 0xD1B5, 0x8BAD, + 0xD1B6, 0x8BAF, 0xD1B7, 0x900A, 0xD1B8, 0x8FC5, 0xD1B9, 0x538B, 0xD1BA, 0x62BC, 0xD1BB, 0x9E26, 0xD1BC, 0x9E2D, 0xD1BD, 0x5440, + 0xD1BE, 0x4E2B, 0xD1BF, 0x82BD, 0xD1C0, 0x7259, 0xD1C1, 0x869C, 0xD1C2, 0x5D16, 0xD1C3, 0x8859, 0xD1C4, 0x6DAF, 0xD1C5, 0x96C5, + 0xD1C6, 0x54D1, 0xD1C7, 0x4E9A, 0xD1C8, 0x8BB6, 0xD1C9, 0x7109, 0xD1CA, 0x54BD, 0xD1CB, 0x9609, 0xD1CC, 0x70DF, 0xD1CD, 0x6DF9, + 0xD1CE, 0x76D0, 0xD1CF, 0x4E25, 0xD1D0, 0x7814, 0xD1D1, 0x8712, 0xD1D2, 0x5CA9, 0xD1D3, 0x5EF6, 0xD1D4, 0x8A00, 0xD1D5, 0x989C, + 0xD1D6, 0x960E, 0xD1D7, 0x708E, 0xD1D8, 0x6CBF, 0xD1D9, 0x5944, 0xD1DA, 0x63A9, 0xD1DB, 0x773C, 0xD1DC, 0x884D, 0xD1DD, 0x6F14, + 0xD1DE, 0x8273, 0xD1DF, 0x5830, 0xD1E0, 0x71D5, 0xD1E1, 0x538C, 0xD1E2, 0x781A, 0xD1E3, 0x96C1, 0xD1E4, 0x5501, 0xD1E5, 0x5F66, + 0xD1E6, 0x7130, 0xD1E7, 0x5BB4, 0xD1E8, 0x8C1A, 0xD1E9, 0x9A8C, 0xD1EA, 0x6B83, 0xD1EB, 0x592E, 0xD1EC, 0x9E2F, 0xD1ED, 0x79E7, + 0xD1EE, 0x6768, 0xD1EF, 0x626C, 0xD1F0, 0x4F6F, 0xD1F1, 0x75A1, 0xD1F2, 0x7F8A, 0xD1F3, 0x6D0B, 0xD1F4, 0x9633, 0xD1F5, 0x6C27, + 0xD1F6, 0x4EF0, 0xD1F7, 0x75D2, 0xD1F8, 0x517B, 0xD1F9, 0x6837, 0xD1FA, 0x6F3E, 0xD1FB, 0x9080, 0xD1FC, 0x8170, 0xD1FD, 0x5996, + 0xD1FE, 0x7476, 0xD240, 0x8938, 0xD241, 0x8939, 0xD242, 0x893A, 0xD243, 0x893B, 0xD244, 0x893C, 0xD245, 0x893D, 0xD246, 0x893E, + 0xD247, 0x893F, 0xD248, 0x8940, 0xD249, 0x8942, 0xD24A, 0x8943, 0xD24B, 0x8945, 0xD24C, 0x8946, 0xD24D, 0x8947, 0xD24E, 0x8948, + 0xD24F, 0x8949, 0xD250, 0x894A, 0xD251, 0x894B, 0xD252, 0x894C, 0xD253, 0x894D, 0xD254, 0x894E, 0xD255, 0x894F, 0xD256, 0x8950, + 0xD257, 0x8951, 0xD258, 0x8952, 0xD259, 0x8953, 0xD25A, 0x8954, 0xD25B, 0x8955, 0xD25C, 0x8956, 0xD25D, 0x8957, 0xD25E, 0x8958, + 0xD25F, 0x8959, 0xD260, 0x895A, 0xD261, 0x895B, 0xD262, 0x895C, 0xD263, 0x895D, 0xD264, 0x8960, 0xD265, 0x8961, 0xD266, 0x8962, + 0xD267, 0x8963, 0xD268, 0x8964, 0xD269, 0x8965, 0xD26A, 0x8967, 0xD26B, 0x8968, 0xD26C, 0x8969, 0xD26D, 0x896A, 0xD26E, 0x896B, + 0xD26F, 0x896C, 0xD270, 0x896D, 0xD271, 0x896E, 0xD272, 0x896F, 0xD273, 0x8970, 0xD274, 0x8971, 0xD275, 0x8972, 0xD276, 0x8973, + 0xD277, 0x8974, 0xD278, 0x8975, 0xD279, 0x8976, 0xD27A, 0x8977, 0xD27B, 0x8978, 0xD27C, 0x8979, 0xD27D, 0x897A, 0xD27E, 0x897C, + 0xD280, 0x897D, 0xD281, 0x897E, 0xD282, 0x8980, 0xD283, 0x8982, 0xD284, 0x8984, 0xD285, 0x8985, 0xD286, 0x8987, 0xD287, 0x8988, + 0xD288, 0x8989, 0xD289, 0x898A, 0xD28A, 0x898B, 0xD28B, 0x898C, 0xD28C, 0x898D, 0xD28D, 0x898E, 0xD28E, 0x898F, 0xD28F, 0x8990, + 0xD290, 0x8991, 0xD291, 0x8992, 0xD292, 0x8993, 0xD293, 0x8994, 0xD294, 0x8995, 0xD295, 0x8996, 0xD296, 0x8997, 0xD297, 0x8998, + 0xD298, 0x8999, 0xD299, 0x899A, 0xD29A, 0x899B, 0xD29B, 0x899C, 0xD29C, 0x899D, 0xD29D, 0x899E, 0xD29E, 0x899F, 0xD29F, 0x89A0, + 0xD2A0, 0x89A1, 0xD2A1, 0x6447, 0xD2A2, 0x5C27, 0xD2A3, 0x9065, 0xD2A4, 0x7A91, 0xD2A5, 0x8C23, 0xD2A6, 0x59DA, 0xD2A7, 0x54AC, + 0xD2A8, 0x8200, 0xD2A9, 0x836F, 0xD2AA, 0x8981, 0xD2AB, 0x8000, 0xD2AC, 0x6930, 0xD2AD, 0x564E, 0xD2AE, 0x8036, 0xD2AF, 0x7237, + 0xD2B0, 0x91CE, 0xD2B1, 0x51B6, 0xD2B2, 0x4E5F, 0xD2B3, 0x9875, 0xD2B4, 0x6396, 0xD2B5, 0x4E1A, 0xD2B6, 0x53F6, 0xD2B7, 0x66F3, + 0xD2B8, 0x814B, 0xD2B9, 0x591C, 0xD2BA, 0x6DB2, 0xD2BB, 0x4E00, 0xD2BC, 0x58F9, 0xD2BD, 0x533B, 0xD2BE, 0x63D6, 0xD2BF, 0x94F1, + 0xD2C0, 0x4F9D, 0xD2C1, 0x4F0A, 0xD2C2, 0x8863, 0xD2C3, 0x9890, 0xD2C4, 0x5937, 0xD2C5, 0x9057, 0xD2C6, 0x79FB, 0xD2C7, 0x4EEA, + 0xD2C8, 0x80F0, 0xD2C9, 0x7591, 0xD2CA, 0x6C82, 0xD2CB, 0x5B9C, 0xD2CC, 0x59E8, 0xD2CD, 0x5F5D, 0xD2CE, 0x6905, 0xD2CF, 0x8681, + 0xD2D0, 0x501A, 0xD2D1, 0x5DF2, 0xD2D2, 0x4E59, 0xD2D3, 0x77E3, 0xD2D4, 0x4EE5, 0xD2D5, 0x827A, 0xD2D6, 0x6291, 0xD2D7, 0x6613, + 0xD2D8, 0x9091, 0xD2D9, 0x5C79, 0xD2DA, 0x4EBF, 0xD2DB, 0x5F79, 0xD2DC, 0x81C6, 0xD2DD, 0x9038, 0xD2DE, 0x8084, 0xD2DF, 0x75AB, + 0xD2E0, 0x4EA6, 0xD2E1, 0x88D4, 0xD2E2, 0x610F, 0xD2E3, 0x6BC5, 0xD2E4, 0x5FC6, 0xD2E5, 0x4E49, 0xD2E6, 0x76CA, 0xD2E7, 0x6EA2, + 0xD2E8, 0x8BE3, 0xD2E9, 0x8BAE, 0xD2EA, 0x8C0A, 0xD2EB, 0x8BD1, 0xD2EC, 0x5F02, 0xD2ED, 0x7FFC, 0xD2EE, 0x7FCC, 0xD2EF, 0x7ECE, + 0xD2F0, 0x8335, 0xD2F1, 0x836B, 0xD2F2, 0x56E0, 0xD2F3, 0x6BB7, 0xD2F4, 0x97F3, 0xD2F5, 0x9634, 0xD2F6, 0x59FB, 0xD2F7, 0x541F, + 0xD2F8, 0x94F6, 0xD2F9, 0x6DEB, 0xD2FA, 0x5BC5, 0xD2FB, 0x996E, 0xD2FC, 0x5C39, 0xD2FD, 0x5F15, 0xD2FE, 0x9690, 0xD340, 0x89A2, + 0xD341, 0x89A3, 0xD342, 0x89A4, 0xD343, 0x89A5, 0xD344, 0x89A6, 0xD345, 0x89A7, 0xD346, 0x89A8, 0xD347, 0x89A9, 0xD348, 0x89AA, + 0xD349, 0x89AB, 0xD34A, 0x89AC, 0xD34B, 0x89AD, 0xD34C, 0x89AE, 0xD34D, 0x89AF, 0xD34E, 0x89B0, 0xD34F, 0x89B1, 0xD350, 0x89B2, + 0xD351, 0x89B3, 0xD352, 0x89B4, 0xD353, 0x89B5, 0xD354, 0x89B6, 0xD355, 0x89B7, 0xD356, 0x89B8, 0xD357, 0x89B9, 0xD358, 0x89BA, + 0xD359, 0x89BB, 0xD35A, 0x89BC, 0xD35B, 0x89BD, 0xD35C, 0x89BE, 0xD35D, 0x89BF, 0xD35E, 0x89C0, 0xD35F, 0x89C3, 0xD360, 0x89CD, + 0xD361, 0x89D3, 0xD362, 0x89D4, 0xD363, 0x89D5, 0xD364, 0x89D7, 0xD365, 0x89D8, 0xD366, 0x89D9, 0xD367, 0x89DB, 0xD368, 0x89DD, + 0xD369, 0x89DF, 0xD36A, 0x89E0, 0xD36B, 0x89E1, 0xD36C, 0x89E2, 0xD36D, 0x89E4, 0xD36E, 0x89E7, 0xD36F, 0x89E8, 0xD370, 0x89E9, + 0xD371, 0x89EA, 0xD372, 0x89EC, 0xD373, 0x89ED, 0xD374, 0x89EE, 0xD375, 0x89F0, 0xD376, 0x89F1, 0xD377, 0x89F2, 0xD378, 0x89F4, + 0xD379, 0x89F5, 0xD37A, 0x89F6, 0xD37B, 0x89F7, 0xD37C, 0x89F8, 0xD37D, 0x89F9, 0xD37E, 0x89FA, 0xD380, 0x89FB, 0xD381, 0x89FC, + 0xD382, 0x89FD, 0xD383, 0x89FE, 0xD384, 0x89FF, 0xD385, 0x8A01, 0xD386, 0x8A02, 0xD387, 0x8A03, 0xD388, 0x8A04, 0xD389, 0x8A05, + 0xD38A, 0x8A06, 0xD38B, 0x8A08, 0xD38C, 0x8A09, 0xD38D, 0x8A0A, 0xD38E, 0x8A0B, 0xD38F, 0x8A0C, 0xD390, 0x8A0D, 0xD391, 0x8A0E, + 0xD392, 0x8A0F, 0xD393, 0x8A10, 0xD394, 0x8A11, 0xD395, 0x8A12, 0xD396, 0x8A13, 0xD397, 0x8A14, 0xD398, 0x8A15, 0xD399, 0x8A16, + 0xD39A, 0x8A17, 0xD39B, 0x8A18, 0xD39C, 0x8A19, 0xD39D, 0x8A1A, 0xD39E, 0x8A1B, 0xD39F, 0x8A1C, 0xD3A0, 0x8A1D, 0xD3A1, 0x5370, + 0xD3A2, 0x82F1, 0xD3A3, 0x6A31, 0xD3A4, 0x5A74, 0xD3A5, 0x9E70, 0xD3A6, 0x5E94, 0xD3A7, 0x7F28, 0xD3A8, 0x83B9, 0xD3A9, 0x8424, + 0xD3AA, 0x8425, 0xD3AB, 0x8367, 0xD3AC, 0x8747, 0xD3AD, 0x8FCE, 0xD3AE, 0x8D62, 0xD3AF, 0x76C8, 0xD3B0, 0x5F71, 0xD3B1, 0x9896, + 0xD3B2, 0x786C, 0xD3B3, 0x6620, 0xD3B4, 0x54DF, 0xD3B5, 0x62E5, 0xD3B6, 0x4F63, 0xD3B7, 0x81C3, 0xD3B8, 0x75C8, 0xD3B9, 0x5EB8, + 0xD3BA, 0x96CD, 0xD3BB, 0x8E0A, 0xD3BC, 0x86F9, 0xD3BD, 0x548F, 0xD3BE, 0x6CF3, 0xD3BF, 0x6D8C, 0xD3C0, 0x6C38, 0xD3C1, 0x607F, + 0xD3C2, 0x52C7, 0xD3C3, 0x7528, 0xD3C4, 0x5E7D, 0xD3C5, 0x4F18, 0xD3C6, 0x60A0, 0xD3C7, 0x5FE7, 0xD3C8, 0x5C24, 0xD3C9, 0x7531, + 0xD3CA, 0x90AE, 0xD3CB, 0x94C0, 0xD3CC, 0x72B9, 0xD3CD, 0x6CB9, 0xD3CE, 0x6E38, 0xD3CF, 0x9149, 0xD3D0, 0x6709, 0xD3D1, 0x53CB, + 0xD3D2, 0x53F3, 0xD3D3, 0x4F51, 0xD3D4, 0x91C9, 0xD3D5, 0x8BF1, 0xD3D6, 0x53C8, 0xD3D7, 0x5E7C, 0xD3D8, 0x8FC2, 0xD3D9, 0x6DE4, + 0xD3DA, 0x4E8E, 0xD3DB, 0x76C2, 0xD3DC, 0x6986, 0xD3DD, 0x865E, 0xD3DE, 0x611A, 0xD3DF, 0x8206, 0xD3E0, 0x4F59, 0xD3E1, 0x4FDE, + 0xD3E2, 0x903E, 0xD3E3, 0x9C7C, 0xD3E4, 0x6109, 0xD3E5, 0x6E1D, 0xD3E6, 0x6E14, 0xD3E7, 0x9685, 0xD3E8, 0x4E88, 0xD3E9, 0x5A31, + 0xD3EA, 0x96E8, 0xD3EB, 0x4E0E, 0xD3EC, 0x5C7F, 0xD3ED, 0x79B9, 0xD3EE, 0x5B87, 0xD3EF, 0x8BED, 0xD3F0, 0x7FBD, 0xD3F1, 0x7389, + 0xD3F2, 0x57DF, 0xD3F3, 0x828B, 0xD3F4, 0x90C1, 0xD3F5, 0x5401, 0xD3F6, 0x9047, 0xD3F7, 0x55BB, 0xD3F8, 0x5CEA, 0xD3F9, 0x5FA1, + 0xD3FA, 0x6108, 0xD3FB, 0x6B32, 0xD3FC, 0x72F1, 0xD3FD, 0x80B2, 0xD3FE, 0x8A89, 0xD440, 0x8A1E, 0xD441, 0x8A1F, 0xD442, 0x8A20, + 0xD443, 0x8A21, 0xD444, 0x8A22, 0xD445, 0x8A23, 0xD446, 0x8A24, 0xD447, 0x8A25, 0xD448, 0x8A26, 0xD449, 0x8A27, 0xD44A, 0x8A28, + 0xD44B, 0x8A29, 0xD44C, 0x8A2A, 0xD44D, 0x8A2B, 0xD44E, 0x8A2C, 0xD44F, 0x8A2D, 0xD450, 0x8A2E, 0xD451, 0x8A2F, 0xD452, 0x8A30, + 0xD453, 0x8A31, 0xD454, 0x8A32, 0xD455, 0x8A33, 0xD456, 0x8A34, 0xD457, 0x8A35, 0xD458, 0x8A36, 0xD459, 0x8A37, 0xD45A, 0x8A38, + 0xD45B, 0x8A39, 0xD45C, 0x8A3A, 0xD45D, 0x8A3B, 0xD45E, 0x8A3C, 0xD45F, 0x8A3D, 0xD460, 0x8A3F, 0xD461, 0x8A40, 0xD462, 0x8A41, + 0xD463, 0x8A42, 0xD464, 0x8A43, 0xD465, 0x8A44, 0xD466, 0x8A45, 0xD467, 0x8A46, 0xD468, 0x8A47, 0xD469, 0x8A49, 0xD46A, 0x8A4A, + 0xD46B, 0x8A4B, 0xD46C, 0x8A4C, 0xD46D, 0x8A4D, 0xD46E, 0x8A4E, 0xD46F, 0x8A4F, 0xD470, 0x8A50, 0xD471, 0x8A51, 0xD472, 0x8A52, + 0xD473, 0x8A53, 0xD474, 0x8A54, 0xD475, 0x8A55, 0xD476, 0x8A56, 0xD477, 0x8A57, 0xD478, 0x8A58, 0xD479, 0x8A59, 0xD47A, 0x8A5A, + 0xD47B, 0x8A5B, 0xD47C, 0x8A5C, 0xD47D, 0x8A5D, 0xD47E, 0x8A5E, 0xD480, 0x8A5F, 0xD481, 0x8A60, 0xD482, 0x8A61, 0xD483, 0x8A62, + 0xD484, 0x8A63, 0xD485, 0x8A64, 0xD486, 0x8A65, 0xD487, 0x8A66, 0xD488, 0x8A67, 0xD489, 0x8A68, 0xD48A, 0x8A69, 0xD48B, 0x8A6A, + 0xD48C, 0x8A6B, 0xD48D, 0x8A6C, 0xD48E, 0x8A6D, 0xD48F, 0x8A6E, 0xD490, 0x8A6F, 0xD491, 0x8A70, 0xD492, 0x8A71, 0xD493, 0x8A72, + 0xD494, 0x8A73, 0xD495, 0x8A74, 0xD496, 0x8A75, 0xD497, 0x8A76, 0xD498, 0x8A77, 0xD499, 0x8A78, 0xD49A, 0x8A7A, 0xD49B, 0x8A7B, + 0xD49C, 0x8A7C, 0xD49D, 0x8A7D, 0xD49E, 0x8A7E, 0xD49F, 0x8A7F, 0xD4A0, 0x8A80, 0xD4A1, 0x6D74, 0xD4A2, 0x5BD3, 0xD4A3, 0x88D5, + 0xD4A4, 0x9884, 0xD4A5, 0x8C6B, 0xD4A6, 0x9A6D, 0xD4A7, 0x9E33, 0xD4A8, 0x6E0A, 0xD4A9, 0x51A4, 0xD4AA, 0x5143, 0xD4AB, 0x57A3, + 0xD4AC, 0x8881, 0xD4AD, 0x539F, 0xD4AE, 0x63F4, 0xD4AF, 0x8F95, 0xD4B0, 0x56ED, 0xD4B1, 0x5458, 0xD4B2, 0x5706, 0xD4B3, 0x733F, + 0xD4B4, 0x6E90, 0xD4B5, 0x7F18, 0xD4B6, 0x8FDC, 0xD4B7, 0x82D1, 0xD4B8, 0x613F, 0xD4B9, 0x6028, 0xD4BA, 0x9662, 0xD4BB, 0x66F0, + 0xD4BC, 0x7EA6, 0xD4BD, 0x8D8A, 0xD4BE, 0x8DC3, 0xD4BF, 0x94A5, 0xD4C0, 0x5CB3, 0xD4C1, 0x7CA4, 0xD4C2, 0x6708, 0xD4C3, 0x60A6, + 0xD4C4, 0x9605, 0xD4C5, 0x8018, 0xD4C6, 0x4E91, 0xD4C7, 0x90E7, 0xD4C8, 0x5300, 0xD4C9, 0x9668, 0xD4CA, 0x5141, 0xD4CB, 0x8FD0, + 0xD4CC, 0x8574, 0xD4CD, 0x915D, 0xD4CE, 0x6655, 0xD4CF, 0x97F5, 0xD4D0, 0x5B55, 0xD4D1, 0x531D, 0xD4D2, 0x7838, 0xD4D3, 0x6742, + 0xD4D4, 0x683D, 0xD4D5, 0x54C9, 0xD4D6, 0x707E, 0xD4D7, 0x5BB0, 0xD4D8, 0x8F7D, 0xD4D9, 0x518D, 0xD4DA, 0x5728, 0xD4DB, 0x54B1, + 0xD4DC, 0x6512, 0xD4DD, 0x6682, 0xD4DE, 0x8D5E, 0xD4DF, 0x8D43, 0xD4E0, 0x810F, 0xD4E1, 0x846C, 0xD4E2, 0x906D, 0xD4E3, 0x7CDF, + 0xD4E4, 0x51FF, 0xD4E5, 0x85FB, 0xD4E6, 0x67A3, 0xD4E7, 0x65E9, 0xD4E8, 0x6FA1, 0xD4E9, 0x86A4, 0xD4EA, 0x8E81, 0xD4EB, 0x566A, + 0xD4EC, 0x9020, 0xD4ED, 0x7682, 0xD4EE, 0x7076, 0xD4EF, 0x71E5, 0xD4F0, 0x8D23, 0xD4F1, 0x62E9, 0xD4F2, 0x5219, 0xD4F3, 0x6CFD, + 0xD4F4, 0x8D3C, 0xD4F5, 0x600E, 0xD4F6, 0x589E, 0xD4F7, 0x618E, 0xD4F8, 0x66FE, 0xD4F9, 0x8D60, 0xD4FA, 0x624E, 0xD4FB, 0x55B3, + 0xD4FC, 0x6E23, 0xD4FD, 0x672D, 0xD4FE, 0x8F67, 0xD540, 0x8A81, 0xD541, 0x8A82, 0xD542, 0x8A83, 0xD543, 0x8A84, 0xD544, 0x8A85, + 0xD545, 0x8A86, 0xD546, 0x8A87, 0xD547, 0x8A88, 0xD548, 0x8A8B, 0xD549, 0x8A8C, 0xD54A, 0x8A8D, 0xD54B, 0x8A8E, 0xD54C, 0x8A8F, + 0xD54D, 0x8A90, 0xD54E, 0x8A91, 0xD54F, 0x8A92, 0xD550, 0x8A94, 0xD551, 0x8A95, 0xD552, 0x8A96, 0xD553, 0x8A97, 0xD554, 0x8A98, + 0xD555, 0x8A99, 0xD556, 0x8A9A, 0xD557, 0x8A9B, 0xD558, 0x8A9C, 0xD559, 0x8A9D, 0xD55A, 0x8A9E, 0xD55B, 0x8A9F, 0xD55C, 0x8AA0, + 0xD55D, 0x8AA1, 0xD55E, 0x8AA2, 0xD55F, 0x8AA3, 0xD560, 0x8AA4, 0xD561, 0x8AA5, 0xD562, 0x8AA6, 0xD563, 0x8AA7, 0xD564, 0x8AA8, + 0xD565, 0x8AA9, 0xD566, 0x8AAA, 0xD567, 0x8AAB, 0xD568, 0x8AAC, 0xD569, 0x8AAD, 0xD56A, 0x8AAE, 0xD56B, 0x8AAF, 0xD56C, 0x8AB0, + 0xD56D, 0x8AB1, 0xD56E, 0x8AB2, 0xD56F, 0x8AB3, 0xD570, 0x8AB4, 0xD571, 0x8AB5, 0xD572, 0x8AB6, 0xD573, 0x8AB7, 0xD574, 0x8AB8, + 0xD575, 0x8AB9, 0xD576, 0x8ABA, 0xD577, 0x8ABB, 0xD578, 0x8ABC, 0xD579, 0x8ABD, 0xD57A, 0x8ABE, 0xD57B, 0x8ABF, 0xD57C, 0x8AC0, + 0xD57D, 0x8AC1, 0xD57E, 0x8AC2, 0xD580, 0x8AC3, 0xD581, 0x8AC4, 0xD582, 0x8AC5, 0xD583, 0x8AC6, 0xD584, 0x8AC7, 0xD585, 0x8AC8, + 0xD586, 0x8AC9, 0xD587, 0x8ACA, 0xD588, 0x8ACB, 0xD589, 0x8ACC, 0xD58A, 0x8ACD, 0xD58B, 0x8ACE, 0xD58C, 0x8ACF, 0xD58D, 0x8AD0, + 0xD58E, 0x8AD1, 0xD58F, 0x8AD2, 0xD590, 0x8AD3, 0xD591, 0x8AD4, 0xD592, 0x8AD5, 0xD593, 0x8AD6, 0xD594, 0x8AD7, 0xD595, 0x8AD8, + 0xD596, 0x8AD9, 0xD597, 0x8ADA, 0xD598, 0x8ADB, 0xD599, 0x8ADC, 0xD59A, 0x8ADD, 0xD59B, 0x8ADE, 0xD59C, 0x8ADF, 0xD59D, 0x8AE0, + 0xD59E, 0x8AE1, 0xD59F, 0x8AE2, 0xD5A0, 0x8AE3, 0xD5A1, 0x94E1, 0xD5A2, 0x95F8, 0xD5A3, 0x7728, 0xD5A4, 0x6805, 0xD5A5, 0x69A8, + 0xD5A6, 0x548B, 0xD5A7, 0x4E4D, 0xD5A8, 0x70B8, 0xD5A9, 0x8BC8, 0xD5AA, 0x6458, 0xD5AB, 0x658B, 0xD5AC, 0x5B85, 0xD5AD, 0x7A84, + 0xD5AE, 0x503A, 0xD5AF, 0x5BE8, 0xD5B0, 0x77BB, 0xD5B1, 0x6BE1, 0xD5B2, 0x8A79, 0xD5B3, 0x7C98, 0xD5B4, 0x6CBE, 0xD5B5, 0x76CF, + 0xD5B6, 0x65A9, 0xD5B7, 0x8F97, 0xD5B8, 0x5D2D, 0xD5B9, 0x5C55, 0xD5BA, 0x8638, 0xD5BB, 0x6808, 0xD5BC, 0x5360, 0xD5BD, 0x6218, + 0xD5BE, 0x7AD9, 0xD5BF, 0x6E5B, 0xD5C0, 0x7EFD, 0xD5C1, 0x6A1F, 0xD5C2, 0x7AE0, 0xD5C3, 0x5F70, 0xD5C4, 0x6F33, 0xD5C5, 0x5F20, + 0xD5C6, 0x638C, 0xD5C7, 0x6DA8, 0xD5C8, 0x6756, 0xD5C9, 0x4E08, 0xD5CA, 0x5E10, 0xD5CB, 0x8D26, 0xD5CC, 0x4ED7, 0xD5CD, 0x80C0, + 0xD5CE, 0x7634, 0xD5CF, 0x969C, 0xD5D0, 0x62DB, 0xD5D1, 0x662D, 0xD5D2, 0x627E, 0xD5D3, 0x6CBC, 0xD5D4, 0x8D75, 0xD5D5, 0x7167, + 0xD5D6, 0x7F69, 0xD5D7, 0x5146, 0xD5D8, 0x8087, 0xD5D9, 0x53EC, 0xD5DA, 0x906E, 0xD5DB, 0x6298, 0xD5DC, 0x54F2, 0xD5DD, 0x86F0, + 0xD5DE, 0x8F99, 0xD5DF, 0x8005, 0xD5E0, 0x9517, 0xD5E1, 0x8517, 0xD5E2, 0x8FD9, 0xD5E3, 0x6D59, 0xD5E4, 0x73CD, 0xD5E5, 0x659F, + 0xD5E6, 0x771F, 0xD5E7, 0x7504, 0xD5E8, 0x7827, 0xD5E9, 0x81FB, 0xD5EA, 0x8D1E, 0xD5EB, 0x9488, 0xD5EC, 0x4FA6, 0xD5ED, 0x6795, + 0xD5EE, 0x75B9, 0xD5EF, 0x8BCA, 0xD5F0, 0x9707, 0xD5F1, 0x632F, 0xD5F2, 0x9547, 0xD5F3, 0x9635, 0xD5F4, 0x84B8, 0xD5F5, 0x6323, + 0xD5F6, 0x7741, 0xD5F7, 0x5F81, 0xD5F8, 0x72F0, 0xD5F9, 0x4E89, 0xD5FA, 0x6014, 0xD5FB, 0x6574, 0xD5FC, 0x62EF, 0xD5FD, 0x6B63, + 0xD5FE, 0x653F, 0xD640, 0x8AE4, 0xD641, 0x8AE5, 0xD642, 0x8AE6, 0xD643, 0x8AE7, 0xD644, 0x8AE8, 0xD645, 0x8AE9, 0xD646, 0x8AEA, + 0xD647, 0x8AEB, 0xD648, 0x8AEC, 0xD649, 0x8AED, 0xD64A, 0x8AEE, 0xD64B, 0x8AEF, 0xD64C, 0x8AF0, 0xD64D, 0x8AF1, 0xD64E, 0x8AF2, + 0xD64F, 0x8AF3, 0xD650, 0x8AF4, 0xD651, 0x8AF5, 0xD652, 0x8AF6, 0xD653, 0x8AF7, 0xD654, 0x8AF8, 0xD655, 0x8AF9, 0xD656, 0x8AFA, + 0xD657, 0x8AFB, 0xD658, 0x8AFC, 0xD659, 0x8AFD, 0xD65A, 0x8AFE, 0xD65B, 0x8AFF, 0xD65C, 0x8B00, 0xD65D, 0x8B01, 0xD65E, 0x8B02, + 0xD65F, 0x8B03, 0xD660, 0x8B04, 0xD661, 0x8B05, 0xD662, 0x8B06, 0xD663, 0x8B08, 0xD664, 0x8B09, 0xD665, 0x8B0A, 0xD666, 0x8B0B, + 0xD667, 0x8B0C, 0xD668, 0x8B0D, 0xD669, 0x8B0E, 0xD66A, 0x8B0F, 0xD66B, 0x8B10, 0xD66C, 0x8B11, 0xD66D, 0x8B12, 0xD66E, 0x8B13, + 0xD66F, 0x8B14, 0xD670, 0x8B15, 0xD671, 0x8B16, 0xD672, 0x8B17, 0xD673, 0x8B18, 0xD674, 0x8B19, 0xD675, 0x8B1A, 0xD676, 0x8B1B, + 0xD677, 0x8B1C, 0xD678, 0x8B1D, 0xD679, 0x8B1E, 0xD67A, 0x8B1F, 0xD67B, 0x8B20, 0xD67C, 0x8B21, 0xD67D, 0x8B22, 0xD67E, 0x8B23, + 0xD680, 0x8B24, 0xD681, 0x8B25, 0xD682, 0x8B27, 0xD683, 0x8B28, 0xD684, 0x8B29, 0xD685, 0x8B2A, 0xD686, 0x8B2B, 0xD687, 0x8B2C, + 0xD688, 0x8B2D, 0xD689, 0x8B2E, 0xD68A, 0x8B2F, 0xD68B, 0x8B30, 0xD68C, 0x8B31, 0xD68D, 0x8B32, 0xD68E, 0x8B33, 0xD68F, 0x8B34, + 0xD690, 0x8B35, 0xD691, 0x8B36, 0xD692, 0x8B37, 0xD693, 0x8B38, 0xD694, 0x8B39, 0xD695, 0x8B3A, 0xD696, 0x8B3B, 0xD697, 0x8B3C, + 0xD698, 0x8B3D, 0xD699, 0x8B3E, 0xD69A, 0x8B3F, 0xD69B, 0x8B40, 0xD69C, 0x8B41, 0xD69D, 0x8B42, 0xD69E, 0x8B43, 0xD69F, 0x8B44, + 0xD6A0, 0x8B45, 0xD6A1, 0x5E27, 0xD6A2, 0x75C7, 0xD6A3, 0x90D1, 0xD6A4, 0x8BC1, 0xD6A5, 0x829D, 0xD6A6, 0x679D, 0xD6A7, 0x652F, + 0xD6A8, 0x5431, 0xD6A9, 0x8718, 0xD6AA, 0x77E5, 0xD6AB, 0x80A2, 0xD6AC, 0x8102, 0xD6AD, 0x6C41, 0xD6AE, 0x4E4B, 0xD6AF, 0x7EC7, + 0xD6B0, 0x804C, 0xD6B1, 0x76F4, 0xD6B2, 0x690D, 0xD6B3, 0x6B96, 0xD6B4, 0x6267, 0xD6B5, 0x503C, 0xD6B6, 0x4F84, 0xD6B7, 0x5740, + 0xD6B8, 0x6307, 0xD6B9, 0x6B62, 0xD6BA, 0x8DBE, 0xD6BB, 0x53EA, 0xD6BC, 0x65E8, 0xD6BD, 0x7EB8, 0xD6BE, 0x5FD7, 0xD6BF, 0x631A, + 0xD6C0, 0x63B7, 0xD6C1, 0x81F3, 0xD6C2, 0x81F4, 0xD6C3, 0x7F6E, 0xD6C4, 0x5E1C, 0xD6C5, 0x5CD9, 0xD6C6, 0x5236, 0xD6C7, 0x667A, + 0xD6C8, 0x79E9, 0xD6C9, 0x7A1A, 0xD6CA, 0x8D28, 0xD6CB, 0x7099, 0xD6CC, 0x75D4, 0xD6CD, 0x6EDE, 0xD6CE, 0x6CBB, 0xD6CF, 0x7A92, + 0xD6D0, 0x4E2D, 0xD6D1, 0x76C5, 0xD6D2, 0x5FE0, 0xD6D3, 0x949F, 0xD6D4, 0x8877, 0xD6D5, 0x7EC8, 0xD6D6, 0x79CD, 0xD6D7, 0x80BF, + 0xD6D8, 0x91CD, 0xD6D9, 0x4EF2, 0xD6DA, 0x4F17, 0xD6DB, 0x821F, 0xD6DC, 0x5468, 0xD6DD, 0x5DDE, 0xD6DE, 0x6D32, 0xD6DF, 0x8BCC, + 0xD6E0, 0x7CA5, 0xD6E1, 0x8F74, 0xD6E2, 0x8098, 0xD6E3, 0x5E1A, 0xD6E4, 0x5492, 0xD6E5, 0x76B1, 0xD6E6, 0x5B99, 0xD6E7, 0x663C, + 0xD6E8, 0x9AA4, 0xD6E9, 0x73E0, 0xD6EA, 0x682A, 0xD6EB, 0x86DB, 0xD6EC, 0x6731, 0xD6ED, 0x732A, 0xD6EE, 0x8BF8, 0xD6EF, 0x8BDB, + 0xD6F0, 0x9010, 0xD6F1, 0x7AF9, 0xD6F2, 0x70DB, 0xD6F3, 0x716E, 0xD6F4, 0x62C4, 0xD6F5, 0x77A9, 0xD6F6, 0x5631, 0xD6F7, 0x4E3B, + 0xD6F8, 0x8457, 0xD6F9, 0x67F1, 0xD6FA, 0x52A9, 0xD6FB, 0x86C0, 0xD6FC, 0x8D2E, 0xD6FD, 0x94F8, 0xD6FE, 0x7B51, 0xD740, 0x8B46, + 0xD741, 0x8B47, 0xD742, 0x8B48, 0xD743, 0x8B49, 0xD744, 0x8B4A, 0xD745, 0x8B4B, 0xD746, 0x8B4C, 0xD747, 0x8B4D, 0xD748, 0x8B4E, + 0xD749, 0x8B4F, 0xD74A, 0x8B50, 0xD74B, 0x8B51, 0xD74C, 0x8B52, 0xD74D, 0x8B53, 0xD74E, 0x8B54, 0xD74F, 0x8B55, 0xD750, 0x8B56, + 0xD751, 0x8B57, 0xD752, 0x8B58, 0xD753, 0x8B59, 0xD754, 0x8B5A, 0xD755, 0x8B5B, 0xD756, 0x8B5C, 0xD757, 0x8B5D, 0xD758, 0x8B5E, + 0xD759, 0x8B5F, 0xD75A, 0x8B60, 0xD75B, 0x8B61, 0xD75C, 0x8B62, 0xD75D, 0x8B63, 0xD75E, 0x8B64, 0xD75F, 0x8B65, 0xD760, 0x8B67, + 0xD761, 0x8B68, 0xD762, 0x8B69, 0xD763, 0x8B6A, 0xD764, 0x8B6B, 0xD765, 0x8B6D, 0xD766, 0x8B6E, 0xD767, 0x8B6F, 0xD768, 0x8B70, + 0xD769, 0x8B71, 0xD76A, 0x8B72, 0xD76B, 0x8B73, 0xD76C, 0x8B74, 0xD76D, 0x8B75, 0xD76E, 0x8B76, 0xD76F, 0x8B77, 0xD770, 0x8B78, + 0xD771, 0x8B79, 0xD772, 0x8B7A, 0xD773, 0x8B7B, 0xD774, 0x8B7C, 0xD775, 0x8B7D, 0xD776, 0x8B7E, 0xD777, 0x8B7F, 0xD778, 0x8B80, + 0xD779, 0x8B81, 0xD77A, 0x8B82, 0xD77B, 0x8B83, 0xD77C, 0x8B84, 0xD77D, 0x8B85, 0xD77E, 0x8B86, 0xD780, 0x8B87, 0xD781, 0x8B88, + 0xD782, 0x8B89, 0xD783, 0x8B8A, 0xD784, 0x8B8B, 0xD785, 0x8B8C, 0xD786, 0x8B8D, 0xD787, 0x8B8E, 0xD788, 0x8B8F, 0xD789, 0x8B90, + 0xD78A, 0x8B91, 0xD78B, 0x8B92, 0xD78C, 0x8B93, 0xD78D, 0x8B94, 0xD78E, 0x8B95, 0xD78F, 0x8B96, 0xD790, 0x8B97, 0xD791, 0x8B98, + 0xD792, 0x8B99, 0xD793, 0x8B9A, 0xD794, 0x8B9B, 0xD795, 0x8B9C, 0xD796, 0x8B9D, 0xD797, 0x8B9E, 0xD798, 0x8B9F, 0xD799, 0x8BAC, + 0xD79A, 0x8BB1, 0xD79B, 0x8BBB, 0xD79C, 0x8BC7, 0xD79D, 0x8BD0, 0xD79E, 0x8BEA, 0xD79F, 0x8C09, 0xD7A0, 0x8C1E, 0xD7A1, 0x4F4F, + 0xD7A2, 0x6CE8, 0xD7A3, 0x795D, 0xD7A4, 0x9A7B, 0xD7A5, 0x6293, 0xD7A6, 0x722A, 0xD7A7, 0x62FD, 0xD7A8, 0x4E13, 0xD7A9, 0x7816, + 0xD7AA, 0x8F6C, 0xD7AB, 0x64B0, 0xD7AC, 0x8D5A, 0xD7AD, 0x7BC6, 0xD7AE, 0x6869, 0xD7AF, 0x5E84, 0xD7B0, 0x88C5, 0xD7B1, 0x5986, + 0xD7B2, 0x649E, 0xD7B3, 0x58EE, 0xD7B4, 0x72B6, 0xD7B5, 0x690E, 0xD7B6, 0x9525, 0xD7B7, 0x8FFD, 0xD7B8, 0x8D58, 0xD7B9, 0x5760, + 0xD7BA, 0x7F00, 0xD7BB, 0x8C06, 0xD7BC, 0x51C6, 0xD7BD, 0x6349, 0xD7BE, 0x62D9, 0xD7BF, 0x5353, 0xD7C0, 0x684C, 0xD7C1, 0x7422, + 0xD7C2, 0x8301, 0xD7C3, 0x914C, 0xD7C4, 0x5544, 0xD7C5, 0x7740, 0xD7C6, 0x707C, 0xD7C7, 0x6D4A, 0xD7C8, 0x5179, 0xD7C9, 0x54A8, + 0xD7CA, 0x8D44, 0xD7CB, 0x59FF, 0xD7CC, 0x6ECB, 0xD7CD, 0x6DC4, 0xD7CE, 0x5B5C, 0xD7CF, 0x7D2B, 0xD7D0, 0x4ED4, 0xD7D1, 0x7C7D, + 0xD7D2, 0x6ED3, 0xD7D3, 0x5B50, 0xD7D4, 0x81EA, 0xD7D5, 0x6E0D, 0xD7D6, 0x5B57, 0xD7D7, 0x9B03, 0xD7D8, 0x68D5, 0xD7D9, 0x8E2A, + 0xD7DA, 0x5B97, 0xD7DB, 0x7EFC, 0xD7DC, 0x603B, 0xD7DD, 0x7EB5, 0xD7DE, 0x90B9, 0xD7DF, 0x8D70, 0xD7E0, 0x594F, 0xD7E1, 0x63CD, + 0xD7E2, 0x79DF, 0xD7E3, 0x8DB3, 0xD7E4, 0x5352, 0xD7E5, 0x65CF, 0xD7E6, 0x7956, 0xD7E7, 0x8BC5, 0xD7E8, 0x963B, 0xD7E9, 0x7EC4, + 0xD7EA, 0x94BB, 0xD7EB, 0x7E82, 0xD7EC, 0x5634, 0xD7ED, 0x9189, 0xD7EE, 0x6700, 0xD7EF, 0x7F6A, 0xD7F0, 0x5C0A, 0xD7F1, 0x9075, + 0xD7F2, 0x6628, 0xD7F3, 0x5DE6, 0xD7F4, 0x4F50, 0xD7F5, 0x67DE, 0xD7F6, 0x505A, 0xD7F7, 0x4F5C, 0xD7F8, 0x5750, 0xD7F9, 0x5EA7, + 0xD840, 0x8C38, 0xD841, 0x8C39, 0xD842, 0x8C3A, 0xD843, 0x8C3B, 0xD844, 0x8C3C, 0xD845, 0x8C3D, 0xD846, 0x8C3E, 0xD847, 0x8C3F, + 0xD848, 0x8C40, 0xD849, 0x8C42, 0xD84A, 0x8C43, 0xD84B, 0x8C44, 0xD84C, 0x8C45, 0xD84D, 0x8C48, 0xD84E, 0x8C4A, 0xD84F, 0x8C4B, + 0xD850, 0x8C4D, 0xD851, 0x8C4E, 0xD852, 0x8C4F, 0xD853, 0x8C50, 0xD854, 0x8C51, 0xD855, 0x8C52, 0xD856, 0x8C53, 0xD857, 0x8C54, + 0xD858, 0x8C56, 0xD859, 0x8C57, 0xD85A, 0x8C58, 0xD85B, 0x8C59, 0xD85C, 0x8C5B, 0xD85D, 0x8C5C, 0xD85E, 0x8C5D, 0xD85F, 0x8C5E, + 0xD860, 0x8C5F, 0xD861, 0x8C60, 0xD862, 0x8C63, 0xD863, 0x8C64, 0xD864, 0x8C65, 0xD865, 0x8C66, 0xD866, 0x8C67, 0xD867, 0x8C68, + 0xD868, 0x8C69, 0xD869, 0x8C6C, 0xD86A, 0x8C6D, 0xD86B, 0x8C6E, 0xD86C, 0x8C6F, 0xD86D, 0x8C70, 0xD86E, 0x8C71, 0xD86F, 0x8C72, + 0xD870, 0x8C74, 0xD871, 0x8C75, 0xD872, 0x8C76, 0xD873, 0x8C77, 0xD874, 0x8C7B, 0xD875, 0x8C7C, 0xD876, 0x8C7D, 0xD877, 0x8C7E, + 0xD878, 0x8C7F, 0xD879, 0x8C80, 0xD87A, 0x8C81, 0xD87B, 0x8C83, 0xD87C, 0x8C84, 0xD87D, 0x8C86, 0xD87E, 0x8C87, 0xD880, 0x8C88, + 0xD881, 0x8C8B, 0xD882, 0x8C8D, 0xD883, 0x8C8E, 0xD884, 0x8C8F, 0xD885, 0x8C90, 0xD886, 0x8C91, 0xD887, 0x8C92, 0xD888, 0x8C93, + 0xD889, 0x8C95, 0xD88A, 0x8C96, 0xD88B, 0x8C97, 0xD88C, 0x8C99, 0xD88D, 0x8C9A, 0xD88E, 0x8C9B, 0xD88F, 0x8C9C, 0xD890, 0x8C9D, + 0xD891, 0x8C9E, 0xD892, 0x8C9F, 0xD893, 0x8CA0, 0xD894, 0x8CA1, 0xD895, 0x8CA2, 0xD896, 0x8CA3, 0xD897, 0x8CA4, 0xD898, 0x8CA5, + 0xD899, 0x8CA6, 0xD89A, 0x8CA7, 0xD89B, 0x8CA8, 0xD89C, 0x8CA9, 0xD89D, 0x8CAA, 0xD89E, 0x8CAB, 0xD89F, 0x8CAC, 0xD8A0, 0x8CAD, + 0xD8A1, 0x4E8D, 0xD8A2, 0x4E0C, 0xD8A3, 0x5140, 0xD8A4, 0x4E10, 0xD8A5, 0x5EFF, 0xD8A6, 0x5345, 0xD8A7, 0x4E15, 0xD8A8, 0x4E98, + 0xD8A9, 0x4E1E, 0xD8AA, 0x9B32, 0xD8AB, 0x5B6C, 0xD8AC, 0x5669, 0xD8AD, 0x4E28, 0xD8AE, 0x79BA, 0xD8AF, 0x4E3F, 0xD8B0, 0x5315, + 0xD8B1, 0x4E47, 0xD8B2, 0x592D, 0xD8B3, 0x723B, 0xD8B4, 0x536E, 0xD8B5, 0x6C10, 0xD8B6, 0x56DF, 0xD8B7, 0x80E4, 0xD8B8, 0x9997, + 0xD8B9, 0x6BD3, 0xD8BA, 0x777E, 0xD8BB, 0x9F17, 0xD8BC, 0x4E36, 0xD8BD, 0x4E9F, 0xD8BE, 0x9F10, 0xD8BF, 0x4E5C, 0xD8C0, 0x4E69, + 0xD8C1, 0x4E93, 0xD8C2, 0x8288, 0xD8C3, 0x5B5B, 0xD8C4, 0x556C, 0xD8C5, 0x560F, 0xD8C6, 0x4EC4, 0xD8C7, 0x538D, 0xD8C8, 0x539D, + 0xD8C9, 0x53A3, 0xD8CA, 0x53A5, 0xD8CB, 0x53AE, 0xD8CC, 0x9765, 0xD8CD, 0x8D5D, 0xD8CE, 0x531A, 0xD8CF, 0x53F5, 0xD8D0, 0x5326, + 0xD8D1, 0x532E, 0xD8D2, 0x533E, 0xD8D3, 0x8D5C, 0xD8D4, 0x5366, 0xD8D5, 0x5363, 0xD8D6, 0x5202, 0xD8D7, 0x5208, 0xD8D8, 0x520E, + 0xD8D9, 0x522D, 0xD8DA, 0x5233, 0xD8DB, 0x523F, 0xD8DC, 0x5240, 0xD8DD, 0x524C, 0xD8DE, 0x525E, 0xD8DF, 0x5261, 0xD8E0, 0x525C, + 0xD8E1, 0x84AF, 0xD8E2, 0x527D, 0xD8E3, 0x5282, 0xD8E4, 0x5281, 0xD8E5, 0x5290, 0xD8E6, 0x5293, 0xD8E7, 0x5182, 0xD8E8, 0x7F54, + 0xD8E9, 0x4EBB, 0xD8EA, 0x4EC3, 0xD8EB, 0x4EC9, 0xD8EC, 0x4EC2, 0xD8ED, 0x4EE8, 0xD8EE, 0x4EE1, 0xD8EF, 0x4EEB, 0xD8F0, 0x4EDE, + 0xD8F1, 0x4F1B, 0xD8F2, 0x4EF3, 0xD8F3, 0x4F22, 0xD8F4, 0x4F64, 0xD8F5, 0x4EF5, 0xD8F6, 0x4F25, 0xD8F7, 0x4F27, 0xD8F8, 0x4F09, + 0xD8F9, 0x4F2B, 0xD8FA, 0x4F5E, 0xD8FB, 0x4F67, 0xD8FC, 0x6538, 0xD8FD, 0x4F5A, 0xD8FE, 0x4F5D, 0xD940, 0x8CAE, 0xD941, 0x8CAF, + 0xD942, 0x8CB0, 0xD943, 0x8CB1, 0xD944, 0x8CB2, 0xD945, 0x8CB3, 0xD946, 0x8CB4, 0xD947, 0x8CB5, 0xD948, 0x8CB6, 0xD949, 0x8CB7, + 0xD94A, 0x8CB8, 0xD94B, 0x8CB9, 0xD94C, 0x8CBA, 0xD94D, 0x8CBB, 0xD94E, 0x8CBC, 0xD94F, 0x8CBD, 0xD950, 0x8CBE, 0xD951, 0x8CBF, + 0xD952, 0x8CC0, 0xD953, 0x8CC1, 0xD954, 0x8CC2, 0xD955, 0x8CC3, 0xD956, 0x8CC4, 0xD957, 0x8CC5, 0xD958, 0x8CC6, 0xD959, 0x8CC7, + 0xD95A, 0x8CC8, 0xD95B, 0x8CC9, 0xD95C, 0x8CCA, 0xD95D, 0x8CCB, 0xD95E, 0x8CCC, 0xD95F, 0x8CCD, 0xD960, 0x8CCE, 0xD961, 0x8CCF, + 0xD962, 0x8CD0, 0xD963, 0x8CD1, 0xD964, 0x8CD2, 0xD965, 0x8CD3, 0xD966, 0x8CD4, 0xD967, 0x8CD5, 0xD968, 0x8CD6, 0xD969, 0x8CD7, + 0xD96A, 0x8CD8, 0xD96B, 0x8CD9, 0xD96C, 0x8CDA, 0xD96D, 0x8CDB, 0xD96E, 0x8CDC, 0xD96F, 0x8CDD, 0xD970, 0x8CDE, 0xD971, 0x8CDF, + 0xD972, 0x8CE0, 0xD973, 0x8CE1, 0xD974, 0x8CE2, 0xD975, 0x8CE3, 0xD976, 0x8CE4, 0xD977, 0x8CE5, 0xD978, 0x8CE6, 0xD979, 0x8CE7, + 0xD97A, 0x8CE8, 0xD97B, 0x8CE9, 0xD97C, 0x8CEA, 0xD97D, 0x8CEB, 0xD97E, 0x8CEC, 0xD980, 0x8CED, 0xD981, 0x8CEE, 0xD982, 0x8CEF, + 0xD983, 0x8CF0, 0xD984, 0x8CF1, 0xD985, 0x8CF2, 0xD986, 0x8CF3, 0xD987, 0x8CF4, 0xD988, 0x8CF5, 0xD989, 0x8CF6, 0xD98A, 0x8CF7, + 0xD98B, 0x8CF8, 0xD98C, 0x8CF9, 0xD98D, 0x8CFA, 0xD98E, 0x8CFB, 0xD98F, 0x8CFC, 0xD990, 0x8CFD, 0xD991, 0x8CFE, 0xD992, 0x8CFF, + 0xD993, 0x8D00, 0xD994, 0x8D01, 0xD995, 0x8D02, 0xD996, 0x8D03, 0xD997, 0x8D04, 0xD998, 0x8D05, 0xD999, 0x8D06, 0xD99A, 0x8D07, + 0xD99B, 0x8D08, 0xD99C, 0x8D09, 0xD99D, 0x8D0A, 0xD99E, 0x8D0B, 0xD99F, 0x8D0C, 0xD9A0, 0x8D0D, 0xD9A1, 0x4F5F, 0xD9A2, 0x4F57, + 0xD9A3, 0x4F32, 0xD9A4, 0x4F3D, 0xD9A5, 0x4F76, 0xD9A6, 0x4F74, 0xD9A7, 0x4F91, 0xD9A8, 0x4F89, 0xD9A9, 0x4F83, 0xD9AA, 0x4F8F, + 0xD9AB, 0x4F7E, 0xD9AC, 0x4F7B, 0xD9AD, 0x4FAA, 0xD9AE, 0x4F7C, 0xD9AF, 0x4FAC, 0xD9B0, 0x4F94, 0xD9B1, 0x4FE6, 0xD9B2, 0x4FE8, + 0xD9B3, 0x4FEA, 0xD9B4, 0x4FC5, 0xD9B5, 0x4FDA, 0xD9B6, 0x4FE3, 0xD9B7, 0x4FDC, 0xD9B8, 0x4FD1, 0xD9B9, 0x4FDF, 0xD9BA, 0x4FF8, + 0xD9BB, 0x5029, 0xD9BC, 0x504C, 0xD9BD, 0x4FF3, 0xD9BE, 0x502C, 0xD9BF, 0x500F, 0xD9C0, 0x502E, 0xD9C1, 0x502D, 0xD9C2, 0x4FFE, + 0xD9C3, 0x501C, 0xD9C4, 0x500C, 0xD9C5, 0x5025, 0xD9C6, 0x5028, 0xD9C7, 0x507E, 0xD9C8, 0x5043, 0xD9C9, 0x5055, 0xD9CA, 0x5048, + 0xD9CB, 0x504E, 0xD9CC, 0x506C, 0xD9CD, 0x507B, 0xD9CE, 0x50A5, 0xD9CF, 0x50A7, 0xD9D0, 0x50A9, 0xD9D1, 0x50BA, 0xD9D2, 0x50D6, + 0xD9D3, 0x5106, 0xD9D4, 0x50ED, 0xD9D5, 0x50EC, 0xD9D6, 0x50E6, 0xD9D7, 0x50EE, 0xD9D8, 0x5107, 0xD9D9, 0x510B, 0xD9DA, 0x4EDD, + 0xD9DB, 0x6C3D, 0xD9DC, 0x4F58, 0xD9DD, 0x4F65, 0xD9DE, 0x4FCE, 0xD9DF, 0x9FA0, 0xD9E0, 0x6C46, 0xD9E1, 0x7C74, 0xD9E2, 0x516E, + 0xD9E3, 0x5DFD, 0xD9E4, 0x9EC9, 0xD9E5, 0x9998, 0xD9E6, 0x5181, 0xD9E7, 0x5914, 0xD9E8, 0x52F9, 0xD9E9, 0x530D, 0xD9EA, 0x8A07, + 0xD9EB, 0x5310, 0xD9EC, 0x51EB, 0xD9ED, 0x5919, 0xD9EE, 0x5155, 0xD9EF, 0x4EA0, 0xD9F0, 0x5156, 0xD9F1, 0x4EB3, 0xD9F2, 0x886E, + 0xD9F3, 0x88A4, 0xD9F4, 0x4EB5, 0xD9F5, 0x8114, 0xD9F6, 0x88D2, 0xD9F7, 0x7980, 0xD9F8, 0x5B34, 0xD9F9, 0x8803, 0xD9FA, 0x7FB8, + 0xD9FB, 0x51AB, 0xD9FC, 0x51B1, 0xD9FD, 0x51BD, 0xD9FE, 0x51BC, 0xDA40, 0x8D0E, 0xDA41, 0x8D0F, 0xDA42, 0x8D10, 0xDA43, 0x8D11, + 0xDA44, 0x8D12, 0xDA45, 0x8D13, 0xDA46, 0x8D14, 0xDA47, 0x8D15, 0xDA48, 0x8D16, 0xDA49, 0x8D17, 0xDA4A, 0x8D18, 0xDA4B, 0x8D19, + 0xDA4C, 0x8D1A, 0xDA4D, 0x8D1B, 0xDA4E, 0x8D1C, 0xDA4F, 0x8D20, 0xDA50, 0x8D51, 0xDA51, 0x8D52, 0xDA52, 0x8D57, 0xDA53, 0x8D5F, + 0xDA54, 0x8D65, 0xDA55, 0x8D68, 0xDA56, 0x8D69, 0xDA57, 0x8D6A, 0xDA58, 0x8D6C, 0xDA59, 0x8D6E, 0xDA5A, 0x8D6F, 0xDA5B, 0x8D71, + 0xDA5C, 0x8D72, 0xDA5D, 0x8D78, 0xDA5E, 0x8D79, 0xDA5F, 0x8D7A, 0xDA60, 0x8D7B, 0xDA61, 0x8D7C, 0xDA62, 0x8D7D, 0xDA63, 0x8D7E, + 0xDA64, 0x8D7F, 0xDA65, 0x8D80, 0xDA66, 0x8D82, 0xDA67, 0x8D83, 0xDA68, 0x8D86, 0xDA69, 0x8D87, 0xDA6A, 0x8D88, 0xDA6B, 0x8D89, + 0xDA6C, 0x8D8C, 0xDA6D, 0x8D8D, 0xDA6E, 0x8D8E, 0xDA6F, 0x8D8F, 0xDA70, 0x8D90, 0xDA71, 0x8D92, 0xDA72, 0x8D93, 0xDA73, 0x8D95, + 0xDA74, 0x8D96, 0xDA75, 0x8D97, 0xDA76, 0x8D98, 0xDA77, 0x8D99, 0xDA78, 0x8D9A, 0xDA79, 0x8D9B, 0xDA7A, 0x8D9C, 0xDA7B, 0x8D9D, + 0xDA7C, 0x8D9E, 0xDA7D, 0x8DA0, 0xDA7E, 0x8DA1, 0xDA80, 0x8DA2, 0xDA81, 0x8DA4, 0xDA82, 0x8DA5, 0xDA83, 0x8DA6, 0xDA84, 0x8DA7, + 0xDA85, 0x8DA8, 0xDA86, 0x8DA9, 0xDA87, 0x8DAA, 0xDA88, 0x8DAB, 0xDA89, 0x8DAC, 0xDA8A, 0x8DAD, 0xDA8B, 0x8DAE, 0xDA8C, 0x8DAF, + 0xDA8D, 0x8DB0, 0xDA8E, 0x8DB2, 0xDA8F, 0x8DB6, 0xDA90, 0x8DB7, 0xDA91, 0x8DB9, 0xDA92, 0x8DBB, 0xDA93, 0x8DBD, 0xDA94, 0x8DC0, + 0xDA95, 0x8DC1, 0xDA96, 0x8DC2, 0xDA97, 0x8DC5, 0xDA98, 0x8DC7, 0xDA99, 0x8DC8, 0xDA9A, 0x8DC9, 0xDA9B, 0x8DCA, 0xDA9C, 0x8DCD, + 0xDA9D, 0x8DD0, 0xDA9E, 0x8DD2, 0xDA9F, 0x8DD3, 0xDAA0, 0x8DD4, 0xDAA1, 0x51C7, 0xDAA2, 0x5196, 0xDAA3, 0x51A2, 0xDAA4, 0x51A5, + 0xDAA5, 0x8BA0, 0xDAA6, 0x8BA6, 0xDAA7, 0x8BA7, 0xDAA8, 0x8BAA, 0xDAA9, 0x8BB4, 0xDAAA, 0x8BB5, 0xDAAB, 0x8BB7, 0xDAAC, 0x8BC2, + 0xDAAD, 0x8BC3, 0xDAAE, 0x8BCB, 0xDAAF, 0x8BCF, 0xDAB0, 0x8BCE, 0xDAB1, 0x8BD2, 0xDAB2, 0x8BD3, 0xDAB3, 0x8BD4, 0xDAB4, 0x8BD6, + 0xDAB5, 0x8BD8, 0xDAB6, 0x8BD9, 0xDAB7, 0x8BDC, 0xDAB8, 0x8BDF, 0xDAB9, 0x8BE0, 0xDABA, 0x8BE4, 0xDABB, 0x8BE8, 0xDABC, 0x8BE9, + 0xDABD, 0x8BEE, 0xDABE, 0x8BF0, 0xDABF, 0x8BF3, 0xDAC0, 0x8BF6, 0xDAC1, 0x8BF9, 0xDAC2, 0x8BFC, 0xDAC3, 0x8BFF, 0xDAC4, 0x8C00, + 0xDAC5, 0x8C02, 0xDAC6, 0x8C04, 0xDAC7, 0x8C07, 0xDAC8, 0x8C0C, 0xDAC9, 0x8C0F, 0xDACA, 0x8C11, 0xDACB, 0x8C12, 0xDACC, 0x8C14, + 0xDACD, 0x8C15, 0xDACE, 0x8C16, 0xDACF, 0x8C19, 0xDAD0, 0x8C1B, 0xDAD1, 0x8C18, 0xDAD2, 0x8C1D, 0xDAD3, 0x8C1F, 0xDAD4, 0x8C20, + 0xDAD5, 0x8C21, 0xDAD6, 0x8C25, 0xDAD7, 0x8C27, 0xDAD8, 0x8C2A, 0xDAD9, 0x8C2B, 0xDADA, 0x8C2E, 0xDADB, 0x8C2F, 0xDADC, 0x8C32, + 0xDADD, 0x8C33, 0xDADE, 0x8C35, 0xDADF, 0x8C36, 0xDAE0, 0x5369, 0xDAE1, 0x537A, 0xDAE2, 0x961D, 0xDAE3, 0x9622, 0xDAE4, 0x9621, + 0xDAE5, 0x9631, 0xDAE6, 0x962A, 0xDAE7, 0x963D, 0xDAE8, 0x963C, 0xDAE9, 0x9642, 0xDAEA, 0x9649, 0xDAEB, 0x9654, 0xDAEC, 0x965F, + 0xDAED, 0x9667, 0xDAEE, 0x966C, 0xDAEF, 0x9672, 0xDAF0, 0x9674, 0xDAF1, 0x9688, 0xDAF2, 0x968D, 0xDAF3, 0x9697, 0xDAF4, 0x96B0, + 0xDAF5, 0x9097, 0xDAF6, 0x909B, 0xDAF7, 0x909D, 0xDAF8, 0x9099, 0xDAF9, 0x90AC, 0xDAFA, 0x90A1, 0xDAFB, 0x90B4, 0xDAFC, 0x90B3, + 0xDAFD, 0x90B6, 0xDAFE, 0x90BA, 0xDB40, 0x8DD5, 0xDB41, 0x8DD8, 0xDB42, 0x8DD9, 0xDB43, 0x8DDC, 0xDB44, 0x8DE0, 0xDB45, 0x8DE1, + 0xDB46, 0x8DE2, 0xDB47, 0x8DE5, 0xDB48, 0x8DE6, 0xDB49, 0x8DE7, 0xDB4A, 0x8DE9, 0xDB4B, 0x8DED, 0xDB4C, 0x8DEE, 0xDB4D, 0x8DF0, + 0xDB4E, 0x8DF1, 0xDB4F, 0x8DF2, 0xDB50, 0x8DF4, 0xDB51, 0x8DF6, 0xDB52, 0x8DFC, 0xDB53, 0x8DFE, 0xDB54, 0x8DFF, 0xDB55, 0x8E00, + 0xDB56, 0x8E01, 0xDB57, 0x8E02, 0xDB58, 0x8E03, 0xDB59, 0x8E04, 0xDB5A, 0x8E06, 0xDB5B, 0x8E07, 0xDB5C, 0x8E08, 0xDB5D, 0x8E0B, + 0xDB5E, 0x8E0D, 0xDB5F, 0x8E0E, 0xDB60, 0x8E10, 0xDB61, 0x8E11, 0xDB62, 0x8E12, 0xDB63, 0x8E13, 0xDB64, 0x8E15, 0xDB65, 0x8E16, + 0xDB66, 0x8E17, 0xDB67, 0x8E18, 0xDB68, 0x8E19, 0xDB69, 0x8E1A, 0xDB6A, 0x8E1B, 0xDB6B, 0x8E1C, 0xDB6C, 0x8E20, 0xDB6D, 0x8E21, + 0xDB6E, 0x8E24, 0xDB6F, 0x8E25, 0xDB70, 0x8E26, 0xDB71, 0x8E27, 0xDB72, 0x8E28, 0xDB73, 0x8E2B, 0xDB74, 0x8E2D, 0xDB75, 0x8E30, + 0xDB76, 0x8E32, 0xDB77, 0x8E33, 0xDB78, 0x8E34, 0xDB79, 0x8E36, 0xDB7A, 0x8E37, 0xDB7B, 0x8E38, 0xDB7C, 0x8E3B, 0xDB7D, 0x8E3C, + 0xDB7E, 0x8E3E, 0xDB80, 0x8E3F, 0xDB81, 0x8E43, 0xDB82, 0x8E45, 0xDB83, 0x8E46, 0xDB84, 0x8E4C, 0xDB85, 0x8E4D, 0xDB86, 0x8E4E, + 0xDB87, 0x8E4F, 0xDB88, 0x8E50, 0xDB89, 0x8E53, 0xDB8A, 0x8E54, 0xDB8B, 0x8E55, 0xDB8C, 0x8E56, 0xDB8D, 0x8E57, 0xDB8E, 0x8E58, + 0xDB8F, 0x8E5A, 0xDB90, 0x8E5B, 0xDB91, 0x8E5C, 0xDB92, 0x8E5D, 0xDB93, 0x8E5E, 0xDB94, 0x8E5F, 0xDB95, 0x8E60, 0xDB96, 0x8E61, + 0xDB97, 0x8E62, 0xDB98, 0x8E63, 0xDB99, 0x8E64, 0xDB9A, 0x8E65, 0xDB9B, 0x8E67, 0xDB9C, 0x8E68, 0xDB9D, 0x8E6A, 0xDB9E, 0x8E6B, + 0xDB9F, 0x8E6E, 0xDBA0, 0x8E71, 0xDBA1, 0x90B8, 0xDBA2, 0x90B0, 0xDBA3, 0x90CF, 0xDBA4, 0x90C5, 0xDBA5, 0x90BE, 0xDBA6, 0x90D0, + 0xDBA7, 0x90C4, 0xDBA8, 0x90C7, 0xDBA9, 0x90D3, 0xDBAA, 0x90E6, 0xDBAB, 0x90E2, 0xDBAC, 0x90DC, 0xDBAD, 0x90D7, 0xDBAE, 0x90DB, + 0xDBAF, 0x90EB, 0xDBB0, 0x90EF, 0xDBB1, 0x90FE, 0xDBB2, 0x9104, 0xDBB3, 0x9122, 0xDBB4, 0x911E, 0xDBB5, 0x9123, 0xDBB6, 0x9131, + 0xDBB7, 0x912F, 0xDBB8, 0x9139, 0xDBB9, 0x9143, 0xDBBA, 0x9146, 0xDBBB, 0x520D, 0xDBBC, 0x5942, 0xDBBD, 0x52A2, 0xDBBE, 0x52AC, + 0xDBBF, 0x52AD, 0xDBC0, 0x52BE, 0xDBC1, 0x54FF, 0xDBC2, 0x52D0, 0xDBC3, 0x52D6, 0xDBC4, 0x52F0, 0xDBC5, 0x53DF, 0xDBC6, 0x71EE, + 0xDBC7, 0x77CD, 0xDBC8, 0x5EF4, 0xDBC9, 0x51F5, 0xDBCA, 0x51FC, 0xDBCB, 0x9B2F, 0xDBCC, 0x53B6, 0xDBCD, 0x5F01, 0xDBCE, 0x755A, + 0xDBCF, 0x5DEF, 0xDBD0, 0x574C, 0xDBD1, 0x57A9, 0xDBD2, 0x57A1, 0xDBD3, 0x587E, 0xDBD4, 0x58BC, 0xDBD5, 0x58C5, 0xDBD6, 0x58D1, + 0xDBD7, 0x5729, 0xDBD8, 0x572C, 0xDBD9, 0x572A, 0xDBDA, 0x5733, 0xDBDB, 0x5739, 0xDBDC, 0x572E, 0xDBDD, 0x572F, 0xDBDE, 0x575C, + 0xDBDF, 0x573B, 0xDBE0, 0x5742, 0xDBE1, 0x5769, 0xDBE2, 0x5785, 0xDBE3, 0x576B, 0xDBE4, 0x5786, 0xDBE5, 0x577C, 0xDBE6, 0x577B, + 0xDBE7, 0x5768, 0xDBE8, 0x576D, 0xDBE9, 0x5776, 0xDBEA, 0x5773, 0xDBEB, 0x57AD, 0xDBEC, 0x57A4, 0xDBED, 0x578C, 0xDBEE, 0x57B2, + 0xDBEF, 0x57CF, 0xDBF0, 0x57A7, 0xDBF1, 0x57B4, 0xDBF2, 0x5793, 0xDBF3, 0x57A0, 0xDBF4, 0x57D5, 0xDBF5, 0x57D8, 0xDBF6, 0x57DA, + 0xDBF7, 0x57D9, 0xDBF8, 0x57D2, 0xDBF9, 0x57B8, 0xDBFA, 0x57F4, 0xDBFB, 0x57EF, 0xDBFC, 0x57F8, 0xDBFD, 0x57E4, 0xDBFE, 0x57DD, + 0xDC40, 0x8E73, 0xDC41, 0x8E75, 0xDC42, 0x8E77, 0xDC43, 0x8E78, 0xDC44, 0x8E79, 0xDC45, 0x8E7A, 0xDC46, 0x8E7B, 0xDC47, 0x8E7D, + 0xDC48, 0x8E7E, 0xDC49, 0x8E80, 0xDC4A, 0x8E82, 0xDC4B, 0x8E83, 0xDC4C, 0x8E84, 0xDC4D, 0x8E86, 0xDC4E, 0x8E88, 0xDC4F, 0x8E89, + 0xDC50, 0x8E8A, 0xDC51, 0x8E8B, 0xDC52, 0x8E8C, 0xDC53, 0x8E8D, 0xDC54, 0x8E8E, 0xDC55, 0x8E91, 0xDC56, 0x8E92, 0xDC57, 0x8E93, + 0xDC58, 0x8E95, 0xDC59, 0x8E96, 0xDC5A, 0x8E97, 0xDC5B, 0x8E98, 0xDC5C, 0x8E99, 0xDC5D, 0x8E9A, 0xDC5E, 0x8E9B, 0xDC5F, 0x8E9D, + 0xDC60, 0x8E9F, 0xDC61, 0x8EA0, 0xDC62, 0x8EA1, 0xDC63, 0x8EA2, 0xDC64, 0x8EA3, 0xDC65, 0x8EA4, 0xDC66, 0x8EA5, 0xDC67, 0x8EA6, + 0xDC68, 0x8EA7, 0xDC69, 0x8EA8, 0xDC6A, 0x8EA9, 0xDC6B, 0x8EAA, 0xDC6C, 0x8EAD, 0xDC6D, 0x8EAE, 0xDC6E, 0x8EB0, 0xDC6F, 0x8EB1, + 0xDC70, 0x8EB3, 0xDC71, 0x8EB4, 0xDC72, 0x8EB5, 0xDC73, 0x8EB6, 0xDC74, 0x8EB7, 0xDC75, 0x8EB8, 0xDC76, 0x8EB9, 0xDC77, 0x8EBB, + 0xDC78, 0x8EBC, 0xDC79, 0x8EBD, 0xDC7A, 0x8EBE, 0xDC7B, 0x8EBF, 0xDC7C, 0x8EC0, 0xDC7D, 0x8EC1, 0xDC7E, 0x8EC2, 0xDC80, 0x8EC3, + 0xDC81, 0x8EC4, 0xDC82, 0x8EC5, 0xDC83, 0x8EC6, 0xDC84, 0x8EC7, 0xDC85, 0x8EC8, 0xDC86, 0x8EC9, 0xDC87, 0x8ECA, 0xDC88, 0x8ECB, + 0xDC89, 0x8ECC, 0xDC8A, 0x8ECD, 0xDC8B, 0x8ECF, 0xDC8C, 0x8ED0, 0xDC8D, 0x8ED1, 0xDC8E, 0x8ED2, 0xDC8F, 0x8ED3, 0xDC90, 0x8ED4, + 0xDC91, 0x8ED5, 0xDC92, 0x8ED6, 0xDC93, 0x8ED7, 0xDC94, 0x8ED8, 0xDC95, 0x8ED9, 0xDC96, 0x8EDA, 0xDC97, 0x8EDB, 0xDC98, 0x8EDC, + 0xDC99, 0x8EDD, 0xDC9A, 0x8EDE, 0xDC9B, 0x8EDF, 0xDC9C, 0x8EE0, 0xDC9D, 0x8EE1, 0xDC9E, 0x8EE2, 0xDC9F, 0x8EE3, 0xDCA0, 0x8EE4, + 0xDCA1, 0x580B, 0xDCA2, 0x580D, 0xDCA3, 0x57FD, 0xDCA4, 0x57ED, 0xDCA5, 0x5800, 0xDCA6, 0x581E, 0xDCA7, 0x5819, 0xDCA8, 0x5844, + 0xDCA9, 0x5820, 0xDCAA, 0x5865, 0xDCAB, 0x586C, 0xDCAC, 0x5881, 0xDCAD, 0x5889, 0xDCAE, 0x589A, 0xDCAF, 0x5880, 0xDCB0, 0x99A8, + 0xDCB1, 0x9F19, 0xDCB2, 0x61FF, 0xDCB3, 0x8279, 0xDCB4, 0x827D, 0xDCB5, 0x827F, 0xDCB6, 0x828F, 0xDCB7, 0x828A, 0xDCB8, 0x82A8, + 0xDCB9, 0x8284, 0xDCBA, 0x828E, 0xDCBB, 0x8291, 0xDCBC, 0x8297, 0xDCBD, 0x8299, 0xDCBE, 0x82AB, 0xDCBF, 0x82B8, 0xDCC0, 0x82BE, + 0xDCC1, 0x82B0, 0xDCC2, 0x82C8, 0xDCC3, 0x82CA, 0xDCC4, 0x82E3, 0xDCC5, 0x8298, 0xDCC6, 0x82B7, 0xDCC7, 0x82AE, 0xDCC8, 0x82CB, + 0xDCC9, 0x82CC, 0xDCCA, 0x82C1, 0xDCCB, 0x82A9, 0xDCCC, 0x82B4, 0xDCCD, 0x82A1, 0xDCCE, 0x82AA, 0xDCCF, 0x829F, 0xDCD0, 0x82C4, + 0xDCD1, 0x82CE, 0xDCD2, 0x82A4, 0xDCD3, 0x82E1, 0xDCD4, 0x8309, 0xDCD5, 0x82F7, 0xDCD6, 0x82E4, 0xDCD7, 0x830F, 0xDCD8, 0x8307, + 0xDCD9, 0x82DC, 0xDCDA, 0x82F4, 0xDCDB, 0x82D2, 0xDCDC, 0x82D8, 0xDCDD, 0x830C, 0xDCDE, 0x82FB, 0xDCDF, 0x82D3, 0xDCE0, 0x8311, + 0xDCE1, 0x831A, 0xDCE2, 0x8306, 0xDCE3, 0x8314, 0xDCE4, 0x8315, 0xDCE5, 0x82E0, 0xDCE6, 0x82D5, 0xDCE7, 0x831C, 0xDCE8, 0x8351, + 0xDCE9, 0x835B, 0xDCEA, 0x835C, 0xDCEB, 0x8308, 0xDCEC, 0x8392, 0xDCED, 0x833C, 0xDCEE, 0x8334, 0xDCEF, 0x8331, 0xDCF0, 0x839B, + 0xDCF1, 0x835E, 0xDCF2, 0x832F, 0xDCF3, 0x834F, 0xDCF4, 0x8347, 0xDCF5, 0x8343, 0xDCF6, 0x835F, 0xDCF7, 0x8340, 0xDCF8, 0x8317, + 0xDCF9, 0x8360, 0xDCFA, 0x832D, 0xDCFB, 0x833A, 0xDCFC, 0x8333, 0xDCFD, 0x8366, 0xDCFE, 0x8365, 0xDD40, 0x8EE5, 0xDD41, 0x8EE6, + 0xDD42, 0x8EE7, 0xDD43, 0x8EE8, 0xDD44, 0x8EE9, 0xDD45, 0x8EEA, 0xDD46, 0x8EEB, 0xDD47, 0x8EEC, 0xDD48, 0x8EED, 0xDD49, 0x8EEE, + 0xDD4A, 0x8EEF, 0xDD4B, 0x8EF0, 0xDD4C, 0x8EF1, 0xDD4D, 0x8EF2, 0xDD4E, 0x8EF3, 0xDD4F, 0x8EF4, 0xDD50, 0x8EF5, 0xDD51, 0x8EF6, + 0xDD52, 0x8EF7, 0xDD53, 0x8EF8, 0xDD54, 0x8EF9, 0xDD55, 0x8EFA, 0xDD56, 0x8EFB, 0xDD57, 0x8EFC, 0xDD58, 0x8EFD, 0xDD59, 0x8EFE, + 0xDD5A, 0x8EFF, 0xDD5B, 0x8F00, 0xDD5C, 0x8F01, 0xDD5D, 0x8F02, 0xDD5E, 0x8F03, 0xDD5F, 0x8F04, 0xDD60, 0x8F05, 0xDD61, 0x8F06, + 0xDD62, 0x8F07, 0xDD63, 0x8F08, 0xDD64, 0x8F09, 0xDD65, 0x8F0A, 0xDD66, 0x8F0B, 0xDD67, 0x8F0C, 0xDD68, 0x8F0D, 0xDD69, 0x8F0E, + 0xDD6A, 0x8F0F, 0xDD6B, 0x8F10, 0xDD6C, 0x8F11, 0xDD6D, 0x8F12, 0xDD6E, 0x8F13, 0xDD6F, 0x8F14, 0xDD70, 0x8F15, 0xDD71, 0x8F16, + 0xDD72, 0x8F17, 0xDD73, 0x8F18, 0xDD74, 0x8F19, 0xDD75, 0x8F1A, 0xDD76, 0x8F1B, 0xDD77, 0x8F1C, 0xDD78, 0x8F1D, 0xDD79, 0x8F1E, + 0xDD7A, 0x8F1F, 0xDD7B, 0x8F20, 0xDD7C, 0x8F21, 0xDD7D, 0x8F22, 0xDD7E, 0x8F23, 0xDD80, 0x8F24, 0xDD81, 0x8F25, 0xDD82, 0x8F26, + 0xDD83, 0x8F27, 0xDD84, 0x8F28, 0xDD85, 0x8F29, 0xDD86, 0x8F2A, 0xDD87, 0x8F2B, 0xDD88, 0x8F2C, 0xDD89, 0x8F2D, 0xDD8A, 0x8F2E, + 0xDD8B, 0x8F2F, 0xDD8C, 0x8F30, 0xDD8D, 0x8F31, 0xDD8E, 0x8F32, 0xDD8F, 0x8F33, 0xDD90, 0x8F34, 0xDD91, 0x8F35, 0xDD92, 0x8F36, + 0xDD93, 0x8F37, 0xDD94, 0x8F38, 0xDD95, 0x8F39, 0xDD96, 0x8F3A, 0xDD97, 0x8F3B, 0xDD98, 0x8F3C, 0xDD99, 0x8F3D, 0xDD9A, 0x8F3E, + 0xDD9B, 0x8F3F, 0xDD9C, 0x8F40, 0xDD9D, 0x8F41, 0xDD9E, 0x8F42, 0xDD9F, 0x8F43, 0xDDA0, 0x8F44, 0xDDA1, 0x8368, 0xDDA2, 0x831B, + 0xDDA3, 0x8369, 0xDDA4, 0x836C, 0xDDA5, 0x836A, 0xDDA6, 0x836D, 0xDDA7, 0x836E, 0xDDA8, 0x83B0, 0xDDA9, 0x8378, 0xDDAA, 0x83B3, + 0xDDAB, 0x83B4, 0xDDAC, 0x83A0, 0xDDAD, 0x83AA, 0xDDAE, 0x8393, 0xDDAF, 0x839C, 0xDDB0, 0x8385, 0xDDB1, 0x837C, 0xDDB2, 0x83B6, + 0xDDB3, 0x83A9, 0xDDB4, 0x837D, 0xDDB5, 0x83B8, 0xDDB6, 0x837B, 0xDDB7, 0x8398, 0xDDB8, 0x839E, 0xDDB9, 0x83A8, 0xDDBA, 0x83BA, + 0xDDBB, 0x83BC, 0xDDBC, 0x83C1, 0xDDBD, 0x8401, 0xDDBE, 0x83E5, 0xDDBF, 0x83D8, 0xDDC0, 0x5807, 0xDDC1, 0x8418, 0xDDC2, 0x840B, + 0xDDC3, 0x83DD, 0xDDC4, 0x83FD, 0xDDC5, 0x83D6, 0xDDC6, 0x841C, 0xDDC7, 0x8438, 0xDDC8, 0x8411, 0xDDC9, 0x8406, 0xDDCA, 0x83D4, + 0xDDCB, 0x83DF, 0xDDCC, 0x840F, 0xDDCD, 0x8403, 0xDDCE, 0x83F8, 0xDDCF, 0x83F9, 0xDDD0, 0x83EA, 0xDDD1, 0x83C5, 0xDDD2, 0x83C0, + 0xDDD3, 0x8426, 0xDDD4, 0x83F0, 0xDDD5, 0x83E1, 0xDDD6, 0x845C, 0xDDD7, 0x8451, 0xDDD8, 0x845A, 0xDDD9, 0x8459, 0xDDDA, 0x8473, + 0xDDDB, 0x8487, 0xDDDC, 0x8488, 0xDDDD, 0x847A, 0xDDDE, 0x8489, 0xDDDF, 0x8478, 0xDDE0, 0x843C, 0xDDE1, 0x8446, 0xDDE2, 0x8469, + 0xDDE3, 0x8476, 0xDDE4, 0x848C, 0xDDE5, 0x848E, 0xDDE6, 0x8431, 0xDDE7, 0x846D, 0xDDE8, 0x84C1, 0xDDE9, 0x84CD, 0xDDEA, 0x84D0, + 0xDDEB, 0x84E6, 0xDDEC, 0x84BD, 0xDDED, 0x84D3, 0xDDEE, 0x84CA, 0xDDEF, 0x84BF, 0xDDF0, 0x84BA, 0xDDF1, 0x84E0, 0xDDF2, 0x84A1, + 0xDDF3, 0x84B9, 0xDDF4, 0x84B4, 0xDDF5, 0x8497, 0xDDF6, 0x84E5, 0xDDF7, 0x84E3, 0xDDF8, 0x850C, 0xDDF9, 0x750D, 0xDDFA, 0x8538, + 0xDDFB, 0x84F0, 0xDDFC, 0x8539, 0xDDFD, 0x851F, 0xDDFE, 0x853A, 0xDE40, 0x8F45, 0xDE41, 0x8F46, 0xDE42, 0x8F47, 0xDE43, 0x8F48, + 0xDE44, 0x8F49, 0xDE45, 0x8F4A, 0xDE46, 0x8F4B, 0xDE47, 0x8F4C, 0xDE48, 0x8F4D, 0xDE49, 0x8F4E, 0xDE4A, 0x8F4F, 0xDE4B, 0x8F50, + 0xDE4C, 0x8F51, 0xDE4D, 0x8F52, 0xDE4E, 0x8F53, 0xDE4F, 0x8F54, 0xDE50, 0x8F55, 0xDE51, 0x8F56, 0xDE52, 0x8F57, 0xDE53, 0x8F58, + 0xDE54, 0x8F59, 0xDE55, 0x8F5A, 0xDE56, 0x8F5B, 0xDE57, 0x8F5C, 0xDE58, 0x8F5D, 0xDE59, 0x8F5E, 0xDE5A, 0x8F5F, 0xDE5B, 0x8F60, + 0xDE5C, 0x8F61, 0xDE5D, 0x8F62, 0xDE5E, 0x8F63, 0xDE5F, 0x8F64, 0xDE60, 0x8F65, 0xDE61, 0x8F6A, 0xDE62, 0x8F80, 0xDE63, 0x8F8C, + 0xDE64, 0x8F92, 0xDE65, 0x8F9D, 0xDE66, 0x8FA0, 0xDE67, 0x8FA1, 0xDE68, 0x8FA2, 0xDE69, 0x8FA4, 0xDE6A, 0x8FA5, 0xDE6B, 0x8FA6, + 0xDE6C, 0x8FA7, 0xDE6D, 0x8FAA, 0xDE6E, 0x8FAC, 0xDE6F, 0x8FAD, 0xDE70, 0x8FAE, 0xDE71, 0x8FAF, 0xDE72, 0x8FB2, 0xDE73, 0x8FB3, + 0xDE74, 0x8FB4, 0xDE75, 0x8FB5, 0xDE76, 0x8FB7, 0xDE77, 0x8FB8, 0xDE78, 0x8FBA, 0xDE79, 0x8FBB, 0xDE7A, 0x8FBC, 0xDE7B, 0x8FBF, + 0xDE7C, 0x8FC0, 0xDE7D, 0x8FC3, 0xDE7E, 0x8FC6, 0xDE80, 0x8FC9, 0xDE81, 0x8FCA, 0xDE82, 0x8FCB, 0xDE83, 0x8FCC, 0xDE84, 0x8FCD, + 0xDE85, 0x8FCF, 0xDE86, 0x8FD2, 0xDE87, 0x8FD6, 0xDE88, 0x8FD7, 0xDE89, 0x8FDA, 0xDE8A, 0x8FE0, 0xDE8B, 0x8FE1, 0xDE8C, 0x8FE3, + 0xDE8D, 0x8FE7, 0xDE8E, 0x8FEC, 0xDE8F, 0x8FEF, 0xDE90, 0x8FF1, 0xDE91, 0x8FF2, 0xDE92, 0x8FF4, 0xDE93, 0x8FF5, 0xDE94, 0x8FF6, + 0xDE95, 0x8FFA, 0xDE96, 0x8FFB, 0xDE97, 0x8FFC, 0xDE98, 0x8FFE, 0xDE99, 0x8FFF, 0xDE9A, 0x9007, 0xDE9B, 0x9008, 0xDE9C, 0x900C, + 0xDE9D, 0x900E, 0xDE9E, 0x9013, 0xDE9F, 0x9015, 0xDEA0, 0x9018, 0xDEA1, 0x8556, 0xDEA2, 0x853B, 0xDEA3, 0x84FF, 0xDEA4, 0x84FC, + 0xDEA5, 0x8559, 0xDEA6, 0x8548, 0xDEA7, 0x8568, 0xDEA8, 0x8564, 0xDEA9, 0x855E, 0xDEAA, 0x857A, 0xDEAB, 0x77A2, 0xDEAC, 0x8543, + 0xDEAD, 0x8572, 0xDEAE, 0x857B, 0xDEAF, 0x85A4, 0xDEB0, 0x85A8, 0xDEB1, 0x8587, 0xDEB2, 0x858F, 0xDEB3, 0x8579, 0xDEB4, 0x85AE, + 0xDEB5, 0x859C, 0xDEB6, 0x8585, 0xDEB7, 0x85B9, 0xDEB8, 0x85B7, 0xDEB9, 0x85B0, 0xDEBA, 0x85D3, 0xDEBB, 0x85C1, 0xDEBC, 0x85DC, + 0xDEBD, 0x85FF, 0xDEBE, 0x8627, 0xDEBF, 0x8605, 0xDEC0, 0x8629, 0xDEC1, 0x8616, 0xDEC2, 0x863C, 0xDEC3, 0x5EFE, 0xDEC4, 0x5F08, + 0xDEC5, 0x593C, 0xDEC6, 0x5941, 0xDEC7, 0x8037, 0xDEC8, 0x5955, 0xDEC9, 0x595A, 0xDECA, 0x5958, 0xDECB, 0x530F, 0xDECC, 0x5C22, + 0xDECD, 0x5C25, 0xDECE, 0x5C2C, 0xDECF, 0x5C34, 0xDED0, 0x624C, 0xDED1, 0x626A, 0xDED2, 0x629F, 0xDED3, 0x62BB, 0xDED4, 0x62CA, + 0xDED5, 0x62DA, 0xDED6, 0x62D7, 0xDED7, 0x62EE, 0xDED8, 0x6322, 0xDED9, 0x62F6, 0xDEDA, 0x6339, 0xDEDB, 0x634B, 0xDEDC, 0x6343, + 0xDEDD, 0x63AD, 0xDEDE, 0x63F6, 0xDEDF, 0x6371, 0xDEE0, 0x637A, 0xDEE1, 0x638E, 0xDEE2, 0x63B4, 0xDEE3, 0x636D, 0xDEE4, 0x63AC, + 0xDEE5, 0x638A, 0xDEE6, 0x6369, 0xDEE7, 0x63AE, 0xDEE8, 0x63BC, 0xDEE9, 0x63F2, 0xDEEA, 0x63F8, 0xDEEB, 0x63E0, 0xDEEC, 0x63FF, + 0xDEED, 0x63C4, 0xDEEE, 0x63DE, 0xDEEF, 0x63CE, 0xDEF0, 0x6452, 0xDEF1, 0x63C6, 0xDEF2, 0x63BE, 0xDEF3, 0x6445, 0xDEF4, 0x6441, + 0xDEF5, 0x640B, 0xDEF6, 0x641B, 0xDEF7, 0x6420, 0xDEF8, 0x640C, 0xDEF9, 0x6426, 0xDEFA, 0x6421, 0xDEFB, 0x645E, 0xDEFC, 0x6484, + 0xDEFD, 0x646D, 0xDEFE, 0x6496, 0xDF40, 0x9019, 0xDF41, 0x901C, 0xDF42, 0x9023, 0xDF43, 0x9024, 0xDF44, 0x9025, 0xDF45, 0x9027, + 0xDF46, 0x9028, 0xDF47, 0x9029, 0xDF48, 0x902A, 0xDF49, 0x902B, 0xDF4A, 0x902C, 0xDF4B, 0x9030, 0xDF4C, 0x9031, 0xDF4D, 0x9032, + 0xDF4E, 0x9033, 0xDF4F, 0x9034, 0xDF50, 0x9037, 0xDF51, 0x9039, 0xDF52, 0x903A, 0xDF53, 0x903D, 0xDF54, 0x903F, 0xDF55, 0x9040, + 0xDF56, 0x9043, 0xDF57, 0x9045, 0xDF58, 0x9046, 0xDF59, 0x9048, 0xDF5A, 0x9049, 0xDF5B, 0x904A, 0xDF5C, 0x904B, 0xDF5D, 0x904C, + 0xDF5E, 0x904E, 0xDF5F, 0x9054, 0xDF60, 0x9055, 0xDF61, 0x9056, 0xDF62, 0x9059, 0xDF63, 0x905A, 0xDF64, 0x905C, 0xDF65, 0x905D, + 0xDF66, 0x905E, 0xDF67, 0x905F, 0xDF68, 0x9060, 0xDF69, 0x9061, 0xDF6A, 0x9064, 0xDF6B, 0x9066, 0xDF6C, 0x9067, 0xDF6D, 0x9069, + 0xDF6E, 0x906A, 0xDF6F, 0x906B, 0xDF70, 0x906C, 0xDF71, 0x906F, 0xDF72, 0x9070, 0xDF73, 0x9071, 0xDF74, 0x9072, 0xDF75, 0x9073, + 0xDF76, 0x9076, 0xDF77, 0x9077, 0xDF78, 0x9078, 0xDF79, 0x9079, 0xDF7A, 0x907A, 0xDF7B, 0x907B, 0xDF7C, 0x907C, 0xDF7D, 0x907E, + 0xDF7E, 0x9081, 0xDF80, 0x9084, 0xDF81, 0x9085, 0xDF82, 0x9086, 0xDF83, 0x9087, 0xDF84, 0x9089, 0xDF85, 0x908A, 0xDF86, 0x908C, + 0xDF87, 0x908D, 0xDF88, 0x908E, 0xDF89, 0x908F, 0xDF8A, 0x9090, 0xDF8B, 0x9092, 0xDF8C, 0x9094, 0xDF8D, 0x9096, 0xDF8E, 0x9098, + 0xDF8F, 0x909A, 0xDF90, 0x909C, 0xDF91, 0x909E, 0xDF92, 0x909F, 0xDF93, 0x90A0, 0xDF94, 0x90A4, 0xDF95, 0x90A5, 0xDF96, 0x90A7, + 0xDF97, 0x90A8, 0xDF98, 0x90A9, 0xDF99, 0x90AB, 0xDF9A, 0x90AD, 0xDF9B, 0x90B2, 0xDF9C, 0x90B7, 0xDF9D, 0x90BC, 0xDF9E, 0x90BD, + 0xDF9F, 0x90BF, 0xDFA0, 0x90C0, 0xDFA1, 0x647A, 0xDFA2, 0x64B7, 0xDFA3, 0x64B8, 0xDFA4, 0x6499, 0xDFA5, 0x64BA, 0xDFA6, 0x64C0, + 0xDFA7, 0x64D0, 0xDFA8, 0x64D7, 0xDFA9, 0x64E4, 0xDFAA, 0x64E2, 0xDFAB, 0x6509, 0xDFAC, 0x6525, 0xDFAD, 0x652E, 0xDFAE, 0x5F0B, + 0xDFAF, 0x5FD2, 0xDFB0, 0x7519, 0xDFB1, 0x5F11, 0xDFB2, 0x535F, 0xDFB3, 0x53F1, 0xDFB4, 0x53FD, 0xDFB5, 0x53E9, 0xDFB6, 0x53E8, + 0xDFB7, 0x53FB, 0xDFB8, 0x5412, 0xDFB9, 0x5416, 0xDFBA, 0x5406, 0xDFBB, 0x544B, 0xDFBC, 0x5452, 0xDFBD, 0x5453, 0xDFBE, 0x5454, + 0xDFBF, 0x5456, 0xDFC0, 0x5443, 0xDFC1, 0x5421, 0xDFC2, 0x5457, 0xDFC3, 0x5459, 0xDFC4, 0x5423, 0xDFC5, 0x5432, 0xDFC6, 0x5482, + 0xDFC7, 0x5494, 0xDFC8, 0x5477, 0xDFC9, 0x5471, 0xDFCA, 0x5464, 0xDFCB, 0x549A, 0xDFCC, 0x549B, 0xDFCD, 0x5484, 0xDFCE, 0x5476, + 0xDFCF, 0x5466, 0xDFD0, 0x549D, 0xDFD1, 0x54D0, 0xDFD2, 0x54AD, 0xDFD3, 0x54C2, 0xDFD4, 0x54B4, 0xDFD5, 0x54D2, 0xDFD6, 0x54A7, + 0xDFD7, 0x54A6, 0xDFD8, 0x54D3, 0xDFD9, 0x54D4, 0xDFDA, 0x5472, 0xDFDB, 0x54A3, 0xDFDC, 0x54D5, 0xDFDD, 0x54BB, 0xDFDE, 0x54BF, + 0xDFDF, 0x54CC, 0xDFE0, 0x54D9, 0xDFE1, 0x54DA, 0xDFE2, 0x54DC, 0xDFE3, 0x54A9, 0xDFE4, 0x54AA, 0xDFE5, 0x54A4, 0xDFE6, 0x54DD, + 0xDFE7, 0x54CF, 0xDFE8, 0x54DE, 0xDFE9, 0x551B, 0xDFEA, 0x54E7, 0xDFEB, 0x5520, 0xDFEC, 0x54FD, 0xDFED, 0x5514, 0xDFEE, 0x54F3, + 0xDFEF, 0x5522, 0xDFF0, 0x5523, 0xDFF1, 0x550F, 0xDFF2, 0x5511, 0xDFF3, 0x5527, 0xDFF4, 0x552A, 0xDFF5, 0x5567, 0xDFF6, 0x558F, + 0xDFF7, 0x55B5, 0xDFF8, 0x5549, 0xDFF9, 0x556D, 0xDFFA, 0x5541, 0xDFFB, 0x5555, 0xDFFC, 0x553F, 0xDFFD, 0x5550, 0xDFFE, 0x553C, + 0xE040, 0x90C2, 0xE041, 0x90C3, 0xE042, 0x90C6, 0xE043, 0x90C8, 0xE044, 0x90C9, 0xE045, 0x90CB, 0xE046, 0x90CC, 0xE047, 0x90CD, + 0xE048, 0x90D2, 0xE049, 0x90D4, 0xE04A, 0x90D5, 0xE04B, 0x90D6, 0xE04C, 0x90D8, 0xE04D, 0x90D9, 0xE04E, 0x90DA, 0xE04F, 0x90DE, + 0xE050, 0x90DF, 0xE051, 0x90E0, 0xE052, 0x90E3, 0xE053, 0x90E4, 0xE054, 0x90E5, 0xE055, 0x90E9, 0xE056, 0x90EA, 0xE057, 0x90EC, + 0xE058, 0x90EE, 0xE059, 0x90F0, 0xE05A, 0x90F1, 0xE05B, 0x90F2, 0xE05C, 0x90F3, 0xE05D, 0x90F5, 0xE05E, 0x90F6, 0xE05F, 0x90F7, + 0xE060, 0x90F9, 0xE061, 0x90FA, 0xE062, 0x90FB, 0xE063, 0x90FC, 0xE064, 0x90FF, 0xE065, 0x9100, 0xE066, 0x9101, 0xE067, 0x9103, + 0xE068, 0x9105, 0xE069, 0x9106, 0xE06A, 0x9107, 0xE06B, 0x9108, 0xE06C, 0x9109, 0xE06D, 0x910A, 0xE06E, 0x910B, 0xE06F, 0x910C, + 0xE070, 0x910D, 0xE071, 0x910E, 0xE072, 0x910F, 0xE073, 0x9110, 0xE074, 0x9111, 0xE075, 0x9112, 0xE076, 0x9113, 0xE077, 0x9114, + 0xE078, 0x9115, 0xE079, 0x9116, 0xE07A, 0x9117, 0xE07B, 0x9118, 0xE07C, 0x911A, 0xE07D, 0x911B, 0xE07E, 0x911C, 0xE080, 0x911D, + 0xE081, 0x911F, 0xE082, 0x9120, 0xE083, 0x9121, 0xE084, 0x9124, 0xE085, 0x9125, 0xE086, 0x9126, 0xE087, 0x9127, 0xE088, 0x9128, + 0xE089, 0x9129, 0xE08A, 0x912A, 0xE08B, 0x912B, 0xE08C, 0x912C, 0xE08D, 0x912D, 0xE08E, 0x912E, 0xE08F, 0x9130, 0xE090, 0x9132, + 0xE091, 0x9133, 0xE092, 0x9134, 0xE093, 0x9135, 0xE094, 0x9136, 0xE095, 0x9137, 0xE096, 0x9138, 0xE097, 0x913A, 0xE098, 0x913B, + 0xE099, 0x913C, 0xE09A, 0x913D, 0xE09B, 0x913E, 0xE09C, 0x913F, 0xE09D, 0x9140, 0xE09E, 0x9141, 0xE09F, 0x9142, 0xE0A0, 0x9144, + 0xE0A1, 0x5537, 0xE0A2, 0x5556, 0xE0A3, 0x5575, 0xE0A4, 0x5576, 0xE0A5, 0x5577, 0xE0A6, 0x5533, 0xE0A7, 0x5530, 0xE0A8, 0x555C, + 0xE0A9, 0x558B, 0xE0AA, 0x55D2, 0xE0AB, 0x5583, 0xE0AC, 0x55B1, 0xE0AD, 0x55B9, 0xE0AE, 0x5588, 0xE0AF, 0x5581, 0xE0B0, 0x559F, + 0xE0B1, 0x557E, 0xE0B2, 0x55D6, 0xE0B3, 0x5591, 0xE0B4, 0x557B, 0xE0B5, 0x55DF, 0xE0B6, 0x55BD, 0xE0B7, 0x55BE, 0xE0B8, 0x5594, + 0xE0B9, 0x5599, 0xE0BA, 0x55EA, 0xE0BB, 0x55F7, 0xE0BC, 0x55C9, 0xE0BD, 0x561F, 0xE0BE, 0x55D1, 0xE0BF, 0x55EB, 0xE0C0, 0x55EC, + 0xE0C1, 0x55D4, 0xE0C2, 0x55E6, 0xE0C3, 0x55DD, 0xE0C4, 0x55C4, 0xE0C5, 0x55EF, 0xE0C6, 0x55E5, 0xE0C7, 0x55F2, 0xE0C8, 0x55F3, + 0xE0C9, 0x55CC, 0xE0CA, 0x55CD, 0xE0CB, 0x55E8, 0xE0CC, 0x55F5, 0xE0CD, 0x55E4, 0xE0CE, 0x8F94, 0xE0CF, 0x561E, 0xE0D0, 0x5608, + 0xE0D1, 0x560C, 0xE0D2, 0x5601, 0xE0D3, 0x5624, 0xE0D4, 0x5623, 0xE0D5, 0x55FE, 0xE0D6, 0x5600, 0xE0D7, 0x5627, 0xE0D8, 0x562D, + 0xE0D9, 0x5658, 0xE0DA, 0x5639, 0xE0DB, 0x5657, 0xE0DC, 0x562C, 0xE0DD, 0x564D, 0xE0DE, 0x5662, 0xE0DF, 0x5659, 0xE0E0, 0x565C, + 0xE0E1, 0x564C, 0xE0E2, 0x5654, 0xE0E3, 0x5686, 0xE0E4, 0x5664, 0xE0E5, 0x5671, 0xE0E6, 0x566B, 0xE0E7, 0x567B, 0xE0E8, 0x567C, + 0xE0E9, 0x5685, 0xE0EA, 0x5693, 0xE0EB, 0x56AF, 0xE0EC, 0x56D4, 0xE0ED, 0x56D7, 0xE0EE, 0x56DD, 0xE0EF, 0x56E1, 0xE0F0, 0x56F5, + 0xE0F1, 0x56EB, 0xE0F2, 0x56F9, 0xE0F3, 0x56FF, 0xE0F4, 0x5704, 0xE0F5, 0x570A, 0xE0F6, 0x5709, 0xE0F7, 0x571C, 0xE0F8, 0x5E0F, + 0xE0F9, 0x5E19, 0xE0FA, 0x5E14, 0xE0FB, 0x5E11, 0xE0FC, 0x5E31, 0xE0FD, 0x5E3B, 0xE0FE, 0x5E3C, 0xE140, 0x9145, 0xE141, 0x9147, + 0xE142, 0x9148, 0xE143, 0x9151, 0xE144, 0x9153, 0xE145, 0x9154, 0xE146, 0x9155, 0xE147, 0x9156, 0xE148, 0x9158, 0xE149, 0x9159, + 0xE14A, 0x915B, 0xE14B, 0x915C, 0xE14C, 0x915F, 0xE14D, 0x9160, 0xE14E, 0x9166, 0xE14F, 0x9167, 0xE150, 0x9168, 0xE151, 0x916B, + 0xE152, 0x916D, 0xE153, 0x9173, 0xE154, 0x917A, 0xE155, 0x917B, 0xE156, 0x917C, 0xE157, 0x9180, 0xE158, 0x9181, 0xE159, 0x9182, + 0xE15A, 0x9183, 0xE15B, 0x9184, 0xE15C, 0x9186, 0xE15D, 0x9188, 0xE15E, 0x918A, 0xE15F, 0x918E, 0xE160, 0x918F, 0xE161, 0x9193, + 0xE162, 0x9194, 0xE163, 0x9195, 0xE164, 0x9196, 0xE165, 0x9197, 0xE166, 0x9198, 0xE167, 0x9199, 0xE168, 0x919C, 0xE169, 0x919D, + 0xE16A, 0x919E, 0xE16B, 0x919F, 0xE16C, 0x91A0, 0xE16D, 0x91A1, 0xE16E, 0x91A4, 0xE16F, 0x91A5, 0xE170, 0x91A6, 0xE171, 0x91A7, + 0xE172, 0x91A8, 0xE173, 0x91A9, 0xE174, 0x91AB, 0xE175, 0x91AC, 0xE176, 0x91B0, 0xE177, 0x91B1, 0xE178, 0x91B2, 0xE179, 0x91B3, + 0xE17A, 0x91B6, 0xE17B, 0x91B7, 0xE17C, 0x91B8, 0xE17D, 0x91B9, 0xE17E, 0x91BB, 0xE180, 0x91BC, 0xE181, 0x91BD, 0xE182, 0x91BE, + 0xE183, 0x91BF, 0xE184, 0x91C0, 0xE185, 0x91C1, 0xE186, 0x91C2, 0xE187, 0x91C3, 0xE188, 0x91C4, 0xE189, 0x91C5, 0xE18A, 0x91C6, + 0xE18B, 0x91C8, 0xE18C, 0x91CB, 0xE18D, 0x91D0, 0xE18E, 0x91D2, 0xE18F, 0x91D3, 0xE190, 0x91D4, 0xE191, 0x91D5, 0xE192, 0x91D6, + 0xE193, 0x91D7, 0xE194, 0x91D8, 0xE195, 0x91D9, 0xE196, 0x91DA, 0xE197, 0x91DB, 0xE198, 0x91DD, 0xE199, 0x91DE, 0xE19A, 0x91DF, + 0xE19B, 0x91E0, 0xE19C, 0x91E1, 0xE19D, 0x91E2, 0xE19E, 0x91E3, 0xE19F, 0x91E4, 0xE1A0, 0x91E5, 0xE1A1, 0x5E37, 0xE1A2, 0x5E44, + 0xE1A3, 0x5E54, 0xE1A4, 0x5E5B, 0xE1A5, 0x5E5E, 0xE1A6, 0x5E61, 0xE1A7, 0x5C8C, 0xE1A8, 0x5C7A, 0xE1A9, 0x5C8D, 0xE1AA, 0x5C90, + 0xE1AB, 0x5C96, 0xE1AC, 0x5C88, 0xE1AD, 0x5C98, 0xE1AE, 0x5C99, 0xE1AF, 0x5C91, 0xE1B0, 0x5C9A, 0xE1B1, 0x5C9C, 0xE1B2, 0x5CB5, + 0xE1B3, 0x5CA2, 0xE1B4, 0x5CBD, 0xE1B5, 0x5CAC, 0xE1B6, 0x5CAB, 0xE1B7, 0x5CB1, 0xE1B8, 0x5CA3, 0xE1B9, 0x5CC1, 0xE1BA, 0x5CB7, + 0xE1BB, 0x5CC4, 0xE1BC, 0x5CD2, 0xE1BD, 0x5CE4, 0xE1BE, 0x5CCB, 0xE1BF, 0x5CE5, 0xE1C0, 0x5D02, 0xE1C1, 0x5D03, 0xE1C2, 0x5D27, + 0xE1C3, 0x5D26, 0xE1C4, 0x5D2E, 0xE1C5, 0x5D24, 0xE1C6, 0x5D1E, 0xE1C7, 0x5D06, 0xE1C8, 0x5D1B, 0xE1C9, 0x5D58, 0xE1CA, 0x5D3E, + 0xE1CB, 0x5D34, 0xE1CC, 0x5D3D, 0xE1CD, 0x5D6C, 0xE1CE, 0x5D5B, 0xE1CF, 0x5D6F, 0xE1D0, 0x5D5D, 0xE1D1, 0x5D6B, 0xE1D2, 0x5D4B, + 0xE1D3, 0x5D4A, 0xE1D4, 0x5D69, 0xE1D5, 0x5D74, 0xE1D6, 0x5D82, 0xE1D7, 0x5D99, 0xE1D8, 0x5D9D, 0xE1D9, 0x8C73, 0xE1DA, 0x5DB7, + 0xE1DB, 0x5DC5, 0xE1DC, 0x5F73, 0xE1DD, 0x5F77, 0xE1DE, 0x5F82, 0xE1DF, 0x5F87, 0xE1E0, 0x5F89, 0xE1E1, 0x5F8C, 0xE1E2, 0x5F95, + 0xE1E3, 0x5F99, 0xE1E4, 0x5F9C, 0xE1E5, 0x5FA8, 0xE1E6, 0x5FAD, 0xE1E7, 0x5FB5, 0xE1E8, 0x5FBC, 0xE1E9, 0x8862, 0xE1EA, 0x5F61, + 0xE1EB, 0x72AD, 0xE1EC, 0x72B0, 0xE1ED, 0x72B4, 0xE1EE, 0x72B7, 0xE1EF, 0x72B8, 0xE1F0, 0x72C3, 0xE1F1, 0x72C1, 0xE1F2, 0x72CE, + 0xE1F3, 0x72CD, 0xE1F4, 0x72D2, 0xE1F5, 0x72E8, 0xE1F6, 0x72EF, 0xE1F7, 0x72E9, 0xE1F8, 0x72F2, 0xE1F9, 0x72F4, 0xE1FA, 0x72F7, + 0xE1FB, 0x7301, 0xE1FC, 0x72F3, 0xE1FD, 0x7303, 0xE1FE, 0x72FA, 0xE240, 0x91E6, 0xE241, 0x91E7, 0xE242, 0x91E8, 0xE243, 0x91E9, + 0xE244, 0x91EA, 0xE245, 0x91EB, 0xE246, 0x91EC, 0xE247, 0x91ED, 0xE248, 0x91EE, 0xE249, 0x91EF, 0xE24A, 0x91F0, 0xE24B, 0x91F1, + 0xE24C, 0x91F2, 0xE24D, 0x91F3, 0xE24E, 0x91F4, 0xE24F, 0x91F5, 0xE250, 0x91F6, 0xE251, 0x91F7, 0xE252, 0x91F8, 0xE253, 0x91F9, + 0xE254, 0x91FA, 0xE255, 0x91FB, 0xE256, 0x91FC, 0xE257, 0x91FD, 0xE258, 0x91FE, 0xE259, 0x91FF, 0xE25A, 0x9200, 0xE25B, 0x9201, + 0xE25C, 0x9202, 0xE25D, 0x9203, 0xE25E, 0x9204, 0xE25F, 0x9205, 0xE260, 0x9206, 0xE261, 0x9207, 0xE262, 0x9208, 0xE263, 0x9209, + 0xE264, 0x920A, 0xE265, 0x920B, 0xE266, 0x920C, 0xE267, 0x920D, 0xE268, 0x920E, 0xE269, 0x920F, 0xE26A, 0x9210, 0xE26B, 0x9211, + 0xE26C, 0x9212, 0xE26D, 0x9213, 0xE26E, 0x9214, 0xE26F, 0x9215, 0xE270, 0x9216, 0xE271, 0x9217, 0xE272, 0x9218, 0xE273, 0x9219, + 0xE274, 0x921A, 0xE275, 0x921B, 0xE276, 0x921C, 0xE277, 0x921D, 0xE278, 0x921E, 0xE279, 0x921F, 0xE27A, 0x9220, 0xE27B, 0x9221, + 0xE27C, 0x9222, 0xE27D, 0x9223, 0xE27E, 0x9224, 0xE280, 0x9225, 0xE281, 0x9226, 0xE282, 0x9227, 0xE283, 0x9228, 0xE284, 0x9229, + 0xE285, 0x922A, 0xE286, 0x922B, 0xE287, 0x922C, 0xE288, 0x922D, 0xE289, 0x922E, 0xE28A, 0x922F, 0xE28B, 0x9230, 0xE28C, 0x9231, + 0xE28D, 0x9232, 0xE28E, 0x9233, 0xE28F, 0x9234, 0xE290, 0x9235, 0xE291, 0x9236, 0xE292, 0x9237, 0xE293, 0x9238, 0xE294, 0x9239, + 0xE295, 0x923A, 0xE296, 0x923B, 0xE297, 0x923C, 0xE298, 0x923D, 0xE299, 0x923E, 0xE29A, 0x923F, 0xE29B, 0x9240, 0xE29C, 0x9241, + 0xE29D, 0x9242, 0xE29E, 0x9243, 0xE29F, 0x9244, 0xE2A0, 0x9245, 0xE2A1, 0x72FB, 0xE2A2, 0x7317, 0xE2A3, 0x7313, 0xE2A4, 0x7321, + 0xE2A5, 0x730A, 0xE2A6, 0x731E, 0xE2A7, 0x731D, 0xE2A8, 0x7315, 0xE2A9, 0x7322, 0xE2AA, 0x7339, 0xE2AB, 0x7325, 0xE2AC, 0x732C, + 0xE2AD, 0x7338, 0xE2AE, 0x7331, 0xE2AF, 0x7350, 0xE2B0, 0x734D, 0xE2B1, 0x7357, 0xE2B2, 0x7360, 0xE2B3, 0x736C, 0xE2B4, 0x736F, + 0xE2B5, 0x737E, 0xE2B6, 0x821B, 0xE2B7, 0x5925, 0xE2B8, 0x98E7, 0xE2B9, 0x5924, 0xE2BA, 0x5902, 0xE2BB, 0x9963, 0xE2BC, 0x9967, + 0xE2BD, 0x9968, 0xE2BE, 0x9969, 0xE2BF, 0x996A, 0xE2C0, 0x996B, 0xE2C1, 0x996C, 0xE2C2, 0x9974, 0xE2C3, 0x9977, 0xE2C4, 0x997D, + 0xE2C5, 0x9980, 0xE2C6, 0x9984, 0xE2C7, 0x9987, 0xE2C8, 0x998A, 0xE2C9, 0x998D, 0xE2CA, 0x9990, 0xE2CB, 0x9991, 0xE2CC, 0x9993, + 0xE2CD, 0x9994, 0xE2CE, 0x9995, 0xE2CF, 0x5E80, 0xE2D0, 0x5E91, 0xE2D1, 0x5E8B, 0xE2D2, 0x5E96, 0xE2D3, 0x5EA5, 0xE2D4, 0x5EA0, + 0xE2D5, 0x5EB9, 0xE2D6, 0x5EB5, 0xE2D7, 0x5EBE, 0xE2D8, 0x5EB3, 0xE2D9, 0x8D53, 0xE2DA, 0x5ED2, 0xE2DB, 0x5ED1, 0xE2DC, 0x5EDB, + 0xE2DD, 0x5EE8, 0xE2DE, 0x5EEA, 0xE2DF, 0x81BA, 0xE2E0, 0x5FC4, 0xE2E1, 0x5FC9, 0xE2E2, 0x5FD6, 0xE2E3, 0x5FCF, 0xE2E4, 0x6003, + 0xE2E5, 0x5FEE, 0xE2E6, 0x6004, 0xE2E7, 0x5FE1, 0xE2E8, 0x5FE4, 0xE2E9, 0x5FFE, 0xE2EA, 0x6005, 0xE2EB, 0x6006, 0xE2EC, 0x5FEA, + 0xE2ED, 0x5FED, 0xE2EE, 0x5FF8, 0xE2EF, 0x6019, 0xE2F0, 0x6035, 0xE2F1, 0x6026, 0xE2F2, 0x601B, 0xE2F3, 0x600F, 0xE2F4, 0x600D, + 0xE2F5, 0x6029, 0xE2F6, 0x602B, 0xE2F7, 0x600A, 0xE2F8, 0x603F, 0xE2F9, 0x6021, 0xE2FA, 0x6078, 0xE2FB, 0x6079, 0xE2FC, 0x607B, + 0xE2FD, 0x607A, 0xE2FE, 0x6042, 0xE340, 0x9246, 0xE341, 0x9247, 0xE342, 0x9248, 0xE343, 0x9249, 0xE344, 0x924A, 0xE345, 0x924B, + 0xE346, 0x924C, 0xE347, 0x924D, 0xE348, 0x924E, 0xE349, 0x924F, 0xE34A, 0x9250, 0xE34B, 0x9251, 0xE34C, 0x9252, 0xE34D, 0x9253, + 0xE34E, 0x9254, 0xE34F, 0x9255, 0xE350, 0x9256, 0xE351, 0x9257, 0xE352, 0x9258, 0xE353, 0x9259, 0xE354, 0x925A, 0xE355, 0x925B, + 0xE356, 0x925C, 0xE357, 0x925D, 0xE358, 0x925E, 0xE359, 0x925F, 0xE35A, 0x9260, 0xE35B, 0x9261, 0xE35C, 0x9262, 0xE35D, 0x9263, + 0xE35E, 0x9264, 0xE35F, 0x9265, 0xE360, 0x9266, 0xE361, 0x9267, 0xE362, 0x9268, 0xE363, 0x9269, 0xE364, 0x926A, 0xE365, 0x926B, + 0xE366, 0x926C, 0xE367, 0x926D, 0xE368, 0x926E, 0xE369, 0x926F, 0xE36A, 0x9270, 0xE36B, 0x9271, 0xE36C, 0x9272, 0xE36D, 0x9273, + 0xE36E, 0x9275, 0xE36F, 0x9276, 0xE370, 0x9277, 0xE371, 0x9278, 0xE372, 0x9279, 0xE373, 0x927A, 0xE374, 0x927B, 0xE375, 0x927C, + 0xE376, 0x927D, 0xE377, 0x927E, 0xE378, 0x927F, 0xE379, 0x9280, 0xE37A, 0x9281, 0xE37B, 0x9282, 0xE37C, 0x9283, 0xE37D, 0x9284, + 0xE37E, 0x9285, 0xE380, 0x9286, 0xE381, 0x9287, 0xE382, 0x9288, 0xE383, 0x9289, 0xE384, 0x928A, 0xE385, 0x928B, 0xE386, 0x928C, + 0xE387, 0x928D, 0xE388, 0x928F, 0xE389, 0x9290, 0xE38A, 0x9291, 0xE38B, 0x9292, 0xE38C, 0x9293, 0xE38D, 0x9294, 0xE38E, 0x9295, + 0xE38F, 0x9296, 0xE390, 0x9297, 0xE391, 0x9298, 0xE392, 0x9299, 0xE393, 0x929A, 0xE394, 0x929B, 0xE395, 0x929C, 0xE396, 0x929D, + 0xE397, 0x929E, 0xE398, 0x929F, 0xE399, 0x92A0, 0xE39A, 0x92A1, 0xE39B, 0x92A2, 0xE39C, 0x92A3, 0xE39D, 0x92A4, 0xE39E, 0x92A5, + 0xE39F, 0x92A6, 0xE3A0, 0x92A7, 0xE3A1, 0x606A, 0xE3A2, 0x607D, 0xE3A3, 0x6096, 0xE3A4, 0x609A, 0xE3A5, 0x60AD, 0xE3A6, 0x609D, + 0xE3A7, 0x6083, 0xE3A8, 0x6092, 0xE3A9, 0x608C, 0xE3AA, 0x609B, 0xE3AB, 0x60EC, 0xE3AC, 0x60BB, 0xE3AD, 0x60B1, 0xE3AE, 0x60DD, + 0xE3AF, 0x60D8, 0xE3B0, 0x60C6, 0xE3B1, 0x60DA, 0xE3B2, 0x60B4, 0xE3B3, 0x6120, 0xE3B4, 0x6126, 0xE3B5, 0x6115, 0xE3B6, 0x6123, + 0xE3B7, 0x60F4, 0xE3B8, 0x6100, 0xE3B9, 0x610E, 0xE3BA, 0x612B, 0xE3BB, 0x614A, 0xE3BC, 0x6175, 0xE3BD, 0x61AC, 0xE3BE, 0x6194, + 0xE3BF, 0x61A7, 0xE3C0, 0x61B7, 0xE3C1, 0x61D4, 0xE3C2, 0x61F5, 0xE3C3, 0x5FDD, 0xE3C4, 0x96B3, 0xE3C5, 0x95E9, 0xE3C6, 0x95EB, + 0xE3C7, 0x95F1, 0xE3C8, 0x95F3, 0xE3C9, 0x95F5, 0xE3CA, 0x95F6, 0xE3CB, 0x95FC, 0xE3CC, 0x95FE, 0xE3CD, 0x9603, 0xE3CE, 0x9604, + 0xE3CF, 0x9606, 0xE3D0, 0x9608, 0xE3D1, 0x960A, 0xE3D2, 0x960B, 0xE3D3, 0x960C, 0xE3D4, 0x960D, 0xE3D5, 0x960F, 0xE3D6, 0x9612, + 0xE3D7, 0x9615, 0xE3D8, 0x9616, 0xE3D9, 0x9617, 0xE3DA, 0x9619, 0xE3DB, 0x961A, 0xE3DC, 0x4E2C, 0xE3DD, 0x723F, 0xE3DE, 0x6215, + 0xE3DF, 0x6C35, 0xE3E0, 0x6C54, 0xE3E1, 0x6C5C, 0xE3E2, 0x6C4A, 0xE3E3, 0x6CA3, 0xE3E4, 0x6C85, 0xE3E5, 0x6C90, 0xE3E6, 0x6C94, + 0xE3E7, 0x6C8C, 0xE3E8, 0x6C68, 0xE3E9, 0x6C69, 0xE3EA, 0x6C74, 0xE3EB, 0x6C76, 0xE3EC, 0x6C86, 0xE3ED, 0x6CA9, 0xE3EE, 0x6CD0, + 0xE3EF, 0x6CD4, 0xE3F0, 0x6CAD, 0xE3F1, 0x6CF7, 0xE3F2, 0x6CF8, 0xE3F3, 0x6CF1, 0xE3F4, 0x6CD7, 0xE3F5, 0x6CB2, 0xE3F6, 0x6CE0, + 0xE3F7, 0x6CD6, 0xE3F8, 0x6CFA, 0xE3F9, 0x6CEB, 0xE3FA, 0x6CEE, 0xE3FB, 0x6CB1, 0xE3FC, 0x6CD3, 0xE3FD, 0x6CEF, 0xE3FE, 0x6CFE, + 0xE440, 0x92A8, 0xE441, 0x92A9, 0xE442, 0x92AA, 0xE443, 0x92AB, 0xE444, 0x92AC, 0xE445, 0x92AD, 0xE446, 0x92AF, 0xE447, 0x92B0, + 0xE448, 0x92B1, 0xE449, 0x92B2, 0xE44A, 0x92B3, 0xE44B, 0x92B4, 0xE44C, 0x92B5, 0xE44D, 0x92B6, 0xE44E, 0x92B7, 0xE44F, 0x92B8, + 0xE450, 0x92B9, 0xE451, 0x92BA, 0xE452, 0x92BB, 0xE453, 0x92BC, 0xE454, 0x92BD, 0xE455, 0x92BE, 0xE456, 0x92BF, 0xE457, 0x92C0, + 0xE458, 0x92C1, 0xE459, 0x92C2, 0xE45A, 0x92C3, 0xE45B, 0x92C4, 0xE45C, 0x92C5, 0xE45D, 0x92C6, 0xE45E, 0x92C7, 0xE45F, 0x92C9, + 0xE460, 0x92CA, 0xE461, 0x92CB, 0xE462, 0x92CC, 0xE463, 0x92CD, 0xE464, 0x92CE, 0xE465, 0x92CF, 0xE466, 0x92D0, 0xE467, 0x92D1, + 0xE468, 0x92D2, 0xE469, 0x92D3, 0xE46A, 0x92D4, 0xE46B, 0x92D5, 0xE46C, 0x92D6, 0xE46D, 0x92D7, 0xE46E, 0x92D8, 0xE46F, 0x92D9, + 0xE470, 0x92DA, 0xE471, 0x92DB, 0xE472, 0x92DC, 0xE473, 0x92DD, 0xE474, 0x92DE, 0xE475, 0x92DF, 0xE476, 0x92E0, 0xE477, 0x92E1, + 0xE478, 0x92E2, 0xE479, 0x92E3, 0xE47A, 0x92E4, 0xE47B, 0x92E5, 0xE47C, 0x92E6, 0xE47D, 0x92E7, 0xE47E, 0x92E8, 0xE480, 0x92E9, + 0xE481, 0x92EA, 0xE482, 0x92EB, 0xE483, 0x92EC, 0xE484, 0x92ED, 0xE485, 0x92EE, 0xE486, 0x92EF, 0xE487, 0x92F0, 0xE488, 0x92F1, + 0xE489, 0x92F2, 0xE48A, 0x92F3, 0xE48B, 0x92F4, 0xE48C, 0x92F5, 0xE48D, 0x92F6, 0xE48E, 0x92F7, 0xE48F, 0x92F8, 0xE490, 0x92F9, + 0xE491, 0x92FA, 0xE492, 0x92FB, 0xE493, 0x92FC, 0xE494, 0x92FD, 0xE495, 0x92FE, 0xE496, 0x92FF, 0xE497, 0x9300, 0xE498, 0x9301, + 0xE499, 0x9302, 0xE49A, 0x9303, 0xE49B, 0x9304, 0xE49C, 0x9305, 0xE49D, 0x9306, 0xE49E, 0x9307, 0xE49F, 0x9308, 0xE4A0, 0x9309, + 0xE4A1, 0x6D39, 0xE4A2, 0x6D27, 0xE4A3, 0x6D0C, 0xE4A4, 0x6D43, 0xE4A5, 0x6D48, 0xE4A6, 0x6D07, 0xE4A7, 0x6D04, 0xE4A8, 0x6D19, + 0xE4A9, 0x6D0E, 0xE4AA, 0x6D2B, 0xE4AB, 0x6D4D, 0xE4AC, 0x6D2E, 0xE4AD, 0x6D35, 0xE4AE, 0x6D1A, 0xE4AF, 0x6D4F, 0xE4B0, 0x6D52, + 0xE4B1, 0x6D54, 0xE4B2, 0x6D33, 0xE4B3, 0x6D91, 0xE4B4, 0x6D6F, 0xE4B5, 0x6D9E, 0xE4B6, 0x6DA0, 0xE4B7, 0x6D5E, 0xE4B8, 0x6D93, + 0xE4B9, 0x6D94, 0xE4BA, 0x6D5C, 0xE4BB, 0x6D60, 0xE4BC, 0x6D7C, 0xE4BD, 0x6D63, 0xE4BE, 0x6E1A, 0xE4BF, 0x6DC7, 0xE4C0, 0x6DC5, + 0xE4C1, 0x6DDE, 0xE4C2, 0x6E0E, 0xE4C3, 0x6DBF, 0xE4C4, 0x6DE0, 0xE4C5, 0x6E11, 0xE4C6, 0x6DE6, 0xE4C7, 0x6DDD, 0xE4C8, 0x6DD9, + 0xE4C9, 0x6E16, 0xE4CA, 0x6DAB, 0xE4CB, 0x6E0C, 0xE4CC, 0x6DAE, 0xE4CD, 0x6E2B, 0xE4CE, 0x6E6E, 0xE4CF, 0x6E4E, 0xE4D0, 0x6E6B, + 0xE4D1, 0x6EB2, 0xE4D2, 0x6E5F, 0xE4D3, 0x6E86, 0xE4D4, 0x6E53, 0xE4D5, 0x6E54, 0xE4D6, 0x6E32, 0xE4D7, 0x6E25, 0xE4D8, 0x6E44, + 0xE4D9, 0x6EDF, 0xE4DA, 0x6EB1, 0xE4DB, 0x6E98, 0xE4DC, 0x6EE0, 0xE4DD, 0x6F2D, 0xE4DE, 0x6EE2, 0xE4DF, 0x6EA5, 0xE4E0, 0x6EA7, + 0xE4E1, 0x6EBD, 0xE4E2, 0x6EBB, 0xE4E3, 0x6EB7, 0xE4E4, 0x6ED7, 0xE4E5, 0x6EB4, 0xE4E6, 0x6ECF, 0xE4E7, 0x6E8F, 0xE4E8, 0x6EC2, + 0xE4E9, 0x6E9F, 0xE4EA, 0x6F62, 0xE4EB, 0x6F46, 0xE4EC, 0x6F47, 0xE4ED, 0x6F24, 0xE4EE, 0x6F15, 0xE4EF, 0x6EF9, 0xE4F0, 0x6F2F, + 0xE4F1, 0x6F36, 0xE4F2, 0x6F4B, 0xE4F3, 0x6F74, 0xE4F4, 0x6F2A, 0xE4F5, 0x6F09, 0xE4F6, 0x6F29, 0xE4F7, 0x6F89, 0xE4F8, 0x6F8D, + 0xE4F9, 0x6F8C, 0xE4FA, 0x6F78, 0xE4FB, 0x6F72, 0xE4FC, 0x6F7C, 0xE4FD, 0x6F7A, 0xE4FE, 0x6FD1, 0xE540, 0x930A, 0xE541, 0x930B, + 0xE542, 0x930C, 0xE543, 0x930D, 0xE544, 0x930E, 0xE545, 0x930F, 0xE546, 0x9310, 0xE547, 0x9311, 0xE548, 0x9312, 0xE549, 0x9313, + 0xE54A, 0x9314, 0xE54B, 0x9315, 0xE54C, 0x9316, 0xE54D, 0x9317, 0xE54E, 0x9318, 0xE54F, 0x9319, 0xE550, 0x931A, 0xE551, 0x931B, + 0xE552, 0x931C, 0xE553, 0x931D, 0xE554, 0x931E, 0xE555, 0x931F, 0xE556, 0x9320, 0xE557, 0x9321, 0xE558, 0x9322, 0xE559, 0x9323, + 0xE55A, 0x9324, 0xE55B, 0x9325, 0xE55C, 0x9326, 0xE55D, 0x9327, 0xE55E, 0x9328, 0xE55F, 0x9329, 0xE560, 0x932A, 0xE561, 0x932B, + 0xE562, 0x932C, 0xE563, 0x932D, 0xE564, 0x932E, 0xE565, 0x932F, 0xE566, 0x9330, 0xE567, 0x9331, 0xE568, 0x9332, 0xE569, 0x9333, + 0xE56A, 0x9334, 0xE56B, 0x9335, 0xE56C, 0x9336, 0xE56D, 0x9337, 0xE56E, 0x9338, 0xE56F, 0x9339, 0xE570, 0x933A, 0xE571, 0x933B, + 0xE572, 0x933C, 0xE573, 0x933D, 0xE574, 0x933F, 0xE575, 0x9340, 0xE576, 0x9341, 0xE577, 0x9342, 0xE578, 0x9343, 0xE579, 0x9344, + 0xE57A, 0x9345, 0xE57B, 0x9346, 0xE57C, 0x9347, 0xE57D, 0x9348, 0xE57E, 0x9349, 0xE580, 0x934A, 0xE581, 0x934B, 0xE582, 0x934C, + 0xE583, 0x934D, 0xE584, 0x934E, 0xE585, 0x934F, 0xE586, 0x9350, 0xE587, 0x9351, 0xE588, 0x9352, 0xE589, 0x9353, 0xE58A, 0x9354, + 0xE58B, 0x9355, 0xE58C, 0x9356, 0xE58D, 0x9357, 0xE58E, 0x9358, 0xE58F, 0x9359, 0xE590, 0x935A, 0xE591, 0x935B, 0xE592, 0x935C, + 0xE593, 0x935D, 0xE594, 0x935E, 0xE595, 0x935F, 0xE596, 0x9360, 0xE597, 0x9361, 0xE598, 0x9362, 0xE599, 0x9363, 0xE59A, 0x9364, + 0xE59B, 0x9365, 0xE59C, 0x9366, 0xE59D, 0x9367, 0xE59E, 0x9368, 0xE59F, 0x9369, 0xE5A0, 0x936B, 0xE5A1, 0x6FC9, 0xE5A2, 0x6FA7, + 0xE5A3, 0x6FB9, 0xE5A4, 0x6FB6, 0xE5A5, 0x6FC2, 0xE5A6, 0x6FE1, 0xE5A7, 0x6FEE, 0xE5A8, 0x6FDE, 0xE5A9, 0x6FE0, 0xE5AA, 0x6FEF, + 0xE5AB, 0x701A, 0xE5AC, 0x7023, 0xE5AD, 0x701B, 0xE5AE, 0x7039, 0xE5AF, 0x7035, 0xE5B0, 0x704F, 0xE5B1, 0x705E, 0xE5B2, 0x5B80, + 0xE5B3, 0x5B84, 0xE5B4, 0x5B95, 0xE5B5, 0x5B93, 0xE5B6, 0x5BA5, 0xE5B7, 0x5BB8, 0xE5B8, 0x752F, 0xE5B9, 0x9A9E, 0xE5BA, 0x6434, + 0xE5BB, 0x5BE4, 0xE5BC, 0x5BEE, 0xE5BD, 0x8930, 0xE5BE, 0x5BF0, 0xE5BF, 0x8E47, 0xE5C0, 0x8B07, 0xE5C1, 0x8FB6, 0xE5C2, 0x8FD3, + 0xE5C3, 0x8FD5, 0xE5C4, 0x8FE5, 0xE5C5, 0x8FEE, 0xE5C6, 0x8FE4, 0xE5C7, 0x8FE9, 0xE5C8, 0x8FE6, 0xE5C9, 0x8FF3, 0xE5CA, 0x8FE8, + 0xE5CB, 0x9005, 0xE5CC, 0x9004, 0xE5CD, 0x900B, 0xE5CE, 0x9026, 0xE5CF, 0x9011, 0xE5D0, 0x900D, 0xE5D1, 0x9016, 0xE5D2, 0x9021, + 0xE5D3, 0x9035, 0xE5D4, 0x9036, 0xE5D5, 0x902D, 0xE5D6, 0x902F, 0xE5D7, 0x9044, 0xE5D8, 0x9051, 0xE5D9, 0x9052, 0xE5DA, 0x9050, + 0xE5DB, 0x9068, 0xE5DC, 0x9058, 0xE5DD, 0x9062, 0xE5DE, 0x905B, 0xE5DF, 0x66B9, 0xE5E0, 0x9074, 0xE5E1, 0x907D, 0xE5E2, 0x9082, + 0xE5E3, 0x9088, 0xE5E4, 0x9083, 0xE5E5, 0x908B, 0xE5E6, 0x5F50, 0xE5E7, 0x5F57, 0xE5E8, 0x5F56, 0xE5E9, 0x5F58, 0xE5EA, 0x5C3B, + 0xE5EB, 0x54AB, 0xE5EC, 0x5C50, 0xE5ED, 0x5C59, 0xE5EE, 0x5B71, 0xE5EF, 0x5C63, 0xE5F0, 0x5C66, 0xE5F1, 0x7FBC, 0xE5F2, 0x5F2A, + 0xE5F3, 0x5F29, 0xE5F4, 0x5F2D, 0xE5F5, 0x8274, 0xE5F6, 0x5F3C, 0xE5F7, 0x9B3B, 0xE5F8, 0x5C6E, 0xE5F9, 0x5981, 0xE5FA, 0x5983, + 0xE5FB, 0x598D, 0xE5FC, 0x59A9, 0xE5FD, 0x59AA, 0xE5FE, 0x59A3, 0xE640, 0x936C, 0xE641, 0x936D, 0xE642, 0x936E, 0xE643, 0x936F, + 0xE644, 0x9370, 0xE645, 0x9371, 0xE646, 0x9372, 0xE647, 0x9373, 0xE648, 0x9374, 0xE649, 0x9375, 0xE64A, 0x9376, 0xE64B, 0x9377, + 0xE64C, 0x9378, 0xE64D, 0x9379, 0xE64E, 0x937A, 0xE64F, 0x937B, 0xE650, 0x937C, 0xE651, 0x937D, 0xE652, 0x937E, 0xE653, 0x937F, + 0xE654, 0x9380, 0xE655, 0x9381, 0xE656, 0x9382, 0xE657, 0x9383, 0xE658, 0x9384, 0xE659, 0x9385, 0xE65A, 0x9386, 0xE65B, 0x9387, + 0xE65C, 0x9388, 0xE65D, 0x9389, 0xE65E, 0x938A, 0xE65F, 0x938B, 0xE660, 0x938C, 0xE661, 0x938D, 0xE662, 0x938E, 0xE663, 0x9390, + 0xE664, 0x9391, 0xE665, 0x9392, 0xE666, 0x9393, 0xE667, 0x9394, 0xE668, 0x9395, 0xE669, 0x9396, 0xE66A, 0x9397, 0xE66B, 0x9398, + 0xE66C, 0x9399, 0xE66D, 0x939A, 0xE66E, 0x939B, 0xE66F, 0x939C, 0xE670, 0x939D, 0xE671, 0x939E, 0xE672, 0x939F, 0xE673, 0x93A0, + 0xE674, 0x93A1, 0xE675, 0x93A2, 0xE676, 0x93A3, 0xE677, 0x93A4, 0xE678, 0x93A5, 0xE679, 0x93A6, 0xE67A, 0x93A7, 0xE67B, 0x93A8, + 0xE67C, 0x93A9, 0xE67D, 0x93AA, 0xE67E, 0x93AB, 0xE680, 0x93AC, 0xE681, 0x93AD, 0xE682, 0x93AE, 0xE683, 0x93AF, 0xE684, 0x93B0, + 0xE685, 0x93B1, 0xE686, 0x93B2, 0xE687, 0x93B3, 0xE688, 0x93B4, 0xE689, 0x93B5, 0xE68A, 0x93B6, 0xE68B, 0x93B7, 0xE68C, 0x93B8, + 0xE68D, 0x93B9, 0xE68E, 0x93BA, 0xE68F, 0x93BB, 0xE690, 0x93BC, 0xE691, 0x93BD, 0xE692, 0x93BE, 0xE693, 0x93BF, 0xE694, 0x93C0, + 0xE695, 0x93C1, 0xE696, 0x93C2, 0xE697, 0x93C3, 0xE698, 0x93C4, 0xE699, 0x93C5, 0xE69A, 0x93C6, 0xE69B, 0x93C7, 0xE69C, 0x93C8, + 0xE69D, 0x93C9, 0xE69E, 0x93CB, 0xE69F, 0x93CC, 0xE6A0, 0x93CD, 0xE6A1, 0x5997, 0xE6A2, 0x59CA, 0xE6A3, 0x59AB, 0xE6A4, 0x599E, + 0xE6A5, 0x59A4, 0xE6A6, 0x59D2, 0xE6A7, 0x59B2, 0xE6A8, 0x59AF, 0xE6A9, 0x59D7, 0xE6AA, 0x59BE, 0xE6AB, 0x5A05, 0xE6AC, 0x5A06, + 0xE6AD, 0x59DD, 0xE6AE, 0x5A08, 0xE6AF, 0x59E3, 0xE6B0, 0x59D8, 0xE6B1, 0x59F9, 0xE6B2, 0x5A0C, 0xE6B3, 0x5A09, 0xE6B4, 0x5A32, + 0xE6B5, 0x5A34, 0xE6B6, 0x5A11, 0xE6B7, 0x5A23, 0xE6B8, 0x5A13, 0xE6B9, 0x5A40, 0xE6BA, 0x5A67, 0xE6BB, 0x5A4A, 0xE6BC, 0x5A55, + 0xE6BD, 0x5A3C, 0xE6BE, 0x5A62, 0xE6BF, 0x5A75, 0xE6C0, 0x80EC, 0xE6C1, 0x5AAA, 0xE6C2, 0x5A9B, 0xE6C3, 0x5A77, 0xE6C4, 0x5A7A, + 0xE6C5, 0x5ABE, 0xE6C6, 0x5AEB, 0xE6C7, 0x5AB2, 0xE6C8, 0x5AD2, 0xE6C9, 0x5AD4, 0xE6CA, 0x5AB8, 0xE6CB, 0x5AE0, 0xE6CC, 0x5AE3, + 0xE6CD, 0x5AF1, 0xE6CE, 0x5AD6, 0xE6CF, 0x5AE6, 0xE6D0, 0x5AD8, 0xE6D1, 0x5ADC, 0xE6D2, 0x5B09, 0xE6D3, 0x5B17, 0xE6D4, 0x5B16, + 0xE6D5, 0x5B32, 0xE6D6, 0x5B37, 0xE6D7, 0x5B40, 0xE6D8, 0x5C15, 0xE6D9, 0x5C1C, 0xE6DA, 0x5B5A, 0xE6DB, 0x5B65, 0xE6DC, 0x5B73, + 0xE6DD, 0x5B51, 0xE6DE, 0x5B53, 0xE6DF, 0x5B62, 0xE6E0, 0x9A75, 0xE6E1, 0x9A77, 0xE6E2, 0x9A78, 0xE6E3, 0x9A7A, 0xE6E4, 0x9A7F, + 0xE6E5, 0x9A7D, 0xE6E6, 0x9A80, 0xE6E7, 0x9A81, 0xE6E8, 0x9A85, 0xE6E9, 0x9A88, 0xE6EA, 0x9A8A, 0xE6EB, 0x9A90, 0xE6EC, 0x9A92, + 0xE6ED, 0x9A93, 0xE6EE, 0x9A96, 0xE6EF, 0x9A98, 0xE6F0, 0x9A9B, 0xE6F1, 0x9A9C, 0xE6F2, 0x9A9D, 0xE6F3, 0x9A9F, 0xE6F4, 0x9AA0, + 0xE6F5, 0x9AA2, 0xE6F6, 0x9AA3, 0xE6F7, 0x9AA5, 0xE6F8, 0x9AA7, 0xE6F9, 0x7E9F, 0xE6FA, 0x7EA1, 0xE6FB, 0x7EA3, 0xE6FC, 0x7EA5, + 0xE6FD, 0x7EA8, 0xE6FE, 0x7EA9, 0xE740, 0x93CE, 0xE741, 0x93CF, 0xE742, 0x93D0, 0xE743, 0x93D1, 0xE744, 0x93D2, 0xE745, 0x93D3, + 0xE746, 0x93D4, 0xE747, 0x93D5, 0xE748, 0x93D7, 0xE749, 0x93D8, 0xE74A, 0x93D9, 0xE74B, 0x93DA, 0xE74C, 0x93DB, 0xE74D, 0x93DC, + 0xE74E, 0x93DD, 0xE74F, 0x93DE, 0xE750, 0x93DF, 0xE751, 0x93E0, 0xE752, 0x93E1, 0xE753, 0x93E2, 0xE754, 0x93E3, 0xE755, 0x93E4, + 0xE756, 0x93E5, 0xE757, 0x93E6, 0xE758, 0x93E7, 0xE759, 0x93E8, 0xE75A, 0x93E9, 0xE75B, 0x93EA, 0xE75C, 0x93EB, 0xE75D, 0x93EC, + 0xE75E, 0x93ED, 0xE75F, 0x93EE, 0xE760, 0x93EF, 0xE761, 0x93F0, 0xE762, 0x93F1, 0xE763, 0x93F2, 0xE764, 0x93F3, 0xE765, 0x93F4, + 0xE766, 0x93F5, 0xE767, 0x93F6, 0xE768, 0x93F7, 0xE769, 0x93F8, 0xE76A, 0x93F9, 0xE76B, 0x93FA, 0xE76C, 0x93FB, 0xE76D, 0x93FC, + 0xE76E, 0x93FD, 0xE76F, 0x93FE, 0xE770, 0x93FF, 0xE771, 0x9400, 0xE772, 0x9401, 0xE773, 0x9402, 0xE774, 0x9403, 0xE775, 0x9404, + 0xE776, 0x9405, 0xE777, 0x9406, 0xE778, 0x9407, 0xE779, 0x9408, 0xE77A, 0x9409, 0xE77B, 0x940A, 0xE77C, 0x940B, 0xE77D, 0x940C, + 0xE77E, 0x940D, 0xE780, 0x940E, 0xE781, 0x940F, 0xE782, 0x9410, 0xE783, 0x9411, 0xE784, 0x9412, 0xE785, 0x9413, 0xE786, 0x9414, + 0xE787, 0x9415, 0xE788, 0x9416, 0xE789, 0x9417, 0xE78A, 0x9418, 0xE78B, 0x9419, 0xE78C, 0x941A, 0xE78D, 0x941B, 0xE78E, 0x941C, + 0xE78F, 0x941D, 0xE790, 0x941E, 0xE791, 0x941F, 0xE792, 0x9420, 0xE793, 0x9421, 0xE794, 0x9422, 0xE795, 0x9423, 0xE796, 0x9424, + 0xE797, 0x9425, 0xE798, 0x9426, 0xE799, 0x9427, 0xE79A, 0x9428, 0xE79B, 0x9429, 0xE79C, 0x942A, 0xE79D, 0x942B, 0xE79E, 0x942C, + 0xE79F, 0x942D, 0xE7A0, 0x942E, 0xE7A1, 0x7EAD, 0xE7A2, 0x7EB0, 0xE7A3, 0x7EBE, 0xE7A4, 0x7EC0, 0xE7A5, 0x7EC1, 0xE7A6, 0x7EC2, + 0xE7A7, 0x7EC9, 0xE7A8, 0x7ECB, 0xE7A9, 0x7ECC, 0xE7AA, 0x7ED0, 0xE7AB, 0x7ED4, 0xE7AC, 0x7ED7, 0xE7AD, 0x7EDB, 0xE7AE, 0x7EE0, + 0xE7AF, 0x7EE1, 0xE7B0, 0x7EE8, 0xE7B1, 0x7EEB, 0xE7B2, 0x7EEE, 0xE7B3, 0x7EEF, 0xE7B4, 0x7EF1, 0xE7B5, 0x7EF2, 0xE7B6, 0x7F0D, + 0xE7B7, 0x7EF6, 0xE7B8, 0x7EFA, 0xE7B9, 0x7EFB, 0xE7BA, 0x7EFE, 0xE7BB, 0x7F01, 0xE7BC, 0x7F02, 0xE7BD, 0x7F03, 0xE7BE, 0x7F07, + 0xE7BF, 0x7F08, 0xE7C0, 0x7F0B, 0xE7C1, 0x7F0C, 0xE7C2, 0x7F0F, 0xE7C3, 0x7F11, 0xE7C4, 0x7F12, 0xE7C5, 0x7F17, 0xE7C6, 0x7F19, + 0xE7C7, 0x7F1C, 0xE7C8, 0x7F1B, 0xE7C9, 0x7F1F, 0xE7CA, 0x7F21, 0xE7CB, 0x7F22, 0xE7CC, 0x7F23, 0xE7CD, 0x7F24, 0xE7CE, 0x7F25, + 0xE7CF, 0x7F26, 0xE7D0, 0x7F27, 0xE7D1, 0x7F2A, 0xE7D2, 0x7F2B, 0xE7D3, 0x7F2C, 0xE7D4, 0x7F2D, 0xE7D5, 0x7F2F, 0xE7D6, 0x7F30, + 0xE7D7, 0x7F31, 0xE7D8, 0x7F32, 0xE7D9, 0x7F33, 0xE7DA, 0x7F35, 0xE7DB, 0x5E7A, 0xE7DC, 0x757F, 0xE7DD, 0x5DDB, 0xE7DE, 0x753E, + 0xE7DF, 0x9095, 0xE7E0, 0x738E, 0xE7E1, 0x7391, 0xE7E2, 0x73AE, 0xE7E3, 0x73A2, 0xE7E4, 0x739F, 0xE7E5, 0x73CF, 0xE7E6, 0x73C2, + 0xE7E7, 0x73D1, 0xE7E8, 0x73B7, 0xE7E9, 0x73B3, 0xE7EA, 0x73C0, 0xE7EB, 0x73C9, 0xE7EC, 0x73C8, 0xE7ED, 0x73E5, 0xE7EE, 0x73D9, + 0xE7EF, 0x987C, 0xE7F0, 0x740A, 0xE7F1, 0x73E9, 0xE7F2, 0x73E7, 0xE7F3, 0x73DE, 0xE7F4, 0x73BA, 0xE7F5, 0x73F2, 0xE7F6, 0x740F, + 0xE7F7, 0x742A, 0xE7F8, 0x745B, 0xE7F9, 0x7426, 0xE7FA, 0x7425, 0xE7FB, 0x7428, 0xE7FC, 0x7430, 0xE7FD, 0x742E, 0xE7FE, 0x742C, + 0xE840, 0x942F, 0xE841, 0x9430, 0xE842, 0x9431, 0xE843, 0x9432, 0xE844, 0x9433, 0xE845, 0x9434, 0xE846, 0x9435, 0xE847, 0x9436, + 0xE848, 0x9437, 0xE849, 0x9438, 0xE84A, 0x9439, 0xE84B, 0x943A, 0xE84C, 0x943B, 0xE84D, 0x943C, 0xE84E, 0x943D, 0xE84F, 0x943F, + 0xE850, 0x9440, 0xE851, 0x9441, 0xE852, 0x9442, 0xE853, 0x9443, 0xE854, 0x9444, 0xE855, 0x9445, 0xE856, 0x9446, 0xE857, 0x9447, + 0xE858, 0x9448, 0xE859, 0x9449, 0xE85A, 0x944A, 0xE85B, 0x944B, 0xE85C, 0x944C, 0xE85D, 0x944D, 0xE85E, 0x944E, 0xE85F, 0x944F, + 0xE860, 0x9450, 0xE861, 0x9451, 0xE862, 0x9452, 0xE863, 0x9453, 0xE864, 0x9454, 0xE865, 0x9455, 0xE866, 0x9456, 0xE867, 0x9457, + 0xE868, 0x9458, 0xE869, 0x9459, 0xE86A, 0x945A, 0xE86B, 0x945B, 0xE86C, 0x945C, 0xE86D, 0x945D, 0xE86E, 0x945E, 0xE86F, 0x945F, + 0xE870, 0x9460, 0xE871, 0x9461, 0xE872, 0x9462, 0xE873, 0x9463, 0xE874, 0x9464, 0xE875, 0x9465, 0xE876, 0x9466, 0xE877, 0x9467, + 0xE878, 0x9468, 0xE879, 0x9469, 0xE87A, 0x946A, 0xE87B, 0x946C, 0xE87C, 0x946D, 0xE87D, 0x946E, 0xE87E, 0x946F, 0xE880, 0x9470, + 0xE881, 0x9471, 0xE882, 0x9472, 0xE883, 0x9473, 0xE884, 0x9474, 0xE885, 0x9475, 0xE886, 0x9476, 0xE887, 0x9477, 0xE888, 0x9478, + 0xE889, 0x9479, 0xE88A, 0x947A, 0xE88B, 0x947B, 0xE88C, 0x947C, 0xE88D, 0x947D, 0xE88E, 0x947E, 0xE88F, 0x947F, 0xE890, 0x9480, + 0xE891, 0x9481, 0xE892, 0x9482, 0xE893, 0x9483, 0xE894, 0x9484, 0xE895, 0x9491, 0xE896, 0x9496, 0xE897, 0x9498, 0xE898, 0x94C7, + 0xE899, 0x94CF, 0xE89A, 0x94D3, 0xE89B, 0x94D4, 0xE89C, 0x94DA, 0xE89D, 0x94E6, 0xE89E, 0x94FB, 0xE89F, 0x951C, 0xE8A0, 0x9520, + 0xE8A1, 0x741B, 0xE8A2, 0x741A, 0xE8A3, 0x7441, 0xE8A4, 0x745C, 0xE8A5, 0x7457, 0xE8A6, 0x7455, 0xE8A7, 0x7459, 0xE8A8, 0x7477, + 0xE8A9, 0x746D, 0xE8AA, 0x747E, 0xE8AB, 0x749C, 0xE8AC, 0x748E, 0xE8AD, 0x7480, 0xE8AE, 0x7481, 0xE8AF, 0x7487, 0xE8B0, 0x748B, + 0xE8B1, 0x749E, 0xE8B2, 0x74A8, 0xE8B3, 0x74A9, 0xE8B4, 0x7490, 0xE8B5, 0x74A7, 0xE8B6, 0x74D2, 0xE8B7, 0x74BA, 0xE8B8, 0x97EA, + 0xE8B9, 0x97EB, 0xE8BA, 0x97EC, 0xE8BB, 0x674C, 0xE8BC, 0x6753, 0xE8BD, 0x675E, 0xE8BE, 0x6748, 0xE8BF, 0x6769, 0xE8C0, 0x67A5, + 0xE8C1, 0x6787, 0xE8C2, 0x676A, 0xE8C3, 0x6773, 0xE8C4, 0x6798, 0xE8C5, 0x67A7, 0xE8C6, 0x6775, 0xE8C7, 0x67A8, 0xE8C8, 0x679E, + 0xE8C9, 0x67AD, 0xE8CA, 0x678B, 0xE8CB, 0x6777, 0xE8CC, 0x677C, 0xE8CD, 0x67F0, 0xE8CE, 0x6809, 0xE8CF, 0x67D8, 0xE8D0, 0x680A, + 0xE8D1, 0x67E9, 0xE8D2, 0x67B0, 0xE8D3, 0x680C, 0xE8D4, 0x67D9, 0xE8D5, 0x67B5, 0xE8D6, 0x67DA, 0xE8D7, 0x67B3, 0xE8D8, 0x67DD, + 0xE8D9, 0x6800, 0xE8DA, 0x67C3, 0xE8DB, 0x67B8, 0xE8DC, 0x67E2, 0xE8DD, 0x680E, 0xE8DE, 0x67C1, 0xE8DF, 0x67FD, 0xE8E0, 0x6832, + 0xE8E1, 0x6833, 0xE8E2, 0x6860, 0xE8E3, 0x6861, 0xE8E4, 0x684E, 0xE8E5, 0x6862, 0xE8E6, 0x6844, 0xE8E7, 0x6864, 0xE8E8, 0x6883, + 0xE8E9, 0x681D, 0xE8EA, 0x6855, 0xE8EB, 0x6866, 0xE8EC, 0x6841, 0xE8ED, 0x6867, 0xE8EE, 0x6840, 0xE8EF, 0x683E, 0xE8F0, 0x684A, + 0xE8F1, 0x6849, 0xE8F2, 0x6829, 0xE8F3, 0x68B5, 0xE8F4, 0x688F, 0xE8F5, 0x6874, 0xE8F6, 0x6877, 0xE8F7, 0x6893, 0xE8F8, 0x686B, + 0xE8F9, 0x68C2, 0xE8FA, 0x696E, 0xE8FB, 0x68FC, 0xE8FC, 0x691F, 0xE8FD, 0x6920, 0xE8FE, 0x68F9, 0xE940, 0x9527, 0xE941, 0x9533, + 0xE942, 0x953D, 0xE943, 0x9543, 0xE944, 0x9548, 0xE945, 0x954B, 0xE946, 0x9555, 0xE947, 0x955A, 0xE948, 0x9560, 0xE949, 0x956E, + 0xE94A, 0x9574, 0xE94B, 0x9575, 0xE94C, 0x9577, 0xE94D, 0x9578, 0xE94E, 0x9579, 0xE94F, 0x957A, 0xE950, 0x957B, 0xE951, 0x957C, + 0xE952, 0x957D, 0xE953, 0x957E, 0xE954, 0x9580, 0xE955, 0x9581, 0xE956, 0x9582, 0xE957, 0x9583, 0xE958, 0x9584, 0xE959, 0x9585, + 0xE95A, 0x9586, 0xE95B, 0x9587, 0xE95C, 0x9588, 0xE95D, 0x9589, 0xE95E, 0x958A, 0xE95F, 0x958B, 0xE960, 0x958C, 0xE961, 0x958D, + 0xE962, 0x958E, 0xE963, 0x958F, 0xE964, 0x9590, 0xE965, 0x9591, 0xE966, 0x9592, 0xE967, 0x9593, 0xE968, 0x9594, 0xE969, 0x9595, + 0xE96A, 0x9596, 0xE96B, 0x9597, 0xE96C, 0x9598, 0xE96D, 0x9599, 0xE96E, 0x959A, 0xE96F, 0x959B, 0xE970, 0x959C, 0xE971, 0x959D, + 0xE972, 0x959E, 0xE973, 0x959F, 0xE974, 0x95A0, 0xE975, 0x95A1, 0xE976, 0x95A2, 0xE977, 0x95A3, 0xE978, 0x95A4, 0xE979, 0x95A5, + 0xE97A, 0x95A6, 0xE97B, 0x95A7, 0xE97C, 0x95A8, 0xE97D, 0x95A9, 0xE97E, 0x95AA, 0xE980, 0x95AB, 0xE981, 0x95AC, 0xE982, 0x95AD, + 0xE983, 0x95AE, 0xE984, 0x95AF, 0xE985, 0x95B0, 0xE986, 0x95B1, 0xE987, 0x95B2, 0xE988, 0x95B3, 0xE989, 0x95B4, 0xE98A, 0x95B5, + 0xE98B, 0x95B6, 0xE98C, 0x95B7, 0xE98D, 0x95B8, 0xE98E, 0x95B9, 0xE98F, 0x95BA, 0xE990, 0x95BB, 0xE991, 0x95BC, 0xE992, 0x95BD, + 0xE993, 0x95BE, 0xE994, 0x95BF, 0xE995, 0x95C0, 0xE996, 0x95C1, 0xE997, 0x95C2, 0xE998, 0x95C3, 0xE999, 0x95C4, 0xE99A, 0x95C5, + 0xE99B, 0x95C6, 0xE99C, 0x95C7, 0xE99D, 0x95C8, 0xE99E, 0x95C9, 0xE99F, 0x95CA, 0xE9A0, 0x95CB, 0xE9A1, 0x6924, 0xE9A2, 0x68F0, + 0xE9A3, 0x690B, 0xE9A4, 0x6901, 0xE9A5, 0x6957, 0xE9A6, 0x68E3, 0xE9A7, 0x6910, 0xE9A8, 0x6971, 0xE9A9, 0x6939, 0xE9AA, 0x6960, + 0xE9AB, 0x6942, 0xE9AC, 0x695D, 0xE9AD, 0x6984, 0xE9AE, 0x696B, 0xE9AF, 0x6980, 0xE9B0, 0x6998, 0xE9B1, 0x6978, 0xE9B2, 0x6934, + 0xE9B3, 0x69CC, 0xE9B4, 0x6987, 0xE9B5, 0x6988, 0xE9B6, 0x69CE, 0xE9B7, 0x6989, 0xE9B8, 0x6966, 0xE9B9, 0x6963, 0xE9BA, 0x6979, + 0xE9BB, 0x699B, 0xE9BC, 0x69A7, 0xE9BD, 0x69BB, 0xE9BE, 0x69AB, 0xE9BF, 0x69AD, 0xE9C0, 0x69D4, 0xE9C1, 0x69B1, 0xE9C2, 0x69C1, + 0xE9C3, 0x69CA, 0xE9C4, 0x69DF, 0xE9C5, 0x6995, 0xE9C6, 0x69E0, 0xE9C7, 0x698D, 0xE9C8, 0x69FF, 0xE9C9, 0x6A2F, 0xE9CA, 0x69ED, + 0xE9CB, 0x6A17, 0xE9CC, 0x6A18, 0xE9CD, 0x6A65, 0xE9CE, 0x69F2, 0xE9CF, 0x6A44, 0xE9D0, 0x6A3E, 0xE9D1, 0x6AA0, 0xE9D2, 0x6A50, + 0xE9D3, 0x6A5B, 0xE9D4, 0x6A35, 0xE9D5, 0x6A8E, 0xE9D6, 0x6A79, 0xE9D7, 0x6A3D, 0xE9D8, 0x6A28, 0xE9D9, 0x6A58, 0xE9DA, 0x6A7C, + 0xE9DB, 0x6A91, 0xE9DC, 0x6A90, 0xE9DD, 0x6AA9, 0xE9DE, 0x6A97, 0xE9DF, 0x6AAB, 0xE9E0, 0x7337, 0xE9E1, 0x7352, 0xE9E2, 0x6B81, + 0xE9E3, 0x6B82, 0xE9E4, 0x6B87, 0xE9E5, 0x6B84, 0xE9E6, 0x6B92, 0xE9E7, 0x6B93, 0xE9E8, 0x6B8D, 0xE9E9, 0x6B9A, 0xE9EA, 0x6B9B, + 0xE9EB, 0x6BA1, 0xE9EC, 0x6BAA, 0xE9ED, 0x8F6B, 0xE9EE, 0x8F6D, 0xE9EF, 0x8F71, 0xE9F0, 0x8F72, 0xE9F1, 0x8F73, 0xE9F2, 0x8F75, + 0xE9F3, 0x8F76, 0xE9F4, 0x8F78, 0xE9F5, 0x8F77, 0xE9F6, 0x8F79, 0xE9F7, 0x8F7A, 0xE9F8, 0x8F7C, 0xE9F9, 0x8F7E, 0xE9FA, 0x8F81, + 0xE9FB, 0x8F82, 0xE9FC, 0x8F84, 0xE9FD, 0x8F87, 0xE9FE, 0x8F8B, 0xEA40, 0x95CC, 0xEA41, 0x95CD, 0xEA42, 0x95CE, 0xEA43, 0x95CF, + 0xEA44, 0x95D0, 0xEA45, 0x95D1, 0xEA46, 0x95D2, 0xEA47, 0x95D3, 0xEA48, 0x95D4, 0xEA49, 0x95D5, 0xEA4A, 0x95D6, 0xEA4B, 0x95D7, + 0xEA4C, 0x95D8, 0xEA4D, 0x95D9, 0xEA4E, 0x95DA, 0xEA4F, 0x95DB, 0xEA50, 0x95DC, 0xEA51, 0x95DD, 0xEA52, 0x95DE, 0xEA53, 0x95DF, + 0xEA54, 0x95E0, 0xEA55, 0x95E1, 0xEA56, 0x95E2, 0xEA57, 0x95E3, 0xEA58, 0x95E4, 0xEA59, 0x95E5, 0xEA5A, 0x95E6, 0xEA5B, 0x95E7, + 0xEA5C, 0x95EC, 0xEA5D, 0x95FF, 0xEA5E, 0x9607, 0xEA5F, 0x9613, 0xEA60, 0x9618, 0xEA61, 0x961B, 0xEA62, 0x961E, 0xEA63, 0x9620, + 0xEA64, 0x9623, 0xEA65, 0x9624, 0xEA66, 0x9625, 0xEA67, 0x9626, 0xEA68, 0x9627, 0xEA69, 0x9628, 0xEA6A, 0x9629, 0xEA6B, 0x962B, + 0xEA6C, 0x962C, 0xEA6D, 0x962D, 0xEA6E, 0x962F, 0xEA6F, 0x9630, 0xEA70, 0x9637, 0xEA71, 0x9638, 0xEA72, 0x9639, 0xEA73, 0x963A, + 0xEA74, 0x963E, 0xEA75, 0x9641, 0xEA76, 0x9643, 0xEA77, 0x964A, 0xEA78, 0x964E, 0xEA79, 0x964F, 0xEA7A, 0x9651, 0xEA7B, 0x9652, + 0xEA7C, 0x9653, 0xEA7D, 0x9656, 0xEA7E, 0x9657, 0xEA80, 0x9658, 0xEA81, 0x9659, 0xEA82, 0x965A, 0xEA83, 0x965C, 0xEA84, 0x965D, + 0xEA85, 0x965E, 0xEA86, 0x9660, 0xEA87, 0x9663, 0xEA88, 0x9665, 0xEA89, 0x9666, 0xEA8A, 0x966B, 0xEA8B, 0x966D, 0xEA8C, 0x966E, + 0xEA8D, 0x966F, 0xEA8E, 0x9670, 0xEA8F, 0x9671, 0xEA90, 0x9673, 0xEA91, 0x9678, 0xEA92, 0x9679, 0xEA93, 0x967A, 0xEA94, 0x967B, + 0xEA95, 0x967C, 0xEA96, 0x967D, 0xEA97, 0x967E, 0xEA98, 0x967F, 0xEA99, 0x9680, 0xEA9A, 0x9681, 0xEA9B, 0x9682, 0xEA9C, 0x9683, + 0xEA9D, 0x9684, 0xEA9E, 0x9687, 0xEA9F, 0x9689, 0xEAA0, 0x968A, 0xEAA1, 0x8F8D, 0xEAA2, 0x8F8E, 0xEAA3, 0x8F8F, 0xEAA4, 0x8F98, + 0xEAA5, 0x8F9A, 0xEAA6, 0x8ECE, 0xEAA7, 0x620B, 0xEAA8, 0x6217, 0xEAA9, 0x621B, 0xEAAA, 0x621F, 0xEAAB, 0x6222, 0xEAAC, 0x6221, + 0xEAAD, 0x6225, 0xEAAE, 0x6224, 0xEAAF, 0x622C, 0xEAB0, 0x81E7, 0xEAB1, 0x74EF, 0xEAB2, 0x74F4, 0xEAB3, 0x74FF, 0xEAB4, 0x750F, + 0xEAB5, 0x7511, 0xEAB6, 0x7513, 0xEAB7, 0x6534, 0xEAB8, 0x65EE, 0xEAB9, 0x65EF, 0xEABA, 0x65F0, 0xEABB, 0x660A, 0xEABC, 0x6619, + 0xEABD, 0x6772, 0xEABE, 0x6603, 0xEABF, 0x6615, 0xEAC0, 0x6600, 0xEAC1, 0x7085, 0xEAC2, 0x66F7, 0xEAC3, 0x661D, 0xEAC4, 0x6634, + 0xEAC5, 0x6631, 0xEAC6, 0x6636, 0xEAC7, 0x6635, 0xEAC8, 0x8006, 0xEAC9, 0x665F, 0xEACA, 0x6654, 0xEACB, 0x6641, 0xEACC, 0x664F, + 0xEACD, 0x6656, 0xEACE, 0x6661, 0xEACF, 0x6657, 0xEAD0, 0x6677, 0xEAD1, 0x6684, 0xEAD2, 0x668C, 0xEAD3, 0x66A7, 0xEAD4, 0x669D, + 0xEAD5, 0x66BE, 0xEAD6, 0x66DB, 0xEAD7, 0x66DC, 0xEAD8, 0x66E6, 0xEAD9, 0x66E9, 0xEADA, 0x8D32, 0xEADB, 0x8D33, 0xEADC, 0x8D36, + 0xEADD, 0x8D3B, 0xEADE, 0x8D3D, 0xEADF, 0x8D40, 0xEAE0, 0x8D45, 0xEAE1, 0x8D46, 0xEAE2, 0x8D48, 0xEAE3, 0x8D49, 0xEAE4, 0x8D47, + 0xEAE5, 0x8D4D, 0xEAE6, 0x8D55, 0xEAE7, 0x8D59, 0xEAE8, 0x89C7, 0xEAE9, 0x89CA, 0xEAEA, 0x89CB, 0xEAEB, 0x89CC, 0xEAEC, 0x89CE, + 0xEAED, 0x89CF, 0xEAEE, 0x89D0, 0xEAEF, 0x89D1, 0xEAF0, 0x726E, 0xEAF1, 0x729F, 0xEAF2, 0x725D, 0xEAF3, 0x7266, 0xEAF4, 0x726F, + 0xEAF5, 0x727E, 0xEAF6, 0x727F, 0xEAF7, 0x7284, 0xEAF8, 0x728B, 0xEAF9, 0x728D, 0xEAFA, 0x728F, 0xEAFB, 0x7292, 0xEAFC, 0x6308, + 0xEAFD, 0x6332, 0xEAFE, 0x63B0, 0xEB40, 0x968C, 0xEB41, 0x968E, 0xEB42, 0x9691, 0xEB43, 0x9692, 0xEB44, 0x9693, 0xEB45, 0x9695, + 0xEB46, 0x9696, 0xEB47, 0x969A, 0xEB48, 0x969B, 0xEB49, 0x969D, 0xEB4A, 0x969E, 0xEB4B, 0x969F, 0xEB4C, 0x96A0, 0xEB4D, 0x96A1, + 0xEB4E, 0x96A2, 0xEB4F, 0x96A3, 0xEB50, 0x96A4, 0xEB51, 0x96A5, 0xEB52, 0x96A6, 0xEB53, 0x96A8, 0xEB54, 0x96A9, 0xEB55, 0x96AA, + 0xEB56, 0x96AB, 0xEB57, 0x96AC, 0xEB58, 0x96AD, 0xEB59, 0x96AE, 0xEB5A, 0x96AF, 0xEB5B, 0x96B1, 0xEB5C, 0x96B2, 0xEB5D, 0x96B4, + 0xEB5E, 0x96B5, 0xEB5F, 0x96B7, 0xEB60, 0x96B8, 0xEB61, 0x96BA, 0xEB62, 0x96BB, 0xEB63, 0x96BF, 0xEB64, 0x96C2, 0xEB65, 0x96C3, + 0xEB66, 0x96C8, 0xEB67, 0x96CA, 0xEB68, 0x96CB, 0xEB69, 0x96D0, 0xEB6A, 0x96D1, 0xEB6B, 0x96D3, 0xEB6C, 0x96D4, 0xEB6D, 0x96D6, + 0xEB6E, 0x96D7, 0xEB6F, 0x96D8, 0xEB70, 0x96D9, 0xEB71, 0x96DA, 0xEB72, 0x96DB, 0xEB73, 0x96DC, 0xEB74, 0x96DD, 0xEB75, 0x96DE, + 0xEB76, 0x96DF, 0xEB77, 0x96E1, 0xEB78, 0x96E2, 0xEB79, 0x96E3, 0xEB7A, 0x96E4, 0xEB7B, 0x96E5, 0xEB7C, 0x96E6, 0xEB7D, 0x96E7, + 0xEB7E, 0x96EB, 0xEB80, 0x96EC, 0xEB81, 0x96ED, 0xEB82, 0x96EE, 0xEB83, 0x96F0, 0xEB84, 0x96F1, 0xEB85, 0x96F2, 0xEB86, 0x96F4, + 0xEB87, 0x96F5, 0xEB88, 0x96F8, 0xEB89, 0x96FA, 0xEB8A, 0x96FB, 0xEB8B, 0x96FC, 0xEB8C, 0x96FD, 0xEB8D, 0x96FF, 0xEB8E, 0x9702, + 0xEB8F, 0x9703, 0xEB90, 0x9705, 0xEB91, 0x970A, 0xEB92, 0x970B, 0xEB93, 0x970C, 0xEB94, 0x9710, 0xEB95, 0x9711, 0xEB96, 0x9712, + 0xEB97, 0x9714, 0xEB98, 0x9715, 0xEB99, 0x9717, 0xEB9A, 0x9718, 0xEB9B, 0x9719, 0xEB9C, 0x971A, 0xEB9D, 0x971B, 0xEB9E, 0x971D, + 0xEB9F, 0x971F, 0xEBA0, 0x9720, 0xEBA1, 0x643F, 0xEBA2, 0x64D8, 0xEBA3, 0x8004, 0xEBA4, 0x6BEA, 0xEBA5, 0x6BF3, 0xEBA6, 0x6BFD, + 0xEBA7, 0x6BF5, 0xEBA8, 0x6BF9, 0xEBA9, 0x6C05, 0xEBAA, 0x6C07, 0xEBAB, 0x6C06, 0xEBAC, 0x6C0D, 0xEBAD, 0x6C15, 0xEBAE, 0x6C18, + 0xEBAF, 0x6C19, 0xEBB0, 0x6C1A, 0xEBB1, 0x6C21, 0xEBB2, 0x6C29, 0xEBB3, 0x6C24, 0xEBB4, 0x6C2A, 0xEBB5, 0x6C32, 0xEBB6, 0x6535, + 0xEBB7, 0x6555, 0xEBB8, 0x656B, 0xEBB9, 0x724D, 0xEBBA, 0x7252, 0xEBBB, 0x7256, 0xEBBC, 0x7230, 0xEBBD, 0x8662, 0xEBBE, 0x5216, + 0xEBBF, 0x809F, 0xEBC0, 0x809C, 0xEBC1, 0x8093, 0xEBC2, 0x80BC, 0xEBC3, 0x670A, 0xEBC4, 0x80BD, 0xEBC5, 0x80B1, 0xEBC6, 0x80AB, + 0xEBC7, 0x80AD, 0xEBC8, 0x80B4, 0xEBC9, 0x80B7, 0xEBCA, 0x80E7, 0xEBCB, 0x80E8, 0xEBCC, 0x80E9, 0xEBCD, 0x80EA, 0xEBCE, 0x80DB, + 0xEBCF, 0x80C2, 0xEBD0, 0x80C4, 0xEBD1, 0x80D9, 0xEBD2, 0x80CD, 0xEBD3, 0x80D7, 0xEBD4, 0x6710, 0xEBD5, 0x80DD, 0xEBD6, 0x80EB, + 0xEBD7, 0x80F1, 0xEBD8, 0x80F4, 0xEBD9, 0x80ED, 0xEBDA, 0x810D, 0xEBDB, 0x810E, 0xEBDC, 0x80F2, 0xEBDD, 0x80FC, 0xEBDE, 0x6715, + 0xEBDF, 0x8112, 0xEBE0, 0x8C5A, 0xEBE1, 0x8136, 0xEBE2, 0x811E, 0xEBE3, 0x812C, 0xEBE4, 0x8118, 0xEBE5, 0x8132, 0xEBE6, 0x8148, + 0xEBE7, 0x814C, 0xEBE8, 0x8153, 0xEBE9, 0x8174, 0xEBEA, 0x8159, 0xEBEB, 0x815A, 0xEBEC, 0x8171, 0xEBED, 0x8160, 0xEBEE, 0x8169, + 0xEBEF, 0x817C, 0xEBF0, 0x817D, 0xEBF1, 0x816D, 0xEBF2, 0x8167, 0xEBF3, 0x584D, 0xEBF4, 0x5AB5, 0xEBF5, 0x8188, 0xEBF6, 0x8182, + 0xEBF7, 0x8191, 0xEBF8, 0x6ED5, 0xEBF9, 0x81A3, 0xEBFA, 0x81AA, 0xEBFB, 0x81CC, 0xEBFC, 0x6726, 0xEBFD, 0x81CA, 0xEBFE, 0x81BB, + 0xEC40, 0x9721, 0xEC41, 0x9722, 0xEC42, 0x9723, 0xEC43, 0x9724, 0xEC44, 0x9725, 0xEC45, 0x9726, 0xEC46, 0x9727, 0xEC47, 0x9728, + 0xEC48, 0x9729, 0xEC49, 0x972B, 0xEC4A, 0x972C, 0xEC4B, 0x972E, 0xEC4C, 0x972F, 0xEC4D, 0x9731, 0xEC4E, 0x9733, 0xEC4F, 0x9734, + 0xEC50, 0x9735, 0xEC51, 0x9736, 0xEC52, 0x9737, 0xEC53, 0x973A, 0xEC54, 0x973B, 0xEC55, 0x973C, 0xEC56, 0x973D, 0xEC57, 0x973F, + 0xEC58, 0x9740, 0xEC59, 0x9741, 0xEC5A, 0x9742, 0xEC5B, 0x9743, 0xEC5C, 0x9744, 0xEC5D, 0x9745, 0xEC5E, 0x9746, 0xEC5F, 0x9747, + 0xEC60, 0x9748, 0xEC61, 0x9749, 0xEC62, 0x974A, 0xEC63, 0x974B, 0xEC64, 0x974C, 0xEC65, 0x974D, 0xEC66, 0x974E, 0xEC67, 0x974F, + 0xEC68, 0x9750, 0xEC69, 0x9751, 0xEC6A, 0x9754, 0xEC6B, 0x9755, 0xEC6C, 0x9757, 0xEC6D, 0x9758, 0xEC6E, 0x975A, 0xEC6F, 0x975C, + 0xEC70, 0x975D, 0xEC71, 0x975F, 0xEC72, 0x9763, 0xEC73, 0x9764, 0xEC74, 0x9766, 0xEC75, 0x9767, 0xEC76, 0x9768, 0xEC77, 0x976A, + 0xEC78, 0x976B, 0xEC79, 0x976C, 0xEC7A, 0x976D, 0xEC7B, 0x976E, 0xEC7C, 0x976F, 0xEC7D, 0x9770, 0xEC7E, 0x9771, 0xEC80, 0x9772, + 0xEC81, 0x9775, 0xEC82, 0x9777, 0xEC83, 0x9778, 0xEC84, 0x9779, 0xEC85, 0x977A, 0xEC86, 0x977B, 0xEC87, 0x977D, 0xEC88, 0x977E, + 0xEC89, 0x977F, 0xEC8A, 0x9780, 0xEC8B, 0x9781, 0xEC8C, 0x9782, 0xEC8D, 0x9783, 0xEC8E, 0x9784, 0xEC8F, 0x9786, 0xEC90, 0x9787, + 0xEC91, 0x9788, 0xEC92, 0x9789, 0xEC93, 0x978A, 0xEC94, 0x978C, 0xEC95, 0x978E, 0xEC96, 0x978F, 0xEC97, 0x9790, 0xEC98, 0x9793, + 0xEC99, 0x9795, 0xEC9A, 0x9796, 0xEC9B, 0x9797, 0xEC9C, 0x9799, 0xEC9D, 0x979A, 0xEC9E, 0x979B, 0xEC9F, 0x979C, 0xECA0, 0x979D, + 0xECA1, 0x81C1, 0xECA2, 0x81A6, 0xECA3, 0x6B24, 0xECA4, 0x6B37, 0xECA5, 0x6B39, 0xECA6, 0x6B43, 0xECA7, 0x6B46, 0xECA8, 0x6B59, + 0xECA9, 0x98D1, 0xECAA, 0x98D2, 0xECAB, 0x98D3, 0xECAC, 0x98D5, 0xECAD, 0x98D9, 0xECAE, 0x98DA, 0xECAF, 0x6BB3, 0xECB0, 0x5F40, + 0xECB1, 0x6BC2, 0xECB2, 0x89F3, 0xECB3, 0x6590, 0xECB4, 0x9F51, 0xECB5, 0x6593, 0xECB6, 0x65BC, 0xECB7, 0x65C6, 0xECB8, 0x65C4, + 0xECB9, 0x65C3, 0xECBA, 0x65CC, 0xECBB, 0x65CE, 0xECBC, 0x65D2, 0xECBD, 0x65D6, 0xECBE, 0x7080, 0xECBF, 0x709C, 0xECC0, 0x7096, + 0xECC1, 0x709D, 0xECC2, 0x70BB, 0xECC3, 0x70C0, 0xECC4, 0x70B7, 0xECC5, 0x70AB, 0xECC6, 0x70B1, 0xECC7, 0x70E8, 0xECC8, 0x70CA, + 0xECC9, 0x7110, 0xECCA, 0x7113, 0xECCB, 0x7116, 0xECCC, 0x712F, 0xECCD, 0x7131, 0xECCE, 0x7173, 0xECCF, 0x715C, 0xECD0, 0x7168, + 0xECD1, 0x7145, 0xECD2, 0x7172, 0xECD3, 0x714A, 0xECD4, 0x7178, 0xECD5, 0x717A, 0xECD6, 0x7198, 0xECD7, 0x71B3, 0xECD8, 0x71B5, + 0xECD9, 0x71A8, 0xECDA, 0x71A0, 0xECDB, 0x71E0, 0xECDC, 0x71D4, 0xECDD, 0x71E7, 0xECDE, 0x71F9, 0xECDF, 0x721D, 0xECE0, 0x7228, + 0xECE1, 0x706C, 0xECE2, 0x7118, 0xECE3, 0x7166, 0xECE4, 0x71B9, 0xECE5, 0x623E, 0xECE6, 0x623D, 0xECE7, 0x6243, 0xECE8, 0x6248, + 0xECE9, 0x6249, 0xECEA, 0x793B, 0xECEB, 0x7940, 0xECEC, 0x7946, 0xECED, 0x7949, 0xECEE, 0x795B, 0xECEF, 0x795C, 0xECF0, 0x7953, + 0xECF1, 0x795A, 0xECF2, 0x7962, 0xECF3, 0x7957, 0xECF4, 0x7960, 0xECF5, 0x796F, 0xECF6, 0x7967, 0xECF7, 0x797A, 0xECF8, 0x7985, + 0xECF9, 0x798A, 0xECFA, 0x799A, 0xECFB, 0x79A7, 0xECFC, 0x79B3, 0xECFD, 0x5FD1, 0xECFE, 0x5FD0, 0xED40, 0x979E, 0xED41, 0x979F, + 0xED42, 0x97A1, 0xED43, 0x97A2, 0xED44, 0x97A4, 0xED45, 0x97A5, 0xED46, 0x97A6, 0xED47, 0x97A7, 0xED48, 0x97A8, 0xED49, 0x97A9, + 0xED4A, 0x97AA, 0xED4B, 0x97AC, 0xED4C, 0x97AE, 0xED4D, 0x97B0, 0xED4E, 0x97B1, 0xED4F, 0x97B3, 0xED50, 0x97B5, 0xED51, 0x97B6, + 0xED52, 0x97B7, 0xED53, 0x97B8, 0xED54, 0x97B9, 0xED55, 0x97BA, 0xED56, 0x97BB, 0xED57, 0x97BC, 0xED58, 0x97BD, 0xED59, 0x97BE, + 0xED5A, 0x97BF, 0xED5B, 0x97C0, 0xED5C, 0x97C1, 0xED5D, 0x97C2, 0xED5E, 0x97C3, 0xED5F, 0x97C4, 0xED60, 0x97C5, 0xED61, 0x97C6, + 0xED62, 0x97C7, 0xED63, 0x97C8, 0xED64, 0x97C9, 0xED65, 0x97CA, 0xED66, 0x97CB, 0xED67, 0x97CC, 0xED68, 0x97CD, 0xED69, 0x97CE, + 0xED6A, 0x97CF, 0xED6B, 0x97D0, 0xED6C, 0x97D1, 0xED6D, 0x97D2, 0xED6E, 0x97D3, 0xED6F, 0x97D4, 0xED70, 0x97D5, 0xED71, 0x97D6, + 0xED72, 0x97D7, 0xED73, 0x97D8, 0xED74, 0x97D9, 0xED75, 0x97DA, 0xED76, 0x97DB, 0xED77, 0x97DC, 0xED78, 0x97DD, 0xED79, 0x97DE, + 0xED7A, 0x97DF, 0xED7B, 0x97E0, 0xED7C, 0x97E1, 0xED7D, 0x97E2, 0xED7E, 0x97E3, 0xED80, 0x97E4, 0xED81, 0x97E5, 0xED82, 0x97E8, + 0xED83, 0x97EE, 0xED84, 0x97EF, 0xED85, 0x97F0, 0xED86, 0x97F1, 0xED87, 0x97F2, 0xED88, 0x97F4, 0xED89, 0x97F7, 0xED8A, 0x97F8, + 0xED8B, 0x97F9, 0xED8C, 0x97FA, 0xED8D, 0x97FB, 0xED8E, 0x97FC, 0xED8F, 0x97FD, 0xED90, 0x97FE, 0xED91, 0x97FF, 0xED92, 0x9800, + 0xED93, 0x9801, 0xED94, 0x9802, 0xED95, 0x9803, 0xED96, 0x9804, 0xED97, 0x9805, 0xED98, 0x9806, 0xED99, 0x9807, 0xED9A, 0x9808, + 0xED9B, 0x9809, 0xED9C, 0x980A, 0xED9D, 0x980B, 0xED9E, 0x980C, 0xED9F, 0x980D, 0xEDA0, 0x980E, 0xEDA1, 0x603C, 0xEDA2, 0x605D, + 0xEDA3, 0x605A, 0xEDA4, 0x6067, 0xEDA5, 0x6041, 0xEDA6, 0x6059, 0xEDA7, 0x6063, 0xEDA8, 0x60AB, 0xEDA9, 0x6106, 0xEDAA, 0x610D, + 0xEDAB, 0x615D, 0xEDAC, 0x61A9, 0xEDAD, 0x619D, 0xEDAE, 0x61CB, 0xEDAF, 0x61D1, 0xEDB0, 0x6206, 0xEDB1, 0x8080, 0xEDB2, 0x807F, + 0xEDB3, 0x6C93, 0xEDB4, 0x6CF6, 0xEDB5, 0x6DFC, 0xEDB6, 0x77F6, 0xEDB7, 0x77F8, 0xEDB8, 0x7800, 0xEDB9, 0x7809, 0xEDBA, 0x7817, + 0xEDBB, 0x7818, 0xEDBC, 0x7811, 0xEDBD, 0x65AB, 0xEDBE, 0x782D, 0xEDBF, 0x781C, 0xEDC0, 0x781D, 0xEDC1, 0x7839, 0xEDC2, 0x783A, + 0xEDC3, 0x783B, 0xEDC4, 0x781F, 0xEDC5, 0x783C, 0xEDC6, 0x7825, 0xEDC7, 0x782C, 0xEDC8, 0x7823, 0xEDC9, 0x7829, 0xEDCA, 0x784E, + 0xEDCB, 0x786D, 0xEDCC, 0x7856, 0xEDCD, 0x7857, 0xEDCE, 0x7826, 0xEDCF, 0x7850, 0xEDD0, 0x7847, 0xEDD1, 0x784C, 0xEDD2, 0x786A, + 0xEDD3, 0x789B, 0xEDD4, 0x7893, 0xEDD5, 0x789A, 0xEDD6, 0x7887, 0xEDD7, 0x789C, 0xEDD8, 0x78A1, 0xEDD9, 0x78A3, 0xEDDA, 0x78B2, + 0xEDDB, 0x78B9, 0xEDDC, 0x78A5, 0xEDDD, 0x78D4, 0xEDDE, 0x78D9, 0xEDDF, 0x78C9, 0xEDE0, 0x78EC, 0xEDE1, 0x78F2, 0xEDE2, 0x7905, + 0xEDE3, 0x78F4, 0xEDE4, 0x7913, 0xEDE5, 0x7924, 0xEDE6, 0x791E, 0xEDE7, 0x7934, 0xEDE8, 0x9F9B, 0xEDE9, 0x9EF9, 0xEDEA, 0x9EFB, + 0xEDEB, 0x9EFC, 0xEDEC, 0x76F1, 0xEDED, 0x7704, 0xEDEE, 0x770D, 0xEDEF, 0x76F9, 0xEDF0, 0x7707, 0xEDF1, 0x7708, 0xEDF2, 0x771A, + 0xEDF3, 0x7722, 0xEDF4, 0x7719, 0xEDF5, 0x772D, 0xEDF6, 0x7726, 0xEDF7, 0x7735, 0xEDF8, 0x7738, 0xEDF9, 0x7750, 0xEDFA, 0x7751, + 0xEDFB, 0x7747, 0xEDFC, 0x7743, 0xEDFD, 0x775A, 0xEDFE, 0x7768, 0xEE40, 0x980F, 0xEE41, 0x9810, 0xEE42, 0x9811, 0xEE43, 0x9812, + 0xEE44, 0x9813, 0xEE45, 0x9814, 0xEE46, 0x9815, 0xEE47, 0x9816, 0xEE48, 0x9817, 0xEE49, 0x9818, 0xEE4A, 0x9819, 0xEE4B, 0x981A, + 0xEE4C, 0x981B, 0xEE4D, 0x981C, 0xEE4E, 0x981D, 0xEE4F, 0x981E, 0xEE50, 0x981F, 0xEE51, 0x9820, 0xEE52, 0x9821, 0xEE53, 0x9822, + 0xEE54, 0x9823, 0xEE55, 0x9824, 0xEE56, 0x9825, 0xEE57, 0x9826, 0xEE58, 0x9827, 0xEE59, 0x9828, 0xEE5A, 0x9829, 0xEE5B, 0x982A, + 0xEE5C, 0x982B, 0xEE5D, 0x982C, 0xEE5E, 0x982D, 0xEE5F, 0x982E, 0xEE60, 0x982F, 0xEE61, 0x9830, 0xEE62, 0x9831, 0xEE63, 0x9832, + 0xEE64, 0x9833, 0xEE65, 0x9834, 0xEE66, 0x9835, 0xEE67, 0x9836, 0xEE68, 0x9837, 0xEE69, 0x9838, 0xEE6A, 0x9839, 0xEE6B, 0x983A, + 0xEE6C, 0x983B, 0xEE6D, 0x983C, 0xEE6E, 0x983D, 0xEE6F, 0x983E, 0xEE70, 0x983F, 0xEE71, 0x9840, 0xEE72, 0x9841, 0xEE73, 0x9842, + 0xEE74, 0x9843, 0xEE75, 0x9844, 0xEE76, 0x9845, 0xEE77, 0x9846, 0xEE78, 0x9847, 0xEE79, 0x9848, 0xEE7A, 0x9849, 0xEE7B, 0x984A, + 0xEE7C, 0x984B, 0xEE7D, 0x984C, 0xEE7E, 0x984D, 0xEE80, 0x984E, 0xEE81, 0x984F, 0xEE82, 0x9850, 0xEE83, 0x9851, 0xEE84, 0x9852, + 0xEE85, 0x9853, 0xEE86, 0x9854, 0xEE87, 0x9855, 0xEE88, 0x9856, 0xEE89, 0x9857, 0xEE8A, 0x9858, 0xEE8B, 0x9859, 0xEE8C, 0x985A, + 0xEE8D, 0x985B, 0xEE8E, 0x985C, 0xEE8F, 0x985D, 0xEE90, 0x985E, 0xEE91, 0x985F, 0xEE92, 0x9860, 0xEE93, 0x9861, 0xEE94, 0x9862, + 0xEE95, 0x9863, 0xEE96, 0x9864, 0xEE97, 0x9865, 0xEE98, 0x9866, 0xEE99, 0x9867, 0xEE9A, 0x9868, 0xEE9B, 0x9869, 0xEE9C, 0x986A, + 0xEE9D, 0x986B, 0xEE9E, 0x986C, 0xEE9F, 0x986D, 0xEEA0, 0x986E, 0xEEA1, 0x7762, 0xEEA2, 0x7765, 0xEEA3, 0x777F, 0xEEA4, 0x778D, + 0xEEA5, 0x777D, 0xEEA6, 0x7780, 0xEEA7, 0x778C, 0xEEA8, 0x7791, 0xEEA9, 0x779F, 0xEEAA, 0x77A0, 0xEEAB, 0x77B0, 0xEEAC, 0x77B5, + 0xEEAD, 0x77BD, 0xEEAE, 0x753A, 0xEEAF, 0x7540, 0xEEB0, 0x754E, 0xEEB1, 0x754B, 0xEEB2, 0x7548, 0xEEB3, 0x755B, 0xEEB4, 0x7572, + 0xEEB5, 0x7579, 0xEEB6, 0x7583, 0xEEB7, 0x7F58, 0xEEB8, 0x7F61, 0xEEB9, 0x7F5F, 0xEEBA, 0x8A48, 0xEEBB, 0x7F68, 0xEEBC, 0x7F74, + 0xEEBD, 0x7F71, 0xEEBE, 0x7F79, 0xEEBF, 0x7F81, 0xEEC0, 0x7F7E, 0xEEC1, 0x76CD, 0xEEC2, 0x76E5, 0xEEC3, 0x8832, 0xEEC4, 0x9485, + 0xEEC5, 0x9486, 0xEEC6, 0x9487, 0xEEC7, 0x948B, 0xEEC8, 0x948A, 0xEEC9, 0x948C, 0xEECA, 0x948D, 0xEECB, 0x948F, 0xEECC, 0x9490, + 0xEECD, 0x9494, 0xEECE, 0x9497, 0xEECF, 0x9495, 0xEED0, 0x949A, 0xEED1, 0x949B, 0xEED2, 0x949C, 0xEED3, 0x94A3, 0xEED4, 0x94A4, + 0xEED5, 0x94AB, 0xEED6, 0x94AA, 0xEED7, 0x94AD, 0xEED8, 0x94AC, 0xEED9, 0x94AF, 0xEEDA, 0x94B0, 0xEEDB, 0x94B2, 0xEEDC, 0x94B4, + 0xEEDD, 0x94B6, 0xEEDE, 0x94B7, 0xEEDF, 0x94B8, 0xEEE0, 0x94B9, 0xEEE1, 0x94BA, 0xEEE2, 0x94BC, 0xEEE3, 0x94BD, 0xEEE4, 0x94BF, + 0xEEE5, 0x94C4, 0xEEE6, 0x94C8, 0xEEE7, 0x94C9, 0xEEE8, 0x94CA, 0xEEE9, 0x94CB, 0xEEEA, 0x94CC, 0xEEEB, 0x94CD, 0xEEEC, 0x94CE, + 0xEEED, 0x94D0, 0xEEEE, 0x94D1, 0xEEEF, 0x94D2, 0xEEF0, 0x94D5, 0xEEF1, 0x94D6, 0xEEF2, 0x94D7, 0xEEF3, 0x94D9, 0xEEF4, 0x94D8, + 0xEEF5, 0x94DB, 0xEEF6, 0x94DE, 0xEEF7, 0x94DF, 0xEEF8, 0x94E0, 0xEEF9, 0x94E2, 0xEEFA, 0x94E4, 0xEEFB, 0x94E5, 0xEEFC, 0x94E7, + 0xEEFD, 0x94E8, 0xEEFE, 0x94EA, 0xEF40, 0x986F, 0xEF41, 0x9870, 0xEF42, 0x9871, 0xEF43, 0x9872, 0xEF44, 0x9873, 0xEF45, 0x9874, + 0xEF46, 0x988B, 0xEF47, 0x988E, 0xEF48, 0x9892, 0xEF49, 0x9895, 0xEF4A, 0x9899, 0xEF4B, 0x98A3, 0xEF4C, 0x98A8, 0xEF4D, 0x98A9, + 0xEF4E, 0x98AA, 0xEF4F, 0x98AB, 0xEF50, 0x98AC, 0xEF51, 0x98AD, 0xEF52, 0x98AE, 0xEF53, 0x98AF, 0xEF54, 0x98B0, 0xEF55, 0x98B1, + 0xEF56, 0x98B2, 0xEF57, 0x98B3, 0xEF58, 0x98B4, 0xEF59, 0x98B5, 0xEF5A, 0x98B6, 0xEF5B, 0x98B7, 0xEF5C, 0x98B8, 0xEF5D, 0x98B9, + 0xEF5E, 0x98BA, 0xEF5F, 0x98BB, 0xEF60, 0x98BC, 0xEF61, 0x98BD, 0xEF62, 0x98BE, 0xEF63, 0x98BF, 0xEF64, 0x98C0, 0xEF65, 0x98C1, + 0xEF66, 0x98C2, 0xEF67, 0x98C3, 0xEF68, 0x98C4, 0xEF69, 0x98C5, 0xEF6A, 0x98C6, 0xEF6B, 0x98C7, 0xEF6C, 0x98C8, 0xEF6D, 0x98C9, + 0xEF6E, 0x98CA, 0xEF6F, 0x98CB, 0xEF70, 0x98CC, 0xEF71, 0x98CD, 0xEF72, 0x98CF, 0xEF73, 0x98D0, 0xEF74, 0x98D4, 0xEF75, 0x98D6, + 0xEF76, 0x98D7, 0xEF77, 0x98DB, 0xEF78, 0x98DC, 0xEF79, 0x98DD, 0xEF7A, 0x98E0, 0xEF7B, 0x98E1, 0xEF7C, 0x98E2, 0xEF7D, 0x98E3, + 0xEF7E, 0x98E4, 0xEF80, 0x98E5, 0xEF81, 0x98E6, 0xEF82, 0x98E9, 0xEF83, 0x98EA, 0xEF84, 0x98EB, 0xEF85, 0x98EC, 0xEF86, 0x98ED, + 0xEF87, 0x98EE, 0xEF88, 0x98EF, 0xEF89, 0x98F0, 0xEF8A, 0x98F1, 0xEF8B, 0x98F2, 0xEF8C, 0x98F3, 0xEF8D, 0x98F4, 0xEF8E, 0x98F5, + 0xEF8F, 0x98F6, 0xEF90, 0x98F7, 0xEF91, 0x98F8, 0xEF92, 0x98F9, 0xEF93, 0x98FA, 0xEF94, 0x98FB, 0xEF95, 0x98FC, 0xEF96, 0x98FD, + 0xEF97, 0x98FE, 0xEF98, 0x98FF, 0xEF99, 0x9900, 0xEF9A, 0x9901, 0xEF9B, 0x9902, 0xEF9C, 0x9903, 0xEF9D, 0x9904, 0xEF9E, 0x9905, + 0xEF9F, 0x9906, 0xEFA0, 0x9907, 0xEFA1, 0x94E9, 0xEFA2, 0x94EB, 0xEFA3, 0x94EE, 0xEFA4, 0x94EF, 0xEFA5, 0x94F3, 0xEFA6, 0x94F4, + 0xEFA7, 0x94F5, 0xEFA8, 0x94F7, 0xEFA9, 0x94F9, 0xEFAA, 0x94FC, 0xEFAB, 0x94FD, 0xEFAC, 0x94FF, 0xEFAD, 0x9503, 0xEFAE, 0x9502, + 0xEFAF, 0x9506, 0xEFB0, 0x9507, 0xEFB1, 0x9509, 0xEFB2, 0x950A, 0xEFB3, 0x950D, 0xEFB4, 0x950E, 0xEFB5, 0x950F, 0xEFB6, 0x9512, + 0xEFB7, 0x9513, 0xEFB8, 0x9514, 0xEFB9, 0x9515, 0xEFBA, 0x9516, 0xEFBB, 0x9518, 0xEFBC, 0x951B, 0xEFBD, 0x951D, 0xEFBE, 0x951E, + 0xEFBF, 0x951F, 0xEFC0, 0x9522, 0xEFC1, 0x952A, 0xEFC2, 0x952B, 0xEFC3, 0x9529, 0xEFC4, 0x952C, 0xEFC5, 0x9531, 0xEFC6, 0x9532, + 0xEFC7, 0x9534, 0xEFC8, 0x9536, 0xEFC9, 0x9537, 0xEFCA, 0x9538, 0xEFCB, 0x953C, 0xEFCC, 0x953E, 0xEFCD, 0x953F, 0xEFCE, 0x9542, + 0xEFCF, 0x9535, 0xEFD0, 0x9544, 0xEFD1, 0x9545, 0xEFD2, 0x9546, 0xEFD3, 0x9549, 0xEFD4, 0x954C, 0xEFD5, 0x954E, 0xEFD6, 0x954F, + 0xEFD7, 0x9552, 0xEFD8, 0x9553, 0xEFD9, 0x9554, 0xEFDA, 0x9556, 0xEFDB, 0x9557, 0xEFDC, 0x9558, 0xEFDD, 0x9559, 0xEFDE, 0x955B, + 0xEFDF, 0x955E, 0xEFE0, 0x955F, 0xEFE1, 0x955D, 0xEFE2, 0x9561, 0xEFE3, 0x9562, 0xEFE4, 0x9564, 0xEFE5, 0x9565, 0xEFE6, 0x9566, + 0xEFE7, 0x9567, 0xEFE8, 0x9568, 0xEFE9, 0x9569, 0xEFEA, 0x956A, 0xEFEB, 0x956B, 0xEFEC, 0x956C, 0xEFED, 0x956F, 0xEFEE, 0x9571, + 0xEFEF, 0x9572, 0xEFF0, 0x9573, 0xEFF1, 0x953A, 0xEFF2, 0x77E7, 0xEFF3, 0x77EC, 0xEFF4, 0x96C9, 0xEFF5, 0x79D5, 0xEFF6, 0x79ED, + 0xEFF7, 0x79E3, 0xEFF8, 0x79EB, 0xEFF9, 0x7A06, 0xEFFA, 0x5D47, 0xEFFB, 0x7A03, 0xEFFC, 0x7A02, 0xEFFD, 0x7A1E, 0xEFFE, 0x7A14, + 0xF040, 0x9908, 0xF041, 0x9909, 0xF042, 0x990A, 0xF043, 0x990B, 0xF044, 0x990C, 0xF045, 0x990E, 0xF046, 0x990F, 0xF047, 0x9911, + 0xF048, 0x9912, 0xF049, 0x9913, 0xF04A, 0x9914, 0xF04B, 0x9915, 0xF04C, 0x9916, 0xF04D, 0x9917, 0xF04E, 0x9918, 0xF04F, 0x9919, + 0xF050, 0x991A, 0xF051, 0x991B, 0xF052, 0x991C, 0xF053, 0x991D, 0xF054, 0x991E, 0xF055, 0x991F, 0xF056, 0x9920, 0xF057, 0x9921, + 0xF058, 0x9922, 0xF059, 0x9923, 0xF05A, 0x9924, 0xF05B, 0x9925, 0xF05C, 0x9926, 0xF05D, 0x9927, 0xF05E, 0x9928, 0xF05F, 0x9929, + 0xF060, 0x992A, 0xF061, 0x992B, 0xF062, 0x992C, 0xF063, 0x992D, 0xF064, 0x992F, 0xF065, 0x9930, 0xF066, 0x9931, 0xF067, 0x9932, + 0xF068, 0x9933, 0xF069, 0x9934, 0xF06A, 0x9935, 0xF06B, 0x9936, 0xF06C, 0x9937, 0xF06D, 0x9938, 0xF06E, 0x9939, 0xF06F, 0x993A, + 0xF070, 0x993B, 0xF071, 0x993C, 0xF072, 0x993D, 0xF073, 0x993E, 0xF074, 0x993F, 0xF075, 0x9940, 0xF076, 0x9941, 0xF077, 0x9942, + 0xF078, 0x9943, 0xF079, 0x9944, 0xF07A, 0x9945, 0xF07B, 0x9946, 0xF07C, 0x9947, 0xF07D, 0x9948, 0xF07E, 0x9949, 0xF080, 0x994A, + 0xF081, 0x994B, 0xF082, 0x994C, 0xF083, 0x994D, 0xF084, 0x994E, 0xF085, 0x994F, 0xF086, 0x9950, 0xF087, 0x9951, 0xF088, 0x9952, + 0xF089, 0x9953, 0xF08A, 0x9956, 0xF08B, 0x9957, 0xF08C, 0x9958, 0xF08D, 0x9959, 0xF08E, 0x995A, 0xF08F, 0x995B, 0xF090, 0x995C, + 0xF091, 0x995D, 0xF092, 0x995E, 0xF093, 0x995F, 0xF094, 0x9960, 0xF095, 0x9961, 0xF096, 0x9962, 0xF097, 0x9964, 0xF098, 0x9966, + 0xF099, 0x9973, 0xF09A, 0x9978, 0xF09B, 0x9979, 0xF09C, 0x997B, 0xF09D, 0x997E, 0xF09E, 0x9982, 0xF09F, 0x9983, 0xF0A0, 0x9989, + 0xF0A1, 0x7A39, 0xF0A2, 0x7A37, 0xF0A3, 0x7A51, 0xF0A4, 0x9ECF, 0xF0A5, 0x99A5, 0xF0A6, 0x7A70, 0xF0A7, 0x7688, 0xF0A8, 0x768E, + 0xF0A9, 0x7693, 0xF0AA, 0x7699, 0xF0AB, 0x76A4, 0xF0AC, 0x74DE, 0xF0AD, 0x74E0, 0xF0AE, 0x752C, 0xF0AF, 0x9E20, 0xF0B0, 0x9E22, + 0xF0B1, 0x9E28, 0xF0B2, 0x9E29, 0xF0B3, 0x9E2A, 0xF0B4, 0x9E2B, 0xF0B5, 0x9E2C, 0xF0B6, 0x9E32, 0xF0B7, 0x9E31, 0xF0B8, 0x9E36, + 0xF0B9, 0x9E38, 0xF0BA, 0x9E37, 0xF0BB, 0x9E39, 0xF0BC, 0x9E3A, 0xF0BD, 0x9E3E, 0xF0BE, 0x9E41, 0xF0BF, 0x9E42, 0xF0C0, 0x9E44, + 0xF0C1, 0x9E46, 0xF0C2, 0x9E47, 0xF0C3, 0x9E48, 0xF0C4, 0x9E49, 0xF0C5, 0x9E4B, 0xF0C6, 0x9E4C, 0xF0C7, 0x9E4E, 0xF0C8, 0x9E51, + 0xF0C9, 0x9E55, 0xF0CA, 0x9E57, 0xF0CB, 0x9E5A, 0xF0CC, 0x9E5B, 0xF0CD, 0x9E5C, 0xF0CE, 0x9E5E, 0xF0CF, 0x9E63, 0xF0D0, 0x9E66, + 0xF0D1, 0x9E67, 0xF0D2, 0x9E68, 0xF0D3, 0x9E69, 0xF0D4, 0x9E6A, 0xF0D5, 0x9E6B, 0xF0D6, 0x9E6C, 0xF0D7, 0x9E71, 0xF0D8, 0x9E6D, + 0xF0D9, 0x9E73, 0xF0DA, 0x7592, 0xF0DB, 0x7594, 0xF0DC, 0x7596, 0xF0DD, 0x75A0, 0xF0DE, 0x759D, 0xF0DF, 0x75AC, 0xF0E0, 0x75A3, + 0xF0E1, 0x75B3, 0xF0E2, 0x75B4, 0xF0E3, 0x75B8, 0xF0E4, 0x75C4, 0xF0E5, 0x75B1, 0xF0E6, 0x75B0, 0xF0E7, 0x75C3, 0xF0E8, 0x75C2, + 0xF0E9, 0x75D6, 0xF0EA, 0x75CD, 0xF0EB, 0x75E3, 0xF0EC, 0x75E8, 0xF0ED, 0x75E6, 0xF0EE, 0x75E4, 0xF0EF, 0x75EB, 0xF0F0, 0x75E7, + 0xF0F1, 0x7603, 0xF0F2, 0x75F1, 0xF0F3, 0x75FC, 0xF0F4, 0x75FF, 0xF0F5, 0x7610, 0xF0F6, 0x7600, 0xF0F7, 0x7605, 0xF0F8, 0x760C, + 0xF0F9, 0x7617, 0xF0FA, 0x760A, 0xF0FB, 0x7625, 0xF0FC, 0x7618, 0xF0FD, 0x7615, 0xF0FE, 0x7619, 0xF140, 0x998C, 0xF141, 0x998E, + 0xF142, 0x999A, 0xF143, 0x999B, 0xF144, 0x999C, 0xF145, 0x999D, 0xF146, 0x999E, 0xF147, 0x999F, 0xF148, 0x99A0, 0xF149, 0x99A1, + 0xF14A, 0x99A2, 0xF14B, 0x99A3, 0xF14C, 0x99A4, 0xF14D, 0x99A6, 0xF14E, 0x99A7, 0xF14F, 0x99A9, 0xF150, 0x99AA, 0xF151, 0x99AB, + 0xF152, 0x99AC, 0xF153, 0x99AD, 0xF154, 0x99AE, 0xF155, 0x99AF, 0xF156, 0x99B0, 0xF157, 0x99B1, 0xF158, 0x99B2, 0xF159, 0x99B3, + 0xF15A, 0x99B4, 0xF15B, 0x99B5, 0xF15C, 0x99B6, 0xF15D, 0x99B7, 0xF15E, 0x99B8, 0xF15F, 0x99B9, 0xF160, 0x99BA, 0xF161, 0x99BB, + 0xF162, 0x99BC, 0xF163, 0x99BD, 0xF164, 0x99BE, 0xF165, 0x99BF, 0xF166, 0x99C0, 0xF167, 0x99C1, 0xF168, 0x99C2, 0xF169, 0x99C3, + 0xF16A, 0x99C4, 0xF16B, 0x99C5, 0xF16C, 0x99C6, 0xF16D, 0x99C7, 0xF16E, 0x99C8, 0xF16F, 0x99C9, 0xF170, 0x99CA, 0xF171, 0x99CB, + 0xF172, 0x99CC, 0xF173, 0x99CD, 0xF174, 0x99CE, 0xF175, 0x99CF, 0xF176, 0x99D0, 0xF177, 0x99D1, 0xF178, 0x99D2, 0xF179, 0x99D3, + 0xF17A, 0x99D4, 0xF17B, 0x99D5, 0xF17C, 0x99D6, 0xF17D, 0x99D7, 0xF17E, 0x99D8, 0xF180, 0x99D9, 0xF181, 0x99DA, 0xF182, 0x99DB, + 0xF183, 0x99DC, 0xF184, 0x99DD, 0xF185, 0x99DE, 0xF186, 0x99DF, 0xF187, 0x99E0, 0xF188, 0x99E1, 0xF189, 0x99E2, 0xF18A, 0x99E3, + 0xF18B, 0x99E4, 0xF18C, 0x99E5, 0xF18D, 0x99E6, 0xF18E, 0x99E7, 0xF18F, 0x99E8, 0xF190, 0x99E9, 0xF191, 0x99EA, 0xF192, 0x99EB, + 0xF193, 0x99EC, 0xF194, 0x99ED, 0xF195, 0x99EE, 0xF196, 0x99EF, 0xF197, 0x99F0, 0xF198, 0x99F1, 0xF199, 0x99F2, 0xF19A, 0x99F3, + 0xF19B, 0x99F4, 0xF19C, 0x99F5, 0xF19D, 0x99F6, 0xF19E, 0x99F7, 0xF19F, 0x99F8, 0xF1A0, 0x99F9, 0xF1A1, 0x761B, 0xF1A2, 0x763C, + 0xF1A3, 0x7622, 0xF1A4, 0x7620, 0xF1A5, 0x7640, 0xF1A6, 0x762D, 0xF1A7, 0x7630, 0xF1A8, 0x763F, 0xF1A9, 0x7635, 0xF1AA, 0x7643, + 0xF1AB, 0x763E, 0xF1AC, 0x7633, 0xF1AD, 0x764D, 0xF1AE, 0x765E, 0xF1AF, 0x7654, 0xF1B0, 0x765C, 0xF1B1, 0x7656, 0xF1B2, 0x766B, + 0xF1B3, 0x766F, 0xF1B4, 0x7FCA, 0xF1B5, 0x7AE6, 0xF1B6, 0x7A78, 0xF1B7, 0x7A79, 0xF1B8, 0x7A80, 0xF1B9, 0x7A86, 0xF1BA, 0x7A88, + 0xF1BB, 0x7A95, 0xF1BC, 0x7AA6, 0xF1BD, 0x7AA0, 0xF1BE, 0x7AAC, 0xF1BF, 0x7AA8, 0xF1C0, 0x7AAD, 0xF1C1, 0x7AB3, 0xF1C2, 0x8864, + 0xF1C3, 0x8869, 0xF1C4, 0x8872, 0xF1C5, 0x887D, 0xF1C6, 0x887F, 0xF1C7, 0x8882, 0xF1C8, 0x88A2, 0xF1C9, 0x88C6, 0xF1CA, 0x88B7, + 0xF1CB, 0x88BC, 0xF1CC, 0x88C9, 0xF1CD, 0x88E2, 0xF1CE, 0x88CE, 0xF1CF, 0x88E3, 0xF1D0, 0x88E5, 0xF1D1, 0x88F1, 0xF1D2, 0x891A, + 0xF1D3, 0x88FC, 0xF1D4, 0x88E8, 0xF1D5, 0x88FE, 0xF1D6, 0x88F0, 0xF1D7, 0x8921, 0xF1D8, 0x8919, 0xF1D9, 0x8913, 0xF1DA, 0x891B, + 0xF1DB, 0x890A, 0xF1DC, 0x8934, 0xF1DD, 0x892B, 0xF1DE, 0x8936, 0xF1DF, 0x8941, 0xF1E0, 0x8966, 0xF1E1, 0x897B, 0xF1E2, 0x758B, + 0xF1E3, 0x80E5, 0xF1E4, 0x76B2, 0xF1E5, 0x76B4, 0xF1E6, 0x77DC, 0xF1E7, 0x8012, 0xF1E8, 0x8014, 0xF1E9, 0x8016, 0xF1EA, 0x801C, + 0xF1EB, 0x8020, 0xF1EC, 0x8022, 0xF1ED, 0x8025, 0xF1EE, 0x8026, 0xF1EF, 0x8027, 0xF1F0, 0x8029, 0xF1F1, 0x8028, 0xF1F2, 0x8031, + 0xF1F3, 0x800B, 0xF1F4, 0x8035, 0xF1F5, 0x8043, 0xF1F6, 0x8046, 0xF1F7, 0x804D, 0xF1F8, 0x8052, 0xF1F9, 0x8069, 0xF1FA, 0x8071, + 0xF1FB, 0x8983, 0xF1FC, 0x9878, 0xF1FD, 0x9880, 0xF1FE, 0x9883, 0xF240, 0x99FA, 0xF241, 0x99FB, 0xF242, 0x99FC, 0xF243, 0x99FD, + 0xF244, 0x99FE, 0xF245, 0x99FF, 0xF246, 0x9A00, 0xF247, 0x9A01, 0xF248, 0x9A02, 0xF249, 0x9A03, 0xF24A, 0x9A04, 0xF24B, 0x9A05, + 0xF24C, 0x9A06, 0xF24D, 0x9A07, 0xF24E, 0x9A08, 0xF24F, 0x9A09, 0xF250, 0x9A0A, 0xF251, 0x9A0B, 0xF252, 0x9A0C, 0xF253, 0x9A0D, + 0xF254, 0x9A0E, 0xF255, 0x9A0F, 0xF256, 0x9A10, 0xF257, 0x9A11, 0xF258, 0x9A12, 0xF259, 0x9A13, 0xF25A, 0x9A14, 0xF25B, 0x9A15, + 0xF25C, 0x9A16, 0xF25D, 0x9A17, 0xF25E, 0x9A18, 0xF25F, 0x9A19, 0xF260, 0x9A1A, 0xF261, 0x9A1B, 0xF262, 0x9A1C, 0xF263, 0x9A1D, + 0xF264, 0x9A1E, 0xF265, 0x9A1F, 0xF266, 0x9A20, 0xF267, 0x9A21, 0xF268, 0x9A22, 0xF269, 0x9A23, 0xF26A, 0x9A24, 0xF26B, 0x9A25, + 0xF26C, 0x9A26, 0xF26D, 0x9A27, 0xF26E, 0x9A28, 0xF26F, 0x9A29, 0xF270, 0x9A2A, 0xF271, 0x9A2B, 0xF272, 0x9A2C, 0xF273, 0x9A2D, + 0xF274, 0x9A2E, 0xF275, 0x9A2F, 0xF276, 0x9A30, 0xF277, 0x9A31, 0xF278, 0x9A32, 0xF279, 0x9A33, 0xF27A, 0x9A34, 0xF27B, 0x9A35, + 0xF27C, 0x9A36, 0xF27D, 0x9A37, 0xF27E, 0x9A38, 0xF280, 0x9A39, 0xF281, 0x9A3A, 0xF282, 0x9A3B, 0xF283, 0x9A3C, 0xF284, 0x9A3D, + 0xF285, 0x9A3E, 0xF286, 0x9A3F, 0xF287, 0x9A40, 0xF288, 0x9A41, 0xF289, 0x9A42, 0xF28A, 0x9A43, 0xF28B, 0x9A44, 0xF28C, 0x9A45, + 0xF28D, 0x9A46, 0xF28E, 0x9A47, 0xF28F, 0x9A48, 0xF290, 0x9A49, 0xF291, 0x9A4A, 0xF292, 0x9A4B, 0xF293, 0x9A4C, 0xF294, 0x9A4D, + 0xF295, 0x9A4E, 0xF296, 0x9A4F, 0xF297, 0x9A50, 0xF298, 0x9A51, 0xF299, 0x9A52, 0xF29A, 0x9A53, 0xF29B, 0x9A54, 0xF29C, 0x9A55, + 0xF29D, 0x9A56, 0xF29E, 0x9A57, 0xF29F, 0x9A58, 0xF2A0, 0x9A59, 0xF2A1, 0x9889, 0xF2A2, 0x988C, 0xF2A3, 0x988D, 0xF2A4, 0x988F, + 0xF2A5, 0x9894, 0xF2A6, 0x989A, 0xF2A7, 0x989B, 0xF2A8, 0x989E, 0xF2A9, 0x989F, 0xF2AA, 0x98A1, 0xF2AB, 0x98A2, 0xF2AC, 0x98A5, + 0xF2AD, 0x98A6, 0xF2AE, 0x864D, 0xF2AF, 0x8654, 0xF2B0, 0x866C, 0xF2B1, 0x866E, 0xF2B2, 0x867F, 0xF2B3, 0x867A, 0xF2B4, 0x867C, + 0xF2B5, 0x867B, 0xF2B6, 0x86A8, 0xF2B7, 0x868D, 0xF2B8, 0x868B, 0xF2B9, 0x86AC, 0xF2BA, 0x869D, 0xF2BB, 0x86A7, 0xF2BC, 0x86A3, + 0xF2BD, 0x86AA, 0xF2BE, 0x8693, 0xF2BF, 0x86A9, 0xF2C0, 0x86B6, 0xF2C1, 0x86C4, 0xF2C2, 0x86B5, 0xF2C3, 0x86CE, 0xF2C4, 0x86B0, + 0xF2C5, 0x86BA, 0xF2C6, 0x86B1, 0xF2C7, 0x86AF, 0xF2C8, 0x86C9, 0xF2C9, 0x86CF, 0xF2CA, 0x86B4, 0xF2CB, 0x86E9, 0xF2CC, 0x86F1, + 0xF2CD, 0x86F2, 0xF2CE, 0x86ED, 0xF2CF, 0x86F3, 0xF2D0, 0x86D0, 0xF2D1, 0x8713, 0xF2D2, 0x86DE, 0xF2D3, 0x86F4, 0xF2D4, 0x86DF, + 0xF2D5, 0x86D8, 0xF2D6, 0x86D1, 0xF2D7, 0x8703, 0xF2D8, 0x8707, 0xF2D9, 0x86F8, 0xF2DA, 0x8708, 0xF2DB, 0x870A, 0xF2DC, 0x870D, + 0xF2DD, 0x8709, 0xF2DE, 0x8723, 0xF2DF, 0x873B, 0xF2E0, 0x871E, 0xF2E1, 0x8725, 0xF2E2, 0x872E, 0xF2E3, 0x871A, 0xF2E4, 0x873E, + 0xF2E5, 0x8748, 0xF2E6, 0x8734, 0xF2E7, 0x8731, 0xF2E8, 0x8729, 0xF2E9, 0x8737, 0xF2EA, 0x873F, 0xF2EB, 0x8782, 0xF2EC, 0x8722, + 0xF2ED, 0x877D, 0xF2EE, 0x877E, 0xF2EF, 0x877B, 0xF2F0, 0x8760, 0xF2F1, 0x8770, 0xF2F2, 0x874C, 0xF2F3, 0x876E, 0xF2F4, 0x878B, + 0xF2F5, 0x8753, 0xF2F6, 0x8763, 0xF2F7, 0x877C, 0xF2F8, 0x8764, 0xF2F9, 0x8759, 0xF2FA, 0x8765, 0xF2FB, 0x8793, 0xF2FC, 0x87AF, + 0xF2FD, 0x87A8, 0xF2FE, 0x87D2, 0xF340, 0x9A5A, 0xF341, 0x9A5B, 0xF342, 0x9A5C, 0xF343, 0x9A5D, 0xF344, 0x9A5E, 0xF345, 0x9A5F, + 0xF346, 0x9A60, 0xF347, 0x9A61, 0xF348, 0x9A62, 0xF349, 0x9A63, 0xF34A, 0x9A64, 0xF34B, 0x9A65, 0xF34C, 0x9A66, 0xF34D, 0x9A67, + 0xF34E, 0x9A68, 0xF34F, 0x9A69, 0xF350, 0x9A6A, 0xF351, 0x9A6B, 0xF352, 0x9A72, 0xF353, 0x9A83, 0xF354, 0x9A89, 0xF355, 0x9A8D, + 0xF356, 0x9A8E, 0xF357, 0x9A94, 0xF358, 0x9A95, 0xF359, 0x9A99, 0xF35A, 0x9AA6, 0xF35B, 0x9AA9, 0xF35C, 0x9AAA, 0xF35D, 0x9AAB, + 0xF35E, 0x9AAC, 0xF35F, 0x9AAD, 0xF360, 0x9AAE, 0xF361, 0x9AAF, 0xF362, 0x9AB2, 0xF363, 0x9AB3, 0xF364, 0x9AB4, 0xF365, 0x9AB5, + 0xF366, 0x9AB9, 0xF367, 0x9ABB, 0xF368, 0x9ABD, 0xF369, 0x9ABE, 0xF36A, 0x9ABF, 0xF36B, 0x9AC3, 0xF36C, 0x9AC4, 0xF36D, 0x9AC6, + 0xF36E, 0x9AC7, 0xF36F, 0x9AC8, 0xF370, 0x9AC9, 0xF371, 0x9ACA, 0xF372, 0x9ACD, 0xF373, 0x9ACE, 0xF374, 0x9ACF, 0xF375, 0x9AD0, + 0xF376, 0x9AD2, 0xF377, 0x9AD4, 0xF378, 0x9AD5, 0xF379, 0x9AD6, 0xF37A, 0x9AD7, 0xF37B, 0x9AD9, 0xF37C, 0x9ADA, 0xF37D, 0x9ADB, + 0xF37E, 0x9ADC, 0xF380, 0x9ADD, 0xF381, 0x9ADE, 0xF382, 0x9AE0, 0xF383, 0x9AE2, 0xF384, 0x9AE3, 0xF385, 0x9AE4, 0xF386, 0x9AE5, + 0xF387, 0x9AE7, 0xF388, 0x9AE8, 0xF389, 0x9AE9, 0xF38A, 0x9AEA, 0xF38B, 0x9AEC, 0xF38C, 0x9AEE, 0xF38D, 0x9AF0, 0xF38E, 0x9AF1, + 0xF38F, 0x9AF2, 0xF390, 0x9AF3, 0xF391, 0x9AF4, 0xF392, 0x9AF5, 0xF393, 0x9AF6, 0xF394, 0x9AF7, 0xF395, 0x9AF8, 0xF396, 0x9AFA, + 0xF397, 0x9AFC, 0xF398, 0x9AFD, 0xF399, 0x9AFE, 0xF39A, 0x9AFF, 0xF39B, 0x9B00, 0xF39C, 0x9B01, 0xF39D, 0x9B02, 0xF39E, 0x9B04, + 0xF39F, 0x9B05, 0xF3A0, 0x9B06, 0xF3A1, 0x87C6, 0xF3A2, 0x8788, 0xF3A3, 0x8785, 0xF3A4, 0x87AD, 0xF3A5, 0x8797, 0xF3A6, 0x8783, + 0xF3A7, 0x87AB, 0xF3A8, 0x87E5, 0xF3A9, 0x87AC, 0xF3AA, 0x87B5, 0xF3AB, 0x87B3, 0xF3AC, 0x87CB, 0xF3AD, 0x87D3, 0xF3AE, 0x87BD, + 0xF3AF, 0x87D1, 0xF3B0, 0x87C0, 0xF3B1, 0x87CA, 0xF3B2, 0x87DB, 0xF3B3, 0x87EA, 0xF3B4, 0x87E0, 0xF3B5, 0x87EE, 0xF3B6, 0x8816, + 0xF3B7, 0x8813, 0xF3B8, 0x87FE, 0xF3B9, 0x880A, 0xF3BA, 0x881B, 0xF3BB, 0x8821, 0xF3BC, 0x8839, 0xF3BD, 0x883C, 0xF3BE, 0x7F36, + 0xF3BF, 0x7F42, 0xF3C0, 0x7F44, 0xF3C1, 0x7F45, 0xF3C2, 0x8210, 0xF3C3, 0x7AFA, 0xF3C4, 0x7AFD, 0xF3C5, 0x7B08, 0xF3C6, 0x7B03, + 0xF3C7, 0x7B04, 0xF3C8, 0x7B15, 0xF3C9, 0x7B0A, 0xF3CA, 0x7B2B, 0xF3CB, 0x7B0F, 0xF3CC, 0x7B47, 0xF3CD, 0x7B38, 0xF3CE, 0x7B2A, + 0xF3CF, 0x7B19, 0xF3D0, 0x7B2E, 0xF3D1, 0x7B31, 0xF3D2, 0x7B20, 0xF3D3, 0x7B25, 0xF3D4, 0x7B24, 0xF3D5, 0x7B33, 0xF3D6, 0x7B3E, + 0xF3D7, 0x7B1E, 0xF3D8, 0x7B58, 0xF3D9, 0x7B5A, 0xF3DA, 0x7B45, 0xF3DB, 0x7B75, 0xF3DC, 0x7B4C, 0xF3DD, 0x7B5D, 0xF3DE, 0x7B60, + 0xF3DF, 0x7B6E, 0xF3E0, 0x7B7B, 0xF3E1, 0x7B62, 0xF3E2, 0x7B72, 0xF3E3, 0x7B71, 0xF3E4, 0x7B90, 0xF3E5, 0x7BA6, 0xF3E6, 0x7BA7, + 0xF3E7, 0x7BB8, 0xF3E8, 0x7BAC, 0xF3E9, 0x7B9D, 0xF3EA, 0x7BA8, 0xF3EB, 0x7B85, 0xF3EC, 0x7BAA, 0xF3ED, 0x7B9C, 0xF3EE, 0x7BA2, + 0xF3EF, 0x7BAB, 0xF3F0, 0x7BB4, 0xF3F1, 0x7BD1, 0xF3F2, 0x7BC1, 0xF3F3, 0x7BCC, 0xF3F4, 0x7BDD, 0xF3F5, 0x7BDA, 0xF3F6, 0x7BE5, + 0xF3F7, 0x7BE6, 0xF3F8, 0x7BEA, 0xF3F9, 0x7C0C, 0xF3FA, 0x7BFE, 0xF3FB, 0x7BFC, 0xF3FC, 0x7C0F, 0xF3FD, 0x7C16, 0xF3FE, 0x7C0B, + 0xF440, 0x9B07, 0xF441, 0x9B09, 0xF442, 0x9B0A, 0xF443, 0x9B0B, 0xF444, 0x9B0C, 0xF445, 0x9B0D, 0xF446, 0x9B0E, 0xF447, 0x9B10, + 0xF448, 0x9B11, 0xF449, 0x9B12, 0xF44A, 0x9B14, 0xF44B, 0x9B15, 0xF44C, 0x9B16, 0xF44D, 0x9B17, 0xF44E, 0x9B18, 0xF44F, 0x9B19, + 0xF450, 0x9B1A, 0xF451, 0x9B1B, 0xF452, 0x9B1C, 0xF453, 0x9B1D, 0xF454, 0x9B1E, 0xF455, 0x9B20, 0xF456, 0x9B21, 0xF457, 0x9B22, + 0xF458, 0x9B24, 0xF459, 0x9B25, 0xF45A, 0x9B26, 0xF45B, 0x9B27, 0xF45C, 0x9B28, 0xF45D, 0x9B29, 0xF45E, 0x9B2A, 0xF45F, 0x9B2B, + 0xF460, 0x9B2C, 0xF461, 0x9B2D, 0xF462, 0x9B2E, 0xF463, 0x9B30, 0xF464, 0x9B31, 0xF465, 0x9B33, 0xF466, 0x9B34, 0xF467, 0x9B35, + 0xF468, 0x9B36, 0xF469, 0x9B37, 0xF46A, 0x9B38, 0xF46B, 0x9B39, 0xF46C, 0x9B3A, 0xF46D, 0x9B3D, 0xF46E, 0x9B3E, 0xF46F, 0x9B3F, + 0xF470, 0x9B40, 0xF471, 0x9B46, 0xF472, 0x9B4A, 0xF473, 0x9B4B, 0xF474, 0x9B4C, 0xF475, 0x9B4E, 0xF476, 0x9B50, 0xF477, 0x9B52, + 0xF478, 0x9B53, 0xF479, 0x9B55, 0xF47A, 0x9B56, 0xF47B, 0x9B57, 0xF47C, 0x9B58, 0xF47D, 0x9B59, 0xF47E, 0x9B5A, 0xF480, 0x9B5B, + 0xF481, 0x9B5C, 0xF482, 0x9B5D, 0xF483, 0x9B5E, 0xF484, 0x9B5F, 0xF485, 0x9B60, 0xF486, 0x9B61, 0xF487, 0x9B62, 0xF488, 0x9B63, + 0xF489, 0x9B64, 0xF48A, 0x9B65, 0xF48B, 0x9B66, 0xF48C, 0x9B67, 0xF48D, 0x9B68, 0xF48E, 0x9B69, 0xF48F, 0x9B6A, 0xF490, 0x9B6B, + 0xF491, 0x9B6C, 0xF492, 0x9B6D, 0xF493, 0x9B6E, 0xF494, 0x9B6F, 0xF495, 0x9B70, 0xF496, 0x9B71, 0xF497, 0x9B72, 0xF498, 0x9B73, + 0xF499, 0x9B74, 0xF49A, 0x9B75, 0xF49B, 0x9B76, 0xF49C, 0x9B77, 0xF49D, 0x9B78, 0xF49E, 0x9B79, 0xF49F, 0x9B7A, 0xF4A0, 0x9B7B, + 0xF4A1, 0x7C1F, 0xF4A2, 0x7C2A, 0xF4A3, 0x7C26, 0xF4A4, 0x7C38, 0xF4A5, 0x7C41, 0xF4A6, 0x7C40, 0xF4A7, 0x81FE, 0xF4A8, 0x8201, + 0xF4A9, 0x8202, 0xF4AA, 0x8204, 0xF4AB, 0x81EC, 0xF4AC, 0x8844, 0xF4AD, 0x8221, 0xF4AE, 0x8222, 0xF4AF, 0x8223, 0xF4B0, 0x822D, + 0xF4B1, 0x822F, 0xF4B2, 0x8228, 0xF4B3, 0x822B, 0xF4B4, 0x8238, 0xF4B5, 0x823B, 0xF4B6, 0x8233, 0xF4B7, 0x8234, 0xF4B8, 0x823E, + 0xF4B9, 0x8244, 0xF4BA, 0x8249, 0xF4BB, 0x824B, 0xF4BC, 0x824F, 0xF4BD, 0x825A, 0xF4BE, 0x825F, 0xF4BF, 0x8268, 0xF4C0, 0x887E, + 0xF4C1, 0x8885, 0xF4C2, 0x8888, 0xF4C3, 0x88D8, 0xF4C4, 0x88DF, 0xF4C5, 0x895E, 0xF4C6, 0x7F9D, 0xF4C7, 0x7F9F, 0xF4C8, 0x7FA7, + 0xF4C9, 0x7FAF, 0xF4CA, 0x7FB0, 0xF4CB, 0x7FB2, 0xF4CC, 0x7C7C, 0xF4CD, 0x6549, 0xF4CE, 0x7C91, 0xF4CF, 0x7C9D, 0xF4D0, 0x7C9C, + 0xF4D1, 0x7C9E, 0xF4D2, 0x7CA2, 0xF4D3, 0x7CB2, 0xF4D4, 0x7CBC, 0xF4D5, 0x7CBD, 0xF4D6, 0x7CC1, 0xF4D7, 0x7CC7, 0xF4D8, 0x7CCC, + 0xF4D9, 0x7CCD, 0xF4DA, 0x7CC8, 0xF4DB, 0x7CC5, 0xF4DC, 0x7CD7, 0xF4DD, 0x7CE8, 0xF4DE, 0x826E, 0xF4DF, 0x66A8, 0xF4E0, 0x7FBF, + 0xF4E1, 0x7FCE, 0xF4E2, 0x7FD5, 0xF4E3, 0x7FE5, 0xF4E4, 0x7FE1, 0xF4E5, 0x7FE6, 0xF4E6, 0x7FE9, 0xF4E7, 0x7FEE, 0xF4E8, 0x7FF3, + 0xF4E9, 0x7CF8, 0xF4EA, 0x7D77, 0xF4EB, 0x7DA6, 0xF4EC, 0x7DAE, 0xF4ED, 0x7E47, 0xF4EE, 0x7E9B, 0xF4EF, 0x9EB8, 0xF4F0, 0x9EB4, + 0xF4F1, 0x8D73, 0xF4F2, 0x8D84, 0xF4F3, 0x8D94, 0xF4F4, 0x8D91, 0xF4F5, 0x8DB1, 0xF4F6, 0x8D67, 0xF4F7, 0x8D6D, 0xF4F8, 0x8C47, + 0xF4F9, 0x8C49, 0xF4FA, 0x914A, 0xF4FB, 0x9150, 0xF4FC, 0x914E, 0xF4FD, 0x914F, 0xF4FE, 0x9164, 0xF540, 0x9B7C, 0xF541, 0x9B7D, + 0xF542, 0x9B7E, 0xF543, 0x9B7F, 0xF544, 0x9B80, 0xF545, 0x9B81, 0xF546, 0x9B82, 0xF547, 0x9B83, 0xF548, 0x9B84, 0xF549, 0x9B85, + 0xF54A, 0x9B86, 0xF54B, 0x9B87, 0xF54C, 0x9B88, 0xF54D, 0x9B89, 0xF54E, 0x9B8A, 0xF54F, 0x9B8B, 0xF550, 0x9B8C, 0xF551, 0x9B8D, + 0xF552, 0x9B8E, 0xF553, 0x9B8F, 0xF554, 0x9B90, 0xF555, 0x9B91, 0xF556, 0x9B92, 0xF557, 0x9B93, 0xF558, 0x9B94, 0xF559, 0x9B95, + 0xF55A, 0x9B96, 0xF55B, 0x9B97, 0xF55C, 0x9B98, 0xF55D, 0x9B99, 0xF55E, 0x9B9A, 0xF55F, 0x9B9B, 0xF560, 0x9B9C, 0xF561, 0x9B9D, + 0xF562, 0x9B9E, 0xF563, 0x9B9F, 0xF564, 0x9BA0, 0xF565, 0x9BA1, 0xF566, 0x9BA2, 0xF567, 0x9BA3, 0xF568, 0x9BA4, 0xF569, 0x9BA5, + 0xF56A, 0x9BA6, 0xF56B, 0x9BA7, 0xF56C, 0x9BA8, 0xF56D, 0x9BA9, 0xF56E, 0x9BAA, 0xF56F, 0x9BAB, 0xF570, 0x9BAC, 0xF571, 0x9BAD, + 0xF572, 0x9BAE, 0xF573, 0x9BAF, 0xF574, 0x9BB0, 0xF575, 0x9BB1, 0xF576, 0x9BB2, 0xF577, 0x9BB3, 0xF578, 0x9BB4, 0xF579, 0x9BB5, + 0xF57A, 0x9BB6, 0xF57B, 0x9BB7, 0xF57C, 0x9BB8, 0xF57D, 0x9BB9, 0xF57E, 0x9BBA, 0xF580, 0x9BBB, 0xF581, 0x9BBC, 0xF582, 0x9BBD, + 0xF583, 0x9BBE, 0xF584, 0x9BBF, 0xF585, 0x9BC0, 0xF586, 0x9BC1, 0xF587, 0x9BC2, 0xF588, 0x9BC3, 0xF589, 0x9BC4, 0xF58A, 0x9BC5, + 0xF58B, 0x9BC6, 0xF58C, 0x9BC7, 0xF58D, 0x9BC8, 0xF58E, 0x9BC9, 0xF58F, 0x9BCA, 0xF590, 0x9BCB, 0xF591, 0x9BCC, 0xF592, 0x9BCD, + 0xF593, 0x9BCE, 0xF594, 0x9BCF, 0xF595, 0x9BD0, 0xF596, 0x9BD1, 0xF597, 0x9BD2, 0xF598, 0x9BD3, 0xF599, 0x9BD4, 0xF59A, 0x9BD5, + 0xF59B, 0x9BD6, 0xF59C, 0x9BD7, 0xF59D, 0x9BD8, 0xF59E, 0x9BD9, 0xF59F, 0x9BDA, 0xF5A0, 0x9BDB, 0xF5A1, 0x9162, 0xF5A2, 0x9161, + 0xF5A3, 0x9170, 0xF5A4, 0x9169, 0xF5A5, 0x916F, 0xF5A6, 0x917D, 0xF5A7, 0x917E, 0xF5A8, 0x9172, 0xF5A9, 0x9174, 0xF5AA, 0x9179, + 0xF5AB, 0x918C, 0xF5AC, 0x9185, 0xF5AD, 0x9190, 0xF5AE, 0x918D, 0xF5AF, 0x9191, 0xF5B0, 0x91A2, 0xF5B1, 0x91A3, 0xF5B2, 0x91AA, + 0xF5B3, 0x91AD, 0xF5B4, 0x91AE, 0xF5B5, 0x91AF, 0xF5B6, 0x91B5, 0xF5B7, 0x91B4, 0xF5B8, 0x91BA, 0xF5B9, 0x8C55, 0xF5BA, 0x9E7E, + 0xF5BB, 0x8DB8, 0xF5BC, 0x8DEB, 0xF5BD, 0x8E05, 0xF5BE, 0x8E59, 0xF5BF, 0x8E69, 0xF5C0, 0x8DB5, 0xF5C1, 0x8DBF, 0xF5C2, 0x8DBC, + 0xF5C3, 0x8DBA, 0xF5C4, 0x8DC4, 0xF5C5, 0x8DD6, 0xF5C6, 0x8DD7, 0xF5C7, 0x8DDA, 0xF5C8, 0x8DDE, 0xF5C9, 0x8DCE, 0xF5CA, 0x8DCF, + 0xF5CB, 0x8DDB, 0xF5CC, 0x8DC6, 0xF5CD, 0x8DEC, 0xF5CE, 0x8DF7, 0xF5CF, 0x8DF8, 0xF5D0, 0x8DE3, 0xF5D1, 0x8DF9, 0xF5D2, 0x8DFB, + 0xF5D3, 0x8DE4, 0xF5D4, 0x8E09, 0xF5D5, 0x8DFD, 0xF5D6, 0x8E14, 0xF5D7, 0x8E1D, 0xF5D8, 0x8E1F, 0xF5D9, 0x8E2C, 0xF5DA, 0x8E2E, + 0xF5DB, 0x8E23, 0xF5DC, 0x8E2F, 0xF5DD, 0x8E3A, 0xF5DE, 0x8E40, 0xF5DF, 0x8E39, 0xF5E0, 0x8E35, 0xF5E1, 0x8E3D, 0xF5E2, 0x8E31, + 0xF5E3, 0x8E49, 0xF5E4, 0x8E41, 0xF5E5, 0x8E42, 0xF5E6, 0x8E51, 0xF5E7, 0x8E52, 0xF5E8, 0x8E4A, 0xF5E9, 0x8E70, 0xF5EA, 0x8E76, + 0xF5EB, 0x8E7C, 0xF5EC, 0x8E6F, 0xF5ED, 0x8E74, 0xF5EE, 0x8E85, 0xF5EF, 0x8E8F, 0xF5F0, 0x8E94, 0xF5F1, 0x8E90, 0xF5F2, 0x8E9C, + 0xF5F3, 0x8E9E, 0xF5F4, 0x8C78, 0xF5F5, 0x8C82, 0xF5F6, 0x8C8A, 0xF5F7, 0x8C85, 0xF5F8, 0x8C98, 0xF5F9, 0x8C94, 0xF5FA, 0x659B, + 0xF5FB, 0x89D6, 0xF5FC, 0x89DE, 0xF5FD, 0x89DA, 0xF5FE, 0x89DC, 0xF640, 0x9BDC, 0xF641, 0x9BDD, 0xF642, 0x9BDE, 0xF643, 0x9BDF, + 0xF644, 0x9BE0, 0xF645, 0x9BE1, 0xF646, 0x9BE2, 0xF647, 0x9BE3, 0xF648, 0x9BE4, 0xF649, 0x9BE5, 0xF64A, 0x9BE6, 0xF64B, 0x9BE7, + 0xF64C, 0x9BE8, 0xF64D, 0x9BE9, 0xF64E, 0x9BEA, 0xF64F, 0x9BEB, 0xF650, 0x9BEC, 0xF651, 0x9BED, 0xF652, 0x9BEE, 0xF653, 0x9BEF, + 0xF654, 0x9BF0, 0xF655, 0x9BF1, 0xF656, 0x9BF2, 0xF657, 0x9BF3, 0xF658, 0x9BF4, 0xF659, 0x9BF5, 0xF65A, 0x9BF6, 0xF65B, 0x9BF7, + 0xF65C, 0x9BF8, 0xF65D, 0x9BF9, 0xF65E, 0x9BFA, 0xF65F, 0x9BFB, 0xF660, 0x9BFC, 0xF661, 0x9BFD, 0xF662, 0x9BFE, 0xF663, 0x9BFF, + 0xF664, 0x9C00, 0xF665, 0x9C01, 0xF666, 0x9C02, 0xF667, 0x9C03, 0xF668, 0x9C04, 0xF669, 0x9C05, 0xF66A, 0x9C06, 0xF66B, 0x9C07, + 0xF66C, 0x9C08, 0xF66D, 0x9C09, 0xF66E, 0x9C0A, 0xF66F, 0x9C0B, 0xF670, 0x9C0C, 0xF671, 0x9C0D, 0xF672, 0x9C0E, 0xF673, 0x9C0F, + 0xF674, 0x9C10, 0xF675, 0x9C11, 0xF676, 0x9C12, 0xF677, 0x9C13, 0xF678, 0x9C14, 0xF679, 0x9C15, 0xF67A, 0x9C16, 0xF67B, 0x9C17, + 0xF67C, 0x9C18, 0xF67D, 0x9C19, 0xF67E, 0x9C1A, 0xF680, 0x9C1B, 0xF681, 0x9C1C, 0xF682, 0x9C1D, 0xF683, 0x9C1E, 0xF684, 0x9C1F, + 0xF685, 0x9C20, 0xF686, 0x9C21, 0xF687, 0x9C22, 0xF688, 0x9C23, 0xF689, 0x9C24, 0xF68A, 0x9C25, 0xF68B, 0x9C26, 0xF68C, 0x9C27, + 0xF68D, 0x9C28, 0xF68E, 0x9C29, 0xF68F, 0x9C2A, 0xF690, 0x9C2B, 0xF691, 0x9C2C, 0xF692, 0x9C2D, 0xF693, 0x9C2E, 0xF694, 0x9C2F, + 0xF695, 0x9C30, 0xF696, 0x9C31, 0xF697, 0x9C32, 0xF698, 0x9C33, 0xF699, 0x9C34, 0xF69A, 0x9C35, 0xF69B, 0x9C36, 0xF69C, 0x9C37, + 0xF69D, 0x9C38, 0xF69E, 0x9C39, 0xF69F, 0x9C3A, 0xF6A0, 0x9C3B, 0xF6A1, 0x89E5, 0xF6A2, 0x89EB, 0xF6A3, 0x89EF, 0xF6A4, 0x8A3E, + 0xF6A5, 0x8B26, 0xF6A6, 0x9753, 0xF6A7, 0x96E9, 0xF6A8, 0x96F3, 0xF6A9, 0x96EF, 0xF6AA, 0x9706, 0xF6AB, 0x9701, 0xF6AC, 0x9708, + 0xF6AD, 0x970F, 0xF6AE, 0x970E, 0xF6AF, 0x972A, 0xF6B0, 0x972D, 0xF6B1, 0x9730, 0xF6B2, 0x973E, 0xF6B3, 0x9F80, 0xF6B4, 0x9F83, + 0xF6B5, 0x9F85, 0xF6B6, 0x9F86, 0xF6B7, 0x9F87, 0xF6B8, 0x9F88, 0xF6B9, 0x9F89, 0xF6BA, 0x9F8A, 0xF6BB, 0x9F8C, 0xF6BC, 0x9EFE, + 0xF6BD, 0x9F0B, 0xF6BE, 0x9F0D, 0xF6BF, 0x96B9, 0xF6C0, 0x96BC, 0xF6C1, 0x96BD, 0xF6C2, 0x96CE, 0xF6C3, 0x96D2, 0xF6C4, 0x77BF, + 0xF6C5, 0x96E0, 0xF6C6, 0x928E, 0xF6C7, 0x92AE, 0xF6C8, 0x92C8, 0xF6C9, 0x933E, 0xF6CA, 0x936A, 0xF6CB, 0x93CA, 0xF6CC, 0x938F, + 0xF6CD, 0x943E, 0xF6CE, 0x946B, 0xF6CF, 0x9C7F, 0xF6D0, 0x9C82, 0xF6D1, 0x9C85, 0xF6D2, 0x9C86, 0xF6D3, 0x9C87, 0xF6D4, 0x9C88, + 0xF6D5, 0x7A23, 0xF6D6, 0x9C8B, 0xF6D7, 0x9C8E, 0xF6D8, 0x9C90, 0xF6D9, 0x9C91, 0xF6DA, 0x9C92, 0xF6DB, 0x9C94, 0xF6DC, 0x9C95, + 0xF6DD, 0x9C9A, 0xF6DE, 0x9C9B, 0xF6DF, 0x9C9E, 0xF6E0, 0x9C9F, 0xF6E1, 0x9CA0, 0xF6E2, 0x9CA1, 0xF6E3, 0x9CA2, 0xF6E4, 0x9CA3, + 0xF6E5, 0x9CA5, 0xF6E6, 0x9CA6, 0xF6E7, 0x9CA7, 0xF6E8, 0x9CA8, 0xF6E9, 0x9CA9, 0xF6EA, 0x9CAB, 0xF6EB, 0x9CAD, 0xF6EC, 0x9CAE, + 0xF6ED, 0x9CB0, 0xF6EE, 0x9CB1, 0xF6EF, 0x9CB2, 0xF6F0, 0x9CB3, 0xF6F1, 0x9CB4, 0xF6F2, 0x9CB5, 0xF6F3, 0x9CB6, 0xF6F4, 0x9CB7, + 0xF6F5, 0x9CBA, 0xF6F6, 0x9CBB, 0xF6F7, 0x9CBC, 0xF6F8, 0x9CBD, 0xF6F9, 0x9CC4, 0xF6FA, 0x9CC5, 0xF6FB, 0x9CC6, 0xF6FC, 0x9CC7, + 0xF6FD, 0x9CCA, 0xF6FE, 0x9CCB, 0xF740, 0x9C3C, 0xF741, 0x9C3D, 0xF742, 0x9C3E, 0xF743, 0x9C3F, 0xF744, 0x9C40, 0xF745, 0x9C41, + 0xF746, 0x9C42, 0xF747, 0x9C43, 0xF748, 0x9C44, 0xF749, 0x9C45, 0xF74A, 0x9C46, 0xF74B, 0x9C47, 0xF74C, 0x9C48, 0xF74D, 0x9C49, + 0xF74E, 0x9C4A, 0xF74F, 0x9C4B, 0xF750, 0x9C4C, 0xF751, 0x9C4D, 0xF752, 0x9C4E, 0xF753, 0x9C4F, 0xF754, 0x9C50, 0xF755, 0x9C51, + 0xF756, 0x9C52, 0xF757, 0x9C53, 0xF758, 0x9C54, 0xF759, 0x9C55, 0xF75A, 0x9C56, 0xF75B, 0x9C57, 0xF75C, 0x9C58, 0xF75D, 0x9C59, + 0xF75E, 0x9C5A, 0xF75F, 0x9C5B, 0xF760, 0x9C5C, 0xF761, 0x9C5D, 0xF762, 0x9C5E, 0xF763, 0x9C5F, 0xF764, 0x9C60, 0xF765, 0x9C61, + 0xF766, 0x9C62, 0xF767, 0x9C63, 0xF768, 0x9C64, 0xF769, 0x9C65, 0xF76A, 0x9C66, 0xF76B, 0x9C67, 0xF76C, 0x9C68, 0xF76D, 0x9C69, + 0xF76E, 0x9C6A, 0xF76F, 0x9C6B, 0xF770, 0x9C6C, 0xF771, 0x9C6D, 0xF772, 0x9C6E, 0xF773, 0x9C6F, 0xF774, 0x9C70, 0xF775, 0x9C71, + 0xF776, 0x9C72, 0xF777, 0x9C73, 0xF778, 0x9C74, 0xF779, 0x9C75, 0xF77A, 0x9C76, 0xF77B, 0x9C77, 0xF77C, 0x9C78, 0xF77D, 0x9C79, + 0xF77E, 0x9C7A, 0xF780, 0x9C7B, 0xF781, 0x9C7D, 0xF782, 0x9C7E, 0xF783, 0x9C80, 0xF784, 0x9C83, 0xF785, 0x9C84, 0xF786, 0x9C89, + 0xF787, 0x9C8A, 0xF788, 0x9C8C, 0xF789, 0x9C8F, 0xF78A, 0x9C93, 0xF78B, 0x9C96, 0xF78C, 0x9C97, 0xF78D, 0x9C98, 0xF78E, 0x9C99, + 0xF78F, 0x9C9D, 0xF790, 0x9CAA, 0xF791, 0x9CAC, 0xF792, 0x9CAF, 0xF793, 0x9CB9, 0xF794, 0x9CBE, 0xF795, 0x9CBF, 0xF796, 0x9CC0, + 0xF797, 0x9CC1, 0xF798, 0x9CC2, 0xF799, 0x9CC8, 0xF79A, 0x9CC9, 0xF79B, 0x9CD1, 0xF79C, 0x9CD2, 0xF79D, 0x9CDA, 0xF79E, 0x9CDB, + 0xF79F, 0x9CE0, 0xF7A0, 0x9CE1, 0xF7A1, 0x9CCC, 0xF7A2, 0x9CCD, 0xF7A3, 0x9CCE, 0xF7A4, 0x9CCF, 0xF7A5, 0x9CD0, 0xF7A6, 0x9CD3, + 0xF7A7, 0x9CD4, 0xF7A8, 0x9CD5, 0xF7A9, 0x9CD7, 0xF7AA, 0x9CD8, 0xF7AB, 0x9CD9, 0xF7AC, 0x9CDC, 0xF7AD, 0x9CDD, 0xF7AE, 0x9CDF, + 0xF7AF, 0x9CE2, 0xF7B0, 0x977C, 0xF7B1, 0x9785, 0xF7B2, 0x9791, 0xF7B3, 0x9792, 0xF7B4, 0x9794, 0xF7B5, 0x97AF, 0xF7B6, 0x97AB, + 0xF7B7, 0x97A3, 0xF7B8, 0x97B2, 0xF7B9, 0x97B4, 0xF7BA, 0x9AB1, 0xF7BB, 0x9AB0, 0xF7BC, 0x9AB7, 0xF7BD, 0x9E58, 0xF7BE, 0x9AB6, + 0xF7BF, 0x9ABA, 0xF7C0, 0x9ABC, 0xF7C1, 0x9AC1, 0xF7C2, 0x9AC0, 0xF7C3, 0x9AC5, 0xF7C4, 0x9AC2, 0xF7C5, 0x9ACB, 0xF7C6, 0x9ACC, + 0xF7C7, 0x9AD1, 0xF7C8, 0x9B45, 0xF7C9, 0x9B43, 0xF7CA, 0x9B47, 0xF7CB, 0x9B49, 0xF7CC, 0x9B48, 0xF7CD, 0x9B4D, 0xF7CE, 0x9B51, + 0xF7CF, 0x98E8, 0xF7D0, 0x990D, 0xF7D1, 0x992E, 0xF7D2, 0x9955, 0xF7D3, 0x9954, 0xF7D4, 0x9ADF, 0xF7D5, 0x9AE1, 0xF7D6, 0x9AE6, + 0xF7D7, 0x9AEF, 0xF7D8, 0x9AEB, 0xF7D9, 0x9AFB, 0xF7DA, 0x9AED, 0xF7DB, 0x9AF9, 0xF7DC, 0x9B08, 0xF7DD, 0x9B0F, 0xF7DE, 0x9B13, + 0xF7DF, 0x9B1F, 0xF7E0, 0x9B23, 0xF7E1, 0x9EBD, 0xF7E2, 0x9EBE, 0xF7E3, 0x7E3B, 0xF7E4, 0x9E82, 0xF7E5, 0x9E87, 0xF7E6, 0x9E88, + 0xF7E7, 0x9E8B, 0xF7E8, 0x9E92, 0xF7E9, 0x93D6, 0xF7EA, 0x9E9D, 0xF7EB, 0x9E9F, 0xF7EC, 0x9EDB, 0xF7ED, 0x9EDC, 0xF7EE, 0x9EDD, + 0xF7EF, 0x9EE0, 0xF7F0, 0x9EDF, 0xF7F1, 0x9EE2, 0xF7F2, 0x9EE9, 0xF7F3, 0x9EE7, 0xF7F4, 0x9EE5, 0xF7F5, 0x9EEA, 0xF7F6, 0x9EEF, + 0xF7F7, 0x9F22, 0xF7F8, 0x9F2C, 0xF7F9, 0x9F2F, 0xF7FA, 0x9F39, 0xF7FB, 0x9F37, 0xF7FC, 0x9F3D, 0xF7FD, 0x9F3E, 0xF7FE, 0x9F44, + 0xF840, 0x9CE3, 0xF841, 0x9CE4, 0xF842, 0x9CE5, 0xF843, 0x9CE6, 0xF844, 0x9CE7, 0xF845, 0x9CE8, 0xF846, 0x9CE9, 0xF847, 0x9CEA, + 0xF848, 0x9CEB, 0xF849, 0x9CEC, 0xF84A, 0x9CED, 0xF84B, 0x9CEE, 0xF84C, 0x9CEF, 0xF84D, 0x9CF0, 0xF84E, 0x9CF1, 0xF84F, 0x9CF2, + 0xF850, 0x9CF3, 0xF851, 0x9CF4, 0xF852, 0x9CF5, 0xF853, 0x9CF6, 0xF854, 0x9CF7, 0xF855, 0x9CF8, 0xF856, 0x9CF9, 0xF857, 0x9CFA, + 0xF858, 0x9CFB, 0xF859, 0x9CFC, 0xF85A, 0x9CFD, 0xF85B, 0x9CFE, 0xF85C, 0x9CFF, 0xF85D, 0x9D00, 0xF85E, 0x9D01, 0xF85F, 0x9D02, + 0xF860, 0x9D03, 0xF861, 0x9D04, 0xF862, 0x9D05, 0xF863, 0x9D06, 0xF864, 0x9D07, 0xF865, 0x9D08, 0xF866, 0x9D09, 0xF867, 0x9D0A, + 0xF868, 0x9D0B, 0xF869, 0x9D0C, 0xF86A, 0x9D0D, 0xF86B, 0x9D0E, 0xF86C, 0x9D0F, 0xF86D, 0x9D10, 0xF86E, 0x9D11, 0xF86F, 0x9D12, + 0xF870, 0x9D13, 0xF871, 0x9D14, 0xF872, 0x9D15, 0xF873, 0x9D16, 0xF874, 0x9D17, 0xF875, 0x9D18, 0xF876, 0x9D19, 0xF877, 0x9D1A, + 0xF878, 0x9D1B, 0xF879, 0x9D1C, 0xF87A, 0x9D1D, 0xF87B, 0x9D1E, 0xF87C, 0x9D1F, 0xF87D, 0x9D20, 0xF87E, 0x9D21, 0xF880, 0x9D22, + 0xF881, 0x9D23, 0xF882, 0x9D24, 0xF883, 0x9D25, 0xF884, 0x9D26, 0xF885, 0x9D27, 0xF886, 0x9D28, 0xF887, 0x9D29, 0xF888, 0x9D2A, + 0xF889, 0x9D2B, 0xF88A, 0x9D2C, 0xF88B, 0x9D2D, 0xF88C, 0x9D2E, 0xF88D, 0x9D2F, 0xF88E, 0x9D30, 0xF88F, 0x9D31, 0xF890, 0x9D32, + 0xF891, 0x9D33, 0xF892, 0x9D34, 0xF893, 0x9D35, 0xF894, 0x9D36, 0xF895, 0x9D37, 0xF896, 0x9D38, 0xF897, 0x9D39, 0xF898, 0x9D3A, + 0xF899, 0x9D3B, 0xF89A, 0x9D3C, 0xF89B, 0x9D3D, 0xF89C, 0x9D3E, 0xF89D, 0x9D3F, 0xF89E, 0x9D40, 0xF89F, 0x9D41, 0xF8A0, 0x9D42, + 0xF940, 0x9D43, 0xF941, 0x9D44, 0xF942, 0x9D45, 0xF943, 0x9D46, 0xF944, 0x9D47, 0xF945, 0x9D48, 0xF946, 0x9D49, 0xF947, 0x9D4A, + 0xF948, 0x9D4B, 0xF949, 0x9D4C, 0xF94A, 0x9D4D, 0xF94B, 0x9D4E, 0xF94C, 0x9D4F, 0xF94D, 0x9D50, 0xF94E, 0x9D51, 0xF94F, 0x9D52, + 0xF950, 0x9D53, 0xF951, 0x9D54, 0xF952, 0x9D55, 0xF953, 0x9D56, 0xF954, 0x9D57, 0xF955, 0x9D58, 0xF956, 0x9D59, 0xF957, 0x9D5A, + 0xF958, 0x9D5B, 0xF959, 0x9D5C, 0xF95A, 0x9D5D, 0xF95B, 0x9D5E, 0xF95C, 0x9D5F, 0xF95D, 0x9D60, 0xF95E, 0x9D61, 0xF95F, 0x9D62, + 0xF960, 0x9D63, 0xF961, 0x9D64, 0xF962, 0x9D65, 0xF963, 0x9D66, 0xF964, 0x9D67, 0xF965, 0x9D68, 0xF966, 0x9D69, 0xF967, 0x9D6A, + 0xF968, 0x9D6B, 0xF969, 0x9D6C, 0xF96A, 0x9D6D, 0xF96B, 0x9D6E, 0xF96C, 0x9D6F, 0xF96D, 0x9D70, 0xF96E, 0x9D71, 0xF96F, 0x9D72, + 0xF970, 0x9D73, 0xF971, 0x9D74, 0xF972, 0x9D75, 0xF973, 0x9D76, 0xF974, 0x9D77, 0xF975, 0x9D78, 0xF976, 0x9D79, 0xF977, 0x9D7A, + 0xF978, 0x9D7B, 0xF979, 0x9D7C, 0xF97A, 0x9D7D, 0xF97B, 0x9D7E, 0xF97C, 0x9D7F, 0xF97D, 0x9D80, 0xF97E, 0x9D81, 0xF980, 0x9D82, + 0xF981, 0x9D83, 0xF982, 0x9D84, 0xF983, 0x9D85, 0xF984, 0x9D86, 0xF985, 0x9D87, 0xF986, 0x9D88, 0xF987, 0x9D89, 0xF988, 0x9D8A, + 0xF989, 0x9D8B, 0xF98A, 0x9D8C, 0xF98B, 0x9D8D, 0xF98C, 0x9D8E, 0xF98D, 0x9D8F, 0xF98E, 0x9D90, 0xF98F, 0x9D91, 0xF990, 0x9D92, + 0xF991, 0x9D93, 0xF992, 0x9D94, 0xF993, 0x9D95, 0xF994, 0x9D96, 0xF995, 0x9D97, 0xF996, 0x9D98, 0xF997, 0x9D99, 0xF998, 0x9D9A, + 0xF999, 0x9D9B, 0xF99A, 0x9D9C, 0xF99B, 0x9D9D, 0xF99C, 0x9D9E, 0xF99D, 0x9D9F, 0xF99E, 0x9DA0, 0xF99F, 0x9DA1, 0xF9A0, 0x9DA2, + 0xFA40, 0x9DA3, 0xFA41, 0x9DA4, 0xFA42, 0x9DA5, 0xFA43, 0x9DA6, 0xFA44, 0x9DA7, 0xFA45, 0x9DA8, 0xFA46, 0x9DA9, 0xFA47, 0x9DAA, + 0xFA48, 0x9DAB, 0xFA49, 0x9DAC, 0xFA4A, 0x9DAD, 0xFA4B, 0x9DAE, 0xFA4C, 0x9DAF, 0xFA4D, 0x9DB0, 0xFA4E, 0x9DB1, 0xFA4F, 0x9DB2, + 0xFA50, 0x9DB3, 0xFA51, 0x9DB4, 0xFA52, 0x9DB5, 0xFA53, 0x9DB6, 0xFA54, 0x9DB7, 0xFA55, 0x9DB8, 0xFA56, 0x9DB9, 0xFA57, 0x9DBA, + 0xFA58, 0x9DBB, 0xFA59, 0x9DBC, 0xFA5A, 0x9DBD, 0xFA5B, 0x9DBE, 0xFA5C, 0x9DBF, 0xFA5D, 0x9DC0, 0xFA5E, 0x9DC1, 0xFA5F, 0x9DC2, + 0xFA60, 0x9DC3, 0xFA61, 0x9DC4, 0xFA62, 0x9DC5, 0xFA63, 0x9DC6, 0xFA64, 0x9DC7, 0xFA65, 0x9DC8, 0xFA66, 0x9DC9, 0xFA67, 0x9DCA, + 0xFA68, 0x9DCB, 0xFA69, 0x9DCC, 0xFA6A, 0x9DCD, 0xFA6B, 0x9DCE, 0xFA6C, 0x9DCF, 0xFA6D, 0x9DD0, 0xFA6E, 0x9DD1, 0xFA6F, 0x9DD2, + 0xFA70, 0x9DD3, 0xFA71, 0x9DD4, 0xFA72, 0x9DD5, 0xFA73, 0x9DD6, 0xFA74, 0x9DD7, 0xFA75, 0x9DD8, 0xFA76, 0x9DD9, 0xFA77, 0x9DDA, + 0xFA78, 0x9DDB, 0xFA79, 0x9DDC, 0xFA7A, 0x9DDD, 0xFA7B, 0x9DDE, 0xFA7C, 0x9DDF, 0xFA7D, 0x9DE0, 0xFA7E, 0x9DE1, 0xFA80, 0x9DE2, + 0xFA81, 0x9DE3, 0xFA82, 0x9DE4, 0xFA83, 0x9DE5, 0xFA84, 0x9DE6, 0xFA85, 0x9DE7, 0xFA86, 0x9DE8, 0xFA87, 0x9DE9, 0xFA88, 0x9DEA, + 0xFA89, 0x9DEB, 0xFA8A, 0x9DEC, 0xFA8B, 0x9DED, 0xFA8C, 0x9DEE, 0xFA8D, 0x9DEF, 0xFA8E, 0x9DF0, 0xFA8F, 0x9DF1, 0xFA90, 0x9DF2, + 0xFA91, 0x9DF3, 0xFA92, 0x9DF4, 0xFA93, 0x9DF5, 0xFA94, 0x9DF6, 0xFA95, 0x9DF7, 0xFA96, 0x9DF8, 0xFA97, 0x9DF9, 0xFA98, 0x9DFA, + 0xFA99, 0x9DFB, 0xFA9A, 0x9DFC, 0xFA9B, 0x9DFD, 0xFA9C, 0x9DFE, 0xFA9D, 0x9DFF, 0xFA9E, 0x9E00, 0xFA9F, 0x9E01, 0xFAA0, 0x9E02, + 0xFB40, 0x9E03, 0xFB41, 0x9E04, 0xFB42, 0x9E05, 0xFB43, 0x9E06, 0xFB44, 0x9E07, 0xFB45, 0x9E08, 0xFB46, 0x9E09, 0xFB47, 0x9E0A, + 0xFB48, 0x9E0B, 0xFB49, 0x9E0C, 0xFB4A, 0x9E0D, 0xFB4B, 0x9E0E, 0xFB4C, 0x9E0F, 0xFB4D, 0x9E10, 0xFB4E, 0x9E11, 0xFB4F, 0x9E12, + 0xFB50, 0x9E13, 0xFB51, 0x9E14, 0xFB52, 0x9E15, 0xFB53, 0x9E16, 0xFB54, 0x9E17, 0xFB55, 0x9E18, 0xFB56, 0x9E19, 0xFB57, 0x9E1A, + 0xFB58, 0x9E1B, 0xFB59, 0x9E1C, 0xFB5A, 0x9E1D, 0xFB5B, 0x9E1E, 0xFB5C, 0x9E24, 0xFB5D, 0x9E27, 0xFB5E, 0x9E2E, 0xFB5F, 0x9E30, + 0xFB60, 0x9E34, 0xFB61, 0x9E3B, 0xFB62, 0x9E3C, 0xFB63, 0x9E40, 0xFB64, 0x9E4D, 0xFB65, 0x9E50, 0xFB66, 0x9E52, 0xFB67, 0x9E53, + 0xFB68, 0x9E54, 0xFB69, 0x9E56, 0xFB6A, 0x9E59, 0xFB6B, 0x9E5D, 0xFB6C, 0x9E5F, 0xFB6D, 0x9E60, 0xFB6E, 0x9E61, 0xFB6F, 0x9E62, + 0xFB70, 0x9E65, 0xFB71, 0x9E6E, 0xFB72, 0x9E6F, 0xFB73, 0x9E72, 0xFB74, 0x9E74, 0xFB75, 0x9E75, 0xFB76, 0x9E76, 0xFB77, 0x9E77, + 0xFB78, 0x9E78, 0xFB79, 0x9E79, 0xFB7A, 0x9E7A, 0xFB7B, 0x9E7B, 0xFB7C, 0x9E7C, 0xFB7D, 0x9E7D, 0xFB7E, 0x9E80, 0xFB80, 0x9E81, + 0xFB81, 0x9E83, 0xFB82, 0x9E84, 0xFB83, 0x9E85, 0xFB84, 0x9E86, 0xFB85, 0x9E89, 0xFB86, 0x9E8A, 0xFB87, 0x9E8C, 0xFB88, 0x9E8D, + 0xFB89, 0x9E8E, 0xFB8A, 0x9E8F, 0xFB8B, 0x9E90, 0xFB8C, 0x9E91, 0xFB8D, 0x9E94, 0xFB8E, 0x9E95, 0xFB8F, 0x9E96, 0xFB90, 0x9E97, + 0xFB91, 0x9E98, 0xFB92, 0x9E99, 0xFB93, 0x9E9A, 0xFB94, 0x9E9B, 0xFB95, 0x9E9C, 0xFB96, 0x9E9E, 0xFB97, 0x9EA0, 0xFB98, 0x9EA1, + 0xFB99, 0x9EA2, 0xFB9A, 0x9EA3, 0xFB9B, 0x9EA4, 0xFB9C, 0x9EA5, 0xFB9D, 0x9EA7, 0xFB9E, 0x9EA8, 0xFB9F, 0x9EA9, 0xFBA0, 0x9EAA, + 0xFC40, 0x9EAB, 0xFC41, 0x9EAC, 0xFC42, 0x9EAD, 0xFC43, 0x9EAE, 0xFC44, 0x9EAF, 0xFC45, 0x9EB0, 0xFC46, 0x9EB1, 0xFC47, 0x9EB2, + 0xFC48, 0x9EB3, 0xFC49, 0x9EB5, 0xFC4A, 0x9EB6, 0xFC4B, 0x9EB7, 0xFC4C, 0x9EB9, 0xFC4D, 0x9EBA, 0xFC4E, 0x9EBC, 0xFC4F, 0x9EBF, + 0xFC50, 0x9EC0, 0xFC51, 0x9EC1, 0xFC52, 0x9EC2, 0xFC53, 0x9EC3, 0xFC54, 0x9EC5, 0xFC55, 0x9EC6, 0xFC56, 0x9EC7, 0xFC57, 0x9EC8, + 0xFC58, 0x9ECA, 0xFC59, 0x9ECB, 0xFC5A, 0x9ECC, 0xFC5B, 0x9ED0, 0xFC5C, 0x9ED2, 0xFC5D, 0x9ED3, 0xFC5E, 0x9ED5, 0xFC5F, 0x9ED6, + 0xFC60, 0x9ED7, 0xFC61, 0x9ED9, 0xFC62, 0x9EDA, 0xFC63, 0x9EDE, 0xFC64, 0x9EE1, 0xFC65, 0x9EE3, 0xFC66, 0x9EE4, 0xFC67, 0x9EE6, + 0xFC68, 0x9EE8, 0xFC69, 0x9EEB, 0xFC6A, 0x9EEC, 0xFC6B, 0x9EED, 0xFC6C, 0x9EEE, 0xFC6D, 0x9EF0, 0xFC6E, 0x9EF1, 0xFC6F, 0x9EF2, + 0xFC70, 0x9EF3, 0xFC71, 0x9EF4, 0xFC72, 0x9EF5, 0xFC73, 0x9EF6, 0xFC74, 0x9EF7, 0xFC75, 0x9EF8, 0xFC76, 0x9EFA, 0xFC77, 0x9EFD, + 0xFC78, 0x9EFF, 0xFC79, 0x9F00, 0xFC7A, 0x9F01, 0xFC7B, 0x9F02, 0xFC7C, 0x9F03, 0xFC7D, 0x9F04, 0xFC7E, 0x9F05, 0xFC80, 0x9F06, + 0xFC81, 0x9F07, 0xFC82, 0x9F08, 0xFC83, 0x9F09, 0xFC84, 0x9F0A, 0xFC85, 0x9F0C, 0xFC86, 0x9F0F, 0xFC87, 0x9F11, 0xFC88, 0x9F12, + 0xFC89, 0x9F14, 0xFC8A, 0x9F15, 0xFC8B, 0x9F16, 0xFC8C, 0x9F18, 0xFC8D, 0x9F1A, 0xFC8E, 0x9F1B, 0xFC8F, 0x9F1C, 0xFC90, 0x9F1D, + 0xFC91, 0x9F1E, 0xFC92, 0x9F1F, 0xFC93, 0x9F21, 0xFC94, 0x9F23, 0xFC95, 0x9F24, 0xFC96, 0x9F25, 0xFC97, 0x9F26, 0xFC98, 0x9F27, + 0xFC99, 0x9F28, 0xFC9A, 0x9F29, 0xFC9B, 0x9F2A, 0xFC9C, 0x9F2B, 0xFC9D, 0x9F2D, 0xFC9E, 0x9F2E, 0xFC9F, 0x9F30, 0xFCA0, 0x9F31, + 0xFD40, 0x9F32, 0xFD41, 0x9F33, 0xFD42, 0x9F34, 0xFD43, 0x9F35, 0xFD44, 0x9F36, 0xFD45, 0x9F38, 0xFD46, 0x9F3A, 0xFD47, 0x9F3C, + 0xFD48, 0x9F3F, 0xFD49, 0x9F40, 0xFD4A, 0x9F41, 0xFD4B, 0x9F42, 0xFD4C, 0x9F43, 0xFD4D, 0x9F45, 0xFD4E, 0x9F46, 0xFD4F, 0x9F47, + 0xFD50, 0x9F48, 0xFD51, 0x9F49, 0xFD52, 0x9F4A, 0xFD53, 0x9F4B, 0xFD54, 0x9F4C, 0xFD55, 0x9F4D, 0xFD56, 0x9F4E, 0xFD57, 0x9F4F, + 0xFD58, 0x9F52, 0xFD59, 0x9F53, 0xFD5A, 0x9F54, 0xFD5B, 0x9F55, 0xFD5C, 0x9F56, 0xFD5D, 0x9F57, 0xFD5E, 0x9F58, 0xFD5F, 0x9F59, + 0xFD60, 0x9F5A, 0xFD61, 0x9F5B, 0xFD62, 0x9F5C, 0xFD63, 0x9F5D, 0xFD64, 0x9F5E, 0xFD65, 0x9F5F, 0xFD66, 0x9F60, 0xFD67, 0x9F61, + 0xFD68, 0x9F62, 0xFD69, 0x9F63, 0xFD6A, 0x9F64, 0xFD6B, 0x9F65, 0xFD6C, 0x9F66, 0xFD6D, 0x9F67, 0xFD6E, 0x9F68, 0xFD6F, 0x9F69, + 0xFD70, 0x9F6A, 0xFD71, 0x9F6B, 0xFD72, 0x9F6C, 0xFD73, 0x9F6D, 0xFD74, 0x9F6E, 0xFD75, 0x9F6F, 0xFD76, 0x9F70, 0xFD77, 0x9F71, + 0xFD78, 0x9F72, 0xFD79, 0x9F73, 0xFD7A, 0x9F74, 0xFD7B, 0x9F75, 0xFD7C, 0x9F76, 0xFD7D, 0x9F77, 0xFD7E, 0x9F78, 0xFD80, 0x9F79, + 0xFD81, 0x9F7A, 0xFD82, 0x9F7B, 0xFD83, 0x9F7C, 0xFD84, 0x9F7D, 0xFD85, 0x9F7E, 0xFD86, 0x9F81, 0xFD87, 0x9F82, 0xFD88, 0x9F8D, + 0xFD89, 0x9F8E, 0xFD8A, 0x9F8F, 0xFD8B, 0x9F90, 0xFD8C, 0x9F91, 0xFD8D, 0x9F92, 0xFD8E, 0x9F93, 0xFD8F, 0x9F94, 0xFD90, 0x9F95, + 0xFD91, 0x9F96, 0xFD92, 0x9F97, 0xFD93, 0x9F98, 0xFD94, 0x9F9C, 0xFD95, 0x9F9D, 0xFD96, 0x9F9E, 0xFD97, 0x9FA1, 0xFD98, 0x9FA2, + 0xFD99, 0x9FA3, 0xFD9A, 0x9FA4, 0xFD9B, 0x9FA5, 0xFD9C, 0xF92C, 0xFD9D, 0xF979, 0xFD9E, 0xF995, 0xFD9F, 0xF9E7, 0xFDA0, 0xF9F1, + 0xFE40, 0xFA0C, 0xFE41, 0xFA0D, 0xFE42, 0xFA0E, 0xFE43, 0xFA0F, 0xFE44, 0xFA11, 0xFE45, 0xFA13, 0xFE46, 0xFA14, 0xFE47, 0xFA18, + 0xFE48, 0xFA1F, 0xFE49, 0xFA20, 0xFE4A, 0xFA21, 0xFE4B, 0xFA23, 0xFE4C, 0xFA24, 0xFE4D, 0xFA27, 0xFE4E, 0xFA28, 0xFE4F, 0xFA29, + 0, 0 +}; +#endif + +#if FF_CODE_PAGE == 949 || FF_CODE_PAGE == 0 /* Korean */ +static +const WCHAR uni2oem949[] = { /* Unicode --> Korean pairs */ + 0x00A1, 0xA2AE, 0x00A4, 0xA2B4, 0x00A7, 0xA1D7, 0x00A8, 0xA1A7, 0x00AA, 0xA8A3, 0x00AD, 0xA1A9, 0x00AE, 0xA2E7, 0x00B0, 0xA1C6, + 0x00B1, 0xA1BE, 0x00B2, 0xA9F7, 0x00B3, 0xA9F8, 0x00B4, 0xA2A5, 0x00B6, 0xA2D2, 0x00B7, 0xA1A4, 0x00B8, 0xA2AC, 0x00B9, 0xA9F6, + 0x00BA, 0xA8AC, 0x00BC, 0xA8F9, 0x00BD, 0xA8F6, 0x00BE, 0xA8FA, 0x00BF, 0xA2AF, 0x00C6, 0xA8A1, 0x00D0, 0xA8A2, 0x00D7, 0xA1BF, + 0x00D8, 0xA8AA, 0x00DE, 0xA8AD, 0x00DF, 0xA9AC, 0x00E6, 0xA9A1, 0x00F0, 0xA9A3, 0x00F7, 0xA1C0, 0x00F8, 0xA9AA, 0x00FE, 0xA9AD, + 0x0111, 0xA9A2, 0x0126, 0xA8A4, 0x0127, 0xA9A4, 0x0131, 0xA9A5, 0x0132, 0xA8A6, 0x0133, 0xA9A6, 0x0138, 0xA9A7, 0x013F, 0xA8A8, + 0x0140, 0xA9A8, 0x0141, 0xA8A9, 0x0142, 0xA9A9, 0x0149, 0xA9B0, 0x014A, 0xA8AF, 0x014B, 0xA9AF, 0x0152, 0xA8AB, 0x0153, 0xA9AB, + 0x0166, 0xA8AE, 0x0167, 0xA9AE, 0x02C7, 0xA2A7, 0x02D0, 0xA2B0, 0x02D8, 0xA2A8, 0x02D9, 0xA2AB, 0x02DA, 0xA2AA, 0x02DB, 0xA2AD, + 0x02DD, 0xA2A9, 0x0391, 0xA5C1, 0x0392, 0xA5C2, 0x0393, 0xA5C3, 0x0394, 0xA5C4, 0x0395, 0xA5C5, 0x0396, 0xA5C6, 0x0397, 0xA5C7, + 0x0398, 0xA5C8, 0x0399, 0xA5C9, 0x039A, 0xA5CA, 0x039B, 0xA5CB, 0x039C, 0xA5CC, 0x039D, 0xA5CD, 0x039E, 0xA5CE, 0x039F, 0xA5CF, + 0x03A0, 0xA5D0, 0x03A1, 0xA5D1, 0x03A3, 0xA5D2, 0x03A4, 0xA5D3, 0x03A5, 0xA5D4, 0x03A6, 0xA5D5, 0x03A7, 0xA5D6, 0x03A8, 0xA5D7, + 0x03A9, 0xA5D8, 0x03B1, 0xA5E1, 0x03B2, 0xA5E2, 0x03B3, 0xA5E3, 0x03B4, 0xA5E4, 0x03B5, 0xA5E5, 0x03B6, 0xA5E6, 0x03B7, 0xA5E7, + 0x03B8, 0xA5E8, 0x03B9, 0xA5E9, 0x03BA, 0xA5EA, 0x03BB, 0xA5EB, 0x03BC, 0xA5EC, 0x03BD, 0xA5ED, 0x03BE, 0xA5EE, 0x03BF, 0xA5EF, + 0x03C0, 0xA5F0, 0x03C1, 0xA5F1, 0x03C3, 0xA5F2, 0x03C4, 0xA5F3, 0x03C5, 0xA5F4, 0x03C6, 0xA5F5, 0x03C7, 0xA5F6, 0x03C8, 0xA5F7, + 0x03C9, 0xA5F8, 0x0401, 0xACA7, 0x0410, 0xACA1, 0x0411, 0xACA2, 0x0412, 0xACA3, 0x0413, 0xACA4, 0x0414, 0xACA5, 0x0415, 0xACA6, + 0x0416, 0xACA8, 0x0417, 0xACA9, 0x0418, 0xACAA, 0x0419, 0xACAB, 0x041A, 0xACAC, 0x041B, 0xACAD, 0x041C, 0xACAE, 0x041D, 0xACAF, + 0x041E, 0xACB0, 0x041F, 0xACB1, 0x0420, 0xACB2, 0x0421, 0xACB3, 0x0422, 0xACB4, 0x0423, 0xACB5, 0x0424, 0xACB6, 0x0425, 0xACB7, + 0x0426, 0xACB8, 0x0427, 0xACB9, 0x0428, 0xACBA, 0x0429, 0xACBB, 0x042A, 0xACBC, 0x042B, 0xACBD, 0x042C, 0xACBE, 0x042D, 0xACBF, + 0x042E, 0xACC0, 0x042F, 0xACC1, 0x0430, 0xACD1, 0x0431, 0xACD2, 0x0432, 0xACD3, 0x0433, 0xACD4, 0x0434, 0xACD5, 0x0435, 0xACD6, + 0x0436, 0xACD8, 0x0437, 0xACD9, 0x0438, 0xACDA, 0x0439, 0xACDB, 0x043A, 0xACDC, 0x043B, 0xACDD, 0x043C, 0xACDE, 0x043D, 0xACDF, + 0x043E, 0xACE0, 0x043F, 0xACE1, 0x0440, 0xACE2, 0x0441, 0xACE3, 0x0442, 0xACE4, 0x0443, 0xACE5, 0x0444, 0xACE6, 0x0445, 0xACE7, + 0x0446, 0xACE8, 0x0447, 0xACE9, 0x0448, 0xACEA, 0x0449, 0xACEB, 0x044A, 0xACEC, 0x044B, 0xACED, 0x044C, 0xACEE, 0x044D, 0xACEF, + 0x044E, 0xACF0, 0x044F, 0xACF1, 0x0451, 0xACD7, 0x2015, 0xA1AA, 0x2018, 0xA1AE, 0x2019, 0xA1AF, 0x201C, 0xA1B0, 0x201D, 0xA1B1, + 0x2020, 0xA2D3, 0x2021, 0xA2D4, 0x2025, 0xA1A5, 0x2026, 0xA1A6, 0x2030, 0xA2B6, 0x2032, 0xA1C7, 0x2033, 0xA1C8, 0x203B, 0xA1D8, + 0x2074, 0xA9F9, 0x207F, 0xA9FA, 0x2081, 0xA9FB, 0x2082, 0xA9FC, 0x2083, 0xA9FD, 0x2084, 0xA9FE, 0x20AC, 0xA2E6, 0x2103, 0xA1C9, + 0x2109, 0xA2B5, 0x2113, 0xA7A4, 0x2116, 0xA2E0, 0x2121, 0xA2E5, 0x2122, 0xA2E2, 0x2126, 0xA7D9, 0x212B, 0xA1CA, 0x2153, 0xA8F7, + 0x2154, 0xA8F8, 0x215B, 0xA8FB, 0x215C, 0xA8FC, 0x215D, 0xA8FD, 0x215E, 0xA8FE, 0x2160, 0xA5B0, 0x2161, 0xA5B1, 0x2162, 0xA5B2, + 0x2163, 0xA5B3, 0x2164, 0xA5B4, 0x2165, 0xA5B5, 0x2166, 0xA5B6, 0x2167, 0xA5B7, 0x2168, 0xA5B8, 0x2169, 0xA5B9, 0x2170, 0xA5A1, + 0x2171, 0xA5A2, 0x2172, 0xA5A3, 0x2173, 0xA5A4, 0x2174, 0xA5A5, 0x2175, 0xA5A6, 0x2176, 0xA5A7, 0x2177, 0xA5A8, 0x2178, 0xA5A9, + 0x2179, 0xA5AA, 0x2190, 0xA1E7, 0x2191, 0xA1E8, 0x2192, 0xA1E6, 0x2193, 0xA1E9, 0x2194, 0xA1EA, 0x2195, 0xA2D5, 0x2196, 0xA2D8, + 0x2197, 0xA2D6, 0x2198, 0xA2D9, 0x2199, 0xA2D7, 0x21D2, 0xA2A1, 0x21D4, 0xA2A2, 0x2200, 0xA2A3, 0x2202, 0xA1D3, 0x2203, 0xA2A4, + 0x2207, 0xA1D4, 0x2208, 0xA1F4, 0x220B, 0xA1F5, 0x220F, 0xA2B3, 0x2211, 0xA2B2, 0x221A, 0xA1EE, 0x221D, 0xA1F0, 0x221E, 0xA1C4, + 0x2220, 0xA1D0, 0x2225, 0xA1AB, 0x2227, 0xA1FC, 0x2228, 0xA1FD, 0x2229, 0xA1FB, 0x222A, 0xA1FA, 0x222B, 0xA1F2, 0x222C, 0xA1F3, + 0x222E, 0xA2B1, 0x2234, 0xA1C5, 0x2235, 0xA1F1, 0x223C, 0xA1AD, 0x223D, 0xA1EF, 0x2252, 0xA1D6, 0x2260, 0xA1C1, 0x2261, 0xA1D5, + 0x2264, 0xA1C2, 0x2265, 0xA1C3, 0x226A, 0xA1EC, 0x226B, 0xA1ED, 0x2282, 0xA1F8, 0x2283, 0xA1F9, 0x2286, 0xA1F6, 0x2287, 0xA1F7, + 0x2299, 0xA2C1, 0x22A5, 0xA1D1, 0x2312, 0xA1D2, 0x2460, 0xA8E7, 0x2461, 0xA8E8, 0x2462, 0xA8E9, 0x2463, 0xA8EA, 0x2464, 0xA8EB, + 0x2465, 0xA8EC, 0x2466, 0xA8ED, 0x2467, 0xA8EE, 0x2468, 0xA8EF, 0x2469, 0xA8F0, 0x246A, 0xA8F1, 0x246B, 0xA8F2, 0x246C, 0xA8F3, + 0x246D, 0xA8F4, 0x246E, 0xA8F5, 0x2474, 0xA9E7, 0x2475, 0xA9E8, 0x2476, 0xA9E9, 0x2477, 0xA9EA, 0x2478, 0xA9EB, 0x2479, 0xA9EC, + 0x247A, 0xA9ED, 0x247B, 0xA9EE, 0x247C, 0xA9EF, 0x247D, 0xA9F0, 0x247E, 0xA9F1, 0x247F, 0xA9F2, 0x2480, 0xA9F3, 0x2481, 0xA9F4, + 0x2482, 0xA9F5, 0x249C, 0xA9CD, 0x249D, 0xA9CE, 0x249E, 0xA9CF, 0x249F, 0xA9D0, 0x24A0, 0xA9D1, 0x24A1, 0xA9D2, 0x24A2, 0xA9D3, + 0x24A3, 0xA9D4, 0x24A4, 0xA9D5, 0x24A5, 0xA9D6, 0x24A6, 0xA9D7, 0x24A7, 0xA9D8, 0x24A8, 0xA9D9, 0x24A9, 0xA9DA, 0x24AA, 0xA9DB, + 0x24AB, 0xA9DC, 0x24AC, 0xA9DD, 0x24AD, 0xA9DE, 0x24AE, 0xA9DF, 0x24AF, 0xA9E0, 0x24B0, 0xA9E1, 0x24B1, 0xA9E2, 0x24B2, 0xA9E3, + 0x24B3, 0xA9E4, 0x24B4, 0xA9E5, 0x24B5, 0xA9E6, 0x24D0, 0xA8CD, 0x24D1, 0xA8CE, 0x24D2, 0xA8CF, 0x24D3, 0xA8D0, 0x24D4, 0xA8D1, + 0x24D5, 0xA8D2, 0x24D6, 0xA8D3, 0x24D7, 0xA8D4, 0x24D8, 0xA8D5, 0x24D9, 0xA8D6, 0x24DA, 0xA8D7, 0x24DB, 0xA8D8, 0x24DC, 0xA8D9, + 0x24DD, 0xA8DA, 0x24DE, 0xA8DB, 0x24DF, 0xA8DC, 0x24E0, 0xA8DD, 0x24E1, 0xA8DE, 0x24E2, 0xA8DF, 0x24E3, 0xA8E0, 0x24E4, 0xA8E1, + 0x24E5, 0xA8E2, 0x24E6, 0xA8E3, 0x24E7, 0xA8E4, 0x24E8, 0xA8E5, 0x24E9, 0xA8E6, 0x2500, 0xA6A1, 0x2501, 0xA6AC, 0x2502, 0xA6A2, + 0x2503, 0xA6AD, 0x250C, 0xA6A3, 0x250D, 0xA6C8, 0x250E, 0xA6C7, 0x250F, 0xA6AE, 0x2510, 0xA6A4, 0x2511, 0xA6C2, 0x2512, 0xA6C1, + 0x2513, 0xA6AF, 0x2514, 0xA6A6, 0x2515, 0xA6C6, 0x2516, 0xA6C5, 0x2517, 0xA6B1, 0x2518, 0xA6A5, 0x2519, 0xA6C4, 0x251A, 0xA6C3, + 0x251B, 0xA6B0, 0x251C, 0xA6A7, 0x251D, 0xA6BC, 0x251E, 0xA6C9, 0x251F, 0xA6CA, 0x2520, 0xA6B7, 0x2521, 0xA6CB, 0x2522, 0xA6CC, + 0x2523, 0xA6B2, 0x2524, 0xA6A9, 0x2525, 0xA6BE, 0x2526, 0xA6CD, 0x2527, 0xA6CE, 0x2528, 0xA6B9, 0x2529, 0xA6CF, 0x252A, 0xA6D0, + 0x252B, 0xA6B4, 0x252C, 0xA6A8, 0x252D, 0xA6D1, 0x252E, 0xA6D2, 0x252F, 0xA6B8, 0x2530, 0xA6BD, 0x2531, 0xA6D3, 0x2532, 0xA6D4, + 0x2533, 0xA6B3, 0x2534, 0xA6AA, 0x2535, 0xA6D5, 0x2536, 0xA6D6, 0x2537, 0xA6BA, 0x2538, 0xA6BF, 0x2539, 0xA6D7, 0x253A, 0xA6D8, + 0x253B, 0xA6B5, 0x253C, 0xA6AB, 0x253D, 0xA6D9, 0x253E, 0xA6DA, 0x253F, 0xA6BB, 0x2540, 0xA6DB, 0x2541, 0xA6DC, 0x2542, 0xA6C0, + 0x2543, 0xA6DD, 0x2544, 0xA6DE, 0x2545, 0xA6DF, 0x2546, 0xA6E0, 0x2547, 0xA6E1, 0x2548, 0xA6E2, 0x2549, 0xA6E3, 0x254A, 0xA6E4, + 0x254B, 0xA6B6, 0x2592, 0xA2C6, 0x25A0, 0xA1E1, 0x25A1, 0xA1E0, 0x25A3, 0xA2C3, 0x25A4, 0xA2C7, 0x25A5, 0xA2C8, 0x25A6, 0xA2CB, + 0x25A7, 0xA2CA, 0x25A8, 0xA2C9, 0x25A9, 0xA2CC, 0x25B2, 0xA1E3, 0x25B3, 0xA1E2, 0x25B6, 0xA2BA, 0x25B7, 0xA2B9, 0x25BC, 0xA1E5, + 0x25BD, 0xA1E4, 0x25C0, 0xA2B8, 0x25C1, 0xA2B7, 0x25C6, 0xA1DF, 0x25C7, 0xA1DE, 0x25C8, 0xA2C2, 0x25CB, 0xA1DB, 0x25CE, 0xA1DD, + 0x25CF, 0xA1DC, 0x25D0, 0xA2C4, 0x25D1, 0xA2C5, 0x2605, 0xA1DA, 0x2606, 0xA1D9, 0x260E, 0xA2CF, 0x260F, 0xA2CE, 0x261C, 0xA2D0, + 0x261E, 0xA2D1, 0x2640, 0xA1CF, 0x2642, 0xA1CE, 0x2660, 0xA2BC, 0x2661, 0xA2BD, 0x2663, 0xA2C0, 0x2664, 0xA2BB, 0x2665, 0xA2BE, + 0x2667, 0xA2BF, 0x2668, 0xA2CD, 0x2669, 0xA2DB, 0x266A, 0xA2DC, 0x266C, 0xA2DD, 0x266D, 0xA2DA, 0x3000, 0xA1A1, 0x3001, 0xA1A2, + 0x3002, 0xA1A3, 0x3003, 0xA1A8, 0x3008, 0xA1B4, 0x3009, 0xA1B5, 0x300A, 0xA1B6, 0x300B, 0xA1B7, 0x300C, 0xA1B8, 0x300D, 0xA1B9, + 0x300E, 0xA1BA, 0x300F, 0xA1BB, 0x3010, 0xA1BC, 0x3011, 0xA1BD, 0x3013, 0xA1EB, 0x3014, 0xA1B2, 0x3015, 0xA1B3, 0x3041, 0xAAA1, + 0x3042, 0xAAA2, 0x3043, 0xAAA3, 0x3044, 0xAAA4, 0x3045, 0xAAA5, 0x3046, 0xAAA6, 0x3047, 0xAAA7, 0x3048, 0xAAA8, 0x3049, 0xAAA9, + 0x304A, 0xAAAA, 0x304B, 0xAAAB, 0x304C, 0xAAAC, 0x304D, 0xAAAD, 0x304E, 0xAAAE, 0x304F, 0xAAAF, 0x3050, 0xAAB0, 0x3051, 0xAAB1, + 0x3052, 0xAAB2, 0x3053, 0xAAB3, 0x3054, 0xAAB4, 0x3055, 0xAAB5, 0x3056, 0xAAB6, 0x3057, 0xAAB7, 0x3058, 0xAAB8, 0x3059, 0xAAB9, + 0x305A, 0xAABA, 0x305B, 0xAABB, 0x305C, 0xAABC, 0x305D, 0xAABD, 0x305E, 0xAABE, 0x305F, 0xAABF, 0x3060, 0xAAC0, 0x3061, 0xAAC1, + 0x3062, 0xAAC2, 0x3063, 0xAAC3, 0x3064, 0xAAC4, 0x3065, 0xAAC5, 0x3066, 0xAAC6, 0x3067, 0xAAC7, 0x3068, 0xAAC8, 0x3069, 0xAAC9, + 0x306A, 0xAACA, 0x306B, 0xAACB, 0x306C, 0xAACC, 0x306D, 0xAACD, 0x306E, 0xAACE, 0x306F, 0xAACF, 0x3070, 0xAAD0, 0x3071, 0xAAD1, + 0x3072, 0xAAD2, 0x3073, 0xAAD3, 0x3074, 0xAAD4, 0x3075, 0xAAD5, 0x3076, 0xAAD6, 0x3077, 0xAAD7, 0x3078, 0xAAD8, 0x3079, 0xAAD9, + 0x307A, 0xAADA, 0x307B, 0xAADB, 0x307C, 0xAADC, 0x307D, 0xAADD, 0x307E, 0xAADE, 0x307F, 0xAADF, 0x3080, 0xAAE0, 0x3081, 0xAAE1, + 0x3082, 0xAAE2, 0x3083, 0xAAE3, 0x3084, 0xAAE4, 0x3085, 0xAAE5, 0x3086, 0xAAE6, 0x3087, 0xAAE7, 0x3088, 0xAAE8, 0x3089, 0xAAE9, + 0x308A, 0xAAEA, 0x308B, 0xAAEB, 0x308C, 0xAAEC, 0x308D, 0xAAED, 0x308E, 0xAAEE, 0x308F, 0xAAEF, 0x3090, 0xAAF0, 0x3091, 0xAAF1, + 0x3092, 0xAAF2, 0x3093, 0xAAF3, 0x30A1, 0xABA1, 0x30A2, 0xABA2, 0x30A3, 0xABA3, 0x30A4, 0xABA4, 0x30A5, 0xABA5, 0x30A6, 0xABA6, + 0x30A7, 0xABA7, 0x30A8, 0xABA8, 0x30A9, 0xABA9, 0x30AA, 0xABAA, 0x30AB, 0xABAB, 0x30AC, 0xABAC, 0x30AD, 0xABAD, 0x30AE, 0xABAE, + 0x30AF, 0xABAF, 0x30B0, 0xABB0, 0x30B1, 0xABB1, 0x30B2, 0xABB2, 0x30B3, 0xABB3, 0x30B4, 0xABB4, 0x30B5, 0xABB5, 0x30B6, 0xABB6, + 0x30B7, 0xABB7, 0x30B8, 0xABB8, 0x30B9, 0xABB9, 0x30BA, 0xABBA, 0x30BB, 0xABBB, 0x30BC, 0xABBC, 0x30BD, 0xABBD, 0x30BE, 0xABBE, + 0x30BF, 0xABBF, 0x30C0, 0xABC0, 0x30C1, 0xABC1, 0x30C2, 0xABC2, 0x30C3, 0xABC3, 0x30C4, 0xABC4, 0x30C5, 0xABC5, 0x30C6, 0xABC6, + 0x30C7, 0xABC7, 0x30C8, 0xABC8, 0x30C9, 0xABC9, 0x30CA, 0xABCA, 0x30CB, 0xABCB, 0x30CC, 0xABCC, 0x30CD, 0xABCD, 0x30CE, 0xABCE, + 0x30CF, 0xABCF, 0x30D0, 0xABD0, 0x30D1, 0xABD1, 0x30D2, 0xABD2, 0x30D3, 0xABD3, 0x30D4, 0xABD4, 0x30D5, 0xABD5, 0x30D6, 0xABD6, + 0x30D7, 0xABD7, 0x30D8, 0xABD8, 0x30D9, 0xABD9, 0x30DA, 0xABDA, 0x30DB, 0xABDB, 0x30DC, 0xABDC, 0x30DD, 0xABDD, 0x30DE, 0xABDE, + 0x30DF, 0xABDF, 0x30E0, 0xABE0, 0x30E1, 0xABE1, 0x30E2, 0xABE2, 0x30E3, 0xABE3, 0x30E4, 0xABE4, 0x30E5, 0xABE5, 0x30E6, 0xABE6, + 0x30E7, 0xABE7, 0x30E8, 0xABE8, 0x30E9, 0xABE9, 0x30EA, 0xABEA, 0x30EB, 0xABEB, 0x30EC, 0xABEC, 0x30ED, 0xABED, 0x30EE, 0xABEE, + 0x30EF, 0xABEF, 0x30F0, 0xABF0, 0x30F1, 0xABF1, 0x30F2, 0xABF2, 0x30F3, 0xABF3, 0x30F4, 0xABF4, 0x30F5, 0xABF5, 0x30F6, 0xABF6, + 0x3131, 0xA4A1, 0x3132, 0xA4A2, 0x3133, 0xA4A3, 0x3134, 0xA4A4, 0x3135, 0xA4A5, 0x3136, 0xA4A6, 0x3137, 0xA4A7, 0x3138, 0xA4A8, + 0x3139, 0xA4A9, 0x313A, 0xA4AA, 0x313B, 0xA4AB, 0x313C, 0xA4AC, 0x313D, 0xA4AD, 0x313E, 0xA4AE, 0x313F, 0xA4AF, 0x3140, 0xA4B0, + 0x3141, 0xA4B1, 0x3142, 0xA4B2, 0x3143, 0xA4B3, 0x3144, 0xA4B4, 0x3145, 0xA4B5, 0x3146, 0xA4B6, 0x3147, 0xA4B7, 0x3148, 0xA4B8, + 0x3149, 0xA4B9, 0x314A, 0xA4BA, 0x314B, 0xA4BB, 0x314C, 0xA4BC, 0x314D, 0xA4BD, 0x314E, 0xA4BE, 0x314F, 0xA4BF, 0x3150, 0xA4C0, + 0x3151, 0xA4C1, 0x3152, 0xA4C2, 0x3153, 0xA4C3, 0x3154, 0xA4C4, 0x3155, 0xA4C5, 0x3156, 0xA4C6, 0x3157, 0xA4C7, 0x3158, 0xA4C8, + 0x3159, 0xA4C9, 0x315A, 0xA4CA, 0x315B, 0xA4CB, 0x315C, 0xA4CC, 0x315D, 0xA4CD, 0x315E, 0xA4CE, 0x315F, 0xA4CF, 0x3160, 0xA4D0, + 0x3161, 0xA4D1, 0x3162, 0xA4D2, 0x3163, 0xA4D3, 0x3164, 0xA4D4, 0x3165, 0xA4D5, 0x3166, 0xA4D6, 0x3167, 0xA4D7, 0x3168, 0xA4D8, + 0x3169, 0xA4D9, 0x316A, 0xA4DA, 0x316B, 0xA4DB, 0x316C, 0xA4DC, 0x316D, 0xA4DD, 0x316E, 0xA4DE, 0x316F, 0xA4DF, 0x3170, 0xA4E0, + 0x3171, 0xA4E1, 0x3172, 0xA4E2, 0x3173, 0xA4E3, 0x3174, 0xA4E4, 0x3175, 0xA4E5, 0x3176, 0xA4E6, 0x3177, 0xA4E7, 0x3178, 0xA4E8, + 0x3179, 0xA4E9, 0x317A, 0xA4EA, 0x317B, 0xA4EB, 0x317C, 0xA4EC, 0x317D, 0xA4ED, 0x317E, 0xA4EE, 0x317F, 0xA4EF, 0x3180, 0xA4F0, + 0x3181, 0xA4F1, 0x3182, 0xA4F2, 0x3183, 0xA4F3, 0x3184, 0xA4F4, 0x3185, 0xA4F5, 0x3186, 0xA4F6, 0x3187, 0xA4F7, 0x3188, 0xA4F8, + 0x3189, 0xA4F9, 0x318A, 0xA4FA, 0x318B, 0xA4FB, 0x318C, 0xA4FC, 0x318D, 0xA4FD, 0x318E, 0xA4FE, 0x3200, 0xA9B1, 0x3201, 0xA9B2, + 0x3202, 0xA9B3, 0x3203, 0xA9B4, 0x3204, 0xA9B5, 0x3205, 0xA9B6, 0x3206, 0xA9B7, 0x3207, 0xA9B8, 0x3208, 0xA9B9, 0x3209, 0xA9BA, + 0x320A, 0xA9BB, 0x320B, 0xA9BC, 0x320C, 0xA9BD, 0x320D, 0xA9BE, 0x320E, 0xA9BF, 0x320F, 0xA9C0, 0x3210, 0xA9C1, 0x3211, 0xA9C2, + 0x3212, 0xA9C3, 0x3213, 0xA9C4, 0x3214, 0xA9C5, 0x3215, 0xA9C6, 0x3216, 0xA9C7, 0x3217, 0xA9C8, 0x3218, 0xA9C9, 0x3219, 0xA9CA, + 0x321A, 0xA9CB, 0x321B, 0xA9CC, 0x321C, 0xA2DF, 0x3260, 0xA8B1, 0x3261, 0xA8B2, 0x3262, 0xA8B3, 0x3263, 0xA8B4, 0x3264, 0xA8B5, + 0x3265, 0xA8B6, 0x3266, 0xA8B7, 0x3267, 0xA8B8, 0x3268, 0xA8B9, 0x3269, 0xA8BA, 0x326A, 0xA8BB, 0x326B, 0xA8BC, 0x326C, 0xA8BD, + 0x326D, 0xA8BE, 0x326E, 0xA8BF, 0x326F, 0xA8C0, 0x3270, 0xA8C1, 0x3271, 0xA8C2, 0x3272, 0xA8C3, 0x3273, 0xA8C4, 0x3274, 0xA8C5, + 0x3275, 0xA8C6, 0x3276, 0xA8C7, 0x3277, 0xA8C8, 0x3278, 0xA8C9, 0x3279, 0xA8CA, 0x327A, 0xA8CB, 0x327B, 0xA8CC, 0x327F, 0xA2DE, + 0x3380, 0xA7C9, 0x3381, 0xA7CA, 0x3382, 0xA7CB, 0x3383, 0xA7CC, 0x3384, 0xA7CD, 0x3388, 0xA7BA, 0x3389, 0xA7BB, 0x338A, 0xA7DC, + 0x338B, 0xA7DD, 0x338C, 0xA7DE, 0x338D, 0xA7B6, 0x338E, 0xA7B7, 0x338F, 0xA7B8, 0x3390, 0xA7D4, 0x3391, 0xA7D5, 0x3392, 0xA7D6, + 0x3393, 0xA7D7, 0x3394, 0xA7D8, 0x3395, 0xA7A1, 0x3396, 0xA7A2, 0x3397, 0xA7A3, 0x3398, 0xA7A5, 0x3399, 0xA7AB, 0x339A, 0xA7AC, + 0x339B, 0xA7AD, 0x339C, 0xA7AE, 0x339D, 0xA7AF, 0x339E, 0xA7B0, 0x339F, 0xA7B1, 0x33A0, 0xA7B2, 0x33A1, 0xA7B3, 0x33A2, 0xA7B4, + 0x33A3, 0xA7A7, 0x33A4, 0xA7A8, 0x33A5, 0xA7A9, 0x33A6, 0xA7AA, 0x33A7, 0xA7BD, 0x33A8, 0xA7BE, 0x33A9, 0xA7E5, 0x33AA, 0xA7E6, + 0x33AB, 0xA7E7, 0x33AC, 0xA7E8, 0x33AD, 0xA7E1, 0x33AE, 0xA7E2, 0x33AF, 0xA7E3, 0x33B0, 0xA7BF, 0x33B1, 0xA7C0, 0x33B2, 0xA7C1, + 0x33B3, 0xA7C2, 0x33B4, 0xA7C3, 0x33B5, 0xA7C4, 0x33B6, 0xA7C5, 0x33B7, 0xA7C6, 0x33B8, 0xA7C7, 0x33B9, 0xA7C8, 0x33BA, 0xA7CE, + 0x33BB, 0xA7CF, 0x33BC, 0xA7D0, 0x33BD, 0xA7D1, 0x33BE, 0xA7D2, 0x33BF, 0xA7D3, 0x33C0, 0xA7DA, 0x33C1, 0xA7DB, 0x33C2, 0xA2E3, + 0x33C3, 0xA7EC, 0x33C4, 0xA7A6, 0x33C5, 0xA7E0, 0x33C6, 0xA7EF, 0x33C7, 0xA2E1, 0x33C8, 0xA7BC, 0x33C9, 0xA7ED, 0x33CA, 0xA7B5, + 0x33CF, 0xA7B9, 0x33D0, 0xA7EA, 0x33D3, 0xA7EB, 0x33D6, 0xA7DF, 0x33D8, 0xA2E4, 0x33DB, 0xA7E4, 0x33DC, 0xA7EE, 0x33DD, 0xA7E9, + 0x4E00, 0xECE9, 0x4E01, 0xEFCB, 0x4E03, 0xF6D2, 0x4E07, 0xD8B2, 0x4E08, 0xEDDB, 0x4E09, 0xDFB2, 0x4E0A, 0xDFBE, 0x4E0B, 0xF9BB, + 0x4E0D, 0xDCF4, 0x4E11, 0xF5E4, 0x4E14, 0xF3A6, 0x4E15, 0xDDE0, 0x4E16, 0xE1A6, 0x4E18, 0xCEF8, 0x4E19, 0xDCB0, 0x4E1E, 0xE3AA, + 0x4E2D, 0xF1E9, 0x4E32, 0xCDFA, 0x4E38, 0xFCAF, 0x4E39, 0xD3A1, 0x4E3B, 0xF1AB, 0x4E42, 0xE7D1, 0x4E43, 0xD2AC, 0x4E45, 0xCEF9, + 0x4E4B, 0xF1FD, 0x4E4D, 0xDEBF, 0x4E4E, 0xFBBA, 0x4E4F, 0xF9B9, 0x4E56, 0xCED2, 0x4E58, 0xE3AB, 0x4E59, 0xEBE0, 0x4E5D, 0xCEFA, + 0x4E5E, 0xCBF7, 0x4E5F, 0xE5A5, 0x4E6B, 0xCAE1, 0x4E6D, 0xD4CC, 0x4E73, 0xEAE1, 0x4E76, 0xDCE3, 0x4E77, 0xDFAD, 0x4E7E, 0xCBEB, + 0x4E82, 0xD5AF, 0x4E86, 0xD6F5, 0x4E88, 0xE5F8, 0x4E8B, 0xDEC0, 0x4E8C, 0xECA3, 0x4E8E, 0xE9CD, 0x4E90, 0xEAA7, 0x4E91, 0xE9F6, + 0x4E92, 0xFBBB, 0x4E94, 0xE7E9, 0x4E95, 0xEFCC, 0x4E98, 0xD0E6, 0x4E9B, 0xDEC1, 0x4E9E, 0xE4AC, 0x4EA1, 0xD8CC, 0x4EA2, 0xF9F1, + 0x4EA4, 0xCEDF, 0x4EA5, 0xFAA4, 0x4EA6, 0xE6B2, 0x4EA8, 0xFAFB, 0x4EAB, 0xFABD, 0x4EAC, 0xCCC8, 0x4EAD, 0xEFCD, 0x4EAE, 0xD5D5, + 0x4EB6, 0xD3A2, 0x4EBA, 0xECD1, 0x4EC0, 0xE4A7, 0x4EC1, 0xECD2, 0x4EC4, 0xF6B1, 0x4EC7, 0xCEFB, 0x4ECA, 0xD0D1, 0x4ECB, 0xCBBF, + 0x4ECD, 0xEDA4, 0x4ED4, 0xEDA8, 0x4ED5, 0xDEC2, 0x4ED6, 0xF6E2, 0x4ED7, 0xEDDC, 0x4ED8, 0xDCF5, 0x4ED9, 0xE0B9, 0x4EDD, 0xD4CE, + 0x4EDF, 0xF4B5, 0x4EE3, 0xD3DB, 0x4EE4, 0xD6B5, 0x4EE5, 0xECA4, 0x4EF0, 0xE4E6, 0x4EF2, 0xF1EA, 0x4EF6, 0xCBEC, 0x4EF7, 0xCBC0, + 0x4EFB, 0xECF2, 0x4F01, 0xD0EA, 0x4F09, 0xF9F2, 0x4F0A, 0xECA5, 0x4F0B, 0xD0DF, 0x4F0D, 0xE7EA, 0x4F0E, 0xD0EB, 0x4F0F, 0xDCD1, + 0x4F10, 0xDBE9, 0x4F11, 0xFDCC, 0x4F2F, 0xDBD7, 0x4F34, 0xDAE1, 0x4F36, 0xD6B6, 0x4F38, 0xE3DF, 0x4F3A, 0xDEC3, 0x4F3C, 0xDEC4, + 0x4F3D, 0xCAA1, 0x4F43, 0xEEEC, 0x4F46, 0xD3A3, 0x4F47, 0xEEB7, 0x4F48, 0xF8CF, 0x4F4D, 0xEAC8, 0x4F4E, 0xEEB8, 0x4F4F, 0xF1AC, + 0x4F50, 0xF1A5, 0x4F51, 0xE9CE, 0x4F55, 0xF9BC, 0x4F59, 0xE5F9, 0x4F5A, 0xECEA, 0x4F5B, 0xDDD6, 0x4F5C, 0xEDC2, 0x4F69, 0xF8A5, + 0x4F6F, 0xE5BA, 0x4F70, 0xDBD8, 0x4F73, 0xCAA2, 0x4F76, 0xD1CD, 0x4F7A, 0xEEED, 0x4F7E, 0xECEB, 0x4F7F, 0xDEC5, 0x4F81, 0xE3E0, + 0x4F83, 0xCAC9, 0x4F84, 0xF2E9, 0x4F86, 0xD5CE, 0x4F88, 0xF6B6, 0x4F8A, 0xCEC2, 0x4F8B, 0xD6C7, 0x4F8D, 0xE3B4, 0x4F8F, 0xF1AD, + 0x4F91, 0xEAE2, 0x4F96, 0xD7C2, 0x4F98, 0xF3A7, 0x4F9B, 0xCDEA, 0x4F9D, 0xEBEE, 0x4FAE, 0xD9B2, 0x4FAF, 0xFDA5, 0x4FB5, 0xF6D5, + 0x4FB6, 0xD5E2, 0x4FBF, 0xF8B5, 0x4FC2, 0xCCF5, 0x4FC3, 0xF5B5, 0x4FC4, 0xE4AD, 0x4FC9, 0xE7EB, 0x4FCA, 0xF1D5, 0x4FCE, 0xF0BB, + 0x4FD1, 0xE9B5, 0x4FD3, 0xCCC9, 0x4FD4, 0xFAD5, 0x4FD7, 0xE1D4, 0x4FDA, 0xD7D6, 0x4FDD, 0xDCC1, 0x4FDF, 0xDEC6, 0x4FE0, 0xFAEF, + 0x4FE1, 0xE3E1, 0x4FEE, 0xE1F3, 0x4FEF, 0xDCF6, 0x4FF1, 0xCEFC, 0x4FF3, 0xDBC4, 0x4FF5, 0xF8F1, 0x4FF8, 0xDCE4, 0x4FFA, 0xE5EF, + 0x5002, 0xDCB1, 0x5006, 0xD5D6, 0x5009, 0xF3DA, 0x500B, 0xCBC1, 0x500D, 0xDBC3, 0x5011, 0xD9FA, 0x5012, 0xD3EE, 0x5016, 0xFAB8, + 0x5019, 0xFDA6, 0x501A, 0xEBEF, 0x501C, 0xF4A6, 0x501E, 0xCCCA, 0x501F, 0xF3A8, 0x5021, 0xF3DB, 0x5023, 0xDBA7, 0x5024, 0xF6B7, + 0x5026, 0xCFE6, 0x5027, 0xF0F2, 0x5028, 0xCBDA, 0x502A, 0xE7D2, 0x502B, 0xD7C3, 0x502C, 0xF6F0, 0x502D, 0xE8DE, 0x503B, 0xE5A6, + 0x5043, 0xE5E7, 0x5047, 0xCAA3, 0x5048, 0xCCA7, 0x5049, 0xEAC9, 0x504F, 0xF8B6, 0x5055, 0xFAA5, 0x505A, 0xF1AE, 0x505C, 0xEFCE, + 0x5065, 0xCBED, 0x5074, 0xF6B0, 0x5075, 0xEFCF, 0x5076, 0xE9CF, 0x5078, 0xF7DE, 0x5080, 0xCED3, 0x5085, 0xDCF7, 0x508D, 0xDBA8, + 0x5091, 0xCBF8, 0x5098, 0xDFA1, 0x5099, 0xDDE1, 0x50AC, 0xF5CA, 0x50AD, 0xE9B6, 0x50B2, 0xE7EC, 0x50B3, 0xEEEE, 0x50B5, 0xF3F0, + 0x50B7, 0xDFBF, 0x50BE, 0xCCCB, 0x50C5, 0xD0C1, 0x50C9, 0xF4D2, 0x50CA, 0xE0BA, 0x50CF, 0xDFC0, 0x50D1, 0xCEE0, 0x50D5, 0xDCD2, + 0x50D6, 0xFDEA, 0x50DA, 0xD6F6, 0x50DE, 0xEACA, 0x50E5, 0xE8E9, 0x50E7, 0xE3AC, 0x50ED, 0xF3D0, 0x50F9, 0xCAA4, 0x50FB, 0xDBF8, + 0x50FF, 0xDEC7, 0x5100, 0xEBF0, 0x5101, 0xF1D6, 0x5104, 0xE5E2, 0x5106, 0xCCCC, 0x5109, 0xCBFB, 0x5112, 0xEAE3, 0x511F, 0xDFC1, + 0x5121, 0xD6ED, 0x512A, 0xE9D0, 0x5132, 0xEEB9, 0x5137, 0xD5E3, 0x513A, 0xD1D3, 0x513C, 0xE5F0, 0x5140, 0xE8B4, 0x5141, 0xEBC3, + 0x5143, 0xEAAA, 0x5144, 0xFAFC, 0x5145, 0xF5F6, 0x5146, 0xF0BC, 0x5147, 0xFDD4, 0x5148, 0xE0BB, 0x5149, 0xCEC3, 0x514B, 0xD0BA, + 0x514C, 0xF7BA, 0x514D, 0xD8F3, 0x514E, 0xF7CD, 0x5152, 0xE4AE, 0x515C, 0xD4DF, 0x5162, 0xD0E7, 0x5165, 0xECFD, 0x5167, 0xD2AE, + 0x5168, 0xEEEF, 0x5169, 0xD5D7, 0x516A, 0xEAE4, 0x516B, 0xF8A2, 0x516C, 0xCDEB, 0x516D, 0xD7BF, 0x516E, 0xFBB1, 0x5171, 0xCDEC, + 0x5175, 0xDCB2, 0x5176, 0xD0EC, 0x5177, 0xCEFD, 0x5178, 0xEEF0, 0x517C, 0xCCC2, 0x5180, 0xD0ED, 0x5186, 0xE5F7, 0x518A, 0xF3FC, + 0x518D, 0xEEA2, 0x5192, 0xD9B3, 0x5195, 0xD8F4, 0x5197, 0xE9B7, 0x51A0, 0xCEAE, 0x51A5, 0xD9A2, 0x51AA, 0xD8F1, 0x51AC, 0xD4CF, + 0x51B6, 0xE5A7, 0x51B7, 0xD5D2, 0x51BD, 0xD6A9, 0x51C4, 0xF4A2, 0x51C6, 0xF1D7, 0x51C9, 0xD5D8, 0x51CB, 0xF0BD, 0x51CC, 0xD7D0, + 0x51CD, 0xD4D0, 0x51DC, 0xD7CF, 0x51DD, 0xEBEA, 0x51DE, 0xFDEB, 0x51E1, 0xDBED, 0x51F0, 0xFCC5, 0x51F1, 0xCBC2, 0x51F6, 0xFDD5, + 0x51F8, 0xF4C8, 0x51F9, 0xE8EA, 0x51FA, 0xF5F3, 0x51FD, 0xF9DE, 0x5200, 0xD3EF, 0x5203, 0xECD3, 0x5206, 0xDDC2, 0x5207, 0xEFB7, + 0x5208, 0xE7D4, 0x520A, 0xCACA, 0x520E, 0xD9FB, 0x5211, 0xFAFD, 0x5217, 0xD6AA, 0x521D, 0xF4F8, 0x5224, 0xF7F7, 0x5225, 0xDCAC, + 0x5229, 0xD7D7, 0x522A, 0xDFA2, 0x522E, 0xCEBE, 0x5230, 0xD3F0, 0x5236, 0xF0A4, 0x5237, 0xE1EC, 0x5238, 0xCFE7, 0x5239, 0xF3CB, + 0x523A, 0xEDA9, 0x523B, 0xCABE, 0x5243, 0xF4EF, 0x5247, 0xF6CE, 0x524A, 0xDEFB, 0x524B, 0xD0BB, 0x524C, 0xD5B7, 0x524D, 0xEEF1, + 0x5254, 0xF4A8, 0x5256, 0xDCF8, 0x525B, 0xCBA7, 0x525D, 0xDACE, 0x5261, 0xE0E6, 0x5269, 0xEDA5, 0x526A, 0xEEF2, 0x526F, 0xDCF9, + 0x5272, 0xF9DC, 0x5275, 0xF3DC, 0x527D, 0xF8F2, 0x527F, 0xF4F9, 0x5283, 0xFCF1, 0x5287, 0xD0BC, 0x5288, 0xDBF9, 0x5289, 0xD7B1, + 0x528D, 0xCBFC, 0x5291, 0xF0A5, 0x5292, 0xCBFD, 0x529B, 0xD5F4, 0x529F, 0xCDED, 0x52A0, 0xCAA5, 0x52A3, 0xD6AB, 0x52A4, 0xD0C2, + 0x52A9, 0xF0BE, 0x52AA, 0xD2BD, 0x52AB, 0xCCA4, 0x52BE, 0xFAB6, 0x52C1, 0xCCCD, 0x52C3, 0xDAFA, 0x52C5, 0xF6CF, 0x52C7, 0xE9B8, + 0x52C9, 0xD8F5, 0x52CD, 0xCCCE, 0x52D2, 0xD7CD, 0x52D5, 0xD4D1, 0x52D6, 0xE9ED, 0x52D8, 0xCAEB, 0x52D9, 0xD9E2, 0x52DB, 0xFDB2, + 0x52DD, 0xE3AD, 0x52DE, 0xD6CC, 0x52DF, 0xD9B4, 0x52E2, 0xE1A7, 0x52E3, 0xEED3, 0x52E4, 0xD0C3, 0x52F3, 0xFDB3, 0x52F5, 0xD5E4, + 0x52F8, 0xCFE8, 0x52FA, 0xEDC3, 0x52FB, 0xD0B2, 0x52FE, 0xCEFE, 0x52FF, 0xDAA8, 0x5305, 0xF8D0, 0x5308, 0xFDD6, 0x530D, 0xF8D1, + 0x530F, 0xF8D2, 0x5310, 0xDCD3, 0x5315, 0xDDE2, 0x5316, 0xFBF9, 0x5317, 0xDDC1, 0x5319, 0xE3B5, 0x5320, 0xEDDD, 0x5321, 0xCEC4, + 0x5323, 0xCBA1, 0x532A, 0xDDE3, 0x532F, 0xFCDD, 0x5339, 0xF9AF, 0x533F, 0xD2FB, 0x5340, 0xCFA1, 0x5341, 0xE4A8, 0x5343, 0xF4B6, + 0x5344, 0xECFE, 0x5347, 0xE3AE, 0x5348, 0xE7ED, 0x5349, 0xFDC1, 0x534A, 0xDAE2, 0x534D, 0xD8B3, 0x5351, 0xDDE4, 0x5352, 0xF0EF, + 0x5353, 0xF6F1, 0x5354, 0xFAF0, 0x5357, 0xD1F5, 0x535A, 0xDACF, 0x535C, 0xDCD4, 0x535E, 0xDCA6, 0x5360, 0xEFBF, 0x5366, 0xCECF, + 0x5368, 0xE0D9, 0x536F, 0xD9D6, 0x5370, 0xECD4, 0x5371, 0xEACB, 0x5374, 0xCABF, 0x5375, 0xD5B0, 0x5377, 0xCFE9, 0x537D, 0xF1ED, + 0x537F, 0xCCCF, 0x5384, 0xE4F8, 0x5393, 0xE4ED, 0x5398, 0xD7D8, 0x539A, 0xFDA7, 0x539F, 0xEAAB, 0x53A0, 0xF6B2, 0x53A5, 0xCFF0, + 0x53A6, 0xF9BD, 0x53AD, 0xE6F4, 0x53BB, 0xCBDB, 0x53C3, 0xF3D1, 0x53C8, 0xE9D1, 0x53C9, 0xF3A9, 0x53CA, 0xD0E0, 0x53CB, 0xE9D2, + 0x53CD, 0xDAE3, 0x53D4, 0xE2D2, 0x53D6, 0xF6A2, 0x53D7, 0xE1F4, 0x53DB, 0xDAE4, 0x53E1, 0xE7D5, 0x53E2, 0xF5BF, 0x53E3, 0xCFA2, + 0x53E4, 0xCDAF, 0x53E5, 0xCFA3, 0x53E9, 0xCDB0, 0x53EA, 0xF1FE, 0x53EB, 0xD0A3, 0x53EC, 0xE1AF, 0x53ED, 0xF8A3, 0x53EF, 0xCAA6, + 0x53F0, 0xF7BB, 0x53F1, 0xF2EA, 0x53F2, 0xDEC8, 0x53F3, 0xE9D3, 0x53F8, 0xDEC9, 0x5403, 0xFDDE, 0x5404, 0xCAC0, 0x5408, 0xF9EA, + 0x5409, 0xD1CE, 0x540A, 0xEED4, 0x540C, 0xD4D2, 0x540D, 0xD9A3, 0x540E, 0xFDA8, 0x540F, 0xD7D9, 0x5410, 0xF7CE, 0x5411, 0xFABE, + 0x541B, 0xCFD6, 0x541D, 0xD7F0, 0x541F, 0xEBE1, 0x5420, 0xF8C5, 0x5426, 0xDCFA, 0x5429, 0xDDC3, 0x542B, 0xF9DF, 0x5433, 0xE7EF, + 0x5438, 0xFDE5, 0x5439, 0xF6A3, 0x543B, 0xD9FC, 0x543C, 0xFDA9, 0x543E, 0xE7EE, 0x5442, 0xD5E5, 0x5448, 0xEFD0, 0x544A, 0xCDB1, + 0x5451, 0xF7A2, 0x5468, 0xF1B2, 0x546A, 0xF1B1, 0x5471, 0xCDB2, 0x5473, 0xDAAB, 0x5475, 0xCAA7, 0x547B, 0xE3E2, 0x547C, 0xFBBC, + 0x547D, 0xD9A4, 0x5480, 0xEEBA, 0x5486, 0xF8D3, 0x548C, 0xFBFA, 0x548E, 0xCFA4, 0x5490, 0xDCFB, 0x54A4, 0xF6E3, 0x54A8, 0xEDAA, + 0x54AB, 0xF2A1, 0x54AC, 0xCEE1, 0x54B3, 0xFAA6, 0x54B8, 0xF9E0, 0x54BD, 0xECD6, 0x54C0, 0xE4EE, 0x54C1, 0xF9A1, 0x54C4, 0xFBEF, + 0x54C8, 0xF9EB, 0x54C9, 0xEEA3, 0x54E1, 0xEAAC, 0x54E5, 0xCAA8, 0x54E8, 0xF4FA, 0x54ED, 0xCDD6, 0x54EE, 0xFCF6, 0x54F2, 0xF4C9, + 0x54FA, 0xF8D4, 0x5504, 0xF8A6, 0x5506, 0xDECA, 0x5507, 0xF2C6, 0x550E, 0xD7DA, 0x5510, 0xD3D0, 0x551C, 0xD8C5, 0x552F, 0xEAE6, + 0x5531, 0xF3DD, 0x5535, 0xE4DA, 0x553E, 0xF6E4, 0x5544, 0xF6F2, 0x5546, 0xDFC2, 0x554F, 0xD9FD, 0x5553, 0xCCF6, 0x5556, 0xD3BA, + 0x555E, 0xE4AF, 0x5563, 0xF9E1, 0x557C, 0xF0A6, 0x5580, 0xCBD3, 0x5584, 0xE0BC, 0x5586, 0xF4CA, 0x5587, 0xD4FA, 0x5589, 0xFDAA, + 0x558A, 0xF9E2, 0x5598, 0xF4B7, 0x5599, 0xFDC2, 0x559A, 0xFCB0, 0x559C, 0xFDEC, 0x559D, 0xCAE2, 0x55A7, 0xFDBD, 0x55A9, 0xEAE7, + 0x55AA, 0xDFC3, 0x55AB, 0xD1D2, 0x55AC, 0xCEE2, 0x55AE, 0xD3A4, 0x55C5, 0xFDAB, 0x55C7, 0xDFE0, 0x55D4, 0xF2C7, 0x55DA, 0xE7F0, + 0x55DC, 0xD0EE, 0x55DF, 0xF3AA, 0x55E3, 0xDECB, 0x55E4, 0xF6B8, 0x55FD, 0xE1F5, 0x55FE, 0xF1B3, 0x5606, 0xF7A3, 0x5609, 0xCAA9, + 0x5614, 0xCFA5, 0x5617, 0xDFC4, 0x562F, 0xE1B0, 0x5632, 0xF0BF, 0x5634, 0xF6A4, 0x5636, 0xE3B6, 0x5653, 0xFAC6, 0x5668, 0xD0EF, + 0x566B, 0xFDED, 0x5674, 0xDDC4, 0x5686, 0xFCF7, 0x56A5, 0xE6BF, 0x56AC, 0xDEAD, 0x56AE, 0xFABF, 0x56B4, 0xE5F1, 0x56BC, 0xEDC4, + 0x56CA, 0xD2A5, 0x56CD, 0xFDEE, 0x56D1, 0xF5B6, 0x56DA, 0xE1F6, 0x56DB, 0xDECC, 0x56DE, 0xFCDE, 0x56E0, 0xECD7, 0x56F0, 0xCDDD, + 0x56F9, 0xD6B7, 0x56FA, 0xCDB3, 0x5703, 0xF8D5, 0x5704, 0xE5D8, 0x5708, 0xCFEA, 0x570B, 0xCFD0, 0x570D, 0xEACC, 0x5712, 0xEAAE, + 0x5713, 0xEAAD, 0x5716, 0xD3F1, 0x5718, 0xD3A5, 0x571F, 0xF7CF, 0x5728, 0xEEA4, 0x572D, 0xD0A4, 0x5730, 0xF2A2, 0x573B, 0xD0F0, + 0x5740, 0xF2A3, 0x5742, 0xF7F8, 0x5747, 0xD0B3, 0x574A, 0xDBA9, 0x574D, 0xD3BB, 0x574E, 0xCAEC, 0x5750, 0xF1A6, 0x5751, 0xCBD5, + 0x5761, 0xF7E7, 0x5764, 0xCDDE, 0x5766, 0xF7A4, 0x576A, 0xF8C0, 0x576E, 0xD3DD, 0x5770, 0xCCD0, 0x5775, 0xCFA6, 0x577C, 0xF6F3, + 0x5782, 0xE1F7, 0x5788, 0xD3DC, 0x578B, 0xFAFE, 0x5793, 0xFAA7, 0x57A0, 0xEBD9, 0x57A2, 0xCFA7, 0x57A3, 0xEAAF, 0x57C3, 0xE4EF, + 0x57C7, 0xE9B9, 0x57C8, 0xF1D8, 0x57CB, 0xD8D8, 0x57CE, 0xE0F2, 0x57DF, 0xE6B4, 0x57E0, 0xDCFC, 0x57F0, 0xF3F1, 0x57F4, 0xE3D0, + 0x57F7, 0xF2FB, 0x57F9, 0xDBC6, 0x57FA, 0xD0F1, 0x57FC, 0xD0F2, 0x5800, 0xCFDC, 0x5802, 0xD3D1, 0x5805, 0xCCB1, 0x5806, 0xF7D8, + 0x5808, 0xCBA8, 0x5809, 0xEBBC, 0x580A, 0xE4BE, 0x581E, 0xF4DC, 0x5821, 0xDCC2, 0x5824, 0xF0A7, 0x5827, 0xE6C0, 0x582A, 0xCAED, + 0x582F, 0xE8EB, 0x5830, 0xE5E8, 0x5831, 0xDCC3, 0x5834, 0xEDDE, 0x5835, 0xD3F2, 0x583A, 0xCCF7, 0x584A, 0xCED4, 0x584B, 0xE7AB, + 0x584F, 0xCBC3, 0x5851, 0xE1B1, 0x5854, 0xF7B2, 0x5857, 0xD3F3, 0x5858, 0xD3D2, 0x585A, 0xF5C0, 0x585E, 0xDFDD, 0x5861, 0xEEF3, + 0x5862, 0xE7F1, 0x5864, 0xFDB4, 0x5875, 0xF2C8, 0x5879, 0xF3D2, 0x587C, 0xEEF4, 0x587E, 0xE2D3, 0x5883, 0xCCD1, 0x5885, 0xDFEA, + 0x5889, 0xE9BA, 0x5893, 0xD9D7, 0x589C, 0xF5CD, 0x589E, 0xF1F2, 0x589F, 0xFAC7, 0x58A8, 0xD9F8, 0x58A9, 0xD4C2, 0x58AE, 0xF6E5, + 0x58B3, 0xDDC5, 0x58BA, 0xE7F2, 0x58BB, 0xEDDF, 0x58BE, 0xCACB, 0x58C1, 0xDBFA, 0x58C5, 0xE8B5, 0x58C7, 0xD3A6, 0x58CE, 0xFDB5, + 0x58D1, 0xF9C9, 0x58D3, 0xE4E2, 0x58D5, 0xFBBD, 0x58D8, 0xD7A4, 0x58D9, 0xCEC5, 0x58DE, 0xCED5, 0x58DF, 0xD6E6, 0x58E4, 0xE5BD, + 0x58EB, 0xDECD, 0x58EC, 0xECF3, 0x58EF, 0xEDE0, 0x58F9, 0xECEC, 0x58FA, 0xFBBE, 0x58FB, 0xDFEB, 0x58FD, 0xE1F8, 0x590F, 0xF9BE, + 0x5914, 0xD0F3, 0x5915, 0xE0AA, 0x5916, 0xE8E2, 0x5919, 0xE2D4, 0x591A, 0xD2FD, 0x591C, 0xE5A8, 0x5922, 0xD9D3, 0x5927, 0xD3DE, + 0x5929, 0xF4B8, 0x592A, 0xF7BC, 0x592B, 0xDCFD, 0x592D, 0xE8EC, 0x592E, 0xE4E7, 0x5931, 0xE3F7, 0x5937, 0xECA8, 0x593E, 0xFAF1, + 0x5944, 0xE5F2, 0x5947, 0xD0F4, 0x5948, 0xD2AF, 0x5949, 0xDCE5, 0x594E, 0xD0A5, 0x594F, 0xF1B4, 0x5950, 0xFCB1, 0x5951, 0xCCF8, + 0x5954, 0xDDC6, 0x5955, 0xFAD1, 0x5957, 0xF7DF, 0x595A, 0xFAA8, 0x5960, 0xEEF5, 0x5962, 0xDECE, 0x5967, 0xE7F3, 0x596A, 0xF7AC, + 0x596B, 0xEBC4, 0x596C, 0xEDE1, 0x596D, 0xE0AB, 0x596E, 0xDDC7, 0x5973, 0xD2B3, 0x5974, 0xD2BF, 0x5978, 0xCACC, 0x597D, 0xFBBF, + 0x5982, 0xE5FD, 0x5983, 0xDDE5, 0x5984, 0xD8CD, 0x598A, 0xECF4, 0x5993, 0xD0F5, 0x5996, 0xE8ED, 0x5997, 0xD0D2, 0x5999, 0xD9D8, + 0x59A5, 0xF6E6, 0x59A8, 0xDBAA, 0x59AC, 0xF7E0, 0x59B9, 0xD8D9, 0x59BB, 0xF4A3, 0x59BE, 0xF4DD, 0x59C3, 0xEFD1, 0x59C6, 0xD9B5, + 0x59C9, 0xEDAB, 0x59CB, 0xE3B7, 0x59D0, 0xEEBB, 0x59D1, 0xCDB4, 0x59D3, 0xE0F3, 0x59D4, 0xEACD, 0x59D9, 0xECF5, 0x59DA, 0xE8EE, + 0x59DC, 0xCBA9, 0x59DD, 0xF1AF, 0x59E6, 0xCACD, 0x59E8, 0xECA9, 0x59EA, 0xF2EB, 0x59EC, 0xFDEF, 0x59EE, 0xF9F3, 0x59F8, 0xE6C1, + 0x59FB, 0xECD8, 0x59FF, 0xEDAC, 0x5A01, 0xEACE, 0x5A03, 0xE8DF, 0x5A11, 0xDECF, 0x5A18, 0xD2A6, 0x5A1B, 0xE7F4, 0x5A1C, 0xD1D6, + 0x5A1F, 0xE6C2, 0x5A20, 0xE3E3, 0x5A25, 0xE4B0, 0x5A29, 0xD8B4, 0x5A36, 0xF6A5, 0x5A3C, 0xF3DE, 0x5A41, 0xD7A5, 0x5A46, 0xF7E8, + 0x5A49, 0xE8C6, 0x5A5A, 0xFBE6, 0x5A62, 0xDDE6, 0x5A66, 0xDCFE, 0x5A92, 0xD8DA, 0x5A9A, 0xDAAC, 0x5A9B, 0xEAB0, 0x5AA4, 0xE3B8, + 0x5AC1, 0xCAAA, 0x5AC2, 0xE1F9, 0x5AC4, 0xEAB1, 0x5AC9, 0xF2EC, 0x5ACC, 0xFAEE, 0x5AE1, 0xEED5, 0x5AE6, 0xF9F4, 0x5AE9, 0xD2EC, + 0x5B05, 0xFBFB, 0x5B09, 0xFDF0, 0x5B0B, 0xE0BD, 0x5B0C, 0xCEE3, 0x5B16, 0xF8C6, 0x5B2A, 0xDEAE, 0x5B40, 0xDFC5, 0x5B43, 0xE5BE, + 0x5B50, 0xEDAD, 0x5B51, 0xFAEA, 0x5B54, 0xCDEE, 0x5B55, 0xEDA6, 0x5B57, 0xEDAE, 0x5B58, 0xF0ED, 0x5B5A, 0xDDA1, 0x5B5C, 0xEDAF, + 0x5B5D, 0xFCF8, 0x5B5F, 0xD8EB, 0x5B63, 0xCCF9, 0x5B64, 0xCDB5, 0x5B69, 0xFAA9, 0x5B6B, 0xE1DD, 0x5B70, 0xE2D5, 0x5B71, 0xEDCF, + 0x5B75, 0xDDA2, 0x5B78, 0xF9CA, 0x5B7A, 0xEAE8, 0x5B7C, 0xE5ED, 0x5B85, 0xD3EB, 0x5B87, 0xE9D4, 0x5B88, 0xE1FA, 0x5B89, 0xE4CC, + 0x5B8B, 0xE1E4, 0x5B8C, 0xE8C7, 0x5B8F, 0xCEDB, 0x5B93, 0xDCD5, 0x5B95, 0xF7B5, 0x5B96, 0xFCF3, 0x5B97, 0xF0F3, 0x5B98, 0xCEAF, + 0x5B99, 0xF1B5, 0x5B9A, 0xEFD2, 0x5B9B, 0xE8C8, 0x5B9C, 0xEBF1, 0x5BA2, 0xCBD4, 0x5BA3, 0xE0BE, 0x5BA4, 0xE3F8, 0x5BA5, 0xEAE9, + 0x5BA6, 0xFCB2, 0x5BAC, 0xE0F4, 0x5BAE, 0xCFE0, 0x5BB0, 0xEEA5, 0x5BB3, 0xFAAA, 0x5BB4, 0xE6C3, 0x5BB5, 0xE1B2, 0x5BB6, 0xCAAB, + 0x5BB8, 0xE3E4, 0x5BB9, 0xE9BB, 0x5BBF, 0xE2D6, 0x5BC0, 0xF3F2, 0x5BC2, 0xEED6, 0x5BC3, 0xEAB2, 0x5BC4, 0xD0F6, 0x5BC5, 0xECD9, + 0x5BC6, 0xDACB, 0x5BC7, 0xCFA8, 0x5BCC, 0xDDA3, 0x5BD0, 0xD8DB, 0x5BD2, 0xF9CE, 0x5BD3, 0xE9D5, 0x5BD4, 0xE3D1, 0x5BD7, 0xD2BC, + 0x5BDE, 0xD8AC, 0x5BDF, 0xF3CC, 0x5BE1, 0xCDFB, 0x5BE2, 0xF6D6, 0x5BE4, 0xE7F5, 0x5BE5, 0xE8EF, 0x5BE6, 0xE3F9, 0x5BE7, 0xD2BB, + 0x5BE8, 0xF3F3, 0x5BE9, 0xE3FB, 0x5BEB, 0xDED0, 0x5BEC, 0xCEB0, 0x5BEE, 0xD6F7, 0x5BEF, 0xF1D9, 0x5BF5, 0xF5C1, 0x5BF6, 0xDCC4, + 0x5BF8, 0xF5BB, 0x5BFA, 0xDED1, 0x5C01, 0xDCE6, 0x5C04, 0xDED2, 0x5C07, 0xEDE2, 0x5C08, 0xEEF6, 0x5C09, 0xEACF, 0x5C0A, 0xF0EE, + 0x5C0B, 0xE3FC, 0x5C0D, 0xD3DF, 0x5C0E, 0xD3F4, 0x5C0F, 0xE1B3, 0x5C11, 0xE1B4, 0x5C16, 0xF4D3, 0x5C19, 0xDFC6, 0x5C24, 0xE9D6, + 0x5C28, 0xDBAB, 0x5C31, 0xF6A6, 0x5C38, 0xE3B9, 0x5C39, 0xEBC5, 0x5C3A, 0xF4A9, 0x5C3B, 0xCDB6, 0x5C3C, 0xD2F9, 0x5C3E, 0xDAAD, + 0x5C3F, 0xD2E3, 0x5C40, 0xCFD1, 0x5C45, 0xCBDC, 0x5C46, 0xCCFA, 0x5C48, 0xCFDD, 0x5C4B, 0xE8A9, 0x5C4D, 0xE3BB, 0x5C4E, 0xE3BA, + 0x5C51, 0xE0DA, 0x5C55, 0xEEF7, 0x5C5B, 0xDCB3, 0x5C60, 0xD3F5, 0x5C62, 0xD7A6, 0x5C64, 0xF6B5, 0x5C65, 0xD7DB, 0x5C6C, 0xE1D5, + 0x5C6F, 0xD4EA, 0x5C71, 0xDFA3, 0x5C79, 0xFDDF, 0x5C90, 0xD0F7, 0x5C91, 0xEDD4, 0x5CA1, 0xCBAA, 0x5CA9, 0xE4DB, 0x5CAB, 0xE1FB, + 0x5CAC, 0xCBA2, 0x5CB1, 0xD3E0, 0x5CB3, 0xE4BF, 0x5CB5, 0xFBC0, 0x5CB7, 0xDABE, 0x5CB8, 0xE4CD, 0x5CBA, 0xD6B9, 0x5CBE, 0xEFC0, + 0x5CC0, 0xE1FC, 0x5CD9, 0xF6B9, 0x5CE0, 0xDFC7, 0x5CE8, 0xE4B1, 0x5CEF, 0xDCE7, 0x5CF0, 0xDCE8, 0x5CF4, 0xFAD6, 0x5CF6, 0xD3F6, + 0x5CFB, 0xF1DA, 0x5CFD, 0xFAF2, 0x5D07, 0xE2FD, 0x5D0D, 0xD5CF, 0x5D0E, 0xD0F8, 0x5D11, 0xCDDF, 0x5D14, 0xF5CB, 0x5D16, 0xE4F0, + 0x5D17, 0xCBAB, 0x5D19, 0xD7C4, 0x5D27, 0xE2FE, 0x5D29, 0xDDDA, 0x5D4B, 0xDAAE, 0x5D4C, 0xCAEE, 0x5D50, 0xD5B9, 0x5D69, 0xE3A1, + 0x5D6C, 0xE8E3, 0x5D6F, 0xF3AB, 0x5D87, 0xCFA9, 0x5D8B, 0xD3F7, 0x5D9D, 0xD4F1, 0x5DA0, 0xCEE4, 0x5DA2, 0xE8F2, 0x5DAA, 0xE5F5, + 0x5DB8, 0xE7AE, 0x5DBA, 0xD6BA, 0x5DBC, 0xDFEC, 0x5DBD, 0xE4C0, 0x5DCD, 0xE8E4, 0x5DD2, 0xD8B5, 0x5DD6, 0xE4DC, 0x5DDD, 0xF4B9, + 0x5DDE, 0xF1B6, 0x5DE1, 0xE2DE, 0x5DE2, 0xE1B5, 0x5DE5, 0xCDEF, 0x5DE6, 0xF1A7, 0x5DE7, 0xCEE5, 0x5DE8, 0xCBDD, 0x5DEB, 0xD9E3, + 0x5DEE, 0xF3AC, 0x5DF1, 0xD0F9, 0x5DF2, 0xECAB, 0x5DF3, 0xDED3, 0x5DF4, 0xF7E9, 0x5DF7, 0xF9F5, 0x5DFD, 0xE1DE, 0x5DFE, 0xCBEE, + 0x5E02, 0xE3BC, 0x5E03, 0xF8D6, 0x5E06, 0xDBEE, 0x5E0C, 0xFDF1, 0x5E11, 0xF7B6, 0x5E16, 0xF4DE, 0x5E19, 0xF2ED, 0x5E1B, 0xDBD9, + 0x5E1D, 0xF0A8, 0x5E25, 0xE1FD, 0x5E2B, 0xDED4, 0x5E2D, 0xE0AC, 0x5E33, 0xEDE3, 0x5E36, 0xD3E1, 0x5E38, 0xDFC8, 0x5E3D, 0xD9B6, + 0x5E3F, 0xFDAC, 0x5E40, 0xEFD3, 0x5E44, 0xE4C1, 0x5E45, 0xF8EB, 0x5E47, 0xDBAC, 0x5E4C, 0xFCC6, 0x5E55, 0xD8AD, 0x5E5F, 0xF6BA, + 0x5E61, 0xDBDF, 0x5E62, 0xD3D3, 0x5E63, 0xF8C7, 0x5E72, 0xCACE, 0x5E73, 0xF8C1, 0x5E74, 0xD2B4, 0x5E77, 0xDCB4, 0x5E78, 0xFAB9, + 0x5E79, 0xCACF, 0x5E7B, 0xFCB3, 0x5E7C, 0xEAEA, 0x5E7D, 0xEAEB, 0x5E7E, 0xD0FA, 0x5E84, 0xEDE4, 0x5E87, 0xDDE7, 0x5E8A, 0xDFC9, + 0x5E8F, 0xDFED, 0x5E95, 0xEEBC, 0x5E97, 0xEFC1, 0x5E9A, 0xCCD2, 0x5E9C, 0xDDA4, 0x5EA0, 0xDFCA, 0x5EA6, 0xD3F8, 0x5EA7, 0xF1A8, + 0x5EAB, 0xCDB7, 0x5EAD, 0xEFD4, 0x5EB5, 0xE4DD, 0x5EB6, 0xDFEE, 0x5EB7, 0xCBAC, 0x5EB8, 0xE9BC, 0x5EBE, 0xEAEC, 0x5EC2, 0xDFCB, + 0x5EC8, 0xF9BF, 0x5EC9, 0xD6AF, 0x5ECA, 0xD5C6, 0x5ED0, 0xCFAA, 0x5ED3, 0xCEA9, 0x5ED6, 0xD6F8, 0x5EDA, 0xF1B7, 0x5EDB, 0xEEF8, + 0x5EDF, 0xD9D9, 0x5EE0, 0xF3DF, 0x5EE2, 0xF8C8, 0x5EE3, 0xCEC6, 0x5EEC, 0xD5E6, 0x5EF3, 0xF4E6, 0x5EF6, 0xE6C5, 0x5EF7, 0xEFD5, + 0x5EFA, 0xCBEF, 0x5EFB, 0xFCDF, 0x5F01, 0xDCA7, 0x5F04, 0xD6E7, 0x5F0A, 0xF8C9, 0x5F0F, 0xE3D2, 0x5F11, 0xE3BD, 0x5F13, 0xCFE1, + 0x5F14, 0xF0C0, 0x5F15, 0xECDA, 0x5F17, 0xDDD7, 0x5F18, 0xFBF0, 0x5F1B, 0xECAC, 0x5F1F, 0xF0A9, 0x5F26, 0xFAD7, 0x5F27, 0xFBC1, + 0x5F29, 0xD2C0, 0x5F31, 0xE5B0, 0x5F35, 0xEDE5, 0x5F3A, 0xCBAD, 0x5F3C, 0xF9B0, 0x5F48, 0xF7A5, 0x5F4A, 0xCBAE, 0x5F4C, 0xDAAF, + 0x5F4E, 0xD8B6, 0x5F56, 0xD3A7, 0x5F57, 0xFBB2, 0x5F59, 0xFDC4, 0x5F5B, 0xECAD, 0x5F62, 0xFBA1, 0x5F66, 0xE5E9, 0x5F67, 0xE9EE, + 0x5F69, 0xF3F4, 0x5F6A, 0xF8F3, 0x5F6B, 0xF0C1, 0x5F6C, 0xDEAF, 0x5F6D, 0xF8B0, 0x5F70, 0xF3E0, 0x5F71, 0xE7AF, 0x5F77, 0xDBAD, + 0x5F79, 0xE6B5, 0x5F7C, 0xF9A8, 0x5F7F, 0xDDD8, 0x5F80, 0xE8D9, 0x5F81, 0xEFD6, 0x5F85, 0xD3E2, 0x5F87, 0xE2DF, 0x5F8A, 0xFCE0, + 0x5F8B, 0xD7C8, 0x5F8C, 0xFDAD, 0x5F90, 0xDFEF, 0x5F91, 0xCCD3, 0x5F92, 0xD3F9, 0x5F97, 0xD4F0, 0x5F98, 0xDBC7, 0x5F99, 0xDED5, + 0x5F9E, 0xF0F4, 0x5FA0, 0xD5D0, 0x5FA1, 0xE5D9, 0x5FA8, 0xFCC7, 0x5FA9, 0xDCD6, 0x5FAA, 0xE2E0, 0x5FAE, 0xDAB0, 0x5FB5, 0xF3A3, + 0x5FB7, 0xD3EC, 0x5FB9, 0xF4CB, 0x5FBD, 0xFDC5, 0x5FC3, 0xE3FD, 0x5FC5, 0xF9B1, 0x5FCC, 0xD0FB, 0x5FCD, 0xECDB, 0x5FD6, 0xF5BC, + 0x5FD7, 0xF2A4, 0x5FD8, 0xD8CE, 0x5FD9, 0xD8CF, 0x5FE0, 0xF5F7, 0x5FEB, 0xF6E1, 0x5FF5, 0xD2B7, 0x5FFD, 0xFBEC, 0x5FFF, 0xDDC8, + 0x600F, 0xE4E8, 0x6012, 0xD2C1, 0x6016, 0xF8D7, 0x601C, 0xD6BB, 0x601D, 0xDED6, 0x6020, 0xF7BD, 0x6021, 0xECAE, 0x6025, 0xD0E1, + 0x6027, 0xE0F5, 0x6028, 0xEAB3, 0x602A, 0xCED6, 0x602F, 0xCCA5, 0x6041, 0xECF6, 0x6042, 0xE2E1, 0x6043, 0xE3BE, 0x604D, 0xFCC8, + 0x6050, 0xCDF0, 0x6052, 0xF9F6, 0x6055, 0xDFF0, 0x6059, 0xE5BF, 0x605D, 0xCEBF, 0x6062, 0xFCE1, 0x6063, 0xEDB0, 0x6064, 0xFDD1, + 0x6065, 0xF6BB, 0x6068, 0xF9CF, 0x6069, 0xEBDA, 0x606A, 0xCAC1, 0x606C, 0xD2B8, 0x606D, 0xCDF1, 0x606F, 0xE3D3, 0x6070, 0xFDE6, + 0x6085, 0xE6ED, 0x6089, 0xE3FA, 0x608C, 0xF0AA, 0x608D, 0xF9D0, 0x6094, 0xFCE2, 0x6096, 0xF8A7, 0x609A, 0xE1E5, 0x609B, 0xEEF9, + 0x609F, 0xE7F6, 0x60A0, 0xEAED, 0x60A3, 0xFCB4, 0x60A4, 0xF5C2, 0x60A7, 0xD7DC, 0x60B0, 0xF0F5, 0x60B2, 0xDDE8, 0x60B3, 0xD3ED, + 0x60B4, 0xF5FC, 0x60B6, 0xDABF, 0x60B8, 0xCCFB, 0x60BC, 0xD3FA, 0x60BD, 0xF4A4, 0x60C5, 0xEFD7, 0x60C7, 0xD4C3, 0x60D1, 0xFBE3, + 0x60DA, 0xFBED, 0x60DC, 0xE0AD, 0x60DF, 0xEAEE, 0x60E0, 0xFBB3, 0x60E1, 0xE4C2, 0x60F0, 0xF6E7, 0x60F1, 0xD2DD, 0x60F3, 0xDFCC, + 0x60F6, 0xFCC9, 0x60F9, 0xE5A9, 0x60FA, 0xE0F6, 0x60FB, 0xF6B3, 0x6101, 0xE1FE, 0x6106, 0xCBF0, 0x6108, 0xEAEF, 0x6109, 0xEAF0, + 0x610D, 0xDAC0, 0x610E, 0xF8B4, 0x610F, 0xEBF2, 0x6115, 0xE4C3, 0x611A, 0xE9D7, 0x611B, 0xE4F1, 0x611F, 0xCAEF, 0x6127, 0xCED7, + 0x6130, 0xFCCA, 0x6134, 0xF3E1, 0x6137, 0xCBC4, 0x613C, 0xE3E5, 0x613E, 0xCBC5, 0x613F, 0xEAB4, 0x6142, 0xE9BD, 0x6144, 0xD7C9, + 0x6147, 0xEBDB, 0x6148, 0xEDB1, 0x614A, 0xCCC3, 0x614B, 0xF7BE, 0x614C, 0xFCCB, 0x6153, 0xF8F4, 0x6155, 0xD9B7, 0x6158, 0xF3D3, + 0x6159, 0xF3D4, 0x615D, 0xF7E4, 0x615F, 0xF7D1, 0x6162, 0xD8B7, 0x6163, 0xCEB1, 0x6164, 0xCAC2, 0x6167, 0xFBB4, 0x6168, 0xCBC6, + 0x616B, 0xF0F6, 0x616E, 0xD5E7, 0x6170, 0xEAD0, 0x6176, 0xCCD4, 0x6177, 0xCBAF, 0x617D, 0xF4AA, 0x617E, 0xE9AF, 0x6181, 0xF5C3, + 0x6182, 0xE9D8, 0x618A, 0xDDE9, 0x618E, 0xF1F3, 0x6190, 0xD5FB, 0x6191, 0xDEBB, 0x6194, 0xF4FB, 0x6198, 0xFDF3, 0x6199, 0xFDF2, + 0x619A, 0xF7A6, 0x61A4, 0xDDC9, 0x61A7, 0xD4D3, 0x61A9, 0xCCA8, 0x61AB, 0xDAC1, 0x61AC, 0xCCD5, 0x61AE, 0xD9E4, 0x61B2, 0xFACA, + 0x61B6, 0xE5E3, 0x61BA, 0xD3BC, 0x61BE, 0xCAF0, 0x61C3, 0xD0C4, 0x61C7, 0xCAD0, 0x61C8, 0xFAAB, 0x61C9, 0xEBEB, 0x61CA, 0xE7F8, + 0x61CB, 0xD9E5, 0x61E6, 0xD1D7, 0x61F2, 0xF3A4, 0x61F6, 0xD4FB, 0x61F7, 0xFCE3, 0x61F8, 0xFAD8, 0x61FA, 0xF3D5, 0x61FC, 0xCFAB, + 0x61FF, 0xEBF3, 0x6200, 0xD5FC, 0x6207, 0xD3D4, 0x6208, 0xCDFC, 0x620A, 0xD9E6, 0x620C, 0xE2F9, 0x620D, 0xE2A1, 0x620E, 0xEBD4, + 0x6210, 0xE0F7, 0x6211, 0xE4B2, 0x6212, 0xCCFC, 0x6216, 0xFBE4, 0x621A, 0xF4AB, 0x621F, 0xD0BD, 0x6221, 0xCAF1, 0x622A, 0xEFB8, + 0x622E, 0xD7C0, 0x6230, 0xEEFA, 0x6231, 0xFDF4, 0x6234, 0xD3E3, 0x6236, 0xFBC2, 0x623E, 0xD5E8, 0x623F, 0xDBAE, 0x6240, 0xE1B6, + 0x6241, 0xF8B7, 0x6247, 0xE0BF, 0x6248, 0xFBC3, 0x6249, 0xDDEA, 0x624B, 0xE2A2, 0x624D, 0xEEA6, 0x6253, 0xF6E8, 0x6258, 0xF6F5, + 0x626E, 0xDDCA, 0x6271, 0xD0E2, 0x6276, 0xDDA6, 0x6279, 0xDDEB, 0x627C, 0xE4F9, 0x627F, 0xE3AF, 0x6280, 0xD0FC, 0x6284, 0xF4FC, + 0x6289, 0xCCBC, 0x628A, 0xF7EA, 0x6291, 0xE5E4, 0x6292, 0xDFF1, 0x6295, 0xF7E1, 0x6297, 0xF9F7, 0x6298, 0xEFB9, 0x629B, 0xF8D8, + 0x62AB, 0xF9A9, 0x62B1, 0xF8D9, 0x62B5, 0xEEBD, 0x62B9, 0xD8C6, 0x62BC, 0xE4E3, 0x62BD, 0xF5CE, 0x62C2, 0xDDD9, 0x62C7, 0xD9E7, + 0x62C8, 0xD2B9, 0x62C9, 0xD5C3, 0x62CC, 0xDAE5, 0x62CD, 0xDAD0, 0x62CF, 0xD1D9, 0x62D0, 0xCED8, 0x62D2, 0xCBDE, 0x62D3, 0xF4AC, + 0x62D4, 0xDAFB, 0x62D6, 0xF6E9, 0x62D7, 0xE8F3, 0x62D8, 0xCFAC, 0x62D9, 0xF0F0, 0x62DB, 0xF4FD, 0x62DC, 0xDBC8, 0x62EC, 0xCEC0, + 0x62ED, 0xE3D4, 0x62EE, 0xD1CF, 0x62EF, 0xF1F5, 0x62F1, 0xCDF2, 0x62F3, 0xCFEB, 0x62F7, 0xCDB8, 0x62FE, 0xE3A6, 0x62FF, 0xD1DA, + 0x6301, 0xF2A5, 0x6307, 0xF2A6, 0x6309, 0xE4CE, 0x6311, 0xD3FB, 0x632B, 0xF1A9, 0x632F, 0xF2C9, 0x633A, 0xEFD8, 0x633B, 0xE6C9, + 0x633D, 0xD8B8, 0x633E, 0xFAF3, 0x6349, 0xF3B5, 0x634C, 0xF8A4, 0x634F, 0xD1F3, 0x6350, 0xE6C8, 0x6355, 0xF8DA, 0x6367, 0xDCE9, + 0x6368, 0xDED7, 0x636E, 0xCBDF, 0x6372, 0xCFEC, 0x6377, 0xF4DF, 0x637A, 0xD1F4, 0x637B, 0xD2BA, 0x637F, 0xDFF2, 0x6383, 0xE1B7, + 0x6388, 0xE2A3, 0x6389, 0xD3FC, 0x638C, 0xEDE6, 0x6392, 0xDBC9, 0x6396, 0xE4FA, 0x6398, 0xCFDE, 0x639B, 0xCED0, 0x63A0, 0xD5D3, + 0x63A1, 0xF3F5, 0x63A2, 0xF7AE, 0x63A5, 0xEFC8, 0x63A7, 0xCDF3, 0x63A8, 0xF5CF, 0x63A9, 0xE5F3, 0x63AA, 0xF0C2, 0x63C0, 0xCAD1, + 0x63C4, 0xEAF1, 0x63C6, 0xD0A6, 0x63CF, 0xD9DA, 0x63D0, 0xF0AB, 0x63D6, 0xEBE7, 0x63DA, 0xE5C0, 0x63DB, 0xFCB5, 0x63E1, 0xE4C4, + 0x63ED, 0xCCA9, 0x63EE, 0xFDC6, 0x63F4, 0xEAB5, 0x63F6, 0xE5AA, 0x63F7, 0xDFBA, 0x640D, 0xE1DF, 0x640F, 0xDAD1, 0x6414, 0xE1B8, + 0x6416, 0xE8F4, 0x6417, 0xD3FD, 0x641C, 0xE2A4, 0x6422, 0xF2CA, 0x642C, 0xDAE6, 0x642D, 0xF7B3, 0x643A, 0xFDCD, 0x643E, 0xF3B6, + 0x6458, 0xEED7, 0x6460, 0xF5C4, 0x6469, 0xD8A4, 0x646F, 0xF2A7, 0x6478, 0xD9B8, 0x6479, 0xD9B9, 0x647A, 0xEFC9, 0x6488, 0xD6CE, + 0x6491, 0xF7CB, 0x6492, 0xDFAE, 0x6493, 0xE8F5, 0x649A, 0xD2B5, 0x649E, 0xD3D5, 0x64A4, 0xF4CC, 0x64A5, 0xDAFC, 0x64AB, 0xD9E8, + 0x64AD, 0xF7EB, 0x64AE, 0xF5C9, 0x64B0, 0xF3BC, 0x64B2, 0xDAD2, 0x64BB, 0xD3B5, 0x64C1, 0xE8B6, 0x64C4, 0xD6CF, 0x64C5, 0xF4BA, + 0x64C7, 0xF7C9, 0x64CA, 0xCCAA, 0x64CD, 0xF0C3, 0x64CE, 0xCCD6, 0x64D2, 0xD0D3, 0x64D4, 0xD3BD, 0x64D8, 0xDBFB, 0x64DA, 0xCBE0, + 0x64E1, 0xD3E4, 0x64E2, 0xF6F7, 0x64E5, 0xD5BA, 0x64E6, 0xF3CD, 0x64E7, 0xCBE1, 0x64EC, 0xEBF4, 0x64F2, 0xF4AD, 0x64F4, 0xFCAA, + 0x64FA, 0xF7EC, 0x64FE, 0xE8F6, 0x6500, 0xDAE7, 0x6504, 0xF7CC, 0x6518, 0xE5C1, 0x651D, 0xE0EE, 0x6523, 0xD5FD, 0x652A, 0xCEE6, + 0x652B, 0xFCAB, 0x652C, 0xD5BB, 0x652F, 0xF2A8, 0x6536, 0xE2A5, 0x6537, 0xCDB9, 0x6538, 0xEAF2, 0x6539, 0xCBC7, 0x653B, 0xCDF4, + 0x653E, 0xDBAF, 0x653F, 0xEFD9, 0x6545, 0xCDBA, 0x6548, 0xFCF9, 0x654D, 0xDFF3, 0x654E, 0xCEE7, 0x654F, 0xDAC2, 0x6551, 0xCFAD, + 0x6556, 0xE7F9, 0x6557, 0xF8A8, 0x655E, 0xF3E2, 0x6562, 0xCAF2, 0x6563, 0xDFA4, 0x6566, 0xD4C4, 0x656C, 0xCCD7, 0x656D, 0xE5C2, + 0x6572, 0xCDBB, 0x6574, 0xEFDA, 0x6575, 0xEED8, 0x6577, 0xDDA7, 0x6578, 0xE2A6, 0x657E, 0xE0C0, 0x6582, 0xD6B0, 0x6583, 0xF8CA, + 0x6585, 0xFCFA, 0x6587, 0xD9FE, 0x658C, 0xDEB0, 0x6590, 0xDDEC, 0x6591, 0xDAE8, 0x6597, 0xD4E0, 0x6599, 0xD6F9, 0x659B, 0xCDD7, + 0x659C, 0xDED8, 0x659F, 0xF2F8, 0x65A1, 0xE4D6, 0x65A4, 0xD0C5, 0x65A5, 0xF4AE, 0x65A7, 0xDDA8, 0x65AB, 0xEDC5, 0x65AC, 0xF3D6, + 0x65AF, 0xDED9, 0x65B0, 0xE3E6, 0x65B7, 0xD3A8, 0x65B9, 0xDBB0, 0x65BC, 0xE5DA, 0x65BD, 0xE3BF, 0x65C1, 0xDBB1, 0x65C5, 0xD5E9, + 0x65CB, 0xE0C1, 0x65CC, 0xEFDB, 0x65CF, 0xF0E9, 0x65D2, 0xD7B2, 0x65D7, 0xD0FD, 0x65E0, 0xD9E9, 0x65E3, 0xD0FE, 0x65E5, 0xECED, + 0x65E6, 0xD3A9, 0x65E8, 0xF2A9, 0x65E9, 0xF0C4, 0x65EC, 0xE2E2, 0x65ED, 0xE9EF, 0x65F1, 0xF9D1, 0x65F4, 0xE9D9, 0x65FA, 0xE8DA, + 0x65FB, 0xDAC3, 0x65FC, 0xDAC4, 0x65FD, 0xD4C5, 0x65FF, 0xE7FA, 0x6606, 0xCDE0, 0x6607, 0xE3B0, 0x6609, 0xDBB2, 0x660A, 0xFBC4, + 0x660C, 0xF3E3, 0x660E, 0xD9A5, 0x660F, 0xFBE7, 0x6610, 0xDDCB, 0x6611, 0xD0D4, 0x6613, 0xE6B6, 0x6614, 0xE0AE, 0x6615, 0xFDDA, + 0x661E, 0xDCB5, 0x661F, 0xE0F8, 0x6620, 0xE7B1, 0x6625, 0xF5F0, 0x6627, 0xD8DC, 0x6628, 0xEDC6, 0x662D, 0xE1B9, 0x662F, 0xE3C0, + 0x6630, 0xF9C0, 0x6631, 0xE9F0, 0x6634, 0xD9DB, 0x6636, 0xF3E4, 0x663A, 0xDCB6, 0x663B, 0xE4E9, 0x6641, 0xF0C5, 0x6642, 0xE3C1, + 0x6643, 0xFCCC, 0x6644, 0xFCCD, 0x6649, 0xF2CB, 0x664B, 0xF2CC, 0x664F, 0xE4CF, 0x6659, 0xF1DB, 0x665B, 0xFAD9, 0x665D, 0xF1B8, + 0x665E, 0xFDF5, 0x665F, 0xE0F9, 0x6664, 0xE7FB, 0x6665, 0xFCB7, 0x6666, 0xFCE4, 0x6667, 0xFBC5, 0x6668, 0xE3E7, 0x6669, 0xD8B9, + 0x666B, 0xF6F8, 0x666E, 0xDCC5, 0x666F, 0xCCD8, 0x6673, 0xE0AF, 0x6674, 0xF4E7, 0x6676, 0xEFDC, 0x6677, 0xCFFC, 0x6678, 0xEFDD, + 0x667A, 0xF2AA, 0x6684, 0xFDBE, 0x6687, 0xCAAC, 0x6688, 0xFDBB, 0x6689, 0xFDC7, 0x668E, 0xE7B2, 0x6690, 0xEAD1, 0x6691, 0xDFF4, + 0x6696, 0xD1EC, 0x6697, 0xE4DE, 0x6698, 0xE5C3, 0x669D, 0xD9A6, 0x66A0, 0xCDBC, 0x66A2, 0xF3E5, 0x66AB, 0xEDD5, 0x66AE, 0xD9BA, + 0x66B2, 0xEDE7, 0x66B3, 0xFBB5, 0x66B4, 0xF8EC, 0x66B9, 0xE0E7, 0x66BB, 0xCCD9, 0x66BE, 0xD4C6, 0x66C4, 0xE7A5, 0x66C6, 0xD5F5, + 0x66C7, 0xD3BE, 0x66C9, 0xFCFB, 0x66D6, 0xE4F2, 0x66D9, 0xDFF5, 0x66DC, 0xE8F8, 0x66DD, 0xF8ED, 0x66E0, 0xCEC7, 0x66E6, 0xFDF6, + 0x66F0, 0xE8D8, 0x66F2, 0xCDD8, 0x66F3, 0xE7D6, 0x66F4, 0xCCDA, 0x66F7, 0xCAE3, 0x66F8, 0xDFF6, 0x66F9, 0xF0C7, 0x66FA, 0xF0C6, + 0x66FC, 0xD8BA, 0x66FE, 0xF1F4, 0x66FF, 0xF4F0, 0x6700, 0xF5CC, 0x6703, 0xFCE5, 0x6708, 0xEAC5, 0x6709, 0xEAF3, 0x670B, 0xDDDB, + 0x670D, 0xDCD7, 0x6714, 0xDEFD, 0x6715, 0xF2F9, 0x6717, 0xD5C7, 0x671B, 0xD8D0, 0x671D, 0xF0C8, 0x671E, 0xD1A1, 0x671F, 0xD1A2, + 0x6726, 0xD9D4, 0x6727, 0xD6E8, 0x6728, 0xD9CA, 0x672A, 0xDAB1, 0x672B, 0xD8C7, 0x672C, 0xDCE2, 0x672D, 0xF3CE, 0x672E, 0xF5F4, + 0x6731, 0xF1B9, 0x6734, 0xDAD3, 0x6736, 0xF6EA, 0x673A, 0xCFF5, 0x673D, 0xFDAE, 0x6746, 0xCAD2, 0x6749, 0xDFB4, 0x674E, 0xD7DD, + 0x674F, 0xFABA, 0x6750, 0xEEA7, 0x6751, 0xF5BD, 0x6753, 0xF8F5, 0x6756, 0xEDE8, 0x675C, 0xD4E1, 0x675E, 0xD1A3, 0x675F, 0xE1D6, + 0x676D, 0xF9F8, 0x676F, 0xDBCA, 0x6770, 0xCBF9, 0x6771, 0xD4D4, 0x6773, 0xD9DC, 0x6775, 0xEEBE, 0x6777, 0xF7ED, 0x677B, 0xD2EE, + 0x677E, 0xE1E6, 0x677F, 0xF7F9, 0x6787, 0xDDED, 0x6789, 0xE8DB, 0x678B, 0xDBB3, 0x678F, 0xD1F7, 0x6790, 0xE0B0, 0x6793, 0xD4E2, + 0x6795, 0xF6D7, 0x6797, 0xD7F9, 0x679A, 0xD8DD, 0x679C, 0xCDFD, 0x679D, 0xF2AB, 0x67AF, 0xCDBD, 0x67B0, 0xF8C2, 0x67B3, 0xF2AC, + 0x67B6, 0xCAAD, 0x67B7, 0xCAAE, 0x67B8, 0xCFAE, 0x67BE, 0xE3C2, 0x67C4, 0xDCB7, 0x67CF, 0xDBDA, 0x67D0, 0xD9BB, 0x67D1, 0xCAF3, + 0x67D2, 0xF6D3, 0x67D3, 0xE6F8, 0x67D4, 0xEAF5, 0x67DA, 0xEAF6, 0x67DD, 0xF6F9, 0x67E9, 0xCFAF, 0x67EC, 0xCAD3, 0x67EF, 0xCAAF, + 0x67F0, 0xD2B0, 0x67F1, 0xF1BA, 0x67F3, 0xD7B3, 0x67F4, 0xE3C3, 0x67F5, 0xF3FD, 0x67F6, 0xDEDA, 0x67FB, 0xDEDB, 0x67FE, 0xEFDE, + 0x6812, 0xE2E3, 0x6813, 0xEEFB, 0x6816, 0xDFF7, 0x6817, 0xD7CA, 0x6821, 0xCEE8, 0x6822, 0xDBDB, 0x682A, 0xF1BB, 0x682F, 0xE9F1, + 0x6838, 0xFAB7, 0x6839, 0xD0C6, 0x683C, 0xCCAB, 0x683D, 0xEEA8, 0x6840, 0xCBFA, 0x6841, 0xF9F9, 0x6842, 0xCCFD, 0x6843, 0xD3FE, + 0x6848, 0xE4D0, 0x684E, 0xF2EE, 0x6850, 0xD4D5, 0x6851, 0xDFCD, 0x6853, 0xFCB8, 0x6854, 0xD1D0, 0x686D, 0xF2CD, 0x6876, 0xF7D2, + 0x687F, 0xCAD4, 0x6881, 0xD5D9, 0x6885, 0xD8DE, 0x688F, 0xCDD9, 0x6893, 0xEEA9, 0x6894, 0xF6BC, 0x6897, 0xCCDB, 0x689D, 0xF0C9, + 0x689F, 0xFCFC, 0x68A1, 0xE8C9, 0x68A2, 0xF4FE, 0x68A7, 0xE7FC, 0x68A8, 0xD7DE, 0x68AD, 0xDEDC, 0x68AF, 0xF0AC, 0x68B0, 0xCCFE, + 0x68B1, 0xCDE1, 0x68B3, 0xE1BA, 0x68B5, 0xDBEF, 0x68B6, 0xDAB2, 0x68C4, 0xD1A5, 0x68C5, 0xDCB8, 0x68C9, 0xD8F6, 0x68CB, 0xD1A4, + 0x68CD, 0xCDE2, 0x68D2, 0xDCEA, 0x68D5, 0xF0F7, 0x68D7, 0xF0CA, 0x68D8, 0xD0BE, 0x68DA, 0xDDDC, 0x68DF, 0xD4D6, 0x68E0, 0xD3D6, + 0x68E7, 0xEDD0, 0x68E8, 0xCDA1, 0x68EE, 0xDFB5, 0x68F2, 0xDFF8, 0x68F9, 0xD4A1, 0x68FA, 0xCEB2, 0x6900, 0xE8CA, 0x6905, 0xEBF5, + 0x690D, 0xE3D5, 0x690E, 0xF5D0, 0x6912, 0xF5A1, 0x6927, 0xD9A7, 0x6930, 0xE5AB, 0x693D, 0xE6CB, 0x693F, 0xF5F1, 0x694A, 0xE5C5, + 0x6953, 0xF9A3, 0x6954, 0xE0DB, 0x6955, 0xF6EB, 0x6957, 0xCBF1, 0x6959, 0xD9EA, 0x695A, 0xF5A2, 0x695E, 0xD7D1, 0x6960, 0xD1F8, + 0x6961, 0xEAF8, 0x6962, 0xEAF9, 0x6963, 0xDAB3, 0x6968, 0xEFDF, 0x696B, 0xF1EF, 0x696D, 0xE5F6, 0x696E, 0xEEBF, 0x696F, 0xE2E4, + 0x6975, 0xD0BF, 0x6977, 0xFAAC, 0x6978, 0xF5D1, 0x6979, 0xE7B3, 0x6995, 0xE9BE, 0x699B, 0xF2CE, 0x699C, 0xDBB4, 0x69A5, 0xFCCE, + 0x69A7, 0xDDEE, 0x69AE, 0xE7B4, 0x69B4, 0xD7B4, 0x69BB, 0xF7B4, 0x69C1, 0xCDBE, 0x69C3, 0xDAE9, 0x69CB, 0xCFB0, 0x69CC, 0xF7D9, + 0x69CD, 0xF3E6, 0x69D0, 0xCED9, 0x69E8, 0xCEAA, 0x69EA, 0xCBC8, 0x69FB, 0xD0A7, 0x69FD, 0xF0CB, 0x69FF, 0xD0C7, 0x6A02, 0xE4C5, + 0x6A0A, 0xDBE0, 0x6A11, 0xD5DA, 0x6A13, 0xD7A7, 0x6A17, 0xEEC0, 0x6A19, 0xF8F6, 0x6A1E, 0xF5D2, 0x6A1F, 0xEDE9, 0x6A21, 0xD9BC, + 0x6A23, 0xE5C6, 0x6A35, 0xF5A3, 0x6A38, 0xDAD4, 0x6A39, 0xE2A7, 0x6A3A, 0xFBFC, 0x6A3D, 0xF1DC, 0x6A44, 0xCAF4, 0x6A48, 0xE8FA, + 0x6A4B, 0xCEE9, 0x6A52, 0xE9F8, 0x6A53, 0xE2E5, 0x6A58, 0xD0B9, 0x6A59, 0xD4F2, 0x6A5F, 0xD1A6, 0x6A61, 0xDFCE, 0x6A6B, 0xFCF4, + 0x6A80, 0xD3AA, 0x6A84, 0xCCAC, 0x6A89, 0xEFE0, 0x6A8D, 0xE5E5, 0x6A8E, 0xD0D5, 0x6A97, 0xDBFC, 0x6A9C, 0xFCE6, 0x6AA2, 0xCBFE, + 0x6AA3, 0xEDEA, 0x6AB3, 0xDEB1, 0x6ABB, 0xF9E3, 0x6AC2, 0xD4A2, 0x6AC3, 0xCFF6, 0x6AD3, 0xD6D0, 0x6ADA, 0xD5EA, 0x6ADB, 0xF1EE, + 0x6AF6, 0xFACB, 0x6AFB, 0xE5A1, 0x6B04, 0xD5B1, 0x6B0A, 0xCFED, 0x6B0C, 0xEDEB, 0x6B12, 0xD5B2, 0x6B16, 0xD5BC, 0x6B20, 0xFDE2, + 0x6B21, 0xF3AD, 0x6B23, 0xFDDB, 0x6B32, 0xE9B0, 0x6B3A, 0xD1A7, 0x6B3D, 0xFDE3, 0x6B3E, 0xCEB3, 0x6B46, 0xFDE4, 0x6B47, 0xFACE, + 0x6B4C, 0xCAB0, 0x6B4E, 0xF7A7, 0x6B50, 0xCFB1, 0x6B5F, 0xE6A2, 0x6B61, 0xFCB6, 0x6B62, 0xF2AD, 0x6B63, 0xEFE1, 0x6B64, 0xF3AE, + 0x6B65, 0xDCC6, 0x6B66, 0xD9EB, 0x6B6A, 0xE8E0, 0x6B72, 0xE1A8, 0x6B77, 0xD5F6, 0x6B78, 0xCFFD, 0x6B7B, 0xDEDD, 0x6B7F, 0xD9D1, + 0x6B83, 0xE4EA, 0x6B84, 0xF2CF, 0x6B86, 0xF7BF, 0x6B89, 0xE2E6, 0x6B8A, 0xE2A8, 0x6B96, 0xE3D6, 0x6B98, 0xEDD1, 0x6B9E, 0xE9F9, + 0x6BAE, 0xD6B1, 0x6BAF, 0xDEB2, 0x6BB2, 0xE0E8, 0x6BB5, 0xD3AB, 0x6BB7, 0xEBDC, 0x6BBA, 0xDFAF, 0x6BBC, 0xCAC3, 0x6BBF, 0xEEFC, + 0x6BC1, 0xFDC3, 0x6BC5, 0xEBF6, 0x6BC6, 0xCFB2, 0x6BCB, 0xD9EC, 0x6BCD, 0xD9BD, 0x6BCF, 0xD8DF, 0x6BD2, 0xD4B8, 0x6BD3, 0xEBBE, + 0x6BD4, 0xDDEF, 0x6BD6, 0xDDF0, 0x6BD7, 0xDDF1, 0x6BD8, 0xDDF2, 0x6BDB, 0xD9BE, 0x6BEB, 0xFBC6, 0x6BEC, 0xCFB3, 0x6C08, 0xEEFD, + 0x6C0F, 0xE4AB, 0x6C11, 0xDAC5, 0x6C13, 0xD8EC, 0x6C23, 0xD1A8, 0x6C34, 0xE2A9, 0x6C37, 0xDEBC, 0x6C38, 0xE7B5, 0x6C3E, 0xDBF0, + 0x6C40, 0xEFE2, 0x6C41, 0xF1F0, 0x6C42, 0xCFB4, 0x6C4E, 0xDBF1, 0x6C50, 0xE0B1, 0x6C55, 0xDFA5, 0x6C57, 0xF9D2, 0x6C5A, 0xE7FD, + 0x6C5D, 0xE6A3, 0x6C5E, 0xFBF1, 0x6C5F, 0xCBB0, 0x6C60, 0xF2AE, 0x6C68, 0xCDE7, 0x6C6A, 0xE8DC, 0x6C6D, 0xE7D7, 0x6C70, 0xF7C0, + 0x6C72, 0xD0E3, 0x6C76, 0xDAA1, 0x6C7A, 0xCCBD, 0x6C7D, 0xD1A9, 0x6C7E, 0xDDCC, 0x6C81, 0xE3FE, 0x6C82, 0xD1AA, 0x6C83, 0xE8AA, + 0x6C85, 0xEAB6, 0x6C86, 0xF9FA, 0x6C87, 0xE6CC, 0x6C88, 0xF6D8, 0x6C8C, 0xD4C7, 0x6C90, 0xD9CB, 0x6C92, 0xD9D2, 0x6C93, 0xD3CB, + 0x6C94, 0xD8F7, 0x6C95, 0xDAA9, 0x6C96, 0xF5F8, 0x6C99, 0xDEDE, 0x6C9A, 0xF2AF, 0x6C9B, 0xF8A9, 0x6CAB, 0xD8C8, 0x6CAE, 0xEEC1, + 0x6CB3, 0xF9C1, 0x6CB8, 0xDDF3, 0x6CB9, 0xEAFA, 0x6CBB, 0xF6BD, 0x6CBC, 0xE1BB, 0x6CBD, 0xCDBF, 0x6CBE, 0xF4D4, 0x6CBF, 0xE6CD, + 0x6CC1, 0xFCCF, 0x6CC2, 0xFBA2, 0x6CC4, 0xE0DC, 0x6CC9, 0xF4BB, 0x6CCA, 0xDAD5, 0x6CCC, 0xF9B2, 0x6CD3, 0xFBF2, 0x6CD5, 0xDBF6, + 0x6CD7, 0xDEDF, 0x6CDB, 0xDBF2, 0x6CE1, 0xF8DC, 0x6CE2, 0xF7EE, 0x6CE3, 0xEBE8, 0x6CE5, 0xD2FA, 0x6CE8, 0xF1BC, 0x6CEB, 0xFADA, + 0x6CEE, 0xDAEA, 0x6CEF, 0xDAC6, 0x6CF0, 0xF7C1, 0x6CF3, 0xE7B6, 0x6D0B, 0xE5C7, 0x6D0C, 0xD6AC, 0x6D11, 0xDCC7, 0x6D17, 0xE1A9, + 0x6D19, 0xE2AA, 0x6D1B, 0xD5A6, 0x6D1E, 0xD4D7, 0x6D25, 0xF2D0, 0x6D27, 0xEAFB, 0x6D29, 0xE0DD, 0x6D2A, 0xFBF3, 0x6D32, 0xF1BD, + 0x6D35, 0xE2E7, 0x6D36, 0xFDD7, 0x6D38, 0xCEC8, 0x6D39, 0xEAB7, 0x6D3B, 0xFCC0, 0x6D3D, 0xFDE7, 0x6D3E, 0xF7EF, 0x6D41, 0xD7B5, + 0x6D59, 0xEFBA, 0x6D5A, 0xF1DD, 0x6D5C, 0xDEB3, 0x6D63, 0xE8CB, 0x6D66, 0xF8DD, 0x6D69, 0xFBC7, 0x6D6A, 0xD5C8, 0x6D6C, 0xD7DF, + 0x6D6E, 0xDDA9, 0x6D74, 0xE9B1, 0x6D77, 0xFAAD, 0x6D78, 0xF6D9, 0x6D79, 0xFAF4, 0x6D7F, 0xF8AA, 0x6D85, 0xE6EE, 0x6D87, 0xCCDC, + 0x6D88, 0xE1BC, 0x6D89, 0xE0EF, 0x6D8C, 0xE9BF, 0x6D8D, 0xFCFD, 0x6D8E, 0xE6CE, 0x6D91, 0xE1D7, 0x6D93, 0xE6CF, 0x6D95, 0xF4F1, + 0x6DAF, 0xE4F3, 0x6DB2, 0xE4FB, 0x6DB5, 0xF9E4, 0x6DC0, 0xEFE3, 0x6DC3, 0xCFEE, 0x6DC4, 0xF6BE, 0x6DC5, 0xE0B2, 0x6DC6, 0xFCFE, + 0x6DC7, 0xD1AB, 0x6DCB, 0xD7FA, 0x6DCF, 0xFBC8, 0x6DD1, 0xE2D7, 0x6DD8, 0xD4A3, 0x6DD9, 0xF0F8, 0x6DDA, 0xD7A8, 0x6DDE, 0xE1E7, + 0x6DE1, 0xD3BF, 0x6DE8, 0xEFE4, 0x6DEA, 0xD7C5, 0x6DEB, 0xEBE2, 0x6DEE, 0xFCE7, 0x6DF1, 0xE4A2, 0x6DF3, 0xE2E8, 0x6DF5, 0xE6D0, + 0x6DF7, 0xFBE8, 0x6DF8, 0xF4E8, 0x6DF9, 0xE5F4, 0x6DFA, 0xF4BC, 0x6DFB, 0xF4D5, 0x6E17, 0xDFB6, 0x6E19, 0xFCB9, 0x6E1A, 0xEEC2, + 0x6E1B, 0xCAF5, 0x6E1F, 0xEFE5, 0x6E20, 0xCBE2, 0x6E21, 0xD4A4, 0x6E23, 0xDEE0, 0x6E24, 0xDAFD, 0x6E25, 0xE4C6, 0x6E26, 0xE8BE, + 0x6E2B, 0xE0DE, 0x6E2C, 0xF6B4, 0x6E2D, 0xEAD2, 0x6E2F, 0xF9FB, 0x6E32, 0xE0C2, 0x6E34, 0xCAE4, 0x6E36, 0xE7B7, 0x6E38, 0xEAFD, + 0x6E3A, 0xD9DD, 0x6E3C, 0xDAB4, 0x6E3D, 0xEEAA, 0x6E3E, 0xFBE9, 0x6E43, 0xDBCB, 0x6E44, 0xDAB5, 0x6E4A, 0xF1BE, 0x6E4D, 0xD3AC, + 0x6E56, 0xFBC9, 0x6E58, 0xDFCF, 0x6E5B, 0xD3C0, 0x6E5C, 0xE3D7, 0x6E5E, 0xEFE6, 0x6E5F, 0xFCD0, 0x6E67, 0xE9C0, 0x6E6B, 0xF5D3, + 0x6E6E, 0xECDC, 0x6E6F, 0xF7B7, 0x6E72, 0xEAB8, 0x6E73, 0xD1F9, 0x6E7A, 0xDCC8, 0x6E90, 0xEAB9, 0x6E96, 0xF1DE, 0x6E9C, 0xD7B6, + 0x6E9D, 0xCFB5, 0x6E9F, 0xD9A8, 0x6EA2, 0xECEE, 0x6EA5, 0xDDAA, 0x6EAA, 0xCDA2, 0x6EAB, 0xE8AE, 0x6EAF, 0xE1BD, 0x6EB1, 0xF2D1, + 0x6EB6, 0xE9C1, 0x6EBA, 0xD2FC, 0x6EC2, 0xDBB5, 0x6EC4, 0xF3E7, 0x6EC5, 0xD8FE, 0x6EC9, 0xFCD1, 0x6ECB, 0xEDB2, 0x6ECC, 0xF4AF, + 0x6ECE, 0xFBA3, 0x6ED1, 0xFCC1, 0x6ED3, 0xEEAB, 0x6ED4, 0xD4A5, 0x6EEF, 0xF4F2, 0x6EF4, 0xEED9, 0x6EF8, 0xFBCA, 0x6EFE, 0xCDE3, + 0x6EFF, 0xD8BB, 0x6F01, 0xE5DB, 0x6F02, 0xF8F7, 0x6F06, 0xF6D4, 0x6F0F, 0xD7A9, 0x6F11, 0xCBC9, 0x6F14, 0xE6D1, 0x6F15, 0xF0CC, + 0x6F20, 0xD8AE, 0x6F22, 0xF9D3, 0x6F23, 0xD5FE, 0x6F2B, 0xD8BC, 0x6F2C, 0xF2B0, 0x6F31, 0xE2AB, 0x6F32, 0xF3E8, 0x6F38, 0xEFC2, + 0x6F3F, 0xEDEC, 0x6F41, 0xE7B8, 0x6F51, 0xDAFE, 0x6F54, 0xCCBE, 0x6F57, 0xF2FC, 0x6F58, 0xDAEB, 0x6F5A, 0xE2D8, 0x6F5B, 0xEDD6, + 0x6F5E, 0xD6D1, 0x6F5F, 0xE0B3, 0x6F62, 0xFCD2, 0x6F64, 0xEBC8, 0x6F6D, 0xD3C1, 0x6F6E, 0xF0CD, 0x6F70, 0xCFF7, 0x6F7A, 0xEDD2, + 0x6F7C, 0xD4D8, 0x6F7D, 0xDCC9, 0x6F7E, 0xD7F1, 0x6F81, 0xDFBB, 0x6F84, 0xF3A5, 0x6F88, 0xF4CD, 0x6F8D, 0xF1BF, 0x6F8E, 0xF8B1, + 0x6F90, 0xE9FA, 0x6F94, 0xFBCB, 0x6F97, 0xCAD5, 0x6FA3, 0xF9D4, 0x6FA4, 0xF7CA, 0x6FA7, 0xD6C8, 0x6FAE, 0xFCE8, 0x6FAF, 0xF3BD, + 0x6FB1, 0xEEFE, 0x6FB3, 0xE7FE, 0x6FB9, 0xD3C2, 0x6FBE, 0xD3B6, 0x6FC0, 0xCCAD, 0x6FC1, 0xF6FA, 0x6FC2, 0xD6B2, 0x6FC3, 0xD2D8, + 0x6FCA, 0xE7D8, 0x6FD5, 0xE3A5, 0x6FDA, 0xE7B9, 0x6FDF, 0xF0AD, 0x6FE0, 0xFBCC, 0x6FE1, 0xEBA1, 0x6FE4, 0xD4A6, 0x6FE9, 0xFBCD, + 0x6FEB, 0xD5BD, 0x6FEC, 0xF1DF, 0x6FEF, 0xF6FB, 0x6FF1, 0xDEB4, 0x6FFE, 0xD5EB, 0x7001, 0xE5C8, 0x7005, 0xFBA4, 0x7006, 0xD4B9, + 0x7009, 0xDEE1, 0x700B, 0xE4A3, 0x700F, 0xD7B7, 0x7011, 0xF8EE, 0x7015, 0xDEB5, 0x7018, 0xD6D2, 0x701A, 0xF9D5, 0x701B, 0xE7BA, + 0x701C, 0xEBD5, 0x701D, 0xD5F7, 0x701E, 0xEFE7, 0x701F, 0xE1BE, 0x7023, 0xFAAE, 0x7027, 0xD6E9, 0x7028, 0xD6EE, 0x702F, 0xE7BB, + 0x7037, 0xECCB, 0x703E, 0xD5B3, 0x704C, 0xCEB4, 0x7050, 0xFBA5, 0x7051, 0xE1EE, 0x7058, 0xF7A8, 0x705D, 0xFBCE, 0x7063, 0xD8BD, + 0x706B, 0xFBFD, 0x7070, 0xFCE9, 0x7078, 0xCFB6, 0x707C, 0xEDC7, 0x707D, 0xEEAC, 0x7085, 0xCCDD, 0x708A, 0xF6A7, 0x708E, 0xE6FA, + 0x7092, 0xF5A4, 0x7098, 0xFDDC, 0x7099, 0xEDB3, 0x709A, 0xCEC9, 0x70A1, 0xEFE8, 0x70A4, 0xE1BF, 0x70AB, 0xFADB, 0x70AC, 0xCBE3, + 0x70AD, 0xF7A9, 0x70AF, 0xFBA6, 0x70B3, 0xDCB9, 0x70B7, 0xF1C0, 0x70B8, 0xEDC8, 0x70B9, 0xEFC3, 0x70C8, 0xD6AD, 0x70CB, 0xFDCE, + 0x70CF, 0xE8A1, 0x70D8, 0xFBF4, 0x70D9, 0xD5A7, 0x70DD, 0xF1F6, 0x70DF, 0xE6D3, 0x70F1, 0xCCDE, 0x70F9, 0xF8B2, 0x70FD, 0xDCEB, + 0x7104, 0xFDB6, 0x7109, 0xE5EA, 0x710C, 0xF1E0, 0x7119, 0xDBCC, 0x711A, 0xDDCD, 0x711E, 0xD4C8, 0x7121, 0xD9ED, 0x7126, 0xF5A5, + 0x7130, 0xE6FB, 0x7136, 0xE6D4, 0x7147, 0xFDC8, 0x7149, 0xD6A1, 0x714A, 0xFDBF, 0x714C, 0xFCD3, 0x714E, 0xEFA1, 0x7150, 0xE7BC, + 0x7156, 0xD1EE, 0x7159, 0xE6D5, 0x715C, 0xE9F2, 0x715E, 0xDFB0, 0x7164, 0xD8E0, 0x7165, 0xFCBA, 0x7166, 0xFDAF, 0x7167, 0xF0CE, + 0x7169, 0xDBE1, 0x716C, 0xE5C9, 0x716E, 0xEDB4, 0x717D, 0xE0C3, 0x7184, 0xE3D8, 0x7189, 0xE9FB, 0x718A, 0xEAA8, 0x718F, 0xFDB7, + 0x7192, 0xFBA7, 0x7194, 0xE9C2, 0x7199, 0xFDF7, 0x719F, 0xE2D9, 0x71A2, 0xDCEC, 0x71AC, 0xE8A2, 0x71B1, 0xE6F0, 0x71B9, 0xFDF8, + 0x71BA, 0xFDF9, 0x71BE, 0xF6BF, 0x71C1, 0xE7A7, 0x71C3, 0xE6D7, 0x71C8, 0xD4F3, 0x71C9, 0xD4C9, 0x71CE, 0xD6FA, 0x71D0, 0xD7F2, + 0x71D2, 0xE1C0, 0x71D4, 0xDBE2, 0x71D5, 0xE6D8, 0x71DF, 0xE7BD, 0x71E5, 0xF0CF, 0x71E6, 0xF3BE, 0x71E7, 0xE2AC, 0x71ED, 0xF5B7, + 0x71EE, 0xE0F0, 0x71FB, 0xFDB8, 0x71FC, 0xE3E8, 0x71FE, 0xD4A7, 0x71FF, 0xE8FC, 0x7200, 0xFAD2, 0x7206, 0xF8EF, 0x7210, 0xD6D3, + 0x721B, 0xD5B4, 0x722A, 0xF0D0, 0x722C, 0xF7F0, 0x722D, 0xEEB3, 0x7230, 0xEABA, 0x7232, 0xEAD3, 0x7235, 0xEDC9, 0x7236, 0xDDAB, + 0x723A, 0xE5AC, 0x723B, 0xFDA1, 0x723D, 0xDFD0, 0x723E, 0xECB3, 0x7240, 0xDFD1, 0x7246, 0xEDED, 0x7247, 0xF8B8, 0x7248, 0xF7FA, + 0x724C, 0xF8AB, 0x7252, 0xF4E0, 0x7258, 0xD4BA, 0x7259, 0xE4B3, 0x725B, 0xE9DA, 0x725D, 0xDEB6, 0x725F, 0xD9BF, 0x7261, 0xD9C0, + 0x7262, 0xD6EF, 0x7267, 0xD9CC, 0x7269, 0xDAAA, 0x7272, 0xDFE5, 0x7279, 0xF7E5, 0x727D, 0xCCB2, 0x7280, 0xDFF9, 0x7281, 0xD7E0, + 0x72A2, 0xD4BB, 0x72A7, 0xFDFA, 0x72AC, 0xCCB3, 0x72AF, 0xDBF3, 0x72C0, 0xDFD2, 0x72C2, 0xCECA, 0x72C4, 0xEEDA, 0x72CE, 0xE4E4, + 0x72D0, 0xFBCF, 0x72D7, 0xCFB7, 0x72D9, 0xEEC3, 0x72E1, 0xCEEA, 0x72E9, 0xE2AD, 0x72F8, 0xD7E1, 0x72F9, 0xFAF5, 0x72FC, 0xD5C9, + 0x72FD, 0xF8AC, 0x730A, 0xE7D9, 0x7316, 0xF3E9, 0x731B, 0xD8ED, 0x731C, 0xE3C4, 0x731D, 0xF0F1, 0x7325, 0xE8E5, 0x7329, 0xE0FA, + 0x732A, 0xEEC4, 0x732B, 0xD9DE, 0x7336, 0xEBA2, 0x7337, 0xEBA3, 0x733E, 0xFCC2, 0x733F, 0xEABB, 0x7344, 0xE8AB, 0x7345, 0xDEE2, + 0x7350, 0xEDEF, 0x7352, 0xE8A3, 0x7357, 0xCFF1, 0x7368, 0xD4BC, 0x736A, 0xFCEA, 0x7370, 0xE7BE, 0x7372, 0xFCF2, 0x7375, 0xD6B4, + 0x7378, 0xE2AE, 0x737A, 0xD3B7, 0x737B, 0xFACC, 0x7384, 0xFADC, 0x7386, 0xEDB5, 0x7387, 0xE1E3, 0x7389, 0xE8AC, 0x738B, 0xE8DD, + 0x738E, 0xEFE9, 0x7394, 0xF4BD, 0x7396, 0xCFB8, 0x7397, 0xE9DB, 0x7398, 0xD1AC, 0x739F, 0xDAC7, 0x73A7, 0xEBC9, 0x73A9, 0xE8CC, + 0x73AD, 0xDEB7, 0x73B2, 0xD6BC, 0x73B3, 0xD3E5, 0x73B9, 0xFADD, 0x73C0, 0xDAD6, 0x73C2, 0xCAB1, 0x73C9, 0xDAC8, 0x73CA, 0xDFA6, + 0x73CC, 0xF9B3, 0x73CD, 0xF2D2, 0x73CF, 0xCAC4, 0x73D6, 0xCECB, 0x73D9, 0xCDF5, 0x73DD, 0xFDB0, 0x73DE, 0xD5A8, 0x73E0, 0xF1C1, + 0x73E3, 0xE2E9, 0x73E4, 0xDCCA, 0x73E5, 0xECB4, 0x73E6, 0xFAC0, 0x73E9, 0xFBA8, 0x73EA, 0xD0A8, 0x73ED, 0xDAEC, 0x73F7, 0xD9EE, + 0x73F9, 0xE0FB, 0x73FD, 0xEFEA, 0x73FE, 0xFADE, 0x7401, 0xE0C4, 0x7403, 0xCFB9, 0x7405, 0xD5CA, 0x7406, 0xD7E2, 0x7407, 0xE2AF, + 0x7409, 0xD7B8, 0x7413, 0xE8CD, 0x741B, 0xF6DA, 0x7420, 0xEFA2, 0x7421, 0xE2DA, 0x7422, 0xF6FC, 0x7425, 0xFBD0, 0x7426, 0xD1AD, + 0x7428, 0xCDE4, 0x742A, 0xD1AE, 0x742B, 0xDCED, 0x742C, 0xE8CE, 0x742E, 0xF0F9, 0x742F, 0xCEB5, 0x7430, 0xE6FC, 0x7433, 0xD7FB, + 0x7434, 0xD0D6, 0x7435, 0xDDF5, 0x7436, 0xF7F1, 0x7438, 0xF6FD, 0x743A, 0xDBF7, 0x743F, 0xFBEA, 0x7440, 0xE9DC, 0x7441, 0xD9C1, + 0x7443, 0xF5F2, 0x7444, 0xE0C5, 0x744B, 0xEAD4, 0x7455, 0xF9C2, 0x7457, 0xEABC, 0x7459, 0xD2C5, 0x745A, 0xFBD1, 0x745B, 0xE7C0, + 0x745C, 0xEBA5, 0x745E, 0xDFFA, 0x745F, 0xE3A2, 0x7460, 0xD7B9, 0x7462, 0xE9C3, 0x7464, 0xE8FD, 0x7465, 0xE8AF, 0x7468, 0xF2D3, + 0x7469, 0xFBA9, 0x746A, 0xD8A5, 0x746F, 0xD5CB, 0x747E, 0xD0C8, 0x7482, 0xD1AF, 0x7483, 0xD7E3, 0x7487, 0xE0C6, 0x7489, 0xD6A2, + 0x748B, 0xEDF0, 0x7498, 0xD7F3, 0x749C, 0xFCD4, 0x749E, 0xDAD7, 0x749F, 0xCCDF, 0x74A1, 0xF2D4, 0x74A3, 0xD1B0, 0x74A5, 0xCCE0, + 0x74A7, 0xDBFD, 0x74A8, 0xF3BF, 0x74AA, 0xF0D1, 0x74B0, 0xFCBB, 0x74B2, 0xE2B0, 0x74B5, 0xE6A5, 0x74B9, 0xE2DB, 0x74BD, 0xDFDE, + 0x74BF, 0xE0C7, 0x74C6, 0xF2EF, 0x74CA, 0xCCE1, 0x74CF, 0xD6EA, 0x74D4, 0xE7C2, 0x74D8, 0xCEB6, 0x74DA, 0xF3C0, 0x74DC, 0xCDFE, + 0x74E0, 0xFBD2, 0x74E2, 0xF8F8, 0x74E3, 0xF7FB, 0x74E6, 0xE8BF, 0x74EE, 0xE8B7, 0x74F7, 0xEDB6, 0x7501, 0xDCBA, 0x7504, 0xCCB4, + 0x7511, 0xF1F7, 0x7515, 0xE8B8, 0x7518, 0xCAF6, 0x751A, 0xE4A4, 0x751B, 0xF4D6, 0x751F, 0xDFE6, 0x7523, 0xDFA7, 0x7525, 0xDFE7, + 0x7526, 0xE1C1, 0x7528, 0xE9C4, 0x752B, 0xDCCB, 0x752C, 0xE9C5, 0x7530, 0xEFA3, 0x7531, 0xEBA6, 0x7532, 0xCBA3, 0x7533, 0xE3E9, + 0x7537, 0xD1FB, 0x7538, 0xEFA4, 0x753A, 0xEFEB, 0x7547, 0xD0B4, 0x754C, 0xCDA3, 0x754F, 0xE8E6, 0x7551, 0xEFA5, 0x7553, 0xD3CC, + 0x7554, 0xDAED, 0x7559, 0xD7BA, 0x755B, 0xF2D5, 0x755C, 0xF5E5, 0x755D, 0xD9EF, 0x7562, 0xF9B4, 0x7565, 0xD5D4, 0x7566, 0xFDCF, + 0x756A, 0xDBE3, 0x756F, 0xF1E1, 0x7570, 0xECB6, 0x7575, 0xFBFE, 0x7576, 0xD3D7, 0x7578, 0xD1B1, 0x757A, 0xCBB1, 0x757F, 0xD1B2, + 0x7586, 0xCBB2, 0x7587, 0xF1C2, 0x758A, 0xF4E1, 0x758B, 0xF9B5, 0x758E, 0xE1C3, 0x758F, 0xE1C2, 0x7591, 0xEBF7, 0x759D, 0xDFA8, + 0x75A5, 0xCBCA, 0x75AB, 0xE6B9, 0x75B1, 0xF8DE, 0x75B2, 0xF9AA, 0x75B3, 0xCAF7, 0x75B5, 0xEDB7, 0x75B8, 0xD3B8, 0x75B9, 0xF2D6, + 0x75BC, 0xD4D9, 0x75BD, 0xEEC5, 0x75BE, 0xF2F0, 0x75C2, 0xCAB2, 0x75C5, 0xDCBB, 0x75C7, 0xF1F8, 0x75CD, 0xECB7, 0x75D2, 0xE5CA, + 0x75D4, 0xF6C0, 0x75D5, 0xFDDD, 0x75D8, 0xD4E3, 0x75D9, 0xCCE2, 0x75DB, 0xF7D4, 0x75E2, 0xD7E5, 0x75F0, 0xD3C3, 0x75F2, 0xD8A6, + 0x75F4, 0xF6C1, 0x75FA, 0xDDF6, 0x75FC, 0xCDC0, 0x7600, 0xE5DC, 0x760D, 0xE5CB, 0x7619, 0xE1C4, 0x761F, 0xE8B0, 0x7620, 0xF4B0, + 0x7621, 0xF3EA, 0x7622, 0xDAEE, 0x7624, 0xD7BB, 0x7626, 0xE2B1, 0x763B, 0xD7AA, 0x7642, 0xD6FB, 0x764C, 0xE4DF, 0x764E, 0xCAD6, + 0x7652, 0xEBA8, 0x7656, 0xDBFE, 0x7661, 0xF6C2, 0x7664, 0xEFBB, 0x7669, 0xD4FD, 0x766C, 0xE0C8, 0x7670, 0xE8B9, 0x7672, 0xEFA6, + 0x7678, 0xCDA4, 0x767B, 0xD4F4, 0x767C, 0xDBA1, 0x767D, 0xDBDC, 0x767E, 0xDBDD, 0x7684, 0xEEDC, 0x7686, 0xCBCB, 0x7687, 0xFCD5, + 0x768E, 0xCEEB, 0x7690, 0xCDC1, 0x7693, 0xFBD3, 0x76AE, 0xF9AB, 0x76BA, 0xF5D4, 0x76BF, 0xD9A9, 0x76C2, 0xE9DD, 0x76C3, 0xDBCD, + 0x76C6, 0xDDCE, 0x76C8, 0xE7C3, 0x76CA, 0xECCC, 0x76D2, 0xF9EC, 0x76D6, 0xCBCC, 0x76DB, 0xE0FC, 0x76DC, 0xD4A8, 0x76DE, 0xEDD3, + 0x76DF, 0xD8EF, 0x76E1, 0xF2D7, 0x76E3, 0xCAF8, 0x76E4, 0xDAEF, 0x76E7, 0xD6D4, 0x76EE, 0xD9CD, 0x76F2, 0xD8EE, 0x76F4, 0xF2C1, + 0x76F8, 0xDFD3, 0x76FC, 0xDAF0, 0x76FE, 0xE2EA, 0x7701, 0xE0FD, 0x7704, 0xD8F8, 0x7708, 0xF7AF, 0x7709, 0xDAB6, 0x770B, 0xCAD7, + 0x771E, 0xF2D8, 0x7720, 0xD8F9, 0x7729, 0xFADF, 0x7737, 0xCFEF, 0x7738, 0xD9C2, 0x773A, 0xF0D2, 0x773C, 0xE4D1, 0x7740, 0xF3B7, + 0x774D, 0xFAE0, 0x775B, 0xEFEC, 0x7761, 0xE2B2, 0x7763, 0xD4BD, 0x7766, 0xD9CE, 0x776B, 0xF4E2, 0x7779, 0xD4A9, 0x777E, 0xCDC2, + 0x777F, 0xE7DA, 0x778B, 0xF2D9, 0x7791, 0xD9AA, 0x779E, 0xD8BE, 0x77A5, 0xDCAD, 0x77AC, 0xE2EB, 0x77AD, 0xD6FC, 0x77B0, 0xCAF9, + 0x77B3, 0xD4DA, 0x77BB, 0xF4D7, 0x77BC, 0xCCA1, 0x77BF, 0xCFBA, 0x77D7, 0xF5B8, 0x77DB, 0xD9C3, 0x77DC, 0xD0E8, 0x77E2, 0xE3C5, + 0x77E3, 0xEBF8, 0x77E5, 0xF2B1, 0x77E9, 0xCFBB, 0x77ED, 0xD3AD, 0x77EE, 0xE8E1, 0x77EF, 0xCEEC, 0x77F3, 0xE0B4, 0x7802, 0xDEE3, + 0x7812, 0xDDF7, 0x7825, 0xF2B2, 0x7826, 0xF3F6, 0x7827, 0xF6DB, 0x782C, 0xD7FE, 0x7832, 0xF8DF, 0x7834, 0xF7F2, 0x7845, 0xD0A9, + 0x784F, 0xE6DA, 0x785D, 0xF5A6, 0x786B, 0xD7BC, 0x786C, 0xCCE3, 0x786F, 0xE6DB, 0x787C, 0xDDDD, 0x7881, 0xD1B3, 0x7887, 0xEFED, + 0x788C, 0xD6DE, 0x788D, 0xE4F4, 0x788E, 0xE1EF, 0x7891, 0xDDF8, 0x7897, 0xE8CF, 0x78A3, 0xCAE5, 0x78A7, 0xDCA1, 0x78A9, 0xE0B5, + 0x78BA, 0xFCAC, 0x78BB, 0xFCAD, 0x78BC, 0xD8A7, 0x78C1, 0xEDB8, 0x78C5, 0xDBB6, 0x78CA, 0xD6F0, 0x78CB, 0xF3AF, 0x78CE, 0xCDA5, + 0x78D0, 0xDAF1, 0x78E8, 0xD8A8, 0x78EC, 0xCCE4, 0x78EF, 0xD1B4, 0x78F5, 0xCAD8, 0x78FB, 0xDAF2, 0x7901, 0xF5A7, 0x790E, 0xF5A8, + 0x7916, 0xE6A6, 0x792A, 0xD5EC, 0x792B, 0xD5F8, 0x792C, 0xDAF3, 0x793A, 0xE3C6, 0x793E, 0xDEE4, 0x7940, 0xDEE5, 0x7941, 0xD1B5, + 0x7947, 0xD1B6, 0x7948, 0xD1B7, 0x7949, 0xF2B3, 0x7950, 0xE9DE, 0x7956, 0xF0D3, 0x7957, 0xF2B4, 0x795A, 0xF0D4, 0x795B, 0xCBE4, + 0x795C, 0xFBD4, 0x795D, 0xF5E6, 0x795E, 0xE3EA, 0x7960, 0xDEE6, 0x7965, 0xDFD4, 0x7968, 0xF8F9, 0x796D, 0xF0AE, 0x797A, 0xD1B8, + 0x797F, 0xD6DF, 0x7981, 0xD0D7, 0x798D, 0xFCA1, 0x798E, 0xEFEE, 0x798F, 0xDCD8, 0x7991, 0xE9DF, 0x79A6, 0xE5DD, 0x79A7, 0xFDFB, + 0x79AA, 0xE0C9, 0x79AE, 0xD6C9, 0x79B1, 0xD4AA, 0x79B3, 0xE5CC, 0x79B9, 0xE9E0, 0x79BD, 0xD0D8, 0x79BE, 0xFCA2, 0x79BF, 0xD4BE, + 0x79C0, 0xE2B3, 0x79C1, 0xDEE7, 0x79C9, 0xDCBC, 0x79CA, 0xD2B6, 0x79CB, 0xF5D5, 0x79D1, 0xCEA1, 0x79D2, 0xF5A9, 0x79D5, 0xDDF9, + 0x79D8, 0xDDFA, 0x79DF, 0xF0D5, 0x79E4, 0xF6DF, 0x79E6, 0xF2DA, 0x79E7, 0xE4EB, 0x79E9, 0xF2F1, 0x79FB, 0xECB9, 0x7A00, 0xFDFC, + 0x7A05, 0xE1AA, 0x7A08, 0xCAD9, 0x7A0B, 0xEFEF, 0x7A0D, 0xF5AA, 0x7A14, 0xECF9, 0x7A17, 0xF8AD, 0x7A19, 0xF2C2, 0x7A1A, 0xF6C3, + 0x7A1C, 0xD7D2, 0x7A1F, 0xF9A2, 0x7A20, 0xF0D6, 0x7A2E, 0xF0FA, 0x7A31, 0xF6E0, 0x7A36, 0xE9F3, 0x7A37, 0xF2C3, 0x7A3B, 0xD4AB, + 0x7A3C, 0xCAB3, 0x7A3D, 0xCDA6, 0x7A3F, 0xCDC3, 0x7A40, 0xCDDA, 0x7A46, 0xD9CF, 0x7A49, 0xF6C4, 0x7A4D, 0xEEDD, 0x7A4E, 0xE7C4, + 0x7A57, 0xE2B4, 0x7A61, 0xDFE2, 0x7A62, 0xE7DB, 0x7A69, 0xE8B1, 0x7A6B, 0xFCAE, 0x7A70, 0xE5CD, 0x7A74, 0xFAEB, 0x7A76, 0xCFBC, + 0x7A79, 0xCFE2, 0x7A7A, 0xCDF6, 0x7A7D, 0xEFF0, 0x7A7F, 0xF4BE, 0x7A81, 0xD4CD, 0x7A84, 0xF3B8, 0x7A88, 0xE9A1, 0x7A92, 0xF2F2, + 0x7A93, 0xF3EB, 0x7A95, 0xF0D7, 0x7A98, 0xCFD7, 0x7A9F, 0xCFDF, 0x7AA9, 0xE8C0, 0x7AAA, 0xE8C1, 0x7AAE, 0xCFE3, 0x7AAF, 0xE9A2, + 0x7ABA, 0xD0AA, 0x7AC4, 0xF3C1, 0x7AC5, 0xD0AB, 0x7AC7, 0xD4E4, 0x7ACA, 0xEFBC, 0x7ACB, 0xD8A1, 0x7AD7, 0xD9DF, 0x7AD9, 0xF3D7, + 0x7ADD, 0xDCBD, 0x7ADF, 0xCCE5, 0x7AE0, 0xEDF1, 0x7AE3, 0xF1E2, 0x7AE5, 0xD4DB, 0x7AEA, 0xE2B5, 0x7AED, 0xCAE6, 0x7AEF, 0xD3AE, + 0x7AF6, 0xCCE6, 0x7AF9, 0xF1D3, 0x7AFA, 0xF5E7, 0x7AFF, 0xCADA, 0x7B0F, 0xFBEE, 0x7B11, 0xE1C5, 0x7B19, 0xDFE9, 0x7B1B, 0xEEDE, + 0x7B1E, 0xF7C2, 0x7B20, 0xD8A2, 0x7B26, 0xDDAC, 0x7B2C, 0xF0AF, 0x7B2D, 0xD6BD, 0x7B39, 0xE1AB, 0x7B46, 0xF9B6, 0x7B49, 0xD4F5, + 0x7B4B, 0xD0C9, 0x7B4C, 0xEFA7, 0x7B4D, 0xE2EC, 0x7B4F, 0xDBEA, 0x7B50, 0xCECC, 0x7B51, 0xF5E8, 0x7B52, 0xF7D5, 0x7B54, 0xD3CD, + 0x7B56, 0xF3FE, 0x7B60, 0xD0B5, 0x7B6C, 0xE0FE, 0x7B6E, 0xDFFB, 0x7B75, 0xE6DD, 0x7B7D, 0xE8A4, 0x7B87, 0xCBCD, 0x7B8B, 0xEFA8, + 0x7B8F, 0xEEB4, 0x7B94, 0xDAD8, 0x7B95, 0xD1B9, 0x7B97, 0xDFA9, 0x7B9A, 0xF3B0, 0x7B9D, 0xCCC4, 0x7BA1, 0xCEB7, 0x7BAD, 0xEFA9, + 0x7BB1, 0xDFD5, 0x7BB4, 0xEDD7, 0x7BB8, 0xEEC6, 0x7BC0, 0xEFBD, 0x7BC1, 0xFCD6, 0x7BC4, 0xDBF4, 0x7BC6, 0xEFAA, 0x7BC7, 0xF8B9, + 0x7BC9, 0xF5E9, 0x7BD2, 0xE3D9, 0x7BE0, 0xE1C6, 0x7BE4, 0xD4BF, 0x7BE9, 0xDEE8, 0x7C07, 0xF0EA, 0x7C12, 0xF3C2, 0x7C1E, 0xD3AF, + 0x7C21, 0xCADB, 0x7C27, 0xFCD7, 0x7C2A, 0xEDD8, 0x7C2B, 0xE1C7, 0x7C3D, 0xF4D8, 0x7C3E, 0xD6B3, 0x7C3F, 0xDDAD, 0x7C43, 0xD5BE, + 0x7C4C, 0xF1C3, 0x7C4D, 0xEEDF, 0x7C60, 0xD6EB, 0x7C64, 0xF4D9, 0x7C6C, 0xD7E6, 0x7C73, 0xDAB7, 0x7C83, 0xDDFB, 0x7C89, 0xDDCF, + 0x7C92, 0xD8A3, 0x7C95, 0xDAD9, 0x7C97, 0xF0D8, 0x7C98, 0xEFC4, 0x7C9F, 0xE1D8, 0x7CA5, 0xF1D4, 0x7CA7, 0xEDF2, 0x7CAE, 0xD5DB, + 0x7CB1, 0xD5DC, 0x7CB2, 0xF3C4, 0x7CB3, 0xCBD7, 0x7CB9, 0xE2B6, 0x7CBE, 0xEFF1, 0x7CCA, 0xFBD5, 0x7CD6, 0xD3D8, 0x7CDE, 0xDDD0, + 0x7CDF, 0xF0D9, 0x7CE0, 0xCBB3, 0x7CE7, 0xD5DD, 0x7CFB, 0xCDA7, 0x7CFE, 0xD0AC, 0x7D00, 0xD1BA, 0x7D02, 0xF1C4, 0x7D04, 0xE5B3, + 0x7D05, 0xFBF5, 0x7D06, 0xE9E1, 0x7D07, 0xFDE0, 0x7D08, 0xFCBC, 0x7D0A, 0xDAA2, 0x7D0B, 0xDAA3, 0x7D0D, 0xD2A1, 0x7D10, 0xD2EF, + 0x7D14, 0xE2ED, 0x7D17, 0xDEE9, 0x7D18, 0xCEDC, 0x7D19, 0xF2B5, 0x7D1A, 0xD0E4, 0x7D1B, 0xDDD1, 0x7D20, 0xE1C8, 0x7D21, 0xDBB7, + 0x7D22, 0xDFE3, 0x7D2B, 0xEDB9, 0x7D2C, 0xF1C5, 0x7D2E, 0xF3CF, 0x7D2F, 0xD7AB, 0x7D30, 0xE1AC, 0x7D33, 0xE3EB, 0x7D35, 0xEEC7, + 0x7D39, 0xE1C9, 0x7D3A, 0xCAFA, 0x7D42, 0xF0FB, 0x7D43, 0xFAE1, 0x7D44, 0xF0DA, 0x7D45, 0xCCE7, 0x7D46, 0xDAF4, 0x7D50, 0xCCBF, + 0x7D5E, 0xCEED, 0x7D61, 0xD5A9, 0x7D62, 0xFAE2, 0x7D66, 0xD0E5, 0x7D68, 0xEBD6, 0x7D6A, 0xECDF, 0x7D6E, 0xDFFC, 0x7D71, 0xF7D6, + 0x7D72, 0xDEEA, 0x7D73, 0xCBB4, 0x7D76, 0xEFBE, 0x7D79, 0xCCB5, 0x7D7F, 0xCFBD, 0x7D8E, 0xEFF2, 0x7D8F, 0xE2B7, 0x7D93, 0xCCE8, + 0x7D9C, 0xF0FC, 0x7DA0, 0xD6E0, 0x7DA2, 0xF1C6, 0x7DAC, 0xE2B8, 0x7DAD, 0xEBAB, 0x7DB1, 0xCBB5, 0x7DB2, 0xD8D1, 0x7DB4, 0xF4CE, + 0x7DB5, 0xF3F7, 0x7DB8, 0xD7C6, 0x7DBA, 0xD1BB, 0x7DBB, 0xF7AA, 0x7DBD, 0xEDCA, 0x7DBE, 0xD7D3, 0x7DBF, 0xD8FA, 0x7DC7, 0xF6C5, + 0x7DCA, 0xD1CC, 0x7DCB, 0xDDFC, 0x7DD6, 0xDFFD, 0x7DD8, 0xF9E5, 0x7DDA, 0xE0CA, 0x7DDD, 0xF2FD, 0x7DDE, 0xD3B0, 0x7DE0, 0xF4F3, + 0x7DE1, 0xDAC9, 0x7DE3, 0xE6DE, 0x7DE8, 0xF8BA, 0x7DE9, 0xE8D0, 0x7DEC, 0xD8FB, 0x7DEF, 0xEAD5, 0x7DF4, 0xD6A3, 0x7DFB, 0xF6C6, + 0x7E09, 0xF2DB, 0x7E0A, 0xE4FC, 0x7E15, 0xE8B2, 0x7E1B, 0xDADA, 0x7E1D, 0xF2DC, 0x7E1E, 0xFBD6, 0x7E1F, 0xE9B2, 0x7E21, 0xEEAD, + 0x7E23, 0xFAE3, 0x7E2B, 0xDCEE, 0x7E2E, 0xF5EA, 0x7E2F, 0xE6E0, 0x7E31, 0xF0FD, 0x7E37, 0xD7AC, 0x7E3D, 0xF5C5, 0x7E3E, 0xEEE0, + 0x7E41, 0xDBE5, 0x7E43, 0xDDDE, 0x7E46, 0xD9F0, 0x7E47, 0xE9A3, 0x7E52, 0xF1F9, 0x7E54, 0xF2C4, 0x7E55, 0xE0CB, 0x7E5E, 0xE9A4, + 0x7E61, 0xE2B9, 0x7E69, 0xE3B1, 0x7E6A, 0xFCEB, 0x7E6B, 0xCDA8, 0x7E6D, 0xCCB6, 0x7E70, 0xF0DB, 0x7E79, 0xE6BA, 0x7E7C, 0xCDA9, + 0x7E82, 0xF3C3, 0x7E8C, 0xE1D9, 0x7E8F, 0xEFAB, 0x7E93, 0xE7C5, 0x7E96, 0xE0E9, 0x7E98, 0xF3C5, 0x7E9B, 0xD4C0, 0x7E9C, 0xD5BF, + 0x7F36, 0xDDAE, 0x7F38, 0xF9FC, 0x7F3A, 0xCCC0, 0x7F4C, 0xE5A2, 0x7F50, 0xCEB8, 0x7F54, 0xD8D2, 0x7F55, 0xF9D6, 0x7F6A, 0xF1AA, + 0x7F6B, 0xCED1, 0x7F6E, 0xF6C7, 0x7F70, 0xDBEB, 0x7F72, 0xDFFE, 0x7F75, 0xD8E1, 0x7F77, 0xF7F3, 0x7F79, 0xD7E7, 0x7F85, 0xD4FE, + 0x7F88, 0xD1BC, 0x7F8A, 0xE5CF, 0x7F8C, 0xCBB6, 0x7F8E, 0xDAB8, 0x7F94, 0xCDC4, 0x7F9A, 0xD6BE, 0x7F9E, 0xE2BA, 0x7FA4, 0xCFD8, + 0x7FA8, 0xE0CC, 0x7FA9, 0xEBF9, 0x7FB2, 0xFDFD, 0x7FB8, 0xD7E8, 0x7FB9, 0xCBD8, 0x7FBD, 0xE9E2, 0x7FC1, 0xE8BA, 0x7FC5, 0xE3C7, + 0x7FCA, 0xECCD, 0x7FCC, 0xECCE, 0x7FCE, 0xD6BF, 0x7FD2, 0xE3A7, 0x7FD4, 0xDFD6, 0x7FD5, 0xFDE8, 0x7FDF, 0xEEE1, 0x7FE0, 0xF6A8, + 0x7FE1, 0xDDFD, 0x7FE9, 0xF8BB, 0x7FEB, 0xE8D1, 0x7FF0, 0xF9D7, 0x7FF9, 0xCEEE, 0x7FFC, 0xECCF, 0x8000, 0xE9A5, 0x8001, 0xD6D5, + 0x8003, 0xCDC5, 0x8005, 0xEDBA, 0x8006, 0xD1BD, 0x8009, 0xCFBE, 0x800C, 0xECBB, 0x8010, 0xD2B1, 0x8015, 0xCCE9, 0x8017, 0xD9C4, + 0x8018, 0xE9FC, 0x802D, 0xD1BE, 0x8033, 0xECBC, 0x8036, 0xE5AD, 0x803D, 0xF7B0, 0x803F, 0xCCEA, 0x8043, 0xD3C4, 0x8046, 0xD6C0, + 0x804A, 0xD6FD, 0x8056, 0xE1A1, 0x8058, 0xDEBD, 0x805A, 0xF6A9, 0x805E, 0xDAA4, 0x806F, 0xD6A4, 0x8070, 0xF5C6, 0x8072, 0xE1A2, + 0x8073, 0xE9C6, 0x8077, 0xF2C5, 0x807D, 0xF4E9, 0x807E, 0xD6EC, 0x807F, 0xEBD3, 0x8084, 0xECBD, 0x8085, 0xE2DC, 0x8086, 0xDEEB, + 0x8087, 0xF0DC, 0x8089, 0xEBBF, 0x808B, 0xD7CE, 0x808C, 0xD1BF, 0x8096, 0xF5AB, 0x809B, 0xF9FD, 0x809D, 0xCADC, 0x80A1, 0xCDC6, + 0x80A2, 0xF2B6, 0x80A5, 0xDDFE, 0x80A9, 0xCCB7, 0x80AA, 0xDBB8, 0x80AF, 0xD0E9, 0x80B1, 0xCEDD, 0x80B2, 0xEBC0, 0x80B4, 0xFDA2, + 0x80BA, 0xF8CB, 0x80C3, 0xEAD6, 0x80C4, 0xF1B0, 0x80CC, 0xDBCE, 0x80CE, 0xF7C3, 0x80DA, 0xDBCF, 0x80DB, 0xCBA4, 0x80DE, 0xF8E0, + 0x80E1, 0xFBD7, 0x80E4, 0xEBCA, 0x80E5, 0xE0A1, 0x80F1, 0xCECD, 0x80F4, 0xD4DC, 0x80F8, 0xFDD8, 0x80FD, 0xD2F6, 0x8102, 0xF2B7, + 0x8105, 0xFAF6, 0x8106, 0xF6AA, 0x8107, 0xFAF7, 0x8108, 0xD8E6, 0x810A, 0xF4B1, 0x8118, 0xE8D2, 0x811A, 0xCAC5, 0x811B, 0xCCEB, + 0x8123, 0xE2EE, 0x8129, 0xE2BB, 0x812B, 0xF7AD, 0x812F, 0xF8E1, 0x8139, 0xF3EC, 0x813E, 0xDEA1, 0x814B, 0xE4FD, 0x814E, 0xE3EC, + 0x8150, 0xDDAF, 0x8151, 0xDDB0, 0x8154, 0xCBB7, 0x8155, 0xE8D3, 0x8165, 0xE1A3, 0x8166, 0xD2E0, 0x816B, 0xF0FE, 0x8170, 0xE9A6, + 0x8171, 0xCBF2, 0x8178, 0xEDF3, 0x8179, 0xDCD9, 0x817A, 0xE0CD, 0x817F, 0xF7DA, 0x8180, 0xDBB9, 0x8188, 0xCCAE, 0x818A, 0xDADB, + 0x818F, 0xCDC7, 0x819A, 0xDDB1, 0x819C, 0xD8AF, 0x819D, 0xE3A3, 0x81A0, 0xCEEF, 0x81A3, 0xF2F3, 0x81A8, 0xF8B3, 0x81B3, 0xE0CE, + 0x81B5, 0xF5FD, 0x81BA, 0xEBEC, 0x81BD, 0xD3C5, 0x81BE, 0xFCEC, 0x81BF, 0xD2DB, 0x81C0, 0xD4EB, 0x81C2, 0xDEA2, 0x81C6, 0xE5E6, + 0x81CD, 0xF0B0, 0x81D8, 0xD5C4, 0x81DF, 0xEDF4, 0x81E3, 0xE3ED, 0x81E5, 0xE8C2, 0x81E7, 0xEDF5, 0x81E8, 0xD7FC, 0x81EA, 0xEDBB, + 0x81ED, 0xF6AB, 0x81F3, 0xF2B8, 0x81F4, 0xF6C8, 0x81FA, 0xD3E6, 0x81FB, 0xF2DD, 0x81FC, 0xCFBF, 0x81FE, 0xEBAC, 0x8205, 0xCFC0, + 0x8207, 0xE6A8, 0x8208, 0xFDE9, 0x820A, 0xCFC1, 0x820C, 0xE0DF, 0x820D, 0xDEEC, 0x8212, 0xE0A2, 0x821B, 0xF4BF, 0x821C, 0xE2EF, + 0x821E, 0xD9F1, 0x821F, 0xF1C7, 0x8221, 0xCBB8, 0x822A, 0xF9FE, 0x822B, 0xDBBA, 0x822C, 0xDAF5, 0x8235, 0xF6EC, 0x8236, 0xDADC, + 0x8237, 0xFAE4, 0x8239, 0xE0CF, 0x8240, 0xDDB2, 0x8245, 0xE6A9, 0x8247, 0xEFF3, 0x8259, 0xF3ED, 0x8264, 0xEBFA, 0x8266, 0xF9E6, + 0x826E, 0xCADD, 0x826F, 0xD5DE, 0x8271, 0xCADE, 0x8272, 0xDFE4, 0x8276, 0xE6FD, 0x8278, 0xF5AC, 0x827E, 0xE4F5, 0x828B, 0xE9E3, + 0x828D, 0xEDCB, 0x828E, 0xCFE4, 0x8292, 0xD8D3, 0x8299, 0xDDB3, 0x829A, 0xD4EC, 0x829D, 0xF2B9, 0x829F, 0xDFB7, 0x82A5, 0xCBCE, + 0x82A6, 0xFBD8, 0x82A9, 0xD0D9, 0x82AC, 0xDDD2, 0x82AD, 0xF7F4, 0x82AE, 0xE7DC, 0x82AF, 0xE4A5, 0x82B1, 0xFCA3, 0x82B3, 0xDBBB, + 0x82B7, 0xF2BA, 0x82B8, 0xE9FD, 0x82B9, 0xD0CA, 0x82BB, 0xF5D6, 0x82BC, 0xD9C5, 0x82BD, 0xE4B4, 0x82BF, 0xEDA7, 0x82D1, 0xEABD, + 0x82D2, 0xE6FE, 0x82D4, 0xF7C4, 0x82D5, 0xF5AD, 0x82D7, 0xD9E0, 0x82DB, 0xCAB4, 0x82DE, 0xF8E2, 0x82DF, 0xCFC2, 0x82E1, 0xECBE, + 0x82E5, 0xE5B4, 0x82E6, 0xCDC8, 0x82E7, 0xEEC8, 0x82F1, 0xE7C8, 0x82FD, 0xCDC9, 0x82FE, 0xF9B7, 0x8301, 0xF1E8, 0x8302, 0xD9F2, + 0x8303, 0xDBF5, 0x8304, 0xCAB5, 0x8305, 0xD9C6, 0x8309, 0xD8C9, 0x8317, 0xD9AB, 0x8328, 0xEDBC, 0x832B, 0xD8D4, 0x832F, 0xDCDA, + 0x8331, 0xE2BC, 0x8334, 0xFCED, 0x8335, 0xECE0, 0x8336, 0xD2FE, 0x8338, 0xE9C7, 0x8339, 0xE6AA, 0x8340, 0xE2F0, 0x8347, 0xFABB, + 0x8349, 0xF5AE, 0x834A, 0xFBAA, 0x834F, 0xECFB, 0x8351, 0xECBF, 0x8352, 0xFCD8, 0x8373, 0xD4E5, 0x8377, 0xF9C3, 0x837B, 0xEEE2, + 0x8389, 0xD7E9, 0x838A, 0xEDF6, 0x838E, 0xDEED, 0x8396, 0xCCEC, 0x8398, 0xE3EE, 0x839E, 0xE8D4, 0x83A2, 0xFAF8, 0x83A9, 0xDDB4, + 0x83AA, 0xE4B5, 0x83AB, 0xD8B0, 0x83BD, 0xD8D5, 0x83C1, 0xF4EA, 0x83C5, 0xCEB9, 0x83C9, 0xD6E1, 0x83CA, 0xCFD2, 0x83CC, 0xD0B6, + 0x83D3, 0xCEA2, 0x83D6, 0xF3EE, 0x83DC, 0xF3F8, 0x83E9, 0xDCCC, 0x83EB, 0xD0CB, 0x83EF, 0xFCA4, 0x83F0, 0xCDCA, 0x83F1, 0xD7D4, + 0x83F2, 0xDEA3, 0x83F4, 0xE4E0, 0x83F9, 0xEEC9, 0x83FD, 0xE2DD, 0x8403, 0xF5FE, 0x8404, 0xD4AC, 0x840A, 0xD5D1, 0x840C, 0xD8F0, + 0x840D, 0xF8C3, 0x840E, 0xEAD7, 0x8429, 0xF5D7, 0x842C, 0xD8BF, 0x8431, 0xFDC0, 0x8438, 0xEBAD, 0x843D, 0xD5AA, 0x8449, 0xE7A8, + 0x8457, 0xEECA, 0x845B, 0xCAE7, 0x8461, 0xF8E3, 0x8463, 0xD4DD, 0x8466, 0xEAD8, 0x846B, 0xFBD9, 0x846C, 0xEDF7, 0x846F, 0xE5B5, + 0x8475, 0xD0AD, 0x847A, 0xF1F1, 0x8490, 0xE2BD, 0x8494, 0xE3C8, 0x8499, 0xD9D5, 0x849C, 0xDFAA, 0x84A1, 0xDBBC, 0x84B2, 0xF8E4, + 0x84B8, 0xF1FA, 0x84BB, 0xE5B6, 0x84BC, 0xF3EF, 0x84BF, 0xFBDA, 0x84C0, 0xE1E0, 0x84C2, 0xD9AC, 0x84C4, 0xF5EB, 0x84C6, 0xE0B6, + 0x84C9, 0xE9C8, 0x84CB, 0xCBCF, 0x84CD, 0xE3C9, 0x84D1, 0xDEEE, 0x84DA, 0xE2BE, 0x84EC, 0xDCEF, 0x84EE, 0xD6A5, 0x84F4, 0xE2F1, + 0x84FC, 0xD6FE, 0x8511, 0xD9A1, 0x8513, 0xD8C0, 0x8514, 0xDCDB, 0x8517, 0xEDBD, 0x8518, 0xDFB8, 0x851A, 0xEAA5, 0x851E, 0xD7AD, + 0x8521, 0xF3F9, 0x8523, 0xEDF8, 0x8525, 0xF5C7, 0x852C, 0xE1CA, 0x852D, 0xEBE3, 0x852F, 0xF2DE, 0x853D, 0xF8CC, 0x853F, 0xEAD9, + 0x8541, 0xD3C6, 0x8543, 0xDBE6, 0x8549, 0xF5AF, 0x854E, 0xCEF0, 0x8553, 0xE9FE, 0x8559, 0xFBB6, 0x8563, 0xE2F2, 0x8568, 0xCFF2, + 0x8569, 0xF7B9, 0x856A, 0xD9F3, 0x856D, 0xE1CB, 0x8584, 0xDADD, 0x8587, 0xDAB9, 0x858F, 0xEBFB, 0x8591, 0xCBB9, 0x8594, 0xEDF9, + 0x859B, 0xE0E0, 0x85A6, 0xF4C0, 0x85A8, 0xFDBC, 0x85A9, 0xDFB1, 0x85AA, 0xE3EF, 0x85AF, 0xE0A3, 0x85B0, 0xFDB9, 0x85BA, 0xF0B1, + 0x85C1, 0xCDCB, 0x85C9, 0xEDBE, 0x85CD, 0xD5C0, 0x85CE, 0xE3F0, 0x85CF, 0xEDFA, 0x85D5, 0xE9E4, 0x85DC, 0xD5ED, 0x85DD, 0xE7DD, + 0x85E4, 0xD4F6, 0x85E5, 0xE5B7, 0x85E9, 0xDBE7, 0x85EA, 0xE2BF, 0x85F7, 0xEECB, 0x85FA, 0xD7F4, 0x85FB, 0xF0DD, 0x85FF, 0xCEAB, + 0x8602, 0xE7DE, 0x8606, 0xD6D6, 0x8607, 0xE1CC, 0x860A, 0xE8B3, 0x8616, 0xE5EE, 0x8617, 0xDCA2, 0x861A, 0xE0D0, 0x862D, 0xD5B5, + 0x863F, 0xD5A1, 0x864E, 0xFBDB, 0x8650, 0xF9CB, 0x8654, 0xCBF3, 0x8655, 0xF4A5, 0x865B, 0xFAC8, 0x865C, 0xD6D7, 0x865E, 0xE9E5, + 0x865F, 0xFBDC, 0x8667, 0xFDD0, 0x8679, 0xFBF6, 0x868A, 0xDAA5, 0x868C, 0xDBBD, 0x8693, 0xECE2, 0x86A3, 0xCDF7, 0x86A4, 0xF0DE, + 0x86A9, 0xF6C9, 0x86C7, 0xDEEF, 0x86CB, 0xD3B1, 0x86D4, 0xFCEE, 0x86D9, 0xE8C3, 0x86DB, 0xF1C8, 0x86DF, 0xCEF1, 0x86E4, 0xF9ED, + 0x86ED, 0xF2F4, 0x86FE, 0xE4B6, 0x8700, 0xF5B9, 0x8702, 0xDCF0, 0x8703, 0xE3F1, 0x8708, 0xE8A5, 0x8718, 0xF2BB, 0x871A, 0xDEA4, + 0x871C, 0xDACC, 0x874E, 0xCAE9, 0x8755, 0xE3DA, 0x8757, 0xFCD9, 0x875F, 0xEADA, 0x8766, 0xF9C4, 0x8768, 0xE3A4, 0x8774, 0xFBDD, + 0x8776, 0xEFCA, 0x8778, 0xE8C4, 0x8782, 0xD5CC, 0x878D, 0xEBD7, 0x879F, 0xD9AD, 0x87A2, 0xFBAB, 0x87B3, 0xD3D9, 0x87BA, 0xD5A2, + 0x87C4, 0xF6DE, 0x87E0, 0xDAF6, 0x87EC, 0xE0D1, 0x87EF, 0xE9A8, 0x87F2, 0xF5F9, 0x87F9, 0xFAAF, 0x87FB, 0xEBFC, 0x87FE, 0xE0EA, + 0x8805, 0xE3B2, 0x881F, 0xD5C5, 0x8822, 0xF1E3, 0x8823, 0xD5EE, 0x8831, 0xCDCC, 0x8836, 0xEDD9, 0x883B, 0xD8C1, 0x8840, 0xFAEC, + 0x8846, 0xF1EB, 0x884C, 0xFABC, 0x884D, 0xE6E2, 0x8852, 0xFAE5, 0x8853, 0xE2FA, 0x8857, 0xCAB6, 0x8859, 0xE4B7, 0x885B, 0xEADB, + 0x885D, 0xF5FA, 0x8861, 0xFBAC, 0x8862, 0xCFC3, 0x8863, 0xEBFD, 0x8868, 0xF8FA, 0x886B, 0xDFB9, 0x8870, 0xE1F1, 0x8872, 0xD2A4, + 0x8877, 0xF5FB, 0x887E, 0xD0DA, 0x887F, 0xD0DB, 0x8881, 0xEABE, 0x8882, 0xD9B1, 0x8888, 0xCAB7, 0x888B, 0xD3E7, 0x888D, 0xF8E5, + 0x8892, 0xD3B2, 0x8896, 0xE2C0, 0x8897, 0xF2DF, 0x889E, 0xCDE5, 0x88AB, 0xF9AC, 0x88B4, 0xCDCD, 0x88C1, 0xEEAE, 0x88C2, 0xD6AE, + 0x88CF, 0xD7EA, 0x88D4, 0xE7E0, 0x88D5, 0xEBAE, 0x88D9, 0xCFD9, 0x88DC, 0xDCCD, 0x88DD, 0xEDFB, 0x88DF, 0xDEF0, 0x88E1, 0xD7EB, + 0x88E8, 0xDEA5, 0x88F3, 0xDFD7, 0x88F4, 0xDBD0, 0x88F5, 0xDBD1, 0x88F8, 0xD5A3, 0x88FD, 0xF0B2, 0x8907, 0xDCDC, 0x8910, 0xCAE8, + 0x8912, 0xF8E6, 0x8913, 0xDCCE, 0x8918, 0xEADC, 0x8919, 0xDBD2, 0x8925, 0xE9B3, 0x892A, 0xF7DB, 0x8936, 0xE3A8, 0x8938, 0xD7AE, + 0x893B, 0xE0E1, 0x8941, 0xCBBA, 0x8944, 0xE5D1, 0x895F, 0xD0DC, 0x8964, 0xD5C1, 0x896A, 0xD8CA, 0x8972, 0xE3A9, 0x897F, 0xE0A4, + 0x8981, 0xE9A9, 0x8983, 0xD3C7, 0x8986, 0xDCDD, 0x8987, 0xF8AE, 0x898B, 0xCCB8, 0x898F, 0xD0AE, 0x8993, 0xD8F2, 0x8996, 0xE3CA, + 0x89A1, 0xCCAF, 0x89A9, 0xD4AD, 0x89AA, 0xF6D1, 0x89B2, 0xD0CC, 0x89BA, 0xCAC6, 0x89BD, 0xD5C2, 0x89C0, 0xCEBA, 0x89D2, 0xCAC7, + 0x89E3, 0xFAB0, 0x89F4, 0xDFD8, 0x89F8, 0xF5BA, 0x8A00, 0xE5EB, 0x8A02, 0xEFF4, 0x8A03, 0xDDB5, 0x8A08, 0xCDAA, 0x8A0A, 0xE3F2, + 0x8A0C, 0xFBF7, 0x8A0E, 0xF7D0, 0x8A13, 0xFDBA, 0x8A16, 0xFDE1, 0x8A17, 0xF6FE, 0x8A18, 0xD1C0, 0x8A1B, 0xE8C5, 0x8A1D, 0xE4B8, + 0x8A1F, 0xE1E8, 0x8A23, 0xCCC1, 0x8A25, 0xD2ED, 0x8A2A, 0xDBBE, 0x8A2D, 0xE0E2, 0x8A31, 0xFAC9, 0x8A34, 0xE1CD, 0x8A36, 0xCAB8, + 0x8A3A, 0xF2E0, 0x8A3B, 0xF1C9, 0x8A50, 0xDEF1, 0x8A54, 0xF0DF, 0x8A55, 0xF8C4, 0x8A5B, 0xEECC, 0x8A5E, 0xDEF2, 0x8A60, 0xE7C9, + 0x8A62, 0xE2F3, 0x8A63, 0xE7E1, 0x8A66, 0xE3CB, 0x8A69, 0xE3CC, 0x8A6D, 0xCFF8, 0x8A6E, 0xEFAC, 0x8A70, 0xFDFE, 0x8A71, 0xFCA5, + 0x8A72, 0xFAB1, 0x8A73, 0xDFD9, 0x8A75, 0xE0D2, 0x8A79, 0xF4DA, 0x8A85, 0xF1CA, 0x8A87, 0xCEA3, 0x8A8C, 0xF2BC, 0x8A8D, 0xECE3, + 0x8A93, 0xE0A5, 0x8A95, 0xF7AB, 0x8A98, 0xEBAF, 0x8A9E, 0xE5DE, 0x8AA0, 0xE1A4, 0x8AA1, 0xCDAB, 0x8AA3, 0xD9F4, 0x8AA4, 0xE8A6, + 0x8AA5, 0xCDCE, 0x8AA6, 0xE1E9, 0x8AA8, 0xFCEF, 0x8AAA, 0xE0E3, 0x8AB0, 0xE2C1, 0x8AB2, 0xCEA4, 0x8AB9, 0xDEA6, 0x8ABC, 0xEBFE, + 0x8ABE, 0xEBDD, 0x8ABF, 0xF0E0, 0x8AC2, 0xF4DB, 0x8AC4, 0xE2F4, 0x8AC7, 0xD3C8, 0x8ACB, 0xF4EB, 0x8ACD, 0xEEB5, 0x8ACF, 0xF5D8, + 0x8AD2, 0xD5DF, 0x8AD6, 0xD6E5, 0x8ADB, 0xEBB0, 0x8ADC, 0xF4E3, 0x8AE1, 0xE3CD, 0x8AE6, 0xF4F4, 0x8AE7, 0xFAB2, 0x8AEA, 0xEFF5, + 0x8AEB, 0xCADF, 0x8AED, 0xEBB1, 0x8AEE, 0xEDBF, 0x8AF1, 0xFDC9, 0x8AF6, 0xE4A6, 0x8AF7, 0xF9A4, 0x8AF8, 0xF0B3, 0x8AFA, 0xE5EC, + 0x8AFE, 0xD1E7, 0x8B00, 0xD9C7, 0x8B01, 0xE4D7, 0x8B02, 0xEADD, 0x8B04, 0xD4F7, 0x8B0E, 0xDABA, 0x8B10, 0xDACD, 0x8B14, 0xF9CC, + 0x8B16, 0xE1DA, 0x8B17, 0xDBBF, 0x8B19, 0xCCC5, 0x8B1A, 0xECD0, 0x8B1B, 0xCBBB, 0x8B1D, 0xDEF3, 0x8B20, 0xE9AA, 0x8B28, 0xD9C8, + 0x8B2B, 0xEEE3, 0x8B2C, 0xD7BD, 0x8B33, 0xCFC4, 0x8B39, 0xD0CD, 0x8B41, 0xFCA6, 0x8B49, 0xF1FB, 0x8B4E, 0xFDD2, 0x8B4F, 0xD1C1, + 0x8B58, 0xE3DB, 0x8B5A, 0xD3C9, 0x8B5C, 0xDCCF, 0x8B66, 0xCCED, 0x8B6C, 0xDEA7, 0x8B6F, 0xE6BB, 0x8B70, 0xECA1, 0x8B74, 0xCCB9, + 0x8B77, 0xFBDE, 0x8B7D, 0xE7E2, 0x8B80, 0xD4C1, 0x8B8A, 0xDCA8, 0x8B90, 0xE2C2, 0x8B92, 0xF3D8, 0x8B93, 0xE5D3, 0x8B96, 0xF3D9, + 0x8B9A, 0xF3C6, 0x8C37, 0xCDDB, 0x8C3F, 0xCDAC, 0x8C41, 0xFCC3, 0x8C46, 0xD4E7, 0x8C48, 0xD1C2, 0x8C4A, 0xF9A5, 0x8C4C, 0xE8D5, + 0x8C55, 0xE3CE, 0x8C5A, 0xD4CA, 0x8C61, 0xDFDA, 0x8C6A, 0xFBDF, 0x8C6B, 0xE7E3, 0x8C79, 0xF8FB, 0x8C7A, 0xE3CF, 0x8C82, 0xF5B0, + 0x8C8A, 0xD8E7, 0x8C8C, 0xD9C9, 0x8C9D, 0xF8AF, 0x8C9E, 0xEFF6, 0x8CA0, 0xDDB6, 0x8CA1, 0xEEAF, 0x8CA2, 0xCDF8, 0x8CA7, 0xDEB8, + 0x8CA8, 0xFCA7, 0x8CA9, 0xF7FC, 0x8CAA, 0xF7B1, 0x8CAB, 0xCEBB, 0x8CAC, 0xF4A1, 0x8CAF, 0xEECD, 0x8CB0, 0xE1AE, 0x8CB3, 0xECC3, + 0x8CB4, 0xCFFE, 0x8CB6, 0xF8BF, 0x8CB7, 0xD8E2, 0x8CB8, 0xD3E8, 0x8CBB, 0xDEA8, 0x8CBC, 0xF4E4, 0x8CBD, 0xECC2, 0x8CBF, 0xD9F5, + 0x8CC0, 0xF9C5, 0x8CC1, 0xDDD3, 0x8CC2, 0xD6F1, 0x8CC3, 0xECFC, 0x8CC4, 0xFCF0, 0x8CC7, 0xEDC0, 0x8CC8, 0xCAB9, 0x8CCA, 0xEEE4, + 0x8CD1, 0xF2E1, 0x8CD3, 0xDEB9, 0x8CDA, 0xD6F2, 0x8CDC, 0xDEF4, 0x8CDE, 0xDFDB, 0x8CE0, 0xDBD3, 0x8CE2, 0xFAE7, 0x8CE3, 0xD8E3, + 0x8CE4, 0xF4C1, 0x8CE6, 0xDDB7, 0x8CEA, 0xF2F5, 0x8CED, 0xD4AE, 0x8CF4, 0xD6F3, 0x8CFB, 0xDDB8, 0x8CFC, 0xCFC5, 0x8CFD, 0xDFDF, + 0x8D04, 0xF2BE, 0x8D05, 0xF6A1, 0x8D07, 0xEBCB, 0x8D08, 0xF1FC, 0x8D0A, 0xF3C7, 0x8D0D, 0xE0EB, 0x8D13, 0xEDFC, 0x8D16, 0xE1DB, + 0x8D64, 0xEEE5, 0x8D66, 0xDEF5, 0x8D6B, 0xFAD3, 0x8D70, 0xF1CB, 0x8D73, 0xD0AF, 0x8D74, 0xDDB9, 0x8D77, 0xD1C3, 0x8D85, 0xF5B1, + 0x8D8A, 0xEAC6, 0x8D99, 0xF0E1, 0x8DA3, 0xF6AC, 0x8DA8, 0xF5D9, 0x8DB3, 0xF0EB, 0x8DBA, 0xDDBA, 0x8DBE, 0xF2BF, 0x8DC6, 0xF7C5, + 0x8DCB, 0xDBA2, 0x8DCC, 0xF2F6, 0x8DCF, 0xCABA, 0x8DDB, 0xF7F5, 0x8DDD, 0xCBE5, 0x8DE1, 0xEEE6, 0x8DE3, 0xE0D3, 0x8DE8, 0xCEA5, + 0x8DEF, 0xD6D8, 0x8DF3, 0xD4AF, 0x8E0A, 0xE9C9, 0x8E0F, 0xD3CE, 0x8E10, 0xF4C2, 0x8E1E, 0xCBE6, 0x8E2A, 0xF1A1, 0x8E30, 0xEBB2, + 0x8E35, 0xF1A2, 0x8E42, 0xEBB3, 0x8E44, 0xF0B4, 0x8E47, 0xCBF4, 0x8E48, 0xD4B0, 0x8E49, 0xF3B2, 0x8E4A, 0xFBB7, 0x8E59, 0xF5EC, + 0x8E5F, 0xEEE7, 0x8E60, 0xF4B2, 0x8E74, 0xF5ED, 0x8E76, 0xCFF3, 0x8E81, 0xF0E2, 0x8E87, 0xEECE, 0x8E8A, 0xF1CC, 0x8E8D, 0xE5B8, + 0x8EAA, 0xD7F5, 0x8EAB, 0xE3F3, 0x8EAC, 0xCFE5, 0x8EC0, 0xCFC6, 0x8ECA, 0xF3B3, 0x8ECB, 0xE4D8, 0x8ECC, 0xCFF9, 0x8ECD, 0xCFDA, + 0x8ED2, 0xFACD, 0x8EDF, 0xE6E3, 0x8EEB, 0xF2E2, 0x8EF8, 0xF5EE, 0x8EFB, 0xCABB, 0x8EFE, 0xE3DC, 0x8F03, 0xCEF2, 0x8F05, 0xD6D9, + 0x8F09, 0xEEB0, 0x8F12, 0xF4E5, 0x8F13, 0xD8C2, 0x8F14, 0xDCD0, 0x8F15, 0xCCEE, 0x8F1B, 0xD5E0, 0x8F1C, 0xF6CA, 0x8F1D, 0xFDCA, + 0x8F1E, 0xD8D6, 0x8F1F, 0xF4CF, 0x8F26, 0xD6A6, 0x8F27, 0xDCBE, 0x8F29, 0xDBD4, 0x8F2A, 0xD7C7, 0x8F2F, 0xF2FE, 0x8F33, 0xF1CD, + 0x8F38, 0xE2C3, 0x8F39, 0xDCDE, 0x8F3B, 0xDCDF, 0x8F3E, 0xEFAD, 0x8F3F, 0xE6AB, 0x8F44, 0xF9DD, 0x8F45, 0xEABF, 0x8F49, 0xEFAE, + 0x8F4D, 0xF4D0, 0x8F4E, 0xCEF3, 0x8F5D, 0xE6AC, 0x8F5F, 0xCEDE, 0x8F62, 0xD5F9, 0x8F9B, 0xE3F4, 0x8F9C, 0xCDD0, 0x8FA3, 0xD5B8, + 0x8FA6, 0xF7FD, 0x8FA8, 0xDCA9, 0x8FAD, 0xDEF6, 0x8FAF, 0xDCAA, 0x8FB0, 0xF2E3, 0x8FB1, 0xE9B4, 0x8FB2, 0xD2DC, 0x8FC2, 0xE9E6, + 0x8FC5, 0xE3F6, 0x8FCE, 0xE7CA, 0x8FD1, 0xD0CE, 0x8FD4, 0xDAF7, 0x8FE6, 0xCABC, 0x8FEA, 0xEEE8, 0x8FEB, 0xDADE, 0x8FED, 0xF2F7, + 0x8FF0, 0xE2FB, 0x8FF2, 0xCCA6, 0x8FF7, 0xDABB, 0x8FF9, 0xEEE9, 0x8FFD, 0xF5DA, 0x9000, 0xF7DC, 0x9001, 0xE1EA, 0x9002, 0xCEC1, + 0x9003, 0xD4B1, 0x9005, 0xFDB1, 0x9006, 0xE6BD, 0x9008, 0xFBAD, 0x900B, 0xF8E7, 0x900D, 0xE1CE, 0x900F, 0xF7E2, 0x9010, 0xF5EF, + 0x9011, 0xCFC7, 0x9014, 0xD4B2, 0x9015, 0xCCEF, 0x9017, 0xD4E8, 0x9019, 0xEECF, 0x901A, 0xF7D7, 0x901D, 0xE0A6, 0x901E, 0xD6C1, + 0x901F, 0xE1DC, 0x9020, 0xF0E3, 0x9021, 0xF1E4, 0x9022, 0xDCF1, 0x9023, 0xD6A7, 0x902E, 0xF4F5, 0x9031, 0xF1CE, 0x9032, 0xF2E4, + 0x9035, 0xD0B0, 0x9038, 0xECEF, 0x903C, 0xF9BA, 0x903E, 0xEBB5, 0x9041, 0xD4ED, 0x9042, 0xE2C4, 0x9047, 0xE9E7, 0x904A, 0xEBB4, + 0x904B, 0xEAA1, 0x904D, 0xF8BC, 0x904E, 0xCEA6, 0x9050, 0xF9C6, 0x9051, 0xFCDA, 0x9053, 0xD4B3, 0x9054, 0xD3B9, 0x9055, 0xEADE, + 0x9059, 0xE9AB, 0x905C, 0xE1E1, 0x905D, 0xD3CF, 0x905E, 0xF4F6, 0x9060, 0xEAC0, 0x9061, 0xE1CF, 0x9063, 0xCCBA, 0x9069, 0xEEEA, + 0x906D, 0xF0E4, 0x906E, 0xF3B4, 0x906F, 0xD4EE, 0x9072, 0xF2C0, 0x9075, 0xF1E5, 0x9077, 0xF4C3, 0x9078, 0xE0D4, 0x907A, 0xEBB6, + 0x907C, 0xD7A1, 0x907D, 0xCBE8, 0x907F, 0xF9AD, 0x9080, 0xE9AD, 0x9081, 0xD8E4, 0x9082, 0xFAB3, 0x9083, 0xE2C5, 0x9084, 0xFCBD, + 0x9087, 0xECC4, 0x9088, 0xD8B1, 0x908A, 0xDCAB, 0x908F, 0xD5A4, 0x9091, 0xEBE9, 0x9095, 0xE8BB, 0x9099, 0xD8D7, 0x90A2, 0xFBAE, + 0x90A3, 0xD1E1, 0x90A6, 0xDBC0, 0x90A8, 0xF5BE, 0x90AA, 0xDEF7, 0x90AF, 0xCAFB, 0x90B0, 0xF7C6, 0x90B1, 0xCFC8, 0x90B5, 0xE1D0, + 0x90B8, 0xEED0, 0x90C1, 0xE9F4, 0x90CA, 0xCEF4, 0x90DE, 0xD5CD, 0x90E1, 0xCFDB, 0x90E8, 0xDDBB, 0x90ED, 0xCEAC, 0x90F5, 0xE9E8, + 0x90FD, 0xD4B4, 0x9102, 0xE4C7, 0x9112, 0xF5DB, 0x9115, 0xFAC1, 0x9119, 0xDEA9, 0x9127, 0xD4F8, 0x912D, 0xEFF7, 0x9132, 0xD3B3, + 0x9149, 0xEBB7, 0x914A, 0xEFF8, 0x914B, 0xF5DC, 0x914C, 0xEDCC, 0x914D, 0xDBD5, 0x914E, 0xF1CF, 0x9152, 0xF1D0, 0x9162, 0xF5B2, + 0x9169, 0xD9AE, 0x916A, 0xD5AC, 0x916C, 0xE2C6, 0x9175, 0xFDA3, 0x9177, 0xFBE5, 0x9178, 0xDFAB, 0x9187, 0xE2F5, 0x9189, 0xF6AD, + 0x918B, 0xF5B3, 0x918D, 0xF0B5, 0x9192, 0xE1A5, 0x919C, 0xF5DD, 0x91AB, 0xECA2, 0x91AC, 0xEDFD, 0x91AE, 0xF5B4, 0x91AF, 0xFBB8, + 0x91B1, 0xDBA3, 0x91B4, 0xD6CA, 0x91B5, 0xCBD9, 0x91C0, 0xE5D4, 0x91C7, 0xF3FA, 0x91C9, 0xEBB8, 0x91CB, 0xE0B7, 0x91CC, 0xD7EC, + 0x91CD, 0xF1EC, 0x91CE, 0xE5AF, 0x91CF, 0xD5E1, 0x91D0, 0xD7ED, 0x91D1, 0xD1D1, 0x91D7, 0xE1F2, 0x91D8, 0xEFF9, 0x91DC, 0xDDBC, + 0x91DD, 0xF6DC, 0x91E3, 0xF0E5, 0x91E7, 0xF4C4, 0x91EA, 0xE9E9, 0x91F5, 0xF3FB, 0x920D, 0xD4EF, 0x9210, 0xCCA2, 0x9211, 0xF7FE, + 0x9212, 0xDFBC, 0x9217, 0xEBCD, 0x921E, 0xD0B7, 0x9234, 0xD6C2, 0x923A, 0xE8AD, 0x923F, 0xEFAF, 0x9240, 0xCBA5, 0x9245, 0xCBE9, + 0x9249, 0xFAE8, 0x9257, 0xCCC6, 0x925B, 0xE6E7, 0x925E, 0xEAC7, 0x9262, 0xDBA4, 0x9264, 0xCFC9, 0x9265, 0xE2FC, 0x9266, 0xEFFA, + 0x9280, 0xEBDE, 0x9283, 0xF5C8, 0x9285, 0xD4DE, 0x9291, 0xE0D5, 0x9293, 0xEFB0, 0x9296, 0xE2C7, 0x9298, 0xD9AF, 0x929C, 0xF9E7, + 0x92B3, 0xE7E5, 0x92B6, 0xCFCA, 0x92B7, 0xE1D1, 0x92B9, 0xE2C8, 0x92CC, 0xEFFB, 0x92CF, 0xFAF9, 0x92D2, 0xDCF2, 0x92E4, 0xE0A7, + 0x92EA, 0xF8E8, 0x92F8, 0xCBEA, 0x92FC, 0xCBBC, 0x9304, 0xD6E2, 0x9310, 0xF5DE, 0x9318, 0xF5DF, 0x931A, 0xEEB6, 0x931E, 0xE2F6, + 0x931F, 0xD3CA, 0x9320, 0xEFFC, 0x9321, 0xD1C4, 0x9322, 0xEFB1, 0x9324, 0xD1C5, 0x9326, 0xD0DE, 0x9328, 0xD9E1, 0x932B, 0xE0B8, + 0x932E, 0xCDD1, 0x932F, 0xF3B9, 0x9348, 0xE7CC, 0x934A, 0xD6A8, 0x934B, 0xCEA7, 0x934D, 0xD4B5, 0x9354, 0xE4C8, 0x935B, 0xD3B4, + 0x936E, 0xEBB9, 0x9375, 0xCBF5, 0x937C, 0xF6DD, 0x937E, 0xF1A3, 0x938C, 0xCCC7, 0x9394, 0xE9CA, 0x9396, 0xE1F0, 0x939A, 0xF5E0, + 0x93A3, 0xFBAF, 0x93A7, 0xCBD1, 0x93AC, 0xFBE0, 0x93AD, 0xF2E5, 0x93B0, 0xECF0, 0x93C3, 0xF0EC, 0x93D1, 0xEEEB, 0x93DE, 0xE9CB, + 0x93E1, 0xCCF0, 0x93E4, 0xD7AF, 0x93F6, 0xF3A1, 0x9404, 0xFCF5, 0x9418, 0xF1A4, 0x9425, 0xE0D6, 0x942B, 0xEFB2, 0x9435, 0xF4D1, + 0x9438, 0xF7A1, 0x9444, 0xF1D1, 0x9451, 0xCAFC, 0x9452, 0xCAFD, 0x945B, 0xCECE, 0x947D, 0xF3C8, 0x947F, 0xF3BA, 0x9577, 0xEDFE, + 0x9580, 0xDAA6, 0x9583, 0xE0EC, 0x9589, 0xF8CD, 0x958B, 0xCBD2, 0x958F, 0xEBCE, 0x9591, 0xF9D8, 0x9592, 0xF9D9, 0x9593, 0xCAE0, + 0x9594, 0xDACA, 0x9598, 0xCBA6, 0x95A3, 0xCAC8, 0x95A4, 0xF9EE, 0x95A5, 0xDBEC, 0x95A8, 0xD0B1, 0x95AD, 0xD5EF, 0x95B1, 0xE6F3, + 0x95BB, 0xE7A2, 0x95BC, 0xE4D9, 0x95C7, 0xE4E1, 0x95CA, 0xFCC4, 0x95D4, 0xF9EF, 0x95D5, 0xCFF4, 0x95D6, 0xF7E6, 0x95DC, 0xCEBC, + 0x95E1, 0xF4C5, 0x95E2, 0xDCA3, 0x961C, 0xDDBD, 0x9621, 0xF4C6, 0x962A, 0xF8A1, 0x962E, 0xE8D6, 0x9632, 0xDBC1, 0x963B, 0xF0E6, + 0x963F, 0xE4B9, 0x9640, 0xF6ED, 0x9642, 0xF9AE, 0x9644, 0xDDBE, 0x964B, 0xD7B0, 0x964C, 0xD8E8, 0x964D, 0xCBBD, 0x9650, 0xF9DA, + 0x965B, 0xF8CE, 0x965C, 0xF9F0, 0x965D, 0xE0ED, 0x965E, 0xE3B3, 0x965F, 0xF4B3, 0x9662, 0xEAC2, 0x9663, 0xF2E6, 0x9664, 0xF0B6, + 0x966A, 0xDBD6, 0x9670, 0xEBE4, 0x9673, 0xF2E7, 0x9675, 0xD7D5, 0x9676, 0xD4B6, 0x9677, 0xF9E8, 0x9678, 0xD7C1, 0x967D, 0xE5D5, + 0x9685, 0xE9EA, 0x9686, 0xD7CC, 0x968A, 0xD3E9, 0x968B, 0xE2C9, 0x968D, 0xFCDB, 0x968E, 0xCDAD, 0x9694, 0xCCB0, 0x9695, 0xEAA2, + 0x9698, 0xE4F6, 0x9699, 0xD0C0, 0x969B, 0xF0B7, 0x969C, 0xEEA1, 0x96A3, 0xD7F6, 0x96A7, 0xE2CA, 0x96A8, 0xE2CB, 0x96AA, 0xFACF, + 0x96B1, 0xEBDF, 0x96B7, 0xD6CB, 0x96BB, 0xF4B4, 0x96C0, 0xEDCD, 0x96C1, 0xE4D2, 0x96C4, 0xEAA9, 0x96C5, 0xE4BA, 0x96C6, 0xF3A2, + 0x96C7, 0xCDD2, 0x96C9, 0xF6CB, 0x96CB, 0xF1E6, 0x96CC, 0xEDC1, 0x96CD, 0xE8BC, 0x96CE, 0xEED1, 0x96D5, 0xF0E7, 0x96D6, 0xE2CC, + 0x96D9, 0xE4AA, 0x96DB, 0xF5E1, 0x96DC, 0xEDDA, 0x96E2, 0xD7EE, 0x96E3, 0xD1F1, 0x96E8, 0xE9EB, 0x96E9, 0xE9EC, 0x96EA, 0xE0E4, + 0x96EF, 0xDAA7, 0x96F0, 0xDDD4, 0x96F2, 0xEAA3, 0x96F6, 0xD6C3, 0x96F7, 0xD6F4, 0x96F9, 0xDADF, 0x96FB, 0xEFB3, 0x9700, 0xE2CD, + 0x9706, 0xEFFD, 0x9707, 0xF2E8, 0x9711, 0xEFC5, 0x9713, 0xE7E7, 0x9716, 0xD7FD, 0x9719, 0xE7CE, 0x971C, 0xDFDC, 0x971E, 0xF9C7, + 0x9727, 0xD9F6, 0x9730, 0xDFAC, 0x9732, 0xD6DA, 0x9739, 0xDCA4, 0x973D, 0xF0B8, 0x9742, 0xD5FA, 0x9744, 0xE4F7, 0x9748, 0xD6C4, + 0x9751, 0xF4EC, 0x9756, 0xEFFE, 0x975C, 0xF0A1, 0x975E, 0xDEAA, 0x9761, 0xDABC, 0x9762, 0xD8FC, 0x9769, 0xFAD4, 0x976D, 0xECE5, + 0x9774, 0xFCA8, 0x9777, 0xECE6, 0x977A, 0xD8CB, 0x978B, 0xFBB9, 0x978D, 0xE4D3, 0x978F, 0xCDF9, 0x97A0, 0xCFD3, 0x97A8, 0xCAEA, + 0x97AB, 0xCFD4, 0x97AD, 0xF8BD, 0x97C6, 0xF4C7, 0x97CB, 0xEADF, 0x97D3, 0xF9DB, 0x97DC, 0xD4B7, 0x97F3, 0xEBE5, 0x97F6, 0xE1D2, + 0x97FB, 0xEAA4, 0x97FF, 0xFAC2, 0x9800, 0xFBE1, 0x9801, 0xFAED, 0x9802, 0xF0A2, 0x9803, 0xCCF1, 0x9805, 0xFAA3, 0x9806, 0xE2F7, + 0x9808, 0xE2CE, 0x980A, 0xE9F5, 0x980C, 0xE1EB, 0x9810, 0xE7E8, 0x9811, 0xE8D7, 0x9812, 0xDAF8, 0x9813, 0xD4CB, 0x9817, 0xF7F6, + 0x9818, 0xD6C5, 0x982D, 0xD4E9, 0x9830, 0xFAFA, 0x9838, 0xCCF2, 0x9839, 0xF7DD, 0x983B, 0xDEBA, 0x9846, 0xCEA8, 0x984C, 0xF0B9, + 0x984D, 0xE4FE, 0x984E, 0xE4C9, 0x9854, 0xE4D4, 0x9858, 0xEAC3, 0x985A, 0xEFB4, 0x985E, 0xD7BE, 0x9865, 0xFBE2, 0x9867, 0xCDD3, + 0x986B, 0xEFB5, 0x986F, 0xFAE9, 0x98A8, 0xF9A6, 0x98AF, 0xDFBD, 0x98B1, 0xF7C7, 0x98C4, 0xF8FD, 0x98C7, 0xF8FC, 0x98DB, 0xDEAB, + 0x98DC, 0xDBE8, 0x98DF, 0xE3DD, 0x98E1, 0xE1E2, 0x98E2, 0xD1C6, 0x98ED, 0xF6D0, 0x98EE, 0xEBE6, 0x98EF, 0xDAF9, 0x98F4, 0xECC7, + 0x98FC, 0xDEF8, 0x98FD, 0xF8E9, 0x98FE, 0xE3DE, 0x9903, 0xCEF5, 0x9909, 0xFAC3, 0x990A, 0xE5D7, 0x990C, 0xECC8, 0x9910, 0xF3C9, + 0x9913, 0xE4BB, 0x9918, 0xE6AE, 0x991E, 0xEFB6, 0x9920, 0xDCBF, 0x9928, 0xCEBD, 0x9945, 0xD8C3, 0x9949, 0xD0CF, 0x994B, 0xCFFA, + 0x994C, 0xF3CA, 0x994D, 0xE0D7, 0x9951, 0xD1C7, 0x9952, 0xE9AE, 0x9954, 0xE8BD, 0x9957, 0xFAC4, 0x9996, 0xE2CF, 0x9999, 0xFAC5, + 0x999D, 0xF9B8, 0x99A5, 0xDCE0, 0x99A8, 0xFBB0, 0x99AC, 0xD8A9, 0x99AD, 0xE5DF, 0x99AE, 0xF9A7, 0x99B1, 0xF6EE, 0x99B3, 0xF6CC, + 0x99B4, 0xE2F8, 0x99B9, 0xECF1, 0x99C1, 0xDAE0, 0x99D0, 0xF1D2, 0x99D1, 0xD2CC, 0x99D2, 0xCFCB, 0x99D5, 0xCABD, 0x99D9, 0xDDBF, + 0x99DD, 0xF6EF, 0x99DF, 0xDEF9, 0x99ED, 0xFAB4, 0x99F1, 0xD5AD, 0x99FF, 0xF1E7, 0x9A01, 0xDEBE, 0x9A08, 0xDCC0, 0x9A0E, 0xD1C8, + 0x9A0F, 0xD1C9, 0x9A19, 0xF8BE, 0x9A2B, 0xCBF6, 0x9A30, 0xD4F9, 0x9A36, 0xF5E2, 0x9A37, 0xE1D3, 0x9A40, 0xD8E9, 0x9A43, 0xF8FE, + 0x9A45, 0xCFCC, 0x9A4D, 0xFDA4, 0x9A55, 0xCEF6, 0x9A57, 0xFAD0, 0x9A5A, 0xCCF3, 0x9A5B, 0xE6BE, 0x9A5F, 0xF6AE, 0x9A62, 0xD5F0, + 0x9A65, 0xD1CA, 0x9A69, 0xFCBE, 0x9A6A, 0xD5F1, 0x9AA8, 0xCDE9, 0x9AB8, 0xFAB5, 0x9AD3, 0xE2D0, 0x9AD4, 0xF4F7, 0x9AD8, 0xCDD4, + 0x9AE5, 0xE7A3, 0x9AEE, 0xDBA5, 0x9B1A, 0xE2D1, 0x9B27, 0xD7A2, 0x9B2A, 0xF7E3, 0x9B31, 0xEAA6, 0x9B3C, 0xD0A1, 0x9B41, 0xCEDA, + 0x9B42, 0xFBEB, 0x9B43, 0xDBA6, 0x9B44, 0xDBDE, 0x9B45, 0xD8E5, 0x9B4F, 0xEAE0, 0x9B54, 0xD8AA, 0x9B5A, 0xE5E0, 0x9B6F, 0xD6DB, + 0x9B8E, 0xEFC6, 0x9B91, 0xF8EA, 0x9B9F, 0xE4D5, 0x9BAB, 0xCEF7, 0x9BAE, 0xE0D8, 0x9BC9, 0xD7EF, 0x9BD6, 0xF4ED, 0x9BE4, 0xCDE6, + 0x9BE8, 0xCCF4, 0x9C0D, 0xF5E3, 0x9C10, 0xE4CA, 0x9C12, 0xDCE1, 0x9C15, 0xF9C8, 0x9C25, 0xFCBF, 0x9C32, 0xE8A7, 0x9C3B, 0xD8C4, + 0x9C47, 0xCBBE, 0x9C49, 0xDCAE, 0x9C57, 0xD7F7, 0x9CE5, 0xF0E8, 0x9CE7, 0xDDC0, 0x9CE9, 0xCFCD, 0x9CF3, 0xDCF3, 0x9CF4, 0xD9B0, + 0x9CF6, 0xE6E9, 0x9D09, 0xE4BC, 0x9D1B, 0xEAC4, 0x9D26, 0xE4EC, 0x9D28, 0xE4E5, 0x9D3B, 0xFBF8, 0x9D51, 0xCCBB, 0x9D5D, 0xE4BD, + 0x9D60, 0xCDDC, 0x9D61, 0xD9F7, 0x9D6C, 0xDDDF, 0x9D72, 0xEDCE, 0x9DA9, 0xD9D0, 0x9DAF, 0xE5A3, 0x9DB4, 0xF9CD, 0x9DC4, 0xCDAE, + 0x9DD7, 0xCFCE, 0x9DF2, 0xF6AF, 0x9DF8, 0xFDD3, 0x9DF9, 0xEBED, 0x9DFA, 0xD6DC, 0x9E1A, 0xE5A4, 0x9E1E, 0xD5B6, 0x9E75, 0xD6DD, + 0x9E79, 0xF9E9, 0x9E7D, 0xE7A4, 0x9E7F, 0xD6E3, 0x9E92, 0xD1CB, 0x9E93, 0xD6E4, 0x9E97, 0xD5F2, 0x9E9D, 0xDEFA, 0x9E9F, 0xD7F8, + 0x9EA5, 0xD8EA, 0x9EB4, 0xCFD5, 0x9EB5, 0xD8FD, 0x9EBB, 0xD8AB, 0x9EBE, 0xFDCB, 0x9EC3, 0xFCDC, 0x9ECD, 0xE0A8, 0x9ECE, 0xD5F3, + 0x9ED1, 0xFDD9, 0x9ED4, 0xCCA3, 0x9ED8, 0xD9F9, 0x9EDB, 0xD3EA, 0x9EDC, 0xF5F5, 0x9EDE, 0xEFC7, 0x9EE8, 0xD3DA, 0x9EF4, 0xDABD, + 0x9F07, 0xE8A8, 0x9F08, 0xDCAF, 0x9F0E, 0xF0A3, 0x9F13, 0xCDD5, 0x9F20, 0xE0A9, 0x9F3B, 0xDEAC, 0x9F4A, 0xF0BA, 0x9F4B, 0xEEB1, + 0x9F4E, 0xEEB2, 0x9F52, 0xF6CD, 0x9F5F, 0xEED2, 0x9F61, 0xD6C6, 0x9F67, 0xE0E5, 0x9F6A, 0xF3BB, 0x9F6C, 0xE5E1, 0x9F77, 0xE4CB, + 0x9F8D, 0xD7A3, 0x9F90, 0xDBC2, 0x9F95, 0xCAFE, 0x9F9C, 0xCFCF, 0xAC00, 0xB0A1, 0xAC01, 0xB0A2, 0xAC02, 0x8141, 0xAC03, 0x8142, + 0xAC04, 0xB0A3, 0xAC05, 0x8143, 0xAC06, 0x8144, 0xAC07, 0xB0A4, 0xAC08, 0xB0A5, 0xAC09, 0xB0A6, 0xAC0A, 0xB0A7, 0xAC0B, 0x8145, + 0xAC0C, 0x8146, 0xAC0D, 0x8147, 0xAC0E, 0x8148, 0xAC0F, 0x8149, 0xAC10, 0xB0A8, 0xAC11, 0xB0A9, 0xAC12, 0xB0AA, 0xAC13, 0xB0AB, + 0xAC14, 0xB0AC, 0xAC15, 0xB0AD, 0xAC16, 0xB0AE, 0xAC17, 0xB0AF, 0xAC18, 0x814A, 0xAC19, 0xB0B0, 0xAC1A, 0xB0B1, 0xAC1B, 0xB0B2, + 0xAC1C, 0xB0B3, 0xAC1D, 0xB0B4, 0xAC1E, 0x814B, 0xAC1F, 0x814C, 0xAC20, 0xB0B5, 0xAC21, 0x814D, 0xAC22, 0x814E, 0xAC23, 0x814F, + 0xAC24, 0xB0B6, 0xAC25, 0x8150, 0xAC26, 0x8151, 0xAC27, 0x8152, 0xAC28, 0x8153, 0xAC29, 0x8154, 0xAC2A, 0x8155, 0xAC2B, 0x8156, + 0xAC2C, 0xB0B7, 0xAC2D, 0xB0B8, 0xAC2E, 0x8157, 0xAC2F, 0xB0B9, 0xAC30, 0xB0BA, 0xAC31, 0xB0BB, 0xAC32, 0x8158, 0xAC33, 0x8159, + 0xAC34, 0x815A, 0xAC35, 0x8161, 0xAC36, 0x8162, 0xAC37, 0x8163, 0xAC38, 0xB0BC, 0xAC39, 0xB0BD, 0xAC3A, 0x8164, 0xAC3B, 0x8165, + 0xAC3C, 0xB0BE, 0xAC3D, 0x8166, 0xAC3E, 0x8167, 0xAC3F, 0x8168, 0xAC40, 0xB0BF, 0xAC41, 0x8169, 0xAC42, 0x816A, 0xAC43, 0x816B, + 0xAC44, 0x816C, 0xAC45, 0x816D, 0xAC46, 0x816E, 0xAC47, 0x816F, 0xAC48, 0x8170, 0xAC49, 0x8171, 0xAC4A, 0x8172, 0xAC4B, 0xB0C0, + 0xAC4C, 0x8173, 0xAC4D, 0xB0C1, 0xAC4E, 0x8174, 0xAC4F, 0x8175, 0xAC50, 0x8176, 0xAC51, 0x8177, 0xAC52, 0x8178, 0xAC53, 0x8179, + 0xAC54, 0xB0C2, 0xAC55, 0x817A, 0xAC56, 0x8181, 0xAC57, 0x8182, 0xAC58, 0xB0C3, 0xAC59, 0x8183, 0xAC5A, 0x8184, 0xAC5B, 0x8185, + 0xAC5C, 0xB0C4, 0xAC5D, 0x8186, 0xAC5E, 0x8187, 0xAC5F, 0x8188, 0xAC60, 0x8189, 0xAC61, 0x818A, 0xAC62, 0x818B, 0xAC63, 0x818C, + 0xAC64, 0x818D, 0xAC65, 0x818E, 0xAC66, 0x818F, 0xAC67, 0x8190, 0xAC68, 0x8191, 0xAC69, 0x8192, 0xAC6A, 0x8193, 0xAC6B, 0x8194, + 0xAC6C, 0x8195, 0xAC6D, 0x8196, 0xAC6E, 0x8197, 0xAC6F, 0x8198, 0xAC70, 0xB0C5, 0xAC71, 0xB0C6, 0xAC72, 0x8199, 0xAC73, 0x819A, + 0xAC74, 0xB0C7, 0xAC75, 0x819B, 0xAC76, 0x819C, 0xAC77, 0xB0C8, 0xAC78, 0xB0C9, 0xAC79, 0x819D, 0xAC7A, 0xB0CA, 0xAC7B, 0x819E, + 0xAC7C, 0x819F, 0xAC7D, 0x81A0, 0xAC7E, 0x81A1, 0xAC7F, 0x81A2, 0xAC80, 0xB0CB, 0xAC81, 0xB0CC, 0xAC82, 0x81A3, 0xAC83, 0xB0CD, + 0xAC84, 0xB0CE, 0xAC85, 0xB0CF, 0xAC86, 0xB0D0, 0xAC87, 0x81A4, 0xAC88, 0x81A5, 0xAC89, 0xB0D1, 0xAC8A, 0xB0D2, 0xAC8B, 0xB0D3, + 0xAC8C, 0xB0D4, 0xAC8D, 0x81A6, 0xAC8E, 0x81A7, 0xAC8F, 0x81A8, 0xAC90, 0xB0D5, 0xAC91, 0x81A9, 0xAC92, 0x81AA, 0xAC93, 0x81AB, + 0xAC94, 0xB0D6, 0xAC95, 0x81AC, 0xAC96, 0x81AD, 0xAC97, 0x81AE, 0xAC98, 0x81AF, 0xAC99, 0x81B0, 0xAC9A, 0x81B1, 0xAC9B, 0x81B2, + 0xAC9C, 0xB0D7, 0xAC9D, 0xB0D8, 0xAC9E, 0x81B3, 0xAC9F, 0xB0D9, 0xACA0, 0xB0DA, 0xACA1, 0xB0DB, 0xACA2, 0x81B4, 0xACA3, 0x81B5, + 0xACA4, 0x81B6, 0xACA5, 0x81B7, 0xACA6, 0x81B8, 0xACA7, 0x81B9, 0xACA8, 0xB0DC, 0xACA9, 0xB0DD, 0xACAA, 0xB0DE, 0xACAB, 0x81BA, + 0xACAC, 0xB0DF, 0xACAD, 0x81BB, 0xACAE, 0x81BC, 0xACAF, 0xB0E0, 0xACB0, 0xB0E1, 0xACB1, 0x81BD, 0xACB2, 0x81BE, 0xACB3, 0x81BF, + 0xACB4, 0x81C0, 0xACB5, 0x81C1, 0xACB6, 0x81C2, 0xACB7, 0x81C3, 0xACB8, 0xB0E2, 0xACB9, 0xB0E3, 0xACBA, 0x81C4, 0xACBB, 0xB0E4, + 0xACBC, 0xB0E5, 0xACBD, 0xB0E6, 0xACBE, 0x81C5, 0xACBF, 0x81C6, 0xACC0, 0x81C7, 0xACC1, 0xB0E7, 0xACC2, 0x81C8, 0xACC3, 0x81C9, + 0xACC4, 0xB0E8, 0xACC5, 0x81CA, 0xACC6, 0x81CB, 0xACC7, 0x81CC, 0xACC8, 0xB0E9, 0xACC9, 0x81CD, 0xACCA, 0x81CE, 0xACCB, 0x81CF, + 0xACCC, 0xB0EA, 0xACCD, 0x81D0, 0xACCE, 0x81D1, 0xACCF, 0x81D2, 0xACD0, 0x81D3, 0xACD1, 0x81D4, 0xACD2, 0x81D5, 0xACD3, 0x81D6, + 0xACD4, 0x81D7, 0xACD5, 0xB0EB, 0xACD6, 0x81D8, 0xACD7, 0xB0EC, 0xACD8, 0x81D9, 0xACD9, 0x81DA, 0xACDA, 0x81DB, 0xACDB, 0x81DC, + 0xACDC, 0x81DD, 0xACDD, 0x81DE, 0xACDE, 0x81DF, 0xACDF, 0x81E0, 0xACE0, 0xB0ED, 0xACE1, 0xB0EE, 0xACE2, 0x81E1, 0xACE3, 0x81E2, + 0xACE4, 0xB0EF, 0xACE5, 0x81E3, 0xACE6, 0x81E4, 0xACE7, 0xB0F0, 0xACE8, 0xB0F1, 0xACE9, 0x81E5, 0xACEA, 0xB0F2, 0xACEB, 0x81E6, + 0xACEC, 0xB0F3, 0xACED, 0x81E7, 0xACEE, 0x81E8, 0xACEF, 0xB0F4, 0xACF0, 0xB0F5, 0xACF1, 0xB0F6, 0xACF2, 0x81E9, 0xACF3, 0xB0F7, + 0xACF4, 0x81EA, 0xACF5, 0xB0F8, 0xACF6, 0xB0F9, 0xACF7, 0x81EB, 0xACF8, 0x81EC, 0xACF9, 0x81ED, 0xACFA, 0x81EE, 0xACFB, 0x81EF, + 0xACFC, 0xB0FA, 0xACFD, 0xB0FB, 0xACFE, 0x81F0, 0xACFF, 0x81F1, 0xAD00, 0xB0FC, 0xAD01, 0x81F2, 0xAD02, 0x81F3, 0xAD03, 0x81F4, + 0xAD04, 0xB0FD, 0xAD05, 0x81F5, 0xAD06, 0xB0FE, 0xAD07, 0x81F6, 0xAD08, 0x81F7, 0xAD09, 0x81F8, 0xAD0A, 0x81F9, 0xAD0B, 0x81FA, + 0xAD0C, 0xB1A1, 0xAD0D, 0xB1A2, 0xAD0E, 0x81FB, 0xAD0F, 0xB1A3, 0xAD10, 0x81FC, 0xAD11, 0xB1A4, 0xAD12, 0x81FD, 0xAD13, 0x81FE, + 0xAD14, 0x8241, 0xAD15, 0x8242, 0xAD16, 0x8243, 0xAD17, 0x8244, 0xAD18, 0xB1A5, 0xAD19, 0x8245, 0xAD1A, 0x8246, 0xAD1B, 0x8247, + 0xAD1C, 0xB1A6, 0xAD1D, 0x8248, 0xAD1E, 0x8249, 0xAD1F, 0x824A, 0xAD20, 0xB1A7, 0xAD21, 0x824B, 0xAD22, 0x824C, 0xAD23, 0x824D, + 0xAD24, 0x824E, 0xAD25, 0x824F, 0xAD26, 0x8250, 0xAD27, 0x8251, 0xAD28, 0x8252, 0xAD29, 0xB1A8, 0xAD2A, 0x8253, 0xAD2B, 0x8254, + 0xAD2C, 0xB1A9, 0xAD2D, 0xB1AA, 0xAD2E, 0x8255, 0xAD2F, 0x8256, 0xAD30, 0x8257, 0xAD31, 0x8258, 0xAD32, 0x8259, 0xAD33, 0x825A, + 0xAD34, 0xB1AB, 0xAD35, 0xB1AC, 0xAD36, 0x8261, 0xAD37, 0x8262, 0xAD38, 0xB1AD, 0xAD39, 0x8263, 0xAD3A, 0x8264, 0xAD3B, 0x8265, + 0xAD3C, 0xB1AE, 0xAD3D, 0x8266, 0xAD3E, 0x8267, 0xAD3F, 0x8268, 0xAD40, 0x8269, 0xAD41, 0x826A, 0xAD42, 0x826B, 0xAD43, 0x826C, + 0xAD44, 0xB1AF, 0xAD45, 0xB1B0, 0xAD46, 0x826D, 0xAD47, 0xB1B1, 0xAD48, 0x826E, 0xAD49, 0xB1B2, 0xAD4A, 0x826F, 0xAD4B, 0x8270, + 0xAD4C, 0x8271, 0xAD4D, 0x8272, 0xAD4E, 0x8273, 0xAD4F, 0x8274, 0xAD50, 0xB1B3, 0xAD51, 0x8275, 0xAD52, 0x8276, 0xAD53, 0x8277, + 0xAD54, 0xB1B4, 0xAD55, 0x8278, 0xAD56, 0x8279, 0xAD57, 0x827A, 0xAD58, 0xB1B5, 0xAD59, 0x8281, 0xAD5A, 0x8282, 0xAD5B, 0x8283, + 0xAD5C, 0x8284, 0xAD5D, 0x8285, 0xAD5E, 0x8286, 0xAD5F, 0x8287, 0xAD60, 0x8288, 0xAD61, 0xB1B6, 0xAD62, 0x8289, 0xAD63, 0xB1B7, + 0xAD64, 0x828A, 0xAD65, 0x828B, 0xAD66, 0x828C, 0xAD67, 0x828D, 0xAD68, 0x828E, 0xAD69, 0x828F, 0xAD6A, 0x8290, 0xAD6B, 0x8291, + 0xAD6C, 0xB1B8, 0xAD6D, 0xB1B9, 0xAD6E, 0x8292, 0xAD6F, 0x8293, 0xAD70, 0xB1BA, 0xAD71, 0x8294, 0xAD72, 0x8295, 0xAD73, 0xB1BB, + 0xAD74, 0xB1BC, 0xAD75, 0xB1BD, 0xAD76, 0xB1BE, 0xAD77, 0x8296, 0xAD78, 0x8297, 0xAD79, 0x8298, 0xAD7A, 0x8299, 0xAD7B, 0xB1BF, + 0xAD7C, 0xB1C0, 0xAD7D, 0xB1C1, 0xAD7E, 0x829A, 0xAD7F, 0xB1C2, 0xAD80, 0x829B, 0xAD81, 0xB1C3, 0xAD82, 0xB1C4, 0xAD83, 0x829C, + 0xAD84, 0x829D, 0xAD85, 0x829E, 0xAD86, 0x829F, 0xAD87, 0x82A0, 0xAD88, 0xB1C5, 0xAD89, 0xB1C6, 0xAD8A, 0x82A1, 0xAD8B, 0x82A2, + 0xAD8C, 0xB1C7, 0xAD8D, 0x82A3, 0xAD8E, 0x82A4, 0xAD8F, 0x82A5, 0xAD90, 0xB1C8, 0xAD91, 0x82A6, 0xAD92, 0x82A7, 0xAD93, 0x82A8, + 0xAD94, 0x82A9, 0xAD95, 0x82AA, 0xAD96, 0x82AB, 0xAD97, 0x82AC, 0xAD98, 0x82AD, 0xAD99, 0x82AE, 0xAD9A, 0x82AF, 0xAD9B, 0x82B0, + 0xAD9C, 0xB1C9, 0xAD9D, 0xB1CA, 0xAD9E, 0x82B1, 0xAD9F, 0x82B2, 0xADA0, 0x82B3, 0xADA1, 0x82B4, 0xADA2, 0x82B5, 0xADA3, 0x82B6, + 0xADA4, 0xB1CB, 0xADA5, 0x82B7, 0xADA6, 0x82B8, 0xADA7, 0x82B9, 0xADA8, 0x82BA, 0xADA9, 0x82BB, 0xADAA, 0x82BC, 0xADAB, 0x82BD, + 0xADAC, 0x82BE, 0xADAD, 0x82BF, 0xADAE, 0x82C0, 0xADAF, 0x82C1, 0xADB0, 0x82C2, 0xADB1, 0x82C3, 0xADB2, 0x82C4, 0xADB3, 0x82C5, + 0xADB4, 0x82C6, 0xADB5, 0x82C7, 0xADB6, 0x82C8, 0xADB7, 0xB1CC, 0xADB8, 0x82C9, 0xADB9, 0x82CA, 0xADBA, 0x82CB, 0xADBB, 0x82CC, + 0xADBC, 0x82CD, 0xADBD, 0x82CE, 0xADBE, 0x82CF, 0xADBF, 0x82D0, 0xADC0, 0xB1CD, 0xADC1, 0xB1CE, 0xADC2, 0x82D1, 0xADC3, 0x82D2, + 0xADC4, 0xB1CF, 0xADC5, 0x82D3, 0xADC6, 0x82D4, 0xADC7, 0x82D5, 0xADC8, 0xB1D0, 0xADC9, 0x82D6, 0xADCA, 0x82D7, 0xADCB, 0x82D8, + 0xADCC, 0x82D9, 0xADCD, 0x82DA, 0xADCE, 0x82DB, 0xADCF, 0x82DC, 0xADD0, 0xB1D1, 0xADD1, 0xB1D2, 0xADD2, 0x82DD, 0xADD3, 0xB1D3, + 0xADD4, 0x82DE, 0xADD5, 0x82DF, 0xADD6, 0x82E0, 0xADD7, 0x82E1, 0xADD8, 0x82E2, 0xADD9, 0x82E3, 0xADDA, 0x82E4, 0xADDB, 0x82E5, + 0xADDC, 0xB1D4, 0xADDD, 0x82E6, 0xADDE, 0x82E7, 0xADDF, 0x82E8, 0xADE0, 0xB1D5, 0xADE1, 0x82E9, 0xADE2, 0x82EA, 0xADE3, 0x82EB, + 0xADE4, 0xB1D6, 0xADE5, 0x82EC, 0xADE6, 0x82ED, 0xADE7, 0x82EE, 0xADE8, 0x82EF, 0xADE9, 0x82F0, 0xADEA, 0x82F1, 0xADEB, 0x82F2, + 0xADEC, 0x82F3, 0xADED, 0x82F4, 0xADEE, 0x82F5, 0xADEF, 0x82F6, 0xADF0, 0x82F7, 0xADF1, 0x82F8, 0xADF2, 0x82F9, 0xADF3, 0x82FA, + 0xADF4, 0x82FB, 0xADF5, 0x82FC, 0xADF6, 0x82FD, 0xADF7, 0x82FE, 0xADF8, 0xB1D7, 0xADF9, 0xB1D8, 0xADFA, 0x8341, 0xADFB, 0x8342, + 0xADFC, 0xB1D9, 0xADFD, 0x8343, 0xADFE, 0x8344, 0xADFF, 0xB1DA, 0xAE00, 0xB1DB, 0xAE01, 0xB1DC, 0xAE02, 0x8345, 0xAE03, 0x8346, + 0xAE04, 0x8347, 0xAE05, 0x8348, 0xAE06, 0x8349, 0xAE07, 0x834A, 0xAE08, 0xB1DD, 0xAE09, 0xB1DE, 0xAE0A, 0x834B, 0xAE0B, 0xB1DF, + 0xAE0C, 0x834C, 0xAE0D, 0xB1E0, 0xAE0E, 0x834D, 0xAE0F, 0x834E, 0xAE10, 0x834F, 0xAE11, 0x8350, 0xAE12, 0x8351, 0xAE13, 0x8352, + 0xAE14, 0xB1E1, 0xAE15, 0x8353, 0xAE16, 0x8354, 0xAE17, 0x8355, 0xAE18, 0x8356, 0xAE19, 0x8357, 0xAE1A, 0x8358, 0xAE1B, 0x8359, + 0xAE1C, 0x835A, 0xAE1D, 0x8361, 0xAE1E, 0x8362, 0xAE1F, 0x8363, 0xAE20, 0x8364, 0xAE21, 0x8365, 0xAE22, 0x8366, 0xAE23, 0x8367, + 0xAE24, 0x8368, 0xAE25, 0x8369, 0xAE26, 0x836A, 0xAE27, 0x836B, 0xAE28, 0x836C, 0xAE29, 0x836D, 0xAE2A, 0x836E, 0xAE2B, 0x836F, + 0xAE2C, 0x8370, 0xAE2D, 0x8371, 0xAE2E, 0x8372, 0xAE2F, 0x8373, 0xAE30, 0xB1E2, 0xAE31, 0xB1E3, 0xAE32, 0x8374, 0xAE33, 0x8375, + 0xAE34, 0xB1E4, 0xAE35, 0x8376, 0xAE36, 0x8377, 0xAE37, 0xB1E5, 0xAE38, 0xB1E6, 0xAE39, 0x8378, 0xAE3A, 0xB1E7, 0xAE3B, 0x8379, + 0xAE3C, 0x837A, 0xAE3D, 0x8381, 0xAE3E, 0x8382, 0xAE3F, 0x8383, 0xAE40, 0xB1E8, 0xAE41, 0xB1E9, 0xAE42, 0x8384, 0xAE43, 0xB1EA, + 0xAE44, 0x8385, 0xAE45, 0xB1EB, 0xAE46, 0xB1EC, 0xAE47, 0x8386, 0xAE48, 0x8387, 0xAE49, 0x8388, 0xAE4A, 0xB1ED, 0xAE4B, 0x8389, + 0xAE4C, 0xB1EE, 0xAE4D, 0xB1EF, 0xAE4E, 0xB1F0, 0xAE4F, 0x838A, 0xAE50, 0xB1F1, 0xAE51, 0x838B, 0xAE52, 0x838C, 0xAE53, 0x838D, + 0xAE54, 0xB1F2, 0xAE55, 0x838E, 0xAE56, 0xB1F3, 0xAE57, 0x838F, 0xAE58, 0x8390, 0xAE59, 0x8391, 0xAE5A, 0x8392, 0xAE5B, 0x8393, + 0xAE5C, 0xB1F4, 0xAE5D, 0xB1F5, 0xAE5E, 0x8394, 0xAE5F, 0xB1F6, 0xAE60, 0xB1F7, 0xAE61, 0xB1F8, 0xAE62, 0x8395, 0xAE63, 0x8396, + 0xAE64, 0x8397, 0xAE65, 0xB1F9, 0xAE66, 0x8398, 0xAE67, 0x8399, 0xAE68, 0xB1FA, 0xAE69, 0xB1FB, 0xAE6A, 0x839A, 0xAE6B, 0x839B, + 0xAE6C, 0xB1FC, 0xAE6D, 0x839C, 0xAE6E, 0x839D, 0xAE6F, 0x839E, 0xAE70, 0xB1FD, 0xAE71, 0x839F, 0xAE72, 0x83A0, 0xAE73, 0x83A1, + 0xAE74, 0x83A2, 0xAE75, 0x83A3, 0xAE76, 0x83A4, 0xAE77, 0x83A5, 0xAE78, 0xB1FE, 0xAE79, 0xB2A1, 0xAE7A, 0x83A6, 0xAE7B, 0xB2A2, + 0xAE7C, 0xB2A3, 0xAE7D, 0xB2A4, 0xAE7E, 0x83A7, 0xAE7F, 0x83A8, 0xAE80, 0x83A9, 0xAE81, 0x83AA, 0xAE82, 0x83AB, 0xAE83, 0x83AC, + 0xAE84, 0xB2A5, 0xAE85, 0xB2A6, 0xAE86, 0x83AD, 0xAE87, 0x83AE, 0xAE88, 0x83AF, 0xAE89, 0x83B0, 0xAE8A, 0x83B1, 0xAE8B, 0x83B2, + 0xAE8C, 0xB2A7, 0xAE8D, 0x83B3, 0xAE8E, 0x83B4, 0xAE8F, 0x83B5, 0xAE90, 0x83B6, 0xAE91, 0x83B7, 0xAE92, 0x83B8, 0xAE93, 0x83B9, + 0xAE94, 0x83BA, 0xAE95, 0x83BB, 0xAE96, 0x83BC, 0xAE97, 0x83BD, 0xAE98, 0x83BE, 0xAE99, 0x83BF, 0xAE9A, 0x83C0, 0xAE9B, 0x83C1, + 0xAE9C, 0x83C2, 0xAE9D, 0x83C3, 0xAE9E, 0x83C4, 0xAE9F, 0x83C5, 0xAEA0, 0x83C6, 0xAEA1, 0x83C7, 0xAEA2, 0x83C8, 0xAEA3, 0x83C9, + 0xAEA4, 0x83CA, 0xAEA5, 0x83CB, 0xAEA6, 0x83CC, 0xAEA7, 0x83CD, 0xAEA8, 0x83CE, 0xAEA9, 0x83CF, 0xAEAA, 0x83D0, 0xAEAB, 0x83D1, + 0xAEAC, 0x83D2, 0xAEAD, 0x83D3, 0xAEAE, 0x83D4, 0xAEAF, 0x83D5, 0xAEB0, 0x83D6, 0xAEB1, 0x83D7, 0xAEB2, 0x83D8, 0xAEB3, 0x83D9, + 0xAEB4, 0x83DA, 0xAEB5, 0x83DB, 0xAEB6, 0x83DC, 0xAEB7, 0x83DD, 0xAEB8, 0x83DE, 0xAEB9, 0x83DF, 0xAEBA, 0x83E0, 0xAEBB, 0x83E1, + 0xAEBC, 0xB2A8, 0xAEBD, 0xB2A9, 0xAEBE, 0xB2AA, 0xAEBF, 0x83E2, 0xAEC0, 0xB2AB, 0xAEC1, 0x83E3, 0xAEC2, 0x83E4, 0xAEC3, 0x83E5, + 0xAEC4, 0xB2AC, 0xAEC5, 0x83E6, 0xAEC6, 0x83E7, 0xAEC7, 0x83E8, 0xAEC8, 0x83E9, 0xAEC9, 0x83EA, 0xAECA, 0x83EB, 0xAECB, 0x83EC, + 0xAECC, 0xB2AD, 0xAECD, 0xB2AE, 0xAECE, 0x83ED, 0xAECF, 0xB2AF, 0xAED0, 0xB2B0, 0xAED1, 0xB2B1, 0xAED2, 0x83EE, 0xAED3, 0x83EF, + 0xAED4, 0x83F0, 0xAED5, 0x83F1, 0xAED6, 0x83F2, 0xAED7, 0x83F3, 0xAED8, 0xB2B2, 0xAED9, 0xB2B3, 0xAEDA, 0x83F4, 0xAEDB, 0x83F5, + 0xAEDC, 0xB2B4, 0xAEDD, 0x83F6, 0xAEDE, 0x83F7, 0xAEDF, 0x83F8, 0xAEE0, 0x83F9, 0xAEE1, 0x83FA, 0xAEE2, 0x83FB, 0xAEE3, 0x83FC, + 0xAEE4, 0x83FD, 0xAEE5, 0x83FE, 0xAEE6, 0x8441, 0xAEE7, 0x8442, 0xAEE8, 0xB2B5, 0xAEE9, 0x8443, 0xAEEA, 0x8444, 0xAEEB, 0xB2B6, + 0xAEEC, 0x8445, 0xAEED, 0xB2B7, 0xAEEE, 0x8446, 0xAEEF, 0x8447, 0xAEF0, 0x8448, 0xAEF1, 0x8449, 0xAEF2, 0x844A, 0xAEF3, 0x844B, + 0xAEF4, 0xB2B8, 0xAEF5, 0x844C, 0xAEF6, 0x844D, 0xAEF7, 0x844E, 0xAEF8, 0xB2B9, 0xAEF9, 0x844F, 0xAEFA, 0x8450, 0xAEFB, 0x8451, + 0xAEFC, 0xB2BA, 0xAEFD, 0x8452, 0xAEFE, 0x8453, 0xAEFF, 0x8454, 0xAF00, 0x8455, 0xAF01, 0x8456, 0xAF02, 0x8457, 0xAF03, 0x8458, + 0xAF04, 0x8459, 0xAF05, 0x845A, 0xAF06, 0x8461, 0xAF07, 0xB2BB, 0xAF08, 0xB2BC, 0xAF09, 0x8462, 0xAF0A, 0x8463, 0xAF0B, 0x8464, + 0xAF0C, 0x8465, 0xAF0D, 0xB2BD, 0xAF0E, 0x8466, 0xAF0F, 0x8467, 0xAF10, 0xB2BE, 0xAF11, 0x8468, 0xAF12, 0x8469, 0xAF13, 0x846A, + 0xAF14, 0x846B, 0xAF15, 0x846C, 0xAF16, 0x846D, 0xAF17, 0x846E, 0xAF18, 0x846F, 0xAF19, 0x8470, 0xAF1A, 0x8471, 0xAF1B, 0x8472, + 0xAF1C, 0x8473, 0xAF1D, 0x8474, 0xAF1E, 0x8475, 0xAF1F, 0x8476, 0xAF20, 0x8477, 0xAF21, 0x8478, 0xAF22, 0x8479, 0xAF23, 0x847A, + 0xAF24, 0x8481, 0xAF25, 0x8482, 0xAF26, 0x8483, 0xAF27, 0x8484, 0xAF28, 0x8485, 0xAF29, 0x8486, 0xAF2A, 0x8487, 0xAF2B, 0x8488, + 0xAF2C, 0xB2BF, 0xAF2D, 0xB2C0, 0xAF2E, 0x8489, 0xAF2F, 0x848A, 0xAF30, 0xB2C1, 0xAF31, 0x848B, 0xAF32, 0xB2C2, 0xAF33, 0x848C, + 0xAF34, 0xB2C3, 0xAF35, 0x848D, 0xAF36, 0x848E, 0xAF37, 0x848F, 0xAF38, 0x8490, 0xAF39, 0x8491, 0xAF3A, 0x8492, 0xAF3B, 0x8493, + 0xAF3C, 0xB2C4, 0xAF3D, 0xB2C5, 0xAF3E, 0x8494, 0xAF3F, 0xB2C6, 0xAF40, 0x8495, 0xAF41, 0xB2C7, 0xAF42, 0xB2C8, 0xAF43, 0xB2C9, + 0xAF44, 0x8496, 0xAF45, 0x8497, 0xAF46, 0x8498, 0xAF47, 0x8499, 0xAF48, 0xB2CA, 0xAF49, 0xB2CB, 0xAF4A, 0x849A, 0xAF4B, 0x849B, + 0xAF4C, 0x849C, 0xAF4D, 0x849D, 0xAF4E, 0x849E, 0xAF4F, 0x849F, 0xAF50, 0xB2CC, 0xAF51, 0x84A0, 0xAF52, 0x84A1, 0xAF53, 0x84A2, + 0xAF54, 0x84A3, 0xAF55, 0x84A4, 0xAF56, 0x84A5, 0xAF57, 0x84A6, 0xAF58, 0x84A7, 0xAF59, 0x84A8, 0xAF5A, 0x84A9, 0xAF5B, 0x84AA, + 0xAF5C, 0xB2CD, 0xAF5D, 0xB2CE, 0xAF5E, 0x84AB, 0xAF5F, 0x84AC, 0xAF60, 0x84AD, 0xAF61, 0x84AE, 0xAF62, 0x84AF, 0xAF63, 0x84B0, + 0xAF64, 0xB2CF, 0xAF65, 0xB2D0, 0xAF66, 0x84B1, 0xAF67, 0x84B2, 0xAF68, 0x84B3, 0xAF69, 0x84B4, 0xAF6A, 0x84B5, 0xAF6B, 0x84B6, + 0xAF6C, 0x84B7, 0xAF6D, 0x84B8, 0xAF6E, 0x84B9, 0xAF6F, 0x84BA, 0xAF70, 0x84BB, 0xAF71, 0x84BC, 0xAF72, 0x84BD, 0xAF73, 0x84BE, + 0xAF74, 0x84BF, 0xAF75, 0x84C0, 0xAF76, 0x84C1, 0xAF77, 0x84C2, 0xAF78, 0x84C3, 0xAF79, 0xB2D1, 0xAF7A, 0x84C4, 0xAF7B, 0x84C5, + 0xAF7C, 0x84C6, 0xAF7D, 0x84C7, 0xAF7E, 0x84C8, 0xAF7F, 0x84C9, 0xAF80, 0xB2D2, 0xAF81, 0x84CA, 0xAF82, 0x84CB, 0xAF83, 0x84CC, + 0xAF84, 0xB2D3, 0xAF85, 0x84CD, 0xAF86, 0x84CE, 0xAF87, 0x84CF, 0xAF88, 0xB2D4, 0xAF89, 0x84D0, 0xAF8A, 0x84D1, 0xAF8B, 0x84D2, + 0xAF8C, 0x84D3, 0xAF8D, 0x84D4, 0xAF8E, 0x84D5, 0xAF8F, 0x84D6, 0xAF90, 0xB2D5, 0xAF91, 0xB2D6, 0xAF92, 0x84D7, 0xAF93, 0x84D8, + 0xAF94, 0x84D9, 0xAF95, 0xB2D7, 0xAF96, 0x84DA, 0xAF97, 0x84DB, 0xAF98, 0x84DC, 0xAF99, 0x84DD, 0xAF9A, 0x84DE, 0xAF9B, 0x84DF, + 0xAF9C, 0xB2D8, 0xAF9D, 0x84E0, 0xAF9E, 0x84E1, 0xAF9F, 0x84E2, 0xAFA0, 0x84E3, 0xAFA1, 0x84E4, 0xAFA2, 0x84E5, 0xAFA3, 0x84E6, + 0xAFA4, 0x84E7, 0xAFA5, 0x84E8, 0xAFA6, 0x84E9, 0xAFA7, 0x84EA, 0xAFA8, 0x84EB, 0xAFA9, 0x84EC, 0xAFAA, 0x84ED, 0xAFAB, 0x84EE, + 0xAFAC, 0x84EF, 0xAFAD, 0x84F0, 0xAFAE, 0x84F1, 0xAFAF, 0x84F2, 0xAFB0, 0x84F3, 0xAFB1, 0x84F4, 0xAFB2, 0x84F5, 0xAFB3, 0x84F6, + 0xAFB4, 0x84F7, 0xAFB5, 0x84F8, 0xAFB6, 0x84F9, 0xAFB7, 0x84FA, 0xAFB8, 0xB2D9, 0xAFB9, 0xB2DA, 0xAFBA, 0x84FB, 0xAFBB, 0x84FC, + 0xAFBC, 0xB2DB, 0xAFBD, 0x84FD, 0xAFBE, 0x84FE, 0xAFBF, 0x8541, 0xAFC0, 0xB2DC, 0xAFC1, 0x8542, 0xAFC2, 0x8543, 0xAFC3, 0x8544, + 0xAFC4, 0x8545, 0xAFC5, 0x8546, 0xAFC6, 0x8547, 0xAFC7, 0xB2DD, 0xAFC8, 0xB2DE, 0xAFC9, 0xB2DF, 0xAFCA, 0x8548, 0xAFCB, 0xB2E0, + 0xAFCC, 0x8549, 0xAFCD, 0xB2E1, 0xAFCE, 0xB2E2, 0xAFCF, 0x854A, 0xAFD0, 0x854B, 0xAFD1, 0x854C, 0xAFD2, 0x854D, 0xAFD3, 0x854E, + 0xAFD4, 0xB2E3, 0xAFD5, 0x854F, 0xAFD6, 0x8550, 0xAFD7, 0x8551, 0xAFD8, 0x8552, 0xAFD9, 0x8553, 0xAFDA, 0x8554, 0xAFDB, 0x8555, + 0xAFDC, 0xB2E4, 0xAFDD, 0x8556, 0xAFDE, 0x8557, 0xAFDF, 0x8558, 0xAFE0, 0x8559, 0xAFE1, 0x855A, 0xAFE2, 0x8561, 0xAFE3, 0x8562, + 0xAFE4, 0x8563, 0xAFE5, 0x8564, 0xAFE6, 0x8565, 0xAFE7, 0x8566, 0xAFE8, 0xB2E5, 0xAFE9, 0xB2E6, 0xAFEA, 0x8567, 0xAFEB, 0x8568, + 0xAFEC, 0x8569, 0xAFED, 0x856A, 0xAFEE, 0x856B, 0xAFEF, 0x856C, 0xAFF0, 0xB2E7, 0xAFF1, 0xB2E8, 0xAFF2, 0x856D, 0xAFF3, 0x856E, + 0xAFF4, 0xB2E9, 0xAFF5, 0x856F, 0xAFF6, 0x8570, 0xAFF7, 0x8571, 0xAFF8, 0xB2EA, 0xAFF9, 0x8572, 0xAFFA, 0x8573, 0xAFFB, 0x8574, + 0xAFFC, 0x8575, 0xAFFD, 0x8576, 0xAFFE, 0x8577, 0xAFFF, 0x8578, 0xB000, 0xB2EB, 0xB001, 0xB2EC, 0xB002, 0x8579, 0xB003, 0x857A, + 0xB004, 0xB2ED, 0xB005, 0x8581, 0xB006, 0x8582, 0xB007, 0x8583, 0xB008, 0x8584, 0xB009, 0x8585, 0xB00A, 0x8586, 0xB00B, 0x8587, + 0xB00C, 0xB2EE, 0xB00D, 0x8588, 0xB00E, 0x8589, 0xB00F, 0x858A, 0xB010, 0xB2EF, 0xB011, 0x858B, 0xB012, 0x858C, 0xB013, 0x858D, + 0xB014, 0xB2F0, 0xB015, 0x858E, 0xB016, 0x858F, 0xB017, 0x8590, 0xB018, 0x8591, 0xB019, 0x8592, 0xB01A, 0x8593, 0xB01B, 0x8594, + 0xB01C, 0xB2F1, 0xB01D, 0xB2F2, 0xB01E, 0x8595, 0xB01F, 0x8596, 0xB020, 0x8597, 0xB021, 0x8598, 0xB022, 0x8599, 0xB023, 0x859A, + 0xB024, 0x859B, 0xB025, 0x859C, 0xB026, 0x859D, 0xB027, 0x859E, 0xB028, 0xB2F3, 0xB029, 0x859F, 0xB02A, 0x85A0, 0xB02B, 0x85A1, + 0xB02C, 0x85A2, 0xB02D, 0x85A3, 0xB02E, 0x85A4, 0xB02F, 0x85A5, 0xB030, 0x85A6, 0xB031, 0x85A7, 0xB032, 0x85A8, 0xB033, 0x85A9, + 0xB034, 0x85AA, 0xB035, 0x85AB, 0xB036, 0x85AC, 0xB037, 0x85AD, 0xB038, 0x85AE, 0xB039, 0x85AF, 0xB03A, 0x85B0, 0xB03B, 0x85B1, + 0xB03C, 0x85B2, 0xB03D, 0x85B3, 0xB03E, 0x85B4, 0xB03F, 0x85B5, 0xB040, 0x85B6, 0xB041, 0x85B7, 0xB042, 0x85B8, 0xB043, 0x85B9, + 0xB044, 0xB2F4, 0xB045, 0xB2F5, 0xB046, 0x85BA, 0xB047, 0x85BB, 0xB048, 0xB2F6, 0xB049, 0x85BC, 0xB04A, 0xB2F7, 0xB04B, 0x85BD, + 0xB04C, 0xB2F8, 0xB04D, 0x85BE, 0xB04E, 0xB2F9, 0xB04F, 0x85BF, 0xB050, 0x85C0, 0xB051, 0x85C1, 0xB052, 0x85C2, 0xB053, 0xB2FA, + 0xB054, 0xB2FB, 0xB055, 0xB2FC, 0xB056, 0x85C3, 0xB057, 0xB2FD, 0xB058, 0x85C4, 0xB059, 0xB2FE, 0xB05A, 0x85C5, 0xB05B, 0x85C6, + 0xB05C, 0x85C7, 0xB05D, 0xB3A1, 0xB05E, 0x85C8, 0xB05F, 0x85C9, 0xB060, 0x85CA, 0xB061, 0x85CB, 0xB062, 0x85CC, 0xB063, 0x85CD, + 0xB064, 0x85CE, 0xB065, 0x85CF, 0xB066, 0x85D0, 0xB067, 0x85D1, 0xB068, 0x85D2, 0xB069, 0x85D3, 0xB06A, 0x85D4, 0xB06B, 0x85D5, + 0xB06C, 0x85D6, 0xB06D, 0x85D7, 0xB06E, 0x85D8, 0xB06F, 0x85D9, 0xB070, 0x85DA, 0xB071, 0x85DB, 0xB072, 0x85DC, 0xB073, 0x85DD, + 0xB074, 0x85DE, 0xB075, 0x85DF, 0xB076, 0x85E0, 0xB077, 0x85E1, 0xB078, 0x85E2, 0xB079, 0x85E3, 0xB07A, 0x85E4, 0xB07B, 0x85E5, + 0xB07C, 0xB3A2, 0xB07D, 0xB3A3, 0xB07E, 0x85E6, 0xB07F, 0x85E7, 0xB080, 0xB3A4, 0xB081, 0x85E8, 0xB082, 0x85E9, 0xB083, 0x85EA, + 0xB084, 0xB3A5, 0xB085, 0x85EB, 0xB086, 0x85EC, 0xB087, 0x85ED, 0xB088, 0x85EE, 0xB089, 0x85EF, 0xB08A, 0x85F0, 0xB08B, 0x85F1, + 0xB08C, 0xB3A6, 0xB08D, 0xB3A7, 0xB08E, 0x85F2, 0xB08F, 0xB3A8, 0xB090, 0x85F3, 0xB091, 0xB3A9, 0xB092, 0x85F4, 0xB093, 0x85F5, + 0xB094, 0x85F6, 0xB095, 0x85F7, 0xB096, 0x85F8, 0xB097, 0x85F9, 0xB098, 0xB3AA, 0xB099, 0xB3AB, 0xB09A, 0xB3AC, 0xB09B, 0x85FA, + 0xB09C, 0xB3AD, 0xB09D, 0x85FB, 0xB09E, 0x85FC, 0xB09F, 0xB3AE, 0xB0A0, 0xB3AF, 0xB0A1, 0xB3B0, 0xB0A2, 0xB3B1, 0xB0A3, 0x85FD, + 0xB0A4, 0x85FE, 0xB0A5, 0x8641, 0xB0A6, 0x8642, 0xB0A7, 0x8643, 0xB0A8, 0xB3B2, 0xB0A9, 0xB3B3, 0xB0AA, 0x8644, 0xB0AB, 0xB3B4, + 0xB0AC, 0xB3B5, 0xB0AD, 0xB3B6, 0xB0AE, 0xB3B7, 0xB0AF, 0xB3B8, 0xB0B0, 0x8645, 0xB0B1, 0xB3B9, 0xB0B2, 0x8646, 0xB0B3, 0xB3BA, + 0xB0B4, 0xB3BB, 0xB0B5, 0xB3BC, 0xB0B6, 0x8647, 0xB0B7, 0x8648, 0xB0B8, 0xB3BD, 0xB0B9, 0x8649, 0xB0BA, 0x864A, 0xB0BB, 0x864B, + 0xB0BC, 0xB3BE, 0xB0BD, 0x864C, 0xB0BE, 0x864D, 0xB0BF, 0x864E, 0xB0C0, 0x864F, 0xB0C1, 0x8650, 0xB0C2, 0x8651, 0xB0C3, 0x8652, + 0xB0C4, 0xB3BF, 0xB0C5, 0xB3C0, 0xB0C6, 0x8653, 0xB0C7, 0xB3C1, 0xB0C8, 0xB3C2, 0xB0C9, 0xB3C3, 0xB0CA, 0x8654, 0xB0CB, 0x8655, + 0xB0CC, 0x8656, 0xB0CD, 0x8657, 0xB0CE, 0x8658, 0xB0CF, 0x8659, 0xB0D0, 0xB3C4, 0xB0D1, 0xB3C5, 0xB0D2, 0x865A, 0xB0D3, 0x8661, + 0xB0D4, 0xB3C6, 0xB0D5, 0x8662, 0xB0D6, 0x8663, 0xB0D7, 0x8664, 0xB0D8, 0xB3C7, 0xB0D9, 0x8665, 0xB0DA, 0x8666, 0xB0DB, 0x8667, + 0xB0DC, 0x8668, 0xB0DD, 0x8669, 0xB0DE, 0x866A, 0xB0DF, 0x866B, 0xB0E0, 0xB3C8, 0xB0E1, 0x866C, 0xB0E2, 0x866D, 0xB0E3, 0x866E, + 0xB0E4, 0x866F, 0xB0E5, 0xB3C9, 0xB0E6, 0x8670, 0xB0E7, 0x8671, 0xB0E8, 0x8672, 0xB0E9, 0x8673, 0xB0EA, 0x8674, 0xB0EB, 0x8675, + 0xB0EC, 0x8676, 0xB0ED, 0x8677, 0xB0EE, 0x8678, 0xB0EF, 0x8679, 0xB0F0, 0x867A, 0xB0F1, 0x8681, 0xB0F2, 0x8682, 0xB0F3, 0x8683, + 0xB0F4, 0x8684, 0xB0F5, 0x8685, 0xB0F6, 0x8686, 0xB0F7, 0x8687, 0xB0F8, 0x8688, 0xB0F9, 0x8689, 0xB0FA, 0x868A, 0xB0FB, 0x868B, + 0xB0FC, 0x868C, 0xB0FD, 0x868D, 0xB0FE, 0x868E, 0xB0FF, 0x868F, 0xB100, 0x8690, 0xB101, 0x8691, 0xB102, 0x8692, 0xB103, 0x8693, + 0xB104, 0x8694, 0xB105, 0x8695, 0xB106, 0x8696, 0xB107, 0x8697, 0xB108, 0xB3CA, 0xB109, 0xB3CB, 0xB10A, 0x8698, 0xB10B, 0xB3CC, + 0xB10C, 0xB3CD, 0xB10D, 0x8699, 0xB10E, 0x869A, 0xB10F, 0x869B, 0xB110, 0xB3CE, 0xB111, 0x869C, 0xB112, 0xB3CF, 0xB113, 0xB3D0, + 0xB114, 0x869D, 0xB115, 0x869E, 0xB116, 0x869F, 0xB117, 0x86A0, 0xB118, 0xB3D1, 0xB119, 0xB3D2, 0xB11A, 0x86A1, 0xB11B, 0xB3D3, + 0xB11C, 0xB3D4, 0xB11D, 0xB3D5, 0xB11E, 0x86A2, 0xB11F, 0x86A3, 0xB120, 0x86A4, 0xB121, 0x86A5, 0xB122, 0x86A6, 0xB123, 0xB3D6, + 0xB124, 0xB3D7, 0xB125, 0xB3D8, 0xB126, 0x86A7, 0xB127, 0x86A8, 0xB128, 0xB3D9, 0xB129, 0x86A9, 0xB12A, 0x86AA, 0xB12B, 0x86AB, + 0xB12C, 0xB3DA, 0xB12D, 0x86AC, 0xB12E, 0x86AD, 0xB12F, 0x86AE, 0xB130, 0x86AF, 0xB131, 0x86B0, 0xB132, 0x86B1, 0xB133, 0x86B2, + 0xB134, 0xB3DB, 0xB135, 0xB3DC, 0xB136, 0x86B3, 0xB137, 0xB3DD, 0xB138, 0xB3DE, 0xB139, 0xB3DF, 0xB13A, 0x86B4, 0xB13B, 0x86B5, + 0xB13C, 0x86B6, 0xB13D, 0x86B7, 0xB13E, 0x86B8, 0xB13F, 0x86B9, 0xB140, 0xB3E0, 0xB141, 0xB3E1, 0xB142, 0x86BA, 0xB143, 0x86BB, + 0xB144, 0xB3E2, 0xB145, 0x86BC, 0xB146, 0x86BD, 0xB147, 0x86BE, 0xB148, 0xB3E3, 0xB149, 0x86BF, 0xB14A, 0x86C0, 0xB14B, 0x86C1, + 0xB14C, 0x86C2, 0xB14D, 0x86C3, 0xB14E, 0x86C4, 0xB14F, 0x86C5, 0xB150, 0xB3E4, 0xB151, 0xB3E5, 0xB152, 0x86C6, 0xB153, 0x86C7, + 0xB154, 0xB3E6, 0xB155, 0xB3E7, 0xB156, 0x86C8, 0xB157, 0x86C9, 0xB158, 0xB3E8, 0xB159, 0x86CA, 0xB15A, 0x86CB, 0xB15B, 0x86CC, + 0xB15C, 0xB3E9, 0xB15D, 0x86CD, 0xB15E, 0x86CE, 0xB15F, 0x86CF, 0xB160, 0xB3EA, 0xB161, 0x86D0, 0xB162, 0x86D1, 0xB163, 0x86D2, + 0xB164, 0x86D3, 0xB165, 0x86D4, 0xB166, 0x86D5, 0xB167, 0x86D6, 0xB168, 0x86D7, 0xB169, 0x86D8, 0xB16A, 0x86D9, 0xB16B, 0x86DA, + 0xB16C, 0x86DB, 0xB16D, 0x86DC, 0xB16E, 0x86DD, 0xB16F, 0x86DE, 0xB170, 0x86DF, 0xB171, 0x86E0, 0xB172, 0x86E1, 0xB173, 0x86E2, + 0xB174, 0x86E3, 0xB175, 0x86E4, 0xB176, 0x86E5, 0xB177, 0x86E6, 0xB178, 0xB3EB, 0xB179, 0xB3EC, 0xB17A, 0x86E7, 0xB17B, 0x86E8, + 0xB17C, 0xB3ED, 0xB17D, 0x86E9, 0xB17E, 0x86EA, 0xB17F, 0x86EB, 0xB180, 0xB3EE, 0xB181, 0x86EC, 0xB182, 0xB3EF, 0xB183, 0x86ED, + 0xB184, 0x86EE, 0xB185, 0x86EF, 0xB186, 0x86F0, 0xB187, 0x86F1, 0xB188, 0xB3F0, 0xB189, 0xB3F1, 0xB18A, 0x86F2, 0xB18B, 0xB3F2, + 0xB18C, 0x86F3, 0xB18D, 0xB3F3, 0xB18E, 0x86F4, 0xB18F, 0x86F5, 0xB190, 0x86F6, 0xB191, 0x86F7, 0xB192, 0xB3F4, 0xB193, 0xB3F5, + 0xB194, 0xB3F6, 0xB195, 0x86F8, 0xB196, 0x86F9, 0xB197, 0x86FA, 0xB198, 0xB3F7, 0xB199, 0x86FB, 0xB19A, 0x86FC, 0xB19B, 0x86FD, + 0xB19C, 0xB3F8, 0xB19D, 0x86FE, 0xB19E, 0x8741, 0xB19F, 0x8742, 0xB1A0, 0x8743, 0xB1A1, 0x8744, 0xB1A2, 0x8745, 0xB1A3, 0x8746, + 0xB1A4, 0x8747, 0xB1A5, 0x8748, 0xB1A6, 0x8749, 0xB1A7, 0x874A, 0xB1A8, 0xB3F9, 0xB1A9, 0x874B, 0xB1AA, 0x874C, 0xB1AB, 0x874D, + 0xB1AC, 0x874E, 0xB1AD, 0x874F, 0xB1AE, 0x8750, 0xB1AF, 0x8751, 0xB1B0, 0x8752, 0xB1B1, 0x8753, 0xB1B2, 0x8754, 0xB1B3, 0x8755, + 0xB1B4, 0x8756, 0xB1B5, 0x8757, 0xB1B6, 0x8758, 0xB1B7, 0x8759, 0xB1B8, 0x875A, 0xB1B9, 0x8761, 0xB1BA, 0x8762, 0xB1BB, 0x8763, + 0xB1BC, 0x8764, 0xB1BD, 0x8765, 0xB1BE, 0x8766, 0xB1BF, 0x8767, 0xB1C0, 0x8768, 0xB1C1, 0x8769, 0xB1C2, 0x876A, 0xB1C3, 0x876B, + 0xB1C4, 0x876C, 0xB1C5, 0x876D, 0xB1C6, 0x876E, 0xB1C7, 0x876F, 0xB1C8, 0x8770, 0xB1C9, 0x8771, 0xB1CA, 0x8772, 0xB1CB, 0x8773, + 0xB1CC, 0xB3FA, 0xB1CD, 0x8774, 0xB1CE, 0x8775, 0xB1CF, 0x8776, 0xB1D0, 0xB3FB, 0xB1D1, 0x8777, 0xB1D2, 0x8778, 0xB1D3, 0x8779, + 0xB1D4, 0xB3FC, 0xB1D5, 0x877A, 0xB1D6, 0x8781, 0xB1D7, 0x8782, 0xB1D8, 0x8783, 0xB1D9, 0x8784, 0xB1DA, 0x8785, 0xB1DB, 0x8786, + 0xB1DC, 0xB3FD, 0xB1DD, 0xB3FE, 0xB1DE, 0x8787, 0xB1DF, 0xB4A1, 0xB1E0, 0x8788, 0xB1E1, 0x8789, 0xB1E2, 0x878A, 0xB1E3, 0x878B, + 0xB1E4, 0x878C, 0xB1E5, 0x878D, 0xB1E6, 0x878E, 0xB1E7, 0x878F, 0xB1E8, 0xB4A2, 0xB1E9, 0xB4A3, 0xB1EA, 0x8790, 0xB1EB, 0x8791, + 0xB1EC, 0xB4A4, 0xB1ED, 0x8792, 0xB1EE, 0x8793, 0xB1EF, 0x8794, 0xB1F0, 0xB4A5, 0xB1F1, 0x8795, 0xB1F2, 0x8796, 0xB1F3, 0x8797, + 0xB1F4, 0x8798, 0xB1F5, 0x8799, 0xB1F6, 0x879A, 0xB1F7, 0x879B, 0xB1F8, 0x879C, 0xB1F9, 0xB4A6, 0xB1FA, 0x879D, 0xB1FB, 0xB4A7, + 0xB1FC, 0x879E, 0xB1FD, 0xB4A8, 0xB1FE, 0x879F, 0xB1FF, 0x87A0, 0xB200, 0x87A1, 0xB201, 0x87A2, 0xB202, 0x87A3, 0xB203, 0x87A4, + 0xB204, 0xB4A9, 0xB205, 0xB4AA, 0xB206, 0x87A5, 0xB207, 0x87A6, 0xB208, 0xB4AB, 0xB209, 0x87A7, 0xB20A, 0x87A8, 0xB20B, 0xB4AC, + 0xB20C, 0xB4AD, 0xB20D, 0x87A9, 0xB20E, 0x87AA, 0xB20F, 0x87AB, 0xB210, 0x87AC, 0xB211, 0x87AD, 0xB212, 0x87AE, 0xB213, 0x87AF, + 0xB214, 0xB4AE, 0xB215, 0xB4AF, 0xB216, 0x87B0, 0xB217, 0xB4B0, 0xB218, 0x87B1, 0xB219, 0xB4B1, 0xB21A, 0x87B2, 0xB21B, 0x87B3, + 0xB21C, 0x87B4, 0xB21D, 0x87B5, 0xB21E, 0x87B6, 0xB21F, 0x87B7, 0xB220, 0xB4B2, 0xB221, 0x87B8, 0xB222, 0x87B9, 0xB223, 0x87BA, + 0xB224, 0x87BB, 0xB225, 0x87BC, 0xB226, 0x87BD, 0xB227, 0x87BE, 0xB228, 0x87BF, 0xB229, 0x87C0, 0xB22A, 0x87C1, 0xB22B, 0x87C2, + 0xB22C, 0x87C3, 0xB22D, 0x87C4, 0xB22E, 0x87C5, 0xB22F, 0x87C6, 0xB230, 0x87C7, 0xB231, 0x87C8, 0xB232, 0x87C9, 0xB233, 0x87CA, + 0xB234, 0xB4B3, 0xB235, 0x87CB, 0xB236, 0x87CC, 0xB237, 0x87CD, 0xB238, 0x87CE, 0xB239, 0x87CF, 0xB23A, 0x87D0, 0xB23B, 0x87D1, + 0xB23C, 0xB4B4, 0xB23D, 0x87D2, 0xB23E, 0x87D3, 0xB23F, 0x87D4, 0xB240, 0x87D5, 0xB241, 0x87D6, 0xB242, 0x87D7, 0xB243, 0x87D8, + 0xB244, 0x87D9, 0xB245, 0x87DA, 0xB246, 0x87DB, 0xB247, 0x87DC, 0xB248, 0x87DD, 0xB249, 0x87DE, 0xB24A, 0x87DF, 0xB24B, 0x87E0, + 0xB24C, 0x87E1, 0xB24D, 0x87E2, 0xB24E, 0x87E3, 0xB24F, 0x87E4, 0xB250, 0x87E5, 0xB251, 0x87E6, 0xB252, 0x87E7, 0xB253, 0x87E8, + 0xB254, 0x87E9, 0xB255, 0x87EA, 0xB256, 0x87EB, 0xB257, 0x87EC, 0xB258, 0xB4B5, 0xB259, 0x87ED, 0xB25A, 0x87EE, 0xB25B, 0x87EF, + 0xB25C, 0xB4B6, 0xB25D, 0x87F0, 0xB25E, 0x87F1, 0xB25F, 0x87F2, 0xB260, 0xB4B7, 0xB261, 0x87F3, 0xB262, 0x87F4, 0xB263, 0x87F5, + 0xB264, 0x87F6, 0xB265, 0x87F7, 0xB266, 0x87F8, 0xB267, 0x87F9, 0xB268, 0xB4B8, 0xB269, 0xB4B9, 0xB26A, 0x87FA, 0xB26B, 0x87FB, + 0xB26C, 0x87FC, 0xB26D, 0x87FD, 0xB26E, 0x87FE, 0xB26F, 0x8841, 0xB270, 0x8842, 0xB271, 0x8843, 0xB272, 0x8844, 0xB273, 0x8845, + 0xB274, 0xB4BA, 0xB275, 0xB4BB, 0xB276, 0x8846, 0xB277, 0x8847, 0xB278, 0x8848, 0xB279, 0x8849, 0xB27A, 0x884A, 0xB27B, 0x884B, + 0xB27C, 0xB4BC, 0xB27D, 0x884C, 0xB27E, 0x884D, 0xB27F, 0x884E, 0xB280, 0x884F, 0xB281, 0x8850, 0xB282, 0x8851, 0xB283, 0x8852, + 0xB284, 0xB4BD, 0xB285, 0xB4BE, 0xB286, 0x8853, 0xB287, 0x8854, 0xB288, 0x8855, 0xB289, 0xB4BF, 0xB28A, 0x8856, 0xB28B, 0x8857, + 0xB28C, 0x8858, 0xB28D, 0x8859, 0xB28E, 0x885A, 0xB28F, 0x8861, 0xB290, 0xB4C0, 0xB291, 0xB4C1, 0xB292, 0x8862, 0xB293, 0x8863, + 0xB294, 0xB4C2, 0xB295, 0x8864, 0xB296, 0x8865, 0xB297, 0x8866, 0xB298, 0xB4C3, 0xB299, 0xB4C4, 0xB29A, 0xB4C5, 0xB29B, 0x8867, + 0xB29C, 0x8868, 0xB29D, 0x8869, 0xB29E, 0x886A, 0xB29F, 0x886B, 0xB2A0, 0xB4C6, 0xB2A1, 0xB4C7, 0xB2A2, 0x886C, 0xB2A3, 0xB4C8, + 0xB2A4, 0x886D, 0xB2A5, 0xB4C9, 0xB2A6, 0xB4CA, 0xB2A7, 0x886E, 0xB2A8, 0x886F, 0xB2A9, 0x8870, 0xB2AA, 0xB4CB, 0xB2AB, 0x8871, + 0xB2AC, 0xB4CC, 0xB2AD, 0x8872, 0xB2AE, 0x8873, 0xB2AF, 0x8874, 0xB2B0, 0xB4CD, 0xB2B1, 0x8875, 0xB2B2, 0x8876, 0xB2B3, 0x8877, + 0xB2B4, 0xB4CE, 0xB2B5, 0x8878, 0xB2B6, 0x8879, 0xB2B7, 0x887A, 0xB2B8, 0x8881, 0xB2B9, 0x8882, 0xB2BA, 0x8883, 0xB2BB, 0x8884, + 0xB2BC, 0x8885, 0xB2BD, 0x8886, 0xB2BE, 0x8887, 0xB2BF, 0x8888, 0xB2C0, 0x8889, 0xB2C1, 0x888A, 0xB2C2, 0x888B, 0xB2C3, 0x888C, + 0xB2C4, 0x888D, 0xB2C5, 0x888E, 0xB2C6, 0x888F, 0xB2C7, 0x8890, 0xB2C8, 0xB4CF, 0xB2C9, 0xB4D0, 0xB2CA, 0x8891, 0xB2CB, 0x8892, + 0xB2CC, 0xB4D1, 0xB2CD, 0x8893, 0xB2CE, 0x8894, 0xB2CF, 0x8895, 0xB2D0, 0xB4D2, 0xB2D1, 0x8896, 0xB2D2, 0xB4D3, 0xB2D3, 0x8897, + 0xB2D4, 0x8898, 0xB2D5, 0x8899, 0xB2D6, 0x889A, 0xB2D7, 0x889B, 0xB2D8, 0xB4D4, 0xB2D9, 0xB4D5, 0xB2DA, 0x889C, 0xB2DB, 0xB4D6, + 0xB2DC, 0x889D, 0xB2DD, 0xB4D7, 0xB2DE, 0x889E, 0xB2DF, 0x889F, 0xB2E0, 0x88A0, 0xB2E1, 0x88A1, 0xB2E2, 0xB4D8, 0xB2E3, 0x88A2, + 0xB2E4, 0xB4D9, 0xB2E5, 0xB4DA, 0xB2E6, 0xB4DB, 0xB2E7, 0x88A3, 0xB2E8, 0xB4DC, 0xB2E9, 0x88A4, 0xB2EA, 0x88A5, 0xB2EB, 0xB4DD, + 0xB2EC, 0xB4DE, 0xB2ED, 0xB4DF, 0xB2EE, 0xB4E0, 0xB2EF, 0xB4E1, 0xB2F0, 0x88A6, 0xB2F1, 0x88A7, 0xB2F2, 0x88A8, 0xB2F3, 0xB4E2, + 0xB2F4, 0xB4E3, 0xB2F5, 0xB4E4, 0xB2F6, 0x88A9, 0xB2F7, 0xB4E5, 0xB2F8, 0xB4E6, 0xB2F9, 0xB4E7, 0xB2FA, 0xB4E8, 0xB2FB, 0xB4E9, + 0xB2FC, 0x88AA, 0xB2FD, 0x88AB, 0xB2FE, 0x88AC, 0xB2FF, 0xB4EA, 0xB300, 0xB4EB, 0xB301, 0xB4EC, 0xB302, 0x88AD, 0xB303, 0x88AE, + 0xB304, 0xB4ED, 0xB305, 0x88AF, 0xB306, 0x88B0, 0xB307, 0x88B1, 0xB308, 0xB4EE, 0xB309, 0x88B2, 0xB30A, 0x88B3, 0xB30B, 0x88B4, + 0xB30C, 0x88B5, 0xB30D, 0x88B6, 0xB30E, 0x88B7, 0xB30F, 0x88B8, 0xB310, 0xB4EF, 0xB311, 0xB4F0, 0xB312, 0x88B9, 0xB313, 0xB4F1, + 0xB314, 0xB4F2, 0xB315, 0xB4F3, 0xB316, 0x88BA, 0xB317, 0x88BB, 0xB318, 0x88BC, 0xB319, 0x88BD, 0xB31A, 0x88BE, 0xB31B, 0x88BF, + 0xB31C, 0xB4F4, 0xB31D, 0x88C0, 0xB31E, 0x88C1, 0xB31F, 0x88C2, 0xB320, 0x88C3, 0xB321, 0x88C4, 0xB322, 0x88C5, 0xB323, 0x88C6, + 0xB324, 0x88C7, 0xB325, 0x88C8, 0xB326, 0x88C9, 0xB327, 0x88CA, 0xB328, 0x88CB, 0xB329, 0x88CC, 0xB32A, 0x88CD, 0xB32B, 0x88CE, + 0xB32C, 0x88CF, 0xB32D, 0x88D0, 0xB32E, 0x88D1, 0xB32F, 0x88D2, 0xB330, 0x88D3, 0xB331, 0x88D4, 0xB332, 0x88D5, 0xB333, 0x88D6, + 0xB334, 0x88D7, 0xB335, 0x88D8, 0xB336, 0x88D9, 0xB337, 0x88DA, 0xB338, 0x88DB, 0xB339, 0x88DC, 0xB33A, 0x88DD, 0xB33B, 0x88DE, + 0xB33C, 0x88DF, 0xB33D, 0x88E0, 0xB33E, 0x88E1, 0xB33F, 0x88E2, 0xB340, 0x88E3, 0xB341, 0x88E4, 0xB342, 0x88E5, 0xB343, 0x88E6, + 0xB344, 0x88E7, 0xB345, 0x88E8, 0xB346, 0x88E9, 0xB347, 0x88EA, 0xB348, 0x88EB, 0xB349, 0x88EC, 0xB34A, 0x88ED, 0xB34B, 0x88EE, + 0xB34C, 0x88EF, 0xB34D, 0x88F0, 0xB34E, 0x88F1, 0xB34F, 0x88F2, 0xB350, 0x88F3, 0xB351, 0x88F4, 0xB352, 0x88F5, 0xB353, 0x88F6, + 0xB354, 0xB4F5, 0xB355, 0xB4F6, 0xB356, 0xB4F7, 0xB357, 0x88F7, 0xB358, 0xB4F8, 0xB359, 0x88F8, 0xB35A, 0x88F9, 0xB35B, 0xB4F9, + 0xB35C, 0xB4FA, 0xB35D, 0x88FA, 0xB35E, 0xB4FB, 0xB35F, 0xB4FC, 0xB360, 0x88FB, 0xB361, 0x88FC, 0xB362, 0x88FD, 0xB363, 0x88FE, + 0xB364, 0xB4FD, 0xB365, 0xB4FE, 0xB366, 0x8941, 0xB367, 0xB5A1, 0xB368, 0x8942, 0xB369, 0xB5A2, 0xB36A, 0x8943, 0xB36B, 0xB5A3, + 0xB36C, 0x8944, 0xB36D, 0x8945, 0xB36E, 0xB5A4, 0xB36F, 0x8946, 0xB370, 0xB5A5, 0xB371, 0xB5A6, 0xB372, 0x8947, 0xB373, 0x8948, + 0xB374, 0xB5A7, 0xB375, 0x8949, 0xB376, 0x894A, 0xB377, 0x894B, 0xB378, 0xB5A8, 0xB379, 0x894C, 0xB37A, 0x894D, 0xB37B, 0x894E, + 0xB37C, 0x894F, 0xB37D, 0x8950, 0xB37E, 0x8951, 0xB37F, 0x8952, 0xB380, 0xB5A9, 0xB381, 0xB5AA, 0xB382, 0x8953, 0xB383, 0xB5AB, + 0xB384, 0xB5AC, 0xB385, 0xB5AD, 0xB386, 0x8954, 0xB387, 0x8955, 0xB388, 0x8956, 0xB389, 0x8957, 0xB38A, 0x8958, 0xB38B, 0x8959, + 0xB38C, 0xB5AE, 0xB38D, 0x895A, 0xB38E, 0x8961, 0xB38F, 0x8962, 0xB390, 0xB5AF, 0xB391, 0x8963, 0xB392, 0x8964, 0xB393, 0x8965, + 0xB394, 0xB5B0, 0xB395, 0x8966, 0xB396, 0x8967, 0xB397, 0x8968, 0xB398, 0x8969, 0xB399, 0x896A, 0xB39A, 0x896B, 0xB39B, 0x896C, + 0xB39C, 0x896D, 0xB39D, 0x896E, 0xB39E, 0x896F, 0xB39F, 0x8970, 0xB3A0, 0xB5B1, 0xB3A1, 0xB5B2, 0xB3A2, 0x8971, 0xB3A3, 0x8972, + 0xB3A4, 0x8973, 0xB3A5, 0x8974, 0xB3A6, 0x8975, 0xB3A7, 0x8976, 0xB3A8, 0xB5B3, 0xB3A9, 0x8977, 0xB3AA, 0x8978, 0xB3AB, 0x8979, + 0xB3AC, 0xB5B4, 0xB3AD, 0x897A, 0xB3AE, 0x8981, 0xB3AF, 0x8982, 0xB3B0, 0x8983, 0xB3B1, 0x8984, 0xB3B2, 0x8985, 0xB3B3, 0x8986, + 0xB3B4, 0x8987, 0xB3B5, 0x8988, 0xB3B6, 0x8989, 0xB3B7, 0x898A, 0xB3B8, 0x898B, 0xB3B9, 0x898C, 0xB3BA, 0x898D, 0xB3BB, 0x898E, + 0xB3BC, 0x898F, 0xB3BD, 0x8990, 0xB3BE, 0x8991, 0xB3BF, 0x8992, 0xB3C0, 0x8993, 0xB3C1, 0x8994, 0xB3C2, 0x8995, 0xB3C3, 0x8996, + 0xB3C4, 0xB5B5, 0xB3C5, 0xB5B6, 0xB3C6, 0x8997, 0xB3C7, 0x8998, 0xB3C8, 0xB5B7, 0xB3C9, 0x8999, 0xB3CA, 0x899A, 0xB3CB, 0xB5B8, + 0xB3CC, 0xB5B9, 0xB3CD, 0x899B, 0xB3CE, 0xB5BA, 0xB3CF, 0x899C, 0xB3D0, 0xB5BB, 0xB3D1, 0x899D, 0xB3D2, 0x899E, 0xB3D3, 0x899F, + 0xB3D4, 0xB5BC, 0xB3D5, 0xB5BD, 0xB3D6, 0x89A0, 0xB3D7, 0xB5BE, 0xB3D8, 0x89A1, 0xB3D9, 0xB5BF, 0xB3DA, 0x89A2, 0xB3DB, 0xB5C0, + 0xB3DC, 0x89A3, 0xB3DD, 0xB5C1, 0xB3DE, 0x89A4, 0xB3DF, 0x89A5, 0xB3E0, 0xB5C2, 0xB3E1, 0x89A6, 0xB3E2, 0x89A7, 0xB3E3, 0x89A8, + 0xB3E4, 0xB5C3, 0xB3E5, 0x89A9, 0xB3E6, 0x89AA, 0xB3E7, 0x89AB, 0xB3E8, 0xB5C4, 0xB3E9, 0x89AC, 0xB3EA, 0x89AD, 0xB3EB, 0x89AE, + 0xB3EC, 0x89AF, 0xB3ED, 0x89B0, 0xB3EE, 0x89B1, 0xB3EF, 0x89B2, 0xB3F0, 0x89B3, 0xB3F1, 0x89B4, 0xB3F2, 0x89B5, 0xB3F3, 0x89B6, + 0xB3F4, 0x89B7, 0xB3F5, 0x89B8, 0xB3F6, 0x89B9, 0xB3F7, 0x89BA, 0xB3F8, 0x89BB, 0xB3F9, 0x89BC, 0xB3FA, 0x89BD, 0xB3FB, 0x89BE, + 0xB3FC, 0xB5C5, 0xB3FD, 0x89BF, 0xB3FE, 0x89C0, 0xB3FF, 0x89C1, 0xB400, 0x89C2, 0xB401, 0x89C3, 0xB402, 0x89C4, 0xB403, 0x89C5, + 0xB404, 0x89C6, 0xB405, 0x89C7, 0xB406, 0x89C8, 0xB407, 0x89C9, 0xB408, 0x89CA, 0xB409, 0x89CB, 0xB40A, 0x89CC, 0xB40B, 0x89CD, + 0xB40C, 0x89CE, 0xB40D, 0x89CF, 0xB40E, 0x89D0, 0xB40F, 0x89D1, 0xB410, 0xB5C6, 0xB411, 0x89D2, 0xB412, 0x89D3, 0xB413, 0x89D4, + 0xB414, 0x89D5, 0xB415, 0x89D6, 0xB416, 0x89D7, 0xB417, 0x89D8, 0xB418, 0xB5C7, 0xB419, 0x89D9, 0xB41A, 0x89DA, 0xB41B, 0x89DB, + 0xB41C, 0xB5C8, 0xB41D, 0x89DC, 0xB41E, 0x89DD, 0xB41F, 0x89DE, 0xB420, 0xB5C9, 0xB421, 0x89DF, 0xB422, 0x89E0, 0xB423, 0x89E1, + 0xB424, 0x89E2, 0xB425, 0x89E3, 0xB426, 0x89E4, 0xB427, 0x89E5, 0xB428, 0xB5CA, 0xB429, 0xB5CB, 0xB42A, 0x89E6, 0xB42B, 0xB5CC, + 0xB42C, 0x89E7, 0xB42D, 0x89E8, 0xB42E, 0x89E9, 0xB42F, 0x89EA, 0xB430, 0x89EB, 0xB431, 0x89EC, 0xB432, 0x89ED, 0xB433, 0x89EE, + 0xB434, 0xB5CD, 0xB435, 0x89EF, 0xB436, 0x89F0, 0xB437, 0x89F1, 0xB438, 0x89F2, 0xB439, 0x89F3, 0xB43A, 0x89F4, 0xB43B, 0x89F5, + 0xB43C, 0x89F6, 0xB43D, 0x89F7, 0xB43E, 0x89F8, 0xB43F, 0x89F9, 0xB440, 0x89FA, 0xB441, 0x89FB, 0xB442, 0x89FC, 0xB443, 0x89FD, + 0xB444, 0x89FE, 0xB445, 0x8A41, 0xB446, 0x8A42, 0xB447, 0x8A43, 0xB448, 0x8A44, 0xB449, 0x8A45, 0xB44A, 0x8A46, 0xB44B, 0x8A47, + 0xB44C, 0x8A48, 0xB44D, 0x8A49, 0xB44E, 0x8A4A, 0xB44F, 0x8A4B, 0xB450, 0xB5CE, 0xB451, 0xB5CF, 0xB452, 0x8A4C, 0xB453, 0x8A4D, + 0xB454, 0xB5D0, 0xB455, 0x8A4E, 0xB456, 0x8A4F, 0xB457, 0x8A50, 0xB458, 0xB5D1, 0xB459, 0x8A51, 0xB45A, 0x8A52, 0xB45B, 0x8A53, + 0xB45C, 0x8A54, 0xB45D, 0x8A55, 0xB45E, 0x8A56, 0xB45F, 0x8A57, 0xB460, 0xB5D2, 0xB461, 0xB5D3, 0xB462, 0x8A58, 0xB463, 0xB5D4, + 0xB464, 0x8A59, 0xB465, 0xB5D5, 0xB466, 0x8A5A, 0xB467, 0x8A61, 0xB468, 0x8A62, 0xB469, 0x8A63, 0xB46A, 0x8A64, 0xB46B, 0x8A65, + 0xB46C, 0xB5D6, 0xB46D, 0x8A66, 0xB46E, 0x8A67, 0xB46F, 0x8A68, 0xB470, 0x8A69, 0xB471, 0x8A6A, 0xB472, 0x8A6B, 0xB473, 0x8A6C, + 0xB474, 0x8A6D, 0xB475, 0x8A6E, 0xB476, 0x8A6F, 0xB477, 0x8A70, 0xB478, 0x8A71, 0xB479, 0x8A72, 0xB47A, 0x8A73, 0xB47B, 0x8A74, + 0xB47C, 0x8A75, 0xB47D, 0x8A76, 0xB47E, 0x8A77, 0xB47F, 0x8A78, 0xB480, 0xB5D7, 0xB481, 0x8A79, 0xB482, 0x8A7A, 0xB483, 0x8A81, + 0xB484, 0x8A82, 0xB485, 0x8A83, 0xB486, 0x8A84, 0xB487, 0x8A85, 0xB488, 0xB5D8, 0xB489, 0x8A86, 0xB48A, 0x8A87, 0xB48B, 0x8A88, + 0xB48C, 0x8A89, 0xB48D, 0x8A8A, 0xB48E, 0x8A8B, 0xB48F, 0x8A8C, 0xB490, 0x8A8D, 0xB491, 0x8A8E, 0xB492, 0x8A8F, 0xB493, 0x8A90, + 0xB494, 0x8A91, 0xB495, 0x8A92, 0xB496, 0x8A93, 0xB497, 0x8A94, 0xB498, 0x8A95, 0xB499, 0x8A96, 0xB49A, 0x8A97, 0xB49B, 0x8A98, + 0xB49C, 0x8A99, 0xB49D, 0xB5D9, 0xB49E, 0x8A9A, 0xB49F, 0x8A9B, 0xB4A0, 0x8A9C, 0xB4A1, 0x8A9D, 0xB4A2, 0x8A9E, 0xB4A3, 0x8A9F, + 0xB4A4, 0xB5DA, 0xB4A5, 0x8AA0, 0xB4A6, 0x8AA1, 0xB4A7, 0x8AA2, 0xB4A8, 0xB5DB, 0xB4A9, 0x8AA3, 0xB4AA, 0x8AA4, 0xB4AB, 0x8AA5, + 0xB4AC, 0xB5DC, 0xB4AD, 0x8AA6, 0xB4AE, 0x8AA7, 0xB4AF, 0x8AA8, 0xB4B0, 0x8AA9, 0xB4B1, 0x8AAA, 0xB4B2, 0x8AAB, 0xB4B3, 0x8AAC, + 0xB4B4, 0x8AAD, 0xB4B5, 0xB5DD, 0xB4B6, 0x8AAE, 0xB4B7, 0xB5DE, 0xB4B8, 0x8AAF, 0xB4B9, 0xB5DF, 0xB4BA, 0x8AB0, 0xB4BB, 0x8AB1, + 0xB4BC, 0x8AB2, 0xB4BD, 0x8AB3, 0xB4BE, 0x8AB4, 0xB4BF, 0x8AB5, 0xB4C0, 0xB5E0, 0xB4C1, 0x8AB6, 0xB4C2, 0x8AB7, 0xB4C3, 0x8AB8, + 0xB4C4, 0xB5E1, 0xB4C5, 0x8AB9, 0xB4C6, 0x8ABA, 0xB4C7, 0x8ABB, 0xB4C8, 0xB5E2, 0xB4C9, 0x8ABC, 0xB4CA, 0x8ABD, 0xB4CB, 0x8ABE, + 0xB4CC, 0x8ABF, 0xB4CD, 0x8AC0, 0xB4CE, 0x8AC1, 0xB4CF, 0x8AC2, 0xB4D0, 0xB5E3, 0xB4D1, 0x8AC3, 0xB4D2, 0x8AC4, 0xB4D3, 0x8AC5, + 0xB4D4, 0x8AC6, 0xB4D5, 0xB5E4, 0xB4D6, 0x8AC7, 0xB4D7, 0x8AC8, 0xB4D8, 0x8AC9, 0xB4D9, 0x8ACA, 0xB4DA, 0x8ACB, 0xB4DB, 0x8ACC, + 0xB4DC, 0xB5E5, 0xB4DD, 0xB5E6, 0xB4DE, 0x8ACD, 0xB4DF, 0x8ACE, 0xB4E0, 0xB5E7, 0xB4E1, 0x8ACF, 0xB4E2, 0x8AD0, 0xB4E3, 0xB5E8, + 0xB4E4, 0xB5E9, 0xB4E5, 0x8AD1, 0xB4E6, 0xB5EA, 0xB4E7, 0x8AD2, 0xB4E8, 0x8AD3, 0xB4E9, 0x8AD4, 0xB4EA, 0x8AD5, 0xB4EB, 0x8AD6, + 0xB4EC, 0xB5EB, 0xB4ED, 0xB5EC, 0xB4EE, 0x8AD7, 0xB4EF, 0xB5ED, 0xB4F0, 0x8AD8, 0xB4F1, 0xB5EE, 0xB4F2, 0x8AD9, 0xB4F3, 0x8ADA, + 0xB4F4, 0x8ADB, 0xB4F5, 0x8ADC, 0xB4F6, 0x8ADD, 0xB4F7, 0x8ADE, 0xB4F8, 0xB5EF, 0xB4F9, 0x8ADF, 0xB4FA, 0x8AE0, 0xB4FB, 0x8AE1, + 0xB4FC, 0x8AE2, 0xB4FD, 0x8AE3, 0xB4FE, 0x8AE4, 0xB4FF, 0x8AE5, 0xB500, 0x8AE6, 0xB501, 0x8AE7, 0xB502, 0x8AE8, 0xB503, 0x8AE9, + 0xB504, 0x8AEA, 0xB505, 0x8AEB, 0xB506, 0x8AEC, 0xB507, 0x8AED, 0xB508, 0x8AEE, 0xB509, 0x8AEF, 0xB50A, 0x8AF0, 0xB50B, 0x8AF1, + 0xB50C, 0x8AF2, 0xB50D, 0x8AF3, 0xB50E, 0x8AF4, 0xB50F, 0x8AF5, 0xB510, 0x8AF6, 0xB511, 0x8AF7, 0xB512, 0x8AF8, 0xB513, 0x8AF9, + 0xB514, 0xB5F0, 0xB515, 0xB5F1, 0xB516, 0x8AFA, 0xB517, 0x8AFB, 0xB518, 0xB5F2, 0xB519, 0x8AFC, 0xB51A, 0x8AFD, 0xB51B, 0xB5F3, + 0xB51C, 0xB5F4, 0xB51D, 0x8AFE, 0xB51E, 0x8B41, 0xB51F, 0x8B42, 0xB520, 0x8B43, 0xB521, 0x8B44, 0xB522, 0x8B45, 0xB523, 0x8B46, + 0xB524, 0xB5F5, 0xB525, 0xB5F6, 0xB526, 0x8B47, 0xB527, 0xB5F7, 0xB528, 0xB5F8, 0xB529, 0xB5F9, 0xB52A, 0xB5FA, 0xB52B, 0x8B48, + 0xB52C, 0x8B49, 0xB52D, 0x8B4A, 0xB52E, 0x8B4B, 0xB52F, 0x8B4C, 0xB530, 0xB5FB, 0xB531, 0xB5FC, 0xB532, 0x8B4D, 0xB533, 0x8B4E, + 0xB534, 0xB5FD, 0xB535, 0x8B4F, 0xB536, 0x8B50, 0xB537, 0x8B51, 0xB538, 0xB5FE, 0xB539, 0x8B52, 0xB53A, 0x8B53, 0xB53B, 0x8B54, + 0xB53C, 0x8B55, 0xB53D, 0x8B56, 0xB53E, 0x8B57, 0xB53F, 0x8B58, 0xB540, 0xB6A1, 0xB541, 0xB6A2, 0xB542, 0x8B59, 0xB543, 0xB6A3, + 0xB544, 0xB6A4, 0xB545, 0xB6A5, 0xB546, 0x8B5A, 0xB547, 0x8B61, 0xB548, 0x8B62, 0xB549, 0x8B63, 0xB54A, 0x8B64, 0xB54B, 0xB6A6, + 0xB54C, 0xB6A7, 0xB54D, 0xB6A8, 0xB54E, 0x8B65, 0xB54F, 0x8B66, 0xB550, 0xB6A9, 0xB551, 0x8B67, 0xB552, 0x8B68, 0xB553, 0x8B69, + 0xB554, 0xB6AA, 0xB555, 0x8B6A, 0xB556, 0x8B6B, 0xB557, 0x8B6C, 0xB558, 0x8B6D, 0xB559, 0x8B6E, 0xB55A, 0x8B6F, 0xB55B, 0x8B70, + 0xB55C, 0xB6AB, 0xB55D, 0xB6AC, 0xB55E, 0x8B71, 0xB55F, 0xB6AD, 0xB560, 0xB6AE, 0xB561, 0xB6AF, 0xB562, 0x8B72, 0xB563, 0x8B73, + 0xB564, 0x8B74, 0xB565, 0x8B75, 0xB566, 0x8B76, 0xB567, 0x8B77, 0xB568, 0x8B78, 0xB569, 0x8B79, 0xB56A, 0x8B7A, 0xB56B, 0x8B81, + 0xB56C, 0x8B82, 0xB56D, 0x8B83, 0xB56E, 0x8B84, 0xB56F, 0x8B85, 0xB570, 0x8B86, 0xB571, 0x8B87, 0xB572, 0x8B88, 0xB573, 0x8B89, + 0xB574, 0x8B8A, 0xB575, 0x8B8B, 0xB576, 0x8B8C, 0xB577, 0x8B8D, 0xB578, 0x8B8E, 0xB579, 0x8B8F, 0xB57A, 0x8B90, 0xB57B, 0x8B91, + 0xB57C, 0x8B92, 0xB57D, 0x8B93, 0xB57E, 0x8B94, 0xB57F, 0x8B95, 0xB580, 0x8B96, 0xB581, 0x8B97, 0xB582, 0x8B98, 0xB583, 0x8B99, + 0xB584, 0x8B9A, 0xB585, 0x8B9B, 0xB586, 0x8B9C, 0xB587, 0x8B9D, 0xB588, 0x8B9E, 0xB589, 0x8B9F, 0xB58A, 0x8BA0, 0xB58B, 0x8BA1, + 0xB58C, 0x8BA2, 0xB58D, 0x8BA3, 0xB58E, 0x8BA4, 0xB58F, 0x8BA5, 0xB590, 0x8BA6, 0xB591, 0x8BA7, 0xB592, 0x8BA8, 0xB593, 0x8BA9, + 0xB594, 0x8BAA, 0xB595, 0x8BAB, 0xB596, 0x8BAC, 0xB597, 0x8BAD, 0xB598, 0x8BAE, 0xB599, 0x8BAF, 0xB59A, 0x8BB0, 0xB59B, 0x8BB1, + 0xB59C, 0x8BB2, 0xB59D, 0x8BB3, 0xB59E, 0x8BB4, 0xB59F, 0x8BB5, 0xB5A0, 0xB6B0, 0xB5A1, 0xB6B1, 0xB5A2, 0x8BB6, 0xB5A3, 0x8BB7, + 0xB5A4, 0xB6B2, 0xB5A5, 0x8BB8, 0xB5A6, 0x8BB9, 0xB5A7, 0x8BBA, 0xB5A8, 0xB6B3, 0xB5A9, 0x8BBB, 0xB5AA, 0xB6B4, 0xB5AB, 0xB6B5, + 0xB5AC, 0x8BBC, 0xB5AD, 0x8BBD, 0xB5AE, 0x8BBE, 0xB5AF, 0x8BBF, 0xB5B0, 0xB6B6, 0xB5B1, 0xB6B7, 0xB5B2, 0x8BC0, 0xB5B3, 0xB6B8, + 0xB5B4, 0xB6B9, 0xB5B5, 0xB6BA, 0xB5B6, 0x8BC1, 0xB5B7, 0x8BC2, 0xB5B8, 0x8BC3, 0xB5B9, 0x8BC4, 0xB5BA, 0x8BC5, 0xB5BB, 0xB6BB, + 0xB5BC, 0xB6BC, 0xB5BD, 0xB6BD, 0xB5BE, 0x8BC6, 0xB5BF, 0x8BC7, 0xB5C0, 0xB6BE, 0xB5C1, 0x8BC8, 0xB5C2, 0x8BC9, 0xB5C3, 0x8BCA, + 0xB5C4, 0xB6BF, 0xB5C5, 0x8BCB, 0xB5C6, 0x8BCC, 0xB5C7, 0x8BCD, 0xB5C8, 0x8BCE, 0xB5C9, 0x8BCF, 0xB5CA, 0x8BD0, 0xB5CB, 0x8BD1, + 0xB5CC, 0xB6C0, 0xB5CD, 0xB6C1, 0xB5CE, 0x8BD2, 0xB5CF, 0xB6C2, 0xB5D0, 0xB6C3, 0xB5D1, 0xB6C4, 0xB5D2, 0x8BD3, 0xB5D3, 0x8BD4, + 0xB5D4, 0x8BD5, 0xB5D5, 0x8BD6, 0xB5D6, 0x8BD7, 0xB5D7, 0x8BD8, 0xB5D8, 0xB6C5, 0xB5D9, 0x8BD9, 0xB5DA, 0x8BDA, 0xB5DB, 0x8BDB, + 0xB5DC, 0x8BDC, 0xB5DD, 0x8BDD, 0xB5DE, 0x8BDE, 0xB5DF, 0x8BDF, 0xB5E0, 0x8BE0, 0xB5E1, 0x8BE1, 0xB5E2, 0x8BE2, 0xB5E3, 0x8BE3, + 0xB5E4, 0x8BE4, 0xB5E5, 0x8BE5, 0xB5E6, 0x8BE6, 0xB5E7, 0x8BE7, 0xB5E8, 0x8BE8, 0xB5E9, 0x8BE9, 0xB5EA, 0x8BEA, 0xB5EB, 0x8BEB, + 0xB5EC, 0xB6C6, 0xB5ED, 0x8BEC, 0xB5EE, 0x8BED, 0xB5EF, 0x8BEE, 0xB5F0, 0x8BEF, 0xB5F1, 0x8BF0, 0xB5F2, 0x8BF1, 0xB5F3, 0x8BF2, + 0xB5F4, 0x8BF3, 0xB5F5, 0x8BF4, 0xB5F6, 0x8BF5, 0xB5F7, 0x8BF6, 0xB5F8, 0x8BF7, 0xB5F9, 0x8BF8, 0xB5FA, 0x8BF9, 0xB5FB, 0x8BFA, + 0xB5FC, 0x8BFB, 0xB5FD, 0x8BFC, 0xB5FE, 0x8BFD, 0xB5FF, 0x8BFE, 0xB600, 0x8C41, 0xB601, 0x8C42, 0xB602, 0x8C43, 0xB603, 0x8C44, + 0xB604, 0x8C45, 0xB605, 0x8C46, 0xB606, 0x8C47, 0xB607, 0x8C48, 0xB608, 0x8C49, 0xB609, 0x8C4A, 0xB60A, 0x8C4B, 0xB60B, 0x8C4C, + 0xB60C, 0x8C4D, 0xB60D, 0x8C4E, 0xB60E, 0x8C4F, 0xB60F, 0x8C50, 0xB610, 0xB6C7, 0xB611, 0xB6C8, 0xB612, 0x8C51, 0xB613, 0x8C52, + 0xB614, 0xB6C9, 0xB615, 0x8C53, 0xB616, 0x8C54, 0xB617, 0x8C55, 0xB618, 0xB6CA, 0xB619, 0x8C56, 0xB61A, 0x8C57, 0xB61B, 0x8C58, + 0xB61C, 0x8C59, 0xB61D, 0x8C5A, 0xB61E, 0x8C61, 0xB61F, 0x8C62, 0xB620, 0x8C63, 0xB621, 0x8C64, 0xB622, 0x8C65, 0xB623, 0x8C66, + 0xB624, 0x8C67, 0xB625, 0xB6CB, 0xB626, 0x8C68, 0xB627, 0x8C69, 0xB628, 0x8C6A, 0xB629, 0x8C6B, 0xB62A, 0x8C6C, 0xB62B, 0x8C6D, + 0xB62C, 0xB6CC, 0xB62D, 0x8C6E, 0xB62E, 0x8C6F, 0xB62F, 0x8C70, 0xB630, 0x8C71, 0xB631, 0x8C72, 0xB632, 0x8C73, 0xB633, 0x8C74, + 0xB634, 0xB6CD, 0xB635, 0x8C75, 0xB636, 0x8C76, 0xB637, 0x8C77, 0xB638, 0x8C78, 0xB639, 0x8C79, 0xB63A, 0x8C7A, 0xB63B, 0x8C81, + 0xB63C, 0x8C82, 0xB63D, 0x8C83, 0xB63E, 0x8C84, 0xB63F, 0x8C85, 0xB640, 0x8C86, 0xB641, 0x8C87, 0xB642, 0x8C88, 0xB643, 0x8C89, + 0xB644, 0x8C8A, 0xB645, 0x8C8B, 0xB646, 0x8C8C, 0xB647, 0x8C8D, 0xB648, 0xB6CE, 0xB649, 0x8C8E, 0xB64A, 0x8C8F, 0xB64B, 0x8C90, + 0xB64C, 0x8C91, 0xB64D, 0x8C92, 0xB64E, 0x8C93, 0xB64F, 0x8C94, 0xB650, 0x8C95, 0xB651, 0x8C96, 0xB652, 0x8C97, 0xB653, 0x8C98, + 0xB654, 0x8C99, 0xB655, 0x8C9A, 0xB656, 0x8C9B, 0xB657, 0x8C9C, 0xB658, 0x8C9D, 0xB659, 0x8C9E, 0xB65A, 0x8C9F, 0xB65B, 0x8CA0, + 0xB65C, 0x8CA1, 0xB65D, 0x8CA2, 0xB65E, 0x8CA3, 0xB65F, 0x8CA4, 0xB660, 0x8CA5, 0xB661, 0x8CA6, 0xB662, 0x8CA7, 0xB663, 0x8CA8, + 0xB664, 0xB6CF, 0xB665, 0x8CA9, 0xB666, 0x8CAA, 0xB667, 0x8CAB, 0xB668, 0xB6D0, 0xB669, 0x8CAC, 0xB66A, 0x8CAD, 0xB66B, 0x8CAE, + 0xB66C, 0x8CAF, 0xB66D, 0x8CB0, 0xB66E, 0x8CB1, 0xB66F, 0x8CB2, 0xB670, 0x8CB3, 0xB671, 0x8CB4, 0xB672, 0x8CB5, 0xB673, 0x8CB6, + 0xB674, 0x8CB7, 0xB675, 0x8CB8, 0xB676, 0x8CB9, 0xB677, 0x8CBA, 0xB678, 0x8CBB, 0xB679, 0x8CBC, 0xB67A, 0x8CBD, 0xB67B, 0x8CBE, + 0xB67C, 0x8CBF, 0xB67D, 0x8CC0, 0xB67E, 0x8CC1, 0xB67F, 0x8CC2, 0xB680, 0x8CC3, 0xB681, 0x8CC4, 0xB682, 0x8CC5, 0xB683, 0x8CC6, + 0xB684, 0x8CC7, 0xB685, 0x8CC8, 0xB686, 0x8CC9, 0xB687, 0x8CCA, 0xB688, 0x8CCB, 0xB689, 0x8CCC, 0xB68A, 0x8CCD, 0xB68B, 0x8CCE, + 0xB68C, 0x8CCF, 0xB68D, 0x8CD0, 0xB68E, 0x8CD1, 0xB68F, 0x8CD2, 0xB690, 0x8CD3, 0xB691, 0x8CD4, 0xB692, 0x8CD5, 0xB693, 0x8CD6, + 0xB694, 0x8CD7, 0xB695, 0x8CD8, 0xB696, 0x8CD9, 0xB697, 0x8CDA, 0xB698, 0x8CDB, 0xB699, 0x8CDC, 0xB69A, 0x8CDD, 0xB69B, 0x8CDE, + 0xB69C, 0xB6D1, 0xB69D, 0xB6D2, 0xB69E, 0x8CDF, 0xB69F, 0x8CE0, 0xB6A0, 0xB6D3, 0xB6A1, 0x8CE1, 0xB6A2, 0x8CE2, 0xB6A3, 0x8CE3, + 0xB6A4, 0xB6D4, 0xB6A5, 0x8CE4, 0xB6A6, 0x8CE5, 0xB6A7, 0x8CE6, 0xB6A8, 0x8CE7, 0xB6A9, 0x8CE8, 0xB6AA, 0x8CE9, 0xB6AB, 0xB6D5, + 0xB6AC, 0xB6D6, 0xB6AD, 0x8CEA, 0xB6AE, 0x8CEB, 0xB6AF, 0x8CEC, 0xB6B0, 0x8CED, 0xB6B1, 0xB6D7, 0xB6B2, 0x8CEE, 0xB6B3, 0x8CEF, + 0xB6B4, 0x8CF0, 0xB6B5, 0x8CF1, 0xB6B6, 0x8CF2, 0xB6B7, 0x8CF3, 0xB6B8, 0x8CF4, 0xB6B9, 0x8CF5, 0xB6BA, 0x8CF6, 0xB6BB, 0x8CF7, + 0xB6BC, 0x8CF8, 0xB6BD, 0x8CF9, 0xB6BE, 0x8CFA, 0xB6BF, 0x8CFB, 0xB6C0, 0x8CFC, 0xB6C1, 0x8CFD, 0xB6C2, 0x8CFE, 0xB6C3, 0x8D41, + 0xB6C4, 0x8D42, 0xB6C5, 0x8D43, 0xB6C6, 0x8D44, 0xB6C7, 0x8D45, 0xB6C8, 0x8D46, 0xB6C9, 0x8D47, 0xB6CA, 0x8D48, 0xB6CB, 0x8D49, + 0xB6CC, 0x8D4A, 0xB6CD, 0x8D4B, 0xB6CE, 0x8D4C, 0xB6CF, 0x8D4D, 0xB6D0, 0x8D4E, 0xB6D1, 0x8D4F, 0xB6D2, 0x8D50, 0xB6D3, 0x8D51, + 0xB6D4, 0xB6D8, 0xB6D5, 0x8D52, 0xB6D6, 0x8D53, 0xB6D7, 0x8D54, 0xB6D8, 0x8D55, 0xB6D9, 0x8D56, 0xB6DA, 0x8D57, 0xB6DB, 0x8D58, + 0xB6DC, 0x8D59, 0xB6DD, 0x8D5A, 0xB6DE, 0x8D61, 0xB6DF, 0x8D62, 0xB6E0, 0x8D63, 0xB6E1, 0x8D64, 0xB6E2, 0x8D65, 0xB6E3, 0x8D66, + 0xB6E4, 0x8D67, 0xB6E5, 0x8D68, 0xB6E6, 0x8D69, 0xB6E7, 0x8D6A, 0xB6E8, 0x8D6B, 0xB6E9, 0x8D6C, 0xB6EA, 0x8D6D, 0xB6EB, 0x8D6E, + 0xB6EC, 0x8D6F, 0xB6ED, 0x8D70, 0xB6EE, 0x8D71, 0xB6EF, 0x8D72, 0xB6F0, 0xB6D9, 0xB6F1, 0x8D73, 0xB6F2, 0x8D74, 0xB6F3, 0x8D75, + 0xB6F4, 0xB6DA, 0xB6F5, 0x8D76, 0xB6F6, 0x8D77, 0xB6F7, 0x8D78, 0xB6F8, 0xB6DB, 0xB6F9, 0x8D79, 0xB6FA, 0x8D7A, 0xB6FB, 0x8D81, + 0xB6FC, 0x8D82, 0xB6FD, 0x8D83, 0xB6FE, 0x8D84, 0xB6FF, 0x8D85, 0xB700, 0xB6DC, 0xB701, 0xB6DD, 0xB702, 0x8D86, 0xB703, 0x8D87, + 0xB704, 0x8D88, 0xB705, 0xB6DE, 0xB706, 0x8D89, 0xB707, 0x8D8A, 0xB708, 0x8D8B, 0xB709, 0x8D8C, 0xB70A, 0x8D8D, 0xB70B, 0x8D8E, + 0xB70C, 0x8D8F, 0xB70D, 0x8D90, 0xB70E, 0x8D91, 0xB70F, 0x8D92, 0xB710, 0x8D93, 0xB711, 0x8D94, 0xB712, 0x8D95, 0xB713, 0x8D96, + 0xB714, 0x8D97, 0xB715, 0x8D98, 0xB716, 0x8D99, 0xB717, 0x8D9A, 0xB718, 0x8D9B, 0xB719, 0x8D9C, 0xB71A, 0x8D9D, 0xB71B, 0x8D9E, + 0xB71C, 0x8D9F, 0xB71D, 0x8DA0, 0xB71E, 0x8DA1, 0xB71F, 0x8DA2, 0xB720, 0x8DA3, 0xB721, 0x8DA4, 0xB722, 0x8DA5, 0xB723, 0x8DA6, + 0xB724, 0x8DA7, 0xB725, 0x8DA8, 0xB726, 0x8DA9, 0xB727, 0x8DAA, 0xB728, 0xB6DF, 0xB729, 0xB6E0, 0xB72A, 0x8DAB, 0xB72B, 0x8DAC, + 0xB72C, 0xB6E1, 0xB72D, 0x8DAD, 0xB72E, 0x8DAE, 0xB72F, 0xB6E2, 0xB730, 0xB6E3, 0xB731, 0x8DAF, 0xB732, 0x8DB0, 0xB733, 0x8DB1, + 0xB734, 0x8DB2, 0xB735, 0x8DB3, 0xB736, 0x8DB4, 0xB737, 0x8DB5, 0xB738, 0xB6E4, 0xB739, 0xB6E5, 0xB73A, 0x8DB6, 0xB73B, 0xB6E6, + 0xB73C, 0x8DB7, 0xB73D, 0x8DB8, 0xB73E, 0x8DB9, 0xB73F, 0x8DBA, 0xB740, 0x8DBB, 0xB741, 0x8DBC, 0xB742, 0x8DBD, 0xB743, 0x8DBE, + 0xB744, 0xB6E7, 0xB745, 0x8DBF, 0xB746, 0x8DC0, 0xB747, 0x8DC1, 0xB748, 0xB6E8, 0xB749, 0x8DC2, 0xB74A, 0x8DC3, 0xB74B, 0x8DC4, + 0xB74C, 0xB6E9, 0xB74D, 0x8DC5, 0xB74E, 0x8DC6, 0xB74F, 0x8DC7, 0xB750, 0x8DC8, 0xB751, 0x8DC9, 0xB752, 0x8DCA, 0xB753, 0x8DCB, + 0xB754, 0xB6EA, 0xB755, 0xB6EB, 0xB756, 0x8DCC, 0xB757, 0x8DCD, 0xB758, 0x8DCE, 0xB759, 0x8DCF, 0xB75A, 0x8DD0, 0xB75B, 0x8DD1, + 0xB75C, 0x8DD2, 0xB75D, 0x8DD3, 0xB75E, 0x8DD4, 0xB75F, 0x8DD5, 0xB760, 0xB6EC, 0xB761, 0x8DD6, 0xB762, 0x8DD7, 0xB763, 0x8DD8, + 0xB764, 0xB6ED, 0xB765, 0x8DD9, 0xB766, 0x8DDA, 0xB767, 0x8DDB, 0xB768, 0xB6EE, 0xB769, 0x8DDC, 0xB76A, 0x8DDD, 0xB76B, 0x8DDE, + 0xB76C, 0x8DDF, 0xB76D, 0x8DE0, 0xB76E, 0x8DE1, 0xB76F, 0x8DE2, 0xB770, 0xB6EF, 0xB771, 0xB6F0, 0xB772, 0x8DE3, 0xB773, 0xB6F1, + 0xB774, 0x8DE4, 0xB775, 0xB6F2, 0xB776, 0x8DE5, 0xB777, 0x8DE6, 0xB778, 0x8DE7, 0xB779, 0x8DE8, 0xB77A, 0x8DE9, 0xB77B, 0x8DEA, + 0xB77C, 0xB6F3, 0xB77D, 0xB6F4, 0xB77E, 0x8DEB, 0xB77F, 0x8DEC, 0xB780, 0xB6F5, 0xB781, 0x8DED, 0xB782, 0x8DEE, 0xB783, 0x8DEF, + 0xB784, 0xB6F6, 0xB785, 0x8DF0, 0xB786, 0x8DF1, 0xB787, 0x8DF2, 0xB788, 0x8DF3, 0xB789, 0x8DF4, 0xB78A, 0x8DF5, 0xB78B, 0x8DF6, + 0xB78C, 0xB6F7, 0xB78D, 0xB6F8, 0xB78E, 0x8DF7, 0xB78F, 0xB6F9, 0xB790, 0xB6FA, 0xB791, 0xB6FB, 0xB792, 0xB6FC, 0xB793, 0x8DF8, + 0xB794, 0x8DF9, 0xB795, 0x8DFA, 0xB796, 0xB6FD, 0xB797, 0xB6FE, 0xB798, 0xB7A1, 0xB799, 0xB7A2, 0xB79A, 0x8DFB, 0xB79B, 0x8DFC, + 0xB79C, 0xB7A3, 0xB79D, 0x8DFD, 0xB79E, 0x8DFE, 0xB79F, 0x8E41, 0xB7A0, 0xB7A4, 0xB7A1, 0x8E42, 0xB7A2, 0x8E43, 0xB7A3, 0x8E44, + 0xB7A4, 0x8E45, 0xB7A5, 0x8E46, 0xB7A6, 0x8E47, 0xB7A7, 0x8E48, 0xB7A8, 0xB7A5, 0xB7A9, 0xB7A6, 0xB7AA, 0x8E49, 0xB7AB, 0xB7A7, + 0xB7AC, 0xB7A8, 0xB7AD, 0xB7A9, 0xB7AE, 0x8E4A, 0xB7AF, 0x8E4B, 0xB7B0, 0x8E4C, 0xB7B1, 0x8E4D, 0xB7B2, 0x8E4E, 0xB7B3, 0x8E4F, + 0xB7B4, 0xB7AA, 0xB7B5, 0xB7AB, 0xB7B6, 0x8E50, 0xB7B7, 0x8E51, 0xB7B8, 0xB7AC, 0xB7B9, 0x8E52, 0xB7BA, 0x8E53, 0xB7BB, 0x8E54, + 0xB7BC, 0x8E55, 0xB7BD, 0x8E56, 0xB7BE, 0x8E57, 0xB7BF, 0x8E58, 0xB7C0, 0x8E59, 0xB7C1, 0x8E5A, 0xB7C2, 0x8E61, 0xB7C3, 0x8E62, + 0xB7C4, 0x8E63, 0xB7C5, 0x8E64, 0xB7C6, 0x8E65, 0xB7C7, 0xB7AD, 0xB7C8, 0x8E66, 0xB7C9, 0xB7AE, 0xB7CA, 0x8E67, 0xB7CB, 0x8E68, + 0xB7CC, 0x8E69, 0xB7CD, 0x8E6A, 0xB7CE, 0x8E6B, 0xB7CF, 0x8E6C, 0xB7D0, 0x8E6D, 0xB7D1, 0x8E6E, 0xB7D2, 0x8E6F, 0xB7D3, 0x8E70, + 0xB7D4, 0x8E71, 0xB7D5, 0x8E72, 0xB7D6, 0x8E73, 0xB7D7, 0x8E74, 0xB7D8, 0x8E75, 0xB7D9, 0x8E76, 0xB7DA, 0x8E77, 0xB7DB, 0x8E78, + 0xB7DC, 0x8E79, 0xB7DD, 0x8E7A, 0xB7DE, 0x8E81, 0xB7DF, 0x8E82, 0xB7E0, 0x8E83, 0xB7E1, 0x8E84, 0xB7E2, 0x8E85, 0xB7E3, 0x8E86, + 0xB7E4, 0x8E87, 0xB7E5, 0x8E88, 0xB7E6, 0x8E89, 0xB7E7, 0x8E8A, 0xB7E8, 0x8E8B, 0xB7E9, 0x8E8C, 0xB7EA, 0x8E8D, 0xB7EB, 0x8E8E, + 0xB7EC, 0xB7AF, 0xB7ED, 0xB7B0, 0xB7EE, 0x8E8F, 0xB7EF, 0x8E90, 0xB7F0, 0xB7B1, 0xB7F1, 0x8E91, 0xB7F2, 0x8E92, 0xB7F3, 0x8E93, + 0xB7F4, 0xB7B2, 0xB7F5, 0x8E94, 0xB7F6, 0x8E95, 0xB7F7, 0x8E96, 0xB7F8, 0x8E97, 0xB7F9, 0x8E98, 0xB7FA, 0x8E99, 0xB7FB, 0x8E9A, + 0xB7FC, 0xB7B3, 0xB7FD, 0xB7B4, 0xB7FE, 0x8E9B, 0xB7FF, 0xB7B5, 0xB800, 0xB7B6, 0xB801, 0xB7B7, 0xB802, 0x8E9C, 0xB803, 0x8E9D, + 0xB804, 0x8E9E, 0xB805, 0x8E9F, 0xB806, 0x8EA0, 0xB807, 0xB7B8, 0xB808, 0xB7B9, 0xB809, 0xB7BA, 0xB80A, 0x8EA1, 0xB80B, 0x8EA2, + 0xB80C, 0xB7BB, 0xB80D, 0x8EA3, 0xB80E, 0x8EA4, 0xB80F, 0x8EA5, 0xB810, 0xB7BC, 0xB811, 0x8EA6, 0xB812, 0x8EA7, 0xB813, 0x8EA8, + 0xB814, 0x8EA9, 0xB815, 0x8EAA, 0xB816, 0x8EAB, 0xB817, 0x8EAC, 0xB818, 0xB7BD, 0xB819, 0xB7BE, 0xB81A, 0x8EAD, 0xB81B, 0xB7BF, + 0xB81C, 0x8EAE, 0xB81D, 0xB7C0, 0xB81E, 0x8EAF, 0xB81F, 0x8EB0, 0xB820, 0x8EB1, 0xB821, 0x8EB2, 0xB822, 0x8EB3, 0xB823, 0x8EB4, + 0xB824, 0xB7C1, 0xB825, 0xB7C2, 0xB826, 0x8EB5, 0xB827, 0x8EB6, 0xB828, 0xB7C3, 0xB829, 0x8EB7, 0xB82A, 0x8EB8, 0xB82B, 0x8EB9, + 0xB82C, 0xB7C4, 0xB82D, 0x8EBA, 0xB82E, 0x8EBB, 0xB82F, 0x8EBC, 0xB830, 0x8EBD, 0xB831, 0x8EBE, 0xB832, 0x8EBF, 0xB833, 0x8EC0, + 0xB834, 0xB7C5, 0xB835, 0xB7C6, 0xB836, 0x8EC1, 0xB837, 0xB7C7, 0xB838, 0xB7C8, 0xB839, 0xB7C9, 0xB83A, 0x8EC2, 0xB83B, 0x8EC3, + 0xB83C, 0x8EC4, 0xB83D, 0x8EC5, 0xB83E, 0x8EC6, 0xB83F, 0x8EC7, 0xB840, 0xB7CA, 0xB841, 0x8EC8, 0xB842, 0x8EC9, 0xB843, 0x8ECA, + 0xB844, 0xB7CB, 0xB845, 0x8ECB, 0xB846, 0x8ECC, 0xB847, 0x8ECD, 0xB848, 0x8ECE, 0xB849, 0x8ECF, 0xB84A, 0x8ED0, 0xB84B, 0x8ED1, + 0xB84C, 0x8ED2, 0xB84D, 0x8ED3, 0xB84E, 0x8ED4, 0xB84F, 0x8ED5, 0xB850, 0x8ED6, 0xB851, 0xB7CC, 0xB852, 0x8ED7, 0xB853, 0xB7CD, + 0xB854, 0x8ED8, 0xB855, 0x8ED9, 0xB856, 0x8EDA, 0xB857, 0x8EDB, 0xB858, 0x8EDC, 0xB859, 0x8EDD, 0xB85A, 0x8EDE, 0xB85B, 0x8EDF, + 0xB85C, 0xB7CE, 0xB85D, 0xB7CF, 0xB85E, 0x8EE0, 0xB85F, 0x8EE1, 0xB860, 0xB7D0, 0xB861, 0x8EE2, 0xB862, 0x8EE3, 0xB863, 0x8EE4, + 0xB864, 0xB7D1, 0xB865, 0x8EE5, 0xB866, 0x8EE6, 0xB867, 0x8EE7, 0xB868, 0x8EE8, 0xB869, 0x8EE9, 0xB86A, 0x8EEA, 0xB86B, 0x8EEB, + 0xB86C, 0xB7D2, 0xB86D, 0xB7D3, 0xB86E, 0x8EEC, 0xB86F, 0xB7D4, 0xB870, 0x8EED, 0xB871, 0xB7D5, 0xB872, 0x8EEE, 0xB873, 0x8EEF, + 0xB874, 0x8EF0, 0xB875, 0x8EF1, 0xB876, 0x8EF2, 0xB877, 0x8EF3, 0xB878, 0xB7D6, 0xB879, 0x8EF4, 0xB87A, 0x8EF5, 0xB87B, 0x8EF6, + 0xB87C, 0xB7D7, 0xB87D, 0x8EF7, 0xB87E, 0x8EF8, 0xB87F, 0x8EF9, 0xB880, 0x8EFA, 0xB881, 0x8EFB, 0xB882, 0x8EFC, 0xB883, 0x8EFD, + 0xB884, 0x8EFE, 0xB885, 0x8F41, 0xB886, 0x8F42, 0xB887, 0x8F43, 0xB888, 0x8F44, 0xB889, 0x8F45, 0xB88A, 0x8F46, 0xB88B, 0x8F47, + 0xB88C, 0x8F48, 0xB88D, 0xB7D8, 0xB88E, 0x8F49, 0xB88F, 0x8F4A, 0xB890, 0x8F4B, 0xB891, 0x8F4C, 0xB892, 0x8F4D, 0xB893, 0x8F4E, + 0xB894, 0x8F4F, 0xB895, 0x8F50, 0xB896, 0x8F51, 0xB897, 0x8F52, 0xB898, 0x8F53, 0xB899, 0x8F54, 0xB89A, 0x8F55, 0xB89B, 0x8F56, + 0xB89C, 0x8F57, 0xB89D, 0x8F58, 0xB89E, 0x8F59, 0xB89F, 0x8F5A, 0xB8A0, 0x8F61, 0xB8A1, 0x8F62, 0xB8A2, 0x8F63, 0xB8A3, 0x8F64, + 0xB8A4, 0x8F65, 0xB8A5, 0x8F66, 0xB8A6, 0x8F67, 0xB8A7, 0x8F68, 0xB8A8, 0xB7D9, 0xB8A9, 0x8F69, 0xB8AA, 0x8F6A, 0xB8AB, 0x8F6B, + 0xB8AC, 0x8F6C, 0xB8AD, 0x8F6D, 0xB8AE, 0x8F6E, 0xB8AF, 0x8F6F, 0xB8B0, 0xB7DA, 0xB8B1, 0x8F70, 0xB8B2, 0x8F71, 0xB8B3, 0x8F72, + 0xB8B4, 0xB7DB, 0xB8B5, 0x8F73, 0xB8B6, 0x8F74, 0xB8B7, 0x8F75, 0xB8B8, 0xB7DC, 0xB8B9, 0x8F76, 0xB8BA, 0x8F77, 0xB8BB, 0x8F78, + 0xB8BC, 0x8F79, 0xB8BD, 0x8F7A, 0xB8BE, 0x8F81, 0xB8BF, 0x8F82, 0xB8C0, 0xB7DD, 0xB8C1, 0xB7DE, 0xB8C2, 0x8F83, 0xB8C3, 0xB7DF, + 0xB8C4, 0x8F84, 0xB8C5, 0xB7E0, 0xB8C6, 0x8F85, 0xB8C7, 0x8F86, 0xB8C8, 0x8F87, 0xB8C9, 0x8F88, 0xB8CA, 0x8F89, 0xB8CB, 0x8F8A, + 0xB8CC, 0xB7E1, 0xB8CD, 0x8F8B, 0xB8CE, 0x8F8C, 0xB8CF, 0x8F8D, 0xB8D0, 0xB7E2, 0xB8D1, 0x8F8E, 0xB8D2, 0x8F8F, 0xB8D3, 0x8F90, + 0xB8D4, 0xB7E3, 0xB8D5, 0x8F91, 0xB8D6, 0x8F92, 0xB8D7, 0x8F93, 0xB8D8, 0x8F94, 0xB8D9, 0x8F95, 0xB8DA, 0x8F96, 0xB8DB, 0x8F97, + 0xB8DC, 0x8F98, 0xB8DD, 0xB7E4, 0xB8DE, 0x8F99, 0xB8DF, 0xB7E5, 0xB8E0, 0x8F9A, 0xB8E1, 0xB7E6, 0xB8E2, 0x8F9B, 0xB8E3, 0x8F9C, + 0xB8E4, 0x8F9D, 0xB8E5, 0x8F9E, 0xB8E6, 0x8F9F, 0xB8E7, 0x8FA0, 0xB8E8, 0xB7E7, 0xB8E9, 0xB7E8, 0xB8EA, 0x8FA1, 0xB8EB, 0x8FA2, + 0xB8EC, 0xB7E9, 0xB8ED, 0x8FA3, 0xB8EE, 0x8FA4, 0xB8EF, 0x8FA5, 0xB8F0, 0xB7EA, 0xB8F1, 0x8FA6, 0xB8F2, 0x8FA7, 0xB8F3, 0x8FA8, + 0xB8F4, 0x8FA9, 0xB8F5, 0x8FAA, 0xB8F6, 0x8FAB, 0xB8F7, 0x8FAC, 0xB8F8, 0xB7EB, 0xB8F9, 0xB7EC, 0xB8FA, 0x8FAD, 0xB8FB, 0xB7ED, + 0xB8FC, 0x8FAE, 0xB8FD, 0xB7EE, 0xB8FE, 0x8FAF, 0xB8FF, 0x8FB0, 0xB900, 0x8FB1, 0xB901, 0x8FB2, 0xB902, 0x8FB3, 0xB903, 0x8FB4, + 0xB904, 0xB7EF, 0xB905, 0x8FB5, 0xB906, 0x8FB6, 0xB907, 0x8FB7, 0xB908, 0x8FB8, 0xB909, 0x8FB9, 0xB90A, 0x8FBA, 0xB90B, 0x8FBB, + 0xB90C, 0x8FBC, 0xB90D, 0x8FBD, 0xB90E, 0x8FBE, 0xB90F, 0x8FBF, 0xB910, 0x8FC0, 0xB911, 0x8FC1, 0xB912, 0x8FC2, 0xB913, 0x8FC3, + 0xB914, 0x8FC4, 0xB915, 0x8FC5, 0xB916, 0x8FC6, 0xB917, 0x8FC7, 0xB918, 0xB7F0, 0xB919, 0x8FC8, 0xB91A, 0x8FC9, 0xB91B, 0x8FCA, + 0xB91C, 0x8FCB, 0xB91D, 0x8FCC, 0xB91E, 0x8FCD, 0xB91F, 0x8FCE, 0xB920, 0xB7F1, 0xB921, 0x8FCF, 0xB922, 0x8FD0, 0xB923, 0x8FD1, + 0xB924, 0x8FD2, 0xB925, 0x8FD3, 0xB926, 0x8FD4, 0xB927, 0x8FD5, 0xB928, 0x8FD6, 0xB929, 0x8FD7, 0xB92A, 0x8FD8, 0xB92B, 0x8FD9, + 0xB92C, 0x8FDA, 0xB92D, 0x8FDB, 0xB92E, 0x8FDC, 0xB92F, 0x8FDD, 0xB930, 0x8FDE, 0xB931, 0x8FDF, 0xB932, 0x8FE0, 0xB933, 0x8FE1, + 0xB934, 0x8FE2, 0xB935, 0x8FE3, 0xB936, 0x8FE4, 0xB937, 0x8FE5, 0xB938, 0x8FE6, 0xB939, 0x8FE7, 0xB93A, 0x8FE8, 0xB93B, 0x8FE9, + 0xB93C, 0xB7F2, 0xB93D, 0xB7F3, 0xB93E, 0x8FEA, 0xB93F, 0x8FEB, 0xB940, 0xB7F4, 0xB941, 0x8FEC, 0xB942, 0x8FED, 0xB943, 0x8FEE, + 0xB944, 0xB7F5, 0xB945, 0x8FEF, 0xB946, 0x8FF0, 0xB947, 0x8FF1, 0xB948, 0x8FF2, 0xB949, 0x8FF3, 0xB94A, 0x8FF4, 0xB94B, 0x8FF5, + 0xB94C, 0xB7F6, 0xB94D, 0x8FF6, 0xB94E, 0x8FF7, 0xB94F, 0xB7F7, 0xB950, 0x8FF8, 0xB951, 0xB7F8, 0xB952, 0x8FF9, 0xB953, 0x8FFA, + 0xB954, 0x8FFB, 0xB955, 0x8FFC, 0xB956, 0x8FFD, 0xB957, 0x8FFE, 0xB958, 0xB7F9, 0xB959, 0xB7FA, 0xB95A, 0x9041, 0xB95B, 0x9042, + 0xB95C, 0xB7FB, 0xB95D, 0x9043, 0xB95E, 0x9044, 0xB95F, 0x9045, 0xB960, 0xB7FC, 0xB961, 0x9046, 0xB962, 0x9047, 0xB963, 0x9048, + 0xB964, 0x9049, 0xB965, 0x904A, 0xB966, 0x904B, 0xB967, 0x904C, 0xB968, 0xB7FD, 0xB969, 0xB7FE, 0xB96A, 0x904D, 0xB96B, 0xB8A1, + 0xB96C, 0x904E, 0xB96D, 0xB8A2, 0xB96E, 0x904F, 0xB96F, 0x9050, 0xB970, 0x9051, 0xB971, 0x9052, 0xB972, 0x9053, 0xB973, 0x9054, + 0xB974, 0xB8A3, 0xB975, 0xB8A4, 0xB976, 0x9055, 0xB977, 0x9056, 0xB978, 0xB8A5, 0xB979, 0x9057, 0xB97A, 0x9058, 0xB97B, 0x9059, + 0xB97C, 0xB8A6, 0xB97D, 0x905A, 0xB97E, 0x9061, 0xB97F, 0x9062, 0xB980, 0x9063, 0xB981, 0x9064, 0xB982, 0x9065, 0xB983, 0x9066, + 0xB984, 0xB8A7, 0xB985, 0xB8A8, 0xB986, 0x9067, 0xB987, 0xB8A9, 0xB988, 0x9068, 0xB989, 0xB8AA, 0xB98A, 0xB8AB, 0xB98B, 0x9069, + 0xB98C, 0x906A, 0xB98D, 0xB8AC, 0xB98E, 0xB8AD, 0xB98F, 0x906B, 0xB990, 0x906C, 0xB991, 0x906D, 0xB992, 0x906E, 0xB993, 0x906F, + 0xB994, 0x9070, 0xB995, 0x9071, 0xB996, 0x9072, 0xB997, 0x9073, 0xB998, 0x9074, 0xB999, 0x9075, 0xB99A, 0x9076, 0xB99B, 0x9077, + 0xB99C, 0x9078, 0xB99D, 0x9079, 0xB99E, 0x907A, 0xB99F, 0x9081, 0xB9A0, 0x9082, 0xB9A1, 0x9083, 0xB9A2, 0x9084, 0xB9A3, 0x9085, + 0xB9A4, 0x9086, 0xB9A5, 0x9087, 0xB9A6, 0x9088, 0xB9A7, 0x9089, 0xB9A8, 0x908A, 0xB9A9, 0x908B, 0xB9AA, 0x908C, 0xB9AB, 0x908D, + 0xB9AC, 0xB8AE, 0xB9AD, 0xB8AF, 0xB9AE, 0x908E, 0xB9AF, 0x908F, 0xB9B0, 0xB8B0, 0xB9B1, 0x9090, 0xB9B2, 0x9091, 0xB9B3, 0x9092, + 0xB9B4, 0xB8B1, 0xB9B5, 0x9093, 0xB9B6, 0x9094, 0xB9B7, 0x9095, 0xB9B8, 0x9096, 0xB9B9, 0x9097, 0xB9BA, 0x9098, 0xB9BB, 0x9099, + 0xB9BC, 0xB8B2, 0xB9BD, 0xB8B3, 0xB9BE, 0x909A, 0xB9BF, 0xB8B4, 0xB9C0, 0x909B, 0xB9C1, 0xB8B5, 0xB9C2, 0x909C, 0xB9C3, 0x909D, + 0xB9C4, 0x909E, 0xB9C5, 0x909F, 0xB9C6, 0x90A0, 0xB9C7, 0x90A1, 0xB9C8, 0xB8B6, 0xB9C9, 0xB8B7, 0xB9CA, 0x90A2, 0xB9CB, 0x90A3, + 0xB9CC, 0xB8B8, 0xB9CD, 0x90A4, 0xB9CE, 0xB8B9, 0xB9CF, 0xB8BA, 0xB9D0, 0xB8BB, 0xB9D1, 0xB8BC, 0xB9D2, 0xB8BD, 0xB9D3, 0x90A5, + 0xB9D4, 0x90A6, 0xB9D5, 0x90A7, 0xB9D6, 0x90A8, 0xB9D7, 0x90A9, 0xB9D8, 0xB8BE, 0xB9D9, 0xB8BF, 0xB9DA, 0x90AA, 0xB9DB, 0xB8C0, + 0xB9DC, 0x90AB, 0xB9DD, 0xB8C1, 0xB9DE, 0xB8C2, 0xB9DF, 0x90AC, 0xB9E0, 0x90AD, 0xB9E1, 0xB8C3, 0xB9E2, 0x90AE, 0xB9E3, 0xB8C4, + 0xB9E4, 0xB8C5, 0xB9E5, 0xB8C6, 0xB9E6, 0x90AF, 0xB9E7, 0x90B0, 0xB9E8, 0xB8C7, 0xB9E9, 0x90B1, 0xB9EA, 0x90B2, 0xB9EB, 0x90B3, + 0xB9EC, 0xB8C8, 0xB9ED, 0x90B4, 0xB9EE, 0x90B5, 0xB9EF, 0x90B6, 0xB9F0, 0x90B7, 0xB9F1, 0x90B8, 0xB9F2, 0x90B9, 0xB9F3, 0x90BA, + 0xB9F4, 0xB8C9, 0xB9F5, 0xB8CA, 0xB9F6, 0x90BB, 0xB9F7, 0xB8CB, 0xB9F8, 0xB8CC, 0xB9F9, 0xB8CD, 0xB9FA, 0xB8CE, 0xB9FB, 0x90BC, + 0xB9FC, 0x90BD, 0xB9FD, 0x90BE, 0xB9FE, 0x90BF, 0xB9FF, 0x90C0, 0xBA00, 0xB8CF, 0xBA01, 0xB8D0, 0xBA02, 0x90C1, 0xBA03, 0x90C2, + 0xBA04, 0x90C3, 0xBA05, 0x90C4, 0xBA06, 0x90C5, 0xBA07, 0x90C6, 0xBA08, 0xB8D1, 0xBA09, 0x90C7, 0xBA0A, 0x90C8, 0xBA0B, 0x90C9, + 0xBA0C, 0x90CA, 0xBA0D, 0x90CB, 0xBA0E, 0x90CC, 0xBA0F, 0x90CD, 0xBA10, 0x90CE, 0xBA11, 0x90CF, 0xBA12, 0x90D0, 0xBA13, 0x90D1, + 0xBA14, 0x90D2, 0xBA15, 0xB8D2, 0xBA16, 0x90D3, 0xBA17, 0x90D4, 0xBA18, 0x90D5, 0xBA19, 0x90D6, 0xBA1A, 0x90D7, 0xBA1B, 0x90D8, + 0xBA1C, 0x90D9, 0xBA1D, 0x90DA, 0xBA1E, 0x90DB, 0xBA1F, 0x90DC, 0xBA20, 0x90DD, 0xBA21, 0x90DE, 0xBA22, 0x90DF, 0xBA23, 0x90E0, + 0xBA24, 0x90E1, 0xBA25, 0x90E2, 0xBA26, 0x90E3, 0xBA27, 0x90E4, 0xBA28, 0x90E5, 0xBA29, 0x90E6, 0xBA2A, 0x90E7, 0xBA2B, 0x90E8, + 0xBA2C, 0x90E9, 0xBA2D, 0x90EA, 0xBA2E, 0x90EB, 0xBA2F, 0x90EC, 0xBA30, 0x90ED, 0xBA31, 0x90EE, 0xBA32, 0x90EF, 0xBA33, 0x90F0, + 0xBA34, 0x90F1, 0xBA35, 0x90F2, 0xBA36, 0x90F3, 0xBA37, 0x90F4, 0xBA38, 0xB8D3, 0xBA39, 0xB8D4, 0xBA3A, 0x90F5, 0xBA3B, 0x90F6, + 0xBA3C, 0xB8D5, 0xBA3D, 0x90F7, 0xBA3E, 0x90F8, 0xBA3F, 0x90F9, 0xBA40, 0xB8D6, 0xBA41, 0x90FA, 0xBA42, 0xB8D7, 0xBA43, 0x90FB, + 0xBA44, 0x90FC, 0xBA45, 0x90FD, 0xBA46, 0x90FE, 0xBA47, 0x9141, 0xBA48, 0xB8D8, 0xBA49, 0xB8D9, 0xBA4A, 0x9142, 0xBA4B, 0xB8DA, + 0xBA4C, 0x9143, 0xBA4D, 0xB8DB, 0xBA4E, 0xB8DC, 0xBA4F, 0x9144, 0xBA50, 0x9145, 0xBA51, 0x9146, 0xBA52, 0x9147, 0xBA53, 0xB8DD, + 0xBA54, 0xB8DE, 0xBA55, 0xB8DF, 0xBA56, 0x9148, 0xBA57, 0x9149, 0xBA58, 0xB8E0, 0xBA59, 0x914A, 0xBA5A, 0x914B, 0xBA5B, 0x914C, + 0xBA5C, 0xB8E1, 0xBA5D, 0x914D, 0xBA5E, 0x914E, 0xBA5F, 0x914F, 0xBA60, 0x9150, 0xBA61, 0x9151, 0xBA62, 0x9152, 0xBA63, 0x9153, + 0xBA64, 0xB8E2, 0xBA65, 0xB8E3, 0xBA66, 0x9154, 0xBA67, 0xB8E4, 0xBA68, 0xB8E5, 0xBA69, 0xB8E6, 0xBA6A, 0x9155, 0xBA6B, 0x9156, + 0xBA6C, 0x9157, 0xBA6D, 0x9158, 0xBA6E, 0x9159, 0xBA6F, 0x915A, 0xBA70, 0xB8E7, 0xBA71, 0xB8E8, 0xBA72, 0x9161, 0xBA73, 0x9162, + 0xBA74, 0xB8E9, 0xBA75, 0x9163, 0xBA76, 0x9164, 0xBA77, 0x9165, 0xBA78, 0xB8EA, 0xBA79, 0x9166, 0xBA7A, 0x9167, 0xBA7B, 0x9168, + 0xBA7C, 0x9169, 0xBA7D, 0x916A, 0xBA7E, 0x916B, 0xBA7F, 0x916C, 0xBA80, 0x916D, 0xBA81, 0x916E, 0xBA82, 0x916F, 0xBA83, 0xB8EB, + 0xBA84, 0xB8EC, 0xBA85, 0xB8ED, 0xBA86, 0x9170, 0xBA87, 0xB8EE, 0xBA88, 0x9171, 0xBA89, 0x9172, 0xBA8A, 0x9173, 0xBA8B, 0x9174, + 0xBA8C, 0xB8EF, 0xBA8D, 0x9175, 0xBA8E, 0x9176, 0xBA8F, 0x9177, 0xBA90, 0x9178, 0xBA91, 0x9179, 0xBA92, 0x917A, 0xBA93, 0x9181, + 0xBA94, 0x9182, 0xBA95, 0x9183, 0xBA96, 0x9184, 0xBA97, 0x9185, 0xBA98, 0x9186, 0xBA99, 0x9187, 0xBA9A, 0x9188, 0xBA9B, 0x9189, + 0xBA9C, 0x918A, 0xBA9D, 0x918B, 0xBA9E, 0x918C, 0xBA9F, 0x918D, 0xBAA0, 0x918E, 0xBAA1, 0x918F, 0xBAA2, 0x9190, 0xBAA3, 0x9191, + 0xBAA4, 0x9192, 0xBAA5, 0x9193, 0xBAA6, 0x9194, 0xBAA7, 0x9195, 0xBAA8, 0xB8F0, 0xBAA9, 0xB8F1, 0xBAAA, 0x9196, 0xBAAB, 0xB8F2, + 0xBAAC, 0xB8F3, 0xBAAD, 0x9197, 0xBAAE, 0x9198, 0xBAAF, 0x9199, 0xBAB0, 0xB8F4, 0xBAB1, 0x919A, 0xBAB2, 0xB8F5, 0xBAB3, 0x919B, + 0xBAB4, 0x919C, 0xBAB5, 0x919D, 0xBAB6, 0x919E, 0xBAB7, 0x919F, 0xBAB8, 0xB8F6, 0xBAB9, 0xB8F7, 0xBABA, 0x91A0, 0xBABB, 0xB8F8, + 0xBABC, 0x91A1, 0xBABD, 0xB8F9, 0xBABE, 0x91A2, 0xBABF, 0x91A3, 0xBAC0, 0x91A4, 0xBAC1, 0x91A5, 0xBAC2, 0x91A6, 0xBAC3, 0x91A7, + 0xBAC4, 0xB8FA, 0xBAC5, 0x91A8, 0xBAC6, 0x91A9, 0xBAC7, 0x91AA, 0xBAC8, 0xB8FB, 0xBAC9, 0x91AB, 0xBACA, 0x91AC, 0xBACB, 0x91AD, + 0xBACC, 0x91AE, 0xBACD, 0x91AF, 0xBACE, 0x91B0, 0xBACF, 0x91B1, 0xBAD0, 0x91B2, 0xBAD1, 0x91B3, 0xBAD2, 0x91B4, 0xBAD3, 0x91B5, + 0xBAD4, 0x91B6, 0xBAD5, 0x91B7, 0xBAD6, 0x91B8, 0xBAD7, 0x91B9, 0xBAD8, 0xB8FC, 0xBAD9, 0xB8FD, 0xBADA, 0x91BA, 0xBADB, 0x91BB, + 0xBADC, 0x91BC, 0xBADD, 0x91BD, 0xBADE, 0x91BE, 0xBADF, 0x91BF, 0xBAE0, 0x91C0, 0xBAE1, 0x91C1, 0xBAE2, 0x91C2, 0xBAE3, 0x91C3, + 0xBAE4, 0x91C4, 0xBAE5, 0x91C5, 0xBAE6, 0x91C6, 0xBAE7, 0x91C7, 0xBAE8, 0x91C8, 0xBAE9, 0x91C9, 0xBAEA, 0x91CA, 0xBAEB, 0x91CB, + 0xBAEC, 0x91CC, 0xBAED, 0x91CD, 0xBAEE, 0x91CE, 0xBAEF, 0x91CF, 0xBAF0, 0x91D0, 0xBAF1, 0x91D1, 0xBAF2, 0x91D2, 0xBAF3, 0x91D3, + 0xBAF4, 0x91D4, 0xBAF5, 0x91D5, 0xBAF6, 0x91D6, 0xBAF7, 0x91D7, 0xBAF8, 0x91D8, 0xBAF9, 0x91D9, 0xBAFA, 0x91DA, 0xBAFB, 0x91DB, + 0xBAFC, 0xB8FE, 0xBAFD, 0x91DC, 0xBAFE, 0x91DD, 0xBAFF, 0x91DE, 0xBB00, 0xB9A1, 0xBB01, 0x91DF, 0xBB02, 0x91E0, 0xBB03, 0x91E1, + 0xBB04, 0xB9A2, 0xBB05, 0x91E2, 0xBB06, 0x91E3, 0xBB07, 0x91E4, 0xBB08, 0x91E5, 0xBB09, 0x91E6, 0xBB0A, 0x91E7, 0xBB0B, 0x91E8, + 0xBB0C, 0x91E9, 0xBB0D, 0xB9A3, 0xBB0E, 0x91EA, 0xBB0F, 0xB9A4, 0xBB10, 0x91EB, 0xBB11, 0xB9A5, 0xBB12, 0x91EC, 0xBB13, 0x91ED, + 0xBB14, 0x91EE, 0xBB15, 0x91EF, 0xBB16, 0x91F0, 0xBB17, 0x91F1, 0xBB18, 0xB9A6, 0xBB19, 0x91F2, 0xBB1A, 0x91F3, 0xBB1B, 0x91F4, + 0xBB1C, 0xB9A7, 0xBB1D, 0x91F5, 0xBB1E, 0x91F6, 0xBB1F, 0x91F7, 0xBB20, 0xB9A8, 0xBB21, 0x91F8, 0xBB22, 0x91F9, 0xBB23, 0x91FA, + 0xBB24, 0x91FB, 0xBB25, 0x91FC, 0xBB26, 0x91FD, 0xBB27, 0x91FE, 0xBB28, 0x9241, 0xBB29, 0xB9A9, 0xBB2A, 0x9242, 0xBB2B, 0xB9AA, + 0xBB2C, 0x9243, 0xBB2D, 0x9244, 0xBB2E, 0x9245, 0xBB2F, 0x9246, 0xBB30, 0x9247, 0xBB31, 0x9248, 0xBB32, 0x9249, 0xBB33, 0x924A, + 0xBB34, 0xB9AB, 0xBB35, 0xB9AC, 0xBB36, 0xB9AD, 0xBB37, 0x924B, 0xBB38, 0xB9AE, 0xBB39, 0x924C, 0xBB3A, 0x924D, 0xBB3B, 0xB9AF, + 0xBB3C, 0xB9B0, 0xBB3D, 0xB9B1, 0xBB3E, 0xB9B2, 0xBB3F, 0x924E, 0xBB40, 0x924F, 0xBB41, 0x9250, 0xBB42, 0x9251, 0xBB43, 0x9252, + 0xBB44, 0xB9B3, 0xBB45, 0xB9B4, 0xBB46, 0x9253, 0xBB47, 0xB9B5, 0xBB48, 0x9254, 0xBB49, 0xB9B6, 0xBB4A, 0x9255, 0xBB4B, 0x9256, + 0xBB4C, 0x9257, 0xBB4D, 0xB9B7, 0xBB4E, 0x9258, 0xBB4F, 0xB9B8, 0xBB50, 0xB9B9, 0xBB51, 0x9259, 0xBB52, 0x925A, 0xBB53, 0x9261, + 0xBB54, 0xB9BA, 0xBB55, 0x9262, 0xBB56, 0x9263, 0xBB57, 0x9264, 0xBB58, 0xB9BB, 0xBB59, 0x9265, 0xBB5A, 0x9266, 0xBB5B, 0x9267, + 0xBB5C, 0x9268, 0xBB5D, 0x9269, 0xBB5E, 0x926A, 0xBB5F, 0x926B, 0xBB60, 0x926C, 0xBB61, 0xB9BC, 0xBB62, 0x926D, 0xBB63, 0xB9BD, + 0xBB64, 0x926E, 0xBB65, 0x926F, 0xBB66, 0x9270, 0xBB67, 0x9271, 0xBB68, 0x9272, 0xBB69, 0x9273, 0xBB6A, 0x9274, 0xBB6B, 0x9275, + 0xBB6C, 0xB9BE, 0xBB6D, 0x9276, 0xBB6E, 0x9277, 0xBB6F, 0x9278, 0xBB70, 0x9279, 0xBB71, 0x927A, 0xBB72, 0x9281, 0xBB73, 0x9282, + 0xBB74, 0x9283, 0xBB75, 0x9284, 0xBB76, 0x9285, 0xBB77, 0x9286, 0xBB78, 0x9287, 0xBB79, 0x9288, 0xBB7A, 0x9289, 0xBB7B, 0x928A, + 0xBB7C, 0x928B, 0xBB7D, 0x928C, 0xBB7E, 0x928D, 0xBB7F, 0x928E, 0xBB80, 0x928F, 0xBB81, 0x9290, 0xBB82, 0x9291, 0xBB83, 0x9292, + 0xBB84, 0x9293, 0xBB85, 0x9294, 0xBB86, 0x9295, 0xBB87, 0x9296, 0xBB88, 0xB9BF, 0xBB89, 0x9297, 0xBB8A, 0x9298, 0xBB8B, 0x9299, + 0xBB8C, 0xB9C0, 0xBB8D, 0x929A, 0xBB8E, 0x929B, 0xBB8F, 0x929C, 0xBB90, 0xB9C1, 0xBB91, 0x929D, 0xBB92, 0x929E, 0xBB93, 0x929F, + 0xBB94, 0x92A0, 0xBB95, 0x92A1, 0xBB96, 0x92A2, 0xBB97, 0x92A3, 0xBB98, 0x92A4, 0xBB99, 0x92A5, 0xBB9A, 0x92A6, 0xBB9B, 0x92A7, + 0xBB9C, 0x92A8, 0xBB9D, 0x92A9, 0xBB9E, 0x92AA, 0xBB9F, 0x92AB, 0xBBA0, 0x92AC, 0xBBA1, 0x92AD, 0xBBA2, 0x92AE, 0xBBA3, 0x92AF, + 0xBBA4, 0xB9C2, 0xBBA5, 0x92B0, 0xBBA6, 0x92B1, 0xBBA7, 0x92B2, 0xBBA8, 0xB9C3, 0xBBA9, 0x92B3, 0xBBAA, 0x92B4, 0xBBAB, 0x92B5, + 0xBBAC, 0xB9C4, 0xBBAD, 0x92B6, 0xBBAE, 0x92B7, 0xBBAF, 0x92B8, 0xBBB0, 0x92B9, 0xBBB1, 0x92BA, 0xBBB2, 0x92BB, 0xBBB3, 0x92BC, + 0xBBB4, 0xB9C5, 0xBBB5, 0x92BD, 0xBBB6, 0x92BE, 0xBBB7, 0xB9C6, 0xBBB8, 0x92BF, 0xBBB9, 0x92C0, 0xBBBA, 0x92C1, 0xBBBB, 0x92C2, + 0xBBBC, 0x92C3, 0xBBBD, 0x92C4, 0xBBBE, 0x92C5, 0xBBBF, 0x92C6, 0xBBC0, 0xB9C7, 0xBBC1, 0x92C7, 0xBBC2, 0x92C8, 0xBBC3, 0x92C9, + 0xBBC4, 0xB9C8, 0xBBC5, 0x92CA, 0xBBC6, 0x92CB, 0xBBC7, 0x92CC, 0xBBC8, 0xB9C9, 0xBBC9, 0x92CD, 0xBBCA, 0x92CE, 0xBBCB, 0x92CF, + 0xBBCC, 0x92D0, 0xBBCD, 0x92D1, 0xBBCE, 0x92D2, 0xBBCF, 0x92D3, 0xBBD0, 0xB9CA, 0xBBD1, 0x92D4, 0xBBD2, 0x92D5, 0xBBD3, 0xB9CB, + 0xBBD4, 0x92D6, 0xBBD5, 0x92D7, 0xBBD6, 0x92D8, 0xBBD7, 0x92D9, 0xBBD8, 0x92DA, 0xBBD9, 0x92DB, 0xBBDA, 0x92DC, 0xBBDB, 0x92DD, + 0xBBDC, 0x92DE, 0xBBDD, 0x92DF, 0xBBDE, 0x92E0, 0xBBDF, 0x92E1, 0xBBE0, 0x92E2, 0xBBE1, 0x92E3, 0xBBE2, 0x92E4, 0xBBE3, 0x92E5, + 0xBBE4, 0x92E6, 0xBBE5, 0x92E7, 0xBBE6, 0x92E8, 0xBBE7, 0x92E9, 0xBBE8, 0x92EA, 0xBBE9, 0x92EB, 0xBBEA, 0x92EC, 0xBBEB, 0x92ED, + 0xBBEC, 0x92EE, 0xBBED, 0x92EF, 0xBBEE, 0x92F0, 0xBBEF, 0x92F1, 0xBBF0, 0x92F2, 0xBBF1, 0x92F3, 0xBBF2, 0x92F4, 0xBBF3, 0x92F5, + 0xBBF4, 0x92F6, 0xBBF5, 0x92F7, 0xBBF6, 0x92F8, 0xBBF7, 0x92F9, 0xBBF8, 0xB9CC, 0xBBF9, 0xB9CD, 0xBBFA, 0x92FA, 0xBBFB, 0x92FB, + 0xBBFC, 0xB9CE, 0xBBFD, 0x92FC, 0xBBFE, 0x92FD, 0xBBFF, 0xB9CF, 0xBC00, 0xB9D0, 0xBC01, 0x92FE, 0xBC02, 0xB9D1, 0xBC03, 0x9341, + 0xBC04, 0x9342, 0xBC05, 0x9343, 0xBC06, 0x9344, 0xBC07, 0x9345, 0xBC08, 0xB9D2, 0xBC09, 0xB9D3, 0xBC0A, 0x9346, 0xBC0B, 0xB9D4, + 0xBC0C, 0xB9D5, 0xBC0D, 0xB9D6, 0xBC0E, 0x9347, 0xBC0F, 0xB9D7, 0xBC10, 0x9348, 0xBC11, 0xB9D8, 0xBC12, 0x9349, 0xBC13, 0x934A, + 0xBC14, 0xB9D9, 0xBC15, 0xB9DA, 0xBC16, 0xB9DB, 0xBC17, 0xB9DC, 0xBC18, 0xB9DD, 0xBC19, 0x934B, 0xBC1A, 0x934C, 0xBC1B, 0xB9DE, + 0xBC1C, 0xB9DF, 0xBC1D, 0xB9E0, 0xBC1E, 0xB9E1, 0xBC1F, 0xB9E2, 0xBC20, 0x934D, 0xBC21, 0x934E, 0xBC22, 0x934F, 0xBC23, 0x9350, + 0xBC24, 0xB9E3, 0xBC25, 0xB9E4, 0xBC26, 0x9351, 0xBC27, 0xB9E5, 0xBC28, 0x9352, 0xBC29, 0xB9E6, 0xBC2A, 0x9353, 0xBC2B, 0x9354, + 0xBC2C, 0x9355, 0xBC2D, 0xB9E7, 0xBC2E, 0x9356, 0xBC2F, 0x9357, 0xBC30, 0xB9E8, 0xBC31, 0xB9E9, 0xBC32, 0x9358, 0xBC33, 0x9359, + 0xBC34, 0xB9EA, 0xBC35, 0x935A, 0xBC36, 0x9361, 0xBC37, 0x9362, 0xBC38, 0xB9EB, 0xBC39, 0x9363, 0xBC3A, 0x9364, 0xBC3B, 0x9365, + 0xBC3C, 0x9366, 0xBC3D, 0x9367, 0xBC3E, 0x9368, 0xBC3F, 0x9369, 0xBC40, 0xB9EC, 0xBC41, 0xB9ED, 0xBC42, 0x936A, 0xBC43, 0xB9EE, + 0xBC44, 0xB9EF, 0xBC45, 0xB9F0, 0xBC46, 0x936B, 0xBC47, 0x936C, 0xBC48, 0x936D, 0xBC49, 0xB9F1, 0xBC4A, 0x936E, 0xBC4B, 0x936F, + 0xBC4C, 0xB9F2, 0xBC4D, 0xB9F3, 0xBC4E, 0x9370, 0xBC4F, 0x9371, 0xBC50, 0xB9F4, 0xBC51, 0x9372, 0xBC52, 0x9373, 0xBC53, 0x9374, + 0xBC54, 0x9375, 0xBC55, 0x9376, 0xBC56, 0x9377, 0xBC57, 0x9378, 0xBC58, 0x9379, 0xBC59, 0x937A, 0xBC5A, 0x9381, 0xBC5B, 0x9382, + 0xBC5C, 0x9383, 0xBC5D, 0xB9F5, 0xBC5E, 0x9384, 0xBC5F, 0x9385, 0xBC60, 0x9386, 0xBC61, 0x9387, 0xBC62, 0x9388, 0xBC63, 0x9389, + 0xBC64, 0x938A, 0xBC65, 0x938B, 0xBC66, 0x938C, 0xBC67, 0x938D, 0xBC68, 0x938E, 0xBC69, 0x938F, 0xBC6A, 0x9390, 0xBC6B, 0x9391, + 0xBC6C, 0x9392, 0xBC6D, 0x9393, 0xBC6E, 0x9394, 0xBC6F, 0x9395, 0xBC70, 0x9396, 0xBC71, 0x9397, 0xBC72, 0x9398, 0xBC73, 0x9399, + 0xBC74, 0x939A, 0xBC75, 0x939B, 0xBC76, 0x939C, 0xBC77, 0x939D, 0xBC78, 0x939E, 0xBC79, 0x939F, 0xBC7A, 0x93A0, 0xBC7B, 0x93A1, + 0xBC7C, 0x93A2, 0xBC7D, 0x93A3, 0xBC7E, 0x93A4, 0xBC7F, 0x93A5, 0xBC80, 0x93A6, 0xBC81, 0x93A7, 0xBC82, 0x93A8, 0xBC83, 0x93A9, + 0xBC84, 0xB9F6, 0xBC85, 0xB9F7, 0xBC86, 0x93AA, 0xBC87, 0x93AB, 0xBC88, 0xB9F8, 0xBC89, 0x93AC, 0xBC8A, 0x93AD, 0xBC8B, 0xB9F9, + 0xBC8C, 0xB9FA, 0xBC8D, 0x93AE, 0xBC8E, 0xB9FB, 0xBC8F, 0x93AF, 0xBC90, 0x93B0, 0xBC91, 0x93B1, 0xBC92, 0x93B2, 0xBC93, 0x93B3, + 0xBC94, 0xB9FC, 0xBC95, 0xB9FD, 0xBC96, 0x93B4, 0xBC97, 0xB9FE, 0xBC98, 0x93B5, 0xBC99, 0xBAA1, 0xBC9A, 0xBAA2, 0xBC9B, 0x93B6, + 0xBC9C, 0x93B7, 0xBC9D, 0x93B8, 0xBC9E, 0x93B9, 0xBC9F, 0x93BA, 0xBCA0, 0xBAA3, 0xBCA1, 0xBAA4, 0xBCA2, 0x93BB, 0xBCA3, 0x93BC, + 0xBCA4, 0xBAA5, 0xBCA5, 0x93BD, 0xBCA6, 0x93BE, 0xBCA7, 0xBAA6, 0xBCA8, 0xBAA7, 0xBCA9, 0x93BF, 0xBCAA, 0x93C0, 0xBCAB, 0x93C1, + 0xBCAC, 0x93C2, 0xBCAD, 0x93C3, 0xBCAE, 0x93C4, 0xBCAF, 0x93C5, 0xBCB0, 0xBAA8, 0xBCB1, 0xBAA9, 0xBCB2, 0x93C6, 0xBCB3, 0xBAAA, + 0xBCB4, 0xBAAB, 0xBCB5, 0xBAAC, 0xBCB6, 0x93C7, 0xBCB7, 0x93C8, 0xBCB8, 0x93C9, 0xBCB9, 0x93CA, 0xBCBA, 0x93CB, 0xBCBB, 0x93CC, + 0xBCBC, 0xBAAD, 0xBCBD, 0xBAAE, 0xBCBE, 0x93CD, 0xBCBF, 0x93CE, 0xBCC0, 0xBAAF, 0xBCC1, 0x93CF, 0xBCC2, 0x93D0, 0xBCC3, 0x93D1, + 0xBCC4, 0xBAB0, 0xBCC5, 0x93D2, 0xBCC6, 0x93D3, 0xBCC7, 0x93D4, 0xBCC8, 0x93D5, 0xBCC9, 0x93D6, 0xBCCA, 0x93D7, 0xBCCB, 0x93D8, + 0xBCCC, 0x93D9, 0xBCCD, 0xBAB1, 0xBCCE, 0x93DA, 0xBCCF, 0xBAB2, 0xBCD0, 0xBAB3, 0xBCD1, 0xBAB4, 0xBCD2, 0x93DB, 0xBCD3, 0x93DC, + 0xBCD4, 0x93DD, 0xBCD5, 0xBAB5, 0xBCD6, 0x93DE, 0xBCD7, 0x93DF, 0xBCD8, 0xBAB6, 0xBCD9, 0x93E0, 0xBCDA, 0x93E1, 0xBCDB, 0x93E2, + 0xBCDC, 0xBAB7, 0xBCDD, 0x93E3, 0xBCDE, 0x93E4, 0xBCDF, 0x93E5, 0xBCE0, 0x93E6, 0xBCE1, 0x93E7, 0xBCE2, 0x93E8, 0xBCE3, 0x93E9, + 0xBCE4, 0x93EA, 0xBCE5, 0x93EB, 0xBCE6, 0x93EC, 0xBCE7, 0x93ED, 0xBCE8, 0x93EE, 0xBCE9, 0x93EF, 0xBCEA, 0x93F0, 0xBCEB, 0x93F1, + 0xBCEC, 0x93F2, 0xBCED, 0x93F3, 0xBCEE, 0x93F4, 0xBCEF, 0x93F5, 0xBCF0, 0x93F6, 0xBCF1, 0x93F7, 0xBCF2, 0x93F8, 0xBCF3, 0x93F9, + 0xBCF4, 0xBAB8, 0xBCF5, 0xBAB9, 0xBCF6, 0xBABA, 0xBCF7, 0x93FA, 0xBCF8, 0xBABB, 0xBCF9, 0x93FB, 0xBCFA, 0x93FC, 0xBCFB, 0x93FD, + 0xBCFC, 0xBABC, 0xBCFD, 0x93FE, 0xBCFE, 0x9441, 0xBCFF, 0x9442, 0xBD00, 0x9443, 0xBD01, 0x9444, 0xBD02, 0x9445, 0xBD03, 0x9446, + 0xBD04, 0xBABD, 0xBD05, 0xBABE, 0xBD06, 0x9447, 0xBD07, 0xBABF, 0xBD08, 0x9448, 0xBD09, 0xBAC0, 0xBD0A, 0x9449, 0xBD0B, 0x944A, + 0xBD0C, 0x944B, 0xBD0D, 0x944C, 0xBD0E, 0x944D, 0xBD0F, 0x944E, 0xBD10, 0xBAC1, 0xBD11, 0x944F, 0xBD12, 0x9450, 0xBD13, 0x9451, + 0xBD14, 0xBAC2, 0xBD15, 0x9452, 0xBD16, 0x9453, 0xBD17, 0x9454, 0xBD18, 0x9455, 0xBD19, 0x9456, 0xBD1A, 0x9457, 0xBD1B, 0x9458, + 0xBD1C, 0x9459, 0xBD1D, 0x945A, 0xBD1E, 0x9461, 0xBD1F, 0x9462, 0xBD20, 0x9463, 0xBD21, 0x9464, 0xBD22, 0x9465, 0xBD23, 0x9466, + 0xBD24, 0xBAC3, 0xBD25, 0x9467, 0xBD26, 0x9468, 0xBD27, 0x9469, 0xBD28, 0x946A, 0xBD29, 0x946B, 0xBD2A, 0x946C, 0xBD2B, 0x946D, + 0xBD2C, 0xBAC4, 0xBD2D, 0x946E, 0xBD2E, 0x946F, 0xBD2F, 0x9470, 0xBD30, 0x9471, 0xBD31, 0x9472, 0xBD32, 0x9473, 0xBD33, 0x9474, + 0xBD34, 0x9475, 0xBD35, 0x9476, 0xBD36, 0x9477, 0xBD37, 0x9478, 0xBD38, 0x9479, 0xBD39, 0x947A, 0xBD3A, 0x9481, 0xBD3B, 0x9482, + 0xBD3C, 0x9483, 0xBD3D, 0x9484, 0xBD3E, 0x9485, 0xBD3F, 0x9486, 0xBD40, 0xBAC5, 0xBD41, 0x9487, 0xBD42, 0x9488, 0xBD43, 0x9489, + 0xBD44, 0x948A, 0xBD45, 0x948B, 0xBD46, 0x948C, 0xBD47, 0x948D, 0xBD48, 0xBAC6, 0xBD49, 0xBAC7, 0xBD4A, 0x948E, 0xBD4B, 0x948F, + 0xBD4C, 0xBAC8, 0xBD4D, 0x9490, 0xBD4E, 0x9491, 0xBD4F, 0x9492, 0xBD50, 0xBAC9, 0xBD51, 0x9493, 0xBD52, 0x9494, 0xBD53, 0x9495, + 0xBD54, 0x9496, 0xBD55, 0x9497, 0xBD56, 0x9498, 0xBD57, 0x9499, 0xBD58, 0xBACA, 0xBD59, 0xBACB, 0xBD5A, 0x949A, 0xBD5B, 0x949B, + 0xBD5C, 0x949C, 0xBD5D, 0x949D, 0xBD5E, 0x949E, 0xBD5F, 0x949F, 0xBD60, 0x94A0, 0xBD61, 0x94A1, 0xBD62, 0x94A2, 0xBD63, 0x94A3, + 0xBD64, 0xBACC, 0xBD65, 0x94A4, 0xBD66, 0x94A5, 0xBD67, 0x94A6, 0xBD68, 0xBACD, 0xBD69, 0x94A7, 0xBD6A, 0x94A8, 0xBD6B, 0x94A9, + 0xBD6C, 0x94AA, 0xBD6D, 0x94AB, 0xBD6E, 0x94AC, 0xBD6F, 0x94AD, 0xBD70, 0x94AE, 0xBD71, 0x94AF, 0xBD72, 0x94B0, 0xBD73, 0x94B1, + 0xBD74, 0x94B2, 0xBD75, 0x94B3, 0xBD76, 0x94B4, 0xBD77, 0x94B5, 0xBD78, 0x94B6, 0xBD79, 0x94B7, 0xBD7A, 0x94B8, 0xBD7B, 0x94B9, + 0xBD7C, 0x94BA, 0xBD7D, 0x94BB, 0xBD7E, 0x94BC, 0xBD7F, 0x94BD, 0xBD80, 0xBACE, 0xBD81, 0xBACF, 0xBD82, 0x94BE, 0xBD83, 0x94BF, + 0xBD84, 0xBAD0, 0xBD85, 0x94C0, 0xBD86, 0x94C1, 0xBD87, 0xBAD1, 0xBD88, 0xBAD2, 0xBD89, 0xBAD3, 0xBD8A, 0xBAD4, 0xBD8B, 0x94C2, + 0xBD8C, 0x94C3, 0xBD8D, 0x94C4, 0xBD8E, 0x94C5, 0xBD8F, 0x94C6, 0xBD90, 0xBAD5, 0xBD91, 0xBAD6, 0xBD92, 0x94C7, 0xBD93, 0xBAD7, + 0xBD94, 0x94C8, 0xBD95, 0xBAD8, 0xBD96, 0x94C9, 0xBD97, 0x94CA, 0xBD98, 0x94CB, 0xBD99, 0xBAD9, 0xBD9A, 0xBADA, 0xBD9B, 0x94CC, + 0xBD9C, 0xBADB, 0xBD9D, 0x94CD, 0xBD9E, 0x94CE, 0xBD9F, 0x94CF, 0xBDA0, 0x94D0, 0xBDA1, 0x94D1, 0xBDA2, 0x94D2, 0xBDA3, 0x94D3, + 0xBDA4, 0xBADC, 0xBDA5, 0x94D4, 0xBDA6, 0x94D5, 0xBDA7, 0x94D6, 0xBDA8, 0x94D7, 0xBDA9, 0x94D8, 0xBDAA, 0x94D9, 0xBDAB, 0x94DA, + 0xBDAC, 0x94DB, 0xBDAD, 0x94DC, 0xBDAE, 0x94DD, 0xBDAF, 0x94DE, 0xBDB0, 0xBADD, 0xBDB1, 0x94DF, 0xBDB2, 0x94E0, 0xBDB3, 0x94E1, + 0xBDB4, 0x94E2, 0xBDB5, 0x94E3, 0xBDB6, 0x94E4, 0xBDB7, 0x94E5, 0xBDB8, 0xBADE, 0xBDB9, 0x94E6, 0xBDBA, 0x94E7, 0xBDBB, 0x94E8, + 0xBDBC, 0x94E9, 0xBDBD, 0x94EA, 0xBDBE, 0x94EB, 0xBDBF, 0x94EC, 0xBDC0, 0x94ED, 0xBDC1, 0x94EE, 0xBDC2, 0x94EF, 0xBDC3, 0x94F0, + 0xBDC4, 0x94F1, 0xBDC5, 0x94F2, 0xBDC6, 0x94F3, 0xBDC7, 0x94F4, 0xBDC8, 0x94F5, 0xBDC9, 0x94F6, 0xBDCA, 0x94F7, 0xBDCB, 0x94F8, + 0xBDCC, 0x94F9, 0xBDCD, 0x94FA, 0xBDCE, 0x94FB, 0xBDCF, 0x94FC, 0xBDD0, 0x94FD, 0xBDD1, 0x94FE, 0xBDD2, 0x9541, 0xBDD3, 0x9542, + 0xBDD4, 0xBADF, 0xBDD5, 0xBAE0, 0xBDD6, 0x9543, 0xBDD7, 0x9544, 0xBDD8, 0xBAE1, 0xBDD9, 0x9545, 0xBDDA, 0x9546, 0xBDDB, 0x9547, + 0xBDDC, 0xBAE2, 0xBDDD, 0x9548, 0xBDDE, 0x9549, 0xBDDF, 0x954A, 0xBDE0, 0x954B, 0xBDE1, 0x954C, 0xBDE2, 0x954D, 0xBDE3, 0x954E, + 0xBDE4, 0x954F, 0xBDE5, 0x9550, 0xBDE6, 0x9551, 0xBDE7, 0x9552, 0xBDE8, 0x9553, 0xBDE9, 0xBAE3, 0xBDEA, 0x9554, 0xBDEB, 0x9555, + 0xBDEC, 0x9556, 0xBDED, 0x9557, 0xBDEE, 0x9558, 0xBDEF, 0x9559, 0xBDF0, 0xBAE4, 0xBDF1, 0x955A, 0xBDF2, 0x9561, 0xBDF3, 0x9562, + 0xBDF4, 0xBAE5, 0xBDF5, 0x9563, 0xBDF6, 0x9564, 0xBDF7, 0x9565, 0xBDF8, 0xBAE6, 0xBDF9, 0x9566, 0xBDFA, 0x9567, 0xBDFB, 0x9568, + 0xBDFC, 0x9569, 0xBDFD, 0x956A, 0xBDFE, 0x956B, 0xBDFF, 0x956C, 0xBE00, 0xBAE7, 0xBE01, 0x956D, 0xBE02, 0x956E, 0xBE03, 0xBAE8, + 0xBE04, 0x956F, 0xBE05, 0xBAE9, 0xBE06, 0x9570, 0xBE07, 0x9571, 0xBE08, 0x9572, 0xBE09, 0x9573, 0xBE0A, 0x9574, 0xBE0B, 0x9575, + 0xBE0C, 0xBAEA, 0xBE0D, 0xBAEB, 0xBE0E, 0x9576, 0xBE0F, 0x9577, 0xBE10, 0xBAEC, 0xBE11, 0x9578, 0xBE12, 0x9579, 0xBE13, 0x957A, + 0xBE14, 0xBAED, 0xBE15, 0x9581, 0xBE16, 0x9582, 0xBE17, 0x9583, 0xBE18, 0x9584, 0xBE19, 0x9585, 0xBE1A, 0x9586, 0xBE1B, 0x9587, + 0xBE1C, 0xBAEE, 0xBE1D, 0xBAEF, 0xBE1E, 0x9588, 0xBE1F, 0xBAF0, 0xBE20, 0x9589, 0xBE21, 0x958A, 0xBE22, 0x958B, 0xBE23, 0x958C, + 0xBE24, 0x958D, 0xBE25, 0x958E, 0xBE26, 0x958F, 0xBE27, 0x9590, 0xBE28, 0x9591, 0xBE29, 0x9592, 0xBE2A, 0x9593, 0xBE2B, 0x9594, + 0xBE2C, 0x9595, 0xBE2D, 0x9596, 0xBE2E, 0x9597, 0xBE2F, 0x9598, 0xBE30, 0x9599, 0xBE31, 0x959A, 0xBE32, 0x959B, 0xBE33, 0x959C, + 0xBE34, 0x959D, 0xBE35, 0x959E, 0xBE36, 0x959F, 0xBE37, 0x95A0, 0xBE38, 0x95A1, 0xBE39, 0x95A2, 0xBE3A, 0x95A3, 0xBE3B, 0x95A4, + 0xBE3C, 0x95A5, 0xBE3D, 0x95A6, 0xBE3E, 0x95A7, 0xBE3F, 0x95A8, 0xBE40, 0x95A9, 0xBE41, 0x95AA, 0xBE42, 0x95AB, 0xBE43, 0x95AC, + 0xBE44, 0xBAF1, 0xBE45, 0xBAF2, 0xBE46, 0x95AD, 0xBE47, 0x95AE, 0xBE48, 0xBAF3, 0xBE49, 0x95AF, 0xBE4A, 0x95B0, 0xBE4B, 0x95B1, + 0xBE4C, 0xBAF4, 0xBE4D, 0x95B2, 0xBE4E, 0xBAF5, 0xBE4F, 0x95B3, 0xBE50, 0x95B4, 0xBE51, 0x95B5, 0xBE52, 0x95B6, 0xBE53, 0x95B7, + 0xBE54, 0xBAF6, 0xBE55, 0xBAF7, 0xBE56, 0x95B8, 0xBE57, 0xBAF8, 0xBE58, 0x95B9, 0xBE59, 0xBAF9, 0xBE5A, 0xBAFA, 0xBE5B, 0xBAFB, + 0xBE5C, 0x95BA, 0xBE5D, 0x95BB, 0xBE5E, 0x95BC, 0xBE5F, 0x95BD, 0xBE60, 0xBAFC, 0xBE61, 0xBAFD, 0xBE62, 0x95BE, 0xBE63, 0x95BF, + 0xBE64, 0xBAFE, 0xBE65, 0x95C0, 0xBE66, 0x95C1, 0xBE67, 0x95C2, 0xBE68, 0xBBA1, 0xBE69, 0x95C3, 0xBE6A, 0xBBA2, 0xBE6B, 0x95C4, + 0xBE6C, 0x95C5, 0xBE6D, 0x95C6, 0xBE6E, 0x95C7, 0xBE6F, 0x95C8, 0xBE70, 0xBBA3, 0xBE71, 0xBBA4, 0xBE72, 0x95C9, 0xBE73, 0xBBA5, + 0xBE74, 0xBBA6, 0xBE75, 0xBBA7, 0xBE76, 0x95CA, 0xBE77, 0x95CB, 0xBE78, 0x95CC, 0xBE79, 0x95CD, 0xBE7A, 0x95CE, 0xBE7B, 0xBBA8, + 0xBE7C, 0xBBA9, 0xBE7D, 0xBBAA, 0xBE7E, 0x95CF, 0xBE7F, 0x95D0, 0xBE80, 0xBBAB, 0xBE81, 0x95D1, 0xBE82, 0x95D2, 0xBE83, 0x95D3, + 0xBE84, 0xBBAC, 0xBE85, 0x95D4, 0xBE86, 0x95D5, 0xBE87, 0x95D6, 0xBE88, 0x95D7, 0xBE89, 0x95D8, 0xBE8A, 0x95D9, 0xBE8B, 0x95DA, + 0xBE8C, 0xBBAD, 0xBE8D, 0xBBAE, 0xBE8E, 0x95DB, 0xBE8F, 0xBBAF, 0xBE90, 0xBBB0, 0xBE91, 0xBBB1, 0xBE92, 0x95DC, 0xBE93, 0x95DD, + 0xBE94, 0x95DE, 0xBE95, 0x95DF, 0xBE96, 0x95E0, 0xBE97, 0x95E1, 0xBE98, 0xBBB2, 0xBE99, 0xBBB3, 0xBE9A, 0x95E2, 0xBE9B, 0x95E3, + 0xBE9C, 0x95E4, 0xBE9D, 0x95E5, 0xBE9E, 0x95E6, 0xBE9F, 0x95E7, 0xBEA0, 0x95E8, 0xBEA1, 0x95E9, 0xBEA2, 0x95EA, 0xBEA3, 0x95EB, + 0xBEA4, 0x95EC, 0xBEA5, 0x95ED, 0xBEA6, 0x95EE, 0xBEA7, 0x95EF, 0xBEA8, 0xBBB4, 0xBEA9, 0x95F0, 0xBEAA, 0x95F1, 0xBEAB, 0x95F2, + 0xBEAC, 0x95F3, 0xBEAD, 0x95F4, 0xBEAE, 0x95F5, 0xBEAF, 0x95F6, 0xBEB0, 0x95F7, 0xBEB1, 0x95F8, 0xBEB2, 0x95F9, 0xBEB3, 0x95FA, + 0xBEB4, 0x95FB, 0xBEB5, 0x95FC, 0xBEB6, 0x95FD, 0xBEB7, 0x95FE, 0xBEB8, 0x9641, 0xBEB9, 0x9642, 0xBEBA, 0x9643, 0xBEBB, 0x9644, + 0xBEBC, 0x9645, 0xBEBD, 0x9646, 0xBEBE, 0x9647, 0xBEBF, 0x9648, 0xBEC0, 0x9649, 0xBEC1, 0x964A, 0xBEC2, 0x964B, 0xBEC3, 0x964C, + 0xBEC4, 0x964D, 0xBEC5, 0x964E, 0xBEC6, 0x964F, 0xBEC7, 0x9650, 0xBEC8, 0x9651, 0xBEC9, 0x9652, 0xBECA, 0x9653, 0xBECB, 0x9654, + 0xBECC, 0x9655, 0xBECD, 0x9656, 0xBECE, 0x9657, 0xBECF, 0x9658, 0xBED0, 0xBBB5, 0xBED1, 0xBBB6, 0xBED2, 0x9659, 0xBED3, 0x965A, + 0xBED4, 0xBBB7, 0xBED5, 0x9661, 0xBED6, 0x9662, 0xBED7, 0xBBB8, 0xBED8, 0xBBB9, 0xBED9, 0x9663, 0xBEDA, 0x9664, 0xBEDB, 0x9665, + 0xBEDC, 0x9666, 0xBEDD, 0x9667, 0xBEDE, 0x9668, 0xBEDF, 0x9669, 0xBEE0, 0xBBBA, 0xBEE1, 0x966A, 0xBEE2, 0x966B, 0xBEE3, 0xBBBB, + 0xBEE4, 0xBBBC, 0xBEE5, 0xBBBD, 0xBEE6, 0x966C, 0xBEE7, 0x966D, 0xBEE8, 0x966E, 0xBEE9, 0x966F, 0xBEEA, 0x9670, 0xBEEB, 0x9671, + 0xBEEC, 0xBBBE, 0xBEED, 0x9672, 0xBEEE, 0x9673, 0xBEEF, 0x9674, 0xBEF0, 0x9675, 0xBEF1, 0x9676, 0xBEF2, 0x9677, 0xBEF3, 0x9678, + 0xBEF4, 0x9679, 0xBEF5, 0x967A, 0xBEF6, 0x9681, 0xBEF7, 0x9682, 0xBEF8, 0x9683, 0xBEF9, 0x9684, 0xBEFA, 0x9685, 0xBEFB, 0x9686, + 0xBEFC, 0x9687, 0xBEFD, 0x9688, 0xBEFE, 0x9689, 0xBEFF, 0x968A, 0xBF00, 0x968B, 0xBF01, 0xBBBF, 0xBF02, 0x968C, 0xBF03, 0x968D, + 0xBF04, 0x968E, 0xBF05, 0x968F, 0xBF06, 0x9690, 0xBF07, 0x9691, 0xBF08, 0xBBC0, 0xBF09, 0xBBC1, 0xBF0A, 0x9692, 0xBF0B, 0x9693, + 0xBF0C, 0x9694, 0xBF0D, 0x9695, 0xBF0E, 0x9696, 0xBF0F, 0x9697, 0xBF10, 0x9698, 0xBF11, 0x9699, 0xBF12, 0x969A, 0xBF13, 0x969B, + 0xBF14, 0x969C, 0xBF15, 0x969D, 0xBF16, 0x969E, 0xBF17, 0x969F, 0xBF18, 0xBBC2, 0xBF19, 0xBBC3, 0xBF1A, 0x96A0, 0xBF1B, 0xBBC4, + 0xBF1C, 0xBBC5, 0xBF1D, 0xBBC6, 0xBF1E, 0x96A1, 0xBF1F, 0x96A2, 0xBF20, 0x96A3, 0xBF21, 0x96A4, 0xBF22, 0x96A5, 0xBF23, 0x96A6, + 0xBF24, 0x96A7, 0xBF25, 0x96A8, 0xBF26, 0x96A9, 0xBF27, 0x96AA, 0xBF28, 0x96AB, 0xBF29, 0x96AC, 0xBF2A, 0x96AD, 0xBF2B, 0x96AE, + 0xBF2C, 0x96AF, 0xBF2D, 0x96B0, 0xBF2E, 0x96B1, 0xBF2F, 0x96B2, 0xBF30, 0x96B3, 0xBF31, 0x96B4, 0xBF32, 0x96B5, 0xBF33, 0x96B6, + 0xBF34, 0x96B7, 0xBF35, 0x96B8, 0xBF36, 0x96B9, 0xBF37, 0x96BA, 0xBF38, 0x96BB, 0xBF39, 0x96BC, 0xBF3A, 0x96BD, 0xBF3B, 0x96BE, + 0xBF3C, 0x96BF, 0xBF3D, 0x96C0, 0xBF3E, 0x96C1, 0xBF3F, 0x96C2, 0xBF40, 0xBBC7, 0xBF41, 0xBBC8, 0xBF42, 0x96C3, 0xBF43, 0x96C4, + 0xBF44, 0xBBC9, 0xBF45, 0x96C5, 0xBF46, 0x96C6, 0xBF47, 0x96C7, 0xBF48, 0xBBCA, 0xBF49, 0x96C8, 0xBF4A, 0x96C9, 0xBF4B, 0x96CA, + 0xBF4C, 0x96CB, 0xBF4D, 0x96CC, 0xBF4E, 0x96CD, 0xBF4F, 0x96CE, 0xBF50, 0xBBCB, 0xBF51, 0xBBCC, 0xBF52, 0x96CF, 0xBF53, 0x96D0, + 0xBF54, 0x96D1, 0xBF55, 0xBBCD, 0xBF56, 0x96D2, 0xBF57, 0x96D3, 0xBF58, 0x96D4, 0xBF59, 0x96D5, 0xBF5A, 0x96D6, 0xBF5B, 0x96D7, + 0xBF5C, 0x96D8, 0xBF5D, 0x96D9, 0xBF5E, 0x96DA, 0xBF5F, 0x96DB, 0xBF60, 0x96DC, 0xBF61, 0x96DD, 0xBF62, 0x96DE, 0xBF63, 0x96DF, + 0xBF64, 0x96E0, 0xBF65, 0x96E1, 0xBF66, 0x96E2, 0xBF67, 0x96E3, 0xBF68, 0x96E4, 0xBF69, 0x96E5, 0xBF6A, 0x96E6, 0xBF6B, 0x96E7, + 0xBF6C, 0x96E8, 0xBF6D, 0x96E9, 0xBF6E, 0x96EA, 0xBF6F, 0x96EB, 0xBF70, 0x96EC, 0xBF71, 0x96ED, 0xBF72, 0x96EE, 0xBF73, 0x96EF, + 0xBF74, 0x96F0, 0xBF75, 0x96F1, 0xBF76, 0x96F2, 0xBF77, 0x96F3, 0xBF78, 0x96F4, 0xBF79, 0x96F5, 0xBF7A, 0x96F6, 0xBF7B, 0x96F7, + 0xBF7C, 0x96F8, 0xBF7D, 0x96F9, 0xBF7E, 0x96FA, 0xBF7F, 0x96FB, 0xBF80, 0x96FC, 0xBF81, 0x96FD, 0xBF82, 0x96FE, 0xBF83, 0x9741, + 0xBF84, 0x9742, 0xBF85, 0x9743, 0xBF86, 0x9744, 0xBF87, 0x9745, 0xBF88, 0x9746, 0xBF89, 0x9747, 0xBF8A, 0x9748, 0xBF8B, 0x9749, + 0xBF8C, 0x974A, 0xBF8D, 0x974B, 0xBF8E, 0x974C, 0xBF8F, 0x974D, 0xBF90, 0x974E, 0xBF91, 0x974F, 0xBF92, 0x9750, 0xBF93, 0x9751, + 0xBF94, 0xBBCE, 0xBF95, 0x9752, 0xBF96, 0x9753, 0xBF97, 0x9754, 0xBF98, 0x9755, 0xBF99, 0x9756, 0xBF9A, 0x9757, 0xBF9B, 0x9758, + 0xBF9C, 0x9759, 0xBF9D, 0x975A, 0xBF9E, 0x9761, 0xBF9F, 0x9762, 0xBFA0, 0x9763, 0xBFA1, 0x9764, 0xBFA2, 0x9765, 0xBFA3, 0x9766, + 0xBFA4, 0x9767, 0xBFA5, 0x9768, 0xBFA6, 0x9769, 0xBFA7, 0x976A, 0xBFA8, 0x976B, 0xBFA9, 0x976C, 0xBFAA, 0x976D, 0xBFAB, 0x976E, + 0xBFAC, 0x976F, 0xBFAD, 0x9770, 0xBFAE, 0x9771, 0xBFAF, 0x9772, 0xBFB0, 0xBBCF, 0xBFB1, 0x9773, 0xBFB2, 0x9774, 0xBFB3, 0x9775, + 0xBFB4, 0x9776, 0xBFB5, 0x9777, 0xBFB6, 0x9778, 0xBFB7, 0x9779, 0xBFB8, 0x977A, 0xBFB9, 0x9781, 0xBFBA, 0x9782, 0xBFBB, 0x9783, + 0xBFBC, 0x9784, 0xBFBD, 0x9785, 0xBFBE, 0x9786, 0xBFBF, 0x9787, 0xBFC0, 0x9788, 0xBFC1, 0x9789, 0xBFC2, 0x978A, 0xBFC3, 0x978B, + 0xBFC4, 0x978C, 0xBFC5, 0xBBD0, 0xBFC6, 0x978D, 0xBFC7, 0x978E, 0xBFC8, 0x978F, 0xBFC9, 0x9790, 0xBFCA, 0x9791, 0xBFCB, 0x9792, + 0xBFCC, 0xBBD1, 0xBFCD, 0xBBD2, 0xBFCE, 0x9793, 0xBFCF, 0x9794, 0xBFD0, 0xBBD3, 0xBFD1, 0x9795, 0xBFD2, 0x9796, 0xBFD3, 0x9797, + 0xBFD4, 0xBBD4, 0xBFD5, 0x9798, 0xBFD6, 0x9799, 0xBFD7, 0x979A, 0xBFD8, 0x979B, 0xBFD9, 0x979C, 0xBFDA, 0x979D, 0xBFDB, 0x979E, + 0xBFDC, 0xBBD5, 0xBFDD, 0x979F, 0xBFDE, 0x97A0, 0xBFDF, 0xBBD6, 0xBFE0, 0x97A1, 0xBFE1, 0xBBD7, 0xBFE2, 0x97A2, 0xBFE3, 0x97A3, + 0xBFE4, 0x97A4, 0xBFE5, 0x97A5, 0xBFE6, 0x97A6, 0xBFE7, 0x97A7, 0xBFE8, 0x97A8, 0xBFE9, 0x97A9, 0xBFEA, 0x97AA, 0xBFEB, 0x97AB, + 0xBFEC, 0x97AC, 0xBFED, 0x97AD, 0xBFEE, 0x97AE, 0xBFEF, 0x97AF, 0xBFF0, 0x97B0, 0xBFF1, 0x97B1, 0xBFF2, 0x97B2, 0xBFF3, 0x97B3, + 0xBFF4, 0x97B4, 0xBFF5, 0x97B5, 0xBFF6, 0x97B6, 0xBFF7, 0x97B7, 0xBFF8, 0x97B8, 0xBFF9, 0x97B9, 0xBFFA, 0x97BA, 0xBFFB, 0x97BB, + 0xBFFC, 0x97BC, 0xBFFD, 0x97BD, 0xBFFE, 0x97BE, 0xBFFF, 0x97BF, 0xC000, 0x97C0, 0xC001, 0x97C1, 0xC002, 0x97C2, 0xC003, 0x97C3, + 0xC004, 0x97C4, 0xC005, 0x97C5, 0xC006, 0x97C6, 0xC007, 0x97C7, 0xC008, 0x97C8, 0xC009, 0x97C9, 0xC00A, 0x97CA, 0xC00B, 0x97CB, + 0xC00C, 0x97CC, 0xC00D, 0x97CD, 0xC00E, 0x97CE, 0xC00F, 0x97CF, 0xC010, 0x97D0, 0xC011, 0x97D1, 0xC012, 0x97D2, 0xC013, 0x97D3, + 0xC014, 0x97D4, 0xC015, 0x97D5, 0xC016, 0x97D6, 0xC017, 0x97D7, 0xC018, 0x97D8, 0xC019, 0x97D9, 0xC01A, 0x97DA, 0xC01B, 0x97DB, + 0xC01C, 0x97DC, 0xC01D, 0x97DD, 0xC01E, 0x97DE, 0xC01F, 0x97DF, 0xC020, 0x97E0, 0xC021, 0x97E1, 0xC022, 0x97E2, 0xC023, 0x97E3, + 0xC024, 0x97E4, 0xC025, 0x97E5, 0xC026, 0x97E6, 0xC027, 0x97E7, 0xC028, 0x97E8, 0xC029, 0x97E9, 0xC02A, 0x97EA, 0xC02B, 0x97EB, + 0xC02C, 0x97EC, 0xC02D, 0x97ED, 0xC02E, 0x97EE, 0xC02F, 0x97EF, 0xC030, 0x97F0, 0xC031, 0x97F1, 0xC032, 0x97F2, 0xC033, 0x97F3, + 0xC034, 0x97F4, 0xC035, 0x97F5, 0xC036, 0x97F6, 0xC037, 0x97F7, 0xC038, 0x97F8, 0xC039, 0x97F9, 0xC03A, 0x97FA, 0xC03B, 0x97FB, + 0xC03C, 0xBBD8, 0xC03D, 0x97FC, 0xC03E, 0x97FD, 0xC03F, 0x97FE, 0xC040, 0x9841, 0xC041, 0x9842, 0xC042, 0x9843, 0xC043, 0x9844, + 0xC044, 0x9845, 0xC045, 0x9846, 0xC046, 0x9847, 0xC047, 0x9848, 0xC048, 0x9849, 0xC049, 0x984A, 0xC04A, 0x984B, 0xC04B, 0x984C, + 0xC04C, 0x984D, 0xC04D, 0x984E, 0xC04E, 0x984F, 0xC04F, 0x9850, 0xC050, 0x9851, 0xC051, 0xBBD9, 0xC052, 0x9852, 0xC053, 0x9853, + 0xC054, 0x9854, 0xC055, 0x9855, 0xC056, 0x9856, 0xC057, 0x9857, 0xC058, 0xBBDA, 0xC059, 0x9858, 0xC05A, 0x9859, 0xC05B, 0x985A, + 0xC05C, 0xBBDB, 0xC05D, 0x9861, 0xC05E, 0x9862, 0xC05F, 0x9863, 0xC060, 0xBBDC, 0xC061, 0x9864, 0xC062, 0x9865, 0xC063, 0x9866, + 0xC064, 0x9867, 0xC065, 0x9868, 0xC066, 0x9869, 0xC067, 0x986A, 0xC068, 0xBBDD, 0xC069, 0xBBDE, 0xC06A, 0x986B, 0xC06B, 0x986C, + 0xC06C, 0x986D, 0xC06D, 0x986E, 0xC06E, 0x986F, 0xC06F, 0x9870, 0xC070, 0x9871, 0xC071, 0x9872, 0xC072, 0x9873, 0xC073, 0x9874, + 0xC074, 0x9875, 0xC075, 0x9876, 0xC076, 0x9877, 0xC077, 0x9878, 0xC078, 0x9879, 0xC079, 0x987A, 0xC07A, 0x9881, 0xC07B, 0x9882, + 0xC07C, 0x9883, 0xC07D, 0x9884, 0xC07E, 0x9885, 0xC07F, 0x9886, 0xC080, 0x9887, 0xC081, 0x9888, 0xC082, 0x9889, 0xC083, 0x988A, + 0xC084, 0x988B, 0xC085, 0x988C, 0xC086, 0x988D, 0xC087, 0x988E, 0xC088, 0x988F, 0xC089, 0x9890, 0xC08A, 0x9891, 0xC08B, 0x9892, + 0xC08C, 0x9893, 0xC08D, 0x9894, 0xC08E, 0x9895, 0xC08F, 0x9896, 0xC090, 0xBBDF, 0xC091, 0xBBE0, 0xC092, 0x9897, 0xC093, 0x9898, + 0xC094, 0xBBE1, 0xC095, 0x9899, 0xC096, 0x989A, 0xC097, 0x989B, 0xC098, 0xBBE2, 0xC099, 0x989C, 0xC09A, 0x989D, 0xC09B, 0x989E, + 0xC09C, 0x989F, 0xC09D, 0x98A0, 0xC09E, 0x98A1, 0xC09F, 0x98A2, 0xC0A0, 0xBBE3, 0xC0A1, 0xBBE4, 0xC0A2, 0x98A3, 0xC0A3, 0xBBE5, + 0xC0A4, 0x98A4, 0xC0A5, 0xBBE6, 0xC0A6, 0x98A5, 0xC0A7, 0x98A6, 0xC0A8, 0x98A7, 0xC0A9, 0x98A8, 0xC0AA, 0x98A9, 0xC0AB, 0x98AA, + 0xC0AC, 0xBBE7, 0xC0AD, 0xBBE8, 0xC0AE, 0x98AB, 0xC0AF, 0xBBE9, 0xC0B0, 0xBBEA, 0xC0B1, 0x98AC, 0xC0B2, 0x98AD, 0xC0B3, 0xBBEB, + 0xC0B4, 0xBBEC, 0xC0B5, 0xBBED, 0xC0B6, 0xBBEE, 0xC0B7, 0x98AE, 0xC0B8, 0x98AF, 0xC0B9, 0x98B0, 0xC0BA, 0x98B1, 0xC0BB, 0x98B2, + 0xC0BC, 0xBBEF, 0xC0BD, 0xBBF0, 0xC0BE, 0x98B3, 0xC0BF, 0xBBF1, 0xC0C0, 0xBBF2, 0xC0C1, 0xBBF3, 0xC0C2, 0x98B4, 0xC0C3, 0x98B5, + 0xC0C4, 0x98B6, 0xC0C5, 0xBBF4, 0xC0C6, 0x98B7, 0xC0C7, 0x98B8, 0xC0C8, 0xBBF5, 0xC0C9, 0xBBF6, 0xC0CA, 0x98B9, 0xC0CB, 0x98BA, + 0xC0CC, 0xBBF7, 0xC0CD, 0x98BB, 0xC0CE, 0x98BC, 0xC0CF, 0x98BD, 0xC0D0, 0xBBF8, 0xC0D1, 0x98BE, 0xC0D2, 0x98BF, 0xC0D3, 0x98C0, + 0xC0D4, 0x98C1, 0xC0D5, 0x98C2, 0xC0D6, 0x98C3, 0xC0D7, 0x98C4, 0xC0D8, 0xBBF9, 0xC0D9, 0xBBFA, 0xC0DA, 0x98C5, 0xC0DB, 0xBBFB, + 0xC0DC, 0xBBFC, 0xC0DD, 0xBBFD, 0xC0DE, 0x98C6, 0xC0DF, 0x98C7, 0xC0E0, 0x98C8, 0xC0E1, 0x98C9, 0xC0E2, 0x98CA, 0xC0E3, 0x98CB, + 0xC0E4, 0xBBFE, 0xC0E5, 0xBCA1, 0xC0E6, 0x98CC, 0xC0E7, 0x98CD, 0xC0E8, 0xBCA2, 0xC0E9, 0x98CE, 0xC0EA, 0x98CF, 0xC0EB, 0x98D0, + 0xC0EC, 0xBCA3, 0xC0ED, 0x98D1, 0xC0EE, 0x98D2, 0xC0EF, 0x98D3, 0xC0F0, 0x98D4, 0xC0F1, 0x98D5, 0xC0F2, 0x98D6, 0xC0F3, 0x98D7, + 0xC0F4, 0xBCA4, 0xC0F5, 0xBCA5, 0xC0F6, 0x98D8, 0xC0F7, 0xBCA6, 0xC0F8, 0x98D9, 0xC0F9, 0xBCA7, 0xC0FA, 0x98DA, 0xC0FB, 0x98DB, + 0xC0FC, 0x98DC, 0xC0FD, 0x98DD, 0xC0FE, 0x98DE, 0xC0FF, 0x98DF, 0xC100, 0xBCA8, 0xC101, 0x98E0, 0xC102, 0x98E1, 0xC103, 0x98E2, + 0xC104, 0xBCA9, 0xC105, 0x98E3, 0xC106, 0x98E4, 0xC107, 0x98E5, 0xC108, 0xBCAA, 0xC109, 0x98E6, 0xC10A, 0x98E7, 0xC10B, 0x98E8, + 0xC10C, 0x98E9, 0xC10D, 0x98EA, 0xC10E, 0x98EB, 0xC10F, 0x98EC, 0xC110, 0xBCAB, 0xC111, 0x98ED, 0xC112, 0x98EE, 0xC113, 0x98EF, + 0xC114, 0x98F0, 0xC115, 0xBCAC, 0xC116, 0x98F1, 0xC117, 0x98F2, 0xC118, 0x98F3, 0xC119, 0x98F4, 0xC11A, 0x98F5, 0xC11B, 0x98F6, + 0xC11C, 0xBCAD, 0xC11D, 0xBCAE, 0xC11E, 0xBCAF, 0xC11F, 0xBCB0, 0xC120, 0xBCB1, 0xC121, 0x98F7, 0xC122, 0x98F8, 0xC123, 0xBCB2, + 0xC124, 0xBCB3, 0xC125, 0x98F9, 0xC126, 0xBCB4, 0xC127, 0xBCB5, 0xC128, 0x98FA, 0xC129, 0x98FB, 0xC12A, 0x98FC, 0xC12B, 0x98FD, + 0xC12C, 0xBCB6, 0xC12D, 0xBCB7, 0xC12E, 0x98FE, 0xC12F, 0xBCB8, 0xC130, 0xBCB9, 0xC131, 0xBCBA, 0xC132, 0x9941, 0xC133, 0x9942, + 0xC134, 0x9943, 0xC135, 0x9944, 0xC136, 0xBCBB, 0xC137, 0x9945, 0xC138, 0xBCBC, 0xC139, 0xBCBD, 0xC13A, 0x9946, 0xC13B, 0x9947, + 0xC13C, 0xBCBE, 0xC13D, 0x9948, 0xC13E, 0x9949, 0xC13F, 0x994A, 0xC140, 0xBCBF, 0xC141, 0x994B, 0xC142, 0x994C, 0xC143, 0x994D, + 0xC144, 0x994E, 0xC145, 0x994F, 0xC146, 0x9950, 0xC147, 0x9951, 0xC148, 0xBCC0, 0xC149, 0xBCC1, 0xC14A, 0x9952, 0xC14B, 0xBCC2, + 0xC14C, 0xBCC3, 0xC14D, 0xBCC4, 0xC14E, 0x9953, 0xC14F, 0x9954, 0xC150, 0x9955, 0xC151, 0x9956, 0xC152, 0x9957, 0xC153, 0x9958, + 0xC154, 0xBCC5, 0xC155, 0xBCC6, 0xC156, 0x9959, 0xC157, 0x995A, 0xC158, 0xBCC7, 0xC159, 0x9961, 0xC15A, 0x9962, 0xC15B, 0x9963, + 0xC15C, 0xBCC8, 0xC15D, 0x9964, 0xC15E, 0x9965, 0xC15F, 0x9966, 0xC160, 0x9967, 0xC161, 0x9968, 0xC162, 0x9969, 0xC163, 0x996A, + 0xC164, 0xBCC9, 0xC165, 0xBCCA, 0xC166, 0x996B, 0xC167, 0xBCCB, 0xC168, 0xBCCC, 0xC169, 0xBCCD, 0xC16A, 0x996C, 0xC16B, 0x996D, + 0xC16C, 0x996E, 0xC16D, 0x996F, 0xC16E, 0x9970, 0xC16F, 0x9971, 0xC170, 0xBCCE, 0xC171, 0x9972, 0xC172, 0x9973, 0xC173, 0x9974, + 0xC174, 0xBCCF, 0xC175, 0x9975, 0xC176, 0x9976, 0xC177, 0x9977, 0xC178, 0xBCD0, 0xC179, 0x9978, 0xC17A, 0x9979, 0xC17B, 0x997A, + 0xC17C, 0x9981, 0xC17D, 0x9982, 0xC17E, 0x9983, 0xC17F, 0x9984, 0xC180, 0x9985, 0xC181, 0x9986, 0xC182, 0x9987, 0xC183, 0x9988, + 0xC184, 0x9989, 0xC185, 0xBCD1, 0xC186, 0x998A, 0xC187, 0x998B, 0xC188, 0x998C, 0xC189, 0x998D, 0xC18A, 0x998E, 0xC18B, 0x998F, + 0xC18C, 0xBCD2, 0xC18D, 0xBCD3, 0xC18E, 0xBCD4, 0xC18F, 0x9990, 0xC190, 0xBCD5, 0xC191, 0x9991, 0xC192, 0x9992, 0xC193, 0x9993, + 0xC194, 0xBCD6, 0xC195, 0x9994, 0xC196, 0xBCD7, 0xC197, 0x9995, 0xC198, 0x9996, 0xC199, 0x9997, 0xC19A, 0x9998, 0xC19B, 0x9999, + 0xC19C, 0xBCD8, 0xC19D, 0xBCD9, 0xC19E, 0x999A, 0xC19F, 0xBCDA, 0xC1A0, 0x999B, 0xC1A1, 0xBCDB, 0xC1A2, 0x999C, 0xC1A3, 0x999D, + 0xC1A4, 0x999E, 0xC1A5, 0xBCDC, 0xC1A6, 0x999F, 0xC1A7, 0x99A0, 0xC1A8, 0xBCDD, 0xC1A9, 0xBCDE, 0xC1AA, 0x99A1, 0xC1AB, 0x99A2, + 0xC1AC, 0xBCDF, 0xC1AD, 0x99A3, 0xC1AE, 0x99A4, 0xC1AF, 0x99A5, 0xC1B0, 0xBCE0, 0xC1B1, 0x99A6, 0xC1B2, 0x99A7, 0xC1B3, 0x99A8, + 0xC1B4, 0x99A9, 0xC1B5, 0x99AA, 0xC1B6, 0x99AB, 0xC1B7, 0x99AC, 0xC1B8, 0x99AD, 0xC1B9, 0x99AE, 0xC1BA, 0x99AF, 0xC1BB, 0x99B0, + 0xC1BC, 0x99B1, 0xC1BD, 0xBCE1, 0xC1BE, 0x99B2, 0xC1BF, 0x99B3, 0xC1C0, 0x99B4, 0xC1C1, 0x99B5, 0xC1C2, 0x99B6, 0xC1C3, 0x99B7, + 0xC1C4, 0xBCE2, 0xC1C5, 0x99B8, 0xC1C6, 0x99B9, 0xC1C7, 0x99BA, 0xC1C8, 0xBCE3, 0xC1C9, 0x99BB, 0xC1CA, 0x99BC, 0xC1CB, 0x99BD, + 0xC1CC, 0xBCE4, 0xC1CD, 0x99BE, 0xC1CE, 0x99BF, 0xC1CF, 0x99C0, 0xC1D0, 0x99C1, 0xC1D1, 0x99C2, 0xC1D2, 0x99C3, 0xC1D3, 0x99C4, + 0xC1D4, 0xBCE5, 0xC1D5, 0x99C5, 0xC1D6, 0x99C6, 0xC1D7, 0xBCE6, 0xC1D8, 0xBCE7, 0xC1D9, 0x99C7, 0xC1DA, 0x99C8, 0xC1DB, 0x99C9, + 0xC1DC, 0x99CA, 0xC1DD, 0x99CB, 0xC1DE, 0x99CC, 0xC1DF, 0x99CD, 0xC1E0, 0xBCE8, 0xC1E1, 0x99CE, 0xC1E2, 0x99CF, 0xC1E3, 0x99D0, + 0xC1E4, 0xBCE9, 0xC1E5, 0x99D1, 0xC1E6, 0x99D2, 0xC1E7, 0x99D3, 0xC1E8, 0xBCEA, 0xC1E9, 0x99D4, 0xC1EA, 0x99D5, 0xC1EB, 0x99D6, + 0xC1EC, 0x99D7, 0xC1ED, 0x99D8, 0xC1EE, 0x99D9, 0xC1EF, 0x99DA, 0xC1F0, 0xBCEB, 0xC1F1, 0xBCEC, 0xC1F2, 0x99DB, 0xC1F3, 0xBCED, + 0xC1F4, 0x99DC, 0xC1F5, 0x99DD, 0xC1F6, 0x99DE, 0xC1F7, 0x99DF, 0xC1F8, 0x99E0, 0xC1F9, 0x99E1, 0xC1FA, 0x99E2, 0xC1FB, 0x99E3, + 0xC1FC, 0xBCEE, 0xC1FD, 0xBCEF, 0xC1FE, 0x99E4, 0xC1FF, 0x99E5, 0xC200, 0xBCF0, 0xC201, 0x99E6, 0xC202, 0x99E7, 0xC203, 0x99E8, + 0xC204, 0xBCF1, 0xC205, 0x99E9, 0xC206, 0x99EA, 0xC207, 0x99EB, 0xC208, 0x99EC, 0xC209, 0x99ED, 0xC20A, 0x99EE, 0xC20B, 0x99EF, + 0xC20C, 0xBCF2, 0xC20D, 0xBCF3, 0xC20E, 0x99F0, 0xC20F, 0xBCF4, 0xC210, 0x99F1, 0xC211, 0xBCF5, 0xC212, 0x99F2, 0xC213, 0x99F3, + 0xC214, 0x99F4, 0xC215, 0x99F5, 0xC216, 0x99F6, 0xC217, 0x99F7, 0xC218, 0xBCF6, 0xC219, 0xBCF7, 0xC21A, 0x99F8, 0xC21B, 0x99F9, + 0xC21C, 0xBCF8, 0xC21D, 0x99FA, 0xC21E, 0x99FB, 0xC21F, 0xBCF9, 0xC220, 0xBCFA, 0xC221, 0x99FC, 0xC222, 0x99FD, 0xC223, 0x99FE, + 0xC224, 0x9A41, 0xC225, 0x9A42, 0xC226, 0x9A43, 0xC227, 0x9A44, 0xC228, 0xBCFB, 0xC229, 0xBCFC, 0xC22A, 0x9A45, 0xC22B, 0xBCFD, + 0xC22C, 0x9A46, 0xC22D, 0xBCFE, 0xC22E, 0x9A47, 0xC22F, 0xBDA1, 0xC230, 0x9A48, 0xC231, 0xBDA2, 0xC232, 0xBDA3, 0xC233, 0x9A49, + 0xC234, 0xBDA4, 0xC235, 0x9A4A, 0xC236, 0x9A4B, 0xC237, 0x9A4C, 0xC238, 0x9A4D, 0xC239, 0x9A4E, 0xC23A, 0x9A4F, 0xC23B, 0x9A50, + 0xC23C, 0x9A51, 0xC23D, 0x9A52, 0xC23E, 0x9A53, 0xC23F, 0x9A54, 0xC240, 0x9A55, 0xC241, 0x9A56, 0xC242, 0x9A57, 0xC243, 0x9A58, + 0xC244, 0x9A59, 0xC245, 0x9A5A, 0xC246, 0x9A61, 0xC247, 0x9A62, 0xC248, 0xBDA5, 0xC249, 0x9A63, 0xC24A, 0x9A64, 0xC24B, 0x9A65, + 0xC24C, 0x9A66, 0xC24D, 0x9A67, 0xC24E, 0x9A68, 0xC24F, 0x9A69, 0xC250, 0xBDA6, 0xC251, 0xBDA7, 0xC252, 0x9A6A, 0xC253, 0x9A6B, + 0xC254, 0xBDA8, 0xC255, 0x9A6C, 0xC256, 0x9A6D, 0xC257, 0x9A6E, 0xC258, 0xBDA9, 0xC259, 0x9A6F, 0xC25A, 0x9A70, 0xC25B, 0x9A71, + 0xC25C, 0x9A72, 0xC25D, 0x9A73, 0xC25E, 0x9A74, 0xC25F, 0x9A75, 0xC260, 0xBDAA, 0xC261, 0x9A76, 0xC262, 0x9A77, 0xC263, 0x9A78, + 0xC264, 0x9A79, 0xC265, 0xBDAB, 0xC266, 0x9A7A, 0xC267, 0x9A81, 0xC268, 0x9A82, 0xC269, 0x9A83, 0xC26A, 0x9A84, 0xC26B, 0x9A85, + 0xC26C, 0xBDAC, 0xC26D, 0xBDAD, 0xC26E, 0x9A86, 0xC26F, 0x9A87, 0xC270, 0xBDAE, 0xC271, 0x9A88, 0xC272, 0x9A89, 0xC273, 0x9A8A, + 0xC274, 0xBDAF, 0xC275, 0x9A8B, 0xC276, 0x9A8C, 0xC277, 0x9A8D, 0xC278, 0x9A8E, 0xC279, 0x9A8F, 0xC27A, 0x9A90, 0xC27B, 0x9A91, + 0xC27C, 0xBDB0, 0xC27D, 0xBDB1, 0xC27E, 0x9A92, 0xC27F, 0xBDB2, 0xC280, 0x9A93, 0xC281, 0xBDB3, 0xC282, 0x9A94, 0xC283, 0x9A95, + 0xC284, 0x9A96, 0xC285, 0x9A97, 0xC286, 0x9A98, 0xC287, 0x9A99, 0xC288, 0xBDB4, 0xC289, 0xBDB5, 0xC28A, 0x9A9A, 0xC28B, 0x9A9B, + 0xC28C, 0x9A9C, 0xC28D, 0x9A9D, 0xC28E, 0x9A9E, 0xC28F, 0x9A9F, 0xC290, 0xBDB6, 0xC291, 0x9AA0, 0xC292, 0x9AA1, 0xC293, 0x9AA2, + 0xC294, 0x9AA3, 0xC295, 0x9AA4, 0xC296, 0x9AA5, 0xC297, 0x9AA6, 0xC298, 0xBDB7, 0xC299, 0x9AA7, 0xC29A, 0x9AA8, 0xC29B, 0xBDB8, + 0xC29C, 0x9AA9, 0xC29D, 0xBDB9, 0xC29E, 0x9AAA, 0xC29F, 0x9AAB, 0xC2A0, 0x9AAC, 0xC2A1, 0x9AAD, 0xC2A2, 0x9AAE, 0xC2A3, 0x9AAF, + 0xC2A4, 0xBDBA, 0xC2A5, 0xBDBB, 0xC2A6, 0x9AB0, 0xC2A7, 0x9AB1, 0xC2A8, 0xBDBC, 0xC2A9, 0x9AB2, 0xC2AA, 0x9AB3, 0xC2AB, 0x9AB4, + 0xC2AC, 0xBDBD, 0xC2AD, 0xBDBE, 0xC2AE, 0x9AB5, 0xC2AF, 0x9AB6, 0xC2B0, 0x9AB7, 0xC2B1, 0x9AB8, 0xC2B2, 0x9AB9, 0xC2B3, 0x9ABA, + 0xC2B4, 0xBDBF, 0xC2B5, 0xBDC0, 0xC2B6, 0x9ABB, 0xC2B7, 0xBDC1, 0xC2B8, 0x9ABC, 0xC2B9, 0xBDC2, 0xC2BA, 0x9ABD, 0xC2BB, 0x9ABE, + 0xC2BC, 0x9ABF, 0xC2BD, 0x9AC0, 0xC2BE, 0x9AC1, 0xC2BF, 0x9AC2, 0xC2C0, 0x9AC3, 0xC2C1, 0x9AC4, 0xC2C2, 0x9AC5, 0xC2C3, 0x9AC6, + 0xC2C4, 0x9AC7, 0xC2C5, 0x9AC8, 0xC2C6, 0x9AC9, 0xC2C7, 0x9ACA, 0xC2C8, 0x9ACB, 0xC2C9, 0x9ACC, 0xC2CA, 0x9ACD, 0xC2CB, 0x9ACE, + 0xC2CC, 0x9ACF, 0xC2CD, 0x9AD0, 0xC2CE, 0x9AD1, 0xC2CF, 0x9AD2, 0xC2D0, 0x9AD3, 0xC2D1, 0x9AD4, 0xC2D2, 0x9AD5, 0xC2D3, 0x9AD6, + 0xC2D4, 0x9AD7, 0xC2D5, 0x9AD8, 0xC2D6, 0x9AD9, 0xC2D7, 0x9ADA, 0xC2D8, 0x9ADB, 0xC2D9, 0x9ADC, 0xC2DA, 0x9ADD, 0xC2DB, 0x9ADE, + 0xC2DC, 0xBDC3, 0xC2DD, 0xBDC4, 0xC2DE, 0x9ADF, 0xC2DF, 0x9AE0, 0xC2E0, 0xBDC5, 0xC2E1, 0x9AE1, 0xC2E2, 0x9AE2, 0xC2E3, 0xBDC6, + 0xC2E4, 0xBDC7, 0xC2E5, 0x9AE3, 0xC2E6, 0x9AE4, 0xC2E7, 0x9AE5, 0xC2E8, 0x9AE6, 0xC2E9, 0x9AE7, 0xC2EA, 0x9AE8, 0xC2EB, 0xBDC8, + 0xC2EC, 0xBDC9, 0xC2ED, 0xBDCA, 0xC2EE, 0x9AE9, 0xC2EF, 0xBDCB, 0xC2F0, 0x9AEA, 0xC2F1, 0xBDCC, 0xC2F2, 0x9AEB, 0xC2F3, 0x9AEC, + 0xC2F4, 0x9AED, 0xC2F5, 0x9AEE, 0xC2F6, 0xBDCD, 0xC2F7, 0x9AEF, 0xC2F8, 0xBDCE, 0xC2F9, 0xBDCF, 0xC2FA, 0x9AF0, 0xC2FB, 0xBDD0, + 0xC2FC, 0xBDD1, 0xC2FD, 0x9AF1, 0xC2FE, 0x9AF2, 0xC2FF, 0x9AF3, 0xC300, 0xBDD2, 0xC301, 0x9AF4, 0xC302, 0x9AF5, 0xC303, 0x9AF6, + 0xC304, 0x9AF7, 0xC305, 0x9AF8, 0xC306, 0x9AF9, 0xC307, 0x9AFA, 0xC308, 0xBDD3, 0xC309, 0xBDD4, 0xC30A, 0x9AFB, 0xC30B, 0x9AFC, + 0xC30C, 0xBDD5, 0xC30D, 0xBDD6, 0xC30E, 0x9AFD, 0xC30F, 0x9AFE, 0xC310, 0x9B41, 0xC311, 0x9B42, 0xC312, 0x9B43, 0xC313, 0xBDD7, + 0xC314, 0xBDD8, 0xC315, 0xBDD9, 0xC316, 0x9B44, 0xC317, 0x9B45, 0xC318, 0xBDDA, 0xC319, 0x9B46, 0xC31A, 0x9B47, 0xC31B, 0x9B48, + 0xC31C, 0xBDDB, 0xC31D, 0x9B49, 0xC31E, 0x9B4A, 0xC31F, 0x9B4B, 0xC320, 0x9B4C, 0xC321, 0x9B4D, 0xC322, 0x9B4E, 0xC323, 0x9B4F, + 0xC324, 0xBDDC, 0xC325, 0xBDDD, 0xC326, 0x9B50, 0xC327, 0x9B51, 0xC328, 0xBDDE, 0xC329, 0xBDDF, 0xC32A, 0x9B52, 0xC32B, 0x9B53, + 0xC32C, 0x9B54, 0xC32D, 0x9B55, 0xC32E, 0x9B56, 0xC32F, 0x9B57, 0xC330, 0x9B58, 0xC331, 0x9B59, 0xC332, 0x9B5A, 0xC333, 0x9B61, + 0xC334, 0x9B62, 0xC335, 0x9B63, 0xC336, 0x9B64, 0xC337, 0x9B65, 0xC338, 0x9B66, 0xC339, 0x9B67, 0xC33A, 0x9B68, 0xC33B, 0x9B69, + 0xC33C, 0x9B6A, 0xC33D, 0x9B6B, 0xC33E, 0x9B6C, 0xC33F, 0x9B6D, 0xC340, 0x9B6E, 0xC341, 0x9B6F, 0xC342, 0x9B70, 0xC343, 0x9B71, + 0xC344, 0x9B72, 0xC345, 0xBDE0, 0xC346, 0x9B73, 0xC347, 0x9B74, 0xC348, 0x9B75, 0xC349, 0x9B76, 0xC34A, 0x9B77, 0xC34B, 0x9B78, + 0xC34C, 0x9B79, 0xC34D, 0x9B7A, 0xC34E, 0x9B81, 0xC34F, 0x9B82, 0xC350, 0x9B83, 0xC351, 0x9B84, 0xC352, 0x9B85, 0xC353, 0x9B86, + 0xC354, 0x9B87, 0xC355, 0x9B88, 0xC356, 0x9B89, 0xC357, 0x9B8A, 0xC358, 0x9B8B, 0xC359, 0x9B8C, 0xC35A, 0x9B8D, 0xC35B, 0x9B8E, + 0xC35C, 0x9B8F, 0xC35D, 0x9B90, 0xC35E, 0x9B91, 0xC35F, 0x9B92, 0xC360, 0x9B93, 0xC361, 0x9B94, 0xC362, 0x9B95, 0xC363, 0x9B96, + 0xC364, 0x9B97, 0xC365, 0x9B98, 0xC366, 0x9B99, 0xC367, 0x9B9A, 0xC368, 0xBDE1, 0xC369, 0xBDE2, 0xC36A, 0x9B9B, 0xC36B, 0x9B9C, + 0xC36C, 0xBDE3, 0xC36D, 0x9B9D, 0xC36E, 0x9B9E, 0xC36F, 0x9B9F, 0xC370, 0xBDE4, 0xC371, 0x9BA0, 0xC372, 0xBDE5, 0xC373, 0x9BA1, + 0xC374, 0x9BA2, 0xC375, 0x9BA3, 0xC376, 0x9BA4, 0xC377, 0x9BA5, 0xC378, 0xBDE6, 0xC379, 0xBDE7, 0xC37A, 0x9BA6, 0xC37B, 0x9BA7, + 0xC37C, 0xBDE8, 0xC37D, 0xBDE9, 0xC37E, 0x9BA8, 0xC37F, 0x9BA9, 0xC380, 0x9BAA, 0xC381, 0x9BAB, 0xC382, 0x9BAC, 0xC383, 0x9BAD, + 0xC384, 0xBDEA, 0xC385, 0x9BAE, 0xC386, 0x9BAF, 0xC387, 0x9BB0, 0xC388, 0xBDEB, 0xC389, 0x9BB1, 0xC38A, 0x9BB2, 0xC38B, 0x9BB3, + 0xC38C, 0xBDEC, 0xC38D, 0x9BB4, 0xC38E, 0x9BB5, 0xC38F, 0x9BB6, 0xC390, 0x9BB7, 0xC391, 0x9BB8, 0xC392, 0x9BB9, 0xC393, 0x9BBA, + 0xC394, 0x9BBB, 0xC395, 0x9BBC, 0xC396, 0x9BBD, 0xC397, 0x9BBE, 0xC398, 0x9BBF, 0xC399, 0x9BC0, 0xC39A, 0x9BC1, 0xC39B, 0x9BC2, + 0xC39C, 0x9BC3, 0xC39D, 0x9BC4, 0xC39E, 0x9BC5, 0xC39F, 0x9BC6, 0xC3A0, 0x9BC7, 0xC3A1, 0x9BC8, 0xC3A2, 0x9BC9, 0xC3A3, 0x9BCA, + 0xC3A4, 0x9BCB, 0xC3A5, 0x9BCC, 0xC3A6, 0x9BCD, 0xC3A7, 0x9BCE, 0xC3A8, 0x9BCF, 0xC3A9, 0x9BD0, 0xC3AA, 0x9BD1, 0xC3AB, 0x9BD2, + 0xC3AC, 0x9BD3, 0xC3AD, 0x9BD4, 0xC3AE, 0x9BD5, 0xC3AF, 0x9BD6, 0xC3B0, 0x9BD7, 0xC3B1, 0x9BD8, 0xC3B2, 0x9BD9, 0xC3B3, 0x9BDA, + 0xC3B4, 0x9BDB, 0xC3B5, 0x9BDC, 0xC3B6, 0x9BDD, 0xC3B7, 0x9BDE, 0xC3B8, 0x9BDF, 0xC3B9, 0x9BE0, 0xC3BA, 0x9BE1, 0xC3BB, 0x9BE2, + 0xC3BC, 0x9BE3, 0xC3BD, 0x9BE4, 0xC3BE, 0x9BE5, 0xC3BF, 0x9BE6, 0xC3C0, 0xBDED, 0xC3C1, 0x9BE7, 0xC3C2, 0x9BE8, 0xC3C3, 0x9BE9, + 0xC3C4, 0x9BEA, 0xC3C5, 0x9BEB, 0xC3C6, 0x9BEC, 0xC3C7, 0x9BED, 0xC3C8, 0x9BEE, 0xC3C9, 0x9BEF, 0xC3CA, 0x9BF0, 0xC3CB, 0x9BF1, + 0xC3CC, 0x9BF2, 0xC3CD, 0x9BF3, 0xC3CE, 0x9BF4, 0xC3CF, 0x9BF5, 0xC3D0, 0x9BF6, 0xC3D1, 0x9BF7, 0xC3D2, 0x9BF8, 0xC3D3, 0x9BF9, + 0xC3D4, 0x9BFA, 0xC3D5, 0x9BFB, 0xC3D6, 0x9BFC, 0xC3D7, 0x9BFD, 0xC3D8, 0xBDEE, 0xC3D9, 0xBDEF, 0xC3DA, 0x9BFE, 0xC3DB, 0x9C41, + 0xC3DC, 0xBDF0, 0xC3DD, 0x9C42, 0xC3DE, 0x9C43, 0xC3DF, 0xBDF1, 0xC3E0, 0xBDF2, 0xC3E1, 0x9C44, 0xC3E2, 0xBDF3, 0xC3E3, 0x9C45, + 0xC3E4, 0x9C46, 0xC3E5, 0x9C47, 0xC3E6, 0x9C48, 0xC3E7, 0x9C49, 0xC3E8, 0xBDF4, 0xC3E9, 0xBDF5, 0xC3EA, 0x9C4A, 0xC3EB, 0x9C4B, + 0xC3EC, 0x9C4C, 0xC3ED, 0xBDF6, 0xC3EE, 0x9C4D, 0xC3EF, 0x9C4E, 0xC3F0, 0x9C4F, 0xC3F1, 0x9C50, 0xC3F2, 0x9C51, 0xC3F3, 0x9C52, + 0xC3F4, 0xBDF7, 0xC3F5, 0xBDF8, 0xC3F6, 0x9C53, 0xC3F7, 0x9C54, 0xC3F8, 0xBDF9, 0xC3F9, 0x9C55, 0xC3FA, 0x9C56, 0xC3FB, 0x9C57, + 0xC3FC, 0x9C58, 0xC3FD, 0x9C59, 0xC3FE, 0x9C5A, 0xC3FF, 0x9C61, 0xC400, 0x9C62, 0xC401, 0x9C63, 0xC402, 0x9C64, 0xC403, 0x9C65, + 0xC404, 0x9C66, 0xC405, 0x9C67, 0xC406, 0x9C68, 0xC407, 0x9C69, 0xC408, 0xBDFA, 0xC409, 0x9C6A, 0xC40A, 0x9C6B, 0xC40B, 0x9C6C, + 0xC40C, 0x9C6D, 0xC40D, 0x9C6E, 0xC40E, 0x9C6F, 0xC40F, 0x9C70, 0xC410, 0xBDFB, 0xC411, 0x9C71, 0xC412, 0x9C72, 0xC413, 0x9C73, + 0xC414, 0x9C74, 0xC415, 0x9C75, 0xC416, 0x9C76, 0xC417, 0x9C77, 0xC418, 0x9C78, 0xC419, 0x9C79, 0xC41A, 0x9C7A, 0xC41B, 0x9C81, + 0xC41C, 0x9C82, 0xC41D, 0x9C83, 0xC41E, 0x9C84, 0xC41F, 0x9C85, 0xC420, 0x9C86, 0xC421, 0x9C87, 0xC422, 0x9C88, 0xC423, 0x9C89, + 0xC424, 0xBDFC, 0xC425, 0x9C8A, 0xC426, 0x9C8B, 0xC427, 0x9C8C, 0xC428, 0x9C8D, 0xC429, 0x9C8E, 0xC42A, 0x9C8F, 0xC42B, 0x9C90, + 0xC42C, 0xBDFD, 0xC42D, 0x9C91, 0xC42E, 0x9C92, 0xC42F, 0x9C93, 0xC430, 0xBDFE, 0xC431, 0x9C94, 0xC432, 0x9C95, 0xC433, 0x9C96, + 0xC434, 0xBEA1, 0xC435, 0x9C97, 0xC436, 0x9C98, 0xC437, 0x9C99, 0xC438, 0x9C9A, 0xC439, 0x9C9B, 0xC43A, 0x9C9C, 0xC43B, 0x9C9D, + 0xC43C, 0xBEA2, 0xC43D, 0xBEA3, 0xC43E, 0x9C9E, 0xC43F, 0x9C9F, 0xC440, 0x9CA0, 0xC441, 0x9CA1, 0xC442, 0x9CA2, 0xC443, 0x9CA3, + 0xC444, 0x9CA4, 0xC445, 0x9CA5, 0xC446, 0x9CA6, 0xC447, 0x9CA7, 0xC448, 0xBEA4, 0xC449, 0x9CA8, 0xC44A, 0x9CA9, 0xC44B, 0x9CAA, + 0xC44C, 0x9CAB, 0xC44D, 0x9CAC, 0xC44E, 0x9CAD, 0xC44F, 0x9CAE, 0xC450, 0x9CAF, 0xC451, 0x9CB0, 0xC452, 0x9CB1, 0xC453, 0x9CB2, + 0xC454, 0x9CB3, 0xC455, 0x9CB4, 0xC456, 0x9CB5, 0xC457, 0x9CB6, 0xC458, 0x9CB7, 0xC459, 0x9CB8, 0xC45A, 0x9CB9, 0xC45B, 0x9CBA, + 0xC45C, 0x9CBB, 0xC45D, 0x9CBC, 0xC45E, 0x9CBD, 0xC45F, 0x9CBE, 0xC460, 0x9CBF, 0xC461, 0x9CC0, 0xC462, 0x9CC1, 0xC463, 0x9CC2, + 0xC464, 0xBEA5, 0xC465, 0xBEA6, 0xC466, 0x9CC3, 0xC467, 0x9CC4, 0xC468, 0xBEA7, 0xC469, 0x9CC5, 0xC46A, 0x9CC6, 0xC46B, 0x9CC7, + 0xC46C, 0xBEA8, 0xC46D, 0x9CC8, 0xC46E, 0x9CC9, 0xC46F, 0x9CCA, 0xC470, 0x9CCB, 0xC471, 0x9CCC, 0xC472, 0x9CCD, 0xC473, 0x9CCE, + 0xC474, 0xBEA9, 0xC475, 0xBEAA, 0xC476, 0x9CCF, 0xC477, 0x9CD0, 0xC478, 0x9CD1, 0xC479, 0xBEAB, 0xC47A, 0x9CD2, 0xC47B, 0x9CD3, + 0xC47C, 0x9CD4, 0xC47D, 0x9CD5, 0xC47E, 0x9CD6, 0xC47F, 0x9CD7, 0xC480, 0xBEAC, 0xC481, 0x9CD8, 0xC482, 0x9CD9, 0xC483, 0x9CDA, + 0xC484, 0x9CDB, 0xC485, 0x9CDC, 0xC486, 0x9CDD, 0xC487, 0x9CDE, 0xC488, 0x9CDF, 0xC489, 0x9CE0, 0xC48A, 0x9CE1, 0xC48B, 0x9CE2, + 0xC48C, 0x9CE3, 0xC48D, 0x9CE4, 0xC48E, 0x9CE5, 0xC48F, 0x9CE6, 0xC490, 0x9CE7, 0xC491, 0x9CE8, 0xC492, 0x9CE9, 0xC493, 0x9CEA, + 0xC494, 0xBEAD, 0xC495, 0x9CEB, 0xC496, 0x9CEC, 0xC497, 0x9CED, 0xC498, 0x9CEE, 0xC499, 0x9CEF, 0xC49A, 0x9CF0, 0xC49B, 0x9CF1, + 0xC49C, 0xBEAE, 0xC49D, 0x9CF2, 0xC49E, 0x9CF3, 0xC49F, 0x9CF4, 0xC4A0, 0x9CF5, 0xC4A1, 0x9CF6, 0xC4A2, 0x9CF7, 0xC4A3, 0x9CF8, + 0xC4A4, 0x9CF9, 0xC4A5, 0x9CFA, 0xC4A6, 0x9CFB, 0xC4A7, 0x9CFC, 0xC4A8, 0x9CFD, 0xC4A9, 0x9CFE, 0xC4AA, 0x9D41, 0xC4AB, 0x9D42, + 0xC4AC, 0x9D43, 0xC4AD, 0x9D44, 0xC4AE, 0x9D45, 0xC4AF, 0x9D46, 0xC4B0, 0x9D47, 0xC4B1, 0x9D48, 0xC4B2, 0x9D49, 0xC4B3, 0x9D4A, + 0xC4B4, 0x9D4B, 0xC4B5, 0x9D4C, 0xC4B6, 0x9D4D, 0xC4B7, 0x9D4E, 0xC4B8, 0xBEAF, 0xC4B9, 0x9D4F, 0xC4BA, 0x9D50, 0xC4BB, 0x9D51, + 0xC4BC, 0xBEB0, 0xC4BD, 0x9D52, 0xC4BE, 0x9D53, 0xC4BF, 0x9D54, 0xC4C0, 0x9D55, 0xC4C1, 0x9D56, 0xC4C2, 0x9D57, 0xC4C3, 0x9D58, + 0xC4C4, 0x9D59, 0xC4C5, 0x9D5A, 0xC4C6, 0x9D61, 0xC4C7, 0x9D62, 0xC4C8, 0x9D63, 0xC4C9, 0x9D64, 0xC4CA, 0x9D65, 0xC4CB, 0x9D66, + 0xC4CC, 0x9D67, 0xC4CD, 0x9D68, 0xC4CE, 0x9D69, 0xC4CF, 0x9D6A, 0xC4D0, 0x9D6B, 0xC4D1, 0x9D6C, 0xC4D2, 0x9D6D, 0xC4D3, 0x9D6E, + 0xC4D4, 0x9D6F, 0xC4D5, 0x9D70, 0xC4D6, 0x9D71, 0xC4D7, 0x9D72, 0xC4D8, 0x9D73, 0xC4D9, 0x9D74, 0xC4DA, 0x9D75, 0xC4DB, 0x9D76, + 0xC4DC, 0x9D77, 0xC4DD, 0x9D78, 0xC4DE, 0x9D79, 0xC4DF, 0x9D7A, 0xC4E0, 0x9D81, 0xC4E1, 0x9D82, 0xC4E2, 0x9D83, 0xC4E3, 0x9D84, + 0xC4E4, 0x9D85, 0xC4E5, 0x9D86, 0xC4E6, 0x9D87, 0xC4E7, 0x9D88, 0xC4E8, 0x9D89, 0xC4E9, 0xBEB1, 0xC4EA, 0x9D8A, 0xC4EB, 0x9D8B, + 0xC4EC, 0x9D8C, 0xC4ED, 0x9D8D, 0xC4EE, 0x9D8E, 0xC4EF, 0x9D8F, 0xC4F0, 0xBEB2, 0xC4F1, 0xBEB3, 0xC4F2, 0x9D90, 0xC4F3, 0x9D91, + 0xC4F4, 0xBEB4, 0xC4F5, 0x9D92, 0xC4F6, 0x9D93, 0xC4F7, 0x9D94, 0xC4F8, 0xBEB5, 0xC4F9, 0x9D95, 0xC4FA, 0xBEB6, 0xC4FB, 0x9D96, + 0xC4FC, 0x9D97, 0xC4FD, 0x9D98, 0xC4FE, 0x9D99, 0xC4FF, 0xBEB7, 0xC500, 0xBEB8, 0xC501, 0xBEB9, 0xC502, 0x9D9A, 0xC503, 0x9D9B, + 0xC504, 0x9D9C, 0xC505, 0x9D9D, 0xC506, 0x9D9E, 0xC507, 0x9D9F, 0xC508, 0x9DA0, 0xC509, 0x9DA1, 0xC50A, 0x9DA2, 0xC50B, 0x9DA3, + 0xC50C, 0xBEBA, 0xC50D, 0x9DA4, 0xC50E, 0x9DA5, 0xC50F, 0x9DA6, 0xC510, 0xBEBB, 0xC511, 0x9DA7, 0xC512, 0x9DA8, 0xC513, 0x9DA9, + 0xC514, 0xBEBC, 0xC515, 0x9DAA, 0xC516, 0x9DAB, 0xC517, 0x9DAC, 0xC518, 0x9DAD, 0xC519, 0x9DAE, 0xC51A, 0x9DAF, 0xC51B, 0x9DB0, + 0xC51C, 0xBEBD, 0xC51D, 0x9DB1, 0xC51E, 0x9DB2, 0xC51F, 0x9DB3, 0xC520, 0x9DB4, 0xC521, 0x9DB5, 0xC522, 0x9DB6, 0xC523, 0x9DB7, + 0xC524, 0x9DB8, 0xC525, 0x9DB9, 0xC526, 0x9DBA, 0xC527, 0x9DBB, 0xC528, 0xBEBE, 0xC529, 0xBEBF, 0xC52A, 0x9DBC, 0xC52B, 0x9DBD, + 0xC52C, 0xBEC0, 0xC52D, 0x9DBE, 0xC52E, 0x9DBF, 0xC52F, 0x9DC0, 0xC530, 0xBEC1, 0xC531, 0x9DC1, 0xC532, 0x9DC2, 0xC533, 0x9DC3, + 0xC534, 0x9DC4, 0xC535, 0x9DC5, 0xC536, 0x9DC6, 0xC537, 0x9DC7, 0xC538, 0xBEC2, 0xC539, 0xBEC3, 0xC53A, 0x9DC8, 0xC53B, 0xBEC4, + 0xC53C, 0x9DC9, 0xC53D, 0xBEC5, 0xC53E, 0x9DCA, 0xC53F, 0x9DCB, 0xC540, 0x9DCC, 0xC541, 0x9DCD, 0xC542, 0x9DCE, 0xC543, 0x9DCF, + 0xC544, 0xBEC6, 0xC545, 0xBEC7, 0xC546, 0x9DD0, 0xC547, 0x9DD1, 0xC548, 0xBEC8, 0xC549, 0xBEC9, 0xC54A, 0xBECA, 0xC54B, 0x9DD2, + 0xC54C, 0xBECB, 0xC54D, 0xBECC, 0xC54E, 0xBECD, 0xC54F, 0x9DD3, 0xC550, 0x9DD4, 0xC551, 0x9DD5, 0xC552, 0x9DD6, 0xC553, 0xBECE, + 0xC554, 0xBECF, 0xC555, 0xBED0, 0xC556, 0x9DD7, 0xC557, 0xBED1, 0xC558, 0xBED2, 0xC559, 0xBED3, 0xC55A, 0x9DD8, 0xC55B, 0x9DD9, + 0xC55C, 0x9DDA, 0xC55D, 0xBED4, 0xC55E, 0xBED5, 0xC55F, 0x9DDB, 0xC560, 0xBED6, 0xC561, 0xBED7, 0xC562, 0x9DDC, 0xC563, 0x9DDD, + 0xC564, 0xBED8, 0xC565, 0x9DDE, 0xC566, 0x9DDF, 0xC567, 0x9DE0, 0xC568, 0xBED9, 0xC569, 0x9DE1, 0xC56A, 0x9DE2, 0xC56B, 0x9DE3, + 0xC56C, 0x9DE4, 0xC56D, 0x9DE5, 0xC56E, 0x9DE6, 0xC56F, 0x9DE7, 0xC570, 0xBEDA, 0xC571, 0xBEDB, 0xC572, 0x9DE8, 0xC573, 0xBEDC, + 0xC574, 0xBEDD, 0xC575, 0xBEDE, 0xC576, 0x9DE9, 0xC577, 0x9DEA, 0xC578, 0x9DEB, 0xC579, 0x9DEC, 0xC57A, 0x9DED, 0xC57B, 0x9DEE, + 0xC57C, 0xBEDF, 0xC57D, 0xBEE0, 0xC57E, 0x9DEF, 0xC57F, 0x9DF0, 0xC580, 0xBEE1, 0xC581, 0x9DF1, 0xC582, 0x9DF2, 0xC583, 0x9DF3, + 0xC584, 0xBEE2, 0xC585, 0x9DF4, 0xC586, 0x9DF5, 0xC587, 0xBEE3, 0xC588, 0x9DF6, 0xC589, 0x9DF7, 0xC58A, 0x9DF8, 0xC58B, 0x9DF9, + 0xC58C, 0xBEE4, 0xC58D, 0xBEE5, 0xC58E, 0x9DFA, 0xC58F, 0xBEE6, 0xC590, 0x9DFB, 0xC591, 0xBEE7, 0xC592, 0x9DFC, 0xC593, 0x9DFD, + 0xC594, 0x9DFE, 0xC595, 0xBEE8, 0xC596, 0x9E41, 0xC597, 0xBEE9, 0xC598, 0xBEEA, 0xC599, 0x9E42, 0xC59A, 0x9E43, 0xC59B, 0x9E44, + 0xC59C, 0xBEEB, 0xC59D, 0x9E45, 0xC59E, 0x9E46, 0xC59F, 0x9E47, 0xC5A0, 0xBEEC, 0xC5A1, 0x9E48, 0xC5A2, 0x9E49, 0xC5A3, 0x9E4A, + 0xC5A4, 0x9E4B, 0xC5A5, 0x9E4C, 0xC5A6, 0x9E4D, 0xC5A7, 0x9E4E, 0xC5A8, 0x9E4F, 0xC5A9, 0xBEED, 0xC5AA, 0x9E50, 0xC5AB, 0x9E51, + 0xC5AC, 0x9E52, 0xC5AD, 0x9E53, 0xC5AE, 0x9E54, 0xC5AF, 0x9E55, 0xC5B0, 0x9E56, 0xC5B1, 0x9E57, 0xC5B2, 0x9E58, 0xC5B3, 0x9E59, + 0xC5B4, 0xBEEE, 0xC5B5, 0xBEEF, 0xC5B6, 0x9E5A, 0xC5B7, 0x9E61, 0xC5B8, 0xBEF0, 0xC5B9, 0xBEF1, 0xC5BA, 0x9E62, 0xC5BB, 0xBEF2, + 0xC5BC, 0xBEF3, 0xC5BD, 0xBEF4, 0xC5BE, 0xBEF5, 0xC5BF, 0x9E63, 0xC5C0, 0x9E64, 0xC5C1, 0x9E65, 0xC5C2, 0x9E66, 0xC5C3, 0x9E67, + 0xC5C4, 0xBEF6, 0xC5C5, 0xBEF7, 0xC5C6, 0xBEF8, 0xC5C7, 0xBEF9, 0xC5C8, 0xBEFA, 0xC5C9, 0xBEFB, 0xC5CA, 0xBEFC, 0xC5CB, 0x9E68, + 0xC5CC, 0xBEFD, 0xC5CD, 0x9E69, 0xC5CE, 0xBEFE, 0xC5CF, 0x9E6A, 0xC5D0, 0xBFA1, 0xC5D1, 0xBFA2, 0xC5D2, 0x9E6B, 0xC5D3, 0x9E6C, + 0xC5D4, 0xBFA3, 0xC5D5, 0x9E6D, 0xC5D6, 0x9E6E, 0xC5D7, 0x9E6F, 0xC5D8, 0xBFA4, 0xC5D9, 0x9E70, 0xC5DA, 0x9E71, 0xC5DB, 0x9E72, + 0xC5DC, 0x9E73, 0xC5DD, 0x9E74, 0xC5DE, 0x9E75, 0xC5DF, 0x9E76, 0xC5E0, 0xBFA5, 0xC5E1, 0xBFA6, 0xC5E2, 0x9E77, 0xC5E3, 0xBFA7, + 0xC5E4, 0x9E78, 0xC5E5, 0xBFA8, 0xC5E6, 0x9E79, 0xC5E7, 0x9E7A, 0xC5E8, 0x9E81, 0xC5E9, 0x9E82, 0xC5EA, 0x9E83, 0xC5EB, 0x9E84, + 0xC5EC, 0xBFA9, 0xC5ED, 0xBFAA, 0xC5EE, 0xBFAB, 0xC5EF, 0x9E85, 0xC5F0, 0xBFAC, 0xC5F1, 0x9E86, 0xC5F2, 0x9E87, 0xC5F3, 0x9E88, + 0xC5F4, 0xBFAD, 0xC5F5, 0x9E89, 0xC5F6, 0xBFAE, 0xC5F7, 0xBFAF, 0xC5F8, 0x9E8A, 0xC5F9, 0x9E8B, 0xC5FA, 0x9E8C, 0xC5FB, 0x9E8D, + 0xC5FC, 0xBFB0, 0xC5FD, 0xBFB1, 0xC5FE, 0xBFB2, 0xC5FF, 0xBFB3, 0xC600, 0xBFB4, 0xC601, 0xBFB5, 0xC602, 0x9E8E, 0xC603, 0x9E8F, + 0xC604, 0x9E90, 0xC605, 0xBFB6, 0xC606, 0xBFB7, 0xC607, 0xBFB8, 0xC608, 0xBFB9, 0xC609, 0x9E91, 0xC60A, 0x9E92, 0xC60B, 0x9E93, + 0xC60C, 0xBFBA, 0xC60D, 0x9E94, 0xC60E, 0x9E95, 0xC60F, 0x9E96, 0xC610, 0xBFBB, 0xC611, 0x9E97, 0xC612, 0x9E98, 0xC613, 0x9E99, + 0xC614, 0x9E9A, 0xC615, 0x9E9B, 0xC616, 0x9E9C, 0xC617, 0x9E9D, 0xC618, 0xBFBC, 0xC619, 0xBFBD, 0xC61A, 0x9E9E, 0xC61B, 0xBFBE, + 0xC61C, 0xBFBF, 0xC61D, 0x9E9F, 0xC61E, 0x9EA0, 0xC61F, 0x9EA1, 0xC620, 0x9EA2, 0xC621, 0x9EA3, 0xC622, 0x9EA4, 0xC623, 0x9EA5, + 0xC624, 0xBFC0, 0xC625, 0xBFC1, 0xC626, 0x9EA6, 0xC627, 0x9EA7, 0xC628, 0xBFC2, 0xC629, 0x9EA8, 0xC62A, 0x9EA9, 0xC62B, 0x9EAA, + 0xC62C, 0xBFC3, 0xC62D, 0xBFC4, 0xC62E, 0xBFC5, 0xC62F, 0x9EAB, 0xC630, 0xBFC6, 0xC631, 0x9EAC, 0xC632, 0x9EAD, 0xC633, 0xBFC7, + 0xC634, 0xBFC8, 0xC635, 0xBFC9, 0xC636, 0x9EAE, 0xC637, 0xBFCA, 0xC638, 0x9EAF, 0xC639, 0xBFCB, 0xC63A, 0x9EB0, 0xC63B, 0xBFCC, + 0xC63C, 0x9EB1, 0xC63D, 0x9EB2, 0xC63E, 0x9EB3, 0xC63F, 0x9EB4, 0xC640, 0xBFCD, 0xC641, 0xBFCE, 0xC642, 0x9EB5, 0xC643, 0x9EB6, + 0xC644, 0xBFCF, 0xC645, 0x9EB7, 0xC646, 0x9EB8, 0xC647, 0x9EB9, 0xC648, 0xBFD0, 0xC649, 0x9EBA, 0xC64A, 0x9EBB, 0xC64B, 0x9EBC, + 0xC64C, 0x9EBD, 0xC64D, 0x9EBE, 0xC64E, 0x9EBF, 0xC64F, 0x9EC0, 0xC650, 0xBFD1, 0xC651, 0xBFD2, 0xC652, 0x9EC1, 0xC653, 0xBFD3, + 0xC654, 0xBFD4, 0xC655, 0xBFD5, 0xC656, 0x9EC2, 0xC657, 0x9EC3, 0xC658, 0x9EC4, 0xC659, 0x9EC5, 0xC65A, 0x9EC6, 0xC65B, 0x9EC7, + 0xC65C, 0xBFD6, 0xC65D, 0xBFD7, 0xC65E, 0x9EC8, 0xC65F, 0x9EC9, 0xC660, 0xBFD8, 0xC661, 0x9ECA, 0xC662, 0x9ECB, 0xC663, 0x9ECC, + 0xC664, 0x9ECD, 0xC665, 0x9ECE, 0xC666, 0x9ECF, 0xC667, 0x9ED0, 0xC668, 0x9ED1, 0xC669, 0x9ED2, 0xC66A, 0x9ED3, 0xC66B, 0x9ED4, + 0xC66C, 0xBFD9, 0xC66D, 0x9ED5, 0xC66E, 0x9ED6, 0xC66F, 0xBFDA, 0xC670, 0x9ED7, 0xC671, 0xBFDB, 0xC672, 0x9ED8, 0xC673, 0x9ED9, + 0xC674, 0x9EDA, 0xC675, 0x9EDB, 0xC676, 0x9EDC, 0xC677, 0x9EDD, 0xC678, 0xBFDC, 0xC679, 0xBFDD, 0xC67A, 0x9EDE, 0xC67B, 0x9EDF, + 0xC67C, 0xBFDE, 0xC67D, 0x9EE0, 0xC67E, 0x9EE1, 0xC67F, 0x9EE2, 0xC680, 0xBFDF, 0xC681, 0x9EE3, 0xC682, 0x9EE4, 0xC683, 0x9EE5, + 0xC684, 0x9EE6, 0xC685, 0x9EE7, 0xC686, 0x9EE8, 0xC687, 0x9EE9, 0xC688, 0xBFE0, 0xC689, 0xBFE1, 0xC68A, 0x9EEA, 0xC68B, 0xBFE2, + 0xC68C, 0x9EEB, 0xC68D, 0xBFE3, 0xC68E, 0x9EEC, 0xC68F, 0x9EED, 0xC690, 0x9EEE, 0xC691, 0x9EEF, 0xC692, 0x9EF0, 0xC693, 0x9EF1, + 0xC694, 0xBFE4, 0xC695, 0xBFE5, 0xC696, 0x9EF2, 0xC697, 0x9EF3, 0xC698, 0xBFE6, 0xC699, 0x9EF4, 0xC69A, 0x9EF5, 0xC69B, 0x9EF6, + 0xC69C, 0xBFE7, 0xC69D, 0x9EF7, 0xC69E, 0x9EF8, 0xC69F, 0x9EF9, 0xC6A0, 0x9EFA, 0xC6A1, 0x9EFB, 0xC6A2, 0x9EFC, 0xC6A3, 0x9EFD, + 0xC6A4, 0xBFE8, 0xC6A5, 0xBFE9, 0xC6A6, 0x9EFE, 0xC6A7, 0xBFEA, 0xC6A8, 0x9F41, 0xC6A9, 0xBFEB, 0xC6AA, 0x9F42, 0xC6AB, 0x9F43, + 0xC6AC, 0x9F44, 0xC6AD, 0x9F45, 0xC6AE, 0x9F46, 0xC6AF, 0x9F47, 0xC6B0, 0xBFEC, 0xC6B1, 0xBFED, 0xC6B2, 0x9F48, 0xC6B3, 0x9F49, + 0xC6B4, 0xBFEE, 0xC6B5, 0x9F4A, 0xC6B6, 0x9F4B, 0xC6B7, 0x9F4C, 0xC6B8, 0xBFEF, 0xC6B9, 0xBFF0, 0xC6BA, 0xBFF1, 0xC6BB, 0x9F4D, + 0xC6BC, 0x9F4E, 0xC6BD, 0x9F4F, 0xC6BE, 0x9F50, 0xC6BF, 0x9F51, 0xC6C0, 0xBFF2, 0xC6C1, 0xBFF3, 0xC6C2, 0x9F52, 0xC6C3, 0xBFF4, + 0xC6C4, 0x9F53, 0xC6C5, 0xBFF5, 0xC6C6, 0x9F54, 0xC6C7, 0x9F55, 0xC6C8, 0x9F56, 0xC6C9, 0x9F57, 0xC6CA, 0x9F58, 0xC6CB, 0x9F59, + 0xC6CC, 0xBFF6, 0xC6CD, 0xBFF7, 0xC6CE, 0x9F5A, 0xC6CF, 0x9F61, 0xC6D0, 0xBFF8, 0xC6D1, 0x9F62, 0xC6D2, 0x9F63, 0xC6D3, 0x9F64, + 0xC6D4, 0xBFF9, 0xC6D5, 0x9F65, 0xC6D6, 0x9F66, 0xC6D7, 0x9F67, 0xC6D8, 0x9F68, 0xC6D9, 0x9F69, 0xC6DA, 0x9F6A, 0xC6DB, 0x9F6B, + 0xC6DC, 0xBFFA, 0xC6DD, 0xBFFB, 0xC6DE, 0x9F6C, 0xC6DF, 0x9F6D, 0xC6E0, 0xBFFC, 0xC6E1, 0xBFFD, 0xC6E2, 0x9F6E, 0xC6E3, 0x9F6F, + 0xC6E4, 0x9F70, 0xC6E5, 0x9F71, 0xC6E6, 0x9F72, 0xC6E7, 0x9F73, 0xC6E8, 0xBFFE, 0xC6E9, 0xC0A1, 0xC6EA, 0x9F74, 0xC6EB, 0x9F75, + 0xC6EC, 0xC0A2, 0xC6ED, 0x9F76, 0xC6EE, 0x9F77, 0xC6EF, 0x9F78, 0xC6F0, 0xC0A3, 0xC6F1, 0x9F79, 0xC6F2, 0x9F7A, 0xC6F3, 0x9F81, + 0xC6F4, 0x9F82, 0xC6F5, 0x9F83, 0xC6F6, 0x9F84, 0xC6F7, 0x9F85, 0xC6F8, 0xC0A4, 0xC6F9, 0xC0A5, 0xC6FA, 0x9F86, 0xC6FB, 0x9F87, + 0xC6FC, 0x9F88, 0xC6FD, 0xC0A6, 0xC6FE, 0x9F89, 0xC6FF, 0x9F8A, 0xC700, 0x9F8B, 0xC701, 0x9F8C, 0xC702, 0x9F8D, 0xC703, 0x9F8E, + 0xC704, 0xC0A7, 0xC705, 0xC0A8, 0xC706, 0x9F8F, 0xC707, 0x9F90, 0xC708, 0xC0A9, 0xC709, 0x9F91, 0xC70A, 0x9F92, 0xC70B, 0x9F93, + 0xC70C, 0xC0AA, 0xC70D, 0x9F94, 0xC70E, 0x9F95, 0xC70F, 0x9F96, 0xC710, 0x9F97, 0xC711, 0x9F98, 0xC712, 0x9F99, 0xC713, 0x9F9A, + 0xC714, 0xC0AB, 0xC715, 0xC0AC, 0xC716, 0x9F9B, 0xC717, 0xC0AD, 0xC718, 0x9F9C, 0xC719, 0xC0AE, 0xC71A, 0x9F9D, 0xC71B, 0x9F9E, + 0xC71C, 0x9F9F, 0xC71D, 0x9FA0, 0xC71E, 0x9FA1, 0xC71F, 0x9FA2, 0xC720, 0xC0AF, 0xC721, 0xC0B0, 0xC722, 0x9FA3, 0xC723, 0x9FA4, + 0xC724, 0xC0B1, 0xC725, 0x9FA5, 0xC726, 0x9FA6, 0xC727, 0x9FA7, 0xC728, 0xC0B2, 0xC729, 0x9FA8, 0xC72A, 0x9FA9, 0xC72B, 0x9FAA, + 0xC72C, 0x9FAB, 0xC72D, 0x9FAC, 0xC72E, 0x9FAD, 0xC72F, 0x9FAE, 0xC730, 0xC0B3, 0xC731, 0xC0B4, 0xC732, 0x9FAF, 0xC733, 0xC0B5, + 0xC734, 0x9FB0, 0xC735, 0xC0B6, 0xC736, 0x9FB1, 0xC737, 0xC0B7, 0xC738, 0x9FB2, 0xC739, 0x9FB3, 0xC73A, 0x9FB4, 0xC73B, 0x9FB5, + 0xC73C, 0xC0B8, 0xC73D, 0xC0B9, 0xC73E, 0x9FB6, 0xC73F, 0x9FB7, 0xC740, 0xC0BA, 0xC741, 0x9FB8, 0xC742, 0x9FB9, 0xC743, 0x9FBA, + 0xC744, 0xC0BB, 0xC745, 0x9FBB, 0xC746, 0x9FBC, 0xC747, 0x9FBD, 0xC748, 0x9FBE, 0xC749, 0x9FBF, 0xC74A, 0xC0BC, 0xC74B, 0x9FC0, + 0xC74C, 0xC0BD, 0xC74D, 0xC0BE, 0xC74E, 0x9FC1, 0xC74F, 0xC0BF, 0xC750, 0x9FC2, 0xC751, 0xC0C0, 0xC752, 0xC0C1, 0xC753, 0xC0C2, + 0xC754, 0xC0C3, 0xC755, 0xC0C4, 0xC756, 0xC0C5, 0xC757, 0xC0C6, 0xC758, 0xC0C7, 0xC759, 0x9FC3, 0xC75A, 0x9FC4, 0xC75B, 0x9FC5, + 0xC75C, 0xC0C8, 0xC75D, 0x9FC6, 0xC75E, 0x9FC7, 0xC75F, 0x9FC8, 0xC760, 0xC0C9, 0xC761, 0x9FC9, 0xC762, 0x9FCA, 0xC763, 0x9FCB, + 0xC764, 0x9FCC, 0xC765, 0x9FCD, 0xC766, 0x9FCE, 0xC767, 0x9FCF, 0xC768, 0xC0CA, 0xC769, 0x9FD0, 0xC76A, 0x9FD1, 0xC76B, 0xC0CB, + 0xC76C, 0x9FD2, 0xC76D, 0x9FD3, 0xC76E, 0x9FD4, 0xC76F, 0x9FD5, 0xC770, 0x9FD6, 0xC771, 0x9FD7, 0xC772, 0x9FD8, 0xC773, 0x9FD9, + 0xC774, 0xC0CC, 0xC775, 0xC0CD, 0xC776, 0x9FDA, 0xC777, 0x9FDB, 0xC778, 0xC0CE, 0xC779, 0x9FDC, 0xC77A, 0x9FDD, 0xC77B, 0x9FDE, + 0xC77C, 0xC0CF, 0xC77D, 0xC0D0, 0xC77E, 0xC0D1, 0xC77F, 0x9FDF, 0xC780, 0x9FE0, 0xC781, 0x9FE1, 0xC782, 0x9FE2, 0xC783, 0xC0D2, + 0xC784, 0xC0D3, 0xC785, 0xC0D4, 0xC786, 0x9FE3, 0xC787, 0xC0D5, 0xC788, 0xC0D6, 0xC789, 0xC0D7, 0xC78A, 0xC0D8, 0xC78B, 0x9FE4, + 0xC78C, 0x9FE5, 0xC78D, 0x9FE6, 0xC78E, 0xC0D9, 0xC78F, 0x9FE7, 0xC790, 0xC0DA, 0xC791, 0xC0DB, 0xC792, 0x9FE8, 0xC793, 0x9FE9, + 0xC794, 0xC0DC, 0xC795, 0x9FEA, 0xC796, 0xC0DD, 0xC797, 0xC0DE, 0xC798, 0xC0DF, 0xC799, 0x9FEB, 0xC79A, 0xC0E0, 0xC79B, 0x9FEC, + 0xC79C, 0x9FED, 0xC79D, 0x9FEE, 0xC79E, 0x9FEF, 0xC79F, 0x9FF0, 0xC7A0, 0xC0E1, 0xC7A1, 0xC0E2, 0xC7A2, 0x9FF1, 0xC7A3, 0xC0E3, + 0xC7A4, 0xC0E4, 0xC7A5, 0xC0E5, 0xC7A6, 0xC0E6, 0xC7A7, 0x9FF2, 0xC7A8, 0x9FF3, 0xC7A9, 0x9FF4, 0xC7AA, 0x9FF5, 0xC7AB, 0x9FF6, + 0xC7AC, 0xC0E7, 0xC7AD, 0xC0E8, 0xC7AE, 0x9FF7, 0xC7AF, 0x9FF8, 0xC7B0, 0xC0E9, 0xC7B1, 0x9FF9, 0xC7B2, 0x9FFA, 0xC7B3, 0x9FFB, + 0xC7B4, 0xC0EA, 0xC7B5, 0x9FFC, 0xC7B6, 0x9FFD, 0xC7B7, 0x9FFE, 0xC7B8, 0xA041, 0xC7B9, 0xA042, 0xC7BA, 0xA043, 0xC7BB, 0xA044, + 0xC7BC, 0xC0EB, 0xC7BD, 0xC0EC, 0xC7BE, 0xA045, 0xC7BF, 0xC0ED, 0xC7C0, 0xC0EE, 0xC7C1, 0xC0EF, 0xC7C2, 0xA046, 0xC7C3, 0xA047, + 0xC7C4, 0xA048, 0xC7C5, 0xA049, 0xC7C6, 0xA04A, 0xC7C7, 0xA04B, 0xC7C8, 0xC0F0, 0xC7C9, 0xC0F1, 0xC7CA, 0xA04C, 0xC7CB, 0xA04D, + 0xC7CC, 0xC0F2, 0xC7CD, 0xA04E, 0xC7CE, 0xC0F3, 0xC7CF, 0xA04F, 0xC7D0, 0xC0F4, 0xC7D1, 0xA050, 0xC7D2, 0xA051, 0xC7D3, 0xA052, + 0xC7D4, 0xA053, 0xC7D5, 0xA054, 0xC7D6, 0xA055, 0xC7D7, 0xA056, 0xC7D8, 0xC0F5, 0xC7D9, 0xA057, 0xC7DA, 0xA058, 0xC7DB, 0xA059, + 0xC7DC, 0xA05A, 0xC7DD, 0xC0F6, 0xC7DE, 0xA061, 0xC7DF, 0xA062, 0xC7E0, 0xA063, 0xC7E1, 0xA064, 0xC7E2, 0xA065, 0xC7E3, 0xA066, + 0xC7E4, 0xC0F7, 0xC7E5, 0xA067, 0xC7E6, 0xA068, 0xC7E7, 0xA069, 0xC7E8, 0xC0F8, 0xC7E9, 0xA06A, 0xC7EA, 0xA06B, 0xC7EB, 0xA06C, + 0xC7EC, 0xC0F9, 0xC7ED, 0xA06D, 0xC7EE, 0xA06E, 0xC7EF, 0xA06F, 0xC7F0, 0xA070, 0xC7F1, 0xA071, 0xC7F2, 0xA072, 0xC7F3, 0xA073, + 0xC7F4, 0xA074, 0xC7F5, 0xA075, 0xC7F6, 0xA076, 0xC7F7, 0xA077, 0xC7F8, 0xA078, 0xC7F9, 0xA079, 0xC7FA, 0xA07A, 0xC7FB, 0xA081, + 0xC7FC, 0xA082, 0xC7FD, 0xA083, 0xC7FE, 0xA084, 0xC7FF, 0xA085, 0xC800, 0xC0FA, 0xC801, 0xC0FB, 0xC802, 0xA086, 0xC803, 0xA087, + 0xC804, 0xC0FC, 0xC805, 0xA088, 0xC806, 0xA089, 0xC807, 0xA08A, 0xC808, 0xC0FD, 0xC809, 0xA08B, 0xC80A, 0xC0FE, 0xC80B, 0xA08C, + 0xC80C, 0xA08D, 0xC80D, 0xA08E, 0xC80E, 0xA08F, 0xC80F, 0xA090, 0xC810, 0xC1A1, 0xC811, 0xC1A2, 0xC812, 0xA091, 0xC813, 0xC1A3, + 0xC814, 0xA092, 0xC815, 0xC1A4, 0xC816, 0xC1A5, 0xC817, 0xA093, 0xC818, 0xA094, 0xC819, 0xA095, 0xC81A, 0xA096, 0xC81B, 0xA097, + 0xC81C, 0xC1A6, 0xC81D, 0xC1A7, 0xC81E, 0xA098, 0xC81F, 0xA099, 0xC820, 0xC1A8, 0xC821, 0xA09A, 0xC822, 0xA09B, 0xC823, 0xA09C, + 0xC824, 0xC1A9, 0xC825, 0xA09D, 0xC826, 0xA09E, 0xC827, 0xA09F, 0xC828, 0xA0A0, 0xC829, 0xA0A1, 0xC82A, 0xA0A2, 0xC82B, 0xA0A3, + 0xC82C, 0xC1AA, 0xC82D, 0xC1AB, 0xC82E, 0xA0A4, 0xC82F, 0xC1AC, 0xC830, 0xA0A5, 0xC831, 0xC1AD, 0xC832, 0xA0A6, 0xC833, 0xA0A7, + 0xC834, 0xA0A8, 0xC835, 0xA0A9, 0xC836, 0xA0AA, 0xC837, 0xA0AB, 0xC838, 0xC1AE, 0xC839, 0xA0AC, 0xC83A, 0xA0AD, 0xC83B, 0xA0AE, + 0xC83C, 0xC1AF, 0xC83D, 0xA0AF, 0xC83E, 0xA0B0, 0xC83F, 0xA0B1, 0xC840, 0xC1B0, 0xC841, 0xA0B2, 0xC842, 0xA0B3, 0xC843, 0xA0B4, + 0xC844, 0xA0B5, 0xC845, 0xA0B6, 0xC846, 0xA0B7, 0xC847, 0xA0B8, 0xC848, 0xC1B1, 0xC849, 0xC1B2, 0xC84A, 0xA0B9, 0xC84B, 0xA0BA, + 0xC84C, 0xC1B3, 0xC84D, 0xC1B4, 0xC84E, 0xA0BB, 0xC84F, 0xA0BC, 0xC850, 0xA0BD, 0xC851, 0xA0BE, 0xC852, 0xA0BF, 0xC853, 0xA0C0, + 0xC854, 0xC1B5, 0xC855, 0xA0C1, 0xC856, 0xA0C2, 0xC857, 0xA0C3, 0xC858, 0xA0C4, 0xC859, 0xA0C5, 0xC85A, 0xA0C6, 0xC85B, 0xA0C7, + 0xC85C, 0xA0C8, 0xC85D, 0xA0C9, 0xC85E, 0xA0CA, 0xC85F, 0xA0CB, 0xC860, 0xA0CC, 0xC861, 0xA0CD, 0xC862, 0xA0CE, 0xC863, 0xA0CF, + 0xC864, 0xA0D0, 0xC865, 0xA0D1, 0xC866, 0xA0D2, 0xC867, 0xA0D3, 0xC868, 0xA0D4, 0xC869, 0xA0D5, 0xC86A, 0xA0D6, 0xC86B, 0xA0D7, + 0xC86C, 0xA0D8, 0xC86D, 0xA0D9, 0xC86E, 0xA0DA, 0xC86F, 0xA0DB, 0xC870, 0xC1B6, 0xC871, 0xC1B7, 0xC872, 0xA0DC, 0xC873, 0xA0DD, + 0xC874, 0xC1B8, 0xC875, 0xA0DE, 0xC876, 0xA0DF, 0xC877, 0xA0E0, 0xC878, 0xC1B9, 0xC879, 0xA0E1, 0xC87A, 0xC1BA, 0xC87B, 0xA0E2, + 0xC87C, 0xA0E3, 0xC87D, 0xA0E4, 0xC87E, 0xA0E5, 0xC87F, 0xA0E6, 0xC880, 0xC1BB, 0xC881, 0xC1BC, 0xC882, 0xA0E7, 0xC883, 0xC1BD, + 0xC884, 0xA0E8, 0xC885, 0xC1BE, 0xC886, 0xC1BF, 0xC887, 0xC1C0, 0xC888, 0xA0E9, 0xC889, 0xA0EA, 0xC88A, 0xA0EB, 0xC88B, 0xC1C1, + 0xC88C, 0xC1C2, 0xC88D, 0xC1C3, 0xC88E, 0xA0EC, 0xC88F, 0xA0ED, 0xC890, 0xA0EE, 0xC891, 0xA0EF, 0xC892, 0xA0F0, 0xC893, 0xA0F1, + 0xC894, 0xC1C4, 0xC895, 0xA0F2, 0xC896, 0xA0F3, 0xC897, 0xA0F4, 0xC898, 0xA0F5, 0xC899, 0xA0F6, 0xC89A, 0xA0F7, 0xC89B, 0xA0F8, + 0xC89C, 0xA0F9, 0xC89D, 0xC1C5, 0xC89E, 0xA0FA, 0xC89F, 0xC1C6, 0xC8A0, 0xA0FB, 0xC8A1, 0xC1C7, 0xC8A2, 0xA0FC, 0xC8A3, 0xA0FD, + 0xC8A4, 0xA0FE, 0xC8A5, 0xA141, 0xC8A6, 0xA142, 0xC8A7, 0xA143, 0xC8A8, 0xC1C8, 0xC8A9, 0xA144, 0xC8AA, 0xA145, 0xC8AB, 0xA146, + 0xC8AC, 0xA147, 0xC8AD, 0xA148, 0xC8AE, 0xA149, 0xC8AF, 0xA14A, 0xC8B0, 0xA14B, 0xC8B1, 0xA14C, 0xC8B2, 0xA14D, 0xC8B3, 0xA14E, + 0xC8B4, 0xA14F, 0xC8B5, 0xA150, 0xC8B6, 0xA151, 0xC8B7, 0xA152, 0xC8B8, 0xA153, 0xC8B9, 0xA154, 0xC8BA, 0xA155, 0xC8BB, 0xA156, + 0xC8BC, 0xC1C9, 0xC8BD, 0xC1CA, 0xC8BE, 0xA157, 0xC8BF, 0xA158, 0xC8C0, 0xA159, 0xC8C1, 0xA15A, 0xC8C2, 0xA161, 0xC8C3, 0xA162, + 0xC8C4, 0xC1CB, 0xC8C5, 0xA163, 0xC8C6, 0xA164, 0xC8C7, 0xA165, 0xC8C8, 0xC1CC, 0xC8C9, 0xA166, 0xC8CA, 0xA167, 0xC8CB, 0xA168, + 0xC8CC, 0xC1CD, 0xC8CD, 0xA169, 0xC8CE, 0xA16A, 0xC8CF, 0xA16B, 0xC8D0, 0xA16C, 0xC8D1, 0xA16D, 0xC8D2, 0xA16E, 0xC8D3, 0xA16F, + 0xC8D4, 0xC1CE, 0xC8D5, 0xC1CF, 0xC8D6, 0xA170, 0xC8D7, 0xC1D0, 0xC8D8, 0xA171, 0xC8D9, 0xC1D1, 0xC8DA, 0xA172, 0xC8DB, 0xA173, + 0xC8DC, 0xA174, 0xC8DD, 0xA175, 0xC8DE, 0xA176, 0xC8DF, 0xA177, 0xC8E0, 0xC1D2, 0xC8E1, 0xC1D3, 0xC8E2, 0xA178, 0xC8E3, 0xA179, + 0xC8E4, 0xC1D4, 0xC8E5, 0xA17A, 0xC8E6, 0xA181, 0xC8E7, 0xA182, 0xC8E8, 0xA183, 0xC8E9, 0xA184, 0xC8EA, 0xA185, 0xC8EB, 0xA186, + 0xC8EC, 0xA187, 0xC8ED, 0xA188, 0xC8EE, 0xA189, 0xC8EF, 0xA18A, 0xC8F0, 0xA18B, 0xC8F1, 0xA18C, 0xC8F2, 0xA18D, 0xC8F3, 0xA18E, + 0xC8F4, 0xA18F, 0xC8F5, 0xC1D5, 0xC8F6, 0xA190, 0xC8F7, 0xA191, 0xC8F8, 0xA192, 0xC8F9, 0xA193, 0xC8FA, 0xA194, 0xC8FB, 0xA195, + 0xC8FC, 0xC1D6, 0xC8FD, 0xC1D7, 0xC8FE, 0xA196, 0xC8FF, 0xA197, 0xC900, 0xC1D8, 0xC901, 0xA198, 0xC902, 0xA199, 0xC903, 0xA19A, + 0xC904, 0xC1D9, 0xC905, 0xC1DA, 0xC906, 0xC1DB, 0xC907, 0xA19B, 0xC908, 0xA19C, 0xC909, 0xA19D, 0xC90A, 0xA19E, 0xC90B, 0xA19F, + 0xC90C, 0xC1DC, 0xC90D, 0xC1DD, 0xC90E, 0xA1A0, 0xC90F, 0xC1DE, 0xC910, 0xA241, 0xC911, 0xC1DF, 0xC912, 0xA242, 0xC913, 0xA243, + 0xC914, 0xA244, 0xC915, 0xA245, 0xC916, 0xA246, 0xC917, 0xA247, 0xC918, 0xC1E0, 0xC919, 0xA248, 0xC91A, 0xA249, 0xC91B, 0xA24A, + 0xC91C, 0xA24B, 0xC91D, 0xA24C, 0xC91E, 0xA24D, 0xC91F, 0xA24E, 0xC920, 0xA24F, 0xC921, 0xA250, 0xC922, 0xA251, 0xC923, 0xA252, + 0xC924, 0xA253, 0xC925, 0xA254, 0xC926, 0xA255, 0xC927, 0xA256, 0xC928, 0xA257, 0xC929, 0xA258, 0xC92A, 0xA259, 0xC92B, 0xA25A, + 0xC92C, 0xC1E1, 0xC92D, 0xA261, 0xC92E, 0xA262, 0xC92F, 0xA263, 0xC930, 0xA264, 0xC931, 0xA265, 0xC932, 0xA266, 0xC933, 0xA267, + 0xC934, 0xC1E2, 0xC935, 0xA268, 0xC936, 0xA269, 0xC937, 0xA26A, 0xC938, 0xA26B, 0xC939, 0xA26C, 0xC93A, 0xA26D, 0xC93B, 0xA26E, + 0xC93C, 0xA26F, 0xC93D, 0xA270, 0xC93E, 0xA271, 0xC93F, 0xA272, 0xC940, 0xA273, 0xC941, 0xA274, 0xC942, 0xA275, 0xC943, 0xA276, + 0xC944, 0xA277, 0xC945, 0xA278, 0xC946, 0xA279, 0xC947, 0xA27A, 0xC948, 0xA281, 0xC949, 0xA282, 0xC94A, 0xA283, 0xC94B, 0xA284, + 0xC94C, 0xA285, 0xC94D, 0xA286, 0xC94E, 0xA287, 0xC94F, 0xA288, 0xC950, 0xC1E3, 0xC951, 0xC1E4, 0xC952, 0xA289, 0xC953, 0xA28A, + 0xC954, 0xC1E5, 0xC955, 0xA28B, 0xC956, 0xA28C, 0xC957, 0xA28D, 0xC958, 0xC1E6, 0xC959, 0xA28E, 0xC95A, 0xA28F, 0xC95B, 0xA290, + 0xC95C, 0xA291, 0xC95D, 0xA292, 0xC95E, 0xA293, 0xC95F, 0xA294, 0xC960, 0xC1E7, 0xC961, 0xC1E8, 0xC962, 0xA295, 0xC963, 0xC1E9, + 0xC964, 0xA296, 0xC965, 0xA297, 0xC966, 0xA298, 0xC967, 0xA299, 0xC968, 0xA29A, 0xC969, 0xA29B, 0xC96A, 0xA29C, 0xC96B, 0xA29D, + 0xC96C, 0xC1EA, 0xC96D, 0xA29E, 0xC96E, 0xA29F, 0xC96F, 0xA2A0, 0xC970, 0xC1EB, 0xC971, 0xA341, 0xC972, 0xA342, 0xC973, 0xA343, + 0xC974, 0xC1EC, 0xC975, 0xA344, 0xC976, 0xA345, 0xC977, 0xA346, 0xC978, 0xA347, 0xC979, 0xA348, 0xC97A, 0xA349, 0xC97B, 0xA34A, + 0xC97C, 0xC1ED, 0xC97D, 0xA34B, 0xC97E, 0xA34C, 0xC97F, 0xA34D, 0xC980, 0xA34E, 0xC981, 0xA34F, 0xC982, 0xA350, 0xC983, 0xA351, + 0xC984, 0xA352, 0xC985, 0xA353, 0xC986, 0xA354, 0xC987, 0xA355, 0xC988, 0xC1EE, 0xC989, 0xC1EF, 0xC98A, 0xA356, 0xC98B, 0xA357, + 0xC98C, 0xC1F0, 0xC98D, 0xA358, 0xC98E, 0xA359, 0xC98F, 0xA35A, 0xC990, 0xC1F1, 0xC991, 0xA361, 0xC992, 0xA362, 0xC993, 0xA363, + 0xC994, 0xA364, 0xC995, 0xA365, 0xC996, 0xA366, 0xC997, 0xA367, 0xC998, 0xC1F2, 0xC999, 0xC1F3, 0xC99A, 0xA368, 0xC99B, 0xC1F4, + 0xC99C, 0xA369, 0xC99D, 0xC1F5, 0xC99E, 0xA36A, 0xC99F, 0xA36B, 0xC9A0, 0xA36C, 0xC9A1, 0xA36D, 0xC9A2, 0xA36E, 0xC9A3, 0xA36F, + 0xC9A4, 0xA370, 0xC9A5, 0xA371, 0xC9A6, 0xA372, 0xC9A7, 0xA373, 0xC9A8, 0xA374, 0xC9A9, 0xA375, 0xC9AA, 0xA376, 0xC9AB, 0xA377, + 0xC9AC, 0xA378, 0xC9AD, 0xA379, 0xC9AE, 0xA37A, 0xC9AF, 0xA381, 0xC9B0, 0xA382, 0xC9B1, 0xA383, 0xC9B2, 0xA384, 0xC9B3, 0xA385, + 0xC9B4, 0xA386, 0xC9B5, 0xA387, 0xC9B6, 0xA388, 0xC9B7, 0xA389, 0xC9B8, 0xA38A, 0xC9B9, 0xA38B, 0xC9BA, 0xA38C, 0xC9BB, 0xA38D, + 0xC9BC, 0xA38E, 0xC9BD, 0xA38F, 0xC9BE, 0xA390, 0xC9BF, 0xA391, 0xC9C0, 0xC1F6, 0xC9C1, 0xC1F7, 0xC9C2, 0xA392, 0xC9C3, 0xA393, + 0xC9C4, 0xC1F8, 0xC9C5, 0xA394, 0xC9C6, 0xA395, 0xC9C7, 0xC1F9, 0xC9C8, 0xC1FA, 0xC9C9, 0xA396, 0xC9CA, 0xC1FB, 0xC9CB, 0xA397, + 0xC9CC, 0xA398, 0xC9CD, 0xA399, 0xC9CE, 0xA39A, 0xC9CF, 0xA39B, 0xC9D0, 0xC1FC, 0xC9D1, 0xC1FD, 0xC9D2, 0xA39C, 0xC9D3, 0xC1FE, + 0xC9D4, 0xA39D, 0xC9D5, 0xC2A1, 0xC9D6, 0xC2A2, 0xC9D7, 0xA39E, 0xC9D8, 0xA39F, 0xC9D9, 0xC2A3, 0xC9DA, 0xC2A4, 0xC9DB, 0xA3A0, + 0xC9DC, 0xC2A5, 0xC9DD, 0xC2A6, 0xC9DE, 0xA441, 0xC9DF, 0xA442, 0xC9E0, 0xC2A7, 0xC9E1, 0xA443, 0xC9E2, 0xC2A8, 0xC9E3, 0xA444, + 0xC9E4, 0xC2A9, 0xC9E5, 0xA445, 0xC9E6, 0xA446, 0xC9E7, 0xC2AA, 0xC9E8, 0xA447, 0xC9E9, 0xA448, 0xC9EA, 0xA449, 0xC9EB, 0xA44A, + 0xC9EC, 0xC2AB, 0xC9ED, 0xC2AC, 0xC9EE, 0xA44B, 0xC9EF, 0xC2AD, 0xC9F0, 0xC2AE, 0xC9F1, 0xC2AF, 0xC9F2, 0xA44C, 0xC9F3, 0xA44D, + 0xC9F4, 0xA44E, 0xC9F5, 0xA44F, 0xC9F6, 0xA450, 0xC9F7, 0xA451, 0xC9F8, 0xC2B0, 0xC9F9, 0xC2B1, 0xC9FA, 0xA452, 0xC9FB, 0xA453, + 0xC9FC, 0xC2B2, 0xC9FD, 0xA454, 0xC9FE, 0xA455, 0xC9FF, 0xA456, 0xCA00, 0xC2B3, 0xCA01, 0xA457, 0xCA02, 0xA458, 0xCA03, 0xA459, + 0xCA04, 0xA45A, 0xCA05, 0xA461, 0xCA06, 0xA462, 0xCA07, 0xA463, 0xCA08, 0xC2B4, 0xCA09, 0xC2B5, 0xCA0A, 0xA464, 0xCA0B, 0xC2B6, + 0xCA0C, 0xC2B7, 0xCA0D, 0xC2B8, 0xCA0E, 0xA465, 0xCA0F, 0xA466, 0xCA10, 0xA467, 0xCA11, 0xA468, 0xCA12, 0xA469, 0xCA13, 0xA46A, + 0xCA14, 0xC2B9, 0xCA15, 0xA46B, 0xCA16, 0xA46C, 0xCA17, 0xA46D, 0xCA18, 0xC2BA, 0xCA19, 0xA46E, 0xCA1A, 0xA46F, 0xCA1B, 0xA470, + 0xCA1C, 0xA471, 0xCA1D, 0xA472, 0xCA1E, 0xA473, 0xCA1F, 0xA474, 0xCA20, 0xA475, 0xCA21, 0xA476, 0xCA22, 0xA477, 0xCA23, 0xA478, + 0xCA24, 0xA479, 0xCA25, 0xA47A, 0xCA26, 0xA481, 0xCA27, 0xA482, 0xCA28, 0xA483, 0xCA29, 0xC2BB, 0xCA2A, 0xA484, 0xCA2B, 0xA485, + 0xCA2C, 0xA486, 0xCA2D, 0xA487, 0xCA2E, 0xA488, 0xCA2F, 0xA489, 0xCA30, 0xA48A, 0xCA31, 0xA48B, 0xCA32, 0xA48C, 0xCA33, 0xA48D, + 0xCA34, 0xA48E, 0xCA35, 0xA48F, 0xCA36, 0xA490, 0xCA37, 0xA491, 0xCA38, 0xA492, 0xCA39, 0xA493, 0xCA3A, 0xA494, 0xCA3B, 0xA495, + 0xCA3C, 0xA496, 0xCA3D, 0xA497, 0xCA3E, 0xA498, 0xCA3F, 0xA499, 0xCA40, 0xA49A, 0xCA41, 0xA49B, 0xCA42, 0xA49C, 0xCA43, 0xA49D, + 0xCA44, 0xA49E, 0xCA45, 0xA49F, 0xCA46, 0xA4A0, 0xCA47, 0xA541, 0xCA48, 0xA542, 0xCA49, 0xA543, 0xCA4A, 0xA544, 0xCA4B, 0xA545, + 0xCA4C, 0xC2BC, 0xCA4D, 0xC2BD, 0xCA4E, 0xA546, 0xCA4F, 0xA547, 0xCA50, 0xC2BE, 0xCA51, 0xA548, 0xCA52, 0xA549, 0xCA53, 0xA54A, + 0xCA54, 0xC2BF, 0xCA55, 0xA54B, 0xCA56, 0xA54C, 0xCA57, 0xA54D, 0xCA58, 0xA54E, 0xCA59, 0xA54F, 0xCA5A, 0xA550, 0xCA5B, 0xA551, + 0xCA5C, 0xC2C0, 0xCA5D, 0xC2C1, 0xCA5E, 0xA552, 0xCA5F, 0xC2C2, 0xCA60, 0xC2C3, 0xCA61, 0xC2C4, 0xCA62, 0xA553, 0xCA63, 0xA554, + 0xCA64, 0xA555, 0xCA65, 0xA556, 0xCA66, 0xA557, 0xCA67, 0xA558, 0xCA68, 0xC2C5, 0xCA69, 0xA559, 0xCA6A, 0xA55A, 0xCA6B, 0xA561, + 0xCA6C, 0xA562, 0xCA6D, 0xA563, 0xCA6E, 0xA564, 0xCA6F, 0xA565, 0xCA70, 0xA566, 0xCA71, 0xA567, 0xCA72, 0xA568, 0xCA73, 0xA569, + 0xCA74, 0xA56A, 0xCA75, 0xA56B, 0xCA76, 0xA56C, 0xCA77, 0xA56D, 0xCA78, 0xA56E, 0xCA79, 0xA56F, 0xCA7A, 0xA570, 0xCA7B, 0xA571, + 0xCA7C, 0xA572, 0xCA7D, 0xC2C6, 0xCA7E, 0xA573, 0xCA7F, 0xA574, 0xCA80, 0xA575, 0xCA81, 0xA576, 0xCA82, 0xA577, 0xCA83, 0xA578, + 0xCA84, 0xC2C7, 0xCA85, 0xA579, 0xCA86, 0xA57A, 0xCA87, 0xA581, 0xCA88, 0xA582, 0xCA89, 0xA583, 0xCA8A, 0xA584, 0xCA8B, 0xA585, + 0xCA8C, 0xA586, 0xCA8D, 0xA587, 0xCA8E, 0xA588, 0xCA8F, 0xA589, 0xCA90, 0xA58A, 0xCA91, 0xA58B, 0xCA92, 0xA58C, 0xCA93, 0xA58D, + 0xCA94, 0xA58E, 0xCA95, 0xA58F, 0xCA96, 0xA590, 0xCA97, 0xA591, 0xCA98, 0xC2C8, 0xCA99, 0xA592, 0xCA9A, 0xA593, 0xCA9B, 0xA594, + 0xCA9C, 0xA595, 0xCA9D, 0xA596, 0xCA9E, 0xA597, 0xCA9F, 0xA598, 0xCAA0, 0xA599, 0xCAA1, 0xA59A, 0xCAA2, 0xA59B, 0xCAA3, 0xA59C, + 0xCAA4, 0xA59D, 0xCAA5, 0xA59E, 0xCAA6, 0xA59F, 0xCAA7, 0xA5A0, 0xCAA8, 0xA641, 0xCAA9, 0xA642, 0xCAAA, 0xA643, 0xCAAB, 0xA644, + 0xCAAC, 0xA645, 0xCAAD, 0xA646, 0xCAAE, 0xA647, 0xCAAF, 0xA648, 0xCAB0, 0xA649, 0xCAB1, 0xA64A, 0xCAB2, 0xA64B, 0xCAB3, 0xA64C, + 0xCAB4, 0xA64D, 0xCAB5, 0xA64E, 0xCAB6, 0xA64F, 0xCAB7, 0xA650, 0xCAB8, 0xA651, 0xCAB9, 0xA652, 0xCABA, 0xA653, 0xCABB, 0xA654, + 0xCABC, 0xC2C9, 0xCABD, 0xC2CA, 0xCABE, 0xA655, 0xCABF, 0xA656, 0xCAC0, 0xC2CB, 0xCAC1, 0xA657, 0xCAC2, 0xA658, 0xCAC3, 0xA659, + 0xCAC4, 0xC2CC, 0xCAC5, 0xA65A, 0xCAC6, 0xA661, 0xCAC7, 0xA662, 0xCAC8, 0xA663, 0xCAC9, 0xA664, 0xCACA, 0xA665, 0xCACB, 0xA666, + 0xCACC, 0xC2CD, 0xCACD, 0xC2CE, 0xCACE, 0xA667, 0xCACF, 0xC2CF, 0xCAD0, 0xA668, 0xCAD1, 0xC2D0, 0xCAD2, 0xA669, 0xCAD3, 0xC2D1, + 0xCAD4, 0xA66A, 0xCAD5, 0xA66B, 0xCAD6, 0xA66C, 0xCAD7, 0xA66D, 0xCAD8, 0xC2D2, 0xCAD9, 0xC2D3, 0xCADA, 0xA66E, 0xCADB, 0xA66F, + 0xCADC, 0xA670, 0xCADD, 0xA671, 0xCADE, 0xA672, 0xCADF, 0xA673, 0xCAE0, 0xC2D4, 0xCAE1, 0xA674, 0xCAE2, 0xA675, 0xCAE3, 0xA676, + 0xCAE4, 0xA677, 0xCAE5, 0xA678, 0xCAE6, 0xA679, 0xCAE7, 0xA67A, 0xCAE8, 0xA681, 0xCAE9, 0xA682, 0xCAEA, 0xA683, 0xCAEB, 0xA684, + 0xCAEC, 0xC2D5, 0xCAED, 0xA685, 0xCAEE, 0xA686, 0xCAEF, 0xA687, 0xCAF0, 0xA688, 0xCAF1, 0xA689, 0xCAF2, 0xA68A, 0xCAF3, 0xA68B, + 0xCAF4, 0xC2D6, 0xCAF5, 0xA68C, 0xCAF6, 0xA68D, 0xCAF7, 0xA68E, 0xCAF8, 0xA68F, 0xCAF9, 0xA690, 0xCAFA, 0xA691, 0xCAFB, 0xA692, + 0xCAFC, 0xA693, 0xCAFD, 0xA694, 0xCAFE, 0xA695, 0xCAFF, 0xA696, 0xCB00, 0xA697, 0xCB01, 0xA698, 0xCB02, 0xA699, 0xCB03, 0xA69A, + 0xCB04, 0xA69B, 0xCB05, 0xA69C, 0xCB06, 0xA69D, 0xCB07, 0xA69E, 0xCB08, 0xC2D7, 0xCB09, 0xA69F, 0xCB0A, 0xA6A0, 0xCB0B, 0xA741, + 0xCB0C, 0xA742, 0xCB0D, 0xA743, 0xCB0E, 0xA744, 0xCB0F, 0xA745, 0xCB10, 0xC2D8, 0xCB11, 0xA746, 0xCB12, 0xA747, 0xCB13, 0xA748, + 0xCB14, 0xC2D9, 0xCB15, 0xA749, 0xCB16, 0xA74A, 0xCB17, 0xA74B, 0xCB18, 0xC2DA, 0xCB19, 0xA74C, 0xCB1A, 0xA74D, 0xCB1B, 0xA74E, + 0xCB1C, 0xA74F, 0xCB1D, 0xA750, 0xCB1E, 0xA751, 0xCB1F, 0xA752, 0xCB20, 0xC2DB, 0xCB21, 0xC2DC, 0xCB22, 0xA753, 0xCB23, 0xA754, + 0xCB24, 0xA755, 0xCB25, 0xA756, 0xCB26, 0xA757, 0xCB27, 0xA758, 0xCB28, 0xA759, 0xCB29, 0xA75A, 0xCB2A, 0xA761, 0xCB2B, 0xA762, + 0xCB2C, 0xA763, 0xCB2D, 0xA764, 0xCB2E, 0xA765, 0xCB2F, 0xA766, 0xCB30, 0xA767, 0xCB31, 0xA768, 0xCB32, 0xA769, 0xCB33, 0xA76A, + 0xCB34, 0xA76B, 0xCB35, 0xA76C, 0xCB36, 0xA76D, 0xCB37, 0xA76E, 0xCB38, 0xA76F, 0xCB39, 0xA770, 0xCB3A, 0xA771, 0xCB3B, 0xA772, + 0xCB3C, 0xA773, 0xCB3D, 0xA774, 0xCB3E, 0xA775, 0xCB3F, 0xA776, 0xCB40, 0xA777, 0xCB41, 0xC2DD, 0xCB42, 0xA778, 0xCB43, 0xA779, + 0xCB44, 0xA77A, 0xCB45, 0xA781, 0xCB46, 0xA782, 0xCB47, 0xA783, 0xCB48, 0xC2DE, 0xCB49, 0xC2DF, 0xCB4A, 0xA784, 0xCB4B, 0xA785, + 0xCB4C, 0xC2E0, 0xCB4D, 0xA786, 0xCB4E, 0xA787, 0xCB4F, 0xA788, 0xCB50, 0xC2E1, 0xCB51, 0xA789, 0xCB52, 0xA78A, 0xCB53, 0xA78B, + 0xCB54, 0xA78C, 0xCB55, 0xA78D, 0xCB56, 0xA78E, 0xCB57, 0xA78F, 0xCB58, 0xC2E2, 0xCB59, 0xC2E3, 0xCB5A, 0xA790, 0xCB5B, 0xA791, + 0xCB5C, 0xA792, 0xCB5D, 0xC2E4, 0xCB5E, 0xA793, 0xCB5F, 0xA794, 0xCB60, 0xA795, 0xCB61, 0xA796, 0xCB62, 0xA797, 0xCB63, 0xA798, + 0xCB64, 0xC2E5, 0xCB65, 0xA799, 0xCB66, 0xA79A, 0xCB67, 0xA79B, 0xCB68, 0xA79C, 0xCB69, 0xA79D, 0xCB6A, 0xA79E, 0xCB6B, 0xA79F, + 0xCB6C, 0xA7A0, 0xCB6D, 0xA841, 0xCB6E, 0xA842, 0xCB6F, 0xA843, 0xCB70, 0xA844, 0xCB71, 0xA845, 0xCB72, 0xA846, 0xCB73, 0xA847, + 0xCB74, 0xA848, 0xCB75, 0xA849, 0xCB76, 0xA84A, 0xCB77, 0xA84B, 0xCB78, 0xC2E6, 0xCB79, 0xC2E7, 0xCB7A, 0xA84C, 0xCB7B, 0xA84D, + 0xCB7C, 0xA84E, 0xCB7D, 0xA84F, 0xCB7E, 0xA850, 0xCB7F, 0xA851, 0xCB80, 0xA852, 0xCB81, 0xA853, 0xCB82, 0xA854, 0xCB83, 0xA855, + 0xCB84, 0xA856, 0xCB85, 0xA857, 0xCB86, 0xA858, 0xCB87, 0xA859, 0xCB88, 0xA85A, 0xCB89, 0xA861, 0xCB8A, 0xA862, 0xCB8B, 0xA863, + 0xCB8C, 0xA864, 0xCB8D, 0xA865, 0xCB8E, 0xA866, 0xCB8F, 0xA867, 0xCB90, 0xA868, 0xCB91, 0xA869, 0xCB92, 0xA86A, 0xCB93, 0xA86B, + 0xCB94, 0xA86C, 0xCB95, 0xA86D, 0xCB96, 0xA86E, 0xCB97, 0xA86F, 0xCB98, 0xA870, 0xCB99, 0xA871, 0xCB9A, 0xA872, 0xCB9B, 0xA873, + 0xCB9C, 0xC2E8, 0xCB9D, 0xA874, 0xCB9E, 0xA875, 0xCB9F, 0xA876, 0xCBA0, 0xA877, 0xCBA1, 0xA878, 0xCBA2, 0xA879, 0xCBA3, 0xA87A, + 0xCBA4, 0xA881, 0xCBA5, 0xA882, 0xCBA6, 0xA883, 0xCBA7, 0xA884, 0xCBA8, 0xA885, 0xCBA9, 0xA886, 0xCBAA, 0xA887, 0xCBAB, 0xA888, + 0xCBAC, 0xA889, 0xCBAD, 0xA88A, 0xCBAE, 0xA88B, 0xCBAF, 0xA88C, 0xCBB0, 0xA88D, 0xCBB1, 0xA88E, 0xCBB2, 0xA88F, 0xCBB3, 0xA890, + 0xCBB4, 0xA891, 0xCBB5, 0xA892, 0xCBB6, 0xA893, 0xCBB7, 0xA894, 0xCBB8, 0xC2E9, 0xCBB9, 0xA895, 0xCBBA, 0xA896, 0xCBBB, 0xA897, + 0xCBBC, 0xA898, 0xCBBD, 0xA899, 0xCBBE, 0xA89A, 0xCBBF, 0xA89B, 0xCBC0, 0xA89C, 0xCBC1, 0xA89D, 0xCBC2, 0xA89E, 0xCBC3, 0xA89F, + 0xCBC4, 0xA8A0, 0xCBC5, 0xA941, 0xCBC6, 0xA942, 0xCBC7, 0xA943, 0xCBC8, 0xA944, 0xCBC9, 0xA945, 0xCBCA, 0xA946, 0xCBCB, 0xA947, + 0xCBCC, 0xA948, 0xCBCD, 0xA949, 0xCBCE, 0xA94A, 0xCBCF, 0xA94B, 0xCBD0, 0xA94C, 0xCBD1, 0xA94D, 0xCBD2, 0xA94E, 0xCBD3, 0xA94F, + 0xCBD4, 0xC2EA, 0xCBD5, 0xA950, 0xCBD6, 0xA951, 0xCBD7, 0xA952, 0xCBD8, 0xA953, 0xCBD9, 0xA954, 0xCBDA, 0xA955, 0xCBDB, 0xA956, + 0xCBDC, 0xA957, 0xCBDD, 0xA958, 0xCBDE, 0xA959, 0xCBDF, 0xA95A, 0xCBE0, 0xA961, 0xCBE1, 0xA962, 0xCBE2, 0xA963, 0xCBE3, 0xA964, + 0xCBE4, 0xC2EB, 0xCBE5, 0xA965, 0xCBE6, 0xA966, 0xCBE7, 0xC2EC, 0xCBE8, 0xA967, 0xCBE9, 0xC2ED, 0xCBEA, 0xA968, 0xCBEB, 0xA969, + 0xCBEC, 0xA96A, 0xCBED, 0xA96B, 0xCBEE, 0xA96C, 0xCBEF, 0xA96D, 0xCBF0, 0xA96E, 0xCBF1, 0xA96F, 0xCBF2, 0xA970, 0xCBF3, 0xA971, + 0xCBF4, 0xA972, 0xCBF5, 0xA973, 0xCBF6, 0xA974, 0xCBF7, 0xA975, 0xCBF8, 0xA976, 0xCBF9, 0xA977, 0xCBFA, 0xA978, 0xCBFB, 0xA979, + 0xCBFC, 0xA97A, 0xCBFD, 0xA981, 0xCBFE, 0xA982, 0xCBFF, 0xA983, 0xCC00, 0xA984, 0xCC01, 0xA985, 0xCC02, 0xA986, 0xCC03, 0xA987, + 0xCC04, 0xA988, 0xCC05, 0xA989, 0xCC06, 0xA98A, 0xCC07, 0xA98B, 0xCC08, 0xA98C, 0xCC09, 0xA98D, 0xCC0A, 0xA98E, 0xCC0B, 0xA98F, + 0xCC0C, 0xC2EE, 0xCC0D, 0xC2EF, 0xCC0E, 0xA990, 0xCC0F, 0xA991, 0xCC10, 0xC2F0, 0xCC11, 0xA992, 0xCC12, 0xA993, 0xCC13, 0xA994, + 0xCC14, 0xC2F1, 0xCC15, 0xA995, 0xCC16, 0xA996, 0xCC17, 0xA997, 0xCC18, 0xA998, 0xCC19, 0xA999, 0xCC1A, 0xA99A, 0xCC1B, 0xA99B, + 0xCC1C, 0xC2F2, 0xCC1D, 0xC2F3, 0xCC1E, 0xA99C, 0xCC1F, 0xA99D, 0xCC20, 0xA99E, 0xCC21, 0xC2F4, 0xCC22, 0xC2F5, 0xCC23, 0xA99F, + 0xCC24, 0xA9A0, 0xCC25, 0xAA41, 0xCC26, 0xAA42, 0xCC27, 0xC2F6, 0xCC28, 0xC2F7, 0xCC29, 0xC2F8, 0xCC2A, 0xAA43, 0xCC2B, 0xAA44, + 0xCC2C, 0xC2F9, 0xCC2D, 0xAA45, 0xCC2E, 0xC2FA, 0xCC2F, 0xAA46, 0xCC30, 0xC2FB, 0xCC31, 0xAA47, 0xCC32, 0xAA48, 0xCC33, 0xAA49, + 0xCC34, 0xAA4A, 0xCC35, 0xAA4B, 0xCC36, 0xAA4C, 0xCC37, 0xAA4D, 0xCC38, 0xC2FC, 0xCC39, 0xC2FD, 0xCC3A, 0xAA4E, 0xCC3B, 0xC2FE, + 0xCC3C, 0xC3A1, 0xCC3D, 0xC3A2, 0xCC3E, 0xC3A3, 0xCC3F, 0xAA4F, 0xCC40, 0xAA50, 0xCC41, 0xAA51, 0xCC42, 0xAA52, 0xCC43, 0xAA53, + 0xCC44, 0xC3A4, 0xCC45, 0xC3A5, 0xCC46, 0xAA54, 0xCC47, 0xAA55, 0xCC48, 0xC3A6, 0xCC49, 0xAA56, 0xCC4A, 0xAA57, 0xCC4B, 0xAA58, + 0xCC4C, 0xC3A7, 0xCC4D, 0xAA59, 0xCC4E, 0xAA5A, 0xCC4F, 0xAA61, 0xCC50, 0xAA62, 0xCC51, 0xAA63, 0xCC52, 0xAA64, 0xCC53, 0xAA65, + 0xCC54, 0xC3A8, 0xCC55, 0xC3A9, 0xCC56, 0xAA66, 0xCC57, 0xC3AA, 0xCC58, 0xC3AB, 0xCC59, 0xC3AC, 0xCC5A, 0xAA67, 0xCC5B, 0xAA68, + 0xCC5C, 0xAA69, 0xCC5D, 0xAA6A, 0xCC5E, 0xAA6B, 0xCC5F, 0xAA6C, 0xCC60, 0xC3AD, 0xCC61, 0xAA6D, 0xCC62, 0xAA6E, 0xCC63, 0xAA6F, + 0xCC64, 0xC3AE, 0xCC65, 0xAA70, 0xCC66, 0xC3AF, 0xCC67, 0xAA71, 0xCC68, 0xC3B0, 0xCC69, 0xAA72, 0xCC6A, 0xAA73, 0xCC6B, 0xAA74, + 0xCC6C, 0xAA75, 0xCC6D, 0xAA76, 0xCC6E, 0xAA77, 0xCC6F, 0xAA78, 0xCC70, 0xC3B1, 0xCC71, 0xAA79, 0xCC72, 0xAA7A, 0xCC73, 0xAA81, + 0xCC74, 0xAA82, 0xCC75, 0xC3B2, 0xCC76, 0xAA83, 0xCC77, 0xAA84, 0xCC78, 0xAA85, 0xCC79, 0xAA86, 0xCC7A, 0xAA87, 0xCC7B, 0xAA88, + 0xCC7C, 0xAA89, 0xCC7D, 0xAA8A, 0xCC7E, 0xAA8B, 0xCC7F, 0xAA8C, 0xCC80, 0xAA8D, 0xCC81, 0xAA8E, 0xCC82, 0xAA8F, 0xCC83, 0xAA90, + 0xCC84, 0xAA91, 0xCC85, 0xAA92, 0xCC86, 0xAA93, 0xCC87, 0xAA94, 0xCC88, 0xAA95, 0xCC89, 0xAA96, 0xCC8A, 0xAA97, 0xCC8B, 0xAA98, + 0xCC8C, 0xAA99, 0xCC8D, 0xAA9A, 0xCC8E, 0xAA9B, 0xCC8F, 0xAA9C, 0xCC90, 0xAA9D, 0xCC91, 0xAA9E, 0xCC92, 0xAA9F, 0xCC93, 0xAAA0, + 0xCC94, 0xAB41, 0xCC95, 0xAB42, 0xCC96, 0xAB43, 0xCC97, 0xAB44, 0xCC98, 0xC3B3, 0xCC99, 0xC3B4, 0xCC9A, 0xAB45, 0xCC9B, 0xAB46, + 0xCC9C, 0xC3B5, 0xCC9D, 0xAB47, 0xCC9E, 0xAB48, 0xCC9F, 0xAB49, 0xCCA0, 0xC3B6, 0xCCA1, 0xAB4A, 0xCCA2, 0xAB4B, 0xCCA3, 0xAB4C, + 0xCCA4, 0xAB4D, 0xCCA5, 0xAB4E, 0xCCA6, 0xAB4F, 0xCCA7, 0xAB50, 0xCCA8, 0xC3B7, 0xCCA9, 0xC3B8, 0xCCAA, 0xAB51, 0xCCAB, 0xC3B9, + 0xCCAC, 0xC3BA, 0xCCAD, 0xC3BB, 0xCCAE, 0xAB52, 0xCCAF, 0xAB53, 0xCCB0, 0xAB54, 0xCCB1, 0xAB55, 0xCCB2, 0xAB56, 0xCCB3, 0xAB57, + 0xCCB4, 0xC3BC, 0xCCB5, 0xC3BD, 0xCCB6, 0xAB58, 0xCCB7, 0xAB59, 0xCCB8, 0xC3BE, 0xCCB9, 0xAB5A, 0xCCBA, 0xAB61, 0xCCBB, 0xAB62, + 0xCCBC, 0xC3BF, 0xCCBD, 0xAB63, 0xCCBE, 0xAB64, 0xCCBF, 0xAB65, 0xCCC0, 0xAB66, 0xCCC1, 0xAB67, 0xCCC2, 0xAB68, 0xCCC3, 0xAB69, + 0xCCC4, 0xC3C0, 0xCCC5, 0xC3C1, 0xCCC6, 0xAB6A, 0xCCC7, 0xC3C2, 0xCCC8, 0xAB6B, 0xCCC9, 0xC3C3, 0xCCCA, 0xAB6C, 0xCCCB, 0xAB6D, + 0xCCCC, 0xAB6E, 0xCCCD, 0xAB6F, 0xCCCE, 0xAB70, 0xCCCF, 0xAB71, 0xCCD0, 0xC3C4, 0xCCD1, 0xAB72, 0xCCD2, 0xAB73, 0xCCD3, 0xAB74, + 0xCCD4, 0xC3C5, 0xCCD5, 0xAB75, 0xCCD6, 0xAB76, 0xCCD7, 0xAB77, 0xCCD8, 0xAB78, 0xCCD9, 0xAB79, 0xCCDA, 0xAB7A, 0xCCDB, 0xAB81, + 0xCCDC, 0xAB82, 0xCCDD, 0xAB83, 0xCCDE, 0xAB84, 0xCCDF, 0xAB85, 0xCCE0, 0xAB86, 0xCCE1, 0xAB87, 0xCCE2, 0xAB88, 0xCCE3, 0xAB89, + 0xCCE4, 0xC3C6, 0xCCE5, 0xAB8A, 0xCCE6, 0xAB8B, 0xCCE7, 0xAB8C, 0xCCE8, 0xAB8D, 0xCCE9, 0xAB8E, 0xCCEA, 0xAB8F, 0xCCEB, 0xAB90, + 0xCCEC, 0xC3C7, 0xCCED, 0xAB91, 0xCCEE, 0xAB92, 0xCCEF, 0xAB93, 0xCCF0, 0xC3C8, 0xCCF1, 0xAB94, 0xCCF2, 0xAB95, 0xCCF3, 0xAB96, + 0xCCF4, 0xAB97, 0xCCF5, 0xAB98, 0xCCF6, 0xAB99, 0xCCF7, 0xAB9A, 0xCCF8, 0xAB9B, 0xCCF9, 0xAB9C, 0xCCFA, 0xAB9D, 0xCCFB, 0xAB9E, + 0xCCFC, 0xAB9F, 0xCCFD, 0xABA0, 0xCCFE, 0xAC41, 0xCCFF, 0xAC42, 0xCD00, 0xAC43, 0xCD01, 0xC3C9, 0xCD02, 0xAC44, 0xCD03, 0xAC45, + 0xCD04, 0xAC46, 0xCD05, 0xAC47, 0xCD06, 0xAC48, 0xCD07, 0xAC49, 0xCD08, 0xC3CA, 0xCD09, 0xC3CB, 0xCD0A, 0xAC4A, 0xCD0B, 0xAC4B, + 0xCD0C, 0xC3CC, 0xCD0D, 0xAC4C, 0xCD0E, 0xAC4D, 0xCD0F, 0xAC4E, 0xCD10, 0xC3CD, 0xCD11, 0xAC4F, 0xCD12, 0xAC50, 0xCD13, 0xAC51, + 0xCD14, 0xAC52, 0xCD15, 0xAC53, 0xCD16, 0xAC54, 0xCD17, 0xAC55, 0xCD18, 0xC3CE, 0xCD19, 0xC3CF, 0xCD1A, 0xAC56, 0xCD1B, 0xC3D0, + 0xCD1C, 0xAC57, 0xCD1D, 0xC3D1, 0xCD1E, 0xAC58, 0xCD1F, 0xAC59, 0xCD20, 0xAC5A, 0xCD21, 0xAC61, 0xCD22, 0xAC62, 0xCD23, 0xAC63, + 0xCD24, 0xC3D2, 0xCD25, 0xAC64, 0xCD26, 0xAC65, 0xCD27, 0xAC66, 0xCD28, 0xC3D3, 0xCD29, 0xAC67, 0xCD2A, 0xAC68, 0xCD2B, 0xAC69, + 0xCD2C, 0xC3D4, 0xCD2D, 0xAC6A, 0xCD2E, 0xAC6B, 0xCD2F, 0xAC6C, 0xCD30, 0xAC6D, 0xCD31, 0xAC6E, 0xCD32, 0xAC6F, 0xCD33, 0xAC70, + 0xCD34, 0xAC71, 0xCD35, 0xAC72, 0xCD36, 0xAC73, 0xCD37, 0xAC74, 0xCD38, 0xAC75, 0xCD39, 0xC3D5, 0xCD3A, 0xAC76, 0xCD3B, 0xAC77, + 0xCD3C, 0xAC78, 0xCD3D, 0xAC79, 0xCD3E, 0xAC7A, 0xCD3F, 0xAC81, 0xCD40, 0xAC82, 0xCD41, 0xAC83, 0xCD42, 0xAC84, 0xCD43, 0xAC85, + 0xCD44, 0xAC86, 0xCD45, 0xAC87, 0xCD46, 0xAC88, 0xCD47, 0xAC89, 0xCD48, 0xAC8A, 0xCD49, 0xAC8B, 0xCD4A, 0xAC8C, 0xCD4B, 0xAC8D, + 0xCD4C, 0xAC8E, 0xCD4D, 0xAC8F, 0xCD4E, 0xAC90, 0xCD4F, 0xAC91, 0xCD50, 0xAC92, 0xCD51, 0xAC93, 0xCD52, 0xAC94, 0xCD53, 0xAC95, + 0xCD54, 0xAC96, 0xCD55, 0xAC97, 0xCD56, 0xAC98, 0xCD57, 0xAC99, 0xCD58, 0xAC9A, 0xCD59, 0xAC9B, 0xCD5A, 0xAC9C, 0xCD5B, 0xAC9D, + 0xCD5C, 0xC3D6, 0xCD5D, 0xAC9E, 0xCD5E, 0xAC9F, 0xCD5F, 0xACA0, 0xCD60, 0xC3D7, 0xCD61, 0xAD41, 0xCD62, 0xAD42, 0xCD63, 0xAD43, + 0xCD64, 0xC3D8, 0xCD65, 0xAD44, 0xCD66, 0xAD45, 0xCD67, 0xAD46, 0xCD68, 0xAD47, 0xCD69, 0xAD48, 0xCD6A, 0xAD49, 0xCD6B, 0xAD4A, + 0xCD6C, 0xC3D9, 0xCD6D, 0xC3DA, 0xCD6E, 0xAD4B, 0xCD6F, 0xC3DB, 0xCD70, 0xAD4C, 0xCD71, 0xC3DC, 0xCD72, 0xAD4D, 0xCD73, 0xAD4E, + 0xCD74, 0xAD4F, 0xCD75, 0xAD50, 0xCD76, 0xAD51, 0xCD77, 0xAD52, 0xCD78, 0xC3DD, 0xCD79, 0xAD53, 0xCD7A, 0xAD54, 0xCD7B, 0xAD55, + 0xCD7C, 0xAD56, 0xCD7D, 0xAD57, 0xCD7E, 0xAD58, 0xCD7F, 0xAD59, 0xCD80, 0xAD5A, 0xCD81, 0xAD61, 0xCD82, 0xAD62, 0xCD83, 0xAD63, + 0xCD84, 0xAD64, 0xCD85, 0xAD65, 0xCD86, 0xAD66, 0xCD87, 0xAD67, 0xCD88, 0xC3DE, 0xCD89, 0xAD68, 0xCD8A, 0xAD69, 0xCD8B, 0xAD6A, + 0xCD8C, 0xAD6B, 0xCD8D, 0xAD6C, 0xCD8E, 0xAD6D, 0xCD8F, 0xAD6E, 0xCD90, 0xAD6F, 0xCD91, 0xAD70, 0xCD92, 0xAD71, 0xCD93, 0xAD72, + 0xCD94, 0xC3DF, 0xCD95, 0xC3E0, 0xCD96, 0xAD73, 0xCD97, 0xAD74, 0xCD98, 0xC3E1, 0xCD99, 0xAD75, 0xCD9A, 0xAD76, 0xCD9B, 0xAD77, + 0xCD9C, 0xC3E2, 0xCD9D, 0xAD78, 0xCD9E, 0xAD79, 0xCD9F, 0xAD7A, 0xCDA0, 0xAD81, 0xCDA1, 0xAD82, 0xCDA2, 0xAD83, 0xCDA3, 0xAD84, + 0xCDA4, 0xC3E3, 0xCDA5, 0xC3E4, 0xCDA6, 0xAD85, 0xCDA7, 0xC3E5, 0xCDA8, 0xAD86, 0xCDA9, 0xC3E6, 0xCDAA, 0xAD87, 0xCDAB, 0xAD88, + 0xCDAC, 0xAD89, 0xCDAD, 0xAD8A, 0xCDAE, 0xAD8B, 0xCDAF, 0xAD8C, 0xCDB0, 0xC3E7, 0xCDB1, 0xAD8D, 0xCDB2, 0xAD8E, 0xCDB3, 0xAD8F, + 0xCDB4, 0xAD90, 0xCDB5, 0xAD91, 0xCDB6, 0xAD92, 0xCDB7, 0xAD93, 0xCDB8, 0xAD94, 0xCDB9, 0xAD95, 0xCDBA, 0xAD96, 0xCDBB, 0xAD97, + 0xCDBC, 0xAD98, 0xCDBD, 0xAD99, 0xCDBE, 0xAD9A, 0xCDBF, 0xAD9B, 0xCDC0, 0xAD9C, 0xCDC1, 0xAD9D, 0xCDC2, 0xAD9E, 0xCDC3, 0xAD9F, + 0xCDC4, 0xC3E8, 0xCDC5, 0xADA0, 0xCDC6, 0xAE41, 0xCDC7, 0xAE42, 0xCDC8, 0xAE43, 0xCDC9, 0xAE44, 0xCDCA, 0xAE45, 0xCDCB, 0xAE46, + 0xCDCC, 0xC3E9, 0xCDCD, 0xAE47, 0xCDCE, 0xAE48, 0xCDCF, 0xAE49, 0xCDD0, 0xC3EA, 0xCDD1, 0xAE4A, 0xCDD2, 0xAE4B, 0xCDD3, 0xAE4C, + 0xCDD4, 0xAE4D, 0xCDD5, 0xAE4E, 0xCDD6, 0xAE4F, 0xCDD7, 0xAE50, 0xCDD8, 0xAE51, 0xCDD9, 0xAE52, 0xCDDA, 0xAE53, 0xCDDB, 0xAE54, + 0xCDDC, 0xAE55, 0xCDDD, 0xAE56, 0xCDDE, 0xAE57, 0xCDDF, 0xAE58, 0xCDE0, 0xAE59, 0xCDE1, 0xAE5A, 0xCDE2, 0xAE61, 0xCDE3, 0xAE62, + 0xCDE4, 0xAE63, 0xCDE5, 0xAE64, 0xCDE6, 0xAE65, 0xCDE7, 0xAE66, 0xCDE8, 0xC3EB, 0xCDE9, 0xAE67, 0xCDEA, 0xAE68, 0xCDEB, 0xAE69, + 0xCDEC, 0xC3EC, 0xCDED, 0xAE6A, 0xCDEE, 0xAE6B, 0xCDEF, 0xAE6C, 0xCDF0, 0xC3ED, 0xCDF1, 0xAE6D, 0xCDF2, 0xAE6E, 0xCDF3, 0xAE6F, + 0xCDF4, 0xAE70, 0xCDF5, 0xAE71, 0xCDF6, 0xAE72, 0xCDF7, 0xAE73, 0xCDF8, 0xC3EE, 0xCDF9, 0xC3EF, 0xCDFA, 0xAE74, 0xCDFB, 0xC3F0, + 0xCDFC, 0xAE75, 0xCDFD, 0xC3F1, 0xCDFE, 0xAE76, 0xCDFF, 0xAE77, 0xCE00, 0xAE78, 0xCE01, 0xAE79, 0xCE02, 0xAE7A, 0xCE03, 0xAE81, + 0xCE04, 0xC3F2, 0xCE05, 0xAE82, 0xCE06, 0xAE83, 0xCE07, 0xAE84, 0xCE08, 0xC3F3, 0xCE09, 0xAE85, 0xCE0A, 0xAE86, 0xCE0B, 0xAE87, + 0xCE0C, 0xC3F4, 0xCE0D, 0xAE88, 0xCE0E, 0xAE89, 0xCE0F, 0xAE8A, 0xCE10, 0xAE8B, 0xCE11, 0xAE8C, 0xCE12, 0xAE8D, 0xCE13, 0xAE8E, + 0xCE14, 0xC3F5, 0xCE15, 0xAE8F, 0xCE16, 0xAE90, 0xCE17, 0xAE91, 0xCE18, 0xAE92, 0xCE19, 0xC3F6, 0xCE1A, 0xAE93, 0xCE1B, 0xAE94, + 0xCE1C, 0xAE95, 0xCE1D, 0xAE96, 0xCE1E, 0xAE97, 0xCE1F, 0xAE98, 0xCE20, 0xC3F7, 0xCE21, 0xC3F8, 0xCE22, 0xAE99, 0xCE23, 0xAE9A, + 0xCE24, 0xC3F9, 0xCE25, 0xAE9B, 0xCE26, 0xAE9C, 0xCE27, 0xAE9D, 0xCE28, 0xC3FA, 0xCE29, 0xAE9E, 0xCE2A, 0xAE9F, 0xCE2B, 0xAEA0, + 0xCE2C, 0xAF41, 0xCE2D, 0xAF42, 0xCE2E, 0xAF43, 0xCE2F, 0xAF44, 0xCE30, 0xC3FB, 0xCE31, 0xC3FC, 0xCE32, 0xAF45, 0xCE33, 0xC3FD, + 0xCE34, 0xAF46, 0xCE35, 0xC3FE, 0xCE36, 0xAF47, 0xCE37, 0xAF48, 0xCE38, 0xAF49, 0xCE39, 0xAF4A, 0xCE3A, 0xAF4B, 0xCE3B, 0xAF4C, + 0xCE3C, 0xAF4D, 0xCE3D, 0xAF4E, 0xCE3E, 0xAF4F, 0xCE3F, 0xAF50, 0xCE40, 0xAF51, 0xCE41, 0xAF52, 0xCE42, 0xAF53, 0xCE43, 0xAF54, + 0xCE44, 0xAF55, 0xCE45, 0xAF56, 0xCE46, 0xAF57, 0xCE47, 0xAF58, 0xCE48, 0xAF59, 0xCE49, 0xAF5A, 0xCE4A, 0xAF61, 0xCE4B, 0xAF62, + 0xCE4C, 0xAF63, 0xCE4D, 0xAF64, 0xCE4E, 0xAF65, 0xCE4F, 0xAF66, 0xCE50, 0xAF67, 0xCE51, 0xAF68, 0xCE52, 0xAF69, 0xCE53, 0xAF6A, + 0xCE54, 0xAF6B, 0xCE55, 0xAF6C, 0xCE56, 0xAF6D, 0xCE57, 0xAF6E, 0xCE58, 0xC4A1, 0xCE59, 0xC4A2, 0xCE5A, 0xAF6F, 0xCE5B, 0xAF70, + 0xCE5C, 0xC4A3, 0xCE5D, 0xAF71, 0xCE5E, 0xAF72, 0xCE5F, 0xC4A4, 0xCE60, 0xC4A5, 0xCE61, 0xC4A6, 0xCE62, 0xAF73, 0xCE63, 0xAF74, + 0xCE64, 0xAF75, 0xCE65, 0xAF76, 0xCE66, 0xAF77, 0xCE67, 0xAF78, 0xCE68, 0xC4A7, 0xCE69, 0xC4A8, 0xCE6A, 0xAF79, 0xCE6B, 0xC4A9, + 0xCE6C, 0xAF7A, 0xCE6D, 0xC4AA, 0xCE6E, 0xAF81, 0xCE6F, 0xAF82, 0xCE70, 0xAF83, 0xCE71, 0xAF84, 0xCE72, 0xAF85, 0xCE73, 0xAF86, + 0xCE74, 0xC4AB, 0xCE75, 0xC4AC, 0xCE76, 0xAF87, 0xCE77, 0xAF88, 0xCE78, 0xC4AD, 0xCE79, 0xAF89, 0xCE7A, 0xAF8A, 0xCE7B, 0xAF8B, + 0xCE7C, 0xC4AE, 0xCE7D, 0xAF8C, 0xCE7E, 0xAF8D, 0xCE7F, 0xAF8E, 0xCE80, 0xAF8F, 0xCE81, 0xAF90, 0xCE82, 0xAF91, 0xCE83, 0xAF92, + 0xCE84, 0xC4AF, 0xCE85, 0xC4B0, 0xCE86, 0xAF93, 0xCE87, 0xC4B1, 0xCE88, 0xAF94, 0xCE89, 0xC4B2, 0xCE8A, 0xAF95, 0xCE8B, 0xAF96, + 0xCE8C, 0xAF97, 0xCE8D, 0xAF98, 0xCE8E, 0xAF99, 0xCE8F, 0xAF9A, 0xCE90, 0xC4B3, 0xCE91, 0xC4B4, 0xCE92, 0xAF9B, 0xCE93, 0xAF9C, + 0xCE94, 0xC4B5, 0xCE95, 0xAF9D, 0xCE96, 0xAF9E, 0xCE97, 0xAF9F, 0xCE98, 0xC4B6, 0xCE99, 0xAFA0, 0xCE9A, 0xB041, 0xCE9B, 0xB042, + 0xCE9C, 0xB043, 0xCE9D, 0xB044, 0xCE9E, 0xB045, 0xCE9F, 0xB046, 0xCEA0, 0xC4B7, 0xCEA1, 0xC4B8, 0xCEA2, 0xB047, 0xCEA3, 0xC4B9, + 0xCEA4, 0xC4BA, 0xCEA5, 0xC4BB, 0xCEA6, 0xB048, 0xCEA7, 0xB049, 0xCEA8, 0xB04A, 0xCEA9, 0xB04B, 0xCEAA, 0xB04C, 0xCEAB, 0xB04D, + 0xCEAC, 0xC4BC, 0xCEAD, 0xC4BD, 0xCEAE, 0xB04E, 0xCEAF, 0xB04F, 0xCEB0, 0xB050, 0xCEB1, 0xB051, 0xCEB2, 0xB052, 0xCEB3, 0xB053, + 0xCEB4, 0xB054, 0xCEB5, 0xB055, 0xCEB6, 0xB056, 0xCEB7, 0xB057, 0xCEB8, 0xB058, 0xCEB9, 0xB059, 0xCEBA, 0xB05A, 0xCEBB, 0xB061, + 0xCEBC, 0xB062, 0xCEBD, 0xB063, 0xCEBE, 0xB064, 0xCEBF, 0xB065, 0xCEC0, 0xB066, 0xCEC1, 0xC4BE, 0xCEC2, 0xB067, 0xCEC3, 0xB068, + 0xCEC4, 0xB069, 0xCEC5, 0xB06A, 0xCEC6, 0xB06B, 0xCEC7, 0xB06C, 0xCEC8, 0xB06D, 0xCEC9, 0xB06E, 0xCECA, 0xB06F, 0xCECB, 0xB070, + 0xCECC, 0xB071, 0xCECD, 0xB072, 0xCECE, 0xB073, 0xCECF, 0xB074, 0xCED0, 0xB075, 0xCED1, 0xB076, 0xCED2, 0xB077, 0xCED3, 0xB078, + 0xCED4, 0xB079, 0xCED5, 0xB07A, 0xCED6, 0xB081, 0xCED7, 0xB082, 0xCED8, 0xB083, 0xCED9, 0xB084, 0xCEDA, 0xB085, 0xCEDB, 0xB086, + 0xCEDC, 0xB087, 0xCEDD, 0xB088, 0xCEDE, 0xB089, 0xCEDF, 0xB08A, 0xCEE0, 0xB08B, 0xCEE1, 0xB08C, 0xCEE2, 0xB08D, 0xCEE3, 0xB08E, + 0xCEE4, 0xC4BF, 0xCEE5, 0xC4C0, 0xCEE6, 0xB08F, 0xCEE7, 0xB090, 0xCEE8, 0xC4C1, 0xCEE9, 0xB091, 0xCEEA, 0xB092, 0xCEEB, 0xC4C2, + 0xCEEC, 0xC4C3, 0xCEED, 0xB093, 0xCEEE, 0xB094, 0xCEEF, 0xB095, 0xCEF0, 0xB096, 0xCEF1, 0xB097, 0xCEF2, 0xB098, 0xCEF3, 0xB099, + 0xCEF4, 0xC4C4, 0xCEF5, 0xC4C5, 0xCEF6, 0xB09A, 0xCEF7, 0xC4C6, 0xCEF8, 0xC4C7, 0xCEF9, 0xC4C8, 0xCEFA, 0xB09B, 0xCEFB, 0xB09C, + 0xCEFC, 0xB09D, 0xCEFD, 0xB09E, 0xCEFE, 0xB09F, 0xCEFF, 0xB0A0, 0xCF00, 0xC4C9, 0xCF01, 0xC4CA, 0xCF02, 0xB141, 0xCF03, 0xB142, + 0xCF04, 0xC4CB, 0xCF05, 0xB143, 0xCF06, 0xB144, 0xCF07, 0xB145, 0xCF08, 0xC4CC, 0xCF09, 0xB146, 0xCF0A, 0xB147, 0xCF0B, 0xB148, + 0xCF0C, 0xB149, 0xCF0D, 0xB14A, 0xCF0E, 0xB14B, 0xCF0F, 0xB14C, 0xCF10, 0xC4CD, 0xCF11, 0xC4CE, 0xCF12, 0xB14D, 0xCF13, 0xC4CF, + 0xCF14, 0xB14E, 0xCF15, 0xC4D0, 0xCF16, 0xB14F, 0xCF17, 0xB150, 0xCF18, 0xB151, 0xCF19, 0xB152, 0xCF1A, 0xB153, 0xCF1B, 0xB154, + 0xCF1C, 0xC4D1, 0xCF1D, 0xB155, 0xCF1E, 0xB156, 0xCF1F, 0xB157, 0xCF20, 0xC4D2, 0xCF21, 0xB158, 0xCF22, 0xB159, 0xCF23, 0xB15A, + 0xCF24, 0xC4D3, 0xCF25, 0xB161, 0xCF26, 0xB162, 0xCF27, 0xB163, 0xCF28, 0xB164, 0xCF29, 0xB165, 0xCF2A, 0xB166, 0xCF2B, 0xB167, + 0xCF2C, 0xC4D4, 0xCF2D, 0xC4D5, 0xCF2E, 0xB168, 0xCF2F, 0xC4D6, 0xCF30, 0xC4D7, 0xCF31, 0xC4D8, 0xCF32, 0xB169, 0xCF33, 0xB16A, + 0xCF34, 0xB16B, 0xCF35, 0xB16C, 0xCF36, 0xB16D, 0xCF37, 0xB16E, 0xCF38, 0xC4D9, 0xCF39, 0xB16F, 0xCF3A, 0xB170, 0xCF3B, 0xB171, + 0xCF3C, 0xB172, 0xCF3D, 0xB173, 0xCF3E, 0xB174, 0xCF3F, 0xB175, 0xCF40, 0xB176, 0xCF41, 0xB177, 0xCF42, 0xB178, 0xCF43, 0xB179, + 0xCF44, 0xB17A, 0xCF45, 0xB181, 0xCF46, 0xB182, 0xCF47, 0xB183, 0xCF48, 0xB184, 0xCF49, 0xB185, 0xCF4A, 0xB186, 0xCF4B, 0xB187, + 0xCF4C, 0xB188, 0xCF4D, 0xB189, 0xCF4E, 0xB18A, 0xCF4F, 0xB18B, 0xCF50, 0xB18C, 0xCF51, 0xB18D, 0xCF52, 0xB18E, 0xCF53, 0xB18F, + 0xCF54, 0xC4DA, 0xCF55, 0xC4DB, 0xCF56, 0xB190, 0xCF57, 0xB191, 0xCF58, 0xC4DC, 0xCF59, 0xB192, 0xCF5A, 0xB193, 0xCF5B, 0xB194, + 0xCF5C, 0xC4DD, 0xCF5D, 0xB195, 0xCF5E, 0xB196, 0xCF5F, 0xB197, 0xCF60, 0xB198, 0xCF61, 0xB199, 0xCF62, 0xB19A, 0xCF63, 0xB19B, + 0xCF64, 0xC4DE, 0xCF65, 0xC4DF, 0xCF66, 0xB19C, 0xCF67, 0xC4E0, 0xCF68, 0xB19D, 0xCF69, 0xC4E1, 0xCF6A, 0xB19E, 0xCF6B, 0xB19F, + 0xCF6C, 0xB1A0, 0xCF6D, 0xB241, 0xCF6E, 0xB242, 0xCF6F, 0xB243, 0xCF70, 0xC4E2, 0xCF71, 0xC4E3, 0xCF72, 0xB244, 0xCF73, 0xB245, + 0xCF74, 0xC4E4, 0xCF75, 0xB246, 0xCF76, 0xB247, 0xCF77, 0xB248, 0xCF78, 0xC4E5, 0xCF79, 0xB249, 0xCF7A, 0xB24A, 0xCF7B, 0xB24B, + 0xCF7C, 0xB24C, 0xCF7D, 0xB24D, 0xCF7E, 0xB24E, 0xCF7F, 0xB24F, 0xCF80, 0xC4E6, 0xCF81, 0xB250, 0xCF82, 0xB251, 0xCF83, 0xB252, + 0xCF84, 0xB253, 0xCF85, 0xC4E7, 0xCF86, 0xB254, 0xCF87, 0xB255, 0xCF88, 0xB256, 0xCF89, 0xB257, 0xCF8A, 0xB258, 0xCF8B, 0xB259, + 0xCF8C, 0xC4E8, 0xCF8D, 0xB25A, 0xCF8E, 0xB261, 0xCF8F, 0xB262, 0xCF90, 0xB263, 0xCF91, 0xB264, 0xCF92, 0xB265, 0xCF93, 0xB266, + 0xCF94, 0xB267, 0xCF95, 0xB268, 0xCF96, 0xB269, 0xCF97, 0xB26A, 0xCF98, 0xB26B, 0xCF99, 0xB26C, 0xCF9A, 0xB26D, 0xCF9B, 0xB26E, + 0xCF9C, 0xB26F, 0xCF9D, 0xB270, 0xCF9E, 0xB271, 0xCF9F, 0xB272, 0xCFA0, 0xB273, 0xCFA1, 0xC4E9, 0xCFA2, 0xB274, 0xCFA3, 0xB275, + 0xCFA4, 0xB276, 0xCFA5, 0xB277, 0xCFA6, 0xB278, 0xCFA7, 0xB279, 0xCFA8, 0xC4EA, 0xCFA9, 0xB27A, 0xCFAA, 0xB281, 0xCFAB, 0xB282, + 0xCFAC, 0xB283, 0xCFAD, 0xB284, 0xCFAE, 0xB285, 0xCFAF, 0xB286, 0xCFB0, 0xC4EB, 0xCFB1, 0xB287, 0xCFB2, 0xB288, 0xCFB3, 0xB289, + 0xCFB4, 0xB28A, 0xCFB5, 0xB28B, 0xCFB6, 0xB28C, 0xCFB7, 0xB28D, 0xCFB8, 0xB28E, 0xCFB9, 0xB28F, 0xCFBA, 0xB290, 0xCFBB, 0xB291, + 0xCFBC, 0xB292, 0xCFBD, 0xB293, 0xCFBE, 0xB294, 0xCFBF, 0xB295, 0xCFC0, 0xB296, 0xCFC1, 0xB297, 0xCFC2, 0xB298, 0xCFC3, 0xB299, + 0xCFC4, 0xC4EC, 0xCFC5, 0xB29A, 0xCFC6, 0xB29B, 0xCFC7, 0xB29C, 0xCFC8, 0xB29D, 0xCFC9, 0xB29E, 0xCFCA, 0xB29F, 0xCFCB, 0xB2A0, + 0xCFCC, 0xB341, 0xCFCD, 0xB342, 0xCFCE, 0xB343, 0xCFCF, 0xB344, 0xCFD0, 0xB345, 0xCFD1, 0xB346, 0xCFD2, 0xB347, 0xCFD3, 0xB348, + 0xCFD4, 0xB349, 0xCFD5, 0xB34A, 0xCFD6, 0xB34B, 0xCFD7, 0xB34C, 0xCFD8, 0xB34D, 0xCFD9, 0xB34E, 0xCFDA, 0xB34F, 0xCFDB, 0xB350, + 0xCFDC, 0xB351, 0xCFDD, 0xB352, 0xCFDE, 0xB353, 0xCFDF, 0xB354, 0xCFE0, 0xC4ED, 0xCFE1, 0xC4EE, 0xCFE2, 0xB355, 0xCFE3, 0xB356, + 0xCFE4, 0xC4EF, 0xCFE5, 0xB357, 0xCFE6, 0xB358, 0xCFE7, 0xB359, 0xCFE8, 0xC4F0, 0xCFE9, 0xB35A, 0xCFEA, 0xB361, 0xCFEB, 0xB362, + 0xCFEC, 0xB363, 0xCFED, 0xB364, 0xCFEE, 0xB365, 0xCFEF, 0xB366, 0xCFF0, 0xC4F1, 0xCFF1, 0xC4F2, 0xCFF2, 0xB367, 0xCFF3, 0xC4F3, + 0xCFF4, 0xB368, 0xCFF5, 0xC4F4, 0xCFF6, 0xB369, 0xCFF7, 0xB36A, 0xCFF8, 0xB36B, 0xCFF9, 0xB36C, 0xCFFA, 0xB36D, 0xCFFB, 0xB36E, + 0xCFFC, 0xC4F5, 0xCFFD, 0xB36F, 0xCFFE, 0xB370, 0xCFFF, 0xB371, 0xD000, 0xC4F6, 0xD001, 0xB372, 0xD002, 0xB373, 0xD003, 0xB374, + 0xD004, 0xC4F7, 0xD005, 0xB375, 0xD006, 0xB376, 0xD007, 0xB377, 0xD008, 0xB378, 0xD009, 0xB379, 0xD00A, 0xB37A, 0xD00B, 0xB381, + 0xD00C, 0xB382, 0xD00D, 0xB383, 0xD00E, 0xB384, 0xD00F, 0xB385, 0xD010, 0xB386, 0xD011, 0xC4F8, 0xD012, 0xB387, 0xD013, 0xB388, + 0xD014, 0xB389, 0xD015, 0xB38A, 0xD016, 0xB38B, 0xD017, 0xB38C, 0xD018, 0xC4F9, 0xD019, 0xB38D, 0xD01A, 0xB38E, 0xD01B, 0xB38F, + 0xD01C, 0xB390, 0xD01D, 0xB391, 0xD01E, 0xB392, 0xD01F, 0xB393, 0xD020, 0xB394, 0xD021, 0xB395, 0xD022, 0xB396, 0xD023, 0xB397, + 0xD024, 0xB398, 0xD025, 0xB399, 0xD026, 0xB39A, 0xD027, 0xB39B, 0xD028, 0xB39C, 0xD029, 0xB39D, 0xD02A, 0xB39E, 0xD02B, 0xB39F, + 0xD02C, 0xB3A0, 0xD02D, 0xC4FA, 0xD02E, 0xB441, 0xD02F, 0xB442, 0xD030, 0xB443, 0xD031, 0xB444, 0xD032, 0xB445, 0xD033, 0xB446, + 0xD034, 0xC4FB, 0xD035, 0xC4FC, 0xD036, 0xB447, 0xD037, 0xB448, 0xD038, 0xC4FD, 0xD039, 0xB449, 0xD03A, 0xB44A, 0xD03B, 0xB44B, + 0xD03C, 0xC4FE, 0xD03D, 0xB44C, 0xD03E, 0xB44D, 0xD03F, 0xB44E, 0xD040, 0xB44F, 0xD041, 0xB450, 0xD042, 0xB451, 0xD043, 0xB452, + 0xD044, 0xC5A1, 0xD045, 0xC5A2, 0xD046, 0xB453, 0xD047, 0xC5A3, 0xD048, 0xB454, 0xD049, 0xC5A4, 0xD04A, 0xB455, 0xD04B, 0xB456, + 0xD04C, 0xB457, 0xD04D, 0xB458, 0xD04E, 0xB459, 0xD04F, 0xB45A, 0xD050, 0xC5A5, 0xD051, 0xB461, 0xD052, 0xB462, 0xD053, 0xB463, + 0xD054, 0xC5A6, 0xD055, 0xB464, 0xD056, 0xB465, 0xD057, 0xB466, 0xD058, 0xC5A7, 0xD059, 0xB467, 0xD05A, 0xB468, 0xD05B, 0xB469, + 0xD05C, 0xB46A, 0xD05D, 0xB46B, 0xD05E, 0xB46C, 0xD05F, 0xB46D, 0xD060, 0xC5A8, 0xD061, 0xB46E, 0xD062, 0xB46F, 0xD063, 0xB470, + 0xD064, 0xB471, 0xD065, 0xB472, 0xD066, 0xB473, 0xD067, 0xB474, 0xD068, 0xB475, 0xD069, 0xB476, 0xD06A, 0xB477, 0xD06B, 0xB478, + 0xD06C, 0xC5A9, 0xD06D, 0xC5AA, 0xD06E, 0xB479, 0xD06F, 0xB47A, 0xD070, 0xC5AB, 0xD071, 0xB481, 0xD072, 0xB482, 0xD073, 0xB483, + 0xD074, 0xC5AC, 0xD075, 0xB484, 0xD076, 0xB485, 0xD077, 0xB486, 0xD078, 0xB487, 0xD079, 0xB488, 0xD07A, 0xB489, 0xD07B, 0xB48A, + 0xD07C, 0xC5AD, 0xD07D, 0xC5AE, 0xD07E, 0xB48B, 0xD07F, 0xB48C, 0xD080, 0xB48D, 0xD081, 0xC5AF, 0xD082, 0xB48E, 0xD083, 0xB48F, + 0xD084, 0xB490, 0xD085, 0xB491, 0xD086, 0xB492, 0xD087, 0xB493, 0xD088, 0xB494, 0xD089, 0xB495, 0xD08A, 0xB496, 0xD08B, 0xB497, + 0xD08C, 0xB498, 0xD08D, 0xB499, 0xD08E, 0xB49A, 0xD08F, 0xB49B, 0xD090, 0xB49C, 0xD091, 0xB49D, 0xD092, 0xB49E, 0xD093, 0xB49F, + 0xD094, 0xB4A0, 0xD095, 0xB541, 0xD096, 0xB542, 0xD097, 0xB543, 0xD098, 0xB544, 0xD099, 0xB545, 0xD09A, 0xB546, 0xD09B, 0xB547, + 0xD09C, 0xB548, 0xD09D, 0xB549, 0xD09E, 0xB54A, 0xD09F, 0xB54B, 0xD0A0, 0xB54C, 0xD0A1, 0xB54D, 0xD0A2, 0xB54E, 0xD0A3, 0xB54F, + 0xD0A4, 0xC5B0, 0xD0A5, 0xC5B1, 0xD0A6, 0xB550, 0xD0A7, 0xB551, 0xD0A8, 0xC5B2, 0xD0A9, 0xB552, 0xD0AA, 0xB553, 0xD0AB, 0xB554, + 0xD0AC, 0xC5B3, 0xD0AD, 0xB555, 0xD0AE, 0xB556, 0xD0AF, 0xB557, 0xD0B0, 0xB558, 0xD0B1, 0xB559, 0xD0B2, 0xB55A, 0xD0B3, 0xB561, + 0xD0B4, 0xC5B4, 0xD0B5, 0xC5B5, 0xD0B6, 0xB562, 0xD0B7, 0xC5B6, 0xD0B8, 0xB563, 0xD0B9, 0xC5B7, 0xD0BA, 0xB564, 0xD0BB, 0xB565, + 0xD0BC, 0xB566, 0xD0BD, 0xB567, 0xD0BE, 0xB568, 0xD0BF, 0xB569, 0xD0C0, 0xC5B8, 0xD0C1, 0xC5B9, 0xD0C2, 0xB56A, 0xD0C3, 0xB56B, + 0xD0C4, 0xC5BA, 0xD0C5, 0xB56C, 0xD0C6, 0xB56D, 0xD0C7, 0xB56E, 0xD0C8, 0xC5BB, 0xD0C9, 0xC5BC, 0xD0CA, 0xB56F, 0xD0CB, 0xB570, + 0xD0CC, 0xB571, 0xD0CD, 0xB572, 0xD0CE, 0xB573, 0xD0CF, 0xB574, 0xD0D0, 0xC5BD, 0xD0D1, 0xC5BE, 0xD0D2, 0xB575, 0xD0D3, 0xC5BF, + 0xD0D4, 0xC5C0, 0xD0D5, 0xC5C1, 0xD0D6, 0xB576, 0xD0D7, 0xB577, 0xD0D8, 0xB578, 0xD0D9, 0xB579, 0xD0DA, 0xB57A, 0xD0DB, 0xB581, + 0xD0DC, 0xC5C2, 0xD0DD, 0xC5C3, 0xD0DE, 0xB582, 0xD0DF, 0xB583, 0xD0E0, 0xC5C4, 0xD0E1, 0xB584, 0xD0E2, 0xB585, 0xD0E3, 0xB586, + 0xD0E4, 0xC5C5, 0xD0E5, 0xB587, 0xD0E6, 0xB588, 0xD0E7, 0xB589, 0xD0E8, 0xB58A, 0xD0E9, 0xB58B, 0xD0EA, 0xB58C, 0xD0EB, 0xB58D, + 0xD0EC, 0xC5C6, 0xD0ED, 0xC5C7, 0xD0EE, 0xB58E, 0xD0EF, 0xC5C8, 0xD0F0, 0xC5C9, 0xD0F1, 0xC5CA, 0xD0F2, 0xB58F, 0xD0F3, 0xB590, + 0xD0F4, 0xB591, 0xD0F5, 0xB592, 0xD0F6, 0xB593, 0xD0F7, 0xB594, 0xD0F8, 0xC5CB, 0xD0F9, 0xB595, 0xD0FA, 0xB596, 0xD0FB, 0xB597, + 0xD0FC, 0xB598, 0xD0FD, 0xB599, 0xD0FE, 0xB59A, 0xD0FF, 0xB59B, 0xD100, 0xB59C, 0xD101, 0xB59D, 0xD102, 0xB59E, 0xD103, 0xB59F, + 0xD104, 0xB5A0, 0xD105, 0xB641, 0xD106, 0xB642, 0xD107, 0xB643, 0xD108, 0xB644, 0xD109, 0xB645, 0xD10A, 0xB646, 0xD10B, 0xB647, + 0xD10C, 0xB648, 0xD10D, 0xC5CC, 0xD10E, 0xB649, 0xD10F, 0xB64A, 0xD110, 0xB64B, 0xD111, 0xB64C, 0xD112, 0xB64D, 0xD113, 0xB64E, + 0xD114, 0xB64F, 0xD115, 0xB650, 0xD116, 0xB651, 0xD117, 0xB652, 0xD118, 0xB653, 0xD119, 0xB654, 0xD11A, 0xB655, 0xD11B, 0xB656, + 0xD11C, 0xB657, 0xD11D, 0xB658, 0xD11E, 0xB659, 0xD11F, 0xB65A, 0xD120, 0xB661, 0xD121, 0xB662, 0xD122, 0xB663, 0xD123, 0xB664, + 0xD124, 0xB665, 0xD125, 0xB666, 0xD126, 0xB667, 0xD127, 0xB668, 0xD128, 0xB669, 0xD129, 0xB66A, 0xD12A, 0xB66B, 0xD12B, 0xB66C, + 0xD12C, 0xB66D, 0xD12D, 0xB66E, 0xD12E, 0xB66F, 0xD12F, 0xB670, 0xD130, 0xC5CD, 0xD131, 0xC5CE, 0xD132, 0xB671, 0xD133, 0xB672, + 0xD134, 0xC5CF, 0xD135, 0xB673, 0xD136, 0xB674, 0xD137, 0xB675, 0xD138, 0xC5D0, 0xD139, 0xB676, 0xD13A, 0xC5D1, 0xD13B, 0xB677, + 0xD13C, 0xB678, 0xD13D, 0xB679, 0xD13E, 0xB67A, 0xD13F, 0xB681, 0xD140, 0xC5D2, 0xD141, 0xC5D3, 0xD142, 0xB682, 0xD143, 0xC5D4, + 0xD144, 0xC5D5, 0xD145, 0xC5D6, 0xD146, 0xB683, 0xD147, 0xB684, 0xD148, 0xB685, 0xD149, 0xB686, 0xD14A, 0xB687, 0xD14B, 0xB688, + 0xD14C, 0xC5D7, 0xD14D, 0xC5D8, 0xD14E, 0xB689, 0xD14F, 0xB68A, 0xD150, 0xC5D9, 0xD151, 0xB68B, 0xD152, 0xB68C, 0xD153, 0xB68D, + 0xD154, 0xC5DA, 0xD155, 0xB68E, 0xD156, 0xB68F, 0xD157, 0xB690, 0xD158, 0xB691, 0xD159, 0xB692, 0xD15A, 0xB693, 0xD15B, 0xB694, + 0xD15C, 0xC5DB, 0xD15D, 0xC5DC, 0xD15E, 0xB695, 0xD15F, 0xC5DD, 0xD160, 0xB696, 0xD161, 0xC5DE, 0xD162, 0xB697, 0xD163, 0xB698, + 0xD164, 0xB699, 0xD165, 0xB69A, 0xD166, 0xB69B, 0xD167, 0xB69C, 0xD168, 0xC5DF, 0xD169, 0xB69D, 0xD16A, 0xB69E, 0xD16B, 0xB69F, + 0xD16C, 0xC5E0, 0xD16D, 0xB6A0, 0xD16E, 0xB741, 0xD16F, 0xB742, 0xD170, 0xB743, 0xD171, 0xB744, 0xD172, 0xB745, 0xD173, 0xB746, + 0xD174, 0xB747, 0xD175, 0xB748, 0xD176, 0xB749, 0xD177, 0xB74A, 0xD178, 0xB74B, 0xD179, 0xB74C, 0xD17A, 0xB74D, 0xD17B, 0xB74E, + 0xD17C, 0xC5E1, 0xD17D, 0xB74F, 0xD17E, 0xB750, 0xD17F, 0xB751, 0xD180, 0xB752, 0xD181, 0xB753, 0xD182, 0xB754, 0xD183, 0xB755, + 0xD184, 0xC5E2, 0xD185, 0xB756, 0xD186, 0xB757, 0xD187, 0xB758, 0xD188, 0xC5E3, 0xD189, 0xB759, 0xD18A, 0xB75A, 0xD18B, 0xB761, + 0xD18C, 0xB762, 0xD18D, 0xB763, 0xD18E, 0xB764, 0xD18F, 0xB765, 0xD190, 0xB766, 0xD191, 0xB767, 0xD192, 0xB768, 0xD193, 0xB769, + 0xD194, 0xB76A, 0xD195, 0xB76B, 0xD196, 0xB76C, 0xD197, 0xB76D, 0xD198, 0xB76E, 0xD199, 0xB76F, 0xD19A, 0xB770, 0xD19B, 0xB771, + 0xD19C, 0xB772, 0xD19D, 0xB773, 0xD19E, 0xB774, 0xD19F, 0xB775, 0xD1A0, 0xC5E4, 0xD1A1, 0xC5E5, 0xD1A2, 0xB776, 0xD1A3, 0xB777, + 0xD1A4, 0xC5E6, 0xD1A5, 0xB778, 0xD1A6, 0xB779, 0xD1A7, 0xB77A, 0xD1A8, 0xC5E7, 0xD1A9, 0xB781, 0xD1AA, 0xB782, 0xD1AB, 0xB783, + 0xD1AC, 0xB784, 0xD1AD, 0xB785, 0xD1AE, 0xB786, 0xD1AF, 0xB787, 0xD1B0, 0xC5E8, 0xD1B1, 0xC5E9, 0xD1B2, 0xB788, 0xD1B3, 0xC5EA, + 0xD1B4, 0xB789, 0xD1B5, 0xC5EB, 0xD1B6, 0xB78A, 0xD1B7, 0xB78B, 0xD1B8, 0xB78C, 0xD1B9, 0xB78D, 0xD1BA, 0xC5EC, 0xD1BB, 0xB78E, + 0xD1BC, 0xC5ED, 0xD1BD, 0xB78F, 0xD1BE, 0xB790, 0xD1BF, 0xB791, 0xD1C0, 0xC5EE, 0xD1C1, 0xB792, 0xD1C2, 0xB793, 0xD1C3, 0xB794, + 0xD1C4, 0xB795, 0xD1C5, 0xB796, 0xD1C6, 0xB797, 0xD1C7, 0xB798, 0xD1C8, 0xB799, 0xD1C9, 0xB79A, 0xD1CA, 0xB79B, 0xD1CB, 0xB79C, + 0xD1CC, 0xB79D, 0xD1CD, 0xB79E, 0xD1CE, 0xB79F, 0xD1CF, 0xB7A0, 0xD1D0, 0xB841, 0xD1D1, 0xB842, 0xD1D2, 0xB843, 0xD1D3, 0xB844, + 0xD1D4, 0xB845, 0xD1D5, 0xB846, 0xD1D6, 0xB847, 0xD1D7, 0xB848, 0xD1D8, 0xC5EF, 0xD1D9, 0xB849, 0xD1DA, 0xB84A, 0xD1DB, 0xB84B, + 0xD1DC, 0xB84C, 0xD1DD, 0xB84D, 0xD1DE, 0xB84E, 0xD1DF, 0xB84F, 0xD1E0, 0xB850, 0xD1E1, 0xB851, 0xD1E2, 0xB852, 0xD1E3, 0xB853, + 0xD1E4, 0xB854, 0xD1E5, 0xB855, 0xD1E6, 0xB856, 0xD1E7, 0xB857, 0xD1E8, 0xB858, 0xD1E9, 0xB859, 0xD1EA, 0xB85A, 0xD1EB, 0xB861, + 0xD1EC, 0xB862, 0xD1ED, 0xB863, 0xD1EE, 0xB864, 0xD1EF, 0xB865, 0xD1F0, 0xB866, 0xD1F1, 0xB867, 0xD1F2, 0xB868, 0xD1F3, 0xB869, + 0xD1F4, 0xC5F0, 0xD1F5, 0xB86A, 0xD1F6, 0xB86B, 0xD1F7, 0xB86C, 0xD1F8, 0xC5F1, 0xD1F9, 0xB86D, 0xD1FA, 0xB86E, 0xD1FB, 0xB86F, + 0xD1FC, 0xB870, 0xD1FD, 0xB871, 0xD1FE, 0xB872, 0xD1FF, 0xB873, 0xD200, 0xB874, 0xD201, 0xB875, 0xD202, 0xB876, 0xD203, 0xB877, + 0xD204, 0xB878, 0xD205, 0xB879, 0xD206, 0xB87A, 0xD207, 0xC5F2, 0xD208, 0xB881, 0xD209, 0xC5F3, 0xD20A, 0xB882, 0xD20B, 0xB883, + 0xD20C, 0xB884, 0xD20D, 0xB885, 0xD20E, 0xB886, 0xD20F, 0xB887, 0xD210, 0xC5F4, 0xD211, 0xB888, 0xD212, 0xB889, 0xD213, 0xB88A, + 0xD214, 0xB88B, 0xD215, 0xB88C, 0xD216, 0xB88D, 0xD217, 0xB88E, 0xD218, 0xB88F, 0xD219, 0xB890, 0xD21A, 0xB891, 0xD21B, 0xB892, + 0xD21C, 0xB893, 0xD21D, 0xB894, 0xD21E, 0xB895, 0xD21F, 0xB896, 0xD220, 0xB897, 0xD221, 0xB898, 0xD222, 0xB899, 0xD223, 0xB89A, + 0xD224, 0xB89B, 0xD225, 0xB89C, 0xD226, 0xB89D, 0xD227, 0xB89E, 0xD228, 0xB89F, 0xD229, 0xB8A0, 0xD22A, 0xB941, 0xD22B, 0xB942, + 0xD22C, 0xC5F5, 0xD22D, 0xC5F6, 0xD22E, 0xB943, 0xD22F, 0xB944, 0xD230, 0xC5F7, 0xD231, 0xB945, 0xD232, 0xB946, 0xD233, 0xB947, + 0xD234, 0xC5F8, 0xD235, 0xB948, 0xD236, 0xB949, 0xD237, 0xB94A, 0xD238, 0xB94B, 0xD239, 0xB94C, 0xD23A, 0xB94D, 0xD23B, 0xB94E, + 0xD23C, 0xC5F9, 0xD23D, 0xC5FA, 0xD23E, 0xB94F, 0xD23F, 0xC5FB, 0xD240, 0xB950, 0xD241, 0xC5FC, 0xD242, 0xB951, 0xD243, 0xB952, + 0xD244, 0xB953, 0xD245, 0xB954, 0xD246, 0xB955, 0xD247, 0xB956, 0xD248, 0xC5FD, 0xD249, 0xB957, 0xD24A, 0xB958, 0xD24B, 0xB959, + 0xD24C, 0xB95A, 0xD24D, 0xB961, 0xD24E, 0xB962, 0xD24F, 0xB963, 0xD250, 0xB964, 0xD251, 0xB965, 0xD252, 0xB966, 0xD253, 0xB967, + 0xD254, 0xB968, 0xD255, 0xB969, 0xD256, 0xB96A, 0xD257, 0xB96B, 0xD258, 0xB96C, 0xD259, 0xB96D, 0xD25A, 0xB96E, 0xD25B, 0xB96F, + 0xD25C, 0xC5FE, 0xD25D, 0xB970, 0xD25E, 0xB971, 0xD25F, 0xB972, 0xD260, 0xB973, 0xD261, 0xB974, 0xD262, 0xB975, 0xD263, 0xB976, + 0xD264, 0xC6A1, 0xD265, 0xB977, 0xD266, 0xB978, 0xD267, 0xB979, 0xD268, 0xB97A, 0xD269, 0xB981, 0xD26A, 0xB982, 0xD26B, 0xB983, + 0xD26C, 0xB984, 0xD26D, 0xB985, 0xD26E, 0xB986, 0xD26F, 0xB987, 0xD270, 0xB988, 0xD271, 0xB989, 0xD272, 0xB98A, 0xD273, 0xB98B, + 0xD274, 0xB98C, 0xD275, 0xB98D, 0xD276, 0xB98E, 0xD277, 0xB98F, 0xD278, 0xB990, 0xD279, 0xB991, 0xD27A, 0xB992, 0xD27B, 0xB993, + 0xD27C, 0xB994, 0xD27D, 0xB995, 0xD27E, 0xB996, 0xD27F, 0xB997, 0xD280, 0xC6A2, 0xD281, 0xC6A3, 0xD282, 0xB998, 0xD283, 0xB999, + 0xD284, 0xC6A4, 0xD285, 0xB99A, 0xD286, 0xB99B, 0xD287, 0xB99C, 0xD288, 0xC6A5, 0xD289, 0xB99D, 0xD28A, 0xB99E, 0xD28B, 0xB99F, + 0xD28C, 0xB9A0, 0xD28D, 0xBA41, 0xD28E, 0xBA42, 0xD28F, 0xBA43, 0xD290, 0xC6A6, 0xD291, 0xC6A7, 0xD292, 0xBA44, 0xD293, 0xBA45, + 0xD294, 0xBA46, 0xD295, 0xC6A8, 0xD296, 0xBA47, 0xD297, 0xBA48, 0xD298, 0xBA49, 0xD299, 0xBA4A, 0xD29A, 0xBA4B, 0xD29B, 0xBA4C, + 0xD29C, 0xC6A9, 0xD29D, 0xBA4D, 0xD29E, 0xBA4E, 0xD29F, 0xBA4F, 0xD2A0, 0xC6AA, 0xD2A1, 0xBA50, 0xD2A2, 0xBA51, 0xD2A3, 0xBA52, + 0xD2A4, 0xC6AB, 0xD2A5, 0xBA53, 0xD2A6, 0xBA54, 0xD2A7, 0xBA55, 0xD2A8, 0xBA56, 0xD2A9, 0xBA57, 0xD2AA, 0xBA58, 0xD2AB, 0xBA59, + 0xD2AC, 0xC6AC, 0xD2AD, 0xBA5A, 0xD2AE, 0xBA61, 0xD2AF, 0xBA62, 0xD2B0, 0xBA63, 0xD2B1, 0xC6AD, 0xD2B2, 0xBA64, 0xD2B3, 0xBA65, + 0xD2B4, 0xBA66, 0xD2B5, 0xBA67, 0xD2B6, 0xBA68, 0xD2B7, 0xBA69, 0xD2B8, 0xC6AE, 0xD2B9, 0xC6AF, 0xD2BA, 0xBA6A, 0xD2BB, 0xBA6B, + 0xD2BC, 0xC6B0, 0xD2BD, 0xBA6C, 0xD2BE, 0xBA6D, 0xD2BF, 0xC6B1, 0xD2C0, 0xC6B2, 0xD2C1, 0xBA6E, 0xD2C2, 0xC6B3, 0xD2C3, 0xBA6F, + 0xD2C4, 0xBA70, 0xD2C5, 0xBA71, 0xD2C6, 0xBA72, 0xD2C7, 0xBA73, 0xD2C8, 0xC6B4, 0xD2C9, 0xC6B5, 0xD2CA, 0xBA74, 0xD2CB, 0xC6B6, + 0xD2CC, 0xBA75, 0xD2CD, 0xBA76, 0xD2CE, 0xBA77, 0xD2CF, 0xBA78, 0xD2D0, 0xBA79, 0xD2D1, 0xBA7A, 0xD2D2, 0xBA81, 0xD2D3, 0xBA82, + 0xD2D4, 0xC6B7, 0xD2D5, 0xBA83, 0xD2D6, 0xBA84, 0xD2D7, 0xBA85, 0xD2D8, 0xC6B8, 0xD2D9, 0xBA86, 0xD2DA, 0xBA87, 0xD2DB, 0xBA88, + 0xD2DC, 0xC6B9, 0xD2DD, 0xBA89, 0xD2DE, 0xBA8A, 0xD2DF, 0xBA8B, 0xD2E0, 0xBA8C, 0xD2E1, 0xBA8D, 0xD2E2, 0xBA8E, 0xD2E3, 0xBA8F, + 0xD2E4, 0xC6BA, 0xD2E5, 0xC6BB, 0xD2E6, 0xBA90, 0xD2E7, 0xBA91, 0xD2E8, 0xBA92, 0xD2E9, 0xBA93, 0xD2EA, 0xBA94, 0xD2EB, 0xBA95, + 0xD2EC, 0xBA96, 0xD2ED, 0xBA97, 0xD2EE, 0xBA98, 0xD2EF, 0xBA99, 0xD2F0, 0xC6BC, 0xD2F1, 0xC6BD, 0xD2F2, 0xBA9A, 0xD2F3, 0xBA9B, + 0xD2F4, 0xC6BE, 0xD2F5, 0xBA9C, 0xD2F6, 0xBA9D, 0xD2F7, 0xBA9E, 0xD2F8, 0xC6BF, 0xD2F9, 0xBA9F, 0xD2FA, 0xBAA0, 0xD2FB, 0xBB41, + 0xD2FC, 0xBB42, 0xD2FD, 0xBB43, 0xD2FE, 0xBB44, 0xD2FF, 0xBB45, 0xD300, 0xC6C0, 0xD301, 0xC6C1, 0xD302, 0xBB46, 0xD303, 0xC6C2, + 0xD304, 0xBB47, 0xD305, 0xC6C3, 0xD306, 0xBB48, 0xD307, 0xBB49, 0xD308, 0xBB4A, 0xD309, 0xBB4B, 0xD30A, 0xBB4C, 0xD30B, 0xBB4D, + 0xD30C, 0xC6C4, 0xD30D, 0xC6C5, 0xD30E, 0xC6C6, 0xD30F, 0xBB4E, 0xD310, 0xC6C7, 0xD311, 0xBB4F, 0xD312, 0xBB50, 0xD313, 0xBB51, + 0xD314, 0xC6C8, 0xD315, 0xBB52, 0xD316, 0xC6C9, 0xD317, 0xBB53, 0xD318, 0xBB54, 0xD319, 0xBB55, 0xD31A, 0xBB56, 0xD31B, 0xBB57, + 0xD31C, 0xC6CA, 0xD31D, 0xC6CB, 0xD31E, 0xBB58, 0xD31F, 0xC6CC, 0xD320, 0xC6CD, 0xD321, 0xC6CE, 0xD322, 0xBB59, 0xD323, 0xBB5A, + 0xD324, 0xBB61, 0xD325, 0xC6CF, 0xD326, 0xBB62, 0xD327, 0xBB63, 0xD328, 0xC6D0, 0xD329, 0xC6D1, 0xD32A, 0xBB64, 0xD32B, 0xBB65, + 0xD32C, 0xC6D2, 0xD32D, 0xBB66, 0xD32E, 0xBB67, 0xD32F, 0xBB68, 0xD330, 0xC6D3, 0xD331, 0xBB69, 0xD332, 0xBB6A, 0xD333, 0xBB6B, + 0xD334, 0xBB6C, 0xD335, 0xBB6D, 0xD336, 0xBB6E, 0xD337, 0xBB6F, 0xD338, 0xC6D4, 0xD339, 0xC6D5, 0xD33A, 0xBB70, 0xD33B, 0xC6D6, + 0xD33C, 0xC6D7, 0xD33D, 0xC6D8, 0xD33E, 0xBB71, 0xD33F, 0xBB72, 0xD340, 0xBB73, 0xD341, 0xBB74, 0xD342, 0xBB75, 0xD343, 0xBB76, + 0xD344, 0xC6D9, 0xD345, 0xC6DA, 0xD346, 0xBB77, 0xD347, 0xBB78, 0xD348, 0xBB79, 0xD349, 0xBB7A, 0xD34A, 0xBB81, 0xD34B, 0xBB82, + 0xD34C, 0xBB83, 0xD34D, 0xBB84, 0xD34E, 0xBB85, 0xD34F, 0xBB86, 0xD350, 0xBB87, 0xD351, 0xBB88, 0xD352, 0xBB89, 0xD353, 0xBB8A, + 0xD354, 0xBB8B, 0xD355, 0xBB8C, 0xD356, 0xBB8D, 0xD357, 0xBB8E, 0xD358, 0xBB8F, 0xD359, 0xBB90, 0xD35A, 0xBB91, 0xD35B, 0xBB92, + 0xD35C, 0xBB93, 0xD35D, 0xBB94, 0xD35E, 0xBB95, 0xD35F, 0xBB96, 0xD360, 0xBB97, 0xD361, 0xBB98, 0xD362, 0xBB99, 0xD363, 0xBB9A, + 0xD364, 0xBB9B, 0xD365, 0xBB9C, 0xD366, 0xBB9D, 0xD367, 0xBB9E, 0xD368, 0xBB9F, 0xD369, 0xBBA0, 0xD36A, 0xBC41, 0xD36B, 0xBC42, + 0xD36C, 0xBC43, 0xD36D, 0xBC44, 0xD36E, 0xBC45, 0xD36F, 0xBC46, 0xD370, 0xBC47, 0xD371, 0xBC48, 0xD372, 0xBC49, 0xD373, 0xBC4A, + 0xD374, 0xBC4B, 0xD375, 0xBC4C, 0xD376, 0xBC4D, 0xD377, 0xBC4E, 0xD378, 0xBC4F, 0xD379, 0xBC50, 0xD37A, 0xBC51, 0xD37B, 0xBC52, + 0xD37C, 0xC6DB, 0xD37D, 0xC6DC, 0xD37E, 0xBC53, 0xD37F, 0xBC54, 0xD380, 0xC6DD, 0xD381, 0xBC55, 0xD382, 0xBC56, 0xD383, 0xBC57, + 0xD384, 0xC6DE, 0xD385, 0xBC58, 0xD386, 0xBC59, 0xD387, 0xBC5A, 0xD388, 0xBC61, 0xD389, 0xBC62, 0xD38A, 0xBC63, 0xD38B, 0xBC64, + 0xD38C, 0xC6DF, 0xD38D, 0xC6E0, 0xD38E, 0xBC65, 0xD38F, 0xC6E1, 0xD390, 0xC6E2, 0xD391, 0xC6E3, 0xD392, 0xBC66, 0xD393, 0xBC67, + 0xD394, 0xBC68, 0xD395, 0xBC69, 0xD396, 0xBC6A, 0xD397, 0xBC6B, 0xD398, 0xC6E4, 0xD399, 0xC6E5, 0xD39A, 0xBC6C, 0xD39B, 0xBC6D, + 0xD39C, 0xC6E6, 0xD39D, 0xBC6E, 0xD39E, 0xBC6F, 0xD39F, 0xBC70, 0xD3A0, 0xC6E7, 0xD3A1, 0xBC71, 0xD3A2, 0xBC72, 0xD3A3, 0xBC73, + 0xD3A4, 0xBC74, 0xD3A5, 0xBC75, 0xD3A6, 0xBC76, 0xD3A7, 0xBC77, 0xD3A8, 0xC6E8, 0xD3A9, 0xC6E9, 0xD3AA, 0xBC78, 0xD3AB, 0xC6EA, + 0xD3AC, 0xBC79, 0xD3AD, 0xC6EB, 0xD3AE, 0xBC7A, 0xD3AF, 0xBC81, 0xD3B0, 0xBC82, 0xD3B1, 0xBC83, 0xD3B2, 0xBC84, 0xD3B3, 0xBC85, + 0xD3B4, 0xC6EC, 0xD3B5, 0xBC86, 0xD3B6, 0xBC87, 0xD3B7, 0xBC88, 0xD3B8, 0xC6ED, 0xD3B9, 0xBC89, 0xD3BA, 0xBC8A, 0xD3BB, 0xBC8B, + 0xD3BC, 0xC6EE, 0xD3BD, 0xBC8C, 0xD3BE, 0xBC8D, 0xD3BF, 0xBC8E, 0xD3C0, 0xBC8F, 0xD3C1, 0xBC90, 0xD3C2, 0xBC91, 0xD3C3, 0xBC92, + 0xD3C4, 0xC6EF, 0xD3C5, 0xC6F0, 0xD3C6, 0xBC93, 0xD3C7, 0xBC94, 0xD3C8, 0xC6F1, 0xD3C9, 0xC6F2, 0xD3CA, 0xBC95, 0xD3CB, 0xBC96, + 0xD3CC, 0xBC97, 0xD3CD, 0xBC98, 0xD3CE, 0xBC99, 0xD3CF, 0xBC9A, 0xD3D0, 0xC6F3, 0xD3D1, 0xBC9B, 0xD3D2, 0xBC9C, 0xD3D3, 0xBC9D, + 0xD3D4, 0xBC9E, 0xD3D5, 0xBC9F, 0xD3D6, 0xBCA0, 0xD3D7, 0xBD41, 0xD3D8, 0xC6F4, 0xD3D9, 0xBD42, 0xD3DA, 0xBD43, 0xD3DB, 0xBD44, + 0xD3DC, 0xBD45, 0xD3DD, 0xBD46, 0xD3DE, 0xBD47, 0xD3DF, 0xBD48, 0xD3E0, 0xBD49, 0xD3E1, 0xC6F5, 0xD3E2, 0xBD4A, 0xD3E3, 0xC6F6, + 0xD3E4, 0xBD4B, 0xD3E5, 0xBD4C, 0xD3E6, 0xBD4D, 0xD3E7, 0xBD4E, 0xD3E8, 0xBD4F, 0xD3E9, 0xBD50, 0xD3EA, 0xBD51, 0xD3EB, 0xBD52, + 0xD3EC, 0xC6F7, 0xD3ED, 0xC6F8, 0xD3EE, 0xBD53, 0xD3EF, 0xBD54, 0xD3F0, 0xC6F9, 0xD3F1, 0xBD55, 0xD3F2, 0xBD56, 0xD3F3, 0xBD57, + 0xD3F4, 0xC6FA, 0xD3F5, 0xBD58, 0xD3F6, 0xBD59, 0xD3F7, 0xBD5A, 0xD3F8, 0xBD61, 0xD3F9, 0xBD62, 0xD3FA, 0xBD63, 0xD3FB, 0xBD64, + 0xD3FC, 0xC6FB, 0xD3FD, 0xC6FC, 0xD3FE, 0xBD65, 0xD3FF, 0xC6FD, 0xD400, 0xBD66, 0xD401, 0xC6FE, 0xD402, 0xBD67, 0xD403, 0xBD68, + 0xD404, 0xBD69, 0xD405, 0xBD6A, 0xD406, 0xBD6B, 0xD407, 0xBD6C, 0xD408, 0xC7A1, 0xD409, 0xBD6D, 0xD40A, 0xBD6E, 0xD40B, 0xBD6F, + 0xD40C, 0xBD70, 0xD40D, 0xBD71, 0xD40E, 0xBD72, 0xD40F, 0xBD73, 0xD410, 0xBD74, 0xD411, 0xBD75, 0xD412, 0xBD76, 0xD413, 0xBD77, + 0xD414, 0xBD78, 0xD415, 0xBD79, 0xD416, 0xBD7A, 0xD417, 0xBD81, 0xD418, 0xBD82, 0xD419, 0xBD83, 0xD41A, 0xBD84, 0xD41B, 0xBD85, + 0xD41C, 0xBD86, 0xD41D, 0xC7A2, 0xD41E, 0xBD87, 0xD41F, 0xBD88, 0xD420, 0xBD89, 0xD421, 0xBD8A, 0xD422, 0xBD8B, 0xD423, 0xBD8C, + 0xD424, 0xBD8D, 0xD425, 0xBD8E, 0xD426, 0xBD8F, 0xD427, 0xBD90, 0xD428, 0xBD91, 0xD429, 0xBD92, 0xD42A, 0xBD93, 0xD42B, 0xBD94, + 0xD42C, 0xBD95, 0xD42D, 0xBD96, 0xD42E, 0xBD97, 0xD42F, 0xBD98, 0xD430, 0xBD99, 0xD431, 0xBD9A, 0xD432, 0xBD9B, 0xD433, 0xBD9C, + 0xD434, 0xBD9D, 0xD435, 0xBD9E, 0xD436, 0xBD9F, 0xD437, 0xBDA0, 0xD438, 0xBE41, 0xD439, 0xBE42, 0xD43A, 0xBE43, 0xD43B, 0xBE44, + 0xD43C, 0xBE45, 0xD43D, 0xBE46, 0xD43E, 0xBE47, 0xD43F, 0xBE48, 0xD440, 0xC7A3, 0xD441, 0xBE49, 0xD442, 0xBE4A, 0xD443, 0xBE4B, + 0xD444, 0xC7A4, 0xD445, 0xBE4C, 0xD446, 0xBE4D, 0xD447, 0xBE4E, 0xD448, 0xBE4F, 0xD449, 0xBE50, 0xD44A, 0xBE51, 0xD44B, 0xBE52, + 0xD44C, 0xBE53, 0xD44D, 0xBE54, 0xD44E, 0xBE55, 0xD44F, 0xBE56, 0xD450, 0xBE57, 0xD451, 0xBE58, 0xD452, 0xBE59, 0xD453, 0xBE5A, + 0xD454, 0xBE61, 0xD455, 0xBE62, 0xD456, 0xBE63, 0xD457, 0xBE64, 0xD458, 0xBE65, 0xD459, 0xBE66, 0xD45A, 0xBE67, 0xD45B, 0xBE68, + 0xD45C, 0xC7A5, 0xD45D, 0xBE69, 0xD45E, 0xBE6A, 0xD45F, 0xBE6B, 0xD460, 0xC7A6, 0xD461, 0xBE6C, 0xD462, 0xBE6D, 0xD463, 0xBE6E, + 0xD464, 0xC7A7, 0xD465, 0xBE6F, 0xD466, 0xBE70, 0xD467, 0xBE71, 0xD468, 0xBE72, 0xD469, 0xBE73, 0xD46A, 0xBE74, 0xD46B, 0xBE75, + 0xD46C, 0xBE76, 0xD46D, 0xC7A8, 0xD46E, 0xBE77, 0xD46F, 0xC7A9, 0xD470, 0xBE78, 0xD471, 0xBE79, 0xD472, 0xBE7A, 0xD473, 0xBE81, + 0xD474, 0xBE82, 0xD475, 0xBE83, 0xD476, 0xBE84, 0xD477, 0xBE85, 0xD478, 0xC7AA, 0xD479, 0xC7AB, 0xD47A, 0xBE86, 0xD47B, 0xBE87, + 0xD47C, 0xC7AC, 0xD47D, 0xBE88, 0xD47E, 0xBE89, 0xD47F, 0xC7AD, 0xD480, 0xC7AE, 0xD481, 0xBE8A, 0xD482, 0xC7AF, 0xD483, 0xBE8B, + 0xD484, 0xBE8C, 0xD485, 0xBE8D, 0xD486, 0xBE8E, 0xD487, 0xBE8F, 0xD488, 0xC7B0, 0xD489, 0xC7B1, 0xD48A, 0xBE90, 0xD48B, 0xC7B2, + 0xD48C, 0xBE91, 0xD48D, 0xC7B3, 0xD48E, 0xBE92, 0xD48F, 0xBE93, 0xD490, 0xBE94, 0xD491, 0xBE95, 0xD492, 0xBE96, 0xD493, 0xBE97, + 0xD494, 0xC7B4, 0xD495, 0xBE98, 0xD496, 0xBE99, 0xD497, 0xBE9A, 0xD498, 0xBE9B, 0xD499, 0xBE9C, 0xD49A, 0xBE9D, 0xD49B, 0xBE9E, + 0xD49C, 0xBE9F, 0xD49D, 0xBEA0, 0xD49E, 0xBF41, 0xD49F, 0xBF42, 0xD4A0, 0xBF43, 0xD4A1, 0xBF44, 0xD4A2, 0xBF45, 0xD4A3, 0xBF46, + 0xD4A4, 0xBF47, 0xD4A5, 0xBF48, 0xD4A6, 0xBF49, 0xD4A7, 0xBF4A, 0xD4A8, 0xBF4B, 0xD4A9, 0xC7B5, 0xD4AA, 0xBF4C, 0xD4AB, 0xBF4D, + 0xD4AC, 0xBF4E, 0xD4AD, 0xBF4F, 0xD4AE, 0xBF50, 0xD4AF, 0xBF51, 0xD4B0, 0xBF52, 0xD4B1, 0xBF53, 0xD4B2, 0xBF54, 0xD4B3, 0xBF55, + 0xD4B4, 0xBF56, 0xD4B5, 0xBF57, 0xD4B6, 0xBF58, 0xD4B7, 0xBF59, 0xD4B8, 0xBF5A, 0xD4B9, 0xBF61, 0xD4BA, 0xBF62, 0xD4BB, 0xBF63, + 0xD4BC, 0xBF64, 0xD4BD, 0xBF65, 0xD4BE, 0xBF66, 0xD4BF, 0xBF67, 0xD4C0, 0xBF68, 0xD4C1, 0xBF69, 0xD4C2, 0xBF6A, 0xD4C3, 0xBF6B, + 0xD4C4, 0xBF6C, 0xD4C5, 0xBF6D, 0xD4C6, 0xBF6E, 0xD4C7, 0xBF6F, 0xD4C8, 0xBF70, 0xD4C9, 0xBF71, 0xD4CA, 0xBF72, 0xD4CB, 0xBF73, + 0xD4CC, 0xC7B6, 0xD4CD, 0xBF74, 0xD4CE, 0xBF75, 0xD4CF, 0xBF76, 0xD4D0, 0xC7B7, 0xD4D1, 0xBF77, 0xD4D2, 0xBF78, 0xD4D3, 0xBF79, + 0xD4D4, 0xC7B8, 0xD4D5, 0xBF7A, 0xD4D6, 0xBF81, 0xD4D7, 0xBF82, 0xD4D8, 0xBF83, 0xD4D9, 0xBF84, 0xD4DA, 0xBF85, 0xD4DB, 0xBF86, + 0xD4DC, 0xC7B9, 0xD4DD, 0xBF87, 0xD4DE, 0xBF88, 0xD4DF, 0xC7BA, 0xD4E0, 0xBF89, 0xD4E1, 0xBF8A, 0xD4E2, 0xBF8B, 0xD4E3, 0xBF8C, + 0xD4E4, 0xBF8D, 0xD4E5, 0xBF8E, 0xD4E6, 0xBF8F, 0xD4E7, 0xBF90, 0xD4E8, 0xC7BB, 0xD4E9, 0xBF91, 0xD4EA, 0xBF92, 0xD4EB, 0xBF93, + 0xD4EC, 0xC7BC, 0xD4ED, 0xBF94, 0xD4EE, 0xBF95, 0xD4EF, 0xBF96, 0xD4F0, 0xC7BD, 0xD4F1, 0xBF97, 0xD4F2, 0xBF98, 0xD4F3, 0xBF99, + 0xD4F4, 0xBF9A, 0xD4F5, 0xBF9B, 0xD4F6, 0xBF9C, 0xD4F7, 0xBF9D, 0xD4F8, 0xC7BE, 0xD4F9, 0xBF9E, 0xD4FA, 0xBF9F, 0xD4FB, 0xC7BF, + 0xD4FC, 0xBFA0, 0xD4FD, 0xC7C0, 0xD4FE, 0xC041, 0xD4FF, 0xC042, 0xD500, 0xC043, 0xD501, 0xC044, 0xD502, 0xC045, 0xD503, 0xC046, + 0xD504, 0xC7C1, 0xD505, 0xC047, 0xD506, 0xC048, 0xD507, 0xC049, 0xD508, 0xC7C2, 0xD509, 0xC04A, 0xD50A, 0xC04B, 0xD50B, 0xC04C, + 0xD50C, 0xC7C3, 0xD50D, 0xC04D, 0xD50E, 0xC04E, 0xD50F, 0xC04F, 0xD510, 0xC050, 0xD511, 0xC051, 0xD512, 0xC052, 0xD513, 0xC053, + 0xD514, 0xC7C4, 0xD515, 0xC7C5, 0xD516, 0xC054, 0xD517, 0xC7C6, 0xD518, 0xC055, 0xD519, 0xC056, 0xD51A, 0xC057, 0xD51B, 0xC058, + 0xD51C, 0xC059, 0xD51D, 0xC05A, 0xD51E, 0xC061, 0xD51F, 0xC062, 0xD520, 0xC063, 0xD521, 0xC064, 0xD522, 0xC065, 0xD523, 0xC066, + 0xD524, 0xC067, 0xD525, 0xC068, 0xD526, 0xC069, 0xD527, 0xC06A, 0xD528, 0xC06B, 0xD529, 0xC06C, 0xD52A, 0xC06D, 0xD52B, 0xC06E, + 0xD52C, 0xC06F, 0xD52D, 0xC070, 0xD52E, 0xC071, 0xD52F, 0xC072, 0xD530, 0xC073, 0xD531, 0xC074, 0xD532, 0xC075, 0xD533, 0xC076, + 0xD534, 0xC077, 0xD535, 0xC078, 0xD536, 0xC079, 0xD537, 0xC07A, 0xD538, 0xC081, 0xD539, 0xC082, 0xD53A, 0xC083, 0xD53B, 0xC084, + 0xD53C, 0xC7C7, 0xD53D, 0xC7C8, 0xD53E, 0xC085, 0xD53F, 0xC086, 0xD540, 0xC7C9, 0xD541, 0xC087, 0xD542, 0xC088, 0xD543, 0xC089, + 0xD544, 0xC7CA, 0xD545, 0xC08A, 0xD546, 0xC08B, 0xD547, 0xC08C, 0xD548, 0xC08D, 0xD549, 0xC08E, 0xD54A, 0xC08F, 0xD54B, 0xC090, + 0xD54C, 0xC7CB, 0xD54D, 0xC7CC, 0xD54E, 0xC091, 0xD54F, 0xC7CD, 0xD550, 0xC092, 0xD551, 0xC7CE, 0xD552, 0xC093, 0xD553, 0xC094, + 0xD554, 0xC095, 0xD555, 0xC096, 0xD556, 0xC097, 0xD557, 0xC098, 0xD558, 0xC7CF, 0xD559, 0xC7D0, 0xD55A, 0xC099, 0xD55B, 0xC09A, + 0xD55C, 0xC7D1, 0xD55D, 0xC09B, 0xD55E, 0xC09C, 0xD55F, 0xC09D, 0xD560, 0xC7D2, 0xD561, 0xC09E, 0xD562, 0xC09F, 0xD563, 0xC0A0, + 0xD564, 0xC141, 0xD565, 0xC7D3, 0xD566, 0xC142, 0xD567, 0xC143, 0xD568, 0xC7D4, 0xD569, 0xC7D5, 0xD56A, 0xC144, 0xD56B, 0xC7D6, + 0xD56C, 0xC145, 0xD56D, 0xC7D7, 0xD56E, 0xC146, 0xD56F, 0xC147, 0xD570, 0xC148, 0xD571, 0xC149, 0xD572, 0xC14A, 0xD573, 0xC14B, + 0xD574, 0xC7D8, 0xD575, 0xC7D9, 0xD576, 0xC14C, 0xD577, 0xC14D, 0xD578, 0xC7DA, 0xD579, 0xC14E, 0xD57A, 0xC14F, 0xD57B, 0xC150, + 0xD57C, 0xC7DB, 0xD57D, 0xC151, 0xD57E, 0xC152, 0xD57F, 0xC153, 0xD580, 0xC154, 0xD581, 0xC155, 0xD582, 0xC156, 0xD583, 0xC157, + 0xD584, 0xC7DC, 0xD585, 0xC7DD, 0xD586, 0xC158, 0xD587, 0xC7DE, 0xD588, 0xC7DF, 0xD589, 0xC7E0, 0xD58A, 0xC159, 0xD58B, 0xC15A, + 0xD58C, 0xC161, 0xD58D, 0xC162, 0xD58E, 0xC163, 0xD58F, 0xC164, 0xD590, 0xC7E1, 0xD591, 0xC165, 0xD592, 0xC166, 0xD593, 0xC167, + 0xD594, 0xC168, 0xD595, 0xC169, 0xD596, 0xC16A, 0xD597, 0xC16B, 0xD598, 0xC16C, 0xD599, 0xC16D, 0xD59A, 0xC16E, 0xD59B, 0xC16F, + 0xD59C, 0xC170, 0xD59D, 0xC171, 0xD59E, 0xC172, 0xD59F, 0xC173, 0xD5A0, 0xC174, 0xD5A1, 0xC175, 0xD5A2, 0xC176, 0xD5A3, 0xC177, + 0xD5A4, 0xC178, 0xD5A5, 0xC7E2, 0xD5A6, 0xC179, 0xD5A7, 0xC17A, 0xD5A8, 0xC181, 0xD5A9, 0xC182, 0xD5AA, 0xC183, 0xD5AB, 0xC184, + 0xD5AC, 0xC185, 0xD5AD, 0xC186, 0xD5AE, 0xC187, 0xD5AF, 0xC188, 0xD5B0, 0xC189, 0xD5B1, 0xC18A, 0xD5B2, 0xC18B, 0xD5B3, 0xC18C, + 0xD5B4, 0xC18D, 0xD5B5, 0xC18E, 0xD5B6, 0xC18F, 0xD5B7, 0xC190, 0xD5B8, 0xC191, 0xD5B9, 0xC192, 0xD5BA, 0xC193, 0xD5BB, 0xC194, + 0xD5BC, 0xC195, 0xD5BD, 0xC196, 0xD5BE, 0xC197, 0xD5BF, 0xC198, 0xD5C0, 0xC199, 0xD5C1, 0xC19A, 0xD5C2, 0xC19B, 0xD5C3, 0xC19C, + 0xD5C4, 0xC19D, 0xD5C5, 0xC19E, 0xD5C6, 0xC19F, 0xD5C7, 0xC1A0, 0xD5C8, 0xC7E3, 0xD5C9, 0xC7E4, 0xD5CA, 0xC241, 0xD5CB, 0xC242, + 0xD5CC, 0xC7E5, 0xD5CD, 0xC243, 0xD5CE, 0xC244, 0xD5CF, 0xC245, 0xD5D0, 0xC7E6, 0xD5D1, 0xC246, 0xD5D2, 0xC7E7, 0xD5D3, 0xC247, + 0xD5D4, 0xC248, 0xD5D5, 0xC249, 0xD5D6, 0xC24A, 0xD5D7, 0xC24B, 0xD5D8, 0xC7E8, 0xD5D9, 0xC7E9, 0xD5DA, 0xC24C, 0xD5DB, 0xC7EA, + 0xD5DC, 0xC24D, 0xD5DD, 0xC7EB, 0xD5DE, 0xC24E, 0xD5DF, 0xC24F, 0xD5E0, 0xC250, 0xD5E1, 0xC251, 0xD5E2, 0xC252, 0xD5E3, 0xC253, + 0xD5E4, 0xC7EC, 0xD5E5, 0xC7ED, 0xD5E6, 0xC254, 0xD5E7, 0xC255, 0xD5E8, 0xC7EE, 0xD5E9, 0xC256, 0xD5EA, 0xC257, 0xD5EB, 0xC258, + 0xD5EC, 0xC7EF, 0xD5ED, 0xC259, 0xD5EE, 0xC25A, 0xD5EF, 0xC261, 0xD5F0, 0xC262, 0xD5F1, 0xC263, 0xD5F2, 0xC264, 0xD5F3, 0xC265, + 0xD5F4, 0xC7F0, 0xD5F5, 0xC7F1, 0xD5F6, 0xC266, 0xD5F7, 0xC7F2, 0xD5F8, 0xC267, 0xD5F9, 0xC7F3, 0xD5FA, 0xC268, 0xD5FB, 0xC269, + 0xD5FC, 0xC26A, 0xD5FD, 0xC26B, 0xD5FE, 0xC26C, 0xD5FF, 0xC26D, 0xD600, 0xC7F4, 0xD601, 0xC7F5, 0xD602, 0xC26E, 0xD603, 0xC26F, + 0xD604, 0xC7F6, 0xD605, 0xC270, 0xD606, 0xC271, 0xD607, 0xC272, 0xD608, 0xC7F7, 0xD609, 0xC273, 0xD60A, 0xC274, 0xD60B, 0xC275, + 0xD60C, 0xC276, 0xD60D, 0xC277, 0xD60E, 0xC278, 0xD60F, 0xC279, 0xD610, 0xC7F8, 0xD611, 0xC7F9, 0xD612, 0xC27A, 0xD613, 0xC7FA, + 0xD614, 0xC7FB, 0xD615, 0xC7FC, 0xD616, 0xC281, 0xD617, 0xC282, 0xD618, 0xC283, 0xD619, 0xC284, 0xD61A, 0xC285, 0xD61B, 0xC286, + 0xD61C, 0xC7FD, 0xD61D, 0xC287, 0xD61E, 0xC288, 0xD61F, 0xC289, 0xD620, 0xC7FE, 0xD621, 0xC28A, 0xD622, 0xC28B, 0xD623, 0xC28C, + 0xD624, 0xC8A1, 0xD625, 0xC28D, 0xD626, 0xC28E, 0xD627, 0xC28F, 0xD628, 0xC290, 0xD629, 0xC291, 0xD62A, 0xC292, 0xD62B, 0xC293, + 0xD62C, 0xC294, 0xD62D, 0xC8A2, 0xD62E, 0xC295, 0xD62F, 0xC296, 0xD630, 0xC297, 0xD631, 0xC298, 0xD632, 0xC299, 0xD633, 0xC29A, + 0xD634, 0xC29B, 0xD635, 0xC29C, 0xD636, 0xC29D, 0xD637, 0xC29E, 0xD638, 0xC8A3, 0xD639, 0xC8A4, 0xD63A, 0xC29F, 0xD63B, 0xC2A0, + 0xD63C, 0xC8A5, 0xD63D, 0xC341, 0xD63E, 0xC342, 0xD63F, 0xC343, 0xD640, 0xC8A6, 0xD641, 0xC344, 0xD642, 0xC345, 0xD643, 0xC346, + 0xD644, 0xC347, 0xD645, 0xC8A7, 0xD646, 0xC348, 0xD647, 0xC349, 0xD648, 0xC8A8, 0xD649, 0xC8A9, 0xD64A, 0xC34A, 0xD64B, 0xC8AA, + 0xD64C, 0xC34B, 0xD64D, 0xC8AB, 0xD64E, 0xC34C, 0xD64F, 0xC34D, 0xD650, 0xC34E, 0xD651, 0xC8AC, 0xD652, 0xC34F, 0xD653, 0xC350, + 0xD654, 0xC8AD, 0xD655, 0xC8AE, 0xD656, 0xC351, 0xD657, 0xC352, 0xD658, 0xC8AF, 0xD659, 0xC353, 0xD65A, 0xC354, 0xD65B, 0xC355, + 0xD65C, 0xC8B0, 0xD65D, 0xC356, 0xD65E, 0xC357, 0xD65F, 0xC358, 0xD660, 0xC359, 0xD661, 0xC35A, 0xD662, 0xC361, 0xD663, 0xC362, + 0xD664, 0xC363, 0xD665, 0xC364, 0xD666, 0xC365, 0xD667, 0xC8B1, 0xD668, 0xC366, 0xD669, 0xC8B2, 0xD66A, 0xC367, 0xD66B, 0xC368, + 0xD66C, 0xC369, 0xD66D, 0xC36A, 0xD66E, 0xC36B, 0xD66F, 0xC36C, 0xD670, 0xC8B3, 0xD671, 0xC8B4, 0xD672, 0xC36D, 0xD673, 0xC36E, + 0xD674, 0xC8B5, 0xD675, 0xC36F, 0xD676, 0xC370, 0xD677, 0xC371, 0xD678, 0xC372, 0xD679, 0xC373, 0xD67A, 0xC374, 0xD67B, 0xC375, + 0xD67C, 0xC376, 0xD67D, 0xC377, 0xD67E, 0xC378, 0xD67F, 0xC379, 0xD680, 0xC37A, 0xD681, 0xC381, 0xD682, 0xC382, 0xD683, 0xC8B6, + 0xD684, 0xC383, 0xD685, 0xC8B7, 0xD686, 0xC384, 0xD687, 0xC385, 0xD688, 0xC386, 0xD689, 0xC387, 0xD68A, 0xC388, 0xD68B, 0xC389, + 0xD68C, 0xC8B8, 0xD68D, 0xC8B9, 0xD68E, 0xC38A, 0xD68F, 0xC38B, 0xD690, 0xC8BA, 0xD691, 0xC38C, 0xD692, 0xC38D, 0xD693, 0xC38E, + 0xD694, 0xC8BB, 0xD695, 0xC38F, 0xD696, 0xC390, 0xD697, 0xC391, 0xD698, 0xC392, 0xD699, 0xC393, 0xD69A, 0xC394, 0xD69B, 0xC395, + 0xD69C, 0xC396, 0xD69D, 0xC8BC, 0xD69E, 0xC397, 0xD69F, 0xC8BD, 0xD6A0, 0xC398, 0xD6A1, 0xC8BE, 0xD6A2, 0xC399, 0xD6A3, 0xC39A, + 0xD6A4, 0xC39B, 0xD6A5, 0xC39C, 0xD6A6, 0xC39D, 0xD6A7, 0xC39E, 0xD6A8, 0xC8BF, 0xD6A9, 0xC39F, 0xD6AA, 0xC3A0, 0xD6AB, 0xC441, + 0xD6AC, 0xC8C0, 0xD6AD, 0xC442, 0xD6AE, 0xC443, 0xD6AF, 0xC444, 0xD6B0, 0xC8C1, 0xD6B1, 0xC445, 0xD6B2, 0xC446, 0xD6B3, 0xC447, + 0xD6B4, 0xC448, 0xD6B5, 0xC449, 0xD6B6, 0xC44A, 0xD6B7, 0xC44B, 0xD6B8, 0xC44C, 0xD6B9, 0xC8C2, 0xD6BA, 0xC44D, 0xD6BB, 0xC8C3, + 0xD6BC, 0xC44E, 0xD6BD, 0xC44F, 0xD6BE, 0xC450, 0xD6BF, 0xC451, 0xD6C0, 0xC452, 0xD6C1, 0xC453, 0xD6C2, 0xC454, 0xD6C3, 0xC455, + 0xD6C4, 0xC8C4, 0xD6C5, 0xC8C5, 0xD6C6, 0xC456, 0xD6C7, 0xC457, 0xD6C8, 0xC8C6, 0xD6C9, 0xC458, 0xD6CA, 0xC459, 0xD6CB, 0xC45A, + 0xD6CC, 0xC8C7, 0xD6CD, 0xC461, 0xD6CE, 0xC462, 0xD6CF, 0xC463, 0xD6D0, 0xC464, 0xD6D1, 0xC8C8, 0xD6D2, 0xC465, 0xD6D3, 0xC466, + 0xD6D4, 0xC8C9, 0xD6D5, 0xC467, 0xD6D6, 0xC468, 0xD6D7, 0xC8CA, 0xD6D8, 0xC469, 0xD6D9, 0xC8CB, 0xD6DA, 0xC46A, 0xD6DB, 0xC46B, + 0xD6DC, 0xC46C, 0xD6DD, 0xC46D, 0xD6DE, 0xC46E, 0xD6DF, 0xC46F, 0xD6E0, 0xC8CC, 0xD6E1, 0xC470, 0xD6E2, 0xC471, 0xD6E3, 0xC472, + 0xD6E4, 0xC8CD, 0xD6E5, 0xC473, 0xD6E6, 0xC474, 0xD6E7, 0xC475, 0xD6E8, 0xC8CE, 0xD6E9, 0xC476, 0xD6EA, 0xC477, 0xD6EB, 0xC478, + 0xD6EC, 0xC479, 0xD6ED, 0xC47A, 0xD6EE, 0xC481, 0xD6EF, 0xC482, 0xD6F0, 0xC8CF, 0xD6F1, 0xC483, 0xD6F2, 0xC484, 0xD6F3, 0xC485, + 0xD6F4, 0xC486, 0xD6F5, 0xC8D0, 0xD6F6, 0xC487, 0xD6F7, 0xC488, 0xD6F8, 0xC489, 0xD6F9, 0xC48A, 0xD6FA, 0xC48B, 0xD6FB, 0xC48C, + 0xD6FC, 0xC8D1, 0xD6FD, 0xC8D2, 0xD6FE, 0xC48D, 0xD6FF, 0xC48E, 0xD700, 0xC8D3, 0xD701, 0xC48F, 0xD702, 0xC490, 0xD703, 0xC491, + 0xD704, 0xC8D4, 0xD705, 0xC492, 0xD706, 0xC493, 0xD707, 0xC494, 0xD708, 0xC495, 0xD709, 0xC496, 0xD70A, 0xC497, 0xD70B, 0xC498, + 0xD70C, 0xC499, 0xD70D, 0xC49A, 0xD70E, 0xC49B, 0xD70F, 0xC49C, 0xD710, 0xC49D, 0xD711, 0xC8D5, 0xD712, 0xC49E, 0xD713, 0xC49F, + 0xD714, 0xC4A0, 0xD715, 0xC541, 0xD716, 0xC542, 0xD717, 0xC543, 0xD718, 0xC8D6, 0xD719, 0xC8D7, 0xD71A, 0xC544, 0xD71B, 0xC545, + 0xD71C, 0xC8D8, 0xD71D, 0xC546, 0xD71E, 0xC547, 0xD71F, 0xC548, 0xD720, 0xC8D9, 0xD721, 0xC549, 0xD722, 0xC54A, 0xD723, 0xC54B, + 0xD724, 0xC54C, 0xD725, 0xC54D, 0xD726, 0xC54E, 0xD727, 0xC54F, 0xD728, 0xC8DA, 0xD729, 0xC8DB, 0xD72A, 0xC550, 0xD72B, 0xC8DC, + 0xD72C, 0xC551, 0xD72D, 0xC8DD, 0xD72E, 0xC552, 0xD72F, 0xC553, 0xD730, 0xC554, 0xD731, 0xC555, 0xD732, 0xC556, 0xD733, 0xC557, + 0xD734, 0xC8DE, 0xD735, 0xC8DF, 0xD736, 0xC558, 0xD737, 0xC559, 0xD738, 0xC8E0, 0xD739, 0xC55A, 0xD73A, 0xC561, 0xD73B, 0xC562, + 0xD73C, 0xC8E1, 0xD73D, 0xC563, 0xD73E, 0xC564, 0xD73F, 0xC565, 0xD740, 0xC566, 0xD741, 0xC567, 0xD742, 0xC568, 0xD743, 0xC569, + 0xD744, 0xC8E2, 0xD745, 0xC56A, 0xD746, 0xC56B, 0xD747, 0xC8E3, 0xD748, 0xC56C, 0xD749, 0xC8E4, 0xD74A, 0xC56D, 0xD74B, 0xC56E, + 0xD74C, 0xC56F, 0xD74D, 0xC570, 0xD74E, 0xC571, 0xD74F, 0xC572, 0xD750, 0xC8E5, 0xD751, 0xC8E6, 0xD752, 0xC573, 0xD753, 0xC574, + 0xD754, 0xC8E7, 0xD755, 0xC575, 0xD756, 0xC8E8, 0xD757, 0xC8E9, 0xD758, 0xC8EA, 0xD759, 0xC8EB, 0xD75A, 0xC576, 0xD75B, 0xC577, + 0xD75C, 0xC578, 0xD75D, 0xC579, 0xD75E, 0xC57A, 0xD75F, 0xC581, 0xD760, 0xC8EC, 0xD761, 0xC8ED, 0xD762, 0xC582, 0xD763, 0xC8EE, + 0xD764, 0xC583, 0xD765, 0xC8EF, 0xD766, 0xC584, 0xD767, 0xC585, 0xD768, 0xC586, 0xD769, 0xC8F0, 0xD76A, 0xC587, 0xD76B, 0xC588, + 0xD76C, 0xC8F1, 0xD76D, 0xC589, 0xD76E, 0xC58A, 0xD76F, 0xC58B, 0xD770, 0xC8F2, 0xD771, 0xC58C, 0xD772, 0xC58D, 0xD773, 0xC58E, + 0xD774, 0xC8F3, 0xD775, 0xC58F, 0xD776, 0xC590, 0xD777, 0xC591, 0xD778, 0xC592, 0xD779, 0xC593, 0xD77A, 0xC594, 0xD77B, 0xC595, + 0xD77C, 0xC8F4, 0xD77D, 0xC8F5, 0xD77E, 0xC596, 0xD77F, 0xC597, 0xD780, 0xC598, 0xD781, 0xC8F6, 0xD782, 0xC599, 0xD783, 0xC59A, + 0xD784, 0xC59B, 0xD785, 0xC59C, 0xD786, 0xC59D, 0xD787, 0xC59E, 0xD788, 0xC8F7, 0xD789, 0xC8F8, 0xD78A, 0xC59F, 0xD78B, 0xC5A0, + 0xD78C, 0xC8F9, 0xD78D, 0xC641, 0xD78E, 0xC642, 0xD78F, 0xC643, 0xD790, 0xC8FA, 0xD791, 0xC644, 0xD792, 0xC645, 0xD793, 0xC646, + 0xD794, 0xC647, 0xD795, 0xC648, 0xD796, 0xC649, 0xD797, 0xC64A, 0xD798, 0xC8FB, 0xD799, 0xC8FC, 0xD79A, 0xC64B, 0xD79B, 0xC8FD, + 0xD79C, 0xC64C, 0xD79D, 0xC8FE, 0xD79E, 0xC64D, 0xD79F, 0xC64E, 0xD7A0, 0xC64F, 0xD7A1, 0xC650, 0xD7A2, 0xC651, 0xD7A3, 0xC652, + 0xF900, 0xCBD0, 0xF901, 0xCBD6, 0xF902, 0xCBE7, 0xF903, 0xCDCF, 0xF904, 0xCDE8, 0xF905, 0xCEAD, 0xF906, 0xCFFB, 0xF907, 0xD0A2, + 0xF908, 0xD0B8, 0xF909, 0xD0D0, 0xF90A, 0xD0DD, 0xF90B, 0xD1D4, 0xF90C, 0xD1D5, 0xF90D, 0xD1D8, 0xF90E, 0xD1DB, 0xF90F, 0xD1DC, + 0xF910, 0xD1DD, 0xF911, 0xD1DE, 0xF912, 0xD1DF, 0xF913, 0xD1E0, 0xF914, 0xD1E2, 0xF915, 0xD1E3, 0xF916, 0xD1E4, 0xF917, 0xD1E5, + 0xF918, 0xD1E6, 0xF919, 0xD1E8, 0xF91A, 0xD1E9, 0xF91B, 0xD1EA, 0xF91C, 0xD1EB, 0xF91D, 0xD1ED, 0xF91E, 0xD1EF, 0xF91F, 0xD1F0, + 0xF920, 0xD1F2, 0xF921, 0xD1F6, 0xF922, 0xD1FA, 0xF923, 0xD1FC, 0xF924, 0xD1FD, 0xF925, 0xD1FE, 0xF926, 0xD2A2, 0xF927, 0xD2A3, + 0xF928, 0xD2A7, 0xF929, 0xD2A8, 0xF92A, 0xD2A9, 0xF92B, 0xD2AA, 0xF92C, 0xD2AB, 0xF92D, 0xD2AD, 0xF92E, 0xD2B2, 0xF92F, 0xD2BE, + 0xF930, 0xD2C2, 0xF931, 0xD2C3, 0xF932, 0xD2C4, 0xF933, 0xD2C6, 0xF934, 0xD2C7, 0xF935, 0xD2C8, 0xF936, 0xD2C9, 0xF937, 0xD2CA, + 0xF938, 0xD2CB, 0xF939, 0xD2CD, 0xF93A, 0xD2CE, 0xF93B, 0xD2CF, 0xF93C, 0xD2D0, 0xF93D, 0xD2D1, 0xF93E, 0xD2D2, 0xF93F, 0xD2D3, + 0xF940, 0xD2D4, 0xF941, 0xD2D5, 0xF942, 0xD2D6, 0xF943, 0xD2D7, 0xF944, 0xD2D9, 0xF945, 0xD2DA, 0xF946, 0xD2DE, 0xF947, 0xD2DF, + 0xF948, 0xD2E1, 0xF949, 0xD2E2, 0xF94A, 0xD2E4, 0xF94B, 0xD2E5, 0xF94C, 0xD2E6, 0xF94D, 0xD2E7, 0xF94E, 0xD2E8, 0xF94F, 0xD2E9, + 0xF950, 0xD2EA, 0xF951, 0xD2EB, 0xF952, 0xD2F0, 0xF953, 0xD2F1, 0xF954, 0xD2F2, 0xF955, 0xD2F3, 0xF956, 0xD2F4, 0xF957, 0xD2F5, + 0xF958, 0xD2F7, 0xF959, 0xD2F8, 0xF95A, 0xD4E6, 0xF95B, 0xD4FC, 0xF95C, 0xD5A5, 0xF95D, 0xD5AB, 0xF95E, 0xD5AE, 0xF95F, 0xD6B8, + 0xF960, 0xD6CD, 0xF961, 0xD7CB, 0xF962, 0xD7E4, 0xF963, 0xDBC5, 0xF964, 0xDBE4, 0xF965, 0xDCA5, 0xF966, 0xDDA5, 0xF967, 0xDDD5, + 0xF968, 0xDDF4, 0xF969, 0xDEFC, 0xF96A, 0xDEFE, 0xF96B, 0xDFB3, 0xF96C, 0xDFE1, 0xF96D, 0xDFE8, 0xF96E, 0xE0F1, 0xF96F, 0xE1AD, + 0xF970, 0xE1ED, 0xF971, 0xE3F5, 0xF972, 0xE4A1, 0xF973, 0xE4A9, 0xF974, 0xE5AE, 0xF975, 0xE5B1, 0xF976, 0xE5B2, 0xF977, 0xE5B9, + 0xF978, 0xE5BB, 0xF979, 0xE5BC, 0xF97A, 0xE5C4, 0xF97B, 0xE5CE, 0xF97C, 0xE5D0, 0xF97D, 0xE5D2, 0xF97E, 0xE5D6, 0xF97F, 0xE5FA, + 0xF980, 0xE5FB, 0xF981, 0xE5FC, 0xF982, 0xE5FE, 0xF983, 0xE6A1, 0xF984, 0xE6A4, 0xF985, 0xE6A7, 0xF986, 0xE6AD, 0xF987, 0xE6AF, + 0xF988, 0xE6B0, 0xF989, 0xE6B1, 0xF98A, 0xE6B3, 0xF98B, 0xE6B7, 0xF98C, 0xE6B8, 0xF98D, 0xE6BC, 0xF98E, 0xE6C4, 0xF98F, 0xE6C6, + 0xF990, 0xE6C7, 0xF991, 0xE6CA, 0xF992, 0xE6D2, 0xF993, 0xE6D6, 0xF994, 0xE6D9, 0xF995, 0xE6DC, 0xF996, 0xE6DF, 0xF997, 0xE6E1, + 0xF998, 0xE6E4, 0xF999, 0xE6E5, 0xF99A, 0xE6E6, 0xF99B, 0xE6E8, 0xF99C, 0xE6EA, 0xF99D, 0xE6EB, 0xF99E, 0xE6EC, 0xF99F, 0xE6EF, + 0xF9A0, 0xE6F1, 0xF9A1, 0xE6F2, 0xF9A2, 0xE6F5, 0xF9A3, 0xE6F6, 0xF9A4, 0xE6F7, 0xF9A5, 0xE6F9, 0xF9A6, 0xE7A1, 0xF9A7, 0xE7A6, + 0xF9A8, 0xE7A9, 0xF9A9, 0xE7AA, 0xF9AA, 0xE7AC, 0xF9AB, 0xE7AD, 0xF9AC, 0xE7B0, 0xF9AD, 0xE7BF, 0xF9AE, 0xE7C1, 0xF9AF, 0xE7C6, + 0xF9B0, 0xE7C7, 0xF9B1, 0xE7CB, 0xF9B2, 0xE7CD, 0xF9B3, 0xE7CF, 0xF9B4, 0xE7D0, 0xF9B5, 0xE7D3, 0xF9B6, 0xE7DF, 0xF9B7, 0xE7E4, + 0xF9B8, 0xE7E6, 0xF9B9, 0xE7F7, 0xF9BA, 0xE8E7, 0xF9BB, 0xE8E8, 0xF9BC, 0xE8F0, 0xF9BD, 0xE8F1, 0xF9BE, 0xE8F7, 0xF9BF, 0xE8F9, + 0xF9C0, 0xE8FB, 0xF9C1, 0xE8FE, 0xF9C2, 0xE9A7, 0xF9C3, 0xE9AC, 0xF9C4, 0xE9CC, 0xF9C5, 0xE9F7, 0xF9C6, 0xEAC1, 0xF9C7, 0xEAE5, + 0xF9C8, 0xEAF4, 0xF9C9, 0xEAF7, 0xF9CA, 0xEAFC, 0xF9CB, 0xEAFE, 0xF9CC, 0xEBA4, 0xF9CD, 0xEBA7, 0xF9CE, 0xEBA9, 0xF9CF, 0xEBAA, + 0xF9D0, 0xEBBA, 0xF9D1, 0xEBBB, 0xF9D2, 0xEBBD, 0xF9D3, 0xEBC1, 0xF9D4, 0xEBC2, 0xF9D5, 0xEBC6, 0xF9D6, 0xEBC7, 0xF9D7, 0xEBCC, + 0xF9D8, 0xEBCF, 0xF9D9, 0xEBD0, 0xF9DA, 0xEBD1, 0xF9DB, 0xEBD2, 0xF9DC, 0xEBD8, 0xF9DD, 0xECA6, 0xF9DE, 0xECA7, 0xF9DF, 0xECAA, + 0xF9E0, 0xECAF, 0xF9E1, 0xECB0, 0xF9E2, 0xECB1, 0xF9E3, 0xECB2, 0xF9E4, 0xECB5, 0xF9E5, 0xECB8, 0xF9E6, 0xECBA, 0xF9E7, 0xECC0, + 0xF9E8, 0xECC1, 0xF9E9, 0xECC5, 0xF9EA, 0xECC6, 0xF9EB, 0xECC9, 0xF9EC, 0xECCA, 0xF9ED, 0xECD5, 0xF9EE, 0xECDD, 0xF9EF, 0xECDE, + 0xF9F0, 0xECE1, 0xF9F1, 0xECE4, 0xF9F2, 0xECE7, 0xF9F3, 0xECE8, 0xF9F4, 0xECF7, 0xF9F5, 0xECF8, 0xF9F6, 0xECFA, 0xF9F7, 0xEDA1, + 0xF9F8, 0xEDA2, 0xF9F9, 0xEDA3, 0xF9FA, 0xEDEE, 0xF9FB, 0xEEDB, 0xF9FC, 0xF2BD, 0xF9FD, 0xF2FA, 0xF9FE, 0xF3B1, 0xF9FF, 0xF4A7, + 0xFA00, 0xF4EE, 0xFA01, 0xF6F4, 0xFA02, 0xF6F6, 0xFA03, 0xF7B8, 0xFA04, 0xF7C8, 0xFA05, 0xF7D3, 0xFA06, 0xF8DB, 0xFA07, 0xF8F0, + 0xFA08, 0xFAA1, 0xFA09, 0xFAA2, 0xFA0A, 0xFAE6, 0xFA0B, 0xFCA9, 0xFF01, 0xA3A1, 0xFF02, 0xA3A2, 0xFF03, 0xA3A3, 0xFF04, 0xA3A4, + 0xFF05, 0xA3A5, 0xFF06, 0xA3A6, 0xFF07, 0xA3A7, 0xFF08, 0xA3A8, 0xFF09, 0xA3A9, 0xFF0A, 0xA3AA, 0xFF0B, 0xA3AB, 0xFF0C, 0xA3AC, + 0xFF0D, 0xA3AD, 0xFF0E, 0xA3AE, 0xFF0F, 0xA3AF, 0xFF10, 0xA3B0, 0xFF11, 0xA3B1, 0xFF12, 0xA3B2, 0xFF13, 0xA3B3, 0xFF14, 0xA3B4, + 0xFF15, 0xA3B5, 0xFF16, 0xA3B6, 0xFF17, 0xA3B7, 0xFF18, 0xA3B8, 0xFF19, 0xA3B9, 0xFF1A, 0xA3BA, 0xFF1B, 0xA3BB, 0xFF1C, 0xA3BC, + 0xFF1D, 0xA3BD, 0xFF1E, 0xA3BE, 0xFF1F, 0xA3BF, 0xFF20, 0xA3C0, 0xFF21, 0xA3C1, 0xFF22, 0xA3C2, 0xFF23, 0xA3C3, 0xFF24, 0xA3C4, + 0xFF25, 0xA3C5, 0xFF26, 0xA3C6, 0xFF27, 0xA3C7, 0xFF28, 0xA3C8, 0xFF29, 0xA3C9, 0xFF2A, 0xA3CA, 0xFF2B, 0xA3CB, 0xFF2C, 0xA3CC, + 0xFF2D, 0xA3CD, 0xFF2E, 0xA3CE, 0xFF2F, 0xA3CF, 0xFF30, 0xA3D0, 0xFF31, 0xA3D1, 0xFF32, 0xA3D2, 0xFF33, 0xA3D3, 0xFF34, 0xA3D4, + 0xFF35, 0xA3D5, 0xFF36, 0xA3D6, 0xFF37, 0xA3D7, 0xFF38, 0xA3D8, 0xFF39, 0xA3D9, 0xFF3A, 0xA3DA, 0xFF3B, 0xA3DB, 0xFF3C, 0xA1AC, + 0xFF3D, 0xA3DD, 0xFF3E, 0xA3DE, 0xFF3F, 0xA3DF, 0xFF40, 0xA3E0, 0xFF41, 0xA3E1, 0xFF42, 0xA3E2, 0xFF43, 0xA3E3, 0xFF44, 0xA3E4, + 0xFF45, 0xA3E5, 0xFF46, 0xA3E6, 0xFF47, 0xA3E7, 0xFF48, 0xA3E8, 0xFF49, 0xA3E9, 0xFF4A, 0xA3EA, 0xFF4B, 0xA3EB, 0xFF4C, 0xA3EC, + 0xFF4D, 0xA3ED, 0xFF4E, 0xA3EE, 0xFF4F, 0xA3EF, 0xFF50, 0xA3F0, 0xFF51, 0xA3F1, 0xFF52, 0xA3F2, 0xFF53, 0xA3F3, 0xFF54, 0xA3F4, + 0xFF55, 0xA3F5, 0xFF56, 0xA3F6, 0xFF57, 0xA3F7, 0xFF58, 0xA3F8, 0xFF59, 0xA3F9, 0xFF5A, 0xA3FA, 0xFF5B, 0xA3FB, 0xFF5C, 0xA3FC, + 0xFF5D, 0xA3FD, 0xFF5E, 0xA2A6, 0xFFE0, 0xA1CB, 0xFFE1, 0xA1CC, 0xFFE2, 0xA1FE, 0xFFE3, 0xA3FE, 0xFFE5, 0xA1CD, 0xFFE6, 0xA3DC, + 0, 0 +}; + +static +const WCHAR oem2uni949[] = { /* Korean --> Unicode pairs */ + 0x8141, 0xAC02, 0x8142, 0xAC03, 0x8143, 0xAC05, 0x8144, 0xAC06, 0x8145, 0xAC0B, 0x8146, 0xAC0C, 0x8147, 0xAC0D, 0x8148, 0xAC0E, + 0x8149, 0xAC0F, 0x814A, 0xAC18, 0x814B, 0xAC1E, 0x814C, 0xAC1F, 0x814D, 0xAC21, 0x814E, 0xAC22, 0x814F, 0xAC23, 0x8150, 0xAC25, + 0x8151, 0xAC26, 0x8152, 0xAC27, 0x8153, 0xAC28, 0x8154, 0xAC29, 0x8155, 0xAC2A, 0x8156, 0xAC2B, 0x8157, 0xAC2E, 0x8158, 0xAC32, + 0x8159, 0xAC33, 0x815A, 0xAC34, 0x8161, 0xAC35, 0x8162, 0xAC36, 0x8163, 0xAC37, 0x8164, 0xAC3A, 0x8165, 0xAC3B, 0x8166, 0xAC3D, + 0x8167, 0xAC3E, 0x8168, 0xAC3F, 0x8169, 0xAC41, 0x816A, 0xAC42, 0x816B, 0xAC43, 0x816C, 0xAC44, 0x816D, 0xAC45, 0x816E, 0xAC46, + 0x816F, 0xAC47, 0x8170, 0xAC48, 0x8171, 0xAC49, 0x8172, 0xAC4A, 0x8173, 0xAC4C, 0x8174, 0xAC4E, 0x8175, 0xAC4F, 0x8176, 0xAC50, + 0x8177, 0xAC51, 0x8178, 0xAC52, 0x8179, 0xAC53, 0x817A, 0xAC55, 0x8181, 0xAC56, 0x8182, 0xAC57, 0x8183, 0xAC59, 0x8184, 0xAC5A, + 0x8185, 0xAC5B, 0x8186, 0xAC5D, 0x8187, 0xAC5E, 0x8188, 0xAC5F, 0x8189, 0xAC60, 0x818A, 0xAC61, 0x818B, 0xAC62, 0x818C, 0xAC63, + 0x818D, 0xAC64, 0x818E, 0xAC65, 0x818F, 0xAC66, 0x8190, 0xAC67, 0x8191, 0xAC68, 0x8192, 0xAC69, 0x8193, 0xAC6A, 0x8194, 0xAC6B, + 0x8195, 0xAC6C, 0x8196, 0xAC6D, 0x8197, 0xAC6E, 0x8198, 0xAC6F, 0x8199, 0xAC72, 0x819A, 0xAC73, 0x819B, 0xAC75, 0x819C, 0xAC76, + 0x819D, 0xAC79, 0x819E, 0xAC7B, 0x819F, 0xAC7C, 0x81A0, 0xAC7D, 0x81A1, 0xAC7E, 0x81A2, 0xAC7F, 0x81A3, 0xAC82, 0x81A4, 0xAC87, + 0x81A5, 0xAC88, 0x81A6, 0xAC8D, 0x81A7, 0xAC8E, 0x81A8, 0xAC8F, 0x81A9, 0xAC91, 0x81AA, 0xAC92, 0x81AB, 0xAC93, 0x81AC, 0xAC95, + 0x81AD, 0xAC96, 0x81AE, 0xAC97, 0x81AF, 0xAC98, 0x81B0, 0xAC99, 0x81B1, 0xAC9A, 0x81B2, 0xAC9B, 0x81B3, 0xAC9E, 0x81B4, 0xACA2, + 0x81B5, 0xACA3, 0x81B6, 0xACA4, 0x81B7, 0xACA5, 0x81B8, 0xACA6, 0x81B9, 0xACA7, 0x81BA, 0xACAB, 0x81BB, 0xACAD, 0x81BC, 0xACAE, + 0x81BD, 0xACB1, 0x81BE, 0xACB2, 0x81BF, 0xACB3, 0x81C0, 0xACB4, 0x81C1, 0xACB5, 0x81C2, 0xACB6, 0x81C3, 0xACB7, 0x81C4, 0xACBA, + 0x81C5, 0xACBE, 0x81C6, 0xACBF, 0x81C7, 0xACC0, 0x81C8, 0xACC2, 0x81C9, 0xACC3, 0x81CA, 0xACC5, 0x81CB, 0xACC6, 0x81CC, 0xACC7, + 0x81CD, 0xACC9, 0x81CE, 0xACCA, 0x81CF, 0xACCB, 0x81D0, 0xACCD, 0x81D1, 0xACCE, 0x81D2, 0xACCF, 0x81D3, 0xACD0, 0x81D4, 0xACD1, + 0x81D5, 0xACD2, 0x81D6, 0xACD3, 0x81D7, 0xACD4, 0x81D8, 0xACD6, 0x81D9, 0xACD8, 0x81DA, 0xACD9, 0x81DB, 0xACDA, 0x81DC, 0xACDB, + 0x81DD, 0xACDC, 0x81DE, 0xACDD, 0x81DF, 0xACDE, 0x81E0, 0xACDF, 0x81E1, 0xACE2, 0x81E2, 0xACE3, 0x81E3, 0xACE5, 0x81E4, 0xACE6, + 0x81E5, 0xACE9, 0x81E6, 0xACEB, 0x81E7, 0xACED, 0x81E8, 0xACEE, 0x81E9, 0xACF2, 0x81EA, 0xACF4, 0x81EB, 0xACF7, 0x81EC, 0xACF8, + 0x81ED, 0xACF9, 0x81EE, 0xACFA, 0x81EF, 0xACFB, 0x81F0, 0xACFE, 0x81F1, 0xACFF, 0x81F2, 0xAD01, 0x81F3, 0xAD02, 0x81F4, 0xAD03, + 0x81F5, 0xAD05, 0x81F6, 0xAD07, 0x81F7, 0xAD08, 0x81F8, 0xAD09, 0x81F9, 0xAD0A, 0x81FA, 0xAD0B, 0x81FB, 0xAD0E, 0x81FC, 0xAD10, + 0x81FD, 0xAD12, 0x81FE, 0xAD13, 0x8241, 0xAD14, 0x8242, 0xAD15, 0x8243, 0xAD16, 0x8244, 0xAD17, 0x8245, 0xAD19, 0x8246, 0xAD1A, + 0x8247, 0xAD1B, 0x8248, 0xAD1D, 0x8249, 0xAD1E, 0x824A, 0xAD1F, 0x824B, 0xAD21, 0x824C, 0xAD22, 0x824D, 0xAD23, 0x824E, 0xAD24, + 0x824F, 0xAD25, 0x8250, 0xAD26, 0x8251, 0xAD27, 0x8252, 0xAD28, 0x8253, 0xAD2A, 0x8254, 0xAD2B, 0x8255, 0xAD2E, 0x8256, 0xAD2F, + 0x8257, 0xAD30, 0x8258, 0xAD31, 0x8259, 0xAD32, 0x825A, 0xAD33, 0x8261, 0xAD36, 0x8262, 0xAD37, 0x8263, 0xAD39, 0x8264, 0xAD3A, + 0x8265, 0xAD3B, 0x8266, 0xAD3D, 0x8267, 0xAD3E, 0x8268, 0xAD3F, 0x8269, 0xAD40, 0x826A, 0xAD41, 0x826B, 0xAD42, 0x826C, 0xAD43, + 0x826D, 0xAD46, 0x826E, 0xAD48, 0x826F, 0xAD4A, 0x8270, 0xAD4B, 0x8271, 0xAD4C, 0x8272, 0xAD4D, 0x8273, 0xAD4E, 0x8274, 0xAD4F, + 0x8275, 0xAD51, 0x8276, 0xAD52, 0x8277, 0xAD53, 0x8278, 0xAD55, 0x8279, 0xAD56, 0x827A, 0xAD57, 0x8281, 0xAD59, 0x8282, 0xAD5A, + 0x8283, 0xAD5B, 0x8284, 0xAD5C, 0x8285, 0xAD5D, 0x8286, 0xAD5E, 0x8287, 0xAD5F, 0x8288, 0xAD60, 0x8289, 0xAD62, 0x828A, 0xAD64, + 0x828B, 0xAD65, 0x828C, 0xAD66, 0x828D, 0xAD67, 0x828E, 0xAD68, 0x828F, 0xAD69, 0x8290, 0xAD6A, 0x8291, 0xAD6B, 0x8292, 0xAD6E, + 0x8293, 0xAD6F, 0x8294, 0xAD71, 0x8295, 0xAD72, 0x8296, 0xAD77, 0x8297, 0xAD78, 0x8298, 0xAD79, 0x8299, 0xAD7A, 0x829A, 0xAD7E, + 0x829B, 0xAD80, 0x829C, 0xAD83, 0x829D, 0xAD84, 0x829E, 0xAD85, 0x829F, 0xAD86, 0x82A0, 0xAD87, 0x82A1, 0xAD8A, 0x82A2, 0xAD8B, + 0x82A3, 0xAD8D, 0x82A4, 0xAD8E, 0x82A5, 0xAD8F, 0x82A6, 0xAD91, 0x82A7, 0xAD92, 0x82A8, 0xAD93, 0x82A9, 0xAD94, 0x82AA, 0xAD95, + 0x82AB, 0xAD96, 0x82AC, 0xAD97, 0x82AD, 0xAD98, 0x82AE, 0xAD99, 0x82AF, 0xAD9A, 0x82B0, 0xAD9B, 0x82B1, 0xAD9E, 0x82B2, 0xAD9F, + 0x82B3, 0xADA0, 0x82B4, 0xADA1, 0x82B5, 0xADA2, 0x82B6, 0xADA3, 0x82B7, 0xADA5, 0x82B8, 0xADA6, 0x82B9, 0xADA7, 0x82BA, 0xADA8, + 0x82BB, 0xADA9, 0x82BC, 0xADAA, 0x82BD, 0xADAB, 0x82BE, 0xADAC, 0x82BF, 0xADAD, 0x82C0, 0xADAE, 0x82C1, 0xADAF, 0x82C2, 0xADB0, + 0x82C3, 0xADB1, 0x82C4, 0xADB2, 0x82C5, 0xADB3, 0x82C6, 0xADB4, 0x82C7, 0xADB5, 0x82C8, 0xADB6, 0x82C9, 0xADB8, 0x82CA, 0xADB9, + 0x82CB, 0xADBA, 0x82CC, 0xADBB, 0x82CD, 0xADBC, 0x82CE, 0xADBD, 0x82CF, 0xADBE, 0x82D0, 0xADBF, 0x82D1, 0xADC2, 0x82D2, 0xADC3, + 0x82D3, 0xADC5, 0x82D4, 0xADC6, 0x82D5, 0xADC7, 0x82D6, 0xADC9, 0x82D7, 0xADCA, 0x82D8, 0xADCB, 0x82D9, 0xADCC, 0x82DA, 0xADCD, + 0x82DB, 0xADCE, 0x82DC, 0xADCF, 0x82DD, 0xADD2, 0x82DE, 0xADD4, 0x82DF, 0xADD5, 0x82E0, 0xADD6, 0x82E1, 0xADD7, 0x82E2, 0xADD8, + 0x82E3, 0xADD9, 0x82E4, 0xADDA, 0x82E5, 0xADDB, 0x82E6, 0xADDD, 0x82E7, 0xADDE, 0x82E8, 0xADDF, 0x82E9, 0xADE1, 0x82EA, 0xADE2, + 0x82EB, 0xADE3, 0x82EC, 0xADE5, 0x82ED, 0xADE6, 0x82EE, 0xADE7, 0x82EF, 0xADE8, 0x82F0, 0xADE9, 0x82F1, 0xADEA, 0x82F2, 0xADEB, + 0x82F3, 0xADEC, 0x82F4, 0xADED, 0x82F5, 0xADEE, 0x82F6, 0xADEF, 0x82F7, 0xADF0, 0x82F8, 0xADF1, 0x82F9, 0xADF2, 0x82FA, 0xADF3, + 0x82FB, 0xADF4, 0x82FC, 0xADF5, 0x82FD, 0xADF6, 0x82FE, 0xADF7, 0x8341, 0xADFA, 0x8342, 0xADFB, 0x8343, 0xADFD, 0x8344, 0xADFE, + 0x8345, 0xAE02, 0x8346, 0xAE03, 0x8347, 0xAE04, 0x8348, 0xAE05, 0x8349, 0xAE06, 0x834A, 0xAE07, 0x834B, 0xAE0A, 0x834C, 0xAE0C, + 0x834D, 0xAE0E, 0x834E, 0xAE0F, 0x834F, 0xAE10, 0x8350, 0xAE11, 0x8351, 0xAE12, 0x8352, 0xAE13, 0x8353, 0xAE15, 0x8354, 0xAE16, + 0x8355, 0xAE17, 0x8356, 0xAE18, 0x8357, 0xAE19, 0x8358, 0xAE1A, 0x8359, 0xAE1B, 0x835A, 0xAE1C, 0x8361, 0xAE1D, 0x8362, 0xAE1E, + 0x8363, 0xAE1F, 0x8364, 0xAE20, 0x8365, 0xAE21, 0x8366, 0xAE22, 0x8367, 0xAE23, 0x8368, 0xAE24, 0x8369, 0xAE25, 0x836A, 0xAE26, + 0x836B, 0xAE27, 0x836C, 0xAE28, 0x836D, 0xAE29, 0x836E, 0xAE2A, 0x836F, 0xAE2B, 0x8370, 0xAE2C, 0x8371, 0xAE2D, 0x8372, 0xAE2E, + 0x8373, 0xAE2F, 0x8374, 0xAE32, 0x8375, 0xAE33, 0x8376, 0xAE35, 0x8377, 0xAE36, 0x8378, 0xAE39, 0x8379, 0xAE3B, 0x837A, 0xAE3C, + 0x8381, 0xAE3D, 0x8382, 0xAE3E, 0x8383, 0xAE3F, 0x8384, 0xAE42, 0x8385, 0xAE44, 0x8386, 0xAE47, 0x8387, 0xAE48, 0x8388, 0xAE49, + 0x8389, 0xAE4B, 0x838A, 0xAE4F, 0x838B, 0xAE51, 0x838C, 0xAE52, 0x838D, 0xAE53, 0x838E, 0xAE55, 0x838F, 0xAE57, 0x8390, 0xAE58, + 0x8391, 0xAE59, 0x8392, 0xAE5A, 0x8393, 0xAE5B, 0x8394, 0xAE5E, 0x8395, 0xAE62, 0x8396, 0xAE63, 0x8397, 0xAE64, 0x8398, 0xAE66, + 0x8399, 0xAE67, 0x839A, 0xAE6A, 0x839B, 0xAE6B, 0x839C, 0xAE6D, 0x839D, 0xAE6E, 0x839E, 0xAE6F, 0x839F, 0xAE71, 0x83A0, 0xAE72, + 0x83A1, 0xAE73, 0x83A2, 0xAE74, 0x83A3, 0xAE75, 0x83A4, 0xAE76, 0x83A5, 0xAE77, 0x83A6, 0xAE7A, 0x83A7, 0xAE7E, 0x83A8, 0xAE7F, + 0x83A9, 0xAE80, 0x83AA, 0xAE81, 0x83AB, 0xAE82, 0x83AC, 0xAE83, 0x83AD, 0xAE86, 0x83AE, 0xAE87, 0x83AF, 0xAE88, 0x83B0, 0xAE89, + 0x83B1, 0xAE8A, 0x83B2, 0xAE8B, 0x83B3, 0xAE8D, 0x83B4, 0xAE8E, 0x83B5, 0xAE8F, 0x83B6, 0xAE90, 0x83B7, 0xAE91, 0x83B8, 0xAE92, + 0x83B9, 0xAE93, 0x83BA, 0xAE94, 0x83BB, 0xAE95, 0x83BC, 0xAE96, 0x83BD, 0xAE97, 0x83BE, 0xAE98, 0x83BF, 0xAE99, 0x83C0, 0xAE9A, + 0x83C1, 0xAE9B, 0x83C2, 0xAE9C, 0x83C3, 0xAE9D, 0x83C4, 0xAE9E, 0x83C5, 0xAE9F, 0x83C6, 0xAEA0, 0x83C7, 0xAEA1, 0x83C8, 0xAEA2, + 0x83C9, 0xAEA3, 0x83CA, 0xAEA4, 0x83CB, 0xAEA5, 0x83CC, 0xAEA6, 0x83CD, 0xAEA7, 0x83CE, 0xAEA8, 0x83CF, 0xAEA9, 0x83D0, 0xAEAA, + 0x83D1, 0xAEAB, 0x83D2, 0xAEAC, 0x83D3, 0xAEAD, 0x83D4, 0xAEAE, 0x83D5, 0xAEAF, 0x83D6, 0xAEB0, 0x83D7, 0xAEB1, 0x83D8, 0xAEB2, + 0x83D9, 0xAEB3, 0x83DA, 0xAEB4, 0x83DB, 0xAEB5, 0x83DC, 0xAEB6, 0x83DD, 0xAEB7, 0x83DE, 0xAEB8, 0x83DF, 0xAEB9, 0x83E0, 0xAEBA, + 0x83E1, 0xAEBB, 0x83E2, 0xAEBF, 0x83E3, 0xAEC1, 0x83E4, 0xAEC2, 0x83E5, 0xAEC3, 0x83E6, 0xAEC5, 0x83E7, 0xAEC6, 0x83E8, 0xAEC7, + 0x83E9, 0xAEC8, 0x83EA, 0xAEC9, 0x83EB, 0xAECA, 0x83EC, 0xAECB, 0x83ED, 0xAECE, 0x83EE, 0xAED2, 0x83EF, 0xAED3, 0x83F0, 0xAED4, + 0x83F1, 0xAED5, 0x83F2, 0xAED6, 0x83F3, 0xAED7, 0x83F4, 0xAEDA, 0x83F5, 0xAEDB, 0x83F6, 0xAEDD, 0x83F7, 0xAEDE, 0x83F8, 0xAEDF, + 0x83F9, 0xAEE0, 0x83FA, 0xAEE1, 0x83FB, 0xAEE2, 0x83FC, 0xAEE3, 0x83FD, 0xAEE4, 0x83FE, 0xAEE5, 0x8441, 0xAEE6, 0x8442, 0xAEE7, + 0x8443, 0xAEE9, 0x8444, 0xAEEA, 0x8445, 0xAEEC, 0x8446, 0xAEEE, 0x8447, 0xAEEF, 0x8448, 0xAEF0, 0x8449, 0xAEF1, 0x844A, 0xAEF2, + 0x844B, 0xAEF3, 0x844C, 0xAEF5, 0x844D, 0xAEF6, 0x844E, 0xAEF7, 0x844F, 0xAEF9, 0x8450, 0xAEFA, 0x8451, 0xAEFB, 0x8452, 0xAEFD, + 0x8453, 0xAEFE, 0x8454, 0xAEFF, 0x8455, 0xAF00, 0x8456, 0xAF01, 0x8457, 0xAF02, 0x8458, 0xAF03, 0x8459, 0xAF04, 0x845A, 0xAF05, + 0x8461, 0xAF06, 0x8462, 0xAF09, 0x8463, 0xAF0A, 0x8464, 0xAF0B, 0x8465, 0xAF0C, 0x8466, 0xAF0E, 0x8467, 0xAF0F, 0x8468, 0xAF11, + 0x8469, 0xAF12, 0x846A, 0xAF13, 0x846B, 0xAF14, 0x846C, 0xAF15, 0x846D, 0xAF16, 0x846E, 0xAF17, 0x846F, 0xAF18, 0x8470, 0xAF19, + 0x8471, 0xAF1A, 0x8472, 0xAF1B, 0x8473, 0xAF1C, 0x8474, 0xAF1D, 0x8475, 0xAF1E, 0x8476, 0xAF1F, 0x8477, 0xAF20, 0x8478, 0xAF21, + 0x8479, 0xAF22, 0x847A, 0xAF23, 0x8481, 0xAF24, 0x8482, 0xAF25, 0x8483, 0xAF26, 0x8484, 0xAF27, 0x8485, 0xAF28, 0x8486, 0xAF29, + 0x8487, 0xAF2A, 0x8488, 0xAF2B, 0x8489, 0xAF2E, 0x848A, 0xAF2F, 0x848B, 0xAF31, 0x848C, 0xAF33, 0x848D, 0xAF35, 0x848E, 0xAF36, + 0x848F, 0xAF37, 0x8490, 0xAF38, 0x8491, 0xAF39, 0x8492, 0xAF3A, 0x8493, 0xAF3B, 0x8494, 0xAF3E, 0x8495, 0xAF40, 0x8496, 0xAF44, + 0x8497, 0xAF45, 0x8498, 0xAF46, 0x8499, 0xAF47, 0x849A, 0xAF4A, 0x849B, 0xAF4B, 0x849C, 0xAF4C, 0x849D, 0xAF4D, 0x849E, 0xAF4E, + 0x849F, 0xAF4F, 0x84A0, 0xAF51, 0x84A1, 0xAF52, 0x84A2, 0xAF53, 0x84A3, 0xAF54, 0x84A4, 0xAF55, 0x84A5, 0xAF56, 0x84A6, 0xAF57, + 0x84A7, 0xAF58, 0x84A8, 0xAF59, 0x84A9, 0xAF5A, 0x84AA, 0xAF5B, 0x84AB, 0xAF5E, 0x84AC, 0xAF5F, 0x84AD, 0xAF60, 0x84AE, 0xAF61, + 0x84AF, 0xAF62, 0x84B0, 0xAF63, 0x84B1, 0xAF66, 0x84B2, 0xAF67, 0x84B3, 0xAF68, 0x84B4, 0xAF69, 0x84B5, 0xAF6A, 0x84B6, 0xAF6B, + 0x84B7, 0xAF6C, 0x84B8, 0xAF6D, 0x84B9, 0xAF6E, 0x84BA, 0xAF6F, 0x84BB, 0xAF70, 0x84BC, 0xAF71, 0x84BD, 0xAF72, 0x84BE, 0xAF73, + 0x84BF, 0xAF74, 0x84C0, 0xAF75, 0x84C1, 0xAF76, 0x84C2, 0xAF77, 0x84C3, 0xAF78, 0x84C4, 0xAF7A, 0x84C5, 0xAF7B, 0x84C6, 0xAF7C, + 0x84C7, 0xAF7D, 0x84C8, 0xAF7E, 0x84C9, 0xAF7F, 0x84CA, 0xAF81, 0x84CB, 0xAF82, 0x84CC, 0xAF83, 0x84CD, 0xAF85, 0x84CE, 0xAF86, + 0x84CF, 0xAF87, 0x84D0, 0xAF89, 0x84D1, 0xAF8A, 0x84D2, 0xAF8B, 0x84D3, 0xAF8C, 0x84D4, 0xAF8D, 0x84D5, 0xAF8E, 0x84D6, 0xAF8F, + 0x84D7, 0xAF92, 0x84D8, 0xAF93, 0x84D9, 0xAF94, 0x84DA, 0xAF96, 0x84DB, 0xAF97, 0x84DC, 0xAF98, 0x84DD, 0xAF99, 0x84DE, 0xAF9A, + 0x84DF, 0xAF9B, 0x84E0, 0xAF9D, 0x84E1, 0xAF9E, 0x84E2, 0xAF9F, 0x84E3, 0xAFA0, 0x84E4, 0xAFA1, 0x84E5, 0xAFA2, 0x84E6, 0xAFA3, + 0x84E7, 0xAFA4, 0x84E8, 0xAFA5, 0x84E9, 0xAFA6, 0x84EA, 0xAFA7, 0x84EB, 0xAFA8, 0x84EC, 0xAFA9, 0x84ED, 0xAFAA, 0x84EE, 0xAFAB, + 0x84EF, 0xAFAC, 0x84F0, 0xAFAD, 0x84F1, 0xAFAE, 0x84F2, 0xAFAF, 0x84F3, 0xAFB0, 0x84F4, 0xAFB1, 0x84F5, 0xAFB2, 0x84F6, 0xAFB3, + 0x84F7, 0xAFB4, 0x84F8, 0xAFB5, 0x84F9, 0xAFB6, 0x84FA, 0xAFB7, 0x84FB, 0xAFBA, 0x84FC, 0xAFBB, 0x84FD, 0xAFBD, 0x84FE, 0xAFBE, + 0x8541, 0xAFBF, 0x8542, 0xAFC1, 0x8543, 0xAFC2, 0x8544, 0xAFC3, 0x8545, 0xAFC4, 0x8546, 0xAFC5, 0x8547, 0xAFC6, 0x8548, 0xAFCA, + 0x8549, 0xAFCC, 0x854A, 0xAFCF, 0x854B, 0xAFD0, 0x854C, 0xAFD1, 0x854D, 0xAFD2, 0x854E, 0xAFD3, 0x854F, 0xAFD5, 0x8550, 0xAFD6, + 0x8551, 0xAFD7, 0x8552, 0xAFD8, 0x8553, 0xAFD9, 0x8554, 0xAFDA, 0x8555, 0xAFDB, 0x8556, 0xAFDD, 0x8557, 0xAFDE, 0x8558, 0xAFDF, + 0x8559, 0xAFE0, 0x855A, 0xAFE1, 0x8561, 0xAFE2, 0x8562, 0xAFE3, 0x8563, 0xAFE4, 0x8564, 0xAFE5, 0x8565, 0xAFE6, 0x8566, 0xAFE7, + 0x8567, 0xAFEA, 0x8568, 0xAFEB, 0x8569, 0xAFEC, 0x856A, 0xAFED, 0x856B, 0xAFEE, 0x856C, 0xAFEF, 0x856D, 0xAFF2, 0x856E, 0xAFF3, + 0x856F, 0xAFF5, 0x8570, 0xAFF6, 0x8571, 0xAFF7, 0x8572, 0xAFF9, 0x8573, 0xAFFA, 0x8574, 0xAFFB, 0x8575, 0xAFFC, 0x8576, 0xAFFD, + 0x8577, 0xAFFE, 0x8578, 0xAFFF, 0x8579, 0xB002, 0x857A, 0xB003, 0x8581, 0xB005, 0x8582, 0xB006, 0x8583, 0xB007, 0x8584, 0xB008, + 0x8585, 0xB009, 0x8586, 0xB00A, 0x8587, 0xB00B, 0x8588, 0xB00D, 0x8589, 0xB00E, 0x858A, 0xB00F, 0x858B, 0xB011, 0x858C, 0xB012, + 0x858D, 0xB013, 0x858E, 0xB015, 0x858F, 0xB016, 0x8590, 0xB017, 0x8591, 0xB018, 0x8592, 0xB019, 0x8593, 0xB01A, 0x8594, 0xB01B, + 0x8595, 0xB01E, 0x8596, 0xB01F, 0x8597, 0xB020, 0x8598, 0xB021, 0x8599, 0xB022, 0x859A, 0xB023, 0x859B, 0xB024, 0x859C, 0xB025, + 0x859D, 0xB026, 0x859E, 0xB027, 0x859F, 0xB029, 0x85A0, 0xB02A, 0x85A1, 0xB02B, 0x85A2, 0xB02C, 0x85A3, 0xB02D, 0x85A4, 0xB02E, + 0x85A5, 0xB02F, 0x85A6, 0xB030, 0x85A7, 0xB031, 0x85A8, 0xB032, 0x85A9, 0xB033, 0x85AA, 0xB034, 0x85AB, 0xB035, 0x85AC, 0xB036, + 0x85AD, 0xB037, 0x85AE, 0xB038, 0x85AF, 0xB039, 0x85B0, 0xB03A, 0x85B1, 0xB03B, 0x85B2, 0xB03C, 0x85B3, 0xB03D, 0x85B4, 0xB03E, + 0x85B5, 0xB03F, 0x85B6, 0xB040, 0x85B7, 0xB041, 0x85B8, 0xB042, 0x85B9, 0xB043, 0x85BA, 0xB046, 0x85BB, 0xB047, 0x85BC, 0xB049, + 0x85BD, 0xB04B, 0x85BE, 0xB04D, 0x85BF, 0xB04F, 0x85C0, 0xB050, 0x85C1, 0xB051, 0x85C2, 0xB052, 0x85C3, 0xB056, 0x85C4, 0xB058, + 0x85C5, 0xB05A, 0x85C6, 0xB05B, 0x85C7, 0xB05C, 0x85C8, 0xB05E, 0x85C9, 0xB05F, 0x85CA, 0xB060, 0x85CB, 0xB061, 0x85CC, 0xB062, + 0x85CD, 0xB063, 0x85CE, 0xB064, 0x85CF, 0xB065, 0x85D0, 0xB066, 0x85D1, 0xB067, 0x85D2, 0xB068, 0x85D3, 0xB069, 0x85D4, 0xB06A, + 0x85D5, 0xB06B, 0x85D6, 0xB06C, 0x85D7, 0xB06D, 0x85D8, 0xB06E, 0x85D9, 0xB06F, 0x85DA, 0xB070, 0x85DB, 0xB071, 0x85DC, 0xB072, + 0x85DD, 0xB073, 0x85DE, 0xB074, 0x85DF, 0xB075, 0x85E0, 0xB076, 0x85E1, 0xB077, 0x85E2, 0xB078, 0x85E3, 0xB079, 0x85E4, 0xB07A, + 0x85E5, 0xB07B, 0x85E6, 0xB07E, 0x85E7, 0xB07F, 0x85E8, 0xB081, 0x85E9, 0xB082, 0x85EA, 0xB083, 0x85EB, 0xB085, 0x85EC, 0xB086, + 0x85ED, 0xB087, 0x85EE, 0xB088, 0x85EF, 0xB089, 0x85F0, 0xB08A, 0x85F1, 0xB08B, 0x85F2, 0xB08E, 0x85F3, 0xB090, 0x85F4, 0xB092, + 0x85F5, 0xB093, 0x85F6, 0xB094, 0x85F7, 0xB095, 0x85F8, 0xB096, 0x85F9, 0xB097, 0x85FA, 0xB09B, 0x85FB, 0xB09D, 0x85FC, 0xB09E, + 0x85FD, 0xB0A3, 0x85FE, 0xB0A4, 0x8641, 0xB0A5, 0x8642, 0xB0A6, 0x8643, 0xB0A7, 0x8644, 0xB0AA, 0x8645, 0xB0B0, 0x8646, 0xB0B2, + 0x8647, 0xB0B6, 0x8648, 0xB0B7, 0x8649, 0xB0B9, 0x864A, 0xB0BA, 0x864B, 0xB0BB, 0x864C, 0xB0BD, 0x864D, 0xB0BE, 0x864E, 0xB0BF, + 0x864F, 0xB0C0, 0x8650, 0xB0C1, 0x8651, 0xB0C2, 0x8652, 0xB0C3, 0x8653, 0xB0C6, 0x8654, 0xB0CA, 0x8655, 0xB0CB, 0x8656, 0xB0CC, + 0x8657, 0xB0CD, 0x8658, 0xB0CE, 0x8659, 0xB0CF, 0x865A, 0xB0D2, 0x8661, 0xB0D3, 0x8662, 0xB0D5, 0x8663, 0xB0D6, 0x8664, 0xB0D7, + 0x8665, 0xB0D9, 0x8666, 0xB0DA, 0x8667, 0xB0DB, 0x8668, 0xB0DC, 0x8669, 0xB0DD, 0x866A, 0xB0DE, 0x866B, 0xB0DF, 0x866C, 0xB0E1, + 0x866D, 0xB0E2, 0x866E, 0xB0E3, 0x866F, 0xB0E4, 0x8670, 0xB0E6, 0x8671, 0xB0E7, 0x8672, 0xB0E8, 0x8673, 0xB0E9, 0x8674, 0xB0EA, + 0x8675, 0xB0EB, 0x8676, 0xB0EC, 0x8677, 0xB0ED, 0x8678, 0xB0EE, 0x8679, 0xB0EF, 0x867A, 0xB0F0, 0x8681, 0xB0F1, 0x8682, 0xB0F2, + 0x8683, 0xB0F3, 0x8684, 0xB0F4, 0x8685, 0xB0F5, 0x8686, 0xB0F6, 0x8687, 0xB0F7, 0x8688, 0xB0F8, 0x8689, 0xB0F9, 0x868A, 0xB0FA, + 0x868B, 0xB0FB, 0x868C, 0xB0FC, 0x868D, 0xB0FD, 0x868E, 0xB0FE, 0x868F, 0xB0FF, 0x8690, 0xB100, 0x8691, 0xB101, 0x8692, 0xB102, + 0x8693, 0xB103, 0x8694, 0xB104, 0x8695, 0xB105, 0x8696, 0xB106, 0x8697, 0xB107, 0x8698, 0xB10A, 0x8699, 0xB10D, 0x869A, 0xB10E, + 0x869B, 0xB10F, 0x869C, 0xB111, 0x869D, 0xB114, 0x869E, 0xB115, 0x869F, 0xB116, 0x86A0, 0xB117, 0x86A1, 0xB11A, 0x86A2, 0xB11E, + 0x86A3, 0xB11F, 0x86A4, 0xB120, 0x86A5, 0xB121, 0x86A6, 0xB122, 0x86A7, 0xB126, 0x86A8, 0xB127, 0x86A9, 0xB129, 0x86AA, 0xB12A, + 0x86AB, 0xB12B, 0x86AC, 0xB12D, 0x86AD, 0xB12E, 0x86AE, 0xB12F, 0x86AF, 0xB130, 0x86B0, 0xB131, 0x86B1, 0xB132, 0x86B2, 0xB133, + 0x86B3, 0xB136, 0x86B4, 0xB13A, 0x86B5, 0xB13B, 0x86B6, 0xB13C, 0x86B7, 0xB13D, 0x86B8, 0xB13E, 0x86B9, 0xB13F, 0x86BA, 0xB142, + 0x86BB, 0xB143, 0x86BC, 0xB145, 0x86BD, 0xB146, 0x86BE, 0xB147, 0x86BF, 0xB149, 0x86C0, 0xB14A, 0x86C1, 0xB14B, 0x86C2, 0xB14C, + 0x86C3, 0xB14D, 0x86C4, 0xB14E, 0x86C5, 0xB14F, 0x86C6, 0xB152, 0x86C7, 0xB153, 0x86C8, 0xB156, 0x86C9, 0xB157, 0x86CA, 0xB159, + 0x86CB, 0xB15A, 0x86CC, 0xB15B, 0x86CD, 0xB15D, 0x86CE, 0xB15E, 0x86CF, 0xB15F, 0x86D0, 0xB161, 0x86D1, 0xB162, 0x86D2, 0xB163, + 0x86D3, 0xB164, 0x86D4, 0xB165, 0x86D5, 0xB166, 0x86D6, 0xB167, 0x86D7, 0xB168, 0x86D8, 0xB169, 0x86D9, 0xB16A, 0x86DA, 0xB16B, + 0x86DB, 0xB16C, 0x86DC, 0xB16D, 0x86DD, 0xB16E, 0x86DE, 0xB16F, 0x86DF, 0xB170, 0x86E0, 0xB171, 0x86E1, 0xB172, 0x86E2, 0xB173, + 0x86E3, 0xB174, 0x86E4, 0xB175, 0x86E5, 0xB176, 0x86E6, 0xB177, 0x86E7, 0xB17A, 0x86E8, 0xB17B, 0x86E9, 0xB17D, 0x86EA, 0xB17E, + 0x86EB, 0xB17F, 0x86EC, 0xB181, 0x86ED, 0xB183, 0x86EE, 0xB184, 0x86EF, 0xB185, 0x86F0, 0xB186, 0x86F1, 0xB187, 0x86F2, 0xB18A, + 0x86F3, 0xB18C, 0x86F4, 0xB18E, 0x86F5, 0xB18F, 0x86F6, 0xB190, 0x86F7, 0xB191, 0x86F8, 0xB195, 0x86F9, 0xB196, 0x86FA, 0xB197, + 0x86FB, 0xB199, 0x86FC, 0xB19A, 0x86FD, 0xB19B, 0x86FE, 0xB19D, 0x8741, 0xB19E, 0x8742, 0xB19F, 0x8743, 0xB1A0, 0x8744, 0xB1A1, + 0x8745, 0xB1A2, 0x8746, 0xB1A3, 0x8747, 0xB1A4, 0x8748, 0xB1A5, 0x8749, 0xB1A6, 0x874A, 0xB1A7, 0x874B, 0xB1A9, 0x874C, 0xB1AA, + 0x874D, 0xB1AB, 0x874E, 0xB1AC, 0x874F, 0xB1AD, 0x8750, 0xB1AE, 0x8751, 0xB1AF, 0x8752, 0xB1B0, 0x8753, 0xB1B1, 0x8754, 0xB1B2, + 0x8755, 0xB1B3, 0x8756, 0xB1B4, 0x8757, 0xB1B5, 0x8758, 0xB1B6, 0x8759, 0xB1B7, 0x875A, 0xB1B8, 0x8761, 0xB1B9, 0x8762, 0xB1BA, + 0x8763, 0xB1BB, 0x8764, 0xB1BC, 0x8765, 0xB1BD, 0x8766, 0xB1BE, 0x8767, 0xB1BF, 0x8768, 0xB1C0, 0x8769, 0xB1C1, 0x876A, 0xB1C2, + 0x876B, 0xB1C3, 0x876C, 0xB1C4, 0x876D, 0xB1C5, 0x876E, 0xB1C6, 0x876F, 0xB1C7, 0x8770, 0xB1C8, 0x8771, 0xB1C9, 0x8772, 0xB1CA, + 0x8773, 0xB1CB, 0x8774, 0xB1CD, 0x8775, 0xB1CE, 0x8776, 0xB1CF, 0x8777, 0xB1D1, 0x8778, 0xB1D2, 0x8779, 0xB1D3, 0x877A, 0xB1D5, + 0x8781, 0xB1D6, 0x8782, 0xB1D7, 0x8783, 0xB1D8, 0x8784, 0xB1D9, 0x8785, 0xB1DA, 0x8786, 0xB1DB, 0x8787, 0xB1DE, 0x8788, 0xB1E0, + 0x8789, 0xB1E1, 0x878A, 0xB1E2, 0x878B, 0xB1E3, 0x878C, 0xB1E4, 0x878D, 0xB1E5, 0x878E, 0xB1E6, 0x878F, 0xB1E7, 0x8790, 0xB1EA, + 0x8791, 0xB1EB, 0x8792, 0xB1ED, 0x8793, 0xB1EE, 0x8794, 0xB1EF, 0x8795, 0xB1F1, 0x8796, 0xB1F2, 0x8797, 0xB1F3, 0x8798, 0xB1F4, + 0x8799, 0xB1F5, 0x879A, 0xB1F6, 0x879B, 0xB1F7, 0x879C, 0xB1F8, 0x879D, 0xB1FA, 0x879E, 0xB1FC, 0x879F, 0xB1FE, 0x87A0, 0xB1FF, + 0x87A1, 0xB200, 0x87A2, 0xB201, 0x87A3, 0xB202, 0x87A4, 0xB203, 0x87A5, 0xB206, 0x87A6, 0xB207, 0x87A7, 0xB209, 0x87A8, 0xB20A, + 0x87A9, 0xB20D, 0x87AA, 0xB20E, 0x87AB, 0xB20F, 0x87AC, 0xB210, 0x87AD, 0xB211, 0x87AE, 0xB212, 0x87AF, 0xB213, 0x87B0, 0xB216, + 0x87B1, 0xB218, 0x87B2, 0xB21A, 0x87B3, 0xB21B, 0x87B4, 0xB21C, 0x87B5, 0xB21D, 0x87B6, 0xB21E, 0x87B7, 0xB21F, 0x87B8, 0xB221, + 0x87B9, 0xB222, 0x87BA, 0xB223, 0x87BB, 0xB224, 0x87BC, 0xB225, 0x87BD, 0xB226, 0x87BE, 0xB227, 0x87BF, 0xB228, 0x87C0, 0xB229, + 0x87C1, 0xB22A, 0x87C2, 0xB22B, 0x87C3, 0xB22C, 0x87C4, 0xB22D, 0x87C5, 0xB22E, 0x87C6, 0xB22F, 0x87C7, 0xB230, 0x87C8, 0xB231, + 0x87C9, 0xB232, 0x87CA, 0xB233, 0x87CB, 0xB235, 0x87CC, 0xB236, 0x87CD, 0xB237, 0x87CE, 0xB238, 0x87CF, 0xB239, 0x87D0, 0xB23A, + 0x87D1, 0xB23B, 0x87D2, 0xB23D, 0x87D3, 0xB23E, 0x87D4, 0xB23F, 0x87D5, 0xB240, 0x87D6, 0xB241, 0x87D7, 0xB242, 0x87D8, 0xB243, + 0x87D9, 0xB244, 0x87DA, 0xB245, 0x87DB, 0xB246, 0x87DC, 0xB247, 0x87DD, 0xB248, 0x87DE, 0xB249, 0x87DF, 0xB24A, 0x87E0, 0xB24B, + 0x87E1, 0xB24C, 0x87E2, 0xB24D, 0x87E3, 0xB24E, 0x87E4, 0xB24F, 0x87E5, 0xB250, 0x87E6, 0xB251, 0x87E7, 0xB252, 0x87E8, 0xB253, + 0x87E9, 0xB254, 0x87EA, 0xB255, 0x87EB, 0xB256, 0x87EC, 0xB257, 0x87ED, 0xB259, 0x87EE, 0xB25A, 0x87EF, 0xB25B, 0x87F0, 0xB25D, + 0x87F1, 0xB25E, 0x87F2, 0xB25F, 0x87F3, 0xB261, 0x87F4, 0xB262, 0x87F5, 0xB263, 0x87F6, 0xB264, 0x87F7, 0xB265, 0x87F8, 0xB266, + 0x87F9, 0xB267, 0x87FA, 0xB26A, 0x87FB, 0xB26B, 0x87FC, 0xB26C, 0x87FD, 0xB26D, 0x87FE, 0xB26E, 0x8841, 0xB26F, 0x8842, 0xB270, + 0x8843, 0xB271, 0x8844, 0xB272, 0x8845, 0xB273, 0x8846, 0xB276, 0x8847, 0xB277, 0x8848, 0xB278, 0x8849, 0xB279, 0x884A, 0xB27A, + 0x884B, 0xB27B, 0x884C, 0xB27D, 0x884D, 0xB27E, 0x884E, 0xB27F, 0x884F, 0xB280, 0x8850, 0xB281, 0x8851, 0xB282, 0x8852, 0xB283, + 0x8853, 0xB286, 0x8854, 0xB287, 0x8855, 0xB288, 0x8856, 0xB28A, 0x8857, 0xB28B, 0x8858, 0xB28C, 0x8859, 0xB28D, 0x885A, 0xB28E, + 0x8861, 0xB28F, 0x8862, 0xB292, 0x8863, 0xB293, 0x8864, 0xB295, 0x8865, 0xB296, 0x8866, 0xB297, 0x8867, 0xB29B, 0x8868, 0xB29C, + 0x8869, 0xB29D, 0x886A, 0xB29E, 0x886B, 0xB29F, 0x886C, 0xB2A2, 0x886D, 0xB2A4, 0x886E, 0xB2A7, 0x886F, 0xB2A8, 0x8870, 0xB2A9, + 0x8871, 0xB2AB, 0x8872, 0xB2AD, 0x8873, 0xB2AE, 0x8874, 0xB2AF, 0x8875, 0xB2B1, 0x8876, 0xB2B2, 0x8877, 0xB2B3, 0x8878, 0xB2B5, + 0x8879, 0xB2B6, 0x887A, 0xB2B7, 0x8881, 0xB2B8, 0x8882, 0xB2B9, 0x8883, 0xB2BA, 0x8884, 0xB2BB, 0x8885, 0xB2BC, 0x8886, 0xB2BD, + 0x8887, 0xB2BE, 0x8888, 0xB2BF, 0x8889, 0xB2C0, 0x888A, 0xB2C1, 0x888B, 0xB2C2, 0x888C, 0xB2C3, 0x888D, 0xB2C4, 0x888E, 0xB2C5, + 0x888F, 0xB2C6, 0x8890, 0xB2C7, 0x8891, 0xB2CA, 0x8892, 0xB2CB, 0x8893, 0xB2CD, 0x8894, 0xB2CE, 0x8895, 0xB2CF, 0x8896, 0xB2D1, + 0x8897, 0xB2D3, 0x8898, 0xB2D4, 0x8899, 0xB2D5, 0x889A, 0xB2D6, 0x889B, 0xB2D7, 0x889C, 0xB2DA, 0x889D, 0xB2DC, 0x889E, 0xB2DE, + 0x889F, 0xB2DF, 0x88A0, 0xB2E0, 0x88A1, 0xB2E1, 0x88A2, 0xB2E3, 0x88A3, 0xB2E7, 0x88A4, 0xB2E9, 0x88A5, 0xB2EA, 0x88A6, 0xB2F0, + 0x88A7, 0xB2F1, 0x88A8, 0xB2F2, 0x88A9, 0xB2F6, 0x88AA, 0xB2FC, 0x88AB, 0xB2FD, 0x88AC, 0xB2FE, 0x88AD, 0xB302, 0x88AE, 0xB303, + 0x88AF, 0xB305, 0x88B0, 0xB306, 0x88B1, 0xB307, 0x88B2, 0xB309, 0x88B3, 0xB30A, 0x88B4, 0xB30B, 0x88B5, 0xB30C, 0x88B6, 0xB30D, + 0x88B7, 0xB30E, 0x88B8, 0xB30F, 0x88B9, 0xB312, 0x88BA, 0xB316, 0x88BB, 0xB317, 0x88BC, 0xB318, 0x88BD, 0xB319, 0x88BE, 0xB31A, + 0x88BF, 0xB31B, 0x88C0, 0xB31D, 0x88C1, 0xB31E, 0x88C2, 0xB31F, 0x88C3, 0xB320, 0x88C4, 0xB321, 0x88C5, 0xB322, 0x88C6, 0xB323, + 0x88C7, 0xB324, 0x88C8, 0xB325, 0x88C9, 0xB326, 0x88CA, 0xB327, 0x88CB, 0xB328, 0x88CC, 0xB329, 0x88CD, 0xB32A, 0x88CE, 0xB32B, + 0x88CF, 0xB32C, 0x88D0, 0xB32D, 0x88D1, 0xB32E, 0x88D2, 0xB32F, 0x88D3, 0xB330, 0x88D4, 0xB331, 0x88D5, 0xB332, 0x88D6, 0xB333, + 0x88D7, 0xB334, 0x88D8, 0xB335, 0x88D9, 0xB336, 0x88DA, 0xB337, 0x88DB, 0xB338, 0x88DC, 0xB339, 0x88DD, 0xB33A, 0x88DE, 0xB33B, + 0x88DF, 0xB33C, 0x88E0, 0xB33D, 0x88E1, 0xB33E, 0x88E2, 0xB33F, 0x88E3, 0xB340, 0x88E4, 0xB341, 0x88E5, 0xB342, 0x88E6, 0xB343, + 0x88E7, 0xB344, 0x88E8, 0xB345, 0x88E9, 0xB346, 0x88EA, 0xB347, 0x88EB, 0xB348, 0x88EC, 0xB349, 0x88ED, 0xB34A, 0x88EE, 0xB34B, + 0x88EF, 0xB34C, 0x88F0, 0xB34D, 0x88F1, 0xB34E, 0x88F2, 0xB34F, 0x88F3, 0xB350, 0x88F4, 0xB351, 0x88F5, 0xB352, 0x88F6, 0xB353, + 0x88F7, 0xB357, 0x88F8, 0xB359, 0x88F9, 0xB35A, 0x88FA, 0xB35D, 0x88FB, 0xB360, 0x88FC, 0xB361, 0x88FD, 0xB362, 0x88FE, 0xB363, + 0x8941, 0xB366, 0x8942, 0xB368, 0x8943, 0xB36A, 0x8944, 0xB36C, 0x8945, 0xB36D, 0x8946, 0xB36F, 0x8947, 0xB372, 0x8948, 0xB373, + 0x8949, 0xB375, 0x894A, 0xB376, 0x894B, 0xB377, 0x894C, 0xB379, 0x894D, 0xB37A, 0x894E, 0xB37B, 0x894F, 0xB37C, 0x8950, 0xB37D, + 0x8951, 0xB37E, 0x8952, 0xB37F, 0x8953, 0xB382, 0x8954, 0xB386, 0x8955, 0xB387, 0x8956, 0xB388, 0x8957, 0xB389, 0x8958, 0xB38A, + 0x8959, 0xB38B, 0x895A, 0xB38D, 0x8961, 0xB38E, 0x8962, 0xB38F, 0x8963, 0xB391, 0x8964, 0xB392, 0x8965, 0xB393, 0x8966, 0xB395, + 0x8967, 0xB396, 0x8968, 0xB397, 0x8969, 0xB398, 0x896A, 0xB399, 0x896B, 0xB39A, 0x896C, 0xB39B, 0x896D, 0xB39C, 0x896E, 0xB39D, + 0x896F, 0xB39E, 0x8970, 0xB39F, 0x8971, 0xB3A2, 0x8972, 0xB3A3, 0x8973, 0xB3A4, 0x8974, 0xB3A5, 0x8975, 0xB3A6, 0x8976, 0xB3A7, + 0x8977, 0xB3A9, 0x8978, 0xB3AA, 0x8979, 0xB3AB, 0x897A, 0xB3AD, 0x8981, 0xB3AE, 0x8982, 0xB3AF, 0x8983, 0xB3B0, 0x8984, 0xB3B1, + 0x8985, 0xB3B2, 0x8986, 0xB3B3, 0x8987, 0xB3B4, 0x8988, 0xB3B5, 0x8989, 0xB3B6, 0x898A, 0xB3B7, 0x898B, 0xB3B8, 0x898C, 0xB3B9, + 0x898D, 0xB3BA, 0x898E, 0xB3BB, 0x898F, 0xB3BC, 0x8990, 0xB3BD, 0x8991, 0xB3BE, 0x8992, 0xB3BF, 0x8993, 0xB3C0, 0x8994, 0xB3C1, + 0x8995, 0xB3C2, 0x8996, 0xB3C3, 0x8997, 0xB3C6, 0x8998, 0xB3C7, 0x8999, 0xB3C9, 0x899A, 0xB3CA, 0x899B, 0xB3CD, 0x899C, 0xB3CF, + 0x899D, 0xB3D1, 0x899E, 0xB3D2, 0x899F, 0xB3D3, 0x89A0, 0xB3D6, 0x89A1, 0xB3D8, 0x89A2, 0xB3DA, 0x89A3, 0xB3DC, 0x89A4, 0xB3DE, + 0x89A5, 0xB3DF, 0x89A6, 0xB3E1, 0x89A7, 0xB3E2, 0x89A8, 0xB3E3, 0x89A9, 0xB3E5, 0x89AA, 0xB3E6, 0x89AB, 0xB3E7, 0x89AC, 0xB3E9, + 0x89AD, 0xB3EA, 0x89AE, 0xB3EB, 0x89AF, 0xB3EC, 0x89B0, 0xB3ED, 0x89B1, 0xB3EE, 0x89B2, 0xB3EF, 0x89B3, 0xB3F0, 0x89B4, 0xB3F1, + 0x89B5, 0xB3F2, 0x89B6, 0xB3F3, 0x89B7, 0xB3F4, 0x89B8, 0xB3F5, 0x89B9, 0xB3F6, 0x89BA, 0xB3F7, 0x89BB, 0xB3F8, 0x89BC, 0xB3F9, + 0x89BD, 0xB3FA, 0x89BE, 0xB3FB, 0x89BF, 0xB3FD, 0x89C0, 0xB3FE, 0x89C1, 0xB3FF, 0x89C2, 0xB400, 0x89C3, 0xB401, 0x89C4, 0xB402, + 0x89C5, 0xB403, 0x89C6, 0xB404, 0x89C7, 0xB405, 0x89C8, 0xB406, 0x89C9, 0xB407, 0x89CA, 0xB408, 0x89CB, 0xB409, 0x89CC, 0xB40A, + 0x89CD, 0xB40B, 0x89CE, 0xB40C, 0x89CF, 0xB40D, 0x89D0, 0xB40E, 0x89D1, 0xB40F, 0x89D2, 0xB411, 0x89D3, 0xB412, 0x89D4, 0xB413, + 0x89D5, 0xB414, 0x89D6, 0xB415, 0x89D7, 0xB416, 0x89D8, 0xB417, 0x89D9, 0xB419, 0x89DA, 0xB41A, 0x89DB, 0xB41B, 0x89DC, 0xB41D, + 0x89DD, 0xB41E, 0x89DE, 0xB41F, 0x89DF, 0xB421, 0x89E0, 0xB422, 0x89E1, 0xB423, 0x89E2, 0xB424, 0x89E3, 0xB425, 0x89E4, 0xB426, + 0x89E5, 0xB427, 0x89E6, 0xB42A, 0x89E7, 0xB42C, 0x89E8, 0xB42D, 0x89E9, 0xB42E, 0x89EA, 0xB42F, 0x89EB, 0xB430, 0x89EC, 0xB431, + 0x89ED, 0xB432, 0x89EE, 0xB433, 0x89EF, 0xB435, 0x89F0, 0xB436, 0x89F1, 0xB437, 0x89F2, 0xB438, 0x89F3, 0xB439, 0x89F4, 0xB43A, + 0x89F5, 0xB43B, 0x89F6, 0xB43C, 0x89F7, 0xB43D, 0x89F8, 0xB43E, 0x89F9, 0xB43F, 0x89FA, 0xB440, 0x89FB, 0xB441, 0x89FC, 0xB442, + 0x89FD, 0xB443, 0x89FE, 0xB444, 0x8A41, 0xB445, 0x8A42, 0xB446, 0x8A43, 0xB447, 0x8A44, 0xB448, 0x8A45, 0xB449, 0x8A46, 0xB44A, + 0x8A47, 0xB44B, 0x8A48, 0xB44C, 0x8A49, 0xB44D, 0x8A4A, 0xB44E, 0x8A4B, 0xB44F, 0x8A4C, 0xB452, 0x8A4D, 0xB453, 0x8A4E, 0xB455, + 0x8A4F, 0xB456, 0x8A50, 0xB457, 0x8A51, 0xB459, 0x8A52, 0xB45A, 0x8A53, 0xB45B, 0x8A54, 0xB45C, 0x8A55, 0xB45D, 0x8A56, 0xB45E, + 0x8A57, 0xB45F, 0x8A58, 0xB462, 0x8A59, 0xB464, 0x8A5A, 0xB466, 0x8A61, 0xB467, 0x8A62, 0xB468, 0x8A63, 0xB469, 0x8A64, 0xB46A, + 0x8A65, 0xB46B, 0x8A66, 0xB46D, 0x8A67, 0xB46E, 0x8A68, 0xB46F, 0x8A69, 0xB470, 0x8A6A, 0xB471, 0x8A6B, 0xB472, 0x8A6C, 0xB473, + 0x8A6D, 0xB474, 0x8A6E, 0xB475, 0x8A6F, 0xB476, 0x8A70, 0xB477, 0x8A71, 0xB478, 0x8A72, 0xB479, 0x8A73, 0xB47A, 0x8A74, 0xB47B, + 0x8A75, 0xB47C, 0x8A76, 0xB47D, 0x8A77, 0xB47E, 0x8A78, 0xB47F, 0x8A79, 0xB481, 0x8A7A, 0xB482, 0x8A81, 0xB483, 0x8A82, 0xB484, + 0x8A83, 0xB485, 0x8A84, 0xB486, 0x8A85, 0xB487, 0x8A86, 0xB489, 0x8A87, 0xB48A, 0x8A88, 0xB48B, 0x8A89, 0xB48C, 0x8A8A, 0xB48D, + 0x8A8B, 0xB48E, 0x8A8C, 0xB48F, 0x8A8D, 0xB490, 0x8A8E, 0xB491, 0x8A8F, 0xB492, 0x8A90, 0xB493, 0x8A91, 0xB494, 0x8A92, 0xB495, + 0x8A93, 0xB496, 0x8A94, 0xB497, 0x8A95, 0xB498, 0x8A96, 0xB499, 0x8A97, 0xB49A, 0x8A98, 0xB49B, 0x8A99, 0xB49C, 0x8A9A, 0xB49E, + 0x8A9B, 0xB49F, 0x8A9C, 0xB4A0, 0x8A9D, 0xB4A1, 0x8A9E, 0xB4A2, 0x8A9F, 0xB4A3, 0x8AA0, 0xB4A5, 0x8AA1, 0xB4A6, 0x8AA2, 0xB4A7, + 0x8AA3, 0xB4A9, 0x8AA4, 0xB4AA, 0x8AA5, 0xB4AB, 0x8AA6, 0xB4AD, 0x8AA7, 0xB4AE, 0x8AA8, 0xB4AF, 0x8AA9, 0xB4B0, 0x8AAA, 0xB4B1, + 0x8AAB, 0xB4B2, 0x8AAC, 0xB4B3, 0x8AAD, 0xB4B4, 0x8AAE, 0xB4B6, 0x8AAF, 0xB4B8, 0x8AB0, 0xB4BA, 0x8AB1, 0xB4BB, 0x8AB2, 0xB4BC, + 0x8AB3, 0xB4BD, 0x8AB4, 0xB4BE, 0x8AB5, 0xB4BF, 0x8AB6, 0xB4C1, 0x8AB7, 0xB4C2, 0x8AB8, 0xB4C3, 0x8AB9, 0xB4C5, 0x8ABA, 0xB4C6, + 0x8ABB, 0xB4C7, 0x8ABC, 0xB4C9, 0x8ABD, 0xB4CA, 0x8ABE, 0xB4CB, 0x8ABF, 0xB4CC, 0x8AC0, 0xB4CD, 0x8AC1, 0xB4CE, 0x8AC2, 0xB4CF, + 0x8AC3, 0xB4D1, 0x8AC4, 0xB4D2, 0x8AC5, 0xB4D3, 0x8AC6, 0xB4D4, 0x8AC7, 0xB4D6, 0x8AC8, 0xB4D7, 0x8AC9, 0xB4D8, 0x8ACA, 0xB4D9, + 0x8ACB, 0xB4DA, 0x8ACC, 0xB4DB, 0x8ACD, 0xB4DE, 0x8ACE, 0xB4DF, 0x8ACF, 0xB4E1, 0x8AD0, 0xB4E2, 0x8AD1, 0xB4E5, 0x8AD2, 0xB4E7, + 0x8AD3, 0xB4E8, 0x8AD4, 0xB4E9, 0x8AD5, 0xB4EA, 0x8AD6, 0xB4EB, 0x8AD7, 0xB4EE, 0x8AD8, 0xB4F0, 0x8AD9, 0xB4F2, 0x8ADA, 0xB4F3, + 0x8ADB, 0xB4F4, 0x8ADC, 0xB4F5, 0x8ADD, 0xB4F6, 0x8ADE, 0xB4F7, 0x8ADF, 0xB4F9, 0x8AE0, 0xB4FA, 0x8AE1, 0xB4FB, 0x8AE2, 0xB4FC, + 0x8AE3, 0xB4FD, 0x8AE4, 0xB4FE, 0x8AE5, 0xB4FF, 0x8AE6, 0xB500, 0x8AE7, 0xB501, 0x8AE8, 0xB502, 0x8AE9, 0xB503, 0x8AEA, 0xB504, + 0x8AEB, 0xB505, 0x8AEC, 0xB506, 0x8AED, 0xB507, 0x8AEE, 0xB508, 0x8AEF, 0xB509, 0x8AF0, 0xB50A, 0x8AF1, 0xB50B, 0x8AF2, 0xB50C, + 0x8AF3, 0xB50D, 0x8AF4, 0xB50E, 0x8AF5, 0xB50F, 0x8AF6, 0xB510, 0x8AF7, 0xB511, 0x8AF8, 0xB512, 0x8AF9, 0xB513, 0x8AFA, 0xB516, + 0x8AFB, 0xB517, 0x8AFC, 0xB519, 0x8AFD, 0xB51A, 0x8AFE, 0xB51D, 0x8B41, 0xB51E, 0x8B42, 0xB51F, 0x8B43, 0xB520, 0x8B44, 0xB521, + 0x8B45, 0xB522, 0x8B46, 0xB523, 0x8B47, 0xB526, 0x8B48, 0xB52B, 0x8B49, 0xB52C, 0x8B4A, 0xB52D, 0x8B4B, 0xB52E, 0x8B4C, 0xB52F, + 0x8B4D, 0xB532, 0x8B4E, 0xB533, 0x8B4F, 0xB535, 0x8B50, 0xB536, 0x8B51, 0xB537, 0x8B52, 0xB539, 0x8B53, 0xB53A, 0x8B54, 0xB53B, + 0x8B55, 0xB53C, 0x8B56, 0xB53D, 0x8B57, 0xB53E, 0x8B58, 0xB53F, 0x8B59, 0xB542, 0x8B5A, 0xB546, 0x8B61, 0xB547, 0x8B62, 0xB548, + 0x8B63, 0xB549, 0x8B64, 0xB54A, 0x8B65, 0xB54E, 0x8B66, 0xB54F, 0x8B67, 0xB551, 0x8B68, 0xB552, 0x8B69, 0xB553, 0x8B6A, 0xB555, + 0x8B6B, 0xB556, 0x8B6C, 0xB557, 0x8B6D, 0xB558, 0x8B6E, 0xB559, 0x8B6F, 0xB55A, 0x8B70, 0xB55B, 0x8B71, 0xB55E, 0x8B72, 0xB562, + 0x8B73, 0xB563, 0x8B74, 0xB564, 0x8B75, 0xB565, 0x8B76, 0xB566, 0x8B77, 0xB567, 0x8B78, 0xB568, 0x8B79, 0xB569, 0x8B7A, 0xB56A, + 0x8B81, 0xB56B, 0x8B82, 0xB56C, 0x8B83, 0xB56D, 0x8B84, 0xB56E, 0x8B85, 0xB56F, 0x8B86, 0xB570, 0x8B87, 0xB571, 0x8B88, 0xB572, + 0x8B89, 0xB573, 0x8B8A, 0xB574, 0x8B8B, 0xB575, 0x8B8C, 0xB576, 0x8B8D, 0xB577, 0x8B8E, 0xB578, 0x8B8F, 0xB579, 0x8B90, 0xB57A, + 0x8B91, 0xB57B, 0x8B92, 0xB57C, 0x8B93, 0xB57D, 0x8B94, 0xB57E, 0x8B95, 0xB57F, 0x8B96, 0xB580, 0x8B97, 0xB581, 0x8B98, 0xB582, + 0x8B99, 0xB583, 0x8B9A, 0xB584, 0x8B9B, 0xB585, 0x8B9C, 0xB586, 0x8B9D, 0xB587, 0x8B9E, 0xB588, 0x8B9F, 0xB589, 0x8BA0, 0xB58A, + 0x8BA1, 0xB58B, 0x8BA2, 0xB58C, 0x8BA3, 0xB58D, 0x8BA4, 0xB58E, 0x8BA5, 0xB58F, 0x8BA6, 0xB590, 0x8BA7, 0xB591, 0x8BA8, 0xB592, + 0x8BA9, 0xB593, 0x8BAA, 0xB594, 0x8BAB, 0xB595, 0x8BAC, 0xB596, 0x8BAD, 0xB597, 0x8BAE, 0xB598, 0x8BAF, 0xB599, 0x8BB0, 0xB59A, + 0x8BB1, 0xB59B, 0x8BB2, 0xB59C, 0x8BB3, 0xB59D, 0x8BB4, 0xB59E, 0x8BB5, 0xB59F, 0x8BB6, 0xB5A2, 0x8BB7, 0xB5A3, 0x8BB8, 0xB5A5, + 0x8BB9, 0xB5A6, 0x8BBA, 0xB5A7, 0x8BBB, 0xB5A9, 0x8BBC, 0xB5AC, 0x8BBD, 0xB5AD, 0x8BBE, 0xB5AE, 0x8BBF, 0xB5AF, 0x8BC0, 0xB5B2, + 0x8BC1, 0xB5B6, 0x8BC2, 0xB5B7, 0x8BC3, 0xB5B8, 0x8BC4, 0xB5B9, 0x8BC5, 0xB5BA, 0x8BC6, 0xB5BE, 0x8BC7, 0xB5BF, 0x8BC8, 0xB5C1, + 0x8BC9, 0xB5C2, 0x8BCA, 0xB5C3, 0x8BCB, 0xB5C5, 0x8BCC, 0xB5C6, 0x8BCD, 0xB5C7, 0x8BCE, 0xB5C8, 0x8BCF, 0xB5C9, 0x8BD0, 0xB5CA, + 0x8BD1, 0xB5CB, 0x8BD2, 0xB5CE, 0x8BD3, 0xB5D2, 0x8BD4, 0xB5D3, 0x8BD5, 0xB5D4, 0x8BD6, 0xB5D5, 0x8BD7, 0xB5D6, 0x8BD8, 0xB5D7, + 0x8BD9, 0xB5D9, 0x8BDA, 0xB5DA, 0x8BDB, 0xB5DB, 0x8BDC, 0xB5DC, 0x8BDD, 0xB5DD, 0x8BDE, 0xB5DE, 0x8BDF, 0xB5DF, 0x8BE0, 0xB5E0, + 0x8BE1, 0xB5E1, 0x8BE2, 0xB5E2, 0x8BE3, 0xB5E3, 0x8BE4, 0xB5E4, 0x8BE5, 0xB5E5, 0x8BE6, 0xB5E6, 0x8BE7, 0xB5E7, 0x8BE8, 0xB5E8, + 0x8BE9, 0xB5E9, 0x8BEA, 0xB5EA, 0x8BEB, 0xB5EB, 0x8BEC, 0xB5ED, 0x8BED, 0xB5EE, 0x8BEE, 0xB5EF, 0x8BEF, 0xB5F0, 0x8BF0, 0xB5F1, + 0x8BF1, 0xB5F2, 0x8BF2, 0xB5F3, 0x8BF3, 0xB5F4, 0x8BF4, 0xB5F5, 0x8BF5, 0xB5F6, 0x8BF6, 0xB5F7, 0x8BF7, 0xB5F8, 0x8BF8, 0xB5F9, + 0x8BF9, 0xB5FA, 0x8BFA, 0xB5FB, 0x8BFB, 0xB5FC, 0x8BFC, 0xB5FD, 0x8BFD, 0xB5FE, 0x8BFE, 0xB5FF, 0x8C41, 0xB600, 0x8C42, 0xB601, + 0x8C43, 0xB602, 0x8C44, 0xB603, 0x8C45, 0xB604, 0x8C46, 0xB605, 0x8C47, 0xB606, 0x8C48, 0xB607, 0x8C49, 0xB608, 0x8C4A, 0xB609, + 0x8C4B, 0xB60A, 0x8C4C, 0xB60B, 0x8C4D, 0xB60C, 0x8C4E, 0xB60D, 0x8C4F, 0xB60E, 0x8C50, 0xB60F, 0x8C51, 0xB612, 0x8C52, 0xB613, + 0x8C53, 0xB615, 0x8C54, 0xB616, 0x8C55, 0xB617, 0x8C56, 0xB619, 0x8C57, 0xB61A, 0x8C58, 0xB61B, 0x8C59, 0xB61C, 0x8C5A, 0xB61D, + 0x8C61, 0xB61E, 0x8C62, 0xB61F, 0x8C63, 0xB620, 0x8C64, 0xB621, 0x8C65, 0xB622, 0x8C66, 0xB623, 0x8C67, 0xB624, 0x8C68, 0xB626, + 0x8C69, 0xB627, 0x8C6A, 0xB628, 0x8C6B, 0xB629, 0x8C6C, 0xB62A, 0x8C6D, 0xB62B, 0x8C6E, 0xB62D, 0x8C6F, 0xB62E, 0x8C70, 0xB62F, + 0x8C71, 0xB630, 0x8C72, 0xB631, 0x8C73, 0xB632, 0x8C74, 0xB633, 0x8C75, 0xB635, 0x8C76, 0xB636, 0x8C77, 0xB637, 0x8C78, 0xB638, + 0x8C79, 0xB639, 0x8C7A, 0xB63A, 0x8C81, 0xB63B, 0x8C82, 0xB63C, 0x8C83, 0xB63D, 0x8C84, 0xB63E, 0x8C85, 0xB63F, 0x8C86, 0xB640, + 0x8C87, 0xB641, 0x8C88, 0xB642, 0x8C89, 0xB643, 0x8C8A, 0xB644, 0x8C8B, 0xB645, 0x8C8C, 0xB646, 0x8C8D, 0xB647, 0x8C8E, 0xB649, + 0x8C8F, 0xB64A, 0x8C90, 0xB64B, 0x8C91, 0xB64C, 0x8C92, 0xB64D, 0x8C93, 0xB64E, 0x8C94, 0xB64F, 0x8C95, 0xB650, 0x8C96, 0xB651, + 0x8C97, 0xB652, 0x8C98, 0xB653, 0x8C99, 0xB654, 0x8C9A, 0xB655, 0x8C9B, 0xB656, 0x8C9C, 0xB657, 0x8C9D, 0xB658, 0x8C9E, 0xB659, + 0x8C9F, 0xB65A, 0x8CA0, 0xB65B, 0x8CA1, 0xB65C, 0x8CA2, 0xB65D, 0x8CA3, 0xB65E, 0x8CA4, 0xB65F, 0x8CA5, 0xB660, 0x8CA6, 0xB661, + 0x8CA7, 0xB662, 0x8CA8, 0xB663, 0x8CA9, 0xB665, 0x8CAA, 0xB666, 0x8CAB, 0xB667, 0x8CAC, 0xB669, 0x8CAD, 0xB66A, 0x8CAE, 0xB66B, + 0x8CAF, 0xB66C, 0x8CB0, 0xB66D, 0x8CB1, 0xB66E, 0x8CB2, 0xB66F, 0x8CB3, 0xB670, 0x8CB4, 0xB671, 0x8CB5, 0xB672, 0x8CB6, 0xB673, + 0x8CB7, 0xB674, 0x8CB8, 0xB675, 0x8CB9, 0xB676, 0x8CBA, 0xB677, 0x8CBB, 0xB678, 0x8CBC, 0xB679, 0x8CBD, 0xB67A, 0x8CBE, 0xB67B, + 0x8CBF, 0xB67C, 0x8CC0, 0xB67D, 0x8CC1, 0xB67E, 0x8CC2, 0xB67F, 0x8CC3, 0xB680, 0x8CC4, 0xB681, 0x8CC5, 0xB682, 0x8CC6, 0xB683, + 0x8CC7, 0xB684, 0x8CC8, 0xB685, 0x8CC9, 0xB686, 0x8CCA, 0xB687, 0x8CCB, 0xB688, 0x8CCC, 0xB689, 0x8CCD, 0xB68A, 0x8CCE, 0xB68B, + 0x8CCF, 0xB68C, 0x8CD0, 0xB68D, 0x8CD1, 0xB68E, 0x8CD2, 0xB68F, 0x8CD3, 0xB690, 0x8CD4, 0xB691, 0x8CD5, 0xB692, 0x8CD6, 0xB693, + 0x8CD7, 0xB694, 0x8CD8, 0xB695, 0x8CD9, 0xB696, 0x8CDA, 0xB697, 0x8CDB, 0xB698, 0x8CDC, 0xB699, 0x8CDD, 0xB69A, 0x8CDE, 0xB69B, + 0x8CDF, 0xB69E, 0x8CE0, 0xB69F, 0x8CE1, 0xB6A1, 0x8CE2, 0xB6A2, 0x8CE3, 0xB6A3, 0x8CE4, 0xB6A5, 0x8CE5, 0xB6A6, 0x8CE6, 0xB6A7, + 0x8CE7, 0xB6A8, 0x8CE8, 0xB6A9, 0x8CE9, 0xB6AA, 0x8CEA, 0xB6AD, 0x8CEB, 0xB6AE, 0x8CEC, 0xB6AF, 0x8CED, 0xB6B0, 0x8CEE, 0xB6B2, + 0x8CEF, 0xB6B3, 0x8CF0, 0xB6B4, 0x8CF1, 0xB6B5, 0x8CF2, 0xB6B6, 0x8CF3, 0xB6B7, 0x8CF4, 0xB6B8, 0x8CF5, 0xB6B9, 0x8CF6, 0xB6BA, + 0x8CF7, 0xB6BB, 0x8CF8, 0xB6BC, 0x8CF9, 0xB6BD, 0x8CFA, 0xB6BE, 0x8CFB, 0xB6BF, 0x8CFC, 0xB6C0, 0x8CFD, 0xB6C1, 0x8CFE, 0xB6C2, + 0x8D41, 0xB6C3, 0x8D42, 0xB6C4, 0x8D43, 0xB6C5, 0x8D44, 0xB6C6, 0x8D45, 0xB6C7, 0x8D46, 0xB6C8, 0x8D47, 0xB6C9, 0x8D48, 0xB6CA, + 0x8D49, 0xB6CB, 0x8D4A, 0xB6CC, 0x8D4B, 0xB6CD, 0x8D4C, 0xB6CE, 0x8D4D, 0xB6CF, 0x8D4E, 0xB6D0, 0x8D4F, 0xB6D1, 0x8D50, 0xB6D2, + 0x8D51, 0xB6D3, 0x8D52, 0xB6D5, 0x8D53, 0xB6D6, 0x8D54, 0xB6D7, 0x8D55, 0xB6D8, 0x8D56, 0xB6D9, 0x8D57, 0xB6DA, 0x8D58, 0xB6DB, + 0x8D59, 0xB6DC, 0x8D5A, 0xB6DD, 0x8D61, 0xB6DE, 0x8D62, 0xB6DF, 0x8D63, 0xB6E0, 0x8D64, 0xB6E1, 0x8D65, 0xB6E2, 0x8D66, 0xB6E3, + 0x8D67, 0xB6E4, 0x8D68, 0xB6E5, 0x8D69, 0xB6E6, 0x8D6A, 0xB6E7, 0x8D6B, 0xB6E8, 0x8D6C, 0xB6E9, 0x8D6D, 0xB6EA, 0x8D6E, 0xB6EB, + 0x8D6F, 0xB6EC, 0x8D70, 0xB6ED, 0x8D71, 0xB6EE, 0x8D72, 0xB6EF, 0x8D73, 0xB6F1, 0x8D74, 0xB6F2, 0x8D75, 0xB6F3, 0x8D76, 0xB6F5, + 0x8D77, 0xB6F6, 0x8D78, 0xB6F7, 0x8D79, 0xB6F9, 0x8D7A, 0xB6FA, 0x8D81, 0xB6FB, 0x8D82, 0xB6FC, 0x8D83, 0xB6FD, 0x8D84, 0xB6FE, + 0x8D85, 0xB6FF, 0x8D86, 0xB702, 0x8D87, 0xB703, 0x8D88, 0xB704, 0x8D89, 0xB706, 0x8D8A, 0xB707, 0x8D8B, 0xB708, 0x8D8C, 0xB709, + 0x8D8D, 0xB70A, 0x8D8E, 0xB70B, 0x8D8F, 0xB70C, 0x8D90, 0xB70D, 0x8D91, 0xB70E, 0x8D92, 0xB70F, 0x8D93, 0xB710, 0x8D94, 0xB711, + 0x8D95, 0xB712, 0x8D96, 0xB713, 0x8D97, 0xB714, 0x8D98, 0xB715, 0x8D99, 0xB716, 0x8D9A, 0xB717, 0x8D9B, 0xB718, 0x8D9C, 0xB719, + 0x8D9D, 0xB71A, 0x8D9E, 0xB71B, 0x8D9F, 0xB71C, 0x8DA0, 0xB71D, 0x8DA1, 0xB71E, 0x8DA2, 0xB71F, 0x8DA3, 0xB720, 0x8DA4, 0xB721, + 0x8DA5, 0xB722, 0x8DA6, 0xB723, 0x8DA7, 0xB724, 0x8DA8, 0xB725, 0x8DA9, 0xB726, 0x8DAA, 0xB727, 0x8DAB, 0xB72A, 0x8DAC, 0xB72B, + 0x8DAD, 0xB72D, 0x8DAE, 0xB72E, 0x8DAF, 0xB731, 0x8DB0, 0xB732, 0x8DB1, 0xB733, 0x8DB2, 0xB734, 0x8DB3, 0xB735, 0x8DB4, 0xB736, + 0x8DB5, 0xB737, 0x8DB6, 0xB73A, 0x8DB7, 0xB73C, 0x8DB8, 0xB73D, 0x8DB9, 0xB73E, 0x8DBA, 0xB73F, 0x8DBB, 0xB740, 0x8DBC, 0xB741, + 0x8DBD, 0xB742, 0x8DBE, 0xB743, 0x8DBF, 0xB745, 0x8DC0, 0xB746, 0x8DC1, 0xB747, 0x8DC2, 0xB749, 0x8DC3, 0xB74A, 0x8DC4, 0xB74B, + 0x8DC5, 0xB74D, 0x8DC6, 0xB74E, 0x8DC7, 0xB74F, 0x8DC8, 0xB750, 0x8DC9, 0xB751, 0x8DCA, 0xB752, 0x8DCB, 0xB753, 0x8DCC, 0xB756, + 0x8DCD, 0xB757, 0x8DCE, 0xB758, 0x8DCF, 0xB759, 0x8DD0, 0xB75A, 0x8DD1, 0xB75B, 0x8DD2, 0xB75C, 0x8DD3, 0xB75D, 0x8DD4, 0xB75E, + 0x8DD5, 0xB75F, 0x8DD6, 0xB761, 0x8DD7, 0xB762, 0x8DD8, 0xB763, 0x8DD9, 0xB765, 0x8DDA, 0xB766, 0x8DDB, 0xB767, 0x8DDC, 0xB769, + 0x8DDD, 0xB76A, 0x8DDE, 0xB76B, 0x8DDF, 0xB76C, 0x8DE0, 0xB76D, 0x8DE1, 0xB76E, 0x8DE2, 0xB76F, 0x8DE3, 0xB772, 0x8DE4, 0xB774, + 0x8DE5, 0xB776, 0x8DE6, 0xB777, 0x8DE7, 0xB778, 0x8DE8, 0xB779, 0x8DE9, 0xB77A, 0x8DEA, 0xB77B, 0x8DEB, 0xB77E, 0x8DEC, 0xB77F, + 0x8DED, 0xB781, 0x8DEE, 0xB782, 0x8DEF, 0xB783, 0x8DF0, 0xB785, 0x8DF1, 0xB786, 0x8DF2, 0xB787, 0x8DF3, 0xB788, 0x8DF4, 0xB789, + 0x8DF5, 0xB78A, 0x8DF6, 0xB78B, 0x8DF7, 0xB78E, 0x8DF8, 0xB793, 0x8DF9, 0xB794, 0x8DFA, 0xB795, 0x8DFB, 0xB79A, 0x8DFC, 0xB79B, + 0x8DFD, 0xB79D, 0x8DFE, 0xB79E, 0x8E41, 0xB79F, 0x8E42, 0xB7A1, 0x8E43, 0xB7A2, 0x8E44, 0xB7A3, 0x8E45, 0xB7A4, 0x8E46, 0xB7A5, + 0x8E47, 0xB7A6, 0x8E48, 0xB7A7, 0x8E49, 0xB7AA, 0x8E4A, 0xB7AE, 0x8E4B, 0xB7AF, 0x8E4C, 0xB7B0, 0x8E4D, 0xB7B1, 0x8E4E, 0xB7B2, + 0x8E4F, 0xB7B3, 0x8E50, 0xB7B6, 0x8E51, 0xB7B7, 0x8E52, 0xB7B9, 0x8E53, 0xB7BA, 0x8E54, 0xB7BB, 0x8E55, 0xB7BC, 0x8E56, 0xB7BD, + 0x8E57, 0xB7BE, 0x8E58, 0xB7BF, 0x8E59, 0xB7C0, 0x8E5A, 0xB7C1, 0x8E61, 0xB7C2, 0x8E62, 0xB7C3, 0x8E63, 0xB7C4, 0x8E64, 0xB7C5, + 0x8E65, 0xB7C6, 0x8E66, 0xB7C8, 0x8E67, 0xB7CA, 0x8E68, 0xB7CB, 0x8E69, 0xB7CC, 0x8E6A, 0xB7CD, 0x8E6B, 0xB7CE, 0x8E6C, 0xB7CF, + 0x8E6D, 0xB7D0, 0x8E6E, 0xB7D1, 0x8E6F, 0xB7D2, 0x8E70, 0xB7D3, 0x8E71, 0xB7D4, 0x8E72, 0xB7D5, 0x8E73, 0xB7D6, 0x8E74, 0xB7D7, + 0x8E75, 0xB7D8, 0x8E76, 0xB7D9, 0x8E77, 0xB7DA, 0x8E78, 0xB7DB, 0x8E79, 0xB7DC, 0x8E7A, 0xB7DD, 0x8E81, 0xB7DE, 0x8E82, 0xB7DF, + 0x8E83, 0xB7E0, 0x8E84, 0xB7E1, 0x8E85, 0xB7E2, 0x8E86, 0xB7E3, 0x8E87, 0xB7E4, 0x8E88, 0xB7E5, 0x8E89, 0xB7E6, 0x8E8A, 0xB7E7, + 0x8E8B, 0xB7E8, 0x8E8C, 0xB7E9, 0x8E8D, 0xB7EA, 0x8E8E, 0xB7EB, 0x8E8F, 0xB7EE, 0x8E90, 0xB7EF, 0x8E91, 0xB7F1, 0x8E92, 0xB7F2, + 0x8E93, 0xB7F3, 0x8E94, 0xB7F5, 0x8E95, 0xB7F6, 0x8E96, 0xB7F7, 0x8E97, 0xB7F8, 0x8E98, 0xB7F9, 0x8E99, 0xB7FA, 0x8E9A, 0xB7FB, + 0x8E9B, 0xB7FE, 0x8E9C, 0xB802, 0x8E9D, 0xB803, 0x8E9E, 0xB804, 0x8E9F, 0xB805, 0x8EA0, 0xB806, 0x8EA1, 0xB80A, 0x8EA2, 0xB80B, + 0x8EA3, 0xB80D, 0x8EA4, 0xB80E, 0x8EA5, 0xB80F, 0x8EA6, 0xB811, 0x8EA7, 0xB812, 0x8EA8, 0xB813, 0x8EA9, 0xB814, 0x8EAA, 0xB815, + 0x8EAB, 0xB816, 0x8EAC, 0xB817, 0x8EAD, 0xB81A, 0x8EAE, 0xB81C, 0x8EAF, 0xB81E, 0x8EB0, 0xB81F, 0x8EB1, 0xB820, 0x8EB2, 0xB821, + 0x8EB3, 0xB822, 0x8EB4, 0xB823, 0x8EB5, 0xB826, 0x8EB6, 0xB827, 0x8EB7, 0xB829, 0x8EB8, 0xB82A, 0x8EB9, 0xB82B, 0x8EBA, 0xB82D, + 0x8EBB, 0xB82E, 0x8EBC, 0xB82F, 0x8EBD, 0xB830, 0x8EBE, 0xB831, 0x8EBF, 0xB832, 0x8EC0, 0xB833, 0x8EC1, 0xB836, 0x8EC2, 0xB83A, + 0x8EC3, 0xB83B, 0x8EC4, 0xB83C, 0x8EC5, 0xB83D, 0x8EC6, 0xB83E, 0x8EC7, 0xB83F, 0x8EC8, 0xB841, 0x8EC9, 0xB842, 0x8ECA, 0xB843, + 0x8ECB, 0xB845, 0x8ECC, 0xB846, 0x8ECD, 0xB847, 0x8ECE, 0xB848, 0x8ECF, 0xB849, 0x8ED0, 0xB84A, 0x8ED1, 0xB84B, 0x8ED2, 0xB84C, + 0x8ED3, 0xB84D, 0x8ED4, 0xB84E, 0x8ED5, 0xB84F, 0x8ED6, 0xB850, 0x8ED7, 0xB852, 0x8ED8, 0xB854, 0x8ED9, 0xB855, 0x8EDA, 0xB856, + 0x8EDB, 0xB857, 0x8EDC, 0xB858, 0x8EDD, 0xB859, 0x8EDE, 0xB85A, 0x8EDF, 0xB85B, 0x8EE0, 0xB85E, 0x8EE1, 0xB85F, 0x8EE2, 0xB861, + 0x8EE3, 0xB862, 0x8EE4, 0xB863, 0x8EE5, 0xB865, 0x8EE6, 0xB866, 0x8EE7, 0xB867, 0x8EE8, 0xB868, 0x8EE9, 0xB869, 0x8EEA, 0xB86A, + 0x8EEB, 0xB86B, 0x8EEC, 0xB86E, 0x8EED, 0xB870, 0x8EEE, 0xB872, 0x8EEF, 0xB873, 0x8EF0, 0xB874, 0x8EF1, 0xB875, 0x8EF2, 0xB876, + 0x8EF3, 0xB877, 0x8EF4, 0xB879, 0x8EF5, 0xB87A, 0x8EF6, 0xB87B, 0x8EF7, 0xB87D, 0x8EF8, 0xB87E, 0x8EF9, 0xB87F, 0x8EFA, 0xB880, + 0x8EFB, 0xB881, 0x8EFC, 0xB882, 0x8EFD, 0xB883, 0x8EFE, 0xB884, 0x8F41, 0xB885, 0x8F42, 0xB886, 0x8F43, 0xB887, 0x8F44, 0xB888, + 0x8F45, 0xB889, 0x8F46, 0xB88A, 0x8F47, 0xB88B, 0x8F48, 0xB88C, 0x8F49, 0xB88E, 0x8F4A, 0xB88F, 0x8F4B, 0xB890, 0x8F4C, 0xB891, + 0x8F4D, 0xB892, 0x8F4E, 0xB893, 0x8F4F, 0xB894, 0x8F50, 0xB895, 0x8F51, 0xB896, 0x8F52, 0xB897, 0x8F53, 0xB898, 0x8F54, 0xB899, + 0x8F55, 0xB89A, 0x8F56, 0xB89B, 0x8F57, 0xB89C, 0x8F58, 0xB89D, 0x8F59, 0xB89E, 0x8F5A, 0xB89F, 0x8F61, 0xB8A0, 0x8F62, 0xB8A1, + 0x8F63, 0xB8A2, 0x8F64, 0xB8A3, 0x8F65, 0xB8A4, 0x8F66, 0xB8A5, 0x8F67, 0xB8A6, 0x8F68, 0xB8A7, 0x8F69, 0xB8A9, 0x8F6A, 0xB8AA, + 0x8F6B, 0xB8AB, 0x8F6C, 0xB8AC, 0x8F6D, 0xB8AD, 0x8F6E, 0xB8AE, 0x8F6F, 0xB8AF, 0x8F70, 0xB8B1, 0x8F71, 0xB8B2, 0x8F72, 0xB8B3, + 0x8F73, 0xB8B5, 0x8F74, 0xB8B6, 0x8F75, 0xB8B7, 0x8F76, 0xB8B9, 0x8F77, 0xB8BA, 0x8F78, 0xB8BB, 0x8F79, 0xB8BC, 0x8F7A, 0xB8BD, + 0x8F81, 0xB8BE, 0x8F82, 0xB8BF, 0x8F83, 0xB8C2, 0x8F84, 0xB8C4, 0x8F85, 0xB8C6, 0x8F86, 0xB8C7, 0x8F87, 0xB8C8, 0x8F88, 0xB8C9, + 0x8F89, 0xB8CA, 0x8F8A, 0xB8CB, 0x8F8B, 0xB8CD, 0x8F8C, 0xB8CE, 0x8F8D, 0xB8CF, 0x8F8E, 0xB8D1, 0x8F8F, 0xB8D2, 0x8F90, 0xB8D3, + 0x8F91, 0xB8D5, 0x8F92, 0xB8D6, 0x8F93, 0xB8D7, 0x8F94, 0xB8D8, 0x8F95, 0xB8D9, 0x8F96, 0xB8DA, 0x8F97, 0xB8DB, 0x8F98, 0xB8DC, + 0x8F99, 0xB8DE, 0x8F9A, 0xB8E0, 0x8F9B, 0xB8E2, 0x8F9C, 0xB8E3, 0x8F9D, 0xB8E4, 0x8F9E, 0xB8E5, 0x8F9F, 0xB8E6, 0x8FA0, 0xB8E7, + 0x8FA1, 0xB8EA, 0x8FA2, 0xB8EB, 0x8FA3, 0xB8ED, 0x8FA4, 0xB8EE, 0x8FA5, 0xB8EF, 0x8FA6, 0xB8F1, 0x8FA7, 0xB8F2, 0x8FA8, 0xB8F3, + 0x8FA9, 0xB8F4, 0x8FAA, 0xB8F5, 0x8FAB, 0xB8F6, 0x8FAC, 0xB8F7, 0x8FAD, 0xB8FA, 0x8FAE, 0xB8FC, 0x8FAF, 0xB8FE, 0x8FB0, 0xB8FF, + 0x8FB1, 0xB900, 0x8FB2, 0xB901, 0x8FB3, 0xB902, 0x8FB4, 0xB903, 0x8FB5, 0xB905, 0x8FB6, 0xB906, 0x8FB7, 0xB907, 0x8FB8, 0xB908, + 0x8FB9, 0xB909, 0x8FBA, 0xB90A, 0x8FBB, 0xB90B, 0x8FBC, 0xB90C, 0x8FBD, 0xB90D, 0x8FBE, 0xB90E, 0x8FBF, 0xB90F, 0x8FC0, 0xB910, + 0x8FC1, 0xB911, 0x8FC2, 0xB912, 0x8FC3, 0xB913, 0x8FC4, 0xB914, 0x8FC5, 0xB915, 0x8FC6, 0xB916, 0x8FC7, 0xB917, 0x8FC8, 0xB919, + 0x8FC9, 0xB91A, 0x8FCA, 0xB91B, 0x8FCB, 0xB91C, 0x8FCC, 0xB91D, 0x8FCD, 0xB91E, 0x8FCE, 0xB91F, 0x8FCF, 0xB921, 0x8FD0, 0xB922, + 0x8FD1, 0xB923, 0x8FD2, 0xB924, 0x8FD3, 0xB925, 0x8FD4, 0xB926, 0x8FD5, 0xB927, 0x8FD6, 0xB928, 0x8FD7, 0xB929, 0x8FD8, 0xB92A, + 0x8FD9, 0xB92B, 0x8FDA, 0xB92C, 0x8FDB, 0xB92D, 0x8FDC, 0xB92E, 0x8FDD, 0xB92F, 0x8FDE, 0xB930, 0x8FDF, 0xB931, 0x8FE0, 0xB932, + 0x8FE1, 0xB933, 0x8FE2, 0xB934, 0x8FE3, 0xB935, 0x8FE4, 0xB936, 0x8FE5, 0xB937, 0x8FE6, 0xB938, 0x8FE7, 0xB939, 0x8FE8, 0xB93A, + 0x8FE9, 0xB93B, 0x8FEA, 0xB93E, 0x8FEB, 0xB93F, 0x8FEC, 0xB941, 0x8FED, 0xB942, 0x8FEE, 0xB943, 0x8FEF, 0xB945, 0x8FF0, 0xB946, + 0x8FF1, 0xB947, 0x8FF2, 0xB948, 0x8FF3, 0xB949, 0x8FF4, 0xB94A, 0x8FF5, 0xB94B, 0x8FF6, 0xB94D, 0x8FF7, 0xB94E, 0x8FF8, 0xB950, + 0x8FF9, 0xB952, 0x8FFA, 0xB953, 0x8FFB, 0xB954, 0x8FFC, 0xB955, 0x8FFD, 0xB956, 0x8FFE, 0xB957, 0x9041, 0xB95A, 0x9042, 0xB95B, + 0x9043, 0xB95D, 0x9044, 0xB95E, 0x9045, 0xB95F, 0x9046, 0xB961, 0x9047, 0xB962, 0x9048, 0xB963, 0x9049, 0xB964, 0x904A, 0xB965, + 0x904B, 0xB966, 0x904C, 0xB967, 0x904D, 0xB96A, 0x904E, 0xB96C, 0x904F, 0xB96E, 0x9050, 0xB96F, 0x9051, 0xB970, 0x9052, 0xB971, + 0x9053, 0xB972, 0x9054, 0xB973, 0x9055, 0xB976, 0x9056, 0xB977, 0x9057, 0xB979, 0x9058, 0xB97A, 0x9059, 0xB97B, 0x905A, 0xB97D, + 0x9061, 0xB97E, 0x9062, 0xB97F, 0x9063, 0xB980, 0x9064, 0xB981, 0x9065, 0xB982, 0x9066, 0xB983, 0x9067, 0xB986, 0x9068, 0xB988, + 0x9069, 0xB98B, 0x906A, 0xB98C, 0x906B, 0xB98F, 0x906C, 0xB990, 0x906D, 0xB991, 0x906E, 0xB992, 0x906F, 0xB993, 0x9070, 0xB994, + 0x9071, 0xB995, 0x9072, 0xB996, 0x9073, 0xB997, 0x9074, 0xB998, 0x9075, 0xB999, 0x9076, 0xB99A, 0x9077, 0xB99B, 0x9078, 0xB99C, + 0x9079, 0xB99D, 0x907A, 0xB99E, 0x9081, 0xB99F, 0x9082, 0xB9A0, 0x9083, 0xB9A1, 0x9084, 0xB9A2, 0x9085, 0xB9A3, 0x9086, 0xB9A4, + 0x9087, 0xB9A5, 0x9088, 0xB9A6, 0x9089, 0xB9A7, 0x908A, 0xB9A8, 0x908B, 0xB9A9, 0x908C, 0xB9AA, 0x908D, 0xB9AB, 0x908E, 0xB9AE, + 0x908F, 0xB9AF, 0x9090, 0xB9B1, 0x9091, 0xB9B2, 0x9092, 0xB9B3, 0x9093, 0xB9B5, 0x9094, 0xB9B6, 0x9095, 0xB9B7, 0x9096, 0xB9B8, + 0x9097, 0xB9B9, 0x9098, 0xB9BA, 0x9099, 0xB9BB, 0x909A, 0xB9BE, 0x909B, 0xB9C0, 0x909C, 0xB9C2, 0x909D, 0xB9C3, 0x909E, 0xB9C4, + 0x909F, 0xB9C5, 0x90A0, 0xB9C6, 0x90A1, 0xB9C7, 0x90A2, 0xB9CA, 0x90A3, 0xB9CB, 0x90A4, 0xB9CD, 0x90A5, 0xB9D3, 0x90A6, 0xB9D4, + 0x90A7, 0xB9D5, 0x90A8, 0xB9D6, 0x90A9, 0xB9D7, 0x90AA, 0xB9DA, 0x90AB, 0xB9DC, 0x90AC, 0xB9DF, 0x90AD, 0xB9E0, 0x90AE, 0xB9E2, + 0x90AF, 0xB9E6, 0x90B0, 0xB9E7, 0x90B1, 0xB9E9, 0x90B2, 0xB9EA, 0x90B3, 0xB9EB, 0x90B4, 0xB9ED, 0x90B5, 0xB9EE, 0x90B6, 0xB9EF, + 0x90B7, 0xB9F0, 0x90B8, 0xB9F1, 0x90B9, 0xB9F2, 0x90BA, 0xB9F3, 0x90BB, 0xB9F6, 0x90BC, 0xB9FB, 0x90BD, 0xB9FC, 0x90BE, 0xB9FD, + 0x90BF, 0xB9FE, 0x90C0, 0xB9FF, 0x90C1, 0xBA02, 0x90C2, 0xBA03, 0x90C3, 0xBA04, 0x90C4, 0xBA05, 0x90C5, 0xBA06, 0x90C6, 0xBA07, + 0x90C7, 0xBA09, 0x90C8, 0xBA0A, 0x90C9, 0xBA0B, 0x90CA, 0xBA0C, 0x90CB, 0xBA0D, 0x90CC, 0xBA0E, 0x90CD, 0xBA0F, 0x90CE, 0xBA10, + 0x90CF, 0xBA11, 0x90D0, 0xBA12, 0x90D1, 0xBA13, 0x90D2, 0xBA14, 0x90D3, 0xBA16, 0x90D4, 0xBA17, 0x90D5, 0xBA18, 0x90D6, 0xBA19, + 0x90D7, 0xBA1A, 0x90D8, 0xBA1B, 0x90D9, 0xBA1C, 0x90DA, 0xBA1D, 0x90DB, 0xBA1E, 0x90DC, 0xBA1F, 0x90DD, 0xBA20, 0x90DE, 0xBA21, + 0x90DF, 0xBA22, 0x90E0, 0xBA23, 0x90E1, 0xBA24, 0x90E2, 0xBA25, 0x90E3, 0xBA26, 0x90E4, 0xBA27, 0x90E5, 0xBA28, 0x90E6, 0xBA29, + 0x90E7, 0xBA2A, 0x90E8, 0xBA2B, 0x90E9, 0xBA2C, 0x90EA, 0xBA2D, 0x90EB, 0xBA2E, 0x90EC, 0xBA2F, 0x90ED, 0xBA30, 0x90EE, 0xBA31, + 0x90EF, 0xBA32, 0x90F0, 0xBA33, 0x90F1, 0xBA34, 0x90F2, 0xBA35, 0x90F3, 0xBA36, 0x90F4, 0xBA37, 0x90F5, 0xBA3A, 0x90F6, 0xBA3B, + 0x90F7, 0xBA3D, 0x90F8, 0xBA3E, 0x90F9, 0xBA3F, 0x90FA, 0xBA41, 0x90FB, 0xBA43, 0x90FC, 0xBA44, 0x90FD, 0xBA45, 0x90FE, 0xBA46, + 0x9141, 0xBA47, 0x9142, 0xBA4A, 0x9143, 0xBA4C, 0x9144, 0xBA4F, 0x9145, 0xBA50, 0x9146, 0xBA51, 0x9147, 0xBA52, 0x9148, 0xBA56, + 0x9149, 0xBA57, 0x914A, 0xBA59, 0x914B, 0xBA5A, 0x914C, 0xBA5B, 0x914D, 0xBA5D, 0x914E, 0xBA5E, 0x914F, 0xBA5F, 0x9150, 0xBA60, + 0x9151, 0xBA61, 0x9152, 0xBA62, 0x9153, 0xBA63, 0x9154, 0xBA66, 0x9155, 0xBA6A, 0x9156, 0xBA6B, 0x9157, 0xBA6C, 0x9158, 0xBA6D, + 0x9159, 0xBA6E, 0x915A, 0xBA6F, 0x9161, 0xBA72, 0x9162, 0xBA73, 0x9163, 0xBA75, 0x9164, 0xBA76, 0x9165, 0xBA77, 0x9166, 0xBA79, + 0x9167, 0xBA7A, 0x9168, 0xBA7B, 0x9169, 0xBA7C, 0x916A, 0xBA7D, 0x916B, 0xBA7E, 0x916C, 0xBA7F, 0x916D, 0xBA80, 0x916E, 0xBA81, + 0x916F, 0xBA82, 0x9170, 0xBA86, 0x9171, 0xBA88, 0x9172, 0xBA89, 0x9173, 0xBA8A, 0x9174, 0xBA8B, 0x9175, 0xBA8D, 0x9176, 0xBA8E, + 0x9177, 0xBA8F, 0x9178, 0xBA90, 0x9179, 0xBA91, 0x917A, 0xBA92, 0x9181, 0xBA93, 0x9182, 0xBA94, 0x9183, 0xBA95, 0x9184, 0xBA96, + 0x9185, 0xBA97, 0x9186, 0xBA98, 0x9187, 0xBA99, 0x9188, 0xBA9A, 0x9189, 0xBA9B, 0x918A, 0xBA9C, 0x918B, 0xBA9D, 0x918C, 0xBA9E, + 0x918D, 0xBA9F, 0x918E, 0xBAA0, 0x918F, 0xBAA1, 0x9190, 0xBAA2, 0x9191, 0xBAA3, 0x9192, 0xBAA4, 0x9193, 0xBAA5, 0x9194, 0xBAA6, + 0x9195, 0xBAA7, 0x9196, 0xBAAA, 0x9197, 0xBAAD, 0x9198, 0xBAAE, 0x9199, 0xBAAF, 0x919A, 0xBAB1, 0x919B, 0xBAB3, 0x919C, 0xBAB4, + 0x919D, 0xBAB5, 0x919E, 0xBAB6, 0x919F, 0xBAB7, 0x91A0, 0xBABA, 0x91A1, 0xBABC, 0x91A2, 0xBABE, 0x91A3, 0xBABF, 0x91A4, 0xBAC0, + 0x91A5, 0xBAC1, 0x91A6, 0xBAC2, 0x91A7, 0xBAC3, 0x91A8, 0xBAC5, 0x91A9, 0xBAC6, 0x91AA, 0xBAC7, 0x91AB, 0xBAC9, 0x91AC, 0xBACA, + 0x91AD, 0xBACB, 0x91AE, 0xBACC, 0x91AF, 0xBACD, 0x91B0, 0xBACE, 0x91B1, 0xBACF, 0x91B2, 0xBAD0, 0x91B3, 0xBAD1, 0x91B4, 0xBAD2, + 0x91B5, 0xBAD3, 0x91B6, 0xBAD4, 0x91B7, 0xBAD5, 0x91B8, 0xBAD6, 0x91B9, 0xBAD7, 0x91BA, 0xBADA, 0x91BB, 0xBADB, 0x91BC, 0xBADC, + 0x91BD, 0xBADD, 0x91BE, 0xBADE, 0x91BF, 0xBADF, 0x91C0, 0xBAE0, 0x91C1, 0xBAE1, 0x91C2, 0xBAE2, 0x91C3, 0xBAE3, 0x91C4, 0xBAE4, + 0x91C5, 0xBAE5, 0x91C6, 0xBAE6, 0x91C7, 0xBAE7, 0x91C8, 0xBAE8, 0x91C9, 0xBAE9, 0x91CA, 0xBAEA, 0x91CB, 0xBAEB, 0x91CC, 0xBAEC, + 0x91CD, 0xBAED, 0x91CE, 0xBAEE, 0x91CF, 0xBAEF, 0x91D0, 0xBAF0, 0x91D1, 0xBAF1, 0x91D2, 0xBAF2, 0x91D3, 0xBAF3, 0x91D4, 0xBAF4, + 0x91D5, 0xBAF5, 0x91D6, 0xBAF6, 0x91D7, 0xBAF7, 0x91D8, 0xBAF8, 0x91D9, 0xBAF9, 0x91DA, 0xBAFA, 0x91DB, 0xBAFB, 0x91DC, 0xBAFD, + 0x91DD, 0xBAFE, 0x91DE, 0xBAFF, 0x91DF, 0xBB01, 0x91E0, 0xBB02, 0x91E1, 0xBB03, 0x91E2, 0xBB05, 0x91E3, 0xBB06, 0x91E4, 0xBB07, + 0x91E5, 0xBB08, 0x91E6, 0xBB09, 0x91E7, 0xBB0A, 0x91E8, 0xBB0B, 0x91E9, 0xBB0C, 0x91EA, 0xBB0E, 0x91EB, 0xBB10, 0x91EC, 0xBB12, + 0x91ED, 0xBB13, 0x91EE, 0xBB14, 0x91EF, 0xBB15, 0x91F0, 0xBB16, 0x91F1, 0xBB17, 0x91F2, 0xBB19, 0x91F3, 0xBB1A, 0x91F4, 0xBB1B, + 0x91F5, 0xBB1D, 0x91F6, 0xBB1E, 0x91F7, 0xBB1F, 0x91F8, 0xBB21, 0x91F9, 0xBB22, 0x91FA, 0xBB23, 0x91FB, 0xBB24, 0x91FC, 0xBB25, + 0x91FD, 0xBB26, 0x91FE, 0xBB27, 0x9241, 0xBB28, 0x9242, 0xBB2A, 0x9243, 0xBB2C, 0x9244, 0xBB2D, 0x9245, 0xBB2E, 0x9246, 0xBB2F, + 0x9247, 0xBB30, 0x9248, 0xBB31, 0x9249, 0xBB32, 0x924A, 0xBB33, 0x924B, 0xBB37, 0x924C, 0xBB39, 0x924D, 0xBB3A, 0x924E, 0xBB3F, + 0x924F, 0xBB40, 0x9250, 0xBB41, 0x9251, 0xBB42, 0x9252, 0xBB43, 0x9253, 0xBB46, 0x9254, 0xBB48, 0x9255, 0xBB4A, 0x9256, 0xBB4B, + 0x9257, 0xBB4C, 0x9258, 0xBB4E, 0x9259, 0xBB51, 0x925A, 0xBB52, 0x9261, 0xBB53, 0x9262, 0xBB55, 0x9263, 0xBB56, 0x9264, 0xBB57, + 0x9265, 0xBB59, 0x9266, 0xBB5A, 0x9267, 0xBB5B, 0x9268, 0xBB5C, 0x9269, 0xBB5D, 0x926A, 0xBB5E, 0x926B, 0xBB5F, 0x926C, 0xBB60, + 0x926D, 0xBB62, 0x926E, 0xBB64, 0x926F, 0xBB65, 0x9270, 0xBB66, 0x9271, 0xBB67, 0x9272, 0xBB68, 0x9273, 0xBB69, 0x9274, 0xBB6A, + 0x9275, 0xBB6B, 0x9276, 0xBB6D, 0x9277, 0xBB6E, 0x9278, 0xBB6F, 0x9279, 0xBB70, 0x927A, 0xBB71, 0x9281, 0xBB72, 0x9282, 0xBB73, + 0x9283, 0xBB74, 0x9284, 0xBB75, 0x9285, 0xBB76, 0x9286, 0xBB77, 0x9287, 0xBB78, 0x9288, 0xBB79, 0x9289, 0xBB7A, 0x928A, 0xBB7B, + 0x928B, 0xBB7C, 0x928C, 0xBB7D, 0x928D, 0xBB7E, 0x928E, 0xBB7F, 0x928F, 0xBB80, 0x9290, 0xBB81, 0x9291, 0xBB82, 0x9292, 0xBB83, + 0x9293, 0xBB84, 0x9294, 0xBB85, 0x9295, 0xBB86, 0x9296, 0xBB87, 0x9297, 0xBB89, 0x9298, 0xBB8A, 0x9299, 0xBB8B, 0x929A, 0xBB8D, + 0x929B, 0xBB8E, 0x929C, 0xBB8F, 0x929D, 0xBB91, 0x929E, 0xBB92, 0x929F, 0xBB93, 0x92A0, 0xBB94, 0x92A1, 0xBB95, 0x92A2, 0xBB96, + 0x92A3, 0xBB97, 0x92A4, 0xBB98, 0x92A5, 0xBB99, 0x92A6, 0xBB9A, 0x92A7, 0xBB9B, 0x92A8, 0xBB9C, 0x92A9, 0xBB9D, 0x92AA, 0xBB9E, + 0x92AB, 0xBB9F, 0x92AC, 0xBBA0, 0x92AD, 0xBBA1, 0x92AE, 0xBBA2, 0x92AF, 0xBBA3, 0x92B0, 0xBBA5, 0x92B1, 0xBBA6, 0x92B2, 0xBBA7, + 0x92B3, 0xBBA9, 0x92B4, 0xBBAA, 0x92B5, 0xBBAB, 0x92B6, 0xBBAD, 0x92B7, 0xBBAE, 0x92B8, 0xBBAF, 0x92B9, 0xBBB0, 0x92BA, 0xBBB1, + 0x92BB, 0xBBB2, 0x92BC, 0xBBB3, 0x92BD, 0xBBB5, 0x92BE, 0xBBB6, 0x92BF, 0xBBB8, 0x92C0, 0xBBB9, 0x92C1, 0xBBBA, 0x92C2, 0xBBBB, + 0x92C3, 0xBBBC, 0x92C4, 0xBBBD, 0x92C5, 0xBBBE, 0x92C6, 0xBBBF, 0x92C7, 0xBBC1, 0x92C8, 0xBBC2, 0x92C9, 0xBBC3, 0x92CA, 0xBBC5, + 0x92CB, 0xBBC6, 0x92CC, 0xBBC7, 0x92CD, 0xBBC9, 0x92CE, 0xBBCA, 0x92CF, 0xBBCB, 0x92D0, 0xBBCC, 0x92D1, 0xBBCD, 0x92D2, 0xBBCE, + 0x92D3, 0xBBCF, 0x92D4, 0xBBD1, 0x92D5, 0xBBD2, 0x92D6, 0xBBD4, 0x92D7, 0xBBD5, 0x92D8, 0xBBD6, 0x92D9, 0xBBD7, 0x92DA, 0xBBD8, + 0x92DB, 0xBBD9, 0x92DC, 0xBBDA, 0x92DD, 0xBBDB, 0x92DE, 0xBBDC, 0x92DF, 0xBBDD, 0x92E0, 0xBBDE, 0x92E1, 0xBBDF, 0x92E2, 0xBBE0, + 0x92E3, 0xBBE1, 0x92E4, 0xBBE2, 0x92E5, 0xBBE3, 0x92E6, 0xBBE4, 0x92E7, 0xBBE5, 0x92E8, 0xBBE6, 0x92E9, 0xBBE7, 0x92EA, 0xBBE8, + 0x92EB, 0xBBE9, 0x92EC, 0xBBEA, 0x92ED, 0xBBEB, 0x92EE, 0xBBEC, 0x92EF, 0xBBED, 0x92F0, 0xBBEE, 0x92F1, 0xBBEF, 0x92F2, 0xBBF0, + 0x92F3, 0xBBF1, 0x92F4, 0xBBF2, 0x92F5, 0xBBF3, 0x92F6, 0xBBF4, 0x92F7, 0xBBF5, 0x92F8, 0xBBF6, 0x92F9, 0xBBF7, 0x92FA, 0xBBFA, + 0x92FB, 0xBBFB, 0x92FC, 0xBBFD, 0x92FD, 0xBBFE, 0x92FE, 0xBC01, 0x9341, 0xBC03, 0x9342, 0xBC04, 0x9343, 0xBC05, 0x9344, 0xBC06, + 0x9345, 0xBC07, 0x9346, 0xBC0A, 0x9347, 0xBC0E, 0x9348, 0xBC10, 0x9349, 0xBC12, 0x934A, 0xBC13, 0x934B, 0xBC19, 0x934C, 0xBC1A, + 0x934D, 0xBC20, 0x934E, 0xBC21, 0x934F, 0xBC22, 0x9350, 0xBC23, 0x9351, 0xBC26, 0x9352, 0xBC28, 0x9353, 0xBC2A, 0x9354, 0xBC2B, + 0x9355, 0xBC2C, 0x9356, 0xBC2E, 0x9357, 0xBC2F, 0x9358, 0xBC32, 0x9359, 0xBC33, 0x935A, 0xBC35, 0x9361, 0xBC36, 0x9362, 0xBC37, + 0x9363, 0xBC39, 0x9364, 0xBC3A, 0x9365, 0xBC3B, 0x9366, 0xBC3C, 0x9367, 0xBC3D, 0x9368, 0xBC3E, 0x9369, 0xBC3F, 0x936A, 0xBC42, + 0x936B, 0xBC46, 0x936C, 0xBC47, 0x936D, 0xBC48, 0x936E, 0xBC4A, 0x936F, 0xBC4B, 0x9370, 0xBC4E, 0x9371, 0xBC4F, 0x9372, 0xBC51, + 0x9373, 0xBC52, 0x9374, 0xBC53, 0x9375, 0xBC54, 0x9376, 0xBC55, 0x9377, 0xBC56, 0x9378, 0xBC57, 0x9379, 0xBC58, 0x937A, 0xBC59, + 0x9381, 0xBC5A, 0x9382, 0xBC5B, 0x9383, 0xBC5C, 0x9384, 0xBC5E, 0x9385, 0xBC5F, 0x9386, 0xBC60, 0x9387, 0xBC61, 0x9388, 0xBC62, + 0x9389, 0xBC63, 0x938A, 0xBC64, 0x938B, 0xBC65, 0x938C, 0xBC66, 0x938D, 0xBC67, 0x938E, 0xBC68, 0x938F, 0xBC69, 0x9390, 0xBC6A, + 0x9391, 0xBC6B, 0x9392, 0xBC6C, 0x9393, 0xBC6D, 0x9394, 0xBC6E, 0x9395, 0xBC6F, 0x9396, 0xBC70, 0x9397, 0xBC71, 0x9398, 0xBC72, + 0x9399, 0xBC73, 0x939A, 0xBC74, 0x939B, 0xBC75, 0x939C, 0xBC76, 0x939D, 0xBC77, 0x939E, 0xBC78, 0x939F, 0xBC79, 0x93A0, 0xBC7A, + 0x93A1, 0xBC7B, 0x93A2, 0xBC7C, 0x93A3, 0xBC7D, 0x93A4, 0xBC7E, 0x93A5, 0xBC7F, 0x93A6, 0xBC80, 0x93A7, 0xBC81, 0x93A8, 0xBC82, + 0x93A9, 0xBC83, 0x93AA, 0xBC86, 0x93AB, 0xBC87, 0x93AC, 0xBC89, 0x93AD, 0xBC8A, 0x93AE, 0xBC8D, 0x93AF, 0xBC8F, 0x93B0, 0xBC90, + 0x93B1, 0xBC91, 0x93B2, 0xBC92, 0x93B3, 0xBC93, 0x93B4, 0xBC96, 0x93B5, 0xBC98, 0x93B6, 0xBC9B, 0x93B7, 0xBC9C, 0x93B8, 0xBC9D, + 0x93B9, 0xBC9E, 0x93BA, 0xBC9F, 0x93BB, 0xBCA2, 0x93BC, 0xBCA3, 0x93BD, 0xBCA5, 0x93BE, 0xBCA6, 0x93BF, 0xBCA9, 0x93C0, 0xBCAA, + 0x93C1, 0xBCAB, 0x93C2, 0xBCAC, 0x93C3, 0xBCAD, 0x93C4, 0xBCAE, 0x93C5, 0xBCAF, 0x93C6, 0xBCB2, 0x93C7, 0xBCB6, 0x93C8, 0xBCB7, + 0x93C9, 0xBCB8, 0x93CA, 0xBCB9, 0x93CB, 0xBCBA, 0x93CC, 0xBCBB, 0x93CD, 0xBCBE, 0x93CE, 0xBCBF, 0x93CF, 0xBCC1, 0x93D0, 0xBCC2, + 0x93D1, 0xBCC3, 0x93D2, 0xBCC5, 0x93D3, 0xBCC6, 0x93D4, 0xBCC7, 0x93D5, 0xBCC8, 0x93D6, 0xBCC9, 0x93D7, 0xBCCA, 0x93D8, 0xBCCB, + 0x93D9, 0xBCCC, 0x93DA, 0xBCCE, 0x93DB, 0xBCD2, 0x93DC, 0xBCD3, 0x93DD, 0xBCD4, 0x93DE, 0xBCD6, 0x93DF, 0xBCD7, 0x93E0, 0xBCD9, + 0x93E1, 0xBCDA, 0x93E2, 0xBCDB, 0x93E3, 0xBCDD, 0x93E4, 0xBCDE, 0x93E5, 0xBCDF, 0x93E6, 0xBCE0, 0x93E7, 0xBCE1, 0x93E8, 0xBCE2, + 0x93E9, 0xBCE3, 0x93EA, 0xBCE4, 0x93EB, 0xBCE5, 0x93EC, 0xBCE6, 0x93ED, 0xBCE7, 0x93EE, 0xBCE8, 0x93EF, 0xBCE9, 0x93F0, 0xBCEA, + 0x93F1, 0xBCEB, 0x93F2, 0xBCEC, 0x93F3, 0xBCED, 0x93F4, 0xBCEE, 0x93F5, 0xBCEF, 0x93F6, 0xBCF0, 0x93F7, 0xBCF1, 0x93F8, 0xBCF2, + 0x93F9, 0xBCF3, 0x93FA, 0xBCF7, 0x93FB, 0xBCF9, 0x93FC, 0xBCFA, 0x93FD, 0xBCFB, 0x93FE, 0xBCFD, 0x9441, 0xBCFE, 0x9442, 0xBCFF, + 0x9443, 0xBD00, 0x9444, 0xBD01, 0x9445, 0xBD02, 0x9446, 0xBD03, 0x9447, 0xBD06, 0x9448, 0xBD08, 0x9449, 0xBD0A, 0x944A, 0xBD0B, + 0x944B, 0xBD0C, 0x944C, 0xBD0D, 0x944D, 0xBD0E, 0x944E, 0xBD0F, 0x944F, 0xBD11, 0x9450, 0xBD12, 0x9451, 0xBD13, 0x9452, 0xBD15, + 0x9453, 0xBD16, 0x9454, 0xBD17, 0x9455, 0xBD18, 0x9456, 0xBD19, 0x9457, 0xBD1A, 0x9458, 0xBD1B, 0x9459, 0xBD1C, 0x945A, 0xBD1D, + 0x9461, 0xBD1E, 0x9462, 0xBD1F, 0x9463, 0xBD20, 0x9464, 0xBD21, 0x9465, 0xBD22, 0x9466, 0xBD23, 0x9467, 0xBD25, 0x9468, 0xBD26, + 0x9469, 0xBD27, 0x946A, 0xBD28, 0x946B, 0xBD29, 0x946C, 0xBD2A, 0x946D, 0xBD2B, 0x946E, 0xBD2D, 0x946F, 0xBD2E, 0x9470, 0xBD2F, + 0x9471, 0xBD30, 0x9472, 0xBD31, 0x9473, 0xBD32, 0x9474, 0xBD33, 0x9475, 0xBD34, 0x9476, 0xBD35, 0x9477, 0xBD36, 0x9478, 0xBD37, + 0x9479, 0xBD38, 0x947A, 0xBD39, 0x9481, 0xBD3A, 0x9482, 0xBD3B, 0x9483, 0xBD3C, 0x9484, 0xBD3D, 0x9485, 0xBD3E, 0x9486, 0xBD3F, + 0x9487, 0xBD41, 0x9488, 0xBD42, 0x9489, 0xBD43, 0x948A, 0xBD44, 0x948B, 0xBD45, 0x948C, 0xBD46, 0x948D, 0xBD47, 0x948E, 0xBD4A, + 0x948F, 0xBD4B, 0x9490, 0xBD4D, 0x9491, 0xBD4E, 0x9492, 0xBD4F, 0x9493, 0xBD51, 0x9494, 0xBD52, 0x9495, 0xBD53, 0x9496, 0xBD54, + 0x9497, 0xBD55, 0x9498, 0xBD56, 0x9499, 0xBD57, 0x949A, 0xBD5A, 0x949B, 0xBD5B, 0x949C, 0xBD5C, 0x949D, 0xBD5D, 0x949E, 0xBD5E, + 0x949F, 0xBD5F, 0x94A0, 0xBD60, 0x94A1, 0xBD61, 0x94A2, 0xBD62, 0x94A3, 0xBD63, 0x94A4, 0xBD65, 0x94A5, 0xBD66, 0x94A6, 0xBD67, + 0x94A7, 0xBD69, 0x94A8, 0xBD6A, 0x94A9, 0xBD6B, 0x94AA, 0xBD6C, 0x94AB, 0xBD6D, 0x94AC, 0xBD6E, 0x94AD, 0xBD6F, 0x94AE, 0xBD70, + 0x94AF, 0xBD71, 0x94B0, 0xBD72, 0x94B1, 0xBD73, 0x94B2, 0xBD74, 0x94B3, 0xBD75, 0x94B4, 0xBD76, 0x94B5, 0xBD77, 0x94B6, 0xBD78, + 0x94B7, 0xBD79, 0x94B8, 0xBD7A, 0x94B9, 0xBD7B, 0x94BA, 0xBD7C, 0x94BB, 0xBD7D, 0x94BC, 0xBD7E, 0x94BD, 0xBD7F, 0x94BE, 0xBD82, + 0x94BF, 0xBD83, 0x94C0, 0xBD85, 0x94C1, 0xBD86, 0x94C2, 0xBD8B, 0x94C3, 0xBD8C, 0x94C4, 0xBD8D, 0x94C5, 0xBD8E, 0x94C6, 0xBD8F, + 0x94C7, 0xBD92, 0x94C8, 0xBD94, 0x94C9, 0xBD96, 0x94CA, 0xBD97, 0x94CB, 0xBD98, 0x94CC, 0xBD9B, 0x94CD, 0xBD9D, 0x94CE, 0xBD9E, + 0x94CF, 0xBD9F, 0x94D0, 0xBDA0, 0x94D1, 0xBDA1, 0x94D2, 0xBDA2, 0x94D3, 0xBDA3, 0x94D4, 0xBDA5, 0x94D5, 0xBDA6, 0x94D6, 0xBDA7, + 0x94D7, 0xBDA8, 0x94D8, 0xBDA9, 0x94D9, 0xBDAA, 0x94DA, 0xBDAB, 0x94DB, 0xBDAC, 0x94DC, 0xBDAD, 0x94DD, 0xBDAE, 0x94DE, 0xBDAF, + 0x94DF, 0xBDB1, 0x94E0, 0xBDB2, 0x94E1, 0xBDB3, 0x94E2, 0xBDB4, 0x94E3, 0xBDB5, 0x94E4, 0xBDB6, 0x94E5, 0xBDB7, 0x94E6, 0xBDB9, + 0x94E7, 0xBDBA, 0x94E8, 0xBDBB, 0x94E9, 0xBDBC, 0x94EA, 0xBDBD, 0x94EB, 0xBDBE, 0x94EC, 0xBDBF, 0x94ED, 0xBDC0, 0x94EE, 0xBDC1, + 0x94EF, 0xBDC2, 0x94F0, 0xBDC3, 0x94F1, 0xBDC4, 0x94F2, 0xBDC5, 0x94F3, 0xBDC6, 0x94F4, 0xBDC7, 0x94F5, 0xBDC8, 0x94F6, 0xBDC9, + 0x94F7, 0xBDCA, 0x94F8, 0xBDCB, 0x94F9, 0xBDCC, 0x94FA, 0xBDCD, 0x94FB, 0xBDCE, 0x94FC, 0xBDCF, 0x94FD, 0xBDD0, 0x94FE, 0xBDD1, + 0x9541, 0xBDD2, 0x9542, 0xBDD3, 0x9543, 0xBDD6, 0x9544, 0xBDD7, 0x9545, 0xBDD9, 0x9546, 0xBDDA, 0x9547, 0xBDDB, 0x9548, 0xBDDD, + 0x9549, 0xBDDE, 0x954A, 0xBDDF, 0x954B, 0xBDE0, 0x954C, 0xBDE1, 0x954D, 0xBDE2, 0x954E, 0xBDE3, 0x954F, 0xBDE4, 0x9550, 0xBDE5, + 0x9551, 0xBDE6, 0x9552, 0xBDE7, 0x9553, 0xBDE8, 0x9554, 0xBDEA, 0x9555, 0xBDEB, 0x9556, 0xBDEC, 0x9557, 0xBDED, 0x9558, 0xBDEE, + 0x9559, 0xBDEF, 0x955A, 0xBDF1, 0x9561, 0xBDF2, 0x9562, 0xBDF3, 0x9563, 0xBDF5, 0x9564, 0xBDF6, 0x9565, 0xBDF7, 0x9566, 0xBDF9, + 0x9567, 0xBDFA, 0x9568, 0xBDFB, 0x9569, 0xBDFC, 0x956A, 0xBDFD, 0x956B, 0xBDFE, 0x956C, 0xBDFF, 0x956D, 0xBE01, 0x956E, 0xBE02, + 0x956F, 0xBE04, 0x9570, 0xBE06, 0x9571, 0xBE07, 0x9572, 0xBE08, 0x9573, 0xBE09, 0x9574, 0xBE0A, 0x9575, 0xBE0B, 0x9576, 0xBE0E, + 0x9577, 0xBE0F, 0x9578, 0xBE11, 0x9579, 0xBE12, 0x957A, 0xBE13, 0x9581, 0xBE15, 0x9582, 0xBE16, 0x9583, 0xBE17, 0x9584, 0xBE18, + 0x9585, 0xBE19, 0x9586, 0xBE1A, 0x9587, 0xBE1B, 0x9588, 0xBE1E, 0x9589, 0xBE20, 0x958A, 0xBE21, 0x958B, 0xBE22, 0x958C, 0xBE23, + 0x958D, 0xBE24, 0x958E, 0xBE25, 0x958F, 0xBE26, 0x9590, 0xBE27, 0x9591, 0xBE28, 0x9592, 0xBE29, 0x9593, 0xBE2A, 0x9594, 0xBE2B, + 0x9595, 0xBE2C, 0x9596, 0xBE2D, 0x9597, 0xBE2E, 0x9598, 0xBE2F, 0x9599, 0xBE30, 0x959A, 0xBE31, 0x959B, 0xBE32, 0x959C, 0xBE33, + 0x959D, 0xBE34, 0x959E, 0xBE35, 0x959F, 0xBE36, 0x95A0, 0xBE37, 0x95A1, 0xBE38, 0x95A2, 0xBE39, 0x95A3, 0xBE3A, 0x95A4, 0xBE3B, + 0x95A5, 0xBE3C, 0x95A6, 0xBE3D, 0x95A7, 0xBE3E, 0x95A8, 0xBE3F, 0x95A9, 0xBE40, 0x95AA, 0xBE41, 0x95AB, 0xBE42, 0x95AC, 0xBE43, + 0x95AD, 0xBE46, 0x95AE, 0xBE47, 0x95AF, 0xBE49, 0x95B0, 0xBE4A, 0x95B1, 0xBE4B, 0x95B2, 0xBE4D, 0x95B3, 0xBE4F, 0x95B4, 0xBE50, + 0x95B5, 0xBE51, 0x95B6, 0xBE52, 0x95B7, 0xBE53, 0x95B8, 0xBE56, 0x95B9, 0xBE58, 0x95BA, 0xBE5C, 0x95BB, 0xBE5D, 0x95BC, 0xBE5E, + 0x95BD, 0xBE5F, 0x95BE, 0xBE62, 0x95BF, 0xBE63, 0x95C0, 0xBE65, 0x95C1, 0xBE66, 0x95C2, 0xBE67, 0x95C3, 0xBE69, 0x95C4, 0xBE6B, + 0x95C5, 0xBE6C, 0x95C6, 0xBE6D, 0x95C7, 0xBE6E, 0x95C8, 0xBE6F, 0x95C9, 0xBE72, 0x95CA, 0xBE76, 0x95CB, 0xBE77, 0x95CC, 0xBE78, + 0x95CD, 0xBE79, 0x95CE, 0xBE7A, 0x95CF, 0xBE7E, 0x95D0, 0xBE7F, 0x95D1, 0xBE81, 0x95D2, 0xBE82, 0x95D3, 0xBE83, 0x95D4, 0xBE85, + 0x95D5, 0xBE86, 0x95D6, 0xBE87, 0x95D7, 0xBE88, 0x95D8, 0xBE89, 0x95D9, 0xBE8A, 0x95DA, 0xBE8B, 0x95DB, 0xBE8E, 0x95DC, 0xBE92, + 0x95DD, 0xBE93, 0x95DE, 0xBE94, 0x95DF, 0xBE95, 0x95E0, 0xBE96, 0x95E1, 0xBE97, 0x95E2, 0xBE9A, 0x95E3, 0xBE9B, 0x95E4, 0xBE9C, + 0x95E5, 0xBE9D, 0x95E6, 0xBE9E, 0x95E7, 0xBE9F, 0x95E8, 0xBEA0, 0x95E9, 0xBEA1, 0x95EA, 0xBEA2, 0x95EB, 0xBEA3, 0x95EC, 0xBEA4, + 0x95ED, 0xBEA5, 0x95EE, 0xBEA6, 0x95EF, 0xBEA7, 0x95F0, 0xBEA9, 0x95F1, 0xBEAA, 0x95F2, 0xBEAB, 0x95F3, 0xBEAC, 0x95F4, 0xBEAD, + 0x95F5, 0xBEAE, 0x95F6, 0xBEAF, 0x95F7, 0xBEB0, 0x95F8, 0xBEB1, 0x95F9, 0xBEB2, 0x95FA, 0xBEB3, 0x95FB, 0xBEB4, 0x95FC, 0xBEB5, + 0x95FD, 0xBEB6, 0x95FE, 0xBEB7, 0x9641, 0xBEB8, 0x9642, 0xBEB9, 0x9643, 0xBEBA, 0x9644, 0xBEBB, 0x9645, 0xBEBC, 0x9646, 0xBEBD, + 0x9647, 0xBEBE, 0x9648, 0xBEBF, 0x9649, 0xBEC0, 0x964A, 0xBEC1, 0x964B, 0xBEC2, 0x964C, 0xBEC3, 0x964D, 0xBEC4, 0x964E, 0xBEC5, + 0x964F, 0xBEC6, 0x9650, 0xBEC7, 0x9651, 0xBEC8, 0x9652, 0xBEC9, 0x9653, 0xBECA, 0x9654, 0xBECB, 0x9655, 0xBECC, 0x9656, 0xBECD, + 0x9657, 0xBECE, 0x9658, 0xBECF, 0x9659, 0xBED2, 0x965A, 0xBED3, 0x9661, 0xBED5, 0x9662, 0xBED6, 0x9663, 0xBED9, 0x9664, 0xBEDA, + 0x9665, 0xBEDB, 0x9666, 0xBEDC, 0x9667, 0xBEDD, 0x9668, 0xBEDE, 0x9669, 0xBEDF, 0x966A, 0xBEE1, 0x966B, 0xBEE2, 0x966C, 0xBEE6, + 0x966D, 0xBEE7, 0x966E, 0xBEE8, 0x966F, 0xBEE9, 0x9670, 0xBEEA, 0x9671, 0xBEEB, 0x9672, 0xBEED, 0x9673, 0xBEEE, 0x9674, 0xBEEF, + 0x9675, 0xBEF0, 0x9676, 0xBEF1, 0x9677, 0xBEF2, 0x9678, 0xBEF3, 0x9679, 0xBEF4, 0x967A, 0xBEF5, 0x9681, 0xBEF6, 0x9682, 0xBEF7, + 0x9683, 0xBEF8, 0x9684, 0xBEF9, 0x9685, 0xBEFA, 0x9686, 0xBEFB, 0x9687, 0xBEFC, 0x9688, 0xBEFD, 0x9689, 0xBEFE, 0x968A, 0xBEFF, + 0x968B, 0xBF00, 0x968C, 0xBF02, 0x968D, 0xBF03, 0x968E, 0xBF04, 0x968F, 0xBF05, 0x9690, 0xBF06, 0x9691, 0xBF07, 0x9692, 0xBF0A, + 0x9693, 0xBF0B, 0x9694, 0xBF0C, 0x9695, 0xBF0D, 0x9696, 0xBF0E, 0x9697, 0xBF0F, 0x9698, 0xBF10, 0x9699, 0xBF11, 0x969A, 0xBF12, + 0x969B, 0xBF13, 0x969C, 0xBF14, 0x969D, 0xBF15, 0x969E, 0xBF16, 0x969F, 0xBF17, 0x96A0, 0xBF1A, 0x96A1, 0xBF1E, 0x96A2, 0xBF1F, + 0x96A3, 0xBF20, 0x96A4, 0xBF21, 0x96A5, 0xBF22, 0x96A6, 0xBF23, 0x96A7, 0xBF24, 0x96A8, 0xBF25, 0x96A9, 0xBF26, 0x96AA, 0xBF27, + 0x96AB, 0xBF28, 0x96AC, 0xBF29, 0x96AD, 0xBF2A, 0x96AE, 0xBF2B, 0x96AF, 0xBF2C, 0x96B0, 0xBF2D, 0x96B1, 0xBF2E, 0x96B2, 0xBF2F, + 0x96B3, 0xBF30, 0x96B4, 0xBF31, 0x96B5, 0xBF32, 0x96B6, 0xBF33, 0x96B7, 0xBF34, 0x96B8, 0xBF35, 0x96B9, 0xBF36, 0x96BA, 0xBF37, + 0x96BB, 0xBF38, 0x96BC, 0xBF39, 0x96BD, 0xBF3A, 0x96BE, 0xBF3B, 0x96BF, 0xBF3C, 0x96C0, 0xBF3D, 0x96C1, 0xBF3E, 0x96C2, 0xBF3F, + 0x96C3, 0xBF42, 0x96C4, 0xBF43, 0x96C5, 0xBF45, 0x96C6, 0xBF46, 0x96C7, 0xBF47, 0x96C8, 0xBF49, 0x96C9, 0xBF4A, 0x96CA, 0xBF4B, + 0x96CB, 0xBF4C, 0x96CC, 0xBF4D, 0x96CD, 0xBF4E, 0x96CE, 0xBF4F, 0x96CF, 0xBF52, 0x96D0, 0xBF53, 0x96D1, 0xBF54, 0x96D2, 0xBF56, + 0x96D3, 0xBF57, 0x96D4, 0xBF58, 0x96D5, 0xBF59, 0x96D6, 0xBF5A, 0x96D7, 0xBF5B, 0x96D8, 0xBF5C, 0x96D9, 0xBF5D, 0x96DA, 0xBF5E, + 0x96DB, 0xBF5F, 0x96DC, 0xBF60, 0x96DD, 0xBF61, 0x96DE, 0xBF62, 0x96DF, 0xBF63, 0x96E0, 0xBF64, 0x96E1, 0xBF65, 0x96E2, 0xBF66, + 0x96E3, 0xBF67, 0x96E4, 0xBF68, 0x96E5, 0xBF69, 0x96E6, 0xBF6A, 0x96E7, 0xBF6B, 0x96E8, 0xBF6C, 0x96E9, 0xBF6D, 0x96EA, 0xBF6E, + 0x96EB, 0xBF6F, 0x96EC, 0xBF70, 0x96ED, 0xBF71, 0x96EE, 0xBF72, 0x96EF, 0xBF73, 0x96F0, 0xBF74, 0x96F1, 0xBF75, 0x96F2, 0xBF76, + 0x96F3, 0xBF77, 0x96F4, 0xBF78, 0x96F5, 0xBF79, 0x96F6, 0xBF7A, 0x96F7, 0xBF7B, 0x96F8, 0xBF7C, 0x96F9, 0xBF7D, 0x96FA, 0xBF7E, + 0x96FB, 0xBF7F, 0x96FC, 0xBF80, 0x96FD, 0xBF81, 0x96FE, 0xBF82, 0x9741, 0xBF83, 0x9742, 0xBF84, 0x9743, 0xBF85, 0x9744, 0xBF86, + 0x9745, 0xBF87, 0x9746, 0xBF88, 0x9747, 0xBF89, 0x9748, 0xBF8A, 0x9749, 0xBF8B, 0x974A, 0xBF8C, 0x974B, 0xBF8D, 0x974C, 0xBF8E, + 0x974D, 0xBF8F, 0x974E, 0xBF90, 0x974F, 0xBF91, 0x9750, 0xBF92, 0x9751, 0xBF93, 0x9752, 0xBF95, 0x9753, 0xBF96, 0x9754, 0xBF97, + 0x9755, 0xBF98, 0x9756, 0xBF99, 0x9757, 0xBF9A, 0x9758, 0xBF9B, 0x9759, 0xBF9C, 0x975A, 0xBF9D, 0x9761, 0xBF9E, 0x9762, 0xBF9F, + 0x9763, 0xBFA0, 0x9764, 0xBFA1, 0x9765, 0xBFA2, 0x9766, 0xBFA3, 0x9767, 0xBFA4, 0x9768, 0xBFA5, 0x9769, 0xBFA6, 0x976A, 0xBFA7, + 0x976B, 0xBFA8, 0x976C, 0xBFA9, 0x976D, 0xBFAA, 0x976E, 0xBFAB, 0x976F, 0xBFAC, 0x9770, 0xBFAD, 0x9771, 0xBFAE, 0x9772, 0xBFAF, + 0x9773, 0xBFB1, 0x9774, 0xBFB2, 0x9775, 0xBFB3, 0x9776, 0xBFB4, 0x9777, 0xBFB5, 0x9778, 0xBFB6, 0x9779, 0xBFB7, 0x977A, 0xBFB8, + 0x9781, 0xBFB9, 0x9782, 0xBFBA, 0x9783, 0xBFBB, 0x9784, 0xBFBC, 0x9785, 0xBFBD, 0x9786, 0xBFBE, 0x9787, 0xBFBF, 0x9788, 0xBFC0, + 0x9789, 0xBFC1, 0x978A, 0xBFC2, 0x978B, 0xBFC3, 0x978C, 0xBFC4, 0x978D, 0xBFC6, 0x978E, 0xBFC7, 0x978F, 0xBFC8, 0x9790, 0xBFC9, + 0x9791, 0xBFCA, 0x9792, 0xBFCB, 0x9793, 0xBFCE, 0x9794, 0xBFCF, 0x9795, 0xBFD1, 0x9796, 0xBFD2, 0x9797, 0xBFD3, 0x9798, 0xBFD5, + 0x9799, 0xBFD6, 0x979A, 0xBFD7, 0x979B, 0xBFD8, 0x979C, 0xBFD9, 0x979D, 0xBFDA, 0x979E, 0xBFDB, 0x979F, 0xBFDD, 0x97A0, 0xBFDE, + 0x97A1, 0xBFE0, 0x97A2, 0xBFE2, 0x97A3, 0xBFE3, 0x97A4, 0xBFE4, 0x97A5, 0xBFE5, 0x97A6, 0xBFE6, 0x97A7, 0xBFE7, 0x97A8, 0xBFE8, + 0x97A9, 0xBFE9, 0x97AA, 0xBFEA, 0x97AB, 0xBFEB, 0x97AC, 0xBFEC, 0x97AD, 0xBFED, 0x97AE, 0xBFEE, 0x97AF, 0xBFEF, 0x97B0, 0xBFF0, + 0x97B1, 0xBFF1, 0x97B2, 0xBFF2, 0x97B3, 0xBFF3, 0x97B4, 0xBFF4, 0x97B5, 0xBFF5, 0x97B6, 0xBFF6, 0x97B7, 0xBFF7, 0x97B8, 0xBFF8, + 0x97B9, 0xBFF9, 0x97BA, 0xBFFA, 0x97BB, 0xBFFB, 0x97BC, 0xBFFC, 0x97BD, 0xBFFD, 0x97BE, 0xBFFE, 0x97BF, 0xBFFF, 0x97C0, 0xC000, + 0x97C1, 0xC001, 0x97C2, 0xC002, 0x97C3, 0xC003, 0x97C4, 0xC004, 0x97C5, 0xC005, 0x97C6, 0xC006, 0x97C7, 0xC007, 0x97C8, 0xC008, + 0x97C9, 0xC009, 0x97CA, 0xC00A, 0x97CB, 0xC00B, 0x97CC, 0xC00C, 0x97CD, 0xC00D, 0x97CE, 0xC00E, 0x97CF, 0xC00F, 0x97D0, 0xC010, + 0x97D1, 0xC011, 0x97D2, 0xC012, 0x97D3, 0xC013, 0x97D4, 0xC014, 0x97D5, 0xC015, 0x97D6, 0xC016, 0x97D7, 0xC017, 0x97D8, 0xC018, + 0x97D9, 0xC019, 0x97DA, 0xC01A, 0x97DB, 0xC01B, 0x97DC, 0xC01C, 0x97DD, 0xC01D, 0x97DE, 0xC01E, 0x97DF, 0xC01F, 0x97E0, 0xC020, + 0x97E1, 0xC021, 0x97E2, 0xC022, 0x97E3, 0xC023, 0x97E4, 0xC024, 0x97E5, 0xC025, 0x97E6, 0xC026, 0x97E7, 0xC027, 0x97E8, 0xC028, + 0x97E9, 0xC029, 0x97EA, 0xC02A, 0x97EB, 0xC02B, 0x97EC, 0xC02C, 0x97ED, 0xC02D, 0x97EE, 0xC02E, 0x97EF, 0xC02F, 0x97F0, 0xC030, + 0x97F1, 0xC031, 0x97F2, 0xC032, 0x97F3, 0xC033, 0x97F4, 0xC034, 0x97F5, 0xC035, 0x97F6, 0xC036, 0x97F7, 0xC037, 0x97F8, 0xC038, + 0x97F9, 0xC039, 0x97FA, 0xC03A, 0x97FB, 0xC03B, 0x97FC, 0xC03D, 0x97FD, 0xC03E, 0x97FE, 0xC03F, 0x9841, 0xC040, 0x9842, 0xC041, + 0x9843, 0xC042, 0x9844, 0xC043, 0x9845, 0xC044, 0x9846, 0xC045, 0x9847, 0xC046, 0x9848, 0xC047, 0x9849, 0xC048, 0x984A, 0xC049, + 0x984B, 0xC04A, 0x984C, 0xC04B, 0x984D, 0xC04C, 0x984E, 0xC04D, 0x984F, 0xC04E, 0x9850, 0xC04F, 0x9851, 0xC050, 0x9852, 0xC052, + 0x9853, 0xC053, 0x9854, 0xC054, 0x9855, 0xC055, 0x9856, 0xC056, 0x9857, 0xC057, 0x9858, 0xC059, 0x9859, 0xC05A, 0x985A, 0xC05B, + 0x9861, 0xC05D, 0x9862, 0xC05E, 0x9863, 0xC05F, 0x9864, 0xC061, 0x9865, 0xC062, 0x9866, 0xC063, 0x9867, 0xC064, 0x9868, 0xC065, + 0x9869, 0xC066, 0x986A, 0xC067, 0x986B, 0xC06A, 0x986C, 0xC06B, 0x986D, 0xC06C, 0x986E, 0xC06D, 0x986F, 0xC06E, 0x9870, 0xC06F, + 0x9871, 0xC070, 0x9872, 0xC071, 0x9873, 0xC072, 0x9874, 0xC073, 0x9875, 0xC074, 0x9876, 0xC075, 0x9877, 0xC076, 0x9878, 0xC077, + 0x9879, 0xC078, 0x987A, 0xC079, 0x9881, 0xC07A, 0x9882, 0xC07B, 0x9883, 0xC07C, 0x9884, 0xC07D, 0x9885, 0xC07E, 0x9886, 0xC07F, + 0x9887, 0xC080, 0x9888, 0xC081, 0x9889, 0xC082, 0x988A, 0xC083, 0x988B, 0xC084, 0x988C, 0xC085, 0x988D, 0xC086, 0x988E, 0xC087, + 0x988F, 0xC088, 0x9890, 0xC089, 0x9891, 0xC08A, 0x9892, 0xC08B, 0x9893, 0xC08C, 0x9894, 0xC08D, 0x9895, 0xC08E, 0x9896, 0xC08F, + 0x9897, 0xC092, 0x9898, 0xC093, 0x9899, 0xC095, 0x989A, 0xC096, 0x989B, 0xC097, 0x989C, 0xC099, 0x989D, 0xC09A, 0x989E, 0xC09B, + 0x989F, 0xC09C, 0x98A0, 0xC09D, 0x98A1, 0xC09E, 0x98A2, 0xC09F, 0x98A3, 0xC0A2, 0x98A4, 0xC0A4, 0x98A5, 0xC0A6, 0x98A6, 0xC0A7, + 0x98A7, 0xC0A8, 0x98A8, 0xC0A9, 0x98A9, 0xC0AA, 0x98AA, 0xC0AB, 0x98AB, 0xC0AE, 0x98AC, 0xC0B1, 0x98AD, 0xC0B2, 0x98AE, 0xC0B7, + 0x98AF, 0xC0B8, 0x98B0, 0xC0B9, 0x98B1, 0xC0BA, 0x98B2, 0xC0BB, 0x98B3, 0xC0BE, 0x98B4, 0xC0C2, 0x98B5, 0xC0C3, 0x98B6, 0xC0C4, + 0x98B7, 0xC0C6, 0x98B8, 0xC0C7, 0x98B9, 0xC0CA, 0x98BA, 0xC0CB, 0x98BB, 0xC0CD, 0x98BC, 0xC0CE, 0x98BD, 0xC0CF, 0x98BE, 0xC0D1, + 0x98BF, 0xC0D2, 0x98C0, 0xC0D3, 0x98C1, 0xC0D4, 0x98C2, 0xC0D5, 0x98C3, 0xC0D6, 0x98C4, 0xC0D7, 0x98C5, 0xC0DA, 0x98C6, 0xC0DE, + 0x98C7, 0xC0DF, 0x98C8, 0xC0E0, 0x98C9, 0xC0E1, 0x98CA, 0xC0E2, 0x98CB, 0xC0E3, 0x98CC, 0xC0E6, 0x98CD, 0xC0E7, 0x98CE, 0xC0E9, + 0x98CF, 0xC0EA, 0x98D0, 0xC0EB, 0x98D1, 0xC0ED, 0x98D2, 0xC0EE, 0x98D3, 0xC0EF, 0x98D4, 0xC0F0, 0x98D5, 0xC0F1, 0x98D6, 0xC0F2, + 0x98D7, 0xC0F3, 0x98D8, 0xC0F6, 0x98D9, 0xC0F8, 0x98DA, 0xC0FA, 0x98DB, 0xC0FB, 0x98DC, 0xC0FC, 0x98DD, 0xC0FD, 0x98DE, 0xC0FE, + 0x98DF, 0xC0FF, 0x98E0, 0xC101, 0x98E1, 0xC102, 0x98E2, 0xC103, 0x98E3, 0xC105, 0x98E4, 0xC106, 0x98E5, 0xC107, 0x98E6, 0xC109, + 0x98E7, 0xC10A, 0x98E8, 0xC10B, 0x98E9, 0xC10C, 0x98EA, 0xC10D, 0x98EB, 0xC10E, 0x98EC, 0xC10F, 0x98ED, 0xC111, 0x98EE, 0xC112, + 0x98EF, 0xC113, 0x98F0, 0xC114, 0x98F1, 0xC116, 0x98F2, 0xC117, 0x98F3, 0xC118, 0x98F4, 0xC119, 0x98F5, 0xC11A, 0x98F6, 0xC11B, + 0x98F7, 0xC121, 0x98F8, 0xC122, 0x98F9, 0xC125, 0x98FA, 0xC128, 0x98FB, 0xC129, 0x98FC, 0xC12A, 0x98FD, 0xC12B, 0x98FE, 0xC12E, + 0x9941, 0xC132, 0x9942, 0xC133, 0x9943, 0xC134, 0x9944, 0xC135, 0x9945, 0xC137, 0x9946, 0xC13A, 0x9947, 0xC13B, 0x9948, 0xC13D, + 0x9949, 0xC13E, 0x994A, 0xC13F, 0x994B, 0xC141, 0x994C, 0xC142, 0x994D, 0xC143, 0x994E, 0xC144, 0x994F, 0xC145, 0x9950, 0xC146, + 0x9951, 0xC147, 0x9952, 0xC14A, 0x9953, 0xC14E, 0x9954, 0xC14F, 0x9955, 0xC150, 0x9956, 0xC151, 0x9957, 0xC152, 0x9958, 0xC153, + 0x9959, 0xC156, 0x995A, 0xC157, 0x9961, 0xC159, 0x9962, 0xC15A, 0x9963, 0xC15B, 0x9964, 0xC15D, 0x9965, 0xC15E, 0x9966, 0xC15F, + 0x9967, 0xC160, 0x9968, 0xC161, 0x9969, 0xC162, 0x996A, 0xC163, 0x996B, 0xC166, 0x996C, 0xC16A, 0x996D, 0xC16B, 0x996E, 0xC16C, + 0x996F, 0xC16D, 0x9970, 0xC16E, 0x9971, 0xC16F, 0x9972, 0xC171, 0x9973, 0xC172, 0x9974, 0xC173, 0x9975, 0xC175, 0x9976, 0xC176, + 0x9977, 0xC177, 0x9978, 0xC179, 0x9979, 0xC17A, 0x997A, 0xC17B, 0x9981, 0xC17C, 0x9982, 0xC17D, 0x9983, 0xC17E, 0x9984, 0xC17F, + 0x9985, 0xC180, 0x9986, 0xC181, 0x9987, 0xC182, 0x9988, 0xC183, 0x9989, 0xC184, 0x998A, 0xC186, 0x998B, 0xC187, 0x998C, 0xC188, + 0x998D, 0xC189, 0x998E, 0xC18A, 0x998F, 0xC18B, 0x9990, 0xC18F, 0x9991, 0xC191, 0x9992, 0xC192, 0x9993, 0xC193, 0x9994, 0xC195, + 0x9995, 0xC197, 0x9996, 0xC198, 0x9997, 0xC199, 0x9998, 0xC19A, 0x9999, 0xC19B, 0x999A, 0xC19E, 0x999B, 0xC1A0, 0x999C, 0xC1A2, + 0x999D, 0xC1A3, 0x999E, 0xC1A4, 0x999F, 0xC1A6, 0x99A0, 0xC1A7, 0x99A1, 0xC1AA, 0x99A2, 0xC1AB, 0x99A3, 0xC1AD, 0x99A4, 0xC1AE, + 0x99A5, 0xC1AF, 0x99A6, 0xC1B1, 0x99A7, 0xC1B2, 0x99A8, 0xC1B3, 0x99A9, 0xC1B4, 0x99AA, 0xC1B5, 0x99AB, 0xC1B6, 0x99AC, 0xC1B7, + 0x99AD, 0xC1B8, 0x99AE, 0xC1B9, 0x99AF, 0xC1BA, 0x99B0, 0xC1BB, 0x99B1, 0xC1BC, 0x99B2, 0xC1BE, 0x99B3, 0xC1BF, 0x99B4, 0xC1C0, + 0x99B5, 0xC1C1, 0x99B6, 0xC1C2, 0x99B7, 0xC1C3, 0x99B8, 0xC1C5, 0x99B9, 0xC1C6, 0x99BA, 0xC1C7, 0x99BB, 0xC1C9, 0x99BC, 0xC1CA, + 0x99BD, 0xC1CB, 0x99BE, 0xC1CD, 0x99BF, 0xC1CE, 0x99C0, 0xC1CF, 0x99C1, 0xC1D0, 0x99C2, 0xC1D1, 0x99C3, 0xC1D2, 0x99C4, 0xC1D3, + 0x99C5, 0xC1D5, 0x99C6, 0xC1D6, 0x99C7, 0xC1D9, 0x99C8, 0xC1DA, 0x99C9, 0xC1DB, 0x99CA, 0xC1DC, 0x99CB, 0xC1DD, 0x99CC, 0xC1DE, + 0x99CD, 0xC1DF, 0x99CE, 0xC1E1, 0x99CF, 0xC1E2, 0x99D0, 0xC1E3, 0x99D1, 0xC1E5, 0x99D2, 0xC1E6, 0x99D3, 0xC1E7, 0x99D4, 0xC1E9, + 0x99D5, 0xC1EA, 0x99D6, 0xC1EB, 0x99D7, 0xC1EC, 0x99D8, 0xC1ED, 0x99D9, 0xC1EE, 0x99DA, 0xC1EF, 0x99DB, 0xC1F2, 0x99DC, 0xC1F4, + 0x99DD, 0xC1F5, 0x99DE, 0xC1F6, 0x99DF, 0xC1F7, 0x99E0, 0xC1F8, 0x99E1, 0xC1F9, 0x99E2, 0xC1FA, 0x99E3, 0xC1FB, 0x99E4, 0xC1FE, + 0x99E5, 0xC1FF, 0x99E6, 0xC201, 0x99E7, 0xC202, 0x99E8, 0xC203, 0x99E9, 0xC205, 0x99EA, 0xC206, 0x99EB, 0xC207, 0x99EC, 0xC208, + 0x99ED, 0xC209, 0x99EE, 0xC20A, 0x99EF, 0xC20B, 0x99F0, 0xC20E, 0x99F1, 0xC210, 0x99F2, 0xC212, 0x99F3, 0xC213, 0x99F4, 0xC214, + 0x99F5, 0xC215, 0x99F6, 0xC216, 0x99F7, 0xC217, 0x99F8, 0xC21A, 0x99F9, 0xC21B, 0x99FA, 0xC21D, 0x99FB, 0xC21E, 0x99FC, 0xC221, + 0x99FD, 0xC222, 0x99FE, 0xC223, 0x9A41, 0xC224, 0x9A42, 0xC225, 0x9A43, 0xC226, 0x9A44, 0xC227, 0x9A45, 0xC22A, 0x9A46, 0xC22C, + 0x9A47, 0xC22E, 0x9A48, 0xC230, 0x9A49, 0xC233, 0x9A4A, 0xC235, 0x9A4B, 0xC236, 0x9A4C, 0xC237, 0x9A4D, 0xC238, 0x9A4E, 0xC239, + 0x9A4F, 0xC23A, 0x9A50, 0xC23B, 0x9A51, 0xC23C, 0x9A52, 0xC23D, 0x9A53, 0xC23E, 0x9A54, 0xC23F, 0x9A55, 0xC240, 0x9A56, 0xC241, + 0x9A57, 0xC242, 0x9A58, 0xC243, 0x9A59, 0xC244, 0x9A5A, 0xC245, 0x9A61, 0xC246, 0x9A62, 0xC247, 0x9A63, 0xC249, 0x9A64, 0xC24A, + 0x9A65, 0xC24B, 0x9A66, 0xC24C, 0x9A67, 0xC24D, 0x9A68, 0xC24E, 0x9A69, 0xC24F, 0x9A6A, 0xC252, 0x9A6B, 0xC253, 0x9A6C, 0xC255, + 0x9A6D, 0xC256, 0x9A6E, 0xC257, 0x9A6F, 0xC259, 0x9A70, 0xC25A, 0x9A71, 0xC25B, 0x9A72, 0xC25C, 0x9A73, 0xC25D, 0x9A74, 0xC25E, + 0x9A75, 0xC25F, 0x9A76, 0xC261, 0x9A77, 0xC262, 0x9A78, 0xC263, 0x9A79, 0xC264, 0x9A7A, 0xC266, 0x9A81, 0xC267, 0x9A82, 0xC268, + 0x9A83, 0xC269, 0x9A84, 0xC26A, 0x9A85, 0xC26B, 0x9A86, 0xC26E, 0x9A87, 0xC26F, 0x9A88, 0xC271, 0x9A89, 0xC272, 0x9A8A, 0xC273, + 0x9A8B, 0xC275, 0x9A8C, 0xC276, 0x9A8D, 0xC277, 0x9A8E, 0xC278, 0x9A8F, 0xC279, 0x9A90, 0xC27A, 0x9A91, 0xC27B, 0x9A92, 0xC27E, + 0x9A93, 0xC280, 0x9A94, 0xC282, 0x9A95, 0xC283, 0x9A96, 0xC284, 0x9A97, 0xC285, 0x9A98, 0xC286, 0x9A99, 0xC287, 0x9A9A, 0xC28A, + 0x9A9B, 0xC28B, 0x9A9C, 0xC28C, 0x9A9D, 0xC28D, 0x9A9E, 0xC28E, 0x9A9F, 0xC28F, 0x9AA0, 0xC291, 0x9AA1, 0xC292, 0x9AA2, 0xC293, + 0x9AA3, 0xC294, 0x9AA4, 0xC295, 0x9AA5, 0xC296, 0x9AA6, 0xC297, 0x9AA7, 0xC299, 0x9AA8, 0xC29A, 0x9AA9, 0xC29C, 0x9AAA, 0xC29E, + 0x9AAB, 0xC29F, 0x9AAC, 0xC2A0, 0x9AAD, 0xC2A1, 0x9AAE, 0xC2A2, 0x9AAF, 0xC2A3, 0x9AB0, 0xC2A6, 0x9AB1, 0xC2A7, 0x9AB2, 0xC2A9, + 0x9AB3, 0xC2AA, 0x9AB4, 0xC2AB, 0x9AB5, 0xC2AE, 0x9AB6, 0xC2AF, 0x9AB7, 0xC2B0, 0x9AB8, 0xC2B1, 0x9AB9, 0xC2B2, 0x9ABA, 0xC2B3, + 0x9ABB, 0xC2B6, 0x9ABC, 0xC2B8, 0x9ABD, 0xC2BA, 0x9ABE, 0xC2BB, 0x9ABF, 0xC2BC, 0x9AC0, 0xC2BD, 0x9AC1, 0xC2BE, 0x9AC2, 0xC2BF, + 0x9AC3, 0xC2C0, 0x9AC4, 0xC2C1, 0x9AC5, 0xC2C2, 0x9AC6, 0xC2C3, 0x9AC7, 0xC2C4, 0x9AC8, 0xC2C5, 0x9AC9, 0xC2C6, 0x9ACA, 0xC2C7, + 0x9ACB, 0xC2C8, 0x9ACC, 0xC2C9, 0x9ACD, 0xC2CA, 0x9ACE, 0xC2CB, 0x9ACF, 0xC2CC, 0x9AD0, 0xC2CD, 0x9AD1, 0xC2CE, 0x9AD2, 0xC2CF, + 0x9AD3, 0xC2D0, 0x9AD4, 0xC2D1, 0x9AD5, 0xC2D2, 0x9AD6, 0xC2D3, 0x9AD7, 0xC2D4, 0x9AD8, 0xC2D5, 0x9AD9, 0xC2D6, 0x9ADA, 0xC2D7, + 0x9ADB, 0xC2D8, 0x9ADC, 0xC2D9, 0x9ADD, 0xC2DA, 0x9ADE, 0xC2DB, 0x9ADF, 0xC2DE, 0x9AE0, 0xC2DF, 0x9AE1, 0xC2E1, 0x9AE2, 0xC2E2, + 0x9AE3, 0xC2E5, 0x9AE4, 0xC2E6, 0x9AE5, 0xC2E7, 0x9AE6, 0xC2E8, 0x9AE7, 0xC2E9, 0x9AE8, 0xC2EA, 0x9AE9, 0xC2EE, 0x9AEA, 0xC2F0, + 0x9AEB, 0xC2F2, 0x9AEC, 0xC2F3, 0x9AED, 0xC2F4, 0x9AEE, 0xC2F5, 0x9AEF, 0xC2F7, 0x9AF0, 0xC2FA, 0x9AF1, 0xC2FD, 0x9AF2, 0xC2FE, + 0x9AF3, 0xC2FF, 0x9AF4, 0xC301, 0x9AF5, 0xC302, 0x9AF6, 0xC303, 0x9AF7, 0xC304, 0x9AF8, 0xC305, 0x9AF9, 0xC306, 0x9AFA, 0xC307, + 0x9AFB, 0xC30A, 0x9AFC, 0xC30B, 0x9AFD, 0xC30E, 0x9AFE, 0xC30F, 0x9B41, 0xC310, 0x9B42, 0xC311, 0x9B43, 0xC312, 0x9B44, 0xC316, + 0x9B45, 0xC317, 0x9B46, 0xC319, 0x9B47, 0xC31A, 0x9B48, 0xC31B, 0x9B49, 0xC31D, 0x9B4A, 0xC31E, 0x9B4B, 0xC31F, 0x9B4C, 0xC320, + 0x9B4D, 0xC321, 0x9B4E, 0xC322, 0x9B4F, 0xC323, 0x9B50, 0xC326, 0x9B51, 0xC327, 0x9B52, 0xC32A, 0x9B53, 0xC32B, 0x9B54, 0xC32C, + 0x9B55, 0xC32D, 0x9B56, 0xC32E, 0x9B57, 0xC32F, 0x9B58, 0xC330, 0x9B59, 0xC331, 0x9B5A, 0xC332, 0x9B61, 0xC333, 0x9B62, 0xC334, + 0x9B63, 0xC335, 0x9B64, 0xC336, 0x9B65, 0xC337, 0x9B66, 0xC338, 0x9B67, 0xC339, 0x9B68, 0xC33A, 0x9B69, 0xC33B, 0x9B6A, 0xC33C, + 0x9B6B, 0xC33D, 0x9B6C, 0xC33E, 0x9B6D, 0xC33F, 0x9B6E, 0xC340, 0x9B6F, 0xC341, 0x9B70, 0xC342, 0x9B71, 0xC343, 0x9B72, 0xC344, + 0x9B73, 0xC346, 0x9B74, 0xC347, 0x9B75, 0xC348, 0x9B76, 0xC349, 0x9B77, 0xC34A, 0x9B78, 0xC34B, 0x9B79, 0xC34C, 0x9B7A, 0xC34D, + 0x9B81, 0xC34E, 0x9B82, 0xC34F, 0x9B83, 0xC350, 0x9B84, 0xC351, 0x9B85, 0xC352, 0x9B86, 0xC353, 0x9B87, 0xC354, 0x9B88, 0xC355, + 0x9B89, 0xC356, 0x9B8A, 0xC357, 0x9B8B, 0xC358, 0x9B8C, 0xC359, 0x9B8D, 0xC35A, 0x9B8E, 0xC35B, 0x9B8F, 0xC35C, 0x9B90, 0xC35D, + 0x9B91, 0xC35E, 0x9B92, 0xC35F, 0x9B93, 0xC360, 0x9B94, 0xC361, 0x9B95, 0xC362, 0x9B96, 0xC363, 0x9B97, 0xC364, 0x9B98, 0xC365, + 0x9B99, 0xC366, 0x9B9A, 0xC367, 0x9B9B, 0xC36A, 0x9B9C, 0xC36B, 0x9B9D, 0xC36D, 0x9B9E, 0xC36E, 0x9B9F, 0xC36F, 0x9BA0, 0xC371, + 0x9BA1, 0xC373, 0x9BA2, 0xC374, 0x9BA3, 0xC375, 0x9BA4, 0xC376, 0x9BA5, 0xC377, 0x9BA6, 0xC37A, 0x9BA7, 0xC37B, 0x9BA8, 0xC37E, + 0x9BA9, 0xC37F, 0x9BAA, 0xC380, 0x9BAB, 0xC381, 0x9BAC, 0xC382, 0x9BAD, 0xC383, 0x9BAE, 0xC385, 0x9BAF, 0xC386, 0x9BB0, 0xC387, + 0x9BB1, 0xC389, 0x9BB2, 0xC38A, 0x9BB3, 0xC38B, 0x9BB4, 0xC38D, 0x9BB5, 0xC38E, 0x9BB6, 0xC38F, 0x9BB7, 0xC390, 0x9BB8, 0xC391, + 0x9BB9, 0xC392, 0x9BBA, 0xC393, 0x9BBB, 0xC394, 0x9BBC, 0xC395, 0x9BBD, 0xC396, 0x9BBE, 0xC397, 0x9BBF, 0xC398, 0x9BC0, 0xC399, + 0x9BC1, 0xC39A, 0x9BC2, 0xC39B, 0x9BC3, 0xC39C, 0x9BC4, 0xC39D, 0x9BC5, 0xC39E, 0x9BC6, 0xC39F, 0x9BC7, 0xC3A0, 0x9BC8, 0xC3A1, + 0x9BC9, 0xC3A2, 0x9BCA, 0xC3A3, 0x9BCB, 0xC3A4, 0x9BCC, 0xC3A5, 0x9BCD, 0xC3A6, 0x9BCE, 0xC3A7, 0x9BCF, 0xC3A8, 0x9BD0, 0xC3A9, + 0x9BD1, 0xC3AA, 0x9BD2, 0xC3AB, 0x9BD3, 0xC3AC, 0x9BD4, 0xC3AD, 0x9BD5, 0xC3AE, 0x9BD6, 0xC3AF, 0x9BD7, 0xC3B0, 0x9BD8, 0xC3B1, + 0x9BD9, 0xC3B2, 0x9BDA, 0xC3B3, 0x9BDB, 0xC3B4, 0x9BDC, 0xC3B5, 0x9BDD, 0xC3B6, 0x9BDE, 0xC3B7, 0x9BDF, 0xC3B8, 0x9BE0, 0xC3B9, + 0x9BE1, 0xC3BA, 0x9BE2, 0xC3BB, 0x9BE3, 0xC3BC, 0x9BE4, 0xC3BD, 0x9BE5, 0xC3BE, 0x9BE6, 0xC3BF, 0x9BE7, 0xC3C1, 0x9BE8, 0xC3C2, + 0x9BE9, 0xC3C3, 0x9BEA, 0xC3C4, 0x9BEB, 0xC3C5, 0x9BEC, 0xC3C6, 0x9BED, 0xC3C7, 0x9BEE, 0xC3C8, 0x9BEF, 0xC3C9, 0x9BF0, 0xC3CA, + 0x9BF1, 0xC3CB, 0x9BF2, 0xC3CC, 0x9BF3, 0xC3CD, 0x9BF4, 0xC3CE, 0x9BF5, 0xC3CF, 0x9BF6, 0xC3D0, 0x9BF7, 0xC3D1, 0x9BF8, 0xC3D2, + 0x9BF9, 0xC3D3, 0x9BFA, 0xC3D4, 0x9BFB, 0xC3D5, 0x9BFC, 0xC3D6, 0x9BFD, 0xC3D7, 0x9BFE, 0xC3DA, 0x9C41, 0xC3DB, 0x9C42, 0xC3DD, + 0x9C43, 0xC3DE, 0x9C44, 0xC3E1, 0x9C45, 0xC3E3, 0x9C46, 0xC3E4, 0x9C47, 0xC3E5, 0x9C48, 0xC3E6, 0x9C49, 0xC3E7, 0x9C4A, 0xC3EA, + 0x9C4B, 0xC3EB, 0x9C4C, 0xC3EC, 0x9C4D, 0xC3EE, 0x9C4E, 0xC3EF, 0x9C4F, 0xC3F0, 0x9C50, 0xC3F1, 0x9C51, 0xC3F2, 0x9C52, 0xC3F3, + 0x9C53, 0xC3F6, 0x9C54, 0xC3F7, 0x9C55, 0xC3F9, 0x9C56, 0xC3FA, 0x9C57, 0xC3FB, 0x9C58, 0xC3FC, 0x9C59, 0xC3FD, 0x9C5A, 0xC3FE, + 0x9C61, 0xC3FF, 0x9C62, 0xC400, 0x9C63, 0xC401, 0x9C64, 0xC402, 0x9C65, 0xC403, 0x9C66, 0xC404, 0x9C67, 0xC405, 0x9C68, 0xC406, + 0x9C69, 0xC407, 0x9C6A, 0xC409, 0x9C6B, 0xC40A, 0x9C6C, 0xC40B, 0x9C6D, 0xC40C, 0x9C6E, 0xC40D, 0x9C6F, 0xC40E, 0x9C70, 0xC40F, + 0x9C71, 0xC411, 0x9C72, 0xC412, 0x9C73, 0xC413, 0x9C74, 0xC414, 0x9C75, 0xC415, 0x9C76, 0xC416, 0x9C77, 0xC417, 0x9C78, 0xC418, + 0x9C79, 0xC419, 0x9C7A, 0xC41A, 0x9C81, 0xC41B, 0x9C82, 0xC41C, 0x9C83, 0xC41D, 0x9C84, 0xC41E, 0x9C85, 0xC41F, 0x9C86, 0xC420, + 0x9C87, 0xC421, 0x9C88, 0xC422, 0x9C89, 0xC423, 0x9C8A, 0xC425, 0x9C8B, 0xC426, 0x9C8C, 0xC427, 0x9C8D, 0xC428, 0x9C8E, 0xC429, + 0x9C8F, 0xC42A, 0x9C90, 0xC42B, 0x9C91, 0xC42D, 0x9C92, 0xC42E, 0x9C93, 0xC42F, 0x9C94, 0xC431, 0x9C95, 0xC432, 0x9C96, 0xC433, + 0x9C97, 0xC435, 0x9C98, 0xC436, 0x9C99, 0xC437, 0x9C9A, 0xC438, 0x9C9B, 0xC439, 0x9C9C, 0xC43A, 0x9C9D, 0xC43B, 0x9C9E, 0xC43E, + 0x9C9F, 0xC43F, 0x9CA0, 0xC440, 0x9CA1, 0xC441, 0x9CA2, 0xC442, 0x9CA3, 0xC443, 0x9CA4, 0xC444, 0x9CA5, 0xC445, 0x9CA6, 0xC446, + 0x9CA7, 0xC447, 0x9CA8, 0xC449, 0x9CA9, 0xC44A, 0x9CAA, 0xC44B, 0x9CAB, 0xC44C, 0x9CAC, 0xC44D, 0x9CAD, 0xC44E, 0x9CAE, 0xC44F, + 0x9CAF, 0xC450, 0x9CB0, 0xC451, 0x9CB1, 0xC452, 0x9CB2, 0xC453, 0x9CB3, 0xC454, 0x9CB4, 0xC455, 0x9CB5, 0xC456, 0x9CB6, 0xC457, + 0x9CB7, 0xC458, 0x9CB8, 0xC459, 0x9CB9, 0xC45A, 0x9CBA, 0xC45B, 0x9CBB, 0xC45C, 0x9CBC, 0xC45D, 0x9CBD, 0xC45E, 0x9CBE, 0xC45F, + 0x9CBF, 0xC460, 0x9CC0, 0xC461, 0x9CC1, 0xC462, 0x9CC2, 0xC463, 0x9CC3, 0xC466, 0x9CC4, 0xC467, 0x9CC5, 0xC469, 0x9CC6, 0xC46A, + 0x9CC7, 0xC46B, 0x9CC8, 0xC46D, 0x9CC9, 0xC46E, 0x9CCA, 0xC46F, 0x9CCB, 0xC470, 0x9CCC, 0xC471, 0x9CCD, 0xC472, 0x9CCE, 0xC473, + 0x9CCF, 0xC476, 0x9CD0, 0xC477, 0x9CD1, 0xC478, 0x9CD2, 0xC47A, 0x9CD3, 0xC47B, 0x9CD4, 0xC47C, 0x9CD5, 0xC47D, 0x9CD6, 0xC47E, + 0x9CD7, 0xC47F, 0x9CD8, 0xC481, 0x9CD9, 0xC482, 0x9CDA, 0xC483, 0x9CDB, 0xC484, 0x9CDC, 0xC485, 0x9CDD, 0xC486, 0x9CDE, 0xC487, + 0x9CDF, 0xC488, 0x9CE0, 0xC489, 0x9CE1, 0xC48A, 0x9CE2, 0xC48B, 0x9CE3, 0xC48C, 0x9CE4, 0xC48D, 0x9CE5, 0xC48E, 0x9CE6, 0xC48F, + 0x9CE7, 0xC490, 0x9CE8, 0xC491, 0x9CE9, 0xC492, 0x9CEA, 0xC493, 0x9CEB, 0xC495, 0x9CEC, 0xC496, 0x9CED, 0xC497, 0x9CEE, 0xC498, + 0x9CEF, 0xC499, 0x9CF0, 0xC49A, 0x9CF1, 0xC49B, 0x9CF2, 0xC49D, 0x9CF3, 0xC49E, 0x9CF4, 0xC49F, 0x9CF5, 0xC4A0, 0x9CF6, 0xC4A1, + 0x9CF7, 0xC4A2, 0x9CF8, 0xC4A3, 0x9CF9, 0xC4A4, 0x9CFA, 0xC4A5, 0x9CFB, 0xC4A6, 0x9CFC, 0xC4A7, 0x9CFD, 0xC4A8, 0x9CFE, 0xC4A9, + 0x9D41, 0xC4AA, 0x9D42, 0xC4AB, 0x9D43, 0xC4AC, 0x9D44, 0xC4AD, 0x9D45, 0xC4AE, 0x9D46, 0xC4AF, 0x9D47, 0xC4B0, 0x9D48, 0xC4B1, + 0x9D49, 0xC4B2, 0x9D4A, 0xC4B3, 0x9D4B, 0xC4B4, 0x9D4C, 0xC4B5, 0x9D4D, 0xC4B6, 0x9D4E, 0xC4B7, 0x9D4F, 0xC4B9, 0x9D50, 0xC4BA, + 0x9D51, 0xC4BB, 0x9D52, 0xC4BD, 0x9D53, 0xC4BE, 0x9D54, 0xC4BF, 0x9D55, 0xC4C0, 0x9D56, 0xC4C1, 0x9D57, 0xC4C2, 0x9D58, 0xC4C3, + 0x9D59, 0xC4C4, 0x9D5A, 0xC4C5, 0x9D61, 0xC4C6, 0x9D62, 0xC4C7, 0x9D63, 0xC4C8, 0x9D64, 0xC4C9, 0x9D65, 0xC4CA, 0x9D66, 0xC4CB, + 0x9D67, 0xC4CC, 0x9D68, 0xC4CD, 0x9D69, 0xC4CE, 0x9D6A, 0xC4CF, 0x9D6B, 0xC4D0, 0x9D6C, 0xC4D1, 0x9D6D, 0xC4D2, 0x9D6E, 0xC4D3, + 0x9D6F, 0xC4D4, 0x9D70, 0xC4D5, 0x9D71, 0xC4D6, 0x9D72, 0xC4D7, 0x9D73, 0xC4D8, 0x9D74, 0xC4D9, 0x9D75, 0xC4DA, 0x9D76, 0xC4DB, + 0x9D77, 0xC4DC, 0x9D78, 0xC4DD, 0x9D79, 0xC4DE, 0x9D7A, 0xC4DF, 0x9D81, 0xC4E0, 0x9D82, 0xC4E1, 0x9D83, 0xC4E2, 0x9D84, 0xC4E3, + 0x9D85, 0xC4E4, 0x9D86, 0xC4E5, 0x9D87, 0xC4E6, 0x9D88, 0xC4E7, 0x9D89, 0xC4E8, 0x9D8A, 0xC4EA, 0x9D8B, 0xC4EB, 0x9D8C, 0xC4EC, + 0x9D8D, 0xC4ED, 0x9D8E, 0xC4EE, 0x9D8F, 0xC4EF, 0x9D90, 0xC4F2, 0x9D91, 0xC4F3, 0x9D92, 0xC4F5, 0x9D93, 0xC4F6, 0x9D94, 0xC4F7, + 0x9D95, 0xC4F9, 0x9D96, 0xC4FB, 0x9D97, 0xC4FC, 0x9D98, 0xC4FD, 0x9D99, 0xC4FE, 0x9D9A, 0xC502, 0x9D9B, 0xC503, 0x9D9C, 0xC504, + 0x9D9D, 0xC505, 0x9D9E, 0xC506, 0x9D9F, 0xC507, 0x9DA0, 0xC508, 0x9DA1, 0xC509, 0x9DA2, 0xC50A, 0x9DA3, 0xC50B, 0x9DA4, 0xC50D, + 0x9DA5, 0xC50E, 0x9DA6, 0xC50F, 0x9DA7, 0xC511, 0x9DA8, 0xC512, 0x9DA9, 0xC513, 0x9DAA, 0xC515, 0x9DAB, 0xC516, 0x9DAC, 0xC517, + 0x9DAD, 0xC518, 0x9DAE, 0xC519, 0x9DAF, 0xC51A, 0x9DB0, 0xC51B, 0x9DB1, 0xC51D, 0x9DB2, 0xC51E, 0x9DB3, 0xC51F, 0x9DB4, 0xC520, + 0x9DB5, 0xC521, 0x9DB6, 0xC522, 0x9DB7, 0xC523, 0x9DB8, 0xC524, 0x9DB9, 0xC525, 0x9DBA, 0xC526, 0x9DBB, 0xC527, 0x9DBC, 0xC52A, + 0x9DBD, 0xC52B, 0x9DBE, 0xC52D, 0x9DBF, 0xC52E, 0x9DC0, 0xC52F, 0x9DC1, 0xC531, 0x9DC2, 0xC532, 0x9DC3, 0xC533, 0x9DC4, 0xC534, + 0x9DC5, 0xC535, 0x9DC6, 0xC536, 0x9DC7, 0xC537, 0x9DC8, 0xC53A, 0x9DC9, 0xC53C, 0x9DCA, 0xC53E, 0x9DCB, 0xC53F, 0x9DCC, 0xC540, + 0x9DCD, 0xC541, 0x9DCE, 0xC542, 0x9DCF, 0xC543, 0x9DD0, 0xC546, 0x9DD1, 0xC547, 0x9DD2, 0xC54B, 0x9DD3, 0xC54F, 0x9DD4, 0xC550, + 0x9DD5, 0xC551, 0x9DD6, 0xC552, 0x9DD7, 0xC556, 0x9DD8, 0xC55A, 0x9DD9, 0xC55B, 0x9DDA, 0xC55C, 0x9DDB, 0xC55F, 0x9DDC, 0xC562, + 0x9DDD, 0xC563, 0x9DDE, 0xC565, 0x9DDF, 0xC566, 0x9DE0, 0xC567, 0x9DE1, 0xC569, 0x9DE2, 0xC56A, 0x9DE3, 0xC56B, 0x9DE4, 0xC56C, + 0x9DE5, 0xC56D, 0x9DE6, 0xC56E, 0x9DE7, 0xC56F, 0x9DE8, 0xC572, 0x9DE9, 0xC576, 0x9DEA, 0xC577, 0x9DEB, 0xC578, 0x9DEC, 0xC579, + 0x9DED, 0xC57A, 0x9DEE, 0xC57B, 0x9DEF, 0xC57E, 0x9DF0, 0xC57F, 0x9DF1, 0xC581, 0x9DF2, 0xC582, 0x9DF3, 0xC583, 0x9DF4, 0xC585, + 0x9DF5, 0xC586, 0x9DF6, 0xC588, 0x9DF7, 0xC589, 0x9DF8, 0xC58A, 0x9DF9, 0xC58B, 0x9DFA, 0xC58E, 0x9DFB, 0xC590, 0x9DFC, 0xC592, + 0x9DFD, 0xC593, 0x9DFE, 0xC594, 0x9E41, 0xC596, 0x9E42, 0xC599, 0x9E43, 0xC59A, 0x9E44, 0xC59B, 0x9E45, 0xC59D, 0x9E46, 0xC59E, + 0x9E47, 0xC59F, 0x9E48, 0xC5A1, 0x9E49, 0xC5A2, 0x9E4A, 0xC5A3, 0x9E4B, 0xC5A4, 0x9E4C, 0xC5A5, 0x9E4D, 0xC5A6, 0x9E4E, 0xC5A7, + 0x9E4F, 0xC5A8, 0x9E50, 0xC5AA, 0x9E51, 0xC5AB, 0x9E52, 0xC5AC, 0x9E53, 0xC5AD, 0x9E54, 0xC5AE, 0x9E55, 0xC5AF, 0x9E56, 0xC5B0, + 0x9E57, 0xC5B1, 0x9E58, 0xC5B2, 0x9E59, 0xC5B3, 0x9E5A, 0xC5B6, 0x9E61, 0xC5B7, 0x9E62, 0xC5BA, 0x9E63, 0xC5BF, 0x9E64, 0xC5C0, + 0x9E65, 0xC5C1, 0x9E66, 0xC5C2, 0x9E67, 0xC5C3, 0x9E68, 0xC5CB, 0x9E69, 0xC5CD, 0x9E6A, 0xC5CF, 0x9E6B, 0xC5D2, 0x9E6C, 0xC5D3, + 0x9E6D, 0xC5D5, 0x9E6E, 0xC5D6, 0x9E6F, 0xC5D7, 0x9E70, 0xC5D9, 0x9E71, 0xC5DA, 0x9E72, 0xC5DB, 0x9E73, 0xC5DC, 0x9E74, 0xC5DD, + 0x9E75, 0xC5DE, 0x9E76, 0xC5DF, 0x9E77, 0xC5E2, 0x9E78, 0xC5E4, 0x9E79, 0xC5E6, 0x9E7A, 0xC5E7, 0x9E81, 0xC5E8, 0x9E82, 0xC5E9, + 0x9E83, 0xC5EA, 0x9E84, 0xC5EB, 0x9E85, 0xC5EF, 0x9E86, 0xC5F1, 0x9E87, 0xC5F2, 0x9E88, 0xC5F3, 0x9E89, 0xC5F5, 0x9E8A, 0xC5F8, + 0x9E8B, 0xC5F9, 0x9E8C, 0xC5FA, 0x9E8D, 0xC5FB, 0x9E8E, 0xC602, 0x9E8F, 0xC603, 0x9E90, 0xC604, 0x9E91, 0xC609, 0x9E92, 0xC60A, + 0x9E93, 0xC60B, 0x9E94, 0xC60D, 0x9E95, 0xC60E, 0x9E96, 0xC60F, 0x9E97, 0xC611, 0x9E98, 0xC612, 0x9E99, 0xC613, 0x9E9A, 0xC614, + 0x9E9B, 0xC615, 0x9E9C, 0xC616, 0x9E9D, 0xC617, 0x9E9E, 0xC61A, 0x9E9F, 0xC61D, 0x9EA0, 0xC61E, 0x9EA1, 0xC61F, 0x9EA2, 0xC620, + 0x9EA3, 0xC621, 0x9EA4, 0xC622, 0x9EA5, 0xC623, 0x9EA6, 0xC626, 0x9EA7, 0xC627, 0x9EA8, 0xC629, 0x9EA9, 0xC62A, 0x9EAA, 0xC62B, + 0x9EAB, 0xC62F, 0x9EAC, 0xC631, 0x9EAD, 0xC632, 0x9EAE, 0xC636, 0x9EAF, 0xC638, 0x9EB0, 0xC63A, 0x9EB1, 0xC63C, 0x9EB2, 0xC63D, + 0x9EB3, 0xC63E, 0x9EB4, 0xC63F, 0x9EB5, 0xC642, 0x9EB6, 0xC643, 0x9EB7, 0xC645, 0x9EB8, 0xC646, 0x9EB9, 0xC647, 0x9EBA, 0xC649, + 0x9EBB, 0xC64A, 0x9EBC, 0xC64B, 0x9EBD, 0xC64C, 0x9EBE, 0xC64D, 0x9EBF, 0xC64E, 0x9EC0, 0xC64F, 0x9EC1, 0xC652, 0x9EC2, 0xC656, + 0x9EC3, 0xC657, 0x9EC4, 0xC658, 0x9EC5, 0xC659, 0x9EC6, 0xC65A, 0x9EC7, 0xC65B, 0x9EC8, 0xC65E, 0x9EC9, 0xC65F, 0x9ECA, 0xC661, + 0x9ECB, 0xC662, 0x9ECC, 0xC663, 0x9ECD, 0xC664, 0x9ECE, 0xC665, 0x9ECF, 0xC666, 0x9ED0, 0xC667, 0x9ED1, 0xC668, 0x9ED2, 0xC669, + 0x9ED3, 0xC66A, 0x9ED4, 0xC66B, 0x9ED5, 0xC66D, 0x9ED6, 0xC66E, 0x9ED7, 0xC670, 0x9ED8, 0xC672, 0x9ED9, 0xC673, 0x9EDA, 0xC674, + 0x9EDB, 0xC675, 0x9EDC, 0xC676, 0x9EDD, 0xC677, 0x9EDE, 0xC67A, 0x9EDF, 0xC67B, 0x9EE0, 0xC67D, 0x9EE1, 0xC67E, 0x9EE2, 0xC67F, + 0x9EE3, 0xC681, 0x9EE4, 0xC682, 0x9EE5, 0xC683, 0x9EE6, 0xC684, 0x9EE7, 0xC685, 0x9EE8, 0xC686, 0x9EE9, 0xC687, 0x9EEA, 0xC68A, + 0x9EEB, 0xC68C, 0x9EEC, 0xC68E, 0x9EED, 0xC68F, 0x9EEE, 0xC690, 0x9EEF, 0xC691, 0x9EF0, 0xC692, 0x9EF1, 0xC693, 0x9EF2, 0xC696, + 0x9EF3, 0xC697, 0x9EF4, 0xC699, 0x9EF5, 0xC69A, 0x9EF6, 0xC69B, 0x9EF7, 0xC69D, 0x9EF8, 0xC69E, 0x9EF9, 0xC69F, 0x9EFA, 0xC6A0, + 0x9EFB, 0xC6A1, 0x9EFC, 0xC6A2, 0x9EFD, 0xC6A3, 0x9EFE, 0xC6A6, 0x9F41, 0xC6A8, 0x9F42, 0xC6AA, 0x9F43, 0xC6AB, 0x9F44, 0xC6AC, + 0x9F45, 0xC6AD, 0x9F46, 0xC6AE, 0x9F47, 0xC6AF, 0x9F48, 0xC6B2, 0x9F49, 0xC6B3, 0x9F4A, 0xC6B5, 0x9F4B, 0xC6B6, 0x9F4C, 0xC6B7, + 0x9F4D, 0xC6BB, 0x9F4E, 0xC6BC, 0x9F4F, 0xC6BD, 0x9F50, 0xC6BE, 0x9F51, 0xC6BF, 0x9F52, 0xC6C2, 0x9F53, 0xC6C4, 0x9F54, 0xC6C6, + 0x9F55, 0xC6C7, 0x9F56, 0xC6C8, 0x9F57, 0xC6C9, 0x9F58, 0xC6CA, 0x9F59, 0xC6CB, 0x9F5A, 0xC6CE, 0x9F61, 0xC6CF, 0x9F62, 0xC6D1, + 0x9F63, 0xC6D2, 0x9F64, 0xC6D3, 0x9F65, 0xC6D5, 0x9F66, 0xC6D6, 0x9F67, 0xC6D7, 0x9F68, 0xC6D8, 0x9F69, 0xC6D9, 0x9F6A, 0xC6DA, + 0x9F6B, 0xC6DB, 0x9F6C, 0xC6DE, 0x9F6D, 0xC6DF, 0x9F6E, 0xC6E2, 0x9F6F, 0xC6E3, 0x9F70, 0xC6E4, 0x9F71, 0xC6E5, 0x9F72, 0xC6E6, + 0x9F73, 0xC6E7, 0x9F74, 0xC6EA, 0x9F75, 0xC6EB, 0x9F76, 0xC6ED, 0x9F77, 0xC6EE, 0x9F78, 0xC6EF, 0x9F79, 0xC6F1, 0x9F7A, 0xC6F2, + 0x9F81, 0xC6F3, 0x9F82, 0xC6F4, 0x9F83, 0xC6F5, 0x9F84, 0xC6F6, 0x9F85, 0xC6F7, 0x9F86, 0xC6FA, 0x9F87, 0xC6FB, 0x9F88, 0xC6FC, + 0x9F89, 0xC6FE, 0x9F8A, 0xC6FF, 0x9F8B, 0xC700, 0x9F8C, 0xC701, 0x9F8D, 0xC702, 0x9F8E, 0xC703, 0x9F8F, 0xC706, 0x9F90, 0xC707, + 0x9F91, 0xC709, 0x9F92, 0xC70A, 0x9F93, 0xC70B, 0x9F94, 0xC70D, 0x9F95, 0xC70E, 0x9F96, 0xC70F, 0x9F97, 0xC710, 0x9F98, 0xC711, + 0x9F99, 0xC712, 0x9F9A, 0xC713, 0x9F9B, 0xC716, 0x9F9C, 0xC718, 0x9F9D, 0xC71A, 0x9F9E, 0xC71B, 0x9F9F, 0xC71C, 0x9FA0, 0xC71D, + 0x9FA1, 0xC71E, 0x9FA2, 0xC71F, 0x9FA3, 0xC722, 0x9FA4, 0xC723, 0x9FA5, 0xC725, 0x9FA6, 0xC726, 0x9FA7, 0xC727, 0x9FA8, 0xC729, + 0x9FA9, 0xC72A, 0x9FAA, 0xC72B, 0x9FAB, 0xC72C, 0x9FAC, 0xC72D, 0x9FAD, 0xC72E, 0x9FAE, 0xC72F, 0x9FAF, 0xC732, 0x9FB0, 0xC734, + 0x9FB1, 0xC736, 0x9FB2, 0xC738, 0x9FB3, 0xC739, 0x9FB4, 0xC73A, 0x9FB5, 0xC73B, 0x9FB6, 0xC73E, 0x9FB7, 0xC73F, 0x9FB8, 0xC741, + 0x9FB9, 0xC742, 0x9FBA, 0xC743, 0x9FBB, 0xC745, 0x9FBC, 0xC746, 0x9FBD, 0xC747, 0x9FBE, 0xC748, 0x9FBF, 0xC749, 0x9FC0, 0xC74B, + 0x9FC1, 0xC74E, 0x9FC2, 0xC750, 0x9FC3, 0xC759, 0x9FC4, 0xC75A, 0x9FC5, 0xC75B, 0x9FC6, 0xC75D, 0x9FC7, 0xC75E, 0x9FC8, 0xC75F, + 0x9FC9, 0xC761, 0x9FCA, 0xC762, 0x9FCB, 0xC763, 0x9FCC, 0xC764, 0x9FCD, 0xC765, 0x9FCE, 0xC766, 0x9FCF, 0xC767, 0x9FD0, 0xC769, + 0x9FD1, 0xC76A, 0x9FD2, 0xC76C, 0x9FD3, 0xC76D, 0x9FD4, 0xC76E, 0x9FD5, 0xC76F, 0x9FD6, 0xC770, 0x9FD7, 0xC771, 0x9FD8, 0xC772, + 0x9FD9, 0xC773, 0x9FDA, 0xC776, 0x9FDB, 0xC777, 0x9FDC, 0xC779, 0x9FDD, 0xC77A, 0x9FDE, 0xC77B, 0x9FDF, 0xC77F, 0x9FE0, 0xC780, + 0x9FE1, 0xC781, 0x9FE2, 0xC782, 0x9FE3, 0xC786, 0x9FE4, 0xC78B, 0x9FE5, 0xC78C, 0x9FE6, 0xC78D, 0x9FE7, 0xC78F, 0x9FE8, 0xC792, + 0x9FE9, 0xC793, 0x9FEA, 0xC795, 0x9FEB, 0xC799, 0x9FEC, 0xC79B, 0x9FED, 0xC79C, 0x9FEE, 0xC79D, 0x9FEF, 0xC79E, 0x9FF0, 0xC79F, + 0x9FF1, 0xC7A2, 0x9FF2, 0xC7A7, 0x9FF3, 0xC7A8, 0x9FF4, 0xC7A9, 0x9FF5, 0xC7AA, 0x9FF6, 0xC7AB, 0x9FF7, 0xC7AE, 0x9FF8, 0xC7AF, + 0x9FF9, 0xC7B1, 0x9FFA, 0xC7B2, 0x9FFB, 0xC7B3, 0x9FFC, 0xC7B5, 0x9FFD, 0xC7B6, 0x9FFE, 0xC7B7, 0xA041, 0xC7B8, 0xA042, 0xC7B9, + 0xA043, 0xC7BA, 0xA044, 0xC7BB, 0xA045, 0xC7BE, 0xA046, 0xC7C2, 0xA047, 0xC7C3, 0xA048, 0xC7C4, 0xA049, 0xC7C5, 0xA04A, 0xC7C6, + 0xA04B, 0xC7C7, 0xA04C, 0xC7CA, 0xA04D, 0xC7CB, 0xA04E, 0xC7CD, 0xA04F, 0xC7CF, 0xA050, 0xC7D1, 0xA051, 0xC7D2, 0xA052, 0xC7D3, + 0xA053, 0xC7D4, 0xA054, 0xC7D5, 0xA055, 0xC7D6, 0xA056, 0xC7D7, 0xA057, 0xC7D9, 0xA058, 0xC7DA, 0xA059, 0xC7DB, 0xA05A, 0xC7DC, + 0xA061, 0xC7DE, 0xA062, 0xC7DF, 0xA063, 0xC7E0, 0xA064, 0xC7E1, 0xA065, 0xC7E2, 0xA066, 0xC7E3, 0xA067, 0xC7E5, 0xA068, 0xC7E6, + 0xA069, 0xC7E7, 0xA06A, 0xC7E9, 0xA06B, 0xC7EA, 0xA06C, 0xC7EB, 0xA06D, 0xC7ED, 0xA06E, 0xC7EE, 0xA06F, 0xC7EF, 0xA070, 0xC7F0, + 0xA071, 0xC7F1, 0xA072, 0xC7F2, 0xA073, 0xC7F3, 0xA074, 0xC7F4, 0xA075, 0xC7F5, 0xA076, 0xC7F6, 0xA077, 0xC7F7, 0xA078, 0xC7F8, + 0xA079, 0xC7F9, 0xA07A, 0xC7FA, 0xA081, 0xC7FB, 0xA082, 0xC7FC, 0xA083, 0xC7FD, 0xA084, 0xC7FE, 0xA085, 0xC7FF, 0xA086, 0xC802, + 0xA087, 0xC803, 0xA088, 0xC805, 0xA089, 0xC806, 0xA08A, 0xC807, 0xA08B, 0xC809, 0xA08C, 0xC80B, 0xA08D, 0xC80C, 0xA08E, 0xC80D, + 0xA08F, 0xC80E, 0xA090, 0xC80F, 0xA091, 0xC812, 0xA092, 0xC814, 0xA093, 0xC817, 0xA094, 0xC818, 0xA095, 0xC819, 0xA096, 0xC81A, + 0xA097, 0xC81B, 0xA098, 0xC81E, 0xA099, 0xC81F, 0xA09A, 0xC821, 0xA09B, 0xC822, 0xA09C, 0xC823, 0xA09D, 0xC825, 0xA09E, 0xC826, + 0xA09F, 0xC827, 0xA0A0, 0xC828, 0xA0A1, 0xC829, 0xA0A2, 0xC82A, 0xA0A3, 0xC82B, 0xA0A4, 0xC82E, 0xA0A5, 0xC830, 0xA0A6, 0xC832, + 0xA0A7, 0xC833, 0xA0A8, 0xC834, 0xA0A9, 0xC835, 0xA0AA, 0xC836, 0xA0AB, 0xC837, 0xA0AC, 0xC839, 0xA0AD, 0xC83A, 0xA0AE, 0xC83B, + 0xA0AF, 0xC83D, 0xA0B0, 0xC83E, 0xA0B1, 0xC83F, 0xA0B2, 0xC841, 0xA0B3, 0xC842, 0xA0B4, 0xC843, 0xA0B5, 0xC844, 0xA0B6, 0xC845, + 0xA0B7, 0xC846, 0xA0B8, 0xC847, 0xA0B9, 0xC84A, 0xA0BA, 0xC84B, 0xA0BB, 0xC84E, 0xA0BC, 0xC84F, 0xA0BD, 0xC850, 0xA0BE, 0xC851, + 0xA0BF, 0xC852, 0xA0C0, 0xC853, 0xA0C1, 0xC855, 0xA0C2, 0xC856, 0xA0C3, 0xC857, 0xA0C4, 0xC858, 0xA0C5, 0xC859, 0xA0C6, 0xC85A, + 0xA0C7, 0xC85B, 0xA0C8, 0xC85C, 0xA0C9, 0xC85D, 0xA0CA, 0xC85E, 0xA0CB, 0xC85F, 0xA0CC, 0xC860, 0xA0CD, 0xC861, 0xA0CE, 0xC862, + 0xA0CF, 0xC863, 0xA0D0, 0xC864, 0xA0D1, 0xC865, 0xA0D2, 0xC866, 0xA0D3, 0xC867, 0xA0D4, 0xC868, 0xA0D5, 0xC869, 0xA0D6, 0xC86A, + 0xA0D7, 0xC86B, 0xA0D8, 0xC86C, 0xA0D9, 0xC86D, 0xA0DA, 0xC86E, 0xA0DB, 0xC86F, 0xA0DC, 0xC872, 0xA0DD, 0xC873, 0xA0DE, 0xC875, + 0xA0DF, 0xC876, 0xA0E0, 0xC877, 0xA0E1, 0xC879, 0xA0E2, 0xC87B, 0xA0E3, 0xC87C, 0xA0E4, 0xC87D, 0xA0E5, 0xC87E, 0xA0E6, 0xC87F, + 0xA0E7, 0xC882, 0xA0E8, 0xC884, 0xA0E9, 0xC888, 0xA0EA, 0xC889, 0xA0EB, 0xC88A, 0xA0EC, 0xC88E, 0xA0ED, 0xC88F, 0xA0EE, 0xC890, + 0xA0EF, 0xC891, 0xA0F0, 0xC892, 0xA0F1, 0xC893, 0xA0F2, 0xC895, 0xA0F3, 0xC896, 0xA0F4, 0xC897, 0xA0F5, 0xC898, 0xA0F6, 0xC899, + 0xA0F7, 0xC89A, 0xA0F8, 0xC89B, 0xA0F9, 0xC89C, 0xA0FA, 0xC89E, 0xA0FB, 0xC8A0, 0xA0FC, 0xC8A2, 0xA0FD, 0xC8A3, 0xA0FE, 0xC8A4, + 0xA141, 0xC8A5, 0xA142, 0xC8A6, 0xA143, 0xC8A7, 0xA144, 0xC8A9, 0xA145, 0xC8AA, 0xA146, 0xC8AB, 0xA147, 0xC8AC, 0xA148, 0xC8AD, + 0xA149, 0xC8AE, 0xA14A, 0xC8AF, 0xA14B, 0xC8B0, 0xA14C, 0xC8B1, 0xA14D, 0xC8B2, 0xA14E, 0xC8B3, 0xA14F, 0xC8B4, 0xA150, 0xC8B5, + 0xA151, 0xC8B6, 0xA152, 0xC8B7, 0xA153, 0xC8B8, 0xA154, 0xC8B9, 0xA155, 0xC8BA, 0xA156, 0xC8BB, 0xA157, 0xC8BE, 0xA158, 0xC8BF, + 0xA159, 0xC8C0, 0xA15A, 0xC8C1, 0xA161, 0xC8C2, 0xA162, 0xC8C3, 0xA163, 0xC8C5, 0xA164, 0xC8C6, 0xA165, 0xC8C7, 0xA166, 0xC8C9, + 0xA167, 0xC8CA, 0xA168, 0xC8CB, 0xA169, 0xC8CD, 0xA16A, 0xC8CE, 0xA16B, 0xC8CF, 0xA16C, 0xC8D0, 0xA16D, 0xC8D1, 0xA16E, 0xC8D2, + 0xA16F, 0xC8D3, 0xA170, 0xC8D6, 0xA171, 0xC8D8, 0xA172, 0xC8DA, 0xA173, 0xC8DB, 0xA174, 0xC8DC, 0xA175, 0xC8DD, 0xA176, 0xC8DE, + 0xA177, 0xC8DF, 0xA178, 0xC8E2, 0xA179, 0xC8E3, 0xA17A, 0xC8E5, 0xA181, 0xC8E6, 0xA182, 0xC8E7, 0xA183, 0xC8E8, 0xA184, 0xC8E9, + 0xA185, 0xC8EA, 0xA186, 0xC8EB, 0xA187, 0xC8EC, 0xA188, 0xC8ED, 0xA189, 0xC8EE, 0xA18A, 0xC8EF, 0xA18B, 0xC8F0, 0xA18C, 0xC8F1, + 0xA18D, 0xC8F2, 0xA18E, 0xC8F3, 0xA18F, 0xC8F4, 0xA190, 0xC8F6, 0xA191, 0xC8F7, 0xA192, 0xC8F8, 0xA193, 0xC8F9, 0xA194, 0xC8FA, + 0xA195, 0xC8FB, 0xA196, 0xC8FE, 0xA197, 0xC8FF, 0xA198, 0xC901, 0xA199, 0xC902, 0xA19A, 0xC903, 0xA19B, 0xC907, 0xA19C, 0xC908, + 0xA19D, 0xC909, 0xA19E, 0xC90A, 0xA19F, 0xC90B, 0xA1A0, 0xC90E, 0xA1A1, 0x3000, 0xA1A2, 0x3001, 0xA1A3, 0x3002, 0xA1A4, 0x00B7, + 0xA1A5, 0x2025, 0xA1A6, 0x2026, 0xA1A7, 0x00A8, 0xA1A8, 0x3003, 0xA1A9, 0x00AD, 0xA1AA, 0x2015, 0xA1AB, 0x2225, 0xA1AC, 0xFF3C, + 0xA1AD, 0x223C, 0xA1AE, 0x2018, 0xA1AF, 0x2019, 0xA1B0, 0x201C, 0xA1B1, 0x201D, 0xA1B2, 0x3014, 0xA1B3, 0x3015, 0xA1B4, 0x3008, + 0xA1B5, 0x3009, 0xA1B6, 0x300A, 0xA1B7, 0x300B, 0xA1B8, 0x300C, 0xA1B9, 0x300D, 0xA1BA, 0x300E, 0xA1BB, 0x300F, 0xA1BC, 0x3010, + 0xA1BD, 0x3011, 0xA1BE, 0x00B1, 0xA1BF, 0x00D7, 0xA1C0, 0x00F7, 0xA1C1, 0x2260, 0xA1C2, 0x2264, 0xA1C3, 0x2265, 0xA1C4, 0x221E, + 0xA1C5, 0x2234, 0xA1C6, 0x00B0, 0xA1C7, 0x2032, 0xA1C8, 0x2033, 0xA1C9, 0x2103, 0xA1CA, 0x212B, 0xA1CB, 0xFFE0, 0xA1CC, 0xFFE1, + 0xA1CD, 0xFFE5, 0xA1CE, 0x2642, 0xA1CF, 0x2640, 0xA1D0, 0x2220, 0xA1D1, 0x22A5, 0xA1D2, 0x2312, 0xA1D3, 0x2202, 0xA1D4, 0x2207, + 0xA1D5, 0x2261, 0xA1D6, 0x2252, 0xA1D7, 0x00A7, 0xA1D8, 0x203B, 0xA1D9, 0x2606, 0xA1DA, 0x2605, 0xA1DB, 0x25CB, 0xA1DC, 0x25CF, + 0xA1DD, 0x25CE, 0xA1DE, 0x25C7, 0xA1DF, 0x25C6, 0xA1E0, 0x25A1, 0xA1E1, 0x25A0, 0xA1E2, 0x25B3, 0xA1E3, 0x25B2, 0xA1E4, 0x25BD, + 0xA1E5, 0x25BC, 0xA1E6, 0x2192, 0xA1E7, 0x2190, 0xA1E8, 0x2191, 0xA1E9, 0x2193, 0xA1EA, 0x2194, 0xA1EB, 0x3013, 0xA1EC, 0x226A, + 0xA1ED, 0x226B, 0xA1EE, 0x221A, 0xA1EF, 0x223D, 0xA1F0, 0x221D, 0xA1F1, 0x2235, 0xA1F2, 0x222B, 0xA1F3, 0x222C, 0xA1F4, 0x2208, + 0xA1F5, 0x220B, 0xA1F6, 0x2286, 0xA1F7, 0x2287, 0xA1F8, 0x2282, 0xA1F9, 0x2283, 0xA1FA, 0x222A, 0xA1FB, 0x2229, 0xA1FC, 0x2227, + 0xA1FD, 0x2228, 0xA1FE, 0xFFE2, 0xA241, 0xC910, 0xA242, 0xC912, 0xA243, 0xC913, 0xA244, 0xC914, 0xA245, 0xC915, 0xA246, 0xC916, + 0xA247, 0xC917, 0xA248, 0xC919, 0xA249, 0xC91A, 0xA24A, 0xC91B, 0xA24B, 0xC91C, 0xA24C, 0xC91D, 0xA24D, 0xC91E, 0xA24E, 0xC91F, + 0xA24F, 0xC920, 0xA250, 0xC921, 0xA251, 0xC922, 0xA252, 0xC923, 0xA253, 0xC924, 0xA254, 0xC925, 0xA255, 0xC926, 0xA256, 0xC927, + 0xA257, 0xC928, 0xA258, 0xC929, 0xA259, 0xC92A, 0xA25A, 0xC92B, 0xA261, 0xC92D, 0xA262, 0xC92E, 0xA263, 0xC92F, 0xA264, 0xC930, + 0xA265, 0xC931, 0xA266, 0xC932, 0xA267, 0xC933, 0xA268, 0xC935, 0xA269, 0xC936, 0xA26A, 0xC937, 0xA26B, 0xC938, 0xA26C, 0xC939, + 0xA26D, 0xC93A, 0xA26E, 0xC93B, 0xA26F, 0xC93C, 0xA270, 0xC93D, 0xA271, 0xC93E, 0xA272, 0xC93F, 0xA273, 0xC940, 0xA274, 0xC941, + 0xA275, 0xC942, 0xA276, 0xC943, 0xA277, 0xC944, 0xA278, 0xC945, 0xA279, 0xC946, 0xA27A, 0xC947, 0xA281, 0xC948, 0xA282, 0xC949, + 0xA283, 0xC94A, 0xA284, 0xC94B, 0xA285, 0xC94C, 0xA286, 0xC94D, 0xA287, 0xC94E, 0xA288, 0xC94F, 0xA289, 0xC952, 0xA28A, 0xC953, + 0xA28B, 0xC955, 0xA28C, 0xC956, 0xA28D, 0xC957, 0xA28E, 0xC959, 0xA28F, 0xC95A, 0xA290, 0xC95B, 0xA291, 0xC95C, 0xA292, 0xC95D, + 0xA293, 0xC95E, 0xA294, 0xC95F, 0xA295, 0xC962, 0xA296, 0xC964, 0xA297, 0xC965, 0xA298, 0xC966, 0xA299, 0xC967, 0xA29A, 0xC968, + 0xA29B, 0xC969, 0xA29C, 0xC96A, 0xA29D, 0xC96B, 0xA29E, 0xC96D, 0xA29F, 0xC96E, 0xA2A0, 0xC96F, 0xA2A1, 0x21D2, 0xA2A2, 0x21D4, + 0xA2A3, 0x2200, 0xA2A4, 0x2203, 0xA2A5, 0x00B4, 0xA2A6, 0xFF5E, 0xA2A7, 0x02C7, 0xA2A8, 0x02D8, 0xA2A9, 0x02DD, 0xA2AA, 0x02DA, + 0xA2AB, 0x02D9, 0xA2AC, 0x00B8, 0xA2AD, 0x02DB, 0xA2AE, 0x00A1, 0xA2AF, 0x00BF, 0xA2B0, 0x02D0, 0xA2B1, 0x222E, 0xA2B2, 0x2211, + 0xA2B3, 0x220F, 0xA2B4, 0x00A4, 0xA2B5, 0x2109, 0xA2B6, 0x2030, 0xA2B7, 0x25C1, 0xA2B8, 0x25C0, 0xA2B9, 0x25B7, 0xA2BA, 0x25B6, + 0xA2BB, 0x2664, 0xA2BC, 0x2660, 0xA2BD, 0x2661, 0xA2BE, 0x2665, 0xA2BF, 0x2667, 0xA2C0, 0x2663, 0xA2C1, 0x2299, 0xA2C2, 0x25C8, + 0xA2C3, 0x25A3, 0xA2C4, 0x25D0, 0xA2C5, 0x25D1, 0xA2C6, 0x2592, 0xA2C7, 0x25A4, 0xA2C8, 0x25A5, 0xA2C9, 0x25A8, 0xA2CA, 0x25A7, + 0xA2CB, 0x25A6, 0xA2CC, 0x25A9, 0xA2CD, 0x2668, 0xA2CE, 0x260F, 0xA2CF, 0x260E, 0xA2D0, 0x261C, 0xA2D1, 0x261E, 0xA2D2, 0x00B6, + 0xA2D3, 0x2020, 0xA2D4, 0x2021, 0xA2D5, 0x2195, 0xA2D6, 0x2197, 0xA2D7, 0x2199, 0xA2D8, 0x2196, 0xA2D9, 0x2198, 0xA2DA, 0x266D, + 0xA2DB, 0x2669, 0xA2DC, 0x266A, 0xA2DD, 0x266C, 0xA2DE, 0x327F, 0xA2DF, 0x321C, 0xA2E0, 0x2116, 0xA2E1, 0x33C7, 0xA2E2, 0x2122, + 0xA2E3, 0x33C2, 0xA2E4, 0x33D8, 0xA2E5, 0x2121, 0xA2E6, 0x20AC, 0xA2E7, 0x00AE, 0xA341, 0xC971, 0xA342, 0xC972, 0xA343, 0xC973, + 0xA344, 0xC975, 0xA345, 0xC976, 0xA346, 0xC977, 0xA347, 0xC978, 0xA348, 0xC979, 0xA349, 0xC97A, 0xA34A, 0xC97B, 0xA34B, 0xC97D, + 0xA34C, 0xC97E, 0xA34D, 0xC97F, 0xA34E, 0xC980, 0xA34F, 0xC981, 0xA350, 0xC982, 0xA351, 0xC983, 0xA352, 0xC984, 0xA353, 0xC985, + 0xA354, 0xC986, 0xA355, 0xC987, 0xA356, 0xC98A, 0xA357, 0xC98B, 0xA358, 0xC98D, 0xA359, 0xC98E, 0xA35A, 0xC98F, 0xA361, 0xC991, + 0xA362, 0xC992, 0xA363, 0xC993, 0xA364, 0xC994, 0xA365, 0xC995, 0xA366, 0xC996, 0xA367, 0xC997, 0xA368, 0xC99A, 0xA369, 0xC99C, + 0xA36A, 0xC99E, 0xA36B, 0xC99F, 0xA36C, 0xC9A0, 0xA36D, 0xC9A1, 0xA36E, 0xC9A2, 0xA36F, 0xC9A3, 0xA370, 0xC9A4, 0xA371, 0xC9A5, + 0xA372, 0xC9A6, 0xA373, 0xC9A7, 0xA374, 0xC9A8, 0xA375, 0xC9A9, 0xA376, 0xC9AA, 0xA377, 0xC9AB, 0xA378, 0xC9AC, 0xA379, 0xC9AD, + 0xA37A, 0xC9AE, 0xA381, 0xC9AF, 0xA382, 0xC9B0, 0xA383, 0xC9B1, 0xA384, 0xC9B2, 0xA385, 0xC9B3, 0xA386, 0xC9B4, 0xA387, 0xC9B5, + 0xA388, 0xC9B6, 0xA389, 0xC9B7, 0xA38A, 0xC9B8, 0xA38B, 0xC9B9, 0xA38C, 0xC9BA, 0xA38D, 0xC9BB, 0xA38E, 0xC9BC, 0xA38F, 0xC9BD, + 0xA390, 0xC9BE, 0xA391, 0xC9BF, 0xA392, 0xC9C2, 0xA393, 0xC9C3, 0xA394, 0xC9C5, 0xA395, 0xC9C6, 0xA396, 0xC9C9, 0xA397, 0xC9CB, + 0xA398, 0xC9CC, 0xA399, 0xC9CD, 0xA39A, 0xC9CE, 0xA39B, 0xC9CF, 0xA39C, 0xC9D2, 0xA39D, 0xC9D4, 0xA39E, 0xC9D7, 0xA39F, 0xC9D8, + 0xA3A0, 0xC9DB, 0xA3A1, 0xFF01, 0xA3A2, 0xFF02, 0xA3A3, 0xFF03, 0xA3A4, 0xFF04, 0xA3A5, 0xFF05, 0xA3A6, 0xFF06, 0xA3A7, 0xFF07, + 0xA3A8, 0xFF08, 0xA3A9, 0xFF09, 0xA3AA, 0xFF0A, 0xA3AB, 0xFF0B, 0xA3AC, 0xFF0C, 0xA3AD, 0xFF0D, 0xA3AE, 0xFF0E, 0xA3AF, 0xFF0F, + 0xA3B0, 0xFF10, 0xA3B1, 0xFF11, 0xA3B2, 0xFF12, 0xA3B3, 0xFF13, 0xA3B4, 0xFF14, 0xA3B5, 0xFF15, 0xA3B6, 0xFF16, 0xA3B7, 0xFF17, + 0xA3B8, 0xFF18, 0xA3B9, 0xFF19, 0xA3BA, 0xFF1A, 0xA3BB, 0xFF1B, 0xA3BC, 0xFF1C, 0xA3BD, 0xFF1D, 0xA3BE, 0xFF1E, 0xA3BF, 0xFF1F, + 0xA3C0, 0xFF20, 0xA3C1, 0xFF21, 0xA3C2, 0xFF22, 0xA3C3, 0xFF23, 0xA3C4, 0xFF24, 0xA3C5, 0xFF25, 0xA3C6, 0xFF26, 0xA3C7, 0xFF27, + 0xA3C8, 0xFF28, 0xA3C9, 0xFF29, 0xA3CA, 0xFF2A, 0xA3CB, 0xFF2B, 0xA3CC, 0xFF2C, 0xA3CD, 0xFF2D, 0xA3CE, 0xFF2E, 0xA3CF, 0xFF2F, + 0xA3D0, 0xFF30, 0xA3D1, 0xFF31, 0xA3D2, 0xFF32, 0xA3D3, 0xFF33, 0xA3D4, 0xFF34, 0xA3D5, 0xFF35, 0xA3D6, 0xFF36, 0xA3D7, 0xFF37, + 0xA3D8, 0xFF38, 0xA3D9, 0xFF39, 0xA3DA, 0xFF3A, 0xA3DB, 0xFF3B, 0xA3DC, 0xFFE6, 0xA3DD, 0xFF3D, 0xA3DE, 0xFF3E, 0xA3DF, 0xFF3F, + 0xA3E0, 0xFF40, 0xA3E1, 0xFF41, 0xA3E2, 0xFF42, 0xA3E3, 0xFF43, 0xA3E4, 0xFF44, 0xA3E5, 0xFF45, 0xA3E6, 0xFF46, 0xA3E7, 0xFF47, + 0xA3E8, 0xFF48, 0xA3E9, 0xFF49, 0xA3EA, 0xFF4A, 0xA3EB, 0xFF4B, 0xA3EC, 0xFF4C, 0xA3ED, 0xFF4D, 0xA3EE, 0xFF4E, 0xA3EF, 0xFF4F, + 0xA3F0, 0xFF50, 0xA3F1, 0xFF51, 0xA3F2, 0xFF52, 0xA3F3, 0xFF53, 0xA3F4, 0xFF54, 0xA3F5, 0xFF55, 0xA3F6, 0xFF56, 0xA3F7, 0xFF57, + 0xA3F8, 0xFF58, 0xA3F9, 0xFF59, 0xA3FA, 0xFF5A, 0xA3FB, 0xFF5B, 0xA3FC, 0xFF5C, 0xA3FD, 0xFF5D, 0xA3FE, 0xFFE3, 0xA441, 0xC9DE, + 0xA442, 0xC9DF, 0xA443, 0xC9E1, 0xA444, 0xC9E3, 0xA445, 0xC9E5, 0xA446, 0xC9E6, 0xA447, 0xC9E8, 0xA448, 0xC9E9, 0xA449, 0xC9EA, + 0xA44A, 0xC9EB, 0xA44B, 0xC9EE, 0xA44C, 0xC9F2, 0xA44D, 0xC9F3, 0xA44E, 0xC9F4, 0xA44F, 0xC9F5, 0xA450, 0xC9F6, 0xA451, 0xC9F7, + 0xA452, 0xC9FA, 0xA453, 0xC9FB, 0xA454, 0xC9FD, 0xA455, 0xC9FE, 0xA456, 0xC9FF, 0xA457, 0xCA01, 0xA458, 0xCA02, 0xA459, 0xCA03, + 0xA45A, 0xCA04, 0xA461, 0xCA05, 0xA462, 0xCA06, 0xA463, 0xCA07, 0xA464, 0xCA0A, 0xA465, 0xCA0E, 0xA466, 0xCA0F, 0xA467, 0xCA10, + 0xA468, 0xCA11, 0xA469, 0xCA12, 0xA46A, 0xCA13, 0xA46B, 0xCA15, 0xA46C, 0xCA16, 0xA46D, 0xCA17, 0xA46E, 0xCA19, 0xA46F, 0xCA1A, + 0xA470, 0xCA1B, 0xA471, 0xCA1C, 0xA472, 0xCA1D, 0xA473, 0xCA1E, 0xA474, 0xCA1F, 0xA475, 0xCA20, 0xA476, 0xCA21, 0xA477, 0xCA22, + 0xA478, 0xCA23, 0xA479, 0xCA24, 0xA47A, 0xCA25, 0xA481, 0xCA26, 0xA482, 0xCA27, 0xA483, 0xCA28, 0xA484, 0xCA2A, 0xA485, 0xCA2B, + 0xA486, 0xCA2C, 0xA487, 0xCA2D, 0xA488, 0xCA2E, 0xA489, 0xCA2F, 0xA48A, 0xCA30, 0xA48B, 0xCA31, 0xA48C, 0xCA32, 0xA48D, 0xCA33, + 0xA48E, 0xCA34, 0xA48F, 0xCA35, 0xA490, 0xCA36, 0xA491, 0xCA37, 0xA492, 0xCA38, 0xA493, 0xCA39, 0xA494, 0xCA3A, 0xA495, 0xCA3B, + 0xA496, 0xCA3C, 0xA497, 0xCA3D, 0xA498, 0xCA3E, 0xA499, 0xCA3F, 0xA49A, 0xCA40, 0xA49B, 0xCA41, 0xA49C, 0xCA42, 0xA49D, 0xCA43, + 0xA49E, 0xCA44, 0xA49F, 0xCA45, 0xA4A0, 0xCA46, 0xA4A1, 0x3131, 0xA4A2, 0x3132, 0xA4A3, 0x3133, 0xA4A4, 0x3134, 0xA4A5, 0x3135, + 0xA4A6, 0x3136, 0xA4A7, 0x3137, 0xA4A8, 0x3138, 0xA4A9, 0x3139, 0xA4AA, 0x313A, 0xA4AB, 0x313B, 0xA4AC, 0x313C, 0xA4AD, 0x313D, + 0xA4AE, 0x313E, 0xA4AF, 0x313F, 0xA4B0, 0x3140, 0xA4B1, 0x3141, 0xA4B2, 0x3142, 0xA4B3, 0x3143, 0xA4B4, 0x3144, 0xA4B5, 0x3145, + 0xA4B6, 0x3146, 0xA4B7, 0x3147, 0xA4B8, 0x3148, 0xA4B9, 0x3149, 0xA4BA, 0x314A, 0xA4BB, 0x314B, 0xA4BC, 0x314C, 0xA4BD, 0x314D, + 0xA4BE, 0x314E, 0xA4BF, 0x314F, 0xA4C0, 0x3150, 0xA4C1, 0x3151, 0xA4C2, 0x3152, 0xA4C3, 0x3153, 0xA4C4, 0x3154, 0xA4C5, 0x3155, + 0xA4C6, 0x3156, 0xA4C7, 0x3157, 0xA4C8, 0x3158, 0xA4C9, 0x3159, 0xA4CA, 0x315A, 0xA4CB, 0x315B, 0xA4CC, 0x315C, 0xA4CD, 0x315D, + 0xA4CE, 0x315E, 0xA4CF, 0x315F, 0xA4D0, 0x3160, 0xA4D1, 0x3161, 0xA4D2, 0x3162, 0xA4D3, 0x3163, 0xA4D4, 0x3164, 0xA4D5, 0x3165, + 0xA4D6, 0x3166, 0xA4D7, 0x3167, 0xA4D8, 0x3168, 0xA4D9, 0x3169, 0xA4DA, 0x316A, 0xA4DB, 0x316B, 0xA4DC, 0x316C, 0xA4DD, 0x316D, + 0xA4DE, 0x316E, 0xA4DF, 0x316F, 0xA4E0, 0x3170, 0xA4E1, 0x3171, 0xA4E2, 0x3172, 0xA4E3, 0x3173, 0xA4E4, 0x3174, 0xA4E5, 0x3175, + 0xA4E6, 0x3176, 0xA4E7, 0x3177, 0xA4E8, 0x3178, 0xA4E9, 0x3179, 0xA4EA, 0x317A, 0xA4EB, 0x317B, 0xA4EC, 0x317C, 0xA4ED, 0x317D, + 0xA4EE, 0x317E, 0xA4EF, 0x317F, 0xA4F0, 0x3180, 0xA4F1, 0x3181, 0xA4F2, 0x3182, 0xA4F3, 0x3183, 0xA4F4, 0x3184, 0xA4F5, 0x3185, + 0xA4F6, 0x3186, 0xA4F7, 0x3187, 0xA4F8, 0x3188, 0xA4F9, 0x3189, 0xA4FA, 0x318A, 0xA4FB, 0x318B, 0xA4FC, 0x318C, 0xA4FD, 0x318D, + 0xA4FE, 0x318E, 0xA541, 0xCA47, 0xA542, 0xCA48, 0xA543, 0xCA49, 0xA544, 0xCA4A, 0xA545, 0xCA4B, 0xA546, 0xCA4E, 0xA547, 0xCA4F, + 0xA548, 0xCA51, 0xA549, 0xCA52, 0xA54A, 0xCA53, 0xA54B, 0xCA55, 0xA54C, 0xCA56, 0xA54D, 0xCA57, 0xA54E, 0xCA58, 0xA54F, 0xCA59, + 0xA550, 0xCA5A, 0xA551, 0xCA5B, 0xA552, 0xCA5E, 0xA553, 0xCA62, 0xA554, 0xCA63, 0xA555, 0xCA64, 0xA556, 0xCA65, 0xA557, 0xCA66, + 0xA558, 0xCA67, 0xA559, 0xCA69, 0xA55A, 0xCA6A, 0xA561, 0xCA6B, 0xA562, 0xCA6C, 0xA563, 0xCA6D, 0xA564, 0xCA6E, 0xA565, 0xCA6F, + 0xA566, 0xCA70, 0xA567, 0xCA71, 0xA568, 0xCA72, 0xA569, 0xCA73, 0xA56A, 0xCA74, 0xA56B, 0xCA75, 0xA56C, 0xCA76, 0xA56D, 0xCA77, + 0xA56E, 0xCA78, 0xA56F, 0xCA79, 0xA570, 0xCA7A, 0xA571, 0xCA7B, 0xA572, 0xCA7C, 0xA573, 0xCA7E, 0xA574, 0xCA7F, 0xA575, 0xCA80, + 0xA576, 0xCA81, 0xA577, 0xCA82, 0xA578, 0xCA83, 0xA579, 0xCA85, 0xA57A, 0xCA86, 0xA581, 0xCA87, 0xA582, 0xCA88, 0xA583, 0xCA89, + 0xA584, 0xCA8A, 0xA585, 0xCA8B, 0xA586, 0xCA8C, 0xA587, 0xCA8D, 0xA588, 0xCA8E, 0xA589, 0xCA8F, 0xA58A, 0xCA90, 0xA58B, 0xCA91, + 0xA58C, 0xCA92, 0xA58D, 0xCA93, 0xA58E, 0xCA94, 0xA58F, 0xCA95, 0xA590, 0xCA96, 0xA591, 0xCA97, 0xA592, 0xCA99, 0xA593, 0xCA9A, + 0xA594, 0xCA9B, 0xA595, 0xCA9C, 0xA596, 0xCA9D, 0xA597, 0xCA9E, 0xA598, 0xCA9F, 0xA599, 0xCAA0, 0xA59A, 0xCAA1, 0xA59B, 0xCAA2, + 0xA59C, 0xCAA3, 0xA59D, 0xCAA4, 0xA59E, 0xCAA5, 0xA59F, 0xCAA6, 0xA5A0, 0xCAA7, 0xA5A1, 0x2170, 0xA5A2, 0x2171, 0xA5A3, 0x2172, + 0xA5A4, 0x2173, 0xA5A5, 0x2174, 0xA5A6, 0x2175, 0xA5A7, 0x2176, 0xA5A8, 0x2177, 0xA5A9, 0x2178, 0xA5AA, 0x2179, 0xA5B0, 0x2160, + 0xA5B1, 0x2161, 0xA5B2, 0x2162, 0xA5B3, 0x2163, 0xA5B4, 0x2164, 0xA5B5, 0x2165, 0xA5B6, 0x2166, 0xA5B7, 0x2167, 0xA5B8, 0x2168, + 0xA5B9, 0x2169, 0xA5C1, 0x0391, 0xA5C2, 0x0392, 0xA5C3, 0x0393, 0xA5C4, 0x0394, 0xA5C5, 0x0395, 0xA5C6, 0x0396, 0xA5C7, 0x0397, + 0xA5C8, 0x0398, 0xA5C9, 0x0399, 0xA5CA, 0x039A, 0xA5CB, 0x039B, 0xA5CC, 0x039C, 0xA5CD, 0x039D, 0xA5CE, 0x039E, 0xA5CF, 0x039F, + 0xA5D0, 0x03A0, 0xA5D1, 0x03A1, 0xA5D2, 0x03A3, 0xA5D3, 0x03A4, 0xA5D4, 0x03A5, 0xA5D5, 0x03A6, 0xA5D6, 0x03A7, 0xA5D7, 0x03A8, + 0xA5D8, 0x03A9, 0xA5E1, 0x03B1, 0xA5E2, 0x03B2, 0xA5E3, 0x03B3, 0xA5E4, 0x03B4, 0xA5E5, 0x03B5, 0xA5E6, 0x03B6, 0xA5E7, 0x03B7, + 0xA5E8, 0x03B8, 0xA5E9, 0x03B9, 0xA5EA, 0x03BA, 0xA5EB, 0x03BB, 0xA5EC, 0x03BC, 0xA5ED, 0x03BD, 0xA5EE, 0x03BE, 0xA5EF, 0x03BF, + 0xA5F0, 0x03C0, 0xA5F1, 0x03C1, 0xA5F2, 0x03C3, 0xA5F3, 0x03C4, 0xA5F4, 0x03C5, 0xA5F5, 0x03C6, 0xA5F6, 0x03C7, 0xA5F7, 0x03C8, + 0xA5F8, 0x03C9, 0xA641, 0xCAA8, 0xA642, 0xCAA9, 0xA643, 0xCAAA, 0xA644, 0xCAAB, 0xA645, 0xCAAC, 0xA646, 0xCAAD, 0xA647, 0xCAAE, + 0xA648, 0xCAAF, 0xA649, 0xCAB0, 0xA64A, 0xCAB1, 0xA64B, 0xCAB2, 0xA64C, 0xCAB3, 0xA64D, 0xCAB4, 0xA64E, 0xCAB5, 0xA64F, 0xCAB6, + 0xA650, 0xCAB7, 0xA651, 0xCAB8, 0xA652, 0xCAB9, 0xA653, 0xCABA, 0xA654, 0xCABB, 0xA655, 0xCABE, 0xA656, 0xCABF, 0xA657, 0xCAC1, + 0xA658, 0xCAC2, 0xA659, 0xCAC3, 0xA65A, 0xCAC5, 0xA661, 0xCAC6, 0xA662, 0xCAC7, 0xA663, 0xCAC8, 0xA664, 0xCAC9, 0xA665, 0xCACA, + 0xA666, 0xCACB, 0xA667, 0xCACE, 0xA668, 0xCAD0, 0xA669, 0xCAD2, 0xA66A, 0xCAD4, 0xA66B, 0xCAD5, 0xA66C, 0xCAD6, 0xA66D, 0xCAD7, + 0xA66E, 0xCADA, 0xA66F, 0xCADB, 0xA670, 0xCADC, 0xA671, 0xCADD, 0xA672, 0xCADE, 0xA673, 0xCADF, 0xA674, 0xCAE1, 0xA675, 0xCAE2, + 0xA676, 0xCAE3, 0xA677, 0xCAE4, 0xA678, 0xCAE5, 0xA679, 0xCAE6, 0xA67A, 0xCAE7, 0xA681, 0xCAE8, 0xA682, 0xCAE9, 0xA683, 0xCAEA, + 0xA684, 0xCAEB, 0xA685, 0xCAED, 0xA686, 0xCAEE, 0xA687, 0xCAEF, 0xA688, 0xCAF0, 0xA689, 0xCAF1, 0xA68A, 0xCAF2, 0xA68B, 0xCAF3, + 0xA68C, 0xCAF5, 0xA68D, 0xCAF6, 0xA68E, 0xCAF7, 0xA68F, 0xCAF8, 0xA690, 0xCAF9, 0xA691, 0xCAFA, 0xA692, 0xCAFB, 0xA693, 0xCAFC, + 0xA694, 0xCAFD, 0xA695, 0xCAFE, 0xA696, 0xCAFF, 0xA697, 0xCB00, 0xA698, 0xCB01, 0xA699, 0xCB02, 0xA69A, 0xCB03, 0xA69B, 0xCB04, + 0xA69C, 0xCB05, 0xA69D, 0xCB06, 0xA69E, 0xCB07, 0xA69F, 0xCB09, 0xA6A0, 0xCB0A, 0xA6A1, 0x2500, 0xA6A2, 0x2502, 0xA6A3, 0x250C, + 0xA6A4, 0x2510, 0xA6A5, 0x2518, 0xA6A6, 0x2514, 0xA6A7, 0x251C, 0xA6A8, 0x252C, 0xA6A9, 0x2524, 0xA6AA, 0x2534, 0xA6AB, 0x253C, + 0xA6AC, 0x2501, 0xA6AD, 0x2503, 0xA6AE, 0x250F, 0xA6AF, 0x2513, 0xA6B0, 0x251B, 0xA6B1, 0x2517, 0xA6B2, 0x2523, 0xA6B3, 0x2533, + 0xA6B4, 0x252B, 0xA6B5, 0x253B, 0xA6B6, 0x254B, 0xA6B7, 0x2520, 0xA6B8, 0x252F, 0xA6B9, 0x2528, 0xA6BA, 0x2537, 0xA6BB, 0x253F, + 0xA6BC, 0x251D, 0xA6BD, 0x2530, 0xA6BE, 0x2525, 0xA6BF, 0x2538, 0xA6C0, 0x2542, 0xA6C1, 0x2512, 0xA6C2, 0x2511, 0xA6C3, 0x251A, + 0xA6C4, 0x2519, 0xA6C5, 0x2516, 0xA6C6, 0x2515, 0xA6C7, 0x250E, 0xA6C8, 0x250D, 0xA6C9, 0x251E, 0xA6CA, 0x251F, 0xA6CB, 0x2521, + 0xA6CC, 0x2522, 0xA6CD, 0x2526, 0xA6CE, 0x2527, 0xA6CF, 0x2529, 0xA6D0, 0x252A, 0xA6D1, 0x252D, 0xA6D2, 0x252E, 0xA6D3, 0x2531, + 0xA6D4, 0x2532, 0xA6D5, 0x2535, 0xA6D6, 0x2536, 0xA6D7, 0x2539, 0xA6D8, 0x253A, 0xA6D9, 0x253D, 0xA6DA, 0x253E, 0xA6DB, 0x2540, + 0xA6DC, 0x2541, 0xA6DD, 0x2543, 0xA6DE, 0x2544, 0xA6DF, 0x2545, 0xA6E0, 0x2546, 0xA6E1, 0x2547, 0xA6E2, 0x2548, 0xA6E3, 0x2549, + 0xA6E4, 0x254A, 0xA741, 0xCB0B, 0xA742, 0xCB0C, 0xA743, 0xCB0D, 0xA744, 0xCB0E, 0xA745, 0xCB0F, 0xA746, 0xCB11, 0xA747, 0xCB12, + 0xA748, 0xCB13, 0xA749, 0xCB15, 0xA74A, 0xCB16, 0xA74B, 0xCB17, 0xA74C, 0xCB19, 0xA74D, 0xCB1A, 0xA74E, 0xCB1B, 0xA74F, 0xCB1C, + 0xA750, 0xCB1D, 0xA751, 0xCB1E, 0xA752, 0xCB1F, 0xA753, 0xCB22, 0xA754, 0xCB23, 0xA755, 0xCB24, 0xA756, 0xCB25, 0xA757, 0xCB26, + 0xA758, 0xCB27, 0xA759, 0xCB28, 0xA75A, 0xCB29, 0xA761, 0xCB2A, 0xA762, 0xCB2B, 0xA763, 0xCB2C, 0xA764, 0xCB2D, 0xA765, 0xCB2E, + 0xA766, 0xCB2F, 0xA767, 0xCB30, 0xA768, 0xCB31, 0xA769, 0xCB32, 0xA76A, 0xCB33, 0xA76B, 0xCB34, 0xA76C, 0xCB35, 0xA76D, 0xCB36, + 0xA76E, 0xCB37, 0xA76F, 0xCB38, 0xA770, 0xCB39, 0xA771, 0xCB3A, 0xA772, 0xCB3B, 0xA773, 0xCB3C, 0xA774, 0xCB3D, 0xA775, 0xCB3E, + 0xA776, 0xCB3F, 0xA777, 0xCB40, 0xA778, 0xCB42, 0xA779, 0xCB43, 0xA77A, 0xCB44, 0xA781, 0xCB45, 0xA782, 0xCB46, 0xA783, 0xCB47, + 0xA784, 0xCB4A, 0xA785, 0xCB4B, 0xA786, 0xCB4D, 0xA787, 0xCB4E, 0xA788, 0xCB4F, 0xA789, 0xCB51, 0xA78A, 0xCB52, 0xA78B, 0xCB53, + 0xA78C, 0xCB54, 0xA78D, 0xCB55, 0xA78E, 0xCB56, 0xA78F, 0xCB57, 0xA790, 0xCB5A, 0xA791, 0xCB5B, 0xA792, 0xCB5C, 0xA793, 0xCB5E, + 0xA794, 0xCB5F, 0xA795, 0xCB60, 0xA796, 0xCB61, 0xA797, 0xCB62, 0xA798, 0xCB63, 0xA799, 0xCB65, 0xA79A, 0xCB66, 0xA79B, 0xCB67, + 0xA79C, 0xCB68, 0xA79D, 0xCB69, 0xA79E, 0xCB6A, 0xA79F, 0xCB6B, 0xA7A0, 0xCB6C, 0xA7A1, 0x3395, 0xA7A2, 0x3396, 0xA7A3, 0x3397, + 0xA7A4, 0x2113, 0xA7A5, 0x3398, 0xA7A6, 0x33C4, 0xA7A7, 0x33A3, 0xA7A8, 0x33A4, 0xA7A9, 0x33A5, 0xA7AA, 0x33A6, 0xA7AB, 0x3399, + 0xA7AC, 0x339A, 0xA7AD, 0x339B, 0xA7AE, 0x339C, 0xA7AF, 0x339D, 0xA7B0, 0x339E, 0xA7B1, 0x339F, 0xA7B2, 0x33A0, 0xA7B3, 0x33A1, + 0xA7B4, 0x33A2, 0xA7B5, 0x33CA, 0xA7B6, 0x338D, 0xA7B7, 0x338E, 0xA7B8, 0x338F, 0xA7B9, 0x33CF, 0xA7BA, 0x3388, 0xA7BB, 0x3389, + 0xA7BC, 0x33C8, 0xA7BD, 0x33A7, 0xA7BE, 0x33A8, 0xA7BF, 0x33B0, 0xA7C0, 0x33B1, 0xA7C1, 0x33B2, 0xA7C2, 0x33B3, 0xA7C3, 0x33B4, + 0xA7C4, 0x33B5, 0xA7C5, 0x33B6, 0xA7C6, 0x33B7, 0xA7C7, 0x33B8, 0xA7C8, 0x33B9, 0xA7C9, 0x3380, 0xA7CA, 0x3381, 0xA7CB, 0x3382, + 0xA7CC, 0x3383, 0xA7CD, 0x3384, 0xA7CE, 0x33BA, 0xA7CF, 0x33BB, 0xA7D0, 0x33BC, 0xA7D1, 0x33BD, 0xA7D2, 0x33BE, 0xA7D3, 0x33BF, + 0xA7D4, 0x3390, 0xA7D5, 0x3391, 0xA7D6, 0x3392, 0xA7D7, 0x3393, 0xA7D8, 0x3394, 0xA7D9, 0x2126, 0xA7DA, 0x33C0, 0xA7DB, 0x33C1, + 0xA7DC, 0x338A, 0xA7DD, 0x338B, 0xA7DE, 0x338C, 0xA7DF, 0x33D6, 0xA7E0, 0x33C5, 0xA7E1, 0x33AD, 0xA7E2, 0x33AE, 0xA7E3, 0x33AF, + 0xA7E4, 0x33DB, 0xA7E5, 0x33A9, 0xA7E6, 0x33AA, 0xA7E7, 0x33AB, 0xA7E8, 0x33AC, 0xA7E9, 0x33DD, 0xA7EA, 0x33D0, 0xA7EB, 0x33D3, + 0xA7EC, 0x33C3, 0xA7ED, 0x33C9, 0xA7EE, 0x33DC, 0xA7EF, 0x33C6, 0xA841, 0xCB6D, 0xA842, 0xCB6E, 0xA843, 0xCB6F, 0xA844, 0xCB70, + 0xA845, 0xCB71, 0xA846, 0xCB72, 0xA847, 0xCB73, 0xA848, 0xCB74, 0xA849, 0xCB75, 0xA84A, 0xCB76, 0xA84B, 0xCB77, 0xA84C, 0xCB7A, + 0xA84D, 0xCB7B, 0xA84E, 0xCB7C, 0xA84F, 0xCB7D, 0xA850, 0xCB7E, 0xA851, 0xCB7F, 0xA852, 0xCB80, 0xA853, 0xCB81, 0xA854, 0xCB82, + 0xA855, 0xCB83, 0xA856, 0xCB84, 0xA857, 0xCB85, 0xA858, 0xCB86, 0xA859, 0xCB87, 0xA85A, 0xCB88, 0xA861, 0xCB89, 0xA862, 0xCB8A, + 0xA863, 0xCB8B, 0xA864, 0xCB8C, 0xA865, 0xCB8D, 0xA866, 0xCB8E, 0xA867, 0xCB8F, 0xA868, 0xCB90, 0xA869, 0xCB91, 0xA86A, 0xCB92, + 0xA86B, 0xCB93, 0xA86C, 0xCB94, 0xA86D, 0xCB95, 0xA86E, 0xCB96, 0xA86F, 0xCB97, 0xA870, 0xCB98, 0xA871, 0xCB99, 0xA872, 0xCB9A, + 0xA873, 0xCB9B, 0xA874, 0xCB9D, 0xA875, 0xCB9E, 0xA876, 0xCB9F, 0xA877, 0xCBA0, 0xA878, 0xCBA1, 0xA879, 0xCBA2, 0xA87A, 0xCBA3, + 0xA881, 0xCBA4, 0xA882, 0xCBA5, 0xA883, 0xCBA6, 0xA884, 0xCBA7, 0xA885, 0xCBA8, 0xA886, 0xCBA9, 0xA887, 0xCBAA, 0xA888, 0xCBAB, + 0xA889, 0xCBAC, 0xA88A, 0xCBAD, 0xA88B, 0xCBAE, 0xA88C, 0xCBAF, 0xA88D, 0xCBB0, 0xA88E, 0xCBB1, 0xA88F, 0xCBB2, 0xA890, 0xCBB3, + 0xA891, 0xCBB4, 0xA892, 0xCBB5, 0xA893, 0xCBB6, 0xA894, 0xCBB7, 0xA895, 0xCBB9, 0xA896, 0xCBBA, 0xA897, 0xCBBB, 0xA898, 0xCBBC, + 0xA899, 0xCBBD, 0xA89A, 0xCBBE, 0xA89B, 0xCBBF, 0xA89C, 0xCBC0, 0xA89D, 0xCBC1, 0xA89E, 0xCBC2, 0xA89F, 0xCBC3, 0xA8A0, 0xCBC4, + 0xA8A1, 0x00C6, 0xA8A2, 0x00D0, 0xA8A3, 0x00AA, 0xA8A4, 0x0126, 0xA8A6, 0x0132, 0xA8A8, 0x013F, 0xA8A9, 0x0141, 0xA8AA, 0x00D8, + 0xA8AB, 0x0152, 0xA8AC, 0x00BA, 0xA8AD, 0x00DE, 0xA8AE, 0x0166, 0xA8AF, 0x014A, 0xA8B1, 0x3260, 0xA8B2, 0x3261, 0xA8B3, 0x3262, + 0xA8B4, 0x3263, 0xA8B5, 0x3264, 0xA8B6, 0x3265, 0xA8B7, 0x3266, 0xA8B8, 0x3267, 0xA8B9, 0x3268, 0xA8BA, 0x3269, 0xA8BB, 0x326A, + 0xA8BC, 0x326B, 0xA8BD, 0x326C, 0xA8BE, 0x326D, 0xA8BF, 0x326E, 0xA8C0, 0x326F, 0xA8C1, 0x3270, 0xA8C2, 0x3271, 0xA8C3, 0x3272, + 0xA8C4, 0x3273, 0xA8C5, 0x3274, 0xA8C6, 0x3275, 0xA8C7, 0x3276, 0xA8C8, 0x3277, 0xA8C9, 0x3278, 0xA8CA, 0x3279, 0xA8CB, 0x327A, + 0xA8CC, 0x327B, 0xA8CD, 0x24D0, 0xA8CE, 0x24D1, 0xA8CF, 0x24D2, 0xA8D0, 0x24D3, 0xA8D1, 0x24D4, 0xA8D2, 0x24D5, 0xA8D3, 0x24D6, + 0xA8D4, 0x24D7, 0xA8D5, 0x24D8, 0xA8D6, 0x24D9, 0xA8D7, 0x24DA, 0xA8D8, 0x24DB, 0xA8D9, 0x24DC, 0xA8DA, 0x24DD, 0xA8DB, 0x24DE, + 0xA8DC, 0x24DF, 0xA8DD, 0x24E0, 0xA8DE, 0x24E1, 0xA8DF, 0x24E2, 0xA8E0, 0x24E3, 0xA8E1, 0x24E4, 0xA8E2, 0x24E5, 0xA8E3, 0x24E6, + 0xA8E4, 0x24E7, 0xA8E5, 0x24E8, 0xA8E6, 0x24E9, 0xA8E7, 0x2460, 0xA8E8, 0x2461, 0xA8E9, 0x2462, 0xA8EA, 0x2463, 0xA8EB, 0x2464, + 0xA8EC, 0x2465, 0xA8ED, 0x2466, 0xA8EE, 0x2467, 0xA8EF, 0x2468, 0xA8F0, 0x2469, 0xA8F1, 0x246A, 0xA8F2, 0x246B, 0xA8F3, 0x246C, + 0xA8F4, 0x246D, 0xA8F5, 0x246E, 0xA8F6, 0x00BD, 0xA8F7, 0x2153, 0xA8F8, 0x2154, 0xA8F9, 0x00BC, 0xA8FA, 0x00BE, 0xA8FB, 0x215B, + 0xA8FC, 0x215C, 0xA8FD, 0x215D, 0xA8FE, 0x215E, 0xA941, 0xCBC5, 0xA942, 0xCBC6, 0xA943, 0xCBC7, 0xA944, 0xCBC8, 0xA945, 0xCBC9, + 0xA946, 0xCBCA, 0xA947, 0xCBCB, 0xA948, 0xCBCC, 0xA949, 0xCBCD, 0xA94A, 0xCBCE, 0xA94B, 0xCBCF, 0xA94C, 0xCBD0, 0xA94D, 0xCBD1, + 0xA94E, 0xCBD2, 0xA94F, 0xCBD3, 0xA950, 0xCBD5, 0xA951, 0xCBD6, 0xA952, 0xCBD7, 0xA953, 0xCBD8, 0xA954, 0xCBD9, 0xA955, 0xCBDA, + 0xA956, 0xCBDB, 0xA957, 0xCBDC, 0xA958, 0xCBDD, 0xA959, 0xCBDE, 0xA95A, 0xCBDF, 0xA961, 0xCBE0, 0xA962, 0xCBE1, 0xA963, 0xCBE2, + 0xA964, 0xCBE3, 0xA965, 0xCBE5, 0xA966, 0xCBE6, 0xA967, 0xCBE8, 0xA968, 0xCBEA, 0xA969, 0xCBEB, 0xA96A, 0xCBEC, 0xA96B, 0xCBED, + 0xA96C, 0xCBEE, 0xA96D, 0xCBEF, 0xA96E, 0xCBF0, 0xA96F, 0xCBF1, 0xA970, 0xCBF2, 0xA971, 0xCBF3, 0xA972, 0xCBF4, 0xA973, 0xCBF5, + 0xA974, 0xCBF6, 0xA975, 0xCBF7, 0xA976, 0xCBF8, 0xA977, 0xCBF9, 0xA978, 0xCBFA, 0xA979, 0xCBFB, 0xA97A, 0xCBFC, 0xA981, 0xCBFD, + 0xA982, 0xCBFE, 0xA983, 0xCBFF, 0xA984, 0xCC00, 0xA985, 0xCC01, 0xA986, 0xCC02, 0xA987, 0xCC03, 0xA988, 0xCC04, 0xA989, 0xCC05, + 0xA98A, 0xCC06, 0xA98B, 0xCC07, 0xA98C, 0xCC08, 0xA98D, 0xCC09, 0xA98E, 0xCC0A, 0xA98F, 0xCC0B, 0xA990, 0xCC0E, 0xA991, 0xCC0F, + 0xA992, 0xCC11, 0xA993, 0xCC12, 0xA994, 0xCC13, 0xA995, 0xCC15, 0xA996, 0xCC16, 0xA997, 0xCC17, 0xA998, 0xCC18, 0xA999, 0xCC19, + 0xA99A, 0xCC1A, 0xA99B, 0xCC1B, 0xA99C, 0xCC1E, 0xA99D, 0xCC1F, 0xA99E, 0xCC20, 0xA99F, 0xCC23, 0xA9A0, 0xCC24, 0xA9A1, 0x00E6, + 0xA9A2, 0x0111, 0xA9A3, 0x00F0, 0xA9A4, 0x0127, 0xA9A5, 0x0131, 0xA9A6, 0x0133, 0xA9A7, 0x0138, 0xA9A8, 0x0140, 0xA9A9, 0x0142, + 0xA9AA, 0x00F8, 0xA9AB, 0x0153, 0xA9AC, 0x00DF, 0xA9AD, 0x00FE, 0xA9AE, 0x0167, 0xA9AF, 0x014B, 0xA9B0, 0x0149, 0xA9B1, 0x3200, + 0xA9B2, 0x3201, 0xA9B3, 0x3202, 0xA9B4, 0x3203, 0xA9B5, 0x3204, 0xA9B6, 0x3205, 0xA9B7, 0x3206, 0xA9B8, 0x3207, 0xA9B9, 0x3208, + 0xA9BA, 0x3209, 0xA9BB, 0x320A, 0xA9BC, 0x320B, 0xA9BD, 0x320C, 0xA9BE, 0x320D, 0xA9BF, 0x320E, 0xA9C0, 0x320F, 0xA9C1, 0x3210, + 0xA9C2, 0x3211, 0xA9C3, 0x3212, 0xA9C4, 0x3213, 0xA9C5, 0x3214, 0xA9C6, 0x3215, 0xA9C7, 0x3216, 0xA9C8, 0x3217, 0xA9C9, 0x3218, + 0xA9CA, 0x3219, 0xA9CB, 0x321A, 0xA9CC, 0x321B, 0xA9CD, 0x249C, 0xA9CE, 0x249D, 0xA9CF, 0x249E, 0xA9D0, 0x249F, 0xA9D1, 0x24A0, + 0xA9D2, 0x24A1, 0xA9D3, 0x24A2, 0xA9D4, 0x24A3, 0xA9D5, 0x24A4, 0xA9D6, 0x24A5, 0xA9D7, 0x24A6, 0xA9D8, 0x24A7, 0xA9D9, 0x24A8, + 0xA9DA, 0x24A9, 0xA9DB, 0x24AA, 0xA9DC, 0x24AB, 0xA9DD, 0x24AC, 0xA9DE, 0x24AD, 0xA9DF, 0x24AE, 0xA9E0, 0x24AF, 0xA9E1, 0x24B0, + 0xA9E2, 0x24B1, 0xA9E3, 0x24B2, 0xA9E4, 0x24B3, 0xA9E5, 0x24B4, 0xA9E6, 0x24B5, 0xA9E7, 0x2474, 0xA9E8, 0x2475, 0xA9E9, 0x2476, + 0xA9EA, 0x2477, 0xA9EB, 0x2478, 0xA9EC, 0x2479, 0xA9ED, 0x247A, 0xA9EE, 0x247B, 0xA9EF, 0x247C, 0xA9F0, 0x247D, 0xA9F1, 0x247E, + 0xA9F2, 0x247F, 0xA9F3, 0x2480, 0xA9F4, 0x2481, 0xA9F5, 0x2482, 0xA9F6, 0x00B9, 0xA9F7, 0x00B2, 0xA9F8, 0x00B3, 0xA9F9, 0x2074, + 0xA9FA, 0x207F, 0xA9FB, 0x2081, 0xA9FC, 0x2082, 0xA9FD, 0x2083, 0xA9FE, 0x2084, 0xAA41, 0xCC25, 0xAA42, 0xCC26, 0xAA43, 0xCC2A, + 0xAA44, 0xCC2B, 0xAA45, 0xCC2D, 0xAA46, 0xCC2F, 0xAA47, 0xCC31, 0xAA48, 0xCC32, 0xAA49, 0xCC33, 0xAA4A, 0xCC34, 0xAA4B, 0xCC35, + 0xAA4C, 0xCC36, 0xAA4D, 0xCC37, 0xAA4E, 0xCC3A, 0xAA4F, 0xCC3F, 0xAA50, 0xCC40, 0xAA51, 0xCC41, 0xAA52, 0xCC42, 0xAA53, 0xCC43, + 0xAA54, 0xCC46, 0xAA55, 0xCC47, 0xAA56, 0xCC49, 0xAA57, 0xCC4A, 0xAA58, 0xCC4B, 0xAA59, 0xCC4D, 0xAA5A, 0xCC4E, 0xAA61, 0xCC4F, + 0xAA62, 0xCC50, 0xAA63, 0xCC51, 0xAA64, 0xCC52, 0xAA65, 0xCC53, 0xAA66, 0xCC56, 0xAA67, 0xCC5A, 0xAA68, 0xCC5B, 0xAA69, 0xCC5C, + 0xAA6A, 0xCC5D, 0xAA6B, 0xCC5E, 0xAA6C, 0xCC5F, 0xAA6D, 0xCC61, 0xAA6E, 0xCC62, 0xAA6F, 0xCC63, 0xAA70, 0xCC65, 0xAA71, 0xCC67, + 0xAA72, 0xCC69, 0xAA73, 0xCC6A, 0xAA74, 0xCC6B, 0xAA75, 0xCC6C, 0xAA76, 0xCC6D, 0xAA77, 0xCC6E, 0xAA78, 0xCC6F, 0xAA79, 0xCC71, + 0xAA7A, 0xCC72, 0xAA81, 0xCC73, 0xAA82, 0xCC74, 0xAA83, 0xCC76, 0xAA84, 0xCC77, 0xAA85, 0xCC78, 0xAA86, 0xCC79, 0xAA87, 0xCC7A, + 0xAA88, 0xCC7B, 0xAA89, 0xCC7C, 0xAA8A, 0xCC7D, 0xAA8B, 0xCC7E, 0xAA8C, 0xCC7F, 0xAA8D, 0xCC80, 0xAA8E, 0xCC81, 0xAA8F, 0xCC82, + 0xAA90, 0xCC83, 0xAA91, 0xCC84, 0xAA92, 0xCC85, 0xAA93, 0xCC86, 0xAA94, 0xCC87, 0xAA95, 0xCC88, 0xAA96, 0xCC89, 0xAA97, 0xCC8A, + 0xAA98, 0xCC8B, 0xAA99, 0xCC8C, 0xAA9A, 0xCC8D, 0xAA9B, 0xCC8E, 0xAA9C, 0xCC8F, 0xAA9D, 0xCC90, 0xAA9E, 0xCC91, 0xAA9F, 0xCC92, + 0xAAA0, 0xCC93, 0xAAA1, 0x3041, 0xAAA2, 0x3042, 0xAAA3, 0x3043, 0xAAA4, 0x3044, 0xAAA5, 0x3045, 0xAAA6, 0x3046, 0xAAA7, 0x3047, + 0xAAA8, 0x3048, 0xAAA9, 0x3049, 0xAAAA, 0x304A, 0xAAAB, 0x304B, 0xAAAC, 0x304C, 0xAAAD, 0x304D, 0xAAAE, 0x304E, 0xAAAF, 0x304F, + 0xAAB0, 0x3050, 0xAAB1, 0x3051, 0xAAB2, 0x3052, 0xAAB3, 0x3053, 0xAAB4, 0x3054, 0xAAB5, 0x3055, 0xAAB6, 0x3056, 0xAAB7, 0x3057, + 0xAAB8, 0x3058, 0xAAB9, 0x3059, 0xAABA, 0x305A, 0xAABB, 0x305B, 0xAABC, 0x305C, 0xAABD, 0x305D, 0xAABE, 0x305E, 0xAABF, 0x305F, + 0xAAC0, 0x3060, 0xAAC1, 0x3061, 0xAAC2, 0x3062, 0xAAC3, 0x3063, 0xAAC4, 0x3064, 0xAAC5, 0x3065, 0xAAC6, 0x3066, 0xAAC7, 0x3067, + 0xAAC8, 0x3068, 0xAAC9, 0x3069, 0xAACA, 0x306A, 0xAACB, 0x306B, 0xAACC, 0x306C, 0xAACD, 0x306D, 0xAACE, 0x306E, 0xAACF, 0x306F, + 0xAAD0, 0x3070, 0xAAD1, 0x3071, 0xAAD2, 0x3072, 0xAAD3, 0x3073, 0xAAD4, 0x3074, 0xAAD5, 0x3075, 0xAAD6, 0x3076, 0xAAD7, 0x3077, + 0xAAD8, 0x3078, 0xAAD9, 0x3079, 0xAADA, 0x307A, 0xAADB, 0x307B, 0xAADC, 0x307C, 0xAADD, 0x307D, 0xAADE, 0x307E, 0xAADF, 0x307F, + 0xAAE0, 0x3080, 0xAAE1, 0x3081, 0xAAE2, 0x3082, 0xAAE3, 0x3083, 0xAAE4, 0x3084, 0xAAE5, 0x3085, 0xAAE6, 0x3086, 0xAAE7, 0x3087, + 0xAAE8, 0x3088, 0xAAE9, 0x3089, 0xAAEA, 0x308A, 0xAAEB, 0x308B, 0xAAEC, 0x308C, 0xAAED, 0x308D, 0xAAEE, 0x308E, 0xAAEF, 0x308F, + 0xAAF0, 0x3090, 0xAAF1, 0x3091, 0xAAF2, 0x3092, 0xAAF3, 0x3093, 0xAB41, 0xCC94, 0xAB42, 0xCC95, 0xAB43, 0xCC96, 0xAB44, 0xCC97, + 0xAB45, 0xCC9A, 0xAB46, 0xCC9B, 0xAB47, 0xCC9D, 0xAB48, 0xCC9E, 0xAB49, 0xCC9F, 0xAB4A, 0xCCA1, 0xAB4B, 0xCCA2, 0xAB4C, 0xCCA3, + 0xAB4D, 0xCCA4, 0xAB4E, 0xCCA5, 0xAB4F, 0xCCA6, 0xAB50, 0xCCA7, 0xAB51, 0xCCAA, 0xAB52, 0xCCAE, 0xAB53, 0xCCAF, 0xAB54, 0xCCB0, + 0xAB55, 0xCCB1, 0xAB56, 0xCCB2, 0xAB57, 0xCCB3, 0xAB58, 0xCCB6, 0xAB59, 0xCCB7, 0xAB5A, 0xCCB9, 0xAB61, 0xCCBA, 0xAB62, 0xCCBB, + 0xAB63, 0xCCBD, 0xAB64, 0xCCBE, 0xAB65, 0xCCBF, 0xAB66, 0xCCC0, 0xAB67, 0xCCC1, 0xAB68, 0xCCC2, 0xAB69, 0xCCC3, 0xAB6A, 0xCCC6, + 0xAB6B, 0xCCC8, 0xAB6C, 0xCCCA, 0xAB6D, 0xCCCB, 0xAB6E, 0xCCCC, 0xAB6F, 0xCCCD, 0xAB70, 0xCCCE, 0xAB71, 0xCCCF, 0xAB72, 0xCCD1, + 0xAB73, 0xCCD2, 0xAB74, 0xCCD3, 0xAB75, 0xCCD5, 0xAB76, 0xCCD6, 0xAB77, 0xCCD7, 0xAB78, 0xCCD8, 0xAB79, 0xCCD9, 0xAB7A, 0xCCDA, + 0xAB81, 0xCCDB, 0xAB82, 0xCCDC, 0xAB83, 0xCCDD, 0xAB84, 0xCCDE, 0xAB85, 0xCCDF, 0xAB86, 0xCCE0, 0xAB87, 0xCCE1, 0xAB88, 0xCCE2, + 0xAB89, 0xCCE3, 0xAB8A, 0xCCE5, 0xAB8B, 0xCCE6, 0xAB8C, 0xCCE7, 0xAB8D, 0xCCE8, 0xAB8E, 0xCCE9, 0xAB8F, 0xCCEA, 0xAB90, 0xCCEB, + 0xAB91, 0xCCED, 0xAB92, 0xCCEE, 0xAB93, 0xCCEF, 0xAB94, 0xCCF1, 0xAB95, 0xCCF2, 0xAB96, 0xCCF3, 0xAB97, 0xCCF4, 0xAB98, 0xCCF5, + 0xAB99, 0xCCF6, 0xAB9A, 0xCCF7, 0xAB9B, 0xCCF8, 0xAB9C, 0xCCF9, 0xAB9D, 0xCCFA, 0xAB9E, 0xCCFB, 0xAB9F, 0xCCFC, 0xABA0, 0xCCFD, + 0xABA1, 0x30A1, 0xABA2, 0x30A2, 0xABA3, 0x30A3, 0xABA4, 0x30A4, 0xABA5, 0x30A5, 0xABA6, 0x30A6, 0xABA7, 0x30A7, 0xABA8, 0x30A8, + 0xABA9, 0x30A9, 0xABAA, 0x30AA, 0xABAB, 0x30AB, 0xABAC, 0x30AC, 0xABAD, 0x30AD, 0xABAE, 0x30AE, 0xABAF, 0x30AF, 0xABB0, 0x30B0, + 0xABB1, 0x30B1, 0xABB2, 0x30B2, 0xABB3, 0x30B3, 0xABB4, 0x30B4, 0xABB5, 0x30B5, 0xABB6, 0x30B6, 0xABB7, 0x30B7, 0xABB8, 0x30B8, + 0xABB9, 0x30B9, 0xABBA, 0x30BA, 0xABBB, 0x30BB, 0xABBC, 0x30BC, 0xABBD, 0x30BD, 0xABBE, 0x30BE, 0xABBF, 0x30BF, 0xABC0, 0x30C0, + 0xABC1, 0x30C1, 0xABC2, 0x30C2, 0xABC3, 0x30C3, 0xABC4, 0x30C4, 0xABC5, 0x30C5, 0xABC6, 0x30C6, 0xABC7, 0x30C7, 0xABC8, 0x30C8, + 0xABC9, 0x30C9, 0xABCA, 0x30CA, 0xABCB, 0x30CB, 0xABCC, 0x30CC, 0xABCD, 0x30CD, 0xABCE, 0x30CE, 0xABCF, 0x30CF, 0xABD0, 0x30D0, + 0xABD1, 0x30D1, 0xABD2, 0x30D2, 0xABD3, 0x30D3, 0xABD4, 0x30D4, 0xABD5, 0x30D5, 0xABD6, 0x30D6, 0xABD7, 0x30D7, 0xABD8, 0x30D8, + 0xABD9, 0x30D9, 0xABDA, 0x30DA, 0xABDB, 0x30DB, 0xABDC, 0x30DC, 0xABDD, 0x30DD, 0xABDE, 0x30DE, 0xABDF, 0x30DF, 0xABE0, 0x30E0, + 0xABE1, 0x30E1, 0xABE2, 0x30E2, 0xABE3, 0x30E3, 0xABE4, 0x30E4, 0xABE5, 0x30E5, 0xABE6, 0x30E6, 0xABE7, 0x30E7, 0xABE8, 0x30E8, + 0xABE9, 0x30E9, 0xABEA, 0x30EA, 0xABEB, 0x30EB, 0xABEC, 0x30EC, 0xABED, 0x30ED, 0xABEE, 0x30EE, 0xABEF, 0x30EF, 0xABF0, 0x30F0, + 0xABF1, 0x30F1, 0xABF2, 0x30F2, 0xABF3, 0x30F3, 0xABF4, 0x30F4, 0xABF5, 0x30F5, 0xABF6, 0x30F6, 0xAC41, 0xCCFE, 0xAC42, 0xCCFF, + 0xAC43, 0xCD00, 0xAC44, 0xCD02, 0xAC45, 0xCD03, 0xAC46, 0xCD04, 0xAC47, 0xCD05, 0xAC48, 0xCD06, 0xAC49, 0xCD07, 0xAC4A, 0xCD0A, + 0xAC4B, 0xCD0B, 0xAC4C, 0xCD0D, 0xAC4D, 0xCD0E, 0xAC4E, 0xCD0F, 0xAC4F, 0xCD11, 0xAC50, 0xCD12, 0xAC51, 0xCD13, 0xAC52, 0xCD14, + 0xAC53, 0xCD15, 0xAC54, 0xCD16, 0xAC55, 0xCD17, 0xAC56, 0xCD1A, 0xAC57, 0xCD1C, 0xAC58, 0xCD1E, 0xAC59, 0xCD1F, 0xAC5A, 0xCD20, + 0xAC61, 0xCD21, 0xAC62, 0xCD22, 0xAC63, 0xCD23, 0xAC64, 0xCD25, 0xAC65, 0xCD26, 0xAC66, 0xCD27, 0xAC67, 0xCD29, 0xAC68, 0xCD2A, + 0xAC69, 0xCD2B, 0xAC6A, 0xCD2D, 0xAC6B, 0xCD2E, 0xAC6C, 0xCD2F, 0xAC6D, 0xCD30, 0xAC6E, 0xCD31, 0xAC6F, 0xCD32, 0xAC70, 0xCD33, + 0xAC71, 0xCD34, 0xAC72, 0xCD35, 0xAC73, 0xCD36, 0xAC74, 0xCD37, 0xAC75, 0xCD38, 0xAC76, 0xCD3A, 0xAC77, 0xCD3B, 0xAC78, 0xCD3C, + 0xAC79, 0xCD3D, 0xAC7A, 0xCD3E, 0xAC81, 0xCD3F, 0xAC82, 0xCD40, 0xAC83, 0xCD41, 0xAC84, 0xCD42, 0xAC85, 0xCD43, 0xAC86, 0xCD44, + 0xAC87, 0xCD45, 0xAC88, 0xCD46, 0xAC89, 0xCD47, 0xAC8A, 0xCD48, 0xAC8B, 0xCD49, 0xAC8C, 0xCD4A, 0xAC8D, 0xCD4B, 0xAC8E, 0xCD4C, + 0xAC8F, 0xCD4D, 0xAC90, 0xCD4E, 0xAC91, 0xCD4F, 0xAC92, 0xCD50, 0xAC93, 0xCD51, 0xAC94, 0xCD52, 0xAC95, 0xCD53, 0xAC96, 0xCD54, + 0xAC97, 0xCD55, 0xAC98, 0xCD56, 0xAC99, 0xCD57, 0xAC9A, 0xCD58, 0xAC9B, 0xCD59, 0xAC9C, 0xCD5A, 0xAC9D, 0xCD5B, 0xAC9E, 0xCD5D, + 0xAC9F, 0xCD5E, 0xACA0, 0xCD5F, 0xACA1, 0x0410, 0xACA2, 0x0411, 0xACA3, 0x0412, 0xACA4, 0x0413, 0xACA5, 0x0414, 0xACA6, 0x0415, + 0xACA7, 0x0401, 0xACA8, 0x0416, 0xACA9, 0x0417, 0xACAA, 0x0418, 0xACAB, 0x0419, 0xACAC, 0x041A, 0xACAD, 0x041B, 0xACAE, 0x041C, + 0xACAF, 0x041D, 0xACB0, 0x041E, 0xACB1, 0x041F, 0xACB2, 0x0420, 0xACB3, 0x0421, 0xACB4, 0x0422, 0xACB5, 0x0423, 0xACB6, 0x0424, + 0xACB7, 0x0425, 0xACB8, 0x0426, 0xACB9, 0x0427, 0xACBA, 0x0428, 0xACBB, 0x0429, 0xACBC, 0x042A, 0xACBD, 0x042B, 0xACBE, 0x042C, + 0xACBF, 0x042D, 0xACC0, 0x042E, 0xACC1, 0x042F, 0xACD1, 0x0430, 0xACD2, 0x0431, 0xACD3, 0x0432, 0xACD4, 0x0433, 0xACD5, 0x0434, + 0xACD6, 0x0435, 0xACD7, 0x0451, 0xACD8, 0x0436, 0xACD9, 0x0437, 0xACDA, 0x0438, 0xACDB, 0x0439, 0xACDC, 0x043A, 0xACDD, 0x043B, + 0xACDE, 0x043C, 0xACDF, 0x043D, 0xACE0, 0x043E, 0xACE1, 0x043F, 0xACE2, 0x0440, 0xACE3, 0x0441, 0xACE4, 0x0442, 0xACE5, 0x0443, + 0xACE6, 0x0444, 0xACE7, 0x0445, 0xACE8, 0x0446, 0xACE9, 0x0447, 0xACEA, 0x0448, 0xACEB, 0x0449, 0xACEC, 0x044A, 0xACED, 0x044B, + 0xACEE, 0x044C, 0xACEF, 0x044D, 0xACF0, 0x044E, 0xACF1, 0x044F, 0xAD41, 0xCD61, 0xAD42, 0xCD62, 0xAD43, 0xCD63, 0xAD44, 0xCD65, + 0xAD45, 0xCD66, 0xAD46, 0xCD67, 0xAD47, 0xCD68, 0xAD48, 0xCD69, 0xAD49, 0xCD6A, 0xAD4A, 0xCD6B, 0xAD4B, 0xCD6E, 0xAD4C, 0xCD70, + 0xAD4D, 0xCD72, 0xAD4E, 0xCD73, 0xAD4F, 0xCD74, 0xAD50, 0xCD75, 0xAD51, 0xCD76, 0xAD52, 0xCD77, 0xAD53, 0xCD79, 0xAD54, 0xCD7A, + 0xAD55, 0xCD7B, 0xAD56, 0xCD7C, 0xAD57, 0xCD7D, 0xAD58, 0xCD7E, 0xAD59, 0xCD7F, 0xAD5A, 0xCD80, 0xAD61, 0xCD81, 0xAD62, 0xCD82, + 0xAD63, 0xCD83, 0xAD64, 0xCD84, 0xAD65, 0xCD85, 0xAD66, 0xCD86, 0xAD67, 0xCD87, 0xAD68, 0xCD89, 0xAD69, 0xCD8A, 0xAD6A, 0xCD8B, + 0xAD6B, 0xCD8C, 0xAD6C, 0xCD8D, 0xAD6D, 0xCD8E, 0xAD6E, 0xCD8F, 0xAD6F, 0xCD90, 0xAD70, 0xCD91, 0xAD71, 0xCD92, 0xAD72, 0xCD93, + 0xAD73, 0xCD96, 0xAD74, 0xCD97, 0xAD75, 0xCD99, 0xAD76, 0xCD9A, 0xAD77, 0xCD9B, 0xAD78, 0xCD9D, 0xAD79, 0xCD9E, 0xAD7A, 0xCD9F, + 0xAD81, 0xCDA0, 0xAD82, 0xCDA1, 0xAD83, 0xCDA2, 0xAD84, 0xCDA3, 0xAD85, 0xCDA6, 0xAD86, 0xCDA8, 0xAD87, 0xCDAA, 0xAD88, 0xCDAB, + 0xAD89, 0xCDAC, 0xAD8A, 0xCDAD, 0xAD8B, 0xCDAE, 0xAD8C, 0xCDAF, 0xAD8D, 0xCDB1, 0xAD8E, 0xCDB2, 0xAD8F, 0xCDB3, 0xAD90, 0xCDB4, + 0xAD91, 0xCDB5, 0xAD92, 0xCDB6, 0xAD93, 0xCDB7, 0xAD94, 0xCDB8, 0xAD95, 0xCDB9, 0xAD96, 0xCDBA, 0xAD97, 0xCDBB, 0xAD98, 0xCDBC, + 0xAD99, 0xCDBD, 0xAD9A, 0xCDBE, 0xAD9B, 0xCDBF, 0xAD9C, 0xCDC0, 0xAD9D, 0xCDC1, 0xAD9E, 0xCDC2, 0xAD9F, 0xCDC3, 0xADA0, 0xCDC5, + 0xAE41, 0xCDC6, 0xAE42, 0xCDC7, 0xAE43, 0xCDC8, 0xAE44, 0xCDC9, 0xAE45, 0xCDCA, 0xAE46, 0xCDCB, 0xAE47, 0xCDCD, 0xAE48, 0xCDCE, + 0xAE49, 0xCDCF, 0xAE4A, 0xCDD1, 0xAE4B, 0xCDD2, 0xAE4C, 0xCDD3, 0xAE4D, 0xCDD4, 0xAE4E, 0xCDD5, 0xAE4F, 0xCDD6, 0xAE50, 0xCDD7, + 0xAE51, 0xCDD8, 0xAE52, 0xCDD9, 0xAE53, 0xCDDA, 0xAE54, 0xCDDB, 0xAE55, 0xCDDC, 0xAE56, 0xCDDD, 0xAE57, 0xCDDE, 0xAE58, 0xCDDF, + 0xAE59, 0xCDE0, 0xAE5A, 0xCDE1, 0xAE61, 0xCDE2, 0xAE62, 0xCDE3, 0xAE63, 0xCDE4, 0xAE64, 0xCDE5, 0xAE65, 0xCDE6, 0xAE66, 0xCDE7, + 0xAE67, 0xCDE9, 0xAE68, 0xCDEA, 0xAE69, 0xCDEB, 0xAE6A, 0xCDED, 0xAE6B, 0xCDEE, 0xAE6C, 0xCDEF, 0xAE6D, 0xCDF1, 0xAE6E, 0xCDF2, + 0xAE6F, 0xCDF3, 0xAE70, 0xCDF4, 0xAE71, 0xCDF5, 0xAE72, 0xCDF6, 0xAE73, 0xCDF7, 0xAE74, 0xCDFA, 0xAE75, 0xCDFC, 0xAE76, 0xCDFE, + 0xAE77, 0xCDFF, 0xAE78, 0xCE00, 0xAE79, 0xCE01, 0xAE7A, 0xCE02, 0xAE81, 0xCE03, 0xAE82, 0xCE05, 0xAE83, 0xCE06, 0xAE84, 0xCE07, + 0xAE85, 0xCE09, 0xAE86, 0xCE0A, 0xAE87, 0xCE0B, 0xAE88, 0xCE0D, 0xAE89, 0xCE0E, 0xAE8A, 0xCE0F, 0xAE8B, 0xCE10, 0xAE8C, 0xCE11, + 0xAE8D, 0xCE12, 0xAE8E, 0xCE13, 0xAE8F, 0xCE15, 0xAE90, 0xCE16, 0xAE91, 0xCE17, 0xAE92, 0xCE18, 0xAE93, 0xCE1A, 0xAE94, 0xCE1B, + 0xAE95, 0xCE1C, 0xAE96, 0xCE1D, 0xAE97, 0xCE1E, 0xAE98, 0xCE1F, 0xAE99, 0xCE22, 0xAE9A, 0xCE23, 0xAE9B, 0xCE25, 0xAE9C, 0xCE26, + 0xAE9D, 0xCE27, 0xAE9E, 0xCE29, 0xAE9F, 0xCE2A, 0xAEA0, 0xCE2B, 0xAF41, 0xCE2C, 0xAF42, 0xCE2D, 0xAF43, 0xCE2E, 0xAF44, 0xCE2F, + 0xAF45, 0xCE32, 0xAF46, 0xCE34, 0xAF47, 0xCE36, 0xAF48, 0xCE37, 0xAF49, 0xCE38, 0xAF4A, 0xCE39, 0xAF4B, 0xCE3A, 0xAF4C, 0xCE3B, + 0xAF4D, 0xCE3C, 0xAF4E, 0xCE3D, 0xAF4F, 0xCE3E, 0xAF50, 0xCE3F, 0xAF51, 0xCE40, 0xAF52, 0xCE41, 0xAF53, 0xCE42, 0xAF54, 0xCE43, + 0xAF55, 0xCE44, 0xAF56, 0xCE45, 0xAF57, 0xCE46, 0xAF58, 0xCE47, 0xAF59, 0xCE48, 0xAF5A, 0xCE49, 0xAF61, 0xCE4A, 0xAF62, 0xCE4B, + 0xAF63, 0xCE4C, 0xAF64, 0xCE4D, 0xAF65, 0xCE4E, 0xAF66, 0xCE4F, 0xAF67, 0xCE50, 0xAF68, 0xCE51, 0xAF69, 0xCE52, 0xAF6A, 0xCE53, + 0xAF6B, 0xCE54, 0xAF6C, 0xCE55, 0xAF6D, 0xCE56, 0xAF6E, 0xCE57, 0xAF6F, 0xCE5A, 0xAF70, 0xCE5B, 0xAF71, 0xCE5D, 0xAF72, 0xCE5E, + 0xAF73, 0xCE62, 0xAF74, 0xCE63, 0xAF75, 0xCE64, 0xAF76, 0xCE65, 0xAF77, 0xCE66, 0xAF78, 0xCE67, 0xAF79, 0xCE6A, 0xAF7A, 0xCE6C, + 0xAF81, 0xCE6E, 0xAF82, 0xCE6F, 0xAF83, 0xCE70, 0xAF84, 0xCE71, 0xAF85, 0xCE72, 0xAF86, 0xCE73, 0xAF87, 0xCE76, 0xAF88, 0xCE77, + 0xAF89, 0xCE79, 0xAF8A, 0xCE7A, 0xAF8B, 0xCE7B, 0xAF8C, 0xCE7D, 0xAF8D, 0xCE7E, 0xAF8E, 0xCE7F, 0xAF8F, 0xCE80, 0xAF90, 0xCE81, + 0xAF91, 0xCE82, 0xAF92, 0xCE83, 0xAF93, 0xCE86, 0xAF94, 0xCE88, 0xAF95, 0xCE8A, 0xAF96, 0xCE8B, 0xAF97, 0xCE8C, 0xAF98, 0xCE8D, + 0xAF99, 0xCE8E, 0xAF9A, 0xCE8F, 0xAF9B, 0xCE92, 0xAF9C, 0xCE93, 0xAF9D, 0xCE95, 0xAF9E, 0xCE96, 0xAF9F, 0xCE97, 0xAFA0, 0xCE99, + 0xB041, 0xCE9A, 0xB042, 0xCE9B, 0xB043, 0xCE9C, 0xB044, 0xCE9D, 0xB045, 0xCE9E, 0xB046, 0xCE9F, 0xB047, 0xCEA2, 0xB048, 0xCEA6, + 0xB049, 0xCEA7, 0xB04A, 0xCEA8, 0xB04B, 0xCEA9, 0xB04C, 0xCEAA, 0xB04D, 0xCEAB, 0xB04E, 0xCEAE, 0xB04F, 0xCEAF, 0xB050, 0xCEB0, + 0xB051, 0xCEB1, 0xB052, 0xCEB2, 0xB053, 0xCEB3, 0xB054, 0xCEB4, 0xB055, 0xCEB5, 0xB056, 0xCEB6, 0xB057, 0xCEB7, 0xB058, 0xCEB8, + 0xB059, 0xCEB9, 0xB05A, 0xCEBA, 0xB061, 0xCEBB, 0xB062, 0xCEBC, 0xB063, 0xCEBD, 0xB064, 0xCEBE, 0xB065, 0xCEBF, 0xB066, 0xCEC0, + 0xB067, 0xCEC2, 0xB068, 0xCEC3, 0xB069, 0xCEC4, 0xB06A, 0xCEC5, 0xB06B, 0xCEC6, 0xB06C, 0xCEC7, 0xB06D, 0xCEC8, 0xB06E, 0xCEC9, + 0xB06F, 0xCECA, 0xB070, 0xCECB, 0xB071, 0xCECC, 0xB072, 0xCECD, 0xB073, 0xCECE, 0xB074, 0xCECF, 0xB075, 0xCED0, 0xB076, 0xCED1, + 0xB077, 0xCED2, 0xB078, 0xCED3, 0xB079, 0xCED4, 0xB07A, 0xCED5, 0xB081, 0xCED6, 0xB082, 0xCED7, 0xB083, 0xCED8, 0xB084, 0xCED9, + 0xB085, 0xCEDA, 0xB086, 0xCEDB, 0xB087, 0xCEDC, 0xB088, 0xCEDD, 0xB089, 0xCEDE, 0xB08A, 0xCEDF, 0xB08B, 0xCEE0, 0xB08C, 0xCEE1, + 0xB08D, 0xCEE2, 0xB08E, 0xCEE3, 0xB08F, 0xCEE6, 0xB090, 0xCEE7, 0xB091, 0xCEE9, 0xB092, 0xCEEA, 0xB093, 0xCEED, 0xB094, 0xCEEE, + 0xB095, 0xCEEF, 0xB096, 0xCEF0, 0xB097, 0xCEF1, 0xB098, 0xCEF2, 0xB099, 0xCEF3, 0xB09A, 0xCEF6, 0xB09B, 0xCEFA, 0xB09C, 0xCEFB, + 0xB09D, 0xCEFC, 0xB09E, 0xCEFD, 0xB09F, 0xCEFE, 0xB0A0, 0xCEFF, 0xB0A1, 0xAC00, 0xB0A2, 0xAC01, 0xB0A3, 0xAC04, 0xB0A4, 0xAC07, + 0xB0A5, 0xAC08, 0xB0A6, 0xAC09, 0xB0A7, 0xAC0A, 0xB0A8, 0xAC10, 0xB0A9, 0xAC11, 0xB0AA, 0xAC12, 0xB0AB, 0xAC13, 0xB0AC, 0xAC14, + 0xB0AD, 0xAC15, 0xB0AE, 0xAC16, 0xB0AF, 0xAC17, 0xB0B0, 0xAC19, 0xB0B1, 0xAC1A, 0xB0B2, 0xAC1B, 0xB0B3, 0xAC1C, 0xB0B4, 0xAC1D, + 0xB0B5, 0xAC20, 0xB0B6, 0xAC24, 0xB0B7, 0xAC2C, 0xB0B8, 0xAC2D, 0xB0B9, 0xAC2F, 0xB0BA, 0xAC30, 0xB0BB, 0xAC31, 0xB0BC, 0xAC38, + 0xB0BD, 0xAC39, 0xB0BE, 0xAC3C, 0xB0BF, 0xAC40, 0xB0C0, 0xAC4B, 0xB0C1, 0xAC4D, 0xB0C2, 0xAC54, 0xB0C3, 0xAC58, 0xB0C4, 0xAC5C, + 0xB0C5, 0xAC70, 0xB0C6, 0xAC71, 0xB0C7, 0xAC74, 0xB0C8, 0xAC77, 0xB0C9, 0xAC78, 0xB0CA, 0xAC7A, 0xB0CB, 0xAC80, 0xB0CC, 0xAC81, + 0xB0CD, 0xAC83, 0xB0CE, 0xAC84, 0xB0CF, 0xAC85, 0xB0D0, 0xAC86, 0xB0D1, 0xAC89, 0xB0D2, 0xAC8A, 0xB0D3, 0xAC8B, 0xB0D4, 0xAC8C, + 0xB0D5, 0xAC90, 0xB0D6, 0xAC94, 0xB0D7, 0xAC9C, 0xB0D8, 0xAC9D, 0xB0D9, 0xAC9F, 0xB0DA, 0xACA0, 0xB0DB, 0xACA1, 0xB0DC, 0xACA8, + 0xB0DD, 0xACA9, 0xB0DE, 0xACAA, 0xB0DF, 0xACAC, 0xB0E0, 0xACAF, 0xB0E1, 0xACB0, 0xB0E2, 0xACB8, 0xB0E3, 0xACB9, 0xB0E4, 0xACBB, + 0xB0E5, 0xACBC, 0xB0E6, 0xACBD, 0xB0E7, 0xACC1, 0xB0E8, 0xACC4, 0xB0E9, 0xACC8, 0xB0EA, 0xACCC, 0xB0EB, 0xACD5, 0xB0EC, 0xACD7, + 0xB0ED, 0xACE0, 0xB0EE, 0xACE1, 0xB0EF, 0xACE4, 0xB0F0, 0xACE7, 0xB0F1, 0xACE8, 0xB0F2, 0xACEA, 0xB0F3, 0xACEC, 0xB0F4, 0xACEF, + 0xB0F5, 0xACF0, 0xB0F6, 0xACF1, 0xB0F7, 0xACF3, 0xB0F8, 0xACF5, 0xB0F9, 0xACF6, 0xB0FA, 0xACFC, 0xB0FB, 0xACFD, 0xB0FC, 0xAD00, + 0xB0FD, 0xAD04, 0xB0FE, 0xAD06, 0xB141, 0xCF02, 0xB142, 0xCF03, 0xB143, 0xCF05, 0xB144, 0xCF06, 0xB145, 0xCF07, 0xB146, 0xCF09, + 0xB147, 0xCF0A, 0xB148, 0xCF0B, 0xB149, 0xCF0C, 0xB14A, 0xCF0D, 0xB14B, 0xCF0E, 0xB14C, 0xCF0F, 0xB14D, 0xCF12, 0xB14E, 0xCF14, + 0xB14F, 0xCF16, 0xB150, 0xCF17, 0xB151, 0xCF18, 0xB152, 0xCF19, 0xB153, 0xCF1A, 0xB154, 0xCF1B, 0xB155, 0xCF1D, 0xB156, 0xCF1E, + 0xB157, 0xCF1F, 0xB158, 0xCF21, 0xB159, 0xCF22, 0xB15A, 0xCF23, 0xB161, 0xCF25, 0xB162, 0xCF26, 0xB163, 0xCF27, 0xB164, 0xCF28, + 0xB165, 0xCF29, 0xB166, 0xCF2A, 0xB167, 0xCF2B, 0xB168, 0xCF2E, 0xB169, 0xCF32, 0xB16A, 0xCF33, 0xB16B, 0xCF34, 0xB16C, 0xCF35, + 0xB16D, 0xCF36, 0xB16E, 0xCF37, 0xB16F, 0xCF39, 0xB170, 0xCF3A, 0xB171, 0xCF3B, 0xB172, 0xCF3C, 0xB173, 0xCF3D, 0xB174, 0xCF3E, + 0xB175, 0xCF3F, 0xB176, 0xCF40, 0xB177, 0xCF41, 0xB178, 0xCF42, 0xB179, 0xCF43, 0xB17A, 0xCF44, 0xB181, 0xCF45, 0xB182, 0xCF46, + 0xB183, 0xCF47, 0xB184, 0xCF48, 0xB185, 0xCF49, 0xB186, 0xCF4A, 0xB187, 0xCF4B, 0xB188, 0xCF4C, 0xB189, 0xCF4D, 0xB18A, 0xCF4E, + 0xB18B, 0xCF4F, 0xB18C, 0xCF50, 0xB18D, 0xCF51, 0xB18E, 0xCF52, 0xB18F, 0xCF53, 0xB190, 0xCF56, 0xB191, 0xCF57, 0xB192, 0xCF59, + 0xB193, 0xCF5A, 0xB194, 0xCF5B, 0xB195, 0xCF5D, 0xB196, 0xCF5E, 0xB197, 0xCF5F, 0xB198, 0xCF60, 0xB199, 0xCF61, 0xB19A, 0xCF62, + 0xB19B, 0xCF63, 0xB19C, 0xCF66, 0xB19D, 0xCF68, 0xB19E, 0xCF6A, 0xB19F, 0xCF6B, 0xB1A0, 0xCF6C, 0xB1A1, 0xAD0C, 0xB1A2, 0xAD0D, + 0xB1A3, 0xAD0F, 0xB1A4, 0xAD11, 0xB1A5, 0xAD18, 0xB1A6, 0xAD1C, 0xB1A7, 0xAD20, 0xB1A8, 0xAD29, 0xB1A9, 0xAD2C, 0xB1AA, 0xAD2D, + 0xB1AB, 0xAD34, 0xB1AC, 0xAD35, 0xB1AD, 0xAD38, 0xB1AE, 0xAD3C, 0xB1AF, 0xAD44, 0xB1B0, 0xAD45, 0xB1B1, 0xAD47, 0xB1B2, 0xAD49, + 0xB1B3, 0xAD50, 0xB1B4, 0xAD54, 0xB1B5, 0xAD58, 0xB1B6, 0xAD61, 0xB1B7, 0xAD63, 0xB1B8, 0xAD6C, 0xB1B9, 0xAD6D, 0xB1BA, 0xAD70, + 0xB1BB, 0xAD73, 0xB1BC, 0xAD74, 0xB1BD, 0xAD75, 0xB1BE, 0xAD76, 0xB1BF, 0xAD7B, 0xB1C0, 0xAD7C, 0xB1C1, 0xAD7D, 0xB1C2, 0xAD7F, + 0xB1C3, 0xAD81, 0xB1C4, 0xAD82, 0xB1C5, 0xAD88, 0xB1C6, 0xAD89, 0xB1C7, 0xAD8C, 0xB1C8, 0xAD90, 0xB1C9, 0xAD9C, 0xB1CA, 0xAD9D, + 0xB1CB, 0xADA4, 0xB1CC, 0xADB7, 0xB1CD, 0xADC0, 0xB1CE, 0xADC1, 0xB1CF, 0xADC4, 0xB1D0, 0xADC8, 0xB1D1, 0xADD0, 0xB1D2, 0xADD1, + 0xB1D3, 0xADD3, 0xB1D4, 0xADDC, 0xB1D5, 0xADE0, 0xB1D6, 0xADE4, 0xB1D7, 0xADF8, 0xB1D8, 0xADF9, 0xB1D9, 0xADFC, 0xB1DA, 0xADFF, + 0xB1DB, 0xAE00, 0xB1DC, 0xAE01, 0xB1DD, 0xAE08, 0xB1DE, 0xAE09, 0xB1DF, 0xAE0B, 0xB1E0, 0xAE0D, 0xB1E1, 0xAE14, 0xB1E2, 0xAE30, + 0xB1E3, 0xAE31, 0xB1E4, 0xAE34, 0xB1E5, 0xAE37, 0xB1E6, 0xAE38, 0xB1E7, 0xAE3A, 0xB1E8, 0xAE40, 0xB1E9, 0xAE41, 0xB1EA, 0xAE43, + 0xB1EB, 0xAE45, 0xB1EC, 0xAE46, 0xB1ED, 0xAE4A, 0xB1EE, 0xAE4C, 0xB1EF, 0xAE4D, 0xB1F0, 0xAE4E, 0xB1F1, 0xAE50, 0xB1F2, 0xAE54, + 0xB1F3, 0xAE56, 0xB1F4, 0xAE5C, 0xB1F5, 0xAE5D, 0xB1F6, 0xAE5F, 0xB1F7, 0xAE60, 0xB1F8, 0xAE61, 0xB1F9, 0xAE65, 0xB1FA, 0xAE68, + 0xB1FB, 0xAE69, 0xB1FC, 0xAE6C, 0xB1FD, 0xAE70, 0xB1FE, 0xAE78, 0xB241, 0xCF6D, 0xB242, 0xCF6E, 0xB243, 0xCF6F, 0xB244, 0xCF72, + 0xB245, 0xCF73, 0xB246, 0xCF75, 0xB247, 0xCF76, 0xB248, 0xCF77, 0xB249, 0xCF79, 0xB24A, 0xCF7A, 0xB24B, 0xCF7B, 0xB24C, 0xCF7C, + 0xB24D, 0xCF7D, 0xB24E, 0xCF7E, 0xB24F, 0xCF7F, 0xB250, 0xCF81, 0xB251, 0xCF82, 0xB252, 0xCF83, 0xB253, 0xCF84, 0xB254, 0xCF86, + 0xB255, 0xCF87, 0xB256, 0xCF88, 0xB257, 0xCF89, 0xB258, 0xCF8A, 0xB259, 0xCF8B, 0xB25A, 0xCF8D, 0xB261, 0xCF8E, 0xB262, 0xCF8F, + 0xB263, 0xCF90, 0xB264, 0xCF91, 0xB265, 0xCF92, 0xB266, 0xCF93, 0xB267, 0xCF94, 0xB268, 0xCF95, 0xB269, 0xCF96, 0xB26A, 0xCF97, + 0xB26B, 0xCF98, 0xB26C, 0xCF99, 0xB26D, 0xCF9A, 0xB26E, 0xCF9B, 0xB26F, 0xCF9C, 0xB270, 0xCF9D, 0xB271, 0xCF9E, 0xB272, 0xCF9F, + 0xB273, 0xCFA0, 0xB274, 0xCFA2, 0xB275, 0xCFA3, 0xB276, 0xCFA4, 0xB277, 0xCFA5, 0xB278, 0xCFA6, 0xB279, 0xCFA7, 0xB27A, 0xCFA9, + 0xB281, 0xCFAA, 0xB282, 0xCFAB, 0xB283, 0xCFAC, 0xB284, 0xCFAD, 0xB285, 0xCFAE, 0xB286, 0xCFAF, 0xB287, 0xCFB1, 0xB288, 0xCFB2, + 0xB289, 0xCFB3, 0xB28A, 0xCFB4, 0xB28B, 0xCFB5, 0xB28C, 0xCFB6, 0xB28D, 0xCFB7, 0xB28E, 0xCFB8, 0xB28F, 0xCFB9, 0xB290, 0xCFBA, + 0xB291, 0xCFBB, 0xB292, 0xCFBC, 0xB293, 0xCFBD, 0xB294, 0xCFBE, 0xB295, 0xCFBF, 0xB296, 0xCFC0, 0xB297, 0xCFC1, 0xB298, 0xCFC2, + 0xB299, 0xCFC3, 0xB29A, 0xCFC5, 0xB29B, 0xCFC6, 0xB29C, 0xCFC7, 0xB29D, 0xCFC8, 0xB29E, 0xCFC9, 0xB29F, 0xCFCA, 0xB2A0, 0xCFCB, + 0xB2A1, 0xAE79, 0xB2A2, 0xAE7B, 0xB2A3, 0xAE7C, 0xB2A4, 0xAE7D, 0xB2A5, 0xAE84, 0xB2A6, 0xAE85, 0xB2A7, 0xAE8C, 0xB2A8, 0xAEBC, + 0xB2A9, 0xAEBD, 0xB2AA, 0xAEBE, 0xB2AB, 0xAEC0, 0xB2AC, 0xAEC4, 0xB2AD, 0xAECC, 0xB2AE, 0xAECD, 0xB2AF, 0xAECF, 0xB2B0, 0xAED0, + 0xB2B1, 0xAED1, 0xB2B2, 0xAED8, 0xB2B3, 0xAED9, 0xB2B4, 0xAEDC, 0xB2B5, 0xAEE8, 0xB2B6, 0xAEEB, 0xB2B7, 0xAEED, 0xB2B8, 0xAEF4, + 0xB2B9, 0xAEF8, 0xB2BA, 0xAEFC, 0xB2BB, 0xAF07, 0xB2BC, 0xAF08, 0xB2BD, 0xAF0D, 0xB2BE, 0xAF10, 0xB2BF, 0xAF2C, 0xB2C0, 0xAF2D, + 0xB2C1, 0xAF30, 0xB2C2, 0xAF32, 0xB2C3, 0xAF34, 0xB2C4, 0xAF3C, 0xB2C5, 0xAF3D, 0xB2C6, 0xAF3F, 0xB2C7, 0xAF41, 0xB2C8, 0xAF42, + 0xB2C9, 0xAF43, 0xB2CA, 0xAF48, 0xB2CB, 0xAF49, 0xB2CC, 0xAF50, 0xB2CD, 0xAF5C, 0xB2CE, 0xAF5D, 0xB2CF, 0xAF64, 0xB2D0, 0xAF65, + 0xB2D1, 0xAF79, 0xB2D2, 0xAF80, 0xB2D3, 0xAF84, 0xB2D4, 0xAF88, 0xB2D5, 0xAF90, 0xB2D6, 0xAF91, 0xB2D7, 0xAF95, 0xB2D8, 0xAF9C, + 0xB2D9, 0xAFB8, 0xB2DA, 0xAFB9, 0xB2DB, 0xAFBC, 0xB2DC, 0xAFC0, 0xB2DD, 0xAFC7, 0xB2DE, 0xAFC8, 0xB2DF, 0xAFC9, 0xB2E0, 0xAFCB, + 0xB2E1, 0xAFCD, 0xB2E2, 0xAFCE, 0xB2E3, 0xAFD4, 0xB2E4, 0xAFDC, 0xB2E5, 0xAFE8, 0xB2E6, 0xAFE9, 0xB2E7, 0xAFF0, 0xB2E8, 0xAFF1, + 0xB2E9, 0xAFF4, 0xB2EA, 0xAFF8, 0xB2EB, 0xB000, 0xB2EC, 0xB001, 0xB2ED, 0xB004, 0xB2EE, 0xB00C, 0xB2EF, 0xB010, 0xB2F0, 0xB014, + 0xB2F1, 0xB01C, 0xB2F2, 0xB01D, 0xB2F3, 0xB028, 0xB2F4, 0xB044, 0xB2F5, 0xB045, 0xB2F6, 0xB048, 0xB2F7, 0xB04A, 0xB2F8, 0xB04C, + 0xB2F9, 0xB04E, 0xB2FA, 0xB053, 0xB2FB, 0xB054, 0xB2FC, 0xB055, 0xB2FD, 0xB057, 0xB2FE, 0xB059, 0xB341, 0xCFCC, 0xB342, 0xCFCD, + 0xB343, 0xCFCE, 0xB344, 0xCFCF, 0xB345, 0xCFD0, 0xB346, 0xCFD1, 0xB347, 0xCFD2, 0xB348, 0xCFD3, 0xB349, 0xCFD4, 0xB34A, 0xCFD5, + 0xB34B, 0xCFD6, 0xB34C, 0xCFD7, 0xB34D, 0xCFD8, 0xB34E, 0xCFD9, 0xB34F, 0xCFDA, 0xB350, 0xCFDB, 0xB351, 0xCFDC, 0xB352, 0xCFDD, + 0xB353, 0xCFDE, 0xB354, 0xCFDF, 0xB355, 0xCFE2, 0xB356, 0xCFE3, 0xB357, 0xCFE5, 0xB358, 0xCFE6, 0xB359, 0xCFE7, 0xB35A, 0xCFE9, + 0xB361, 0xCFEA, 0xB362, 0xCFEB, 0xB363, 0xCFEC, 0xB364, 0xCFED, 0xB365, 0xCFEE, 0xB366, 0xCFEF, 0xB367, 0xCFF2, 0xB368, 0xCFF4, + 0xB369, 0xCFF6, 0xB36A, 0xCFF7, 0xB36B, 0xCFF8, 0xB36C, 0xCFF9, 0xB36D, 0xCFFA, 0xB36E, 0xCFFB, 0xB36F, 0xCFFD, 0xB370, 0xCFFE, + 0xB371, 0xCFFF, 0xB372, 0xD001, 0xB373, 0xD002, 0xB374, 0xD003, 0xB375, 0xD005, 0xB376, 0xD006, 0xB377, 0xD007, 0xB378, 0xD008, + 0xB379, 0xD009, 0xB37A, 0xD00A, 0xB381, 0xD00B, 0xB382, 0xD00C, 0xB383, 0xD00D, 0xB384, 0xD00E, 0xB385, 0xD00F, 0xB386, 0xD010, + 0xB387, 0xD012, 0xB388, 0xD013, 0xB389, 0xD014, 0xB38A, 0xD015, 0xB38B, 0xD016, 0xB38C, 0xD017, 0xB38D, 0xD019, 0xB38E, 0xD01A, + 0xB38F, 0xD01B, 0xB390, 0xD01C, 0xB391, 0xD01D, 0xB392, 0xD01E, 0xB393, 0xD01F, 0xB394, 0xD020, 0xB395, 0xD021, 0xB396, 0xD022, + 0xB397, 0xD023, 0xB398, 0xD024, 0xB399, 0xD025, 0xB39A, 0xD026, 0xB39B, 0xD027, 0xB39C, 0xD028, 0xB39D, 0xD029, 0xB39E, 0xD02A, + 0xB39F, 0xD02B, 0xB3A0, 0xD02C, 0xB3A1, 0xB05D, 0xB3A2, 0xB07C, 0xB3A3, 0xB07D, 0xB3A4, 0xB080, 0xB3A5, 0xB084, 0xB3A6, 0xB08C, + 0xB3A7, 0xB08D, 0xB3A8, 0xB08F, 0xB3A9, 0xB091, 0xB3AA, 0xB098, 0xB3AB, 0xB099, 0xB3AC, 0xB09A, 0xB3AD, 0xB09C, 0xB3AE, 0xB09F, + 0xB3AF, 0xB0A0, 0xB3B0, 0xB0A1, 0xB3B1, 0xB0A2, 0xB3B2, 0xB0A8, 0xB3B3, 0xB0A9, 0xB3B4, 0xB0AB, 0xB3B5, 0xB0AC, 0xB3B6, 0xB0AD, + 0xB3B7, 0xB0AE, 0xB3B8, 0xB0AF, 0xB3B9, 0xB0B1, 0xB3BA, 0xB0B3, 0xB3BB, 0xB0B4, 0xB3BC, 0xB0B5, 0xB3BD, 0xB0B8, 0xB3BE, 0xB0BC, + 0xB3BF, 0xB0C4, 0xB3C0, 0xB0C5, 0xB3C1, 0xB0C7, 0xB3C2, 0xB0C8, 0xB3C3, 0xB0C9, 0xB3C4, 0xB0D0, 0xB3C5, 0xB0D1, 0xB3C6, 0xB0D4, + 0xB3C7, 0xB0D8, 0xB3C8, 0xB0E0, 0xB3C9, 0xB0E5, 0xB3CA, 0xB108, 0xB3CB, 0xB109, 0xB3CC, 0xB10B, 0xB3CD, 0xB10C, 0xB3CE, 0xB110, + 0xB3CF, 0xB112, 0xB3D0, 0xB113, 0xB3D1, 0xB118, 0xB3D2, 0xB119, 0xB3D3, 0xB11B, 0xB3D4, 0xB11C, 0xB3D5, 0xB11D, 0xB3D6, 0xB123, + 0xB3D7, 0xB124, 0xB3D8, 0xB125, 0xB3D9, 0xB128, 0xB3DA, 0xB12C, 0xB3DB, 0xB134, 0xB3DC, 0xB135, 0xB3DD, 0xB137, 0xB3DE, 0xB138, + 0xB3DF, 0xB139, 0xB3E0, 0xB140, 0xB3E1, 0xB141, 0xB3E2, 0xB144, 0xB3E3, 0xB148, 0xB3E4, 0xB150, 0xB3E5, 0xB151, 0xB3E6, 0xB154, + 0xB3E7, 0xB155, 0xB3E8, 0xB158, 0xB3E9, 0xB15C, 0xB3EA, 0xB160, 0xB3EB, 0xB178, 0xB3EC, 0xB179, 0xB3ED, 0xB17C, 0xB3EE, 0xB180, + 0xB3EF, 0xB182, 0xB3F0, 0xB188, 0xB3F1, 0xB189, 0xB3F2, 0xB18B, 0xB3F3, 0xB18D, 0xB3F4, 0xB192, 0xB3F5, 0xB193, 0xB3F6, 0xB194, + 0xB3F7, 0xB198, 0xB3F8, 0xB19C, 0xB3F9, 0xB1A8, 0xB3FA, 0xB1CC, 0xB3FB, 0xB1D0, 0xB3FC, 0xB1D4, 0xB3FD, 0xB1DC, 0xB3FE, 0xB1DD, + 0xB441, 0xD02E, 0xB442, 0xD02F, 0xB443, 0xD030, 0xB444, 0xD031, 0xB445, 0xD032, 0xB446, 0xD033, 0xB447, 0xD036, 0xB448, 0xD037, + 0xB449, 0xD039, 0xB44A, 0xD03A, 0xB44B, 0xD03B, 0xB44C, 0xD03D, 0xB44D, 0xD03E, 0xB44E, 0xD03F, 0xB44F, 0xD040, 0xB450, 0xD041, + 0xB451, 0xD042, 0xB452, 0xD043, 0xB453, 0xD046, 0xB454, 0xD048, 0xB455, 0xD04A, 0xB456, 0xD04B, 0xB457, 0xD04C, 0xB458, 0xD04D, + 0xB459, 0xD04E, 0xB45A, 0xD04F, 0xB461, 0xD051, 0xB462, 0xD052, 0xB463, 0xD053, 0xB464, 0xD055, 0xB465, 0xD056, 0xB466, 0xD057, + 0xB467, 0xD059, 0xB468, 0xD05A, 0xB469, 0xD05B, 0xB46A, 0xD05C, 0xB46B, 0xD05D, 0xB46C, 0xD05E, 0xB46D, 0xD05F, 0xB46E, 0xD061, + 0xB46F, 0xD062, 0xB470, 0xD063, 0xB471, 0xD064, 0xB472, 0xD065, 0xB473, 0xD066, 0xB474, 0xD067, 0xB475, 0xD068, 0xB476, 0xD069, + 0xB477, 0xD06A, 0xB478, 0xD06B, 0xB479, 0xD06E, 0xB47A, 0xD06F, 0xB481, 0xD071, 0xB482, 0xD072, 0xB483, 0xD073, 0xB484, 0xD075, + 0xB485, 0xD076, 0xB486, 0xD077, 0xB487, 0xD078, 0xB488, 0xD079, 0xB489, 0xD07A, 0xB48A, 0xD07B, 0xB48B, 0xD07E, 0xB48C, 0xD07F, + 0xB48D, 0xD080, 0xB48E, 0xD082, 0xB48F, 0xD083, 0xB490, 0xD084, 0xB491, 0xD085, 0xB492, 0xD086, 0xB493, 0xD087, 0xB494, 0xD088, + 0xB495, 0xD089, 0xB496, 0xD08A, 0xB497, 0xD08B, 0xB498, 0xD08C, 0xB499, 0xD08D, 0xB49A, 0xD08E, 0xB49B, 0xD08F, 0xB49C, 0xD090, + 0xB49D, 0xD091, 0xB49E, 0xD092, 0xB49F, 0xD093, 0xB4A0, 0xD094, 0xB4A1, 0xB1DF, 0xB4A2, 0xB1E8, 0xB4A3, 0xB1E9, 0xB4A4, 0xB1EC, + 0xB4A5, 0xB1F0, 0xB4A6, 0xB1F9, 0xB4A7, 0xB1FB, 0xB4A8, 0xB1FD, 0xB4A9, 0xB204, 0xB4AA, 0xB205, 0xB4AB, 0xB208, 0xB4AC, 0xB20B, + 0xB4AD, 0xB20C, 0xB4AE, 0xB214, 0xB4AF, 0xB215, 0xB4B0, 0xB217, 0xB4B1, 0xB219, 0xB4B2, 0xB220, 0xB4B3, 0xB234, 0xB4B4, 0xB23C, + 0xB4B5, 0xB258, 0xB4B6, 0xB25C, 0xB4B7, 0xB260, 0xB4B8, 0xB268, 0xB4B9, 0xB269, 0xB4BA, 0xB274, 0xB4BB, 0xB275, 0xB4BC, 0xB27C, + 0xB4BD, 0xB284, 0xB4BE, 0xB285, 0xB4BF, 0xB289, 0xB4C0, 0xB290, 0xB4C1, 0xB291, 0xB4C2, 0xB294, 0xB4C3, 0xB298, 0xB4C4, 0xB299, + 0xB4C5, 0xB29A, 0xB4C6, 0xB2A0, 0xB4C7, 0xB2A1, 0xB4C8, 0xB2A3, 0xB4C9, 0xB2A5, 0xB4CA, 0xB2A6, 0xB4CB, 0xB2AA, 0xB4CC, 0xB2AC, + 0xB4CD, 0xB2B0, 0xB4CE, 0xB2B4, 0xB4CF, 0xB2C8, 0xB4D0, 0xB2C9, 0xB4D1, 0xB2CC, 0xB4D2, 0xB2D0, 0xB4D3, 0xB2D2, 0xB4D4, 0xB2D8, + 0xB4D5, 0xB2D9, 0xB4D6, 0xB2DB, 0xB4D7, 0xB2DD, 0xB4D8, 0xB2E2, 0xB4D9, 0xB2E4, 0xB4DA, 0xB2E5, 0xB4DB, 0xB2E6, 0xB4DC, 0xB2E8, + 0xB4DD, 0xB2EB, 0xB4DE, 0xB2EC, 0xB4DF, 0xB2ED, 0xB4E0, 0xB2EE, 0xB4E1, 0xB2EF, 0xB4E2, 0xB2F3, 0xB4E3, 0xB2F4, 0xB4E4, 0xB2F5, + 0xB4E5, 0xB2F7, 0xB4E6, 0xB2F8, 0xB4E7, 0xB2F9, 0xB4E8, 0xB2FA, 0xB4E9, 0xB2FB, 0xB4EA, 0xB2FF, 0xB4EB, 0xB300, 0xB4EC, 0xB301, + 0xB4ED, 0xB304, 0xB4EE, 0xB308, 0xB4EF, 0xB310, 0xB4F0, 0xB311, 0xB4F1, 0xB313, 0xB4F2, 0xB314, 0xB4F3, 0xB315, 0xB4F4, 0xB31C, + 0xB4F5, 0xB354, 0xB4F6, 0xB355, 0xB4F7, 0xB356, 0xB4F8, 0xB358, 0xB4F9, 0xB35B, 0xB4FA, 0xB35C, 0xB4FB, 0xB35E, 0xB4FC, 0xB35F, + 0xB4FD, 0xB364, 0xB4FE, 0xB365, 0xB541, 0xD095, 0xB542, 0xD096, 0xB543, 0xD097, 0xB544, 0xD098, 0xB545, 0xD099, 0xB546, 0xD09A, + 0xB547, 0xD09B, 0xB548, 0xD09C, 0xB549, 0xD09D, 0xB54A, 0xD09E, 0xB54B, 0xD09F, 0xB54C, 0xD0A0, 0xB54D, 0xD0A1, 0xB54E, 0xD0A2, + 0xB54F, 0xD0A3, 0xB550, 0xD0A6, 0xB551, 0xD0A7, 0xB552, 0xD0A9, 0xB553, 0xD0AA, 0xB554, 0xD0AB, 0xB555, 0xD0AD, 0xB556, 0xD0AE, + 0xB557, 0xD0AF, 0xB558, 0xD0B0, 0xB559, 0xD0B1, 0xB55A, 0xD0B2, 0xB561, 0xD0B3, 0xB562, 0xD0B6, 0xB563, 0xD0B8, 0xB564, 0xD0BA, + 0xB565, 0xD0BB, 0xB566, 0xD0BC, 0xB567, 0xD0BD, 0xB568, 0xD0BE, 0xB569, 0xD0BF, 0xB56A, 0xD0C2, 0xB56B, 0xD0C3, 0xB56C, 0xD0C5, + 0xB56D, 0xD0C6, 0xB56E, 0xD0C7, 0xB56F, 0xD0CA, 0xB570, 0xD0CB, 0xB571, 0xD0CC, 0xB572, 0xD0CD, 0xB573, 0xD0CE, 0xB574, 0xD0CF, + 0xB575, 0xD0D2, 0xB576, 0xD0D6, 0xB577, 0xD0D7, 0xB578, 0xD0D8, 0xB579, 0xD0D9, 0xB57A, 0xD0DA, 0xB581, 0xD0DB, 0xB582, 0xD0DE, + 0xB583, 0xD0DF, 0xB584, 0xD0E1, 0xB585, 0xD0E2, 0xB586, 0xD0E3, 0xB587, 0xD0E5, 0xB588, 0xD0E6, 0xB589, 0xD0E7, 0xB58A, 0xD0E8, + 0xB58B, 0xD0E9, 0xB58C, 0xD0EA, 0xB58D, 0xD0EB, 0xB58E, 0xD0EE, 0xB58F, 0xD0F2, 0xB590, 0xD0F3, 0xB591, 0xD0F4, 0xB592, 0xD0F5, + 0xB593, 0xD0F6, 0xB594, 0xD0F7, 0xB595, 0xD0F9, 0xB596, 0xD0FA, 0xB597, 0xD0FB, 0xB598, 0xD0FC, 0xB599, 0xD0FD, 0xB59A, 0xD0FE, + 0xB59B, 0xD0FF, 0xB59C, 0xD100, 0xB59D, 0xD101, 0xB59E, 0xD102, 0xB59F, 0xD103, 0xB5A0, 0xD104, 0xB5A1, 0xB367, 0xB5A2, 0xB369, + 0xB5A3, 0xB36B, 0xB5A4, 0xB36E, 0xB5A5, 0xB370, 0xB5A6, 0xB371, 0xB5A7, 0xB374, 0xB5A8, 0xB378, 0xB5A9, 0xB380, 0xB5AA, 0xB381, + 0xB5AB, 0xB383, 0xB5AC, 0xB384, 0xB5AD, 0xB385, 0xB5AE, 0xB38C, 0xB5AF, 0xB390, 0xB5B0, 0xB394, 0xB5B1, 0xB3A0, 0xB5B2, 0xB3A1, + 0xB5B3, 0xB3A8, 0xB5B4, 0xB3AC, 0xB5B5, 0xB3C4, 0xB5B6, 0xB3C5, 0xB5B7, 0xB3C8, 0xB5B8, 0xB3CB, 0xB5B9, 0xB3CC, 0xB5BA, 0xB3CE, + 0xB5BB, 0xB3D0, 0xB5BC, 0xB3D4, 0xB5BD, 0xB3D5, 0xB5BE, 0xB3D7, 0xB5BF, 0xB3D9, 0xB5C0, 0xB3DB, 0xB5C1, 0xB3DD, 0xB5C2, 0xB3E0, + 0xB5C3, 0xB3E4, 0xB5C4, 0xB3E8, 0xB5C5, 0xB3FC, 0xB5C6, 0xB410, 0xB5C7, 0xB418, 0xB5C8, 0xB41C, 0xB5C9, 0xB420, 0xB5CA, 0xB428, + 0xB5CB, 0xB429, 0xB5CC, 0xB42B, 0xB5CD, 0xB434, 0xB5CE, 0xB450, 0xB5CF, 0xB451, 0xB5D0, 0xB454, 0xB5D1, 0xB458, 0xB5D2, 0xB460, + 0xB5D3, 0xB461, 0xB5D4, 0xB463, 0xB5D5, 0xB465, 0xB5D6, 0xB46C, 0xB5D7, 0xB480, 0xB5D8, 0xB488, 0xB5D9, 0xB49D, 0xB5DA, 0xB4A4, + 0xB5DB, 0xB4A8, 0xB5DC, 0xB4AC, 0xB5DD, 0xB4B5, 0xB5DE, 0xB4B7, 0xB5DF, 0xB4B9, 0xB5E0, 0xB4C0, 0xB5E1, 0xB4C4, 0xB5E2, 0xB4C8, + 0xB5E3, 0xB4D0, 0xB5E4, 0xB4D5, 0xB5E5, 0xB4DC, 0xB5E6, 0xB4DD, 0xB5E7, 0xB4E0, 0xB5E8, 0xB4E3, 0xB5E9, 0xB4E4, 0xB5EA, 0xB4E6, + 0xB5EB, 0xB4EC, 0xB5EC, 0xB4ED, 0xB5ED, 0xB4EF, 0xB5EE, 0xB4F1, 0xB5EF, 0xB4F8, 0xB5F0, 0xB514, 0xB5F1, 0xB515, 0xB5F2, 0xB518, + 0xB5F3, 0xB51B, 0xB5F4, 0xB51C, 0xB5F5, 0xB524, 0xB5F6, 0xB525, 0xB5F7, 0xB527, 0xB5F8, 0xB528, 0xB5F9, 0xB529, 0xB5FA, 0xB52A, + 0xB5FB, 0xB530, 0xB5FC, 0xB531, 0xB5FD, 0xB534, 0xB5FE, 0xB538, 0xB641, 0xD105, 0xB642, 0xD106, 0xB643, 0xD107, 0xB644, 0xD108, + 0xB645, 0xD109, 0xB646, 0xD10A, 0xB647, 0xD10B, 0xB648, 0xD10C, 0xB649, 0xD10E, 0xB64A, 0xD10F, 0xB64B, 0xD110, 0xB64C, 0xD111, + 0xB64D, 0xD112, 0xB64E, 0xD113, 0xB64F, 0xD114, 0xB650, 0xD115, 0xB651, 0xD116, 0xB652, 0xD117, 0xB653, 0xD118, 0xB654, 0xD119, + 0xB655, 0xD11A, 0xB656, 0xD11B, 0xB657, 0xD11C, 0xB658, 0xD11D, 0xB659, 0xD11E, 0xB65A, 0xD11F, 0xB661, 0xD120, 0xB662, 0xD121, + 0xB663, 0xD122, 0xB664, 0xD123, 0xB665, 0xD124, 0xB666, 0xD125, 0xB667, 0xD126, 0xB668, 0xD127, 0xB669, 0xD128, 0xB66A, 0xD129, + 0xB66B, 0xD12A, 0xB66C, 0xD12B, 0xB66D, 0xD12C, 0xB66E, 0xD12D, 0xB66F, 0xD12E, 0xB670, 0xD12F, 0xB671, 0xD132, 0xB672, 0xD133, + 0xB673, 0xD135, 0xB674, 0xD136, 0xB675, 0xD137, 0xB676, 0xD139, 0xB677, 0xD13B, 0xB678, 0xD13C, 0xB679, 0xD13D, 0xB67A, 0xD13E, + 0xB681, 0xD13F, 0xB682, 0xD142, 0xB683, 0xD146, 0xB684, 0xD147, 0xB685, 0xD148, 0xB686, 0xD149, 0xB687, 0xD14A, 0xB688, 0xD14B, + 0xB689, 0xD14E, 0xB68A, 0xD14F, 0xB68B, 0xD151, 0xB68C, 0xD152, 0xB68D, 0xD153, 0xB68E, 0xD155, 0xB68F, 0xD156, 0xB690, 0xD157, + 0xB691, 0xD158, 0xB692, 0xD159, 0xB693, 0xD15A, 0xB694, 0xD15B, 0xB695, 0xD15E, 0xB696, 0xD160, 0xB697, 0xD162, 0xB698, 0xD163, + 0xB699, 0xD164, 0xB69A, 0xD165, 0xB69B, 0xD166, 0xB69C, 0xD167, 0xB69D, 0xD169, 0xB69E, 0xD16A, 0xB69F, 0xD16B, 0xB6A0, 0xD16D, + 0xB6A1, 0xB540, 0xB6A2, 0xB541, 0xB6A3, 0xB543, 0xB6A4, 0xB544, 0xB6A5, 0xB545, 0xB6A6, 0xB54B, 0xB6A7, 0xB54C, 0xB6A8, 0xB54D, + 0xB6A9, 0xB550, 0xB6AA, 0xB554, 0xB6AB, 0xB55C, 0xB6AC, 0xB55D, 0xB6AD, 0xB55F, 0xB6AE, 0xB560, 0xB6AF, 0xB561, 0xB6B0, 0xB5A0, + 0xB6B1, 0xB5A1, 0xB6B2, 0xB5A4, 0xB6B3, 0xB5A8, 0xB6B4, 0xB5AA, 0xB6B5, 0xB5AB, 0xB6B6, 0xB5B0, 0xB6B7, 0xB5B1, 0xB6B8, 0xB5B3, + 0xB6B9, 0xB5B4, 0xB6BA, 0xB5B5, 0xB6BB, 0xB5BB, 0xB6BC, 0xB5BC, 0xB6BD, 0xB5BD, 0xB6BE, 0xB5C0, 0xB6BF, 0xB5C4, 0xB6C0, 0xB5CC, + 0xB6C1, 0xB5CD, 0xB6C2, 0xB5CF, 0xB6C3, 0xB5D0, 0xB6C4, 0xB5D1, 0xB6C5, 0xB5D8, 0xB6C6, 0xB5EC, 0xB6C7, 0xB610, 0xB6C8, 0xB611, + 0xB6C9, 0xB614, 0xB6CA, 0xB618, 0xB6CB, 0xB625, 0xB6CC, 0xB62C, 0xB6CD, 0xB634, 0xB6CE, 0xB648, 0xB6CF, 0xB664, 0xB6D0, 0xB668, + 0xB6D1, 0xB69C, 0xB6D2, 0xB69D, 0xB6D3, 0xB6A0, 0xB6D4, 0xB6A4, 0xB6D5, 0xB6AB, 0xB6D6, 0xB6AC, 0xB6D7, 0xB6B1, 0xB6D8, 0xB6D4, + 0xB6D9, 0xB6F0, 0xB6DA, 0xB6F4, 0xB6DB, 0xB6F8, 0xB6DC, 0xB700, 0xB6DD, 0xB701, 0xB6DE, 0xB705, 0xB6DF, 0xB728, 0xB6E0, 0xB729, + 0xB6E1, 0xB72C, 0xB6E2, 0xB72F, 0xB6E3, 0xB730, 0xB6E4, 0xB738, 0xB6E5, 0xB739, 0xB6E6, 0xB73B, 0xB6E7, 0xB744, 0xB6E8, 0xB748, + 0xB6E9, 0xB74C, 0xB6EA, 0xB754, 0xB6EB, 0xB755, 0xB6EC, 0xB760, 0xB6ED, 0xB764, 0xB6EE, 0xB768, 0xB6EF, 0xB770, 0xB6F0, 0xB771, + 0xB6F1, 0xB773, 0xB6F2, 0xB775, 0xB6F3, 0xB77C, 0xB6F4, 0xB77D, 0xB6F5, 0xB780, 0xB6F6, 0xB784, 0xB6F7, 0xB78C, 0xB6F8, 0xB78D, + 0xB6F9, 0xB78F, 0xB6FA, 0xB790, 0xB6FB, 0xB791, 0xB6FC, 0xB792, 0xB6FD, 0xB796, 0xB6FE, 0xB797, 0xB741, 0xD16E, 0xB742, 0xD16F, + 0xB743, 0xD170, 0xB744, 0xD171, 0xB745, 0xD172, 0xB746, 0xD173, 0xB747, 0xD174, 0xB748, 0xD175, 0xB749, 0xD176, 0xB74A, 0xD177, + 0xB74B, 0xD178, 0xB74C, 0xD179, 0xB74D, 0xD17A, 0xB74E, 0xD17B, 0xB74F, 0xD17D, 0xB750, 0xD17E, 0xB751, 0xD17F, 0xB752, 0xD180, + 0xB753, 0xD181, 0xB754, 0xD182, 0xB755, 0xD183, 0xB756, 0xD185, 0xB757, 0xD186, 0xB758, 0xD187, 0xB759, 0xD189, 0xB75A, 0xD18A, + 0xB761, 0xD18B, 0xB762, 0xD18C, 0xB763, 0xD18D, 0xB764, 0xD18E, 0xB765, 0xD18F, 0xB766, 0xD190, 0xB767, 0xD191, 0xB768, 0xD192, + 0xB769, 0xD193, 0xB76A, 0xD194, 0xB76B, 0xD195, 0xB76C, 0xD196, 0xB76D, 0xD197, 0xB76E, 0xD198, 0xB76F, 0xD199, 0xB770, 0xD19A, + 0xB771, 0xD19B, 0xB772, 0xD19C, 0xB773, 0xD19D, 0xB774, 0xD19E, 0xB775, 0xD19F, 0xB776, 0xD1A2, 0xB777, 0xD1A3, 0xB778, 0xD1A5, + 0xB779, 0xD1A6, 0xB77A, 0xD1A7, 0xB781, 0xD1A9, 0xB782, 0xD1AA, 0xB783, 0xD1AB, 0xB784, 0xD1AC, 0xB785, 0xD1AD, 0xB786, 0xD1AE, + 0xB787, 0xD1AF, 0xB788, 0xD1B2, 0xB789, 0xD1B4, 0xB78A, 0xD1B6, 0xB78B, 0xD1B7, 0xB78C, 0xD1B8, 0xB78D, 0xD1B9, 0xB78E, 0xD1BB, + 0xB78F, 0xD1BD, 0xB790, 0xD1BE, 0xB791, 0xD1BF, 0xB792, 0xD1C1, 0xB793, 0xD1C2, 0xB794, 0xD1C3, 0xB795, 0xD1C4, 0xB796, 0xD1C5, + 0xB797, 0xD1C6, 0xB798, 0xD1C7, 0xB799, 0xD1C8, 0xB79A, 0xD1C9, 0xB79B, 0xD1CA, 0xB79C, 0xD1CB, 0xB79D, 0xD1CC, 0xB79E, 0xD1CD, + 0xB79F, 0xD1CE, 0xB7A0, 0xD1CF, 0xB7A1, 0xB798, 0xB7A2, 0xB799, 0xB7A3, 0xB79C, 0xB7A4, 0xB7A0, 0xB7A5, 0xB7A8, 0xB7A6, 0xB7A9, + 0xB7A7, 0xB7AB, 0xB7A8, 0xB7AC, 0xB7A9, 0xB7AD, 0xB7AA, 0xB7B4, 0xB7AB, 0xB7B5, 0xB7AC, 0xB7B8, 0xB7AD, 0xB7C7, 0xB7AE, 0xB7C9, + 0xB7AF, 0xB7EC, 0xB7B0, 0xB7ED, 0xB7B1, 0xB7F0, 0xB7B2, 0xB7F4, 0xB7B3, 0xB7FC, 0xB7B4, 0xB7FD, 0xB7B5, 0xB7FF, 0xB7B6, 0xB800, + 0xB7B7, 0xB801, 0xB7B8, 0xB807, 0xB7B9, 0xB808, 0xB7BA, 0xB809, 0xB7BB, 0xB80C, 0xB7BC, 0xB810, 0xB7BD, 0xB818, 0xB7BE, 0xB819, + 0xB7BF, 0xB81B, 0xB7C0, 0xB81D, 0xB7C1, 0xB824, 0xB7C2, 0xB825, 0xB7C3, 0xB828, 0xB7C4, 0xB82C, 0xB7C5, 0xB834, 0xB7C6, 0xB835, + 0xB7C7, 0xB837, 0xB7C8, 0xB838, 0xB7C9, 0xB839, 0xB7CA, 0xB840, 0xB7CB, 0xB844, 0xB7CC, 0xB851, 0xB7CD, 0xB853, 0xB7CE, 0xB85C, + 0xB7CF, 0xB85D, 0xB7D0, 0xB860, 0xB7D1, 0xB864, 0xB7D2, 0xB86C, 0xB7D3, 0xB86D, 0xB7D4, 0xB86F, 0xB7D5, 0xB871, 0xB7D6, 0xB878, + 0xB7D7, 0xB87C, 0xB7D8, 0xB88D, 0xB7D9, 0xB8A8, 0xB7DA, 0xB8B0, 0xB7DB, 0xB8B4, 0xB7DC, 0xB8B8, 0xB7DD, 0xB8C0, 0xB7DE, 0xB8C1, + 0xB7DF, 0xB8C3, 0xB7E0, 0xB8C5, 0xB7E1, 0xB8CC, 0xB7E2, 0xB8D0, 0xB7E3, 0xB8D4, 0xB7E4, 0xB8DD, 0xB7E5, 0xB8DF, 0xB7E6, 0xB8E1, + 0xB7E7, 0xB8E8, 0xB7E8, 0xB8E9, 0xB7E9, 0xB8EC, 0xB7EA, 0xB8F0, 0xB7EB, 0xB8F8, 0xB7EC, 0xB8F9, 0xB7ED, 0xB8FB, 0xB7EE, 0xB8FD, + 0xB7EF, 0xB904, 0xB7F0, 0xB918, 0xB7F1, 0xB920, 0xB7F2, 0xB93C, 0xB7F3, 0xB93D, 0xB7F4, 0xB940, 0xB7F5, 0xB944, 0xB7F6, 0xB94C, + 0xB7F7, 0xB94F, 0xB7F8, 0xB951, 0xB7F9, 0xB958, 0xB7FA, 0xB959, 0xB7FB, 0xB95C, 0xB7FC, 0xB960, 0xB7FD, 0xB968, 0xB7FE, 0xB969, + 0xB841, 0xD1D0, 0xB842, 0xD1D1, 0xB843, 0xD1D2, 0xB844, 0xD1D3, 0xB845, 0xD1D4, 0xB846, 0xD1D5, 0xB847, 0xD1D6, 0xB848, 0xD1D7, + 0xB849, 0xD1D9, 0xB84A, 0xD1DA, 0xB84B, 0xD1DB, 0xB84C, 0xD1DC, 0xB84D, 0xD1DD, 0xB84E, 0xD1DE, 0xB84F, 0xD1DF, 0xB850, 0xD1E0, + 0xB851, 0xD1E1, 0xB852, 0xD1E2, 0xB853, 0xD1E3, 0xB854, 0xD1E4, 0xB855, 0xD1E5, 0xB856, 0xD1E6, 0xB857, 0xD1E7, 0xB858, 0xD1E8, + 0xB859, 0xD1E9, 0xB85A, 0xD1EA, 0xB861, 0xD1EB, 0xB862, 0xD1EC, 0xB863, 0xD1ED, 0xB864, 0xD1EE, 0xB865, 0xD1EF, 0xB866, 0xD1F0, + 0xB867, 0xD1F1, 0xB868, 0xD1F2, 0xB869, 0xD1F3, 0xB86A, 0xD1F5, 0xB86B, 0xD1F6, 0xB86C, 0xD1F7, 0xB86D, 0xD1F9, 0xB86E, 0xD1FA, + 0xB86F, 0xD1FB, 0xB870, 0xD1FC, 0xB871, 0xD1FD, 0xB872, 0xD1FE, 0xB873, 0xD1FF, 0xB874, 0xD200, 0xB875, 0xD201, 0xB876, 0xD202, + 0xB877, 0xD203, 0xB878, 0xD204, 0xB879, 0xD205, 0xB87A, 0xD206, 0xB881, 0xD208, 0xB882, 0xD20A, 0xB883, 0xD20B, 0xB884, 0xD20C, + 0xB885, 0xD20D, 0xB886, 0xD20E, 0xB887, 0xD20F, 0xB888, 0xD211, 0xB889, 0xD212, 0xB88A, 0xD213, 0xB88B, 0xD214, 0xB88C, 0xD215, + 0xB88D, 0xD216, 0xB88E, 0xD217, 0xB88F, 0xD218, 0xB890, 0xD219, 0xB891, 0xD21A, 0xB892, 0xD21B, 0xB893, 0xD21C, 0xB894, 0xD21D, + 0xB895, 0xD21E, 0xB896, 0xD21F, 0xB897, 0xD220, 0xB898, 0xD221, 0xB899, 0xD222, 0xB89A, 0xD223, 0xB89B, 0xD224, 0xB89C, 0xD225, + 0xB89D, 0xD226, 0xB89E, 0xD227, 0xB89F, 0xD228, 0xB8A0, 0xD229, 0xB8A1, 0xB96B, 0xB8A2, 0xB96D, 0xB8A3, 0xB974, 0xB8A4, 0xB975, + 0xB8A5, 0xB978, 0xB8A6, 0xB97C, 0xB8A7, 0xB984, 0xB8A8, 0xB985, 0xB8A9, 0xB987, 0xB8AA, 0xB989, 0xB8AB, 0xB98A, 0xB8AC, 0xB98D, + 0xB8AD, 0xB98E, 0xB8AE, 0xB9AC, 0xB8AF, 0xB9AD, 0xB8B0, 0xB9B0, 0xB8B1, 0xB9B4, 0xB8B2, 0xB9BC, 0xB8B3, 0xB9BD, 0xB8B4, 0xB9BF, + 0xB8B5, 0xB9C1, 0xB8B6, 0xB9C8, 0xB8B7, 0xB9C9, 0xB8B8, 0xB9CC, 0xB8B9, 0xB9CE, 0xB8BA, 0xB9CF, 0xB8BB, 0xB9D0, 0xB8BC, 0xB9D1, + 0xB8BD, 0xB9D2, 0xB8BE, 0xB9D8, 0xB8BF, 0xB9D9, 0xB8C0, 0xB9DB, 0xB8C1, 0xB9DD, 0xB8C2, 0xB9DE, 0xB8C3, 0xB9E1, 0xB8C4, 0xB9E3, + 0xB8C5, 0xB9E4, 0xB8C6, 0xB9E5, 0xB8C7, 0xB9E8, 0xB8C8, 0xB9EC, 0xB8C9, 0xB9F4, 0xB8CA, 0xB9F5, 0xB8CB, 0xB9F7, 0xB8CC, 0xB9F8, + 0xB8CD, 0xB9F9, 0xB8CE, 0xB9FA, 0xB8CF, 0xBA00, 0xB8D0, 0xBA01, 0xB8D1, 0xBA08, 0xB8D2, 0xBA15, 0xB8D3, 0xBA38, 0xB8D4, 0xBA39, + 0xB8D5, 0xBA3C, 0xB8D6, 0xBA40, 0xB8D7, 0xBA42, 0xB8D8, 0xBA48, 0xB8D9, 0xBA49, 0xB8DA, 0xBA4B, 0xB8DB, 0xBA4D, 0xB8DC, 0xBA4E, + 0xB8DD, 0xBA53, 0xB8DE, 0xBA54, 0xB8DF, 0xBA55, 0xB8E0, 0xBA58, 0xB8E1, 0xBA5C, 0xB8E2, 0xBA64, 0xB8E3, 0xBA65, 0xB8E4, 0xBA67, + 0xB8E5, 0xBA68, 0xB8E6, 0xBA69, 0xB8E7, 0xBA70, 0xB8E8, 0xBA71, 0xB8E9, 0xBA74, 0xB8EA, 0xBA78, 0xB8EB, 0xBA83, 0xB8EC, 0xBA84, + 0xB8ED, 0xBA85, 0xB8EE, 0xBA87, 0xB8EF, 0xBA8C, 0xB8F0, 0xBAA8, 0xB8F1, 0xBAA9, 0xB8F2, 0xBAAB, 0xB8F3, 0xBAAC, 0xB8F4, 0xBAB0, + 0xB8F5, 0xBAB2, 0xB8F6, 0xBAB8, 0xB8F7, 0xBAB9, 0xB8F8, 0xBABB, 0xB8F9, 0xBABD, 0xB8FA, 0xBAC4, 0xB8FB, 0xBAC8, 0xB8FC, 0xBAD8, + 0xB8FD, 0xBAD9, 0xB8FE, 0xBAFC, 0xB941, 0xD22A, 0xB942, 0xD22B, 0xB943, 0xD22E, 0xB944, 0xD22F, 0xB945, 0xD231, 0xB946, 0xD232, + 0xB947, 0xD233, 0xB948, 0xD235, 0xB949, 0xD236, 0xB94A, 0xD237, 0xB94B, 0xD238, 0xB94C, 0xD239, 0xB94D, 0xD23A, 0xB94E, 0xD23B, + 0xB94F, 0xD23E, 0xB950, 0xD240, 0xB951, 0xD242, 0xB952, 0xD243, 0xB953, 0xD244, 0xB954, 0xD245, 0xB955, 0xD246, 0xB956, 0xD247, + 0xB957, 0xD249, 0xB958, 0xD24A, 0xB959, 0xD24B, 0xB95A, 0xD24C, 0xB961, 0xD24D, 0xB962, 0xD24E, 0xB963, 0xD24F, 0xB964, 0xD250, + 0xB965, 0xD251, 0xB966, 0xD252, 0xB967, 0xD253, 0xB968, 0xD254, 0xB969, 0xD255, 0xB96A, 0xD256, 0xB96B, 0xD257, 0xB96C, 0xD258, + 0xB96D, 0xD259, 0xB96E, 0xD25A, 0xB96F, 0xD25B, 0xB970, 0xD25D, 0xB971, 0xD25E, 0xB972, 0xD25F, 0xB973, 0xD260, 0xB974, 0xD261, + 0xB975, 0xD262, 0xB976, 0xD263, 0xB977, 0xD265, 0xB978, 0xD266, 0xB979, 0xD267, 0xB97A, 0xD268, 0xB981, 0xD269, 0xB982, 0xD26A, + 0xB983, 0xD26B, 0xB984, 0xD26C, 0xB985, 0xD26D, 0xB986, 0xD26E, 0xB987, 0xD26F, 0xB988, 0xD270, 0xB989, 0xD271, 0xB98A, 0xD272, + 0xB98B, 0xD273, 0xB98C, 0xD274, 0xB98D, 0xD275, 0xB98E, 0xD276, 0xB98F, 0xD277, 0xB990, 0xD278, 0xB991, 0xD279, 0xB992, 0xD27A, + 0xB993, 0xD27B, 0xB994, 0xD27C, 0xB995, 0xD27D, 0xB996, 0xD27E, 0xB997, 0xD27F, 0xB998, 0xD282, 0xB999, 0xD283, 0xB99A, 0xD285, + 0xB99B, 0xD286, 0xB99C, 0xD287, 0xB99D, 0xD289, 0xB99E, 0xD28A, 0xB99F, 0xD28B, 0xB9A0, 0xD28C, 0xB9A1, 0xBB00, 0xB9A2, 0xBB04, + 0xB9A3, 0xBB0D, 0xB9A4, 0xBB0F, 0xB9A5, 0xBB11, 0xB9A6, 0xBB18, 0xB9A7, 0xBB1C, 0xB9A8, 0xBB20, 0xB9A9, 0xBB29, 0xB9AA, 0xBB2B, + 0xB9AB, 0xBB34, 0xB9AC, 0xBB35, 0xB9AD, 0xBB36, 0xB9AE, 0xBB38, 0xB9AF, 0xBB3B, 0xB9B0, 0xBB3C, 0xB9B1, 0xBB3D, 0xB9B2, 0xBB3E, + 0xB9B3, 0xBB44, 0xB9B4, 0xBB45, 0xB9B5, 0xBB47, 0xB9B6, 0xBB49, 0xB9B7, 0xBB4D, 0xB9B8, 0xBB4F, 0xB9B9, 0xBB50, 0xB9BA, 0xBB54, + 0xB9BB, 0xBB58, 0xB9BC, 0xBB61, 0xB9BD, 0xBB63, 0xB9BE, 0xBB6C, 0xB9BF, 0xBB88, 0xB9C0, 0xBB8C, 0xB9C1, 0xBB90, 0xB9C2, 0xBBA4, + 0xB9C3, 0xBBA8, 0xB9C4, 0xBBAC, 0xB9C5, 0xBBB4, 0xB9C6, 0xBBB7, 0xB9C7, 0xBBC0, 0xB9C8, 0xBBC4, 0xB9C9, 0xBBC8, 0xB9CA, 0xBBD0, + 0xB9CB, 0xBBD3, 0xB9CC, 0xBBF8, 0xB9CD, 0xBBF9, 0xB9CE, 0xBBFC, 0xB9CF, 0xBBFF, 0xB9D0, 0xBC00, 0xB9D1, 0xBC02, 0xB9D2, 0xBC08, + 0xB9D3, 0xBC09, 0xB9D4, 0xBC0B, 0xB9D5, 0xBC0C, 0xB9D6, 0xBC0D, 0xB9D7, 0xBC0F, 0xB9D8, 0xBC11, 0xB9D9, 0xBC14, 0xB9DA, 0xBC15, + 0xB9DB, 0xBC16, 0xB9DC, 0xBC17, 0xB9DD, 0xBC18, 0xB9DE, 0xBC1B, 0xB9DF, 0xBC1C, 0xB9E0, 0xBC1D, 0xB9E1, 0xBC1E, 0xB9E2, 0xBC1F, + 0xB9E3, 0xBC24, 0xB9E4, 0xBC25, 0xB9E5, 0xBC27, 0xB9E6, 0xBC29, 0xB9E7, 0xBC2D, 0xB9E8, 0xBC30, 0xB9E9, 0xBC31, 0xB9EA, 0xBC34, + 0xB9EB, 0xBC38, 0xB9EC, 0xBC40, 0xB9ED, 0xBC41, 0xB9EE, 0xBC43, 0xB9EF, 0xBC44, 0xB9F0, 0xBC45, 0xB9F1, 0xBC49, 0xB9F2, 0xBC4C, + 0xB9F3, 0xBC4D, 0xB9F4, 0xBC50, 0xB9F5, 0xBC5D, 0xB9F6, 0xBC84, 0xB9F7, 0xBC85, 0xB9F8, 0xBC88, 0xB9F9, 0xBC8B, 0xB9FA, 0xBC8C, + 0xB9FB, 0xBC8E, 0xB9FC, 0xBC94, 0xB9FD, 0xBC95, 0xB9FE, 0xBC97, 0xBA41, 0xD28D, 0xBA42, 0xD28E, 0xBA43, 0xD28F, 0xBA44, 0xD292, + 0xBA45, 0xD293, 0xBA46, 0xD294, 0xBA47, 0xD296, 0xBA48, 0xD297, 0xBA49, 0xD298, 0xBA4A, 0xD299, 0xBA4B, 0xD29A, 0xBA4C, 0xD29B, + 0xBA4D, 0xD29D, 0xBA4E, 0xD29E, 0xBA4F, 0xD29F, 0xBA50, 0xD2A1, 0xBA51, 0xD2A2, 0xBA52, 0xD2A3, 0xBA53, 0xD2A5, 0xBA54, 0xD2A6, + 0xBA55, 0xD2A7, 0xBA56, 0xD2A8, 0xBA57, 0xD2A9, 0xBA58, 0xD2AA, 0xBA59, 0xD2AB, 0xBA5A, 0xD2AD, 0xBA61, 0xD2AE, 0xBA62, 0xD2AF, + 0xBA63, 0xD2B0, 0xBA64, 0xD2B2, 0xBA65, 0xD2B3, 0xBA66, 0xD2B4, 0xBA67, 0xD2B5, 0xBA68, 0xD2B6, 0xBA69, 0xD2B7, 0xBA6A, 0xD2BA, + 0xBA6B, 0xD2BB, 0xBA6C, 0xD2BD, 0xBA6D, 0xD2BE, 0xBA6E, 0xD2C1, 0xBA6F, 0xD2C3, 0xBA70, 0xD2C4, 0xBA71, 0xD2C5, 0xBA72, 0xD2C6, + 0xBA73, 0xD2C7, 0xBA74, 0xD2CA, 0xBA75, 0xD2CC, 0xBA76, 0xD2CD, 0xBA77, 0xD2CE, 0xBA78, 0xD2CF, 0xBA79, 0xD2D0, 0xBA7A, 0xD2D1, + 0xBA81, 0xD2D2, 0xBA82, 0xD2D3, 0xBA83, 0xD2D5, 0xBA84, 0xD2D6, 0xBA85, 0xD2D7, 0xBA86, 0xD2D9, 0xBA87, 0xD2DA, 0xBA88, 0xD2DB, + 0xBA89, 0xD2DD, 0xBA8A, 0xD2DE, 0xBA8B, 0xD2DF, 0xBA8C, 0xD2E0, 0xBA8D, 0xD2E1, 0xBA8E, 0xD2E2, 0xBA8F, 0xD2E3, 0xBA90, 0xD2E6, + 0xBA91, 0xD2E7, 0xBA92, 0xD2E8, 0xBA93, 0xD2E9, 0xBA94, 0xD2EA, 0xBA95, 0xD2EB, 0xBA96, 0xD2EC, 0xBA97, 0xD2ED, 0xBA98, 0xD2EE, + 0xBA99, 0xD2EF, 0xBA9A, 0xD2F2, 0xBA9B, 0xD2F3, 0xBA9C, 0xD2F5, 0xBA9D, 0xD2F6, 0xBA9E, 0xD2F7, 0xBA9F, 0xD2F9, 0xBAA0, 0xD2FA, + 0xBAA1, 0xBC99, 0xBAA2, 0xBC9A, 0xBAA3, 0xBCA0, 0xBAA4, 0xBCA1, 0xBAA5, 0xBCA4, 0xBAA6, 0xBCA7, 0xBAA7, 0xBCA8, 0xBAA8, 0xBCB0, + 0xBAA9, 0xBCB1, 0xBAAA, 0xBCB3, 0xBAAB, 0xBCB4, 0xBAAC, 0xBCB5, 0xBAAD, 0xBCBC, 0xBAAE, 0xBCBD, 0xBAAF, 0xBCC0, 0xBAB0, 0xBCC4, + 0xBAB1, 0xBCCD, 0xBAB2, 0xBCCF, 0xBAB3, 0xBCD0, 0xBAB4, 0xBCD1, 0xBAB5, 0xBCD5, 0xBAB6, 0xBCD8, 0xBAB7, 0xBCDC, 0xBAB8, 0xBCF4, + 0xBAB9, 0xBCF5, 0xBABA, 0xBCF6, 0xBABB, 0xBCF8, 0xBABC, 0xBCFC, 0xBABD, 0xBD04, 0xBABE, 0xBD05, 0xBABF, 0xBD07, 0xBAC0, 0xBD09, + 0xBAC1, 0xBD10, 0xBAC2, 0xBD14, 0xBAC3, 0xBD24, 0xBAC4, 0xBD2C, 0xBAC5, 0xBD40, 0xBAC6, 0xBD48, 0xBAC7, 0xBD49, 0xBAC8, 0xBD4C, + 0xBAC9, 0xBD50, 0xBACA, 0xBD58, 0xBACB, 0xBD59, 0xBACC, 0xBD64, 0xBACD, 0xBD68, 0xBACE, 0xBD80, 0xBACF, 0xBD81, 0xBAD0, 0xBD84, + 0xBAD1, 0xBD87, 0xBAD2, 0xBD88, 0xBAD3, 0xBD89, 0xBAD4, 0xBD8A, 0xBAD5, 0xBD90, 0xBAD6, 0xBD91, 0xBAD7, 0xBD93, 0xBAD8, 0xBD95, + 0xBAD9, 0xBD99, 0xBADA, 0xBD9A, 0xBADB, 0xBD9C, 0xBADC, 0xBDA4, 0xBADD, 0xBDB0, 0xBADE, 0xBDB8, 0xBADF, 0xBDD4, 0xBAE0, 0xBDD5, + 0xBAE1, 0xBDD8, 0xBAE2, 0xBDDC, 0xBAE3, 0xBDE9, 0xBAE4, 0xBDF0, 0xBAE5, 0xBDF4, 0xBAE6, 0xBDF8, 0xBAE7, 0xBE00, 0xBAE8, 0xBE03, + 0xBAE9, 0xBE05, 0xBAEA, 0xBE0C, 0xBAEB, 0xBE0D, 0xBAEC, 0xBE10, 0xBAED, 0xBE14, 0xBAEE, 0xBE1C, 0xBAEF, 0xBE1D, 0xBAF0, 0xBE1F, + 0xBAF1, 0xBE44, 0xBAF2, 0xBE45, 0xBAF3, 0xBE48, 0xBAF4, 0xBE4C, 0xBAF5, 0xBE4E, 0xBAF6, 0xBE54, 0xBAF7, 0xBE55, 0xBAF8, 0xBE57, + 0xBAF9, 0xBE59, 0xBAFA, 0xBE5A, 0xBAFB, 0xBE5B, 0xBAFC, 0xBE60, 0xBAFD, 0xBE61, 0xBAFE, 0xBE64, 0xBB41, 0xD2FB, 0xBB42, 0xD2FC, + 0xBB43, 0xD2FD, 0xBB44, 0xD2FE, 0xBB45, 0xD2FF, 0xBB46, 0xD302, 0xBB47, 0xD304, 0xBB48, 0xD306, 0xBB49, 0xD307, 0xBB4A, 0xD308, + 0xBB4B, 0xD309, 0xBB4C, 0xD30A, 0xBB4D, 0xD30B, 0xBB4E, 0xD30F, 0xBB4F, 0xD311, 0xBB50, 0xD312, 0xBB51, 0xD313, 0xBB52, 0xD315, + 0xBB53, 0xD317, 0xBB54, 0xD318, 0xBB55, 0xD319, 0xBB56, 0xD31A, 0xBB57, 0xD31B, 0xBB58, 0xD31E, 0xBB59, 0xD322, 0xBB5A, 0xD323, + 0xBB61, 0xD324, 0xBB62, 0xD326, 0xBB63, 0xD327, 0xBB64, 0xD32A, 0xBB65, 0xD32B, 0xBB66, 0xD32D, 0xBB67, 0xD32E, 0xBB68, 0xD32F, + 0xBB69, 0xD331, 0xBB6A, 0xD332, 0xBB6B, 0xD333, 0xBB6C, 0xD334, 0xBB6D, 0xD335, 0xBB6E, 0xD336, 0xBB6F, 0xD337, 0xBB70, 0xD33A, + 0xBB71, 0xD33E, 0xBB72, 0xD33F, 0xBB73, 0xD340, 0xBB74, 0xD341, 0xBB75, 0xD342, 0xBB76, 0xD343, 0xBB77, 0xD346, 0xBB78, 0xD347, + 0xBB79, 0xD348, 0xBB7A, 0xD349, 0xBB81, 0xD34A, 0xBB82, 0xD34B, 0xBB83, 0xD34C, 0xBB84, 0xD34D, 0xBB85, 0xD34E, 0xBB86, 0xD34F, + 0xBB87, 0xD350, 0xBB88, 0xD351, 0xBB89, 0xD352, 0xBB8A, 0xD353, 0xBB8B, 0xD354, 0xBB8C, 0xD355, 0xBB8D, 0xD356, 0xBB8E, 0xD357, + 0xBB8F, 0xD358, 0xBB90, 0xD359, 0xBB91, 0xD35A, 0xBB92, 0xD35B, 0xBB93, 0xD35C, 0xBB94, 0xD35D, 0xBB95, 0xD35E, 0xBB96, 0xD35F, + 0xBB97, 0xD360, 0xBB98, 0xD361, 0xBB99, 0xD362, 0xBB9A, 0xD363, 0xBB9B, 0xD364, 0xBB9C, 0xD365, 0xBB9D, 0xD366, 0xBB9E, 0xD367, + 0xBB9F, 0xD368, 0xBBA0, 0xD369, 0xBBA1, 0xBE68, 0xBBA2, 0xBE6A, 0xBBA3, 0xBE70, 0xBBA4, 0xBE71, 0xBBA5, 0xBE73, 0xBBA6, 0xBE74, + 0xBBA7, 0xBE75, 0xBBA8, 0xBE7B, 0xBBA9, 0xBE7C, 0xBBAA, 0xBE7D, 0xBBAB, 0xBE80, 0xBBAC, 0xBE84, 0xBBAD, 0xBE8C, 0xBBAE, 0xBE8D, + 0xBBAF, 0xBE8F, 0xBBB0, 0xBE90, 0xBBB1, 0xBE91, 0xBBB2, 0xBE98, 0xBBB3, 0xBE99, 0xBBB4, 0xBEA8, 0xBBB5, 0xBED0, 0xBBB6, 0xBED1, + 0xBBB7, 0xBED4, 0xBBB8, 0xBED7, 0xBBB9, 0xBED8, 0xBBBA, 0xBEE0, 0xBBBB, 0xBEE3, 0xBBBC, 0xBEE4, 0xBBBD, 0xBEE5, 0xBBBE, 0xBEEC, + 0xBBBF, 0xBF01, 0xBBC0, 0xBF08, 0xBBC1, 0xBF09, 0xBBC2, 0xBF18, 0xBBC3, 0xBF19, 0xBBC4, 0xBF1B, 0xBBC5, 0xBF1C, 0xBBC6, 0xBF1D, + 0xBBC7, 0xBF40, 0xBBC8, 0xBF41, 0xBBC9, 0xBF44, 0xBBCA, 0xBF48, 0xBBCB, 0xBF50, 0xBBCC, 0xBF51, 0xBBCD, 0xBF55, 0xBBCE, 0xBF94, + 0xBBCF, 0xBFB0, 0xBBD0, 0xBFC5, 0xBBD1, 0xBFCC, 0xBBD2, 0xBFCD, 0xBBD3, 0xBFD0, 0xBBD4, 0xBFD4, 0xBBD5, 0xBFDC, 0xBBD6, 0xBFDF, + 0xBBD7, 0xBFE1, 0xBBD8, 0xC03C, 0xBBD9, 0xC051, 0xBBDA, 0xC058, 0xBBDB, 0xC05C, 0xBBDC, 0xC060, 0xBBDD, 0xC068, 0xBBDE, 0xC069, + 0xBBDF, 0xC090, 0xBBE0, 0xC091, 0xBBE1, 0xC094, 0xBBE2, 0xC098, 0xBBE3, 0xC0A0, 0xBBE4, 0xC0A1, 0xBBE5, 0xC0A3, 0xBBE6, 0xC0A5, + 0xBBE7, 0xC0AC, 0xBBE8, 0xC0AD, 0xBBE9, 0xC0AF, 0xBBEA, 0xC0B0, 0xBBEB, 0xC0B3, 0xBBEC, 0xC0B4, 0xBBED, 0xC0B5, 0xBBEE, 0xC0B6, + 0xBBEF, 0xC0BC, 0xBBF0, 0xC0BD, 0xBBF1, 0xC0BF, 0xBBF2, 0xC0C0, 0xBBF3, 0xC0C1, 0xBBF4, 0xC0C5, 0xBBF5, 0xC0C8, 0xBBF6, 0xC0C9, + 0xBBF7, 0xC0CC, 0xBBF8, 0xC0D0, 0xBBF9, 0xC0D8, 0xBBFA, 0xC0D9, 0xBBFB, 0xC0DB, 0xBBFC, 0xC0DC, 0xBBFD, 0xC0DD, 0xBBFE, 0xC0E4, + 0xBC41, 0xD36A, 0xBC42, 0xD36B, 0xBC43, 0xD36C, 0xBC44, 0xD36D, 0xBC45, 0xD36E, 0xBC46, 0xD36F, 0xBC47, 0xD370, 0xBC48, 0xD371, + 0xBC49, 0xD372, 0xBC4A, 0xD373, 0xBC4B, 0xD374, 0xBC4C, 0xD375, 0xBC4D, 0xD376, 0xBC4E, 0xD377, 0xBC4F, 0xD378, 0xBC50, 0xD379, + 0xBC51, 0xD37A, 0xBC52, 0xD37B, 0xBC53, 0xD37E, 0xBC54, 0xD37F, 0xBC55, 0xD381, 0xBC56, 0xD382, 0xBC57, 0xD383, 0xBC58, 0xD385, + 0xBC59, 0xD386, 0xBC5A, 0xD387, 0xBC61, 0xD388, 0xBC62, 0xD389, 0xBC63, 0xD38A, 0xBC64, 0xD38B, 0xBC65, 0xD38E, 0xBC66, 0xD392, + 0xBC67, 0xD393, 0xBC68, 0xD394, 0xBC69, 0xD395, 0xBC6A, 0xD396, 0xBC6B, 0xD397, 0xBC6C, 0xD39A, 0xBC6D, 0xD39B, 0xBC6E, 0xD39D, + 0xBC6F, 0xD39E, 0xBC70, 0xD39F, 0xBC71, 0xD3A1, 0xBC72, 0xD3A2, 0xBC73, 0xD3A3, 0xBC74, 0xD3A4, 0xBC75, 0xD3A5, 0xBC76, 0xD3A6, + 0xBC77, 0xD3A7, 0xBC78, 0xD3AA, 0xBC79, 0xD3AC, 0xBC7A, 0xD3AE, 0xBC81, 0xD3AF, 0xBC82, 0xD3B0, 0xBC83, 0xD3B1, 0xBC84, 0xD3B2, + 0xBC85, 0xD3B3, 0xBC86, 0xD3B5, 0xBC87, 0xD3B6, 0xBC88, 0xD3B7, 0xBC89, 0xD3B9, 0xBC8A, 0xD3BA, 0xBC8B, 0xD3BB, 0xBC8C, 0xD3BD, + 0xBC8D, 0xD3BE, 0xBC8E, 0xD3BF, 0xBC8F, 0xD3C0, 0xBC90, 0xD3C1, 0xBC91, 0xD3C2, 0xBC92, 0xD3C3, 0xBC93, 0xD3C6, 0xBC94, 0xD3C7, + 0xBC95, 0xD3CA, 0xBC96, 0xD3CB, 0xBC97, 0xD3CC, 0xBC98, 0xD3CD, 0xBC99, 0xD3CE, 0xBC9A, 0xD3CF, 0xBC9B, 0xD3D1, 0xBC9C, 0xD3D2, + 0xBC9D, 0xD3D3, 0xBC9E, 0xD3D4, 0xBC9F, 0xD3D5, 0xBCA0, 0xD3D6, 0xBCA1, 0xC0E5, 0xBCA2, 0xC0E8, 0xBCA3, 0xC0EC, 0xBCA4, 0xC0F4, + 0xBCA5, 0xC0F5, 0xBCA6, 0xC0F7, 0xBCA7, 0xC0F9, 0xBCA8, 0xC100, 0xBCA9, 0xC104, 0xBCAA, 0xC108, 0xBCAB, 0xC110, 0xBCAC, 0xC115, + 0xBCAD, 0xC11C, 0xBCAE, 0xC11D, 0xBCAF, 0xC11E, 0xBCB0, 0xC11F, 0xBCB1, 0xC120, 0xBCB2, 0xC123, 0xBCB3, 0xC124, 0xBCB4, 0xC126, + 0xBCB5, 0xC127, 0xBCB6, 0xC12C, 0xBCB7, 0xC12D, 0xBCB8, 0xC12F, 0xBCB9, 0xC130, 0xBCBA, 0xC131, 0xBCBB, 0xC136, 0xBCBC, 0xC138, + 0xBCBD, 0xC139, 0xBCBE, 0xC13C, 0xBCBF, 0xC140, 0xBCC0, 0xC148, 0xBCC1, 0xC149, 0xBCC2, 0xC14B, 0xBCC3, 0xC14C, 0xBCC4, 0xC14D, + 0xBCC5, 0xC154, 0xBCC6, 0xC155, 0xBCC7, 0xC158, 0xBCC8, 0xC15C, 0xBCC9, 0xC164, 0xBCCA, 0xC165, 0xBCCB, 0xC167, 0xBCCC, 0xC168, + 0xBCCD, 0xC169, 0xBCCE, 0xC170, 0xBCCF, 0xC174, 0xBCD0, 0xC178, 0xBCD1, 0xC185, 0xBCD2, 0xC18C, 0xBCD3, 0xC18D, 0xBCD4, 0xC18E, + 0xBCD5, 0xC190, 0xBCD6, 0xC194, 0xBCD7, 0xC196, 0xBCD8, 0xC19C, 0xBCD9, 0xC19D, 0xBCDA, 0xC19F, 0xBCDB, 0xC1A1, 0xBCDC, 0xC1A5, + 0xBCDD, 0xC1A8, 0xBCDE, 0xC1A9, 0xBCDF, 0xC1AC, 0xBCE0, 0xC1B0, 0xBCE1, 0xC1BD, 0xBCE2, 0xC1C4, 0xBCE3, 0xC1C8, 0xBCE4, 0xC1CC, + 0xBCE5, 0xC1D4, 0xBCE6, 0xC1D7, 0xBCE7, 0xC1D8, 0xBCE8, 0xC1E0, 0xBCE9, 0xC1E4, 0xBCEA, 0xC1E8, 0xBCEB, 0xC1F0, 0xBCEC, 0xC1F1, + 0xBCED, 0xC1F3, 0xBCEE, 0xC1FC, 0xBCEF, 0xC1FD, 0xBCF0, 0xC200, 0xBCF1, 0xC204, 0xBCF2, 0xC20C, 0xBCF3, 0xC20D, 0xBCF4, 0xC20F, + 0xBCF5, 0xC211, 0xBCF6, 0xC218, 0xBCF7, 0xC219, 0xBCF8, 0xC21C, 0xBCF9, 0xC21F, 0xBCFA, 0xC220, 0xBCFB, 0xC228, 0xBCFC, 0xC229, + 0xBCFD, 0xC22B, 0xBCFE, 0xC22D, 0xBD41, 0xD3D7, 0xBD42, 0xD3D9, 0xBD43, 0xD3DA, 0xBD44, 0xD3DB, 0xBD45, 0xD3DC, 0xBD46, 0xD3DD, + 0xBD47, 0xD3DE, 0xBD48, 0xD3DF, 0xBD49, 0xD3E0, 0xBD4A, 0xD3E2, 0xBD4B, 0xD3E4, 0xBD4C, 0xD3E5, 0xBD4D, 0xD3E6, 0xBD4E, 0xD3E7, + 0xBD4F, 0xD3E8, 0xBD50, 0xD3E9, 0xBD51, 0xD3EA, 0xBD52, 0xD3EB, 0xBD53, 0xD3EE, 0xBD54, 0xD3EF, 0xBD55, 0xD3F1, 0xBD56, 0xD3F2, + 0xBD57, 0xD3F3, 0xBD58, 0xD3F5, 0xBD59, 0xD3F6, 0xBD5A, 0xD3F7, 0xBD61, 0xD3F8, 0xBD62, 0xD3F9, 0xBD63, 0xD3FA, 0xBD64, 0xD3FB, + 0xBD65, 0xD3FE, 0xBD66, 0xD400, 0xBD67, 0xD402, 0xBD68, 0xD403, 0xBD69, 0xD404, 0xBD6A, 0xD405, 0xBD6B, 0xD406, 0xBD6C, 0xD407, + 0xBD6D, 0xD409, 0xBD6E, 0xD40A, 0xBD6F, 0xD40B, 0xBD70, 0xD40C, 0xBD71, 0xD40D, 0xBD72, 0xD40E, 0xBD73, 0xD40F, 0xBD74, 0xD410, + 0xBD75, 0xD411, 0xBD76, 0xD412, 0xBD77, 0xD413, 0xBD78, 0xD414, 0xBD79, 0xD415, 0xBD7A, 0xD416, 0xBD81, 0xD417, 0xBD82, 0xD418, + 0xBD83, 0xD419, 0xBD84, 0xD41A, 0xBD85, 0xD41B, 0xBD86, 0xD41C, 0xBD87, 0xD41E, 0xBD88, 0xD41F, 0xBD89, 0xD420, 0xBD8A, 0xD421, + 0xBD8B, 0xD422, 0xBD8C, 0xD423, 0xBD8D, 0xD424, 0xBD8E, 0xD425, 0xBD8F, 0xD426, 0xBD90, 0xD427, 0xBD91, 0xD428, 0xBD92, 0xD429, + 0xBD93, 0xD42A, 0xBD94, 0xD42B, 0xBD95, 0xD42C, 0xBD96, 0xD42D, 0xBD97, 0xD42E, 0xBD98, 0xD42F, 0xBD99, 0xD430, 0xBD9A, 0xD431, + 0xBD9B, 0xD432, 0xBD9C, 0xD433, 0xBD9D, 0xD434, 0xBD9E, 0xD435, 0xBD9F, 0xD436, 0xBDA0, 0xD437, 0xBDA1, 0xC22F, 0xBDA2, 0xC231, + 0xBDA3, 0xC232, 0xBDA4, 0xC234, 0xBDA5, 0xC248, 0xBDA6, 0xC250, 0xBDA7, 0xC251, 0xBDA8, 0xC254, 0xBDA9, 0xC258, 0xBDAA, 0xC260, + 0xBDAB, 0xC265, 0xBDAC, 0xC26C, 0xBDAD, 0xC26D, 0xBDAE, 0xC270, 0xBDAF, 0xC274, 0xBDB0, 0xC27C, 0xBDB1, 0xC27D, 0xBDB2, 0xC27F, + 0xBDB3, 0xC281, 0xBDB4, 0xC288, 0xBDB5, 0xC289, 0xBDB6, 0xC290, 0xBDB7, 0xC298, 0xBDB8, 0xC29B, 0xBDB9, 0xC29D, 0xBDBA, 0xC2A4, + 0xBDBB, 0xC2A5, 0xBDBC, 0xC2A8, 0xBDBD, 0xC2AC, 0xBDBE, 0xC2AD, 0xBDBF, 0xC2B4, 0xBDC0, 0xC2B5, 0xBDC1, 0xC2B7, 0xBDC2, 0xC2B9, + 0xBDC3, 0xC2DC, 0xBDC4, 0xC2DD, 0xBDC5, 0xC2E0, 0xBDC6, 0xC2E3, 0xBDC7, 0xC2E4, 0xBDC8, 0xC2EB, 0xBDC9, 0xC2EC, 0xBDCA, 0xC2ED, + 0xBDCB, 0xC2EF, 0xBDCC, 0xC2F1, 0xBDCD, 0xC2F6, 0xBDCE, 0xC2F8, 0xBDCF, 0xC2F9, 0xBDD0, 0xC2FB, 0xBDD1, 0xC2FC, 0xBDD2, 0xC300, + 0xBDD3, 0xC308, 0xBDD4, 0xC309, 0xBDD5, 0xC30C, 0xBDD6, 0xC30D, 0xBDD7, 0xC313, 0xBDD8, 0xC314, 0xBDD9, 0xC315, 0xBDDA, 0xC318, + 0xBDDB, 0xC31C, 0xBDDC, 0xC324, 0xBDDD, 0xC325, 0xBDDE, 0xC328, 0xBDDF, 0xC329, 0xBDE0, 0xC345, 0xBDE1, 0xC368, 0xBDE2, 0xC369, + 0xBDE3, 0xC36C, 0xBDE4, 0xC370, 0xBDE5, 0xC372, 0xBDE6, 0xC378, 0xBDE7, 0xC379, 0xBDE8, 0xC37C, 0xBDE9, 0xC37D, 0xBDEA, 0xC384, + 0xBDEB, 0xC388, 0xBDEC, 0xC38C, 0xBDED, 0xC3C0, 0xBDEE, 0xC3D8, 0xBDEF, 0xC3D9, 0xBDF0, 0xC3DC, 0xBDF1, 0xC3DF, 0xBDF2, 0xC3E0, + 0xBDF3, 0xC3E2, 0xBDF4, 0xC3E8, 0xBDF5, 0xC3E9, 0xBDF6, 0xC3ED, 0xBDF7, 0xC3F4, 0xBDF8, 0xC3F5, 0xBDF9, 0xC3F8, 0xBDFA, 0xC408, + 0xBDFB, 0xC410, 0xBDFC, 0xC424, 0xBDFD, 0xC42C, 0xBDFE, 0xC430, 0xBE41, 0xD438, 0xBE42, 0xD439, 0xBE43, 0xD43A, 0xBE44, 0xD43B, + 0xBE45, 0xD43C, 0xBE46, 0xD43D, 0xBE47, 0xD43E, 0xBE48, 0xD43F, 0xBE49, 0xD441, 0xBE4A, 0xD442, 0xBE4B, 0xD443, 0xBE4C, 0xD445, + 0xBE4D, 0xD446, 0xBE4E, 0xD447, 0xBE4F, 0xD448, 0xBE50, 0xD449, 0xBE51, 0xD44A, 0xBE52, 0xD44B, 0xBE53, 0xD44C, 0xBE54, 0xD44D, + 0xBE55, 0xD44E, 0xBE56, 0xD44F, 0xBE57, 0xD450, 0xBE58, 0xD451, 0xBE59, 0xD452, 0xBE5A, 0xD453, 0xBE61, 0xD454, 0xBE62, 0xD455, + 0xBE63, 0xD456, 0xBE64, 0xD457, 0xBE65, 0xD458, 0xBE66, 0xD459, 0xBE67, 0xD45A, 0xBE68, 0xD45B, 0xBE69, 0xD45D, 0xBE6A, 0xD45E, + 0xBE6B, 0xD45F, 0xBE6C, 0xD461, 0xBE6D, 0xD462, 0xBE6E, 0xD463, 0xBE6F, 0xD465, 0xBE70, 0xD466, 0xBE71, 0xD467, 0xBE72, 0xD468, + 0xBE73, 0xD469, 0xBE74, 0xD46A, 0xBE75, 0xD46B, 0xBE76, 0xD46C, 0xBE77, 0xD46E, 0xBE78, 0xD470, 0xBE79, 0xD471, 0xBE7A, 0xD472, + 0xBE81, 0xD473, 0xBE82, 0xD474, 0xBE83, 0xD475, 0xBE84, 0xD476, 0xBE85, 0xD477, 0xBE86, 0xD47A, 0xBE87, 0xD47B, 0xBE88, 0xD47D, + 0xBE89, 0xD47E, 0xBE8A, 0xD481, 0xBE8B, 0xD483, 0xBE8C, 0xD484, 0xBE8D, 0xD485, 0xBE8E, 0xD486, 0xBE8F, 0xD487, 0xBE90, 0xD48A, + 0xBE91, 0xD48C, 0xBE92, 0xD48E, 0xBE93, 0xD48F, 0xBE94, 0xD490, 0xBE95, 0xD491, 0xBE96, 0xD492, 0xBE97, 0xD493, 0xBE98, 0xD495, + 0xBE99, 0xD496, 0xBE9A, 0xD497, 0xBE9B, 0xD498, 0xBE9C, 0xD499, 0xBE9D, 0xD49A, 0xBE9E, 0xD49B, 0xBE9F, 0xD49C, 0xBEA0, 0xD49D, + 0xBEA1, 0xC434, 0xBEA2, 0xC43C, 0xBEA3, 0xC43D, 0xBEA4, 0xC448, 0xBEA5, 0xC464, 0xBEA6, 0xC465, 0xBEA7, 0xC468, 0xBEA8, 0xC46C, + 0xBEA9, 0xC474, 0xBEAA, 0xC475, 0xBEAB, 0xC479, 0xBEAC, 0xC480, 0xBEAD, 0xC494, 0xBEAE, 0xC49C, 0xBEAF, 0xC4B8, 0xBEB0, 0xC4BC, + 0xBEB1, 0xC4E9, 0xBEB2, 0xC4F0, 0xBEB3, 0xC4F1, 0xBEB4, 0xC4F4, 0xBEB5, 0xC4F8, 0xBEB6, 0xC4FA, 0xBEB7, 0xC4FF, 0xBEB8, 0xC500, + 0xBEB9, 0xC501, 0xBEBA, 0xC50C, 0xBEBB, 0xC510, 0xBEBC, 0xC514, 0xBEBD, 0xC51C, 0xBEBE, 0xC528, 0xBEBF, 0xC529, 0xBEC0, 0xC52C, + 0xBEC1, 0xC530, 0xBEC2, 0xC538, 0xBEC3, 0xC539, 0xBEC4, 0xC53B, 0xBEC5, 0xC53D, 0xBEC6, 0xC544, 0xBEC7, 0xC545, 0xBEC8, 0xC548, + 0xBEC9, 0xC549, 0xBECA, 0xC54A, 0xBECB, 0xC54C, 0xBECC, 0xC54D, 0xBECD, 0xC54E, 0xBECE, 0xC553, 0xBECF, 0xC554, 0xBED0, 0xC555, + 0xBED1, 0xC557, 0xBED2, 0xC558, 0xBED3, 0xC559, 0xBED4, 0xC55D, 0xBED5, 0xC55E, 0xBED6, 0xC560, 0xBED7, 0xC561, 0xBED8, 0xC564, + 0xBED9, 0xC568, 0xBEDA, 0xC570, 0xBEDB, 0xC571, 0xBEDC, 0xC573, 0xBEDD, 0xC574, 0xBEDE, 0xC575, 0xBEDF, 0xC57C, 0xBEE0, 0xC57D, + 0xBEE1, 0xC580, 0xBEE2, 0xC584, 0xBEE3, 0xC587, 0xBEE4, 0xC58C, 0xBEE5, 0xC58D, 0xBEE6, 0xC58F, 0xBEE7, 0xC591, 0xBEE8, 0xC595, + 0xBEE9, 0xC597, 0xBEEA, 0xC598, 0xBEEB, 0xC59C, 0xBEEC, 0xC5A0, 0xBEED, 0xC5A9, 0xBEEE, 0xC5B4, 0xBEEF, 0xC5B5, 0xBEF0, 0xC5B8, + 0xBEF1, 0xC5B9, 0xBEF2, 0xC5BB, 0xBEF3, 0xC5BC, 0xBEF4, 0xC5BD, 0xBEF5, 0xC5BE, 0xBEF6, 0xC5C4, 0xBEF7, 0xC5C5, 0xBEF8, 0xC5C6, + 0xBEF9, 0xC5C7, 0xBEFA, 0xC5C8, 0xBEFB, 0xC5C9, 0xBEFC, 0xC5CA, 0xBEFD, 0xC5CC, 0xBEFE, 0xC5CE, 0xBF41, 0xD49E, 0xBF42, 0xD49F, + 0xBF43, 0xD4A0, 0xBF44, 0xD4A1, 0xBF45, 0xD4A2, 0xBF46, 0xD4A3, 0xBF47, 0xD4A4, 0xBF48, 0xD4A5, 0xBF49, 0xD4A6, 0xBF4A, 0xD4A7, + 0xBF4B, 0xD4A8, 0xBF4C, 0xD4AA, 0xBF4D, 0xD4AB, 0xBF4E, 0xD4AC, 0xBF4F, 0xD4AD, 0xBF50, 0xD4AE, 0xBF51, 0xD4AF, 0xBF52, 0xD4B0, + 0xBF53, 0xD4B1, 0xBF54, 0xD4B2, 0xBF55, 0xD4B3, 0xBF56, 0xD4B4, 0xBF57, 0xD4B5, 0xBF58, 0xD4B6, 0xBF59, 0xD4B7, 0xBF5A, 0xD4B8, + 0xBF61, 0xD4B9, 0xBF62, 0xD4BA, 0xBF63, 0xD4BB, 0xBF64, 0xD4BC, 0xBF65, 0xD4BD, 0xBF66, 0xD4BE, 0xBF67, 0xD4BF, 0xBF68, 0xD4C0, + 0xBF69, 0xD4C1, 0xBF6A, 0xD4C2, 0xBF6B, 0xD4C3, 0xBF6C, 0xD4C4, 0xBF6D, 0xD4C5, 0xBF6E, 0xD4C6, 0xBF6F, 0xD4C7, 0xBF70, 0xD4C8, + 0xBF71, 0xD4C9, 0xBF72, 0xD4CA, 0xBF73, 0xD4CB, 0xBF74, 0xD4CD, 0xBF75, 0xD4CE, 0xBF76, 0xD4CF, 0xBF77, 0xD4D1, 0xBF78, 0xD4D2, + 0xBF79, 0xD4D3, 0xBF7A, 0xD4D5, 0xBF81, 0xD4D6, 0xBF82, 0xD4D7, 0xBF83, 0xD4D8, 0xBF84, 0xD4D9, 0xBF85, 0xD4DA, 0xBF86, 0xD4DB, + 0xBF87, 0xD4DD, 0xBF88, 0xD4DE, 0xBF89, 0xD4E0, 0xBF8A, 0xD4E1, 0xBF8B, 0xD4E2, 0xBF8C, 0xD4E3, 0xBF8D, 0xD4E4, 0xBF8E, 0xD4E5, + 0xBF8F, 0xD4E6, 0xBF90, 0xD4E7, 0xBF91, 0xD4E9, 0xBF92, 0xD4EA, 0xBF93, 0xD4EB, 0xBF94, 0xD4ED, 0xBF95, 0xD4EE, 0xBF96, 0xD4EF, + 0xBF97, 0xD4F1, 0xBF98, 0xD4F2, 0xBF99, 0xD4F3, 0xBF9A, 0xD4F4, 0xBF9B, 0xD4F5, 0xBF9C, 0xD4F6, 0xBF9D, 0xD4F7, 0xBF9E, 0xD4F9, + 0xBF9F, 0xD4FA, 0xBFA0, 0xD4FC, 0xBFA1, 0xC5D0, 0xBFA2, 0xC5D1, 0xBFA3, 0xC5D4, 0xBFA4, 0xC5D8, 0xBFA5, 0xC5E0, 0xBFA6, 0xC5E1, + 0xBFA7, 0xC5E3, 0xBFA8, 0xC5E5, 0xBFA9, 0xC5EC, 0xBFAA, 0xC5ED, 0xBFAB, 0xC5EE, 0xBFAC, 0xC5F0, 0xBFAD, 0xC5F4, 0xBFAE, 0xC5F6, + 0xBFAF, 0xC5F7, 0xBFB0, 0xC5FC, 0xBFB1, 0xC5FD, 0xBFB2, 0xC5FE, 0xBFB3, 0xC5FF, 0xBFB4, 0xC600, 0xBFB5, 0xC601, 0xBFB6, 0xC605, + 0xBFB7, 0xC606, 0xBFB8, 0xC607, 0xBFB9, 0xC608, 0xBFBA, 0xC60C, 0xBFBB, 0xC610, 0xBFBC, 0xC618, 0xBFBD, 0xC619, 0xBFBE, 0xC61B, + 0xBFBF, 0xC61C, 0xBFC0, 0xC624, 0xBFC1, 0xC625, 0xBFC2, 0xC628, 0xBFC3, 0xC62C, 0xBFC4, 0xC62D, 0xBFC5, 0xC62E, 0xBFC6, 0xC630, + 0xBFC7, 0xC633, 0xBFC8, 0xC634, 0xBFC9, 0xC635, 0xBFCA, 0xC637, 0xBFCB, 0xC639, 0xBFCC, 0xC63B, 0xBFCD, 0xC640, 0xBFCE, 0xC641, + 0xBFCF, 0xC644, 0xBFD0, 0xC648, 0xBFD1, 0xC650, 0xBFD2, 0xC651, 0xBFD3, 0xC653, 0xBFD4, 0xC654, 0xBFD5, 0xC655, 0xBFD6, 0xC65C, + 0xBFD7, 0xC65D, 0xBFD8, 0xC660, 0xBFD9, 0xC66C, 0xBFDA, 0xC66F, 0xBFDB, 0xC671, 0xBFDC, 0xC678, 0xBFDD, 0xC679, 0xBFDE, 0xC67C, + 0xBFDF, 0xC680, 0xBFE0, 0xC688, 0xBFE1, 0xC689, 0xBFE2, 0xC68B, 0xBFE3, 0xC68D, 0xBFE4, 0xC694, 0xBFE5, 0xC695, 0xBFE6, 0xC698, + 0xBFE7, 0xC69C, 0xBFE8, 0xC6A4, 0xBFE9, 0xC6A5, 0xBFEA, 0xC6A7, 0xBFEB, 0xC6A9, 0xBFEC, 0xC6B0, 0xBFED, 0xC6B1, 0xBFEE, 0xC6B4, + 0xBFEF, 0xC6B8, 0xBFF0, 0xC6B9, 0xBFF1, 0xC6BA, 0xBFF2, 0xC6C0, 0xBFF3, 0xC6C1, 0xBFF4, 0xC6C3, 0xBFF5, 0xC6C5, 0xBFF6, 0xC6CC, + 0xBFF7, 0xC6CD, 0xBFF8, 0xC6D0, 0xBFF9, 0xC6D4, 0xBFFA, 0xC6DC, 0xBFFB, 0xC6DD, 0xBFFC, 0xC6E0, 0xBFFD, 0xC6E1, 0xBFFE, 0xC6E8, + 0xC041, 0xD4FE, 0xC042, 0xD4FF, 0xC043, 0xD500, 0xC044, 0xD501, 0xC045, 0xD502, 0xC046, 0xD503, 0xC047, 0xD505, 0xC048, 0xD506, + 0xC049, 0xD507, 0xC04A, 0xD509, 0xC04B, 0xD50A, 0xC04C, 0xD50B, 0xC04D, 0xD50D, 0xC04E, 0xD50E, 0xC04F, 0xD50F, 0xC050, 0xD510, + 0xC051, 0xD511, 0xC052, 0xD512, 0xC053, 0xD513, 0xC054, 0xD516, 0xC055, 0xD518, 0xC056, 0xD519, 0xC057, 0xD51A, 0xC058, 0xD51B, + 0xC059, 0xD51C, 0xC05A, 0xD51D, 0xC061, 0xD51E, 0xC062, 0xD51F, 0xC063, 0xD520, 0xC064, 0xD521, 0xC065, 0xD522, 0xC066, 0xD523, + 0xC067, 0xD524, 0xC068, 0xD525, 0xC069, 0xD526, 0xC06A, 0xD527, 0xC06B, 0xD528, 0xC06C, 0xD529, 0xC06D, 0xD52A, 0xC06E, 0xD52B, + 0xC06F, 0xD52C, 0xC070, 0xD52D, 0xC071, 0xD52E, 0xC072, 0xD52F, 0xC073, 0xD530, 0xC074, 0xD531, 0xC075, 0xD532, 0xC076, 0xD533, + 0xC077, 0xD534, 0xC078, 0xD535, 0xC079, 0xD536, 0xC07A, 0xD537, 0xC081, 0xD538, 0xC082, 0xD539, 0xC083, 0xD53A, 0xC084, 0xD53B, + 0xC085, 0xD53E, 0xC086, 0xD53F, 0xC087, 0xD541, 0xC088, 0xD542, 0xC089, 0xD543, 0xC08A, 0xD545, 0xC08B, 0xD546, 0xC08C, 0xD547, + 0xC08D, 0xD548, 0xC08E, 0xD549, 0xC08F, 0xD54A, 0xC090, 0xD54B, 0xC091, 0xD54E, 0xC092, 0xD550, 0xC093, 0xD552, 0xC094, 0xD553, + 0xC095, 0xD554, 0xC096, 0xD555, 0xC097, 0xD556, 0xC098, 0xD557, 0xC099, 0xD55A, 0xC09A, 0xD55B, 0xC09B, 0xD55D, 0xC09C, 0xD55E, + 0xC09D, 0xD55F, 0xC09E, 0xD561, 0xC09F, 0xD562, 0xC0A0, 0xD563, 0xC0A1, 0xC6E9, 0xC0A2, 0xC6EC, 0xC0A3, 0xC6F0, 0xC0A4, 0xC6F8, + 0xC0A5, 0xC6F9, 0xC0A6, 0xC6FD, 0xC0A7, 0xC704, 0xC0A8, 0xC705, 0xC0A9, 0xC708, 0xC0AA, 0xC70C, 0xC0AB, 0xC714, 0xC0AC, 0xC715, + 0xC0AD, 0xC717, 0xC0AE, 0xC719, 0xC0AF, 0xC720, 0xC0B0, 0xC721, 0xC0B1, 0xC724, 0xC0B2, 0xC728, 0xC0B3, 0xC730, 0xC0B4, 0xC731, + 0xC0B5, 0xC733, 0xC0B6, 0xC735, 0xC0B7, 0xC737, 0xC0B8, 0xC73C, 0xC0B9, 0xC73D, 0xC0BA, 0xC740, 0xC0BB, 0xC744, 0xC0BC, 0xC74A, + 0xC0BD, 0xC74C, 0xC0BE, 0xC74D, 0xC0BF, 0xC74F, 0xC0C0, 0xC751, 0xC0C1, 0xC752, 0xC0C2, 0xC753, 0xC0C3, 0xC754, 0xC0C4, 0xC755, + 0xC0C5, 0xC756, 0xC0C6, 0xC757, 0xC0C7, 0xC758, 0xC0C8, 0xC75C, 0xC0C9, 0xC760, 0xC0CA, 0xC768, 0xC0CB, 0xC76B, 0xC0CC, 0xC774, + 0xC0CD, 0xC775, 0xC0CE, 0xC778, 0xC0CF, 0xC77C, 0xC0D0, 0xC77D, 0xC0D1, 0xC77E, 0xC0D2, 0xC783, 0xC0D3, 0xC784, 0xC0D4, 0xC785, + 0xC0D5, 0xC787, 0xC0D6, 0xC788, 0xC0D7, 0xC789, 0xC0D8, 0xC78A, 0xC0D9, 0xC78E, 0xC0DA, 0xC790, 0xC0DB, 0xC791, 0xC0DC, 0xC794, + 0xC0DD, 0xC796, 0xC0DE, 0xC797, 0xC0DF, 0xC798, 0xC0E0, 0xC79A, 0xC0E1, 0xC7A0, 0xC0E2, 0xC7A1, 0xC0E3, 0xC7A3, 0xC0E4, 0xC7A4, + 0xC0E5, 0xC7A5, 0xC0E6, 0xC7A6, 0xC0E7, 0xC7AC, 0xC0E8, 0xC7AD, 0xC0E9, 0xC7B0, 0xC0EA, 0xC7B4, 0xC0EB, 0xC7BC, 0xC0EC, 0xC7BD, + 0xC0ED, 0xC7BF, 0xC0EE, 0xC7C0, 0xC0EF, 0xC7C1, 0xC0F0, 0xC7C8, 0xC0F1, 0xC7C9, 0xC0F2, 0xC7CC, 0xC0F3, 0xC7CE, 0xC0F4, 0xC7D0, + 0xC0F5, 0xC7D8, 0xC0F6, 0xC7DD, 0xC0F7, 0xC7E4, 0xC0F8, 0xC7E8, 0xC0F9, 0xC7EC, 0xC0FA, 0xC800, 0xC0FB, 0xC801, 0xC0FC, 0xC804, + 0xC0FD, 0xC808, 0xC0FE, 0xC80A, 0xC141, 0xD564, 0xC142, 0xD566, 0xC143, 0xD567, 0xC144, 0xD56A, 0xC145, 0xD56C, 0xC146, 0xD56E, + 0xC147, 0xD56F, 0xC148, 0xD570, 0xC149, 0xD571, 0xC14A, 0xD572, 0xC14B, 0xD573, 0xC14C, 0xD576, 0xC14D, 0xD577, 0xC14E, 0xD579, + 0xC14F, 0xD57A, 0xC150, 0xD57B, 0xC151, 0xD57D, 0xC152, 0xD57E, 0xC153, 0xD57F, 0xC154, 0xD580, 0xC155, 0xD581, 0xC156, 0xD582, + 0xC157, 0xD583, 0xC158, 0xD586, 0xC159, 0xD58A, 0xC15A, 0xD58B, 0xC161, 0xD58C, 0xC162, 0xD58D, 0xC163, 0xD58E, 0xC164, 0xD58F, + 0xC165, 0xD591, 0xC166, 0xD592, 0xC167, 0xD593, 0xC168, 0xD594, 0xC169, 0xD595, 0xC16A, 0xD596, 0xC16B, 0xD597, 0xC16C, 0xD598, + 0xC16D, 0xD599, 0xC16E, 0xD59A, 0xC16F, 0xD59B, 0xC170, 0xD59C, 0xC171, 0xD59D, 0xC172, 0xD59E, 0xC173, 0xD59F, 0xC174, 0xD5A0, + 0xC175, 0xD5A1, 0xC176, 0xD5A2, 0xC177, 0xD5A3, 0xC178, 0xD5A4, 0xC179, 0xD5A6, 0xC17A, 0xD5A7, 0xC181, 0xD5A8, 0xC182, 0xD5A9, + 0xC183, 0xD5AA, 0xC184, 0xD5AB, 0xC185, 0xD5AC, 0xC186, 0xD5AD, 0xC187, 0xD5AE, 0xC188, 0xD5AF, 0xC189, 0xD5B0, 0xC18A, 0xD5B1, + 0xC18B, 0xD5B2, 0xC18C, 0xD5B3, 0xC18D, 0xD5B4, 0xC18E, 0xD5B5, 0xC18F, 0xD5B6, 0xC190, 0xD5B7, 0xC191, 0xD5B8, 0xC192, 0xD5B9, + 0xC193, 0xD5BA, 0xC194, 0xD5BB, 0xC195, 0xD5BC, 0xC196, 0xD5BD, 0xC197, 0xD5BE, 0xC198, 0xD5BF, 0xC199, 0xD5C0, 0xC19A, 0xD5C1, + 0xC19B, 0xD5C2, 0xC19C, 0xD5C3, 0xC19D, 0xD5C4, 0xC19E, 0xD5C5, 0xC19F, 0xD5C6, 0xC1A0, 0xD5C7, 0xC1A1, 0xC810, 0xC1A2, 0xC811, + 0xC1A3, 0xC813, 0xC1A4, 0xC815, 0xC1A5, 0xC816, 0xC1A6, 0xC81C, 0xC1A7, 0xC81D, 0xC1A8, 0xC820, 0xC1A9, 0xC824, 0xC1AA, 0xC82C, + 0xC1AB, 0xC82D, 0xC1AC, 0xC82F, 0xC1AD, 0xC831, 0xC1AE, 0xC838, 0xC1AF, 0xC83C, 0xC1B0, 0xC840, 0xC1B1, 0xC848, 0xC1B2, 0xC849, + 0xC1B3, 0xC84C, 0xC1B4, 0xC84D, 0xC1B5, 0xC854, 0xC1B6, 0xC870, 0xC1B7, 0xC871, 0xC1B8, 0xC874, 0xC1B9, 0xC878, 0xC1BA, 0xC87A, + 0xC1BB, 0xC880, 0xC1BC, 0xC881, 0xC1BD, 0xC883, 0xC1BE, 0xC885, 0xC1BF, 0xC886, 0xC1C0, 0xC887, 0xC1C1, 0xC88B, 0xC1C2, 0xC88C, + 0xC1C3, 0xC88D, 0xC1C4, 0xC894, 0xC1C5, 0xC89D, 0xC1C6, 0xC89F, 0xC1C7, 0xC8A1, 0xC1C8, 0xC8A8, 0xC1C9, 0xC8BC, 0xC1CA, 0xC8BD, + 0xC1CB, 0xC8C4, 0xC1CC, 0xC8C8, 0xC1CD, 0xC8CC, 0xC1CE, 0xC8D4, 0xC1CF, 0xC8D5, 0xC1D0, 0xC8D7, 0xC1D1, 0xC8D9, 0xC1D2, 0xC8E0, + 0xC1D3, 0xC8E1, 0xC1D4, 0xC8E4, 0xC1D5, 0xC8F5, 0xC1D6, 0xC8FC, 0xC1D7, 0xC8FD, 0xC1D8, 0xC900, 0xC1D9, 0xC904, 0xC1DA, 0xC905, + 0xC1DB, 0xC906, 0xC1DC, 0xC90C, 0xC1DD, 0xC90D, 0xC1DE, 0xC90F, 0xC1DF, 0xC911, 0xC1E0, 0xC918, 0xC1E1, 0xC92C, 0xC1E2, 0xC934, + 0xC1E3, 0xC950, 0xC1E4, 0xC951, 0xC1E5, 0xC954, 0xC1E6, 0xC958, 0xC1E7, 0xC960, 0xC1E8, 0xC961, 0xC1E9, 0xC963, 0xC1EA, 0xC96C, + 0xC1EB, 0xC970, 0xC1EC, 0xC974, 0xC1ED, 0xC97C, 0xC1EE, 0xC988, 0xC1EF, 0xC989, 0xC1F0, 0xC98C, 0xC1F1, 0xC990, 0xC1F2, 0xC998, + 0xC1F3, 0xC999, 0xC1F4, 0xC99B, 0xC1F5, 0xC99D, 0xC1F6, 0xC9C0, 0xC1F7, 0xC9C1, 0xC1F8, 0xC9C4, 0xC1F9, 0xC9C7, 0xC1FA, 0xC9C8, + 0xC1FB, 0xC9CA, 0xC1FC, 0xC9D0, 0xC1FD, 0xC9D1, 0xC1FE, 0xC9D3, 0xC241, 0xD5CA, 0xC242, 0xD5CB, 0xC243, 0xD5CD, 0xC244, 0xD5CE, + 0xC245, 0xD5CF, 0xC246, 0xD5D1, 0xC247, 0xD5D3, 0xC248, 0xD5D4, 0xC249, 0xD5D5, 0xC24A, 0xD5D6, 0xC24B, 0xD5D7, 0xC24C, 0xD5DA, + 0xC24D, 0xD5DC, 0xC24E, 0xD5DE, 0xC24F, 0xD5DF, 0xC250, 0xD5E0, 0xC251, 0xD5E1, 0xC252, 0xD5E2, 0xC253, 0xD5E3, 0xC254, 0xD5E6, + 0xC255, 0xD5E7, 0xC256, 0xD5E9, 0xC257, 0xD5EA, 0xC258, 0xD5EB, 0xC259, 0xD5ED, 0xC25A, 0xD5EE, 0xC261, 0xD5EF, 0xC262, 0xD5F0, + 0xC263, 0xD5F1, 0xC264, 0xD5F2, 0xC265, 0xD5F3, 0xC266, 0xD5F6, 0xC267, 0xD5F8, 0xC268, 0xD5FA, 0xC269, 0xD5FB, 0xC26A, 0xD5FC, + 0xC26B, 0xD5FD, 0xC26C, 0xD5FE, 0xC26D, 0xD5FF, 0xC26E, 0xD602, 0xC26F, 0xD603, 0xC270, 0xD605, 0xC271, 0xD606, 0xC272, 0xD607, + 0xC273, 0xD609, 0xC274, 0xD60A, 0xC275, 0xD60B, 0xC276, 0xD60C, 0xC277, 0xD60D, 0xC278, 0xD60E, 0xC279, 0xD60F, 0xC27A, 0xD612, + 0xC281, 0xD616, 0xC282, 0xD617, 0xC283, 0xD618, 0xC284, 0xD619, 0xC285, 0xD61A, 0xC286, 0xD61B, 0xC287, 0xD61D, 0xC288, 0xD61E, + 0xC289, 0xD61F, 0xC28A, 0xD621, 0xC28B, 0xD622, 0xC28C, 0xD623, 0xC28D, 0xD625, 0xC28E, 0xD626, 0xC28F, 0xD627, 0xC290, 0xD628, + 0xC291, 0xD629, 0xC292, 0xD62A, 0xC293, 0xD62B, 0xC294, 0xD62C, 0xC295, 0xD62E, 0xC296, 0xD62F, 0xC297, 0xD630, 0xC298, 0xD631, + 0xC299, 0xD632, 0xC29A, 0xD633, 0xC29B, 0xD634, 0xC29C, 0xD635, 0xC29D, 0xD636, 0xC29E, 0xD637, 0xC29F, 0xD63A, 0xC2A0, 0xD63B, + 0xC2A1, 0xC9D5, 0xC2A2, 0xC9D6, 0xC2A3, 0xC9D9, 0xC2A4, 0xC9DA, 0xC2A5, 0xC9DC, 0xC2A6, 0xC9DD, 0xC2A7, 0xC9E0, 0xC2A8, 0xC9E2, + 0xC2A9, 0xC9E4, 0xC2AA, 0xC9E7, 0xC2AB, 0xC9EC, 0xC2AC, 0xC9ED, 0xC2AD, 0xC9EF, 0xC2AE, 0xC9F0, 0xC2AF, 0xC9F1, 0xC2B0, 0xC9F8, + 0xC2B1, 0xC9F9, 0xC2B2, 0xC9FC, 0xC2B3, 0xCA00, 0xC2B4, 0xCA08, 0xC2B5, 0xCA09, 0xC2B6, 0xCA0B, 0xC2B7, 0xCA0C, 0xC2B8, 0xCA0D, + 0xC2B9, 0xCA14, 0xC2BA, 0xCA18, 0xC2BB, 0xCA29, 0xC2BC, 0xCA4C, 0xC2BD, 0xCA4D, 0xC2BE, 0xCA50, 0xC2BF, 0xCA54, 0xC2C0, 0xCA5C, + 0xC2C1, 0xCA5D, 0xC2C2, 0xCA5F, 0xC2C3, 0xCA60, 0xC2C4, 0xCA61, 0xC2C5, 0xCA68, 0xC2C6, 0xCA7D, 0xC2C7, 0xCA84, 0xC2C8, 0xCA98, + 0xC2C9, 0xCABC, 0xC2CA, 0xCABD, 0xC2CB, 0xCAC0, 0xC2CC, 0xCAC4, 0xC2CD, 0xCACC, 0xC2CE, 0xCACD, 0xC2CF, 0xCACF, 0xC2D0, 0xCAD1, + 0xC2D1, 0xCAD3, 0xC2D2, 0xCAD8, 0xC2D3, 0xCAD9, 0xC2D4, 0xCAE0, 0xC2D5, 0xCAEC, 0xC2D6, 0xCAF4, 0xC2D7, 0xCB08, 0xC2D8, 0xCB10, + 0xC2D9, 0xCB14, 0xC2DA, 0xCB18, 0xC2DB, 0xCB20, 0xC2DC, 0xCB21, 0xC2DD, 0xCB41, 0xC2DE, 0xCB48, 0xC2DF, 0xCB49, 0xC2E0, 0xCB4C, + 0xC2E1, 0xCB50, 0xC2E2, 0xCB58, 0xC2E3, 0xCB59, 0xC2E4, 0xCB5D, 0xC2E5, 0xCB64, 0xC2E6, 0xCB78, 0xC2E7, 0xCB79, 0xC2E8, 0xCB9C, + 0xC2E9, 0xCBB8, 0xC2EA, 0xCBD4, 0xC2EB, 0xCBE4, 0xC2EC, 0xCBE7, 0xC2ED, 0xCBE9, 0xC2EE, 0xCC0C, 0xC2EF, 0xCC0D, 0xC2F0, 0xCC10, + 0xC2F1, 0xCC14, 0xC2F2, 0xCC1C, 0xC2F3, 0xCC1D, 0xC2F4, 0xCC21, 0xC2F5, 0xCC22, 0xC2F6, 0xCC27, 0xC2F7, 0xCC28, 0xC2F8, 0xCC29, + 0xC2F9, 0xCC2C, 0xC2FA, 0xCC2E, 0xC2FB, 0xCC30, 0xC2FC, 0xCC38, 0xC2FD, 0xCC39, 0xC2FE, 0xCC3B, 0xC341, 0xD63D, 0xC342, 0xD63E, + 0xC343, 0xD63F, 0xC344, 0xD641, 0xC345, 0xD642, 0xC346, 0xD643, 0xC347, 0xD644, 0xC348, 0xD646, 0xC349, 0xD647, 0xC34A, 0xD64A, + 0xC34B, 0xD64C, 0xC34C, 0xD64E, 0xC34D, 0xD64F, 0xC34E, 0xD650, 0xC34F, 0xD652, 0xC350, 0xD653, 0xC351, 0xD656, 0xC352, 0xD657, + 0xC353, 0xD659, 0xC354, 0xD65A, 0xC355, 0xD65B, 0xC356, 0xD65D, 0xC357, 0xD65E, 0xC358, 0xD65F, 0xC359, 0xD660, 0xC35A, 0xD661, + 0xC361, 0xD662, 0xC362, 0xD663, 0xC363, 0xD664, 0xC364, 0xD665, 0xC365, 0xD666, 0xC366, 0xD668, 0xC367, 0xD66A, 0xC368, 0xD66B, + 0xC369, 0xD66C, 0xC36A, 0xD66D, 0xC36B, 0xD66E, 0xC36C, 0xD66F, 0xC36D, 0xD672, 0xC36E, 0xD673, 0xC36F, 0xD675, 0xC370, 0xD676, + 0xC371, 0xD677, 0xC372, 0xD678, 0xC373, 0xD679, 0xC374, 0xD67A, 0xC375, 0xD67B, 0xC376, 0xD67C, 0xC377, 0xD67D, 0xC378, 0xD67E, + 0xC379, 0xD67F, 0xC37A, 0xD680, 0xC381, 0xD681, 0xC382, 0xD682, 0xC383, 0xD684, 0xC384, 0xD686, 0xC385, 0xD687, 0xC386, 0xD688, + 0xC387, 0xD689, 0xC388, 0xD68A, 0xC389, 0xD68B, 0xC38A, 0xD68E, 0xC38B, 0xD68F, 0xC38C, 0xD691, 0xC38D, 0xD692, 0xC38E, 0xD693, + 0xC38F, 0xD695, 0xC390, 0xD696, 0xC391, 0xD697, 0xC392, 0xD698, 0xC393, 0xD699, 0xC394, 0xD69A, 0xC395, 0xD69B, 0xC396, 0xD69C, + 0xC397, 0xD69E, 0xC398, 0xD6A0, 0xC399, 0xD6A2, 0xC39A, 0xD6A3, 0xC39B, 0xD6A4, 0xC39C, 0xD6A5, 0xC39D, 0xD6A6, 0xC39E, 0xD6A7, + 0xC39F, 0xD6A9, 0xC3A0, 0xD6AA, 0xC3A1, 0xCC3C, 0xC3A2, 0xCC3D, 0xC3A3, 0xCC3E, 0xC3A4, 0xCC44, 0xC3A5, 0xCC45, 0xC3A6, 0xCC48, + 0xC3A7, 0xCC4C, 0xC3A8, 0xCC54, 0xC3A9, 0xCC55, 0xC3AA, 0xCC57, 0xC3AB, 0xCC58, 0xC3AC, 0xCC59, 0xC3AD, 0xCC60, 0xC3AE, 0xCC64, + 0xC3AF, 0xCC66, 0xC3B0, 0xCC68, 0xC3B1, 0xCC70, 0xC3B2, 0xCC75, 0xC3B3, 0xCC98, 0xC3B4, 0xCC99, 0xC3B5, 0xCC9C, 0xC3B6, 0xCCA0, + 0xC3B7, 0xCCA8, 0xC3B8, 0xCCA9, 0xC3B9, 0xCCAB, 0xC3BA, 0xCCAC, 0xC3BB, 0xCCAD, 0xC3BC, 0xCCB4, 0xC3BD, 0xCCB5, 0xC3BE, 0xCCB8, + 0xC3BF, 0xCCBC, 0xC3C0, 0xCCC4, 0xC3C1, 0xCCC5, 0xC3C2, 0xCCC7, 0xC3C3, 0xCCC9, 0xC3C4, 0xCCD0, 0xC3C5, 0xCCD4, 0xC3C6, 0xCCE4, + 0xC3C7, 0xCCEC, 0xC3C8, 0xCCF0, 0xC3C9, 0xCD01, 0xC3CA, 0xCD08, 0xC3CB, 0xCD09, 0xC3CC, 0xCD0C, 0xC3CD, 0xCD10, 0xC3CE, 0xCD18, + 0xC3CF, 0xCD19, 0xC3D0, 0xCD1B, 0xC3D1, 0xCD1D, 0xC3D2, 0xCD24, 0xC3D3, 0xCD28, 0xC3D4, 0xCD2C, 0xC3D5, 0xCD39, 0xC3D6, 0xCD5C, + 0xC3D7, 0xCD60, 0xC3D8, 0xCD64, 0xC3D9, 0xCD6C, 0xC3DA, 0xCD6D, 0xC3DB, 0xCD6F, 0xC3DC, 0xCD71, 0xC3DD, 0xCD78, 0xC3DE, 0xCD88, + 0xC3DF, 0xCD94, 0xC3E0, 0xCD95, 0xC3E1, 0xCD98, 0xC3E2, 0xCD9C, 0xC3E3, 0xCDA4, 0xC3E4, 0xCDA5, 0xC3E5, 0xCDA7, 0xC3E6, 0xCDA9, + 0xC3E7, 0xCDB0, 0xC3E8, 0xCDC4, 0xC3E9, 0xCDCC, 0xC3EA, 0xCDD0, 0xC3EB, 0xCDE8, 0xC3EC, 0xCDEC, 0xC3ED, 0xCDF0, 0xC3EE, 0xCDF8, + 0xC3EF, 0xCDF9, 0xC3F0, 0xCDFB, 0xC3F1, 0xCDFD, 0xC3F2, 0xCE04, 0xC3F3, 0xCE08, 0xC3F4, 0xCE0C, 0xC3F5, 0xCE14, 0xC3F6, 0xCE19, + 0xC3F7, 0xCE20, 0xC3F8, 0xCE21, 0xC3F9, 0xCE24, 0xC3FA, 0xCE28, 0xC3FB, 0xCE30, 0xC3FC, 0xCE31, 0xC3FD, 0xCE33, 0xC3FE, 0xCE35, + 0xC441, 0xD6AB, 0xC442, 0xD6AD, 0xC443, 0xD6AE, 0xC444, 0xD6AF, 0xC445, 0xD6B1, 0xC446, 0xD6B2, 0xC447, 0xD6B3, 0xC448, 0xD6B4, + 0xC449, 0xD6B5, 0xC44A, 0xD6B6, 0xC44B, 0xD6B7, 0xC44C, 0xD6B8, 0xC44D, 0xD6BA, 0xC44E, 0xD6BC, 0xC44F, 0xD6BD, 0xC450, 0xD6BE, + 0xC451, 0xD6BF, 0xC452, 0xD6C0, 0xC453, 0xD6C1, 0xC454, 0xD6C2, 0xC455, 0xD6C3, 0xC456, 0xD6C6, 0xC457, 0xD6C7, 0xC458, 0xD6C9, + 0xC459, 0xD6CA, 0xC45A, 0xD6CB, 0xC461, 0xD6CD, 0xC462, 0xD6CE, 0xC463, 0xD6CF, 0xC464, 0xD6D0, 0xC465, 0xD6D2, 0xC466, 0xD6D3, + 0xC467, 0xD6D5, 0xC468, 0xD6D6, 0xC469, 0xD6D8, 0xC46A, 0xD6DA, 0xC46B, 0xD6DB, 0xC46C, 0xD6DC, 0xC46D, 0xD6DD, 0xC46E, 0xD6DE, + 0xC46F, 0xD6DF, 0xC470, 0xD6E1, 0xC471, 0xD6E2, 0xC472, 0xD6E3, 0xC473, 0xD6E5, 0xC474, 0xD6E6, 0xC475, 0xD6E7, 0xC476, 0xD6E9, + 0xC477, 0xD6EA, 0xC478, 0xD6EB, 0xC479, 0xD6EC, 0xC47A, 0xD6ED, 0xC481, 0xD6EE, 0xC482, 0xD6EF, 0xC483, 0xD6F1, 0xC484, 0xD6F2, + 0xC485, 0xD6F3, 0xC486, 0xD6F4, 0xC487, 0xD6F6, 0xC488, 0xD6F7, 0xC489, 0xD6F8, 0xC48A, 0xD6F9, 0xC48B, 0xD6FA, 0xC48C, 0xD6FB, + 0xC48D, 0xD6FE, 0xC48E, 0xD6FF, 0xC48F, 0xD701, 0xC490, 0xD702, 0xC491, 0xD703, 0xC492, 0xD705, 0xC493, 0xD706, 0xC494, 0xD707, + 0xC495, 0xD708, 0xC496, 0xD709, 0xC497, 0xD70A, 0xC498, 0xD70B, 0xC499, 0xD70C, 0xC49A, 0xD70D, 0xC49B, 0xD70E, 0xC49C, 0xD70F, + 0xC49D, 0xD710, 0xC49E, 0xD712, 0xC49F, 0xD713, 0xC4A0, 0xD714, 0xC4A1, 0xCE58, 0xC4A2, 0xCE59, 0xC4A3, 0xCE5C, 0xC4A4, 0xCE5F, + 0xC4A5, 0xCE60, 0xC4A6, 0xCE61, 0xC4A7, 0xCE68, 0xC4A8, 0xCE69, 0xC4A9, 0xCE6B, 0xC4AA, 0xCE6D, 0xC4AB, 0xCE74, 0xC4AC, 0xCE75, + 0xC4AD, 0xCE78, 0xC4AE, 0xCE7C, 0xC4AF, 0xCE84, 0xC4B0, 0xCE85, 0xC4B1, 0xCE87, 0xC4B2, 0xCE89, 0xC4B3, 0xCE90, 0xC4B4, 0xCE91, + 0xC4B5, 0xCE94, 0xC4B6, 0xCE98, 0xC4B7, 0xCEA0, 0xC4B8, 0xCEA1, 0xC4B9, 0xCEA3, 0xC4BA, 0xCEA4, 0xC4BB, 0xCEA5, 0xC4BC, 0xCEAC, + 0xC4BD, 0xCEAD, 0xC4BE, 0xCEC1, 0xC4BF, 0xCEE4, 0xC4C0, 0xCEE5, 0xC4C1, 0xCEE8, 0xC4C2, 0xCEEB, 0xC4C3, 0xCEEC, 0xC4C4, 0xCEF4, + 0xC4C5, 0xCEF5, 0xC4C6, 0xCEF7, 0xC4C7, 0xCEF8, 0xC4C8, 0xCEF9, 0xC4C9, 0xCF00, 0xC4CA, 0xCF01, 0xC4CB, 0xCF04, 0xC4CC, 0xCF08, + 0xC4CD, 0xCF10, 0xC4CE, 0xCF11, 0xC4CF, 0xCF13, 0xC4D0, 0xCF15, 0xC4D1, 0xCF1C, 0xC4D2, 0xCF20, 0xC4D3, 0xCF24, 0xC4D4, 0xCF2C, + 0xC4D5, 0xCF2D, 0xC4D6, 0xCF2F, 0xC4D7, 0xCF30, 0xC4D8, 0xCF31, 0xC4D9, 0xCF38, 0xC4DA, 0xCF54, 0xC4DB, 0xCF55, 0xC4DC, 0xCF58, + 0xC4DD, 0xCF5C, 0xC4DE, 0xCF64, 0xC4DF, 0xCF65, 0xC4E0, 0xCF67, 0xC4E1, 0xCF69, 0xC4E2, 0xCF70, 0xC4E3, 0xCF71, 0xC4E4, 0xCF74, + 0xC4E5, 0xCF78, 0xC4E6, 0xCF80, 0xC4E7, 0xCF85, 0xC4E8, 0xCF8C, 0xC4E9, 0xCFA1, 0xC4EA, 0xCFA8, 0xC4EB, 0xCFB0, 0xC4EC, 0xCFC4, + 0xC4ED, 0xCFE0, 0xC4EE, 0xCFE1, 0xC4EF, 0xCFE4, 0xC4F0, 0xCFE8, 0xC4F1, 0xCFF0, 0xC4F2, 0xCFF1, 0xC4F3, 0xCFF3, 0xC4F4, 0xCFF5, + 0xC4F5, 0xCFFC, 0xC4F6, 0xD000, 0xC4F7, 0xD004, 0xC4F8, 0xD011, 0xC4F9, 0xD018, 0xC4FA, 0xD02D, 0xC4FB, 0xD034, 0xC4FC, 0xD035, + 0xC4FD, 0xD038, 0xC4FE, 0xD03C, 0xC541, 0xD715, 0xC542, 0xD716, 0xC543, 0xD717, 0xC544, 0xD71A, 0xC545, 0xD71B, 0xC546, 0xD71D, + 0xC547, 0xD71E, 0xC548, 0xD71F, 0xC549, 0xD721, 0xC54A, 0xD722, 0xC54B, 0xD723, 0xC54C, 0xD724, 0xC54D, 0xD725, 0xC54E, 0xD726, + 0xC54F, 0xD727, 0xC550, 0xD72A, 0xC551, 0xD72C, 0xC552, 0xD72E, 0xC553, 0xD72F, 0xC554, 0xD730, 0xC555, 0xD731, 0xC556, 0xD732, + 0xC557, 0xD733, 0xC558, 0xD736, 0xC559, 0xD737, 0xC55A, 0xD739, 0xC561, 0xD73A, 0xC562, 0xD73B, 0xC563, 0xD73D, 0xC564, 0xD73E, + 0xC565, 0xD73F, 0xC566, 0xD740, 0xC567, 0xD741, 0xC568, 0xD742, 0xC569, 0xD743, 0xC56A, 0xD745, 0xC56B, 0xD746, 0xC56C, 0xD748, + 0xC56D, 0xD74A, 0xC56E, 0xD74B, 0xC56F, 0xD74C, 0xC570, 0xD74D, 0xC571, 0xD74E, 0xC572, 0xD74F, 0xC573, 0xD752, 0xC574, 0xD753, + 0xC575, 0xD755, 0xC576, 0xD75A, 0xC577, 0xD75B, 0xC578, 0xD75C, 0xC579, 0xD75D, 0xC57A, 0xD75E, 0xC581, 0xD75F, 0xC582, 0xD762, + 0xC583, 0xD764, 0xC584, 0xD766, 0xC585, 0xD767, 0xC586, 0xD768, 0xC587, 0xD76A, 0xC588, 0xD76B, 0xC589, 0xD76D, 0xC58A, 0xD76E, + 0xC58B, 0xD76F, 0xC58C, 0xD771, 0xC58D, 0xD772, 0xC58E, 0xD773, 0xC58F, 0xD775, 0xC590, 0xD776, 0xC591, 0xD777, 0xC592, 0xD778, + 0xC593, 0xD779, 0xC594, 0xD77A, 0xC595, 0xD77B, 0xC596, 0xD77E, 0xC597, 0xD77F, 0xC598, 0xD780, 0xC599, 0xD782, 0xC59A, 0xD783, + 0xC59B, 0xD784, 0xC59C, 0xD785, 0xC59D, 0xD786, 0xC59E, 0xD787, 0xC59F, 0xD78A, 0xC5A0, 0xD78B, 0xC5A1, 0xD044, 0xC5A2, 0xD045, + 0xC5A3, 0xD047, 0xC5A4, 0xD049, 0xC5A5, 0xD050, 0xC5A6, 0xD054, 0xC5A7, 0xD058, 0xC5A8, 0xD060, 0xC5A9, 0xD06C, 0xC5AA, 0xD06D, + 0xC5AB, 0xD070, 0xC5AC, 0xD074, 0xC5AD, 0xD07C, 0xC5AE, 0xD07D, 0xC5AF, 0xD081, 0xC5B0, 0xD0A4, 0xC5B1, 0xD0A5, 0xC5B2, 0xD0A8, + 0xC5B3, 0xD0AC, 0xC5B4, 0xD0B4, 0xC5B5, 0xD0B5, 0xC5B6, 0xD0B7, 0xC5B7, 0xD0B9, 0xC5B8, 0xD0C0, 0xC5B9, 0xD0C1, 0xC5BA, 0xD0C4, + 0xC5BB, 0xD0C8, 0xC5BC, 0xD0C9, 0xC5BD, 0xD0D0, 0xC5BE, 0xD0D1, 0xC5BF, 0xD0D3, 0xC5C0, 0xD0D4, 0xC5C1, 0xD0D5, 0xC5C2, 0xD0DC, + 0xC5C3, 0xD0DD, 0xC5C4, 0xD0E0, 0xC5C5, 0xD0E4, 0xC5C6, 0xD0EC, 0xC5C7, 0xD0ED, 0xC5C8, 0xD0EF, 0xC5C9, 0xD0F0, 0xC5CA, 0xD0F1, + 0xC5CB, 0xD0F8, 0xC5CC, 0xD10D, 0xC5CD, 0xD130, 0xC5CE, 0xD131, 0xC5CF, 0xD134, 0xC5D0, 0xD138, 0xC5D1, 0xD13A, 0xC5D2, 0xD140, + 0xC5D3, 0xD141, 0xC5D4, 0xD143, 0xC5D5, 0xD144, 0xC5D6, 0xD145, 0xC5D7, 0xD14C, 0xC5D8, 0xD14D, 0xC5D9, 0xD150, 0xC5DA, 0xD154, + 0xC5DB, 0xD15C, 0xC5DC, 0xD15D, 0xC5DD, 0xD15F, 0xC5DE, 0xD161, 0xC5DF, 0xD168, 0xC5E0, 0xD16C, 0xC5E1, 0xD17C, 0xC5E2, 0xD184, + 0xC5E3, 0xD188, 0xC5E4, 0xD1A0, 0xC5E5, 0xD1A1, 0xC5E6, 0xD1A4, 0xC5E7, 0xD1A8, 0xC5E8, 0xD1B0, 0xC5E9, 0xD1B1, 0xC5EA, 0xD1B3, + 0xC5EB, 0xD1B5, 0xC5EC, 0xD1BA, 0xC5ED, 0xD1BC, 0xC5EE, 0xD1C0, 0xC5EF, 0xD1D8, 0xC5F0, 0xD1F4, 0xC5F1, 0xD1F8, 0xC5F2, 0xD207, + 0xC5F3, 0xD209, 0xC5F4, 0xD210, 0xC5F5, 0xD22C, 0xC5F6, 0xD22D, 0xC5F7, 0xD230, 0xC5F8, 0xD234, 0xC5F9, 0xD23C, 0xC5FA, 0xD23D, + 0xC5FB, 0xD23F, 0xC5FC, 0xD241, 0xC5FD, 0xD248, 0xC5FE, 0xD25C, 0xC641, 0xD78D, 0xC642, 0xD78E, 0xC643, 0xD78F, 0xC644, 0xD791, + 0xC645, 0xD792, 0xC646, 0xD793, 0xC647, 0xD794, 0xC648, 0xD795, 0xC649, 0xD796, 0xC64A, 0xD797, 0xC64B, 0xD79A, 0xC64C, 0xD79C, + 0xC64D, 0xD79E, 0xC64E, 0xD79F, 0xC64F, 0xD7A0, 0xC650, 0xD7A1, 0xC651, 0xD7A2, 0xC652, 0xD7A3, 0xC6A1, 0xD264, 0xC6A2, 0xD280, + 0xC6A3, 0xD281, 0xC6A4, 0xD284, 0xC6A5, 0xD288, 0xC6A6, 0xD290, 0xC6A7, 0xD291, 0xC6A8, 0xD295, 0xC6A9, 0xD29C, 0xC6AA, 0xD2A0, + 0xC6AB, 0xD2A4, 0xC6AC, 0xD2AC, 0xC6AD, 0xD2B1, 0xC6AE, 0xD2B8, 0xC6AF, 0xD2B9, 0xC6B0, 0xD2BC, 0xC6B1, 0xD2BF, 0xC6B2, 0xD2C0, + 0xC6B3, 0xD2C2, 0xC6B4, 0xD2C8, 0xC6B5, 0xD2C9, 0xC6B6, 0xD2CB, 0xC6B7, 0xD2D4, 0xC6B8, 0xD2D8, 0xC6B9, 0xD2DC, 0xC6BA, 0xD2E4, + 0xC6BB, 0xD2E5, 0xC6BC, 0xD2F0, 0xC6BD, 0xD2F1, 0xC6BE, 0xD2F4, 0xC6BF, 0xD2F8, 0xC6C0, 0xD300, 0xC6C1, 0xD301, 0xC6C2, 0xD303, + 0xC6C3, 0xD305, 0xC6C4, 0xD30C, 0xC6C5, 0xD30D, 0xC6C6, 0xD30E, 0xC6C7, 0xD310, 0xC6C8, 0xD314, 0xC6C9, 0xD316, 0xC6CA, 0xD31C, + 0xC6CB, 0xD31D, 0xC6CC, 0xD31F, 0xC6CD, 0xD320, 0xC6CE, 0xD321, 0xC6CF, 0xD325, 0xC6D0, 0xD328, 0xC6D1, 0xD329, 0xC6D2, 0xD32C, + 0xC6D3, 0xD330, 0xC6D4, 0xD338, 0xC6D5, 0xD339, 0xC6D6, 0xD33B, 0xC6D7, 0xD33C, 0xC6D8, 0xD33D, 0xC6D9, 0xD344, 0xC6DA, 0xD345, + 0xC6DB, 0xD37C, 0xC6DC, 0xD37D, 0xC6DD, 0xD380, 0xC6DE, 0xD384, 0xC6DF, 0xD38C, 0xC6E0, 0xD38D, 0xC6E1, 0xD38F, 0xC6E2, 0xD390, + 0xC6E3, 0xD391, 0xC6E4, 0xD398, 0xC6E5, 0xD399, 0xC6E6, 0xD39C, 0xC6E7, 0xD3A0, 0xC6E8, 0xD3A8, 0xC6E9, 0xD3A9, 0xC6EA, 0xD3AB, + 0xC6EB, 0xD3AD, 0xC6EC, 0xD3B4, 0xC6ED, 0xD3B8, 0xC6EE, 0xD3BC, 0xC6EF, 0xD3C4, 0xC6F0, 0xD3C5, 0xC6F1, 0xD3C8, 0xC6F2, 0xD3C9, + 0xC6F3, 0xD3D0, 0xC6F4, 0xD3D8, 0xC6F5, 0xD3E1, 0xC6F6, 0xD3E3, 0xC6F7, 0xD3EC, 0xC6F8, 0xD3ED, 0xC6F9, 0xD3F0, 0xC6FA, 0xD3F4, + 0xC6FB, 0xD3FC, 0xC6FC, 0xD3FD, 0xC6FD, 0xD3FF, 0xC6FE, 0xD401, 0xC7A1, 0xD408, 0xC7A2, 0xD41D, 0xC7A3, 0xD440, 0xC7A4, 0xD444, + 0xC7A5, 0xD45C, 0xC7A6, 0xD460, 0xC7A7, 0xD464, 0xC7A8, 0xD46D, 0xC7A9, 0xD46F, 0xC7AA, 0xD478, 0xC7AB, 0xD479, 0xC7AC, 0xD47C, + 0xC7AD, 0xD47F, 0xC7AE, 0xD480, 0xC7AF, 0xD482, 0xC7B0, 0xD488, 0xC7B1, 0xD489, 0xC7B2, 0xD48B, 0xC7B3, 0xD48D, 0xC7B4, 0xD494, + 0xC7B5, 0xD4A9, 0xC7B6, 0xD4CC, 0xC7B7, 0xD4D0, 0xC7B8, 0xD4D4, 0xC7B9, 0xD4DC, 0xC7BA, 0xD4DF, 0xC7BB, 0xD4E8, 0xC7BC, 0xD4EC, + 0xC7BD, 0xD4F0, 0xC7BE, 0xD4F8, 0xC7BF, 0xD4FB, 0xC7C0, 0xD4FD, 0xC7C1, 0xD504, 0xC7C2, 0xD508, 0xC7C3, 0xD50C, 0xC7C4, 0xD514, + 0xC7C5, 0xD515, 0xC7C6, 0xD517, 0xC7C7, 0xD53C, 0xC7C8, 0xD53D, 0xC7C9, 0xD540, 0xC7CA, 0xD544, 0xC7CB, 0xD54C, 0xC7CC, 0xD54D, + 0xC7CD, 0xD54F, 0xC7CE, 0xD551, 0xC7CF, 0xD558, 0xC7D0, 0xD559, 0xC7D1, 0xD55C, 0xC7D2, 0xD560, 0xC7D3, 0xD565, 0xC7D4, 0xD568, + 0xC7D5, 0xD569, 0xC7D6, 0xD56B, 0xC7D7, 0xD56D, 0xC7D8, 0xD574, 0xC7D9, 0xD575, 0xC7DA, 0xD578, 0xC7DB, 0xD57C, 0xC7DC, 0xD584, + 0xC7DD, 0xD585, 0xC7DE, 0xD587, 0xC7DF, 0xD588, 0xC7E0, 0xD589, 0xC7E1, 0xD590, 0xC7E2, 0xD5A5, 0xC7E3, 0xD5C8, 0xC7E4, 0xD5C9, + 0xC7E5, 0xD5CC, 0xC7E6, 0xD5D0, 0xC7E7, 0xD5D2, 0xC7E8, 0xD5D8, 0xC7E9, 0xD5D9, 0xC7EA, 0xD5DB, 0xC7EB, 0xD5DD, 0xC7EC, 0xD5E4, + 0xC7ED, 0xD5E5, 0xC7EE, 0xD5E8, 0xC7EF, 0xD5EC, 0xC7F0, 0xD5F4, 0xC7F1, 0xD5F5, 0xC7F2, 0xD5F7, 0xC7F3, 0xD5F9, 0xC7F4, 0xD600, + 0xC7F5, 0xD601, 0xC7F6, 0xD604, 0xC7F7, 0xD608, 0xC7F8, 0xD610, 0xC7F9, 0xD611, 0xC7FA, 0xD613, 0xC7FB, 0xD614, 0xC7FC, 0xD615, + 0xC7FD, 0xD61C, 0xC7FE, 0xD620, 0xC8A1, 0xD624, 0xC8A2, 0xD62D, 0xC8A3, 0xD638, 0xC8A4, 0xD639, 0xC8A5, 0xD63C, 0xC8A6, 0xD640, + 0xC8A7, 0xD645, 0xC8A8, 0xD648, 0xC8A9, 0xD649, 0xC8AA, 0xD64B, 0xC8AB, 0xD64D, 0xC8AC, 0xD651, 0xC8AD, 0xD654, 0xC8AE, 0xD655, + 0xC8AF, 0xD658, 0xC8B0, 0xD65C, 0xC8B1, 0xD667, 0xC8B2, 0xD669, 0xC8B3, 0xD670, 0xC8B4, 0xD671, 0xC8B5, 0xD674, 0xC8B6, 0xD683, + 0xC8B7, 0xD685, 0xC8B8, 0xD68C, 0xC8B9, 0xD68D, 0xC8BA, 0xD690, 0xC8BB, 0xD694, 0xC8BC, 0xD69D, 0xC8BD, 0xD69F, 0xC8BE, 0xD6A1, + 0xC8BF, 0xD6A8, 0xC8C0, 0xD6AC, 0xC8C1, 0xD6B0, 0xC8C2, 0xD6B9, 0xC8C3, 0xD6BB, 0xC8C4, 0xD6C4, 0xC8C5, 0xD6C5, 0xC8C6, 0xD6C8, + 0xC8C7, 0xD6CC, 0xC8C8, 0xD6D1, 0xC8C9, 0xD6D4, 0xC8CA, 0xD6D7, 0xC8CB, 0xD6D9, 0xC8CC, 0xD6E0, 0xC8CD, 0xD6E4, 0xC8CE, 0xD6E8, + 0xC8CF, 0xD6F0, 0xC8D0, 0xD6F5, 0xC8D1, 0xD6FC, 0xC8D2, 0xD6FD, 0xC8D3, 0xD700, 0xC8D4, 0xD704, 0xC8D5, 0xD711, 0xC8D6, 0xD718, + 0xC8D7, 0xD719, 0xC8D8, 0xD71C, 0xC8D9, 0xD720, 0xC8DA, 0xD728, 0xC8DB, 0xD729, 0xC8DC, 0xD72B, 0xC8DD, 0xD72D, 0xC8DE, 0xD734, + 0xC8DF, 0xD735, 0xC8E0, 0xD738, 0xC8E1, 0xD73C, 0xC8E2, 0xD744, 0xC8E3, 0xD747, 0xC8E4, 0xD749, 0xC8E5, 0xD750, 0xC8E6, 0xD751, + 0xC8E7, 0xD754, 0xC8E8, 0xD756, 0xC8E9, 0xD757, 0xC8EA, 0xD758, 0xC8EB, 0xD759, 0xC8EC, 0xD760, 0xC8ED, 0xD761, 0xC8EE, 0xD763, + 0xC8EF, 0xD765, 0xC8F0, 0xD769, 0xC8F1, 0xD76C, 0xC8F2, 0xD770, 0xC8F3, 0xD774, 0xC8F4, 0xD77C, 0xC8F5, 0xD77D, 0xC8F6, 0xD781, + 0xC8F7, 0xD788, 0xC8F8, 0xD789, 0xC8F9, 0xD78C, 0xC8FA, 0xD790, 0xC8FB, 0xD798, 0xC8FC, 0xD799, 0xC8FD, 0xD79B, 0xC8FE, 0xD79D, + 0xCAA1, 0x4F3D, 0xCAA2, 0x4F73, 0xCAA3, 0x5047, 0xCAA4, 0x50F9, 0xCAA5, 0x52A0, 0xCAA6, 0x53EF, 0xCAA7, 0x5475, 0xCAA8, 0x54E5, + 0xCAA9, 0x5609, 0xCAAA, 0x5AC1, 0xCAAB, 0x5BB6, 0xCAAC, 0x6687, 0xCAAD, 0x67B6, 0xCAAE, 0x67B7, 0xCAAF, 0x67EF, 0xCAB0, 0x6B4C, + 0xCAB1, 0x73C2, 0xCAB2, 0x75C2, 0xCAB3, 0x7A3C, 0xCAB4, 0x82DB, 0xCAB5, 0x8304, 0xCAB6, 0x8857, 0xCAB7, 0x8888, 0xCAB8, 0x8A36, + 0xCAB9, 0x8CC8, 0xCABA, 0x8DCF, 0xCABB, 0x8EFB, 0xCABC, 0x8FE6, 0xCABD, 0x99D5, 0xCABE, 0x523B, 0xCABF, 0x5374, 0xCAC0, 0x5404, + 0xCAC1, 0x606A, 0xCAC2, 0x6164, 0xCAC3, 0x6BBC, 0xCAC4, 0x73CF, 0xCAC5, 0x811A, 0xCAC6, 0x89BA, 0xCAC7, 0x89D2, 0xCAC8, 0x95A3, + 0xCAC9, 0x4F83, 0xCACA, 0x520A, 0xCACB, 0x58BE, 0xCACC, 0x5978, 0xCACD, 0x59E6, 0xCACE, 0x5E72, 0xCACF, 0x5E79, 0xCAD0, 0x61C7, + 0xCAD1, 0x63C0, 0xCAD2, 0x6746, 0xCAD3, 0x67EC, 0xCAD4, 0x687F, 0xCAD5, 0x6F97, 0xCAD6, 0x764E, 0xCAD7, 0x770B, 0xCAD8, 0x78F5, + 0xCAD9, 0x7A08, 0xCADA, 0x7AFF, 0xCADB, 0x7C21, 0xCADC, 0x809D, 0xCADD, 0x826E, 0xCADE, 0x8271, 0xCADF, 0x8AEB, 0xCAE0, 0x9593, + 0xCAE1, 0x4E6B, 0xCAE2, 0x559D, 0xCAE3, 0x66F7, 0xCAE4, 0x6E34, 0xCAE5, 0x78A3, 0xCAE6, 0x7AED, 0xCAE7, 0x845B, 0xCAE8, 0x8910, + 0xCAE9, 0x874E, 0xCAEA, 0x97A8, 0xCAEB, 0x52D8, 0xCAEC, 0x574E, 0xCAED, 0x582A, 0xCAEE, 0x5D4C, 0xCAEF, 0x611F, 0xCAF0, 0x61BE, + 0xCAF1, 0x6221, 0xCAF2, 0x6562, 0xCAF3, 0x67D1, 0xCAF4, 0x6A44, 0xCAF5, 0x6E1B, 0xCAF6, 0x7518, 0xCAF7, 0x75B3, 0xCAF8, 0x76E3, + 0xCAF9, 0x77B0, 0xCAFA, 0x7D3A, 0xCAFB, 0x90AF, 0xCAFC, 0x9451, 0xCAFD, 0x9452, 0xCAFE, 0x9F95, 0xCBA1, 0x5323, 0xCBA2, 0x5CAC, + 0xCBA3, 0x7532, 0xCBA4, 0x80DB, 0xCBA5, 0x9240, 0xCBA6, 0x9598, 0xCBA7, 0x525B, 0xCBA8, 0x5808, 0xCBA9, 0x59DC, 0xCBAA, 0x5CA1, + 0xCBAB, 0x5D17, 0xCBAC, 0x5EB7, 0xCBAD, 0x5F3A, 0xCBAE, 0x5F4A, 0xCBAF, 0x6177, 0xCBB0, 0x6C5F, 0xCBB1, 0x757A, 0xCBB2, 0x7586, + 0xCBB3, 0x7CE0, 0xCBB4, 0x7D73, 0xCBB5, 0x7DB1, 0xCBB6, 0x7F8C, 0xCBB7, 0x8154, 0xCBB8, 0x8221, 0xCBB9, 0x8591, 0xCBBA, 0x8941, + 0xCBBB, 0x8B1B, 0xCBBC, 0x92FC, 0xCBBD, 0x964D, 0xCBBE, 0x9C47, 0xCBBF, 0x4ECB, 0xCBC0, 0x4EF7, 0xCBC1, 0x500B, 0xCBC2, 0x51F1, + 0xCBC3, 0x584F, 0xCBC4, 0x6137, 0xCBC5, 0x613E, 0xCBC6, 0x6168, 0xCBC7, 0x6539, 0xCBC8, 0x69EA, 0xCBC9, 0x6F11, 0xCBCA, 0x75A5, + 0xCBCB, 0x7686, 0xCBCC, 0x76D6, 0xCBCD, 0x7B87, 0xCBCE, 0x82A5, 0xCBCF, 0x84CB, 0xCBD0, 0xF900, 0xCBD1, 0x93A7, 0xCBD2, 0x958B, + 0xCBD3, 0x5580, 0xCBD4, 0x5BA2, 0xCBD5, 0x5751, 0xCBD6, 0xF901, 0xCBD7, 0x7CB3, 0xCBD8, 0x7FB9, 0xCBD9, 0x91B5, 0xCBDA, 0x5028, + 0xCBDB, 0x53BB, 0xCBDC, 0x5C45, 0xCBDD, 0x5DE8, 0xCBDE, 0x62D2, 0xCBDF, 0x636E, 0xCBE0, 0x64DA, 0xCBE1, 0x64E7, 0xCBE2, 0x6E20, + 0xCBE3, 0x70AC, 0xCBE4, 0x795B, 0xCBE5, 0x8DDD, 0xCBE6, 0x8E1E, 0xCBE7, 0xF902, 0xCBE8, 0x907D, 0xCBE9, 0x9245, 0xCBEA, 0x92F8, + 0xCBEB, 0x4E7E, 0xCBEC, 0x4EF6, 0xCBED, 0x5065, 0xCBEE, 0x5DFE, 0xCBEF, 0x5EFA, 0xCBF0, 0x6106, 0xCBF1, 0x6957, 0xCBF2, 0x8171, + 0xCBF3, 0x8654, 0xCBF4, 0x8E47, 0xCBF5, 0x9375, 0xCBF6, 0x9A2B, 0xCBF7, 0x4E5E, 0xCBF8, 0x5091, 0xCBF9, 0x6770, 0xCBFA, 0x6840, + 0xCBFB, 0x5109, 0xCBFC, 0x528D, 0xCBFD, 0x5292, 0xCBFE, 0x6AA2, 0xCCA1, 0x77BC, 0xCCA2, 0x9210, 0xCCA3, 0x9ED4, 0xCCA4, 0x52AB, + 0xCCA5, 0x602F, 0xCCA6, 0x8FF2, 0xCCA7, 0x5048, 0xCCA8, 0x61A9, 0xCCA9, 0x63ED, 0xCCAA, 0x64CA, 0xCCAB, 0x683C, 0xCCAC, 0x6A84, + 0xCCAD, 0x6FC0, 0xCCAE, 0x8188, 0xCCAF, 0x89A1, 0xCCB0, 0x9694, 0xCCB1, 0x5805, 0xCCB2, 0x727D, 0xCCB3, 0x72AC, 0xCCB4, 0x7504, + 0xCCB5, 0x7D79, 0xCCB6, 0x7E6D, 0xCCB7, 0x80A9, 0xCCB8, 0x898B, 0xCCB9, 0x8B74, 0xCCBA, 0x9063, 0xCCBB, 0x9D51, 0xCCBC, 0x6289, + 0xCCBD, 0x6C7A, 0xCCBE, 0x6F54, 0xCCBF, 0x7D50, 0xCCC0, 0x7F3A, 0xCCC1, 0x8A23, 0xCCC2, 0x517C, 0xCCC3, 0x614A, 0xCCC4, 0x7B9D, + 0xCCC5, 0x8B19, 0xCCC6, 0x9257, 0xCCC7, 0x938C, 0xCCC8, 0x4EAC, 0xCCC9, 0x4FD3, 0xCCCA, 0x501E, 0xCCCB, 0x50BE, 0xCCCC, 0x5106, + 0xCCCD, 0x52C1, 0xCCCE, 0x52CD, 0xCCCF, 0x537F, 0xCCD0, 0x5770, 0xCCD1, 0x5883, 0xCCD2, 0x5E9A, 0xCCD3, 0x5F91, 0xCCD4, 0x6176, + 0xCCD5, 0x61AC, 0xCCD6, 0x64CE, 0xCCD7, 0x656C, 0xCCD8, 0x666F, 0xCCD9, 0x66BB, 0xCCDA, 0x66F4, 0xCCDB, 0x6897, 0xCCDC, 0x6D87, + 0xCCDD, 0x7085, 0xCCDE, 0x70F1, 0xCCDF, 0x749F, 0xCCE0, 0x74A5, 0xCCE1, 0x74CA, 0xCCE2, 0x75D9, 0xCCE3, 0x786C, 0xCCE4, 0x78EC, + 0xCCE5, 0x7ADF, 0xCCE6, 0x7AF6, 0xCCE7, 0x7D45, 0xCCE8, 0x7D93, 0xCCE9, 0x8015, 0xCCEA, 0x803F, 0xCCEB, 0x811B, 0xCCEC, 0x8396, + 0xCCED, 0x8B66, 0xCCEE, 0x8F15, 0xCCEF, 0x9015, 0xCCF0, 0x93E1, 0xCCF1, 0x9803, 0xCCF2, 0x9838, 0xCCF3, 0x9A5A, 0xCCF4, 0x9BE8, + 0xCCF5, 0x4FC2, 0xCCF6, 0x5553, 0xCCF7, 0x583A, 0xCCF8, 0x5951, 0xCCF9, 0x5B63, 0xCCFA, 0x5C46, 0xCCFB, 0x60B8, 0xCCFC, 0x6212, + 0xCCFD, 0x6842, 0xCCFE, 0x68B0, 0xCDA1, 0x68E8, 0xCDA2, 0x6EAA, 0xCDA3, 0x754C, 0xCDA4, 0x7678, 0xCDA5, 0x78CE, 0xCDA6, 0x7A3D, + 0xCDA7, 0x7CFB, 0xCDA8, 0x7E6B, 0xCDA9, 0x7E7C, 0xCDAA, 0x8A08, 0xCDAB, 0x8AA1, 0xCDAC, 0x8C3F, 0xCDAD, 0x968E, 0xCDAE, 0x9DC4, + 0xCDAF, 0x53E4, 0xCDB0, 0x53E9, 0xCDB1, 0x544A, 0xCDB2, 0x5471, 0xCDB3, 0x56FA, 0xCDB4, 0x59D1, 0xCDB5, 0x5B64, 0xCDB6, 0x5C3B, + 0xCDB7, 0x5EAB, 0xCDB8, 0x62F7, 0xCDB9, 0x6537, 0xCDBA, 0x6545, 0xCDBB, 0x6572, 0xCDBC, 0x66A0, 0xCDBD, 0x67AF, 0xCDBE, 0x69C1, + 0xCDBF, 0x6CBD, 0xCDC0, 0x75FC, 0xCDC1, 0x7690, 0xCDC2, 0x777E, 0xCDC3, 0x7A3F, 0xCDC4, 0x7F94, 0xCDC5, 0x8003, 0xCDC6, 0x80A1, + 0xCDC7, 0x818F, 0xCDC8, 0x82E6, 0xCDC9, 0x82FD, 0xCDCA, 0x83F0, 0xCDCB, 0x85C1, 0xCDCC, 0x8831, 0xCDCD, 0x88B4, 0xCDCE, 0x8AA5, + 0xCDCF, 0xF903, 0xCDD0, 0x8F9C, 0xCDD1, 0x932E, 0xCDD2, 0x96C7, 0xCDD3, 0x9867, 0xCDD4, 0x9AD8, 0xCDD5, 0x9F13, 0xCDD6, 0x54ED, + 0xCDD7, 0x659B, 0xCDD8, 0x66F2, 0xCDD9, 0x688F, 0xCDDA, 0x7A40, 0xCDDB, 0x8C37, 0xCDDC, 0x9D60, 0xCDDD, 0x56F0, 0xCDDE, 0x5764, + 0xCDDF, 0x5D11, 0xCDE0, 0x6606, 0xCDE1, 0x68B1, 0xCDE2, 0x68CD, 0xCDE3, 0x6EFE, 0xCDE4, 0x7428, 0xCDE5, 0x889E, 0xCDE6, 0x9BE4, + 0xCDE7, 0x6C68, 0xCDE8, 0xF904, 0xCDE9, 0x9AA8, 0xCDEA, 0x4F9B, 0xCDEB, 0x516C, 0xCDEC, 0x5171, 0xCDED, 0x529F, 0xCDEE, 0x5B54, + 0xCDEF, 0x5DE5, 0xCDF0, 0x6050, 0xCDF1, 0x606D, 0xCDF2, 0x62F1, 0xCDF3, 0x63A7, 0xCDF4, 0x653B, 0xCDF5, 0x73D9, 0xCDF6, 0x7A7A, + 0xCDF7, 0x86A3, 0xCDF8, 0x8CA2, 0xCDF9, 0x978F, 0xCDFA, 0x4E32, 0xCDFB, 0x5BE1, 0xCDFC, 0x6208, 0xCDFD, 0x679C, 0xCDFE, 0x74DC, + 0xCEA1, 0x79D1, 0xCEA2, 0x83D3, 0xCEA3, 0x8A87, 0xCEA4, 0x8AB2, 0xCEA5, 0x8DE8, 0xCEA6, 0x904E, 0xCEA7, 0x934B, 0xCEA8, 0x9846, + 0xCEA9, 0x5ED3, 0xCEAA, 0x69E8, 0xCEAB, 0x85FF, 0xCEAC, 0x90ED, 0xCEAD, 0xF905, 0xCEAE, 0x51A0, 0xCEAF, 0x5B98, 0xCEB0, 0x5BEC, + 0xCEB1, 0x6163, 0xCEB2, 0x68FA, 0xCEB3, 0x6B3E, 0xCEB4, 0x704C, 0xCEB5, 0x742F, 0xCEB6, 0x74D8, 0xCEB7, 0x7BA1, 0xCEB8, 0x7F50, + 0xCEB9, 0x83C5, 0xCEBA, 0x89C0, 0xCEBB, 0x8CAB, 0xCEBC, 0x95DC, 0xCEBD, 0x9928, 0xCEBE, 0x522E, 0xCEBF, 0x605D, 0xCEC0, 0x62EC, + 0xCEC1, 0x9002, 0xCEC2, 0x4F8A, 0xCEC3, 0x5149, 0xCEC4, 0x5321, 0xCEC5, 0x58D9, 0xCEC6, 0x5EE3, 0xCEC7, 0x66E0, 0xCEC8, 0x6D38, + 0xCEC9, 0x709A, 0xCECA, 0x72C2, 0xCECB, 0x73D6, 0xCECC, 0x7B50, 0xCECD, 0x80F1, 0xCECE, 0x945B, 0xCECF, 0x5366, 0xCED0, 0x639B, + 0xCED1, 0x7F6B, 0xCED2, 0x4E56, 0xCED3, 0x5080, 0xCED4, 0x584A, 0xCED5, 0x58DE, 0xCED6, 0x602A, 0xCED7, 0x6127, 0xCED8, 0x62D0, + 0xCED9, 0x69D0, 0xCEDA, 0x9B41, 0xCEDB, 0x5B8F, 0xCEDC, 0x7D18, 0xCEDD, 0x80B1, 0xCEDE, 0x8F5F, 0xCEDF, 0x4EA4, 0xCEE0, 0x50D1, + 0xCEE1, 0x54AC, 0xCEE2, 0x55AC, 0xCEE3, 0x5B0C, 0xCEE4, 0x5DA0, 0xCEE5, 0x5DE7, 0xCEE6, 0x652A, 0xCEE7, 0x654E, 0xCEE8, 0x6821, + 0xCEE9, 0x6A4B, 0xCEEA, 0x72E1, 0xCEEB, 0x768E, 0xCEEC, 0x77EF, 0xCEED, 0x7D5E, 0xCEEE, 0x7FF9, 0xCEEF, 0x81A0, 0xCEF0, 0x854E, + 0xCEF1, 0x86DF, 0xCEF2, 0x8F03, 0xCEF3, 0x8F4E, 0xCEF4, 0x90CA, 0xCEF5, 0x9903, 0xCEF6, 0x9A55, 0xCEF7, 0x9BAB, 0xCEF8, 0x4E18, + 0xCEF9, 0x4E45, 0xCEFA, 0x4E5D, 0xCEFB, 0x4EC7, 0xCEFC, 0x4FF1, 0xCEFD, 0x5177, 0xCEFE, 0x52FE, 0xCFA1, 0x5340, 0xCFA2, 0x53E3, + 0xCFA3, 0x53E5, 0xCFA4, 0x548E, 0xCFA5, 0x5614, 0xCFA6, 0x5775, 0xCFA7, 0x57A2, 0xCFA8, 0x5BC7, 0xCFA9, 0x5D87, 0xCFAA, 0x5ED0, + 0xCFAB, 0x61FC, 0xCFAC, 0x62D8, 0xCFAD, 0x6551, 0xCFAE, 0x67B8, 0xCFAF, 0x67E9, 0xCFB0, 0x69CB, 0xCFB1, 0x6B50, 0xCFB2, 0x6BC6, + 0xCFB3, 0x6BEC, 0xCFB4, 0x6C42, 0xCFB5, 0x6E9D, 0xCFB6, 0x7078, 0xCFB7, 0x72D7, 0xCFB8, 0x7396, 0xCFB9, 0x7403, 0xCFBA, 0x77BF, + 0xCFBB, 0x77E9, 0xCFBC, 0x7A76, 0xCFBD, 0x7D7F, 0xCFBE, 0x8009, 0xCFBF, 0x81FC, 0xCFC0, 0x8205, 0xCFC1, 0x820A, 0xCFC2, 0x82DF, + 0xCFC3, 0x8862, 0xCFC4, 0x8B33, 0xCFC5, 0x8CFC, 0xCFC6, 0x8EC0, 0xCFC7, 0x9011, 0xCFC8, 0x90B1, 0xCFC9, 0x9264, 0xCFCA, 0x92B6, + 0xCFCB, 0x99D2, 0xCFCC, 0x9A45, 0xCFCD, 0x9CE9, 0xCFCE, 0x9DD7, 0xCFCF, 0x9F9C, 0xCFD0, 0x570B, 0xCFD1, 0x5C40, 0xCFD2, 0x83CA, + 0xCFD3, 0x97A0, 0xCFD4, 0x97AB, 0xCFD5, 0x9EB4, 0xCFD6, 0x541B, 0xCFD7, 0x7A98, 0xCFD8, 0x7FA4, 0xCFD9, 0x88D9, 0xCFDA, 0x8ECD, + 0xCFDB, 0x90E1, 0xCFDC, 0x5800, 0xCFDD, 0x5C48, 0xCFDE, 0x6398, 0xCFDF, 0x7A9F, 0xCFE0, 0x5BAE, 0xCFE1, 0x5F13, 0xCFE2, 0x7A79, + 0xCFE3, 0x7AAE, 0xCFE4, 0x828E, 0xCFE5, 0x8EAC, 0xCFE6, 0x5026, 0xCFE7, 0x5238, 0xCFE8, 0x52F8, 0xCFE9, 0x5377, 0xCFEA, 0x5708, + 0xCFEB, 0x62F3, 0xCFEC, 0x6372, 0xCFED, 0x6B0A, 0xCFEE, 0x6DC3, 0xCFEF, 0x7737, 0xCFF0, 0x53A5, 0xCFF1, 0x7357, 0xCFF2, 0x8568, + 0xCFF3, 0x8E76, 0xCFF4, 0x95D5, 0xCFF5, 0x673A, 0xCFF6, 0x6AC3, 0xCFF7, 0x6F70, 0xCFF8, 0x8A6D, 0xCFF9, 0x8ECC, 0xCFFA, 0x994B, + 0xCFFB, 0xF906, 0xCFFC, 0x6677, 0xCFFD, 0x6B78, 0xCFFE, 0x8CB4, 0xD0A1, 0x9B3C, 0xD0A2, 0xF907, 0xD0A3, 0x53EB, 0xD0A4, 0x572D, + 0xD0A5, 0x594E, 0xD0A6, 0x63C6, 0xD0A7, 0x69FB, 0xD0A8, 0x73EA, 0xD0A9, 0x7845, 0xD0AA, 0x7ABA, 0xD0AB, 0x7AC5, 0xD0AC, 0x7CFE, + 0xD0AD, 0x8475, 0xD0AE, 0x898F, 0xD0AF, 0x8D73, 0xD0B0, 0x9035, 0xD0B1, 0x95A8, 0xD0B2, 0x52FB, 0xD0B3, 0x5747, 0xD0B4, 0x7547, + 0xD0B5, 0x7B60, 0xD0B6, 0x83CC, 0xD0B7, 0x921E, 0xD0B8, 0xF908, 0xD0B9, 0x6A58, 0xD0BA, 0x514B, 0xD0BB, 0x524B, 0xD0BC, 0x5287, + 0xD0BD, 0x621F, 0xD0BE, 0x68D8, 0xD0BF, 0x6975, 0xD0C0, 0x9699, 0xD0C1, 0x50C5, 0xD0C2, 0x52A4, 0xD0C3, 0x52E4, 0xD0C4, 0x61C3, + 0xD0C5, 0x65A4, 0xD0C6, 0x6839, 0xD0C7, 0x69FF, 0xD0C8, 0x747E, 0xD0C9, 0x7B4B, 0xD0CA, 0x82B9, 0xD0CB, 0x83EB, 0xD0CC, 0x89B2, + 0xD0CD, 0x8B39, 0xD0CE, 0x8FD1, 0xD0CF, 0x9949, 0xD0D0, 0xF909, 0xD0D1, 0x4ECA, 0xD0D2, 0x5997, 0xD0D3, 0x64D2, 0xD0D4, 0x6611, + 0xD0D5, 0x6A8E, 0xD0D6, 0x7434, 0xD0D7, 0x7981, 0xD0D8, 0x79BD, 0xD0D9, 0x82A9, 0xD0DA, 0x887E, 0xD0DB, 0x887F, 0xD0DC, 0x895F, + 0xD0DD, 0xF90A, 0xD0DE, 0x9326, 0xD0DF, 0x4F0B, 0xD0E0, 0x53CA, 0xD0E1, 0x6025, 0xD0E2, 0x6271, 0xD0E3, 0x6C72, 0xD0E4, 0x7D1A, + 0xD0E5, 0x7D66, 0xD0E6, 0x4E98, 0xD0E7, 0x5162, 0xD0E8, 0x77DC, 0xD0E9, 0x80AF, 0xD0EA, 0x4F01, 0xD0EB, 0x4F0E, 0xD0EC, 0x5176, + 0xD0ED, 0x5180, 0xD0EE, 0x55DC, 0xD0EF, 0x5668, 0xD0F0, 0x573B, 0xD0F1, 0x57FA, 0xD0F2, 0x57FC, 0xD0F3, 0x5914, 0xD0F4, 0x5947, + 0xD0F5, 0x5993, 0xD0F6, 0x5BC4, 0xD0F7, 0x5C90, 0xD0F8, 0x5D0E, 0xD0F9, 0x5DF1, 0xD0FA, 0x5E7E, 0xD0FB, 0x5FCC, 0xD0FC, 0x6280, + 0xD0FD, 0x65D7, 0xD0FE, 0x65E3, 0xD1A1, 0x671E, 0xD1A2, 0x671F, 0xD1A3, 0x675E, 0xD1A4, 0x68CB, 0xD1A5, 0x68C4, 0xD1A6, 0x6A5F, + 0xD1A7, 0x6B3A, 0xD1A8, 0x6C23, 0xD1A9, 0x6C7D, 0xD1AA, 0x6C82, 0xD1AB, 0x6DC7, 0xD1AC, 0x7398, 0xD1AD, 0x7426, 0xD1AE, 0x742A, + 0xD1AF, 0x7482, 0xD1B0, 0x74A3, 0xD1B1, 0x7578, 0xD1B2, 0x757F, 0xD1B3, 0x7881, 0xD1B4, 0x78EF, 0xD1B5, 0x7941, 0xD1B6, 0x7947, + 0xD1B7, 0x7948, 0xD1B8, 0x797A, 0xD1B9, 0x7B95, 0xD1BA, 0x7D00, 0xD1BB, 0x7DBA, 0xD1BC, 0x7F88, 0xD1BD, 0x8006, 0xD1BE, 0x802D, + 0xD1BF, 0x808C, 0xD1C0, 0x8A18, 0xD1C1, 0x8B4F, 0xD1C2, 0x8C48, 0xD1C3, 0x8D77, 0xD1C4, 0x9321, 0xD1C5, 0x9324, 0xD1C6, 0x98E2, + 0xD1C7, 0x9951, 0xD1C8, 0x9A0E, 0xD1C9, 0x9A0F, 0xD1CA, 0x9A65, 0xD1CB, 0x9E92, 0xD1CC, 0x7DCA, 0xD1CD, 0x4F76, 0xD1CE, 0x5409, + 0xD1CF, 0x62EE, 0xD1D0, 0x6854, 0xD1D1, 0x91D1, 0xD1D2, 0x55AB, 0xD1D3, 0x513A, 0xD1D4, 0xF90B, 0xD1D5, 0xF90C, 0xD1D6, 0x5A1C, + 0xD1D7, 0x61E6, 0xD1D8, 0xF90D, 0xD1D9, 0x62CF, 0xD1DA, 0x62FF, 0xD1DB, 0xF90E, 0xD1DC, 0xF90F, 0xD1DD, 0xF910, 0xD1DE, 0xF911, + 0xD1DF, 0xF912, 0xD1E0, 0xF913, 0xD1E1, 0x90A3, 0xD1E2, 0xF914, 0xD1E3, 0xF915, 0xD1E4, 0xF916, 0xD1E5, 0xF917, 0xD1E6, 0xF918, + 0xD1E7, 0x8AFE, 0xD1E8, 0xF919, 0xD1E9, 0xF91A, 0xD1EA, 0xF91B, 0xD1EB, 0xF91C, 0xD1EC, 0x6696, 0xD1ED, 0xF91D, 0xD1EE, 0x7156, + 0xD1EF, 0xF91E, 0xD1F0, 0xF91F, 0xD1F1, 0x96E3, 0xD1F2, 0xF920, 0xD1F3, 0x634F, 0xD1F4, 0x637A, 0xD1F5, 0x5357, 0xD1F6, 0xF921, + 0xD1F7, 0x678F, 0xD1F8, 0x6960, 0xD1F9, 0x6E73, 0xD1FA, 0xF922, 0xD1FB, 0x7537, 0xD1FC, 0xF923, 0xD1FD, 0xF924, 0xD1FE, 0xF925, + 0xD2A1, 0x7D0D, 0xD2A2, 0xF926, 0xD2A3, 0xF927, 0xD2A4, 0x8872, 0xD2A5, 0x56CA, 0xD2A6, 0x5A18, 0xD2A7, 0xF928, 0xD2A8, 0xF929, + 0xD2A9, 0xF92A, 0xD2AA, 0xF92B, 0xD2AB, 0xF92C, 0xD2AC, 0x4E43, 0xD2AD, 0xF92D, 0xD2AE, 0x5167, 0xD2AF, 0x5948, 0xD2B0, 0x67F0, + 0xD2B1, 0x8010, 0xD2B2, 0xF92E, 0xD2B3, 0x5973, 0xD2B4, 0x5E74, 0xD2B5, 0x649A, 0xD2B6, 0x79CA, 0xD2B7, 0x5FF5, 0xD2B8, 0x606C, + 0xD2B9, 0x62C8, 0xD2BA, 0x637B, 0xD2BB, 0x5BE7, 0xD2BC, 0x5BD7, 0xD2BD, 0x52AA, 0xD2BE, 0xF92F, 0xD2BF, 0x5974, 0xD2C0, 0x5F29, + 0xD2C1, 0x6012, 0xD2C2, 0xF930, 0xD2C3, 0xF931, 0xD2C4, 0xF932, 0xD2C5, 0x7459, 0xD2C6, 0xF933, 0xD2C7, 0xF934, 0xD2C8, 0xF935, + 0xD2C9, 0xF936, 0xD2CA, 0xF937, 0xD2CB, 0xF938, 0xD2CC, 0x99D1, 0xD2CD, 0xF939, 0xD2CE, 0xF93A, 0xD2CF, 0xF93B, 0xD2D0, 0xF93C, + 0xD2D1, 0xF93D, 0xD2D2, 0xF93E, 0xD2D3, 0xF93F, 0xD2D4, 0xF940, 0xD2D5, 0xF941, 0xD2D6, 0xF942, 0xD2D7, 0xF943, 0xD2D8, 0x6FC3, + 0xD2D9, 0xF944, 0xD2DA, 0xF945, 0xD2DB, 0x81BF, 0xD2DC, 0x8FB2, 0xD2DD, 0x60F1, 0xD2DE, 0xF946, 0xD2DF, 0xF947, 0xD2E0, 0x8166, + 0xD2E1, 0xF948, 0xD2E2, 0xF949, 0xD2E3, 0x5C3F, 0xD2E4, 0xF94A, 0xD2E5, 0xF94B, 0xD2E6, 0xF94C, 0xD2E7, 0xF94D, 0xD2E8, 0xF94E, + 0xD2E9, 0xF94F, 0xD2EA, 0xF950, 0xD2EB, 0xF951, 0xD2EC, 0x5AE9, 0xD2ED, 0x8A25, 0xD2EE, 0x677B, 0xD2EF, 0x7D10, 0xD2F0, 0xF952, + 0xD2F1, 0xF953, 0xD2F2, 0xF954, 0xD2F3, 0xF955, 0xD2F4, 0xF956, 0xD2F5, 0xF957, 0xD2F6, 0x80FD, 0xD2F7, 0xF958, 0xD2F8, 0xF959, + 0xD2F9, 0x5C3C, 0xD2FA, 0x6CE5, 0xD2FB, 0x533F, 0xD2FC, 0x6EBA, 0xD2FD, 0x591A, 0xD2FE, 0x8336, 0xD3A1, 0x4E39, 0xD3A2, 0x4EB6, + 0xD3A3, 0x4F46, 0xD3A4, 0x55AE, 0xD3A5, 0x5718, 0xD3A6, 0x58C7, 0xD3A7, 0x5F56, 0xD3A8, 0x65B7, 0xD3A9, 0x65E6, 0xD3AA, 0x6A80, + 0xD3AB, 0x6BB5, 0xD3AC, 0x6E4D, 0xD3AD, 0x77ED, 0xD3AE, 0x7AEF, 0xD3AF, 0x7C1E, 0xD3B0, 0x7DDE, 0xD3B1, 0x86CB, 0xD3B2, 0x8892, + 0xD3B3, 0x9132, 0xD3B4, 0x935B, 0xD3B5, 0x64BB, 0xD3B6, 0x6FBE, 0xD3B7, 0x737A, 0xD3B8, 0x75B8, 0xD3B9, 0x9054, 0xD3BA, 0x5556, + 0xD3BB, 0x574D, 0xD3BC, 0x61BA, 0xD3BD, 0x64D4, 0xD3BE, 0x66C7, 0xD3BF, 0x6DE1, 0xD3C0, 0x6E5B, 0xD3C1, 0x6F6D, 0xD3C2, 0x6FB9, + 0xD3C3, 0x75F0, 0xD3C4, 0x8043, 0xD3C5, 0x81BD, 0xD3C6, 0x8541, 0xD3C7, 0x8983, 0xD3C8, 0x8AC7, 0xD3C9, 0x8B5A, 0xD3CA, 0x931F, + 0xD3CB, 0x6C93, 0xD3CC, 0x7553, 0xD3CD, 0x7B54, 0xD3CE, 0x8E0F, 0xD3CF, 0x905D, 0xD3D0, 0x5510, 0xD3D1, 0x5802, 0xD3D2, 0x5858, + 0xD3D3, 0x5E62, 0xD3D4, 0x6207, 0xD3D5, 0x649E, 0xD3D6, 0x68E0, 0xD3D7, 0x7576, 0xD3D8, 0x7CD6, 0xD3D9, 0x87B3, 0xD3DA, 0x9EE8, + 0xD3DB, 0x4EE3, 0xD3DC, 0x5788, 0xD3DD, 0x576E, 0xD3DE, 0x5927, 0xD3DF, 0x5C0D, 0xD3E0, 0x5CB1, 0xD3E1, 0x5E36, 0xD3E2, 0x5F85, + 0xD3E3, 0x6234, 0xD3E4, 0x64E1, 0xD3E5, 0x73B3, 0xD3E6, 0x81FA, 0xD3E7, 0x888B, 0xD3E8, 0x8CB8, 0xD3E9, 0x968A, 0xD3EA, 0x9EDB, + 0xD3EB, 0x5B85, 0xD3EC, 0x5FB7, 0xD3ED, 0x60B3, 0xD3EE, 0x5012, 0xD3EF, 0x5200, 0xD3F0, 0x5230, 0xD3F1, 0x5716, 0xD3F2, 0x5835, + 0xD3F3, 0x5857, 0xD3F4, 0x5C0E, 0xD3F5, 0x5C60, 0xD3F6, 0x5CF6, 0xD3F7, 0x5D8B, 0xD3F8, 0x5EA6, 0xD3F9, 0x5F92, 0xD3FA, 0x60BC, + 0xD3FB, 0x6311, 0xD3FC, 0x6389, 0xD3FD, 0x6417, 0xD3FE, 0x6843, 0xD4A1, 0x68F9, 0xD4A2, 0x6AC2, 0xD4A3, 0x6DD8, 0xD4A4, 0x6E21, + 0xD4A5, 0x6ED4, 0xD4A6, 0x6FE4, 0xD4A7, 0x71FE, 0xD4A8, 0x76DC, 0xD4A9, 0x7779, 0xD4AA, 0x79B1, 0xD4AB, 0x7A3B, 0xD4AC, 0x8404, + 0xD4AD, 0x89A9, 0xD4AE, 0x8CED, 0xD4AF, 0x8DF3, 0xD4B0, 0x8E48, 0xD4B1, 0x9003, 0xD4B2, 0x9014, 0xD4B3, 0x9053, 0xD4B4, 0x90FD, + 0xD4B5, 0x934D, 0xD4B6, 0x9676, 0xD4B7, 0x97DC, 0xD4B8, 0x6BD2, 0xD4B9, 0x7006, 0xD4BA, 0x7258, 0xD4BB, 0x72A2, 0xD4BC, 0x7368, + 0xD4BD, 0x7763, 0xD4BE, 0x79BF, 0xD4BF, 0x7BE4, 0xD4C0, 0x7E9B, 0xD4C1, 0x8B80, 0xD4C2, 0x58A9, 0xD4C3, 0x60C7, 0xD4C4, 0x6566, + 0xD4C5, 0x65FD, 0xD4C6, 0x66BE, 0xD4C7, 0x6C8C, 0xD4C8, 0x711E, 0xD4C9, 0x71C9, 0xD4CA, 0x8C5A, 0xD4CB, 0x9813, 0xD4CC, 0x4E6D, + 0xD4CD, 0x7A81, 0xD4CE, 0x4EDD, 0xD4CF, 0x51AC, 0xD4D0, 0x51CD, 0xD4D1, 0x52D5, 0xD4D2, 0x540C, 0xD4D3, 0x61A7, 0xD4D4, 0x6771, + 0xD4D5, 0x6850, 0xD4D6, 0x68DF, 0xD4D7, 0x6D1E, 0xD4D8, 0x6F7C, 0xD4D9, 0x75BC, 0xD4DA, 0x77B3, 0xD4DB, 0x7AE5, 0xD4DC, 0x80F4, + 0xD4DD, 0x8463, 0xD4DE, 0x9285, 0xD4DF, 0x515C, 0xD4E0, 0x6597, 0xD4E1, 0x675C, 0xD4E2, 0x6793, 0xD4E3, 0x75D8, 0xD4E4, 0x7AC7, + 0xD4E5, 0x8373, 0xD4E6, 0xF95A, 0xD4E7, 0x8C46, 0xD4E8, 0x9017, 0xD4E9, 0x982D, 0xD4EA, 0x5C6F, 0xD4EB, 0x81C0, 0xD4EC, 0x829A, + 0xD4ED, 0x9041, 0xD4EE, 0x906F, 0xD4EF, 0x920D, 0xD4F0, 0x5F97, 0xD4F1, 0x5D9D, 0xD4F2, 0x6A59, 0xD4F3, 0x71C8, 0xD4F4, 0x767B, + 0xD4F5, 0x7B49, 0xD4F6, 0x85E4, 0xD4F7, 0x8B04, 0xD4F8, 0x9127, 0xD4F9, 0x9A30, 0xD4FA, 0x5587, 0xD4FB, 0x61F6, 0xD4FC, 0xF95B, + 0xD4FD, 0x7669, 0xD4FE, 0x7F85, 0xD5A1, 0x863F, 0xD5A2, 0x87BA, 0xD5A3, 0x88F8, 0xD5A4, 0x908F, 0xD5A5, 0xF95C, 0xD5A6, 0x6D1B, + 0xD5A7, 0x70D9, 0xD5A8, 0x73DE, 0xD5A9, 0x7D61, 0xD5AA, 0x843D, 0xD5AB, 0xF95D, 0xD5AC, 0x916A, 0xD5AD, 0x99F1, 0xD5AE, 0xF95E, + 0xD5AF, 0x4E82, 0xD5B0, 0x5375, 0xD5B1, 0x6B04, 0xD5B2, 0x6B12, 0xD5B3, 0x703E, 0xD5B4, 0x721B, 0xD5B5, 0x862D, 0xD5B6, 0x9E1E, + 0xD5B7, 0x524C, 0xD5B8, 0x8FA3, 0xD5B9, 0x5D50, 0xD5BA, 0x64E5, 0xD5BB, 0x652C, 0xD5BC, 0x6B16, 0xD5BD, 0x6FEB, 0xD5BE, 0x7C43, + 0xD5BF, 0x7E9C, 0xD5C0, 0x85CD, 0xD5C1, 0x8964, 0xD5C2, 0x89BD, 0xD5C3, 0x62C9, 0xD5C4, 0x81D8, 0xD5C5, 0x881F, 0xD5C6, 0x5ECA, + 0xD5C7, 0x6717, 0xD5C8, 0x6D6A, 0xD5C9, 0x72FC, 0xD5CA, 0x7405, 0xD5CB, 0x746F, 0xD5CC, 0x8782, 0xD5CD, 0x90DE, 0xD5CE, 0x4F86, + 0xD5CF, 0x5D0D, 0xD5D0, 0x5FA0, 0xD5D1, 0x840A, 0xD5D2, 0x51B7, 0xD5D3, 0x63A0, 0xD5D4, 0x7565, 0xD5D5, 0x4EAE, 0xD5D6, 0x5006, + 0xD5D7, 0x5169, 0xD5D8, 0x51C9, 0xD5D9, 0x6881, 0xD5DA, 0x6A11, 0xD5DB, 0x7CAE, 0xD5DC, 0x7CB1, 0xD5DD, 0x7CE7, 0xD5DE, 0x826F, + 0xD5DF, 0x8AD2, 0xD5E0, 0x8F1B, 0xD5E1, 0x91CF, 0xD5E2, 0x4FB6, 0xD5E3, 0x5137, 0xD5E4, 0x52F5, 0xD5E5, 0x5442, 0xD5E6, 0x5EEC, + 0xD5E7, 0x616E, 0xD5E8, 0x623E, 0xD5E9, 0x65C5, 0xD5EA, 0x6ADA, 0xD5EB, 0x6FFE, 0xD5EC, 0x792A, 0xD5ED, 0x85DC, 0xD5EE, 0x8823, + 0xD5EF, 0x95AD, 0xD5F0, 0x9A62, 0xD5F1, 0x9A6A, 0xD5F2, 0x9E97, 0xD5F3, 0x9ECE, 0xD5F4, 0x529B, 0xD5F5, 0x66C6, 0xD5F6, 0x6B77, + 0xD5F7, 0x701D, 0xD5F8, 0x792B, 0xD5F9, 0x8F62, 0xD5FA, 0x9742, 0xD5FB, 0x6190, 0xD5FC, 0x6200, 0xD5FD, 0x6523, 0xD5FE, 0x6F23, + 0xD6A1, 0x7149, 0xD6A2, 0x7489, 0xD6A3, 0x7DF4, 0xD6A4, 0x806F, 0xD6A5, 0x84EE, 0xD6A6, 0x8F26, 0xD6A7, 0x9023, 0xD6A8, 0x934A, + 0xD6A9, 0x51BD, 0xD6AA, 0x5217, 0xD6AB, 0x52A3, 0xD6AC, 0x6D0C, 0xD6AD, 0x70C8, 0xD6AE, 0x88C2, 0xD6AF, 0x5EC9, 0xD6B0, 0x6582, + 0xD6B1, 0x6BAE, 0xD6B2, 0x6FC2, 0xD6B3, 0x7C3E, 0xD6B4, 0x7375, 0xD6B5, 0x4EE4, 0xD6B6, 0x4F36, 0xD6B7, 0x56F9, 0xD6B8, 0xF95F, + 0xD6B9, 0x5CBA, 0xD6BA, 0x5DBA, 0xD6BB, 0x601C, 0xD6BC, 0x73B2, 0xD6BD, 0x7B2D, 0xD6BE, 0x7F9A, 0xD6BF, 0x7FCE, 0xD6C0, 0x8046, + 0xD6C1, 0x901E, 0xD6C2, 0x9234, 0xD6C3, 0x96F6, 0xD6C4, 0x9748, 0xD6C5, 0x9818, 0xD6C6, 0x9F61, 0xD6C7, 0x4F8B, 0xD6C8, 0x6FA7, + 0xD6C9, 0x79AE, 0xD6CA, 0x91B4, 0xD6CB, 0x96B7, 0xD6CC, 0x52DE, 0xD6CD, 0xF960, 0xD6CE, 0x6488, 0xD6CF, 0x64C4, 0xD6D0, 0x6AD3, + 0xD6D1, 0x6F5E, 0xD6D2, 0x7018, 0xD6D3, 0x7210, 0xD6D4, 0x76E7, 0xD6D5, 0x8001, 0xD6D6, 0x8606, 0xD6D7, 0x865C, 0xD6D8, 0x8DEF, + 0xD6D9, 0x8F05, 0xD6DA, 0x9732, 0xD6DB, 0x9B6F, 0xD6DC, 0x9DFA, 0xD6DD, 0x9E75, 0xD6DE, 0x788C, 0xD6DF, 0x797F, 0xD6E0, 0x7DA0, + 0xD6E1, 0x83C9, 0xD6E2, 0x9304, 0xD6E3, 0x9E7F, 0xD6E4, 0x9E93, 0xD6E5, 0x8AD6, 0xD6E6, 0x58DF, 0xD6E7, 0x5F04, 0xD6E8, 0x6727, + 0xD6E9, 0x7027, 0xD6EA, 0x74CF, 0xD6EB, 0x7C60, 0xD6EC, 0x807E, 0xD6ED, 0x5121, 0xD6EE, 0x7028, 0xD6EF, 0x7262, 0xD6F0, 0x78CA, + 0xD6F1, 0x8CC2, 0xD6F2, 0x8CDA, 0xD6F3, 0x8CF4, 0xD6F4, 0x96F7, 0xD6F5, 0x4E86, 0xD6F6, 0x50DA, 0xD6F7, 0x5BEE, 0xD6F8, 0x5ED6, + 0xD6F9, 0x6599, 0xD6FA, 0x71CE, 0xD6FB, 0x7642, 0xD6FC, 0x77AD, 0xD6FD, 0x804A, 0xD6FE, 0x84FC, 0xD7A1, 0x907C, 0xD7A2, 0x9B27, + 0xD7A3, 0x9F8D, 0xD7A4, 0x58D8, 0xD7A5, 0x5A41, 0xD7A6, 0x5C62, 0xD7A7, 0x6A13, 0xD7A8, 0x6DDA, 0xD7A9, 0x6F0F, 0xD7AA, 0x763B, + 0xD7AB, 0x7D2F, 0xD7AC, 0x7E37, 0xD7AD, 0x851E, 0xD7AE, 0x8938, 0xD7AF, 0x93E4, 0xD7B0, 0x964B, 0xD7B1, 0x5289, 0xD7B2, 0x65D2, + 0xD7B3, 0x67F3, 0xD7B4, 0x69B4, 0xD7B5, 0x6D41, 0xD7B6, 0x6E9C, 0xD7B7, 0x700F, 0xD7B8, 0x7409, 0xD7B9, 0x7460, 0xD7BA, 0x7559, + 0xD7BB, 0x7624, 0xD7BC, 0x786B, 0xD7BD, 0x8B2C, 0xD7BE, 0x985E, 0xD7BF, 0x516D, 0xD7C0, 0x622E, 0xD7C1, 0x9678, 0xD7C2, 0x4F96, + 0xD7C3, 0x502B, 0xD7C4, 0x5D19, 0xD7C5, 0x6DEA, 0xD7C6, 0x7DB8, 0xD7C7, 0x8F2A, 0xD7C8, 0x5F8B, 0xD7C9, 0x6144, 0xD7CA, 0x6817, + 0xD7CB, 0xF961, 0xD7CC, 0x9686, 0xD7CD, 0x52D2, 0xD7CE, 0x808B, 0xD7CF, 0x51DC, 0xD7D0, 0x51CC, 0xD7D1, 0x695E, 0xD7D2, 0x7A1C, + 0xD7D3, 0x7DBE, 0xD7D4, 0x83F1, 0xD7D5, 0x9675, 0xD7D6, 0x4FDA, 0xD7D7, 0x5229, 0xD7D8, 0x5398, 0xD7D9, 0x540F, 0xD7DA, 0x550E, + 0xD7DB, 0x5C65, 0xD7DC, 0x60A7, 0xD7DD, 0x674E, 0xD7DE, 0x68A8, 0xD7DF, 0x6D6C, 0xD7E0, 0x7281, 0xD7E1, 0x72F8, 0xD7E2, 0x7406, + 0xD7E3, 0x7483, 0xD7E4, 0xF962, 0xD7E5, 0x75E2, 0xD7E6, 0x7C6C, 0xD7E7, 0x7F79, 0xD7E8, 0x7FB8, 0xD7E9, 0x8389, 0xD7EA, 0x88CF, + 0xD7EB, 0x88E1, 0xD7EC, 0x91CC, 0xD7ED, 0x91D0, 0xD7EE, 0x96E2, 0xD7EF, 0x9BC9, 0xD7F0, 0x541D, 0xD7F1, 0x6F7E, 0xD7F2, 0x71D0, + 0xD7F3, 0x7498, 0xD7F4, 0x85FA, 0xD7F5, 0x8EAA, 0xD7F6, 0x96A3, 0xD7F7, 0x9C57, 0xD7F8, 0x9E9F, 0xD7F9, 0x6797, 0xD7FA, 0x6DCB, + 0xD7FB, 0x7433, 0xD7FC, 0x81E8, 0xD7FD, 0x9716, 0xD7FE, 0x782C, 0xD8A1, 0x7ACB, 0xD8A2, 0x7B20, 0xD8A3, 0x7C92, 0xD8A4, 0x6469, + 0xD8A5, 0x746A, 0xD8A6, 0x75F2, 0xD8A7, 0x78BC, 0xD8A8, 0x78E8, 0xD8A9, 0x99AC, 0xD8AA, 0x9B54, 0xD8AB, 0x9EBB, 0xD8AC, 0x5BDE, + 0xD8AD, 0x5E55, 0xD8AE, 0x6F20, 0xD8AF, 0x819C, 0xD8B0, 0x83AB, 0xD8B1, 0x9088, 0xD8B2, 0x4E07, 0xD8B3, 0x534D, 0xD8B4, 0x5A29, + 0xD8B5, 0x5DD2, 0xD8B6, 0x5F4E, 0xD8B7, 0x6162, 0xD8B8, 0x633D, 0xD8B9, 0x6669, 0xD8BA, 0x66FC, 0xD8BB, 0x6EFF, 0xD8BC, 0x6F2B, + 0xD8BD, 0x7063, 0xD8BE, 0x779E, 0xD8BF, 0x842C, 0xD8C0, 0x8513, 0xD8C1, 0x883B, 0xD8C2, 0x8F13, 0xD8C3, 0x9945, 0xD8C4, 0x9C3B, + 0xD8C5, 0x551C, 0xD8C6, 0x62B9, 0xD8C7, 0x672B, 0xD8C8, 0x6CAB, 0xD8C9, 0x8309, 0xD8CA, 0x896A, 0xD8CB, 0x977A, 0xD8CC, 0x4EA1, + 0xD8CD, 0x5984, 0xD8CE, 0x5FD8, 0xD8CF, 0x5FD9, 0xD8D0, 0x671B, 0xD8D1, 0x7DB2, 0xD8D2, 0x7F54, 0xD8D3, 0x8292, 0xD8D4, 0x832B, + 0xD8D5, 0x83BD, 0xD8D6, 0x8F1E, 0xD8D7, 0x9099, 0xD8D8, 0x57CB, 0xD8D9, 0x59B9, 0xD8DA, 0x5A92, 0xD8DB, 0x5BD0, 0xD8DC, 0x6627, + 0xD8DD, 0x679A, 0xD8DE, 0x6885, 0xD8DF, 0x6BCF, 0xD8E0, 0x7164, 0xD8E1, 0x7F75, 0xD8E2, 0x8CB7, 0xD8E3, 0x8CE3, 0xD8E4, 0x9081, + 0xD8E5, 0x9B45, 0xD8E6, 0x8108, 0xD8E7, 0x8C8A, 0xD8E8, 0x964C, 0xD8E9, 0x9A40, 0xD8EA, 0x9EA5, 0xD8EB, 0x5B5F, 0xD8EC, 0x6C13, + 0xD8ED, 0x731B, 0xD8EE, 0x76F2, 0xD8EF, 0x76DF, 0xD8F0, 0x840C, 0xD8F1, 0x51AA, 0xD8F2, 0x8993, 0xD8F3, 0x514D, 0xD8F4, 0x5195, + 0xD8F5, 0x52C9, 0xD8F6, 0x68C9, 0xD8F7, 0x6C94, 0xD8F8, 0x7704, 0xD8F9, 0x7720, 0xD8FA, 0x7DBF, 0xD8FB, 0x7DEC, 0xD8FC, 0x9762, + 0xD8FD, 0x9EB5, 0xD8FE, 0x6EC5, 0xD9A1, 0x8511, 0xD9A2, 0x51A5, 0xD9A3, 0x540D, 0xD9A4, 0x547D, 0xD9A5, 0x660E, 0xD9A6, 0x669D, + 0xD9A7, 0x6927, 0xD9A8, 0x6E9F, 0xD9A9, 0x76BF, 0xD9AA, 0x7791, 0xD9AB, 0x8317, 0xD9AC, 0x84C2, 0xD9AD, 0x879F, 0xD9AE, 0x9169, + 0xD9AF, 0x9298, 0xD9B0, 0x9CF4, 0xD9B1, 0x8882, 0xD9B2, 0x4FAE, 0xD9B3, 0x5192, 0xD9B4, 0x52DF, 0xD9B5, 0x59C6, 0xD9B6, 0x5E3D, + 0xD9B7, 0x6155, 0xD9B8, 0x6478, 0xD9B9, 0x6479, 0xD9BA, 0x66AE, 0xD9BB, 0x67D0, 0xD9BC, 0x6A21, 0xD9BD, 0x6BCD, 0xD9BE, 0x6BDB, + 0xD9BF, 0x725F, 0xD9C0, 0x7261, 0xD9C1, 0x7441, 0xD9C2, 0x7738, 0xD9C3, 0x77DB, 0xD9C4, 0x8017, 0xD9C5, 0x82BC, 0xD9C6, 0x8305, + 0xD9C7, 0x8B00, 0xD9C8, 0x8B28, 0xD9C9, 0x8C8C, 0xD9CA, 0x6728, 0xD9CB, 0x6C90, 0xD9CC, 0x7267, 0xD9CD, 0x76EE, 0xD9CE, 0x7766, + 0xD9CF, 0x7A46, 0xD9D0, 0x9DA9, 0xD9D1, 0x6B7F, 0xD9D2, 0x6C92, 0xD9D3, 0x5922, 0xD9D4, 0x6726, 0xD9D5, 0x8499, 0xD9D6, 0x536F, + 0xD9D7, 0x5893, 0xD9D8, 0x5999, 0xD9D9, 0x5EDF, 0xD9DA, 0x63CF, 0xD9DB, 0x6634, 0xD9DC, 0x6773, 0xD9DD, 0x6E3A, 0xD9DE, 0x732B, + 0xD9DF, 0x7AD7, 0xD9E0, 0x82D7, 0xD9E1, 0x9328, 0xD9E2, 0x52D9, 0xD9E3, 0x5DEB, 0xD9E4, 0x61AE, 0xD9E5, 0x61CB, 0xD9E6, 0x620A, + 0xD9E7, 0x62C7, 0xD9E8, 0x64AB, 0xD9E9, 0x65E0, 0xD9EA, 0x6959, 0xD9EB, 0x6B66, 0xD9EC, 0x6BCB, 0xD9ED, 0x7121, 0xD9EE, 0x73F7, + 0xD9EF, 0x755D, 0xD9F0, 0x7E46, 0xD9F1, 0x821E, 0xD9F2, 0x8302, 0xD9F3, 0x856A, 0xD9F4, 0x8AA3, 0xD9F5, 0x8CBF, 0xD9F6, 0x9727, + 0xD9F7, 0x9D61, 0xD9F8, 0x58A8, 0xD9F9, 0x9ED8, 0xD9FA, 0x5011, 0xD9FB, 0x520E, 0xD9FC, 0x543B, 0xD9FD, 0x554F, 0xD9FE, 0x6587, + 0xDAA1, 0x6C76, 0xDAA2, 0x7D0A, 0xDAA3, 0x7D0B, 0xDAA4, 0x805E, 0xDAA5, 0x868A, 0xDAA6, 0x9580, 0xDAA7, 0x96EF, 0xDAA8, 0x52FF, + 0xDAA9, 0x6C95, 0xDAAA, 0x7269, 0xDAAB, 0x5473, 0xDAAC, 0x5A9A, 0xDAAD, 0x5C3E, 0xDAAE, 0x5D4B, 0xDAAF, 0x5F4C, 0xDAB0, 0x5FAE, + 0xDAB1, 0x672A, 0xDAB2, 0x68B6, 0xDAB3, 0x6963, 0xDAB4, 0x6E3C, 0xDAB5, 0x6E44, 0xDAB6, 0x7709, 0xDAB7, 0x7C73, 0xDAB8, 0x7F8E, + 0xDAB9, 0x8587, 0xDABA, 0x8B0E, 0xDABB, 0x8FF7, 0xDABC, 0x9761, 0xDABD, 0x9EF4, 0xDABE, 0x5CB7, 0xDABF, 0x60B6, 0xDAC0, 0x610D, + 0xDAC1, 0x61AB, 0xDAC2, 0x654F, 0xDAC3, 0x65FB, 0xDAC4, 0x65FC, 0xDAC5, 0x6C11, 0xDAC6, 0x6CEF, 0xDAC7, 0x739F, 0xDAC8, 0x73C9, + 0xDAC9, 0x7DE1, 0xDACA, 0x9594, 0xDACB, 0x5BC6, 0xDACC, 0x871C, 0xDACD, 0x8B10, 0xDACE, 0x525D, 0xDACF, 0x535A, 0xDAD0, 0x62CD, + 0xDAD1, 0x640F, 0xDAD2, 0x64B2, 0xDAD3, 0x6734, 0xDAD4, 0x6A38, 0xDAD5, 0x6CCA, 0xDAD6, 0x73C0, 0xDAD7, 0x749E, 0xDAD8, 0x7B94, + 0xDAD9, 0x7C95, 0xDADA, 0x7E1B, 0xDADB, 0x818A, 0xDADC, 0x8236, 0xDADD, 0x8584, 0xDADE, 0x8FEB, 0xDADF, 0x96F9, 0xDAE0, 0x99C1, + 0xDAE1, 0x4F34, 0xDAE2, 0x534A, 0xDAE3, 0x53CD, 0xDAE4, 0x53DB, 0xDAE5, 0x62CC, 0xDAE6, 0x642C, 0xDAE7, 0x6500, 0xDAE8, 0x6591, + 0xDAE9, 0x69C3, 0xDAEA, 0x6CEE, 0xDAEB, 0x6F58, 0xDAEC, 0x73ED, 0xDAED, 0x7554, 0xDAEE, 0x7622, 0xDAEF, 0x76E4, 0xDAF0, 0x76FC, + 0xDAF1, 0x78D0, 0xDAF2, 0x78FB, 0xDAF3, 0x792C, 0xDAF4, 0x7D46, 0xDAF5, 0x822C, 0xDAF6, 0x87E0, 0xDAF7, 0x8FD4, 0xDAF8, 0x9812, + 0xDAF9, 0x98EF, 0xDAFA, 0x52C3, 0xDAFB, 0x62D4, 0xDAFC, 0x64A5, 0xDAFD, 0x6E24, 0xDAFE, 0x6F51, 0xDBA1, 0x767C, 0xDBA2, 0x8DCB, + 0xDBA3, 0x91B1, 0xDBA4, 0x9262, 0xDBA5, 0x9AEE, 0xDBA6, 0x9B43, 0xDBA7, 0x5023, 0xDBA8, 0x508D, 0xDBA9, 0x574A, 0xDBAA, 0x59A8, + 0xDBAB, 0x5C28, 0xDBAC, 0x5E47, 0xDBAD, 0x5F77, 0xDBAE, 0x623F, 0xDBAF, 0x653E, 0xDBB0, 0x65B9, 0xDBB1, 0x65C1, 0xDBB2, 0x6609, + 0xDBB3, 0x678B, 0xDBB4, 0x699C, 0xDBB5, 0x6EC2, 0xDBB6, 0x78C5, 0xDBB7, 0x7D21, 0xDBB8, 0x80AA, 0xDBB9, 0x8180, 0xDBBA, 0x822B, + 0xDBBB, 0x82B3, 0xDBBC, 0x84A1, 0xDBBD, 0x868C, 0xDBBE, 0x8A2A, 0xDBBF, 0x8B17, 0xDBC0, 0x90A6, 0xDBC1, 0x9632, 0xDBC2, 0x9F90, + 0xDBC3, 0x500D, 0xDBC4, 0x4FF3, 0xDBC5, 0xF963, 0xDBC6, 0x57F9, 0xDBC7, 0x5F98, 0xDBC8, 0x62DC, 0xDBC9, 0x6392, 0xDBCA, 0x676F, + 0xDBCB, 0x6E43, 0xDBCC, 0x7119, 0xDBCD, 0x76C3, 0xDBCE, 0x80CC, 0xDBCF, 0x80DA, 0xDBD0, 0x88F4, 0xDBD1, 0x88F5, 0xDBD2, 0x8919, + 0xDBD3, 0x8CE0, 0xDBD4, 0x8F29, 0xDBD5, 0x914D, 0xDBD6, 0x966A, 0xDBD7, 0x4F2F, 0xDBD8, 0x4F70, 0xDBD9, 0x5E1B, 0xDBDA, 0x67CF, + 0xDBDB, 0x6822, 0xDBDC, 0x767D, 0xDBDD, 0x767E, 0xDBDE, 0x9B44, 0xDBDF, 0x5E61, 0xDBE0, 0x6A0A, 0xDBE1, 0x7169, 0xDBE2, 0x71D4, + 0xDBE3, 0x756A, 0xDBE4, 0xF964, 0xDBE5, 0x7E41, 0xDBE6, 0x8543, 0xDBE7, 0x85E9, 0xDBE8, 0x98DC, 0xDBE9, 0x4F10, 0xDBEA, 0x7B4F, + 0xDBEB, 0x7F70, 0xDBEC, 0x95A5, 0xDBED, 0x51E1, 0xDBEE, 0x5E06, 0xDBEF, 0x68B5, 0xDBF0, 0x6C3E, 0xDBF1, 0x6C4E, 0xDBF2, 0x6CDB, + 0xDBF3, 0x72AF, 0xDBF4, 0x7BC4, 0xDBF5, 0x8303, 0xDBF6, 0x6CD5, 0xDBF7, 0x743A, 0xDBF8, 0x50FB, 0xDBF9, 0x5288, 0xDBFA, 0x58C1, + 0xDBFB, 0x64D8, 0xDBFC, 0x6A97, 0xDBFD, 0x74A7, 0xDBFE, 0x7656, 0xDCA1, 0x78A7, 0xDCA2, 0x8617, 0xDCA3, 0x95E2, 0xDCA4, 0x9739, + 0xDCA5, 0xF965, 0xDCA6, 0x535E, 0xDCA7, 0x5F01, 0xDCA8, 0x8B8A, 0xDCA9, 0x8FA8, 0xDCAA, 0x8FAF, 0xDCAB, 0x908A, 0xDCAC, 0x5225, + 0xDCAD, 0x77A5, 0xDCAE, 0x9C49, 0xDCAF, 0x9F08, 0xDCB0, 0x4E19, 0xDCB1, 0x5002, 0xDCB2, 0x5175, 0xDCB3, 0x5C5B, 0xDCB4, 0x5E77, + 0xDCB5, 0x661E, 0xDCB6, 0x663A, 0xDCB7, 0x67C4, 0xDCB8, 0x68C5, 0xDCB9, 0x70B3, 0xDCBA, 0x7501, 0xDCBB, 0x75C5, 0xDCBC, 0x79C9, + 0xDCBD, 0x7ADD, 0xDCBE, 0x8F27, 0xDCBF, 0x9920, 0xDCC0, 0x9A08, 0xDCC1, 0x4FDD, 0xDCC2, 0x5821, 0xDCC3, 0x5831, 0xDCC4, 0x5BF6, + 0xDCC5, 0x666E, 0xDCC6, 0x6B65, 0xDCC7, 0x6D11, 0xDCC8, 0x6E7A, 0xDCC9, 0x6F7D, 0xDCCA, 0x73E4, 0xDCCB, 0x752B, 0xDCCC, 0x83E9, + 0xDCCD, 0x88DC, 0xDCCE, 0x8913, 0xDCCF, 0x8B5C, 0xDCD0, 0x8F14, 0xDCD1, 0x4F0F, 0xDCD2, 0x50D5, 0xDCD3, 0x5310, 0xDCD4, 0x535C, + 0xDCD5, 0x5B93, 0xDCD6, 0x5FA9, 0xDCD7, 0x670D, 0xDCD8, 0x798F, 0xDCD9, 0x8179, 0xDCDA, 0x832F, 0xDCDB, 0x8514, 0xDCDC, 0x8907, + 0xDCDD, 0x8986, 0xDCDE, 0x8F39, 0xDCDF, 0x8F3B, 0xDCE0, 0x99A5, 0xDCE1, 0x9C12, 0xDCE2, 0x672C, 0xDCE3, 0x4E76, 0xDCE4, 0x4FF8, + 0xDCE5, 0x5949, 0xDCE6, 0x5C01, 0xDCE7, 0x5CEF, 0xDCE8, 0x5CF0, 0xDCE9, 0x6367, 0xDCEA, 0x68D2, 0xDCEB, 0x70FD, 0xDCEC, 0x71A2, + 0xDCED, 0x742B, 0xDCEE, 0x7E2B, 0xDCEF, 0x84EC, 0xDCF0, 0x8702, 0xDCF1, 0x9022, 0xDCF2, 0x92D2, 0xDCF3, 0x9CF3, 0xDCF4, 0x4E0D, + 0xDCF5, 0x4ED8, 0xDCF6, 0x4FEF, 0xDCF7, 0x5085, 0xDCF8, 0x5256, 0xDCF9, 0x526F, 0xDCFA, 0x5426, 0xDCFB, 0x5490, 0xDCFC, 0x57E0, + 0xDCFD, 0x592B, 0xDCFE, 0x5A66, 0xDDA1, 0x5B5A, 0xDDA2, 0x5B75, 0xDDA3, 0x5BCC, 0xDDA4, 0x5E9C, 0xDDA5, 0xF966, 0xDDA6, 0x6276, + 0xDDA7, 0x6577, 0xDDA8, 0x65A7, 0xDDA9, 0x6D6E, 0xDDAA, 0x6EA5, 0xDDAB, 0x7236, 0xDDAC, 0x7B26, 0xDDAD, 0x7C3F, 0xDDAE, 0x7F36, + 0xDDAF, 0x8150, 0xDDB0, 0x8151, 0xDDB1, 0x819A, 0xDDB2, 0x8240, 0xDDB3, 0x8299, 0xDDB4, 0x83A9, 0xDDB5, 0x8A03, 0xDDB6, 0x8CA0, + 0xDDB7, 0x8CE6, 0xDDB8, 0x8CFB, 0xDDB9, 0x8D74, 0xDDBA, 0x8DBA, 0xDDBB, 0x90E8, 0xDDBC, 0x91DC, 0xDDBD, 0x961C, 0xDDBE, 0x9644, + 0xDDBF, 0x99D9, 0xDDC0, 0x9CE7, 0xDDC1, 0x5317, 0xDDC2, 0x5206, 0xDDC3, 0x5429, 0xDDC4, 0x5674, 0xDDC5, 0x58B3, 0xDDC6, 0x5954, + 0xDDC7, 0x596E, 0xDDC8, 0x5FFF, 0xDDC9, 0x61A4, 0xDDCA, 0x626E, 0xDDCB, 0x6610, 0xDDCC, 0x6C7E, 0xDDCD, 0x711A, 0xDDCE, 0x76C6, + 0xDDCF, 0x7C89, 0xDDD0, 0x7CDE, 0xDDD1, 0x7D1B, 0xDDD2, 0x82AC, 0xDDD3, 0x8CC1, 0xDDD4, 0x96F0, 0xDDD5, 0xF967, 0xDDD6, 0x4F5B, + 0xDDD7, 0x5F17, 0xDDD8, 0x5F7F, 0xDDD9, 0x62C2, 0xDDDA, 0x5D29, 0xDDDB, 0x670B, 0xDDDC, 0x68DA, 0xDDDD, 0x787C, 0xDDDE, 0x7E43, + 0xDDDF, 0x9D6C, 0xDDE0, 0x4E15, 0xDDE1, 0x5099, 0xDDE2, 0x5315, 0xDDE3, 0x532A, 0xDDE4, 0x5351, 0xDDE5, 0x5983, 0xDDE6, 0x5A62, + 0xDDE7, 0x5E87, 0xDDE8, 0x60B2, 0xDDE9, 0x618A, 0xDDEA, 0x6249, 0xDDEB, 0x6279, 0xDDEC, 0x6590, 0xDDED, 0x6787, 0xDDEE, 0x69A7, + 0xDDEF, 0x6BD4, 0xDDF0, 0x6BD6, 0xDDF1, 0x6BD7, 0xDDF2, 0x6BD8, 0xDDF3, 0x6CB8, 0xDDF4, 0xF968, 0xDDF5, 0x7435, 0xDDF6, 0x75FA, + 0xDDF7, 0x7812, 0xDDF8, 0x7891, 0xDDF9, 0x79D5, 0xDDFA, 0x79D8, 0xDDFB, 0x7C83, 0xDDFC, 0x7DCB, 0xDDFD, 0x7FE1, 0xDDFE, 0x80A5, + 0xDEA1, 0x813E, 0xDEA2, 0x81C2, 0xDEA3, 0x83F2, 0xDEA4, 0x871A, 0xDEA5, 0x88E8, 0xDEA6, 0x8AB9, 0xDEA7, 0x8B6C, 0xDEA8, 0x8CBB, + 0xDEA9, 0x9119, 0xDEAA, 0x975E, 0xDEAB, 0x98DB, 0xDEAC, 0x9F3B, 0xDEAD, 0x56AC, 0xDEAE, 0x5B2A, 0xDEAF, 0x5F6C, 0xDEB0, 0x658C, + 0xDEB1, 0x6AB3, 0xDEB2, 0x6BAF, 0xDEB3, 0x6D5C, 0xDEB4, 0x6FF1, 0xDEB5, 0x7015, 0xDEB6, 0x725D, 0xDEB7, 0x73AD, 0xDEB8, 0x8CA7, + 0xDEB9, 0x8CD3, 0xDEBA, 0x983B, 0xDEBB, 0x6191, 0xDEBC, 0x6C37, 0xDEBD, 0x8058, 0xDEBE, 0x9A01, 0xDEBF, 0x4E4D, 0xDEC0, 0x4E8B, + 0xDEC1, 0x4E9B, 0xDEC2, 0x4ED5, 0xDEC3, 0x4F3A, 0xDEC4, 0x4F3C, 0xDEC5, 0x4F7F, 0xDEC6, 0x4FDF, 0xDEC7, 0x50FF, 0xDEC8, 0x53F2, + 0xDEC9, 0x53F8, 0xDECA, 0x5506, 0xDECB, 0x55E3, 0xDECC, 0x56DB, 0xDECD, 0x58EB, 0xDECE, 0x5962, 0xDECF, 0x5A11, 0xDED0, 0x5BEB, + 0xDED1, 0x5BFA, 0xDED2, 0x5C04, 0xDED3, 0x5DF3, 0xDED4, 0x5E2B, 0xDED5, 0x5F99, 0xDED6, 0x601D, 0xDED7, 0x6368, 0xDED8, 0x659C, + 0xDED9, 0x65AF, 0xDEDA, 0x67F6, 0xDEDB, 0x67FB, 0xDEDC, 0x68AD, 0xDEDD, 0x6B7B, 0xDEDE, 0x6C99, 0xDEDF, 0x6CD7, 0xDEE0, 0x6E23, + 0xDEE1, 0x7009, 0xDEE2, 0x7345, 0xDEE3, 0x7802, 0xDEE4, 0x793E, 0xDEE5, 0x7940, 0xDEE6, 0x7960, 0xDEE7, 0x79C1, 0xDEE8, 0x7BE9, + 0xDEE9, 0x7D17, 0xDEEA, 0x7D72, 0xDEEB, 0x8086, 0xDEEC, 0x820D, 0xDEED, 0x838E, 0xDEEE, 0x84D1, 0xDEEF, 0x86C7, 0xDEF0, 0x88DF, + 0xDEF1, 0x8A50, 0xDEF2, 0x8A5E, 0xDEF3, 0x8B1D, 0xDEF4, 0x8CDC, 0xDEF5, 0x8D66, 0xDEF6, 0x8FAD, 0xDEF7, 0x90AA, 0xDEF8, 0x98FC, + 0xDEF9, 0x99DF, 0xDEFA, 0x9E9D, 0xDEFB, 0x524A, 0xDEFC, 0xF969, 0xDEFD, 0x6714, 0xDEFE, 0xF96A, 0xDFA1, 0x5098, 0xDFA2, 0x522A, + 0xDFA3, 0x5C71, 0xDFA4, 0x6563, 0xDFA5, 0x6C55, 0xDFA6, 0x73CA, 0xDFA7, 0x7523, 0xDFA8, 0x759D, 0xDFA9, 0x7B97, 0xDFAA, 0x849C, + 0xDFAB, 0x9178, 0xDFAC, 0x9730, 0xDFAD, 0x4E77, 0xDFAE, 0x6492, 0xDFAF, 0x6BBA, 0xDFB0, 0x715E, 0xDFB1, 0x85A9, 0xDFB2, 0x4E09, + 0xDFB3, 0xF96B, 0xDFB4, 0x6749, 0xDFB5, 0x68EE, 0xDFB6, 0x6E17, 0xDFB7, 0x829F, 0xDFB8, 0x8518, 0xDFB9, 0x886B, 0xDFBA, 0x63F7, + 0xDFBB, 0x6F81, 0xDFBC, 0x9212, 0xDFBD, 0x98AF, 0xDFBE, 0x4E0A, 0xDFBF, 0x50B7, 0xDFC0, 0x50CF, 0xDFC1, 0x511F, 0xDFC2, 0x5546, + 0xDFC3, 0x55AA, 0xDFC4, 0x5617, 0xDFC5, 0x5B40, 0xDFC6, 0x5C19, 0xDFC7, 0x5CE0, 0xDFC8, 0x5E38, 0xDFC9, 0x5E8A, 0xDFCA, 0x5EA0, + 0xDFCB, 0x5EC2, 0xDFCC, 0x60F3, 0xDFCD, 0x6851, 0xDFCE, 0x6A61, 0xDFCF, 0x6E58, 0xDFD0, 0x723D, 0xDFD1, 0x7240, 0xDFD2, 0x72C0, + 0xDFD3, 0x76F8, 0xDFD4, 0x7965, 0xDFD5, 0x7BB1, 0xDFD6, 0x7FD4, 0xDFD7, 0x88F3, 0xDFD8, 0x89F4, 0xDFD9, 0x8A73, 0xDFDA, 0x8C61, + 0xDFDB, 0x8CDE, 0xDFDC, 0x971C, 0xDFDD, 0x585E, 0xDFDE, 0x74BD, 0xDFDF, 0x8CFD, 0xDFE0, 0x55C7, 0xDFE1, 0xF96C, 0xDFE2, 0x7A61, + 0xDFE3, 0x7D22, 0xDFE4, 0x8272, 0xDFE5, 0x7272, 0xDFE6, 0x751F, 0xDFE7, 0x7525, 0xDFE8, 0xF96D, 0xDFE9, 0x7B19, 0xDFEA, 0x5885, + 0xDFEB, 0x58FB, 0xDFEC, 0x5DBC, 0xDFED, 0x5E8F, 0xDFEE, 0x5EB6, 0xDFEF, 0x5F90, 0xDFF0, 0x6055, 0xDFF1, 0x6292, 0xDFF2, 0x637F, + 0xDFF3, 0x654D, 0xDFF4, 0x6691, 0xDFF5, 0x66D9, 0xDFF6, 0x66F8, 0xDFF7, 0x6816, 0xDFF8, 0x68F2, 0xDFF9, 0x7280, 0xDFFA, 0x745E, + 0xDFFB, 0x7B6E, 0xDFFC, 0x7D6E, 0xDFFD, 0x7DD6, 0xDFFE, 0x7F72, 0xE0A1, 0x80E5, 0xE0A2, 0x8212, 0xE0A3, 0x85AF, 0xE0A4, 0x897F, + 0xE0A5, 0x8A93, 0xE0A6, 0x901D, 0xE0A7, 0x92E4, 0xE0A8, 0x9ECD, 0xE0A9, 0x9F20, 0xE0AA, 0x5915, 0xE0AB, 0x596D, 0xE0AC, 0x5E2D, + 0xE0AD, 0x60DC, 0xE0AE, 0x6614, 0xE0AF, 0x6673, 0xE0B0, 0x6790, 0xE0B1, 0x6C50, 0xE0B2, 0x6DC5, 0xE0B3, 0x6F5F, 0xE0B4, 0x77F3, + 0xE0B5, 0x78A9, 0xE0B6, 0x84C6, 0xE0B7, 0x91CB, 0xE0B8, 0x932B, 0xE0B9, 0x4ED9, 0xE0BA, 0x50CA, 0xE0BB, 0x5148, 0xE0BC, 0x5584, + 0xE0BD, 0x5B0B, 0xE0BE, 0x5BA3, 0xE0BF, 0x6247, 0xE0C0, 0x657E, 0xE0C1, 0x65CB, 0xE0C2, 0x6E32, 0xE0C3, 0x717D, 0xE0C4, 0x7401, + 0xE0C5, 0x7444, 0xE0C6, 0x7487, 0xE0C7, 0x74BF, 0xE0C8, 0x766C, 0xE0C9, 0x79AA, 0xE0CA, 0x7DDA, 0xE0CB, 0x7E55, 0xE0CC, 0x7FA8, + 0xE0CD, 0x817A, 0xE0CE, 0x81B3, 0xE0CF, 0x8239, 0xE0D0, 0x861A, 0xE0D1, 0x87EC, 0xE0D2, 0x8A75, 0xE0D3, 0x8DE3, 0xE0D4, 0x9078, + 0xE0D5, 0x9291, 0xE0D6, 0x9425, 0xE0D7, 0x994D, 0xE0D8, 0x9BAE, 0xE0D9, 0x5368, 0xE0DA, 0x5C51, 0xE0DB, 0x6954, 0xE0DC, 0x6CC4, + 0xE0DD, 0x6D29, 0xE0DE, 0x6E2B, 0xE0DF, 0x820C, 0xE0E0, 0x859B, 0xE0E1, 0x893B, 0xE0E2, 0x8A2D, 0xE0E3, 0x8AAA, 0xE0E4, 0x96EA, + 0xE0E5, 0x9F67, 0xE0E6, 0x5261, 0xE0E7, 0x66B9, 0xE0E8, 0x6BB2, 0xE0E9, 0x7E96, 0xE0EA, 0x87FE, 0xE0EB, 0x8D0D, 0xE0EC, 0x9583, + 0xE0ED, 0x965D, 0xE0EE, 0x651D, 0xE0EF, 0x6D89, 0xE0F0, 0x71EE, 0xE0F1, 0xF96E, 0xE0F2, 0x57CE, 0xE0F3, 0x59D3, 0xE0F4, 0x5BAC, + 0xE0F5, 0x6027, 0xE0F6, 0x60FA, 0xE0F7, 0x6210, 0xE0F8, 0x661F, 0xE0F9, 0x665F, 0xE0FA, 0x7329, 0xE0FB, 0x73F9, 0xE0FC, 0x76DB, + 0xE0FD, 0x7701, 0xE0FE, 0x7B6C, 0xE1A1, 0x8056, 0xE1A2, 0x8072, 0xE1A3, 0x8165, 0xE1A4, 0x8AA0, 0xE1A5, 0x9192, 0xE1A6, 0x4E16, + 0xE1A7, 0x52E2, 0xE1A8, 0x6B72, 0xE1A9, 0x6D17, 0xE1AA, 0x7A05, 0xE1AB, 0x7B39, 0xE1AC, 0x7D30, 0xE1AD, 0xF96F, 0xE1AE, 0x8CB0, + 0xE1AF, 0x53EC, 0xE1B0, 0x562F, 0xE1B1, 0x5851, 0xE1B2, 0x5BB5, 0xE1B3, 0x5C0F, 0xE1B4, 0x5C11, 0xE1B5, 0x5DE2, 0xE1B6, 0x6240, + 0xE1B7, 0x6383, 0xE1B8, 0x6414, 0xE1B9, 0x662D, 0xE1BA, 0x68B3, 0xE1BB, 0x6CBC, 0xE1BC, 0x6D88, 0xE1BD, 0x6EAF, 0xE1BE, 0x701F, + 0xE1BF, 0x70A4, 0xE1C0, 0x71D2, 0xE1C1, 0x7526, 0xE1C2, 0x758F, 0xE1C3, 0x758E, 0xE1C4, 0x7619, 0xE1C5, 0x7B11, 0xE1C6, 0x7BE0, + 0xE1C7, 0x7C2B, 0xE1C8, 0x7D20, 0xE1C9, 0x7D39, 0xE1CA, 0x852C, 0xE1CB, 0x856D, 0xE1CC, 0x8607, 0xE1CD, 0x8A34, 0xE1CE, 0x900D, + 0xE1CF, 0x9061, 0xE1D0, 0x90B5, 0xE1D1, 0x92B7, 0xE1D2, 0x97F6, 0xE1D3, 0x9A37, 0xE1D4, 0x4FD7, 0xE1D5, 0x5C6C, 0xE1D6, 0x675F, + 0xE1D7, 0x6D91, 0xE1D8, 0x7C9F, 0xE1D9, 0x7E8C, 0xE1DA, 0x8B16, 0xE1DB, 0x8D16, 0xE1DC, 0x901F, 0xE1DD, 0x5B6B, 0xE1DE, 0x5DFD, + 0xE1DF, 0x640D, 0xE1E0, 0x84C0, 0xE1E1, 0x905C, 0xE1E2, 0x98E1, 0xE1E3, 0x7387, 0xE1E4, 0x5B8B, 0xE1E5, 0x609A, 0xE1E6, 0x677E, + 0xE1E7, 0x6DDE, 0xE1E8, 0x8A1F, 0xE1E9, 0x8AA6, 0xE1EA, 0x9001, 0xE1EB, 0x980C, 0xE1EC, 0x5237, 0xE1ED, 0xF970, 0xE1EE, 0x7051, + 0xE1EF, 0x788E, 0xE1F0, 0x9396, 0xE1F1, 0x8870, 0xE1F2, 0x91D7, 0xE1F3, 0x4FEE, 0xE1F4, 0x53D7, 0xE1F5, 0x55FD, 0xE1F6, 0x56DA, + 0xE1F7, 0x5782, 0xE1F8, 0x58FD, 0xE1F9, 0x5AC2, 0xE1FA, 0x5B88, 0xE1FB, 0x5CAB, 0xE1FC, 0x5CC0, 0xE1FD, 0x5E25, 0xE1FE, 0x6101, + 0xE2A1, 0x620D, 0xE2A2, 0x624B, 0xE2A3, 0x6388, 0xE2A4, 0x641C, 0xE2A5, 0x6536, 0xE2A6, 0x6578, 0xE2A7, 0x6A39, 0xE2A8, 0x6B8A, + 0xE2A9, 0x6C34, 0xE2AA, 0x6D19, 0xE2AB, 0x6F31, 0xE2AC, 0x71E7, 0xE2AD, 0x72E9, 0xE2AE, 0x7378, 0xE2AF, 0x7407, 0xE2B0, 0x74B2, + 0xE2B1, 0x7626, 0xE2B2, 0x7761, 0xE2B3, 0x79C0, 0xE2B4, 0x7A57, 0xE2B5, 0x7AEA, 0xE2B6, 0x7CB9, 0xE2B7, 0x7D8F, 0xE2B8, 0x7DAC, + 0xE2B9, 0x7E61, 0xE2BA, 0x7F9E, 0xE2BB, 0x8129, 0xE2BC, 0x8331, 0xE2BD, 0x8490, 0xE2BE, 0x84DA, 0xE2BF, 0x85EA, 0xE2C0, 0x8896, + 0xE2C1, 0x8AB0, 0xE2C2, 0x8B90, 0xE2C3, 0x8F38, 0xE2C4, 0x9042, 0xE2C5, 0x9083, 0xE2C6, 0x916C, 0xE2C7, 0x9296, 0xE2C8, 0x92B9, + 0xE2C9, 0x968B, 0xE2CA, 0x96A7, 0xE2CB, 0x96A8, 0xE2CC, 0x96D6, 0xE2CD, 0x9700, 0xE2CE, 0x9808, 0xE2CF, 0x9996, 0xE2D0, 0x9AD3, + 0xE2D1, 0x9B1A, 0xE2D2, 0x53D4, 0xE2D3, 0x587E, 0xE2D4, 0x5919, 0xE2D5, 0x5B70, 0xE2D6, 0x5BBF, 0xE2D7, 0x6DD1, 0xE2D8, 0x6F5A, + 0xE2D9, 0x719F, 0xE2DA, 0x7421, 0xE2DB, 0x74B9, 0xE2DC, 0x8085, 0xE2DD, 0x83FD, 0xE2DE, 0x5DE1, 0xE2DF, 0x5F87, 0xE2E0, 0x5FAA, + 0xE2E1, 0x6042, 0xE2E2, 0x65EC, 0xE2E3, 0x6812, 0xE2E4, 0x696F, 0xE2E5, 0x6A53, 0xE2E6, 0x6B89, 0xE2E7, 0x6D35, 0xE2E8, 0x6DF3, + 0xE2E9, 0x73E3, 0xE2EA, 0x76FE, 0xE2EB, 0x77AC, 0xE2EC, 0x7B4D, 0xE2ED, 0x7D14, 0xE2EE, 0x8123, 0xE2EF, 0x821C, 0xE2F0, 0x8340, + 0xE2F1, 0x84F4, 0xE2F2, 0x8563, 0xE2F3, 0x8A62, 0xE2F4, 0x8AC4, 0xE2F5, 0x9187, 0xE2F6, 0x931E, 0xE2F7, 0x9806, 0xE2F8, 0x99B4, + 0xE2F9, 0x620C, 0xE2FA, 0x8853, 0xE2FB, 0x8FF0, 0xE2FC, 0x9265, 0xE2FD, 0x5D07, 0xE2FE, 0x5D27, 0xE3A1, 0x5D69, 0xE3A2, 0x745F, + 0xE3A3, 0x819D, 0xE3A4, 0x8768, 0xE3A5, 0x6FD5, 0xE3A6, 0x62FE, 0xE3A7, 0x7FD2, 0xE3A8, 0x8936, 0xE3A9, 0x8972, 0xE3AA, 0x4E1E, + 0xE3AB, 0x4E58, 0xE3AC, 0x50E7, 0xE3AD, 0x52DD, 0xE3AE, 0x5347, 0xE3AF, 0x627F, 0xE3B0, 0x6607, 0xE3B1, 0x7E69, 0xE3B2, 0x8805, + 0xE3B3, 0x965E, 0xE3B4, 0x4F8D, 0xE3B5, 0x5319, 0xE3B6, 0x5636, 0xE3B7, 0x59CB, 0xE3B8, 0x5AA4, 0xE3B9, 0x5C38, 0xE3BA, 0x5C4E, + 0xE3BB, 0x5C4D, 0xE3BC, 0x5E02, 0xE3BD, 0x5F11, 0xE3BE, 0x6043, 0xE3BF, 0x65BD, 0xE3C0, 0x662F, 0xE3C1, 0x6642, 0xE3C2, 0x67BE, + 0xE3C3, 0x67F4, 0xE3C4, 0x731C, 0xE3C5, 0x77E2, 0xE3C6, 0x793A, 0xE3C7, 0x7FC5, 0xE3C8, 0x8494, 0xE3C9, 0x84CD, 0xE3CA, 0x8996, + 0xE3CB, 0x8A66, 0xE3CC, 0x8A69, 0xE3CD, 0x8AE1, 0xE3CE, 0x8C55, 0xE3CF, 0x8C7A, 0xE3D0, 0x57F4, 0xE3D1, 0x5BD4, 0xE3D2, 0x5F0F, + 0xE3D3, 0x606F, 0xE3D4, 0x62ED, 0xE3D5, 0x690D, 0xE3D6, 0x6B96, 0xE3D7, 0x6E5C, 0xE3D8, 0x7184, 0xE3D9, 0x7BD2, 0xE3DA, 0x8755, + 0xE3DB, 0x8B58, 0xE3DC, 0x8EFE, 0xE3DD, 0x98DF, 0xE3DE, 0x98FE, 0xE3DF, 0x4F38, 0xE3E0, 0x4F81, 0xE3E1, 0x4FE1, 0xE3E2, 0x547B, + 0xE3E3, 0x5A20, 0xE3E4, 0x5BB8, 0xE3E5, 0x613C, 0xE3E6, 0x65B0, 0xE3E7, 0x6668, 0xE3E8, 0x71FC, 0xE3E9, 0x7533, 0xE3EA, 0x795E, + 0xE3EB, 0x7D33, 0xE3EC, 0x814E, 0xE3ED, 0x81E3, 0xE3EE, 0x8398, 0xE3EF, 0x85AA, 0xE3F0, 0x85CE, 0xE3F1, 0x8703, 0xE3F2, 0x8A0A, + 0xE3F3, 0x8EAB, 0xE3F4, 0x8F9B, 0xE3F5, 0xF971, 0xE3F6, 0x8FC5, 0xE3F7, 0x5931, 0xE3F8, 0x5BA4, 0xE3F9, 0x5BE6, 0xE3FA, 0x6089, + 0xE3FB, 0x5BE9, 0xE3FC, 0x5C0B, 0xE3FD, 0x5FC3, 0xE3FE, 0x6C81, 0xE4A1, 0xF972, 0xE4A2, 0x6DF1, 0xE4A3, 0x700B, 0xE4A4, 0x751A, + 0xE4A5, 0x82AF, 0xE4A6, 0x8AF6, 0xE4A7, 0x4EC0, 0xE4A8, 0x5341, 0xE4A9, 0xF973, 0xE4AA, 0x96D9, 0xE4AB, 0x6C0F, 0xE4AC, 0x4E9E, + 0xE4AD, 0x4FC4, 0xE4AE, 0x5152, 0xE4AF, 0x555E, 0xE4B0, 0x5A25, 0xE4B1, 0x5CE8, 0xE4B2, 0x6211, 0xE4B3, 0x7259, 0xE4B4, 0x82BD, + 0xE4B5, 0x83AA, 0xE4B6, 0x86FE, 0xE4B7, 0x8859, 0xE4B8, 0x8A1D, 0xE4B9, 0x963F, 0xE4BA, 0x96C5, 0xE4BB, 0x9913, 0xE4BC, 0x9D09, + 0xE4BD, 0x9D5D, 0xE4BE, 0x580A, 0xE4BF, 0x5CB3, 0xE4C0, 0x5DBD, 0xE4C1, 0x5E44, 0xE4C2, 0x60E1, 0xE4C3, 0x6115, 0xE4C4, 0x63E1, + 0xE4C5, 0x6A02, 0xE4C6, 0x6E25, 0xE4C7, 0x9102, 0xE4C8, 0x9354, 0xE4C9, 0x984E, 0xE4CA, 0x9C10, 0xE4CB, 0x9F77, 0xE4CC, 0x5B89, + 0xE4CD, 0x5CB8, 0xE4CE, 0x6309, 0xE4CF, 0x664F, 0xE4D0, 0x6848, 0xE4D1, 0x773C, 0xE4D2, 0x96C1, 0xE4D3, 0x978D, 0xE4D4, 0x9854, + 0xE4D5, 0x9B9F, 0xE4D6, 0x65A1, 0xE4D7, 0x8B01, 0xE4D8, 0x8ECB, 0xE4D9, 0x95BC, 0xE4DA, 0x5535, 0xE4DB, 0x5CA9, 0xE4DC, 0x5DD6, + 0xE4DD, 0x5EB5, 0xE4DE, 0x6697, 0xE4DF, 0x764C, 0xE4E0, 0x83F4, 0xE4E1, 0x95C7, 0xE4E2, 0x58D3, 0xE4E3, 0x62BC, 0xE4E4, 0x72CE, + 0xE4E5, 0x9D28, 0xE4E6, 0x4EF0, 0xE4E7, 0x592E, 0xE4E8, 0x600F, 0xE4E9, 0x663B, 0xE4EA, 0x6B83, 0xE4EB, 0x79E7, 0xE4EC, 0x9D26, + 0xE4ED, 0x5393, 0xE4EE, 0x54C0, 0xE4EF, 0x57C3, 0xE4F0, 0x5D16, 0xE4F1, 0x611B, 0xE4F2, 0x66D6, 0xE4F3, 0x6DAF, 0xE4F4, 0x788D, + 0xE4F5, 0x827E, 0xE4F6, 0x9698, 0xE4F7, 0x9744, 0xE4F8, 0x5384, 0xE4F9, 0x627C, 0xE4FA, 0x6396, 0xE4FB, 0x6DB2, 0xE4FC, 0x7E0A, + 0xE4FD, 0x814B, 0xE4FE, 0x984D, 0xE5A1, 0x6AFB, 0xE5A2, 0x7F4C, 0xE5A3, 0x9DAF, 0xE5A4, 0x9E1A, 0xE5A5, 0x4E5F, 0xE5A6, 0x503B, + 0xE5A7, 0x51B6, 0xE5A8, 0x591C, 0xE5A9, 0x60F9, 0xE5AA, 0x63F6, 0xE5AB, 0x6930, 0xE5AC, 0x723A, 0xE5AD, 0x8036, 0xE5AE, 0xF974, + 0xE5AF, 0x91CE, 0xE5B0, 0x5F31, 0xE5B1, 0xF975, 0xE5B2, 0xF976, 0xE5B3, 0x7D04, 0xE5B4, 0x82E5, 0xE5B5, 0x846F, 0xE5B6, 0x84BB, + 0xE5B7, 0x85E5, 0xE5B8, 0x8E8D, 0xE5B9, 0xF977, 0xE5BA, 0x4F6F, 0xE5BB, 0xF978, 0xE5BC, 0xF979, 0xE5BD, 0x58E4, 0xE5BE, 0x5B43, + 0xE5BF, 0x6059, 0xE5C0, 0x63DA, 0xE5C1, 0x6518, 0xE5C2, 0x656D, 0xE5C3, 0x6698, 0xE5C4, 0xF97A, 0xE5C5, 0x694A, 0xE5C6, 0x6A23, + 0xE5C7, 0x6D0B, 0xE5C8, 0x7001, 0xE5C9, 0x716C, 0xE5CA, 0x75D2, 0xE5CB, 0x760D, 0xE5CC, 0x79B3, 0xE5CD, 0x7A70, 0xE5CE, 0xF97B, + 0xE5CF, 0x7F8A, 0xE5D0, 0xF97C, 0xE5D1, 0x8944, 0xE5D2, 0xF97D, 0xE5D3, 0x8B93, 0xE5D4, 0x91C0, 0xE5D5, 0x967D, 0xE5D6, 0xF97E, + 0xE5D7, 0x990A, 0xE5D8, 0x5704, 0xE5D9, 0x5FA1, 0xE5DA, 0x65BC, 0xE5DB, 0x6F01, 0xE5DC, 0x7600, 0xE5DD, 0x79A6, 0xE5DE, 0x8A9E, + 0xE5DF, 0x99AD, 0xE5E0, 0x9B5A, 0xE5E1, 0x9F6C, 0xE5E2, 0x5104, 0xE5E3, 0x61B6, 0xE5E4, 0x6291, 0xE5E5, 0x6A8D, 0xE5E6, 0x81C6, + 0xE5E7, 0x5043, 0xE5E8, 0x5830, 0xE5E9, 0x5F66, 0xE5EA, 0x7109, 0xE5EB, 0x8A00, 0xE5EC, 0x8AFA, 0xE5ED, 0x5B7C, 0xE5EE, 0x8616, + 0xE5EF, 0x4FFA, 0xE5F0, 0x513C, 0xE5F1, 0x56B4, 0xE5F2, 0x5944, 0xE5F3, 0x63A9, 0xE5F4, 0x6DF9, 0xE5F5, 0x5DAA, 0xE5F6, 0x696D, + 0xE5F7, 0x5186, 0xE5F8, 0x4E88, 0xE5F9, 0x4F59, 0xE5FA, 0xF97F, 0xE5FB, 0xF980, 0xE5FC, 0xF981, 0xE5FD, 0x5982, 0xE5FE, 0xF982, + 0xE6A1, 0xF983, 0xE6A2, 0x6B5F, 0xE6A3, 0x6C5D, 0xE6A4, 0xF984, 0xE6A5, 0x74B5, 0xE6A6, 0x7916, 0xE6A7, 0xF985, 0xE6A8, 0x8207, + 0xE6A9, 0x8245, 0xE6AA, 0x8339, 0xE6AB, 0x8F3F, 0xE6AC, 0x8F5D, 0xE6AD, 0xF986, 0xE6AE, 0x9918, 0xE6AF, 0xF987, 0xE6B0, 0xF988, + 0xE6B1, 0xF989, 0xE6B2, 0x4EA6, 0xE6B3, 0xF98A, 0xE6B4, 0x57DF, 0xE6B5, 0x5F79, 0xE6B6, 0x6613, 0xE6B7, 0xF98B, 0xE6B8, 0xF98C, + 0xE6B9, 0x75AB, 0xE6BA, 0x7E79, 0xE6BB, 0x8B6F, 0xE6BC, 0xF98D, 0xE6BD, 0x9006, 0xE6BE, 0x9A5B, 0xE6BF, 0x56A5, 0xE6C0, 0x5827, + 0xE6C1, 0x59F8, 0xE6C2, 0x5A1F, 0xE6C3, 0x5BB4, 0xE6C4, 0xF98E, 0xE6C5, 0x5EF6, 0xE6C6, 0xF98F, 0xE6C7, 0xF990, 0xE6C8, 0x6350, + 0xE6C9, 0x633B, 0xE6CA, 0xF991, 0xE6CB, 0x693D, 0xE6CC, 0x6C87, 0xE6CD, 0x6CBF, 0xE6CE, 0x6D8E, 0xE6CF, 0x6D93, 0xE6D0, 0x6DF5, + 0xE6D1, 0x6F14, 0xE6D2, 0xF992, 0xE6D3, 0x70DF, 0xE6D4, 0x7136, 0xE6D5, 0x7159, 0xE6D6, 0xF993, 0xE6D7, 0x71C3, 0xE6D8, 0x71D5, + 0xE6D9, 0xF994, 0xE6DA, 0x784F, 0xE6DB, 0x786F, 0xE6DC, 0xF995, 0xE6DD, 0x7B75, 0xE6DE, 0x7DE3, 0xE6DF, 0xF996, 0xE6E0, 0x7E2F, + 0xE6E1, 0xF997, 0xE6E2, 0x884D, 0xE6E3, 0x8EDF, 0xE6E4, 0xF998, 0xE6E5, 0xF999, 0xE6E6, 0xF99A, 0xE6E7, 0x925B, 0xE6E8, 0xF99B, + 0xE6E9, 0x9CF6, 0xE6EA, 0xF99C, 0xE6EB, 0xF99D, 0xE6EC, 0xF99E, 0xE6ED, 0x6085, 0xE6EE, 0x6D85, 0xE6EF, 0xF99F, 0xE6F0, 0x71B1, + 0xE6F1, 0xF9A0, 0xE6F2, 0xF9A1, 0xE6F3, 0x95B1, 0xE6F4, 0x53AD, 0xE6F5, 0xF9A2, 0xE6F6, 0xF9A3, 0xE6F7, 0xF9A4, 0xE6F8, 0x67D3, + 0xE6F9, 0xF9A5, 0xE6FA, 0x708E, 0xE6FB, 0x7130, 0xE6FC, 0x7430, 0xE6FD, 0x8276, 0xE6FE, 0x82D2, 0xE7A1, 0xF9A6, 0xE7A2, 0x95BB, + 0xE7A3, 0x9AE5, 0xE7A4, 0x9E7D, 0xE7A5, 0x66C4, 0xE7A6, 0xF9A7, 0xE7A7, 0x71C1, 0xE7A8, 0x8449, 0xE7A9, 0xF9A8, 0xE7AA, 0xF9A9, + 0xE7AB, 0x584B, 0xE7AC, 0xF9AA, 0xE7AD, 0xF9AB, 0xE7AE, 0x5DB8, 0xE7AF, 0x5F71, 0xE7B0, 0xF9AC, 0xE7B1, 0x6620, 0xE7B2, 0x668E, + 0xE7B3, 0x6979, 0xE7B4, 0x69AE, 0xE7B5, 0x6C38, 0xE7B6, 0x6CF3, 0xE7B7, 0x6E36, 0xE7B8, 0x6F41, 0xE7B9, 0x6FDA, 0xE7BA, 0x701B, + 0xE7BB, 0x702F, 0xE7BC, 0x7150, 0xE7BD, 0x71DF, 0xE7BE, 0x7370, 0xE7BF, 0xF9AD, 0xE7C0, 0x745B, 0xE7C1, 0xF9AE, 0xE7C2, 0x74D4, + 0xE7C3, 0x76C8, 0xE7C4, 0x7A4E, 0xE7C5, 0x7E93, 0xE7C6, 0xF9AF, 0xE7C7, 0xF9B0, 0xE7C8, 0x82F1, 0xE7C9, 0x8A60, 0xE7CA, 0x8FCE, + 0xE7CB, 0xF9B1, 0xE7CC, 0x9348, 0xE7CD, 0xF9B2, 0xE7CE, 0x9719, 0xE7CF, 0xF9B3, 0xE7D0, 0xF9B4, 0xE7D1, 0x4E42, 0xE7D2, 0x502A, + 0xE7D3, 0xF9B5, 0xE7D4, 0x5208, 0xE7D5, 0x53E1, 0xE7D6, 0x66F3, 0xE7D7, 0x6C6D, 0xE7D8, 0x6FCA, 0xE7D9, 0x730A, 0xE7DA, 0x777F, + 0xE7DB, 0x7A62, 0xE7DC, 0x82AE, 0xE7DD, 0x85DD, 0xE7DE, 0x8602, 0xE7DF, 0xF9B6, 0xE7E0, 0x88D4, 0xE7E1, 0x8A63, 0xE7E2, 0x8B7D, + 0xE7E3, 0x8C6B, 0xE7E4, 0xF9B7, 0xE7E5, 0x92B3, 0xE7E6, 0xF9B8, 0xE7E7, 0x9713, 0xE7E8, 0x9810, 0xE7E9, 0x4E94, 0xE7EA, 0x4F0D, + 0xE7EB, 0x4FC9, 0xE7EC, 0x50B2, 0xE7ED, 0x5348, 0xE7EE, 0x543E, 0xE7EF, 0x5433, 0xE7F0, 0x55DA, 0xE7F1, 0x5862, 0xE7F2, 0x58BA, + 0xE7F3, 0x5967, 0xE7F4, 0x5A1B, 0xE7F5, 0x5BE4, 0xE7F6, 0x609F, 0xE7F7, 0xF9B9, 0xE7F8, 0x61CA, 0xE7F9, 0x6556, 0xE7FA, 0x65FF, + 0xE7FB, 0x6664, 0xE7FC, 0x68A7, 0xE7FD, 0x6C5A, 0xE7FE, 0x6FB3, 0xE8A1, 0x70CF, 0xE8A2, 0x71AC, 0xE8A3, 0x7352, 0xE8A4, 0x7B7D, + 0xE8A5, 0x8708, 0xE8A6, 0x8AA4, 0xE8A7, 0x9C32, 0xE8A8, 0x9F07, 0xE8A9, 0x5C4B, 0xE8AA, 0x6C83, 0xE8AB, 0x7344, 0xE8AC, 0x7389, + 0xE8AD, 0x923A, 0xE8AE, 0x6EAB, 0xE8AF, 0x7465, 0xE8B0, 0x761F, 0xE8B1, 0x7A69, 0xE8B2, 0x7E15, 0xE8B3, 0x860A, 0xE8B4, 0x5140, + 0xE8B5, 0x58C5, 0xE8B6, 0x64C1, 0xE8B7, 0x74EE, 0xE8B8, 0x7515, 0xE8B9, 0x7670, 0xE8BA, 0x7FC1, 0xE8BB, 0x9095, 0xE8BC, 0x96CD, + 0xE8BD, 0x9954, 0xE8BE, 0x6E26, 0xE8BF, 0x74E6, 0xE8C0, 0x7AA9, 0xE8C1, 0x7AAA, 0xE8C2, 0x81E5, 0xE8C3, 0x86D9, 0xE8C4, 0x8778, + 0xE8C5, 0x8A1B, 0xE8C6, 0x5A49, 0xE8C7, 0x5B8C, 0xE8C8, 0x5B9B, 0xE8C9, 0x68A1, 0xE8CA, 0x6900, 0xE8CB, 0x6D63, 0xE8CC, 0x73A9, + 0xE8CD, 0x7413, 0xE8CE, 0x742C, 0xE8CF, 0x7897, 0xE8D0, 0x7DE9, 0xE8D1, 0x7FEB, 0xE8D2, 0x8118, 0xE8D3, 0x8155, 0xE8D4, 0x839E, + 0xE8D5, 0x8C4C, 0xE8D6, 0x962E, 0xE8D7, 0x9811, 0xE8D8, 0x66F0, 0xE8D9, 0x5F80, 0xE8DA, 0x65FA, 0xE8DB, 0x6789, 0xE8DC, 0x6C6A, + 0xE8DD, 0x738B, 0xE8DE, 0x502D, 0xE8DF, 0x5A03, 0xE8E0, 0x6B6A, 0xE8E1, 0x77EE, 0xE8E2, 0x5916, 0xE8E3, 0x5D6C, 0xE8E4, 0x5DCD, + 0xE8E5, 0x7325, 0xE8E6, 0x754F, 0xE8E7, 0xF9BA, 0xE8E8, 0xF9BB, 0xE8E9, 0x50E5, 0xE8EA, 0x51F9, 0xE8EB, 0x582F, 0xE8EC, 0x592D, + 0xE8ED, 0x5996, 0xE8EE, 0x59DA, 0xE8EF, 0x5BE5, 0xE8F0, 0xF9BC, 0xE8F1, 0xF9BD, 0xE8F2, 0x5DA2, 0xE8F3, 0x62D7, 0xE8F4, 0x6416, + 0xE8F5, 0x6493, 0xE8F6, 0x64FE, 0xE8F7, 0xF9BE, 0xE8F8, 0x66DC, 0xE8F9, 0xF9BF, 0xE8FA, 0x6A48, 0xE8FB, 0xF9C0, 0xE8FC, 0x71FF, + 0xE8FD, 0x7464, 0xE8FE, 0xF9C1, 0xE9A1, 0x7A88, 0xE9A2, 0x7AAF, 0xE9A3, 0x7E47, 0xE9A4, 0x7E5E, 0xE9A5, 0x8000, 0xE9A6, 0x8170, + 0xE9A7, 0xF9C2, 0xE9A8, 0x87EF, 0xE9A9, 0x8981, 0xE9AA, 0x8B20, 0xE9AB, 0x9059, 0xE9AC, 0xF9C3, 0xE9AD, 0x9080, 0xE9AE, 0x9952, + 0xE9AF, 0x617E, 0xE9B0, 0x6B32, 0xE9B1, 0x6D74, 0xE9B2, 0x7E1F, 0xE9B3, 0x8925, 0xE9B4, 0x8FB1, 0xE9B5, 0x4FD1, 0xE9B6, 0x50AD, + 0xE9B7, 0x5197, 0xE9B8, 0x52C7, 0xE9B9, 0x57C7, 0xE9BA, 0x5889, 0xE9BB, 0x5BB9, 0xE9BC, 0x5EB8, 0xE9BD, 0x6142, 0xE9BE, 0x6995, + 0xE9BF, 0x6D8C, 0xE9C0, 0x6E67, 0xE9C1, 0x6EB6, 0xE9C2, 0x7194, 0xE9C3, 0x7462, 0xE9C4, 0x7528, 0xE9C5, 0x752C, 0xE9C6, 0x8073, + 0xE9C7, 0x8338, 0xE9C8, 0x84C9, 0xE9C9, 0x8E0A, 0xE9CA, 0x9394, 0xE9CB, 0x93DE, 0xE9CC, 0xF9C4, 0xE9CD, 0x4E8E, 0xE9CE, 0x4F51, + 0xE9CF, 0x5076, 0xE9D0, 0x512A, 0xE9D1, 0x53C8, 0xE9D2, 0x53CB, 0xE9D3, 0x53F3, 0xE9D4, 0x5B87, 0xE9D5, 0x5BD3, 0xE9D6, 0x5C24, + 0xE9D7, 0x611A, 0xE9D8, 0x6182, 0xE9D9, 0x65F4, 0xE9DA, 0x725B, 0xE9DB, 0x7397, 0xE9DC, 0x7440, 0xE9DD, 0x76C2, 0xE9DE, 0x7950, + 0xE9DF, 0x7991, 0xE9E0, 0x79B9, 0xE9E1, 0x7D06, 0xE9E2, 0x7FBD, 0xE9E3, 0x828B, 0xE9E4, 0x85D5, 0xE9E5, 0x865E, 0xE9E6, 0x8FC2, + 0xE9E7, 0x9047, 0xE9E8, 0x90F5, 0xE9E9, 0x91EA, 0xE9EA, 0x9685, 0xE9EB, 0x96E8, 0xE9EC, 0x96E9, 0xE9ED, 0x52D6, 0xE9EE, 0x5F67, + 0xE9EF, 0x65ED, 0xE9F0, 0x6631, 0xE9F1, 0x682F, 0xE9F2, 0x715C, 0xE9F3, 0x7A36, 0xE9F4, 0x90C1, 0xE9F5, 0x980A, 0xE9F6, 0x4E91, + 0xE9F7, 0xF9C5, 0xE9F8, 0x6A52, 0xE9F9, 0x6B9E, 0xE9FA, 0x6F90, 0xE9FB, 0x7189, 0xE9FC, 0x8018, 0xE9FD, 0x82B8, 0xE9FE, 0x8553, + 0xEAA1, 0x904B, 0xEAA2, 0x9695, 0xEAA3, 0x96F2, 0xEAA4, 0x97FB, 0xEAA5, 0x851A, 0xEAA6, 0x9B31, 0xEAA7, 0x4E90, 0xEAA8, 0x718A, + 0xEAA9, 0x96C4, 0xEAAA, 0x5143, 0xEAAB, 0x539F, 0xEAAC, 0x54E1, 0xEAAD, 0x5713, 0xEAAE, 0x5712, 0xEAAF, 0x57A3, 0xEAB0, 0x5A9B, + 0xEAB1, 0x5AC4, 0xEAB2, 0x5BC3, 0xEAB3, 0x6028, 0xEAB4, 0x613F, 0xEAB5, 0x63F4, 0xEAB6, 0x6C85, 0xEAB7, 0x6D39, 0xEAB8, 0x6E72, + 0xEAB9, 0x6E90, 0xEABA, 0x7230, 0xEABB, 0x733F, 0xEABC, 0x7457, 0xEABD, 0x82D1, 0xEABE, 0x8881, 0xEABF, 0x8F45, 0xEAC0, 0x9060, + 0xEAC1, 0xF9C6, 0xEAC2, 0x9662, 0xEAC3, 0x9858, 0xEAC4, 0x9D1B, 0xEAC5, 0x6708, 0xEAC6, 0x8D8A, 0xEAC7, 0x925E, 0xEAC8, 0x4F4D, + 0xEAC9, 0x5049, 0xEACA, 0x50DE, 0xEACB, 0x5371, 0xEACC, 0x570D, 0xEACD, 0x59D4, 0xEACE, 0x5A01, 0xEACF, 0x5C09, 0xEAD0, 0x6170, + 0xEAD1, 0x6690, 0xEAD2, 0x6E2D, 0xEAD3, 0x7232, 0xEAD4, 0x744B, 0xEAD5, 0x7DEF, 0xEAD6, 0x80C3, 0xEAD7, 0x840E, 0xEAD8, 0x8466, + 0xEAD9, 0x853F, 0xEADA, 0x875F, 0xEADB, 0x885B, 0xEADC, 0x8918, 0xEADD, 0x8B02, 0xEADE, 0x9055, 0xEADF, 0x97CB, 0xEAE0, 0x9B4F, + 0xEAE1, 0x4E73, 0xEAE2, 0x4F91, 0xEAE3, 0x5112, 0xEAE4, 0x516A, 0xEAE5, 0xF9C7, 0xEAE6, 0x552F, 0xEAE7, 0x55A9, 0xEAE8, 0x5B7A, + 0xEAE9, 0x5BA5, 0xEAEA, 0x5E7C, 0xEAEB, 0x5E7D, 0xEAEC, 0x5EBE, 0xEAED, 0x60A0, 0xEAEE, 0x60DF, 0xEAEF, 0x6108, 0xEAF0, 0x6109, + 0xEAF1, 0x63C4, 0xEAF2, 0x6538, 0xEAF3, 0x6709, 0xEAF4, 0xF9C8, 0xEAF5, 0x67D4, 0xEAF6, 0x67DA, 0xEAF7, 0xF9C9, 0xEAF8, 0x6961, + 0xEAF9, 0x6962, 0xEAFA, 0x6CB9, 0xEAFB, 0x6D27, 0xEAFC, 0xF9CA, 0xEAFD, 0x6E38, 0xEAFE, 0xF9CB, 0xEBA1, 0x6FE1, 0xEBA2, 0x7336, + 0xEBA3, 0x7337, 0xEBA4, 0xF9CC, 0xEBA5, 0x745C, 0xEBA6, 0x7531, 0xEBA7, 0xF9CD, 0xEBA8, 0x7652, 0xEBA9, 0xF9CE, 0xEBAA, 0xF9CF, + 0xEBAB, 0x7DAD, 0xEBAC, 0x81FE, 0xEBAD, 0x8438, 0xEBAE, 0x88D5, 0xEBAF, 0x8A98, 0xEBB0, 0x8ADB, 0xEBB1, 0x8AED, 0xEBB2, 0x8E30, + 0xEBB3, 0x8E42, 0xEBB4, 0x904A, 0xEBB5, 0x903E, 0xEBB6, 0x907A, 0xEBB7, 0x9149, 0xEBB8, 0x91C9, 0xEBB9, 0x936E, 0xEBBA, 0xF9D0, + 0xEBBB, 0xF9D1, 0xEBBC, 0x5809, 0xEBBD, 0xF9D2, 0xEBBE, 0x6BD3, 0xEBBF, 0x8089, 0xEBC0, 0x80B2, 0xEBC1, 0xF9D3, 0xEBC2, 0xF9D4, + 0xEBC3, 0x5141, 0xEBC4, 0x596B, 0xEBC5, 0x5C39, 0xEBC6, 0xF9D5, 0xEBC7, 0xF9D6, 0xEBC8, 0x6F64, 0xEBC9, 0x73A7, 0xEBCA, 0x80E4, + 0xEBCB, 0x8D07, 0xEBCC, 0xF9D7, 0xEBCD, 0x9217, 0xEBCE, 0x958F, 0xEBCF, 0xF9D8, 0xEBD0, 0xF9D9, 0xEBD1, 0xF9DA, 0xEBD2, 0xF9DB, + 0xEBD3, 0x807F, 0xEBD4, 0x620E, 0xEBD5, 0x701C, 0xEBD6, 0x7D68, 0xEBD7, 0x878D, 0xEBD8, 0xF9DC, 0xEBD9, 0x57A0, 0xEBDA, 0x6069, + 0xEBDB, 0x6147, 0xEBDC, 0x6BB7, 0xEBDD, 0x8ABE, 0xEBDE, 0x9280, 0xEBDF, 0x96B1, 0xEBE0, 0x4E59, 0xEBE1, 0x541F, 0xEBE2, 0x6DEB, + 0xEBE3, 0x852D, 0xEBE4, 0x9670, 0xEBE5, 0x97F3, 0xEBE6, 0x98EE, 0xEBE7, 0x63D6, 0xEBE8, 0x6CE3, 0xEBE9, 0x9091, 0xEBEA, 0x51DD, + 0xEBEB, 0x61C9, 0xEBEC, 0x81BA, 0xEBED, 0x9DF9, 0xEBEE, 0x4F9D, 0xEBEF, 0x501A, 0xEBF0, 0x5100, 0xEBF1, 0x5B9C, 0xEBF2, 0x610F, + 0xEBF3, 0x61FF, 0xEBF4, 0x64EC, 0xEBF5, 0x6905, 0xEBF6, 0x6BC5, 0xEBF7, 0x7591, 0xEBF8, 0x77E3, 0xEBF9, 0x7FA9, 0xEBFA, 0x8264, + 0xEBFB, 0x858F, 0xEBFC, 0x87FB, 0xEBFD, 0x8863, 0xEBFE, 0x8ABC, 0xECA1, 0x8B70, 0xECA2, 0x91AB, 0xECA3, 0x4E8C, 0xECA4, 0x4EE5, + 0xECA5, 0x4F0A, 0xECA6, 0xF9DD, 0xECA7, 0xF9DE, 0xECA8, 0x5937, 0xECA9, 0x59E8, 0xECAA, 0xF9DF, 0xECAB, 0x5DF2, 0xECAC, 0x5F1B, + 0xECAD, 0x5F5B, 0xECAE, 0x6021, 0xECAF, 0xF9E0, 0xECB0, 0xF9E1, 0xECB1, 0xF9E2, 0xECB2, 0xF9E3, 0xECB3, 0x723E, 0xECB4, 0x73E5, + 0xECB5, 0xF9E4, 0xECB6, 0x7570, 0xECB7, 0x75CD, 0xECB8, 0xF9E5, 0xECB9, 0x79FB, 0xECBA, 0xF9E6, 0xECBB, 0x800C, 0xECBC, 0x8033, + 0xECBD, 0x8084, 0xECBE, 0x82E1, 0xECBF, 0x8351, 0xECC0, 0xF9E7, 0xECC1, 0xF9E8, 0xECC2, 0x8CBD, 0xECC3, 0x8CB3, 0xECC4, 0x9087, + 0xECC5, 0xF9E9, 0xECC6, 0xF9EA, 0xECC7, 0x98F4, 0xECC8, 0x990C, 0xECC9, 0xF9EB, 0xECCA, 0xF9EC, 0xECCB, 0x7037, 0xECCC, 0x76CA, + 0xECCD, 0x7FCA, 0xECCE, 0x7FCC, 0xECCF, 0x7FFC, 0xECD0, 0x8B1A, 0xECD1, 0x4EBA, 0xECD2, 0x4EC1, 0xECD3, 0x5203, 0xECD4, 0x5370, + 0xECD5, 0xF9ED, 0xECD6, 0x54BD, 0xECD7, 0x56E0, 0xECD8, 0x59FB, 0xECD9, 0x5BC5, 0xECDA, 0x5F15, 0xECDB, 0x5FCD, 0xECDC, 0x6E6E, + 0xECDD, 0xF9EE, 0xECDE, 0xF9EF, 0xECDF, 0x7D6A, 0xECE0, 0x8335, 0xECE1, 0xF9F0, 0xECE2, 0x8693, 0xECE3, 0x8A8D, 0xECE4, 0xF9F1, + 0xECE5, 0x976D, 0xECE6, 0x9777, 0xECE7, 0xF9F2, 0xECE8, 0xF9F3, 0xECE9, 0x4E00, 0xECEA, 0x4F5A, 0xECEB, 0x4F7E, 0xECEC, 0x58F9, + 0xECED, 0x65E5, 0xECEE, 0x6EA2, 0xECEF, 0x9038, 0xECF0, 0x93B0, 0xECF1, 0x99B9, 0xECF2, 0x4EFB, 0xECF3, 0x58EC, 0xECF4, 0x598A, + 0xECF5, 0x59D9, 0xECF6, 0x6041, 0xECF7, 0xF9F4, 0xECF8, 0xF9F5, 0xECF9, 0x7A14, 0xECFA, 0xF9F6, 0xECFB, 0x834F, 0xECFC, 0x8CC3, + 0xECFD, 0x5165, 0xECFE, 0x5344, 0xEDA1, 0xF9F7, 0xEDA2, 0xF9F8, 0xEDA3, 0xF9F9, 0xEDA4, 0x4ECD, 0xEDA5, 0x5269, 0xEDA6, 0x5B55, + 0xEDA7, 0x82BF, 0xEDA8, 0x4ED4, 0xEDA9, 0x523A, 0xEDAA, 0x54A8, 0xEDAB, 0x59C9, 0xEDAC, 0x59FF, 0xEDAD, 0x5B50, 0xEDAE, 0x5B57, + 0xEDAF, 0x5B5C, 0xEDB0, 0x6063, 0xEDB1, 0x6148, 0xEDB2, 0x6ECB, 0xEDB3, 0x7099, 0xEDB4, 0x716E, 0xEDB5, 0x7386, 0xEDB6, 0x74F7, + 0xEDB7, 0x75B5, 0xEDB8, 0x78C1, 0xEDB9, 0x7D2B, 0xEDBA, 0x8005, 0xEDBB, 0x81EA, 0xEDBC, 0x8328, 0xEDBD, 0x8517, 0xEDBE, 0x85C9, + 0xEDBF, 0x8AEE, 0xEDC0, 0x8CC7, 0xEDC1, 0x96CC, 0xEDC2, 0x4F5C, 0xEDC3, 0x52FA, 0xEDC4, 0x56BC, 0xEDC5, 0x65AB, 0xEDC6, 0x6628, + 0xEDC7, 0x707C, 0xEDC8, 0x70B8, 0xEDC9, 0x7235, 0xEDCA, 0x7DBD, 0xEDCB, 0x828D, 0xEDCC, 0x914C, 0xEDCD, 0x96C0, 0xEDCE, 0x9D72, + 0xEDCF, 0x5B71, 0xEDD0, 0x68E7, 0xEDD1, 0x6B98, 0xEDD2, 0x6F7A, 0xEDD3, 0x76DE, 0xEDD4, 0x5C91, 0xEDD5, 0x66AB, 0xEDD6, 0x6F5B, + 0xEDD7, 0x7BB4, 0xEDD8, 0x7C2A, 0xEDD9, 0x8836, 0xEDDA, 0x96DC, 0xEDDB, 0x4E08, 0xEDDC, 0x4ED7, 0xEDDD, 0x5320, 0xEDDE, 0x5834, + 0xEDDF, 0x58BB, 0xEDE0, 0x58EF, 0xEDE1, 0x596C, 0xEDE2, 0x5C07, 0xEDE3, 0x5E33, 0xEDE4, 0x5E84, 0xEDE5, 0x5F35, 0xEDE6, 0x638C, + 0xEDE7, 0x66B2, 0xEDE8, 0x6756, 0xEDE9, 0x6A1F, 0xEDEA, 0x6AA3, 0xEDEB, 0x6B0C, 0xEDEC, 0x6F3F, 0xEDED, 0x7246, 0xEDEE, 0xF9FA, + 0xEDEF, 0x7350, 0xEDF0, 0x748B, 0xEDF1, 0x7AE0, 0xEDF2, 0x7CA7, 0xEDF3, 0x8178, 0xEDF4, 0x81DF, 0xEDF5, 0x81E7, 0xEDF6, 0x838A, + 0xEDF7, 0x846C, 0xEDF8, 0x8523, 0xEDF9, 0x8594, 0xEDFA, 0x85CF, 0xEDFB, 0x88DD, 0xEDFC, 0x8D13, 0xEDFD, 0x91AC, 0xEDFE, 0x9577, + 0xEEA1, 0x969C, 0xEEA2, 0x518D, 0xEEA3, 0x54C9, 0xEEA4, 0x5728, 0xEEA5, 0x5BB0, 0xEEA6, 0x624D, 0xEEA7, 0x6750, 0xEEA8, 0x683D, + 0xEEA9, 0x6893, 0xEEAA, 0x6E3D, 0xEEAB, 0x6ED3, 0xEEAC, 0x707D, 0xEEAD, 0x7E21, 0xEEAE, 0x88C1, 0xEEAF, 0x8CA1, 0xEEB0, 0x8F09, + 0xEEB1, 0x9F4B, 0xEEB2, 0x9F4E, 0xEEB3, 0x722D, 0xEEB4, 0x7B8F, 0xEEB5, 0x8ACD, 0xEEB6, 0x931A, 0xEEB7, 0x4F47, 0xEEB8, 0x4F4E, + 0xEEB9, 0x5132, 0xEEBA, 0x5480, 0xEEBB, 0x59D0, 0xEEBC, 0x5E95, 0xEEBD, 0x62B5, 0xEEBE, 0x6775, 0xEEBF, 0x696E, 0xEEC0, 0x6A17, + 0xEEC1, 0x6CAE, 0xEEC2, 0x6E1A, 0xEEC3, 0x72D9, 0xEEC4, 0x732A, 0xEEC5, 0x75BD, 0xEEC6, 0x7BB8, 0xEEC7, 0x7D35, 0xEEC8, 0x82E7, + 0xEEC9, 0x83F9, 0xEECA, 0x8457, 0xEECB, 0x85F7, 0xEECC, 0x8A5B, 0xEECD, 0x8CAF, 0xEECE, 0x8E87, 0xEECF, 0x9019, 0xEED0, 0x90B8, + 0xEED1, 0x96CE, 0xEED2, 0x9F5F, 0xEED3, 0x52E3, 0xEED4, 0x540A, 0xEED5, 0x5AE1, 0xEED6, 0x5BC2, 0xEED7, 0x6458, 0xEED8, 0x6575, + 0xEED9, 0x6EF4, 0xEEDA, 0x72C4, 0xEEDB, 0xF9FB, 0xEEDC, 0x7684, 0xEEDD, 0x7A4D, 0xEEDE, 0x7B1B, 0xEEDF, 0x7C4D, 0xEEE0, 0x7E3E, + 0xEEE1, 0x7FDF, 0xEEE2, 0x837B, 0xEEE3, 0x8B2B, 0xEEE4, 0x8CCA, 0xEEE5, 0x8D64, 0xEEE6, 0x8DE1, 0xEEE7, 0x8E5F, 0xEEE8, 0x8FEA, + 0xEEE9, 0x8FF9, 0xEEEA, 0x9069, 0xEEEB, 0x93D1, 0xEEEC, 0x4F43, 0xEEED, 0x4F7A, 0xEEEE, 0x50B3, 0xEEEF, 0x5168, 0xEEF0, 0x5178, + 0xEEF1, 0x524D, 0xEEF2, 0x526A, 0xEEF3, 0x5861, 0xEEF4, 0x587C, 0xEEF5, 0x5960, 0xEEF6, 0x5C08, 0xEEF7, 0x5C55, 0xEEF8, 0x5EDB, + 0xEEF9, 0x609B, 0xEEFA, 0x6230, 0xEEFB, 0x6813, 0xEEFC, 0x6BBF, 0xEEFD, 0x6C08, 0xEEFE, 0x6FB1, 0xEFA1, 0x714E, 0xEFA2, 0x7420, + 0xEFA3, 0x7530, 0xEFA4, 0x7538, 0xEFA5, 0x7551, 0xEFA6, 0x7672, 0xEFA7, 0x7B4C, 0xEFA8, 0x7B8B, 0xEFA9, 0x7BAD, 0xEFAA, 0x7BC6, + 0xEFAB, 0x7E8F, 0xEFAC, 0x8A6E, 0xEFAD, 0x8F3E, 0xEFAE, 0x8F49, 0xEFAF, 0x923F, 0xEFB0, 0x9293, 0xEFB1, 0x9322, 0xEFB2, 0x942B, + 0xEFB3, 0x96FB, 0xEFB4, 0x985A, 0xEFB5, 0x986B, 0xEFB6, 0x991E, 0xEFB7, 0x5207, 0xEFB8, 0x622A, 0xEFB9, 0x6298, 0xEFBA, 0x6D59, + 0xEFBB, 0x7664, 0xEFBC, 0x7ACA, 0xEFBD, 0x7BC0, 0xEFBE, 0x7D76, 0xEFBF, 0x5360, 0xEFC0, 0x5CBE, 0xEFC1, 0x5E97, 0xEFC2, 0x6F38, + 0xEFC3, 0x70B9, 0xEFC4, 0x7C98, 0xEFC5, 0x9711, 0xEFC6, 0x9B8E, 0xEFC7, 0x9EDE, 0xEFC8, 0x63A5, 0xEFC9, 0x647A, 0xEFCA, 0x8776, + 0xEFCB, 0x4E01, 0xEFCC, 0x4E95, 0xEFCD, 0x4EAD, 0xEFCE, 0x505C, 0xEFCF, 0x5075, 0xEFD0, 0x5448, 0xEFD1, 0x59C3, 0xEFD2, 0x5B9A, + 0xEFD3, 0x5E40, 0xEFD4, 0x5EAD, 0xEFD5, 0x5EF7, 0xEFD6, 0x5F81, 0xEFD7, 0x60C5, 0xEFD8, 0x633A, 0xEFD9, 0x653F, 0xEFDA, 0x6574, + 0xEFDB, 0x65CC, 0xEFDC, 0x6676, 0xEFDD, 0x6678, 0xEFDE, 0x67FE, 0xEFDF, 0x6968, 0xEFE0, 0x6A89, 0xEFE1, 0x6B63, 0xEFE2, 0x6C40, + 0xEFE3, 0x6DC0, 0xEFE4, 0x6DE8, 0xEFE5, 0x6E1F, 0xEFE6, 0x6E5E, 0xEFE7, 0x701E, 0xEFE8, 0x70A1, 0xEFE9, 0x738E, 0xEFEA, 0x73FD, + 0xEFEB, 0x753A, 0xEFEC, 0x775B, 0xEFED, 0x7887, 0xEFEE, 0x798E, 0xEFEF, 0x7A0B, 0xEFF0, 0x7A7D, 0xEFF1, 0x7CBE, 0xEFF2, 0x7D8E, + 0xEFF3, 0x8247, 0xEFF4, 0x8A02, 0xEFF5, 0x8AEA, 0xEFF6, 0x8C9E, 0xEFF7, 0x912D, 0xEFF8, 0x914A, 0xEFF9, 0x91D8, 0xEFFA, 0x9266, + 0xEFFB, 0x92CC, 0xEFFC, 0x9320, 0xEFFD, 0x9706, 0xEFFE, 0x9756, 0xF0A1, 0x975C, 0xF0A2, 0x9802, 0xF0A3, 0x9F0E, 0xF0A4, 0x5236, + 0xF0A5, 0x5291, 0xF0A6, 0x557C, 0xF0A7, 0x5824, 0xF0A8, 0x5E1D, 0xF0A9, 0x5F1F, 0xF0AA, 0x608C, 0xF0AB, 0x63D0, 0xF0AC, 0x68AF, + 0xF0AD, 0x6FDF, 0xF0AE, 0x796D, 0xF0AF, 0x7B2C, 0xF0B0, 0x81CD, 0xF0B1, 0x85BA, 0xF0B2, 0x88FD, 0xF0B3, 0x8AF8, 0xF0B4, 0x8E44, + 0xF0B5, 0x918D, 0xF0B6, 0x9664, 0xF0B7, 0x969B, 0xF0B8, 0x973D, 0xF0B9, 0x984C, 0xF0BA, 0x9F4A, 0xF0BB, 0x4FCE, 0xF0BC, 0x5146, + 0xF0BD, 0x51CB, 0xF0BE, 0x52A9, 0xF0BF, 0x5632, 0xF0C0, 0x5F14, 0xF0C1, 0x5F6B, 0xF0C2, 0x63AA, 0xF0C3, 0x64CD, 0xF0C4, 0x65E9, + 0xF0C5, 0x6641, 0xF0C6, 0x66FA, 0xF0C7, 0x66F9, 0xF0C8, 0x671D, 0xF0C9, 0x689D, 0xF0CA, 0x68D7, 0xF0CB, 0x69FD, 0xF0CC, 0x6F15, + 0xF0CD, 0x6F6E, 0xF0CE, 0x7167, 0xF0CF, 0x71E5, 0xF0D0, 0x722A, 0xF0D1, 0x74AA, 0xF0D2, 0x773A, 0xF0D3, 0x7956, 0xF0D4, 0x795A, + 0xF0D5, 0x79DF, 0xF0D6, 0x7A20, 0xF0D7, 0x7A95, 0xF0D8, 0x7C97, 0xF0D9, 0x7CDF, 0xF0DA, 0x7D44, 0xF0DB, 0x7E70, 0xF0DC, 0x8087, + 0xF0DD, 0x85FB, 0xF0DE, 0x86A4, 0xF0DF, 0x8A54, 0xF0E0, 0x8ABF, 0xF0E1, 0x8D99, 0xF0E2, 0x8E81, 0xF0E3, 0x9020, 0xF0E4, 0x906D, + 0xF0E5, 0x91E3, 0xF0E6, 0x963B, 0xF0E7, 0x96D5, 0xF0E8, 0x9CE5, 0xF0E9, 0x65CF, 0xF0EA, 0x7C07, 0xF0EB, 0x8DB3, 0xF0EC, 0x93C3, + 0xF0ED, 0x5B58, 0xF0EE, 0x5C0A, 0xF0EF, 0x5352, 0xF0F0, 0x62D9, 0xF0F1, 0x731D, 0xF0F2, 0x5027, 0xF0F3, 0x5B97, 0xF0F4, 0x5F9E, + 0xF0F5, 0x60B0, 0xF0F6, 0x616B, 0xF0F7, 0x68D5, 0xF0F8, 0x6DD9, 0xF0F9, 0x742E, 0xF0FA, 0x7A2E, 0xF0FB, 0x7D42, 0xF0FC, 0x7D9C, + 0xF0FD, 0x7E31, 0xF0FE, 0x816B, 0xF1A1, 0x8E2A, 0xF1A2, 0x8E35, 0xF1A3, 0x937E, 0xF1A4, 0x9418, 0xF1A5, 0x4F50, 0xF1A6, 0x5750, + 0xF1A7, 0x5DE6, 0xF1A8, 0x5EA7, 0xF1A9, 0x632B, 0xF1AA, 0x7F6A, 0xF1AB, 0x4E3B, 0xF1AC, 0x4F4F, 0xF1AD, 0x4F8F, 0xF1AE, 0x505A, + 0xF1AF, 0x59DD, 0xF1B0, 0x80C4, 0xF1B1, 0x546A, 0xF1B2, 0x5468, 0xF1B3, 0x55FE, 0xF1B4, 0x594F, 0xF1B5, 0x5B99, 0xF1B6, 0x5DDE, + 0xF1B7, 0x5EDA, 0xF1B8, 0x665D, 0xF1B9, 0x6731, 0xF1BA, 0x67F1, 0xF1BB, 0x682A, 0xF1BC, 0x6CE8, 0xF1BD, 0x6D32, 0xF1BE, 0x6E4A, + 0xF1BF, 0x6F8D, 0xF1C0, 0x70B7, 0xF1C1, 0x73E0, 0xF1C2, 0x7587, 0xF1C3, 0x7C4C, 0xF1C4, 0x7D02, 0xF1C5, 0x7D2C, 0xF1C6, 0x7DA2, + 0xF1C7, 0x821F, 0xF1C8, 0x86DB, 0xF1C9, 0x8A3B, 0xF1CA, 0x8A85, 0xF1CB, 0x8D70, 0xF1CC, 0x8E8A, 0xF1CD, 0x8F33, 0xF1CE, 0x9031, + 0xF1CF, 0x914E, 0xF1D0, 0x9152, 0xF1D1, 0x9444, 0xF1D2, 0x99D0, 0xF1D3, 0x7AF9, 0xF1D4, 0x7CA5, 0xF1D5, 0x4FCA, 0xF1D6, 0x5101, + 0xF1D7, 0x51C6, 0xF1D8, 0x57C8, 0xF1D9, 0x5BEF, 0xF1DA, 0x5CFB, 0xF1DB, 0x6659, 0xF1DC, 0x6A3D, 0xF1DD, 0x6D5A, 0xF1DE, 0x6E96, + 0xF1DF, 0x6FEC, 0xF1E0, 0x710C, 0xF1E1, 0x756F, 0xF1E2, 0x7AE3, 0xF1E3, 0x8822, 0xF1E4, 0x9021, 0xF1E5, 0x9075, 0xF1E6, 0x96CB, + 0xF1E7, 0x99FF, 0xF1E8, 0x8301, 0xF1E9, 0x4E2D, 0xF1EA, 0x4EF2, 0xF1EB, 0x8846, 0xF1EC, 0x91CD, 0xF1ED, 0x537D, 0xF1EE, 0x6ADB, + 0xF1EF, 0x696B, 0xF1F0, 0x6C41, 0xF1F1, 0x847A, 0xF1F2, 0x589E, 0xF1F3, 0x618E, 0xF1F4, 0x66FE, 0xF1F5, 0x62EF, 0xF1F6, 0x70DD, + 0xF1F7, 0x7511, 0xF1F8, 0x75C7, 0xF1F9, 0x7E52, 0xF1FA, 0x84B8, 0xF1FB, 0x8B49, 0xF1FC, 0x8D08, 0xF1FD, 0x4E4B, 0xF1FE, 0x53EA, + 0xF2A1, 0x54AB, 0xF2A2, 0x5730, 0xF2A3, 0x5740, 0xF2A4, 0x5FD7, 0xF2A5, 0x6301, 0xF2A6, 0x6307, 0xF2A7, 0x646F, 0xF2A8, 0x652F, + 0xF2A9, 0x65E8, 0xF2AA, 0x667A, 0xF2AB, 0x679D, 0xF2AC, 0x67B3, 0xF2AD, 0x6B62, 0xF2AE, 0x6C60, 0xF2AF, 0x6C9A, 0xF2B0, 0x6F2C, + 0xF2B1, 0x77E5, 0xF2B2, 0x7825, 0xF2B3, 0x7949, 0xF2B4, 0x7957, 0xF2B5, 0x7D19, 0xF2B6, 0x80A2, 0xF2B7, 0x8102, 0xF2B8, 0x81F3, + 0xF2B9, 0x829D, 0xF2BA, 0x82B7, 0xF2BB, 0x8718, 0xF2BC, 0x8A8C, 0xF2BD, 0xF9FC, 0xF2BE, 0x8D04, 0xF2BF, 0x8DBE, 0xF2C0, 0x9072, + 0xF2C1, 0x76F4, 0xF2C2, 0x7A19, 0xF2C3, 0x7A37, 0xF2C4, 0x7E54, 0xF2C5, 0x8077, 0xF2C6, 0x5507, 0xF2C7, 0x55D4, 0xF2C8, 0x5875, + 0xF2C9, 0x632F, 0xF2CA, 0x6422, 0xF2CB, 0x6649, 0xF2CC, 0x664B, 0xF2CD, 0x686D, 0xF2CE, 0x699B, 0xF2CF, 0x6B84, 0xF2D0, 0x6D25, + 0xF2D1, 0x6EB1, 0xF2D2, 0x73CD, 0xF2D3, 0x7468, 0xF2D4, 0x74A1, 0xF2D5, 0x755B, 0xF2D6, 0x75B9, 0xF2D7, 0x76E1, 0xF2D8, 0x771E, + 0xF2D9, 0x778B, 0xF2DA, 0x79E6, 0xF2DB, 0x7E09, 0xF2DC, 0x7E1D, 0xF2DD, 0x81FB, 0xF2DE, 0x852F, 0xF2DF, 0x8897, 0xF2E0, 0x8A3A, + 0xF2E1, 0x8CD1, 0xF2E2, 0x8EEB, 0xF2E3, 0x8FB0, 0xF2E4, 0x9032, 0xF2E5, 0x93AD, 0xF2E6, 0x9663, 0xF2E7, 0x9673, 0xF2E8, 0x9707, + 0xF2E9, 0x4F84, 0xF2EA, 0x53F1, 0xF2EB, 0x59EA, 0xF2EC, 0x5AC9, 0xF2ED, 0x5E19, 0xF2EE, 0x684E, 0xF2EF, 0x74C6, 0xF2F0, 0x75BE, + 0xF2F1, 0x79E9, 0xF2F2, 0x7A92, 0xF2F3, 0x81A3, 0xF2F4, 0x86ED, 0xF2F5, 0x8CEA, 0xF2F6, 0x8DCC, 0xF2F7, 0x8FED, 0xF2F8, 0x659F, + 0xF2F9, 0x6715, 0xF2FA, 0xF9FD, 0xF2FB, 0x57F7, 0xF2FC, 0x6F57, 0xF2FD, 0x7DDD, 0xF2FE, 0x8F2F, 0xF3A1, 0x93F6, 0xF3A2, 0x96C6, + 0xF3A3, 0x5FB5, 0xF3A4, 0x61F2, 0xF3A5, 0x6F84, 0xF3A6, 0x4E14, 0xF3A7, 0x4F98, 0xF3A8, 0x501F, 0xF3A9, 0x53C9, 0xF3AA, 0x55DF, + 0xF3AB, 0x5D6F, 0xF3AC, 0x5DEE, 0xF3AD, 0x6B21, 0xF3AE, 0x6B64, 0xF3AF, 0x78CB, 0xF3B0, 0x7B9A, 0xF3B1, 0xF9FE, 0xF3B2, 0x8E49, + 0xF3B3, 0x8ECA, 0xF3B4, 0x906E, 0xF3B5, 0x6349, 0xF3B6, 0x643E, 0xF3B7, 0x7740, 0xF3B8, 0x7A84, 0xF3B9, 0x932F, 0xF3BA, 0x947F, + 0xF3BB, 0x9F6A, 0xF3BC, 0x64B0, 0xF3BD, 0x6FAF, 0xF3BE, 0x71E6, 0xF3BF, 0x74A8, 0xF3C0, 0x74DA, 0xF3C1, 0x7AC4, 0xF3C2, 0x7C12, + 0xF3C3, 0x7E82, 0xF3C4, 0x7CB2, 0xF3C5, 0x7E98, 0xF3C6, 0x8B9A, 0xF3C7, 0x8D0A, 0xF3C8, 0x947D, 0xF3C9, 0x9910, 0xF3CA, 0x994C, + 0xF3CB, 0x5239, 0xF3CC, 0x5BDF, 0xF3CD, 0x64E6, 0xF3CE, 0x672D, 0xF3CF, 0x7D2E, 0xF3D0, 0x50ED, 0xF3D1, 0x53C3, 0xF3D2, 0x5879, + 0xF3D3, 0x6158, 0xF3D4, 0x6159, 0xF3D5, 0x61FA, 0xF3D6, 0x65AC, 0xF3D7, 0x7AD9, 0xF3D8, 0x8B92, 0xF3D9, 0x8B96, 0xF3DA, 0x5009, + 0xF3DB, 0x5021, 0xF3DC, 0x5275, 0xF3DD, 0x5531, 0xF3DE, 0x5A3C, 0xF3DF, 0x5EE0, 0xF3E0, 0x5F70, 0xF3E1, 0x6134, 0xF3E2, 0x655E, + 0xF3E3, 0x660C, 0xF3E4, 0x6636, 0xF3E5, 0x66A2, 0xF3E6, 0x69CD, 0xF3E7, 0x6EC4, 0xF3E8, 0x6F32, 0xF3E9, 0x7316, 0xF3EA, 0x7621, + 0xF3EB, 0x7A93, 0xF3EC, 0x8139, 0xF3ED, 0x8259, 0xF3EE, 0x83D6, 0xF3EF, 0x84BC, 0xF3F0, 0x50B5, 0xF3F1, 0x57F0, 0xF3F2, 0x5BC0, + 0xF3F3, 0x5BE8, 0xF3F4, 0x5F69, 0xF3F5, 0x63A1, 0xF3F6, 0x7826, 0xF3F7, 0x7DB5, 0xF3F8, 0x83DC, 0xF3F9, 0x8521, 0xF3FA, 0x91C7, + 0xF3FB, 0x91F5, 0xF3FC, 0x518A, 0xF3FD, 0x67F5, 0xF3FE, 0x7B56, 0xF4A1, 0x8CAC, 0xF4A2, 0x51C4, 0xF4A3, 0x59BB, 0xF4A4, 0x60BD, + 0xF4A5, 0x8655, 0xF4A6, 0x501C, 0xF4A7, 0xF9FF, 0xF4A8, 0x5254, 0xF4A9, 0x5C3A, 0xF4AA, 0x617D, 0xF4AB, 0x621A, 0xF4AC, 0x62D3, + 0xF4AD, 0x64F2, 0xF4AE, 0x65A5, 0xF4AF, 0x6ECC, 0xF4B0, 0x7620, 0xF4B1, 0x810A, 0xF4B2, 0x8E60, 0xF4B3, 0x965F, 0xF4B4, 0x96BB, + 0xF4B5, 0x4EDF, 0xF4B6, 0x5343, 0xF4B7, 0x5598, 0xF4B8, 0x5929, 0xF4B9, 0x5DDD, 0xF4BA, 0x64C5, 0xF4BB, 0x6CC9, 0xF4BC, 0x6DFA, + 0xF4BD, 0x7394, 0xF4BE, 0x7A7F, 0xF4BF, 0x821B, 0xF4C0, 0x85A6, 0xF4C1, 0x8CE4, 0xF4C2, 0x8E10, 0xF4C3, 0x9077, 0xF4C4, 0x91E7, + 0xF4C5, 0x95E1, 0xF4C6, 0x9621, 0xF4C7, 0x97C6, 0xF4C8, 0x51F8, 0xF4C9, 0x54F2, 0xF4CA, 0x5586, 0xF4CB, 0x5FB9, 0xF4CC, 0x64A4, + 0xF4CD, 0x6F88, 0xF4CE, 0x7DB4, 0xF4CF, 0x8F1F, 0xF4D0, 0x8F4D, 0xF4D1, 0x9435, 0xF4D2, 0x50C9, 0xF4D3, 0x5C16, 0xF4D4, 0x6CBE, + 0xF4D5, 0x6DFB, 0xF4D6, 0x751B, 0xF4D7, 0x77BB, 0xF4D8, 0x7C3D, 0xF4D9, 0x7C64, 0xF4DA, 0x8A79, 0xF4DB, 0x8AC2, 0xF4DC, 0x581E, + 0xF4DD, 0x59BE, 0xF4DE, 0x5E16, 0xF4DF, 0x6377, 0xF4E0, 0x7252, 0xF4E1, 0x758A, 0xF4E2, 0x776B, 0xF4E3, 0x8ADC, 0xF4E4, 0x8CBC, + 0xF4E5, 0x8F12, 0xF4E6, 0x5EF3, 0xF4E7, 0x6674, 0xF4E8, 0x6DF8, 0xF4E9, 0x807D, 0xF4EA, 0x83C1, 0xF4EB, 0x8ACB, 0xF4EC, 0x9751, + 0xF4ED, 0x9BD6, 0xF4EE, 0xFA00, 0xF4EF, 0x5243, 0xF4F0, 0x66FF, 0xF4F1, 0x6D95, 0xF4F2, 0x6EEF, 0xF4F3, 0x7DE0, 0xF4F4, 0x8AE6, + 0xF4F5, 0x902E, 0xF4F6, 0x905E, 0xF4F7, 0x9AD4, 0xF4F8, 0x521D, 0xF4F9, 0x527F, 0xF4FA, 0x54E8, 0xF4FB, 0x6194, 0xF4FC, 0x6284, + 0xF4FD, 0x62DB, 0xF4FE, 0x68A2, 0xF5A1, 0x6912, 0xF5A2, 0x695A, 0xF5A3, 0x6A35, 0xF5A4, 0x7092, 0xF5A5, 0x7126, 0xF5A6, 0x785D, + 0xF5A7, 0x7901, 0xF5A8, 0x790E, 0xF5A9, 0x79D2, 0xF5AA, 0x7A0D, 0xF5AB, 0x8096, 0xF5AC, 0x8278, 0xF5AD, 0x82D5, 0xF5AE, 0x8349, + 0xF5AF, 0x8549, 0xF5B0, 0x8C82, 0xF5B1, 0x8D85, 0xF5B2, 0x9162, 0xF5B3, 0x918B, 0xF5B4, 0x91AE, 0xF5B5, 0x4FC3, 0xF5B6, 0x56D1, + 0xF5B7, 0x71ED, 0xF5B8, 0x77D7, 0xF5B9, 0x8700, 0xF5BA, 0x89F8, 0xF5BB, 0x5BF8, 0xF5BC, 0x5FD6, 0xF5BD, 0x6751, 0xF5BE, 0x90A8, + 0xF5BF, 0x53E2, 0xF5C0, 0x585A, 0xF5C1, 0x5BF5, 0xF5C2, 0x60A4, 0xF5C3, 0x6181, 0xF5C4, 0x6460, 0xF5C5, 0x7E3D, 0xF5C6, 0x8070, + 0xF5C7, 0x8525, 0xF5C8, 0x9283, 0xF5C9, 0x64AE, 0xF5CA, 0x50AC, 0xF5CB, 0x5D14, 0xF5CC, 0x6700, 0xF5CD, 0x589C, 0xF5CE, 0x62BD, + 0xF5CF, 0x63A8, 0xF5D0, 0x690E, 0xF5D1, 0x6978, 0xF5D2, 0x6A1E, 0xF5D3, 0x6E6B, 0xF5D4, 0x76BA, 0xF5D5, 0x79CB, 0xF5D6, 0x82BB, + 0xF5D7, 0x8429, 0xF5D8, 0x8ACF, 0xF5D9, 0x8DA8, 0xF5DA, 0x8FFD, 0xF5DB, 0x9112, 0xF5DC, 0x914B, 0xF5DD, 0x919C, 0xF5DE, 0x9310, + 0xF5DF, 0x9318, 0xF5E0, 0x939A, 0xF5E1, 0x96DB, 0xF5E2, 0x9A36, 0xF5E3, 0x9C0D, 0xF5E4, 0x4E11, 0xF5E5, 0x755C, 0xF5E6, 0x795D, + 0xF5E7, 0x7AFA, 0xF5E8, 0x7B51, 0xF5E9, 0x7BC9, 0xF5EA, 0x7E2E, 0xF5EB, 0x84C4, 0xF5EC, 0x8E59, 0xF5ED, 0x8E74, 0xF5EE, 0x8EF8, + 0xF5EF, 0x9010, 0xF5F0, 0x6625, 0xF5F1, 0x693F, 0xF5F2, 0x7443, 0xF5F3, 0x51FA, 0xF5F4, 0x672E, 0xF5F5, 0x9EDC, 0xF5F6, 0x5145, + 0xF5F7, 0x5FE0, 0xF5F8, 0x6C96, 0xF5F9, 0x87F2, 0xF5FA, 0x885D, 0xF5FB, 0x8877, 0xF5FC, 0x60B4, 0xF5FD, 0x81B5, 0xF5FE, 0x8403, + 0xF6A1, 0x8D05, 0xF6A2, 0x53D6, 0xF6A3, 0x5439, 0xF6A4, 0x5634, 0xF6A5, 0x5A36, 0xF6A6, 0x5C31, 0xF6A7, 0x708A, 0xF6A8, 0x7FE0, + 0xF6A9, 0x805A, 0xF6AA, 0x8106, 0xF6AB, 0x81ED, 0xF6AC, 0x8DA3, 0xF6AD, 0x9189, 0xF6AE, 0x9A5F, 0xF6AF, 0x9DF2, 0xF6B0, 0x5074, + 0xF6B1, 0x4EC4, 0xF6B2, 0x53A0, 0xF6B3, 0x60FB, 0xF6B4, 0x6E2C, 0xF6B5, 0x5C64, 0xF6B6, 0x4F88, 0xF6B7, 0x5024, 0xF6B8, 0x55E4, + 0xF6B9, 0x5CD9, 0xF6BA, 0x5E5F, 0xF6BB, 0x6065, 0xF6BC, 0x6894, 0xF6BD, 0x6CBB, 0xF6BE, 0x6DC4, 0xF6BF, 0x71BE, 0xF6C0, 0x75D4, + 0xF6C1, 0x75F4, 0xF6C2, 0x7661, 0xF6C3, 0x7A1A, 0xF6C4, 0x7A49, 0xF6C5, 0x7DC7, 0xF6C6, 0x7DFB, 0xF6C7, 0x7F6E, 0xF6C8, 0x81F4, + 0xF6C9, 0x86A9, 0xF6CA, 0x8F1C, 0xF6CB, 0x96C9, 0xF6CC, 0x99B3, 0xF6CD, 0x9F52, 0xF6CE, 0x5247, 0xF6CF, 0x52C5, 0xF6D0, 0x98ED, + 0xF6D1, 0x89AA, 0xF6D2, 0x4E03, 0xF6D3, 0x67D2, 0xF6D4, 0x6F06, 0xF6D5, 0x4FB5, 0xF6D6, 0x5BE2, 0xF6D7, 0x6795, 0xF6D8, 0x6C88, + 0xF6D9, 0x6D78, 0xF6DA, 0x741B, 0xF6DB, 0x7827, 0xF6DC, 0x91DD, 0xF6DD, 0x937C, 0xF6DE, 0x87C4, 0xF6DF, 0x79E4, 0xF6E0, 0x7A31, + 0xF6E1, 0x5FEB, 0xF6E2, 0x4ED6, 0xF6E3, 0x54A4, 0xF6E4, 0x553E, 0xF6E5, 0x58AE, 0xF6E6, 0x59A5, 0xF6E7, 0x60F0, 0xF6E8, 0x6253, + 0xF6E9, 0x62D6, 0xF6EA, 0x6736, 0xF6EB, 0x6955, 0xF6EC, 0x8235, 0xF6ED, 0x9640, 0xF6EE, 0x99B1, 0xF6EF, 0x99DD, 0xF6F0, 0x502C, + 0xF6F1, 0x5353, 0xF6F2, 0x5544, 0xF6F3, 0x577C, 0xF6F4, 0xFA01, 0xF6F5, 0x6258, 0xF6F6, 0xFA02, 0xF6F7, 0x64E2, 0xF6F8, 0x666B, + 0xF6F9, 0x67DD, 0xF6FA, 0x6FC1, 0xF6FB, 0x6FEF, 0xF6FC, 0x7422, 0xF6FD, 0x7438, 0xF6FE, 0x8A17, 0xF7A1, 0x9438, 0xF7A2, 0x5451, + 0xF7A3, 0x5606, 0xF7A4, 0x5766, 0xF7A5, 0x5F48, 0xF7A6, 0x619A, 0xF7A7, 0x6B4E, 0xF7A8, 0x7058, 0xF7A9, 0x70AD, 0xF7AA, 0x7DBB, + 0xF7AB, 0x8A95, 0xF7AC, 0x596A, 0xF7AD, 0x812B, 0xF7AE, 0x63A2, 0xF7AF, 0x7708, 0xF7B0, 0x803D, 0xF7B1, 0x8CAA, 0xF7B2, 0x5854, + 0xF7B3, 0x642D, 0xF7B4, 0x69BB, 0xF7B5, 0x5B95, 0xF7B6, 0x5E11, 0xF7B7, 0x6E6F, 0xF7B8, 0xFA03, 0xF7B9, 0x8569, 0xF7BA, 0x514C, + 0xF7BB, 0x53F0, 0xF7BC, 0x592A, 0xF7BD, 0x6020, 0xF7BE, 0x614B, 0xF7BF, 0x6B86, 0xF7C0, 0x6C70, 0xF7C1, 0x6CF0, 0xF7C2, 0x7B1E, + 0xF7C3, 0x80CE, 0xF7C4, 0x82D4, 0xF7C5, 0x8DC6, 0xF7C6, 0x90B0, 0xF7C7, 0x98B1, 0xF7C8, 0xFA04, 0xF7C9, 0x64C7, 0xF7CA, 0x6FA4, + 0xF7CB, 0x6491, 0xF7CC, 0x6504, 0xF7CD, 0x514E, 0xF7CE, 0x5410, 0xF7CF, 0x571F, 0xF7D0, 0x8A0E, 0xF7D1, 0x615F, 0xF7D2, 0x6876, + 0xF7D3, 0xFA05, 0xF7D4, 0x75DB, 0xF7D5, 0x7B52, 0xF7D6, 0x7D71, 0xF7D7, 0x901A, 0xF7D8, 0x5806, 0xF7D9, 0x69CC, 0xF7DA, 0x817F, + 0xF7DB, 0x892A, 0xF7DC, 0x9000, 0xF7DD, 0x9839, 0xF7DE, 0x5078, 0xF7DF, 0x5957, 0xF7E0, 0x59AC, 0xF7E1, 0x6295, 0xF7E2, 0x900F, + 0xF7E3, 0x9B2A, 0xF7E4, 0x615D, 0xF7E5, 0x7279, 0xF7E6, 0x95D6, 0xF7E7, 0x5761, 0xF7E8, 0x5A46, 0xF7E9, 0x5DF4, 0xF7EA, 0x628A, + 0xF7EB, 0x64AD, 0xF7EC, 0x64FA, 0xF7ED, 0x6777, 0xF7EE, 0x6CE2, 0xF7EF, 0x6D3E, 0xF7F0, 0x722C, 0xF7F1, 0x7436, 0xF7F2, 0x7834, + 0xF7F3, 0x7F77, 0xF7F4, 0x82AD, 0xF7F5, 0x8DDB, 0xF7F6, 0x9817, 0xF7F7, 0x5224, 0xF7F8, 0x5742, 0xF7F9, 0x677F, 0xF7FA, 0x7248, + 0xF7FB, 0x74E3, 0xF7FC, 0x8CA9, 0xF7FD, 0x8FA6, 0xF7FE, 0x9211, 0xF8A1, 0x962A, 0xF8A2, 0x516B, 0xF8A3, 0x53ED, 0xF8A4, 0x634C, + 0xF8A5, 0x4F69, 0xF8A6, 0x5504, 0xF8A7, 0x6096, 0xF8A8, 0x6557, 0xF8A9, 0x6C9B, 0xF8AA, 0x6D7F, 0xF8AB, 0x724C, 0xF8AC, 0x72FD, + 0xF8AD, 0x7A17, 0xF8AE, 0x8987, 0xF8AF, 0x8C9D, 0xF8B0, 0x5F6D, 0xF8B1, 0x6F8E, 0xF8B2, 0x70F9, 0xF8B3, 0x81A8, 0xF8B4, 0x610E, + 0xF8B5, 0x4FBF, 0xF8B6, 0x504F, 0xF8B7, 0x6241, 0xF8B8, 0x7247, 0xF8B9, 0x7BC7, 0xF8BA, 0x7DE8, 0xF8BB, 0x7FE9, 0xF8BC, 0x904D, + 0xF8BD, 0x97AD, 0xF8BE, 0x9A19, 0xF8BF, 0x8CB6, 0xF8C0, 0x576A, 0xF8C1, 0x5E73, 0xF8C2, 0x67B0, 0xF8C3, 0x840D, 0xF8C4, 0x8A55, + 0xF8C5, 0x5420, 0xF8C6, 0x5B16, 0xF8C7, 0x5E63, 0xF8C8, 0x5EE2, 0xF8C9, 0x5F0A, 0xF8CA, 0x6583, 0xF8CB, 0x80BA, 0xF8CC, 0x853D, + 0xF8CD, 0x9589, 0xF8CE, 0x965B, 0xF8CF, 0x4F48, 0xF8D0, 0x5305, 0xF8D1, 0x530D, 0xF8D2, 0x530F, 0xF8D3, 0x5486, 0xF8D4, 0x54FA, + 0xF8D5, 0x5703, 0xF8D6, 0x5E03, 0xF8D7, 0x6016, 0xF8D8, 0x629B, 0xF8D9, 0x62B1, 0xF8DA, 0x6355, 0xF8DB, 0xFA06, 0xF8DC, 0x6CE1, + 0xF8DD, 0x6D66, 0xF8DE, 0x75B1, 0xF8DF, 0x7832, 0xF8E0, 0x80DE, 0xF8E1, 0x812F, 0xF8E2, 0x82DE, 0xF8E3, 0x8461, 0xF8E4, 0x84B2, + 0xF8E5, 0x888D, 0xF8E6, 0x8912, 0xF8E7, 0x900B, 0xF8E8, 0x92EA, 0xF8E9, 0x98FD, 0xF8EA, 0x9B91, 0xF8EB, 0x5E45, 0xF8EC, 0x66B4, + 0xF8ED, 0x66DD, 0xF8EE, 0x7011, 0xF8EF, 0x7206, 0xF8F0, 0xFA07, 0xF8F1, 0x4FF5, 0xF8F2, 0x527D, 0xF8F3, 0x5F6A, 0xF8F4, 0x6153, + 0xF8F5, 0x6753, 0xF8F6, 0x6A19, 0xF8F7, 0x6F02, 0xF8F8, 0x74E2, 0xF8F9, 0x7968, 0xF8FA, 0x8868, 0xF8FB, 0x8C79, 0xF8FC, 0x98C7, + 0xF8FD, 0x98C4, 0xF8FE, 0x9A43, 0xF9A1, 0x54C1, 0xF9A2, 0x7A1F, 0xF9A3, 0x6953, 0xF9A4, 0x8AF7, 0xF9A5, 0x8C4A, 0xF9A6, 0x98A8, + 0xF9A7, 0x99AE, 0xF9A8, 0x5F7C, 0xF9A9, 0x62AB, 0xF9AA, 0x75B2, 0xF9AB, 0x76AE, 0xF9AC, 0x88AB, 0xF9AD, 0x907F, 0xF9AE, 0x9642, + 0xF9AF, 0x5339, 0xF9B0, 0x5F3C, 0xF9B1, 0x5FC5, 0xF9B2, 0x6CCC, 0xF9B3, 0x73CC, 0xF9B4, 0x7562, 0xF9B5, 0x758B, 0xF9B6, 0x7B46, + 0xF9B7, 0x82FE, 0xF9B8, 0x999D, 0xF9B9, 0x4E4F, 0xF9BA, 0x903C, 0xF9BB, 0x4E0B, 0xF9BC, 0x4F55, 0xF9BD, 0x53A6, 0xF9BE, 0x590F, + 0xF9BF, 0x5EC8, 0xF9C0, 0x6630, 0xF9C1, 0x6CB3, 0xF9C2, 0x7455, 0xF9C3, 0x8377, 0xF9C4, 0x8766, 0xF9C5, 0x8CC0, 0xF9C6, 0x9050, + 0xF9C7, 0x971E, 0xF9C8, 0x9C15, 0xF9C9, 0x58D1, 0xF9CA, 0x5B78, 0xF9CB, 0x8650, 0xF9CC, 0x8B14, 0xF9CD, 0x9DB4, 0xF9CE, 0x5BD2, + 0xF9CF, 0x6068, 0xF9D0, 0x608D, 0xF9D1, 0x65F1, 0xF9D2, 0x6C57, 0xF9D3, 0x6F22, 0xF9D4, 0x6FA3, 0xF9D5, 0x701A, 0xF9D6, 0x7F55, + 0xF9D7, 0x7FF0, 0xF9D8, 0x9591, 0xF9D9, 0x9592, 0xF9DA, 0x9650, 0xF9DB, 0x97D3, 0xF9DC, 0x5272, 0xF9DD, 0x8F44, 0xF9DE, 0x51FD, + 0xF9DF, 0x542B, 0xF9E0, 0x54B8, 0xF9E1, 0x5563, 0xF9E2, 0x558A, 0xF9E3, 0x6ABB, 0xF9E4, 0x6DB5, 0xF9E5, 0x7DD8, 0xF9E6, 0x8266, + 0xF9E7, 0x929C, 0xF9E8, 0x9677, 0xF9E9, 0x9E79, 0xF9EA, 0x5408, 0xF9EB, 0x54C8, 0xF9EC, 0x76D2, 0xF9ED, 0x86E4, 0xF9EE, 0x95A4, + 0xF9EF, 0x95D4, 0xF9F0, 0x965C, 0xF9F1, 0x4EA2, 0xF9F2, 0x4F09, 0xF9F3, 0x59EE, 0xF9F4, 0x5AE6, 0xF9F5, 0x5DF7, 0xF9F6, 0x6052, + 0xF9F7, 0x6297, 0xF9F8, 0x676D, 0xF9F9, 0x6841, 0xF9FA, 0x6C86, 0xF9FB, 0x6E2F, 0xF9FC, 0x7F38, 0xF9FD, 0x809B, 0xF9FE, 0x822A, + 0xFAA1, 0xFA08, 0xFAA2, 0xFA09, 0xFAA3, 0x9805, 0xFAA4, 0x4EA5, 0xFAA5, 0x5055, 0xFAA6, 0x54B3, 0xFAA7, 0x5793, 0xFAA8, 0x595A, + 0xFAA9, 0x5B69, 0xFAAA, 0x5BB3, 0xFAAB, 0x61C8, 0xFAAC, 0x6977, 0xFAAD, 0x6D77, 0xFAAE, 0x7023, 0xFAAF, 0x87F9, 0xFAB0, 0x89E3, + 0xFAB1, 0x8A72, 0xFAB2, 0x8AE7, 0xFAB3, 0x9082, 0xFAB4, 0x99ED, 0xFAB5, 0x9AB8, 0xFAB6, 0x52BE, 0xFAB7, 0x6838, 0xFAB8, 0x5016, + 0xFAB9, 0x5E78, 0xFABA, 0x674F, 0xFABB, 0x8347, 0xFABC, 0x884C, 0xFABD, 0x4EAB, 0xFABE, 0x5411, 0xFABF, 0x56AE, 0xFAC0, 0x73E6, + 0xFAC1, 0x9115, 0xFAC2, 0x97FF, 0xFAC3, 0x9909, 0xFAC4, 0x9957, 0xFAC5, 0x9999, 0xFAC6, 0x5653, 0xFAC7, 0x589F, 0xFAC8, 0x865B, + 0xFAC9, 0x8A31, 0xFACA, 0x61B2, 0xFACB, 0x6AF6, 0xFACC, 0x737B, 0xFACD, 0x8ED2, 0xFACE, 0x6B47, 0xFACF, 0x96AA, 0xFAD0, 0x9A57, + 0xFAD1, 0x5955, 0xFAD2, 0x7200, 0xFAD3, 0x8D6B, 0xFAD4, 0x9769, 0xFAD5, 0x4FD4, 0xFAD6, 0x5CF4, 0xFAD7, 0x5F26, 0xFAD8, 0x61F8, + 0xFAD9, 0x665B, 0xFADA, 0x6CEB, 0xFADB, 0x70AB, 0xFADC, 0x7384, 0xFADD, 0x73B9, 0xFADE, 0x73FE, 0xFADF, 0x7729, 0xFAE0, 0x774D, + 0xFAE1, 0x7D43, 0xFAE2, 0x7D62, 0xFAE3, 0x7E23, 0xFAE4, 0x8237, 0xFAE5, 0x8852, 0xFAE6, 0xFA0A, 0xFAE7, 0x8CE2, 0xFAE8, 0x9249, + 0xFAE9, 0x986F, 0xFAEA, 0x5B51, 0xFAEB, 0x7A74, 0xFAEC, 0x8840, 0xFAED, 0x9801, 0xFAEE, 0x5ACC, 0xFAEF, 0x4FE0, 0xFAF0, 0x5354, + 0xFAF1, 0x593E, 0xFAF2, 0x5CFD, 0xFAF3, 0x633E, 0xFAF4, 0x6D79, 0xFAF5, 0x72F9, 0xFAF6, 0x8105, 0xFAF7, 0x8107, 0xFAF8, 0x83A2, + 0xFAF9, 0x92CF, 0xFAFA, 0x9830, 0xFAFB, 0x4EA8, 0xFAFC, 0x5144, 0xFAFD, 0x5211, 0xFAFE, 0x578B, 0xFBA1, 0x5F62, 0xFBA2, 0x6CC2, + 0xFBA3, 0x6ECE, 0xFBA4, 0x7005, 0xFBA5, 0x7050, 0xFBA6, 0x70AF, 0xFBA7, 0x7192, 0xFBA8, 0x73E9, 0xFBA9, 0x7469, 0xFBAA, 0x834A, + 0xFBAB, 0x87A2, 0xFBAC, 0x8861, 0xFBAD, 0x9008, 0xFBAE, 0x90A2, 0xFBAF, 0x93A3, 0xFBB0, 0x99A8, 0xFBB1, 0x516E, 0xFBB2, 0x5F57, + 0xFBB3, 0x60E0, 0xFBB4, 0x6167, 0xFBB5, 0x66B3, 0xFBB6, 0x8559, 0xFBB7, 0x8E4A, 0xFBB8, 0x91AF, 0xFBB9, 0x978B, 0xFBBA, 0x4E4E, + 0xFBBB, 0x4E92, 0xFBBC, 0x547C, 0xFBBD, 0x58D5, 0xFBBE, 0x58FA, 0xFBBF, 0x597D, 0xFBC0, 0x5CB5, 0xFBC1, 0x5F27, 0xFBC2, 0x6236, + 0xFBC3, 0x6248, 0xFBC4, 0x660A, 0xFBC5, 0x6667, 0xFBC6, 0x6BEB, 0xFBC7, 0x6D69, 0xFBC8, 0x6DCF, 0xFBC9, 0x6E56, 0xFBCA, 0x6EF8, + 0xFBCB, 0x6F94, 0xFBCC, 0x6FE0, 0xFBCD, 0x6FE9, 0xFBCE, 0x705D, 0xFBCF, 0x72D0, 0xFBD0, 0x7425, 0xFBD1, 0x745A, 0xFBD2, 0x74E0, + 0xFBD3, 0x7693, 0xFBD4, 0x795C, 0xFBD5, 0x7CCA, 0xFBD6, 0x7E1E, 0xFBD7, 0x80E1, 0xFBD8, 0x82A6, 0xFBD9, 0x846B, 0xFBDA, 0x84BF, + 0xFBDB, 0x864E, 0xFBDC, 0x865F, 0xFBDD, 0x8774, 0xFBDE, 0x8B77, 0xFBDF, 0x8C6A, 0xFBE0, 0x93AC, 0xFBE1, 0x9800, 0xFBE2, 0x9865, + 0xFBE3, 0x60D1, 0xFBE4, 0x6216, 0xFBE5, 0x9177, 0xFBE6, 0x5A5A, 0xFBE7, 0x660F, 0xFBE8, 0x6DF7, 0xFBE9, 0x6E3E, 0xFBEA, 0x743F, + 0xFBEB, 0x9B42, 0xFBEC, 0x5FFD, 0xFBED, 0x60DA, 0xFBEE, 0x7B0F, 0xFBEF, 0x54C4, 0xFBF0, 0x5F18, 0xFBF1, 0x6C5E, 0xFBF2, 0x6CD3, + 0xFBF3, 0x6D2A, 0xFBF4, 0x70D8, 0xFBF5, 0x7D05, 0xFBF6, 0x8679, 0xFBF7, 0x8A0C, 0xFBF8, 0x9D3B, 0xFBF9, 0x5316, 0xFBFA, 0x548C, + 0xFBFB, 0x5B05, 0xFBFC, 0x6A3A, 0xFBFD, 0x706B, 0xFBFE, 0x7575, 0xFCA1, 0x798D, 0xFCA2, 0x79BE, 0xFCA3, 0x82B1, 0xFCA4, 0x83EF, + 0xFCA5, 0x8A71, 0xFCA6, 0x8B41, 0xFCA7, 0x8CA8, 0xFCA8, 0x9774, 0xFCA9, 0xFA0B, 0xFCAA, 0x64F4, 0xFCAB, 0x652B, 0xFCAC, 0x78BA, + 0xFCAD, 0x78BB, 0xFCAE, 0x7A6B, 0xFCAF, 0x4E38, 0xFCB0, 0x559A, 0xFCB1, 0x5950, 0xFCB2, 0x5BA6, 0xFCB3, 0x5E7B, 0xFCB4, 0x60A3, + 0xFCB5, 0x63DB, 0xFCB6, 0x6B61, 0xFCB7, 0x6665, 0xFCB8, 0x6853, 0xFCB9, 0x6E19, 0xFCBA, 0x7165, 0xFCBB, 0x74B0, 0xFCBC, 0x7D08, + 0xFCBD, 0x9084, 0xFCBE, 0x9A69, 0xFCBF, 0x9C25, 0xFCC0, 0x6D3B, 0xFCC1, 0x6ED1, 0xFCC2, 0x733E, 0xFCC3, 0x8C41, 0xFCC4, 0x95CA, + 0xFCC5, 0x51F0, 0xFCC6, 0x5E4C, 0xFCC7, 0x5FA8, 0xFCC8, 0x604D, 0xFCC9, 0x60F6, 0xFCCA, 0x6130, 0xFCCB, 0x614C, 0xFCCC, 0x6643, + 0xFCCD, 0x6644, 0xFCCE, 0x69A5, 0xFCCF, 0x6CC1, 0xFCD0, 0x6E5F, 0xFCD1, 0x6EC9, 0xFCD2, 0x6F62, 0xFCD3, 0x714C, 0xFCD4, 0x749C, + 0xFCD5, 0x7687, 0xFCD6, 0x7BC1, 0xFCD7, 0x7C27, 0xFCD8, 0x8352, 0xFCD9, 0x8757, 0xFCDA, 0x9051, 0xFCDB, 0x968D, 0xFCDC, 0x9EC3, + 0xFCDD, 0x532F, 0xFCDE, 0x56DE, 0xFCDF, 0x5EFB, 0xFCE0, 0x5F8A, 0xFCE1, 0x6062, 0xFCE2, 0x6094, 0xFCE3, 0x61F7, 0xFCE4, 0x6666, + 0xFCE5, 0x6703, 0xFCE6, 0x6A9C, 0xFCE7, 0x6DEE, 0xFCE8, 0x6FAE, 0xFCE9, 0x7070, 0xFCEA, 0x736A, 0xFCEB, 0x7E6A, 0xFCEC, 0x81BE, + 0xFCED, 0x8334, 0xFCEE, 0x86D4, 0xFCEF, 0x8AA8, 0xFCF0, 0x8CC4, 0xFCF1, 0x5283, 0xFCF2, 0x7372, 0xFCF3, 0x5B96, 0xFCF4, 0x6A6B, + 0xFCF5, 0x9404, 0xFCF6, 0x54EE, 0xFCF7, 0x5686, 0xFCF8, 0x5B5D, 0xFCF9, 0x6548, 0xFCFA, 0x6585, 0xFCFB, 0x66C9, 0xFCFC, 0x689F, + 0xFCFD, 0x6D8D, 0xFCFE, 0x6DC6, 0xFDA1, 0x723B, 0xFDA2, 0x80B4, 0xFDA3, 0x9175, 0xFDA4, 0x9A4D, 0xFDA5, 0x4FAF, 0xFDA6, 0x5019, + 0xFDA7, 0x539A, 0xFDA8, 0x540E, 0xFDA9, 0x543C, 0xFDAA, 0x5589, 0xFDAB, 0x55C5, 0xFDAC, 0x5E3F, 0xFDAD, 0x5F8C, 0xFDAE, 0x673D, + 0xFDAF, 0x7166, 0xFDB0, 0x73DD, 0xFDB1, 0x9005, 0xFDB2, 0x52DB, 0xFDB3, 0x52F3, 0xFDB4, 0x5864, 0xFDB5, 0x58CE, 0xFDB6, 0x7104, + 0xFDB7, 0x718F, 0xFDB8, 0x71FB, 0xFDB9, 0x85B0, 0xFDBA, 0x8A13, 0xFDBB, 0x6688, 0xFDBC, 0x85A8, 0xFDBD, 0x55A7, 0xFDBE, 0x6684, + 0xFDBF, 0x714A, 0xFDC0, 0x8431, 0xFDC1, 0x5349, 0xFDC2, 0x5599, 0xFDC3, 0x6BC1, 0xFDC4, 0x5F59, 0xFDC5, 0x5FBD, 0xFDC6, 0x63EE, + 0xFDC7, 0x6689, 0xFDC8, 0x7147, 0xFDC9, 0x8AF1, 0xFDCA, 0x8F1D, 0xFDCB, 0x9EBE, 0xFDCC, 0x4F11, 0xFDCD, 0x643A, 0xFDCE, 0x70CB, + 0xFDCF, 0x7566, 0xFDD0, 0x8667, 0xFDD1, 0x6064, 0xFDD2, 0x8B4E, 0xFDD3, 0x9DF8, 0xFDD4, 0x5147, 0xFDD5, 0x51F6, 0xFDD6, 0x5308, + 0xFDD7, 0x6D36, 0xFDD8, 0x80F8, 0xFDD9, 0x9ED1, 0xFDDA, 0x6615, 0xFDDB, 0x6B23, 0xFDDC, 0x7098, 0xFDDD, 0x75D5, 0xFDDE, 0x5403, + 0xFDDF, 0x5C79, 0xFDE0, 0x7D07, 0xFDE1, 0x8A16, 0xFDE2, 0x6B20, 0xFDE3, 0x6B3D, 0xFDE4, 0x6B46, 0xFDE5, 0x5438, 0xFDE6, 0x6070, + 0xFDE7, 0x6D3D, 0xFDE8, 0x7FD5, 0xFDE9, 0x8208, 0xFDEA, 0x50D6, 0xFDEB, 0x51DE, 0xFDEC, 0x559C, 0xFDED, 0x566B, 0xFDEE, 0x56CD, + 0xFDEF, 0x59EC, 0xFDF0, 0x5B09, 0xFDF1, 0x5E0C, 0xFDF2, 0x6199, 0xFDF3, 0x6198, 0xFDF4, 0x6231, 0xFDF5, 0x665E, 0xFDF6, 0x66E6, + 0xFDF7, 0x7199, 0xFDF8, 0x71B9, 0xFDF9, 0x71BA, 0xFDFA, 0x72A7, 0xFDFB, 0x79A7, 0xFDFC, 0x7A00, 0xFDFD, 0x7FB2, 0xFDFE, 0x8A70, + 0, 0 +}; +#endif + +#if FF_CODE_PAGE == 950 || FF_CODE_PAGE == 0 /* Traditional Chinese */ +static +const WCHAR uni2oem950[] = { /* Unicode --> Big5 pairs */ + 0x00A7, 0xA1B1, 0x00AF, 0xA1C2, 0x00B0, 0xA258, 0x00B1, 0xA1D3, 0x00B7, 0xA150, 0x00D7, 0xA1D1, 0x00F7, 0xA1D2, 0x02C7, 0xA3BE, + 0x02C9, 0xA3BC, 0x02CA, 0xA3BD, 0x02CB, 0xA3BF, 0x02CD, 0xA1C5, 0x02D9, 0xA3BB, 0x0391, 0xA344, 0x0392, 0xA345, 0x0393, 0xA346, + 0x0394, 0xA347, 0x0395, 0xA348, 0x0396, 0xA349, 0x0397, 0xA34A, 0x0398, 0xA34B, 0x0399, 0xA34C, 0x039A, 0xA34D, 0x039B, 0xA34E, + 0x039C, 0xA34F, 0x039D, 0xA350, 0x039E, 0xA351, 0x039F, 0xA352, 0x03A0, 0xA353, 0x03A1, 0xA354, 0x03A3, 0xA355, 0x03A4, 0xA356, + 0x03A5, 0xA357, 0x03A6, 0xA358, 0x03A7, 0xA359, 0x03A8, 0xA35A, 0x03A9, 0xA35B, 0x03B1, 0xA35C, 0x03B2, 0xA35D, 0x03B3, 0xA35E, + 0x03B4, 0xA35F, 0x03B5, 0xA360, 0x03B6, 0xA361, 0x03B7, 0xA362, 0x03B8, 0xA363, 0x03B9, 0xA364, 0x03BA, 0xA365, 0x03BB, 0xA366, + 0x03BC, 0xA367, 0x03BD, 0xA368, 0x03BE, 0xA369, 0x03BF, 0xA36A, 0x03C0, 0xA36B, 0x03C1, 0xA36C, 0x03C3, 0xA36D, 0x03C4, 0xA36E, + 0x03C5, 0xA36F, 0x03C6, 0xA370, 0x03C7, 0xA371, 0x03C8, 0xA372, 0x03C9, 0xA373, 0x2013, 0xA156, 0x2014, 0xA158, 0x2018, 0xA1A5, + 0x2019, 0xA1A6, 0x201C, 0xA1A7, 0x201D, 0xA1A8, 0x2025, 0xA14C, 0x2026, 0xA14B, 0x2027, 0xA145, 0x2032, 0xA1AC, 0x2035, 0xA1AB, + 0x203B, 0xA1B0, 0x20AC, 0xA3E1, 0x2103, 0xA24A, 0x2105, 0xA1C1, 0x2109, 0xA24B, 0x2160, 0xA2B9, 0x2161, 0xA2BA, 0x2162, 0xA2BB, + 0x2163, 0xA2BC, 0x2164, 0xA2BD, 0x2165, 0xA2BE, 0x2166, 0xA2BF, 0x2167, 0xA2C0, 0x2168, 0xA2C1, 0x2169, 0xA2C2, 0x2190, 0xA1F6, + 0x2191, 0xA1F4, 0x2192, 0xA1F7, 0x2193, 0xA1F5, 0x2196, 0xA1F8, 0x2197, 0xA1F9, 0x2198, 0xA1FB, 0x2199, 0xA1FA, 0x2215, 0xA241, + 0x221A, 0xA1D4, 0x221E, 0xA1DB, 0x221F, 0xA1E8, 0x2220, 0xA1E7, 0x2223, 0xA1FD, 0x2225, 0xA1FC, 0x2229, 0xA1E4, 0x222A, 0xA1E5, + 0x222B, 0xA1EC, 0x222E, 0xA1ED, 0x2234, 0xA1EF, 0x2235, 0xA1EE, 0x2252, 0xA1DC, 0x2260, 0xA1DA, 0x2261, 0xA1DD, 0x2266, 0xA1D8, + 0x2267, 0xA1D9, 0x2295, 0xA1F2, 0x2299, 0xA1F3, 0x22A5, 0xA1E6, 0x22BF, 0xA1E9, 0x2500, 0xA277, 0x2502, 0xA278, 0x250C, 0xA27A, + 0x2510, 0xA27B, 0x2514, 0xA27C, 0x2518, 0xA27D, 0x251C, 0xA275, 0x2524, 0xA274, 0x252C, 0xA273, 0x2534, 0xA272, 0x253C, 0xA271, + 0x2550, 0xA2A4, 0x2550, 0xF9F9, 0x2551, 0xF9F8, 0x2552, 0xF9E6, 0x2553, 0xF9EF, 0x2554, 0xF9DD, 0x2555, 0xF9E8, 0x2556, 0xF9F1, + 0x2557, 0xF9DF, 0x2558, 0xF9EC, 0x2559, 0xF9F5, 0x255A, 0xF9E3, 0x255B, 0xF9EE, 0x255C, 0xF9F7, 0x255D, 0xF9E5, 0x255E, 0xA2A5, + 0x255E, 0xF9E9, 0x255F, 0xF9F2, 0x2560, 0xF9E0, 0x2561, 0xA2A7, 0x2561, 0xF9EB, 0x2562, 0xF9F4, 0x2563, 0xF9E2, 0x2564, 0xF9E7, + 0x2565, 0xF9F0, 0x2566, 0xF9DE, 0x2567, 0xF9ED, 0x2568, 0xF9F6, 0x2569, 0xF9E4, 0x256A, 0xA2A6, 0x256A, 0xF9EA, 0x256B, 0xF9F3, + 0x256C, 0xF9E1, 0x256D, 0xA27E, 0x256D, 0xF9FA, 0x256E, 0xA2A1, 0x256E, 0xF9FB, 0x256F, 0xA2A3, 0x256F, 0xF9FD, 0x2570, 0xA2A2, + 0x2570, 0xF9FC, 0x2571, 0xA2AC, 0x2572, 0xA2AD, 0x2573, 0xA2AE, 0x2574, 0xA15A, 0x2581, 0xA262, 0x2582, 0xA263, 0x2583, 0xA264, + 0x2584, 0xA265, 0x2585, 0xA266, 0x2586, 0xA267, 0x2587, 0xA268, 0x2588, 0xA269, 0x2589, 0xA270, 0x258A, 0xA26F, 0x258B, 0xA26E, + 0x258C, 0xA26D, 0x258D, 0xA26C, 0x258E, 0xA26B, 0x258F, 0xA26A, 0x2593, 0xF9FE, 0x2594, 0xA276, 0x2595, 0xA279, 0x25A0, 0xA1BD, + 0x25A1, 0xA1BC, 0x25B2, 0xA1B6, 0x25B3, 0xA1B5, 0x25BC, 0xA1BF, 0x25BD, 0xA1BE, 0x25C6, 0xA1BB, 0x25C7, 0xA1BA, 0x25CB, 0xA1B3, + 0x25CE, 0xA1B7, 0x25CF, 0xA1B4, 0x25E2, 0xA2A8, 0x25E3, 0xA2A9, 0x25E4, 0xA2AB, 0x25E5, 0xA2AA, 0x2605, 0xA1B9, 0x2606, 0xA1B8, + 0x2640, 0xA1F0, 0x2642, 0xA1F1, 0x3000, 0xA140, 0x3001, 0xA142, 0x3002, 0xA143, 0x3003, 0xA1B2, 0x3008, 0xA171, 0x3009, 0xA172, + 0x300A, 0xA16D, 0x300B, 0xA16E, 0x300C, 0xA175, 0x300D, 0xA176, 0x300E, 0xA179, 0x300F, 0xA17A, 0x3010, 0xA169, 0x3011, 0xA16A, + 0x3012, 0xA245, 0x3014, 0xA165, 0x3015, 0xA166, 0x301D, 0xA1A9, 0x301E, 0xA1AA, 0x3021, 0xA2C3, 0x3022, 0xA2C4, 0x3023, 0xA2C5, + 0x3024, 0xA2C6, 0x3025, 0xA2C7, 0x3026, 0xA2C8, 0x3027, 0xA2C9, 0x3028, 0xA2CA, 0x3029, 0xA2CB, 0x3105, 0xA374, 0x3106, 0xA375, + 0x3107, 0xA376, 0x3108, 0xA377, 0x3109, 0xA378, 0x310A, 0xA379, 0x310B, 0xA37A, 0x310C, 0xA37B, 0x310D, 0xA37C, 0x310E, 0xA37D, + 0x310F, 0xA37E, 0x3110, 0xA3A1, 0x3111, 0xA3A2, 0x3112, 0xA3A3, 0x3113, 0xA3A4, 0x3114, 0xA3A5, 0x3115, 0xA3A6, 0x3116, 0xA3A7, + 0x3117, 0xA3A8, 0x3118, 0xA3A9, 0x3119, 0xA3AA, 0x311A, 0xA3AB, 0x311B, 0xA3AC, 0x311C, 0xA3AD, 0x311D, 0xA3AE, 0x311E, 0xA3AF, + 0x311F, 0xA3B0, 0x3120, 0xA3B1, 0x3121, 0xA3B2, 0x3122, 0xA3B3, 0x3123, 0xA3B4, 0x3124, 0xA3B5, 0x3125, 0xA3B6, 0x3126, 0xA3B7, + 0x3127, 0xA3B8, 0x3128, 0xA3B9, 0x3129, 0xA3BA, 0x32A3, 0xA1C0, 0x338E, 0xA255, 0x338F, 0xA256, 0x339C, 0xA250, 0x339D, 0xA251, + 0x339E, 0xA252, 0x33A1, 0xA254, 0x33C4, 0xA257, 0x33CE, 0xA253, 0x33D1, 0xA1EB, 0x33D2, 0xA1EA, 0x33D5, 0xA24F, 0x4E00, 0xA440, + 0x4E01, 0xA442, 0x4E03, 0xA443, 0x4E07, 0xC945, 0x4E08, 0xA456, 0x4E09, 0xA454, 0x4E0A, 0xA457, 0x4E0B, 0xA455, 0x4E0C, 0xC946, + 0x4E0D, 0xA4A3, 0x4E0E, 0xC94F, 0x4E0F, 0xC94D, 0x4E10, 0xA4A2, 0x4E11, 0xA4A1, 0x4E14, 0xA542, 0x4E15, 0xA541, 0x4E16, 0xA540, + 0x4E18, 0xA543, 0x4E19, 0xA4FE, 0x4E1E, 0xA5E0, 0x4E1F, 0xA5E1, 0x4E26, 0xA8C3, 0x4E2B, 0xA458, 0x4E2D, 0xA4A4, 0x4E2E, 0xC950, + 0x4E30, 0xA4A5, 0x4E31, 0xC963, 0x4E32, 0xA6EA, 0x4E33, 0xCBB1, 0x4E38, 0xA459, 0x4E39, 0xA4A6, 0x4E3B, 0xA544, 0x4E3C, 0xC964, + 0x4E42, 0xC940, 0x4E43, 0xA444, 0x4E45, 0xA45B, 0x4E47, 0xC947, 0x4E48, 0xA45C, 0x4E4B, 0xA4A7, 0x4E4D, 0xA545, 0x4E4E, 0xA547, + 0x4E4F, 0xA546, 0x4E52, 0xA5E2, 0x4E53, 0xA5E3, 0x4E56, 0xA8C4, 0x4E58, 0xADBC, 0x4E59, 0xA441, 0x4E5C, 0xC941, 0x4E5D, 0xA445, + 0x4E5E, 0xA45E, 0x4E5F, 0xA45D, 0x4E69, 0xA5E4, 0x4E73, 0xA8C5, 0x4E7E, 0xB0AE, 0x4E7F, 0xD44B, 0x4E82, 0xB6C3, 0x4E83, 0xDCB1, + 0x4E84, 0xDCB2, 0x4E86, 0xA446, 0x4E88, 0xA4A9, 0x4E8B, 0xA8C6, 0x4E8C, 0xA447, 0x4E8D, 0xC948, 0x4E8E, 0xA45F, 0x4E91, 0xA4AA, + 0x4E92, 0xA4AC, 0x4E93, 0xC951, 0x4E94, 0xA4AD, 0x4E95, 0xA4AB, 0x4E99, 0xA5E5, 0x4E9B, 0xA8C7, 0x4E9E, 0xA8C8, 0x4E9F, 0xAB45, + 0x4EA1, 0xA460, 0x4EA2, 0xA4AE, 0x4EA4, 0xA5E6, 0x4EA5, 0xA5E8, 0x4EA6, 0xA5E7, 0x4EA8, 0xA6EB, 0x4EAB, 0xA8C9, 0x4EAC, 0xA8CA, + 0x4EAD, 0xAB46, 0x4EAE, 0xAB47, 0x4EB3, 0xADBD, 0x4EB6, 0xDCB3, 0x4EB9, 0xF6D6, 0x4EBA, 0xA448, 0x4EC0, 0xA4B0, 0x4EC1, 0xA4AF, + 0x4EC2, 0xC952, 0x4EC3, 0xA4B1, 0x4EC4, 0xA4B7, 0x4EC6, 0xA4B2, 0x4EC7, 0xA4B3, 0x4EC8, 0xC954, 0x4EC9, 0xC953, 0x4ECA, 0xA4B5, + 0x4ECB, 0xA4B6, 0x4ECD, 0xA4B4, 0x4ED4, 0xA54A, 0x4ED5, 0xA54B, 0x4ED6, 0xA54C, 0x4ED7, 0xA54D, 0x4ED8, 0xA549, 0x4ED9, 0xA550, + 0x4EDA, 0xC96A, 0x4EDC, 0xC966, 0x4EDD, 0xC969, 0x4EDE, 0xA551, 0x4EDF, 0xA561, 0x4EE1, 0xC968, 0x4EE3, 0xA54E, 0x4EE4, 0xA54F, + 0x4EE5, 0xA548, 0x4EE8, 0xC965, 0x4EE9, 0xC967, 0x4EF0, 0xA5F5, 0x4EF1, 0xC9B0, 0x4EF2, 0xA5F2, 0x4EF3, 0xA5F6, 0x4EF4, 0xC9BA, + 0x4EF5, 0xC9AE, 0x4EF6, 0xA5F3, 0x4EF7, 0xC9B2, 0x4EFB, 0xA5F4, 0x4EFD, 0xA5F7, 0x4EFF, 0xA5E9, 0x4F00, 0xC9B1, 0x4F01, 0xA5F8, + 0x4F02, 0xC9B5, 0x4F04, 0xC9B9, 0x4F05, 0xC9B6, 0x4F08, 0xC9B3, 0x4F09, 0xA5EA, 0x4F0A, 0xA5EC, 0x4F0B, 0xA5F9, 0x4F0D, 0xA5EE, + 0x4F0E, 0xC9AB, 0x4F0F, 0xA5F1, 0x4F10, 0xA5EF, 0x4F11, 0xA5F0, 0x4F12, 0xC9BB, 0x4F13, 0xC9B8, 0x4F14, 0xC9AF, 0x4F15, 0xA5ED, + 0x4F18, 0xC9AC, 0x4F19, 0xA5EB, 0x4F1D, 0xC9B4, 0x4F22, 0xC9B7, 0x4F2C, 0xC9AD, 0x4F2D, 0xCA66, 0x4F2F, 0xA742, 0x4F30, 0xA6F4, + 0x4F33, 0xCA67, 0x4F34, 0xA6F1, 0x4F36, 0xA744, 0x4F38, 0xA6F9, 0x4F3A, 0xA6F8, 0x4F3B, 0xCA5B, 0x4F3C, 0xA6FC, 0x4F3D, 0xA6F7, + 0x4F3E, 0xCA60, 0x4F3F, 0xCA68, 0x4F41, 0xCA64, 0x4F43, 0xA6FA, 0x4F46, 0xA6FD, 0x4F47, 0xA6EE, 0x4F48, 0xA747, 0x4F49, 0xCA5D, + 0x4F4C, 0xCBBD, 0x4F4D, 0xA6EC, 0x4F4E, 0xA743, 0x4F4F, 0xA6ED, 0x4F50, 0xA6F5, 0x4F51, 0xA6F6, 0x4F52, 0xCA62, 0x4F53, 0xCA5E, + 0x4F54, 0xA6FB, 0x4F55, 0xA6F3, 0x4F56, 0xCA5A, 0x4F57, 0xA6EF, 0x4F58, 0xCA65, 0x4F59, 0xA745, 0x4F5A, 0xA748, 0x4F5B, 0xA6F2, + 0x4F5C, 0xA740, 0x4F5D, 0xA746, 0x4F5E, 0xA6F0, 0x4F5F, 0xCA63, 0x4F60, 0xA741, 0x4F61, 0xCA69, 0x4F62, 0xCA5C, 0x4F63, 0xA6FE, + 0x4F64, 0xCA5F, 0x4F67, 0xCA61, 0x4F69, 0xA8D8, 0x4F6A, 0xCBBF, 0x4F6B, 0xCBCB, 0x4F6C, 0xA8D0, 0x4F6E, 0xCBCC, 0x4F6F, 0xA8CB, + 0x4F70, 0xA8D5, 0x4F73, 0xA8CE, 0x4F74, 0xCBB9, 0x4F75, 0xA8D6, 0x4F76, 0xCBB8, 0x4F77, 0xCBBC, 0x4F78, 0xCBC3, 0x4F79, 0xCBC1, + 0x4F7A, 0xA8DE, 0x4F7B, 0xA8D9, 0x4F7C, 0xCBB3, 0x4F7D, 0xCBB5, 0x4F7E, 0xA8DB, 0x4F7F, 0xA8CF, 0x4F80, 0xCBB6, 0x4F81, 0xCBC2, + 0x4F82, 0xCBC9, 0x4F83, 0xA8D4, 0x4F84, 0xCBBB, 0x4F85, 0xCBB4, 0x4F86, 0xA8D3, 0x4F87, 0xCBB7, 0x4F88, 0xA8D7, 0x4F89, 0xCBBA, + 0x4F8B, 0xA8D2, 0x4F8D, 0xA8CD, 0x4F8F, 0xA8DC, 0x4F90, 0xCBC4, 0x4F91, 0xA8DD, 0x4F92, 0xCBC8, 0x4F94, 0xCBC6, 0x4F95, 0xCBCA, + 0x4F96, 0xA8DA, 0x4F97, 0xCBBE, 0x4F98, 0xCBB2, 0x4F9A, 0xCBC0, 0x4F9B, 0xA8D1, 0x4F9C, 0xCBC5, 0x4F9D, 0xA8CC, 0x4F9E, 0xCBC7, + 0x4FAE, 0xAB56, 0x4FAF, 0xAB4A, 0x4FB2, 0xCDE0, 0x4FB3, 0xCDE8, 0x4FB5, 0xAB49, 0x4FB6, 0xAB51, 0x4FB7, 0xAB5D, 0x4FB9, 0xCDEE, + 0x4FBA, 0xCDEC, 0x4FBB, 0xCDE7, 0x4FBF, 0xAB4B, 0x4FC0, 0xCDED, 0x4FC1, 0xCDE3, 0x4FC2, 0xAB59, 0x4FC3, 0xAB50, 0x4FC4, 0xAB58, + 0x4FC5, 0xCDDE, 0x4FC7, 0xCDEA, 0x4FC9, 0xCDE1, 0x4FCA, 0xAB54, 0x4FCB, 0xCDE2, 0x4FCD, 0xCDDD, 0x4FCE, 0xAB5B, 0x4FCF, 0xAB4E, + 0x4FD0, 0xAB57, 0x4FD1, 0xAB4D, 0x4FD3, 0xCDDF, 0x4FD4, 0xCDE4, 0x4FD6, 0xCDEB, 0x4FD7, 0xAB55, 0x4FD8, 0xAB52, 0x4FD9, 0xCDE6, + 0x4FDA, 0xAB5A, 0x4FDB, 0xCDE9, 0x4FDC, 0xCDE5, 0x4FDD, 0xAB4F, 0x4FDE, 0xAB5C, 0x4FDF, 0xAB53, 0x4FE0, 0xAB4C, 0x4FE1, 0xAB48, + 0x4FEC, 0xCDEF, 0x4FEE, 0xADD7, 0x4FEF, 0xADC1, 0x4FF1, 0xADD1, 0x4FF3, 0xADD6, 0x4FF4, 0xD0D0, 0x4FF5, 0xD0CF, 0x4FF6, 0xD0D4, + 0x4FF7, 0xD0D5, 0x4FF8, 0xADC4, 0x4FFA, 0xADCD, 0x4FFE, 0xADDA, 0x5000, 0xADCE, 0x5005, 0xD0C9, 0x5006, 0xADC7, 0x5007, 0xD0CA, + 0x5009, 0xADDC, 0x500B, 0xADD3, 0x500C, 0xADBE, 0x500D, 0xADBF, 0x500E, 0xD0DD, 0x500F, 0xB0BF, 0x5011, 0xADCC, 0x5012, 0xADCB, + 0x5013, 0xD0CB, 0x5014, 0xADCF, 0x5015, 0xD45B, 0x5016, 0xADC6, 0x5017, 0xD0D6, 0x5018, 0xADD5, 0x5019, 0xADD4, 0x501A, 0xADCA, + 0x501B, 0xD0CE, 0x501C, 0xD0D7, 0x501E, 0xD0C8, 0x501F, 0xADC9, 0x5020, 0xD0D8, 0x5021, 0xADD2, 0x5022, 0xD0CC, 0x5023, 0xADC0, + 0x5025, 0xADC3, 0x5026, 0xADC2, 0x5027, 0xD0D9, 0x5028, 0xADD0, 0x5029, 0xADC5, 0x502A, 0xADD9, 0x502B, 0xADDB, 0x502C, 0xD0D3, + 0x502D, 0xADD8, 0x502F, 0xD0DB, 0x5030, 0xD0CD, 0x5031, 0xD0DC, 0x5033, 0xD0D1, 0x5035, 0xD0DA, 0x5037, 0xD0D2, 0x503C, 0xADC8, + 0x5040, 0xD463, 0x5041, 0xD457, 0x5043, 0xB0B3, 0x5045, 0xD45C, 0x5046, 0xD462, 0x5047, 0xB0B2, 0x5048, 0xD455, 0x5049, 0xB0B6, + 0x504A, 0xD459, 0x504B, 0xD452, 0x504C, 0xB0B4, 0x504D, 0xD456, 0x504E, 0xB0B9, 0x504F, 0xB0BE, 0x5051, 0xD467, 0x5053, 0xD451, + 0x5055, 0xB0BA, 0x5057, 0xD466, 0x505A, 0xB0B5, 0x505B, 0xD458, 0x505C, 0xB0B1, 0x505D, 0xD453, 0x505E, 0xD44F, 0x505F, 0xD45D, + 0x5060, 0xD450, 0x5061, 0xD44E, 0x5062, 0xD45A, 0x5063, 0xD460, 0x5064, 0xD461, 0x5065, 0xB0B7, 0x5068, 0xD85B, 0x5069, 0xD45E, + 0x506A, 0xD44D, 0x506B, 0xD45F, 0x506D, 0xB0C1, 0x506E, 0xD464, 0x506F, 0xB0C0, 0x5070, 0xD44C, 0x5072, 0xD454, 0x5073, 0xD465, + 0x5074, 0xB0BC, 0x5075, 0xB0BB, 0x5076, 0xB0B8, 0x5077, 0xB0BD, 0x507A, 0xB0AF, 0x507D, 0xB0B0, 0x5080, 0xB3C8, 0x5082, 0xD85E, + 0x5083, 0xD857, 0x5085, 0xB3C5, 0x5087, 0xD85F, 0x508B, 0xD855, 0x508C, 0xD858, 0x508D, 0xB3C4, 0x508E, 0xD859, 0x5091, 0xB3C7, + 0x5092, 0xD85D, 0x5094, 0xD853, 0x5095, 0xD852, 0x5096, 0xB3C9, 0x5098, 0xB3CA, 0x5099, 0xB3C6, 0x509A, 0xB3CB, 0x509B, 0xD851, + 0x509C, 0xD85C, 0x509D, 0xD85A, 0x509E, 0xD854, 0x50A2, 0xB3C3, 0x50A3, 0xD856, 0x50AC, 0xB6CA, 0x50AD, 0xB6C4, 0x50AE, 0xDCB7, + 0x50AF, 0xB6CD, 0x50B0, 0xDCBD, 0x50B1, 0xDCC0, 0x50B2, 0xB6C6, 0x50B3, 0xB6C7, 0x50B4, 0xDCBA, 0x50B5, 0xB6C5, 0x50B6, 0xDCC3, + 0x50B7, 0xB6CB, 0x50B8, 0xDCC4, 0x50BA, 0xDCBF, 0x50BB, 0xB6CC, 0x50BD, 0xDCB4, 0x50BE, 0xB6C9, 0x50BF, 0xDCB5, 0x50C1, 0xDCBE, + 0x50C2, 0xDCBC, 0x50C4, 0xDCB8, 0x50C5, 0xB6C8, 0x50C6, 0xDCB6, 0x50C7, 0xB6CE, 0x50C8, 0xDCBB, 0x50C9, 0xDCC2, 0x50CA, 0xDCB9, + 0x50CB, 0xDCC1, 0x50CE, 0xB9B6, 0x50CF, 0xB9B3, 0x50D1, 0xB9B4, 0x50D3, 0xE0F9, 0x50D4, 0xE0F1, 0x50D5, 0xB9B2, 0x50D6, 0xB9AF, + 0x50D7, 0xE0F2, 0x50DA, 0xB9B1, 0x50DB, 0xE0F5, 0x50DD, 0xE0F7, 0x50E0, 0xE0FE, 0x50E3, 0xE0FD, 0x50E4, 0xE0F8, 0x50E5, 0xB9AE, + 0x50E6, 0xE0F0, 0x50E7, 0xB9AC, 0x50E8, 0xE0F3, 0x50E9, 0xB9B7, 0x50EA, 0xE0F6, 0x50EC, 0xE0FA, 0x50ED, 0xB9B0, 0x50EE, 0xB9AD, + 0x50EF, 0xE0FC, 0x50F0, 0xE0FB, 0x50F1, 0xB9B5, 0x50F3, 0xE0F4, 0x50F5, 0xBBF8, 0x50F6, 0xE4EC, 0x50F8, 0xE4E9, 0x50F9, 0xBBF9, + 0x50FB, 0xBBF7, 0x50FD, 0xE4F0, 0x50FE, 0xE4ED, 0x50FF, 0xE4E6, 0x5100, 0xBBF6, 0x5102, 0xBBFA, 0x5103, 0xE4E7, 0x5104, 0xBBF5, + 0x5105, 0xBBFD, 0x5106, 0xE4EA, 0x5107, 0xE4EB, 0x5108, 0xBBFB, 0x5109, 0xBBFC, 0x510A, 0xE4F1, 0x510B, 0xE4EE, 0x510C, 0xE4EF, + 0x5110, 0xBEAA, 0x5111, 0xE8F8, 0x5112, 0xBEA7, 0x5113, 0xE8F5, 0x5114, 0xBEA9, 0x5115, 0xBEAB, 0x5117, 0xE8F6, 0x5118, 0xBEA8, + 0x511A, 0xE8F7, 0x511C, 0xE8F4, 0x511F, 0xC076, 0x5120, 0xECBD, 0x5121, 0xC077, 0x5122, 0xECBB, 0x5124, 0xECBC, 0x5125, 0xECBA, + 0x5126, 0xECB9, 0x5129, 0xECBE, 0x512A, 0xC075, 0x512D, 0xEFB8, 0x512E, 0xEFB9, 0x5130, 0xE4E8, 0x5131, 0xEFB7, 0x5132, 0xC078, + 0x5133, 0xC35F, 0x5134, 0xF1EB, 0x5135, 0xF1EC, 0x5137, 0xC4D7, 0x5138, 0xC4D8, 0x5139, 0xF5C1, 0x513A, 0xF5C0, 0x513B, 0xC56C, + 0x513C, 0xC56B, 0x513D, 0xF7D0, 0x513F, 0xA449, 0x5140, 0xA461, 0x5141, 0xA4B9, 0x5143, 0xA4B8, 0x5144, 0xA553, 0x5145, 0xA552, + 0x5146, 0xA5FC, 0x5147, 0xA5FB, 0x5148, 0xA5FD, 0x5149, 0xA5FA, 0x514B, 0xA74A, 0x514C, 0xA749, 0x514D, 0xA74B, 0x5152, 0xA8E0, + 0x5154, 0xA8DF, 0x5155, 0xA8E1, 0x5157, 0xAB5E, 0x5159, 0xA259, 0x515A, 0xD0DE, 0x515B, 0xA25A, 0x515C, 0xB0C2, 0x515D, 0xA25C, + 0x515E, 0xA25B, 0x515F, 0xD860, 0x5161, 0xA25D, 0x5162, 0xB9B8, 0x5163, 0xA25E, 0x5165, 0xA44A, 0x5167, 0xA4BA, 0x5168, 0xA5FE, + 0x5169, 0xA8E2, 0x516B, 0xA44B, 0x516C, 0xA4BD, 0x516D, 0xA4BB, 0x516E, 0xA4BC, 0x5171, 0xA640, 0x5175, 0xA74C, 0x5176, 0xA8E4, + 0x5177, 0xA8E3, 0x5178, 0xA8E5, 0x517C, 0xADDD, 0x5180, 0xBEAC, 0x5187, 0xC94E, 0x5189, 0xA554, 0x518A, 0xA555, 0x518D, 0xA641, + 0x518F, 0xCA6A, 0x5191, 0xAB60, 0x5192, 0xAB5F, 0x5193, 0xD0E0, 0x5194, 0xD0DF, 0x5195, 0xB0C3, 0x5197, 0xA4BE, 0x5198, 0xC955, + 0x519E, 0xCBCD, 0x51A0, 0xAB61, 0x51A2, 0xADE0, 0x51A4, 0xADDE, 0x51A5, 0xADDF, 0x51AA, 0xBEAD, 0x51AC, 0xA556, 0x51B0, 0xA642, + 0x51B1, 0xC9BC, 0x51B6, 0xA74D, 0x51B7, 0xA74E, 0x51B9, 0xCA6B, 0x51BC, 0xCBCE, 0x51BD, 0xA8E6, 0x51BE, 0xCBCF, 0x51C4, 0xD0E2, + 0x51C5, 0xD0E3, 0x51C6, 0xADE3, 0x51C8, 0xD0E4, 0x51CA, 0xD0E1, 0x51CB, 0xADE4, 0x51CC, 0xADE2, 0x51CD, 0xADE1, 0x51CE, 0xD0E5, + 0x51D0, 0xD468, 0x51D4, 0xD861, 0x51D7, 0xDCC5, 0x51D8, 0xE140, 0x51DC, 0xBBFE, 0x51DD, 0xBEAE, 0x51DE, 0xE8F9, 0x51E0, 0xA44C, + 0x51E1, 0xA45A, 0x51F0, 0xB0C4, 0x51F1, 0xB3CD, 0x51F3, 0xB9B9, 0x51F5, 0xC942, 0x51F6, 0xA4BF, 0x51F8, 0xA559, 0x51F9, 0xA557, + 0x51FA, 0xA558, 0x51FD, 0xA8E7, 0x5200, 0xA44D, 0x5201, 0xA44E, 0x5203, 0xA462, 0x5206, 0xA4C0, 0x5207, 0xA4C1, 0x5208, 0xA4C2, + 0x5209, 0xC9BE, 0x520A, 0xA55A, 0x520C, 0xC96B, 0x520E, 0xA646, 0x5210, 0xC9BF, 0x5211, 0xA644, 0x5212, 0xA645, 0x5213, 0xC9BD, + 0x5216, 0xA647, 0x5217, 0xA643, 0x521C, 0xCA6C, 0x521D, 0xAAEC, 0x521E, 0xCA6D, 0x5221, 0xCA6E, 0x5224, 0xA750, 0x5225, 0xA74F, + 0x5228, 0xA753, 0x5229, 0xA751, 0x522A, 0xA752, 0x522E, 0xA8ED, 0x5230, 0xA8EC, 0x5231, 0xCBD4, 0x5232, 0xCBD1, 0x5233, 0xCBD2, + 0x5235, 0xCBD0, 0x5236, 0xA8EE, 0x5237, 0xA8EA, 0x5238, 0xA8E9, 0x523A, 0xA8EB, 0x523B, 0xA8E8, 0x5241, 0xA8EF, 0x5243, 0xAB63, + 0x5244, 0xCDF0, 0x5246, 0xCBD3, 0x5247, 0xAB68, 0x5249, 0xCDF1, 0x524A, 0xAB64, 0x524B, 0xAB67, 0x524C, 0xAB66, 0x524D, 0xAB65, + 0x524E, 0xAB62, 0x5252, 0xD0E8, 0x5254, 0xADE7, 0x5255, 0xD0EB, 0x5256, 0xADE5, 0x525A, 0xD0E7, 0x525B, 0xADE8, 0x525C, 0xADE6, + 0x525D, 0xADE9, 0x525E, 0xD0E9, 0x525F, 0xD0EA, 0x5261, 0xD0E6, 0x5262, 0xD0EC, 0x5269, 0xB3D1, 0x526A, 0xB0C5, 0x526B, 0xD469, + 0x526C, 0xD46B, 0x526D, 0xD46A, 0x526E, 0xD46C, 0x526F, 0xB0C6, 0x5272, 0xB3CE, 0x5274, 0xB3CF, 0x5275, 0xB3D0, 0x5277, 0xB6D0, + 0x5278, 0xDCC7, 0x527A, 0xDCC6, 0x527B, 0xDCC8, 0x527C, 0xDCC9, 0x527D, 0xB6D1, 0x527F, 0xB6CF, 0x5280, 0xE141, 0x5281, 0xE142, + 0x5282, 0xB9BB, 0x5283, 0xB9BA, 0x5284, 0xE35A, 0x5287, 0xBC40, 0x5288, 0xBC41, 0x5289, 0xBC42, 0x528A, 0xBC44, 0x528B, 0xE4F2, + 0x528C, 0xE4F3, 0x528D, 0xBC43, 0x5291, 0xBEAF, 0x5293, 0xBEB0, 0x5296, 0xF1ED, 0x5297, 0xF5C3, 0x5298, 0xF5C2, 0x5299, 0xF7D1, + 0x529B, 0xA44F, 0x529F, 0xA55C, 0x52A0, 0xA55B, 0x52A3, 0xA648, 0x52A6, 0xC9C0, 0x52A9, 0xA755, 0x52AA, 0xA756, 0x52AB, 0xA754, + 0x52AC, 0xA757, 0x52AD, 0xCA6F, 0x52AE, 0xCA70, 0x52BB, 0xA8F1, 0x52BC, 0xCBD5, 0x52BE, 0xA8F0, 0x52C0, 0xCDF2, 0x52C1, 0xAB6C, + 0x52C2, 0xCDF3, 0x52C3, 0xAB6B, 0x52C7, 0xAB69, 0x52C9, 0xAB6A, 0x52CD, 0xD0ED, 0x52D2, 0xB0C7, 0x52D3, 0xD46E, 0x52D5, 0xB0CA, + 0x52D6, 0xD46D, 0x52D7, 0xB1E5, 0x52D8, 0xB0C9, 0x52D9, 0xB0C8, 0x52DB, 0xB3D4, 0x52DD, 0xB3D3, 0x52DE, 0xB3D2, 0x52DF, 0xB6D2, + 0x52E2, 0xB6D5, 0x52E3, 0xB6D6, 0x52E4, 0xB6D4, 0x52E6, 0xB6D3, 0x52E9, 0xE143, 0x52EB, 0xE144, 0x52EF, 0xE4F5, 0x52F0, 0xBC45, + 0x52F1, 0xE4F4, 0x52F3, 0xBEB1, 0x52F4, 0xECBF, 0x52F5, 0xC079, 0x52F7, 0xF1EE, 0x52F8, 0xC455, 0x52FA, 0xA463, 0x52FB, 0xA4C3, + 0x52FC, 0xC956, 0x52FE, 0xA4C4, 0x52FF, 0xA4C5, 0x5305, 0xA55D, 0x5306, 0xA55E, 0x5308, 0xA649, 0x5309, 0xCA71, 0x530A, 0xCBD6, + 0x530B, 0xCBD7, 0x530D, 0xAB6D, 0x530E, 0xD0EE, 0x530F, 0xB0CC, 0x5310, 0xB0CB, 0x5311, 0xD863, 0x5312, 0xD862, 0x5315, 0xA450, + 0x5316, 0xA4C6, 0x5317, 0xA55F, 0x5319, 0xB0CD, 0x531A, 0xC943, 0x531C, 0xC96C, 0x531D, 0xA560, 0x531F, 0xC9C2, 0x5320, 0xA64B, + 0x5321, 0xA64A, 0x5322, 0xC9C1, 0x5323, 0xA758, 0x532A, 0xADEA, 0x532D, 0xD46F, 0x532F, 0xB6D7, 0x5330, 0xE145, 0x5331, 0xB9BC, + 0x5334, 0xE8FA, 0x5337, 0xF3FD, 0x5339, 0xA4C7, 0x533C, 0xCBD8, 0x533D, 0xCDF4, 0x533E, 0xB0D0, 0x533F, 0xB0CE, 0x5340, 0xB0CF, + 0x5341, 0xA2CC, 0x5341, 0xA451, 0x5343, 0xA464, 0x5344, 0xA2CD, 0x5345, 0xA2CE, 0x5345, 0xA4CA, 0x5347, 0xA4C9, 0x5348, 0xA4C8, + 0x5349, 0xA563, 0x534A, 0xA562, 0x534C, 0xC96D, 0x534D, 0xC9C3, 0x5351, 0xA8F5, 0x5352, 0xA8F2, 0x5353, 0xA8F4, 0x5354, 0xA8F3, + 0x5357, 0xAB6E, 0x535A, 0xB3D5, 0x535C, 0xA452, 0x535E, 0xA4CB, 0x5360, 0xA565, 0x5361, 0xA564, 0x5363, 0xCA72, 0x5366, 0xA8F6, + 0x536C, 0xC957, 0x536E, 0xA567, 0x536F, 0xA566, 0x5370, 0xA64C, 0x5371, 0xA64D, 0x5372, 0xCA73, 0x5373, 0xA759, 0x5375, 0xA75A, + 0x5377, 0xA8F7, 0x5378, 0xA8F8, 0x5379, 0xA8F9, 0x537B, 0xAB6F, 0x537C, 0xCDF5, 0x537F, 0xADEB, 0x5382, 0xC944, 0x5384, 0xA4CC, + 0x538A, 0xC9C4, 0x538E, 0xCA74, 0x538F, 0xCA75, 0x5392, 0xCBD9, 0x5394, 0xCBDA, 0x5396, 0xCDF7, 0x5397, 0xCDF6, 0x5398, 0xCDF9, + 0x5399, 0xCDF8, 0x539A, 0xAB70, 0x539C, 0xD470, 0x539D, 0xADED, 0x539E, 0xD0EF, 0x539F, 0xADEC, 0x53A4, 0xD864, 0x53A5, 0xB3D6, + 0x53A7, 0xD865, 0x53AC, 0xE146, 0x53AD, 0xB9BD, 0x53B2, 0xBC46, 0x53B4, 0xF1EF, 0x53B9, 0xC958, 0x53BB, 0xA568, 0x53C3, 0xB0D1, + 0x53C8, 0xA453, 0x53C9, 0xA465, 0x53CA, 0xA4CE, 0x53CB, 0xA4CD, 0x53CD, 0xA4CF, 0x53D4, 0xA8FB, 0x53D6, 0xA8FA, 0x53D7, 0xA8FC, + 0x53DB, 0xAB71, 0x53DF, 0xADEE, 0x53E1, 0xE8FB, 0x53E2, 0xC24F, 0x53E3, 0xA466, 0x53E4, 0xA56A, 0x53E5, 0xA579, 0x53E6, 0xA574, + 0x53E8, 0xA56F, 0x53E9, 0xA56E, 0x53EA, 0xA575, 0x53EB, 0xA573, 0x53EC, 0xA56C, 0x53ED, 0xA57A, 0x53EE, 0xA56D, 0x53EF, 0xA569, + 0x53F0, 0xA578, 0x53F1, 0xA577, 0x53F2, 0xA576, 0x53F3, 0xA56B, 0x53F5, 0xA572, 0x53F8, 0xA571, 0x53FB, 0xA57B, 0x53FC, 0xA570, + 0x5401, 0xA653, 0x5403, 0xA659, 0x5404, 0xA655, 0x5406, 0xA65B, 0x5407, 0xC9C5, 0x5408, 0xA658, 0x5409, 0xA64E, 0x540A, 0xA651, + 0x540B, 0xA654, 0x540C, 0xA650, 0x540D, 0xA657, 0x540E, 0xA65A, 0x540F, 0xA64F, 0x5410, 0xA652, 0x5411, 0xA656, 0x5412, 0xA65C, + 0x5418, 0xCA7E, 0x5419, 0xCA7B, 0x541B, 0xA767, 0x541C, 0xCA7C, 0x541D, 0xA75B, 0x541E, 0xA75D, 0x541F, 0xA775, 0x5420, 0xA770, + 0x5424, 0xCAA5, 0x5425, 0xCA7D, 0x5426, 0xA75F, 0x5427, 0xA761, 0x5428, 0xCAA4, 0x5429, 0xA768, 0x542A, 0xCA78, 0x542B, 0xA774, + 0x542C, 0xA776, 0x542D, 0xA75C, 0x542E, 0xA76D, 0x5430, 0xCA76, 0x5431, 0xA773, 0x5433, 0xA764, 0x5435, 0xA76E, 0x5436, 0xA76F, + 0x5437, 0xCA77, 0x5438, 0xA76C, 0x5439, 0xA76A, 0x543B, 0xA76B, 0x543C, 0xA771, 0x543D, 0xCAA1, 0x543E, 0xA75E, 0x5440, 0xA772, + 0x5441, 0xCAA3, 0x5442, 0xA766, 0x5443, 0xA763, 0x5445, 0xCA7A, 0x5446, 0xA762, 0x5447, 0xCAA6, 0x5448, 0xA765, 0x544A, 0xA769, + 0x544E, 0xA760, 0x544F, 0xCAA2, 0x5454, 0xCA79, 0x5460, 0xCBEB, 0x5461, 0xCBEA, 0x5462, 0xA94F, 0x5463, 0xCBED, 0x5464, 0xCBEF, + 0x5465, 0xCBE4, 0x5466, 0xCBE7, 0x5467, 0xCBEE, 0x5468, 0xA950, 0x546B, 0xCBE1, 0x546C, 0xCBE5, 0x546F, 0xCBE9, 0x5470, 0xCE49, + 0x5471, 0xA94B, 0x5472, 0xCE4D, 0x5473, 0xA8FD, 0x5474, 0xCBE6, 0x5475, 0xA8FE, 0x5476, 0xA94C, 0x5477, 0xA945, 0x5478, 0xA941, + 0x547A, 0xCBE2, 0x547B, 0xA944, 0x547C, 0xA949, 0x547D, 0xA952, 0x547E, 0xCBE3, 0x547F, 0xCBDC, 0x5480, 0xA943, 0x5481, 0xCBDD, + 0x5482, 0xCBDF, 0x5484, 0xA946, 0x5486, 0xA948, 0x5487, 0xCBDB, 0x5488, 0xCBE0, 0x548B, 0xA951, 0x548C, 0xA94D, 0x548D, 0xCBE8, + 0x548E, 0xA953, 0x5490, 0xA94A, 0x5491, 0xCBDE, 0x5492, 0xA947, 0x5495, 0xA942, 0x5496, 0xA940, 0x5498, 0xCBEC, 0x549A, 0xA94E, + 0x54A0, 0xCE48, 0x54A1, 0xCDFB, 0x54A2, 0xCE4B, 0x54A5, 0xCDFD, 0x54A6, 0xAB78, 0x54A7, 0xABA8, 0x54A8, 0xAB74, 0x54A9, 0xABA7, + 0x54AA, 0xAB7D, 0x54AB, 0xABA4, 0x54AC, 0xAB72, 0x54AD, 0xCDFC, 0x54AE, 0xCE43, 0x54AF, 0xABA3, 0x54B0, 0xCE4F, 0x54B1, 0xABA5, + 0x54B3, 0xAB79, 0x54B6, 0xCE45, 0x54B7, 0xCE42, 0x54B8, 0xAB77, 0x54BA, 0xCDFA, 0x54BB, 0xABA6, 0x54BC, 0xCE4A, 0x54BD, 0xAB7C, + 0x54BE, 0xCE4C, 0x54BF, 0xABA9, 0x54C0, 0xAB73, 0x54C1, 0xAB7E, 0x54C2, 0xAB7B, 0x54C3, 0xCE40, 0x54C4, 0xABA1, 0x54C5, 0xCE46, + 0x54C6, 0xCE47, 0x54C7, 0xAB7A, 0x54C8, 0xABA2, 0x54C9, 0xAB76, 0x54CE, 0xAB75, 0x54CF, 0xCDFE, 0x54D6, 0xCE44, 0x54DE, 0xCE4E, + 0x54E0, 0xD144, 0x54E1, 0xADFB, 0x54E2, 0xD0F1, 0x54E4, 0xD0F6, 0x54E5, 0xADF4, 0x54E6, 0xAE40, 0x54E7, 0xD0F4, 0x54E8, 0xADEF, + 0x54E9, 0xADF9, 0x54EA, 0xADFE, 0x54EB, 0xD0FB, 0x54ED, 0xADFA, 0x54EE, 0xADFD, 0x54F1, 0xD0FE, 0x54F2, 0xADF5, 0x54F3, 0xD0F5, + 0x54F7, 0xD142, 0x54F8, 0xD143, 0x54FA, 0xADF7, 0x54FB, 0xD141, 0x54FC, 0xADF3, 0x54FD, 0xAE43, 0x54FF, 0xD0F8, 0x5501, 0xADF1, + 0x5503, 0xD146, 0x5504, 0xD0F9, 0x5505, 0xD0FD, 0x5506, 0xADF6, 0x5507, 0xAE42, 0x5508, 0xD0FA, 0x5509, 0xADFC, 0x550A, 0xD140, + 0x550B, 0xD147, 0x550C, 0xD4A1, 0x550E, 0xD145, 0x550F, 0xAE44, 0x5510, 0xADF0, 0x5511, 0xD0FC, 0x5512, 0xD0F3, 0x5514, 0xADF8, + 0x5517, 0xD0F2, 0x551A, 0xD0F7, 0x5526, 0xD0F0, 0x5527, 0xAE41, 0x552A, 0xD477, 0x552C, 0xB0E4, 0x552D, 0xD4A7, 0x552E, 0xB0E2, + 0x552F, 0xB0DF, 0x5530, 0xD47C, 0x5531, 0xB0DB, 0x5532, 0xD4A2, 0x5533, 0xB0E6, 0x5534, 0xD476, 0x5535, 0xD47B, 0x5536, 0xD47A, + 0x5537, 0xADF2, 0x5538, 0xB0E1, 0x5539, 0xD4A5, 0x553B, 0xD4A8, 0x553C, 0xD473, 0x553E, 0xB3E8, 0x5540, 0xD4A9, 0x5541, 0xB0E7, + 0x5543, 0xB0D9, 0x5544, 0xB0D6, 0x5545, 0xD47E, 0x5546, 0xB0D3, 0x5548, 0xD4A6, 0x554A, 0xB0DA, 0x554B, 0xD4AA, 0x554D, 0xD474, + 0x554E, 0xD4A4, 0x554F, 0xB0DD, 0x5550, 0xD475, 0x5551, 0xD478, 0x5552, 0xD47D, 0x5555, 0xB0DE, 0x5556, 0xB0DC, 0x5557, 0xB0E8, + 0x555C, 0xB0E3, 0x555E, 0xB0D7, 0x555F, 0xB1D2, 0x5561, 0xB0D8, 0x5562, 0xD479, 0x5563, 0xB0E5, 0x5564, 0xB0E0, 0x5565, 0xD4A3, + 0x5566, 0xB0D5, 0x556A, 0xB0D4, 0x5575, 0xD471, 0x5576, 0xD472, 0x5577, 0xD86A, 0x557B, 0xB3D7, 0x557C, 0xB3DA, 0x557D, 0xD875, + 0x557E, 0xB3EE, 0x557F, 0xD878, 0x5580, 0xB3D8, 0x5581, 0xD871, 0x5582, 0xB3DE, 0x5583, 0xB3E4, 0x5584, 0xB5BD, 0x5587, 0xB3E2, + 0x5588, 0xD86E, 0x5589, 0xB3EF, 0x558A, 0xB3DB, 0x558B, 0xB3E3, 0x558C, 0xD876, 0x558D, 0xDCD7, 0x558E, 0xD87B, 0x558F, 0xD86F, + 0x5591, 0xD866, 0x5592, 0xD873, 0x5593, 0xD86D, 0x5594, 0xB3E1, 0x5595, 0xD879, 0x5598, 0xB3DD, 0x5599, 0xB3F1, 0x559A, 0xB3EA, + 0x559C, 0xB3DF, 0x559D, 0xB3DC, 0x559F, 0xB3E7, 0x55A1, 0xD87A, 0x55A2, 0xD86C, 0x55A3, 0xD872, 0x55A4, 0xD874, 0x55A5, 0xD868, + 0x55A6, 0xD877, 0x55A7, 0xB3D9, 0x55A8, 0xD867, 0x55AA, 0xB3E0, 0x55AB, 0xB3F0, 0x55AC, 0xB3EC, 0x55AD, 0xD869, 0x55AE, 0xB3E6, + 0x55B1, 0xB3ED, 0x55B2, 0xB3E9, 0x55B3, 0xB3E5, 0x55B5, 0xD870, 0x55BB, 0xB3EB, 0x55BF, 0xDCD5, 0x55C0, 0xDCD1, 0x55C2, 0xDCE0, + 0x55C3, 0xDCCA, 0x55C4, 0xDCD3, 0x55C5, 0xB6E5, 0x55C6, 0xB6E6, 0x55C7, 0xB6DE, 0x55C8, 0xDCDC, 0x55C9, 0xB6E8, 0x55CA, 0xDCCF, + 0x55CB, 0xDCCE, 0x55CC, 0xDCCC, 0x55CD, 0xDCDE, 0x55CE, 0xB6DC, 0x55CF, 0xDCD8, 0x55D0, 0xDCCD, 0x55D1, 0xB6DF, 0x55D2, 0xDCD6, + 0x55D3, 0xB6DA, 0x55D4, 0xDCD2, 0x55D5, 0xDCD9, 0x55D6, 0xDCDB, 0x55D9, 0xDCDF, 0x55DA, 0xB6E3, 0x55DB, 0xDCCB, 0x55DC, 0xB6DD, + 0x55DD, 0xDCD0, 0x55DF, 0xB6D8, 0x55E1, 0xB6E4, 0x55E2, 0xDCDA, 0x55E3, 0xB6E0, 0x55E4, 0xB6E1, 0x55E5, 0xB6E7, 0x55E6, 0xB6DB, + 0x55E7, 0xA25F, 0x55E8, 0xB6D9, 0x55E9, 0xDCD4, 0x55EF, 0xB6E2, 0x55F2, 0xDCDD, 0x55F6, 0xB9CD, 0x55F7, 0xB9C8, 0x55F9, 0xE155, + 0x55FA, 0xE151, 0x55FC, 0xE14B, 0x55FD, 0xB9C2, 0x55FE, 0xB9BE, 0x55FF, 0xE154, 0x5600, 0xB9BF, 0x5601, 0xE14E, 0x5602, 0xE150, + 0x5604, 0xE153, 0x5606, 0xB9C4, 0x5608, 0xB9CB, 0x5609, 0xB9C5, 0x560C, 0xE149, 0x560D, 0xB9C6, 0x560E, 0xB9C7, 0x560F, 0xE14C, + 0x5610, 0xB9CC, 0x5612, 0xE14A, 0x5613, 0xE14F, 0x5614, 0xB9C3, 0x5615, 0xE148, 0x5616, 0xB9C9, 0x5617, 0xB9C1, 0x561B, 0xB9C0, + 0x561C, 0xE14D, 0x561D, 0xE152, 0x561F, 0xB9CA, 0x5627, 0xE147, 0x5629, 0xBC4D, 0x562A, 0xE547, 0x562C, 0xE544, 0x562E, 0xBC47, + 0x562F, 0xBC53, 0x5630, 0xBC54, 0x5632, 0xBC4A, 0x5633, 0xE542, 0x5634, 0xBC4C, 0x5635, 0xE4F9, 0x5636, 0xBC52, 0x5638, 0xE546, + 0x5639, 0xBC49, 0x563A, 0xE548, 0x563B, 0xBC48, 0x563D, 0xE543, 0x563E, 0xE545, 0x563F, 0xBC4B, 0x5640, 0xE541, 0x5641, 0xE4FA, + 0x5642, 0xE4F7, 0x5645, 0xD86B, 0x5646, 0xE4FD, 0x5648, 0xE4F6, 0x5649, 0xE4FC, 0x564A, 0xE4FB, 0x564C, 0xE4F8, 0x564E, 0xBC4F, + 0x5653, 0xBC4E, 0x5657, 0xBC50, 0x5658, 0xE4FE, 0x5659, 0xBEB2, 0x565A, 0xE540, 0x565E, 0xE945, 0x5660, 0xE8FD, 0x5662, 0xBEBE, + 0x5663, 0xE942, 0x5664, 0xBEB6, 0x5665, 0xBEBA, 0x5666, 0xE941, 0x5668, 0xBEB9, 0x5669, 0xBEB5, 0x566A, 0xBEB8, 0x566B, 0xBEB3, + 0x566C, 0xBEBD, 0x566D, 0xE943, 0x566E, 0xE8FE, 0x566F, 0xBEBC, 0x5670, 0xE8FC, 0x5671, 0xBEBB, 0x5672, 0xE944, 0x5673, 0xE940, + 0x5674, 0xBC51, 0x5676, 0xBEBF, 0x5677, 0xE946, 0x5678, 0xBEB7, 0x5679, 0xBEB4, 0x567E, 0xECC6, 0x567F, 0xECC8, 0x5680, 0xC07B, + 0x5681, 0xECC9, 0x5682, 0xECC7, 0x5683, 0xECC5, 0x5684, 0xECC4, 0x5685, 0xC07D, 0x5686, 0xECC3, 0x5687, 0xC07E, 0x568C, 0xECC1, + 0x568D, 0xECC2, 0x568E, 0xC07A, 0x568F, 0xC0A1, 0x5690, 0xC07C, 0x5693, 0xECC0, 0x5695, 0xC250, 0x5697, 0xEFBC, 0x5698, 0xEFBA, + 0x5699, 0xEFBF, 0x569A, 0xEFBD, 0x569C, 0xEFBB, 0x569D, 0xEFBE, 0x56A5, 0xC360, 0x56A6, 0xF1F2, 0x56A7, 0xF1F3, 0x56A8, 0xC456, + 0x56AA, 0xF1F4, 0x56AB, 0xF1F0, 0x56AC, 0xF1F5, 0x56AD, 0xF1F1, 0x56AE, 0xC251, 0x56B2, 0xF3FE, 0x56B3, 0xF441, 0x56B4, 0xC459, + 0x56B5, 0xF440, 0x56B6, 0xC458, 0x56B7, 0xC457, 0x56BC, 0xC45A, 0x56BD, 0xF5C5, 0x56BE, 0xF5C6, 0x56C0, 0xC4DA, 0x56C1, 0xC4D9, + 0x56C2, 0xC4DB, 0x56C3, 0xF5C4, 0x56C5, 0xF6D8, 0x56C6, 0xF6D7, 0x56C8, 0xC56D, 0x56C9, 0xC56F, 0x56CA, 0xC56E, 0x56CB, 0xF6D9, + 0x56CC, 0xC5C8, 0x56CD, 0xF8A6, 0x56D1, 0xC5F1, 0x56D3, 0xF8A5, 0x56D4, 0xF8EE, 0x56D7, 0xC949, 0x56DA, 0xA57D, 0x56DB, 0xA57C, + 0x56DD, 0xA65F, 0x56DE, 0xA65E, 0x56DF, 0xC9C7, 0x56E0, 0xA65D, 0x56E1, 0xC9C6, 0x56E4, 0xA779, 0x56E5, 0xCAA9, 0x56E7, 0xCAA8, + 0x56EA, 0xA777, 0x56EB, 0xA77A, 0x56EE, 0xCAA7, 0x56F0, 0xA778, 0x56F7, 0xCBF0, 0x56F9, 0xCBF1, 0x56FA, 0xA954, 0x56FF, 0xABAA, + 0x5701, 0xD148, 0x5702, 0xD149, 0x5703, 0xAE45, 0x5704, 0xAE46, 0x5707, 0xD4AC, 0x5708, 0xB0E9, 0x5709, 0xB0EB, 0x570A, 0xD4AB, + 0x570B, 0xB0EA, 0x570C, 0xD87C, 0x570D, 0xB3F2, 0x5712, 0xB6E9, 0x5713, 0xB6EA, 0x5714, 0xDCE1, 0x5716, 0xB9CF, 0x5718, 0xB9CE, + 0x571A, 0xE549, 0x571B, 0xE948, 0x571C, 0xE947, 0x571E, 0xF96B, 0x571F, 0xA467, 0x5720, 0xC959, 0x5722, 0xC96E, 0x5723, 0xC96F, + 0x5728, 0xA662, 0x5729, 0xA666, 0x572A, 0xC9C9, 0x572C, 0xA664, 0x572D, 0xA663, 0x572E, 0xC9C8, 0x572F, 0xA665, 0x5730, 0xA661, + 0x5733, 0xA660, 0x5734, 0xC9CA, 0x573B, 0xA7A6, 0x573E, 0xA7A3, 0x5740, 0xA77D, 0x5741, 0xCAAA, 0x5745, 0xCAAB, 0x5747, 0xA7A1, + 0x5749, 0xCAAD, 0x574A, 0xA77B, 0x574B, 0xCAAE, 0x574C, 0xCAAC, 0x574D, 0xA77E, 0x574E, 0xA7A2, 0x574F, 0xA7A5, 0x5750, 0xA7A4, + 0x5751, 0xA77C, 0x5752, 0xCAAF, 0x5761, 0xA959, 0x5762, 0xCBFE, 0x5764, 0xA95B, 0x5766, 0xA95A, 0x5768, 0xCC40, 0x5769, 0xA958, + 0x576A, 0xA957, 0x576B, 0xCBF5, 0x576D, 0xCBF4, 0x576F, 0xCBF2, 0x5770, 0xCBF7, 0x5771, 0xCBF6, 0x5772, 0xCBF3, 0x5773, 0xCBFC, + 0x5774, 0xCBFD, 0x5775, 0xCBFA, 0x5776, 0xCBF8, 0x5777, 0xA956, 0x577B, 0xCBFB, 0x577C, 0xA95C, 0x577D, 0xCC41, 0x5780, 0xCBF9, + 0x5782, 0xABAB, 0x5783, 0xA955, 0x578B, 0xABAC, 0x578C, 0xCE54, 0x578F, 0xCE5A, 0x5793, 0xABB2, 0x5794, 0xCE58, 0x5795, 0xCE5E, + 0x5797, 0xCE55, 0x5798, 0xCE59, 0x5799, 0xCE5B, 0x579A, 0xCE5D, 0x579B, 0xCE57, 0x579D, 0xCE56, 0x579E, 0xCE51, 0x579F, 0xCE52, + 0x57A0, 0xABAD, 0x57A2, 0xABAF, 0x57A3, 0xABAE, 0x57A4, 0xCE53, 0x57A5, 0xCE5C, 0x57AE, 0xABB1, 0x57B5, 0xCE50, 0x57B6, 0xD153, + 0x57B8, 0xD152, 0x57B9, 0xD157, 0x57BA, 0xD14E, 0x57BC, 0xD151, 0x57BD, 0xD150, 0x57BF, 0xD154, 0x57C1, 0xD158, 0x57C2, 0xAE47, + 0x57C3, 0xAE4A, 0x57C6, 0xD14F, 0x57C7, 0xD155, 0x57CB, 0xAE49, 0x57CC, 0xD14A, 0x57CE, 0xABB0, 0x57CF, 0xD4BA, 0x57D0, 0xD156, + 0x57D2, 0xD14D, 0x57D4, 0xAE48, 0x57D5, 0xD14C, 0x57DC, 0xD4B1, 0x57DF, 0xB0EC, 0x57E0, 0xB0F0, 0x57E1, 0xD4C1, 0x57E2, 0xD4AF, + 0x57E3, 0xD4BD, 0x57E4, 0xB0F1, 0x57E5, 0xD4BF, 0x57E7, 0xD4C5, 0x57E9, 0xD4C9, 0x57EC, 0xD4C0, 0x57ED, 0xD4B4, 0x57EE, 0xD4BC, + 0x57F0, 0xD4CA, 0x57F1, 0xD4C8, 0x57F2, 0xD4BE, 0x57F3, 0xD4B9, 0x57F4, 0xD4B2, 0x57F5, 0xD8A6, 0x57F6, 0xD4B0, 0x57F7, 0xB0F5, + 0x57F8, 0xD4B7, 0x57F9, 0xB0F6, 0x57FA, 0xB0F2, 0x57FB, 0xD4AD, 0x57FC, 0xD4C3, 0x57FD, 0xD4B5, 0x5800, 0xD4B3, 0x5801, 0xD4C6, + 0x5802, 0xB0F3, 0x5804, 0xD4CC, 0x5805, 0xB0ED, 0x5806, 0xB0EF, 0x5807, 0xD4BB, 0x5808, 0xD4B6, 0x5809, 0xAE4B, 0x580A, 0xB0EE, + 0x580B, 0xD4B8, 0x580C, 0xD4C7, 0x580D, 0xD4CB, 0x580E, 0xD4C2, 0x5810, 0xD4C4, 0x5814, 0xD4AE, 0x5819, 0xD8A1, 0x581B, 0xD8AA, + 0x581C, 0xD8A9, 0x581D, 0xB3FA, 0x581E, 0xD8A2, 0x5820, 0xB3FB, 0x5821, 0xB3F9, 0x5823, 0xD8A4, 0x5824, 0xB3F6, 0x5825, 0xD8A8, + 0x5827, 0xD8A3, 0x5828, 0xD8A5, 0x5829, 0xD87D, 0x582A, 0xB3F4, 0x582C, 0xD8B2, 0x582D, 0xD8B1, 0x582E, 0xD8AE, 0x582F, 0xB3F3, + 0x5830, 0xB3F7, 0x5831, 0xB3F8, 0x5832, 0xD14B, 0x5833, 0xD8AB, 0x5834, 0xB3F5, 0x5835, 0xB0F4, 0x5836, 0xD8AD, 0x5837, 0xD87E, + 0x5838, 0xD8B0, 0x5839, 0xD8AF, 0x583B, 0xD8B3, 0x583D, 0xDCEF, 0x583F, 0xD8AC, 0x5848, 0xD8A7, 0x5849, 0xDCE7, 0x584A, 0xB6F4, + 0x584B, 0xB6F7, 0x584C, 0xB6F2, 0x584D, 0xDCE6, 0x584E, 0xDCEA, 0x584F, 0xDCE5, 0x5851, 0xB6EC, 0x5852, 0xB6F6, 0x5853, 0xDCE2, + 0x5854, 0xB6F0, 0x5855, 0xDCE9, 0x5857, 0xB6EE, 0x5858, 0xB6ED, 0x5859, 0xDCEC, 0x585A, 0xB6EF, 0x585B, 0xDCEE, 0x585D, 0xDCEB, + 0x585E, 0xB6EB, 0x5862, 0xB6F5, 0x5863, 0xDCF0, 0x5864, 0xDCE4, 0x5865, 0xDCED, 0x5868, 0xDCE3, 0x586B, 0xB6F1, 0x586D, 0xB6F3, + 0x586F, 0xDCE8, 0x5871, 0xDCF1, 0x5874, 0xE15D, 0x5875, 0xB9D0, 0x5876, 0xE163, 0x5879, 0xB9D5, 0x587A, 0xE15F, 0x587B, 0xE166, + 0x587C, 0xE157, 0x587D, 0xB9D7, 0x587E, 0xB9D1, 0x587F, 0xE15C, 0x5880, 0xBC55, 0x5881, 0xE15B, 0x5882, 0xE164, 0x5883, 0xB9D2, + 0x5885, 0xB9D6, 0x5886, 0xE15A, 0x5887, 0xE160, 0x5888, 0xE165, 0x5889, 0xE156, 0x588A, 0xB9D4, 0x588B, 0xE15E, 0x588E, 0xE162, + 0x588F, 0xE168, 0x5890, 0xE158, 0x5891, 0xE161, 0x5893, 0xB9D3, 0x5894, 0xE167, 0x5898, 0xE159, 0x589C, 0xBC59, 0x589D, 0xE54B, + 0x589E, 0xBC57, 0x589F, 0xBC56, 0x58A0, 0xE54D, 0x58A1, 0xE552, 0x58A3, 0xE54E, 0x58A5, 0xE551, 0x58A6, 0xBC5C, 0x58A8, 0xBEA5, + 0x58A9, 0xBC5B, 0x58AB, 0xE54A, 0x58AC, 0xE550, 0x58AE, 0xBC5A, 0x58AF, 0xE54F, 0x58B1, 0xE54C, 0x58B3, 0xBC58, 0x58BA, 0xE94D, + 0x58BB, 0xF9D9, 0x58BC, 0xE94F, 0x58BD, 0xE94A, 0x58BE, 0xBEC1, 0x58BF, 0xE94C, 0x58C1, 0xBEC0, 0x58C2, 0xE94E, 0x58C5, 0xBEC3, + 0x58C6, 0xE950, 0x58C7, 0xBEC2, 0x58C8, 0xE949, 0x58C9, 0xE94B, 0x58CE, 0xC0A5, 0x58CF, 0xECCC, 0x58D1, 0xC0A4, 0x58D2, 0xECCD, + 0x58D3, 0xC0A3, 0x58D4, 0xECCB, 0x58D5, 0xC0A2, 0x58D6, 0xECCA, 0x58D8, 0xC253, 0x58D9, 0xC252, 0x58DA, 0xF1F6, 0x58DB, 0xF1F8, + 0x58DD, 0xF1F7, 0x58DE, 0xC361, 0x58DF, 0xC362, 0x58E2, 0xC363, 0x58E3, 0xF442, 0x58E4, 0xC45B, 0x58E7, 0xF7D3, 0x58E8, 0xF7D2, + 0x58E9, 0xC5F2, 0x58EB, 0xA468, 0x58EC, 0xA4D0, 0x58EF, 0xA7A7, 0x58F4, 0xCE5F, 0x58F9, 0xB3FC, 0x58FA, 0xB3FD, 0x58FC, 0xDCF2, + 0x58FD, 0xB9D8, 0x58FE, 0xE169, 0x58FF, 0xE553, 0x5903, 0xC95A, 0x5906, 0xCAB0, 0x590C, 0xCC42, 0x590D, 0xCE60, 0x590E, 0xD159, + 0x590F, 0xAE4C, 0x5912, 0xF1F9, 0x5914, 0xC4DC, 0x5915, 0xA469, 0x5916, 0xA57E, 0x5917, 0xC970, 0x5919, 0xA667, 0x591A, 0xA668, + 0x591C, 0xA95D, 0x5920, 0xB0F7, 0x5922, 0xB9DA, 0x5924, 0xB9DB, 0x5925, 0xB9D9, 0x5927, 0xA46A, 0x5929, 0xA4D1, 0x592A, 0xA4D3, + 0x592B, 0xA4D2, 0x592C, 0xC95B, 0x592D, 0xA4D4, 0x592E, 0xA5A1, 0x592F, 0xC971, 0x5931, 0xA5A2, 0x5937, 0xA669, 0x5938, 0xA66A, + 0x593C, 0xC9CB, 0x593E, 0xA7A8, 0x5940, 0xCAB1, 0x5944, 0xA961, 0x5945, 0xCC43, 0x5947, 0xA95F, 0x5948, 0xA960, 0x5949, 0xA95E, + 0x594A, 0xD15A, 0x594E, 0xABB6, 0x594F, 0xABB5, 0x5950, 0xABB7, 0x5951, 0xABB4, 0x5953, 0xCE61, 0x5954, 0xA962, 0x5955, 0xABB3, + 0x5957, 0xAE4D, 0x5958, 0xAE4E, 0x595A, 0xAE4F, 0x595C, 0xD4CD, 0x5960, 0xB3FE, 0x5961, 0xD8B4, 0x5962, 0xB0F8, 0x5967, 0xB6F8, + 0x5969, 0xB9DD, 0x596A, 0xB9DC, 0x596B, 0xE16A, 0x596D, 0xBC5D, 0x596E, 0xBEC4, 0x5970, 0xEFC0, 0x5971, 0xF6DA, 0x5972, 0xF7D4, + 0x5973, 0xA46B, 0x5974, 0xA5A3, 0x5976, 0xA5A4, 0x5977, 0xC9D1, 0x5978, 0xA66C, 0x5979, 0xA66F, 0x597B, 0xC9CF, 0x597C, 0xC9CD, + 0x597D, 0xA66E, 0x597E, 0xC9D0, 0x597F, 0xC9D2, 0x5980, 0xC9CC, 0x5981, 0xA671, 0x5982, 0xA670, 0x5983, 0xA66D, 0x5984, 0xA66B, + 0x5985, 0xC9CE, 0x598A, 0xA7B3, 0x598D, 0xA7B0, 0x598E, 0xCAB6, 0x598F, 0xCAB9, 0x5990, 0xCAB8, 0x5992, 0xA7AA, 0x5993, 0xA7B2, + 0x5996, 0xA7AF, 0x5997, 0xCAB5, 0x5998, 0xCAB3, 0x5999, 0xA7AE, 0x599D, 0xA7A9, 0x599E, 0xA7AC, 0x59A0, 0xCAB4, 0x59A1, 0xCABB, + 0x59A2, 0xCAB7, 0x59A3, 0xA7AD, 0x59A4, 0xA7B1, 0x59A5, 0xA7B4, 0x59A6, 0xCAB2, 0x59A7, 0xCABA, 0x59A8, 0xA7AB, 0x59AE, 0xA967, + 0x59AF, 0xA96F, 0x59B1, 0xCC4F, 0x59B2, 0xCC48, 0x59B3, 0xA970, 0x59B4, 0xCC53, 0x59B5, 0xCC44, 0x59B6, 0xCC4B, 0x59B9, 0xA966, + 0x59BA, 0xCC45, 0x59BB, 0xA964, 0x59BC, 0xCC4C, 0x59BD, 0xCC50, 0x59BE, 0xA963, 0x59C0, 0xCC51, 0x59C1, 0xCC4A, 0x59C3, 0xCC4D, + 0x59C5, 0xA972, 0x59C6, 0xA969, 0x59C7, 0xCC54, 0x59C8, 0xCC52, 0x59CA, 0xA96E, 0x59CB, 0xA96C, 0x59CC, 0xCC49, 0x59CD, 0xA96B, + 0x59CE, 0xCC47, 0x59CF, 0xCC46, 0x59D0, 0xA96A, 0x59D1, 0xA968, 0x59D2, 0xA971, 0x59D3, 0xA96D, 0x59D4, 0xA965, 0x59D6, 0xCC4E, + 0x59D8, 0xABB9, 0x59DA, 0xABC0, 0x59DB, 0xCE6F, 0x59DC, 0xABB8, 0x59DD, 0xCE67, 0x59DE, 0xCE63, 0x59E0, 0xCE73, 0x59E1, 0xCE62, + 0x59E3, 0xABBB, 0x59E4, 0xCE6C, 0x59E5, 0xABBE, 0x59E6, 0xABC1, 0x59E8, 0xABBC, 0x59E9, 0xCE70, 0x59EA, 0xABBF, 0x59EC, 0xAE56, + 0x59ED, 0xCE76, 0x59EE, 0xCE64, 0x59F1, 0xCE66, 0x59F2, 0xCE6D, 0x59F3, 0xCE71, 0x59F4, 0xCE75, 0x59F5, 0xCE72, 0x59F6, 0xCE6B, + 0x59F7, 0xCE6E, 0x59FA, 0xCE68, 0x59FB, 0xABC3, 0x59FC, 0xCE6A, 0x59FD, 0xCE69, 0x59FE, 0xCE74, 0x59FF, 0xABBA, 0x5A00, 0xCE65, + 0x5A01, 0xABC2, 0x5A03, 0xABBD, 0x5A09, 0xAE5C, 0x5A0A, 0xD162, 0x5A0C, 0xAE5B, 0x5A0F, 0xD160, 0x5A11, 0xAE50, 0x5A13, 0xAE55, + 0x5A15, 0xD15F, 0x5A16, 0xD15C, 0x5A17, 0xD161, 0x5A18, 0xAE51, 0x5A19, 0xD15B, 0x5A1B, 0xAE54, 0x5A1C, 0xAE52, 0x5A1E, 0xD163, + 0x5A1F, 0xAE53, 0x5A20, 0xAE57, 0x5A23, 0xAE58, 0x5A25, 0xAE5A, 0x5A29, 0xAE59, 0x5A2D, 0xD15D, 0x5A2E, 0xD15E, 0x5A33, 0xD164, + 0x5A35, 0xD4D4, 0x5A36, 0xB0F9, 0x5A37, 0xD8C2, 0x5A38, 0xD4D3, 0x5A39, 0xD4E6, 0x5A3C, 0xB140, 0x5A3E, 0xD4E4, 0x5A40, 0xB0FE, + 0x5A41, 0xB0FA, 0x5A42, 0xD4ED, 0x5A43, 0xD4DD, 0x5A44, 0xD4E0, 0x5A46, 0xB143, 0x5A47, 0xD4EA, 0x5A48, 0xD4E2, 0x5A49, 0xB0FB, + 0x5A4A, 0xB144, 0x5A4C, 0xD4E7, 0x5A4D, 0xD4E5, 0x5A50, 0xD4D6, 0x5A51, 0xD4EB, 0x5A52, 0xD4DF, 0x5A53, 0xD4DA, 0x5A55, 0xD4D0, + 0x5A56, 0xD4EC, 0x5A57, 0xD4DC, 0x5A58, 0xD4CF, 0x5A5A, 0xB142, 0x5A5B, 0xD4E1, 0x5A5C, 0xD4EE, 0x5A5D, 0xD4DE, 0x5A5E, 0xD4D2, + 0x5A5F, 0xD4D7, 0x5A60, 0xD4CE, 0x5A62, 0xB141, 0x5A64, 0xD4DB, 0x5A65, 0xD4D8, 0x5A66, 0xB0FC, 0x5A67, 0xD4D1, 0x5A69, 0xD4E9, + 0x5A6A, 0xB0FD, 0x5A6C, 0xD4D9, 0x5A6D, 0xD4D5, 0x5A70, 0xD4E8, 0x5A77, 0xB440, 0x5A78, 0xD8BB, 0x5A7A, 0xD8B8, 0x5A7B, 0xD8C9, + 0x5A7C, 0xD8BD, 0x5A7D, 0xD8CA, 0x5A7F, 0xB442, 0x5A83, 0xD8C6, 0x5A84, 0xD8C3, 0x5A8A, 0xD8C4, 0x5A8B, 0xD8C7, 0x5A8C, 0xD8CB, + 0x5A8E, 0xD4E3, 0x5A8F, 0xD8CD, 0x5A90, 0xDD47, 0x5A92, 0xB443, 0x5A93, 0xD8CE, 0x5A94, 0xD8B6, 0x5A95, 0xD8C0, 0x5A97, 0xD8C5, + 0x5A9A, 0xB441, 0x5A9B, 0xB444, 0x5A9C, 0xD8CC, 0x5A9D, 0xD8CF, 0x5A9E, 0xD8BA, 0x5A9F, 0xD8B7, 0x5AA2, 0xD8B9, 0x5AA5, 0xD8BE, + 0x5AA6, 0xD8BC, 0x5AA7, 0xB445, 0x5AA9, 0xD8C8, 0x5AAC, 0xD8BF, 0x5AAE, 0xD8C1, 0x5AAF, 0xD8B5, 0x5AB0, 0xDCFA, 0x5AB1, 0xDCF8, + 0x5AB2, 0xB742, 0x5AB3, 0xB740, 0x5AB4, 0xDD43, 0x5AB5, 0xDCF9, 0x5AB6, 0xDD44, 0x5AB7, 0xDD40, 0x5AB8, 0xDCF7, 0x5AB9, 0xDD46, + 0x5ABA, 0xDCF6, 0x5ABB, 0xDCFD, 0x5ABC, 0xB6FE, 0x5ABD, 0xB6FD, 0x5ABE, 0xB6FC, 0x5ABF, 0xDCFB, 0x5AC0, 0xDD41, 0x5AC1, 0xB6F9, + 0x5AC2, 0xB741, 0x5AC4, 0xDCF4, 0x5AC6, 0xDCFE, 0x5AC7, 0xDCF3, 0x5AC8, 0xDCFC, 0x5AC9, 0xB6FA, 0x5ACA, 0xDD42, 0x5ACB, 0xDCF5, + 0x5ACC, 0xB6FB, 0x5ACD, 0xDD45, 0x5AD5, 0xE16E, 0x5AD6, 0xB9E2, 0x5AD7, 0xB9E1, 0x5AD8, 0xB9E3, 0x5AD9, 0xE17A, 0x5ADA, 0xE170, + 0x5ADB, 0xE176, 0x5ADC, 0xE16B, 0x5ADD, 0xE179, 0x5ADE, 0xE178, 0x5ADF, 0xE17C, 0x5AE0, 0xE175, 0x5AE1, 0xB9DE, 0x5AE2, 0xE174, + 0x5AE3, 0xB9E4, 0x5AE5, 0xE16D, 0x5AE6, 0xB9DF, 0x5AE8, 0xE17B, 0x5AE9, 0xB9E0, 0x5AEA, 0xE16F, 0x5AEB, 0xE172, 0x5AEC, 0xE177, + 0x5AED, 0xE171, 0x5AEE, 0xE16C, 0x5AF3, 0xE173, 0x5AF4, 0xE555, 0x5AF5, 0xBC61, 0x5AF6, 0xE558, 0x5AF7, 0xE557, 0x5AF8, 0xE55A, + 0x5AF9, 0xE55C, 0x5AFA, 0xF9DC, 0x5AFB, 0xBC5F, 0x5AFD, 0xE556, 0x5AFF, 0xE554, 0x5B01, 0xE55D, 0x5B02, 0xE55B, 0x5B03, 0xE559, + 0x5B05, 0xE55F, 0x5B07, 0xE55E, 0x5B08, 0xBC63, 0x5B09, 0xBC5E, 0x5B0B, 0xBC60, 0x5B0C, 0xBC62, 0x5B0F, 0xE560, 0x5B10, 0xE957, + 0x5B13, 0xE956, 0x5B14, 0xE955, 0x5B16, 0xE958, 0x5B17, 0xE951, 0x5B19, 0xE952, 0x5B1A, 0xE95A, 0x5B1B, 0xE953, 0x5B1D, 0xBEC5, + 0x5B1E, 0xE95C, 0x5B20, 0xE95B, 0x5B21, 0xE954, 0x5B23, 0xECD1, 0x5B24, 0xC0A8, 0x5B25, 0xECCF, 0x5B26, 0xECD4, 0x5B27, 0xECD3, + 0x5B28, 0xE959, 0x5B2A, 0xC0A7, 0x5B2C, 0xECD2, 0x5B2D, 0xECCE, 0x5B2E, 0xECD6, 0x5B2F, 0xECD5, 0x5B30, 0xC0A6, 0x5B32, 0xECD0, + 0x5B34, 0xBEC6, 0x5B38, 0xC254, 0x5B3C, 0xEFC1, 0x5B3D, 0xF1FA, 0x5B3E, 0xF1FB, 0x5B3F, 0xF1FC, 0x5B40, 0xC45C, 0x5B43, 0xC45D, + 0x5B45, 0xF443, 0x5B47, 0xF5C8, 0x5B48, 0xF5C7, 0x5B4B, 0xF6DB, 0x5B4C, 0xF6DC, 0x5B4D, 0xF7D5, 0x5B4E, 0xF8A7, 0x5B50, 0xA46C, + 0x5B51, 0xA46D, 0x5B53, 0xA46E, 0x5B54, 0xA4D5, 0x5B55, 0xA5A5, 0x5B56, 0xC9D3, 0x5B57, 0xA672, 0x5B58, 0xA673, 0x5B5A, 0xA7B7, + 0x5B5B, 0xA7B8, 0x5B5C, 0xA7B6, 0x5B5D, 0xA7B5, 0x5B5F, 0xA973, 0x5B62, 0xCC55, 0x5B63, 0xA975, 0x5B64, 0xA974, 0x5B65, 0xCC56, + 0x5B69, 0xABC4, 0x5B6B, 0xAE5D, 0x5B6C, 0xD165, 0x5B6E, 0xD4F0, 0x5B70, 0xB145, 0x5B71, 0xB447, 0x5B72, 0xD4EF, 0x5B73, 0xB446, + 0x5B75, 0xB9E5, 0x5B77, 0xE17D, 0x5B78, 0xBEC7, 0x5B7A, 0xC0A9, 0x5B7B, 0xECD7, 0x5B7D, 0xC45E, 0x5B7F, 0xC570, 0x5B81, 0xC972, + 0x5B83, 0xA5A6, 0x5B84, 0xC973, 0x5B85, 0xA676, 0x5B87, 0xA674, 0x5B88, 0xA675, 0x5B89, 0xA677, 0x5B8B, 0xA7BA, 0x5B8C, 0xA7B9, + 0x5B8E, 0xCABC, 0x5B8F, 0xA7BB, 0x5B92, 0xCABD, 0x5B93, 0xCC57, 0x5B95, 0xCC58, 0x5B97, 0xA976, 0x5B98, 0xA978, 0x5B99, 0xA97A, + 0x5B9A, 0xA977, 0x5B9B, 0xA97B, 0x5B9C, 0xA979, 0x5BA2, 0xABC8, 0x5BA3, 0xABC5, 0x5BA4, 0xABC7, 0x5BA5, 0xABC9, 0x5BA6, 0xABC6, + 0x5BA7, 0xD166, 0x5BA8, 0xCE77, 0x5BAC, 0xD168, 0x5BAD, 0xD167, 0x5BAE, 0xAE63, 0x5BB0, 0xAE5F, 0x5BB3, 0xAE60, 0x5BB4, 0xAE62, + 0x5BB5, 0xAE64, 0x5BB6, 0xAE61, 0x5BB8, 0xAE66, 0x5BB9, 0xAE65, 0x5BBF, 0xB14A, 0x5BC0, 0xD4F2, 0x5BC1, 0xD4F1, 0x5BC2, 0xB149, + 0x5BC4, 0xB148, 0x5BC5, 0xB147, 0x5BC6, 0xB14B, 0x5BC7, 0xB146, 0x5BCA, 0xD8D5, 0x5BCB, 0xD8D2, 0x5BCC, 0xB449, 0x5BCD, 0xD8D1, + 0x5BCE, 0xD8D6, 0x5BD0, 0xB44B, 0x5BD1, 0xD8D4, 0x5BD2, 0xB448, 0x5BD3, 0xB44A, 0x5BD4, 0xD8D3, 0x5BD6, 0xDD48, 0x5BD8, 0xDD49, + 0x5BD9, 0xDD4A, 0x5BDE, 0xB9E6, 0x5BDF, 0xB9EE, 0x5BE0, 0xE17E, 0x5BE1, 0xB9E8, 0x5BE2, 0xB9EC, 0x5BE3, 0xE1A1, 0x5BE4, 0xB9ED, + 0x5BE5, 0xB9E9, 0x5BE6, 0xB9EA, 0x5BE7, 0xB9E7, 0x5BE8, 0xB9EB, 0x5BE9, 0xBC66, 0x5BEA, 0xD8D0, 0x5BEB, 0xBC67, 0x5BEC, 0xBC65, + 0x5BEE, 0xBC64, 0x5BEF, 0xE95D, 0x5BF0, 0xBEC8, 0x5BF1, 0xECD8, 0x5BF2, 0xECD9, 0x5BF5, 0xC364, 0x5BF6, 0xC45F, 0x5BF8, 0xA46F, + 0x5BFA, 0xA678, 0x5C01, 0xABCA, 0x5C03, 0xD169, 0x5C04, 0xAE67, 0x5C07, 0xB14E, 0x5C08, 0xB14D, 0x5C09, 0xB14C, 0x5C0A, 0xB44C, + 0x5C0B, 0xB44D, 0x5C0C, 0xD8D7, 0x5C0D, 0xB9EF, 0x5C0E, 0xBEC9, 0x5C0F, 0xA470, 0x5C10, 0xC95C, 0x5C11, 0xA4D6, 0x5C12, 0xC974, + 0x5C15, 0xC9D4, 0x5C16, 0xA679, 0x5C1A, 0xA97C, 0x5C1F, 0xDD4B, 0x5C22, 0xA471, 0x5C24, 0xA4D7, 0x5C25, 0xC9D5, 0x5C28, 0xCABE, + 0x5C2A, 0xCABF, 0x5C2C, 0xA7BC, 0x5C30, 0xD8D8, 0x5C31, 0xB44E, 0x5C33, 0xDD4C, 0x5C37, 0xC0AA, 0x5C38, 0xA472, 0x5C39, 0xA4A8, + 0x5C3A, 0xA4D8, 0x5C3B, 0xC975, 0x5C3C, 0xA5A7, 0x5C3E, 0xA7C0, 0x5C3F, 0xA7BF, 0x5C40, 0xA7BD, 0x5C41, 0xA7BE, 0x5C44, 0xCC59, + 0x5C45, 0xA97E, 0x5C46, 0xA9A1, 0x5C47, 0xCC5A, 0x5C48, 0xA97D, 0x5C4B, 0xABCE, 0x5C4C, 0xCE78, 0x5C4D, 0xABCD, 0x5C4E, 0xABCB, + 0x5C4F, 0xABCC, 0x5C50, 0xAE6A, 0x5C51, 0xAE68, 0x5C54, 0xD16B, 0x5C55, 0xAE69, 0x5C56, 0xD16A, 0x5C58, 0xAE5E, 0x5C59, 0xD4F3, + 0x5C5C, 0xB150, 0x5C5D, 0xB151, 0x5C60, 0xB14F, 0x5C62, 0xB9F0, 0x5C63, 0xE1A2, 0x5C64, 0xBC68, 0x5C65, 0xBC69, 0x5C67, 0xE561, + 0x5C68, 0xC0AB, 0x5C69, 0xEFC2, 0x5C6A, 0xEFC3, 0x5C6C, 0xC4DD, 0x5C6D, 0xF8A8, 0x5C6E, 0xC94B, 0x5C6F, 0xA4D9, 0x5C71, 0xA473, + 0x5C73, 0xC977, 0x5C74, 0xC976, 0x5C79, 0xA67A, 0x5C7A, 0xC9D7, 0x5C7B, 0xC9D8, 0x5C7C, 0xC9D6, 0x5C7E, 0xC9D9, 0x5C86, 0xCAC7, + 0x5C88, 0xCAC2, 0x5C89, 0xCAC4, 0x5C8A, 0xCAC6, 0x5C8B, 0xCAC3, 0x5C8C, 0xA7C4, 0x5C8D, 0xCAC0, 0x5C8F, 0xCAC1, 0x5C90, 0xA7C1, + 0x5C91, 0xA7C2, 0x5C92, 0xCAC5, 0x5C93, 0xCAC8, 0x5C94, 0xA7C3, 0x5C95, 0xCAC9, 0x5C9D, 0xCC68, 0x5C9F, 0xCC62, 0x5CA0, 0xCC5D, + 0x5CA1, 0xA9A3, 0x5CA2, 0xCC65, 0x5CA3, 0xCC63, 0x5CA4, 0xCC5C, 0x5CA5, 0xCC69, 0x5CA6, 0xCC6C, 0x5CA7, 0xCC67, 0x5CA8, 0xCC60, + 0x5CA9, 0xA9A5, 0x5CAA, 0xCC66, 0x5CAB, 0xA9A6, 0x5CAC, 0xCC61, 0x5CAD, 0xCC64, 0x5CAE, 0xCC5B, 0x5CAF, 0xCC5F, 0x5CB0, 0xCC6B, + 0x5CB1, 0xA9A7, 0x5CB3, 0xA9A8, 0x5CB5, 0xCC5E, 0x5CB6, 0xCC6A, 0x5CB7, 0xA9A2, 0x5CB8, 0xA9A4, 0x5CC6, 0xCEAB, 0x5CC7, 0xCEA4, + 0x5CC8, 0xCEAA, 0x5CC9, 0xCEA3, 0x5CCA, 0xCEA5, 0x5CCB, 0xCE7D, 0x5CCC, 0xCE7B, 0x5CCE, 0xCEAC, 0x5CCF, 0xCEA9, 0x5CD0, 0xCE79, + 0x5CD2, 0xABD0, 0x5CD3, 0xCEA7, 0x5CD4, 0xCEA8, 0x5CD6, 0xCEA6, 0x5CD7, 0xCE7C, 0x5CD8, 0xCE7A, 0x5CD9, 0xABCF, 0x5CDA, 0xCEA2, + 0x5CDB, 0xCE7E, 0x5CDE, 0xCEA1, 0x5CDF, 0xCEAD, 0x5CE8, 0xAE6F, 0x5CEA, 0xAE6E, 0x5CEC, 0xD16C, 0x5CED, 0xAE6B, 0x5CEE, 0xD16E, + 0x5CF0, 0xAE70, 0x5CF1, 0xD16F, 0x5CF4, 0xAE73, 0x5CF6, 0xAE71, 0x5CF7, 0xD170, 0x5CF8, 0xCEAE, 0x5CF9, 0xD172, 0x5CFB, 0xAE6D, + 0x5CFD, 0xAE6C, 0x5CFF, 0xD16D, 0x5D00, 0xD171, 0x5D01, 0xAE72, 0x5D06, 0xB153, 0x5D07, 0xB152, 0x5D0B, 0xD4F5, 0x5D0C, 0xD4F9, + 0x5D0D, 0xD4FB, 0x5D0E, 0xB154, 0x5D0F, 0xD4FE, 0x5D11, 0xB158, 0x5D12, 0xD541, 0x5D14, 0xB15A, 0x5D16, 0xB156, 0x5D17, 0xB15E, + 0x5D19, 0xB15B, 0x5D1A, 0xD4F7, 0x5D1B, 0xB155, 0x5D1D, 0xD4F6, 0x5D1E, 0xD4F4, 0x5D1F, 0xD543, 0x5D20, 0xD4F8, 0x5D22, 0xB157, + 0x5D23, 0xD542, 0x5D24, 0xB15C, 0x5D25, 0xD4FD, 0x5D26, 0xD4FC, 0x5D27, 0xB15D, 0x5D28, 0xD4FA, 0x5D29, 0xB159, 0x5D2E, 0xD544, + 0x5D30, 0xD540, 0x5D31, 0xD8E7, 0x5D32, 0xD8EE, 0x5D33, 0xD8E3, 0x5D34, 0xB451, 0x5D35, 0xD8DF, 0x5D36, 0xD8EF, 0x5D37, 0xD8D9, + 0x5D38, 0xD8EC, 0x5D39, 0xD8EA, 0x5D3A, 0xD8E4, 0x5D3C, 0xD8ED, 0x5D3D, 0xD8E6, 0x5D3F, 0xD8DE, 0x5D40, 0xD8F0, 0x5D41, 0xD8DC, + 0x5D42, 0xD8E9, 0x5D43, 0xD8DA, 0x5D45, 0xD8F1, 0x5D47, 0xB452, 0x5D49, 0xD8EB, 0x5D4A, 0xDD4F, 0x5D4B, 0xD8DD, 0x5D4C, 0xB44F, + 0x5D4E, 0xD8E1, 0x5D50, 0xB450, 0x5D51, 0xD8E0, 0x5D52, 0xD8E5, 0x5D55, 0xD8E2, 0x5D59, 0xD8E8, 0x5D5E, 0xDD53, 0x5D62, 0xDD56, + 0x5D63, 0xDD4E, 0x5D65, 0xDD50, 0x5D67, 0xDD55, 0x5D68, 0xDD54, 0x5D69, 0xB743, 0x5D6B, 0xD8DB, 0x5D6C, 0xDD52, 0x5D6F, 0xB744, + 0x5D71, 0xDD4D, 0x5D72, 0xDD51, 0x5D77, 0xE1A9, 0x5D79, 0xE1B0, 0x5D7A, 0xE1A7, 0x5D7C, 0xE1AE, 0x5D7D, 0xE1A5, 0x5D7E, 0xE1AD, + 0x5D7F, 0xE1B1, 0x5D80, 0xE1A4, 0x5D81, 0xE1A8, 0x5D82, 0xE1A3, 0x5D84, 0xB9F1, 0x5D86, 0xE1A6, 0x5D87, 0xB9F2, 0x5D88, 0xE1AC, + 0x5D89, 0xE1AB, 0x5D8A, 0xE1AA, 0x5D8D, 0xE1AF, 0x5D92, 0xE565, 0x5D93, 0xE567, 0x5D94, 0xBC6B, 0x5D95, 0xE568, 0x5D97, 0xE563, + 0x5D99, 0xE562, 0x5D9A, 0xE56C, 0x5D9C, 0xE56A, 0x5D9D, 0xBC6A, 0x5D9E, 0xE56D, 0x5D9F, 0xE564, 0x5DA0, 0xE569, 0x5DA1, 0xE56B, + 0x5DA2, 0xE566, 0x5DA7, 0xE961, 0x5DA8, 0xE966, 0x5DA9, 0xE960, 0x5DAA, 0xE965, 0x5DAC, 0xE95E, 0x5DAD, 0xE968, 0x5DAE, 0xE964, + 0x5DAF, 0xE969, 0x5DB0, 0xE963, 0x5DB1, 0xE95F, 0x5DB2, 0xE967, 0x5DB4, 0xE96A, 0x5DB5, 0xE962, 0x5DB7, 0xECDA, 0x5DB8, 0xC0AF, + 0x5DBA, 0xC0AD, 0x5DBC, 0xC0AC, 0x5DBD, 0xC0AE, 0x5DC0, 0xEFC4, 0x5DC2, 0xF172, 0x5DC3, 0xF1FD, 0x5DC6, 0xF444, 0x5DC7, 0xF445, + 0x5DC9, 0xC460, 0x5DCB, 0xF5C9, 0x5DCD, 0xC4DE, 0x5DCF, 0xF5CA, 0x5DD1, 0xF6DE, 0x5DD2, 0xC572, 0x5DD4, 0xC571, 0x5DD5, 0xF6DD, + 0x5DD6, 0xC5C9, 0x5DD8, 0xF7D6, 0x5DDD, 0xA474, 0x5DDE, 0xA67B, 0x5DDF, 0xC9DA, 0x5DE0, 0xCACA, 0x5DE1, 0xA8B5, 0x5DE2, 0xB15F, + 0x5DE5, 0xA475, 0x5DE6, 0xA5AA, 0x5DE7, 0xA5A9, 0x5DE8, 0xA5A8, 0x5DEB, 0xA7C5, 0x5DEE, 0xAE74, 0x5DF0, 0xDD57, 0x5DF1, 0xA476, + 0x5DF2, 0xA477, 0x5DF3, 0xA478, 0x5DF4, 0xA4DA, 0x5DF7, 0xABD1, 0x5DF9, 0xCEAF, 0x5DFD, 0xB453, 0x5DFE, 0xA479, 0x5DFF, 0xC95D, + 0x5E02, 0xA5AB, 0x5E03, 0xA5AC, 0x5E04, 0xC978, 0x5E06, 0xA67C, 0x5E0A, 0xCACB, 0x5E0C, 0xA7C6, 0x5E0E, 0xCACC, 0x5E11, 0xA9AE, + 0x5E14, 0xCC6E, 0x5E15, 0xA9AC, 0x5E16, 0xA9AB, 0x5E17, 0xCC6D, 0x5E18, 0xA9A9, 0x5E19, 0xCC6F, 0x5E1A, 0xA9AA, 0x5E1B, 0xA9AD, + 0x5E1D, 0xABD2, 0x5E1F, 0xABD4, 0x5E20, 0xCEB3, 0x5E21, 0xCEB0, 0x5E22, 0xCEB1, 0x5E23, 0xCEB2, 0x5E24, 0xCEB4, 0x5E25, 0xABD3, + 0x5E28, 0xD174, 0x5E29, 0xD173, 0x5E2B, 0xAE76, 0x5E2D, 0xAE75, 0x5E33, 0xB162, 0x5E34, 0xD546, 0x5E36, 0xB161, 0x5E37, 0xB163, + 0x5E38, 0xB160, 0x5E3D, 0xB455, 0x5E3E, 0xD545, 0x5E40, 0xB456, 0x5E41, 0xD8F3, 0x5E43, 0xB457, 0x5E44, 0xD8F2, 0x5E45, 0xB454, + 0x5E4A, 0xDD5A, 0x5E4B, 0xDD5C, 0x5E4C, 0xB745, 0x5E4D, 0xDD5B, 0x5E4E, 0xDD59, 0x5E4F, 0xDD58, 0x5E53, 0xE1B4, 0x5E54, 0xB9F7, + 0x5E55, 0xB9F5, 0x5E57, 0xB9F6, 0x5E58, 0xE1B2, 0x5E59, 0xE1B3, 0x5E5B, 0xB9F3, 0x5E5C, 0xE571, 0x5E5D, 0xE56F, 0x5E5F, 0xBC6D, + 0x5E60, 0xE570, 0x5E61, 0xBC6E, 0x5E62, 0xBC6C, 0x5E63, 0xB9F4, 0x5E66, 0xE96D, 0x5E67, 0xE96B, 0x5E68, 0xE96C, 0x5E69, 0xE56E, + 0x5E6A, 0xECDC, 0x5E6B, 0xC0B0, 0x5E6C, 0xECDB, 0x5E6D, 0xEFC5, 0x5E6E, 0xEFC6, 0x5E6F, 0xE96E, 0x5E70, 0xF1FE, 0x5E72, 0xA47A, + 0x5E73, 0xA5AD, 0x5E74, 0xA67E, 0x5E75, 0xC9DB, 0x5E76, 0xA67D, 0x5E78, 0xA9AF, 0x5E79, 0xB746, 0x5E7B, 0xA4DB, 0x5E7C, 0xA5AE, + 0x5E7D, 0xABD5, 0x5E7E, 0xB458, 0x5E80, 0xC979, 0x5E82, 0xC97A, 0x5E84, 0xC9DC, 0x5E87, 0xA7C8, 0x5E88, 0xCAD0, 0x5E89, 0xCACE, + 0x5E8A, 0xA7C9, 0x5E8B, 0xCACD, 0x5E8C, 0xCACF, 0x5E8D, 0xCAD1, 0x5E8F, 0xA7C7, 0x5E95, 0xA9B3, 0x5E96, 0xA9B4, 0x5E97, 0xA9B1, + 0x5E9A, 0xA9B0, 0x5E9B, 0xCEB8, 0x5E9C, 0xA9B2, 0x5EA0, 0xABD6, 0x5EA2, 0xCEB7, 0x5EA3, 0xCEB9, 0x5EA4, 0xCEB6, 0x5EA5, 0xCEBA, + 0x5EA6, 0xABD7, 0x5EA7, 0xAE79, 0x5EA8, 0xD175, 0x5EAA, 0xD177, 0x5EAB, 0xAE77, 0x5EAC, 0xD178, 0x5EAD, 0xAE78, 0x5EAE, 0xD176, + 0x5EB0, 0xCEB5, 0x5EB1, 0xD547, 0x5EB2, 0xD54A, 0x5EB3, 0xD54B, 0x5EB4, 0xD548, 0x5EB5, 0xB167, 0x5EB6, 0xB166, 0x5EB7, 0xB164, + 0x5EB8, 0xB165, 0x5EB9, 0xD549, 0x5EBE, 0xB168, 0x5EC1, 0xB45A, 0x5EC2, 0xB45B, 0x5EC4, 0xB45C, 0x5EC5, 0xDD5D, 0x5EC6, 0xDD5F, + 0x5EC7, 0xDD61, 0x5EC8, 0xB748, 0x5EC9, 0xB747, 0x5ECA, 0xB459, 0x5ECB, 0xDD60, 0x5ECC, 0xDD5E, 0x5ECE, 0xE1B8, 0x5ED1, 0xE1B6, + 0x5ED2, 0xE1BC, 0x5ED3, 0xB9F8, 0x5ED4, 0xE1BD, 0x5ED5, 0xE1BA, 0x5ED6, 0xB9F9, 0x5ED7, 0xE1B7, 0x5ED8, 0xE1B5, 0x5ED9, 0xE1BB, + 0x5EDA, 0xBC70, 0x5EDB, 0xE573, 0x5EDC, 0xE1B9, 0x5EDD, 0xBC72, 0x5EDE, 0xE574, 0x5EDF, 0xBC71, 0x5EE0, 0xBC74, 0x5EE1, 0xE575, + 0x5EE2, 0xBC6F, 0x5EE3, 0xBC73, 0x5EE5, 0xE973, 0x5EE6, 0xE971, 0x5EE7, 0xE970, 0x5EE8, 0xE972, 0x5EE9, 0xE96F, 0x5EEC, 0xC366, + 0x5EEE, 0xF446, 0x5EEF, 0xF447, 0x5EF1, 0xF5CB, 0x5EF2, 0xF6DF, 0x5EF3, 0xC655, 0x5EF6, 0xA9B5, 0x5EF7, 0xA7CA, 0x5EFA, 0xABD8, + 0x5EFE, 0xA47B, 0x5EFF, 0xA4DC, 0x5F01, 0xA5AF, 0x5F02, 0xC9DD, 0x5F04, 0xA7CB, 0x5F05, 0xCAD2, 0x5F07, 0xCEBB, 0x5F08, 0xABD9, + 0x5F0A, 0xB9FA, 0x5F0B, 0xA47C, 0x5F0F, 0xA6A1, 0x5F12, 0xB749, 0x5F13, 0xA47D, 0x5F14, 0xA4DD, 0x5F15, 0xA4DE, 0x5F17, 0xA5B1, + 0x5F18, 0xA5B0, 0x5F1A, 0xC9DE, 0x5F1B, 0xA6A2, 0x5F1D, 0xCAD3, 0x5F1F, 0xA7CC, 0x5F22, 0xCC71, 0x5F23, 0xCC72, 0x5F24, 0xCC73, + 0x5F26, 0xA9B6, 0x5F27, 0xA9B7, 0x5F28, 0xCC70, 0x5F29, 0xA9B8, 0x5F2D, 0xABDA, 0x5F2E, 0xCEBC, 0x5F30, 0xD17A, 0x5F31, 0xAE7A, + 0x5F33, 0xD179, 0x5F35, 0xB169, 0x5F36, 0xD54C, 0x5F37, 0xB16A, 0x5F38, 0xD54D, 0x5F3C, 0xB45D, 0x5F40, 0xDD62, 0x5F43, 0xE1BF, + 0x5F44, 0xE1BE, 0x5F46, 0xB9FB, 0x5F48, 0xBC75, 0x5F49, 0xE576, 0x5F4A, 0xBECA, 0x5F4B, 0xE974, 0x5F4C, 0xC0B1, 0x5F4E, 0xC573, + 0x5F4F, 0xF7D8, 0x5F54, 0xCC74, 0x5F56, 0xCEBD, 0x5F57, 0xB16B, 0x5F58, 0xD8F4, 0x5F59, 0xB74A, 0x5F5D, 0xC255, 0x5F62, 0xA7CE, + 0x5F64, 0xA7CD, 0x5F65, 0xABDB, 0x5F67, 0xD17B, 0x5F69, 0xB16D, 0x5F6A, 0xB343, 0x5F6B, 0xB16E, 0x5F6C, 0xB16C, 0x5F6D, 0xB45E, + 0x5F6F, 0xE1C0, 0x5F70, 0xB9FC, 0x5F71, 0xBC76, 0x5F73, 0xC94C, 0x5F74, 0xC9DF, 0x5F76, 0xCAD5, 0x5F77, 0xA7CF, 0x5F78, 0xCAD4, + 0x5F79, 0xA7D0, 0x5F7C, 0xA9BC, 0x5F7D, 0xCC77, 0x5F7E, 0xCC76, 0x5F7F, 0xA9BB, 0x5F80, 0xA9B9, 0x5F81, 0xA9BA, 0x5F82, 0xCC75, + 0x5F85, 0xABDD, 0x5F86, 0xCEBE, 0x5F87, 0xABE0, 0x5F88, 0xABDC, 0x5F89, 0xABE2, 0x5F8A, 0xABDE, 0x5F8B, 0xABDF, 0x5F8C, 0xABE1, + 0x5F90, 0xAE7D, 0x5F91, 0xAE7C, 0x5F92, 0xAE7B, 0x5F96, 0xD54F, 0x5F97, 0xB16F, 0x5F98, 0xB172, 0x5F99, 0xB170, 0x5F9B, 0xD54E, + 0x5F9C, 0xB175, 0x5F9E, 0xB171, 0x5F9F, 0xD550, 0x5FA0, 0xB174, 0x5FA1, 0xB173, 0x5FA5, 0xD8F6, 0x5FA6, 0xD8F5, 0x5FA8, 0xB461, + 0x5FA9, 0xB45F, 0x5FAA, 0xB460, 0x5FAB, 0xD8F7, 0x5FAC, 0xB74B, 0x5FAD, 0xDD64, 0x5FAE, 0xB74C, 0x5FAF, 0xDD63, 0x5FB2, 0xE577, + 0x5FB5, 0xBC78, 0x5FB6, 0xE1C1, 0x5FB7, 0xBC77, 0x5FB9, 0xB9FD, 0x5FBB, 0xECDE, 0x5FBC, 0xE975, 0x5FBD, 0xC0B2, 0x5FBE, 0xECDD, + 0x5FBF, 0xF240, 0x5FC0, 0xF448, 0x5FC1, 0xF449, 0x5FC3, 0xA4DF, 0x5FC5, 0xA5B2, 0x5FC9, 0xC97B, 0x5FCC, 0xA7D2, 0x5FCD, 0xA7D4, + 0x5FCF, 0xC9E2, 0x5FD0, 0xCAD8, 0x5FD1, 0xCAD7, 0x5FD2, 0xCAD6, 0x5FD4, 0xC9E1, 0x5FD5, 0xC9E0, 0x5FD6, 0xA6A4, 0x5FD7, 0xA7D3, + 0x5FD8, 0xA7D1, 0x5FD9, 0xA6A3, 0x5FDD, 0xA9BD, 0x5FDE, 0xCC78, 0x5FE0, 0xA9BE, 0x5FE1, 0xCADD, 0x5FE3, 0xCADF, 0x5FE4, 0xCADE, + 0x5FE5, 0xCC79, 0x5FE8, 0xCADA, 0x5FEA, 0xA7D8, 0x5FEB, 0xA7D6, 0x5FED, 0xCAD9, 0x5FEE, 0xCADB, 0x5FEF, 0xCAE1, 0x5FF1, 0xA7D5, + 0x5FF3, 0xCADC, 0x5FF4, 0xCAE5, 0x5FF5, 0xA9C0, 0x5FF7, 0xCAE2, 0x5FF8, 0xA7D7, 0x5FFA, 0xCAE0, 0x5FFB, 0xCAE3, 0x5FFD, 0xA9BF, + 0x5FFF, 0xA9C1, 0x6000, 0xCAE4, 0x6009, 0xCCAF, 0x600A, 0xCCA2, 0x600B, 0xCC7E, 0x600C, 0xCCAE, 0x600D, 0xCCA9, 0x600E, 0xABE7, + 0x600F, 0xA9C2, 0x6010, 0xCCAA, 0x6011, 0xCCAD, 0x6012, 0xABE3, 0x6013, 0xCCAC, 0x6014, 0xA9C3, 0x6015, 0xA9C8, 0x6016, 0xA9C6, + 0x6017, 0xCCA3, 0x6019, 0xCC7C, 0x601A, 0xCCA5, 0x601B, 0xA9CD, 0x601C, 0xCCB0, 0x601D, 0xABE4, 0x601E, 0xCCA6, 0x6020, 0xABE5, + 0x6021, 0xA9C9, 0x6022, 0xCCA8, 0x6024, 0xCECD, 0x6025, 0xABE6, 0x6026, 0xCC7B, 0x6027, 0xA9CA, 0x6028, 0xABE8, 0x6029, 0xA9CB, + 0x602A, 0xA9C7, 0x602B, 0xA9CC, 0x602C, 0xCCA7, 0x602D, 0xCC7A, 0x602E, 0xCCAB, 0x602F, 0xA9C4, 0x6032, 0xCC7D, 0x6033, 0xCCA4, + 0x6034, 0xCCA1, 0x6035, 0xA9C5, 0x6037, 0xCEBF, 0x6039, 0xCEC0, 0x6040, 0xCECA, 0x6041, 0xD1A1, 0x6042, 0xCECB, 0x6043, 0xABEE, + 0x6044, 0xCECE, 0x6045, 0xCEC4, 0x6046, 0xABED, 0x6047, 0xCEC6, 0x6049, 0xCEC7, 0x604C, 0xCEC9, 0x604D, 0xABE9, 0x6050, 0xAEA3, + 0x6052, 0xF9DA, 0x6053, 0xCEC5, 0x6054, 0xCEC1, 0x6055, 0xAEA4, 0x6058, 0xCECF, 0x6059, 0xAE7E, 0x605A, 0xD17D, 0x605B, 0xCEC8, + 0x605D, 0xD17C, 0x605E, 0xCEC3, 0x605F, 0xCECC, 0x6062, 0xABEC, 0x6063, 0xAEA1, 0x6064, 0xABF2, 0x6065, 0xAEA2, 0x6066, 0xCED0, + 0x6067, 0xD17E, 0x6068, 0xABEB, 0x6069, 0xAEA6, 0x606A, 0xABF1, 0x606B, 0xABF0, 0x606C, 0xABEF, 0x606D, 0xAEA5, 0x606E, 0xCED1, + 0x606F, 0xAEA7, 0x6070, 0xABEA, 0x6072, 0xCEC2, 0x607F, 0xB176, 0x6080, 0xD1A4, 0x6081, 0xD1A6, 0x6083, 0xD1A8, 0x6084, 0xAEA8, + 0x6085, 0xAEAE, 0x6086, 0xD553, 0x6087, 0xD1AC, 0x6088, 0xD1A3, 0x6089, 0xB178, 0x608A, 0xD551, 0x608C, 0xAEAD, 0x608D, 0xAEAB, + 0x608E, 0xD1AE, 0x6090, 0xD552, 0x6092, 0xD1A5, 0x6094, 0xAEAC, 0x6095, 0xD1A9, 0x6096, 0xAEAF, 0x6097, 0xD1AB, 0x609A, 0xAEAA, + 0x609B, 0xD1AA, 0x609C, 0xD1AD, 0x609D, 0xD1A7, 0x609F, 0xAEA9, 0x60A0, 0xB179, 0x60A2, 0xD1A2, 0x60A3, 0xB177, 0x60A8, 0xB17A, + 0x60B0, 0xD555, 0x60B1, 0xD55E, 0x60B2, 0xB464, 0x60B4, 0xB17C, 0x60B5, 0xB1A3, 0x60B6, 0xB465, 0x60B7, 0xD560, 0x60B8, 0xB1AA, + 0x60B9, 0xD8F9, 0x60BA, 0xD556, 0x60BB, 0xB1A2, 0x60BC, 0xB1A5, 0x60BD, 0xB17E, 0x60BE, 0xD554, 0x60BF, 0xD562, 0x60C0, 0xD565, + 0x60C1, 0xD949, 0x60C3, 0xD563, 0x60C4, 0xD8FD, 0x60C5, 0xB1A1, 0x60C6, 0xB1A8, 0x60C7, 0xB1AC, 0x60C8, 0xD55D, 0x60C9, 0xD8F8, + 0x60CA, 0xD561, 0x60CB, 0xB17B, 0x60CC, 0xD8FA, 0x60CD, 0xD564, 0x60CE, 0xD8FC, 0x60CF, 0xD559, 0x60D1, 0xB462, 0x60D3, 0xD557, + 0x60D4, 0xD558, 0x60D5, 0xB1A7, 0x60D8, 0xB1A6, 0x60D9, 0xD55B, 0x60DA, 0xB1AB, 0x60DB, 0xD55F, 0x60DC, 0xB1A4, 0x60DD, 0xD55C, + 0x60DF, 0xB1A9, 0x60E0, 0xB466, 0x60E1, 0xB463, 0x60E2, 0xD8FB, 0x60E4, 0xD55A, 0x60E6, 0xB17D, 0x60F0, 0xB46B, 0x60F1, 0xB46F, + 0x60F2, 0xD940, 0x60F3, 0xB751, 0x60F4, 0xB46D, 0x60F5, 0xD944, 0x60F6, 0xB471, 0x60F7, 0xDD65, 0x60F8, 0xD946, 0x60F9, 0xB753, + 0x60FA, 0xB469, 0x60FB, 0xB46C, 0x60FC, 0xD947, 0x60FE, 0xD948, 0x60FF, 0xD94E, 0x6100, 0xB473, 0x6101, 0xB754, 0x6103, 0xD94A, + 0x6104, 0xD94F, 0x6105, 0xD943, 0x6106, 0xB75E, 0x6108, 0xB755, 0x6109, 0xB472, 0x610A, 0xD941, 0x610B, 0xD950, 0x610D, 0xB75D, + 0x610E, 0xB470, 0x610F, 0xB74E, 0x6110, 0xD94D, 0x6112, 0xB474, 0x6113, 0xD945, 0x6114, 0xD8FE, 0x6115, 0xB46A, 0x6116, 0xD942, + 0x6118, 0xD94B, 0x611A, 0xB74D, 0x611B, 0xB752, 0x611C, 0xB467, 0x611D, 0xD94C, 0x611F, 0xB750, 0x6123, 0xB468, 0x6127, 0xB75C, + 0x6128, 0xE1C3, 0x6129, 0xDD70, 0x612B, 0xDD68, 0x612C, 0xE1C2, 0x612E, 0xDD6C, 0x612F, 0xDD6E, 0x6132, 0xDD6B, 0x6134, 0xB75B, + 0x6136, 0xDD6A, 0x6137, 0xB75F, 0x613B, 0xE1D2, 0x613E, 0xB75A, 0x613F, 0xBA40, 0x6140, 0xDD71, 0x6141, 0xE1C4, 0x6144, 0xB758, + 0x6145, 0xDD69, 0x6146, 0xDD6D, 0x6147, 0xB9FE, 0x6148, 0xB74F, 0x6149, 0xDD66, 0x614A, 0xDD67, 0x614B, 0xBA41, 0x614C, 0xB757, + 0x614D, 0xB759, 0x614E, 0xB756, 0x614F, 0xDD6F, 0x6152, 0xE1C8, 0x6153, 0xE1C9, 0x6154, 0xE1CE, 0x6155, 0xBC7D, 0x6156, 0xE1D5, + 0x6158, 0xBA47, 0x615A, 0xBA46, 0x615B, 0xE1D0, 0x615D, 0xBC7C, 0x615E, 0xE1C5, 0x615F, 0xBA45, 0x6161, 0xE1D4, 0x6162, 0xBA43, + 0x6163, 0xBA44, 0x6165, 0xE1D1, 0x6166, 0xE5AA, 0x6167, 0xBC7A, 0x6168, 0xB46E, 0x616A, 0xE1D3, 0x616B, 0xBCA3, 0x616C, 0xE1CB, + 0x616E, 0xBC7B, 0x6170, 0xBCA2, 0x6171, 0xE1C6, 0x6172, 0xE1CA, 0x6173, 0xE1C7, 0x6174, 0xE1CD, 0x6175, 0xBA48, 0x6176, 0xBC79, + 0x6177, 0xBA42, 0x6179, 0xE57A, 0x617A, 0xE1CF, 0x617C, 0xBCA1, 0x617E, 0xBCA4, 0x6180, 0xE1CC, 0x6182, 0xBC7E, 0x6183, 0xE579, + 0x6189, 0xE57E, 0x618A, 0xBECE, 0x618B, 0xE578, 0x618C, 0xE9A3, 0x618D, 0xE5A9, 0x618E, 0xBCA8, 0x6190, 0xBCA6, 0x6191, 0xBECC, + 0x6192, 0xE5A6, 0x6193, 0xE5A2, 0x6194, 0xBCAC, 0x6196, 0xE978, 0x619A, 0xBCAA, 0x619B, 0xE5A1, 0x619D, 0xE976, 0x619F, 0xE5A5, + 0x61A1, 0xE5A8, 0x61A2, 0xE57D, 0x61A4, 0xBCAB, 0x61A7, 0xBCA5, 0x61A8, 0xE977, 0x61A9, 0xBECD, 0x61AA, 0xE5A7, 0x61AB, 0xBCA7, + 0x61AC, 0xBCA9, 0x61AD, 0xE5A4, 0x61AE, 0xBCAD, 0x61AF, 0xE5A3, 0x61B0, 0xE57C, 0x61B1, 0xE57B, 0x61B2, 0xBECB, 0x61B3, 0xE5AB, + 0x61B4, 0xE97A, 0x61B5, 0xECE0, 0x61B6, 0xBED0, 0x61B8, 0xE9A2, 0x61BA, 0xE97E, 0x61BC, 0xECE1, 0x61BE, 0xBED1, 0x61BF, 0xE9A1, + 0x61C1, 0xE97C, 0x61C2, 0xC0B4, 0x61C3, 0xECDF, 0x61C5, 0xE979, 0x61C6, 0xE97B, 0x61C7, 0xC0B5, 0x61C8, 0xBED3, 0x61C9, 0xC0B3, + 0x61CA, 0xBED2, 0x61CB, 0xC0B7, 0x61CC, 0xE97D, 0x61CD, 0xBECF, 0x61D6, 0xEFCF, 0x61D8, 0xEFC7, 0x61DE, 0xECE7, 0x61DF, 0xEFC8, + 0x61E0, 0xECE3, 0x61E3, 0xC256, 0x61E4, 0xECE5, 0x61E5, 0xECE4, 0x61E6, 0xC0B6, 0x61E7, 0xECE2, 0x61E8, 0xECE6, 0x61E9, 0xEFD0, + 0x61EA, 0xEFCC, 0x61EB, 0xEFCE, 0x61ED, 0xEFC9, 0x61EE, 0xEFCA, 0x61F0, 0xEFCD, 0x61F1, 0xEFCB, 0x61F2, 0xC367, 0x61F5, 0xC36A, + 0x61F6, 0xC369, 0x61F7, 0xC368, 0x61F8, 0xC461, 0x61F9, 0xF44A, 0x61FA, 0xC462, 0x61FB, 0xF241, 0x61FC, 0xC4DF, 0x61FD, 0xF5CC, + 0x61FE, 0xC4E0, 0x61FF, 0xC574, 0x6200, 0xC5CA, 0x6201, 0xF7D9, 0x6203, 0xF7DA, 0x6204, 0xF7DB, 0x6207, 0xF9BA, 0x6208, 0xA4E0, + 0x6209, 0xC97C, 0x620A, 0xA5B3, 0x620C, 0xA6A6, 0x620D, 0xA6A7, 0x620E, 0xA6A5, 0x6210, 0xA6A8, 0x6211, 0xA7DA, 0x6212, 0xA7D9, + 0x6214, 0xCCB1, 0x6215, 0xA9CF, 0x6216, 0xA9CE, 0x6219, 0xD1AF, 0x621A, 0xB1AD, 0x621B, 0xB1AE, 0x621F, 0xB475, 0x6220, 0xDD72, + 0x6221, 0xB760, 0x6222, 0xB761, 0x6223, 0xDD74, 0x6224, 0xDD76, 0x6225, 0xDD75, 0x6227, 0xE1D7, 0x6229, 0xE1D6, 0x622A, 0xBA49, + 0x622B, 0xE1D8, 0x622D, 0xE5AC, 0x622E, 0xBCAE, 0x6230, 0xBED4, 0x6232, 0xC0B8, 0x6233, 0xC257, 0x6234, 0xC0B9, 0x6236, 0xA4E1, + 0x623A, 0xCAE6, 0x623D, 0xCCB2, 0x623E, 0xA9D1, 0x623F, 0xA9D0, 0x6240, 0xA9D2, 0x6241, 0xABF3, 0x6242, 0xCED2, 0x6243, 0xCED3, + 0x6246, 0xD1B0, 0x6247, 0xAEB0, 0x6248, 0xB1AF, 0x6249, 0xB476, 0x624A, 0xD951, 0x624B, 0xA4E2, 0x624D, 0xA47E, 0x624E, 0xA4E3, + 0x6250, 0xC97D, 0x6251, 0xA5B7, 0x6252, 0xA5B6, 0x6253, 0xA5B4, 0x6254, 0xA5B5, 0x6258, 0xA6AB, 0x6259, 0xC9E9, 0x625A, 0xC9EB, + 0x625B, 0xA6AA, 0x625C, 0xC9E3, 0x625E, 0xC9E4, 0x6260, 0xC9EA, 0x6261, 0xC9E6, 0x6262, 0xC9E8, 0x6263, 0xA6A9, 0x6264, 0xC9E5, + 0x6265, 0xC9EC, 0x6266, 0xC9E7, 0x626D, 0xA7E1, 0x626E, 0xA7EA, 0x626F, 0xA7E8, 0x6270, 0xCAF0, 0x6271, 0xCAED, 0x6272, 0xCAF5, + 0x6273, 0xA7E6, 0x6274, 0xCAF6, 0x6276, 0xA7DF, 0x6277, 0xCAF3, 0x6279, 0xA7E5, 0x627A, 0xCAEF, 0x627B, 0xCAEE, 0x627C, 0xA7E3, + 0x627D, 0xCAF4, 0x627E, 0xA7E4, 0x627F, 0xA9D3, 0x6280, 0xA7DE, 0x6281, 0xCAF1, 0x6283, 0xCAE7, 0x6284, 0xA7DB, 0x6286, 0xA7EE, + 0x6287, 0xCAEC, 0x6288, 0xCAF2, 0x6289, 0xA7E0, 0x628A, 0xA7E2, 0x628C, 0xCAE8, 0x628E, 0xCAE9, 0x628F, 0xCAEA, 0x6291, 0xA7ED, + 0x6292, 0xA7E7, 0x6293, 0xA7EC, 0x6294, 0xCAEB, 0x6295, 0xA7EB, 0x6296, 0xA7DD, 0x6297, 0xA7DC, 0x6298, 0xA7E9, 0x62A8, 0xA9E1, + 0x62A9, 0xCCBE, 0x62AA, 0xCCB7, 0x62AB, 0xA9DC, 0x62AC, 0xA9EF, 0x62AD, 0xCCB3, 0x62AE, 0xCCBA, 0x62AF, 0xCCBC, 0x62B0, 0xCCBF, + 0x62B1, 0xA9EA, 0x62B3, 0xCCBB, 0x62B4, 0xCCB4, 0x62B5, 0xA9E8, 0x62B6, 0xCCB8, 0x62B8, 0xCCC0, 0x62B9, 0xA9D9, 0x62BB, 0xCCBD, + 0x62BC, 0xA9E3, 0x62BD, 0xA9E2, 0x62BE, 0xCCB6, 0x62BF, 0xA9D7, 0x62C2, 0xA9D8, 0x62C4, 0xA9D6, 0x62C6, 0xA9EE, 0x62C7, 0xA9E6, + 0x62C8, 0xA9E0, 0x62C9, 0xA9D4, 0x62CA, 0xCCB9, 0x62CB, 0xA9DF, 0x62CC, 0xA9D5, 0x62CD, 0xA9E7, 0x62CE, 0xA9F0, 0x62CF, 0xCED4, + 0x62D0, 0xA9E4, 0x62D1, 0xCCB5, 0x62D2, 0xA9DA, 0x62D3, 0xA9DD, 0x62D4, 0xA9DE, 0x62D6, 0xA9EC, 0x62D7, 0xA9ED, 0x62D8, 0xA9EB, + 0x62D9, 0xA9E5, 0x62DA, 0xA9E9, 0x62DB, 0xA9DB, 0x62DC, 0xABF4, 0x62EB, 0xCEDA, 0x62EC, 0xAC41, 0x62ED, 0xABF8, 0x62EE, 0xABFA, + 0x62EF, 0xAC40, 0x62F0, 0xCEE6, 0x62F1, 0xABFD, 0x62F2, 0xD1B1, 0x62F3, 0xAEB1, 0x62F4, 0xAC43, 0x62F5, 0xCED7, 0x62F6, 0xCEDF, + 0x62F7, 0xABFE, 0x62F8, 0xCEDE, 0x62F9, 0xCEDB, 0x62FA, 0xCEE3, 0x62FB, 0xCEE5, 0x62FC, 0xABF7, 0x62FD, 0xABFB, 0x62FE, 0xAC42, + 0x62FF, 0xAEB3, 0x6300, 0xCEE0, 0x6301, 0xABF9, 0x6302, 0xAC45, 0x6303, 0xCED9, 0x6307, 0xABFC, 0x6308, 0xAEB2, 0x6309, 0xABF6, + 0x630B, 0xCED6, 0x630C, 0xCEDD, 0x630D, 0xCED5, 0x630E, 0xCED8, 0x630F, 0xCEDC, 0x6310, 0xD1B2, 0x6311, 0xAC44, 0x6313, 0xCEE1, + 0x6314, 0xCEE2, 0x6315, 0xCEE4, 0x6316, 0xABF5, 0x6328, 0xAEC1, 0x6329, 0xD1BE, 0x632A, 0xAEBF, 0x632B, 0xAEC0, 0x632C, 0xD1B4, + 0x632D, 0xD1C4, 0x632F, 0xAEB6, 0x6332, 0xD566, 0x6333, 0xD1C6, 0x6334, 0xD1C0, 0x6336, 0xD1B7, 0x6338, 0xD1C9, 0x6339, 0xD1BA, + 0x633A, 0xAEBC, 0x633B, 0xD57D, 0x633C, 0xD1BD, 0x633D, 0xAEBE, 0x633E, 0xAEB5, 0x6340, 0xD1CB, 0x6341, 0xD1BF, 0x6342, 0xAEB8, + 0x6343, 0xD1B8, 0x6344, 0xD1B5, 0x6345, 0xD1B6, 0x6346, 0xAEB9, 0x6347, 0xD1C5, 0x6348, 0xD1CC, 0x6349, 0xAEBB, 0x634A, 0xD1BC, + 0x634B, 0xD1BB, 0x634C, 0xAEC3, 0x634D, 0xAEC2, 0x634E, 0xAEB4, 0x634F, 0xAEBA, 0x6350, 0xAEBD, 0x6351, 0xD1C8, 0x6354, 0xD1C2, + 0x6355, 0xAEB7, 0x6356, 0xD1B3, 0x6357, 0xD1CA, 0x6358, 0xD1C1, 0x6359, 0xD1C3, 0x635A, 0xD1C7, 0x6365, 0xD567, 0x6367, 0xB1B7, + 0x6368, 0xB1CB, 0x6369, 0xB1CA, 0x636B, 0xB1BF, 0x636D, 0xD579, 0x636E, 0xD575, 0x636F, 0xD572, 0x6370, 0xD5A6, 0x6371, 0xB1BA, + 0x6372, 0xB1B2, 0x6375, 0xD577, 0x6376, 0xB4A8, 0x6377, 0xB1B6, 0x6378, 0xD5A1, 0x637A, 0xB1CC, 0x637B, 0xB1C9, 0x637C, 0xD57B, + 0x637D, 0xD56A, 0x6380, 0xB1C8, 0x6381, 0xD5A3, 0x6382, 0xD569, 0x6383, 0xB1BD, 0x6384, 0xB1C1, 0x6385, 0xD5A2, 0x6387, 0xD573, + 0x6388, 0xB1C2, 0x6389, 0xB1BC, 0x638A, 0xD568, 0x638C, 0xB478, 0x638D, 0xD5A5, 0x638E, 0xD571, 0x638F, 0xB1C7, 0x6390, 0xD574, + 0x6391, 0xD5A4, 0x6392, 0xB1C6, 0x6394, 0xD952, 0x6396, 0xB1B3, 0x6397, 0xD56F, 0x6398, 0xB1B8, 0x6399, 0xB1C3, 0x639B, 0xB1BE, + 0x639C, 0xD578, 0x639D, 0xD56E, 0x639E, 0xD56C, 0x639F, 0xD57E, 0x63A0, 0xB1B0, 0x63A1, 0xB1C4, 0x63A2, 0xB1B4, 0x63A3, 0xB477, + 0x63A4, 0xD57C, 0x63A5, 0xB1B5, 0x63A7, 0xB1B1, 0x63A8, 0xB1C0, 0x63A9, 0xB1BB, 0x63AA, 0xB1B9, 0x63AB, 0xD570, 0x63AC, 0xB1C5, + 0x63AD, 0xD56D, 0x63AE, 0xD57A, 0x63AF, 0xD576, 0x63B0, 0xD954, 0x63B1, 0xD953, 0x63BD, 0xD56B, 0x63BE, 0xD964, 0x63C0, 0xB47A, + 0x63C2, 0xD96A, 0x63C3, 0xD959, 0x63C4, 0xD967, 0x63C5, 0xDD77, 0x63C6, 0xB47D, 0x63C7, 0xD96B, 0x63C8, 0xD96E, 0x63C9, 0xB47C, + 0x63CA, 0xD95C, 0x63CB, 0xD96D, 0x63CC, 0xD96C, 0x63CD, 0xB47E, 0x63CE, 0xD955, 0x63CF, 0xB479, 0x63D0, 0xB4A3, 0x63D2, 0xB4A1, + 0x63D3, 0xD969, 0x63D5, 0xD95F, 0x63D6, 0xB4A5, 0x63D7, 0xD970, 0x63D8, 0xD968, 0x63D9, 0xD971, 0x63DA, 0xB4AD, 0x63DB, 0xB4AB, + 0x63DC, 0xD966, 0x63DD, 0xD965, 0x63DF, 0xD963, 0x63E0, 0xD95D, 0x63E1, 0xB4A4, 0x63E3, 0xB4A2, 0x63E4, 0xD1B9, 0x63E5, 0xD956, + 0x63E7, 0xDDB7, 0x63E8, 0xD957, 0x63E9, 0xB47B, 0x63EA, 0xB4AA, 0x63EB, 0xDD79, 0x63ED, 0xB4A6, 0x63EE, 0xB4A7, 0x63EF, 0xD958, + 0x63F0, 0xD96F, 0x63F1, 0xDD78, 0x63F2, 0xD960, 0x63F3, 0xD95B, 0x63F4, 0xB4A9, 0x63F5, 0xD961, 0x63F6, 0xD95E, 0x63F9, 0xB4AE, + 0x6406, 0xB770, 0x6409, 0xDD7C, 0x640A, 0xDDB1, 0x640B, 0xDDB6, 0x640C, 0xDDAA, 0x640D, 0xB76C, 0x640E, 0xDDBB, 0x640F, 0xB769, + 0x6410, 0xDD7A, 0x6412, 0xDD7B, 0x6413, 0xB762, 0x6414, 0xB76B, 0x6415, 0xDDA4, 0x6416, 0xB76E, 0x6417, 0xB76F, 0x6418, 0xDDA5, + 0x641A, 0xDDB2, 0x641B, 0xDDB8, 0x641C, 0xB76A, 0x641E, 0xB764, 0x641F, 0xDDA3, 0x6420, 0xDD7D, 0x6421, 0xDDBA, 0x6422, 0xDDA8, + 0x6423, 0xDDA9, 0x6424, 0xDD7E, 0x6425, 0xDDB4, 0x6426, 0xDDAB, 0x6427, 0xDDB5, 0x6428, 0xDDAD, 0x642A, 0xB765, 0x642B, 0xE1D9, + 0x642C, 0xB768, 0x642D, 0xB766, 0x642E, 0xDDB9, 0x642F, 0xDDB0, 0x6430, 0xDDAC, 0x6433, 0xDDA1, 0x6434, 0xBA53, 0x6435, 0xDDAF, + 0x6436, 0xB76D, 0x6437, 0xDDA7, 0x6439, 0xDDA6, 0x643D, 0xB767, 0x643E, 0xB763, 0x643F, 0xE1EE, 0x6440, 0xDDB3, 0x6441, 0xDDAE, + 0x6443, 0xDDA2, 0x644B, 0xE1E9, 0x644D, 0xE1DA, 0x644E, 0xE1E5, 0x6450, 0xE1EC, 0x6451, 0xBA51, 0x6452, 0xB4AC, 0x6453, 0xE1EA, + 0x6454, 0xBA4C, 0x6458, 0xBA4B, 0x6459, 0xE1F1, 0x645B, 0xE1DB, 0x645C, 0xE1E8, 0x645D, 0xE1DC, 0x645E, 0xE1E7, 0x645F, 0xBA4F, + 0x6460, 0xE1EB, 0x6461, 0xD962, 0x6465, 0xE1F2, 0x6466, 0xE1E3, 0x6467, 0xBA52, 0x6468, 0xE5BA, 0x6469, 0xBCAF, 0x646B, 0xE1F0, + 0x646C, 0xE1EF, 0x646D, 0xBA54, 0x646E, 0xE5AD, 0x646F, 0xBCB0, 0x6470, 0xE5AE, 0x6472, 0xE1DF, 0x6473, 0xE1E0, 0x6474, 0xE1DD, + 0x6475, 0xE1E2, 0x6476, 0xE1DE, 0x6477, 0xE1F3, 0x6478, 0xBA4E, 0x6479, 0xBCB1, 0x647A, 0xBA50, 0x647B, 0xBA55, 0x647D, 0xE1E1, + 0x647F, 0xE1ED, 0x6482, 0xE1E6, 0x6485, 0xE5B1, 0x6487, 0xBA4A, 0x6488, 0xBCB4, 0x6489, 0xE9AA, 0x648A, 0xE5B6, 0x648B, 0xE5B5, + 0x648C, 0xE5B7, 0x648F, 0xE5B4, 0x6490, 0xBCB5, 0x6492, 0xBCBB, 0x6493, 0xBCB8, 0x6495, 0xBCB9, 0x6496, 0xE5AF, 0x6497, 0xE5B2, + 0x6498, 0xE5BC, 0x6499, 0xBCC1, 0x649A, 0xBCBF, 0x649C, 0xE5B3, 0x649D, 0xD95A, 0x649E, 0xBCB2, 0x649F, 0xE5B9, 0x64A0, 0xE5B0, + 0x64A2, 0xBCC2, 0x64A3, 0xE5B8, 0x64A4, 0xBA4D, 0x64A5, 0xBCB7, 0x64A6, 0xE1E4, 0x64A9, 0xBCBA, 0x64AB, 0xBCBE, 0x64AC, 0xBCC0, + 0x64AD, 0xBCBD, 0x64AE, 0xBCBC, 0x64B0, 0xBCB6, 0x64B1, 0xE5BB, 0x64B2, 0xBCB3, 0x64B3, 0xBCC3, 0x64BB, 0xBED8, 0x64BC, 0xBED9, + 0x64BD, 0xE9A9, 0x64BE, 0xBEE2, 0x64BF, 0xBEDF, 0x64C1, 0xBED6, 0x64C2, 0xBEDD, 0x64C3, 0xE9AB, 0x64C4, 0xBEDB, 0x64C5, 0xBED5, + 0x64C7, 0xBEDC, 0x64C9, 0xE9A8, 0x64CA, 0xC0BB, 0x64CB, 0xBED7, 0x64CD, 0xBEDE, 0x64CE, 0xC0BA, 0x64CF, 0xE9A7, 0x64D0, 0xE9A6, + 0x64D2, 0xBEE0, 0x64D4, 0xBEE1, 0x64D6, 0xE9A5, 0x64D7, 0xE9A4, 0x64D8, 0xC0BC, 0x64D9, 0xE9AE, 0x64DA, 0xBEDA, 0x64DB, 0xE9AC, + 0x64E0, 0xC0BD, 0x64E2, 0xC0C2, 0x64E3, 0xECEA, 0x64E4, 0xECEC, 0x64E6, 0xC0BF, 0x64E8, 0xECED, 0x64E9, 0xECE9, 0x64EB, 0xECEB, + 0x64EC, 0xC0C0, 0x64ED, 0xC0C3, 0x64EF, 0xECE8, 0x64F0, 0xC0BE, 0x64F1, 0xC0C1, 0x64F2, 0xC259, 0x64F3, 0xE9AD, 0x64F4, 0xC258, + 0x64F7, 0xC25E, 0x64F8, 0xEFD4, 0x64FA, 0xC25C, 0x64FB, 0xC25D, 0x64FC, 0xEFD7, 0x64FD, 0xEFD3, 0x64FE, 0xC25A, 0x64FF, 0xEFD1, + 0x6500, 0xC36B, 0x6501, 0xEFD5, 0x6503, 0xEFD6, 0x6504, 0xEFD2, 0x6506, 0xC25B, 0x6507, 0xF242, 0x6509, 0xF245, 0x650C, 0xF246, + 0x650D, 0xF244, 0x650E, 0xF247, 0x650F, 0xC36C, 0x6510, 0xF243, 0x6513, 0xF44E, 0x6514, 0xC464, 0x6515, 0xF44D, 0x6516, 0xF44C, + 0x6517, 0xF44B, 0x6518, 0xC463, 0x6519, 0xC465, 0x651B, 0xF5CD, 0x651C, 0xC4E2, 0x651D, 0xC4E1, 0x6520, 0xF6E1, 0x6521, 0xF6E0, + 0x6522, 0xF6E3, 0x6523, 0xC5CB, 0x6524, 0xC575, 0x6525, 0xF7DD, 0x6526, 0xF6E2, 0x6529, 0xF7DC, 0x652A, 0xC5CD, 0x652B, 0xC5CC, + 0x652C, 0xC5F3, 0x652D, 0xF8A9, 0x652E, 0xF8EF, 0x652F, 0xA4E4, 0x6532, 0xD972, 0x6533, 0xE9AF, 0x6536, 0xA6AC, 0x6537, 0xCAF7, + 0x6538, 0xA7F1, 0x6539, 0xA7EF, 0x653B, 0xA7F0, 0x653D, 0xCCC1, 0x653E, 0xA9F1, 0x653F, 0xAC46, 0x6541, 0xCEE7, 0x6543, 0xCEE8, + 0x6545, 0xAC47, 0x6546, 0xD1CE, 0x6548, 0xAEC4, 0x6549, 0xAEC5, 0x654A, 0xD1CD, 0x654F, 0xB1D3, 0x6551, 0xB1CF, 0x6553, 0xD5A7, + 0x6554, 0xB1D6, 0x6555, 0xB1D5, 0x6556, 0xB1CE, 0x6557, 0xB1D1, 0x6558, 0xB1D4, 0x6559, 0xB1D0, 0x655C, 0xD976, 0x655D, 0xB1CD, + 0x655E, 0xB4AF, 0x6562, 0xB4B1, 0x6563, 0xB4B2, 0x6564, 0xD975, 0x6565, 0xD978, 0x6566, 0xB4B0, 0x6567, 0xD973, 0x6568, 0xD977, + 0x656A, 0xD974, 0x656C, 0xB771, 0x656F, 0xDDBC, 0x6572, 0xBA56, 0x6573, 0xE1F4, 0x6574, 0xBEE3, 0x6575, 0xBCC4, 0x6576, 0xE5BD, + 0x6577, 0xBCC5, 0x6578, 0xBCC6, 0x6579, 0xE5BF, 0x657A, 0xE5BE, 0x657B, 0xE5C0, 0x657C, 0xE9B1, 0x657F, 0xE9B0, 0x6580, 0xECEF, + 0x6581, 0xECEE, 0x6582, 0xC0C4, 0x6583, 0xC0C5, 0x6584, 0xF248, 0x6587, 0xA4E5, 0x658C, 0xD979, 0x6590, 0xB4B4, 0x6591, 0xB4B3, + 0x6592, 0xDDBD, 0x6594, 0xEFD8, 0x6595, 0xC4E3, 0x6596, 0xF7DE, 0x6597, 0xA4E6, 0x6599, 0xAEC6, 0x659B, 0xB1D8, 0x659C, 0xB1D7, + 0x659D, 0xD97A, 0x659E, 0xD97B, 0x659F, 0xB772, 0x65A0, 0xE1F5, 0x65A1, 0xBA57, 0x65A2, 0xE9B2, 0x65A4, 0xA4E7, 0x65A5, 0xA5B8, + 0x65A7, 0xA9F2, 0x65A8, 0xCCC2, 0x65AA, 0xCEE9, 0x65AB, 0xAC48, 0x65AC, 0xB1D9, 0x65AE, 0xD97C, 0x65AF, 0xB4B5, 0x65B0, 0xB773, + 0x65B2, 0xE5C1, 0x65B3, 0xE5C2, 0x65B6, 0xECF0, 0x65B7, 0xC25F, 0x65B8, 0xF8F0, 0x65B9, 0xA4E8, 0x65BB, 0xCCC3, 0x65BC, 0xA9F3, + 0x65BD, 0xAC49, 0x65BF, 0xCEEA, 0x65C1, 0xAEC7, 0x65C2, 0xD1D2, 0x65C3, 0xD1D0, 0x65C4, 0xD1D1, 0x65C5, 0xAEC8, 0x65C6, 0xD1CF, + 0x65CB, 0xB1DB, 0x65CC, 0xB1DC, 0x65CD, 0xD5A8, 0x65CE, 0xB1DD, 0x65CF, 0xB1DA, 0x65D0, 0xD97D, 0x65D2, 0xD97E, 0x65D3, 0xDDBE, + 0x65D6, 0xBA59, 0x65D7, 0xBA58, 0x65DA, 0xECF1, 0x65DB, 0xEFD9, 0x65DD, 0xF24A, 0x65DE, 0xF249, 0x65DF, 0xF44F, 0x65E1, 0xC95E, + 0x65E2, 0xAC4A, 0x65E5, 0xA4E9, 0x65E6, 0xA5B9, 0x65E8, 0xA6AE, 0x65E9, 0xA6AD, 0x65EC, 0xA6AF, 0x65ED, 0xA6B0, 0x65EE, 0xC9EE, + 0x65EF, 0xC9ED, 0x65F0, 0xCAF8, 0x65F1, 0xA7F2, 0x65F2, 0xCAFB, 0x65F3, 0xCAFA, 0x65F4, 0xCAF9, 0x65F5, 0xCAFC, 0x65FA, 0xA9F4, + 0x65FB, 0xCCC9, 0x65FC, 0xCCC5, 0x65FD, 0xCCCE, 0x6600, 0xA9FB, 0x6602, 0xA9F9, 0x6603, 0xCCCA, 0x6604, 0xCCC6, 0x6605, 0xCCCD, + 0x6606, 0xA9F8, 0x6607, 0xAA40, 0x6608, 0xCCC8, 0x6609, 0xCCC4, 0x660A, 0xA9FE, 0x660B, 0xCCCB, 0x660C, 0xA9F7, 0x660D, 0xCCCC, + 0x660E, 0xA9FA, 0x660F, 0xA9FC, 0x6610, 0xCCD0, 0x6611, 0xCCCF, 0x6612, 0xCCC7, 0x6613, 0xA9F6, 0x6614, 0xA9F5, 0x6615, 0xA9FD, + 0x661C, 0xCEEF, 0x661D, 0xCEF5, 0x661F, 0xAC50, 0x6620, 0xAC4D, 0x6621, 0xCEEC, 0x6622, 0xCEF1, 0x6624, 0xAC53, 0x6625, 0xAC4B, + 0x6626, 0xCEF0, 0x6627, 0xAC4E, 0x6628, 0xAC51, 0x662B, 0xCEF3, 0x662D, 0xAC4C, 0x662E, 0xCEF8, 0x662F, 0xAC4F, 0x6631, 0xAC52, + 0x6632, 0xCEED, 0x6633, 0xCEF2, 0x6634, 0xCEF6, 0x6635, 0xCEEE, 0x6636, 0xCEEB, 0x6639, 0xCEF7, 0x663A, 0xCEF4, 0x6641, 0xAED0, + 0x6642, 0xAEC9, 0x6643, 0xAECC, 0x6645, 0xAECF, 0x6647, 0xD1D5, 0x6649, 0xAECA, 0x664A, 0xD1D3, 0x664C, 0xAECE, 0x664F, 0xAECB, + 0x6651, 0xD1D6, 0x6652, 0xAECD, 0x6659, 0xD5AC, 0x665A, 0xB1DF, 0x665B, 0xD5AB, 0x665C, 0xD5AD, 0x665D, 0xB1DE, 0x665E, 0xB1E3, + 0x665F, 0xD1D4, 0x6661, 0xD5AA, 0x6662, 0xD5AE, 0x6664, 0xB1E0, 0x6665, 0xD5A9, 0x6666, 0xB1E2, 0x6668, 0xB1E1, 0x666A, 0xD9A7, + 0x666C, 0xD9A2, 0x666E, 0xB4B6, 0x666F, 0xB4BA, 0x6670, 0xB4B7, 0x6671, 0xD9A5, 0x6672, 0xD9A8, 0x6674, 0xB4B8, 0x6676, 0xB4B9, + 0x6677, 0xB4BE, 0x6678, 0xDDC7, 0x6679, 0xD9A6, 0x667A, 0xB4BC, 0x667B, 0xD9A3, 0x667C, 0xD9A1, 0x667E, 0xB4BD, 0x6680, 0xD9A4, + 0x6684, 0xB779, 0x6686, 0xDDBF, 0x6687, 0xB776, 0x6688, 0xB777, 0x6689, 0xB775, 0x668A, 0xDDC4, 0x668B, 0xDDC3, 0x668C, 0xDDC0, + 0x668D, 0xB77B, 0x6690, 0xDDC2, 0x6691, 0xB4BB, 0x6694, 0xDDC6, 0x6695, 0xDDC1, 0x6696, 0xB778, 0x6697, 0xB774, 0x6698, 0xB77A, + 0x6699, 0xDDC5, 0x669D, 0xBA5C, 0x669F, 0xE1F8, 0x66A0, 0xE1F7, 0x66A1, 0xE1F6, 0x66A2, 0xBA5A, 0x66A8, 0xBA5B, 0x66A9, 0xE5C5, + 0x66AA, 0xE5C8, 0x66AB, 0xBCC8, 0x66AE, 0xBCC7, 0x66AF, 0xE5C9, 0x66B0, 0xE5C4, 0x66B1, 0xBCCA, 0x66B2, 0xE5C6, 0x66B4, 0xBCC9, + 0x66B5, 0xE5C3, 0x66B7, 0xE5C7, 0x66B8, 0xBEE9, 0x66B9, 0xBEE6, 0x66BA, 0xE9BB, 0x66BB, 0xE9BA, 0x66BD, 0xE9B9, 0x66BE, 0xE9B4, + 0x66C0, 0xE9B5, 0x66C4, 0xBEE7, 0x66C6, 0xBEE4, 0x66C7, 0xBEE8, 0x66C8, 0xE9B3, 0x66C9, 0xBEE5, 0x66CA, 0xE9B6, 0x66CB, 0xE9B7, + 0x66CC, 0xE9BC, 0x66CF, 0xE9B8, 0x66D2, 0xECF2, 0x66D6, 0xC0C7, 0x66D8, 0xEFDC, 0x66D9, 0xC0C6, 0x66DA, 0xEFDA, 0x66DB, 0xEFDB, + 0x66DC, 0xC260, 0x66DD, 0xC36E, 0x66DE, 0xF24B, 0x66E0, 0xC36D, 0x66E3, 0xF451, 0x66E4, 0xF452, 0x66E6, 0xC466, 0x66E8, 0xF450, + 0x66E9, 0xC4E4, 0x66EB, 0xF7DF, 0x66EC, 0xC5CE, 0x66ED, 0xF8AA, 0x66EE, 0xF8AB, 0x66F0, 0xA4EA, 0x66F2, 0xA6B1, 0x66F3, 0xA6B2, + 0x66F4, 0xA7F3, 0x66F6, 0xCCD1, 0x66F7, 0xAC54, 0x66F8, 0xAED1, 0x66F9, 0xB1E4, 0x66FC, 0xB0D2, 0x66FE, 0xB4BF, 0x66FF, 0xB4C0, + 0x6700, 0xB3CC, 0x6701, 0xD9A9, 0x6703, 0xB77C, 0x6704, 0xE1FA, 0x6705, 0xE1F9, 0x6708, 0xA4EB, 0x6709, 0xA6B3, 0x670A, 0xCCD2, + 0x670B, 0xAA42, 0x670D, 0xAA41, 0x670F, 0xCEF9, 0x6710, 0xCEFA, 0x6712, 0xD1D7, 0x6713, 0xD1D8, 0x6714, 0xAED2, 0x6715, 0xAED3, + 0x6717, 0xAED4, 0x6718, 0xD5AF, 0x671B, 0xB1E6, 0x671D, 0xB4C2, 0x671F, 0xB4C1, 0x6720, 0xDDC8, 0x6721, 0xDF7A, 0x6722, 0xE1FB, + 0x6723, 0xE9BD, 0x6726, 0xC261, 0x6727, 0xC467, 0x6728, 0xA4EC, 0x672A, 0xA5BC, 0x672B, 0xA5BD, 0x672C, 0xA5BB, 0x672D, 0xA5BE, + 0x672E, 0xA5BA, 0x6731, 0xA6B6, 0x6733, 0xC9F6, 0x6734, 0xA6B5, 0x6735, 0xA6B7, 0x6738, 0xC9F1, 0x6739, 0xC9F0, 0x673A, 0xC9F3, + 0x673B, 0xC9F2, 0x673C, 0xC9F5, 0x673D, 0xA6B4, 0x673E, 0xC9EF, 0x673F, 0xC9F4, 0x6745, 0xCAFD, 0x6746, 0xA7FD, 0x6747, 0xCAFE, + 0x6748, 0xCB43, 0x6749, 0xA7FC, 0x674B, 0xCB47, 0x674C, 0xCB42, 0x674D, 0xCB45, 0x674E, 0xA7F5, 0x674F, 0xA7F6, 0x6750, 0xA7F7, + 0x6751, 0xA7F8, 0x6753, 0xA840, 0x6755, 0xCB41, 0x6756, 0xA7FA, 0x6757, 0xA841, 0x6759, 0xCB40, 0x675A, 0xCB46, 0x675C, 0xA7F9, + 0x675D, 0xCB44, 0x675E, 0xA7FB, 0x675F, 0xA7F4, 0x6760, 0xA7FE, 0x676A, 0xAA57, 0x676C, 0xCCD4, 0x676D, 0xAA43, 0x676F, 0xAA4D, + 0x6770, 0xAA4E, 0x6771, 0xAA46, 0x6772, 0xAA58, 0x6773, 0xAA48, 0x6774, 0xCCDC, 0x6775, 0xAA53, 0x6776, 0xCCD7, 0x6777, 0xAA49, + 0x6778, 0xCCE6, 0x6779, 0xCCE7, 0x677A, 0xCCDF, 0x677B, 0xCCD8, 0x677C, 0xAA56, 0x677D, 0xCCE4, 0x677E, 0xAA51, 0x677F, 0xAA4F, + 0x6781, 0xCCE5, 0x6783, 0xCCE3, 0x6784, 0xCCDB, 0x6785, 0xCCD3, 0x6786, 0xCCDA, 0x6787, 0xAA4A, 0x6789, 0xAA50, 0x678B, 0xAA44, + 0x678C, 0xCCDE, 0x678D, 0xCCDD, 0x678E, 0xCCD5, 0x6790, 0xAA52, 0x6791, 0xCCE1, 0x6792, 0xCCD6, 0x6793, 0xAA55, 0x6794, 0xCCE8, + 0x6795, 0xAA45, 0x6797, 0xAA4C, 0x6798, 0xCCD9, 0x6799, 0xCCE2, 0x679A, 0xAA54, 0x679C, 0xAA47, 0x679D, 0xAA4B, 0x679F, 0xCCE0, + 0x67AE, 0xCF5B, 0x67AF, 0xAC5C, 0x67B0, 0xAC69, 0x67B2, 0xCF56, 0x67B3, 0xCF4C, 0x67B4, 0xAC62, 0x67B5, 0xCF4A, 0x67B6, 0xAC5B, + 0x67B7, 0xCF45, 0x67B8, 0xAC65, 0x67B9, 0xCF52, 0x67BA, 0xCEFE, 0x67BB, 0xCF41, 0x67C0, 0xCF44, 0x67C1, 0xCEFB, 0x67C2, 0xCF51, + 0x67C3, 0xCF61, 0x67C4, 0xAC60, 0x67C5, 0xCF46, 0x67C6, 0xCF58, 0x67C8, 0xCEFD, 0x67C9, 0xCF5F, 0x67CA, 0xCF60, 0x67CB, 0xCF63, + 0x67CC, 0xCF5A, 0x67CD, 0xCF4B, 0x67CE, 0xCF53, 0x67CF, 0xAC66, 0x67D0, 0xAC59, 0x67D1, 0xAC61, 0x67D2, 0xAC6D, 0x67D3, 0xAC56, + 0x67D4, 0xAC58, 0x67D8, 0xCF43, 0x67D9, 0xAC6A, 0x67DA, 0xAC63, 0x67DB, 0xCF5D, 0x67DC, 0xCF40, 0x67DD, 0xAC6C, 0x67DE, 0xAC67, + 0x67DF, 0xCF49, 0x67E2, 0xAC6B, 0x67E3, 0xCF50, 0x67E4, 0xCF48, 0x67E5, 0xAC64, 0x67E6, 0xCF5C, 0x67E7, 0xCF54, 0x67E9, 0xAC5E, + 0x67EA, 0xCF62, 0x67EB, 0xCF47, 0x67EC, 0xAC5A, 0x67ED, 0xCF59, 0x67EE, 0xCF4F, 0x67EF, 0xAC5F, 0x67F0, 0xCF55, 0x67F1, 0xAC57, + 0x67F2, 0xCEFC, 0x67F3, 0xAC68, 0x67F4, 0xAEE3, 0x67F5, 0xAC5D, 0x67F6, 0xCF4E, 0x67F7, 0xCF4D, 0x67F8, 0xCF42, 0x67FA, 0xCF5E, + 0x67FC, 0xCF57, 0x67FF, 0xAC55, 0x6812, 0xD1EC, 0x6813, 0xAEEA, 0x6814, 0xD1ED, 0x6816, 0xD1E1, 0x6817, 0xAEDF, 0x6818, 0xAEEB, + 0x681A, 0xD1DA, 0x681C, 0xD1E3, 0x681D, 0xD1EB, 0x681F, 0xD1D9, 0x6820, 0xD1F4, 0x6821, 0xAED5, 0x6825, 0xD1F3, 0x6826, 0xD1EE, + 0x6828, 0xD1EF, 0x6829, 0xAEDD, 0x682A, 0xAEE8, 0x682B, 0xD1E5, 0x682D, 0xD1E6, 0x682E, 0xD1F0, 0x682F, 0xD1E7, 0x6831, 0xD1E2, + 0x6832, 0xD1DC, 0x6833, 0xD1DD, 0x6834, 0xD1EA, 0x6835, 0xD1E4, 0x6838, 0xAED6, 0x6839, 0xAEDA, 0x683A, 0xD1F2, 0x683B, 0xD1DE, + 0x683C, 0xAEE6, 0x683D, 0xAEE2, 0x6840, 0xAEE5, 0x6841, 0xAEEC, 0x6842, 0xAEDB, 0x6843, 0xAEE7, 0x6844, 0xD1E9, 0x6845, 0xAEE9, + 0x6846, 0xAED8, 0x6848, 0xAED7, 0x6849, 0xD1DB, 0x684B, 0xD1DF, 0x684C, 0xAEE0, 0x684D, 0xD1F1, 0x684E, 0xD1E8, 0x684F, 0xD1E0, + 0x6850, 0xAEE4, 0x6851, 0xAEE1, 0x6853, 0xAED9, 0x6854, 0xAEDC, 0x686B, 0xD5C4, 0x686D, 0xD5B4, 0x686E, 0xD5B5, 0x686F, 0xD5B9, + 0x6871, 0xD5C8, 0x6872, 0xD5C5, 0x6874, 0xD5BE, 0x6875, 0xD5BD, 0x6876, 0xB1ED, 0x6877, 0xD5C1, 0x6878, 0xD5D0, 0x6879, 0xD5B0, + 0x687B, 0xD5D1, 0x687C, 0xD5C3, 0x687D, 0xD5D5, 0x687E, 0xD5C9, 0x687F, 0xB1EC, 0x6880, 0xD5C7, 0x6881, 0xB1E7, 0x6882, 0xB1FC, + 0x6883, 0xB1F2, 0x6885, 0xB1F6, 0x6886, 0xB1F5, 0x6887, 0xD5B1, 0x6889, 0xD5CE, 0x688A, 0xD5D4, 0x688B, 0xD5CC, 0x688C, 0xD5D3, + 0x688F, 0xD5C0, 0x6890, 0xD5B2, 0x6891, 0xD5D2, 0x6892, 0xD5C2, 0x6893, 0xB1EA, 0x6894, 0xB1F7, 0x6896, 0xD5CB, 0x6897, 0xB1F0, + 0x689B, 0xD5CA, 0x689C, 0xD5B3, 0x689D, 0xB1F8, 0x689F, 0xB1FA, 0x68A0, 0xD5CD, 0x68A1, 0xB1FB, 0x68A2, 0xB1E9, 0x68A3, 0xD5BA, + 0x68A4, 0xD5CF, 0x68A7, 0xB1EF, 0x68A8, 0xB1F9, 0x68A9, 0xD5BC, 0x68AA, 0xD5C6, 0x68AB, 0xD5B7, 0x68AC, 0xD5BB, 0x68AD, 0xB1F4, + 0x68AE, 0xD5B6, 0x68AF, 0xB1E8, 0x68B0, 0xB1F1, 0x68B1, 0xB1EE, 0x68B2, 0xD5BF, 0x68B3, 0xAEDE, 0x68B4, 0xD9C0, 0x68B5, 0xB1EB, + 0x68C4, 0xB1F3, 0x68C6, 0xD9C3, 0x68C7, 0xD9D9, 0x68C8, 0xD9CE, 0x68C9, 0xB4D6, 0x68CB, 0xB4D1, 0x68CC, 0xD9BD, 0x68CD, 0xB4D2, + 0x68CE, 0xD9CD, 0x68D0, 0xD9C6, 0x68D1, 0xD9D3, 0x68D2, 0xB4CE, 0x68D3, 0xD9AB, 0x68D4, 0xD9D5, 0x68D5, 0xB4C4, 0x68D6, 0xD9B3, + 0x68D7, 0xB4C7, 0x68D8, 0xB4C6, 0x68DA, 0xB4D7, 0x68DC, 0xD9AD, 0x68DD, 0xD9CF, 0x68DE, 0xD9D0, 0x68DF, 0xB4C9, 0x68E0, 0xB4C5, + 0x68E1, 0xD9BB, 0x68E3, 0xB4D0, 0x68E4, 0xD9B6, 0x68E6, 0xD9D1, 0x68E7, 0xB4CC, 0x68E8, 0xD9C9, 0x68E9, 0xD9D6, 0x68EA, 0xD9B0, + 0x68EB, 0xD9B5, 0x68EC, 0xD9AF, 0x68EE, 0xB4CB, 0x68EF, 0xD9C2, 0x68F0, 0xDDDE, 0x68F1, 0xD9B1, 0x68F2, 0xB4CF, 0x68F3, 0xD9BA, + 0x68F4, 0xD9D2, 0x68F5, 0xB4CA, 0x68F6, 0xD9B7, 0x68F7, 0xD9B4, 0x68F8, 0xD9C5, 0x68F9, 0xB4CD, 0x68FA, 0xB4C3, 0x68FB, 0xB4D9, + 0x68FC, 0xD9C8, 0x68FD, 0xD9C7, 0x6904, 0xD9AC, 0x6905, 0xB4C8, 0x6906, 0xD9D4, 0x6907, 0xD9BC, 0x6908, 0xD9BE, 0x690A, 0xD9CB, + 0x690B, 0xD9CA, 0x690C, 0xD9AA, 0x690D, 0xB4D3, 0x690E, 0xB4D5, 0x690F, 0xD9B2, 0x6910, 0xD9B9, 0x6911, 0xD9C1, 0x6912, 0xB4D4, + 0x6913, 0xD9B8, 0x6914, 0xD9C4, 0x6915, 0xD9D7, 0x6917, 0xD9CC, 0x6925, 0xD9D8, 0x692A, 0xD9AE, 0x692F, 0xDDF2, 0x6930, 0xB7A6, + 0x6932, 0xDDF0, 0x6933, 0xDDDB, 0x6934, 0xDDE0, 0x6935, 0xDDD9, 0x6937, 0xDDEC, 0x6938, 0xDDCB, 0x6939, 0xDDD2, 0x693B, 0xDDEA, + 0x693C, 0xDDF4, 0x693D, 0xDDDC, 0x693F, 0xDDCF, 0x6940, 0xDDE2, 0x6941, 0xDDE7, 0x6942, 0xDDD3, 0x6944, 0xDDE4, 0x6945, 0xDDD0, + 0x6948, 0xDDD7, 0x6949, 0xDDD8, 0x694A, 0xB7A8, 0x694B, 0xDDEB, 0x694C, 0xDDE9, 0x694E, 0xDDCC, 0x694F, 0xDDEE, 0x6951, 0xDDEF, + 0x6952, 0xDDF1, 0x6953, 0xB7AC, 0x6954, 0xB7A4, 0x6956, 0xD5B8, 0x6957, 0xDDD4, 0x6958, 0xDDE6, 0x6959, 0xDDD5, 0x695A, 0xB7A1, + 0x695B, 0xB7B1, 0x695C, 0xDDED, 0x695D, 0xB7AF, 0x695E, 0xB7AB, 0x695F, 0xDDCA, 0x6960, 0xB7A3, 0x6962, 0xDDCD, 0x6963, 0xB7B0, + 0x6965, 0xDDDD, 0x6966, 0xDDC9, 0x6968, 0xB7A9, 0x6969, 0xDDE1, 0x696A, 0xDDD1, 0x696B, 0xB7AA, 0x696C, 0xDDDA, 0x696D, 0xB77E, + 0x696E, 0xB4D8, 0x696F, 0xDDE3, 0x6970, 0xD9BF, 0x6971, 0xDDCE, 0x6974, 0xDDE8, 0x6975, 0xB7A5, 0x6976, 0xDDE5, 0x6977, 0xB7A2, + 0x6978, 0xDDDF, 0x6979, 0xB7AD, 0x697A, 0xDDD6, 0x697B, 0xDDF3, 0x6982, 0xB7A7, 0x6983, 0xDEC6, 0x6986, 0xB7AE, 0x698D, 0xE24A, + 0x698E, 0xE248, 0x6990, 0xE25E, 0x6991, 0xE246, 0x6993, 0xE258, 0x6994, 0xB77D, 0x6995, 0xBA5F, 0x6996, 0xE242, 0x6997, 0xE25D, + 0x6999, 0xE247, 0x699A, 0xE255, 0x699B, 0xBA64, 0x699C, 0xBA5D, 0x699E, 0xE25B, 0x69A0, 0xE240, 0x69A1, 0xE25A, 0x69A3, 0xBA6F, + 0x69A4, 0xE251, 0x69A5, 0xE261, 0x69A6, 0xBA6D, 0x69A7, 0xE249, 0x69A8, 0xBA5E, 0x69A9, 0xE24B, 0x69AA, 0xE259, 0x69AB, 0xBA67, + 0x69AC, 0xE244, 0x69AD, 0xBA6B, 0x69AE, 0xBA61, 0x69AF, 0xE24D, 0x69B0, 0xE243, 0x69B1, 0xE1FC, 0x69B3, 0xE257, 0x69B4, 0xBA68, + 0x69B5, 0xE260, 0x69B6, 0xE1FD, 0x69B7, 0xBA65, 0x69B9, 0xE253, 0x69BB, 0xBA66, 0x69BC, 0xE245, 0x69BD, 0xE250, 0x69BE, 0xE24C, + 0x69BF, 0xE24E, 0x69C1, 0xBA60, 0x69C2, 0xE25F, 0x69C3, 0xBA6E, 0x69C4, 0xE24F, 0x69C6, 0xE262, 0x69C9, 0xE1FE, 0x69CA, 0xE254, + 0x69CB, 0xBA63, 0x69CC, 0xBA6C, 0x69CD, 0xBA6A, 0x69CE, 0xE241, 0x69CF, 0xE256, 0x69D0, 0xBA69, 0x69D3, 0xBA62, 0x69D4, 0xE252, + 0x69D9, 0xE25C, 0x69E2, 0xE5D5, 0x69E4, 0xE5D1, 0x69E5, 0xE5CD, 0x69E6, 0xE5E1, 0x69E7, 0xE5DE, 0x69E8, 0xBCCD, 0x69EB, 0xE5E5, + 0x69EC, 0xE5D4, 0x69ED, 0xBCD8, 0x69EE, 0xE5DB, 0x69F1, 0xE5D0, 0x69F2, 0xE5DA, 0x69F3, 0xBCD5, 0x69F4, 0xE5EE, 0x69F6, 0xE5EB, + 0x69F7, 0xE5DD, 0x69F8, 0xE5CE, 0x69FB, 0xE5E2, 0x69FC, 0xE5E4, 0x69FD, 0xBCD1, 0x69FE, 0xE5D8, 0x69FF, 0xE5D3, 0x6A00, 0xE5CA, + 0x6A01, 0xBCCE, 0x6A02, 0xBCD6, 0x6A04, 0xE5E7, 0x6A05, 0xBCD7, 0x6A06, 0xE5CB, 0x6A07, 0xE5ED, 0x6A08, 0xE5E0, 0x6A09, 0xE5E6, + 0x6A0A, 0xBCD4, 0x6A0D, 0xE5E3, 0x6A0F, 0xE5EA, 0x6A11, 0xBCD9, 0x6A13, 0xBCD3, 0x6A14, 0xE5DC, 0x6A15, 0xE5CF, 0x6A16, 0xE5EF, + 0x6A17, 0xE5CC, 0x6A18, 0xE5E8, 0x6A19, 0xBCD0, 0x6A1B, 0xE5D6, 0x6A1D, 0xE5D7, 0x6A1E, 0xBCCF, 0x6A1F, 0xBCCC, 0x6A20, 0xE5D2, + 0x6A21, 0xBCD2, 0x6A23, 0xBCCB, 0x6A25, 0xE5E9, 0x6A26, 0xE5EC, 0x6A27, 0xE5D9, 0x6A28, 0xE9CA, 0x6A32, 0xE9C2, 0x6A34, 0xE9BE, + 0x6A35, 0xBEF6, 0x6A38, 0xBEEB, 0x6A39, 0xBEF0, 0x6A3A, 0xBEEC, 0x6A3B, 0xE9CC, 0x6A3C, 0xE9D7, 0x6A3D, 0xBEEA, 0x6A3E, 0xE9C4, + 0x6A3F, 0xE9CD, 0x6A40, 0xE5DF, 0x6A41, 0xE9CE, 0x6A44, 0xBEF1, 0x6A46, 0xE9DD, 0x6A47, 0xBEF5, 0x6A48, 0xBEF8, 0x6A49, 0xE9C0, + 0x6A4B, 0xBEF4, 0x6A4D, 0xE9DB, 0x6A4E, 0xE9DC, 0x6A4F, 0xE9D2, 0x6A50, 0xE9D1, 0x6A51, 0xE9C9, 0x6A54, 0xE9D3, 0x6A55, 0xE9DA, + 0x6A56, 0xE9D9, 0x6A58, 0xBEEF, 0x6A59, 0xBEED, 0x6A5A, 0xE9CB, 0x6A5B, 0xE9C8, 0x6A5D, 0xE9C5, 0x6A5E, 0xE9D8, 0x6A5F, 0xBEF7, + 0x6A60, 0xE9D6, 0x6A61, 0xBEF3, 0x6A62, 0xBEF2, 0x6A64, 0xE9D0, 0x6A66, 0xE9BF, 0x6A67, 0xE9C1, 0x6A68, 0xE9C3, 0x6A69, 0xE9D5, + 0x6A6A, 0xE9CF, 0x6A6B, 0xBEEE, 0x6A6D, 0xE9C6, 0x6A6F, 0xE9D4, 0x6A76, 0xE9C7, 0x6A7E, 0xC0CF, 0x6A7F, 0xED45, 0x6A80, 0xC0C8, + 0x6A81, 0xECF5, 0x6A83, 0xED41, 0x6A84, 0xC0CA, 0x6A85, 0xED48, 0x6A87, 0xECFC, 0x6A89, 0xECF7, 0x6A8C, 0xED49, 0x6A8D, 0xECF3, + 0x6A8E, 0xECFE, 0x6A90, 0xC0D1, 0x6A91, 0xED44, 0x6A92, 0xED4A, 0x6A93, 0xECFD, 0x6A94, 0xC0C9, 0x6A95, 0xED40, 0x6A96, 0xECF4, + 0x6A97, 0xC0D0, 0x6A9A, 0xED47, 0x6A9B, 0xECF9, 0x6A9C, 0xC0CC, 0x6A9E, 0xECFB, 0x6A9F, 0xECF8, 0x6AA0, 0xC0D2, 0x6AA1, 0xECFA, + 0x6AA2, 0xC0CB, 0x6AA3, 0xC0CE, 0x6AA4, 0xED43, 0x6AA5, 0xECF6, 0x6AA6, 0xED46, 0x6AA8, 0xED42, 0x6AAC, 0xC263, 0x6AAD, 0xEFE7, + 0x6AAE, 0xC268, 0x6AAF, 0xC269, 0x6AB3, 0xC262, 0x6AB4, 0xEFE6, 0x6AB6, 0xEFE3, 0x6AB7, 0xEFE4, 0x6AB8, 0xC266, 0x6AB9, 0xEFDE, + 0x6ABA, 0xEFE2, 0x6ABB, 0xC265, 0x6ABD, 0xEFDF, 0x6AC2, 0xC267, 0x6AC3, 0xC264, 0x6AC5, 0xEFDD, 0x6AC6, 0xEFE1, 0x6AC7, 0xEFE5, + 0x6ACB, 0xF251, 0x6ACC, 0xF24E, 0x6ACD, 0xF257, 0x6ACF, 0xF256, 0x6AD0, 0xF254, 0x6AD1, 0xF24F, 0x6AD3, 0xC372, 0x6AD9, 0xF250, + 0x6ADA, 0xC371, 0x6ADB, 0xC0CD, 0x6ADC, 0xF253, 0x6ADD, 0xC370, 0x6ADE, 0xF258, 0x6ADF, 0xF252, 0x6AE0, 0xF24D, 0x6AE1, 0xEFE0, + 0x6AE5, 0xC36F, 0x6AE7, 0xF24C, 0x6AE8, 0xF456, 0x6AEA, 0xF455, 0x6AEB, 0xF255, 0x6AEC, 0xC468, 0x6AEE, 0xF459, 0x6AEF, 0xF45A, + 0x6AF0, 0xF454, 0x6AF1, 0xF458, 0x6AF3, 0xF453, 0x6AF8, 0xF5D1, 0x6AF9, 0xF457, 0x6AFA, 0xC4E7, 0x6AFB, 0xC4E5, 0x6AFC, 0xF5CF, + 0x6B00, 0xF5D2, 0x6B02, 0xF5CE, 0x6B03, 0xF5D0, 0x6B04, 0xC4E6, 0x6B08, 0xF6E5, 0x6B09, 0xF6E6, 0x6B0A, 0xC576, 0x6B0B, 0xF6E4, + 0x6B0F, 0xF7E2, 0x6B10, 0xC5CF, 0x6B11, 0xF7E0, 0x6B12, 0xF7E1, 0x6B13, 0xF8AC, 0x6B16, 0xC656, 0x6B17, 0xF8F3, 0x6B18, 0xF8F1, + 0x6B19, 0xF8F2, 0x6B1A, 0xF8F4, 0x6B1E, 0xF9BB, 0x6B20, 0xA4ED, 0x6B21, 0xA6B8, 0x6B23, 0xAA59, 0x6B25, 0xCCE9, 0x6B28, 0xCF64, + 0x6B2C, 0xD1F5, 0x6B2D, 0xD1F7, 0x6B2F, 0xD1F6, 0x6B31, 0xD1F8, 0x6B32, 0xB1FD, 0x6B33, 0xD5D7, 0x6B34, 0xD1F9, 0x6B36, 0xD5D6, + 0x6B37, 0xD5D8, 0x6B38, 0xD5D9, 0x6B39, 0xD9DA, 0x6B3A, 0xB4DB, 0x6B3B, 0xD9DB, 0x6B3C, 0xD9DD, 0x6B3D, 0xB4DC, 0x6B3E, 0xB4DA, + 0x6B3F, 0xD9DC, 0x6B41, 0xDDFA, 0x6B42, 0xDDF8, 0x6B43, 0xDDF7, 0x6B45, 0xDDF6, 0x6B46, 0xDDF5, 0x6B47, 0xB7B2, 0x6B48, 0xDDF9, + 0x6B49, 0xBA70, 0x6B4A, 0xE263, 0x6B4B, 0xE265, 0x6B4C, 0xBA71, 0x6B4D, 0xE264, 0x6B4E, 0xBCDB, 0x6B50, 0xBCDA, 0x6B51, 0xE5F0, + 0x6B54, 0xE9DF, 0x6B55, 0xE9DE, 0x6B56, 0xE9E0, 0x6B59, 0xBEF9, 0x6B5B, 0xED4B, 0x6B5C, 0xC0D3, 0x6B5E, 0xEFE8, 0x6B5F, 0xC26A, + 0x6B60, 0xF259, 0x6B61, 0xC577, 0x6B62, 0xA4EE, 0x6B63, 0xA5BF, 0x6B64, 0xA6B9, 0x6B65, 0xA842, 0x6B66, 0xAA5A, 0x6B67, 0xAA5B, + 0x6B6A, 0xAC6E, 0x6B6D, 0xD1FA, 0x6B72, 0xB7B3, 0x6B76, 0xE6D1, 0x6B77, 0xBEFA, 0x6B78, 0xC26B, 0x6B79, 0xA4EF, 0x6B7B, 0xA6BA, + 0x6B7E, 0xCCEB, 0x6B7F, 0xAA5C, 0x6B80, 0xCCEA, 0x6B82, 0xCF65, 0x6B83, 0xAC6F, 0x6B84, 0xCF66, 0x6B86, 0xAC70, 0x6B88, 0xD1FC, + 0x6B89, 0xAEEE, 0x6B8A, 0xAEED, 0x6B8C, 0xD5DE, 0x6B8D, 0xD5DC, 0x6B8E, 0xD5DD, 0x6B8F, 0xD5DB, 0x6B91, 0xD5DA, 0x6B94, 0xD9DE, + 0x6B95, 0xD9E1, 0x6B96, 0xB4DE, 0x6B97, 0xD9DF, 0x6B98, 0xB4DD, 0x6B99, 0xD9E0, 0x6B9B, 0xDDFB, 0x6B9E, 0xE266, 0x6B9F, 0xE267, + 0x6BA0, 0xE268, 0x6BA2, 0xE5F3, 0x6BA3, 0xE5F2, 0x6BA4, 0xBCDC, 0x6BA5, 0xE5F1, 0x6BA6, 0xE5F4, 0x6BA7, 0xE9E1, 0x6BAA, 0xE9E2, + 0x6BAB, 0xE9E3, 0x6BAD, 0xED4C, 0x6BAE, 0xC0D4, 0x6BAF, 0xC26C, 0x6BB0, 0xF25A, 0x6BB2, 0xC4E8, 0x6BB3, 0xC95F, 0x6BB5, 0xAC71, + 0x6BB6, 0xCF67, 0x6BB7, 0xAEEF, 0x6BBA, 0xB1FE, 0x6BBC, 0xB4DF, 0x6BBD, 0xD9E2, 0x6BBF, 0xB7B5, 0x6BC0, 0xB7B4, 0x6BC3, 0xE269, + 0x6BC4, 0xE26A, 0x6BC5, 0xBCDD, 0x6BC6, 0xBCDE, 0x6BC7, 0xE9E5, 0x6BC8, 0xE9E4, 0x6BC9, 0xEFE9, 0x6BCA, 0xF7E3, 0x6BCB, 0xA4F0, + 0x6BCC, 0xC960, 0x6BCD, 0xA5C0, 0x6BCF, 0xA843, 0x6BD0, 0xCB48, 0x6BD2, 0xAC72, 0x6BD3, 0xB7B6, 0x6BD4, 0xA4F1, 0x6BD6, 0xCF68, + 0x6BD7, 0xAC73, 0x6BD8, 0xCF69, 0x6BDA, 0xC0D5, 0x6BDB, 0xA4F2, 0x6BDE, 0xCCEC, 0x6BE0, 0xCF6A, 0x6BE2, 0xD242, 0x6BE3, 0xD241, + 0x6BE4, 0xD1FE, 0x6BE6, 0xD1FD, 0x6BE7, 0xD243, 0x6BE8, 0xD240, 0x6BEB, 0xB240, 0x6BEC, 0xB241, 0x6BEF, 0xB4E0, 0x6BF0, 0xD9E3, + 0x6BF2, 0xD9E4, 0x6BF3, 0xD9E5, 0x6BF7, 0xDE41, 0x6BF8, 0xDE42, 0x6BF9, 0xDE40, 0x6BFB, 0xDDFD, 0x6BFC, 0xDDFE, 0x6BFD, 0xB7B7, + 0x6BFE, 0xE26B, 0x6BFF, 0xE5F7, 0x6C00, 0xE5F6, 0x6C01, 0xE5F5, 0x6C02, 0xE5F8, 0x6C03, 0xE9E7, 0x6C04, 0xE9E6, 0x6C05, 0xBEFB, + 0x6C06, 0xE9E8, 0x6C08, 0xC0D6, 0x6C09, 0xED4D, 0x6C0B, 0xEFEA, 0x6C0C, 0xF25B, 0x6C0D, 0xF6E7, 0x6C0F, 0xA4F3, 0x6C10, 0xA5C2, + 0x6C11, 0xA5C1, 0x6C13, 0xAA5D, 0x6C14, 0xC961, 0x6C15, 0xC97E, 0x6C16, 0xA6BB, 0x6C18, 0xC9F7, 0x6C19, 0xCB49, 0x6C1A, 0xCB4A, + 0x6C1B, 0xAA5E, 0x6C1D, 0xCCED, 0x6C1F, 0xAC74, 0x6C20, 0xCF6B, 0x6C21, 0xCF6C, 0x6C23, 0xAEF0, 0x6C24, 0xAEF4, 0x6C25, 0xD244, + 0x6C26, 0xAEF3, 0x6C27, 0xAEF1, 0x6C28, 0xAEF2, 0x6C2A, 0xD5DF, 0x6C2B, 0xB242, 0x6C2C, 0xB4E3, 0x6C2E, 0xB4E1, 0x6C2F, 0xB4E2, + 0x6C30, 0xD9E6, 0x6C33, 0xBA72, 0x6C34, 0xA4F4, 0x6C36, 0xC9A1, 0x6C38, 0xA5C3, 0x6C3B, 0xC9A4, 0x6C3E, 0xA5C6, 0x6C3F, 0xC9A3, + 0x6C40, 0xA5C5, 0x6C41, 0xA5C4, 0x6C42, 0xA844, 0x6C43, 0xC9A2, 0x6C46, 0xC9F8, 0x6C4A, 0xC9FC, 0x6C4B, 0xC9FE, 0x6C4C, 0xCA40, + 0x6C4D, 0xA6C5, 0x6C4E, 0xA6C6, 0x6C4F, 0xC9FB, 0x6C50, 0xA6C1, 0x6C52, 0xC9F9, 0x6C54, 0xC9FD, 0x6C55, 0xA6C2, 0x6C57, 0xA6BD, + 0x6C59, 0xA6BE, 0x6C5B, 0xA6C4, 0x6C5C, 0xC9FA, 0x6C5D, 0xA6BC, 0x6C5E, 0xA845, 0x6C5F, 0xA6BF, 0x6C60, 0xA6C0, 0x6C61, 0xA6C3, + 0x6C65, 0xCB5B, 0x6C66, 0xCB59, 0x6C67, 0xCB4C, 0x6C68, 0xA851, 0x6C69, 0xCB53, 0x6C6A, 0xA84C, 0x6C6B, 0xCB4D, 0x6C6D, 0xCB55, + 0x6C6F, 0xCB52, 0x6C70, 0xA84F, 0x6C71, 0xCB51, 0x6C72, 0xA856, 0x6C73, 0xCB5A, 0x6C74, 0xA858, 0x6C76, 0xA85A, 0x6C78, 0xCB4B, + 0x6C7A, 0xA84D, 0x6C7B, 0xCB5C, 0x6C7D, 0xA854, 0x6C7E, 0xA857, 0x6C80, 0xCD45, 0x6C81, 0xA847, 0x6C82, 0xA85E, 0x6C83, 0xA855, + 0x6C84, 0xCB4E, 0x6C85, 0xA84A, 0x6C86, 0xA859, 0x6C87, 0xCB56, 0x6C88, 0xA848, 0x6C89, 0xA849, 0x6C8A, 0xCD43, 0x6C8B, 0xCB4F, + 0x6C8C, 0xA850, 0x6C8D, 0xA85B, 0x6C8E, 0xCB5D, 0x6C8F, 0xCB50, 0x6C90, 0xA84E, 0x6C92, 0xA853, 0x6C93, 0xCCEE, 0x6C94, 0xA85C, + 0x6C95, 0xCB57, 0x6C96, 0xA852, 0x6C98, 0xA85D, 0x6C99, 0xA846, 0x6C9A, 0xCB54, 0x6C9B, 0xA84B, 0x6C9C, 0xCB58, 0x6C9D, 0xCD44, + 0x6CAB, 0xAA6A, 0x6CAC, 0xAA7A, 0x6CAD, 0xCCF5, 0x6CAE, 0xAA71, 0x6CB0, 0xCD4B, 0x6CB1, 0xAA62, 0x6CB3, 0xAA65, 0x6CB4, 0xCD42, + 0x6CB6, 0xCCF3, 0x6CB7, 0xCCF7, 0x6CB8, 0xAA6D, 0x6CB9, 0xAA6F, 0x6CBA, 0xCCFA, 0x6CBB, 0xAA76, 0x6CBC, 0xAA68, 0x6CBD, 0xAA66, + 0x6CBE, 0xAA67, 0x6CBF, 0xAA75, 0x6CC0, 0xCD47, 0x6CC1, 0xAA70, 0x6CC2, 0xCCF9, 0x6CC3, 0xCCFB, 0x6CC4, 0xAA6E, 0x6CC5, 0xAA73, + 0x6CC6, 0xCCFC, 0x6CC7, 0xCD4A, 0x6CC9, 0xAC75, 0x6CCA, 0xAA79, 0x6CCC, 0xAA63, 0x6CCD, 0xCD49, 0x6CCF, 0xCD4D, 0x6CD0, 0xCCF8, + 0x6CD1, 0xCD4F, 0x6CD2, 0xCD40, 0x6CD3, 0xAA6C, 0x6CD4, 0xCCF4, 0x6CD5, 0xAA6B, 0x6CD6, 0xAA7D, 0x6CD7, 0xAA72, 0x6CD9, 0xCCF2, + 0x6CDA, 0xCF75, 0x6CDB, 0xAA78, 0x6CDC, 0xAA7C, 0x6CDD, 0xCD41, 0x6CDE, 0xCD46, 0x6CE0, 0xAA7E, 0x6CE1, 0xAA77, 0x6CE2, 0xAA69, + 0x6CE3, 0xAA5F, 0x6CE5, 0xAA64, 0x6CE7, 0xCCF6, 0x6CE8, 0xAA60, 0x6CE9, 0xCD4E, 0x6CEB, 0xCCF0, 0x6CEC, 0xCCEF, 0x6CED, 0xCCFD, + 0x6CEE, 0xCCF1, 0x6CEF, 0xAA7B, 0x6CF0, 0xAEF5, 0x6CF1, 0xAA74, 0x6CF2, 0xCCFE, 0x6CF3, 0xAA61, 0x6CF5, 0xACA6, 0x6CF9, 0xCD4C, + 0x6D00, 0xCF7C, 0x6D01, 0xCFA1, 0x6D03, 0xCFA4, 0x6D04, 0xCF77, 0x6D07, 0xCFA7, 0x6D08, 0xCFAA, 0x6D09, 0xCFAC, 0x6D0A, 0xCF74, + 0x6D0B, 0xAC76, 0x6D0C, 0xAC7B, 0x6D0D, 0xD249, 0x6D0E, 0xACAD, 0x6D0F, 0xCFA5, 0x6D10, 0xCFAD, 0x6D11, 0xCF7B, 0x6D12, 0xCF73, + 0x6D16, 0xD264, 0x6D17, 0xAC7E, 0x6D18, 0xCFA2, 0x6D19, 0xCF78, 0x6D1A, 0xCF7A, 0x6D1B, 0xACA5, 0x6D1D, 0xCF7D, 0x6D1E, 0xAC7D, + 0x6D1F, 0xCF70, 0x6D20, 0xCFA8, 0x6D22, 0xCFAB, 0x6D25, 0xAC7A, 0x6D27, 0xACA8, 0x6D28, 0xCF6D, 0x6D29, 0xACAA, 0x6D2A, 0xAC78, + 0x6D2B, 0xACAE, 0x6D2C, 0xCFA9, 0x6D2D, 0xCF6F, 0x6D2E, 0xACAB, 0x6D2F, 0xD25E, 0x6D30, 0xCD48, 0x6D31, 0xAC7C, 0x6D32, 0xAC77, + 0x6D33, 0xCF76, 0x6D34, 0xCF6E, 0x6D35, 0xACAC, 0x6D36, 0xACA4, 0x6D37, 0xCFA3, 0x6D38, 0xACA9, 0x6D39, 0xACA7, 0x6D3A, 0xCF79, + 0x6D3B, 0xACA1, 0x6D3C, 0xCF71, 0x6D3D, 0xACA2, 0x6D3E, 0xACA3, 0x6D3F, 0xCF72, 0x6D40, 0xCFA6, 0x6D41, 0xAC79, 0x6D42, 0xCF7E, + 0x6D58, 0xD24C, 0x6D59, 0xAEFD, 0x6D5A, 0xAF43, 0x6D5E, 0xD255, 0x6D5F, 0xD25B, 0x6D60, 0xD257, 0x6D61, 0xD24A, 0x6D62, 0xD24D, + 0x6D63, 0xD246, 0x6D64, 0xD247, 0x6D65, 0xAF4A, 0x6D66, 0xAEFA, 0x6D67, 0xD256, 0x6D68, 0xD25F, 0x6D69, 0xAF45, 0x6D6A, 0xAEF6, + 0x6D6C, 0xAF40, 0x6D6D, 0xD24E, 0x6D6E, 0xAF42, 0x6D6F, 0xD24F, 0x6D70, 0xD259, 0x6D74, 0xAF44, 0x6D75, 0xD268, 0x6D76, 0xD248, + 0x6D77, 0xAEFC, 0x6D78, 0xAEFB, 0x6D79, 0xAF48, 0x6D7A, 0xD245, 0x6D7B, 0xD266, 0x6D7C, 0xD25A, 0x6D7D, 0xD267, 0x6D7E, 0xD261, + 0x6D7F, 0xD253, 0x6D80, 0xD262, 0x6D82, 0xD25C, 0x6D83, 0xD265, 0x6D84, 0xD263, 0x6D85, 0xAF49, 0x6D86, 0xD254, 0x6D87, 0xAEF9, + 0x6D88, 0xAEF8, 0x6D89, 0xAF41, 0x6D8A, 0xAF47, 0x6D8B, 0xD260, 0x6D8C, 0xAF46, 0x6D8D, 0xD251, 0x6D8E, 0xB243, 0x6D90, 0xD269, + 0x6D91, 0xD250, 0x6D92, 0xD24B, 0x6D93, 0xAEFE, 0x6D94, 0xAF4B, 0x6D95, 0xAEF7, 0x6D97, 0xD258, 0x6D98, 0xD25D, 0x6DAA, 0xB265, + 0x6DAB, 0xD5E1, 0x6DAC, 0xD5E5, 0x6DAE, 0xB252, 0x6DAF, 0xB250, 0x6DB2, 0xB247, 0x6DB3, 0xD5E3, 0x6DB4, 0xD5E2, 0x6DB5, 0xB25B, + 0x6DB7, 0xD5E8, 0x6DB8, 0xB255, 0x6DBA, 0xD5FA, 0x6DBB, 0xD647, 0x6DBC, 0xB244, 0x6DBD, 0xD5F7, 0x6DBE, 0xD5F0, 0x6DBF, 0xB267, + 0x6DC0, 0xD5E0, 0x6DC2, 0xD5FC, 0x6DC4, 0xB264, 0x6DC5, 0xB258, 0x6DC6, 0xB263, 0x6DC7, 0xB24E, 0x6DC8, 0xD5EC, 0x6DC9, 0xD5FE, + 0x6DCA, 0xD5F6, 0x6DCB, 0xB24F, 0x6DCC, 0xB249, 0x6DCD, 0xD645, 0x6DCF, 0xD5FD, 0x6DD0, 0xD640, 0x6DD1, 0xB251, 0x6DD2, 0xB259, + 0x6DD3, 0xD642, 0x6DD4, 0xD5EA, 0x6DD5, 0xD5FB, 0x6DD6, 0xD5EF, 0x6DD7, 0xD644, 0x6DD8, 0xB25E, 0x6DD9, 0xB246, 0x6DDA, 0xB25C, + 0x6DDB, 0xD5F4, 0x6DDC, 0xD5F2, 0x6DDD, 0xD5F3, 0x6DDE, 0xB253, 0x6DDF, 0xD5EE, 0x6DE0, 0xD5ED, 0x6DE1, 0xB248, 0x6DE2, 0xD5E7, + 0x6DE3, 0xD646, 0x6DE4, 0xB24A, 0x6DE5, 0xD5F1, 0x6DE6, 0xB268, 0x6DE8, 0xB262, 0x6DE9, 0xD5E6, 0x6DEA, 0xB25F, 0x6DEB, 0xB25D, + 0x6DEC, 0xB266, 0x6DED, 0xD5F8, 0x6DEE, 0xB261, 0x6DEF, 0xD252, 0x6DF0, 0xD5F9, 0x6DF1, 0xB260, 0x6DF2, 0xD641, 0x6DF3, 0xB245, + 0x6DF4, 0xD5F5, 0x6DF5, 0xB257, 0x6DF6, 0xD5E9, 0x6DF7, 0xB256, 0x6DF9, 0xB254, 0x6DFA, 0xB24C, 0x6DFB, 0xB24B, 0x6DFC, 0xD9E7, + 0x6DFD, 0xD643, 0x6E00, 0xD5EB, 0x6E03, 0xD9FC, 0x6E05, 0xB24D, 0x6E19, 0xB541, 0x6E1A, 0xB25A, 0x6E1B, 0xB4EE, 0x6E1C, 0xD9F6, + 0x6E1D, 0xB4FC, 0x6E1F, 0xD9EA, 0x6E20, 0xB4EB, 0x6E21, 0xB4E7, 0x6E22, 0xDA49, 0x6E23, 0xB4ED, 0x6E24, 0xB4F1, 0x6E25, 0xB4EC, + 0x6E26, 0xB4F5, 0x6E27, 0xDA4D, 0x6E28, 0xDA44, 0x6E2B, 0xD9F1, 0x6E2C, 0xB4FA, 0x6E2D, 0xB4F4, 0x6E2E, 0xD9FD, 0x6E2F, 0xB4E4, + 0x6E30, 0xDA4A, 0x6E31, 0xDA43, 0x6E32, 0xB4E8, 0x6E33, 0xD9F7, 0x6E34, 0xB4F7, 0x6E35, 0xDA55, 0x6E36, 0xDA56, 0x6E38, 0xB4E5, + 0x6E39, 0xDA48, 0x6E3A, 0xB4F9, 0x6E3B, 0xD9FB, 0x6E3C, 0xD9ED, 0x6E3D, 0xD9EE, 0x6E3E, 0xB4FD, 0x6E3F, 0xD9F2, 0x6E40, 0xD9F9, + 0x6E41, 0xD9F3, 0x6E43, 0xB4FB, 0x6E44, 0xB544, 0x6E45, 0xD9EF, 0x6E46, 0xD9E8, 0x6E47, 0xD9E9, 0x6E49, 0xD9EB, 0x6E4A, 0xB4EA, + 0x6E4B, 0xD9F8, 0x6E4D, 0xB4F8, 0x6E4E, 0xB542, 0x6E51, 0xD9FA, 0x6E52, 0xDA53, 0x6E53, 0xDA4B, 0x6E54, 0xB4E6, 0x6E55, 0xDA51, + 0x6E56, 0xB4F2, 0x6E58, 0xB4F0, 0x6E5A, 0xDA57, 0x6E5B, 0xB4EF, 0x6E5C, 0xDA41, 0x6E5D, 0xD9F4, 0x6E5E, 0xD9FE, 0x6E5F, 0xB547, + 0x6E60, 0xDA45, 0x6E61, 0xDA42, 0x6E62, 0xD9F0, 0x6E63, 0xB543, 0x6E64, 0xDA4F, 0x6E65, 0xDA4C, 0x6E66, 0xDA54, 0x6E67, 0xB4E9, + 0x6E68, 0xDA40, 0x6E69, 0xB546, 0x6E6B, 0xDA47, 0x6E6E, 0xB4F3, 0x6E6F, 0xB4F6, 0x6E71, 0xDA46, 0x6E72, 0xB545, 0x6E73, 0xD9F5, + 0x6E74, 0xD5E4, 0x6E77, 0xDA50, 0x6E78, 0xDA4E, 0x6E79, 0xDA52, 0x6E88, 0xD9EC, 0x6E89, 0xB540, 0x6E8D, 0xDE61, 0x6E8E, 0xDE60, + 0x6E8F, 0xDE46, 0x6E90, 0xB7BD, 0x6E92, 0xDE5F, 0x6E93, 0xDE49, 0x6E94, 0xDE4A, 0x6E96, 0xB7C7, 0x6E97, 0xDE68, 0x6E98, 0xB7C2, + 0x6E99, 0xDE5E, 0x6E9B, 0xDE43, 0x6E9C, 0xB7C8, 0x6E9D, 0xB7BE, 0x6E9E, 0xDE52, 0x6E9F, 0xDE48, 0x6EA0, 0xDE4B, 0x6EA1, 0xDE63, + 0x6EA2, 0xB7B8, 0x6EA3, 0xDE6A, 0x6EA4, 0xDE62, 0x6EA5, 0xB7C1, 0x6EA6, 0xDE57, 0x6EA7, 0xB7CC, 0x6EAA, 0xB7CB, 0x6EAB, 0xB7C5, + 0x6EAE, 0xDE69, 0x6EAF, 0xB7B9, 0x6EB0, 0xDE55, 0x6EB1, 0xDE4C, 0x6EB2, 0xDE59, 0x6EB3, 0xDE65, 0x6EB4, 0xB7CD, 0x6EB6, 0xB7BB, + 0x6EB7, 0xDE54, 0x6EB9, 0xDE4D, 0x6EBA, 0xB7C4, 0x6EBC, 0xB7C3, 0x6EBD, 0xDE50, 0x6EBE, 0xDE5A, 0x6EBF, 0xDE64, 0x6EC0, 0xDE47, + 0x6EC1, 0xDE51, 0x6EC2, 0xB7BC, 0x6EC3, 0xDE5B, 0x6EC4, 0xB7C9, 0x6EC5, 0xB7C0, 0x6EC6, 0xDE4E, 0x6EC7, 0xB7BF, 0x6EC8, 0xDE45, + 0x6EC9, 0xDE53, 0x6ECA, 0xDE67, 0x6ECB, 0xB4FE, 0x6ECC, 0xBAB0, 0x6ECD, 0xDE56, 0x6ECE, 0xE26C, 0x6ECF, 0xDE58, 0x6ED0, 0xDE66, + 0x6ED1, 0xB7C6, 0x6ED2, 0xDE4F, 0x6ED3, 0xB7BA, 0x6ED4, 0xB7CA, 0x6ED5, 0xBCF0, 0x6ED6, 0xDE44, 0x6ED8, 0xDE5D, 0x6EDC, 0xDE5C, + 0x6EEB, 0xE2AA, 0x6EEC, 0xBAAD, 0x6EED, 0xE27D, 0x6EEE, 0xE2A4, 0x6EEF, 0xBAA2, 0x6EF1, 0xE26E, 0x6EF2, 0xBAAF, 0x6EF4, 0xBA77, + 0x6EF5, 0xE26D, 0x6EF6, 0xE2B0, 0x6EF7, 0xBAB1, 0x6EF8, 0xE271, 0x6EF9, 0xE2A3, 0x6EFB, 0xE273, 0x6EFC, 0xE2B3, 0x6EFD, 0xE2AF, + 0x6EFE, 0xBA75, 0x6EFF, 0xBAA1, 0x6F00, 0xE653, 0x6F01, 0xBAAE, 0x6F02, 0xBA7D, 0x6F03, 0xE26F, 0x6F05, 0xE2AE, 0x6F06, 0xBAA3, + 0x6F07, 0xE2AB, 0x6F08, 0xE2B8, 0x6F09, 0xE275, 0x6F0A, 0xE27E, 0x6F0D, 0xE2B6, 0x6F0E, 0xE2AC, 0x6F0F, 0xBA7C, 0x6F12, 0xE27C, + 0x6F13, 0xBA76, 0x6F14, 0xBA74, 0x6F15, 0xBAA8, 0x6F18, 0xE27A, 0x6F19, 0xE277, 0x6F1A, 0xE278, 0x6F1C, 0xE2B2, 0x6F1E, 0xE2B7, + 0x6F1F, 0xE2B5, 0x6F20, 0xBA7A, 0x6F21, 0xE2B9, 0x6F22, 0xBA7E, 0x6F23, 0xBAA7, 0x6F25, 0xE270, 0x6F26, 0xE5FA, 0x6F27, 0xE279, + 0x6F29, 0xBA78, 0x6F2A, 0xBAAC, 0x6F2B, 0xBAA9, 0x6F2C, 0xBA7B, 0x6F2D, 0xE2A5, 0x6F2E, 0xE274, 0x6F2F, 0xBAAA, 0x6F30, 0xE2A7, + 0x6F31, 0xBAA4, 0x6F32, 0xBAA6, 0x6F33, 0xBA73, 0x6F35, 0xE2A9, 0x6F36, 0xE2A1, 0x6F37, 0xE272, 0x6F38, 0xBAA5, 0x6F39, 0xE2B1, + 0x6F3A, 0xE2B4, 0x6F3B, 0xE27B, 0x6F3C, 0xE2A8, 0x6F3E, 0xBA79, 0x6F3F, 0xBCDF, 0x6F40, 0xE2A6, 0x6F41, 0xE5F9, 0x6F43, 0xE2AD, + 0x6F4E, 0xE276, 0x6F4F, 0xE644, 0x6F50, 0xE64E, 0x6F51, 0xBCE2, 0x6F52, 0xE64D, 0x6F53, 0xE659, 0x6F54, 0xBCE4, 0x6F55, 0xE64B, + 0x6F57, 0xE64F, 0x6F58, 0xBCEF, 0x6F5A, 0xE646, 0x6F5B, 0xBCE7, 0x6F5D, 0xE652, 0x6F5E, 0xE9F0, 0x6F5F, 0xBCF3, 0x6F60, 0xBCF2, + 0x6F61, 0xE654, 0x6F62, 0xE643, 0x6F63, 0xE65E, 0x6F64, 0xBCED, 0x6F66, 0xBCE3, 0x6F67, 0xE657, 0x6F69, 0xE65B, 0x6F6A, 0xE660, + 0x6F6B, 0xE655, 0x6F6C, 0xE649, 0x6F6D, 0xBCE6, 0x6F6E, 0xBCE9, 0x6F6F, 0xBCF1, 0x6F70, 0xBCEC, 0x6F72, 0xE64C, 0x6F73, 0xE2A2, + 0x6F76, 0xE648, 0x6F77, 0xE65F, 0x6F78, 0xBCE8, 0x6F7A, 0xBCEB, 0x6F7B, 0xE661, 0x6F7C, 0xBCE0, 0x6F7D, 0xE656, 0x6F7E, 0xE5FB, + 0x6F7F, 0xE65C, 0x6F80, 0xC0DF, 0x6F82, 0xE64A, 0x6F84, 0xBCE1, 0x6F85, 0xE645, 0x6F86, 0xBCE5, 0x6F87, 0xE5FC, 0x6F88, 0xBAAB, + 0x6F89, 0xE641, 0x6F8B, 0xE65A, 0x6F8C, 0xE642, 0x6F8D, 0xE640, 0x6F8E, 0xBCEA, 0x6F90, 0xE658, 0x6F92, 0xE5FE, 0x6F93, 0xE651, + 0x6F94, 0xE650, 0x6F95, 0xE65D, 0x6F96, 0xE647, 0x6F97, 0xBCEE, 0x6F9E, 0xE9F3, 0x6FA0, 0xBF49, 0x6FA1, 0xBEFE, 0x6FA2, 0xEA40, + 0x6FA3, 0xE9EB, 0x6FA4, 0xBF41, 0x6FA5, 0xE9F7, 0x6FA6, 0xBF48, 0x6FA7, 0xBF43, 0x6FA8, 0xE9F5, 0x6FA9, 0xED4F, 0x6FAA, 0xE9FB, + 0x6FAB, 0xEA42, 0x6FAC, 0xE9FA, 0x6FAD, 0xE9E9, 0x6FAE, 0xE9F8, 0x6FAF, 0xEA44, 0x6FB0, 0xEA46, 0x6FB1, 0xBEFD, 0x6FB2, 0xEA45, + 0x6FB3, 0xBF44, 0x6FB4, 0xBF4A, 0x6FB6, 0xBF47, 0x6FB8, 0xE9FE, 0x6FB9, 0xBF46, 0x6FBA, 0xE9F9, 0x6FBC, 0xE9ED, 0x6FBD, 0xE9F2, + 0x6FBF, 0xE9FD, 0x6FC0, 0xBF45, 0x6FC1, 0xBF42, 0x6FC2, 0xBEFC, 0x6FC3, 0xBF40, 0x6FC4, 0xE9F1, 0x6FC6, 0xE5FD, 0x6FC7, 0xE9EC, + 0x6FC8, 0xE9EF, 0x6FC9, 0xEA41, 0x6FCA, 0xE9F4, 0x6FCB, 0xE9EA, 0x6FCC, 0xED4E, 0x6FCD, 0xEA43, 0x6FCE, 0xE9EE, 0x6FCF, 0xE9FC, + 0x6FD4, 0xED51, 0x6FD5, 0xC0E3, 0x6FD8, 0xC0D7, 0x6FDB, 0xC0DB, 0x6FDC, 0xED53, 0x6FDD, 0xED59, 0x6FDE, 0xED57, 0x6FDF, 0xC0D9, + 0x6FE0, 0xC0DA, 0x6FE1, 0xC0E1, 0x6FE2, 0xED5A, 0x6FE3, 0xED52, 0x6FE4, 0xC0DC, 0x6FE6, 0xED56, 0x6FE7, 0xED55, 0x6FE8, 0xED5B, + 0x6FE9, 0xC0E2, 0x6FEB, 0xC0DD, 0x6FEC, 0xC0E0, 0x6FED, 0xED54, 0x6FEE, 0xC0E4, 0x6FEF, 0xC0DE, 0x6FF0, 0xC0E5, 0x6FF1, 0xC0D8, + 0x6FF2, 0xED58, 0x6FF4, 0xED50, 0x6FF7, 0xEFF7, 0x6FFA, 0xC271, 0x6FFB, 0xEFF4, 0x6FFC, 0xEFF6, 0x6FFE, 0xC26F, 0x6FFF, 0xEFF2, + 0x7000, 0xEFF3, 0x7001, 0xEFEE, 0x7004, 0xE9F6, 0x7005, 0xEFEF, 0x7006, 0xC270, 0x7007, 0xEFEB, 0x7009, 0xC26D, 0x700A, 0xEFF8, + 0x700B, 0xC26E, 0x700C, 0xEFEC, 0x700D, 0xEFED, 0x700E, 0xEFF1, 0x700F, 0xC273, 0x7011, 0xC272, 0x7014, 0xEFF0, 0x7015, 0xC378, + 0x7016, 0xF25F, 0x7017, 0xF265, 0x7018, 0xC379, 0x7019, 0xF25C, 0x701A, 0xC376, 0x701B, 0xC373, 0x701C, 0xF267, 0x701D, 0xC377, + 0x701F, 0xC374, 0x7020, 0xF25E, 0x7021, 0xF261, 0x7022, 0xF262, 0x7023, 0xF263, 0x7024, 0xF266, 0x7026, 0xEFF5, 0x7027, 0xF25D, + 0x7028, 0xC375, 0x7029, 0xF264, 0x702A, 0xF268, 0x702B, 0xF260, 0x702F, 0xF45D, 0x7030, 0xC46A, 0x7031, 0xF460, 0x7032, 0xC46B, + 0x7033, 0xF468, 0x7034, 0xF45F, 0x7035, 0xF45C, 0x7037, 0xF45E, 0x7038, 0xF462, 0x7039, 0xF465, 0x703A, 0xF464, 0x703B, 0xF467, + 0x703C, 0xF45B, 0x703E, 0xC469, 0x703F, 0xF463, 0x7040, 0xF466, 0x7041, 0xF469, 0x7042, 0xF461, 0x7043, 0xF5D3, 0x7044, 0xF5D4, + 0x7045, 0xF5D8, 0x7046, 0xF5D9, 0x7048, 0xF5D6, 0x7049, 0xF5D7, 0x704A, 0xF5D5, 0x704C, 0xC4E9, 0x7051, 0xC578, 0x7052, 0xF6EB, + 0x7055, 0xF6E8, 0x7056, 0xF6E9, 0x7057, 0xF6EA, 0x7058, 0xC579, 0x705A, 0xF7E5, 0x705B, 0xF7E4, 0x705D, 0xF8AF, 0x705E, 0xC5F4, + 0x705F, 0xF8AD, 0x7060, 0xF8B0, 0x7061, 0xF8AE, 0x7062, 0xF8F5, 0x7063, 0xC657, 0x7064, 0xC665, 0x7065, 0xF9A3, 0x7066, 0xF96C, + 0x7068, 0xF9A2, 0x7069, 0xF9D0, 0x706A, 0xF9D1, 0x706B, 0xA4F5, 0x7070, 0xA6C7, 0x7071, 0xCA41, 0x7074, 0xCB5E, 0x7076, 0xA85F, + 0x7078, 0xA862, 0x707A, 0xCB5F, 0x707C, 0xA860, 0x707D, 0xA861, 0x7082, 0xCD58, 0x7083, 0xCD5A, 0x7084, 0xCD55, 0x7085, 0xCD52, + 0x7086, 0xCD54, 0x708A, 0xAAA4, 0x708E, 0xAAA2, 0x7091, 0xCD56, 0x7092, 0xAAA3, 0x7093, 0xCD53, 0x7094, 0xCD50, 0x7095, 0xAAA1, + 0x7096, 0xCD57, 0x7098, 0xCD51, 0x7099, 0xAAA5, 0x709A, 0xCD59, 0x709F, 0xCFAF, 0x70A1, 0xCFB3, 0x70A4, 0xACB7, 0x70A9, 0xCFB6, + 0x70AB, 0xACAF, 0x70AC, 0xACB2, 0x70AD, 0xACB4, 0x70AE, 0xACB6, 0x70AF, 0xACB3, 0x70B0, 0xCFB2, 0x70B1, 0xCFB1, 0x70B3, 0xACB1, + 0x70B4, 0xCFB4, 0x70B5, 0xCFB5, 0x70B7, 0xCFAE, 0x70B8, 0xACB5, 0x70BA, 0xACB0, 0x70BE, 0xCFB0, 0x70C5, 0xD277, 0x70C6, 0xD278, + 0x70C7, 0xD279, 0x70C8, 0xAF50, 0x70CA, 0xAF4C, 0x70CB, 0xD26E, 0x70CD, 0xD276, 0x70CE, 0xD27B, 0x70CF, 0xAF51, 0x70D1, 0xD26C, + 0x70D2, 0xD272, 0x70D3, 0xD26B, 0x70D4, 0xD275, 0x70D7, 0xD271, 0x70D8, 0xAF4D, 0x70D9, 0xAF4F, 0x70DA, 0xD27A, 0x70DC, 0xD26A, + 0x70DD, 0xD26D, 0x70DE, 0xD273, 0x70E0, 0xD274, 0x70E1, 0xD27C, 0x70E2, 0xD270, 0x70E4, 0xAF4E, 0x70EF, 0xB26D, 0x70F0, 0xD64E, + 0x70F3, 0xD650, 0x70F4, 0xD64C, 0x70F6, 0xD658, 0x70F7, 0xD64A, 0x70F8, 0xD657, 0x70F9, 0xB269, 0x70FA, 0xD648, 0x70FB, 0xDA5B, + 0x70FC, 0xD652, 0x70FD, 0xB26C, 0x70FF, 0xD653, 0x7100, 0xD656, 0x7102, 0xD65A, 0x7104, 0xD64F, 0x7106, 0xD654, 0x7109, 0xB26A, + 0x710A, 0xB26B, 0x710B, 0xD659, 0x710C, 0xD64D, 0x710D, 0xD649, 0x710E, 0xD65B, 0x7110, 0xD651, 0x7113, 0xD655, 0x7117, 0xD64B, + 0x7119, 0xB548, 0x711A, 0xB549, 0x711B, 0xDA65, 0x711C, 0xB54F, 0x711E, 0xDA59, 0x711F, 0xDA62, 0x7120, 0xDA58, 0x7121, 0xB54C, + 0x7122, 0xDA60, 0x7123, 0xDA5E, 0x7125, 0xDA5F, 0x7126, 0xB54A, 0x7128, 0xDA63, 0x712E, 0xDA5C, 0x712F, 0xDA5A, 0x7130, 0xB54B, + 0x7131, 0xDA5D, 0x7132, 0xDA61, 0x7136, 0xB54D, 0x713A, 0xDA64, 0x7141, 0xDE70, 0x7142, 0xDE77, 0x7143, 0xDE79, 0x7144, 0xDEA1, + 0x7146, 0xB7DA, 0x7147, 0xDE6B, 0x7149, 0xB7D2, 0x714B, 0xDE7A, 0x714C, 0xB7D7, 0x714D, 0xDEA2, 0x714E, 0xB7CE, 0x7150, 0xDE7D, + 0x7152, 0xDE6D, 0x7153, 0xDE7E, 0x7154, 0xDE6C, 0x7156, 0xB7DC, 0x7158, 0xDE78, 0x7159, 0xB7CF, 0x715A, 0xDEA3, 0x715C, 0xB7D4, + 0x715D, 0xDE71, 0x715E, 0xB7D9, 0x715F, 0xDE7C, 0x7160, 0xDE6F, 0x7161, 0xDE76, 0x7162, 0xDE72, 0x7163, 0xDE6E, 0x7164, 0xB7D1, + 0x7165, 0xB7D8, 0x7166, 0xB7D6, 0x7167, 0xB7D3, 0x7168, 0xB7DB, 0x7169, 0xB7D0, 0x716A, 0xDE75, 0x716C, 0xB7D5, 0x716E, 0xB54E, + 0x7170, 0xDE7B, 0x7172, 0xDE73, 0x7178, 0xDE74, 0x717B, 0xE2C1, 0x717D, 0xBAB4, 0x7180, 0xE2BD, 0x7181, 0xE2C3, 0x7182, 0xE2BF, + 0x7184, 0xBAB6, 0x7185, 0xE2BE, 0x7186, 0xE2C2, 0x7187, 0xE2BA, 0x7189, 0xE2BC, 0x718A, 0xBAB5, 0x718F, 0xE2C0, 0x7190, 0xE2BB, + 0x7192, 0xBAB7, 0x7194, 0xBAB2, 0x7197, 0xE2C4, 0x7199, 0xBAB3, 0x719A, 0xE667, 0x719B, 0xE664, 0x719C, 0xE670, 0x719D, 0xE66A, + 0x719E, 0xE66C, 0x719F, 0xBCF4, 0x71A0, 0xE666, 0x71A1, 0xE66E, 0x71A4, 0xE66D, 0x71A5, 0xE66B, 0x71A7, 0xE671, 0x71A8, 0xBCF7, + 0x71A9, 0xE668, 0x71AA, 0xE66F, 0x71AC, 0xBCF5, 0x71AF, 0xE663, 0x71B0, 0xE665, 0x71B1, 0xBCF6, 0x71B2, 0xE662, 0x71B3, 0xE672, + 0x71B5, 0xE669, 0x71B8, 0xEA4A, 0x71B9, 0xBF51, 0x71BC, 0xEA55, 0x71BD, 0xEA53, 0x71BE, 0xBF4B, 0x71BF, 0xEA49, 0x71C0, 0xEA4C, + 0x71C1, 0xEA4D, 0x71C2, 0xEA48, 0x71C3, 0xBF55, 0x71C4, 0xBF56, 0x71C5, 0xEA47, 0x71C6, 0xEA56, 0x71C7, 0xEA51, 0x71C8, 0xBF4F, + 0x71C9, 0xBF4C, 0x71CA, 0xEA50, 0x71CB, 0xEA4E, 0x71CE, 0xBF52, 0x71CF, 0xEA52, 0x71D0, 0xBF4D, 0x71D2, 0xBF4E, 0x71D4, 0xEA4F, + 0x71D5, 0xBF50, 0x71D6, 0xEA4B, 0x71D8, 0xEA54, 0x71D9, 0xBF53, 0x71DA, 0xEA57, 0x71DB, 0xEA58, 0x71DC, 0xBF54, 0x71DF, 0xC0E7, + 0x71E0, 0xC0EE, 0x71E1, 0xED5C, 0x71E2, 0xED62, 0x71E4, 0xED60, 0x71E5, 0xC0EA, 0x71E6, 0xC0E9, 0x71E7, 0xC0E6, 0x71E8, 0xED5E, + 0x71EC, 0xC0EC, 0x71ED, 0xC0EB, 0x71EE, 0xC0E8, 0x71F0, 0xED61, 0x71F1, 0xED5D, 0x71F2, 0xED5F, 0x71F4, 0xC0ED, 0x71F8, 0xC277, + 0x71F9, 0xEFFB, 0x71FB, 0xC274, 0x71FC, 0xC275, 0x71FD, 0xEFFD, 0x71FE, 0xC276, 0x71FF, 0xEFFA, 0x7201, 0xEFF9, 0x7202, 0xF26C, + 0x7203, 0xEFFC, 0x7205, 0xF26D, 0x7206, 0xC37A, 0x7207, 0xF26B, 0x720A, 0xF26A, 0x720C, 0xF269, 0x720D, 0xC37B, 0x7210, 0xC46C, + 0x7213, 0xF46A, 0x7214, 0xF46B, 0x7219, 0xF5DC, 0x721A, 0xF5DB, 0x721B, 0xC4EA, 0x721D, 0xF5DA, 0x721E, 0xF6EC, 0x721F, 0xF6ED, + 0x7222, 0xF7E6, 0x7223, 0xF8B1, 0x7226, 0xF8F6, 0x7227, 0xF9BC, 0x7228, 0xC679, 0x7229, 0xF9C6, 0x722A, 0xA4F6, 0x722C, 0xAAA6, + 0x722D, 0xAAA7, 0x7230, 0xACB8, 0x7235, 0xC0EF, 0x7236, 0xA4F7, 0x7238, 0xAAA8, 0x7239, 0xAF52, 0x723A, 0xB7DD, 0x723B, 0xA4F8, + 0x723D, 0xB26E, 0x723E, 0xBAB8, 0x723F, 0xC962, 0x7241, 0xCFB7, 0x7242, 0xD27D, 0x7244, 0xE2C5, 0x7246, 0xC0F0, 0x7247, 0xA4F9, + 0x7248, 0xAAA9, 0x7249, 0xCFB8, 0x724A, 0xCFB9, 0x724B, 0xDA66, 0x724C, 0xB550, 0x724F, 0xDEA4, 0x7252, 0xB7DE, 0x7253, 0xE2C6, + 0x7256, 0xBCF8, 0x7258, 0xC37C, 0x7259, 0xA4FA, 0x725A, 0xDA67, 0x725B, 0xA4FB, 0x725D, 0xA6C9, 0x725E, 0xCA42, 0x725F, 0xA6C8, + 0x7260, 0xA865, 0x7261, 0xA864, 0x7262, 0xA863, 0x7263, 0xCB60, 0x7267, 0xAAAA, 0x7269, 0xAAAB, 0x726A, 0xCD5B, 0x726C, 0xCFBA, + 0x726E, 0xCFBD, 0x726F, 0xACBA, 0x7270, 0xCFBB, 0x7272, 0xACB9, 0x7273, 0xCFBC, 0x7274, 0xACBB, 0x7276, 0xD2A2, 0x7277, 0xD2A1, + 0x7278, 0xD27E, 0x7279, 0xAF53, 0x727B, 0xD65D, 0x727C, 0xD65E, 0x727D, 0xB26F, 0x727E, 0xD65C, 0x727F, 0xD65F, 0x7280, 0xB552, + 0x7281, 0xB270, 0x7284, 0xB551, 0x7285, 0xDA6B, 0x7286, 0xDA6A, 0x7288, 0xDA68, 0x7289, 0xDA69, 0x728B, 0xDA6C, 0x728C, 0xDEA6, + 0x728D, 0xDEA5, 0x728E, 0xDEA9, 0x7290, 0xDEA8, 0x7291, 0xDEA7, 0x7292, 0xBAB9, 0x7293, 0xE2C9, 0x7295, 0xE2C8, 0x7296, 0xBABA, + 0x7297, 0xE2C7, 0x7298, 0xE673, 0x729A, 0xE674, 0x729B, 0xBCF9, 0x729D, 0xEA59, 0x729E, 0xEA5A, 0x72A1, 0xF272, 0x72A2, 0xC37D, + 0x72A3, 0xF271, 0x72A4, 0xF270, 0x72A5, 0xF26E, 0x72A6, 0xF26F, 0x72A7, 0xC4EB, 0x72A8, 0xF46C, 0x72A9, 0xF6EE, 0x72AA, 0xF8F7, + 0x72AC, 0xA4FC, 0x72AE, 0xC9A5, 0x72AF, 0xA5C7, 0x72B0, 0xC9A6, 0x72B4, 0xCA43, 0x72B5, 0xCA44, 0x72BA, 0xCB66, 0x72BD, 0xCB62, + 0x72BF, 0xCB61, 0x72C0, 0xAAAC, 0x72C1, 0xCB65, 0x72C2, 0xA867, 0x72C3, 0xCB63, 0x72C4, 0xA866, 0x72C5, 0xCB67, 0x72C6, 0xCB64, + 0x72C9, 0xCD5F, 0x72CA, 0xCFBE, 0x72CB, 0xCD5D, 0x72CC, 0xCD64, 0x72CE, 0xAAAD, 0x72D0, 0xAAB0, 0x72D1, 0xCD65, 0x72D2, 0xCD61, + 0x72D4, 0xCD62, 0x72D6, 0xCD5C, 0x72D7, 0xAAAF, 0x72D8, 0xCD5E, 0x72D9, 0xAAAE, 0x72DA, 0xCD63, 0x72DC, 0xCD60, 0x72DF, 0xCFC2, + 0x72E0, 0xACBD, 0x72E1, 0xACBE, 0x72E3, 0xCFC5, 0x72E4, 0xCFBF, 0x72E6, 0xCFC4, 0x72E8, 0xCFC0, 0x72E9, 0xACBC, 0x72EA, 0xCFC3, + 0x72EB, 0xCFC1, 0x72F3, 0xD2A8, 0x72F4, 0xD2A5, 0x72F6, 0xD2A7, 0x72F7, 0xAF58, 0x72F8, 0xAF57, 0x72F9, 0xAF55, 0x72FA, 0xD2A4, + 0x72FB, 0xD2A9, 0x72FC, 0xAF54, 0x72FD, 0xAF56, 0x72FE, 0xD2A6, 0x72FF, 0xD667, 0x7300, 0xD2A3, 0x7301, 0xD2AA, 0x7307, 0xD662, + 0x7308, 0xD666, 0x730A, 0xD665, 0x730B, 0xDA6E, 0x730C, 0xDA79, 0x730F, 0xD668, 0x7311, 0xD663, 0x7312, 0xDA6D, 0x7313, 0xB274, + 0x7316, 0xB273, 0x7317, 0xD661, 0x7318, 0xD664, 0x7319, 0xB275, 0x731B, 0xB272, 0x731C, 0xB271, 0x731D, 0xD660, 0x731E, 0xD669, + 0x7322, 0xDA70, 0x7323, 0xDA77, 0x7325, 0xB554, 0x7326, 0xDA76, 0x7327, 0xDA73, 0x7329, 0xB556, 0x732D, 0xDA75, 0x7330, 0xDA6F, + 0x7331, 0xDA71, 0x7332, 0xDA74, 0x7333, 0xDA72, 0x7334, 0xB555, 0x7335, 0xDA78, 0x7336, 0xB553, 0x7337, 0xB7DF, 0x733A, 0xDEAD, + 0x733B, 0xDEAC, 0x733C, 0xDEAA, 0x733E, 0xB7E2, 0x733F, 0xB7E1, 0x7340, 0xDEAE, 0x7342, 0xDEAB, 0x7343, 0xE2CA, 0x7344, 0xBABB, + 0x7345, 0xB7E0, 0x7349, 0xDEB0, 0x734A, 0xDEAF, 0x734C, 0xE2CD, 0x734D, 0xE2CB, 0x734E, 0xBCFA, 0x7350, 0xBABC, 0x7351, 0xE2CC, + 0x7352, 0xE676, 0x7357, 0xBCFB, 0x7358, 0xE675, 0x7359, 0xE67E, 0x735A, 0xE67D, 0x735B, 0xE67B, 0x735D, 0xE67A, 0x735E, 0xE677, + 0x735F, 0xE678, 0x7360, 0xE679, 0x7361, 0xE67C, 0x7362, 0xE6A1, 0x7365, 0xEA5F, 0x7366, 0xEA5C, 0x7367, 0xEA5D, 0x7368, 0xBF57, + 0x7369, 0xEA5B, 0x736A, 0xEA61, 0x736B, 0xEA60, 0x736C, 0xEA5E, 0x736E, 0xED64, 0x736F, 0xED65, 0x7370, 0xC0F1, 0x7372, 0xC0F2, + 0x7373, 0xED63, 0x7375, 0xC279, 0x7376, 0xEFFE, 0x7377, 0xC278, 0x7378, 0xC37E, 0x737A, 0xC3A1, 0x737B, 0xC46D, 0x737C, 0xF46E, + 0x737D, 0xF46D, 0x737E, 0xF5DD, 0x737F, 0xF6EF, 0x7380, 0xC57A, 0x7381, 0xF7E8, 0x7382, 0xF7E7, 0x7383, 0xF7E9, 0x7384, 0xA5C8, + 0x7385, 0xCFC6, 0x7386, 0xAF59, 0x7387, 0xB276, 0x7388, 0xD66A, 0x7389, 0xA5C9, 0x738A, 0xC9A7, 0x738B, 0xA4FD, 0x738E, 0xCA45, + 0x7392, 0xCB6C, 0x7393, 0xCB6A, 0x7394, 0xCB6B, 0x7395, 0xCB68, 0x7396, 0xA868, 0x7397, 0xCB69, 0x739D, 0xCD6D, 0x739F, 0xAAB3, + 0x73A0, 0xCD6B, 0x73A1, 0xCD67, 0x73A2, 0xCD6A, 0x73A4, 0xCD66, 0x73A5, 0xAAB5, 0x73A6, 0xCD69, 0x73A8, 0xAAB2, 0x73A9, 0xAAB1, + 0x73AB, 0xAAB4, 0x73AC, 0xCD6C, 0x73AD, 0xCD68, 0x73B2, 0xACC2, 0x73B3, 0xACC5, 0x73B4, 0xCFCE, 0x73B5, 0xCFCD, 0x73B6, 0xCFCC, + 0x73B7, 0xACBF, 0x73B8, 0xCFD5, 0x73B9, 0xCFCB, 0x73BB, 0xACC1, 0x73BC, 0xD2AF, 0x73BE, 0xCFD2, 0x73BF, 0xCFD0, 0x73C0, 0xACC4, + 0x73C2, 0xCFC8, 0x73C3, 0xCFD3, 0x73C5, 0xCFCA, 0x73C6, 0xCFD4, 0x73C7, 0xCFD1, 0x73C8, 0xCFC9, 0x73CA, 0xACC0, 0x73CB, 0xCFD6, + 0x73CC, 0xCFC7, 0x73CD, 0xACC3, 0x73D2, 0xD2B4, 0x73D3, 0xD2AB, 0x73D4, 0xD2B6, 0x73D6, 0xD2AE, 0x73D7, 0xD2B9, 0x73D8, 0xD2BA, + 0x73D9, 0xD2AC, 0x73DA, 0xD2B8, 0x73DB, 0xD2B5, 0x73DC, 0xD2B3, 0x73DD, 0xD2B7, 0x73DE, 0xAF5F, 0x73E0, 0xAF5D, 0x73E3, 0xD2B1, + 0x73E5, 0xD2AD, 0x73E7, 0xD2B0, 0x73E8, 0xD2BB, 0x73E9, 0xD2B2, 0x73EA, 0xAF5E, 0x73EB, 0xCFCF, 0x73ED, 0xAF5A, 0x73EE, 0xAF5C, + 0x73F4, 0xD678, 0x73F5, 0xD66D, 0x73F6, 0xD66B, 0x73F8, 0xD66C, 0x73FA, 0xD673, 0x73FC, 0xD674, 0x73FD, 0xD670, 0x73FE, 0xB27B, + 0x73FF, 0xD675, 0x7400, 0xD672, 0x7401, 0xD66F, 0x7403, 0xB279, 0x7404, 0xD66E, 0x7405, 0xB277, 0x7406, 0xB27A, 0x7407, 0xD671, + 0x7408, 0xD679, 0x7409, 0xAF5B, 0x740A, 0xB278, 0x740B, 0xD677, 0x740C, 0xD676, 0x740D, 0xB27C, 0x7416, 0xDA7E, 0x741A, 0xDAA1, + 0x741B, 0xB560, 0x741D, 0xDAA7, 0x7420, 0xDAA9, 0x7421, 0xDAA2, 0x7422, 0xB55A, 0x7423, 0xDAA6, 0x7424, 0xDAA5, 0x7425, 0xB55B, + 0x7426, 0xB561, 0x7428, 0xB562, 0x7429, 0xDAA8, 0x742A, 0xB558, 0x742B, 0xDA7D, 0x742C, 0xDA7B, 0x742D, 0xDAA3, 0x742E, 0xDA7A, + 0x742F, 0xB55F, 0x7430, 0xDA7C, 0x7431, 0xDAA4, 0x7432, 0xDAAA, 0x7433, 0xB559, 0x7434, 0xB55E, 0x7435, 0xB55C, 0x7436, 0xB55D, + 0x743A, 0xB557, 0x743F, 0xB7E9, 0x7440, 0xDEB7, 0x7441, 0xB7E8, 0x7442, 0xDEBB, 0x7444, 0xDEB1, 0x7446, 0xDEBC, 0x744A, 0xDEB2, + 0x744B, 0xDEB3, 0x744D, 0xDEBD, 0x744E, 0xDEBA, 0x744F, 0xDEB8, 0x7450, 0xDEB9, 0x7451, 0xDEB5, 0x7452, 0xDEB4, 0x7454, 0xDEBE, + 0x7455, 0xB7E5, 0x7457, 0xDEB6, 0x7459, 0xB7EA, 0x745A, 0xB7E4, 0x745B, 0xB7EB, 0x745C, 0xB7EC, 0x745E, 0xB7E7, 0x745F, 0xB7E6, + 0x7462, 0xE2CE, 0x7463, 0xBABE, 0x7464, 0xBABD, 0x7467, 0xE2D3, 0x7469, 0xBCFC, 0x746A, 0xBABF, 0x746D, 0xBAC1, 0x746E, 0xE2D4, + 0x746F, 0xB7E3, 0x7470, 0xBAC0, 0x7471, 0xE2D0, 0x7472, 0xE2D2, 0x7473, 0xE2CF, 0x7475, 0xE2D1, 0x7479, 0xE6AB, 0x747C, 0xE6AA, + 0x747D, 0xE6A7, 0x747E, 0xBD40, 0x747F, 0xEA62, 0x7480, 0xBD41, 0x7481, 0xE6A6, 0x7483, 0xBCFE, 0x7485, 0xE6A8, 0x7486, 0xE6A5, + 0x7487, 0xE6A2, 0x7488, 0xE6A9, 0x7489, 0xE6A3, 0x748A, 0xE6A4, 0x748B, 0xBCFD, 0x7490, 0xED69, 0x7492, 0xEA66, 0x7494, 0xEA65, + 0x7495, 0xEA67, 0x7497, 0xED66, 0x7498, 0xBF5A, 0x749A, 0xEA63, 0x749C, 0xBF58, 0x749E, 0xBF5C, 0x749F, 0xBF5B, 0x74A0, 0xEA64, + 0x74A1, 0xEA68, 0x74A3, 0xBF59, 0x74A5, 0xED6D, 0x74A6, 0xC0F5, 0x74A7, 0xC27A, 0x74A8, 0xC0F6, 0x74A9, 0xC0F3, 0x74AA, 0xED6A, + 0x74AB, 0xED68, 0x74AD, 0xED6B, 0x74AF, 0xED6E, 0x74B0, 0xC0F4, 0x74B1, 0xED6C, 0x74B2, 0xED67, 0x74B5, 0xF042, 0x74B6, 0xF045, + 0x74B7, 0xF275, 0x74B8, 0xF040, 0x74BA, 0xF46F, 0x74BB, 0xF046, 0x74BD, 0xC3A2, 0x74BE, 0xF044, 0x74BF, 0xC27B, 0x74C0, 0xF041, + 0x74C1, 0xF043, 0x74C2, 0xF047, 0x74C3, 0xF276, 0x74C5, 0xF274, 0x74CA, 0xC3A3, 0x74CB, 0xF273, 0x74CF, 0xC46E, 0x74D4, 0xC4ED, + 0x74D5, 0xF6F1, 0x74D6, 0xC4EC, 0x74D7, 0xF6F3, 0x74D8, 0xF6F0, 0x74D9, 0xF6F2, 0x74DA, 0xC5D0, 0x74DB, 0xF8B2, 0x74DC, 0xA5CA, + 0x74DD, 0xCD6E, 0x74DE, 0xD2BC, 0x74DF, 0xD2BD, 0x74E0, 0xB27D, 0x74E1, 0xDEBF, 0x74E2, 0xBF5D, 0x74E3, 0xC3A4, 0x74E4, 0xC57B, + 0x74E5, 0xF8B3, 0x74E6, 0xA5CB, 0x74E8, 0xCD6F, 0x74E9, 0xA260, 0x74EC, 0xCFD7, 0x74EE, 0xCFD8, 0x74F4, 0xD2BE, 0x74F5, 0xD2BF, + 0x74F6, 0xB27E, 0x74F7, 0xB2A1, 0x74FB, 0xDAAB, 0x74FD, 0xDEC2, 0x74FE, 0xDEC1, 0x74FF, 0xDEC0, 0x7500, 0xE2D5, 0x7502, 0xE2D6, + 0x7503, 0xE2D7, 0x7504, 0xBAC2, 0x7507, 0xE6AD, 0x7508, 0xE6AC, 0x750B, 0xEA69, 0x750C, 0xBF5E, 0x750D, 0xBF5F, 0x750F, 0xED72, + 0x7510, 0xED6F, 0x7511, 0xED70, 0x7512, 0xED71, 0x7513, 0xF049, 0x7514, 0xF048, 0x7515, 0xC27C, 0x7516, 0xF277, 0x7517, 0xF5DE, + 0x7518, 0xA5CC, 0x751A, 0xACC6, 0x751C, 0xB2A2, 0x751D, 0xDEC3, 0x751F, 0xA5CD, 0x7521, 0xD2C0, 0x7522, 0xB2A3, 0x7525, 0xB563, + 0x7526, 0xB564, 0x7528, 0xA5CE, 0x7529, 0xA5CF, 0x752A, 0xCA46, 0x752B, 0xA86A, 0x752C, 0xA869, 0x752D, 0xACC7, 0x752E, 0xCFD9, + 0x752F, 0xDAAC, 0x7530, 0xA5D0, 0x7531, 0xA5D1, 0x7532, 0xA5D2, 0x7533, 0xA5D3, 0x7537, 0xA86B, 0x7538, 0xA86C, 0x7539, 0xCB6E, + 0x753A, 0xCB6D, 0x753D, 0xAAB6, 0x753E, 0xCD72, 0x753F, 0xCD70, 0x7540, 0xCD71, 0x7547, 0xCFDA, 0x7548, 0xCFDB, 0x754B, 0xACCB, + 0x754C, 0xACC9, 0x754E, 0xACCA, 0x754F, 0xACC8, 0x7554, 0xAF60, 0x7559, 0xAF64, 0x755A, 0xAF63, 0x755B, 0xD2C1, 0x755C, 0xAF62, + 0x755D, 0xAF61, 0x755F, 0xD2C2, 0x7562, 0xB2A6, 0x7563, 0xD67B, 0x7564, 0xD67A, 0x7565, 0xB2A4, 0x7566, 0xB2A5, 0x756A, 0xB566, + 0x756B, 0xB565, 0x756C, 0xDAAE, 0x756F, 0xDAAD, 0x7570, 0xB2A7, 0x7576, 0xB7ED, 0x7577, 0xDEC5, 0x7578, 0xB7EE, 0x7579, 0xDEC4, + 0x757D, 0xE2D8, 0x757E, 0xE6AE, 0x757F, 0xBD42, 0x7580, 0xEA6A, 0x7584, 0xED73, 0x7586, 0xC3A6, 0x7587, 0xC3A5, 0x758A, 0xC57C, + 0x758B, 0xA5D4, 0x758C, 0xCD73, 0x758F, 0xB2A8, 0x7590, 0xE2D9, 0x7591, 0xBAC3, 0x7594, 0xCB6F, 0x7595, 0xCB70, 0x7598, 0xCD74, + 0x7599, 0xAAB8, 0x759A, 0xAAB9, 0x759D, 0xAAB7, 0x75A2, 0xACCF, 0x75A3, 0xACD0, 0x75A4, 0xACCD, 0x75A5, 0xACCE, 0x75A7, 0xCFDC, + 0x75AA, 0xCFDD, 0x75AB, 0xACCC, 0x75B0, 0xD2C3, 0x75B2, 0xAF68, 0x75B3, 0xAF69, 0x75B5, 0xB2AB, 0x75B6, 0xD2C9, 0x75B8, 0xAF6E, + 0x75B9, 0xAF6C, 0x75BA, 0xD2CA, 0x75BB, 0xD2C5, 0x75BC, 0xAF6B, 0x75BD, 0xAF6A, 0x75BE, 0xAF65, 0x75BF, 0xD2C8, 0x75C0, 0xD2C7, + 0x75C1, 0xD2C4, 0x75C2, 0xAF6D, 0x75C4, 0xD2C6, 0x75C5, 0xAF66, 0x75C7, 0xAF67, 0x75CA, 0xB2AC, 0x75CB, 0xD6A1, 0x75CC, 0xD6A2, + 0x75CD, 0xB2AD, 0x75CE, 0xD67C, 0x75CF, 0xD67E, 0x75D0, 0xD6A4, 0x75D1, 0xD6A3, 0x75D2, 0xD67D, 0x75D4, 0xB2A9, 0x75D5, 0xB2AA, + 0x75D7, 0xDAB6, 0x75D8, 0xB56B, 0x75D9, 0xB56A, 0x75DA, 0xDAB0, 0x75DB, 0xB568, 0x75DD, 0xDAB3, 0x75DE, 0xB56C, 0x75DF, 0xDAB4, + 0x75E0, 0xB56D, 0x75E1, 0xDAB1, 0x75E2, 0xB567, 0x75E3, 0xB569, 0x75E4, 0xDAB5, 0x75E6, 0xDAB2, 0x75E7, 0xDAAF, 0x75ED, 0xDED2, + 0x75EF, 0xDEC7, 0x75F0, 0xB7F0, 0x75F1, 0xB7F3, 0x75F2, 0xB7F2, 0x75F3, 0xB7F7, 0x75F4, 0xB7F6, 0x75F5, 0xDED3, 0x75F6, 0xDED1, + 0x75F7, 0xDECA, 0x75F8, 0xDECE, 0x75F9, 0xDECD, 0x75FA, 0xB7F4, 0x75FB, 0xDED0, 0x75FC, 0xDECC, 0x75FD, 0xDED4, 0x75FE, 0xDECB, + 0x75FF, 0xB7F5, 0x7600, 0xB7EF, 0x7601, 0xB7F1, 0x7603, 0xDEC9, 0x7608, 0xE2DB, 0x7609, 0xBAC7, 0x760A, 0xE2DF, 0x760B, 0xBAC6, + 0x760C, 0xE2DC, 0x760D, 0xBAC5, 0x760F, 0xDEC8, 0x7610, 0xDECF, 0x7611, 0xE2DE, 0x7613, 0xBAC8, 0x7614, 0xE2E0, 0x7615, 0xE2DD, + 0x7616, 0xE2DA, 0x7619, 0xE6B1, 0x761A, 0xE6B5, 0x761B, 0xE6B7, 0x761C, 0xE6B3, 0x761D, 0xE6B2, 0x761E, 0xE6B0, 0x761F, 0xBD45, + 0x7620, 0xBD43, 0x7621, 0xBD48, 0x7622, 0xBD49, 0x7623, 0xE6B4, 0x7624, 0xBD46, 0x7625, 0xE6AF, 0x7626, 0xBD47, 0x7627, 0xBAC4, + 0x7628, 0xE6B6, 0x7629, 0xBD44, 0x762D, 0xEA6C, 0x762F, 0xEA6B, 0x7630, 0xEA73, 0x7631, 0xEA6D, 0x7632, 0xEA72, 0x7633, 0xEA6F, + 0x7634, 0xBF60, 0x7635, 0xEA71, 0x7638, 0xBF61, 0x763A, 0xBF62, 0x763C, 0xEA70, 0x763D, 0xEA6E, 0x7642, 0xC0F8, 0x7643, 0xED74, + 0x7646, 0xC0F7, 0x7647, 0xED77, 0x7648, 0xED75, 0x7649, 0xED76, 0x764C, 0xC0F9, 0x7650, 0xF04D, 0x7652, 0xC2A1, 0x7653, 0xF04E, + 0x7656, 0xC27D, 0x7657, 0xF04F, 0x7658, 0xC27E, 0x7659, 0xF04C, 0x765A, 0xF050, 0x765C, 0xF04A, 0x765F, 0xC3A7, 0x7660, 0xF278, + 0x7661, 0xC3A8, 0x7662, 0xC46F, 0x7664, 0xF04B, 0x7665, 0xC470, 0x7669, 0xC4EE, 0x766A, 0xF5DF, 0x766C, 0xC57E, 0x766D, 0xF6F4, + 0x766E, 0xC57D, 0x7670, 0xF7EA, 0x7671, 0xC5F5, 0x7672, 0xC5F6, 0x7675, 0xF9CC, 0x7678, 0xACD1, 0x7679, 0xCFDE, 0x767B, 0xB56E, + 0x767C, 0xB56F, 0x767D, 0xA5D5, 0x767E, 0xA6CA, 0x767F, 0xCA47, 0x7681, 0xCB71, 0x7682, 0xA86D, 0x7684, 0xAABA, 0x7686, 0xACD2, + 0x7687, 0xACD3, 0x7688, 0xACD4, 0x7689, 0xD6A6, 0x768A, 0xD2CB, 0x768B, 0xAF6F, 0x768E, 0xB2AE, 0x768F, 0xD6A5, 0x7692, 0xDAB8, + 0x7693, 0xB571, 0x7695, 0xDAB7, 0x7696, 0xB570, 0x7699, 0xDED5, 0x769A, 0xBD4A, 0x769B, 0xE6BB, 0x769C, 0xE6B8, 0x769D, 0xE6B9, + 0x769E, 0xE6BA, 0x76A4, 0xED78, 0x76A6, 0xF051, 0x76AA, 0xF471, 0x76AB, 0xF470, 0x76AD, 0xF6F5, 0x76AE, 0xA5D6, 0x76AF, 0xCD75, + 0x76B0, 0xAF70, 0x76B4, 0xB572, 0x76B5, 0xDED6, 0x76B8, 0xE2E1, 0x76BA, 0xBD4B, 0x76BB, 0xEA74, 0x76BD, 0xF052, 0x76BE, 0xF472, + 0x76BF, 0xA5D7, 0x76C2, 0xAABB, 0x76C3, 0xACD7, 0x76C4, 0xCFDF, 0x76C5, 0xACD8, 0x76C6, 0xACD6, 0x76C8, 0xACD5, 0x76C9, 0xD2CC, + 0x76CA, 0xAF71, 0x76CD, 0xAF72, 0x76CE, 0xAF73, 0x76D2, 0xB2B0, 0x76D3, 0xD6A7, 0x76D4, 0xB2AF, 0x76DA, 0xDAB9, 0x76DB, 0xB2B1, + 0x76DC, 0xB573, 0x76DD, 0xDED7, 0x76DE, 0xB7F8, 0x76DF, 0xB7F9, 0x76E1, 0xBAC9, 0x76E3, 0xBACA, 0x76E4, 0xBD4C, 0x76E5, 0xBF64, + 0x76E6, 0xEA75, 0x76E7, 0xBF63, 0x76E9, 0xED79, 0x76EA, 0xC0FA, 0x76EC, 0xF053, 0x76ED, 0xF473, 0x76EE, 0xA5D8, 0x76EF, 0xA86E, + 0x76F0, 0xCD78, 0x76F1, 0xCD77, 0x76F2, 0xAABC, 0x76F3, 0xCD76, 0x76F4, 0xAABD, 0x76F5, 0xCD79, 0x76F7, 0xCFE5, 0x76F8, 0xACDB, + 0x76F9, 0xACDA, 0x76FA, 0xCFE7, 0x76FB, 0xCFE6, 0x76FC, 0xACDF, 0x76FE, 0xACDE, 0x7701, 0xACD9, 0x7703, 0xCFE1, 0x7704, 0xCFE2, + 0x7705, 0xCFE3, 0x7707, 0xACE0, 0x7708, 0xCFE0, 0x7709, 0xACDC, 0x770A, 0xCFE4, 0x770B, 0xACDD, 0x7710, 0xD2CF, 0x7711, 0xD2D3, + 0x7712, 0xD2D1, 0x7713, 0xD2D0, 0x7715, 0xD2D4, 0x7719, 0xD2D5, 0x771A, 0xD2D6, 0x771B, 0xD2CE, 0x771D, 0xD2CD, 0x771F, 0xAF75, + 0x7720, 0xAF76, 0x7722, 0xD2D7, 0x7723, 0xD2D2, 0x7725, 0xD6B0, 0x7727, 0xD2D8, 0x7728, 0xAF77, 0x7729, 0xAF74, 0x772D, 0xD6AA, + 0x772F, 0xD6A9, 0x7731, 0xD6AB, 0x7732, 0xD6AC, 0x7733, 0xD6AE, 0x7734, 0xD6AD, 0x7735, 0xD6B2, 0x7736, 0xB2B5, 0x7737, 0xB2B2, + 0x7738, 0xB2B6, 0x7739, 0xD6A8, 0x773A, 0xB2B7, 0x773B, 0xD6B1, 0x773C, 0xB2B4, 0x773D, 0xD6AF, 0x773E, 0xB2B3, 0x7744, 0xDABC, + 0x7745, 0xDABE, 0x7746, 0xDABA, 0x7747, 0xDABB, 0x774A, 0xDABF, 0x774B, 0xDAC1, 0x774C, 0xDAC2, 0x774D, 0xDABD, 0x774E, 0xDAC0, + 0x774F, 0xB574, 0x7752, 0xDEDB, 0x7754, 0xDEE0, 0x7755, 0xDED8, 0x7756, 0xDEDC, 0x7759, 0xDEE1, 0x775A, 0xDEDD, 0x775B, 0xB7FA, + 0x775C, 0xB843, 0x775E, 0xB7FD, 0x775F, 0xDED9, 0x7760, 0xDEDA, 0x7761, 0xBACE, 0x7762, 0xB846, 0x7763, 0xB7FE, 0x7765, 0xB844, + 0x7766, 0xB7FC, 0x7767, 0xDEDF, 0x7768, 0xB845, 0x7769, 0xDEDE, 0x776A, 0xB841, 0x776B, 0xB7FB, 0x776C, 0xB842, 0x776D, 0xDEE2, + 0x776E, 0xE2E6, 0x776F, 0xE2E8, 0x7779, 0xB840, 0x777C, 0xE2E3, 0x777D, 0xBACC, 0x777E, 0xE2E9, 0x777F, 0xBACD, 0x7780, 0xE2E7, + 0x7781, 0xE2E2, 0x7782, 0xE2E5, 0x7783, 0xE2EA, 0x7784, 0xBACB, 0x7785, 0xE2E4, 0x7787, 0xBD4E, 0x7788, 0xE6BF, 0x7789, 0xE6BE, + 0x778B, 0xBD51, 0x778C, 0xBD4F, 0x778D, 0xE6BC, 0x778E, 0xBD4D, 0x778F, 0xE6BD, 0x7791, 0xBD50, 0x7795, 0xEA7D, 0x7797, 0xEAA1, + 0x7799, 0xEA7E, 0x779A, 0xEA76, 0x779B, 0xEA7A, 0x779C, 0xEA79, 0x779D, 0xEA77, 0x779E, 0xBF66, 0x779F, 0xBF67, 0x77A0, 0xBF65, + 0x77A1, 0xEA78, 0x77A2, 0xEA7B, 0x77A3, 0xEA7C, 0x77A5, 0xBF68, 0x77A7, 0xC140, 0x77A8, 0xEDA3, 0x77AA, 0xC0FC, 0x77AB, 0xED7B, + 0x77AC, 0xC0FE, 0x77AD, 0xC141, 0x77B0, 0xC0FD, 0x77B1, 0xEDA2, 0x77B2, 0xED7C, 0x77B3, 0xC0FB, 0x77B4, 0xEDA1, 0x77B5, 0xED7A, + 0x77B6, 0xED7E, 0x77B7, 0xED7D, 0x77BA, 0xF055, 0x77BB, 0xC2A4, 0x77BC, 0xC2A5, 0x77BD, 0xC2A2, 0x77BF, 0xC2A3, 0x77C2, 0xF054, + 0x77C4, 0xF27B, 0x77C7, 0xC3A9, 0x77C9, 0xF279, 0x77CA, 0xF27A, 0x77CC, 0xF474, 0x77CD, 0xF477, 0x77CE, 0xF475, 0x77CF, 0xF476, + 0x77D0, 0xF5E0, 0x77D3, 0xC4EF, 0x77D4, 0xF7EB, 0x77D5, 0xF8B4, 0x77D7, 0xC5F7, 0x77D8, 0xF8F8, 0x77D9, 0xF8F9, 0x77DA, 0xC666, + 0x77DB, 0xA5D9, 0x77DC, 0xACE1, 0x77DE, 0xDAC3, 0x77E0, 0xDEE3, 0x77E2, 0xA5DA, 0x77E3, 0xA86F, 0x77E5, 0xAABE, 0x77E7, 0xCFE8, + 0x77E8, 0xCFE9, 0x77E9, 0xAF78, 0x77EC, 0xDAC4, 0x77ED, 0xB575, 0x77EE, 0xB847, 0x77EF, 0xC142, 0x77F0, 0xEDA4, 0x77F1, 0xF27C, + 0x77F2, 0xF478, 0x77F3, 0xA5DB, 0x77F7, 0xCDA1, 0x77F8, 0xCD7A, 0x77F9, 0xCD7C, 0x77FA, 0xCD7E, 0x77FB, 0xCD7D, 0x77FC, 0xCD7B, + 0x77FD, 0xAABF, 0x7802, 0xACE2, 0x7803, 0xCFF2, 0x7805, 0xCFED, 0x7806, 0xCFEA, 0x7809, 0xCFF1, 0x780C, 0xACE4, 0x780D, 0xACE5, + 0x780E, 0xCFF0, 0x780F, 0xCFEF, 0x7810, 0xCFEE, 0x7811, 0xCFEB, 0x7812, 0xCFEC, 0x7813, 0xCFF3, 0x7814, 0xACE3, 0x781D, 0xAF7C, + 0x781F, 0xAFA4, 0x7820, 0xAFA3, 0x7821, 0xD2E1, 0x7822, 0xD2DB, 0x7823, 0xD2D9, 0x7825, 0xAFA1, 0x7826, 0xD6B9, 0x7827, 0xAF7A, + 0x7828, 0xD2DE, 0x7829, 0xD2E2, 0x782A, 0xD2E4, 0x782B, 0xD2E0, 0x782C, 0xD2DA, 0x782D, 0xAFA2, 0x782E, 0xD2DF, 0x782F, 0xD2DD, + 0x7830, 0xAF79, 0x7831, 0xD2E5, 0x7832, 0xAFA5, 0x7833, 0xD2E3, 0x7834, 0xAF7D, 0x7835, 0xD2DC, 0x7837, 0xAF7E, 0x7838, 0xAF7B, + 0x7843, 0xB2B9, 0x7845, 0xD6BA, 0x7848, 0xD6B3, 0x7849, 0xD6B5, 0x784A, 0xD6B7, 0x784C, 0xD6B8, 0x784D, 0xD6B6, 0x784E, 0xB2BA, + 0x7850, 0xD6BB, 0x7852, 0xD6B4, 0x785C, 0xDAC8, 0x785D, 0xB576, 0x785E, 0xDAD0, 0x7860, 0xDAC5, 0x7862, 0xDAD1, 0x7864, 0xDAC6, + 0x7865, 0xDAC7, 0x7868, 0xDACF, 0x7869, 0xDACE, 0x786A, 0xDACB, 0x786B, 0xB2B8, 0x786C, 0xB577, 0x786D, 0xDAC9, 0x786E, 0xDACC, + 0x786F, 0xB578, 0x7870, 0xDACD, 0x7871, 0xDACA, 0x7879, 0xDEEE, 0x787B, 0xDEF2, 0x787C, 0xB84E, 0x787E, 0xE2F0, 0x787F, 0xB851, + 0x7880, 0xDEF0, 0x7881, 0xF9D6, 0x7883, 0xDEED, 0x7884, 0xDEE8, 0x7885, 0xDEEA, 0x7886, 0xDEEB, 0x7887, 0xDEE4, 0x7889, 0xB84D, + 0x788C, 0xB84C, 0x788E, 0xB848, 0x788F, 0xDEE7, 0x7891, 0xB84F, 0x7893, 0xB850, 0x7894, 0xDEE6, 0x7895, 0xDEE9, 0x7896, 0xDEF1, + 0x7897, 0xB84A, 0x7898, 0xB84B, 0x7899, 0xDEEF, 0x789A, 0xDEE5, 0x789E, 0xE2F2, 0x789F, 0xBAD0, 0x78A0, 0xE2F4, 0x78A1, 0xDEEC, + 0x78A2, 0xE2F6, 0x78A3, 0xBAD4, 0x78A4, 0xE2F7, 0x78A5, 0xE2F3, 0x78A7, 0xBAD1, 0x78A8, 0xE2EF, 0x78A9, 0xBAD3, 0x78AA, 0xE2EC, + 0x78AB, 0xE2F1, 0x78AC, 0xE2F5, 0x78AD, 0xE2EE, 0x78B0, 0xB849, 0x78B2, 0xE2EB, 0x78B3, 0xBAD2, 0x78B4, 0xE2ED, 0x78BA, 0xBD54, + 0x78BB, 0xE6C1, 0x78BC, 0xBD58, 0x78BE, 0xBD56, 0x78C1, 0xBACF, 0x78C3, 0xE6C8, 0x78C4, 0xE6C9, 0x78C5, 0xBD53, 0x78C8, 0xE6C7, + 0x78C9, 0xE6CA, 0x78CA, 0xBD55, 0x78CB, 0xBD52, 0x78CC, 0xE6C3, 0x78CD, 0xE6C0, 0x78CE, 0xE6C5, 0x78CF, 0xE6C2, 0x78D0, 0xBD59, + 0x78D1, 0xE6C4, 0x78D4, 0xE6C6, 0x78D5, 0xBD57, 0x78DA, 0xBF6A, 0x78DB, 0xEAA8, 0x78DD, 0xEAA2, 0x78DE, 0xEAA6, 0x78DF, 0xEAAC, + 0x78E0, 0xEAAD, 0x78E1, 0xEAA9, 0x78E2, 0xEAAA, 0x78E3, 0xEAA7, 0x78E5, 0xEAA4, 0x78E7, 0xBF6C, 0x78E8, 0xBF69, 0x78E9, 0xEAA3, + 0x78EA, 0xEAA5, 0x78EC, 0xBF6B, 0x78ED, 0xEAAB, 0x78EF, 0xC146, 0x78F2, 0xEDAA, 0x78F3, 0xEDA5, 0x78F4, 0xC145, 0x78F7, 0xC143, + 0x78F9, 0xEDAC, 0x78FA, 0xC144, 0x78FB, 0xEDA8, 0x78FC, 0xEDA9, 0x78FD, 0xEDA6, 0x78FE, 0xEDAD, 0x78FF, 0xF056, 0x7901, 0xC147, + 0x7902, 0xEDA7, 0x7904, 0xEDAE, 0x7905, 0xEDAB, 0x7909, 0xF05A, 0x790C, 0xF057, 0x790E, 0xC2A6, 0x7910, 0xF05B, 0x7911, 0xF05D, + 0x7912, 0xF05C, 0x7913, 0xF058, 0x7914, 0xF059, 0x7917, 0xF2A3, 0x7919, 0xC3AA, 0x791B, 0xF27E, 0x791C, 0xF2A2, 0x791D, 0xF27D, + 0x791E, 0xF2A4, 0x7921, 0xF2A1, 0x7923, 0xF47A, 0x7924, 0xF47D, 0x7925, 0xF479, 0x7926, 0xC471, 0x7927, 0xF47B, 0x7928, 0xF47C, + 0x7929, 0xF47E, 0x792A, 0xC472, 0x792B, 0xC474, 0x792C, 0xC473, 0x792D, 0xF5E1, 0x792F, 0xF5E3, 0x7931, 0xF5E2, 0x7935, 0xF6F6, + 0x7938, 0xF8B5, 0x7939, 0xF8FA, 0x793A, 0xA5DC, 0x793D, 0xCB72, 0x793E, 0xAAC0, 0x793F, 0xCDA3, 0x7940, 0xAAC1, 0x7941, 0xAAC2, + 0x7942, 0xCDA2, 0x7944, 0xCFF8, 0x7945, 0xCFF7, 0x7946, 0xACE6, 0x7947, 0xACE9, 0x7948, 0xACE8, 0x7949, 0xACE7, 0x794A, 0xCFF4, + 0x794B, 0xCFF6, 0x794C, 0xCFF5, 0x794F, 0xD2E8, 0x7950, 0xAFA7, 0x7951, 0xD2EC, 0x7952, 0xD2EB, 0x7953, 0xD2EA, 0x7954, 0xD2E6, + 0x7955, 0xAFA6, 0x7956, 0xAFAA, 0x7957, 0xAFAD, 0x795A, 0xAFAE, 0x795B, 0xD2E7, 0x795C, 0xD2E9, 0x795D, 0xAFAC, 0x795E, 0xAFAB, + 0x795F, 0xAFA9, 0x7960, 0xAFA8, 0x7961, 0xD6C2, 0x7963, 0xD6C0, 0x7964, 0xD6BC, 0x7965, 0xB2BB, 0x7967, 0xD6BD, 0x7968, 0xB2BC, + 0x7969, 0xD6BE, 0x796A, 0xD6BF, 0x796B, 0xD6C1, 0x796D, 0xB2BD, 0x7970, 0xDAD5, 0x7972, 0xDAD4, 0x7973, 0xDAD3, 0x7974, 0xDAD2, + 0x7979, 0xDEF6, 0x797A, 0xB852, 0x797C, 0xDEF3, 0x797D, 0xDEF5, 0x797F, 0xB853, 0x7981, 0xB854, 0x7982, 0xDEF4, 0x7988, 0xE341, + 0x798A, 0xE2F9, 0x798B, 0xE2FA, 0x798D, 0xBAD7, 0x798E, 0xBAD5, 0x798F, 0xBAD6, 0x7990, 0xE343, 0x7992, 0xE342, 0x7993, 0xE2FE, + 0x7994, 0xE2FD, 0x7995, 0xE2FC, 0x7996, 0xE2FB, 0x7997, 0xE340, 0x7998, 0xE2F8, 0x799A, 0xE6CB, 0x799B, 0xE6D0, 0x799C, 0xE6CE, + 0x79A0, 0xE6CD, 0x79A1, 0xE6CC, 0x79A2, 0xE6CF, 0x79A4, 0xEAAE, 0x79A6, 0xBF6D, 0x79A7, 0xC148, 0x79A8, 0xEDB0, 0x79AA, 0xC149, + 0x79AB, 0xEDAF, 0x79AC, 0xF05F, 0x79AD, 0xF05E, 0x79AE, 0xC2A7, 0x79B0, 0xF2A5, 0x79B1, 0xC3AB, 0x79B2, 0xF4A1, 0x79B3, 0xC5A1, + 0x79B4, 0xF6F7, 0x79B6, 0xF8B7, 0x79B7, 0xF8B6, 0x79B8, 0xC9A8, 0x79B9, 0xACEA, 0x79BA, 0xACEB, 0x79BB, 0xD6C3, 0x79BD, 0xB856, + 0x79BE, 0xA5DD, 0x79BF, 0xA872, 0x79C0, 0xA871, 0x79C1, 0xA870, 0x79C5, 0xCDA4, 0x79C8, 0xAAC4, 0x79C9, 0xAAC3, 0x79CB, 0xACEE, + 0x79CD, 0xCFFA, 0x79CE, 0xCFFD, 0x79CF, 0xCFFB, 0x79D1, 0xACEC, 0x79D2, 0xACED, 0x79D5, 0xCFF9, 0x79D6, 0xCFFC, 0x79D8, 0xAFB5, + 0x79DC, 0xD2F3, 0x79DD, 0xD2F5, 0x79DE, 0xD2F4, 0x79DF, 0xAFB2, 0x79E0, 0xD2EF, 0x79E3, 0xAFB0, 0x79E4, 0xAFAF, 0x79E6, 0xAFB3, + 0x79E7, 0xAFB1, 0x79E9, 0xAFB4, 0x79EA, 0xD2F2, 0x79EB, 0xD2ED, 0x79EC, 0xD2EE, 0x79ED, 0xD2F1, 0x79EE, 0xD2F0, 0x79F6, 0xD6C6, + 0x79F7, 0xD6C7, 0x79F8, 0xD6C5, 0x79FA, 0xD6C4, 0x79FB, 0xB2BE, 0x7A00, 0xB57D, 0x7A02, 0xDAD6, 0x7A03, 0xDAD8, 0x7A04, 0xDADA, + 0x7A05, 0xB57C, 0x7A08, 0xB57A, 0x7A0A, 0xDAD7, 0x7A0B, 0xB57B, 0x7A0C, 0xDAD9, 0x7A0D, 0xB579, 0x7A10, 0xDF41, 0x7A11, 0xDEF7, + 0x7A12, 0xDEFA, 0x7A13, 0xDEFE, 0x7A14, 0xB85A, 0x7A15, 0xDEFC, 0x7A17, 0xDEFB, 0x7A18, 0xDEF8, 0x7A19, 0xDEF9, 0x7A1A, 0xB858, + 0x7A1B, 0xDF40, 0x7A1C, 0xB857, 0x7A1E, 0xB85C, 0x7A1F, 0xB85B, 0x7A20, 0xB859, 0x7A22, 0xDEFD, 0x7A26, 0xE349, 0x7A28, 0xE348, + 0x7A2B, 0xE344, 0x7A2E, 0xBAD8, 0x7A2F, 0xE347, 0x7A30, 0xE346, 0x7A31, 0xBAD9, 0x7A37, 0xBD5E, 0x7A39, 0xE6D2, 0x7A3B, 0xBD5F, + 0x7A3C, 0xBD5B, 0x7A3D, 0xBD5D, 0x7A3F, 0xBD5A, 0x7A40, 0xBD5C, 0x7A44, 0xEAAF, 0x7A46, 0xBF70, 0x7A47, 0xEAB1, 0x7A48, 0xEAB0, + 0x7A4A, 0xE345, 0x7A4B, 0xBF72, 0x7A4C, 0xBF71, 0x7A4D, 0xBF6E, 0x7A4E, 0xBF6F, 0x7A54, 0xEDB5, 0x7A56, 0xEDB3, 0x7A57, 0xC14A, + 0x7A58, 0xEDB4, 0x7A5A, 0xEDB6, 0x7A5B, 0xEDB2, 0x7A5C, 0xEDB1, 0x7A5F, 0xF060, 0x7A60, 0xC2AA, 0x7A61, 0xC2A8, 0x7A62, 0xC2A9, + 0x7A67, 0xF2A6, 0x7A68, 0xF2A7, 0x7A69, 0xC3AD, 0x7A6B, 0xC3AC, 0x7A6C, 0xF4A3, 0x7A6D, 0xF4A4, 0x7A6E, 0xF4A2, 0x7A70, 0xF6F8, + 0x7A71, 0xF6F9, 0x7A74, 0xA5DE, 0x7A75, 0xCA48, 0x7A76, 0xA873, 0x7A78, 0xCDA5, 0x7A79, 0xAAC6, 0x7A7A, 0xAAC5, 0x7A7B, 0xCDA6, + 0x7A7E, 0xD040, 0x7A7F, 0xACEF, 0x7A80, 0xCFFE, 0x7A81, 0xACF0, 0x7A84, 0xAFB6, 0x7A85, 0xD2F8, 0x7A86, 0xD2F6, 0x7A87, 0xD2FC, + 0x7A88, 0xAFB7, 0x7A89, 0xD2F7, 0x7A8A, 0xD2FB, 0x7A8B, 0xD2F9, 0x7A8C, 0xD2FA, 0x7A8F, 0xD6C8, 0x7A90, 0xD6CA, 0x7A92, 0xB2BF, + 0x7A94, 0xD6C9, 0x7A95, 0xB2C0, 0x7A96, 0xB5A2, 0x7A97, 0xB5A1, 0x7A98, 0xB57E, 0x7A99, 0xDADB, 0x7A9E, 0xDF44, 0x7A9F, 0xB85D, + 0x7AA0, 0xB85E, 0x7AA2, 0xDF43, 0x7AA3, 0xDF42, 0x7AA8, 0xE34A, 0x7AA9, 0xBADB, 0x7AAA, 0xBADA, 0x7AAB, 0xE34B, 0x7AAC, 0xE34C, + 0x7AAE, 0xBD61, 0x7AAF, 0xBD60, 0x7AB1, 0xEAB5, 0x7AB2, 0xE6D3, 0x7AB3, 0xE6D5, 0x7AB4, 0xE6D4, 0x7AB5, 0xEAB4, 0x7AB6, 0xEAB2, + 0x7AB7, 0xEAB6, 0x7AB8, 0xEAB3, 0x7ABA, 0xBF73, 0x7ABE, 0xEDB7, 0x7ABF, 0xC14B, 0x7AC0, 0xEDB8, 0x7AC1, 0xEDB9, 0x7AC4, 0xC2AB, + 0x7AC5, 0xC2AC, 0x7AC7, 0xC475, 0x7ACA, 0xC5D1, 0x7ACB, 0xA5DF, 0x7AD1, 0xD041, 0x7AD8, 0xD2FD, 0x7AD9, 0xAFB8, 0x7ADF, 0xB3BA, + 0x7AE0, 0xB3B9, 0x7AE3, 0xB5A4, 0x7AE4, 0xDADD, 0x7AE5, 0xB5A3, 0x7AE6, 0xDADC, 0x7AEB, 0xDF45, 0x7AED, 0xBADC, 0x7AEE, 0xE34D, + 0x7AEF, 0xBADD, 0x7AF6, 0xC476, 0x7AF7, 0xF4A5, 0x7AF9, 0xA6CB, 0x7AFA, 0xAAC7, 0x7AFB, 0xCDA7, 0x7AFD, 0xACF2, 0x7AFF, 0xACF1, + 0x7B00, 0xD042, 0x7B01, 0xD043, 0x7B04, 0xD340, 0x7B05, 0xD342, 0x7B06, 0xAFB9, 0x7B08, 0xD344, 0x7B09, 0xD347, 0x7B0A, 0xD345, + 0x7B0E, 0xD346, 0x7B0F, 0xD343, 0x7B10, 0xD2FE, 0x7B11, 0xAFBA, 0x7B12, 0xD348, 0x7B13, 0xD341, 0x7B18, 0xD6D3, 0x7B19, 0xB2C6, + 0x7B1A, 0xD6DC, 0x7B1B, 0xB2C3, 0x7B1D, 0xD6D5, 0x7B1E, 0xB2C7, 0x7B20, 0xB2C1, 0x7B22, 0xD6D0, 0x7B23, 0xD6DD, 0x7B24, 0xD6D1, + 0x7B25, 0xD6CE, 0x7B26, 0xB2C5, 0x7B28, 0xB2C2, 0x7B2A, 0xD6D4, 0x7B2B, 0xD6D7, 0x7B2C, 0xB2C4, 0x7B2D, 0xD6D8, 0x7B2E, 0xB2C8, + 0x7B2F, 0xD6D9, 0x7B30, 0xD6CF, 0x7B31, 0xD6D6, 0x7B32, 0xD6DA, 0x7B33, 0xD6D2, 0x7B34, 0xD6CD, 0x7B35, 0xD6CB, 0x7B38, 0xD6DB, + 0x7B3B, 0xDADF, 0x7B40, 0xDAE4, 0x7B44, 0xDAE0, 0x7B45, 0xDAE6, 0x7B46, 0xB5A7, 0x7B47, 0xD6CC, 0x7B48, 0xDAE1, 0x7B49, 0xB5A5, + 0x7B4A, 0xDADE, 0x7B4B, 0xB5AC, 0x7B4C, 0xDAE2, 0x7B4D, 0xB5AB, 0x7B4E, 0xDAE3, 0x7B4F, 0xB5AD, 0x7B50, 0xB5A8, 0x7B51, 0xB5AE, + 0x7B52, 0xB5A9, 0x7B54, 0xB5AA, 0x7B56, 0xB5A6, 0x7B58, 0xDAE5, 0x7B60, 0xB861, 0x7B61, 0xDF50, 0x7B63, 0xDF53, 0x7B64, 0xDF47, + 0x7B65, 0xDF4C, 0x7B66, 0xDF46, 0x7B67, 0xB863, 0x7B69, 0xDF4A, 0x7B6D, 0xDF48, 0x7B6E, 0xB862, 0x7B70, 0xDF4F, 0x7B71, 0xDF4E, + 0x7B72, 0xDF4B, 0x7B73, 0xDF4D, 0x7B74, 0xDF49, 0x7B75, 0xBAE1, 0x7B76, 0xDF52, 0x7B77, 0xB85F, 0x7B78, 0xDF51, 0x7B82, 0xE35D, + 0x7B84, 0xBAE8, 0x7B85, 0xE358, 0x7B87, 0xBAE7, 0x7B88, 0xE34E, 0x7B8A, 0xE350, 0x7B8B, 0xBAE0, 0x7B8C, 0xE355, 0x7B8D, 0xE354, + 0x7B8E, 0xE357, 0x7B8F, 0xBAE5, 0x7B90, 0xE352, 0x7B91, 0xE351, 0x7B94, 0xBAE4, 0x7B95, 0xBADF, 0x7B96, 0xE353, 0x7B97, 0xBAE2, + 0x7B98, 0xE359, 0x7B99, 0xE35B, 0x7B9B, 0xE356, 0x7B9C, 0xE34F, 0x7B9D, 0xBAE3, 0x7BA0, 0xBD69, 0x7BA1, 0xBADE, 0x7BA4, 0xE35C, + 0x7BAC, 0xE6D9, 0x7BAD, 0xBD62, 0x7BAF, 0xE6DB, 0x7BB1, 0xBD63, 0x7BB4, 0xBD65, 0x7BB5, 0xE6DE, 0x7BB7, 0xE6D6, 0x7BB8, 0xBAE6, + 0x7BB9, 0xE6DC, 0x7BBE, 0xE6D8, 0x7BC0, 0xB860, 0x7BC1, 0xBD68, 0x7BC4, 0xBD64, 0x7BC6, 0xBD66, 0x7BC7, 0xBD67, 0x7BC9, 0xBF76, + 0x7BCA, 0xE6DD, 0x7BCB, 0xE6D7, 0x7BCC, 0xBD6A, 0x7BCE, 0xE6DA, 0x7BD4, 0xEAC0, 0x7BD5, 0xEABB, 0x7BD8, 0xEAC5, 0x7BD9, 0xBF74, + 0x7BDA, 0xEABD, 0x7BDB, 0xBF78, 0x7BDC, 0xEAC3, 0x7BDD, 0xEABA, 0x7BDE, 0xEAB7, 0x7BDF, 0xEAC6, 0x7BE0, 0xC151, 0x7BE1, 0xBF79, + 0x7BE2, 0xEAC2, 0x7BE3, 0xEAB8, 0x7BE4, 0xBF77, 0x7BE5, 0xEABC, 0x7BE6, 0xBF7B, 0x7BE7, 0xEAB9, 0x7BE8, 0xEABE, 0x7BE9, 0xBF7A, + 0x7BEA, 0xEAC1, 0x7BEB, 0xEAC4, 0x7BF0, 0xEDCB, 0x7BF1, 0xEDCC, 0x7BF2, 0xEDBC, 0x7BF3, 0xEDC3, 0x7BF4, 0xEDC1, 0x7BF7, 0xC14F, + 0x7BF8, 0xEDC8, 0x7BF9, 0xEABF, 0x7BFB, 0xEDBF, 0x7BFD, 0xEDC9, 0x7BFE, 0xC14E, 0x7BFF, 0xEDBE, 0x7C00, 0xEDBD, 0x7C01, 0xEDC7, + 0x7C02, 0xEDC4, 0x7C03, 0xEDC6, 0x7C05, 0xEDBA, 0x7C06, 0xEDCA, 0x7C07, 0xC14C, 0x7C09, 0xEDC5, 0x7C0A, 0xEDCE, 0x7C0B, 0xEDC2, + 0x7C0C, 0xC150, 0x7C0D, 0xC14D, 0x7C0E, 0xEDC0, 0x7C0F, 0xEDBB, 0x7C10, 0xEDCD, 0x7C11, 0xBF75, 0x7C19, 0xF063, 0x7C1C, 0xF061, + 0x7C1D, 0xF067, 0x7C1E, 0xC2B0, 0x7C1F, 0xF065, 0x7C20, 0xF064, 0x7C21, 0xC2B2, 0x7C22, 0xF06A, 0x7C23, 0xC2B1, 0x7C25, 0xF06B, + 0x7C26, 0xF068, 0x7C27, 0xC2AE, 0x7C28, 0xF069, 0x7C29, 0xF062, 0x7C2A, 0xC2AF, 0x7C2B, 0xC2AD, 0x7C2C, 0xF2AB, 0x7C2D, 0xF066, + 0x7C30, 0xF06C, 0x7C33, 0xF2A8, 0x7C37, 0xC3B2, 0x7C38, 0xC3B0, 0x7C39, 0xF2AA, 0x7C3B, 0xF2AC, 0x7C3C, 0xF2A9, 0x7C3D, 0xC3B1, + 0x7C3E, 0xC3AE, 0x7C3F, 0xC3AF, 0x7C40, 0xC3B3, 0x7C43, 0xC478, 0x7C45, 0xF4AA, 0x7C47, 0xF4A9, 0x7C48, 0xF4A7, 0x7C49, 0xF4A6, + 0x7C4A, 0xF4A8, 0x7C4C, 0xC477, 0x7C4D, 0xC479, 0x7C50, 0xC4F0, 0x7C53, 0xF5E5, 0x7C54, 0xF5E4, 0x7C57, 0xF6FA, 0x7C59, 0xF6FC, + 0x7C5A, 0xF6FE, 0x7C5B, 0xF6FD, 0x7C5C, 0xF6FB, 0x7C5F, 0xC5A3, 0x7C60, 0xC5A2, 0x7C63, 0xC5D3, 0x7C64, 0xC5D2, 0x7C65, 0xC5D4, + 0x7C66, 0xF7ED, 0x7C67, 0xF7EC, 0x7C69, 0xF8FB, 0x7C6A, 0xF8B8, 0x7C6B, 0xF8FC, 0x7C6C, 0xC658, 0x7C6E, 0xC659, 0x7C6F, 0xF96D, + 0x7C72, 0xC67E, 0x7C73, 0xA6CC, 0x7C75, 0xCDA8, 0x7C78, 0xD045, 0x7C79, 0xD046, 0x7C7A, 0xD044, 0x7C7D, 0xACF3, 0x7C7F, 0xD047, + 0x7C80, 0xD048, 0x7C81, 0xD049, 0x7C84, 0xD349, 0x7C85, 0xD34F, 0x7C88, 0xD34D, 0x7C89, 0xAFBB, 0x7C8A, 0xD34B, 0x7C8C, 0xD34C, + 0x7C8D, 0xD34E, 0x7C91, 0xD34A, 0x7C92, 0xB2C9, 0x7C94, 0xD6DE, 0x7C95, 0xB2CB, 0x7C96, 0xD6E0, 0x7C97, 0xB2CA, 0x7C98, 0xD6DF, + 0x7C9E, 0xDAE8, 0x7C9F, 0xB5AF, 0x7CA1, 0xDAEA, 0x7CA2, 0xDAE7, 0x7CA3, 0xD6E1, 0x7CA5, 0xB5B0, 0x7CA7, 0xF9DB, 0x7CA8, 0xDAE9, + 0x7CAF, 0xDF56, 0x7CB1, 0xB864, 0x7CB2, 0xDF54, 0x7CB3, 0xB865, 0x7CB4, 0xDF55, 0x7CB5, 0xB866, 0x7CB9, 0xBAE9, 0x7CBA, 0xE361, + 0x7CBB, 0xE35E, 0x7CBC, 0xE360, 0x7CBD, 0xBAEA, 0x7CBE, 0xBAEB, 0x7CBF, 0xE35F, 0x7CC5, 0xE6DF, 0x7CC8, 0xE6E0, 0x7CCA, 0xBD6B, + 0x7CCB, 0xE6E2, 0x7CCC, 0xE6E1, 0x7CCE, 0xA261, 0x7CD0, 0xEACA, 0x7CD1, 0xEACB, 0x7CD2, 0xEAC7, 0x7CD4, 0xEAC8, 0x7CD5, 0xBF7C, + 0x7CD6, 0xBF7D, 0x7CD7, 0xEAC9, 0x7CD9, 0xC157, 0x7CDC, 0xC153, 0x7CDD, 0xC158, 0x7CDE, 0xC154, 0x7CDF, 0xC156, 0x7CE0, 0xC152, + 0x7CE2, 0xC155, 0x7CE7, 0xC2B3, 0x7CE8, 0xEDCF, 0x7CEA, 0xF2AE, 0x7CEC, 0xF2AD, 0x7CEE, 0xF4AB, 0x7CEF, 0xC47A, 0x7CF0, 0xC47B, + 0x7CF1, 0xF741, 0x7CF2, 0xF5E6, 0x7CF4, 0xF740, 0x7CF6, 0xF8FD, 0x7CF7, 0xF9A4, 0x7CF8, 0xA6CD, 0x7CFB, 0xA874, 0x7CFD, 0xCDA9, + 0x7CFE, 0xAAC8, 0x7D00, 0xACF6, 0x7D01, 0xD04C, 0x7D02, 0xACF4, 0x7D03, 0xD04A, 0x7D04, 0xACF9, 0x7D05, 0xACF5, 0x7D06, 0xACFA, + 0x7D07, 0xACF8, 0x7D08, 0xD04B, 0x7D09, 0xACF7, 0x7D0A, 0xAFBF, 0x7D0B, 0xAFBE, 0x7D0C, 0xD35A, 0x7D0D, 0xAFC7, 0x7D0E, 0xD353, + 0x7D0F, 0xD359, 0x7D10, 0xAFC3, 0x7D11, 0xD352, 0x7D12, 0xD358, 0x7D13, 0xD356, 0x7D14, 0xAFC2, 0x7D15, 0xAFC4, 0x7D16, 0xD355, + 0x7D17, 0xAFBD, 0x7D18, 0xD354, 0x7D19, 0xAFC8, 0x7D1A, 0xAFC5, 0x7D1B, 0xAFC9, 0x7D1C, 0xAFC6, 0x7D1D, 0xD351, 0x7D1E, 0xD350, + 0x7D1F, 0xD357, 0x7D20, 0xAFC0, 0x7D21, 0xAFBC, 0x7D22, 0xAFC1, 0x7D28, 0xD6F0, 0x7D29, 0xD6E9, 0x7D2B, 0xB5B5, 0x7D2C, 0xD6E8, + 0x7D2E, 0xB2CF, 0x7D2F, 0xB2D6, 0x7D30, 0xB2D3, 0x7D31, 0xB2D9, 0x7D32, 0xB2D8, 0x7D33, 0xB2D4, 0x7D35, 0xD6E2, 0x7D36, 0xD6E5, + 0x7D38, 0xD6E4, 0x7D39, 0xB2D0, 0x7D3A, 0xD6E6, 0x7D3B, 0xD6EF, 0x7D3C, 0xB2D1, 0x7D3D, 0xD6E3, 0x7D3E, 0xD6EC, 0x7D3F, 0xD6ED, + 0x7D40, 0xB2D2, 0x7D41, 0xD6EA, 0x7D42, 0xB2D7, 0x7D43, 0xB2CD, 0x7D44, 0xB2D5, 0x7D45, 0xD6E7, 0x7D46, 0xB2CC, 0x7D47, 0xD6EB, + 0x7D4A, 0xD6EE, 0x7D4E, 0xDAFB, 0x7D4F, 0xDAF2, 0x7D50, 0xB5B2, 0x7D51, 0xDAF9, 0x7D52, 0xDAF6, 0x7D53, 0xDAEE, 0x7D54, 0xDAF7, + 0x7D55, 0xB5B4, 0x7D56, 0xDAEF, 0x7D58, 0xDAEB, 0x7D5B, 0xB86C, 0x7D5C, 0xDAF4, 0x7D5E, 0xB5B1, 0x7D5F, 0xDAFA, 0x7D61, 0xB5B8, + 0x7D62, 0xB5BA, 0x7D63, 0xDAED, 0x7D66, 0xB5B9, 0x7D67, 0xDAF0, 0x7D68, 0xB5B3, 0x7D69, 0xDAF8, 0x7D6A, 0xDAF1, 0x7D6B, 0xDAF5, + 0x7D6D, 0xDAF3, 0x7D6E, 0xB5B6, 0x7D6F, 0xDAEC, 0x7D70, 0xB5BB, 0x7D71, 0xB2CE, 0x7D72, 0xB5B7, 0x7D73, 0xB5BC, 0x7D79, 0xB868, + 0x7D7A, 0xDF5D, 0x7D7B, 0xDF5F, 0x7D7C, 0xDF61, 0x7D7D, 0xDF65, 0x7D7F, 0xDF5B, 0x7D80, 0xDF59, 0x7D81, 0xB86A, 0x7D83, 0xDF60, + 0x7D84, 0xDF64, 0x7D85, 0xDF5C, 0x7D86, 0xDF58, 0x7D88, 0xDF57, 0x7D8C, 0xDF62, 0x7D8D, 0xDF5A, 0x7D8E, 0xDF5E, 0x7D8F, 0xB86B, + 0x7D91, 0xB869, 0x7D92, 0xDF66, 0x7D93, 0xB867, 0x7D94, 0xDF63, 0x7D96, 0xE372, 0x7D9C, 0xBAEE, 0x7D9D, 0xE36A, 0x7D9E, 0xBD78, + 0x7D9F, 0xE374, 0x7DA0, 0xBAF1, 0x7DA1, 0xE378, 0x7DA2, 0xBAF7, 0x7DA3, 0xE365, 0x7DA6, 0xE375, 0x7DA7, 0xE362, 0x7DA9, 0xE377, + 0x7DAA, 0xE366, 0x7DAC, 0xBAFE, 0x7DAD, 0xBAFB, 0x7DAE, 0xE376, 0x7DAF, 0xE370, 0x7DB0, 0xBAED, 0x7DB1, 0xBAF5, 0x7DB2, 0xBAF4, + 0x7DB4, 0xBAF3, 0x7DB5, 0xBAF9, 0x7DB7, 0xE363, 0x7DB8, 0xBAFA, 0x7DB9, 0xE371, 0x7DBA, 0xBAF6, 0x7DBB, 0xBAEC, 0x7DBC, 0xE373, + 0x7DBD, 0xBAEF, 0x7DBE, 0xBAF0, 0x7DBF, 0xBAF8, 0x7DC0, 0xE368, 0x7DC1, 0xE367, 0x7DC2, 0xE364, 0x7DC4, 0xE36C, 0x7DC5, 0xE369, + 0x7DC6, 0xE36D, 0x7DC7, 0xBAFD, 0x7DC9, 0xE379, 0x7DCA, 0xBAF2, 0x7DCB, 0xE36E, 0x7DCC, 0xE36F, 0x7DCE, 0xE36B, 0x7DD2, 0xBAFC, + 0x7DD7, 0xE6E7, 0x7DD8, 0xBD70, 0x7DD9, 0xBD79, 0x7DDA, 0xBD75, 0x7DDB, 0xE6E4, 0x7DDD, 0xBD72, 0x7DDE, 0xBD76, 0x7DDF, 0xE6F0, + 0x7DE0, 0xBD6C, 0x7DE1, 0xE6E8, 0x7DE3, 0xBD74, 0x7DE6, 0xE6EB, 0x7DE7, 0xE6E6, 0x7DE8, 0xBD73, 0x7DE9, 0xBD77, 0x7DEA, 0xE6E5, + 0x7DEC, 0xBD71, 0x7DEE, 0xE6EF, 0x7DEF, 0xBD6E, 0x7DF0, 0xE6EE, 0x7DF1, 0xE6ED, 0x7DF2, 0xBD7A, 0x7DF3, 0xE572, 0x7DF4, 0xBD6D, + 0x7DF6, 0xE6EC, 0x7DF7, 0xE6E3, 0x7DF9, 0xBD7B, 0x7DFA, 0xE6EA, 0x7DFB, 0xBD6F, 0x7E03, 0xE6E9, 0x7E08, 0xBFA2, 0x7E09, 0xBFA7, + 0x7E0A, 0xBF7E, 0x7E0B, 0xEAD8, 0x7E0C, 0xEACF, 0x7E0D, 0xEADB, 0x7E0E, 0xEAD3, 0x7E0F, 0xEAD9, 0x7E10, 0xBFA8, 0x7E11, 0xBFA1, + 0x7E12, 0xEACC, 0x7E13, 0xEAD2, 0x7E14, 0xEADC, 0x7E15, 0xEAD5, 0x7E16, 0xEADA, 0x7E17, 0xEACE, 0x7E1A, 0xEAD6, 0x7E1B, 0xBFA3, + 0x7E1C, 0xEAD4, 0x7E1D, 0xBFA6, 0x7E1E, 0xBFA5, 0x7E1F, 0xEAD0, 0x7E20, 0xEAD1, 0x7E21, 0xEACD, 0x7E22, 0xEAD7, 0x7E23, 0xBFA4, + 0x7E24, 0xEADE, 0x7E25, 0xEADD, 0x7E29, 0xEDDA, 0x7E2A, 0xEDD6, 0x7E2B, 0xC15F, 0x7E2D, 0xEDD0, 0x7E2E, 0xC159, 0x7E2F, 0xC169, + 0x7E30, 0xEDDC, 0x7E31, 0xC161, 0x7E32, 0xC15D, 0x7E33, 0xEDD3, 0x7E34, 0xC164, 0x7E35, 0xC167, 0x7E36, 0xEDDE, 0x7E37, 0xC15C, + 0x7E38, 0xEDD5, 0x7E39, 0xC165, 0x7E3A, 0xEDE0, 0x7E3B, 0xEDDD, 0x7E3C, 0xEDD1, 0x7E3D, 0xC160, 0x7E3E, 0xC15A, 0x7E3F, 0xC168, + 0x7E40, 0xEDD8, 0x7E41, 0xC163, 0x7E42, 0xEDD2, 0x7E43, 0xC15E, 0x7E44, 0xEDDF, 0x7E45, 0xC162, 0x7E46, 0xC15B, 0x7E47, 0xEDD9, + 0x7E48, 0xC166, 0x7E49, 0xEDD7, 0x7E4C, 0xEDDB, 0x7E50, 0xF06E, 0x7E51, 0xF074, 0x7E52, 0xC2B9, 0x7E53, 0xF077, 0x7E54, 0xC2B4, + 0x7E55, 0xC2B5, 0x7E56, 0xF06F, 0x7E57, 0xF076, 0x7E58, 0xF071, 0x7E59, 0xC2BA, 0x7E5A, 0xC2B7, 0x7E5C, 0xF06D, 0x7E5E, 0xC2B6, + 0x7E5F, 0xF073, 0x7E60, 0xF075, 0x7E61, 0xC2B8, 0x7E62, 0xF072, 0x7E63, 0xF070, 0x7E68, 0xF2B8, 0x7E69, 0xC3B7, 0x7E6A, 0xC3B8, + 0x7E6B, 0xC3B4, 0x7E6D, 0xC3B5, 0x7E6F, 0xF2B4, 0x7E70, 0xF2B2, 0x7E72, 0xF2B6, 0x7E73, 0xC3BA, 0x7E74, 0xF2B7, 0x7E75, 0xF2B0, + 0x7E76, 0xF2AF, 0x7E77, 0xF2B3, 0x7E78, 0xF2B1, 0x7E79, 0xC3B6, 0x7E7A, 0xF2B5, 0x7E7B, 0xF4AC, 0x7E7C, 0xC47E, 0x7E7D, 0xC47D, + 0x7E7E, 0xF4AD, 0x7E80, 0xF4AF, 0x7E81, 0xF4AE, 0x7E82, 0xC4A1, 0x7E86, 0xF5EB, 0x7E87, 0xF5E8, 0x7E88, 0xF5E9, 0x7E8A, 0xF5E7, + 0x7E8B, 0xF5EA, 0x7E8C, 0xC4F2, 0x7E8D, 0xF5EC, 0x7E8F, 0xC4F1, 0x7E91, 0xF742, 0x7E93, 0xC5D5, 0x7E94, 0xC5D7, 0x7E95, 0xF7EE, + 0x7E96, 0xC5D6, 0x7E97, 0xF8B9, 0x7E98, 0xF940, 0x7E99, 0xF942, 0x7E9A, 0xF8FE, 0x7E9B, 0xF941, 0x7E9C, 0xC66C, 0x7F36, 0xA6CE, + 0x7F38, 0xACFB, 0x7F39, 0xD26F, 0x7F3A, 0xAFCA, 0x7F3D, 0xB2DA, 0x7F3E, 0xDAFC, 0x7F3F, 0xDAFD, 0x7F43, 0xEADF, 0x7F44, 0xC16A, + 0x7F45, 0xEDE1, 0x7F48, 0xC2BB, 0x7F4A, 0xF2BA, 0x7F4B, 0xF2B9, 0x7F4C, 0xC4A2, 0x7F4D, 0xF5ED, 0x7F4F, 0xF743, 0x7F50, 0xC5F8, + 0x7F51, 0xCA49, 0x7F54, 0xAAC9, 0x7F55, 0xA875, 0x7F58, 0xD04D, 0x7F5B, 0xD360, 0x7F5C, 0xD35B, 0x7F5D, 0xD35F, 0x7F5E, 0xD35D, + 0x7F5F, 0xAFCB, 0x7F60, 0xD35E, 0x7F61, 0xD35C, 0x7F63, 0xD6F1, 0x7F65, 0xDAFE, 0x7F66, 0xDB40, 0x7F67, 0xDF69, 0x7F68, 0xDF6A, + 0x7F69, 0xB86E, 0x7F6A, 0xB86F, 0x7F6B, 0xDF68, 0x7F6C, 0xDF6B, 0x7F6D, 0xDF67, 0x7F6E, 0xB86D, 0x7F70, 0xBB40, 0x7F72, 0xB870, + 0x7F73, 0xE37A, 0x7F75, 0xBD7C, 0x7F76, 0xE6F1, 0x7F77, 0xBD7D, 0x7F79, 0xBFA9, 0x7F7A, 0xEAE2, 0x7F7B, 0xEAE0, 0x7F7C, 0xEAE1, + 0x7F7D, 0xEDE4, 0x7F7E, 0xEDE3, 0x7F7F, 0xEDE2, 0x7F83, 0xF2BB, 0x7F85, 0xC3B9, 0x7F86, 0xF2BC, 0x7F87, 0xF744, 0x7F88, 0xC5F9, + 0x7F89, 0xF8BA, 0x7F8A, 0xA6CF, 0x7F8B, 0xAACB, 0x7F8C, 0xAACA, 0x7F8D, 0xD04F, 0x7F8E, 0xACFC, 0x7F91, 0xD04E, 0x7F92, 0xD362, + 0x7F94, 0xAFCC, 0x7F95, 0xD6F2, 0x7F96, 0xD361, 0x7F9A, 0xB2DC, 0x7F9B, 0xD6F5, 0x7F9C, 0xD6F3, 0x7F9D, 0xD6F4, 0x7F9E, 0xB2DB, + 0x7FA0, 0xDB42, 0x7FA1, 0xDB43, 0x7FA2, 0xDB41, 0x7FA4, 0xB873, 0x7FA5, 0xDF6D, 0x7FA6, 0xDF6C, 0x7FA7, 0xDF6E, 0x7FA8, 0xB872, + 0x7FA9, 0xB871, 0x7FAC, 0xE6F2, 0x7FAD, 0xE6F4, 0x7FAF, 0xBD7E, 0x7FB0, 0xE6F3, 0x7FB1, 0xEAE3, 0x7FB2, 0xBFAA, 0x7FB3, 0xF079, + 0x7FB5, 0xF078, 0x7FB6, 0xC3BB, 0x7FB7, 0xF2BD, 0x7FB8, 0xC3BD, 0x7FB9, 0xC3BC, 0x7FBA, 0xF4B0, 0x7FBB, 0xF5EE, 0x7FBC, 0xC4F3, + 0x7FBD, 0xA6D0, 0x7FBE, 0xD050, 0x7FBF, 0xACFD, 0x7FC0, 0xD365, 0x7FC1, 0xAFCE, 0x7FC2, 0xD364, 0x7FC3, 0xD363, 0x7FC5, 0xAFCD, + 0x7FC7, 0xD6FB, 0x7FC9, 0xD6FD, 0x7FCA, 0xD6F6, 0x7FCB, 0xD6F7, 0x7FCC, 0xB2DD, 0x7FCD, 0xD6F8, 0x7FCE, 0xB2DE, 0x7FCF, 0xD6FC, + 0x7FD0, 0xD6F9, 0x7FD1, 0xD6FA, 0x7FD2, 0xB2DF, 0x7FD4, 0xB5BE, 0x7FD5, 0xB5BF, 0x7FD7, 0xDB44, 0x7FDB, 0xDF6F, 0x7FDC, 0xDF70, + 0x7FDE, 0xE37E, 0x7FDF, 0xBB43, 0x7FE0, 0xBB41, 0x7FE1, 0xBB42, 0x7FE2, 0xE37B, 0x7FE3, 0xE37C, 0x7FE5, 0xE37D, 0x7FE6, 0xE6F9, + 0x7FE8, 0xE6FA, 0x7FE9, 0xBDA1, 0x7FEA, 0xE6F7, 0x7FEB, 0xE6F6, 0x7FEC, 0xE6F8, 0x7FED, 0xE6F5, 0x7FEE, 0xBFAD, 0x7FEF, 0xEAE4, + 0x7FF0, 0xBFAB, 0x7FF1, 0xBFAC, 0x7FF2, 0xEDE6, 0x7FF3, 0xC16B, 0x7FF4, 0xEDE5, 0x7FF5, 0xEFA8, 0x7FF7, 0xF07A, 0x7FF8, 0xF07B, + 0x7FF9, 0xC2BC, 0x7FFB, 0xC2BD, 0x7FFC, 0xC16C, 0x7FFD, 0xF2BE, 0x7FFE, 0xF2BF, 0x7FFF, 0xF4B1, 0x8000, 0xC4A3, 0x8001, 0xA6D1, + 0x8003, 0xA6D2, 0x8004, 0xACFE, 0x8005, 0xAACC, 0x8006, 0xAFCF, 0x8007, 0xD051, 0x800B, 0xB5C0, 0x800C, 0xA6D3, 0x800D, 0xAD41, + 0x800E, 0xD052, 0x800F, 0xD053, 0x8010, 0xAD40, 0x8011, 0xAD42, 0x8012, 0xA6D4, 0x8014, 0xD054, 0x8015, 0xAFD1, 0x8016, 0xD366, + 0x8017, 0xAFD3, 0x8018, 0xAFD0, 0x8019, 0xAFD2, 0x801B, 0xD741, 0x801C, 0xB2E0, 0x801E, 0xD740, 0x801F, 0xD6FE, 0x8021, 0xDF71, + 0x8024, 0xE3A1, 0x8026, 0xBDA2, 0x8028, 0xBFAE, 0x8029, 0xEAE6, 0x802A, 0xEAE5, 0x802C, 0xEDE7, 0x8030, 0xF5EF, 0x8033, 0xA6D5, + 0x8034, 0xCB73, 0x8035, 0xCDAA, 0x8036, 0xAD43, 0x8037, 0xD055, 0x8039, 0xD368, 0x803D, 0xAFD4, 0x803E, 0xD367, 0x803F, 0xAFD5, + 0x8043, 0xD743, 0x8046, 0xB2E2, 0x8047, 0xD742, 0x8048, 0xD744, 0x804A, 0xB2E1, 0x804F, 0xDB46, 0x8050, 0xDB47, 0x8051, 0xDB45, + 0x8052, 0xB5C1, 0x8056, 0xB874, 0x8058, 0xB875, 0x805A, 0xBB45, 0x805C, 0xE3A3, 0x805D, 0xE3A2, 0x805E, 0xBB44, 0x8064, 0xE6FB, + 0x8067, 0xE6FC, 0x806C, 0xEAE7, 0x806F, 0xC170, 0x8070, 0xC16F, 0x8071, 0xC16D, 0x8072, 0xC16E, 0x8073, 0xC171, 0x8075, 0xF07C, + 0x8076, 0xC2BF, 0x8077, 0xC2BE, 0x8078, 0xF2C0, 0x8079, 0xF4B2, 0x807D, 0xC5A5, 0x807E, 0xC5A4, 0x807F, 0xA6D6, 0x8082, 0xD1FB, + 0x8084, 0xB877, 0x8085, 0xB5C2, 0x8086, 0xB876, 0x8087, 0xBB46, 0x8089, 0xA6D7, 0x808A, 0xC9A9, 0x808B, 0xA6D8, 0x808C, 0xA6D9, + 0x808F, 0xCDAB, 0x8090, 0xCB76, 0x8092, 0xCB77, 0x8093, 0xA877, 0x8095, 0xCB74, 0x8096, 0xA876, 0x8098, 0xA879, 0x8099, 0xCB75, + 0x809A, 0xA87B, 0x809B, 0xA87A, 0x809C, 0xCB78, 0x809D, 0xA878, 0x80A1, 0xAAD1, 0x80A2, 0xAACF, 0x80A3, 0xCDAD, 0x80A5, 0xAACE, + 0x80A9, 0xAAD3, 0x80AA, 0xAAD5, 0x80AB, 0xAAD2, 0x80AD, 0xCDB0, 0x80AE, 0xCDAC, 0x80AF, 0xAAD6, 0x80B1, 0xAAD0, 0x80B2, 0xA87C, + 0x80B4, 0xAAD4, 0x80B5, 0xCDAF, 0x80B8, 0xCDAE, 0x80BA, 0xAACD, 0x80C2, 0xD05B, 0x80C3, 0xAD47, 0x80C4, 0xAD48, 0x80C5, 0xD05D, + 0x80C7, 0xD057, 0x80C8, 0xD05A, 0x80C9, 0xD063, 0x80CA, 0xD061, 0x80CC, 0xAD49, 0x80CD, 0xD067, 0x80CE, 0xAD4C, 0x80CF, 0xD064, + 0x80D0, 0xD05C, 0x80D1, 0xD059, 0x80D4, 0xDB49, 0x80D5, 0xD062, 0x80D6, 0xAD44, 0x80D7, 0xD065, 0x80D8, 0xD056, 0x80D9, 0xD05F, + 0x80DA, 0xAD46, 0x80DB, 0xAD4B, 0x80DC, 0xD060, 0x80DD, 0xAD4F, 0x80DE, 0xAD4D, 0x80E0, 0xD058, 0x80E1, 0xAD4A, 0x80E3, 0xD05E, + 0x80E4, 0xAD4E, 0x80E5, 0xAD45, 0x80E6, 0xD066, 0x80ED, 0xAFDA, 0x80EF, 0xAFE3, 0x80F0, 0xAFD8, 0x80F1, 0xAFD6, 0x80F2, 0xD36A, + 0x80F3, 0xAFDE, 0x80F4, 0xAFDB, 0x80F5, 0xD36C, 0x80F8, 0xAFDD, 0x80F9, 0xD36B, 0x80FA, 0xD369, 0x80FB, 0xD36E, 0x80FC, 0xAFE2, + 0x80FD, 0xAFE0, 0x80FE, 0xDB48, 0x8100, 0xD36F, 0x8101, 0xD36D, 0x8102, 0xAFD7, 0x8105, 0xAFD9, 0x8106, 0xAFDC, 0x8108, 0xAFDF, + 0x810A, 0xAFE1, 0x8115, 0xD74E, 0x8116, 0xB2E4, 0x8118, 0xD745, 0x8119, 0xD747, 0x811B, 0xD748, 0x811D, 0xD750, 0x811E, 0xD74C, + 0x811F, 0xD74A, 0x8121, 0xD74D, 0x8122, 0xD751, 0x8123, 0xB2E5, 0x8124, 0xB2E9, 0x8125, 0xD746, 0x8127, 0xD74F, 0x8129, 0xB2E7, + 0x812B, 0xB2E6, 0x812C, 0xD74B, 0x812D, 0xD749, 0x812F, 0xB2E3, 0x8130, 0xB2E8, 0x8139, 0xB5C8, 0x813A, 0xDB51, 0x813D, 0xDB4F, + 0x813E, 0xB5CA, 0x8143, 0xDB4A, 0x8144, 0xDFA1, 0x8146, 0xB5C9, 0x8147, 0xDB4E, 0x814A, 0xDB4B, 0x814B, 0xB5C5, 0x814C, 0xB5CB, + 0x814D, 0xDB50, 0x814E, 0xB5C7, 0x814F, 0xDB4D, 0x8150, 0xBB47, 0x8151, 0xB5C6, 0x8152, 0xDB4C, 0x8153, 0xB5CC, 0x8154, 0xB5C4, + 0x8155, 0xB5C3, 0x815B, 0xDF77, 0x815C, 0xDF75, 0x815E, 0xDF7B, 0x8160, 0xDF73, 0x8161, 0xDFA2, 0x8162, 0xDF78, 0x8164, 0xDF72, + 0x8165, 0xB87B, 0x8166, 0xB8A3, 0x8167, 0xDF7D, 0x8169, 0xDF76, 0x816B, 0xB87E, 0x816E, 0xB87C, 0x816F, 0xDF7E, 0x8170, 0xB879, + 0x8171, 0xB878, 0x8172, 0xDF79, 0x8173, 0xB87D, 0x8174, 0xB5CD, 0x8176, 0xDF7C, 0x8177, 0xDF74, 0x8178, 0xB87A, 0x8179, 0xB8A1, + 0x817A, 0xB8A2, 0x817F, 0xBB4C, 0x8180, 0xBB48, 0x8182, 0xBB4D, 0x8183, 0xE3A6, 0x8186, 0xE3A5, 0x8187, 0xE3A7, 0x8188, 0xBB4A, + 0x8189, 0xE3A4, 0x818A, 0xBB4B, 0x818B, 0xE3AA, 0x818C, 0xE3A9, 0x818D, 0xE3A8, 0x818F, 0xBB49, 0x8195, 0xE741, 0x8197, 0xE744, + 0x8198, 0xBDA8, 0x8199, 0xE743, 0x819A, 0xBDA7, 0x819B, 0xBDA3, 0x819C, 0xBDA4, 0x819D, 0xBDA5, 0x819E, 0xE740, 0x819F, 0xE6FE, + 0x81A0, 0xBDA6, 0x81A2, 0xE742, 0x81A3, 0xE6FD, 0x81A6, 0xEAE9, 0x81A7, 0xEAF3, 0x81A8, 0xBFB1, 0x81A9, 0xBFB0, 0x81AB, 0xEAED, + 0x81AC, 0xEAEF, 0x81AE, 0xEAEA, 0x81B0, 0xEAEE, 0x81B1, 0xEAE8, 0x81B2, 0xEAF1, 0x81B3, 0xBFAF, 0x81B4, 0xEAF0, 0x81B5, 0xEAEC, + 0x81B7, 0xEAF2, 0x81B9, 0xEAEB, 0x81BA, 0xC174, 0x81BB, 0xEDE8, 0x81BC, 0xEDEE, 0x81BD, 0xC178, 0x81BE, 0xC17A, 0x81BF, 0xC177, + 0x81C0, 0xC176, 0x81C2, 0xC175, 0x81C3, 0xC173, 0x81C4, 0xEDE9, 0x81C5, 0xEDEC, 0x81C6, 0xC172, 0x81C7, 0xEDED, 0x81C9, 0xC179, + 0x81CA, 0xEDEB, 0x81CC, 0xEDEA, 0x81CD, 0xC2C0, 0x81CF, 0xC2C1, 0x81D0, 0xF0A1, 0x81D1, 0xF07D, 0x81D2, 0xF07E, 0x81D5, 0xF2C2, + 0x81D7, 0xF2C1, 0x81D8, 0xC3BE, 0x81D9, 0xF4B4, 0x81DA, 0xC4A4, 0x81DB, 0xF4B3, 0x81DD, 0xF5F0, 0x81DE, 0xF745, 0x81DF, 0xC5A6, + 0x81E0, 0xF943, 0x81E1, 0xF944, 0x81E2, 0xC5D8, 0x81E3, 0xA6DA, 0x81E5, 0xAAD7, 0x81E6, 0xDB52, 0x81E7, 0xBB4E, 0x81E8, 0xC17B, + 0x81E9, 0xEDEF, 0x81EA, 0xA6DB, 0x81EC, 0xAFE5, 0x81ED, 0xAFE4, 0x81EE, 0xDB53, 0x81F2, 0xEAF4, 0x81F3, 0xA6DC, 0x81F4, 0xAD50, + 0x81F7, 0xDB54, 0x81F8, 0xDB55, 0x81F9, 0xDB56, 0x81FA, 0xBB4F, 0x81FB, 0xBFB2, 0x81FC, 0xA6DD, 0x81FE, 0xAAD8, 0x81FF, 0xD068, + 0x8200, 0xAFE6, 0x8201, 0xD370, 0x8202, 0xB2EA, 0x8204, 0xDB57, 0x8205, 0xB8A4, 0x8207, 0xBB50, 0x8208, 0xBFB3, 0x8209, 0xC17C, + 0x820A, 0xC2C2, 0x820B, 0xF4B5, 0x820C, 0xA6DE, 0x820D, 0xAAD9, 0x8210, 0xAFE7, 0x8211, 0xD752, 0x8212, 0xB5CE, 0x8214, 0xBB51, + 0x8215, 0xE3AB, 0x8216, 0xE745, 0x821B, 0xA6DF, 0x821C, 0xB5CF, 0x821D, 0xDFA3, 0x821E, 0xBB52, 0x821F, 0xA6E0, 0x8220, 0xCDB1, + 0x8221, 0xD069, 0x8222, 0xAD51, 0x8225, 0xD372, 0x8228, 0xAFEA, 0x822A, 0xAFE8, 0x822B, 0xAFE9, 0x822C, 0xAFEB, 0x822F, 0xD371, + 0x8232, 0xD757, 0x8233, 0xD754, 0x8234, 0xD756, 0x8235, 0xB2EB, 0x8236, 0xB2ED, 0x8237, 0xB2EC, 0x8238, 0xD753, 0x8239, 0xB2EE, + 0x823A, 0xD755, 0x823C, 0xDB58, 0x823D, 0xDB59, 0x823F, 0xDB5A, 0x8240, 0xDFA6, 0x8242, 0xDFA7, 0x8244, 0xDFA5, 0x8245, 0xDFA8, + 0x8247, 0xB8A5, 0x8249, 0xDFA4, 0x824B, 0xBB53, 0x824E, 0xE74A, 0x824F, 0xE746, 0x8250, 0xE749, 0x8251, 0xE74B, 0x8252, 0xE748, + 0x8253, 0xE747, 0x8255, 0xEAF5, 0x8256, 0xEAF6, 0x8257, 0xEAF7, 0x8258, 0xBFB4, 0x8259, 0xBFB5, 0x825A, 0xEDF1, 0x825B, 0xEDF0, + 0x825C, 0xEDF2, 0x825E, 0xF0A3, 0x825F, 0xF0A2, 0x8261, 0xF2C4, 0x8263, 0xF2C5, 0x8264, 0xF2C3, 0x8266, 0xC4A5, 0x8268, 0xF4B6, + 0x8269, 0xF4B7, 0x826B, 0xF746, 0x826C, 0xF7EF, 0x826D, 0xF8BB, 0x826E, 0xA6E1, 0x826F, 0xA87D, 0x8271, 0xC17D, 0x8272, 0xA6E2, + 0x8274, 0xD758, 0x8275, 0xDB5B, 0x8277, 0xC641, 0x8278, 0xCA4A, 0x827C, 0xCA4B, 0x827D, 0xCA4D, 0x827E, 0xA6E3, 0x827F, 0xCA4E, + 0x8280, 0xCA4C, 0x8283, 0xCBA2, 0x8284, 0xCBA3, 0x8285, 0xCB7B, 0x828A, 0xCBA1, 0x828B, 0xA8A1, 0x828D, 0xA8A2, 0x828E, 0xCB7C, + 0x828F, 0xCB7A, 0x8290, 0xCB79, 0x8291, 0xCB7D, 0x8292, 0xA87E, 0x8293, 0xCB7E, 0x8294, 0xD06A, 0x8298, 0xCDB6, 0x8299, 0xAADC, + 0x829A, 0xCDB5, 0x829B, 0xCDB7, 0x829D, 0xAADB, 0x829E, 0xCDBC, 0x829F, 0xAADF, 0x82A0, 0xCDB2, 0x82A1, 0xCDC0, 0x82A2, 0xCDC6, + 0x82A3, 0xAAE6, 0x82A4, 0xCDC3, 0x82A5, 0xAAE3, 0x82A7, 0xCDB9, 0x82A8, 0xCDBF, 0x82A9, 0xCDC1, 0x82AB, 0xCDB4, 0x82AC, 0xAAE2, + 0x82AD, 0xAADD, 0x82AE, 0xCDBA, 0x82AF, 0xAAE4, 0x82B0, 0xAAE7, 0x82B1, 0xAAE1, 0x82B3, 0xAADA, 0x82B4, 0xCDBE, 0x82B5, 0xCDB8, + 0x82B6, 0xCDC5, 0x82B7, 0xAAE9, 0x82B8, 0xAAE5, 0x82B9, 0xAAE0, 0x82BA, 0xCDBD, 0x82BB, 0xAFEC, 0x82BC, 0xCDBB, 0x82BD, 0xAADE, + 0x82BE, 0xAAE8, 0x82C0, 0xCDB3, 0x82C2, 0xCDC2, 0x82C3, 0xCDC4, 0x82D1, 0xAD62, 0x82D2, 0xAD5C, 0x82D3, 0xAD64, 0x82D4, 0xAD61, + 0x82D5, 0xD071, 0x82D6, 0xD074, 0x82D7, 0xAD5D, 0x82D9, 0xD06B, 0x82DB, 0xAD56, 0x82DC, 0xAD60, 0x82DE, 0xAD63, 0x82DF, 0xAD65, + 0x82E0, 0xD0A2, 0x82E1, 0xD077, 0x82E3, 0xAD55, 0x82E4, 0xD0A1, 0x82E5, 0xAD59, 0x82E6, 0xAD57, 0x82E7, 0xAD52, 0x82E8, 0xD06F, + 0x82EA, 0xD07E, 0x82EB, 0xD073, 0x82EC, 0xD076, 0x82ED, 0xD0A5, 0x82EF, 0xAD66, 0x82F0, 0xD07D, 0x82F1, 0xAD5E, 0x82F2, 0xD078, + 0x82F3, 0xD0A4, 0x82F4, 0xD075, 0x82F5, 0xD079, 0x82F6, 0xD07C, 0x82F9, 0xD06D, 0x82FA, 0xD0A3, 0x82FB, 0xD07B, 0x82FE, 0xD06C, + 0x8300, 0xD070, 0x8301, 0xAD5F, 0x8302, 0xAD5A, 0x8303, 0xAD53, 0x8304, 0xAD58, 0x8305, 0xAD54, 0x8306, 0xAD67, 0x8307, 0xD06E, + 0x8308, 0xD3A5, 0x8309, 0xAD5B, 0x830C, 0xD07A, 0x830D, 0xCE41, 0x8316, 0xD3A8, 0x8317, 0xAFFA, 0x8319, 0xD376, 0x831B, 0xD3A3, + 0x831C, 0xD37D, 0x831E, 0xD3B2, 0x8320, 0xD3AA, 0x8322, 0xD37E, 0x8324, 0xD3A9, 0x8325, 0xD378, 0x8326, 0xD37C, 0x8327, 0xD3B5, + 0x8328, 0xAFFD, 0x8329, 0xD3AD, 0x832A, 0xD3A4, 0x832B, 0xAFED, 0x832C, 0xD3B3, 0x832D, 0xD374, 0x832F, 0xD3AC, 0x8331, 0xAFFC, + 0x8332, 0xAFF7, 0x8333, 0xD373, 0x8334, 0xAFF5, 0x8335, 0xAFF4, 0x8336, 0xAFF9, 0x8337, 0xD3AB, 0x8338, 0xAFF1, 0x8339, 0xAFF8, + 0x833A, 0xD072, 0x833B, 0xDB5C, 0x833C, 0xD3A6, 0x833F, 0xD37A, 0x8340, 0xAFFB, 0x8341, 0xD37B, 0x8342, 0xD3A1, 0x8343, 0xAFFE, + 0x8344, 0xD375, 0x8345, 0xD3AF, 0x8347, 0xD3AE, 0x8348, 0xD3B6, 0x8349, 0xAFF3, 0x834A, 0xAFF0, 0x834B, 0xD3B4, 0x834C, 0xD3B0, + 0x834D, 0xD3A7, 0x834E, 0xD3A2, 0x834F, 0xAFF6, 0x8350, 0xAFF2, 0x8351, 0xD377, 0x8352, 0xAFEE, 0x8353, 0xD3B1, 0x8354, 0xAFEF, + 0x8356, 0xD379, 0x8373, 0xD75E, 0x8374, 0xD760, 0x8375, 0xD765, 0x8376, 0xD779, 0x8377, 0xB2FC, 0x8378, 0xB2F2, 0x837A, 0xD75D, + 0x837B, 0xB2FD, 0x837C, 0xB2FE, 0x837D, 0xD768, 0x837E, 0xD76F, 0x837F, 0xD775, 0x8381, 0xD762, 0x8383, 0xD769, 0x8386, 0xB340, + 0x8387, 0xD777, 0x8388, 0xD772, 0x8389, 0xB2FA, 0x838A, 0xB2F8, 0x838B, 0xD76E, 0x838C, 0xD76A, 0x838D, 0xD75C, 0x838E, 0xB2EF, + 0x838F, 0xD761, 0x8390, 0xD759, 0x8392, 0xB2F7, 0x8393, 0xB2F9, 0x8394, 0xD766, 0x8395, 0xD763, 0x8396, 0xB2F4, 0x8397, 0xD773, + 0x8398, 0xB2F1, 0x8399, 0xD764, 0x839A, 0xD77A, 0x839B, 0xD76C, 0x839D, 0xD76B, 0x839E, 0xB2F0, 0x83A0, 0xB2FB, 0x83A2, 0xB2F3, + 0x83A3, 0xD75A, 0x83A4, 0xD75F, 0x83A5, 0xD770, 0x83A6, 0xD776, 0x83A7, 0xB341, 0x83A8, 0xD75B, 0x83A9, 0xD767, 0x83AA, 0xD76D, + 0x83AB, 0xB2F6, 0x83AE, 0xD778, 0x83AF, 0xD771, 0x83B0, 0xD774, 0x83BD, 0xB2F5, 0x83BF, 0xDB6C, 0x83C0, 0xDB60, 0x83C1, 0xB5D7, + 0x83C2, 0xDB7D, 0x83C3, 0xDBA7, 0x83C4, 0xDBAA, 0x83C5, 0xB5D5, 0x83C6, 0xDB68, 0x83C7, 0xDBA3, 0x83C8, 0xDB69, 0x83C9, 0xDB77, + 0x83CA, 0xB5E2, 0x83CB, 0xDB73, 0x83CC, 0xB5DF, 0x83CE, 0xDB74, 0x83CF, 0xDB5D, 0x83D1, 0xDBA4, 0x83D4, 0xB5E8, 0x83D5, 0xDBA1, + 0x83D6, 0xDB75, 0x83D7, 0xDBAC, 0x83D8, 0xDB70, 0x83D9, 0xDFC8, 0x83DB, 0xDBAF, 0x83DC, 0xB5E6, 0x83DD, 0xDB6E, 0x83DE, 0xDB7A, + 0x83DF, 0xB5E9, 0x83E0, 0xB5D4, 0x83E1, 0xDB72, 0x83E2, 0xDBAD, 0x83E3, 0xDB6B, 0x83E4, 0xDB64, 0x83E5, 0xDB6F, 0x83E7, 0xDB63, + 0x83E8, 0xDB61, 0x83E9, 0xB5D0, 0x83EA, 0xDBA5, 0x83EB, 0xDB6A, 0x83EC, 0xDBA8, 0x83EE, 0xDBA9, 0x83EF, 0xB5D8, 0x83F0, 0xB5DD, + 0x83F1, 0xB5D9, 0x83F2, 0xB5E1, 0x83F3, 0xDB7E, 0x83F4, 0xB5DA, 0x83F5, 0xDB76, 0x83F6, 0xDB66, 0x83F8, 0xB5D2, 0x83F9, 0xDB5E, + 0x83FA, 0xDBA2, 0x83FB, 0xDBAB, 0x83FC, 0xDB65, 0x83FD, 0xB5E0, 0x83FE, 0xDBB0, 0x83FF, 0xDB71, 0x8401, 0xDB6D, 0x8403, 0xB5D1, + 0x8404, 0xB5E5, 0x8406, 0xDB7C, 0x8407, 0xB5E7, 0x8409, 0xDB78, 0x840A, 0xB5DC, 0x840B, 0xB5D6, 0x840C, 0xB5DE, 0x840D, 0xB5D3, + 0x840E, 0xB5E4, 0x840F, 0xDB79, 0x8410, 0xDB67, 0x8411, 0xDB7B, 0x8412, 0xDB62, 0x8413, 0xDBA6, 0x841B, 0xDBAE, 0x8423, 0xDB5F, + 0x8429, 0xDFC7, 0x842B, 0xDFDD, 0x842C, 0xB855, 0x842D, 0xDFCC, 0x842F, 0xDFCA, 0x8430, 0xDFB5, 0x8431, 0xB8A9, 0x8432, 0xDFC5, + 0x8433, 0xDFD9, 0x8434, 0xDFC1, 0x8435, 0xB8B1, 0x8436, 0xDFD8, 0x8437, 0xDFBF, 0x8438, 0xB5E3, 0x8439, 0xDFCF, 0x843A, 0xDFC0, + 0x843B, 0xDFD6, 0x843C, 0xB8B0, 0x843D, 0xB8A8, 0x843F, 0xDFAA, 0x8440, 0xDFB2, 0x8442, 0xDFCB, 0x8443, 0xDFC3, 0x8444, 0xDFDC, + 0x8445, 0xDFC6, 0x8446, 0xB8B6, 0x8447, 0xDFD7, 0x8449, 0xB8AD, 0x844B, 0xDFC9, 0x844C, 0xDFD1, 0x844D, 0xDFB6, 0x844E, 0xDFD0, + 0x8450, 0xDFE1, 0x8451, 0xDFB1, 0x8452, 0xDFD2, 0x8454, 0xDFDF, 0x8456, 0xDFAB, 0x8457, 0xB5DB, 0x8459, 0xDFB9, 0x845A, 0xDFB8, + 0x845B, 0xB8AF, 0x845D, 0xDFBC, 0x845E, 0xDFBE, 0x845F, 0xDFCD, 0x8460, 0xDFDE, 0x8461, 0xB8B2, 0x8463, 0xB8B3, 0x8465, 0xDFB0, + 0x8466, 0xB8AB, 0x8467, 0xDFB4, 0x8468, 0xDFDA, 0x8469, 0xB8B4, 0x846B, 0xB8AC, 0x846C, 0xB8AE, 0x846D, 0xB8B5, 0x846E, 0xDFE0, + 0x846F, 0xDFD3, 0x8470, 0xDFCE, 0x8473, 0xDFBB, 0x8474, 0xDFBA, 0x8475, 0xB8AA, 0x8476, 0xDFAC, 0x8477, 0xB8A7, 0x8478, 0xDFC4, + 0x8479, 0xDFAD, 0x847A, 0xDFC2, 0x847D, 0xDFB7, 0x847E, 0xDFDB, 0x8482, 0xB8A6, 0x8486, 0xDFB3, 0x848D, 0xDFAF, 0x848E, 0xDFD5, + 0x848F, 0xDFAE, 0x8490, 0xBB60, 0x8491, 0xE3D3, 0x8494, 0xE3C2, 0x8497, 0xE3AC, 0x8498, 0xE3CA, 0x8499, 0xBB58, 0x849A, 0xE3BB, + 0x849B, 0xE3C5, 0x849C, 0xBB5B, 0x849D, 0xE3BE, 0x849E, 0xBB59, 0x849F, 0xE3AF, 0x84A0, 0xE3CD, 0x84A1, 0xE3AE, 0x84A2, 0xE3C1, + 0x84A4, 0xE3AD, 0x84A7, 0xE3BF, 0x84A8, 0xE3C8, 0x84A9, 0xE3C6, 0x84AA, 0xE3BA, 0x84AB, 0xE3B5, 0x84AC, 0xE3B3, 0x84AE, 0xE3B4, + 0x84AF, 0xE3C7, 0x84B0, 0xE3D2, 0x84B1, 0xE3BC, 0x84B2, 0xBB5A, 0x84B4, 0xE3B7, 0x84B6, 0xE3CB, 0x84B8, 0xBB5D, 0x84B9, 0xE3B6, + 0x84BA, 0xE3B0, 0x84BB, 0xE3C0, 0x84BC, 0xBB61, 0x84BF, 0xBB55, 0x84C0, 0xBB5E, 0x84C1, 0xE3B8, 0x84C2, 0xE3B2, 0x84C4, 0xBB57, + 0x84C5, 0xDFD4, 0x84C6, 0xBB56, 0x84C7, 0xE3C3, 0x84C9, 0xBB54, 0x84CA, 0xBB63, 0x84CB, 0xBB5C, 0x84CC, 0xE3C4, 0x84CD, 0xE3B9, + 0x84CE, 0xE3B1, 0x84CF, 0xE3CC, 0x84D0, 0xE3BD, 0x84D1, 0xBB62, 0x84D2, 0xE3D0, 0x84D3, 0xBB5F, 0x84D4, 0xE3CF, 0x84D6, 0xE3C9, + 0x84D7, 0xE3CE, 0x84DB, 0xE3D1, 0x84E7, 0xE773, 0x84E8, 0xE774, 0x84E9, 0xE767, 0x84EA, 0xE766, 0x84EB, 0xE762, 0x84EC, 0xBDB4, + 0x84EE, 0xBDAC, 0x84EF, 0xE776, 0x84F0, 0xE775, 0x84F1, 0xDFA9, 0x84F2, 0xE75F, 0x84F3, 0xE763, 0x84F4, 0xE75D, 0x84F6, 0xE770, + 0x84F7, 0xE761, 0x84F9, 0xE777, 0x84FA, 0xE75A, 0x84FB, 0xE758, 0x84FC, 0xE764, 0x84FD, 0xE76E, 0x84FE, 0xE769, 0x84FF, 0xBDB6, + 0x8500, 0xE74F, 0x8502, 0xE76D, 0x8506, 0xBDB7, 0x8507, 0xDFBD, 0x8508, 0xE75B, 0x8509, 0xE752, 0x850A, 0xE755, 0x850B, 0xE77B, + 0x850C, 0xE75C, 0x850D, 0xE753, 0x850E, 0xE751, 0x850F, 0xE74E, 0x8511, 0xBDB0, 0x8512, 0xE765, 0x8513, 0xBDAF, 0x8514, 0xBDB3, + 0x8515, 0xE760, 0x8516, 0xE768, 0x8517, 0xBDA9, 0x8518, 0xE778, 0x8519, 0xE77C, 0x851A, 0xBDAB, 0x851C, 0xE757, 0x851D, 0xE76B, + 0x851E, 0xE76F, 0x851F, 0xE754, 0x8520, 0xE779, 0x8521, 0xBDB2, 0x8523, 0xBDB1, 0x8524, 0xE74C, 0x8525, 0xBDB5, 0x8526, 0xE772, + 0x8527, 0xE756, 0x8528, 0xE76A, 0x8529, 0xE750, 0x852A, 0xE75E, 0x852B, 0xE759, 0x852C, 0xBDAD, 0x852D, 0xBDAE, 0x852E, 0xE76C, + 0x852F, 0xE77D, 0x8530, 0xE77A, 0x8531, 0xE771, 0x853B, 0xE74D, 0x853D, 0xBDAA, 0x853E, 0xEB49, 0x8540, 0xEB40, 0x8541, 0xEB43, + 0x8543, 0xBFBB, 0x8544, 0xEB45, 0x8545, 0xEAF9, 0x8546, 0xEB41, 0x8547, 0xEB47, 0x8548, 0xBFB8, 0x8549, 0xBFBC, 0x854A, 0xBFB6, + 0x854D, 0xEAFB, 0x854E, 0xEB4C, 0x8551, 0xEB46, 0x8553, 0xEAFC, 0x8554, 0xEB55, 0x8555, 0xEB4F, 0x8556, 0xEAF8, 0x8557, 0xEE46, + 0x8558, 0xEAFE, 0x8559, 0xBFB7, 0x855B, 0xEB4A, 0x855D, 0xEB54, 0x855E, 0xBFBF, 0x8560, 0xEB51, 0x8561, 0xEAFD, 0x8562, 0xEB44, + 0x8563, 0xEB48, 0x8564, 0xEB42, 0x8565, 0xEB56, 0x8566, 0xEB53, 0x8567, 0xEB50, 0x8568, 0xBFB9, 0x8569, 0xBFBA, 0x856A, 0xBFBE, + 0x856B, 0xEAFA, 0x856C, 0xEB57, 0x856D, 0xBFBD, 0x856E, 0xEB4D, 0x8571, 0xEB4B, 0x8575, 0xEB4E, 0x8576, 0xEE53, 0x8577, 0xEE40, + 0x8578, 0xEE45, 0x8579, 0xEE52, 0x857A, 0xEE44, 0x857B, 0xEDFB, 0x857C, 0xEE41, 0x857E, 0xC1A2, 0x8580, 0xEDF4, 0x8581, 0xEE4D, + 0x8582, 0xEE4F, 0x8583, 0xEDF3, 0x8584, 0xC1A1, 0x8585, 0xEE51, 0x8586, 0xEE49, 0x8587, 0xC1A8, 0x8588, 0xEE50, 0x8589, 0xEE42, + 0x858A, 0xC1AA, 0x858B, 0xEDF9, 0x858C, 0xEB52, 0x858D, 0xEE4A, 0x858E, 0xEE47, 0x858F, 0xEDF5, 0x8590, 0xEE55, 0x8591, 0xC1A4, + 0x8594, 0xC1A5, 0x8595, 0xEDF7, 0x8596, 0xEE48, 0x8598, 0xEE54, 0x8599, 0xEE4B, 0x859A, 0xEDFD, 0x859B, 0xC1A7, 0x859C, 0xC1A3, + 0x859D, 0xEE4C, 0x859E, 0xEDFE, 0x859F, 0xEE56, 0x85A0, 0xEDF8, 0x85A1, 0xEE43, 0x85A2, 0xEE4E, 0x85A3, 0xEDFA, 0x85A4, 0xEDFC, + 0x85A6, 0xC2CB, 0x85A7, 0xEDF6, 0x85A8, 0xC1A9, 0x85A9, 0xC2C4, 0x85AA, 0xC17E, 0x85AF, 0xC1A6, 0x85B0, 0xC2C8, 0x85B1, 0xF0B3, + 0x85B3, 0xF0A9, 0x85B4, 0xF0A4, 0x85B5, 0xF0AA, 0x85B6, 0xF0B4, 0x85B7, 0xF0B8, 0x85B8, 0xF0B7, 0x85B9, 0xC2CA, 0x85BA, 0xC2C9, + 0x85BD, 0xF0AB, 0x85BE, 0xF0B9, 0x85BF, 0xF0AE, 0x85C0, 0xF0A6, 0x85C2, 0xF0A8, 0x85C3, 0xF0A7, 0x85C4, 0xF0AD, 0x85C5, 0xF0B2, + 0x85C6, 0xF0A5, 0x85C7, 0xF0AC, 0x85C8, 0xF0B1, 0x85C9, 0xC2C7, 0x85CB, 0xF0AF, 0x85CD, 0xC2C5, 0x85CE, 0xF0B0, 0x85CF, 0xC2C3, + 0x85D0, 0xC2C6, 0x85D1, 0xF2D5, 0x85D2, 0xF0B5, 0x85D5, 0xC3C2, 0x85D7, 0xF2CD, 0x85D8, 0xF2D1, 0x85D9, 0xF2C9, 0x85DA, 0xF2CC, + 0x85DC, 0xF2D4, 0x85DD, 0xC3C0, 0x85DE, 0xF2D9, 0x85DF, 0xF2D2, 0x85E1, 0xF2CA, 0x85E2, 0xF2DA, 0x85E3, 0xF2D3, 0x85E4, 0xC3C3, + 0x85E5, 0xC3C4, 0x85E6, 0xF2D7, 0x85E8, 0xF2CB, 0x85E9, 0xC3BF, 0x85EA, 0xC3C1, 0x85EB, 0xF2C6, 0x85EC, 0xF2CE, 0x85ED, 0xF2C8, + 0x85EF, 0xF2D8, 0x85F0, 0xF2D6, 0x85F1, 0xF2C7, 0x85F2, 0xF2CF, 0x85F6, 0xF4BE, 0x85F7, 0xC3C5, 0x85F8, 0xF2D0, 0x85F9, 0xC4A7, + 0x85FA, 0xC4A9, 0x85FB, 0xC4A6, 0x85FD, 0xF4C3, 0x85FE, 0xF4BB, 0x85FF, 0xF4B9, 0x8600, 0xF4BD, 0x8601, 0xF4BA, 0x8604, 0xF4BF, + 0x8605, 0xF4C1, 0x8606, 0xC4AA, 0x8607, 0xC4AC, 0x8609, 0xF4C0, 0x860A, 0xC4AD, 0x860B, 0xC4AB, 0x860C, 0xF4C2, 0x8611, 0xC4A8, + 0x8617, 0xC4F4, 0x8618, 0xF5F1, 0x8619, 0xF5F7, 0x861A, 0xC4F6, 0x861B, 0xF4BC, 0x861C, 0xF5F6, 0x861E, 0xF5FD, 0x861F, 0xF5F4, + 0x8620, 0xF5FB, 0x8621, 0xF5FA, 0x8622, 0xF4B8, 0x8623, 0xF5F5, 0x8624, 0xF0B6, 0x8625, 0xF5FE, 0x8626, 0xF5F3, 0x8627, 0xF5F8, + 0x8629, 0xF5FC, 0x862A, 0xF5F2, 0x862C, 0xF74A, 0x862D, 0xC4F5, 0x862E, 0xF5F9, 0x8631, 0xF7F4, 0x8632, 0xF74B, 0x8633, 0xF749, + 0x8634, 0xF747, 0x8635, 0xF748, 0x8636, 0xF74C, 0x8638, 0xC5D9, 0x8639, 0xF7F2, 0x863A, 0xF7F0, 0x863B, 0xF7F5, 0x863C, 0xF7F3, + 0x863E, 0xF7F6, 0x863F, 0xC5DA, 0x8640, 0xF7F1, 0x8643, 0xF8BC, 0x8646, 0xF945, 0x8647, 0xF946, 0x8648, 0xF947, 0x864B, 0xF9C7, + 0x864C, 0xF9BD, 0x864D, 0xCA4F, 0x864E, 0xAAEA, 0x8650, 0xAD68, 0x8652, 0xD3B8, 0x8653, 0xD3B7, 0x8654, 0xB040, 0x8655, 0xB342, + 0x8656, 0xD77C, 0x8659, 0xD77B, 0x865B, 0xB5EA, 0x865C, 0xB8B8, 0x865E, 0xB8B7, 0x865F, 0xB8B9, 0x8661, 0xE3D4, 0x8662, 0xE77E, + 0x8663, 0xEB58, 0x8664, 0xEB5A, 0x8665, 0xEB59, 0x8667, 0xC1AB, 0x8668, 0xEE57, 0x8669, 0xF0BA, 0x866A, 0xF9A5, 0x866B, 0xA6E4, + 0x866D, 0xCDC9, 0x866E, 0xCDCA, 0x866F, 0xCDC8, 0x8670, 0xCDC7, 0x8671, 0xAAEB, 0x8673, 0xD0A9, 0x8674, 0xD0A7, 0x8677, 0xD0A6, + 0x8679, 0xAD69, 0x867A, 0xAD6B, 0x867B, 0xAD6A, 0x867C, 0xD0A8, 0x8685, 0xD3C4, 0x8686, 0xD3C1, 0x8687, 0xD3BF, 0x868A, 0xB041, + 0x868B, 0xD3C2, 0x868C, 0xB046, 0x868D, 0xD3BC, 0x868E, 0xD3CB, 0x8690, 0xD3CD, 0x8691, 0xD3BD, 0x8693, 0xB043, 0x8694, 0xD3CE, + 0x8695, 0xD3C9, 0x8696, 0xD3BB, 0x8697, 0xD3C0, 0x8698, 0xD3CA, 0x8699, 0xD3C6, 0x869A, 0xD3C3, 0x869C, 0xB048, 0x869D, 0xD3CC, + 0x869E, 0xD3BE, 0x86A1, 0xD3C7, 0x86A2, 0xD3B9, 0x86A3, 0xB047, 0x86A4, 0xB044, 0x86A5, 0xD3C5, 0x86A7, 0xD3C8, 0x86A8, 0xD3BA, + 0x86A9, 0xB045, 0x86AA, 0xB042, 0x86AF, 0xB34C, 0x86B0, 0xD7A5, 0x86B1, 0xB34B, 0x86B3, 0xD7A8, 0x86B4, 0xD7AB, 0x86B5, 0xB348, + 0x86B6, 0xB346, 0x86B7, 0xD77E, 0x86B8, 0xD7A9, 0x86B9, 0xD7A7, 0x86BA, 0xD7A4, 0x86BB, 0xD7AC, 0x86BC, 0xD7AD, 0x86BD, 0xD7AF, + 0x86BE, 0xD7B0, 0x86BF, 0xD77D, 0x86C0, 0xB345, 0x86C1, 0xD7A2, 0x86C2, 0xD7A1, 0x86C3, 0xD7AE, 0x86C4, 0xB347, 0x86C5, 0xD7A3, + 0x86C6, 0xB349, 0x86C7, 0xB344, 0x86C8, 0xD7A6, 0x86C9, 0xB34D, 0x86CB, 0xB34A, 0x86CC, 0xD7AA, 0x86D0, 0xB5F1, 0x86D1, 0xDBBF, + 0x86D3, 0xDBB4, 0x86D4, 0xB5EE, 0x86D6, 0xDFE7, 0x86D7, 0xDBBD, 0x86D8, 0xDBB1, 0x86D9, 0xB5EC, 0x86DA, 0xDBB6, 0x86DB, 0xB5EF, + 0x86DC, 0xDBBA, 0x86DD, 0xDBB8, 0x86DE, 0xB5F2, 0x86DF, 0xB5EB, 0x86E2, 0xDBB2, 0x86E3, 0xDBB5, 0x86E4, 0xB5F0, 0x86E6, 0xDBB3, + 0x86E8, 0xDBBE, 0x86E9, 0xDBBC, 0x86EA, 0xDBB7, 0x86EB, 0xDBB9, 0x86EC, 0xDBBB, 0x86ED, 0xB5ED, 0x86F5, 0xDFE8, 0x86F6, 0xDFEE, + 0x86F7, 0xDFE4, 0x86F8, 0xDFEA, 0x86F9, 0xB8BA, 0x86FA, 0xDFE6, 0x86FB, 0xB8C0, 0x86FE, 0xB8BF, 0x8700, 0xB8BE, 0x8701, 0xDFED, + 0x8702, 0xB8C1, 0x8703, 0xB8C2, 0x8704, 0xDFE3, 0x8705, 0xDFF0, 0x8706, 0xB8C3, 0x8707, 0xB8BD, 0x8708, 0xB8BC, 0x8709, 0xDFEC, + 0x870A, 0xB8C4, 0x870B, 0xDFE2, 0x870C, 0xDFE5, 0x870D, 0xDFEF, 0x870E, 0xDFEB, 0x8711, 0xE3F4, 0x8712, 0xE3E9, 0x8713, 0xB8BB, + 0x8718, 0xBB6A, 0x8719, 0xE3DD, 0x871A, 0xE3F2, 0x871B, 0xE3DE, 0x871C, 0xBB65, 0x871E, 0xE3DB, 0x8720, 0xE3E4, 0x8721, 0xE3DC, + 0x8722, 0xBB67, 0x8723, 0xE3D6, 0x8724, 0xE3F1, 0x8725, 0xBB68, 0x8726, 0xE3EE, 0x8727, 0xE3EF, 0x8728, 0xE3D7, 0x8729, 0xBB6D, + 0x872A, 0xE3E6, 0x872C, 0xE3E0, 0x872D, 0xE3E7, 0x872E, 0xE3DA, 0x8730, 0xE3F3, 0x8731, 0xE3EB, 0x8732, 0xE3E5, 0x8733, 0xE3D5, + 0x8734, 0xBB69, 0x8735, 0xE3EC, 0x8737, 0xBB6C, 0x8738, 0xE3F0, 0x873A, 0xE3EA, 0x873B, 0xBB66, 0x873C, 0xE3E8, 0x873E, 0xE3E2, + 0x873F, 0xBB64, 0x8740, 0xE3D9, 0x8741, 0xE3E1, 0x8742, 0xE3ED, 0x8743, 0xE3DF, 0x8746, 0xE3E3, 0x874C, 0xBDC1, 0x874D, 0xDFE9, + 0x874E, 0xE7B2, 0x874F, 0xE7BB, 0x8750, 0xE7B1, 0x8751, 0xE7AD, 0x8752, 0xE7AA, 0x8753, 0xBDC2, 0x8754, 0xE7A8, 0x8755, 0xBB6B, + 0x8756, 0xE7A1, 0x8757, 0xBDC0, 0x8758, 0xE7A7, 0x8759, 0xBDBF, 0x875A, 0xE7AC, 0x875B, 0xE7A9, 0x875C, 0xE7B9, 0x875D, 0xE7B4, + 0x875E, 0xE7AE, 0x875F, 0xE7B3, 0x8760, 0xBDBB, 0x8761, 0xE7AB, 0x8762, 0xE7BE, 0x8763, 0xE7A2, 0x8764, 0xE7A3, 0x8765, 0xE7BA, + 0x8766, 0xBDBC, 0x8767, 0xE7BF, 0x8768, 0xBDBE, 0x8769, 0xE7C0, 0x876A, 0xE7B0, 0x876B, 0xE3D8, 0x876C, 0xE7B6, 0x876D, 0xE7AF, + 0x876E, 0xE7B8, 0x876F, 0xE7B5, 0x8773, 0xE7A6, 0x8774, 0xBDB9, 0x8775, 0xE7BD, 0x8776, 0xBDBA, 0x8777, 0xE7A4, 0x8778, 0xBDBD, + 0x8779, 0xEB64, 0x877A, 0xE7B7, 0x877B, 0xE7BC, 0x8781, 0xEB61, 0x8782, 0xBDB8, 0x8783, 0xBFC0, 0x8784, 0xEB6B, 0x8785, 0xEB67, + 0x8787, 0xEB65, 0x8788, 0xEB60, 0x8789, 0xEB6F, 0x878D, 0xBFC4, 0x878F, 0xEB5C, 0x8790, 0xEB68, 0x8791, 0xEB69, 0x8792, 0xEB5F, + 0x8793, 0xEB5E, 0x8794, 0xEB6C, 0x8796, 0xEB62, 0x8797, 0xEB5D, 0x8798, 0xEB63, 0x879A, 0xEB6E, 0x879B, 0xEB5B, 0x879C, 0xEB6D, + 0x879D, 0xEB6A, 0x879E, 0xBFC2, 0x879F, 0xBFC1, 0x87A2, 0xBFC3, 0x87A3, 0xEB66, 0x87A4, 0xF0CB, 0x87AA, 0xEE59, 0x87AB, 0xC1B1, + 0x87AC, 0xEE5D, 0x87AD, 0xEE5A, 0x87AE, 0xEE61, 0x87AF, 0xEE67, 0x87B0, 0xEE5C, 0x87B2, 0xEE70, 0x87B3, 0xC1AE, 0x87B4, 0xEE6A, + 0x87B5, 0xEE5F, 0x87B6, 0xEE6B, 0x87B7, 0xEE66, 0x87B8, 0xEE6D, 0x87B9, 0xEE5E, 0x87BA, 0xC1B3, 0x87BB, 0xC1B2, 0x87BC, 0xEE60, + 0x87BD, 0xEE6E, 0x87BE, 0xEE58, 0x87BF, 0xEE6C, 0x87C0, 0xC1AC, 0x87C2, 0xEE64, 0x87C3, 0xEE63, 0x87C4, 0xEE68, 0x87C5, 0xEE5B, + 0x87C6, 0xC1B0, 0x87C8, 0xC1B4, 0x87C9, 0xEE62, 0x87CA, 0xEE69, 0x87CB, 0xC1B5, 0x87CC, 0xEE65, 0x87D1, 0xC1AD, 0x87D2, 0xC1AF, + 0x87D3, 0xF0C7, 0x87D4, 0xF0C5, 0x87D7, 0xF0CC, 0x87D8, 0xF0C9, 0x87D9, 0xF0CD, 0x87DB, 0xF0BE, 0x87DC, 0xF0C6, 0x87DD, 0xF0D1, + 0x87DE, 0xEE6F, 0x87DF, 0xF0C2, 0x87E0, 0xC2CF, 0x87E1, 0xE7A5, 0x87E2, 0xF0BD, 0x87E3, 0xF0CA, 0x87E4, 0xF0C4, 0x87E5, 0xF0C1, + 0x87E6, 0xF0BC, 0x87E7, 0xF0BB, 0x87E8, 0xF0D0, 0x87EA, 0xF0C0, 0x87EB, 0xF0BF, 0x87EC, 0xC2CD, 0x87ED, 0xF0C8, 0x87EF, 0xC2CC, + 0x87F2, 0xC2CE, 0x87F3, 0xF0C3, 0x87F4, 0xF0CF, 0x87F6, 0xF2DE, 0x87F7, 0xF2DF, 0x87F9, 0xC3C9, 0x87FA, 0xF2DC, 0x87FB, 0xC3C6, + 0x87FC, 0xF2E4, 0x87FE, 0xC3CA, 0x87FF, 0xF2E6, 0x8800, 0xF2DB, 0x8801, 0xF0CE, 0x8802, 0xF2E8, 0x8803, 0xF2DD, 0x8805, 0xC3C7, + 0x8806, 0xF2E3, 0x8808, 0xF2E5, 0x8809, 0xF2E0, 0x880A, 0xF2E7, 0x880B, 0xF2E2, 0x880C, 0xF2E1, 0x880D, 0xC3C8, 0x8810, 0xF4C5, + 0x8811, 0xF4C6, 0x8813, 0xF4C8, 0x8814, 0xC4AE, 0x8815, 0xC4AF, 0x8816, 0xF4C9, 0x8817, 0xF4C7, 0x8819, 0xF4C4, 0x881B, 0xF642, + 0x881C, 0xF645, 0x881D, 0xF641, 0x881F, 0xC4FA, 0x8820, 0xF643, 0x8821, 0xC4F9, 0x8822, 0xC4F8, 0x8823, 0xC4F7, 0x8824, 0xF644, + 0x8825, 0xF751, 0x8826, 0xF74F, 0x8828, 0xF74E, 0x8829, 0xF640, 0x882A, 0xF750, 0x882B, 0xF646, 0x882C, 0xF74D, 0x882E, 0xF7F9, + 0x882F, 0xF7D7, 0x8830, 0xF7F7, 0x8831, 0xC5DB, 0x8832, 0xF7F8, 0x8833, 0xF7FA, 0x8835, 0xF8BF, 0x8836, 0xC5FA, 0x8837, 0xF8BE, + 0x8838, 0xF8BD, 0x8839, 0xC5FB, 0x883B, 0xC65A, 0x883C, 0xF96E, 0x883D, 0xF9A7, 0x883E, 0xF9A6, 0x883F, 0xF9A8, 0x8840, 0xA6E5, + 0x8841, 0xD0AA, 0x8843, 0xD3CF, 0x8844, 0xD3D0, 0x8848, 0xDBC0, 0x884A, 0xF647, 0x884B, 0xF8C0, 0x884C, 0xA6E6, 0x884D, 0xAD6C, + 0x884E, 0xD0AB, 0x8852, 0xD7B1, 0x8853, 0xB34E, 0x8855, 0xDBC2, 0x8856, 0xDBC1, 0x8857, 0xB5F3, 0x8859, 0xB8C5, 0x885A, 0xE7C1, + 0x885B, 0xBDC3, 0x885D, 0xBDC4, 0x8861, 0xBFC5, 0x8862, 0xC5FC, 0x8863, 0xA6E7, 0x8867, 0xD0AC, 0x8868, 0xAAED, 0x8869, 0xD0AE, + 0x886A, 0xD0AD, 0x886B, 0xAD6D, 0x886D, 0xD3D1, 0x886F, 0xD3D8, 0x8870, 0xB049, 0x8871, 0xD3D6, 0x8872, 0xD3D4, 0x8874, 0xD3DB, + 0x8875, 0xD3D2, 0x8876, 0xD3D3, 0x8877, 0xB04A, 0x8879, 0xB04E, 0x887C, 0xD3DC, 0x887D, 0xB04D, 0x887E, 0xD3DA, 0x887F, 0xD3D7, + 0x8880, 0xD3D5, 0x8881, 0xB04B, 0x8882, 0xB04C, 0x8883, 0xD3D9, 0x8888, 0xB350, 0x8889, 0xD7B2, 0x888B, 0xB355, 0x888C, 0xD7C2, + 0x888D, 0xB354, 0x888E, 0xD7C4, 0x8891, 0xD7B8, 0x8892, 0xB352, 0x8893, 0xD7C3, 0x8895, 0xD7B3, 0x8896, 0xB353, 0x8897, 0xD7BF, + 0x8898, 0xD7BB, 0x8899, 0xD7BD, 0x889A, 0xD7B7, 0x889B, 0xD7BE, 0x889E, 0xB34F, 0x889F, 0xD7BA, 0x88A1, 0xD7B9, 0x88A2, 0xD7B5, + 0x88A4, 0xD7C0, 0x88A7, 0xD7BC, 0x88A8, 0xD7B4, 0x88AA, 0xD7B6, 0x88AB, 0xB351, 0x88AC, 0xD7C1, 0x88B1, 0xB5F6, 0x88B2, 0xDBCD, + 0x88B6, 0xDBC9, 0x88B7, 0xDBCB, 0x88B8, 0xDBC6, 0x88B9, 0xDBC5, 0x88BA, 0xDBC3, 0x88BC, 0xDBCA, 0x88BD, 0xDBCC, 0x88BE, 0xDBC8, + 0x88C0, 0xDBC7, 0x88C1, 0xB5F4, 0x88C2, 0xB5F5, 0x88C9, 0xDBCF, 0x88CA, 0xB8CD, 0x88CB, 0xDFF2, 0x88CC, 0xDFF8, 0x88CD, 0xDFF3, + 0x88CE, 0xDFF4, 0x88CF, 0xF9D8, 0x88D0, 0xDFF9, 0x88D2, 0xB8CF, 0x88D4, 0xB8C7, 0x88D5, 0xB8CE, 0x88D6, 0xDFF1, 0x88D7, 0xDBC4, + 0x88D8, 0xB8CA, 0x88D9, 0xB8C8, 0x88DA, 0xDFF7, 0x88DB, 0xDFF6, 0x88DC, 0xB8C9, 0x88DD, 0xB8CB, 0x88DE, 0xDFF5, 0x88DF, 0xB8C6, + 0x88E1, 0xB8CC, 0x88E7, 0xE3F6, 0x88E8, 0xBB74, 0x88EB, 0xE442, 0x88EC, 0xE441, 0x88EE, 0xE3FB, 0x88EF, 0xBB76, 0x88F0, 0xE440, + 0x88F1, 0xE3F7, 0x88F2, 0xE3F8, 0x88F3, 0xBB6E, 0x88F4, 0xBB70, 0x88F6, 0xE3FD, 0x88F7, 0xE3F5, 0x88F8, 0xBB72, 0x88F9, 0xBB71, + 0x88FA, 0xE3F9, 0x88FB, 0xE3FE, 0x88FC, 0xE3FC, 0x88FD, 0xBB73, 0x88FE, 0xE3FA, 0x8901, 0xDBCE, 0x8902, 0xBB6F, 0x8905, 0xE7C2, + 0x8906, 0xE7C9, 0x8907, 0xBDC6, 0x8909, 0xE7CD, 0x890A, 0xBDCA, 0x890B, 0xE7C5, 0x890C, 0xE7C3, 0x890E, 0xE7CC, 0x8910, 0xBDC5, + 0x8911, 0xE7CB, 0x8912, 0xBDC7, 0x8913, 0xBDC8, 0x8914, 0xE7C4, 0x8915, 0xBDC9, 0x8916, 0xE7CA, 0x8917, 0xE7C6, 0x8918, 0xE7C7, + 0x8919, 0xE7C8, 0x891A, 0xBB75, 0x891E, 0xEB70, 0x891F, 0xEB7C, 0x8921, 0xBFCA, 0x8922, 0xEB77, 0x8923, 0xEB79, 0x8925, 0xBFC8, + 0x8926, 0xEB71, 0x8927, 0xEB75, 0x8929, 0xEB78, 0x892A, 0xBFC6, 0x892B, 0xBFC9, 0x892C, 0xEB7B, 0x892D, 0xEB73, 0x892E, 0xEB74, + 0x892F, 0xEB7A, 0x8930, 0xEB72, 0x8931, 0xEB76, 0x8932, 0xBFC7, 0x8933, 0xEE72, 0x8935, 0xEE71, 0x8936, 0xC1B7, 0x8937, 0xEE77, + 0x8938, 0xC1B9, 0x893B, 0xC1B6, 0x893C, 0xEE73, 0x893D, 0xC1BA, 0x893E, 0xEE74, 0x8941, 0xEE75, 0x8942, 0xEE78, 0x8944, 0xC1B8, + 0x8946, 0xF0D6, 0x8949, 0xF0D9, 0x894B, 0xF0D3, 0x894C, 0xF0D5, 0x894F, 0xF0D4, 0x8950, 0xF0D7, 0x8951, 0xF0D8, 0x8952, 0xEE76, + 0x8953, 0xF0D2, 0x8956, 0xC3CD, 0x8957, 0xF2EC, 0x8958, 0xF2EF, 0x8959, 0xF2F1, 0x895A, 0xF2EA, 0x895B, 0xF2EB, 0x895C, 0xF2EE, + 0x895D, 0xF2F0, 0x895E, 0xC3CE, 0x895F, 0xC3CC, 0x8960, 0xC3CB, 0x8961, 0xF2ED, 0x8962, 0xF2E9, 0x8963, 0xF4CA, 0x8964, 0xC4B0, + 0x8966, 0xF4CB, 0x8969, 0xF649, 0x896A, 0xC4FB, 0x896B, 0xF64B, 0x896C, 0xC4FC, 0x896D, 0xF648, 0x896E, 0xF64A, 0x896F, 0xC5A8, + 0x8971, 0xF752, 0x8972, 0xC5A7, 0x8973, 0xF7FD, 0x8974, 0xF7FC, 0x8976, 0xF7FB, 0x8979, 0xF948, 0x897A, 0xF949, 0x897B, 0xF94B, + 0x897C, 0xF94A, 0x897E, 0xCA50, 0x897F, 0xA6E8, 0x8981, 0xAD6E, 0x8982, 0xD7C5, 0x8983, 0xB5F7, 0x8985, 0xDFFA, 0x8986, 0xC2D0, + 0x8988, 0xF2F2, 0x898B, 0xA8A3, 0x898F, 0xB357, 0x8993, 0xB356, 0x8995, 0xDBD0, 0x8996, 0xB5F8, 0x8997, 0xDBD2, 0x8998, 0xDBD1, + 0x899B, 0xDFFB, 0x899C, 0xB8D0, 0x899D, 0xE443, 0x899E, 0xE446, 0x899F, 0xE445, 0x89A1, 0xE444, 0x89A2, 0xE7CE, 0x89A3, 0xE7D0, + 0x89A4, 0xE7CF, 0x89A6, 0xBFCC, 0x89AA, 0xBFCB, 0x89AC, 0xC1BB, 0x89AD, 0xEE79, 0x89AE, 0xEE7B, 0x89AF, 0xEE7A, 0x89B2, 0xC2D1, + 0x89B6, 0xF2F4, 0x89B7, 0xF2F3, 0x89B9, 0xF4CC, 0x89BA, 0xC4B1, 0x89BD, 0xC4FD, 0x89BE, 0xF754, 0x89BF, 0xF753, 0x89C0, 0xC65B, + 0x89D2, 0xA8A4, 0x89D3, 0xD0AF, 0x89D4, 0xAD6F, 0x89D5, 0xD7C8, 0x89D6, 0xD7C6, 0x89D9, 0xD7C7, 0x89DA, 0xDBD4, 0x89DB, 0xDBD5, + 0x89DC, 0xE043, 0x89DD, 0xDBD3, 0x89DF, 0xDFFC, 0x89E0, 0xE041, 0x89E1, 0xE040, 0x89E2, 0xE042, 0x89E3, 0xB8D1, 0x89E4, 0xDFFE, + 0x89E5, 0xDFFD, 0x89E6, 0xE044, 0x89E8, 0xE449, 0x89E9, 0xE447, 0x89EB, 0xE448, 0x89EC, 0xE7D3, 0x89ED, 0xE7D1, 0x89F0, 0xE7D2, + 0x89F1, 0xEB7D, 0x89F2, 0xEE7C, 0x89F3, 0xEE7D, 0x89F4, 0xC2D2, 0x89F6, 0xF2F5, 0x89F7, 0xF4CD, 0x89F8, 0xC4B2, 0x89FA, 0xF64C, + 0x89FB, 0xF755, 0x89FC, 0xC5A9, 0x89FE, 0xF7FE, 0x89FF, 0xF94C, 0x8A00, 0xA8A5, 0x8A02, 0xAD71, 0x8A03, 0xAD72, 0x8A04, 0xD0B0, + 0x8A07, 0xD0B1, 0x8A08, 0xAD70, 0x8A0A, 0xB054, 0x8A0C, 0xB052, 0x8A0E, 0xB051, 0x8A0F, 0xB058, 0x8A10, 0xB050, 0x8A11, 0xB059, + 0x8A12, 0xD3DD, 0x8A13, 0xB056, 0x8A15, 0xB053, 0x8A16, 0xB057, 0x8A17, 0xB055, 0x8A18, 0xB04F, 0x8A1B, 0xB35F, 0x8A1D, 0xB359, + 0x8A1E, 0xD7CC, 0x8A1F, 0xB35E, 0x8A22, 0xB360, 0x8A23, 0xB35A, 0x8A25, 0xB35B, 0x8A27, 0xD7CA, 0x8A2A, 0xB358, 0x8A2C, 0xD7CB, + 0x8A2D, 0xB35D, 0x8A30, 0xD7C9, 0x8A31, 0xB35C, 0x8A34, 0xB644, 0x8A36, 0xB646, 0x8A39, 0xDBD8, 0x8A3A, 0xB645, 0x8A3B, 0xB5F9, + 0x8A3C, 0xB5FD, 0x8A3E, 0xB8E4, 0x8A3F, 0xE049, 0x8A40, 0xDBDA, 0x8A41, 0xB5FE, 0x8A44, 0xDBDD, 0x8A45, 0xDBDE, 0x8A46, 0xB643, + 0x8A48, 0xDBE0, 0x8A4A, 0xDBE2, 0x8A4C, 0xDBE3, 0x8A4D, 0xDBD7, 0x8A4E, 0xDBD6, 0x8A4F, 0xDBE4, 0x8A50, 0xB642, 0x8A51, 0xDBE1, + 0x8A52, 0xDBDF, 0x8A54, 0xB640, 0x8A55, 0xB5FB, 0x8A56, 0xB647, 0x8A57, 0xDBDB, 0x8A58, 0xDBDC, 0x8A59, 0xDBD9, 0x8A5B, 0xB641, + 0x8A5E, 0xB5FC, 0x8A60, 0xB5FA, 0x8A61, 0xE048, 0x8A62, 0xB8DF, 0x8A63, 0xB8DA, 0x8A66, 0xB8D5, 0x8A68, 0xB8E5, 0x8A69, 0xB8D6, + 0x8A6B, 0xB8D2, 0x8A6C, 0xB8E1, 0x8A6D, 0xB8DE, 0x8A6E, 0xB8E0, 0x8A70, 0xB8D7, 0x8A71, 0xB8DC, 0x8A72, 0xB8D3, 0x8A73, 0xB8D4, + 0x8A74, 0xE050, 0x8A75, 0xE04D, 0x8A76, 0xE045, 0x8A77, 0xE04A, 0x8A79, 0xB8E2, 0x8A7A, 0xE051, 0x8A7B, 0xB8E3, 0x8A7C, 0xB8D9, + 0x8A7F, 0xE047, 0x8A81, 0xE04F, 0x8A82, 0xE04B, 0x8A83, 0xE04E, 0x8A84, 0xE04C, 0x8A85, 0xB8DD, 0x8A86, 0xE046, 0x8A87, 0xB8D8, + 0x8A8B, 0xE44C, 0x8A8C, 0xBB78, 0x8A8D, 0xBB7B, 0x8A8F, 0xE44E, 0x8A91, 0xBBA5, 0x8A92, 0xE44D, 0x8A93, 0xBB7D, 0x8A95, 0xBDCF, + 0x8A96, 0xE44F, 0x8A98, 0xBBA4, 0x8A99, 0xE44B, 0x8A9A, 0xBBA6, 0x8A9E, 0xBB79, 0x8AA0, 0xB8DB, 0x8AA1, 0xBB7C, 0x8AA3, 0xBB7A, + 0x8AA4, 0xBB7E, 0x8AA5, 0xBBA2, 0x8AA6, 0xBB77, 0x8AA7, 0xBBA7, 0x8AA8, 0xBBA3, 0x8AAA, 0xBBA1, 0x8AAB, 0xE44A, 0x8AB0, 0xBDD6, + 0x8AB2, 0xBDD2, 0x8AB6, 0xBDD9, 0x8AB8, 0xE7D6, 0x8AB9, 0xBDDA, 0x8ABA, 0xE7E2, 0x8ABB, 0xE7DB, 0x8ABC, 0xBDCB, 0x8ABD, 0xE7E3, + 0x8ABE, 0xE7DD, 0x8ABF, 0xBDD5, 0x8AC0, 0xE7DE, 0x8AC2, 0xBDD4, 0x8AC3, 0xE7E1, 0x8AC4, 0xBDCE, 0x8AC5, 0xE7DF, 0x8AC6, 0xE7D5, + 0x8AC7, 0xBDCD, 0x8AC8, 0xEBAA, 0x8AC9, 0xBDD3, 0x8ACB, 0xBDD0, 0x8ACD, 0xBDD8, 0x8ACF, 0xE7D4, 0x8AD1, 0xE7D8, 0x8AD2, 0xBDCC, + 0x8AD3, 0xE7D7, 0x8AD4, 0xE7D9, 0x8AD5, 0xE7DA, 0x8AD6, 0xBDD7, 0x8AD7, 0xE7DC, 0x8AD8, 0xE7E0, 0x8AD9, 0xE7E4, 0x8ADB, 0xBDDB, + 0x8ADC, 0xBFD2, 0x8ADD, 0xEBA5, 0x8ADE, 0xEBAB, 0x8ADF, 0xEBA8, 0x8AE0, 0xEB7E, 0x8AE1, 0xEBAC, 0x8AE2, 0xEBA1, 0x8AE4, 0xEBA7, + 0x8AE6, 0xBFCD, 0x8AE7, 0xBFD3, 0x8AE8, 0xEBAD, 0x8AEB, 0xBFCF, 0x8AED, 0xBFD9, 0x8AEE, 0xBFD4, 0x8AEF, 0xEBAF, 0x8AF0, 0xEBA9, + 0x8AF1, 0xBFD0, 0x8AF2, 0xEBA2, 0x8AF3, 0xBFDA, 0x8AF4, 0xEBA3, 0x8AF5, 0xEBA4, 0x8AF6, 0xBFDB, 0x8AF7, 0xBFD8, 0x8AF8, 0xBDD1, + 0x8AFA, 0xBFCE, 0x8AFB, 0xEBB0, 0x8AFC, 0xBFDC, 0x8AFE, 0xBFD5, 0x8AFF, 0xEBAE, 0x8B00, 0xBFD1, 0x8B01, 0xBFD6, 0x8B02, 0xBFD7, + 0x8B04, 0xC1C3, 0x8B05, 0xEEA4, 0x8B06, 0xEEAD, 0x8B07, 0xEEAA, 0x8B08, 0xEEAC, 0x8B0A, 0xC1C0, 0x8B0B, 0xEEA5, 0x8B0D, 0xEEAB, + 0x8B0E, 0xC1BC, 0x8B0F, 0xEEA7, 0x8B10, 0xC1C4, 0x8B11, 0xEEA3, 0x8B12, 0xEEA8, 0x8B13, 0xEEAF, 0x8B14, 0xEBA6, 0x8B15, 0xEEA9, + 0x8B16, 0xEEA2, 0x8B17, 0xC1BD, 0x8B18, 0xEEA1, 0x8B19, 0xC1BE, 0x8B1A, 0xEEB0, 0x8B1B, 0xC1BF, 0x8B1C, 0xEEAE, 0x8B1D, 0xC1C2, + 0x8B1E, 0xEE7E, 0x8B20, 0xC1C1, 0x8B22, 0xEEA6, 0x8B23, 0xF0DC, 0x8B24, 0xF0EA, 0x8B25, 0xF0E5, 0x8B26, 0xF0E7, 0x8B27, 0xF0DB, + 0x8B28, 0xC2D3, 0x8B2A, 0xF0DA, 0x8B2B, 0xC2D6, 0x8B2C, 0xC2D5, 0x8B2E, 0xF0E9, 0x8B2F, 0xF0E1, 0x8B30, 0xF0DE, 0x8B31, 0xF0E4, + 0x8B33, 0xF0DD, 0x8B35, 0xF0DF, 0x8B36, 0xF0E8, 0x8B37, 0xF0E6, 0x8B39, 0xC2D4, 0x8B3A, 0xF0ED, 0x8B3B, 0xF0EB, 0x8B3C, 0xF0E2, + 0x8B3D, 0xF0EC, 0x8B3E, 0xF0E3, 0x8B40, 0xF2F9, 0x8B41, 0xC3CF, 0x8B42, 0xF341, 0x8B45, 0xF64F, 0x8B46, 0xC3D6, 0x8B47, 0xF0E0, + 0x8B48, 0xF2F7, 0x8B49, 0xC3D2, 0x8B4A, 0xF2F8, 0x8B4B, 0xF2FD, 0x8B4E, 0xC3D4, 0x8B4F, 0xC3D5, 0x8B50, 0xF2F6, 0x8B51, 0xF340, + 0x8B52, 0xF342, 0x8B53, 0xF2FA, 0x8B54, 0xF2FC, 0x8B55, 0xF2FE, 0x8B56, 0xF2FB, 0x8B57, 0xF343, 0x8B58, 0xC3D1, 0x8B59, 0xC3D7, + 0x8B5A, 0xC3D3, 0x8B5C, 0xC3D0, 0x8B5D, 0xF4D0, 0x8B5F, 0xC4B7, 0x8B60, 0xF4CE, 0x8B63, 0xF4D2, 0x8B65, 0xF4D3, 0x8B66, 0xC4B5, + 0x8B67, 0xF4D4, 0x8B68, 0xF4D1, 0x8B6A, 0xF4CF, 0x8B6B, 0xC4B8, 0x8B6C, 0xC4B4, 0x8B6D, 0xF4D5, 0x8B6F, 0xC4B6, 0x8B70, 0xC4B3, + 0x8B74, 0xC4FE, 0x8B77, 0xC540, 0x8B78, 0xF64E, 0x8B79, 0xF64D, 0x8B7A, 0xF650, 0x8B7B, 0xF651, 0x8B7D, 0xC541, 0x8B7E, 0xF756, + 0x8B7F, 0xF75B, 0x8B80, 0xC5AA, 0x8B82, 0xF758, 0x8B84, 0xF757, 0x8B85, 0xF75A, 0x8B86, 0xF759, 0x8B88, 0xF843, 0x8B8A, 0xC5DC, + 0x8B8B, 0xF842, 0x8B8C, 0xF840, 0x8B8E, 0xF841, 0x8B92, 0xC5FE, 0x8B93, 0xC5FD, 0x8B94, 0xF8C1, 0x8B95, 0xF8C2, 0x8B96, 0xC640, + 0x8B98, 0xF94D, 0x8B99, 0xF94E, 0x8B9A, 0xC667, 0x8B9C, 0xC66D, 0x8B9E, 0xF9A9, 0x8B9F, 0xF9C8, 0x8C37, 0xA8A6, 0x8C39, 0xD7CD, + 0x8C3B, 0xD7CE, 0x8C3C, 0xE052, 0x8C3D, 0xE450, 0x8C3E, 0xE7E5, 0x8C3F, 0xC1C6, 0x8C41, 0xC1C5, 0x8C42, 0xF0EE, 0x8C43, 0xF344, + 0x8C45, 0xF844, 0x8C46, 0xA8A7, 0x8C47, 0xD3DE, 0x8C48, 0xB05A, 0x8C49, 0xB361, 0x8C4A, 0xE054, 0x8C4B, 0xE053, 0x8C4C, 0xBDDC, + 0x8C4D, 0xE7E6, 0x8C4E, 0xBDDD, 0x8C4F, 0xEEB1, 0x8C50, 0xC2D7, 0x8C54, 0xC676, 0x8C55, 0xA8A8, 0x8C56, 0xCDCB, 0x8C57, 0xD3DF, + 0x8C5A, 0xB362, 0x8C5C, 0xD7CF, 0x8C5D, 0xD7D0, 0x8C5F, 0xDBE5, 0x8C61, 0xB648, 0x8C62, 0xB8E6, 0x8C64, 0xE056, 0x8C65, 0xE055, + 0x8C66, 0xE057, 0x8C68, 0xE451, 0x8C69, 0xE452, 0x8C6A, 0xBBA8, 0x8C6B, 0xBFDD, 0x8C6C, 0xBDDE, 0x8C6D, 0xBFDE, 0x8C6F, 0xEEB5, + 0x8C70, 0xEEB2, 0x8C71, 0xEEB4, 0x8C72, 0xEEB3, 0x8C73, 0xC1C7, 0x8C75, 0xF0EF, 0x8C76, 0xF346, 0x8C77, 0xF345, 0x8C78, 0xCBA4, + 0x8C79, 0xB05C, 0x8C7A, 0xB05B, 0x8C7B, 0xD3E0, 0x8C7D, 0xD7D1, 0x8C80, 0xDBE7, 0x8C81, 0xDBE6, 0x8C82, 0xB649, 0x8C84, 0xE059, + 0x8C85, 0xE05A, 0x8C86, 0xE058, 0x8C89, 0xB8E8, 0x8C8A, 0xB8E7, 0x8C8C, 0xBBAA, 0x8C8D, 0xBBA9, 0x8C8F, 0xE7E7, 0x8C90, 0xEBB3, + 0x8C91, 0xEBB1, 0x8C92, 0xEBB2, 0x8C93, 0xBFDF, 0x8C94, 0xEEB7, 0x8C95, 0xEEB6, 0x8C97, 0xF0F2, 0x8C98, 0xF0F1, 0x8C99, 0xF0F0, + 0x8C9A, 0xF347, 0x8C9C, 0xF9AA, 0x8C9D, 0xA8A9, 0x8C9E, 0xAD73, 0x8CA0, 0xAD74, 0x8CA1, 0xB05D, 0x8CA2, 0xB05E, 0x8CA3, 0xD3E2, + 0x8CA4, 0xD3E1, 0x8CA5, 0xD7D2, 0x8CA7, 0xB368, 0x8CA8, 0xB366, 0x8CA9, 0xB363, 0x8CAA, 0xB367, 0x8CAB, 0xB365, 0x8CAC, 0xB364, + 0x8CAF, 0xB64A, 0x8CB0, 0xDBEA, 0x8CB2, 0xB8ED, 0x8CB3, 0xB64C, 0x8CB4, 0xB651, 0x8CB5, 0xDBEC, 0x8CB6, 0xB653, 0x8CB7, 0xB652, + 0x8CB8, 0xB655, 0x8CB9, 0xDBEB, 0x8CBA, 0xDBE8, 0x8CBB, 0xB64F, 0x8CBC, 0xB64B, 0x8CBD, 0xB64D, 0x8CBE, 0xDBE9, 0x8CBF, 0xB654, + 0x8CC0, 0xB650, 0x8CC1, 0xB64E, 0x8CC2, 0xB8EF, 0x8CC3, 0xB8EE, 0x8CC4, 0xB8EC, 0x8CC5, 0xB8F0, 0x8CC7, 0xB8EA, 0x8CC8, 0xB8EB, + 0x8CCA, 0xB8E9, 0x8CCC, 0xE05B, 0x8CCF, 0xE454, 0x8CD1, 0xBBAC, 0x8CD2, 0xBBAD, 0x8CD3, 0xBBAB, 0x8CD5, 0xE453, 0x8CD7, 0xE455, + 0x8CD9, 0xE7EA, 0x8CDA, 0xE7EC, 0x8CDC, 0xBDE7, 0x8CDD, 0xE7ED, 0x8CDE, 0xBDE0, 0x8CDF, 0xE7E9, 0x8CE0, 0xBDDF, 0x8CE1, 0xBDE9, + 0x8CE2, 0xBDE5, 0x8CE3, 0xBDE6, 0x8CE4, 0xBDE2, 0x8CE5, 0xE7E8, 0x8CE6, 0xBDE1, 0x8CE7, 0xE7EE, 0x8CE8, 0xE7EB, 0x8CEA, 0xBDE8, + 0x8CEC, 0xBDE3, 0x8CED, 0xBDE4, 0x8CEE, 0xEBB5, 0x8CF0, 0xEBB7, 0x8CF1, 0xEBB6, 0x8CF3, 0xEBB8, 0x8CF4, 0xBFE0, 0x8CF5, 0xEBB4, + 0x8CF8, 0xC1CB, 0x8CF9, 0xEEB8, 0x8CFA, 0xC1C8, 0x8CFB, 0xC1CC, 0x8CFC, 0xC1CA, 0x8CFD, 0xC1C9, 0x8CFE, 0xF0F3, 0x8D00, 0xF0F6, + 0x8D02, 0xF0F5, 0x8D04, 0xF0F4, 0x8D05, 0xC2D8, 0x8D06, 0xF348, 0x8D07, 0xF349, 0x8D08, 0xC3D8, 0x8D09, 0xF34A, 0x8D0A, 0xC3D9, + 0x8D0D, 0xC4BA, 0x8D0F, 0xC4B9, 0x8D10, 0xF652, 0x8D13, 0xC542, 0x8D14, 0xF653, 0x8D15, 0xF75C, 0x8D16, 0xC5AB, 0x8D17, 0xC5AC, + 0x8D19, 0xF845, 0x8D1B, 0xC642, 0x8D64, 0xA8AA, 0x8D66, 0xB36A, 0x8D67, 0xB369, 0x8D68, 0xE05C, 0x8D69, 0xE05D, 0x8D6B, 0xBBAE, + 0x8D6C, 0xEBB9, 0x8D6D, 0xBDEA, 0x8D6E, 0xEBBA, 0x8D6F, 0xEEB9, 0x8D70, 0xA8AB, 0x8D72, 0xD0B2, 0x8D73, 0xAD76, 0x8D74, 0xAD75, + 0x8D76, 0xD3E3, 0x8D77, 0xB05F, 0x8D78, 0xD3E4, 0x8D79, 0xD7D5, 0x8D7B, 0xD7D4, 0x8D7D, 0xD7D3, 0x8D80, 0xDBEE, 0x8D81, 0xB658, + 0x8D84, 0xDBED, 0x8D85, 0xB657, 0x8D89, 0xDBEF, 0x8D8A, 0xB656, 0x8D8C, 0xE05F, 0x8D8D, 0xE062, 0x8D8E, 0xE060, 0x8D8F, 0xE061, + 0x8D90, 0xE065, 0x8D91, 0xE05E, 0x8D92, 0xE066, 0x8D93, 0xE063, 0x8D94, 0xE064, 0x8D95, 0xBBB0, 0x8D96, 0xE456, 0x8D99, 0xBBAF, + 0x8D9B, 0xE7F2, 0x8D9C, 0xE7F0, 0x8D9F, 0xBDEB, 0x8DA0, 0xE7EF, 0x8DA1, 0xE7F1, 0x8DA3, 0xBDEC, 0x8DA5, 0xEBBB, 0x8DA7, 0xEBBC, + 0x8DA8, 0xC1CD, 0x8DAA, 0xF34C, 0x8DAB, 0xF34E, 0x8DAC, 0xF34B, 0x8DAD, 0xF34D, 0x8DAE, 0xF4D6, 0x8DAF, 0xF654, 0x8DB2, 0xF96F, + 0x8DB3, 0xA8AC, 0x8DB4, 0xAD77, 0x8DB5, 0xD3E5, 0x8DB6, 0xD3E7, 0x8DB7, 0xD3E6, 0x8DB9, 0xD7D8, 0x8DBA, 0xB36C, 0x8DBC, 0xD7D6, + 0x8DBE, 0xB36B, 0x8DBF, 0xD7D9, 0x8DC1, 0xD7DA, 0x8DC2, 0xD7D7, 0x8DC5, 0xDBFB, 0x8DC6, 0xB660, 0x8DC7, 0xDBF3, 0x8DC8, 0xDBF9, + 0x8DCB, 0xB65B, 0x8DCC, 0xB65E, 0x8DCD, 0xDBF2, 0x8DCE, 0xB659, 0x8DCF, 0xDBF6, 0x8DD0, 0xE06C, 0x8DD1, 0xB65D, 0x8DD3, 0xDBF1, + 0x8DD5, 0xDBF7, 0x8DD6, 0xDBF4, 0x8DD7, 0xDBFA, 0x8DD8, 0xDBF0, 0x8DD9, 0xDBF8, 0x8DDA, 0xB65C, 0x8DDB, 0xB65F, 0x8DDC, 0xDBF5, + 0x8DDD, 0xB65A, 0x8DDF, 0xB8F2, 0x8DE0, 0xE068, 0x8DE1, 0xB8F1, 0x8DE2, 0xE06F, 0x8DE3, 0xE06E, 0x8DE4, 0xB8F8, 0x8DE6, 0xB8F9, + 0x8DE7, 0xE070, 0x8DE8, 0xB8F3, 0x8DE9, 0xE06D, 0x8DEA, 0xB8F7, 0x8DEB, 0xE072, 0x8DEC, 0xE069, 0x8DEE, 0xE06B, 0x8DEF, 0xB8F4, + 0x8DF0, 0xE067, 0x8DF1, 0xE06A, 0x8DF2, 0xE071, 0x8DF3, 0xB8F5, 0x8DF4, 0xE073, 0x8DFA, 0xB8F6, 0x8DFC, 0xBBB1, 0x8DFD, 0xE45B, + 0x8DFE, 0xE461, 0x8DFF, 0xE459, 0x8E00, 0xE462, 0x8E02, 0xE458, 0x8E03, 0xE45D, 0x8E04, 0xE463, 0x8E05, 0xE460, 0x8E06, 0xE45F, + 0x8E07, 0xE45E, 0x8E09, 0xE457, 0x8E0A, 0xE45C, 0x8E0D, 0xE45A, 0x8E0F, 0xBDF1, 0x8E10, 0xBDEE, 0x8E11, 0xE7FB, 0x8E12, 0xE841, + 0x8E13, 0xE843, 0x8E14, 0xE840, 0x8E15, 0xE7F8, 0x8E16, 0xE7FA, 0x8E17, 0xE845, 0x8E18, 0xE842, 0x8E19, 0xE7FC, 0x8E1A, 0xE846, + 0x8E1B, 0xE7F9, 0x8E1C, 0xE844, 0x8E1D, 0xBDEF, 0x8E1E, 0xBDF5, 0x8E1F, 0xBDF3, 0x8E20, 0xE7F3, 0x8E21, 0xBDF4, 0x8E22, 0xBDF0, + 0x8E23, 0xE7F4, 0x8E24, 0xE7F6, 0x8E25, 0xE7F5, 0x8E26, 0xE7FD, 0x8E27, 0xE7FE, 0x8E29, 0xBDF2, 0x8E2B, 0xBDED, 0x8E2E, 0xE7F7, + 0x8E30, 0xEBC6, 0x8E31, 0xBFE2, 0x8E33, 0xEBBD, 0x8E34, 0xBFE3, 0x8E35, 0xBFE6, 0x8E36, 0xEBC2, 0x8E38, 0xEBBF, 0x8E39, 0xBFE5, + 0x8E3C, 0xEBC3, 0x8E3D, 0xEBC4, 0x8E3E, 0xEBBE, 0x8E3F, 0xEBC7, 0x8E40, 0xEBC0, 0x8E41, 0xEBC5, 0x8E42, 0xBFE4, 0x8E44, 0xBFE1, + 0x8E45, 0xEBC1, 0x8E47, 0xEEBF, 0x8E48, 0xC1D0, 0x8E49, 0xC1CE, 0x8E4A, 0xC1D1, 0x8E4B, 0xC1CF, 0x8E4C, 0xEEBE, 0x8E4D, 0xEEBB, + 0x8E4E, 0xEEBA, 0x8E50, 0xEEBD, 0x8E53, 0xEEBC, 0x8E54, 0xF145, 0x8E55, 0xC2DE, 0x8E56, 0xF0FB, 0x8E57, 0xF0FA, 0x8E59, 0xC2D9, + 0x8E5A, 0xF141, 0x8E5B, 0xF140, 0x8E5C, 0xF0F7, 0x8E5D, 0xF143, 0x8E5E, 0xF0FC, 0x8E5F, 0xC2DD, 0x8E60, 0xF0F9, 0x8E61, 0xF142, + 0x8E62, 0xF0F8, 0x8E63, 0xC2DA, 0x8E64, 0xC2DC, 0x8E65, 0xF0FD, 0x8E66, 0xC2DB, 0x8E67, 0xF0FE, 0x8E69, 0xF144, 0x8E6A, 0xF352, + 0x8E6C, 0xC3DE, 0x8E6D, 0xF34F, 0x8E6F, 0xF353, 0x8E72, 0xC3DB, 0x8E73, 0xF351, 0x8E74, 0xC3E0, 0x8E76, 0xC3DD, 0x8E78, 0xF350, + 0x8E7A, 0xC3DF, 0x8E7B, 0xF354, 0x8E7C, 0xC3DA, 0x8E81, 0xC4BC, 0x8E82, 0xC4BE, 0x8E84, 0xF4D9, 0x8E85, 0xC4BD, 0x8E86, 0xF4D7, + 0x8E87, 0xC3DC, 0x8E88, 0xF4D8, 0x8E89, 0xC4BB, 0x8E8A, 0xC543, 0x8E8B, 0xC545, 0x8E8C, 0xF656, 0x8E8D, 0xC544, 0x8E8E, 0xF655, + 0x8E90, 0xF761, 0x8E91, 0xC5AD, 0x8E92, 0xF760, 0x8E93, 0xC5AE, 0x8E94, 0xF75E, 0x8E95, 0xF75D, 0x8E96, 0xF762, 0x8E97, 0xF763, + 0x8E98, 0xF846, 0x8E9A, 0xF75F, 0x8E9D, 0xF8C6, 0x8E9E, 0xF8C3, 0x8E9F, 0xF8C4, 0x8EA0, 0xF8C5, 0x8EA1, 0xC65C, 0x8EA3, 0xF951, + 0x8EA4, 0xF950, 0x8EA5, 0xF94F, 0x8EA6, 0xF970, 0x8EA8, 0xF9BE, 0x8EA9, 0xF9AB, 0x8EAA, 0xC66E, 0x8EAB, 0xA8AD, 0x8EAC, 0xB060, + 0x8EB2, 0xB8FA, 0x8EBA, 0xBDF6, 0x8EBD, 0xEBC8, 0x8EC0, 0xC2DF, 0x8EC2, 0xF355, 0x8EC9, 0xF9AC, 0x8ECA, 0xA8AE, 0x8ECB, 0xAAEE, + 0x8ECC, 0xAD79, 0x8ECD, 0xAD78, 0x8ECF, 0xB063, 0x8ED1, 0xD3E8, 0x8ED2, 0xB061, 0x8ED3, 0xD3E9, 0x8ED4, 0xB062, 0x8ED7, 0xD7DF, + 0x8ED8, 0xD7DB, 0x8EDB, 0xB36D, 0x8EDC, 0xD7DE, 0x8EDD, 0xD7DD, 0x8EDE, 0xD7DC, 0x8EDF, 0xB36E, 0x8EE0, 0xD7E0, 0x8EE1, 0xD7E1, + 0x8EE5, 0xDC43, 0x8EE6, 0xDC41, 0x8EE7, 0xDC45, 0x8EE8, 0xDC46, 0x8EE9, 0xDC4C, 0x8EEB, 0xDC48, 0x8EEC, 0xDC4A, 0x8EEE, 0xDC42, + 0x8EEF, 0xDBFC, 0x8EF1, 0xDC49, 0x8EF4, 0xDC4B, 0x8EF5, 0xDC44, 0x8EF6, 0xDC47, 0x8EF7, 0xDBFD, 0x8EF8, 0xB662, 0x8EF9, 0xDC40, + 0x8EFA, 0xDBFE, 0x8EFB, 0xB661, 0x8EFC, 0xB663, 0x8EFE, 0xB8FD, 0x8EFF, 0xE075, 0x8F00, 0xE077, 0x8F01, 0xE076, 0x8F02, 0xE07B, + 0x8F03, 0xB8FB, 0x8F05, 0xE078, 0x8F06, 0xE074, 0x8F07, 0xE079, 0x8F08, 0xE07A, 0x8F09, 0xB8FC, 0x8F0A, 0xB8FE, 0x8F0B, 0xE07C, + 0x8F0D, 0xE467, 0x8F0E, 0xE466, 0x8F10, 0xE464, 0x8F11, 0xE465, 0x8F12, 0xBBB3, 0x8F13, 0xBBB5, 0x8F14, 0xBBB2, 0x8F15, 0xBBB4, + 0x8F16, 0xE84D, 0x8F17, 0xE84E, 0x8F18, 0xE849, 0x8F1A, 0xE84A, 0x8F1B, 0xBDF8, 0x8F1C, 0xBDFD, 0x8F1D, 0xBDF7, 0x8F1E, 0xBDFE, + 0x8F1F, 0xBDF9, 0x8F20, 0xE84B, 0x8F23, 0xE84C, 0x8F24, 0xE848, 0x8F25, 0xBE40, 0x8F26, 0xBDFB, 0x8F29, 0xBDFA, 0x8F2A, 0xBDFC, + 0x8F2C, 0xE847, 0x8F2E, 0xEBCA, 0x8F2F, 0xBFE8, 0x8F32, 0xEBCC, 0x8F33, 0xBFEA, 0x8F34, 0xEBCF, 0x8F35, 0xEBCB, 0x8F36, 0xEBC9, + 0x8F37, 0xEBCE, 0x8F38, 0xBFE9, 0x8F39, 0xEBCD, 0x8F3B, 0xBFE7, 0x8F3E, 0xC1D3, 0x8F3F, 0xC1D6, 0x8F40, 0xEEC1, 0x8F42, 0xC1D4, + 0x8F43, 0xEEC0, 0x8F44, 0xC1D2, 0x8F45, 0xC1D5, 0x8F46, 0xF146, 0x8F47, 0xF147, 0x8F48, 0xF148, 0x8F49, 0xC2E0, 0x8F4B, 0xF149, + 0x8F4D, 0xC2E1, 0x8F4E, 0xC3E2, 0x8F4F, 0xF358, 0x8F50, 0xF359, 0x8F51, 0xF357, 0x8F52, 0xF356, 0x8F53, 0xF35A, 0x8F54, 0xC3E1, + 0x8F55, 0xF4DD, 0x8F56, 0xF4DB, 0x8F57, 0xF4DC, 0x8F58, 0xF4DE, 0x8F59, 0xF4DA, 0x8F5A, 0xF4DF, 0x8F5B, 0xF658, 0x8F5D, 0xF659, + 0x8F5E, 0xF657, 0x8F5F, 0xC546, 0x8F60, 0xF764, 0x8F61, 0xC5AF, 0x8F62, 0xF765, 0x8F63, 0xF848, 0x8F64, 0xF847, 0x8F9B, 0xA8AF, + 0x8F9C, 0xB664, 0x8F9F, 0xB940, 0x8FA3, 0xBBB6, 0x8FA6, 0xBFEC, 0x8FA8, 0xBFEB, 0x8FAD, 0xC3E3, 0x8FAE, 0xC47C, 0x8FAF, 0xC547, + 0x8FB0, 0xA8B0, 0x8FB1, 0xB064, 0x8FB2, 0xB941, 0x8FB4, 0xF35B, 0x8FBF, 0xCBA6, 0x8FC2, 0xA8B1, 0x8FC4, 0xA8B4, 0x8FC5, 0xA8B3, + 0x8FC6, 0xA8B2, 0x8FC9, 0xCBA5, 0x8FCB, 0xCDCD, 0x8FCD, 0xCDCF, 0x8FCE, 0xAAEF, 0x8FD1, 0xAAF1, 0x8FD2, 0xCDCC, 0x8FD3, 0xCDCE, + 0x8FD4, 0xAAF0, 0x8FD5, 0xCDD1, 0x8FD6, 0xCDD0, 0x8FD7, 0xCDD2, 0x8FE0, 0xD0B6, 0x8FE1, 0xD0B4, 0x8FE2, 0xAD7C, 0x8FE3, 0xD0B3, + 0x8FE4, 0xADA3, 0x8FE5, 0xAD7E, 0x8FE6, 0xAD7B, 0x8FE8, 0xADA4, 0x8FEA, 0xAD7D, 0x8FEB, 0xADA2, 0x8FED, 0xADA1, 0x8FEE, 0xD0B5, + 0x8FF0, 0xAD7A, 0x8FF4, 0xB06A, 0x8FF5, 0xD3EB, 0x8FF6, 0xD3F1, 0x8FF7, 0xB067, 0x8FF8, 0xB06E, 0x8FFA, 0xB069, 0x8FFB, 0xD3EE, + 0x8FFC, 0xD3F0, 0x8FFD, 0xB06C, 0x8FFE, 0xD3EA, 0x8FFF, 0xD3ED, 0x9000, 0xB068, 0x9001, 0xB065, 0x9002, 0xD3EC, 0x9003, 0xB06B, + 0x9004, 0xD3EF, 0x9005, 0xB06D, 0x9006, 0xB066, 0x900B, 0xD7E3, 0x900C, 0xD7E6, 0x900D, 0xB370, 0x900F, 0xB37A, 0x9010, 0xB376, + 0x9011, 0xD7E4, 0x9014, 0xB37E, 0x9015, 0xB377, 0x9016, 0xB37C, 0x9017, 0xB372, 0x9019, 0xB36F, 0x901A, 0xB371, 0x901B, 0xB37D, + 0x901C, 0xD7E5, 0x901D, 0xB375, 0x901E, 0xB378, 0x901F, 0xB374, 0x9020, 0xB379, 0x9021, 0xD7E7, 0x9022, 0xB37B, 0x9023, 0xB373, + 0x9024, 0xD7E2, 0x902D, 0xDC4D, 0x902E, 0xB665, 0x902F, 0xDC4F, 0x9031, 0xB667, 0x9032, 0xB669, 0x9034, 0xDC4E, 0x9035, 0xB666, + 0x9036, 0xB66A, 0x9038, 0xB668, 0x903C, 0xB947, 0x903D, 0xE0A3, 0x903E, 0xB94F, 0x903F, 0xE07E, 0x9041, 0xB950, 0x9042, 0xB945, + 0x9044, 0xE0A1, 0x9047, 0xB94A, 0x9049, 0xE0A2, 0x904A, 0xB943, 0x904B, 0xB942, 0x904D, 0xB94D, 0x904E, 0xB94C, 0x904F, 0xB94B, + 0x9050, 0xB949, 0x9051, 0xB94E, 0x9052, 0xE07D, 0x9053, 0xB944, 0x9054, 0xB946, 0x9055, 0xB948, 0x9058, 0xBBB8, 0x9059, 0xBBBB, + 0x905B, 0xBBBF, 0x905C, 0xBBB9, 0x905D, 0xBBBE, 0x905E, 0xBBBC, 0x9060, 0xBBB7, 0x9062, 0xBBBD, 0x9063, 0xBBBA, 0x9067, 0xE852, + 0x9068, 0xBE43, 0x9069, 0xBE41, 0x906B, 0xE853, 0x906D, 0xBE44, 0x906E, 0xBE42, 0x906F, 0xE851, 0x9070, 0xE850, 0x9072, 0xBFF0, + 0x9073, 0xE84F, 0x9074, 0xBFEE, 0x9075, 0xBFED, 0x9076, 0xEBD0, 0x9077, 0xBE45, 0x9078, 0xBFEF, 0x9079, 0xEBD1, 0x907A, 0xBFF2, + 0x907B, 0xEBD2, 0x907C, 0xBFF1, 0x907D, 0xC1D8, 0x907E, 0xEEC3, 0x907F, 0xC1D7, 0x9080, 0xC1DC, 0x9081, 0xC1DA, 0x9082, 0xC1DB, + 0x9083, 0xC2E3, 0x9084, 0xC1D9, 0x9085, 0xEEC2, 0x9086, 0xEBD3, 0x9087, 0xC2E2, 0x9088, 0xC2E4, 0x908A, 0xC3E4, 0x908B, 0xC3E5, + 0x908D, 0xF4E0, 0x908F, 0xC5DE, 0x9090, 0xC5DD, 0x9091, 0xA8B6, 0x9094, 0xCA55, 0x9095, 0xB06F, 0x9097, 0xCA52, 0x9098, 0xCA53, + 0x9099, 0xCA51, 0x909B, 0xCA54, 0x909E, 0xCBAA, 0x909F, 0xCBA7, 0x90A0, 0xCBAC, 0x90A1, 0xCBA8, 0x90A2, 0xA8B7, 0x90A3, 0xA8BA, + 0x90A5, 0xCBA9, 0x90A6, 0xA8B9, 0x90A7, 0xCBAB, 0x90AA, 0xA8B8, 0x90AF, 0xCDD5, 0x90B0, 0xCDD7, 0x90B1, 0xAAF4, 0x90B2, 0xCDD3, + 0x90B3, 0xCDD6, 0x90B4, 0xCDD4, 0x90B5, 0xAAF2, 0x90B6, 0xAAF5, 0x90B8, 0xAAF3, 0x90BD, 0xD0B8, 0x90BE, 0xD0BC, 0x90BF, 0xD0B9, + 0x90C1, 0xADA7, 0x90C3, 0xADA8, 0x90C5, 0xD0BB, 0x90C7, 0xD0BD, 0x90C8, 0xD0BF, 0x90CA, 0xADA5, 0x90CB, 0xD0BE, 0x90CE, 0xADA6, + 0x90D4, 0xD7EE, 0x90D5, 0xD0BA, 0x90D6, 0xD3F2, 0x90D7, 0xD3FB, 0x90D8, 0xD3F9, 0x90D9, 0xD3F4, 0x90DA, 0xD3F5, 0x90DB, 0xD3FA, + 0x90DC, 0xD3FC, 0x90DD, 0xB071, 0x90DF, 0xD3F7, 0x90E0, 0xD3F3, 0x90E1, 0xB070, 0x90E2, 0xB072, 0x90E3, 0xD3F6, 0x90E4, 0xD3FD, + 0x90E5, 0xD3F8, 0x90E8, 0xB3A1, 0x90E9, 0xD7F1, 0x90EA, 0xD7E9, 0x90EB, 0xD7EF, 0x90EC, 0xD7F0, 0x90ED, 0xB3A2, 0x90EF, 0xD7E8, + 0x90F0, 0xD7EA, 0x90F1, 0xD0B7, 0x90F2, 0xD7EC, 0x90F3, 0xD7ED, 0x90F4, 0xD7EB, 0x90F5, 0xB66C, 0x90F9, 0xDC56, 0x90FA, 0xEBD4, + 0x90FB, 0xDC57, 0x90FC, 0xDC54, 0x90FD, 0xB3A3, 0x90FE, 0xB66E, 0x90FF, 0xDC53, 0x9100, 0xDC59, 0x9101, 0xDC58, 0x9102, 0xB66B, + 0x9103, 0xDC5C, 0x9104, 0xDC52, 0x9105, 0xDC5B, 0x9106, 0xDC50, 0x9107, 0xDC5A, 0x9108, 0xDC55, 0x9109, 0xB66D, 0x910B, 0xE0AA, + 0x910D, 0xE0A5, 0x910E, 0xE0AB, 0x910F, 0xE0A6, 0x9110, 0xE0A4, 0x9111, 0xE0A7, 0x9112, 0xB951, 0x9114, 0xE0A9, 0x9116, 0xE0A8, + 0x9117, 0xB952, 0x9118, 0xBBC1, 0x9119, 0xBBC0, 0x911A, 0xE46E, 0x911B, 0xE471, 0x911C, 0xE469, 0x911D, 0xE46D, 0x911E, 0xBBC2, + 0x911F, 0xE46C, 0x9120, 0xE46A, 0x9121, 0xE470, 0x9122, 0xE46B, 0x9123, 0xE468, 0x9124, 0xE46F, 0x9126, 0xE859, 0x9127, 0xBE48, + 0x9128, 0xF14A, 0x9129, 0xE856, 0x912A, 0xE857, 0x912B, 0xE855, 0x912C, 0xDC51, 0x912D, 0xBE47, 0x912E, 0xE85A, 0x912F, 0xE854, + 0x9130, 0xBE46, 0x9131, 0xBE49, 0x9132, 0xE858, 0x9133, 0xEBD5, 0x9134, 0xBFF3, 0x9135, 0xEBD6, 0x9136, 0xEBD7, 0x9138, 0xEEC4, + 0x9139, 0xC1DD, 0x913A, 0xF14B, 0x913B, 0xF14C, 0x913E, 0xF14D, 0x913F, 0xF35D, 0x9140, 0xF35C, 0x9141, 0xF4E2, 0x9143, 0xF4E1, + 0x9144, 0xF65B, 0x9145, 0xF65C, 0x9146, 0xF65A, 0x9147, 0xF766, 0x9148, 0xC5B0, 0x9149, 0xA8BB, 0x914A, 0xADAA, 0x914B, 0xADA9, + 0x914C, 0xB075, 0x914D, 0xB074, 0x914E, 0xD440, 0x914F, 0xD441, 0x9150, 0xD3FE, 0x9152, 0xB073, 0x9153, 0xD7F5, 0x9155, 0xD7F6, + 0x9156, 0xD7F2, 0x9157, 0xB3A4, 0x9158, 0xD7F3, 0x915A, 0xD7F4, 0x915F, 0xDC5F, 0x9160, 0xDC61, 0x9161, 0xDC5D, 0x9162, 0xDC60, + 0x9163, 0xB66F, 0x9164, 0xDC5E, 0x9165, 0xB670, 0x9168, 0xDD73, 0x9169, 0xB955, 0x916A, 0xB954, 0x916C, 0xB953, 0x916E, 0xE0AC, + 0x916F, 0xE0AD, 0x9172, 0xE473, 0x9173, 0xE475, 0x9174, 0xBBC6, 0x9175, 0xBBC3, 0x9177, 0xBBC5, 0x9178, 0xBBC4, 0x9179, 0xE474, + 0x917A, 0xE472, 0x9180, 0xE861, 0x9181, 0xE85E, 0x9182, 0xE85F, 0x9183, 0xBE4D, 0x9184, 0xE860, 0x9185, 0xE85B, 0x9186, 0xE85C, + 0x9187, 0xBE4A, 0x9189, 0xBE4B, 0x918A, 0xE85D, 0x918B, 0xBE4C, 0x918D, 0xEBDB, 0x918F, 0xEBDC, 0x9190, 0xEBD9, 0x9191, 0xEBDA, + 0x9192, 0xBFF4, 0x9193, 0xEBD8, 0x9199, 0xEEC8, 0x919A, 0xEEC5, 0x919B, 0xEEC7, 0x919C, 0xC1E0, 0x919D, 0xEECB, 0x919E, 0xC1DF, + 0x919F, 0xEEC9, 0x91A0, 0xEECC, 0x91A1, 0xEECA, 0x91A2, 0xEEC6, 0x91A3, 0xC1DE, 0x91A5, 0xF14F, 0x91A7, 0xF150, 0x91A8, 0xF14E, + 0x91AA, 0xF152, 0x91AB, 0xC2E5, 0x91AC, 0xC2E6, 0x91AD, 0xF35F, 0x91AE, 0xC3E7, 0x91AF, 0xF151, 0x91B0, 0xF35E, 0x91B1, 0xC3E6, + 0x91B2, 0xF4E5, 0x91B3, 0xF4E6, 0x91B4, 0xC4BF, 0x91B5, 0xF4E4, 0x91B7, 0xF4E3, 0x91B9, 0xF65D, 0x91BA, 0xC548, 0x91BC, 0xF849, + 0x91BD, 0xF8C8, 0x91BE, 0xF8C7, 0x91C0, 0xC643, 0x91C1, 0xC65D, 0x91C2, 0xF8C9, 0x91C3, 0xF971, 0x91C5, 0xC66F, 0x91C6, 0xA8BC, + 0x91C7, 0xAAF6, 0x91C9, 0xB956, 0x91CB, 0xC4C0, 0x91CC, 0xA8BD, 0x91CD, 0xADAB, 0x91CE, 0xB3A5, 0x91CF, 0xB671, 0x91D0, 0xC2E7, + 0x91D1, 0xAAF7, 0x91D3, 0xD0C1, 0x91D4, 0xD0C0, 0x91D5, 0xD442, 0x91D7, 0xB078, 0x91D8, 0xB076, 0x91D9, 0xB07A, 0x91DA, 0xD444, + 0x91DC, 0xB079, 0x91DD, 0xB077, 0x91E2, 0xD443, 0x91E3, 0xB3A8, 0x91E4, 0xD7FC, 0x91E6, 0xB3A7, 0x91E7, 0xB3A9, 0x91E8, 0xD842, + 0x91E9, 0xB3AB, 0x91EA, 0xD7FE, 0x91EB, 0xD840, 0x91EC, 0xD7F7, 0x91ED, 0xB3AA, 0x91EE, 0xD843, 0x91F1, 0xD7F9, 0x91F3, 0xD7FA, + 0x91F4, 0xD7F8, 0x91F5, 0xB3A6, 0x91F7, 0xD841, 0x91F8, 0xD7FB, 0x91F9, 0xD7FD, 0x91FD, 0xDC6D, 0x91FF, 0xDC6C, 0x9200, 0xDC6A, + 0x9201, 0xDC62, 0x9202, 0xDC71, 0x9203, 0xDC65, 0x9204, 0xDC6F, 0x9205, 0xDC76, 0x9206, 0xDC6E, 0x9207, 0xB679, 0x9209, 0xB675, + 0x920A, 0xDC63, 0x920C, 0xDC69, 0x920D, 0xB677, 0x920F, 0xDC68, 0x9210, 0xB678, 0x9211, 0xB67A, 0x9212, 0xDC6B, 0x9214, 0xB672, + 0x9215, 0xB673, 0x9216, 0xDC77, 0x9217, 0xDC75, 0x9219, 0xDC74, 0x921A, 0xDC66, 0x921C, 0xDC72, 0x921E, 0xB676, 0x9223, 0xB674, + 0x9224, 0xDC73, 0x9225, 0xDC64, 0x9226, 0xDC67, 0x9227, 0xDC70, 0x922D, 0xE4BA, 0x922E, 0xE0B7, 0x9230, 0xE0B0, 0x9231, 0xE0C3, + 0x9232, 0xE0CC, 0x9233, 0xE0B3, 0x9234, 0xB961, 0x9236, 0xE0C0, 0x9237, 0xB957, 0x9238, 0xB959, 0x9239, 0xB965, 0x923A, 0xE0B1, + 0x923D, 0xB95A, 0x923E, 0xB95C, 0x923F, 0xB966, 0x9240, 0xB95B, 0x9245, 0xB964, 0x9246, 0xE0B9, 0x9248, 0xE0AE, 0x9249, 0xB962, + 0x924A, 0xE0B8, 0x924B, 0xB95E, 0x924C, 0xE0CA, 0x924D, 0xB963, 0x924E, 0xE0C8, 0x924F, 0xE0BC, 0x9250, 0xE0C6, 0x9251, 0xB960, + 0x9252, 0xE0AF, 0x9253, 0xE0C9, 0x9254, 0xE0C4, 0x9256, 0xE0CB, 0x9257, 0xB958, 0x925A, 0xB967, 0x925B, 0xB95D, 0x925E, 0xE0B5, + 0x9260, 0xE0BD, 0x9261, 0xE0C1, 0x9263, 0xE0C5, 0x9264, 0xB95F, 0x9265, 0xE0B4, 0x9266, 0xE0B2, 0x9267, 0xE0BE, 0x926C, 0xE0BB, + 0x926D, 0xE0BA, 0x926F, 0xE0BF, 0x9270, 0xE0C2, 0x9272, 0xE0C7, 0x9276, 0xE478, 0x9278, 0xBBC7, 0x9279, 0xE4A4, 0x927A, 0xE47A, + 0x927B, 0xBBCC, 0x927C, 0xBBD0, 0x927D, 0xE4AD, 0x927E, 0xE4B5, 0x927F, 0xE4A6, 0x9280, 0xBBC8, 0x9282, 0xE4AA, 0x9283, 0xE0B6, + 0x9285, 0xBBC9, 0x9286, 0xE4B1, 0x9287, 0xE4B6, 0x9288, 0xE4AE, 0x928A, 0xE4B0, 0x928B, 0xE4B9, 0x928C, 0xE4B2, 0x928D, 0xE47E, + 0x928E, 0xE4A9, 0x9291, 0xBBD1, 0x9293, 0xBBCD, 0x9294, 0xE47C, 0x9295, 0xE4AB, 0x9296, 0xBBCB, 0x9297, 0xE4A5, 0x9298, 0xBBCA, + 0x9299, 0xE4B3, 0x929A, 0xE4A2, 0x929B, 0xE479, 0x929C, 0xBBCE, 0x929D, 0xE4B8, 0x92A0, 0xE47B, 0x92A1, 0xE4AF, 0x92A2, 0xE4AC, + 0x92A3, 0xE4A7, 0x92A4, 0xE477, 0x92A5, 0xE476, 0x92A6, 0xE4A1, 0x92A7, 0xE4B4, 0x92A8, 0xBBCF, 0x92A9, 0xE4B7, 0x92AA, 0xE47D, + 0x92AB, 0xE4A3, 0x92AC, 0xBE52, 0x92B2, 0xBE5A, 0x92B3, 0xBE55, 0x92B4, 0xE8A4, 0x92B5, 0xE8A1, 0x92B6, 0xE867, 0x92B7, 0xBE50, + 0x92B9, 0xF9D7, 0x92BB, 0xBE4F, 0x92BC, 0xBE56, 0x92C0, 0xE865, 0x92C1, 0xBE54, 0x92C2, 0xE871, 0x92C3, 0xE863, 0x92C4, 0xE864, + 0x92C5, 0xBE4E, 0x92C6, 0xE8A3, 0x92C7, 0xBE58, 0x92C8, 0xE874, 0x92C9, 0xE879, 0x92CA, 0xE873, 0x92CB, 0xEBEE, 0x92CC, 0xE86F, + 0x92CD, 0xE877, 0x92CE, 0xE875, 0x92CF, 0xE868, 0x92D0, 0xE862, 0x92D1, 0xE87D, 0x92D2, 0xBE57, 0x92D3, 0xE87E, 0x92D5, 0xE878, + 0x92D7, 0xE86D, 0x92D8, 0xE86B, 0x92D9, 0xE866, 0x92DD, 0xE86E, 0x92DE, 0xE87B, 0x92DF, 0xE86A, 0x92E0, 0xE87A, 0x92E1, 0xE8A2, + 0x92E4, 0xBE53, 0x92E6, 0xE876, 0x92E7, 0xE87C, 0x92E8, 0xE872, 0x92E9, 0xE86C, 0x92EA, 0xBE51, 0x92EE, 0xE4A8, 0x92EF, 0xE870, + 0x92F0, 0xBE59, 0x92F1, 0xE869, 0x92F7, 0xEBF4, 0x92F8, 0xBFF7, 0x92F9, 0xEBF3, 0x92FA, 0xEBF0, 0x92FB, 0xEC44, 0x92FC, 0xBFFB, + 0x92FE, 0xEC41, 0x92FF, 0xEBF8, 0x9300, 0xEC43, 0x9301, 0xEBE9, 0x9302, 0xEBF6, 0x9304, 0xBFFD, 0x9306, 0xEBE1, 0x9308, 0xEBDF, + 0x9309, 0xEC42, 0x930B, 0xEC40, 0x930C, 0xEBFE, 0x930D, 0xEBED, 0x930E, 0xEBEC, 0x930F, 0xEBE2, 0x9310, 0xC040, 0x9312, 0xEBE8, + 0x9313, 0xEBF2, 0x9314, 0xEBFD, 0x9315, 0xC043, 0x9316, 0xEC45, 0x9318, 0xC1E8, 0x9319, 0xC045, 0x931A, 0xBFFE, 0x931B, 0xEBE6, + 0x931D, 0xEBEF, 0x931E, 0xEBDE, 0x931F, 0xEBE0, 0x9320, 0xBFF5, 0x9321, 0xC042, 0x9322, 0xBFFA, 0x9323, 0xEBE7, 0x9324, 0xEBF7, + 0x9325, 0xEBF1, 0x9326, 0xC041, 0x9327, 0xEBDD, 0x9328, 0xC1E3, 0x9329, 0xEBF9, 0x932A, 0xEBFC, 0x932B, 0xBFFC, 0x932D, 0xEBEB, + 0x932E, 0xC044, 0x932F, 0xBFF9, 0x9333, 0xBFF8, 0x9334, 0xEBF5, 0x9335, 0xEBFB, 0x9336, 0xBFF6, 0x9338, 0xEBE4, 0x9339, 0xEBFA, + 0x933C, 0xEBE5, 0x9346, 0xEBEA, 0x9347, 0xEED2, 0x9349, 0xEED7, 0x934A, 0xC1E5, 0x934B, 0xC1E7, 0x934C, 0xEEDD, 0x934D, 0xC1E1, + 0x934E, 0xEEEC, 0x934F, 0xEEE3, 0x9350, 0xEED8, 0x9351, 0xEED9, 0x9352, 0xEEE2, 0x9354, 0xC1EE, 0x9355, 0xEEE1, 0x9356, 0xEED1, + 0x9357, 0xEEE0, 0x9358, 0xEED4, 0x9359, 0xEEED, 0x935A, 0xC1ED, 0x935B, 0xC1EB, 0x935C, 0xEED5, 0x935E, 0xEEE8, 0x9360, 0xEEDA, + 0x9361, 0xEEE7, 0x9363, 0xEEE9, 0x9364, 0xEED0, 0x9365, 0xC1E6, 0x9367, 0xEEEA, 0x936A, 0xEEDE, 0x936C, 0xC1EA, 0x936D, 0xEEDB, + 0x9370, 0xC1EC, 0x9371, 0xEEE4, 0x9375, 0xC1E4, 0x9376, 0xEED6, 0x9377, 0xEEE5, 0x9379, 0xEEDF, 0x937A, 0xEBE3, 0x937B, 0xEEE6, + 0x937C, 0xEED3, 0x937E, 0xC1E9, 0x9380, 0xEEEB, 0x9382, 0xC1E2, 0x9383, 0xEECE, 0x9388, 0xF160, 0x9389, 0xF159, 0x938A, 0xC2E9, + 0x938C, 0xF154, 0x938D, 0xF163, 0x938E, 0xF15B, 0x938F, 0xEEDC, 0x9391, 0xF165, 0x9392, 0xF155, 0x9394, 0xC2E8, 0x9395, 0xF15F, + 0x9396, 0xC2EA, 0x9397, 0xC2F2, 0x9398, 0xC2F0, 0x9399, 0xF161, 0x939A, 0xC2F1, 0x939B, 0xF157, 0x939D, 0xF158, 0x939E, 0xF15D, + 0x939F, 0xF162, 0x93A1, 0xEECD, 0x93A2, 0xC2EB, 0x93A3, 0xF16A, 0x93A4, 0xF167, 0x93A5, 0xF16B, 0x93A6, 0xF15E, 0x93A7, 0xF15A, + 0x93A8, 0xF168, 0x93A9, 0xF36A, 0x93AA, 0xF15C, 0x93AC, 0xC2EE, 0x93AE, 0xC2ED, 0x93AF, 0xEECF, 0x93B0, 0xC2EF, 0x93B1, 0xF164, + 0x93B2, 0xF166, 0x93B3, 0xC2EC, 0x93B4, 0xF169, 0x93B5, 0xF153, 0x93B7, 0xF156, 0x93C0, 0xF373, 0x93C2, 0xF363, 0x93C3, 0xC3EB, + 0x93C4, 0xF371, 0x93C7, 0xF361, 0x93C8, 0xC3EC, 0x93CA, 0xF36C, 0x93CC, 0xF368, 0x93CD, 0xC3F1, 0x93CE, 0xF372, 0x93CF, 0xF362, + 0x93D0, 0xF365, 0x93D1, 0xC3E9, 0x93D2, 0xF374, 0x93D4, 0xF36D, 0x93D5, 0xF370, 0x93D6, 0xC3EF, 0x93D7, 0xC3F4, 0x93D8, 0xC3F2, + 0x93D9, 0xF369, 0x93DA, 0xF364, 0x93DC, 0xC3ED, 0x93DD, 0xC3EE, 0x93DE, 0xF360, 0x93DF, 0xC3EA, 0x93E1, 0xC3E8, 0x93E2, 0xC3F0, + 0x93E3, 0xF36F, 0x93E4, 0xC3F3, 0x93E6, 0xF36B, 0x93E7, 0xF375, 0x93E8, 0xC3F5, 0x93EC, 0xF367, 0x93EE, 0xF36E, 0x93F5, 0xF4F3, + 0x93F6, 0xF542, 0x93F7, 0xF4F5, 0x93F8, 0xF4FC, 0x93F9, 0xF366, 0x93FA, 0xF4FA, 0x93FB, 0xF4E9, 0x93FC, 0xF540, 0x93FD, 0xC4C3, + 0x93FE, 0xF4ED, 0x93FF, 0xF4FE, 0x9400, 0xF4F4, 0x9403, 0xC4C2, 0x9406, 0xF544, 0x9407, 0xF4F6, 0x9409, 0xF4FB, 0x940A, 0xF4FD, + 0x940B, 0xF4E7, 0x940C, 0xF541, 0x940D, 0xF4F2, 0x940E, 0xF4F7, 0x940F, 0xF4EB, 0x9410, 0xF4EF, 0x9411, 0xF543, 0x9412, 0xF4F9, + 0x9413, 0xF4E8, 0x9414, 0xF4EC, 0x9415, 0xF4EE, 0x9416, 0xF4F8, 0x9418, 0xC4C1, 0x9419, 0xF4F1, 0x9420, 0xF4EA, 0x9428, 0xF4F0, + 0x9429, 0xF661, 0x942A, 0xF666, 0x942B, 0xC54F, 0x942C, 0xF668, 0x942E, 0xC549, 0x9430, 0xF664, 0x9431, 0xF66A, 0x9432, 0xC54E, + 0x9433, 0xC54A, 0x9435, 0xC54B, 0x9436, 0xF660, 0x9437, 0xF667, 0x9438, 0xC54D, 0x9439, 0xF665, 0x943A, 0xC54C, 0x943B, 0xF65F, + 0x943C, 0xF663, 0x943D, 0xF662, 0x943F, 0xF65E, 0x9440, 0xF669, 0x9444, 0xC5B1, 0x9445, 0xF76D, 0x9446, 0xF770, 0x9447, 0xF76C, + 0x9448, 0xF76E, 0x9449, 0xF76F, 0x944A, 0xF769, 0x944B, 0xF76A, 0x944C, 0xF767, 0x944F, 0xF76B, 0x9450, 0xF768, 0x9451, 0xC5B2, + 0x9452, 0xC5B3, 0x9455, 0xF84B, 0x9457, 0xF84D, 0x945D, 0xF84C, 0x945E, 0xF84E, 0x9460, 0xC5E0, 0x9462, 0xF84A, 0x9463, 0xC5DF, + 0x9464, 0xC5E1, 0x9468, 0xF8CB, 0x9469, 0xF8CC, 0x946A, 0xC644, 0x946B, 0xF8CA, 0x946D, 0xF953, 0x946E, 0xF952, 0x946F, 0xF954, + 0x9470, 0xC65F, 0x9471, 0xF955, 0x9472, 0xC65E, 0x9473, 0xF956, 0x9474, 0xF972, 0x9475, 0xF975, 0x9476, 0xF974, 0x9477, 0xC668, + 0x9478, 0xF973, 0x947C, 0xC672, 0x947D, 0xC670, 0x947E, 0xC671, 0x947F, 0xC677, 0x9480, 0xF9C0, 0x9481, 0xF9C1, 0x9482, 0xF9BF, + 0x9483, 0xF9C9, 0x9577, 0xAAF8, 0x957A, 0xD844, 0x957B, 0xDC78, 0x957C, 0xE8A5, 0x957D, 0xF376, 0x9580, 0xAAF9, 0x9582, 0xADAC, + 0x9583, 0xB07B, 0x9586, 0xD845, 0x9588, 0xD846, 0x9589, 0xB3AC, 0x958B, 0xB67D, 0x958C, 0xDC7A, 0x958D, 0xDC79, 0x958E, 0xB6A3, + 0x958F, 0xB67C, 0x9590, 0xDC7B, 0x9591, 0xB67E, 0x9592, 0xB6A2, 0x9593, 0xB6A1, 0x9594, 0xB67B, 0x9598, 0xB968, 0x959B, 0xE0D0, + 0x959C, 0xE0CE, 0x959E, 0xE0CF, 0x959F, 0xE0CD, 0x95A1, 0xBBD2, 0x95A3, 0xBBD5, 0x95A4, 0xBBD7, 0x95A5, 0xBBD6, 0x95A8, 0xBBD3, + 0x95A9, 0xBBD4, 0x95AB, 0xE8A7, 0x95AC, 0xE8A6, 0x95AD, 0xBE5B, 0x95AE, 0xE8A8, 0x95B0, 0xE8A9, 0x95B1, 0xBE5C, 0x95B5, 0xEC4D, + 0x95B6, 0xEC4B, 0x95B7, 0xEEF3, 0x95B9, 0xEC49, 0x95BA, 0xEC4A, 0x95BB, 0xC046, 0x95BC, 0xEC46, 0x95BD, 0xEC4E, 0x95BE, 0xEC48, + 0x95BF, 0xEC4C, 0x95C0, 0xEEEF, 0x95C3, 0xEEF1, 0x95C5, 0xEEF2, 0x95C6, 0xC1F3, 0x95C7, 0xEEEE, 0x95C8, 0xC1F2, 0x95C9, 0xEEF0, + 0x95CA, 0xC1EF, 0x95CB, 0xC1F0, 0x95CC, 0xC1F1, 0x95CD, 0xEC47, 0x95D0, 0xC2F5, 0x95D1, 0xF16E, 0x95D2, 0xF16C, 0x95D3, 0xF16D, + 0x95D4, 0xC2F3, 0x95D5, 0xC2F6, 0x95D6, 0xC2F4, 0x95DA, 0xF377, 0x95DB, 0xF378, 0x95DC, 0xC3F6, 0x95DE, 0xF545, 0x95DF, 0xF547, + 0x95E0, 0xF546, 0x95E1, 0xC4C4, 0x95E2, 0xC550, 0x95E3, 0xF66D, 0x95E4, 0xF66C, 0x95E5, 0xF66B, 0x961C, 0xAAFA, 0x961E, 0xC9AA, + 0x9620, 0xCA58, 0x9621, 0xA6E9, 0x9622, 0xCA56, 0x9623, 0xCA59, 0x9624, 0xCA57, 0x9628, 0xCBAE, 0x962A, 0xA8C1, 0x962C, 0xA8C2, + 0x962D, 0xCBB0, 0x962E, 0xA8BF, 0x962F, 0xCBAF, 0x9630, 0xCBAD, 0x9631, 0xA8C0, 0x9632, 0xA8BE, 0x9639, 0xCDD8, 0x963A, 0xCDDB, + 0x963B, 0xAAFD, 0x963C, 0xCDDA, 0x963D, 0xCDD9, 0x963F, 0xAAFC, 0x9640, 0xAAFB, 0x9642, 0xAB40, 0x9643, 0xCDDC, 0x9644, 0xAAFE, + 0x964A, 0xD0C6, 0x964B, 0xADAE, 0x964C, 0xADAF, 0x964D, 0xADB0, 0x964E, 0xD0C7, 0x964F, 0xD0C3, 0x9650, 0xADAD, 0x9651, 0xD0C4, + 0x9653, 0xD0C5, 0x9654, 0xD0C2, 0x9658, 0xB0A4, 0x965B, 0xB0A1, 0x965C, 0xD445, 0x965D, 0xB0A2, 0x965E, 0xB0A5, 0x965F, 0xD446, + 0x9661, 0xB07E, 0x9662, 0xB07C, 0x9663, 0xB07D, 0x9664, 0xB0A3, 0x966A, 0xB3AD, 0x966B, 0xD849, 0x966C, 0xB3B5, 0x966D, 0xD848, + 0x966F, 0xD84B, 0x9670, 0xB3B1, 0x9671, 0xD84A, 0x9672, 0xB6AB, 0x9673, 0xB3AF, 0x9674, 0xB3B2, 0x9675, 0xB3AE, 0x9676, 0xB3B3, + 0x9677, 0xB3B4, 0x9678, 0xB3B0, 0x967C, 0xD847, 0x967D, 0xB6A7, 0x967E, 0xDC7D, 0x9680, 0xDCA3, 0x9683, 0xDCA2, 0x9684, 0xB6AC, + 0x9685, 0xB6A8, 0x9686, 0xB6A9, 0x9687, 0xDC7C, 0x9688, 0xDC7E, 0x9689, 0xDCA1, 0x968A, 0xB6A4, 0x968B, 0xB6A6, 0x968D, 0xB6AA, + 0x968E, 0xB6A5, 0x9691, 0xE0D3, 0x9692, 0xE0D1, 0x9693, 0xE0D2, 0x9694, 0xB96A, 0x9695, 0xB96B, 0x9697, 0xE0D4, 0x9698, 0xB969, + 0x9699, 0xBBD8, 0x969B, 0xBBDA, 0x969C, 0xBBD9, 0x969E, 0xE4BB, 0x96A1, 0xE4BC, 0x96A2, 0xE8AB, 0x96A4, 0xE8AA, 0x96A7, 0xC047, + 0x96A8, 0xC048, 0x96A9, 0xEC4F, 0x96AA, 0xC049, 0x96AC, 0xEEF6, 0x96AE, 0xEEF4, 0x96B0, 0xEEF5, 0x96B1, 0xC1F4, 0x96B3, 0xF16F, + 0x96B4, 0xC3F7, 0x96B8, 0xC1F5, 0x96B9, 0xAB41, 0x96BB, 0xB0A6, 0x96BC, 0xD447, 0x96BF, 0xD84C, 0x96C0, 0xB3B6, 0x96C1, 0xB6AD, + 0x96C2, 0xDCA4, 0x96C3, 0xDCA6, 0x96C4, 0xB6AF, 0x96C5, 0xB6AE, 0x96C6, 0xB6B0, 0x96C7, 0xB6B1, 0x96C8, 0xDCA5, 0x96C9, 0xB96E, + 0x96CA, 0xB96F, 0x96CB, 0xB96D, 0x96CC, 0xBBDB, 0x96CD, 0xB96C, 0x96CE, 0xE0D5, 0x96D2, 0xBBDC, 0x96D3, 0xE8AC, 0x96D4, 0xEC50, + 0x96D5, 0xC04A, 0x96D6, 0xC1F6, 0x96D7, 0xF170, 0x96D8, 0xF174, 0x96D9, 0xC2F9, 0x96DA, 0xF171, 0x96DB, 0xC2FA, 0x96DC, 0xC2F8, + 0x96DD, 0xF175, 0x96DE, 0xC2FB, 0x96DF, 0xF173, 0x96E1, 0xF379, 0x96E2, 0xC2F7, 0x96E3, 0xC3F8, 0x96E5, 0xF8CD, 0x96E8, 0xAB42, + 0x96E9, 0xB3B8, 0x96EA, 0xB3B7, 0x96EF, 0xB6B2, 0x96F0, 0xDCA8, 0x96F1, 0xDCA7, 0x96F2, 0xB6B3, 0x96F5, 0xE0D9, 0x96F6, 0xB973, + 0x96F7, 0xB970, 0x96F8, 0xE0D8, 0x96F9, 0xB972, 0x96FA, 0xE0D6, 0x96FB, 0xB971, 0x96FD, 0xE0D7, 0x96FF, 0xE4BD, 0x9700, 0xBBDD, + 0x9702, 0xE8AF, 0x9704, 0xBE5D, 0x9705, 0xE8AD, 0x9706, 0xBE5E, 0x9707, 0xBE5F, 0x9708, 0xE8AE, 0x9709, 0xBE60, 0x970B, 0xEC51, + 0x970D, 0xC04E, 0x970E, 0xC04B, 0x970F, 0xC050, 0x9710, 0xEC53, 0x9711, 0xC04C, 0x9712, 0xEC52, 0x9713, 0xC04F, 0x9716, 0xC04D, + 0x9718, 0xEEF9, 0x9719, 0xEEFB, 0x971C, 0xC1F7, 0x971D, 0xEEFA, 0x971E, 0xC1F8, 0x971F, 0xEEF8, 0x9720, 0xEEF7, 0x9722, 0xF177, + 0x9723, 0xF176, 0x9724, 0xC2FC, 0x9725, 0xF178, 0x9726, 0xF37E, 0x9727, 0xC3FA, 0x9728, 0xF37D, 0x9729, 0xF37A, 0x972A, 0xC3F9, + 0x972B, 0xF37B, 0x972C, 0xF37C, 0x972E, 0xF548, 0x972F, 0xF549, 0x9730, 0xC4C5, 0x9732, 0xC553, 0x9735, 0xF66E, 0x9738, 0xC551, + 0x9739, 0xC552, 0x973A, 0xF66F, 0x973D, 0xC5B4, 0x973E, 0xC5B5, 0x973F, 0xF771, 0x9742, 0xC645, 0x9743, 0xF8CF, 0x9744, 0xC647, + 0x9746, 0xF8CE, 0x9747, 0xF8D0, 0x9748, 0xC646, 0x9749, 0xF957, 0x974B, 0xF9AD, 0x9752, 0xAB43, 0x9756, 0xB974, 0x9758, 0xE4BE, + 0x975A, 0xE8B0, 0x975B, 0xC051, 0x975C, 0xC052, 0x975E, 0xAB44, 0x9760, 0xBE61, 0x9761, 0xC3FB, 0x9762, 0xADB1, 0x9766, 0xC053, + 0x9768, 0xC5E2, 0x9769, 0xADB2, 0x976A, 0xD84D, 0x976C, 0xDCA9, 0x976E, 0xDCAB, 0x9770, 0xDCAA, 0x9772, 0xE0DD, 0x9773, 0xE0DA, + 0x9774, 0xB975, 0x9776, 0xB976, 0x9777, 0xE0DB, 0x9778, 0xE0DC, 0x977A, 0xE4C0, 0x977B, 0xE4C5, 0x977C, 0xBBDE, 0x977D, 0xE4BF, + 0x977E, 0xE4C1, 0x977F, 0xE4C8, 0x9780, 0xE4C3, 0x9781, 0xE4C7, 0x9782, 0xE4C4, 0x9783, 0xE4C2, 0x9784, 0xE4C6, 0x9785, 0xBBDF, + 0x9788, 0xE8B3, 0x978A, 0xE8B1, 0x978B, 0xBE63, 0x978D, 0xBE62, 0x978E, 0xE8B2, 0x978F, 0xBE64, 0x9794, 0xEC56, 0x9797, 0xEC55, + 0x9798, 0xC054, 0x9799, 0xEC54, 0x979A, 0xEEFC, 0x979C, 0xEEFE, 0x979D, 0xEF41, 0x979E, 0xEF40, 0x97A0, 0xC1F9, 0x97A1, 0xEEFD, + 0x97A2, 0xF1A1, 0x97A3, 0xC2FD, 0x97A4, 0xF17D, 0x97A5, 0xF1A2, 0x97A6, 0xC2FE, 0x97A8, 0xF17B, 0x97AA, 0xF17E, 0x97AB, 0xF17C, + 0x97AC, 0xF179, 0x97AD, 0xC340, 0x97AE, 0xF17A, 0x97B3, 0xF3A1, 0x97B6, 0xF3A3, 0x97B7, 0xF3A2, 0x97B9, 0xF54A, 0x97BB, 0xF54B, + 0x97BF, 0xF670, 0x97C1, 0xC5B7, 0x97C3, 0xC5B6, 0x97C4, 0xF84F, 0x97C5, 0xF850, 0x97C6, 0xC648, 0x97C7, 0xF8D1, 0x97C9, 0xC669, + 0x97CB, 0xADB3, 0x97CC, 0xB6B4, 0x97CD, 0xE4CA, 0x97CE, 0xE4C9, 0x97CF, 0xE8B5, 0x97D0, 0xE8B4, 0x97D3, 0xC1FA, 0x97D4, 0xEF43, + 0x97D5, 0xEF42, 0x97D6, 0xF1A5, 0x97D7, 0xF1A3, 0x97D8, 0xF1A6, 0x97D9, 0xF1A4, 0x97DC, 0xC3FC, 0x97DD, 0xF3A4, 0x97DE, 0xF3A5, + 0x97DF, 0xF3A6, 0x97E1, 0xF671, 0x97E3, 0xF772, 0x97E5, 0xF8D2, 0x97ED, 0xADB4, 0x97F0, 0xEC57, 0x97F1, 0xEF44, 0x97F3, 0xADB5, + 0x97F6, 0xBBE0, 0x97F8, 0xEC58, 0x97F9, 0xC341, 0x97FA, 0xF1A7, 0x97FB, 0xC3FD, 0x97FD, 0xF54C, 0x97FE, 0xF54D, 0x97FF, 0xC554, + 0x9800, 0xF851, 0x9801, 0xADB6, 0x9802, 0xB3BB, 0x9803, 0xB3BC, 0x9804, 0xD84E, 0x9805, 0xB6B5, 0x9806, 0xB6B6, 0x9807, 0xDCAC, + 0x9808, 0xB6B7, 0x980A, 0xB97A, 0x980C, 0xB97C, 0x980D, 0xE0DF, 0x980E, 0xE0E0, 0x980F, 0xE0DE, 0x9810, 0xB977, 0x9811, 0xB978, + 0x9812, 0xB97B, 0x9813, 0xB979, 0x9816, 0xE4CB, 0x9817, 0xBBE1, 0x9818, 0xBBE2, 0x981B, 0xE8BC, 0x981C, 0xBE67, 0x981D, 0xE8B7, + 0x981E, 0xE8B6, 0x9820, 0xE8BB, 0x9821, 0xBE65, 0x9824, 0xC05B, 0x9826, 0xE8B8, 0x9827, 0xE8BD, 0x9828, 0xE8BA, 0x9829, 0xE8B9, + 0x982B, 0xBE66, 0x982D, 0xC059, 0x982F, 0xEC5A, 0x9830, 0xC055, 0x9832, 0xEC5B, 0x9835, 0xEC59, 0x9837, 0xC058, 0x9838, 0xC056, + 0x9839, 0xC05A, 0x983B, 0xC057, 0x9841, 0xEF45, 0x9843, 0xEF4A, 0x9844, 0xEF46, 0x9845, 0xEF49, 0x9846, 0xC1FB, 0x9848, 0xEDD4, + 0x9849, 0xEF48, 0x984A, 0xEF47, 0x984C, 0xC344, 0x984D, 0xC342, 0x984E, 0xC345, 0x984F, 0xC343, 0x9850, 0xF1A8, 0x9851, 0xF1A9, + 0x9852, 0xF1AA, 0x9853, 0xC346, 0x9857, 0xF3AA, 0x9858, 0xC440, 0x9859, 0xF3A8, 0x985B, 0xC441, 0x985C, 0xF3A7, 0x985D, 0xF3A9, + 0x985E, 0xC3FE, 0x985F, 0xF551, 0x9860, 0xF54E, 0x9862, 0xF54F, 0x9863, 0xF550, 0x9864, 0xF672, 0x9865, 0xC556, 0x9867, 0xC555, + 0x9869, 0xF774, 0x986A, 0xF773, 0x986B, 0xC5B8, 0x986F, 0xC5E3, 0x9870, 0xC649, 0x9871, 0xC660, 0x9872, 0xF958, 0x9873, 0xF9AE, + 0x9874, 0xF9AF, 0x98A8, 0xADB7, 0x98A9, 0xDCAD, 0x98AC, 0xE0E1, 0x98AD, 0xE4CC, 0x98AE, 0xE4CD, 0x98AF, 0xBBE3, 0x98B1, 0xBBE4, + 0x98B2, 0xE8BE, 0x98B3, 0xBE68, 0x98B6, 0xC1FC, 0x98B8, 0xF1AB, 0x98BA, 0xC347, 0x98BB, 0xF3AD, 0x98BC, 0xC442, 0x98BD, 0xF3AC, + 0x98BE, 0xF3AE, 0x98BF, 0xF3AB, 0x98C0, 0xF675, 0x98C1, 0xF552, 0x98C2, 0xF553, 0x98C4, 0xC4C6, 0x98C6, 0xF674, 0x98C9, 0xF673, + 0x98CB, 0xF775, 0x98CC, 0xF9B0, 0x98DB, 0xADB8, 0x98DF, 0xADB9, 0x98E2, 0xB0A7, 0x98E3, 0xD448, 0x98E5, 0xD84F, 0x98E7, 0xB6B8, + 0x98E9, 0xB6BB, 0x98EA, 0xB6B9, 0x98EB, 0xDCAE, 0x98ED, 0xB6BD, 0x98EF, 0xB6BA, 0x98F2, 0xB6BC, 0x98F4, 0xB97E, 0x98F6, 0xE0E2, + 0x98F9, 0xE0E3, 0x98FA, 0xE8C0, 0x98FC, 0xB97D, 0x98FD, 0xB9A1, 0x98FE, 0xB9A2, 0x9900, 0xE4CF, 0x9902, 0xE4CE, 0x9903, 0xBBE5, + 0x9905, 0xBBE6, 0x9907, 0xE4D0, 0x9908, 0xE8BF, 0x9909, 0xBBE8, 0x990A, 0xBE69, 0x990C, 0xBBE7, 0x9910, 0xC05C, 0x9911, 0xE8C1, + 0x9912, 0xBE6B, 0x9913, 0xBE6A, 0x9914, 0xE8C2, 0x9915, 0xE8C5, 0x9916, 0xE8C3, 0x9917, 0xE8C4, 0x9918, 0xBE6C, 0x991A, 0xC061, + 0x991B, 0xC05F, 0x991E, 0xC05E, 0x991F, 0xEC5D, 0x9921, 0xC060, 0x9924, 0xEC5C, 0x9925, 0xEF4B, 0x9927, 0xEC5E, 0x9928, 0xC05D, + 0x9929, 0xEC5F, 0x992A, 0xEF4E, 0x992B, 0xEF4C, 0x992C, 0xEF4D, 0x992D, 0xEF52, 0x992E, 0xC34B, 0x992F, 0xEF51, 0x9930, 0xEF54, + 0x9931, 0xEF53, 0x9932, 0xEF50, 0x9933, 0xEF4F, 0x9935, 0xC1FD, 0x993A, 0xF1AE, 0x993C, 0xF1AD, 0x993D, 0xC34A, 0x993E, 0xC348, + 0x993F, 0xC349, 0x9941, 0xF1AC, 0x9943, 0xF3B1, 0x9945, 0xC443, 0x9947, 0xF3B0, 0x9948, 0xF3AF, 0x9949, 0xC444, 0x994B, 0xF558, + 0x994C, 0xF557, 0x994E, 0xF555, 0x9950, 0xF554, 0x9951, 0xC4C8, 0x9952, 0xC4C7, 0x9953, 0xF559, 0x9954, 0xF776, 0x9955, 0xC5B9, + 0x9956, 0xF677, 0x9957, 0xC557, 0x9958, 0xF676, 0x9959, 0xF556, 0x995B, 0xF777, 0x995C, 0xC5E4, 0x995E, 0xC661, 0x995F, 0xF959, + 0x9961, 0xF9B1, 0x9996, 0xADBA, 0x9997, 0xD850, 0x9998, 0xEF55, 0x9999, 0xADBB, 0x999C, 0xE4D2, 0x999D, 0xE4D1, 0x999E, 0xEC60, + 0x99A1, 0xEF57, 0x99A3, 0xEF56, 0x99A5, 0xC34C, 0x99A6, 0xF3B2, 0x99A7, 0xF3B3, 0x99A8, 0xC4C9, 0x99AB, 0xF9B2, 0x99AC, 0xB0A8, + 0x99AD, 0xB6BF, 0x99AE, 0xB6BE, 0x99AF, 0xE0E4, 0x99B0, 0xE0E6, 0x99B1, 0xB9A4, 0x99B2, 0xE0E5, 0x99B3, 0xB9A3, 0x99B4, 0xB9A5, + 0x99B5, 0xE0E7, 0x99B9, 0xE4D4, 0x99BA, 0xE4D6, 0x99BB, 0xE4D5, 0x99BD, 0xE4D8, 0x99C1, 0xBBE9, 0x99C2, 0xE4D7, 0x99C3, 0xE4D3, + 0x99C7, 0xE4D9, 0x99C9, 0xE8CC, 0x99CB, 0xE8CF, 0x99CC, 0xE8D1, 0x99CD, 0xE8C7, 0x99CE, 0xE8CB, 0x99CF, 0xE8C8, 0x99D0, 0xBE6E, + 0x99D1, 0xBE71, 0x99D2, 0xBE73, 0x99D3, 0xE8C9, 0x99D4, 0xE8CA, 0x99D5, 0xBE72, 0x99D6, 0xE8CD, 0x99D7, 0xE8D0, 0x99D8, 0xE8CE, + 0x99D9, 0xBE74, 0x99DB, 0xBE70, 0x99DC, 0xE8C6, 0x99DD, 0xBE6D, 0x99DF, 0xBE6F, 0x99E2, 0xC063, 0x99E3, 0xEC66, 0x99E4, 0xEC64, + 0x99E5, 0xEC63, 0x99E7, 0xEC69, 0x99E9, 0xEC68, 0x99EA, 0xEC67, 0x99EC, 0xEC62, 0x99ED, 0xC062, 0x99EE, 0xEC61, 0x99F0, 0xEC65, + 0x99F1, 0xC064, 0x99F4, 0xEF5A, 0x99F6, 0xEF5E, 0x99F7, 0xEF5B, 0x99F8, 0xEF5D, 0x99F9, 0xEF5C, 0x99FA, 0xEF59, 0x99FB, 0xEF5F, + 0x99FC, 0xEF62, 0x99FD, 0xEF60, 0x99FE, 0xEF61, 0x99FF, 0xC240, 0x9A01, 0xC1FE, 0x9A02, 0xEF58, 0x9A03, 0xEF63, 0x9A04, 0xF1B3, + 0x9A05, 0xF1B6, 0x9A06, 0xF1B8, 0x9A07, 0xF1B7, 0x9A09, 0xF1B1, 0x9A0A, 0xF1B5, 0x9A0B, 0xF1B0, 0x9A0D, 0xF1B2, 0x9A0E, 0xC34D, + 0x9A0F, 0xF1AF, 0x9A11, 0xF1B4, 0x9A14, 0xF3C0, 0x9A15, 0xF3B5, 0x9A16, 0xC445, 0x9A19, 0xC446, 0x9A1A, 0xF3B4, 0x9A1B, 0xF3B9, + 0x9A1C, 0xF3BF, 0x9A1D, 0xF3B7, 0x9A1E, 0xF3BE, 0x9A20, 0xF3BB, 0x9A22, 0xF3BA, 0x9A23, 0xF3BD, 0x9A24, 0xF3B8, 0x9A25, 0xF3B6, + 0x9A27, 0xF3BC, 0x9A29, 0xF560, 0x9A2A, 0xF55E, 0x9A2B, 0xC4CA, 0x9A2C, 0xF55D, 0x9A2D, 0xF563, 0x9A2E, 0xF561, 0x9A30, 0xC4CB, + 0x9A31, 0xF55C, 0x9A32, 0xF55A, 0x9A34, 0xF55B, 0x9A35, 0xC4CD, 0x9A36, 0xF55F, 0x9A37, 0xC4CC, 0x9A38, 0xF562, 0x9A39, 0xF678, + 0x9A3A, 0xF67E, 0x9A3D, 0xF679, 0x9A3E, 0xC55B, 0x9A3F, 0xF6A1, 0x9A40, 0xC55A, 0x9A41, 0xF67D, 0x9A42, 0xF67C, 0x9A43, 0xC559, + 0x9A44, 0xF67B, 0x9A45, 0xC558, 0x9A46, 0xF67A, 0x9A48, 0xF77D, 0x9A49, 0xF7A1, 0x9A4A, 0xF77E, 0x9A4C, 0xF77B, 0x9A4D, 0xC5BB, + 0x9A4E, 0xF778, 0x9A4F, 0xF77C, 0x9A50, 0xF7A3, 0x9A52, 0xF7A2, 0x9A53, 0xF779, 0x9A54, 0xF77A, 0x9A55, 0xC5BA, 0x9A56, 0xF852, + 0x9A57, 0xC5E7, 0x9A59, 0xF853, 0x9A5A, 0xC5E5, 0x9A5B, 0xC5E6, 0x9A5E, 0xF8D3, 0x9A5F, 0xC64A, 0x9A60, 0xF976, 0x9A62, 0xC66A, + 0x9A64, 0xF9B3, 0x9A65, 0xC66B, 0x9A66, 0xF9B4, 0x9A67, 0xF9B5, 0x9A68, 0xF9C3, 0x9A69, 0xF9C2, 0x9A6A, 0xC67A, 0x9A6B, 0xF9CD, + 0x9AA8, 0xB0A9, 0x9AAB, 0xE0E9, 0x9AAD, 0xE0E8, 0x9AAF, 0xBBEA, 0x9AB0, 0xBBEB, 0x9AB1, 0xE4DA, 0x9AB3, 0xE8D2, 0x9AB4, 0xEC6C, + 0x9AB7, 0xBE75, 0x9AB8, 0xC065, 0x9AB9, 0xEC6A, 0x9ABB, 0xEC6D, 0x9ABC, 0xC066, 0x9ABE, 0xEF64, 0x9ABF, 0xEC6B, 0x9AC0, 0xF1B9, + 0x9AC1, 0xC34E, 0x9AC2, 0xF3C1, 0x9AC6, 0xF566, 0x9AC7, 0xF564, 0x9ACA, 0xF565, 0x9ACD, 0xF6A2, 0x9ACF, 0xC55C, 0x9AD0, 0xF7A4, + 0x9AD1, 0xC5EA, 0x9AD2, 0xC5BC, 0x9AD3, 0xC5E8, 0x9AD4, 0xC5E9, 0x9AD5, 0xF8D4, 0x9AD6, 0xC662, 0x9AD8, 0xB0AA, 0x9ADC, 0xF1BA, + 0x9ADF, 0xD449, 0x9AE1, 0xB9A6, 0x9AE3, 0xE4DB, 0x9AE6, 0xBBEC, 0x9AE7, 0xE4DC, 0x9AEB, 0xE8D4, 0x9AEC, 0xE8D3, 0x9AED, 0xC068, + 0x9AEE, 0xBE76, 0x9AEF, 0xBE77, 0x9AF1, 0xE8D7, 0x9AF2, 0xE8D6, 0x9AF3, 0xE8D5, 0x9AF6, 0xEC6E, 0x9AF7, 0xEC71, 0x9AF9, 0xEC70, + 0x9AFA, 0xEC6F, 0x9AFB, 0xC067, 0x9AFC, 0xEF68, 0x9AFD, 0xEF66, 0x9AFE, 0xEF65, 0x9B01, 0xEF67, 0x9B03, 0xC34F, 0x9B04, 0xF1BC, + 0x9B05, 0xF1BD, 0x9B06, 0xC350, 0x9B08, 0xF1BB, 0x9B0A, 0xF3C3, 0x9B0B, 0xF3C2, 0x9B0C, 0xF3C5, 0x9B0D, 0xC447, 0x9B0E, 0xF3C4, + 0x9B10, 0xF567, 0x9B11, 0xF569, 0x9B12, 0xF568, 0x9B15, 0xF6A3, 0x9B16, 0xF6A6, 0x9B17, 0xF6A4, 0x9B18, 0xF6A5, 0x9B19, 0xF7A5, + 0x9B1A, 0xC5BD, 0x9B1E, 0xF854, 0x9B1F, 0xF855, 0x9B20, 0xF856, 0x9B22, 0xC64B, 0x9B23, 0xC663, 0x9B24, 0xF9B6, 0x9B25, 0xB0AB, + 0x9B27, 0xBE78, 0x9B28, 0xC069, 0x9B29, 0xF1BE, 0x9B2B, 0xF7A6, 0x9B2E, 0xF9C4, 0x9B2F, 0xD44A, 0x9B31, 0xC67B, 0x9B32, 0xB0AC, + 0x9B33, 0xEC72, 0x9B35, 0xF1BF, 0x9B37, 0xF3C6, 0x9B3A, 0xF6A7, 0x9B3B, 0xF7A7, 0x9B3C, 0xB0AD, 0x9B3E, 0xE4DD, 0x9B3F, 0xE4DE, + 0x9B41, 0xBBED, 0x9B42, 0xBBEE, 0x9B43, 0xE8D9, 0x9B44, 0xBE7A, 0x9B45, 0xBE79, 0x9B46, 0xE8D8, 0x9B48, 0xEF69, 0x9B4A, 0xF1C0, + 0x9B4B, 0xF1C2, 0x9B4C, 0xF1C1, 0x9B4D, 0xC353, 0x9B4E, 0xC352, 0x9B4F, 0xC351, 0x9B51, 0xC55E, 0x9B52, 0xF6A8, 0x9B54, 0xC55D, + 0x9B55, 0xF7A9, 0x9B56, 0xF7A8, 0x9B58, 0xC64C, 0x9B59, 0xF8D5, 0x9B5A, 0xB3BD, 0x9B5B, 0xE0EA, 0x9B5F, 0xE4E1, 0x9B60, 0xE4DF, + 0x9B61, 0xE4E0, 0x9B64, 0xE8E2, 0x9B66, 0xE8DD, 0x9B67, 0xE8DA, 0x9B68, 0xE8E1, 0x9B6C, 0xE8E3, 0x9B6F, 0xBE7C, 0x9B70, 0xE8E0, + 0x9B71, 0xE8DC, 0x9B74, 0xE8DB, 0x9B75, 0xE8DF, 0x9B76, 0xE8DE, 0x9B77, 0xBE7B, 0x9B7A, 0xEC7D, 0x9B7B, 0xEC78, 0x9B7C, 0xEC76, + 0x9B7D, 0xECA1, 0x9B7E, 0xEC77, 0x9B80, 0xEC73, 0x9B82, 0xEC79, 0x9B85, 0xEC74, 0x9B86, 0xEF72, 0x9B87, 0xEC75, 0x9B88, 0xECA2, + 0x9B90, 0xEC7C, 0x9B91, 0xC06A, 0x9B92, 0xEC7B, 0x9B93, 0xEC7A, 0x9B95, 0xEC7E, 0x9B9A, 0xEF6A, 0x9B9B, 0xEF6D, 0x9B9E, 0xEF6C, + 0x9BA0, 0xEF74, 0x9BA1, 0xEF6F, 0x9BA2, 0xEF73, 0x9BA4, 0xEF71, 0x9BA5, 0xEF70, 0x9BA6, 0xEF6E, 0x9BA8, 0xEF6B, 0x9BAA, 0xC243, + 0x9BAB, 0xC242, 0x9BAD, 0xC244, 0x9BAE, 0xC241, 0x9BAF, 0xEF75, 0x9BB5, 0xF1C8, 0x9BB6, 0xF1CB, 0x9BB8, 0xF1C9, 0x9BB9, 0xF1CD, + 0x9BBD, 0xF1CE, 0x9BBF, 0xF1C6, 0x9BC0, 0xC358, 0x9BC1, 0xF1C7, 0x9BC3, 0xF1C5, 0x9BC4, 0xF1CC, 0x9BC6, 0xF1C4, 0x9BC7, 0xF1C3, + 0x9BC8, 0xC357, 0x9BC9, 0xC355, 0x9BCA, 0xC354, 0x9BD3, 0xF1CA, 0x9BD4, 0xF3CF, 0x9BD5, 0xF3D5, 0x9BD6, 0xC44A, 0x9BD7, 0xF3D0, + 0x9BD9, 0xF3D3, 0x9BDA, 0xF3D7, 0x9BDB, 0xC44B, 0x9BDC, 0xF3D2, 0x9BDE, 0xF3CA, 0x9BE0, 0xF3C9, 0x9BE1, 0xF3D6, 0x9BE2, 0xF3CD, + 0x9BE4, 0xF3CB, 0x9BE5, 0xF3D4, 0x9BE6, 0xF3CC, 0x9BE7, 0xC449, 0x9BE8, 0xC448, 0x9BEA, 0xF3C7, 0x9BEB, 0xF3C8, 0x9BEC, 0xF3D1, + 0x9BF0, 0xF3CE, 0x9BF7, 0xF56C, 0x9BF8, 0xF56F, 0x9BFD, 0xC356, 0x9C05, 0xF56D, 0x9C06, 0xF573, 0x9C07, 0xF571, 0x9C08, 0xF56B, + 0x9C09, 0xF576, 0x9C0B, 0xF56A, 0x9C0D, 0xC4CF, 0x9C0E, 0xF572, 0x9C12, 0xF56E, 0x9C13, 0xC4CE, 0x9C14, 0xF575, 0x9C17, 0xF574, + 0x9C1C, 0xF6AB, 0x9C1D, 0xF6AA, 0x9C21, 0xF6B1, 0x9C23, 0xF6AD, 0x9C24, 0xF6B0, 0x9C25, 0xC560, 0x9C28, 0xF6AE, 0x9C29, 0xF6AF, + 0x9C2B, 0xF6A9, 0x9C2C, 0xF6AC, 0x9C2D, 0xC55F, 0x9C31, 0xC5BF, 0x9C32, 0xF7B4, 0x9C33, 0xF7AF, 0x9C34, 0xF7B3, 0x9C36, 0xF7B6, + 0x9C37, 0xF7B2, 0x9C39, 0xF7AE, 0x9C3B, 0xC5C1, 0x9C3C, 0xF7B1, 0x9C3D, 0xF7B5, 0x9C3E, 0xC5C0, 0x9C3F, 0xF7AC, 0x9C40, 0xF570, + 0x9C41, 0xF7B0, 0x9C44, 0xF7AD, 0x9C46, 0xF7AA, 0x9C48, 0xF7AB, 0x9C49, 0xC5BE, 0x9C4A, 0xF85A, 0x9C4B, 0xF85C, 0x9C4C, 0xF85F, + 0x9C4D, 0xF85B, 0x9C4E, 0xF860, 0x9C50, 0xF859, 0x9C52, 0xF857, 0x9C54, 0xC5EB, 0x9C55, 0xF85D, 0x9C56, 0xC5ED, 0x9C57, 0xC5EC, + 0x9C58, 0xF858, 0x9C59, 0xF85E, 0x9C5E, 0xF8DA, 0x9C5F, 0xC64D, 0x9C60, 0xF8DB, 0x9C62, 0xF8D9, 0x9C63, 0xF8D6, 0x9C66, 0xF8D8, + 0x9C67, 0xF8D7, 0x9C68, 0xF95A, 0x9C6D, 0xF95C, 0x9C6E, 0xF95B, 0x9C71, 0xF979, 0x9C73, 0xF978, 0x9C74, 0xF977, 0x9C75, 0xF97A, + 0x9C77, 0xC673, 0x9C78, 0xC674, 0x9C79, 0xF9CA, 0x9C7A, 0xF9CE, 0x9CE5, 0xB3BE, 0x9CE6, 0xDCAF, 0x9CE7, 0xE0ED, 0x9CE9, 0xB9A7, + 0x9CEA, 0xE0EB, 0x9CED, 0xE0EC, 0x9CF1, 0xE4E2, 0x9CF2, 0xE4E3, 0x9CF3, 0xBBF1, 0x9CF4, 0xBBEF, 0x9CF5, 0xE4E4, 0x9CF6, 0xBBF0, + 0x9CF7, 0xE8E8, 0x9CF9, 0xE8EB, 0x9CFA, 0xE8E5, 0x9CFB, 0xE8EC, 0x9CFC, 0xE8E4, 0x9CFD, 0xE8E6, 0x9CFF, 0xE8E7, 0x9D00, 0xE8EA, + 0x9D03, 0xBEA1, 0x9D04, 0xE8EF, 0x9D05, 0xE8EE, 0x9D06, 0xBE7D, 0x9D07, 0xE8E9, 0x9D08, 0xE8ED, 0x9D09, 0xBE7E, 0x9D10, 0xECAC, + 0x9D12, 0xC06F, 0x9D14, 0xECA7, 0x9D15, 0xC06B, 0x9D17, 0xECA4, 0x9D18, 0xECAA, 0x9D19, 0xECAD, 0x9D1B, 0xC070, 0x9D1D, 0xECA9, + 0x9D1E, 0xECA6, 0x9D1F, 0xECAE, 0x9D20, 0xECA5, 0x9D22, 0xECAB, 0x9D23, 0xC06C, 0x9D25, 0xECA3, 0x9D26, 0xC06D, 0x9D28, 0xC06E, + 0x9D29, 0xECA8, 0x9D2D, 0xEFA9, 0x9D2E, 0xEF7A, 0x9D2F, 0xEF7B, 0x9D30, 0xEF7E, 0x9D31, 0xEF7C, 0x9D33, 0xEF76, 0x9D36, 0xEF79, + 0x9D37, 0xEFA5, 0x9D38, 0xEF7D, 0x9D3B, 0xC245, 0x9D3D, 0xEFA7, 0x9D3E, 0xEFA4, 0x9D3F, 0xC246, 0x9D40, 0xEFA6, 0x9D41, 0xEF77, + 0x9D42, 0xEFA2, 0x9D43, 0xEFA3, 0x9D45, 0xEFA1, 0x9D4A, 0xF1D2, 0x9D4B, 0xF1D4, 0x9D4C, 0xF1D7, 0x9D4F, 0xF1D1, 0x9D51, 0xC359, + 0x9D52, 0xF1D9, 0x9D53, 0xF1D0, 0x9D54, 0xF1DA, 0x9D56, 0xF1D6, 0x9D57, 0xF1D8, 0x9D58, 0xF1DC, 0x9D59, 0xF1D5, 0x9D5A, 0xF1DD, + 0x9D5B, 0xF1D3, 0x9D5C, 0xF1CF, 0x9D5D, 0xC35A, 0x9D5F, 0xF1DB, 0x9D60, 0xC35B, 0x9D61, 0xC44D, 0x9D67, 0xEF78, 0x9D68, 0xF3F1, + 0x9D69, 0xF3E8, 0x9D6A, 0xC44F, 0x9D6B, 0xF3E4, 0x9D6C, 0xC450, 0x9D6F, 0xF3ED, 0x9D70, 0xF3E7, 0x9D71, 0xF3DD, 0x9D72, 0xC44E, + 0x9D73, 0xF3EA, 0x9D74, 0xF3E5, 0x9D75, 0xF3E6, 0x9D77, 0xF3D8, 0x9D78, 0xF3DF, 0x9D79, 0xF3EE, 0x9D7B, 0xF3EB, 0x9D7D, 0xF3E3, + 0x9D7F, 0xF3EF, 0x9D80, 0xF3DE, 0x9D81, 0xF3D9, 0x9D82, 0xF3EC, 0x9D84, 0xF3DB, 0x9D85, 0xF3E9, 0x9D86, 0xF3E0, 0x9D87, 0xF3F0, + 0x9D88, 0xF3DC, 0x9D89, 0xC44C, 0x9D8A, 0xF3DA, 0x9D8B, 0xF3E1, 0x9D8C, 0xF3E2, 0x9D90, 0xF57D, 0x9D92, 0xF57B, 0x9D94, 0xF5A2, + 0x9D96, 0xF5AE, 0x9D97, 0xF5A5, 0x9D98, 0xF57C, 0x9D99, 0xF578, 0x9D9A, 0xF5A7, 0x9D9B, 0xF57E, 0x9D9C, 0xF5A3, 0x9D9D, 0xF57A, + 0x9D9E, 0xF5AA, 0x9D9F, 0xF577, 0x9DA0, 0xF5A1, 0x9DA1, 0xF5A6, 0x9DA2, 0xF5A8, 0x9DA3, 0xF5AB, 0x9DA4, 0xF579, 0x9DA6, 0xF5AF, + 0x9DA7, 0xF5B0, 0x9DA8, 0xF5A9, 0x9DA9, 0xF5AD, 0x9DAA, 0xF5A4, 0x9DAC, 0xF6C1, 0x9DAD, 0xF6C4, 0x9DAF, 0xC561, 0x9DB1, 0xF6C3, + 0x9DB2, 0xF6C8, 0x9DB3, 0xF6C6, 0x9DB4, 0xC562, 0x9DB5, 0xF6BD, 0x9DB6, 0xF6B3, 0x9DB7, 0xF6B2, 0x9DB8, 0xC564, 0x9DB9, 0xF6BF, + 0x9DBA, 0xF6C0, 0x9DBB, 0xF6BC, 0x9DBC, 0xF6B4, 0x9DBE, 0xF6B9, 0x9DBF, 0xF5AC, 0x9DC1, 0xF6B5, 0x9DC2, 0xC563, 0x9DC3, 0xF6BB, + 0x9DC5, 0xF6BA, 0x9DC7, 0xF6B6, 0x9DC8, 0xF6C2, 0x9DCA, 0xF6B7, 0x9DCB, 0xF7BB, 0x9DCC, 0xF6C5, 0x9DCD, 0xF6C7, 0x9DCE, 0xF6BE, + 0x9DCF, 0xF6B8, 0x9DD0, 0xF7BC, 0x9DD1, 0xF7BE, 0x9DD2, 0xF7B8, 0x9DD3, 0xC5C2, 0x9DD5, 0xF7C5, 0x9DD6, 0xF7C3, 0x9DD7, 0xC5C3, + 0x9DD8, 0xF7C2, 0x9DD9, 0xF7C1, 0x9DDA, 0xF7BA, 0x9DDB, 0xF7B7, 0x9DDC, 0xF7BD, 0x9DDD, 0xF7C6, 0x9DDE, 0xF7B9, 0x9DDF, 0xF7BF, + 0x9DE1, 0xF869, 0x9DE2, 0xF86E, 0x9DE3, 0xF864, 0x9DE4, 0xF867, 0x9DE5, 0xC5EE, 0x9DE6, 0xF86B, 0x9DE8, 0xF872, 0x9DE9, 0xF7C0, + 0x9DEB, 0xF865, 0x9DEC, 0xF86F, 0x9DED, 0xF873, 0x9DEE, 0xF86A, 0x9DEF, 0xF863, 0x9DF0, 0xF86D, 0x9DF2, 0xF86C, 0x9DF3, 0xF871, + 0x9DF4, 0xF870, 0x9DF5, 0xF7C4, 0x9DF6, 0xF868, 0x9DF7, 0xF862, 0x9DF8, 0xF866, 0x9DF9, 0xC64E, 0x9DFA, 0xC64F, 0x9DFB, 0xF861, + 0x9DFD, 0xF8E6, 0x9DFE, 0xF8DD, 0x9DFF, 0xF8E5, 0x9E00, 0xF8E2, 0x9E01, 0xF8E3, 0x9E02, 0xF8DC, 0x9E03, 0xF8DF, 0x9E04, 0xF8E7, + 0x9E05, 0xF8E1, 0x9E06, 0xF8E0, 0x9E07, 0xF8DE, 0x9E09, 0xF8E4, 0x9E0B, 0xF95D, 0x9E0D, 0xF95E, 0x9E0F, 0xF960, 0x9E10, 0xF95F, + 0x9E11, 0xF962, 0x9E12, 0xF961, 0x9E13, 0xF97C, 0x9E14, 0xF97B, 0x9E15, 0xF9B7, 0x9E17, 0xF9B8, 0x9E19, 0xF9C5, 0x9E1A, 0xC678, + 0x9E1B, 0xC67C, 0x9E1D, 0xF9CF, 0x9E1E, 0xC67D, 0x9E75, 0xB3BF, 0x9E79, 0xC4D0, 0x9E7A, 0xF6C9, 0x9E7C, 0xC650, 0x9E7D, 0xC651, + 0x9E7F, 0xB3C0, 0x9E80, 0xE0EE, 0x9E82, 0xB9A8, 0x9E83, 0xE8F0, 0x9E86, 0xECB0, 0x9E87, 0xECB1, 0x9E88, 0xECAF, 0x9E89, 0xEFAB, + 0x9E8A, 0xEFAA, 0x9E8B, 0xC247, 0x9E8C, 0xF1DF, 0x9E8D, 0xEFAC, 0x9E8E, 0xF1DE, 0x9E91, 0xF3F3, 0x9E92, 0xC451, 0x9E93, 0xC453, + 0x9E94, 0xF3F2, 0x9E97, 0xC452, 0x9E99, 0xF5B1, 0x9E9A, 0xF5B3, 0x9E9B, 0xF5B2, 0x9E9C, 0xF6CA, 0x9E9D, 0xC565, 0x9E9F, 0xC5EF, + 0x9EA0, 0xF8E8, 0x9EA1, 0xF963, 0x9EA4, 0xF9D2, 0x9EA5, 0xB3C1, 0x9EA7, 0xE4E5, 0x9EA9, 0xBEA2, 0x9EAD, 0xECB3, 0x9EAE, 0xECB2, + 0x9EB0, 0xEFAD, 0x9EB4, 0xC454, 0x9EB5, 0xC4D1, 0x9EB6, 0xF7C7, 0x9EB7, 0xF9CB, 0x9EBB, 0xB3C2, 0x9EBC, 0xBBF2, 0x9EBE, 0xBEA3, + 0x9EC0, 0xF3F4, 0x9EC2, 0xF874, 0x9EC3, 0xB6C0, 0x9EC8, 0xEFAE, 0x9ECC, 0xC664, 0x9ECD, 0xB6C1, 0x9ECE, 0xBEA4, 0x9ECF, 0xC248, + 0x9ED0, 0xF875, 0x9ED1, 0xB6C2, 0x9ED3, 0xE8F1, 0x9ED4, 0xC072, 0x9ED5, 0xECB4, 0x9ED6, 0xECB5, 0x9ED8, 0xC071, 0x9EDA, 0xEFAF, + 0x9EDB, 0xC24C, 0x9EDC, 0xC24A, 0x9EDD, 0xC24B, 0x9EDE, 0xC249, 0x9EDF, 0xF1E0, 0x9EE0, 0xC35C, 0x9EE4, 0xF5B5, 0x9EE5, 0xF5B4, + 0x9EE6, 0xF5B7, 0x9EE7, 0xF5B6, 0x9EE8, 0xC4D2, 0x9EEB, 0xF6CB, 0x9EED, 0xF6CD, 0x9EEE, 0xF6CC, 0x9EEF, 0xC566, 0x9EF0, 0xF7C8, + 0x9EF2, 0xF876, 0x9EF3, 0xF877, 0x9EF4, 0xC5F0, 0x9EF5, 0xF964, 0x9EF6, 0xF97D, 0x9EF7, 0xC675, 0x9EF9, 0xDCB0, 0x9EFA, 0xECB6, + 0x9EFB, 0xEFB0, 0x9EFC, 0xF3F5, 0x9EFD, 0xE0EF, 0x9EFF, 0xEFB1, 0x9F00, 0xF1E2, 0x9F01, 0xF1E1, 0x9F06, 0xF878, 0x9F07, 0xC652, + 0x9F09, 0xF965, 0x9F0A, 0xF97E, 0x9F0E, 0xB9A9, 0x9F0F, 0xE8F2, 0x9F10, 0xE8F3, 0x9F12, 0xECB7, 0x9F13, 0xB9AA, 0x9F15, 0xC35D, + 0x9F16, 0xF1E3, 0x9F18, 0xF6CF, 0x9F19, 0xC567, 0x9F1A, 0xF6D0, 0x9F1B, 0xF6CE, 0x9F1C, 0xF879, 0x9F1E, 0xF8E9, 0x9F20, 0xB9AB, + 0x9F22, 0xEFB4, 0x9F23, 0xEFB3, 0x9F24, 0xEFB2, 0x9F25, 0xF1E4, 0x9F28, 0xF1E8, 0x9F29, 0xF1E7, 0x9F2A, 0xF1E6, 0x9F2B, 0xF1E5, + 0x9F2C, 0xC35E, 0x9F2D, 0xF3F6, 0x9F2E, 0xF5B9, 0x9F2F, 0xC4D3, 0x9F30, 0xF5B8, 0x9F31, 0xF6D1, 0x9F32, 0xF7CB, 0x9F33, 0xF7CA, + 0x9F34, 0xC5C4, 0x9F35, 0xF7C9, 0x9F36, 0xF87C, 0x9F37, 0xF87B, 0x9F38, 0xF87A, 0x9F3B, 0xBBF3, 0x9F3D, 0xECB8, 0x9F3E, 0xC24D, + 0x9F40, 0xF3F7, 0x9F41, 0xF3F8, 0x9F42, 0xF7CC, 0x9F43, 0xF87D, 0x9F46, 0xF8EA, 0x9F47, 0xF966, 0x9F48, 0xF9B9, 0x9F49, 0xF9D4, + 0x9F4A, 0xBBF4, 0x9F4B, 0xC24E, 0x9F4C, 0xF1E9, 0x9F4D, 0xF3F9, 0x9F4E, 0xF6D2, 0x9F4F, 0xF87E, 0x9F52, 0xBEA6, 0x9F54, 0xEFB5, + 0x9F55, 0xF1EA, 0x9F56, 0xF3FA, 0x9F57, 0xF3FB, 0x9F58, 0xF3FC, 0x9F59, 0xF5BE, 0x9F5B, 0xF5BA, 0x9F5C, 0xC568, 0x9F5D, 0xF5BD, + 0x9F5E, 0xF5BC, 0x9F5F, 0xC4D4, 0x9F60, 0xF5BB, 0x9F61, 0xC4D6, 0x9F63, 0xC4D5, 0x9F64, 0xF6D4, 0x9F65, 0xF6D3, 0x9F66, 0xC569, + 0x9F67, 0xC56A, 0x9F6A, 0xC5C6, 0x9F6B, 0xF7CD, 0x9F6C, 0xC5C5, 0x9F6E, 0xF8A3, 0x9F6F, 0xF8A4, 0x9F70, 0xF8A2, 0x9F71, 0xF8A1, + 0x9F72, 0xC654, 0x9F74, 0xF8EB, 0x9F75, 0xF8EC, 0x9F76, 0xF8ED, 0x9F77, 0xC653, 0x9F78, 0xF967, 0x9F79, 0xF96A, 0x9F7A, 0xF969, + 0x9F7B, 0xF968, 0x9F7E, 0xF9D3, 0x9F8D, 0xC073, 0x9F90, 0xC365, 0x9F91, 0xF5BF, 0x9F92, 0xF6D5, 0x9F94, 0xC5C7, 0x9F95, 0xF7CE, + 0x9F98, 0xF9D5, 0x9F9C, 0xC074, 0x9FA0, 0xEFB6, 0x9FA2, 0xF7CF, 0x9FA4, 0xF9A1, 0xFA0C, 0xC94A, 0xFA0D, 0xDDFC, 0xFE30, 0xA14A, + 0xFE31, 0xA157, 0xFE33, 0xA159, 0xFE34, 0xA15B, 0xFE35, 0xA15F, 0xFE36, 0xA160, 0xFE37, 0xA163, 0xFE38, 0xA164, 0xFE39, 0xA167, + 0xFE3A, 0xA168, 0xFE3B, 0xA16B, 0xFE3C, 0xA16C, 0xFE3D, 0xA16F, 0xFE3E, 0xA170, 0xFE3F, 0xA173, 0xFE40, 0xA174, 0xFE41, 0xA177, + 0xFE42, 0xA178, 0xFE43, 0xA17B, 0xFE44, 0xA17C, 0xFE49, 0xA1C6, 0xFE4A, 0xA1C7, 0xFE4B, 0xA1CA, 0xFE4C, 0xA1CB, 0xFE4D, 0xA1C8, + 0xFE4E, 0xA1C9, 0xFE4F, 0xA15C, 0xFE50, 0xA14D, 0xFE51, 0xA14E, 0xFE52, 0xA14F, 0xFE54, 0xA151, 0xFE55, 0xA152, 0xFE56, 0xA153, + 0xFE57, 0xA154, 0xFE59, 0xA17D, 0xFE5A, 0xA17E, 0xFE5B, 0xA1A1, 0xFE5C, 0xA1A2, 0xFE5D, 0xA1A3, 0xFE5E, 0xA1A4, 0xFE5F, 0xA1CC, + 0xFE60, 0xA1CD, 0xFE61, 0xA1CE, 0xFE62, 0xA1DE, 0xFE63, 0xA1DF, 0xFE64, 0xA1E0, 0xFE65, 0xA1E1, 0xFE66, 0xA1E2, 0xFE68, 0xA242, + 0xFE69, 0xA24C, 0xFE6A, 0xA24D, 0xFE6B, 0xA24E, 0xFF01, 0xA149, 0xFF03, 0xA1AD, 0xFF04, 0xA243, 0xFF05, 0xA248, 0xFF06, 0xA1AE, + 0xFF08, 0xA15D, 0xFF09, 0xA15E, 0xFF0A, 0xA1AF, 0xFF0B, 0xA1CF, 0xFF0C, 0xA141, 0xFF0D, 0xA1D0, 0xFF0E, 0xA144, 0xFF0F, 0xA1FE, + 0xFF10, 0xA2AF, 0xFF11, 0xA2B0, 0xFF12, 0xA2B1, 0xFF13, 0xA2B2, 0xFF14, 0xA2B3, 0xFF15, 0xA2B4, 0xFF16, 0xA2B5, 0xFF17, 0xA2B6, + 0xFF18, 0xA2B7, 0xFF19, 0xA2B8, 0xFF1A, 0xA147, 0xFF1B, 0xA146, 0xFF1C, 0xA1D5, 0xFF1D, 0xA1D7, 0xFF1E, 0xA1D6, 0xFF1F, 0xA148, + 0xFF20, 0xA249, 0xFF21, 0xA2CF, 0xFF22, 0xA2D0, 0xFF23, 0xA2D1, 0xFF24, 0xA2D2, 0xFF25, 0xA2D3, 0xFF26, 0xA2D4, 0xFF27, 0xA2D5, + 0xFF28, 0xA2D6, 0xFF29, 0xA2D7, 0xFF2A, 0xA2D8, 0xFF2B, 0xA2D9, 0xFF2C, 0xA2DA, 0xFF2D, 0xA2DB, 0xFF2E, 0xA2DC, 0xFF2F, 0xA2DD, + 0xFF30, 0xA2DE, 0xFF31, 0xA2DF, 0xFF32, 0xA2E0, 0xFF33, 0xA2E1, 0xFF34, 0xA2E2, 0xFF35, 0xA2E3, 0xFF36, 0xA2E4, 0xFF37, 0xA2E5, + 0xFF38, 0xA2E6, 0xFF39, 0xA2E7, 0xFF3A, 0xA2E8, 0xFF3C, 0xA240, 0xFF3F, 0xA1C4, 0xFF41, 0xA2E9, 0xFF42, 0xA2EA, 0xFF43, 0xA2EB, + 0xFF44, 0xA2EC, 0xFF45, 0xA2ED, 0xFF46, 0xA2EE, 0xFF47, 0xA2EF, 0xFF48, 0xA2F0, 0xFF49, 0xA2F1, 0xFF4A, 0xA2F2, 0xFF4B, 0xA2F3, + 0xFF4C, 0xA2F4, 0xFF4D, 0xA2F5, 0xFF4E, 0xA2F6, 0xFF4F, 0xA2F7, 0xFF50, 0xA2F8, 0xFF51, 0xA2F9, 0xFF52, 0xA2FA, 0xFF53, 0xA2FB, + 0xFF54, 0xA2FC, 0xFF55, 0xA2FD, 0xFF56, 0xA2FE, 0xFF57, 0xA340, 0xFF58, 0xA341, 0xFF59, 0xA342, 0xFF5A, 0xA343, 0xFF5B, 0xA161, + 0xFF5C, 0xA155, 0xFF5D, 0xA162, 0xFF5E, 0xA1E3, 0xFFE0, 0xA246, 0xFFE1, 0xA247, 0xFFE3, 0xA1C3, 0xFFE5, 0xA244, 0, 0 +}; + +static +const WCHAR oem2uni950[] = { /* Big5 --> Unicode pairs */ + 0xA140, 0x3000, 0xA141, 0xFF0C, 0xA142, 0x3001, 0xA143, 0x3002, 0xA144, 0xFF0E, 0xA145, 0x2027, 0xA146, 0xFF1B, 0xA147, 0xFF1A, + 0xA148, 0xFF1F, 0xA149, 0xFF01, 0xA14A, 0xFE30, 0xA14B, 0x2026, 0xA14C, 0x2025, 0xA14D, 0xFE50, 0xA14E, 0xFE51, 0xA14F, 0xFE52, + 0xA150, 0x00B7, 0xA151, 0xFE54, 0xA152, 0xFE55, 0xA153, 0xFE56, 0xA154, 0xFE57, 0xA155, 0xFF5C, 0xA156, 0x2013, 0xA157, 0xFE31, + 0xA158, 0x2014, 0xA159, 0xFE33, 0xA15A, 0x2574, 0xA15B, 0xFE34, 0xA15C, 0xFE4F, 0xA15D, 0xFF08, 0xA15E, 0xFF09, 0xA15F, 0xFE35, + 0xA160, 0xFE36, 0xA161, 0xFF5B, 0xA162, 0xFF5D, 0xA163, 0xFE37, 0xA164, 0xFE38, 0xA165, 0x3014, 0xA166, 0x3015, 0xA167, 0xFE39, + 0xA168, 0xFE3A, 0xA169, 0x3010, 0xA16A, 0x3011, 0xA16B, 0xFE3B, 0xA16C, 0xFE3C, 0xA16D, 0x300A, 0xA16E, 0x300B, 0xA16F, 0xFE3D, + 0xA170, 0xFE3E, 0xA171, 0x3008, 0xA172, 0x3009, 0xA173, 0xFE3F, 0xA174, 0xFE40, 0xA175, 0x300C, 0xA176, 0x300D, 0xA177, 0xFE41, + 0xA178, 0xFE42, 0xA179, 0x300E, 0xA17A, 0x300F, 0xA17B, 0xFE43, 0xA17C, 0xFE44, 0xA17D, 0xFE59, 0xA17E, 0xFE5A, 0xA1A1, 0xFE5B, + 0xA1A2, 0xFE5C, 0xA1A3, 0xFE5D, 0xA1A4, 0xFE5E, 0xA1A5, 0x2018, 0xA1A6, 0x2019, 0xA1A7, 0x201C, 0xA1A8, 0x201D, 0xA1A9, 0x301D, + 0xA1AA, 0x301E, 0xA1AB, 0x2035, 0xA1AC, 0x2032, 0xA1AD, 0xFF03, 0xA1AE, 0xFF06, 0xA1AF, 0xFF0A, 0xA1B0, 0x203B, 0xA1B1, 0x00A7, + 0xA1B2, 0x3003, 0xA1B3, 0x25CB, 0xA1B4, 0x25CF, 0xA1B5, 0x25B3, 0xA1B6, 0x25B2, 0xA1B7, 0x25CE, 0xA1B8, 0x2606, 0xA1B9, 0x2605, + 0xA1BA, 0x25C7, 0xA1BB, 0x25C6, 0xA1BC, 0x25A1, 0xA1BD, 0x25A0, 0xA1BE, 0x25BD, 0xA1BF, 0x25BC, 0xA1C0, 0x32A3, 0xA1C1, 0x2105, + 0xA1C2, 0x00AF, 0xA1C3, 0xFFE3, 0xA1C4, 0xFF3F, 0xA1C5, 0x02CD, 0xA1C6, 0xFE49, 0xA1C7, 0xFE4A, 0xA1C8, 0xFE4D, 0xA1C9, 0xFE4E, + 0xA1CA, 0xFE4B, 0xA1CB, 0xFE4C, 0xA1CC, 0xFE5F, 0xA1CD, 0xFE60, 0xA1CE, 0xFE61, 0xA1CF, 0xFF0B, 0xA1D0, 0xFF0D, 0xA1D1, 0x00D7, + 0xA1D2, 0x00F7, 0xA1D3, 0x00B1, 0xA1D4, 0x221A, 0xA1D5, 0xFF1C, 0xA1D6, 0xFF1E, 0xA1D7, 0xFF1D, 0xA1D8, 0x2266, 0xA1D9, 0x2267, + 0xA1DA, 0x2260, 0xA1DB, 0x221E, 0xA1DC, 0x2252, 0xA1DD, 0x2261, 0xA1DE, 0xFE62, 0xA1DF, 0xFE63, 0xA1E0, 0xFE64, 0xA1E1, 0xFE65, + 0xA1E2, 0xFE66, 0xA1E3, 0xFF5E, 0xA1E4, 0x2229, 0xA1E5, 0x222A, 0xA1E6, 0x22A5, 0xA1E7, 0x2220, 0xA1E8, 0x221F, 0xA1E9, 0x22BF, + 0xA1EA, 0x33D2, 0xA1EB, 0x33D1, 0xA1EC, 0x222B, 0xA1ED, 0x222E, 0xA1EE, 0x2235, 0xA1EF, 0x2234, 0xA1F0, 0x2640, 0xA1F1, 0x2642, + 0xA1F2, 0x2295, 0xA1F3, 0x2299, 0xA1F4, 0x2191, 0xA1F5, 0x2193, 0xA1F6, 0x2190, 0xA1F7, 0x2192, 0xA1F8, 0x2196, 0xA1F9, 0x2197, + 0xA1FA, 0x2199, 0xA1FB, 0x2198, 0xA1FC, 0x2225, 0xA1FD, 0x2223, 0xA1FE, 0xFF0F, 0xA240, 0xFF3C, 0xA241, 0x2215, 0xA242, 0xFE68, + 0xA243, 0xFF04, 0xA244, 0xFFE5, 0xA245, 0x3012, 0xA246, 0xFFE0, 0xA247, 0xFFE1, 0xA248, 0xFF05, 0xA249, 0xFF20, 0xA24A, 0x2103, + 0xA24B, 0x2109, 0xA24C, 0xFE69, 0xA24D, 0xFE6A, 0xA24E, 0xFE6B, 0xA24F, 0x33D5, 0xA250, 0x339C, 0xA251, 0x339D, 0xA252, 0x339E, + 0xA253, 0x33CE, 0xA254, 0x33A1, 0xA255, 0x338E, 0xA256, 0x338F, 0xA257, 0x33C4, 0xA258, 0x00B0, 0xA259, 0x5159, 0xA25A, 0x515B, + 0xA25B, 0x515E, 0xA25C, 0x515D, 0xA25D, 0x5161, 0xA25E, 0x5163, 0xA25F, 0x55E7, 0xA260, 0x74E9, 0xA261, 0x7CCE, 0xA262, 0x2581, + 0xA263, 0x2582, 0xA264, 0x2583, 0xA265, 0x2584, 0xA266, 0x2585, 0xA267, 0x2586, 0xA268, 0x2587, 0xA269, 0x2588, 0xA26A, 0x258F, + 0xA26B, 0x258E, 0xA26C, 0x258D, 0xA26D, 0x258C, 0xA26E, 0x258B, 0xA26F, 0x258A, 0xA270, 0x2589, 0xA271, 0x253C, 0xA272, 0x2534, + 0xA273, 0x252C, 0xA274, 0x2524, 0xA275, 0x251C, 0xA276, 0x2594, 0xA277, 0x2500, 0xA278, 0x2502, 0xA279, 0x2595, 0xA27A, 0x250C, + 0xA27B, 0x2510, 0xA27C, 0x2514, 0xA27D, 0x2518, 0xA27E, 0x256D, 0xA2A1, 0x256E, 0xA2A2, 0x2570, 0xA2A3, 0x256F, 0xA2A4, 0x2550, + 0xA2A5, 0x255E, 0xA2A6, 0x256A, 0xA2A7, 0x2561, 0xA2A8, 0x25E2, 0xA2A9, 0x25E3, 0xA2AA, 0x25E5, 0xA2AB, 0x25E4, 0xA2AC, 0x2571, + 0xA2AD, 0x2572, 0xA2AE, 0x2573, 0xA2AF, 0xFF10, 0xA2B0, 0xFF11, 0xA2B1, 0xFF12, 0xA2B2, 0xFF13, 0xA2B3, 0xFF14, 0xA2B4, 0xFF15, + 0xA2B5, 0xFF16, 0xA2B6, 0xFF17, 0xA2B7, 0xFF18, 0xA2B8, 0xFF19, 0xA2B9, 0x2160, 0xA2BA, 0x2161, 0xA2BB, 0x2162, 0xA2BC, 0x2163, + 0xA2BD, 0x2164, 0xA2BE, 0x2165, 0xA2BF, 0x2166, 0xA2C0, 0x2167, 0xA2C1, 0x2168, 0xA2C2, 0x2169, 0xA2C3, 0x3021, 0xA2C4, 0x3022, + 0xA2C5, 0x3023, 0xA2C6, 0x3024, 0xA2C7, 0x3025, 0xA2C8, 0x3026, 0xA2C9, 0x3027, 0xA2CA, 0x3028, 0xA2CB, 0x3029, 0xA2CC, 0x5341, + 0xA2CD, 0x5344, 0xA2CE, 0x5345, 0xA2CF, 0xFF21, 0xA2D0, 0xFF22, 0xA2D1, 0xFF23, 0xA2D2, 0xFF24, 0xA2D3, 0xFF25, 0xA2D4, 0xFF26, + 0xA2D5, 0xFF27, 0xA2D6, 0xFF28, 0xA2D7, 0xFF29, 0xA2D8, 0xFF2A, 0xA2D9, 0xFF2B, 0xA2DA, 0xFF2C, 0xA2DB, 0xFF2D, 0xA2DC, 0xFF2E, + 0xA2DD, 0xFF2F, 0xA2DE, 0xFF30, 0xA2DF, 0xFF31, 0xA2E0, 0xFF32, 0xA2E1, 0xFF33, 0xA2E2, 0xFF34, 0xA2E3, 0xFF35, 0xA2E4, 0xFF36, + 0xA2E5, 0xFF37, 0xA2E6, 0xFF38, 0xA2E7, 0xFF39, 0xA2E8, 0xFF3A, 0xA2E9, 0xFF41, 0xA2EA, 0xFF42, 0xA2EB, 0xFF43, 0xA2EC, 0xFF44, + 0xA2ED, 0xFF45, 0xA2EE, 0xFF46, 0xA2EF, 0xFF47, 0xA2F0, 0xFF48, 0xA2F1, 0xFF49, 0xA2F2, 0xFF4A, 0xA2F3, 0xFF4B, 0xA2F4, 0xFF4C, + 0xA2F5, 0xFF4D, 0xA2F6, 0xFF4E, 0xA2F7, 0xFF4F, 0xA2F8, 0xFF50, 0xA2F9, 0xFF51, 0xA2FA, 0xFF52, 0xA2FB, 0xFF53, 0xA2FC, 0xFF54, + 0xA2FD, 0xFF55, 0xA2FE, 0xFF56, 0xA340, 0xFF57, 0xA341, 0xFF58, 0xA342, 0xFF59, 0xA343, 0xFF5A, 0xA344, 0x0391, 0xA345, 0x0392, + 0xA346, 0x0393, 0xA347, 0x0394, 0xA348, 0x0395, 0xA349, 0x0396, 0xA34A, 0x0397, 0xA34B, 0x0398, 0xA34C, 0x0399, 0xA34D, 0x039A, + 0xA34E, 0x039B, 0xA34F, 0x039C, 0xA350, 0x039D, 0xA351, 0x039E, 0xA352, 0x039F, 0xA353, 0x03A0, 0xA354, 0x03A1, 0xA355, 0x03A3, + 0xA356, 0x03A4, 0xA357, 0x03A5, 0xA358, 0x03A6, 0xA359, 0x03A7, 0xA35A, 0x03A8, 0xA35B, 0x03A9, 0xA35C, 0x03B1, 0xA35D, 0x03B2, + 0xA35E, 0x03B3, 0xA35F, 0x03B4, 0xA360, 0x03B5, 0xA361, 0x03B6, 0xA362, 0x03B7, 0xA363, 0x03B8, 0xA364, 0x03B9, 0xA365, 0x03BA, + 0xA366, 0x03BB, 0xA367, 0x03BC, 0xA368, 0x03BD, 0xA369, 0x03BE, 0xA36A, 0x03BF, 0xA36B, 0x03C0, 0xA36C, 0x03C1, 0xA36D, 0x03C3, + 0xA36E, 0x03C4, 0xA36F, 0x03C5, 0xA370, 0x03C6, 0xA371, 0x03C7, 0xA372, 0x03C8, 0xA373, 0x03C9, 0xA374, 0x3105, 0xA375, 0x3106, + 0xA376, 0x3107, 0xA377, 0x3108, 0xA378, 0x3109, 0xA379, 0x310A, 0xA37A, 0x310B, 0xA37B, 0x310C, 0xA37C, 0x310D, 0xA37D, 0x310E, + 0xA37E, 0x310F, 0xA3A1, 0x3110, 0xA3A2, 0x3111, 0xA3A3, 0x3112, 0xA3A4, 0x3113, 0xA3A5, 0x3114, 0xA3A6, 0x3115, 0xA3A7, 0x3116, + 0xA3A8, 0x3117, 0xA3A9, 0x3118, 0xA3AA, 0x3119, 0xA3AB, 0x311A, 0xA3AC, 0x311B, 0xA3AD, 0x311C, 0xA3AE, 0x311D, 0xA3AF, 0x311E, + 0xA3B0, 0x311F, 0xA3B1, 0x3120, 0xA3B2, 0x3121, 0xA3B3, 0x3122, 0xA3B4, 0x3123, 0xA3B5, 0x3124, 0xA3B6, 0x3125, 0xA3B7, 0x3126, + 0xA3B8, 0x3127, 0xA3B9, 0x3128, 0xA3BA, 0x3129, 0xA3BB, 0x02D9, 0xA3BC, 0x02C9, 0xA3BD, 0x02CA, 0xA3BE, 0x02C7, 0xA3BF, 0x02CB, + 0xA3E1, 0x20AC, 0xA440, 0x4E00, 0xA441, 0x4E59, 0xA442, 0x4E01, 0xA443, 0x4E03, 0xA444, 0x4E43, 0xA445, 0x4E5D, 0xA446, 0x4E86, + 0xA447, 0x4E8C, 0xA448, 0x4EBA, 0xA449, 0x513F, 0xA44A, 0x5165, 0xA44B, 0x516B, 0xA44C, 0x51E0, 0xA44D, 0x5200, 0xA44E, 0x5201, + 0xA44F, 0x529B, 0xA450, 0x5315, 0xA451, 0x5341, 0xA452, 0x535C, 0xA453, 0x53C8, 0xA454, 0x4E09, 0xA455, 0x4E0B, 0xA456, 0x4E08, + 0xA457, 0x4E0A, 0xA458, 0x4E2B, 0xA459, 0x4E38, 0xA45A, 0x51E1, 0xA45B, 0x4E45, 0xA45C, 0x4E48, 0xA45D, 0x4E5F, 0xA45E, 0x4E5E, + 0xA45F, 0x4E8E, 0xA460, 0x4EA1, 0xA461, 0x5140, 0xA462, 0x5203, 0xA463, 0x52FA, 0xA464, 0x5343, 0xA465, 0x53C9, 0xA466, 0x53E3, + 0xA467, 0x571F, 0xA468, 0x58EB, 0xA469, 0x5915, 0xA46A, 0x5927, 0xA46B, 0x5973, 0xA46C, 0x5B50, 0xA46D, 0x5B51, 0xA46E, 0x5B53, + 0xA46F, 0x5BF8, 0xA470, 0x5C0F, 0xA471, 0x5C22, 0xA472, 0x5C38, 0xA473, 0x5C71, 0xA474, 0x5DDD, 0xA475, 0x5DE5, 0xA476, 0x5DF1, + 0xA477, 0x5DF2, 0xA478, 0x5DF3, 0xA479, 0x5DFE, 0xA47A, 0x5E72, 0xA47B, 0x5EFE, 0xA47C, 0x5F0B, 0xA47D, 0x5F13, 0xA47E, 0x624D, + 0xA4A1, 0x4E11, 0xA4A2, 0x4E10, 0xA4A3, 0x4E0D, 0xA4A4, 0x4E2D, 0xA4A5, 0x4E30, 0xA4A6, 0x4E39, 0xA4A7, 0x4E4B, 0xA4A8, 0x5C39, + 0xA4A9, 0x4E88, 0xA4AA, 0x4E91, 0xA4AB, 0x4E95, 0xA4AC, 0x4E92, 0xA4AD, 0x4E94, 0xA4AE, 0x4EA2, 0xA4AF, 0x4EC1, 0xA4B0, 0x4EC0, + 0xA4B1, 0x4EC3, 0xA4B2, 0x4EC6, 0xA4B3, 0x4EC7, 0xA4B4, 0x4ECD, 0xA4B5, 0x4ECA, 0xA4B6, 0x4ECB, 0xA4B7, 0x4EC4, 0xA4B8, 0x5143, + 0xA4B9, 0x5141, 0xA4BA, 0x5167, 0xA4BB, 0x516D, 0xA4BC, 0x516E, 0xA4BD, 0x516C, 0xA4BE, 0x5197, 0xA4BF, 0x51F6, 0xA4C0, 0x5206, + 0xA4C1, 0x5207, 0xA4C2, 0x5208, 0xA4C3, 0x52FB, 0xA4C4, 0x52FE, 0xA4C5, 0x52FF, 0xA4C6, 0x5316, 0xA4C7, 0x5339, 0xA4C8, 0x5348, + 0xA4C9, 0x5347, 0xA4CA, 0x5345, 0xA4CB, 0x535E, 0xA4CC, 0x5384, 0xA4CD, 0x53CB, 0xA4CE, 0x53CA, 0xA4CF, 0x53CD, 0xA4D0, 0x58EC, + 0xA4D1, 0x5929, 0xA4D2, 0x592B, 0xA4D3, 0x592A, 0xA4D4, 0x592D, 0xA4D5, 0x5B54, 0xA4D6, 0x5C11, 0xA4D7, 0x5C24, 0xA4D8, 0x5C3A, + 0xA4D9, 0x5C6F, 0xA4DA, 0x5DF4, 0xA4DB, 0x5E7B, 0xA4DC, 0x5EFF, 0xA4DD, 0x5F14, 0xA4DE, 0x5F15, 0xA4DF, 0x5FC3, 0xA4E0, 0x6208, + 0xA4E1, 0x6236, 0xA4E2, 0x624B, 0xA4E3, 0x624E, 0xA4E4, 0x652F, 0xA4E5, 0x6587, 0xA4E6, 0x6597, 0xA4E7, 0x65A4, 0xA4E8, 0x65B9, + 0xA4E9, 0x65E5, 0xA4EA, 0x66F0, 0xA4EB, 0x6708, 0xA4EC, 0x6728, 0xA4ED, 0x6B20, 0xA4EE, 0x6B62, 0xA4EF, 0x6B79, 0xA4F0, 0x6BCB, + 0xA4F1, 0x6BD4, 0xA4F2, 0x6BDB, 0xA4F3, 0x6C0F, 0xA4F4, 0x6C34, 0xA4F5, 0x706B, 0xA4F6, 0x722A, 0xA4F7, 0x7236, 0xA4F8, 0x723B, + 0xA4F9, 0x7247, 0xA4FA, 0x7259, 0xA4FB, 0x725B, 0xA4FC, 0x72AC, 0xA4FD, 0x738B, 0xA4FE, 0x4E19, 0xA540, 0x4E16, 0xA541, 0x4E15, + 0xA542, 0x4E14, 0xA543, 0x4E18, 0xA544, 0x4E3B, 0xA545, 0x4E4D, 0xA546, 0x4E4F, 0xA547, 0x4E4E, 0xA548, 0x4EE5, 0xA549, 0x4ED8, + 0xA54A, 0x4ED4, 0xA54B, 0x4ED5, 0xA54C, 0x4ED6, 0xA54D, 0x4ED7, 0xA54E, 0x4EE3, 0xA54F, 0x4EE4, 0xA550, 0x4ED9, 0xA551, 0x4EDE, + 0xA552, 0x5145, 0xA553, 0x5144, 0xA554, 0x5189, 0xA555, 0x518A, 0xA556, 0x51AC, 0xA557, 0x51F9, 0xA558, 0x51FA, 0xA559, 0x51F8, + 0xA55A, 0x520A, 0xA55B, 0x52A0, 0xA55C, 0x529F, 0xA55D, 0x5305, 0xA55E, 0x5306, 0xA55F, 0x5317, 0xA560, 0x531D, 0xA561, 0x4EDF, + 0xA562, 0x534A, 0xA563, 0x5349, 0xA564, 0x5361, 0xA565, 0x5360, 0xA566, 0x536F, 0xA567, 0x536E, 0xA568, 0x53BB, 0xA569, 0x53EF, + 0xA56A, 0x53E4, 0xA56B, 0x53F3, 0xA56C, 0x53EC, 0xA56D, 0x53EE, 0xA56E, 0x53E9, 0xA56F, 0x53E8, 0xA570, 0x53FC, 0xA571, 0x53F8, + 0xA572, 0x53F5, 0xA573, 0x53EB, 0xA574, 0x53E6, 0xA575, 0x53EA, 0xA576, 0x53F2, 0xA577, 0x53F1, 0xA578, 0x53F0, 0xA579, 0x53E5, + 0xA57A, 0x53ED, 0xA57B, 0x53FB, 0xA57C, 0x56DB, 0xA57D, 0x56DA, 0xA57E, 0x5916, 0xA5A1, 0x592E, 0xA5A2, 0x5931, 0xA5A3, 0x5974, + 0xA5A4, 0x5976, 0xA5A5, 0x5B55, 0xA5A6, 0x5B83, 0xA5A7, 0x5C3C, 0xA5A8, 0x5DE8, 0xA5A9, 0x5DE7, 0xA5AA, 0x5DE6, 0xA5AB, 0x5E02, + 0xA5AC, 0x5E03, 0xA5AD, 0x5E73, 0xA5AE, 0x5E7C, 0xA5AF, 0x5F01, 0xA5B0, 0x5F18, 0xA5B1, 0x5F17, 0xA5B2, 0x5FC5, 0xA5B3, 0x620A, + 0xA5B4, 0x6253, 0xA5B5, 0x6254, 0xA5B6, 0x6252, 0xA5B7, 0x6251, 0xA5B8, 0x65A5, 0xA5B9, 0x65E6, 0xA5BA, 0x672E, 0xA5BB, 0x672C, + 0xA5BC, 0x672A, 0xA5BD, 0x672B, 0xA5BE, 0x672D, 0xA5BF, 0x6B63, 0xA5C0, 0x6BCD, 0xA5C1, 0x6C11, 0xA5C2, 0x6C10, 0xA5C3, 0x6C38, + 0xA5C4, 0x6C41, 0xA5C5, 0x6C40, 0xA5C6, 0x6C3E, 0xA5C7, 0x72AF, 0xA5C8, 0x7384, 0xA5C9, 0x7389, 0xA5CA, 0x74DC, 0xA5CB, 0x74E6, + 0xA5CC, 0x7518, 0xA5CD, 0x751F, 0xA5CE, 0x7528, 0xA5CF, 0x7529, 0xA5D0, 0x7530, 0xA5D1, 0x7531, 0xA5D2, 0x7532, 0xA5D3, 0x7533, + 0xA5D4, 0x758B, 0xA5D5, 0x767D, 0xA5D6, 0x76AE, 0xA5D7, 0x76BF, 0xA5D8, 0x76EE, 0xA5D9, 0x77DB, 0xA5DA, 0x77E2, 0xA5DB, 0x77F3, + 0xA5DC, 0x793A, 0xA5DD, 0x79BE, 0xA5DE, 0x7A74, 0xA5DF, 0x7ACB, 0xA5E0, 0x4E1E, 0xA5E1, 0x4E1F, 0xA5E2, 0x4E52, 0xA5E3, 0x4E53, + 0xA5E4, 0x4E69, 0xA5E5, 0x4E99, 0xA5E6, 0x4EA4, 0xA5E7, 0x4EA6, 0xA5E8, 0x4EA5, 0xA5E9, 0x4EFF, 0xA5EA, 0x4F09, 0xA5EB, 0x4F19, + 0xA5EC, 0x4F0A, 0xA5ED, 0x4F15, 0xA5EE, 0x4F0D, 0xA5EF, 0x4F10, 0xA5F0, 0x4F11, 0xA5F1, 0x4F0F, 0xA5F2, 0x4EF2, 0xA5F3, 0x4EF6, + 0xA5F4, 0x4EFB, 0xA5F5, 0x4EF0, 0xA5F6, 0x4EF3, 0xA5F7, 0x4EFD, 0xA5F8, 0x4F01, 0xA5F9, 0x4F0B, 0xA5FA, 0x5149, 0xA5FB, 0x5147, + 0xA5FC, 0x5146, 0xA5FD, 0x5148, 0xA5FE, 0x5168, 0xA640, 0x5171, 0xA641, 0x518D, 0xA642, 0x51B0, 0xA643, 0x5217, 0xA644, 0x5211, + 0xA645, 0x5212, 0xA646, 0x520E, 0xA647, 0x5216, 0xA648, 0x52A3, 0xA649, 0x5308, 0xA64A, 0x5321, 0xA64B, 0x5320, 0xA64C, 0x5370, + 0xA64D, 0x5371, 0xA64E, 0x5409, 0xA64F, 0x540F, 0xA650, 0x540C, 0xA651, 0x540A, 0xA652, 0x5410, 0xA653, 0x5401, 0xA654, 0x540B, + 0xA655, 0x5404, 0xA656, 0x5411, 0xA657, 0x540D, 0xA658, 0x5408, 0xA659, 0x5403, 0xA65A, 0x540E, 0xA65B, 0x5406, 0xA65C, 0x5412, + 0xA65D, 0x56E0, 0xA65E, 0x56DE, 0xA65F, 0x56DD, 0xA660, 0x5733, 0xA661, 0x5730, 0xA662, 0x5728, 0xA663, 0x572D, 0xA664, 0x572C, + 0xA665, 0x572F, 0xA666, 0x5729, 0xA667, 0x5919, 0xA668, 0x591A, 0xA669, 0x5937, 0xA66A, 0x5938, 0xA66B, 0x5984, 0xA66C, 0x5978, + 0xA66D, 0x5983, 0xA66E, 0x597D, 0xA66F, 0x5979, 0xA670, 0x5982, 0xA671, 0x5981, 0xA672, 0x5B57, 0xA673, 0x5B58, 0xA674, 0x5B87, + 0xA675, 0x5B88, 0xA676, 0x5B85, 0xA677, 0x5B89, 0xA678, 0x5BFA, 0xA679, 0x5C16, 0xA67A, 0x5C79, 0xA67B, 0x5DDE, 0xA67C, 0x5E06, + 0xA67D, 0x5E76, 0xA67E, 0x5E74, 0xA6A1, 0x5F0F, 0xA6A2, 0x5F1B, 0xA6A3, 0x5FD9, 0xA6A4, 0x5FD6, 0xA6A5, 0x620E, 0xA6A6, 0x620C, + 0xA6A7, 0x620D, 0xA6A8, 0x6210, 0xA6A9, 0x6263, 0xA6AA, 0x625B, 0xA6AB, 0x6258, 0xA6AC, 0x6536, 0xA6AD, 0x65E9, 0xA6AE, 0x65E8, + 0xA6AF, 0x65EC, 0xA6B0, 0x65ED, 0xA6B1, 0x66F2, 0xA6B2, 0x66F3, 0xA6B3, 0x6709, 0xA6B4, 0x673D, 0xA6B5, 0x6734, 0xA6B6, 0x6731, + 0xA6B7, 0x6735, 0xA6B8, 0x6B21, 0xA6B9, 0x6B64, 0xA6BA, 0x6B7B, 0xA6BB, 0x6C16, 0xA6BC, 0x6C5D, 0xA6BD, 0x6C57, 0xA6BE, 0x6C59, + 0xA6BF, 0x6C5F, 0xA6C0, 0x6C60, 0xA6C1, 0x6C50, 0xA6C2, 0x6C55, 0xA6C3, 0x6C61, 0xA6C4, 0x6C5B, 0xA6C5, 0x6C4D, 0xA6C6, 0x6C4E, + 0xA6C7, 0x7070, 0xA6C8, 0x725F, 0xA6C9, 0x725D, 0xA6CA, 0x767E, 0xA6CB, 0x7AF9, 0xA6CC, 0x7C73, 0xA6CD, 0x7CF8, 0xA6CE, 0x7F36, + 0xA6CF, 0x7F8A, 0xA6D0, 0x7FBD, 0xA6D1, 0x8001, 0xA6D2, 0x8003, 0xA6D3, 0x800C, 0xA6D4, 0x8012, 0xA6D5, 0x8033, 0xA6D6, 0x807F, + 0xA6D7, 0x8089, 0xA6D8, 0x808B, 0xA6D9, 0x808C, 0xA6DA, 0x81E3, 0xA6DB, 0x81EA, 0xA6DC, 0x81F3, 0xA6DD, 0x81FC, 0xA6DE, 0x820C, + 0xA6DF, 0x821B, 0xA6E0, 0x821F, 0xA6E1, 0x826E, 0xA6E2, 0x8272, 0xA6E3, 0x827E, 0xA6E4, 0x866B, 0xA6E5, 0x8840, 0xA6E6, 0x884C, + 0xA6E7, 0x8863, 0xA6E8, 0x897F, 0xA6E9, 0x9621, 0xA6EA, 0x4E32, 0xA6EB, 0x4EA8, 0xA6EC, 0x4F4D, 0xA6ED, 0x4F4F, 0xA6EE, 0x4F47, + 0xA6EF, 0x4F57, 0xA6F0, 0x4F5E, 0xA6F1, 0x4F34, 0xA6F2, 0x4F5B, 0xA6F3, 0x4F55, 0xA6F4, 0x4F30, 0xA6F5, 0x4F50, 0xA6F6, 0x4F51, + 0xA6F7, 0x4F3D, 0xA6F8, 0x4F3A, 0xA6F9, 0x4F38, 0xA6FA, 0x4F43, 0xA6FB, 0x4F54, 0xA6FC, 0x4F3C, 0xA6FD, 0x4F46, 0xA6FE, 0x4F63, + 0xA740, 0x4F5C, 0xA741, 0x4F60, 0xA742, 0x4F2F, 0xA743, 0x4F4E, 0xA744, 0x4F36, 0xA745, 0x4F59, 0xA746, 0x4F5D, 0xA747, 0x4F48, + 0xA748, 0x4F5A, 0xA749, 0x514C, 0xA74A, 0x514B, 0xA74B, 0x514D, 0xA74C, 0x5175, 0xA74D, 0x51B6, 0xA74E, 0x51B7, 0xA74F, 0x5225, + 0xA750, 0x5224, 0xA751, 0x5229, 0xA752, 0x522A, 0xA753, 0x5228, 0xA754, 0x52AB, 0xA755, 0x52A9, 0xA756, 0x52AA, 0xA757, 0x52AC, + 0xA758, 0x5323, 0xA759, 0x5373, 0xA75A, 0x5375, 0xA75B, 0x541D, 0xA75C, 0x542D, 0xA75D, 0x541E, 0xA75E, 0x543E, 0xA75F, 0x5426, + 0xA760, 0x544E, 0xA761, 0x5427, 0xA762, 0x5446, 0xA763, 0x5443, 0xA764, 0x5433, 0xA765, 0x5448, 0xA766, 0x5442, 0xA767, 0x541B, + 0xA768, 0x5429, 0xA769, 0x544A, 0xA76A, 0x5439, 0xA76B, 0x543B, 0xA76C, 0x5438, 0xA76D, 0x542E, 0xA76E, 0x5435, 0xA76F, 0x5436, + 0xA770, 0x5420, 0xA771, 0x543C, 0xA772, 0x5440, 0xA773, 0x5431, 0xA774, 0x542B, 0xA775, 0x541F, 0xA776, 0x542C, 0xA777, 0x56EA, + 0xA778, 0x56F0, 0xA779, 0x56E4, 0xA77A, 0x56EB, 0xA77B, 0x574A, 0xA77C, 0x5751, 0xA77D, 0x5740, 0xA77E, 0x574D, 0xA7A1, 0x5747, + 0xA7A2, 0x574E, 0xA7A3, 0x573E, 0xA7A4, 0x5750, 0xA7A5, 0x574F, 0xA7A6, 0x573B, 0xA7A7, 0x58EF, 0xA7A8, 0x593E, 0xA7A9, 0x599D, + 0xA7AA, 0x5992, 0xA7AB, 0x59A8, 0xA7AC, 0x599E, 0xA7AD, 0x59A3, 0xA7AE, 0x5999, 0xA7AF, 0x5996, 0xA7B0, 0x598D, 0xA7B1, 0x59A4, + 0xA7B2, 0x5993, 0xA7B3, 0x598A, 0xA7B4, 0x59A5, 0xA7B5, 0x5B5D, 0xA7B6, 0x5B5C, 0xA7B7, 0x5B5A, 0xA7B8, 0x5B5B, 0xA7B9, 0x5B8C, + 0xA7BA, 0x5B8B, 0xA7BB, 0x5B8F, 0xA7BC, 0x5C2C, 0xA7BD, 0x5C40, 0xA7BE, 0x5C41, 0xA7BF, 0x5C3F, 0xA7C0, 0x5C3E, 0xA7C1, 0x5C90, + 0xA7C2, 0x5C91, 0xA7C3, 0x5C94, 0xA7C4, 0x5C8C, 0xA7C5, 0x5DEB, 0xA7C6, 0x5E0C, 0xA7C7, 0x5E8F, 0xA7C8, 0x5E87, 0xA7C9, 0x5E8A, + 0xA7CA, 0x5EF7, 0xA7CB, 0x5F04, 0xA7CC, 0x5F1F, 0xA7CD, 0x5F64, 0xA7CE, 0x5F62, 0xA7CF, 0x5F77, 0xA7D0, 0x5F79, 0xA7D1, 0x5FD8, + 0xA7D2, 0x5FCC, 0xA7D3, 0x5FD7, 0xA7D4, 0x5FCD, 0xA7D5, 0x5FF1, 0xA7D6, 0x5FEB, 0xA7D7, 0x5FF8, 0xA7D8, 0x5FEA, 0xA7D9, 0x6212, + 0xA7DA, 0x6211, 0xA7DB, 0x6284, 0xA7DC, 0x6297, 0xA7DD, 0x6296, 0xA7DE, 0x6280, 0xA7DF, 0x6276, 0xA7E0, 0x6289, 0xA7E1, 0x626D, + 0xA7E2, 0x628A, 0xA7E3, 0x627C, 0xA7E4, 0x627E, 0xA7E5, 0x6279, 0xA7E6, 0x6273, 0xA7E7, 0x6292, 0xA7E8, 0x626F, 0xA7E9, 0x6298, + 0xA7EA, 0x626E, 0xA7EB, 0x6295, 0xA7EC, 0x6293, 0xA7ED, 0x6291, 0xA7EE, 0x6286, 0xA7EF, 0x6539, 0xA7F0, 0x653B, 0xA7F1, 0x6538, + 0xA7F2, 0x65F1, 0xA7F3, 0x66F4, 0xA7F4, 0x675F, 0xA7F5, 0x674E, 0xA7F6, 0x674F, 0xA7F7, 0x6750, 0xA7F8, 0x6751, 0xA7F9, 0x675C, + 0xA7FA, 0x6756, 0xA7FB, 0x675E, 0xA7FC, 0x6749, 0xA7FD, 0x6746, 0xA7FE, 0x6760, 0xA840, 0x6753, 0xA841, 0x6757, 0xA842, 0x6B65, + 0xA843, 0x6BCF, 0xA844, 0x6C42, 0xA845, 0x6C5E, 0xA846, 0x6C99, 0xA847, 0x6C81, 0xA848, 0x6C88, 0xA849, 0x6C89, 0xA84A, 0x6C85, + 0xA84B, 0x6C9B, 0xA84C, 0x6C6A, 0xA84D, 0x6C7A, 0xA84E, 0x6C90, 0xA84F, 0x6C70, 0xA850, 0x6C8C, 0xA851, 0x6C68, 0xA852, 0x6C96, + 0xA853, 0x6C92, 0xA854, 0x6C7D, 0xA855, 0x6C83, 0xA856, 0x6C72, 0xA857, 0x6C7E, 0xA858, 0x6C74, 0xA859, 0x6C86, 0xA85A, 0x6C76, + 0xA85B, 0x6C8D, 0xA85C, 0x6C94, 0xA85D, 0x6C98, 0xA85E, 0x6C82, 0xA85F, 0x7076, 0xA860, 0x707C, 0xA861, 0x707D, 0xA862, 0x7078, + 0xA863, 0x7262, 0xA864, 0x7261, 0xA865, 0x7260, 0xA866, 0x72C4, 0xA867, 0x72C2, 0xA868, 0x7396, 0xA869, 0x752C, 0xA86A, 0x752B, + 0xA86B, 0x7537, 0xA86C, 0x7538, 0xA86D, 0x7682, 0xA86E, 0x76EF, 0xA86F, 0x77E3, 0xA870, 0x79C1, 0xA871, 0x79C0, 0xA872, 0x79BF, + 0xA873, 0x7A76, 0xA874, 0x7CFB, 0xA875, 0x7F55, 0xA876, 0x8096, 0xA877, 0x8093, 0xA878, 0x809D, 0xA879, 0x8098, 0xA87A, 0x809B, + 0xA87B, 0x809A, 0xA87C, 0x80B2, 0xA87D, 0x826F, 0xA87E, 0x8292, 0xA8A1, 0x828B, 0xA8A2, 0x828D, 0xA8A3, 0x898B, 0xA8A4, 0x89D2, + 0xA8A5, 0x8A00, 0xA8A6, 0x8C37, 0xA8A7, 0x8C46, 0xA8A8, 0x8C55, 0xA8A9, 0x8C9D, 0xA8AA, 0x8D64, 0xA8AB, 0x8D70, 0xA8AC, 0x8DB3, + 0xA8AD, 0x8EAB, 0xA8AE, 0x8ECA, 0xA8AF, 0x8F9B, 0xA8B0, 0x8FB0, 0xA8B1, 0x8FC2, 0xA8B2, 0x8FC6, 0xA8B3, 0x8FC5, 0xA8B4, 0x8FC4, + 0xA8B5, 0x5DE1, 0xA8B6, 0x9091, 0xA8B7, 0x90A2, 0xA8B8, 0x90AA, 0xA8B9, 0x90A6, 0xA8BA, 0x90A3, 0xA8BB, 0x9149, 0xA8BC, 0x91C6, + 0xA8BD, 0x91CC, 0xA8BE, 0x9632, 0xA8BF, 0x962E, 0xA8C0, 0x9631, 0xA8C1, 0x962A, 0xA8C2, 0x962C, 0xA8C3, 0x4E26, 0xA8C4, 0x4E56, + 0xA8C5, 0x4E73, 0xA8C6, 0x4E8B, 0xA8C7, 0x4E9B, 0xA8C8, 0x4E9E, 0xA8C9, 0x4EAB, 0xA8CA, 0x4EAC, 0xA8CB, 0x4F6F, 0xA8CC, 0x4F9D, + 0xA8CD, 0x4F8D, 0xA8CE, 0x4F73, 0xA8CF, 0x4F7F, 0xA8D0, 0x4F6C, 0xA8D1, 0x4F9B, 0xA8D2, 0x4F8B, 0xA8D3, 0x4F86, 0xA8D4, 0x4F83, + 0xA8D5, 0x4F70, 0xA8D6, 0x4F75, 0xA8D7, 0x4F88, 0xA8D8, 0x4F69, 0xA8D9, 0x4F7B, 0xA8DA, 0x4F96, 0xA8DB, 0x4F7E, 0xA8DC, 0x4F8F, + 0xA8DD, 0x4F91, 0xA8DE, 0x4F7A, 0xA8DF, 0x5154, 0xA8E0, 0x5152, 0xA8E1, 0x5155, 0xA8E2, 0x5169, 0xA8E3, 0x5177, 0xA8E4, 0x5176, + 0xA8E5, 0x5178, 0xA8E6, 0x51BD, 0xA8E7, 0x51FD, 0xA8E8, 0x523B, 0xA8E9, 0x5238, 0xA8EA, 0x5237, 0xA8EB, 0x523A, 0xA8EC, 0x5230, + 0xA8ED, 0x522E, 0xA8EE, 0x5236, 0xA8EF, 0x5241, 0xA8F0, 0x52BE, 0xA8F1, 0x52BB, 0xA8F2, 0x5352, 0xA8F3, 0x5354, 0xA8F4, 0x5353, + 0xA8F5, 0x5351, 0xA8F6, 0x5366, 0xA8F7, 0x5377, 0xA8F8, 0x5378, 0xA8F9, 0x5379, 0xA8FA, 0x53D6, 0xA8FB, 0x53D4, 0xA8FC, 0x53D7, + 0xA8FD, 0x5473, 0xA8FE, 0x5475, 0xA940, 0x5496, 0xA941, 0x5478, 0xA942, 0x5495, 0xA943, 0x5480, 0xA944, 0x547B, 0xA945, 0x5477, + 0xA946, 0x5484, 0xA947, 0x5492, 0xA948, 0x5486, 0xA949, 0x547C, 0xA94A, 0x5490, 0xA94B, 0x5471, 0xA94C, 0x5476, 0xA94D, 0x548C, + 0xA94E, 0x549A, 0xA94F, 0x5462, 0xA950, 0x5468, 0xA951, 0x548B, 0xA952, 0x547D, 0xA953, 0x548E, 0xA954, 0x56FA, 0xA955, 0x5783, + 0xA956, 0x5777, 0xA957, 0x576A, 0xA958, 0x5769, 0xA959, 0x5761, 0xA95A, 0x5766, 0xA95B, 0x5764, 0xA95C, 0x577C, 0xA95D, 0x591C, + 0xA95E, 0x5949, 0xA95F, 0x5947, 0xA960, 0x5948, 0xA961, 0x5944, 0xA962, 0x5954, 0xA963, 0x59BE, 0xA964, 0x59BB, 0xA965, 0x59D4, + 0xA966, 0x59B9, 0xA967, 0x59AE, 0xA968, 0x59D1, 0xA969, 0x59C6, 0xA96A, 0x59D0, 0xA96B, 0x59CD, 0xA96C, 0x59CB, 0xA96D, 0x59D3, + 0xA96E, 0x59CA, 0xA96F, 0x59AF, 0xA970, 0x59B3, 0xA971, 0x59D2, 0xA972, 0x59C5, 0xA973, 0x5B5F, 0xA974, 0x5B64, 0xA975, 0x5B63, + 0xA976, 0x5B97, 0xA977, 0x5B9A, 0xA978, 0x5B98, 0xA979, 0x5B9C, 0xA97A, 0x5B99, 0xA97B, 0x5B9B, 0xA97C, 0x5C1A, 0xA97D, 0x5C48, + 0xA97E, 0x5C45, 0xA9A1, 0x5C46, 0xA9A2, 0x5CB7, 0xA9A3, 0x5CA1, 0xA9A4, 0x5CB8, 0xA9A5, 0x5CA9, 0xA9A6, 0x5CAB, 0xA9A7, 0x5CB1, + 0xA9A8, 0x5CB3, 0xA9A9, 0x5E18, 0xA9AA, 0x5E1A, 0xA9AB, 0x5E16, 0xA9AC, 0x5E15, 0xA9AD, 0x5E1B, 0xA9AE, 0x5E11, 0xA9AF, 0x5E78, + 0xA9B0, 0x5E9A, 0xA9B1, 0x5E97, 0xA9B2, 0x5E9C, 0xA9B3, 0x5E95, 0xA9B4, 0x5E96, 0xA9B5, 0x5EF6, 0xA9B6, 0x5F26, 0xA9B7, 0x5F27, + 0xA9B8, 0x5F29, 0xA9B9, 0x5F80, 0xA9BA, 0x5F81, 0xA9BB, 0x5F7F, 0xA9BC, 0x5F7C, 0xA9BD, 0x5FDD, 0xA9BE, 0x5FE0, 0xA9BF, 0x5FFD, + 0xA9C0, 0x5FF5, 0xA9C1, 0x5FFF, 0xA9C2, 0x600F, 0xA9C3, 0x6014, 0xA9C4, 0x602F, 0xA9C5, 0x6035, 0xA9C6, 0x6016, 0xA9C7, 0x602A, + 0xA9C8, 0x6015, 0xA9C9, 0x6021, 0xA9CA, 0x6027, 0xA9CB, 0x6029, 0xA9CC, 0x602B, 0xA9CD, 0x601B, 0xA9CE, 0x6216, 0xA9CF, 0x6215, + 0xA9D0, 0x623F, 0xA9D1, 0x623E, 0xA9D2, 0x6240, 0xA9D3, 0x627F, 0xA9D4, 0x62C9, 0xA9D5, 0x62CC, 0xA9D6, 0x62C4, 0xA9D7, 0x62BF, + 0xA9D8, 0x62C2, 0xA9D9, 0x62B9, 0xA9DA, 0x62D2, 0xA9DB, 0x62DB, 0xA9DC, 0x62AB, 0xA9DD, 0x62D3, 0xA9DE, 0x62D4, 0xA9DF, 0x62CB, + 0xA9E0, 0x62C8, 0xA9E1, 0x62A8, 0xA9E2, 0x62BD, 0xA9E3, 0x62BC, 0xA9E4, 0x62D0, 0xA9E5, 0x62D9, 0xA9E6, 0x62C7, 0xA9E7, 0x62CD, + 0xA9E8, 0x62B5, 0xA9E9, 0x62DA, 0xA9EA, 0x62B1, 0xA9EB, 0x62D8, 0xA9EC, 0x62D6, 0xA9ED, 0x62D7, 0xA9EE, 0x62C6, 0xA9EF, 0x62AC, + 0xA9F0, 0x62CE, 0xA9F1, 0x653E, 0xA9F2, 0x65A7, 0xA9F3, 0x65BC, 0xA9F4, 0x65FA, 0xA9F5, 0x6614, 0xA9F6, 0x6613, 0xA9F7, 0x660C, + 0xA9F8, 0x6606, 0xA9F9, 0x6602, 0xA9FA, 0x660E, 0xA9FB, 0x6600, 0xA9FC, 0x660F, 0xA9FD, 0x6615, 0xA9FE, 0x660A, 0xAA40, 0x6607, + 0xAA41, 0x670D, 0xAA42, 0x670B, 0xAA43, 0x676D, 0xAA44, 0x678B, 0xAA45, 0x6795, 0xAA46, 0x6771, 0xAA47, 0x679C, 0xAA48, 0x6773, + 0xAA49, 0x6777, 0xAA4A, 0x6787, 0xAA4B, 0x679D, 0xAA4C, 0x6797, 0xAA4D, 0x676F, 0xAA4E, 0x6770, 0xAA4F, 0x677F, 0xAA50, 0x6789, + 0xAA51, 0x677E, 0xAA52, 0x6790, 0xAA53, 0x6775, 0xAA54, 0x679A, 0xAA55, 0x6793, 0xAA56, 0x677C, 0xAA57, 0x676A, 0xAA58, 0x6772, + 0xAA59, 0x6B23, 0xAA5A, 0x6B66, 0xAA5B, 0x6B67, 0xAA5C, 0x6B7F, 0xAA5D, 0x6C13, 0xAA5E, 0x6C1B, 0xAA5F, 0x6CE3, 0xAA60, 0x6CE8, + 0xAA61, 0x6CF3, 0xAA62, 0x6CB1, 0xAA63, 0x6CCC, 0xAA64, 0x6CE5, 0xAA65, 0x6CB3, 0xAA66, 0x6CBD, 0xAA67, 0x6CBE, 0xAA68, 0x6CBC, + 0xAA69, 0x6CE2, 0xAA6A, 0x6CAB, 0xAA6B, 0x6CD5, 0xAA6C, 0x6CD3, 0xAA6D, 0x6CB8, 0xAA6E, 0x6CC4, 0xAA6F, 0x6CB9, 0xAA70, 0x6CC1, + 0xAA71, 0x6CAE, 0xAA72, 0x6CD7, 0xAA73, 0x6CC5, 0xAA74, 0x6CF1, 0xAA75, 0x6CBF, 0xAA76, 0x6CBB, 0xAA77, 0x6CE1, 0xAA78, 0x6CDB, + 0xAA79, 0x6CCA, 0xAA7A, 0x6CAC, 0xAA7B, 0x6CEF, 0xAA7C, 0x6CDC, 0xAA7D, 0x6CD6, 0xAA7E, 0x6CE0, 0xAAA1, 0x7095, 0xAAA2, 0x708E, + 0xAAA3, 0x7092, 0xAAA4, 0x708A, 0xAAA5, 0x7099, 0xAAA6, 0x722C, 0xAAA7, 0x722D, 0xAAA8, 0x7238, 0xAAA9, 0x7248, 0xAAAA, 0x7267, + 0xAAAB, 0x7269, 0xAAAC, 0x72C0, 0xAAAD, 0x72CE, 0xAAAE, 0x72D9, 0xAAAF, 0x72D7, 0xAAB0, 0x72D0, 0xAAB1, 0x73A9, 0xAAB2, 0x73A8, + 0xAAB3, 0x739F, 0xAAB4, 0x73AB, 0xAAB5, 0x73A5, 0xAAB6, 0x753D, 0xAAB7, 0x759D, 0xAAB8, 0x7599, 0xAAB9, 0x759A, 0xAABA, 0x7684, + 0xAABB, 0x76C2, 0xAABC, 0x76F2, 0xAABD, 0x76F4, 0xAABE, 0x77E5, 0xAABF, 0x77FD, 0xAAC0, 0x793E, 0xAAC1, 0x7940, 0xAAC2, 0x7941, + 0xAAC3, 0x79C9, 0xAAC4, 0x79C8, 0xAAC5, 0x7A7A, 0xAAC6, 0x7A79, 0xAAC7, 0x7AFA, 0xAAC8, 0x7CFE, 0xAAC9, 0x7F54, 0xAACA, 0x7F8C, + 0xAACB, 0x7F8B, 0xAACC, 0x8005, 0xAACD, 0x80BA, 0xAACE, 0x80A5, 0xAACF, 0x80A2, 0xAAD0, 0x80B1, 0xAAD1, 0x80A1, 0xAAD2, 0x80AB, + 0xAAD3, 0x80A9, 0xAAD4, 0x80B4, 0xAAD5, 0x80AA, 0xAAD6, 0x80AF, 0xAAD7, 0x81E5, 0xAAD8, 0x81FE, 0xAAD9, 0x820D, 0xAADA, 0x82B3, + 0xAADB, 0x829D, 0xAADC, 0x8299, 0xAADD, 0x82AD, 0xAADE, 0x82BD, 0xAADF, 0x829F, 0xAAE0, 0x82B9, 0xAAE1, 0x82B1, 0xAAE2, 0x82AC, + 0xAAE3, 0x82A5, 0xAAE4, 0x82AF, 0xAAE5, 0x82B8, 0xAAE6, 0x82A3, 0xAAE7, 0x82B0, 0xAAE8, 0x82BE, 0xAAE9, 0x82B7, 0xAAEA, 0x864E, + 0xAAEB, 0x8671, 0xAAEC, 0x521D, 0xAAED, 0x8868, 0xAAEE, 0x8ECB, 0xAAEF, 0x8FCE, 0xAAF0, 0x8FD4, 0xAAF1, 0x8FD1, 0xAAF2, 0x90B5, + 0xAAF3, 0x90B8, 0xAAF4, 0x90B1, 0xAAF5, 0x90B6, 0xAAF6, 0x91C7, 0xAAF7, 0x91D1, 0xAAF8, 0x9577, 0xAAF9, 0x9580, 0xAAFA, 0x961C, + 0xAAFB, 0x9640, 0xAAFC, 0x963F, 0xAAFD, 0x963B, 0xAAFE, 0x9644, 0xAB40, 0x9642, 0xAB41, 0x96B9, 0xAB42, 0x96E8, 0xAB43, 0x9752, + 0xAB44, 0x975E, 0xAB45, 0x4E9F, 0xAB46, 0x4EAD, 0xAB47, 0x4EAE, 0xAB48, 0x4FE1, 0xAB49, 0x4FB5, 0xAB4A, 0x4FAF, 0xAB4B, 0x4FBF, + 0xAB4C, 0x4FE0, 0xAB4D, 0x4FD1, 0xAB4E, 0x4FCF, 0xAB4F, 0x4FDD, 0xAB50, 0x4FC3, 0xAB51, 0x4FB6, 0xAB52, 0x4FD8, 0xAB53, 0x4FDF, + 0xAB54, 0x4FCA, 0xAB55, 0x4FD7, 0xAB56, 0x4FAE, 0xAB57, 0x4FD0, 0xAB58, 0x4FC4, 0xAB59, 0x4FC2, 0xAB5A, 0x4FDA, 0xAB5B, 0x4FCE, + 0xAB5C, 0x4FDE, 0xAB5D, 0x4FB7, 0xAB5E, 0x5157, 0xAB5F, 0x5192, 0xAB60, 0x5191, 0xAB61, 0x51A0, 0xAB62, 0x524E, 0xAB63, 0x5243, + 0xAB64, 0x524A, 0xAB65, 0x524D, 0xAB66, 0x524C, 0xAB67, 0x524B, 0xAB68, 0x5247, 0xAB69, 0x52C7, 0xAB6A, 0x52C9, 0xAB6B, 0x52C3, + 0xAB6C, 0x52C1, 0xAB6D, 0x530D, 0xAB6E, 0x5357, 0xAB6F, 0x537B, 0xAB70, 0x539A, 0xAB71, 0x53DB, 0xAB72, 0x54AC, 0xAB73, 0x54C0, + 0xAB74, 0x54A8, 0xAB75, 0x54CE, 0xAB76, 0x54C9, 0xAB77, 0x54B8, 0xAB78, 0x54A6, 0xAB79, 0x54B3, 0xAB7A, 0x54C7, 0xAB7B, 0x54C2, + 0xAB7C, 0x54BD, 0xAB7D, 0x54AA, 0xAB7E, 0x54C1, 0xABA1, 0x54C4, 0xABA2, 0x54C8, 0xABA3, 0x54AF, 0xABA4, 0x54AB, 0xABA5, 0x54B1, + 0xABA6, 0x54BB, 0xABA7, 0x54A9, 0xABA8, 0x54A7, 0xABA9, 0x54BF, 0xABAA, 0x56FF, 0xABAB, 0x5782, 0xABAC, 0x578B, 0xABAD, 0x57A0, + 0xABAE, 0x57A3, 0xABAF, 0x57A2, 0xABB0, 0x57CE, 0xABB1, 0x57AE, 0xABB2, 0x5793, 0xABB3, 0x5955, 0xABB4, 0x5951, 0xABB5, 0x594F, + 0xABB6, 0x594E, 0xABB7, 0x5950, 0xABB8, 0x59DC, 0xABB9, 0x59D8, 0xABBA, 0x59FF, 0xABBB, 0x59E3, 0xABBC, 0x59E8, 0xABBD, 0x5A03, + 0xABBE, 0x59E5, 0xABBF, 0x59EA, 0xABC0, 0x59DA, 0xABC1, 0x59E6, 0xABC2, 0x5A01, 0xABC3, 0x59FB, 0xABC4, 0x5B69, 0xABC5, 0x5BA3, + 0xABC6, 0x5BA6, 0xABC7, 0x5BA4, 0xABC8, 0x5BA2, 0xABC9, 0x5BA5, 0xABCA, 0x5C01, 0xABCB, 0x5C4E, 0xABCC, 0x5C4F, 0xABCD, 0x5C4D, + 0xABCE, 0x5C4B, 0xABCF, 0x5CD9, 0xABD0, 0x5CD2, 0xABD1, 0x5DF7, 0xABD2, 0x5E1D, 0xABD3, 0x5E25, 0xABD4, 0x5E1F, 0xABD5, 0x5E7D, + 0xABD6, 0x5EA0, 0xABD7, 0x5EA6, 0xABD8, 0x5EFA, 0xABD9, 0x5F08, 0xABDA, 0x5F2D, 0xABDB, 0x5F65, 0xABDC, 0x5F88, 0xABDD, 0x5F85, + 0xABDE, 0x5F8A, 0xABDF, 0x5F8B, 0xABE0, 0x5F87, 0xABE1, 0x5F8C, 0xABE2, 0x5F89, 0xABE3, 0x6012, 0xABE4, 0x601D, 0xABE5, 0x6020, + 0xABE6, 0x6025, 0xABE7, 0x600E, 0xABE8, 0x6028, 0xABE9, 0x604D, 0xABEA, 0x6070, 0xABEB, 0x6068, 0xABEC, 0x6062, 0xABED, 0x6046, + 0xABEE, 0x6043, 0xABEF, 0x606C, 0xABF0, 0x606B, 0xABF1, 0x606A, 0xABF2, 0x6064, 0xABF3, 0x6241, 0xABF4, 0x62DC, 0xABF5, 0x6316, + 0xABF6, 0x6309, 0xABF7, 0x62FC, 0xABF8, 0x62ED, 0xABF9, 0x6301, 0xABFA, 0x62EE, 0xABFB, 0x62FD, 0xABFC, 0x6307, 0xABFD, 0x62F1, + 0xABFE, 0x62F7, 0xAC40, 0x62EF, 0xAC41, 0x62EC, 0xAC42, 0x62FE, 0xAC43, 0x62F4, 0xAC44, 0x6311, 0xAC45, 0x6302, 0xAC46, 0x653F, + 0xAC47, 0x6545, 0xAC48, 0x65AB, 0xAC49, 0x65BD, 0xAC4A, 0x65E2, 0xAC4B, 0x6625, 0xAC4C, 0x662D, 0xAC4D, 0x6620, 0xAC4E, 0x6627, + 0xAC4F, 0x662F, 0xAC50, 0x661F, 0xAC51, 0x6628, 0xAC52, 0x6631, 0xAC53, 0x6624, 0xAC54, 0x66F7, 0xAC55, 0x67FF, 0xAC56, 0x67D3, + 0xAC57, 0x67F1, 0xAC58, 0x67D4, 0xAC59, 0x67D0, 0xAC5A, 0x67EC, 0xAC5B, 0x67B6, 0xAC5C, 0x67AF, 0xAC5D, 0x67F5, 0xAC5E, 0x67E9, + 0xAC5F, 0x67EF, 0xAC60, 0x67C4, 0xAC61, 0x67D1, 0xAC62, 0x67B4, 0xAC63, 0x67DA, 0xAC64, 0x67E5, 0xAC65, 0x67B8, 0xAC66, 0x67CF, + 0xAC67, 0x67DE, 0xAC68, 0x67F3, 0xAC69, 0x67B0, 0xAC6A, 0x67D9, 0xAC6B, 0x67E2, 0xAC6C, 0x67DD, 0xAC6D, 0x67D2, 0xAC6E, 0x6B6A, + 0xAC6F, 0x6B83, 0xAC70, 0x6B86, 0xAC71, 0x6BB5, 0xAC72, 0x6BD2, 0xAC73, 0x6BD7, 0xAC74, 0x6C1F, 0xAC75, 0x6CC9, 0xAC76, 0x6D0B, + 0xAC77, 0x6D32, 0xAC78, 0x6D2A, 0xAC79, 0x6D41, 0xAC7A, 0x6D25, 0xAC7B, 0x6D0C, 0xAC7C, 0x6D31, 0xAC7D, 0x6D1E, 0xAC7E, 0x6D17, + 0xACA1, 0x6D3B, 0xACA2, 0x6D3D, 0xACA3, 0x6D3E, 0xACA4, 0x6D36, 0xACA5, 0x6D1B, 0xACA6, 0x6CF5, 0xACA7, 0x6D39, 0xACA8, 0x6D27, + 0xACA9, 0x6D38, 0xACAA, 0x6D29, 0xACAB, 0x6D2E, 0xACAC, 0x6D35, 0xACAD, 0x6D0E, 0xACAE, 0x6D2B, 0xACAF, 0x70AB, 0xACB0, 0x70BA, + 0xACB1, 0x70B3, 0xACB2, 0x70AC, 0xACB3, 0x70AF, 0xACB4, 0x70AD, 0xACB5, 0x70B8, 0xACB6, 0x70AE, 0xACB7, 0x70A4, 0xACB8, 0x7230, + 0xACB9, 0x7272, 0xACBA, 0x726F, 0xACBB, 0x7274, 0xACBC, 0x72E9, 0xACBD, 0x72E0, 0xACBE, 0x72E1, 0xACBF, 0x73B7, 0xACC0, 0x73CA, + 0xACC1, 0x73BB, 0xACC2, 0x73B2, 0xACC3, 0x73CD, 0xACC4, 0x73C0, 0xACC5, 0x73B3, 0xACC6, 0x751A, 0xACC7, 0x752D, 0xACC8, 0x754F, + 0xACC9, 0x754C, 0xACCA, 0x754E, 0xACCB, 0x754B, 0xACCC, 0x75AB, 0xACCD, 0x75A4, 0xACCE, 0x75A5, 0xACCF, 0x75A2, 0xACD0, 0x75A3, + 0xACD1, 0x7678, 0xACD2, 0x7686, 0xACD3, 0x7687, 0xACD4, 0x7688, 0xACD5, 0x76C8, 0xACD6, 0x76C6, 0xACD7, 0x76C3, 0xACD8, 0x76C5, + 0xACD9, 0x7701, 0xACDA, 0x76F9, 0xACDB, 0x76F8, 0xACDC, 0x7709, 0xACDD, 0x770B, 0xACDE, 0x76FE, 0xACDF, 0x76FC, 0xACE0, 0x7707, + 0xACE1, 0x77DC, 0xACE2, 0x7802, 0xACE3, 0x7814, 0xACE4, 0x780C, 0xACE5, 0x780D, 0xACE6, 0x7946, 0xACE7, 0x7949, 0xACE8, 0x7948, + 0xACE9, 0x7947, 0xACEA, 0x79B9, 0xACEB, 0x79BA, 0xACEC, 0x79D1, 0xACED, 0x79D2, 0xACEE, 0x79CB, 0xACEF, 0x7A7F, 0xACF0, 0x7A81, + 0xACF1, 0x7AFF, 0xACF2, 0x7AFD, 0xACF3, 0x7C7D, 0xACF4, 0x7D02, 0xACF5, 0x7D05, 0xACF6, 0x7D00, 0xACF7, 0x7D09, 0xACF8, 0x7D07, + 0xACF9, 0x7D04, 0xACFA, 0x7D06, 0xACFB, 0x7F38, 0xACFC, 0x7F8E, 0xACFD, 0x7FBF, 0xACFE, 0x8004, 0xAD40, 0x8010, 0xAD41, 0x800D, + 0xAD42, 0x8011, 0xAD43, 0x8036, 0xAD44, 0x80D6, 0xAD45, 0x80E5, 0xAD46, 0x80DA, 0xAD47, 0x80C3, 0xAD48, 0x80C4, 0xAD49, 0x80CC, + 0xAD4A, 0x80E1, 0xAD4B, 0x80DB, 0xAD4C, 0x80CE, 0xAD4D, 0x80DE, 0xAD4E, 0x80E4, 0xAD4F, 0x80DD, 0xAD50, 0x81F4, 0xAD51, 0x8222, + 0xAD52, 0x82E7, 0xAD53, 0x8303, 0xAD54, 0x8305, 0xAD55, 0x82E3, 0xAD56, 0x82DB, 0xAD57, 0x82E6, 0xAD58, 0x8304, 0xAD59, 0x82E5, + 0xAD5A, 0x8302, 0xAD5B, 0x8309, 0xAD5C, 0x82D2, 0xAD5D, 0x82D7, 0xAD5E, 0x82F1, 0xAD5F, 0x8301, 0xAD60, 0x82DC, 0xAD61, 0x82D4, + 0xAD62, 0x82D1, 0xAD63, 0x82DE, 0xAD64, 0x82D3, 0xAD65, 0x82DF, 0xAD66, 0x82EF, 0xAD67, 0x8306, 0xAD68, 0x8650, 0xAD69, 0x8679, + 0xAD6A, 0x867B, 0xAD6B, 0x867A, 0xAD6C, 0x884D, 0xAD6D, 0x886B, 0xAD6E, 0x8981, 0xAD6F, 0x89D4, 0xAD70, 0x8A08, 0xAD71, 0x8A02, + 0xAD72, 0x8A03, 0xAD73, 0x8C9E, 0xAD74, 0x8CA0, 0xAD75, 0x8D74, 0xAD76, 0x8D73, 0xAD77, 0x8DB4, 0xAD78, 0x8ECD, 0xAD79, 0x8ECC, + 0xAD7A, 0x8FF0, 0xAD7B, 0x8FE6, 0xAD7C, 0x8FE2, 0xAD7D, 0x8FEA, 0xAD7E, 0x8FE5, 0xADA1, 0x8FED, 0xADA2, 0x8FEB, 0xADA3, 0x8FE4, + 0xADA4, 0x8FE8, 0xADA5, 0x90CA, 0xADA6, 0x90CE, 0xADA7, 0x90C1, 0xADA8, 0x90C3, 0xADA9, 0x914B, 0xADAA, 0x914A, 0xADAB, 0x91CD, + 0xADAC, 0x9582, 0xADAD, 0x9650, 0xADAE, 0x964B, 0xADAF, 0x964C, 0xADB0, 0x964D, 0xADB1, 0x9762, 0xADB2, 0x9769, 0xADB3, 0x97CB, + 0xADB4, 0x97ED, 0xADB5, 0x97F3, 0xADB6, 0x9801, 0xADB7, 0x98A8, 0xADB8, 0x98DB, 0xADB9, 0x98DF, 0xADBA, 0x9996, 0xADBB, 0x9999, + 0xADBC, 0x4E58, 0xADBD, 0x4EB3, 0xADBE, 0x500C, 0xADBF, 0x500D, 0xADC0, 0x5023, 0xADC1, 0x4FEF, 0xADC2, 0x5026, 0xADC3, 0x5025, + 0xADC4, 0x4FF8, 0xADC5, 0x5029, 0xADC6, 0x5016, 0xADC7, 0x5006, 0xADC8, 0x503C, 0xADC9, 0x501F, 0xADCA, 0x501A, 0xADCB, 0x5012, + 0xADCC, 0x5011, 0xADCD, 0x4FFA, 0xADCE, 0x5000, 0xADCF, 0x5014, 0xADD0, 0x5028, 0xADD1, 0x4FF1, 0xADD2, 0x5021, 0xADD3, 0x500B, + 0xADD4, 0x5019, 0xADD5, 0x5018, 0xADD6, 0x4FF3, 0xADD7, 0x4FEE, 0xADD8, 0x502D, 0xADD9, 0x502A, 0xADDA, 0x4FFE, 0xADDB, 0x502B, + 0xADDC, 0x5009, 0xADDD, 0x517C, 0xADDE, 0x51A4, 0xADDF, 0x51A5, 0xADE0, 0x51A2, 0xADE1, 0x51CD, 0xADE2, 0x51CC, 0xADE3, 0x51C6, + 0xADE4, 0x51CB, 0xADE5, 0x5256, 0xADE6, 0x525C, 0xADE7, 0x5254, 0xADE8, 0x525B, 0xADE9, 0x525D, 0xADEA, 0x532A, 0xADEB, 0x537F, + 0xADEC, 0x539F, 0xADED, 0x539D, 0xADEE, 0x53DF, 0xADEF, 0x54E8, 0xADF0, 0x5510, 0xADF1, 0x5501, 0xADF2, 0x5537, 0xADF3, 0x54FC, + 0xADF4, 0x54E5, 0xADF5, 0x54F2, 0xADF6, 0x5506, 0xADF7, 0x54FA, 0xADF8, 0x5514, 0xADF9, 0x54E9, 0xADFA, 0x54ED, 0xADFB, 0x54E1, + 0xADFC, 0x5509, 0xADFD, 0x54EE, 0xADFE, 0x54EA, 0xAE40, 0x54E6, 0xAE41, 0x5527, 0xAE42, 0x5507, 0xAE43, 0x54FD, 0xAE44, 0x550F, + 0xAE45, 0x5703, 0xAE46, 0x5704, 0xAE47, 0x57C2, 0xAE48, 0x57D4, 0xAE49, 0x57CB, 0xAE4A, 0x57C3, 0xAE4B, 0x5809, 0xAE4C, 0x590F, + 0xAE4D, 0x5957, 0xAE4E, 0x5958, 0xAE4F, 0x595A, 0xAE50, 0x5A11, 0xAE51, 0x5A18, 0xAE52, 0x5A1C, 0xAE53, 0x5A1F, 0xAE54, 0x5A1B, + 0xAE55, 0x5A13, 0xAE56, 0x59EC, 0xAE57, 0x5A20, 0xAE58, 0x5A23, 0xAE59, 0x5A29, 0xAE5A, 0x5A25, 0xAE5B, 0x5A0C, 0xAE5C, 0x5A09, + 0xAE5D, 0x5B6B, 0xAE5E, 0x5C58, 0xAE5F, 0x5BB0, 0xAE60, 0x5BB3, 0xAE61, 0x5BB6, 0xAE62, 0x5BB4, 0xAE63, 0x5BAE, 0xAE64, 0x5BB5, + 0xAE65, 0x5BB9, 0xAE66, 0x5BB8, 0xAE67, 0x5C04, 0xAE68, 0x5C51, 0xAE69, 0x5C55, 0xAE6A, 0x5C50, 0xAE6B, 0x5CED, 0xAE6C, 0x5CFD, + 0xAE6D, 0x5CFB, 0xAE6E, 0x5CEA, 0xAE6F, 0x5CE8, 0xAE70, 0x5CF0, 0xAE71, 0x5CF6, 0xAE72, 0x5D01, 0xAE73, 0x5CF4, 0xAE74, 0x5DEE, + 0xAE75, 0x5E2D, 0xAE76, 0x5E2B, 0xAE77, 0x5EAB, 0xAE78, 0x5EAD, 0xAE79, 0x5EA7, 0xAE7A, 0x5F31, 0xAE7B, 0x5F92, 0xAE7C, 0x5F91, + 0xAE7D, 0x5F90, 0xAE7E, 0x6059, 0xAEA1, 0x6063, 0xAEA2, 0x6065, 0xAEA3, 0x6050, 0xAEA4, 0x6055, 0xAEA5, 0x606D, 0xAEA6, 0x6069, + 0xAEA7, 0x606F, 0xAEA8, 0x6084, 0xAEA9, 0x609F, 0xAEAA, 0x609A, 0xAEAB, 0x608D, 0xAEAC, 0x6094, 0xAEAD, 0x608C, 0xAEAE, 0x6085, + 0xAEAF, 0x6096, 0xAEB0, 0x6247, 0xAEB1, 0x62F3, 0xAEB2, 0x6308, 0xAEB3, 0x62FF, 0xAEB4, 0x634E, 0xAEB5, 0x633E, 0xAEB6, 0x632F, + 0xAEB7, 0x6355, 0xAEB8, 0x6342, 0xAEB9, 0x6346, 0xAEBA, 0x634F, 0xAEBB, 0x6349, 0xAEBC, 0x633A, 0xAEBD, 0x6350, 0xAEBE, 0x633D, + 0xAEBF, 0x632A, 0xAEC0, 0x632B, 0xAEC1, 0x6328, 0xAEC2, 0x634D, 0xAEC3, 0x634C, 0xAEC4, 0x6548, 0xAEC5, 0x6549, 0xAEC6, 0x6599, + 0xAEC7, 0x65C1, 0xAEC8, 0x65C5, 0xAEC9, 0x6642, 0xAECA, 0x6649, 0xAECB, 0x664F, 0xAECC, 0x6643, 0xAECD, 0x6652, 0xAECE, 0x664C, + 0xAECF, 0x6645, 0xAED0, 0x6641, 0xAED1, 0x66F8, 0xAED2, 0x6714, 0xAED3, 0x6715, 0xAED4, 0x6717, 0xAED5, 0x6821, 0xAED6, 0x6838, + 0xAED7, 0x6848, 0xAED8, 0x6846, 0xAED9, 0x6853, 0xAEDA, 0x6839, 0xAEDB, 0x6842, 0xAEDC, 0x6854, 0xAEDD, 0x6829, 0xAEDE, 0x68B3, + 0xAEDF, 0x6817, 0xAEE0, 0x684C, 0xAEE1, 0x6851, 0xAEE2, 0x683D, 0xAEE3, 0x67F4, 0xAEE4, 0x6850, 0xAEE5, 0x6840, 0xAEE6, 0x683C, + 0xAEE7, 0x6843, 0xAEE8, 0x682A, 0xAEE9, 0x6845, 0xAEEA, 0x6813, 0xAEEB, 0x6818, 0xAEEC, 0x6841, 0xAEED, 0x6B8A, 0xAEEE, 0x6B89, + 0xAEEF, 0x6BB7, 0xAEF0, 0x6C23, 0xAEF1, 0x6C27, 0xAEF2, 0x6C28, 0xAEF3, 0x6C26, 0xAEF4, 0x6C24, 0xAEF5, 0x6CF0, 0xAEF6, 0x6D6A, + 0xAEF7, 0x6D95, 0xAEF8, 0x6D88, 0xAEF9, 0x6D87, 0xAEFA, 0x6D66, 0xAEFB, 0x6D78, 0xAEFC, 0x6D77, 0xAEFD, 0x6D59, 0xAEFE, 0x6D93, + 0xAF40, 0x6D6C, 0xAF41, 0x6D89, 0xAF42, 0x6D6E, 0xAF43, 0x6D5A, 0xAF44, 0x6D74, 0xAF45, 0x6D69, 0xAF46, 0x6D8C, 0xAF47, 0x6D8A, + 0xAF48, 0x6D79, 0xAF49, 0x6D85, 0xAF4A, 0x6D65, 0xAF4B, 0x6D94, 0xAF4C, 0x70CA, 0xAF4D, 0x70D8, 0xAF4E, 0x70E4, 0xAF4F, 0x70D9, + 0xAF50, 0x70C8, 0xAF51, 0x70CF, 0xAF52, 0x7239, 0xAF53, 0x7279, 0xAF54, 0x72FC, 0xAF55, 0x72F9, 0xAF56, 0x72FD, 0xAF57, 0x72F8, + 0xAF58, 0x72F7, 0xAF59, 0x7386, 0xAF5A, 0x73ED, 0xAF5B, 0x7409, 0xAF5C, 0x73EE, 0xAF5D, 0x73E0, 0xAF5E, 0x73EA, 0xAF5F, 0x73DE, + 0xAF60, 0x7554, 0xAF61, 0x755D, 0xAF62, 0x755C, 0xAF63, 0x755A, 0xAF64, 0x7559, 0xAF65, 0x75BE, 0xAF66, 0x75C5, 0xAF67, 0x75C7, + 0xAF68, 0x75B2, 0xAF69, 0x75B3, 0xAF6A, 0x75BD, 0xAF6B, 0x75BC, 0xAF6C, 0x75B9, 0xAF6D, 0x75C2, 0xAF6E, 0x75B8, 0xAF6F, 0x768B, + 0xAF70, 0x76B0, 0xAF71, 0x76CA, 0xAF72, 0x76CD, 0xAF73, 0x76CE, 0xAF74, 0x7729, 0xAF75, 0x771F, 0xAF76, 0x7720, 0xAF77, 0x7728, + 0xAF78, 0x77E9, 0xAF79, 0x7830, 0xAF7A, 0x7827, 0xAF7B, 0x7838, 0xAF7C, 0x781D, 0xAF7D, 0x7834, 0xAF7E, 0x7837, 0xAFA1, 0x7825, + 0xAFA2, 0x782D, 0xAFA3, 0x7820, 0xAFA4, 0x781F, 0xAFA5, 0x7832, 0xAFA6, 0x7955, 0xAFA7, 0x7950, 0xAFA8, 0x7960, 0xAFA9, 0x795F, + 0xAFAA, 0x7956, 0xAFAB, 0x795E, 0xAFAC, 0x795D, 0xAFAD, 0x7957, 0xAFAE, 0x795A, 0xAFAF, 0x79E4, 0xAFB0, 0x79E3, 0xAFB1, 0x79E7, + 0xAFB2, 0x79DF, 0xAFB3, 0x79E6, 0xAFB4, 0x79E9, 0xAFB5, 0x79D8, 0xAFB6, 0x7A84, 0xAFB7, 0x7A88, 0xAFB8, 0x7AD9, 0xAFB9, 0x7B06, + 0xAFBA, 0x7B11, 0xAFBB, 0x7C89, 0xAFBC, 0x7D21, 0xAFBD, 0x7D17, 0xAFBE, 0x7D0B, 0xAFBF, 0x7D0A, 0xAFC0, 0x7D20, 0xAFC1, 0x7D22, + 0xAFC2, 0x7D14, 0xAFC3, 0x7D10, 0xAFC4, 0x7D15, 0xAFC5, 0x7D1A, 0xAFC6, 0x7D1C, 0xAFC7, 0x7D0D, 0xAFC8, 0x7D19, 0xAFC9, 0x7D1B, + 0xAFCA, 0x7F3A, 0xAFCB, 0x7F5F, 0xAFCC, 0x7F94, 0xAFCD, 0x7FC5, 0xAFCE, 0x7FC1, 0xAFCF, 0x8006, 0xAFD0, 0x8018, 0xAFD1, 0x8015, + 0xAFD2, 0x8019, 0xAFD3, 0x8017, 0xAFD4, 0x803D, 0xAFD5, 0x803F, 0xAFD6, 0x80F1, 0xAFD7, 0x8102, 0xAFD8, 0x80F0, 0xAFD9, 0x8105, + 0xAFDA, 0x80ED, 0xAFDB, 0x80F4, 0xAFDC, 0x8106, 0xAFDD, 0x80F8, 0xAFDE, 0x80F3, 0xAFDF, 0x8108, 0xAFE0, 0x80FD, 0xAFE1, 0x810A, + 0xAFE2, 0x80FC, 0xAFE3, 0x80EF, 0xAFE4, 0x81ED, 0xAFE5, 0x81EC, 0xAFE6, 0x8200, 0xAFE7, 0x8210, 0xAFE8, 0x822A, 0xAFE9, 0x822B, + 0xAFEA, 0x8228, 0xAFEB, 0x822C, 0xAFEC, 0x82BB, 0xAFED, 0x832B, 0xAFEE, 0x8352, 0xAFEF, 0x8354, 0xAFF0, 0x834A, 0xAFF1, 0x8338, + 0xAFF2, 0x8350, 0xAFF3, 0x8349, 0xAFF4, 0x8335, 0xAFF5, 0x8334, 0xAFF6, 0x834F, 0xAFF7, 0x8332, 0xAFF8, 0x8339, 0xAFF9, 0x8336, + 0xAFFA, 0x8317, 0xAFFB, 0x8340, 0xAFFC, 0x8331, 0xAFFD, 0x8328, 0xAFFE, 0x8343, 0xB040, 0x8654, 0xB041, 0x868A, 0xB042, 0x86AA, + 0xB043, 0x8693, 0xB044, 0x86A4, 0xB045, 0x86A9, 0xB046, 0x868C, 0xB047, 0x86A3, 0xB048, 0x869C, 0xB049, 0x8870, 0xB04A, 0x8877, + 0xB04B, 0x8881, 0xB04C, 0x8882, 0xB04D, 0x887D, 0xB04E, 0x8879, 0xB04F, 0x8A18, 0xB050, 0x8A10, 0xB051, 0x8A0E, 0xB052, 0x8A0C, + 0xB053, 0x8A15, 0xB054, 0x8A0A, 0xB055, 0x8A17, 0xB056, 0x8A13, 0xB057, 0x8A16, 0xB058, 0x8A0F, 0xB059, 0x8A11, 0xB05A, 0x8C48, + 0xB05B, 0x8C7A, 0xB05C, 0x8C79, 0xB05D, 0x8CA1, 0xB05E, 0x8CA2, 0xB05F, 0x8D77, 0xB060, 0x8EAC, 0xB061, 0x8ED2, 0xB062, 0x8ED4, + 0xB063, 0x8ECF, 0xB064, 0x8FB1, 0xB065, 0x9001, 0xB066, 0x9006, 0xB067, 0x8FF7, 0xB068, 0x9000, 0xB069, 0x8FFA, 0xB06A, 0x8FF4, + 0xB06B, 0x9003, 0xB06C, 0x8FFD, 0xB06D, 0x9005, 0xB06E, 0x8FF8, 0xB06F, 0x9095, 0xB070, 0x90E1, 0xB071, 0x90DD, 0xB072, 0x90E2, + 0xB073, 0x9152, 0xB074, 0x914D, 0xB075, 0x914C, 0xB076, 0x91D8, 0xB077, 0x91DD, 0xB078, 0x91D7, 0xB079, 0x91DC, 0xB07A, 0x91D9, + 0xB07B, 0x9583, 0xB07C, 0x9662, 0xB07D, 0x9663, 0xB07E, 0x9661, 0xB0A1, 0x965B, 0xB0A2, 0x965D, 0xB0A3, 0x9664, 0xB0A4, 0x9658, + 0xB0A5, 0x965E, 0xB0A6, 0x96BB, 0xB0A7, 0x98E2, 0xB0A8, 0x99AC, 0xB0A9, 0x9AA8, 0xB0AA, 0x9AD8, 0xB0AB, 0x9B25, 0xB0AC, 0x9B32, + 0xB0AD, 0x9B3C, 0xB0AE, 0x4E7E, 0xB0AF, 0x507A, 0xB0B0, 0x507D, 0xB0B1, 0x505C, 0xB0B2, 0x5047, 0xB0B3, 0x5043, 0xB0B4, 0x504C, + 0xB0B5, 0x505A, 0xB0B6, 0x5049, 0xB0B7, 0x5065, 0xB0B8, 0x5076, 0xB0B9, 0x504E, 0xB0BA, 0x5055, 0xB0BB, 0x5075, 0xB0BC, 0x5074, + 0xB0BD, 0x5077, 0xB0BE, 0x504F, 0xB0BF, 0x500F, 0xB0C0, 0x506F, 0xB0C1, 0x506D, 0xB0C2, 0x515C, 0xB0C3, 0x5195, 0xB0C4, 0x51F0, + 0xB0C5, 0x526A, 0xB0C6, 0x526F, 0xB0C7, 0x52D2, 0xB0C8, 0x52D9, 0xB0C9, 0x52D8, 0xB0CA, 0x52D5, 0xB0CB, 0x5310, 0xB0CC, 0x530F, + 0xB0CD, 0x5319, 0xB0CE, 0x533F, 0xB0CF, 0x5340, 0xB0D0, 0x533E, 0xB0D1, 0x53C3, 0xB0D2, 0x66FC, 0xB0D3, 0x5546, 0xB0D4, 0x556A, + 0xB0D5, 0x5566, 0xB0D6, 0x5544, 0xB0D7, 0x555E, 0xB0D8, 0x5561, 0xB0D9, 0x5543, 0xB0DA, 0x554A, 0xB0DB, 0x5531, 0xB0DC, 0x5556, + 0xB0DD, 0x554F, 0xB0DE, 0x5555, 0xB0DF, 0x552F, 0xB0E0, 0x5564, 0xB0E1, 0x5538, 0xB0E2, 0x552E, 0xB0E3, 0x555C, 0xB0E4, 0x552C, + 0xB0E5, 0x5563, 0xB0E6, 0x5533, 0xB0E7, 0x5541, 0xB0E8, 0x5557, 0xB0E9, 0x5708, 0xB0EA, 0x570B, 0xB0EB, 0x5709, 0xB0EC, 0x57DF, + 0xB0ED, 0x5805, 0xB0EE, 0x580A, 0xB0EF, 0x5806, 0xB0F0, 0x57E0, 0xB0F1, 0x57E4, 0xB0F2, 0x57FA, 0xB0F3, 0x5802, 0xB0F4, 0x5835, + 0xB0F5, 0x57F7, 0xB0F6, 0x57F9, 0xB0F7, 0x5920, 0xB0F8, 0x5962, 0xB0F9, 0x5A36, 0xB0FA, 0x5A41, 0xB0FB, 0x5A49, 0xB0FC, 0x5A66, + 0xB0FD, 0x5A6A, 0xB0FE, 0x5A40, 0xB140, 0x5A3C, 0xB141, 0x5A62, 0xB142, 0x5A5A, 0xB143, 0x5A46, 0xB144, 0x5A4A, 0xB145, 0x5B70, + 0xB146, 0x5BC7, 0xB147, 0x5BC5, 0xB148, 0x5BC4, 0xB149, 0x5BC2, 0xB14A, 0x5BBF, 0xB14B, 0x5BC6, 0xB14C, 0x5C09, 0xB14D, 0x5C08, + 0xB14E, 0x5C07, 0xB14F, 0x5C60, 0xB150, 0x5C5C, 0xB151, 0x5C5D, 0xB152, 0x5D07, 0xB153, 0x5D06, 0xB154, 0x5D0E, 0xB155, 0x5D1B, + 0xB156, 0x5D16, 0xB157, 0x5D22, 0xB158, 0x5D11, 0xB159, 0x5D29, 0xB15A, 0x5D14, 0xB15B, 0x5D19, 0xB15C, 0x5D24, 0xB15D, 0x5D27, + 0xB15E, 0x5D17, 0xB15F, 0x5DE2, 0xB160, 0x5E38, 0xB161, 0x5E36, 0xB162, 0x5E33, 0xB163, 0x5E37, 0xB164, 0x5EB7, 0xB165, 0x5EB8, + 0xB166, 0x5EB6, 0xB167, 0x5EB5, 0xB168, 0x5EBE, 0xB169, 0x5F35, 0xB16A, 0x5F37, 0xB16B, 0x5F57, 0xB16C, 0x5F6C, 0xB16D, 0x5F69, + 0xB16E, 0x5F6B, 0xB16F, 0x5F97, 0xB170, 0x5F99, 0xB171, 0x5F9E, 0xB172, 0x5F98, 0xB173, 0x5FA1, 0xB174, 0x5FA0, 0xB175, 0x5F9C, + 0xB176, 0x607F, 0xB177, 0x60A3, 0xB178, 0x6089, 0xB179, 0x60A0, 0xB17A, 0x60A8, 0xB17B, 0x60CB, 0xB17C, 0x60B4, 0xB17D, 0x60E6, + 0xB17E, 0x60BD, 0xB1A1, 0x60C5, 0xB1A2, 0x60BB, 0xB1A3, 0x60B5, 0xB1A4, 0x60DC, 0xB1A5, 0x60BC, 0xB1A6, 0x60D8, 0xB1A7, 0x60D5, + 0xB1A8, 0x60C6, 0xB1A9, 0x60DF, 0xB1AA, 0x60B8, 0xB1AB, 0x60DA, 0xB1AC, 0x60C7, 0xB1AD, 0x621A, 0xB1AE, 0x621B, 0xB1AF, 0x6248, + 0xB1B0, 0x63A0, 0xB1B1, 0x63A7, 0xB1B2, 0x6372, 0xB1B3, 0x6396, 0xB1B4, 0x63A2, 0xB1B5, 0x63A5, 0xB1B6, 0x6377, 0xB1B7, 0x6367, + 0xB1B8, 0x6398, 0xB1B9, 0x63AA, 0xB1BA, 0x6371, 0xB1BB, 0x63A9, 0xB1BC, 0x6389, 0xB1BD, 0x6383, 0xB1BE, 0x639B, 0xB1BF, 0x636B, + 0xB1C0, 0x63A8, 0xB1C1, 0x6384, 0xB1C2, 0x6388, 0xB1C3, 0x6399, 0xB1C4, 0x63A1, 0xB1C5, 0x63AC, 0xB1C6, 0x6392, 0xB1C7, 0x638F, + 0xB1C8, 0x6380, 0xB1C9, 0x637B, 0xB1CA, 0x6369, 0xB1CB, 0x6368, 0xB1CC, 0x637A, 0xB1CD, 0x655D, 0xB1CE, 0x6556, 0xB1CF, 0x6551, + 0xB1D0, 0x6559, 0xB1D1, 0x6557, 0xB1D2, 0x555F, 0xB1D3, 0x654F, 0xB1D4, 0x6558, 0xB1D5, 0x6555, 0xB1D6, 0x6554, 0xB1D7, 0x659C, + 0xB1D8, 0x659B, 0xB1D9, 0x65AC, 0xB1DA, 0x65CF, 0xB1DB, 0x65CB, 0xB1DC, 0x65CC, 0xB1DD, 0x65CE, 0xB1DE, 0x665D, 0xB1DF, 0x665A, + 0xB1E0, 0x6664, 0xB1E1, 0x6668, 0xB1E2, 0x6666, 0xB1E3, 0x665E, 0xB1E4, 0x66F9, 0xB1E5, 0x52D7, 0xB1E6, 0x671B, 0xB1E7, 0x6881, + 0xB1E8, 0x68AF, 0xB1E9, 0x68A2, 0xB1EA, 0x6893, 0xB1EB, 0x68B5, 0xB1EC, 0x687F, 0xB1ED, 0x6876, 0xB1EE, 0x68B1, 0xB1EF, 0x68A7, + 0xB1F0, 0x6897, 0xB1F1, 0x68B0, 0xB1F2, 0x6883, 0xB1F3, 0x68C4, 0xB1F4, 0x68AD, 0xB1F5, 0x6886, 0xB1F6, 0x6885, 0xB1F7, 0x6894, + 0xB1F8, 0x689D, 0xB1F9, 0x68A8, 0xB1FA, 0x689F, 0xB1FB, 0x68A1, 0xB1FC, 0x6882, 0xB1FD, 0x6B32, 0xB1FE, 0x6BBA, 0xB240, 0x6BEB, + 0xB241, 0x6BEC, 0xB242, 0x6C2B, 0xB243, 0x6D8E, 0xB244, 0x6DBC, 0xB245, 0x6DF3, 0xB246, 0x6DD9, 0xB247, 0x6DB2, 0xB248, 0x6DE1, + 0xB249, 0x6DCC, 0xB24A, 0x6DE4, 0xB24B, 0x6DFB, 0xB24C, 0x6DFA, 0xB24D, 0x6E05, 0xB24E, 0x6DC7, 0xB24F, 0x6DCB, 0xB250, 0x6DAF, + 0xB251, 0x6DD1, 0xB252, 0x6DAE, 0xB253, 0x6DDE, 0xB254, 0x6DF9, 0xB255, 0x6DB8, 0xB256, 0x6DF7, 0xB257, 0x6DF5, 0xB258, 0x6DC5, + 0xB259, 0x6DD2, 0xB25A, 0x6E1A, 0xB25B, 0x6DB5, 0xB25C, 0x6DDA, 0xB25D, 0x6DEB, 0xB25E, 0x6DD8, 0xB25F, 0x6DEA, 0xB260, 0x6DF1, + 0xB261, 0x6DEE, 0xB262, 0x6DE8, 0xB263, 0x6DC6, 0xB264, 0x6DC4, 0xB265, 0x6DAA, 0xB266, 0x6DEC, 0xB267, 0x6DBF, 0xB268, 0x6DE6, + 0xB269, 0x70F9, 0xB26A, 0x7109, 0xB26B, 0x710A, 0xB26C, 0x70FD, 0xB26D, 0x70EF, 0xB26E, 0x723D, 0xB26F, 0x727D, 0xB270, 0x7281, + 0xB271, 0x731C, 0xB272, 0x731B, 0xB273, 0x7316, 0xB274, 0x7313, 0xB275, 0x7319, 0xB276, 0x7387, 0xB277, 0x7405, 0xB278, 0x740A, + 0xB279, 0x7403, 0xB27A, 0x7406, 0xB27B, 0x73FE, 0xB27C, 0x740D, 0xB27D, 0x74E0, 0xB27E, 0x74F6, 0xB2A1, 0x74F7, 0xB2A2, 0x751C, + 0xB2A3, 0x7522, 0xB2A4, 0x7565, 0xB2A5, 0x7566, 0xB2A6, 0x7562, 0xB2A7, 0x7570, 0xB2A8, 0x758F, 0xB2A9, 0x75D4, 0xB2AA, 0x75D5, + 0xB2AB, 0x75B5, 0xB2AC, 0x75CA, 0xB2AD, 0x75CD, 0xB2AE, 0x768E, 0xB2AF, 0x76D4, 0xB2B0, 0x76D2, 0xB2B1, 0x76DB, 0xB2B2, 0x7737, + 0xB2B3, 0x773E, 0xB2B4, 0x773C, 0xB2B5, 0x7736, 0xB2B6, 0x7738, 0xB2B7, 0x773A, 0xB2B8, 0x786B, 0xB2B9, 0x7843, 0xB2BA, 0x784E, + 0xB2BB, 0x7965, 0xB2BC, 0x7968, 0xB2BD, 0x796D, 0xB2BE, 0x79FB, 0xB2BF, 0x7A92, 0xB2C0, 0x7A95, 0xB2C1, 0x7B20, 0xB2C2, 0x7B28, + 0xB2C3, 0x7B1B, 0xB2C4, 0x7B2C, 0xB2C5, 0x7B26, 0xB2C6, 0x7B19, 0xB2C7, 0x7B1E, 0xB2C8, 0x7B2E, 0xB2C9, 0x7C92, 0xB2CA, 0x7C97, + 0xB2CB, 0x7C95, 0xB2CC, 0x7D46, 0xB2CD, 0x7D43, 0xB2CE, 0x7D71, 0xB2CF, 0x7D2E, 0xB2D0, 0x7D39, 0xB2D1, 0x7D3C, 0xB2D2, 0x7D40, + 0xB2D3, 0x7D30, 0xB2D4, 0x7D33, 0xB2D5, 0x7D44, 0xB2D6, 0x7D2F, 0xB2D7, 0x7D42, 0xB2D8, 0x7D32, 0xB2D9, 0x7D31, 0xB2DA, 0x7F3D, + 0xB2DB, 0x7F9E, 0xB2DC, 0x7F9A, 0xB2DD, 0x7FCC, 0xB2DE, 0x7FCE, 0xB2DF, 0x7FD2, 0xB2E0, 0x801C, 0xB2E1, 0x804A, 0xB2E2, 0x8046, + 0xB2E3, 0x812F, 0xB2E4, 0x8116, 0xB2E5, 0x8123, 0xB2E6, 0x812B, 0xB2E7, 0x8129, 0xB2E8, 0x8130, 0xB2E9, 0x8124, 0xB2EA, 0x8202, + 0xB2EB, 0x8235, 0xB2EC, 0x8237, 0xB2ED, 0x8236, 0xB2EE, 0x8239, 0xB2EF, 0x838E, 0xB2F0, 0x839E, 0xB2F1, 0x8398, 0xB2F2, 0x8378, + 0xB2F3, 0x83A2, 0xB2F4, 0x8396, 0xB2F5, 0x83BD, 0xB2F6, 0x83AB, 0xB2F7, 0x8392, 0xB2F8, 0x838A, 0xB2F9, 0x8393, 0xB2FA, 0x8389, + 0xB2FB, 0x83A0, 0xB2FC, 0x8377, 0xB2FD, 0x837B, 0xB2FE, 0x837C, 0xB340, 0x8386, 0xB341, 0x83A7, 0xB342, 0x8655, 0xB343, 0x5F6A, + 0xB344, 0x86C7, 0xB345, 0x86C0, 0xB346, 0x86B6, 0xB347, 0x86C4, 0xB348, 0x86B5, 0xB349, 0x86C6, 0xB34A, 0x86CB, 0xB34B, 0x86B1, + 0xB34C, 0x86AF, 0xB34D, 0x86C9, 0xB34E, 0x8853, 0xB34F, 0x889E, 0xB350, 0x8888, 0xB351, 0x88AB, 0xB352, 0x8892, 0xB353, 0x8896, + 0xB354, 0x888D, 0xB355, 0x888B, 0xB356, 0x8993, 0xB357, 0x898F, 0xB358, 0x8A2A, 0xB359, 0x8A1D, 0xB35A, 0x8A23, 0xB35B, 0x8A25, + 0xB35C, 0x8A31, 0xB35D, 0x8A2D, 0xB35E, 0x8A1F, 0xB35F, 0x8A1B, 0xB360, 0x8A22, 0xB361, 0x8C49, 0xB362, 0x8C5A, 0xB363, 0x8CA9, + 0xB364, 0x8CAC, 0xB365, 0x8CAB, 0xB366, 0x8CA8, 0xB367, 0x8CAA, 0xB368, 0x8CA7, 0xB369, 0x8D67, 0xB36A, 0x8D66, 0xB36B, 0x8DBE, + 0xB36C, 0x8DBA, 0xB36D, 0x8EDB, 0xB36E, 0x8EDF, 0xB36F, 0x9019, 0xB370, 0x900D, 0xB371, 0x901A, 0xB372, 0x9017, 0xB373, 0x9023, + 0xB374, 0x901F, 0xB375, 0x901D, 0xB376, 0x9010, 0xB377, 0x9015, 0xB378, 0x901E, 0xB379, 0x9020, 0xB37A, 0x900F, 0xB37B, 0x9022, + 0xB37C, 0x9016, 0xB37D, 0x901B, 0xB37E, 0x9014, 0xB3A1, 0x90E8, 0xB3A2, 0x90ED, 0xB3A3, 0x90FD, 0xB3A4, 0x9157, 0xB3A5, 0x91CE, + 0xB3A6, 0x91F5, 0xB3A7, 0x91E6, 0xB3A8, 0x91E3, 0xB3A9, 0x91E7, 0xB3AA, 0x91ED, 0xB3AB, 0x91E9, 0xB3AC, 0x9589, 0xB3AD, 0x966A, + 0xB3AE, 0x9675, 0xB3AF, 0x9673, 0xB3B0, 0x9678, 0xB3B1, 0x9670, 0xB3B2, 0x9674, 0xB3B3, 0x9676, 0xB3B4, 0x9677, 0xB3B5, 0x966C, + 0xB3B6, 0x96C0, 0xB3B7, 0x96EA, 0xB3B8, 0x96E9, 0xB3B9, 0x7AE0, 0xB3BA, 0x7ADF, 0xB3BB, 0x9802, 0xB3BC, 0x9803, 0xB3BD, 0x9B5A, + 0xB3BE, 0x9CE5, 0xB3BF, 0x9E75, 0xB3C0, 0x9E7F, 0xB3C1, 0x9EA5, 0xB3C2, 0x9EBB, 0xB3C3, 0x50A2, 0xB3C4, 0x508D, 0xB3C5, 0x5085, + 0xB3C6, 0x5099, 0xB3C7, 0x5091, 0xB3C8, 0x5080, 0xB3C9, 0x5096, 0xB3CA, 0x5098, 0xB3CB, 0x509A, 0xB3CC, 0x6700, 0xB3CD, 0x51F1, + 0xB3CE, 0x5272, 0xB3CF, 0x5274, 0xB3D0, 0x5275, 0xB3D1, 0x5269, 0xB3D2, 0x52DE, 0xB3D3, 0x52DD, 0xB3D4, 0x52DB, 0xB3D5, 0x535A, + 0xB3D6, 0x53A5, 0xB3D7, 0x557B, 0xB3D8, 0x5580, 0xB3D9, 0x55A7, 0xB3DA, 0x557C, 0xB3DB, 0x558A, 0xB3DC, 0x559D, 0xB3DD, 0x5598, + 0xB3DE, 0x5582, 0xB3DF, 0x559C, 0xB3E0, 0x55AA, 0xB3E1, 0x5594, 0xB3E2, 0x5587, 0xB3E3, 0x558B, 0xB3E4, 0x5583, 0xB3E5, 0x55B3, + 0xB3E6, 0x55AE, 0xB3E7, 0x559F, 0xB3E8, 0x553E, 0xB3E9, 0x55B2, 0xB3EA, 0x559A, 0xB3EB, 0x55BB, 0xB3EC, 0x55AC, 0xB3ED, 0x55B1, + 0xB3EE, 0x557E, 0xB3EF, 0x5589, 0xB3F0, 0x55AB, 0xB3F1, 0x5599, 0xB3F2, 0x570D, 0xB3F3, 0x582F, 0xB3F4, 0x582A, 0xB3F5, 0x5834, + 0xB3F6, 0x5824, 0xB3F7, 0x5830, 0xB3F8, 0x5831, 0xB3F9, 0x5821, 0xB3FA, 0x581D, 0xB3FB, 0x5820, 0xB3FC, 0x58F9, 0xB3FD, 0x58FA, + 0xB3FE, 0x5960, 0xB440, 0x5A77, 0xB441, 0x5A9A, 0xB442, 0x5A7F, 0xB443, 0x5A92, 0xB444, 0x5A9B, 0xB445, 0x5AA7, 0xB446, 0x5B73, + 0xB447, 0x5B71, 0xB448, 0x5BD2, 0xB449, 0x5BCC, 0xB44A, 0x5BD3, 0xB44B, 0x5BD0, 0xB44C, 0x5C0A, 0xB44D, 0x5C0B, 0xB44E, 0x5C31, + 0xB44F, 0x5D4C, 0xB450, 0x5D50, 0xB451, 0x5D34, 0xB452, 0x5D47, 0xB453, 0x5DFD, 0xB454, 0x5E45, 0xB455, 0x5E3D, 0xB456, 0x5E40, + 0xB457, 0x5E43, 0xB458, 0x5E7E, 0xB459, 0x5ECA, 0xB45A, 0x5EC1, 0xB45B, 0x5EC2, 0xB45C, 0x5EC4, 0xB45D, 0x5F3C, 0xB45E, 0x5F6D, + 0xB45F, 0x5FA9, 0xB460, 0x5FAA, 0xB461, 0x5FA8, 0xB462, 0x60D1, 0xB463, 0x60E1, 0xB464, 0x60B2, 0xB465, 0x60B6, 0xB466, 0x60E0, + 0xB467, 0x611C, 0xB468, 0x6123, 0xB469, 0x60FA, 0xB46A, 0x6115, 0xB46B, 0x60F0, 0xB46C, 0x60FB, 0xB46D, 0x60F4, 0xB46E, 0x6168, + 0xB46F, 0x60F1, 0xB470, 0x610E, 0xB471, 0x60F6, 0xB472, 0x6109, 0xB473, 0x6100, 0xB474, 0x6112, 0xB475, 0x621F, 0xB476, 0x6249, + 0xB477, 0x63A3, 0xB478, 0x638C, 0xB479, 0x63CF, 0xB47A, 0x63C0, 0xB47B, 0x63E9, 0xB47C, 0x63C9, 0xB47D, 0x63C6, 0xB47E, 0x63CD, + 0xB4A1, 0x63D2, 0xB4A2, 0x63E3, 0xB4A3, 0x63D0, 0xB4A4, 0x63E1, 0xB4A5, 0x63D6, 0xB4A6, 0x63ED, 0xB4A7, 0x63EE, 0xB4A8, 0x6376, + 0xB4A9, 0x63F4, 0xB4AA, 0x63EA, 0xB4AB, 0x63DB, 0xB4AC, 0x6452, 0xB4AD, 0x63DA, 0xB4AE, 0x63F9, 0xB4AF, 0x655E, 0xB4B0, 0x6566, + 0xB4B1, 0x6562, 0xB4B2, 0x6563, 0xB4B3, 0x6591, 0xB4B4, 0x6590, 0xB4B5, 0x65AF, 0xB4B6, 0x666E, 0xB4B7, 0x6670, 0xB4B8, 0x6674, + 0xB4B9, 0x6676, 0xB4BA, 0x666F, 0xB4BB, 0x6691, 0xB4BC, 0x667A, 0xB4BD, 0x667E, 0xB4BE, 0x6677, 0xB4BF, 0x66FE, 0xB4C0, 0x66FF, + 0xB4C1, 0x671F, 0xB4C2, 0x671D, 0xB4C3, 0x68FA, 0xB4C4, 0x68D5, 0xB4C5, 0x68E0, 0xB4C6, 0x68D8, 0xB4C7, 0x68D7, 0xB4C8, 0x6905, + 0xB4C9, 0x68DF, 0xB4CA, 0x68F5, 0xB4CB, 0x68EE, 0xB4CC, 0x68E7, 0xB4CD, 0x68F9, 0xB4CE, 0x68D2, 0xB4CF, 0x68F2, 0xB4D0, 0x68E3, + 0xB4D1, 0x68CB, 0xB4D2, 0x68CD, 0xB4D3, 0x690D, 0xB4D4, 0x6912, 0xB4D5, 0x690E, 0xB4D6, 0x68C9, 0xB4D7, 0x68DA, 0xB4D8, 0x696E, + 0xB4D9, 0x68FB, 0xB4DA, 0x6B3E, 0xB4DB, 0x6B3A, 0xB4DC, 0x6B3D, 0xB4DD, 0x6B98, 0xB4DE, 0x6B96, 0xB4DF, 0x6BBC, 0xB4E0, 0x6BEF, + 0xB4E1, 0x6C2E, 0xB4E2, 0x6C2F, 0xB4E3, 0x6C2C, 0xB4E4, 0x6E2F, 0xB4E5, 0x6E38, 0xB4E6, 0x6E54, 0xB4E7, 0x6E21, 0xB4E8, 0x6E32, + 0xB4E9, 0x6E67, 0xB4EA, 0x6E4A, 0xB4EB, 0x6E20, 0xB4EC, 0x6E25, 0xB4ED, 0x6E23, 0xB4EE, 0x6E1B, 0xB4EF, 0x6E5B, 0xB4F0, 0x6E58, + 0xB4F1, 0x6E24, 0xB4F2, 0x6E56, 0xB4F3, 0x6E6E, 0xB4F4, 0x6E2D, 0xB4F5, 0x6E26, 0xB4F6, 0x6E6F, 0xB4F7, 0x6E34, 0xB4F8, 0x6E4D, + 0xB4F9, 0x6E3A, 0xB4FA, 0x6E2C, 0xB4FB, 0x6E43, 0xB4FC, 0x6E1D, 0xB4FD, 0x6E3E, 0xB4FE, 0x6ECB, 0xB540, 0x6E89, 0xB541, 0x6E19, + 0xB542, 0x6E4E, 0xB543, 0x6E63, 0xB544, 0x6E44, 0xB545, 0x6E72, 0xB546, 0x6E69, 0xB547, 0x6E5F, 0xB548, 0x7119, 0xB549, 0x711A, + 0xB54A, 0x7126, 0xB54B, 0x7130, 0xB54C, 0x7121, 0xB54D, 0x7136, 0xB54E, 0x716E, 0xB54F, 0x711C, 0xB550, 0x724C, 0xB551, 0x7284, + 0xB552, 0x7280, 0xB553, 0x7336, 0xB554, 0x7325, 0xB555, 0x7334, 0xB556, 0x7329, 0xB557, 0x743A, 0xB558, 0x742A, 0xB559, 0x7433, + 0xB55A, 0x7422, 0xB55B, 0x7425, 0xB55C, 0x7435, 0xB55D, 0x7436, 0xB55E, 0x7434, 0xB55F, 0x742F, 0xB560, 0x741B, 0xB561, 0x7426, + 0xB562, 0x7428, 0xB563, 0x7525, 0xB564, 0x7526, 0xB565, 0x756B, 0xB566, 0x756A, 0xB567, 0x75E2, 0xB568, 0x75DB, 0xB569, 0x75E3, + 0xB56A, 0x75D9, 0xB56B, 0x75D8, 0xB56C, 0x75DE, 0xB56D, 0x75E0, 0xB56E, 0x767B, 0xB56F, 0x767C, 0xB570, 0x7696, 0xB571, 0x7693, + 0xB572, 0x76B4, 0xB573, 0x76DC, 0xB574, 0x774F, 0xB575, 0x77ED, 0xB576, 0x785D, 0xB577, 0x786C, 0xB578, 0x786F, 0xB579, 0x7A0D, + 0xB57A, 0x7A08, 0xB57B, 0x7A0B, 0xB57C, 0x7A05, 0xB57D, 0x7A00, 0xB57E, 0x7A98, 0xB5A1, 0x7A97, 0xB5A2, 0x7A96, 0xB5A3, 0x7AE5, + 0xB5A4, 0x7AE3, 0xB5A5, 0x7B49, 0xB5A6, 0x7B56, 0xB5A7, 0x7B46, 0xB5A8, 0x7B50, 0xB5A9, 0x7B52, 0xB5AA, 0x7B54, 0xB5AB, 0x7B4D, + 0xB5AC, 0x7B4B, 0xB5AD, 0x7B4F, 0xB5AE, 0x7B51, 0xB5AF, 0x7C9F, 0xB5B0, 0x7CA5, 0xB5B1, 0x7D5E, 0xB5B2, 0x7D50, 0xB5B3, 0x7D68, + 0xB5B4, 0x7D55, 0xB5B5, 0x7D2B, 0xB5B6, 0x7D6E, 0xB5B7, 0x7D72, 0xB5B8, 0x7D61, 0xB5B9, 0x7D66, 0xB5BA, 0x7D62, 0xB5BB, 0x7D70, + 0xB5BC, 0x7D73, 0xB5BD, 0x5584, 0xB5BE, 0x7FD4, 0xB5BF, 0x7FD5, 0xB5C0, 0x800B, 0xB5C1, 0x8052, 0xB5C2, 0x8085, 0xB5C3, 0x8155, + 0xB5C4, 0x8154, 0xB5C5, 0x814B, 0xB5C6, 0x8151, 0xB5C7, 0x814E, 0xB5C8, 0x8139, 0xB5C9, 0x8146, 0xB5CA, 0x813E, 0xB5CB, 0x814C, + 0xB5CC, 0x8153, 0xB5CD, 0x8174, 0xB5CE, 0x8212, 0xB5CF, 0x821C, 0xB5D0, 0x83E9, 0xB5D1, 0x8403, 0xB5D2, 0x83F8, 0xB5D3, 0x840D, + 0xB5D4, 0x83E0, 0xB5D5, 0x83C5, 0xB5D6, 0x840B, 0xB5D7, 0x83C1, 0xB5D8, 0x83EF, 0xB5D9, 0x83F1, 0xB5DA, 0x83F4, 0xB5DB, 0x8457, + 0xB5DC, 0x840A, 0xB5DD, 0x83F0, 0xB5DE, 0x840C, 0xB5DF, 0x83CC, 0xB5E0, 0x83FD, 0xB5E1, 0x83F2, 0xB5E2, 0x83CA, 0xB5E3, 0x8438, + 0xB5E4, 0x840E, 0xB5E5, 0x8404, 0xB5E6, 0x83DC, 0xB5E7, 0x8407, 0xB5E8, 0x83D4, 0xB5E9, 0x83DF, 0xB5EA, 0x865B, 0xB5EB, 0x86DF, + 0xB5EC, 0x86D9, 0xB5ED, 0x86ED, 0xB5EE, 0x86D4, 0xB5EF, 0x86DB, 0xB5F0, 0x86E4, 0xB5F1, 0x86D0, 0xB5F2, 0x86DE, 0xB5F3, 0x8857, + 0xB5F4, 0x88C1, 0xB5F5, 0x88C2, 0xB5F6, 0x88B1, 0xB5F7, 0x8983, 0xB5F8, 0x8996, 0xB5F9, 0x8A3B, 0xB5FA, 0x8A60, 0xB5FB, 0x8A55, + 0xB5FC, 0x8A5E, 0xB5FD, 0x8A3C, 0xB5FE, 0x8A41, 0xB640, 0x8A54, 0xB641, 0x8A5B, 0xB642, 0x8A50, 0xB643, 0x8A46, 0xB644, 0x8A34, + 0xB645, 0x8A3A, 0xB646, 0x8A36, 0xB647, 0x8A56, 0xB648, 0x8C61, 0xB649, 0x8C82, 0xB64A, 0x8CAF, 0xB64B, 0x8CBC, 0xB64C, 0x8CB3, + 0xB64D, 0x8CBD, 0xB64E, 0x8CC1, 0xB64F, 0x8CBB, 0xB650, 0x8CC0, 0xB651, 0x8CB4, 0xB652, 0x8CB7, 0xB653, 0x8CB6, 0xB654, 0x8CBF, + 0xB655, 0x8CB8, 0xB656, 0x8D8A, 0xB657, 0x8D85, 0xB658, 0x8D81, 0xB659, 0x8DCE, 0xB65A, 0x8DDD, 0xB65B, 0x8DCB, 0xB65C, 0x8DDA, + 0xB65D, 0x8DD1, 0xB65E, 0x8DCC, 0xB65F, 0x8DDB, 0xB660, 0x8DC6, 0xB661, 0x8EFB, 0xB662, 0x8EF8, 0xB663, 0x8EFC, 0xB664, 0x8F9C, + 0xB665, 0x902E, 0xB666, 0x9035, 0xB667, 0x9031, 0xB668, 0x9038, 0xB669, 0x9032, 0xB66A, 0x9036, 0xB66B, 0x9102, 0xB66C, 0x90F5, + 0xB66D, 0x9109, 0xB66E, 0x90FE, 0xB66F, 0x9163, 0xB670, 0x9165, 0xB671, 0x91CF, 0xB672, 0x9214, 0xB673, 0x9215, 0xB674, 0x9223, + 0xB675, 0x9209, 0xB676, 0x921E, 0xB677, 0x920D, 0xB678, 0x9210, 0xB679, 0x9207, 0xB67A, 0x9211, 0xB67B, 0x9594, 0xB67C, 0x958F, + 0xB67D, 0x958B, 0xB67E, 0x9591, 0xB6A1, 0x9593, 0xB6A2, 0x9592, 0xB6A3, 0x958E, 0xB6A4, 0x968A, 0xB6A5, 0x968E, 0xB6A6, 0x968B, + 0xB6A7, 0x967D, 0xB6A8, 0x9685, 0xB6A9, 0x9686, 0xB6AA, 0x968D, 0xB6AB, 0x9672, 0xB6AC, 0x9684, 0xB6AD, 0x96C1, 0xB6AE, 0x96C5, + 0xB6AF, 0x96C4, 0xB6B0, 0x96C6, 0xB6B1, 0x96C7, 0xB6B2, 0x96EF, 0xB6B3, 0x96F2, 0xB6B4, 0x97CC, 0xB6B5, 0x9805, 0xB6B6, 0x9806, + 0xB6B7, 0x9808, 0xB6B8, 0x98E7, 0xB6B9, 0x98EA, 0xB6BA, 0x98EF, 0xB6BB, 0x98E9, 0xB6BC, 0x98F2, 0xB6BD, 0x98ED, 0xB6BE, 0x99AE, + 0xB6BF, 0x99AD, 0xB6C0, 0x9EC3, 0xB6C1, 0x9ECD, 0xB6C2, 0x9ED1, 0xB6C3, 0x4E82, 0xB6C4, 0x50AD, 0xB6C5, 0x50B5, 0xB6C6, 0x50B2, + 0xB6C7, 0x50B3, 0xB6C8, 0x50C5, 0xB6C9, 0x50BE, 0xB6CA, 0x50AC, 0xB6CB, 0x50B7, 0xB6CC, 0x50BB, 0xB6CD, 0x50AF, 0xB6CE, 0x50C7, + 0xB6CF, 0x527F, 0xB6D0, 0x5277, 0xB6D1, 0x527D, 0xB6D2, 0x52DF, 0xB6D3, 0x52E6, 0xB6D4, 0x52E4, 0xB6D5, 0x52E2, 0xB6D6, 0x52E3, + 0xB6D7, 0x532F, 0xB6D8, 0x55DF, 0xB6D9, 0x55E8, 0xB6DA, 0x55D3, 0xB6DB, 0x55E6, 0xB6DC, 0x55CE, 0xB6DD, 0x55DC, 0xB6DE, 0x55C7, + 0xB6DF, 0x55D1, 0xB6E0, 0x55E3, 0xB6E1, 0x55E4, 0xB6E2, 0x55EF, 0xB6E3, 0x55DA, 0xB6E4, 0x55E1, 0xB6E5, 0x55C5, 0xB6E6, 0x55C6, + 0xB6E7, 0x55E5, 0xB6E8, 0x55C9, 0xB6E9, 0x5712, 0xB6EA, 0x5713, 0xB6EB, 0x585E, 0xB6EC, 0x5851, 0xB6ED, 0x5858, 0xB6EE, 0x5857, + 0xB6EF, 0x585A, 0xB6F0, 0x5854, 0xB6F1, 0x586B, 0xB6F2, 0x584C, 0xB6F3, 0x586D, 0xB6F4, 0x584A, 0xB6F5, 0x5862, 0xB6F6, 0x5852, + 0xB6F7, 0x584B, 0xB6F8, 0x5967, 0xB6F9, 0x5AC1, 0xB6FA, 0x5AC9, 0xB6FB, 0x5ACC, 0xB6FC, 0x5ABE, 0xB6FD, 0x5ABD, 0xB6FE, 0x5ABC, + 0xB740, 0x5AB3, 0xB741, 0x5AC2, 0xB742, 0x5AB2, 0xB743, 0x5D69, 0xB744, 0x5D6F, 0xB745, 0x5E4C, 0xB746, 0x5E79, 0xB747, 0x5EC9, + 0xB748, 0x5EC8, 0xB749, 0x5F12, 0xB74A, 0x5F59, 0xB74B, 0x5FAC, 0xB74C, 0x5FAE, 0xB74D, 0x611A, 0xB74E, 0x610F, 0xB74F, 0x6148, + 0xB750, 0x611F, 0xB751, 0x60F3, 0xB752, 0x611B, 0xB753, 0x60F9, 0xB754, 0x6101, 0xB755, 0x6108, 0xB756, 0x614E, 0xB757, 0x614C, + 0xB758, 0x6144, 0xB759, 0x614D, 0xB75A, 0x613E, 0xB75B, 0x6134, 0xB75C, 0x6127, 0xB75D, 0x610D, 0xB75E, 0x6106, 0xB75F, 0x6137, + 0xB760, 0x6221, 0xB761, 0x6222, 0xB762, 0x6413, 0xB763, 0x643E, 0xB764, 0x641E, 0xB765, 0x642A, 0xB766, 0x642D, 0xB767, 0x643D, + 0xB768, 0x642C, 0xB769, 0x640F, 0xB76A, 0x641C, 0xB76B, 0x6414, 0xB76C, 0x640D, 0xB76D, 0x6436, 0xB76E, 0x6416, 0xB76F, 0x6417, + 0xB770, 0x6406, 0xB771, 0x656C, 0xB772, 0x659F, 0xB773, 0x65B0, 0xB774, 0x6697, 0xB775, 0x6689, 0xB776, 0x6687, 0xB777, 0x6688, + 0xB778, 0x6696, 0xB779, 0x6684, 0xB77A, 0x6698, 0xB77B, 0x668D, 0xB77C, 0x6703, 0xB77D, 0x6994, 0xB77E, 0x696D, 0xB7A1, 0x695A, + 0xB7A2, 0x6977, 0xB7A3, 0x6960, 0xB7A4, 0x6954, 0xB7A5, 0x6975, 0xB7A6, 0x6930, 0xB7A7, 0x6982, 0xB7A8, 0x694A, 0xB7A9, 0x6968, + 0xB7AA, 0x696B, 0xB7AB, 0x695E, 0xB7AC, 0x6953, 0xB7AD, 0x6979, 0xB7AE, 0x6986, 0xB7AF, 0x695D, 0xB7B0, 0x6963, 0xB7B1, 0x695B, + 0xB7B2, 0x6B47, 0xB7B3, 0x6B72, 0xB7B4, 0x6BC0, 0xB7B5, 0x6BBF, 0xB7B6, 0x6BD3, 0xB7B7, 0x6BFD, 0xB7B8, 0x6EA2, 0xB7B9, 0x6EAF, + 0xB7BA, 0x6ED3, 0xB7BB, 0x6EB6, 0xB7BC, 0x6EC2, 0xB7BD, 0x6E90, 0xB7BE, 0x6E9D, 0xB7BF, 0x6EC7, 0xB7C0, 0x6EC5, 0xB7C1, 0x6EA5, + 0xB7C2, 0x6E98, 0xB7C3, 0x6EBC, 0xB7C4, 0x6EBA, 0xB7C5, 0x6EAB, 0xB7C6, 0x6ED1, 0xB7C7, 0x6E96, 0xB7C8, 0x6E9C, 0xB7C9, 0x6EC4, + 0xB7CA, 0x6ED4, 0xB7CB, 0x6EAA, 0xB7CC, 0x6EA7, 0xB7CD, 0x6EB4, 0xB7CE, 0x714E, 0xB7CF, 0x7159, 0xB7D0, 0x7169, 0xB7D1, 0x7164, + 0xB7D2, 0x7149, 0xB7D3, 0x7167, 0xB7D4, 0x715C, 0xB7D5, 0x716C, 0xB7D6, 0x7166, 0xB7D7, 0x714C, 0xB7D8, 0x7165, 0xB7D9, 0x715E, + 0xB7DA, 0x7146, 0xB7DB, 0x7168, 0xB7DC, 0x7156, 0xB7DD, 0x723A, 0xB7DE, 0x7252, 0xB7DF, 0x7337, 0xB7E0, 0x7345, 0xB7E1, 0x733F, + 0xB7E2, 0x733E, 0xB7E3, 0x746F, 0xB7E4, 0x745A, 0xB7E5, 0x7455, 0xB7E6, 0x745F, 0xB7E7, 0x745E, 0xB7E8, 0x7441, 0xB7E9, 0x743F, + 0xB7EA, 0x7459, 0xB7EB, 0x745B, 0xB7EC, 0x745C, 0xB7ED, 0x7576, 0xB7EE, 0x7578, 0xB7EF, 0x7600, 0xB7F0, 0x75F0, 0xB7F1, 0x7601, + 0xB7F2, 0x75F2, 0xB7F3, 0x75F1, 0xB7F4, 0x75FA, 0xB7F5, 0x75FF, 0xB7F6, 0x75F4, 0xB7F7, 0x75F3, 0xB7F8, 0x76DE, 0xB7F9, 0x76DF, + 0xB7FA, 0x775B, 0xB7FB, 0x776B, 0xB7FC, 0x7766, 0xB7FD, 0x775E, 0xB7FE, 0x7763, 0xB840, 0x7779, 0xB841, 0x776A, 0xB842, 0x776C, + 0xB843, 0x775C, 0xB844, 0x7765, 0xB845, 0x7768, 0xB846, 0x7762, 0xB847, 0x77EE, 0xB848, 0x788E, 0xB849, 0x78B0, 0xB84A, 0x7897, + 0xB84B, 0x7898, 0xB84C, 0x788C, 0xB84D, 0x7889, 0xB84E, 0x787C, 0xB84F, 0x7891, 0xB850, 0x7893, 0xB851, 0x787F, 0xB852, 0x797A, + 0xB853, 0x797F, 0xB854, 0x7981, 0xB855, 0x842C, 0xB856, 0x79BD, 0xB857, 0x7A1C, 0xB858, 0x7A1A, 0xB859, 0x7A20, 0xB85A, 0x7A14, + 0xB85B, 0x7A1F, 0xB85C, 0x7A1E, 0xB85D, 0x7A9F, 0xB85E, 0x7AA0, 0xB85F, 0x7B77, 0xB860, 0x7BC0, 0xB861, 0x7B60, 0xB862, 0x7B6E, + 0xB863, 0x7B67, 0xB864, 0x7CB1, 0xB865, 0x7CB3, 0xB866, 0x7CB5, 0xB867, 0x7D93, 0xB868, 0x7D79, 0xB869, 0x7D91, 0xB86A, 0x7D81, + 0xB86B, 0x7D8F, 0xB86C, 0x7D5B, 0xB86D, 0x7F6E, 0xB86E, 0x7F69, 0xB86F, 0x7F6A, 0xB870, 0x7F72, 0xB871, 0x7FA9, 0xB872, 0x7FA8, + 0xB873, 0x7FA4, 0xB874, 0x8056, 0xB875, 0x8058, 0xB876, 0x8086, 0xB877, 0x8084, 0xB878, 0x8171, 0xB879, 0x8170, 0xB87A, 0x8178, + 0xB87B, 0x8165, 0xB87C, 0x816E, 0xB87D, 0x8173, 0xB87E, 0x816B, 0xB8A1, 0x8179, 0xB8A2, 0x817A, 0xB8A3, 0x8166, 0xB8A4, 0x8205, + 0xB8A5, 0x8247, 0xB8A6, 0x8482, 0xB8A7, 0x8477, 0xB8A8, 0x843D, 0xB8A9, 0x8431, 0xB8AA, 0x8475, 0xB8AB, 0x8466, 0xB8AC, 0x846B, + 0xB8AD, 0x8449, 0xB8AE, 0x846C, 0xB8AF, 0x845B, 0xB8B0, 0x843C, 0xB8B1, 0x8435, 0xB8B2, 0x8461, 0xB8B3, 0x8463, 0xB8B4, 0x8469, + 0xB8B5, 0x846D, 0xB8B6, 0x8446, 0xB8B7, 0x865E, 0xB8B8, 0x865C, 0xB8B9, 0x865F, 0xB8BA, 0x86F9, 0xB8BB, 0x8713, 0xB8BC, 0x8708, + 0xB8BD, 0x8707, 0xB8BE, 0x8700, 0xB8BF, 0x86FE, 0xB8C0, 0x86FB, 0xB8C1, 0x8702, 0xB8C2, 0x8703, 0xB8C3, 0x8706, 0xB8C4, 0x870A, + 0xB8C5, 0x8859, 0xB8C6, 0x88DF, 0xB8C7, 0x88D4, 0xB8C8, 0x88D9, 0xB8C9, 0x88DC, 0xB8CA, 0x88D8, 0xB8CB, 0x88DD, 0xB8CC, 0x88E1, + 0xB8CD, 0x88CA, 0xB8CE, 0x88D5, 0xB8CF, 0x88D2, 0xB8D0, 0x899C, 0xB8D1, 0x89E3, 0xB8D2, 0x8A6B, 0xB8D3, 0x8A72, 0xB8D4, 0x8A73, + 0xB8D5, 0x8A66, 0xB8D6, 0x8A69, 0xB8D7, 0x8A70, 0xB8D8, 0x8A87, 0xB8D9, 0x8A7C, 0xB8DA, 0x8A63, 0xB8DB, 0x8AA0, 0xB8DC, 0x8A71, + 0xB8DD, 0x8A85, 0xB8DE, 0x8A6D, 0xB8DF, 0x8A62, 0xB8E0, 0x8A6E, 0xB8E1, 0x8A6C, 0xB8E2, 0x8A79, 0xB8E3, 0x8A7B, 0xB8E4, 0x8A3E, + 0xB8E5, 0x8A68, 0xB8E6, 0x8C62, 0xB8E7, 0x8C8A, 0xB8E8, 0x8C89, 0xB8E9, 0x8CCA, 0xB8EA, 0x8CC7, 0xB8EB, 0x8CC8, 0xB8EC, 0x8CC4, + 0xB8ED, 0x8CB2, 0xB8EE, 0x8CC3, 0xB8EF, 0x8CC2, 0xB8F0, 0x8CC5, 0xB8F1, 0x8DE1, 0xB8F2, 0x8DDF, 0xB8F3, 0x8DE8, 0xB8F4, 0x8DEF, + 0xB8F5, 0x8DF3, 0xB8F6, 0x8DFA, 0xB8F7, 0x8DEA, 0xB8F8, 0x8DE4, 0xB8F9, 0x8DE6, 0xB8FA, 0x8EB2, 0xB8FB, 0x8F03, 0xB8FC, 0x8F09, + 0xB8FD, 0x8EFE, 0xB8FE, 0x8F0A, 0xB940, 0x8F9F, 0xB941, 0x8FB2, 0xB942, 0x904B, 0xB943, 0x904A, 0xB944, 0x9053, 0xB945, 0x9042, + 0xB946, 0x9054, 0xB947, 0x903C, 0xB948, 0x9055, 0xB949, 0x9050, 0xB94A, 0x9047, 0xB94B, 0x904F, 0xB94C, 0x904E, 0xB94D, 0x904D, + 0xB94E, 0x9051, 0xB94F, 0x903E, 0xB950, 0x9041, 0xB951, 0x9112, 0xB952, 0x9117, 0xB953, 0x916C, 0xB954, 0x916A, 0xB955, 0x9169, + 0xB956, 0x91C9, 0xB957, 0x9237, 0xB958, 0x9257, 0xB959, 0x9238, 0xB95A, 0x923D, 0xB95B, 0x9240, 0xB95C, 0x923E, 0xB95D, 0x925B, + 0xB95E, 0x924B, 0xB95F, 0x9264, 0xB960, 0x9251, 0xB961, 0x9234, 0xB962, 0x9249, 0xB963, 0x924D, 0xB964, 0x9245, 0xB965, 0x9239, + 0xB966, 0x923F, 0xB967, 0x925A, 0xB968, 0x9598, 0xB969, 0x9698, 0xB96A, 0x9694, 0xB96B, 0x9695, 0xB96C, 0x96CD, 0xB96D, 0x96CB, + 0xB96E, 0x96C9, 0xB96F, 0x96CA, 0xB970, 0x96F7, 0xB971, 0x96FB, 0xB972, 0x96F9, 0xB973, 0x96F6, 0xB974, 0x9756, 0xB975, 0x9774, + 0xB976, 0x9776, 0xB977, 0x9810, 0xB978, 0x9811, 0xB979, 0x9813, 0xB97A, 0x980A, 0xB97B, 0x9812, 0xB97C, 0x980C, 0xB97D, 0x98FC, + 0xB97E, 0x98F4, 0xB9A1, 0x98FD, 0xB9A2, 0x98FE, 0xB9A3, 0x99B3, 0xB9A4, 0x99B1, 0xB9A5, 0x99B4, 0xB9A6, 0x9AE1, 0xB9A7, 0x9CE9, + 0xB9A8, 0x9E82, 0xB9A9, 0x9F0E, 0xB9AA, 0x9F13, 0xB9AB, 0x9F20, 0xB9AC, 0x50E7, 0xB9AD, 0x50EE, 0xB9AE, 0x50E5, 0xB9AF, 0x50D6, + 0xB9B0, 0x50ED, 0xB9B1, 0x50DA, 0xB9B2, 0x50D5, 0xB9B3, 0x50CF, 0xB9B4, 0x50D1, 0xB9B5, 0x50F1, 0xB9B6, 0x50CE, 0xB9B7, 0x50E9, + 0xB9B8, 0x5162, 0xB9B9, 0x51F3, 0xB9BA, 0x5283, 0xB9BB, 0x5282, 0xB9BC, 0x5331, 0xB9BD, 0x53AD, 0xB9BE, 0x55FE, 0xB9BF, 0x5600, + 0xB9C0, 0x561B, 0xB9C1, 0x5617, 0xB9C2, 0x55FD, 0xB9C3, 0x5614, 0xB9C4, 0x5606, 0xB9C5, 0x5609, 0xB9C6, 0x560D, 0xB9C7, 0x560E, + 0xB9C8, 0x55F7, 0xB9C9, 0x5616, 0xB9CA, 0x561F, 0xB9CB, 0x5608, 0xB9CC, 0x5610, 0xB9CD, 0x55F6, 0xB9CE, 0x5718, 0xB9CF, 0x5716, + 0xB9D0, 0x5875, 0xB9D1, 0x587E, 0xB9D2, 0x5883, 0xB9D3, 0x5893, 0xB9D4, 0x588A, 0xB9D5, 0x5879, 0xB9D6, 0x5885, 0xB9D7, 0x587D, + 0xB9D8, 0x58FD, 0xB9D9, 0x5925, 0xB9DA, 0x5922, 0xB9DB, 0x5924, 0xB9DC, 0x596A, 0xB9DD, 0x5969, 0xB9DE, 0x5AE1, 0xB9DF, 0x5AE6, + 0xB9E0, 0x5AE9, 0xB9E1, 0x5AD7, 0xB9E2, 0x5AD6, 0xB9E3, 0x5AD8, 0xB9E4, 0x5AE3, 0xB9E5, 0x5B75, 0xB9E6, 0x5BDE, 0xB9E7, 0x5BE7, + 0xB9E8, 0x5BE1, 0xB9E9, 0x5BE5, 0xB9EA, 0x5BE6, 0xB9EB, 0x5BE8, 0xB9EC, 0x5BE2, 0xB9ED, 0x5BE4, 0xB9EE, 0x5BDF, 0xB9EF, 0x5C0D, + 0xB9F0, 0x5C62, 0xB9F1, 0x5D84, 0xB9F2, 0x5D87, 0xB9F3, 0x5E5B, 0xB9F4, 0x5E63, 0xB9F5, 0x5E55, 0xB9F6, 0x5E57, 0xB9F7, 0x5E54, + 0xB9F8, 0x5ED3, 0xB9F9, 0x5ED6, 0xB9FA, 0x5F0A, 0xB9FB, 0x5F46, 0xB9FC, 0x5F70, 0xB9FD, 0x5FB9, 0xB9FE, 0x6147, 0xBA40, 0x613F, + 0xBA41, 0x614B, 0xBA42, 0x6177, 0xBA43, 0x6162, 0xBA44, 0x6163, 0xBA45, 0x615F, 0xBA46, 0x615A, 0xBA47, 0x6158, 0xBA48, 0x6175, + 0xBA49, 0x622A, 0xBA4A, 0x6487, 0xBA4B, 0x6458, 0xBA4C, 0x6454, 0xBA4D, 0x64A4, 0xBA4E, 0x6478, 0xBA4F, 0x645F, 0xBA50, 0x647A, + 0xBA51, 0x6451, 0xBA52, 0x6467, 0xBA53, 0x6434, 0xBA54, 0x646D, 0xBA55, 0x647B, 0xBA56, 0x6572, 0xBA57, 0x65A1, 0xBA58, 0x65D7, + 0xBA59, 0x65D6, 0xBA5A, 0x66A2, 0xBA5B, 0x66A8, 0xBA5C, 0x669D, 0xBA5D, 0x699C, 0xBA5E, 0x69A8, 0xBA5F, 0x6995, 0xBA60, 0x69C1, + 0xBA61, 0x69AE, 0xBA62, 0x69D3, 0xBA63, 0x69CB, 0xBA64, 0x699B, 0xBA65, 0x69B7, 0xBA66, 0x69BB, 0xBA67, 0x69AB, 0xBA68, 0x69B4, + 0xBA69, 0x69D0, 0xBA6A, 0x69CD, 0xBA6B, 0x69AD, 0xBA6C, 0x69CC, 0xBA6D, 0x69A6, 0xBA6E, 0x69C3, 0xBA6F, 0x69A3, 0xBA70, 0x6B49, + 0xBA71, 0x6B4C, 0xBA72, 0x6C33, 0xBA73, 0x6F33, 0xBA74, 0x6F14, 0xBA75, 0x6EFE, 0xBA76, 0x6F13, 0xBA77, 0x6EF4, 0xBA78, 0x6F29, + 0xBA79, 0x6F3E, 0xBA7A, 0x6F20, 0xBA7B, 0x6F2C, 0xBA7C, 0x6F0F, 0xBA7D, 0x6F02, 0xBA7E, 0x6F22, 0xBAA1, 0x6EFF, 0xBAA2, 0x6EEF, + 0xBAA3, 0x6F06, 0xBAA4, 0x6F31, 0xBAA5, 0x6F38, 0xBAA6, 0x6F32, 0xBAA7, 0x6F23, 0xBAA8, 0x6F15, 0xBAA9, 0x6F2B, 0xBAAA, 0x6F2F, + 0xBAAB, 0x6F88, 0xBAAC, 0x6F2A, 0xBAAD, 0x6EEC, 0xBAAE, 0x6F01, 0xBAAF, 0x6EF2, 0xBAB0, 0x6ECC, 0xBAB1, 0x6EF7, 0xBAB2, 0x7194, + 0xBAB3, 0x7199, 0xBAB4, 0x717D, 0xBAB5, 0x718A, 0xBAB6, 0x7184, 0xBAB7, 0x7192, 0xBAB8, 0x723E, 0xBAB9, 0x7292, 0xBABA, 0x7296, + 0xBABB, 0x7344, 0xBABC, 0x7350, 0xBABD, 0x7464, 0xBABE, 0x7463, 0xBABF, 0x746A, 0xBAC0, 0x7470, 0xBAC1, 0x746D, 0xBAC2, 0x7504, + 0xBAC3, 0x7591, 0xBAC4, 0x7627, 0xBAC5, 0x760D, 0xBAC6, 0x760B, 0xBAC7, 0x7609, 0xBAC8, 0x7613, 0xBAC9, 0x76E1, 0xBACA, 0x76E3, + 0xBACB, 0x7784, 0xBACC, 0x777D, 0xBACD, 0x777F, 0xBACE, 0x7761, 0xBACF, 0x78C1, 0xBAD0, 0x789F, 0xBAD1, 0x78A7, 0xBAD2, 0x78B3, + 0xBAD3, 0x78A9, 0xBAD4, 0x78A3, 0xBAD5, 0x798E, 0xBAD6, 0x798F, 0xBAD7, 0x798D, 0xBAD8, 0x7A2E, 0xBAD9, 0x7A31, 0xBADA, 0x7AAA, + 0xBADB, 0x7AA9, 0xBADC, 0x7AED, 0xBADD, 0x7AEF, 0xBADE, 0x7BA1, 0xBADF, 0x7B95, 0xBAE0, 0x7B8B, 0xBAE1, 0x7B75, 0xBAE2, 0x7B97, + 0xBAE3, 0x7B9D, 0xBAE4, 0x7B94, 0xBAE5, 0x7B8F, 0xBAE6, 0x7BB8, 0xBAE7, 0x7B87, 0xBAE8, 0x7B84, 0xBAE9, 0x7CB9, 0xBAEA, 0x7CBD, + 0xBAEB, 0x7CBE, 0xBAEC, 0x7DBB, 0xBAED, 0x7DB0, 0xBAEE, 0x7D9C, 0xBAEF, 0x7DBD, 0xBAF0, 0x7DBE, 0xBAF1, 0x7DA0, 0xBAF2, 0x7DCA, + 0xBAF3, 0x7DB4, 0xBAF4, 0x7DB2, 0xBAF5, 0x7DB1, 0xBAF6, 0x7DBA, 0xBAF7, 0x7DA2, 0xBAF8, 0x7DBF, 0xBAF9, 0x7DB5, 0xBAFA, 0x7DB8, + 0xBAFB, 0x7DAD, 0xBAFC, 0x7DD2, 0xBAFD, 0x7DC7, 0xBAFE, 0x7DAC, 0xBB40, 0x7F70, 0xBB41, 0x7FE0, 0xBB42, 0x7FE1, 0xBB43, 0x7FDF, + 0xBB44, 0x805E, 0xBB45, 0x805A, 0xBB46, 0x8087, 0xBB47, 0x8150, 0xBB48, 0x8180, 0xBB49, 0x818F, 0xBB4A, 0x8188, 0xBB4B, 0x818A, + 0xBB4C, 0x817F, 0xBB4D, 0x8182, 0xBB4E, 0x81E7, 0xBB4F, 0x81FA, 0xBB50, 0x8207, 0xBB51, 0x8214, 0xBB52, 0x821E, 0xBB53, 0x824B, + 0xBB54, 0x84C9, 0xBB55, 0x84BF, 0xBB56, 0x84C6, 0xBB57, 0x84C4, 0xBB58, 0x8499, 0xBB59, 0x849E, 0xBB5A, 0x84B2, 0xBB5B, 0x849C, + 0xBB5C, 0x84CB, 0xBB5D, 0x84B8, 0xBB5E, 0x84C0, 0xBB5F, 0x84D3, 0xBB60, 0x8490, 0xBB61, 0x84BC, 0xBB62, 0x84D1, 0xBB63, 0x84CA, + 0xBB64, 0x873F, 0xBB65, 0x871C, 0xBB66, 0x873B, 0xBB67, 0x8722, 0xBB68, 0x8725, 0xBB69, 0x8734, 0xBB6A, 0x8718, 0xBB6B, 0x8755, + 0xBB6C, 0x8737, 0xBB6D, 0x8729, 0xBB6E, 0x88F3, 0xBB6F, 0x8902, 0xBB70, 0x88F4, 0xBB71, 0x88F9, 0xBB72, 0x88F8, 0xBB73, 0x88FD, + 0xBB74, 0x88E8, 0xBB75, 0x891A, 0xBB76, 0x88EF, 0xBB77, 0x8AA6, 0xBB78, 0x8A8C, 0xBB79, 0x8A9E, 0xBB7A, 0x8AA3, 0xBB7B, 0x8A8D, + 0xBB7C, 0x8AA1, 0xBB7D, 0x8A93, 0xBB7E, 0x8AA4, 0xBBA1, 0x8AAA, 0xBBA2, 0x8AA5, 0xBBA3, 0x8AA8, 0xBBA4, 0x8A98, 0xBBA5, 0x8A91, + 0xBBA6, 0x8A9A, 0xBBA7, 0x8AA7, 0xBBA8, 0x8C6A, 0xBBA9, 0x8C8D, 0xBBAA, 0x8C8C, 0xBBAB, 0x8CD3, 0xBBAC, 0x8CD1, 0xBBAD, 0x8CD2, + 0xBBAE, 0x8D6B, 0xBBAF, 0x8D99, 0xBBB0, 0x8D95, 0xBBB1, 0x8DFC, 0xBBB2, 0x8F14, 0xBBB3, 0x8F12, 0xBBB4, 0x8F15, 0xBBB5, 0x8F13, + 0xBBB6, 0x8FA3, 0xBBB7, 0x9060, 0xBBB8, 0x9058, 0xBBB9, 0x905C, 0xBBBA, 0x9063, 0xBBBB, 0x9059, 0xBBBC, 0x905E, 0xBBBD, 0x9062, + 0xBBBE, 0x905D, 0xBBBF, 0x905B, 0xBBC0, 0x9119, 0xBBC1, 0x9118, 0xBBC2, 0x911E, 0xBBC3, 0x9175, 0xBBC4, 0x9178, 0xBBC5, 0x9177, + 0xBBC6, 0x9174, 0xBBC7, 0x9278, 0xBBC8, 0x9280, 0xBBC9, 0x9285, 0xBBCA, 0x9298, 0xBBCB, 0x9296, 0xBBCC, 0x927B, 0xBBCD, 0x9293, + 0xBBCE, 0x929C, 0xBBCF, 0x92A8, 0xBBD0, 0x927C, 0xBBD1, 0x9291, 0xBBD2, 0x95A1, 0xBBD3, 0x95A8, 0xBBD4, 0x95A9, 0xBBD5, 0x95A3, + 0xBBD6, 0x95A5, 0xBBD7, 0x95A4, 0xBBD8, 0x9699, 0xBBD9, 0x969C, 0xBBDA, 0x969B, 0xBBDB, 0x96CC, 0xBBDC, 0x96D2, 0xBBDD, 0x9700, + 0xBBDE, 0x977C, 0xBBDF, 0x9785, 0xBBE0, 0x97F6, 0xBBE1, 0x9817, 0xBBE2, 0x9818, 0xBBE3, 0x98AF, 0xBBE4, 0x98B1, 0xBBE5, 0x9903, + 0xBBE6, 0x9905, 0xBBE7, 0x990C, 0xBBE8, 0x9909, 0xBBE9, 0x99C1, 0xBBEA, 0x9AAF, 0xBBEB, 0x9AB0, 0xBBEC, 0x9AE6, 0xBBED, 0x9B41, + 0xBBEE, 0x9B42, 0xBBEF, 0x9CF4, 0xBBF0, 0x9CF6, 0xBBF1, 0x9CF3, 0xBBF2, 0x9EBC, 0xBBF3, 0x9F3B, 0xBBF4, 0x9F4A, 0xBBF5, 0x5104, + 0xBBF6, 0x5100, 0xBBF7, 0x50FB, 0xBBF8, 0x50F5, 0xBBF9, 0x50F9, 0xBBFA, 0x5102, 0xBBFB, 0x5108, 0xBBFC, 0x5109, 0xBBFD, 0x5105, + 0xBBFE, 0x51DC, 0xBC40, 0x5287, 0xBC41, 0x5288, 0xBC42, 0x5289, 0xBC43, 0x528D, 0xBC44, 0x528A, 0xBC45, 0x52F0, 0xBC46, 0x53B2, + 0xBC47, 0x562E, 0xBC48, 0x563B, 0xBC49, 0x5639, 0xBC4A, 0x5632, 0xBC4B, 0x563F, 0xBC4C, 0x5634, 0xBC4D, 0x5629, 0xBC4E, 0x5653, + 0xBC4F, 0x564E, 0xBC50, 0x5657, 0xBC51, 0x5674, 0xBC52, 0x5636, 0xBC53, 0x562F, 0xBC54, 0x5630, 0xBC55, 0x5880, 0xBC56, 0x589F, + 0xBC57, 0x589E, 0xBC58, 0x58B3, 0xBC59, 0x589C, 0xBC5A, 0x58AE, 0xBC5B, 0x58A9, 0xBC5C, 0x58A6, 0xBC5D, 0x596D, 0xBC5E, 0x5B09, + 0xBC5F, 0x5AFB, 0xBC60, 0x5B0B, 0xBC61, 0x5AF5, 0xBC62, 0x5B0C, 0xBC63, 0x5B08, 0xBC64, 0x5BEE, 0xBC65, 0x5BEC, 0xBC66, 0x5BE9, + 0xBC67, 0x5BEB, 0xBC68, 0x5C64, 0xBC69, 0x5C65, 0xBC6A, 0x5D9D, 0xBC6B, 0x5D94, 0xBC6C, 0x5E62, 0xBC6D, 0x5E5F, 0xBC6E, 0x5E61, + 0xBC6F, 0x5EE2, 0xBC70, 0x5EDA, 0xBC71, 0x5EDF, 0xBC72, 0x5EDD, 0xBC73, 0x5EE3, 0xBC74, 0x5EE0, 0xBC75, 0x5F48, 0xBC76, 0x5F71, + 0xBC77, 0x5FB7, 0xBC78, 0x5FB5, 0xBC79, 0x6176, 0xBC7A, 0x6167, 0xBC7B, 0x616E, 0xBC7C, 0x615D, 0xBC7D, 0x6155, 0xBC7E, 0x6182, + 0xBCA1, 0x617C, 0xBCA2, 0x6170, 0xBCA3, 0x616B, 0xBCA4, 0x617E, 0xBCA5, 0x61A7, 0xBCA6, 0x6190, 0xBCA7, 0x61AB, 0xBCA8, 0x618E, + 0xBCA9, 0x61AC, 0xBCAA, 0x619A, 0xBCAB, 0x61A4, 0xBCAC, 0x6194, 0xBCAD, 0x61AE, 0xBCAE, 0x622E, 0xBCAF, 0x6469, 0xBCB0, 0x646F, + 0xBCB1, 0x6479, 0xBCB2, 0x649E, 0xBCB3, 0x64B2, 0xBCB4, 0x6488, 0xBCB5, 0x6490, 0xBCB6, 0x64B0, 0xBCB7, 0x64A5, 0xBCB8, 0x6493, + 0xBCB9, 0x6495, 0xBCBA, 0x64A9, 0xBCBB, 0x6492, 0xBCBC, 0x64AE, 0xBCBD, 0x64AD, 0xBCBE, 0x64AB, 0xBCBF, 0x649A, 0xBCC0, 0x64AC, + 0xBCC1, 0x6499, 0xBCC2, 0x64A2, 0xBCC3, 0x64B3, 0xBCC4, 0x6575, 0xBCC5, 0x6577, 0xBCC6, 0x6578, 0xBCC7, 0x66AE, 0xBCC8, 0x66AB, + 0xBCC9, 0x66B4, 0xBCCA, 0x66B1, 0xBCCB, 0x6A23, 0xBCCC, 0x6A1F, 0xBCCD, 0x69E8, 0xBCCE, 0x6A01, 0xBCCF, 0x6A1E, 0xBCD0, 0x6A19, + 0xBCD1, 0x69FD, 0xBCD2, 0x6A21, 0xBCD3, 0x6A13, 0xBCD4, 0x6A0A, 0xBCD5, 0x69F3, 0xBCD6, 0x6A02, 0xBCD7, 0x6A05, 0xBCD8, 0x69ED, + 0xBCD9, 0x6A11, 0xBCDA, 0x6B50, 0xBCDB, 0x6B4E, 0xBCDC, 0x6BA4, 0xBCDD, 0x6BC5, 0xBCDE, 0x6BC6, 0xBCDF, 0x6F3F, 0xBCE0, 0x6F7C, + 0xBCE1, 0x6F84, 0xBCE2, 0x6F51, 0xBCE3, 0x6F66, 0xBCE4, 0x6F54, 0xBCE5, 0x6F86, 0xBCE6, 0x6F6D, 0xBCE7, 0x6F5B, 0xBCE8, 0x6F78, + 0xBCE9, 0x6F6E, 0xBCEA, 0x6F8E, 0xBCEB, 0x6F7A, 0xBCEC, 0x6F70, 0xBCED, 0x6F64, 0xBCEE, 0x6F97, 0xBCEF, 0x6F58, 0xBCF0, 0x6ED5, + 0xBCF1, 0x6F6F, 0xBCF2, 0x6F60, 0xBCF3, 0x6F5F, 0xBCF4, 0x719F, 0xBCF5, 0x71AC, 0xBCF6, 0x71B1, 0xBCF7, 0x71A8, 0xBCF8, 0x7256, + 0xBCF9, 0x729B, 0xBCFA, 0x734E, 0xBCFB, 0x7357, 0xBCFC, 0x7469, 0xBCFD, 0x748B, 0xBCFE, 0x7483, 0xBD40, 0x747E, 0xBD41, 0x7480, + 0xBD42, 0x757F, 0xBD43, 0x7620, 0xBD44, 0x7629, 0xBD45, 0x761F, 0xBD46, 0x7624, 0xBD47, 0x7626, 0xBD48, 0x7621, 0xBD49, 0x7622, + 0xBD4A, 0x769A, 0xBD4B, 0x76BA, 0xBD4C, 0x76E4, 0xBD4D, 0x778E, 0xBD4E, 0x7787, 0xBD4F, 0x778C, 0xBD50, 0x7791, 0xBD51, 0x778B, + 0xBD52, 0x78CB, 0xBD53, 0x78C5, 0xBD54, 0x78BA, 0xBD55, 0x78CA, 0xBD56, 0x78BE, 0xBD57, 0x78D5, 0xBD58, 0x78BC, 0xBD59, 0x78D0, + 0xBD5A, 0x7A3F, 0xBD5B, 0x7A3C, 0xBD5C, 0x7A40, 0xBD5D, 0x7A3D, 0xBD5E, 0x7A37, 0xBD5F, 0x7A3B, 0xBD60, 0x7AAF, 0xBD61, 0x7AAE, + 0xBD62, 0x7BAD, 0xBD63, 0x7BB1, 0xBD64, 0x7BC4, 0xBD65, 0x7BB4, 0xBD66, 0x7BC6, 0xBD67, 0x7BC7, 0xBD68, 0x7BC1, 0xBD69, 0x7BA0, + 0xBD6A, 0x7BCC, 0xBD6B, 0x7CCA, 0xBD6C, 0x7DE0, 0xBD6D, 0x7DF4, 0xBD6E, 0x7DEF, 0xBD6F, 0x7DFB, 0xBD70, 0x7DD8, 0xBD71, 0x7DEC, + 0xBD72, 0x7DDD, 0xBD73, 0x7DE8, 0xBD74, 0x7DE3, 0xBD75, 0x7DDA, 0xBD76, 0x7DDE, 0xBD77, 0x7DE9, 0xBD78, 0x7D9E, 0xBD79, 0x7DD9, + 0xBD7A, 0x7DF2, 0xBD7B, 0x7DF9, 0xBD7C, 0x7F75, 0xBD7D, 0x7F77, 0xBD7E, 0x7FAF, 0xBDA1, 0x7FE9, 0xBDA2, 0x8026, 0xBDA3, 0x819B, + 0xBDA4, 0x819C, 0xBDA5, 0x819D, 0xBDA6, 0x81A0, 0xBDA7, 0x819A, 0xBDA8, 0x8198, 0xBDA9, 0x8517, 0xBDAA, 0x853D, 0xBDAB, 0x851A, + 0xBDAC, 0x84EE, 0xBDAD, 0x852C, 0xBDAE, 0x852D, 0xBDAF, 0x8513, 0xBDB0, 0x8511, 0xBDB1, 0x8523, 0xBDB2, 0x8521, 0xBDB3, 0x8514, + 0xBDB4, 0x84EC, 0xBDB5, 0x8525, 0xBDB6, 0x84FF, 0xBDB7, 0x8506, 0xBDB8, 0x8782, 0xBDB9, 0x8774, 0xBDBA, 0x8776, 0xBDBB, 0x8760, + 0xBDBC, 0x8766, 0xBDBD, 0x8778, 0xBDBE, 0x8768, 0xBDBF, 0x8759, 0xBDC0, 0x8757, 0xBDC1, 0x874C, 0xBDC2, 0x8753, 0xBDC3, 0x885B, + 0xBDC4, 0x885D, 0xBDC5, 0x8910, 0xBDC6, 0x8907, 0xBDC7, 0x8912, 0xBDC8, 0x8913, 0xBDC9, 0x8915, 0xBDCA, 0x890A, 0xBDCB, 0x8ABC, + 0xBDCC, 0x8AD2, 0xBDCD, 0x8AC7, 0xBDCE, 0x8AC4, 0xBDCF, 0x8A95, 0xBDD0, 0x8ACB, 0xBDD1, 0x8AF8, 0xBDD2, 0x8AB2, 0xBDD3, 0x8AC9, + 0xBDD4, 0x8AC2, 0xBDD5, 0x8ABF, 0xBDD6, 0x8AB0, 0xBDD7, 0x8AD6, 0xBDD8, 0x8ACD, 0xBDD9, 0x8AB6, 0xBDDA, 0x8AB9, 0xBDDB, 0x8ADB, + 0xBDDC, 0x8C4C, 0xBDDD, 0x8C4E, 0xBDDE, 0x8C6C, 0xBDDF, 0x8CE0, 0xBDE0, 0x8CDE, 0xBDE1, 0x8CE6, 0xBDE2, 0x8CE4, 0xBDE3, 0x8CEC, + 0xBDE4, 0x8CED, 0xBDE5, 0x8CE2, 0xBDE6, 0x8CE3, 0xBDE7, 0x8CDC, 0xBDE8, 0x8CEA, 0xBDE9, 0x8CE1, 0xBDEA, 0x8D6D, 0xBDEB, 0x8D9F, + 0xBDEC, 0x8DA3, 0xBDED, 0x8E2B, 0xBDEE, 0x8E10, 0xBDEF, 0x8E1D, 0xBDF0, 0x8E22, 0xBDF1, 0x8E0F, 0xBDF2, 0x8E29, 0xBDF3, 0x8E1F, + 0xBDF4, 0x8E21, 0xBDF5, 0x8E1E, 0xBDF6, 0x8EBA, 0xBDF7, 0x8F1D, 0xBDF8, 0x8F1B, 0xBDF9, 0x8F1F, 0xBDFA, 0x8F29, 0xBDFB, 0x8F26, + 0xBDFC, 0x8F2A, 0xBDFD, 0x8F1C, 0xBDFE, 0x8F1E, 0xBE40, 0x8F25, 0xBE41, 0x9069, 0xBE42, 0x906E, 0xBE43, 0x9068, 0xBE44, 0x906D, + 0xBE45, 0x9077, 0xBE46, 0x9130, 0xBE47, 0x912D, 0xBE48, 0x9127, 0xBE49, 0x9131, 0xBE4A, 0x9187, 0xBE4B, 0x9189, 0xBE4C, 0x918B, + 0xBE4D, 0x9183, 0xBE4E, 0x92C5, 0xBE4F, 0x92BB, 0xBE50, 0x92B7, 0xBE51, 0x92EA, 0xBE52, 0x92AC, 0xBE53, 0x92E4, 0xBE54, 0x92C1, + 0xBE55, 0x92B3, 0xBE56, 0x92BC, 0xBE57, 0x92D2, 0xBE58, 0x92C7, 0xBE59, 0x92F0, 0xBE5A, 0x92B2, 0xBE5B, 0x95AD, 0xBE5C, 0x95B1, + 0xBE5D, 0x9704, 0xBE5E, 0x9706, 0xBE5F, 0x9707, 0xBE60, 0x9709, 0xBE61, 0x9760, 0xBE62, 0x978D, 0xBE63, 0x978B, 0xBE64, 0x978F, + 0xBE65, 0x9821, 0xBE66, 0x982B, 0xBE67, 0x981C, 0xBE68, 0x98B3, 0xBE69, 0x990A, 0xBE6A, 0x9913, 0xBE6B, 0x9912, 0xBE6C, 0x9918, + 0xBE6D, 0x99DD, 0xBE6E, 0x99D0, 0xBE6F, 0x99DF, 0xBE70, 0x99DB, 0xBE71, 0x99D1, 0xBE72, 0x99D5, 0xBE73, 0x99D2, 0xBE74, 0x99D9, + 0xBE75, 0x9AB7, 0xBE76, 0x9AEE, 0xBE77, 0x9AEF, 0xBE78, 0x9B27, 0xBE79, 0x9B45, 0xBE7A, 0x9B44, 0xBE7B, 0x9B77, 0xBE7C, 0x9B6F, + 0xBE7D, 0x9D06, 0xBE7E, 0x9D09, 0xBEA1, 0x9D03, 0xBEA2, 0x9EA9, 0xBEA3, 0x9EBE, 0xBEA4, 0x9ECE, 0xBEA5, 0x58A8, 0xBEA6, 0x9F52, + 0xBEA7, 0x5112, 0xBEA8, 0x5118, 0xBEA9, 0x5114, 0xBEAA, 0x5110, 0xBEAB, 0x5115, 0xBEAC, 0x5180, 0xBEAD, 0x51AA, 0xBEAE, 0x51DD, + 0xBEAF, 0x5291, 0xBEB0, 0x5293, 0xBEB1, 0x52F3, 0xBEB2, 0x5659, 0xBEB3, 0x566B, 0xBEB4, 0x5679, 0xBEB5, 0x5669, 0xBEB6, 0x5664, + 0xBEB7, 0x5678, 0xBEB8, 0x566A, 0xBEB9, 0x5668, 0xBEBA, 0x5665, 0xBEBB, 0x5671, 0xBEBC, 0x566F, 0xBEBD, 0x566C, 0xBEBE, 0x5662, + 0xBEBF, 0x5676, 0xBEC0, 0x58C1, 0xBEC1, 0x58BE, 0xBEC2, 0x58C7, 0xBEC3, 0x58C5, 0xBEC4, 0x596E, 0xBEC5, 0x5B1D, 0xBEC6, 0x5B34, + 0xBEC7, 0x5B78, 0xBEC8, 0x5BF0, 0xBEC9, 0x5C0E, 0xBECA, 0x5F4A, 0xBECB, 0x61B2, 0xBECC, 0x6191, 0xBECD, 0x61A9, 0xBECE, 0x618A, + 0xBECF, 0x61CD, 0xBED0, 0x61B6, 0xBED1, 0x61BE, 0xBED2, 0x61CA, 0xBED3, 0x61C8, 0xBED4, 0x6230, 0xBED5, 0x64C5, 0xBED6, 0x64C1, + 0xBED7, 0x64CB, 0xBED8, 0x64BB, 0xBED9, 0x64BC, 0xBEDA, 0x64DA, 0xBEDB, 0x64C4, 0xBEDC, 0x64C7, 0xBEDD, 0x64C2, 0xBEDE, 0x64CD, + 0xBEDF, 0x64BF, 0xBEE0, 0x64D2, 0xBEE1, 0x64D4, 0xBEE2, 0x64BE, 0xBEE3, 0x6574, 0xBEE4, 0x66C6, 0xBEE5, 0x66C9, 0xBEE6, 0x66B9, + 0xBEE7, 0x66C4, 0xBEE8, 0x66C7, 0xBEE9, 0x66B8, 0xBEEA, 0x6A3D, 0xBEEB, 0x6A38, 0xBEEC, 0x6A3A, 0xBEED, 0x6A59, 0xBEEE, 0x6A6B, + 0xBEEF, 0x6A58, 0xBEF0, 0x6A39, 0xBEF1, 0x6A44, 0xBEF2, 0x6A62, 0xBEF3, 0x6A61, 0xBEF4, 0x6A4B, 0xBEF5, 0x6A47, 0xBEF6, 0x6A35, + 0xBEF7, 0x6A5F, 0xBEF8, 0x6A48, 0xBEF9, 0x6B59, 0xBEFA, 0x6B77, 0xBEFB, 0x6C05, 0xBEFC, 0x6FC2, 0xBEFD, 0x6FB1, 0xBEFE, 0x6FA1, + 0xBF40, 0x6FC3, 0xBF41, 0x6FA4, 0xBF42, 0x6FC1, 0xBF43, 0x6FA7, 0xBF44, 0x6FB3, 0xBF45, 0x6FC0, 0xBF46, 0x6FB9, 0xBF47, 0x6FB6, + 0xBF48, 0x6FA6, 0xBF49, 0x6FA0, 0xBF4A, 0x6FB4, 0xBF4B, 0x71BE, 0xBF4C, 0x71C9, 0xBF4D, 0x71D0, 0xBF4E, 0x71D2, 0xBF4F, 0x71C8, + 0xBF50, 0x71D5, 0xBF51, 0x71B9, 0xBF52, 0x71CE, 0xBF53, 0x71D9, 0xBF54, 0x71DC, 0xBF55, 0x71C3, 0xBF56, 0x71C4, 0xBF57, 0x7368, + 0xBF58, 0x749C, 0xBF59, 0x74A3, 0xBF5A, 0x7498, 0xBF5B, 0x749F, 0xBF5C, 0x749E, 0xBF5D, 0x74E2, 0xBF5E, 0x750C, 0xBF5F, 0x750D, + 0xBF60, 0x7634, 0xBF61, 0x7638, 0xBF62, 0x763A, 0xBF63, 0x76E7, 0xBF64, 0x76E5, 0xBF65, 0x77A0, 0xBF66, 0x779E, 0xBF67, 0x779F, + 0xBF68, 0x77A5, 0xBF69, 0x78E8, 0xBF6A, 0x78DA, 0xBF6B, 0x78EC, 0xBF6C, 0x78E7, 0xBF6D, 0x79A6, 0xBF6E, 0x7A4D, 0xBF6F, 0x7A4E, + 0xBF70, 0x7A46, 0xBF71, 0x7A4C, 0xBF72, 0x7A4B, 0xBF73, 0x7ABA, 0xBF74, 0x7BD9, 0xBF75, 0x7C11, 0xBF76, 0x7BC9, 0xBF77, 0x7BE4, + 0xBF78, 0x7BDB, 0xBF79, 0x7BE1, 0xBF7A, 0x7BE9, 0xBF7B, 0x7BE6, 0xBF7C, 0x7CD5, 0xBF7D, 0x7CD6, 0xBF7E, 0x7E0A, 0xBFA1, 0x7E11, + 0xBFA2, 0x7E08, 0xBFA3, 0x7E1B, 0xBFA4, 0x7E23, 0xBFA5, 0x7E1E, 0xBFA6, 0x7E1D, 0xBFA7, 0x7E09, 0xBFA8, 0x7E10, 0xBFA9, 0x7F79, + 0xBFAA, 0x7FB2, 0xBFAB, 0x7FF0, 0xBFAC, 0x7FF1, 0xBFAD, 0x7FEE, 0xBFAE, 0x8028, 0xBFAF, 0x81B3, 0xBFB0, 0x81A9, 0xBFB1, 0x81A8, + 0xBFB2, 0x81FB, 0xBFB3, 0x8208, 0xBFB4, 0x8258, 0xBFB5, 0x8259, 0xBFB6, 0x854A, 0xBFB7, 0x8559, 0xBFB8, 0x8548, 0xBFB9, 0x8568, + 0xBFBA, 0x8569, 0xBFBB, 0x8543, 0xBFBC, 0x8549, 0xBFBD, 0x856D, 0xBFBE, 0x856A, 0xBFBF, 0x855E, 0xBFC0, 0x8783, 0xBFC1, 0x879F, + 0xBFC2, 0x879E, 0xBFC3, 0x87A2, 0xBFC4, 0x878D, 0xBFC5, 0x8861, 0xBFC6, 0x892A, 0xBFC7, 0x8932, 0xBFC8, 0x8925, 0xBFC9, 0x892B, + 0xBFCA, 0x8921, 0xBFCB, 0x89AA, 0xBFCC, 0x89A6, 0xBFCD, 0x8AE6, 0xBFCE, 0x8AFA, 0xBFCF, 0x8AEB, 0xBFD0, 0x8AF1, 0xBFD1, 0x8B00, + 0xBFD2, 0x8ADC, 0xBFD3, 0x8AE7, 0xBFD4, 0x8AEE, 0xBFD5, 0x8AFE, 0xBFD6, 0x8B01, 0xBFD7, 0x8B02, 0xBFD8, 0x8AF7, 0xBFD9, 0x8AED, + 0xBFDA, 0x8AF3, 0xBFDB, 0x8AF6, 0xBFDC, 0x8AFC, 0xBFDD, 0x8C6B, 0xBFDE, 0x8C6D, 0xBFDF, 0x8C93, 0xBFE0, 0x8CF4, 0xBFE1, 0x8E44, + 0xBFE2, 0x8E31, 0xBFE3, 0x8E34, 0xBFE4, 0x8E42, 0xBFE5, 0x8E39, 0xBFE6, 0x8E35, 0xBFE7, 0x8F3B, 0xBFE8, 0x8F2F, 0xBFE9, 0x8F38, + 0xBFEA, 0x8F33, 0xBFEB, 0x8FA8, 0xBFEC, 0x8FA6, 0xBFED, 0x9075, 0xBFEE, 0x9074, 0xBFEF, 0x9078, 0xBFF0, 0x9072, 0xBFF1, 0x907C, + 0xBFF2, 0x907A, 0xBFF3, 0x9134, 0xBFF4, 0x9192, 0xBFF5, 0x9320, 0xBFF6, 0x9336, 0xBFF7, 0x92F8, 0xBFF8, 0x9333, 0xBFF9, 0x932F, + 0xBFFA, 0x9322, 0xBFFB, 0x92FC, 0xBFFC, 0x932B, 0xBFFD, 0x9304, 0xBFFE, 0x931A, 0xC040, 0x9310, 0xC041, 0x9326, 0xC042, 0x9321, + 0xC043, 0x9315, 0xC044, 0x932E, 0xC045, 0x9319, 0xC046, 0x95BB, 0xC047, 0x96A7, 0xC048, 0x96A8, 0xC049, 0x96AA, 0xC04A, 0x96D5, + 0xC04B, 0x970E, 0xC04C, 0x9711, 0xC04D, 0x9716, 0xC04E, 0x970D, 0xC04F, 0x9713, 0xC050, 0x970F, 0xC051, 0x975B, 0xC052, 0x975C, + 0xC053, 0x9766, 0xC054, 0x9798, 0xC055, 0x9830, 0xC056, 0x9838, 0xC057, 0x983B, 0xC058, 0x9837, 0xC059, 0x982D, 0xC05A, 0x9839, + 0xC05B, 0x9824, 0xC05C, 0x9910, 0xC05D, 0x9928, 0xC05E, 0x991E, 0xC05F, 0x991B, 0xC060, 0x9921, 0xC061, 0x991A, 0xC062, 0x99ED, + 0xC063, 0x99E2, 0xC064, 0x99F1, 0xC065, 0x9AB8, 0xC066, 0x9ABC, 0xC067, 0x9AFB, 0xC068, 0x9AED, 0xC069, 0x9B28, 0xC06A, 0x9B91, + 0xC06B, 0x9D15, 0xC06C, 0x9D23, 0xC06D, 0x9D26, 0xC06E, 0x9D28, 0xC06F, 0x9D12, 0xC070, 0x9D1B, 0xC071, 0x9ED8, 0xC072, 0x9ED4, + 0xC073, 0x9F8D, 0xC074, 0x9F9C, 0xC075, 0x512A, 0xC076, 0x511F, 0xC077, 0x5121, 0xC078, 0x5132, 0xC079, 0x52F5, 0xC07A, 0x568E, + 0xC07B, 0x5680, 0xC07C, 0x5690, 0xC07D, 0x5685, 0xC07E, 0x5687, 0xC0A1, 0x568F, 0xC0A2, 0x58D5, 0xC0A3, 0x58D3, 0xC0A4, 0x58D1, + 0xC0A5, 0x58CE, 0xC0A6, 0x5B30, 0xC0A7, 0x5B2A, 0xC0A8, 0x5B24, 0xC0A9, 0x5B7A, 0xC0AA, 0x5C37, 0xC0AB, 0x5C68, 0xC0AC, 0x5DBC, + 0xC0AD, 0x5DBA, 0xC0AE, 0x5DBD, 0xC0AF, 0x5DB8, 0xC0B0, 0x5E6B, 0xC0B1, 0x5F4C, 0xC0B2, 0x5FBD, 0xC0B3, 0x61C9, 0xC0B4, 0x61C2, + 0xC0B5, 0x61C7, 0xC0B6, 0x61E6, 0xC0B7, 0x61CB, 0xC0B8, 0x6232, 0xC0B9, 0x6234, 0xC0BA, 0x64CE, 0xC0BB, 0x64CA, 0xC0BC, 0x64D8, + 0xC0BD, 0x64E0, 0xC0BE, 0x64F0, 0xC0BF, 0x64E6, 0xC0C0, 0x64EC, 0xC0C1, 0x64F1, 0xC0C2, 0x64E2, 0xC0C3, 0x64ED, 0xC0C4, 0x6582, + 0xC0C5, 0x6583, 0xC0C6, 0x66D9, 0xC0C7, 0x66D6, 0xC0C8, 0x6A80, 0xC0C9, 0x6A94, 0xC0CA, 0x6A84, 0xC0CB, 0x6AA2, 0xC0CC, 0x6A9C, + 0xC0CD, 0x6ADB, 0xC0CE, 0x6AA3, 0xC0CF, 0x6A7E, 0xC0D0, 0x6A97, 0xC0D1, 0x6A90, 0xC0D2, 0x6AA0, 0xC0D3, 0x6B5C, 0xC0D4, 0x6BAE, + 0xC0D5, 0x6BDA, 0xC0D6, 0x6C08, 0xC0D7, 0x6FD8, 0xC0D8, 0x6FF1, 0xC0D9, 0x6FDF, 0xC0DA, 0x6FE0, 0xC0DB, 0x6FDB, 0xC0DC, 0x6FE4, + 0xC0DD, 0x6FEB, 0xC0DE, 0x6FEF, 0xC0DF, 0x6F80, 0xC0E0, 0x6FEC, 0xC0E1, 0x6FE1, 0xC0E2, 0x6FE9, 0xC0E3, 0x6FD5, 0xC0E4, 0x6FEE, + 0xC0E5, 0x6FF0, 0xC0E6, 0x71E7, 0xC0E7, 0x71DF, 0xC0E8, 0x71EE, 0xC0E9, 0x71E6, 0xC0EA, 0x71E5, 0xC0EB, 0x71ED, 0xC0EC, 0x71EC, + 0xC0ED, 0x71F4, 0xC0EE, 0x71E0, 0xC0EF, 0x7235, 0xC0F0, 0x7246, 0xC0F1, 0x7370, 0xC0F2, 0x7372, 0xC0F3, 0x74A9, 0xC0F4, 0x74B0, + 0xC0F5, 0x74A6, 0xC0F6, 0x74A8, 0xC0F7, 0x7646, 0xC0F8, 0x7642, 0xC0F9, 0x764C, 0xC0FA, 0x76EA, 0xC0FB, 0x77B3, 0xC0FC, 0x77AA, + 0xC0FD, 0x77B0, 0xC0FE, 0x77AC, 0xC140, 0x77A7, 0xC141, 0x77AD, 0xC142, 0x77EF, 0xC143, 0x78F7, 0xC144, 0x78FA, 0xC145, 0x78F4, + 0xC146, 0x78EF, 0xC147, 0x7901, 0xC148, 0x79A7, 0xC149, 0x79AA, 0xC14A, 0x7A57, 0xC14B, 0x7ABF, 0xC14C, 0x7C07, 0xC14D, 0x7C0D, + 0xC14E, 0x7BFE, 0xC14F, 0x7BF7, 0xC150, 0x7C0C, 0xC151, 0x7BE0, 0xC152, 0x7CE0, 0xC153, 0x7CDC, 0xC154, 0x7CDE, 0xC155, 0x7CE2, + 0xC156, 0x7CDF, 0xC157, 0x7CD9, 0xC158, 0x7CDD, 0xC159, 0x7E2E, 0xC15A, 0x7E3E, 0xC15B, 0x7E46, 0xC15C, 0x7E37, 0xC15D, 0x7E32, + 0xC15E, 0x7E43, 0xC15F, 0x7E2B, 0xC160, 0x7E3D, 0xC161, 0x7E31, 0xC162, 0x7E45, 0xC163, 0x7E41, 0xC164, 0x7E34, 0xC165, 0x7E39, + 0xC166, 0x7E48, 0xC167, 0x7E35, 0xC168, 0x7E3F, 0xC169, 0x7E2F, 0xC16A, 0x7F44, 0xC16B, 0x7FF3, 0xC16C, 0x7FFC, 0xC16D, 0x8071, + 0xC16E, 0x8072, 0xC16F, 0x8070, 0xC170, 0x806F, 0xC171, 0x8073, 0xC172, 0x81C6, 0xC173, 0x81C3, 0xC174, 0x81BA, 0xC175, 0x81C2, + 0xC176, 0x81C0, 0xC177, 0x81BF, 0xC178, 0x81BD, 0xC179, 0x81C9, 0xC17A, 0x81BE, 0xC17B, 0x81E8, 0xC17C, 0x8209, 0xC17D, 0x8271, + 0xC17E, 0x85AA, 0xC1A1, 0x8584, 0xC1A2, 0x857E, 0xC1A3, 0x859C, 0xC1A4, 0x8591, 0xC1A5, 0x8594, 0xC1A6, 0x85AF, 0xC1A7, 0x859B, + 0xC1A8, 0x8587, 0xC1A9, 0x85A8, 0xC1AA, 0x858A, 0xC1AB, 0x8667, 0xC1AC, 0x87C0, 0xC1AD, 0x87D1, 0xC1AE, 0x87B3, 0xC1AF, 0x87D2, + 0xC1B0, 0x87C6, 0xC1B1, 0x87AB, 0xC1B2, 0x87BB, 0xC1B3, 0x87BA, 0xC1B4, 0x87C8, 0xC1B5, 0x87CB, 0xC1B6, 0x893B, 0xC1B7, 0x8936, + 0xC1B8, 0x8944, 0xC1B9, 0x8938, 0xC1BA, 0x893D, 0xC1BB, 0x89AC, 0xC1BC, 0x8B0E, 0xC1BD, 0x8B17, 0xC1BE, 0x8B19, 0xC1BF, 0x8B1B, + 0xC1C0, 0x8B0A, 0xC1C1, 0x8B20, 0xC1C2, 0x8B1D, 0xC1C3, 0x8B04, 0xC1C4, 0x8B10, 0xC1C5, 0x8C41, 0xC1C6, 0x8C3F, 0xC1C7, 0x8C73, + 0xC1C8, 0x8CFA, 0xC1C9, 0x8CFD, 0xC1CA, 0x8CFC, 0xC1CB, 0x8CF8, 0xC1CC, 0x8CFB, 0xC1CD, 0x8DA8, 0xC1CE, 0x8E49, 0xC1CF, 0x8E4B, + 0xC1D0, 0x8E48, 0xC1D1, 0x8E4A, 0xC1D2, 0x8F44, 0xC1D3, 0x8F3E, 0xC1D4, 0x8F42, 0xC1D5, 0x8F45, 0xC1D6, 0x8F3F, 0xC1D7, 0x907F, + 0xC1D8, 0x907D, 0xC1D9, 0x9084, 0xC1DA, 0x9081, 0xC1DB, 0x9082, 0xC1DC, 0x9080, 0xC1DD, 0x9139, 0xC1DE, 0x91A3, 0xC1DF, 0x919E, + 0xC1E0, 0x919C, 0xC1E1, 0x934D, 0xC1E2, 0x9382, 0xC1E3, 0x9328, 0xC1E4, 0x9375, 0xC1E5, 0x934A, 0xC1E6, 0x9365, 0xC1E7, 0x934B, + 0xC1E8, 0x9318, 0xC1E9, 0x937E, 0xC1EA, 0x936C, 0xC1EB, 0x935B, 0xC1EC, 0x9370, 0xC1ED, 0x935A, 0xC1EE, 0x9354, 0xC1EF, 0x95CA, + 0xC1F0, 0x95CB, 0xC1F1, 0x95CC, 0xC1F2, 0x95C8, 0xC1F3, 0x95C6, 0xC1F4, 0x96B1, 0xC1F5, 0x96B8, 0xC1F6, 0x96D6, 0xC1F7, 0x971C, + 0xC1F8, 0x971E, 0xC1F9, 0x97A0, 0xC1FA, 0x97D3, 0xC1FB, 0x9846, 0xC1FC, 0x98B6, 0xC1FD, 0x9935, 0xC1FE, 0x9A01, 0xC240, 0x99FF, + 0xC241, 0x9BAE, 0xC242, 0x9BAB, 0xC243, 0x9BAA, 0xC244, 0x9BAD, 0xC245, 0x9D3B, 0xC246, 0x9D3F, 0xC247, 0x9E8B, 0xC248, 0x9ECF, + 0xC249, 0x9EDE, 0xC24A, 0x9EDC, 0xC24B, 0x9EDD, 0xC24C, 0x9EDB, 0xC24D, 0x9F3E, 0xC24E, 0x9F4B, 0xC24F, 0x53E2, 0xC250, 0x5695, + 0xC251, 0x56AE, 0xC252, 0x58D9, 0xC253, 0x58D8, 0xC254, 0x5B38, 0xC255, 0x5F5D, 0xC256, 0x61E3, 0xC257, 0x6233, 0xC258, 0x64F4, + 0xC259, 0x64F2, 0xC25A, 0x64FE, 0xC25B, 0x6506, 0xC25C, 0x64FA, 0xC25D, 0x64FB, 0xC25E, 0x64F7, 0xC25F, 0x65B7, 0xC260, 0x66DC, + 0xC261, 0x6726, 0xC262, 0x6AB3, 0xC263, 0x6AAC, 0xC264, 0x6AC3, 0xC265, 0x6ABB, 0xC266, 0x6AB8, 0xC267, 0x6AC2, 0xC268, 0x6AAE, + 0xC269, 0x6AAF, 0xC26A, 0x6B5F, 0xC26B, 0x6B78, 0xC26C, 0x6BAF, 0xC26D, 0x7009, 0xC26E, 0x700B, 0xC26F, 0x6FFE, 0xC270, 0x7006, + 0xC271, 0x6FFA, 0xC272, 0x7011, 0xC273, 0x700F, 0xC274, 0x71FB, 0xC275, 0x71FC, 0xC276, 0x71FE, 0xC277, 0x71F8, 0xC278, 0x7377, + 0xC279, 0x7375, 0xC27A, 0x74A7, 0xC27B, 0x74BF, 0xC27C, 0x7515, 0xC27D, 0x7656, 0xC27E, 0x7658, 0xC2A1, 0x7652, 0xC2A2, 0x77BD, + 0xC2A3, 0x77BF, 0xC2A4, 0x77BB, 0xC2A5, 0x77BC, 0xC2A6, 0x790E, 0xC2A7, 0x79AE, 0xC2A8, 0x7A61, 0xC2A9, 0x7A62, 0xC2AA, 0x7A60, + 0xC2AB, 0x7AC4, 0xC2AC, 0x7AC5, 0xC2AD, 0x7C2B, 0xC2AE, 0x7C27, 0xC2AF, 0x7C2A, 0xC2B0, 0x7C1E, 0xC2B1, 0x7C23, 0xC2B2, 0x7C21, + 0xC2B3, 0x7CE7, 0xC2B4, 0x7E54, 0xC2B5, 0x7E55, 0xC2B6, 0x7E5E, 0xC2B7, 0x7E5A, 0xC2B8, 0x7E61, 0xC2B9, 0x7E52, 0xC2BA, 0x7E59, + 0xC2BB, 0x7F48, 0xC2BC, 0x7FF9, 0xC2BD, 0x7FFB, 0xC2BE, 0x8077, 0xC2BF, 0x8076, 0xC2C0, 0x81CD, 0xC2C1, 0x81CF, 0xC2C2, 0x820A, + 0xC2C3, 0x85CF, 0xC2C4, 0x85A9, 0xC2C5, 0x85CD, 0xC2C6, 0x85D0, 0xC2C7, 0x85C9, 0xC2C8, 0x85B0, 0xC2C9, 0x85BA, 0xC2CA, 0x85B9, + 0xC2CB, 0x85A6, 0xC2CC, 0x87EF, 0xC2CD, 0x87EC, 0xC2CE, 0x87F2, 0xC2CF, 0x87E0, 0xC2D0, 0x8986, 0xC2D1, 0x89B2, 0xC2D2, 0x89F4, + 0xC2D3, 0x8B28, 0xC2D4, 0x8B39, 0xC2D5, 0x8B2C, 0xC2D6, 0x8B2B, 0xC2D7, 0x8C50, 0xC2D8, 0x8D05, 0xC2D9, 0x8E59, 0xC2DA, 0x8E63, + 0xC2DB, 0x8E66, 0xC2DC, 0x8E64, 0xC2DD, 0x8E5F, 0xC2DE, 0x8E55, 0xC2DF, 0x8EC0, 0xC2E0, 0x8F49, 0xC2E1, 0x8F4D, 0xC2E2, 0x9087, + 0xC2E3, 0x9083, 0xC2E4, 0x9088, 0xC2E5, 0x91AB, 0xC2E6, 0x91AC, 0xC2E7, 0x91D0, 0xC2E8, 0x9394, 0xC2E9, 0x938A, 0xC2EA, 0x9396, + 0xC2EB, 0x93A2, 0xC2EC, 0x93B3, 0xC2ED, 0x93AE, 0xC2EE, 0x93AC, 0xC2EF, 0x93B0, 0xC2F0, 0x9398, 0xC2F1, 0x939A, 0xC2F2, 0x9397, + 0xC2F3, 0x95D4, 0xC2F4, 0x95D6, 0xC2F5, 0x95D0, 0xC2F6, 0x95D5, 0xC2F7, 0x96E2, 0xC2F8, 0x96DC, 0xC2F9, 0x96D9, 0xC2FA, 0x96DB, + 0xC2FB, 0x96DE, 0xC2FC, 0x9724, 0xC2FD, 0x97A3, 0xC2FE, 0x97A6, 0xC340, 0x97AD, 0xC341, 0x97F9, 0xC342, 0x984D, 0xC343, 0x984F, + 0xC344, 0x984C, 0xC345, 0x984E, 0xC346, 0x9853, 0xC347, 0x98BA, 0xC348, 0x993E, 0xC349, 0x993F, 0xC34A, 0x993D, 0xC34B, 0x992E, + 0xC34C, 0x99A5, 0xC34D, 0x9A0E, 0xC34E, 0x9AC1, 0xC34F, 0x9B03, 0xC350, 0x9B06, 0xC351, 0x9B4F, 0xC352, 0x9B4E, 0xC353, 0x9B4D, + 0xC354, 0x9BCA, 0xC355, 0x9BC9, 0xC356, 0x9BFD, 0xC357, 0x9BC8, 0xC358, 0x9BC0, 0xC359, 0x9D51, 0xC35A, 0x9D5D, 0xC35B, 0x9D60, + 0xC35C, 0x9EE0, 0xC35D, 0x9F15, 0xC35E, 0x9F2C, 0xC35F, 0x5133, 0xC360, 0x56A5, 0xC361, 0x58DE, 0xC362, 0x58DF, 0xC363, 0x58E2, + 0xC364, 0x5BF5, 0xC365, 0x9F90, 0xC366, 0x5EEC, 0xC367, 0x61F2, 0xC368, 0x61F7, 0xC369, 0x61F6, 0xC36A, 0x61F5, 0xC36B, 0x6500, + 0xC36C, 0x650F, 0xC36D, 0x66E0, 0xC36E, 0x66DD, 0xC36F, 0x6AE5, 0xC370, 0x6ADD, 0xC371, 0x6ADA, 0xC372, 0x6AD3, 0xC373, 0x701B, + 0xC374, 0x701F, 0xC375, 0x7028, 0xC376, 0x701A, 0xC377, 0x701D, 0xC378, 0x7015, 0xC379, 0x7018, 0xC37A, 0x7206, 0xC37B, 0x720D, + 0xC37C, 0x7258, 0xC37D, 0x72A2, 0xC37E, 0x7378, 0xC3A1, 0x737A, 0xC3A2, 0x74BD, 0xC3A3, 0x74CA, 0xC3A4, 0x74E3, 0xC3A5, 0x7587, + 0xC3A6, 0x7586, 0xC3A7, 0x765F, 0xC3A8, 0x7661, 0xC3A9, 0x77C7, 0xC3AA, 0x7919, 0xC3AB, 0x79B1, 0xC3AC, 0x7A6B, 0xC3AD, 0x7A69, + 0xC3AE, 0x7C3E, 0xC3AF, 0x7C3F, 0xC3B0, 0x7C38, 0xC3B1, 0x7C3D, 0xC3B2, 0x7C37, 0xC3B3, 0x7C40, 0xC3B4, 0x7E6B, 0xC3B5, 0x7E6D, + 0xC3B6, 0x7E79, 0xC3B7, 0x7E69, 0xC3B8, 0x7E6A, 0xC3B9, 0x7F85, 0xC3BA, 0x7E73, 0xC3BB, 0x7FB6, 0xC3BC, 0x7FB9, 0xC3BD, 0x7FB8, + 0xC3BE, 0x81D8, 0xC3BF, 0x85E9, 0xC3C0, 0x85DD, 0xC3C1, 0x85EA, 0xC3C2, 0x85D5, 0xC3C3, 0x85E4, 0xC3C4, 0x85E5, 0xC3C5, 0x85F7, + 0xC3C6, 0x87FB, 0xC3C7, 0x8805, 0xC3C8, 0x880D, 0xC3C9, 0x87F9, 0xC3CA, 0x87FE, 0xC3CB, 0x8960, 0xC3CC, 0x895F, 0xC3CD, 0x8956, + 0xC3CE, 0x895E, 0xC3CF, 0x8B41, 0xC3D0, 0x8B5C, 0xC3D1, 0x8B58, 0xC3D2, 0x8B49, 0xC3D3, 0x8B5A, 0xC3D4, 0x8B4E, 0xC3D5, 0x8B4F, + 0xC3D6, 0x8B46, 0xC3D7, 0x8B59, 0xC3D8, 0x8D08, 0xC3D9, 0x8D0A, 0xC3DA, 0x8E7C, 0xC3DB, 0x8E72, 0xC3DC, 0x8E87, 0xC3DD, 0x8E76, + 0xC3DE, 0x8E6C, 0xC3DF, 0x8E7A, 0xC3E0, 0x8E74, 0xC3E1, 0x8F54, 0xC3E2, 0x8F4E, 0xC3E3, 0x8FAD, 0xC3E4, 0x908A, 0xC3E5, 0x908B, + 0xC3E6, 0x91B1, 0xC3E7, 0x91AE, 0xC3E8, 0x93E1, 0xC3E9, 0x93D1, 0xC3EA, 0x93DF, 0xC3EB, 0x93C3, 0xC3EC, 0x93C8, 0xC3ED, 0x93DC, + 0xC3EE, 0x93DD, 0xC3EF, 0x93D6, 0xC3F0, 0x93E2, 0xC3F1, 0x93CD, 0xC3F2, 0x93D8, 0xC3F3, 0x93E4, 0xC3F4, 0x93D7, 0xC3F5, 0x93E8, + 0xC3F6, 0x95DC, 0xC3F7, 0x96B4, 0xC3F8, 0x96E3, 0xC3F9, 0x972A, 0xC3FA, 0x9727, 0xC3FB, 0x9761, 0xC3FC, 0x97DC, 0xC3FD, 0x97FB, + 0xC3FE, 0x985E, 0xC440, 0x9858, 0xC441, 0x985B, 0xC442, 0x98BC, 0xC443, 0x9945, 0xC444, 0x9949, 0xC445, 0x9A16, 0xC446, 0x9A19, + 0xC447, 0x9B0D, 0xC448, 0x9BE8, 0xC449, 0x9BE7, 0xC44A, 0x9BD6, 0xC44B, 0x9BDB, 0xC44C, 0x9D89, 0xC44D, 0x9D61, 0xC44E, 0x9D72, + 0xC44F, 0x9D6A, 0xC450, 0x9D6C, 0xC451, 0x9E92, 0xC452, 0x9E97, 0xC453, 0x9E93, 0xC454, 0x9EB4, 0xC455, 0x52F8, 0xC456, 0x56A8, + 0xC457, 0x56B7, 0xC458, 0x56B6, 0xC459, 0x56B4, 0xC45A, 0x56BC, 0xC45B, 0x58E4, 0xC45C, 0x5B40, 0xC45D, 0x5B43, 0xC45E, 0x5B7D, + 0xC45F, 0x5BF6, 0xC460, 0x5DC9, 0xC461, 0x61F8, 0xC462, 0x61FA, 0xC463, 0x6518, 0xC464, 0x6514, 0xC465, 0x6519, 0xC466, 0x66E6, + 0xC467, 0x6727, 0xC468, 0x6AEC, 0xC469, 0x703E, 0xC46A, 0x7030, 0xC46B, 0x7032, 0xC46C, 0x7210, 0xC46D, 0x737B, 0xC46E, 0x74CF, + 0xC46F, 0x7662, 0xC470, 0x7665, 0xC471, 0x7926, 0xC472, 0x792A, 0xC473, 0x792C, 0xC474, 0x792B, 0xC475, 0x7AC7, 0xC476, 0x7AF6, + 0xC477, 0x7C4C, 0xC478, 0x7C43, 0xC479, 0x7C4D, 0xC47A, 0x7CEF, 0xC47B, 0x7CF0, 0xC47C, 0x8FAE, 0xC47D, 0x7E7D, 0xC47E, 0x7E7C, + 0xC4A1, 0x7E82, 0xC4A2, 0x7F4C, 0xC4A3, 0x8000, 0xC4A4, 0x81DA, 0xC4A5, 0x8266, 0xC4A6, 0x85FB, 0xC4A7, 0x85F9, 0xC4A8, 0x8611, + 0xC4A9, 0x85FA, 0xC4AA, 0x8606, 0xC4AB, 0x860B, 0xC4AC, 0x8607, 0xC4AD, 0x860A, 0xC4AE, 0x8814, 0xC4AF, 0x8815, 0xC4B0, 0x8964, + 0xC4B1, 0x89BA, 0xC4B2, 0x89F8, 0xC4B3, 0x8B70, 0xC4B4, 0x8B6C, 0xC4B5, 0x8B66, 0xC4B6, 0x8B6F, 0xC4B7, 0x8B5F, 0xC4B8, 0x8B6B, + 0xC4B9, 0x8D0F, 0xC4BA, 0x8D0D, 0xC4BB, 0x8E89, 0xC4BC, 0x8E81, 0xC4BD, 0x8E85, 0xC4BE, 0x8E82, 0xC4BF, 0x91B4, 0xC4C0, 0x91CB, + 0xC4C1, 0x9418, 0xC4C2, 0x9403, 0xC4C3, 0x93FD, 0xC4C4, 0x95E1, 0xC4C5, 0x9730, 0xC4C6, 0x98C4, 0xC4C7, 0x9952, 0xC4C8, 0x9951, + 0xC4C9, 0x99A8, 0xC4CA, 0x9A2B, 0xC4CB, 0x9A30, 0xC4CC, 0x9A37, 0xC4CD, 0x9A35, 0xC4CE, 0x9C13, 0xC4CF, 0x9C0D, 0xC4D0, 0x9E79, + 0xC4D1, 0x9EB5, 0xC4D2, 0x9EE8, 0xC4D3, 0x9F2F, 0xC4D4, 0x9F5F, 0xC4D5, 0x9F63, 0xC4D6, 0x9F61, 0xC4D7, 0x5137, 0xC4D8, 0x5138, + 0xC4D9, 0x56C1, 0xC4DA, 0x56C0, 0xC4DB, 0x56C2, 0xC4DC, 0x5914, 0xC4DD, 0x5C6C, 0xC4DE, 0x5DCD, 0xC4DF, 0x61FC, 0xC4E0, 0x61FE, + 0xC4E1, 0x651D, 0xC4E2, 0x651C, 0xC4E3, 0x6595, 0xC4E4, 0x66E9, 0xC4E5, 0x6AFB, 0xC4E6, 0x6B04, 0xC4E7, 0x6AFA, 0xC4E8, 0x6BB2, + 0xC4E9, 0x704C, 0xC4EA, 0x721B, 0xC4EB, 0x72A7, 0xC4EC, 0x74D6, 0xC4ED, 0x74D4, 0xC4EE, 0x7669, 0xC4EF, 0x77D3, 0xC4F0, 0x7C50, + 0xC4F1, 0x7E8F, 0xC4F2, 0x7E8C, 0xC4F3, 0x7FBC, 0xC4F4, 0x8617, 0xC4F5, 0x862D, 0xC4F6, 0x861A, 0xC4F7, 0x8823, 0xC4F8, 0x8822, + 0xC4F9, 0x8821, 0xC4FA, 0x881F, 0xC4FB, 0x896A, 0xC4FC, 0x896C, 0xC4FD, 0x89BD, 0xC4FE, 0x8B74, 0xC540, 0x8B77, 0xC541, 0x8B7D, + 0xC542, 0x8D13, 0xC543, 0x8E8A, 0xC544, 0x8E8D, 0xC545, 0x8E8B, 0xC546, 0x8F5F, 0xC547, 0x8FAF, 0xC548, 0x91BA, 0xC549, 0x942E, + 0xC54A, 0x9433, 0xC54B, 0x9435, 0xC54C, 0x943A, 0xC54D, 0x9438, 0xC54E, 0x9432, 0xC54F, 0x942B, 0xC550, 0x95E2, 0xC551, 0x9738, + 0xC552, 0x9739, 0xC553, 0x9732, 0xC554, 0x97FF, 0xC555, 0x9867, 0xC556, 0x9865, 0xC557, 0x9957, 0xC558, 0x9A45, 0xC559, 0x9A43, + 0xC55A, 0x9A40, 0xC55B, 0x9A3E, 0xC55C, 0x9ACF, 0xC55D, 0x9B54, 0xC55E, 0x9B51, 0xC55F, 0x9C2D, 0xC560, 0x9C25, 0xC561, 0x9DAF, + 0xC562, 0x9DB4, 0xC563, 0x9DC2, 0xC564, 0x9DB8, 0xC565, 0x9E9D, 0xC566, 0x9EEF, 0xC567, 0x9F19, 0xC568, 0x9F5C, 0xC569, 0x9F66, + 0xC56A, 0x9F67, 0xC56B, 0x513C, 0xC56C, 0x513B, 0xC56D, 0x56C8, 0xC56E, 0x56CA, 0xC56F, 0x56C9, 0xC570, 0x5B7F, 0xC571, 0x5DD4, + 0xC572, 0x5DD2, 0xC573, 0x5F4E, 0xC574, 0x61FF, 0xC575, 0x6524, 0xC576, 0x6B0A, 0xC577, 0x6B61, 0xC578, 0x7051, 0xC579, 0x7058, + 0xC57A, 0x7380, 0xC57B, 0x74E4, 0xC57C, 0x758A, 0xC57D, 0x766E, 0xC57E, 0x766C, 0xC5A1, 0x79B3, 0xC5A2, 0x7C60, 0xC5A3, 0x7C5F, + 0xC5A4, 0x807E, 0xC5A5, 0x807D, 0xC5A6, 0x81DF, 0xC5A7, 0x8972, 0xC5A8, 0x896F, 0xC5A9, 0x89FC, 0xC5AA, 0x8B80, 0xC5AB, 0x8D16, + 0xC5AC, 0x8D17, 0xC5AD, 0x8E91, 0xC5AE, 0x8E93, 0xC5AF, 0x8F61, 0xC5B0, 0x9148, 0xC5B1, 0x9444, 0xC5B2, 0x9451, 0xC5B3, 0x9452, + 0xC5B4, 0x973D, 0xC5B5, 0x973E, 0xC5B6, 0x97C3, 0xC5B7, 0x97C1, 0xC5B8, 0x986B, 0xC5B9, 0x9955, 0xC5BA, 0x9A55, 0xC5BB, 0x9A4D, + 0xC5BC, 0x9AD2, 0xC5BD, 0x9B1A, 0xC5BE, 0x9C49, 0xC5BF, 0x9C31, 0xC5C0, 0x9C3E, 0xC5C1, 0x9C3B, 0xC5C2, 0x9DD3, 0xC5C3, 0x9DD7, + 0xC5C4, 0x9F34, 0xC5C5, 0x9F6C, 0xC5C6, 0x9F6A, 0xC5C7, 0x9F94, 0xC5C8, 0x56CC, 0xC5C9, 0x5DD6, 0xC5CA, 0x6200, 0xC5CB, 0x6523, + 0xC5CC, 0x652B, 0xC5CD, 0x652A, 0xC5CE, 0x66EC, 0xC5CF, 0x6B10, 0xC5D0, 0x74DA, 0xC5D1, 0x7ACA, 0xC5D2, 0x7C64, 0xC5D3, 0x7C63, + 0xC5D4, 0x7C65, 0xC5D5, 0x7E93, 0xC5D6, 0x7E96, 0xC5D7, 0x7E94, 0xC5D8, 0x81E2, 0xC5D9, 0x8638, 0xC5DA, 0x863F, 0xC5DB, 0x8831, + 0xC5DC, 0x8B8A, 0xC5DD, 0x9090, 0xC5DE, 0x908F, 0xC5DF, 0x9463, 0xC5E0, 0x9460, 0xC5E1, 0x9464, 0xC5E2, 0x9768, 0xC5E3, 0x986F, + 0xC5E4, 0x995C, 0xC5E5, 0x9A5A, 0xC5E6, 0x9A5B, 0xC5E7, 0x9A57, 0xC5E8, 0x9AD3, 0xC5E9, 0x9AD4, 0xC5EA, 0x9AD1, 0xC5EB, 0x9C54, + 0xC5EC, 0x9C57, 0xC5ED, 0x9C56, 0xC5EE, 0x9DE5, 0xC5EF, 0x9E9F, 0xC5F0, 0x9EF4, 0xC5F1, 0x56D1, 0xC5F2, 0x58E9, 0xC5F3, 0x652C, + 0xC5F4, 0x705E, 0xC5F5, 0x7671, 0xC5F6, 0x7672, 0xC5F7, 0x77D7, 0xC5F8, 0x7F50, 0xC5F9, 0x7F88, 0xC5FA, 0x8836, 0xC5FB, 0x8839, + 0xC5FC, 0x8862, 0xC5FD, 0x8B93, 0xC5FE, 0x8B92, 0xC640, 0x8B96, 0xC641, 0x8277, 0xC642, 0x8D1B, 0xC643, 0x91C0, 0xC644, 0x946A, + 0xC645, 0x9742, 0xC646, 0x9748, 0xC647, 0x9744, 0xC648, 0x97C6, 0xC649, 0x9870, 0xC64A, 0x9A5F, 0xC64B, 0x9B22, 0xC64C, 0x9B58, + 0xC64D, 0x9C5F, 0xC64E, 0x9DF9, 0xC64F, 0x9DFA, 0xC650, 0x9E7C, 0xC651, 0x9E7D, 0xC652, 0x9F07, 0xC653, 0x9F77, 0xC654, 0x9F72, + 0xC655, 0x5EF3, 0xC656, 0x6B16, 0xC657, 0x7063, 0xC658, 0x7C6C, 0xC659, 0x7C6E, 0xC65A, 0x883B, 0xC65B, 0x89C0, 0xC65C, 0x8EA1, + 0xC65D, 0x91C1, 0xC65E, 0x9472, 0xC65F, 0x9470, 0xC660, 0x9871, 0xC661, 0x995E, 0xC662, 0x9AD6, 0xC663, 0x9B23, 0xC664, 0x9ECC, + 0xC665, 0x7064, 0xC666, 0x77DA, 0xC667, 0x8B9A, 0xC668, 0x9477, 0xC669, 0x97C9, 0xC66A, 0x9A62, 0xC66B, 0x9A65, 0xC66C, 0x7E9C, + 0xC66D, 0x8B9C, 0xC66E, 0x8EAA, 0xC66F, 0x91C5, 0xC670, 0x947D, 0xC671, 0x947E, 0xC672, 0x947C, 0xC673, 0x9C77, 0xC674, 0x9C78, + 0xC675, 0x9EF7, 0xC676, 0x8C54, 0xC677, 0x947F, 0xC678, 0x9E1A, 0xC679, 0x7228, 0xC67A, 0x9A6A, 0xC67B, 0x9B31, 0xC67C, 0x9E1B, + 0xC67D, 0x9E1E, 0xC67E, 0x7C72, 0xC940, 0x4E42, 0xC941, 0x4E5C, 0xC942, 0x51F5, 0xC943, 0x531A, 0xC944, 0x5382, 0xC945, 0x4E07, + 0xC946, 0x4E0C, 0xC947, 0x4E47, 0xC948, 0x4E8D, 0xC949, 0x56D7, 0xC94A, 0xFA0C, 0xC94B, 0x5C6E, 0xC94C, 0x5F73, 0xC94D, 0x4E0F, + 0xC94E, 0x5187, 0xC94F, 0x4E0E, 0xC950, 0x4E2E, 0xC951, 0x4E93, 0xC952, 0x4EC2, 0xC953, 0x4EC9, 0xC954, 0x4EC8, 0xC955, 0x5198, + 0xC956, 0x52FC, 0xC957, 0x536C, 0xC958, 0x53B9, 0xC959, 0x5720, 0xC95A, 0x5903, 0xC95B, 0x592C, 0xC95C, 0x5C10, 0xC95D, 0x5DFF, + 0xC95E, 0x65E1, 0xC95F, 0x6BB3, 0xC960, 0x6BCC, 0xC961, 0x6C14, 0xC962, 0x723F, 0xC963, 0x4E31, 0xC964, 0x4E3C, 0xC965, 0x4EE8, + 0xC966, 0x4EDC, 0xC967, 0x4EE9, 0xC968, 0x4EE1, 0xC969, 0x4EDD, 0xC96A, 0x4EDA, 0xC96B, 0x520C, 0xC96C, 0x531C, 0xC96D, 0x534C, + 0xC96E, 0x5722, 0xC96F, 0x5723, 0xC970, 0x5917, 0xC971, 0x592F, 0xC972, 0x5B81, 0xC973, 0x5B84, 0xC974, 0x5C12, 0xC975, 0x5C3B, + 0xC976, 0x5C74, 0xC977, 0x5C73, 0xC978, 0x5E04, 0xC979, 0x5E80, 0xC97A, 0x5E82, 0xC97B, 0x5FC9, 0xC97C, 0x6209, 0xC97D, 0x6250, + 0xC97E, 0x6C15, 0xC9A1, 0x6C36, 0xC9A2, 0x6C43, 0xC9A3, 0x6C3F, 0xC9A4, 0x6C3B, 0xC9A5, 0x72AE, 0xC9A6, 0x72B0, 0xC9A7, 0x738A, + 0xC9A8, 0x79B8, 0xC9A9, 0x808A, 0xC9AA, 0x961E, 0xC9AB, 0x4F0E, 0xC9AC, 0x4F18, 0xC9AD, 0x4F2C, 0xC9AE, 0x4EF5, 0xC9AF, 0x4F14, + 0xC9B0, 0x4EF1, 0xC9B1, 0x4F00, 0xC9B2, 0x4EF7, 0xC9B3, 0x4F08, 0xC9B4, 0x4F1D, 0xC9B5, 0x4F02, 0xC9B6, 0x4F05, 0xC9B7, 0x4F22, + 0xC9B8, 0x4F13, 0xC9B9, 0x4F04, 0xC9BA, 0x4EF4, 0xC9BB, 0x4F12, 0xC9BC, 0x51B1, 0xC9BD, 0x5213, 0xC9BE, 0x5209, 0xC9BF, 0x5210, + 0xC9C0, 0x52A6, 0xC9C1, 0x5322, 0xC9C2, 0x531F, 0xC9C3, 0x534D, 0xC9C4, 0x538A, 0xC9C5, 0x5407, 0xC9C6, 0x56E1, 0xC9C7, 0x56DF, + 0xC9C8, 0x572E, 0xC9C9, 0x572A, 0xC9CA, 0x5734, 0xC9CB, 0x593C, 0xC9CC, 0x5980, 0xC9CD, 0x597C, 0xC9CE, 0x5985, 0xC9CF, 0x597B, + 0xC9D0, 0x597E, 0xC9D1, 0x5977, 0xC9D2, 0x597F, 0xC9D3, 0x5B56, 0xC9D4, 0x5C15, 0xC9D5, 0x5C25, 0xC9D6, 0x5C7C, 0xC9D7, 0x5C7A, + 0xC9D8, 0x5C7B, 0xC9D9, 0x5C7E, 0xC9DA, 0x5DDF, 0xC9DB, 0x5E75, 0xC9DC, 0x5E84, 0xC9DD, 0x5F02, 0xC9DE, 0x5F1A, 0xC9DF, 0x5F74, + 0xC9E0, 0x5FD5, 0xC9E1, 0x5FD4, 0xC9E2, 0x5FCF, 0xC9E3, 0x625C, 0xC9E4, 0x625E, 0xC9E5, 0x6264, 0xC9E6, 0x6261, 0xC9E7, 0x6266, + 0xC9E8, 0x6262, 0xC9E9, 0x6259, 0xC9EA, 0x6260, 0xC9EB, 0x625A, 0xC9EC, 0x6265, 0xC9ED, 0x65EF, 0xC9EE, 0x65EE, 0xC9EF, 0x673E, + 0xC9F0, 0x6739, 0xC9F1, 0x6738, 0xC9F2, 0x673B, 0xC9F3, 0x673A, 0xC9F4, 0x673F, 0xC9F5, 0x673C, 0xC9F6, 0x6733, 0xC9F7, 0x6C18, + 0xC9F8, 0x6C46, 0xC9F9, 0x6C52, 0xC9FA, 0x6C5C, 0xC9FB, 0x6C4F, 0xC9FC, 0x6C4A, 0xC9FD, 0x6C54, 0xC9FE, 0x6C4B, 0xCA40, 0x6C4C, + 0xCA41, 0x7071, 0xCA42, 0x725E, 0xCA43, 0x72B4, 0xCA44, 0x72B5, 0xCA45, 0x738E, 0xCA46, 0x752A, 0xCA47, 0x767F, 0xCA48, 0x7A75, + 0xCA49, 0x7F51, 0xCA4A, 0x8278, 0xCA4B, 0x827C, 0xCA4C, 0x8280, 0xCA4D, 0x827D, 0xCA4E, 0x827F, 0xCA4F, 0x864D, 0xCA50, 0x897E, + 0xCA51, 0x9099, 0xCA52, 0x9097, 0xCA53, 0x9098, 0xCA54, 0x909B, 0xCA55, 0x9094, 0xCA56, 0x9622, 0xCA57, 0x9624, 0xCA58, 0x9620, + 0xCA59, 0x9623, 0xCA5A, 0x4F56, 0xCA5B, 0x4F3B, 0xCA5C, 0x4F62, 0xCA5D, 0x4F49, 0xCA5E, 0x4F53, 0xCA5F, 0x4F64, 0xCA60, 0x4F3E, + 0xCA61, 0x4F67, 0xCA62, 0x4F52, 0xCA63, 0x4F5F, 0xCA64, 0x4F41, 0xCA65, 0x4F58, 0xCA66, 0x4F2D, 0xCA67, 0x4F33, 0xCA68, 0x4F3F, + 0xCA69, 0x4F61, 0xCA6A, 0x518F, 0xCA6B, 0x51B9, 0xCA6C, 0x521C, 0xCA6D, 0x521E, 0xCA6E, 0x5221, 0xCA6F, 0x52AD, 0xCA70, 0x52AE, + 0xCA71, 0x5309, 0xCA72, 0x5363, 0xCA73, 0x5372, 0xCA74, 0x538E, 0xCA75, 0x538F, 0xCA76, 0x5430, 0xCA77, 0x5437, 0xCA78, 0x542A, + 0xCA79, 0x5454, 0xCA7A, 0x5445, 0xCA7B, 0x5419, 0xCA7C, 0x541C, 0xCA7D, 0x5425, 0xCA7E, 0x5418, 0xCAA1, 0x543D, 0xCAA2, 0x544F, + 0xCAA3, 0x5441, 0xCAA4, 0x5428, 0xCAA5, 0x5424, 0xCAA6, 0x5447, 0xCAA7, 0x56EE, 0xCAA8, 0x56E7, 0xCAA9, 0x56E5, 0xCAAA, 0x5741, + 0xCAAB, 0x5745, 0xCAAC, 0x574C, 0xCAAD, 0x5749, 0xCAAE, 0x574B, 0xCAAF, 0x5752, 0xCAB0, 0x5906, 0xCAB1, 0x5940, 0xCAB2, 0x59A6, + 0xCAB3, 0x5998, 0xCAB4, 0x59A0, 0xCAB5, 0x5997, 0xCAB6, 0x598E, 0xCAB7, 0x59A2, 0xCAB8, 0x5990, 0xCAB9, 0x598F, 0xCABA, 0x59A7, + 0xCABB, 0x59A1, 0xCABC, 0x5B8E, 0xCABD, 0x5B92, 0xCABE, 0x5C28, 0xCABF, 0x5C2A, 0xCAC0, 0x5C8D, 0xCAC1, 0x5C8F, 0xCAC2, 0x5C88, + 0xCAC3, 0x5C8B, 0xCAC4, 0x5C89, 0xCAC5, 0x5C92, 0xCAC6, 0x5C8A, 0xCAC7, 0x5C86, 0xCAC8, 0x5C93, 0xCAC9, 0x5C95, 0xCACA, 0x5DE0, + 0xCACB, 0x5E0A, 0xCACC, 0x5E0E, 0xCACD, 0x5E8B, 0xCACE, 0x5E89, 0xCACF, 0x5E8C, 0xCAD0, 0x5E88, 0xCAD1, 0x5E8D, 0xCAD2, 0x5F05, + 0xCAD3, 0x5F1D, 0xCAD4, 0x5F78, 0xCAD5, 0x5F76, 0xCAD6, 0x5FD2, 0xCAD7, 0x5FD1, 0xCAD8, 0x5FD0, 0xCAD9, 0x5FED, 0xCADA, 0x5FE8, + 0xCADB, 0x5FEE, 0xCADC, 0x5FF3, 0xCADD, 0x5FE1, 0xCADE, 0x5FE4, 0xCADF, 0x5FE3, 0xCAE0, 0x5FFA, 0xCAE1, 0x5FEF, 0xCAE2, 0x5FF7, + 0xCAE3, 0x5FFB, 0xCAE4, 0x6000, 0xCAE5, 0x5FF4, 0xCAE6, 0x623A, 0xCAE7, 0x6283, 0xCAE8, 0x628C, 0xCAE9, 0x628E, 0xCAEA, 0x628F, + 0xCAEB, 0x6294, 0xCAEC, 0x6287, 0xCAED, 0x6271, 0xCAEE, 0x627B, 0xCAEF, 0x627A, 0xCAF0, 0x6270, 0xCAF1, 0x6281, 0xCAF2, 0x6288, + 0xCAF3, 0x6277, 0xCAF4, 0x627D, 0xCAF5, 0x6272, 0xCAF6, 0x6274, 0xCAF7, 0x6537, 0xCAF8, 0x65F0, 0xCAF9, 0x65F4, 0xCAFA, 0x65F3, + 0xCAFB, 0x65F2, 0xCAFC, 0x65F5, 0xCAFD, 0x6745, 0xCAFE, 0x6747, 0xCB40, 0x6759, 0xCB41, 0x6755, 0xCB42, 0x674C, 0xCB43, 0x6748, + 0xCB44, 0x675D, 0xCB45, 0x674D, 0xCB46, 0x675A, 0xCB47, 0x674B, 0xCB48, 0x6BD0, 0xCB49, 0x6C19, 0xCB4A, 0x6C1A, 0xCB4B, 0x6C78, + 0xCB4C, 0x6C67, 0xCB4D, 0x6C6B, 0xCB4E, 0x6C84, 0xCB4F, 0x6C8B, 0xCB50, 0x6C8F, 0xCB51, 0x6C71, 0xCB52, 0x6C6F, 0xCB53, 0x6C69, + 0xCB54, 0x6C9A, 0xCB55, 0x6C6D, 0xCB56, 0x6C87, 0xCB57, 0x6C95, 0xCB58, 0x6C9C, 0xCB59, 0x6C66, 0xCB5A, 0x6C73, 0xCB5B, 0x6C65, + 0xCB5C, 0x6C7B, 0xCB5D, 0x6C8E, 0xCB5E, 0x7074, 0xCB5F, 0x707A, 0xCB60, 0x7263, 0xCB61, 0x72BF, 0xCB62, 0x72BD, 0xCB63, 0x72C3, + 0xCB64, 0x72C6, 0xCB65, 0x72C1, 0xCB66, 0x72BA, 0xCB67, 0x72C5, 0xCB68, 0x7395, 0xCB69, 0x7397, 0xCB6A, 0x7393, 0xCB6B, 0x7394, + 0xCB6C, 0x7392, 0xCB6D, 0x753A, 0xCB6E, 0x7539, 0xCB6F, 0x7594, 0xCB70, 0x7595, 0xCB71, 0x7681, 0xCB72, 0x793D, 0xCB73, 0x8034, + 0xCB74, 0x8095, 0xCB75, 0x8099, 0xCB76, 0x8090, 0xCB77, 0x8092, 0xCB78, 0x809C, 0xCB79, 0x8290, 0xCB7A, 0x828F, 0xCB7B, 0x8285, + 0xCB7C, 0x828E, 0xCB7D, 0x8291, 0xCB7E, 0x8293, 0xCBA1, 0x828A, 0xCBA2, 0x8283, 0xCBA3, 0x8284, 0xCBA4, 0x8C78, 0xCBA5, 0x8FC9, + 0xCBA6, 0x8FBF, 0xCBA7, 0x909F, 0xCBA8, 0x90A1, 0xCBA9, 0x90A5, 0xCBAA, 0x909E, 0xCBAB, 0x90A7, 0xCBAC, 0x90A0, 0xCBAD, 0x9630, + 0xCBAE, 0x9628, 0xCBAF, 0x962F, 0xCBB0, 0x962D, 0xCBB1, 0x4E33, 0xCBB2, 0x4F98, 0xCBB3, 0x4F7C, 0xCBB4, 0x4F85, 0xCBB5, 0x4F7D, + 0xCBB6, 0x4F80, 0xCBB7, 0x4F87, 0xCBB8, 0x4F76, 0xCBB9, 0x4F74, 0xCBBA, 0x4F89, 0xCBBB, 0x4F84, 0xCBBC, 0x4F77, 0xCBBD, 0x4F4C, + 0xCBBE, 0x4F97, 0xCBBF, 0x4F6A, 0xCBC0, 0x4F9A, 0xCBC1, 0x4F79, 0xCBC2, 0x4F81, 0xCBC3, 0x4F78, 0xCBC4, 0x4F90, 0xCBC5, 0x4F9C, + 0xCBC6, 0x4F94, 0xCBC7, 0x4F9E, 0xCBC8, 0x4F92, 0xCBC9, 0x4F82, 0xCBCA, 0x4F95, 0xCBCB, 0x4F6B, 0xCBCC, 0x4F6E, 0xCBCD, 0x519E, + 0xCBCE, 0x51BC, 0xCBCF, 0x51BE, 0xCBD0, 0x5235, 0xCBD1, 0x5232, 0xCBD2, 0x5233, 0xCBD3, 0x5246, 0xCBD4, 0x5231, 0xCBD5, 0x52BC, + 0xCBD6, 0x530A, 0xCBD7, 0x530B, 0xCBD8, 0x533C, 0xCBD9, 0x5392, 0xCBDA, 0x5394, 0xCBDB, 0x5487, 0xCBDC, 0x547F, 0xCBDD, 0x5481, + 0xCBDE, 0x5491, 0xCBDF, 0x5482, 0xCBE0, 0x5488, 0xCBE1, 0x546B, 0xCBE2, 0x547A, 0xCBE3, 0x547E, 0xCBE4, 0x5465, 0xCBE5, 0x546C, + 0xCBE6, 0x5474, 0xCBE7, 0x5466, 0xCBE8, 0x548D, 0xCBE9, 0x546F, 0xCBEA, 0x5461, 0xCBEB, 0x5460, 0xCBEC, 0x5498, 0xCBED, 0x5463, + 0xCBEE, 0x5467, 0xCBEF, 0x5464, 0xCBF0, 0x56F7, 0xCBF1, 0x56F9, 0xCBF2, 0x576F, 0xCBF3, 0x5772, 0xCBF4, 0x576D, 0xCBF5, 0x576B, + 0xCBF6, 0x5771, 0xCBF7, 0x5770, 0xCBF8, 0x5776, 0xCBF9, 0x5780, 0xCBFA, 0x5775, 0xCBFB, 0x577B, 0xCBFC, 0x5773, 0xCBFD, 0x5774, + 0xCBFE, 0x5762, 0xCC40, 0x5768, 0xCC41, 0x577D, 0xCC42, 0x590C, 0xCC43, 0x5945, 0xCC44, 0x59B5, 0xCC45, 0x59BA, 0xCC46, 0x59CF, + 0xCC47, 0x59CE, 0xCC48, 0x59B2, 0xCC49, 0x59CC, 0xCC4A, 0x59C1, 0xCC4B, 0x59B6, 0xCC4C, 0x59BC, 0xCC4D, 0x59C3, 0xCC4E, 0x59D6, + 0xCC4F, 0x59B1, 0xCC50, 0x59BD, 0xCC51, 0x59C0, 0xCC52, 0x59C8, 0xCC53, 0x59B4, 0xCC54, 0x59C7, 0xCC55, 0x5B62, 0xCC56, 0x5B65, + 0xCC57, 0x5B93, 0xCC58, 0x5B95, 0xCC59, 0x5C44, 0xCC5A, 0x5C47, 0xCC5B, 0x5CAE, 0xCC5C, 0x5CA4, 0xCC5D, 0x5CA0, 0xCC5E, 0x5CB5, + 0xCC5F, 0x5CAF, 0xCC60, 0x5CA8, 0xCC61, 0x5CAC, 0xCC62, 0x5C9F, 0xCC63, 0x5CA3, 0xCC64, 0x5CAD, 0xCC65, 0x5CA2, 0xCC66, 0x5CAA, + 0xCC67, 0x5CA7, 0xCC68, 0x5C9D, 0xCC69, 0x5CA5, 0xCC6A, 0x5CB6, 0xCC6B, 0x5CB0, 0xCC6C, 0x5CA6, 0xCC6D, 0x5E17, 0xCC6E, 0x5E14, + 0xCC6F, 0x5E19, 0xCC70, 0x5F28, 0xCC71, 0x5F22, 0xCC72, 0x5F23, 0xCC73, 0x5F24, 0xCC74, 0x5F54, 0xCC75, 0x5F82, 0xCC76, 0x5F7E, + 0xCC77, 0x5F7D, 0xCC78, 0x5FDE, 0xCC79, 0x5FE5, 0xCC7A, 0x602D, 0xCC7B, 0x6026, 0xCC7C, 0x6019, 0xCC7D, 0x6032, 0xCC7E, 0x600B, + 0xCCA1, 0x6034, 0xCCA2, 0x600A, 0xCCA3, 0x6017, 0xCCA4, 0x6033, 0xCCA5, 0x601A, 0xCCA6, 0x601E, 0xCCA7, 0x602C, 0xCCA8, 0x6022, + 0xCCA9, 0x600D, 0xCCAA, 0x6010, 0xCCAB, 0x602E, 0xCCAC, 0x6013, 0xCCAD, 0x6011, 0xCCAE, 0x600C, 0xCCAF, 0x6009, 0xCCB0, 0x601C, + 0xCCB1, 0x6214, 0xCCB2, 0x623D, 0xCCB3, 0x62AD, 0xCCB4, 0x62B4, 0xCCB5, 0x62D1, 0xCCB6, 0x62BE, 0xCCB7, 0x62AA, 0xCCB8, 0x62B6, + 0xCCB9, 0x62CA, 0xCCBA, 0x62AE, 0xCCBB, 0x62B3, 0xCCBC, 0x62AF, 0xCCBD, 0x62BB, 0xCCBE, 0x62A9, 0xCCBF, 0x62B0, 0xCCC0, 0x62B8, + 0xCCC1, 0x653D, 0xCCC2, 0x65A8, 0xCCC3, 0x65BB, 0xCCC4, 0x6609, 0xCCC5, 0x65FC, 0xCCC6, 0x6604, 0xCCC7, 0x6612, 0xCCC8, 0x6608, + 0xCCC9, 0x65FB, 0xCCCA, 0x6603, 0xCCCB, 0x660B, 0xCCCC, 0x660D, 0xCCCD, 0x6605, 0xCCCE, 0x65FD, 0xCCCF, 0x6611, 0xCCD0, 0x6610, + 0xCCD1, 0x66F6, 0xCCD2, 0x670A, 0xCCD3, 0x6785, 0xCCD4, 0x676C, 0xCCD5, 0x678E, 0xCCD6, 0x6792, 0xCCD7, 0x6776, 0xCCD8, 0x677B, + 0xCCD9, 0x6798, 0xCCDA, 0x6786, 0xCCDB, 0x6784, 0xCCDC, 0x6774, 0xCCDD, 0x678D, 0xCCDE, 0x678C, 0xCCDF, 0x677A, 0xCCE0, 0x679F, + 0xCCE1, 0x6791, 0xCCE2, 0x6799, 0xCCE3, 0x6783, 0xCCE4, 0x677D, 0xCCE5, 0x6781, 0xCCE6, 0x6778, 0xCCE7, 0x6779, 0xCCE8, 0x6794, + 0xCCE9, 0x6B25, 0xCCEA, 0x6B80, 0xCCEB, 0x6B7E, 0xCCEC, 0x6BDE, 0xCCED, 0x6C1D, 0xCCEE, 0x6C93, 0xCCEF, 0x6CEC, 0xCCF0, 0x6CEB, + 0xCCF1, 0x6CEE, 0xCCF2, 0x6CD9, 0xCCF3, 0x6CB6, 0xCCF4, 0x6CD4, 0xCCF5, 0x6CAD, 0xCCF6, 0x6CE7, 0xCCF7, 0x6CB7, 0xCCF8, 0x6CD0, + 0xCCF9, 0x6CC2, 0xCCFA, 0x6CBA, 0xCCFB, 0x6CC3, 0xCCFC, 0x6CC6, 0xCCFD, 0x6CED, 0xCCFE, 0x6CF2, 0xCD40, 0x6CD2, 0xCD41, 0x6CDD, + 0xCD42, 0x6CB4, 0xCD43, 0x6C8A, 0xCD44, 0x6C9D, 0xCD45, 0x6C80, 0xCD46, 0x6CDE, 0xCD47, 0x6CC0, 0xCD48, 0x6D30, 0xCD49, 0x6CCD, + 0xCD4A, 0x6CC7, 0xCD4B, 0x6CB0, 0xCD4C, 0x6CF9, 0xCD4D, 0x6CCF, 0xCD4E, 0x6CE9, 0xCD4F, 0x6CD1, 0xCD50, 0x7094, 0xCD51, 0x7098, + 0xCD52, 0x7085, 0xCD53, 0x7093, 0xCD54, 0x7086, 0xCD55, 0x7084, 0xCD56, 0x7091, 0xCD57, 0x7096, 0xCD58, 0x7082, 0xCD59, 0x709A, + 0xCD5A, 0x7083, 0xCD5B, 0x726A, 0xCD5C, 0x72D6, 0xCD5D, 0x72CB, 0xCD5E, 0x72D8, 0xCD5F, 0x72C9, 0xCD60, 0x72DC, 0xCD61, 0x72D2, + 0xCD62, 0x72D4, 0xCD63, 0x72DA, 0xCD64, 0x72CC, 0xCD65, 0x72D1, 0xCD66, 0x73A4, 0xCD67, 0x73A1, 0xCD68, 0x73AD, 0xCD69, 0x73A6, + 0xCD6A, 0x73A2, 0xCD6B, 0x73A0, 0xCD6C, 0x73AC, 0xCD6D, 0x739D, 0xCD6E, 0x74DD, 0xCD6F, 0x74E8, 0xCD70, 0x753F, 0xCD71, 0x7540, + 0xCD72, 0x753E, 0xCD73, 0x758C, 0xCD74, 0x7598, 0xCD75, 0x76AF, 0xCD76, 0x76F3, 0xCD77, 0x76F1, 0xCD78, 0x76F0, 0xCD79, 0x76F5, + 0xCD7A, 0x77F8, 0xCD7B, 0x77FC, 0xCD7C, 0x77F9, 0xCD7D, 0x77FB, 0xCD7E, 0x77FA, 0xCDA1, 0x77F7, 0xCDA2, 0x7942, 0xCDA3, 0x793F, + 0xCDA4, 0x79C5, 0xCDA5, 0x7A78, 0xCDA6, 0x7A7B, 0xCDA7, 0x7AFB, 0xCDA8, 0x7C75, 0xCDA9, 0x7CFD, 0xCDAA, 0x8035, 0xCDAB, 0x808F, + 0xCDAC, 0x80AE, 0xCDAD, 0x80A3, 0xCDAE, 0x80B8, 0xCDAF, 0x80B5, 0xCDB0, 0x80AD, 0xCDB1, 0x8220, 0xCDB2, 0x82A0, 0xCDB3, 0x82C0, + 0xCDB4, 0x82AB, 0xCDB5, 0x829A, 0xCDB6, 0x8298, 0xCDB7, 0x829B, 0xCDB8, 0x82B5, 0xCDB9, 0x82A7, 0xCDBA, 0x82AE, 0xCDBB, 0x82BC, + 0xCDBC, 0x829E, 0xCDBD, 0x82BA, 0xCDBE, 0x82B4, 0xCDBF, 0x82A8, 0xCDC0, 0x82A1, 0xCDC1, 0x82A9, 0xCDC2, 0x82C2, 0xCDC3, 0x82A4, + 0xCDC4, 0x82C3, 0xCDC5, 0x82B6, 0xCDC6, 0x82A2, 0xCDC7, 0x8670, 0xCDC8, 0x866F, 0xCDC9, 0x866D, 0xCDCA, 0x866E, 0xCDCB, 0x8C56, + 0xCDCC, 0x8FD2, 0xCDCD, 0x8FCB, 0xCDCE, 0x8FD3, 0xCDCF, 0x8FCD, 0xCDD0, 0x8FD6, 0xCDD1, 0x8FD5, 0xCDD2, 0x8FD7, 0xCDD3, 0x90B2, + 0xCDD4, 0x90B4, 0xCDD5, 0x90AF, 0xCDD6, 0x90B3, 0xCDD7, 0x90B0, 0xCDD8, 0x9639, 0xCDD9, 0x963D, 0xCDDA, 0x963C, 0xCDDB, 0x963A, + 0xCDDC, 0x9643, 0xCDDD, 0x4FCD, 0xCDDE, 0x4FC5, 0xCDDF, 0x4FD3, 0xCDE0, 0x4FB2, 0xCDE1, 0x4FC9, 0xCDE2, 0x4FCB, 0xCDE3, 0x4FC1, + 0xCDE4, 0x4FD4, 0xCDE5, 0x4FDC, 0xCDE6, 0x4FD9, 0xCDE7, 0x4FBB, 0xCDE8, 0x4FB3, 0xCDE9, 0x4FDB, 0xCDEA, 0x4FC7, 0xCDEB, 0x4FD6, + 0xCDEC, 0x4FBA, 0xCDED, 0x4FC0, 0xCDEE, 0x4FB9, 0xCDEF, 0x4FEC, 0xCDF0, 0x5244, 0xCDF1, 0x5249, 0xCDF2, 0x52C0, 0xCDF3, 0x52C2, + 0xCDF4, 0x533D, 0xCDF5, 0x537C, 0xCDF6, 0x5397, 0xCDF7, 0x5396, 0xCDF8, 0x5399, 0xCDF9, 0x5398, 0xCDFA, 0x54BA, 0xCDFB, 0x54A1, + 0xCDFC, 0x54AD, 0xCDFD, 0x54A5, 0xCDFE, 0x54CF, 0xCE40, 0x54C3, 0xCE41, 0x830D, 0xCE42, 0x54B7, 0xCE43, 0x54AE, 0xCE44, 0x54D6, + 0xCE45, 0x54B6, 0xCE46, 0x54C5, 0xCE47, 0x54C6, 0xCE48, 0x54A0, 0xCE49, 0x5470, 0xCE4A, 0x54BC, 0xCE4B, 0x54A2, 0xCE4C, 0x54BE, + 0xCE4D, 0x5472, 0xCE4E, 0x54DE, 0xCE4F, 0x54B0, 0xCE50, 0x57B5, 0xCE51, 0x579E, 0xCE52, 0x579F, 0xCE53, 0x57A4, 0xCE54, 0x578C, + 0xCE55, 0x5797, 0xCE56, 0x579D, 0xCE57, 0x579B, 0xCE58, 0x5794, 0xCE59, 0x5798, 0xCE5A, 0x578F, 0xCE5B, 0x5799, 0xCE5C, 0x57A5, + 0xCE5D, 0x579A, 0xCE5E, 0x5795, 0xCE5F, 0x58F4, 0xCE60, 0x590D, 0xCE61, 0x5953, 0xCE62, 0x59E1, 0xCE63, 0x59DE, 0xCE64, 0x59EE, + 0xCE65, 0x5A00, 0xCE66, 0x59F1, 0xCE67, 0x59DD, 0xCE68, 0x59FA, 0xCE69, 0x59FD, 0xCE6A, 0x59FC, 0xCE6B, 0x59F6, 0xCE6C, 0x59E4, + 0xCE6D, 0x59F2, 0xCE6E, 0x59F7, 0xCE6F, 0x59DB, 0xCE70, 0x59E9, 0xCE71, 0x59F3, 0xCE72, 0x59F5, 0xCE73, 0x59E0, 0xCE74, 0x59FE, + 0xCE75, 0x59F4, 0xCE76, 0x59ED, 0xCE77, 0x5BA8, 0xCE78, 0x5C4C, 0xCE79, 0x5CD0, 0xCE7A, 0x5CD8, 0xCE7B, 0x5CCC, 0xCE7C, 0x5CD7, + 0xCE7D, 0x5CCB, 0xCE7E, 0x5CDB, 0xCEA1, 0x5CDE, 0xCEA2, 0x5CDA, 0xCEA3, 0x5CC9, 0xCEA4, 0x5CC7, 0xCEA5, 0x5CCA, 0xCEA6, 0x5CD6, + 0xCEA7, 0x5CD3, 0xCEA8, 0x5CD4, 0xCEA9, 0x5CCF, 0xCEAA, 0x5CC8, 0xCEAB, 0x5CC6, 0xCEAC, 0x5CCE, 0xCEAD, 0x5CDF, 0xCEAE, 0x5CF8, + 0xCEAF, 0x5DF9, 0xCEB0, 0x5E21, 0xCEB1, 0x5E22, 0xCEB2, 0x5E23, 0xCEB3, 0x5E20, 0xCEB4, 0x5E24, 0xCEB5, 0x5EB0, 0xCEB6, 0x5EA4, + 0xCEB7, 0x5EA2, 0xCEB8, 0x5E9B, 0xCEB9, 0x5EA3, 0xCEBA, 0x5EA5, 0xCEBB, 0x5F07, 0xCEBC, 0x5F2E, 0xCEBD, 0x5F56, 0xCEBE, 0x5F86, + 0xCEBF, 0x6037, 0xCEC0, 0x6039, 0xCEC1, 0x6054, 0xCEC2, 0x6072, 0xCEC3, 0x605E, 0xCEC4, 0x6045, 0xCEC5, 0x6053, 0xCEC6, 0x6047, + 0xCEC7, 0x6049, 0xCEC8, 0x605B, 0xCEC9, 0x604C, 0xCECA, 0x6040, 0xCECB, 0x6042, 0xCECC, 0x605F, 0xCECD, 0x6024, 0xCECE, 0x6044, + 0xCECF, 0x6058, 0xCED0, 0x6066, 0xCED1, 0x606E, 0xCED2, 0x6242, 0xCED3, 0x6243, 0xCED4, 0x62CF, 0xCED5, 0x630D, 0xCED6, 0x630B, + 0xCED7, 0x62F5, 0xCED8, 0x630E, 0xCED9, 0x6303, 0xCEDA, 0x62EB, 0xCEDB, 0x62F9, 0xCEDC, 0x630F, 0xCEDD, 0x630C, 0xCEDE, 0x62F8, + 0xCEDF, 0x62F6, 0xCEE0, 0x6300, 0xCEE1, 0x6313, 0xCEE2, 0x6314, 0xCEE3, 0x62FA, 0xCEE4, 0x6315, 0xCEE5, 0x62FB, 0xCEE6, 0x62F0, + 0xCEE7, 0x6541, 0xCEE8, 0x6543, 0xCEE9, 0x65AA, 0xCEEA, 0x65BF, 0xCEEB, 0x6636, 0xCEEC, 0x6621, 0xCEED, 0x6632, 0xCEEE, 0x6635, + 0xCEEF, 0x661C, 0xCEF0, 0x6626, 0xCEF1, 0x6622, 0xCEF2, 0x6633, 0xCEF3, 0x662B, 0xCEF4, 0x663A, 0xCEF5, 0x661D, 0xCEF6, 0x6634, + 0xCEF7, 0x6639, 0xCEF8, 0x662E, 0xCEF9, 0x670F, 0xCEFA, 0x6710, 0xCEFB, 0x67C1, 0xCEFC, 0x67F2, 0xCEFD, 0x67C8, 0xCEFE, 0x67BA, + 0xCF40, 0x67DC, 0xCF41, 0x67BB, 0xCF42, 0x67F8, 0xCF43, 0x67D8, 0xCF44, 0x67C0, 0xCF45, 0x67B7, 0xCF46, 0x67C5, 0xCF47, 0x67EB, + 0xCF48, 0x67E4, 0xCF49, 0x67DF, 0xCF4A, 0x67B5, 0xCF4B, 0x67CD, 0xCF4C, 0x67B3, 0xCF4D, 0x67F7, 0xCF4E, 0x67F6, 0xCF4F, 0x67EE, + 0xCF50, 0x67E3, 0xCF51, 0x67C2, 0xCF52, 0x67B9, 0xCF53, 0x67CE, 0xCF54, 0x67E7, 0xCF55, 0x67F0, 0xCF56, 0x67B2, 0xCF57, 0x67FC, + 0xCF58, 0x67C6, 0xCF59, 0x67ED, 0xCF5A, 0x67CC, 0xCF5B, 0x67AE, 0xCF5C, 0x67E6, 0xCF5D, 0x67DB, 0xCF5E, 0x67FA, 0xCF5F, 0x67C9, + 0xCF60, 0x67CA, 0xCF61, 0x67C3, 0xCF62, 0x67EA, 0xCF63, 0x67CB, 0xCF64, 0x6B28, 0xCF65, 0x6B82, 0xCF66, 0x6B84, 0xCF67, 0x6BB6, + 0xCF68, 0x6BD6, 0xCF69, 0x6BD8, 0xCF6A, 0x6BE0, 0xCF6B, 0x6C20, 0xCF6C, 0x6C21, 0xCF6D, 0x6D28, 0xCF6E, 0x6D34, 0xCF6F, 0x6D2D, + 0xCF70, 0x6D1F, 0xCF71, 0x6D3C, 0xCF72, 0x6D3F, 0xCF73, 0x6D12, 0xCF74, 0x6D0A, 0xCF75, 0x6CDA, 0xCF76, 0x6D33, 0xCF77, 0x6D04, + 0xCF78, 0x6D19, 0xCF79, 0x6D3A, 0xCF7A, 0x6D1A, 0xCF7B, 0x6D11, 0xCF7C, 0x6D00, 0xCF7D, 0x6D1D, 0xCF7E, 0x6D42, 0xCFA1, 0x6D01, + 0xCFA2, 0x6D18, 0xCFA3, 0x6D37, 0xCFA4, 0x6D03, 0xCFA5, 0x6D0F, 0xCFA6, 0x6D40, 0xCFA7, 0x6D07, 0xCFA8, 0x6D20, 0xCFA9, 0x6D2C, + 0xCFAA, 0x6D08, 0xCFAB, 0x6D22, 0xCFAC, 0x6D09, 0xCFAD, 0x6D10, 0xCFAE, 0x70B7, 0xCFAF, 0x709F, 0xCFB0, 0x70BE, 0xCFB1, 0x70B1, + 0xCFB2, 0x70B0, 0xCFB3, 0x70A1, 0xCFB4, 0x70B4, 0xCFB5, 0x70B5, 0xCFB6, 0x70A9, 0xCFB7, 0x7241, 0xCFB8, 0x7249, 0xCFB9, 0x724A, + 0xCFBA, 0x726C, 0xCFBB, 0x7270, 0xCFBC, 0x7273, 0xCFBD, 0x726E, 0xCFBE, 0x72CA, 0xCFBF, 0x72E4, 0xCFC0, 0x72E8, 0xCFC1, 0x72EB, + 0xCFC2, 0x72DF, 0xCFC3, 0x72EA, 0xCFC4, 0x72E6, 0xCFC5, 0x72E3, 0xCFC6, 0x7385, 0xCFC7, 0x73CC, 0xCFC8, 0x73C2, 0xCFC9, 0x73C8, + 0xCFCA, 0x73C5, 0xCFCB, 0x73B9, 0xCFCC, 0x73B6, 0xCFCD, 0x73B5, 0xCFCE, 0x73B4, 0xCFCF, 0x73EB, 0xCFD0, 0x73BF, 0xCFD1, 0x73C7, + 0xCFD2, 0x73BE, 0xCFD3, 0x73C3, 0xCFD4, 0x73C6, 0xCFD5, 0x73B8, 0xCFD6, 0x73CB, 0xCFD7, 0x74EC, 0xCFD8, 0x74EE, 0xCFD9, 0x752E, + 0xCFDA, 0x7547, 0xCFDB, 0x7548, 0xCFDC, 0x75A7, 0xCFDD, 0x75AA, 0xCFDE, 0x7679, 0xCFDF, 0x76C4, 0xCFE0, 0x7708, 0xCFE1, 0x7703, + 0xCFE2, 0x7704, 0xCFE3, 0x7705, 0xCFE4, 0x770A, 0xCFE5, 0x76F7, 0xCFE6, 0x76FB, 0xCFE7, 0x76FA, 0xCFE8, 0x77E7, 0xCFE9, 0x77E8, + 0xCFEA, 0x7806, 0xCFEB, 0x7811, 0xCFEC, 0x7812, 0xCFED, 0x7805, 0xCFEE, 0x7810, 0xCFEF, 0x780F, 0xCFF0, 0x780E, 0xCFF1, 0x7809, + 0xCFF2, 0x7803, 0xCFF3, 0x7813, 0xCFF4, 0x794A, 0xCFF5, 0x794C, 0xCFF6, 0x794B, 0xCFF7, 0x7945, 0xCFF8, 0x7944, 0xCFF9, 0x79D5, + 0xCFFA, 0x79CD, 0xCFFB, 0x79CF, 0xCFFC, 0x79D6, 0xCFFD, 0x79CE, 0xCFFE, 0x7A80, 0xD040, 0x7A7E, 0xD041, 0x7AD1, 0xD042, 0x7B00, + 0xD043, 0x7B01, 0xD044, 0x7C7A, 0xD045, 0x7C78, 0xD046, 0x7C79, 0xD047, 0x7C7F, 0xD048, 0x7C80, 0xD049, 0x7C81, 0xD04A, 0x7D03, + 0xD04B, 0x7D08, 0xD04C, 0x7D01, 0xD04D, 0x7F58, 0xD04E, 0x7F91, 0xD04F, 0x7F8D, 0xD050, 0x7FBE, 0xD051, 0x8007, 0xD052, 0x800E, + 0xD053, 0x800F, 0xD054, 0x8014, 0xD055, 0x8037, 0xD056, 0x80D8, 0xD057, 0x80C7, 0xD058, 0x80E0, 0xD059, 0x80D1, 0xD05A, 0x80C8, + 0xD05B, 0x80C2, 0xD05C, 0x80D0, 0xD05D, 0x80C5, 0xD05E, 0x80E3, 0xD05F, 0x80D9, 0xD060, 0x80DC, 0xD061, 0x80CA, 0xD062, 0x80D5, + 0xD063, 0x80C9, 0xD064, 0x80CF, 0xD065, 0x80D7, 0xD066, 0x80E6, 0xD067, 0x80CD, 0xD068, 0x81FF, 0xD069, 0x8221, 0xD06A, 0x8294, + 0xD06B, 0x82D9, 0xD06C, 0x82FE, 0xD06D, 0x82F9, 0xD06E, 0x8307, 0xD06F, 0x82E8, 0xD070, 0x8300, 0xD071, 0x82D5, 0xD072, 0x833A, + 0xD073, 0x82EB, 0xD074, 0x82D6, 0xD075, 0x82F4, 0xD076, 0x82EC, 0xD077, 0x82E1, 0xD078, 0x82F2, 0xD079, 0x82F5, 0xD07A, 0x830C, + 0xD07B, 0x82FB, 0xD07C, 0x82F6, 0xD07D, 0x82F0, 0xD07E, 0x82EA, 0xD0A1, 0x82E4, 0xD0A2, 0x82E0, 0xD0A3, 0x82FA, 0xD0A4, 0x82F3, + 0xD0A5, 0x82ED, 0xD0A6, 0x8677, 0xD0A7, 0x8674, 0xD0A8, 0x867C, 0xD0A9, 0x8673, 0xD0AA, 0x8841, 0xD0AB, 0x884E, 0xD0AC, 0x8867, + 0xD0AD, 0x886A, 0xD0AE, 0x8869, 0xD0AF, 0x89D3, 0xD0B0, 0x8A04, 0xD0B1, 0x8A07, 0xD0B2, 0x8D72, 0xD0B3, 0x8FE3, 0xD0B4, 0x8FE1, + 0xD0B5, 0x8FEE, 0xD0B6, 0x8FE0, 0xD0B7, 0x90F1, 0xD0B8, 0x90BD, 0xD0B9, 0x90BF, 0xD0BA, 0x90D5, 0xD0BB, 0x90C5, 0xD0BC, 0x90BE, + 0xD0BD, 0x90C7, 0xD0BE, 0x90CB, 0xD0BF, 0x90C8, 0xD0C0, 0x91D4, 0xD0C1, 0x91D3, 0xD0C2, 0x9654, 0xD0C3, 0x964F, 0xD0C4, 0x9651, + 0xD0C5, 0x9653, 0xD0C6, 0x964A, 0xD0C7, 0x964E, 0xD0C8, 0x501E, 0xD0C9, 0x5005, 0xD0CA, 0x5007, 0xD0CB, 0x5013, 0xD0CC, 0x5022, + 0xD0CD, 0x5030, 0xD0CE, 0x501B, 0xD0CF, 0x4FF5, 0xD0D0, 0x4FF4, 0xD0D1, 0x5033, 0xD0D2, 0x5037, 0xD0D3, 0x502C, 0xD0D4, 0x4FF6, + 0xD0D5, 0x4FF7, 0xD0D6, 0x5017, 0xD0D7, 0x501C, 0xD0D8, 0x5020, 0xD0D9, 0x5027, 0xD0DA, 0x5035, 0xD0DB, 0x502F, 0xD0DC, 0x5031, + 0xD0DD, 0x500E, 0xD0DE, 0x515A, 0xD0DF, 0x5194, 0xD0E0, 0x5193, 0xD0E1, 0x51CA, 0xD0E2, 0x51C4, 0xD0E3, 0x51C5, 0xD0E4, 0x51C8, + 0xD0E5, 0x51CE, 0xD0E6, 0x5261, 0xD0E7, 0x525A, 0xD0E8, 0x5252, 0xD0E9, 0x525E, 0xD0EA, 0x525F, 0xD0EB, 0x5255, 0xD0EC, 0x5262, + 0xD0ED, 0x52CD, 0xD0EE, 0x530E, 0xD0EF, 0x539E, 0xD0F0, 0x5526, 0xD0F1, 0x54E2, 0xD0F2, 0x5517, 0xD0F3, 0x5512, 0xD0F4, 0x54E7, + 0xD0F5, 0x54F3, 0xD0F6, 0x54E4, 0xD0F7, 0x551A, 0xD0F8, 0x54FF, 0xD0F9, 0x5504, 0xD0FA, 0x5508, 0xD0FB, 0x54EB, 0xD0FC, 0x5511, + 0xD0FD, 0x5505, 0xD0FE, 0x54F1, 0xD140, 0x550A, 0xD141, 0x54FB, 0xD142, 0x54F7, 0xD143, 0x54F8, 0xD144, 0x54E0, 0xD145, 0x550E, + 0xD146, 0x5503, 0xD147, 0x550B, 0xD148, 0x5701, 0xD149, 0x5702, 0xD14A, 0x57CC, 0xD14B, 0x5832, 0xD14C, 0x57D5, 0xD14D, 0x57D2, + 0xD14E, 0x57BA, 0xD14F, 0x57C6, 0xD150, 0x57BD, 0xD151, 0x57BC, 0xD152, 0x57B8, 0xD153, 0x57B6, 0xD154, 0x57BF, 0xD155, 0x57C7, + 0xD156, 0x57D0, 0xD157, 0x57B9, 0xD158, 0x57C1, 0xD159, 0x590E, 0xD15A, 0x594A, 0xD15B, 0x5A19, 0xD15C, 0x5A16, 0xD15D, 0x5A2D, + 0xD15E, 0x5A2E, 0xD15F, 0x5A15, 0xD160, 0x5A0F, 0xD161, 0x5A17, 0xD162, 0x5A0A, 0xD163, 0x5A1E, 0xD164, 0x5A33, 0xD165, 0x5B6C, + 0xD166, 0x5BA7, 0xD167, 0x5BAD, 0xD168, 0x5BAC, 0xD169, 0x5C03, 0xD16A, 0x5C56, 0xD16B, 0x5C54, 0xD16C, 0x5CEC, 0xD16D, 0x5CFF, + 0xD16E, 0x5CEE, 0xD16F, 0x5CF1, 0xD170, 0x5CF7, 0xD171, 0x5D00, 0xD172, 0x5CF9, 0xD173, 0x5E29, 0xD174, 0x5E28, 0xD175, 0x5EA8, + 0xD176, 0x5EAE, 0xD177, 0x5EAA, 0xD178, 0x5EAC, 0xD179, 0x5F33, 0xD17A, 0x5F30, 0xD17B, 0x5F67, 0xD17C, 0x605D, 0xD17D, 0x605A, + 0xD17E, 0x6067, 0xD1A1, 0x6041, 0xD1A2, 0x60A2, 0xD1A3, 0x6088, 0xD1A4, 0x6080, 0xD1A5, 0x6092, 0xD1A6, 0x6081, 0xD1A7, 0x609D, + 0xD1A8, 0x6083, 0xD1A9, 0x6095, 0xD1AA, 0x609B, 0xD1AB, 0x6097, 0xD1AC, 0x6087, 0xD1AD, 0x609C, 0xD1AE, 0x608E, 0xD1AF, 0x6219, + 0xD1B0, 0x6246, 0xD1B1, 0x62F2, 0xD1B2, 0x6310, 0xD1B3, 0x6356, 0xD1B4, 0x632C, 0xD1B5, 0x6344, 0xD1B6, 0x6345, 0xD1B7, 0x6336, + 0xD1B8, 0x6343, 0xD1B9, 0x63E4, 0xD1BA, 0x6339, 0xD1BB, 0x634B, 0xD1BC, 0x634A, 0xD1BD, 0x633C, 0xD1BE, 0x6329, 0xD1BF, 0x6341, + 0xD1C0, 0x6334, 0xD1C1, 0x6358, 0xD1C2, 0x6354, 0xD1C3, 0x6359, 0xD1C4, 0x632D, 0xD1C5, 0x6347, 0xD1C6, 0x6333, 0xD1C7, 0x635A, + 0xD1C8, 0x6351, 0xD1C9, 0x6338, 0xD1CA, 0x6357, 0xD1CB, 0x6340, 0xD1CC, 0x6348, 0xD1CD, 0x654A, 0xD1CE, 0x6546, 0xD1CF, 0x65C6, + 0xD1D0, 0x65C3, 0xD1D1, 0x65C4, 0xD1D2, 0x65C2, 0xD1D3, 0x664A, 0xD1D4, 0x665F, 0xD1D5, 0x6647, 0xD1D6, 0x6651, 0xD1D7, 0x6712, + 0xD1D8, 0x6713, 0xD1D9, 0x681F, 0xD1DA, 0x681A, 0xD1DB, 0x6849, 0xD1DC, 0x6832, 0xD1DD, 0x6833, 0xD1DE, 0x683B, 0xD1DF, 0x684B, + 0xD1E0, 0x684F, 0xD1E1, 0x6816, 0xD1E2, 0x6831, 0xD1E3, 0x681C, 0xD1E4, 0x6835, 0xD1E5, 0x682B, 0xD1E6, 0x682D, 0xD1E7, 0x682F, + 0xD1E8, 0x684E, 0xD1E9, 0x6844, 0xD1EA, 0x6834, 0xD1EB, 0x681D, 0xD1EC, 0x6812, 0xD1ED, 0x6814, 0xD1EE, 0x6826, 0xD1EF, 0x6828, + 0xD1F0, 0x682E, 0xD1F1, 0x684D, 0xD1F2, 0x683A, 0xD1F3, 0x6825, 0xD1F4, 0x6820, 0xD1F5, 0x6B2C, 0xD1F6, 0x6B2F, 0xD1F7, 0x6B2D, + 0xD1F8, 0x6B31, 0xD1F9, 0x6B34, 0xD1FA, 0x6B6D, 0xD1FB, 0x8082, 0xD1FC, 0x6B88, 0xD1FD, 0x6BE6, 0xD1FE, 0x6BE4, 0xD240, 0x6BE8, + 0xD241, 0x6BE3, 0xD242, 0x6BE2, 0xD243, 0x6BE7, 0xD244, 0x6C25, 0xD245, 0x6D7A, 0xD246, 0x6D63, 0xD247, 0x6D64, 0xD248, 0x6D76, + 0xD249, 0x6D0D, 0xD24A, 0x6D61, 0xD24B, 0x6D92, 0xD24C, 0x6D58, 0xD24D, 0x6D62, 0xD24E, 0x6D6D, 0xD24F, 0x6D6F, 0xD250, 0x6D91, + 0xD251, 0x6D8D, 0xD252, 0x6DEF, 0xD253, 0x6D7F, 0xD254, 0x6D86, 0xD255, 0x6D5E, 0xD256, 0x6D67, 0xD257, 0x6D60, 0xD258, 0x6D97, + 0xD259, 0x6D70, 0xD25A, 0x6D7C, 0xD25B, 0x6D5F, 0xD25C, 0x6D82, 0xD25D, 0x6D98, 0xD25E, 0x6D2F, 0xD25F, 0x6D68, 0xD260, 0x6D8B, + 0xD261, 0x6D7E, 0xD262, 0x6D80, 0xD263, 0x6D84, 0xD264, 0x6D16, 0xD265, 0x6D83, 0xD266, 0x6D7B, 0xD267, 0x6D7D, 0xD268, 0x6D75, + 0xD269, 0x6D90, 0xD26A, 0x70DC, 0xD26B, 0x70D3, 0xD26C, 0x70D1, 0xD26D, 0x70DD, 0xD26E, 0x70CB, 0xD26F, 0x7F39, 0xD270, 0x70E2, + 0xD271, 0x70D7, 0xD272, 0x70D2, 0xD273, 0x70DE, 0xD274, 0x70E0, 0xD275, 0x70D4, 0xD276, 0x70CD, 0xD277, 0x70C5, 0xD278, 0x70C6, + 0xD279, 0x70C7, 0xD27A, 0x70DA, 0xD27B, 0x70CE, 0xD27C, 0x70E1, 0xD27D, 0x7242, 0xD27E, 0x7278, 0xD2A1, 0x7277, 0xD2A2, 0x7276, + 0xD2A3, 0x7300, 0xD2A4, 0x72FA, 0xD2A5, 0x72F4, 0xD2A6, 0x72FE, 0xD2A7, 0x72F6, 0xD2A8, 0x72F3, 0xD2A9, 0x72FB, 0xD2AA, 0x7301, + 0xD2AB, 0x73D3, 0xD2AC, 0x73D9, 0xD2AD, 0x73E5, 0xD2AE, 0x73D6, 0xD2AF, 0x73BC, 0xD2B0, 0x73E7, 0xD2B1, 0x73E3, 0xD2B2, 0x73E9, + 0xD2B3, 0x73DC, 0xD2B4, 0x73D2, 0xD2B5, 0x73DB, 0xD2B6, 0x73D4, 0xD2B7, 0x73DD, 0xD2B8, 0x73DA, 0xD2B9, 0x73D7, 0xD2BA, 0x73D8, + 0xD2BB, 0x73E8, 0xD2BC, 0x74DE, 0xD2BD, 0x74DF, 0xD2BE, 0x74F4, 0xD2BF, 0x74F5, 0xD2C0, 0x7521, 0xD2C1, 0x755B, 0xD2C2, 0x755F, + 0xD2C3, 0x75B0, 0xD2C4, 0x75C1, 0xD2C5, 0x75BB, 0xD2C6, 0x75C4, 0xD2C7, 0x75C0, 0xD2C8, 0x75BF, 0xD2C9, 0x75B6, 0xD2CA, 0x75BA, + 0xD2CB, 0x768A, 0xD2CC, 0x76C9, 0xD2CD, 0x771D, 0xD2CE, 0x771B, 0xD2CF, 0x7710, 0xD2D0, 0x7713, 0xD2D1, 0x7712, 0xD2D2, 0x7723, + 0xD2D3, 0x7711, 0xD2D4, 0x7715, 0xD2D5, 0x7719, 0xD2D6, 0x771A, 0xD2D7, 0x7722, 0xD2D8, 0x7727, 0xD2D9, 0x7823, 0xD2DA, 0x782C, + 0xD2DB, 0x7822, 0xD2DC, 0x7835, 0xD2DD, 0x782F, 0xD2DE, 0x7828, 0xD2DF, 0x782E, 0xD2E0, 0x782B, 0xD2E1, 0x7821, 0xD2E2, 0x7829, + 0xD2E3, 0x7833, 0xD2E4, 0x782A, 0xD2E5, 0x7831, 0xD2E6, 0x7954, 0xD2E7, 0x795B, 0xD2E8, 0x794F, 0xD2E9, 0x795C, 0xD2EA, 0x7953, + 0xD2EB, 0x7952, 0xD2EC, 0x7951, 0xD2ED, 0x79EB, 0xD2EE, 0x79EC, 0xD2EF, 0x79E0, 0xD2F0, 0x79EE, 0xD2F1, 0x79ED, 0xD2F2, 0x79EA, + 0xD2F3, 0x79DC, 0xD2F4, 0x79DE, 0xD2F5, 0x79DD, 0xD2F6, 0x7A86, 0xD2F7, 0x7A89, 0xD2F8, 0x7A85, 0xD2F9, 0x7A8B, 0xD2FA, 0x7A8C, + 0xD2FB, 0x7A8A, 0xD2FC, 0x7A87, 0xD2FD, 0x7AD8, 0xD2FE, 0x7B10, 0xD340, 0x7B04, 0xD341, 0x7B13, 0xD342, 0x7B05, 0xD343, 0x7B0F, + 0xD344, 0x7B08, 0xD345, 0x7B0A, 0xD346, 0x7B0E, 0xD347, 0x7B09, 0xD348, 0x7B12, 0xD349, 0x7C84, 0xD34A, 0x7C91, 0xD34B, 0x7C8A, + 0xD34C, 0x7C8C, 0xD34D, 0x7C88, 0xD34E, 0x7C8D, 0xD34F, 0x7C85, 0xD350, 0x7D1E, 0xD351, 0x7D1D, 0xD352, 0x7D11, 0xD353, 0x7D0E, + 0xD354, 0x7D18, 0xD355, 0x7D16, 0xD356, 0x7D13, 0xD357, 0x7D1F, 0xD358, 0x7D12, 0xD359, 0x7D0F, 0xD35A, 0x7D0C, 0xD35B, 0x7F5C, + 0xD35C, 0x7F61, 0xD35D, 0x7F5E, 0xD35E, 0x7F60, 0xD35F, 0x7F5D, 0xD360, 0x7F5B, 0xD361, 0x7F96, 0xD362, 0x7F92, 0xD363, 0x7FC3, + 0xD364, 0x7FC2, 0xD365, 0x7FC0, 0xD366, 0x8016, 0xD367, 0x803E, 0xD368, 0x8039, 0xD369, 0x80FA, 0xD36A, 0x80F2, 0xD36B, 0x80F9, + 0xD36C, 0x80F5, 0xD36D, 0x8101, 0xD36E, 0x80FB, 0xD36F, 0x8100, 0xD370, 0x8201, 0xD371, 0x822F, 0xD372, 0x8225, 0xD373, 0x8333, + 0xD374, 0x832D, 0xD375, 0x8344, 0xD376, 0x8319, 0xD377, 0x8351, 0xD378, 0x8325, 0xD379, 0x8356, 0xD37A, 0x833F, 0xD37B, 0x8341, + 0xD37C, 0x8326, 0xD37D, 0x831C, 0xD37E, 0x8322, 0xD3A1, 0x8342, 0xD3A2, 0x834E, 0xD3A3, 0x831B, 0xD3A4, 0x832A, 0xD3A5, 0x8308, + 0xD3A6, 0x833C, 0xD3A7, 0x834D, 0xD3A8, 0x8316, 0xD3A9, 0x8324, 0xD3AA, 0x8320, 0xD3AB, 0x8337, 0xD3AC, 0x832F, 0xD3AD, 0x8329, + 0xD3AE, 0x8347, 0xD3AF, 0x8345, 0xD3B0, 0x834C, 0xD3B1, 0x8353, 0xD3B2, 0x831E, 0xD3B3, 0x832C, 0xD3B4, 0x834B, 0xD3B5, 0x8327, + 0xD3B6, 0x8348, 0xD3B7, 0x8653, 0xD3B8, 0x8652, 0xD3B9, 0x86A2, 0xD3BA, 0x86A8, 0xD3BB, 0x8696, 0xD3BC, 0x868D, 0xD3BD, 0x8691, + 0xD3BE, 0x869E, 0xD3BF, 0x8687, 0xD3C0, 0x8697, 0xD3C1, 0x8686, 0xD3C2, 0x868B, 0xD3C3, 0x869A, 0xD3C4, 0x8685, 0xD3C5, 0x86A5, + 0xD3C6, 0x8699, 0xD3C7, 0x86A1, 0xD3C8, 0x86A7, 0xD3C9, 0x8695, 0xD3CA, 0x8698, 0xD3CB, 0x868E, 0xD3CC, 0x869D, 0xD3CD, 0x8690, + 0xD3CE, 0x8694, 0xD3CF, 0x8843, 0xD3D0, 0x8844, 0xD3D1, 0x886D, 0xD3D2, 0x8875, 0xD3D3, 0x8876, 0xD3D4, 0x8872, 0xD3D5, 0x8880, + 0xD3D6, 0x8871, 0xD3D7, 0x887F, 0xD3D8, 0x886F, 0xD3D9, 0x8883, 0xD3DA, 0x887E, 0xD3DB, 0x8874, 0xD3DC, 0x887C, 0xD3DD, 0x8A12, + 0xD3DE, 0x8C47, 0xD3DF, 0x8C57, 0xD3E0, 0x8C7B, 0xD3E1, 0x8CA4, 0xD3E2, 0x8CA3, 0xD3E3, 0x8D76, 0xD3E4, 0x8D78, 0xD3E5, 0x8DB5, + 0xD3E6, 0x8DB7, 0xD3E7, 0x8DB6, 0xD3E8, 0x8ED1, 0xD3E9, 0x8ED3, 0xD3EA, 0x8FFE, 0xD3EB, 0x8FF5, 0xD3EC, 0x9002, 0xD3ED, 0x8FFF, + 0xD3EE, 0x8FFB, 0xD3EF, 0x9004, 0xD3F0, 0x8FFC, 0xD3F1, 0x8FF6, 0xD3F2, 0x90D6, 0xD3F3, 0x90E0, 0xD3F4, 0x90D9, 0xD3F5, 0x90DA, + 0xD3F6, 0x90E3, 0xD3F7, 0x90DF, 0xD3F8, 0x90E5, 0xD3F9, 0x90D8, 0xD3FA, 0x90DB, 0xD3FB, 0x90D7, 0xD3FC, 0x90DC, 0xD3FD, 0x90E4, + 0xD3FE, 0x9150, 0xD440, 0x914E, 0xD441, 0x914F, 0xD442, 0x91D5, 0xD443, 0x91E2, 0xD444, 0x91DA, 0xD445, 0x965C, 0xD446, 0x965F, + 0xD447, 0x96BC, 0xD448, 0x98E3, 0xD449, 0x9ADF, 0xD44A, 0x9B2F, 0xD44B, 0x4E7F, 0xD44C, 0x5070, 0xD44D, 0x506A, 0xD44E, 0x5061, + 0xD44F, 0x505E, 0xD450, 0x5060, 0xD451, 0x5053, 0xD452, 0x504B, 0xD453, 0x505D, 0xD454, 0x5072, 0xD455, 0x5048, 0xD456, 0x504D, + 0xD457, 0x5041, 0xD458, 0x505B, 0xD459, 0x504A, 0xD45A, 0x5062, 0xD45B, 0x5015, 0xD45C, 0x5045, 0xD45D, 0x505F, 0xD45E, 0x5069, + 0xD45F, 0x506B, 0xD460, 0x5063, 0xD461, 0x5064, 0xD462, 0x5046, 0xD463, 0x5040, 0xD464, 0x506E, 0xD465, 0x5073, 0xD466, 0x5057, + 0xD467, 0x5051, 0xD468, 0x51D0, 0xD469, 0x526B, 0xD46A, 0x526D, 0xD46B, 0x526C, 0xD46C, 0x526E, 0xD46D, 0x52D6, 0xD46E, 0x52D3, + 0xD46F, 0x532D, 0xD470, 0x539C, 0xD471, 0x5575, 0xD472, 0x5576, 0xD473, 0x553C, 0xD474, 0x554D, 0xD475, 0x5550, 0xD476, 0x5534, + 0xD477, 0x552A, 0xD478, 0x5551, 0xD479, 0x5562, 0xD47A, 0x5536, 0xD47B, 0x5535, 0xD47C, 0x5530, 0xD47D, 0x5552, 0xD47E, 0x5545, + 0xD4A1, 0x550C, 0xD4A2, 0x5532, 0xD4A3, 0x5565, 0xD4A4, 0x554E, 0xD4A5, 0x5539, 0xD4A6, 0x5548, 0xD4A7, 0x552D, 0xD4A8, 0x553B, + 0xD4A9, 0x5540, 0xD4AA, 0x554B, 0xD4AB, 0x570A, 0xD4AC, 0x5707, 0xD4AD, 0x57FB, 0xD4AE, 0x5814, 0xD4AF, 0x57E2, 0xD4B0, 0x57F6, + 0xD4B1, 0x57DC, 0xD4B2, 0x57F4, 0xD4B3, 0x5800, 0xD4B4, 0x57ED, 0xD4B5, 0x57FD, 0xD4B6, 0x5808, 0xD4B7, 0x57F8, 0xD4B8, 0x580B, + 0xD4B9, 0x57F3, 0xD4BA, 0x57CF, 0xD4BB, 0x5807, 0xD4BC, 0x57EE, 0xD4BD, 0x57E3, 0xD4BE, 0x57F2, 0xD4BF, 0x57E5, 0xD4C0, 0x57EC, + 0xD4C1, 0x57E1, 0xD4C2, 0x580E, 0xD4C3, 0x57FC, 0xD4C4, 0x5810, 0xD4C5, 0x57E7, 0xD4C6, 0x5801, 0xD4C7, 0x580C, 0xD4C8, 0x57F1, + 0xD4C9, 0x57E9, 0xD4CA, 0x57F0, 0xD4CB, 0x580D, 0xD4CC, 0x5804, 0xD4CD, 0x595C, 0xD4CE, 0x5A60, 0xD4CF, 0x5A58, 0xD4D0, 0x5A55, + 0xD4D1, 0x5A67, 0xD4D2, 0x5A5E, 0xD4D3, 0x5A38, 0xD4D4, 0x5A35, 0xD4D5, 0x5A6D, 0xD4D6, 0x5A50, 0xD4D7, 0x5A5F, 0xD4D8, 0x5A65, + 0xD4D9, 0x5A6C, 0xD4DA, 0x5A53, 0xD4DB, 0x5A64, 0xD4DC, 0x5A57, 0xD4DD, 0x5A43, 0xD4DE, 0x5A5D, 0xD4DF, 0x5A52, 0xD4E0, 0x5A44, + 0xD4E1, 0x5A5B, 0xD4E2, 0x5A48, 0xD4E3, 0x5A8E, 0xD4E4, 0x5A3E, 0xD4E5, 0x5A4D, 0xD4E6, 0x5A39, 0xD4E7, 0x5A4C, 0xD4E8, 0x5A70, + 0xD4E9, 0x5A69, 0xD4EA, 0x5A47, 0xD4EB, 0x5A51, 0xD4EC, 0x5A56, 0xD4ED, 0x5A42, 0xD4EE, 0x5A5C, 0xD4EF, 0x5B72, 0xD4F0, 0x5B6E, + 0xD4F1, 0x5BC1, 0xD4F2, 0x5BC0, 0xD4F3, 0x5C59, 0xD4F4, 0x5D1E, 0xD4F5, 0x5D0B, 0xD4F6, 0x5D1D, 0xD4F7, 0x5D1A, 0xD4F8, 0x5D20, + 0xD4F9, 0x5D0C, 0xD4FA, 0x5D28, 0xD4FB, 0x5D0D, 0xD4FC, 0x5D26, 0xD4FD, 0x5D25, 0xD4FE, 0x5D0F, 0xD540, 0x5D30, 0xD541, 0x5D12, + 0xD542, 0x5D23, 0xD543, 0x5D1F, 0xD544, 0x5D2E, 0xD545, 0x5E3E, 0xD546, 0x5E34, 0xD547, 0x5EB1, 0xD548, 0x5EB4, 0xD549, 0x5EB9, + 0xD54A, 0x5EB2, 0xD54B, 0x5EB3, 0xD54C, 0x5F36, 0xD54D, 0x5F38, 0xD54E, 0x5F9B, 0xD54F, 0x5F96, 0xD550, 0x5F9F, 0xD551, 0x608A, + 0xD552, 0x6090, 0xD553, 0x6086, 0xD554, 0x60BE, 0xD555, 0x60B0, 0xD556, 0x60BA, 0xD557, 0x60D3, 0xD558, 0x60D4, 0xD559, 0x60CF, + 0xD55A, 0x60E4, 0xD55B, 0x60D9, 0xD55C, 0x60DD, 0xD55D, 0x60C8, 0xD55E, 0x60B1, 0xD55F, 0x60DB, 0xD560, 0x60B7, 0xD561, 0x60CA, + 0xD562, 0x60BF, 0xD563, 0x60C3, 0xD564, 0x60CD, 0xD565, 0x60C0, 0xD566, 0x6332, 0xD567, 0x6365, 0xD568, 0x638A, 0xD569, 0x6382, + 0xD56A, 0x637D, 0xD56B, 0x63BD, 0xD56C, 0x639E, 0xD56D, 0x63AD, 0xD56E, 0x639D, 0xD56F, 0x6397, 0xD570, 0x63AB, 0xD571, 0x638E, + 0xD572, 0x636F, 0xD573, 0x6387, 0xD574, 0x6390, 0xD575, 0x636E, 0xD576, 0x63AF, 0xD577, 0x6375, 0xD578, 0x639C, 0xD579, 0x636D, + 0xD57A, 0x63AE, 0xD57B, 0x637C, 0xD57C, 0x63A4, 0xD57D, 0x633B, 0xD57E, 0x639F, 0xD5A1, 0x6378, 0xD5A2, 0x6385, 0xD5A3, 0x6381, + 0xD5A4, 0x6391, 0xD5A5, 0x638D, 0xD5A6, 0x6370, 0xD5A7, 0x6553, 0xD5A8, 0x65CD, 0xD5A9, 0x6665, 0xD5AA, 0x6661, 0xD5AB, 0x665B, + 0xD5AC, 0x6659, 0xD5AD, 0x665C, 0xD5AE, 0x6662, 0xD5AF, 0x6718, 0xD5B0, 0x6879, 0xD5B1, 0x6887, 0xD5B2, 0x6890, 0xD5B3, 0x689C, + 0xD5B4, 0x686D, 0xD5B5, 0x686E, 0xD5B6, 0x68AE, 0xD5B7, 0x68AB, 0xD5B8, 0x6956, 0xD5B9, 0x686F, 0xD5BA, 0x68A3, 0xD5BB, 0x68AC, + 0xD5BC, 0x68A9, 0xD5BD, 0x6875, 0xD5BE, 0x6874, 0xD5BF, 0x68B2, 0xD5C0, 0x688F, 0xD5C1, 0x6877, 0xD5C2, 0x6892, 0xD5C3, 0x687C, + 0xD5C4, 0x686B, 0xD5C5, 0x6872, 0xD5C6, 0x68AA, 0xD5C7, 0x6880, 0xD5C8, 0x6871, 0xD5C9, 0x687E, 0xD5CA, 0x689B, 0xD5CB, 0x6896, + 0xD5CC, 0x688B, 0xD5CD, 0x68A0, 0xD5CE, 0x6889, 0xD5CF, 0x68A4, 0xD5D0, 0x6878, 0xD5D1, 0x687B, 0xD5D2, 0x6891, 0xD5D3, 0x688C, + 0xD5D4, 0x688A, 0xD5D5, 0x687D, 0xD5D6, 0x6B36, 0xD5D7, 0x6B33, 0xD5D8, 0x6B37, 0xD5D9, 0x6B38, 0xD5DA, 0x6B91, 0xD5DB, 0x6B8F, + 0xD5DC, 0x6B8D, 0xD5DD, 0x6B8E, 0xD5DE, 0x6B8C, 0xD5DF, 0x6C2A, 0xD5E0, 0x6DC0, 0xD5E1, 0x6DAB, 0xD5E2, 0x6DB4, 0xD5E3, 0x6DB3, + 0xD5E4, 0x6E74, 0xD5E5, 0x6DAC, 0xD5E6, 0x6DE9, 0xD5E7, 0x6DE2, 0xD5E8, 0x6DB7, 0xD5E9, 0x6DF6, 0xD5EA, 0x6DD4, 0xD5EB, 0x6E00, + 0xD5EC, 0x6DC8, 0xD5ED, 0x6DE0, 0xD5EE, 0x6DDF, 0xD5EF, 0x6DD6, 0xD5F0, 0x6DBE, 0xD5F1, 0x6DE5, 0xD5F2, 0x6DDC, 0xD5F3, 0x6DDD, + 0xD5F4, 0x6DDB, 0xD5F5, 0x6DF4, 0xD5F6, 0x6DCA, 0xD5F7, 0x6DBD, 0xD5F8, 0x6DED, 0xD5F9, 0x6DF0, 0xD5FA, 0x6DBA, 0xD5FB, 0x6DD5, + 0xD5FC, 0x6DC2, 0xD5FD, 0x6DCF, 0xD5FE, 0x6DC9, 0xD640, 0x6DD0, 0xD641, 0x6DF2, 0xD642, 0x6DD3, 0xD643, 0x6DFD, 0xD644, 0x6DD7, + 0xD645, 0x6DCD, 0xD646, 0x6DE3, 0xD647, 0x6DBB, 0xD648, 0x70FA, 0xD649, 0x710D, 0xD64A, 0x70F7, 0xD64B, 0x7117, 0xD64C, 0x70F4, + 0xD64D, 0x710C, 0xD64E, 0x70F0, 0xD64F, 0x7104, 0xD650, 0x70F3, 0xD651, 0x7110, 0xD652, 0x70FC, 0xD653, 0x70FF, 0xD654, 0x7106, + 0xD655, 0x7113, 0xD656, 0x7100, 0xD657, 0x70F8, 0xD658, 0x70F6, 0xD659, 0x710B, 0xD65A, 0x7102, 0xD65B, 0x710E, 0xD65C, 0x727E, + 0xD65D, 0x727B, 0xD65E, 0x727C, 0xD65F, 0x727F, 0xD660, 0x731D, 0xD661, 0x7317, 0xD662, 0x7307, 0xD663, 0x7311, 0xD664, 0x7318, + 0xD665, 0x730A, 0xD666, 0x7308, 0xD667, 0x72FF, 0xD668, 0x730F, 0xD669, 0x731E, 0xD66A, 0x7388, 0xD66B, 0x73F6, 0xD66C, 0x73F8, + 0xD66D, 0x73F5, 0xD66E, 0x7404, 0xD66F, 0x7401, 0xD670, 0x73FD, 0xD671, 0x7407, 0xD672, 0x7400, 0xD673, 0x73FA, 0xD674, 0x73FC, + 0xD675, 0x73FF, 0xD676, 0x740C, 0xD677, 0x740B, 0xD678, 0x73F4, 0xD679, 0x7408, 0xD67A, 0x7564, 0xD67B, 0x7563, 0xD67C, 0x75CE, + 0xD67D, 0x75D2, 0xD67E, 0x75CF, 0xD6A1, 0x75CB, 0xD6A2, 0x75CC, 0xD6A3, 0x75D1, 0xD6A4, 0x75D0, 0xD6A5, 0x768F, 0xD6A6, 0x7689, + 0xD6A7, 0x76D3, 0xD6A8, 0x7739, 0xD6A9, 0x772F, 0xD6AA, 0x772D, 0xD6AB, 0x7731, 0xD6AC, 0x7732, 0xD6AD, 0x7734, 0xD6AE, 0x7733, + 0xD6AF, 0x773D, 0xD6B0, 0x7725, 0xD6B1, 0x773B, 0xD6B2, 0x7735, 0xD6B3, 0x7848, 0xD6B4, 0x7852, 0xD6B5, 0x7849, 0xD6B6, 0x784D, + 0xD6B7, 0x784A, 0xD6B8, 0x784C, 0xD6B9, 0x7826, 0xD6BA, 0x7845, 0xD6BB, 0x7850, 0xD6BC, 0x7964, 0xD6BD, 0x7967, 0xD6BE, 0x7969, + 0xD6BF, 0x796A, 0xD6C0, 0x7963, 0xD6C1, 0x796B, 0xD6C2, 0x7961, 0xD6C3, 0x79BB, 0xD6C4, 0x79FA, 0xD6C5, 0x79F8, 0xD6C6, 0x79F6, + 0xD6C7, 0x79F7, 0xD6C8, 0x7A8F, 0xD6C9, 0x7A94, 0xD6CA, 0x7A90, 0xD6CB, 0x7B35, 0xD6CC, 0x7B47, 0xD6CD, 0x7B34, 0xD6CE, 0x7B25, + 0xD6CF, 0x7B30, 0xD6D0, 0x7B22, 0xD6D1, 0x7B24, 0xD6D2, 0x7B33, 0xD6D3, 0x7B18, 0xD6D4, 0x7B2A, 0xD6D5, 0x7B1D, 0xD6D6, 0x7B31, + 0xD6D7, 0x7B2B, 0xD6D8, 0x7B2D, 0xD6D9, 0x7B2F, 0xD6DA, 0x7B32, 0xD6DB, 0x7B38, 0xD6DC, 0x7B1A, 0xD6DD, 0x7B23, 0xD6DE, 0x7C94, + 0xD6DF, 0x7C98, 0xD6E0, 0x7C96, 0xD6E1, 0x7CA3, 0xD6E2, 0x7D35, 0xD6E3, 0x7D3D, 0xD6E4, 0x7D38, 0xD6E5, 0x7D36, 0xD6E6, 0x7D3A, + 0xD6E7, 0x7D45, 0xD6E8, 0x7D2C, 0xD6E9, 0x7D29, 0xD6EA, 0x7D41, 0xD6EB, 0x7D47, 0xD6EC, 0x7D3E, 0xD6ED, 0x7D3F, 0xD6EE, 0x7D4A, + 0xD6EF, 0x7D3B, 0xD6F0, 0x7D28, 0xD6F1, 0x7F63, 0xD6F2, 0x7F95, 0xD6F3, 0x7F9C, 0xD6F4, 0x7F9D, 0xD6F5, 0x7F9B, 0xD6F6, 0x7FCA, + 0xD6F7, 0x7FCB, 0xD6F8, 0x7FCD, 0xD6F9, 0x7FD0, 0xD6FA, 0x7FD1, 0xD6FB, 0x7FC7, 0xD6FC, 0x7FCF, 0xD6FD, 0x7FC9, 0xD6FE, 0x801F, + 0xD740, 0x801E, 0xD741, 0x801B, 0xD742, 0x8047, 0xD743, 0x8043, 0xD744, 0x8048, 0xD745, 0x8118, 0xD746, 0x8125, 0xD747, 0x8119, + 0xD748, 0x811B, 0xD749, 0x812D, 0xD74A, 0x811F, 0xD74B, 0x812C, 0xD74C, 0x811E, 0xD74D, 0x8121, 0xD74E, 0x8115, 0xD74F, 0x8127, + 0xD750, 0x811D, 0xD751, 0x8122, 0xD752, 0x8211, 0xD753, 0x8238, 0xD754, 0x8233, 0xD755, 0x823A, 0xD756, 0x8234, 0xD757, 0x8232, + 0xD758, 0x8274, 0xD759, 0x8390, 0xD75A, 0x83A3, 0xD75B, 0x83A8, 0xD75C, 0x838D, 0xD75D, 0x837A, 0xD75E, 0x8373, 0xD75F, 0x83A4, + 0xD760, 0x8374, 0xD761, 0x838F, 0xD762, 0x8381, 0xD763, 0x8395, 0xD764, 0x8399, 0xD765, 0x8375, 0xD766, 0x8394, 0xD767, 0x83A9, + 0xD768, 0x837D, 0xD769, 0x8383, 0xD76A, 0x838C, 0xD76B, 0x839D, 0xD76C, 0x839B, 0xD76D, 0x83AA, 0xD76E, 0x838B, 0xD76F, 0x837E, + 0xD770, 0x83A5, 0xD771, 0x83AF, 0xD772, 0x8388, 0xD773, 0x8397, 0xD774, 0x83B0, 0xD775, 0x837F, 0xD776, 0x83A6, 0xD777, 0x8387, + 0xD778, 0x83AE, 0xD779, 0x8376, 0xD77A, 0x839A, 0xD77B, 0x8659, 0xD77C, 0x8656, 0xD77D, 0x86BF, 0xD77E, 0x86B7, 0xD7A1, 0x86C2, + 0xD7A2, 0x86C1, 0xD7A3, 0x86C5, 0xD7A4, 0x86BA, 0xD7A5, 0x86B0, 0xD7A6, 0x86C8, 0xD7A7, 0x86B9, 0xD7A8, 0x86B3, 0xD7A9, 0x86B8, + 0xD7AA, 0x86CC, 0xD7AB, 0x86B4, 0xD7AC, 0x86BB, 0xD7AD, 0x86BC, 0xD7AE, 0x86C3, 0xD7AF, 0x86BD, 0xD7B0, 0x86BE, 0xD7B1, 0x8852, + 0xD7B2, 0x8889, 0xD7B3, 0x8895, 0xD7B4, 0x88A8, 0xD7B5, 0x88A2, 0xD7B6, 0x88AA, 0xD7B7, 0x889A, 0xD7B8, 0x8891, 0xD7B9, 0x88A1, + 0xD7BA, 0x889F, 0xD7BB, 0x8898, 0xD7BC, 0x88A7, 0xD7BD, 0x8899, 0xD7BE, 0x889B, 0xD7BF, 0x8897, 0xD7C0, 0x88A4, 0xD7C1, 0x88AC, + 0xD7C2, 0x888C, 0xD7C3, 0x8893, 0xD7C4, 0x888E, 0xD7C5, 0x8982, 0xD7C6, 0x89D6, 0xD7C7, 0x89D9, 0xD7C8, 0x89D5, 0xD7C9, 0x8A30, + 0xD7CA, 0x8A27, 0xD7CB, 0x8A2C, 0xD7CC, 0x8A1E, 0xD7CD, 0x8C39, 0xD7CE, 0x8C3B, 0xD7CF, 0x8C5C, 0xD7D0, 0x8C5D, 0xD7D1, 0x8C7D, + 0xD7D2, 0x8CA5, 0xD7D3, 0x8D7D, 0xD7D4, 0x8D7B, 0xD7D5, 0x8D79, 0xD7D6, 0x8DBC, 0xD7D7, 0x8DC2, 0xD7D8, 0x8DB9, 0xD7D9, 0x8DBF, + 0xD7DA, 0x8DC1, 0xD7DB, 0x8ED8, 0xD7DC, 0x8EDE, 0xD7DD, 0x8EDD, 0xD7DE, 0x8EDC, 0xD7DF, 0x8ED7, 0xD7E0, 0x8EE0, 0xD7E1, 0x8EE1, + 0xD7E2, 0x9024, 0xD7E3, 0x900B, 0xD7E4, 0x9011, 0xD7E5, 0x901C, 0xD7E6, 0x900C, 0xD7E7, 0x9021, 0xD7E8, 0x90EF, 0xD7E9, 0x90EA, + 0xD7EA, 0x90F0, 0xD7EB, 0x90F4, 0xD7EC, 0x90F2, 0xD7ED, 0x90F3, 0xD7EE, 0x90D4, 0xD7EF, 0x90EB, 0xD7F0, 0x90EC, 0xD7F1, 0x90E9, + 0xD7F2, 0x9156, 0xD7F3, 0x9158, 0xD7F4, 0x915A, 0xD7F5, 0x9153, 0xD7F6, 0x9155, 0xD7F7, 0x91EC, 0xD7F8, 0x91F4, 0xD7F9, 0x91F1, + 0xD7FA, 0x91F3, 0xD7FB, 0x91F8, 0xD7FC, 0x91E4, 0xD7FD, 0x91F9, 0xD7FE, 0x91EA, 0xD840, 0x91EB, 0xD841, 0x91F7, 0xD842, 0x91E8, + 0xD843, 0x91EE, 0xD844, 0x957A, 0xD845, 0x9586, 0xD846, 0x9588, 0xD847, 0x967C, 0xD848, 0x966D, 0xD849, 0x966B, 0xD84A, 0x9671, + 0xD84B, 0x966F, 0xD84C, 0x96BF, 0xD84D, 0x976A, 0xD84E, 0x9804, 0xD84F, 0x98E5, 0xD850, 0x9997, 0xD851, 0x509B, 0xD852, 0x5095, + 0xD853, 0x5094, 0xD854, 0x509E, 0xD855, 0x508B, 0xD856, 0x50A3, 0xD857, 0x5083, 0xD858, 0x508C, 0xD859, 0x508E, 0xD85A, 0x509D, + 0xD85B, 0x5068, 0xD85C, 0x509C, 0xD85D, 0x5092, 0xD85E, 0x5082, 0xD85F, 0x5087, 0xD860, 0x515F, 0xD861, 0x51D4, 0xD862, 0x5312, + 0xD863, 0x5311, 0xD864, 0x53A4, 0xD865, 0x53A7, 0xD866, 0x5591, 0xD867, 0x55A8, 0xD868, 0x55A5, 0xD869, 0x55AD, 0xD86A, 0x5577, + 0xD86B, 0x5645, 0xD86C, 0x55A2, 0xD86D, 0x5593, 0xD86E, 0x5588, 0xD86F, 0x558F, 0xD870, 0x55B5, 0xD871, 0x5581, 0xD872, 0x55A3, + 0xD873, 0x5592, 0xD874, 0x55A4, 0xD875, 0x557D, 0xD876, 0x558C, 0xD877, 0x55A6, 0xD878, 0x557F, 0xD879, 0x5595, 0xD87A, 0x55A1, + 0xD87B, 0x558E, 0xD87C, 0x570C, 0xD87D, 0x5829, 0xD87E, 0x5837, 0xD8A1, 0x5819, 0xD8A2, 0x581E, 0xD8A3, 0x5827, 0xD8A4, 0x5823, + 0xD8A5, 0x5828, 0xD8A6, 0x57F5, 0xD8A7, 0x5848, 0xD8A8, 0x5825, 0xD8A9, 0x581C, 0xD8AA, 0x581B, 0xD8AB, 0x5833, 0xD8AC, 0x583F, + 0xD8AD, 0x5836, 0xD8AE, 0x582E, 0xD8AF, 0x5839, 0xD8B0, 0x5838, 0xD8B1, 0x582D, 0xD8B2, 0x582C, 0xD8B3, 0x583B, 0xD8B4, 0x5961, + 0xD8B5, 0x5AAF, 0xD8B6, 0x5A94, 0xD8B7, 0x5A9F, 0xD8B8, 0x5A7A, 0xD8B9, 0x5AA2, 0xD8BA, 0x5A9E, 0xD8BB, 0x5A78, 0xD8BC, 0x5AA6, + 0xD8BD, 0x5A7C, 0xD8BE, 0x5AA5, 0xD8BF, 0x5AAC, 0xD8C0, 0x5A95, 0xD8C1, 0x5AAE, 0xD8C2, 0x5A37, 0xD8C3, 0x5A84, 0xD8C4, 0x5A8A, + 0xD8C5, 0x5A97, 0xD8C6, 0x5A83, 0xD8C7, 0x5A8B, 0xD8C8, 0x5AA9, 0xD8C9, 0x5A7B, 0xD8CA, 0x5A7D, 0xD8CB, 0x5A8C, 0xD8CC, 0x5A9C, + 0xD8CD, 0x5A8F, 0xD8CE, 0x5A93, 0xD8CF, 0x5A9D, 0xD8D0, 0x5BEA, 0xD8D1, 0x5BCD, 0xD8D2, 0x5BCB, 0xD8D3, 0x5BD4, 0xD8D4, 0x5BD1, + 0xD8D5, 0x5BCA, 0xD8D6, 0x5BCE, 0xD8D7, 0x5C0C, 0xD8D8, 0x5C30, 0xD8D9, 0x5D37, 0xD8DA, 0x5D43, 0xD8DB, 0x5D6B, 0xD8DC, 0x5D41, + 0xD8DD, 0x5D4B, 0xD8DE, 0x5D3F, 0xD8DF, 0x5D35, 0xD8E0, 0x5D51, 0xD8E1, 0x5D4E, 0xD8E2, 0x5D55, 0xD8E3, 0x5D33, 0xD8E4, 0x5D3A, + 0xD8E5, 0x5D52, 0xD8E6, 0x5D3D, 0xD8E7, 0x5D31, 0xD8E8, 0x5D59, 0xD8E9, 0x5D42, 0xD8EA, 0x5D39, 0xD8EB, 0x5D49, 0xD8EC, 0x5D38, + 0xD8ED, 0x5D3C, 0xD8EE, 0x5D32, 0xD8EF, 0x5D36, 0xD8F0, 0x5D40, 0xD8F1, 0x5D45, 0xD8F2, 0x5E44, 0xD8F3, 0x5E41, 0xD8F4, 0x5F58, + 0xD8F5, 0x5FA6, 0xD8F6, 0x5FA5, 0xD8F7, 0x5FAB, 0xD8F8, 0x60C9, 0xD8F9, 0x60B9, 0xD8FA, 0x60CC, 0xD8FB, 0x60E2, 0xD8FC, 0x60CE, + 0xD8FD, 0x60C4, 0xD8FE, 0x6114, 0xD940, 0x60F2, 0xD941, 0x610A, 0xD942, 0x6116, 0xD943, 0x6105, 0xD944, 0x60F5, 0xD945, 0x6113, + 0xD946, 0x60F8, 0xD947, 0x60FC, 0xD948, 0x60FE, 0xD949, 0x60C1, 0xD94A, 0x6103, 0xD94B, 0x6118, 0xD94C, 0x611D, 0xD94D, 0x6110, + 0xD94E, 0x60FF, 0xD94F, 0x6104, 0xD950, 0x610B, 0xD951, 0x624A, 0xD952, 0x6394, 0xD953, 0x63B1, 0xD954, 0x63B0, 0xD955, 0x63CE, + 0xD956, 0x63E5, 0xD957, 0x63E8, 0xD958, 0x63EF, 0xD959, 0x63C3, 0xD95A, 0x649D, 0xD95B, 0x63F3, 0xD95C, 0x63CA, 0xD95D, 0x63E0, + 0xD95E, 0x63F6, 0xD95F, 0x63D5, 0xD960, 0x63F2, 0xD961, 0x63F5, 0xD962, 0x6461, 0xD963, 0x63DF, 0xD964, 0x63BE, 0xD965, 0x63DD, + 0xD966, 0x63DC, 0xD967, 0x63C4, 0xD968, 0x63D8, 0xD969, 0x63D3, 0xD96A, 0x63C2, 0xD96B, 0x63C7, 0xD96C, 0x63CC, 0xD96D, 0x63CB, + 0xD96E, 0x63C8, 0xD96F, 0x63F0, 0xD970, 0x63D7, 0xD971, 0x63D9, 0xD972, 0x6532, 0xD973, 0x6567, 0xD974, 0x656A, 0xD975, 0x6564, + 0xD976, 0x655C, 0xD977, 0x6568, 0xD978, 0x6565, 0xD979, 0x658C, 0xD97A, 0x659D, 0xD97B, 0x659E, 0xD97C, 0x65AE, 0xD97D, 0x65D0, + 0xD97E, 0x65D2, 0xD9A1, 0x667C, 0xD9A2, 0x666C, 0xD9A3, 0x667B, 0xD9A4, 0x6680, 0xD9A5, 0x6671, 0xD9A6, 0x6679, 0xD9A7, 0x666A, + 0xD9A8, 0x6672, 0xD9A9, 0x6701, 0xD9AA, 0x690C, 0xD9AB, 0x68D3, 0xD9AC, 0x6904, 0xD9AD, 0x68DC, 0xD9AE, 0x692A, 0xD9AF, 0x68EC, + 0xD9B0, 0x68EA, 0xD9B1, 0x68F1, 0xD9B2, 0x690F, 0xD9B3, 0x68D6, 0xD9B4, 0x68F7, 0xD9B5, 0x68EB, 0xD9B6, 0x68E4, 0xD9B7, 0x68F6, + 0xD9B8, 0x6913, 0xD9B9, 0x6910, 0xD9BA, 0x68F3, 0xD9BB, 0x68E1, 0xD9BC, 0x6907, 0xD9BD, 0x68CC, 0xD9BE, 0x6908, 0xD9BF, 0x6970, + 0xD9C0, 0x68B4, 0xD9C1, 0x6911, 0xD9C2, 0x68EF, 0xD9C3, 0x68C6, 0xD9C4, 0x6914, 0xD9C5, 0x68F8, 0xD9C6, 0x68D0, 0xD9C7, 0x68FD, + 0xD9C8, 0x68FC, 0xD9C9, 0x68E8, 0xD9CA, 0x690B, 0xD9CB, 0x690A, 0xD9CC, 0x6917, 0xD9CD, 0x68CE, 0xD9CE, 0x68C8, 0xD9CF, 0x68DD, + 0xD9D0, 0x68DE, 0xD9D1, 0x68E6, 0xD9D2, 0x68F4, 0xD9D3, 0x68D1, 0xD9D4, 0x6906, 0xD9D5, 0x68D4, 0xD9D6, 0x68E9, 0xD9D7, 0x6915, + 0xD9D8, 0x6925, 0xD9D9, 0x68C7, 0xD9DA, 0x6B39, 0xD9DB, 0x6B3B, 0xD9DC, 0x6B3F, 0xD9DD, 0x6B3C, 0xD9DE, 0x6B94, 0xD9DF, 0x6B97, + 0xD9E0, 0x6B99, 0xD9E1, 0x6B95, 0xD9E2, 0x6BBD, 0xD9E3, 0x6BF0, 0xD9E4, 0x6BF2, 0xD9E5, 0x6BF3, 0xD9E6, 0x6C30, 0xD9E7, 0x6DFC, + 0xD9E8, 0x6E46, 0xD9E9, 0x6E47, 0xD9EA, 0x6E1F, 0xD9EB, 0x6E49, 0xD9EC, 0x6E88, 0xD9ED, 0x6E3C, 0xD9EE, 0x6E3D, 0xD9EF, 0x6E45, + 0xD9F0, 0x6E62, 0xD9F1, 0x6E2B, 0xD9F2, 0x6E3F, 0xD9F3, 0x6E41, 0xD9F4, 0x6E5D, 0xD9F5, 0x6E73, 0xD9F6, 0x6E1C, 0xD9F7, 0x6E33, + 0xD9F8, 0x6E4B, 0xD9F9, 0x6E40, 0xD9FA, 0x6E51, 0xD9FB, 0x6E3B, 0xD9FC, 0x6E03, 0xD9FD, 0x6E2E, 0xD9FE, 0x6E5E, 0xDA40, 0x6E68, + 0xDA41, 0x6E5C, 0xDA42, 0x6E61, 0xDA43, 0x6E31, 0xDA44, 0x6E28, 0xDA45, 0x6E60, 0xDA46, 0x6E71, 0xDA47, 0x6E6B, 0xDA48, 0x6E39, + 0xDA49, 0x6E22, 0xDA4A, 0x6E30, 0xDA4B, 0x6E53, 0xDA4C, 0x6E65, 0xDA4D, 0x6E27, 0xDA4E, 0x6E78, 0xDA4F, 0x6E64, 0xDA50, 0x6E77, + 0xDA51, 0x6E55, 0xDA52, 0x6E79, 0xDA53, 0x6E52, 0xDA54, 0x6E66, 0xDA55, 0x6E35, 0xDA56, 0x6E36, 0xDA57, 0x6E5A, 0xDA58, 0x7120, + 0xDA59, 0x711E, 0xDA5A, 0x712F, 0xDA5B, 0x70FB, 0xDA5C, 0x712E, 0xDA5D, 0x7131, 0xDA5E, 0x7123, 0xDA5F, 0x7125, 0xDA60, 0x7122, + 0xDA61, 0x7132, 0xDA62, 0x711F, 0xDA63, 0x7128, 0xDA64, 0x713A, 0xDA65, 0x711B, 0xDA66, 0x724B, 0xDA67, 0x725A, 0xDA68, 0x7288, + 0xDA69, 0x7289, 0xDA6A, 0x7286, 0xDA6B, 0x7285, 0xDA6C, 0x728B, 0xDA6D, 0x7312, 0xDA6E, 0x730B, 0xDA6F, 0x7330, 0xDA70, 0x7322, + 0xDA71, 0x7331, 0xDA72, 0x7333, 0xDA73, 0x7327, 0xDA74, 0x7332, 0xDA75, 0x732D, 0xDA76, 0x7326, 0xDA77, 0x7323, 0xDA78, 0x7335, + 0xDA79, 0x730C, 0xDA7A, 0x742E, 0xDA7B, 0x742C, 0xDA7C, 0x7430, 0xDA7D, 0x742B, 0xDA7E, 0x7416, 0xDAA1, 0x741A, 0xDAA2, 0x7421, + 0xDAA3, 0x742D, 0xDAA4, 0x7431, 0xDAA5, 0x7424, 0xDAA6, 0x7423, 0xDAA7, 0x741D, 0xDAA8, 0x7429, 0xDAA9, 0x7420, 0xDAAA, 0x7432, + 0xDAAB, 0x74FB, 0xDAAC, 0x752F, 0xDAAD, 0x756F, 0xDAAE, 0x756C, 0xDAAF, 0x75E7, 0xDAB0, 0x75DA, 0xDAB1, 0x75E1, 0xDAB2, 0x75E6, + 0xDAB3, 0x75DD, 0xDAB4, 0x75DF, 0xDAB5, 0x75E4, 0xDAB6, 0x75D7, 0xDAB7, 0x7695, 0xDAB8, 0x7692, 0xDAB9, 0x76DA, 0xDABA, 0x7746, + 0xDABB, 0x7747, 0xDABC, 0x7744, 0xDABD, 0x774D, 0xDABE, 0x7745, 0xDABF, 0x774A, 0xDAC0, 0x774E, 0xDAC1, 0x774B, 0xDAC2, 0x774C, + 0xDAC3, 0x77DE, 0xDAC4, 0x77EC, 0xDAC5, 0x7860, 0xDAC6, 0x7864, 0xDAC7, 0x7865, 0xDAC8, 0x785C, 0xDAC9, 0x786D, 0xDACA, 0x7871, + 0xDACB, 0x786A, 0xDACC, 0x786E, 0xDACD, 0x7870, 0xDACE, 0x7869, 0xDACF, 0x7868, 0xDAD0, 0x785E, 0xDAD1, 0x7862, 0xDAD2, 0x7974, + 0xDAD3, 0x7973, 0xDAD4, 0x7972, 0xDAD5, 0x7970, 0xDAD6, 0x7A02, 0xDAD7, 0x7A0A, 0xDAD8, 0x7A03, 0xDAD9, 0x7A0C, 0xDADA, 0x7A04, + 0xDADB, 0x7A99, 0xDADC, 0x7AE6, 0xDADD, 0x7AE4, 0xDADE, 0x7B4A, 0xDADF, 0x7B3B, 0xDAE0, 0x7B44, 0xDAE1, 0x7B48, 0xDAE2, 0x7B4C, + 0xDAE3, 0x7B4E, 0xDAE4, 0x7B40, 0xDAE5, 0x7B58, 0xDAE6, 0x7B45, 0xDAE7, 0x7CA2, 0xDAE8, 0x7C9E, 0xDAE9, 0x7CA8, 0xDAEA, 0x7CA1, + 0xDAEB, 0x7D58, 0xDAEC, 0x7D6F, 0xDAED, 0x7D63, 0xDAEE, 0x7D53, 0xDAEF, 0x7D56, 0xDAF0, 0x7D67, 0xDAF1, 0x7D6A, 0xDAF2, 0x7D4F, + 0xDAF3, 0x7D6D, 0xDAF4, 0x7D5C, 0xDAF5, 0x7D6B, 0xDAF6, 0x7D52, 0xDAF7, 0x7D54, 0xDAF8, 0x7D69, 0xDAF9, 0x7D51, 0xDAFA, 0x7D5F, + 0xDAFB, 0x7D4E, 0xDAFC, 0x7F3E, 0xDAFD, 0x7F3F, 0xDAFE, 0x7F65, 0xDB40, 0x7F66, 0xDB41, 0x7FA2, 0xDB42, 0x7FA0, 0xDB43, 0x7FA1, + 0xDB44, 0x7FD7, 0xDB45, 0x8051, 0xDB46, 0x804F, 0xDB47, 0x8050, 0xDB48, 0x80FE, 0xDB49, 0x80D4, 0xDB4A, 0x8143, 0xDB4B, 0x814A, + 0xDB4C, 0x8152, 0xDB4D, 0x814F, 0xDB4E, 0x8147, 0xDB4F, 0x813D, 0xDB50, 0x814D, 0xDB51, 0x813A, 0xDB52, 0x81E6, 0xDB53, 0x81EE, + 0xDB54, 0x81F7, 0xDB55, 0x81F8, 0xDB56, 0x81F9, 0xDB57, 0x8204, 0xDB58, 0x823C, 0xDB59, 0x823D, 0xDB5A, 0x823F, 0xDB5B, 0x8275, + 0xDB5C, 0x833B, 0xDB5D, 0x83CF, 0xDB5E, 0x83F9, 0xDB5F, 0x8423, 0xDB60, 0x83C0, 0xDB61, 0x83E8, 0xDB62, 0x8412, 0xDB63, 0x83E7, + 0xDB64, 0x83E4, 0xDB65, 0x83FC, 0xDB66, 0x83F6, 0xDB67, 0x8410, 0xDB68, 0x83C6, 0xDB69, 0x83C8, 0xDB6A, 0x83EB, 0xDB6B, 0x83E3, + 0xDB6C, 0x83BF, 0xDB6D, 0x8401, 0xDB6E, 0x83DD, 0xDB6F, 0x83E5, 0xDB70, 0x83D8, 0xDB71, 0x83FF, 0xDB72, 0x83E1, 0xDB73, 0x83CB, + 0xDB74, 0x83CE, 0xDB75, 0x83D6, 0xDB76, 0x83F5, 0xDB77, 0x83C9, 0xDB78, 0x8409, 0xDB79, 0x840F, 0xDB7A, 0x83DE, 0xDB7B, 0x8411, + 0xDB7C, 0x8406, 0xDB7D, 0x83C2, 0xDB7E, 0x83F3, 0xDBA1, 0x83D5, 0xDBA2, 0x83FA, 0xDBA3, 0x83C7, 0xDBA4, 0x83D1, 0xDBA5, 0x83EA, + 0xDBA6, 0x8413, 0xDBA7, 0x83C3, 0xDBA8, 0x83EC, 0xDBA9, 0x83EE, 0xDBAA, 0x83C4, 0xDBAB, 0x83FB, 0xDBAC, 0x83D7, 0xDBAD, 0x83E2, + 0xDBAE, 0x841B, 0xDBAF, 0x83DB, 0xDBB0, 0x83FE, 0xDBB1, 0x86D8, 0xDBB2, 0x86E2, 0xDBB3, 0x86E6, 0xDBB4, 0x86D3, 0xDBB5, 0x86E3, + 0xDBB6, 0x86DA, 0xDBB7, 0x86EA, 0xDBB8, 0x86DD, 0xDBB9, 0x86EB, 0xDBBA, 0x86DC, 0xDBBB, 0x86EC, 0xDBBC, 0x86E9, 0xDBBD, 0x86D7, + 0xDBBE, 0x86E8, 0xDBBF, 0x86D1, 0xDBC0, 0x8848, 0xDBC1, 0x8856, 0xDBC2, 0x8855, 0xDBC3, 0x88BA, 0xDBC4, 0x88D7, 0xDBC5, 0x88B9, + 0xDBC6, 0x88B8, 0xDBC7, 0x88C0, 0xDBC8, 0x88BE, 0xDBC9, 0x88B6, 0xDBCA, 0x88BC, 0xDBCB, 0x88B7, 0xDBCC, 0x88BD, 0xDBCD, 0x88B2, + 0xDBCE, 0x8901, 0xDBCF, 0x88C9, 0xDBD0, 0x8995, 0xDBD1, 0x8998, 0xDBD2, 0x8997, 0xDBD3, 0x89DD, 0xDBD4, 0x89DA, 0xDBD5, 0x89DB, + 0xDBD6, 0x8A4E, 0xDBD7, 0x8A4D, 0xDBD8, 0x8A39, 0xDBD9, 0x8A59, 0xDBDA, 0x8A40, 0xDBDB, 0x8A57, 0xDBDC, 0x8A58, 0xDBDD, 0x8A44, + 0xDBDE, 0x8A45, 0xDBDF, 0x8A52, 0xDBE0, 0x8A48, 0xDBE1, 0x8A51, 0xDBE2, 0x8A4A, 0xDBE3, 0x8A4C, 0xDBE4, 0x8A4F, 0xDBE5, 0x8C5F, + 0xDBE6, 0x8C81, 0xDBE7, 0x8C80, 0xDBE8, 0x8CBA, 0xDBE9, 0x8CBE, 0xDBEA, 0x8CB0, 0xDBEB, 0x8CB9, 0xDBEC, 0x8CB5, 0xDBED, 0x8D84, + 0xDBEE, 0x8D80, 0xDBEF, 0x8D89, 0xDBF0, 0x8DD8, 0xDBF1, 0x8DD3, 0xDBF2, 0x8DCD, 0xDBF3, 0x8DC7, 0xDBF4, 0x8DD6, 0xDBF5, 0x8DDC, + 0xDBF6, 0x8DCF, 0xDBF7, 0x8DD5, 0xDBF8, 0x8DD9, 0xDBF9, 0x8DC8, 0xDBFA, 0x8DD7, 0xDBFB, 0x8DC5, 0xDBFC, 0x8EEF, 0xDBFD, 0x8EF7, + 0xDBFE, 0x8EFA, 0xDC40, 0x8EF9, 0xDC41, 0x8EE6, 0xDC42, 0x8EEE, 0xDC43, 0x8EE5, 0xDC44, 0x8EF5, 0xDC45, 0x8EE7, 0xDC46, 0x8EE8, + 0xDC47, 0x8EF6, 0xDC48, 0x8EEB, 0xDC49, 0x8EF1, 0xDC4A, 0x8EEC, 0xDC4B, 0x8EF4, 0xDC4C, 0x8EE9, 0xDC4D, 0x902D, 0xDC4E, 0x9034, + 0xDC4F, 0x902F, 0xDC50, 0x9106, 0xDC51, 0x912C, 0xDC52, 0x9104, 0xDC53, 0x90FF, 0xDC54, 0x90FC, 0xDC55, 0x9108, 0xDC56, 0x90F9, + 0xDC57, 0x90FB, 0xDC58, 0x9101, 0xDC59, 0x9100, 0xDC5A, 0x9107, 0xDC5B, 0x9105, 0xDC5C, 0x9103, 0xDC5D, 0x9161, 0xDC5E, 0x9164, + 0xDC5F, 0x915F, 0xDC60, 0x9162, 0xDC61, 0x9160, 0xDC62, 0x9201, 0xDC63, 0x920A, 0xDC64, 0x9225, 0xDC65, 0x9203, 0xDC66, 0x921A, + 0xDC67, 0x9226, 0xDC68, 0x920F, 0xDC69, 0x920C, 0xDC6A, 0x9200, 0xDC6B, 0x9212, 0xDC6C, 0x91FF, 0xDC6D, 0x91FD, 0xDC6E, 0x9206, + 0xDC6F, 0x9204, 0xDC70, 0x9227, 0xDC71, 0x9202, 0xDC72, 0x921C, 0xDC73, 0x9224, 0xDC74, 0x9219, 0xDC75, 0x9217, 0xDC76, 0x9205, + 0xDC77, 0x9216, 0xDC78, 0x957B, 0xDC79, 0x958D, 0xDC7A, 0x958C, 0xDC7B, 0x9590, 0xDC7C, 0x9687, 0xDC7D, 0x967E, 0xDC7E, 0x9688, + 0xDCA1, 0x9689, 0xDCA2, 0x9683, 0xDCA3, 0x9680, 0xDCA4, 0x96C2, 0xDCA5, 0x96C8, 0xDCA6, 0x96C3, 0xDCA7, 0x96F1, 0xDCA8, 0x96F0, + 0xDCA9, 0x976C, 0xDCAA, 0x9770, 0xDCAB, 0x976E, 0xDCAC, 0x9807, 0xDCAD, 0x98A9, 0xDCAE, 0x98EB, 0xDCAF, 0x9CE6, 0xDCB0, 0x9EF9, + 0xDCB1, 0x4E83, 0xDCB2, 0x4E84, 0xDCB3, 0x4EB6, 0xDCB4, 0x50BD, 0xDCB5, 0x50BF, 0xDCB6, 0x50C6, 0xDCB7, 0x50AE, 0xDCB8, 0x50C4, + 0xDCB9, 0x50CA, 0xDCBA, 0x50B4, 0xDCBB, 0x50C8, 0xDCBC, 0x50C2, 0xDCBD, 0x50B0, 0xDCBE, 0x50C1, 0xDCBF, 0x50BA, 0xDCC0, 0x50B1, + 0xDCC1, 0x50CB, 0xDCC2, 0x50C9, 0xDCC3, 0x50B6, 0xDCC4, 0x50B8, 0xDCC5, 0x51D7, 0xDCC6, 0x527A, 0xDCC7, 0x5278, 0xDCC8, 0x527B, + 0xDCC9, 0x527C, 0xDCCA, 0x55C3, 0xDCCB, 0x55DB, 0xDCCC, 0x55CC, 0xDCCD, 0x55D0, 0xDCCE, 0x55CB, 0xDCCF, 0x55CA, 0xDCD0, 0x55DD, + 0xDCD1, 0x55C0, 0xDCD2, 0x55D4, 0xDCD3, 0x55C4, 0xDCD4, 0x55E9, 0xDCD5, 0x55BF, 0xDCD6, 0x55D2, 0xDCD7, 0x558D, 0xDCD8, 0x55CF, + 0xDCD9, 0x55D5, 0xDCDA, 0x55E2, 0xDCDB, 0x55D6, 0xDCDC, 0x55C8, 0xDCDD, 0x55F2, 0xDCDE, 0x55CD, 0xDCDF, 0x55D9, 0xDCE0, 0x55C2, + 0xDCE1, 0x5714, 0xDCE2, 0x5853, 0xDCE3, 0x5868, 0xDCE4, 0x5864, 0xDCE5, 0x584F, 0xDCE6, 0x584D, 0xDCE7, 0x5849, 0xDCE8, 0x586F, + 0xDCE9, 0x5855, 0xDCEA, 0x584E, 0xDCEB, 0x585D, 0xDCEC, 0x5859, 0xDCED, 0x5865, 0xDCEE, 0x585B, 0xDCEF, 0x583D, 0xDCF0, 0x5863, + 0xDCF1, 0x5871, 0xDCF2, 0x58FC, 0xDCF3, 0x5AC7, 0xDCF4, 0x5AC4, 0xDCF5, 0x5ACB, 0xDCF6, 0x5ABA, 0xDCF7, 0x5AB8, 0xDCF8, 0x5AB1, + 0xDCF9, 0x5AB5, 0xDCFA, 0x5AB0, 0xDCFB, 0x5ABF, 0xDCFC, 0x5AC8, 0xDCFD, 0x5ABB, 0xDCFE, 0x5AC6, 0xDD40, 0x5AB7, 0xDD41, 0x5AC0, + 0xDD42, 0x5ACA, 0xDD43, 0x5AB4, 0xDD44, 0x5AB6, 0xDD45, 0x5ACD, 0xDD46, 0x5AB9, 0xDD47, 0x5A90, 0xDD48, 0x5BD6, 0xDD49, 0x5BD8, + 0xDD4A, 0x5BD9, 0xDD4B, 0x5C1F, 0xDD4C, 0x5C33, 0xDD4D, 0x5D71, 0xDD4E, 0x5D63, 0xDD4F, 0x5D4A, 0xDD50, 0x5D65, 0xDD51, 0x5D72, + 0xDD52, 0x5D6C, 0xDD53, 0x5D5E, 0xDD54, 0x5D68, 0xDD55, 0x5D67, 0xDD56, 0x5D62, 0xDD57, 0x5DF0, 0xDD58, 0x5E4F, 0xDD59, 0x5E4E, + 0xDD5A, 0x5E4A, 0xDD5B, 0x5E4D, 0xDD5C, 0x5E4B, 0xDD5D, 0x5EC5, 0xDD5E, 0x5ECC, 0xDD5F, 0x5EC6, 0xDD60, 0x5ECB, 0xDD61, 0x5EC7, + 0xDD62, 0x5F40, 0xDD63, 0x5FAF, 0xDD64, 0x5FAD, 0xDD65, 0x60F7, 0xDD66, 0x6149, 0xDD67, 0x614A, 0xDD68, 0x612B, 0xDD69, 0x6145, + 0xDD6A, 0x6136, 0xDD6B, 0x6132, 0xDD6C, 0x612E, 0xDD6D, 0x6146, 0xDD6E, 0x612F, 0xDD6F, 0x614F, 0xDD70, 0x6129, 0xDD71, 0x6140, + 0xDD72, 0x6220, 0xDD73, 0x9168, 0xDD74, 0x6223, 0xDD75, 0x6225, 0xDD76, 0x6224, 0xDD77, 0x63C5, 0xDD78, 0x63F1, 0xDD79, 0x63EB, + 0xDD7A, 0x6410, 0xDD7B, 0x6412, 0xDD7C, 0x6409, 0xDD7D, 0x6420, 0xDD7E, 0x6424, 0xDDA1, 0x6433, 0xDDA2, 0x6443, 0xDDA3, 0x641F, + 0xDDA4, 0x6415, 0xDDA5, 0x6418, 0xDDA6, 0x6439, 0xDDA7, 0x6437, 0xDDA8, 0x6422, 0xDDA9, 0x6423, 0xDDAA, 0x640C, 0xDDAB, 0x6426, + 0xDDAC, 0x6430, 0xDDAD, 0x6428, 0xDDAE, 0x6441, 0xDDAF, 0x6435, 0xDDB0, 0x642F, 0xDDB1, 0x640A, 0xDDB2, 0x641A, 0xDDB3, 0x6440, + 0xDDB4, 0x6425, 0xDDB5, 0x6427, 0xDDB6, 0x640B, 0xDDB7, 0x63E7, 0xDDB8, 0x641B, 0xDDB9, 0x642E, 0xDDBA, 0x6421, 0xDDBB, 0x640E, + 0xDDBC, 0x656F, 0xDDBD, 0x6592, 0xDDBE, 0x65D3, 0xDDBF, 0x6686, 0xDDC0, 0x668C, 0xDDC1, 0x6695, 0xDDC2, 0x6690, 0xDDC3, 0x668B, + 0xDDC4, 0x668A, 0xDDC5, 0x6699, 0xDDC6, 0x6694, 0xDDC7, 0x6678, 0xDDC8, 0x6720, 0xDDC9, 0x6966, 0xDDCA, 0x695F, 0xDDCB, 0x6938, + 0xDDCC, 0x694E, 0xDDCD, 0x6962, 0xDDCE, 0x6971, 0xDDCF, 0x693F, 0xDDD0, 0x6945, 0xDDD1, 0x696A, 0xDDD2, 0x6939, 0xDDD3, 0x6942, + 0xDDD4, 0x6957, 0xDDD5, 0x6959, 0xDDD6, 0x697A, 0xDDD7, 0x6948, 0xDDD8, 0x6949, 0xDDD9, 0x6935, 0xDDDA, 0x696C, 0xDDDB, 0x6933, + 0xDDDC, 0x693D, 0xDDDD, 0x6965, 0xDDDE, 0x68F0, 0xDDDF, 0x6978, 0xDDE0, 0x6934, 0xDDE1, 0x6969, 0xDDE2, 0x6940, 0xDDE3, 0x696F, + 0xDDE4, 0x6944, 0xDDE5, 0x6976, 0xDDE6, 0x6958, 0xDDE7, 0x6941, 0xDDE8, 0x6974, 0xDDE9, 0x694C, 0xDDEA, 0x693B, 0xDDEB, 0x694B, + 0xDDEC, 0x6937, 0xDDED, 0x695C, 0xDDEE, 0x694F, 0xDDEF, 0x6951, 0xDDF0, 0x6932, 0xDDF1, 0x6952, 0xDDF2, 0x692F, 0xDDF3, 0x697B, + 0xDDF4, 0x693C, 0xDDF5, 0x6B46, 0xDDF6, 0x6B45, 0xDDF7, 0x6B43, 0xDDF8, 0x6B42, 0xDDF9, 0x6B48, 0xDDFA, 0x6B41, 0xDDFB, 0x6B9B, + 0xDDFC, 0xFA0D, 0xDDFD, 0x6BFB, 0xDDFE, 0x6BFC, 0xDE40, 0x6BF9, 0xDE41, 0x6BF7, 0xDE42, 0x6BF8, 0xDE43, 0x6E9B, 0xDE44, 0x6ED6, + 0xDE45, 0x6EC8, 0xDE46, 0x6E8F, 0xDE47, 0x6EC0, 0xDE48, 0x6E9F, 0xDE49, 0x6E93, 0xDE4A, 0x6E94, 0xDE4B, 0x6EA0, 0xDE4C, 0x6EB1, + 0xDE4D, 0x6EB9, 0xDE4E, 0x6EC6, 0xDE4F, 0x6ED2, 0xDE50, 0x6EBD, 0xDE51, 0x6EC1, 0xDE52, 0x6E9E, 0xDE53, 0x6EC9, 0xDE54, 0x6EB7, + 0xDE55, 0x6EB0, 0xDE56, 0x6ECD, 0xDE57, 0x6EA6, 0xDE58, 0x6ECF, 0xDE59, 0x6EB2, 0xDE5A, 0x6EBE, 0xDE5B, 0x6EC3, 0xDE5C, 0x6EDC, + 0xDE5D, 0x6ED8, 0xDE5E, 0x6E99, 0xDE5F, 0x6E92, 0xDE60, 0x6E8E, 0xDE61, 0x6E8D, 0xDE62, 0x6EA4, 0xDE63, 0x6EA1, 0xDE64, 0x6EBF, + 0xDE65, 0x6EB3, 0xDE66, 0x6ED0, 0xDE67, 0x6ECA, 0xDE68, 0x6E97, 0xDE69, 0x6EAE, 0xDE6A, 0x6EA3, 0xDE6B, 0x7147, 0xDE6C, 0x7154, + 0xDE6D, 0x7152, 0xDE6E, 0x7163, 0xDE6F, 0x7160, 0xDE70, 0x7141, 0xDE71, 0x715D, 0xDE72, 0x7162, 0xDE73, 0x7172, 0xDE74, 0x7178, + 0xDE75, 0x716A, 0xDE76, 0x7161, 0xDE77, 0x7142, 0xDE78, 0x7158, 0xDE79, 0x7143, 0xDE7A, 0x714B, 0xDE7B, 0x7170, 0xDE7C, 0x715F, + 0xDE7D, 0x7150, 0xDE7E, 0x7153, 0xDEA1, 0x7144, 0xDEA2, 0x714D, 0xDEA3, 0x715A, 0xDEA4, 0x724F, 0xDEA5, 0x728D, 0xDEA6, 0x728C, + 0xDEA7, 0x7291, 0xDEA8, 0x7290, 0xDEA9, 0x728E, 0xDEAA, 0x733C, 0xDEAB, 0x7342, 0xDEAC, 0x733B, 0xDEAD, 0x733A, 0xDEAE, 0x7340, + 0xDEAF, 0x734A, 0xDEB0, 0x7349, 0xDEB1, 0x7444, 0xDEB2, 0x744A, 0xDEB3, 0x744B, 0xDEB4, 0x7452, 0xDEB5, 0x7451, 0xDEB6, 0x7457, + 0xDEB7, 0x7440, 0xDEB8, 0x744F, 0xDEB9, 0x7450, 0xDEBA, 0x744E, 0xDEBB, 0x7442, 0xDEBC, 0x7446, 0xDEBD, 0x744D, 0xDEBE, 0x7454, + 0xDEBF, 0x74E1, 0xDEC0, 0x74FF, 0xDEC1, 0x74FE, 0xDEC2, 0x74FD, 0xDEC3, 0x751D, 0xDEC4, 0x7579, 0xDEC5, 0x7577, 0xDEC6, 0x6983, + 0xDEC7, 0x75EF, 0xDEC8, 0x760F, 0xDEC9, 0x7603, 0xDECA, 0x75F7, 0xDECB, 0x75FE, 0xDECC, 0x75FC, 0xDECD, 0x75F9, 0xDECE, 0x75F8, + 0xDECF, 0x7610, 0xDED0, 0x75FB, 0xDED1, 0x75F6, 0xDED2, 0x75ED, 0xDED3, 0x75F5, 0xDED4, 0x75FD, 0xDED5, 0x7699, 0xDED6, 0x76B5, + 0xDED7, 0x76DD, 0xDED8, 0x7755, 0xDED9, 0x775F, 0xDEDA, 0x7760, 0xDEDB, 0x7752, 0xDEDC, 0x7756, 0xDEDD, 0x775A, 0xDEDE, 0x7769, + 0xDEDF, 0x7767, 0xDEE0, 0x7754, 0xDEE1, 0x7759, 0xDEE2, 0x776D, 0xDEE3, 0x77E0, 0xDEE4, 0x7887, 0xDEE5, 0x789A, 0xDEE6, 0x7894, + 0xDEE7, 0x788F, 0xDEE8, 0x7884, 0xDEE9, 0x7895, 0xDEEA, 0x7885, 0xDEEB, 0x7886, 0xDEEC, 0x78A1, 0xDEED, 0x7883, 0xDEEE, 0x7879, + 0xDEEF, 0x7899, 0xDEF0, 0x7880, 0xDEF1, 0x7896, 0xDEF2, 0x787B, 0xDEF3, 0x797C, 0xDEF4, 0x7982, 0xDEF5, 0x797D, 0xDEF6, 0x7979, + 0xDEF7, 0x7A11, 0xDEF8, 0x7A18, 0xDEF9, 0x7A19, 0xDEFA, 0x7A12, 0xDEFB, 0x7A17, 0xDEFC, 0x7A15, 0xDEFD, 0x7A22, 0xDEFE, 0x7A13, + 0xDF40, 0x7A1B, 0xDF41, 0x7A10, 0xDF42, 0x7AA3, 0xDF43, 0x7AA2, 0xDF44, 0x7A9E, 0xDF45, 0x7AEB, 0xDF46, 0x7B66, 0xDF47, 0x7B64, + 0xDF48, 0x7B6D, 0xDF49, 0x7B74, 0xDF4A, 0x7B69, 0xDF4B, 0x7B72, 0xDF4C, 0x7B65, 0xDF4D, 0x7B73, 0xDF4E, 0x7B71, 0xDF4F, 0x7B70, + 0xDF50, 0x7B61, 0xDF51, 0x7B78, 0xDF52, 0x7B76, 0xDF53, 0x7B63, 0xDF54, 0x7CB2, 0xDF55, 0x7CB4, 0xDF56, 0x7CAF, 0xDF57, 0x7D88, + 0xDF58, 0x7D86, 0xDF59, 0x7D80, 0xDF5A, 0x7D8D, 0xDF5B, 0x7D7F, 0xDF5C, 0x7D85, 0xDF5D, 0x7D7A, 0xDF5E, 0x7D8E, 0xDF5F, 0x7D7B, + 0xDF60, 0x7D83, 0xDF61, 0x7D7C, 0xDF62, 0x7D8C, 0xDF63, 0x7D94, 0xDF64, 0x7D84, 0xDF65, 0x7D7D, 0xDF66, 0x7D92, 0xDF67, 0x7F6D, + 0xDF68, 0x7F6B, 0xDF69, 0x7F67, 0xDF6A, 0x7F68, 0xDF6B, 0x7F6C, 0xDF6C, 0x7FA6, 0xDF6D, 0x7FA5, 0xDF6E, 0x7FA7, 0xDF6F, 0x7FDB, + 0xDF70, 0x7FDC, 0xDF71, 0x8021, 0xDF72, 0x8164, 0xDF73, 0x8160, 0xDF74, 0x8177, 0xDF75, 0x815C, 0xDF76, 0x8169, 0xDF77, 0x815B, + 0xDF78, 0x8162, 0xDF79, 0x8172, 0xDF7A, 0x6721, 0xDF7B, 0x815E, 0xDF7C, 0x8176, 0xDF7D, 0x8167, 0xDF7E, 0x816F, 0xDFA1, 0x8144, + 0xDFA2, 0x8161, 0xDFA3, 0x821D, 0xDFA4, 0x8249, 0xDFA5, 0x8244, 0xDFA6, 0x8240, 0xDFA7, 0x8242, 0xDFA8, 0x8245, 0xDFA9, 0x84F1, + 0xDFAA, 0x843F, 0xDFAB, 0x8456, 0xDFAC, 0x8476, 0xDFAD, 0x8479, 0xDFAE, 0x848F, 0xDFAF, 0x848D, 0xDFB0, 0x8465, 0xDFB1, 0x8451, + 0xDFB2, 0x8440, 0xDFB3, 0x8486, 0xDFB4, 0x8467, 0xDFB5, 0x8430, 0xDFB6, 0x844D, 0xDFB7, 0x847D, 0xDFB8, 0x845A, 0xDFB9, 0x8459, + 0xDFBA, 0x8474, 0xDFBB, 0x8473, 0xDFBC, 0x845D, 0xDFBD, 0x8507, 0xDFBE, 0x845E, 0xDFBF, 0x8437, 0xDFC0, 0x843A, 0xDFC1, 0x8434, + 0xDFC2, 0x847A, 0xDFC3, 0x8443, 0xDFC4, 0x8478, 0xDFC5, 0x8432, 0xDFC6, 0x8445, 0xDFC7, 0x8429, 0xDFC8, 0x83D9, 0xDFC9, 0x844B, + 0xDFCA, 0x842F, 0xDFCB, 0x8442, 0xDFCC, 0x842D, 0xDFCD, 0x845F, 0xDFCE, 0x8470, 0xDFCF, 0x8439, 0xDFD0, 0x844E, 0xDFD1, 0x844C, + 0xDFD2, 0x8452, 0xDFD3, 0x846F, 0xDFD4, 0x84C5, 0xDFD5, 0x848E, 0xDFD6, 0x843B, 0xDFD7, 0x8447, 0xDFD8, 0x8436, 0xDFD9, 0x8433, + 0xDFDA, 0x8468, 0xDFDB, 0x847E, 0xDFDC, 0x8444, 0xDFDD, 0x842B, 0xDFDE, 0x8460, 0xDFDF, 0x8454, 0xDFE0, 0x846E, 0xDFE1, 0x8450, + 0xDFE2, 0x870B, 0xDFE3, 0x8704, 0xDFE4, 0x86F7, 0xDFE5, 0x870C, 0xDFE6, 0x86FA, 0xDFE7, 0x86D6, 0xDFE8, 0x86F5, 0xDFE9, 0x874D, + 0xDFEA, 0x86F8, 0xDFEB, 0x870E, 0xDFEC, 0x8709, 0xDFED, 0x8701, 0xDFEE, 0x86F6, 0xDFEF, 0x870D, 0xDFF0, 0x8705, 0xDFF1, 0x88D6, + 0xDFF2, 0x88CB, 0xDFF3, 0x88CD, 0xDFF4, 0x88CE, 0xDFF5, 0x88DE, 0xDFF6, 0x88DB, 0xDFF7, 0x88DA, 0xDFF8, 0x88CC, 0xDFF9, 0x88D0, + 0xDFFA, 0x8985, 0xDFFB, 0x899B, 0xDFFC, 0x89DF, 0xDFFD, 0x89E5, 0xDFFE, 0x89E4, 0xE040, 0x89E1, 0xE041, 0x89E0, 0xE042, 0x89E2, + 0xE043, 0x89DC, 0xE044, 0x89E6, 0xE045, 0x8A76, 0xE046, 0x8A86, 0xE047, 0x8A7F, 0xE048, 0x8A61, 0xE049, 0x8A3F, 0xE04A, 0x8A77, + 0xE04B, 0x8A82, 0xE04C, 0x8A84, 0xE04D, 0x8A75, 0xE04E, 0x8A83, 0xE04F, 0x8A81, 0xE050, 0x8A74, 0xE051, 0x8A7A, 0xE052, 0x8C3C, + 0xE053, 0x8C4B, 0xE054, 0x8C4A, 0xE055, 0x8C65, 0xE056, 0x8C64, 0xE057, 0x8C66, 0xE058, 0x8C86, 0xE059, 0x8C84, 0xE05A, 0x8C85, + 0xE05B, 0x8CCC, 0xE05C, 0x8D68, 0xE05D, 0x8D69, 0xE05E, 0x8D91, 0xE05F, 0x8D8C, 0xE060, 0x8D8E, 0xE061, 0x8D8F, 0xE062, 0x8D8D, + 0xE063, 0x8D93, 0xE064, 0x8D94, 0xE065, 0x8D90, 0xE066, 0x8D92, 0xE067, 0x8DF0, 0xE068, 0x8DE0, 0xE069, 0x8DEC, 0xE06A, 0x8DF1, + 0xE06B, 0x8DEE, 0xE06C, 0x8DD0, 0xE06D, 0x8DE9, 0xE06E, 0x8DE3, 0xE06F, 0x8DE2, 0xE070, 0x8DE7, 0xE071, 0x8DF2, 0xE072, 0x8DEB, + 0xE073, 0x8DF4, 0xE074, 0x8F06, 0xE075, 0x8EFF, 0xE076, 0x8F01, 0xE077, 0x8F00, 0xE078, 0x8F05, 0xE079, 0x8F07, 0xE07A, 0x8F08, + 0xE07B, 0x8F02, 0xE07C, 0x8F0B, 0xE07D, 0x9052, 0xE07E, 0x903F, 0xE0A1, 0x9044, 0xE0A2, 0x9049, 0xE0A3, 0x903D, 0xE0A4, 0x9110, + 0xE0A5, 0x910D, 0xE0A6, 0x910F, 0xE0A7, 0x9111, 0xE0A8, 0x9116, 0xE0A9, 0x9114, 0xE0AA, 0x910B, 0xE0AB, 0x910E, 0xE0AC, 0x916E, + 0xE0AD, 0x916F, 0xE0AE, 0x9248, 0xE0AF, 0x9252, 0xE0B0, 0x9230, 0xE0B1, 0x923A, 0xE0B2, 0x9266, 0xE0B3, 0x9233, 0xE0B4, 0x9265, + 0xE0B5, 0x925E, 0xE0B6, 0x9283, 0xE0B7, 0x922E, 0xE0B8, 0x924A, 0xE0B9, 0x9246, 0xE0BA, 0x926D, 0xE0BB, 0x926C, 0xE0BC, 0x924F, + 0xE0BD, 0x9260, 0xE0BE, 0x9267, 0xE0BF, 0x926F, 0xE0C0, 0x9236, 0xE0C1, 0x9261, 0xE0C2, 0x9270, 0xE0C3, 0x9231, 0xE0C4, 0x9254, + 0xE0C5, 0x9263, 0xE0C6, 0x9250, 0xE0C7, 0x9272, 0xE0C8, 0x924E, 0xE0C9, 0x9253, 0xE0CA, 0x924C, 0xE0CB, 0x9256, 0xE0CC, 0x9232, + 0xE0CD, 0x959F, 0xE0CE, 0x959C, 0xE0CF, 0x959E, 0xE0D0, 0x959B, 0xE0D1, 0x9692, 0xE0D2, 0x9693, 0xE0D3, 0x9691, 0xE0D4, 0x9697, + 0xE0D5, 0x96CE, 0xE0D6, 0x96FA, 0xE0D7, 0x96FD, 0xE0D8, 0x96F8, 0xE0D9, 0x96F5, 0xE0DA, 0x9773, 0xE0DB, 0x9777, 0xE0DC, 0x9778, + 0xE0DD, 0x9772, 0xE0DE, 0x980F, 0xE0DF, 0x980D, 0xE0E0, 0x980E, 0xE0E1, 0x98AC, 0xE0E2, 0x98F6, 0xE0E3, 0x98F9, 0xE0E4, 0x99AF, + 0xE0E5, 0x99B2, 0xE0E6, 0x99B0, 0xE0E7, 0x99B5, 0xE0E8, 0x9AAD, 0xE0E9, 0x9AAB, 0xE0EA, 0x9B5B, 0xE0EB, 0x9CEA, 0xE0EC, 0x9CED, + 0xE0ED, 0x9CE7, 0xE0EE, 0x9E80, 0xE0EF, 0x9EFD, 0xE0F0, 0x50E6, 0xE0F1, 0x50D4, 0xE0F2, 0x50D7, 0xE0F3, 0x50E8, 0xE0F4, 0x50F3, + 0xE0F5, 0x50DB, 0xE0F6, 0x50EA, 0xE0F7, 0x50DD, 0xE0F8, 0x50E4, 0xE0F9, 0x50D3, 0xE0FA, 0x50EC, 0xE0FB, 0x50F0, 0xE0FC, 0x50EF, + 0xE0FD, 0x50E3, 0xE0FE, 0x50E0, 0xE140, 0x51D8, 0xE141, 0x5280, 0xE142, 0x5281, 0xE143, 0x52E9, 0xE144, 0x52EB, 0xE145, 0x5330, + 0xE146, 0x53AC, 0xE147, 0x5627, 0xE148, 0x5615, 0xE149, 0x560C, 0xE14A, 0x5612, 0xE14B, 0x55FC, 0xE14C, 0x560F, 0xE14D, 0x561C, + 0xE14E, 0x5601, 0xE14F, 0x5613, 0xE150, 0x5602, 0xE151, 0x55FA, 0xE152, 0x561D, 0xE153, 0x5604, 0xE154, 0x55FF, 0xE155, 0x55F9, + 0xE156, 0x5889, 0xE157, 0x587C, 0xE158, 0x5890, 0xE159, 0x5898, 0xE15A, 0x5886, 0xE15B, 0x5881, 0xE15C, 0x587F, 0xE15D, 0x5874, + 0xE15E, 0x588B, 0xE15F, 0x587A, 0xE160, 0x5887, 0xE161, 0x5891, 0xE162, 0x588E, 0xE163, 0x5876, 0xE164, 0x5882, 0xE165, 0x5888, + 0xE166, 0x587B, 0xE167, 0x5894, 0xE168, 0x588F, 0xE169, 0x58FE, 0xE16A, 0x596B, 0xE16B, 0x5ADC, 0xE16C, 0x5AEE, 0xE16D, 0x5AE5, + 0xE16E, 0x5AD5, 0xE16F, 0x5AEA, 0xE170, 0x5ADA, 0xE171, 0x5AED, 0xE172, 0x5AEB, 0xE173, 0x5AF3, 0xE174, 0x5AE2, 0xE175, 0x5AE0, + 0xE176, 0x5ADB, 0xE177, 0x5AEC, 0xE178, 0x5ADE, 0xE179, 0x5ADD, 0xE17A, 0x5AD9, 0xE17B, 0x5AE8, 0xE17C, 0x5ADF, 0xE17D, 0x5B77, + 0xE17E, 0x5BE0, 0xE1A1, 0x5BE3, 0xE1A2, 0x5C63, 0xE1A3, 0x5D82, 0xE1A4, 0x5D80, 0xE1A5, 0x5D7D, 0xE1A6, 0x5D86, 0xE1A7, 0x5D7A, + 0xE1A8, 0x5D81, 0xE1A9, 0x5D77, 0xE1AA, 0x5D8A, 0xE1AB, 0x5D89, 0xE1AC, 0x5D88, 0xE1AD, 0x5D7E, 0xE1AE, 0x5D7C, 0xE1AF, 0x5D8D, + 0xE1B0, 0x5D79, 0xE1B1, 0x5D7F, 0xE1B2, 0x5E58, 0xE1B3, 0x5E59, 0xE1B4, 0x5E53, 0xE1B5, 0x5ED8, 0xE1B6, 0x5ED1, 0xE1B7, 0x5ED7, + 0xE1B8, 0x5ECE, 0xE1B9, 0x5EDC, 0xE1BA, 0x5ED5, 0xE1BB, 0x5ED9, 0xE1BC, 0x5ED2, 0xE1BD, 0x5ED4, 0xE1BE, 0x5F44, 0xE1BF, 0x5F43, + 0xE1C0, 0x5F6F, 0xE1C1, 0x5FB6, 0xE1C2, 0x612C, 0xE1C3, 0x6128, 0xE1C4, 0x6141, 0xE1C5, 0x615E, 0xE1C6, 0x6171, 0xE1C7, 0x6173, + 0xE1C8, 0x6152, 0xE1C9, 0x6153, 0xE1CA, 0x6172, 0xE1CB, 0x616C, 0xE1CC, 0x6180, 0xE1CD, 0x6174, 0xE1CE, 0x6154, 0xE1CF, 0x617A, + 0xE1D0, 0x615B, 0xE1D1, 0x6165, 0xE1D2, 0x613B, 0xE1D3, 0x616A, 0xE1D4, 0x6161, 0xE1D5, 0x6156, 0xE1D6, 0x6229, 0xE1D7, 0x6227, + 0xE1D8, 0x622B, 0xE1D9, 0x642B, 0xE1DA, 0x644D, 0xE1DB, 0x645B, 0xE1DC, 0x645D, 0xE1DD, 0x6474, 0xE1DE, 0x6476, 0xE1DF, 0x6472, + 0xE1E0, 0x6473, 0xE1E1, 0x647D, 0xE1E2, 0x6475, 0xE1E3, 0x6466, 0xE1E4, 0x64A6, 0xE1E5, 0x644E, 0xE1E6, 0x6482, 0xE1E7, 0x645E, + 0xE1E8, 0x645C, 0xE1E9, 0x644B, 0xE1EA, 0x6453, 0xE1EB, 0x6460, 0xE1EC, 0x6450, 0xE1ED, 0x647F, 0xE1EE, 0x643F, 0xE1EF, 0x646C, + 0xE1F0, 0x646B, 0xE1F1, 0x6459, 0xE1F2, 0x6465, 0xE1F3, 0x6477, 0xE1F4, 0x6573, 0xE1F5, 0x65A0, 0xE1F6, 0x66A1, 0xE1F7, 0x66A0, + 0xE1F8, 0x669F, 0xE1F9, 0x6705, 0xE1FA, 0x6704, 0xE1FB, 0x6722, 0xE1FC, 0x69B1, 0xE1FD, 0x69B6, 0xE1FE, 0x69C9, 0xE240, 0x69A0, + 0xE241, 0x69CE, 0xE242, 0x6996, 0xE243, 0x69B0, 0xE244, 0x69AC, 0xE245, 0x69BC, 0xE246, 0x6991, 0xE247, 0x6999, 0xE248, 0x698E, + 0xE249, 0x69A7, 0xE24A, 0x698D, 0xE24B, 0x69A9, 0xE24C, 0x69BE, 0xE24D, 0x69AF, 0xE24E, 0x69BF, 0xE24F, 0x69C4, 0xE250, 0x69BD, + 0xE251, 0x69A4, 0xE252, 0x69D4, 0xE253, 0x69B9, 0xE254, 0x69CA, 0xE255, 0x699A, 0xE256, 0x69CF, 0xE257, 0x69B3, 0xE258, 0x6993, + 0xE259, 0x69AA, 0xE25A, 0x69A1, 0xE25B, 0x699E, 0xE25C, 0x69D9, 0xE25D, 0x6997, 0xE25E, 0x6990, 0xE25F, 0x69C2, 0xE260, 0x69B5, + 0xE261, 0x69A5, 0xE262, 0x69C6, 0xE263, 0x6B4A, 0xE264, 0x6B4D, 0xE265, 0x6B4B, 0xE266, 0x6B9E, 0xE267, 0x6B9F, 0xE268, 0x6BA0, + 0xE269, 0x6BC3, 0xE26A, 0x6BC4, 0xE26B, 0x6BFE, 0xE26C, 0x6ECE, 0xE26D, 0x6EF5, 0xE26E, 0x6EF1, 0xE26F, 0x6F03, 0xE270, 0x6F25, + 0xE271, 0x6EF8, 0xE272, 0x6F37, 0xE273, 0x6EFB, 0xE274, 0x6F2E, 0xE275, 0x6F09, 0xE276, 0x6F4E, 0xE277, 0x6F19, 0xE278, 0x6F1A, + 0xE279, 0x6F27, 0xE27A, 0x6F18, 0xE27B, 0x6F3B, 0xE27C, 0x6F12, 0xE27D, 0x6EED, 0xE27E, 0x6F0A, 0xE2A1, 0x6F36, 0xE2A2, 0x6F73, + 0xE2A3, 0x6EF9, 0xE2A4, 0x6EEE, 0xE2A5, 0x6F2D, 0xE2A6, 0x6F40, 0xE2A7, 0x6F30, 0xE2A8, 0x6F3C, 0xE2A9, 0x6F35, 0xE2AA, 0x6EEB, + 0xE2AB, 0x6F07, 0xE2AC, 0x6F0E, 0xE2AD, 0x6F43, 0xE2AE, 0x6F05, 0xE2AF, 0x6EFD, 0xE2B0, 0x6EF6, 0xE2B1, 0x6F39, 0xE2B2, 0x6F1C, + 0xE2B3, 0x6EFC, 0xE2B4, 0x6F3A, 0xE2B5, 0x6F1F, 0xE2B6, 0x6F0D, 0xE2B7, 0x6F1E, 0xE2B8, 0x6F08, 0xE2B9, 0x6F21, 0xE2BA, 0x7187, + 0xE2BB, 0x7190, 0xE2BC, 0x7189, 0xE2BD, 0x7180, 0xE2BE, 0x7185, 0xE2BF, 0x7182, 0xE2C0, 0x718F, 0xE2C1, 0x717B, 0xE2C2, 0x7186, + 0xE2C3, 0x7181, 0xE2C4, 0x7197, 0xE2C5, 0x7244, 0xE2C6, 0x7253, 0xE2C7, 0x7297, 0xE2C8, 0x7295, 0xE2C9, 0x7293, 0xE2CA, 0x7343, + 0xE2CB, 0x734D, 0xE2CC, 0x7351, 0xE2CD, 0x734C, 0xE2CE, 0x7462, 0xE2CF, 0x7473, 0xE2D0, 0x7471, 0xE2D1, 0x7475, 0xE2D2, 0x7472, + 0xE2D3, 0x7467, 0xE2D4, 0x746E, 0xE2D5, 0x7500, 0xE2D6, 0x7502, 0xE2D7, 0x7503, 0xE2D8, 0x757D, 0xE2D9, 0x7590, 0xE2DA, 0x7616, + 0xE2DB, 0x7608, 0xE2DC, 0x760C, 0xE2DD, 0x7615, 0xE2DE, 0x7611, 0xE2DF, 0x760A, 0xE2E0, 0x7614, 0xE2E1, 0x76B8, 0xE2E2, 0x7781, + 0xE2E3, 0x777C, 0xE2E4, 0x7785, 0xE2E5, 0x7782, 0xE2E6, 0x776E, 0xE2E7, 0x7780, 0xE2E8, 0x776F, 0xE2E9, 0x777E, 0xE2EA, 0x7783, + 0xE2EB, 0x78B2, 0xE2EC, 0x78AA, 0xE2ED, 0x78B4, 0xE2EE, 0x78AD, 0xE2EF, 0x78A8, 0xE2F0, 0x787E, 0xE2F1, 0x78AB, 0xE2F2, 0x789E, + 0xE2F3, 0x78A5, 0xE2F4, 0x78A0, 0xE2F5, 0x78AC, 0xE2F6, 0x78A2, 0xE2F7, 0x78A4, 0xE2F8, 0x7998, 0xE2F9, 0x798A, 0xE2FA, 0x798B, + 0xE2FB, 0x7996, 0xE2FC, 0x7995, 0xE2FD, 0x7994, 0xE2FE, 0x7993, 0xE340, 0x7997, 0xE341, 0x7988, 0xE342, 0x7992, 0xE343, 0x7990, + 0xE344, 0x7A2B, 0xE345, 0x7A4A, 0xE346, 0x7A30, 0xE347, 0x7A2F, 0xE348, 0x7A28, 0xE349, 0x7A26, 0xE34A, 0x7AA8, 0xE34B, 0x7AAB, + 0xE34C, 0x7AAC, 0xE34D, 0x7AEE, 0xE34E, 0x7B88, 0xE34F, 0x7B9C, 0xE350, 0x7B8A, 0xE351, 0x7B91, 0xE352, 0x7B90, 0xE353, 0x7B96, + 0xE354, 0x7B8D, 0xE355, 0x7B8C, 0xE356, 0x7B9B, 0xE357, 0x7B8E, 0xE358, 0x7B85, 0xE359, 0x7B98, 0xE35A, 0x5284, 0xE35B, 0x7B99, + 0xE35C, 0x7BA4, 0xE35D, 0x7B82, 0xE35E, 0x7CBB, 0xE35F, 0x7CBF, 0xE360, 0x7CBC, 0xE361, 0x7CBA, 0xE362, 0x7DA7, 0xE363, 0x7DB7, + 0xE364, 0x7DC2, 0xE365, 0x7DA3, 0xE366, 0x7DAA, 0xE367, 0x7DC1, 0xE368, 0x7DC0, 0xE369, 0x7DC5, 0xE36A, 0x7D9D, 0xE36B, 0x7DCE, + 0xE36C, 0x7DC4, 0xE36D, 0x7DC6, 0xE36E, 0x7DCB, 0xE36F, 0x7DCC, 0xE370, 0x7DAF, 0xE371, 0x7DB9, 0xE372, 0x7D96, 0xE373, 0x7DBC, + 0xE374, 0x7D9F, 0xE375, 0x7DA6, 0xE376, 0x7DAE, 0xE377, 0x7DA9, 0xE378, 0x7DA1, 0xE379, 0x7DC9, 0xE37A, 0x7F73, 0xE37B, 0x7FE2, + 0xE37C, 0x7FE3, 0xE37D, 0x7FE5, 0xE37E, 0x7FDE, 0xE3A1, 0x8024, 0xE3A2, 0x805D, 0xE3A3, 0x805C, 0xE3A4, 0x8189, 0xE3A5, 0x8186, + 0xE3A6, 0x8183, 0xE3A7, 0x8187, 0xE3A8, 0x818D, 0xE3A9, 0x818C, 0xE3AA, 0x818B, 0xE3AB, 0x8215, 0xE3AC, 0x8497, 0xE3AD, 0x84A4, + 0xE3AE, 0x84A1, 0xE3AF, 0x849F, 0xE3B0, 0x84BA, 0xE3B1, 0x84CE, 0xE3B2, 0x84C2, 0xE3B3, 0x84AC, 0xE3B4, 0x84AE, 0xE3B5, 0x84AB, + 0xE3B6, 0x84B9, 0xE3B7, 0x84B4, 0xE3B8, 0x84C1, 0xE3B9, 0x84CD, 0xE3BA, 0x84AA, 0xE3BB, 0x849A, 0xE3BC, 0x84B1, 0xE3BD, 0x84D0, + 0xE3BE, 0x849D, 0xE3BF, 0x84A7, 0xE3C0, 0x84BB, 0xE3C1, 0x84A2, 0xE3C2, 0x8494, 0xE3C3, 0x84C7, 0xE3C4, 0x84CC, 0xE3C5, 0x849B, + 0xE3C6, 0x84A9, 0xE3C7, 0x84AF, 0xE3C8, 0x84A8, 0xE3C9, 0x84D6, 0xE3CA, 0x8498, 0xE3CB, 0x84B6, 0xE3CC, 0x84CF, 0xE3CD, 0x84A0, + 0xE3CE, 0x84D7, 0xE3CF, 0x84D4, 0xE3D0, 0x84D2, 0xE3D1, 0x84DB, 0xE3D2, 0x84B0, 0xE3D3, 0x8491, 0xE3D4, 0x8661, 0xE3D5, 0x8733, + 0xE3D6, 0x8723, 0xE3D7, 0x8728, 0xE3D8, 0x876B, 0xE3D9, 0x8740, 0xE3DA, 0x872E, 0xE3DB, 0x871E, 0xE3DC, 0x8721, 0xE3DD, 0x8719, + 0xE3DE, 0x871B, 0xE3DF, 0x8743, 0xE3E0, 0x872C, 0xE3E1, 0x8741, 0xE3E2, 0x873E, 0xE3E3, 0x8746, 0xE3E4, 0x8720, 0xE3E5, 0x8732, + 0xE3E6, 0x872A, 0xE3E7, 0x872D, 0xE3E8, 0x873C, 0xE3E9, 0x8712, 0xE3EA, 0x873A, 0xE3EB, 0x8731, 0xE3EC, 0x8735, 0xE3ED, 0x8742, + 0xE3EE, 0x8726, 0xE3EF, 0x8727, 0xE3F0, 0x8738, 0xE3F1, 0x8724, 0xE3F2, 0x871A, 0xE3F3, 0x8730, 0xE3F4, 0x8711, 0xE3F5, 0x88F7, + 0xE3F6, 0x88E7, 0xE3F7, 0x88F1, 0xE3F8, 0x88F2, 0xE3F9, 0x88FA, 0xE3FA, 0x88FE, 0xE3FB, 0x88EE, 0xE3FC, 0x88FC, 0xE3FD, 0x88F6, + 0xE3FE, 0x88FB, 0xE440, 0x88F0, 0xE441, 0x88EC, 0xE442, 0x88EB, 0xE443, 0x899D, 0xE444, 0x89A1, 0xE445, 0x899F, 0xE446, 0x899E, + 0xE447, 0x89E9, 0xE448, 0x89EB, 0xE449, 0x89E8, 0xE44A, 0x8AAB, 0xE44B, 0x8A99, 0xE44C, 0x8A8B, 0xE44D, 0x8A92, 0xE44E, 0x8A8F, + 0xE44F, 0x8A96, 0xE450, 0x8C3D, 0xE451, 0x8C68, 0xE452, 0x8C69, 0xE453, 0x8CD5, 0xE454, 0x8CCF, 0xE455, 0x8CD7, 0xE456, 0x8D96, + 0xE457, 0x8E09, 0xE458, 0x8E02, 0xE459, 0x8DFF, 0xE45A, 0x8E0D, 0xE45B, 0x8DFD, 0xE45C, 0x8E0A, 0xE45D, 0x8E03, 0xE45E, 0x8E07, + 0xE45F, 0x8E06, 0xE460, 0x8E05, 0xE461, 0x8DFE, 0xE462, 0x8E00, 0xE463, 0x8E04, 0xE464, 0x8F10, 0xE465, 0x8F11, 0xE466, 0x8F0E, + 0xE467, 0x8F0D, 0xE468, 0x9123, 0xE469, 0x911C, 0xE46A, 0x9120, 0xE46B, 0x9122, 0xE46C, 0x911F, 0xE46D, 0x911D, 0xE46E, 0x911A, + 0xE46F, 0x9124, 0xE470, 0x9121, 0xE471, 0x911B, 0xE472, 0x917A, 0xE473, 0x9172, 0xE474, 0x9179, 0xE475, 0x9173, 0xE476, 0x92A5, + 0xE477, 0x92A4, 0xE478, 0x9276, 0xE479, 0x929B, 0xE47A, 0x927A, 0xE47B, 0x92A0, 0xE47C, 0x9294, 0xE47D, 0x92AA, 0xE47E, 0x928D, + 0xE4A1, 0x92A6, 0xE4A2, 0x929A, 0xE4A3, 0x92AB, 0xE4A4, 0x9279, 0xE4A5, 0x9297, 0xE4A6, 0x927F, 0xE4A7, 0x92A3, 0xE4A8, 0x92EE, + 0xE4A9, 0x928E, 0xE4AA, 0x9282, 0xE4AB, 0x9295, 0xE4AC, 0x92A2, 0xE4AD, 0x927D, 0xE4AE, 0x9288, 0xE4AF, 0x92A1, 0xE4B0, 0x928A, + 0xE4B1, 0x9286, 0xE4B2, 0x928C, 0xE4B3, 0x9299, 0xE4B4, 0x92A7, 0xE4B5, 0x927E, 0xE4B6, 0x9287, 0xE4B7, 0x92A9, 0xE4B8, 0x929D, + 0xE4B9, 0x928B, 0xE4BA, 0x922D, 0xE4BB, 0x969E, 0xE4BC, 0x96A1, 0xE4BD, 0x96FF, 0xE4BE, 0x9758, 0xE4BF, 0x977D, 0xE4C0, 0x977A, + 0xE4C1, 0x977E, 0xE4C2, 0x9783, 0xE4C3, 0x9780, 0xE4C4, 0x9782, 0xE4C5, 0x977B, 0xE4C6, 0x9784, 0xE4C7, 0x9781, 0xE4C8, 0x977F, + 0xE4C9, 0x97CE, 0xE4CA, 0x97CD, 0xE4CB, 0x9816, 0xE4CC, 0x98AD, 0xE4CD, 0x98AE, 0xE4CE, 0x9902, 0xE4CF, 0x9900, 0xE4D0, 0x9907, + 0xE4D1, 0x999D, 0xE4D2, 0x999C, 0xE4D3, 0x99C3, 0xE4D4, 0x99B9, 0xE4D5, 0x99BB, 0xE4D6, 0x99BA, 0xE4D7, 0x99C2, 0xE4D8, 0x99BD, + 0xE4D9, 0x99C7, 0xE4DA, 0x9AB1, 0xE4DB, 0x9AE3, 0xE4DC, 0x9AE7, 0xE4DD, 0x9B3E, 0xE4DE, 0x9B3F, 0xE4DF, 0x9B60, 0xE4E0, 0x9B61, + 0xE4E1, 0x9B5F, 0xE4E2, 0x9CF1, 0xE4E3, 0x9CF2, 0xE4E4, 0x9CF5, 0xE4E5, 0x9EA7, 0xE4E6, 0x50FF, 0xE4E7, 0x5103, 0xE4E8, 0x5130, + 0xE4E9, 0x50F8, 0xE4EA, 0x5106, 0xE4EB, 0x5107, 0xE4EC, 0x50F6, 0xE4ED, 0x50FE, 0xE4EE, 0x510B, 0xE4EF, 0x510C, 0xE4F0, 0x50FD, + 0xE4F1, 0x510A, 0xE4F2, 0x528B, 0xE4F3, 0x528C, 0xE4F4, 0x52F1, 0xE4F5, 0x52EF, 0xE4F6, 0x5648, 0xE4F7, 0x5642, 0xE4F8, 0x564C, + 0xE4F9, 0x5635, 0xE4FA, 0x5641, 0xE4FB, 0x564A, 0xE4FC, 0x5649, 0xE4FD, 0x5646, 0xE4FE, 0x5658, 0xE540, 0x565A, 0xE541, 0x5640, + 0xE542, 0x5633, 0xE543, 0x563D, 0xE544, 0x562C, 0xE545, 0x563E, 0xE546, 0x5638, 0xE547, 0x562A, 0xE548, 0x563A, 0xE549, 0x571A, + 0xE54A, 0x58AB, 0xE54B, 0x589D, 0xE54C, 0x58B1, 0xE54D, 0x58A0, 0xE54E, 0x58A3, 0xE54F, 0x58AF, 0xE550, 0x58AC, 0xE551, 0x58A5, + 0xE552, 0x58A1, 0xE553, 0x58FF, 0xE554, 0x5AFF, 0xE555, 0x5AF4, 0xE556, 0x5AFD, 0xE557, 0x5AF7, 0xE558, 0x5AF6, 0xE559, 0x5B03, + 0xE55A, 0x5AF8, 0xE55B, 0x5B02, 0xE55C, 0x5AF9, 0xE55D, 0x5B01, 0xE55E, 0x5B07, 0xE55F, 0x5B05, 0xE560, 0x5B0F, 0xE561, 0x5C67, + 0xE562, 0x5D99, 0xE563, 0x5D97, 0xE564, 0x5D9F, 0xE565, 0x5D92, 0xE566, 0x5DA2, 0xE567, 0x5D93, 0xE568, 0x5D95, 0xE569, 0x5DA0, + 0xE56A, 0x5D9C, 0xE56B, 0x5DA1, 0xE56C, 0x5D9A, 0xE56D, 0x5D9E, 0xE56E, 0x5E69, 0xE56F, 0x5E5D, 0xE570, 0x5E60, 0xE571, 0x5E5C, + 0xE572, 0x7DF3, 0xE573, 0x5EDB, 0xE574, 0x5EDE, 0xE575, 0x5EE1, 0xE576, 0x5F49, 0xE577, 0x5FB2, 0xE578, 0x618B, 0xE579, 0x6183, + 0xE57A, 0x6179, 0xE57B, 0x61B1, 0xE57C, 0x61B0, 0xE57D, 0x61A2, 0xE57E, 0x6189, 0xE5A1, 0x619B, 0xE5A2, 0x6193, 0xE5A3, 0x61AF, + 0xE5A4, 0x61AD, 0xE5A5, 0x619F, 0xE5A6, 0x6192, 0xE5A7, 0x61AA, 0xE5A8, 0x61A1, 0xE5A9, 0x618D, 0xE5AA, 0x6166, 0xE5AB, 0x61B3, + 0xE5AC, 0x622D, 0xE5AD, 0x646E, 0xE5AE, 0x6470, 0xE5AF, 0x6496, 0xE5B0, 0x64A0, 0xE5B1, 0x6485, 0xE5B2, 0x6497, 0xE5B3, 0x649C, + 0xE5B4, 0x648F, 0xE5B5, 0x648B, 0xE5B6, 0x648A, 0xE5B7, 0x648C, 0xE5B8, 0x64A3, 0xE5B9, 0x649F, 0xE5BA, 0x6468, 0xE5BB, 0x64B1, + 0xE5BC, 0x6498, 0xE5BD, 0x6576, 0xE5BE, 0x657A, 0xE5BF, 0x6579, 0xE5C0, 0x657B, 0xE5C1, 0x65B2, 0xE5C2, 0x65B3, 0xE5C3, 0x66B5, + 0xE5C4, 0x66B0, 0xE5C5, 0x66A9, 0xE5C6, 0x66B2, 0xE5C7, 0x66B7, 0xE5C8, 0x66AA, 0xE5C9, 0x66AF, 0xE5CA, 0x6A00, 0xE5CB, 0x6A06, + 0xE5CC, 0x6A17, 0xE5CD, 0x69E5, 0xE5CE, 0x69F8, 0xE5CF, 0x6A15, 0xE5D0, 0x69F1, 0xE5D1, 0x69E4, 0xE5D2, 0x6A20, 0xE5D3, 0x69FF, + 0xE5D4, 0x69EC, 0xE5D5, 0x69E2, 0xE5D6, 0x6A1B, 0xE5D7, 0x6A1D, 0xE5D8, 0x69FE, 0xE5D9, 0x6A27, 0xE5DA, 0x69F2, 0xE5DB, 0x69EE, + 0xE5DC, 0x6A14, 0xE5DD, 0x69F7, 0xE5DE, 0x69E7, 0xE5DF, 0x6A40, 0xE5E0, 0x6A08, 0xE5E1, 0x69E6, 0xE5E2, 0x69FB, 0xE5E3, 0x6A0D, + 0xE5E4, 0x69FC, 0xE5E5, 0x69EB, 0xE5E6, 0x6A09, 0xE5E7, 0x6A04, 0xE5E8, 0x6A18, 0xE5E9, 0x6A25, 0xE5EA, 0x6A0F, 0xE5EB, 0x69F6, + 0xE5EC, 0x6A26, 0xE5ED, 0x6A07, 0xE5EE, 0x69F4, 0xE5EF, 0x6A16, 0xE5F0, 0x6B51, 0xE5F1, 0x6BA5, 0xE5F2, 0x6BA3, 0xE5F3, 0x6BA2, + 0xE5F4, 0x6BA6, 0xE5F5, 0x6C01, 0xE5F6, 0x6C00, 0xE5F7, 0x6BFF, 0xE5F8, 0x6C02, 0xE5F9, 0x6F41, 0xE5FA, 0x6F26, 0xE5FB, 0x6F7E, + 0xE5FC, 0x6F87, 0xE5FD, 0x6FC6, 0xE5FE, 0x6F92, 0xE640, 0x6F8D, 0xE641, 0x6F89, 0xE642, 0x6F8C, 0xE643, 0x6F62, 0xE644, 0x6F4F, + 0xE645, 0x6F85, 0xE646, 0x6F5A, 0xE647, 0x6F96, 0xE648, 0x6F76, 0xE649, 0x6F6C, 0xE64A, 0x6F82, 0xE64B, 0x6F55, 0xE64C, 0x6F72, + 0xE64D, 0x6F52, 0xE64E, 0x6F50, 0xE64F, 0x6F57, 0xE650, 0x6F94, 0xE651, 0x6F93, 0xE652, 0x6F5D, 0xE653, 0x6F00, 0xE654, 0x6F61, + 0xE655, 0x6F6B, 0xE656, 0x6F7D, 0xE657, 0x6F67, 0xE658, 0x6F90, 0xE659, 0x6F53, 0xE65A, 0x6F8B, 0xE65B, 0x6F69, 0xE65C, 0x6F7F, + 0xE65D, 0x6F95, 0xE65E, 0x6F63, 0xE65F, 0x6F77, 0xE660, 0x6F6A, 0xE661, 0x6F7B, 0xE662, 0x71B2, 0xE663, 0x71AF, 0xE664, 0x719B, + 0xE665, 0x71B0, 0xE666, 0x71A0, 0xE667, 0x719A, 0xE668, 0x71A9, 0xE669, 0x71B5, 0xE66A, 0x719D, 0xE66B, 0x71A5, 0xE66C, 0x719E, + 0xE66D, 0x71A4, 0xE66E, 0x71A1, 0xE66F, 0x71AA, 0xE670, 0x719C, 0xE671, 0x71A7, 0xE672, 0x71B3, 0xE673, 0x7298, 0xE674, 0x729A, + 0xE675, 0x7358, 0xE676, 0x7352, 0xE677, 0x735E, 0xE678, 0x735F, 0xE679, 0x7360, 0xE67A, 0x735D, 0xE67B, 0x735B, 0xE67C, 0x7361, + 0xE67D, 0x735A, 0xE67E, 0x7359, 0xE6A1, 0x7362, 0xE6A2, 0x7487, 0xE6A3, 0x7489, 0xE6A4, 0x748A, 0xE6A5, 0x7486, 0xE6A6, 0x7481, + 0xE6A7, 0x747D, 0xE6A8, 0x7485, 0xE6A9, 0x7488, 0xE6AA, 0x747C, 0xE6AB, 0x7479, 0xE6AC, 0x7508, 0xE6AD, 0x7507, 0xE6AE, 0x757E, + 0xE6AF, 0x7625, 0xE6B0, 0x761E, 0xE6B1, 0x7619, 0xE6B2, 0x761D, 0xE6B3, 0x761C, 0xE6B4, 0x7623, 0xE6B5, 0x761A, 0xE6B6, 0x7628, + 0xE6B7, 0x761B, 0xE6B8, 0x769C, 0xE6B9, 0x769D, 0xE6BA, 0x769E, 0xE6BB, 0x769B, 0xE6BC, 0x778D, 0xE6BD, 0x778F, 0xE6BE, 0x7789, + 0xE6BF, 0x7788, 0xE6C0, 0x78CD, 0xE6C1, 0x78BB, 0xE6C2, 0x78CF, 0xE6C3, 0x78CC, 0xE6C4, 0x78D1, 0xE6C5, 0x78CE, 0xE6C6, 0x78D4, + 0xE6C7, 0x78C8, 0xE6C8, 0x78C3, 0xE6C9, 0x78C4, 0xE6CA, 0x78C9, 0xE6CB, 0x799A, 0xE6CC, 0x79A1, 0xE6CD, 0x79A0, 0xE6CE, 0x799C, + 0xE6CF, 0x79A2, 0xE6D0, 0x799B, 0xE6D1, 0x6B76, 0xE6D2, 0x7A39, 0xE6D3, 0x7AB2, 0xE6D4, 0x7AB4, 0xE6D5, 0x7AB3, 0xE6D6, 0x7BB7, + 0xE6D7, 0x7BCB, 0xE6D8, 0x7BBE, 0xE6D9, 0x7BAC, 0xE6DA, 0x7BCE, 0xE6DB, 0x7BAF, 0xE6DC, 0x7BB9, 0xE6DD, 0x7BCA, 0xE6DE, 0x7BB5, + 0xE6DF, 0x7CC5, 0xE6E0, 0x7CC8, 0xE6E1, 0x7CCC, 0xE6E2, 0x7CCB, 0xE6E3, 0x7DF7, 0xE6E4, 0x7DDB, 0xE6E5, 0x7DEA, 0xE6E6, 0x7DE7, + 0xE6E7, 0x7DD7, 0xE6E8, 0x7DE1, 0xE6E9, 0x7E03, 0xE6EA, 0x7DFA, 0xE6EB, 0x7DE6, 0xE6EC, 0x7DF6, 0xE6ED, 0x7DF1, 0xE6EE, 0x7DF0, + 0xE6EF, 0x7DEE, 0xE6F0, 0x7DDF, 0xE6F1, 0x7F76, 0xE6F2, 0x7FAC, 0xE6F3, 0x7FB0, 0xE6F4, 0x7FAD, 0xE6F5, 0x7FED, 0xE6F6, 0x7FEB, + 0xE6F7, 0x7FEA, 0xE6F8, 0x7FEC, 0xE6F9, 0x7FE6, 0xE6FA, 0x7FE8, 0xE6FB, 0x8064, 0xE6FC, 0x8067, 0xE6FD, 0x81A3, 0xE6FE, 0x819F, + 0xE740, 0x819E, 0xE741, 0x8195, 0xE742, 0x81A2, 0xE743, 0x8199, 0xE744, 0x8197, 0xE745, 0x8216, 0xE746, 0x824F, 0xE747, 0x8253, + 0xE748, 0x8252, 0xE749, 0x8250, 0xE74A, 0x824E, 0xE74B, 0x8251, 0xE74C, 0x8524, 0xE74D, 0x853B, 0xE74E, 0x850F, 0xE74F, 0x8500, + 0xE750, 0x8529, 0xE751, 0x850E, 0xE752, 0x8509, 0xE753, 0x850D, 0xE754, 0x851F, 0xE755, 0x850A, 0xE756, 0x8527, 0xE757, 0x851C, + 0xE758, 0x84FB, 0xE759, 0x852B, 0xE75A, 0x84FA, 0xE75B, 0x8508, 0xE75C, 0x850C, 0xE75D, 0x84F4, 0xE75E, 0x852A, 0xE75F, 0x84F2, + 0xE760, 0x8515, 0xE761, 0x84F7, 0xE762, 0x84EB, 0xE763, 0x84F3, 0xE764, 0x84FC, 0xE765, 0x8512, 0xE766, 0x84EA, 0xE767, 0x84E9, + 0xE768, 0x8516, 0xE769, 0x84FE, 0xE76A, 0x8528, 0xE76B, 0x851D, 0xE76C, 0x852E, 0xE76D, 0x8502, 0xE76E, 0x84FD, 0xE76F, 0x851E, + 0xE770, 0x84F6, 0xE771, 0x8531, 0xE772, 0x8526, 0xE773, 0x84E7, 0xE774, 0x84E8, 0xE775, 0x84F0, 0xE776, 0x84EF, 0xE777, 0x84F9, + 0xE778, 0x8518, 0xE779, 0x8520, 0xE77A, 0x8530, 0xE77B, 0x850B, 0xE77C, 0x8519, 0xE77D, 0x852F, 0xE77E, 0x8662, 0xE7A1, 0x8756, + 0xE7A2, 0x8763, 0xE7A3, 0x8764, 0xE7A4, 0x8777, 0xE7A5, 0x87E1, 0xE7A6, 0x8773, 0xE7A7, 0x8758, 0xE7A8, 0x8754, 0xE7A9, 0x875B, + 0xE7AA, 0x8752, 0xE7AB, 0x8761, 0xE7AC, 0x875A, 0xE7AD, 0x8751, 0xE7AE, 0x875E, 0xE7AF, 0x876D, 0xE7B0, 0x876A, 0xE7B1, 0x8750, + 0xE7B2, 0x874E, 0xE7B3, 0x875F, 0xE7B4, 0x875D, 0xE7B5, 0x876F, 0xE7B6, 0x876C, 0xE7B7, 0x877A, 0xE7B8, 0x876E, 0xE7B9, 0x875C, + 0xE7BA, 0x8765, 0xE7BB, 0x874F, 0xE7BC, 0x877B, 0xE7BD, 0x8775, 0xE7BE, 0x8762, 0xE7BF, 0x8767, 0xE7C0, 0x8769, 0xE7C1, 0x885A, + 0xE7C2, 0x8905, 0xE7C3, 0x890C, 0xE7C4, 0x8914, 0xE7C5, 0x890B, 0xE7C6, 0x8917, 0xE7C7, 0x8918, 0xE7C8, 0x8919, 0xE7C9, 0x8906, + 0xE7CA, 0x8916, 0xE7CB, 0x8911, 0xE7CC, 0x890E, 0xE7CD, 0x8909, 0xE7CE, 0x89A2, 0xE7CF, 0x89A4, 0xE7D0, 0x89A3, 0xE7D1, 0x89ED, + 0xE7D2, 0x89F0, 0xE7D3, 0x89EC, 0xE7D4, 0x8ACF, 0xE7D5, 0x8AC6, 0xE7D6, 0x8AB8, 0xE7D7, 0x8AD3, 0xE7D8, 0x8AD1, 0xE7D9, 0x8AD4, + 0xE7DA, 0x8AD5, 0xE7DB, 0x8ABB, 0xE7DC, 0x8AD7, 0xE7DD, 0x8ABE, 0xE7DE, 0x8AC0, 0xE7DF, 0x8AC5, 0xE7E0, 0x8AD8, 0xE7E1, 0x8AC3, + 0xE7E2, 0x8ABA, 0xE7E3, 0x8ABD, 0xE7E4, 0x8AD9, 0xE7E5, 0x8C3E, 0xE7E6, 0x8C4D, 0xE7E7, 0x8C8F, 0xE7E8, 0x8CE5, 0xE7E9, 0x8CDF, + 0xE7EA, 0x8CD9, 0xE7EB, 0x8CE8, 0xE7EC, 0x8CDA, 0xE7ED, 0x8CDD, 0xE7EE, 0x8CE7, 0xE7EF, 0x8DA0, 0xE7F0, 0x8D9C, 0xE7F1, 0x8DA1, + 0xE7F2, 0x8D9B, 0xE7F3, 0x8E20, 0xE7F4, 0x8E23, 0xE7F5, 0x8E25, 0xE7F6, 0x8E24, 0xE7F7, 0x8E2E, 0xE7F8, 0x8E15, 0xE7F9, 0x8E1B, + 0xE7FA, 0x8E16, 0xE7FB, 0x8E11, 0xE7FC, 0x8E19, 0xE7FD, 0x8E26, 0xE7FE, 0x8E27, 0xE840, 0x8E14, 0xE841, 0x8E12, 0xE842, 0x8E18, + 0xE843, 0x8E13, 0xE844, 0x8E1C, 0xE845, 0x8E17, 0xE846, 0x8E1A, 0xE847, 0x8F2C, 0xE848, 0x8F24, 0xE849, 0x8F18, 0xE84A, 0x8F1A, + 0xE84B, 0x8F20, 0xE84C, 0x8F23, 0xE84D, 0x8F16, 0xE84E, 0x8F17, 0xE84F, 0x9073, 0xE850, 0x9070, 0xE851, 0x906F, 0xE852, 0x9067, + 0xE853, 0x906B, 0xE854, 0x912F, 0xE855, 0x912B, 0xE856, 0x9129, 0xE857, 0x912A, 0xE858, 0x9132, 0xE859, 0x9126, 0xE85A, 0x912E, + 0xE85B, 0x9185, 0xE85C, 0x9186, 0xE85D, 0x918A, 0xE85E, 0x9181, 0xE85F, 0x9182, 0xE860, 0x9184, 0xE861, 0x9180, 0xE862, 0x92D0, + 0xE863, 0x92C3, 0xE864, 0x92C4, 0xE865, 0x92C0, 0xE866, 0x92D9, 0xE867, 0x92B6, 0xE868, 0x92CF, 0xE869, 0x92F1, 0xE86A, 0x92DF, + 0xE86B, 0x92D8, 0xE86C, 0x92E9, 0xE86D, 0x92D7, 0xE86E, 0x92DD, 0xE86F, 0x92CC, 0xE870, 0x92EF, 0xE871, 0x92C2, 0xE872, 0x92E8, + 0xE873, 0x92CA, 0xE874, 0x92C8, 0xE875, 0x92CE, 0xE876, 0x92E6, 0xE877, 0x92CD, 0xE878, 0x92D5, 0xE879, 0x92C9, 0xE87A, 0x92E0, + 0xE87B, 0x92DE, 0xE87C, 0x92E7, 0xE87D, 0x92D1, 0xE87E, 0x92D3, 0xE8A1, 0x92B5, 0xE8A2, 0x92E1, 0xE8A3, 0x92C6, 0xE8A4, 0x92B4, + 0xE8A5, 0x957C, 0xE8A6, 0x95AC, 0xE8A7, 0x95AB, 0xE8A8, 0x95AE, 0xE8A9, 0x95B0, 0xE8AA, 0x96A4, 0xE8AB, 0x96A2, 0xE8AC, 0x96D3, + 0xE8AD, 0x9705, 0xE8AE, 0x9708, 0xE8AF, 0x9702, 0xE8B0, 0x975A, 0xE8B1, 0x978A, 0xE8B2, 0x978E, 0xE8B3, 0x9788, 0xE8B4, 0x97D0, + 0xE8B5, 0x97CF, 0xE8B6, 0x981E, 0xE8B7, 0x981D, 0xE8B8, 0x9826, 0xE8B9, 0x9829, 0xE8BA, 0x9828, 0xE8BB, 0x9820, 0xE8BC, 0x981B, + 0xE8BD, 0x9827, 0xE8BE, 0x98B2, 0xE8BF, 0x9908, 0xE8C0, 0x98FA, 0xE8C1, 0x9911, 0xE8C2, 0x9914, 0xE8C3, 0x9916, 0xE8C4, 0x9917, + 0xE8C5, 0x9915, 0xE8C6, 0x99DC, 0xE8C7, 0x99CD, 0xE8C8, 0x99CF, 0xE8C9, 0x99D3, 0xE8CA, 0x99D4, 0xE8CB, 0x99CE, 0xE8CC, 0x99C9, + 0xE8CD, 0x99D6, 0xE8CE, 0x99D8, 0xE8CF, 0x99CB, 0xE8D0, 0x99D7, 0xE8D1, 0x99CC, 0xE8D2, 0x9AB3, 0xE8D3, 0x9AEC, 0xE8D4, 0x9AEB, + 0xE8D5, 0x9AF3, 0xE8D6, 0x9AF2, 0xE8D7, 0x9AF1, 0xE8D8, 0x9B46, 0xE8D9, 0x9B43, 0xE8DA, 0x9B67, 0xE8DB, 0x9B74, 0xE8DC, 0x9B71, + 0xE8DD, 0x9B66, 0xE8DE, 0x9B76, 0xE8DF, 0x9B75, 0xE8E0, 0x9B70, 0xE8E1, 0x9B68, 0xE8E2, 0x9B64, 0xE8E3, 0x9B6C, 0xE8E4, 0x9CFC, + 0xE8E5, 0x9CFA, 0xE8E6, 0x9CFD, 0xE8E7, 0x9CFF, 0xE8E8, 0x9CF7, 0xE8E9, 0x9D07, 0xE8EA, 0x9D00, 0xE8EB, 0x9CF9, 0xE8EC, 0x9CFB, + 0xE8ED, 0x9D08, 0xE8EE, 0x9D05, 0xE8EF, 0x9D04, 0xE8F0, 0x9E83, 0xE8F1, 0x9ED3, 0xE8F2, 0x9F0F, 0xE8F3, 0x9F10, 0xE8F4, 0x511C, + 0xE8F5, 0x5113, 0xE8F6, 0x5117, 0xE8F7, 0x511A, 0xE8F8, 0x5111, 0xE8F9, 0x51DE, 0xE8FA, 0x5334, 0xE8FB, 0x53E1, 0xE8FC, 0x5670, + 0xE8FD, 0x5660, 0xE8FE, 0x566E, 0xE940, 0x5673, 0xE941, 0x5666, 0xE942, 0x5663, 0xE943, 0x566D, 0xE944, 0x5672, 0xE945, 0x565E, + 0xE946, 0x5677, 0xE947, 0x571C, 0xE948, 0x571B, 0xE949, 0x58C8, 0xE94A, 0x58BD, 0xE94B, 0x58C9, 0xE94C, 0x58BF, 0xE94D, 0x58BA, + 0xE94E, 0x58C2, 0xE94F, 0x58BC, 0xE950, 0x58C6, 0xE951, 0x5B17, 0xE952, 0x5B19, 0xE953, 0x5B1B, 0xE954, 0x5B21, 0xE955, 0x5B14, + 0xE956, 0x5B13, 0xE957, 0x5B10, 0xE958, 0x5B16, 0xE959, 0x5B28, 0xE95A, 0x5B1A, 0xE95B, 0x5B20, 0xE95C, 0x5B1E, 0xE95D, 0x5BEF, + 0xE95E, 0x5DAC, 0xE95F, 0x5DB1, 0xE960, 0x5DA9, 0xE961, 0x5DA7, 0xE962, 0x5DB5, 0xE963, 0x5DB0, 0xE964, 0x5DAE, 0xE965, 0x5DAA, + 0xE966, 0x5DA8, 0xE967, 0x5DB2, 0xE968, 0x5DAD, 0xE969, 0x5DAF, 0xE96A, 0x5DB4, 0xE96B, 0x5E67, 0xE96C, 0x5E68, 0xE96D, 0x5E66, + 0xE96E, 0x5E6F, 0xE96F, 0x5EE9, 0xE970, 0x5EE7, 0xE971, 0x5EE6, 0xE972, 0x5EE8, 0xE973, 0x5EE5, 0xE974, 0x5F4B, 0xE975, 0x5FBC, + 0xE976, 0x619D, 0xE977, 0x61A8, 0xE978, 0x6196, 0xE979, 0x61C5, 0xE97A, 0x61B4, 0xE97B, 0x61C6, 0xE97C, 0x61C1, 0xE97D, 0x61CC, + 0xE97E, 0x61BA, 0xE9A1, 0x61BF, 0xE9A2, 0x61B8, 0xE9A3, 0x618C, 0xE9A4, 0x64D7, 0xE9A5, 0x64D6, 0xE9A6, 0x64D0, 0xE9A7, 0x64CF, + 0xE9A8, 0x64C9, 0xE9A9, 0x64BD, 0xE9AA, 0x6489, 0xE9AB, 0x64C3, 0xE9AC, 0x64DB, 0xE9AD, 0x64F3, 0xE9AE, 0x64D9, 0xE9AF, 0x6533, + 0xE9B0, 0x657F, 0xE9B1, 0x657C, 0xE9B2, 0x65A2, 0xE9B3, 0x66C8, 0xE9B4, 0x66BE, 0xE9B5, 0x66C0, 0xE9B6, 0x66CA, 0xE9B7, 0x66CB, + 0xE9B8, 0x66CF, 0xE9B9, 0x66BD, 0xE9BA, 0x66BB, 0xE9BB, 0x66BA, 0xE9BC, 0x66CC, 0xE9BD, 0x6723, 0xE9BE, 0x6A34, 0xE9BF, 0x6A66, + 0xE9C0, 0x6A49, 0xE9C1, 0x6A67, 0xE9C2, 0x6A32, 0xE9C3, 0x6A68, 0xE9C4, 0x6A3E, 0xE9C5, 0x6A5D, 0xE9C6, 0x6A6D, 0xE9C7, 0x6A76, + 0xE9C8, 0x6A5B, 0xE9C9, 0x6A51, 0xE9CA, 0x6A28, 0xE9CB, 0x6A5A, 0xE9CC, 0x6A3B, 0xE9CD, 0x6A3F, 0xE9CE, 0x6A41, 0xE9CF, 0x6A6A, + 0xE9D0, 0x6A64, 0xE9D1, 0x6A50, 0xE9D2, 0x6A4F, 0xE9D3, 0x6A54, 0xE9D4, 0x6A6F, 0xE9D5, 0x6A69, 0xE9D6, 0x6A60, 0xE9D7, 0x6A3C, + 0xE9D8, 0x6A5E, 0xE9D9, 0x6A56, 0xE9DA, 0x6A55, 0xE9DB, 0x6A4D, 0xE9DC, 0x6A4E, 0xE9DD, 0x6A46, 0xE9DE, 0x6B55, 0xE9DF, 0x6B54, + 0xE9E0, 0x6B56, 0xE9E1, 0x6BA7, 0xE9E2, 0x6BAA, 0xE9E3, 0x6BAB, 0xE9E4, 0x6BC8, 0xE9E5, 0x6BC7, 0xE9E6, 0x6C04, 0xE9E7, 0x6C03, + 0xE9E8, 0x6C06, 0xE9E9, 0x6FAD, 0xE9EA, 0x6FCB, 0xE9EB, 0x6FA3, 0xE9EC, 0x6FC7, 0xE9ED, 0x6FBC, 0xE9EE, 0x6FCE, 0xE9EF, 0x6FC8, + 0xE9F0, 0x6F5E, 0xE9F1, 0x6FC4, 0xE9F2, 0x6FBD, 0xE9F3, 0x6F9E, 0xE9F4, 0x6FCA, 0xE9F5, 0x6FA8, 0xE9F6, 0x7004, 0xE9F7, 0x6FA5, + 0xE9F8, 0x6FAE, 0xE9F9, 0x6FBA, 0xE9FA, 0x6FAC, 0xE9FB, 0x6FAA, 0xE9FC, 0x6FCF, 0xE9FD, 0x6FBF, 0xE9FE, 0x6FB8, 0xEA40, 0x6FA2, + 0xEA41, 0x6FC9, 0xEA42, 0x6FAB, 0xEA43, 0x6FCD, 0xEA44, 0x6FAF, 0xEA45, 0x6FB2, 0xEA46, 0x6FB0, 0xEA47, 0x71C5, 0xEA48, 0x71C2, + 0xEA49, 0x71BF, 0xEA4A, 0x71B8, 0xEA4B, 0x71D6, 0xEA4C, 0x71C0, 0xEA4D, 0x71C1, 0xEA4E, 0x71CB, 0xEA4F, 0x71D4, 0xEA50, 0x71CA, + 0xEA51, 0x71C7, 0xEA52, 0x71CF, 0xEA53, 0x71BD, 0xEA54, 0x71D8, 0xEA55, 0x71BC, 0xEA56, 0x71C6, 0xEA57, 0x71DA, 0xEA58, 0x71DB, + 0xEA59, 0x729D, 0xEA5A, 0x729E, 0xEA5B, 0x7369, 0xEA5C, 0x7366, 0xEA5D, 0x7367, 0xEA5E, 0x736C, 0xEA5F, 0x7365, 0xEA60, 0x736B, + 0xEA61, 0x736A, 0xEA62, 0x747F, 0xEA63, 0x749A, 0xEA64, 0x74A0, 0xEA65, 0x7494, 0xEA66, 0x7492, 0xEA67, 0x7495, 0xEA68, 0x74A1, + 0xEA69, 0x750B, 0xEA6A, 0x7580, 0xEA6B, 0x762F, 0xEA6C, 0x762D, 0xEA6D, 0x7631, 0xEA6E, 0x763D, 0xEA6F, 0x7633, 0xEA70, 0x763C, + 0xEA71, 0x7635, 0xEA72, 0x7632, 0xEA73, 0x7630, 0xEA74, 0x76BB, 0xEA75, 0x76E6, 0xEA76, 0x779A, 0xEA77, 0x779D, 0xEA78, 0x77A1, + 0xEA79, 0x779C, 0xEA7A, 0x779B, 0xEA7B, 0x77A2, 0xEA7C, 0x77A3, 0xEA7D, 0x7795, 0xEA7E, 0x7799, 0xEAA1, 0x7797, 0xEAA2, 0x78DD, + 0xEAA3, 0x78E9, 0xEAA4, 0x78E5, 0xEAA5, 0x78EA, 0xEAA6, 0x78DE, 0xEAA7, 0x78E3, 0xEAA8, 0x78DB, 0xEAA9, 0x78E1, 0xEAAA, 0x78E2, + 0xEAAB, 0x78ED, 0xEAAC, 0x78DF, 0xEAAD, 0x78E0, 0xEAAE, 0x79A4, 0xEAAF, 0x7A44, 0xEAB0, 0x7A48, 0xEAB1, 0x7A47, 0xEAB2, 0x7AB6, + 0xEAB3, 0x7AB8, 0xEAB4, 0x7AB5, 0xEAB5, 0x7AB1, 0xEAB6, 0x7AB7, 0xEAB7, 0x7BDE, 0xEAB8, 0x7BE3, 0xEAB9, 0x7BE7, 0xEABA, 0x7BDD, + 0xEABB, 0x7BD5, 0xEABC, 0x7BE5, 0xEABD, 0x7BDA, 0xEABE, 0x7BE8, 0xEABF, 0x7BF9, 0xEAC0, 0x7BD4, 0xEAC1, 0x7BEA, 0xEAC2, 0x7BE2, + 0xEAC3, 0x7BDC, 0xEAC4, 0x7BEB, 0xEAC5, 0x7BD8, 0xEAC6, 0x7BDF, 0xEAC7, 0x7CD2, 0xEAC8, 0x7CD4, 0xEAC9, 0x7CD7, 0xEACA, 0x7CD0, + 0xEACB, 0x7CD1, 0xEACC, 0x7E12, 0xEACD, 0x7E21, 0xEACE, 0x7E17, 0xEACF, 0x7E0C, 0xEAD0, 0x7E1F, 0xEAD1, 0x7E20, 0xEAD2, 0x7E13, + 0xEAD3, 0x7E0E, 0xEAD4, 0x7E1C, 0xEAD5, 0x7E15, 0xEAD6, 0x7E1A, 0xEAD7, 0x7E22, 0xEAD8, 0x7E0B, 0xEAD9, 0x7E0F, 0xEADA, 0x7E16, + 0xEADB, 0x7E0D, 0xEADC, 0x7E14, 0xEADD, 0x7E25, 0xEADE, 0x7E24, 0xEADF, 0x7F43, 0xEAE0, 0x7F7B, 0xEAE1, 0x7F7C, 0xEAE2, 0x7F7A, + 0xEAE3, 0x7FB1, 0xEAE4, 0x7FEF, 0xEAE5, 0x802A, 0xEAE6, 0x8029, 0xEAE7, 0x806C, 0xEAE8, 0x81B1, 0xEAE9, 0x81A6, 0xEAEA, 0x81AE, + 0xEAEB, 0x81B9, 0xEAEC, 0x81B5, 0xEAED, 0x81AB, 0xEAEE, 0x81B0, 0xEAEF, 0x81AC, 0xEAF0, 0x81B4, 0xEAF1, 0x81B2, 0xEAF2, 0x81B7, + 0xEAF3, 0x81A7, 0xEAF4, 0x81F2, 0xEAF5, 0x8255, 0xEAF6, 0x8256, 0xEAF7, 0x8257, 0xEAF8, 0x8556, 0xEAF9, 0x8545, 0xEAFA, 0x856B, + 0xEAFB, 0x854D, 0xEAFC, 0x8553, 0xEAFD, 0x8561, 0xEAFE, 0x8558, 0xEB40, 0x8540, 0xEB41, 0x8546, 0xEB42, 0x8564, 0xEB43, 0x8541, + 0xEB44, 0x8562, 0xEB45, 0x8544, 0xEB46, 0x8551, 0xEB47, 0x8547, 0xEB48, 0x8563, 0xEB49, 0x853E, 0xEB4A, 0x855B, 0xEB4B, 0x8571, + 0xEB4C, 0x854E, 0xEB4D, 0x856E, 0xEB4E, 0x8575, 0xEB4F, 0x8555, 0xEB50, 0x8567, 0xEB51, 0x8560, 0xEB52, 0x858C, 0xEB53, 0x8566, + 0xEB54, 0x855D, 0xEB55, 0x8554, 0xEB56, 0x8565, 0xEB57, 0x856C, 0xEB58, 0x8663, 0xEB59, 0x8665, 0xEB5A, 0x8664, 0xEB5B, 0x879B, + 0xEB5C, 0x878F, 0xEB5D, 0x8797, 0xEB5E, 0x8793, 0xEB5F, 0x8792, 0xEB60, 0x8788, 0xEB61, 0x8781, 0xEB62, 0x8796, 0xEB63, 0x8798, + 0xEB64, 0x8779, 0xEB65, 0x8787, 0xEB66, 0x87A3, 0xEB67, 0x8785, 0xEB68, 0x8790, 0xEB69, 0x8791, 0xEB6A, 0x879D, 0xEB6B, 0x8784, + 0xEB6C, 0x8794, 0xEB6D, 0x879C, 0xEB6E, 0x879A, 0xEB6F, 0x8789, 0xEB70, 0x891E, 0xEB71, 0x8926, 0xEB72, 0x8930, 0xEB73, 0x892D, + 0xEB74, 0x892E, 0xEB75, 0x8927, 0xEB76, 0x8931, 0xEB77, 0x8922, 0xEB78, 0x8929, 0xEB79, 0x8923, 0xEB7A, 0x892F, 0xEB7B, 0x892C, + 0xEB7C, 0x891F, 0xEB7D, 0x89F1, 0xEB7E, 0x8AE0, 0xEBA1, 0x8AE2, 0xEBA2, 0x8AF2, 0xEBA3, 0x8AF4, 0xEBA4, 0x8AF5, 0xEBA5, 0x8ADD, + 0xEBA6, 0x8B14, 0xEBA7, 0x8AE4, 0xEBA8, 0x8ADF, 0xEBA9, 0x8AF0, 0xEBAA, 0x8AC8, 0xEBAB, 0x8ADE, 0xEBAC, 0x8AE1, 0xEBAD, 0x8AE8, + 0xEBAE, 0x8AFF, 0xEBAF, 0x8AEF, 0xEBB0, 0x8AFB, 0xEBB1, 0x8C91, 0xEBB2, 0x8C92, 0xEBB3, 0x8C90, 0xEBB4, 0x8CF5, 0xEBB5, 0x8CEE, + 0xEBB6, 0x8CF1, 0xEBB7, 0x8CF0, 0xEBB8, 0x8CF3, 0xEBB9, 0x8D6C, 0xEBBA, 0x8D6E, 0xEBBB, 0x8DA5, 0xEBBC, 0x8DA7, 0xEBBD, 0x8E33, + 0xEBBE, 0x8E3E, 0xEBBF, 0x8E38, 0xEBC0, 0x8E40, 0xEBC1, 0x8E45, 0xEBC2, 0x8E36, 0xEBC3, 0x8E3C, 0xEBC4, 0x8E3D, 0xEBC5, 0x8E41, + 0xEBC6, 0x8E30, 0xEBC7, 0x8E3F, 0xEBC8, 0x8EBD, 0xEBC9, 0x8F36, 0xEBCA, 0x8F2E, 0xEBCB, 0x8F35, 0xEBCC, 0x8F32, 0xEBCD, 0x8F39, + 0xEBCE, 0x8F37, 0xEBCF, 0x8F34, 0xEBD0, 0x9076, 0xEBD1, 0x9079, 0xEBD2, 0x907B, 0xEBD3, 0x9086, 0xEBD4, 0x90FA, 0xEBD5, 0x9133, + 0xEBD6, 0x9135, 0xEBD7, 0x9136, 0xEBD8, 0x9193, 0xEBD9, 0x9190, 0xEBDA, 0x9191, 0xEBDB, 0x918D, 0xEBDC, 0x918F, 0xEBDD, 0x9327, + 0xEBDE, 0x931E, 0xEBDF, 0x9308, 0xEBE0, 0x931F, 0xEBE1, 0x9306, 0xEBE2, 0x930F, 0xEBE3, 0x937A, 0xEBE4, 0x9338, 0xEBE5, 0x933C, + 0xEBE6, 0x931B, 0xEBE7, 0x9323, 0xEBE8, 0x9312, 0xEBE9, 0x9301, 0xEBEA, 0x9346, 0xEBEB, 0x932D, 0xEBEC, 0x930E, 0xEBED, 0x930D, + 0xEBEE, 0x92CB, 0xEBEF, 0x931D, 0xEBF0, 0x92FA, 0xEBF1, 0x9325, 0xEBF2, 0x9313, 0xEBF3, 0x92F9, 0xEBF4, 0x92F7, 0xEBF5, 0x9334, + 0xEBF6, 0x9302, 0xEBF7, 0x9324, 0xEBF8, 0x92FF, 0xEBF9, 0x9329, 0xEBFA, 0x9339, 0xEBFB, 0x9335, 0xEBFC, 0x932A, 0xEBFD, 0x9314, + 0xEBFE, 0x930C, 0xEC40, 0x930B, 0xEC41, 0x92FE, 0xEC42, 0x9309, 0xEC43, 0x9300, 0xEC44, 0x92FB, 0xEC45, 0x9316, 0xEC46, 0x95BC, + 0xEC47, 0x95CD, 0xEC48, 0x95BE, 0xEC49, 0x95B9, 0xEC4A, 0x95BA, 0xEC4B, 0x95B6, 0xEC4C, 0x95BF, 0xEC4D, 0x95B5, 0xEC4E, 0x95BD, + 0xEC4F, 0x96A9, 0xEC50, 0x96D4, 0xEC51, 0x970B, 0xEC52, 0x9712, 0xEC53, 0x9710, 0xEC54, 0x9799, 0xEC55, 0x9797, 0xEC56, 0x9794, + 0xEC57, 0x97F0, 0xEC58, 0x97F8, 0xEC59, 0x9835, 0xEC5A, 0x982F, 0xEC5B, 0x9832, 0xEC5C, 0x9924, 0xEC5D, 0x991F, 0xEC5E, 0x9927, + 0xEC5F, 0x9929, 0xEC60, 0x999E, 0xEC61, 0x99EE, 0xEC62, 0x99EC, 0xEC63, 0x99E5, 0xEC64, 0x99E4, 0xEC65, 0x99F0, 0xEC66, 0x99E3, + 0xEC67, 0x99EA, 0xEC68, 0x99E9, 0xEC69, 0x99E7, 0xEC6A, 0x9AB9, 0xEC6B, 0x9ABF, 0xEC6C, 0x9AB4, 0xEC6D, 0x9ABB, 0xEC6E, 0x9AF6, + 0xEC6F, 0x9AFA, 0xEC70, 0x9AF9, 0xEC71, 0x9AF7, 0xEC72, 0x9B33, 0xEC73, 0x9B80, 0xEC74, 0x9B85, 0xEC75, 0x9B87, 0xEC76, 0x9B7C, + 0xEC77, 0x9B7E, 0xEC78, 0x9B7B, 0xEC79, 0x9B82, 0xEC7A, 0x9B93, 0xEC7B, 0x9B92, 0xEC7C, 0x9B90, 0xEC7D, 0x9B7A, 0xEC7E, 0x9B95, + 0xECA1, 0x9B7D, 0xECA2, 0x9B88, 0xECA3, 0x9D25, 0xECA4, 0x9D17, 0xECA5, 0x9D20, 0xECA6, 0x9D1E, 0xECA7, 0x9D14, 0xECA8, 0x9D29, + 0xECA9, 0x9D1D, 0xECAA, 0x9D18, 0xECAB, 0x9D22, 0xECAC, 0x9D10, 0xECAD, 0x9D19, 0xECAE, 0x9D1F, 0xECAF, 0x9E88, 0xECB0, 0x9E86, + 0xECB1, 0x9E87, 0xECB2, 0x9EAE, 0xECB3, 0x9EAD, 0xECB4, 0x9ED5, 0xECB5, 0x9ED6, 0xECB6, 0x9EFA, 0xECB7, 0x9F12, 0xECB8, 0x9F3D, + 0xECB9, 0x5126, 0xECBA, 0x5125, 0xECBB, 0x5122, 0xECBC, 0x5124, 0xECBD, 0x5120, 0xECBE, 0x5129, 0xECBF, 0x52F4, 0xECC0, 0x5693, + 0xECC1, 0x568C, 0xECC2, 0x568D, 0xECC3, 0x5686, 0xECC4, 0x5684, 0xECC5, 0x5683, 0xECC6, 0x567E, 0xECC7, 0x5682, 0xECC8, 0x567F, + 0xECC9, 0x5681, 0xECCA, 0x58D6, 0xECCB, 0x58D4, 0xECCC, 0x58CF, 0xECCD, 0x58D2, 0xECCE, 0x5B2D, 0xECCF, 0x5B25, 0xECD0, 0x5B32, + 0xECD1, 0x5B23, 0xECD2, 0x5B2C, 0xECD3, 0x5B27, 0xECD4, 0x5B26, 0xECD5, 0x5B2F, 0xECD6, 0x5B2E, 0xECD7, 0x5B7B, 0xECD8, 0x5BF1, + 0xECD9, 0x5BF2, 0xECDA, 0x5DB7, 0xECDB, 0x5E6C, 0xECDC, 0x5E6A, 0xECDD, 0x5FBE, 0xECDE, 0x5FBB, 0xECDF, 0x61C3, 0xECE0, 0x61B5, + 0xECE1, 0x61BC, 0xECE2, 0x61E7, 0xECE3, 0x61E0, 0xECE4, 0x61E5, 0xECE5, 0x61E4, 0xECE6, 0x61E8, 0xECE7, 0x61DE, 0xECE8, 0x64EF, + 0xECE9, 0x64E9, 0xECEA, 0x64E3, 0xECEB, 0x64EB, 0xECEC, 0x64E4, 0xECED, 0x64E8, 0xECEE, 0x6581, 0xECEF, 0x6580, 0xECF0, 0x65B6, + 0xECF1, 0x65DA, 0xECF2, 0x66D2, 0xECF3, 0x6A8D, 0xECF4, 0x6A96, 0xECF5, 0x6A81, 0xECF6, 0x6AA5, 0xECF7, 0x6A89, 0xECF8, 0x6A9F, + 0xECF9, 0x6A9B, 0xECFA, 0x6AA1, 0xECFB, 0x6A9E, 0xECFC, 0x6A87, 0xECFD, 0x6A93, 0xECFE, 0x6A8E, 0xED40, 0x6A95, 0xED41, 0x6A83, + 0xED42, 0x6AA8, 0xED43, 0x6AA4, 0xED44, 0x6A91, 0xED45, 0x6A7F, 0xED46, 0x6AA6, 0xED47, 0x6A9A, 0xED48, 0x6A85, 0xED49, 0x6A8C, + 0xED4A, 0x6A92, 0xED4B, 0x6B5B, 0xED4C, 0x6BAD, 0xED4D, 0x6C09, 0xED4E, 0x6FCC, 0xED4F, 0x6FA9, 0xED50, 0x6FF4, 0xED51, 0x6FD4, + 0xED52, 0x6FE3, 0xED53, 0x6FDC, 0xED54, 0x6FED, 0xED55, 0x6FE7, 0xED56, 0x6FE6, 0xED57, 0x6FDE, 0xED58, 0x6FF2, 0xED59, 0x6FDD, + 0xED5A, 0x6FE2, 0xED5B, 0x6FE8, 0xED5C, 0x71E1, 0xED5D, 0x71F1, 0xED5E, 0x71E8, 0xED5F, 0x71F2, 0xED60, 0x71E4, 0xED61, 0x71F0, + 0xED62, 0x71E2, 0xED63, 0x7373, 0xED64, 0x736E, 0xED65, 0x736F, 0xED66, 0x7497, 0xED67, 0x74B2, 0xED68, 0x74AB, 0xED69, 0x7490, + 0xED6A, 0x74AA, 0xED6B, 0x74AD, 0xED6C, 0x74B1, 0xED6D, 0x74A5, 0xED6E, 0x74AF, 0xED6F, 0x7510, 0xED70, 0x7511, 0xED71, 0x7512, + 0xED72, 0x750F, 0xED73, 0x7584, 0xED74, 0x7643, 0xED75, 0x7648, 0xED76, 0x7649, 0xED77, 0x7647, 0xED78, 0x76A4, 0xED79, 0x76E9, + 0xED7A, 0x77B5, 0xED7B, 0x77AB, 0xED7C, 0x77B2, 0xED7D, 0x77B7, 0xED7E, 0x77B6, 0xEDA1, 0x77B4, 0xEDA2, 0x77B1, 0xEDA3, 0x77A8, + 0xEDA4, 0x77F0, 0xEDA5, 0x78F3, 0xEDA6, 0x78FD, 0xEDA7, 0x7902, 0xEDA8, 0x78FB, 0xEDA9, 0x78FC, 0xEDAA, 0x78F2, 0xEDAB, 0x7905, + 0xEDAC, 0x78F9, 0xEDAD, 0x78FE, 0xEDAE, 0x7904, 0xEDAF, 0x79AB, 0xEDB0, 0x79A8, 0xEDB1, 0x7A5C, 0xEDB2, 0x7A5B, 0xEDB3, 0x7A56, + 0xEDB4, 0x7A58, 0xEDB5, 0x7A54, 0xEDB6, 0x7A5A, 0xEDB7, 0x7ABE, 0xEDB8, 0x7AC0, 0xEDB9, 0x7AC1, 0xEDBA, 0x7C05, 0xEDBB, 0x7C0F, + 0xEDBC, 0x7BF2, 0xEDBD, 0x7C00, 0xEDBE, 0x7BFF, 0xEDBF, 0x7BFB, 0xEDC0, 0x7C0E, 0xEDC1, 0x7BF4, 0xEDC2, 0x7C0B, 0xEDC3, 0x7BF3, + 0xEDC4, 0x7C02, 0xEDC5, 0x7C09, 0xEDC6, 0x7C03, 0xEDC7, 0x7C01, 0xEDC8, 0x7BF8, 0xEDC9, 0x7BFD, 0xEDCA, 0x7C06, 0xEDCB, 0x7BF0, + 0xEDCC, 0x7BF1, 0xEDCD, 0x7C10, 0xEDCE, 0x7C0A, 0xEDCF, 0x7CE8, 0xEDD0, 0x7E2D, 0xEDD1, 0x7E3C, 0xEDD2, 0x7E42, 0xEDD3, 0x7E33, + 0xEDD4, 0x9848, 0xEDD5, 0x7E38, 0xEDD6, 0x7E2A, 0xEDD7, 0x7E49, 0xEDD8, 0x7E40, 0xEDD9, 0x7E47, 0xEDDA, 0x7E29, 0xEDDB, 0x7E4C, + 0xEDDC, 0x7E30, 0xEDDD, 0x7E3B, 0xEDDE, 0x7E36, 0xEDDF, 0x7E44, 0xEDE0, 0x7E3A, 0xEDE1, 0x7F45, 0xEDE2, 0x7F7F, 0xEDE3, 0x7F7E, + 0xEDE4, 0x7F7D, 0xEDE5, 0x7FF4, 0xEDE6, 0x7FF2, 0xEDE7, 0x802C, 0xEDE8, 0x81BB, 0xEDE9, 0x81C4, 0xEDEA, 0x81CC, 0xEDEB, 0x81CA, + 0xEDEC, 0x81C5, 0xEDED, 0x81C7, 0xEDEE, 0x81BC, 0xEDEF, 0x81E9, 0xEDF0, 0x825B, 0xEDF1, 0x825A, 0xEDF2, 0x825C, 0xEDF3, 0x8583, + 0xEDF4, 0x8580, 0xEDF5, 0x858F, 0xEDF6, 0x85A7, 0xEDF7, 0x8595, 0xEDF8, 0x85A0, 0xEDF9, 0x858B, 0xEDFA, 0x85A3, 0xEDFB, 0x857B, + 0xEDFC, 0x85A4, 0xEDFD, 0x859A, 0xEDFE, 0x859E, 0xEE40, 0x8577, 0xEE41, 0x857C, 0xEE42, 0x8589, 0xEE43, 0x85A1, 0xEE44, 0x857A, + 0xEE45, 0x8578, 0xEE46, 0x8557, 0xEE47, 0x858E, 0xEE48, 0x8596, 0xEE49, 0x8586, 0xEE4A, 0x858D, 0xEE4B, 0x8599, 0xEE4C, 0x859D, + 0xEE4D, 0x8581, 0xEE4E, 0x85A2, 0xEE4F, 0x8582, 0xEE50, 0x8588, 0xEE51, 0x8585, 0xEE52, 0x8579, 0xEE53, 0x8576, 0xEE54, 0x8598, + 0xEE55, 0x8590, 0xEE56, 0x859F, 0xEE57, 0x8668, 0xEE58, 0x87BE, 0xEE59, 0x87AA, 0xEE5A, 0x87AD, 0xEE5B, 0x87C5, 0xEE5C, 0x87B0, + 0xEE5D, 0x87AC, 0xEE5E, 0x87B9, 0xEE5F, 0x87B5, 0xEE60, 0x87BC, 0xEE61, 0x87AE, 0xEE62, 0x87C9, 0xEE63, 0x87C3, 0xEE64, 0x87C2, + 0xEE65, 0x87CC, 0xEE66, 0x87B7, 0xEE67, 0x87AF, 0xEE68, 0x87C4, 0xEE69, 0x87CA, 0xEE6A, 0x87B4, 0xEE6B, 0x87B6, 0xEE6C, 0x87BF, + 0xEE6D, 0x87B8, 0xEE6E, 0x87BD, 0xEE6F, 0x87DE, 0xEE70, 0x87B2, 0xEE71, 0x8935, 0xEE72, 0x8933, 0xEE73, 0x893C, 0xEE74, 0x893E, + 0xEE75, 0x8941, 0xEE76, 0x8952, 0xEE77, 0x8937, 0xEE78, 0x8942, 0xEE79, 0x89AD, 0xEE7A, 0x89AF, 0xEE7B, 0x89AE, 0xEE7C, 0x89F2, + 0xEE7D, 0x89F3, 0xEE7E, 0x8B1E, 0xEEA1, 0x8B18, 0xEEA2, 0x8B16, 0xEEA3, 0x8B11, 0xEEA4, 0x8B05, 0xEEA5, 0x8B0B, 0xEEA6, 0x8B22, + 0xEEA7, 0x8B0F, 0xEEA8, 0x8B12, 0xEEA9, 0x8B15, 0xEEAA, 0x8B07, 0xEEAB, 0x8B0D, 0xEEAC, 0x8B08, 0xEEAD, 0x8B06, 0xEEAE, 0x8B1C, + 0xEEAF, 0x8B13, 0xEEB0, 0x8B1A, 0xEEB1, 0x8C4F, 0xEEB2, 0x8C70, 0xEEB3, 0x8C72, 0xEEB4, 0x8C71, 0xEEB5, 0x8C6F, 0xEEB6, 0x8C95, + 0xEEB7, 0x8C94, 0xEEB8, 0x8CF9, 0xEEB9, 0x8D6F, 0xEEBA, 0x8E4E, 0xEEBB, 0x8E4D, 0xEEBC, 0x8E53, 0xEEBD, 0x8E50, 0xEEBE, 0x8E4C, + 0xEEBF, 0x8E47, 0xEEC0, 0x8F43, 0xEEC1, 0x8F40, 0xEEC2, 0x9085, 0xEEC3, 0x907E, 0xEEC4, 0x9138, 0xEEC5, 0x919A, 0xEEC6, 0x91A2, + 0xEEC7, 0x919B, 0xEEC8, 0x9199, 0xEEC9, 0x919F, 0xEECA, 0x91A1, 0xEECB, 0x919D, 0xEECC, 0x91A0, 0xEECD, 0x93A1, 0xEECE, 0x9383, + 0xEECF, 0x93AF, 0xEED0, 0x9364, 0xEED1, 0x9356, 0xEED2, 0x9347, 0xEED3, 0x937C, 0xEED4, 0x9358, 0xEED5, 0x935C, 0xEED6, 0x9376, + 0xEED7, 0x9349, 0xEED8, 0x9350, 0xEED9, 0x9351, 0xEEDA, 0x9360, 0xEEDB, 0x936D, 0xEEDC, 0x938F, 0xEEDD, 0x934C, 0xEEDE, 0x936A, + 0xEEDF, 0x9379, 0xEEE0, 0x9357, 0xEEE1, 0x9355, 0xEEE2, 0x9352, 0xEEE3, 0x934F, 0xEEE4, 0x9371, 0xEEE5, 0x9377, 0xEEE6, 0x937B, + 0xEEE7, 0x9361, 0xEEE8, 0x935E, 0xEEE9, 0x9363, 0xEEEA, 0x9367, 0xEEEB, 0x9380, 0xEEEC, 0x934E, 0xEEED, 0x9359, 0xEEEE, 0x95C7, + 0xEEEF, 0x95C0, 0xEEF0, 0x95C9, 0xEEF1, 0x95C3, 0xEEF2, 0x95C5, 0xEEF3, 0x95B7, 0xEEF4, 0x96AE, 0xEEF5, 0x96B0, 0xEEF6, 0x96AC, + 0xEEF7, 0x9720, 0xEEF8, 0x971F, 0xEEF9, 0x9718, 0xEEFA, 0x971D, 0xEEFB, 0x9719, 0xEEFC, 0x979A, 0xEEFD, 0x97A1, 0xEEFE, 0x979C, + 0xEF40, 0x979E, 0xEF41, 0x979D, 0xEF42, 0x97D5, 0xEF43, 0x97D4, 0xEF44, 0x97F1, 0xEF45, 0x9841, 0xEF46, 0x9844, 0xEF47, 0x984A, + 0xEF48, 0x9849, 0xEF49, 0x9845, 0xEF4A, 0x9843, 0xEF4B, 0x9925, 0xEF4C, 0x992B, 0xEF4D, 0x992C, 0xEF4E, 0x992A, 0xEF4F, 0x9933, + 0xEF50, 0x9932, 0xEF51, 0x992F, 0xEF52, 0x992D, 0xEF53, 0x9931, 0xEF54, 0x9930, 0xEF55, 0x9998, 0xEF56, 0x99A3, 0xEF57, 0x99A1, + 0xEF58, 0x9A02, 0xEF59, 0x99FA, 0xEF5A, 0x99F4, 0xEF5B, 0x99F7, 0xEF5C, 0x99F9, 0xEF5D, 0x99F8, 0xEF5E, 0x99F6, 0xEF5F, 0x99FB, + 0xEF60, 0x99FD, 0xEF61, 0x99FE, 0xEF62, 0x99FC, 0xEF63, 0x9A03, 0xEF64, 0x9ABE, 0xEF65, 0x9AFE, 0xEF66, 0x9AFD, 0xEF67, 0x9B01, + 0xEF68, 0x9AFC, 0xEF69, 0x9B48, 0xEF6A, 0x9B9A, 0xEF6B, 0x9BA8, 0xEF6C, 0x9B9E, 0xEF6D, 0x9B9B, 0xEF6E, 0x9BA6, 0xEF6F, 0x9BA1, + 0xEF70, 0x9BA5, 0xEF71, 0x9BA4, 0xEF72, 0x9B86, 0xEF73, 0x9BA2, 0xEF74, 0x9BA0, 0xEF75, 0x9BAF, 0xEF76, 0x9D33, 0xEF77, 0x9D41, + 0xEF78, 0x9D67, 0xEF79, 0x9D36, 0xEF7A, 0x9D2E, 0xEF7B, 0x9D2F, 0xEF7C, 0x9D31, 0xEF7D, 0x9D38, 0xEF7E, 0x9D30, 0xEFA1, 0x9D45, + 0xEFA2, 0x9D42, 0xEFA3, 0x9D43, 0xEFA4, 0x9D3E, 0xEFA5, 0x9D37, 0xEFA6, 0x9D40, 0xEFA7, 0x9D3D, 0xEFA8, 0x7FF5, 0xEFA9, 0x9D2D, + 0xEFAA, 0x9E8A, 0xEFAB, 0x9E89, 0xEFAC, 0x9E8D, 0xEFAD, 0x9EB0, 0xEFAE, 0x9EC8, 0xEFAF, 0x9EDA, 0xEFB0, 0x9EFB, 0xEFB1, 0x9EFF, + 0xEFB2, 0x9F24, 0xEFB3, 0x9F23, 0xEFB4, 0x9F22, 0xEFB5, 0x9F54, 0xEFB6, 0x9FA0, 0xEFB7, 0x5131, 0xEFB8, 0x512D, 0xEFB9, 0x512E, + 0xEFBA, 0x5698, 0xEFBB, 0x569C, 0xEFBC, 0x5697, 0xEFBD, 0x569A, 0xEFBE, 0x569D, 0xEFBF, 0x5699, 0xEFC0, 0x5970, 0xEFC1, 0x5B3C, + 0xEFC2, 0x5C69, 0xEFC3, 0x5C6A, 0xEFC4, 0x5DC0, 0xEFC5, 0x5E6D, 0xEFC6, 0x5E6E, 0xEFC7, 0x61D8, 0xEFC8, 0x61DF, 0xEFC9, 0x61ED, + 0xEFCA, 0x61EE, 0xEFCB, 0x61F1, 0xEFCC, 0x61EA, 0xEFCD, 0x61F0, 0xEFCE, 0x61EB, 0xEFCF, 0x61D6, 0xEFD0, 0x61E9, 0xEFD1, 0x64FF, + 0xEFD2, 0x6504, 0xEFD3, 0x64FD, 0xEFD4, 0x64F8, 0xEFD5, 0x6501, 0xEFD6, 0x6503, 0xEFD7, 0x64FC, 0xEFD8, 0x6594, 0xEFD9, 0x65DB, + 0xEFDA, 0x66DA, 0xEFDB, 0x66DB, 0xEFDC, 0x66D8, 0xEFDD, 0x6AC5, 0xEFDE, 0x6AB9, 0xEFDF, 0x6ABD, 0xEFE0, 0x6AE1, 0xEFE1, 0x6AC6, + 0xEFE2, 0x6ABA, 0xEFE3, 0x6AB6, 0xEFE4, 0x6AB7, 0xEFE5, 0x6AC7, 0xEFE6, 0x6AB4, 0xEFE7, 0x6AAD, 0xEFE8, 0x6B5E, 0xEFE9, 0x6BC9, + 0xEFEA, 0x6C0B, 0xEFEB, 0x7007, 0xEFEC, 0x700C, 0xEFED, 0x700D, 0xEFEE, 0x7001, 0xEFEF, 0x7005, 0xEFF0, 0x7014, 0xEFF1, 0x700E, + 0xEFF2, 0x6FFF, 0xEFF3, 0x7000, 0xEFF4, 0x6FFB, 0xEFF5, 0x7026, 0xEFF6, 0x6FFC, 0xEFF7, 0x6FF7, 0xEFF8, 0x700A, 0xEFF9, 0x7201, + 0xEFFA, 0x71FF, 0xEFFB, 0x71F9, 0xEFFC, 0x7203, 0xEFFD, 0x71FD, 0xEFFE, 0x7376, 0xF040, 0x74B8, 0xF041, 0x74C0, 0xF042, 0x74B5, + 0xF043, 0x74C1, 0xF044, 0x74BE, 0xF045, 0x74B6, 0xF046, 0x74BB, 0xF047, 0x74C2, 0xF048, 0x7514, 0xF049, 0x7513, 0xF04A, 0x765C, + 0xF04B, 0x7664, 0xF04C, 0x7659, 0xF04D, 0x7650, 0xF04E, 0x7653, 0xF04F, 0x7657, 0xF050, 0x765A, 0xF051, 0x76A6, 0xF052, 0x76BD, + 0xF053, 0x76EC, 0xF054, 0x77C2, 0xF055, 0x77BA, 0xF056, 0x78FF, 0xF057, 0x790C, 0xF058, 0x7913, 0xF059, 0x7914, 0xF05A, 0x7909, + 0xF05B, 0x7910, 0xF05C, 0x7912, 0xF05D, 0x7911, 0xF05E, 0x79AD, 0xF05F, 0x79AC, 0xF060, 0x7A5F, 0xF061, 0x7C1C, 0xF062, 0x7C29, + 0xF063, 0x7C19, 0xF064, 0x7C20, 0xF065, 0x7C1F, 0xF066, 0x7C2D, 0xF067, 0x7C1D, 0xF068, 0x7C26, 0xF069, 0x7C28, 0xF06A, 0x7C22, + 0xF06B, 0x7C25, 0xF06C, 0x7C30, 0xF06D, 0x7E5C, 0xF06E, 0x7E50, 0xF06F, 0x7E56, 0xF070, 0x7E63, 0xF071, 0x7E58, 0xF072, 0x7E62, + 0xF073, 0x7E5F, 0xF074, 0x7E51, 0xF075, 0x7E60, 0xF076, 0x7E57, 0xF077, 0x7E53, 0xF078, 0x7FB5, 0xF079, 0x7FB3, 0xF07A, 0x7FF7, + 0xF07B, 0x7FF8, 0xF07C, 0x8075, 0xF07D, 0x81D1, 0xF07E, 0x81D2, 0xF0A1, 0x81D0, 0xF0A2, 0x825F, 0xF0A3, 0x825E, 0xF0A4, 0x85B4, + 0xF0A5, 0x85C6, 0xF0A6, 0x85C0, 0xF0A7, 0x85C3, 0xF0A8, 0x85C2, 0xF0A9, 0x85B3, 0xF0AA, 0x85B5, 0xF0AB, 0x85BD, 0xF0AC, 0x85C7, + 0xF0AD, 0x85C4, 0xF0AE, 0x85BF, 0xF0AF, 0x85CB, 0xF0B0, 0x85CE, 0xF0B1, 0x85C8, 0xF0B2, 0x85C5, 0xF0B3, 0x85B1, 0xF0B4, 0x85B6, + 0xF0B5, 0x85D2, 0xF0B6, 0x8624, 0xF0B7, 0x85B8, 0xF0B8, 0x85B7, 0xF0B9, 0x85BE, 0xF0BA, 0x8669, 0xF0BB, 0x87E7, 0xF0BC, 0x87E6, + 0xF0BD, 0x87E2, 0xF0BE, 0x87DB, 0xF0BF, 0x87EB, 0xF0C0, 0x87EA, 0xF0C1, 0x87E5, 0xF0C2, 0x87DF, 0xF0C3, 0x87F3, 0xF0C4, 0x87E4, + 0xF0C5, 0x87D4, 0xF0C6, 0x87DC, 0xF0C7, 0x87D3, 0xF0C8, 0x87ED, 0xF0C9, 0x87D8, 0xF0CA, 0x87E3, 0xF0CB, 0x87A4, 0xF0CC, 0x87D7, + 0xF0CD, 0x87D9, 0xF0CE, 0x8801, 0xF0CF, 0x87F4, 0xF0D0, 0x87E8, 0xF0D1, 0x87DD, 0xF0D2, 0x8953, 0xF0D3, 0x894B, 0xF0D4, 0x894F, + 0xF0D5, 0x894C, 0xF0D6, 0x8946, 0xF0D7, 0x8950, 0xF0D8, 0x8951, 0xF0D9, 0x8949, 0xF0DA, 0x8B2A, 0xF0DB, 0x8B27, 0xF0DC, 0x8B23, + 0xF0DD, 0x8B33, 0xF0DE, 0x8B30, 0xF0DF, 0x8B35, 0xF0E0, 0x8B47, 0xF0E1, 0x8B2F, 0xF0E2, 0x8B3C, 0xF0E3, 0x8B3E, 0xF0E4, 0x8B31, + 0xF0E5, 0x8B25, 0xF0E6, 0x8B37, 0xF0E7, 0x8B26, 0xF0E8, 0x8B36, 0xF0E9, 0x8B2E, 0xF0EA, 0x8B24, 0xF0EB, 0x8B3B, 0xF0EC, 0x8B3D, + 0xF0ED, 0x8B3A, 0xF0EE, 0x8C42, 0xF0EF, 0x8C75, 0xF0F0, 0x8C99, 0xF0F1, 0x8C98, 0xF0F2, 0x8C97, 0xF0F3, 0x8CFE, 0xF0F4, 0x8D04, + 0xF0F5, 0x8D02, 0xF0F6, 0x8D00, 0xF0F7, 0x8E5C, 0xF0F8, 0x8E62, 0xF0F9, 0x8E60, 0xF0FA, 0x8E57, 0xF0FB, 0x8E56, 0xF0FC, 0x8E5E, + 0xF0FD, 0x8E65, 0xF0FE, 0x8E67, 0xF140, 0x8E5B, 0xF141, 0x8E5A, 0xF142, 0x8E61, 0xF143, 0x8E5D, 0xF144, 0x8E69, 0xF145, 0x8E54, + 0xF146, 0x8F46, 0xF147, 0x8F47, 0xF148, 0x8F48, 0xF149, 0x8F4B, 0xF14A, 0x9128, 0xF14B, 0x913A, 0xF14C, 0x913B, 0xF14D, 0x913E, + 0xF14E, 0x91A8, 0xF14F, 0x91A5, 0xF150, 0x91A7, 0xF151, 0x91AF, 0xF152, 0x91AA, 0xF153, 0x93B5, 0xF154, 0x938C, 0xF155, 0x9392, + 0xF156, 0x93B7, 0xF157, 0x939B, 0xF158, 0x939D, 0xF159, 0x9389, 0xF15A, 0x93A7, 0xF15B, 0x938E, 0xF15C, 0x93AA, 0xF15D, 0x939E, + 0xF15E, 0x93A6, 0xF15F, 0x9395, 0xF160, 0x9388, 0xF161, 0x9399, 0xF162, 0x939F, 0xF163, 0x938D, 0xF164, 0x93B1, 0xF165, 0x9391, + 0xF166, 0x93B2, 0xF167, 0x93A4, 0xF168, 0x93A8, 0xF169, 0x93B4, 0xF16A, 0x93A3, 0xF16B, 0x93A5, 0xF16C, 0x95D2, 0xF16D, 0x95D3, + 0xF16E, 0x95D1, 0xF16F, 0x96B3, 0xF170, 0x96D7, 0xF171, 0x96DA, 0xF172, 0x5DC2, 0xF173, 0x96DF, 0xF174, 0x96D8, 0xF175, 0x96DD, + 0xF176, 0x9723, 0xF177, 0x9722, 0xF178, 0x9725, 0xF179, 0x97AC, 0xF17A, 0x97AE, 0xF17B, 0x97A8, 0xF17C, 0x97AB, 0xF17D, 0x97A4, + 0xF17E, 0x97AA, 0xF1A1, 0x97A2, 0xF1A2, 0x97A5, 0xF1A3, 0x97D7, 0xF1A4, 0x97D9, 0xF1A5, 0x97D6, 0xF1A6, 0x97D8, 0xF1A7, 0x97FA, + 0xF1A8, 0x9850, 0xF1A9, 0x9851, 0xF1AA, 0x9852, 0xF1AB, 0x98B8, 0xF1AC, 0x9941, 0xF1AD, 0x993C, 0xF1AE, 0x993A, 0xF1AF, 0x9A0F, + 0xF1B0, 0x9A0B, 0xF1B1, 0x9A09, 0xF1B2, 0x9A0D, 0xF1B3, 0x9A04, 0xF1B4, 0x9A11, 0xF1B5, 0x9A0A, 0xF1B6, 0x9A05, 0xF1B7, 0x9A07, + 0xF1B8, 0x9A06, 0xF1B9, 0x9AC0, 0xF1BA, 0x9ADC, 0xF1BB, 0x9B08, 0xF1BC, 0x9B04, 0xF1BD, 0x9B05, 0xF1BE, 0x9B29, 0xF1BF, 0x9B35, + 0xF1C0, 0x9B4A, 0xF1C1, 0x9B4C, 0xF1C2, 0x9B4B, 0xF1C3, 0x9BC7, 0xF1C4, 0x9BC6, 0xF1C5, 0x9BC3, 0xF1C6, 0x9BBF, 0xF1C7, 0x9BC1, + 0xF1C8, 0x9BB5, 0xF1C9, 0x9BB8, 0xF1CA, 0x9BD3, 0xF1CB, 0x9BB6, 0xF1CC, 0x9BC4, 0xF1CD, 0x9BB9, 0xF1CE, 0x9BBD, 0xF1CF, 0x9D5C, + 0xF1D0, 0x9D53, 0xF1D1, 0x9D4F, 0xF1D2, 0x9D4A, 0xF1D3, 0x9D5B, 0xF1D4, 0x9D4B, 0xF1D5, 0x9D59, 0xF1D6, 0x9D56, 0xF1D7, 0x9D4C, + 0xF1D8, 0x9D57, 0xF1D9, 0x9D52, 0xF1DA, 0x9D54, 0xF1DB, 0x9D5F, 0xF1DC, 0x9D58, 0xF1DD, 0x9D5A, 0xF1DE, 0x9E8E, 0xF1DF, 0x9E8C, + 0xF1E0, 0x9EDF, 0xF1E1, 0x9F01, 0xF1E2, 0x9F00, 0xF1E3, 0x9F16, 0xF1E4, 0x9F25, 0xF1E5, 0x9F2B, 0xF1E6, 0x9F2A, 0xF1E7, 0x9F29, + 0xF1E8, 0x9F28, 0xF1E9, 0x9F4C, 0xF1EA, 0x9F55, 0xF1EB, 0x5134, 0xF1EC, 0x5135, 0xF1ED, 0x5296, 0xF1EE, 0x52F7, 0xF1EF, 0x53B4, + 0xF1F0, 0x56AB, 0xF1F1, 0x56AD, 0xF1F2, 0x56A6, 0xF1F3, 0x56A7, 0xF1F4, 0x56AA, 0xF1F5, 0x56AC, 0xF1F6, 0x58DA, 0xF1F7, 0x58DD, + 0xF1F8, 0x58DB, 0xF1F9, 0x5912, 0xF1FA, 0x5B3D, 0xF1FB, 0x5B3E, 0xF1FC, 0x5B3F, 0xF1FD, 0x5DC3, 0xF1FE, 0x5E70, 0xF240, 0x5FBF, + 0xF241, 0x61FB, 0xF242, 0x6507, 0xF243, 0x6510, 0xF244, 0x650D, 0xF245, 0x6509, 0xF246, 0x650C, 0xF247, 0x650E, 0xF248, 0x6584, + 0xF249, 0x65DE, 0xF24A, 0x65DD, 0xF24B, 0x66DE, 0xF24C, 0x6AE7, 0xF24D, 0x6AE0, 0xF24E, 0x6ACC, 0xF24F, 0x6AD1, 0xF250, 0x6AD9, + 0xF251, 0x6ACB, 0xF252, 0x6ADF, 0xF253, 0x6ADC, 0xF254, 0x6AD0, 0xF255, 0x6AEB, 0xF256, 0x6ACF, 0xF257, 0x6ACD, 0xF258, 0x6ADE, + 0xF259, 0x6B60, 0xF25A, 0x6BB0, 0xF25B, 0x6C0C, 0xF25C, 0x7019, 0xF25D, 0x7027, 0xF25E, 0x7020, 0xF25F, 0x7016, 0xF260, 0x702B, + 0xF261, 0x7021, 0xF262, 0x7022, 0xF263, 0x7023, 0xF264, 0x7029, 0xF265, 0x7017, 0xF266, 0x7024, 0xF267, 0x701C, 0xF268, 0x702A, + 0xF269, 0x720C, 0xF26A, 0x720A, 0xF26B, 0x7207, 0xF26C, 0x7202, 0xF26D, 0x7205, 0xF26E, 0x72A5, 0xF26F, 0x72A6, 0xF270, 0x72A4, + 0xF271, 0x72A3, 0xF272, 0x72A1, 0xF273, 0x74CB, 0xF274, 0x74C5, 0xF275, 0x74B7, 0xF276, 0x74C3, 0xF277, 0x7516, 0xF278, 0x7660, + 0xF279, 0x77C9, 0xF27A, 0x77CA, 0xF27B, 0x77C4, 0xF27C, 0x77F1, 0xF27D, 0x791D, 0xF27E, 0x791B, 0xF2A1, 0x7921, 0xF2A2, 0x791C, + 0xF2A3, 0x7917, 0xF2A4, 0x791E, 0xF2A5, 0x79B0, 0xF2A6, 0x7A67, 0xF2A7, 0x7A68, 0xF2A8, 0x7C33, 0xF2A9, 0x7C3C, 0xF2AA, 0x7C39, + 0xF2AB, 0x7C2C, 0xF2AC, 0x7C3B, 0xF2AD, 0x7CEC, 0xF2AE, 0x7CEA, 0xF2AF, 0x7E76, 0xF2B0, 0x7E75, 0xF2B1, 0x7E78, 0xF2B2, 0x7E70, + 0xF2B3, 0x7E77, 0xF2B4, 0x7E6F, 0xF2B5, 0x7E7A, 0xF2B6, 0x7E72, 0xF2B7, 0x7E74, 0xF2B8, 0x7E68, 0xF2B9, 0x7F4B, 0xF2BA, 0x7F4A, + 0xF2BB, 0x7F83, 0xF2BC, 0x7F86, 0xF2BD, 0x7FB7, 0xF2BE, 0x7FFD, 0xF2BF, 0x7FFE, 0xF2C0, 0x8078, 0xF2C1, 0x81D7, 0xF2C2, 0x81D5, + 0xF2C3, 0x8264, 0xF2C4, 0x8261, 0xF2C5, 0x8263, 0xF2C6, 0x85EB, 0xF2C7, 0x85F1, 0xF2C8, 0x85ED, 0xF2C9, 0x85D9, 0xF2CA, 0x85E1, + 0xF2CB, 0x85E8, 0xF2CC, 0x85DA, 0xF2CD, 0x85D7, 0xF2CE, 0x85EC, 0xF2CF, 0x85F2, 0xF2D0, 0x85F8, 0xF2D1, 0x85D8, 0xF2D2, 0x85DF, + 0xF2D3, 0x85E3, 0xF2D4, 0x85DC, 0xF2D5, 0x85D1, 0xF2D6, 0x85F0, 0xF2D7, 0x85E6, 0xF2D8, 0x85EF, 0xF2D9, 0x85DE, 0xF2DA, 0x85E2, + 0xF2DB, 0x8800, 0xF2DC, 0x87FA, 0xF2DD, 0x8803, 0xF2DE, 0x87F6, 0xF2DF, 0x87F7, 0xF2E0, 0x8809, 0xF2E1, 0x880C, 0xF2E2, 0x880B, + 0xF2E3, 0x8806, 0xF2E4, 0x87FC, 0xF2E5, 0x8808, 0xF2E6, 0x87FF, 0xF2E7, 0x880A, 0xF2E8, 0x8802, 0xF2E9, 0x8962, 0xF2EA, 0x895A, + 0xF2EB, 0x895B, 0xF2EC, 0x8957, 0xF2ED, 0x8961, 0xF2EE, 0x895C, 0xF2EF, 0x8958, 0xF2F0, 0x895D, 0xF2F1, 0x8959, 0xF2F2, 0x8988, + 0xF2F3, 0x89B7, 0xF2F4, 0x89B6, 0xF2F5, 0x89F6, 0xF2F6, 0x8B50, 0xF2F7, 0x8B48, 0xF2F8, 0x8B4A, 0xF2F9, 0x8B40, 0xF2FA, 0x8B53, + 0xF2FB, 0x8B56, 0xF2FC, 0x8B54, 0xF2FD, 0x8B4B, 0xF2FE, 0x8B55, 0xF340, 0x8B51, 0xF341, 0x8B42, 0xF342, 0x8B52, 0xF343, 0x8B57, + 0xF344, 0x8C43, 0xF345, 0x8C77, 0xF346, 0x8C76, 0xF347, 0x8C9A, 0xF348, 0x8D06, 0xF349, 0x8D07, 0xF34A, 0x8D09, 0xF34B, 0x8DAC, + 0xF34C, 0x8DAA, 0xF34D, 0x8DAD, 0xF34E, 0x8DAB, 0xF34F, 0x8E6D, 0xF350, 0x8E78, 0xF351, 0x8E73, 0xF352, 0x8E6A, 0xF353, 0x8E6F, + 0xF354, 0x8E7B, 0xF355, 0x8EC2, 0xF356, 0x8F52, 0xF357, 0x8F51, 0xF358, 0x8F4F, 0xF359, 0x8F50, 0xF35A, 0x8F53, 0xF35B, 0x8FB4, + 0xF35C, 0x9140, 0xF35D, 0x913F, 0xF35E, 0x91B0, 0xF35F, 0x91AD, 0xF360, 0x93DE, 0xF361, 0x93C7, 0xF362, 0x93CF, 0xF363, 0x93C2, + 0xF364, 0x93DA, 0xF365, 0x93D0, 0xF366, 0x93F9, 0xF367, 0x93EC, 0xF368, 0x93CC, 0xF369, 0x93D9, 0xF36A, 0x93A9, 0xF36B, 0x93E6, + 0xF36C, 0x93CA, 0xF36D, 0x93D4, 0xF36E, 0x93EE, 0xF36F, 0x93E3, 0xF370, 0x93D5, 0xF371, 0x93C4, 0xF372, 0x93CE, 0xF373, 0x93C0, + 0xF374, 0x93D2, 0xF375, 0x93E7, 0xF376, 0x957D, 0xF377, 0x95DA, 0xF378, 0x95DB, 0xF379, 0x96E1, 0xF37A, 0x9729, 0xF37B, 0x972B, + 0xF37C, 0x972C, 0xF37D, 0x9728, 0xF37E, 0x9726, 0xF3A1, 0x97B3, 0xF3A2, 0x97B7, 0xF3A3, 0x97B6, 0xF3A4, 0x97DD, 0xF3A5, 0x97DE, + 0xF3A6, 0x97DF, 0xF3A7, 0x985C, 0xF3A8, 0x9859, 0xF3A9, 0x985D, 0xF3AA, 0x9857, 0xF3AB, 0x98BF, 0xF3AC, 0x98BD, 0xF3AD, 0x98BB, + 0xF3AE, 0x98BE, 0xF3AF, 0x9948, 0xF3B0, 0x9947, 0xF3B1, 0x9943, 0xF3B2, 0x99A6, 0xF3B3, 0x99A7, 0xF3B4, 0x9A1A, 0xF3B5, 0x9A15, + 0xF3B6, 0x9A25, 0xF3B7, 0x9A1D, 0xF3B8, 0x9A24, 0xF3B9, 0x9A1B, 0xF3BA, 0x9A22, 0xF3BB, 0x9A20, 0xF3BC, 0x9A27, 0xF3BD, 0x9A23, + 0xF3BE, 0x9A1E, 0xF3BF, 0x9A1C, 0xF3C0, 0x9A14, 0xF3C1, 0x9AC2, 0xF3C2, 0x9B0B, 0xF3C3, 0x9B0A, 0xF3C4, 0x9B0E, 0xF3C5, 0x9B0C, + 0xF3C6, 0x9B37, 0xF3C7, 0x9BEA, 0xF3C8, 0x9BEB, 0xF3C9, 0x9BE0, 0xF3CA, 0x9BDE, 0xF3CB, 0x9BE4, 0xF3CC, 0x9BE6, 0xF3CD, 0x9BE2, + 0xF3CE, 0x9BF0, 0xF3CF, 0x9BD4, 0xF3D0, 0x9BD7, 0xF3D1, 0x9BEC, 0xF3D2, 0x9BDC, 0xF3D3, 0x9BD9, 0xF3D4, 0x9BE5, 0xF3D5, 0x9BD5, + 0xF3D6, 0x9BE1, 0xF3D7, 0x9BDA, 0xF3D8, 0x9D77, 0xF3D9, 0x9D81, 0xF3DA, 0x9D8A, 0xF3DB, 0x9D84, 0xF3DC, 0x9D88, 0xF3DD, 0x9D71, + 0xF3DE, 0x9D80, 0xF3DF, 0x9D78, 0xF3E0, 0x9D86, 0xF3E1, 0x9D8B, 0xF3E2, 0x9D8C, 0xF3E3, 0x9D7D, 0xF3E4, 0x9D6B, 0xF3E5, 0x9D74, + 0xF3E6, 0x9D75, 0xF3E7, 0x9D70, 0xF3E8, 0x9D69, 0xF3E9, 0x9D85, 0xF3EA, 0x9D73, 0xF3EB, 0x9D7B, 0xF3EC, 0x9D82, 0xF3ED, 0x9D6F, + 0xF3EE, 0x9D79, 0xF3EF, 0x9D7F, 0xF3F0, 0x9D87, 0xF3F1, 0x9D68, 0xF3F2, 0x9E94, 0xF3F3, 0x9E91, 0xF3F4, 0x9EC0, 0xF3F5, 0x9EFC, + 0xF3F6, 0x9F2D, 0xF3F7, 0x9F40, 0xF3F8, 0x9F41, 0xF3F9, 0x9F4D, 0xF3FA, 0x9F56, 0xF3FB, 0x9F57, 0xF3FC, 0x9F58, 0xF3FD, 0x5337, + 0xF3FE, 0x56B2, 0xF440, 0x56B5, 0xF441, 0x56B3, 0xF442, 0x58E3, 0xF443, 0x5B45, 0xF444, 0x5DC6, 0xF445, 0x5DC7, 0xF446, 0x5EEE, + 0xF447, 0x5EEF, 0xF448, 0x5FC0, 0xF449, 0x5FC1, 0xF44A, 0x61F9, 0xF44B, 0x6517, 0xF44C, 0x6516, 0xF44D, 0x6515, 0xF44E, 0x6513, + 0xF44F, 0x65DF, 0xF450, 0x66E8, 0xF451, 0x66E3, 0xF452, 0x66E4, 0xF453, 0x6AF3, 0xF454, 0x6AF0, 0xF455, 0x6AEA, 0xF456, 0x6AE8, + 0xF457, 0x6AF9, 0xF458, 0x6AF1, 0xF459, 0x6AEE, 0xF45A, 0x6AEF, 0xF45B, 0x703C, 0xF45C, 0x7035, 0xF45D, 0x702F, 0xF45E, 0x7037, + 0xF45F, 0x7034, 0xF460, 0x7031, 0xF461, 0x7042, 0xF462, 0x7038, 0xF463, 0x703F, 0xF464, 0x703A, 0xF465, 0x7039, 0xF466, 0x7040, + 0xF467, 0x703B, 0xF468, 0x7033, 0xF469, 0x7041, 0xF46A, 0x7213, 0xF46B, 0x7214, 0xF46C, 0x72A8, 0xF46D, 0x737D, 0xF46E, 0x737C, + 0xF46F, 0x74BA, 0xF470, 0x76AB, 0xF471, 0x76AA, 0xF472, 0x76BE, 0xF473, 0x76ED, 0xF474, 0x77CC, 0xF475, 0x77CE, 0xF476, 0x77CF, + 0xF477, 0x77CD, 0xF478, 0x77F2, 0xF479, 0x7925, 0xF47A, 0x7923, 0xF47B, 0x7927, 0xF47C, 0x7928, 0xF47D, 0x7924, 0xF47E, 0x7929, + 0xF4A1, 0x79B2, 0xF4A2, 0x7A6E, 0xF4A3, 0x7A6C, 0xF4A4, 0x7A6D, 0xF4A5, 0x7AF7, 0xF4A6, 0x7C49, 0xF4A7, 0x7C48, 0xF4A8, 0x7C4A, + 0xF4A9, 0x7C47, 0xF4AA, 0x7C45, 0xF4AB, 0x7CEE, 0xF4AC, 0x7E7B, 0xF4AD, 0x7E7E, 0xF4AE, 0x7E81, 0xF4AF, 0x7E80, 0xF4B0, 0x7FBA, + 0xF4B1, 0x7FFF, 0xF4B2, 0x8079, 0xF4B3, 0x81DB, 0xF4B4, 0x81D9, 0xF4B5, 0x820B, 0xF4B6, 0x8268, 0xF4B7, 0x8269, 0xF4B8, 0x8622, + 0xF4B9, 0x85FF, 0xF4BA, 0x8601, 0xF4BB, 0x85FE, 0xF4BC, 0x861B, 0xF4BD, 0x8600, 0xF4BE, 0x85F6, 0xF4BF, 0x8604, 0xF4C0, 0x8609, + 0xF4C1, 0x8605, 0xF4C2, 0x860C, 0xF4C3, 0x85FD, 0xF4C4, 0x8819, 0xF4C5, 0x8810, 0xF4C6, 0x8811, 0xF4C7, 0x8817, 0xF4C8, 0x8813, + 0xF4C9, 0x8816, 0xF4CA, 0x8963, 0xF4CB, 0x8966, 0xF4CC, 0x89B9, 0xF4CD, 0x89F7, 0xF4CE, 0x8B60, 0xF4CF, 0x8B6A, 0xF4D0, 0x8B5D, + 0xF4D1, 0x8B68, 0xF4D2, 0x8B63, 0xF4D3, 0x8B65, 0xF4D4, 0x8B67, 0xF4D5, 0x8B6D, 0xF4D6, 0x8DAE, 0xF4D7, 0x8E86, 0xF4D8, 0x8E88, + 0xF4D9, 0x8E84, 0xF4DA, 0x8F59, 0xF4DB, 0x8F56, 0xF4DC, 0x8F57, 0xF4DD, 0x8F55, 0xF4DE, 0x8F58, 0xF4DF, 0x8F5A, 0xF4E0, 0x908D, + 0xF4E1, 0x9143, 0xF4E2, 0x9141, 0xF4E3, 0x91B7, 0xF4E4, 0x91B5, 0xF4E5, 0x91B2, 0xF4E6, 0x91B3, 0xF4E7, 0x940B, 0xF4E8, 0x9413, + 0xF4E9, 0x93FB, 0xF4EA, 0x9420, 0xF4EB, 0x940F, 0xF4EC, 0x9414, 0xF4ED, 0x93FE, 0xF4EE, 0x9415, 0xF4EF, 0x9410, 0xF4F0, 0x9428, + 0xF4F1, 0x9419, 0xF4F2, 0x940D, 0xF4F3, 0x93F5, 0xF4F4, 0x9400, 0xF4F5, 0x93F7, 0xF4F6, 0x9407, 0xF4F7, 0x940E, 0xF4F8, 0x9416, + 0xF4F9, 0x9412, 0xF4FA, 0x93FA, 0xF4FB, 0x9409, 0xF4FC, 0x93F8, 0xF4FD, 0x940A, 0xF4FE, 0x93FF, 0xF540, 0x93FC, 0xF541, 0x940C, + 0xF542, 0x93F6, 0xF543, 0x9411, 0xF544, 0x9406, 0xF545, 0x95DE, 0xF546, 0x95E0, 0xF547, 0x95DF, 0xF548, 0x972E, 0xF549, 0x972F, + 0xF54A, 0x97B9, 0xF54B, 0x97BB, 0xF54C, 0x97FD, 0xF54D, 0x97FE, 0xF54E, 0x9860, 0xF54F, 0x9862, 0xF550, 0x9863, 0xF551, 0x985F, + 0xF552, 0x98C1, 0xF553, 0x98C2, 0xF554, 0x9950, 0xF555, 0x994E, 0xF556, 0x9959, 0xF557, 0x994C, 0xF558, 0x994B, 0xF559, 0x9953, + 0xF55A, 0x9A32, 0xF55B, 0x9A34, 0xF55C, 0x9A31, 0xF55D, 0x9A2C, 0xF55E, 0x9A2A, 0xF55F, 0x9A36, 0xF560, 0x9A29, 0xF561, 0x9A2E, + 0xF562, 0x9A38, 0xF563, 0x9A2D, 0xF564, 0x9AC7, 0xF565, 0x9ACA, 0xF566, 0x9AC6, 0xF567, 0x9B10, 0xF568, 0x9B12, 0xF569, 0x9B11, + 0xF56A, 0x9C0B, 0xF56B, 0x9C08, 0xF56C, 0x9BF7, 0xF56D, 0x9C05, 0xF56E, 0x9C12, 0xF56F, 0x9BF8, 0xF570, 0x9C40, 0xF571, 0x9C07, + 0xF572, 0x9C0E, 0xF573, 0x9C06, 0xF574, 0x9C17, 0xF575, 0x9C14, 0xF576, 0x9C09, 0xF577, 0x9D9F, 0xF578, 0x9D99, 0xF579, 0x9DA4, + 0xF57A, 0x9D9D, 0xF57B, 0x9D92, 0xF57C, 0x9D98, 0xF57D, 0x9D90, 0xF57E, 0x9D9B, 0xF5A1, 0x9DA0, 0xF5A2, 0x9D94, 0xF5A3, 0x9D9C, + 0xF5A4, 0x9DAA, 0xF5A5, 0x9D97, 0xF5A6, 0x9DA1, 0xF5A7, 0x9D9A, 0xF5A8, 0x9DA2, 0xF5A9, 0x9DA8, 0xF5AA, 0x9D9E, 0xF5AB, 0x9DA3, + 0xF5AC, 0x9DBF, 0xF5AD, 0x9DA9, 0xF5AE, 0x9D96, 0xF5AF, 0x9DA6, 0xF5B0, 0x9DA7, 0xF5B1, 0x9E99, 0xF5B2, 0x9E9B, 0xF5B3, 0x9E9A, + 0xF5B4, 0x9EE5, 0xF5B5, 0x9EE4, 0xF5B6, 0x9EE7, 0xF5B7, 0x9EE6, 0xF5B8, 0x9F30, 0xF5B9, 0x9F2E, 0xF5BA, 0x9F5B, 0xF5BB, 0x9F60, + 0xF5BC, 0x9F5E, 0xF5BD, 0x9F5D, 0xF5BE, 0x9F59, 0xF5BF, 0x9F91, 0xF5C0, 0x513A, 0xF5C1, 0x5139, 0xF5C2, 0x5298, 0xF5C3, 0x5297, + 0xF5C4, 0x56C3, 0xF5C5, 0x56BD, 0xF5C6, 0x56BE, 0xF5C7, 0x5B48, 0xF5C8, 0x5B47, 0xF5C9, 0x5DCB, 0xF5CA, 0x5DCF, 0xF5CB, 0x5EF1, + 0xF5CC, 0x61FD, 0xF5CD, 0x651B, 0xF5CE, 0x6B02, 0xF5CF, 0x6AFC, 0xF5D0, 0x6B03, 0xF5D1, 0x6AF8, 0xF5D2, 0x6B00, 0xF5D3, 0x7043, + 0xF5D4, 0x7044, 0xF5D5, 0x704A, 0xF5D6, 0x7048, 0xF5D7, 0x7049, 0xF5D8, 0x7045, 0xF5D9, 0x7046, 0xF5DA, 0x721D, 0xF5DB, 0x721A, + 0xF5DC, 0x7219, 0xF5DD, 0x737E, 0xF5DE, 0x7517, 0xF5DF, 0x766A, 0xF5E0, 0x77D0, 0xF5E1, 0x792D, 0xF5E2, 0x7931, 0xF5E3, 0x792F, + 0xF5E4, 0x7C54, 0xF5E5, 0x7C53, 0xF5E6, 0x7CF2, 0xF5E7, 0x7E8A, 0xF5E8, 0x7E87, 0xF5E9, 0x7E88, 0xF5EA, 0x7E8B, 0xF5EB, 0x7E86, + 0xF5EC, 0x7E8D, 0xF5ED, 0x7F4D, 0xF5EE, 0x7FBB, 0xF5EF, 0x8030, 0xF5F0, 0x81DD, 0xF5F1, 0x8618, 0xF5F2, 0x862A, 0xF5F3, 0x8626, + 0xF5F4, 0x861F, 0xF5F5, 0x8623, 0xF5F6, 0x861C, 0xF5F7, 0x8619, 0xF5F8, 0x8627, 0xF5F9, 0x862E, 0xF5FA, 0x8621, 0xF5FB, 0x8620, + 0xF5FC, 0x8629, 0xF5FD, 0x861E, 0xF5FE, 0x8625, 0xF640, 0x8829, 0xF641, 0x881D, 0xF642, 0x881B, 0xF643, 0x8820, 0xF644, 0x8824, + 0xF645, 0x881C, 0xF646, 0x882B, 0xF647, 0x884A, 0xF648, 0x896D, 0xF649, 0x8969, 0xF64A, 0x896E, 0xF64B, 0x896B, 0xF64C, 0x89FA, + 0xF64D, 0x8B79, 0xF64E, 0x8B78, 0xF64F, 0x8B45, 0xF650, 0x8B7A, 0xF651, 0x8B7B, 0xF652, 0x8D10, 0xF653, 0x8D14, 0xF654, 0x8DAF, + 0xF655, 0x8E8E, 0xF656, 0x8E8C, 0xF657, 0x8F5E, 0xF658, 0x8F5B, 0xF659, 0x8F5D, 0xF65A, 0x9146, 0xF65B, 0x9144, 0xF65C, 0x9145, + 0xF65D, 0x91B9, 0xF65E, 0x943F, 0xF65F, 0x943B, 0xF660, 0x9436, 0xF661, 0x9429, 0xF662, 0x943D, 0xF663, 0x943C, 0xF664, 0x9430, + 0xF665, 0x9439, 0xF666, 0x942A, 0xF667, 0x9437, 0xF668, 0x942C, 0xF669, 0x9440, 0xF66A, 0x9431, 0xF66B, 0x95E5, 0xF66C, 0x95E4, + 0xF66D, 0x95E3, 0xF66E, 0x9735, 0xF66F, 0x973A, 0xF670, 0x97BF, 0xF671, 0x97E1, 0xF672, 0x9864, 0xF673, 0x98C9, 0xF674, 0x98C6, + 0xF675, 0x98C0, 0xF676, 0x9958, 0xF677, 0x9956, 0xF678, 0x9A39, 0xF679, 0x9A3D, 0xF67A, 0x9A46, 0xF67B, 0x9A44, 0xF67C, 0x9A42, + 0xF67D, 0x9A41, 0xF67E, 0x9A3A, 0xF6A1, 0x9A3F, 0xF6A2, 0x9ACD, 0xF6A3, 0x9B15, 0xF6A4, 0x9B17, 0xF6A5, 0x9B18, 0xF6A6, 0x9B16, + 0xF6A7, 0x9B3A, 0xF6A8, 0x9B52, 0xF6A9, 0x9C2B, 0xF6AA, 0x9C1D, 0xF6AB, 0x9C1C, 0xF6AC, 0x9C2C, 0xF6AD, 0x9C23, 0xF6AE, 0x9C28, + 0xF6AF, 0x9C29, 0xF6B0, 0x9C24, 0xF6B1, 0x9C21, 0xF6B2, 0x9DB7, 0xF6B3, 0x9DB6, 0xF6B4, 0x9DBC, 0xF6B5, 0x9DC1, 0xF6B6, 0x9DC7, + 0xF6B7, 0x9DCA, 0xF6B8, 0x9DCF, 0xF6B9, 0x9DBE, 0xF6BA, 0x9DC5, 0xF6BB, 0x9DC3, 0xF6BC, 0x9DBB, 0xF6BD, 0x9DB5, 0xF6BE, 0x9DCE, + 0xF6BF, 0x9DB9, 0xF6C0, 0x9DBA, 0xF6C1, 0x9DAC, 0xF6C2, 0x9DC8, 0xF6C3, 0x9DB1, 0xF6C4, 0x9DAD, 0xF6C5, 0x9DCC, 0xF6C6, 0x9DB3, + 0xF6C7, 0x9DCD, 0xF6C8, 0x9DB2, 0xF6C9, 0x9E7A, 0xF6CA, 0x9E9C, 0xF6CB, 0x9EEB, 0xF6CC, 0x9EEE, 0xF6CD, 0x9EED, 0xF6CE, 0x9F1B, + 0xF6CF, 0x9F18, 0xF6D0, 0x9F1A, 0xF6D1, 0x9F31, 0xF6D2, 0x9F4E, 0xF6D3, 0x9F65, 0xF6D4, 0x9F64, 0xF6D5, 0x9F92, 0xF6D6, 0x4EB9, + 0xF6D7, 0x56C6, 0xF6D8, 0x56C5, 0xF6D9, 0x56CB, 0xF6DA, 0x5971, 0xF6DB, 0x5B4B, 0xF6DC, 0x5B4C, 0xF6DD, 0x5DD5, 0xF6DE, 0x5DD1, + 0xF6DF, 0x5EF2, 0xF6E0, 0x6521, 0xF6E1, 0x6520, 0xF6E2, 0x6526, 0xF6E3, 0x6522, 0xF6E4, 0x6B0B, 0xF6E5, 0x6B08, 0xF6E6, 0x6B09, + 0xF6E7, 0x6C0D, 0xF6E8, 0x7055, 0xF6E9, 0x7056, 0xF6EA, 0x7057, 0xF6EB, 0x7052, 0xF6EC, 0x721E, 0xF6ED, 0x721F, 0xF6EE, 0x72A9, + 0xF6EF, 0x737F, 0xF6F0, 0x74D8, 0xF6F1, 0x74D5, 0xF6F2, 0x74D9, 0xF6F3, 0x74D7, 0xF6F4, 0x766D, 0xF6F5, 0x76AD, 0xF6F6, 0x7935, + 0xF6F7, 0x79B4, 0xF6F8, 0x7A70, 0xF6F9, 0x7A71, 0xF6FA, 0x7C57, 0xF6FB, 0x7C5C, 0xF6FC, 0x7C59, 0xF6FD, 0x7C5B, 0xF6FE, 0x7C5A, + 0xF740, 0x7CF4, 0xF741, 0x7CF1, 0xF742, 0x7E91, 0xF743, 0x7F4F, 0xF744, 0x7F87, 0xF745, 0x81DE, 0xF746, 0x826B, 0xF747, 0x8634, + 0xF748, 0x8635, 0xF749, 0x8633, 0xF74A, 0x862C, 0xF74B, 0x8632, 0xF74C, 0x8636, 0xF74D, 0x882C, 0xF74E, 0x8828, 0xF74F, 0x8826, + 0xF750, 0x882A, 0xF751, 0x8825, 0xF752, 0x8971, 0xF753, 0x89BF, 0xF754, 0x89BE, 0xF755, 0x89FB, 0xF756, 0x8B7E, 0xF757, 0x8B84, + 0xF758, 0x8B82, 0xF759, 0x8B86, 0xF75A, 0x8B85, 0xF75B, 0x8B7F, 0xF75C, 0x8D15, 0xF75D, 0x8E95, 0xF75E, 0x8E94, 0xF75F, 0x8E9A, + 0xF760, 0x8E92, 0xF761, 0x8E90, 0xF762, 0x8E96, 0xF763, 0x8E97, 0xF764, 0x8F60, 0xF765, 0x8F62, 0xF766, 0x9147, 0xF767, 0x944C, + 0xF768, 0x9450, 0xF769, 0x944A, 0xF76A, 0x944B, 0xF76B, 0x944F, 0xF76C, 0x9447, 0xF76D, 0x9445, 0xF76E, 0x9448, 0xF76F, 0x9449, + 0xF770, 0x9446, 0xF771, 0x973F, 0xF772, 0x97E3, 0xF773, 0x986A, 0xF774, 0x9869, 0xF775, 0x98CB, 0xF776, 0x9954, 0xF777, 0x995B, + 0xF778, 0x9A4E, 0xF779, 0x9A53, 0xF77A, 0x9A54, 0xF77B, 0x9A4C, 0xF77C, 0x9A4F, 0xF77D, 0x9A48, 0xF77E, 0x9A4A, 0xF7A1, 0x9A49, + 0xF7A2, 0x9A52, 0xF7A3, 0x9A50, 0xF7A4, 0x9AD0, 0xF7A5, 0x9B19, 0xF7A6, 0x9B2B, 0xF7A7, 0x9B3B, 0xF7A8, 0x9B56, 0xF7A9, 0x9B55, + 0xF7AA, 0x9C46, 0xF7AB, 0x9C48, 0xF7AC, 0x9C3F, 0xF7AD, 0x9C44, 0xF7AE, 0x9C39, 0xF7AF, 0x9C33, 0xF7B0, 0x9C41, 0xF7B1, 0x9C3C, + 0xF7B2, 0x9C37, 0xF7B3, 0x9C34, 0xF7B4, 0x9C32, 0xF7B5, 0x9C3D, 0xF7B6, 0x9C36, 0xF7B7, 0x9DDB, 0xF7B8, 0x9DD2, 0xF7B9, 0x9DDE, + 0xF7BA, 0x9DDA, 0xF7BB, 0x9DCB, 0xF7BC, 0x9DD0, 0xF7BD, 0x9DDC, 0xF7BE, 0x9DD1, 0xF7BF, 0x9DDF, 0xF7C0, 0x9DE9, 0xF7C1, 0x9DD9, + 0xF7C2, 0x9DD8, 0xF7C3, 0x9DD6, 0xF7C4, 0x9DF5, 0xF7C5, 0x9DD5, 0xF7C6, 0x9DDD, 0xF7C7, 0x9EB6, 0xF7C8, 0x9EF0, 0xF7C9, 0x9F35, + 0xF7CA, 0x9F33, 0xF7CB, 0x9F32, 0xF7CC, 0x9F42, 0xF7CD, 0x9F6B, 0xF7CE, 0x9F95, 0xF7CF, 0x9FA2, 0xF7D0, 0x513D, 0xF7D1, 0x5299, + 0xF7D2, 0x58E8, 0xF7D3, 0x58E7, 0xF7D4, 0x5972, 0xF7D5, 0x5B4D, 0xF7D6, 0x5DD8, 0xF7D7, 0x882F, 0xF7D8, 0x5F4F, 0xF7D9, 0x6201, + 0xF7DA, 0x6203, 0xF7DB, 0x6204, 0xF7DC, 0x6529, 0xF7DD, 0x6525, 0xF7DE, 0x6596, 0xF7DF, 0x66EB, 0xF7E0, 0x6B11, 0xF7E1, 0x6B12, + 0xF7E2, 0x6B0F, 0xF7E3, 0x6BCA, 0xF7E4, 0x705B, 0xF7E5, 0x705A, 0xF7E6, 0x7222, 0xF7E7, 0x7382, 0xF7E8, 0x7381, 0xF7E9, 0x7383, + 0xF7EA, 0x7670, 0xF7EB, 0x77D4, 0xF7EC, 0x7C67, 0xF7ED, 0x7C66, 0xF7EE, 0x7E95, 0xF7EF, 0x826C, 0xF7F0, 0x863A, 0xF7F1, 0x8640, + 0xF7F2, 0x8639, 0xF7F3, 0x863C, 0xF7F4, 0x8631, 0xF7F5, 0x863B, 0xF7F6, 0x863E, 0xF7F7, 0x8830, 0xF7F8, 0x8832, 0xF7F9, 0x882E, + 0xF7FA, 0x8833, 0xF7FB, 0x8976, 0xF7FC, 0x8974, 0xF7FD, 0x8973, 0xF7FE, 0x89FE, 0xF840, 0x8B8C, 0xF841, 0x8B8E, 0xF842, 0x8B8B, + 0xF843, 0x8B88, 0xF844, 0x8C45, 0xF845, 0x8D19, 0xF846, 0x8E98, 0xF847, 0x8F64, 0xF848, 0x8F63, 0xF849, 0x91BC, 0xF84A, 0x9462, + 0xF84B, 0x9455, 0xF84C, 0x945D, 0xF84D, 0x9457, 0xF84E, 0x945E, 0xF84F, 0x97C4, 0xF850, 0x97C5, 0xF851, 0x9800, 0xF852, 0x9A56, + 0xF853, 0x9A59, 0xF854, 0x9B1E, 0xF855, 0x9B1F, 0xF856, 0x9B20, 0xF857, 0x9C52, 0xF858, 0x9C58, 0xF859, 0x9C50, 0xF85A, 0x9C4A, + 0xF85B, 0x9C4D, 0xF85C, 0x9C4B, 0xF85D, 0x9C55, 0xF85E, 0x9C59, 0xF85F, 0x9C4C, 0xF860, 0x9C4E, 0xF861, 0x9DFB, 0xF862, 0x9DF7, + 0xF863, 0x9DEF, 0xF864, 0x9DE3, 0xF865, 0x9DEB, 0xF866, 0x9DF8, 0xF867, 0x9DE4, 0xF868, 0x9DF6, 0xF869, 0x9DE1, 0xF86A, 0x9DEE, + 0xF86B, 0x9DE6, 0xF86C, 0x9DF2, 0xF86D, 0x9DF0, 0xF86E, 0x9DE2, 0xF86F, 0x9DEC, 0xF870, 0x9DF4, 0xF871, 0x9DF3, 0xF872, 0x9DE8, + 0xF873, 0x9DED, 0xF874, 0x9EC2, 0xF875, 0x9ED0, 0xF876, 0x9EF2, 0xF877, 0x9EF3, 0xF878, 0x9F06, 0xF879, 0x9F1C, 0xF87A, 0x9F38, + 0xF87B, 0x9F37, 0xF87C, 0x9F36, 0xF87D, 0x9F43, 0xF87E, 0x9F4F, 0xF8A1, 0x9F71, 0xF8A2, 0x9F70, 0xF8A3, 0x9F6E, 0xF8A4, 0x9F6F, + 0xF8A5, 0x56D3, 0xF8A6, 0x56CD, 0xF8A7, 0x5B4E, 0xF8A8, 0x5C6D, 0xF8A9, 0x652D, 0xF8AA, 0x66ED, 0xF8AB, 0x66EE, 0xF8AC, 0x6B13, + 0xF8AD, 0x705F, 0xF8AE, 0x7061, 0xF8AF, 0x705D, 0xF8B0, 0x7060, 0xF8B1, 0x7223, 0xF8B2, 0x74DB, 0xF8B3, 0x74E5, 0xF8B4, 0x77D5, + 0xF8B5, 0x7938, 0xF8B6, 0x79B7, 0xF8B7, 0x79B6, 0xF8B8, 0x7C6A, 0xF8B9, 0x7E97, 0xF8BA, 0x7F89, 0xF8BB, 0x826D, 0xF8BC, 0x8643, + 0xF8BD, 0x8838, 0xF8BE, 0x8837, 0xF8BF, 0x8835, 0xF8C0, 0x884B, 0xF8C1, 0x8B94, 0xF8C2, 0x8B95, 0xF8C3, 0x8E9E, 0xF8C4, 0x8E9F, + 0xF8C5, 0x8EA0, 0xF8C6, 0x8E9D, 0xF8C7, 0x91BE, 0xF8C8, 0x91BD, 0xF8C9, 0x91C2, 0xF8CA, 0x946B, 0xF8CB, 0x9468, 0xF8CC, 0x9469, + 0xF8CD, 0x96E5, 0xF8CE, 0x9746, 0xF8CF, 0x9743, 0xF8D0, 0x9747, 0xF8D1, 0x97C7, 0xF8D2, 0x97E5, 0xF8D3, 0x9A5E, 0xF8D4, 0x9AD5, + 0xF8D5, 0x9B59, 0xF8D6, 0x9C63, 0xF8D7, 0x9C67, 0xF8D8, 0x9C66, 0xF8D9, 0x9C62, 0xF8DA, 0x9C5E, 0xF8DB, 0x9C60, 0xF8DC, 0x9E02, + 0xF8DD, 0x9DFE, 0xF8DE, 0x9E07, 0xF8DF, 0x9E03, 0xF8E0, 0x9E06, 0xF8E1, 0x9E05, 0xF8E2, 0x9E00, 0xF8E3, 0x9E01, 0xF8E4, 0x9E09, + 0xF8E5, 0x9DFF, 0xF8E6, 0x9DFD, 0xF8E7, 0x9E04, 0xF8E8, 0x9EA0, 0xF8E9, 0x9F1E, 0xF8EA, 0x9F46, 0xF8EB, 0x9F74, 0xF8EC, 0x9F75, + 0xF8ED, 0x9F76, 0xF8EE, 0x56D4, 0xF8EF, 0x652E, 0xF8F0, 0x65B8, 0xF8F1, 0x6B18, 0xF8F2, 0x6B19, 0xF8F3, 0x6B17, 0xF8F4, 0x6B1A, + 0xF8F5, 0x7062, 0xF8F6, 0x7226, 0xF8F7, 0x72AA, 0xF8F8, 0x77D8, 0xF8F9, 0x77D9, 0xF8FA, 0x7939, 0xF8FB, 0x7C69, 0xF8FC, 0x7C6B, + 0xF8FD, 0x7CF6, 0xF8FE, 0x7E9A, 0xF940, 0x7E98, 0xF941, 0x7E9B, 0xF942, 0x7E99, 0xF943, 0x81E0, 0xF944, 0x81E1, 0xF945, 0x8646, + 0xF946, 0x8647, 0xF947, 0x8648, 0xF948, 0x8979, 0xF949, 0x897A, 0xF94A, 0x897C, 0xF94B, 0x897B, 0xF94C, 0x89FF, 0xF94D, 0x8B98, + 0xF94E, 0x8B99, 0xF94F, 0x8EA5, 0xF950, 0x8EA4, 0xF951, 0x8EA3, 0xF952, 0x946E, 0xF953, 0x946D, 0xF954, 0x946F, 0xF955, 0x9471, + 0xF956, 0x9473, 0xF957, 0x9749, 0xF958, 0x9872, 0xF959, 0x995F, 0xF95A, 0x9C68, 0xF95B, 0x9C6E, 0xF95C, 0x9C6D, 0xF95D, 0x9E0B, + 0xF95E, 0x9E0D, 0xF95F, 0x9E10, 0xF960, 0x9E0F, 0xF961, 0x9E12, 0xF962, 0x9E11, 0xF963, 0x9EA1, 0xF964, 0x9EF5, 0xF965, 0x9F09, + 0xF966, 0x9F47, 0xF967, 0x9F78, 0xF968, 0x9F7B, 0xF969, 0x9F7A, 0xF96A, 0x9F79, 0xF96B, 0x571E, 0xF96C, 0x7066, 0xF96D, 0x7C6F, + 0xF96E, 0x883C, 0xF96F, 0x8DB2, 0xF970, 0x8EA6, 0xF971, 0x91C3, 0xF972, 0x9474, 0xF973, 0x9478, 0xF974, 0x9476, 0xF975, 0x9475, + 0xF976, 0x9A60, 0xF977, 0x9C74, 0xF978, 0x9C73, 0xF979, 0x9C71, 0xF97A, 0x9C75, 0xF97B, 0x9E14, 0xF97C, 0x9E13, 0xF97D, 0x9EF6, + 0xF97E, 0x9F0A, 0xF9A1, 0x9FA4, 0xF9A2, 0x7068, 0xF9A3, 0x7065, 0xF9A4, 0x7CF7, 0xF9A5, 0x866A, 0xF9A6, 0x883E, 0xF9A7, 0x883D, + 0xF9A8, 0x883F, 0xF9A9, 0x8B9E, 0xF9AA, 0x8C9C, 0xF9AB, 0x8EA9, 0xF9AC, 0x8EC9, 0xF9AD, 0x974B, 0xF9AE, 0x9873, 0xF9AF, 0x9874, + 0xF9B0, 0x98CC, 0xF9B1, 0x9961, 0xF9B2, 0x99AB, 0xF9B3, 0x9A64, 0xF9B4, 0x9A66, 0xF9B5, 0x9A67, 0xF9B6, 0x9B24, 0xF9B7, 0x9E15, + 0xF9B8, 0x9E17, 0xF9B9, 0x9F48, 0xF9BA, 0x6207, 0xF9BB, 0x6B1E, 0xF9BC, 0x7227, 0xF9BD, 0x864C, 0xF9BE, 0x8EA8, 0xF9BF, 0x9482, + 0xF9C0, 0x9480, 0xF9C1, 0x9481, 0xF9C2, 0x9A69, 0xF9C3, 0x9A68, 0xF9C4, 0x9B2E, 0xF9C5, 0x9E19, 0xF9C6, 0x7229, 0xF9C7, 0x864B, + 0xF9C8, 0x8B9F, 0xF9C9, 0x9483, 0xF9CA, 0x9C79, 0xF9CB, 0x9EB7, 0xF9CC, 0x7675, 0xF9CD, 0x9A6B, 0xF9CE, 0x9C7A, 0xF9CF, 0x9E1D, + 0xF9D0, 0x7069, 0xF9D1, 0x706A, 0xF9D2, 0x9EA4, 0xF9D3, 0x9F7E, 0xF9D4, 0x9F49, 0xF9D5, 0x9F98, 0xF9D6, 0x7881, 0xF9D7, 0x92B9, + 0xF9D8, 0x88CF, 0xF9D9, 0x58BB, 0xF9DA, 0x6052, 0xF9DB, 0x7CA7, 0xF9DC, 0x5AFA, 0xF9DD, 0x2554, 0xF9DE, 0x2566, 0xF9DF, 0x2557, + 0xF9E0, 0x2560, 0xF9E1, 0x256C, 0xF9E2, 0x2563, 0xF9E3, 0x255A, 0xF9E4, 0x2569, 0xF9E5, 0x255D, 0xF9E6, 0x2552, 0xF9E7, 0x2564, + 0xF9E8, 0x2555, 0xF9E9, 0x255E, 0xF9EA, 0x256A, 0xF9EB, 0x2561, 0xF9EC, 0x2558, 0xF9ED, 0x2567, 0xF9EE, 0x255B, 0xF9EF, 0x2553, + 0xF9F0, 0x2565, 0xF9F1, 0x2556, 0xF9F2, 0x255F, 0xF9F3, 0x256B, 0xF9F4, 0x2562, 0xF9F5, 0x2559, 0xF9F6, 0x2568, 0xF9F7, 0x255C, + 0xF9F8, 0x2551, 0xF9F9, 0x2550, 0xF9FA, 0x256D, 0xF9FB, 0x256E, 0xF9FC, 0x2570, 0xF9FD, 0x256F, 0xF9FE, 0x2593, 0, 0 +}; +#endif + +#if FF_CODE_PAGE == 437 || FF_CODE_PAGE == 0 +static +const WCHAR uc437[] = { /* CP437(U.S.) to Unicode conversion table */ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, + 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, + 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 720 || FF_CODE_PAGE == 0 +static +const WCHAR uc720[] = { /* CP720(Arabic) to Unicode conversion table */ + 0x0000, 0x0000, 0x00E9, 0x00E2, 0x0000, 0x00E0, 0x0000, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0651, 0x0652, 0x00F4, 0x00A4, 0x0640, 0x00FB, 0x00F9, 0x0621, 0x0622, 0x0623, 0x0624, 0x00A3, 0x0625, 0x0626, 0x0627, + 0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x0636, 0x0637, 0x0638, 0x0639, 0x063A, 0x0641, 0x00B5, 0x0642, 0x0643, 0x0644, 0x0645, 0x0646, 0x0647, 0x0648, 0x0649, 0x064A, + 0x2261, 0x064B, 0x064C, 0x064D, 0x064E, 0x064F, 0x0650, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 737 || FF_CODE_PAGE == 0 +static +const WCHAR uc737[] = { /* CP737(Greek) to Unicode conversion table */ + 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, 0x03A0, + 0x03A1, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8, + 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0, 0x03C1, 0x03C3, 0x03C2, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x03C9, 0x03AC, 0x03AD, 0x03AE, 0x03CA, 0x03AF, 0x03CC, 0x03CD, 0x03CB, 0x03CE, 0x0386, 0x0388, 0x0389, 0x038A, 0x038C, 0x038E, + 0x038F, 0x00B1, 0x2265, 0x2264, 0x03AA, 0x03AB, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 771 || FF_CODE_PAGE == 0 +static +const WCHAR uc771[] = { /* CP771(KBL) to Unicode conversion table */ + 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, + 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, + 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x2558, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x0104, 0x0105, 0x010C, 0x010D, + 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F, + 0x0118, 0x0119, 0x0116, 0x0117, 0x012E, 0x012F, 0x0160, 0x0161, 0x0172, 0x0173, 0x016A, 0x016B, 0x017D, 0x017E, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 775 || FF_CODE_PAGE == 0 +static +const WCHAR uc775[] = { /* CP775(Baltic) to Unicode conversion table */ + 0x0106, 0x00FC, 0x00E9, 0x0101, 0x00E4, 0x0123, 0x00E5, 0x0107, 0x0142, 0x0113, 0x0156, 0x0157, 0x012B, 0x0179, 0x00C4, 0x00C5, + 0x00C9, 0x00E6, 0x00C6, 0x014D, 0x00F6, 0x0122, 0x00A2, 0x015A, 0x015B, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x00A4, + 0x0100, 0x012A, 0x00F3, 0x017B, 0x017C, 0x017A, 0x201D, 0x00A6, 0x00A9, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x0141, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x0104, 0x010C, 0x0118, 0x0116, 0x2563, 0x2551, 0x2557, 0x255D, 0x012E, 0x0160, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0172, 0x016A, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x017D, + 0x0105, 0x010D, 0x0119, 0x0117, 0x012F, 0x0161, 0x0173, 0x016B, 0x017E, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x00D3, 0x00DF, 0x014C, 0x0143, 0x00F5, 0x00D5, 0x00B5, 0x0144, 0x0136, 0x0137, 0x013B, 0x013C, 0x0146, 0x0112, 0x0145, 0x2019, + 0x00AD, 0x00B1, 0x201C, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x201E, 0x00B0, 0x2219, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 850 || FF_CODE_PAGE == 0 +static +const WCHAR uc850[] = { /* CP850(Latin 1) to Unicode conversion table */ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, + 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0, 0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, + 0x00F0, 0x00D0, 0x00CA, 0x00CB, 0x00C8, 0x0131, 0x00CD, 0x00CE, 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580, + 0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x00FE, 0x00DE, 0x00DA, 0x00DB, 0x00D9, 0x00FD, 0x00DD, 0x00AF, 0x00B4, + 0x00AD, 0x00B1, 0x2017, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 852 || FF_CODE_PAGE == 0 +static +const WCHAR uc852[] = { /* CP852(Latin 2) to Unicode conversion table */ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x016F, 0x0107, 0x00E7, 0x0142, 0x00EB, 0x0150, 0x0151, 0x00EE, 0x0179, 0x00C4, 0x0106, + 0x00C9, 0x0139, 0x013A, 0x00F4, 0x00F6, 0x013D, 0x013E, 0x015A, 0x015B, 0x00D6, 0x00DC, 0x0164, 0x0165, 0x0141, 0x00D7, 0x010D, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x0104, 0x0105, 0x017D, 0x017E, 0x0118, 0x0119, 0x00AC, 0x017A, 0x010C, 0x015F, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x011A, 0x015E, 0x2563, 0x2551, 0x2557, 0x255D, 0x017B, 0x017C, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0102, 0x0103, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, + 0x0111, 0x0110, 0x010E, 0x00CB, 0x010F, 0x0147, 0x00CD, 0x00CE, 0x011B, 0x2518, 0x250C, 0x2588, 0x2584, 0x0162, 0x016E, 0x2580, + 0x00D3, 0x00DF, 0x00D4, 0x0143, 0x0144, 0x0148, 0x0160, 0x0161, 0x0154, 0x00DA, 0x0155, 0x0170, 0x00FD, 0x00DD, 0x0163, 0x00B4, + 0x00AD, 0x02DD, 0x02DB, 0x02C7, 0x02D8, 0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x02D9, 0x0171, 0x0158, 0x0159, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 855 || FF_CODE_PAGE == 0 +static +const WCHAR uc855[] = { /* CP855(Cyrillic) to Unicode conversion table */ + 0x0452, 0x0402, 0x0453, 0x0403, 0x0451, 0x0401, 0x0454, 0x0404, 0x0455, 0x0405, 0x0456, 0x0406, 0x0457, 0x0407, 0x0458, 0x0408, + 0x0459, 0x0409, 0x045A, 0x040A, 0x045B, 0x040B, 0x045C, 0x040C, 0x045E, 0x040E, 0x045F, 0x040F, 0x044E, 0x042E, 0x044A, 0x042A, + 0x0430, 0x0410, 0x0431, 0x0411, 0x0446, 0x0426, 0x0434, 0x0414, 0x0435, 0x0415, 0x0444, 0x0424, 0x0433, 0x0413, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x0445, 0x0425, 0x0438, 0x0418, 0x2563, 0x2551, 0x2557, 0x255D, 0x0439, 0x0419, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x043A, 0x041A, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, + 0x043B, 0x041B, 0x043C, 0x041C, 0x043D, 0x041D, 0x043E, 0x041E, 0x043F, 0x2518, 0x250C, 0x2588, 0x2584, 0x041F, 0x044F, 0x2580, + 0x042F, 0x0440, 0x0420, 0x0441, 0x0421, 0x0442, 0x0422, 0x0443, 0x0423, 0x0436, 0x0416, 0x0432, 0x0412, 0x044C, 0x042C, 0x2116, + 0x00AD, 0x044B, 0x042B, 0x0437, 0x0417, 0x0448, 0x0428, 0x044D, 0x042D, 0x0449, 0x0429, 0x0447, 0x0427, 0x00A7, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 857 || FF_CODE_PAGE == 0 +static +const WCHAR uc857[] = { /* CP857(Turkish) to Unicode conversion table */ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0131, 0x00C4, 0x00C5, + 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x0130, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x015E, 0x015F, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x011E, 0x011F, 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0, 0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4, + 0x00BA, 0x00AA, 0x00CA, 0x00CB, 0x00C8, 0x0000, 0x00CD, 0x00CE, 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580, + 0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x0000, 0x00D7, 0x00DA, 0x00DB, 0x00D9, 0x00EC, 0x00FF, 0x00AF, 0x00B4, + 0x00AD, 0x00B1, 0x0000, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 860 || FF_CODE_PAGE == 0 +static +const WCHAR uc860[] = { /* CP860(Portuguese) to Unicode conversion table */ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E3, 0x00E0, 0x00C1, 0x00E7, 0x00EA, 0x00CA, 0x00E8, 0x00CD, 0x00D4, 0x00EC, 0x00C3, 0x00C2, + 0x00C9, 0x00C0, 0x00C8, 0x00F4, 0x00F5, 0x00F2, 0x00DA, 0x00F9, 0x00CC, 0x00D5, 0x00DC, 0x00A2, 0x00A3, 0x00D9, 0x20A7, 0x00D3, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x00D2, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x2558, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, + 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 861 || FF_CODE_PAGE == 0 +static +const WCHAR uc861[] = { /* CP861(Icelandic) to Unicode conversion table */ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E6, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00D0, 0x00F0, 0x00DE, 0x00C4, 0x00C5, + 0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00FE, 0x00FB, 0x00DD, 0x00FD, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x20A7, 0x0192, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00C1, 0x00CD, 0x00D3, 0x00DA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, + 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 862 || FF_CODE_PAGE == 0 +static +const WCHAR uc862[] = { /* CP862(Hebrew) to Unicode conversion table */ + 0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF, + 0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, 0x05E8, 0x05E9, 0x05EA, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, + 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 863 || FF_CODE_PAGE == 0 +static +const WCHAR uc863[] = { /* CP863(Canadian French) to Unicode conversion table */ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00C2, 0x00E0, 0x00B6, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x2017, 0x00C0, + 0x00C9, 0x00C8, 0x00CA, 0x00F4, 0x00CB, 0x00CF, 0x00FB, 0x00F9, 0x00A4, 0x00D4, 0x00DC, 0x00A2, 0x00A3, 0x00D9, 0x00DB, 0x0192, + 0x00A6, 0x00B4, 0x00F3, 0x00FA, 0x00A8, 0x00BB, 0x00B3, 0x00AF, 0x00CE, 0x3210, 0x00AC, 0x00BD, 0x00BC, 0x00BE, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2219, + 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 864 || FF_CODE_PAGE == 0 +static +const WCHAR uc864[] = { /* CP864(Arabic) to Unicode conversion table */ + 0x00B0, 0x00B7, 0x2219, 0x221A, 0x2592, 0x2500, 0x2502, 0x253C, 0x2524, 0x252C, 0x251C, 0x2534, 0x2510, 0x250C, 0x2514, 0x2518, + 0x03B2, 0x221E, 0x03C6, 0x00B1, 0x00BD, 0x00BC, 0x2248, 0x00AB, 0x00BB, 0xFEF7, 0xFEF8, 0x0000, 0x0000, 0xFEFB, 0xFEFC, 0x0000, + 0x00A0, 0x00AD, 0xFE82, 0x00A3, 0x00A4, 0xFE84, 0x0000, 0x20AC, 0xFE8E, 0xFE8F, 0xFE95, 0xFE99, 0x060C, 0xFE9D, 0xFEA1, 0xFEA5, + 0x0660, 0x0661, 0x0662, 0x0663, 0x0664, 0x0665, 0x0666, 0x0667, 0x0668, 0x0669, 0xFED1, 0x061B, 0xFEB1, 0xFEB5, 0xFEB9, 0x061F, + 0x00A2, 0xFE80, 0xFE81, 0xFE83, 0xFE85, 0xFECA, 0xFE8B, 0xFE8D, 0xFE91, 0xFE93, 0xFE97, 0xFE9B, 0xFE9F, 0xFEA3, 0xFEA7, 0xFEA9, + 0xFEAB, 0xFEAD, 0xFEAF, 0xFEB3, 0xFEB7, 0xFEBB, 0xFEBF, 0xFEC1, 0xFEC5, 0xFECB, 0xFECF, 0x00A6, 0x00AC, 0x00F7, 0x00D7, 0xFEC9, + 0x0640, 0xFED3, 0xFED7, 0xFEDB, 0xFEDF, 0xFEE3, 0xFEE7, 0xFEEB, 0xFEED, 0xFEEF, 0xFEF3, 0xFEBD, 0xFECC, 0xFECE, 0xFECD, 0xFEE1, + 0xFE7D, 0x0651, 0xFEE5, 0xFEE9, 0xFEEC, 0xFEF0, 0xFEF2, 0xFED0, 0xFED5, 0xFEF5, 0xFEF6, 0xFEDD, 0xFED9, 0xFEF1, 0x25A0, 0x0000 +}; +#endif +#if FF_CODE_PAGE == 865 || FF_CODE_PAGE == 0 +static +const WCHAR uc865[] = { /* CP865(Nordic) to Unicode conversion table */ + 0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5, + 0x00C5, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x20A7, 0x0192, + 0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00A4, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x2558, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229, + 0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 866 || FF_CODE_PAGE == 0 +static +const WCHAR uc866[] = { /* CP866(Russian) to Unicode conversion table */ + 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F, + 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F, + 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F, + 0x0401, 0x0451, 0x0404, 0x0454, 0x0407, 0x0457, 0x040E, 0x045E, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x2116, 0x00A4, 0x25A0, 0x00A0 +}; +#endif +#if FF_CODE_PAGE == 869 || FF_CODE_PAGE == 0 +static +const WCHAR uc869[] = { /* CP869(Greek 2) to Unicode conversion table */ + 0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x0386, 0x00B7, 0x00B7, 0x00AC, 0x00A6, 0x2018, 0x2019, 0x0388, 0x2015, 0x0389, + 0x038A, 0x03AA, 0x038C, 0x00B7, 0x00B7, 0x038E, 0x03AB, 0x00A9, 0x038F, 0x00B2, 0x00B3, 0x03AC, 0x00A3, 0x03AD, 0x03AE, 0x03AF, + 0x03CA, 0x0390, 0x03CC, 0x03CD, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x00BD, 0x0398, 0x0399, 0x00AB, 0x00BB, + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x039A, 0x039B, 0x039C, 0x039D, 0x2563, 0x2551, 0x2557, 0x255D, 0x039E, 0x039F, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0A30, 0x03A1, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x03A3, + 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, 0x03B1, 0x03B2, 0x03B3, 0x2518, 0x250C, 0x2588, 0x2584, 0x03B4, 0x03B5, 0x2580, + 0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0, 0x03C1, 0x03C3, 0x03C2, 0x03C4, 0x0384, + 0x00AD, 0x00B1, 0x03C5, 0x03C6, 0x03C7, 0x00A7, 0x03C8, 0x0385, 0x00B0, 0x00A8, 0x03C9, 0x03CB, 0x03B0, 0x03CE, 0x25A0, 0x00A0 +}; +#endif + + + + +/*------------------------------------------------------------------------*/ +/* OEM <==> Unicode conversions for static code page configuration */ +/* SBCS fixed code page */ +/*------------------------------------------------------------------------*/ + +#if FF_CODE_PAGE != 0 && FF_CODE_PAGE < 900 +WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */ + WCHAR uni, /* Unicode character to be converted */ + WORD cp /* Code page for the conversion */ +) +{ + WCHAR c = 0; + const WCHAR *p = CVTBL(uc, FF_CODE_PAGE); + + + if (uni < 0x80) { /* ASCII char */ + c = uni; + + } else { /* Non-ASCII char */ + if (cp == FF_CODE_PAGE) { /* Is it a valid code page? */ + for (c = 0; c < 0x80 && uni != p[c]; c++) ; + c = (c + 0x80) & 0xFF; + } + } + return c; +} + +WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */ + WCHAR oem, /* OEM code to be converted */ + WORD cp /* Code page for the conversion */ +) +{ + WCHAR c = 0; + const WCHAR *p = CVTBL(uc, FF_CODE_PAGE); + + + if (oem < 0x80) { /* ASCII char */ + c = oem; + + } else { /* Extended char */ + if (cp == FF_CODE_PAGE) { /* Is it a valid code page? */ + if (oem < 0x100) c = p[oem - 0x80]; + } + } + return c; +} + +#endif + + + +/*------------------------------------------------------------------------*/ +/* OEM <==> Unicode conversions for static code page configuration */ +/* DBCS fixed code page */ +/*------------------------------------------------------------------------*/ + +#if FF_CODE_PAGE != 0 && FF_CODE_PAGE >= 900 +WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */ + WCHAR uni, /* Unicode character to be converted */ + WORD cp /* Code page for the conversion */ +) +{ + const WCHAR *p; + WCHAR c = 0; + UINT i, n, li, hi; + + + if (uni < 0x80) { /* ASCII char */ + c = uni; + + } else { /* Non-ASCII char */ + if (cp == FF_CODE_PAGE) { /* Is it a valid code page? */ + p = CVTBL(uni2oem, FF_CODE_PAGE); + hi = sizeof CVTBL(uni2oem, FF_CODE_PAGE) / 4 - 1; + li = 0; + for (n = 16; n; n--) { + i = li + (hi - li) / 2; + if (uni == p[i * 2]) break; + if (uni > p[i * 2]) { + li = i; + } else { + hi = i; + } + } + if (n != 0) c = p[i * 2 + 1]; + } + } + return c; +} + + +WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */ + WCHAR oem, /* OEM code to be converted */ + WORD cp /* Code page for the conversion */ +) +{ + const WCHAR *p; + WCHAR c = 0; + UINT i, n, li, hi; + + + if (oem < 0x80) { /* ASCII char */ + c = oem; + + } else { /* Extended char */ + if (cp == FF_CODE_PAGE) { /* Is it a valid code page? */ + p = CVTBL(oem2uni, FF_CODE_PAGE); + hi = sizeof CVTBL(oem2uni, FF_CODE_PAGE) / 4 - 1; + li = 0; + for (n = 16; n; n--) { + i = li + (hi - li) / 2; + if (oem == p[i * 2]) break; + if (oem > p[i * 2]) { + li = i; + } else { + hi = i; + } + } + if (n != 0) c = p[i * 2 + 1]; + } + } + return c; +} +#endif + + + +/*------------------------------------------------------------------------*/ +/* OEM <==> Unicode conversions for dynamic code page configuration */ +/*------------------------------------------------------------------------*/ + +#if FF_CODE_PAGE == 0 + +static const WORD cp_code[] = { 437, 720, 737, 771, 775, 850, 852, 855, 857, 860, 861, 862, 863, 864, 865, 866, 869, 0}; +static const WCHAR *const cp_table[] = {uc437, uc720, uc737, uc771, uc775, uc850, uc852, uc855, uc857, uc860, uc861, uc862, uc863, uc864, uc865, uc866, uc869, 0}; + + +WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */ + WCHAR uni, /* Unicode character to be converted */ + WORD cp /* Code page for the conversion */ +) +{ + const WCHAR *p; + WCHAR c = 0; + UINT i, n, li, hi; + + + if (uni < 0x80) { /* ASCII char */ + c = uni; + + } else { /* Non-ASCII char */ + p = 0; + if (cp < 900) { /* SBCS */ + for (i = 0; cp_code[i] != 0 && cp_code[i] != cp; i++) ; /* Get table */ + p = cp_table[i]; + if (p) { /* Is it a valid CP ? */ + for (c = 0; c < 0x80 && uni != p[c]; c++) ; /* Find OEM code in the table */ + c = (c + 0x80) & 0xFF; + } + } else { /* DBCS */ + switch (cp) { + case 932 : p = uni2oem932; hi = sizeof uni2oem932 / 4 - 1; break; + case 936 : p = uni2oem936; hi = sizeof uni2oem936 / 4 - 1; break; + case 949 : p = uni2oem949; hi = sizeof uni2oem949 / 4 - 1; break; + case 950 : p = uni2oem950; hi = sizeof uni2oem950 / 4 - 1; break; + } + if (p) { /* Is it a valid code page? */ + li = 0; + for (n = 16; n; n--) { /* Find OEM code */ + i = li + (hi - li) / 2; + if (uni == p[i * 2]) break; + if (uni > p[i * 2]) { + li = i; + } else { + hi = i; + } + } + if (n != 0) c = p[i * 2 + 1]; + } + } + } + return c; +} + + +WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */ + WCHAR oem, /* OEM code to be converted */ + WORD cp /* Code page for the conversion */ +) +{ + const WCHAR *p; + WCHAR c = 0; + UINT i, n, li, hi; + + + if (oem < 0x80) { /* ASCII char */ + c = oem; + + } else { /* Extended char */ + p = 0; + if (cp < 900) { /* SBCS */ + for (i = 0; cp_code[i] != 0 && cp_code[i] != cp; i++) ; /* Get table */ + p = cp_table[i]; + if (p) { /* Is it a valid CP ? */ + if (oem < 0x100) c = p[oem - 0x80]; + } + } else { /* DBCS */ + switch (cp) { + case 932 : p = oem2uni932; hi = sizeof oem2uni932 / 4 - 1; break; + case 936 : p = oem2uni936; hi = sizeof oem2uni936 / 4 - 1; break; + case 949 : p = oem2uni949; hi = sizeof oem2uni949 / 4 - 1; break; + case 950 : p = oem2uni950; hi = sizeof oem2uni950 / 4 - 1; break; + } + if (p) { + li = 0; + for (n = 16; n; n--) { + i = li + (hi - li) / 2; + if (oem == p[i * 2]) break; + if (oem > p[i * 2]) { + li = i; + } else { + hi = i; + } + } + if (n != 0) c = p[i * 2 + 1]; + } + } + } + return c; +} +#endif + + + +/*------------------------------------------------------------------------*/ +/* Unicode up-case conversion */ +/*------------------------------------------------------------------------*/ + +WCHAR ff_wtoupper ( /* Returns up-converted character */ + WCHAR uni /* Unicode character to be upper converted (BMP only) */ +) +{ + /* Compressed upper conversion table */ + static const WCHAR cvt1[] = { /* U+0000 - U+0FFF */ + /* Basic Latin */ + 0x0061,0x031A, + /* Latin-1 Supplement */ + 0x00E0,0x0317, 0x00F8,0x0307, 0x00FF,0x0001,0x0178, + /* Latin Extended-A */ + 0x0100,0x0130, 0x0132,0x0106, 0x0139,0x0110, 0x014A,0x012E, 0x0179,0x0106, + /* Latin Extended-B */ + 0x0180,0x004D,0x0243,0x0181,0x0182,0x0182,0x0184,0x0184,0x0186,0x0187,0x0187,0x0189,0x018A,0x018B,0x018B,0x018D,0x018E,0x018F,0x0190,0x0191,0x0191,0x0193,0x0194,0x01F6,0x0196,0x0197,0x0198,0x0198,0x023D,0x019B,0x019C,0x019D,0x0220,0x019F,0x01A0,0x01A0,0x01A2,0x01A2,0x01A4,0x01A4,0x01A6,0x01A7,0x01A7,0x01A9,0x01AA,0x01AB,0x01AC,0x01AC,0x01AE,0x01AF,0x01AF,0x01B1,0x01B2,0x01B3,0x01B3,0x01B5,0x01B5,0x01B7,0x01B8,0x01B8,0x01BA,0x01BB,0x01BC,0x01BC,0x01BE,0x01F7,0x01C0,0x01C1,0x01C2,0x01C3,0x01C4,0x01C5,0x01C4,0x01C7,0x01C8,0x01C7,0x01CA,0x01CB,0x01CA, + 0x01CD,0x0110, 0x01DD,0x0001,0x018E, 0x01DE,0x0112, 0x01F3,0x0003,0x01F1,0x01F4,0x01F4, 0x01F8,0x0128, + 0x0222,0x0112, 0x023A,0x0009,0x2C65,0x023B,0x023B,0x023D,0x2C66,0x023F,0x0240,0x0241,0x0241, 0x0246,0x010A, + /* IPA Extensions */ + 0x0253,0x0040,0x0181,0x0186,0x0255,0x0189,0x018A,0x0258,0x018F,0x025A,0x0190,0x025C,0x025D,0x025E,0x025F,0x0193,0x0261,0x0262,0x0194,0x0264,0x0265,0x0266,0x0267,0x0197,0x0196,0x026A,0x2C62,0x026C,0x026D,0x026E,0x019C,0x0270,0x0271,0x019D,0x0273,0x0274,0x019F,0x0276,0x0277,0x0278,0x0279,0x027A,0x027B,0x027C,0x2C64,0x027E,0x027F,0x01A6,0x0281,0x0282,0x01A9,0x0284,0x0285,0x0286,0x0287,0x01AE,0x0244,0x01B1,0x01B2,0x0245,0x028D,0x028E,0x028F,0x0290,0x0291,0x01B7, + /* Greek, Coptic */ + 0x037B,0x0003,0x03FD,0x03FE,0x03FF, 0x03AC,0x0004,0x0386,0x0388,0x0389,0x038A, 0x03B1,0x0311, + 0x03C2,0x0002,0x03A3,0x03A3, 0x03C4,0x0308, 0x03CC,0x0003,0x038C,0x038E,0x038F, 0x03D8,0x0118, + 0x03F2,0x000A,0x03F9,0x03F3,0x03F4,0x03F5,0x03F6,0x03F7,0x03F7,0x03F9,0x03FA,0x03FA, + /* Cyrillic */ + 0x0430,0x0320, 0x0450,0x0710, 0x0460,0x0122, 0x048A,0x0136, 0x04C1,0x010E, 0x04CF,0x0001,0x04C0, 0x04D0,0x0144, + /* Armenian */ + 0x0561,0x0426, + + 0x0000 + }; + static const WCHAR cvt2[] = { /* U+1000 - U+FFFF */ + /* Phonetic Extensions */ + 0x1D7D,0x0001,0x2C63, + /* Latin Extended Additional */ + 0x1E00,0x0196, 0x1EA0,0x015A, + /* Greek Extended */ + 0x1F00,0x0608, 0x1F10,0x0606, 0x1F20,0x0608, 0x1F30,0x0608, 0x1F40,0x0606, + 0x1F51,0x0007,0x1F59,0x1F52,0x1F5B,0x1F54,0x1F5D,0x1F56,0x1F5F, 0x1F60,0x0608, + 0x1F70,0x000E,0x1FBA,0x1FBB,0x1FC8,0x1FC9,0x1FCA,0x1FCB,0x1FDA,0x1FDB,0x1FF8,0x1FF9,0x1FEA,0x1FEB,0x1FFA,0x1FFB, + 0x1F80,0x0608, 0x1F90,0x0608, 0x1FA0,0x0608, 0x1FB0,0x0004,0x1FB8,0x1FB9,0x1FB2,0x1FBC, + 0x1FCC,0x0001,0x1FC3, 0x1FD0,0x0602, 0x1FE0,0x0602, 0x1FE5,0x0001,0x1FEC, 0x1FF3,0x0001,0x1FFC, + /* Letterlike Symbols */ + 0x214E,0x0001,0x2132, + /* Number forms */ + 0x2170,0x0210, 0x2184,0x0001,0x2183, + /* Enclosed Alphanumerics */ + 0x24D0,0x051A, 0x2C30,0x042F, + /* Latin Extended-C */ + 0x2C60,0x0102, 0x2C67,0x0106, 0x2C75,0x0102, + /* Coptic */ + 0x2C80,0x0164, + /* Georgian Supplement */ + 0x2D00,0x0826, + /* Full-width */ + 0xFF41,0x031A, + + 0x0000 + }; + const WCHAR *p; + WCHAR bc, nc, cmd; + + + p = uni < 0x1000 ? cvt1 : cvt2; + for (;;) { + bc = *p++; /* Get block base */ + if (!bc || uni < bc) break; + nc = *p++; cmd = nc >> 8; nc &= 0xFF; /* Get processing command and block size */ + if (uni < bc + nc) { /* In the block? */ + switch (cmd) { + case 0: uni = p[uni - bc]; break; /* Table conversion */ + case 1: uni -= (uni - bc) & 1; break; /* Case pairs */ + case 2: uni -= 16; break; /* Shift -16 */ + case 3: uni -= 32; break; /* Shift -32 */ + case 4: uni -= 48; break; /* Shift -48 */ + case 5: uni -= 26; break; /* Shift -26 */ + case 6: uni += 8; break; /* Shift +8 */ + case 7: uni -= 80; break; /* Shift -80 */ + case 8: uni -= 0x1C60; break; /* Shift -0x1C60 */ + } + break; + } + if (!cmd) p += nc; + } + + return uni; +} + + +#endif /* #if _USE_LFN */ diff --git a/beken_os/beken378/func/music_player/fs_fat/integer.h b/beken_os/beken378/func/music_player/fs_fat/integer.h new file mode 100755 index 0000000..4fcf5c4 --- /dev/null +++ b/beken_os/beken378/func/music_player/fs_fat/integer.h @@ -0,0 +1,38 @@ +/*-------------------------------------------*/ +/* Integer type definitions for FatFs module */ +/*-------------------------------------------*/ + +#ifndef FF_INTEGER +#define FF_INTEGER + +#ifdef _WIN32 /* FatFs development platform */ + +#include +#include +typedef unsigned __int64 QWORD; + + +#else /* Embedded platform */ + +/* These types MUST be 16-bit or 32-bit */ +typedef int INT; +typedef unsigned int UINT; + +/* This type MUST be 8-bit */ +typedef unsigned char BYTE; + +/* These types MUST be 16-bit */ +typedef short SHORT; +typedef unsigned short WORD; +typedef unsigned short WCHAR; + +/* These types MUST be 32-bit */ +typedef long LONG; +typedef unsigned long DWORD; + +/* This type MUST be 64-bit (Remove this for ANSI C (C89) compatibility) */ +typedef unsigned long long QWORD; + +#endif + +#endif diff --git a/beken_os/beken378/func/music_player/fs_fat/playmode.c b/beken_os/beken378/func/music_player/fs_fat/playmode.c new file mode 100755 index 0000000..9023924 --- /dev/null +++ b/beken_os/beken378/func/music_player/fs_fat/playmode.c @@ -0,0 +1,450 @@ +#include "include.h" +#include "mem_pub.h" +#include "uart_pub.h" +#include "ff.h" +#include "driver_audio_if_pub.h" + +#if (CONFIG_APP_MP3PLAYER == 1) + +#define MAX_DIR_SUPPORT 1024 +#define MAX_SONG_DIR 64 // 128 +#define MAX_DIR_LEVEL 6 +#define MAX_DISK_NUM 2 + +BYTE MP3_Ext[] = ".MP3"; + +FILE_INFO FileInfo; +FAT_DIR_INFO* file_queue = NULL; + +FATFS *Fatfs_buf; +FIL *fsFD; +DIR_QUEUE *point_front;//ͷָ +DIR_QUEUE *point_rear;//βָ +static SHORT rear_cnt = 0; +static SHORT mp3queuecount = 0; //MP3ļļĿ +static SHORT mp3filecount = 0;// MP3ܵĿ +BYTE disk_no = 0; + +int beken_strcmpi (const void* dst, const void* src, int cnt) +{ + const char *d = (const char *)dst, *s = (const char *)src; + int r = 0; + while (cnt-- && (r = *d++ - *s++) == 0) ; + return r; +} + +char * strrchr_con(char * str,char ch) +{ + char *p = (char *)str; + while (*str) str++; + while ((str-- != p) && (*str != ch)); + if (*str == ch) + return( (char *)str ); + return NULL; +} +static void Convert2UpperCase(char *str,UINT len) +{ + UINT i; + for(i=0;i='a'))?(str[i]-=0x20):str[i]; +} + +FRESULT f_open_con ( + FIL *fp, /* Pointer to the blank file object */ + PFILINFOADD finfo, + BYTE mode /* Access mode and file open mode flags */ +) +{ + + fp->obj.sclust = finfo->fcluster;/* File start cluster */ + fp->obj.objsize = finfo->fsize; /* File size */ + + fp->obj.fs = Fatfs_buf; + fp->obj.id = Fatfs_buf->id; /* Owner file system object of the file */ + fp->flag = mode; /* File access mode */ + fp->err = 0; /* Clear error flag */ + fp->sect = 0; /* Invalidate current data sector */ + fp->fptr = 0; /* Set file pointer top of the file */ + if(fp->obj.fs->fs_type == FS_EXFAT) + { + fp->obj.n_frag = 0; + fp->obj.stat = finfo->ExNoChainFlag; + } + return FR_OK; +} + +/*input: +i -- directory index +number -- music file idx in directory i */ +static FIL *GetFile_From_NumInDir(WORD i, WORD number) +{ + WORD n,brootdir,music_count; + FRESULT res; + FILINFOADD fno; + DIR dj_con; + char *Ext = NULL; + FIL *fio = fsFD; + FAT_DIR_INFO* file = file_queue + i; + + dj_con.obj.fs = Fatfs_buf; + brootdir = file->broot_dir; + + res=init_buf(Fatfs_buf); + if(res != FR_OK) + return NULL; + + if(brootdir) + dj_con.obj.sclust = 0; + else + dj_con.obj.sclust = file->first_cluster; + + music_count = 0; + number += 1; + res = Beken_dir_sdi(&dj_con, 0); + if (res != FR_OK) + { + fio =NULL; + goto ret_free; + } + + while(res == FR_OK) + { + res = Beken_dir_read(&dj_con, 0); + if (res != FR_OK) + break; + /* Get the directory name and push it to the buffer */ + Beken_get_fileinfo(&dj_con, &fno); + if((fno.fattrib & 0x20)!=0)/*ֻءϵͳļ֧*/ + { + for (n = 0; fno.fname[n]; n++); + if((n > 4)&&(n <= FF_MAX_LFN)) + { + Convert2UpperCase(&fno.fname[n-3],3); + Ext = &fno.fname[n-4]; + if (!beken_strcmpi((const void*)Ext, (const void*)MP3_Ext, 4)) + music_count++; + } + } + if (music_count == number) + { + beken_mem_cpy(FileInfo.fname,fno.fname,12); + beken_mem_cpy(FileInfo.extname,fno.fname+n-3,3); + break; + } + else + res = Beken_dir_next(&dj_con, 0); + } + + FileInfo.fcluster = fno.fcluster; + f_open_con(fio, &fno, FA_READ); + +ret_free: + uninit_buf(Fatfs_buf); + return fio; + +} + + +/* +dir_num:dir index (start from 0) +song_idx:current song index +*/ +FIL *Get_Cur_Dir_file(WORD dir_num,WORD song_idx) +{ + FIL *fhFile; + FAT_DIR_INFO* file = NULL; + + if(dir_num >= mp3queuecount) + dir_num = 0; + + file = file_queue + dir_num; + if(song_idx > file->music_total) + song_idx = 0; + os_printf("total_dir:%d,cur_dir:%d,cur_dir_song_num:%d,cur_dir_song_index:%d\r\n",mp3queuecount,dir_num,file->music_total,song_idx); + fhFile = GetFile_From_NumInDir(dir_num, song_idx); + return fhFile; + +} + +/*input:number -- 0~mp3filecount-1 */ +//Playlist_GetSongFileInfo +FIL *Get_File_From_Number(WORD number) +{ + WORD i; + FIL *fhFile; + FAT_DIR_INFO* file = NULL; + + for(i=0; i= file->music_total) + { + number = number - file->music_total; + continue; + } + else + break; + } + if(i == MAX_SONG_DIR) + return NULL; + fhFile = GetFile_From_NumInDir(i, number); + return fhFile; +} + + + +static FRESULT get_curdir_info(DIR_QUEUE *p_front) +{ + WORD n; + + DIR dj; + FILINFOADD fno; + unsigned short cur_musicfile = 0; + char *Ext = NULL; + FAT_DIR_INFO* file = NULL; + FRESULT res = FR_OK; + DIR_QUEUE* front; + DIR_QUEUE* next; + + dj.obj.fs = Fatfs_buf; + dj.obj.stat = p_front->ExNoChainFlag; + + res=init_buf(Fatfs_buf); + if(res != FR_OK) + return res; + + if(p_front->broot_dir) + dj.obj.sclust = 0;//for Fat16 + else + { + dj.obj.sclust = p_front ->cluster_number; + dj.obj.stat = p_front ->ExNoChainFlag; + } + + front = p_front; + next = p_front->next; + + res = Beken_dir_sdi(&dj, 0); + while(res == FR_OK) + { + res = Beken_dir_read(&dj, 0); + if (res != FR_OK) + break; + + /* Get the directory name and push it to the buffer */ + Beken_get_fileinfo(&dj, &fno); + if(((fno.fattrib & 0x10) !=0) &&(front->dirlevel + 1 < MAX_DIR_LEVEL)) + { + p_front->next = point_rear; + p_front = point_rear; + point_rear->cluster_number = fno.fcluster; + point_rear->dirlevel = front->dirlevel + 1; + point_rear->broot_dir = 0; + point_rear->ExNoChainFlag = fno.ExNoChainFlag; + point_rear->next = next; + if(++rear_cnt > MAX_DIR_SUPPORT-1) + break; + point_rear++; + } + if((fno.fattrib & 0x20)!=0)/*ֻءϵͳļ֧*/ + { + for (n = 0; fno.fname[n]; n++); + if((n > 4)&&(n <= FF_MAX_LFN)) + { + Convert2UpperCase(&fno.fname[n-3],3); + Ext = &fno.fname[n-4]; + + if (!beken_strcmpi((const void*)Ext, (const void*)MP3_Ext, 4)) + cur_musicfile++; + } + } + res = Beken_dir_next(&dj, 0); + } + + if (cur_musicfile) + { + file = file_queue + mp3queuecount; + file->first_cluster = front->cluster_number; + file->music_total = cur_musicfile; + file->broot_dir = front->broot_dir; + file->ExNoChainFlag = front->ExNoChainFlag; + mp3queuecount++; + mp3filecount += cur_musicfile; + } + + uninit_buf(Fatfs_buf); + return FR_OK; +} +FRESULT fat_malloc_files_buffer(void) +{ + fsFD = (FIL*)ff_memalloc(sizeof(FIL)); + Fatfs_buf = (FATFS*)ff_memalloc(sizeof(FATFS)); + file_queue = (FAT_DIR_INFO*)ff_memalloc(MAX_SONG_DIR*sizeof(FAT_DIR_INFO)); + if(!fsFD || !Fatfs_buf || !file_queue) + { + goto failed; + } + + return FR_OK; + +failed: + if(file_queue) + ff_memfree(file_queue); + if(Fatfs_buf) + ff_memfree(Fatfs_buf); + if(fsFD) + ff_memfree(fsFD); + file_queue = NULL; + Fatfs_buf = NULL; + fsFD = NULL; + return FR_INT_ERR; +} + +void fat_free_files_buffer(void) +{ + if(file_queue) + ff_memfree(file_queue); + if(Fatfs_buf) + ff_memfree(Fatfs_buf); + if(fsFD) + ff_memfree(fsFD); + + file_queue = NULL; + Fatfs_buf = NULL; + fsFD = NULL; +} + +BYTE scan_disk(void) +{ + UINT count = 0; + DIR_QUEUE *dir_buf; + + rear_cnt = 0; + dir_buf=(DIR_QUEUE*)ff_memalloc(MAX_DIR_SUPPORT*sizeof(DIR_QUEUE));//ֵ֧ļ + if(!dir_buf) + { + return 1; + } + + beken_mem_set(file_queue, 0, MAX_SONG_DIR* sizeof(FAT_DIR_INFO)); + mp3filecount = 0; + mp3queuecount = 0; + point_front = point_rear = dir_buf; + + point_front ->cluster_number = Fatfs_buf->dirbase; + point_front ->dirlevel = 0; + point_front ->ExNoChainFlag = 0; + point_front->next = NULL; + + + if (Fatfs_buf->fs_type == FS_FAT16) + point_front ->broot_dir = 1; + else + point_front ->broot_dir = 0; + + point_rear++; + rear_cnt++; + while(1) + { + if ((mp3queuecount MAX_DIR_SUPPORT-1) + break; + + get_curdir_info(point_front); + count++; + point_front = point_front->next; + } + else + break; + } + os_printf("dir cnt=%d, mp3 dir cnt=%d mp3filecount=%d,rear_cnt =%d\r\n",count,mp3queuecount,mp3filecount,rear_cnt); + + ff_memfree(dir_buf); + + return 0; +} + +BYTE media_init(BYTE disk_type) +{ + FRESULT res; + FileInfo.fat_ok_flag = 0; + + if(FR_OK != fat_malloc_files_buffer()) + { + os_printf("media alloc fail\r\n"); + return 1; + } + + if(disk_type >= MAX_DISK_NUM) + disk_type = 0; + disk_no = disk_type; + + if(disk_no ==0) + res=f_mount(Fatfs_buf,"0:",1); + else + res=f_mount(Fatfs_buf,"1:",1); + + if(res!=FR_OK)/* Mount a logical drive */ + { + os_printf("mount fail:%x\r\n",res); + if(Fatfs_buf) + os_printf("+++%x--\r\n",Fatfs_buf->pdrv); + return 1; + } + + if(scan_disk() != FR_OK) + return 1; + + FileInfo.fat_ok_flag = 1; + return 0; +} + +void media_uninit(void) +{ + mp3filecount = 0; + FileInfo.fat_ok_flag = 0; + + if(disk_no == 0) + f_unmount(0,"0:",1); + else + f_unmount(1,"1:",1); + fat_free_files_buffer(); +} + + +BYTE get_fat_ok_flag(void) +{ + return FileInfo.fat_ok_flag; +} + +WORD get_musicfile_count(void) +{ + return mp3filecount; +} +WORD get_curDirMusicfile_count(uint16 curDir) +{ + FAT_DIR_INFO* file = NULL; + os_printf("get_curDirMusicfile_count curDir=%d,\r\n",curDir); + if(curDir >= mp3queuecount) + curDir = 0; + file = file_queue + curDir; + os_printf("get_curDirMusicfile_file=0x%x,file->music_total=%d\r\n",file,file->music_total); + return file->music_total; +} +FILE_INFO *get_file_info(void) +{ + return (&FileInfo); +} + +BYTE get_disk_type(void) +{ + return Fatfs_buf->pdrv; +} + +WORD get_music_dir_count(void) +{ + return mp3queuecount; +} +#endif + diff --git a/beken_os/beken378/func/music_player/fs_fat/playmode_pub.h b/beken_os/beken378/func/music_player/fs_fat/playmode_pub.h new file mode 100755 index 0000000..e7a8459 --- /dev/null +++ b/beken_os/beken378/func/music_player/fs_fat/playmode_pub.h @@ -0,0 +1,12 @@ +#ifndef _PLAY_MODE_H_ +#define _PLAY_MODE_H_ + +#include "ff.h" + +extern FIL *Get_File_From_Number(WORD number); +extern FILE_INFO *get_file_info(void); +extern WORD get_musicfile_count(void); +extern BYTE media_init(BYTE disk_type); +extern BYTE get_fat_ok_flag(void); +extern void media_uninit(void); +#endif diff --git a/beken_os/beken378/func/net_param_intf/net_param.c b/beken_os/beken378/func/net_param_intf/net_param.c new file mode 100755 index 0000000..426a4a9 --- /dev/null +++ b/beken_os/beken378/func/net_param_intf/net_param.c @@ -0,0 +1,297 @@ +#include "include.h" + +#if 1 //CFG_ENABLE_ATE_FEATURE +#include "mem_pub.h" +#include "drv_model_pub.h" +#include "net_param_pub.h" +#include "flash_pub.h" +#if CFG_SUPPORT_ALIOS +#include "hal/soc/soc.h" +#else +#include "BkDriverFlash.h" +#include "BkDriverUart.h" +#endif + +static UINT32 search_info_tbl(UINT8 *buf,UINT32 *cfg_len) +{ + UINT32 ret = 0, status; + DD_HANDLE flash_handle; + TLV_HEADER_ST head; +#if CFG_SUPPORT_ALIOS + hal_logic_partition_t *pt = hal_flash_get_info(HAL_PARTITION_PARAMETER_4); +#else + bk_logic_partition_t *pt = bk_flash_get_info(BK_PARTITION_NET_PARAM); +#endif + + *cfg_len = 0; + flash_handle = ddev_open(FLASH_DEV_NAME, &status, 0); + ddev_read(flash_handle, (char *)&head, sizeof(TLV_HEADER_ST), pt->partition_start_addr); + if(INFO_TLV_HEADER == head.type) + { + *cfg_len = head.len + sizeof(TLV_HEADER_ST); + ret = 1; + if(buf != NULL) + ddev_read(flash_handle, (char*)buf, *cfg_len, pt->partition_start_addr); + } + ddev_close(flash_handle); + return ret; +} + +static UINT32 search_info_item(NET_INFO_ITEM type, UINT32 start_addr) +{ + UINT32 status, addr, end_addr; + DD_HANDLE flash_handle; + INFO_ITEM_ST head; + + flash_handle = ddev_open(FLASH_DEV_NAME, &status, 0); + ddev_read(flash_handle, (char *)&head, sizeof(TLV_HEADER_ST), start_addr); + addr = start_addr + sizeof(TLV_HEADER_ST); + end_addr = addr + head.len; + while(addr < end_addr) + { + ddev_read(flash_handle, (char *)&head, sizeof(INFO_ITEM_ST), addr); + if(type != head.type) + { + addr += sizeof(INFO_ITEM_ST); + addr += head.len; + } + else + { + break; + } + } + + if(addr >= end_addr) + { + addr = 0; + } + ddev_close(flash_handle); + + return addr; +} + +static UINT32 info_item_len(NET_INFO_ITEM item) +{ + UINT32 len = 0; + switch(item) + { + case AUTO_CONNECT_ITEM: + case WIFI_MODE_ITEM: + case DHCP_MODE_ITEM: + case RF_CFG_TSSI_ITEM: + case RF_CFG_DIST_ITEM: + case RF_CFG_MODE_ITEM: + case RF_CFG_TSSI_B_ITEM: + len = sizeof(ITEM_COMM_ST); + break; + case WIFI_MAC_ITEM: + len = sizeof(ITEM_MAC_ADDR_ST); + break; + + case SSID_KEY_ITEM: + len = sizeof(ITEM_SSIDKEY_ST); + break; + case IP_CONFIG_ITEM: + len = sizeof(ITEM_IP_CONFIG_ST); + break; + default: + len = sizeof(ITEM_COMM_ST); + break; + } + return len; +} + +UINT32 get_info_item(NET_INFO_ITEM item,UINT8 *ptr0,UINT8 *ptr1, UINT8 *ptr2) +{ + UINT32 status, addr_start,len; + DD_HANDLE flash_handle; + INFO_ITEM_ST head; +#if CFG_SUPPORT_ALIOS + hal_logic_partition_t *pt; +#else + bk_logic_partition_t *pt; +#endif + UINT32 ret = 0; + + if(!search_info_tbl(NULL,&len)) + return ret; + +#if CFG_SUPPORT_ALIOS + pt = hal_flash_get_info(HAL_PARTITION_PARAMETER_4); +#else + pt = bk_flash_get_info(BK_PARTITION_NET_PARAM); +#endif + addr_start = search_info_item(item, pt->partition_start_addr); + if(!addr_start) + return ret; + + flash_handle = ddev_open(FLASH_DEV_NAME, &status, 0); + ddev_read(flash_handle, (char *)&head, sizeof(INFO_ITEM_ST), addr_start); + addr_start += sizeof(INFO_ITEM_ST); + + switch(item) + { + case AUTO_CONNECT_ITEM: + case WIFI_MODE_ITEM: + case DHCP_MODE_ITEM: + case WIFI_MAC_ITEM: + case RF_CFG_TSSI_ITEM: + case RF_CFG_DIST_ITEM: + case RF_CFG_MODE_ITEM: + case RF_CFG_TSSI_B_ITEM: + if(ptr0 != NULL) + { + ddev_read(flash_handle, (char *)ptr0, head.len, addr_start); + ret = 1; + } + break; + + case SSID_KEY_ITEM: + if((ptr0 != NULL) && (ptr1 != NULL)) + { + ddev_read(flash_handle, (char *)ptr0, 32, addr_start); + addr_start += 32; + ddev_read(flash_handle, (char *)ptr1, 64, addr_start); + ret = 1; + } + break; + + case IP_CONFIG_ITEM: + if((ptr0 != NULL) && (ptr1 != NULL) && (ptr2 != NULL)) + { + ddev_read(flash_handle, (char *)ptr0, 16, addr_start); + addr_start += 16; + ddev_read(flash_handle, (char *)ptr1, 16, addr_start); + addr_start += 16; + ddev_read(flash_handle, (char *)ptr2, 16, addr_start); + ret = 1; + } + break; + + default: + ret = 0; + break; + } + + + ddev_close(flash_handle); + return ret; +} + +UINT32 save_info_item(NET_INFO_ITEM item,UINT8 *ptr0,UINT8*ptr1,UINT8 *ptr2) +{ + UINT32 addr_offset,cfg_tbl_len,item_len,tmp; + UINT8 *tmpptr; + UINT8 *item_buf; + UINT32 *wrbuf; +/// DD_HANDLE flash_handle; + INFO_ITEM_ST head; + INFO_ITEM_ST_PTR item_head_ptr; +#if CFG_SUPPORT_ALIOS + UINT32 offset; + hal_logic_partition_t *pt = hal_flash_get_info(HAL_PARTITION_PARAMETER_4); +#else + bk_logic_partition_t *pt = bk_flash_get_info(BK_PARTITION_NET_PARAM); +#endif + + item_len = info_item_len(item); + + head.type = INFO_TLV_HEADER; + + if(!search_info_tbl(NULL,&cfg_tbl_len))//no TLV + { + cfg_tbl_len = sizeof(INFO_ITEM_ST)+item_len; + addr_offset = sizeof(INFO_ITEM_ST); + head.len = item_len; + wrbuf = os_zalloc(cfg_tbl_len); + if(wrbuf == NULL) + return 0; + } + else + { + addr_offset = search_info_item(item, pt->partition_start_addr); + + if(!addr_offset)//no item + { + addr_offset = cfg_tbl_len; + cfg_tbl_len += item_len; + } + else + { + addr_offset -= pt->partition_start_addr; + } + wrbuf = os_zalloc(cfg_tbl_len); + if(wrbuf == NULL) + return 0; + search_info_tbl((UINT8*)wrbuf,&tmp); + head.len = cfg_tbl_len - sizeof(TLV_HEADER_ST); + } + + tmpptr = (UINT8*)wrbuf; + item_head_ptr = (INFO_ITEM_ST_PTR)(tmpptr + addr_offset); + item_buf =(UINT8*)(tmpptr + addr_offset + sizeof(INFO_ITEM_ST)); + switch(item) + { + case AUTO_CONNECT_ITEM: + case WIFI_MODE_ITEM: + case DHCP_MODE_ITEM: + case RF_CFG_TSSI_ITEM: + case RF_CFG_DIST_ITEM: + case RF_CFG_MODE_ITEM: + case RF_CFG_TSSI_B_ITEM: + os_memcpy(item_buf,ptr0,4); + break; + + case WIFI_MAC_ITEM: + os_memcpy(item_buf,ptr0,6); + break; + + case SSID_KEY_ITEM: + os_memcpy(item_buf,ptr0,32); + os_memcpy(item_buf+32,ptr1,64); + break; + + case IP_CONFIG_ITEM: + os_memcpy(item_buf,ptr0,16); + os_memcpy(item_buf+16,ptr1,16); + os_memcpy(item_buf+32,ptr2,16); + break; + + default: + os_memcpy(item_buf,ptr0,4); + break; + } + item_head_ptr->type = item; + item_head_ptr->len = item_len- sizeof(INFO_ITEM_ST); + +//set TLV header + os_memcpy(tmpptr,&head,sizeof(TLV_HEADER_ST)); + + hal_flash_lock(); +//assume info cfg tbl size is less than 4k +#if CFG_SUPPORT_ALIOS + offset = 0; + hal_flash_dis_secure(HAL_PARTITION_PARAMETER_4, 0, 0); + hal_flash_erase(HAL_PARTITION_PARAMETER_4,0,cfg_tbl_len); + hal_flash_write(HAL_PARTITION_PARAMETER_4,&offset,tmpptr,cfg_tbl_len); + hal_flash_enable_secure(HAL_PARTITION_PARAMETER_4, 0, 0); +#else + bk_flash_enable_security(FLASH_PROTECT_NONE); + bk_flash_erase(BK_PARTITION_NET_PARAM,0,cfg_tbl_len); + bk_flash_write(BK_PARTITION_NET_PARAM,0,tmpptr,cfg_tbl_len); + bk_flash_enable_security(FLASH_PROTECT_ALL); +#endif + hal_flash_unlock(); + + os_free(wrbuf); + + return 1; +} +/////////////////////for test purpose///////////////// +UINT32 test_get_whole_tbl(UINT8 *ptr) +{ + UINT32 len; + return search_info_tbl(ptr,&len); +} + +#endif // CFG_ENABLE_ATE_FEATURE \ No newline at end of file diff --git a/beken_os/beken378/func/power_save/manual_ps.c b/beken_os/beken378/func/power_save/manual_ps.c new file mode 100755 index 0000000..5089ac6 --- /dev/null +++ b/beken_os/beken378/func/power_save/manual_ps.c @@ -0,0 +1,288 @@ +#include "manual_ps.h" +#include "manual_ps_pub.h" +#include "gpio_pub.h" +#include "power_save_pub.h" +#include "sys_ctrl_pub.h" +#include "target_util_pub.h" +#include "start_type_pub.h" + + +#if PS_SUPPORT_MANUAL_SLEEP +/** @brief Request power save,and wakeup some time later + * @param sleep_time: Sleep time with milliseconds. + * if 0xffffffff not wakeup + */ +void bk_wlan_ps_wakeup_with_timer(UINT32 sleep_time) +{ + deep_sleep_wakeup_with_timer(sleep_time); +} + +/** @brief Request power save,and wakeup by uart if uart2_wk=1,nd wakeup by gpio from bitmap of gpio_index_map. + */ +void bk_wlan_ps_wakeup_with_peri( UINT8 uart2_wk, UINT32 gpio_index_map) +{ + power_save_wakeup_with_peri(uart2_wk, gpio_index_map); +} + +void power_save_wakeup_with_peri( UINT8 uart2_wk, UINT32 gpio_index_map) +{ + UINT32 reg, ret; + UINT32 param = 0; + UINT32 i; + UINT32 gpio_stat_cfg[32]; + + if(power_save_ps_mode_get() != PS_NO_PS_MODE) + { + os_printf("can't peri ps,ps in mode %d!\r\n", power_save_ps_mode_get()); + return ; + } + + for (i = 0; i < GPIONUM; i++) + { + gpio_stat_cfg[i] = REG_READ(0x00802800 + i * 4); + + if (gpio_index_map & (0x01UL << i)) + { + bk_gpio_config_input_pdwn(i); + BkGpioEnableIRQ(i, 0x2, NULL, NULL); + os_printf("set peri wkup gpio %d\r\n", i); + } + } + +#if(PS_XTAL26M_EN == 1) + reg = REG_READ(SCTRL_LOW_PWR_CLK); + reg &= ~(LPO_CLK_MUX_MASK); + reg |= (LPO_SRC_32K_DIV << LPO_CLK_MUX_POSI); + REG_WRITE(SCTRL_LOW_PWR_CLK, reg); +#endif + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + PS_DEBUG_DOWN_OUT; + PS_DEBUG_UP_OUT; + + if(uart2_wk == 1) + { + param |= ( UART2_ARM_WAKEUP_EN_BIT); + os_printf("set peri wkup uart2\r\n"); + } + + if(gpio_index_map) + param |= ( GPIO_ARM_WAKEUP_EN_BIT); + + os_printf("enter peri ps\r\n"); + sddev_control(ICU_DEV_NAME, CMD_ARM_WAKEUP, ¶m); + power_save_ps_mode_set(PS_MCU_PS_MODE); + param = (0xfffff & ~PWD_UART2_CLK_BIT); + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_NORMAL_SLEEP, ¶m); + delay(200000); + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_NORMAL_WAKEUP, 0); + + for (i = 0; i < GPIONUM; i++) + { + if (gpio_index_map & (0x01UL << i)) + { + bk_gpio_config_input_pdwn(i); + BkGpioDisableIRQ(i); + } + + REG_WRITE(0x00802800 + i * 4, gpio_stat_cfg[i]); + } + + power_save_ps_mode_set(PS_NO_PS_MODE); + GLOBAL_INT_RESTORE(); + os_printf("exit peri ps\r\n"); +} + + +void power_save_timer1_isr(UINT8 param) +{ + PS_DEBUG_PWM_OUT; +} + + +void power_save_timer1_init() +{ + UINT32 ret; + pwm_param_t param; + param.channel = PWM1; + param.cfg.bits.en = PWM_DISABLE; + param.cfg.bits.int_en = PWM_INT_EN; + param.cfg.bits.mode = PMODE_TIMER; + param.cfg.bits.clk = PWM_CLK_32K; + param.p_Int_Handler = power_save_timer1_isr; + param.duty_cycle = 0x10; + param.end_value = 3276; + ret = sddev_control(PWM_DEV_NAME, CMD_PWM_INIT_PARAM, ¶m); + ASSERT(PWM_SUCCESS == ret); +} + +void power_save_wakeup_with_timer(UINT32 sleep_time) +{ + UINT32 reg; + UINT32 param; + UINT32 wakeup_timer; + + if(power_save_ps_mode_get() != PS_NO_PS_MODE) + { + os_printf("can't pwm ps,ps in mode %d!\r\n", power_save_ps_mode_get()); + return ; + } + + if(sleep_time != 0xffffffff) + { + os_printf("sleep with pwm,%d ms\r\n", sleep_time); +#if 1 + reg = REG_READ(SCTRL_LOW_PWR_CLK); + reg &= ~(LPO_CLK_MUX_MASK); + reg |= (LPO_SRC_ROSC << LPO_CLK_MUX_POSI); + REG_WRITE(SCTRL_LOW_PWR_CLK, reg); +#endif + power_save_timer1_init(); + wakeup_timer = ((sleep_time * 102400) / 3125) ; + + if(wakeup_timer > 65535) //only 16 bit + wakeup_timer = 65535; + else if(wakeup_timer < 32) + wakeup_timer = 32; + + delay(5); + power_save_pwm1_enable(wakeup_timer); + } + else + { + os_printf("sleep forever\r\n"); + } + + os_printf("enter pwm ps\r\n"); + param = PWM_ARM_WAKEUP_EN_BIT; + sddev_control(ICU_DEV_NAME, CMD_ARM_WAKEUP, ¶m); + power_save_ps_mode_set(PS_STANDBY_PS_MODE); + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + PS_DEBUG_DOWN_OUT; + param = (0xfffff & (~PWD_PWM1_CLK_BIT) & (~PWD_UART2_CLK_BIT)); + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_RTOS_IDLE_SLEEP, ¶m); + PS_DEBUG_UP_OUT; + delay(5); + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_RTOS_IDLE_WAKEUP, 0); + phy_init_after_wakeup(); + GLOBAL_INT_RESTORE(); + power_save_ps_mode_set(PS_NO_PS_MODE); + power_save_pwm1_disable(); + os_printf("exit pwm ps\r\n"); +} + + +void power_save_wakeup_with_gpio(UINT32 gpio_index) +{ + UINT32 reg; + UINT32 param; + + if(power_save_ps_mode_get() != PS_NO_PS_MODE) + { + os_printf("can't gpio ps,ps in mode %d!\r\n", power_save_ps_mode_get()); + return ; + } + + os_printf("enter gpio ps\r\n"); + bk_gpio_config_input_pdwn(gpio_index); + BkGpioEnableIRQ(gpio_index, 0x2, NULL, NULL); + reg = REG_READ(SCTRL_LOW_PWR_CLK); + reg &= ~(LPO_CLK_MUX_MASK); + reg |= (LPO_SRC_ROSC << LPO_CLK_MUX_POSI); + REG_WRITE(SCTRL_LOW_PWR_CLK, reg); + param = (GPIO_ARM_WAKEUP_EN_BIT); + sddev_control(ICU_DEV_NAME, CMD_ARM_WAKEUP, ¶m); + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + PS_DEBUG_DOWN_OUT; + PS_DEBUG_UP_OUT; + param = (0xfffff & (~PWD_UART2_CLK_BIT)); + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_RTOS_IDLE_SLEEP, ¶m); + delay(5); + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_RTOS_IDLE_WAKEUP, 0); + phy_init_after_wakeup(); + GLOBAL_INT_RESTORE(); + os_printf("exit gpio ps\r\n"); +} + +#endif + +#if CFG_USE_DEEP_PS +void bk_enter_deep_sleep_mode ( PS_DEEP_CTRL_PARAM *deep_param ) +{ + UINT32 param; + UINT32 i; + ASSERT ( deep_param != NULL ); + + if ( ( deep_param->wake_up_way & PS_DEEP_WAKEUP_GPIO ) ) { + if ( deep_param->gpio_index_map ) { + bk_printf ( "---enter deep sleep :wake up with gpio 0~31 ps: 0x%x 0x%x \r\n", + deep_param->gpio_index_map, deep_param->gpio_edge_map ); + } + + if ( deep_param->gpio_last_index_map ) { + bk_printf ( "---enter deep sleep :wake up with gpio32~39 ps: 0x%x 0x%x \r\n", + deep_param->gpio_last_index_map, deep_param->gpio_last_edge_map ); + } + } + + if ( ( deep_param->wake_up_way & PS_DEEP_WAKEUP_RTC ) ) { + bk_printf ( "---enter deep sleep :wake up with " ); + + if ( deep_param->lpo_32k_src == LPO_SELECT_32K_XTAL ) { + bk_printf ( " xtal 32k " ); + } + else { + bk_printf ( " rosc " ); + } + + bk_printf ( " ps :%d s\r\n", deep_param->sleep_time ); + + if ( deep_param->sleep_time > 0x1ffff ) { + deep_param->sleep_time = 0x1ffff; + } + + deep_param->sleep_time = 32768 * deep_param->sleep_time; + } + + bk_misc_update_set_type(RESET_SOURCE_DEEPPS_GPIO); + + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + sddev_control ( SCTRL_DEV_NAME, CMD_SCTRL_RTOS_DEEP_SLEEP, deep_param ); + delay ( 5 ); + GLOBAL_INT_RESTORE(); + (void)i; + (void)param; +} + +#if 0 +void test_deep_ps() +{ + PS_DEEP_CTRL_PARAM deep_sleep_param; + + deep_sleep_param.wake_up_way = 0; + + deep_sleep_param.gpio_index_map = 0xc00; + deep_sleep_param.gpio_edge_map = 0x800; + deep_sleep_param.gpio_last_index_map = 0; + deep_sleep_param.gpio_last_edge_map = 0; + deep_sleep_param.sleep_time = 50; + deep_sleep_param.wake_up_way = 3; + deep_sleep_param.gpio_stay_lo_map = 0; + deep_sleep_param.gpio_stay_hi_map = 0; + + os_printf("---deep sleep test param : 0x%0X 0x%0X 0x%0X 0x%0X %d %d\r\n", + deep_sleep_param.gpio_index_map, + deep_sleep_param.gpio_edge_map, + deep_sleep_param.gpio_last_index_map, + deep_sleep_param.gpio_last_edge_map, + deep_sleep_param.sleep_time, + deep_sleep_param.wake_up_way); + + bk_enter_deep_sleep_mode(&deep_sleep_param); +} +#endif +#endif + diff --git a/beken_os/beken378/func/power_save/manual_ps.h b/beken_os/beken378/func/power_save/manual_ps.h new file mode 100755 index 0000000..fc1fb65 --- /dev/null +++ b/beken_os/beken378/func/power_save/manual_ps.h @@ -0,0 +1,11 @@ +#ifndef _MANUAL_PS_H_ +#define _MANUAL_PS_H_ + +#include "rtos_pub.h" +#include "uart_pub.h" +#include "arm_arch.h" + +#define PS_XTAL26M_EN 1 + +#endif + diff --git a/beken_os/beken378/func/power_save/mcu_ps.c b/beken_os/beken378/func/power_save/mcu_ps.c new file mode 100755 index 0000000..1076d66 --- /dev/null +++ b/beken_os/beken378/func/power_save/mcu_ps.c @@ -0,0 +1,560 @@ +#include "intc_pub.h" +#include "pwm_pub.h" +#include "rw_pub.h" +#include "rtos_pub.h" +#include "arm_arch.h" +#include "sys_ctrl_pub.h" +#include "mcu_ps.h" +#include "mcu_ps_pub.h" +#include "power_save_pub.h" +#include "ps_debug_pub.h" +#include "target_util_pub.h" +#include "icu_pub.h" +#include "fake_clock_pub.h" +#include "bk_timer_pub.h" +#include "drv_model_pub.h" + +#if CFG_USE_MCU_PS +static MCU_PS_INFO mcu_ps_info = +{ + .mcu_ps_on = 0, + .peri_busy_count = 0, + .mcu_prevent = 0, + +}; + +MCU_PS_TSF mcu_ps_tsf_save; +MCU_PS_MACHW_TM mcu_ps_machw_save; +int increase_tick = 0; + +extern UINT8 sctrl_if_mcu_can_sleep(void); + +#if (CHIP_U_MCU_WKUP_USE_TIMER && ((CFG_SOC_NAME == SOC_BK7231U) || (CFG_SOC_NAME == SOC_BK7231N))) +extern UINT32 ps_timer3_disable(void); +#endif + +#if (CFG_SUPPORT_ALIOS & CFG_USE_MCU_PS) +static UINT32 sleep_pwm_t, wkup_type; +#endif + +void mcu_ps_cal_increase_tick(UINT32 *lost_p); + +void peri_busy_count_add(void ) +{ + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + mcu_ps_info.peri_busy_count ++; + GLOBAL_INT_RESTORE(); +} + +void peri_busy_count_dec(void ) +{ + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + mcu_ps_info.peri_busy_count --; + GLOBAL_INT_RESTORE(); +} + +UINT32 peri_busy_count_get(void ) +{ + return mcu_ps_info.peri_busy_count; +} + +void mcu_prevent_set(UINT32 prevent ) +{ + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + mcu_ps_info.mcu_prevent |= prevent; + GLOBAL_INT_RESTORE(); +} + +void mcu_prevent_clear(UINT32 prevent ) +{ + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + mcu_ps_info.mcu_prevent &= ~ prevent; + GLOBAL_INT_RESTORE(); +} + +UINT32 mcu_prevent_get(void ) +{ + return mcu_ps_info.mcu_prevent; +} + +void mcu_ps_enable(void ) +{ + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + mcu_ps_info.mcu_ps_on = 1; + GLOBAL_INT_RESTORE(); +} + +void mcu_ps_disable(void ) +{ + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + mcu_ps_info.mcu_ps_on = 0; + GLOBAL_INT_RESTORE(); +} + +UINT32 mcu_power_save(UINT32 sleep_tick) +{ + UINT32 sleep_ms, sleep_pwm_t, param, uart_miss_us = 0, miss_ticks = 0; + UINT32 wkup_type, wastage = 0; + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + + if(mcu_ps_info.mcu_ps_on == 1 + && (peri_busy_count_get() == 0) + && (mcu_prevent_get() == 0) +#if CFG_USE_STA_PS +#if NX_POWERSAVE + && (txl_sleep_check()) +#endif +#endif + ) + { + do + { + sleep_ms = BK_TICKS_TO_MS(sleep_tick); + if(sleep_ms <= 2) + { + break; + } + sleep_ms = sleep_ms - FCLK_DURATION_MS;//early wkup + + sleep_pwm_t = (sleep_ms * 32); + if((int32)sleep_pwm_t <= 64) + { + break; + } +#if (CFG_SOC_NAME == SOC_BK7231) + if(sleep_pwm_t > 65535) + sleep_pwm_t = 65535; + else +#endif + if(sleep_pwm_t < 64) + sleep_pwm_t = 64; + + if(sctrl_if_mcu_can_sleep()) + { +#if (CHIP_U_MCU_WKUP_USE_TIMER && ((CFG_SOC_NAME == SOC_BK7231U) || (SOC_BK7231N == CFG_SOC_NAME))) + extern void ps_timer3_enable(UINT32 period); + ps_timer3_enable(sleep_pwm_t); +#else + extern void ps_pwm_suspend_tick(UINT32 period); + ps_pwm_suspend_tick(sleep_pwm_t); +#endif + } + +#if (CHIP_U_MCU_WKUP_USE_TIMER && ((CFG_SOC_NAME == SOC_BK7231U) || (SOC_BK7231N == CFG_SOC_NAME))) + param = (0xfffff & (~PWD_TIMER_26M_CLK_BIT) & (~PWD_TIMER_32K_CLK_BIT) & (~PWD_UART2_CLK_BIT) + & (~PWD_UART1_CLK_BIT) + ); +#else + param = (0xfffff & (~PWD_MCU_WAKE_PWM_BIT) & (~PWD_UART2_CLK_BIT) + & (~PWD_UART1_CLK_BIT) + ); +#endif + sctrl_mcu_sleep(param); +#if (CHIP_U_MCU_WKUP_USE_TIMER && ((CFG_SOC_NAME == SOC_BK7231U) || (SOC_BK7231N == CFG_SOC_NAME))) + ps_timer3_measure_prepare(); +#endif + wkup_type = sctrl_mcu_wakeup(); + +#if (CHIP_U_MCU_WKUP_USE_TIMER && ((CFG_SOC_NAME == SOC_BK7231U) || (SOC_BK7231N == CFG_SOC_NAME))) + if(1 == wkup_type) + { + wastage = 768; + + if(!(sctrl_if_rf_sleep() || power_save_if_rf_sleep() || ble_switch_mac_sleeped)) + { + ps_timer3_disable(); + mcu_ps_machw_cal(); + } + else + { + miss_ticks = (ps_timer3_disable() + (uart_miss_us + wastage) / 1000) / FCLK_DURATION_MS; + } + } + +#else + + { + if(1 == wkup_type) + { + wastage = 24; + } + + if(ps_pwm_int_status()) + { + miss_ticks = (sleep_pwm_t + (uart_miss_us >> 5) + wastage) / (FCLK_DURATION_MS * 32); + } + else + { + if(!(sctrl_if_rf_sleep() || power_save_if_rf_sleep())) + { + mcu_ps_machw_cal(); + } + else + { + miss_ticks = ((uart_miss_us >> 5) + wastage) / (FCLK_DURATION_MS * 32); + } + } + + miss_ticks += FCLK_DURATION_MS;//for early wkup + } + ps_pwm_resume_tick(); + +#endif + } + while(0); + } + else + { + } + + mcu_ps_cal_increase_tick(& miss_ticks); + GLOBAL_INT_RESTORE(); + ASSERT(miss_ticks >= 0); + return miss_ticks; +} + + +void mcu_ps_dump(void) +{ + os_printf("mcu:%x\r\n", mcu_ps_info.mcu_ps_on); +} + +void mcu_ps_init(void) +{ + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + + if(0 == mcu_ps_info.mcu_ps_on) + { + sctrl_mcu_init(); + mcu_ps_info.mcu_ps_on = 1; + mcu_ps_info.peri_busy_count = 0; + os_printf("%s %d\r\n", __FUNCTION__,mcu_ps_info.mcu_prevent); + } + + mcu_ps_machw_init(); + GLOBAL_INT_RESTORE(); + +} + +void mcu_ps_exit(void) +{ + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + + if(1 == mcu_ps_info.mcu_ps_on) + { + mcu_ps_info.mcu_ps_on = 0; + sctrl_mcu_exit(); + mcu_ps_info.peri_busy_count = 0; + os_printf("%s %d\r\n", __FUNCTION__,mcu_ps_info.mcu_prevent); + } + + mcu_ps_machw_reset(); + GLOBAL_INT_RESTORE(); +} + +static struct mac_addr bssid;; +static UINT64 last_tsf = 0; +extern UINT32 use_cal_net; +void mcu_ps_bcn_callback(uint8_t *data, int len, hal_wifi_link_info_t *info) +{ + struct bcn_frame *bcn = (struct bcn_frame *)data; + UINT64 tsf_start_peer = bcn->tsf; + + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + if(use_cal_net == 0) + { + last_tsf = tsf_start_peer; + GLOBAL_INT_RESTORE(); + return ; + } + + if(memcmp(&(bcn->h.addr3), &bssid, 6) || (last_tsf >= tsf_start_peer)) + { + mcu_ps_tsf_cal((UINT64)0); + memcpy(&bssid, &(bcn->h.addr3), 6); + } + else + { + mcu_ps_tsf_cal((UINT64)tsf_start_peer); + } + + last_tsf = tsf_start_peer; + GLOBAL_INT_RESTORE(); +} + +void mcu_ps_increase_clr(void) +{ + increase_tick = 0; +} + +void mcu_ps_cal_increase_tick(UINT32 *lost_p) +{ + int32 lost = * lost_p; + GLOBAL_INT_DECLARATION(); + + if((lost <= 0) || (0 == increase_tick)) + return; + + #if 0 + if((increase_tick < (-5000))|| (increase_tick > 5000)) + { + os_printf("--itick--:%x\r\n",increase_tick); + increase_tick = 0; + } + #endif + + GLOBAL_INT_DISABLE(); + lost += increase_tick; + if(lost < 0) + { + increase_tick = lost; + lost = 0; + } + else + { + increase_tick = 0; + } + + *lost_p = lost; + GLOBAL_INT_RESTORE(); +} + +extern void mcu_ps_cal_increase_tick(UINT32 *lost_p); +uint32_t mcu_ps_need_pstick(void) +{ + static uint32_t need_pass = 0; + uint32_t ret; + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + if(((1 == mcu_ps_info.mcu_ps_on) && power_save_if_ps_rf_dtim_enabled())) + { + ret = FCLK_DURATION_MS; + } + + if(((need_pass ++)%5) == 0) + { + UINT32 lost = FCLK_DURATION_MS; + mcu_ps_cal_increase_tick(&lost); + if(!lost) + { + //os_printf("p_t\r\n"); + } + ret = lost; + } + else + { + ret = FCLK_DURATION_MS; + } + GLOBAL_INT_RESTORE(); + + return ret; +} + + +UINT32 mcu_ps_tsf_cal(UINT64 tsf) +{ +#if (CFG_SUPPORT_ALIOS) + UINT64 fclk, tmp2, tmp4; +#else + UINT32 fclk, tmp2, tmp4; +#endif + UINT64 machw, tmp1, tmp3; + INT32 loss; + GLOBAL_INT_DECLARATION(); + + GLOBAL_INT_DISABLE(); + + if((0 == tsf) || (0 == mcu_ps_tsf_save.first_tsf)) + { + goto TFS_RESET; + } + + fclk = BK_TICKS_TO_MS(fclk_get_tick()); + + machw = tsf; + tmp3 = mcu_ps_tsf_save.first_tsf; + tmp4 = mcu_ps_tsf_save.first_tick; + + if(machw < mcu_ps_tsf_save.first_tsf) + { + goto TFS_RESET; + } + else + { + tmp1 = machw - mcu_ps_tsf_save.first_tsf; + } + + + tmp2 = (fclk - mcu_ps_tsf_save.first_tick); + + tmp1 /= 1000; + loss = (INT32)(tmp1 - (UINT64)tmp2); + + if(loss > 0) + { + if(loss > 5000) + { + os_printf("tsf cal_:%x \r\n", loss); +#if (CFG_SUPPORT_ALIOS) + os_printf("%x %x\r\n", (UINT32)(fclk >> 32), (UINT32)(fclk)); + os_printf("%x %x\r\n", (UINT32)(tmp2 >> 32), (UINT32)(tmp2)); + os_printf("%x %x\r\n", (UINT32)(tmp4 >> 32), (UINT32)(tmp4)); +#else + os_printf("%x %x %x\r\n", fclk, tmp2, tmp4); +#endif + os_printf("tsf:%x %x\r\n", (UINT32)(machw >> 32), (UINT32)machw); + os_printf("tmp3:%x %x\r\n", (UINT32)(tmp3 >> 32), (UINT32)tmp3); + os_printf("tmp1:%x %x\r\n", (UINT32)(tmp1 >> 32), (UINT32)tmp1); + if(loss > 50000) + { + goto TFS_RESET; + } + } + + fclk_update_tick(BK_MS_TO_TICKS(loss)); + mcu_ps_machw_init(); + + increase_tick = 0; + } + else + { + if(loss < 0) + { + if(loss < (-50000)) + { + goto TFS_RESET; + } + increase_tick = loss; + } + } + GLOBAL_INT_RESTORE(); + return 0 ; + +TFS_RESET: + mcu_ps_tsf_save.first_tsf = tsf; + + fclk = BK_TICKS_TO_MS(fclk_get_tick()); + mcu_ps_tsf_save.first_tick = fclk; + os_printf("mcu_ps_tsf_cal init\r\n"); + GLOBAL_INT_RESTORE(); + return 0 ; + +} + +UINT32 mcu_ps_machw_reset(void) +{ + mcu_ps_machw_save.fclk_tick = 0; + mcu_ps_machw_save.machw_tm = 0; + + return 0; +} + +UINT32 mcu_ps_machw_init(void) +{ +#if (CFG_SUPPORT_ALIOS) + UINT64 fclk; +#else + UINT32 fclk; +#endif + + fclk = BK_TICKS_TO_MS(fclk_get_tick()); + + mcu_ps_machw_save.fclk_tick = fclk; + mcu_ps_machw_save.machw_tm = hal_machw_time(); + + return 0; +} + +UINT32 mcu_ps_machw_cal(void) +{ +#if (CFG_SUPPORT_ALIOS) + UINT64 fclk, tmp2; +#else + UINT32 fclk, tmp2; +#endif + UINT32 machw, tmp1; + UINT32 lost; + GLOBAL_INT_DECLARATION(); + + if(!((1 == mcu_ps_info.mcu_ps_on) && power_save_if_ps_rf_dtim_enabled())) + { + return 0; + } + + if((0 == mcu_ps_machw_save.machw_tm) || (0xdead5555 == mcu_ps_machw_save.machw_tm) + || (0xdead5555 == hal_machw_time())) + { + mcu_ps_machw_init(); + return 0 ; + } + + GLOBAL_INT_DISABLE(); + + fclk = BK_TICKS_TO_MS(fclk_get_tick()); + + machw = hal_machw_time(); + + tmp1 = (machw - mcu_ps_machw_save.machw_tm); + + tmp2 = (fclk - mcu_ps_machw_save.fclk_tick); + + tmp1 /= 1000; + lost = (INT32)(tmp1 - tmp2); + + if((lost < (0xFFFFFFFF >> 1)) && (lost > 0)) + { + if(lost > 5000) + { + os_printf("hw cal_:%x %x %x\r\n", lost, machw, mcu_ps_machw_save.machw_tm); + if(lost > 50000) + { + goto HWCAL_RESET; + } + } + + //os_printf("mc:%d\r\n",lost); + mcu_ps_cal_increase_tick(&lost); + fclk_update_tick(BK_MS_TO_TICKS(lost)); + mcu_ps_machw_init(); + //os_printf("rmc:%d\r\n",lost); + } + else + { + } + GLOBAL_INT_RESTORE(); + return 0 ; + +HWCAL_RESET: + mcu_ps_machw_init(); + GLOBAL_INT_RESTORE(); + return 0 ; +} + +#else +void peri_busy_count_add(void ) +{ +} + +void peri_busy_count_dec(void ) +{ +} +void mcu_prevent_set(UINT32 prevent ) +{ +} + +void mcu_prevent_clear(UINT32 prevent ) +{ +} + +#endif + diff --git a/beken_os/beken378/func/power_save/mcu_ps.h b/beken_os/beken378/func/power_save/mcu_ps.h new file mode 100755 index 0000000..0173a54 --- /dev/null +++ b/beken_os/beken378/func/power_save/mcu_ps.h @@ -0,0 +1,34 @@ +#ifndef _MCU_PS_H_ +#define _MCU_PS_H_ + +//#define MCU_PS_DEBUG + +#ifdef MCU_PS_DEBUG +#define MCU_PS_PRT os_printf + +#else +#define MCU_PS_PRT os_null_printf + +#endif + +typedef struct +{ +#if (CFG_SUPPORT_ALIOS) + UINT64 first_tick; +#else + UINT32 first_tick; +#endif + UINT64 first_tsf; +} MCU_PS_TSF; +typedef struct +{ +#if (CFG_SUPPORT_ALIOS) + UINT64 fclk_tick; +#else + UINT32 fclk_tick; +#endif + UINT32 machw_tm; +} MCU_PS_MACHW_TM; + +#endif + diff --git a/beken_os/beken378/func/power_save/power_save.c b/beken_os/beken378/func/power_save/power_save.c new file mode 100755 index 0000000..28d908c --- /dev/null +++ b/beken_os/beken378/func/power_save/power_save.c @@ -0,0 +1,1665 @@ +#include "intc_pub.h" +#include "rtos_pub.h" + +#include "wdt_pub.h" +#include "gpio_pub.h" +#include "pwm_pub.h" +#include "mem_pub.h" +#include "icu_pub.h" + +#include "fake_clock_pub.h" +#include "power_save.h" +#include "target_util_pub.h" +#include "sys_ctrl_pub.h" +#include "drv_model_pub.h" +#include "arm_arch.h" +#include "rwnx_config.h" +#include "ps.h" +#include "rwnx.h" +#include "uart_pub.h" +#include "mcu_ps_pub.h" +#include "rtos_error.h" +#include "role_launch.h" +#include "ble_pub.h" +#include "start_type_pub.h" + +volatile static PS_MODE_STATUS bk_ps_mode = PS_NO_PS_MODE; +UINT32 last_rw_time = 0; + +#if CFG_USE_STA_PS +static STA_PS_INFO bk_ps_info = +{ + .tm_status = PS_TM_CK_TIMEOUT, + .ps_dtim_period = 1, + .ps_dtim_multi = 1, + .sleep_ms = 300, + .liston_int = 1, + .waited_beacon = STA_GET_INIT, + .ps_bcn_ab_status = PS_BCN_STATUS_INIT, + .sleep_first = 1, + .ps_can_sleep = 0, + .ps_bcn_cal_status = PS_BCN_NO_CAL, + .ps_real_sleep = 0, + .pwm_less_time = 0, +}; + +#if (CFG_SOC_NAME == SOC_BK7231) +static UINT16 r_wakeup_time = 50; +#elif (CFG_SOC_NAME == SOC_BK7231N) +static UINT16 r_wakeup_time = 90; +#else +static UINT16 r_wakeup_time = 66; +#endif + +#if PS_DTIM_WITH_NORMAL +volatile static UINT8 ps_dtim_normal_enable = 0; +#endif +static UINT32 int_enable_reg_save = 0; +static UINT8 ps_lock = 1; +static PS_FORBID_STATUS bk_forbid_code = 0; +static UINT16 bk_forbid_count = 0; +static UINT32 ps_dis_flag = 0; +static UINT16 beacon_len = 0; +#if PS_DTIM_PERI_WAKE_DELAY +static UINT32 ps_delay_wait_time = 0; +#endif +static UINT32 ps_delay_rfup_time = 0; +UINT32 ps_next_data_ck_time = 0; +static UINT8 pwm_use_for_ps = 0; +#if CFG_SUPPORT_ALIOS +static beken_timer_t ps_td_ck_timer = {0}; +static beken_timer_t ps_keep_timer = {0}; +static beken_timer_t ps_wait_timer = {0}; +#else +static beken2_timer_t ps_td_ck_timer = {0}; +static beken2_timer_t ps_keep_timer = {0}; +static beken2_timer_t ps_wait_timer = {0}; +#endif +static UINT32 ps_td_ck_timer_status = 0; +static UINT32 ps_keep_timer_status = 0; +static UINT32 ps_wait_timer_status = 0; + +static UINT32 ps_td_last_tick = 0; +static UINT32 ps_keep_timer_period = 0; +static UINT32 ps_reseted_moniter_flag = 0; +static UINT32 ps_bcn_loss_max_count = 0; + +static UINT32 ps_keep_timer_flag = 1; + +void power_save_td_ck_timer_handler(void *data); +void power_save_keep_timer_handler(void *data); +void power_save_td_timer_stop(void); +extern void sctrl_sta_rf_sleep(void); +extern void sctrl_sta_rf_wakeup(void); + +int net_if_is_up(void) +{ + return (mhdr_get_station_status() == RW_EVT_STA_GOT_IP); +} + +void power_save_wakeup_isr(void) +{ +} + +void power_save_dtim_wake(UINT32 status ) +{ + if(bk_ps_mode == PS_DTIM_PS_MODE && + bk_ps_info.ps_arm_wakeup_way == PS_ARM_WAKEUP_NONE) + { + UINT32 reg; + + if(status ) + { + if((status) & MAC_ARM_WAKEUP_EN_BIT) + { + bk_ps_info.ps_arm_wakeup_way = PS_ARM_WAKEUP_UPING; + reg = REG_READ(ICU_INTERRUPT_ENABLE); + reg &= ~(CO_BIT(FIQ_MAC_WAKEUP)); + REG_WRITE(ICU_INTERRUPT_ENABLE, reg); + PS_DEBUG_UP_TRIGER; +#if 1 + + if( bk_ps_info.pwm_less_time != 0) + { + if(bk_ps_info.pwm_clkmux == PWM_MUX_PCLK) + { + #if (CFG_SOC_NAME == SOC_BK7231) + ps_pwm_reconfig(bk_ps_info.pwm_less_time, bk_ps_info.pwm_clkmux); + #endif + bk_ps_info.tm_status = TM_LOW_POWER; + pwm_use_for_ps = 1; + } + else if(bk_ps_info.pwm_clkmux == PWM_MUX_LPO) + { + UINT32 cur_tick = fclk_get_tick(); + ps_delay_rfup_time = cur_tick + bk_ps_info.pwm_less_time / 2; + + if(ps_delay_rfup_time < cur_tick) + { + power_save_ieee_dtim_wakeup(); + ps_delay_rfup_time = 0; + } + } + else + { + bk_ps_info.ps_arm_wakeup_way = PS_ARM_WAKEUP_RW; + power_save_ieee_dtim_wakeup(); + } + + bk_ps_info.pwm_less_time = 0; + } + else + { + bk_ps_info.ps_arm_wakeup_way = PS_ARM_WAKEUP_RW; + power_save_ieee_dtim_wakeup(); + } + +#else + power_save_ieee_dtim_wakeup(); +#endif + } + } + } +} + +void power_save_pwm_isr(UINT8 param) +{ + if(bk_ps_mode == PS_DTIM_PS_MODE) + { + if (bk_ps_info.tm_status == TM_LOW_POWER) + { + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + bk_ps_info.ps_arm_wakeup_way = PS_ARM_WAKEUP_RW; + power_save_ieee_dtim_wakeup(); + #if (CFG_SOC_NAME == SOC_BK7231) + ps_pwm_resume_tick(); + #endif + pwm_use_for_ps = 0; + bk_ps_info.tm_status = PS_TM_CK_TIMEOUT; + GLOBAL_INT_RESTORE(); + } + } +} + +UINT32 power_save_use_pwm_isr(void) +{ + return (pwm_use_for_ps == 1); +} + +void power_save_td_check(void) +{ + /*receive UC or manual wakeup send*/ + if((PS_DPSM_STATE_GET(PAUSE) + || PS_DPSM_STATE_GET(PAUSING) || PS_DPSM_STATE_GET(RESUMING)) + || bk_ps_info.ps_arm_wakeup_way == PS_ARM_WAKEUP_USER) + { + ps_run_td_timer(0); + } +} + +/*This function will run in mac go to ps fiq, +only an actual emergency can put here, +can't operate wifi tx,rx,modem,rf here*/ +void power_save_gops_wait_idle_int_cb(void) +{ + //rf_ps_wakeup_isr_idle_int_cb(); +} + +extern uint8_t ble_switch_mac_sleeped; +bool power_save_sleep(void) +{ + UINT32 ret = false; + UINT32 reg; + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + + if(1 == bk_ps_info.ps_real_sleep || ble_switch_mac_sleeped) + { + GLOBAL_INT_RESTORE(); + return ret; + } + + if(! (PS_STA_DTIM_CAN_SLEEP)) + { + GLOBAL_INT_RESTORE(); + return ret; + } + + if(rwnxl_get_status_in_doze()) + { + GLOBAL_INT_RESTORE(); + return ret; + } + + nxmac_enable_idle_interrupt_setf(1); + PS_DEBUG_CK_TRIGER; + + if(REG_READ((ICU_BASE + 19 * 4)) + & (CO_BIT(FIQ_MAC_TX_RX_MISC) + | CO_BIT(FIQ_MAC_TX_RX_TIMER) + | CO_BIT(FIQ_MAC_RX_TRIGGER) + | CO_BIT(FIQ_MAC_TX_TRIGGER) + | CO_BIT(FIQ_MAC_PROT_TRIGGER) + )) + { + GLOBAL_INT_RESTORE(); + return ret; + } + + reg = REG_READ(ICU_INTERRUPT_ENABLE); + int_enable_reg_save = reg; + reg &= ~(CO_BIT(FIQ_MAC_TX_RX_MISC) + | CO_BIT(FIQ_MAC_TX_RX_TIMER) + | CO_BIT(FIQ_MAC_RX_TRIGGER) + | CO_BIT(FIQ_MAC_TX_TRIGGER) + | CO_BIT(FIQ_MAC_GENERAL) + | CO_BIT(FIQ_MAC_PROT_TRIGGER) + | CO_BIT(FIQ_DPLL_UNLOCK)); + REG_WRITE(ICU_INTERRUPT_ENABLE, reg); +#if NX_POWERSAVE + last_rw_time = nxmac_monotonic_counter_2_lo_get(); + + if ( last_rw_time == 0xdead5555 ) { + os_null_printf ( "TIME DEAD\r\n" ); + } + + ret = rwnxl_sleep(power_save_gops_wait_idle_int_cb, power_save_mac_idle_callback); + + if(false == ret) + { + PS_PRT("can't ps\r\n"); + REG_WRITE(ICU_INTERRUPT_ENABLE, int_enable_reg_save); + GLOBAL_INT_RESTORE(); + return ret; + } + +#endif + + if(ps_lock) + ps_lock --; + else + { + PS_WPRT("error ps\r\n"); + GLOBAL_INT_RESTORE(); + return ret; + } + + PS_WPRT("go ps\r\n"); +#if CFG_USE_STA_PS + power_save_sleep_status_set(); + sctrl_sta_rf_sleep(); + + reg = REG_READ(ICU_INTERRUPT_ENABLE); + reg |= (CO_BIT(FIQ_MAC_WAKEUP)); + REG_WRITE(ICU_INTERRUPT_ENABLE, reg); +#endif + if(1 == ps_keep_timer_status) + { + bmsg_ps_sender(PS_BMSG_IOCTL_RF_KP_STOP); + } + + GLOBAL_INT_RESTORE(); + return true; +} + +/*time = BI*1024*LIST*0.016*/ +void power_save_wkup_time_cal(UINT8 sleep_int) +{ + UINT32 tmp_r_wkup = r_wakeup_time + 12; + + nxmac_radio_wake_up_time_setf(tmp_r_wkup); +} + +int power_save_get_wkup_less_time() +{ + if(bk_ps_info.liston_mode == PS_LISTEN_MODE_DTIM) + { + return bk_ps_info.ps_dtim_period * bk_ps_info.ps_dtim_multi \ + *bk_ps_info.ps_beacon_int * 15; + } + else + { + return bk_ps_info.liston_int * bk_ps_info.ps_beacon_int * 15; + } +} + +void power_save_mac_idle_callback(void) +{ + if(power_save_if_sleep_first()) + { + power_save_wkup_time_cal(1); + nxmac_tsf_mgt_disable_setf(0); + nxmac_listen_interval_setf(1); + + nxmac_atim_w_setf(512); + nxmac_wake_up_sw_setf(0); + /*first clear beacon interval,delay,then set beacon interval,to fix rw sleep wakeup time*/ + nxmac_beacon_int_setf(0); + delay(1); + nxmac_beacon_int_setf(bk_ps_info.ps_beacon_int); + os_null_printf(" sleep_first %d\r\n", bk_ps_info.liston_mode); + os_printf(" dtim period:%d multi:%d\r\n", bk_ps_info.ps_dtim_period, bk_ps_info.ps_dtim_multi); + bk_ps_info.sleep_first = 0; + } + else + { + if(bk_ps_info.liston_mode == PS_LISTEN_MODE_DTIM) + { + { + power_save_wkup_time_cal(1); + nxmac_listen_interval_setf(1); + } + } + else + { + } + + } + + bk_ps_info.sleep_count ++; +} + + +void power_save_sleep_status_set(void) +{ + bk_ps_info.ps_real_sleep = 1; + bk_ps_info.ps_arm_wakeup_way = PS_ARM_WAKEUP_NONE; +} + +UINT8 power_save_set_all_vif_prevent_sleep(UINT32 prevent_bit ) +{ + VIF_INF_PTR vif_entry = NULL; + UINT32 i; + + for(i = 0; i < NX_VIRT_DEV_MAX; i++) + { + vif_entry = &vif_info_tab[i]; + + if(vif_entry->active && vif_entry->type == VIF_STA) + { + vif_entry->prevent_sleep |= prevent_bit; + } + } + + return 0; +} + +/*This function will run in mac wakeup fiq, +only an actual emergency can put here, +can't operate wifi tx,rx,modem,rf here*/ +void power_save_wkup_wait_idle_int_cb(void) +{ + //rf_ps_wakeup_isr_idle_int_cb(); +} + +UINT8 power_save_clr_all_vif_prevent_sleep(UINT32 prevent_bit ) +{ + VIF_INF_PTR vif_entry = NULL; + UINT32 i; + + for(i = 0; i < NX_VIRT_DEV_MAX; i++) + { + vif_entry = &vif_info_tab[i]; + + if(vif_entry->active && vif_entry->type == VIF_STA) + { + vif_entry->prevent_sleep &= ~ (prevent_bit); + } + } + + return 0; +} +void power_save_wakeup(void) +{ + UINT32 reg; + PS_DEBUG_UP_TRIGER; + bk_ps_info.waited_beacon = STA_GET_FALSE; + + if(bk_ps_info.ps_arm_wakeup_way == PS_ARM_WAKEUP_RW) + { + power_save_set_all_vif_prevent_sleep((UINT32)(PS_VIF_WAITING_BCN)); + } + +#if CFG_USE_STA_PS + sctrl_sta_rf_wakeup(); +#if CFG_USE_BLE_PS + rf_wifi_used_set(); +#endif + reg = REG_READ(ICU_ARM_WAKEUP_EN); + reg &= ~(MAC_ARM_WAKEUP_EN_BIT); + REG_WRITE(ICU_ARM_WAKEUP_EN, reg); +#endif + bk_ps_info.tm_status = PS_TM_CK_TIMEOUT; +#if NX_POWERSAVE + rwnxl_wakeup(power_save_wkup_wait_idle_int_cb); +#endif + + reg = REG_READ(ICU_INTERRUPT_ENABLE); + reg |= (CO_BIT(FIQ_MAC_TX_RX_MISC) + | CO_BIT(FIQ_MAC_TX_RX_TIMER) + | CO_BIT(FIQ_MAC_RX_TRIGGER) + | CO_BIT(FIQ_MAC_TX_TRIGGER) + | CO_BIT(FIQ_MAC_GENERAL) + | CO_BIT(FIQ_MAC_PROT_TRIGGER) + | CO_BIT(FIQ_DPLL_UNLOCK)); + reg &= ~(CO_BIT(FIQ_MAC_WAKEUP)); + REG_WRITE(ICU_INTERRUPT_ENABLE, reg); + + PS_DEBUG_UP_TRIGER; + + ASSERT(!ps_lock); + ps_lock ++; +} + +void power_save_dtim_exit_check() +{ + if(power_save_wkup_event_get() & NEED_DISABLE_BIT) + { + power_save_dtim_rf_ps_disable_send_msg(); + power_save_wkup_event_clear(NEED_DISABLE_BIT); + } +} + +void power_save_ieee_dtim_wakeup(void) +{ + if((bk_ps_info.ps_arm_wakeup_way > PS_ARM_WAKEUP_NONE + && bk_ps_info.ps_arm_wakeup_way <= PS_ARM_WAKEUP_USER) + && bk_ps_info.ps_real_sleep) + { + PS_DEBUG_UP_TRIGER; + power_save_wakeup(); + + if(!bk_ps_info.ps_real_sleep) + os_printf("ps r s not 0\r\n"); + + bk_ps_info.ps_real_sleep = 0; + bk_ps_info.ps_can_sleep = 1; +#if PS_DTIM_PERI_WAKE_DELAY + + if(bk_ps_info.ps_arm_wakeup_way == PS_DTIM_ARM_WAKEUP_PERI) + { + os_printf("w:peri wake\r\n"); + + if(bk_ps_info.PsPeriWakeupWaitTimeMs != 0) + { + ps_delay_wait_time = fclk_get_tick() + bk_ps_info.PsPeriWakeupWaitTimeMs / 2; + os_printf("uart wake delay %d %d\r\n", bk_ps_info.PsPeriWakeupWaitTimeMs, ps_delay_wait_time); + } + } +#endif +#if CFG_USE_MCU_PS + //tick check + mcu_ps_machw_cal(); +#endif + if(!power_save_if_sleep_first() && ps_keep_timer_period) + { + ps_keep_timer_flag = 1; + bmsg_ps_sender(PS_BMSG_IOCTL_RF_KP_SET); + } + + if (!ble_switch_mac_sleeped) + power_save_rf_ps_wkup_semlist_set(); + + ke_evt_set(KE_EVT_KE_TIMER_BIT); + ke_evt_set(KE_EVT_MM_TIMER_BIT); + power_save_dtim_exit_check(); + } +} + + +bool power_save_rf_sleep_check( void ) +{ +#if (NX_POWERSAVE) +#if CFG_USE_STA_PS +#if PS_WAKEUP_MOTHOD_RW + if(PS_STA_DTIM_SWITCH) + { + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + + if((ps_delay_rfup_time != 0) && ((INT32)(ps_delay_rfup_time - fclk_get_tick()) <= 0)) + { + if(bk_ps_info.ps_arm_wakeup_way == PS_ARM_WAKEUP_UPING) + { + bk_ps_info.ps_arm_wakeup_way = PS_ARM_WAKEUP_RW; + power_save_ieee_dtim_wakeup(); + } + + ps_delay_rfup_time = 0; + } + + if(ps_td_last_tick && + (power_save_beacon_state_get() == STA_GET_TRUE \ + || power_save_wkup_way_get() == PS_ARM_WAKEUP_USER)) + { + { + power_save_td_check(); + ps_td_last_tick = 0; + } + } + + GLOBAL_INT_RESTORE(); + } + + if(PS_STA_DTIM_CAN_SLEEP) + { + GLOBAL_INT_DECLARATION(); + + if (ke_evt_get() != 0) + { + return false; + } + + if(!bmsg_is_empty()) + { + return false; + } + + GLOBAL_INT_DISABLE(); + ps_sleep_check(); + GLOBAL_INT_RESTORE(); + } +#endif +#endif +#endif //(NX_POWERSAVE) + + return 0; +} + +void power_save_me_ps_first_set_state(UINT8 state) +{ + int param_len; + VIF_INF_PTR vif_entry; + struct ke_msg *kmsg_dst; + struct me_set_ps_disable_req *me_ps_ptr; + os_null_printf("%s:%d\r\n", __FUNCTION__, __LINE__); + param_len = sizeof(struct me_set_ps_disable_req); + + vif_entry = (VIF_INF_PTR)rwm_mgmt_is_vif_first_used(); + while(vif_entry) + { + if(vif_entry->type == VIF_STA && vif_entry->active) + { + kmsg_dst = (struct ke_msg *)os_malloc(sizeof(struct ke_msg) + + param_len); + + if(0 == kmsg_dst) + { + os_printf("%s:%d malloc fail\r\n", __FUNCTION__, __LINE__); + return ; + } + +#if CFG_ROLE_LAUNCH + rl_pre_sta_set_status(RL_STATUS_STA_PS_SETTING); +#endif + os_memset(kmsg_dst, 0, (sizeof(struct ke_msg) + param_len)); + kmsg_dst->id = ME_PS_REQ; + kmsg_dst->dest_id = TASK_ME; + kmsg_dst->src_id = TASK_NONE; + kmsg_dst->param_len = param_len; + me_ps_ptr = (struct me_set_ps_disable_req *)kmsg_dst->param; + me_ps_ptr->ps_disable = state; + me_ps_ptr->vif_idx = vif_entry->index; + + ke_msg_send(ke_msg2param(kmsg_dst)); + } + vif_entry = (VIF_INF_PTR)rwm_mgmt_next(vif_entry); + } + +} + + +void power_save_me_ps_set_state(UINT8 state , UINT8 vif_idx) +{ + os_null_printf("%s:%d\r\n", __FUNCTION__, __LINE__); + { + struct me_set_ps_disable_req *me_ps_ptr = KE_MSG_ALLOC(ME_SET_PS_DISABLE_REQ, TASK_ME, TASK_NONE, + me_set_ps_disable_req); + me_ps_ptr->ps_disable = state; + me_ps_ptr->vif_idx = vif_idx; + ke_msg_send(me_ps_ptr); + } +} + +void power_save_sm_set_bcmc(UINT8 bcmc , UINT8 vif_idx) +{ + struct mm_set_ps_options_req *req; + // Get a pointer to the kernel message + req = KE_MSG_ALLOC(MM_SET_PS_OPTIONS_REQ, TASK_MM, TASK_NONE, mm_set_ps_options_req); + // Fill the message parameters + req->dont_listen_bc_mc = bcmc; + req->listen_interval = 0; + req->vif_index = vif_idx; + os_printf("%s %d %d %d\r\n", __FUNCTION__, req->dont_listen_bc_mc, + req->listen_interval, req->vif_index); + // Set the PS options for this VIF + ke_msg_send(req); +} + +UINT8 power_save_sm_set_all_bcmc(UINT8 bcmc ) +{ + VIF_INF_PTR vif_entry = NULL; + UINT32 i; + + for(i = 0; i < NX_VIRT_DEV_MAX; i++) + { + vif_entry = &vif_info_tab[i]; + + if(vif_entry->active && vif_entry->type != VIF_STA) + { + os_null_printf("%s:%d %d is %d not STA!!!!\r\n", __FUNCTION__, __LINE__, i, vif_entry->type); + return 0; + } + } + + for(i = 0; i < NX_VIRT_DEV_MAX; i++) + { + vif_entry = &vif_info_tab[i]; + + if(vif_entry->active && vif_entry->type == VIF_STA) + { + power_save_sm_set_bcmc(bcmc, i); + } + } + + return 0; +} + + + +UINT8 power_save_me_ps_set_all_state(UINT8 state ) +{ + VIF_INF_PTR vif_entry = NULL; + UINT32 i; + + if(state == false) + { + for(i = 0; i < NX_VIRT_DEV_MAX; i++) + { + vif_entry = &vif_info_tab[i]; + + if(vif_entry->active && vif_entry->type != VIF_STA) + { + os_null_printf("%s:%d %d is %d not STA!!!!\r\n", __FUNCTION__, __LINE__, i, vif_entry->type); + return 0; + } + } + } + + for(i = 0; i < NX_VIRT_DEV_MAX; i++) + { + vif_entry = &vif_info_tab[i]; + if(vif_entry->active && vif_entry->type == VIF_STA) + { +#if CFG_ROLE_LAUNCH + rl_pre_sta_set_status(RL_STATUS_STA_PS_SETTING); +#endif + power_save_me_ps_set_state(state, i); + } + } + + return 0; +} + +void power_save_timer_init(void) +{ + UINT32 err; + +#if CFG_SUPPORT_ALIOS + if(rtos_is_timer_init(&ps_td_ck_timer)) +#else + if(rtos_is_oneshot_timer_init(&ps_td_ck_timer)) +#endif + { + power_save_td_timer_stop(); +#if CFG_SUPPORT_ALIOS + err = rtos_deinit_timer(&ps_td_ck_timer); +#else + err = rtos_deinit_oneshot_timer(&ps_td_ck_timer); +#endif + ASSERT(kNoErr == err); + } + + if(bk_ps_info.PsDataWakeupWaitTimeMs > 0) + { +#if CFG_SUPPORT_ALIOS + err = rtos_init_timer(&ps_td_ck_timer, +#else + err = rtos_init_oneshot_timer(&ps_td_ck_timer, +#endif + bk_ps_info.PsDataWakeupWaitTimeMs, +#if CFG_SUPPORT_ALIOS + (timer_handler_t)power_save_td_ck_timer_handler, +#else + (timer_2handler_t)power_save_td_ck_timer_handler, + NULL, +#endif + NULL); + ASSERT(kNoErr == err); + } +} + +void power_save_keep_timer_init(void) +{ + UINT32 err; + +#if CFG_SUPPORT_ALIOS + if(rtos_is_timer_init(&ps_keep_timer)) +#else + if(rtos_is_oneshot_timer_init(&ps_keep_timer)) +#endif + { + power_save_keep_timer_stop(); +#if CFG_SUPPORT_ALIOS + err = rtos_deinit_timer(&ps_keep_timer); +#else + err = rtos_deinit_oneshot_timer(&ps_keep_timer); +#endif + ASSERT(kNoErr == err); + } + os_null_printf("ps_keep_timer init\r\n"); + + if(ps_keep_timer_period > 0) + { +#if CFG_SUPPORT_ALIOS + err = rtos_init_timer(&ps_keep_timer, +#else + err = rtos_init_oneshot_timer(&ps_keep_timer, +#endif + ps_keep_timer_period, +#if CFG_SUPPORT_ALIOS + (timer_handler_t)power_save_keep_timer_handler, +#else + (timer_2handler_t)power_save_keep_timer_handler, + NULL, +#endif + NULL); + ASSERT(kNoErr == err); + } +} + + +void power_save_dtim_ps_init(void) +{ + PS_DEBUG_UP_OUT; + PS_DEBUG_RX_OUT; + PS_DEBUG_CK_OUT; + PS_DEBUG_BCN_OUT; + PS_DEBUG_DOWN_OUT; + PS_DEBUG_PWM_OUT; + + bk_ps_info.sleep_count = 0; + bk_ps_info.sleep_first = 1; + + os_null_printf("power_save_dtim_ps_init\r\n"); + bk_ps_info.ps_can_sleep = 1; + ps_td_last_tick = 0; +} + +void power_save_dtim_ps_exit(void) +{ + bk_ps_info.ps_can_sleep = 0; + bk_ps_info.waited_beacon = STA_GET_INIT; + bk_ps_info.PsDataWakeupWaitTimeMs = 0 ; + bk_ps_info.PsPeriWakeupWaitTimeMs = 0 ; + nxmac_beacon_int_setf(0); + delay(1); + bk_ps_info.ps_real_sleep = 0; + bk_ps_info.sleep_count = 0; + bk_ps_info.sleep_first = 1; +} + +int power_save_dtim_enable_handler(void) +{ + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + + if((bk_ps_mode == PS_DTIM_PS_OPENING) && (mhdr_get_station_status() >= RW_EVT_STA_CONNECTED)) + { + os_printf("enter %d ps,p:%d m:%d int:%d l:%d!\r\n", bk_ps_info.liston_mode, + bk_ps_info.ps_dtim_period, bk_ps_info.ps_dtim_multi, + bk_ps_info.ps_beacon_int, bk_ps_info.liston_int); + power_save_set_uart_linger_time(0); + power_save_dtim_ps_init(); + bk_ps_info.if_wait_bcn = 1; + bk_ps_mode = PS_DTIM_PS_MODE; + + extern void power_save_wait_timer_init(void); + power_save_wait_timer_init(); + } + else + { + os_printf("%s:%d %d %d--\r\n", __FUNCTION__, __LINE__,bk_ps_mode,mhdr_get_station_status()); + } + +#if CFG_ROLE_LAUNCH + rl_pre_sta_set_status(RL_STATUS_STA_LAUNCHED); +#endif + + GLOBAL_INT_RESTORE(); + + return 0; +} + + +int power_save_dtim_enable(void) +{ + if( ! net_if_is_up()) + { + os_printf("net %d not ip up\r\n",mhdr_get_station_status()); + return -1; + } + + if(g_wlan_general_param->role != CONFIG_ROLE_STA) + { + os_printf("can't dtim,role %d not only sta!\r\n", g_wlan_general_param->role); + return -1; + } + + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + + if(bk_ps_mode != PS_NO_PS_MODE) + { + os_printf("can't dtim ps,ps in mode %d!\r\n", bk_ps_mode); + GLOBAL_INT_RESTORE(); + return -1; + } + + { + os_printf("first enable sleep \r\n"); + power_save_me_ps_first_set_state(PS_MODE_ON_DYN); + } + + GLOBAL_INT_RESTORE(); + return 0; +} + +int power_save_dtim_disable_handler(void) +{ + UINT32 wdt_val = 5; + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + +#if CFG_USE_BLE_PS + rf_wifi_used_clr(); +#endif + if(bk_ps_mode == PS_DTIM_PS_CLOSING) + { + bk_ps_mode = PS_NO_PS_MODE; + + if(bk_ps_info.ps_real_sleep == 1) + { + os_printf("%s:%d err\r\n", __FUNCTION__, __LINE__); + } + + rwnxl_set_nxmac_timer_value(); + power_save_dtim_ps_exit(); + + if(power_save_wkup_event_get() & NEED_REBOOT_BIT) + { + sddev_control(WDT_DEV_NAME, WCMD_POWER_DOWN, NULL); + os_printf("pswdt reboot\r\n"); + bk_misc_update_set_type(RESET_SOURCE_REBOOT); + sddev_control(WDT_DEV_NAME, WCMD_SET_PERIOD, &wdt_val); + sddev_control(WDT_DEV_NAME, WCMD_POWER_UP, NULL); + while(1); + + } + + if(power_save_wkup_event_get() & NEED_START_EZ_BIT) + { + hal_machw_enter_ez_of_sta(); + power_save_wkup_event_clear(NEED_START_EZ_BIT); + } + + if(power_save_wkup_event_get() & NEED_STOP_EZ_BIT) + { + hal_machw_exit_ez_of_sta(); + power_save_wkup_event_clear(NEED_STOP_EZ_BIT); + } + + } + else + { + os_printf("%s:%d %d %d\r\n", __FUNCTION__, __LINE__,bk_ps_mode,mhdr_get_station_status()); + } + +#if CFG_ROLE_LAUNCH + rl_pre_sta_set_status(RL_STATUS_STA_LAUNCHED); +#endif + + GLOBAL_INT_RESTORE(); + os_printf("exit dtim ps!\r\n"); + return 0; +} + +int power_save_dtim_disable(void) +{ + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + + if(bk_ps_mode != PS_NO_PS_MODE) + { + GLOBAL_INT_RESTORE(); + power_save_me_ps_set_all_state(true); + os_printf("start exit!\r\n"); + return 0; + } + else + { + GLOBAL_INT_RESTORE(); + } + + return 0; +} + + +int power_save_dtim_rf_ps_disable_send_msg(void) +{ + if(bk_ps_mode != PS_NO_PS_MODE) + { + bmsg_ps_sender(PS_BMSG_IOCTL_RF_DISANABLE); + } + + return 0; +} + +void power_save_rf_dtim_manual_do_wakeup(void) +{ + UINT32 reg; + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + + if (ble_switch_mac_sleeped) + { + GLOBAL_INT_RESTORE(); + return; + } + + PS_DEBUG_UP_TRIGER; + + if((bk_ps_mode == PS_DTIM_PS_MODE) + && (bk_ps_info.ps_arm_wakeup_way == PS_ARM_WAKEUP_NONE + || bk_ps_info.ps_arm_wakeup_way == PS_ARM_WAKEUP_UPING) + && (bk_ps_info.ps_real_sleep == 1)) + { + delay(1); + PS_DEBUG_UP_TRIGER; + + if(bk_ps_info.ps_arm_wakeup_way == PS_ARM_WAKEUP_UPING) + { + bk_ps_info.ps_arm_wakeup_way = PS_ARM_WAKEUP_RW; + } + else + { + bk_ps_info.ps_arm_wakeup_way = PS_ARM_WAKEUP_USER; + } + + reg = REG_READ(ICU_INTERRUPT_ENABLE); + reg &= ~(CO_BIT(FIQ_MAC_WAKEUP)); + REG_WRITE(ICU_INTERRUPT_ENABLE, reg); + power_save_ieee_dtim_wakeup(); + PS_PRT("m_r_u\r\n"); + } + + GLOBAL_INT_RESTORE(); +} + +/*@brief set the time how long wait after the last tx/rx. +* @param data_wakeup_time(ms): if 0 mean wait maximum time, +* else wait the set time. +*/ +void power_save_set_linger_time(UINT32 data_wakeup_time) +{ + if(data_wakeup_time >= 0 && data_wakeup_time < 100) + { + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + bk_ps_info.PsDataWakeupWaitTimeMs = data_wakeup_time ; + power_save_timer_init(); + GLOBAL_INT_RESTORE(); + } + return; +} + +void power_save_set_keep_timer_time(UINT32 time) +{ + if(time >= 0 && time < 100) + { + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + ps_keep_timer_period = time ; + power_save_keep_timer_init(); + GLOBAL_INT_RESTORE(); + } + return; +} + +void power_save_set_uart_linger_time(UINT32 uart_wakeup_time) +{ + bk_ps_info.PsPeriWakeupWaitTimeMs = uart_wakeup_time; + return; +} + +void power_save_set_dtim_period(UINT8 period) +{ + if(bk_ps_info.ps_dtim_period != period) + { + os_printf("new dtim period:%d\r\n", period); + } + + bk_ps_info.ps_dtim_period = period; +} + +void power_save_set_dtim_count(UINT8 count) +{ + bk_ps_info.ps_dtim_count = count; +} + +void power_save_cal_bcn_liston_int(UINT16 bcn_int) +{ + if(bcn_int != 0 ) + { + bk_ps_info.ps_beacon_int = bcn_int; + bk_ps_info.liston_int = 100; + } +} + +UINT8 power_save_get_liston_int(void) +{ + return bk_ps_info.liston_int; +} + +void power_save_td_timer_stop(void) +{ + int32 err; + + GLOBAL_INT_DECLARATION(); +#if CFG_SUPPORT_ALIOS + err = rtos_stop_timer(&ps_td_ck_timer); +#else + err = rtos_stop_oneshot_timer(&ps_td_ck_timer); +#endif + ASSERT(kNoErr == err); + GLOBAL_INT_DISABLE(); + ps_td_ck_timer_status = 0; + GLOBAL_INT_RESTORE(); +} + +void power_save_td_ck_timer_real_handler(void *data) +{ + power_save_td_timer_stop(); + + if(PS_STA_DTIM_SWITCH) + { + ps_td_last_tick = 1; + } + +#if CFG_USE_STA_PS + extern void bmsg_null_sender(void); + bmsg_null_sender(); +#endif +} + +void power_save_td_ck_timer_handler(void *data) +{ + bmsg_ps_sender(PS_BMSG_IOCTL_RF_TD_HANDLER); +} + +void power_save_delay_sleep_check(void) +{ + bmsg_ps_sender(PS_BMSG_IOCTL_RF_TD_SET); +} + +void power_save_td_ck_timer_set(void) +{ + OSStatus err; + +#if CFG_SUPPORT_ALIOS + if(rtos_is_timer_init(&ps_td_ck_timer) && ps_td_ck_timer_status == 0) +#else + if(rtos_is_oneshot_timer_init(&ps_td_ck_timer) && ps_td_ck_timer_status == 0) +#endif + { + ps_td_ck_timer_status = 1; +#if CFG_SUPPORT_ALIOS + err = rtos_start_timer(&ps_td_ck_timer); +#else + err = rtos_start_oneshot_timer(&ps_td_ck_timer); +#endif + ASSERT(kNoErr == err); + } +} + + +void power_save_wait_timer_stop(void) +{ + OSStatus err; + GLOBAL_INT_DECLARATION(); +#if CFG_SUPPORT_ALIOS + err = rtos_stop_timer(&ps_wait_timer); +#else + err = rtos_stop_oneshot_timer(&ps_wait_timer); +#endif + + ASSERT(kNoErr == err); + GLOBAL_INT_DISABLE(); + ps_wait_timer_status = 0; + GLOBAL_INT_RESTORE(); +} + +extern void power_save_beacon_state_set(PS_STA_BEACON_STATE state); +void power_save_wait_timer_real_handler(void *data) +{ + power_save_wait_timer_stop(); + if(PS_STA_DTIM_SWITCH) + { + power_save_beacon_state_set(STA_GET_TRUE); + } +} + +void power_save_wait_timer_handler(void *data) +{ + bmsg_ps_sender(PS_BMSG_IOCTL_WAIT_TM_HANDLER); +} +void power_save_wait_timer_init(void) +{ + UINT32 err; + +#if CFG_SUPPORT_ALIOS + if(rtos_is_timer_init(&ps_wait_timer)) +#else + if(rtos_is_oneshot_timer_init(&ps_wait_timer)) +#endif + { + power_save_wait_timer_stop(); +#if CFG_SUPPORT_ALIOS + err = rtos_deinit_timer(&ps_wait_timer); +#else + err = rtos_deinit_oneshot_timer(&ps_wait_timer); +#endif + ASSERT(kNoErr == err); + } + + { +#if CFG_SUPPORT_ALIOS + err = rtos_init_timer(&ps_wait_timer, +#else + err = rtos_init_oneshot_timer(&ps_wait_timer, + #endif + 20, + #if CFG_SUPPORT_ALIOS + (timer_handler_t)power_save_wait_timer_handler, +#else + (timer_2handler_t)power_save_wait_timer_handler, + NULL, +#endif + NULL); + ASSERT(kNoErr == err); + } +} + +void power_save_wait_timer_set(void *data) +{ + if(PS_STA_DTIM_SWITCH) + { + bmsg_ps_sender(PS_BMSG_IOCTL_WAIT_TM_SET); + } +} + +void power_save_wait_timer_start(void) +{ + OSStatus err; + +#if CFG_SUPPORT_ALIOS + if(rtos_is_timer_init(&ps_wait_timer) && ps_wait_timer_status == 0) +#else + if(rtos_is_oneshot_timer_init(&ps_wait_timer) && ps_wait_timer_status == 0) +#endif + { + ps_wait_timer_status = 1; + power_save_beacon_state_set(STA_GET_FALSE); +#if CFG_SUPPORT_ALIOS + err = rtos_start_timer(&ps_wait_timer); +#else + err = rtos_start_oneshot_timer(&ps_wait_timer); +#endif + + ASSERT(kNoErr == err); + } +} + + +void power_save_keep_timer_stop(void) +{ + OSStatus err; + GLOBAL_INT_DECLARATION(); +#if CFG_SUPPORT_ALIOS + err = rtos_stop_timer(&ps_keep_timer); +#else + err = rtos_stop_oneshot_timer(&ps_keep_timer); +#endif + ASSERT(kNoErr == err); + GLOBAL_INT_DISABLE(); + ps_keep_timer_status = 0; + GLOBAL_INT_RESTORE(); +} + +void power_save_keep_timer_real_handler() +{ + GLOBAL_INT_DECLARATION(); + + power_save_keep_timer_stop(); + PS_DEBUG_PWM_TRIGER; + +#if CFG_USE_BLE_PS + rf_wifi_used_clr(); +#endif + + GLOBAL_INT_DISABLE(); + if((PS_STA_DTIM_SWITCH) + && bk_ps_info.ps_arm_wakeup_way == PS_ARM_WAKEUP_RW + && 0 == bk_ps_info.ps_real_sleep) + { + if(ps_keep_timer_flag && (power_save_beacon_state_get() != STA_GET_TRUE)) + { + PS_DBG("@%d ",__LINE__); + ps_fake_data_rx_check(); + ps_keep_timer_flag = 0; + bmsg_ps_sender(PS_BMSG_IOCTL_RF_KP_SET); + GLOBAL_INT_RESTORE(); + return; + } + if(0 == ps_reseted_moniter_flag + && ps_bcn_loss_max_count < PS_BCN_MAX_LOSS_LIMIT + ) + { + bk_ps_info.ps_arm_wakeup_way = PS_ARM_WAKEUP_USER; + power_save_clr_all_vif_prevent_sleep((UINT32)(PS_VIF_WAITING_BCN)); + ps_bcn_loss_max_count ++; + + PS_DBG("@%d ",__LINE__); + ps_run_td_timer(0); + } + else + { + ps_reseted_moniter_flag = 0; + } + GLOBAL_INT_RESTORE(); + delay(1); + PS_DEBUG_PWM_TRIGER; + +#if CFG_USE_STA_PS + extern void bmsg_null_sender(void); + bmsg_null_sender(); +#endif + } + else + { + GLOBAL_INT_RESTORE(); + } + +} + +void power_save_keep_timer_handler(void *data) +{ + bmsg_ps_sender(PS_BMSG_IOCTL_RF_KP_HANDLER); +} + +void power_save_keep_timer_set(void) +{ + OSStatus err; + +#if CFG_SUPPORT_ALIOS + if(rtos_is_timer_init(&ps_keep_timer) && ps_keep_timer_status == 0) +#else + if(rtos_is_oneshot_timer_init(&ps_keep_timer) && ps_keep_timer_status == 0) +#endif + { + ps_keep_timer_status = 1; +#if CFG_SUPPORT_ALIOS + err = rtos_start_timer(&ps_keep_timer); +#else + err = rtos_start_oneshot_timer(&ps_keep_timer); +#endif + ASSERT(kNoErr == err); + } +} + + +void power_save_rf_ps_wkup_semlist_init(void) +{ + co_list_init(&bk_ps_info.wk_list); +} + +void * power_save_rf_ps_wkup_semlist_create(void) +{ + UINT32 ret; + + PS_DO_WKUP_SEM *sem_list = (PS_DO_WKUP_SEM *) os_malloc(sizeof(PS_DO_WKUP_SEM)); + + if(!sem_list) + { + os_printf("semlist_wait NULL\r\n"); + return 0; + } + +#if CFG_SUPPORT_ALIOS + ret = rtos_init_semaphore(&sem_list->wkup_sema, 0); +#else + ret = rtos_init_semaphore(&sem_list->wkup_sema, 1); +#endif + ASSERT(0 == ret); + + return sem_list; +} + +void power_save_rf_ps_wkup_semlist_wait(void *sem_list_p) +{ + PS_DO_WKUP_SEM *sem_list = (PS_DO_WKUP_SEM *)sem_list_p; + + co_list_push_back(&bk_ps_info.wk_list, &sem_list->list); + + if (!ble_switch_mac_sleeped) + bmsg_ps_sender(PS_BMSG_IOCTL_RF_USER_WKUP); +} + +void power_save_rf_ps_wkup_semlist_destroy(void *sem_list_p) +{ + UINT32 ret; + PS_DO_WKUP_SEM *sem_list = (PS_DO_WKUP_SEM *)sem_list_p; + + ret = rtos_deinit_semaphore(&sem_list->wkup_sema); + ASSERT(0 == ret); +} + +void power_save_rf_ps_wkup_semlist_get(void *sem_list) +{ + UINT32 ret; + + if(sem_list) + { + ret = rtos_get_semaphore(&((PS_DO_WKUP_SEM *)sem_list)->wkup_sema, BEKEN_NEVER_TIMEOUT); + ASSERT(0 == ret); + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + co_list_extract(&bk_ps_info.wk_list, &((PS_DO_WKUP_SEM *)sem_list)->list); + GLOBAL_INT_RESTORE(); + + ret = rtos_deinit_semaphore(&((PS_DO_WKUP_SEM *)sem_list)->wkup_sema); + ASSERT(0 == ret); + + os_free(sem_list); + sem_list = NULL; + } +} + +void power_save_rf_ps_wkup_semlist_set(void) +{ + UINT32 ret; + + while (!co_list_is_empty(&bk_ps_info.wk_list)) + { + PS_DO_WKUP_SEM *sem_list; + sem_list = list2sem(co_list_pop_front(&bk_ps_info.wk_list)); + ret = rtos_set_semaphore(&sem_list->wkup_sema); + ASSERT(0 == ret); + } +} + +void power_save_beacon_state_set(PS_STA_BEACON_STATE state) +{ + bk_ps_info.waited_beacon = state; +} + +void power_save_beacon_state_update(void) +{ + PS_DEBUG_RX_TRIGER; + +#if CFG_USE_BLE_PS + rf_wifi_used_clr(); +#endif + if(PS_STA_DTIM_SWITCH) + { + if(power_save_if_ps_can_sleep() + && power_save_beacon_state_get() == STA_GET_INIT) + { + power_save_beacon_state_set(STA_GET_FALSE); + } + } + + if(PS_STA_DTIM_SWITCH + && (power_save_beacon_state_get() != STA_GET_TRUE) + ) + { + power_save_beacon_state_set(STA_GET_TRUE); + ps_bcn_loss_max_count = 0; + + if(1 == ps_keep_timer_status) + { + bmsg_ps_sender(PS_BMSG_IOCTL_RF_KP_STOP); + } + + if(0 == ps_keep_timer_flag) + { + PS_DBG("@%d ",__LINE__); + ps_run_td_timer(0); + } + } +} + + +void power_save_bcn_callback(uint8_t *data, int len, hal_wifi_link_info_t *info) +{ + struct bcn_frame *bcn = (struct bcn_frame *)data; + VIF_INF_PTR vif_entry; + + vif_entry = (VIF_INF_PTR)rwm_mgmt_is_vif_first_used(); + while(vif_entry) + { + if(vif_entry->type == VIF_STA && vif_entry->active) + { + break; + } + vif_entry = (VIF_INF_PTR)rwm_mgmt_next(vif_entry); + } + + if (!vif_entry) + return; + + if(bcn->bcnint != bk_ps_info.ps_beacon_int) + { + os_printf("bcn interval changed %x %x\r\n", bcn->bcnint, bk_ps_info.ps_beacon_int); + mm_send_connection_loss_ind(vif_entry); + } + +} + +UINT8 power_save_if_sleep_first(void) +{ + return bk_ps_info.sleep_first; +} + +PS_STA_BEACON_STATE power_save_beacon_state_get(void) +{ + return bk_ps_info.waited_beacon; +} + +PS_ARM_WAKEUP_WAY power_save_wkup_way_get(void) +{ + return bk_ps_info.ps_arm_wakeup_way; +} + + +UINT8 power_save_if_ps_can_sleep(void) +{ + return (bk_ps_info.ps_can_sleep == 1); +} + +INT8 power_save_if_sleep_at_first(void) +{ + return (bk_ps_info.sleep_count < 6); +} + +UINT32 power_save_get_sleep_count(void) +{ + return bk_ps_info.sleep_count; +} + +UINT8 power_save_if_ps_rf_dtim_enabled(void) +{ + return (bk_ps_mode == PS_DTIM_PS_MODE); +} + +void power_save_ps_mode_set(PS_MODE_STATUS mode) +{ + bk_ps_mode = mode; +} + +UINT16 power_save_radio_wkup_get(void) +{ + return r_wakeup_time; +} + +void power_save_radio_wkup_set(UINT16 time) +{ + r_wakeup_time = time; +} + +UINT32 power_save_wkup_event_get(void) +{ + return ps_dis_flag; +} + +void power_save_wkup_event_set(UINT32 value) +{ + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + ps_dis_flag |= value; + GLOBAL_INT_RESTORE(); +} + +void power_save_wkup_event_clear(UINT32 value) +{ + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + ps_dis_flag &= ~value; + GLOBAL_INT_RESTORE(); +} + +UINT16 power_save_beacon_len_get(void) +{ + return beacon_len; +} + +void power_save_beacon_len_set(UINT16 len) +{ + beacon_len = len + 4/*fcs*/ /*+25 radiotap*/; +} + +void power_save_set_reseted_flag(void) +{ + ps_reseted_moniter_flag = 1; +} + +UINT32 power_save_get_bcn_lost_count(void) +{ + return ps_bcn_loss_max_count; +} + +UINT8 power_save_set_dtim_multi(UINT8 multi) +{ + bk_ps_info.ps_dtim_multi = multi; + + if(bk_ps_info.ps_dtim_multi > 0 && bk_ps_info.ps_dtim_multi < 100) + { + os_printf("set listen dtim:%d\r\n", bk_ps_info.ps_dtim_multi); + } + else + { + os_printf("set listen dtim:%d err,use default 1\r\n", bk_ps_info.ps_dtim_multi); + bk_ps_info.ps_dtim_multi = 1; + } + + bk_ps_info.liston_mode = PS_LISTEN_MODE_DTIM; + + return 0; +} + +UINT16 power_save_forbid_trace(PS_FORBID_STATUS forbid) +{ + bk_forbid_count ++; + + if(bk_forbid_code != forbid || (bk_forbid_count % 100 == 0)) + { + PS_PRT("front c:%d\r\n\r\n", bk_forbid_count); + PS_PRT("ps_cd:%d\r\n", forbid); + bk_forbid_count = 0; + } + + bk_forbid_code = forbid; + return bk_forbid_count; +} + +void power_save_dump(void) +{ + UINT32 i; + extern UINT32 txl_cntrl_pck_get(void ); + os_printf("rf:%x\r\n", bk_ps_mode); + os_printf("info dump\r\n"); + + for(i = 0; i < sizeof(bk_ps_info); i++) + os_printf(" %d 0x%x\r\n", i, *((UINT8 *)(&bk_ps_info) + i)); + + os_printf("globel dump\r\n"); + os_printf("%d %d %d %d %d %d\r\n", + bk_ps_mode, + mhdr_get_station_status(), + g_wlan_general_param->role, + bk_ps_info.waited_beacon, + bk_ps_info.ps_can_sleep, + ps_lock); + os_printf("env dump\r\n"); + os_printf("%d %d %d %d\r\n", + ps_env.ps_on, + me_env.ps_on, + beacon_len, + txl_cntrl_pck_get()); +#if CFG_USE_MCU_PS + os_printf("mcu dump\r\n"); + os_printf("%d %d\r\n", + peri_busy_count_get(), + mcu_prevent_get()); +#endif + + os_printf("%d %d %d %d %d %d\r\n", + bk_ps_info.pwm_less_time, bk_ps_info.pwm_clkmux, + bk_ps_info.ps_dtim_period, bk_ps_info.ps_dtim_count, + bk_ps_info.ps_dtim_multi, bk_forbid_code); +#if CFG_USE_STA_PS + sctrl_ps_dump(); +#endif +} + +#endif + +PS_MODE_STATUS power_save_ps_mode_get(void) +{ + return bk_ps_mode; +} +UINT8 power_save_if_rf_sleep(void) +{ +#if CFG_USE_STA_PS + if(bk_ps_info.ps_real_sleep == 1) + { + return 1; + } +#endif + return 0; +} + + +// eof + diff --git a/beken_os/beken378/func/power_save/power_save.h b/beken_os/beken378/func/power_save/power_save.h new file mode 100755 index 0000000..d091be7 --- /dev/null +++ b/beken_os/beken378/func/power_save/power_save.h @@ -0,0 +1,137 @@ +#ifndef _POWER_SAVE_H_ +#define _POWER_SAVE_H_ + +#include "param_config.h" +#include "co_list.h" +#include "power_save_pub.h" +#include "ps_debug_pub.h" + +#define PS_DTIM_PERI_WAKE_DELAY 0 +#define PS_WAKE_DATA_DELAY 1 + +#define PS_BCN_MAX_LOSS_LIMIT (5) + +typedef enum +{ + STA_GET_INIT = 0, + STA_GET_TRUE = 1, + STA_GET_FALSE = 2, + STA_GET_TIMEOUT = 3, +} PS_STA_BEACON_STATE; + +typedef UINT8 PS_WAIT_STATUS; +typedef enum +{ + PS_BCN_SUCC = 0, + PS_BCN_LOSS_LEFT = 1, + PS_BCN_LOSS_RIGHT = 2, + PS_BCN_LOSS_MIDDLE = 3, + PS_BCN_LOSS_FIRST = 4, +} PS_BCN_STATUS; + +typedef enum +{ + PS_BCN_STATUS_INIT = 0, + PS_BCN_STATUS_UP = 1, + PS_BCN_ABNORMAL_AT = 2, + PS_BCN_STATUS_DOWN = 3, +} PS_BCN_ABNORMAL_STATUS; + + +typedef enum +{ + PS_ARM_WAKEUP_NONE = 0, + PS_ARM_WAKEUP_RW = 1, + PS_DTIM_ARM_WAKEUP_PERI = 2, + PS_ARM_WAKEUP_PWM = 3, + PS_ARM_WAKEUP_USER = 4, + PS_ARM_WAKEUP_UPING = 5, +} PS_ARM_WAKEUP_WAY; + +typedef enum +{ + TM_LOW_POWER = 0, + PS_TM_CK_AB_BCN = 1, + PS_TM_CK_TIMEOUT = 2, + PS_TM_CK_DATA_OVER = 3, +} PS_TM_STATUS; + +typedef enum +{ + PS_BCN_NO_CAL = 0, + PS_BCN_LOST_10 = 1, +} PS_BCN_CAL_STATUS; + +typedef enum +{ + PS_LISTEN_MODE_DTIM = 0, + PS_LISTEN_MODE_INTERVAL = 1, +} PS_LISTEN_MODE; + +typedef struct ps_do_wkup_sem +{ + beken_semaphore_t wkup_sema; + struct co_list_hdr list; +} PS_DO_WKUP_SEM; + +typedef struct ps_sta +{ + PS_BCN_ABNORMAL_STATUS ps_bcn_ab_status ; + PS_ARM_WAKEUP_WAY ps_arm_wakeup_way ; + UINT8 ps_real_sleep ; + UINT8 sleep_first; + UINT8 ps_can_sleep; + UINT8 if_wait_bcn; + UINT8 liston_int; + PS_LISTEN_MODE liston_mode; + UINT8 pwm_clkmux; + PS_TM_STATUS tm_status; + UINT8 ps_dtim_period; + UINT8 ps_dtim_count; + UINT8 ps_dtim_multi; + volatile PS_STA_BEACON_STATE waited_beacon; + UINT8 ps_bcn_loss_cnt; + PS_BCN_CAL_STATUS ps_bcn_cal_status; + UINT16 ps_beacon_int; + UINT16 PsDataWakeupWaitTimeMs ; + UINT16 PsPeriWakeupWaitTimeMs ; + UINT16 sleep_ms; + UINT32 nxmac_timer_v; + UINT32 pwm_less_time; + UINT32 sleep_count ; + UINT32 next_ps_time; + struct co_list wk_list; +} STA_PS_INFO; + + +__INLINE struct ps_do_wkup_sem *list2sem(struct co_list_hdr const *l_list) +{ + return (struct ps_do_wkup_sem *) (((uint8_t *)l_list) - offsetof(struct ps_do_wkup_sem, list)); +} + +void power_save_mac_idle_callback(void); +UINT32 power_save_wkup_event_get(void); +void power_save_dtim_ps_init(); +void power_save_ieee_dtim_wakeup(void); +UINT8 power_save_me_ps_set_all_state(UINT8 state); +PS_STA_BEACON_STATE power_save_beacon_state_get(void); +PS_ARM_WAKEUP_WAY power_save_wkup_way_get(void); +void power_save_set_uart_linger_time(UINT32 uart_wakeup_time); +extern void bmsg_ps_sender(uint8_t ioctl); +extern void ps_fake_data_rx_check(void); +extern bool ps_sleep_check(void); +extern u8 rwn_mgmt_is_only_sta_role_add(void); + +#define PS_STA_DTIM_SWITCH (power_save_if_ps_rf_dtim_enabled() \ + && net_if_is_up() \ + &&g_wlan_general_param->role == CONFIG_ROLE_STA) + + +#define PS_STA_DTIM_CAN_SLEEP (PS_STA_DTIM_SWITCH \ + && (power_save_beacon_state_get() == STA_GET_TRUE \ + || power_save_wkup_way_get() == PS_ARM_WAKEUP_USER) \ + && power_save_if_ps_can_sleep()) + +#endif // _POWER_SAVE_H_ +// eof + diff --git a/beken_os/beken378/func/rf_test/rx_sensitivity.c b/beken_os/beken378/func/rf_test/rx_sensitivity.c new file mode 100755 index 0000000..b7a8e9e --- /dev/null +++ b/beken_os/beken378/func/rf_test/rx_sensitivity.c @@ -0,0 +1,594 @@ +#include "include.h" +#include "rx_sensitivity.h" +#include "rx_sensitivity_pub.h" + +#include "uart_pub.h" +#include "arm_arch.h" +#include "ble_pub.h" +#include "icu_pub.h" +#include "sys_ctrl_pub.h" + +#include "mac.h" +#include "phy.h" +#include "hal_machw.h" +#include "me.h" +#include "mm.h" +#include "ke_task.h" +#include "vif_mgmt.h" +#include "drv_model_pub.h" +#include "target_util_pub.h" +#include "mac_phy_bypass_pub.h" + +#if CFG_RX_SENSITIVITY_TEST +struct mac_addr const rs_mac_addr = { + {0x7112, 0x7111, 0x7111} + }; + +UINT32 g_txbw20; +UINT32 g_txbw40; +UINT32 g_txbw80; +UINT32 g_txbw160; +UINT32 g_txoctectinampdu; +UINT32 g_txampdu; +UINT32 g_rxbw20; +UINT32 g_rxbw40; +UINT32 g_rxbw80; +UINT32 g_rxbw160; +UINT32 g_rxoctectinampdu; +UINT32 g_rxampdu; +UINT32 g_fcserror; +UINT32 g_phyerror; +UINT32 g_rxflowc; + +UINT32 g_s_rxbw20; +UINT32 g_s_rxbw40; + + +const UINT16 rs_freq_2_4_G[RS_2_4_G_CHANNEL_NUM] = { + 2412, + 2417, + 2422, + 2427, + 2432, + 2437, + 2442, + 2447, + 2452, + 2457, + 2462, + 2467, + 2472, + 2484 +}; + +UINT32 rs_channel = 2437; +UINT32 rs_mode = PHY_CHNL_BW_20; + +void rs_init(UINT32 channel, UINT32 mode) +{ + struct phy_cfg_tag cfg; + + /*reset mm*/ + RS_PRT("[RS]reset_mm\r\n"); + hal_machw_stop(); + phy_stop(); + me_init(); + mm_init(); + ke_state_set(TASK_MM, MM_IDLE); + + /*config me*/ + RS_PRT("[RS]config_me\r\n"); + + /*config me channel*/ + RS_PRT("[RS]config_me_channel\r\n"); + + /*start mm*/ + RS_PRT("[RS]start_mm\r\n"); + cfg.parameters[0] = 1; + cfg.parameters[1] = 0; + phy_init(&cfg); + + phy_set_channel(PHY_BAND_2G4, mode, channel, channel, 0, PHY_PRIM); + + /* Put the HW in active state*/ + mm_active(); +} + +void rs_rx_monitor(void) +{ + hal_machw_enter_monitor_mode(); + + RS_PRT("[RS]rs_rx_monitor\r\n"); +} + +UINT32 rs_set_channel(UINT32 channel_id) +{ + if((0 == channel_id) + || (channel_id > RS_2_4_G_CHANNEL_NUM)) + { + return 1; + } + + rs_channel = rs_freq_2_4_G[channel_id - 1]; + + return 0; +} + +UINT32 rs_set_mode(UINT32 mode) +{ + rs_mode = mode; + return 0; +} + +void rs_test(void) +{ + rs_init(rs_channel, rs_mode); + rs_rx_monitor(); +} + +void rx_get_rx_result_begin(void) +{ + g_txbw20 = REG_READ(0xc0000b70); + g_txbw40 = REG_READ(0xc0000b74); + g_txbw80 = REG_READ(0xc0000b78); + g_txbw160 = REG_READ(0xc0000b7c); + + (void)REG_READ(0xc0000b34); + g_txoctectinampdu = REG_READ(0xc0000b38); + g_txampdu = REG_READ(0xc0000b30); + + g_rxbw20 = REG_READ(0xc0000b80); + g_rxbw40 = REG_READ(0xc0000b84); + g_rxbw80 = REG_READ(0xc0000b88); + g_rxbw160 = REG_READ(0xc0000b8c); + + (void)REG_READ(0xc0000b48); + g_rxoctectinampdu = REG_READ(0xc0000b4c); + g_rxampdu = REG_READ(0xc0000b3c); + + g_fcserror = REG_READ(0xc0000804); + g_phyerror = REG_READ(0xc0000808); + g_rxflowc = REG_READ(0xc000080c); + + REG_WRITE(0xc0000220, 0x0); + REG_WRITE(0xc0000290, 0x0); + REG_WRITE(0xc0000294, 0x0); + REG_WRITE(0xc0000298, 0x0); + REG_WRITE(0xc0000040, 0x00011881); + + phy_enable_rx_switch(); +} + +void rx_clean_rx_statistic_result(void) +{ + RS_PRT("[RS]RXSENS_RTYPTE_CLEAN\r\n"); + g_s_rxbw20 = g_s_rxbw40 = 0; + + rx_get_rx_result_begin(); +} + +UINT32 rx_get_rx20M_statistic_result(void) +{ + RS_PRT("[RS]RXSENS_RTYPTE_20M :%d\r\n", g_s_rxbw20); + return g_s_rxbw20; +} + +UINT32 rx_get_rx40M_statistic_result(void) +{ + RS_PRT("[RS]RXSENS_RTYPTE_40M :%d\r\n", g_s_rxbw40); + return g_s_rxbw40; +} + +void rx_get_rx_result_end(void) +{ + UINT32 txbw20new; + UINT32 txbw40new; + UINT32 txbw80new; + UINT32 txbw160new; + + UINT32 txoctectinampdunew; + UINT32 txampdunew; + + UINT32 rxbw20new; + UINT32 rxbw40new; + UINT32 rxbw80new; + UINT32 rxbw160new; + + UINT32 rxoctectinampdunew; + UINT32 rxampdunew; + + UINT32 fcserrornew; + UINT32 phyerrornew; + UINT32 rxflowcnew; + UINT32 ccapri; + UINT32 ccasec20; + UINT32 ccasec40; + UINT32 ccasec80; + + UINT32 txbw20cur; + UINT32 txbw40cur; + UINT32 txbw80cur; + UINT32 txbw160cur; + UINT32 txtot; + + UINT32 txampducur; + + UINT32 rxbw20cur; + UINT32 rxbw40cur; + UINT32 rxbw80cur; + UINT32 rxbw160cur; + + UINT32 rxampducur; + + UINT32 fcserrcur; + UINT32 phyerrcur; + UINT32 rxflowccur; + UINT32 rxtot; + + txbw20new = REG_READ(0xc0000b70); + txbw40new = REG_READ(0xc0000b74); + txbw80new = REG_READ(0xc0000b78); + txbw160new = REG_READ(0xc0000b7c); + + (void)REG_READ(0xc0000b34); + txoctectinampdunew = REG_READ(0xc0000b38); + txampdunew = REG_READ(0xc0000b30); + + rxbw20new = REG_READ(0xc0000b80); + rxbw40new = REG_READ(0xc0000b84); + rxbw80new = REG_READ(0xc0000b88); + rxbw160new = REG_READ(0xc0000b8c); + + (void)REG_READ(0xc0000b48); + rxoctectinampdunew = REG_READ(0xc0000b4c); + rxampdunew = REG_READ(0xc0000b3c); + + fcserrornew = REG_READ(0xc0000804); + phyerrornew = REG_READ(0xc0000808); + rxflowcnew = REG_READ(0xc000080c); + ccapri = REG_READ(0xc0000220); + ccasec20 = REG_READ(0xc0000290); + ccasec40 = REG_READ(0xc0000294); + ccasec80 = REG_READ(0xc0000298); + + txbw20cur = ((txbw20new - g_txbw20)); + txbw40cur = ((txbw40new - g_txbw40)); + txbw80cur = ((txbw80new - g_txbw80)); + txbw160cur = ((txbw160new - g_txbw160)); + txtot = ((txbw40cur + txbw20cur + txbw80cur + txbw160cur)); + + txampducur = ((txampdunew - g_txampdu)); + + if(0 == txtot) + { + txtot = 1; + } + + if(0 == txampducur) + { + txampducur = 1; + } + + rxbw20cur = (rxbw20new - g_rxbw20); + g_s_rxbw20 = rxbw20cur; + rxbw40cur = (rxbw40new - g_rxbw40); + g_s_rxbw40 = rxbw40cur; + + rxbw80cur = (rxbw80new - g_rxbw80); + rxbw160cur = (rxbw160new - g_rxbw160); + + rxampducur = (rxampdunew - g_rxampdu); + + fcserrcur = (fcserrornew - g_fcserror); + phyerrcur = (phyerrornew - g_phyerror); + rxflowccur = (rxflowcnew - g_rxflowc); + rxtot = (rxbw40cur + rxbw20cur + rxbw80cur + rxbw160cur + fcserrcur + phyerrcur + rxflowccur); + + if(0 == rxtot) + { + rxtot = 1; + } + + RS_PRT("\r\nrx\r\n"); + RS_PRT("20mhz : %0d (%0d %%)\r\n", rxbw20cur, (100*rxbw20cur/rxtot)); + RS_PRT("40mhz : %0d (%0d %%)\r\n", rxbw40cur, (100*rxbw40cur/rxtot)); + + if(0 == rxampducur) + { + rxampducur = 1; + } + + RS_PRT("fcserr : %0d (%0d %%), ", fcserrcur, (100*fcserrcur/rxtot)); + RS_PRT("phyerr : %0d (%0d %%), ", phyerrcur, (100*phyerrcur/rxtot)); + RS_PRT("rxflowerr: %0d (%0d %%)\r\n", rxflowccur, (100*rxflowccur/rxtot)); + + (void) ccapri; + (void) ccasec20; + (void) ccasec40; + (void) ccasec80; + (void) rxoctectinampdunew; + (void) txoctectinampdunew; +} + +/* refer to txrx_stat.sh*/ +void rs_get_rx_result(void) +{ + UINT32 TXBW20; + UINT32 TXBW40; + UINT32 TXBW80; + UINT32 TXBW160; + + UINT32 TXOCTECTINAMPDU; + UINT32 TXAMPDU; + + UINT32 RXBW20; + UINT32 RXBW40; + UINT32 RXBW80; + UINT32 RXBW160; + + UINT32 RXOCTECTINAMPDU; + UINT32 RXAMPDU; + + UINT32 FCSERROR; + UINT32 PHYERROR; + UINT32 RXFLOWC; + + UINT32 TXBW20NEW; + UINT32 TXBW40NEW; + UINT32 TXBW80NEW; + UINT32 TXBW160NEW; + + UINT32 TXOCTECTINAMPDUNEW; + UINT32 TXAMPDUNEW; + + UINT32 RXBW20NEW; + UINT32 RXBW40NEW; + UINT32 RXBW80NEW; + UINT32 RXBW160NEW; + + UINT32 RXOCTECTINAMPDUNEW; + UINT32 RXAMPDUNEW; + + UINT32 FCSERRORNEW; + UINT32 PHYERRORNEW; + UINT32 RXFLOWCNEW; + UINT32 CCAPRI; + UINT32 CCASEC20; + UINT32 CCASEC40; + UINT32 CCASEC80; + + UINT32 TXBW20CUR; + UINT32 TXBW40CUR; + UINT32 TXBW80CUR; + UINT32 TXBW160CUR; + UINT32 TXTOT; + + UINT32 TXAMPDUCUR; + UINT32 TXOCTECTINAMPDUCUR; + + UINT32 RXBW20CUR; + UINT32 RXBW40CUR; + UINT32 RXBW80CUR; + UINT32 RXBW160CUR; + + UINT32 RXAMPDUCUR; + UINT32 RXOCTECTINAMPDUCUR; + + UINT32 FCSERRCUR; + UINT32 PHYERRCUR; + UINT32 RXFLOWCCUR; + UINT32 RXTOT; + + TXBW20 = REG_READ(0xc0000b70); + TXBW40 = REG_READ(0xc0000b74); + TXBW80 = REG_READ(0xc0000b78); + TXBW160 = REG_READ(0xc0000b7C); + + (void)REG_READ(0xc0000b34); + TXOCTECTINAMPDU = REG_READ(0xc0000b38); + TXAMPDU = REG_READ(0xc0000b30); + + RXBW20 = REG_READ(0xc0000b80); + RXBW40 = REG_READ(0xc0000b84); + RXBW80 = REG_READ(0xc0000b88); + RXBW160 = REG_READ(0xc0000b8C); + + (void)REG_READ(0xc0000b48); + RXOCTECTINAMPDU = REG_READ(0xc0000b4C); + RXAMPDU = REG_READ(0xc0000b3C); + + FCSERROR = REG_READ(0xc0000804); + PHYERROR = REG_READ(0xc0000808); + RXFLOWC = REG_READ(0xc000080c); + + REG_WRITE(0xc0000220, 0x0); + REG_WRITE(0xc0000290, 0x0); + REG_WRITE(0xc0000294, 0x0); + REG_WRITE(0xc0000298, 0x0); + REG_WRITE(0xc0000040, 0x00011881); + + delay(100); + + TXBW20NEW = REG_READ(0xc0000b70); + TXBW40NEW = REG_READ(0xc0000b74); + TXBW80NEW = REG_READ(0xc0000b78); + TXBW160NEW = REG_READ(0xc0000b7C); + + (void)REG_READ(0xc0000b34); + TXOCTECTINAMPDUNEW = REG_READ(0xc0000b38); + TXAMPDUNEW = REG_READ(0xc0000b30); + + RXBW20NEW = REG_READ(0xc0000b80); + RXBW40NEW = REG_READ(0xc0000b84); + RXBW80NEW = REG_READ(0xc0000b88); + RXBW160NEW = REG_READ(0xc0000b8C); + + (void)REG_READ(0xc0000b48); + RXOCTECTINAMPDUNEW = REG_READ(0xc0000b4C); + RXAMPDUNEW = REG_READ(0xc0000b3C); + + FCSERRORNEW = REG_READ(0xc0000804); + PHYERRORNEW = REG_READ(0xc0000808); + RXFLOWCNEW = REG_READ(0xc000080c); + CCAPRI = REG_READ(0xc0000220); + CCASEC20 = REG_READ(0xc0000290); + CCASEC40 = REG_READ(0xc0000294); + CCASEC80 = REG_READ(0xc0000298); + + TXBW20CUR = ((TXBW20NEW - TXBW20)); + TXBW40CUR = ((TXBW40NEW - TXBW40)); + TXBW80CUR = ((TXBW80NEW - TXBW80)); + TXBW160CUR = ((TXBW160NEW - TXBW160)); + TXTOT = ((TXBW40CUR + TXBW20CUR + TXBW80CUR + TXBW160CUR)); + + TXAMPDUCUR = ((TXAMPDUNEW - TXAMPDU)); + TXOCTECTINAMPDUCUR = ((TXOCTECTINAMPDUNEW - TXOCTECTINAMPDU)); + + if(0 == TXTOT) + { + TXTOT = 1; + } + + RS_PRT("TX\n"); + RS_PRT("20MHz : %0d (%0d %%)\r\n", TXBW20CUR, 100*TXBW20CUR/TXTOT); + RS_PRT("40MHz : %0d (%0d %%)\r\n", TXBW40CUR, 100*TXBW40CUR/TXTOT); + RS_PRT("80MHz : %0d (%0d %%)\r\n", TXBW80CUR, 100*TXBW80CUR/TXTOT); + RS_PRT("160MHz : %0d (%0d %%)\r\n", TXBW160CUR, 100*TXBW160CUR/TXTOT); + + RS_PRT("AMPDU : %0d (%0d %%)\r\n", TXAMPDUCUR, 100*TXAMPDUCUR/TXTOT); + + if(0 == TXAMPDUCUR) + { + TXAMPDUCUR = 1; + } + + RS_PRT("Bytes in AMPDU : %0d\r\n", (TXOCTECTINAMPDUCUR/TXAMPDUCUR)); + RS_PRT("AMPDU Throughput : %0.1f Mbps\r\n", ((float)8*TXOCTECTINAMPDUCUR/1000000)); + + RXBW20CUR = (RXBW20NEW - RXBW20); + RXBW40CUR = (RXBW40NEW - RXBW40); + RXBW80CUR = (RXBW80NEW - RXBW80); + RXBW160CUR = (RXBW160NEW - RXBW160); + + RXAMPDUCUR = (RXAMPDUNEW - RXAMPDU); + RXOCTECTINAMPDUCUR = (RXOCTECTINAMPDUNEW - RXOCTECTINAMPDU); + + FCSERRCUR = (FCSERRORNEW - FCSERROR); + PHYERRCUR = (PHYERRORNEW - PHYERROR); + RXFLOWCCUR = (RXFLOWCNEW - RXFLOWC); + RXTOT = (RXBW40CUR + RXBW20CUR + RXBW80CUR + RXBW160CUR + FCSERRCUR + PHYERRCUR + RXFLOWCCUR); + + if(0 == RXTOT) + { + RXTOT = 1; + } + + RS_PRT("\nRX\n"); + RS_PRT("20MHz : %0d (%0d %%)\r\n", RXBW20CUR, (100*RXBW20CUR/RXTOT)); + RS_PRT("40MHz : %0d (%0d %%)\r\n", RXBW40CUR, (100*RXBW40CUR/RXTOT)); + RS_PRT("80MHz : %0d (%0d %%)\r\n", RXBW80CUR, (100*RXBW80CUR/RXTOT)); + RS_PRT("160MHz : %0d (%0d %%)\r\n", RXBW160CUR, (100*RXBW160CUR/RXTOT)); + + RS_PRT("AMPDU : %0d (%0d %%)\r\n", RXAMPDUCUR, (100*RXAMPDUCUR/RXTOT)); + + if(0 == RXAMPDUCUR) + { + RXAMPDUCUR = 1; + } + + RS_PRT("Bytes in AMPDU : %0d\r\n", (RXOCTECTINAMPDUCUR/RXAMPDUCUR)); + RS_PRT("AMPDU Throughput : %0.1f Mbps\r\n", ((float)8*RXOCTECTINAMPDUCUR/1000000)); + + RS_PRT("FCSErr : %0d (%0d %%)\r\n", FCSERRCUR, (100*FCSERRCUR/RXTOT)); + RS_PRT("PHYErr : %0d (%0d %%)\r\n", PHYERRCUR, (100*PHYERRCUR/RXTOT)); + RS_PRT("RxFlowErr: %0d (%0d %%)\r\n", RXFLOWCCUR, (100*RXFLOWCCUR/RXTOT)); + RS_PRT("CCAPrim Busy : %3d %%\r\n", (CCAPRI / 10000)); + RS_PRT("CCASec20 Busy : %3d %%\r\n", (CCASEC20 / 10000)); + RS_PRT("CCASec40 Busy : %3d %%\r\n", (CCASEC40 / 10000)); + RS_PRT("CCASec80 Busy : %3d %%\r\n", (CCASEC80 / 10000)); + RS_PRT("\r\n"); +} + +void rx_clean_ble_rx_result(void) +{ + sddev_control(BLE_DEV_NAME, CMD_BLE_STOP_COUNTING, NULL); +} + +void rx_start_ble_rx_counting() +{ + sddev_control(BLE_DEV_NAME, CMD_BLE_START_COUNTING, NULL); +} + +void rs_ble_test_start(UINT32 channel) +{ + UINT32 param; + param = PWD_BLE_CLK_BIT; + + sddev_control(SCTRL_DEV_NAME, CMD_BLE_RF_BIT_SET, NULL); + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_BLE_POWERUP, NULL); + sddev_control(ICU_DEV_NAME, CMD_TL410_CLK_PWR_UP, ¶m); + + param = 0x3ba7a940; + sddev_control(BLE_DEV_NAME, CMD_BLE_SET_GFSK_SYNCWD, ¶m); + sddev_control(BLE_DEV_NAME, CMD_BLE_AUTO_CHANNEL_DISABLE, NULL); + sddev_control(BLE_DEV_NAME, CMD_BLE_AUTO_SYNCWD_DISABLE, NULL); + + if(channel > 39) + { + channel = 39; + } + param = (channel + 1) * 2; + sddev_control(BLE_DEV_NAME, CMD_BLE_SET_CHANNEL, ¶m); + param = PN9_RX; + sddev_control(BLE_DEV_NAME, CMD_BLE_SET_PN9_TRX, ¶m); +} + +void rs_ble_test_stop(void) +{ + sddev_control(SCTRL_DEV_NAME, CMD_BLE_RF_BIT_CLR, NULL); + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_BLE_POWERDOWN, NULL); +} + +void rx_get_ble_rx_result(void) +{ + UINT32 rx_ble_total = 0xFFFFFFFF; + UINT32 rx_ble_total_old = 0xFFFFFFFF; + UINT32 rx_ble_err_total = 0xFFFFFFFF; + UINT32 rx_ble_err_total_old = 0xFFFFFFFF; + + sddev_control(BLE_DEV_NAME, CMD_BLE_HOLD_PN9_ESTIMATE, NULL); + + rx_ble_total = REG_READ(0x0080B454); + while(rx_ble_total != rx_ble_total_old) + { + rx_ble_total_old = rx_ble_total; + rx_ble_total = REG_READ(0x0080B454); + } + + rx_ble_err_total = REG_READ(0x0080B458); + while(rx_ble_err_total != rx_ble_err_total_old) + { + rx_ble_err_total_old = rx_ble_err_total; + rx_ble_err_total = REG_READ(0x0080B458); + } + + RS_PRT("\r\nTotal : %d\r\n", rx_ble_total); + RS_PRT("Error : %d\r\n", rx_ble_err_total); + + if(rx_ble_err_total > 0) + { + RS_PRT("BER : %d.%02d %%\r\n", (10000 * rx_ble_err_total / rx_ble_total) / 100, + (1000 * rx_ble_err_total / rx_ble_total) % 100); + } + else + { + RS_PRT("BER : %d.%02d %%\r\n", 0, 0); + } + + sddev_control(BLE_DEV_NAME, CMD_BLE_STOP_COUNTING, NULL); + sddev_control(BLE_DEV_NAME, CMD_BLE_START_COUNTING, NULL); +} + +#endif // CFG_RX_SENSITIVITY_TEST +// eof + diff --git a/beken_os/beken378/func/rf_test/rx_sensitivity.h b/beken_os/beken378/func/rf_test/rx_sensitivity.h new file mode 100755 index 0000000..c002a45 --- /dev/null +++ b/beken_os/beken378/func/rf_test/rx_sensitivity.h @@ -0,0 +1,159 @@ +#ifndef _RX_SENSITIVITY_H_ +#define _RX_SENSITIVITY_H_ + +#define RS_DEBUG + +#ifdef RS_DEBUG +#define RS_PRT os_printf +#define RS_WPRT warning_prf +#else +#define RS_PRT os_null_printf +#define RS_WPRT os_null_printf +#endif // RS_DEBUG + +#define RS_2_4_G_CHANNEL_NUM (14) + + +/* pseudo-code*/ +/* +void rs_get_rx_result(void) +{ +#!/bin/bash + echo "" + TXBW20=`mem 0xc0b00b70` + TXBW40=`mem 0xc0b00b74` + TXBW80=`mem 0xc0b00b78` + TXBW160=`mem 0xc0b00b7C` + + TXMPDUINAMPDU=`mem 0xc0b00b34` + TXOCTECTINAMPDU=`mem 0xc0b00b38` + TXAMPDU=`mem 0xc0b00b30` + + RXBW20=`mem 0xc0b00b80` + RXBW40=`mem 0xc0b00b84` + RXBW80=`mem 0xc0b00b88` + RXBW160=`mem 0xc0b00b8C` + + RXMPDUINAMPDU=`mem 0xc0b00b48` + RXOCTECTINAMPDU=`mem 0xc0b00b4C` + RXAMPDU=`mem 0xc0b00b3C` + + FCSERROR=`mem 0xc0b00804` + PHYERROR=`mem 0xc0b00808` + RXFLOWC=`mem 0xc0b0080c` + + mem 0xc0b00220 w 0x0 > /dev/null + mem 0xc0b00290 w 0x0 > /dev/null + mem 0xc0b00294 w 0x0 > /dev/null + mem 0xc0b00298 w 0x0 > /dev/null + mem 0xc0b00040 w 0x00011881 > /dev/null + + + sleep 1 + TXBW20NEW=`mem 0xc0b00b70` + TXBW40NEW=`mem 0xc0b00b74` + TXBW80NEW=`mem 0xc0b00b78` + TXBW160NEW=`mem 0xc0b00b7C` + + TXMPDUINAMPDUNEW=`mem 0xc0b00b34` + TXOCTECTINAMPDUNEW=`mem 0xc0b00b38` + TXAMPDUNEW=`mem 0xc0b00b30` + + RXBW20NEW=`mem 0xc0b00b80` + RXBW40NEW=`mem 0xc0b00b84` + RXBW80NEW=`mem 0xc0b00b88` + RXBW160NEW=`mem 0xc0b00b8C` + + RXMPDUINAMPDUNEW=`mem 0xc0b00b48` + RXOCTECTINAMPDUNEW=`mem 0xc0b00b4C` + RXAMPDUNEW=`mem 0xc0b00b3C` + + FCSERRORNEW=`mem 0xc0b00804` + PHYERRORNEW=`mem 0xc0b00808` + RXFLOWCNEW=`mem 0xc0b0080c` + CCAPRI=`mem 0xc0b00220` + CCASEC20=`mem 0xc0b00290` + CCASEC40=`mem 0xc0b00294` + CCASEC80=`mem 0xc0b00298` + + TXBW20CUR=$((0x$TXBW20NEW - 0x$TXBW20)) + TXBW40CUR=$((0x$TXBW40NEW - 0x$TXBW40)) + TXBW80CUR=$((0x$TXBW80NEW - 0x$TXBW80)) + TXBW160CUR=$((0x$TXBW160NEW - 0x$TXBW160)) + TXTOT=$(($TXBW40CUR + $TXBW20CUR + $TXBW80CUR + $TXBW160CUR)) + + + TXAMPDUCUR=$((0x$TXAMPDUNEW - 0x$TXAMPDU)) + TXMPDUINAMPDUCUR=$((0x$TXMPDUINAMPDUNEW - 0x$TXMPDUINAMPDU)) + TXOCTECTINAMPDUCUR=$((0x$TXOCTECTINAMPDUNEW - 0x$TXOCTECTINAMPDU)) + #TXAMPDUCUR=$TXBW40CUR + + if [ $TXTOT == 0 ] + then + TXTOT=1 + fi + + printf "TX\n" + printf "20MHz : %0d (%0d %%)\n" $TXBW20CUR $((100*$TXBW20CUR/$TXTOT)) + printf "40MHz : %0d (%0d %%)\n" $TXBW40CUR $((100*$TXBW40CUR/$TXTOT)) + printf "80MHz : %0d (%0d %%)\n" $TXBW80CUR $((100*$TXBW80CUR/$TXTOT)) + printf "160MHz : %0d (%0d %%)\n" $TXBW160CUR $((100*$TXBW160CUR/$TXTOT)) + + printf "AMPDU : %0d (%0d %%)\n" $TXAMPDUCUR $((100*$TXAMPDUCUR/$TXTOT)) + if [ $TXAMPDUCUR == 0 ] + then + TXAMPDUCUR=1 + fi + echo "$TXMPDUINAMPDUCUR $TXAMPDUCUR" | awk '{printf "MPDU in AMPDU : %0.1f \n", $1/$2}' + printf "Bytes in AMPDU : %0d\n" $(($TXOCTECTINAMPDUCUR/$TXAMPDUCUR)) + printf "AMPDU Throughput : %0.1fMbps\n" $((8*$TXOCTECTINAMPDUCUR/1000000)) + + + + RXBW20CUR=$((0x$RXBW20NEW - 0x$RXBW20)) + RXBW40CUR=$((0x$RXBW40NEW - 0x$RXBW40)) + RXBW80CUR=$((0x$RXBW80NEW - 0x$RXBW80)) + RXBW160CUR=$((0x$RXBW160NEW - 0x$RXBW160)) + + RXAMPDUCUR=$((0x$RXAMPDUNEW - 0x$RXAMPDU)) + RXMPDUINAMPDUCUR=$((0x$RXMPDUINAMPDUNEW - 0x$RXMPDUINAMPDU)) + RXOCTECTINAMPDUCUR=$((0x$RXOCTECTINAMPDUNEW - 0x$RXOCTECTINAMPDU)) + + FCSERRCUR=$((0x$FCSERRORNEW - 0x$FCSERROR)) + PHYERRCUR=$((0x$PHYERRORNEW - 0x$PHYERROR)) + RXFLOWCCUR=$((0x$RXFLOWCNEW - 0x$RXFLOWC)) + RXTOT=$(($RXBW40CUR + $RXBW20CUR + $RXBW80CUR + $RXBW160CUR + $FCSERRCUR + $PHYERRCUR + $RXFLOWCCUR)) + + if [ $RXTOT == 0 ] + then + RXTOT=1 + fi + + printf "\nRX\n" + printf "20MHz : %0d (%0d %%)\n" $RXBW20CUR $((100*$RXBW20CUR/$RXTOT)) + printf "40MHz : %0d (%0d %%)\n" $RXBW40CUR $((100*$RXBW40CUR/$RXTOT)) + printf "80MHz : %0d (%0d %%)\n" $RXBW80CUR $((100*$RXBW80CUR/$RXTOT)) + printf "160MHz : %0d (%0d %%)\n" $RXBW160CUR $((100*$RXBW160CUR/$RXTOT)) + + printf "AMPDU : %0d (%0d %%)\n" $RXAMPDUCUR $((100*$RXAMPDUCUR/$RXTOT)) + if [ $RXAMPDUCUR == 0 ] + then + RXAMPDUCUR=1 + fi + echo "$RXMPDUINAMPDUCUR $RXAMPDUCUR" | awk '{printf "MPDU in AMPDU : %0.1f \n", $1/$2}' + printf "Bytes in AMPDU : %0d\n" $(($RXOCTECTINAMPDUCUR/$RXAMPDUCUR)) + printf "AMPDU Throughput : %0.1fMbps\n" $((8*$RXOCTECTINAMPDUCUR/1000000)) + + printf "FCSErr : %0d (%0d %%)\n" $FCSERRCUR $((100*$FCSERRCUR/$RXTOT)) + printf "PHYErr : %0d (%0d %%)\n" $PHYERRCUR $((100*$PHYERRCUR/$RXTOT)) + printf "RxFlowErr: %0d (%0d %%)\n" $RXFLOWCCUR $((100*$RXFLOWCCUR/$RXTOT)) + printf "CCAPrim Busy : %3d %%\n" $((0x$CCAPRI / 10000)) + printf "CCASec20 Busy : %3d %%\n" $((0x$CCASEC20 / 10000)) + printf "CCASec40 Busy : %3d %%\n" $((0x$CCASEC40 / 10000)) + printf "CCASec80 Busy : %3d %%\n" $((0x$CCASEC80 / 10000)) + printf "\n" +} +*/ + +#endif // _RX_SENSITIVITY_H_ + diff --git a/beken_os/beken378/func/rf_test/tx_evm.c b/beken_os/beken378/func/rf_test/tx_evm.c new file mode 100755 index 0000000..3e44e4c --- /dev/null +++ b/beken_os/beken378/func/rf_test/tx_evm.c @@ -0,0 +1,470 @@ +#include "include.h" +#include "tx_evm_pub.h" +#include "tx_evm.h" + +#include "mac_phy_bypass_pub.h" +#include "uart_pub.h" +#if ((CFG_SOC_NAME != SOC_BK7231) && (CFG_SUPPORT_BLE == 1)) +#include "ble_pub.h" +#endif +#include "icu_pub.h" +#include "sys_ctrl_pub.h" +#include "reg_rc.h" + +#include "mac.h" +#include "phy.h" +#include "hal_machw.h" +#include "me.h" +#include "mm.h" +#include "ke_task.h" +#include "vif_mgmt.h" + +#include "drv_model_pub.h" +#include "target_util_pub.h" +#include "ke_event.h" + +#include "arm_arch.h" +#include "rtos_pub.h" + +#if CFG_TX_EVM_TEST +#define TX_2_4_G_CHANNEL_NUM (14) +#define EVM_MAC_PKT_CNT_UNLIMITED (0xFFFFFFFF) + +UINT32 evm_mac_pkt_count = 0; +UINT32 evm_mac_pkt_max = EVM_MAC_PKT_CNT_UNLIMITED; +UINT32 evm_channel = EVM_DEFAULT_CHANNEL; +UINT32 evm_bandwidth = PHY_CHNL_BW_20; +UINT32 evm_rate = HW_RATE_1MBPS; +UINT32 evm_modul_format = FORMATMOD_NON_HT; +UINT32 evm_guard_i_tpye = 0; // LONG_GI; +UINT32 evm_pwr_idx = 0; +UINT32 evm_test_via_mac_flag = 0; + +struct mac_addr const evm_mac_addr = { + {0x7112, 0x7111, 0x7111} + }; + +const UINT16 tx_freq_2_4_G[TX_2_4_G_CHANNEL_NUM] = { + 2412, + 2417, + 2422, + 2427, + 2432, + 2437, + 2442, + 2447, + 2452, + 2457, + 2462, + 2467, + 2472, + 2484 +}; + +void evm_bypass_set_single_carrier(SC_TYPE_T type, UINT32 rate) +{ + UINT32 reg; + + reg = REG_READ((REG_RC_BASE_ADDR+0x00*4)); // RC_BEKEN_0x0 [31] : 1 + reg |= (1u<<31); + REG_WRITE((REG_RC_BASE_ADDR+0x00*4),reg); + + reg = REG_READ((REG_RC_BASE_ADDR+0x4c*4)); // RC_BEKEN_0x4c [31:30] : 1 + reg &= ~(0x3u<<30); + reg |= (0x1u<<30); +#if (CFG_SOC_NAME == SOC_BK7231N) + reg &= ~(0xFFFu<<0); + reg &= ~(0xFFFu<<16); +#else + reg &= ~(0x3FFu<<0); + reg &= ~(0x3FFu<<16); +#endif + if(type == SINGLE_CARRIER_11B) + { +#if (CFG_SOC_NAME == SOC_BK7231N) + reg |= (0x380u << 0); + reg |= (0x380u << 16); +#else + reg |= (0x118u << 0); + reg |= (0x118u << 16); +#endif + } + else if(type == SINGLE_CARRIER_11G) + { +#if (CFG_SOC_NAME == SOC_BK7231N) + if ((rate >= 128) && (evm_bandwidth == PHY_CHNL_BW_40)) + { + reg |= (0x658u << 0); + reg |= (0x658u << 16); + } + else + { + reg |= (0x627u << 0); + reg |= (0x627u << 16); + } +#else + reg |= (0x1A8u << 0); + reg |= (0x1A8u << 16); +#endif + } + else + { + reg |= (0xDDu << 0); + reg |= (0xDDu << 16); + } + REG_WRITE((REG_RC_BASE_ADDR+0x4c*4),reg); + +} + +void evm_bypass_mac_init(UINT32 channel, UINT32 bandwidth) +{ + struct phy_cfg_tag cfg; + /*reset mm*/ + EVM_PRT("[EVM]reset_mm\r\n"); + hal_machw_stop(); + phy_stop(); + me_init(); + mm_init(); + ke_state_set(TASK_MM, MM_IDLE); + + /*start mm*/ + EVM_PRT("[EVM]phy init\r\n"); + cfg.parameters[0] = 1; + cfg.parameters[1] = 0; + phy_init(&cfg); + + EVM_PRT("[EVM]set channel:%d\r\n", channel); + phy_set_channel(PHY_BAND_2G4, bandwidth, channel, channel, 0, PHY_PRIM); + + /* Put the HW in active state*/ + mm_active(); + + /*disable rx*/ + nxmac_rx_cntrl_set(0); +} + +void evm_init(UINT32 channel, UINT32 bandwidth) +{ + BOOL p2p = 0; + UINT8 vif_idx; + UINT8 vif_type = 2; + struct phy_cfg_tag cfg; + + /*reset mm*/ + EVM_PRT("[EVM]reset_mm\r\n"); + hal_machw_stop(); + phy_stop(); + me_init(); + mm_init(); + ke_state_set(TASK_MM, MM_IDLE); + + /*config me*/ + EVM_PRT("[EVM]config_me\r\n"); + + /*config me channel*/ + EVM_PRT("[EVM]config_me_channel\r\n"); + + /*start mm*/ + EVM_PRT("[EVM]start_mm\r\n"); + cfg.parameters[0] = 1; + cfg.parameters[1] = 0; + phy_init(&cfg); + + phy_set_channel(PHY_BAND_2G4, bandwidth, channel, channel, 0, PHY_PRIM); + + /*add mm interface*/ + EVM_PRT("[EVM]add_mm_interface\r\n"); + vif_mgmt_register(&evm_mac_addr, vif_type, p2p, &vif_idx); + + /* Put the HW in active state*/ + mm_active(); + + /*disable rx*/ + nxmac_rx_cntrl_set(0); +} + +UINT32 evm_bypass_mac_set_tx_data_length(UINT32 modul_format, UINT32 len, UINT32 rate, UINT32 bandwidth, UINT32 need_change) +{ + UINT32 ret, is_legacy_mode = 1; + UINT32 param; + + if (0)//(need_change) + { + if(bandwidth == 0) + { + if ((1 == rate)||(2 == rate)||(5 == rate)||(6 == rate)||(128 == rate)) + { + len = 1024; + } + } + else + { + if ((128 == rate)||(129 == rate)||(130 == rate)||(131 == rate)) + { + len = 1024; + } + } + } + + if(modul_format >= 0x02) // 0x2: HT-MM; 0x3: HT-GF + is_legacy_mode = 0; + + if(is_legacy_mode) + { + if(len > TX_LEGACY_DATA_LEN_MASK) + len = TX_LEGACY_DATA_LEN_MASK; + + param = len; + ret = sddev_control(MPB_DEV_NAME, MCMD_TX_LEGACY_SET_LEN, ¶m); + } + else + { + if(len > TX_HT_VHT_DATA_LEN_MASK) + len = TX_HT_VHT_DATA_LEN_MASK; + + param = len; + ret = sddev_control(MPB_DEV_NAME, MCMD_TX_HT_VHT_SET_LEN, ¶m); + } + + EVM_PRT("[EVM]tx_mode_bypass_mac_set_length:%d, %d\r\n", modul_format, len); + + return ret; +} + +UINT32 evm_bypass_mac_set_rate_mformat(UINT32 ppdu_rate, UINT32 m_format) +{ + UINT32 ret; + MBPS_TXS_MFR_ST param; + + param.mod_format = m_format; + param.rate = ppdu_rate; + + ret = sddev_control(MPB_DEV_NAME, MCMD_BYPASS_TX_SET_RATE_MFORMAT, ¶m); + + EVM_PRT("[EVM]tx_mode_bypass_mac_set_rate:%d, modf:%d\r\n", ppdu_rate, m_format); + + return ret; +} + +UINT32 evm_bypass_mac_set_txdelay(UINT32 delay_us) +{ + UINT32 ret, param; + + param = delay_us; + ret = sddev_control(MPB_DEV_NAME, MCMD_SET_TXDELAY, ¶m); + + EVM_PRT("[EVM]tx_mode_bypass_mac_set_txdelay:%d us\r\n", param); + + return ret; +} + +void evm_bypass_mac_set_channel(UINT32 channel) +{ + channel = tx_freq_2_4_G[channel - 1]; + + evm_channel = channel; +} + +void evm_set_bandwidth(UINT32 bandwidth) +{ + UINT32 param; + + if(bandwidth >= PHY_CHNL_BW_80) + return; + + evm_bandwidth = bandwidth; + param = evm_bandwidth; + sddev_control(MPB_DEV_NAME, MCMD_SET_BANDWIDTH, ¶m); +} + +void evm_bypass_mac_set_guard_i_type(UINT32 gi_tpye) +{ + UINT32 param; + + if(gi_tpye > 2) + return; + + param = gi_tpye; + sddev_control(MPB_DEV_NAME, MCMD_SET_GI, ¶m); +} + + +void evm_bypass_mac(void) +{ + sddev_control(MPB_DEV_NAME, MCMD_TX_MODE_BYPASS_MAC, 0); + EVM_PRT("[EVM]tx_mode_bypass_mac\r\n"); +} + +void evm_stop_bypass_mac(void) +{ + UINT32 reg; + + reg = REG_READ((REG_RC_BASE_ADDR+0x00*4)); // RC_BEKEN_0x0 [31] : 0 + reg &= ~(1u<<31); + REG_WRITE((REG_RC_BASE_ADDR+0x00*4),reg); + + reg = REG_READ((REG_RC_BASE_ADDR+0x4c*4)); // RC_BEKEN_0x4c [31:30] : 0 + reg &= ~(0x3u<<30); + REG_WRITE((REG_RC_BASE_ADDR+0x4c*4),reg); + sddev_control(MPB_DEV_NAME, MCMD_STOP_BYPASS_MAC, 0); + EVM_PRT("[EVM]tx_mode_stop_bypass_mac\r\n"); +} + +void evm_start_bypass_mac(void) +{ + //EVM_PRT("[EVM]tx_mode_stop_bypass_mac\r\n"); + sddev_control(MPB_DEV_NAME, MCMD_START_BYPASS_MAC, 0); +} + +void evm_bypass_mac_test(void) +{ + evm_bypass_mac_init(evm_channel, evm_bandwidth); + + evm_bypass_mac(); + EVM_PRT("[EVM]test_bypass_mac\r\n"); +} + +void evm_bypass_ble_test_start(UINT32 channel) +{ +#if ((CFG_SOC_NAME != SOC_BK7231) && (CFG_SUPPORT_BLE == 1)) + UINT32 param; + param = PWD_BLE_CLK_BIT; + + UINT32 reg; + + reg = REG_READ((REG_RC_BASE_ADDR+0x00*4)); // RC_BEKEN_0x0 [31] : 0 + reg &= ~(1u<<31); + REG_WRITE((REG_RC_BASE_ADDR+0x00*4),reg); + + reg = REG_READ((REG_RC_BASE_ADDR+0x4c*4)); // RC_BEKEN_0x4c [31:30] : 0 + reg &= ~(0x3u<<30); + REG_WRITE((REG_RC_BASE_ADDR+0x4c*4),reg); + + sddev_control(SCTRL_DEV_NAME, CMD_BLE_RF_BIT_SET, NULL); + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_BLE_POWERUP, NULL); + sddev_control(ICU_DEV_NAME, CMD_TL410_CLK_PWR_UP, ¶m); + + param = 0x3ba7a940; + sddev_control(BLE_DEV_NAME, CMD_BLE_SET_GFSK_SYNCWD, ¶m); + sddev_control(BLE_DEV_NAME, CMD_BLE_AUTO_CHANNEL_DISABLE, NULL); + sddev_control(BLE_DEV_NAME, CMD_BLE_AUTO_SYNCWD_DISABLE, NULL); + + if(channel < 2400) + { + channel = 2400; + } + param = (channel - 2400) & 0x7F; + sddev_control(BLE_DEV_NAME, CMD_BLE_SET_CHANNEL, ¶m); + param = PN9_TX; + sddev_control(BLE_DEV_NAME, CMD_BLE_SET_PN9_TRX, ¶m); +#endif +} + +void evm_bypass_ble_test_stop(void) +{ +#if ((CFG_SOC_NAME != SOC_BK7231) && (CFG_SUPPORT_BLE == 1)) + UINT32 reg; + + reg = REG_READ((REG_RC_BASE_ADDR+0x00*4)); // RC_BEKEN_0x0 [31] : 0 + reg &= ~(1u<<31); + REG_WRITE((REG_RC_BASE_ADDR+0x00*4),reg); + + reg = REG_READ((REG_RC_BASE_ADDR+0x4c*4)); // RC_BEKEN_0x4c [31:30] : 0 + reg &= ~(0x3u<<30); + REG_WRITE((REG_RC_BASE_ADDR+0x4c*4),reg); + + sddev_control(SCTRL_DEV_NAME, CMD_BLE_RF_BIT_CLR, NULL); + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_BLE_POWERDOWN, NULL); +#endif +} + +void evm_via_mac_evt(int dummy) +{ + ke_evt_clear(KE_EVT_EVM_MAC_BIT); + + if(evm_mac_pkt_max == EVM_MAC_PKT_CNT_UNLIMITED) + { + rtos_delay_milliseconds(10); + // un limited, send forever + evm_req_tx(&evm_mac_addr); + } + else + { + if(evm_mac_pkt_count < evm_mac_pkt_max) + { + evm_req_tx(&evm_mac_addr); + } + else + { + evm_test_via_mac_flag = 0; + EVM_PRT("[EVM]test by mac cnt to max, stop:%d\r\n", evm_mac_pkt_max); + } + evm_mac_pkt_count ++; + } +} + +uint32_t evm_via_mac_is_start(void) +{ + return evm_test_via_mac_flag; +} + +void evm_via_mac_init(void) +{ + evm_init(evm_channel, evm_bandwidth); +} + +void evm_via_mac_begin(void) +{ + evm_test_via_mac_flag = 1; + evm_via_mac_evt(0); +} + +void evm_via_mac_continue(void) +{ + if(0 == evm_test_via_mac_flag) + { + return; + } + + ke_evt_set(KE_EVT_EVM_MAC_BIT); +} + +void evm_via_mac_set_rate(HW_RATE_E rate, uint32_t modul_format, uint32_t guard_i_tpye) +{ + evm_rate = rate; + evm_modul_format = modul_format; + evm_guard_i_tpye = guard_i_tpye; + + EVM_PRT("[EVM]test by mac, rate:%d, m:%d, gi:%d\r\n", rate, modul_format, guard_i_tpye); +} + +void evm_via_mac_set_channel(UINT32 channel) +{ + channel = tx_freq_2_4_G[channel - 1]; + evm_channel = channel; + + //evm_via_mac_begin(); +} + +void evm_via_mac_set_power(UINT32 pwr_idx) +{ + evm_pwr_idx = pwr_idx; +} + +void evm_via_mac_set_bandwidth(UINT32 bandwidth) +{ + if(bandwidth >= PHY_CHNL_BW_80) + return; + + evm_bandwidth = bandwidth; +} + +#else + +void evm_via_mac_evt(int dummy) +{ +} + +#endif // CFG_TX_EVM_TEST +// eof + diff --git a/beken_os/beken378/func/rf_test/tx_evm.h b/beken_os/beken378/func/rf_test/tx_evm.h new file mode 100755 index 0000000..177e670 --- /dev/null +++ b/beken_os/beken378/func/rf_test/tx_evm.h @@ -0,0 +1,24 @@ +#ifndef _TX_EVM_H_ +#define _TX_EVM_H_ + +#define EVM_DEBUG + +#ifdef EVM_DEBUG +#define EVM_PRT os_printf +#define EVM_WPRT warning_prf +#else +#define EVM_PRT os_null_printf +#define EVM_WPRT os_null_printf +#endif + +#define EVM_DEFAULT_CHANNEL 2437 + +/******************************************************************************* +* Function Declarations +*******************************************************************************/ +void evm_bypass_mac(void); +uint32_t evm_via_mac_is_start(void); + +#endif // _TX_EVM_H_ +// eof + diff --git a/beken_os/beken378/func/rwnx_intf/rw_ieee80211.c b/beken_os/beken378/func/rwnx_intf/rw_ieee80211.c new file mode 100755 index 0000000..df94545 --- /dev/null +++ b/beken_os/beken378/func/rwnx_intf/rw_ieee80211.c @@ -0,0 +1,316 @@ +#include "include.h" +#include "rw_ieee80211.h" +#include "rw_pub.h" +#include "rwnx.h" +#include "rw_msdu.h" +#include "mem_pub.h" + +typedef struct _wifi_cn_code_st_ +{ + UINT32 init; + wifi_country_t cfg; +} WIFI_CN_ST, *WIFI_CN_PTR; + +WIFI_CN_ST g_country_code = {0}; + +#define COUNTRY_CODE_CN {.cc= "CN", .schan=1, .nchan=13, .max_tx_power=0, .policy=WIFI_COUNTRY_POLICY_MANUAL}; +#define COUNTRY_CODE_US {.cc= "US", .schan=1, .nchan=11, .max_tx_power=0, .policy=WIFI_COUNTRY_POLICY_MANUAL}; +#define COUNTRY_CODE_EP {.cc= "EP", .schan=1, .nchan=13, .max_tx_power=0, .policy=WIFI_COUNTRY_POLICY_MANUAL}; +#define COUNTRY_CODE_JP {.cc= "JP", .schan=1, .nchan=14, .max_tx_power=0, .policy=WIFI_COUNTRY_POLICY_MANUAL}; +#define COUNTRY_CODE_AU {.cc= "AU", .schan=1, .nchan=13, .max_tx_power=0, .policy=WIFI_COUNTRY_POLICY_MANUAL}; + +const static struct ieee80211_channel rw_2ghz_channels[] = +{ + CHAN2G(1, 2412, 0), + CHAN2G(2, 2417, 0), + CHAN2G(3, 2422, 0), + CHAN2G(4, 2427, 0), + CHAN2G(5, 2432, 0), + CHAN2G(6, 2437, 0), + CHAN2G(7, 2442, 0), + CHAN2G(8, 2447, 0), + CHAN2G(9, 2452, 0), + CHAN2G(10, 2457, 0), + CHAN2G(11, 2462, 0), + CHAN2G(12, 2467, 0), + CHAN2G(13, 2472, 0), + CHAN2G(14, 2484, 0), +}; + + +#ifdef ENABLE_5GHZ_IEEE80211 +static struct ieee80211_channel rw_5ghz_a_channels[] = +{ + CHAN5G(34, 0), + CHAN5G(36, 0), + CHAN5G(38, 0), + CHAN5G(40, 0), + CHAN5G(42, 0), + CHAN5G(44, 0), + CHAN5G(46, 0), + CHAN5G(48, 0), + CHAN5G(52, 0), + CHAN5G(56, 0), + CHAN5G(60, 0), + CHAN5G(64, 0), + CHAN5G(100, 0), + CHAN5G(104, 0), + CHAN5G(108, 0), + CHAN5G(112, 0), + CHAN5G(116, 0), + CHAN5G(120, 0), + CHAN5G(124, 0), + CHAN5G(128, 0), + CHAN5G(132, 0), + CHAN5G(136, 0), + CHAN5G(140, 0), + CHAN5G(149, 0), + CHAN5G(153, 0), + CHAN5G(157, 0), + CHAN5G(161, 0), + CHAN5G(165, 0), + CHAN5G(184, 0), + CHAN5G(188, 0), + CHAN5G(192, 0), + CHAN5G(196, 0), + CHAN5G(200, 0), + CHAN5G(204, 0), + CHAN5G(208, 0), + CHAN5G(212, 0), + CHAN5G(216, 0), +}; +#endif + +WIPHY_T g_wiphy; +const UINT8 beacon[149] = +{ + 128, 0, 0, 0, 255, 255, 255, 255, 255, 255, 18, 113, 17, 113, 11, 113, + 18, 113, 17, 113, 11, 113, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 100, 0, 49, 4, 0, 5, 74, 73, 69, 87, 85, 1, 8, 130, 132, 139, // 49 33 + 150, 12, 18, 24, 36, 3, 1, 6, 5, 4, 0, 2, 0, 0, 42, 1, // 6 --> chan_connect + 0, 50, 4, 48, 72, 96, 108, 45, 26, 12, 0, 27, 255, 0, 0, 0, + 1, 0, 0, 0, 0, 0, 150, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 61, 22, 8, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 221, 24, 0, 80, 242, + 2, 1, 1, 0, 0, 3, 164, 0, 0, 39, 164, 0, 0, 66, 67, 94, + 0, 98, 50, 47, 0 +}; + +UINT32 rw_ieee80211_init(void) +{ + RW_CONNECTOR_T intf; + struct ieee80211_sta_ht_cap ht_cap = RWNX_HT_CAPABILITIES; + struct ieee80211_sta_vht_cap vht_cap = RWNX_VHT_CAPABILITIES; + + g_wiphy.bands[IEEE80211_BAND_2GHZ].num_channels = sizeof(rw_2ghz_channels) / + sizeof(rw_2ghz_channels[0]); + g_wiphy.bands[IEEE80211_BAND_2GHZ].channels = (struct ieee80211_channel *)rw_2ghz_channels; + g_wiphy.bands[IEEE80211_BAND_2GHZ].ht_cap = ht_cap; + +#ifdef ENABLE_5GHZ_IEEE80211 + g_wiphy.bands[IEEE80211_BAND_5GHZ].num_channels = sizeof(rw_5ghz_a_channels) / + sizeof(rw_5ghz_a_channels[0]); + g_wiphy.bands[IEEE80211_BAND_5GHZ].channels = rw_5ghz_a_channels; +#else + g_wiphy.bands[IEEE80211_BAND_5GHZ].num_channels = 0; + g_wiphy.bands[IEEE80211_BAND_5GHZ].channels = 0; +#endif + g_wiphy.bands[IEEE80211_BAND_5GHZ].ht_cap = ht_cap; + g_wiphy.bands[IEEE80211_BAND_5GHZ].vht_cap = vht_cap; + + g_wiphy.bands[IEEE80211_BAND_60GHZ].num_channels = 0; + g_wiphy.bands[IEEE80211_BAND_60GHZ].channels = 0; + + intf.msg_outbound_func = mr_kmsg_fwd; + intf.data_outbound_func = rwm_upload_data; + intf.rx_alloc_func = rwm_get_rx_free_node; + intf.get_rx_valid_status_func = rwm_get_rx_valid; + intf.tx_confirm_func = rwm_tx_confirm; + + rwnxl_register_connector(&intf); + + g_country_code.cfg.cc[0] = 'C'; + g_country_code.cfg.cc[1] = 'N'; + g_country_code.cfg.cc[2] = 0; + g_country_code.cfg.schan = 1; + g_country_code.cfg.nchan = 13; + g_country_code.cfg.max_tx_power = 0; + g_country_code.cfg.policy = WIFI_COUNTRY_POLICY_MANUAL; + + g_country_code.init = 1; + + return 0; +} + +UINT32 rw_ieee80211_set_country(const wifi_country_t *country) +{ + if(country) + { + UINT32 prev_policy; + + if(g_country_code.init == 0) + return kNotInitializedErr; + + prev_policy = g_country_code.cfg.policy; + + os_memcpy(&g_country_code.cfg, country, sizeof(wifi_country_t)); + os_printf("rw_ieee80211_set_country code:\r\n"); + os_printf("code: %s\r\n", g_country_code.cfg.cc); + os_printf("channel: %d - %d\r\n", g_country_code.cfg.schan, + g_country_code.cfg.schan + g_country_code.cfg.nchan - 1); + + if(g_country_code.cfg.policy == WIFI_COUNTRY_POLICY_MANUAL) + os_printf("mode: MANUAL\r\n", g_country_code.cfg.policy ); + else + { + os_printf("mode: AUTO\r\n", g_country_code.cfg.policy ); + if(prev_policy != g_country_code.cfg.policy) + { + os_printf("in auto mode, need change softap beacon\r\n"); + // to do + } + } + + return kNoErr; + } + else + { + return kParamErr; + } +} + +UINT32 rw_ieee80211_get_country(wifi_country_t *country) +{ + if(country) + { + if(g_country_code.init == 0) + return kNotInitializedErr; + + os_memcpy(country, &g_country_code.cfg, sizeof(wifi_country_t)); + + return kNoErr; + } + else + { + return kParamErr; + } +} + +UINT32 rw_ieee80211_get_centre_frequency(UINT32 chan_id) +{ + UINT32 freq = 0; + struct ieee80211_channel *channels = NULL; + + if((chan_id >= 1) && (chan_id <= 14)) + { + channels = (struct ieee80211_channel *)rw_2ghz_channels; + } + +#ifdef ENABLE_5GHZ_IEEE80211 + if(chan_id > 14) + { + } +#endif + + if(channels) + { + freq = channels[chan_id - 1].center_freq; + } + + ASSERT(freq); + return freq; +} + +UINT8 rw_ieee80211_get_chan_id(UINT32 freq) +{ + int i; + struct ieee80211_channel *channels = NULL; + + channels = (struct ieee80211_channel *)rw_2ghz_channels; + for(i = 0; i < 14; i++) + { + if(channels[i].center_freq == freq) + { + break; + } + } + + if(i == 14) + { + return 0; + } + + return i + 1; +} + +UINT8 rw_ieee80211_init_scan_chan(struct scanu_start_req *req) +{ + UINT32 i, start_chan, num_chan; + + ASSERT(g_country_code.init); + ASSERT(req); + + start_chan = g_country_code.cfg.schan; + + if(g_country_code.cfg.policy == WIFI_COUNTRY_POLICY_MANUAL) + num_chan = g_country_code.cfg.nchan; + else { + // auto mode, sta need scan all channel + num_chan = g_wiphy.bands[IEEE80211_BAND_2GHZ].num_channels; + } + + for(i = 0; i < num_chan; i ++) + { + req->chan[i].band = IEEE80211_BAND_2GHZ; + req->chan[i].flags = 0; + req->chan[i].freq = rw_ieee80211_get_centre_frequency(i + start_chan); + } + +#ifdef ENABLE_5GHZ_IEEE80211 + for(i = 0; i < g_wiphy.bands[IEEE80211_BAND_5GHZ].num_channels; i ++) + { + req->chan[i].band = IEEE80211_BAND_5GHZ; + req->chan[i].flags = 0; + req->chan[i].freq = rw_ieee80211_get_centre_frequency(i + + SCAN_CHANNEL_2G4 + + start_chan); + + ASSERT(req->chan[i].freq); + } +#endif + + req->chan_cnt = num_chan; + + return 0; +} + +UINT8 rw_ieee80211_is_scan_rst_in_countrycode(UINT8 freq) +{ + UINT32 start_chan, end_chan; + + ASSERT(g_country_code.init); + + if(g_country_code.cfg.policy != WIFI_COUNTRY_POLICY_MANUAL) + { + // auto mode, sta need scan all channel, and get all rst + return 1; + } + + start_chan = g_country_code.cfg.schan; + end_chan = (start_chan + g_country_code.cfg.nchan - 1); + + if((freq < start_chan) || (freq > end_chan)) + return 0; + + return 1; +} + +#if CFG_IEEE80211N +void rw_ieee80211_set_ht_cap(UINT8 ht_supp) +{ + g_wiphy.bands[IEEE80211_BAND_2GHZ].ht_cap.ht_supported = ht_supp; + rw_msg_send_me_config_req(); +} +#endif + +// eof diff --git a/beken_os/beken378/func/rwnx_intf/rw_ieee80211.h b/beken_os/beken378/func/rwnx_intf/rw_ieee80211.h new file mode 100755 index 0000000..1b267b0 --- /dev/null +++ b/beken_os/beken378/func/rwnx_intf/rw_ieee80211.h @@ -0,0 +1,429 @@ +#ifndef _RW_IEEE80211_H_ +#define _RW_IEEE80211_H_ + +#ifndef ETH_P_PAE +#define ETH_P_PAE 0x888E /* Port Access Entity (IEEE 802.1X) */ +#endif /* ETH_P_PAE */ + +#define ETH_P_PREAUTH 0x88C7 /* IEEE 802.11i pre-authentication */ + +#define ETH_P_ECONET 0x0018 + +#ifndef ETH_P_80211_RAW +#define ETH_P_80211_RAW (ETH_P_ECONET + 1) +#endif + +#define CHAN2G(_channel, _freq, _flags) { \ + .band = IEEE80211_BAND_2GHZ, \ + .hw_value = (_channel), \ + .center_freq = (_freq), \ + .flags = (_flags), \ + .max_antenna_gain = 0, \ + .max_power = 30, \ +} + +#define CHAN5G(_channel, _flags) { \ + .band = IEEE80211_BAND_5GHZ, \ + .hw_value = (_channel), \ + .center_freq = 5000 + (5 * (_channel)), \ + .flags = (_flags), \ + .max_antenna_gain = 0, \ + .max_power = 30, \ +} + + +/* 802.11n HT capabilities masks (for cap_info) */ +#define IEEE80211_HT_CAP_LDPC_CODING 0x0001 +#define IEEE80211_HT_CAP_SUP_WIDTH_20_40 0x0002 +#define IEEE80211_HT_CAP_SM_PS 0x000C +#define IEEE80211_HT_CAP_SM_PS_SHIFT 2 +#define IEEE80211_HT_CAP_GRN_FLD 0x0010 +#define IEEE80211_HT_CAP_SGI_20 0x0020 +#define IEEE80211_HT_CAP_SGI_40 0x0040 +#define IEEE80211_HT_CAP_TX_STBC 0x0080 +#define IEEE80211_HT_CAP_RX_STBC 0x0300 +#define IEEE80211_HT_CAP_RX_STBC_SHIFT 8 +#define IEEE80211_HT_CAP_DELAY_BA 0x0400 +#define IEEE80211_HT_CAP_MAX_AMSDU 0x0800 +#define IEEE80211_HT_CAP_DSSSCCK40 0x1000 +#define IEEE80211_HT_CAP_RESERVED 0x2000 +#define IEEE80211_HT_CAP_40MHZ_INTOLERANT 0x4000 +#define IEEE80211_HT_CAP_LSIG_TXOP_PROT 0x8000 + +/* 802.11n HT extended capabilities masks (for extended_ht_cap_info) */ +#define IEEE80211_HT_EXT_CAP_PCO 0x0001 +#define IEEE80211_HT_EXT_CAP_PCO_TIME 0x0006 +#define IEEE80211_HT_EXT_CAP_PCO_TIME_SHIFT 1 +#define IEEE80211_HT_EXT_CAP_MCS_FB 0x0300 +#define IEEE80211_HT_EXT_CAP_MCS_FB_SHIFT 8 +#define IEEE80211_HT_EXT_CAP_HTC_SUP 0x0400 +#define IEEE80211_HT_EXT_CAP_RD_RESPONDER 0x0800 + +/* 802.11n HT capability AMPDU settings (for ampdu_params_info) */ +#define IEEE80211_HT_AMPDU_PARM_FACTOR 0x03 +#define IEEE80211_HT_AMPDU_PARM_DENSITY 0x1C +#define IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT 2 + +/* + * Maximum length of AMPDU that the STA can receive in high-throughput (HT). + * Length = 2 ^ (13 + max_ampdu_length_exp) - 1 (octets) + */ +enum ieee80211_max_ampdu_length_exp +{ + IEEE80211_HT_MAX_AMPDU_8K = 0, + IEEE80211_HT_MAX_AMPDU_16K = 1, + IEEE80211_HT_MAX_AMPDU_32K = 2, + IEEE80211_HT_MAX_AMPDU_64K = 3 +}; + +/* + * Maximum length of AMPDU that the STA can receive in VHT. + * Length = 2 ^ (13 + max_ampdu_length_exp) - 1 (octets) + */ +enum ieee80211_vht_max_ampdu_length_exp +{ + IEEE80211_VHT_MAX_AMPDU_8K = 0, + IEEE80211_VHT_MAX_AMPDU_16K = 1, + IEEE80211_VHT_MAX_AMPDU_32K = 2, + IEEE80211_VHT_MAX_AMPDU_64K = 3, + IEEE80211_VHT_MAX_AMPDU_128K = 4, + IEEE80211_VHT_MAX_AMPDU_256K = 5, + IEEE80211_VHT_MAX_AMPDU_512K = 6, + IEEE80211_VHT_MAX_AMPDU_1024K = 7 +}; + +#define IEEE80211_HT_MAX_AMPDU_FACTOR 13 + +/* Minimum MPDU start spacing */ +enum ieee80211_min_mpdu_spacing +{ + IEEE80211_HT_MPDU_DENSITY_NONE = 0, /* No restriction */ + IEEE80211_HT_MPDU_DENSITY_0_25 = 1, /* 1/4 usec */ + IEEE80211_HT_MPDU_DENSITY_0_5 = 2, /* 1/2 usec */ + IEEE80211_HT_MPDU_DENSITY_1 = 3, /* 1 usec */ + IEEE80211_HT_MPDU_DENSITY_2 = 4, /* 2 usec */ + IEEE80211_HT_MPDU_DENSITY_4 = 5, /* 4 usec */ + IEEE80211_HT_MPDU_DENSITY_8 = 6, /* 8 usec */ + IEEE80211_HT_MPDU_DENSITY_16 = 7 /* 16 usec */ +}; + +/* 802.11n HT capability MSC set */ +#define IEEE80211_HT_MCS_RX_HIGHEST_MASK 0x3ff +#define IEEE80211_HT_MCS_TX_DEFINED 0x01 +#define IEEE80211_HT_MCS_TX_RX_DIFF 0x02 + +/* value 0 == 1 stream etc */ +#define IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK 0x0C +#define IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT 2 +#define IEEE80211_HT_MCS_TX_MAX_STREAMS 4 +#define IEEE80211_HT_MCS_TX_UNEQUAL_MODULATION 0x10 + +/* + * 802.11n D5.0 20.3.5 / 20.6 says: + * - indices 0 to 7 and 32 are single spatial stream + * - 8 to 31 are multiple spatial streams using equal modulation + * [8..15 for two streams, 16..23 for three and 24..31 for four] + * - remainder are multiple spatial streams using unequal modulation + */ +#define IEEE80211_HT_MCS_UNEQUAL_MODULATION_START 33 +#define IEEE80211_HT_MCS_UNEQUAL_MODULATION_START_BYTE \ + (IEEE80211_HT_MCS_UNEQUAL_MODULATION_START / 8) + +#define RWNX_HT_CAPABILITIES \ +{ \ + .ht_supported = true, \ + .cap = 0x0f30, \ + .ampdu_factor = IEEE80211_HT_MAX_AMPDU_8K, \ + .ampdu_density = IEEE80211_HT_MPDU_DENSITY_16, \ + .mcs = { \ + .rx_mask = { 0xff, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, \ + .rx_highest = (0x100), \ + .tx_params = IEEE80211_HT_MCS_TX_DEFINED, \ + }, \ +} + +/* +HT Capabilities Info: 0x01ad + .... .... .... ...1 = HT LDPC coding capability: Transmitter supports receiving LDPC coded packets + .... .... .... ..0. = HT Support channel width: Transmitter only supports 20MHz operation + .... .... .... 11.. = HT SM Power Save: SM Power Save disabled (0x3) + .... .... ...0 .... = HT Green Field: Transmitter is not able to receive PPDUs with Green Field (GF) preamble + .... .... ..1. .... = HT Short GI for 20MHz: Supported + .... .... .0.. .... = HT Short GI for 40MHz: Not supported + .... .... 1... .... = HT Tx STBC: Supported + .... ..01 .... .... = HT Rx STBC: Rx support of one spatial stream (0x1) + .... .0.. .... .... = HT Delayed Block ACK: Transmitter does not support HT-Delayed BlockAck + .... 0... .... .... = HT Max A-MSDU length: 3839 bytes + ...0 .... .... .... = HT DSSS/CCK mode in 40MHz: Won't/Can't use of DSSS/CCK in 40 MHz + ..0. .... .... .... = HT PSMP Support: Won't/Can't support PSMP operation + .0.. .... .... .... = HT Forty MHz Intolerant: Use of 40 MHz transmissions unrestricted/allowed + 0... .... .... .... = HT L-SIG TXOP Protection support: Not supported +*/ + +/** + * enum ieee80211_channel_flags - channel flags + * + * Channel flags set by the regulatory control code. + * + * @IEEE80211_CHAN_DISABLED: This channel is disabled. + * @IEEE80211_CHAN_NO_IR: do not initiate radiation, this includes + * sending probe requests or beaconing. + * @IEEE80211_CHAN_RADAR: Radar detection is required on this channel. + * @IEEE80211_CHAN_NO_HT40PLUS: extension channel above this channel + * is not permitted. + * @IEEE80211_CHAN_NO_HT40MINUS: extension channel below this channel + * is not permitted. + * @IEEE80211_CHAN_NO_OFDM: OFDM is not allowed on this channel. + * @IEEE80211_CHAN_NO_80MHZ: If the driver supports 80 MHz on the band, + * this flag indicates that an 80 MHz channel cannot use this + * channel as the control or any of the secondary channels. + * This may be due to the driver or due to regulatory bandwidth + * restrictions. + * @IEEE80211_CHAN_NO_160MHZ: If the driver supports 160 MHz on the band, + * this flag indicates that an 160 MHz channel cannot use this + * channel as the control or any of the secondary channels. + * This may be due to the driver or due to regulatory bandwidth + * restrictions. + * @IEEE80211_CHAN_INDOOR_ONLY: see %NL80211_FREQUENCY_ATTR_INDOOR_ONLY + * @IEEE80211_CHAN_IR_CONCURRENT: see %NL80211_FREQUENCY_ATTR_IR_CONCURRENT + * @IEEE80211_CHAN_NO_20MHZ: 20 MHz bandwidth is not permitted + * on this channel. + * @IEEE80211_CHAN_NO_10MHZ: 10 MHz bandwidth is not permitted + * on this channel. + * + */ +enum ieee80211_channel_flags +{ + IEEE80211_CHAN_DISABLED = 1 << 0, + IEEE80211_CHAN_NO_IR = 1 << 1, + /* hole at 1<<2 */ + IEEE80211_CHAN_RADAR = 1 << 3, + IEEE80211_CHAN_NO_HT40PLUS = 1 << 4, + IEEE80211_CHAN_NO_HT40MINUS = 1 << 5, + IEEE80211_CHAN_NO_OFDM = 1 << 6, + IEEE80211_CHAN_NO_80MHZ = 1 << 7, + IEEE80211_CHAN_NO_160MHZ = 1 << 8, + IEEE80211_CHAN_INDOOR_ONLY = 1 << 9, + IEEE80211_CHAN_IR_CONCURRENT = 1 << 10, + IEEE80211_CHAN_NO_20MHZ = 1 << 11, + IEEE80211_CHAN_NO_10MHZ = 1 << 12, +}; + + +/** + * enum ieee80211_band - supported frequency bands + * + * The bands are assigned this way because the supported + * bitrates differ in these bands. + * + * @IEEE80211_BAND_2GHZ: 2.4GHz ISM band + * @IEEE80211_BAND_5GHZ: around 5GHz band (4.9-5.7) + * @IEEE80211_BAND_60GHZ: around 60 GHz band (58.32 - 64.80 GHz) + * @IEEE80211_NUM_BANDS: number of defined bands + */ +enum ieee80211_band +{ + IEEE80211_BAND_2GHZ = 0, + IEEE80211_BAND_5GHZ = 1, + IEEE80211_BAND_60GHZ = 2, + + /* keep last */ + IEEE80211_NUM_BANDS +}; + +struct ieee80211_channel +{ + enum ieee80211_band band; + UINT16 center_freq; + UINT16 hw_value; + UINT32 flags; + INT32 max_antenna_gain; + INT32 max_power; +}; + +#define IEEE80211_HT_MCS_MASK_LEN 10 + +/* 802.11ac VHT Capabilities */ +#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895 0x00000000 +#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991 0x00000001 +#define IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 0x00000002 +#define IEEE80211_VHT_CAP_MAX_MPDU_MASK 0x00000003 +#define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ 0x00000004 +#define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ 0x00000008 +#define IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK 0x0000000C +#define IEEE80211_VHT_CAP_RXLDPC 0x00000010 +#define IEEE80211_VHT_CAP_SHORT_GI_80 0x00000020 +#define IEEE80211_VHT_CAP_SHORT_GI_160 0x00000040 +#define IEEE80211_VHT_CAP_TXSTBC 0x00000080 +#define IEEE80211_VHT_CAP_RXSTBC_1 0x00000100 +#define IEEE80211_VHT_CAP_RXSTBC_2 0x00000200 +#define IEEE80211_VHT_CAP_RXSTBC_3 0x00000300 +#define IEEE80211_VHT_CAP_RXSTBC_4 0x00000400 +#define IEEE80211_VHT_CAP_RXSTBC_MASK 0x00000700 +#define IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE 0x00000800 +#define IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE 0x00001000 +#define IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT 13 +#define IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK \ + (7 << IEEE80211_VHT_CAP_BEAMFORMEE_STS_SHIFT) +#define IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT 16 +#define IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK \ + (7 << IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_SHIFT) +#define IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE 0x00080000 +#define IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE 0x00100000 +#define IEEE80211_VHT_CAP_VHT_TXOP_PS 0x00200000 +#define IEEE80211_VHT_CAP_HTC_VHT 0x00400000 +#define IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT 23 +#define IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_MASK \ + (7 << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT) +#define IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_UNSOL_MFB 0x08000000 +#define IEEE80211_VHT_CAP_VHT_LINK_ADAPTATION_VHT_MRQ_MFB 0x0c000000 +#define IEEE80211_VHT_CAP_RX_ANTENNA_PATTERN 0x10000000 +#define IEEE80211_VHT_CAP_TX_ANTENNA_PATTERN 0x20000000 + + +/** + * enum ieee80211_vht_mcs_support - VHT MCS support definitions + * @IEEE80211_VHT_MCS_SUPPORT_0_7: MCSes 0-7 are supported for the + * number of streams + * @IEEE80211_VHT_MCS_SUPPORT_0_8: MCSes 0-8 are supported + * @IEEE80211_VHT_MCS_SUPPORT_0_9: MCSes 0-9 are supported + * @IEEE80211_VHT_MCS_NOT_SUPPORTED: This number of streams isn't supported + * + * These definitions are used in each 2-bit subfield of the @rx_mcs_map + * and @tx_mcs_map fields of &struct ieee80211_vht_mcs_info, which are + * both split into 8 subfields by number of streams. These values indicate + * which MCSes are supported for the number of streams the value appears + * for. + */ +enum ieee80211_vht_mcs_support +{ + IEEE80211_VHT_MCS_SUPPORT_0_7 = 0, + IEEE80211_VHT_MCS_SUPPORT_0_8 = 1, + IEEE80211_VHT_MCS_SUPPORT_0_9 = 2, + IEEE80211_VHT_MCS_NOT_SUPPORTED = 3, +}; + +#define RWNX_VHT_CAPABILITIES \ +{ \ + .vht_supported = false, \ + .cap = \ + 3 << IEEE80211_VHT_CAP_MAX_A_MPDU_LENGTH_EXPONENT_SHIFT,\ + .vht_mcs = { \ + .rx_mcs_map = ( \ + IEEE80211_VHT_MCS_SUPPORT_0_9 << 0 | \ + IEEE80211_VHT_MCS_NOT_SUPPORTED << 2 | \ + IEEE80211_VHT_MCS_NOT_SUPPORTED << 4 | \ + IEEE80211_VHT_MCS_NOT_SUPPORTED << 6 | \ + IEEE80211_VHT_MCS_NOT_SUPPORTED << 8 | \ + IEEE80211_VHT_MCS_NOT_SUPPORTED << 10 | \ + IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 | \ + IEEE80211_VHT_MCS_NOT_SUPPORTED << 14), \ + .tx_mcs_map = ( \ + IEEE80211_VHT_MCS_SUPPORT_0_9 << 0 | \ + IEEE80211_VHT_MCS_NOT_SUPPORTED << 2 | \ + IEEE80211_VHT_MCS_NOT_SUPPORTED << 4 | \ + IEEE80211_VHT_MCS_NOT_SUPPORTED << 6 | \ + IEEE80211_VHT_MCS_NOT_SUPPORTED << 8 | \ + IEEE80211_VHT_MCS_NOT_SUPPORTED << 10 | \ + IEEE80211_VHT_MCS_NOT_SUPPORTED << 12 | \ + IEEE80211_VHT_MCS_NOT_SUPPORTED << 14), \ + } \ +} + +/** + * struct ieee80211_mcs_info - MCS information + * @rx_mask: RX mask + * @rx_highest: highest supported RX rate. If set represents + * the highest supported RX data rate in units of 1 Mbps. + * If this field is 0 this value should not be used to + * consider the highest RX data rate supported. + * @tx_params: TX parameters + */ +struct ieee80211_mcs_info +{ + UINT8 rx_mask[IEEE80211_HT_MCS_MASK_LEN]; + UINT16 rx_highest; + UINT8 tx_params; + UINT8 reserved[3]; +} __attribute__ ((packed)); + +/** + * struct ieee80211_sta_ht_cap - STA's HT capabilities + * + * This structure describes most essential parameters needed + * to describe 802.11n HT capabilities for an STA. + * + * @ht_supported: is HT supported by the STA + * @cap: HT capabilities map as described in 802.11n spec + * @ampdu_factor: Maximum A-MPDU length factor + * @ampdu_density: Minimum A-MPDU spacing + * @mcs: Supported MCS rates + */ +struct ieee80211_sta_ht_cap +{ + UINT16 cap; /* use IEEE80211_HT_CAP_ */ + UINT8 ht_supported; + UINT8 ampdu_factor; + UINT8 ampdu_density; + struct ieee80211_mcs_info mcs; +}; + +/** + * struct ieee80211_vht_mcs_info - VHT MCS information + * @rx_mcs_map: RX MCS map 2 bits for each stream, total 8 streams + * @rx_highest: Indicates highest long GI VHT PPDU data rate + * STA can receive. Rate expressed in units of 1 Mbps. + * If this field is 0 this value should not be used to + * consider the highest RX data rate supported. + * The top 3 bits of this field are reserved. + * @tx_mcs_map: TX MCS map 2 bits for each stream, total 8 streams + * @tx_highest: Indicates highest long GI VHT PPDU data rate + * STA can transmit. Rate expressed in units of 1 Mbps. + * If this field is 0 this value should not be used to + * consider the highest TX data rate supported. + * The top 3 bits of this field are reserved. + */ +struct ieee80211_vht_mcs_info +{ + UINT16 rx_mcs_map; + UINT16 rx_highest; + UINT16 tx_mcs_map; + UINT16 tx_highest; +} __attribute__ ((packed)); + +/** + * struct ieee80211_sta_vht_cap - STA's VHT capabilities + * + * This structure describes most essential parameters needed + * to describe 802.11ac VHT capabilities for an STA. + * + * @vht_supported: is VHT supported by the STA + * @cap: VHT capabilities map as described in 802.11ac spec + * @vht_mcs: Supported VHT MCS rates + */ +struct ieee80211_sta_vht_cap +{ + UINT8 vht_supported; + UINT32 cap; /* use IEEE80211_VHT_CAP_ */ + struct ieee80211_vht_mcs_info vht_mcs; +}; + +struct ieee80211_supported_band +{ + struct ieee80211_channel *channels; + INT32 num_channels; + struct ieee80211_sta_ht_cap ht_cap; + struct ieee80211_sta_vht_cap vht_cap; +}; + +typedef struct wiphy +{ + struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; +} WIPHY_T; + + +extern WIPHY_T g_wiphy; + +#endif // _RW_IEEE80211_H_ +// eof + diff --git a/beken_os/beken378/func/rwnx_intf/rw_msdu.c b/beken_os/beken378/func/rwnx_intf/rw_msdu.c new file mode 100755 index 0000000..82026e2 --- /dev/null +++ b/beken_os/beken378/func/rwnx_intf/rw_msdu.c @@ -0,0 +1,1122 @@ +#include "include.h" +#include "rw_msdu.h" +#include "rw_pub.h" +#include "str_pub.h" +#include "mem_pub.h" +#include "txu_cntrl.h" +#include "lwip/pbuf.h" +#include "prot/ip4.h" +#include "prot/ip6.h" +#include "prot/ethernet.h" + +#include "arm_arch.h" + +#if CFG_GENERAL_DMA +#include "general_dma_pub.h" +#endif + +#include "param_config.h" +#include "fake_clock_pub.h" +#include "power_save_pub.h" + +#include "tkl_lwip.h" + +extern UINT32 rwm_transfer_node(MSDU_NODE_T *node, u8 flag); + +LIST_HEAD_DEFINE(msdu_rx_list); + +#if CFG_USE_AP_PS +#include "ps.h" +#include "app.h" +#define MAX_PS_STA_NUM BROADCAST_STA_IDX_MIN // CFG_STA_MAX +#define MAX_BUFFER_TIME 10000 // 10S + +typedef struct sta_ps_st { + beken_timer_t timer; + struct list_head txing; +} STA_PS_ST, *STA_PS_PTR; + +typedef struct rwm_ap_ps_st { + BOOL active; + STA_PS_ST sta_ps[MAX_PS_STA_NUM]; +} AP_PS_ST, *AP_PS_PTR; + +AP_PS_ST g_ap_ps = {0}; +#endif + +void rwm_push_rx_list(MSDU_NODE_T *node) +{ + GLOBAL_INT_DECLARATION(); + + GLOBAL_INT_DISABLE(); + list_add_tail(&node->hdr, &msdu_rx_list); + GLOBAL_INT_RESTORE(); +} + +MSDU_NODE_T *rwm_pop_rx_list(void) +{ + LIST_HEADER_T *tmp; + LIST_HEADER_T *pos; + MSDU_NODE_PTR node; + + GLOBAL_INT_DECLARATION(); + + GLOBAL_INT_DISABLE(); + + node = NULLPTR; + list_for_each_safe(pos, tmp, &msdu_rx_list) + { + list_del(pos); + node = list_entry(pos, MSDU_NODE_T, hdr); + + break; + } + + GLOBAL_INT_RESTORE(); + + return node; +} + +void rwm_flush_rx_list(void) +{ + MSDU_NODE_T *node_ptr; + + while(1) + { + node_ptr = rwm_pop_rx_list(); + if(node_ptr) + { + os_free(node_ptr); + } + else + { + break; + } + } +} + +void rwm_tx_confirm(void *param) +{ + struct txdesc *txdesc = (struct txdesc *)param; + + if(txdesc && txdesc->host.msdu_node) + { + os_null_printf("flush_desc:0x%x\r\n", txdesc->host.msdu_node); + + if(txdesc->host.callback) + { + (*txdesc->host.callback)(txdesc->host.param); + } + + os_free(txdesc->host.msdu_node); + txdesc->host.msdu_node = NULL; + } +} + +void rwm_tx_msdu_renew(UINT8 *buf, UINT32 len, UINT8 *orig_addr) +{ +#if CFG_GENERAL_DMA_ + gdma_memcpy((void *)((UINT32)orig_addr + CFG_MSDU_RESV_HEAD_LEN), buf, len); +#else + os_memmove((void *)((UINT32)orig_addr + CFG_MSDU_RESV_HEAD_LEN), buf, len); +#endif +} + +UINT8 *rwm_get_msdu_content_ptr(MSDU_NODE_T *node) +{ + return (UINT8 *)((UINT32)node->msdu_ptr + CFG_MSDU_RESV_HEAD_LEN); +} + +void rwm_txdesc_copy(struct txdesc *dst_local, ETH_HDR_PTR eth_hdr_ptr) +{ + struct hostdesc *host_ptr; + + host_ptr = &dst_local->host; + + os_memcpy(&host_ptr->eth_dest_addr, ð_hdr_ptr->e_dest, sizeof(host_ptr->eth_dest_addr)); + os_memcpy(&host_ptr->eth_src_addr, ð_hdr_ptr->e_src, sizeof(host_ptr->eth_src_addr)); +} + +extern int bmsg_ps_handler_rf_ps_mode_real_wakeup(void); +int rwm_raw_frame_with_cb(uint8_t *buffer, int len, void *cb, void *param) +{ + int ret = 0; + uint8_t *pkt = buffer; + MSDU_NODE_T *node; + UINT8 *content_ptr; + UINT32 queue_idx = AC_VI; + struct txdesc *txdesc_new; + struct umacdesc *umac; + + node = rwm_tx_node_alloc(len); + if (node == NULL) { + goto exit; + } + + rwm_tx_msdu_renew(pkt, len, node->msdu_ptr); + content_ptr = rwm_get_msdu_content_ptr(node); + + txdesc_new = tx_txdesc_prepare(queue_idx); + if(txdesc_new == NULL || TXDESC_STA_USED == txdesc_new->status) { + rwm_node_free(node); + goto exit; + } + + txdesc_new->status = TXDESC_STA_USED; + txdesc_new->host.flags = TXU_CNTRL_MGMT; + txdesc_new->host.orig_addr = (UINT32)node->msdu_ptr; + txdesc_new->host.packet_addr = (UINT32)content_ptr; + txdesc_new->host.packet_len = len; + txdesc_new->host.status_desc_addr = (UINT32)content_ptr; + txdesc_new->host.tid = 0xff; + txdesc_new->host.callback = (mgmt_tx_cb_t)cb; + txdesc_new->host.param = param; + txdesc_new->host.msdu_node = (void *)node; + + umac = &txdesc_new->umac; + umac->payl_len = len; + umac->head_len = 0; + umac->tail_len = 0; + umac->hdr_len_802_2 = 0; + + umac->buf_control = &txl_buffer_control_24G; + + txdesc_new->lmac.agg_desc = NULL; + txdesc_new->lmac.hw_desc->cfm.status = 0; + + ps_set_data_prevent(); + nxmac_pwr_mgt_setf(0); +#if CFG_USE_STA_PS + bmsg_ps_handler_rf_ps_mode_real_wakeup(); +#endif + + txl_cntrl_push(txdesc_new, queue_idx); + + ret = len; + +exit: + return ret; +} + +MSDU_NODE_T *rwm_tx_node_alloc(UINT32 len) +{ + UINT8 *buff_ptr; + MSDU_NODE_T *node_ptr = 0; + + node_ptr = (MSDU_NODE_T *)os_malloc(sizeof(MSDU_NODE_T) + + CFG_MSDU_RESV_HEAD_LEN + + len + + CFG_MSDU_RESV_TAIL_LEN); + + if(NULL == node_ptr) + { + goto alloc_exit; + } + + buff_ptr = (UINT8 *)((UINT32)node_ptr + sizeof(MSDU_NODE_T)); + + node_ptr->msdu_ptr = buff_ptr; + node_ptr->len = len; + +alloc_exit: + return node_ptr; +} + +void rwm_node_free(MSDU_NODE_T *node) +{ + ASSERT(node); + os_free(node); +} + +UINT8 *rwm_rx_buf_alloc(UINT32 len) +{ + return (UINT8 *)os_malloc(len); +} + +UINT32 rwm_get_rx_valid(void) +{ + UINT32 count = 0; + LIST_HEADER_T *tmp; + LIST_HEADER_T *pos; + LIST_HEADER_T *head = &msdu_rx_list; + + GLOBAL_INT_DECLARATION(); + + GLOBAL_INT_DISABLE(); + list_for_each_safe(pos, tmp, head) + { + count ++; + } + GLOBAL_INT_RESTORE(); + + return ((count >= MSDU_RX_MAX_CNT) ? 0 : 1); +} + +UINT32 rwm_get_rx_valid_node_len(void) +{ + UINT32 len = 0; + LIST_HEADER_T *tmp; + LIST_HEADER_T *pos; + MSDU_NODE_PTR node; + + GLOBAL_INT_DECLARATION(); + + GLOBAL_INT_DISABLE(); + + node = NULLPTR; + list_for_each_safe(pos, tmp, &msdu_rx_list) + { + node = list_entry(pos, MSDU_NODE_T, hdr); + len = node->len; + break; + } + + GLOBAL_INT_RESTORE(); + + return len; +} + +#if CFG_USE_AP_PS +extern void bmsg_txing_sender(uint8_t sta_idx); +void rwm_push_txing_list(MSDU_NODE_T *node, UINT8 sta_idx) +{ + GLOBAL_INT_DECLARATION(); + + if(sta_idx >= MAX_PS_STA_NUM) + return; + + GLOBAL_INT_DISABLE(); + list_add_tail(&node->hdr, &g_ap_ps.sta_ps[sta_idx].txing); + GLOBAL_INT_RESTORE(); +} + +MSDU_NODE_T *rwm_pop_txing_list(UINT8 sta_idx) +{ + LIST_HEADER_T *tmp; + LIST_HEADER_T *pos; + MSDU_NODE_PTR node; + + GLOBAL_INT_DECLARATION(); + + if(sta_idx >= MAX_PS_STA_NUM) + return NULL; + + GLOBAL_INT_DISABLE(); + + node = NULLPTR; + list_for_each_safe(pos, tmp, &g_ap_ps.sta_ps[sta_idx].txing) + { + list_del(pos); + node = list_entry(pos, MSDU_NODE_T, hdr); + break; + } + + GLOBAL_INT_RESTORE(); + + return node; +} + +UINT32 rwm_txling_list_node_count(UINT8 sta_idx) +{ + if(sta_idx >= MAX_PS_STA_NUM) + return 0; + + return list_size(&g_ap_ps.sta_ps[sta_idx].txing); +} + +void rwm_flush_txing_list(UINT8 sta_idx) +{ + MSDU_NODE_T *node_ptr; + int ret; + + if(sta_idx >= MAX_PS_STA_NUM) + return; + + if(rwm_txling_list_node_count(sta_idx)) + { + os_printf("flush buffered node, staid:%d\r\n", sta_idx); + while(1) { + node_ptr = rwm_pop_txing_list(sta_idx); + if(node_ptr) + os_free(node_ptr); + else + break; + } + } + + if(rtos_is_timer_running(&g_ap_ps.sta_ps[sta_idx].timer)) + { + os_printf("stop ap ps timer, staid:%d\r\n", sta_idx); + ret = rtos_stop_timer(&g_ap_ps.sta_ps[sta_idx].timer); + ASSERT(0 == ret); + } +} + +void rwm_ps_tranfer_node(MSDU_NODE_T *node) +{ + UINT8 vif_idx, sta_idx; + BOOL need_buffer = false; + + if(!node) + return; + + vif_idx = node->vif_idx; + sta_idx = node->sta_idx; + + if(!rwm_mgmt_is_ap_inface(vif_idx)) + { + #if NX_POWERSAVE + txl_cntrl_inc_pck_cnt(); + #endif + // normal transfer + rwm_transfer_node(node, 0); + } + else + { + // only ap mode need check peer stations in ps mode + if(!g_ap_ps.active) + { + #if NX_POWERSAVE + txl_cntrl_inc_pck_cnt(); + #endif + // normal transfer + rwm_transfer_node(node, 0); + } + else + { + if((sta_mgmt_is_in_ps(sta_idx) || rwm_txling_list_node_count(sta_idx)) + && (sta_idx < MAX_PS_STA_NUM)) + { + if(!rwm_txling_list_node_count(sta_idx)) + { + u8 vif_idx = sta_mgmt_get_vif_idx(sta_idx); + u16 aid = sta_mgmt_get_aid(sta_idx); + int ret; + + //os_printf("on bcn tim: vif:%d, aid:%d, sta:%d\r\n", vif_idx, aid, sta_idx); + + //rwnx_send_me_uapsd_traffic_ind(sta_idx, 1); + rw_msg_send_tim_update(vif_idx, aid, 1); + if(!rtos_is_timer_running(&g_ap_ps.sta_ps[sta_idx].timer)) { + ret = rtos_start_timer(&g_ap_ps.sta_ps[sta_idx].timer); + ASSERT(0 == ret); + } + } + + // add this node to txing list + //os_printf("addto txing list node:%p, sta:%d\r\n", node, sta_idx); + rwm_push_txing_list(node, sta_idx); + } + else + { + #if NX_POWERSAVE + txl_cntrl_inc_pck_cnt(); + #endif + // normal transfer + rwm_transfer_node(node, 0); + } + } + } +} + +void rwm_msdu_send_txing_node(UINT8 sta_idx) +{ + MSDU_NODE_T *node = NULL; + struct txdesc *txdesc_new = NULL; + UINT32 node_left; + + node = rwm_pop_txing_list(sta_idx); + if(!node) + return; + + node_left = rwm_txling_list_node_count(sta_idx); + + #if NX_POWERSAVE + txl_cntrl_inc_pck_cnt(); + #endif + + rwm_transfer_node(node, TXU_CNTRL_MORE_DATA); + + if(node_left && !sta_mgmt_is_in_ps(sta_idx)) { + /* trigger sending txing again*/ + bmsg_txing_sender(sta_idx); + } + else if(!node_left) + { + u8 vif_idx = sta_mgmt_get_vif_idx(sta_idx); + u16 aid = sta_mgmt_get_aid(sta_idx); + + rw_msg_send_tim_update(vif_idx, aid, 0); + } +} + +void rwm_msdu_ps_change_ind_handler(void *msg) +{ + struct ke_msg *msg_ptr = (struct ke_msg *)msg; + struct mm_ps_change_ind *ind; + UINT32 node_left; + int ret; + + if(!msg_ptr || !msg_ptr->param) + return; + + ind = (struct mm_ps_change_ind *)msg_ptr->param; + node_left = rwm_txling_list_node_count(ind->sta_idx); + + if((ind->ps_state == PS_MODE_OFF) && node_left) { + // trigger txing sending + bmsg_txing_sender(ind->sta_idx); + + if(rtos_is_timer_running(&g_ap_ps.sta_ps[ind->sta_idx].timer)) { + ret = rtos_stop_timer(&g_ap_ps.sta_ps[ind->sta_idx].timer); + ASSERT(0 == ret); + } + } else if((ind->ps_state == PS_MODE_ON) && node_left) { + // do something + if(!rtos_is_timer_running(&g_ap_ps.sta_ps[ind->sta_idx].timer)) { + ret = rtos_start_timer(&g_ap_ps.sta_ps[ind->sta_idx].timer); + ASSERT(0 == ret); + } + } +} + +void rwm_msdu_ap_ps_timeout(void *data) +{ + u8 sta_idx = (u32)data; + + rwm_flush_txing_list(sta_idx); +} +#endif + +void rwm_msdu_init(void) +{ + #if CFG_USE_AP_PS + g_ap_ps.active = true; + + for(int i=0; i> 5; +} + +/* extract flow control field */ +uint8_t ipv6_ieee8023_dscp(UINT8 *buf) +{ + uint8_t tos; + struct ip_hdr *iphd = (struct ip_hdr *)buf; + struct ip6_hdr *hdr = (struct ip6_hdr *)iphd; + + tos = IP6H_FL(hdr); + + return (tos & 0xfc) >> 5; +} + +/* + * get user priority from @buf. + * ipv4 dscp/tos, ipv6 flow control. for eapol packets, disable qos. + */ +uint8_t classify8021d(UINT8 *buf) +{ +#ifdef CFG_WFA_CERTIFICATION + struct eth_hdr *ethhdr = (struct eth_hdr *)buf; + + switch (PP_HTONS(ethhdr->type)) { + case ETHTYPE_IP: + return ipv4_ieee8023_dscp(ethhdr + 1); + case ETHTYPE_IPV6: + return ipv6_ieee8023_dscp(ethhdr + 1); + case ETH_P_PAE: + return 7; /* TID7 highest user priority */ + default: + return 0; + } +#else + return 4; // TID4: mapped to AC_VI +#endif +} + +UINT32 rwm_transfer(UINT8 vif_idx, UINT8 *buf, UINT32 len, int sync, void *args) +{ + UINT32 ret = 0; + MSDU_NODE_T *node; + ETH_HDR_PTR eth_hdr_ptr; + + ret = RW_FAILURE; + node = rwm_tx_node_alloc(len); + if(NULL == node) + { + #if NX_POWERSAVE + txl_cntrl_dec_pck_cnt(); + #endif + + os_printf("rwm_transfer no node\r\n"); + goto tx_exit; + } + rwm_tx_msdu_renew(buf, len, node->msdu_ptr); + + eth_hdr_ptr = (ETH_HDR_PTR)buf; + node->vif_idx = vif_idx; + node->sync = sync; + node->args = args; + node->sta_idx = rwm_mgmt_tx_get_staidx(vif_idx, + ð_hdr_ptr->e_dest); + +#if CFG_USE_AP_PS + ret = rwm_ps_tranfer_node(node); +#else + ret = rwm_transfer_node(node, 0); +#endif + +tx_exit: + return ret; +} + +void ieee80211_data_tx_cb(void *param) +{ + struct txdesc *txdesc_new = (struct txdesc *)param; + MSDU_NODE_T *node = (MSDU_NODE_T *)txdesc_new->host.msdu_node; + struct tx_hd *txhd = &txdesc_new->lmac.hw_desc->thd; + struct ieee80211_tx_cb *cb = (struct ieee80211_tx_cb *)node->args; + uint32_t status = txhd->statinfo; + + if(0 == node) + { + os_printf("zero_node\r\n"); + return; + } + + if (status & FRAME_SUCCESSFUL_TX_BIT /*DESC_DONE_SW_TX_BIT*/) { + cb->result = RW_SUCCESS; + } else { + cb->result = RW_FAILURE; + } + + rtos_set_semaphore(&cb->sema); +} + +int sta_11n_nss(uint8_t *mcs_set) +{ + int i; + int nss = 0; /* spartial stream num */ + + // Go through the MCS map to find out one valid mcs + for (i = 0; i < 4; i++) { // 4 == sizeof(rc_ss->rate_map.ht) + if (mcs_set[i] != 0) + nss++; + } + + return nss; +} + +int qos_need_enabled(struct sta_info_tag *sta) +{ + int i; + struct mac_rateset *rate_set; + int rate_22mbps_found = 0; + int nss = 0; + + if (!sta) + return 0; + if (!(sta->info.capa_flags & STA_QOS_CAPA)) + return 0; + +#define CONFIG_WRT3200_ISSUE +#ifdef CONFIG_WRT3200_ISSUE + /* workaround for WRT3200 */ + + /* find rate 22mbps */ + rate_set = &sta->info.rate_set; + for (i = 0; i < rate_set->length; i++) { + if (rate_set->array[i] == 0x2c) { + rate_22mbps_found = 1; + break; + } + } + + /* ignore rate doesn't contain 22Mbps */ + if (!rate_22mbps_found) + return 0; + + /* ignore 11AC */ + if (sta->info.capa_flags & STA_VHT_CAPA) + return 0; + + /* ignore non-HT */ + if (!(sta->info.capa_flags & STA_HT_CAPA)) + return 0; + + /* ingore nss != 3*/ + nss = sta_11n_nss(sta->info.ht_cap.mcs_rate); + if (nss != 3) + return 0; + + /* ignore LDPC and DSSS/CCK in 40M not both enabled */ + if (!((sta->info.ht_cap.ht_capa_info & MAC_HTCAPA_LDPC) && + (sta->info.ht_cap.ht_capa_info & MAC_HTCAPA_DSSS_CCK_40))) + return 0; +#endif + + return 1; +} + +UINT32 rwm_transfer_node(MSDU_NODE_T *node, u8 flag) +{ + UINT8 tid; + UINT32 ret = RW_FAILURE; + UINT8 *content_ptr; + UINT32 queue_idx; + ETH_HDR_PTR eth_hdr_ptr; + struct txdesc *txdesc_new; + struct sta_info_tag *sta; + struct vif_info_tag *vif; + + if(!node) + { + goto tx_exit; + } + + content_ptr = rwm_get_msdu_content_ptr(node); + eth_hdr_ptr = (ETH_HDR_PTR)content_ptr; + +#if CFG_RWNX_QOS_MSDU + vif = rwm_mgmt_vif_idx2ptr(node->vif_idx); + if (NULL == vif) + { + os_printf("%s: vif is NULL!\r\n", __func__); + goto tx_exit; + } + + if (likely(vif->active)) { + sta = &sta_info_tab[vif->u.sta.ap_id]; + if (qos_need_enabled(sta)) { + int i; + tid = classify8021d((u8*)eth_hdr_ptr); + /* check admission ctrl */ + for (i = mac_tid2ac[tid]; i >= 0; i--) + if (!(vif->bss_info.edca_param.acm & BIT(i))) + break; + if (i < 0) + goto tx_exit; + queue_idx = i; /* AC_* */ + } else { + /* + * non-WMM STA + * + * CWmin 15, CWmax 1023, AIFSN 2, TXOP 0. set these values when joining with this BSS. + */ + tid = 0xFF; + queue_idx = AC_VI; + } + } else { + tid = 0xFF; + queue_idx = AC_VI; + } +#else + tid = 0xff; + queue_idx = AC_VI; +#endif + + txdesc_new = tx_txdesc_prepare(queue_idx); + if(TXDESC_STA_USED == txdesc_new->status) + { + os_printf("rwm_transfer no txdesc \r\n"); + goto tx_exit; + } + + txdesc_new->status = TXDESC_STA_USED; + rwm_txdesc_copy(txdesc_new, eth_hdr_ptr); + + txdesc_new->host.flags = flag; +#if NX_AMSDU_TX + txdesc_new->host.orig_addr[0] = (UINT32)node->msdu_ptr; + txdesc_new->host.packet_addr[0] = (UINT32)content_ptr + 14; + txdesc_new->host.packet_len[0] = node->len - 14; + txdesc_new->host.packet_cnt = 1; +#else + txdesc_new->host.orig_addr = (UINT32)node->msdu_ptr; + txdesc_new->host.packet_addr = (UINT32)content_ptr + 14; + txdesc_new->host.packet_len = node->len - 14; +#endif + txdesc_new->host.status_desc_addr = (UINT32)content_ptr + 14; + txdesc_new->host.ethertype = eth_hdr_ptr->e_proto; + txdesc_new->host.tid = tid; + + txdesc_new->host.vif_idx = node->vif_idx; + txdesc_new->host.staid = node->sta_idx; + txdesc_new->host.msdu_node = (void *)node; + + if (node->sync) + { + txdesc_new->host.callback = (mgmt_tx_cb_t)ieee80211_data_tx_cb; + txdesc_new->host.param = (void *)txdesc_new; + } + else + { + txdesc_new->host.callback = 0; + } + + txdesc_new->lmac.agg_desc = NULL; + txdesc_new->lmac.hw_desc->cfm.status = 0; + + txu_cntrl_push(txdesc_new, queue_idx); + return ret; + +tx_exit: + if (NULL != node) + rwm_node_free(node); + + #if NX_POWERSAVE + txl_cntrl_dec_pck_cnt(); + #endif + + return ret; +} + +UINT32 rwm_get_rx_free_node(struct pbuf **p_ret, UINT32 len) +{ + struct pbuf *p; + + p = pbuf_alloc(PBUF_RAW, len, PBUF_RAM); + *p_ret = p; + + return RW_SUCCESS; +} + +UINT32 rwm_upload_data(RW_RXIFO_PTR rx_info) +{ + struct pbuf *p = (struct pbuf *)rx_info->data; + + os_null_printf("s:%d, v:%d, d:%d, r:%d, c:%d, l:%d, %p\r\n", + rx_info->sta_idx, + rx_info->vif_idx, + rx_info->dst_idx, + rx_info->rssi, + rx_info->center_freq, + rx_info->length, + rx_info->data); + + struct netif * netif = NULL; + + netif = rwm_mgmt_get_vif2netif(rx_info->vif_idx); + tkl_ethernetif_recv(netif, p); + + return RW_SUCCESS; +} + +UINT32 rwm_uploaded_data_handle(UINT8 *upper_buf, UINT32 len) +{ + UINT32 count; + UINT32 ret = RW_FAILURE; + MSDU_NODE_T *node_ptr; + + node_ptr = rwm_pop_rx_list(); + if(node_ptr) + { + count = MIN(len, node_ptr->len); +#if CFG_GENERAL_DMA_ + gdma_memcpy(upper_buf, node_ptr->msdu_ptr, count); +#else + os_memcpy(upper_buf, node_ptr->msdu_ptr, count); +#endif + ret = count; + + os_free(node_ptr); + node_ptr = NULL; + } + + return ret; +} + +/////////////////////////////////////////////////////////////////////////////// +VIF_INF_PTR rwm_mgmt_vif_idx2ptr(UINT8 vif_idx) +{ + VIF_INF_PTR vif_entry = NULL; + + if(vif_idx < NX_VIRT_DEV_MAX) + vif_entry = &vif_info_tab[vif_idx]; + + return vif_entry; +} + +VIF_INF_PTR rwm_mgmt_vif_type2ptr(UINT8 vif_type) +{ + VIF_INF_PTR vif_entry = NULL; + UINT32 i; + + for(i = 0; i < NX_VIRT_DEV_MAX; i++) + { + vif_entry = &vif_info_tab[i]; + if(vif_entry->type == vif_type) + break; + } + + if(i == NX_VIRT_DEV_MAX) + vif_entry = NULL; + + return vif_entry; +} + +STA_INF_PTR rwm_mgmt_sta_idx2ptr(UINT8 staid) +{ + STA_INF_PTR sta_entry = NULL; + + if(staid < NX_REMOTE_STA_MAX) + sta_entry = &sta_info_tab[staid]; + + return sta_entry; +} + +STA_INF_PTR rwm_mgmt_sta_mac2ptr(void *mac) +{ + UINT32 i; + STA_INF_PTR sta_entry = NULL; + + for(i = 0; i < NX_REMOTE_STA_MAX; i++) + { + sta_entry = &sta_info_tab[i]; + if(MAC_ADDR_CMP((void *)&sta_entry->mac_addr, mac)) + break; + } + + return sta_entry; +} + +UINT8 rwm_mgmt_sta_mac2idx(void *mac) +{ + UINT32 i; + UINT8 staid = 0xff; + STA_INF_PTR sta_entry = NULL; + + for(i = 0; i < NX_REMOTE_STA_MAX; i++) + { + sta_entry = &sta_info_tab[i]; + if(MAC_ADDR_CMP((void *)&sta_entry->mac_addr, mac)) + break; + } + if(i < NX_REMOTE_STA_MAX) + staid = i; + + return staid; +} + +UINT8 rwm_mgmt_vif_mac2idx(void *mac) +{ + VIF_INF_PTR vif_entry = NULL; + UINT8 vif_idx = 0xff; + UINT32 i; + + for(i = 0; i < NX_VIRT_DEV_MAX; i++) + { + vif_entry = &vif_info_tab[i]; + if(MAC_ADDR_CMP((void *)&vif_entry->mac_addr, mac)) + break; + } + + if(i < NX_VIRT_DEV_MAX) + vif_idx = i; + + return vif_idx; +} + +UINT8 rwm_mgmt_vif_name2idx(char *name) +{ + VIF_INF_PTR vif_entry = NULL; + struct netif *lwip_if; + UINT8 vif_idx = 0xff; + UINT32 i; + + for(i = 0; i < NX_VIRT_DEV_MAX; i++) + { + vif_entry = &vif_info_tab[i]; + if(vif_entry->priv) + { + lwip_if = (struct netif *)vif_entry->priv; + if (!os_strncmp(lwip_if->hostname, name, os_strlen(lwip_if->hostname))) + { + break; + } + } + } + + if(i < NX_VIRT_DEV_MAX) + vif_idx = i; + + return vif_idx; +} + +UINT8 rwm_mgmt_get_hwkeyidx(UINT8 vif_idx, UINT8 staid) +{ + UINT8 hw_key_idx = MM_SEC_MAX_KEY_NBR + 1; + struct key_info_tag *key = NULL; + + VIF_INF_PTR vif_entry = NULL; + STA_INF_PTR sta_entry = NULL; + + if(staid == 0xff) // group key + { + vif_entry = rwm_mgmt_vif_idx2ptr(vif_idx); + if(vif_entry) + key = vif_entry->default_key; + } + else + { + sta_entry = rwm_mgmt_sta_idx2ptr(staid); + if(sta_entry) + key = *(sta_entry->sta_sec_info.cur_key); + } + + if(key) + { + hw_key_idx = key->hw_key_idx; + } + + return hw_key_idx; +} + +void rwm_mgmt_set_vif_netif(struct netif *net_if) +{ + VIF_INF_PTR vif_entry = NULL; + UINT8 vif_idx; + + if(!net_if) + return; + + vif_idx = rwm_mgmt_vif_mac2idx(net_if->hwaddr); + vif_entry = rwm_mgmt_vif_idx2ptr(vif_idx); + + if(vif_entry) + { + vif_entry->priv = net_if; + net_if->state = (void *)vif_entry; + } + else + { + os_printf("warnning: set_vif_netif failed\r\n"); + } +} + +struct netif *rwm_mgmt_get_vif2netif(UINT8 vif_idx) +{ + VIF_INF_PTR vif_entry = NULL; + struct netif *netif = NULL; + + vif_entry = rwm_mgmt_vif_idx2ptr(vif_idx); + + if(vif_entry) + netif = (struct netif *)vif_entry->priv; + + return netif; +} + +UINT8 rwm_mgmt_get_netif2vif(struct netif *netif) +{ + UINT8 vif_idx = 0xff; + VIF_INF_PTR vif_entry = NULL; + + if(netif && netif->state) + { + vif_entry = (VIF_INF_PTR)netif->state; + vif_idx = vif_entry->index; + } + + return vif_idx; +} + +UINT8 rwm_mgmt_tx_get_staidx(UINT8 vif_idx, void *dstmac) +{ + UINT8 staid = 0xff; + VIF_INF_PTR vif_entry = NULL; + + vif_entry = rwm_mgmt_vif_idx2ptr(vif_idx); + + if(vif_entry) + { + if(vif_entry->type == VIF_STA) + { + staid = vif_entry->u.sta.ap_id; + } + else if(vif_entry->type == VIF_AP) + { + staid = rwm_mgmt_sta_mac2idx(dstmac); + } + } + + if(staid == 0xff) + { + staid = VIF_TO_BCMC_IDX(vif_idx); + } + + return staid; +} + +u8 rwn_mgmt_is_only_sta_role_add(void) +{ + VIF_INF_PTR vif_entry = (VIF_INF_PTR)rwm_mgmt_is_vif_first_used(); + + if(!vif_entry) + return 0; + + if(vif_entry->type == VIF_STA) + return 1; + + return 0; +} + +#include "lwip/sockets.h" +extern uint8_t* dhcp_lookup_mac(uint8_t *chaddr); + +void rwn_mgmt_show_vif_peer_sta_list(UINT8 role) +{ + struct vif_info_tag *vif = (VIF_INF_PTR)rwm_mgmt_is_vif_first_used(); + struct sta_info_tag *sta; + UINT8 num = 0; + + while(vif) { + if ( vif->type == role) { + sta = (struct sta_info_tag *)co_list_pick(&vif->sta_list); + while (sta != NULL) + { + UINT8 *macptr = (UINT8*)sta->mac_addr.array; + UINT8 *ipptr = NULL; + + if(role == VIF_AP) { + ipptr = dhcp_lookup_mac(macptr); + } else if (role == VIF_STA){ + struct netif *netif = (struct netif *)vif->priv; + ipptr = (UINT8 *)inet_ntoa(netif->gw); + } + + os_printf("%d: mac:%02x-%02x-%02x-%02x-%02x-%02x, ip:%s\r\n", num++, + macptr[0], macptr[1], macptr[2], + macptr[3], macptr[4], macptr[5],ipptr); + + sta = (struct sta_info_tag *)co_list_next(&sta->list_hdr); + } + } + vif = (VIF_INF_PTR) rwm_mgmt_next(vif); + } +} + +// eof + diff --git a/beken_os/beken378/func/rwnx_intf/rw_msdu.h b/beken_os/beken378/func/rwnx_intf/rw_msdu.h new file mode 100755 index 0000000..8b11c37 --- /dev/null +++ b/beken_os/beken378/func/rwnx_intf/rw_msdu.h @@ -0,0 +1,61 @@ +#ifndef _RW_MSDU_H_ +#define _RW_MSDU_H_ + +#include "doubly_list.h" +#include "tx_swdesc.h" +#include "lwip/pbuf.h" +#include "rtos_pub.h" +#include "rwnx.h" + +#define MSDU_TX_MAX_CNT (32) +#define MSDU_RX_MAX_CNT (32) + +#define ETH_ADDR_LEN 6 /* Octets in one ethernet addr */ + +static inline int is_broadcast_eth_addr(const u8 *a) +{ + return (a[0] & a[1] & a[2] & a[3] & a[4] & a[5]) == 0xff; +} + +typedef struct _eth_hdr +{ + UINT8 e_dest[ETH_ADDR_LEN]; + UINT8 e_src[ETH_ADDR_LEN]; + UINT16 e_proto; +} __attribute__((packed)) ETH_HDR_T, *ETH_HDR_PTR; + +struct ieee80211_tx_cb { + beken_semaphore_t sema; + int result; +}; + +typedef struct _msdu_node_ +{ + LIST_HEADER_T hdr; + + UINT8 *msdu_ptr; + UINT32 len; + + UINT8 vif_idx; + UINT8 sta_idx; + void *args; + int sync; +} MSDU_NODE_T, *MSDU_NODE_PTR; + +extern void rwm_push_rx_list(MSDU_NODE_T *node); +extern MSDU_NODE_T *rwm_pop_rx_list(void); +extern void rwm_tx_confirm(void *); +extern void rwm_tx_msdu_renew(UINT8 *buf, UINT32 len, UINT8 *orig_addr); +extern UINT8 *rwm_get_msdu_content_ptr(MSDU_NODE_T *node); +extern void rwm_txdesc_copy(struct txdesc *dst_local, ETH_HDR_PTR eth_hdr_ptr); +extern MSDU_NODE_T *rwm_tx_node_alloc(UINT32 len); +extern void rwm_node_free(MSDU_NODE_T *node); +extern UINT8 *rwm_rx_buf_alloc(UINT32 len); +extern UINT32 rwm_upload_data(RW_RXIFO_PTR rx_info); +extern UINT32 rwm_get_rx_free_node(struct pbuf **p_ret, UINT32 len); +extern UINT32 rwm_get_rx_valid(void); +extern int rwm_raw_frame_with_cb(uint8_t *buffer, int len, void *cb, void *param); + +#endif // _RW_MSDU_H_ +// eof + diff --git a/beken_os/beken378/func/rwnx_intf/rw_msg_rx.c b/beken_os/beken378/func/rwnx_intf/rw_msg_rx.c new file mode 100755 index 0000000..acd7a46 --- /dev/null +++ b/beken_os/beken378/func/rwnx_intf/rw_msg_rx.c @@ -0,0 +1,1007 @@ +#include "include.h" +#include "rw_msg_rx.h" +#include "rw_pub.h" +#include "ke_msg.h" +#include "mem_pub.h" +#include "mac_common.h" +#include "scanu_task.h" +#include "sa_station.h" +#include "apm_task.h" +#include "me_task.h" +#include "sm_task.h" +#include "hostapd_intf_pub.h" +#include "mac_ie.h" +#include "ieee802_11_defs.h" +#include "wlan_ui_pub.h" +#include "mcu_ps_pub.h" +#include "driver.h" +#if CFG_WPA_CTRL_IFACE +#include "signal.h" +#include "ctrl_iface.h" +#endif + +#if CFG_ROLE_LAUNCH +#include "role_launch.h" +#endif +#if CFG_WPA_CTRL_IFACE +#include "wpa_ctrl.h" +#include "notifier.h" +#endif +#include "rxu_task.h" + +uint32_t resultful_scan_cfm = 0; +uint8_t *ind_buf_ptr = 0; +struct co_list rw_msg_rx_head; +struct co_list rw_msg_tx_head; + +/* transient status is the passing status of station connection, + abnormal status is exceptional status, which maybe is uploaded to upper layer. + the application will go with the status. + */ +static rw_evt_type g_connect_transient_status = RW_EVT_STA_IDLE; +static rw_evt_type g_connect_abnormal_status = RW_EVT_STA_IDLE; + +SCAN_RST_UPLOAD_T *scan_rst_set_ptr = 0; +#if CFG_WPA_CTRL_IFACE +IND_CALLBACK_T scan_cfm_cb_user = {0}; +#endif +IND_CALLBACK_T scan_cfm_cb = {0}; +IND_CALLBACK_T assoc_cfm_cb = {0}; +IND_CALLBACK_T deassoc_evt_cb = {0}; +IND_CALLBACK_T deauth_evt_cb = {0}; +IND_CALLBACK_T wlan_connect_user_cb = {0}; + +extern void app_set_sema(void); +extern int get_security_type_from_ie(u8 *, int, u16); +extern void rwnx_cal_set_txpwr(UINT32 pwr_gain, UINT32 grate); +extern void bk7011_default_rxsens_setting(void); +#if CFG_WPA_CTRL_IFACE +extern int wpa_is_scan_only(); +int wlan_get_bss_beacon_ies(struct wpabuf *buf, const u8 *bcn_ie, int ie_len); +#endif + +/* scan result malloc item */ +UINT8 *sr_malloc_result_item(UINT32 vies_len) +{ + return os_zalloc(vies_len + sizeof(struct sta_scan_res)); +} + +/* free scan result item */ +void sr_free_result_item(UINT8 *item_ptr) +{ + os_free(item_ptr); +} + +UINT8 *sr_malloc_shell(void) +{ + UINT8 *ptr; + UINT32 layer1_space_len; + UINT32 layer2_space_len; + + layer1_space_len = sizeof(SCAN_RST_UPLOAD_T); + layer2_space_len = MAX_BSS_LIST * sizeof(struct sta_scan_res *); + ptr = os_zalloc(layer1_space_len + layer2_space_len); + + ASSERT(ptr); + + return ptr; +} + +void sr_free_shell(UINT8 *shell_ptr) +{ + os_free(shell_ptr); +} + +void sr_free_all(SCAN_RST_UPLOAD_T *scan_rst) +{ + UINT32 i; + + for(i = 0; i < scan_rst->scanu_num; i ++) + { + sr_free_result_item((UINT8 *)scan_rst->res[i]); + scan_rst->res[i] = 0; + } + scan_rst->scanu_num = 0; + + sr_free_shell((UINT8 *)scan_rst); +} + +void *sr_get_scan_results(void) +{ + return scan_rst_set_ptr; +} + +void sr_release_scan_results(SCAN_RST_UPLOAD_PTR ptr) +{ + if(ptr) + { + sr_free_all(ptr); + } + + scan_rst_set_ptr = 0; + resultful_scan_cfm = 0; + wpa_clear_scan_results(); +} + +void mr_kmsg_init(void) +{ + co_list_init(&rw_msg_tx_head); + co_list_init(&rw_msg_rx_head); +} + +UINT32 mr_kmsg_fwd(struct ke_msg *msg) +{ + GLOBAL_INT_DECLARATION(); + + GLOBAL_INT_DISABLE(); + co_list_push_back(&rw_msg_rx_head, &msg->hdr); + GLOBAL_INT_RESTORE(); + + app_set_sema(); + + return 0; +} + +void mr_kmsg_flush(void) +{ + while(mr_kmsg_fuzzy_handle()); +} + +UINT32 mr_kmsg_fuzzy_handle(void) +{ + UINT32 ret = 0; + struct ke_msg *msg; + struct co_list_hdr *node; + + GLOBAL_INT_DECLARATION(); + + GLOBAL_INT_DISABLE(); + node = co_list_pop_front(&rw_msg_rx_head); + GLOBAL_INT_RESTORE(); + + if(node) + { + msg = (struct ke_msg *)node; + ke_msg_free(msg); + + ret = 1; + } + + return ret; +} + +UINT32 mr_kmsg_exact_handle(UINT16 rsp) +{ + UINT32 ret = 0; + struct ke_msg *msg; + struct co_list_hdr *node; + + GLOBAL_INT_DECLARATION(); + + GLOBAL_INT_DISABLE(); + node = co_list_pop_front(&rw_msg_rx_head); + GLOBAL_INT_RESTORE(); + + if(node) + { + msg = (struct ke_msg *)node; + if(rsp == msg->id) + { + ret = 1; + } + ke_msg_free(msg); + } + + return ret; +} + +void mhdr_connect_user_cb(FUNC_2PARAM_PTR ind_cb, void *ctxt) +{ + wlan_connect_user_cb.cb = ind_cb; + wlan_connect_user_cb.ctxt_arg = ctxt; +} + +void mhdr_assoc_cfm_cb(FUNC_2PARAM_PTR ind_cb, void *ctxt) +{ + assoc_cfm_cb.cb = ind_cb; + assoc_cfm_cb.ctxt_arg = ctxt; +} + +#if CFG_WPA_CTRL_IFACE +void scanu_notifier_func(void *cxt, int type, int value) +{ + //os_printf("%s: type %d, cb %p, value %d\r\n", __func__, type, scan_cfm_cb_user.cb, value); + if (type != WLAN_EVENT_SCAN_RESULTS || !scan_cfm_cb_user.cb || !value) + return; + scan_cfm_cb_user.cb(cxt, (uint8_t)value); +} + +void mhdr_scanu_reg_cb_for_wpa(FUNC_2PARAM_PTR ind_cb, void *ctxt) +{ + scan_cfm_cb.cb = ind_cb; + scan_cfm_cb.ctxt_arg = ctxt; +} + +void mhdr_scanu_reg_cb(FUNC_2PARAM_PTR ind_cb, void *ctxt) +{ + scan_cfm_cb_user.cb = ind_cb; + scan_cfm_cb_user.ctxt_arg = ctxt; + wlan_register_notifier(scanu_notifier_func, ctxt); +} + +#else /* !CFG_WPA_CTRL_IFACE */ + +void mhdr_scanu_reg_cb(FUNC_2PARAM_PTR ind_cb, void *ctxt) +{ + scan_cfm_cb.cb = ind_cb; + scan_cfm_cb.ctxt_arg = ctxt; +} +#endif + + + +void mhdr_deauth_evt_cb(FUNC_2PARAM_PTR ind_cb, void *ctxt) +{ + deauth_evt_cb.cb = ind_cb; + deauth_evt_cb.ctxt_arg = ctxt; +} + +void mhdr_deassoc_evt_cb(FUNC_2PARAM_PTR ind_cb, void *ctxt) +{ + deassoc_evt_cb.cb = ind_cb; + deassoc_evt_cb.ctxt_arg = ctxt; +} + +void mhdr_disconnect_ind(void *msg) +{ + struct ke_msg *msg_ptr; + struct sm_disconnect_ind *disc; + + msg_ptr = (struct ke_msg *)msg; + disc = (struct sm_disconnect_ind *)msg_ptr->param; + + os_printf("%s reason_code=%d\n", __FUNCTION__, disc->reason_code); + +#if CFG_ROLE_LAUNCH + if(rl_sta_req_is_null()) + { + rl_sta_cache_request_enter(); + } + else if(msg && disc + && (VENDOR_CONNECTION_LOSS == disc->reason_code)) + { + os_printf("VENDOR_CONNECTION_LOSS\r\n"); + rl_sta_cache_request_enter(); + } + else if(deassoc_evt_cb.cb) +#else + if(deassoc_evt_cb.cb) +#endif + { + os_printf("deassoc_evt_cb\r\n"); + (*deassoc_evt_cb.cb)(deassoc_evt_cb.ctxt_arg, disc->vif_idx); + } +} + +void mhdr_connect_ind(void *msg, UINT32 len) +{ + struct ke_msg *msg_ptr; + struct sm_connect_indication *conn_ind_ptr; + + msg_ptr = (struct ke_msg *)msg; + conn_ind_ptr = (struct sm_connect_indication *)msg_ptr->param; +#if !CFG_WPA_CTRL_IFACE + if(0 == conn_ind_ptr->status_code) + { + os_printf("---------SM_CONNECT_IND_ok\r\n"); + + bk7011_default_rxsens_setting(); + + if(assoc_cfm_cb.cb) + { + (*assoc_cfm_cb.cb)(assoc_cfm_cb.ctxt_arg, conn_ind_ptr->vif_idx); + } + + if(wlan_connect_user_cb.cb) + { + (*wlan_connect_user_cb.cb)(wlan_connect_user_cb.ctxt_arg, 0); + } + } + else + { + os_printf("---------SM_CONNECT_IND_fail\r\n"); + mhdr_disconnect_ind(msg); + } +#else + if (0 == conn_ind_ptr->status_code) { + os_printf("---------SM_CONNECT_IND_ok\n"); + + bk7011_default_rxsens_setting(); + + if (wlan_connect_user_cb.cb) + (*wlan_connect_user_cb.cb)(wlan_connect_user_cb.ctxt_arg, 0); + } else { + os_printf("---------SM_CONNECT_IND_fail\n"); + } + + /* Send to wpa_supplicant */ + wpa_ctrl_event_copy(WPA_CTRL_EVENT_CONNECT_IND, conn_ind_ptr, sizeof(*conn_ind_ptr)); +#endif + mcu_prevent_clear(MCU_PS_CONNECT); +} + +#if defined(CFG_IEEE80211W) +/* RXU_MGT_IND handler, send it to wpa_s */ +void mhdr_mgmt_ind(void *msg, UINT32 len) +{ + struct ke_msg *msg_ptr = (struct ke_msg *)msg; + struct rxu_mgt_ind *ind = (struct rxu_mgt_ind *)msg_ptr->param; + +#if CFG_WPA_CTRL_IFACE + os_printf("WPA_CTRL_EVENT_MGMT_IND\n"); + wpa_ctrl_event_copy(WPA_CTRL_EVENT_MGMT_IND, ind, sizeof(*ind) + ind->length); +#else + /* FIXME: DON'T CALL IN RWNX_MSG THREAD */ + union wpa_event_data data; + struct wpa_supplicant *wpa_s = wpa_suppliant_ctrl_get_wpas(); + + os_memset(&data, 0, sizeof(data)); + data.rx_mgmt.ssi_signal = ind->rssi; + data.rx_mgmt.frame = (u8 *)ind->payload; + data.rx_mgmt.frame_len = ind->length; + data.rx_mgmt.freq = ind->center_freq; + + //print_hex_dump("MGMT: ", ind->payload, ind->length); + if (wpa_s) + wpa_supplicant_event_sta(wpa_s, EVENT_RX_MGMT, &data); +#endif +} +#endif + +static STATION_STATUS_CB station_status_cb = NULL; +void mhdr_set_station_status_cb(STATION_STATUS_CB cb) +{ + bk_printf(">>> mhdr_set_station_status_cb\r\n"); + station_status_cb = cb; + station_status_cb(g_connect_transient_status); +} + +void mhdr_set_station_status_when_reconnect_over(void) +{ + if(RW_EVT_STA_CONNECTED != g_connect_transient_status) + { + if (g_connect_transient_status != g_connect_abnormal_status) { + g_connect_transient_status = g_connect_abnormal_status; + if (station_status_cb) { + bk_printf(">>> mhdr_set_station_status_when_reconnect_over %d\r\n", g_connect_transient_status); + station_status_cb(g_connect_transient_status); + } + } + } +} + + +void mhdr_set_abnormal_status(rw_evt_type val) +{ + rw_evt_type pre_status = g_connect_abnormal_status; + + if((RW_EVT_STA_PASSWORD_WRONG == pre_status) + || (RW_EVT_STA_NO_AP_FOUND == pre_status)) + { + goto set_exit; + } + + g_connect_abnormal_status = val; + +set_exit: + return; +} + +uint32_t mhdr_is_station_abnormal_status(rw_evt_type val) +{ + uint32_t unusual_flag = 0; + + if((RW_EVT_STA_PASSWORD_WRONG == val) + || (RW_EVT_STA_NO_AP_FOUND == val) + || (RW_EVT_STA_BEACON_LOSE == val) + || (RW_EVT_STA_ASSOC_FULL == val) + || (RW_EVT_STA_DISCONNECTED == val) + || (RW_EVT_STA_CONNECT_FAILED == val)) + { + unusual_flag = 1; + } + + return unusual_flag; +} + +void mhdr_set_station_status(rw_evt_type val) +{ + rw_evt_type tmp; + + GLOBAL_INT_DECLARATION(); + + GLOBAL_INT_DISABLE(); + tmp = g_connect_transient_status; + g_connect_transient_status = val; + + if(mhdr_is_station_abnormal_status(val)) + { + mhdr_set_abnormal_status(val); + } + GLOBAL_INT_RESTORE(); + + if (tmp != val) { + if (station_status_cb) { + bk_printf(">>> mhdr_set_station_status %d\r\n", val); + station_status_cb(val); + } + } +} + +rw_evt_type mhdr_get_station_status(void) +{ + return g_connect_transient_status; +} + +static void sort_scan_result(SCAN_RST_UPLOAD_T *ap_list) +{ + int i, j; + struct sta_scan_res *tmp; + + if (ap_list->scanu_num == 0) + return; + + for(i = 0; i < (ap_list->scanu_num - 1); i++) + { + for(j = i + 1; j < ap_list->scanu_num; j++) + { + if (ap_list->res[j]->level > ap_list->res[i]->level) + { + tmp = ap_list->res[j]; + ap_list->res[j] = ap_list->res[i]; + ap_list->res[i] = tmp; + } + } + } +} + +UINT32 mhdr_scanu_start_cfm(void *msg, SCAN_RST_UPLOAD_T *ap_list) +{ + struct scanu_start_cfm *cfm; + struct ke_msg *msg_ptr; + + msg_ptr = (struct ke_msg *)msg; + cfm = (struct scanu_start_cfm *)msg_ptr->param; + + if(ap_list) + { + sort_scan_result(ap_list); + wpa_buffer_scan_results(); + } + + if(scan_cfm_cb.cb) + { + (*scan_cfm_cb.cb)(scan_cfm_cb.ctxt_arg, cfm->vif_idx); + } + + return RW_SUCCESS; +} + + +UINT32 mhdr_scanu_result_ind(SCAN_RST_UPLOAD_T *scan_rst, void *msg, UINT32 len) +{ + UINT32 ret, chann; + UINT8 *elmt_addr; + UINT32 vies_len, i; + UINT8 *var_part_addr; + struct ke_msg *msg_ptr; + SCAN_RST_ITEM_PTR item; + SCAN_RST_UPLOAD_PTR result_ptr; + SCAN_IND_PTR scanu_ret_ptr; + IEEE802_11_PROBE_RSP_PTR probe_rsp_ieee80211_ptr; + char on_channel; + int replace_index = -1; + uint16_t framectrl; +#if CFG_WPA_CTRL_IFACE + bool reduce_ie = false; + struct wpabuf *ies = 0; + + if (wpa_is_scan_only()) + reduce_ie = true; +#endif + + ret = RW_SUCCESS; + result_ptr = scan_rst; + + if (result_ptr->scanu_num >= MAX_BSS_LIST) + goto scan_rst_exit; + + msg_ptr = (struct ke_msg *)msg; + scanu_ret_ptr = (SCAN_IND_PTR)msg_ptr->param; + probe_rsp_ieee80211_ptr = (IEEE802_11_PROBE_RSP_PTR)scanu_ret_ptr->payload; + vies_len = scanu_ret_ptr->length - MAC_BEACON_VARIABLE_PART_OFT; + var_part_addr = probe_rsp_ieee80211_ptr->rsp.variable; + framectrl = probe_rsp_ieee80211_ptr->frame_control; + + elmt_addr = (UINT8 *)mac_ie_find((UINT32)var_part_addr, (UINT16)vies_len, MAC_ELTID_DS); + if(elmt_addr) // adjust channel + { + chann = *(elmt_addr + MAC_DS_CHANNEL_OFT); + if(rw_ieee80211_is_scan_rst_in_countrycode(chann) == 0) + { + elmt_addr = (UINT8 *)mac_ie_find((UINT32)var_part_addr, + (UINT16)vies_len, + MAC_ELTID_SSID); + if(elmt_addr) + { + UINT8 ssid_b[MAC_SSID_LEN]; + UINT8 ssid_len = *(elmt_addr + MAC_SSID_LEN_OFT); + + if (ssid_len > MAC_SSID_LEN) + ssid_len = MAC_SSID_LEN; + + + os_memcpy(ssid_b, elmt_addr + MAC_SSID_SSID_OFT, ssid_len); + os_printf("drop: %s, chan:%d\r\n", ssid_b, chann); + } + + goto scan_rst_exit; + } + + if (chann == rw_ieee80211_get_chan_id(scanu_ret_ptr->center_freq)) + on_channel = 1; + else + on_channel = 0; + } + else + { + chann = rw_ieee80211_get_chan_id(scanu_ret_ptr->center_freq); + on_channel = 0; + os_printf("scan rst no ds param, drop it?\r\n"); + } + + /* check the duplicate bssid*/ + do + { + for(i = 0; i < result_ptr->scanu_num; i ++) + { + if(!os_memcmp(probe_rsp_ieee80211_ptr->bssid, result_ptr->res[i]->bssid, ETH_ALEN)) + { + if (on_channel == 0) + goto scan_rst_exit; + + if (result_ptr->res[i]->on_channel == 1) + { + /* update rssi */ + if (scanu_ret_ptr->rssi > result_ptr->res[i]->level) { + os_printf("RSSI: " MACSTR " %d -> %d\r\n", + MAC2STR(result_ptr->res[i]->bssid), result_ptr->res[i]->level, + scanu_ret_ptr->rssi); + result_ptr->res[i]->level = scanu_ret_ptr->rssi; + } + + /* + * if previous stored scan result is based on beacon, and current frame is a probe response, + * update scan result based on probe response. + */ + if ((framectrl & MAC_FCTRL_TYPESUBTYPE_MASK) == MAC_FCTRL_PROBERSP && + !result_ptr->res[i]->is_probersp) { + replace_index = i; // should replace with probe rsp. + } else { + goto scan_rst_exit; + } + } + else + { + replace_index = i; // should replace it. + } + } + } + }while(0); + + +#if CFG_WPA_CTRL_IFACE + if (reduce_ie) { + ies = wpabuf_alloc(128); + if (!ies) + goto scan_rst_exit; + wlan_get_bss_beacon_ies(ies, (u8 *)(var_part_addr), vies_len); + item = (SCAN_RST_ITEM_PTR)sr_malloc_result_item(wpabuf_len(ies)); + // os_printf("%s: %d-> %d\n", __func__, vies_len, wpabuf_len(ies)); + } else +#endif + item = (SCAN_RST_ITEM_PTR)sr_malloc_result_item(vies_len); + if (item == NULL) + goto scan_rst_exit; + + elmt_addr = (UINT8 *)mac_ie_find((UINT32)var_part_addr, + (UINT16)vies_len, + MAC_ELTID_SSID); + if(elmt_addr) + { + UINT8 ssid_len = *(elmt_addr + MAC_SSID_LEN_OFT); + + if (ssid_len > MAC_SSID_LEN) + ssid_len = MAC_SSID_LEN; + + os_memcpy(item->ssid, elmt_addr + MAC_SSID_SSID_OFT, ssid_len); + } + else + { + os_printf("NoSSid\r\n"); + } + + os_memcpy(item->bssid, probe_rsp_ieee80211_ptr->bssid, ETH_ALEN); + item->channel = chann; + item->beacon_int = probe_rsp_ieee80211_ptr->rsp.beacon_int; + item->caps = probe_rsp_ieee80211_ptr->rsp.capab_info; + item->level = scanu_ret_ptr->rssi; + item->on_channel = on_channel; + + os_memcpy(item->tsf, probe_rsp_ieee80211_ptr->rsp.timestamp, 8); + +#if CFG_WPA_CTRL_IFACE + if (reduce_ie) + { + item->ie_len = wpabuf_len(ies); + os_memcpy(item + 1, wpabuf_head(ies), wpabuf_len(ies)); + } else +#endif + { + item->ie_len = vies_len; + os_memcpy(item + 1, var_part_addr, vies_len); + } + + item->security = get_security_type_from_ie((u8 *)var_part_addr, vies_len, item->caps); + item->is_probersp = !!((framectrl & MAC_FCTRL_TYPESUBTYPE_MASK) == MAC_FCTRL_PROBERSP); + + if (replace_index >= 0) + { + sr_free_result_item((UINT8 *)result_ptr->res[replace_index]); + result_ptr->res[replace_index] = item; + //os_printf("replace bss " MACSTR ", fctl 0x%x, ie_len %d\n", + // MAC2STR(probe_rsp_ieee80211_ptr->bssid), framectrl, item->ie_len); + } + else + { + result_ptr->res[result_ptr->scanu_num] = item; + result_ptr->scanu_num ++; + //os_printf("add bss " MACSTR ", fctl 0x%x, ie_len %d\n", + // MAC2STR(probe_rsp_ieee80211_ptr->bssid), framectrl, item->ie_len); + } + +scan_rst_exit: +#if CFG_WPA_CTRL_IFACE + if (ies) + wpabuf_free(ies); +#endif + + return ret; +} + +void rwnx_handle_recv_msg(struct ke_msg *rx_msg) +{ + uint32_t param; + extern FUNC_1PARAM_PTR bk_wlan_get_status_cb(void); + FUNC_1PARAM_PTR fn = bk_wlan_get_status_cb(); + + //bk_printf("%s: msgid 0x%x\n", __func__, rx_msg->id); + switch (rx_msg->id) { + + /**************************************************************************/ + /* scan_hdlrs */ + /**************************************************************************/ + case SCANU_START_CFM: + /* scan complete */ + if(scan_rst_set_ptr) + { + resultful_scan_cfm = 1; + } + + mhdr_scanu_start_cfm(rx_msg, scan_rst_set_ptr); + break; + + case SCANU_RESULT_IND: + if(resultful_scan_cfm && scan_rst_set_ptr) + { + sr_release_scan_results(scan_rst_set_ptr); + scan_rst_set_ptr = 0; + resultful_scan_cfm = 0; + } + + if(0 == scan_rst_set_ptr) + { + scan_rst_set_ptr = (SCAN_RST_UPLOAD_T *)sr_malloc_shell(); + ASSERT(scan_rst_set_ptr); + scan_rst_set_ptr->scanu_num = 0; + scan_rst_set_ptr->res = (SCAN_RST_ITEM_PTR*)&scan_rst_set_ptr[1]; + } + + mhdr_scanu_result_ind(scan_rst_set_ptr, rx_msg, rx_msg->param_len); + break; + + /**************************************************************************/ + /* sm_hdlrs */ + /**************************************************************************/ + case SM_CONNECT_IND: + /* connect indication */ + if(scan_rst_set_ptr) { + sr_release_scan_results(scan_rst_set_ptr); + scan_rst_set_ptr = 0; + } + + mhdr_connect_ind(rx_msg, rx_msg->param_len); + break; + +#if defined(CFG_IEEE80211W) + case RXU_MGT_IND: + // STA mgmt: FIXME: AP may sends RXU_MGT_IND? + mhdr_mgmt_ind(rx_msg, rx_msg->param_len); + break; +#endif + + case SM_DISCONNECT_IND: + /* disconnect indication */ + os_printf("SM_DISCONNECT_IND\r\n"); + mhdr_disconnect_ind(rx_msg); + + extern UINT32 rwnx_sys_is_enable_hw_tpc(void); + if(rwnx_sys_is_enable_hw_tpc() == 0) + rwnx_cal_set_txpwr(20, 11); + break; + + case SM_CONNCTION_START_IND: + if(fn) + { + param = RW_EVT_STA_CONNECTING; + (*fn)(¶m); + } + mhdr_set_station_status(RW_EVT_STA_CONNECTING); + break; + + case SM_BEACON_LOSE_IND: + if(fn) + { + param = RW_EVT_STA_BEACON_LOSE; + (*fn)(¶m); + } + mhdr_set_station_status(RW_EVT_STA_BEACON_LOSE); + break; + + case SM_DISASSOC_IND: + { + struct sm_fail_stat *status_ind; + + status_ind = (struct sm_fail_stat *)rx_msg->param; + os_null_printf("[wzl]SM_DISASSOC_IND:%d, 0x%x\r\n", (status_ind->status), fn); + switch (status_ind->status) + { + case WLAN_REASON_MICHAEL_MIC_FAILURE: + param = RW_EVT_STA_PASSWORD_WRONG; +#if RL_SUPPORT_FAST_CONNECT + rl_clear_bssid_info(); +#elif (CFG_WPA_CTRL_IFACE && CFG_WLAN_FAST_CONNECT) + wlan_clear_fast_connect_info(); +#endif + break; + + default: + param = RW_EVT_STA_DISCONNECTED; + break; + } + mhdr_set_station_status(param); + } + + if(fn) + { + (*fn)(¶m); + } + + break; + + case SM_AUTHEN_FAIL_IND: + { + struct sm_fail_stat *status_ind; + + status_ind = (struct sm_fail_stat *)rx_msg->param; + switch (status_ind->status) + { + case WLAN_REASON_PREV_AUTH_NOT_VALID: + case WLAN_REASON_4WAY_HANDSHAKE_TIMEOUT: + param = RW_EVT_STA_PASSWORD_WRONG; + break; + + case MAC_RS_DIASSOC_TOO_MANY_STA: + param = RW_EVT_STA_ASSOC_FULL; + break; + + case WLAN_REASON_DEAUTH_LEAVING: + default: + param = RW_EVT_STA_CONNECT_FAILED; + break; + } + if(fn) + { + (*fn)(¶m); + } + mhdr_set_station_status(param); + } + break; + + case SM_ASSOC_FAIL_INID: + { + struct sm_fail_stat *assoc_state; + + assoc_state = (struct sm_fail_stat *)rx_msg->param; + if(assoc_state->status == MAC_ST_ASSOC_TOO_MANY_STA) + { + param = RW_EVT_STA_ASSOC_FULL; + } + else + { + param = RW_EVT_STA_DISCONNECTED; + } + if(fn) + { + (*fn)(¶m); + } + mhdr_set_station_status(param); + } + break; + + case SM_ASSOC_IND: + if(fn) + { + param = RW_EVT_STA_CONNECTED; + (*fn)(¶m); + } + if (mhdr_get_station_status() < RW_EVT_STA_CONNECTED) + { + mhdr_set_station_status(RW_EVT_STA_CONNECTED); + } + break; + + case APM_ASSOC_IND: + if(fn) + { + param = RW_EVT_AP_CONNECTED; + (*fn)(¶m); + } + break; + + case APM_DEASSOC_IND: + if(fn) + { + param = RW_EVT_AP_DISCONNECTED; + (*fn)(¶m); + } + break; + + case APM_ASSOC_FAILED_IND: + if(fn) + { + param = RW_EVT_AP_CONNECT_FAILED; + (*fn)(¶m); + } + break; + +#if CFG_USE_AP_PS + case MM_PS_CHANGE_IND: + rwm_msdu_ps_change_ind_handler(rx_msg); + break; +#endif + + /**************************************************************************/ + /* me_hdlrs */ + /**************************************************************************/ + case ME_TKIP_MIC_FAILURE_IND: + break; + + /**************************************************************************/ + /* mm_hdlrs */ + /**************************************************************************/ + case MM_CHANNEL_SWITCH_IND: + break; + case MM_CHANNEL_PRE_SWITCH_IND: + break; + case MM_REMAIN_ON_CHANNEL_EXP_IND: + break; + case MM_PS_CHANGE_IND: + break; + case MM_TRAFFIC_REQ_IND: + break; + case MM_P2P_VIF_PS_CHANGE_IND: + break; + case MM_CSA_COUNTER_IND: + break; + case MM_CSA_FINISH_IND: + break; + case MM_CSA_TRAFFIC_IND: + break; + case MM_CHANNEL_SURVEY_IND: + break; + case MM_P2P_NOA_UPD_IND: + break; + + case MM_RSSI_STATUS_IND: + //NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT + break; + +#ifdef CONFIG_SAE_EXTERNAL + case SM_EXTERNAL_AUTH_REQUIRED_IND: { + struct ke_msg *msg_ptr; + struct sm_external_auth_required_ind *ind; + + msg_ptr = (struct ke_msg *)rx_msg; + ind = (struct sm_external_auth_required_ind *)msg_ptr->param; + + wpa_ctrl_event_copy(WPA_CTRL_EVENT_EXTERNAL_AUTH_IND, ind, sizeof(*ind)); + } break; +#endif + + default: + break; + } +} + +void rwnx_recv_msg(void) +{ + struct ke_msg *rx_msg; + MSG_SND_NODE_PTR tx_msg; + struct co_list_hdr *rx_node, *tx_node; + + GLOBAL_INT_DECLARATION(); + + while(1) + { + uint8_t find = 0; + + rx_node = co_list_pop_front(&rw_msg_rx_head); + if(!rx_node) + break; + + rx_msg = (struct ke_msg *)rx_node; + + GLOBAL_INT_DISABLE(); + tx_node = co_list_pick(&rw_msg_tx_head); + GLOBAL_INT_RESTORE(); + + while(tx_node) + { + tx_msg = (MSG_SND_NODE_PTR)tx_node; + if(rx_msg->id == tx_msg->reqid) + { + find = 1; + break; + } + + GLOBAL_INT_DISABLE(); + tx_node = co_list_next(tx_node); + GLOBAL_INT_RESTORE(); + } + + if(find) + { + int ret; + GLOBAL_INT_DISABLE(); + co_list_extract(&rw_msg_rx_head, rx_node); + co_list_extract(&rw_msg_tx_head, tx_node); + GLOBAL_INT_RESTORE(); + + if(tx_msg->cfm && rx_msg->param_len) + os_memcpy(tx_msg->cfm, &rx_msg->param[0], rx_msg->param_len); + + ret = rtos_set_semaphore(&tx_msg->semaphore); + ASSERT(0 == ret); + } + else + { + rwnx_handle_recv_msg(rx_msg); + } + + ke_msg_free(rx_msg); + } +} + +// eof + diff --git a/beken_os/beken378/func/rwnx_intf/rw_msg_rx.h b/beken_os/beken378/func/rwnx_intf/rw_msg_rx.h new file mode 100755 index 0000000..7d6677d --- /dev/null +++ b/beken_os/beken378/func/rwnx_intf/rw_msg_rx.h @@ -0,0 +1,16 @@ +#ifndef _RW_MSG_RX_H_ +#define _RW_MSG_RX_H_ + +extern void mr_kmsg_init(void); +extern void rwnx_recv_msg(void); +extern void mhdr_assoc_cfm_cb(FUNC_2PARAM_PTR ind_cb, void *ctxt); +extern void mhdr_scanu_reg_cb(FUNC_2PARAM_PTR ind_cb, void *ctxt); +extern void mhdr_deauth_evt_cb(FUNC_2PARAM_PTR ind_cb, void *ctxt); +extern void mhdr_deassoc_evt_cb(FUNC_2PARAM_PTR ind_cb, void *ctxt); +extern void mhdr_scanu_reg_cb_for_wpa(FUNC_2PARAM_PTR ind_cb, void *ctxt); +extern void mhdr_set_station_status_when_reconnect_over(void); + + +#endif // _RW_MSG_RX_H_ +// eof + diff --git a/beken_os/beken378/func/rwnx_intf/rw_msg_tx.c b/beken_os/beken378/func/rwnx_intf/rw_msg_tx.c new file mode 100755 index 0000000..7f49216 --- /dev/null +++ b/beken_os/beken378/func/rwnx_intf/rw_msg_tx.c @@ -0,0 +1,873 @@ +#include "include.h" +#include "rw_msg_tx.h" +#include "ke_msg.h" +#include "rw_ieee80211.h" +#include "rw_pub.h" +#include "mem_pub.h" +#include "common.h" + +#include "scanu_task.h" +#include "scan_task.h" +#include "mm_task.h" +#include "sm_task.h" +#include "me_task.h" +#include "apm_task.h" +#include "vif_mgmt.h" +#include "str_pub.h" +#include "mac_frame.h" +#include "lwip/def.h" +#include "lwip/errno.h" +#include "scanu_task.h" +#include "wlan_ui_pub.h" +#include "param_config.h" +#include "signal.h" +#include "mm_task.h" + +#if CFG_ROLE_LAUNCH +#include "role_launch.h" +#endif +#include "rtos_error.h" +#include "rtos_pub.h" +#include "power_save_pub.h" +#include "ble_pub.h" + +extern int bmsg_ioctl_sender(void *arg); +extern void wpa_handler_signal(void *arg, u8 vif_idx); +uint32_t rw_tx_msg_timeout_count = 0; + +int rw_msg_timeout_handler(uint32_t timeout_cnt) +{ + #if TX_MSG_TIMEOUT_ZERO_TOLERANCE + bk_reboot(); + #else + if(timeout_cnt >= TX_MSG_TIMEOUT_MAX) + { + bk_reboot(); + } + #endif + + return 0; +} + +int rw_msg_send(const void *msg_params, uint16_t reqid, void *cfm) +{ + int ret; + struct ke_msg *msg = ke_param2msg(msg_params); + uint8_t need_cfm = 0; + MSG_SND_NODE_PTR tx_msg; + + GLOBAL_INT_DECLARATION(); + + // Need wait cfm from full mac + if(cfm != NULL) + { + tx_msg = os_malloc(sizeof(MSG_SND_NODE_ST)); + if(!tx_msg) + return -1; + + tx_msg->msg = msg; + tx_msg->reqid = reqid; + tx_msg->cfm = cfm; + +#if CFG_SUPPORT_ALIOS + ret = rtos_init_semaphore(&tx_msg->semaphore, 0); +#else + ret = rtos_init_semaphore(&tx_msg->semaphore, 1); +#endif + ASSERT(0 == ret); + + GLOBAL_INT_DISABLE(); + co_list_push_back(&rw_msg_tx_head, &tx_msg->hdr); + GLOBAL_INT_RESTORE(); + + need_cfm = 1; + } + + ret = bmsg_ioctl_sender((void*)msg_params); + if (kNoErr != ret) + { + os_printf("%s failed send %d\n", __FUNCTION__, msg->id); + os_free((void*)msg_params); + + goto failed_or_timeout; + } + else if (need_cfm) + { + ret = rtos_get_semaphore(&tx_msg->semaphore, 5 * MICROSECONDS); + if (0 != ret) + { + os_printf("%s timeout for %d\n", __FUNCTION__, reqid); + extern uint8_t ble_switch_mac_sleeped; + os_printf("%s dtim_enabled=%d,rf_sleep=%d,mac_sleeped=%d,wifi_used=%d,rf_switch_to_ble=%d\n", __FUNCTION__, power_save_if_ps_rf_dtim_enabled(), power_save_if_rf_sleep(), ble_switch_mac_sleeped, if_rf_wifi_used(), is_rf_switch_to_ble()); + + extern beken_thread_t core_thread_handle; + rtos_print_stack(&core_thread_handle); + + GLOBAL_INT_DISABLE(); + co_list_extract(&rw_msg_tx_head, &tx_msg->hdr); + GLOBAL_INT_RESTORE(); + + rw_tx_msg_timeout_count ++; + + rw_msg_timeout_handler(rw_tx_msg_timeout_count); + + goto failed_or_timeout; + } + + rw_tx_msg_timeout_count = 0; + ret = rtos_deinit_semaphore(&tx_msg->semaphore); + ASSERT(0 == ret); + + os_free(tx_msg); + } + + return 0; + +failed_or_timeout: + if (need_cfm) + { + ret = rtos_deinit_semaphore(&tx_msg->semaphore); + ASSERT(0 == ret); + + os_free(tx_msg); + } + + return -1; +} + +int rw_msg_send_reset(void) +{ + void *void_param; + + /* RESET REQ has no parameter */ + void_param = ke_msg_alloc(MM_RESET_REQ, TASK_MM, TASK_API, 0); + if (!void_param) + return -1; + + return rw_msg_send(void_param, MM_RESET_CFM, NULL); +} + +int rw_msg_send_mm_active_req() +{ + struct mm_set_idle_req *active = ke_msg_alloc(MM_SET_IDLE_REQ, TASK_MM, + TASK_API, sizeof(struct mm_set_idle_req)); + + if (!active) + return -1; + + // Send the message to the LMAC + active->hw_idle = 0; + + return rw_msg_send(active, MM_SET_IDLE_CFM, NULL); +} + + +int rw_msg_send_start(void) +{ + struct mm_start_req *start_req_param; + + /* Build the START REQ message */ + start_req_param = ke_msg_alloc(MM_START_REQ, TASK_MM, TASK_API, + sizeof(struct mm_start_req)); + if (!start_req_param) + return -1; + + /* Set parameters for the START message */ + start_req_param->phy_cfg.parameters[0] = 1; + start_req_param->phy_cfg.parameters[1] = 0; + start_req_param->uapsd_timeout = 300; + start_req_param->lp_clk_accuracy = 20; + + /* Send the START REQ message to LMAC FW */ + return rw_msg_send(start_req_param, MM_START_CFM, NULL); +} + +int rw_msg_send_me_config_req(void) +{ + struct me_config_req *req; + +#if CFG_IEEE80211N + WIPHY_T *wiphy = &g_wiphy; + struct ieee80211_sta_ht_cap *ht_cap = &wiphy->bands[IEEE80211_BAND_2GHZ].ht_cap; + struct ieee80211_sta_vht_cap *vht_cap = &wiphy->bands[IEEE80211_BAND_2GHZ].vht_cap; + uint8_t *ht_mcs = (uint8_t *)&ht_cap->mcs; + int i; +#endif // CFG_IEEE80211N + + /* Build the ME_CONFIG_REQ message */ + req = ke_msg_alloc(ME_CONFIG_REQ, TASK_ME, TASK_API, + sizeof(struct me_config_req)); + if (!req) + return -1; + + /* Set parameters for the ME_CONFIG_REQ message */ +#if CFG_IEEE80211N + req->ht_supp = ht_cap->ht_supported; + req->vht_supp = vht_cap->vht_supported; + req->ht_cap.ht_capa_info = cpu_to_le16(ht_cap->cap); + req->ht_cap.a_mpdu_param = ht_cap->ampdu_factor | + (ht_cap->ampdu_density << + IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT); + + for (i = 0; i < sizeof(ht_cap->mcs); i++) + { + req->ht_cap.mcs_rate[i] = ht_mcs[i]; + } + + req->ht_cap.ht_extended_capa = 0; + req->ht_cap.tx_beamforming_capa = 0x64000000; + req->ht_cap.asel_capa = 0x1; + + req->vht_cap.vht_capa_info = cpu_to_le32(vht_cap->cap); + req->vht_cap.rx_highest = cpu_to_le16(vht_cap->vht_mcs.rx_highest); + req->vht_cap.rx_mcs_map = cpu_to_le16(vht_cap->vht_mcs.rx_mcs_map); + req->vht_cap.tx_highest = cpu_to_le16(vht_cap->vht_mcs.tx_highest); + req->vht_cap.tx_mcs_map = cpu_to_le16(vht_cap->vht_mcs.tx_mcs_map); +#endif // CFG_IEEE80211N + + /* Send the ME_CONFIG_REQ message to LMAC FW */ + return rw_msg_send(req, ME_CONFIG_CFM, NULL); +} + +int rw_msg_send_me_chan_config_req(void) +{ + struct me_chan_config_req *req; + WIPHY_T *wiphy = &g_wiphy; + int i; + + /* Build the ME_CHAN_CONFIG_REQ message */ + req = ke_msg_alloc(ME_CHAN_CONFIG_REQ, TASK_ME, TASK_API, + sizeof(struct me_chan_config_req)); + if (!req) + return -1; + + req->chan2G4_cnt = 0; + if (wiphy->bands[IEEE80211_BAND_2GHZ].num_channels) + { + struct ieee80211_supported_band *b = &wiphy->bands[IEEE80211_BAND_2GHZ]; + for (i = 0; i < b->num_channels; i++) + { + req->chan2G4[req->chan2G4_cnt].flags = 0; + + if (b->channels[i].flags & IEEE80211_CHAN_DISABLED) + req->chan2G4[req->chan2G4_cnt].flags |= SCAN_DISABLED_BIT; + + if (b->channels[i].flags & IEEE80211_CHAN_NO_IR) + req->chan2G4[req->chan2G4_cnt].flags |= SCAN_PASSIVE_BIT; + + req->chan2G4[req->chan2G4_cnt].band = IEEE80211_BAND_2GHZ; + req->chan2G4[req->chan2G4_cnt].freq = b->channels[i].center_freq; + req->chan2G4_cnt++; + + if (req->chan2G4_cnt == SCAN_CHANNEL_2G4) + break; + } + } + + req->chan5G_cnt = 0; + if (wiphy->bands[IEEE80211_BAND_5GHZ].num_channels) + { + struct ieee80211_supported_band *b = &wiphy->bands[IEEE80211_BAND_5GHZ]; + for (i = 0; i < b->num_channels; i++) + { + req->chan5G[req->chan5G_cnt].flags = 0; + + if (b->channels[i].flags & IEEE80211_CHAN_DISABLED) + req->chan5G[req->chan5G_cnt].flags |= SCAN_DISABLED_BIT; + + if (b->channels[i].flags & IEEE80211_CHAN_NO_IR) + req->chan5G[req->chan5G_cnt].flags |= SCAN_PASSIVE_BIT; + + req->chan5G[req->chan5G_cnt].band = IEEE80211_BAND_5GHZ; + req->chan5G[req->chan5G_cnt].freq = b->channels[i].center_freq; + req->chan5G_cnt++; + if (req->chan5G_cnt == SCAN_CHANNEL_5G) + break; + } + } + /* Send the ME_CHAN_CONFIG_REQ message to LMAC FW */ + return rw_msg_send(req, ME_CHAN_CONFIG_CFM, NULL); +} + +int rw_msg_send_add_if(const unsigned char *mac, + enum nl80211_iftype iftype, + bool p2p, + struct mm_add_if_cfm *cfm) +{ + struct mm_add_if_req *add_if_req_param; + + /* Build the ADD_IF_REQ message */ + add_if_req_param = ke_msg_alloc(MM_ADD_IF_REQ, TASK_MM, TASK_API, + sizeof(struct mm_add_if_req)); + if (!add_if_req_param) + return -1; + + /* Set parameters for the ADD_IF_REQ message */ + os_memcpy(&(add_if_req_param->addr.array[0]), mac, ETH_ALEN); + switch (iftype) + { + case NL80211_IFTYPE_STATION: + add_if_req_param->type = VIF_STA; + break; + + case NL80211_IFTYPE_ADHOC: + add_if_req_param->type = VIF_IBSS; + break; + + case NL80211_IFTYPE_AP: + add_if_req_param->type = VIF_AP; + break; + + case NL80211_IFTYPE_MESH_POINT: + add_if_req_param->type = VIF_MESH_POINT; + break; + + default: + add_if_req_param->type = VIF_STA; + break; + } + + add_if_req_param->p2p = p2p; + + /* Send the ADD_IF_REQ message to LMAC FW */ + return rw_msg_send( add_if_req_param, MM_ADD_IF_CFM, cfm); +} + +int rw_msg_send_remove_if(u8 vif_index) +{ + struct ke_msg cfm; + struct mm_remove_if_req *remove_if_req; + + /* Build the MM_REMOVE_IF_REQ message */ + remove_if_req = ke_msg_alloc(MM_REMOVE_IF_REQ, TASK_MM, TASK_API, + sizeof(struct mm_remove_if_req)); + if (!remove_if_req) + return -1; + + /* Set parameters for the MM_REMOVE_IF_REQ message */ + remove_if_req->inst_nbr = vif_index; + + /* Send the MM_REMOVE_IF_REQ message to LMAC FW */ + return rw_msg_send(remove_if_req, MM_REMOVE_IF_CFM, &cfm); +} + +int rw_msg_send_apm_start_req(u8 vif_index, u8 channel, + struct apm_start_cfm *cfm) +{ + struct apm_start_req *req; + + /* Build the APM_START_REQ message */ + req = ke_msg_alloc(APM_START_REQ, TASK_APM, TASK_API, + sizeof(struct apm_start_req)); + if (!req) + return -1; + + req->basic_rates.length = 4; + req->basic_rates.array[0] = 130; + req->basic_rates.array[1] = 132; + req->basic_rates.array[2] = 139; + req->basic_rates.array[3] = 150; + + req->chan.band = 0; + req->chan.flags = 0; + req->chan.freq = rw_ieee80211_get_centre_frequency(channel); + req->center_freq1 = rw_ieee80211_get_centre_frequency(channel); + req->center_freq2 = 0; + req->ch_width = 0; + + req->bcn_addr = (UINT32)beacon; + req->bcn_len = sizeof(beacon); + req->tim_oft = 56; + req->tim_len = 6; + req->bcn_int = BEACON_INTERVAL; + + if(g_ap_param_ptr->cipher_suite > SECURITY_TYPE_WEP) + { + req->flags = WPA_WPA2_IN_USE; + req->flags |= CONTROL_PORT_HOST; + } + else + { + req->flags = 0; + } + + req->ctrl_port_ethertype = PP_HTONS(ETH_P_PAE); + req->vif_idx = vif_index; + + os_printf("apm start with vif:%d\r\n", vif_index); + + /* Send the APM_START_REQ message to LMAC FW */ + return rw_msg_send(req, APM_START_CFM, cfm); +} + +int rw_msg_send_apm_stop_req(u8 vif_index) +{ + struct apm_stop_req *req; + struct apm_stop_cfm *cfm + = (struct apm_stop_cfm *)os_malloc(sizeof(struct apm_stop_cfm)); + int ret; + /* Build the APM_STOP_REQ message */ + req = ke_msg_alloc(APM_STOP_REQ, TASK_APM, TASK_API, + sizeof(struct apm_stop_req)); + if ((!req) || (!cfm)) + { + if(cfm) + os_free(cfm); + if(req) + os_free(req); + return -1; + } + + /* Set parameters for the APM_STOP_REQ message */ + req->vif_idx = vif_index; + bk_printf("[msg]rw_msg_send_apm_stop_req\n"); + + /* Send the APM_STOP_REQ message to LMAC FW */ + //ret = rw_msg_send(req, APM_STOP_CFM, NULL); + ret = rw_msg_send(req, APM_STOP_CFM, cfm); + if(cfm->status) + { + bk_printf("[T]APM_STOP_CFM\n"); + } + os_free(cfm); + return ret; +} + +int rw_msg_send_bcn_change(void *bcn_param) +{ + struct mm_bcn_change_req *req; + BCN_PARAM_PTR param = (BCN_PARAM_PTR)bcn_param; + + /* Build the MM_BCN_CHANGE_REQ message */ + req = ke_msg_alloc(MM_BCN_CHANGE_REQ, TASK_MM, TASK_API, + sizeof(struct mm_bcn_change_req)); + if (!req) + return -1; + + /* Set parameters for the MM_BCN_CHANGE_REQ message */ + req->bcn_ptr = (u32)(param->bcn_ptr); + req->bcn_len = param->bcn_len; + req->tim_len = param->tim_len; + req->tim_oft = param->tim_oft; + req->inst_nbr = param->vif_idx; + req->bcn_ptr_malloc_flag = param->flag; + + if (param->csa_oft) + { + for (int i = 0; i < BCN_MAX_CSA_CPT; i++) + { + req->csa_oft[i] = param->csa_oft[i]; + } + } + + /* Send the MM_BCN_CHANGE_REQ message to LMAC FW */ + return rw_msg_send(req, MM_BCN_CHANGE_CFM, NULL); +} + +int rw_msg_send_me_sta_add(struct add_sta_st *param, + struct me_sta_add_cfm *cfm) +{ + struct me_sta_add_req *req; + + /* Build the MM_STA_ADD_REQ message */ + req = ke_msg_alloc(ME_STA_ADD_REQ, TASK_ME, TASK_API, + sizeof(struct me_sta_add_req)); + if (!req) + return -1; + + /* Set parameters for the MM_STA_ADD_REQ message */ + os_memcpy(&(req->mac_addr.array[0]), param->sta_addr, ETH_ALEN); + + req->vif_idx = param->ap_vif_idx; + req->aid = param->aid; + req->flags = 0x01; // 1:STA_QOS_CAPA 2: STA_HT_CAPA + + os_printf("hapd_intf_sta_add:%d, vif:%d\r\n", req->aid, req->vif_idx); + + req->rate_set.length = 12; + req->rate_set.array[0] = 130; + req->rate_set.array[1] = 132; + req->rate_set.array[2] = 139; + req->rate_set.array[3] = 150; + req->rate_set.array[4] = 36; + req->rate_set.array[5] = 48; + req->rate_set.array[6] = 72; + req->rate_set.array[7] = 108; + req->rate_set.array[8] = 12; + req->rate_set.array[9] = 18; + req->rate_set.array[10] = 24; + req->rate_set.array[11] = 96; + + req->ht_cap.mcs_rate[0] = 255; + + /* Send the ME_STA_ADD_REQ message to LMAC FW */ + return rw_msg_send(req, ME_STA_ADD_CFM, cfm); +} + +int rw_msg_send_me_sta_del(u8 sta_idx, bool tdls_sta) +{ + struct me_sta_del_req *req; + + /* Build the MM_STA_DEL_REQ message */ + req = ke_msg_alloc(ME_STA_DEL_REQ, TASK_ME, TASK_API, + sizeof(struct me_sta_del_req)); + if (!req) + return -1; + + /* Set parameters for the MM_STA_DEL_REQ message */ + req->sta_idx = sta_idx; + req->tdls_sta = tdls_sta; + + /* Send the ME_STA_DEL_REQ message to LMAC FW */ + return rw_msg_send(req, ME_STA_DEL_CFM, NULL); +} + +int rw_msg_me_set_control_port_req(bool opened, u8 sta_idx) +{ + struct me_set_control_port_req *req; + + /* Build the ME_SET_CONTROL_PORT_REQ message */ + req = ke_msg_alloc(ME_SET_CONTROL_PORT_REQ, TASK_ME, TASK_API, + sizeof(struct me_set_control_port_req)); + if (!req) + return -1; + + /* Set parameters for the ME_SET_CONTROL_PORT_REQ message */ + req->sta_idx = sta_idx; + req->control_port_open = opened; + + /* Send the ME_SET_CONTROL_PORT_REQ message to LMAC FW */ + return rw_msg_send(req, ME_SET_CONTROL_PORT_CFM, NULL); +} + +int rw_msg_send_key_add(KEY_PARAM_T *param, struct mm_key_add_cfm *cfm) +{ + struct mm_key_add_req *key_add_req; + + /* Build the MM_KEY_ADD_REQ message */ + key_add_req = ke_msg_alloc(MM_KEY_ADD_REQ, TASK_MM, TASK_API, + sizeof(struct mm_key_add_req)); + if (!key_add_req) + return -1; + + /* Set parameters for the MM_KEY_ADD_REQ message */ + if (param->sta_idx != 0xFF) + { + /* Pairwise key */ + key_add_req->sta_idx = param->sta_idx; + } + else + { + /* Default key */ + key_add_req->sta_idx = param->sta_idx; + key_add_req->key_idx = param->key_idx; /* only useful for default keys */ + } + + key_add_req->spp = 0; + key_add_req->pairwise = 0; + key_add_req->inst_nbr = param->inst_nbr; + key_add_req->key.length = param->key.length; + os_memcpy(&(key_add_req->key.array[0]), &(param->key.array[0]), param->key.length); + + key_add_req->cipher_suite = param->cipher_suite; + + /* Send the MM_KEY_ADD_REQ message to LMAC FW */ + return rw_msg_send(key_add_req, MM_KEY_ADD_CFM, cfm); +} + +int rw_msg_send_key_del(u8 hw_key_idx) +{ + struct mm_key_del_req *key_del_req; + + /* Build the MM_KEY_DEL_REQ message */ + key_del_req = ke_msg_alloc(MM_KEY_DEL_REQ, TASK_MM, TASK_API, + sizeof(struct mm_key_del_req)); + if (!key_del_req) + return -1; + + /* Set parameters for the MM_KEY_DEL_REQ message */ + key_del_req->hw_key_idx = hw_key_idx; + + /* Send the MM_KEY_DEL_REQ message to LMAC FW */ + return rw_msg_send(key_del_req, MM_KEY_DEL_CFM, NULL); +} + +int rw_msg_send_scanu_req(SCAN_PARAM_T *scan_param) +{ + int i; + struct scanu_start_req *req; + +#if CFG_ROLE_LAUNCH + if(rl_pre_sta_set_status(RL_STATUS_STA_SCANNING)) + { + return -1; + } +#endif + + /* Build the SCANU_START_REQ message */ + req = ke_msg_alloc(SCANU_START_REQ, TASK_SCANU, TASK_API, + sizeof(struct scanu_start_req)); + if (!req) + return -1; + + /* Set parameters */ + req->vif_idx = scan_param->vif_idx; + req->no_cck = 0; + + int *freqs = scan_param->freqs; + if (!freqs[0]) { + /* no specified freq, set to all freqs supported */ + rw_ieee80211_init_scan_chan(req); + } else { + /* specified freqs: XXX 5g band */ + for (i = 0; i < ARRAY_SIZE(scan_param->freqs); i++, freqs++) { + if (!*freqs) + break; + req->chan[i].band = IEEE80211_BAND_2GHZ; + req->chan[i].flags = 0; + req->chan[i].freq = *freqs; + } + req->chan_cnt = i; + //os_printf("Using specified freqs\n"); + } + + os_memcpy(&req->bssid, &scan_param->bssid, sizeof(req->bssid)); + req->ssid_cnt = scan_param->num_ssids; + for (i = 0; i < req->ssid_cnt; i++) { + req->ssid[i].length = scan_param->ssids[i].length; + os_memcpy(req->ssid[i].array, scan_param->ssids[i].array, req->ssid[i].length); + } + + req->add_ies = 0; + req->add_ie_len = 0; + +#if CFG_WPA_CTRL_IFACE + wpa_handler_signal((void *)SIGSCAN_START, scan_param->vif_idx); +#endif + + /* Send the SCANU_START_REQ message to LMAC FW */ + return rw_msg_send(req, SCANU_START_CFM, NULL); +} + +int rw_msg_send_scanu_fast_req(FAST_SCAN_PARAM_T *fscan_param) +{ + struct scanu_fast_req *req; + + /* Build the SCANU_START_REQ message */ + req = ke_msg_alloc(SCANU_FAST_REQ, TASK_SCANU, TASK_API, + sizeof(struct scanu_fast_req)); + + req->bssid = fscan_param->bssid; + req->ch_nbr = fscan_param->ch_num; + req->maxch_time = fscan_param->max_ch_time; + req->minch_time = fscan_param->min_ch_time; + req->probe_delay = fscan_param->probe_delay; + req->ssid = fscan_param->ssid; + + return rw_msg_send(req, SCANU_FAST_CFM, NULL); +} + +int rw_msg_send_connection_loss_ind(u8 vif_index) +{ + struct mm_connection_loss_ind *ind = ke_msg_alloc(MM_CONNECTION_LOSS_IND, + TASK_SM, TASK_API, sizeof(struct mm_connection_loss_ind)); + + // Fill-in the indication message parameters + ind->inst_nbr = vif_index; + + // Send the indication to the upper layers + return rw_msg_send(ind, 0, NULL); +} + +int rw_msg_get_bss_info(u8 vif_idx, void *cfm) +{ + struct sm_get_bss_info_req *req = NULL; + + if(vif_idx >= NX_VIRT_DEV_MAX) + return -1; + + req = ke_msg_alloc(SM_GET_BSS_INFO_REQ, TASK_SM, TASK_API, + sizeof(struct sm_get_bss_info_req)); + + if (!req) + return -1; + + req->vif_idx = vif_idx; + + return rw_msg_send(req, SM_GET_BSS_INFO_CFM, cfm); +} + +int rw_msg_get_channel(void *cfm) +{ + struct phy_channel_info info; + + phy_get_channel(&info, 0); + + return info.info2; +} + +int rw_msg_set_filter(uint32_t filter) +{ + struct mm_set_filter_req *set_filter_req_param; + uint32_t rx_filter = 0; + + /* Build the MM_SET_FILTER_REQ message */ + set_filter_req_param = + ke_msg_alloc(MM_SET_FILTER_REQ, TASK_MM, TASK_API, + sizeof(struct mm_set_filter_req)); + if (!set_filter_req_param) + return -1; + + /* Now copy all the flags into the message parameter */ + set_filter_req_param->filter = rx_filter; + + + /* Send the MM_SET_FILTER_REQ message to LMAC FW */ + return rw_msg_send(set_filter_req_param, MM_SET_FILTER_CFM, NULL); +} + +int rw_msg_set_channel(uint32_t channel, uint32_t band_width, void *cfm) +{ + struct mm_set_channel_req *set_chnl_par; + + set_chnl_par = ke_msg_alloc(MM_SET_CHANNEL_REQ, TASK_MM, TASK_API, + sizeof(struct mm_set_channel_req)); + if (!set_chnl_par) + return -ENOMEM; + + set_chnl_par->band = PHY_BAND_2G4; + set_chnl_par->type = band_width;//PHY_CHNL_BW_20; + set_chnl_par->prim20_freq = set_chnl_par->center1_freq + = rw_ieee80211_get_centre_frequency(channel); + set_chnl_par->center2_freq = 0; + set_chnl_par->index = PHY_PRIM; + set_chnl_par->tx_power = 0; + set_chnl_par->index = PHY_SEC; + + /* Send the MM_SET_CHANNEL_REQ REQ message to LMAC FW */ + return rw_msg_send(set_chnl_par, MM_SET_CHANNEL_CFM, cfm); +} + +int rw_msg_send_scan_cancel_req(void *cfm) +{ + struct scan_cancel_req *req; + + /* Build the SCAN_CANCEL_REQ message */ + req = ke_msg_alloc(SCAN_CANCEL_REQ, TASK_SCAN, TASK_API, + sizeof(struct scan_cancel_req)); + if (!req) + return -1; + + /* Send the SCAN_CANCEL_REQ message to LMAC FW */ + return rw_msg_send(req, SCAN_CANCEL_CFM, cfm); +} + +int rw_msg_send_sm_disconnect_req(DISCONNECT_PARAM_T *param) +{ + struct ke_msg cfm; + struct sm_disconnect_req *req; + + /* Build the SM_DISCONNECT_REQ message */ + req = ke_msg_alloc(SM_DISCONNECT_REQ, TASK_SM, TASK_API, + sizeof(struct sm_disconnect_req)); + if (!req) + return -1; + + /* Set parameters for the SM_DISCONNECT_REQ message */ + req->reason_code = param->reason_code; + req->vif_idx = param->vif_idx; + + return rw_msg_send(req, SM_DISCONNECT_CFM, &cfm); +} + +int rw_msg_send_sm_connect_req( CONNECT_PARAM_T *sme, void *cfm) +{ + struct sm_connect_req *req; + + /* Build the SM_CONNECT_REQ message */ + req = ke_msg_alloc(SM_CONNECT_REQ, TASK_SM, TASK_API, + sizeof(struct sm_connect_req) + sme->bcn_len); + if (!req) + return -1; + + ke_msg_send_basic(SM_CONNCTION_START_IND, TASK_API, TASK_SM); + + /* Set parameters for the SM_CONNECT_REQ message */ + req->ssid.length = sme->ssid.length; + os_memcpy(req->ssid.array, sme->ssid.array, sme->ssid.length); + os_memcpy(&req->bssid, &sme->bssid, sizeof(sme->bssid)); + + req->vif_idx = sme->vif_idx; + req->chan.band = sme->chan.band; + req->chan.flags = sme->chan.flags; + req->chan.freq = sme->chan.freq; + req->flags = sme->flags; + req->ctrl_port_ethertype = PP_HTONS(ETH_P_PAE); + req->ie_len = sme->ie_len; + req->auth_type = sme->auth_type; + os_memcpy((UINT8 *)req->ie_buf, (UINT8 *)sme->ie_buf, req->ie_len); + req->bcn_len = sme->bcn_len; + if (req->bcn_len) + os_memcpy((UINT8 *)req->bcn_buf, (UINT8 *)sme->bcn_buf, req->bcn_len); + + /* Send the SM_CONNECT_REQ message to LMAC FW */ + return rw_msg_send(req, SM_CONNECT_CFM, cfm); +} + +#ifdef CONFIG_SAE_EXTERNAL +int rw_msg_send_sm_external_auth_status(EXTERNAL_AUTH_PARAM_T *auth_param) +{ + struct sm_external_auth_required_rsp *req; + + /* Build the SM_CONNECT_REQ message */ + req = ke_msg_alloc(SM_EXTERNAL_AUTH_REQUIRED_RSP, TASK_SM, TASK_API, + sizeof(struct sm_external_auth_required_rsp)); + if (!req) + return -1; + + req->vif_idx = auth_param->vif_idx; + req->status = auth_param->status; + + /* Send the SM_CONNECT_REQ message to LMAC FW */ + return rw_msg_send(req, 0/*DUMMY*/, NULL); +} +#endif + +int rw_msg_send_tim_update(u8 vif_idx, u16 aid, u8 tx_status) +{ + struct mm_tim_update_req *req; + + /* Build the MM_TIM_UPDATE_REQ message */ + req = ke_msg_alloc(MM_TIM_UPDATE_REQ, TASK_MM, TASK_API, + sizeof(struct mm_tim_update_req)); + if (!req) + return -1; + + /* Set parameters for the MM_TIM_UPDATE_REQ message */ + req->aid = aid; + req->tx_avail = tx_status; + req->inst_nbr = vif_idx; + + /* Send the MM_TIM_UPDATE_REQ message to LMAC FW */ + return rw_msg_send(req, MM_TIM_UPDATE_CFM, NULL); +} + +int rw_msg_set_power(u8 vif_idx, u8 power) +{ + struct mm_set_power_req *req; + + /* Build the MM_SET_POWER_REQ message */ + req = ke_msg_alloc(MM_SET_POWER_REQ, TASK_MM, TASK_NONE, + sizeof(struct mm_set_power_req)); + if (!req) + return -1; + + /* Set parameters for the MM_SET_POWER_REQ message */ + req->inst_nbr = vif_idx; + req->power = power; + + /* Send the MM_SET_POWER_REQ message to LMAC FW */ + return rw_msg_send(req, MM_SET_POWER_CFM, NULL); +} +// eof + diff --git a/beken_os/beken378/func/rwnx_intf/rw_msg_tx.h b/beken_os/beken378/func/rwnx_intf/rw_msg_tx.h new file mode 100755 index 0000000..337b5e8 --- /dev/null +++ b/beken_os/beken378/func/rwnx_intf/rw_msg_tx.h @@ -0,0 +1,30 @@ +#ifndef _RW_MSG_TX_H_ +#define _RW_MSG_TX_H_ + +#include "include.h" +#include "scan.h" +#include "mac.h" +#include "rw_pub.h" + +#define BEACON_INTERVAL (100) +#define TX_MSG_TIMEOUT_MAX (4) +#define TX_MSG_TIMEOUT_ZERO_TOLERANCE (0) + +struct scan_cancel_req +{ +}; + +extern void mt_reset(void); +extern void mt_me_config(void); +extern void mt_channel_config(void); +extern void mt_start(void); +extern void mt_add_if(UINT32 type); +extern void mt_apm_start(void); +extern void mt_key_add(KEY_PARAM_T *key_param); +extern void mt_key_del(KEY_PARAM_T *key_param); +extern void mt_set_ctrl_port(void); +extern void mt_sm_connect(CONNECT_PARAM_T *sme); +extern void mt_scan_start(SCAN_PARAM_T *scan_param); +#endif // _RW_MSG_TX_H_ +// eof + diff --git a/beken_os/beken378/func/sd_music/sdcard_test.c b/beken_os/beken378/func/sd_music/sdcard_test.c new file mode 100755 index 0000000..cfd7e43 --- /dev/null +++ b/beken_os/beken378/func/sd_music/sdcard_test.c @@ -0,0 +1,106 @@ +#include "include.h" +#include "arm_arch.h" + +#if CFG_USE_SDCARD_HOST + +#include "sdio_driver.h" +#include "sdcard.h" +#include "sdcard_pub.h" + +#include "drv_model_pub.h" +#include "sys_ctrl_pub.h" +#include "mem_pub.h" +#include "icu_pub.h" +#include "target_util_pub.h" + +#include "sdcard_test.h" + +extern DD_HANDLE sdcard_hdl; +uint8_t *testbuf; + +static SDIO_Error sdcard_test_open(void) +{ + UINT32 status; + + sdcard_hdl = ddev_open(SDCARD_DEV_NAME, &status, 0); + if(DD_HANDLE_UNVALID == sdcard_hdl){ + return (SDIO_Error)status; + } + return status; +} + +static void sdcard_test_close(void) +{ + ddev_close(sdcard_hdl); +} + +UINT32 sdcard_intf_test(void) +{ + SDIO_Error ret = SD_OK; + UINT32 err = SDCARD_SUCCESS; + + ret = sdcard_test_open(); + if(ret != SD_OK){ + SDCARD_FATAL("Can't open sdcard, please check\r\n"); + goto err_out; + } + SDCARD_PRT("sdcard_open is ok \r\n"); + return err; + +err_out: + SDCARD_FATAL("sdcard_test err, ret:%d\r\n", ret); + return SDCARD_FAILURE; + +} + +UINT32 test_sdcard_read(UINT32 blk) +{ + UINT32 ret; + if(sdcard_hdl == DD_HANDLE_UNVALID) + { + os_printf("no init err\r\n"); + return 1; + } + testbuf = os_malloc(512); + os_memset(testbuf, 0, 512); + if(testbuf == NULL) + return 1; + ret = ddev_read(sdcard_hdl, testbuf, 1, blk); + + for(int i = 0;i<512;i++) + { + os_printf("%x ",testbuf[i]); + } + os_printf("\r\nread over\r\n"); + + os_free(testbuf); + return ret; +} + +UINT32 test_sdcard_write(UINT32 blk) +{ + UINT32 ret; + + UINT32 i; + if(sdcard_hdl == DD_HANDLE_UNVALID) + { + os_printf("no init err\r\n"); + return 1; + } + testbuf = os_malloc(512); + if(testbuf == NULL) + return 1; + for(i=0;i<512;i++) + testbuf[i]=0x50; + //blk = 0x20000;//just for test + ret = ddev_write(sdcard_hdl, testbuf, 1, blk); + os_free(testbuf); + return ret; +} +void sdcard_intf_close(void) +{ + sdcard_test_close(); +} + +#endif + diff --git a/beken_os/beken378/func/sd_music/sdcard_test.h b/beken_os/beken378/func/sd_music/sdcard_test.h new file mode 100755 index 0000000..6432b7a --- /dev/null +++ b/beken_os/beken378/func/sd_music/sdcard_test.h @@ -0,0 +1,9 @@ +#ifndef __SDCARD_TEST_H__ +#define __SDCARD_TEST_H__ + +UINT32 sdcard_intf_test(void); + +void sdcard_intf_close(void); + +#endif + diff --git a/beken_os/beken378/func/sdio_intf/sdio_intf.c b/beken_os/beken378/func/sdio_intf/sdio_intf.c new file mode 100755 index 0000000..1bd6a2f --- /dev/null +++ b/beken_os/beken378/func/sdio_intf/sdio_intf.c @@ -0,0 +1,1694 @@ +#include "include.h" +#include "arm_arch.h" + +#include "sdio_pub.h" + +#include "sdio_intf.h" +#include "sdio_intf_pub.h" + +#include "sdio_pub.h" +#include "drv_model_pub.h" + +#include "mem_pub.h" + +#include "mac.h" +#include "ke_event.h" +#include "llc.h" +#include "txu_cntrl.h" +#include "txl_cntrl.h" + +#include "mem_pub.h" +#include "co_utils.h" +#include "scan_task.h" +#include "scanu_task.h" +#include "me_task.h" +#include "mm_task.h" +#include "sm_task.h" +#include "vif_mgmt.h" +#include "apm_task.h" +#include "rxu_task.h" + +#include "uart_pub.h" +#include "mem_pub.h" +#include "apm_task.h" +#include "mac_ie.h" + +#include "hostapd_cfg.h" +#include "sa_station.h" + +#if CFG_USE_TEMPERATURE_DETECT +#include "temp_detect_pub.h" +#endif + +#include "common.h" +#include "rwnx.h" +#include "rw_pub.h" + + + +#if CFG_SDIO +LIST_HEADER_T inbound_list; + +UINT16 freq_2_4_G[WIFI_2_4_G_CHANNEL_NUM] = +{ + 2412, + 2417, + 2422, + 2427, + 2432, + 2437, + 2442, + 2447, + 2452, + 2457, + 2462, + 2467, + 2472, + 2484 +}; + +UINT32 scan_start_flag = 0; +UINT32 scan_resp_cmd_sn = 0; +SDIO_NODE_PTR temp_mem_node_ptr; + +SDIO_NODE_PTR sdio_get_rxed_node(void) +{ + UINT32 status; + UINT32 rd_sta; + DD_HANDLE sdio_hdl; + SDIO_NODE_PTR ret = 0; + SDIO_NODE_PTR mem_node_ptr; + + sdio_hdl = ddev_open(SDIO_DEV_NAME, &status, 0); + if(DD_HANDLE_UNVALID == sdio_hdl) + { + goto rxed_exception; + } + + rd_sta = ddev_read(sdio_hdl, (char *)SDIO_DUMMY_BUFF_ADDR, SDIO_DUMMY_LENGTH, H2S_RD_SPECIAL); + if(SDIO_FAILURE == rd_sta) + { + goto rd_fail; + } + else + { + mem_node_ptr = (SDIO_NODE_PTR)rd_sta; + ret = mem_node_ptr; + } + +rd_fail: + //ddev_close(sdio_hdl); + +rxed_exception: + return ret; +} + +UINT32 sdio_get_free_node_count(void) +{ + UINT32 status; + UINT32 count = 0; + DD_HANDLE sdio_hdl; + + sdio_hdl = ddev_open(SDIO_DEV_NAME, &status, 0); + if(DD_HANDLE_UNVALID == sdio_hdl) + { + count = 0; + + goto rxed_exception; + } + + ddev_control(sdio_hdl, SDIO_CMD_GET_CNT_FREE_NODE, &count); + +rxed_exception: + return count; +} + +UINT32 sdio_get_free_node(UINT8 **buf_pptr, UINT32 buf_size) +{ + UINT32 size; + UINT32 status; + DD_HANDLE sdio_hdl; + UINT32 ret = SDIO_INTF_SUCCESS; + + sdio_hdl = ddev_open(SDIO_DEV_NAME, &status, 0); + if(DD_HANDLE_UNVALID == sdio_hdl) + { + ret = SDIO_INTF_FAILURE; + + goto rxed_exception; + } + + size = buf_size; + temp_mem_node_ptr = (SDIO_NODE_PTR)ddev_control(sdio_hdl, SDIO_CMD_GET_FREE_NODE, &size); + if(temp_mem_node_ptr) + { + *buf_pptr = temp_mem_node_ptr->addr; + temp_mem_node_ptr->length = size; + } + else + { + *buf_pptr = 0; + } + +rxed_exception: + return ret; +} + +UINT32 sdio_release_one_node(SDIO_NODE_PTR mem_node_ptr) +{ + UINT32 status; + DD_HANDLE sdio_hdl; + UINT32 ret = SDIO_INTF_SUCCESS; + + sdio_hdl = ddev_open(SDIO_DEV_NAME, &status, 0); + if(DD_HANDLE_UNVALID == sdio_hdl) + { + ret = SDIO_INTF_FAILURE; + + goto rxed_exception; + } + + ddev_control(sdio_hdl, SDIO_CMD_PUSH_FREE_NODE, (void *)mem_node_ptr); + +rxed_exception: + return ret; +} + +UINT32 sdio_emb_get_tx_info(UINT8 *buf, UINT8 *tid) +{ + *tid = 0xFF; + + return SDIO_INTF_SUCCESS; +} + +UINT32 sdio_emb_get_hwqueue_id(UINT8 tid) +{ + return AC_VI; +} + +void sdio_emb_txdesc_copy(struct txdesc *dst_local, ETHHDR_PTR eth_hdr_ptr) +{ + struct hostdesc *host_ptr; + + host_ptr = &dst_local->host; + + os_memcpy(&host_ptr->eth_dest_addr, ð_hdr_ptr->h_dest, sizeof(host_ptr->eth_dest_addr)); + os_memcpy(&host_ptr->eth_src_addr, ð_hdr_ptr->h_src, sizeof(host_ptr->eth_src_addr)); +} + +UINT32 outbound_upload_data(RW_RXIFO_PTR rx_info) +{ + UINT32 status; + DD_HANDLE sdio_hdl; + UINT32 ret = SDIO_INTF_SUCCESS; + SDIO_NODE_PTR node = temp_mem_node_ptr; + + ASSERT(rx_info->data == node->addr); + +#if 1 + STM32_FRAME_HDR *frm_hdr_ptr; + STM32_RXPD_PTR rx_ptr; + + ASSERT(node->length); + frm_hdr_ptr = (STM32_FRAME_HDR *)node->addr; + frm_hdr_ptr->len = node->length; + frm_hdr_ptr->type = MVMS_DAT; + + rx_ptr = (STM32_RXPD_PTR)&frm_hdr_ptr[1]; + os_memset(rx_ptr, 0, sizeof(STM32_RXPD_S)); + rx_ptr->pkt_ptr = 0x36; // 0x4e; +#endif + + sdio_hdl = ddev_open(SDIO_DEV_NAME, &status, 0); + if(DD_HANDLE_UNVALID == sdio_hdl) + { + ret = SDIO_INTF_FAILURE; + + goto rxed_exception; + } + + ddev_write(sdio_hdl, (char *)node, SDIO_DUMMY_LENGTH, S2H_WR_SPECIAL); + +rxed_exception: + + return ret; +} + +void inbound_cfm(void *param) +{ + LIST_HEADER_T *tmp; + LIST_HEADER_T *pos; + SDIO_NODE_PTR node; + + GLOBAL_INT_DECLARATION(); + + //SDIO_INTF_PRT("inbound_cfm\r\n"); + + GLOBAL_INT_DISABLE(); + + node = NULLPTR; + list_for_each_safe(pos, tmp, &inbound_list) + { + list_del(pos); + node = list_entry(pos, SDIO_NODE_T, node_list); + + if(node->callback) + { + (*(node->callback))(node->Lparam, node->Rparam); + } + + node->callback = NULLPTR; + node->Lparam = NULL; + node->Rparam = NULL; + + sdio_release_one_node(node); + + break; + } + + GLOBAL_INT_RESTORE(); + + return; +} + +#if 1 +UINT32 resp_inc_seqnum(void) +{ + static UINT32 seq = 0; + + seq ++; + + return seq; +} + +UINT32 resp_conversion_generic_cfm(struct ke_msg *msg, STM32_FRAME_HDR **frm_pptr, UINT16 ret_cmd) +{ + UINT32 len; + STM32_FRAME_HDR *frm; + STM32_CMD_HDR_PTR hdr_ptr; + + len = sizeof(STM32_FRAME_HDR) + sizeof(STM32_CMD_HDR_S); + frm = (STM32_FRAME_HDR *)os_malloc(len); + ASSERT(frm); + + frm->len = len; + frm->type = MVMS_CMD; + *frm_pptr = frm; + + hdr_ptr = (STM32_CMD_HDR_PTR)((UINT32)frm + sizeof(STM32_FRAME_HDR)); + hdr_ptr->command = CMD_RET(ret_cmd); + hdr_ptr->result = 0; + hdr_ptr->seqnum = resp_inc_seqnum(); + hdr_ptr->size = len - sizeof(STM32_FRAME_HDR); + + *frm_pptr = frm; + + return len; +} + +UINT32 resp_conversion_rxu_mgt_ind(struct ke_msg *msg, STM32_FRAME_HDR **frm_pptr) +{ + UINT32 len; + UINT16 cmd = 0; + struct rxu_mgt_ind *mgt; + STM32_TX_MGMT_S *frm; + + mgt = (struct rxu_mgt_ind *)msg->param; + + if((mgt->framectrl & MAC_FCTRL_TYPESUBTYPE_MASK) == MAC_FCTRL_ASSOCREQ) + { + SDIO_INTF_PRT("802_11_ASSOCIATE\r\n"); + cmd = SCMD_802_11_ASSOCIATE; + } + else if((mgt->framectrl & MAC_FCTRL_TYPESUBTYPE_MASK) == MAC_FCTRL_AUTHENT) + { + SDIO_INTF_PRT("802_11_AUTHENTICATE\r\n"); + cmd = SCMD_802_11_AUTHENTICATE; + } + + len = sizeof(STM32_TX_MGMT_S); + frm = (STM32_TX_MGMT_S *)os_malloc(len); + ASSERT(frm); + + *frm_pptr = (STM32_FRAME_HDR *)frm; + + frm->len = len; + frm->type = MVMS_CMD; + frm->hdr.command = cmd; + frm->hdr.result = 0; + frm->hdr.size = len - sizeof(STM32_FRAME_HDR); + + return len; +} + +UINT32 resp_conversion_start_apm_cfm(struct ke_msg *msg, STM32_FRAME_HDR **frm_pptr) +{ + return resp_conversion_generic_cfm(msg, frm_pptr, SCMD_APM_START); +} + +UINT32 resp_conversion_bcn_change_cfm(struct ke_msg *msg, STM32_FRAME_HDR **frm_pptr) +{ + return resp_conversion_generic_cfm(msg, frm_pptr, SCMD_BCN_CHANGE); +} + +UINT32 resp_conversion_mgmt_tx_cfm(struct ke_msg *msg, STM32_FRAME_HDR **frm_pptr) +{ + UINT32 len; + STM32_FRAME_HDR *frm; + STM32_CMD_HDR_PTR hdr_ptr; +#if CFG_WIFI_AP_MODE + struct me_mgmt_tx_cfm *cfm_ptr; +#endif + + len = sizeof(STM32_FRAME_HDR) + sizeof(STM32_CMD_HDR_S); + frm = (STM32_FRAME_HDR *)os_malloc(len); + ASSERT(frm); + + frm->len = len; + frm->type = MVMS_CMD; + *frm_pptr = frm; + + hdr_ptr = (STM32_CMD_HDR_PTR)((UINT32)frm + sizeof(STM32_FRAME_HDR)); + hdr_ptr->command = CMD_RET(SCMD_MGMT_TX_REQ); + hdr_ptr->result = 0; + hdr_ptr->seqnum = resp_inc_seqnum(); + hdr_ptr->size = len - sizeof(STM32_FRAME_HDR); + + *frm_pptr = frm; + +#if CFG_WIFI_AP_MODE + cfm_ptr = (struct me_mgmt_tx_cfm *)msg->param; + if(CO_OK == cfm_ptr->status) + { + extern int ke_mgmt_packet_tx(unsigned char * buf, int len, int flag); + + ke_mgmt_packet_tx((unsigned char *)cfm_ptr->hostid, cfm_ptr->length, 0); + if(cfm_ptr->rsp_frm_new) + { + os_free((void *)cfm_ptr->hostid); + } + } +#endif + + return len; +} + + +UINT32 resp_conversion_add_sta_cfm(struct ke_msg *msg, STM32_FRAME_HDR **frm_pptr) +{ + return resp_conversion_generic_cfm(msg, frm_pptr, SCMD_ADD_STA_REQ); +} + +UINT32 resp_conversion_reset_cfm(struct ke_msg *msg, STM32_FRAME_HDR **frm_pptr) +{ + return resp_conversion_generic_cfm(msg, frm_pptr, SCMD_RESET_REQ); +} + +UINT32 resp_conversion_me_config_cfm(struct ke_msg *msg, STM32_FRAME_HDR **frm_pptr) +{ + return resp_conversion_generic_cfm(msg, frm_pptr, SCMD_ME_CONFIG_REQ); +} + +UINT32 resp_conversion_me_chan_config_cfm(struct ke_msg *msg, STM32_FRAME_HDR **frm_pptr) +{ + return resp_conversion_generic_cfm(msg, frm_pptr, SCMD_ME_CHAN_CONFIG_REQ); +} + +UINT32 resp_conversion_start_cfm(struct ke_msg *msg, STM32_FRAME_HDR **frm_pptr) +{ + return resp_conversion_generic_cfm(msg, frm_pptr, SCMD_START_REQ); +} + +UINT32 resp_conversion_add_if_cfm(struct ke_msg *msg, STM32_FRAME_HDR **frm_pptr) +{ + return resp_conversion_generic_cfm(msg, frm_pptr, SCMD_ADD_IF_REQ); +} + +UINT32 resp_conversion_set_port_cfm(struct ke_msg *msg, STM32_FRAME_HDR **frm_pptr) +{ + return resp_conversion_generic_cfm(msg, frm_pptr, SCMD_SET_PORT_REQ); +} + +UINT32 resp_conversion_key_add_cfm(struct ke_msg *msg, STM32_FRAME_HDR **frm_pptr) +{ + return resp_conversion_generic_cfm(msg, frm_pptr, SCMD_802_11_KEY_MATERIAL); +} + +UINT32 resp_conversion_connect_ind(struct ke_msg *msg, STM32_FRAME_HDR **frm_pptr) +{ + UINT32 len; + STM32_FRAME_HDR *frm; + ASSOC_RESP_PTR assoc_rsp_ptr; + struct sm_connect_indication *conn_ind_ptr; +#if CFG_REAL_SDIO + len = sizeof(STM32_FRAME_HDR) + sizeof(STM32_CMD_HDR_S) + msg->param_len; +#else + len = sizeof(STM32_FRAME_HDR) + sizeof(ASSOC_RESP_S); +#endif + frm = (STM32_FRAME_HDR *)os_malloc(len); + ASSERT(frm); + + frm->len = len; + frm->type = MVMS_CMD; + *frm_pptr = frm; + + conn_ind_ptr = (struct sm_connect_indication *)msg->param; + SDIO_INTF_PRT("connect_ind:%x\r\n", conn_ind_ptr->status_code); + + assoc_rsp_ptr = (ASSOC_RESP_PTR)((UINT32)frm + sizeof(STM32_FRAME_HDR)); + assoc_rsp_ptr->hdr.command = CMD_RET(SCMD_802_11_ASSOCIATE); + +#if CFG_REAL_SDIO + assoc_rsp_ptr->hdr.result = conn_ind_ptr->status_code; +#else + assoc_rsp_ptr->hdr.result = 0; +#endif + assoc_rsp_ptr->hdr.seqnum = resp_inc_seqnum(); + assoc_rsp_ptr->hdr.size = len - sizeof(STM32_FRAME_HDR); +#if CFG_REAL_SDIO + os_memcpy((void *)((UINT32)assoc_rsp_ptr + sizeof(STM32_CMD_HDR_S)), msg->param, msg->param_len); +#else + assoc_rsp_ptr->statuscode = conn_ind_ptr->status_code; +#endif + return len; +} + +UINT32 resp_conversion_scanu_cfm(struct ke_msg *msg, STM32_FRAME_HDR **frm_pptr) +{ + UINT32 len; + STM32_FRAME_HDR *frm; + STM32_SCAN_RSP_PTR stm32_scan_rsp_ptr; +#if CFG_REAL_SDIO + len = sizeof(STM32_FRAME_HDR) + sizeof(STM32_CMD_HDR_S); +#else + len = sizeof(STM32_FRAME_HDR) + sizeof(STM32_SCAN_RSP_S); +#endif + + frm = (STM32_FRAME_HDR *)os_malloc(len); + ASSERT(frm); + + frm->len = len; + frm->type = MVMS_CMD; + *frm_pptr = frm; + + stm32_scan_rsp_ptr = (STM32_SCAN_RSP_PTR)((UINT32)frm + sizeof(STM32_FRAME_HDR)); + stm32_scan_rsp_ptr->hdr.command = CMD_RET(SCMD_802_11_SCAN); + stm32_scan_rsp_ptr->hdr.result = 0; + stm32_scan_rsp_ptr->hdr.seqnum = scan_resp_cmd_sn; +#if CFG_REAL_SDIO + stm32_scan_rsp_ptr->hdr.size = 0; +#else + stm32_scan_rsp_ptr->hdr.size = len - sizeof(STM32_FRAME_HDR); + stm32_scan_rsp_ptr->bssdescriptsize = sizeof(BEACON_INFO_S); + stm32_scan_rsp_ptr->nr_sets = 0; +#endif + return len; +} + +UINT32 resp_conversion_scanu_ret(struct ke_msg *msg, STM32_FRAME_HDR **frm_pptr) +{ + UINT32 len; + STM32_FRAME_HDR *frm; + SCANU_RET_IND_PTR scanu_ret_ptr; + STM32_SCAN_RSP_PTR stm32_scan_rsp_ptr; + IEEE80211_PROBE_RSP_PTR probe_rsp_ieee80211_ptr; +#if (! CFG_REAL_SDIO) + UINT32 vies_len; + BEACON_INFO_PTR beacon_ptr; + UINT8 *var_part_addr; + UINT8 *elmt_addr; + char ssid[MAC_SSID_LEN + 1]; +#endif + + scanu_ret_ptr = (SCANU_RET_IND_PTR)msg->param; + SDIO_INTF_PRT("____center:%d\r\n", scanu_ret_ptr->center_freq); + SDIO_INTF_PRT("____band:%d\r\n", scanu_ret_ptr->band); + SDIO_INTF_PRT("____rssi:%d\r\n", scanu_ret_ptr->rssi); + + probe_rsp_ieee80211_ptr = (IEEE80211_PROBE_RSP_PTR)scanu_ret_ptr->payload; + SDIO_INTF_PRT("____bssid:%x:%x:%x:%x:%x:%x\r\n", probe_rsp_ieee80211_ptr->bssid[0] + , probe_rsp_ieee80211_ptr->bssid[1] + , probe_rsp_ieee80211_ptr->bssid[2] + , probe_rsp_ieee80211_ptr->bssid[3] + , probe_rsp_ieee80211_ptr->bssid[4] + , probe_rsp_ieee80211_ptr->bssid[5]); + +#if CFG_REAL_SDIO + len = sizeof(STM32_FRAME_HDR) + sizeof(STM32_CMD_HDR_S) + + msg->param_len; +#else + vies_len = scanu_ret_ptr->length - (sizeof(SCANU_RET_IND_S) - (SCANU_RET_PAYLOAD_LEN << 2)) + - (sizeof(IEEE80211_PROBE_RSP_S) - 1) + 10; + len = sizeof(STM32_FRAME_HDR) + sizeof(STM32_SCAN_RSP_S) - 1 + + sizeof(BEACON_INFO_S) + + vies_len; + + var_part_addr = probe_rsp_ieee80211_ptr->rsp.variable; + elmt_addr = (UINT8 *)mac_ie_find((UINT32)var_part_addr, (UINT16)vies_len, MAC_ELTID_SSID); + if (elmt_addr) + { + UINT8 ssid_len = *(elmt_addr + MAC_SSID_LEN_OFT); + if (ssid_len > MAC_SSID_LEN) + ssid_len = MAC_SSID_LEN; + + os_memcpy(&ssid[0], elmt_addr + MAC_SSID_SSID_OFT, ssid_len); + ssid[ssid_len] = '\0'; + SDIO_INTF_PRT("____ssid:%s\r\n", ssid); + } +#endif + SDIO_INTF_PRT("\r\n"); + + frm = (STM32_FRAME_HDR *)os_malloc(len); + ASSERT(frm); + + *frm_pptr = frm; + + frm->len = len; + frm->type = MVMS_CMD; + + stm32_scan_rsp_ptr = (STM32_SCAN_RSP_PTR)((UINT32)frm + sizeof(STM32_FRAME_HDR)); + stm32_scan_rsp_ptr->hdr.command = CMD_RET(SCMD_802_11_SCAN); + stm32_scan_rsp_ptr->hdr.result = 0; + stm32_scan_rsp_ptr->hdr.seqnum = scan_resp_cmd_sn; +#if CFG_REAL_SDIO + stm32_scan_rsp_ptr->hdr.size = msg->param_len; + os_memcpy((void *)((UINT32)stm32_scan_rsp_ptr + sizeof(STM32_CMD_HDR_S)) , msg->param, msg->param_len); +#else + stm32_scan_rsp_ptr->hdr.size = len - sizeof(STM32_FRAME_HDR); + stm32_scan_rsp_ptr->bssdescriptsize = sizeof(BEACON_INFO_S) + vies_len; + stm32_scan_rsp_ptr->nr_sets = 1; + + beacon_ptr = &stm32_scan_rsp_ptr->beacon_info; + beacon_ptr->len = sizeof(BEACON_INFO_S) + vies_len - 2; // 2-->len + os_memcpy(beacon_ptr->bssid, probe_rsp_ieee80211_ptr->bssid, ETH_ALEN); + beacon_ptr->rssi = scanu_ret_ptr->rssi; + os_memcpy(beacon_ptr->timestamp, probe_rsp_ieee80211_ptr->rsp.timestamp, BEACON_TIMESTAMP_LEN); + beacon_ptr->beacon_interval = probe_rsp_ieee80211_ptr->rsp.beacon_int; + beacon_ptr->capability = probe_rsp_ieee80211_ptr->rsp.capab_info; + + os_memcpy(stm32_scan_rsp_ptr->tlvbuffer, probe_rsp_ieee80211_ptr->rsp.variable, vies_len); +#endif + + return len; +} + +UINT32 resp_conversion_sm_disconnect_ind(struct ke_msg *msg, + STM32_FRAME_HDR **frm_pptr) +{ + struct sm_disconnect_ind *disc = (struct sm_disconnect_ind *)msg->param; + + *frm_pptr = NULL; + SDIO_INTF_PRT("reason:%d, vif_idx:%d\r\n", disc->reason_code, disc->vif_idx); + +#if CFG_WIFI_STATION_MODE + SDIO_INTF_PRT("exit all application process\r\n"); + SDIO_INTF_PRT("polling sa_station_process to scan and associate\r\n"); + sa_station_set_reconnect_timer(); +#endif + + return 0; +} + +UINT32 sdio_resp_conversion(struct ke_msg *msg, STM32_FRAME_HDR **frm_pptr) +{ + UINT32 len = 0; + + switch (msg->id) + { + case ME_MGMT_TX_CFM: + SDIO_INTF_PRT("mgmt_tx_cfm\r\n"); + len = resp_conversion_mgmt_tx_cfm(msg, frm_pptr); + break; + + case MM_KEY_ADD_CFM: + SDIO_INTF_PRT("mm_key_add_cfm\r\n"); + len = resp_conversion_key_add_cfm(msg, frm_pptr); + break; + + case RXU_MGT_IND: + SDIO_INTF_PRT("rxu_mgt_ind\r\n"); + len = resp_conversion_rxu_mgt_ind(msg, frm_pptr); + break; + + case ME_STA_ADD_CFM: + SDIO_INTF_PRT("add_station_cfm\r\n"); + len = resp_conversion_add_sta_cfm(msg, frm_pptr); + break; + + case MM_BCN_CHANGE_CFM: + SDIO_INTF_PRT("bcn_change_cfm\r\n"); + len = resp_conversion_bcn_change_cfm(msg, frm_pptr); + break; + + case APM_START_CFM: + SDIO_INTF_PRT("apm_start_cfm\r\n"); + len = resp_conversion_start_apm_cfm(msg, frm_pptr); + break; + + case SCANU_RESULT_IND: + SDIO_INTF_PRT("scanu-result-ind\r\n"); + len = resp_conversion_scanu_ret(msg, frm_pptr); + break; + + case SCANU_START_CFM: + scan_start_flag = 0; + SDIO_INTF_PRT("scanu-start-cfm\r\n"); + len = resp_conversion_scanu_cfm(msg, frm_pptr); + break; + + case MM_RESET_CFM: + SDIO_INTF_PRT("mm-reset-cfm\r\n"); + len = resp_conversion_reset_cfm(msg, frm_pptr); + break; + + case ME_CONFIG_CFM: + SDIO_INTF_PRT("me-config-cfm\r\n"); + len = resp_conversion_me_config_cfm(msg, frm_pptr); + break; + + case ME_CHAN_CONFIG_CFM: + SDIO_INTF_PRT("me-channel-config-cfm\r\n"); + len = resp_conversion_me_chan_config_cfm(msg, frm_pptr); + break; + + case MM_START_CFM: + SDIO_INTF_PRT("mm-start-cfm\r\n"); + len = resp_conversion_start_cfm(msg, frm_pptr); + break; + + case MM_ADD_IF_CFM: + SDIO_INTF_PRT("mm-add-if-cfm\r\n"); + len = resp_conversion_add_if_cfm(msg, frm_pptr); + break; + + case SM_CONNECT_CFM: + SDIO_INTF_PRT("sm-connect-cfm\r\n"); + break; + + case SM_CONNECT_IND: + SDIO_INTF_PRT("sm-connect-ind\r\n"); + len = resp_conversion_connect_ind(msg, frm_pptr); + break; + + case ME_SET_CONTROL_PORT_CFM: + SDIO_INTF_PRT("mm-set-control-port-cfm\r\n"); + len = resp_conversion_set_port_cfm(msg, frm_pptr); + break; + + case MM_CHANNEL_SWITCH_IND: + SDIO_INTF_PRT("mm-channel-switch-ind\r\n"); + break; + + case MM_PS_CHANGE_IND: + break; + + case SM_DISCONNECT_IND: + SDIO_INTF_PRT("sm-disconnect-ind\r\n"); + len = resp_conversion_sm_disconnect_ind(msg, frm_pptr); + break; + + default: + SDIO_INTF_PRT("resp-unkown\r\n"); + break; + } + + return len; +} + +UINT32 sdio_emb_kmsg_fwd(struct ke_msg *msg) +{ + UINT32 ret; + UINT32 len; + UINT32 status; + UINT32 wr_sta; + DD_HANDLE sdio_hdl; + STM32_FRAME_HDR *frm_ptr; + + ret = SDIO_INTF_FAILURE; + + /*prepare for response content*/ + len = sdio_resp_conversion(msg, &frm_ptr); + + ke_msg_free(msg); + + if(0 == len) + { + goto tx_ok; + } + + /*forward the new message*/ + sdio_hdl = ddev_open(SDIO_DEV_NAME, &status, 0); + if(DD_HANDLE_UNVALID == sdio_hdl) + { + goto tx_exception; + } + + wr_sta = ddev_write(sdio_hdl, (char *)frm_ptr, len, S2H_WR_SYNC); + if(SDIO_FAILURE == wr_sta) + { + goto tx_exception; + } + + if(frm_ptr) + { + os_free(frm_ptr); + } + +tx_ok: + ret = SDIO_INTF_SUCCESS; + +tx_exception: + + return ret; +} +#endif + +#if 2 +#if CFG_WIFI_AP_MODE +UINT8 chan_connect = CFG_CHANNEL_AP; +#else +UINT8 chan_connect = 10; +#endif + +UINT32 ie_info[32] = {0x500016dd, 0x101f2, 0x2f25000, 0x50000001, 0x102f2, 0x2f25000}; + +void cmd_conversion_add_wep_key(STM32_FRAME_HDR *frm_ptr, struct ke_msg **kmsg_pptr) +{ + extern int hexstr2bin(const char * hex, u8 * buf, size_t len); + + UINT32 param_len; + struct ke_msg *kmsg_dst; + struct mm_key_add_req *add_wep_key_ptr; + + param_len = sizeof(struct mm_key_add_req); + kmsg_dst = (struct ke_msg *)os_malloc(sizeof(struct ke_msg) + + param_len); + ASSERT(kmsg_dst); + os_memset(kmsg_dst, 0, (sizeof(struct ke_msg) + param_len)); + + kmsg_dst->id = MM_KEY_ADD_REQ; + kmsg_dst->dest_id = TASK_MM; + kmsg_dst->src_id = DRV_TASK_ID; + kmsg_dst->param_len = param_len; + + *kmsg_pptr = kmsg_dst; + add_wep_key_ptr = (struct mm_key_add_req *)kmsg_dst->param; + + add_wep_key_ptr->cipher_suite = MAC_RSNIE_CIPHER_WEP40; + add_wep_key_ptr->sta_idx = 0xff; + add_wep_key_ptr->inst_nbr = 0; + + add_wep_key_ptr->key.length = os_strlen(CFG_WEP_KEY); + hexstr2bin(CFG_WEP_KEY, (u8 *)&add_wep_key_ptr->key.array[0], add_wep_key_ptr->key.length); + + add_wep_key_ptr->key_idx = 0; + add_wep_key_ptr->spp = 0; + + return; +} + +void cmd_conversion_start_apm(STM32_FRAME_HDR *frm_ptr, struct ke_msg **kmsg_pptr) +{ + UINT32 param_len; + struct ke_msg *kmsg_dst; + struct apm_start_req *start_req_ptr; + + param_len = sizeof(struct apm_start_req); + kmsg_dst = (struct ke_msg *)os_malloc(sizeof(struct ke_msg) + + param_len); + ASSERT(kmsg_dst); + os_memset(kmsg_dst, 0, (sizeof(struct ke_msg) + param_len)); + + kmsg_dst->id = APM_START_REQ; + kmsg_dst->dest_id = TASK_APM; + kmsg_dst->src_id = DRV_TASK_ID; + kmsg_dst->param_len = param_len; + + *kmsg_pptr = kmsg_dst; + start_req_ptr = (struct apm_start_req *)kmsg_dst->param; + start_req_ptr->basic_rates.length = 4; + start_req_ptr->basic_rates.array[0] = 130; + start_req_ptr->basic_rates.array[1] = 132; + start_req_ptr->basic_rates.array[2] = 139; + start_req_ptr->basic_rates.array[3] = 150; + start_req_ptr->chan.band = 0; + start_req_ptr->chan.freq = freq_2_4_G[chan_connect - 1]; + start_req_ptr->chan.flags = 0; + start_req_ptr->center_freq1 = freq_2_4_G[chan_connect - 1]; + start_req_ptr->center_freq2 = 0; + start_req_ptr->ch_width = 0; + start_req_ptr->bcn_addr = (UINT32)beacon; + start_req_ptr->bcn_len = sizeof(beacon); + start_req_ptr->tim_oft = 56; + start_req_ptr->tim_len = 6; + start_req_ptr->bcn_int = 100; +#if CFG_WIFI_WPA + start_req_ptr->flags = 8; +#else + start_req_ptr->flags = 0; +#endif + start_req_ptr->ctrl_port_ethertype = 36488; + start_req_ptr->vif_idx = 0; + + return; +} + +void cmd_conversion_beacon_change(STM32_FRAME_HDR *frm_ptr, struct ke_msg **kmsg_pptr) +{ + UINT32 param_len; + struct ke_msg *kmsg_dst; + struct mm_bcn_change_req *bcn_change_ptr; + + param_len = sizeof(struct mm_bcn_change_req); + kmsg_dst = (struct ke_msg *)os_malloc(sizeof(struct ke_msg) + + param_len); + ASSERT(kmsg_dst); + os_memset(kmsg_dst, 0, (sizeof(struct ke_msg) + param_len)); + + kmsg_dst->id = MM_BCN_CHANGE_REQ; + kmsg_dst->dest_id = TASK_MM; + kmsg_dst->src_id = DRV_TASK_ID; + kmsg_dst->param_len = param_len; + + *kmsg_pptr = kmsg_dst; + bcn_change_ptr = (struct mm_bcn_change_req *)kmsg_dst->param; + bcn_change_ptr->bcn_ptr = (UINT32)beacon; + bcn_change_ptr->bcn_len = sizeof(beacon); + bcn_change_ptr->tim_len = 6; + bcn_change_ptr->tim_oft = 56; + + return; +} + +/* hard code: dest addr, src addr, ap ssid, ap mac addr*/ +UINT8 auth_rsp[] = +{ + 0xb0, 0x00, 0x40, 0x01, 0x48, 0x5a, 0xb6, 0xc1 + , 0xea, 0xe1, 0x12, 0x71, 0x11, 0x71, 0x11 + , 0x71, 0x12, 0x71, 0x11, 0x71, 0x11, 0x71 + , 0xe0, 0x04, + 0, 0, 2, 0, 0, 0 +}; +UINT8 assoc_rsp[] = +{ + 0x10, 0x00, 0x40, 0x01, 0x48, 0x5a, 0xb6, 0xc1 + , 0xea, 0xe1, 0x12, 0x71, 0x11, 0x71, 0x11 + , 0x71, 0x12, 0x71, 0x11, 0x71, 0x11, 0x71 + , 0xf0, 0x04, + 0x21, 0x04, 0x00, 0x00, 0x01, 0xc0, 0x01, 0x08 + , 0x82, 0x84, 0x8B, 0x96, 0x0C, 0x12, 0x18, 0x24 + , 0x32, 0x04, 0x30, 0x48, 0x60, 0x6C, 0x2D, 0x1A + , 0x0C, 0x00, 0x1B, 0xFF, 0x00, 0x00, 0x00, 0x01 + , 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0x00, 0x01 + , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + , 0x00, 0x00, 0x3D, 0x16, 0x08, 0x00, 0x04, 0x00 + , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + , 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 + , 0x00, 0x00, 0xDD, 0x18, 0x00, 0x50, 0xF2, 0x02 + , 0x01, 0x01, 0x00, 0x00, 0x03, 0xA4, 0x00, 0x00 + , 0x27, 0xA4, 0x00, 0x00, 0x42, 0x43, 0x5E, 0x00 + , 0x62, 0x32, 0x2F, 0x00 +}; + +void cmd_conversion_mgmt_tx_req(STM32_FRAME_HDR *frm_ptr, struct ke_msg **kmsg_pptr) +{ + UINT32 param_len; + struct ke_msg *kmsg_dst; + STM32_TX_MGMT_PTR tx_mgmt_ptr; + struct me_mgmt_tx_req *mgmt_tx_ptr; + + param_len = sizeof(struct me_mgmt_tx_req); + kmsg_dst = (struct ke_msg *)os_malloc(sizeof(struct ke_msg) + + param_len); + ASSERT(kmsg_dst); + os_memset(kmsg_dst, 0, (sizeof(struct ke_msg) + param_len)); + + kmsg_dst->id = ME_MGMT_TX_REQ; + kmsg_dst->dest_id = TASK_ME; + kmsg_dst->src_id = DRV_TASK_ID; + kmsg_dst->param_len = param_len; + + *kmsg_pptr = kmsg_dst; + mgmt_tx_ptr = (struct me_mgmt_tx_req *)kmsg_dst->param; + + tx_mgmt_ptr = (STM32_TX_MGMT_PTR)frm_ptr; + if(SCMD_802_11_AUTHENTICATE == tx_mgmt_ptr->private) + { + mgmt_tx_ptr->addr = (UINT32)auth_rsp; + mgmt_tx_ptr->hostid = (UINT32)auth_rsp; + mgmt_tx_ptr->len = sizeof(auth_rsp); + } + else if(SCMD_802_11_ASSOCIATE == tx_mgmt_ptr->private) + { + mgmt_tx_ptr->addr = (UINT32)assoc_rsp; + mgmt_tx_ptr->hostid = (UINT32)assoc_rsp; + mgmt_tx_ptr->len = sizeof(assoc_rsp); + } + + return; +} + + +void cmd_conversion_add_sta_req(STM32_FRAME_HDR *frm_ptr, struct ke_msg **kmsg_pptr) +{ + UINT32 param_len; + struct ke_msg *kmsg_dst; + struct me_sta_add_req *sta_add_ptr; + + param_len = sizeof(struct me_sta_add_req); + kmsg_dst = (struct ke_msg *)os_malloc(sizeof(struct ke_msg) + + param_len); + ASSERT(kmsg_dst); + os_memset(kmsg_dst, 0, (sizeof(struct ke_msg) + param_len)); + + kmsg_dst->id = ME_STA_ADD_REQ; + kmsg_dst->dest_id = TASK_ME; + kmsg_dst->src_id = DRV_TASK_ID; + kmsg_dst->param_len = param_len; + + *kmsg_pptr = kmsg_dst; + sta_add_ptr = (struct me_sta_add_req *)kmsg_dst->param; + + sta_add_ptr->vif_idx = 0; + sta_add_ptr->aid = 1; + sta_add_ptr->flags = 0x03; + + sta_add_ptr->rate_set.length = 12; + sta_add_ptr->rate_set.array[0] = 130; + sta_add_ptr->rate_set.array[1] = 132; + sta_add_ptr->rate_set.array[2] = 139; + sta_add_ptr->rate_set.array[3] = 150; + sta_add_ptr->rate_set.array[4] = 108; + sta_add_ptr->rate_set.array[5] = 36; + sta_add_ptr->rate_set.array[6] = 48; + sta_add_ptr->rate_set.array[7] = 72; + sta_add_ptr->rate_set.array[8] = 12; + sta_add_ptr->rate_set.array[9] = 18; + sta_add_ptr->rate_set.array[10] = 24; + sta_add_ptr->rate_set.array[11] = 96; + + sta_add_ptr->ht_cap.mcs_rate[0] = 255; + + return; +} + +void cmd_conversion_reset_req(STM32_FRAME_HDR *frm_ptr, struct ke_msg **kmsg_pptr) +{ + UINT32 param_len; + struct ke_msg *kmsg_dst; + + param_len = 0; + kmsg_dst = (struct ke_msg *)os_malloc(sizeof(struct ke_msg) + + param_len); + ASSERT(kmsg_dst); + os_memset(kmsg_dst, 0, (sizeof(struct ke_msg) + param_len)); + + kmsg_dst->id = MM_RESET_REQ; + kmsg_dst->dest_id = TASK_MM; + kmsg_dst->src_id = TASK_API; + kmsg_dst->param_len = param_len; + + *kmsg_pptr = kmsg_dst; + + return; +} + +void cmd_conversion_me_config_req(STM32_FRAME_HDR *frm_ptr, struct ke_msg **kmsg_pptr) +{ + UINT32 param_len; + struct ke_msg *kmsg_dst; + + param_len = sizeof(struct me_config_req); + kmsg_dst = (struct ke_msg *)os_malloc(sizeof(struct ke_msg) + + param_len); + ASSERT(kmsg_dst); + os_memset(kmsg_dst, 0, (sizeof(struct ke_msg) + param_len)); + + kmsg_dst->id = ME_CONFIG_REQ; + kmsg_dst->dest_id = TASK_ME; + kmsg_dst->src_id = TASK_API; + kmsg_dst->param_len = param_len; + + *kmsg_pptr = kmsg_dst; + + return; +} + +void cmd_conversion_me_chan_config_req(STM32_FRAME_HDR *frm_ptr, struct ke_msg **kmsg_pptr) +{ + UINT32 i; + UINT32 param_len; + struct ke_msg *kmsg_dst; + struct me_chan_config_req *me_chan_cfg_ptr; + + param_len = sizeof(struct me_chan_config_req); + kmsg_dst = (struct ke_msg *)os_malloc(sizeof(struct ke_msg) + + param_len); + ASSERT(kmsg_dst); + os_memset(kmsg_dst, 0, (sizeof(struct ke_msg) + param_len)); + + kmsg_dst->id = ME_CHAN_CONFIG_REQ; + kmsg_dst->dest_id = TASK_ME; + kmsg_dst->src_id = TASK_API; + kmsg_dst->param_len = param_len; + + *kmsg_pptr = kmsg_dst; + + me_chan_cfg_ptr = (struct me_chan_config_req *)kmsg_dst->param; + + for(i = 0; i < WIFI_2_4_G_CHANNEL_NUM; i ++) + { + me_chan_cfg_ptr->chan2G4[i].band = WIFI_2_4_G_BAND; + me_chan_cfg_ptr->chan2G4[i].flags = 0; + me_chan_cfg_ptr->chan2G4[i].freq = freq_2_4_G[i]; + } + + me_chan_cfg_ptr->chan2G4_cnt = WIFI_2_4_G_CHANNEL_NUM; + me_chan_cfg_ptr->chan5G_cnt = 0; + + return; +} +void cmd_conversion_set_port_req(STM32_FRAME_HDR *frm_ptr, struct ke_msg **kmsg_pptr) +{ + UINT32 param_len; + struct ke_msg *kmsg_dst; + struct me_set_control_port_req *set_port_ptr; + + param_len = sizeof(struct me_set_control_port_req); + kmsg_dst = (struct ke_msg *)os_malloc(sizeof(struct ke_msg) + + param_len); + ASSERT(kmsg_dst); + os_memset(kmsg_dst, 0, (sizeof(struct ke_msg) + param_len)); + + kmsg_dst->id = ME_SET_CONTROL_PORT_REQ; + kmsg_dst->dest_id = TASK_ME; + kmsg_dst->src_id = TASK_API; + kmsg_dst->param_len = param_len; + + *kmsg_pptr = kmsg_dst; + + set_port_ptr = (struct me_set_control_port_req *)kmsg_dst->param; + set_port_ptr->control_port_open = 1; + set_port_ptr->sta_idx = 0; + + return; +} + +void cmd_conversion_start_req(STM32_FRAME_HDR *frm_ptr, struct ke_msg **kmsg_pptr) +{ + UINT32 param_len; + struct ke_msg *kmsg_dst; + struct mm_start_req *mm_start_ptr; + + param_len = sizeof(struct mm_start_req); + kmsg_dst = (struct ke_msg *)os_malloc(sizeof(struct ke_msg) + + param_len); + ASSERT(kmsg_dst); + os_memset(kmsg_dst, 0, (sizeof(struct ke_msg) + param_len)); + + kmsg_dst->id = MM_START_REQ; + kmsg_dst->dest_id = TASK_MM; + kmsg_dst->src_id = TASK_API; + kmsg_dst->param_len = param_len; + + *kmsg_pptr = kmsg_dst; + + mm_start_ptr = (struct mm_start_req *)kmsg_dst->param; + + mm_start_ptr->phy_cfg.parameters[0] = 1; + mm_start_ptr->phy_cfg.parameters[1] = 0; + mm_start_ptr->uapsd_timeout = 300; + + return; +} + +void cmd_conversion_assoc_req(STM32_FRAME_HDR *frm_ptr, struct ke_msg **kmsg_pptr) +{ + UINT32 param_len; + struct ke_msg *kmsg_dst; + ASSOC_REQ_PTR asso_ptr; + struct sm_connect_req *sm_connect_req_ptr; +#if CFG_REAL_SDIO + char *temp; +#endif + + asso_ptr = (ASSOC_REQ_PTR)&frm_ptr[1]; + + param_len = sizeof(struct sm_connect_req); + kmsg_dst = (struct ke_msg *)os_malloc(sizeof(struct ke_msg) + + param_len); + ASSERT(kmsg_dst); + os_memset(kmsg_dst, 0, (sizeof(struct ke_msg) + param_len)); + + kmsg_dst->id = SM_CONNECT_REQ; + kmsg_dst->dest_id = TASK_SM; + kmsg_dst->src_id = TASK_API; + kmsg_dst->param_len = param_len; + + *kmsg_pptr = kmsg_dst; + sm_connect_req_ptr = (struct sm_connect_req *)kmsg_dst->param; +#if CFG_REAL_SDIO + temp = (char *)((UINT32)asso_ptr + sizeof(STM32_CMD_HDR_S)); + os_memcpy((char *)&sm_connect_req_ptr->ssid, temp, sizeof(struct mac_ssid)); + os_memcpy((char *)&sm_connect_req_ptr->bssid, + temp + sizeof(struct mac_ssid) + 1, sizeof(struct sm_connect_req) - sizeof(struct mac_ssid)); + +#if CFG_WIFI_WEP + sm_connect_req_ptr->auth_type = MAC_AUTH_ALGO_SHARED; +#else + sm_connect_req_ptr->auth_type = MAC_AUTH_ALGO_OPEN; +#endif +#else +#if (0 == CFG_WIFI_AP_MODE) + sm_connect_req_ptr->ssid.length = os_strlen((const char *)CFG_OOB_CONNECT_SSID); + os_memcpy(sm_connect_req_ptr->ssid.array, CFG_OOB_CONNECT_SSID, sm_connect_req_ptr->ssid.length); +#endif + + os_memcpy(&sm_connect_req_ptr->bssid, &asso_ptr->bssid, sizeof(asso_ptr->bssid)); + + sm_connect_req_ptr->chan.band = 0; + sm_connect_req_ptr->chan.flags = 0; + sm_connect_req_ptr->chan.freq = freq_2_4_G[chan_connect - 1]; + sm_connect_req_ptr->flags = 1; // wpa 5 + sm_connect_req_ptr->ctrl_port_ethertype = 36488; + sm_connect_req_ptr->ie_len = 0; // wpa 24 + +#if CFG_WIFI_WEP + sm_connect_req_ptr->auth_type = MAC_AUTH_ALGO_SHARED | MAC_AUTH_ALGO_OPEN; +#else + sm_connect_req_ptr->auth_type = MAC_AUTH_ALGO_OPEN; +#endif + + sm_connect_req_ptr->vif_idx = 0; + os_memcpy(sm_connect_req_ptr->ie_buf, ie_info, sm_connect_req_ptr->ie_len); +#endif + return; +} + +void cmd_conversion_key_material_req(STM32_FRAME_HDR *frm_ptr, struct ke_msg **kmsg_pptr) +{ + UINT32 param_len; + struct ke_msg *kmsg_dst; + struct mm_key_add_req *key_add_req_ptr; + STM32_KEY_MATERIAL_PTR key_material_ptr; + + key_material_ptr = (STM32_KEY_MATERIAL_PTR)&frm_ptr[1]; + + param_len = sizeof(struct mm_key_add_req); + kmsg_dst = (struct ke_msg *)os_malloc(sizeof(struct ke_msg) + + param_len); + ASSERT(kmsg_dst); + os_memset(kmsg_dst, 0, (sizeof(struct ke_msg) + param_len)); + + kmsg_dst->id = MM_KEY_ADD_REQ; + kmsg_dst->dest_id = TASK_MM; + kmsg_dst->src_id = TASK_API; + kmsg_dst->param_len = param_len; + + *kmsg_pptr = kmsg_dst; + key_add_req_ptr = (struct mm_key_add_req *)kmsg_dst->param; + + if(key_material_ptr->action) + { + key_add_req_ptr->sta_idx = 255; + } + else + { + key_add_req_ptr->sta_idx = 0; + } + + key_add_req_ptr->key_idx = 0; + key_add_req_ptr->key.length = os_strlen(CFG_WEP_KEY); + hexstr2bin(CFG_WEP_KEY, (u8 *)&key_add_req_ptr->key.array[0], key_add_req_ptr->key.length); + key_add_req_ptr->cipher_suite = 1; + key_add_req_ptr->inst_nbr = 0; + key_add_req_ptr->spp = 0; + + return; +} + +void cmd_conversion_add_if_req(STM32_FRAME_HDR *frm_ptr, struct ke_msg **kmsg_pptr) +{ + UINT32 param_len; + struct ke_msg *kmsg_dst; + struct mm_add_if_req *mm_add_if_ptr; + + param_len = sizeof(struct mm_add_if_req); + kmsg_dst = (struct ke_msg *)os_malloc(sizeof(struct ke_msg) + + param_len); + ASSERT(kmsg_dst); + os_memset(kmsg_dst, 0, (sizeof(struct ke_msg) + param_len)); + + kmsg_dst->id = MM_ADD_IF_REQ; + kmsg_dst->dest_id = TASK_MM; + kmsg_dst->src_id = TASK_API; + kmsg_dst->param_len = param_len; + + *kmsg_pptr = kmsg_dst; + + mm_add_if_ptr = (struct mm_add_if_req *)kmsg_dst->param; + +#if CFG_WIFI_AP_MODE + SDIO_INTF_PRT("vif_ap\r\n"); + mm_add_if_ptr->type = VIF_AP; +#else + SDIO_INTF_PRT("vif_sta\r\n"); + mm_add_if_ptr->type = VIF_STA; +#endif + + return; +} + +void cmd_conversion_802_11_scan(STM32_FRAME_HDR *frm_ptr, struct ke_msg **kmsg_pptr) +{ + UINT32 param_len; + struct ke_msg *kmsg_dst; + STM32_CMD_HDR_PTR scmd_hdr_ptr; + struct scan_start_req *scan_start_ptr; +#if (! CFG_REAL_SDIO) + UINT32 ssid_id; + UINT32 channel_id; + UINT32 ie_total_len; + MRVL_IE_HDR_PTR mrvl_ie_ptr; + STM32_CMD_802_11_SCAN_PTR scan_cmd_ptr; +#endif + + kmsg_dst = NULLPTR; + scmd_hdr_ptr = (STM32_CMD_HDR_PTR)&frm_ptr[1]; + + param_len = sizeof(struct scan_start_req); + kmsg_dst = (struct ke_msg *)os_malloc(sizeof(struct ke_msg) + + param_len); + ASSERT(kmsg_dst); + os_memset(kmsg_dst, 0, (sizeof(struct ke_msg) + param_len)); + + /*directly set value*/ + kmsg_dst->id = SCANU_START_REQ; + kmsg_dst->dest_id = TASK_SCANU; + kmsg_dst->param_len = param_len; + + kmsg_dst->hdr.next = NULL; + kmsg_dst->src_id = TASK_API; + +#if (! CFG_REAL_SDIO) + /* conversion*/ + ssid_id = 0; + channel_id = 0; + + scan_start_ptr = (struct scan_start_req *)kmsg_dst->param; + scan_cmd_ptr = (STM32_CMD_802_11_SCAN_PTR)scmd_hdr_ptr; + mrvl_ie_ptr = (MRVL_IE_HDR_PTR)scan_cmd_ptr->tlvbuffer; + ie_total_len = scmd_hdr_ptr->size - ((UINT32)mrvl_ie_ptr - (UINT32)scmd_hdr_ptr); + + while(ie_total_len) + { + ie_total_len -= (mrvl_ie_ptr->len + sizeof(MRVL_IE_HDR_S)); + switch(mrvl_ie_ptr->type) + { + case TLV_TYPE_SSID: + { + MRVL_IE_SSID_PARAM_PTR ssid; + + ssid = (MRVL_IE_SSID_PARAM_PTR)mrvl_ie_ptr; + scan_start_ptr->ssid[ssid_id].length = ssid->header.len; + os_memcpy(scan_start_ptr->ssid[ssid_id].array, ssid->ssid, ssid->header.len); + + ssid_id ++; + scan_start_ptr->ssid_cnt = ssid_id; + + break; + } + + case TLV_TYPE_CHANLIST: + { + UINT32 i; + + for(i = 0; i < WIFI_2_4_G_CHANNEL_NUM; i ++) + { + scan_start_ptr->chan[i].band = WIFI_2_4_G_BAND; + scan_start_ptr->chan[i].flags = 0; + scan_start_ptr->chan[i].freq = freq_2_4_G[i]; + + channel_id ++; + } + + scan_start_ptr->chan_cnt = channel_id; + + break; + } + + case TLV_TYPE_RATES: + { + break; + } + + default: + break; + } + + mrvl_ie_ptr = (MRVL_IE_HDR_PTR)((UINT32)scan_cmd_ptr->tlvbuffer + + (UINT32)mrvl_ie_ptr->len + + sizeof(MRVL_IE_HDR_S)); + } + + os_memset(&scan_start_ptr->bssid, 0xff, ETH_ALEN); + + scan_start_ptr->ssid_cnt = 1; + scan_start_ptr->ssid[0].length = 0; + scan_start_ptr->add_ies = 0; + scan_start_ptr->add_ie_len = 0; +#endif + + ASSERT_ERR(ke_task_local(kmsg_dst->dest_id)); + + *kmsg_pptr = kmsg_dst; + +#if CFG_REAL_SDIO + scan_start_ptr = (struct scan_start_req *)kmsg_dst->param; + + os_memcpy(scan_start_ptr, (void *)&scmd_hdr_ptr[1], kmsg_dst->param_len); +#endif + scan_resp_cmd_sn = resp_inc_seqnum(); + + return; +} + +UINT32 sdio_h2e_msg_conversion(STM32_FRAME_HDR *frm_ptr, struct ke_msg **kmsg_pptr) +{ + UINT32 ret = SDIO_INTF_SUCCESS; + STM32_CMD_HDR_PTR scmd_hdr_ptr; + + scmd_hdr_ptr = (STM32_CMD_HDR_PTR)&frm_ptr[1]; + if(frm_ptr->len <= sizeof(STM32_FRAME_HDR)) + { + ret = SDIO_INTF_FAILURE; + goto conv_exit; + } + + SDIO_INTF_PRT("cmd:%x\r\n", scmd_hdr_ptr->command); + switch(scmd_hdr_ptr->command) + { + case SCMD_ADD_WEP_KEY: + cmd_conversion_add_wep_key(frm_ptr, kmsg_pptr); + break; + + case SCMD_APM_START: + SDIO_INTF_PRT("start-ap-mode\r\n"); + cmd_conversion_start_apm(frm_ptr, kmsg_pptr); + break; + + case SCMD_BCN_CHANGE: + SDIO_INTF_PRT("beacon-change\r\n"); + break; + + case SCMD_MGMT_TX_REQ: + SDIO_INTF_PRT("mgmt_tx_req\r\n"); + cmd_conversion_mgmt_tx_req(frm_ptr, kmsg_pptr); + break; + + case SCMD_ADD_STA_REQ: + SDIO_INTF_PRT("add-sta\r\n"); + cmd_conversion_add_sta_req(frm_ptr, kmsg_pptr); + break; + + case SCMD_802_11_SCAN: +#if CFG_REAL_SDIO + if(1) +#else + if(0 == scan_start_flag) +#endif + { + scan_start_flag = 1; + SDIO_INTF_PRT("80211-scan\r\n"); + cmd_conversion_802_11_scan(frm_ptr, kmsg_pptr); + } + else + { + SDIO_INTF_PRT("discard_scan\r\n"); + ret = SDIO_INTF_FAILURE; + goto conv_exit; + } + break; + + case SCMD_RESET_REQ: + SDIO_INTF_PRT("reset-mm\r\n"); + cmd_conversion_reset_req(frm_ptr, kmsg_pptr); + break; + + case SCMD_ME_CONFIG_REQ: + SDIO_INTF_PRT("me-config\r\n"); + cmd_conversion_me_config_req(frm_ptr, kmsg_pptr); + break; + + case SCMD_ME_CHAN_CONFIG_REQ: + SDIO_INTF_PRT("me-channel-config\r\n"); + cmd_conversion_me_chan_config_req(frm_ptr, kmsg_pptr); + break; + + case SCMD_START_REQ: + SDIO_INTF_PRT("mm-start\r\n"); + cmd_conversion_start_req(frm_ptr, kmsg_pptr); + break; + + case SCMD_ADD_IF_REQ: + SDIO_INTF_PRT("add-if"); + cmd_conversion_add_if_req(frm_ptr, kmsg_pptr); + break; + + case SCMD_802_11_KEY_MATERIAL: + SDIO_INTF_PRT("mm-key-add\r\n"); + cmd_conversion_key_material_req(frm_ptr, kmsg_pptr); + break; + + case SCMD_802_11_ASSOCIATE: + SDIO_INTF_PRT("sm-connect\r\n"); + cmd_conversion_assoc_req(frm_ptr, kmsg_pptr); + break; + + case SCMD_SET_PORT_REQ: + SDIO_INTF_PRT("set-port\r\n"); + cmd_conversion_set_port_req(frm_ptr, kmsg_pptr); + break; + + default: + SDIO_INTF_PRT("default-unkown\r\n"); + ret = SDIO_INTF_FAILURE; + break; + } + +conv_exit: + return ret; +} + +void sdio_h2e_kmsg_hdlr(struct ke_msg *kmsg_ptr) +{ + ke_msg_send(ke_msg2param(kmsg_ptr)); +} +#endif + +void sdio_emb_rxed_evt(int dummy) +{ + UINT32 status; + UINT32 queue_idx; + UINT8 *content_ptr; + bool pushed = false; + SDIO_NODE_PTR mem_node_ptr; + STM32_TX_FRAME *frm_tx_ptr; + STM32_FRAME_HDR *frm_hdr_ptr; +#if CFG_REAL_SDIO + UINT8 i = 0; +#else + STM32_TXPD_S *txpd; +#endif + + queue_idx = AC_VI; + mem_node_ptr = sdio_get_rxed_node(); + + while(mem_node_ptr) + { + frm_hdr_ptr = (STM32_FRAME_HDR *)mem_node_ptr->addr; + switch(frm_hdr_ptr->type) + { + case MVMS_DAT: + { + UINT8 tid; + ETHHDR_PTR eth_hdr_ptr; + struct txdesc *txdesc_new; + GLOBAL_INT_DECLARATION(); + + GLOBAL_INT_DISABLE(); + list_add_tail(&mem_node_ptr->node_list, &inbound_list); + GLOBAL_INT_RESTORE(); + + frm_tx_ptr = (STM32_TX_FRAME *)mem_node_ptr->addr; +#if CFG_REAL_SDIO + content_ptr = (UINT8 *)&frm_tx_ptr->frm + 2; +#else + txpd = &frm_tx_ptr->frm; + content_ptr = (UINT8 *)&txpd[1]; +#endif + + eth_hdr_ptr = (ETHHDR_PTR)content_ptr; + + status = sdio_emb_get_tx_info(content_ptr, &tid); + if(SDIO_INTF_SUCCESS != status) + { + goto rxed_exception; + } + + queue_idx = sdio_emb_get_hwqueue_id(tid); + + /*allocation of the tx descriptor*/ + txdesc_new = tx_txdesc_prepare(queue_idx); + if(TXDESC_STA_USED == txdesc_new->status) + { + fatal_prf("TFull\r\n"); + + inbound_cfm(); + + goto rxed_exception; + } + + txdesc_new->status = TXDESC_STA_USED; + sdio_emb_txdesc_copy(txdesc_new, eth_hdr_ptr); + + txdesc_new->host.flags = 0; + txdesc_new->host.orig_addr = (UINT32)mem_node_ptr->orig_addr; + txdesc_new->host.packet_addr = (UINT32)content_ptr + 14; +#if CFG_REAL_SDIO + txdesc_new->host.packet_len = frm_hdr_ptr->len - 14 - sizeof(STM32_FRAME_HDR) - 2; + txdesc_new->host.staid = 0; +#else + txdesc_new->host.packet_len = frm_hdr_ptr->len - 14 - sizeof(STM32_FRAME_HDR) - sizeof(STM32_TXPD_S); +#endif + txdesc_new->host.status_desc_addr = (UINT32)content_ptr + 14; + txdesc_new->host.ethertype = eth_hdr_ptr->h_proto; + txdesc_new->host.tid = tid; + txdesc_new->host.vif_idx = 0; + +#if (! CFG_REAL_SDIO) +#if CFG_WIFI_AP_MODE + if(is_broadcast_ether_addr(eth_hdr_ptr->h_dest)) + { + txdesc_new->host.staid = VIF_TO_BCMC_IDX(txdesc_new->host.vif_idx); + } + else + { + txdesc_new->host.staid = 0; + } +#else + txdesc_new->host.staid = 0; +#endif +#endif + // Initialize some fields of the descriptor + txdesc_new->lmac.agg_desc = NULL; + txdesc_new->lmac.hw_desc->cfm.status = 0; + +#if NX_POWERSAVE + txl_cntrl_inc_pck_cnt(); +#endif + txu_cntrl_push(txdesc_new, queue_idx); + + pushed = true; + +#if FOR_SDIO_BLK_512 + i++; +#endif + break; + } + + case MVMS_CMD: + { + UINT32 ret; + struct ke_msg *kmsg; + + ret = sdio_h2e_msg_conversion(frm_hdr_ptr, &kmsg); + if(SDIO_INTF_SUCCESS == ret) + { + sdio_h2e_kmsg_hdlr(kmsg); + } + + sdio_release_one_node(mem_node_ptr); + + break; + } + + case MVMS_EVENT: + break; + + case MVMS_TXDONE: + break; + + default: + break; + } + + + mem_node_ptr = sdio_get_rxed_node(); + +#if FOR_SDIO_BLK_512 + if(i > 10) + { + mem_node_ptr = 0; + } +#endif + } + + if(0 == mem_node_ptr) + { + ke_evt_clear(KE_EVT_SDIO_RXED_DATA_BIT); + } + + if (pushed) + { +#if (NX_AMPDU_TX) + // Check if the current A-MPDU under construction has to be closed + txl_aggregate_check(queue_idx); +#endif //(NX_AMPDU_TX) + } + +rxed_exception: + return; +} + +void sdio_rxed_trigger_evt(void) +{ + ke_evt_set(KE_EVT_SDIO_RXED_DATA_BIT); +} + +UINT32 sdio_intf_init(void) +{ + UINT32 ret; + UINT32 status; + DD_HANDLE sdio_hdl; + RW_CONNECTOR_T intf; + + ret = SDIO_INTF_FAILURE; + + intf.msg_outbound_func = sdio_emb_kmsg_fwd; + intf.data_outbound_func = outbound_upload_data; + intf.rx_alloc_func = sdio_get_free_node; + intf.get_rx_valid_status_func = sdio_get_free_node_count; + intf.tx_confirm_func = inbound_cfm; + rwnxl_register_connector(&intf); + + INIT_LIST_HEAD(&inbound_list); + + sdio_hdl = ddev_open(SDIO_DEV_NAME, &status, 0); + if(DD_HANDLE_UNVALID == sdio_hdl) + { + goto init_exception; + } + + ddev_control(sdio_hdl, SDIO_CMD_REG_RX_CALLBACK, (void *)sdio_rxed_trigger_evt); + + SDIO_INTF_PRT("sdio_intf_init\r\n"); + ret = SDIO_INTF_SUCCESS; + +init_exception: + + return ret; +} +#endif // CFG_SDIO +// EOF + diff --git a/beken_os/beken378/func/sdio_intf/sdio_intf.h b/beken_os/beken378/func/sdio_intf/sdio_intf.h new file mode 100755 index 0000000..a69bb38 --- /dev/null +++ b/beken_os/beken378/func/sdio_intf/sdio_intf.h @@ -0,0 +1,552 @@ +#ifndef _SDIO_INTF_H_ +#define _SDIO_INTF_H_ + +#include "tx_swdesc.h" + +#define SDIO_INTF_DEBUG + +#ifdef SDIO_INTF_DEBUG +#define SDIO_INTF_PRT os_printf +#define SDIO_INTF_WPRT warning_prf +#else +#define SDIO_INTF_PRT os_null_printf +#define SDIO_INTF_WPRT warning_prf +#endif + +#define H2E_MSG_BUF_SIZE 31 + +#define WIFI_2_4_G_BAND (0) +#define WIFI_5_0_G_BAND (1) +#define WIFI_2_4_G_CHANNEL_NUM (14) + +#if CFG_SDIO +struct h2e_msg +{ + uint32_t dummy_word; // used to cope with kernel message structure + uint32_t msg[H2E_MSG_BUF_SIZE]; // body of the msg +}; + +#define E2A_MSG_PARAM_SIZE 256 // size in 4-byte words + +/// Message structure for MSGs from Emb to App +typedef struct e2a_msg +{ + UINT16 id; ///< Message id. + UINT16 dummy_dest_id; ///< + UINT16 dummy_src_id; ///< + UINT16 param_len; ///< Parameter embedded struct length. + UINT16 param[E2A_MSG_PARAM_SIZE]; ///< Parameter embedded struct. Must be word-aligned. + UINT16 pattern; ///< Used to stamp a valid MSG buffer +} E2A_MSG_S, *E2A_MSG_PTR; + +#define SCANU_RET_PAYLOAD_LEN 128 + +typedef struct scanu_result_ind +{ + /// Length of the frame + UINT16 length; + /// Frame control field of the frame. + UINT16 framectrl; + /// Center frequency on which we received the packet + UINT16 center_freq; + /// PHY band + UINT8 band; + /// Index of the station that sent the frame. 0xFF if unknown. + UINT8 sta_idx; + /// Index of the VIF that received the frame. 0xFF if unknown. + UINT8 inst_nbr; + /// RSSI of the received frame. + INT8 rssi; + /// Frame payload. + UINT32 payload[SCANU_RET_PAYLOAD_LEN]; +} SCANU_RET_IND_S, *SCANU_RET_IND_PTR; + + +typedef struct probe_resp +{ + UINT8 timestamp[8]; + UINT16 beacon_int; + UINT16 capab_info; + + /* followed by some of SSID, Supported rates, + * FH Params, DS Params, CF Params, IBSS Params */ + UINT8 variable[1]; +} __attribute__ ((packed)) probe_resp_s; + +typedef struct ieee80211_probe_rsp +{ + UINT16 frame_control; + UINT16 duration; + UINT8 da[6]; + UINT8 sa[6]; + UINT8 bssid[6]; + UINT16 seq_ctrl; + struct probe_resp rsp; +} __attribute__ ((packed)) IEEE80211_PROBE_RSP_S, *IEEE80211_PROBE_RSP_PTR; + +#define STM32_PLATFORM + +#ifdef STM32_PLATFORM + +#define CMD_RET(cmd) (0x8000 | cmd) + +/* Command codes */ +#define SCMD_GET_HW_SPEC 0x0003 +#define SCMD_EEPROM_UPDATE 0x0004 +#define SCMD_802_11_RESET 0x0005 +#define SCMD_802_11_SCAN 0x0006 +#define SCMD_802_11_GET_LOG 0x000b +#define SCMD_MAC_MULTICAST_ADR 0x0010 +#define SCMD_802_11_AUTHENTICATE 0x0011 +#define SCMD_802_11_EEPROM_ACCESS 0x0059 +#define SCMD_802_11_ASSOCIATE 0x0050 +#define SCMD_802_11_SET_WEP 0x0013 +#define SCMD_802_11_GET_STAT 0x0014 +#define SCMD_802_3_GET_STAT 0x0015 +#define SCMD_802_11_SNMP_MIB 0x0016 +#define SCMD_MAC_REG_MAP 0x0017 +#define SCMD_BBP_REG_MAP 0x0018 +#define SCMD_MAC_REG_ACCESS 0x0019 +#define SCMD_BBP_REG_ACCESS 0x001a +#define SCMD_RF_REG_ACCESS 0x001b +#define SCMD_802_11_RADIO_CONTROL 0x001c +#define SCMD_802_11_RF_CHANNEL 0x001d +#define SCMD_802_11_RF_TX_POWER 0x001e +#define SCMD_802_11_RSSI 0x001f +#define SCMD_802_11_RF_ANTENNA 0x0020 +#define SCMD_802_11_PS_MODE 0x0021 +#define SCMD_802_11_DATA_RATE 0x0022 +#define SCMD_RF_REG_MAP 0x0023 +#define SCMD_802_11_DEAUTHENTICATE 0x0024 +#define SCMD_802_11_REASSOCIATE 0x0025 +#define SCMD_MAC_CONTROL 0x0028 +#define SCMD_802_11_AD_HOC_START 0x002b +#define SCMD_802_11_AD_HOC_JOIN 0x002c +#define SCMD_802_11_QUERY_TKIP_REPLY_CNTRS 0x002e +#define SCMD_802_11_ENABLE_RSN 0x002f +#define SCMD_802_11_SET_AFC 0x003c +#define SCMD_802_11_GET_AFC 0x003d +#define SCMD_802_11_AD_HOC_STOP 0x0040 +#define SCMD_802_11_HOST_SLEEP_CFG 0x0043 +#define SCMD_802_11_WAKEUP_CONFIRM 0x0044 +#define SCMD_802_11_HOST_SLEEP_ACTIVATE 0x0045 +#define SCMD_802_11_BEACON_STOP 0x0049 +#define SCMD_802_11_MAC_ADDRESS 0x004d +#define SCMD_802_11_LED_GPIO_CTRL 0x004e +#define SCMD_802_11_EEPROM_ACCESS 0x0059 +#define SCMD_802_11_BAND_CONFIG 0x0058 +#define SCMD_GSPI_BUS_CONFIG 0x005a +#define SCMD_802_11D_DOMAIN_INFO 0x005b +#define SCMD_802_11_KEY_MATERIAL 0x005e +#define SCMD_802_11_SLEEP_PARAMS 0x0066 +#define SCMD_802_11_INACTIVITY_TIMEOUT 0x0067 +#define SCMD_802_11_SLEEP_PERIOD 0x0068 +#define SCMD_802_11_TPC_CFG 0x0072 +#define SCMD_802_11_PA_CFG 0x0073 +#define SCMD_802_11_FW_WAKE_METHOD 0x0074 +#define SCMD_802_11_SUBSCRIBE_EVENT 0x0075 +#define SCMD_802_11_RATE_ADAPT_RATESET 0x0076 +#define SCMD_802_11_TX_RATE_QUERY 0x007f +#define SCMD_GET_TSF 0x0080 +#define SCMD_BT_ACCESS 0x0087 +#define SCMD_FWT_ACCESS 0x0095 +#define SCMD_802_11_MONITOR_MODE 0x0098 +#define SCMD_MESH_ACCESS 0x009b +#define SCMD_MESH_CONFIG_OLD 0x00a3 +#define SCMD_MESH_CONFIG 0x00ac +#define SCMD_SET_BOOT2_VER 0x00a5 +#define SCMD_FUNC_INIT 0x00a9 +#define SCMD_FUNC_SHUTDOWN 0x00aa +#define SCMD_802_11_BEACON_CTRL 0x00b0 + +#define SCMD_RESET_REQ 0x00b1 +#define SCMD_ME_CONFIG_REQ 0x00b2 +#define SCMD_ME_CHAN_CONFIG_REQ 0x00b3 +#define SCMD_START_REQ 0x00b4 +#define SCMD_ADD_IF_REQ 0x00b5 +#define SCMD_SET_PORT_REQ 0x00b6 + +#define SCMD_APM_START 0x00b7 +#define SCMD_BCN_CHANGE 0x00b8 +#define SCMD_MGMT_TX_REQ 0x00b9 +#define SCMD_ADD_STA_REQ 0x00ba +#define SCMD_ADD_WEP_KEY 0x00bb + +/* For the IEEE Power Save */ +#define SCMD_SUBSCMD_ENTER_PS 0x0030 +#define SCMD_SUBSCMD_EXIT_PS 0x0031 +#define SCMD_SUBSCMD_SLEEP_CONFIRMED 0x0034 +#define SCMD_SUBSCMD_FULL_POWERDOWN 0x0035 +#define SCMD_SUBSCMD_FULL_POWERUP 0x0036 + +#define SCMD_ENABLE_RSN 0x0001 +#define SCMD_DISABLE_RSN 0x0000 + +#define SCMD_ACT_GET 0x0000 +#define SCMD_ACT_SET 0x0001 +#define SCMD_ACT_GET_AES 0x0002 +#define SCMD_ACT_SET_AES 0x0003 +#define SCMD_ACT_REMOVE_AES 0x0004 + +/* Define action or option for SCMD_802_11_SET_WEP */ +#define SCMD_ACT_ADD 0x0002 +#define SCMD_ACT_REMOVE 0x0004 +#define SCMD_ACT_USE_DEFAULT 0x0008 + +#define SCMD_TYPE_WEP_40_BIT 0x01 +#define SCMD_TYPE_WEP_104_BIT 0x02 + +#define SCMD_NUM_OF_WEP_KEYS 4 + +#define SCMD_WEP_KEY_INDEX_MASK 0x3fff + +/* Define action or option for SCMD_802_11_RESET */ +#define SCMD_ACT_HALT 0x0003 + +/* Define action or option for SCMD_802_11_SCAN */ +#define SCMD_BSS_TYPE_BSS 0x0001 +#define SCMD_BSS_TYPE_IBSS 0x0002 +#define SCMD_BSS_TYPE_ANY 0x0003 + +/* Define action or option for SCMD_802_11_SCAN */ +#define SCMD_SCAN_TYPE_ACTIVE 0x0000 +#define SCMD_SCAN_TYPE_PASSIVE 0x0001 + +#define SCMD_SCAN_RADIO_TYPE_BG 0 + +#define SCMD_SCAN_PROBE_DELAY_TIME 0 + +/* Define action or option for SCMD_MAC_CONTROL */ +#define SCMD_ACT_MAC_RX_ON 0x0001 +#define SCMD_ACT_MAC_TX_ON 0x0002 +#define SCMD_ACT_MAC_LOOPBACK_ON 0x0004 +#define SCMD_ACT_MAC_WEP_ENABLE 0x0008 +#define SCMD_ACT_MAC_INT_ENABLE 0x0010 +#define SCMD_ACT_MAC_MULTICAST_ENABLE 0x0020 +#define SCMD_ACT_MAC_BROADCAST_ENABLE 0x0040 +#define SCMD_ACT_MAC_PROMISCUOUS_ENABLE 0x0080 +#define SCMD_ACT_MAC_ALL_MULTICAST_ENABLE 0x0100 +#define SCMD_ACT_MAC_STRICT_PROTECTION_ENABLE 0x0400 + +/* Event flags for SCMD_802_11_SUBSCRIBE_EVENT */ +#define SCMD_SUBSCRIBE_RSSI_LOW 0x0001 +#define SCMD_SUBSCRIBE_SNR_LOW 0x0002 +#define SCMD_SUBSCRIBE_FAILCOUNT 0x0004 +#define SCMD_SUBSCRIBE_BCNMISS 0x0008 +#define SCMD_SUBSCRIBE_RSSI_HIGH 0x0010 +#define SCMD_SUBSCRIBE_SNR_HIGH 0x0020 + +#pragma pack(1) + +#define PROPRIETARY_TLV_BASE_ID 0x0100 +#define MRVL_TERMINATE_TLV_ID 0xffff + +#define TLV_TYPE_SSID 0x0000 +#define TLV_TYPE_RATES 0x0001 +#define TLV_TYPE_PHY_FH 0x0002 +#define TLV_TYPE_PHY_DS 0x0003 +#define TLV_TYPE_CF 0x0004 +#define TLV_TYPE_IBSS 0x0006 + +#define TLV_TYPE_DOMAIN 0x0007 + +#define TLV_TYPE_POWER_CAPABILITY 0x0021 + +#define TLV_TYPE_KEY_MATERIAL (PROPRIETARY_TLV_BASE_ID + 0) +#define TLV_TYPE_CHANLIST (PROPRIETARY_TLV_BASE_ID + 1) +#define TLV_TYPE_NUMPROBES (PROPRIETARY_TLV_BASE_ID + 2) +#define TLV_TYPE_RSSI_LOW (PROPRIETARY_TLV_BASE_ID + 4) +#define TLV_TYPE_SNR_LOW (PROPRIETARY_TLV_BASE_ID + 5) +#define TLV_TYPE_FAILCOUNT (PROPRIETARY_TLV_BASE_ID + 6) +#define TLV_TYPE_BCNMISS (PROPRIETARY_TLV_BASE_ID + 7) +#define TLV_TYPE_LED_GPIO (PROPRIETARY_TLV_BASE_ID + 8) +#define TLV_TYPE_LEDBEHAVIOR (PROPRIETARY_TLV_BASE_ID + 9) +#define TLV_TYPE_PASSTHROUGH (PROPRIETARY_TLV_BASE_ID + 10) +#define TLV_TYPE_REASSOCAP (PROPRIETARY_TLV_BASE_ID + 11) +#define TLV_TYPE_POWER_TBL_2_4GHZ (PROPRIETARY_TLV_BASE_ID + 12) +#define TLV_TYPE_POWER_TBL_5GHZ (PROPRIETARY_TLV_BASE_ID + 13) +#define TLV_TYPE_BCASTPROBE (PROPRIETARY_TLV_BASE_ID + 14) +#define TLV_TYPE_NUMSSID_PROBE (PROPRIETARY_TLV_BASE_ID + 15) +#define TLV_TYPE_WMMQSTATUS (PROPRIETARY_TLV_BASE_ID + 16) +#define TLV_TYPE_CRYPTO_DATA (PROPRIETARY_TLV_BASE_ID + 17) +#define TLV_TYPE_WILDCARDSSID (PROPRIETARY_TLV_BASE_ID + 18) +#define TLV_TYPE_TSFTIMESTAMP (PROPRIETARY_TLV_BASE_ID + 19) +#define TLV_TYPE_RSSI_HIGH (PROPRIETARY_TLV_BASE_ID + 22) +#define TLV_TYPE_SNR_HIGH (PROPRIETARY_TLV_BASE_ID + 23) +#define TLV_TYPE_AUTH_TYPE (PROPRIETARY_TLV_BASE_ID + 31) +#define TLV_TYPE_MESH_ID (PROPRIETARY_TLV_BASE_ID + 37) +#define TLV_TYPE_OLD_MESH_ID (PROPRIETARY_TLV_BASE_ID + 291) + +typedef struct mrvl_ie_header +{ + UINT16 type; + UINT16 len; +} __attribute__((packed)) MRVL_IE_HDR_S, *MRVL_IE_HDR_PTR; + + +typedef struct mrvl_ie_ssid_param_set +{ + struct mrvl_ie_header header; + UINT8 ssid[1]; +} __attribute__((packed)) MRVL_IE_SSID_PARAM_S, *MRVL_IE_SSID_PARAM_PTR; + +typedef struct chanscanmode +{ + UINT8 passivescan: 1; + UINT8 disablechanfilt: 1; + UINT8 reserved_2_7: 6; +} __attribute__((packed))CHAN_SCAN_MODE_S, *CHAN_SCAN_MODE_PTR; + +typedef struct chanscanparamset +{ + UINT8 radiotype; + UINT8 channumber; + CHAN_SCAN_MODE_S chanscanmode; + UINT16 minscantime; + UINT16 maxscantime; +} __attribute__((packed)) CHAN_SCAN_PARAM_S, *CHAN_SCAN_PARAM_PTR; + +typedef struct stm32_cmd_hdr +{ + UINT16 command; + UINT16 size; + UINT16 seqnum; + UINT16 result; +} __attribute__((packed)) STM32_CMD_HDR_S, *STM32_CMD_HDR_PTR; + +/* 802.11-related definitions */ +/* TxPD descriptor */ +typedef struct stm32_txpd +{ + /* union to cope up with later FW revisions */ + union + { + /* Current Tx packet status */ + UINT32 tx_status; + struct + { + /* BSS type: client, AP, etc. */ + UINT8 bss_type; + /* BSS number */ + UINT8 bss_num; + /* Reserved */ + UINT16 reserved; + } __attribute__((packed)) bss; + + } __attribute__((packed)) u ; + + /* Tx control */ + UINT32 tx_control; + UINT32 tx_packet_location; + /* Tx packet length */ + UINT16 tx_packet_length; + /* First 2 byte of destination MAC address */ + UINT8 tx_dest_addr_high[2]; + /* Last 4 byte of destination MAC address */ + UINT8 tx_dest_addr_low[4]; + /* Pkt Priority */ + UINT8 priority; + /* Pkt Trasnit Power control */ + UINT8 powermgmt; + /* Amount of time the packet has been queued in the driver (units = 2ms) */ + UINT8 pktdelay_2ms; + /* reserved */ + UINT8 reserved1; +} __attribute__((packed)) STM32_TXPD_S, *STM32_TXPD_PTR; + +/* RxPD Descriptor */ +typedef struct stm32_rxpd +{ + /* union to cope up with later FW revisions */ + union + { + /* Current Rx packet status */ + UINT16 status; + struct + { + /* BSS type: client, AP, etc. */ + UINT8 bss_type; + /* BSS number */ + UINT8 bss_num; + } __attribute__((packed)) bss; + } __attribute__((packed)) u; + + /* SNR */ + UINT8 snr; + /* Tx control */ + UINT8 rx_control; + /* Pkt length */ + UINT16 pkt_len; + /* Noise Floor */ + UINT8 nf; + /* Rx Packet Rate */ + UINT8 rx_rate; + /* Pkt addr */ + UINT32 pkt_ptr; + /* Next Rx RxPD addr */ + UINT32 next_rxpd_ptr; + /* Pkt Priority */ + UINT8 priority; + UINT8 reserved[3]; +} __attribute__((packed)) STM32_RXPD_S, *STM32_RXPD_PTR; + +enum stm32_ms_type +{ + MVMS_DAT = 0, + MVMS_CMD = 1, + MVMS_TXDONE = 2, + MVMS_EVENT +}; + +#define BEACON_TIMESTAMP_LEN 8 +#define ETH_ALEN 6 /* Octets in one ethernet addr */ + +typedef struct ethhdr +{ + UINT8 h_dest[ETH_ALEN]; + UINT8 h_src[ETH_ALEN]; + UINT16 h_proto; +} __attribute__((packed)) ETHHDR_S, *ETHHDR_PTR; + +typedef struct beacon_info +{ + UINT16 len; + UINT8 bssid[ETH_ALEN]; + INT8 rssi; + UINT8 timestamp[BEACON_TIMESTAMP_LEN]; + UINT16 beacon_interval; + UINT16 capability; +} __attribute__((packed)) BEACON_INFO_S, *BEACON_INFO_PTR; + +typedef struct cmd_ds_802_11_scan_rsp +{ + STM32_CMD_HDR_S hdr; + + UINT16 bssdescriptsize; + UINT8 nr_sets; + BEACON_INFO_S beacon_info; + UINT8 tlvbuffer[1]; +} __attribute__((packed)) STM32_SCAN_RSP_S, *STM32_SCAN_RSP_PTR; + + +typedef struct _stm32_frame_hdr +{ + UINT16 len; +#if FOR_SDIO_BLK_512 + UINT8 type; + UINT8 seq; +#else + UINT16 type; +#endif + + +} STM32_FRAME_HDR; + +typedef struct _stm32_tx_frame_ +{ + UINT16 len; +#if FOR_SDIO_BLK_512 + UINT8 type; + UINT8 seq; +#else + UINT16 type; +#endif + + STM32_TXPD_S frm; + + void *private; +} STM32_TX_FRAME; + +typedef struct +{ + UINT16 len; + UINT16 type; + + STM32_CMD_HDR_S hdr; + + UINT32 resv; +} STM32_CMD_S, STM32_RSP_S; + +typedef struct +{ + UINT16 len; + UINT16 type; + + STM32_CMD_HDR_S hdr; + + UINT16 private; +} STM32_TX_MGMT_S, *STM32_TX_MGMT_PTR; + +typedef struct stm32_cmd_802_11_scan +{ + STM32_CMD_HDR_S hdr; + + UINT8 bsstype; + UINT8 bssid[ETH_ALEN]; + UINT8 tlvbuffer[1]; +} __attribute__((packed)) STM32_CMD_802_11_SCAN_S, *STM32_CMD_802_11_SCAN_PTR; + +struct MrvlIEtype_keyParamSet +{ + /* type ID */ + UINT16 type; + + /* length of Payload */ + UINT16 length; + + /* type of key: WEP=0, TKIP=1, AES=2 */ + UINT16 keytypeid; + + /* key control Info specific to a keytypeid */ + UINT16 keyinfo; + + /* length of key */ + UINT16 keylen; + + /* key material of size keylen */ + UINT8 key[32]; +} __attribute__((packed)); + +typedef struct cmd_ds_802_11_key_material +{ + STM32_CMD_HDR_S hdr; + + UINT16 action; + struct MrvlIEtype_keyParamSet keyParamSet[2]; +} __attribute__((packed)) STM32_KEY_MATERIAL_S, *STM32_KEY_MATERIAL_PTR; + +typedef struct cmd_ds_802_11_associate_response +{ + STM32_CMD_HDR_S hdr; + + UINT16 capability; + UINT16 statuscode; + UINT16 aid; + UINT8 iebuf[512]; +} __attribute__((packed)) ASSOC_RESP_S, *ASSOC_RESP_PTR; + +typedef struct cmd_ds_802_11_associate +{ + STM32_CMD_HDR_S hdr; + + UINT8 bssid[6]; + UINT16 capability; + UINT16 listeninterval; + UINT16 bcnperiod; + UINT8 dtimperiod; + UINT8 iebuf[512]; /* Enough for required and most optional IEs */ +} __attribute__((packed)) ASSOC_REQ_S, *ASSOC_REQ_PTR; + +#pragma pack() +#endif // STM32_PLATFORM + + +/******************************************************************************* +* Function Declarations +*******************************************************************************/ +extern void sdio_emb_txdesc_copy(struct txdesc *dst_local, ETHHDR_PTR eth_hdr_ptr); +extern void sdio_rxed_trigger_evt(void); +#endif // CFG_SDIO + +#endif // _SDIO_INTF_H_ + diff --git a/beken_os/beken378/func/sdio_trans/sdio_trans.c b/beken_os/beken378/func/sdio_trans/sdio_trans.c new file mode 100755 index 0000000..98c0b34 --- /dev/null +++ b/beken_os/beken378/func/sdio_trans/sdio_trans.c @@ -0,0 +1,152 @@ +#include "include.h" +#include "arm_arch.h" +#include "sdio_pub.h" +#include "sdio_trans.h" +#include "sdio_intf_pub.h" +#include "sdio_pub.h" +#include "drv_model_pub.h" +#include "mem_pub.h" +#include "mac.h" +#include "ke_event.h" +#include "llc.h" +#include "txu_cntrl.h" +#include "txl_cntrl.h" +#include "mem_pub.h" +#include "co_utils.h" +#include "scan_task.h" +#include "scanu_task.h" +#include "me_task.h" +#include "mm_task.h" +#include "sm_task.h" +#include "vif_mgmt.h" +#include "apm_task.h" +#include "rxu_task.h" +#include "uart_pub.h" +#include "mem_pub.h" +#include "apm_task.h" +#include "mac_ie.h" + +#include "hostapd_cfg.h" +#include "sa_station.h" + +#if CFG_USE_TEMPERATURE_DETECT +#include "temp_detect_pub.h" +#endif + +#include "common.h" +#include "rwnx.h" +#include "rw_pub.h" + +#if CFG_SDIO_TRANS + +static DD_HANDLE sdio_hdl; + +SDIO_NODE_PTR sdio_trans_get_node(void) +{ + UINT32 status; + UINT32 rd_sta; + DD_HANDLE sdio_hdl; + SDIO_NODE_PTR ret = 0; + SDIO_NODE_PTR mem_node_ptr; + + sdio_hdl = ddev_open(SDIO_DEV_NAME, &status, 0); + if(DD_HANDLE_UNVALID == sdio_hdl) + { + goto rxed_exception; + } + + rd_sta = ddev_read(sdio_hdl, (char *)SDIO_DUMMY_BUFF_ADDR, SDIO_DUMMY_LENGTH, H2S_RD_SPECIAL); + if(SDIO_FAILURE == rd_sta) + { + goto rd_fail; + } + else + { + mem_node_ptr = (SDIO_NODE_PTR)rd_sta; + ret = mem_node_ptr; + } + +rd_fail: + +rxed_exception: + return ret; +} + +UINT32 sdio_trans_release_node(SDIO_NODE_PTR mem_node_ptr) +{ + UINT32 status; + DD_HANDLE sdio_hdl; + UINT32 ret = SDIO_INTF_SUCCESS; + + sdio_hdl = ddev_open(SDIO_DEV_NAME, &status, 0); + if(DD_HANDLE_UNVALID == sdio_hdl) + { + ret = SDIO_INTF_FAILURE; + + goto rxed_exception; + } + + ddev_control(sdio_hdl, SDIO_CMD_PUSH_FREE_NODE, (void *)mem_node_ptr); + +rxed_exception: + return ret; +} +void sdio_trans_evt(int dummy) +{ + SDIO_NODE_PTR mem_node_ptr; + STM32_FRAME_HDR *frm_hdr_ptr; + + mem_node_ptr = sdio_trans_get_node(); + + while(mem_node_ptr) + { + frm_hdr_ptr = (STM32_FRAME_HDR *)mem_node_ptr->addr; + + app_lwip_udp_send_packet(frm_hdr_ptr ,mem_node_ptr->length); + os_printf("sdio recv len:%d\r\n",mem_node_ptr->length); + + sdio_trans_release_node(mem_node_ptr); + + mem_node_ptr = sdio_trans_get_node(); + } + + if(0 == mem_node_ptr) + { + ke_evt_clear(KE_EVT_SDIO_TRANS_DATA_BIT); + } + + return; +} + +void sdio_trans_trigger_evt(void) +{ + ke_evt_set(KE_EVT_SDIO_TRANS_DATA_BIT); +} +void sdio_trans_close(void) +{ + ddev_close(sdio_hdl); +} + int sdio_trans_init(void) +{ + UINT32 ret; + UINT32 status; + + ret = SDIO_TRANS_FAILURE; + + sdio_hdl = ddev_open(SDIO_DEV_NAME, &status, 0); + if(DD_HANDLE_UNVALID == sdio_hdl) + { + goto init_exception; + } + + ddev_control(sdio_hdl, SDIO_CMD_REG_RX_CALLBACK, (void *)sdio_trans_trigger_evt); + + SDIO_TRANS_PRT("sdio_intf_init\r\n"); + ret = SDIO_TRANS_SUCCESS; + +init_exception: + return ret; +} + +#endif + diff --git a/beken_os/beken378/func/sdio_trans/sdio_trans.h b/beken_os/beken378/func/sdio_trans/sdio_trans.h new file mode 100755 index 0000000..9e426a3 --- /dev/null +++ b/beken_os/beken378/func/sdio_trans/sdio_trans.h @@ -0,0 +1,29 @@ +#include "tx_swdesc.h" + +#if CFG_SDIO_TRANS + +#define SDIO_TRANS_DEBUG + +#ifdef SDIO_TRANS_DEBUG +#define SDIO_TRANS_PRT os_printf +#define SDIO_TRANS_WPRT warning_prf +#else +#define SDIO_TRANS_PRT os_null_printf +#define SDIO_TRANS_WPRT warning_prf +#endif + +#define SDIO_TRANS_FAILURE ((UINT32)-1) +#define SDIO_TRANS_SUCCESS (0) + +typedef struct _stm32_frame_hdr +{ + UINT16 len; +#if FOR_SDIO_BLK_512 + UINT8 type; + UINT8 seq; +#else + UINT16 type; +#endif +} STM32_FRAME_HDR; + +#endif diff --git a/beken_os/beken378/func/sim_uart/gpio_uart.c b/beken_os/beken378/func/sim_uart/gpio_uart.c new file mode 100755 index 0000000..2276445 --- /dev/null +++ b/beken_os/beken378/func/sim_uart/gpio_uart.c @@ -0,0 +1,134 @@ +#include +#include "include.h" +#include "arm_arch.h" + +#include "uart_pub.h" +#include "uart.h" + +#include "drv_model_pub.h" +#include "sys_ctrl_pub.h" +#include "mem_pub.h" +#include "icu_pub.h" +#include "gpio_pub.h" +#include "gpio_uart.h" + + +#include "mem_pub.h" +#include "intc_pub.h" + +#include "icu_pub.h" +#include "gpio_pub.h" + +void gu_delay(uint32_t usec) +{ + volatile uint32_t loops; + + while (usec--) + { + loops = 40; + while (loops--); + } +} + +#ifdef CONFIG_GPIO_SIMU_UART_TX +void gpio_uart_send_init(void) +{ + UINT32 param; + + param = GPIO_CFG_PARAM(SIMU_UART_GPIONUM, GMODE_OUTPUT); + sddev_control(GPIO_DEV_NAME, CMD_GPIO_CFG, ¶m); +} + +void gpio_uart_send_byte(unsigned char *buff, unsigned int len) +{ + volatile unsigned char c, n, loops; + UINT32 param; + + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + + param = GPIO_CFG_PARAM(SIMU_UART_GPIONUM, GMODE_OUTPUT); + sddev_control(GPIO_DEV_NAME, CMD_GPIO_OUTPUT, ¶m); + gu_delay(60); + + while(len--) + { + param = GPIO_CFG_PARAM(SIMU_UART_GPIONUM, GMODE_INPUT_PULLDOWN); + sddev_control(GPIO_DEV_NAME, CMD_GPIO_OUTPUT, ¶m); + gu_delay(33); + loops = 10; + while (loops--); + c = *buff++; + n = 8; + while(n--) + { + param = GPIO_CFG_PARAM(SIMU_UART_GPIONUM, (c & 0x01)); + sddev_control(GPIO_DEV_NAME, CMD_GPIO_OUTPUT, ¶m); + gu_delay(33); + loops = 6; + while (loops--); + c >>= 1; + } + param = GPIO_CFG_PARAM(SIMU_UART_GPIONUM, GMODE_OUTPUT); + sddev_control(GPIO_DEV_NAME, CMD_GPIO_OUTPUT, ¶m); + gu_delay(33); + loops = 6; + while (loops--); + } + GLOBAL_INT_RESTORE(); +} + +int guart_fputc(int ch, FILE *f) +{ + gpio_uart_send_byte((unsigned char *)&ch, 1); + + return ch; +} + +#endif + +#ifdef CONFIG_GPIO_SIMU_UART_TX +void GPIO_Simu_Isr(unsigned char ucChannel) +{ + UINT8 c = 0, n, loops; + + if(ucChannel == SIMU_UART_GPIO_RX) + { + gu_delay(21); + loops = 5; + while (loops--); + for(n = 0; n < 8; n++) + { + c >>= 1; + if(bk_gpio_input(SIMU_UART_GPIO_RX)) + c |= 0x80; + + gu_delay(33); + loops = 20; + while (loops--); + loops++; + } + } +} + +void gpio_uart_recv_init(void) +{ + UINT32 param; + GPIO_INT_ST int_param; + + param = GPIO_CFG_PARAM(SIMU_UART_GPIO_RX, GMODE_INPUT_PULLUP); + sddev_control(GPIO_DEV_NAME, CMD_GPIO_CFG, ¶m); + + intc_service_register(IRQ_GPIO, PRI_IRQ_GPIO, gpio_isr); + + param = IRQ_GPIO_BIT; + sddev_control(ICU_DEV_NAME, CMD_ICU_INT_ENABLE, ¶m); + + int_param.id = SIMU_UART_GPIO_RX; + int_param.mode = GMODE_INPUT_PULLDOWN; + int_param.phandler = GPIO_Simu_Isr; + sddev_control(GPIO_DEV_NAME, CMD_GPIO_INT_ENABLE, &int_param); +} +#endif +// eof + diff --git a/beken_os/beken378/func/sim_uart/gpio_uart.h b/beken_os/beken378/func/sim_uart/gpio_uart.h new file mode 100755 index 0000000..9019a1d --- /dev/null +++ b/beken_os/beken378/func/sim_uart/gpio_uart.h @@ -0,0 +1,25 @@ +#ifndef _GPIO_UART_H_ +#define _GPIO_UART_H_ + +#define CONFIG_GPIO_SIMU_UART_RX 1 +#define CONFIG_GPIO_SIMU_UART_TX 1 + + +#define SIMU_UART_GPIONUM 18 +#define SIMU_UART_GPIO_RX 19 +#define SIMU_UART_GPIO_TEST 15 + +extern void gpio_isr(void); +extern void gu_delay(uint32_t ) ; +#ifdef CONFIG_GPIO_SIMU_UART_TX +extern void gpio_uart_send_init(void); +extern int guart_fputc(int , FILE *); +#endif + +#ifdef CONFIG_GPIO_SIMU_UART_RX +extern void gpio_uart_recv_init(void); +#endif + +#endif // _GPIO_UART_H_ +// eof + diff --git a/beken_os/beken378/func/sim_uart/pwm_uart.c b/beken_os/beken378/func/sim_uart/pwm_uart.c new file mode 100755 index 0000000..f49eef6 --- /dev/null +++ b/beken_os/beken378/func/sim_uart/pwm_uart.c @@ -0,0 +1,540 @@ +#include +#include "include.h" +#include "arm_arch.h" +#include "uart_pub.h" +#include "uart.h" +#include "pwm_pub.h" +#include "drv_model_pub.h" +#include "sys_ctrl_pub.h" +#include "mem_pub.h" +#include "icu_pub.h" +#include "gpio_pub.h" +#include "mem_pub.h" +#include "intc_pub.h" +#include "pwm_uart.h" + +uint8_t uart_io_start ; + +#ifdef INCLUDE_RX_MODE +volatile BOOL uart_io_sim_rx_done = false; +unsigned char uart_io_sim_rx_buf[UART_IO_SIM_RX_FIFO_MAX_COUNT]; +volatile unsigned char uart_io_sim_rx_buf_current_cnt; +#ifdef INTERRUPT_METHOD +LOCAL volatile unsigned char uart_io_sim_rx_buf_current_bit; +LOCAL volatile unsigned int uart_io_sim_rx_int_count = 0; +LOCAL volatile unsigned char uart_io_sim_rx_firt_start_bit = 0; + +#endif +#endif +#ifdef INCLUDE_TX_MODE +LOCAL unsigned char *p_uart_io_sim_tx_buf = NULL; +#endif + +#ifdef INCLUDE_TX_MODE +unsigned char uart_io_sim_tx_buf[UART_IO_SIM_TX_FIFO_MAX_COUNT]; +#ifdef INTERRUPT_METHOD +LOCAL int uart_io_sim_tx_buf_size; +LOCAL unsigned char uart_io_sim_tx_buf_current_bit; + +LOCAL unsigned char uart_io_sim_tx_first_start = 0; + +LOCAL unsigned long uart_io_sim_tx_buf_current_cnt; +#endif +#endif + +#if defined GPIO_7231_STYLE +extern UART_S uart[2]; +extern void (*p_PWM_Int_Handler[])(UINT8); + +void GPIO_UART_io_sim_tx_function_enable(void) +{ + *((volatile UINT32 *)(GPIO_BASE_ADDR + GPIO_UART_IO_SIM_TX_PIN * 4)) = 0x0; +} + +void UARTCALL uart_io_sim_set_tx(unsigned long ulValue) +{ + if(ulValue) + { + *((volatile UINT32 *)(GPIO_BASE_ADDR + GPIO_UART_IO_SIM_TX_PIN * 4)) = \ + *((volatile UINT32 *)(GPIO_BASE_ADDR + GPIO_UART_IO_SIM_TX_PIN * 4))\ + | (0x01 << GCFG_OUTPUT_POS); + } + else + { + *((volatile UINT32 *)(GPIO_BASE_ADDR + GPIO_UART_IO_SIM_TX_PIN * 4)) = \ + *((volatile UINT32 *)(GPIO_BASE_ADDR + GPIO_UART_IO_SIM_TX_PIN * 4))\ + & ~(0x01 << GCFG_OUTPUT_POS); + } +} + +void GPIO_UART_io_sim_rx_function_enable(void) +{ + *((volatile UINT32 *)(GPIO_BASE_ADDR + GPIO_UART_IO_SIM_RX_PIN * 4)) = 0x3C; +} + +unsigned long uart_io_sim_get_rx(void) +{ + return *((volatile UINT32 *)(GPIO_BASE_ADDR + GPIO_UART_IO_SIM_RX_PIN * 4))& GCFG_INPUT_BIT; +} +#endif + +#ifdef INCLUDE_RX_MODE +LOCAL void uart_io_sim_pwm_cap_neg_init_for_rx(void); +extern void UARTCALL uart_io_sim_receive(void); +LOCAL void uart_io_sim_pwm_cap_neg_init_for_rx(void); +#endif + +#ifdef INCLUDE_TX_MODE +extern void uart_io_sim_send_string(char *); +#endif + +#ifdef POLLING_METHOD +static void uart_io_sim_delay(volatile unsigned long times) +{ + while (times != 0) + { + times --; + } +} +#endif + +#ifdef INCLUDE_TX_MODE +void uart_io_sim_tx_buf_init(void) +{ + os_memset(uart_io_sim_tx_buf, 0, sizeof(uart_io_sim_tx_buf)); +#if defined INTERRUPT_METHOD + uart_io_sim_tx_buf_size = 0; + p_uart_io_sim_tx_buf = NULL; + uart_io_sim_tx_buf_current_bit = 0; + uart_io_sim_tx_buf_current_cnt = 0; +#endif +} +#endif /* #ifdef INCLUDE_TX_MODE */ + +#ifdef INCLUDE_RX_MODE +void uart_io_sim_rx_buf_init(void) +{ + os_memset(uart_io_sim_rx_buf, 0, sizeof(uart_io_sim_rx_buf)); + + uart_io_sim_rx_done = false; + uart_io_sim_rx_buf_current_cnt = 0; +#if defined INTERRUPT_METHOD + uart_io_sim_rx_buf_current_bit = 0; +#endif +} +#endif /* #ifdef INCLUDE_RX_MODE */ + + +#if defined INTERRUPT_METHOD +#ifdef INCLUDE_TX_MODE + +void UARTCALL uart_io_sim_timer_int_handle_tx_data(unsigned char ucChannel) +{ + if(uart_io_sim_tx_first_start) + { + uart_io_sim_tx_first_start = 0; + uart_io_sim_set_tx(0x00UL); + return; + } + + if (p_uart_io_sim_tx_buf == NULL) + { + uart_io_sim_set_tx(0x01UL); + *((volatile UINT32 *)(PWM_CTL)) = (*(volatile UINT32 *)(PWM_CTL))& ~(2 << (UART_IO_SIM_PWM_TIMER_TX_CHN * 4)); + return; + } + + if (uart_io_sim_tx_buf_current_bit < 8) + { + uart_io_sim_set_tx((p_uart_io_sim_tx_buf[uart_io_sim_tx_buf_current_cnt] >> uart_io_sim_tx_buf_current_bit) + & 0x01UL); // data bit + uart_io_sim_tx_buf_current_bit ++; + } + else if (uart_io_sim_tx_buf_current_bit == 8 || uart_io_sim_tx_buf_current_bit == 9) + { + uart_io_sim_set_tx(0x01UL); // STOP bit + uart_io_sim_tx_buf_current_bit ++; + } + else + { + uart_io_sim_tx_buf_current_bit = 0; + uart_io_sim_tx_buf_current_cnt ++; + if(uart_io_sim_tx_buf_current_cnt == UART_IO_SIM_TX_FIFO_MAX_COUNT) + uart_io_sim_tx_buf_current_cnt = 0; + if (uart_io_sim_tx_buf_current_cnt == uart_io_sim_tx_buf_size) + { + p_uart_io_sim_tx_buf = NULL; // data send over + } + else + { + uart_io_sim_set_tx(0x00UL); // START bit + } + } +} + +void uart_io_sim_pwm_timer_init_for_tx(void) +{ + UINT32 ret; + pwm_param_t param; + + /*init pwm*/ + param.channel = UART_IO_SIM_PWM_TIMER_TX_CHN; + param.cfg.bits.en = PWM_ENABLE; + param.cfg.bits.int_en = PWM_INT_DIS; + param.cfg.bits.mode = PMODE_TIMER; + +#if(CFG_RUNNING_PLATFORM == FPGA_PLATFORM) // FPGA:PWM0-2-32kCLK, pwm3-5-24CLK + param.cfg.bits.clk = PWM_CLK_32K; +#else + param.cfg.bits.clk = PWM_CLK_26M; +#endif + + param.p_Int_Handler = uart_io_sim_timer_int_handle_tx_data; + param.duty_cycle = 0; + param.end_value = UART_IO_SIM_CLK_DIVID_SET_TX; + + ret = sddev_control(PWM_DEV_NAME, CMD_PWM_INIT_PARAM, ¶m); + ASSERT(PWM_SUCCESS == ret); +} +#endif + +#ifdef INCLUDE_RX_MODE +extern void uart_io_sim_pwm_timer_init_for_rx(UINT16 end); + +static void UARTCALL init_pwm_param_2(pwm_param_t *pwm_param) +{ + UINT32 value; + + *((volatile UINT32 *)(GPIO_BASE_ADDR + PWM2_GPIO_PIN * 4)) = 0x40; + *((volatile UINT32 *)(REG_GPIO_FUNC_CFG)) = *((volatile UINT32 *)(REG_GPIO_FUNC_CFG)) | BIT(PWM2_GPIO_PIN); + + value = REG_READ(PWM_CTL); + value = (value & ~(0x0F << (0x04 * pwm_param->channel))) + | ((pwm_param->cfg.val & 0x0F) << (0x04 * pwm_param->channel)); + REG_WRITE(PWM_CTL, value); + + value = (((UINT32)pwm_param->duty_cycle & 0x0000FFFF) << 16) + + ((UINT32)pwm_param->end_value & 0x0000FFFF); + + #if (CFG_SOC_NAME == SOC_BK7231) + REG_WRITE(REG_APB_BK_PWMn_CNT_ADDR(pwm_param->channel), value); + #else + REG_WRITE(REG_APB_BK_PWMn_END_ADDR(pwm_param->channel), value); + #endif + + p_PWM_Int_Handler[pwm_param->channel] = pwm_param->p_Int_Handler; + + *((volatile UINT32 *)(ICU_PERI_CLK_PWD)) = *((volatile UINT32 *)(ICU_PERI_CLK_PWD))& ~(PWD_PWM2_CLK_BIT); + *((volatile UINT32 *)(ICU_PWM_CLK_MUX)) = *((volatile UINT32 *)(ICU_PWM_CLK_MUX))& ~(1 << (pwm_param->channel)); + *((volatile UINT32 *)(ICU_INTERRUPT_ENABLE)) = *((volatile UINT32 *)(ICU_INTERRUPT_ENABLE)) | (IRQ_PWM_BIT); +} + +static void UARTCALL init_pwm_param_5(pwm_param_t *pwm_param) +{ + UINT32 value; + + *((volatile UINT32 *)(GPIO_BASE_ADDR + PWM5_GPIO_PIN * 4)) = 0x40; + *((volatile UINT32 *)(REG_GPIO_FUNC_CFG)) = *((volatile UINT32 *)(REG_GPIO_FUNC_CFG)) | BIT(PWM5_GPIO_PIN); + + value = REG_READ(PWM_CTL); + value = (value & ~(0x0F << (0x04 * pwm_param->channel))) + | ((pwm_param->cfg.val & 0x0F) << (0x04 * pwm_param->channel)); + REG_WRITE(PWM_CTL, value); + + value = (((UINT32)pwm_param->duty_cycle & 0x0000FFFF) << 16) + + ((UINT32)pwm_param->end_value & 0x0000FFFF); + #if (CFG_SOC_NAME == SOC_BK7231) + REG_WRITE(REG_APB_BK_PWMn_CNT_ADDR(pwm_param->channel), value); + #else + REG_WRITE(REG_APB_BK_PWMn_END_ADDR(pwm_param->channel), value); + #endif + + p_PWM_Int_Handler[pwm_param->channel] = pwm_param->p_Int_Handler; + + *((volatile UINT32 *)(ICU_PERI_CLK_PWD)) = *((volatile UINT32 *)(ICU_PERI_CLK_PWD))& ~(PWD_PWM5_CLK_BIT); + *((volatile UINT32 *)(ICU_PWM_CLK_MUX)) = *((volatile UINT32 *)(ICU_PWM_CLK_MUX))& ~(1 << (pwm_param->channel)); + *((volatile UINT32 *)(ICU_INTERRUPT_ENABLE)) = *((volatile UINT32 *)(ICU_INTERRUPT_ENABLE)) | (IRQ_PWM_BIT); +} + +void UARTCALL uart_io_sim_timer_int_handle_rx_data(unsigned char ucChannel) +{ + volatile UINT8 val = 0 ; + val = *((volatile UINT32 *)(GPIO_BASE_ADDR + GPIO_UART_IO_SIM_RX_PIN * 4))& GCFG_INPUT_BIT; + + ++uart_io_sim_rx_int_count; + if( uart_io_sim_rx_int_count % 5 != 2 || uart_io_sim_rx_int_count == 2) + return; + + if (uart_io_sim_rx_buf_current_bit < 8) // data bit + { + uart_io_sim_rx_buf[uart_io_sim_rx_buf_current_cnt] |= (val << uart_io_sim_rx_buf_current_bit); + uart_io_sim_rx_buf_current_bit ++; + if(uart_io_sim_rx_buf_current_bit == 8) + { + uart_io_sim_rx_buf_current_bit = 0; + uart_io_sim_rx_int_count = 0; + *((volatile UINT32 *)(PWM_CTL)) = *((volatile UINT32 *)(PWM_CTL))& ~(2 << (ucChannel * 4)); + *((volatile UINT32 *)(GPIO_BASE_ADDR + GPIO_UART_IO_SIM_RX_PIN * 4)) = 0x40; + *((volatile UINT32 *)(PWM_CTL)) = (*(volatile UINT32 *)(PWM_CTL)) | (2 << (UART_IO_SIM_PWM_CAP_NEG_RX_CHN * 4)); + + kfifo_put(uart[1].rx, (UINT8 *) & (uart_io_sim_rx_buf[uart_io_sim_rx_buf_current_cnt]), 1); //get char c + uart_io_sim_rx_buf_current_cnt ++; + if(uart_io_sim_rx_buf_current_cnt == UART_IO_SIM_RX_FIFO_MAX_COUNT) + { + uart_io_sim_rx_buf_current_cnt = 0; + os_memset(uart_io_sim_rx_buf, 0, UART_IO_SIM_RX_FIFO_MAX_COUNT); + } + } + } +} + +void UARTCALL uart_io_sim_pwm_timer_init_for_rx(UINT16 end) +{ + pwm_param_t param; + + /*init pwm*/ + param.channel = UART_IO_SIM_PWM_TIMER_RX_CHN; + param.cfg.bits.en = PWM_ENABLE; + param.cfg.bits.int_en = PWM_INT_DIS; + param.cfg.bits.mode = PMODE_TIMER; +#if(CFG_RUNNING_PLATFORM == FPGA_PLATFORM) + param.cfg.bits.clk = PWM_CLK_32K; +#else + param.cfg.bits.clk = PWM_CLK_26M; +#endif + param.p_Int_Handler = uart_io_sim_timer_int_handle_rx_data; + param.duty_cycle = 0; + param.end_value = end; + + init_pwm_param_2(¶m); + +} + +void UARTCALL uart_io_sim_int_handle_rx_cap_neg(unsigned char ucChannel) +{ + // capture START bit, prepare to receive data bits + *((volatile UINT32 *)(GPIO_BASE_ADDR + GPIO_UART_IO_SIM_RX_PIN * 4)) = 0x3C; + +#if defined INTERRUPT_METHOD + *((volatile UINT32 *)(PWM_CTL)) = (*(volatile UINT32 *)(PWM_CTL))&~(2 << (ucChannel * 4)); + + uart_io_sim_rx_int_count = 0; + uart_io_sim_rx_firt_start_bit = 0; + uart_io_sim_rx_buf_current_bit = 0; + + *((volatile UINT32 *)(PWM_CTL)) = *((volatile UINT32 *)(PWM_CTL)) | (2 << (UART_IO_SIM_PWM_TIMER_RX_CHN * 4)); +#elif defined POLLING_METHOD + uart_io_sim_receive(); +#endif +} + +void UARTCALL uart_io_sim_pwm_cap_neg_init_for_rx(void) +{ + pwm_param_t param; + /*init pwm*/ + param.channel = UART_IO_SIM_PWM_CAP_NEG_RX_CHN; + param.cfg.bits.en = PWM_ENABLE; + param.cfg.bits.int_en = PWM_INT_DIS; + param.cfg.bits.mode = PMODE_CAP_NEG; +#if(CFG_RUNNING_PLATFORM == FPGA_PLATFORM) + param.cfg.bits.clk = PWM_CLK_32K; +#else + param.cfg.bits.clk = PWM_CLK_26M; +#endif + param.p_Int_Handler = uart_io_sim_int_handle_rx_cap_neg; + param.duty_cycle = 0; + param.end_value = 0xFFFF; + + init_pwm_param_5(¶m); +} +#endif +#endif + +//#ifdef (INCLUDE_TX_MODE || INCLUDE_RX_MODE) +#if ((defined INCLUDE_TX_MODE) || (defined INCLUDE_RX_MODE)) +void uart_io_sim_init(void) +{ + //gpio_config(SIMU_UART_GPIOCLK,GMODE_OUTPUT); +#ifdef INCLUDE_TX_MODE + GPIO_UART_io_sim_tx_function_enable(); + uart_io_sim_tx_buf_init(); + uart_io_sim_set_tx(0x01UL); + uart_io_sim_delay(1000); + uart_io_sim_pwm_timer_init_for_tx(); +#endif + +#ifdef INCLUDE_RX_MODE + uart_io_sim_rx_buf_init(); + uart_io_sim_pwm_timer_init_for_rx(UART_IO_SIM_CLK_DIVID_SET); + uart_io_sim_pwm_cap_neg_init_for_rx(); + *((volatile UINT32 *)(PWM_CTL)) = *((volatile UINT32 *)(PWM_CTL)) | (2 << (UART_IO_SIM_PWM_CAP_NEG_RX_CHN * 4)); + +#endif + +#ifdef INCLUDE_TX_MODE + uart_io_start = 1; +#endif +} + +void uart_io_sim_disable(void) +{ +#if defined INTERRUPT_METHOD + UINT32 param; + UINT32 ret; + + param = UART_IO_SIM_PWM_CAP_NEG_RX_CHN; + ret = sddev_control(PWM_DEV_NAME, CMD_PWM_UINT_DISABLE, ¶m); + ASSERT(PWM_SUCCESS == ret); + + param = UART_IO_SIM_PWM_TIMER_TX_CHN; + ret = sddev_control(PWM_DEV_NAME, CMD_PWM_UINT_DISABLE, ¶m); + ASSERT(PWM_SUCCESS == ret); + p_uart_io_sim_tx_buf = NULL; + + param = UART_IO_SIM_PWM_TIMER_RX_CHN; + ret = sddev_control(PWM_DEV_NAME, CMD_PWM_UINT_DISABLE, ¶m); + ASSERT(PWM_SUCCESS == ret); +#ifdef INCLUDE_TX_MODE + uart_io_start = 0; +#endif + +#endif +} +#endif + +//---------------------------------------------- +// UART_IO_SIM Tx/Rx character driver +//---------------------------------------------- +#ifdef INCLUDE_TX_MODE +void UARTCALL uart_io_sim_send_byte(u8 data) +{ +#if defined INTERRUPT_METHOD + if(!uart_io_start) + return; + + if(p_uart_io_sim_tx_buf) + { + p_uart_io_sim_tx_buf[uart_io_sim_tx_buf_size++] = data; + if(uart_io_sim_tx_buf_size == UART_IO_SIM_TX_FIFO_MAX_COUNT) + { + uart_io_sim_tx_buf_size = 0; + } + } + else + { + p_uart_io_sim_tx_buf = uart_io_sim_tx_buf; + uart_io_sim_tx_buf_size = 0; + uart_io_sim_tx_buf_current_cnt = 0; + uart_io_sim_tx_first_start = 1; + os_memset(p_uart_io_sim_tx_buf, 0, UART_IO_SIM_TX_FIFO_MAX_COUNT); + p_uart_io_sim_tx_buf[uart_io_sim_tx_buf_size++] = data; + if(uart_io_sim_tx_buf_size == UART_IO_SIM_TX_FIFO_MAX_COUNT) + uart_io_sim_tx_buf_size = 0; + + *((volatile UINT32 *)(PWM_CTL)) = (*(volatile UINT32 *)(PWM_CTL)) | (2 << (UART_IO_SIM_PWM_TIMER_TX_CHN * 4)); + } + +#elif defined POLLING_METHOD + int i; + uart_io_sim_set_tx(0x00UL); // START bit + uart_io_sim_delay(SEND_BYTE_START_DELAY); + for (i = 0; i < 8; i++) + { + uart_io_sim_set_tx((data >> i) & 0x01UL); + uart_io_sim_delay(DELAY_NOPS_COUNT); + } + uart_io_sim_set_tx(0x01UL); // STOP bit + uart_io_sim_delay(DELAY_NOPS_COUNT * 3); +#endif +} + +void uart_io_sim_send_string(char *buff) +{ + while (*buff) + uart_io_sim_send_byte(*buff++); +} + +void uart_io_sim_send(u8 *buff, int len) +{ + if (buff == NULL) + { + return; + } + + if (len < 0) + { + return; + } + +#if defined INTERRUPT_METHOD + p_uart_io_sim_tx_buf = buff; + uart_io_sim_tx_buf_size = len; + uart_io_sim_tx_buf_current_cnt = 0; + uart_io_sim_tx_buf_current_bit = 0; + + *((volatile UINT32 *)(PWM_CTL)) = (*(volatile UINT32 *)(PWM_CTL)) | (2 << (UART_IO_SIM_PWM_TIMER_TX_CHN * 4)); + +#elif defined POLLING_METHOD + REG_ICU_INT_GLOBAL_ENABLE = 0; + while (len--) + { + uart_io_sim_send_byte(*buff ++); + } + REG_ICU_INT_GLOBAL_ENABLE = ICU_INT_GLOBAL_ENABLE_IRQ_SET + ICU_INT_GLOBAL_ENABLE_FIQ_SET; // CPU IRQ enable +#endif +} +#endif /* #ifdef INCLUDE_TX_MODE */ + +#ifdef INCLUDE_RX_MODE +unsigned char UARTCALL uart_io_sim_receive_byte(void) +{ + unsigned char ucTemp; + ucTemp = 0; +#if defined INTERRUPT_METHOD +#elif defined POLLING_METHOD +#if (MCU_CLK > MCU_CLK_16MHz) + uart_io_sim_delay(RECEIVE_BYTE_START_DELAY); +#endif + int i; + for (i = 0; i < 7; i++) + { + ucTemp |= (uart_io_sim_get_rx() << i); + uart_io_sim_delay(RECEIVE_BYTE_MIDDLE_DELAY); + } + uart_io_sim_delay(RECEIVE_BYTE_CALI_LAST_DELAY); + ucTemp |= (uart_io_sim_get_rx() << 7); + uart_io_sim_delay(RECEIVE_BYTE_LAST_DELAY); +#endif + return ucTemp; +} + +void UARTCALL uart_io_sim_receive(void) +{ +#if defined INTERRUPT_METHOD +#elif defined POLLING_METHOD + int i; + REG_ICU_INT_GLOBAL_ENABLE = 0; // CPU IRQ disable + while (uart_io_sim_rx_buf_current_cnt < UART_IO_SIM_RX_FIFO_MAX_COUNT) + { + uart_io_sim_rx_buf[uart_io_sim_rx_buf_current_cnt] = uart_io_sim_receive_byte(); + uart_io_sim_rx_buf_current_cnt ++; + uart_io_sim_rx_done = TRUE; + i = 0; + while (i++ < (DELAY_NOPS_COUNT * 10)) + { + if (uart_io_sim_get_rx() == 0x00) + { + uart_io_sim_delay(RECEIVE_BYTE_STOP_DELAY); + break; + } + } + if (i >= (DELAY_NOPS_COUNT * 10)) + { + break; + } + } + uart_io_sim_pwm_cap_neg_init_for_rx(); + REG_ICU_INT_GLOBAL_ENABLE = ICU_INT_GLOBAL_ENABLE_IRQ_SET + ICU_INT_GLOBAL_ENABLE_FIQ_SET; // CPU IRQ enable +#endif +} +#endif /* #ifdef INCLUDE_RX_MODE */ diff --git a/beken_os/beken378/func/sim_uart/pwm_uart.h b/beken_os/beken378/func/sim_uart/pwm_uart.h new file mode 100755 index 0000000..7d01eaf --- /dev/null +++ b/beken_os/beken378/func/sim_uart/pwm_uart.h @@ -0,0 +1,111 @@ + +#ifndef __DRIVER_UART_IO_SIM_H__ + +#define __DRIVER_UART_IO_SIM_H__ + + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + + +#define UART_IO_SIM_RX_FIFO_MAX_COUNT 128 +#define UART_IO_SIM_TX_FIFO_MAX_COUNT 512 + +#define UARTCALL __attribute__((section("uartcall"))) + +#define LOCAL static +#define CHIP_7231 6 +#define CHIP_ID CHIP_7231 + +#if (CHIP_ID == CHIP_7231) + +#define MCU_CLK_120MHz 120000000 +#define MCU_CLK MCU_CLK_120MHz + +#define PER_CLK_120MHz 120000000 +#endif /* #if (CHIP_ID == CHIP_7211) */ + + //#define POLLING_METHOD +#define INTERRUPT_METHOD + +//#define INCLUDE_TX_MODE +//#define INCLUDE_RX_MODE +//#define GPIO_7231_STYLE 1 + + +#if defined POLLING_METHOD +#if (MCU_CLK == MCU_CLK_120MHz) +#define DELAY_NOPS_COUNT 102 +#define SEND_BYTE_START_DELAY (DELAY_NOPS_COUNT - 2) +#define RECEIVE_BYTE_START_DELAY (DELAY_NOPS_COUNT - 11) +#define RECEIVE_BYTE_MIDDLE_DELAY (DELAY_NOPS_COUNT + 1) +#define RECEIVE_BYTE_CALI_LAST_DELAY (1) +#define RECEIVE_BYTE_LAST_DELAY (DELAY_NOPS_COUNT - 2 - RECEIVE_BYTE_CALI_LAST_DELAY) +#define RECEIVE_BYTE_STOP_DELAY (DELAY_NOPS_COUNT + 6) +#define WATCH_SAMPLE_POINT_RCV_MID_DLY (DELAY_NOPS_COUNT - 4) +#define WATCH_SAMPLE_POINT_RCV_LST_DLY (DELAY_NOPS_COUNT - 6) +#endif +#endif + + +#ifdef INTERRUPT_METHOD +#define UART_IO_SIM_DEFAULT_CLK MCU_CLK +#define UART_IO_SIM_BAUD_115200 60000000 /*115200*/ +#define UART_IO_SIM_DEFAULT_BAUD UART_IO_SIM_BAUD_115200 +#define UART_IO_SIM_CLK_DIVID_SET 271 +#define UART_IO_SIM_CLK_DIVID_SET_TX 2710 +#define UART_IO_SIM_CLK_FIRST_DELAY_SET 4000 +#endif + + +#ifdef INTERRUPT_METHOD +#define UART_IO_SIM_PWM_TIMER_TX_CHN PWM1 +#define UART_IO_SIM_PWM_TIMER_RX_CHN PWM2 +#endif + + + +#if defined GPIO_7231_STYLE +#define GPIO_UART_IO_SIM_TX_PIN 18 +#define GPIO_UART_IO_SIM_RX_PIN 19 +#define UART_IO_SIM_PWM_CAP_NEG_RX_CHN PWM5 +#define SIMU_UART_GPIO_TEST 15 +#define PWM5_GPIO_PIN GPIO_UART_IO_SIM_RX_PIN + +#endif + +#if 0//defined GPIO_7231_STYLE +#define GCFG_OUTPUT_POS 1 +#define GCFG_INPUT_BIT (1 << 0) +#define GPIO_BASE_ADDR (0x0802800) +#define PWM2_GPIO_PIN 8 + +#define PWM_CTL (PWM_BASE + 0 * 4) +#define ICU_BASE (0x00802000) +#define ICU_PERI_CLK_PWD (ICU_BASE + 2 * 4) +#define ICU_PWM_CLK_MUX (ICU_BASE + 1 * 4) +#define ICU_INTERRUPT_ENABLE (ICU_BASE + 16 * 4) +#define REG_GPIO_FUNC_CFG (GPIO_BASE_ADDR + 32*4) +#if (CFG_SOC_NAME == SOC_BK7231) +#define PWM_BASE (0x00802A00) +#define REG_APB_BK_PWMn_CNT_ADDR(n) (PWM_BASE + 0x08 + 2 * 0x04 * (n)) +#else +#define PWM_NEW_BASE (0x00802A00) +#define PWM_BASE (PWM_NEW_BASE + 0x20 * 4 ) +#define REG_APB_BK_PWMn_END_ADDR(n) (PWM_BASE + 0x08 + 2 * 0x04 * (n)) +#endif +#endif + +extern void uart_io_sim_init(void); +extern void uart_io_sim_disable(void); +extern void uart_io_sim_send_byte(u8 data); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + + +#endif /* __DRIVER_UART_IO_SIM_H__ */ + diff --git a/beken_os/beken378/func/spidma_intf/spidma_intf.c b/beken_os/beken378/func/spidma_intf/spidma_intf.c new file mode 100755 index 0000000..c29cb57 --- /dev/null +++ b/beken_os/beken378/func/spidma_intf/spidma_intf.c @@ -0,0 +1,141 @@ +#include "include.h" +#include "arm_arch.h" + +#if CFG_USE_SPIDMA +#include "video_transfer.h" + +#include "spidma_pub.h" +#include "spidma_intf.h" +#include "spidma_intf_pub.h" + +#include "drv_model_pub.h" +#include "mem_pub.h" +#if CFG_GENERAL_DMA +#include "general_dma_pub.h" +#endif + +#define SPIDMA_INTF_DEBUG 1 +#include "uart_pub.h" +#if SPIDMA_INTF_DEBUG +#define SPIDMA_INTF_PRT os_printf +#define SPIDMA_INTF_WPRT warning_prf +#define SPIDMA_INTF_FATAL fatal_prf +#else +#define SPIDMA_INTF_PRT null_prf +#define SPIDMA_INTF_WPRT null_prf +#define SPIDMA_INTF_FATAL null_prf +#endif + +#define RX_TIMEOUT_30US 30 +#define RX_TIMEOUT_500US 500 +#define FPGA_MAIN_CLK 120 +#define SPIDMA_RXDATA_TIMEOUT (FPGA_MAIN_CLK * RX_TIMEOUT_500US) + +#ifndef SPIDMA_RXDATA_TIMEOUT +#define SPIDMA_RXDATA_TIMEOUT SPIDMA_DEF_RXDATA_TIMEOUT_VAL +#endif + +#define SPIDMA_CHNAL GDMA_CHANNEL_5 + +DD_HANDLE spidma_hdl = DD_HANDLE_UNVALID; +SPIDMA_DESC_ST spidma_intf; + +#if CFG_GENERAL_DMA +static void spidma_intf_node_rx_handler(UINT32 dma) +{ + UINT16 already_len = spidma_intf.rx_read_len; + UINT16 copy_len = spidma_intf.node_len; + GLOBAL_INT_DECLARATION(); + + if(spidma_intf.node_full_handler != NULL) { + spidma_intf.node_full_handler(spidma_intf.rxbuf + already_len, copy_len, 0, 0); + } + + already_len += copy_len; + + if(already_len >= spidma_intf.rxbuf_len) + already_len = 0; + + GLOBAL_INT_DISABLE(); + spidma_intf.rx_read_len = already_len; + GLOBAL_INT_RESTORE(); +} +#endif + +static void spidma_intf_frame_end_handler(void) +{ + #if CFG_GENERAL_DMA + GDMA_CFG_ST en_cfg; + UINT16 already_len = spidma_intf.rx_read_len; + UINT32 channel = SPIDMA_CHNAL; + int left_len = sddev_control(GDMA_DEV_NAME, CMD_GDMA_GET_LEFT_LEN, (void*)channel); + int rec_len = spidma_intf.node_len - left_len; + + if((spidma_intf.node_full_handler != NULL) && (rec_len > 0)) { + spidma_intf.node_full_handler(spidma_intf.rxbuf + already_len, rec_len, 0, 0); + } + + already_len += rec_len; + if(already_len >= spidma_intf.rxbuf_len) { + already_len -= spidma_intf.rxbuf_len; + } + + spidma_intf.rx_read_len = already_len; + + // turn off dma, so dma can start from first configure. for easy handler + en_cfg.channel = SPIDMA_CHNAL; + en_cfg.param = 0; + sddev_control(GDMA_DEV_NAME, CMD_GDMA_SET_DMA_ENABLE, &en_cfg); + + spidma_intf.rx_read_len = 0; + en_cfg.param = 1; + sddev_control(GDMA_DEV_NAME, CMD_GDMA_SET_DMA_ENABLE, &en_cfg); + #endif + + if((spidma_intf.data_end_handler)) { + spidma_intf.data_end_handler(); + } +} + +static void spidma_intfer_config_desc(void* data) +{ + os_memset(&spidma_intf, 0, sizeof(SPIDMA_DESC_ST)); + os_memcpy(&spidma_intf, data, sizeof(TVIDEO_DESC_ST)); + + spidma_intf.txbuf = NULL; + spidma_intf.txbuf_len = 0; + + spidma_intf.tx_handler = NULL; + + spidma_intf.mode = 0; + spidma_intf.timeout_val = SPIDMA_RXDATA_TIMEOUT; + spidma_intf.end_frame_handler = spidma_intf_frame_end_handler; + + #if CFG_GENERAL_DMA + spidma_intf.dma_rx_handler = spidma_intf_node_rx_handler; + spidma_intf.dma_channel = SPIDMA_CHNAL; +#endif +} + +/*---------------------------------------------------------------------------*/ +void spidma_intfer_init(void* data) +{ + UINT32 status; + spidma_intfer_config_desc(data); + + spidma_hdl = ddev_open(SPIDMA_DEV_NAME, &status, (UINT32)&spidma_intf); + SPIDMA_INTF_FATAL("spidma_intfer_init,%p\r\n", spidma_hdl); +} + +void spidma_intfer_deinit(void) +{ + SPIDMA_INTF_FATAL("spidma_intfer_deinit,%p\r\n", spidma_hdl); + ddev_close(spidma_hdl); + os_memset(&spidma_intf, 0, sizeof(SPIDMA_DESC_ST)); + + spidma_hdl = DD_HANDLE_UNVALID; +} +/*---------------------------------------------------------------------------*/ + +#endif // CFG_USE_SPIDMA + diff --git a/beken_os/beken378/func/spidma_intf/spidma_intf.h b/beken_os/beken378/func/spidma_intf/spidma_intf.h new file mode 100755 index 0000000..23b56fa --- /dev/null +++ b/beken_os/beken378/func/spidma_intf/spidma_intf.h @@ -0,0 +1,6 @@ +#ifndef __SPIDMA_INTF_H__ +#define __SPIDMA_INTF_H__ + + +#endif + diff --git a/beken_os/beken378/func/spidma_intf/spidma_intf_pub.h b/beken_os/beken378/func/spidma_intf/spidma_intf_pub.h new file mode 100755 index 0000000..abe80e9 --- /dev/null +++ b/beken_os/beken378/func/spidma_intf/spidma_intf_pub.h @@ -0,0 +1,8 @@ +#ifndef __SPIDMA_INTF_PUB_H__ +#define __SPIDMA_INTF_PUB_H__ + +void spidma_intfer_init(void* data); +void spidma_intfer_deinit(void); + +#endif + diff --git a/beken_os/beken378/func/temp_detect/temp_detect.c b/beken_os/beken378/func/temp_detect/temp_detect.c new file mode 100755 index 0000000..d4825cf --- /dev/null +++ b/beken_os/beken378/func/temp_detect/temp_detect.c @@ -0,0 +1,706 @@ +#include "include.h" +#include "arm_arch.h" + + +#include "target_util_pub.h" +#include "mem_pub.h" +#include "drv_model_pub.h" +#include "sys_ctrl_pub.h" +#include "saradc_pub.h" +#include "uart_pub.h" + +#if (!CFG_SUPPORT_ALIOS) +#include "sys_rtos.h" +#endif +#include "rtos_pub.h" +#include "rtos_error.h" +#include "fake_clock_pub.h" + +#include "bk7011_cal_pub.h" +#include "temp_detect_pub.h" +#include "temp_detect.h" +#include "power_save_pub.h" + +// for single temp dectect +saradc_desc_t tmp_single_desc; +UINT16 tmp_single_buff[ADC_TEMP_BUFFER_SIZE]; +volatile DD_HANDLE tmp_single_hdl = DD_HANDLE_UNVALID; +beken_semaphore_t tmp_single_semaphore = NULL; + +extern void manual_cal_tmp_pwr_init(UINT16 init_temp, UINT16 init_thre, UINT16 init_dist); +extern void turnoff_PA_in_temp_dect(void); +extern void turnon_PA_in_temp_dect(void); +static void temp_single_get_desc_init(void); +extern void ps_set_temp_prevent(void); +extern void ps_clear_temp_prevent(void); + +#if CFG_USE_TEMPERATURE_DETECT +volatile DD_HANDLE tmp_detect_hdl = DD_HANDLE_UNVALID; +saradc_desc_t tmp_detect_desc; +UINT16 tmp_detect_buff[ADC_TEMP_BUFFER_SIZE]; +TEMP_DETECT_CONFIG_ST g_temp_detect_config; +#if CFG_SUPPORT_ALIOS +beken_thread_t temp_detct_handle = NULL; +#else +xTaskHandle temp_detct_handle = NULL; +#endif + +enum +{ + TMPD_PAUSE_TIMER = 0, + TMPD_RESTART_TIMER, + TMPD_CHANGE_PARAM, + TMPD_TIMER_POLL, + TMPD_INT_POLL, + TMPD_EXIT, +}; + +typedef struct temp_message +{ + u32 temp_msg; +}TEMP_MSG_T; + +#define TEMP_DET_QITEM_COUNT (5) + +beken_queue_t tempd_msg_que = NULL; + + +static void temp_detect_handler(void); +static void temp_detect_main( beken_thread_arg_t data ); +extern void rwnx_cal_do_temp_detect(UINT16 cur_val, UINT16 thre, UINT16 *last); + +static void temp_detect_desc_init(void) +{ + tmp_detect_desc.has_data = 0; + tmp_detect_desc.current_sample_data_cnt = 0; +} + +static void temp_detect_enable_config_sysctrl(void) +{ + UINT32 param; + + param = BLK_BIT_TEMPRATURE_SENSOR; + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_BLK_ENABLE, ¶m); +} + +static void temp_detect_disable_config_sysctrl(void) +{ + UINT32 param; + param = BLK_BIT_TEMPRATURE_SENSOR; + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_BLK_DISABLE, ¶m); +} + +void temp_detect_send_msg(u32 new_msg) +{ + OSStatus ret; + TEMP_MSG_T msg; + + if(tempd_msg_que) { + msg.temp_msg = new_msg; + + ret = rtos_push_to_queue(&tempd_msg_que, &msg, BEKEN_NO_WAIT); + if(kNoErr != ret) + { + os_printf("temp_detect_send_msg failed\r\n"); + } + } +} + + +UINT32 temp_detect_init(UINT32 init_val) +{ + int ret; + + TMP_DETECT_FATAL("temp_detect_init %d\r\n", init_val); + + if((!temp_detct_handle) && (!tempd_msg_que)) + { + + ret = rtos_init_queue(&tempd_msg_que, + "temp_det_queue", + sizeof(TEMP_MSG_T), + TEMP_DET_QITEM_COUNT); + if (kNoErr != ret) + { + TMP_DETECT_FATAL("temp detect ceate queue failed\r\n"); + return kGeneralErr; + } + + ret = rtos_create_thread(&temp_detct_handle, + BEKEN_DEFAULT_WORKER_PRIORITY, + "temp_detct", + (beken_thread_function_t)temp_detect_main, + 1024, + (beken_thread_arg_t)init_val); + if (ret != kNoErr) + { + rtos_deinit_queue(&tempd_msg_que); + tempd_msg_que = NULL; + TMP_DETECT_FATAL("Error: Failed to create temp_detect: %d\r\n", ret); + return kGeneralErr; + } + } + + return kNoErr; +} + +UINT32 temp_detect_uninit(void) +{ + if((temp_detct_handle) && (tempd_msg_que)) + { + //temp_detect_send_msg(TMPD_EXIT); + + // wait untill task exit + //while(temp_detct_handle) + // rtos_delay_milliseconds(100); + + // set reg mod & pa to initial value, this must be happened in + // txevm or rxsens to calibration txpwr or rxsens + manual_cal_temp_pwr_unint(); + } + + return 0; +} + +void temp_detect_pause_timer(void) +{ + if(g_temp_detect_config.detect_timer.function + && rtos_is_timer_running(&g_temp_detect_config.detect_timer)) + { + temp_detect_send_msg(TMPD_PAUSE_TIMER); + } +} + +void temp_detect_restart_detect(void) +{ + if(g_temp_detect_config.detect_timer.function && + !rtos_is_timer_running(&g_temp_detect_config.detect_timer)) + { + temp_detect_send_msg(TMPD_RESTART_TIMER); + } +} + +UINT32 temp_detect_is_opened_saradc(void) +{ + // if saradc is opened, idle hook to do sleep may turn off saradc's icu clk and inter enbit + // so before sleep, should check this bit + + return (DD_HANDLE_UNVALID != tmp_detect_hdl); +} + +UINT32 temp_detect_is_init(void) +{ + return ((temp_detct_handle) && (tempd_msg_que)); +} + +static UINT32 temp_detect_open(void) +{ + UINT32 status; + GLOBAL_INT_DECLARATION(); + +#if (CFG_SOC_NAME == SOC_BK7231) + turnoff_PA_in_temp_dect(); +#endif // (CFG_SOC_NAME == SOC_BK7231) + + GLOBAL_INT_DISABLE(); + tmp_detect_hdl = ddev_open(SARADC_DEV_NAME, &status, (UINT32)&tmp_detect_desc); + if ((DD_HANDLE_UNVALID == tmp_detect_hdl) || (SARADC_SUCCESS != status)) + { + if (SARADC_SUCCESS != status) + { + ddev_close(tmp_detect_hdl); + } + tmp_detect_hdl = DD_HANDLE_UNVALID; + GLOBAL_INT_RESTORE(); + return SARADC_FAILURE; + } + + GLOBAL_INT_RESTORE(); + + return SARADC_SUCCESS; +} + +static UINT32 temp_detect_close(void) +{ + UINT32 status = DRV_SUCCESS; + GLOBAL_INT_DECLARATION(); + + GLOBAL_INT_DISABLE(); + status = ddev_close(tmp_detect_hdl); + if(DRV_FAILURE == status ) + { + } + tmp_detect_hdl = DD_HANDLE_UNVALID; + GLOBAL_INT_RESTORE(); + + return SARADC_SUCCESS; +} + +static UINT32 temp_detect_enable(void) +{ + UINT32 err = SARADC_SUCCESS; + + if(tmp_detect_hdl != DD_HANDLE_UNVALID) + { + //aready enable saradc, so return no err + TMP_DETECT_PRT("aready open\r\n"); + return SARADC_SUCCESS; + } + + while(tmp_single_hdl != DD_HANDLE_UNVALID) + { + rtos_delay_milliseconds(10);; + } + + err = rtos_stop_timer(&g_temp_detect_config.detect_timer); + ASSERT(kNoErr == err); + TMP_DETECT_PRT("stop detect timer, start ADC\r\n"); + + temp_detect_desc_init(); + temp_detect_enable_config_sysctrl(); + + err = temp_detect_open(); + if(err == SARADC_FAILURE) + { + temp_detect_disable_config_sysctrl(); + + TMP_DETECT_FATAL("Can't open saradc, have you register this device?\r\n"); + return err; + } + TMP_DETECT_PRT("saradc_open is ok \r\n"); + + return SARADC_SUCCESS; +} + +static void temp_detect_disable(void) +{ + temp_detect_close(); + saradc_ensure_close(); + temp_detect_disable_config_sysctrl(); + TMP_DETECT_PRT("saradc_open is close \r\n"); +} + +static void temp_detect_timer_handler(void *data) +{ + temp_detect_send_msg(TMPD_TIMER_POLL); +} + +static void temp_detect_timer_poll(void) +{ + OSStatus err; + + if((temp_detect_enable() != SARADC_SUCCESS)) + { + err = rtos_reload_timer(&g_temp_detect_config.detect_timer); + TMP_DETECT_PRT("temp_detect_enable failed, restart detect timer, \r\n"); + } + (void)err; +} + +static void temp_detect_polling_handler(void) +{ + OSStatus err; + UINT16 cur_val, thre; + + #if (CFG_SOC_NAME != SOC_BK7231) + cur_val = tmp_detect_desc.pData[0]; + #else + cur_val = tmp_detect_desc.pData[ADC_TEMP_BUFFER_SIZE-1]; + #endif // (CFG_SOC_NAME != SOC_BK7231) + + thre = g_temp_detect_config.detect_thre; + + g_temp_detect_config.detect_intval_change++; + + TMP_DETECT_PRT("%d:%d seconds: last:%d, cur:%d, thr:%d\r\n", + g_temp_detect_config.detect_intval, + g_temp_detect_config.detect_intval_change, + g_temp_detect_config.last_detect_val, + cur_val, + g_temp_detect_config.detect_thre); + + ps_set_temp_prevent(); + + #if CFG_USE_STA_PS + bk_wlan_dtim_rf_ps_mode_do_wakeup(); + #endif + + rwnx_cal_do_temp_detect(cur_val, thre, &g_temp_detect_config.last_detect_val); + ps_clear_temp_prevent(); + + if(g_temp_detect_config.detect_intval_change == ADC_TMEP_DETECT_INTVAL_CHANGE) + { + temp_detect_send_msg(TMPD_CHANGE_PARAM); + } + else + { + err = rtos_reload_timer(&g_temp_detect_config.detect_timer); + ASSERT(kNoErr == err); + } +} + +static void temp_detect_main( beken_thread_arg_t data ) +{ + OSStatus err; + + os_memset(&tmp_detect_buff[0], 0, sizeof(UINT16)*ADC_TEMP_BUFFER_SIZE); + + saradc_config_param_init(&tmp_detect_desc); + tmp_detect_desc.channel = ADC_TEMP_SENSER_CHANNEL; + tmp_detect_desc.pData = &tmp_detect_buff[0]; + tmp_detect_desc.data_buff_size = ADC_TEMP_BUFFER_SIZE; + tmp_detect_desc.p_Int_Handler = temp_detect_handler; + + g_temp_detect_config.last_detect_val = (UINT32)(data); +#if CFG_TEMP_DETECT_VERSION == CFG_TEMP_DETECT_VERSION1 + g_temp_detect_config.inital_data = (UINT32)(data); +#else + g_temp_detect_config.inital_data = (UINT32)(data) + ADC_TMEP_DIST_INTIAL_VAL; +#endif + g_temp_detect_config.detect_thre = ADC_TMEP_LSB_PER_10DEGREE * ADC_TMEP_10DEGREE_PER_DBPWR; + g_temp_detect_config.detect_intval = ADC_TMEP_DETECT_INTVAL_INIT; + g_temp_detect_config.detect_intval_change = 0; + g_temp_detect_config.dist_inital = ADC_TMEP_DIST_INTIAL_VAL; + +#if CFG_TEMP_DETECT_VERSION != CFG_TEMP_DETECT_VERSION1 + g_temp_detect_config.last_xtal_val = (UINT32)(data); + #if (CFG_SOC_NAME != SOC_BK7231) + g_temp_detect_config.xtal_thre_val = ADC_XTAL_DIST_INTIAL_VAL; + g_temp_detect_config.xtal_init_val = sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_GET_XTALH_CTUNE, NULL); + os_printf("xtal inital:%d, %d, %d\r\n", g_temp_detect_config.last_xtal_val, + g_temp_detect_config.xtal_thre_val, g_temp_detect_config.xtal_init_val); + #endif // (CFG_SOC_NAME != SOC_BK7231) +#endif + err = rtos_init_timer(&g_temp_detect_config.detect_timer, + g_temp_detect_config.detect_intval * 1000, + temp_detect_timer_handler, + (void *)0); + ASSERT(kNoErr == err); + err = rtos_start_timer(&g_temp_detect_config.detect_timer); + + ASSERT(kNoErr == err); + + while(1) + { + TEMP_MSG_T msg; + err = rtos_pop_from_queue(&tempd_msg_que, &msg, BEKEN_WAIT_FOREVER); + if(kNoErr == err) + { + switch(msg.temp_msg) + { + case TMPD_PAUSE_TIMER: + { + os_printf("pause_detect\r\n"); + err = rtos_stop_timer(&g_temp_detect_config.detect_timer); + ASSERT(kNoErr == err); + } + break; + case TMPD_RESTART_TIMER: + { + os_printf(" restart detect timer\r\n"); + err = rtos_reload_timer(&g_temp_detect_config.detect_timer); + ASSERT(kNoErr == err); + } + break; + case TMPD_CHANGE_PARAM: + { + temp_detect_change_configuration(ADC_TMEP_DETECT_INTVAL, + g_temp_detect_config.detect_thre, ADC_TMEP_DIST_INTIAL_VAL); + } + break; + case TMPD_TIMER_POLL: + { + temp_detect_timer_poll(); + } + break; + case TMPD_INT_POLL: + temp_detect_polling_handler(); + break; + case TMPD_EXIT: + goto tempd_exit; + break; + default: + break; + } + } + } + +tempd_exit: + err = rtos_deinit_timer(&g_temp_detect_config.detect_timer); + ASSERT(kNoErr == err); + + rtos_deinit_queue(&tempd_msg_que); + tempd_msg_que = NULL; + + temp_detct_handle = NULL; + rtos_delete_thread(NULL); +} + +static void temp_detect_handler(void) +{ + if(tmp_detect_hdl == DD_HANDLE_UNVALID) + { + //os_printf("u_err\r\n"); + return; + } + + if(tmp_detect_desc.current_sample_data_cnt >= tmp_detect_desc.data_buff_size) + { +#if (CFG_SOC_NAME == SOC_BK7231N) + UINT32 sum = 0, index, count = 0; + + temp_detect_disable(); + TMP_DETECT_PRT("buff:%p,%d,%d,%d,%d,%d\r\n", tmp_detect_desc.pData, + tmp_detect_desc.pData[5], tmp_detect_desc.pData[6], + tmp_detect_desc.pData[7], tmp_detect_desc.pData[8], + tmp_detect_desc.pData[9]); + for (index = 5; index < ADC_TEMP_BUFFER_SIZE; index++) + { + /* 0 is invalid, but saradc may return 0 in power save mode */ + if ((0 != tmp_detect_desc.pData[index]) && (2048 != tmp_detect_desc.pData[index])) + { + sum += tmp_detect_desc.pData[index]; + count++; + } + } + if (count == 0) + { + tmp_detect_desc.pData[0] = 0; + } + else + { + sum = sum / count; + sum = sum / 4; + tmp_detect_desc.pData[0] = sum; + } +#elif (CFG_SOC_NAME != SOC_BK7231) + UINT32 sum = 0, sum1, sum2; + //turnon_PA_in_temp_dect(); + temp_detect_disable(); + TMP_DETECT_PRT("buff:%p,%d,%d,%d,%d,%d\r\n", tmp_detect_desc.pData, + tmp_detect_desc.pData[0], tmp_detect_desc.pData[1], + tmp_detect_desc.pData[2], tmp_detect_desc.pData[3], + tmp_detect_desc.pData[4]); + sum1 = tmp_detect_desc.pData[1] + tmp_detect_desc.pData[2]; + sum2 += tmp_detect_desc.pData[3] + tmp_detect_desc.pData[4]; + sum = sum1 / 2 + sum1 / 2; + sum = sum / 2; + sum = sum / 4; + tmp_detect_desc.pData[0] = sum; + #else + turnon_PA_in_temp_dect(); + TMP_DETECT_PRT("buff:%p,%d,%d,%d,%d,%d\r\n", tmp_detect_desc.pData, + tmp_detect_desc.pData[0], tmp_detect_desc.pData[1], + tmp_detect_desc.pData[2], tmp_detect_desc.pData[3], + tmp_detect_desc.pData[4]); + temp_detect_disable(); + #endif // (CFG_SOC_NAME != SOC_BK7231) + temp_detect_send_msg(TMPD_INT_POLL); + } +} + +void temp_detect_change_configuration(UINT32 intval, UINT32 thre, UINT32 dist) +{ + OSStatus err; + + if(intval == 0) + intval = ADC_TMEP_DETECT_INTVAL; + if(thre == 0) + thre = ADC_TMEP_LSB_PER_10DEGREE * ADC_TMEP_10DEGREE_PER_DBPWR; + if(dist == 0) + dist = ADC_TMEP_DIST_INTIAL_VAL; + + TMP_DETECT_WARN("config: intval:%d, thre:%d, dist:%d\r\n", intval, thre, dist); + + if((g_temp_detect_config.detect_thre != thre) + || (g_temp_detect_config.dist_inital != dist)) + { + if(g_temp_detect_config.detect_thre != thre) + g_temp_detect_config.detect_thre = thre; + + if(g_temp_detect_config.dist_inital != dist) + g_temp_detect_config.dist_inital = dist; + + manual_cal_tmp_pwr_init(g_temp_detect_config.inital_data, + g_temp_detect_config.detect_thre, g_temp_detect_config.dist_inital); + } + + if(g_temp_detect_config.detect_intval != intval) + { + g_temp_detect_config.detect_intval = intval; + + if(g_temp_detect_config.detect_timer.function) { + err = rtos_deinit_timer(&g_temp_detect_config.detect_timer); + ASSERT(kNoErr == err); + } + + err = rtos_init_timer(&g_temp_detect_config.detect_timer, + g_temp_detect_config.detect_intval * 1000, + temp_detect_timer_handler, + (void *)0); + ASSERT(kNoErr == err); + + err = rtos_start_timer(&g_temp_detect_config.detect_timer); + ASSERT(kNoErr == err); + } +} + +UINT32 temp_get_detect_time(void) +{ + return rtos_get_timer_expiry_time(&g_temp_detect_config.detect_timer); +} + +//////////////////////////////////////////////////////////////////////// +#endif // CFG_USE_TEMPERATURE_DETECT + +static UINT32 temp_single_get_enable(void) +{ + UINT32 status; + GLOBAL_INT_DECLARATION(); + +#if CFG_USE_TEMPERATURE_DETECT + while(tmp_detect_hdl != DD_HANDLE_UNVALID) + { + rtos_delay_milliseconds(10); + } +#endif + temp_single_get_desc_init(); + + status = BLK_BIT_TEMPRATURE_SENSOR; + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_BLK_ENABLE, &status); + +#if (CFG_SOC_NAME == SOC_BK7231) + turnoff_PA_in_temp_dect(); +#endif // (CFG_SOC_NAME == SOC_BK7231) + GLOBAL_INT_DISABLE(); + tmp_single_hdl = ddev_open(SARADC_DEV_NAME, &status, (UINT32)&tmp_single_desc); + if(DD_HANDLE_UNVALID == tmp_single_hdl) + { + GLOBAL_INT_RESTORE(); + TMP_DETECT_FATAL("Can't open saradc, have you register this device?\r\n"); + return SARADC_FAILURE; + } + GLOBAL_INT_RESTORE(); + + return SARADC_SUCCESS; +} + +static void temp_single_get_disable(void) +{ + UINT32 status = DRV_SUCCESS; + + status = ddev_close(tmp_single_hdl); + if(DRV_FAILURE == status ) + { + //TMP_DETECT_PRT("saradc disable failed\r\n"); + //return; + } + saradc_ensure_close(); + tmp_single_hdl = DD_HANDLE_UNVALID; + + status = BLK_BIT_TEMPRATURE_SENSOR; + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_BLK_DISABLE, &status); + + TMP_DETECT_PRT("saradc_open is close \r\n"); +} + +static void temp_single_detect_handler(void) +{ + if(tmp_single_desc.current_sample_data_cnt >= tmp_single_desc.data_buff_size) + { + #if (CFG_SOC_NAME != SOC_BK7231) + UINT32 sum = 0, sum1, sum2; + //turnon_PA_in_temp_dect(); + temp_single_get_disable(); + TMP_DETECT_PRT("buff:%p,%d,%d,%d,%d,%d\r\n", tmp_single_desc.pData, + tmp_single_desc.pData[0], tmp_single_desc.pData[1], + tmp_single_desc.pData[2], tmp_single_desc.pData[3], + tmp_single_desc.pData[4]); + +#if (CFG_SOC_NAME == SOC_BK7231N) + sum1 = tmp_single_desc.pData[6] + tmp_single_desc.pData[7]; + sum2 = tmp_single_desc.pData[8] + tmp_single_desc.pData[9]; + sum = sum1 / 2 + sum2 / 2; +#else + sum1 = tmp_single_desc.pData[1] + tmp_single_desc.pData[2]; + sum2 += tmp_single_desc.pData[3] + tmp_single_desc.pData[4]; + sum = sum1 / 2 + sum1 / 2; +#endif + sum = sum / 2; +#if (CFG_SOC_NAME == SOC_BK7231N) + sum = sum / 4; +#endif + tmp_single_desc.pData[0] = sum; + #else + turnon_PA_in_temp_dect(); + temp_single_get_disable(); + TMP_DETECT_PRT("buff:%p,%d,%d,%d,%d,%d\r\n", tmp_single_desc.pData, + tmp_single_desc.pData[0], tmp_single_desc.pData[1], + tmp_single_desc.pData[2], tmp_single_desc.pData[3], + tmp_single_desc.pData[4]); + #endif // (CFG_SOC_NAME != SOC_BK7231) + + rtos_set_semaphore(&tmp_single_semaphore); + } +} + +static void temp_single_get_desc_init(void) +{ + os_memset(&tmp_single_buff[0], 0, sizeof(UINT16)*ADC_TEMP_BUFFER_SIZE); + + saradc_config_param_init(&tmp_single_desc); + tmp_single_desc.channel = ADC_TEMP_SENSER_CHANNEL; + tmp_single_desc.pData = &tmp_single_buff[0]; + tmp_single_desc.data_buff_size = ADC_TEMP_BUFFER_SIZE; + tmp_single_desc.p_Int_Handler = temp_single_detect_handler; +} + +UINT32 temp_single_get_current_temperature(UINT32 *temp_value) +{ + UINT32 ret; + int result; + int retry_count = 3; + + *temp_value = 0; + + for (; retry_count > 0; retry_count--) { + if(tmp_single_semaphore == NULL) { +#if CFG_SUPPORT_ALIOS + result = rtos_init_semaphore(&tmp_single_semaphore, 0); +#else + result = rtos_init_semaphore(&tmp_single_semaphore, 1); +#endif + ASSERT(kNoErr == result); + } + + ret = temp_single_get_enable(); + if (SARADC_SUCCESS != ret) + { + continue; + } + + ret = 1000; // 1s + result = rtos_get_semaphore(&tmp_single_semaphore, ret); + if(result == kNoErr) { + #if (CFG_SOC_NAME != SOC_BK7231) + *temp_value = tmp_single_desc.pData[0]; + #else + *temp_value = tmp_single_desc.pData[4]; + #endif + ret = 0; + }else { + TMP_DETECT_FATAL("temp_single timeout\r\n"); + ret = 1; + } + + if ((ADC_TEMP_VAL_MIN < *temp_value) && (*temp_value < ADC_TEMP_VAL_MAX)) { + break; + } + } + + return ret; +} + +//EOF + + diff --git a/beken_os/beken378/func/temp_detect/temp_detect.h b/beken_os/beken378/func/temp_detect/temp_detect.h new file mode 100755 index 0000000..f3d31d0 --- /dev/null +++ b/beken_os/beken378/func/temp_detect/temp_detect.h @@ -0,0 +1,24 @@ +#ifndef __TEMP_DETECT_H__ +#define __TEMP_DETECT_H__ + +typedef struct temp_detect_config_st +{ + UINT16 last_detect_val; + UINT16 detect_intval; + UINT16 detect_thre; + UINT16 inital_data; + UINT16 dist_inital; + UINT16 last_xtal_val; + + #if (CFG_SOC_NAME != SOC_BK7231) + UINT16 xtal_thre_val; + UINT16 xtal_init_val; + #endif + + UINT32 detect_intval_change; + beken_timer_t detect_timer; +} TEMP_DETECT_CONFIG_ST, TEMP_DETECT_CONFIG_PTR; + +#endif +// eof + diff --git a/beken_os/beken378/func/temp_detect/temp_detect_pub.h b/beken_os/beken378/func/temp_detect/temp_detect_pub.h new file mode 100755 index 0000000..f479431 --- /dev/null +++ b/beken_os/beken378/func/temp_detect/temp_detect_pub.h @@ -0,0 +1,66 @@ +#ifndef __TEMP_DETECT_PUB_H__ +#define __TEMP_DETECT_PUB_H__ + +//#define TMP_DETECT_DEBUG + +#ifdef TMP_DETECT_DEBUG +#define TMP_DETECT_PRT os_printf +#define TMP_DETECT_WARN warning_prf +#define TMP_DETECT_FATAL fatal_prf +#else +#define TMP_DETECT_PRT null_prf +#define TMP_DETECT_WARN null_prf +#define TMP_DETECT_FATAL null_prf +#endif + +#if (CFG_SOC_NAME == SOC_BK7221U) +#define ADC_TEMP_SENSER_CHANNEL 8 +#else +#define ADC_TEMP_SENSER_CHANNEL 7 +#endif +#if (CFG_SOC_NAME == SOC_BK7231N) +#define ADC_TEMP_BUFFER_SIZE (5+5)//(+5 for skip) +#else +#define ADC_TEMP_BUFFER_SIZE 5 +#endif + +#if CFG_USE_TEMPERATURE_DETECT +#define ADC_TMEP_DETECT_INTVAL (15) // 15s how many second +#define ADC_TMEP_DETECT_INTVAL_INIT (1) // 1s +#define ADC_TMEP_XTAL_INIT (60) // 60s +#define ADC_TMEP_DETECT_INTVAL_CHANGE (120) // 2 mins + +#define ADC_TMEP_DIST_INTIAL_VAL (0) +#if (CFG_SOC_NAME == SOC_BK7231) +#define ADC_TMEP_LSB_PER_10DEGREE (24) +#elif (CFG_SOC_NAME == SOC_BK7231U) +#define ADC_TMEP_LSB_PER_10DEGREE (12) ///7231U:12 +#elif (CFG_SOC_NAME == SOC_BK7231N) +#define ADC_TMEP_LSB_PER_10DEGREE (20) +#else +#define ADC_TMEP_LSB_PER_10DEGREE (22)// 7231:24 +#endif +#define ADC_TMEP_10DEGREE_PER_DBPWR (1) // 7231:1,7231U:1, +#define ADC_TEMP_VAL_MIN (50) +#define ADC_TEMP_VAL_MAX (700) + +#define ADC_XTAL_DIST_INTIAL_VAL (70) + +/******************************************************************************* +* Function Declarations +*******************************************************************************/ +void temp_detect_change_configuration(UINT32 intval, UINT32 thre, UINT32 dist); +UINT32 temp_detect_init(UINT32 init_val); +UINT32 temp_detect_uninit(void); +void temp_detect_pause_timer(void); +void temp_detect_restart_detect(void); +UINT32 temp_get_detect_time(void); +UINT32 temp_detect_is_opened_saradc(void) ; +UINT32 temp_detect_is_init(void); + +#endif + +UINT32 temp_single_get_current_temperature(UINT32 *temp_value); + +#endif + diff --git a/beken_os/beken378/func/uart_debug/cmd_evm.c b/beken_os/beken378/func/uart_debug/cmd_evm.c new file mode 100755 index 0000000..45a4063 --- /dev/null +++ b/beken_os/beken378/func/uart_debug/cmd_evm.c @@ -0,0 +1,791 @@ +#include "include.h" +#include "cmd_evm.h" +#include "mem_pub.h" +#include "str_pub.h" +#include "uart_debug_pub.h" +#include "tx_evm_pub.h" +#include "reg_mdm_cfg.h" +#include "udebug.h" +#include "uart_pub.h" +#include "schedule_pub.h" +#include "sys_ctrl_pub.h" + +#if CFG_SUPPORT_CALIBRATION +#include "bk7011_cal_pub.h" +#include "power_save_pub.h" +#endif + +#if CFG_USE_TEMPERATURE_DETECT +#include "temp_detect_pub.h" +#endif + +#include "ate_app.h" +#include "param_config.h" + +#include "arm_arch.h" +#include "sys_ctrl_pub.h" + +typedef enum { + TXEVM_E_STOP = 0, + TXEVM_E_REBOOT, + TXEVM_E_DOFITTING, + TXEVM_E_CLR_OPT, + TXEVM_E_SET_RFCALI_STATUS, + TXEVM_E_MAX +} TXEVM_E_TYPE; + +typedef enum { + TXEVM_G_TEMP = 0, + TXEVM_G_MAC, + TXEVM_G_OPT, + TXEVM_G_TEMP_FLASH, + TXEVM_G_XTAL_FLASH, + TXEVM_G_DIFF_FLASH, + TXEVM_G_GET_SW_VER, + TXEVM_G_D0_SINGLE_TD, + TXEVM_G_RFCALI_STATUS, + TXEVM_G_DEVICE_ID, + TXEVM_G_MAX +} TXEVM_G_TYPE; + +extern void sctrl_cali_dpll(UINT8 flag); +extern void sctrl_dpll_int_open(void); +extern void mpb_set_txdelay(UINT32 delay_us); +extern void mpb_set_txdelay_precision(float delay_us); +extern UINT32 sctrl_ctrl(UINT32 cmd, void *param); +extern void manual_cal_set_dif_ble(UINT32 diff); + +UINT32 g_rate = EVM_DEFUALT_RATE; +UINT32 g_single_carrier = EVM_DEFUALT_SINGLE_CARRIER; +#define RCB_POWER_TABLE_ADDR 0x01050200 +#define RC_BEKEN_BASE 0x01050000 + +#if CFG_TX_EVM_TEST +static UINT32 evm_translate_tx_rate(UINT32 rate) +{ + UINT32 param; + + switch(rate) + { + case 1 : + param = 0x0; + break; // 1Mbps + case 2 : + param = 0x1; + break; // 2Mbps + case 5 : + param = 0x2; + break; // 5.5Mbps + case 11: + param = 0x3; + break; // 11Mbps + case 6 : + param = 0x4; + break; // 6Mbps + case 9 : + param = 0x5; + break; // 9Mbps + case 12: + param = 0x6; + break; // 12Mbps + case 18: + param = 0x7; + break; // 18Mbps + case 24: + param = 0x8; + break; // 24Mbps + case 36: + param = 0x9; + break; // 36Mbps + case 48: + param = 0xa; + break; // 48Mbps + case 54: + param = 0xb; + break; // 54Mbps + default: + param = rate; + break; // 54Mbps + } + + if(rate <= 5 || rate == 11) + g_rate = EVM_DEFUALT_B_RATE; + else + g_rate = EVM_DEFUALT_RATE; + + return param; +} +#endif + +int do_evm_get_vision(UINT8 *v_tab, UINT8 v_len) +{ + #define BOOT_LOAD_VISION_LEN (14) + #define BOOT_LOAD_VISION_ADDR (0x90) + #define VISION_HEAD (0x00CCBBEE) + #define VISION_HEAD_MASK (0x00FFFFFF) + #define VISION_LEN(x) ((x >> 24) & 0xff) + #define VISION_HEAD_MASK (0x00FFFFFF) + + UINT32 header; + UINT32 len; + + if((v_tab != NULL) && (v_len >= sizeof(UINT32))) + { + os_memcpy((UINT8*)&header, (UINT8*)BOOT_LOAD_VISION_ADDR, sizeof(header)); + len = VISION_LEN(header); + + if(((header & VISION_HEAD_MASK) == VISION_HEAD) && (len <= v_len)) + { + os_memset(v_tab, 0, v_len); + os_memcpy(v_tab, (UINT8*)(BOOT_LOAD_VISION_ADDR + sizeof(UINT32)), len); + return 1; + } + } + + return 0; +} + +/*txevm [-m mode] [-c channel] [-l packet-length] [-r physical-rate]*/ +UINT32 gmode = EVM_DEFUALT_MODE; +UINT32 gtest_mode = 0; +int do_evm(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ +#if CFG_TX_EVM_TEST + char cmd0 = 0; + char cmd1 = 0; + UINT8 fail = 0; + UINT32 packet_len = 0; + UINT32 channel = EVM_DEFUALT_CHANNEL; + UINT32 ble_channel = EVM_DEFUALT_BLE_CHANNEL; + UINT32 mode = EVM_DEFUALT_MODE; + UINT32 rate = EVM_DEFUALT_RATE; + UINT32 bandwidth = EVM_DEFUALT_BW; + UINT32 pwr_mod = EVM_DEFUALT_PWR_MOD; + UINT32 ble_pwr_mod = EVM_DEFUALT_BLE_PWR_MOD; + UINT32 pwr_pa = EVM_DEFUALT_PWR_PA; + UINT32 ble_pwr_pa = EVM_DEFUALT_PWR_PA; + UINT32 modul_format = EVM_DEFUALT_MODUL_FORMAT; + UINT32 guard_i_tpye = EVM_DEFUALT_GI_TYPE; + UINT32 single_carrier = EVM_DEFUALT_SINGLE_CARRIER; + UINT32 dif_g = 0; + UINT32 test_mode = 0; + UINT8 trigger_pll= 1; + UINT32 arg_id = 1; + UINT32 arg_cnt = argc; + UINT32 lpfcapcal_i = 0x80, lpfcapcal_q = 0x80; + UINT32 xtal = 0x10; + UINT32 is_ble_test = 0;; + UINT32 ble_test = 0; + UINT32 reg; + UINT32 txdelay = 125; + SC_TYPE_T single_carrier_type = SINGLE_CARRIER_11G; + + if(arg_cnt == 1) + return 0; + + /*step0, parameter conversion*/ + while(arg_cnt > 1) + { + if(arg_cnt > 1) + { + cmd0 = argv[arg_id][0]; + cmd1 = argv[arg_id][1]; + } + + switch(cmd0) + { + case '-': + { + arg_cnt -= 1; + + if(arg_cnt < 1) + { + fail = 1; + break; + } + + arg_cnt -= 1; + switch(cmd1) + { + case 'm': + mode = os_strtoul(argv[arg_id + 1], NULL, 10); + break; + + case 'c': + if(is_ble_test) + { + ble_channel = os_strtoul(argv[arg_id + 1], NULL, 10); + } + else + { + channel = os_strtoul(argv[arg_id + 1], NULL, 10); + } + break; + + case 'l': + packet_len = os_strtoul(argv[arg_id + 1], NULL, 10); + break; + + case 'r': // mcs 0-7: MCS0 =128, MCS1=129 t0 CS7=135. + rate = os_strtoul(argv[arg_id + 1], NULL, 10); + break; + + case 'b': + bandwidth = os_strtoul(argv[arg_id + 1], NULL, 10); + break; + + case 'f': // 0x0: Non-HT; 0x1:Non-HT-DUP; 0x2: HT-MM; 0x3: HT-GF + modul_format = os_strtoul(argv[arg_id + 1], NULL, 10); + break; + + case 'i': //GI Type. 0x0: 800ns; 0x1: 400ns + guard_i_tpye = os_strtoul(argv[arg_id + 1], NULL, 10); + break; + + case 'w': + single_carrier = os_strtoul(argv[arg_id + 1], NULL, 10); + break; + + case 't': + test_mode = os_strtoul(argv[arg_id + 1], NULL, 10); + break; + + case 'u': + trigger_pll = os_strtoul(argv[arg_id + 1], NULL, 10); + break; + +#if CFG_SUPPORT_MANUAL_CALI + case 'g': {// get system current temperature + UINT32 op = os_strtoul(argv[arg_id + 1], NULL, 10); + if(op < TXEVM_G_MAX) { + if(op == TXEVM_G_TEMP){ + manual_cal_set_rfcal_step0(); + manual_cal_get_current_temperature(); + }else if(op == TXEVM_G_MAC) { + UINT8 sysmac[6] = {0}; + //manual_cal_get_macaddr_from_flash(&sysmac[0]); + cfg_load_mac(&sysmac[0]); + os_printf("sys MAC:%02x:%02x:%02x:%02x:%02x:%02x\r\n", + sysmac[0], sysmac[1], sysmac[2], sysmac[3], sysmac[4], sysmac[5]); + }else if(op == TXEVM_G_OPT) { + manual_cal_show_otp_flash(); + }else if(op == TXEVM_G_TEMP_FLASH) { + manual_cal_load_temp_tag_from_flash(); + }else if(op == TXEVM_G_DIFF_FLASH) { + manual_cal_load_differ_tag_from_flash(); + }else if(op == TXEVM_G_GET_SW_VER) { + UINT8 vision[20]; + if(do_evm_get_vision(vision, 20)) + { + os_printf("version: %s\r\n", vision); + } + else + { + os_printf("no version\r\n", vision); + } + + }else if(op == TXEVM_G_RFCALI_STATUS) { + UINT8 index; + reg = manual_cal_g_rfcali_status(); + //match with E_CALI_STATUS + const char *status[] = + { + "not found", + "ok", + "evm fail", + "pwr fail", + }; + index = reg; + if (reg >= sizeof(status) / sizeof(status[0])) + { + index = 0; + } + os_printf("get rfcali status %d(%s)\r\n", reg, status[index]); + } + else if (op == TXEVM_G_DEVICE_ID) + { + os_printf("device_id=%08x\r\n", sctrl_ctrl(CMD_GET_DEVICE_ID, NULL)); + } + #if (CFG_SOC_NAME != SOC_BK7231) + else if(op == TXEVM_G_XTAL_FLASH) { + manual_cal_load_xtal_tag_from_flash(); + } + else if(op == TXEVM_G_D0_SINGLE_TD) + { + #if CFG_USE_TEMPERATURE_DETECT + manual_cal_do_single_temperature(); + #endif + } + #endif // #if (CFG_SOC_NAME != SOC_BK7231) + return 0; + } else { + return -1; + } + break; + } + + case 'd':{ + UINT32 flag = 0; + flag = os_strtoul(argv[arg_id + 1], NULL, 10); + dif_g = (os_strtoul(argv[arg_id + 2], NULL, 10)); + os_printf("set dif g and n20: dif:%d\r\n", dif_g); + if(flag == 1) + manual_cal_set_dif_g_n40(dif_g); + else if (flag == 2) + manual_cal_set_dif_ble(dif_g); + else if (flag == 0) + manual_cal_set_dif_g_n20(dif_g); + } + return 0; + break; + + case 'p': { // power: mod, pa + if(is_ble_test) + { + ble_pwr_mod = (os_strtoul(argv[arg_id + 1], NULL, 10)); + ble_pwr_pa = (os_strtoul(argv[arg_id + 2], NULL, 10)); + arg_cnt -= 1; + arg_id += 1; + os_printf("set ble pwr: gain:%d, unused:%d, rate:11\r\n", ble_pwr_mod, ble_pwr_pa); + rwnx_cal_set_txpwr(ble_pwr_mod, EVM_DEFUALT_BLE_RATE); + return 0; + } + else + { + pwr_mod = (os_strtoul(argv[arg_id + 1], NULL, 10)); + pwr_pa = (os_strtoul(argv[arg_id + 2], NULL, 10)); + arg_cnt -= 1; + arg_id += 1; + os_printf("set wifi pwr: gain:%d, unused:%d, rate:%d\r\n", pwr_mod, pwr_pa, g_rate); + if((gmode == EVM_DEFUALT_MODE) || (gmode == EVM_VIAMAC_NOTPC_MODE)) + rwnx_cal_set_txpwr(pwr_mod, g_rate); + else { + #if (CFG_SOC_NAME != SOC_BK7231) + pwr_mod = rwnx_tpc_pwr_idx_translate(pwr_mod, g_rate, 1); + evm_via_mac_set_power(pwr_mod); + #else + rwnx_cal_set_txpwr(pwr_mod, g_rate); + #endif + } +#if (CFG_SOC_NAME == SOC_BK7231N) + if (g_single_carrier) + { + UINT32 pwr_gain = REG_READ(RCB_POWER_TABLE_ADDR + (0x34 * 4)); + os_printf("pwr_gain:0x%x\r\n", pwr_gain & 0x3FF); + REG_WRITE((RC_BEKEN_BASE + (0x43 * 4)), pwr_gain & 0x3FF); + } +#endif + return 0; + } + } + + case 's': { // save txpwr: rate:b or g? channel mod pa + rate = os_strtoul(argv[arg_id + 1], NULL, 10); + channel = os_strtoul(argv[arg_id + 2], NULL, 10); + pwr_mod = (os_strtoul(argv[arg_id + 3], NULL, 10)); + pwr_pa = (os_strtoul(argv[arg_id + 4], NULL, 10)); + arg_cnt -= 3; + arg_id += 3; + os_printf("save pwr: rate:%d, ch:%d, gain:%d, unused:%d\r\n", + rate, channel, pwr_mod, pwr_pa); + + if(channel == 1) + { + // set flag0 for rfcali mode + manual_cal_set_setp0(); + } + + manual_cal_save_txpwr(rate, channel, pwr_mod); + return 0; + } +#endif + + case 'e': { // 0: exit TXEVM, 1: reboot -enter 2: do fitting + UINT32 op = os_strtoul(argv[arg_id + 1], NULL, 10); + if(op < TXEVM_E_MAX) { + if(op == TXEVM_E_STOP){ + if (g_single_carrier) + { +#if (CFG_SOC_NAME == SOC_BK7231N) + os_printf("pwr_gain:0x%x\r\n", 0x200); + REG_WRITE((RC_BEKEN_BASE + (0x43 * 4)), 0x200); +#endif + g_single_carrier= 0; + } + evm_stop_bypass_mac(); +#if (CFG_SOC_NAME == SOC_BK7231N) + rwnx_cal_dis_extra_txpa(); + REG_WRITE((REG_MDM_CFG_BASE_ADDR + 0xC00 * 4), REG_READ(REG_MDM_CFG_BASE_ADDR + 0xC00 * 4) & (~0x1)); +#endif + } + #if CFG_SUPPORT_MANUAL_CALI + else if(op == TXEVM_E_DOFITTING) { + + // set flag1 for rfcali mode + manual_cal_set_setp1(); + + #if ((CFG_SOC_NAME == SOC_BK7231U) || (CFG_SOC_NAME == SOC_BK7231N)) + manual_cal_11b_2_ble(); + #endif + manual_cal_fitting_txpwr_tab(); + manual_cal_save_chipinfo_tab_to_flash(); + manual_cal_save_txpwr_tab_to_flash(); + + manual_cal_save_cailmain_tx_tab_to_flash(); + manual_cal_save_cailmain_rx_tab_to_flash(); + // g_xcali might mismatch with g_xtal, need reload from flash since iTest would send "txevm -g 7" + manual_cal_load_xtal_tag_flash(); + } + else if(op == TXEVM_E_CLR_OPT){ + manual_cal_clear_otp_flash(); + } + else if(op == TXEVM_E_SET_RFCALI_STATUS){ // txevm -e 4 X + if(argc == 4) + { + reg = os_strtoul(argv[arg_id + 2], NULL, 10); + if(manual_cal_set_rfcali_status_inflash(reg) != 1) + { + os_printf("%d-fail\r\n", reg); + } + else + { + os_printf("%d-ok\r\n", reg); + } + } + } + #endif + else { + #if ATE_APP_FUN + if(get_ate_mode_state()) + os_printf("RF ATE mode!!!\r\n"); + else + os_printf("Normal mode!!!\r\n"); + #endif + + #if CFG_USE_TEMPERATURE_DETECT + temp_detect_uninit(); + #endif + } + return 0; + } else { + return -1; + } + } + break; + +#if (CFG_SOC_NAME != SOC_BK7231) + case 'q': { // lpfcapcal i&q + lpfcapcal_i = (os_strtoul(argv[arg_id + 1], NULL, 10)); + lpfcapcal_q = (os_strtoul(argv[arg_id + 2], NULL, 10)); + arg_cnt -= 1; + arg_id += 1; + os_printf("set lpfcapcal: I:%d, Q:%d\r\n", lpfcapcal_i, lpfcapcal_q); + manual_cal_set_lpf_iq(lpfcapcal_i, lpfcapcal_q); + return 0; + } + + case 'x': { // xtal_cali + xtal = os_strtoul(argv[arg_id + 1], NULL, 10); + os_printf("xtal_cali:%d\r\n", xtal); + manual_cal_set_xtal(xtal); + return 0; + } +#endif // (CFG_SOC_NAME != SOC_BK7231) + case 'o': { + is_ble_test = 1; + ble_test = os_strtoul(argv[arg_id + 1], NULL, 10); // 1:start 0:stop + } + break; + + case 'a': { // tx pkt delay + txdelay = os_strtoul(argv[arg_id + 1], NULL, 10); + } + break; + + default: + fail = 1; + break; + } + } + break; + + default: + fail = 1; + break; + } + + if(fail) + { + return 1; + } + + arg_id += 2; + } + + /*step1, parameter check*/ + if(!(((1 == mode) + || (0 == mode) + || (2 == mode)) + && ((1 == bandwidth) + || (0 == bandwidth)) + && (modul_format <= 3) + && (guard_i_tpye <= 1) + && ((1 <= channel) + && (14 >= channel)) + && ((0 <= packet_len) + && (4095 >= packet_len)) + && ((1 == rate) + || (2 == rate) + || (5 == rate) + || (6 == rate) + || (9 == rate) + || (11 == rate) + || (12 == rate) + || (18 == rate) + || (24 == rate) + || (36 == rate) + || (48 == rate) + || (54 == rate) + || (128 == rate) // MCS0 + || (129 == rate) + || (130 == rate) + || (131 == rate) // MCS3 + || (132 == rate) + || (133 == rate) + || (134 == rate) + || (135 == rate)))) // MCS7 + { + return 1; + } + + gtest_mode = test_mode; + + /*step2, handle*/ + if(!is_ble_test) + { +#if (CFG_SOC_NAME != SOC_BK7231N) + if(bandwidth == 0) + { + reg = 3; + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_SET_VDD_VALUE, ®); + } + else + { + reg = 4; + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_SET_VDD_VALUE, ®); + } + + rwnx_cal_set_reg_adda_ldo(1); +#endif + + if(mode == EVM_DEFUALT_MODE) + { + rwnx_no_use_tpc_set_pwr(); + + mdm_scramblerctrl_set(0x83); //change from 0x85 to 0x83 by cunliang + + if(rate <= 54) { + modul_format = 0; + } + + if(packet_len != 0) + { + evm_bypass_mac_set_tx_data_length(modul_format, packet_len, rate, bandwidth, 0); + } + else if ((rate <= 5) || (rate == 11)) + { + evm_bypass_mac_set_tx_data_length(modul_format, EVM_DEFUALT_B_PACKET_LEN, rate, bandwidth, 1); + packet_len = EVM_DEFUALT_B_PACKET_LEN; + } + else + { + evm_bypass_mac_set_tx_data_length(modul_format, EVM_DEFUALT_PACKET_LEN, rate, bandwidth, 1); + packet_len = EVM_DEFUALT_PACKET_LEN; + } + + evm_bypass_mac_set_rate_mformat(rate, modul_format); + evm_bypass_mac_set_channel(channel); + evm_set_bandwidth(bandwidth); + evm_bypass_mac_set_guard_i_type(guard_i_tpye); + + evm_bypass_mac_test(); + + rwnx_cal_en_extra_txpa(); + +#if CFG_SUPPORT_CALIBRATION + CHECK_OPERATE_RF_REG_IF_IN_SLEEP(); + rwnx_cal_set_txpwr_by_rate(evm_translate_tx_rate(rate), test_mode); + CHECK_OPERATE_RF_REG_IF_IN_SLEEP_END(); +#endif + //evm_bypass_mac_set_txdelay(txdelay); + + evm_start_bypass_mac(); + + if(g_rate == EVM_DEFUALT_B_RATE) + { + single_carrier_type = SINGLE_CARRIER_11B; + } + else + { + single_carrier_type = SINGLE_CARRIER_11G; + } + //if (g_single_carrier != single_carrier) + { + g_single_carrier = single_carrier; +#if (CFG_SOC_NAME == SOC_BK7231N) + if (single_carrier) + { + UINT32 pwr_gain = REG_READ(RCB_POWER_TABLE_ADDR + (0x34 * 4)); + os_printf("pwr_gain:0x%x\r\n", pwr_gain & 0x3FF); + REG_WRITE((RC_BEKEN_BASE + (0x43 * 4)), pwr_gain & 0x3FF); + } + else + { + os_printf("pwr_gain:0x%x\r\n", 0x200); + REG_WRITE((RC_BEKEN_BASE + (0x43 * 4)), 0x200); + } +#endif + } + if(single_carrier) + { + evm_bypass_set_single_carrier(single_carrier_type, rate); + } + + if(trigger_pll) { + os_printf("cal dpll and open int\r\n"); + sctrl_cali_dpll(0); + sctrl_dpll_int_open(); + } + if (test_mode) + { +#if 0 + if(bandwidth == 0) + { + if ((1 == rate)||(6 == rate)||(128 == rate)) + { + mpb_set_txdelay(10); + } + else + { + mpb_set_txdelay(240); + } + } + else + { + if (128 == rate) + { + mpb_set_txdelay(5); + } + else + { + mpb_set_txdelay(120); + } + } +#else + uint32_t duty_in_us; + if (rate < 128) + { + /* long preamble always on since MSB of verctor4 in macbypass */ + duty_in_us = hal_machw_frame_duration(bandwidth, FMOD_NON_HT, evm_translate_tx_rate(rate), 1, guard_i_tpye, packet_len); + } + else + { + duty_in_us = hal_machw_frame_duration(bandwidth, FMOD_HT_MF, rate - 128, 1, guard_i_tpye, packet_len); + } + /* keep duty cycle 99% */ + mpb_set_txdelay_precision((float)duty_in_us / 99); +#endif + } + else + { + uint32_t duty_in_us; + if (rate < 128) + { + /* long preamble always on since MSB of verctor4 in macbypass */ + duty_in_us = hal_machw_frame_duration(bandwidth, FMOD_NON_HT, evm_translate_tx_rate(rate), 1, guard_i_tpye, packet_len); + } + else + { + duty_in_us = hal_machw_frame_duration(bandwidth, FMOD_HT_MF, rate - 128, 1, guard_i_tpye, packet_len); + } + /* keep duty cycle 10% */ + mpb_set_txdelay(duty_in_us * 9); + } + } + + else if(mode == EVM_VIAMAC_TPC_MODE) + { + #if (CFG_SOC_NAME != SOC_BK7231) + UINT32 h_rate = evm_translate_tx_rate(rate), txpwr; + + evm_stop_bypass_mac(); + + rwnx_use_tpc_set_pwr(); + + evm_via_mac_set_bandwidth(bandwidth); + evm_via_mac_set_channel(channel); + evm_via_mac_init(); + + evm_via_mac_set_rate((HW_RATE_E)h_rate, modul_format, guard_i_tpye); + + rwnx_cal_en_extra_txpa(); + txpwr = rwnx_tpc_get_pwridx_by_rate(h_rate, 1); + evm_via_mac_set_power(txpwr); + + evm_via_mac_begin(); + #endif + } + else if(mode == EVM_VIAMAC_NOTPC_MODE) + { + UINT32 h_rate = evm_translate_tx_rate(rate); + + evm_stop_bypass_mac(); + + rwnx_no_use_tpc_set_pwr(); + + evm_via_mac_set_bandwidth(bandwidth); + evm_via_mac_set_channel(channel); + evm_via_mac_init(); + + evm_via_mac_set_rate((HW_RATE_E)h_rate, modul_format, guard_i_tpye); + +#if CFG_SUPPORT_CALIBRATION + CHECK_OPERATE_RF_REG_IF_IN_SLEEP(); + rwnx_cal_set_txpwr_by_rate(evm_translate_tx_rate(rate), test_mode); + CHECK_OPERATE_RF_REG_IF_IN_SLEEP_END(); +#endif + evm_via_mac_begin(); + } + + gmode = mode; + } + else + { + #if (CFG_SOC_NAME != SOC_BK7231) + if(ble_test) + { + //os_printf("ble_test\r\n"); + single_carrier_type = SINGLE_CARRIER_BLE; + + rwnx_cal_set_txpwr(ble_pwr_mod, 11); + evm_bypass_ble_test_start(ble_channel); + g_single_carrier = single_carrier; + if(single_carrier) + evm_bypass_set_single_carrier(single_carrier_type, rate); + } + else + { + evm_bypass_ble_test_stop(); + } + #endif + } + +#endif // CFG_TX_EVM_TEST + + (void)txdelay; + + return 0; +} + +// eof + diff --git a/beken_os/beken378/func/uart_debug/cmd_evm.h b/beken_os/beken378/func/uart_debug/cmd_evm.h new file mode 100755 index 0000000..43cf208 --- /dev/null +++ b/beken_os/beken378/func/uart_debug/cmd_evm.h @@ -0,0 +1,42 @@ +#ifndef _CMD_EVM_H_ +#define _CMD_EVM_H_ + +#include "command_table.h" + +extern int do_evm(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]); + +#define CMD_EVM_MAXARG 10 + +#define EVM_DEFUALT_MODE (1) +#define EVM_VIAMAC_TPC_MODE (0) +#define EVM_VIAMAC_NOTPC_MODE (2) +#define EVM_DEFUALT_PACKET_LEN (1024)//(500) +#define EVM_DEFUALT_B_PACKET_LEN (1024)//(100) +#define EVM_DEFUALT_RATE (54) +#define EVM_DEFUALT_B_RATE (11) +#define EVM_DEFUALT_BLE_RATE (158) +#define EVM_DEFUALT_CHANNEL (6) +#define EVM_DEFUALT_BLE_CHANNEL (2402) +#define EVM_DEFUALT_BW (0) +#define EVM_DEFUALT_PWR_MOD (2) +#define EVM_DEFUALT_BLE_PWR_MOD (4) +#define EVM_DEFUALT_PWR_PA (8) +#define EVM_DEFUALT_MODUL_FORMAT (0) +#define EVM_DEFUALT_GI_TYPE (0) +#define EVM_DEFUALT_SINGLE_CARRIER (0) + + +#define ENTRY_CMD_EVM \ + ENTRY_CMD(txevm, \ + CMD_EVM_MAXARG, \ + 1, \ + do_evm, \ + "txevm [-m mode] [-c channel] [-l packet-length] [-r physical-rate]\r\n", \ + "Options:\r\n"\ + " -m mode: 1,0 1: tx packet bypass mac, 0: via mac\r\n"\ + " -c channel: 1,2,...,14 channel number\r\n"\ + " -l packet-length: 0--4095 legacy:0--4095 ht:0--65535 vht:0--1048575\r\n"\ + " -r ppdu-rate: 1,2,5,6,9,11,12,18,24,36,48,54 Mbps\r\n"\ + ) + +#endif // _CMD_EVM_H_ diff --git a/beken_os/beken378/func/uart_debug/cmd_help.c b/beken_os/beken378/func/uart_debug/cmd_help.c new file mode 100755 index 0000000..c9232d5 --- /dev/null +++ b/beken_os/beken378/func/uart_debug/cmd_help.c @@ -0,0 +1,100 @@ +#include "include.h" +#include "cmd_help.h" +#include "mem_pub.h" +#include "str_pub.h" +#include "uart_pub.h" +#include "command_line.h" + +int _do_help(cmd_tbl_t *cmd_start, int cmd_items, cmd_tbl_t *cmdtp, int flag, + int argc, char *const argv[]) +{ + int i; + int rcode = 0; + + if (argc == 1) /* show list of commands */ + { + cmd_tbl_t *cmd_array[COMMAND_MAX_COUNT]; + int i, j, swaps; + + /* Make array of commands from .uboot_cmd section */ + cmdtp = cmd_start; + for (i = 0; i < cmd_items; i++) + { + cmd_array[i] = cmdtp++; + } + + /* Sort command list (trivial bubble sort) */ + for (i = cmd_items - 1; i > 0; --i) + { + swaps = 0; + for (j = 0; j < i; ++j) + { + if (os_strcmp(cmd_array[j]->name, + cmd_array[j + 1]->name) > 0) + { + cmd_tbl_t *tmp; + tmp = cmd_array[j]; + cmd_array[j] = cmd_array[j + 1]; + cmd_array[j + 1] = tmp; + ++swaps; + } + } + if (!swaps) + break; + } + + /* print short help (usage) */ + for (i = 0; i < cmd_items; i++) + { + const char *usage = cmd_array[i]->usage; + + /* allow user abort */ + + if (usage == NULL) + continue; + + os_printf("%-*s- %s\n", CONFIG_SYS_HELP_CMD_WIDTH, + cmd_array[i]->name, usage); + } + return 0; + } + + /* + * command help (long version) + */ + for (i = 1; i < argc; ++i) + { + cmdtp = cmd_find_tbl(argv[i], cmd_start, cmd_items); + if (cmdtp != NULL) + { + rcode |= cmd_usage(cmdtp); + } + else + { + os_printf("Unknown command '%s' - try 'help' without arguments for list of all known commands\n\n", + argv[i]); + rcode = 1; + } + } + return rcode; +} + + +/* + * Use puts() instead of os_printf() to avoid os_printf buffer overflow + * for long help messages + */ +int do_help(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ +#if CFG_UART_DEBUG + cmd_tbl_t *start = entry_get_start(); + const int len = entry_get_count(); + + return _do_help(start, len, cmdtp, flag, argc, argv); +#else + return 0; +#endif +} + +// eof + diff --git a/beken_os/beken378/func/uart_debug/cmd_help.h b/beken_os/beken378/func/uart_debug/cmd_help.h new file mode 100755 index 0000000..ed5b670 --- /dev/null +++ b/beken_os/beken378/func/uart_debug/cmd_help.h @@ -0,0 +1,25 @@ +#ifndef _CMD_HELP_H_ +#define _CMD_HELP_H_ + +#include "command_table.h" + +extern int do_help(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]); + +#define CMD_HELP_MAXARG 4 +#define CONFIG_SYS_HELP_CMD_WIDTH 8 + +#define ENTRY_CMD_HELP \ + ENTRY_CMD(help, \ + CMD_HELP_MAXARG, \ + 1, \ + do_help, \ + "print command description/usage\r\n",\ + "\r\n"\ + " - print brief description of all commands\r\n"\ + "help command ...\r\n"\ + " - print detailed usage of 'command'"\ + "\r\n") + +#endif // _CMD_HELP_H_ +// eof + diff --git a/beken_os/beken378/func/uart_debug/cmd_reg.c b/beken_os/beken378/func/uart_debug/cmd_reg.c new file mode 100755 index 0000000..660c5e6 --- /dev/null +++ b/beken_os/beken378/func/uart_debug/cmd_reg.c @@ -0,0 +1,131 @@ +#include "include.h" +#include "uart_debug_pub.h" +#include "cmd_reg.h" +#include "mem_pub.h" +#include "str_pub.h" +#include "arm_arch.h" + +int do_reg(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ + char cmd0 = 0; + char cmd1 = 0; + char cmd2 = 0; + UINT8 fail = 0; + UINT32 i; + UINT32 arg_id = 1; + UINT32 arg_cnt = argc; + UINT32 regr[REG_RD_MAX_CNT] = {0}; + UINT32 regr_cnt = 0; + UINT32 regw = 0; + UINT32 regw_value = 0; + + /*step0, parameter conversion*/ + arg_cnt -= 1; /* CmdWord*/ + + while(arg_cnt > 0) + { + cmd0 = argv[arg_id][0]; + cmd1 = argv[arg_id][1]; + + switch(cmd0) + { + case '-': + { + arg_cnt -= 1; /* ''-'' */ + + switch(cmd1) + { + case 'r': + if(arg_cnt < 1) + { + fail = 1; + break; + } + + while(1) + { + if((regr_cnt >= REG_RD_MAX_CNT) + || (0 == arg_cnt)) + { + break; + } + + cmd2 = argv[arg_id + 1][0]; + if('-' == cmd2) + { + break; + } + + regr[regr_cnt ++] = os_strtoul(argv[arg_id + 1], NULL, 16); + arg_id += 1; + arg_cnt -= 1; + } + + break; + + case 'w': + if(arg_cnt < 2) + { + fail = 1; + break; + } + + regw = os_strtoul(argv[arg_id + 1], NULL, 16); + regw_value = os_strtoul(argv[arg_id + 2], NULL, 0); + + arg_cnt -= 2; + arg_id += 2; + break; + + default: + fail = 1; + break; + } + } + break; + + default: + fail = 1; + break; + } + + if(fail) + { + goto fail_exit; + } + } + + /*step1, parameter check*/ + if(regw & REG_MASK) + { + goto fail_exit; + } + + for(i = 0; i < regr_cnt; i ++) + { + if(regr[i] & REG_MASK) + { + goto fail_exit; + } + } + + /*step2, handle*/ + if(regw) + { + REG_WRITE(regw, regw_value); + CREG_PRT(" write register: 0x%x, value: 0x%x\r\n", regw, regw_value); + } + + for(i = 0; i < regr_cnt; i ++) + { + CREG_PRT(" read register: 0x%x, value: 0x%x\r\n", regr[i], REG_READ(regr[i])); + } + + return 0; + +fail_exit: + return 1; +} + +// eof + diff --git a/beken_os/beken378/func/uart_debug/cmd_reg.h b/beken_os/beken378/func/uart_debug/cmd_reg.h new file mode 100755 index 0000000..1a71f59 --- /dev/null +++ b/beken_os/beken378/func/uart_debug/cmd_reg.h @@ -0,0 +1,38 @@ +#ifndef _CMD_REG_H_ +#define _CMD_REG_H_ + +#include "command_table.h" + +#define REG_RD_MAX_CNT 4 +#define REG_MASK 3 + +#define CREG_DEBUG + +#ifdef CREG_DEBUG +#define CREG_PRT os_printf +#define CREG_WPRT warning_prf +#else +#define CREG_PRT os_null_printf +#define CREG_WPRT os_null_printf +#endif + +extern int do_reg(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]); + +#define CMD_REG_MAXARG 6 + +#define ENTRY_CMD_REG \ + ENTRY_CMD(reg, \ + CMD_REG_MAXARG, \ + 1, \ + do_reg, \ + "reg [-r register register...] [-w register value]\r\n",\ + "\r\n"\ + " read register, or write register\r\n"\ + "Options:\r\n"\ + " -r register register... register: hex\r\n"\ + " -w register value register: hex, value: hex\r\n"\ + "\r\n") + +#endif // _CMD_REG_H_ +// eof + diff --git a/beken_os/beken378/func/uart_debug/cmd_rx_sensitivity.c b/beken_os/beken378/func/uart_debug/cmd_rx_sensitivity.c new file mode 100755 index 0000000..e2641ee --- /dev/null +++ b/beken_os/beken378/func/uart_debug/cmd_rx_sensitivity.c @@ -0,0 +1,460 @@ +#include "include.h" +#include "cmd_rx_sensitivity.h" +#include "mem_pub.h" +#include "str_pub.h" +#include "rx_sensitivity_pub.h" +#include "fake_clock_pub.h" +#include "uart_debug_pub.h" +#include "schedule_pub.h" +#include "rtos_pub.h" +#include "rtos_error.h" +#include "sys_ctrl_pub.h" +#include "drv_model_pub.h" +#include "bk7011_cal_pub.h" +#include "reg_mdm_cfg.h" +#include "bk7231N_cal.h" +#include "arm_arch.h" + +#if CFG_RX_SENSITIVITY_TEST +beken_timer_t rx_sens_tmr = {0}; +beken_timer_t rx_sens_ble_tmr = {0}; +#endif + +UINT32 g_rxsens_start = 0; + +extern void bk7011_max_rxsens_setting(void); +extern void bk7011_normal_rxsens_setting(void); + +int bk7011_reduce_vdddig_for_rx(int reduce) +{ + static UINT32 default_vdddig = 0; + UINT32 new_vdddig; + if (!default_vdddig) + { + default_vdddig = sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_GET_VDD_VALUE, NULL); + if (!default_vdddig) + { + return -1; + } + } + if (reduce) + { + new_vdddig = default_vdddig - 1; + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_SET_VDD_VALUE, (void *)&new_vdddig); + } + else + { + /* recover vdddig */ + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_SET_VDD_VALUE, (void *)&default_vdddig); + } + + return 0; +} + +void rxsens_ct_hdl(void *param) +{ +#if CFG_RX_SENSITIVITY_TEST + OSStatus err; + rx_get_rx_result_end(); + rx_get_rx_result_begin(); + + if(rx_sens_tmr.handle != NULL) { + err = rtos_reload_timer(&rx_sens_tmr); + ASSERT(kNoErr == err); + } +#endif // CFG_RX_SENSITIVITY_TEST +} + +void rxsens_ble_ct_hdl(void *param) +{ +#if CFG_RX_SENSITIVITY_TEST + OSStatus err; + rx_get_ble_rx_result(); + if(rx_sens_ble_tmr.handle != NULL) { + err = rtos_reload_timer(&rx_sens_ble_tmr); + ASSERT(kNoErr == err); + } +#endif +} + +void rxsens_ct_show_hdl(void *param) +{ +#if CFG_RX_SENSITIVITY_TEST + rx_get_rx_result_end(); +#endif // CFG_RX_SENSITIVITY_TEST +} + +int do_rx_sensitivity(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ + char cmd0 = 0; + char cmd1 = 0; + UINT8 fail = 0; + + UINT32 mode = RXSENS_DEFUALT_MODE; + UINT32 duration = RXSENS_DEFUALT_DURATION; + UINT32 channel = RXSENS_DEFUALT_CHANNEL; + UINT32 ble_channel = RXSENS_DEFUALT_BLE_CHANNEL; + UINT32 is_ble_test = 0;; + UINT32 ble_test = 0; + +#if CFG_RX_SENSITIVITY_TEST + OSStatus err; + UINT8 ret; + /// UINT32 reg; +#endif + + UINT32 arg_id = 1; + UINT32 arg_cnt = argc; + +#if CFG_RX_SENSITIVITY_TEST + uint32_t t_ms = 0; +#endif + + /*step0, parameter conversion*/ + while(arg_cnt > 1) + { + if(arg_cnt > 1) + { + cmd0 = argv[arg_id][0]; + cmd1 = argv[arg_id][1]; + } + + switch(cmd0) + { + case '-': + { + arg_cnt -= 1; + + if(arg_cnt < 1) + { + fail = 1; + break; + } + + arg_cnt -= 1; + switch(cmd1) + { + case 'b': // bandwidth 0:20M, 1:40M + mode = os_strtoul(argv[arg_id + 1], NULL, 10); + break; + + case 'd': // timer intval + duration = os_strtoul(argv[arg_id + 1], NULL, 10); + break; + + case 'c': // channel + if(is_ble_test) + { + ble_channel = os_strtoul(argv[arg_id + 1], NULL, 10); + } + else + { + channel = os_strtoul(argv[arg_id + 1], NULL, 10); + } + break; + + case 'e': { // 0: exit, 1: enter, 2: stop last rx +#if CFG_RX_SENSITIVITY_TEST + UINT32 op = os_strtoul(argv[arg_id + 1], NULL, 10); + if(op < RXSENS_G_MAX) { + if (op == RXSENS_G_STOP_LASTRX) { +#if (CFG_SOC_NAME == SOC_BK7231N) + /* recover MDM_REG202<23>=0 */ + mdm_cpemode_setf(0); + /* recover MDM_REG206<17:16>=0 */ + mdm_cfgsmooth_setf(0); + /* recover TRX_REG12<8:7>=3 */ + rwnx_cal_set_reg_adda_ldo(3); + /* recover rx filter */ + rwnx_cal_en_rx_filter_offset(); + bk7011_reduce_vdddig_for_rx(0); + /* recover TRX_REG9<22>=0 for band20 */ + rwnx_cal_set_bw_i2v(0); +#endif + g_rxsens_start = 0; + if(rx_sens_tmr.handle != NULL) { + err = rtos_deinit_timer(&rx_sens_tmr); + ASSERT(kNoErr == err); + rx_sens_tmr.handle = NULL; + } + } else { +#if (CFG_SOC_NAME == SOC_BK7231N) + /* set TRX_REG12<8:7>=2 for rx */ + rwnx_cal_set_reg_adda_ldo(2); + rwnx_cal_dis_rx_filter_offset(); +#endif + } + return 0; + } else { + return -1; + } +#endif + } + + case 's': { // start / stop +#if CFG_RX_SENSITIVITY_TEST + if(!is_ble_test) + { + UINT32 sta = os_strtoul(argv[arg_id + 1], NULL, 10); + if(sta) { + rx_clean_rx_statistic_result(); + } + else { + rx_get_rx_result_end(); + } + } + else + { + UINT32 sta = os_strtoul(argv[arg_id + 1], NULL, 10); + if(sta) + { + rx_start_ble_rx_counting(); + } + else + { + rx_get_ble_rx_result(); + } + } +#endif + return 0; + } + + case 'g': { // get statistic 0: clean, 1:20M, 2:40M + #if CFG_RX_SENSITIVITY_TEST + if(!is_ble_test) + { + UINT32 g_type = os_strtoul(argv[arg_id + 1], NULL, 10); + if(g_type < RXSENS_RTYPTE_MAX ) + { + if(g_type == RXSENS_RTYPTE_CLEAN) { + rx_clean_rx_statistic_result(); + } + else if(g_type == RXSENS_RTYPTE_20M) { + rx_get_rx20M_statistic_result(); + } + + else if(g_type == RXSENS_RTYPTE_40M){ + rx_get_rx40M_statistic_result(); + } + else if(g_type == RXSENS_RTYPTE_SIG_RES){ + rxsens_ct_hdl(NULL); + } + return 0; + } else + return -1; + } + else + { + UINT32 g_type = os_strtoul(argv[arg_id + 1], NULL, 10); + if(g_type == RXSENS_RTYPTE_CLEAN) + { + rx_clean_ble_rx_result(); + return 0; + } + else + { + return -1; + } + } +#endif + } + + case 'o': { + is_ble_test = 1; + ble_test = os_strtoul(argv[arg_id + 1], NULL, 10); // 1:start 0:stop + } + break; + + default: + fail = 1; + break; + } + } + break; + + default: + fail = 1; + break; + } + + if(fail) + { + return 1; + } + + arg_id += 2; + } + + /*step1, parameter check*/ + if(!((0 < channel) + || (14 > channel))) + { + return 1; + } + + if(!((0 < ble_channel) + || (40 > ble_channel))) + { + return 1; + } + + if((mode != 1) && (mode != 0) ) + { + return 1; + } + + /*step2, handle*/ +#if CFG_RX_SENSITIVITY_TEST + + if(!is_ble_test) + { + ret = rs_set_mode(mode); + if(ret) + { + return 1; + } + + ret = rs_set_channel(channel); + if(ret) + { + return 1; + } + + //sys_ctrl_0x42[6:4]=SCTRL_DIGTAL_VDD=4 +#if (CFG_SOC_NAME == SOC_BK7231N) + if(mode == 0) + { + /* set MDM_REG206<17:16>=3 for band20 */ + mdm_cfgsmooth_setf(3); + bk7011_reduce_vdddig_for_rx(1); + /* recover TRX_REG9<22>=0 for band20 */ + rwnx_cal_set_bw_i2v(0); + } + else + { + /* set MDM_REG206<17:16>=1 for band40 */ + mdm_cfgsmooth_setf(1); + bk7011_reduce_vdddig_for_rx(0); + /* set TRX_REG9<22>=1 for band40 */ + rwnx_cal_set_bw_i2v(1); + } +#else + if(mode == 0) + { + reg = 3; + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_SET_VDD_VALUE, ®); + } + else + { + reg = 5; + sddev_control(SCTRL_DEV_NAME, CMD_SCTRL_SET_VDD_VALUE, ®); + } +#endif + + rs_test(); + +#if (CFG_SOC_NAME == SOC_BK7231N) + extern void phy_enable_lsig_intr(void); + phy_enable_lsig_intr(); + /* set MDM_REG202<23>=1 for rx */ + mdm_cpemode_setf(1); +#else + if((channel == 13) ||(channel == 14)) + rwnx_cal_set_reg_adda_ldo(0); + else + rwnx_cal_set_reg_adda_ldo(3); + + rwnx_cal_set_reg_rx_ldo(); + bk7011_max_rxsens_setting(); + rwnx_cal_dis_extra_txpa(); + + if(mode == 1) + { + if((channel >= 3) && (channel <= 10)) + rwnx_cal_set_40M_extra_setting(1); + else + rwnx_cal_set_40M_extra_setting(0); + } + else + rwnx_cal_set_40M_extra_setting(0); +#endif + + g_rxsens_start = 1; + + if(duration) { + rx_get_rx_result_begin(); + //t_ms = fclk_from_sec_to_tick(duration); + t_ms = duration * 1000; + + if(rx_sens_tmr.handle != NULL) { + err = rtos_deinit_timer(&rx_sens_tmr); + ASSERT(kNoErr == err); + rx_sens_tmr.handle = NULL; + } + + err = rtos_init_timer(&rx_sens_tmr, + t_ms, + rxsens_ct_hdl, + (void *)0); + ASSERT(kNoErr == err); + err = rtos_start_timer(&rx_sens_tmr); + ASSERT(kNoErr == err); + } else { + if(rx_sens_tmr.handle != NULL) { + err = rtos_deinit_timer(&rx_sens_tmr); + ASSERT(kNoErr == err); + rx_sens_tmr.handle = NULL; + } + } + } + else + { + if(ble_test) + { + os_printf("ble_test\r\n"); + //rwnx_cal_set_txpwr(ble_pwr_mod, 11); + rs_ble_test_start(ble_channel); + if(duration) { + //t_ms = fclk_from_sec_to_tick(duration); + t_ms = duration * 1000; + + if(rx_sens_ble_tmr.handle != NULL) { + err = rtos_deinit_timer(&rx_sens_ble_tmr); + ASSERT(kNoErr == err); + rx_sens_ble_tmr.handle = NULL; + } + + err = rtos_init_timer(&rx_sens_ble_tmr, + t_ms, + rxsens_ble_ct_hdl, + (void *)0); + ASSERT(kNoErr == err); + err = rtos_start_timer(&rx_sens_ble_tmr); + ASSERT(kNoErr == err); + } else { + if(rx_sens_ble_tmr.handle != NULL) { + err = rtos_deinit_timer(&rx_sens_ble_tmr); + ASSERT(kNoErr == err); + rx_sens_ble_tmr.handle = NULL; + } + } + } + else + { + if(rx_sens_ble_tmr.handle != NULL) { + err = rtos_deinit_timer(&rx_sens_ble_tmr); + ASSERT(kNoErr == err); + rx_sens_ble_tmr.handle = NULL; + } + rs_ble_test_stop(); + } + } + + +#endif // CFG_RX_SENSITIVITY_TEST + + return 0; +} + +// eof + diff --git a/beken_os/beken378/func/uart_debug/cmd_rx_sensitivity.h b/beken_os/beken378/func/uart_debug/cmd_rx_sensitivity.h new file mode 100755 index 0000000..98f046b --- /dev/null +++ b/beken_os/beken378/func/uart_debug/cmd_rx_sensitivity.h @@ -0,0 +1,44 @@ +#ifndef _CMD_RX_SENSITIVITY_H_ +#define _CMD_RX_SENSITIVITY_H_ + +#include "command_table.h" + +typedef enum { + RXSENS_RTYPTE_CLEAN = 0, + RXSENS_RTYPTE_20M = 1, + RXSENS_RTYPTE_40M = 2, + RXSENS_RTYPTE_SIG_RES = 3, + RXSENS_RTYPTE_MAX +} RXSENS_RESULT_TYPE; + +typedef enum { + RXSENS_G_STOP_LASTRX = 0, + RXSENS_G_REBOOT = 1, + RXSENS_G_STOP_TIME = 2, + RXSENS_G_MAX +} RXSENS_G_TYPE; + +extern int do_rx_sensitivity(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]); + +#define CMD_RX_SENSITIVITY_MAXARG (8) +#define RXSENS_DEFUALT_MODE (0) +#define RXSENS_DEFUALT_DURATION (0) +#define RXSENS_DEFUALT_CHANNEL (6) +#define RXSENS_DEFUALT_BLE_CHANNEL (2) + + +#define ENTRY_CMD_RX_SENSITIVITY \ + ENTRY_CMD(rxsens, \ + CMD_RX_SENSITIVITY_MAXARG, \ + 1, \ + do_rx_sensitivity, \ + "rxsens [-m mode] [-d duration] [-c channel] [-l lost]\r\n" \ + " test rx sensitivity, and get statistic result about fcs, per and so on\r\n", \ + "Options:\r\n" \ + " -m mode 0:PHY_CHNL_BW_20 1:PHY_CHNL_BW_40 \r\n"\ + " -d duration duration: n second\r\n"\ + " -c channel: 1,2,...,14 channel number\r\n"\ + " -l don't show rxsens log any more\r\n"\ + "\r\n") + +#endif // _CMD_RX_SENSITIVITY_H_ diff --git a/beken_os/beken378/func/uart_debug/command_line.c b/beken_os/beken378/func/uart_debug/command_line.c new file mode 100755 index 0000000..f7667f3 --- /dev/null +++ b/beken_os/beken378/func/uart_debug/command_line.c @@ -0,0 +1,785 @@ +#include "include.h" +#include "command_line.h" +#include "command_table.h" +#include "str_pub.h" +#include "uart_pub.h" +#include "mem_pub.h" +#if CFG_SUPPORT_ALIOS +#include "hal/soc/soc.h" +#else +#include "BkDriverFlash.h" +#endif +#include "wlan_ui_pub.h" +#include "ate_app.h" + +#if CFG_UART_DEBUG +/* find command table entry for a command */ +cmd_tbl_t *cmd_find_tbl(const char *cmd, cmd_tbl_t *table, int table_len) +{ + cmd_tbl_t *cmdtp; + cmd_tbl_t *cmdtp_temp = table; /* Init value */ + const char *p; + int len; + int n_found = 0; + + if (!cmd) + return NULL; + /* + * Some commands allow length modifiers (like "cp.b"); + * compare command name only until first dot. + */ + len = ((p = os_strchr(cmd, '.')) == NULL) ? os_strlen (cmd) : (p - cmd); + + for (cmdtp = table; cmdtp != table + table_len; cmdtp++) + { + if (os_strncmp(cmd, cmdtp->name, len) == 0) + { + if (len == os_strlen(cmdtp->name)) + return cmdtp; /* full match */ + + cmdtp_temp = cmdtp; /* abbreviated command ? */ + n_found++; + } + } + if (n_found == 1) /* exactly one match */ + { + return cmdtp_temp; + } + + return NULL; /* not found or ambiguous command */ +} + +cmd_tbl_t *cmd_find(const char *cmd) +{ + cmd_tbl_t *start = entry_get_start(); + const int len = entry_get_count(); + + return cmd_find_tbl(cmd, start, len); +} + +int cmd_usage(const cmd_tbl_t *cmdtp) +{ + CLI_PRT("%s\r\n", cmdtp->usage); + +#ifdef CONFIG_SYS_LONGHELP + if (!cmdtp->help) + { + CLI_PRT ("- No additional help available.\n"); + return 1; + } + + CLI_PRT(cmdtp->help); + CLI_PRT("\r\n"); +#endif /* CONFIG_SYS_LONGHELP */ + + return 0; +} + +/** + * Call a command function. This should be the only route in U-Boot to call + * a command, so that we can track whether we are waiting for input or + * executing a command. + * + * @param cmdtp Pointer to the command to execute + * @param flag Some flags normally 0 (see CMD_FLAG_.. above) + * @param argc Number of arguments (arg 0 must be the command text) + * @param argv Arguments + * @return 0 if command succeeded, else non-zero (CMD_RET_...) + */ +static int cmd_call(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]) +{ + int result; + + result = (cmdtp->cmd)(cmdtp, flag, argc, argv); + if (result) + CLI_PRT("Command failed, result=%d\n", result); + + return result; +} + +int cmd_process(int flag, int argc, char *const argv[], + int *repeatable, unsigned int *ticks) +{ + int rc = CMD_RET_SUCCESS; + cmd_tbl_t *cmdtp; + + /* Look up command in command table */ + cmdtp = cmd_find(argv[0]); + if (cmdtp == NULL) + { + CLI_PRT("Unknown command '%s' - try 'help'\n", argv[0]); + return CMD_RET_FAILURE; + } + + if(DEBUG_PARSER) + { + CLI_PRT(" cmd_find\r\n"); + } + + CLI_PRT("\r\n -------------------------------------------------------------------\r\n"); + + /* found - check max args */ + if (argc > cmdtp->maxargs) + rc = CMD_RET_USAGE; + + /* If OK so far, then do the command */ + if (!rc) + { + rc = cmd_call(cmdtp, flag, argc, argv); + + *repeatable &= cmdtp->repeatable; + } + if (rc == CMD_RET_USAGE) + rc = cmd_usage(cmdtp); + + CLI_PRT("\r\n -------------------------------------------------------------------\r\n"); + return rc; +} + +int cmd_parse_line(char *line, char *argv[]) +{ + int nargs = 0; + + while (nargs < CONFIG_SYS_MAXARGS) + { + /* skip any white space */ + while (isblank(*line)) + ++line; + + if (*line == '\0') /* end of line, no more args */ + { + argv[nargs] = NULL; + return nargs; + } + + argv[nargs++] = line; /* begin of argument string */ + + /* find end of string */ + while (*line && !isblank(*line)) + ++line; + + if (*line == '\0') /* end of line, no more args */ + { + argv[nargs] = NULL; + return nargs; + } + + *line++ = '\0'; /* terminate current arg */ + } + + CLI_PRT("** Too many args (max. %d) **\n", CONFIG_SYS_MAXARGS); + + return nargs; +} + +void cmd_process_macros(const char *input, char *output) +{ + char c, prev; + int inputcnt = os_strlen(input); + int outputcnt = CONFIG_SYS_CBSIZE; + int state = 0; /* 0 = waiting for '$' */ + + /* 1 = waiting for '(' or '{' */ + /* 2 = waiting for ')' or '}' */ + /* 3 = waiting for ''' */ + + prev = '\0'; /* previous character */ + + while (inputcnt && outputcnt) + { + c = *input++; + inputcnt--; + + if (state != 3) + { + /* remove one level of escape characters */ + if ((c == '\\') && (prev != '\\')) + { + if (inputcnt-- == 0) + break; + prev = c; + c = *input++; + } + } + + switch (state) + { + case 0: /* Waiting for (unescaped) $ */ + if ((c == '\'') && (prev != '\\')) + { + state = 3; + break; + } + if ((c == '$') && (prev != '\\')) + { + state++; + } + else + { + *(output++) = c; + outputcnt--; + } + break; + case 1: /* Waiting for ( */ + if (c == '(' || c == '{') + { + state++; + } + else + { + state = 0; + *(output++) = '$'; + outputcnt--; + + if (outputcnt) + { + *(output++) = c; + outputcnt--; + } + } + break; + case 2: /* Waiting for ) */ + if (c == ')' || c == '}') + { + char *envval; + /* Varname # of chars */ + + /* Get the varname */ + + /* Get its value */ + envval = 0; // getenv(envname); + + /* Copy into the line if it exists */ + if (envval != NULL) + while ((*envval) && outputcnt) + { + *(output++) = *(envval++); + outputcnt--; + } + /* Look for another '$' */ + state = 0; + } + break; + case 3: /* Waiting for ' */ + if ((c == '\'') && (prev != '\\')) + { + state = 0; + } + else + { + *(output++) = c; + outputcnt--; + } + break; + } + prev = c; + } + + if (outputcnt) + *output = 0; + else + *(output - 1) = 0; +} + + +/* + * Run a command using the selected parser. + * + * @param cmd Command to run + * @param flag Execution flags (CMD_FLAG_...) + * @return 0 on success, or != 0 on error. + */ +int run_command(const char *cmd, int flag) +{ + char cmdbuf[CONFIG_SYS_CBSIZE]; /* working copy of cmd */ + char *token; /* start of token in cmdbuf */ + char *sep; /* end of token (separator) in cmdbuf */ + char finaltoken[CONFIG_SYS_CBSIZE]; + char *str = cmdbuf; + char *argv[CONFIG_SYS_MAXARGS + 1]; /* NULL terminated */ + int argc, inquotes; + int repeatable = 1; + int rc = 0; + + if (DEBUG_PARSER + && (cmd[0])) + { + /* use CLI_PRT - string may be loooong */ + CLI_PRT("run_command: "); + CLI_PRT(cmd ? cmd : "NULL"); + } + + /* forget any previous Control C */ + if (!cmd || !*cmd) + return -1; /* empty command */ + + if (os_strlen(cmd) >= CONFIG_SYS_CBSIZE) + { + CLI_PRT("## Command too long!\n"); + return -1; + } + + os_strcpy(cmdbuf, cmd); + + /* Process separators and check for invalid + * repeatable commands + */ + + while (*str) + { + /* + * Find separator, or string end + * Allow simple escape of ';' by writing "\;" + */ + for (inquotes = 0, sep = str; *sep; sep++) + { + if ((*sep == '\'') && + (*(sep - 1) != '\\')) + inquotes = !inquotes; + + if (!inquotes && + (*sep == ';') && /* separator */ + (sep != str) && /* past string start */ + (*(sep - 1) != '\\')) /* and NOT escaped */ + break; + } + + /* + * Limit the token to data between separators + */ + token = str; + if (*sep) + { + str = sep + 1; /* start of command for next pass */ + *sep = '\0'; + } + else + { + str = sep; /* no more commands for next pass */ + } + + /* find macros in this token and replace them */ + cmd_process_macros(token, finaltoken); + + /* Extract arguments */ + argc = cmd_parse_line(finaltoken, argv); + if (argc == 0) + { + rc = -1; /* no command at all */ + continue; + } + + if (cmd_process(flag, argc, argv, &repeatable, NULL)) + rc = -1; + + /* Did the user stop this? */ + } + + return rc ? rc : repeatable; +} + +#elif CFG_ENABLE_ATE_FEATURE +extern void bk_send_byte(UINT8 uport, UINT8 data); + +void bkreg_tx(HCI_EVENT_PACKET *pHCItxBuf) +{ +#ifndef KEIL_SIMULATOR + char *tmp; + unsigned int i; + unsigned int tx_len = HCI_EVENT_HEAD_LENGTH + pHCItxBuf->total; + + pHCItxBuf->code = TRA_HCIT_EVENT; + pHCItxBuf->event = HCI_COMMAND_COMPLETE_EVENT; + + tmp = (char *)pHCItxBuf; + for(i = 0; i < tx_len; i ++) + { + bk_send_byte(0,tmp[i]);//BK_UART_1 + } +#endif +} + +cmd_tbl_t *cmd_find_tbl(const char *cmd, cmd_tbl_t *table, int table_len) +{ + return 0; +} + +int cmd_usage(const cmd_tbl_t *cmdtp) +{ + return 0; +} +int run_command(const char *cmd, int flag) +{ + return 0; +} + +#if CFG_SUPPORT_BKREG + +#if CFG_USE_TUYA_CCA_TEST +/** + * @name RWNXAGCCCA1 register definitions + *
+ *   Bits           Field Name   Reset Value
+ *  -----   ------------------   -----------
+ *  28:20     INBDCCAPOWMINDBM   0x1B5
+ *  19:12        CCAFALLTHRDBM   0xBF
+ *     09             DISCCAEN   1
+ *     08             SATCCAEN   1
+ *  07:00        CCARISETHRDBM   0xC2
+ * 
+ * + * @{ + */ + +#define AGC_RWNXAGCCCA1_ADDR_dbg (0x01002074) + +#define AGC_INBDCCAPOWMINDBM_MASK_dbg ((UINT32)0x1FF00000) +/// INBDCCAPOWMINDBM field LSB position +#define AGC_INBDCCAPOWMINDBM_LSB_dbg 20 +/// INBDCCAPOWMINDBM field width +#define AGC_INBDCCAPOWMINDBM_WIDTH_dbg ((UINT32)0x00000009) +/// CCAFALLTHRDBM field mask +#define AGC_CCAFALLTHRDBM_MASK_dbg ((UINT32)0x000FF000) +/// CCAFALLTHRDBM field LSB position +#define AGC_CCAFALLTHRDBM_LSB_dbg 12 +/// CCAFALLTHRDBM field width +#define AGC_CCAFALLTHRDBM_WIDTH_dbg ((UINT32)0x00000008) +/// DISCCAEN field bit +#define AGC_DISCCAEN_BIT_dbg ((UINT32)0x00000200) +/// DISCCAEN field position +#define AGC_DISCCAEN_POS_dbg 9 +/// SATCCAEN field bit +#define AGC_SATCCAEN_BIT_dbg ((UINT32)0x00000100) +/// SATCCAEN field position +#define AGC_SATCCAEN_POS_dbg 8 +/// CCARISETHRDBM field mask +#define AGC_CCARISETHRDBM_MASK_dbg ((UINT32)0x000000FF) +/// CCARISETHRDBM field LSB position +#define AGC_CCARISETHRDBM_LSB_dbg 0 +/// CCARISETHRDBM field width +#define AGC_CCARISETHRDBM_WIDTH_dbg ((UINT32)0x00000008) + +#endif + +#include "bk7011_cal_pub.h" +int bkreg_run_command(const char *content, int cnt) +{ + char tx_buf[BKREG_TX_FIFO_THRD]; + UINT32 uart_rx_index; + REGISTER_PARAM *rx_param; + REGISTER_PARAM *tx_param; + HCI_EVENT_PACKET *pHCItxBuf = (HCI_EVENT_PACKET *)tx_buf; + HCI_COMMAND_PACKET *pHCIrxBuf = (HCI_COMMAND_PACKET *)content; + + uart_rx_index = cnt; + pHCItxBuf->total = 1; + pHCItxBuf->param[0] = pHCIrxBuf->cmd; + switch(pHCIrxBuf->cmd) + { + case BEKEN_UART_REGISTER_WRITE_CMD: + rx_param = (REGISTER_PARAM *)pHCIrxBuf->param; + REG_WRITE(rx_param->addr, rx_param->value); + + pHCItxBuf->total = uart_rx_index - 1; + os_memcpy(pHCItxBuf->param, pHCIrxBuf, HCI_EVENT_HEAD_LENGTH); + pHCItxBuf->param[3] = pHCIrxBuf->cmd; + + tx_param = (REGISTER_PARAM *)&pHCItxBuf->param[HCI_COMMAND_HEAD_LENGTH]; + tx_param->addr = rx_param->addr; + tx_param->value = rx_param->value; + +#if CFG_SUPPORT_CALIBRATION + { + extern INT32 rwnx_cal_save_trx_rcbekn_reg_val(void); + // when write trx and rc beken regs, updata registers save. + if( (rx_param->addr & 0xfff0000) == 0x1050000) + rwnx_cal_save_trx_rcbekn_reg_val(); + } +#endif + break; + + case BEKEN_UART_REGISTER_READ_CMD: + rx_param = (REGISTER_PARAM *)pHCIrxBuf->param; + pHCItxBuf->total = HCI_EVENT_HEAD_LENGTH + uart_rx_index; /*may err, porting from bk3260*/ + os_memcpy(pHCItxBuf->param, pHCIrxBuf, HCI_EVENT_HEAD_LENGTH); + pHCItxBuf->param[3] = pHCIrxBuf->cmd; + + tx_param = (REGISTER_PARAM *)&pHCItxBuf->param[HCI_COMMAND_HEAD_LENGTH]; + tx_param->addr = rx_param->addr; + + if(rx_param->addr == 0x00800014) { + #if ATE_APP_FUN + if(get_ate_mode_state()) + tx_param->value = 0x1B190104; // testmode flag[31:28] | bk7231U:B [27:24] | date + else + #endif + tx_param->value = 0x0B190104; + } + else + tx_param->value = REG_READ(rx_param->addr); + break; + + case BEKEN_WRITE_OTP_CMD: { + UINT8 *flag_ptr = NULL, *write_buf = NULL; + UINT8 flag = 0; + rx_param = (REGISTER_PARAM *)pHCIrxBuf->param; + write_buf = (UINT8 *)(rx_param + 1); + + flag = manual_cal_wirte_otp_flash(rx_param->addr, rx_param->value, write_buf); + + pHCItxBuf->total = OTP_CMD_RET_LEN + 1; + os_memcpy(pHCItxBuf->param, pHCIrxBuf, HCI_EVENT_HEAD_LENGTH); + pHCItxBuf->param[3] = pHCIrxBuf->cmd; + + tx_param = (REGISTER_PARAM *)&pHCItxBuf->param[HCI_COMMAND_HEAD_LENGTH]; + tx_param->addr = rx_param->addr; + tx_param->value = rx_param->value; + + flag_ptr = (UINT8 *)&pHCItxBuf->param[OTP_CMD_RET_LEN]; + *flag_ptr = flag; + } + break; + + case BEKEN_READ_OTP_CMD: { + UINT32 len, len_left = 0, addr; + UINT8 *read_buf = (UINT8 *)&pHCItxBuf->param[OTP_CMD_RET_LEN]; + + rx_param = (REGISTER_PARAM *)pHCIrxBuf->param; + +#if CFG_SUPPORT_ALIOS + hal_logic_partition_t *pt = hal_flash_get_info(HAL_PARTITION_RF_FIRMWARE); +#else + bk_logic_partition_t *pt = bk_flash_get_info(BK_PARTITION_RF_FIRMWARE); +#endif + + len_left = rx_param->value; + addr = rx_param->addr - pt->partition_start_addr;//0xFA000; + + while(len_left) { + len = (len_left > OTP_READ_MAX_LEN)? OTP_READ_MAX_LEN : len_left; + len = manual_cal_read_otp_flash(addr, len, read_buf); + if(len == 0) + return 0; + + pHCItxBuf->total = OTP_CMD_RET_LEN + len; + os_memcpy(pHCItxBuf->param, pHCIrxBuf, HCI_EVENT_HEAD_LENGTH); + pHCItxBuf->param[3] = pHCIrxBuf->cmd; + + tx_param = (REGISTER_PARAM *)&pHCItxBuf->param[HCI_COMMAND_HEAD_LENGTH]; + tx_param->addr = rx_param->addr + addr; + tx_param->value = len; + bkreg_tx(pHCItxBuf); + len_left -= len; + addr += len; + } + return 0; + } + break; + + case BEKEN_TEMP_CMD: { + #if CFG_USE_AUD_DAC + extern void audio_intf_dac_pause(void); + audio_intf_dac_pause(); + #endif + + #if CFG_USE_AUD_ADC + extern void audio_intf_adc_pause(void); + audio_intf_adc_pause(); + #endif + + } + break; + + case BEKEN_TEMP_TCP: { + #if CFG_USE_AUD_DAC + extern void audio_intf_dac_play(void); + audio_intf_dac_play(); + #endif + + #if CFG_USE_AUD_ADC + extern void audio_intf_adc_play(void); + audio_intf_adc_play(); + #endif + } + break; + + case BEKEN_TEST_UDP: { + #if CFG_SUPPORT_MANUAL_CALI + manual_cal_show_txpwr_tab(); + #endif + } + break; + + case BEKEN_SD_CLOSE: { + #if CFG_SUPPORT_MANUAL_CALI + manual_cal_fitting_txpwr_tab(); + #endif + } + break; +#if (CFG_SOC_NAME == SOC_BK7231U) //|| (CFG_SOC_NAME == SOC_BK7231N) + case BEKEN_TUYA_PWM: { + UINT32 u32_end_value; + UINT32 u32_duty_cycle1, u32_duty_cycle2; + UINT32 u32_dead_band_1; + extern void bk_cw_pwm_init(uint8 channel_num, uint32 end_value, uint32 duty_cycle); + extern void bk_cw_pwm_stop(uint8 channel_num_1, uint8 channel_num_2); + extern void bk_cw_pwm_reset_duty_cycle(uint8 channel_num_1, uint8 channel_num_2, + uint32 duty_cycle_1, uint32 duty_cycle_2, + uint32 end_value, uint32 dead_band_1); + os_printf("BEKEN_TUYA_PWM\r\n"); + switch (pHCIrxBuf->param[0]) + { + case 0x01: + u32_end_value = 0 | ( pHCIrxBuf->param[2] & 0x000000FFUL) + | ((pHCIrxBuf->param[3]<<8) & 0x0000FF00UL) + | ((pHCIrxBuf->param[4]<<16) & 0x00FF0000UL) + | ((pHCIrxBuf->param[5]<<24) & 0xFF000000UL); + u32_duty_cycle1 = 0 | ( pHCIrxBuf->param[6] & 0x000000FFUL) + | ((pHCIrxBuf->param[7]<<8) & 0x0000FF00UL) + | ((pHCIrxBuf->param[8]<<16) & 0x00FF0000UL) + | ((pHCIrxBuf->param[9]<<24) & 0xFF000000UL); + os_printf("tuya_pwm_init\r\n"); + bk_cw_pwm_init(pHCIrxBuf->param[1], u32_end_value, u32_duty_cycle1); + break; + case 0x02: + os_printf("tuya_pwm_stop\r\n"); + bk_cw_pwm_stop(pHCIrxBuf->param[1], pHCIrxBuf->param[2]); + break; + case 0x03: + u32_duty_cycle1 = 0 | ( pHCIrxBuf->param[3] & 0x000000FFUL) + | ((pHCIrxBuf->param[4]<<8) & 0x0000FF00UL) + | ((pHCIrxBuf->param[5]<<16) & 0x00FF0000UL) + | ((pHCIrxBuf->param[6]<<24) & 0xFF000000UL); + u32_duty_cycle2 = 0 | ( pHCIrxBuf->param[7] & 0x000000FFUL) + | ((pHCIrxBuf->param[8]<<8) & 0x0000FF00UL) + | ((pHCIrxBuf->param[9]<<16) & 0x00FF0000UL) + | ((pHCIrxBuf->param[10]<<24) & 0xFF000000UL); + u32_end_value = 0 | ( pHCIrxBuf->param[11] & 0x000000FFUL) + | ((pHCIrxBuf->param[12]<<8) & 0x0000FF00UL) + | ((pHCIrxBuf->param[13]<<16) & 0x00FF0000UL) + | ((pHCIrxBuf->param[14]<<24) & 0xFF000000UL); + u32_dead_band_1 = 0 | ( pHCIrxBuf->param[15] & 0x000000FFUL) + | ((pHCIrxBuf->param[16]<<8) & 0x0000FF00UL) + | ((pHCIrxBuf->param[17]<<16) & 0x00FF0000UL) + | ((pHCIrxBuf->param[18]<<24) & 0xFF000000UL); + os_printf("tuya_pwm_reset_duty_cycle\r\n"); + bk_cw_pwm_init(pHCIrxBuf->param[1], u32_end_value, u32_duty_cycle1); + bk_cw_pwm_init(pHCIrxBuf->param[2], u32_end_value, u32_duty_cycle2); + bk_cw_pwm_reset_duty_cycle(pHCIrxBuf->param[1], pHCIrxBuf->param[2], + u32_duty_cycle1, u32_duty_cycle2, + u32_end_value, u32_dead_band_1); + break; + + default: + break; + } + } + break; +#endif + + case LOOP_MODE_CMD: + { + #if CFG_USE_AUDIO + extern void audio_intf_uninit(void); + + audio_intf_uninit(); + #endif + } + break; + + case BEKEN_DUMP_ENV_CMD: + { + #if CFG_USE_AUDIO + extern UINT32 audio_intf_init(void); + + audio_intf_init(); + #endif + } + break; + +#if CFG_USE_TEMPERATURE_DETECT + case BEKEN_TEMP_DETECT_CONFIG_CMD: // 01 E0 FC 04 ec 02 01 05 + { + extern void temp_detect_change_configuration(UINT32 intval, UINT32 thre, UINT32 dist); + + int intval, thre, dist; + + intval = (int)pHCIrxBuf->param[0]; + thre = (int)pHCIrxBuf->param[1]; + dist = (int)pHCIrxBuf->param[2]; + + temp_detect_change_configuration(intval, thre, dist); + } + break; +#endif + + case BEKEN_SHOW_BT_STATUS: + { +#if CFG_USE_TUYA_CCA_TEST + UINT32 val, reg; + val = (UINT32)pHCIrxBuf->param[0]; + + reg = REG_READ(AGC_RWNXAGCCCA1_ADDR_dbg); + + os_printf("0 set cca val:0x%08x, 0x%08x\r\n", val, reg); + + reg &= ~(AGC_CCARISETHRDBM_MASK_dbg << AGC_CCARISETHRDBM_LSB_dbg); + reg |= ((val &AGC_CCARISETHRDBM_MASK_dbg) << AGC_CCARISETHRDBM_LSB_dbg); + REG_WRITE(AGC_RWNXAGCCCA1_ADDR_dbg, reg); + + reg = REG_READ(AGC_RWNXAGCCCA1_ADDR_dbg); + os_printf("1 set cca val:0x%08x, 0x%08x\r\n", val, reg); +#endif + } + break; + + case BEKEN_SHOW_BT_DEBUG: + { +#if CFG_USE_TUYA_CCA_TEST + UINT32 val; + + val = REG_READ(AGC_RWNXAGCCCA1_ADDR_dbg); + + os_printf("cca val:0x%08x\r\n", val); +#endif + } + break; + + case BEKEN_DO_REBOOT: + { + if((pHCIrxBuf->param[0] == 0x95) + && (pHCIrxBuf->param[1] == 0x27) + && (pHCIrxBuf->param[2] == 0x95) + && (pHCIrxBuf->param[3] == 0x27)) + { + /// reboot(NULL,NULL,1,NULL); + extern void bk_reboot(void); + bk_reboot(); + } + } + break; + + default: + pHCItxBuf->total = 1; + pHCItxBuf->param[0] = pHCIrxBuf->cmd; + break; + } + + bkreg_tx(pHCItxBuf); + + return 0; +} +#else +int bkreg_run_command(const char *content, int cnt) +{ + return 0; +} +#endif // CFG_SUPPORT_BKREG +#else +int bkreg_run_command(const char *content, int cnt) +{ + return 0; +} +#endif // CFG_UART_DEBUG +// eof + diff --git a/beken_os/beken378/func/uart_debug/command_line.h b/beken_os/beken378/func/uart_debug/command_line.h new file mode 100755 index 0000000..c0e3e9d --- /dev/null +++ b/beken_os/beken378/func/uart_debug/command_line.h @@ -0,0 +1,296 @@ +#ifndef _COMMAND_LINE_H_ +#define _COMMAND_LINE_H_ + +#include "include.h" +#include "command_table.h" + +#define CLI_DEBUG + +#ifdef CLI_DEBUG +#define CLI_PRT os_printf +#define CLI_WPRT warning_prf +#else +#define CLI_PRT os_null_printf +#define CLI_WPRT os_null_printf +#endif + + +#define DEBUG_PARSER 1 +#define CONFIG_SYS_CBSIZE 128 +#define CONFIG_SYS_MAXARGS 8 + +/* + * Rather than doubling the size of the _ctype lookup table to hold a 'blank' + * flag, just check for space or tab. + */ +#define isblank(c) (((c) == ' ') || ((c) == '\t')) +#define isascii(c) (((unsigned char)(c))<=0x7f) +#define toascii(c) (((unsigned char)(c))&0x7f) + +/* + * Error codes that commands return to cmd_process(). We use the standard 0 + * and 1 for success and failure, but add one more case - failure with a + * request to call cmd_usage(). But the cmd_process() function handles + * CMD_RET_USAGE itself and after calling cmd_usage() it will return 1. + * This is just a convenience for commands to avoid them having to call + * cmd_usage() all over the place. + */ +enum command_ret_t +{ + CMD_RET_SUCCESS, /* 0 = Success */ + CMD_RET_FAILURE, /* 1 = Failure */ + CMD_RET_USAGE = -1, /* Failure, please report 'usage' error */ +}; + +#include "arm_arch.h" + +typedef struct +{ + unsigned int addr; + unsigned int value; +} __attribute__ ((packed)) REGISTER_PARAM; + +typedef struct +{ + unsigned char code; /**< 0x01: HCI Command Packet + 0x02: HCI ACL Data Packet + 0x03: HCI Synchronous Data Packet + 0x04: HCI Event Packet */ + unsigned short opcode; + unsigned char total; + unsigned char cmd; /**< private command */ + unsigned char param[]; +} __attribute__ ((packed)) HCI_COMMAND_PACKET; + +typedef struct +{ + unsigned char code; /**< 0x01: HCI Command Packet + 0x02: HCI ACL Data Packet + 0x03: HCI Synchronous Data Packet + 0x04: HCI Event Packet */ + unsigned char event; /**< 0x00-0xFF: Each event is assigned a 1-Octet event code used to uniquely identify different types of events*/ + unsigned char total; /**< Parameter Total Length */ + unsigned char param[]; +} __attribute__ ((packed)) HCI_EVENT_PACKET; + +#include "uart.h" +#define BKREG_TX_FIFO_THRD RX_RB_LENGTH //(0x40) + +#define HCI_EVENT_HEAD_LENGTH (0x03) +#define HCI_COMMAND_HEAD_LENGTH (0x04) +#define OTP_CMD_RET_LEN (12) +#define OTP_READ_MAX_LEN (BKREG_TX_FIFO_THRD - HCI_EVENT_HEAD_LENGTH - OTP_CMD_RET_LEN) +#define OTP_WRITE_MAX_LEN (RX_RB_LENGTH - 13) // RX_RB_LENGTH 01E0FCXXA8 ADDR-4 LEN-4 + +/***************************** + * HCI Events - Event codes + ******************************/ +#define HCI_INQUIRY_COMPLETE_EVENT 0x01 +#define HCI_INQUIRY_RESULT_EVENT 0x02 +#define HCI_CONNECTION_COMPLETE_EVENT 0x03 +#define HCI_CONNECTION_REQUEST_EVENT 0x04 +#define HCI_DISCONNECTION_COMPLETE_EVENT 0x05 +#define HCI_AUTHENTICATION_COMPLETE_EVENT 0x06 +#define HCI_READ_REMOTE_NAME_REQUEST_COMPLETE_EVENT 0x07 +#define HCI_ENCRYPTION_CHANGE_EVENT 0x08 +#define HCI_CHANGE_CONNECTION_LINK_KEY_COMPLETE_EVENT 0x09 +#define HCI_MASTER_LINK_KEY_COMPLETE_EVENT 0x0A +#define HCI_READ_REMOTE_SUPPORTED_FEATURES_COMPLETE_EVENT 0x0B +#define HCI_READ_REMOTE_VERSION_INFORMATION_COMPLETE_EVENT 0x0C +#define HCI_QoS_SETUP_COMPLETE_EVENT 0x0D +#define HCI_COMMAND_COMPLETE_EVENT 0x0E +#define HCI_COMMAND_STATUS_EVENT 0x0F +#define HCI_HARDWARE_ERROR_EVENT 0x10 +#define HCI_FLUSH_OCCURED_EVENT 0x11 +#define HCI_ROLE_CHANGE_EVENT 0x12 +#define HCI_NUMBER_OF_COMPLETED_PACKETS_EVENT 0x13 +#define HCI_MODE_CHANGE_EVENT 0x14 +#define HCI_RETURN_LINK_KEYS_EVENT 0x15 +#define HCI_PIN_CODE_REQUEST_EVENT 0x16 +#define HCI_LINK_KEY_REQUEST_EVENT 0x17 +#define HCI_LINK_KEY_NOTIFICATION_EVENT 0x18 +#define HCI_LOOPBACK_COMMAND_EVENT 0x19 +#define HCI_DATA_BUFFER_OVERFLOW_EVENT 0x1A +#define HCI_MAX_SLOTS_CHANGE_EVENT 0x1B +#define HCI_READ_CLOCK_OFFSET_EVENT 0x1C +#define HCI_CONNECTION_PACKET_TYPE_CHANGED_EVENT 0x1D +#define HCI_CONNECTION_PACKET_TYPE_CHANGED_EVENT 0x1D +#define HCI_QOS_VIOLATION_EVENT 0x1E +#define HCI_PAGE_SCAN_MODE_CHANGE_EVENT 0x1F +#define HCI_PAGE_SCAN_REPETITION_MODE_CHANGE_EVENT 0x20 + + +/* + * HCI transport type bytes + */ + +enum +{ + TRA_HCIT_COMMAND = 1, + TRA_HCIT_ACLDATA = 2, + TRA_HCIT_SCODATA = 3, + TRA_HCIT_EVENT = 4 +}; + +enum +{ + BEKEN_UART_LINK_CHECK = 0x00, /*return 0x04 0x0e 0x04 0x01 0xe0 0xfc 0x00*/ + BEKEN_UART_REGISTER_WRITE_CMD = 0x01, /*Write certain reg*/ + BEKEN_UART_REGISTER_CONTINUOUS_WRITE_CMD = 0x02, /*write reg continuous*/ + BEKEN_UART_REGISTER_READ_CMD = 0x03, /*read certain reg value*/ + + BEKEN_UART_BT_START_CMD = 0x04, /*useless*/ + BEKEN_UART_BT_STOP_CMD = 0x05, /*useless*/ + BEKEN_UART_PATCH_CMD = 0x06, /*useless*/ + + BEKEN_UART_SET_UART_PROTOCOL = 0x07, /*set uart protocol, H4:00 BCSP:01*/ + + /* + 01 e0 fc 09 08 aa aa aa aa bb cc dd ee + aa: baudrate + bb: byte size 5,6,7,8 + cc: stop len 1 or 2 + dd: par_en 00:no par 01:par + ee: par 00:odd 01:even + */ + BEKEN_UART_SET_UART_CONFIG = 0x08, /*set uart config*/ + BEKEN_ENABLE_AFC = 0x09, /*enable afc*/ + + /* + 01 e0 fc 06 0A aa bb cc dd ee + aa: data_len 0:16bit, N(8,13,14,15): N bit + bb: speed; 0:200K,1: 1M,2:64K,3:external,4:256K,5:512K,6:128K + cc: is_msb 0:msb,1:lsb + dd: role; 0:slave 1:master + ee: sync_type; 0:short_sync, N(1-7): long_sync with length N + */ + BEKEN_CONFIG_PCM = 0x0A, /*config PCM*/ + + //0:normal mode; 1:only stop CPU when acl number = 0; 2:not stop CPU + BEKEN_CPU_HALT_MODE = 0x0B, /*set CPU sleep mode*/ + BEKEN_ENABLE_32K_SLEEP = 0x0C, /*enable cpu enter 32K sleep*/ + BEKEN_ENABLE_ANALOG_POWERDOWN = 0x0D, /*enable close CEVA clock*/ + + BEKEN_ENABLE_GPIO_EINT_WAKEUP = 0x0E, /*enable GPIO wake up CPU*/ + BEKEN_ENABLE_UART_RX_WAKEUP = 0x0F, /*enable uart RX wake up BT chip*/ + BEKEN_SET_UART_RX_WAKEUP_COUNT = 0x10, /*set UART RX wake up count*/ + + BEKEN_ENABLE_UART_TX_WAKEUP = 0x11, /*enable uart TX wake up HOST*/ + BEKEN_SET_UART_AFTER_WAKEUP_SIG_WAIT_COUNT = 0x12, /*set UART TX wake up HOST count*/ + + BEKEN_MAX_ACL_BUFF_SIZE = 0x13, /*useless*/ + BEKEN_ACL_ACTIVE_CHECK_WHEN_SLEEP = 0x14, + BEKEN_DISABLE_SNIFFER_WHEN_OTHER_LINK_ACTIVE = 0x15, + BEKEN_LM_CONFIG_SLEEP_IN_STANDBY_MONITOR_PERIOD = 0x16, + BEKEN_LM_CONFIG_AWAKE_IN_STANDBY_MONITOR_PERIOD = 0x17, + BEKEN_DISABLE_ACL_ACCEPT_WHEN_ACL_EXIST = 0x18, + BEKEN_ENABLE_TX_POWER_CONTROL = 0x19, + BEKEN_LM_CONFIG_AWAKE_KEEP_WHEN_UART_WAKEUP = 0x1A, + BEKEN_DISABLE_INQUIRY_WHEN_ACL_EXIST = 0x1B, + BEKEN_DELAY_BETWEEN_EVERY_PACKET_UART_TX = 0x1C, + BEKEN_SCATTER_LENGTH_FOR_PACKET_UART_TX = 0x1D, + BEKEN_ENABLE_ACK_SEQ_CHECK = 0x1E, + BEKEN_RESET_ACK_SEQ_AFTER_TX = 0x1F, + BEKEN_GET_FW_VERSION = 0x20, + BEKEN_UART_CLOCK_CONFIG_BEFORE_TX_LOW_LEVEL = 0x21, + BEKEN_UART_BAUD_RATE_FOR_TX_LOW_LEVEL = 0x22, + BEKEN_DELAY1_AFTER_TX_LOW_LEVEL = 0x23, + BEKEN_DELAY2_AFTER_TX_LOW_LEVEL = 0x24, + BEKEN_DELAY_FOR_OBEX_PACKET_FINAL = 0x25, + BEKEN_DISABLE_SPREADTRUM_HCI = 0x26, + BEKEN_MAX_ACL_BUFF_NUMBER = 0x27, + BEKEN_WRITE_ADDR_AFTER_RESET = 0x28, + + BEKEN_ENABLE_MASTER_AFC = 0x2C, + BEKEN_ENABLE_VIMicro_ENCRYPTION_ISSUE = 0x2D, + BEKEN_ENABLE_CPU_SPEED_FOR_ECC = 0x2E, + BEKEN_CHANGE_CPU_CLK = 0x2F, + BEKEN_ENABLE_CSR_TX_CRC = 0x30, + + SLEEP_FOR_ATE_POWER_TEST = 0x32, + BEKEN_DISALBE_HAREWARE_ERROR_LOG = 0x33, + BEKEN_ENABLE_ROLE_SWITCH = 0x34, + BEKEN_SET_LMP_FEATURES = 0x35, + BEKEN_SET_LMP_EXT_FEATURES = 0x36, + BEKEN_DISALBE_EDR3 = 0x37, + BEKEN_DISALBE_2DH1_WHEN_AUTORATE = 0x38, + BEKEN_FORCE_DM1_WHEN_LITTLE_PACKET = 0x39, + BEKEN_ENABLE_QOS = 0x3A, + // BEKEN_DISABLE_ESCO =0x3A, + BEKEN_DELAY_PTT_SET = 0x3B, + BEKEN_SET_32K_WAKUP_TIME = 0x3C, + BEKEN_CFG_MIN_SLOTS_FOR_SLEEP_PROCEDURE = 0x3D, + BEKEN_SET_HOST_WAKEUP_TIME = 0x3E, + BEKEN_BT_ACTIVE_PIN_SEL = 0x3F, + BEKEN_BT_PRIORITY_PIN_SEL = 0x40, + BEKEN_WLAN_ACTIVE_PIN_SEL = 0x41, + BEKEN_WLAN_ACTIVE_PIN_POL = 0x42, + BEKEN_ENABLE_SOFTIRQ_FOR_UART = 0x43, + BEKEN_SET_T_SNIFF_MIN = 0x44, + BEKEN_SET_T_SNIFF_MAX = 0x45, + BEKEN_CHANGE_SNIFF_ATTEMP_WHEN_SNIFF_MIN_IS_SMALL = 0x46, + BEKEN_CHANGE_SNIFF_TIMEOUT_WHEN_SNIFF_MIN_IS_SMALL = 0x47, + BEKEN_PTA_TX_DELAY_AFTER_PRIORITY = 0x48, + BEKEN_PTA_TX_DELAY_AFTER_FREQ_OVERLAP = 0x49, + BEKEN_PTA_RX_DELAY_AFTER_PRIORITY = 0x4A, + BEKEN_ENABLE_PTA = 0x4B, + BEKEN_ENABLE_CPU_SPEED_FOR_ECC2 = 0x4C, + BEKEN_SPEED_UART_CRC = 0x4D, + BEKEN_UART_MODULE_TEST_CMD = 0x50, + BEKEN_UART_MODULE_SUB_TEST_CMD = 0x51, + BEKEN_UART_MODULE_GENERAL_CMD = 0x52, + BEKEN_ENABLE_AUTO_CHANGE_CPU_CLK = 0x53, + BEKEN_SET_SCO_USE_HCI = 0x82, +#if (DEBUG_BASEBAND_MONITORS == 1) + BEKEN_READ_BASEBAND_MONITORS = 0x90, + BEKEN_RESET_BASEBAND_MONITORS = 0x91, +#endif +#if (DEBUG_AGC_MODE_CHANNEL_ASSESSMENT == 1) + BEKEN_AGC_MODE_PARAM = 0x92, +#endif + BEKEN_FLASH_READ_CMD = 0xA0, + BEKEN_FLASH_WRITE_CMD = 0xA1, + BEKEN_FLASH_ERASE_CMD = 0xA2, + BEKEN_SHOW_STACK_CMD = 0XAA, + BEKEN_DUMP_ENV_CMD = 0xAB, + BEKEN_SHOW_BT_STATUS = 0xAC, + BEKEN_SHOW_BT_DEBUG = 0xAD, + BEKEN_PRINT_LINK_KEY = 0XAE, + BEKEN_ENTRY_DUT_MODE = 0XAF, + BEKEN_READ_OTP_CMD = 0XA7, + BEKEN_WRITE_OTP_CMD = 0XA8, + LOOP_MODE_CMD = 0XCC, + BEKEN_TEMP_CMD = 0XDD, + BEKEN_TEMP_TCP = 0XEE, + BEKEN_TEMP_DETECT_CONFIG_CMD = 0XEC, + BEKEN_TEST_UDP = 0XDE, + BEKEN_SD_CLOSE = 0XDC, + BEKEN_TUYA_PWM = 0XDB, + BEKEN_DO_REBOOT = 0XFE, +}; + +/** + * Process a command with arguments. We look up the command and execute it + * if valid. Otherwise we print a usage message. + * + * @param flag Some flags normally 0 (see CMD_FLAG_.. above) + * @param argc Number of arguments (arg 0 must be the command text) + * @param argv Arguments + * @param repeatable This function sets this to 0 if the command is not + * repeatable. If the command is repeatable, the value + * is left unchanged. + * @param ticks If ticks is not null, this function set it to the + * number of ticks the command took to complete. + * @return 0 if the command succeeded, 1 if it failed + */ +int cmd_process(int flag, int argc, char *const argv[], + int *repeatable, unsigned int *ticks); +int run_command(const char *cmd, int flag); +cmd_tbl_t *cmd_find_tbl(const char *cmd, cmd_tbl_t *table, int table_len); +int cmd_usage(const cmd_tbl_t *cmdtp); + +#if CFG_SUPPORT_BKREG +extern int bkreg_run_command(const char *cmd, int flag); +#endif // CFG_SUPPORT_BKREG + +#endif // _COMMAND_LINE_H_ diff --git a/beken_os/beken378/func/uart_debug/command_table.c b/beken_os/beken378/func/uart_debug/command_table.c new file mode 100755 index 0000000..3f88167 --- /dev/null +++ b/beken_os/beken378/func/uart_debug/command_table.c @@ -0,0 +1,35 @@ +#include "include.h" +#include "command_table.h" + +#include "entry_declare.h" +#include "cmd_help.h" +#include "cmd_evm.h" +#include "cmd_rx_sensitivity.h" +#include "cmd_reg.h" + +#if CFG_UART_DEBUG +cmd_tbl_t command_tbl[] = +{ + /* add new entry*/ + ENTRY_CMD_EVM, + ENTRY_CMD_RX_SENSITIVITY, + ENTRY_CMD_HELP, + ENTRY_CMD_REG, + + /* last null entry*/ + {NULL, 0, 0, NULLPTR, NULLPTR} +}; + +cmd_tbl_t *entry_get_start(void) +{ + return &command_tbl[0]; +} + +int entry_get_count(void) +{ + return sizeof(command_tbl) / sizeof(command_tbl[0]); +} +#endif // CFG_UART_DEBUG + +// eof + diff --git a/beken_os/beken378/func/uart_debug/command_table.h b/beken_os/beken378/func/uart_debug/command_table.h new file mode 100755 index 0000000..20d097a --- /dev/null +++ b/beken_os/beken378/func/uart_debug/command_table.h @@ -0,0 +1,39 @@ +#ifndef _COMMAND_TABLE_H_ +#define _COMMAND_TABLE_H_ + +#define COMMAND_MAX_COUNT 16 + +#define CONFIG_SYS_LONGHELP 1 + +/* + * Monitor Command Table + */ +struct cmd_tbl_s +{ + char *name; /* Command Name */ + int maxargs; /* maximum number of arguments */ + int repeatable; /* autorepeat allowed? */ + /* Implementation function */ + int (*cmd)(struct cmd_tbl_s *, int, int, char *const []); + char *usage; /* Usage message (short) */ + +#ifdef CONFIG_SYS_LONGHELP + char *help; /* Help message (long) */ +#endif + +#ifdef CONFIG_AUTO_COMPLETE + /* do auto completion on the arguments */ + int (*complete)(int argc, char *const argv[], char last_char, int maxv, char *cmdv[]); +#endif +}; + +typedef struct cmd_tbl_s cmd_tbl_t; + +#if CFG_UART_DEBUG +extern cmd_tbl_t command_tbl[]; + +cmd_tbl_t *entry_get_start(void); +int entry_get_count(void); +#endif // CFG_UART_DEBUG + +#endif // _COMMAND_TABLE_H_ diff --git a/beken_os/beken378/func/uart_debug/entry_declare.h b/beken_os/beken378/func/uart_debug/entry_declare.h new file mode 100755 index 0000000..3fb5fa5 --- /dev/null +++ b/beken_os/beken378/func/uart_debug/entry_declare.h @@ -0,0 +1,25 @@ +#ifndef _ENTRY_DECLARE_H_ +#define _ENTRY_DECLARE_H_ + + +#ifdef CONFIG_AUTO_COMPLETE +#define _CMD_COMPLETE(x) x, +#else +#define _CMD_COMPLETE(x) +#endif + +#ifdef CONFIG_SYS_LONGHELP +#define _CMD_HELP(x) x, +#else +#define _CMD_HELP(x) +#endif + +#define ENTRY_CMD_COMPLETE(_name, _maxargs, _rep, _cmd, _usage, _help, _comp) \ + { #_name, _maxargs, _rep, _cmd, _usage, \ + _CMD_HELP(_help) _CMD_COMPLETE(_comp) } + +#define ENTRY_CMD(_name, _maxargs, _rep, _cmd, _usage, _help) \ + ENTRY_CMD_COMPLETE(_name, _maxargs, _rep, _cmd, _usage, _help, NULL) + + +#endif // _ENTRY_DECLARE_H_ diff --git a/beken_os/beken378/func/uart_debug/udebug.c b/beken_os/beken378/func/uart_debug/udebug.c new file mode 100755 index 0000000..20a0e0f --- /dev/null +++ b/beken_os/beken378/func/uart_debug/udebug.c @@ -0,0 +1,241 @@ +#include "include.h" + +#if CFG_UART_DEBUG +#include "udebug.h" +#include "uart_debug_pub.h" +#include "uart_pub.h" +#include "mem_pub.h" +#include "drv_model_pub.h" +#include "command_line.h" + +char udebug_buf[CONFIG_SYS_CBSIZE]; +UINT32 udebug_last_cnt = 0; +UINT32 udebug_cnt = 0; + +UINT32 debug_pri_level = DEBUG_PRI_LEVEL_1; +UINT32 debug_chunk_count = DEBUG_CHUNK_DEFAULT_COUNT; + +UINT32 uart_debug_init(void) +{ + return 0; +} + +void udebug_update_chunk_cnt(void) +{ + debug_chunk_count = debug_pri_level * DEBUG_CHUNK_DEFAULT_COUNT; +} + +void udebug_set_pri_level(UINT32 level) +{ + if(level >= DEBUG_PRI_LEVEL_MAX) + { + level = DEBUG_PRI_LEVEL_6; + } + else if(level <= DEBUG_PRI_LEVEL_MIN) + { + level = DEBUG_PRI_LEVEL_1; + } + + debug_pri_level = level; +} + +UINT32 udebug_get_pri_level(void) +{ + return debug_pri_level; +} + +UINT32 udebug_has_ctrlc(void) +{ + char val; + UINT32 ret = 0; + UINT32 status; + DD_HANDLE uart_hdl; + uart_hdl = ddev_open(UART2_DEV_NAME, &status, 0); + ASSERT(DRV_FAILURE != uart_hdl); + + ret = ddev_read(uart_hdl, &val, sizeof(val), 0); + if(ret) + { + if(0x03 == val) /* ^C control c*/ + { + ddev_close(uart_hdl); + return 1; + } + } + + ddev_close(uart_hdl); + + return 0; +} + +UINT32 udebug_wait_ctrlc_exit(void) +{ + char val; + UINT32 ret = 0; + UINT32 status; + DD_HANDLE uart_hdl; + + uart_hdl = ddev_open(UART2_DEV_NAME, &status, 0); + ASSERT(DRV_FAILURE != uart_hdl); + + while(1) + { + ret = ddev_read(uart_hdl, &val, sizeof(val), 0); + if(ret) + { + if(0x03 == val) /* ^C control c*/ + { + break; + } + } + } + + ddev_close(uart_hdl); + + return 0; +} + +UINT32 udebug_handler(void) +{ + char val; + UINT32 ret; + UINT32 hit = 0; + UINT32 status; + DD_HANDLE uart_hdl; + UART_PEEK_RX_T peek; + + char uart_peek[UART_PEEK_LEN]; + + uart_hdl = ddev_open(UART2_DEV_NAME, &status, 0); + ASSERT(DRV_FAILURE != uart_hdl); + + while(1) + { + do + { + ret = ddev_control(uart_hdl, CMD_RX_COUNT, 0); + if(ret < BKREG_MIN_LEN) + { + break; + } + + peek.sig = URX_PEEK_SIG; + peek.ptr = &uart_peek[0]; + peek.len = UART_PEEK_LEN; + ret = ddev_control(uart_hdl, CMD_RX_PEEK, &peek); + +#ifdef UD_SUPPORT_UPKEY + if((UP_KEY_COUNT == ret) + && (0x1B == uart_peek[0]) + && (0x4F == uart_peek[1]) + && (0x41 == uart_peek[2])) + { + ret = ddev_read(uart_hdl, uart_peek, sizeof(uart_peek), 0); + ASSERT(UP_KEY_COUNT == ret); + + if(0 == udebug_cnt) + { + udebug_cnt = udebug_last_cnt; + + UD_PRT("%s", udebug_buf); + UD_PRT("\r\n"); + + run_command(udebug_buf, 0); + + UD_PRT(UDEBUG_PROMPT); + + udebug_cnt = 0; + os_memset(uart_peek, 0, sizeof(uart_peek)); + + break; + } + } + else +#endif // UD_SUPPORT_UPKEY + { +#if CFG_SUPPORT_BKREG + if((ret > BKREG_MIN_LEN) + && (BKREG_MAGIC_WORD0 == uart_peek[0]) + && (BKREG_MAGIC_WORD1 == uart_peek[1]) + && (BKREG_MAGIC_WORD2 == uart_peek[2])) + { + ret = ddev_read(uart_hdl, uart_peek, sizeof(uart_peek), 0); + ASSERT(ret > BKREG_MIN_LEN); + + bkreg_run_command(uart_peek, ret); + os_memset(uart_peek, 0, sizeof(uart_peek)); + + break; + } +#endif // CFG_SUPPORT_BKREG + } + } + while(0); + + ret = ddev_read(uart_hdl, &val, sizeof(val), 0); + if(0 == ret) + { + break; + } + +#ifdef CONSOLE_NO_LOCAL_ECHO + UD_PRT("%c", val); +#endif + + if(('\n' == val) + || ('\n' == val) + || ('\r' == val) + || (sizeof(udebug_buf) == udebug_cnt)) + { + hit = 1; + break; + } + + if(0x08 == val) /* 0x08 bs backspace*/ + { + if(udebug_cnt >= 1) + { + udebug_cnt = udebug_cnt - 1; + } + } + else + { + if(0 == udebug_cnt) + { + os_memset(udebug_buf, 0, sizeof(udebug_buf)); + } + + udebug_buf[udebug_cnt] = val; + udebug_cnt ++; + } + } + + if(hit) + { + if(udebug_cnt) + { + run_command(udebug_buf, 0); + } + +#ifdef UD_SUPPORT_UPKEY + udebug_last_cnt = udebug_cnt; +#else + os_memset(udebug_buf, 0, sizeof(udebug_buf)); +#endif + + udebug_cnt = 0; + + UD_PRT("\r\n"); + UD_PRT(UDEBUG_PROMPT); + + return 0; + } + else + { + return 1; + } +} +#endif + +// eof + diff --git a/beken_os/beken378/func/uart_debug/udebug.h b/beken_os/beken378/func/uart_debug/udebug.h new file mode 100755 index 0000000..3d8cf59 --- /dev/null +++ b/beken_os/beken378/func/uart_debug/udebug.h @@ -0,0 +1,43 @@ +#ifndef _UDEBUG_H_ +#define _UDEBUG_H_ + +#define UD_DEBUG + +#ifdef UD_DEBUG +#define UD_PRT os_printf +#define UD_WPRT warning_prf +#else +#define UD_PRT os_null_printf +#define UD_WPRT os_null_printf +#endif + +#define BKREG_MIN_LEN 3 +#define BKREG_MAGIC_WORD0 (0x01) +#define BKREG_MAGIC_WORD1 (0xE0uc) +#define BKREG_MAGIC_WORD2 (0xFCuc) + +// largest one 01 e0 fc 09 03 xx xx xx xx xx xx xx xx +#define UART_PEEK_LEN 13 + +//#define CONSOLE_NO_LOCAL_ECHO +#define UD_SUPPORT_UPKEY + +#define UP_KEY_COUNT 3 +#define DEBUG_CHUNK_DEFAULT_COUNT 20*5 +#define UDEBUG_PROMPT "\\BK7211\\UART_DEBUG>" + +enum +{ + DEBUG_PRI_LEVEL_MIN, + DEBUG_PRI_LEVEL_1, + DEBUG_PRI_LEVEL_2, + DEBUG_PRI_LEVEL_3, + DEBUG_PRI_LEVEL_4, + DEBUG_PRI_LEVEL_5, + DEBUG_PRI_LEVEL_6, + DEBUG_PRI_LEVEL_MAX +}; + +#endif // _UDEBUG_H_ + +// eof diff --git a/beken_os/beken378/func/udisk_mp3/ump3.c b/beken_os/beken378/func/udisk_mp3/ump3.c new file mode 100755 index 0000000..273c9d9 --- /dev/null +++ b/beken_os/beken378/func/udisk_mp3/ump3.c @@ -0,0 +1,126 @@ +#include "include.h" +#include "ump3.h" +#include "ump3_pub.h" +#include "usb_pub.h" +#include "uart_pub.h" +#include "rtos_pub.h" +#include "drv_model_pub.h" +#include "diskio.h" + +#define UMP3_STACK_SIZE (4 * 1024) +beken_thread_t ump3_thread_handle = NULL; +beken_semaphore_t ump3_device_connect_sema = NULL; + +#if CFG_USE_USB_HOST +extern void test_mount(DISK_NUMBER number); +extern void test_fatfs(DISK_NUMBER number); +#endif + +void um_init(void) +{ + UINT32 ret; + UINT32 status; + UINT32 op_flag; + void *parameter; + DD_HANDLE usb_handler; + + op_flag = USB_HOST_MODE; + usb_handler = ddev_open(USB_DEV_NAME, &status, op_flag); + if(DD_HANDLE_UNVALID == usb_handler) + { + UM_PRT("usb_open_failed\r\n"); + return; + } + + parameter = (void *)um_connect_cb; + ret = ddev_control(usb_handler, UCMD_USB_CONNECTED_REGISTER_CB, parameter); + if(ret) + { + UM_PRT("UCMD_USB_CONNECTED_REGISTER_CB failed\r\n"); + } + + um_work_init(); +} + +void um_uninit(void) +{ + OSStatus ret; + + if(ump3_thread_handle) + { + ret = rtos_delete_thread(&ump3_thread_handle); + ASSERT(kNoErr == ret); + } + + if(ump3_device_connect_sema) + { + rtos_deinit_semaphore(&ump3_device_connect_sema); + } +} + +void um_connect_cb(void) +{ + if(ump3_device_connect_sema) + { + UM_PRT("um_connect_cb\r\n"); + rtos_set_semaphore(&ump3_device_connect_sema); + } +} + +void um_thread_main(void *arg) +{ + OSStatus result; + + while(1) + { + result = rtos_get_semaphore(&ump3_device_connect_sema, BEKEN_WAIT_FOREVER); + if(kNoErr == result) + { + UM_PRT("test_mount\r\n"); +#if CFG_USE_USB_HOST + test_mount(1); + + UM_PRT("test_fatfs\r\n"); + test_fatfs(1); +#endif + } + } +} + +uint32_t um_work_init(void) +{ + OSStatus ret = 0; + + if(ump3_thread_handle) + { + goto work_exit; + } + + ret = rtos_create_thread(&ump3_thread_handle, + THD_UMP3_PRIORITY, + "ump3_thread", + (beken_thread_function_t)um_thread_main, + (unsigned short)UMP3_STACK_SIZE, + (beken_thread_arg_t)0); + if (kNoErr != ret) + { + UM_PRT("create ump3 thread failed\r\n"); + goto work_exit; + } + + UM_PRT("um_work_init\r\n"); + if(NULL == ump3_device_connect_sema) + { + ret = rtos_init_semaphore(&ump3_device_connect_sema, 1); + if (kNoErr != ret) + { + UM_PRT("create device connect sema failed\r\n"); + goto work_exit; + } + } + +work_exit: + return (uint32_t)ret; +} +// eof + diff --git a/beken_os/beken378/func/udisk_mp3/ump3.h b/beken_os/beken378/func/udisk_mp3/ump3.h new file mode 100755 index 0000000..b18bf94 --- /dev/null +++ b/beken_os/beken378/func/udisk_mp3/ump3.h @@ -0,0 +1,17 @@ +#ifndef _U_MP3_H_ +#define _U_MP3_H_ + +#define UM_DEBUG +#ifdef UM_DEBUG +#define UM_PRT os_printf +#define UM_WPRT warning_prf +#else +#define UM_PRT os_null_printf +#define UM_WPRT os_null_printf +#endif + +extern uint32_t um_work_init(void); +extern void um_connect_cb(void); + +#endif // _U_MP3_H_ +// eof diff --git a/beken_os/beken378/func/usb/fusb.c b/beken_os/beken378/func/usb/fusb.c new file mode 100755 index 0000000..240e70a --- /dev/null +++ b/beken_os/beken378/func/usb/fusb.c @@ -0,0 +1,231 @@ +#include "include.h" +#include "uart_pub.h" +#include "fusb_pub.h" +#include "fusb.h" +#include "usb_pub.h" +#include "drv_model_pub.h" +#include "sys_rtos.h" +#include "rtos_pub.h" +#include "diskio.h" +#include "usb_pub.h" + +#if CFG_USB +volatile int g_usb_flag = 0; +xTaskHandle usb_test_thread_handle; + +extern void test_mount(DISK_NUMBER number); +extern void scan_file_system(DISK_NUMBER number); +extern void test_fatfs(DISK_NUMBER number); + +static void usb_test_thread_main( void *arg ) +{ + FUSB_PRT("usb_test_thread_main\r\n"); + while (1) + { + if (MUSB_GetConnect_Flag()) + { + FUSB_PRT("usb_test_thread_main: Udisk Connected\r\n"); + if (g_usb_flag == 0) + { + g_usb_flag = 1; + FUSB_PRT("test_mount\r\n"); + test_mount(DISK_NUMBER_UDISK); + } + else if (g_usb_flag == 1) + { + g_usb_flag = 2; + FUSB_PRT("scan_file_system\r\n"); + scan_file_system(DISK_NUMBER_UDISK); + } + else if (g_usb_flag == 2) + { + g_usb_flag = 3; + FUSB_PRT("test_fatfs\r\n"); + test_fatfs(DISK_NUMBER_UDISK); + } + } + else + { + FUSB_PRT("usb_test_thread_main: Udisk Disconnected\r\n"); + } + } +} + +UINT32 fusb_init(void) +{ + UINT32 ret; + UINT32 status; + UINT32 op_flag; + DD_HANDLE usb_handler; + + ret = FUSB_SUCCESS; + +#ifdef FMSC_TEST + fmsc_test_init(); +#elif defined(FUVC_TEST) + //fuvc_test_init(); +#else +#endif + + op_flag = USB_HOST_MODE; + usb_handler = ddev_open(USB_DEV_NAME, &status, op_flag); + if(DD_HANDLE_UNVALID == usb_handler) + { + FUSB_PRT("usb_open_failed\r\n"); + } + else if(USB_SUCCESS == status) + { + FUSB_PRT("usb_open_success\r\n"); + } + +#ifdef FUSB_ENABLE_USER_MAIN + ret = rtos_create_thread(&usb_test_thread_handle, + 5, + "usb_test_thread", + (beken_thread_function_t)usb_test_thread_main, + (unsigned short)2048, + (beken_thread_arg_t)0); +#endif // FUSB_ENABLE_USER_MAIN + + return ret; +} + +#ifdef FMSC_TEST +#define TEST_BUFFER_SIZE 512 +#define FIRST_BLOCK 1 +#define BLOCK_COUNT 1 + +UINT8 test_buff[TEST_BUFFER_SIZE] = {0}; + +void fmsc_test_init(void) +{ + UINT32 status; + void *parameter; + DD_HANDLE usb_hdl; + + FUSB_PRT("fmsc_test_init\r\n"); + usb_hdl = ddev_open(USB_DEV_NAME, &status, 0); + if(DD_HANDLE_UNVALID == usb_hdl) + { + goto init_failed; + } + + parameter = (void *)fmsc_fiddle_process; + ddev_control(usb_hdl, UCMD_MSC_REGISTER_FIDDLE_CB, parameter); + ddev_close(usb_hdl); + +init_failed: + return; +} + +void fmsc_fiddle_process(void) +{ +} +#endif // FMSC_TEST + +#ifdef FUVC_TEST +#include "schedule_pub.h" + +#ifdef CFG_SUPPORT_UVC +#define TEST_BUFFER_SIZE 1024 * 50 +#else +#define TEST_BUFFER_SIZE 1024 * 16 +#endif + +UINT8 test_buff[TEST_BUFFER_SIZE] = {0}; + +void fuvc_test_init( uint8_t LinkType ) +{ + UINT32 param; + UINT32 status; + void *parameter; + DD_HANDLE usb_hdl; + + usb_hdl = ddev_open(USB_DEV_NAME, &status, 0); + if(DD_HANDLE_UNVALID == usb_hdl) + { + goto init_error; + } + + parameter = (void *)fuvc_notify_uvc_configed; + ddev_control(usb_hdl, UCMD_UVC_REGISTER_CONFIG_NOTIFY_CB, parameter); + parameter = (void *)fuvc_fiddle_rx_vs; + ddev_control(usb_hdl, UCMD_UVC_REGISTER_RX_VSTREAM_CB, parameter); + + parameter = (void *)test_buff; + ddev_control(usb_hdl, UCMD_UVC_REGISTER_RX_VSTREAM_BUF_PTR, parameter); + param = TEST_BUFFER_SIZE; + ddev_control(usb_hdl, UCMD_UVC_REGISTER_RX_VSTREAM_BUF_LEN, ¶m); + + param = LinkType; + ddev_control(usb_hdl, UCMD_UVC_REGISTER_LINK, ¶m); + +#ifdef UVC_DEMO_SUPPORT100 + param = UVC_MUX_PARAM(U1_FRAME_640_480, FPS_30); + ddev_control(usb_hdl, UCMD_UVC_SET_PARAM, ¶m); +#endif + + process_start(&fuvc_test, NULL); + +init_error: + return; +} + +void fuvc_notify_uvc_configed(void) +{ + process_post(&fuvc_test, PROCESS_EVENT_MSG, NULL); +} + +void fuvc_fiddle_rx_vs(void) +{ + process_post(&fuvc_test, PROCESS_EVENT_POLL, NULL); +} + +PROCESS_THREAD(fuvc_test, ev, data) +{ + UINT32 status; + static DD_HANDLE usb_hdl; + + PROCESS_BEGIN(); + + while(51) + { + usb_hdl = ddev_open(USB_DEV_NAME, &status, 0); + ASSERT(DD_HANDLE_UNVALID != usb_hdl); + + PROCESS_WAIT_EVENT(); + + if(PROCESS_EVENT_MSG == ev) + { +#ifdef UVC_DEMO_SUPPORT102 + UINT32 param; + + ddev_control(usb_hdl, UCMD_UVC_ENABLE_H264, 0); + param = UVC_MUX_PARAM(UVC_FRAME_640_480, FPS_30); + ddev_control(usb_hdl, UCMD_UVC_SET_PARAM, ¶m); +#endif + + ddev_control(usb_hdl, UCMD_UVC_START_STREAM, 0); + } + else if(PROCESS_EVENT_POLL == ev) + { + ddev_control(usb_hdl, UCMD_UVC_RECEIVE_VSTREAM, 0); + } + else if(PROCESS_EVENT_EXIT == ev) + { + ddev_close(usb_hdl); + usb_hdl = 0; + } + else + { + } + } + + PROCESS_END(); +} + +#endif // FUVC_TEST +#endif // CFG_USB + +// eof + diff --git a/beken_os/beken378/func/usb/fusb.h b/beken_os/beken378/func/usb/fusb.h new file mode 100755 index 0000000..852c24f --- /dev/null +++ b/beken_os/beken378/func/usb/fusb.h @@ -0,0 +1,27 @@ +#ifndef _FUSB_H_ +#define _FUSB_H_ + +#define FUSB_DEBUG + +#ifdef FUSB_DEBUG +#define FUSB_PRT os_printf +#define FUSB_WARN warning_prf +#define FUSB_FATAL fatal_prf +#else +#define FUSB_PRT null_prf +#define FUSB_WARN null_prf +#define FUSB_FATAL null_prf +#endif + +#ifdef FMSC_TEST +extern void fmsc_test_init(void); +extern void fmsc_fiddle_process(void); +#elif defined(FUVC_TEST) +extern void fuvc_test_init(uint8_t); +extern void fuvc_notify_uvc_configed(void); +extern void fuvc_fiddle_rx_vs(void); +#endif + +#endif +// eof + diff --git a/beken_os/beken378/func/user_driver/BkDriverAdc.h b/beken_os/beken378/func/user_driver/BkDriverAdc.h new file mode 100755 index 0000000..a5c25df --- /dev/null +++ b/beken_os/beken378/func/user_driver/BkDriverAdc.h @@ -0,0 +1,126 @@ +/** + ****************************************************************************** + * @file BkDriverAdc.h + * @brief This file provides all the headers of ADC operation functions. + ****************************************************************************** + * + * The MIT License + * Copyright (c) 2017 BEKEN Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR + * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + ****************************************************************************** + */ + +#ifndef __BEKENDRIVERADC_H__ +#define __BEKENDRIVERADC_H__ + +#pragma once +#include "include.h" + +/** @addtogroup BK_PLATFORM +* @{ +*/ + +/** @defgroup BK_ADC _BK_ ADC Driver + * @brief Analog to Digital Converter (ADC) Functions + * @{ + */ + +/****************************************************** + * Macros + ******************************************************/ + +/****************************************************** + * Enumerations + ******************************************************/ + +/****************************************************** + * Type Definitions + ******************************************************/ + +/****************************************************** + * Structures + ******************************************************/ + +/****************************************************** + * Variables + ******************************************************/ + +/****************************************************** + * Function Declarations + ******************************************************/ + +/**@biref Initialises an ADC interface + * + * Prepares an ADC hardware interface for sampling + * + * @param adc : the interface which should be initialised + * @param sampling_cycle : sampling period in number of ADC clock cycles. If the + * MCU does not support the value provided, the closest + * supported value is used. + * + * @return kNoErr : on success. + * @return kGeneralErr : if an error occurred with any step + */ +OSStatus BkAdcInitialize( bk_adc_t adc, uint32_t sampling_cycle ); + + +/**@biref Takes a single sample from an ADC interface + * + * Takes a single sample from an ADC interface + * + * @param adc : the interface which should be sampled + * @param output : pointer to a variable which will receive the sample + * + * @return kNoErr : on success. + * @return kGeneralErr : if an error occurred with any step + */ +OSStatus BkAdcTakeSample( bk_adc_t adc, uint16_t *output ); + + +/**@biref Takes multiple samples from an ADC interface + * + * Takes multiple samples from an ADC interface and stores them in + * a memory buffer + * + * @param adc : the interface which should be sampled + * @param buffer : a memory buffer which will receive the samples + * Each sample will be uint16_t little endian. + * @param buffer_length : length in bytes of the memory buffer. + * + * + * @return kNoErr : on success. + * @return kGeneralErr : if an error occurred with any step + */ +OSStatus BkAdcTakeSampleStreram( bk_adc_t adc, void *buffer, uint16_t buffer_length ); + + +/**@biref De-initialises an ADC interface + * + * @abstract Turns off an ADC hardware interface + * + * @param adc : the interface which should be de-initialised + * + * @return kNoErr : on success. + * @return kGeneralErr : if an error occurred with any step + */ +OSStatus BkAdcFinalize( bk_adc_t adc ); + +/** @} */ +/** @} */ +#endif diff --git a/beken_os/beken378/func/user_driver/BkDriverFlash.c b/beken_os/beken378/func/user_driver/BkDriverFlash.c new file mode 100755 index 0000000..c7bdbb6 --- /dev/null +++ b/beken_os/beken378/func/user_driver/BkDriverFlash.c @@ -0,0 +1,381 @@ +/** + ****************************************************************************** + * @file BkDriverFlash.h + * @brief This file provides all the headers of Flash operation functions. + ****************************************************************************** + * + * The MIT License + * Copyright (c) 2017 BEKEN Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR + * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + ****************************************************************************** + */ +#include "include.h" +#include "rtos_pub.h" +#include "BkDriverFlash.h" +#include "flash_pub.h" +#include "drv_model_pub.h" +#include "rtos_error.h" +#include "uart_pub.h" +#include "mem_pub.h" + +static beken_mutex_t hal_flash_mutex; + +/* Logic partition on flash devices */ +const bk_logic_partition_t bk7231_partitions[BK_PARTITION_MAX] = +{ + [BK_PARTITION_BOOTLOADER] = + { + .partition_owner = BK_FLASH_EMBEDDED, + .partition_description = "Bootloader", + .partition_start_addr = 0x00000000, + .partition_length = 0x11000,//68KB + .partition_options = PAR_OPT_READ_EN | PAR_OPT_WRITE_DIS, + }, + [BK_PARTITION_APPLICATION] = + { + .partition_owner = BK_FLASH_EMBEDDED, + .partition_description = "Application", + .partition_start_addr = 0x11000, + .partition_length = 0x121000,//1156KB + .partition_options = PAR_OPT_READ_EN | PAR_OPT_WRITE_DIS, + }, + [BK_PARTITION_OTA] = + { + .partition_owner = BK_FLASH_EMBEDDED, + .partition_description = "ota", + .partition_start_addr = 0x12A000, + .partition_length = 0xA6000, //664KB + .partition_options = PAR_OPT_READ_EN | PAR_OPT_WRITE_DIS, + }, + [BK_PARTITION_RF_FIRMWARE] = + { + .partition_owner = BK_FLASH_EMBEDDED, + .partition_description = "RF Firmware", + .partition_start_addr = 0x1D0000,// for rf related info + .partition_length = 0x1000, + .partition_options = PAR_OPT_READ_EN | PAR_OPT_WRITE_DIS, + }, + [BK_PARTITION_NET_PARAM] = + { + .partition_owner = BK_FLASH_EMBEDDED, + .partition_description = "NET info", + .partition_start_addr = 0x1D1000,// for net related info + .partition_length = 0x1000, + .partition_options = PAR_OPT_READ_EN | PAR_OPT_WRITE_DIS, + } +}; + +static void BkFlashPartitionAssert( bk_partition_t inPartition ) +{ + ASSERT(BK_PARTITION_BOOTLOADER < BK_PARTITION_MAX); +} + +static uint32_t BkFlashPartitionIsValid( bk_partition_t inPartition ) +{ + if((inPartition >= BK_PARTITION_BOOTLOADER)&&(inPartition < BK_PARTITION_MAX)) + { + return 1; + } + else + { + return 0; + } +} + +bk_logic_partition_t *bk_flash_get_info( bk_partition_t inPartition ) +{ + bk_logic_partition_t *pt = NULL; + + BkFlashPartitionAssert(inPartition); + + if(BkFlashPartitionIsValid(inPartition)) + { + pt = (bk_logic_partition_t *)&bk7231_partitions[inPartition]; + } + else + pt = NULL; + return pt; +} + +OSStatus BkFlashInit(void) +{ + return 0; +} + +OSStatus BkFlashUninit(void) +{ + return 0; +} + +OSStatus bk_flash_erase(bk_partition_t inPartition, uint32_t off_set, uint32_t size) +{ + uint32_t i; + uint32_t param; + UINT32 status; + DD_HANDLE flash_hdl; + uint32_t start_sector, end_sector; + bk_logic_partition_t *partition_info; + GLOBAL_INT_DECLARATION(); + + partition_info = bk_flash_get_info(inPartition); + start_sector = off_set >> 12; + end_sector = (off_set + size - 1) >> 12; + + flash_hdl = ddev_open(FLASH_DEV_NAME, &status, 0); + ASSERT(DD_HANDLE_UNVALID != flash_hdl); + for(i = start_sector; i <= end_sector; i ++) + { + param = partition_info->partition_start_addr + (i << 12); + GLOBAL_INT_DISABLE(); + ddev_control(flash_hdl, CMD_FLASH_ERASE_SECTOR, (void *)¶m); + GLOBAL_INT_RESTORE(); + } + + return kNoErr; +} + +OSStatus bk_flash_write( bk_partition_t inPartition, volatile uint32_t off_set, uint8_t *inBuffer , uint32_t inBufferLength) +{ + UINT32 status; + DD_HANDLE flash_hdl; + uint32_t start_addr; + bk_logic_partition_t *partition_info; + GLOBAL_INT_DECLARATION(); + + if (NULL == inBuffer) + { + os_printf("%s inBuffer=NULL\r\n", __FUNCTION__); + return kParamErr; + } + + partition_info = bk_flash_get_info(inPartition); + if (NULL == partition_info) + { + os_printf("%s partiion not found\r\n", __FUNCTION__); + return kNotFoundErr; + } + + start_addr = partition_info->partition_start_addr + off_set; + + flash_hdl = ddev_open(FLASH_DEV_NAME, &status, 0); + if (DD_HANDLE_UNVALID == flash_hdl) + { + os_printf("%s open failed\r\n", __FUNCTION__); + return kOpenErr; + } + + GLOBAL_INT_DISABLE(); + ddev_write(flash_hdl, (char*)inBuffer, inBufferLength, start_addr); + GLOBAL_INT_RESTORE(); + + return kNoErr; +} + +OSStatus bk_flash_read( bk_partition_t inPartition, volatile uint32_t off_set, uint8_t *outBuffer, uint32_t inBufferLength) +{ + UINT32 status; + uint32_t start_addr; + DD_HANDLE flash_hdl; + bk_logic_partition_t *partition_info; + GLOBAL_INT_DECLARATION(); + + if (NULL == outBuffer) + { + os_printf("%s outBuffer=NULL\r\n", __FUNCTION__); + return kParamErr; + } + + partition_info = bk_flash_get_info(inPartition); + if (NULL == partition_info) + { + os_printf("%s partiion not found\r\n", __FUNCTION__); + return kNotFoundErr; + } + + start_addr = partition_info->partition_start_addr + off_set; + + flash_hdl = ddev_open(FLASH_DEV_NAME, &status, 0); + if (DD_HANDLE_UNVALID == flash_hdl) + { + os_printf("%s open failed\r\n", __FUNCTION__); + return kOpenErr; + } + + GLOBAL_INT_DISABLE(); + ddev_read(flash_hdl, (char*)outBuffer, inBufferLength, start_addr); + GLOBAL_INT_RESTORE(); + + return kNoErr; +} + +OSStatus bk_flash_enable_security(PROTECT_TYPE type ) +{ + DD_HANDLE flash_hdl; + UINT32 status; + uint32_t param = type; + + flash_hdl = ddev_open(FLASH_DEV_NAME, &status, 0); + if (DD_HANDLE_UNVALID == flash_hdl) + { + os_printf("%s open failed\r\n", __FUNCTION__); + return kOpenErr; + } + ddev_control(flash_hdl, CMD_FLASH_SET_PROTECT, (void *)¶m); + + return kNoErr; +} + + +OSStatus test_flash_write(volatile uint32_t start_addr, uint32_t len) +{ + UINT32 status; + DD_HANDLE flash_hdl; + uint32_t i; + u8 buf[256]; + uint32_t addr = start_addr; + uint32_t length = len; + uint32_t tmp = addr + length; + + for(i=0;i<256;i++) + buf[i]=i; + + flash_hdl = ddev_open(FLASH_DEV_NAME, &status, 0); + ASSERT(DD_HANDLE_UNVALID != flash_hdl); + for(;addr +#include "include.h" +#include "rtos_pub.h" +#include "BkDriverPwm.h" +#include "drv_model_pub.h" +#include "rtos_error.h" +#include "pwm_pub.h" +#include "uart_pub.h" + +#if (CFG_SOC_NAME != SOC_BK7231N) +OSStatus bk_pwm_initialize(bk_pwm_t pwm, uint32_t frequency, uint32_t duty_cycle) +{ + UINT32 ret; + pwm_param_t param; + + /*init pwm*/ + param.channel = (uint8_t)pwm; + + param.cfg.bits.en = PWM_INT_DIS; + param.cfg.bits.int_en = PWM_INT_DIS;//PWM_INT_EN; + + param.cfg.bits.mode = PWM_PWM_MODE; + param.cfg.bits.clk = PWM_CLK_26M; + param.p_Int_Handler = 0; + param.duty_cycle = duty_cycle; + param.end_value = frequency; // ????? + + ret = sddev_control(PWM_DEV_NAME, CMD_PWM_INIT_PARAM, ¶m); + ASSERT(PWM_SUCCESS == ret); + return kNoErr; +} + +OSStatus bk_pwm_update_param(bk_pwm_t pwm, uint32_t frequency, uint32_t duty_cycle) +{ + UINT32 ret; + pwm_param_t param; + + /*init pwm*/ + param.channel = (uint8_t)pwm; + param.cfg.bits.en = PWM_INT_EN; + param.cfg.bits.int_en = PWM_INT_DIS;//PWM_INT_EN; + param.cfg.bits.mode = PWM_PWM_MODE; + param.cfg.bits.clk = PWM_CLK_26M; + param.p_Int_Handler = 0; + param.duty_cycle = duty_cycle; + param.end_value = frequency; // ????? + + ret = sddev_control(PWM_DEV_NAME, CMD_PWM_INIT_PARAM, ¶m); + ASSERT(PWM_SUCCESS == ret); + + return kNoErr; +} + +OSStatus bk_pwm_capture_initialize(bk_pwm_t pwm, uint8_t cap_mode) +{ + UINT32 ret; + pwm_param_t param; + + /*init pwm*/ + param.channel = (uint8_t)pwm; + param.cfg.bits.en = PWM_INT_EN; + param.cfg.bits.int_en = PWM_INT_EN; + + param.cfg.bits.clk = PWM_CLK_26M; + param.p_Int_Handler = 0; + param.duty_cycle = 0; + param.end_value = 0; + if(cap_mode == 0x01) + { + param.cfg.bits.mode = PWM_CAP_POS_MODE; + } + else if(cap_mode == 0x02) + { + param.cfg.bits.mode = PWM_CAP_NEG_MODE; + } + else + { + param.cfg.bits.mode = PWM_PWM_MODE; + } + + ret = sddev_control(PWM_DEV_NAME, CMD_PWM_INIT_PARAM, ¶m); + ASSERT(PWM_SUCCESS == ret); + + return kNoErr; +} + +#else +#include "pwm_new.h" + +OSStatus bk_pwm_initialize(bk_pwm_t pwm, uint32_t count, uint32_t duty_cycle1,uint32_t duty_cycle2,uint32_t duty_cycle3) +{ + UINT32 ret; + pwm_param_t param; + + /*init pwm*/ + param.channel = (uint8_t)pwm; + param.cfg.bits.int_en = PWM_INT_DIS; + param.cfg.bits.mode = PWM_PWM_MODE; + param.cfg.bits.clk = PWM_CLK_26M; + param.p_Int_Handler = 0; + param.duty_cycle1 = duty_cycle1; + param.duty_cycle2 = duty_cycle2; + param.duty_cycle3 = duty_cycle3; + param.end_value = count; + + if(!duty_cycle1) { + bk_pwm_initlevl_set_low(pwm); + } else { + bk_pwm_initlevl_set_high(pwm); + } + + os_null_printf("bk pwm initial:mode = %x\r\n",param.cfg.val); + os_null_printf("bk pwm initial:duty_cycle1 = %x\r\n",duty_cycle1); + ret = sddev_control(PWM_DEV_NAME, CMD_PWM_INIT_PARAM, ¶m); + ASSERT(PWM_SUCCESS == ret); + + return kNoErr; +} + +OSStatus bk_pwm_capture_initialize(bk_pwm_t pwm, uint8_t cap_mode) +{ + UINT32 ret; + pwm_param_t param; + + /*init pwm*/ + param.channel = (uint8_t)pwm; + param.cfg.bits.int_en = PWM_INT_EN; + param.cfg.bits.clk = PWM_CLK_26M; + param.p_Int_Handler = 0; + param.duty_cycle1 = 0; + param.duty_cycle2 = 0; + param.duty_cycle3 = 0; + param.end_value = 0; + param.cfg.bits.mode = cap_mode; + + ret = sddev_control(PWM_DEV_NAME, CMD_PWM_INIT_PARAM, ¶m); + ASSERT(PWM_SUCCESS == ret); + + return kNoErr; +} +#endif + + +OSStatus bk_pwm_start(bk_pwm_t pwm) +{ + UINT32 ret; + UINT32 param; + + param = pwm; + + ret = sddev_control(PWM_DEV_NAME, CMD_PWM_UNIT_ENABLE, ¶m); + ASSERT(PWM_SUCCESS == ret); + + return kNoErr; +} + +OSStatus bk_pwm_stop(bk_pwm_t pwm) +{ + UINT32 ret; + UINT32 param; + + param = pwm; + ret = sddev_control(PWM_DEV_NAME, CMD_PWM_UNIT_DISABLE, ¶m); + ASSERT(PWM_SUCCESS == ret); + + return kNoErr; +} + +#if (CFG_SOC_NAME == SOC_BK7231N) + +static UINT8 group_flag=0; +static UINT8 pwm1_set_high_flag=0; +static UINT8 pwm2_set_low_flag=0; + +OSStatus bk_pwm_group_initialize(bk_pwm_t pwm1, bk_pwm_t pwm2,uint32_t frequency, uint32_t duty_cycle1,uint32_t duty_cycle2,uint32_t dead_band) +{ + pwm_param_t param; + if(pwm1 >= pwm2) + { + warning_prf("pwm channel:%d error\r\n", pwm2); + return kParamErr; + } + + /*init pwm1*/ + param.channel = pwm1 ; + param.cfg.bits.int_en = PWM_INT_DIS; + param.cfg.bits.mode = PWM_PWM_MODE; + param.cfg.bits.clk = PWM_CLK_26M; + param.p_Int_Handler = 0; + param.duty_cycle1 = frequency -duty_cycle1-dead_band; + param.duty_cycle2 = frequency - dead_band; + param.duty_cycle3 = 0; + param.end_value = frequency; + + init_pwm_param(¶m, 1); + pwm_init_levl_set_low(pwm1); + + /*init pwm2*/ + param.channel = pwm2 ; + param.cfg.bits.int_en = PWM_INT_DIS; + param.cfg.bits.mode = PWM_PWM_MODE; + param.cfg.bits.clk = PWM_CLK_26M; + param.p_Int_Handler = 0; + param.duty_cycle1 = duty_cycle1; + param.duty_cycle2 = frequency; + param.duty_cycle3 = 0; + param.end_value = frequency; + + init_pwm_param(¶m, 1); + pwm_init_levl_set_high(pwm2); + + if((pwm1+1) == pwm2) + { + //grounp enable + pwm_group_mode_enable(pwm1); + } + else + { + pwm_unit_enable(pwm1); + pwm_unit_enable(pwm2); + } + + return kNoErr; +} + +OSStatus bk_pwm_update_param(bk_pwm_t pwm, uint32_t frequency, uint32_t duty_cycle1, uint32_t duty_cycle2, uint32_t duty_cycle3) +{ + UINT32 ret; + UINT32 init_level = 0; + pwm_param_t param; + + param.channel = (uint8_t)pwm; + param.duty_cycle1 = duty_cycle1; + param.duty_cycle2 = duty_cycle2; + param.duty_cycle3 = duty_cycle3; + param.end_value = frequency; + + + if(!duty_cycle1) { + init_level = 0; + } else { + init_level = 1; + + } + + ret = sddev_control(PWM_DEV_NAME, CMD_PWM_SINGLE_UPDATA_PARAM, ¶m); + + pwm_single_update_param_enable(pwm,init_level); + (void)ret; + + return kNoErr; +} + +OSStatus bk_pwm_group_mode_enable(bk_pwm_t pwm) +{ + UINT32 ret; + UINT32 param; + + param = pwm; + ret = sddev_control(PWM_DEV_NAME, CMD_PWM_GROUP_ENABLE, ¶m); + ASSERT(PWM_SUCCESS == ret); + + return kNoErr; +} + +OSStatus bk_pwm_group_mode_disable(bk_pwm_t pwm) +{ + UINT32 ret; + UINT32 param; + + param = pwm; + ret = sddev_control(PWM_DEV_NAME, CMD_PWM_GROUP_DISABLE, ¶m); + ASSERT(PWM_SUCCESS == ret); + + return kNoErr; +} + +OSStatus bk_pwm_initlevl_set_low(bk_pwm_t pwm) +{ + UINT32 ret; + UINT32 param; + + param = pwm; + ret = sddev_control(PWM_DEV_NAME, CMD_PWM_INIT_LEVL_SET_LOW, ¶m); + ASSERT(PWM_SUCCESS == ret); + + return kNoErr; +} + +OSStatus bk_pwm_initlevl_set_high(bk_pwm_t pwm) +{ + UINT32 ret; + UINT32 param; + + param = pwm; + ret = sddev_control(PWM_DEV_NAME, CMD_PWM_INIT_LEVL_SET_HIGH, ¶m); + ASSERT(PWM_SUCCESS == ret); + + return kNoErr; +} + +OSStatus bk_pwm_set_isr_callback(bk_pwm_t pwm, pwm_isr_cb callback) +{ + UINT32 ret; + pwm_int_cfg_t param; + + param.channel = pwm; + param.p_Int_Handler = (PFUNC)callback; + + ret = sddev_control(PWM_DEV_NAME, CMD_PWM_SET_IR_CALLBACK, ¶m); + ASSERT(PWM_SUCCESS == ret); + + return kNoErr; +} + +OSStatus bk_pwm_en_isr_callback(bk_pwm_t pwm) +{ + UINT32 ret; + pwm_int_cfg_t param; + + param.channel = pwm; + param.p_Int_Handler = NULL; + + ret = sddev_control(PWM_DEV_NAME, CMD_PWM_IR_ENABLE, ¶m); + ASSERT(PWM_SUCCESS == ret); + + return kNoErr; +} + +OSStatus bk_pwm_dis_isr_callback(bk_pwm_t pwm) +{ + UINT32 ret; + pwm_int_cfg_t param; + + param.channel = pwm; + param.p_Int_Handler = NULL; + + ret = sddev_control(PWM_DEV_NAME, CMD_PWM_IR_DISABLE, ¶m); + ASSERT(PWM_SUCCESS == ret); + + return kNoErr; +} + +UINT32 bk_pwm_get_capvalue(bk_pwm_t pwm) +{ + UINT32 ret; + + pwm_capture_t pwm_cap; + + pwm_cap.ucChannel = pwm; + + ret = sddev_control(PWM_DEV_NAME, CMD_PWM_CAP_GET, (VOID *)&pwm_cap); + ASSERT(PWM_SUCCESS == ret); + + return pwm_cap.value; +} + +OSStatus bk_pwm_cw_initialize(bk_pwm_t pwm1, bk_pwm_t pwm2,uint32_t count, uint32_t duty_cycle1,uint32_t duty_cycle2, uint32_t dead_band) +{ + pwm_param_t param; + + if(count < (duty_cycle1 + duty_cycle2 + 2*dead_band)) + { + bk_printf("pwm param set error:freq:%x ,cycle1:%x,cycle2:%x,dead_band:%x\r\n", count, duty_cycle1, duty_cycle2, dead_band); + return -1; + } + + memset(¶m, 0, sizeof(pwm_param_t)); + + group_flag = pwm_check_group(pwm1, pwm2); + + /*init pwm1*/ + param.channel = (UINT8)pwm1 ; + param.cfg.bits.int_en = PWM_INT_DIS; + param.cfg.bits.mode = PWM_PWM_MODE; + param.cfg.bits.clk = PWM_CLK_26M; + param.p_Int_Handler = 0; + if (0 == duty_cycle1) { + param.duty_cycle1 = 0; + param.duty_cycle2 = 0; + } else { + param.duty_cycle1 = count - duty_cycle1- dead_band; + param.duty_cycle2 = count - dead_band; + } + param.duty_cycle3 = 0; + param.end_value = count; + + init_pwm_param(¶m, 1); + pwm_init_levl_set_low(pwm1); + + /*init pwm2*/ + param.channel = pwm2 ; + param.cfg.bits.int_en = PWM_INT_DIS; + param.cfg.bits.mode = PWM_PWM_MODE; + param.cfg.bits.clk = PWM_CLK_26M; + param.p_Int_Handler = 0; + param.duty_cycle1 = duty_cycle2; + param.duty_cycle2 = count; + param.duty_cycle3 = 0; + param.end_value = count; + + init_pwm_param(¶m, 1); + + if(duty_cycle2 ==0) + { + pwm2_set_low_flag = 1; + bk_pwm_initlevl_set_low(pwm2); + + } + else + { + pwm2_set_low_flag = 0; + pwm_init_levl_set_high(pwm2); + } + + if(duty_cycle1 ==count) + { + pwm1_set_high_flag = 1; + bk_pwm_initlevl_set_high(pwm1); + + } + else + { + pwm1_set_high_flag = 0; + pwm_init_levl_set_low(pwm1); + } + + return kNoErr; +} + +OSStatus bk_pwm_cw_start(bk_pwm_t pwm1, bk_pwm_t pwm2) +{ + if(group_flag == 1) + { + //grounp enable + pwm_group_mode_enable(pwm1); + } + else + { + pwm_unit_enable(pwm1); + pwm_unit_enable(pwm2); + } + + return kNoErr; +} + +OSStatus bk_pwm_cw_stop(bk_pwm_t pwm1, bk_pwm_t pwm2) +{ + if(group_flag == 1) + { + //grounp enable + pwm_group_mode_disable(pwm1); + } + else + { + pwm_unit_disable(pwm1); + pwm_unit_disable(pwm2); + } + + return kNoErr; +} + +OSStatus bk_pwm_cw_update_param(bk_pwm_t pwm1, bk_pwm_t pwm2,uint32_t count, uint32_t duty_cycle1,uint32_t duty_cycle2, uint32_t dead_band) +{ + UINT32 ret = 0; + pwm_param_t param; + + if(count < (duty_cycle1 + duty_cycle2 + 2*dead_band)) + { + bk_printf("pwm param set error:freq:%x ,cycle1:%x,cycle2:%x,dead_band:%x\r\n", count, duty_cycle1, duty_cycle2, dead_band); + return -1; + } + + if(duty_cycle2 <= 0) + { + duty_cycle2 = 0; + } + + if(duty_cycle1 <= 0) + { + duty_cycle1 = 0; + dead_band = 0; + } + + //bk_printf("pwm channel :%d :freq:%x ,cycle1:%x,cycle2:%x,dead_band:%x\r\n",pwm1,frequency, duty_cycle1, duty_cycle2, dead_band); + group_flag = pwm_check_group(pwm1, pwm2); + + /*init pwm1*/ + param.channel = pwm1 ; + param.duty_cycle1 = count - duty_cycle1 - dead_band; + param.duty_cycle2 = count - dead_band; + param.duty_cycle3 = 0; + param.end_value = count; + + ret = sddev_control(PWM_DEV_NAME, CMD_PWM_UPDATA_PARAM, ¶m); + + /*init pwm2*/ + param.channel = pwm2 ; + param.duty_cycle1 = duty_cycle2; + param.duty_cycle2 = count; + param.duty_cycle3 = 0; + param.end_value = count; + + ret = sddev_control(PWM_DEV_NAME, CMD_PWM_UPDATA_PARAM, ¶m); + + if(pwm1_set_high_flag == 1) + { + if(duty_cycle1 == count) + { + pwm1_set_high_flag = 1; + param.init_level0 = 1; + } + else + { + pwm1_set_high_flag = 0; + param.init_level0 = 0; + } + } + + if(pwm2_set_low_flag == 1) + { + if(duty_cycle2 == 0) + { + pwm2_set_low_flag = 1; + param.init_level1 = 0 ; + } + else + { + pwm2_set_low_flag=0; + param.init_level1 = 1 ; + } + } + + if(duty_cycle2 == 0) + { + if(pwm_init_levl_get(pwm2) == 1) + { + pwm2_set_low_flag = 1; + param.init_level1 = 0 ; + } + } + else + { + param.init_level1 = 1 ; + } + + if(duty_cycle1 == count) + { + if(pwm_init_levl_get(pwm1) == 0) + { + pwm1_set_high_flag = 1; + param.init_level0 = 1; + } + } + else + { + param.init_level0 = 0; + } + + if(group_flag) + { + pwm_group_update_param_enable(pwm1, pwm2, ¶m); + } + else + { + pwm_nogroup_update_param_enable(pwm1, pwm2, ¶m); + } + + return ret; +} + +#endif +// eof + diff --git a/beken_os/beken378/func/user_driver/BkDriverPwm.h b/beken_os/beken378/func/user_driver/BkDriverPwm.h new file mode 100755 index 0000000..31cfcef --- /dev/null +++ b/beken_os/beken378/func/user_driver/BkDriverPwm.h @@ -0,0 +1,279 @@ +/** + ****************************************************************************** + * @file BkDriverPwm.h + * @brief This file provides all the headers of PWM operation functions. + ****************************************************************************** + * + * The MIT License + * Copyright (c) 2017 BEKEN Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR + * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + ****************************************************************************** + */ + +#ifndef __BEKENDRIVERPWM_H__ +#define __BEKENDRIVERPWM_H__ + +#pragma once +#include "include.h" +#include "rtos_pub.h" + +/** @addtogroup BK_PLATFORM + * @{ + */ + +/** @defgroup BK_PWM _BK_ PWM Driver + * @brief Pulse-Width Modulation (PWM) Functions + * @{ + */ + +/****************************************************** + * Enumerations + ******************************************************/ +typedef enum +{ + BK_PWM_0, + BK_PWM_1, + BK_PWM_2, + BK_PWM_3, + BK_PWM_4, + BK_PWM_5, + BK_PWM_MAX, /* Denotes the total number of PWM port aliases. Not a valid PWM alias */ + BK_PWM_NONE, +} bk_pwm_t; + +/****************************************************** + * Type Definitions + ******************************************************/ +typedef void (*pwm_isr_cb)(uint8_t); + +/****************************************************** +* Function Declarations +******************************************************/ + + +#if (CFG_SOC_NAME != SOC_BK7231N) +/**@brief Initialises a PWM pin + * + * @note Prepares a Pulse-Width Modulation pin for use. + * Does not start the PWM output (use @ref bk_pwm_start). + * + * @param pwm : the PWM interface which should be initialised + * @param frequency : Output signal frequency in Hertz + * @param duty_cycle : Duty cycle of signal as a floating-point percentage (0.0 to 100.0) + * + * @return kNoErr : on success. + * @return kGeneralErr : if an error occurred with any step + */ +OSStatus bk_pwm_initialize(bk_pwm_t pwm, uint32_t frequency, uint32_t duty_cycle); + +OSStatus bk_pwm_capture_initialize(bk_pwm_t pwm, uint8_t cap_mode); + +#else +/**@brief Initialises a PWM pin + * + * @note Prepares a Pulse-Width Modulation pin for use. + * Does not start the PWM output (use @ref bk_pwm_start). + * + * @param pwm : the PWM interface which should be initialised + * @param count : Output signal counter to turn + * @param duty_cycle1 : Set pwm first level reversal time + * @param duty_cycle2 : Set pwm 2nd level reversal time + * @param duty_cycle3 : Set pwm 3th level reversal time + + * @return kNoErr : on success. + * @return kGeneralErr : if an error occurred with any step + */ + +OSStatus bk_pwm_initialize(bk_pwm_t pwm, uint32_t count, uint32_t duty_cycle1,uint32_t duty_cycle2,uint32_t duty_cycle3); + + +OSStatus bk_pwm_capture_initialize(bk_pwm_t pwm, uint8_t cap_mode); + +#endif + +/**@brief Starts PWM output on a PWM interface + * + * @note Starts Pulse-Width Modulation signal output on a PWM pin + * + * @param pwm : the PWM interface which should be started + * + * @return kNoErr : on success. + * @return kGeneralErr : if an error occurred with any step + */ +OSStatus bk_pwm_start(bk_pwm_t pwm); + + +/**@brief Stops output on a PWM pin + * + * @note Stops Pulse-Width Modulation signal output on a PWM pin + * + * @param pwm : the PWM interface which should be stopped + * + * @return kNoErr : on success. + * @return kGeneralErr : if an error occurred with any step + */ +OSStatus bk_pwm_stop(bk_pwm_t pwm); + + +/**@brief Initialises a PWM pin + * + * @note Update pwm cycle and duty_cycle when pwm working. + * + * @param pwm : the PWM interface which should be initialised + * @param frequency : Output signal frequency in Hertz + * @param duty_cycle1 : Set pwm first level reversal time + * @param duty_cycle2 : Set pwm 2nd level reversal time + * @param duty_cycle3 : Set pwm 3th level reversal time + + * @return kNoErr : on success. + * @return kGeneralErr : if an error occurred with any step + */ + + +#if (CFG_SOC_NAME == SOC_BK7231N) + +/**@brief Set PWM as group output + * + * @note Start pwm group mode ,pwm0/1 pwm2/3 pwm4/5 + * + * @param pwm1 : the PWM1 interface which should be started + * @param pwm2 : the PWM2 interface which should be started + * @param frequency : pwm frequency + * @param duty_cycle1 : set first level change time + * @param duty_cycle2 : set 2nd level change time + * @param dead_band : set pwm grounp dead band time + * + * @return kNoErr : on success. + * @return kGeneralErr : if an error occurred with any step + */ + +OSStatus bk_pwm_group_initialize(bk_pwm_t pwm1, bk_pwm_t pwm2, uint32_t frequency, uint32_t duty_cycle1,uint32_t duty_cycle2, uint32_t dead_band); + +OSStatus bk_pwm_update_param(bk_pwm_t pwm, uint32_t frequency, uint32_t duty_cycle1, uint32_t duty_cycle2, uint32_t duty_cycle3); + + +/**@brief Starts PWM output on a PWM interface + * + * @note Start pwm group mode ,when set pwm0 pwm0/pwm1 as a group output-levl:pwm0:high pwm1-low + * + * @param pwm : the PWM interface which should be started + * + * @return kNoErr : on success. + * @return kGeneralErr : if an error occurred with any step + */ +OSStatus bk_pwm_group_mode_enable(bk_pwm_t pwm); + + + +/**@brief Starts PWM output on a PWM interface + * + * @note Disable pwm group mode + * + * @param pwm : the PWM interface which should be started + * + * @return kNoErr : on success. + * @return kGeneralErr : if an error occurred with any step + */ +OSStatus bk_pwm_group_mode_disable(bk_pwm_t pwm); + + + +/**@brief Starts PWM output on a PWM interface + * + * @note Set pwm init output level as low + * + * @param pwm : the PWM interface which should be started + * + * @return kNoErr : on success. + * @return kGeneralErr : if an error occurred with any step + */ +OSStatus bk_pwm_initlevl_set_low(bk_pwm_t pwm); + + + +/**@brief Set PWM interrupt a PWM interface + * + * @note register isr callback + * + * @param pwm : the PWM interface which should be set + * @param callback : the isr callback + * + * @return kNoErr : on success. + * @return kGeneralErr : if an error occurred with any step + */ +OSStatus bk_pwm_set_isr_callback(bk_pwm_t pwm, pwm_isr_cb callback); + + + +/**@brief Set PWM interrupt a PWM interface + * + * @note enable PWM interrupt and isr callback + * + * @param pwm : the PWM interface which should be set + * + * @return kNoErr : on success. + * @return kGeneralErr : if an error occurred with any step + */ +OSStatus bk_pwm_en_isr_callback(bk_pwm_t pwm); + + + +/**@brief Set PWM interrupt a PWM interface + * + * @note disable PWM interrupt and isr callback + * + * @param pwm : the PWM interface which should be set + * + * @return kNoErr : on success. + * @return kGeneralErr : if an error occurred with any step + */ +OSStatus bk_pwm_dis_isr_callback(bk_pwm_t pwm); + + + +/**@brief Starts PWM output on a PWM interface + * + * @note Set pwm init output level as high + * + * @param pwm : the PWM interface which should be started + * + * @return kNoErr : on success. + * @return kGeneralErr : if an error occurred with any step + */ +OSStatus bk_pwm_initlevl_set_high(bk_pwm_t pwm); + +UINT32 bk_pwm_get_capvalue(bk_pwm_t pwm); + +OSStatus bk_pwm_cw_initialize(bk_pwm_t pwm1, bk_pwm_t pwm2,uint32_t count, uint32_t duty_cycle1, uint32_t duty_cycle, uint32_t dead_band); + +OSStatus bk_pwm_cw_start(bk_pwm_t pwm1, bk_pwm_t pwm2); + +OSStatus bk_pwm_cw_stop(bk_pwm_t pwm1, bk_pwm_t pwm2); + +OSStatus bk_pwm_cw_update_param(bk_pwm_t pwm1, bk_pwm_t pwm2,uint32_t count, uint32_t duty_cycle1, uint32_t duty_cycle, uint32_t dead_band); + +#endif + + + + +/** @} */ +/** @} */ + +#endif diff --git a/beken_os/beken378/func/user_driver/BkDriverRng.c b/beken_os/beken378/func/user_driver/BkDriverRng.c new file mode 100755 index 0000000..5fca17c --- /dev/null +++ b/beken_os/beken378/func/user_driver/BkDriverRng.c @@ -0,0 +1,67 @@ +/** + ****************************************************************************** + * @file BkDriverPwm.h + * @brief This file provides all the headers of PWM operation functions. + ****************************************************************************** + * + * The MIT License + * Copyright (c) 2017 BEKEN Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR + * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + ****************************************************************************** + */ +#include "include.h" +#include "rtos_pub.h" +#include "BkDriverRng.h" +#include "drv_model_pub.h" +#include "rtos_error.h" +#include "uart_pub.h" +#include "irda_pub.h" +#include + +int bk_rand(void) +{ + int i = 0; + + BkRandomNumberRead(&i, sizeof(i)); + return (i & RAND_MAX); +} + +OSStatus BkRandomNumberRead( void *inBuffer, int inByteCount ) +{ + uint32_t param = 0; + uint32_t len, i; + char *src, *dest; + + ASSERT(inBuffer); + sddev_control(IRDA_DEV_NAME, TRNG_CMD_GET, ¶m); + + src = (char *)¶m; + dest = (char *)inBuffer; + + len = MIN(inByteCount, sizeof(param)); + for(i = 0; i < len; i ++) + { + dest[i] = src[i]; + } + + return 0; +} + +// eof + diff --git a/beken_os/beken378/func/user_driver/BkDriverRng.h b/beken_os/beken378/func/user_driver/BkDriverRng.h new file mode 100755 index 0000000..d302f0b --- /dev/null +++ b/beken_os/beken378/func/user_driver/BkDriverRng.h @@ -0,0 +1,83 @@ +/** + ****************************************************************************** + * @file BkDriverRng.h + * @brief This file provides all the headers of RNG operation functions. + ****************************************************************************** + * + * The MIT License + * Copyright (c) 2017 BEKEN Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR + * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + ****************************************************************************** + */ + +#ifndef __BEKENDRIVERRNG_H__ +#define __BEKENDRIVERRNG_H__ + +#pragma once +#include "include.h" + +/** @addtogroup BK_PLATFORM +* @{ +*/ + +/** @defgroup BK_RNG _BK_ RNG Driver + * @brief Random Number Generater(RNG) Functions + * @{ + */ + +/****************************************************** + * Macros + ******************************************************/ + +#define PlatformRandomBytes BkRandomNumberRead /**< For API compatible with older version */ + +/****************************************************** + * Enumerations + ******************************************************/ + + +/****************************************************** + * Type Definitions + ******************************************************/ + +/****************************************************** +* Function Declarations +******************************************************/ + + + +/**@brief Fill in a memory buffer with random data + * + * @param inBuffer : Point to a valid memory buffer, this function will fill + in this memory with random numbers after executed + * @param inByteCount : Length of the memory buffer (bytes) + * + * @return kNoErr : on success. + * @return kGeneralErr : if an error occurred with any step + */ +OSStatus BkRandomNumberRead( void *inBuffer, int inByteCount ); + +int bk_rand(void); + +/** @} */ +/** @} */ + +#endif + + diff --git a/beken_os/beken378/func/user_driver/BkDriverRtc.h b/beken_os/beken378/func/user_driver/BkDriverRtc.h new file mode 100755 index 0000000..af6a4ac --- /dev/null +++ b/beken_os/beken378/func/user_driver/BkDriverRtc.h @@ -0,0 +1,107 @@ +/** + ****************************************************************************** + * @file BkDriverRtc.h + * @brief This file provides all the headers of RTC operation functions. + ****************************************************************************** + * + * The MIT License + * Copyright (c) 2017 BEKEN Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR + * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + ****************************************************************************** + */ + +#ifndef __BEKENDRIVERRTC_H__ +#define __BEKENDRIVERRTC_H__ + +#pragma once +#include "include.h" + +/** @addtogroup BK_PLATFORM +* @{ +*/ + +/** @defgroup BK_RTC _BK_ RTC Driver +* @brief Real-time clock (RTC) Functions +* @{ +*/ + +/****************************************************** + * Macros + ******************************************************/ + +/****************************************************** + * Enumerations + ******************************************************/ + +/****************************************************** + * Type Definitions + ******************************************************/ + +typedef platform_rtc_time_t bk_rtc_time_t; + +/****************************************************** +* Structures +******************************************************/ + +/****************************************************** + * Variables + ******************************************************/ + +/****************************************************** + Function Declarations + ******************************************************/ + + + +/**@brief This function will initialize the on board CPU real time clock + * + * @note This function should be called by _BK_ system when initializing clocks, so + * It is not needed to be called by application + * + * @return kNoErr : on success. + * @return kGeneralErr : if an error occurred with any step + */ +void BkRtcInitialize(void); + +/**@brief This function will return the value of time read from the on board CPU real time clock. Time value must be given in the format of + * the structure bk_rtc_time_t + * + * @param time : pointer to a time structure + * + * @return kNoErr : on success. + * @return kGeneralErr : if an error occurred with any step + */ +OSStatus BkRtcGetTime(bk_rtc_time_t *time); + +/**@brief This function will set MCU RTC time to a new value. Time value must be given in the format of + * the structure bk_rtc_time_t + * + * @param time : pointer to a time structure + * + * @return kNoErr : on success. + * @return kGeneralErr : if an error occurred with any step + */ +OSStatus BkRtcSetTime(bk_rtc_time_t *time); + +/** @} */ +/** @} */ + +#endif + + diff --git a/beken_os/beken378/func/user_driver/BkDriverSpi.h b/beken_os/beken378/func/user_driver/BkDriverSpi.h new file mode 100755 index 0000000..bbaa1bd --- /dev/null +++ b/beken_os/beken378/func/user_driver/BkDriverSpi.h @@ -0,0 +1,125 @@ +/** + ****************************************************************************** + * @file BkDriverSpi.h + * @brief This file provides all the headers of SPi operation functions. + ****************************************************************************** + * + * The MIT License + * Copyright (c) 2017 BEKEN Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR + * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + ****************************************************************************** + */ + +#ifndef __BEKENDRIVERSPI_H__ +#define __BEKENDRIVERSPI_H__ + +#pragma once +#include "include.h" + +/** @addtogroup BK_PLATFORM +* @{ +*/ +/** @defgroup BK_SPI _BK_ SPI Driver +* @brief Serial Peripheral Interface (SPI) Functions +* @{ +*/ +/****************************************************** + * Constants + ******************************************************/ +/* SPI mode constants */ +#define SPI_CLOCK_RISING_EDGE ( 1 << 0 ) +#define SPI_CLOCK_FALLING_EDGE ( 0 << 0 ) +#define SPI_CLOCK_IDLE_HIGH ( 1 << 1 ) +#define SPI_CLOCK_IDLE_LOW ( 0 << 1 ) +#define SPI_USE_DMA ( 1 << 2 ) +#define SPI_NO_DMA ( 0 << 2 ) +#define SPI_MSB_FIRST ( 1 << 3 ) +#define SPI_LSB_FIRST ( 0 << 3 ) + + +/****************************************************** + * Enumerations + ******************************************************/ + + +/****************************************************** + * Structures + ******************************************************/ + + +typedef struct +{ + bk_spi_t port; + bk_gpio_t chip_select; + uint32_t speed; + uint8_t mode; + uint8_t bits; +} bk_spi_device_t; + +typedef platform_spi_message_segment_t bk_spi_message_segment_t; + +/****************************************************** + * Variables + ******************************************************/ + +/****************************************************** + * Function Declarations + ******************************************************/ + + + +/**@brief Initialises the SPI interface for a given SPI device + * + * @note Prepares a SPI hardware interface for communication as a master + * + * @param spi : the SPI device to be initialised + * + * @return kNoErr : on success. + * @return kGeneralErr : if the SPI device could not be initialised + */ +OSStatus BkSpiInitialize( const bk_spi_device_t *spi ); + + +/**@brief Transmits and/or receives data from a SPI device + * + * @param spi : the SPI device to be initialised + * @param segments : a pointer to an array of segments + * @param number_of_segments : the number of segments to transfer + * + * @return kNoErr : on success. + * @return kGeneralErr : if an error occurred + */ +OSStatus BkSpiTransfer( const bk_spi_device_t *spi, const bk_spi_message_segment_t *segments, uint16_t number_of_segments ); + + +/**@brief De-initialises a SPI interface + * + * @note Turns off a SPI hardware interface + * + * @param spi : the SPI device to be de-initialised + * + * @return kNoErr : on success. + * @return kGeneralErr : if an error occurred + */ +OSStatus BkSpiFinalize( const bk_spi_device_t *spi ); + +/** @} */ +/** @} */ + +#endif diff --git a/beken_os/beken378/func/user_driver/BkDriverTimer.c b/beken_os/beken378/func/user_driver/BkDriverTimer.c new file mode 100755 index 0000000..d2c4146 --- /dev/null +++ b/beken_os/beken378/func/user_driver/BkDriverTimer.c @@ -0,0 +1,118 @@ +/** + ****************************************************************************** + * @file BkDriverTimer.h + * @brief This file provides all the headers of timer operation functions. + ****************************************************************************** + * + * The MIT License + * Copyright (c) 2017 BEKEN Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR + * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + ****************************************************************************** + */ + +#include "include.h" +#include "rtos_pub.h" +#include "rtos_error.h" +#include "bk_timer_pub.h" +#include "drv_model_pub.h" + +/**@brief Initialises a timer and start + * + * @note user can user timer0 timer1 timer2 timer4 timer5 + * + * @param timer_id : the timer id + * @param time_ms : time value(unit:ms) + * @param callback : callback + * + * @return kNoErr : on success. + * @return kGeneralErr : if an error occurred with any step + */ +OSStatus bk_timer_initialize(uint8_t timer_id, uint32_t time_ms, void *callback) +{ + UINT32 ret; + timer_param_t param; + + param.channel = timer_id; + param.div = 1; //timer0 timer1 timer2 26M // timer4 timer5 32K (n+1) division + param.period = time_ms; + param.t_Int_Handler= callback; + + ret = sddev_control(TIMER_DEV_NAME, CMD_TIMER_INIT_PARAM, ¶m); + ASSERT(BK_TIMER_SUCCESS == ret); + + return kNoErr; +} + +OSStatus bk_timer_initialize_us(uint8_t timer_id, uint32_t time_us, void *callback) +{ + UINT32 ret; + timer_param_t param; + + param.channel = timer_id; + param.div = 1; //timer0 timer1 timer2 26M // timer4 timer5 32K (n+1) division + param.period = time_us; + param.t_Int_Handler= callback; + + ret = sddev_control(TIMER_DEV_NAME, CMD_TIMER_INIT_PARAM_US, ¶m); + ASSERT(BK_TIMER_SUCCESS == ret); + + return kNoErr; +} + +OSStatus bk_timer_read_cnt(uint8_t timer_id, uint32_t *timer_cnt) +{ + UINT32 ret; + timer_param_t param; + + param.channel = timer_id; + param.div = 1; //timer0 timer1 timer2 26M // timer4 timer5 32K (n+1) division + param.period = 0; + param.t_Int_Handler= NULL; + + ret = sddev_control(TIMER_DEV_NAME, CMD_TIMER_READ_CNT, ¶m); + ASSERT(BK_TIMER_SUCCESS == ret); + + *timer_cnt = param.period; + + return kNoErr; +} + +/**@brief stop timer + * + * @note user can user timer0 timer1 timer2 timer4 timer5 + * + * @param timer_id : the timer id + * + * @return kNoErr : on success. + * @return kGeneralErr : if an error occurred with any step + */ +OSStatus bk_timer_stop(uint8_t timer_id) +{ + UINT32 ret; + UINT32 timer_channel; + + timer_channel = timer_id; + ret = sddev_control(TIMER_DEV_NAME, CMD_TIMER_UNIT_DISABLE, &timer_channel); + ASSERT(BK_TIMER_SUCCESS == ret); + + return kNoErr; +} + +// eof + diff --git a/beken_os/beken378/func/user_driver/BkDriverTimer.h b/beken_os/beken378/func/user_driver/BkDriverTimer.h new file mode 100755 index 0000000..3f7bfae --- /dev/null +++ b/beken_os/beken378/func/user_driver/BkDriverTimer.h @@ -0,0 +1,88 @@ +/** + ****************************************************************************** + * @file BkDriverTimer.h + * @brief This file provides all the headers of PWM operation functions. + ****************************************************************************** + * + * The MIT License + * Copyright (c) 2017 BEKEN Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR + * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + ****************************************************************************** + */ + +#ifndef __BEKENDRIVERTIMER_H__ +#define __BEKENDRIVERTIMER_H__ + +#pragma once +#include "include.h" +#include "rtos_pub.h" + +/** @addtogroup BK_PLATFORM + * @{ + */ + +/** @defgroup BK_TIMER _BK_ TIMER Driver + * @brief Pulse-Width Modulation (PWM) Functions + * @{ + */ + +/****************************************************** + * Enumerations + ******************************************************/ + + +/****************************************************** + * Type Definitions + ******************************************************/ + +/****************************************************** +* Function Declarations +******************************************************/ + + +/**@brief Initialises a timer and start + * + * @note user can user timer0 timer1 timer2 timer4 timer5 + * + * @param timer_id : the timer id + * @param time_ms : time value(unit:ms) + * @param callback : callback + * + * @return kNoErr : on success. + * @return kGeneralErr : if an error occurred with any step + */ +OSStatus bk_timer_initialize(uint8_t timer_id, uint32_t time_ms, void *callback); + +/**@brief stop timer + * + * @note user can user timer0 timer1 timer2 timer4 timer5 + * + * @param timer_id : the timer id + * + * @return kNoErr : on success. + * @return kGeneralErr : if an error occurred with any step + */ +OSStatus bk_timer_stop(uint8_t timer_id); + + + +/** @} */ +/** @} */ + +#endif diff --git a/beken_os/beken378/func/user_driver/BkDriverUart.c b/beken_os/beken378/func/user_driver/BkDriverUart.c new file mode 100755 index 0000000..9d26bb5 --- /dev/null +++ b/beken_os/beken378/func/user_driver/BkDriverUart.c @@ -0,0 +1,181 @@ +/** + ****************************************************************************** + * @file BkDriverUart.h + * @brief This file provides all the headers of UART operation functions. + ****************************************************************************** + * + * The MIT License + * Copyright (c) 2017 BEKEN Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR + * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + ****************************************************************************** + */ +#include "include.h" +#include "BkDriverUart.h" +#include "drv_model_pub.h" +#include "rtos_error.h" + +OSStatus bk_uart_initialize( bk_uart_t uart, const bk_uart_config_t *config, ring_buffer_t *optional_rx_buffer ) +{ + UINT32 ret; + UINT32 status; + DD_HANDLE uart_hdl; + + ASSERT(uart < BK_UART_MAX); + if(BK_UART_1 == uart) + uart_hdl = ddev_open(UART1_DEV_NAME, &status, 0); + else + uart_hdl = ddev_open(UART2_DEV_NAME, &status, 0); + + ASSERT(DRV_FAILURE != uart_hdl); + + ret = ddev_control(uart_hdl, CMD_UART_INIT, (void *)config); + return ret; +} + +OSStatus bk_uart_finalize( bk_uart_t uart) +{ + UINT32 status; + DD_HANDLE uart_hdl; + + if(BK_UART_1 == uart) + uart_hdl = ddev_open(UART1_DEV_NAME, &status, 0); + else + uart_hdl = ddev_open(UART2_DEV_NAME, &status, 0); + + ASSERT(DRV_FAILURE != uart_hdl); + + ddev_close(uart_hdl); + + return kNoErr; +} + +OSStatus bk_uart_send( bk_uart_t uart, const void *data, uint32_t size ) +{ + bk_send_string(uart, data); + + return kNoErr; +} + +OSStatus bk_uart_recv( bk_uart_t uart, void *data, uint32_t size, uint32_t timeout ) +{ + UINT32 ret; + UINT32 status; + DD_HANDLE uart_hdl; + + if(BK_UART_1 == uart) + uart_hdl = ddev_open(UART1_DEV_NAME, &status, 0); + else + uart_hdl = ddev_open(UART2_DEV_NAME, &status, 0); + + ASSERT(DRV_FAILURE != uart_hdl); + ret = ddev_control(uart_hdl, CMD_RX_COUNT, 0); + if(ret < size) + { + return kGeneralErr; + } + + ret = ddev_read(uart_hdl, data, size, 0); + ASSERT(size == ret); + + return kNoErr; +} + +OSStatus bk_uart_recv_prefetch( bk_uart_t uart, void *data, uint32_t size, uint32_t timeout ) +{ + UINT32 ret; + UINT32 status; + DD_HANDLE uart_hdl; + UART_PEEK_RX_T peek; + + if(BK_UART_1 == uart) + uart_hdl = ddev_open(UART1_DEV_NAME, &status, 0); + else + uart_hdl = ddev_open(UART2_DEV_NAME, &status, 0); + + ASSERT(DRV_FAILURE != uart_hdl); + + peek.sig = URX_PEEK_SIG; + peek.ptr = data; + peek.len = size; + ret = ddev_control(uart_hdl, CMD_RX_PEEK, &peek); + ASSERT(size == ret); + + return kNoErr; +} + +uint32_t bk_uart_get_length_in_buffer( bk_uart_t uart ) +{ + uint32_t length; + UINT32 status; + DD_HANDLE uart_hdl; + + if(BK_UART_1 == uart) + uart_hdl = ddev_open(UART1_DEV_NAME, &status, 0); + else + uart_hdl = ddev_open(UART2_DEV_NAME, &status, 0); + + ASSERT(DRV_FAILURE != uart_hdl); + length = (uint32_t)ddev_control(uart_hdl, CMD_RX_COUNT, 0); + + return length; +} + +OSStatus bk_uart_set_rx_callback(bk_uart_t uart, uart_callback callback, void *param) +{ + UINT32 ret; + UINT32 status; + DD_HANDLE uart_hdl; + UART_CALLBACK_RX_T uart_callback_rx; + + if(BK_UART_1 == uart) + uart_hdl = ddev_open(UART1_DEV_NAME, &status, 0); + else + uart_hdl = ddev_open(UART2_DEV_NAME, &status, 0); + + ASSERT(DRV_FAILURE != uart_hdl); + + uart_callback_rx.callback = callback; + uart_callback_rx.param = param; + ret = ddev_control(uart_hdl, CMD_UART_SET_RX_CALLBACK, &uart_callback_rx); + ASSERT(UART_SUCCESS == ret); + + return kNoErr; +} + +OSStatus bk_uart_diable_rx(bk_uart_t uart) +{ + UINT32 ret; + UINT32 status; + DD_HANDLE uart_hdl; + + if(BK_UART_1 == uart) + uart_hdl = ddev_open(UART1_DEV_NAME, &status, 0); + else + uart_hdl = ddev_open(UART2_DEV_NAME, &status, 0); + + ASSERT(DRV_FAILURE != uart_hdl); + + ret = ddev_control(uart_hdl, CMD_DISABLE_UART_RX, 0); + ASSERT(UART_SUCCESS == ret); + + return kNoErr; +} + +// eof + diff --git a/beken_os/beken378/func/user_driver/BkDriverUart.h b/beken_os/beken378/func/user_driver/BkDriverUart.h new file mode 100755 index 0000000..795827c --- /dev/null +++ b/beken_os/beken378/func/user_driver/BkDriverUart.h @@ -0,0 +1,159 @@ +/** + ****************************************************************************** + * @file BkDriverUart.h + * @brief This file provides all the headers of UART operation functions. + ****************************************************************************** + * + * The MIT License + * Copyright (c) 2017 BEKEN Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR + * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + ****************************************************************************** + */ + + +#ifndef __BEKENDRIVERUART_H__ +#define __BEKENDRIVERUART_H__ + +#pragma once +#include "include.h" +#include "uart_pub.h" +#include "rtos_pub.h" + +/** @addtogroup BK_PLATFORM +* @{ +*/ + +/** @defgroup BK_UART _BK_ UART Driver +* @brief Universal Asynchronous Receiver Transmitter (UART) Functions +* @{ +*/ + +/****************************************************** + * Enumerations + ******************************************************/ +typedef enum +{ + BK_UART_1 = 0, + BK_UART_2, + BK_UART_MAX, +} bk_uart_t; + +/****************************************************** + * Structures + ******************************************************/ +/****************************************************** + * Type Definitions + ******************************************************/ +typedef struct +{ + uint32_t baud_rate; + uart_data_width_t data_width; + uart_parity_t parity; + uart_stop_bits_t stop_bits; + uart_flow_control_t flow_control; + uint8_t flags; /**< if set, UART can wake up MCU from stop mode, reference: @ref UART_WAKEUP_DISABLE and @ref UART_WAKEUP_ENABLE*/ +} platform_uart_config_t; + +typedef struct +{ + uint32_t size; + uint32_t head; + uint32_t tail; + uint8_t *buffer; +} ring_buffer_t; + +typedef platform_uart_config_t bk_uart_config_t; + +/****************************************************** + * Function Declarations + ******************************************************/ +OSStatus bk_uart_initialize_test( bk_uart_t uart, uint8_t config, ring_buffer_t *optional_rx_buffer ); +/**@brief Initialises a UART interface + * + * @note Prepares an UART hardware interface for communications + * + * @param uart : the interface which should be initialised + * @param config : UART configuration structure + * @param optional_rx_buffer : Pointer to an optional RX ring buffer + * + * @return kNoErr : on success. + * @return kGeneralErr : if an error occurred with any step + */ +OSStatus bk_uart_initialize( bk_uart_t uart, const bk_uart_config_t *config, ring_buffer_t *optional_rx_buffer ); + +/**@brief Deinitialises a UART interface + * + * @param uart : the interface which should be deinitialised + * + * @return kNoErr : on success. + * @return kGeneralErr : if an error occurred with any step + */ +OSStatus bk_uart_finalize( bk_uart_t uart ); + + +/**@brief Transmit data on a UART interface + * + * @param uart : the UART interface + * @param data : pointer to the start of data + * @param size : number of bytes to transmit + * + * @return kNoErr : on success. + * @return kGeneralErr : if an error occurred with any step + */ +OSStatus bk_uart_send( bk_uart_t uart, const void *data, uint32_t size ); + + +/**@brief Receive data on a UART interface + * + * @param uart : the UART interface + * @param data : pointer to the buffer which will store incoming data + * @param size : number of bytes to receive + * @param timeout : timeout in milisecond + * + * @return kNoErr : on success. + * @return kGeneralErr : if an error occurred with any step + */ +OSStatus bk_uart_recv( bk_uart_t uart, void *data, uint32_t size, uint32_t timeout ); +OSStatus bk_uart_recv_prefetch( bk_uart_t uart, void *data, uint32_t size, uint32_t timeout ); + +/**@brief Read the length of the data that is already recived by uart driver and stored in buffer + * + * @param uart : the UART interface + * + * @return Data length + */ +uint32_t bk_uart_get_length_in_buffer( bk_uart_t uart ); + +/**@brief set receive data callback on a UART interface, please notice that, the callback will beinvoked in ISR + * + * @param uart : the UART interface + * @param callback : callback to invoke when UART receive data, use NULL to clear callback + * @param param : user param which will filled in callback as 2nd parameter + * + * @return kNoErr : on success. + * @return kGeneralErr : if an error occurred with any step + */ +OSStatus bk_uart_set_rx_callback( bk_uart_t uart, uart_callback callback, void *param ); + +OSStatus bk_uart_diable_rx(bk_uart_t uart); + +/** @} */ +/** @} */ + +#endif diff --git a/beken_os/beken378/func/user_driver/BkDriverWdg.c b/beken_os/beken378/func/user_driver/BkDriverWdg.c new file mode 100755 index 0000000..41e22ba --- /dev/null +++ b/beken_os/beken378/func/user_driver/BkDriverWdg.c @@ -0,0 +1,73 @@ +/** + ****************************************************************************** + * @file BkDriverWdg.h + + * @version V1.0.0 + * @date 16-Sep-2014 + * @brief This file provides all the headers of WDG operation functions. + ****************************************************************************** + * + * The MIT License + * Copyright (c) 2017 BEKEN Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR + * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + ****************************************************************************** + */ +#include "include.h" +#include "rtos_pub.h" +#include "BkDriverWdg.h" +#include "drv_model_pub.h" +#include "rtos_error.h" +#include "wdt_pub.h" + +OSStatus bk_wdg_initialize( uint32_t timeout ) +{ + UINT32 ret, param; + + ret = sddev_control(WDT_DEV_NAME, WCMD_POWER_UP, 0); + ASSERT(WDT_SUCCESS == ret); + + param = timeout; + ret = sddev_control(WDT_DEV_NAME, WCMD_SET_PERIOD, ¶m); + ASSERT(WDT_SUCCESS == ret); + + return kNoErr; +} + +void bk_wdg_reload( void ) +{ + UINT32 ret; + + ret = sddev_control(WDT_DEV_NAME, WCMD_RELOAD_PERIOD, 0); + ASSERT(WDT_SUCCESS == ret); + + return; +} + +OSStatus bk_wdg_finalize( void ) +{ + UINT32 ret; + + ret = sddev_control(WDT_DEV_NAME, WCMD_POWER_DOWN, 0); + ASSERT(WDT_SUCCESS == ret); + + return kNoErr; +} + +// eof + diff --git a/beken_os/beken378/func/user_driver/BkDriverWdg.h b/beken_os/beken378/func/user_driver/BkDriverWdg.h new file mode 100755 index 0000000..709c768 --- /dev/null +++ b/beken_os/beken378/func/user_driver/BkDriverWdg.h @@ -0,0 +1,115 @@ +/** + ****************************************************************************** + * @file BkDriverWdg.h + + * @version V1.0.0 + * @date 16-Sep-2014 + * @brief This file provides all the headers of WDG operation functions. + ****************************************************************************** + * + * The MIT License + * Copyright (c) 2017 BEKEN Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR + * IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + ****************************************************************************** + */ + + +#ifndef __BEKENDRIVERWDG_H__ +#define __BEKENDRIVERWDG_H__ + +#pragma once +#include "include.h" +#include "rtos_pub.h" + +/** @addtogroup BK_PLATFORM +* @{ +*/ + +/** @defgroup BK_WDG _BK_ WDG Driver +* @brief Hardware watch dog Functions (WDG) Functions +* @note These Functions are used by _BK_'s system monitor service, If any defined system monitor +* cannot be reloaded for some reason, system monitor service use this hardware watch dog +* to perform a system reset. So the watch dog reload time should be greater than system +* monitor's refresh time. +* @{ +*/ + +/****************************************************** + * Macros + ******************************************************/ +#define PlatformWDGInitialize bk_wdg_initialize /**< For API compatiable with older version */ +#define PlatformWDGReload bk_wdg_reload /**< For API compatiable with older version */ +#define PlatformWDGFinalize bk_wdg_finalize /**< For API compatiable with older version */ + +/****************************************************** + * Enumerations + ******************************************************/ + +/****************************************************** + * Type Definitions + ******************************************************/ + +/****************************************************** +* Structures +******************************************************/ + + +/****************************************************** + * Variables + ******************************************************/ + +/****************************************************** + * Function Declarations + ******************************************************/ + + +/** + * @biref This function will initialize the on board CPU hardware watch dog + * + * @param timeout : Watchdag timeout, application should call bk_wdg_reload befor timeout. + * + * @return kNoErr : on success. + * @return kGeneralErr : if an error occurred with any step + */ +OSStatus bk_wdg_initialize( uint32_t timeout ); + +/** + * @biref Reload watchdog counter. + * + * @param none + * @return none + */ +void bk_wdg_reload( void ); + +/** + * @biref This function performs any platform-specific cleanup needed for hardware watch dog. + * + * @param none + * + * @return kNoErr : on success. + * @return kGeneralErr : if an error occurred with any step + */ +OSStatus bk_wdg_finalize( void ); + +/** @} */ +/** @} */ + +#endif + + diff --git a/beken_os/beken378/func/video_transfer/video_transfer.c b/beken_os/beken378/func/video_transfer/video_transfer.c new file mode 100755 index 0000000..40b5217 --- /dev/null +++ b/beken_os/beken378/func/video_transfer/video_transfer.c @@ -0,0 +1,448 @@ +#include "include.h" +#include "arm_arch.h" + +#if (CFG_USE_SPIDMA || CFG_USE_CAMERA_INTF) +#include "FreeRTOS.h" +#include "task.h" +#include "rtos_pub.h" +#include "error.h" +#include "co_list.h" + +#include "video_transfer.h" + +#include "drv_model_pub.h" +#include "mem_pub.h" + +#include "spidma_intf_pub.h" +#include "camera_intf_pub.h" + +#include "app_lwip_tcp.h" +#include "app_lwip_udp.h" + +#if CFG_GENERAL_DMA +#include "general_dma_pub.h" +#endif + +#define TVIDEO_DEBUG 1 +#include "uart_pub.h" +#if TVIDEO_DEBUG +#define TVIDEO_PRT os_printf +#define TVIDEO_WPRT warning_prf +#define TVIDEO_FATAL fatal_prf +#else +#define TVIDEO_PRT null_prf +#define TVIDEO_WPRT null_prf +#define TVIDEO_FATAL null_prf +#endif + +#define TVIDEO_DROP_DATA_NONODE 0 +#define TVIDEO_USE_HDR 1 + +#define TVIDEO_RXNODE_SIZE_UDP 1472//32//1472 +#define TVIDEO_RXNODE_SIZE_TCP 1460//20//1460 +#ifndef TVIDEO_RXNODE_SIZE +#define TVIDEO_RXNODE_SIZE TVIDEO_RXNODE_SIZE_UDP +#endif + +#define TVIDEO_DROP_DATA_FLAG 0x01 + +#if TVIDEO_DROP_DATA_NONODE +#define TVIDEO_POOL_LEN (TVIDEO_RXNODE_SIZE * 38) // 54KB +#else +#define TVIDEO_POOL_LEN (TVIDEO_RXNODE_SIZE * 10) // 7KB +#endif + +#define TVIDEO_RXBUF_LEN (TVIDEO_RXNODE_SIZE_UDP * 4) + +UINT8 tvideo_rxbuf[TVIDEO_RXBUF_LEN]; + +TVIDEO_DESC_ST tvideo_st; + +typedef struct tvideo_hdr_st +{ + UINT8 id; + UINT8 is_eof; + UINT8 pkt_cnt; + UINT8 size; +}TV_HDR_ST, *TV_HDR_PTR; + +typedef struct tvideo_elem_st +{ + struct co_list_hdr hdr; + void *buf_start; + UINT32 buf_len; +} TVIDEO_ELEM_ST, *TVIDEO_ELEM_PTR; + +typedef struct tvideo_pool_st +{ + UINT8 pool[TVIDEO_POOL_LEN]; + TVIDEO_ELEM_ST elem[TVIDEO_POOL_LEN / TVIDEO_RXNODE_SIZE]; + struct co_list free; + struct co_list ready; + #if TVIDEO_DROP_DATA_NONODE + struct co_list receiving; + UINT32 drop_pkt_flag; + #endif + int (*send_func)(UINT8 *data, UINT32 len); + #if(TVIDEO_USE_HDR && CFG_USE_CAMERA_INTF) + TV_HDR_ST tv_hdr; + #endif +} TVIDEO_POOL_ST, *TVIDEO_POOL_PTR; + +TVIDEO_POOL_ST tvideo_pool; + +enum +{ + TV_INT_POLL = 0, + TV_EXIT, +}; + +typedef struct tvideo_message +{ + UINT32 data; +}TV_MSG_T; + +#define TV_QITEM_COUNT (30) +xTaskHandle tvideo_thread_hdl = NULL; +beken_queue_t tvideo_msg_que = NULL; + +void tvideo_intfer_send_msg(UINT32 new_msg) +{ + OSStatus ret; + TV_MSG_T msg; + + if(tvideo_msg_que) + { + msg.data = new_msg; + + ret = rtos_push_to_queue(&tvideo_msg_que, &msg, BEKEN_NO_WAIT); + if(kNoErr != ret) + { + TVIDEO_FATAL("tvideo_intfer_send_msg failed\r\n"); + } + } +} + +static void tvideo_pool_init(void* data) +{ + UINT32 i = 0; + TVIDEO_SND_TYPE snd_type = (TVIDEO_SND_TYPE)((int)data); + os_memset(&tvideo_pool.pool[0], 0, sizeof(UINT8)*TVIDEO_POOL_LEN); + co_list_init(&tvideo_pool.free); + co_list_init(&tvideo_pool.ready); + #if TVIDEO_DROP_DATA_NONODE + co_list_init(&tvideo_pool.receiving); + tvideo_pool.drop_pkt_flag = 0; + #endif + + for(i = 0; i < (TVIDEO_POOL_LEN / TVIDEO_RXNODE_SIZE); i++) + { + tvideo_pool.elem[i].buf_start = + (void *)&tvideo_pool.pool[i * TVIDEO_RXNODE_SIZE]; + tvideo_pool.elem[i].buf_len = 0; + + co_list_push_back(&tvideo_pool.free, + (struct co_list_hdr *)&tvideo_pool.elem[i].hdr); + } + + TVIDEO_PRT("video transfer send type:%d\r\n", snd_type); + + if(snd_type == TVIDEO_SND_UDP) + tvideo_pool.send_func = app_lwip_udp_send_packet; + else if(snd_type == TVIDEO_SND_TCP) + tvideo_pool.send_func = app_lwip_tcp_send_packet; + else + tvideo_pool.send_func = NULL; + + #if(TVIDEO_USE_HDR && CFG_USE_CAMERA_INTF) + tvideo_pool.tv_hdr.id = 0; + tvideo_pool.tv_hdr.is_eof = 0; + tvideo_pool.tv_hdr.pkt_cnt = 0; + tvideo_pool.tv_hdr.size = 0; + #endif +} + +#if CFG_GENERAL_DMA +static void tvideo_config_general_dma(void) +{ + GDMACFG_TPYES_ST cfg; + + cfg.dstdat_width = 32; + cfg.srcdat_width = 32; + cfg.dstptr_incr = 1; + cfg.srcptr_incr = 1; + cfg.src_start_addr = NULL; + cfg.dst_start_addr = NULL; + + cfg.channel = GDMA_CHANNEL_1; + cfg.prio = 0; + cfg.u.type1.src_loop_start_addr = &tvideo_rxbuf[0]; + cfg.u.type1.src_loop_end_addr = &tvideo_rxbuf[tvideo_st.rxbuf_len]; + + sddev_control(GDMA_DEV_NAME, CMD_GDMA_CFG_TYPE1, &cfg); +} +#endif + +void *tvideo_memcpy(void *out, const void *in, UINT32 n) +{ + #if CFG_GENERAL_DMA + GDMA_DO_ST do_st; + do_st.channel = GDMA_CHANNEL_1; + do_st.src_addr = (void*)in; + do_st.length = n; + do_st.dst_addr = out; + sddev_control(GDMA_DEV_NAME, CMD_GDMA_ENABLE, &do_st); + #else + os_memcpy(out, in, n); + #endif + return out; +} + +static void tvideo_rx_handler(void *curptr, UINT32 newlen, UINT32 is_eof, UINT32 frame_len) +{ + TVIDEO_ELEM_PTR elem = NULL; + do { + if(!newlen) + break; + + #if TVIDEO_DROP_DATA_NONODE + // drop pkt has happened, so drop it, until spidma timeout handler. + if(tvideo_pool.drop_pkt_flag & TVIDEO_DROP_DATA_FLAG) + break; + #endif + + elem = (TVIDEO_ELEM_PTR)co_list_pick(&tvideo_pool.free); + if(elem) { + if(newlen > tvideo_st.node_len) + newlen = tvideo_st.node_len; + + #if(TVIDEO_USE_HDR && CFG_USE_CAMERA_INTF) + TV_HDR_PTR elem_tvhdr = (TV_HDR_PTR)elem->buf_start; + + if(is_eof) { + tvideo_pool.tv_hdr.is_eof = 1; + tvideo_pool.tv_hdr.pkt_cnt = frame_len / tvideo_st.node_len; + if(frame_len % tvideo_st.node_len) { + tvideo_pool.tv_hdr.pkt_cnt += 1; + } + } + + elem_tvhdr->id = tvideo_pool.tv_hdr.id; + elem_tvhdr->is_eof = tvideo_pool.tv_hdr.is_eof; + elem_tvhdr->pkt_cnt = tvideo_pool.tv_hdr.pkt_cnt; + elem_tvhdr->size = tvideo_pool.tv_hdr.size; + + tvideo_memcpy(elem_tvhdr + 1, curptr, newlen); + if(tvideo_st.node_len > newlen){ + //UINT32 left = tvideo_st.node_len - newlen; + //os_memset((elem_tvhdr + 1 + newlen), 0, left); + } + //elem->buf_len = tvideo_st.node_len + sizeof(TV_HDR_ST); + elem->buf_len = newlen + sizeof(TV_HDR_ST); + + #else // (TVIDEO_USE_HDR && CFG_USE_CAMERA_INTF) + tvideo_memcpy(elem->buf_start, curptr, newlen); + if(tvideo_st.node_len > newlen){ + //UINT32 left = tvideo_st.node_len - newlen; + //os_memset(((UINT8*)elem->buf_start + newlen), 0, left); + } + //elem->buf_len = tvideo_st.node_len; + elem->buf_len = newlen; + #endif // (TVIDEO_USE_HDR && CFG_USE_CAMERA_INTF) + + co_list_pop_front(&tvideo_pool.free); + #if TVIDEO_DROP_DATA_NONODE + co_list_push_back(&tvideo_pool.receiving, (struct co_list_hdr *)&elem->hdr); + #else + co_list_push_back(&tvideo_pool.ready, (struct co_list_hdr *)&elem->hdr); + #endif + } + else { + #if TVIDEO_DROP_DATA_NONODE + // not node for receive pkt, drop aready received, and also drop + // the new come. + UINT32 cnt_rdy = co_list_cnt(&tvideo_pool.receiving); + + tvideo_pool.drop_pkt_flag |= TVIDEO_DROP_DATA_FLAG; + if(cnt_rdy) + co_list_concat(&tvideo_pool.free, &tvideo_pool.receiving); + #endif + //os_printf("lost\r\n"); + } + } while(0); + + tvideo_intfer_send_msg(TV_INT_POLL); +} + +static void tvideo_end_frame_handler(void) +{ + #if TVIDEO_DROP_DATA_NONODE + // reset drop flag, new pkt can receive + tvideo_pool.drop_pkt_flag &= (~TVIDEO_DROP_DATA_FLAG); + if(!co_list_is_empty(&tvideo_pool.receiving)) { + co_list_concat(&tvideo_pool.ready, &tvideo_pool.receiving); + } + #endif + + #if(TVIDEO_USE_HDR && CFG_USE_CAMERA_INTF) + tvideo_pool.tv_hdr.id++; + tvideo_pool.tv_hdr.is_eof = 0; + #endif + + tvideo_intfer_send_msg(TV_INT_POLL); +} + +static void tvideo_config_desc(void* data) +{ + TVIDEO_SND_TYPE snd_type = (TVIDEO_SND_TYPE)((int)data); + UINT32 node_len = TVIDEO_RXNODE_SIZE_TCP; + + if(snd_type == TVIDEO_SND_UDP) { + #if(TVIDEO_USE_HDR && CFG_USE_CAMERA_INTF) + node_len = TVIDEO_RXNODE_SIZE_UDP - sizeof(TV_HDR_ST); + #else + node_len = TVIDEO_RXNODE_SIZE_UDP; + #endif + } + else if(snd_type == TVIDEO_SND_TCP) + node_len = TVIDEO_RXNODE_SIZE_TCP; + else { + TVIDEO_WPRT("Err snd tpye in spidma\r\n"); + } + + tvideo_st.rxbuf = &tvideo_rxbuf[0]; + tvideo_st.rxbuf_len = node_len * 4; + tvideo_st.node_len = node_len; + tvideo_st.rx_read_len = 0; + + tvideo_st.node_full_handler = tvideo_rx_handler; + tvideo_st.data_end_handler = tvideo_end_frame_handler; +} + +static void tvideo_poll_handler(void) +{ + UINT32 send_len; + TVIDEO_ELEM_PTR elem = NULL; + + do{ + elem = (TVIDEO_ELEM_PTR)co_list_pick(&tvideo_pool.ready); + if(elem) { + if(tvideo_pool.send_func) { + REG_WRITE((0x00802800+(18*4)), 0x02); + send_len = tvideo_pool.send_func(elem->buf_start, elem->buf_len); + REG_WRITE((0x00802800+(18*4)), 0x00); + if(send_len != elem->buf_len) { + break; + } + } + + co_list_pop_front(&tvideo_pool.ready); + co_list_push_back(&tvideo_pool.free, (struct co_list_hdr *)&elem->hdr); + } + } + while(elem); +} + +/*---------------------------------------------------------------------------*/ +static void video_transfer_main( beken_thread_arg_t data ) +{ + OSStatus err; + TVIDEO_PRT("video_transfer_main entry\r\n"); + + tvideo_pool_init(data); + tvideo_config_desc(data); +#if CFG_GENERAL_DMA + tvideo_config_general_dma(); +#endif + + { + #if CFG_USE_SPIDMA + spidma_intfer_init(&tvideo_st); + #elif CFG_USE_CAMERA_INTF + camera_intfer_init(&tvideo_st); + #endif + } + + while(1) + { + TV_MSG_T msg; + err = rtos_pop_from_queue(&tvideo_msg_que, &msg, BEKEN_WAIT_FOREVER); + if(kNoErr == err) + { + switch(msg.data) + { + case TV_INT_POLL: + tvideo_poll_handler(); + break; + + case TV_EXIT: + goto tvideo_exit; + break; + + default: + break; + } + } + } + +tvideo_exit: + TVIDEO_PRT("video_transfer_main exit\r\n"); + + #if CFG_USE_SPIDMA + spidma_intfer_deinit(); + #elif CFG_USE_CAMERA_INTF + camera_intfer_deinit(); + #endif + + rtos_deinit_queue(&tvideo_msg_que); + tvideo_msg_que = NULL; + + tvideo_thread_hdl = NULL; + rtos_delete_thread(NULL); +} + +UINT32 video_transfer_init(UINT32 tcp_udp_mode) +{ + int ret; + + TVIDEO_PRT("video_transfer_init %d\r\n", tcp_udp_mode); + if((!tvideo_thread_hdl) && (!tvideo_msg_que)) + { + + ret = rtos_init_queue(&tvideo_msg_que, + "tvideo_queue", + sizeof(TV_MSG_T), + TV_QITEM_COUNT); + if (kNoErr != ret) + { + TVIDEO_FATAL("spidma_intfer ceate queue failed\r\n"); + return kGeneralErr; + } + + ret = rtos_create_thread(&tvideo_thread_hdl, + 4, + "video_intf", + (beken_thread_function_t)video_transfer_main, + 1024, + (beken_thread_arg_t)tcp_udp_mode); + if (ret != kNoErr) + { + rtos_deinit_queue(&tvideo_msg_que); + tvideo_msg_que = NULL; + tvideo_thread_hdl = NULL; + TVIDEO_FATAL("Error: Failed to create spidma_intfer: %d\r\n", ret); + return kGeneralErr; + } + } + + return kNoErr; +} + +UINT32 video_transfer_deinit(void) +{ + TVIDEO_PRT("video_transfer_deinit\r\n"); + + tvideo_intfer_send_msg(TV_EXIT); +} +#endif // (CFG_USE_SPIDMA || CFG_USE_CAMERA_INTF) + diff --git a/beken_os/beken378/func/video_transfer/video_transfer.h b/beken_os/beken378/func/video_transfer/video_transfer.h new file mode 100755 index 0000000..efc917a --- /dev/null +++ b/beken_os/beken378/func/video_transfer/video_transfer.h @@ -0,0 +1,28 @@ +#ifndef __VIDEO_TRANS_H__ +#define __VIDEO_TRANS_H__ + +typedef enum { + TVIDEO_SND_NONE = 0LU, + TVIDEO_SND_UDP, + TVIDEO_SND_TCP, +} TVIDEO_SND_TYPE; + +typedef struct tvideo_desc +{ + UINT8 *rxbuf; + + void (*node_full_handler)(void *curptr, UINT32 newlen, UINT32 is_eof, UINT32 frame_len); + void (*data_end_handler)(void); + + UINT16 rxbuf_len; + UINT16 rx_read_len; + UINT32 node_len; +} TVIDEO_DESC_ST, *TVIDEO_DESC_PTR; + +#if (CFG_USE_SPIDMA || CFG_USE_CAMERA_INTF) +void tvideo_intfer_send_msg(UINT32 new_msg); +UINT32 video_transfer_init(UINT32 tcp_udp_mode); +UINT32 video_transfer_deinit(void); +#endif + +#endif // __VIDEO_TRANS_H__ diff --git a/beken_os/beken378/func/wlan_ui/extral_cli.c b/beken_os/beken378/func/wlan_ui/extral_cli.c new file mode 100755 index 0000000..554fbae --- /dev/null +++ b/beken_os/beken378/func/wlan_ui/extral_cli.c @@ -0,0 +1,489 @@ +#include +#include +#include +#include +#include +#include + +#include "hal/soc/soc.h" +#include +#if CFG_SUPPORT_BLE +#include "ble_pub.h" +#endif +#include "vif_mgmt.h" +#include "bk7011_cal_pub.h" + +#if CFG_SUPPORT_ALIOS +#define TO_MEDIA_GENERAL_BIN 0x01 +#define TO_MEDIA_ONLY_AP_BIN 0x02 +#define TO_MEDIA_ONLY_STA_BIN 0x03 +#define TO_MEDIA_ONLY_BLE_BIN 0x04 +#define TO_MEDIA_AP_BLE_BIN 0x05 +#define TO_MEDIA_STA_BLE_BIN 0x06 +#define TO_MEDIA_AP_BLE_IDLE_BIN 0x07 +#define TO_MEDIA_STA_BLE_IDLE_BIN 0x08 + +#define TO_MEDIA_BIN (TO_MEDIA_GENERAL_BIN) + +static void softap_Command(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv); +static void sta_Command(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv); +static void ble_entry_Command(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv); +static void ap_get_info_Command(void); +static void sta_get_info_Command(void); +static void ble_get_info_Command(void); +static void linkkit_start_only_ap(void); +static void linkkit_start_only_sta(void); +static void linkkit_start_only_ble(void) ; + +static const struct cli_command user_cmd[] = { + {"softap", "softap ssid key", softap_Command}, + {"sta", "sta ap_ssid key", sta_Command}, + {"ble", "ble help/active/dut/adv", ble_entry_Command}, +}; + +#define NAME_DIF_LEN 4 +#define MAX_AP_SSID_LEN 28 +char linkkit_ap_ssid[MAX_AP_SSID_LEN + NAME_DIF_LEN] = {0}; + +#define MAX_BLE_NAME_LEN 9 +char linkkit_ble_name[MAX_BLE_NAME_LEN + NAME_DIF_LEN] = {0}; + +char name_diff[NAME_DIF_LEN+1] = {0}; + +static void linkkit_generate_name_diff(void) +{ + uint8_t mac_addr[6], *ptr; + + wifi_get_mac_address((char *)&mac_addr, 2); // get sta's mac addr + + ptr = &mac_addr[4]; + *ptr = ((*ptr & 0x0f) << 4) | ((*ptr & 0xf0) >> 4); + sprintf(&name_diff[0], "%02x", *ptr); + + ptr = &mac_addr[5]; + *ptr = ((*ptr & 0x0f) << 4) | ((*ptr & 0xf0) >> 4); + sprintf(&name_diff[2], "%02x", *ptr); + + name_diff[4] = '\0'; + + aos_cli_printf("name_diff:%s\r\n", name_diff); +} + +static void linkkit_generate_ap_ssid(char *org_ssid) +{ + uint32 len = 0; + + len = strlen(org_ssid); + len = (len > MAX_AP_SSID_LEN) ? MAX_AP_SSID_LEN : len; + + os_memcpy(linkkit_ap_ssid, org_ssid, len); + os_memcpy(&linkkit_ap_ssid[len], name_diff, NAME_DIF_LEN); +} + +static void linkkit_generate_ble_name(char *org_name) +{ + uint32 len = 0; + + len = strlen(org_name); + len = (len > MAX_BLE_NAME_LEN) ? MAX_BLE_NAME_LEN : len; + + os_memcpy(linkkit_ble_name, org_name, len); + os_memcpy(&linkkit_ble_name[len], &name_diff[1], NAME_DIF_LEN-1); +} + +static void linkkit_wlan_start_ap(const char *ap_ssid, int ap_key) +{ +#define LINK_WLAN_DEFAULT_IP "192.168.0.1" +#define LINK_WLAN_DEFAULT_GW "192.168.0.1" +#define LINK_WLAN_DEFAULT_MASK "255.255.255.0" + + hal_wifi_init_type_t type; + int len; + + os_memset(&type, 0x0, sizeof(hal_wifi_init_type_t)); + + len = os_strlen(ap_ssid); + if(32 < len) + { + bk_printf("ssid name more than 32 Bytes\r\n"); + return; + } + + os_strcpy((char *)type.wifi_ssid, ap_ssid); + os_strcpy((char *)type.wifi_key, ap_key); + + type.wifi_mode = SOFT_AP; + type.dhcp_mode = DHCP_SERVER; + type.wifi_retry_interval = 100; + os_strcpy((char *)type.local_ip_addr, LINK_WLAN_DEFAULT_IP); + os_strcpy((char *)type.net_mask, LINK_WLAN_DEFAULT_MASK); + os_strcpy((char *)type.dns_server_ip_addr, LINK_WLAN_DEFAULT_GW); + + aos_cli_printf("ssid:%s key:%s\r\n", type.wifi_ssid, type.wifi_key); + bk_wlan_start(&type); +} + +static void linkkit_softap_usage(void) +{ + aos_cli_printf("softap help - Help information\n"); + aos_cli_printf("softap info - list softap info\n"); + aos_cli_printf("softap [ssid] [key] - start wlan with softap with ssdi+key\n"); + aos_cli_printf("softap - start wlan with BK7231AP-V1-xxxx,no key\r\n"); +} + +static void softap_Command(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + char *ap_ssid = NULL; + char *ap_key; + + aos_cli_printf("SOFTAP_COMMAND\r\n\r\n"); + if (argc == 2) + { + if(!os_strcasecmp(argv[1], "info")) { + ap_get_info_Command(); + return; + } else if(!os_strcasecmp(argv[1], "help")){ + linkkit_softap_usage(); + return; + } + + ap_ssid = argv[1]; + ap_key = "1"; + } + else if (argc == 3) + { + ap_ssid = argv[1]; + ap_key = argv[2]; + } else if (argc == 1) { + linkkit_start_only_ap(); + } + + if(ap_ssid) + { + linkkit_wlan_start_ap(ap_ssid, ap_key); + } +} + +static void linkkit_wlan_connect_ap(const char *oob_ssid, int connect_key) +{ + hal_wifi_init_type_t type; + + int len; + os_memset(&type, 0x0, sizeof(hal_wifi_init_type_t)); + + len = os_strlen(oob_ssid); + if(32 < len) + { + bk_printf("ssid name more than 32 Bytes\r\n"); + return; + } + + os_strcpy((char *)type.wifi_ssid, oob_ssid); + os_strcpy((char *)type.wifi_key, connect_key); + + type.wifi_mode = STATION; + type.dhcp_mode = DHCP_CLIENT; + type.wifi_retry_interval = 100; + + bk_printf("ssid:%s key:%s\r\n", type.wifi_ssid, type.wifi_key); + bk_wlan_start(&type); +} + +static void linkkit_sta_usage(void) +{ + aos_cli_printf("sta help - Help information\n"); + aos_cli_printf("sta info - list sta info\n"); + aos_cli_printf("sta [ssid] [key] - start wlan as sta to connect to router with ssdi+key\n"); + aos_cli_printf("sta - start wlan as sta to connect BK7231STA-V1,no key\n"); +} + +static void sta_Command(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + char *oob_ssid = NULL; + char *connect_key; + + aos_cli_printf("sta_Command\r\n"); + if (argc == 2) + { + if(!os_strcasecmp(argv[1], "info")) { + sta_get_info_Command(); + return; + } else if(!os_strcasecmp(argv[1], "help")){ + linkkit_sta_usage(); + return; + } + + oob_ssid = argv[1]; + connect_key = "1"; + } + else if (argc == 3) + { + oob_ssid = argv[1]; + connect_key = argv[2]; + } + else if (argc == 1) { + linkkit_start_only_sta(); + } + else + { + aos_cli_printf("parameter invalid\r\n"); + } + + if(oob_ssid) + { + linkkit_wlan_connect_ap(oob_ssid, connect_key); + } +} + +static void linkkit_ble_usage(void) +{ + aos_cli_printf("ble help - Help information\n"); + aos_cli_printf("ble active [name] - Active ble to with name\n"); + aos_cli_printf("ble active - Active ble to with BK7231BTxxx\n"); + aos_cli_printf("ble dut - Active ble to do BLE DUT\n"); + aos_cli_printf("ble info - get ble app info\n"); +} + +static void ble_set_adv_data(char *buf, int len, int argc, char **argv) +{ + int i; + + bk_printf("%s argc %d\r\n",__func__,argc); + for(i=0;i time_ms) {// RTS match + rts_match = 1; + } + for(i=0; i-5) && (delta<5)) { // DO report for each RSSI match. + report_lsig(len, rssi, i); + reported++; + } + } + } + if ((rts_match != 1) || (reported != 0)) + return; + + // new entry + if (rts_tbl_num < MAX_RTS_TBL) { + os_memcpy(rts_tbl[rts_tbl_num].ra, last_rts.ra, 12); + rts_tbl[rts_tbl_num].security = 0xFF; + rts_tbl[rts_tbl_num].rssi = rssi; + rts_tbl[rts_tbl_num].last_time = rtos_get_time(); + rts_tbl[rts_tbl_num].last_len = len; + rts_tbl_num++; + return; + } + + // replace old entry. + rep_index = 0; + min_time = rts_tbl[0].last_time; + for(i=1; i rts_tbl[i].last_time) { + min_time = rts_tbl[i].last_time; + rep_index = i; + } + } + + os_memcpy(rts_tbl[rep_index].ra, last_rts.ra, 12); + rts_tbl[rep_index].security = 0xFF; + rts_tbl[rep_index].rssi = rssi; + rts_tbl[rep_index].last_len = len; + rts_tbl[rep_index].last_time = rtos_get_time(); +} + + diff --git a/beken_os/beken378/func/wlan_ui/wlan_cli.c b/beken_os/beken378/func/wlan_ui/wlan_cli.c new file mode 100755 index 0000000..8f5ae36 --- /dev/null +++ b/beken_os/beken378/func/wlan_ui/wlan_cli.c @@ -0,0 +1,2578 @@ +/** + * UNPUBLISHED PROPRIETARY SOURCE CODE + * Copyright (c) 2016 BEKEN Inc. + * + * The contents of this file may not be disclosed to third parties, copied or + * duplicated in any form, in whole or in part, without the prior written + * permission of BEKEN Corporation. + * + */ +#include "sys_rtos.h" +#include "rtos_pub.h" +#include "rtos_error.h" +#include "wlan_cli_pub.h" +#include "stdarg.h" +#include "include.h" +#include "mem_pub.h" +#include "str_pub.h" +#include "uart_pub.h" +#include "BkDriverFlash.h" +#include "wlan_ui_pub.h" +#include "param_config.h" +#include "gpio_pub.h" +#include "sys_ctrl_pub.h" +#include "icu_pub.h" +#include "power_save_pub.h" +#include "cmd_rx_sensitivity.h" +#include "cmd_evm.h" +#include "BkDriverGpio.h" +#include "command_line.h" +#include "role_launch.h" +#include "wdt_pub.h" +#include "saradc_pub.h" +#include "bk7011_cal_pub.h" +#include "flash_pub.h" +#include "mcu_ps_pub.h" +#include "ate_app.h" +#include "BkDriverPwm.h" +#include "ieee802_11_demo.h" + +#if CFG_SUPPORT_BOOTLOADER +#include "wdt_pub.h" +#include "lwip/sockets.h" +#include "lwip/ip_addr.h" +#include "lwip/inet.h" +#endif + +#include "temp_detect_pub.h" +#if CFG_SUPPORT_OTA_HTTP +#include "utils_httpc.h" +#endif + +#include "start_type_pub.h" + +#if CFG_ENABLE_ATE_FEATURE +static void pwm_command(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv); + +#ifndef MOC +static void task_Command( char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv ); +#endif + +#if CFG_SUPPORT_BKREG +extern int bkreg_run_command(const char *content, int cnt); +#endif + +int mico_debug_enabled; +char log_buf[LOG_SERVICE_BUFLEN]; +static struct cli_st *pCli = NULL; +beken_semaphore_t log_rx_interrupt_sema = NULL; + +extern u8* wpas_get_sta_psk(void); +extern int cli_putstr(const char *msg); + +#if CFG_SUPPORT_BKREG +void bkreg_cmd_handle_input(char *inbuf, int len); +#endif + +extern int hexstr2bin(const char *hex, u8 *buf, size_t len); + +#if CFG_SUPPORT_OTA_HTTP +extern int httpclient_common(httpclient_t *client, + const char *url, + int port, + const char *ca_crt, + int method, + uint32_t timeout_ms, + httpclient_data_t *client_data); +#endif + +#if CFG_SARADC_CALIBRATE +static void adc_command(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv); +#endif + +void cli_rx_callback(int uport, void *param); + +#if (CFG_SOC_NAME != SOC_BK7231) +static void efuse_cmd_test(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv); +static void efuse_mac_cmd_test(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv); +#endif + +#if CFG_SUPPORT_BKREG +#define BKREG_MAGIC_WORD0 (0x01) +#define BKREG_MAGIC_WORD1 (0xE0) +#define BKREG_MAGIC_WORD2 (0xFC) +#define BKREG_MIN_LEN 3 +#endif + +/* Find the command 'name' in the cli commands table. +* If len is 0 then full match will be performed else upto len bytes. +* Returns: a pointer to the corresponding cli_command struct or NULL. +*/ +static const struct cli_command *lookup_command(char *name, int len) +{ + int i = 0; + int n = 0; + + while (i < MAX_COMMANDS && n < pCli->num_commands) + { + if (pCli->commands[i]->name == NULL) + { + i++; + continue; + } + /* See if partial or full match is expected */ + if (len != 0) + { + if (!os_strncmp(pCli->commands[i]->name, name, len)) + return pCli->commands[i]; + } + else + { + if (!os_strcmp(pCli->commands[i]->name, name)) + return pCli->commands[i]; + } + + i++; + n++; + } + + return NULL; +} + +/* Parse input line and locate arguments (if any), keeping count of the number +* of arguments and their locations. Look up and call the corresponding cli +* function if one is found and pass it the argv array. +* +* Returns: 0 on success: the input line contained at least a function name and +* that function exists and was called. +* 1 on lookup failure: there is no corresponding function for the +* input line. +* 2 on invalid syntax: the arguments list couldn't be parsed +*/ +static int handle_input(char *inbuf) +{ + struct + { + unsigned inArg: 1; + unsigned inQuote: 1; + unsigned done: 1; + } stat; + static char *argv[20]; + int argc = 0; + int i = 0; + const struct cli_command *command = NULL; + const char *p; + + os_memset((void *)&argv, 0, sizeof(argv)); + os_memset(&stat, 0, sizeof(stat)); + + do + { + switch (inbuf[i]) + { + case '\0': + if (stat.inQuote) + return 2; + stat.done = 1; + break; + + case '"': + if (i > 0 && inbuf[i - 1] == '\\' && stat.inArg) + { + os_memcpy(&inbuf[i - 1], &inbuf[i], + os_strlen(&inbuf[i]) + 1); + --i; + break; + } + if (!stat.inQuote && stat.inArg) + break; + if (stat.inQuote && !stat.inArg) + return 2; + + if (!stat.inQuote && !stat.inArg) + { + stat.inArg = 1; + stat.inQuote = 1; + argc++; + argv[argc - 1] = &inbuf[i + 1]; + } + else if (stat.inQuote && stat.inArg) + { + stat.inArg = 0; + stat.inQuote = 0; + inbuf[i] = '\0'; + } + break; + + case ' ': + if (i > 0 && inbuf[i - 1] == '\\' && stat.inArg) + { + os_memcpy(&inbuf[i - 1], &inbuf[i], + os_strlen(&inbuf[i]) + 1); + --i; + break; + } + if (!stat.inQuote && stat.inArg) + { + stat.inArg = 0; + inbuf[i] = '\0'; + } + break; + + default: + if (!stat.inArg) + { + stat.inArg = 1; + argc++; + argv[argc - 1] = &inbuf[i]; + } + break; + } + } + while (!stat.done && ++i < INBUF_SIZE); + + if (stat.inQuote) + return 2; + + if (argc < 1) + return 0; + + if (!pCli->echo_disabled) + os_printf("\r\n"); + + /* + * Some comamands can allow extensions like foo.a, foo.b and hence + * compare commands before first dot. + */ + i = ((p = os_strchr(argv[0], '.')) == NULL) ? 0 : + (p - argv[0]); + command = lookup_command(argv[0], i); + if (command == NULL) + return 1; + + os_memset(pCli->outbuf, 0, OUTBUF_SIZE); + cli_putstr("\r\n"); + + #if CFG_USE_STA_PS + /*if cmd,exit dtim ps*/ + if (os_strncmp(command->name, "ps", 2)) + { + } + #endif + + command->function(pCli->outbuf, OUTBUF_SIZE, argc, argv); + cli_putstr(pCli->outbuf); + return 0; +} + +/* Perform basic tab-completion on the input buffer by string-matching the +* current input line against the cli functions table. The current input line +* is assumed to be NULL-terminated. */ +static void tab_complete(char *inbuf, unsigned int *bp) +{ + int i, n, m; + const char *fm = NULL; + + os_printf("\r\n"); + + /* show matching commands */ + for (i = 0, n = 0, m = 0; i < MAX_COMMANDS && n < pCli->num_commands; + i++) + { + if (pCli->commands[i]->name != NULL) + { + if (!os_strncmp(inbuf, pCli->commands[i]->name, *bp)) + { + m++; + if (m == 1) + fm = pCli->commands[i]->name; + else if (m == 2) + os_printf("%s %s ", fm, + pCli->commands[i]->name); + else + os_printf("%s ", + pCli->commands[i]->name); + } + n++; + } + } + + /* there's only one match, so complete the line */ + if (m == 1 && fm) + { + n = os_strlen(fm) - *bp; + if (*bp + n < INBUF_SIZE) + { + os_memcpy(inbuf + *bp, fm + *bp, n); + *bp += n; + inbuf[(*bp)++] = ' '; + inbuf[*bp] = '\0'; + } + } + + /* just redraw input line */ + os_printf("%s%s", PROMPT, inbuf); +} + +/* Get an input line. +* +* Returns: 1 if there is input, 0 if the line should be ignored. */ +static int get_input(char *inbuf, unsigned int *bp) +{ + if (inbuf == NULL) + { + os_printf("inbuf_null\r\n"); + return 0; + } + + while (cli_getchar(&inbuf[*bp]) == 1) + { +#if CFG_SUPPORT_BKREG + if(get_ate_mode_state()) + { + if((0x01U == (UINT8)inbuf[*bp]) && (*bp == 0)) { + (*bp)++; + continue; + } else if((0xe0U == (UINT8)inbuf[*bp]) && (*bp == 1)) { + (*bp)++; + continue; + } else if((0xfcU == (UINT8)inbuf[*bp]) && (*bp == 2)) { + (*bp)++; + continue; + } else { + if((0x01U == (UINT8)inbuf[0]) + && (0xe0U == (UINT8)inbuf[1]) + && (0xfcU == (UINT8)inbuf[2]) + && (*bp == 3)) + { + char ch = inbuf[*bp]; + int left = (int)ch, len = 4 + (int)ch; + inbuf[*bp] = ch; + (*bp)++; + + while(left--) { + if(0 == cli_getchar(&ch)) + { + memset(inbuf, 0, len); + *bp = 0; + + return 0; + } + + inbuf[*bp] = ch; + (*bp)++; + } + + bkreg_run_command(inbuf, len); + + memset(inbuf, 0, len); + *bp = 0; + + continue; + } + } + } +#endif + if (inbuf[*bp] == RET_CHAR) + continue; + if (inbuf[*bp] == END_CHAR) /* end of input line */ + { + inbuf[*bp] = '\0'; + *bp = 0; + return 1; + } + + if ((inbuf[*bp] == 0x08) || /* backspace */ + (inbuf[*bp] == 0x7f)) /* DEL */ + { + if (*bp > 0) + { + (*bp)--; + if (!pCli->echo_disabled) + os_printf("%c %c", 0x08, 0x08); + } + continue; + } + + if (inbuf[*bp] == '\t') + { + inbuf[*bp] = '\0'; + tab_complete(inbuf, bp); + continue; + } + + if (!pCli->echo_disabled) + os_printf("%c", inbuf[*bp]); + + (*bp)++; + if (*bp >= INBUF_SIZE) + { + os_printf("Error: input buffer overflow\r\n"); + os_printf(PROMPT); + *bp = 0; + return 0; + } + + } + + return 0; +} + +/* Print out a bad command string, including a hex +* representation of non-printable characters. +* Non-printable characters show as "\0xXX". +*/ +static void print_bad_command(char *cmd_string) +{ + if (cmd_string != NULL) + { + char *c = cmd_string; + os_printf("command '"); + while (*c != '\0') + { + if (is_print(*c)) + { + os_printf("%c", *c); + } + else + { + os_printf("\\0x%x", *c); + } + ++c; + } + os_printf("' not found\r\n"); + } +} + +/* Main CLI processing thread +* +* Waits to receive a command buffer pointer from an input collector, and +* then processes. Note that it must cleanup the buffer when done with it. +* +* Input collectors handle their own lexical analysis and must pass complete +* command lines to CLI. +*/ +static void cli_main( uint32_t data ) +{ + bk_uart_set_rx_callback(CLI_UART, cli_rx_callback, NULL); + while (1) + { + int ret; + char *msg = NULL; + + rtos_get_semaphore(&log_rx_interrupt_sema, BEKEN_NEVER_TIMEOUT); + + while(get_input(pCli->inbuf, &pCli->bp)) + { + msg = pCli->inbuf; + + if (os_strcmp(msg, EXIT_MSG) == 0) + break; + + ret = handle_input(msg); + if (ret == 1) + print_bad_command(msg); + else if (ret == 2) + os_printf("syntax error\r\n"); + + os_printf(PROMPT); + } + } + + os_printf("CLI exited\r\n"); + os_free(pCli); + pCli = NULL; + + bk_uart_set_rx_callback(CLI_UART, NULL, NULL); + rtos_delete_thread(NULL); +} + +#ifndef MOC +static void task_Command( char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv ) +{ + rtos_print_thread_status( pcWriteBuffer, xWriteBufferLen ); +} +#endif + +void tftp_Command(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ +} + +static void partShow_Command(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + bk_partition_t i; + bk_logic_partition_t *partition; + + for( i = BK_PARTITION_BOOTLOADER; i <= BK_PARTITION_MAX; i++ ) + { + partition = bk_flash_get_info( i ); + if (partition == NULL) + continue; + + os_printf( "%4d | %11s | Dev:%d | 0x%08lx | 0x%08lx |\r\n", i, + partition->partition_description, partition->partition_owner, + partition->partition_start_addr, partition->partition_length); + }; + +} + +static void uptime_Command(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + os_printf("UP time %ldms\r\n", rtos_get_time()); +} + +void tftp_ota_thread( beken_thread_arg_t arg ) +{ + rtos_delete_thread( NULL ); +} + +void ota_Command( char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv ) +{ + rtos_create_thread( NULL, + BEKEN_APPLICATION_PRIORITY, + "LOCAL OTA", + (beken_thread_function_t)tftp_ota_thread, + 0x4096, + 0 ); +} + +void help_command(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv); + +/* +* Command buffer API +*/ +void wifiscan_Command(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ +#if CFG_ROLE_LAUNCH + LAUNCH_REQ param; + + param.req_type = LAUNCH_REQ_PURE_STA_SCAN; + rl_sta_request_enter(¶m, 0); +#else + demo_scan_app_init(); +#endif +} + +extern void demo_scan_adv_app_init(uint8_t *oob_ssid); +void wifiadvscan_Command(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + uint8_t *ap_ssid; + + if ( argc < 2 ) + { + os_printf("Please input ssid\r\n"); + return; + } + ap_ssid = (uint8_t *)argv[1]; + + demo_scan_adv_app_init(ap_ssid); +} + +extern void demo_softap_app_init(char *ap_ssid, char *ap_key); +void softap_Command(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + char *ap_ssid = NULL; + char *ap_key; + + os_printf("SOFTAP_COMMAND\r\n\r\n"); + if (argc == 2) + { + ap_ssid = argv[1]; + ap_key = "1"; + } + else if (argc == 3) + { + ap_ssid = argv[1]; + ap_key = argv[2]; + } + + if(ap_ssid) + { + demo_softap_app_init(ap_ssid, ap_key); + } +} + +void stop_wlan_intface_Command(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + uint8_t inface = 0; + + os_printf("stop_wlan_intface_Command\r\n"); + if (argc == 2) + { + inface = strtoul(argv[1], NULL, 0); + os_printf("stop wlan intface:%d\r\n", inface); + + if(inface == 0) + { + bk_wlan_stop(SOFT_AP); + } + else if(inface == 1) + { + bk_wlan_stop(STATION); + } + } + else + { + os_printf("bad parameters\r\n"); + } +} +extern void demo_wlan_app_init(VIF_ADDCFG_PTR cfg); +void add_virtual_intface(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + VIF_ADDCFG_ST cfg; + u8 argc_cnt = 1; + + if(argc <= 1) + return; + + if (!os_strncmp(argv[argc_cnt], "softap", sizeof("softap"))) + { + cfg.wlan_role = SOFT_AP; + } + else if (!os_strncmp(argv[argc_cnt], "sta", sizeof("sta"))) + { + cfg.wlan_role = STATION; + } + else + { + os_printf("role error:%s, must be softap or sta\r\n", argv[argc_cnt]); + return; + } + argc_cnt++; + + if(argc == argc_cnt) + cfg.ssid = "default ssid"; + else + cfg.ssid = argv[argc_cnt]; + argc_cnt++; + + if(argc == argc_cnt) + cfg.key = "1234567890"; + else + cfg.key = argv[argc_cnt]; + argc_cnt++; + + if((cfg.wlan_role == STATION) && (argc > argc_cnt)) + { + if (!os_strncmp(argv[argc_cnt], "adv", sizeof("adv"))) + cfg.adv = 1; + else + cfg.adv = 0; + } + else + { + cfg.adv = 0; + } + argc_cnt++; + + cfg.name = NULL; + + os_printf("role: %d\r\n", cfg.wlan_role); + os_printf("ssid: %s\r\n", cfg.ssid); + os_printf("key : %s\r\n", cfg.key); + os_printf("adv : %d\r\n", cfg.adv); + + demo_wlan_app_init(&cfg); +} + +void del_virtual_intface(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + char *type; + u8 role = 0xff; + + #if CFG_ROLE_LAUNCH + LAUNCH_REQ param; + #endif + + if(argc <= 1) + return; + + type = argv[1]; + + if (!os_strncmp(type, "softap", sizeof("softap"))) + { + role = SOFT_AP; + + #if CFG_ROLE_LAUNCH + param.req_type = LAUNCH_REQ_DELIF_AP; + + rl_ap_request_enter(¶m, 0); + #endif + } + else if(!os_strncmp(type, "sta", sizeof("sta"))) + { + role = STATION; + + #if CFG_ROLE_LAUNCH + param.req_type = LAUNCH_REQ_DELIF_STA; + + rl_sta_request_enter(¶m, 0); + #endif + } + + if(role == 0xff) + { + os_printf("%s virtual intface not found\r\n", type ); + return; + } + +#if (0 == CFG_ROLE_LAUNCH) + bk_wlan_stop(role); +#endif +} + +void show_virtual_intface(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + u8 i = 1; + u8 *mac_ptr; + char *role; + const char *name; + struct netif *lwip_if; + VIF_INF_PTR vif_entry; + + os_printf("\r\nshow_virtual_intface:\r\n"); + vif_entry = (VIF_INF_PTR)rwm_mgmt_is_vif_first_used(); + while(vif_entry) + { + mac_ptr = (u8 *)&vif_entry->mac_addr; + lwip_if = (struct netif *)vif_entry->priv; + name = lwip_if->hostname; + if(vif_entry->type == VIF_AP) + { + role = "softap\0"; + } + else if(vif_entry->type == VIF_STA) + { + role = "sta\0"; + } + else + { + role = "others\0"; + } + + os_printf("%1d: %s, %s, %02x:%02x:%02x:%02x:%02x:%02x\r\n", i, name, role, + mac_ptr[0], mac_ptr[1], mac_ptr[2], mac_ptr[3], mac_ptr[4], mac_ptr[5]); + + vif_entry = (VIF_INF_PTR)rwm_mgmt_next(vif_entry); + i++; + } + + os_printf("\r\nend of show\r\n"); + +} +#if 1 +uint32_t channel_count = 0; +void cli_monitor_cb(uint8_t *data, int len, hal_wifi_link_info_t *info) +{ + uint32_t count, i; + + count = MIN(32, len); + os_printf("cli_monitor_cb:%d:%d\r\n", count, len); + for(i = 0; i < count; i ++) + { + os_printf("%x ", data[i]); + } + os_printf("\r\n"); + + channel_count ++; +} + +xTaskHandle mtr_thread_handle = NULL; +uint32_t mtr_stack_size = 2000; +#define THD_MTR_PRIORITY 5 + +void mtr_thread_main( void *arg ) +{ + OSStatus ret; + static uint32_t channel_num = 1; + + // stop monitor mode, need stop hal mac first + bk_wlan_stop_monitor(); + // then set monitor callback + bk_wlan_register_monitor_cb(NULL); + + // start monitor, need set callback + bk_wlan_register_monitor_cb(cli_monitor_cb); + // then start hal mac + bk_wlan_start_monitor(); + + while(1) + { + channel_count = 0; + + bk_wlan_set_channel_sync(channel_num); + channel_num ++; + + if(14 == channel_num) + { + channel_num = 1; + } + + rtos_delay_milliseconds(100); + os_printf("channel:%d count:%x\r\n", channel_num, channel_count); + } + (void)ret; +} +#endif + +void mtr_Command(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + OSStatus ret; + + if(argc != 2) + { + os_printf("monitor_parameter invalid\r\n"); + return; + } +#if 0 + if(NULL == mtr_thread_handle) + { + ret = rtos_create_thread(&mtr_thread_handle, + THD_MTR_PRIORITY, + "mtr", + (beken_thread_function_t)mtr_thread_main, + (unsigned short)mtr_stack_size, + (beken_thread_arg_t)0); + ASSERT(kNoErr == ret); + } +#else + uint32_t channel_num; + + channel_num = os_strtoul(argv[1], NULL, 10); + if(99 == channel_num) + { + bk_wlan_stop_monitor(); + } + else + { + bk_wlan_register_monitor_cb(cli_monitor_cb); + bk_wlan_start_monitor(); + bk_wlan_set_channel_sync(channel_num); + } + (void)ret; +#endif +} +extern void demo_sta_adv_app_init(char *oob_ssid,char *connect_key); +void sta_adv_Command(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + char *oob_ssid = NULL; + char *connect_key; + + os_printf("sta_adv_Command\r\n"); + if (argc == 2) + { + oob_ssid = argv[1]; + connect_key = "1"; + } + else if (argc == 3) + { + oob_ssid = argv[1]; + connect_key = argv[2]; + } + else + { + os_printf("parameter invalid\r\n"); + return; + } + + if(oob_ssid) + { + demo_sta_adv_app_init(oob_ssid, connect_key); + } +} + +void show_sta_psk(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + uint8_t *psk; + int i; + + psk = wpas_get_sta_psk(); + os_printf("John# show_sta_psk.r\n"); + for ( i = 0 ; i < 32 ; i++ ) + { + os_printf("%02x ", psk[i]); + } + os_printf("\r\n"); +} +extern void demo_sta_app_init(char *oob_ssid,char *connect_key); +void sta_Command(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + char *oob_ssid = NULL; + char *connect_key; + + os_printf("sta_Command\r\n"); + if (argc == 2) + { + oob_ssid = argv[1]; + connect_key = "1"; + } + else if (argc == 3) + { + oob_ssid = argv[1]; + connect_key = argv[2]; + } + else + { + os_printf("parameter invalid\r\n"); + } + + if(oob_ssid) + { + demo_sta_app_init(oob_ssid, connect_key); + } +} + +#if (CFG_SOC_NAME == SOC_BK7231U) || (CFG_SOC_NAME == SOC_BK7231N) +#if (CFG_SOC_NAME == SOC_BK7231N) +#include "app_ble.h" +#include "ble_ui.h" +#endif +static void ble_entry_Command(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + if (strcmp(argv[1], "adv") == 0) + { +#if (CFG_SOC_NAME == SOC_BK7231U) + os_printf("Start adv\r\n"); + appm_start_advertising(); +#endif + } + else if (strcmp(argv[1], "dut") == 0) + { + ble_dut_start(); + } +#if (CFG_SOC_NAME == SOC_BK7231U) + else if (strcmp(argv[1], "active") == 0) + { + char *name = NULL; + if(argc == 3) { + name = argv[2]; + ble_activate(name); + }else if(argc == 2){ + //linkkit_start_only_ble(); + os_printf("Activate BLE\r\n"); + ble_activate(NULL); + } + + } +#endif + + return; +} +#endif + +void easylink_Command(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + /* mxchip_easy_link_start(120);*/ +} + +#if 0 +void airkiss_Command(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + u8 start = 0; + + if(argc != 2) + { + os_printf("need 2 parameters: airkiss 1(start), 0(stop)\r\n"); + return; + } + + start = strtoul(argv[1], NULL, 0); + + airkiss_process(start); +} +#endif + +#if CFG_USE_TEMPERATURE_DETECT +void temp_detect_Command(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + u8 start = 0; + + if(argc != 2) + { + os_printf("need 2 parameters: airkiss 1(start), 0(stop)\r\n"); + return; + } + + start = strtoul(argv[1], NULL, 0); + + if(start == 0) + temp_detect_pause_timer(); + else + temp_detect_restart_detect(); +} +#endif +extern void demo_state_app_init(void); +void wifistate_Command(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + os_printf("wifistate_Command\r\n"); + demo_state_app_init(); +} + +void wifidebug_Command(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + os_printf("wifidebug_Command\r\n"); +} +extern void demo_ip_app_init(void); +void ifconfig_Command(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + demo_ip_app_init(); +} + +void arp_Command(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + os_printf("arp_Command\r\n"); +} + +void ping_Command(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + os_printf("ping_Command\r\n"); +} + +void dns_Command(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + os_printf("dns_Command\r\n"); +} + +void socket_show_Command(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + os_printf("socket_show_Command\r\n"); +} + +void memory_show_Command(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + cmd_printf("free memory %d\r\n", xPortGetFreeHeapSize()); +} + +void memory_dump_Command( char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv ) +{ + int i; + uint8_t *pstart; + uint32_t start, length; + + if (argc != 3) + { + cmd_printf("Usage: memdump .\r\n"); + return; + } + + start = strtoul(argv[1], NULL, 0); + length = strtoul(argv[2], NULL, 0); + pstart = (uint8_t *)start; + + for(i = 0; i < length; i++) + { + cmd_printf("%02x ", pstart[i]); + if (i % 0x10 == 0x0F) + { + cmd_printf("\r\n"); + + } + } +} + + +void memory_set_Command(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + os_printf("memory_set_Command\r\n"); +} + +void driver_state_Command(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + os_printf("driver_state_Command\r\n"); +} + +void get_version(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + os_printf("get_version\r\n"); +} + +void reboot(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + bk_reboot(); +} + +static void echo_cmd_handler(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + if (argc == 1) + { + os_printf("Usage: echo on/off. Echo is currently %s\r\n", + pCli->echo_disabled ? "Disabled" : "Enabled"); + return; + } + + if (!os_strcasecmp(argv[1], "on")) + { + os_printf("Enable echo\r\n"); + pCli->echo_disabled = 0; + } + else if (!os_strcasecmp(argv[1], "off")) + { + os_printf("Disable echo\r\n"); + pCli->echo_disabled = 1; + } +} + +static void cli_exit_handler(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + // exit command not executed +} + +/* +CMD FORMAT: GPIO CMD index PARAM +exmaple:GPIO 0 18 2 (config GPIO18 input & pull-up) +*/ +static void Gpio_op_Command(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + uint32_t ret, id, mode, i; + char cmd0 = 0; + char cmd1 = 0; + char cmd; + + for(i = 0; i < argc; i++) + { + os_printf("Argument %d = %s\r\n", i + 1, argv[i]); + } + + if(argc == 4) + { + cmd = argv[1][0]; + mode = argv[3][0]; + + cmd0 = argv[2][0] - 0x30; + cmd1 = argv[2][1] - 0x30; + + id = (uint32_t)(cmd0 * 10 + cmd1); + os_printf("---%x,%x----\r\n", id, mode); + ret = BKGpioOp(cmd, id, mode); + os_printf("gpio op:%x\r\n", ret); + } + else + os_printf("cmd param error\r\n"); +} + +void test_fun(char para) +{ + os_printf("---%d---\r\n", para); +} +/* +cmd format: GPIO_INT cmd index triggermode +enable: GPIO_INT 1 18 0 +*/ +static void Gpio_int_Command(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + uint32_t id, mode; + char cmd0 = 0; + char cmd1 = 0; + char cmd; + + if(argc == 4) + { + cmd = argv[1][0] - 0x30; + mode = argv[3][0] - 0x30; + + cmd0 = argv[2][0] - 0x30; + cmd1 = argv[2][1] - 0x30; + + id = (uint32_t)(cmd0 * 10 + cmd1); + BKGpioIntcEn(cmd, id, mode, test_fun); + } + else + os_printf("cmd param error\r\n"); + +} + + +#if CFG_USE_SDCARD_HOST +/* +sdtest I 0 -- +sdtest R secnum +sdtest W secnum +*/ +extern uint32_t sdcard_intf_test(void); +extern uint32_t test_sdcard_read(uint32_t blk); +extern uint32_t test_sdcard_write(uint32_t blk); +extern void sdcard_intf_close(void); + +static void sd_operate(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + uint32_t cmd; + uint32_t blknum; + uint32_t ret; + if(argc == 3) + { + cmd = argv[1][0]; + blknum = os_strtoul(argv[2], NULL, 16); + switch(cmd) + { + case 'I': + ret = sdcard_intf_test(); + os_printf("init :%x\r\n", ret); + break; + case 'R': + ret = test_sdcard_read(blknum); + os_printf("read :%x\r\n", ret); + break; + case 'W': + ret = test_sdcard_write(blknum); + os_printf("write :%x\r\n", ret); + break; + case 'C': + sdcard_intf_close(); + os_printf("close \r\n"); + break; + default: + break; + } + } + else + os_printf("cmd param error\r\n"); +} + +#endif +/* +format: FLASH E/R/W 0xABCD +example: FLASH R 0x00100 + +*/ + +extern OSStatus test_flash_write(volatile uint32_t start_addr, uint32_t len); +extern OSStatus test_flash_erase(volatile uint32_t start_addr, uint32_t len); +extern OSStatus test_flash_read(volatile uint32_t start_addr, uint32_t len); +extern OSStatus test_flash_read_time(volatile uint32_t start_addr, uint32_t len); + +static void flash_command_test(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + char cmd = 0; + uint32_t len = 0; + uint32_t addr = 0; + + if(argc == 4) + { + cmd = argv[1][0]; + addr = atoi(argv[2]); + len = atoi(argv[3]); + + switch(cmd) + { + case 'E': + bk_flash_enable_security(FLASH_PROTECT_NONE); + test_flash_erase(addr,len); + bk_flash_enable_security(FLASH_UNPROTECT_LAST_BLOCK); + break; + + case 'R': + test_flash_read(addr,len); + break; + case 'W': + bk_flash_enable_security(FLASH_PROTECT_NONE); + test_flash_write(addr,len); + bk_flash_enable_security(FLASH_UNPROTECT_LAST_BLOCK); + break; + //to check whether protection mechanism can work + case 'N': + test_flash_erase(addr,len); + break; + case 'M': + test_flash_write(addr,len); + break; + case 'T': + test_flash_read_time(addr,len); + break; + default: + break; + } + } + else + { + os_printf("FLASH \r\n"); + } +} + +/*UART I index +example: UART I 0 +*/ +static void tx_evm_cmd_test(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + int ret = do_evm(NULL, 0, argc, argv); + if(ret) + { + os_printf("tx_evm bad parameters\r\n"); + } +} + +static void rx_sens_cmd_test(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + int ret = do_rx_sensitivity(NULL, 0, argc, argv); + if(ret) + { + os_printf("rx sensitivity bad parameters\r\n"); + } +} + +#if (CFG_SOC_NAME != SOC_BK7231) +static void efuse_cmd_test(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + uint8_t addr, data; + + if(argc == 3) + { + if (os_strncmp(argv[1], "-r", 2) == 0) { + hexstr2bin(argv[2], &addr, 1); + os_printf("efuse read: addr-0x%02x, data-0x%02x\r\n", + addr, wifi_read_efuse(addr)); + } + } + else if(argc == 4) + { + if(os_strncmp(argv[1], "-w", 2) == 0) { + hexstr2bin(argv[2], &addr, 1); + hexstr2bin(argv[3], &data, 6); + os_printf("efuse write: addr-0x%02x, data-0x%02x, ret:%d\r\n", + addr, data, wifi_write_efuse(addr, data)); + } + } + else { + os_printf("efuse [-r addr] [-w addr data]\r\n"); + } +} + +static void efuse_mac_cmd_test(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + uint8_t mac[6]; + + if (argc == 1) + { + if(wifi_get_mac_address_from_efuse(mac)) + os_printf("MAC address: %02x-%02x-%02x-%02x-%02x-%02x\r\n", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + } + else if(argc == 2) + { + if (os_strncmp(argv[1], "-r", 2) == 0) { + if(wifi_get_mac_address_from_efuse(mac)) + os_printf("MAC address: %02x-%02x-%02x-%02x-%02x-%02x\r\n", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + } + } + else if(argc == 3) + { + if(os_strncmp(argv[1], "-w", 2) == 0) { + hexstr2bin(argv[2], mac, 6); + //if(wifi_set_mac_address_to_efuse(mac)) + os_printf("Set MAC address: %02x-%02x-%02x-%02x-%02x-%02x\r\n", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + } + } + else { + os_printf("efusemac [-r] [-w] [mac]\r\n"); + } +} +#endif //(CFG_SOC_NAME != SOC_BK7231) + + +#if CFG_SUPPORT_BKREG +#define BKCMD_RXSENS_R 'r' +#define BKCMD_RXSENS_X 'x' +#define BKCMD_RXSENS_s 's' + +#define BKCMD_TXEVM_T 't' +#define BKCMD_TXEVM_X 'x' +#define BKCMD_TXEVM_E 'e' + +void bkreg_cmd_handle_input(char *inbuf, int len) +{ + if(((char)BKREG_MAGIC_WORD0 == inbuf[0]) + && ((char)BKREG_MAGIC_WORD1 == inbuf[1]) + && ((char)BKREG_MAGIC_WORD2 == inbuf[2])) + { + if(cli_getchars(inbuf, len)) + { + bkreg_run_command(inbuf, len); + os_memset(inbuf, 0, len); + } + } + else if((((char)BKCMD_RXSENS_R == inbuf[0]) + && ((char)BKCMD_RXSENS_X == inbuf[1]) + && ((char)BKCMD_RXSENS_s == inbuf[2])) + || (((char)BKCMD_TXEVM_T == inbuf[0]) + && ((char)BKCMD_TXEVM_X == inbuf[1]) + && ((char)BKCMD_TXEVM_E == inbuf[2])) ) + { + if(cli_getchars(inbuf, len)) + { + handle_input(inbuf); + os_memset(inbuf, 0, len); + } + } + +} +#endif + +#include "phy_trident.h" +static void phy_cca_test(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + if(argc != 2) + { + os_printf("cca open\r\n"); + os_printf("cca close\r\n"); + os_printf("cca show\r\n"); + return; + } + + if (os_strncmp(argv[1], "open", 4) == 0) { + phy_open_cca(); + os_printf("cca opened\r\n"); + } else if (os_strncmp(argv[1], "close", 4) == 0) { + phy_close_cca(); + os_printf("cca closed\r\n"); + } else if (os_strncmp(argv[1], "show", 4) == 0) { + phy_show_cca(); + } else { + os_printf("cca open\r\n"); + os_printf("cca close\r\n"); + os_printf("cca show\r\n"); + } +} + +#if CFG_SUPPORT_OTA_TFTP +extern void tftp_start(void); +extern void string_to_ip(char *s); +static void tftp_ota_get_Command(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + short len = 0,i; + extern char BootFile[] ; + + if(argc > 3 ) + { + os_printf("ota server_ip ota_file\r\n"); + return; + } + + os_printf("%s\r\n",argv[1]); + + os_strcpy(BootFile,argv[2]); + os_printf("%s\r\n",BootFile); + string_to_ip (argv[1]); + + + tftp_start(); + + return; + +} +#endif + +#define HTTP_RESP_CONTENT_LEN (256) +/* +*when HTTP_WR_TO_FLASH = 1 & CFG_SUPPORT_OTA_HTTP = 0 http data will write to flash ,addr #define HTTP_FLASH_ADDR 0xff000 +*when HTTP_WR_TO_FLASH = 1 & CFG_SUPPORT_OTA_HTTP = 1 http data will write to flash ,with bk ota fromat +*when HTTP_WR_TO_FLASH = 0 can get http data at http_data_process() +*/ +#if CFG_SUPPORT_OTA_HTTP +void http_client_Command(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + int ret; + httpclient_t httpclient; + httpclient_data_t httpclient_data; + char http_content[HTTP_RESP_CONTENT_LEN]; + + if ( argc != 2 ) + { + goto HTTP_CMD_ERR; + } + os_memset(&httpclient, 0, sizeof(httpclient_t)); + os_memset(&httpclient_data, 0, sizeof(httpclient_data)); + os_memset(&http_content, 0, sizeof(HTTP_RESP_CONTENT_LEN)); + httpclient.header = "Accept: text/xml,text/html,\r\n"; + httpclient_data.response_buf = http_content; + httpclient_data.response_content_len = HTTP_RESP_CONTENT_LEN; + ret = httpclient_common(&httpclient, + argv[1], + 80, + NULL, + HTTPCLIENT_GET, + 5000, + &httpclient_data); + if (0 != ret) { + os_printf("request epoch time from remote server failed."); + } else { + os_printf("sucess.\r\n"); + } + + return; +HTTP_CMD_ERR: + os_printf("Usage:httpc [url:]\r\n"); + +} +#endif +#if CFG_USE_TUYA_CCA_TEST +void udp_server_test(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + extern int demo_start_upd( void ); + demo_start_upd(); +} +#endif + +static const struct cli_command built_ins[] = +{ + {"help", NULL, help_command}, +#if !CFG_LESS_CODE_SIZE + {"version", NULL, get_version}, + {"echo", NULL, echo_cmd_handler}, + {"exit", "CLI exit", cli_exit_handler}, +#endif + /// WIFI + {"scan", "scan ap", wifiscan_Command}, + {"advscan", "scan ap", wifiadvscan_Command}, + {"softap", "softap ssid key", softap_Command}, + {"stopintf", "stopintf intfacename", stop_wlan_intface_Command}, + {"sta", "sta ap_ssid key", sta_Command}, +#if !CFG_LESS_CODE_SIZE + #if (CFG_SOC_NAME == SOC_BK7231U) || (CFG_SOC_NAME == SOC_BK7231N) + {"ble", "ble help/active/dut", ble_entry_Command}, + #endif + {"adv", "adv", sta_adv_Command}, + {"mtr", "mtr channel", mtr_Command}, + {"addif", "addif param", add_virtual_intface}, + {"delif", "delif role", del_virtual_intface}, + {"showif", "show", show_virtual_intface}, + {"psk", "show psk", show_sta_psk}, +#endif + + {"wifistate", "Show wifi state", wifistate_Command}, + + // network + {"ifconfig", "Show IP address", ifconfig_Command}, +#if !CFG_LESS_CODE_SIZE + {"ping", "ping ", ping_Command}, + {"dns", "show/clean/", dns_Command}, + {"sockshow", "Show all sockets", socket_show_Command}, + // os + {"tasklist", "list all thread name status", task_Command}, + + // others + {"memshow", "print memory information", memory_show_Command}, + {"memdump", " ", memory_dump_Command}, + {"os_memset", " [ ... ]", memory_set_Command}, + //{"memp", "print memp list", memp_dump_Command}, +#endif + {"reboot", "reboot system", reboot}, + +#if !CFG_LESS_CODE_SIZE + {"time", "system time", uptime_Command}, + {"flash", "Flash memory map", partShow_Command}, + + {"GPIO", "GPIO ", Gpio_op_Command}, + {"GPIO_INT", "GPIO_INT ", Gpio_int_Command}, + {"FLASH", "FLASH ", flash_command_test}, + //{"UART", "UART I ", Uart_command_test}, +#endif + + {"txevm", "txevm [-m] [-c] [-l] [-r] [-w]", tx_evm_cmd_test}, + {"rxsens", "rxsens [-m] [-d] [-c] [-l]", rx_sens_cmd_test}, + #if (CFG_SOC_NAME != SOC_BK7231) + {"efuse", "efuse [-r addr] [-w addr data]", efuse_cmd_test}, + {"efusemac", "efusemac [-r] [-w] [mac]", efuse_mac_cmd_test}, + #endif // (CFG_SOC_NAME != SOC_BK7231) + +#if CFG_SARADC_CALIBRATE + {"adc", "adc [func] [param]", adc_command}, +#endif + + //{"easylink", "start easylink", easylink_Command}, + //{"airkiss", "start airkiss", airkiss_Command}, +#if CFG_SUPPORT_OTA_TFTP + {"tftpota", "tftpota [ip] [file]", tftp_ota_get_Command}, +#endif + +#if CFG_USE_SDCARD_HOST + {"sdtest", "sdtest ", sd_operate}, +#endif + +#if CFG_USE_TEMPERATURE_DETECT && !CFG_LESS_CODE_SIZE + {"tmpdetect", "tmpdetect ", temp_detect_Command}, +#endif +#if CFG_SUPPORT_OTA_HTTP + {"httpc", "http client", http_client_Command}, +#endif +#if CFG_USE_TUYA_CCA_TEST + {"udpserver", "udpserver<>", udp_server_test}, +#endif + +#if !CFG_LESS_CODE_SIZE + {"cca", "cca open\\close\\show", phy_cca_test}, + + {"pwm_test", "pwm_test<>", pwm_command}, +#endif +}; + +/* Built-in "help" command: prints all registered commands and their help +* text string, if any. */ +void help_command(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + int i, n; + uint32_t build_in_count = sizeof(built_ins) / sizeof(struct cli_command); + +#if (DEBUG) + build_in_count++; //For command: micodebug +#endif + + os_printf( "====Build-in Commands====\r\n" ); + for (i = 0, n = 0; i < MAX_COMMANDS && n < pCli->num_commands; i++) + { + if (pCli->commands[i]->name) + { + os_printf("%s: %s\r\n", pCli->commands[i]->name, + pCli->commands[i]->help ? + pCli->commands[i]->help : ""); + n++; + if( n == build_in_count ) + { + os_printf("\r\n====User Commands====\r\n"); + } + } + } +} + + +int cli_register_command(const struct cli_command *command) +{ + int i; + if (!command->name || !command->function) + return 1; + + if (pCli->num_commands < MAX_COMMANDS) + { + /* Check if the command has already been registered. + * Return 0, if it has been registered. + */ + for (i = 0; i < pCli->num_commands; i++) + { + if (pCli->commands[i] == command) + return 0; + } + pCli->commands[pCli->num_commands++] = command; + return 0; + } + + return 1; +} + +int cli_unregister_command(const struct cli_command *command) +{ + int i; + if (!command->name || !command->function) + return 1; + + for (i = 0; i < pCli->num_commands; i++) + { + if (pCli->commands[i] == command) + { + pCli->num_commands--; + int remaining_cmds = pCli->num_commands - i; + if (remaining_cmds > 0) + { + os_memmove(&pCli->commands[i], &pCli->commands[i + 1], + (remaining_cmds * + sizeof(struct cli_command *))); + } + pCli->commands[pCli->num_commands] = NULL; + return 0; + } + } + + return 1; +} + + +int cli_register_commands(const struct cli_command *commands, int num_commands) +{ + int i; + for (i = 0; i < num_commands; i++) + if (cli_register_command(commands++)) + return 1; + return 0; +} + +int cli_unregister_commands(const struct cli_command *commands, + int num_commands) +{ + int i; + for (i = 0; i < num_commands; i++) + if (cli_unregister_command(commands++)) + return 1; + + return 0; +} + +static void micodebug_Command(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + if (argc == 1) + { + os_printf("Usage: micodebug on/off. _BK_ debug is currently %s\r\n", + mico_debug_enabled ? "Enabled" : "Disabled"); + return; + } + + if (!os_strcasecmp(argv[1], "on")) + { + os_printf("Enable _BK_ debug\r\n"); + mico_debug_enabled = 1; + } + else if (!os_strcasecmp(argv[1], "off")) + { + os_printf("Disable _BK_ debug\r\n"); + mico_debug_enabled = 0; + } +} + +void monitor(uint8_t *data, int len, hal_wifi_link_info_t *info) +{ + int i; + + os_printf("[%d]: ", len); + for(i = 0; i < len; i++) + { + os_printf("%02x ", data[i]); + } + os_printf("\r\n"); +} + +static void monitor_Command(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + if (argc == 1) + { + os_printf("Usage: monitor on/off."); + return; + } + + if (!os_strcasecmp(argv[1], "on")) + { + cmd_printf("start monitor\r\n"); + // start monitor, need set callback + bk_wlan_register_monitor_cb(monitor); + // then start hal mac + bk_wlan_start_monitor(); + } + else if (!os_strcasecmp(argv[1], "off")) + { + cmd_printf("stop monitor\r\n"); + mico_debug_enabled = 0; + + // stop monitor mode, need stop hal mac first + bk_wlan_stop_monitor(); + // then set monitor callback + bk_wlan_register_monitor_cb(NULL); + } +} + +static void channel_Command(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + int channel, i = 0; + + if (argc == 1) + { + os_printf("Usage: channel [1~13]."); + return; + } + + while(argv[1][i]) + { + if((argv[1][i] < '0') || (argv[1][i] > '9')) + { + os_printf("parameter should be a number\r\n"); + return ; + } + i++; + } + + channel = atoi(argv[1]); + + if((channel < 1) || (channel > 13)) + { + os_printf("Invalid channel number \r\n"); + return ; + } + cmd_printf("set to channel %d\r\n", channel); + bk_wlan_set_channel_sync(channel); +} + +void pwr_Command(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + int pwr = 0; + + if(argc != 2) + { + os_printf("Usage: pwr [hex:5~15]."); + return; + } + + pwr = os_strtoul(argv[1], NULL, 16); + + rw_msg_set_power(0,pwr); +} + +static void Deep_Sleep_Command(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + PS_DEEP_CTRL_PARAM deep_sleep_param; + + deep_sleep_param.wake_up_way = 0; + + deep_sleep_param.gpio_index_map = os_strtoul(argv[1], NULL, 16); + deep_sleep_param.gpio_edge_map = os_strtoul(argv[2], NULL, 16); + deep_sleep_param.gpio_last_index_map = os_strtoul(argv[3], NULL, 16); + deep_sleep_param.gpio_last_edge_map = os_strtoul(argv[4], NULL, 16); + deep_sleep_param.sleep_time = os_strtoul(argv[5], NULL, 16); + deep_sleep_param.wake_up_way = os_strtoul(argv[6], NULL, 16); + deep_sleep_param.gpio_stay_lo_map = os_strtoul(argv[7], NULL, 16); + deep_sleep_param.gpio_stay_hi_map = os_strtoul(argv[8], NULL, 16); + + if(argc == 9) + { + os_printf("---deep sleep test param : 0x%0X 0x%0X 0x%0X 0x%0X %d %d\r\n", + deep_sleep_param.gpio_index_map, + deep_sleep_param.gpio_edge_map, + deep_sleep_param.gpio_last_index_map, + deep_sleep_param.gpio_last_edge_map, + deep_sleep_param.sleep_time, + deep_sleep_param.wake_up_way); + + bk_enter_deep_sleep_mode(&deep_sleep_param); + } + else + { + os_printf("---argc error!!! \r\n"); + } +} + +static void Ps_Command(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + UINT32 gpio_index = 0; + + #if PS_SUPPORT_MANUAL_SLEEP + UINT32 standby_time = 0; + #endif + + UINT32 dtim = 0; + + if(argc < 3) + { + goto IDLE_CMD_ERR; + } +#if CFG_USE_MCU_PS + else if(0 == os_strcmp(argv[1], "mcudtim")) + { + if(argc != 3) + { + goto IDLE_CMD_ERR; + } + + dtim = os_strtoul(argv[2], NULL, 10); + if(dtim == 1) + { + bk_wlan_mcu_ps_mode_enable(); + } + else if(dtim == 0) + { + bk_wlan_mcu_ps_mode_disable(); + } + else + { + goto IDLE_CMD_ERR; + } + } +#endif +#if CFG_USE_STA_PS + else if(0 == os_strcmp(argv[1], "rfwkup")) + { + if(argc != 3) + { + goto IDLE_CMD_ERR; + } + + bk_wlan_dtim_rf_ps_mode_do_wakeup(); + } + else if(0 == os_strcmp(argv[1], "rfdtim")) + { + if(argc != 3) + { + goto IDLE_CMD_ERR; + } + + dtim = os_strtoul(argv[2], NULL, 10); + if(dtim == 1) + { + bk_wlan_dtim_rf_ps_mode_enable(); + } + else if(dtim == 0) + { + bk_wlan_dtim_rf_ps_disable_send_msg(); + } + else + { + goto IDLE_CMD_ERR; + } + } + else if(0 == os_strcmp(argv[1], "setwktm")) + { + if(argc != 3) + { + os_printf("beacon len:%d\r\n", power_save_beacon_len_get()); + os_printf("wktm:%d\r\n", power_save_radio_wkup_get()); + goto IDLE_CMD_ERR; + } + + dtim = os_strtoul(argv[2], NULL, 10); + + if(dtim) + { + power_save_radio_wkup_set(dtim); + os_printf("set ridio wkup:%d\r\n", dtim); + } + else + { + goto IDLE_CMD_ERR; + } + } + else if(0 == os_strcmp(argv[1], "bcmc")) + { + if(argc != 3) + { + goto IDLE_CMD_ERR; + } + + dtim = os_strtoul(argv[2], NULL, 10); + + if(dtim == 0 || dtim == 1) + { + power_save_sm_set_all_bcmc(dtim); + } + else + { + goto IDLE_CMD_ERR; + } + } + else if(0 == os_strcmp(argv[1], "rf_timer")) + { + if(argc != 3) + { + goto IDLE_CMD_ERR; + } + + dtim = os_strtoul(argv[2], NULL, 10); + + if(dtim == 1) + { + extern int bk_wlan_dtim_rf_ps_timer_start(void); + bk_wlan_dtim_rf_ps_timer_start(); + } + else if(dtim == 0) + { + extern int bk_wlan_dtim_rf_ps_timer_pause(void); + bk_wlan_dtim_rf_ps_timer_pause(); + } + else + { + goto IDLE_CMD_ERR; + } + } + else if(0 == os_strcmp(argv[1], "normal")) + { + #if PS_DTIM_WITH_NORMAL + if(argc != 3) + { + goto IDLE_CMD_ERR; + } + dtim = os_strtoul(argv[2], NULL, 10); + if(dtim == 0) + { + bk_wlan_dtim_with_normal_close(); + } + else if(dtim == 1) + { + bk_wlan_dtim_with_normal_open(); + } + else + { + goto IDLE_CMD_ERR; + } + #endif + } + else if(0 == os_strcmp(argv[1], "listen")) + { + if(argc != 4) + { + goto IDLE_CMD_ERR; + } + + if(0 == os_strcmp(argv[2], "dtim")) + { + dtim = os_strtoul(argv[3], NULL, 10); + power_save_set_dtim_multi(dtim); + + } + else + { + goto IDLE_CMD_ERR; + } + + } + else if(0 == os_strcmp(argv[1], "dump")) + { + mcu_ps_dump(); + power_save_dump(); + } +#endif + #if PS_SUPPORT_MANUAL_SLEEP + else if(0 == os_strcmp(argv[1], "pwm")) + { + if(argc != 3) + { + goto IDLE_CMD_ERR; + } + + standby_time = os_strtoul(argv[2], NULL, 10); + bk_wlan_ps_wakeup_with_timer(standby_time); + } + else if(0 == os_strcmp(argv[1], "peri")) + { + if(argc != 4) + { + goto IDLE_CMD_ERR; + } + dtim = os_strtoul(argv[2], NULL, 10); + gpio_index = os_strtoul(argv[3], NULL, 16); + + if(dtim != 1 && dtim != 0) + { + goto IDLE_CMD_ERR; + } + os_printf("peri %d %x\r\n", dtim, gpio_index); + bk_wlan_ps_wakeup_with_peri(dtim, gpio_index); + + } + #endif + else + { + goto IDLE_CMD_ERR; + } + + + return; +IDLE_CMD_ERR: + os_printf("Usage:ps [func] [param] []\r\n"); + os_printf("standby:ps deepps [gpio_map] "); + os_printf("gpio_map is hex and every bits is map to gpio0-gpio31\r\n"); + os_printf("ieee:ps rfdtim [],[1/0] is open or close \r\n\r\n"); + os_printf("ieee:ps mcudtim [] ,[1/0] is open or close \r\n\r\n"); + (void)gpio_index; +} + +static void mac_command(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + uint8_t mac[6]; + + if (argc == 1) + { + wifi_get_mac_address((char *)mac, CONFIG_ROLE_STA); + os_printf("MAC address: %02x-%02x-%02x-%02x-%02x-%02x\r\n", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + } + else if(argc == 2) + { + hexstr2bin(argv[1], mac, 6); + wifi_set_mac_address((char *)mac); + os_printf("Set MAC address: %02x-%02x-%02x-%02x-%02x-%02x\r\n", + mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); + } + else + { + os_printf("invalid cmd\r\n"); + } + +} + +#if CFG_SARADC_CALIBRATE +static void adc_command(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + UINT32 status; + DD_HANDLE flash_handle; + DD_HANDLE saradc_handle; + saradc_cal_val_t p_ADC_cal; + float voltage = 0.0; + saradc_desc_t *p_ADC_drv_desc = NULL; + + if(argc < 2) + goto IDLE_CMD_ERR; + + if(0 == os_strcmp(argv[1], "read")) + { + status = manual_cal_load_adc_cali_flash(); + if(status != 0) + { + os_printf("Can't read cali value, use default!\r\n"); + os_printf("calibrate low value:[%x]\r\n", saradc_val.low); + os_printf("calibrate high value:[%x]\r\n", saradc_val.high); + } + } + else if(0 == os_strcmp(argv[1], "set")) + { + p_ADC_drv_desc = (saradc_desc_t *)os_malloc(sizeof(saradc_desc_t)); + if (p_ADC_drv_desc == NULL) + { + os_printf("malloc1 failed!\r\n"); + return; + } + + saradc_config_param_init(p_ADC_drv_desc); + + p_ADC_drv_desc->data_buff_size = ADC_TEMP_BUFFER_SIZE; + p_ADC_drv_desc->pData = (UINT16 *)os_malloc(p_ADC_drv_desc->data_buff_size * sizeof(UINT16)); + os_memset(p_ADC_drv_desc->pData, 0x00, p_ADC_drv_desc->data_buff_size * sizeof(UINT16)); + + if(p_ADC_drv_desc->pData == NULL) + { + os_printf("malloc1 failed!\r\n"); + os_free(p_ADC_drv_desc); + return; + } + + saradc_handle = ddev_open(SARADC_DEV_NAME, &status, (UINT32)p_ADC_drv_desc); + + while (1) + { + if (p_ADC_drv_desc->current_sample_data_cnt == p_ADC_drv_desc->data_buff_size) + { + ddev_close(saradc_handle); + break; + } + } + + if(0 == os_strcmp(argv[2], "low")) + { + p_ADC_cal.mode = SARADC_CALIBRATE_LOW; + } + else if(0 == os_strcmp(argv[2], "high")) + { + p_ADC_cal.mode = SARADC_CALIBRATE_HIGH; + } + else + { + os_printf("invalid parameter\r\n"); + return; + } + p_ADC_cal.val = p_ADC_drv_desc->pData[4]; + if(SARADC_FAILURE == ddev_control(saradc_handle, SARADC_CMD_SET_CAL_VAL, (VOID *)&p_ADC_cal)) + { + os_printf("set calibrate value failture\r\n"); + os_free(p_ADC_drv_desc->pData); + os_free(p_ADC_drv_desc); + return; + } + os_printf("set calibrate success\r\n"); + os_printf("type:[%s] value:[0x%x]\r\n", (p_ADC_cal.mode ? "high":"low"), p_ADC_cal.val); + os_free(p_ADC_drv_desc->pData); + os_free(p_ADC_drv_desc); + } + else if(0 == os_strcmp(argv[1], "write")) + { + manual_cal_save_chipinfo_tab_to_flash(); + os_printf("calibrate low value:[%x]\r\n", saradc_val.low); + os_printf("calibrate high value:[%x]\r\n", saradc_val.high); + } + /* for test + else if(0 == os_strcmp(argv[1], "get")) + { + p_ADC_drv_desc = (saradc_desc_t *)os_malloc(sizeof(saradc_desc_t)); + if (p_ADC_drv_desc == NULL) + { + os_printf("malloc1 failed!\r\n"); + return; + } + + os_memset(p_ADC_drv_desc, 0x00, sizeof(saradc_desc_t)); + p_ADC_drv_desc->channel = 1; + p_ADC_drv_desc->data_buff_size = ADC_TEMP_BUFFER_SIZE; + p_ADC_drv_desc->mode = (ADC_CONFIG_MODE_CONTINUE << 0) + | (ADC_CONFIG_MODE_36DIV << 2); + + p_ADC_drv_desc->has_data = 0; + p_ADC_drv_desc->current_read_data_cnt = 0; + p_ADC_drv_desc->current_sample_data_cnt = 0; + p_ADC_drv_desc->pre_div = 0x10; + p_ADC_drv_desc->samp_rate = 0x20; + p_ADC_drv_desc->pData = (UINT16 *)os_malloc(p_ADC_drv_desc->data_buff_size * sizeof(UINT16)); + os_memset(p_ADC_drv_desc->pData, 0x00, p_ADC_drv_desc->data_buff_size * sizeof(UINT16)); + + if(p_ADC_drv_desc->pData == NULL) + { + os_printf("malloc1 failed!\r\n"); + os_free(p_ADC_drv_desc); + return; + } + + saradc_handle = ddev_open(SARADC_DEV_NAME, &status, (UINT32)p_ADC_drv_desc); + + while (1) + { + if (p_ADC_drv_desc->current_sample_data_cnt == p_ADC_drv_desc->data_buff_size) + { + ddev_close(saradc_handle); + break; + } + } + voltage = saradc_calculate(p_ADC_drv_desc->pData[4]); + + os_printf("voltage is [%f]\r\n", voltage); + os_free(p_ADC_drv_desc->pData); + os_free(p_ADC_drv_desc); + return; + + }*/ + else + { + goto IDLE_CMD_ERR; + } + + return; +IDLE_CMD_ERR: + os_printf("Usage:ps [func] [param]\r\n"); +} +#endif + +void pwm_isr_cb_ch0(uint8_t param) +{ + os_printf("pwm0\r\n"); +} + +void pwm_isr_cb_ch1(uint8_t param) +{ + os_printf("pwm1\r\n"); +} + +void pwm_isr_cb_ch2(uint8_t param) +{ + os_printf("pwm2\r\n"); +} + +void pwm_isr_cb_ch3(uint8_t param) +{ + os_printf("pwm3\r\n"); +} + +void pwm_isr_cb_ch4(uint8_t param) +{ + os_printf("pwm4\r\n"); +} + +void pwm_isr_cb_ch5(uint8_t param) +{ + os_printf("pwm5\r\n"); +} + +UINT32 fn_tab[] = { + (UINT32)pwm_isr_cb_ch0, + (UINT32)pwm_isr_cb_ch1, + (UINT32)pwm_isr_cb_ch2, + (UINT32)pwm_isr_cb_ch3, + (UINT32)pwm_isr_cb_ch4, + (UINT32)pwm_isr_cb_ch5, +}; + +static void pwm_command(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv) +{ + UINT8 channel1; + UINT32 duty_cycle1, cycle, cap_value; +#if (CFG_SOC_NAME == SOC_BK7231N) || (CFG_SOC_NAME == SOC_BK7236) + UINT8 channel2; + UINT32 duty_cycle2; + UINT32 dead_band; +#endif + + /*get the parameters from command line*/ + channel1 = atoi(argv[2]); + duty_cycle1 = atoi(argv[3]); + cycle = atoi(argv[4]); +#if (CFG_SOC_NAME == SOC_BK7231N) || (CFG_SOC_NAME == SOC_BK7236) + channel2 = atoi(argv[5]); + duty_cycle2 = atoi(argv[6]); + dead_band = atoi(argv[7]); +#endif + + if (os_strcmp(argv[1], "single") == 0) + { + if (cycle < duty_cycle1) + { + bk_printf("pwm param error: end < duty\r\n"); + return; + } + + if (5 != argc) { + bk_printf( "pwm single test usage: pwm [single][channel][duty_cycle][freq]\r\n"); + return; + } + bk_printf( "pwm channel %d: duty_cycle: %d freq:%d \r\n", channel1, duty_cycle1, cycle); + +#if (CFG_SOC_NAME != SOC_BK7231N) + bk_pwm_initialize(channel1, cycle, duty_cycle1); + bk_pwm_start(channel1); /*start single pwm channel once */ +#else + bk_pwm_initialize(channel1, cycle, duty_cycle1, 0, 0); + bk_pwm_set_isr_callback(channel1, (pwm_isr_cb)(fn_tab[channel1])); + bk_pwm_en_isr_callback(channel1); + bk_pwm_start(channel1); +#endif + } else if (os_strcmp(argv[1], "stop") == 0) + bk_pwm_stop(channel1); +#if (CFG_SOC_NAME == SOC_BK7231N) + else if (os_strcmp(argv[1], "int") == 0) + { + UINT32 en = atoi(argv[3]); + if(en) + bk_pwm_en_isr_callback(channel1); + else + bk_pwm_dis_isr_callback(channel1); + } +#endif +#if ((CFG_SOC_NAME == SOC_BK7231N) || (CFG_SOC_NAME == SOC_BK7236) ||(CFG_SOC_NAME == SOC_BK7271)) + else if (os_strcmp(argv[1], "update") == 0) + { + if (5 != argc) { + bk_printf("pwm update usage: pwm [update][channel1][duty_cycle][freq]\r\n"); + return; + } + + bk_printf("pwm api TODO\r\n"); + } + else if (os_strcmp(argv[1], "cap") == 0) + { + if (cycle < duty_cycle1) + { + bk_printf("pwm param error: end < duty\r\n"); + return; + } + + uint8_t cap_mode = duty_cycle1; + + if (5 != argc) { + bk_printf("pwm cap usage: pwm [cap][channel1][mode][freq]\r\n"); + return; + } + + bk_pwm_capture_initialize(channel1, cap_mode); /*capture pwm value */ + bk_pwm_start(channel1); + } else if (os_strcmp(argv[1], "capvalue") == 0) + { + cap_value = bk_pwm_get_capvalue(channel1); + bk_printf("pwm : %d cap_value=%x \r\n", channel1, cap_value); + } + #if ((CFG_SOC_NAME == SOC_BK7231N) || (CFG_SOC_NAME == SOC_BK7236)) + else if (os_strcmp(argv[1], "cw") == 0) + { + if (cycle < duty_cycle1) + { + bk_printf("pwm param error: end < duty\r\n"); + return; + } + + if (8 != argc) { + bk_printf( "pwm cw test usage: pwm [cw][channel1][duty_cycle1][freq][channel2][duty_cycle2][dead_band]\r\n"); + return; + } + + bk_printf("pwm : %d / %d cw pwm test \r\n", channel1, channel2); + + bk_pwm_cw_initialize(channel1, channel2, cycle, duty_cycle1, duty_cycle2, dead_band); + bk_pwm_cw_start(channel1, channel2); + } else if (os_strcmp(argv[1], "updatecw") == 0) + { + if (cycle < duty_cycle1) + { + bk_printf("pwm param error: end < duty\r\n"); + return; + } + + if (8 != argc) { + bk_printf( "pwm cw test usage: pwm [cw][channel1][duty_cycle1][freq][channel2][duty_cycle2][dead_band]\r\n"); + return; + } + + bk_printf( "pwm : %d / %d cw updatw pwm test \r\n", channel1, channel2); + + bk_pwm_cw_update_param(channel1, channel2, cycle, duty_cycle1, duty_cycle2, dead_band); + } else if (os_strcmp(argv[1], "loop") == 0) + { + UINT16 cnt = 1000; + if (cycle < duty_cycle1) + { + bk_printf("pwm param error: end < duty\r\n"); + return; + } + + bk_printf("pwm : %d / %d pwm update loop test \r\n", channel1, channel2); + + while (cnt--) { + duty_cycle1 = duty_cycle1 - 100; + + bk_pwm_cw_update_param(channel1, channel2, cycle, duty_cycle1, duty_cycle2, dead_band); + rtos_delay_milliseconds(10); + + if (duty_cycle1 == 0) + duty_cycle1 = cycle; + } + }else if (os_strcmp(argv[1], "cwstop") == 0) + { + + bk_printf( "pwm : %d / %d cw updatw pwm stop \r\n", channel1, channel2); + + bk_pwm_cw_stop(channel1, channel2); + } + #endif + #endif +} + +void cli_rx_callback(int uport, void *param) +{ + if(log_rx_interrupt_sema) + rtos_set_semaphore(&log_rx_interrupt_sema); +} + +/* ========= CLI input&output APIs ============ */ +int cli_printf(const char *msg, ...) +{ + va_list ap; + char *pos, message[256]; + int sz; + int nMessageLen = 0; + + os_memset(message, 0, 256); + pos = message; + + sz = 0; + va_start(ap, msg); + nMessageLen = vsnprintf(pos, 256 - sz, msg, ap); + va_end(ap); + + if( nMessageLen <= 0 ) return 0; + + cli_putstr((const char *)message); + return 0; +} + + +int cli_putstr(const char *msg) +{ + if (msg[0] != 0) + bk_uart_send( CLI_UART, (const char *)msg, os_strlen(msg) ); + + return 0; +} + +int cli_getchar(char *inbuf) +{ + if (bk_uart_recv(CLI_UART, inbuf, 1, BEKEN_WAIT_FOREVER) == 0) + return 1; + else + return 0; +} + +int cli_getchars(char *inbuf, int len) +{ + if(bk_uart_recv(CLI_UART, inbuf, len, BEKEN_WAIT_FOREVER) == 0) + return 1; + else + return 0; +} + +int cli_getchars_prefetch(char *inbuf, int len) +{ + if(bk_uart_recv_prefetch(CLI_UART, inbuf, len, BEKEN_WAIT_FOREVER) == 0) + return 1; + else + return 0; +} + +int cli_get_all_chars_len(void) +{ + return bk_uart_get_length_in_buffer(CLI_UART); +} + +#if CFG_IPERF_TEST +extern void iperf(char *pcWriteBuffer, int xWriteBufferLen, int argc, char **argv); +#endif // CFG_IPERF_TEST + +static const struct cli_command user_clis[] = +{ +#if !CFG_LESS_CODE_SIZE + {"micodebug", "micodebug on/off", micodebug_Command}, + {"monitor", "monitor on/off", monitor_Command}, + {"channel", "channel []", channel_Command}, +#endif + {"mac", "mac , Get mac/Set mac. : c89346000001", mac_command}, +#if !CFG_LESS_CODE_SIZE + {"ps", "ps [func] [param]", Ps_Command}, + {"deep_sleep", "deep_sleep [param]", Deep_Sleep_Command}, +#endif +#ifdef TCP_CLIENT_DEMO + {"tcp_cont", "tcp_cont [ip] [port]", tcp_make_connect_server_command}, +#endif +// {"tcp_server", "tcp_server [ip] [port]",make_tcp_server_command }, + +#if CFG_IPERF_TEST + {"iperf", "iperf help", iperf }, +#endif // CFG_IPERF_TEST +#if CFG_SUPPORT_TPC_PA_MAP && !CFG_LESS_CODE_SIZE + {"pwr", "pwr help", pwr_Command }, +#endif +}; + +int cli_init(void) +{ + int ret; + + pCli = (struct cli_st *)os_malloc(sizeof(struct cli_st)); + if (pCli == NULL) + return kNoMemoryErr; + + os_memset((void *)pCli, 0, sizeof(struct cli_st)); + rtos_init_semaphore(&log_rx_interrupt_sema, 10); + + if (cli_register_commands(&built_ins[0], + sizeof(built_ins) / sizeof(struct cli_command))) + { + goto init_general_err; + } + + cli_register_commands(user_clis, sizeof(user_clis) / sizeof(struct cli_command)); + + ret = rtos_create_thread(NULL, + BEKEN_DEFAULT_WORKER_PRIORITY, + "cli", + (beken_thread_function_t)cli_main, + 4096, + 0); + if (ret != kNoErr) + { + os_printf("Error: Failed to create cli thread: %d\r\n", + ret); + goto init_general_err; + } + + pCli->initialized = 1; + pCli->echo_disabled = 0; + + return kNoErr; + +init_general_err: + if(pCli) + { + os_free(pCli); + pCli = NULL; + } + + return kGeneralErr; +} +#endif // CFG_ENABLE_ATE_FEATURE + +// eof + diff --git a/beken_os/beken378/func/wlan_ui/wlan_ui.c b/beken_os/beken378/func/wlan_ui/wlan_ui.c new file mode 100755 index 0000000..272c59c --- /dev/null +++ b/beken_os/beken378/func/wlan_ui/wlan_ui.c @@ -0,0 +1,2085 @@ +#include "include.h" +#include "wlan_ui_pub.h" +#include "rw_pub.h" +#include "vif_mgmt.h" +#include "sa_station.h" +#include "param_config.h" +#include "common/ieee802_11_defs.h" +#include "driver_beken.h" +#include "mac_ie.h" +#include "sa_ap.h" +#include "main_none.h" +#include "sm.h" +#include "mac.h" +#include "sm_task.h" +#include "scan_task.h" +#include "hal_machw.h" +#include "rtos_error.h" +#include "lwip_netif_address.h" +#include "lwip/inet.h" +#include +#include "rw_pub.h" +#include "power_save_pub.h" +#include "rwnx.h" +#include "net.h" +#include "mm_bcn.h" +#include "phy_trident.h" +#include "mcu_ps_pub.h" +#include "manual_ps_pub.h" +#include "gpio_pub.h" +#include "wdt_pub.h" +#include "start_type_pub.h" +#include "wpa_psk_cache.h" +#include "sys_ctrl_pub.h" +#include "lwip/net.h" +#include "txu_cntrl.h" +#include "rw_msdu.h" +#if CFG_WPA_CTRL_IFACE +#include "../wpa_supplicant/wlan_defs.h" +#include "wpa_ctrl.h" +#include "flash_pub.h" +#endif +#include "ate_app.h" +#include "bk7011_cal_pub.h" +#include "app.h" +#if CFG_ROLE_LAUNCH +#include "role_launch.h" +#endif +#include "soft_encrypt.h" + +uint8_t ble_switch_mac_sleeped = 0; + +monitor_data_cb_t g_monitor_cb = 0; +static monitor_data_cb_t g_bcn_cb = 0; +#if CFG_AP_MONITOR_COEXIST +static int g_ap_monitor_coexist = 0; +#endif + +int g_set_channel_postpone_num = 0; +#ifdef CONFIG_AOS_MESH +monitor_data_cb_t g_mesh_monitor_cb = 0; +uint8_t g_mesh_bssid[6]; +#endif +FUNC_1PARAM_PTR connection_status_cb = 0; + +extern void mm_hw_ap_disable(void); +extern int hostapd_main_exit(void); +extern int supplicant_main_exit(void); +extern void net_wlan_add_netif(void *mac); +extern void wpa_hostapd_release_scan_rst(void); +extern int mm_bcn_get_tx_cfm(void); +extern void wlan_ui_bcn_callback(uint8_t *data, int len, hal_wifi_link_info_t *info); +extern void power_save_bcn_callback(uint8_t *data, int len, hal_wifi_link_info_t *info); +extern void bk_wlan_register_bcn_cb(monitor_data_cb_t fn); +extern void mcu_ps_bcn_callback(uint8_t *data, int len, hal_wifi_link_info_t *info); +extern uint32_t get_ate_mode_state(void); + +static void rwnx_remove_added_interface(void) +{ + int ret; + u8 test_mac[6]; + struct mm_add_if_cfm *cfm; + struct apm_start_cfm *apm_cfm = 0; + + wifi_get_mac_address((char*)test_mac, CONFIG_ROLE_STA); + cfm = (struct mm_add_if_cfm *)os_malloc(sizeof(struct mm_add_if_cfm)); + ret = rw_msg_send_add_if((const unsigned char *)&test_mac, 3, 0, cfm); + + if(ret || (cfm->status != CO_OK)) + { + os_printf("[saap]MM_ADD_IF_REQ failed!\r\n"); + goto ERR_RETURN; + } + + apm_cfm = (struct apm_start_cfm *)os_malloc(sizeof(struct apm_start_cfm)); + ret = rw_msg_send_apm_start_req(cfm->inst_nbr, 1, apm_cfm); + + if(ret || (apm_cfm->status != CO_OK)) + { + os_printf("[saap]APM_START_REQ failed!\r\n"); + goto ERR_RETURN; + } + + rw_msg_send_remove_if(cfm->inst_nbr); + +ERR_RETURN: + if(cfm) + { + os_free(cfm); + } + + if(apm_cfm) + { + os_free(apm_cfm); + } +} + +void bk_wlan_connection_loss(void) +{ + struct vif_info_tag *p_vif_entry = vif_mgmt_first_used(); + + while (p_vif_entry != NULL) + { + if(p_vif_entry->type == VIF_STA) + { + os_printf("bk_wlan_connection_loss vif:%d\r\n", p_vif_entry->index); + sta_ip_down(); + rw_msg_send_connection_loss_ind(p_vif_entry->index); + } + p_vif_entry = vif_mgmt_next(p_vif_entry); + } +} + +uint32_t bk_sta_cipher_is_open(void) +{ + ASSERT(g_sta_param_ptr); + return (SECURITY_TYPE_NONE == g_sta_param_ptr->cipher_suite); +} + +uint32_t bk_sta_cipher_is_wep(void) +{ + ASSERT(g_sta_param_ptr); + return (SECURITY_TYPE_WEP == g_sta_param_ptr->cipher_suite); +} + +int bk_sta_cipher_type(void) +{ + if(!sta_ip_is_start()) + { + return -1; + } + + return g_sta_param_ptr->cipher_suite; +} + +OSStatus bk_wlan_set_country(const wifi_country_t *country) +{ + return rw_ieee80211_set_country(country); +} + +OSStatus bk_wlan_get_country(wifi_country_t *country) +{ + return rw_ieee80211_get_country(country); +} + +void bk_wlan_set_max_txpwr(FP32 max_tx_pwr) +{ + void rwnx_cal_set_max_twper(FP32 max_tx_pwr); + rwnx_cal_set_max_twper(max_tx_pwr); +} + +uint32_t bk_wlan_ap_get_frequency(void) +{ + uint8_t channel = bk_wlan_ap_get_channel_config(); + + return rw_ieee80211_get_centre_frequency(channel); +} + +uint8_t bk_wlan_ap_get_channel_config(void) +{ + return g_ap_param_ptr->chann; +} + +void bk_wlan_ap_set_channel_config(uint8_t channel) +{ + g_ap_param_ptr->chann = channel; +} + +uint8_t bk_wlan_has_role(uint8_t role) +{ + VIF_INF_PTR vif_entry; + uint32_t role_count = 0; + + vif_entry = (VIF_INF_PTR)rwm_mgmt_is_vif_first_used(); + while(vif_entry) + { + if(vif_entry->type == role) + { + role_count ++ ; + } + + vif_entry = (VIF_INF_PTR)rwm_mgmt_next(vif_entry); + } + + return role_count; +} + +void bk_wlan_set_coexist_at_init_phase(uint8_t current_role) +{ + uint32_t coexit = 0; + + switch(current_role) + { + case CONFIG_ROLE_AP: + if(bk_wlan_has_role(VIF_STA)) + { + coexit = 1; + } + break; + + case CONFIG_ROLE_STA: + if(bk_wlan_has_role(VIF_AP)) + { + coexit = 1; + } + break; + + case CONFIG_ROLE_NULL: + if(bk_wlan_has_role(VIF_STA) + && bk_wlan_has_role(VIF_AP)) + { + coexit = 1; + } + break; + + case CONFIG_ROLE_COEXIST: + coexit = 1; + ASSERT(CONFIG_ROLE_COEXIST == g_wlan_general_param->role); + break; + + default: + break; + } + + if(coexit) + { + g_wlan_general_param->role = CONFIG_ROLE_COEXIST; + } +} + +uint16_t bk_wlan_sta_get_frequency(void) +{ + uint16_t frequency = 0; + uint32_t sta_flag = 0; + VIF_INF_PTR vif_entry; + + vif_entry = (VIF_INF_PTR)rwm_mgmt_is_vif_first_used(); + while(vif_entry) + { + if(vif_entry->type == VIF_STA) + { + sta_flag = 1; + break; + } + + vif_entry = (VIF_INF_PTR)rwm_mgmt_next(vif_entry); + } + + if(0 == sta_flag) + { + goto get_exit; + } + + frequency = chan_get_vif_frequency(vif_entry); + +get_exit: + return frequency; +} + +uint8_t bk_wlan_sta_get_channel(void) +{ + uint8_t channel = 0; + uint16_t frequency; + + frequency = bk_wlan_sta_get_frequency(); + if(frequency) + { + channel = rw_ieee80211_get_chan_id(frequency); + } + + return channel; +} + +uint8_t sys_channel = DEFAULT_CHANNEL_AP; +uint8_t bk_wlan_ap_get_default_channel(void) +{ + uint8_t channel; + + /* if ap and sta are coexist, ap channel shall match sta channel firstly*/ + channel = bk_wlan_sta_get_channel(); + if(0 == channel) + { + if(sys_channel == DEFAULT_CHANNEL_AP) + channel = DEFAULT_CHANNEL_AP; + else + channel = sys_channel; + } + + return channel; +} + +void bk_wlan_ap_set_default_channel(uint8_t channel) +{ + sys_channel = channel; +} + +void bk_wlan_ap_csa_coexist_mode(void *arg, uint8_t dummy) +{ + int ret = 0; + uint16_t frequency; + + if(0 == bk_wlan_has_role(VIF_AP)) + { + return; + } + + frequency = bk_wlan_sta_get_frequency(); + if(frequency) + { + os_printf("\r\nhostapd_channel_switch\r\n"); +#if CFG_ROLE_LAUNCH + if(!fl_get_pre_sta_cancel_status()) +#endif + { + ret = hostapd_channel_switch(frequency); + } + if(ret) + { + os_printf("csa_failed:%x\r\n", ret); + } + } +} + +void bk_wlan_reg_csa_cb_coexist_mode(void) +{ + /* the callback routine will be invoked at the timepoint of associating at station mode*/ + mhdr_connect_user_cb(bk_wlan_ap_csa_coexist_mode, 0); +} + +#include "phy_trident.h" +void bk_wlan_phy_open_cca(void) +{ + CHECK_OPERATE_RF_REG_IF_IN_SLEEP(); + phy_open_cca(); + CHECK_OPERATE_RF_REG_IF_IN_SLEEP_END(); + os_printf("bk_wlan cca opened\r\n"); +} + +void bk_wlan_phy_close_cca(void) +{ + CHECK_OPERATE_RF_REG_IF_IN_SLEEP(); + phy_close_cca(); + CHECK_OPERATE_RF_REG_IF_IN_SLEEP_END(); + os_printf("bk_wlan cca closed\r\n"); +} + +void bk_wlan_phy_show_cca(void) +{ + phy_show_cca(); +} +extern void delay_ms(UINT32 ms_count); +void bk_reboot(void) +{ + UINT32 wdt_val = 5; + + os_printf("bk_reboot\r\n"); + + bk_misc_update_set_type(RESET_SOURCE_REBOOT); + + GLOBAL_INT_DECLARATION(); + + GLOBAL_INT_DISABLE(); + + sddev_control(WDT_DEV_NAME, WCMD_POWER_DOWN, NULL); + os_null_printf("wdt reboot\r\n"); + delay_ms(100); + sddev_control(WDT_DEV_NAME, WCMD_SET_PERIOD, &wdt_val); + sddev_control(WDT_DEV_NAME, WCMD_POWER_UP, NULL); + while(1); + GLOBAL_INT_RESTORE(); +} +void bk_wlan_ap_init(network_InitTypeDef_st *inNetworkInitPara) +{ + os_printf("Soft_AP_start\r\n"); + + if(!g_ap_param_ptr) + { + g_ap_param_ptr = (ap_param_t *)os_zalloc(sizeof(ap_param_t)); + ASSERT(g_ap_param_ptr); + } + + os_memset(g_ap_param_ptr, 0x00, sizeof(*g_ap_param_ptr)); + + if(MAC_ADDR_NULL((u8 *)&g_ap_param_ptr->bssid)) + { + wifi_get_mac_address((char *)&g_ap_param_ptr->bssid, CONFIG_ROLE_AP); + } + + bk_wlan_ap_set_channel_config(bk_wlan_ap_get_default_channel()); + + if(!g_wlan_general_param) + { + g_wlan_general_param = (general_param_t *)os_zalloc(sizeof(general_param_t)); + ASSERT(g_wlan_general_param); + } + g_wlan_general_param->role = CONFIG_ROLE_AP; + bk_wlan_set_coexist_at_init_phase(CONFIG_ROLE_AP); + + if(inNetworkInitPara) + { + g_ap_param_ptr->ssid.length = MIN(SSID_MAX_LEN, os_strlen(inNetworkInitPara->wifi_ssid)); + os_memcpy(g_ap_param_ptr->ssid.array, inNetworkInitPara->wifi_ssid, g_ap_param_ptr->ssid.length); + g_ap_param_ptr->key_len = os_strlen(inNetworkInitPara->wifi_key); + if(g_ap_param_ptr->key_len < 8) + { + g_ap_param_ptr->cipher_suite = SECURITY_TYPE_NONE; + } + else + { +#if CFG_SOFTAP_WPA3 + g_ap_param_ptr->cipher_suite = SECURITY_TYPE_WPA3_WPA2_MIXED; +#else + g_ap_param_ptr->cipher_suite = SECURITY_TYPE_WPA2_AES; +#endif + os_memcpy(g_ap_param_ptr->key, inNetworkInitPara->wifi_key, g_ap_param_ptr->key_len); + } + + if(inNetworkInitPara->dhcp_mode == DHCP_SERVER) + { + g_wlan_general_param->dhcp_enable = 1; + } + else + { + g_wlan_general_param->dhcp_enable = 0; + } + inet_aton(inNetworkInitPara->local_ip_addr, &(g_wlan_general_param->ip_addr)); + inet_aton(inNetworkInitPara->net_mask, &(g_wlan_general_param->ip_mask)); + inet_aton(inNetworkInitPara->gateway_ip_addr, &(g_wlan_general_param->ip_gw)); + +#if CFG_ROLE_LAUNCH + if(rl_pre_ap_set_status(RL_STATUS_AP_INITING)) + { + return; + } +#endif + } + + sa_ap_init(); +} + +OSStatus bk_wlan_start_ap(network_InitTypeDef_st *inNetworkInitParaAP) +{ +#if !CFG_WPA_CTRL_IFACE + int ret, flag ,empty; + GLOBAL_INT_DECLARATION(); + + while( 1 ) + { + GLOBAL_INT_DISABLE(); + flag = mm_bcn_get_tx_cfm(); + empty = is_apm_bss_config_empty(); + if ( flag == 0 && empty == 1) + { + GLOBAL_INT_RESTORE(); + break; + } + else + { + GLOBAL_INT_RESTORE(); + rtos_delay_milliseconds(100); + } + } + + bk_wlan_stop(SOFT_AP); + + bk_wlan_ap_init(inNetworkInitParaAP); + + ret = hostapd_main_entry(2, 0); + if(ret) + { + os_printf("bk_wlan_start softap failed!!\r\n"); + bk_wlan_stop(SOFT_AP); + return -1; + } + + net_wlan_add_netif(&g_ap_param_ptr->bssid); + + ip_address_set(SOFT_AP, + inNetworkInitParaAP->dhcp_mode, + inNetworkInitParaAP->local_ip_addr, + inNetworkInitParaAP->net_mask, + inNetworkInitParaAP->gateway_ip_addr, + inNetworkInitParaAP->dns_server_ip_addr); + uap_ip_start(); + + sm_build_broadcast_deauthenticate(); +#else /* CFG_WPA_CTRL_IFACE */ + /* stop lwip netif */ + static beken_semaphore_t sema = NULL; + if (!sema) { + OSStatus ret = rtos_init_semaphore_adv(&sema, 1, 1); + if (ret != kNoErr) + return ret; + } + rtos_get_semaphore(&sema, BEKEN_NEVER_TIMEOUT); + uap_ip_down(); + + /* set AP parameter, ssid, akm, etc. */ + bk_wlan_ap_init(inNetworkInitParaAP); + + // enable hostapd + wlan_ap_enable(); + + // reload bss configuration + wlan_ap_reload(); + + /* now ap has started, set ip address to this interface */ + ip_address_set(SOFT_AP, + inNetworkInitParaAP->dhcp_mode, + inNetworkInitParaAP->local_ip_addr, + inNetworkInitParaAP->net_mask, + inNetworkInitParaAP->gateway_ip_addr, + inNetworkInitParaAP->dns_server_ip_addr); + + /* restart lwip network */ + uap_ip_start(); + rtos_set_semaphore(&sema); +#endif + + return kNoErr; +} + +void bk_wlan_terminate_sta_rescan(void) +{ + os_printf("bk_wlan_terminate_sta_rescan\r\n"); + if(g_sta_param_ptr) + { + g_sta_param_ptr->retry_cnt = 0; + } +} + +void bk_wlan_sta_init(network_InitTypeDef_st *inNetworkInitPara) +{ + if(inNetworkInitPara) + { + mhdr_set_station_status(RW_EVT_STA_IDLE); + } + + if(!g_sta_param_ptr) + { + g_sta_param_ptr = (sta_param_t *)os_zalloc(sizeof(sta_param_t)); + ASSERT(g_sta_param_ptr); + } + + g_sta_param_ptr->retry_cnt = MAX_STA_RETRY_COUNT; + wifi_get_mac_address((char*)&g_sta_param_ptr->own_mac, CONFIG_ROLE_STA); + if(!g_wlan_general_param) + { + g_wlan_general_param = (general_param_t *)os_zalloc(sizeof(general_param_t)); + ASSERT(g_wlan_general_param); + } + g_wlan_general_param->role = CONFIG_ROLE_STA; + bk_wlan_set_coexist_at_init_phase(CONFIG_ROLE_STA); + + if(inNetworkInitPara) + { + g_sta_param_ptr->ssid.length = MIN(SSID_MAX_LEN, os_strlen(inNetworkInitPara->wifi_ssid)); + os_memcpy(g_sta_param_ptr->ssid.array, + inNetworkInitPara->wifi_ssid, + g_sta_param_ptr->ssid.length); + + g_sta_param_ptr->key_len = os_strlen(inNetworkInitPara->wifi_key); + os_memcpy(g_sta_param_ptr->key, inNetworkInitPara->wifi_key, g_sta_param_ptr->key_len); + g_sta_param_ptr->key[g_sta_param_ptr->key_len] = 0; /* append \0 */ +#if !RL_SUPPORT_FAST_CONNECT + g_sta_param_ptr->orig_key_len = g_sta_param_ptr->key_len; + os_memcpy(g_sta_param_ptr->orig_key, inNetworkInitPara->wifi_key, g_sta_param_ptr->orig_key_len); + os_null_printf("%s:%d key_len=%d,orig_key_len=%d,%.*s,%.*s\r\n", __FUNCTION__, __LINE__, g_sta_param_ptr->key_len, g_sta_param_ptr->orig_key_len, g_sta_param_ptr->key_len, g_sta_param_ptr->key, g_sta_param_ptr->orig_key_len, g_sta_param_ptr->orig_key); +#endif + +#if CFG_SUPPORT_ALIOS + if(inNetworkInitPara->dhcp_mode == DHCP_CLIENT) +#else + if(inNetworkInitPara->dhcp_mode == DHCP_CLIENT) +#endif + { + g_wlan_general_param->dhcp_enable = 1; + } + else + { + g_wlan_general_param->dhcp_enable = 0; + inet_aton(inNetworkInitPara->local_ip_addr, &(g_wlan_general_param->ip_addr)); + inet_aton(inNetworkInitPara->net_mask, &(g_wlan_general_param->ip_mask)); + inet_aton(inNetworkInitPara->gateway_ip_addr, &(g_wlan_general_param->ip_gw)); + } + +#if CFG_ROLE_LAUNCH + if(rl_pre_sta_set_status(RL_STATUS_STA_INITING)) + { + return; + } +#endif + } + + bk_wlan_reg_csa_cb_coexist_mode(); + sa_station_init(); + + bk_wlan_register_bcn_cb(wlan_ui_bcn_callback); + +} + +#if CFG_WPA_CTRL_IFACE && CFG_WLAN_FAST_CONNECT +char wlan_fast_connect_buffer[sizeof(UINT32) + sizeof(struct wlan_fast_connect_info)] = { 0 }; +void wlan_write_fast_connect_info(struct wlan_fast_connect_info *fci) +{ + UINT32 *length_ptr = (UINT32 *)wlan_fast_connect_buffer; + + *length_ptr = sizeof(struct wlan_fast_connect_info); + + os_memcpy(wlan_fast_connect_buffer + sizeof(UINT32), fci, sizeof(*fci)); + + bk_printf("writed fci to flash ssid=%s\n", fci->ssid); +} + +void wlan_clear_fast_connect_info(void) +{ + os_memset(wlan_fast_connect_buffer, 0x00, sizeof(wlan_fast_connect_buffer)); + os_printf("wlan_clear_fast_connect_info\n"); +} + +void *wlan_get_fast_connect_info(void) +{ + return (void *)wlan_fast_connect_buffer; +} +#endif + + +OSStatus bk_wlan_start_sta_fast(struct wlan_fast_connect_info *fci) +{ + size_t psk_len = 0; + u8 *psk = 0; +#if CFG_WPA_CTRL_IFACE + network_InitTypeDef_st wNetConfig; + network_InitTypeDef_st *inNetworkInitPara; + int chan = 0; + + /* diconnect previous connection if may */ + sta_ip_down(); // XXX: WLAN_DISCONNECT_EVENT may handle this + wlan_sta_disconnect(); +#else /* !CFG_WPA_CTRL_IFACE */ + rwnxl_reset_evt(0); + + bk_wlan_stop(STATION); +#endif + + /* clear it before connect, or init with current fci ? */ + wlan_clear_fast_connect_info(); + os_memset(&wNetConfig, 0x0, sizeof(network_InitTypeDef_st)); + inNetworkInitPara = &wNetConfig; + + os_strcpy((char *)inNetworkInitPara->wifi_ssid, (const char *)fci->ssid); + os_strcpy((char *)inNetworkInitPara->wifi_key, (const char *)fci->pwd); + + inNetworkInitPara->wifi_mode = STATION; + inNetworkInitPara->dhcp_mode = DHCP_CLIENT; + + bk_wlan_sta_init(inNetworkInitPara); + +#if CFG_WPA_CTRL_IFACE + chan = fci->channel; + psk = fci->psk; + psk_len = PMK_LEN * 2; + + bk_printf("fast_connect\n"); + if (os_strlen((char *)psk) == 0) { + // no psk info, calcuate pmk + psk = 0; + psk_len = 0; + } +#endif + + /* + * let wpa_psk_cal thread to caculate psk. + * XXX: If you know psk value, fill last two parameters of `wpa_psk_request()'. + */ + wpa_psk_request(g_sta_param_ptr->ssid.array, g_sta_param_ptr->ssid.length, + (char*)g_sta_param_ptr->key, psk, psk_len); + +#if CFG_WPA_CTRL_IFACE + /* enable wpa_supplicant */ + wlan_sta_enable(); + + /* set network parameters: ssid, passphase */ + wlan_sta_set((uint8_t *)inNetworkInitPara->wifi_ssid, os_strlen(inNetworkInitPara->wifi_ssid), (uint8_t *)inNetworkInitPara->wifi_key); + + /* connect to AP */ + wlan_sta_connect(chan); +#else /* !CFG_WPA_CTRL_IFACE */ + supplicant_main_entry(inNetworkInitPara->wifi_ssid); + net_wlan_add_netif(&g_sta_param_ptr->own_mac); +#endif + + /* set IP mode */ + ip_address_set(inNetworkInitPara->wifi_mode, + inNetworkInitPara->dhcp_mode, + inNetworkInitPara->local_ip_addr, + inNetworkInitPara->net_mask, + inNetworkInitPara->gateway_ip_addr, + inNetworkInitPara->dns_server_ip_addr); + + return kNoErr; +} + +/* only executed once */ +void wlan_send_disconnect_after_reboot(uint16_t freq, uint8_t *bssid, uint8_t *sta, uint16_t reason) +{ + static bool disconnect_sent = false; + uint8_t data[26] = {0}; + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)data; + wlan_sta_send_mlme_t mlme; + + if (disconnect_sent) + return; + disconnect_sent = true; + + hdr->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_DEAUTH); + os_memcpy(hdr->addr1, bssid, ETH_ALEN); + os_memcpy(hdr->addr2, sta, ETH_ALEN); + os_memcpy(hdr->addr3, bssid, ETH_ALEN); + *(uint16_t *)(hdr + 1) = host_to_le16(reason); // reason code + + mlme.data = data; + mlme.data_len = 26; + mlme.freq = freq; + + // print_hex_dump("MLME: ", data, 26); + + wpa_ctrl_request(WPA_CTRL_CMD_STA_SEND_MLME, &mlme); + + // rtos_delay_milliseconds(100); +} + +OSStatus bk_wlan_start_sta(network_InitTypeDef_st *inNetworkInitPara) +{ + size_t psk_len = 0; + u8 *psk = 0; +#if CFG_WPA_CTRL_IFACE + int chan = 0; + + /* diconnect previous connection if may */ + sta_ip_down(); // XXX: WLAN_DISCONNECT_EVENT may handle this + wlan_sta_disconnect(); +#else /* !CFG_WPA_CTRL_IFACE */ + rwnxl_reset_evt(0); + + bk_wlan_stop(STATION); +#endif + +#if (CFG_SOC_NAME == SOC_BK7231N) + if (get_ate_mode_state()) + { + // cunliang20210407 set blk_standby_cfg with blk_txen_cfg like txevm, qunshan confirmed + rwnx_cal_en_extra_txpa(); + } +#endif + bk_wlan_sta_init(inNetworkInitPara); + + /* + * let wpa_psk_cal thread to caculate psk. + * XXX: If you know psk value, fill last two parameters of `wpa_psk_request()'. + */ + wpa_psk_request(g_sta_param_ptr->ssid.array, g_sta_param_ptr->ssid.length, + (char*)g_sta_param_ptr->key, psk, psk_len); + +#if CFG_WPA_CTRL_IFACE + /* enable wpa_supplicant */ + wlan_sta_enable(); + + /* set network parameters: ssid, passphase */ + wlan_sta_set((uint8_t *)inNetworkInitPara->wifi_ssid, os_strlen(inNetworkInitPara->wifi_ssid), (uint8_t *)inNetworkInitPara->wifi_key); + + /* connect to AP */ + wlan_sta_connect(chan); +#else /* !CFG_WPA_CTRL_IFACE */ + supplicant_main_entry(inNetworkInitPara->wifi_ssid); + net_wlan_add_netif(&g_sta_param_ptr->own_mac); +#endif + + /* set IP mode */ + ip_address_set(inNetworkInitPara->wifi_mode, + inNetworkInitPara->dhcp_mode, + inNetworkInitPara->local_ip_addr, + inNetworkInitPara->net_mask, + inNetworkInitPara->gateway_ip_addr, + inNetworkInitPara->dns_server_ip_addr); + + return kNoErr; +} + +OSStatus bk_wlan_start(network_InitTypeDef_st *inNetworkInitPara) +{ + int ret = 0; +#if CFG_ROLE_LAUNCH + LAUNCH_REQ lreq; +#endif + + if(bk_wlan_is_monitor_mode()) + { + os_printf("monitor not finish!\r\n"); + return ret; + } + + if(inNetworkInitPara->wifi_mode == SOFT_AP) + { + #if CFG_ROLE_LAUNCH + lreq.req_type = LAUNCH_REQ_AP; + lreq.descr = *inNetworkInitPara; + + rl_ap_request_enter(&lreq, 0); + #else + bk_wlan_start_ap(inNetworkInitPara); + #endif + } + else if(inNetworkInitPara->wifi_mode == STATION) + { + #if CFG_ROLE_LAUNCH + lreq.req_type = LAUNCH_REQ_STA; + lreq.descr = *inNetworkInitPara; + + rl_sta_request_enter(&lreq, 0); + #else + bk_wlan_start_sta(inNetworkInitPara); + #endif + } + + return 0; +} + +int bk_wlan_start_scan(void) +{ + int ret = 0; + +#if !CFG_WPA_CTRL_IFACE + SCAN_PARAM_T scan_param = {0}; +#endif + +#if CFG_USE_STA_PS + bk_wlan_dtim_rf_ps_disable_send_msg(); +#endif + + if(bk_wlan_is_monitor_mode()) + { + os_printf("monitor not finish!\r\n"); + #if CFG_ROLE_LAUNCH + rl_pre_sta_set_status(RL_STATUS_STA_LAUNCH_FAILED); + #endif + return ret; + } + + bk_wlan_sta_init(0); + +#if CFG_WPA_CTRL_IFACE + wlan_sta_enable(); + ret = wlan_sta_scan_once(); +#else /* !CFG_WPA_CTRL_IFACE */ + os_memset(&scan_param.bssid, 0xff, ETH_ALEN); + scan_param.vif_idx = INVALID_VIF_IDX; + scan_param.num_ssids = 1; + + rw_msg_send_scanu_req(&scan_param); +#endif + + return ret; +} + +void bk_wlan_scan_ap_reg_cb(FUNC_2PARAM_PTR ind_cb) +{ + mhdr_scanu_reg_cb(ind_cb,0); +} + +unsigned char bk_wlan_get_scan_ap_result_numbers(void) +{ + struct scanu_rst_upload *scan_rst; + unsigned char scanu_num = 0; + + scan_rst = sr_get_scan_results(); + if(scan_rst) + { + scanu_num = scan_rst->scanu_num; + } + + return scanu_num; +} + +void bk_wlan_get_scan_ap_result(SCAN_RST_ITEM_PTR scan_rst_table,unsigned char get_scanu_num) +{ + struct scanu_rst_upload *scan_rst; + unsigned char scanu_num = 0,i; + + scan_rst = sr_get_scan_results(); + if(scan_rst) + { + scanu_num = (scan_rst->scanu_num) > get_scanu_num ? (get_scanu_num):(scan_rst->scanu_num); + + for(i = 0;ires[i]); + } + } + + sr_release_scan_results(scan_rst); +} + + +int bk_wlan_start_assign_scan(UINT8 **ssid_ary, UINT8 ssid_num) +{ + int ret = 0; + +#if !CFG_WPA_CTRL_IFACE + SCAN_PARAM_T scan_param = {0}; + + bk_wlan_sta_init(0); + + os_memset(&scan_param.bssid, 0xff, ETH_ALEN); + scan_param.vif_idx = INVALID_VIF_IDX; + scan_param.num_ssids = ssid_num; + for (int i = 0 ; i < ssid_num ; i++ ) + { + scan_param.ssids[i].length = MIN(SSID_MAX_LEN, os_strlen((char*)ssid_ary[i])); + os_memcpy(scan_param.ssids[i].array, ssid_ary[i], scan_param.ssids[i].length); + } + rw_msg_send_scanu_req(&scan_param); +#else + wlan_sta_scan_param_t scan_param = {0}; + + /* init hw */ + bk_wlan_sta_init(0); + + /* enable wpa_supplicant */ + wlan_sta_enable(); + + /* set scan ssid list */ + scan_param.num_ssids = ssid_num; + for (int i = 0 ; i < ssid_num ; i++) { + scan_param.ssids[i].ssid_len = MIN(WLAN_SSID_MAX_LEN, os_strlen((char*)ssid_ary[i])); + os_memcpy(scan_param.ssids[i].ssid, ssid_ary[i], scan_param.ssids[i].ssid_len); + } + + /* start scan */ + ret = wlan_sta_scan(&scan_param); +#endif + + return ret; +} + +void bk_wlan_sta_init_adv(network_InitTypeDef_adv_st *inNetworkInitParaAdv) +{ + if(inNetworkInitParaAdv) + { + mhdr_set_station_status(RW_EVT_STA_IDLE); + } + + if(!g_sta_param_ptr) + { + g_sta_param_ptr = (sta_param_t *)os_zalloc(sizeof(sta_param_t)); + ASSERT(g_sta_param_ptr); + } + + g_sta_param_ptr->retry_cnt = MAX_STA_RETRY_COUNT; + if(MAC_ADDR_NULL((u8 *)&g_sta_param_ptr->own_mac)) + { + wifi_get_mac_address((char *)&g_sta_param_ptr->own_mac, CONFIG_ROLE_STA); + } + + g_sta_param_ptr->ssid.length = MIN(SSID_MAX_LEN, os_strlen(inNetworkInitParaAdv->ap_info.ssid)); + os_memcpy(g_sta_param_ptr->ssid.array, inNetworkInitParaAdv->ap_info.ssid, g_sta_param_ptr->ssid.length); + + g_sta_param_ptr->cipher_suite = inNetworkInitParaAdv->ap_info.security; + g_sta_param_ptr->fast_connect_set = 1; + g_sta_param_ptr->fast_connect.chann = inNetworkInitParaAdv->ap_info.channel; + os_memcpy(g_sta_param_ptr->fast_connect.bssid, inNetworkInitParaAdv->ap_info.bssid, ETH_ALEN); + g_sta_param_ptr->key_len = inNetworkInitParaAdv->key_len; + os_memcpy((uint8_t *)g_sta_param_ptr->key, inNetworkInitParaAdv->key, inNetworkInitParaAdv->key_len); + g_sta_param_ptr->key[inNetworkInitParaAdv->key_len] = 0; /* append \0 */ + os_null_printf("%s:%d key_len=%d,orig_key_len=%d,%.*s,%.*s\r\n", __FUNCTION__, __LINE__, g_sta_param_ptr->key_len, g_sta_param_ptr->orig_key_len, g_sta_param_ptr->key_len, g_sta_param_ptr->key, g_sta_param_ptr->orig_key_len, g_sta_param_ptr->orig_key); + + if(!g_wlan_general_param) + { + g_wlan_general_param = (general_param_t *)os_malloc(sizeof(general_param_t)); + } + g_wlan_general_param->role = CONFIG_ROLE_STA; + bk_wlan_set_coexist_at_init_phase(CONFIG_ROLE_STA); + + if(inNetworkInitParaAdv->dhcp_mode == DHCP_CLIENT) + { + g_wlan_general_param->dhcp_enable = 1; + } + else + { + g_wlan_general_param->dhcp_enable = 0; + inet_aton(inNetworkInitParaAdv->local_ip_addr, &(g_wlan_general_param->ip_addr)); + inet_aton(inNetworkInitParaAdv->net_mask, &(g_wlan_general_param->ip_mask)); + inet_aton(inNetworkInitParaAdv->gateway_ip_addr, &(g_wlan_general_param->ip_gw)); + } + +#if CFG_ROLE_LAUNCH + if(rl_pre_sta_set_status(RL_STATUS_STA_CONNECTING)) + { + return; + } +#endif + + bk_wlan_reg_csa_cb_coexist_mode(); + sa_station_init(); +} + +#if (!CFG_SUPPORT_ALIOS) +void bk_wlan_ap_init_adv(network_InitTypeDef_ap_st *inNetworkInitParaAP) +{ + if(!g_ap_param_ptr) + { + g_ap_param_ptr = (ap_param_t *)os_zalloc(sizeof(ap_param_t)); + ASSERT(g_ap_param_ptr); + } + + if(MAC_ADDR_NULL((u8 *)&g_ap_param_ptr->bssid)) + { + wifi_get_mac_address((char *)&g_ap_param_ptr->bssid, CONFIG_ROLE_AP); + } + + if(!g_wlan_general_param) + { + g_wlan_general_param = (general_param_t *)os_zalloc(sizeof(general_param_t)); + ASSERT(g_wlan_general_param); + } + g_wlan_general_param->role = CONFIG_ROLE_AP; + bk_wlan_set_coexist_at_init_phase(CONFIG_ROLE_AP); + + if(inNetworkInitParaAP) + { + if(0 == inNetworkInitParaAP->channel) + { + g_ap_param_ptr->chann = bk_wlan_ap_get_default_channel(); + } + else + { + g_ap_param_ptr->chann = inNetworkInitParaAP->channel; + } + + g_ap_param_ptr->ssid.length = MIN(SSID_MAX_LEN, os_strlen(inNetworkInitParaAP->wifi_ssid)); + os_memcpy(g_ap_param_ptr->ssid.array, inNetworkInitParaAP->wifi_ssid, g_ap_param_ptr->ssid.length); + g_ap_param_ptr->key_len = os_strlen(inNetworkInitParaAP->wifi_key); + os_memcpy(g_ap_param_ptr->key, inNetworkInitParaAP->wifi_key, g_ap_param_ptr->key_len); + + g_ap_param_ptr->cipher_suite = inNetworkInitParaAP->security; + + if(inNetworkInitParaAP->dhcp_mode == DHCP_SERVER) + { + g_wlan_general_param->dhcp_enable = 1; + } + else + { + g_wlan_general_param->dhcp_enable = 0; + } + inet_aton(inNetworkInitParaAP->local_ip_addr, &(g_wlan_general_param->ip_addr)); + inet_aton(inNetworkInitParaAP->net_mask, &(g_wlan_general_param->ip_mask)); + inet_aton(inNetworkInitParaAP->gateway_ip_addr, &(g_wlan_general_param->ip_gw)); + } + + sa_ap_init(); +} +#endif + +OSStatus bk_wlan_start_sta_adv(network_InitTypeDef_adv_st *inNetworkInitParaAdv) +{ + if(bk_wlan_is_monitor_mode()) + { + os_printf("airkiss not finish!\r\n"); + return 0; + } + +#if !CFG_WPA_CTRL_IFACE + bk_wlan_stop(STATION); + +#if CFG_ROLE_LAUNCH + if(rl_pre_sta_set_status(RL_STATUS_STA_INITING)) + { + return 0; + } +#endif + +#if (CFG_SOC_NAME == SOC_BK7231N) + if (get_ate_mode_state()) + { + // cunliang20210407 set blk_standby_cfg with blk_txen_cfg like txevm, qunshan confirmed + rwnx_cal_en_extra_txpa(); + } +#endif + bk_wlan_sta_init_adv(inNetworkInitParaAdv); + + /* + * let wpa_psk_cal thread to caculate psk. + * XXX: If you know psk value, fill last two parameters of `wpa_psk_request()'. + */ + wpa_psk_request(g_sta_param_ptr->ssid.array, g_sta_param_ptr->ssid.length, + (char*)(g_sta_param_ptr->key), NULL, 0); + + supplicant_main_entry(inNetworkInitParaAdv->ap_info.ssid); + + net_wlan_add_netif(&g_sta_param_ptr->own_mac); + + +#else /* CFG_WPA_CTRL_IFACE */ + wlan_sta_config_t config; + +#if (CFG_SOC_NAME == SOC_BK7231N) + if (get_ate_mode_state()) + { + // cunliang20210407 set blk_standby_cfg with blk_txen_cfg like txevm, qunshan confirmed + rwnx_cal_en_extra_txpa(); + } +#endif + bk_wlan_sta_init_adv(inNetworkInitParaAdv); + + /* + * let wpa_psk_cal thread to caculate psk. + * XXX: If you know psk value, fill last two parameters of `wpa_psk_request()'. + */ + wpa_psk_request(g_sta_param_ptr->ssid.array, g_sta_param_ptr->ssid.length, + (char *)g_sta_param_ptr->key, NULL, 0); + + /* disconnect previous connected network */ + wlan_sta_disconnect(); + + /* start wpa_supplicant */ + wlan_sta_enable(); + + /* set network parameters: ssid, passphase */ + wlan_sta_set((uint8_t *)inNetworkInitParaAdv->ap_info.ssid, os_strlen(inNetworkInitParaAdv->ap_info.ssid), + (uint8_t *)inNetworkInitParaAdv->key); + + /* set fast connect bssid */ + os_memset(&config, 0, sizeof(config)); + os_memcpy(config.u.bssid, inNetworkInitParaAdv->ap_info.bssid, ETH_ALEN); + config.field = WLAN_STA_FIELD_BSSID; + wpa_ctrl_request(WPA_CTRL_CMD_STA_SET, &config); + + /* set fast connect freq */ + os_memset(&config, 0, sizeof(config)); + config.u.channel = inNetworkInitParaAdv->ap_info.channel; + config.field = WLAN_STA_FIELD_FREQ; + wpa_ctrl_request(WPA_CTRL_CMD_STA_SET, &config); + + /* connect to AP */ + wlan_sta_connect(g_sta_param_ptr->fast_connect_set ? g_sta_param_ptr->fast_connect.chann : 0); + +#endif + ip_address_set(STATION, inNetworkInitParaAdv->dhcp_mode, + inNetworkInitParaAdv->local_ip_addr, + inNetworkInitParaAdv->net_mask, + inNetworkInitParaAdv->gateway_ip_addr, + inNetworkInitParaAdv->dns_server_ip_addr); + + return 0; +} + +#if (!CFG_SUPPORT_ALIOS) +OSStatus bk_wlan_start_ap_adv(network_InitTypeDef_ap_st *inNetworkInitParaAP) +{ + int ret = 0; + + if(bk_wlan_is_monitor_mode()) + { + os_printf("monitor not finish!\r\n"); + return ret; + } + +#if !CFG_WPA_CTRL_IFACE + bk_wlan_stop(SOFT_AP); + +#if CFG_ROLE_LAUNCH + if(rl_pre_ap_set_status(RL_STATUS_AP_INITING)) + { + return 0; + } +#endif + + bk_wlan_ap_init_adv(inNetworkInitParaAP); + + ret = hostapd_main_entry(2, 0); + if(ret) + { + os_printf("bk_wlan_start_ap_adv failed!!\r\n"); + bk_wlan_stop(SOFT_AP); + return -1; + } + + net_wlan_add_netif(&g_ap_param_ptr->bssid); + + ip_address_set(SOFT_AP, inNetworkInitParaAP->dhcp_mode, + inNetworkInitParaAP->local_ip_addr, + inNetworkInitParaAP->net_mask, + inNetworkInitParaAP->gateway_ip_addr, + inNetworkInitParaAP->dns_server_ip_addr); + uap_ip_start(); + + sm_build_broadcast_deauthenticate(); +#else /* CFG_WPA_CTRL_IFACE */ + /* stop lwip netif */ + uap_ip_down(); + + /* set AP parameter, ssid, akm, etc. */ + bk_wlan_ap_init_adv(inNetworkInitParaAP); + + // enable hostapd + wlan_ap_enable(); + + // reload bss configuration + wlan_ap_reload(); + + /* now ap has started, set ip address to this interface */ + ip_address_set(SOFT_AP, inNetworkInitParaAP->dhcp_mode, + inNetworkInitParaAP->local_ip_addr, + inNetworkInitParaAP->net_mask, + inNetworkInitParaAP->gateway_ip_addr, + inNetworkInitParaAP->dns_server_ip_addr); + + /* restart lwip network */ + uap_ip_start(); +#endif + + return kNoErr; +} +#endif + +int bk_wlan_stop(char mode) +{ + int ret = kNoErr; + + mhdr_set_station_status(RW_EVT_STA_IDLE); +#if CFG_USE_STA_PS + bk_wlan_dtim_rf_ps_disable_send_msg(); +#endif + + switch(mode) + { + case SOFT_AP: + mm_hw_ap_disable(); + +#if !CFG_WPA_CTRL_IFACE + uap_ip_down(); + bk_printf("%x:%x:%x:%x:%x:%x\r\n", g_ap_param_ptr->bssid.array[0], g_ap_param_ptr->bssid.array[1], g_ap_param_ptr->bssid.array[2], + g_ap_param_ptr->bssid.array[3], g_ap_param_ptr->bssid.array[4], g_ap_param_ptr->bssid.array[5]); + net_wlan_remove_netif(&g_ap_param_ptr->bssid); + hostapd_main_exit(); +#else + wlan_ap_disable(); +#endif + if(bk_wlan_has_role(VIF_STA)) + { + g_wlan_general_param->role = CONFIG_ROLE_STA; + } + +#if CFG_ROLE_LAUNCH + rl_pre_ap_set_status(RL_STATUS_AP_LAUNCHED); +#endif + break; + + case STATION: +#if (CFG_SOC_NAME == SOC_BK7231N) + if (get_ate_mode_state()) + { + // cunliang20210407 recovery blk_standby_cfg like txevm -e 0, qunshan confirmed + rwnx_cal_dis_extra_txpa(); + } +#endif + sta_ip_down(); +#if !CFG_WPA_CTRL_IFACE + net_wlan_remove_netif(&g_sta_param_ptr->own_mac); + supplicant_main_exit(); + wpa_hostapd_release_scan_rst(); +#else + wlan_sta_disable(); /* same but call in wpas task */ +#endif + if(bk_wlan_has_role(VIF_AP)) + { + g_wlan_general_param->role = CONFIG_ROLE_AP; + } + +#if CFG_ROLE_LAUNCH + rl_pre_sta_set_status(RL_STATUS_STA_LAUNCHED); +#endif + break; + + default: + ret = kGeneralErr; + break; + } + + return ret; +} + +OSStatus bk_wlan_set_ip_status(IPStatusTypedef *inNetpara, WiFi_Interface inInterface) +{ + OSStatus ret = kNoErr; + + switch ( inInterface ) + { + case SOFT_AP : + if ( uap_ip_is_start() ) + { + uap_ip_down(); + } + else + { + ret = kGeneralErr; + } + break; + + case STATION : + if ( sta_ip_is_start() ) + { + sta_ip_down(); + } + else + { + ret = kGeneralErr; + } + break; + + default: + ret = kGeneralErr; + break; + } + + if ( ret == kNoErr ) + { + ip_address_set(inInterface, inNetpara->dhcp, inNetpara->ip, + inNetpara->mask, inNetpara->gate, inNetpara->dns); + if ( inInterface == SOFT_AP ) + { + uap_ip_is_start(); + } + else if ( inInterface == STATION ) + { + sta_ip_start(); + } + } + + return ret; +} + +OSStatus bk_wlan_get_ip_status(IPStatusTypedef *outNetpara, WiFi_Interface inInterface) +{ + OSStatus ret = kNoErr; + struct wlan_ip_config addr; + + os_memset(&addr, 0, sizeof(struct wlan_ip_config)); + + switch ( inInterface ) + { + case SOFT_AP : + net_get_if_addr(&addr, net_get_uap_handle()); + net_get_if_macaddr(outNetpara->mac, net_get_uap_handle()); + break; + + case STATION : + net_get_if_addr(&addr, net_get_sta_handle()); + net_get_if_macaddr(outNetpara->mac, net_get_sta_handle()); + break; + + default: + ret = kGeneralErr; + break; + } + + if ( ret == kNoErr ) + { + outNetpara->dhcp = addr.ipv4.addr_type; + os_strcpy(outNetpara->ip, inet_ntoa(addr.ipv4.address)); + os_strcpy(outNetpara->mask, inet_ntoa(addr.ipv4.netmask)); + os_strcpy(outNetpara->gate, inet_ntoa(addr.ipv4.gw)); + os_strcpy(outNetpara->dns, inet_ntoa(addr.ipv4.dns1)); + } + + return ret; +} + +OSStatus bk_wlan_get_link_status(LinkStatusTypeDef *outStatus) +{ + struct sm_get_bss_info_cfm *cfm; +#if CFG_SUPPORT_ALIOS + msg_sta_states sta_stat; +#endif + int ret; + u8 vif_idx = 0, ssid_len; + + if( !sta_ip_is_start() ) + { + return kGeneralErr; + } + +#if CFG_SUPPORT_ALIOS + sta_stat = mhdr_get_station_status(); + if(sta_stat == MSG_GOT_IP) + { + outStatus->is_connected = true; + } + else + { + outStatus->is_connected = false; + } +#else + outStatus->conn_state = mhdr_get_station_status(); +#endif + + cfm = os_malloc(sizeof(struct sm_get_bss_info_cfm)); + if(!cfm) + { + return kNoMemoryErr; + } + + vif_idx = rwm_mgmt_vif_mac2idx((void *)&g_sta_param_ptr->own_mac); + ret = rw_msg_get_bss_info(vif_idx, (void *)cfm); + if(ret) + { + os_free(cfm); + return kGeneralErr; + } + + outStatus->wifi_strength = cfm->rssi; + if(outStatus->wifi_strength >=0) + { + // app accept rssi less than 0 + outStatus->wifi_strength = -1; + } + outStatus->channel = rw_ieee80211_get_chan_id(cfm->freq); + #if (!CFG_SUPPORT_ALIOS) + outStatus->security = g_sta_param_ptr->cipher_suite; + #endif + os_memcpy(outStatus->bssid, cfm->bssid, 6); + ssid_len = MIN(SSID_MAX_LEN, os_strlen((char*)cfm->ssid)); + os_memcpy(outStatus->ssid, cfm->ssid, ssid_len); + + os_free(cfm); + + return kNoErr; +} + +#if (!CFG_SUPPORT_ALIOS) +void bk_wlan_ap_para_info_get(network_InitTypeDef_ap_st *ap_info) +{ + IPStatusTypedef ap_ips; + + if((!ap_info)||(!uap_ip_is_start())) + { + return; + } + + memcpy(ap_info->wifi_ssid,g_ap_param_ptr->ssid.array,g_ap_param_ptr->ssid.length); + memcpy(ap_info->wifi_key,g_ap_param_ptr->key,g_ap_param_ptr->key_len); + ap_info->channel = g_ap_param_ptr->chann; + ap_info->security = g_ap_param_ptr->cipher_suite; + + bk_wlan_get_ip_status(&ap_ips,SOFT_AP); + memcpy(ap_info->local_ip_addr,ap_ips.ip,16); + memcpy(ap_info->gateway_ip_addr,ap_ips.gate,16); + memcpy(ap_info->net_mask,ap_ips.mask,16); + memcpy(ap_info->dns_server_ip_addr,ap_ips.dns,16); + + ap_info->dhcp_mode = g_wlan_general_param->dhcp_enable; +} +#endif + +uint32_t bk_wlan_get_INT_status(void) +{ + return platform_is_in_interrupt_context(); +} + +/** @brief Add the packet type which monitor should receive + * + * @detail This function can be called many times to receive different wifi packets. + */ +int bk_wlan_monitor_rx_type(int type) +{ + switch(type) + { + case WLAN_RX_BEACON: + nxmac_accept_beacon_setf(1); + break; + case WLAN_RX_PROBE_REQ: + nxmac_accept_probe_req_setf(1); + break; + case WLAN_RX_PROBE_RES: + nxmac_accept_probe_resp_setf(1); + break; + case WLAN_RX_ACTION: + break; + case WLAN_RX_MANAGEMENT: + nxmac_accept_other_mgmt_frames_setf(1); + break; + case WLAN_RX_DATA: + nxmac_accept_other_data_frames_setf(1); + nxmac_accept_qo_s_null_setf(1); + nxmac_accept_qcfwo_data_setf(1); + nxmac_accept_q_data_setf(1); + nxmac_accept_cfwo_data_setf(1); + nxmac_accept_data_setf(1); + break; + case WLAN_RX_MCAST_DATA: + nxmac_accept_multicast_setf(1); + nxmac_accept_broadcast_setf(1); + break; + case WLAN_RX_ALL: + nxmac_rx_cntrl_set((uint32_t)0x7FFFFFFC); + break; + } + + return 0; +} + +void bk_wlan_enable_lsig(void) +{ + hal_machw_allow_rx_rts_cts(); + phy_enable_lsig_intr(); +} + +void bk_wlan_disable_lsig(void) +{ + hal_machw_disallow_rx_rts_cts(); + phy_disable_lsig_intr(); +} + +#if CFG_AP_MONITOR_COEXIST +/** + * set AP+EZ mode + * @val: 1 if enable AP+EZ, 0: pure EZ + */ +void bk_wlan_set_ap_monitor_coexist(int val) +{ + g_ap_monitor_coexist = !!val; +} + +int bk_wlan_get_ap_monitor_coexist() +{ + return g_ap_monitor_coexist; +} +#endif + +/** @brief Start wifi monitor mode + * + * @detail This function disconnect wifi station and softAP. + * + */ +int bk_wlan_start_monitor(void) +{ +#if !CFG_AP_MONITOR_COEXIST + monitor_data_cb_t cb_bakup = g_monitor_cb; + g_monitor_cb = NULL; + + bk_wlan_stop(SOFT_AP); + bk_wlan_stop(STATION); + + g_monitor_cb = cb_bakup; + +#if CFG_SUPPORT_ALIOS + lsig_init(); +#endif + bk_wlan_ap_init(0); + rwnx_remove_added_interface(); + g_wlan_general_param->role = CONFIG_ROLE_NULL; +#else + if (bk_wlan_get_ap_monitor_coexist()) { + /* AP+Monitor Mode, don't need to remove all interfaces */ + hal_machw_enter_monitor_mode(); + } else { + /* Just pure monitor mode */ + monitor_data_cb_t cb_bakup = g_monitor_cb; + g_monitor_cb = NULL; + + bk_wlan_stop(SOFT_AP); + bk_wlan_stop(STATION); + + g_monitor_cb = cb_bakup; + +#if CFG_SUPPORT_ALIOS + lsig_init(); +#endif + bk_wlan_ap_init(0); + rwnx_remove_added_interface(); + g_wlan_general_param->role = CONFIG_ROLE_NULL; + } +#endif + return 0; +} + +/** @brief Stop wifi monitor mode + * + */ +int bk_wlan_stop_monitor(void) +{ + if(g_monitor_cb) + { + g_monitor_cb = 0; + hal_machw_exit_monitor_mode(); + } + + return 0; +} + +int bk_wlan_get_channel(void) +{ + int channel, freq; + + freq = rw_msg_get_channel(NULL); + channel = rw_ieee80211_get_chan_id(freq); + + return channel; +} + +/** @brief Set the monitor channel + * + * @detail This function change the monitor channel (from 1~13). + * it can change the channel dynamically, don't need restart monitor mode. + */ +int bk_wlan_set_channel_sync(int channel) +{ + rwnxl_reset_evt(0); + rw_msg_set_channel(channel, PHY_CHNL_BW_20, NULL); + + return 0; +} + +int bk_wlan_get_channel_with_band_width(int *channel, int *band_width) +{ + struct phy_channel_info info; + + phy_get_channel(&info, 0); + + *channel = rw_ieee80211_get_chan_id(info.info2); + *band_width = (info.info1 >> 8) & 0xFF; + + return 0; +} + +int bk_wlan_set_channel_with_band_width(int channel, int band_width) +{ + rwnxl_reset_evt(0); + rw_msg_set_channel((uint32_t)channel, (uint32_t)band_width, NULL); + + return 0; +} + +/** @brief Set channel at the asynchronous method + * + * @detail This function change the monitor channel (from 1~13). + * it can change the channel dynamically, don't need restart monitor mode. + */ +int bk_wlan_set_channel(int channel) +{ + wifi_country_t country; + GLOBAL_INT_DECLARATION(); + + if(0 == channel) + { + channel = 1; + } + + rw_ieee80211_get_country(&country); + if(channel < country.schan || channel > country.nchan) + { + return channel; + } + + GLOBAL_INT_DISABLE(); + g_set_channel_postpone_num = channel; + GLOBAL_INT_RESTORE(); + + CHECK_OPERATE_RF_REG_IF_IN_SLEEP(); + ke_evt_set(KE_EVT_RESET_BIT); + CHECK_OPERATE_RF_REG_IF_IN_SLEEP_END(); + + return 0; +} + +/** @brief Register the monitor callback function + * Once received a 802.11 packet call the registered function to return the packet. + */ +void bk_wlan_register_monitor_cb(monitor_data_cb_t fn) +{ + if(fn) + { + g_monitor_cb = fn; + } +} + +monitor_data_cb_t bk_wlan_get_monitor_cb(void) +{ + if (g_monitor_cb) + { +#if CFG_SUPPORT_ALIOS + return bk_monitor_callback; +#else + return g_monitor_cb; +#endif + } + else + { + return NULL; + } +} + +int bk_wlan_is_monitor_mode(void) +{ + return (0 == g_monitor_cb) ? false : true; +} + +void wlan_ui_bcn_callback(uint8_t *data, int len, hal_wifi_link_info_t *info) +{ +#if CFG_USE_STA_PS + if(power_save_if_ps_rf_dtim_enabled()) + { + power_save_bcn_callback(data,len,info); + } +#endif +#if CFG_USE_MCU_PS + mcu_ps_bcn_callback(data,len,info); +#endif +} + +void bk_wlan_register_bcn_cb(monitor_data_cb_t fn) +{ + g_bcn_cb = fn; +} + +monitor_data_cb_t bk_wlan_get_bcn_cb(void) +{ + return g_bcn_cb; +} + +extern void bmsg_ps_sender(uint8_t ioctl); + +#if CFG_USE_DEEP_PS +extern void bk_enter_deep_sleep_mode ( PS_DEEP_CTRL_PARAM *deep_param ); +#endif + +#if CFG_USE_STA_PS +static uint32_t rf_ps_enabled = 0; +/** @brief Enable dtim power save,close rf,and wakeup by ieee dtim dynamical + * + */ +int bk_wlan_dtim_rf_ps_mode_enable(void ) +{ + GLOBAL_INT_DECLARATION(); + + GLOBAL_INT_DISABLE(); + rf_ps_enabled = 1; + GLOBAL_INT_RESTORE(); + bmsg_ps_sender(PS_BMSG_IOCTL_RF_ENABLE); + + return 0; +} + + +/** @brief When in dtim rf off mode,user can manual wakeup before dtim wakeup time. + * this function can not be called in "core_thread" context + */ +extern uint8_t ble_switch_mac_sleeped; +int bk_wlan_dtim_rf_ps_mode_do_wakeup() +{ + void *sem_list = NULL; + UINT32 ret = 0; + + sem_list = power_save_rf_ps_wkup_semlist_create(); + + if (!sem_list) + { + os_null_printf("err ---- NULL\r\n"); + ASSERT(0); + } + + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + + if((power_save_if_ps_rf_dtim_enabled() + && power_save_if_rf_sleep()) || ble_switch_mac_sleeped) + { + power_save_rf_ps_wkup_semlist_wait(sem_list); + } + else + { + power_save_rf_ps_wkup_semlist_destroy(sem_list); + os_free(sem_list); + sem_list = NULL; + } + + GLOBAL_INT_RESTORE(); + + power_save_rf_ps_wkup_semlist_get(sem_list); + + return ret; +} + +int bk_wlan_dtim_rf_ps_disable_send_msg(void) +{ + power_save_dtim_rf_ps_disable_send_msg(); + + return 0; +} + +/** @brief Request exit dtim dynamical ps mode + */ +int bk_wlan_dtim_rf_ps_mode_disable(void) +{ + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + rf_ps_enabled = 0; + GLOBAL_INT_RESTORE(); + bk_wlan_dtim_rf_ps_disable_send_msg(); + return 0; +} + +int bk_wlan_dtim_rf_ps_timer_start(void) +{ + bmsg_ps_sender(PS_BMSG_IOCTL_RF_PS_TIMER_INIT); + return 0; +} + +int bk_wlan_dtim_rf_ps_timer_pause(void) +{ + bmsg_ps_sender(PS_BMSG_IOCTL_RF_PS_TIMER_DEINIT); + return 0; +} + + +int bk_wlan_dtim_rf_ps_set_linger_time(UINT32 time_ms) +{ + power_save_set_linger_time(time_ms); + + return 0; +} + +int auto_check_dtim_rf_ps_mode(void ) +{ + if(1 == rf_ps_enabled) + { + bmsg_ps_sender(PS_BMSG_IOCTL_RF_ENABLE); + } + + return 0; +} +#endif + +int bk_wlan_mcu_suppress_and_sleep(UINT32 sleep_ticks ) +{ +#if CFG_USE_MCU_PS + #if (CFG_OS_FREERTOS) + GLOBAL_INT_DECLARATION(); + GLOBAL_INT_DISABLE(); + TickType_t missed_ticks = 0; + + missed_ticks = mcu_power_save( sleep_ticks ); + fclk_update_tick( missed_ticks ); + GLOBAL_INT_RESTORE(); + #endif +#endif + return 0; +} + +#if CFG_USE_MCU_PS +/** @brief Enable mcu power save,close mcu ,and wakeup by irq + */ +int bk_wlan_mcu_ps_mode_enable(void) +{ + bmsg_ps_sender(PS_BMSG_IOCTL_MCU_ENABLE); + + return 0; +} + +/** @brief Disable mcu power save mode + */ +int bk_wlan_mcu_ps_mode_disable(void) +{ + bmsg_ps_sender(PS_BMSG_IOCTL_MCU_DISANABLE); + + return 0; +} +#endif + +#if PS_DTIM_WITH_NORMAL +/** @brief Open dtim with normal flag + */ +int bk_wlan_dtim_with_normal_open() +{ + ps_dtim_normal_enable = 1; +} + +/** @brief Close dtim with normal flag + */ +int bk_wlan_dtim_with_normal_close() +{ + ps_dtim_normal_enable = 0; +} +#endif + +BK_PS_LEVEL global_ps_level = 0; +int bk_wlan_power_save_set_level(BK_PS_LEVEL level) +{ + if(level & PS_DEEP_SLEEP_BIT) + { +#if CFG_USE_STA_PS + if(global_ps_level & PS_RF_SLEEP_BIT) + { + bk_wlan_dtim_rf_ps_mode_disable(); + } +#endif +#if CFG_USE_MCU_PS + if(global_ps_level & PS_MCU_SLEEP_BIT) + { + bk_wlan_mcu_ps_mode_disable(); + } +#endif + rtos_delay_milliseconds(100); +#if CFG_USE_DEEP_PS + /// bk_enter_deep_sleep(0xc000,0x0); +#endif + } + + if((global_ps_level & PS_RF_SLEEP_BIT) ^ (level & PS_RF_SLEEP_BIT)) + { +#if CFG_USE_STA_PS + if(global_ps_level & PS_RF_SLEEP_BIT) + { + bk_wlan_dtim_rf_ps_mode_disable(); + } + else + { + bk_wlan_dtim_rf_ps_mode_enable(); + } +#endif + } + + if((global_ps_level & PS_MCU_SLEEP_BIT) ^ (level & PS_MCU_SLEEP_BIT)) + { +#if CFG_USE_MCU_PS + if(global_ps_level & PS_MCU_SLEEP_BIT) + { + bk_wlan_mcu_ps_mode_disable(); + } + else + { + bk_wlan_mcu_ps_mode_enable(); + } +#endif + } + + global_ps_level = level; + + return 0; +} + +void bk_wlan_status_register_cb(FUNC_1PARAM_PTR cb) +{ + connection_status_cb = cb; +} + +FUNC_1PARAM_PTR bk_wlan_get_status_cb(void) +{ + return connection_status_cb; +} + +#if CFG_SUPPORT_RTT +OSStatus bk_wlan_ap_is_up(void) +{ + #if CFG_ROLE_LAUNCH + if(RL_STATUS_AP_INITING < rl_pre_ap_get_status()) + { + return 1; + } + #endif + + return 0; +} + +OSStatus bk_wlan_sta_is_connected(void) +{ + #if CFG_ROLE_LAUNCH + if(RL_STATUS_STA_LAUNCHED <= rl_pre_sta_get_status()) + { + return 1; + } + #endif + + return 0; +} +#endif + +UINT32 if_other_mode_rf_sleep(void) +{ + if(!bk_wlan_has_role(VIF_AP) + &&!bk_wlan_has_role(VIF_MESH_POINT) + &&!bk_wlan_has_role(VIF_IBSS) + &&!bk_wlan_is_monitor_mode()) + { + return 1; + } + else + { + return 0; + } +} + +uint32_t bk_wlan_start_ez_of_sta(void) +{ + return hal_machw_enter_ez_of_sta(); +} + +uint32_t bk_wlan_stop_ez_of_sta(void) +{ + return hal_machw_exit_ez_of_sta(); +} + +uint32_t bk_wlan_reg_rx_mgmt_cb(mgmt_rx_cb_t cb, uint32_t rx_mgmt_flag) +{ + return rxu_reg_mgmt_cb(cb, rx_mgmt_flag); +} + +int bk_wlan_sync_send_raw_frame(uint8_t *buffer, int len) +{ + // TODO + + return 0; +} + +extern int bmsg_tx_raw_cb_sender(uint8_t *buffer, int length, void *cb, void *param); +int bk_wlan_send_raw_frame_with_cb(uint8_t *buffer, int len, void *cb, void *param) +{ + return bmsg_tx_raw_cb_sender(buffer, len, cb, param); +} + +extern int bmsg_tx_raw_sender(uint8_t *payload, uint16_t length); +int bk_wlan_send_80211_raw_frame(uint8_t *buffer, int len) +{ + uint8_t *pkt; + int ret; + + pkt = os_malloc(len); + if (pkt == NULL) + { + return -1; + } + + os_memcpy(pkt, buffer, len); + ret = bmsg_tx_raw_sender(pkt, len); + return ret; +} + +int bk_wlan_send_80211_beacon_frame(uint8_t channel, uint8_t *ssid, uint8_t ssid_len) +{ + int ret; + BUS_MSG_PARAM_T *bcn_param; + + bcn_param = (BUS_MSG_PARAM_T*)os_zalloc(sizeof(BUS_MSG_PARAM_T)); + if (bcn_param == NULL) + return -1; + if (ssid_len >= sizeof(bcn_param->ssid)) + return -1; + bcn_param->channel = channel; + os_memcpy(bcn_param->ssid, ssid, ssid_len); + ret = bmsg_tx_beacon_sender(bcn_param); + + return ret; +} + +// eof + diff --git a/beken_os/beken378/func/wolfssl/AUTHORS b/beken_os/beken378/func/wolfssl/AUTHORS new file mode 100755 index 0000000..e69de29 diff --git a/beken_os/beken378/func/wolfssl/ChangeLog.md b/beken_os/beken378/func/wolfssl/ChangeLog.md new file mode 100755 index 0000000..d2f6f17 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/ChangeLog.md @@ -0,0 +1,2207 @@ +# wolfSSL Release 4.1.0 (07/22/2019) + +Release 4.1.0 of wolfSSL embedded TLS has bug fixes and new features including: + +* A fix for the check on return value when verifying PKCS7 bundle signatures, all users with applications using the function wc_PKCS7_VerifySignedData should update +* Adding the function wc_PKCS7_GetSignerSID for PKCS7 firmware bundles as a getter function for the signers SID +* PKCS7 callback functions for unwrapping of CEK and for decryption +* Adding the error value PKCS7_SIGNEEDS_CHECK when no certificates are available in a PKCS7 bundle to verify the signature +* TLS 1.3 fixes including if major version is TLS Draft then it is now ignored and if version negotiation occurs but none were matched then an alert is now sent +* Addition of the WOLFSSL_PSK_ONE_ID macro for indicating that only one identity in TLS 1.3 PSK is available and will be cached +* Adding sanity checks on length of PSK identity from a TLS 1.3 pre-shared key extension +* Additional sanity checks and alert messages added for TLS 1.3 +* Adding XTIME_MS macro to simplify the tls13.c time requirement +* Improvements and refactoring of code related to parsing and creating TLS 1.3 client hello packets +* TLS 1.3 version renegotiation now happens before interpreting ClientHello message +* Chacha20 algorithm optimizations on the ARM architecture for performance increase +* Poly1305 algorithm performance enhancements for the ARM architecture using the SIMD NEON extension +* Curve25519 and Ed25519 optimized for ARM architecture for performance increase +* SHA-512/384 optimizations for performance with ARM architecture using the SIMD NEON extension +* Sniffer updates including adding support for the null cipher and static ECDH key exchange and new SSLWatchCb callback +* Cipher suite TLS_RSA_WITH_NULL_MD5 for use with the sniffer (off by default) +* Sniffer statistic print outs with the macro WOLFSSL_SNIFFER_STATS defined +* A fix for wolfSSL_DH_generate_key when WOLFSSL_SMALL_STACK is defined +* wolfSSL_BN_Init implementation for opensslextra builds +* Updates to the function wolfSSL_i2d_RSAPrivateKey and additional automated tests +* Fixes for EVP_CipherFinal edge cases to match behavior desired +* Check for appropriate private vs public flag with ECC key decode in wolfSSL_EC_KEY_LoadDer_ex, thanks to Eric Miller for the report +* Implementation of the function wolfSSL_PEM_write_DHparams +* wolfSSL_RAND_seed is called in wolfSSL_Init now when opensslextra is enabled +* CryptoCell-310 support on nRF52840 added +* Fixes for atmel_ecc_create_pms to free the used slot. +* Fixes for building ATECC with ATCAPRINTF or WOLFSSL_PUBLIC_MP +* Cortex-M code changes to support IAR compiler +* Improvements to STM32 AES-GCM performance +* Fixes for 16-bit systems including PK callbacks, ATECC and LowResTimer function ptoto. +* IAR-EWARM compiler warning fix +* Clean up of user_settings for CS+ port +* Updating Renesas example projects to the latest version +* Micrium updates adjusting STATIC macro name and added inline flag +* Fixes for building with WOLFSSL_CUSTOM_CURVES on Windows +* Updates and refactor to the default build settings with Arduino +* Fixes for visibility tags with Cygwin build +* STSAFE Improvements to support wolfSSL Crypto Callbacks +* Improvements to NetBSD builds and mutex use in test case +* Updating TI hardware offload with WOLFSSL_TI_CRYPT build +* Maintaining Xilinx FreeRTOS port by adjusting time.h include in wolfSSL +* SiFive HiFive E31 RISC‐V core family port +* Port for Telit IoT AppZone SDK +* OCSP Response signed by issuer with identical SKID fix +* Fix for sending revoked certificate with OCSP +* Honor the status sent over connection with peers and do not perform an internal OCSP lookup +* Adding the build flag `--enable-ecccustcurves=all` to enable all curve types +* Support add for Ed25519ctx and Ed25519ph sign/verify algorithms as per RFC 8032 +* Addition of the macro WOLFSSL_NO_SIGALG to disable signature algorithms extension +* wc_AesCtrEncrypt in place addition, where input and output buffer can be the same buffer +* Single shot API added for SHA3; wc_Sha3_224Hash, wc_Sha3_256Hash, wc_Sha3_384Hash, wc_Sha3_512Hash +* Function additions for JSSE support some of which are wolfSSL_get_ciphers_iana and wolfSSL_X509_verify along with expansion of the --enable-jni option +* Macro guards for more modular SHA3 build (i.e. support for 384 size only) +* Benchmarking -thread argument support for asynchronous crypto +* Blake2s support (--enable-blake2s), which provides 32-bit Blake2 support +* Macro SHA256_MANY_REGISTERS addition to potentially speed up SHA256 depending on architecture +* Additional TLS alert messages sent with the macro WOLFSSL_EXTRA_ALERTS defined +* Feature to fail resumption of a session if the session’s cipher suite is not in the client’s list, this can be overridden by defining the macro NO_RESUME_SUITE_CHECK +* Fallback SCSV (Signaling Cipher Suite Value) support on Server only (--enable-fallback-scsv) +* DTLS export state only (wolfSSL_dtls_export_state_only) which is a subset of the information exported from previous DTLS export function +* Function wc_DhCheckPubValue added to perform simple validity checks on DH keys +* Support for RSA SHA-224 signatures with TLS added +* Additional option “-print” to the benchmark app for printing out a brief summary after benchmarks are complete +* Adding (--disable-pkcs12) option and improvements for disabled sections in pwdbased.c, asn.c, rsa.c, pkcs12.c and wc_encrypt +* Added DES3 support to the wolfSSL crypto callbacks +* Compile time fixes for build case with SP math and RSA only +* Fixes for Coverity static analysis report including explicit initialization of reported stack variables some additional Coverity fixes added thanks to Martin +* Fixes for scan build warnings (i.e possible null dereference in ecc.c) +* Resetting verify send value with a call to wolfSSL_clear function +* Fix for extern with sp_ModExp_2048 when building with --cpp option +* Fix for typo issue with --enable-sp=cortexm +* Adding #pragma warning disable 4127 for tfm.c when building with Visual Studio +* Improvements to the maximum ECC signature calculations +* Improvements to TLS write handling in error cases which helps user application not go through with a wolfSSL_write attempt after a wolfSSL_read failure +* Fix for read directory functions with Windows (wc_ReadDirFirst and wc_ReadDirNext) +* Sanity check on index before accessing domain component buffer in call to wolfSSL_X509_NAME_get_entry +* Sending fatal alert from client side on version error +* Fix for static RSA cipher suite with PK callback and no loaded private key +* Fix for potential memory leak in error case with the function wc_DsaKeyToDer, thanks to Chris H. for the report +* Adjusting STRING_USER macro to remove includes of standard lib or +* Bug fix for checking wrong allocation assignment in the function wc_PBKDF2 and handling potential leak on allocation failure. This case is only hit when the specific call to malloc fails in the function wc_PBKDF2. Thanks to Robert Altnoeder (Linbit) for the report +* Improved length checks when parsing ASN.1 certificates +* extern "C" additions to header files that were missing them +* Improved checking of return values with TLS extension functions and error codes +* Removing redundant calls to the generate function when instantiating and reseeding DRBG +* Refactoring and improvements to autoconf code with consolidating AM_CONDITIONAL statements +* Improvements for handling error return codes when reading input from transport layer +* Improvements to efficiency of SNI extension parsing and error checking with ALPN parsing +* Macro WOLFSSL_DEBUG_TLS addition for printing out extension data being parsed during a TLS connection +* Adjustment of prime testing with --disable-fastmath builds + + +This release of wolfSSL includes a fix for 2 security vulnerabilities. + +There is a fix for a potential buffer overflow case with the TLSv1.3 PSK extension parsing. This affects users that are enabling TLSv1.3 (--enable-tls13). Thanks to Robert Hoerr for the report. The CVE associated with the report is CVE-2019-11873. + +There is a fix for the potential leak of nonce sizes when performing ECDSA signing operations. The leak is considered to be difficult to exploit but it could potentially be used maliciously to perform a lattice based timing attack against previous wolfSSL versions. ECC operations with --enable-sp and --enable-sp-asm are not affected, users with private ECC keys in other builds that are performing ECDSA signing operations should update versions of wolfSSL along with private ECC keys. Thanks to Ján Jančár from Masaryk University for the report. + + +# wolfSSL Release 4.0.0 (03/20/2019) + +Release 4.0.0 of wolfSSL embedded TLS has bug fixes and new features including: + +* Support for wolfCrypt FIPS v4.0.0, certificate #3389 +* FIPS Ready Initiative +* Compatibility fixes for secure renegotiation with Chrome +* Better size check for TLS record fragment reassembly +* Improvements to non-blocking and handshake message retry support for DTLS +* Improvements to OCSP with ECDSA signers +* Added TLS server side secure renegotiation +* Added TLS Trusted CA extension +* Add support for the Deos Safety Critical RTOS +* OCSP fixes for memory management and initializations +* Fixes for EVP Cipher decryption padding checks +* Removal of null terminators on `wolfSSL_X509_print` substrings +* `wolfSSL_sk_ASN1_OBJCET_pop` function renamed to `wolfSSL_sk_ASN1_OBJECT_pop` +* Adjustment to include path in compatibility layer for evp.h and objects.h +* Fixes for decoding BER encoded PKCS7 contents +* TLS handshake now supports using PKCS #11 for private keys +* PKCS #11 support of HMAC, AES-CBC and random seeding/generation +* Support for named FFDHE parameters in TLS 1.2 (RFC 7919) +* Port to Zephyr Project +* Move the TLS PRF to wolfCrypt. +* Update to CMS KARI support +* Added ESP32 WROOM support +* Fixes and additions to the OpenSSL compatibility layer +* Added WICED Studio Support +* MDK CMSIS RTOS v2 +* Xcode project file update +* Fixes for ATECC508A/ATECC608A +* Fixes issue with CA path length for self signed root CA's +* Fixes for Single Precision (SP) ASM when building sources directly +* Fixes for STM32 AES GCM +* Fixes for ECC sign with hardware to ensure the input is truncated +* Fixes for proper detection of PKCS7 buffer overflow case +* Fixes to handle degenerate PKCS 7 with BER encoding +* Fixes for TLS v1.3 handling of 6144 and 8192 bit keys +* Fixes for possible build issues with SafeRTOS +* Added `ECC_PUBLICKEY_TYPE` to the support PEM header types +* Added strict checking of the ECDSA signature DER encoding length +* Added ECDSA option to limit sig/algos in client_hello to key size with + `USE_ECDSA_KEYSZ_HASH_ALGO` +* Added Cortex-M support for Single Precision (SP) math +* Added wolfCrypt RSA non-blocking time support +* Added 16-bit compiler support using --enable-16bit option +* Improved Arduino sketch example +* Improved crypto callback features +* Improved TLS benchmark tool +* Added new wrapper for snprintf for use with certain Visual Studio builds, + thanks to David Parnell (Cambridge Consultants) + +This release of wolfSSL includes a fix for 1 security vulnerability. + +* Fixed a bug in tls_bench.c example test application unrelated to the crypto + or TLS portions of the library. (CVE-2019-6439) + + +# wolfSSL Release 3.15.7 (12/26/2018) + +Release 3.15.7 of wolfSSL embedded TLS has bug fixes and new features including: + +* Support for Espressif ESP-IDF development framework +* Fix for XCode build with iPhone simulator on i386 +* PKCS7 support for generating and verify bundles using a detached signature +* Fix for build disabling AES-CBC and enabling opensslextra compatibility layer +* Updates to sniffer for showing session information and handling split messages across records +* Port update for Micrium uC/OS-III +* Feature to adjust max fragment size post handshake when compiled with the macro WOLFSSL_ALLOW_MAX_FRAGMENT_ADJUST +* Adding the macro NO_MULTIBYTE_PRINT for compiling out special characters that embedded devices may have problems with +* Updates for Doxygen documentation, including PKCS #11 API and more +* Adding Intel QuickAssist v1.7 driver support for asynchronous crypto +* Adding Intel QuickAssist RSA key generation and SHA-3 support +* RSA verify only (--enable-rsavfy) and RSA public only (--enable-rsapub) builds added +* Enhancements to test cases for increased code coverage +* Updates to VxWorks port for use with Mongoose, including updates to the OpenSSL compatibility layer +* Yocto Project ease of use improvements along with many updates and build instructions added to the INSTALL file +* Maximum ticket nonce size was increased to 8 +* Updating --enable-armasm build for ease of use with autotools +* Updates to internal code checking TLS 1.3 version with a connection +* Removing unnecessary extended master secret from ServerHello if using TLS 1.3 +* Fix for TLS v1.3 HelloRetryRequest to be sent immediately and not grouped + + + +This release of wolfSSL includes a fix for 1 security vulnerability. + +Medium level fix for potential cache attack with a variant of Bleichenbacher’s attack. Earlier versions of wolfSSL leaked PKCS #1 v1.5 padding information during private key decryption that could lead to a potential padding oracle attack. It is recommended that users update to the latest version of wolfSSL if they have RSA cipher suites enabled and have the potential for malicious software to be ran on the same system that is performing RSA operations. Users that have only ECC cipher suites enabled and are not performing RSA PKCS #1 v1.5 Decryption operations are not vulnerable. Also users with TLS 1.3 only connections are not vulnerable to this attack. Thanks to Eyal Ronen (Weizmann Institute), Robert Gillham (University of Adelaide), Daniel Genkin (University of Michigan), Adi Shamir (Weizmann Institute), David Wong (NCC Group), and Yuval Yarom (University of Adelaide and Data61) for the report. + +The paper for further reading on the attack details can be found at http://cat.eyalro.net/cat.pdf. + + +See INSTALL file for build instructions. +More info can be found on-line at http://wolfssl.com/wolfSSL/Docs.html + + +# wolfSSL Release 3.15.5 (11/07/2018) + +Release 3.15.5 of wolfSSL embedded TLS has bug fixes and new features including: + +* Fixes for GCC-8 warnings with strings +* Additional compatibility API’s added, including functions like wolfSSL_X509_CA_num and wolfSSL_PEM_read_X509_CRL +* Fixes for OCSP use with NGINX port +* Renamed the macro INLINE to WC_INLINE for inline functions +* Doxygen updates and formatting for documentation generation +* Added support for the STM32L4 with AES/SHA hardware acceleration +* Adds checking for critical extension with certificate Auth ID and the macro WOLFSSL_ALLOW_CRIT_SKID to override the check +* Added public key callbacks to ConfirmSignature function to expand public key callback support +* Added ECC and Curve25519 key generation callback support +* Fix for memory management with wolfSSL_BN_hex2bn function +* Added support for dynamic allocation of PKCS7 structure using wc_PKCS7_New and wc_PKCS7_Free +* Port to apache mynewt added in the directory wolfssl-3.15.5/IDE/mynewt/* +* OCSP stapling in TLS 1.3 additions +* Port for ASIO added with --enable-asio configure flag +* Contiki port added with macro WOLFSSL_CONTIKI +* Memory free optimizations with adding in earlier free’s where possible +* Made modifications to the primality testing so that the Miller-Rabin tests check against up to 40 random numbers rather than a fixed list of small primes +* Certificate validation time generation updated +* Fixes for MQX classic 4.0 with IAR-EWARM +* Fix for assembly optimized version of Curve25519 +* Make SOCKET_PEER_CLOSED_E consistent between read and write cases +* Relocate compatibility layer functions for OpenSSH port update +* Update to Intel® SGX port, files included by Windows version and macros defined when using WOLFSSL_SGX +* Updates to Nucleus version supported +* Stack size reduction with smallstack build +* Updates to Rowley-Crossworks settings for CMSIS 4 +* Added reference STSAFE-A100 public key callbacks for TLS support +* Added reference ATECC508A/ATECC608A public key callbacks for TLS support +* Updated support for latest CryptoAuthLib (10/25/2018) +* Added a wolfSSL static library project for Atollic TrueSTUDIO +* Flag to disable AES-CBC and have only AEAD cipher suites with TLS +* AF_ALG and cryptodev-linux crypto support added +* Update to IO callbacks with use of WOLFSSL_BIO +* Additional support for parsing certificate subject OIDs (businessCategory, jurisdiction of incorporation country, and jurisdiction of incorporation state) +* Added wc_ecc_ecport_ex and wc_export_inti API's for ECC hex string exporting +* Updates to XCODE build with wolfSSL +* Fix for guard on when to include sys/time.h header +* Updates and enhancements to the GCC-ARM example +* Fix for PKCS8 padding with encryption +* Updates for wolfcrypt JNI wrapper +* ALT_ECC_SIZE use with SP math +* PIC32MZ hardware acceleration buffer alignment fixes +* Renesas e2studio project files added +* Renesas RX example project added +* Fix for DH algorithm when using SP math with ARM assembly +* Fixes and enhancements for NXP K82 support +* Benchmark enhancements to print in CSV format and in Japanese +* Support for PKCS#11 added with --enable-pkcs11 +* Fixes for asynchronous crypto use with TLS 1.3 +* TLS 1.3 only build, allows for disabling TLS 1.2 and earlier protocols +* Fix for GCC warnings in function wolfSSL_ASN1_TIME_adj +* Added --enable-asn=nocrypt for certificate only parsing support +* Added support for parsing PIV format certificates with the function wc_ParseCertPIV and macro WOLFSSL_CERT_PIV +* Added APIs to support GZIP +* Updates to support Lighttpd +* Version resource added for Windows DLL builds +* Increased code coverage with additional testing +* Added support for constructed OCTET_STRING with PKCS#7 signed data +* Added DTLS either (server/client) side initialization setting +* Minor fixes for building with MINGW32 compiler +* Added support for generic ECC PEM header/footer with PKCS8 parsing +* Added Japanese output to example server and client with “-1 1” flag +* Added USE_ECDSA_KEYSZ_HASH_ALGO macro for building to use digest sizes that match ephemeral key size +* Expand PKCS#7 CMS support with KEKRI, PWRI and ORI +* Streaming capability for PKCS#7 decoding and sign verify added + + +See INSTALL file for build instructions. +More info can be found on-line at http://wolfssl.com/wolfSSL/Docs.html + + +# wolfSSL Release 3.15.3 (6/20/2018) + +Release 3.15.3 of wolfSSL embedded TLS has bug fixes and new features including: + +* ECDSA blinding added for hardening against side channel attacks +* Fix for compatibility layer build with no server and no client defined +* Use of optimized Intel assembly instructions on compatible AMD processor +* wolfCrypt Nucleus port additions +* Fix added for MatchDomainName and additional tests added +* Fixes for building with ‘WOLFSSL_ATECC508A’ defined +* Fix for verifying a PKCS7 file in BER format with indefinite size + + +This release of wolfSSL fixes 2 security vulnerability fixes. + +Medium level fix for PRIME + PROBE attack combined with a variant of Lucky 13. Constant time hardening was done to avoid potential cache-based side channel attacks when verifying the MAC on a TLS packet. CBC cipher suites are susceptible on systems where an attacker could gain access and run a parallel program for inspecting caching. Only wolfSSL users that are using TLS/DTLS CBC cipher suites need to update. Users that have only AEAD and stream cipher suites set, or have built with WOLFSSL_MAX_STRENGTH (--enable-maxstrength), are not vulnerable. Thanks to Eyal Ronen, Kenny Paterson, and Adi Shamir for the report. + +Medium level fix for a ECDSA side channel attack. wolfSSL is one of over a dozen vendors mentioned in the recent Technical Advisory “ROHNP” by author Ryan Keegan. Only wolfSSL users with long term ECDSA private keys using our fastmath or normal math libraries on systems where attackers can get access to the machine using the ECDSA key need to update. An attacker gaining access to the system could mount a memory cache side channel attack that could recover the key within a few thousand signatures. wolfSSL users that are not using ECDSA private keys, that are using the single precision math library, or that are using ECDSA offloading do not need to update. (blog with more information https://www.wolfssl.com/wolfssh-and-rohnp/) + + +See INSTALL file for build instructions. +More info can be found on-line at http://wolfssl.com/wolfSSL/Docs.html + +# wolfSSL Release 3.15.0 (06/05/2018) + +Release 3.15.0 of wolfSSL embedded TLS has bug fixes and new features including: + +* Support for TLS 1.3 Draft versions 23, 26 and 28. +* Add FIPS SGX support! +* Single Precision assembly code added for ARM and 64-bit ARM to enhance performance. +* Improved performance for Single Precision maths on 32-bit. +* Improved downgrade support for the TLS 1.3 handshake. +* Improved TLS 1.3 support from interoperability testing. +* Added option to allow TLS 1.2 to be compiled out to reduce size and enhance security. +* Added option to support Ed25519 in TLS 1.2 and 1.3. +* Update wolfSSL_HMAC_Final() so the length parameter is optional. +* Various fixes for Coverity static analysis reports. +* Add define to use internal struct timeval (USE_WOLF_TIMEVAL_T). +* Switch LowResTimer() to call XTIME instead of time(0) for better portability. +* Expanded OpenSSL compatibility layer with a bevy of new functions. +* Added Renesas CS+ project files. +* Align DH support with NIST SP 800-56A, add wc_DhSetKey_ex() for q parameter. +* Add build option for CAVP self test build (--enable-selftest). +* Expose mp_toradix() when WOLFSSL_PUBLIC_MP is defined. +* Example certificate expiration dates and generation script updated. +* Additional optimizations to trim out unused strings depending on build options. +* Fix for DN tag strings to have “=” when returning the string value to users. +* Fix for wolfSSL_ERR_get_error_line_data return value if no more errors are in the queue. +* Fix for AES-CBC IV value with PIC32 hardware acceleration. +* Fix for wolfSSL_X509_print with ECC certificates. +* Fix for strict checking on URI absolute vs relative path. +* Added crypto device framework to handle PK RSA/ECC operations using callbacks, which adds new build option `./configure --enable-cryptodev` or `WOLF_CRYPTO_DEV`. +* Added devId support to ECC and PKCS7 for hardware based private key. +* Fixes in PKCS7 for handling possible memory leak in some error cases. +* Added test for invalid cert common name when set with `wolfSSL_check_domain_name`. +* Refactor of the cipher suite names to use single array, which contains internal name, IANA name and cipher suite bytes. +* Added new function `wolfSSL_get_cipher_name_from_suite` for getting IANA cipher suite name using bytes. +* Fixes for fsanitize reports. +* Fix for openssl compatibility function `wolfSSL_RSA_verify` to check returned size. +* Fixes and improvements for FreeRTOS AWS. +* Fixes for building openssl compatibility with FreeRTOS. +* Fix and new test for handling match on domain name that may have a null terminator inside. +* Cleanup of the socket close code used for examples, CRL/OCSP and BIO to use single macro `CloseSocket`. +* Refactor of the TLSX code to support returning error codes. +* Added new signature wrapper functions `wc_SignatureVerifyHash` and `wc_SignatureGenerateHash` to allow direct use of hash. +* Improvement to GCC-ARM IDE example. +* Enhancements and cleanups for the ASN date/time code including new API's `wc_GetDateInfo`, `wc_GetCertDates` and `wc_GetDateAsCalendarTime`. +* Fixes to resolve issues with C99 compliance. Added build option `WOLF_C99` to force C99. +* Added a new `--enable-opensslall` option to enable all openssl compatibility features. +* Added new `--enable-webclient` option for enabling a few HTTP API's. +* Added new `wc_OidGetHash` API for getting the hash type from a hash OID. +* Moved `wolfSSL_CertPemToDer`, `wolfSSL_KeyPemToDer`, `wolfSSL_PubKeyPemToDer` to asn.c and renamed to `wc_`. Added backwards compatibility macro for old function names. +* Added new `WC_MAX_SYM_KEY_SIZE` macro for helping determine max key size. +* Added `--enable-enckeys` or (`WOLFSSL_ENCRYPTED_KEYS`) to enable support for encrypted PEM private keys using password callback without having to use opensslextra. +* Added ForceZero on the password buffer after done using it. +* Refactor unique hash types to use same internal values (ex WC_MD5 == WC_HASH_TYPE_MD5). +* Refactor the Sha3 types to use `wc_` naming, while retaining old names for compatibility. +* Improvements to `wc_PBKDF1` to support more hash types and the non-standard extra data option. +* Fix TLS 1.3 with ECC disabled and CURVE25519 enabled. +* Added new define `NO_DEV_URANDOM` to disable the use of `/dev/urandom`. +* Added `WC_RNG_BLOCKING` to indicate block w/sleep(0) is okay. +* Fix for `HAVE_EXT_CACHE` callbacks not being available without `OPENSSL_EXTRA` defined. +* Fix for ECC max bits `MAX_ECC_BITS` not always calculating correctly due to macro order. +* Added support for building and using PKCS7 without RSA (assuming ECC is enabled). +* Fixes and additions for Cavium Nitrox V to support ECC, AES-GCM and HMAC (SHA-224 and SHA3). +* Enabled ECC, AES-GCM and SHA-512/384 by default in (Linux and Windows) +* Added `./configure --enable-base16` and `WOLFSSL_BASE16` configuration option to enable Base16 API's. +* Improvements to ATECC508A support for building without `WOLFSSL_ATMEL` defined. +* Refactor IO callback function names to use `_CTX_` to eliminate confusion about the first parameter. +* Added support for not loading a private key for server or client when `HAVE_PK_CALLBACK` is defined and the private PK callback is set. +* Added new ECC API `wc_ecc_sig_size_calc` to return max signature size for a key size. +* Cleanup ECC point import/export code and added new API `wc_ecc_import_unsigned`. +* Fixes for handling OCSP with non-blocking. +* Added new PK (Primary Key) callbacks for the VerifyRsaSign. The new callbacks API's are `wolfSSL_CTX_SetRsaVerifySignCb` and `wolfSSL_CTX_SetRsaPssVerifySignCb`. +* Added new ECC API `wc_ecc_rs_raw_to_sig` to take raw unsigned R and S and encodes them into ECDSA signature format. +* Added support for `WOLFSSL_STM32F1`. +* Cleanup of the ASN X509 header/footer and XSTRNCPY logic. +* Add copyright notice to autoconf files. (Thanks Brian Aker!) +* Updated the M4 files for autotools. (Thanks Brian Aker!) +* Add support for the cipher suite TLS_DH_anon_WITH_AES256_GCM_SHA384 with test cases. (Thanks Thivya Ashok!) +* Add the TLS alert message unknown_psk_identity (115) from RFC 4279, section 2. (Thanks Thivya Ashok!) +* Fix the case when using TCP with timeouts with TLS. wolfSSL shall be agnostic to network socket behavior for TLS. (DTLS is another matter.) The functions `wolfSSL_set_using_nonblock()` and `wolfSSL_get_using_nonblock()` are deprecated. +* Hush the AR warning when building the static library with autotools. +* Hush the “-pthread” warning when building in some environments. +* Added a dist-hook target to the Makefile to reset the default options.h file. +* Removed the need for the darwin-clang.m4 file with the updates provided by Brian A. +* Renamed the AES assembly file so GCC on the Mac will build it using the preprocessor. +* Add a disable option (--disable-optflags) to turn off the default optimization flags so user may supply their own custom flags. +* Correctly touch the dummy fips.h header. + +If you have questions on any of this, then email us at info@wolfssl.com. +See INSTALL file for build instructions. +More info can be found on-line at http://wolfssl.com/wolfSSL/Docs.html + + +# wolfSSL Release 3.14.0 (03/02/2018) + +Release 3.14.0 of wolfSSL embedded TLS has bug fixes and new features including: + +* TLS 1.3 draft 22 and 23 support added +* Additional unit tests for; SHA3, AES-CMAC, Ed25519, ECC, RSA-PSS, AES-GCM +* Many additions to the OpenSSL compatibility layer were made in this release. Some of these being enhancements to PKCS12, WOLFSSL_X509 use, WOLFSSL_EVP_PKEY, and WOLFSSL_BIO operations +* AVX1 and AVX2 performance improvements with ChaCha20 and Poly1305 +* Added i.MX CAAM driver support with Integrity OS support +* Improvements to logging with debugging, including exposing more API calls and adding options to reduce debugging code size +* Fix for signature type detection with PKCS7 RSA SignedData +* Public key call back functions added for DH Agree +* RSA-PSS API added for operating on non inline buffers (separate input and output buffers) +* API added for importing and exporting raw DSA parameters +* Updated DSA key generation to be FIPS 186-4 compliant +* Fix for wolfSSL_check_private_key when comparing ECC keys +* Support for AES Cipher Feedback(CFB) mode added +* Updated RSA key generation to be FIPS 186-4 compliant +* Update added for the ARM CMSIS software pack +* WOLFSSL_IGNORE_FILE_WARN macro added for avoiding build warnings when not working with autotools +* Performance improvements for AES-GCM with AVX1 and AVX2 +* Fix for possible memory leak on error case with wc_RsaKeyToDer function +* Make wc_PKCS7_PadData function available +* Updates made to building SGX on Linux +* STM32 hashing algorithm improvements including clock/power optimizations and auto detection of if SHA2 is supported +* Update static memory feature for FREERTOS use +* Reverse the order that certificates are compared during PKCS12 parse to account for case where multiple certificates have the same matching private key +* Update NGINX port to version 1.13.8 +* Support for HMAC-SHA3 added +* Added stricter ASN checks to enforce RFC 5280 rules. Thanks to the report from Professor Zhenhua Duan, Professor Cong Tian, and Ph.D candidate Chu Chen from Institute of Computing Theory and Technology (ICTT) of Xidian University. +* Option to have ecc_mul2add function public facing +* Getter function wc_PKCS7_GetAttributeValue added for PKCS7 attributes +* Macros NO_AES_128, NO_AES_192, NO_AES_256 added for AES key size selection at compile time +* Support for writing multiple organizations units (OU) and domain components (DC) with CSR and certificate creation +* Support for indefinite length BER encodings in PKCS7 +* Added API for additional validation of prime q in a public DH key +* Added support for RSA encrypt and decrypt without padding + + +See INSTALL file for build instructions. +More info can be found on-line at http://wolfssl.com/wolfSSL/Docs.html + + +# wolfSSL (Formerly CyaSSL) Release 3.13.0 (12/21/2017) + +wolfSSL 3.13.0 includes bug fixes and new features, including support for +TLS 1.3 Draft 21, performance and footprint optimizations, build fixes, +updated examples and project files, and one vulnerability fix. The full list +of changes and additions in this release include: + +* Fixes for TLS 1.3, support for Draft 21 +* TLS 1.0 disabled by default, addition of “--enable-tlsv10” configure option +* New option to reduce SHA-256 code size at expense of performance + (USE_SLOW_SHA256) +* New option for memory reduced build (--enable-lowresource) +* AES-GCM performance improvements on AVX1 (IvyBridge) and AVX2 +* SHA-256 and SHA-512 performance improvements using AVX1/2 ASM +* SHA-3 size and performance optimizations +* Fixes for Intel AVX2 builds on Mac/OSX +* Intel assembly for Curve25519, and Ed25519 performance optimizations +* New option to force 32-bit mode with “--enable-32bit” +* New option to disable all inline assembly with “--disable-asm” +* Ability to override maximum signature algorithms using WOLFSSL_MAX_SIGALGO +* Fixes for handling of unsupported TLS extensions. +* Fixes for compiling AES-GCM code with GCC 4.8.* +* Allow adjusting static I/O buffer size with WOLFMEM_IO_SZ +* Fixes for building without a filesystem +* Removes 3DES and SHA1 dependencies from PKCS#7 +* Adds ability to disable PKCS#7 EncryptedData type (NO_PKCS7_ENCRYPTED_DATA) +* Add ability to get client-side SNI +* Expanded OpenSSL compatibility layer +* Fix for logging file names with OpenSSL compatibility layer enabled, with + WOLFSSL_MAX_ERROR_SZ user-overridable +* Adds static memory support to the wolfSSL example client +* Fixes for sniffer to use TLS 1.2 client method +* Adds option to wolfCrypt benchmark to benchmark individual algorithms +* Adds option to wolfCrypt benchmark to display benchmarks in powers + of 10 (-base10) +* Updated Visual Studio for ARM builds (for ECC supported curves and SHA-384) +* Updated Texas Instruments TI-RTOS build +* Updated STM32 CubeMX build with fixes for SHA +* Updated IAR EWARM project files +* Updated Apple Xcode projects with the addition of a benchmark example project + +This release of wolfSSL fixes 1 security vulnerability. + +wolfSSL is cited in the recent ROBOT Attack by Böck, Somorovsky, and Young. +The paper notes that wolfSSL only gives a weak oracle without a practical +attack but this is still a flaw. This release contains a fix for this report. +Please note that wolfSSL has static RSA cipher suites disabled by default as +of version 3.6.6 because of the lack of perfect forward secrecy. Only users +who have explicitly enabled static RSA cipher suites with WOLFSSL_STATIC_RSA +and use those suites on a host are affected. More information will be +available on our website at: + +https://wolfssl.com/wolfSSL/security/vulnerabilities.php + +See INSTALL file for build instructions. +More info can be found on-line at http://wolfssl.com/wolfSSL/Docs.html + + +# wolfSSL (Formerly CyaSSL) Release 3.12.2 (10/23/2017) + +## Release 3.12.2 of wolfSSL has bug fixes and new features including: + +This release includes many performance improvements with Intel ASM (AVX/AVX2) and AES-NI. New single precision math option to speedup RSA, DH and ECC. Embedded hardware support has been expanded for STM32, PIC32MZ and ATECC508A. AES now supports XTS mode for disk encryption. Certificate improvements for setting serial number, key usage and extended key usage. Refactor of SSL_ and hash types to allow openssl coexistence. Improvements for TLS 1.3. Fixes for OCSP stapling to allow disable and WOLFSSL specific user context for callbacks. Fixes for openssl and MySQL compatibility. Updated Micrium port. Fixes for asynchronous modes. + +* Added TLS extension for Supported Point Formats (ec_point_formats) +* Fix to not send OCSP stapling extensions in client_hello when not enabled +* Added new API's for disabling OCSP stapling +* Add check for SIZEOF_LONG with sun and LP64 +* Fixes for various TLS 1.3 disable options (RSA, ECC and ED/Curve 25519). +* Fix to disallow upgrading to TLS v1.3 +* Fixes for wolfSSL_EVP_CipherFinal() when message size is a round multiple of a block size. +* Add HMAC benchmark and expanded AES key size benchmarks +* Added simple GCC ARM Makefile example +* Add tests for 3072-bit RSA and DH. +* Fixed DRAFT_18 define and fixed downgrading with TLS v1.3 +* Fixes to allow custom serial number during certificate generation +* Add method to get WOLFSSL_CTX certificate manager +* Improvement to `wolfSSL_SetOCSP_Cb` to allow context per WOLFSSL object +* Alternate certificate chain support `WOLFSSL_ALT_CERT_CHAINS`. Enables checking cert against multiple CA's. +* Added new `--disable-oldnames` option to allow for using openssl along-side wolfssl headers (without OPENSSL_EXTRA). +* Refactor SSL_ and hashing types to use wolf specific prefix (WOLFSSL and WC_) to allow openssl coexistence. +* Fixes for HAVE_INTEL_MULX +* Cleanup include paths for MySQL cmake build +* Added configure option for building library for wolfSSH (--enable-wolfssh) +* Openssl compatibility layer improvements +* Expanded API unit tests +* Fixes for STM32 crypto hardware acceleration +* Added AES XTS mode (--enable-xts) +* Added ASN Extended Key Usage Support (see wc_SetExtKeyUsage). +* Math updates and added TFM_MIPS speedup. +* Fix for creation of the KeyUsage BitString +* Fix for 8k keys with MySQL compatibility +* Fixes for ATECC508A. +* Fixes for PIC32MZ hashing. +* Fixes and improvements to asynchronous modes for Intel QuickAssist and Cavium Nitrox V. +* Update HASH_DRBG Reseed mechanism and add test case +* Rename the file io.h/io.c to wolfio.h/wolfio.c +* Cleanup the wolfIO_Send function. +* OpenSSL Compatibility Additions and Fixes +* Improvements to Visual Studio DLL project/solution. +* Added function to generate public ECC key from private key +* Added async blocking support for sniffer tool. +* Added wolfCrypt hash tests for empty string and large data. +* Added ability to use of wolf implementation of `strtok` using `USE_WOLF_STRTOK`. +* Updated Micrium uC/OS-III Port +* Updated root certs for OCSP scripts +* New Single Precision math option for RSA, DH and ECC (off by default). See `--enable-sp`. +* Speedups for AES GCM with AESNI (--enable-aesni) +* Speedups for SHA2, ChaCha20/Poly1035 using AVX/AVX2 + + +# wolfSSL (Formerly CyaSSL) Release 3.12.0 (8/04/2017) + +## Release 3.12.0 of wolfSSL has bug fixes and new features including: + +- TLS 1.3 with Nginx! TLS 1.3 with ARMv8! TLS 1.3 with Async Crypto! (--enable-tls13) +- TLS 1.3 0RTT feature added +- Added port for using Intel SGX with Linux +- Update and fix PIC32MZ port +- Additional unit testing for MD5, SHA, SHA224, SHA256, SHA384, SHA512, RipeMd, HMAC, 3DES, IDEA, ChaCha20, ChaCha20Poly1305 AEAD, Camellia, Rabbit, ARC4, AES, RSA, Hc128 +- AVX and AVX2 assembly for improved ChaCha20 performance +- Intel QAT fixes for when using --disable-fastmath +- Update how DTLS handles decryption and MAC failures +- Update DTLS session export version number for --enable-sessionexport feature +- Add additional input argument sanity checks to ARMv8 assembly port +- Fix for making PKCS12 dynamic types match +- Fixes for potential memory leaks when using --enable-fast-rsa +- Fix for when using custom ECC curves and add BRAINPOOLP256R1 test +- Update TI-RTOS port for dependency on new wolfSSL source files +- DTLS multicast feature added, --enable-mcast +- Fix for Async crypto with GCC 7.1 and HMAC when not using Intel QuickAssist +- Improvements and enhancements to Intel QuickAssist support +- Added Xilinx port +- Added SHA3 Keccak feature, --enable-sha3 +- Expand wolfSSL Python wrapper to now include a client side implementation +- Adjust example servers to not treat a peer closed error as a hard error +- Added more sanity checks to fp_read_unsigned_bin function +- Add SHA224 and AES key wrap to ARMv8 port +- Update MQX classics and mmCAU ports +- Fix for potential buffer over read with wolfSSL_CertPemToDer +- Add PKCS7/CMS decode support for KARI with IssuerAndSerialNumber +- Fix ThreadX/NetX warning +- Fixes for OCSP and CRL non blocking sockets and for incomplete cert chain with OCSP +- Added RSA PSS sign and verify +- Fix for STM32F4 AES-GCM +- Added enable all feature (--enable-all) +- Added trackmemory feature (--enable-trackmemory) +- Fixes for AES key wrap and PKCS7 on Windows VS +- Added benchmark block size argument +- Support use of staticmemory with PKCS7 +- Fix for Blake2b build with GCC 5.4 +- Fixes for compiling wolfSSL with GCC version 7, most dealing with switch statement fall through warnings. +- Added warning when compiling without hardened math operations + + +Note: +There is a known issue with using ChaCha20 AVX assembly on versions of GCC earlier than 5.2. This is encountered with using the wolfSSL enable options --enable-intelasm and --enable-chacha. To avoid this issue ChaCha20 can be enabled with --enable-chacha=noasm. +If using --enable-intelasm and also using --enable-sha224 or --enable-sha256 there is a known issue with trying to use -fsanitize=address. + +This release of wolfSSL fixes 1 low level security vulnerability. + +Low level fix for a potential DoS attack on a wolfSSL client. Previously a client would accept many warning alert messages without a limit. This fix puts a limit to the number of warning alert messages received and if this limit is reached a fatal error ALERT_COUNT_E is returned. The max number of warning alerts by default is set to 5 and can be adjusted with the macro WOLFSSL_ALERT_COUNT_MAX. Thanks for the report from Tarun Yadav and Koustav Sadhukhan from Defence Research and Development Organization, INDIA. + + +See INSTALL file for build instructions. +More info can be found on-line at http://wolfssl.com/wolfSSL/Docs.html + + +# wolfSSL (Formerly CyaSSL) Release 3.11.1 (5/11/2017) + +## Release 3.11.1 of wolfSSL is a TLS 1.3 BETA release, which includes: + +- TLS 1.3 client and server support for TLS 1.3 with Draft 18 support + +This is strictly a BETA release, and designed for testing and user feedback. +Please send any comments, testing results, or feedback to wolfSSL at +support@wolfssl.com. + +See INSTALL file for build instructions. +More info can be found on-line at http://wolfssl.com/wolfSSL/Docs.html + + +# wolfSSL (Formerly CyaSSL) Release 3.11.0 (5/04/2017) + +## Release 3.11.0 of wolfSSL has bug fixes and new features including: + +- Code updates for warnings reported by Coverity scans +- Testing and warning fixes for FreeBSD on PowerPC +- Updates and refactoring done to ASN1 parsing functions +- Change max PSK identity buffer to account for an identity length of 128 characters +- Update Arduino script to handle recent files and additions +- Added support for PKCS#7 Signed Data with ECDSA +- Fix for interoperability with ChaCha20-Poly1305 suites using older draft versions +- DTLS update to allow multiple handshake messages in one DTLS record. Thanks to Eric Samsel over at Welch Allyn for reporting this bug. +- Intel QuickAssist asynchronous support (PR #715 - https://www.wolfssl.com/wolfSSL/Blog/Entries/2017/1/18_wolfSSL_Asynchronous_Intel_QuickAssist_Support.html) +- Added support for HAproxy load balancer +- Added option to allow SHA1 with TLS 1.2 for IIS compatibility (WOLFSSL_ALLOW_TLS_SHA1) +- Added Curve25519 51-bit Implementation, increasing performance on systems that have 128 bit types +- Fix to not send session ID on server side if session cache is off unless we're echoing +session ID as part of session tickets +- Fixes for ensuring all default ciphers are setup correctly (see PR #830) +- Added NXP Hexiwear example in `IDE/HEXIWEAR`. +- Added wolfSSL_write_dup() to create write only WOLFSSL object for concurrent access +- Fixes for TLS elliptic curve selection on private key import. +- Fixes for RNG with Intel rdrand and rdseed speedups. +- Improved performance with Intel rdrand to use full 64-bit output +- Added new --enable-intelrand option to indicate use of RDRAND preference for RNG source +- Removed RNG ARC4 support +- Added ECC helpers to get size and id from curve name. +- Added ECC Cofactor DH (ECC-CDH) support +- Added ECC private key only import / export functions. +- Added PKCS8 create function +- Improvements to TLS layer CTX handling for switching keys / certs. +- Added check for duplicate certificate policy OID in certificates. +- Normal math speed-up to not allocate on mp_int and defer until mp_grow +- Reduce heap usage with fast math when not using ALT_ECC_SIZE +- Fixes for building CRL with Windows +- Added support for inline CRL lookup when HAVE_CRL_IO is defined +- Added port for tenAsys INtime RTOS +- Improvements to uTKernel port (WOLFSSL_uTKERNEL2) +- Updated WPA Supplicant support +- Added support for Nginx +- Update stunnel port for version 5.40 +- Fixes for STM32 hardware crypto acceleration +- Extended test code coverage in bundled test.c +- Added a sanity check for minimum authentication tag size with AES-GCM. Thanks to Yueh-Hsun Lin and Peng Li at KNOX Security at Samsung Research America for suggesting this. +- Added a sanity check that subject key identifier is marked as non-critical and a check that no policy OIDS appear more than once in the cert policies extension. Thanks to the report from Professor Zhenhua Duan, Professor Cong Tian, and Ph.D candidate Chu Chen from Institute of Computing Theory and Technology (ICTT) of Xidian University, China. Profs. Zhenhua Duan and Cong Tian are supervisors of Ph.D candidate Chu Chen. + +This release of wolfSSL fixes 5 low and 1 medium level security vulnerability. + +3 Low level fixes reported by Yueh-Hsun Lin and Peng Li from KNOX Security, Samsung Research America. +- Fix for out of bounds memory access in wc_DhParamsLoad() when GetLength() returns a zero. Before this fix there is a case where wolfSSL would read out of bounds memory in the function wc_DhParamsLoad. +- Fix for DH key accepted by wc_DhAgree when the key was malformed. +- Fix for a double free case when adding CA cert into X509_store. + +Low level fix for memory management with static memory feature enabled. By default static memory is disabled. Thanks to GitHub user hajjihraf for reporting this. + + +Low level fix for out of bounds write in the function wolfSSL_X509_NAME_get_text_by_NID. This function is not used by TLS or crypto operations but could result in a buffer out of bounds write by one if called explicitly in an application. Discovered by Aleksandar Nikolic of Cisco Talos. http://talosintelligence.com/vulnerability-reports/ + +Medium level fix for check on certificate signature. There is a case in release versions 3.9.10, 3.10.0 and 3.10.2 where a corrupted signature on a peer certificate would not be properly flagged. Thanks to Wens Lo, James Tsai, Kenny Chang, and Oscar Yang at Castles Technology. + + +See INSTALL file for build instructions. +More info can be found on-line at http://wolfssl.com/wolfSSL/Docs.html + + +# wolfSSL (Formerly CyaSSL) Release 3.10.2 (2/10/2017) + +## Release 3.10.2 of wolfSSL has bug fixes and new features including: + +- Poly1305 Windows macros fix. Thanks to GitHub user Jay Satiro +- Compatibility layer expanded with multiple functions added +- Improve fp_copy performance with ALT_ECC_SIZE +- OCSP updates and improvements +- Fixes for IAR EWARM 8 compiler warnings +- Reduce stack usage with ECC_CACHE_CURVE disabled +- Added ECC export raw for public and private key +- Fix for NO_ASN_TIME build +- Supported curves extensions now populated by default +- Add DTLS build without big integer math +- Fix for static memory feature with wc_ecc_verify_hash_ex and not SHAMIR +- Added PSK interoperability testing to script bundled with wolfSSL +- Fix for Python wrapper random number generation. Compiler optimizations with Python could place the random number in same buffer location each time. Thanks to GitHub user Erik Bray (embray) +- Fix for tests on unaligned memory with static memory feature +- Add macro WOLFSSL_NO_OCSP_OPTIONAL_CERTS to skip optional OCSP certificates +- Sanity checks on NULL arguments added to wolfSSL_set_fd and wolfSSL_DTLS_SetCookieSecret +- mp_jacobi stack use reduced, thanks to Szabi Tolnai for providing a solution to reduce stack usage + + +This release of wolfSSL fixes 2 low and 1 medium level security vulnerability. + +Low level fix of buffer overflow for when loading in a malformed temporary DH file. Thanks to Yueh-Hsun Lin and Peng Li from KNOX Security, Samsung Research America for the report. + +Medium level fix for processing of OCSP response. If using OCSP without hard faults enforced and no alternate revocation checks like OCSP stapling then it is recommended to update. + +Low level fix for potential cache attack on RSA operations. If using wolfSSL RSA on a server that other users can have access to monitor the cache, then it is recommended to update wolfSSL. Thanks to Andreas Zankl, Johann Heyszl and Georg Sigl at Fraunhofer AISEC for the initial report. + +See INSTALL file for build instructions. +More info can be found on-line at http://wolfssl.com/wolfSSL/Docs.html + + +# wolfSSL (Formerly CyaSSL) Release 3.10.0 (12/21/2016) + +## Release 3.10.0 of wolfSSL has bug fixes and new features including: + +- Added support for SHA224 +- Added scrypt feature +- Build for Intel SGX use, added in directory IDE/WIN-SGX +- Fix for ChaCha20-Poly1305 ECDSA certificate type request +- Enhance PKCS#7 with ECC enveloped data and AES key wrap support +- Added support for RIOT OS +- Add support for parsing PKCS#12 files +- ECC performance increased with custom curves +- ARMv8 expanded to AArch32 and performance increased +- Added ANSI-X9.63-KDF support +- Port to STM32 F2/F4 CubeMX +- Port to Atmel ATECC508A board +- Removed fPIE by default when wolfSSL library is compiled +- Update to Python wrapper, dropping DES and adding wc_RSASetRNG +- Added support for NXP K82 hardware acceleration +- Added SCR client and server verify check +- Added a disable rng option with autoconf +- Added more tests vectors to test.c with AES-CTR +- Updated DTLS session export version number +- Updated DTLS for 64 bit sequence numbers +- Fix for memory management with TI and WOLFSSL_SMALL_STACK +- Hardening RSA CRT to be constant time +- Fix uninitialized warning with IAR compiler +- Fix for C# wrapper example IO hang on unexpected connection termination + + +This release of wolfSSL fixes a low level security vulnerability. The vulnerability reported was a potential cache attack on RSA operations. If using wolfSSL RSA on a server that other users can have access to monitor the cache, then it is recommended to update wolfSSL. Thanks to Andreas Zankl, Johann Heyszl and Georg Sigl at Fraunhofer AISEC for the report. More information will be available on our site: + +https://wolfssl.com/wolfSSL/security/vulnerabilities.php + +See INSTALL file for build instructions. +More info can be found on-line at http://wolfssl.com/wolfSSL/Docs.html + + +# wolfSSL (Formerly CyaSSL) Release 3.9.10 (9/23/2016) + +## Release 3.9.10 of wolfSSL has bug fixes and new features including: + +- Default configure option changes: + 1. DES3 disabled by default + 2. ECC Supported Curves Extension enabled by default + 3. New option Extended Master Secret enabled by default +- Added checking CA certificate path length, and new test certs +- Fix to DSA pre padding and sanity check on R/S values +- Added CTX level RNG for single-threaded builds +- Intel RDSEED enhancements +- ARMv8 hardware acceleration support for AES-CBC/CTR/GCM, SHA-256 +- Arduino support updates +- Added the Extended Master Secret TLS extension + 1. Enabled by default in configure options, API to disable + 2. Added support for Extended Master Secret to sniffer +- OCSP fix with issuer key hash, lookup refactor +- Added support for Frosted OS +- Added support for DTLS over SCTP +- Added support for static memory with wolfCrypt +- Fix to ECC Custom Curve support +- Support for asynchronous wolfCrypt RSA and TLS client +- Added distribution build configure option +- Update the test certificates + +This release of wolfSSL fixes medium level security vulnerabilities. Fixes for +potential AES, RSA, and ECC side channel leaks is included that a local user +monitoring the same CPU core cache could exploit. VM users, hyper-threading +users, and users where potential attackers have access to the CPU cache will +need to update if they utilize AES, RSA private keys, or ECC private keys. +Thanks to Gorka Irazoqui Apecechea and Xiaofei Guo from Intel Corporation for +the report. More information will be available on our site: + +https://wolfssl.com/wolfSSL/security/vulnerabilities.php + +See INSTALL file for build instructions. +More info can be found on-line at https://wolfssl.com/wolfSSL/Docs.html + + +# wolfSSL (Formerly CyaSSL) Release 3.9.8 (7/29/2016) + +##Release 3.9.8 of wolfSSL has bug fixes and new features including: + +- Add support for custom ECC curves. +- Add cipher suite ECDHE-ECDSA-AES128-CCM. +- Add compkey enable option. This option is for compressed ECC keys. +- Add in the option to use test.h without gettimeofday function using the macro + WOLFSSL_USER_CURRTIME. +- Add RSA blinding for private key operations. Enable option of harden which is + on by default. This negates timing attacks. +- Add ECC and TLS support for all SECP, Koblitz and Brainpool curves. +- Add helper functions for static memory option to allow getting optimum buffer + sizes. +- Update DTLS behavior on bad MAC. DTLS silently drops packets with bad MACs now. +- Update fp_isprime function from libtom enchancement/cleanup repository. +- Update sanity checks on inputs and return values for AES-CMAC. +- Update wolfSSL for use with MYSQL v5.6.30. +- Update LPCXpresso eclipse project to not include misc.c when not needed. +- Fix retransmit of last DTLS flight with timeout notification. The last flight + is no longer retransmitted on timeout. +- Fixes to some code in math sections for compressed ECC keys. This includes + edge cases for buffer size on allocation and adjustments for compressed curves + build. The code and full list can be found on github with pull request #456. +- Fix function argument mismatch for build with secure renegotiation. +- X.509 bug fixes for reading in malformed certificates, reported by researchers + at Columbia University +- Fix GCC version 6 warning about hard tabs in poly1305.c. This was a warning + produced by GCC 6 trying to determine the intent of code. +- Fixes for static memory option. Including avoid potential race conditions with + counters, decrement handshake counter correctly. +- Fix anonymous cipher with Diffie Hellman on the server side. Was an issue of a + possible buffer corruption. For information and code see pull request #481. + + +- One high level security fix that requires an update for use with static RSA + cipher suites was submitted. This fix was the addition of RSA blinding for + private RSA operations. We recommend servers who allow static RSA cipher + suites to also generate new private RSA keys. Static RSA cipher suites are + turned off by default. + +See INSTALL file for build instructions. +More info can be found on-line at //http://wolfssl.com/wolfSSL/Docs.html + +# wolfSSL (Formerly CyaSSL) Release 3.9.6 (6/14/2016) + +##Release 3.9.6 of wolfSSL has bug fixes and new features including: + +- Add staticmemory feature +- Add public wc_GetTime API with base64encode feature +- Add AES CMAC algorithm +- Add DTLS sessionexport feature +- Add python wolfCrypt wrapper +- Add ECC encrypt/decrypt benchmarks +- Add dynamic session tickets +- Add eccshamir option +- Add Whitewood netRandom support --with-wnr +- Add embOS port +- Add minimum key size checks for RSA and ECC +- Add STARTTLS support to examples +- Add uTasker port +- Add asynchronous crypto and wolf event support +- Add compile check for misc.c with inline +- Add RNG benchmark +- Add reduction to stack usage with hash-based RNG +- Update STM32F2_CRYPTO port with additional algorithms supported +- Update MDK5 projects +- Update AES-NI +- Fix for STM32 with STM32F2_HASH defined +- Fix for building with MinGw +- Fix ECC math bugs with ALT_ECC_SIZE and key sizes over 256 bit (1) +- Fix certificate buffers github issue #422 +- Fix decrypt max size with RSA OAEP +- Fix DTLS sanity check with DTLS timeout notification +- Fix free of WOLFSSL_METHOD on failure to create CTX +- Fix memory leak in failure case with wc_RsaFunction (2) + +- No high level security fixes that requires an update though we always +recommend updating to the latest +- (1) Code changes for ECC fix can be found at pull requests #411, #416, and #428 +- (2) Builds using RSA with using normal math and not RSA_LOW_MEM should update + +See INSTALL file for build instructions. +More info can be found on-line at //http://wolfssl.com/wolfSSL/Docs.html + +# wolfSSL (Formerly CyaSSL) Release 3.9.0 (03/18/2016) + +##Release 3.9.0 of wolfSSL has bug fixes and new features including: + +- Add new leantls configuration +- Add RSA OAEP padding at wolfCrypt level +- Add Arduino port and example client +- Add fixed point DH operation +- Add CUSTOM_RAND_GENRATE_SEED_OS and CUSTOM_RAND_GENERATE_BLOCK +- Add ECDHE-PSK cipher suites +- Add PSK ChaCha20-Poly1305 cipher suites +- Add option for fail on no peer cert except PSK suites +- Add port for Nordic nRF51 +- Add additional ECC NIST test vectors for 256, 384 and 521 +- Add more granular ECC, Ed25519/Curve25519 and AES configs +- Update to ChaCha20-Poly1305 +- Update support for Freescale KSDK 1.3.0 +- Update DER buffer handling code, refactoring and reducing memory +- Fix to AESNI 192 bit key expansion +- Fix to C# wrapper character encoding +- Fix sequence number issue with DTLS epoch 0 messages +- Fix RNGA with K64 build +- Fix ASN.1 X509 V3 certificate policy extension parsing +- Fix potential free of uninitialized RSA key in asn.c +- Fix potential underflow when using ECC build with FP_ECC +- Fixes for warnings in Visual Studio 2015 build + +- No high level security fixes that requires an update though we always +recommend updating to the latest +- FP_ECC is off by default, users with it enabled should update for the zero +sized hash fix + +See INSTALL file for build instructions. +More info can be found on-line at //http://wolfssl.com/yaSSL/Docs.html + +# wolfSSL (Formerly CyaSSL) Release 3.8.0 (12/30/2015) + +##Release 3.8.0 of wolfSSL has bug fixes and new features including: + +- Example client/server with VxWorks +- AESNI use with AES-GCM +- Stunnel compatibility enhancements +- Single shot hash and signature/verify API added +- Update cavium nitrox port +- LPCXpresso IDE support added +- C# wrapper to support wolfSSL use by a C# program +- (BETA version)OCSP stapling added +- Update OpenSSH compatibility +- Improve DTLS handshake when retransmitting finished message +- fix idea_mult() for 16 and 32bit systems +- fix LowResTimer on Microchip ports + +- No high level security fixes that requires an update though we always +recommend updating to the latest + +See INSTALL file for build instructions. +More info can be found on-line at //http://wolfssl.com/yaSSL/Docs.html + +# wolfSSL (Formerly CyaSSL) Release 3.7.0 (10/26/2015) + +##Release 3.7.0 of wolfSSL has bug fixes and new features including: + +- ALPN extension support added for HTTP2 connections with --enable-alpn +- Change of example/client/client max fragment flag -L -> -F +- Throughput benchmarking, added scripts/benchmark.test +- Sniffer API ssl_FreeDecodeBuffer added +- Addition of AES_GCM to Sniffer +- Sniffer change to handle unlimited decrypt buffer size +- New option for the sniffer where it will try to pick up decoding after a + sequence number acknowldgement fault. Also includes some additional stats. +- JNI API setter and getter function for jobject added +- User RSA crypto plugin abstraction. An example placed in wolfcrypt/user-crypto +- fix to asn configuration bug +- AES-GCM/CCM fixes. +- Port for Rowley added +- Rowley Crossworks bare metal examples added +- MDK5-ARM project update +- FreeRTOS support updates. +- VXWorks support updates. +- Added the IDEA cipher and support in wolfSSL. +- Update wolfSSL website CA. +- CFLAGS is usable when configuring source. + +- No high level security fixes that requires an update though we always +recommend updating to the latest + +See INSTALL file for build instructions. +More info can be found on-line at //http://wolfssl.com/yaSSL/Docs.html + +#wolfSSL (Formerly CyaSSL) Release 3.6.8 (09/17/2015) + +##Release 3.6.8 of wolfSSL fixes two high severity vulnerabilities. +##It also includes bug fixes and new features including: + +- Two High level security fixes, all users SHOULD update. + a) If using wolfSSL for DTLS on the server side of a publicly accessible + machine you MUST update. + b) If using wolfSSL for TLS on the server side with private RSA keys allowing + ephemeral key exchange without low memory optimziations you MUST update and + regenerate the private RSA keys. + + Please see https://www.wolfssl.com/wolfSSL/Blog/Blog.html for more details + +- No filesystem build fixes for various configurations +- Certificate generation now supports several extensions including KeyUsage, + SKID, AKID, and Ceritifcate Policies +- CRLs can be loaded from buffers as well as files now +- SHA-512 Ceritifcate Signing generation +- Fixes for sniffer reassembly processing + +See INSTALL file for build instructions. +More info can be found on-line at //http://wolfssl.com/yaSSL/Docs.html + +#wolfSSL (Formerly CyaSSL) Release 3.6.6 (08/20/2015) + +##Release 3.6.6 of wolfSSL has bug fixes and new features including: + +- OpenSSH compatibility with --enable-openssh +- stunnel compatibility with --enable-stunnel +- lighttpd compatibility with --enable-lighty +- SSLv3 is now disabled by default, can be enabled with --enable-sslv3 +- Ephemeral key cipher suites only are now supported by default + To enable static ECDH cipher suites define WOLFSSL_STATIC_DH + To enable static RSA cipher suites define WOLFSSL_STATIC_RSA + To enable static PSK cipher suites define WOLFSSL_STATIC_PSK +- Added QSH (quantum-safe handshake) extension with --enable-ntru +- SRP is now part of wolfCrypt, enable with --enabe-srp +- Certificate handshake messages can now be sent fragmented if the record + size is smaller than the total message size, no user action required. +- DTLS duplicate message fixes +- Visual Studio project files now support DLL and static builds for 32/64bit. +- Support for new Freesacle I/O +- FreeRTOS FIPS support + +- No high level security fixes that requires an update though we always + recommend updating to the latest + +See INSTALL file for build instructions. +More info can be found on-line at //http://wolfssl.com/yaSSL/Docs.html + + +#wolfSSL (Formerly CyaSSL) Release 3.6.0 (06/19/2015) + +##Release 3.6.0 of wolfSSL has bug fixes and new features including: + +- Max Strength build that only allows TLSv1.2, AEAD ciphers, and PFS (Perfect + Forward Secrecy). With --enable-maxstrength +- Server side session ticket support, the example server and echosever use the + example callback myTicketEncCb(), see wolfSSL_CTX_set_TicketEncCb() +- FIPS version submitted for iOS. +- TI Crypto Hardware Acceleration +- DTLS fragmentation fixes +- ECC key check validation with wc_ecc_check_key() +- 32bit code options to reduce memory for Curve25519 and Ed25519 +- wolfSSL JNI build switch with --enable-jni +- PicoTCP support improvements +- DH min ephemeral key size enforcement with wolfSSL_CTX_SetMinDhKey_Sz() +- KEEP_PEER_CERT and AltNames can now be used together +- ChaCha20 big endian fix +- SHA-512 signature algorithm support for key exchange and verify messages +- ECC make key crash fix on RNG failure, ECC users must update. +- Improvements to usage of time code. +- Improvements to VS solution files. +- GNU Binutils 2.24 ld has problems with some debug builds, to fix an ld error + add -fdebug-types-section to C_EXTRA_FLAGS + +- No high level security fixes that requires an update though we always + recommend updating to the latest (except note 14, ecc RNG failure) + +See INSTALL file for build instructions. +More info can be found on-line at //http://wolfssl.com/yaSSL/Docs.html + + +#wolfSSL (Formerly CyaSSL) Release 3.4.8 (04/06/2015) + +##Release 3.4.8 of wolfSSL has bug fixes and new features including: + +- FIPS version submitted for iOS. +- Max Strength build that only allows TLSv1.2, AEAD ciphers, and PFS. +- Improvements to usage of time code. +- Improvements to VS solution files. + +See INSTALL file for build instructions. +More info can be found on-line at //http://wolfssl.com/yaSSL/Docs.html + + +#wolfSSL (Formerly CyaSSL) Release 3.4.6 (03/30/2015) + +##Release 3.4.6 of wolfSSL has bug fixes and new features including: + +- Intel Assembly Speedups using instructions rdrand, rdseed, aesni, avx1/2, + rorx, mulx, adox, adcx . They can be enabled with --enable-intelasm. + These speedup the use of RNG, SHA2, and public key algorithms. +- Ed25519 support at the crypto level. Turn on with --enable-ed25519. Examples + in wolcrypt/test/test.c ed25519_test(). +- Post Handshake Memory reductions. wolfSSL can now hold less than 1,000 bytes + of memory per secure connection including cipher state. +- wolfSSL API and wolfCrypt API fixes, you can still include the cyassl and + ctaocrypt headers which will enable the compatibility APIs for the + foreseeable future +- INSTALL file to help direct users to build instructions for their environment +- For ECC users with the normal math library a fix that prevents a crash when + verify signature fails. Users of 3.4.0 with ECC and the normal math library + must update +- RC4 is now disabled by default in autoconf mode +- AES-GCM and ChaCha20/Poly1305 are now enabled by default to make AEAD ciphers + available without a switch +- External ChaCha-Poly AEAD API, thanks to Andrew Burks for the contribution +- DHE-PSK cipher suites can now be built without ASN or Cert support +- Fix some NO MD5 build issues with optional features +- Freescale CodeWarrior project updates +- ECC curves can be individually turned on/off at build time. +- Sniffer handles Cert Status message and other minor fixes +- SetMinVersion() at the wolfSSL Context level instead of just SSL session level + to allow minimum protocol version allowed at runtime +- RNG failure resource cleanup fix + +- No high level security fixes that requires an update though we always + recommend updating to the latest (except note 6 use case of ecc/normal math) + +See INSTALL file for build instructions. +More info can be found on-line at //http://wolfssl.com/yaSSL/Docs.html + + +#wolfSSL (Formerly CyaSSL) Release 3.4.0 (02/23/2015) + +## Release 3.4.0 wolfSSL has bug fixes and new features including: + +- wolfSSL API and wolfCrypt API, you can still include the cyassl and ctaocrypt + headers which will enable the compatibility APIs for the foreseeable future +- Example use of the wolfCrypt API can be found in wolfcrypt/test/test.c +- Example use of the wolfSSL API can be found in examples/client/client.c +- Curve25519 now supported at the wolfCrypt level, wolfSSL layer coming soon +- Improvements in the build configuration under AIX +- Microchip Pic32 MZ updates +- TIRTOS updates +- PowerPC updates +- Xcode project update +- Bidirectional shutdown examples in client/server with -w (wait for full + shutdown) option +- Cycle counts on benchmarks for x86_64, more coming soon +- ALT_ECC_SIZE for reducing ecc heap use with fastmath when also using large RSA + keys +- Various compile warnings +- Scan-build warning fixes +- Changed a memcpy to memmove in the sniffer (if using sniffer please update) +- No high level security fixes that requires an update though we always + recommend updating to the latest + + +# CyaSSL Release 3.3.0 (12/05/2014) + +- Countermeasuers for Handshake message duplicates, CHANGE CIPHER without + FINISHED, and fast forward attempts. Thanks to Karthikeyan Bhargavan from + the Prosecco team at INRIA Paris-Rocquencourt for the report. +- FIPS version submitted +- Removes SSLv2 Client Hello processing, can be enabled with OLD_HELLO_ALLOWED +- User can set mimimum downgrade version with CyaSSL_SetMinVersion() +- Small stack improvements at TLS/SSL layer +- TLS Master Secret generation and Key Expansion are now exposed +- Adds client side Secure Renegotiation, * not recommended * +- Client side session ticket support, not fully tested with Secure Renegotiation +- Allows up to 4096bit DHE at TLS Key Exchange layer +- Handles non standard SessionID sizes in Hello Messages +- PicoTCP Support +- Sniffer now supports SNI Virtual Hosts +- Sniffer now handles non HTTPS protocols using STARTTLS +- Sniffer can now parse records with multiple messages +- TI-RTOS updates +- Fix for ColdFire optimized fp_digit read only in explicit 32bit case +- ADH Cipher Suite ADH-AES128-SHA for EAP-FAST + +The CyaSSL manual is available at: +http://www.wolfssl.com/documentation/CyaSSL-Manual.pdf. For build instructions +and comments about the new features please check the manual. + + +# CyaSSL Release 3.2.0 (09/10/2014) + +#### Release 3.2.0 CyaSSL has bug fixes and new features including: + +- ChaCha20 and Poly1305 crypto and suites +- Small stack improvements for OCSP, CRL, TLS, DTLS +- NTRU Encrypt and Decrypt benchmarks +- Updated Visual Studio project files +- Updated Keil MDK5 project files +- Fix for DTLS sequence numbers with GCM/CCM +- Updated HashDRBG with more secure struct declaration +- TI-RTOS support and example Code Composer Studio project files +- Ability to get enabled cipher suites, CyaSSL_get_ciphers() +- AES-GCM/CCM/Direct support for Freescale mmCAU and CAU +- Sniffer improvement checking for decrypt key setup +- Support for raw ECC key import +- Ability to convert ecc_key to DER, EccKeyToDer() +- Security fix for RSA Padding check vulnerability reported by Intel Security + Advanced Threat Research team + +The CyaSSL manual is available at: +http://www.wolfssl.com/documentation/CyaSSL-Manual.pdf. For build instructions +and comments about the new features please check the manual. + + +# CyaSSL Release 3.1.0 (07/14/2014) + +#### Release 3.1.0 CyaSSL has bug fixes and new features including: + +- Fix for older versions of icc without 128-bit type +- Intel ASM syntax for AES-NI +- Updated NTRU support, keygen benchmark +- FIPS check for minimum required HMAC key length +- Small stack (--enable-smallstack) improvements for PKCS#7, ASN +- TLS extension support for DTLS +- Default I/O callbacks external to user +- Updated example client with bad clock test +- Ability to set optional ECC context info +- Ability to enable/disable DH separate from opensslextra +- Additional test key/cert buffers for CA and server +- Updated example certificates + +The CyaSSL manual is available at: +http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions +and comments about the new features please check the manual. + + +# CyaSSL Release 3.0.2 (05/30/2014) + +#### Release 3.0.2 CyaSSL has bug fixes and new features including: + +- Added the following cipher suites: + * TLS_PSK_WITH_AES_128_GCM_SHA256 + * TLS_PSK_WITH_AES_256_GCM_SHA384 + * TLS_PSK_WITH_AES_256_CBC_SHA384 + * TLS_PSK_WITH_NULL_SHA384 + * TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + * TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 + * TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + * TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + * TLS_DHE_PSK_WITH_NULL_SHA256 + * TLS_DHE_PSK_WITH_NULL_SHA384 + * TLS_DHE_PSK_WITH_AES_128_CCM + * TLS_DHE_PSK_WITH_AES_256_CCM +- Added AES-NI support for Microsoft Visual Studio builds. +- Changed small stack build to be disabled by default. +- Updated the Hash DRBG and provided a configure option to enable. + +The CyaSSL manual is available at: +http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions +and comments about the new features please check the manual. + + +# CyaSSL Release 3.0.0 (04/29/2014) + +#### Release 3.0.0 CyaSSL has bug fixes and new features including: + +- FIPS release candidate +- X.509 improvements that address items reported by Suman Jana with security + researchers at UT Austin and UC Davis +- Small stack size improvements, --enable-smallstack. Offloads large local + variables to the heap. (Note this is not complete.) +- Updated AES-CCM-8 cipher suites to use approved suite numbers. + +The CyaSSL manual is available at: +http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions +and comments about the new features please check the manual. + + +# CyaSSL Release 2.9.4 (04/09/2014) + +#### Release 2.9.4 CyaSSL has bug fixes and new features including: + +- Security fixes that address items reported by Ivan Fratric of the Google + Security Team +- X.509 Unknown critical extensions treated as errors, report by Suman Jana with + security researchers at UT Austin and UC Davis +- Sniffer fixes for corrupted packet length and Jumbo frames +- ARM thumb mode assembly fixes +- Xcode 5.1 support including new clang +- PIC32 MZ hardware support +- CyaSSL Object has enough room to read the Record Header now w/o allocs +- FIPS wrappers for AES, 3DES, SHA1, SHA256, SHA384, HMAC, and RSA. +- A sample I/O pool is demonstrated with --enable-iopool to overtake memory + handling and reduce memory fragmentation on I/O large sizes + +The CyaSSL manual is available at: +http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions +and comments about the new features please check the manual. + + +# CyaSSL Release 2.9.0 (02/07/2014) + +#### Release 2.9.0 CyaSSL has bug fixes and new features including: +- Freescale Kinetis RNGB support +- Freescale Kinetis mmCAU support +- TLS Hello extensions + - ECC + - Secure Renegotiation (null) + - Truncated HMAC +- SCEP support + - PKCS #7 Enveloped data and signed data + - PKCS #10 Certificate Signing Request generation +- DTLS sliding window +- OCSP Improvements + - API change to integrate into Certificate Manager + - IPv4/IPv6 agnostic + - example client/server support for OCSP + - OCSP nonces are optional +- GMAC hashing +- Windows build additions +- Windows CYGWIN build fixes +- Updated test certificates +- Microchip MPLAB Harmony support +- Update autoconf scripts +- Additional X.509 inspection functions +- ECC encrypt/decrypt primitives +- ECC Certificate generation + +The Freescale Kinetis K53 RNGB documentation can be found in Chapter 33 of the +K53 Sub-Family Reference Manual: +http://cache.freescale.com/files/32bit/doc/ref_manual/K53P144M100SF2RM.pdf + +Freescale Kinetis K60 mmCAU (AES, DES, 3DES, MD5, SHA, SHA256) documentation +can be found in the "ColdFire/ColdFire+ CAU and Kinetis mmCAU Software Library +User Guide": +http://cache.freescale.com/files/32bit/doc/user_guide/CAUAPIUG.pdf + + +# CyaSSL Release 2.8.0 (8/30/2013) + +#### Release 2.8.0 CyaSSL has bug fixes and new features including: +- AES-GCM and AES-CCM use AES-NI +- NetX default IO callback handlers +- IPv6 fixes for DTLS Hello Cookies +- The ability to unload Certs/Keys after the handshake, CyaSSL_UnloadCertsKeys() +- SEP certificate extensions +- Callback getters for easier resource freeing +- External CYASSL_MAX_ERROR_SZ for correct error buffer sizing +- MacEncrypt and DecryptVerify Callbacks for User Atomic Record Layer Processing +- Public Key Callbacks for ECC and RSA +- Client now sends blank cert upon request if doesn't have one with TLS <= 1.2 + + +The CyaSSL manual is available at: +http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions +and comments about the new features please check the manual. + + +# CyaSSL Release 2.7.0 (6/17/2013) + +#### Release 2.7.0 CyaSSL has bug fixes and new features including: +- SNI support for client and server +- KEIL MDK-ARM projects +- Wildcard check to domain name match, and Subject altnames are checked too +- Better error messages for certificate verification errors +- Ability to discard session during handshake verify +- More consistent error returns across all APIs +- Ability to unload CAs at the CTX or CertManager level +- Authority subject id support for Certificate matching +- Persistent session cache functionality +- Persistent CA cache functionality +- Client session table lookups to push serverID table to library level +- Camellia support to sniffer +- User controllable settings for DTLS timeout values +- Sniffer fixes for caching long lived sessions +- DTLS reliability enhancements for the handshake +- Better ThreadX support + +When compiling with Mingw, libtool may give the following warning due to +path conversion errors: + +``` +libtool: link: Could not determine host file name corresponding to ** +libtool: link: Continuing, but uninstalled executables may not work. +``` + +If so, examples and testsuite will have problems when run, showing an +error while loading shared libraries. To resolve, please run "make install". + +The CyaSSL manual is available at: +http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions +and comments about the new features please check the manual. + + +# CyaSSL Release 2.6.0 (04/15/2013) + +#### Release 2.6.0 CyaSSL has bug fixes and new features including: +- DTLS 1.2 support including AEAD ciphers +- SHA-3 finalist Blake2 support, it's fast and uses little resources +- SHA-384 cipher suites including ECC ones +- HMAC now supports SHA-512 +- Track memory use for example client/server with -t option +- Better IPv6 examples with --enable-ipv6, before if ipv6 examples/tests were + turned on, localhost only was used. Now link-local (with scope ids) and ipv6 + hosts can be used as well. +- Xcode v4.6 project for iOS v6.1 update +- settings.h is now checked in all *.c files for true one file setting detection +- Better alignment at SSL layer for hardware crypto alignment needs + * Note, SSL itself isn't friendly to alignment with 5 byte TLS headers and + 13 bytes DTLS headers, but every effort is now made to align with the + CYASSL_GENERAL_ALIGNMENT flag which sets desired alignment requirement +- NO_64BIT flag to turn off 64bit data type accumulators in public key code + * Note, some systems are faster with 32bit accumulators +- --enable-stacksize for example client/server stack use + * Note, modern desktop Operating Systems may add bytes to each stack frame +- Updated compression/decompression with direct crypto access +- All ./configure options are now lowercase only for consistency +- ./configure builds default to fastmath option + * Note, if on ia32 and building in shared mode this may produce a problem + with a missing register being available because of PIC, there are at least + 6 solutions to this: + 1) --disable-fastmath , don't use fastmath + 2) --disable-shared, don't build a shared library + 3) C_EXTRA_FLAGS=-DTFM_NO_ASM , turn off assembly use + 4) use clang, it just seems to work + 5) play around with no PIC options to force all registers being open, + e.g., --without-pic + 6) if static lib is still a problem try removing fPIE +- Many new ./configure switches for option enable/disable for example + * rsa + * dh + * dsa + * md5 + * sha + * arc4 + * null (allow NULL ciphers) + * oldtls (only use TLS 1.2) + * asn (no certs or public keys allowed) +- ./configure generates cyassl/options.h which allows a header the user can + include in their app to make sure the same options are set at the app and + CyaSSL level. +- autoconf no longer needs serial-tests which lowers version requirements of + automake to 1.11 and autoconf to 2.63 + +The CyaSSL manual is available at: +http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions +and comments about the new features please check the manual. + + + +# CyaSSL Release 2.5.0 (02/04/2013) + +#### Release 2.5.0 CyaSSL has bug fixes and new features including: +- Fix for TLS CBC padding timing attack identified by Nadhem Alfardan and + Kenny Paterson: http://www.isg.rhul.ac.uk/tls/ +- Microchip PIC32 (MIPS16, MIPS32) support +- Microchip MPLAB X example projects for PIC32 Ethernet Starter Kit +- Updated CTaoCrypt benchmark app for embedded systems +- 1024-bit test certs/keys and cert/key buffers +- AES-CCM-8 crypto and cipher suites +- Camellia crypto and cipher suites +- Bumped minimum autoconf version to 2.65, automake version to 1.12 +- Addition of OCSP callbacks +- STM32F2 support with hardware crypto and RNG +- Cavium NITROX support + +CTaoCrypt now has support for the Microchip PIC32 and has been tested with +the Microchip PIC32 Ethernet Starter Kit, the XC32 compiler and +MPLAB X IDE in both MIPS16 and MIPS32 instruction set modes. See the README +located under the /mplabx directory for more details. + +To add Cavium NITROX support do: + +./configure --with-cavium=/home/user/cavium/software + +pointing to your licensed cavium/software directory. Since Cavium doesn't +build a library we pull in the cavium_common.o file which gives a libtool +warning about the portability of this. Also, if you're using the github source +tree you'll need to remove the -Wredundant-decls warning from the generated +Makefile because the cavium headers don't conform to this warning. Currently +CyaSSL supports Cavium RNG, AES, 3DES, RC4, HMAC, and RSA directly at the crypto +layer. Support at the SSL level is partial and currently just does AES, 3DES, +and RC4. RSA and HMAC are slower until the Cavium calls can be utilized in non +blocking mode. The example client turns on cavium support as does the crypto +test and benchmark. Please see the HAVE_CAVIUM define. + +CyaSSL is able to use the STM32F2 hardware-based cryptography and random number +generator through the STM32F2 Standard Peripheral Library. For necessary +defines, see the CYASSL_STM32F2 define in settings.h. Documentation for the +STM32F2 Standard Peripheral Library can be found in the following document: +http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/USER_MANUAL/DM00023896.pdf + +The CyaSSL manual is available at: +http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions +and comments about the new features please check the manual. + + + +# CyaSSL Release 2.4.6 (12/20/2012) + +#### Release 2.4.6 CyaSSL has bug fixes and a few new features including: +- ECC into main version +- Lean PSK build (reduced code size, RAM usage, and stack usage) +- FreeBSD CRL monitor support +- CyaSSL_peek() +- CyaSSL_send() and CyaSSL_recv() for I/O flag setting +- CodeWarrior Support +- MQX Support +- Freescale Kinetis support including Hardware RNG +- autoconf builds use jobserver +- cyassl-config +- Sniffer memory reductions + +Thanks to Brian Aker for the improved autoconf system, make rpm, cyassl-config, +warning system, and general good ideas for improving CyaSSL! + +The Freescale Kinetis K70 RNGA documentation can be found in Chapter 37 of the +K70 Sub-Family Reference Manual: +http://cache.freescale.com/files/microcontrollers/doc/ref_manual/K70P256M150SF3RM.pdf + +The CyaSSL manual is available at: +http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions +and comments about the new features please check the manual. + + +# CyaSSL Release 2.4.0 (10/10/2012) + +#### Release 2.4.0 CyaSSL has bug fixes and a few new features including: +- DTLS reliability +- Reduced memory usage after handshake +- Updated build process + +The CyaSSL manual is available at: +http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions +and comments about the new features please check the manual. + + + +# CyaSSL Release 2.3.0 (8/10/2012) + +#### Release 2.3.0 CyaSSL has bug fixes and a few new features including: +- AES-GCM crypto and cipher suites +- make test cipher suite checks +- Subject AltName processing +- Command line support for client/server examples +- Sniffer SessionTicket support +- SHA-384 cipher suites +- Verify cipher suite validity when user overrides +- CRL dir monitoring +- DTLS Cookie support, reliability coming soon + +The CyaSSL manual is available at: +http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions +and comments about the new features please check the manual. + + + +# CyaSSL Release 2.2.0 (5/18/2012) + +#### Release 2.2.0 CyaSSL has bug fixes and a few new features including: +- Initial CRL support (--enable-crl) +- Initial OCSP support (--enable-ocsp) +- Add static ECDH suites +- SHA-384 support +- ECC client certificate support +- Add medium session cache size (1055 sessions) +- Updated unit tests +- Protection against mutex reinitialization + + +The CyaSSL manual is available at: +http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions +and comments about the new features please check the manual. + + + +# CyaSSL Release 2.0.8 (2/24/2012) + +#### Release 2.0.8 CyaSSL has bug fixes and a few new features including: +- A fix for malicious certificates pointed out by Remi Gacogne (thanks) + resulting in NULL pointer use. +- Respond to renegotiation attempt with no_renegoatation alert +- Add basic path support for load_verify_locations() +- Add set Temp EC-DHE key size +- Extra checks on rsa test when porting into + + +The CyaSSL manual is available at: +http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions +and comments about the new features please check the manual. + + + +# CyaSSL Release 2.0.6 (1/27/2012) + +#### Release 2.0.6 CyaSSL has bug fixes and a few new features including: +- Fixes for CA basis constraint check +- CTX reference counting +- Initial unit test additions +- Lean and Mean Windows fix +- ECC benchmarking +- SSMTP build support +- Ability to group handshake messages with set_group_messages(ctx/ssl) +- CA cache addition callback +- Export Base64_Encode for general use + +The CyaSSL manual is available at: +http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions +and comments about the new features please check the manual. + + + +# CyaSSL Release 2.0.2 (12/05/2011) + +#### Release 2.0.2 CyaSSL has bug fixes and a few new features including: +- CTaoCrypt Runtime library detection settings when directly using the crypto + library +- Default certificate generation now uses SHAwRSA and adds SHA256wRSA generation +- All test certificates now use 2048bit and SHA-1 for better modern browser + support +- Direct AES block access and AES-CTR (counter) mode +- Microchip pic32 support + +The CyaSSL manual is available at: +http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions +and comments about the new features please check the manual. + + + +# CyaSSL Release 2.0.0rc3 (9/28/2011) + +#### Release 2.0.0rc3 for CyaSSL has bug fixes and a few new features including: +- updated autoconf support +- better make install and uninstall (uses system directories) +- make test / make check +- CyaSSL headers now in +- CTaocrypt headers now in +- OpenSSL compatibility headers now in +- examples and tests all run from home directory so can use certs in ./certs + (see note 1) + +So previous applications that used the OpenSSL compatibility header + now need to include instead, no other +changes are required. + +Special Thanks to Brian Aker for his autoconf, install, and header patches. + +The CyaSSL manual is available at: +http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions +and comments about the new features please check the manual. + +# CyaSSL Release 2.0.0rc2 (6/6/2011) + +#### Release 2.0.0rc2 for CyaSSL has bug fixes and a few new features including: +- bug fixes (Alerts, DTLS with DHE) +- FreeRTOS support +- lwIP support +- Wshadow warnings removed +- asn public header +- CTaoCrypt public headers now all have ctc_ prefix (the manual is still being + updated to reflect this change) +- and more. + +This is the 2nd and perhaps final release candidate for version 2. +Please send any comments or questions to support@yassl.com. + +The CyaSSL manual is available at: +http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions +and comments about the new features please check the manual. + +# CyaSSL Release 2.0.0rc1 (5/2/2011) + +#### Release 2.0.0rc1 for CyaSSL has many new features including: +- bug fixes +- SHA-256 cipher suites +- Root Certificate Verification (instead of needing all certs in the chain) +- PKCS #8 private key encryption (supports PKCS #5 v1-v2 and PKCS #12) +- Serial number retrieval for x509 +- PBKDF2 and PKCS #12 PBKDF +- UID parsing for x509 +- SHA-256 certificate signatures +- Client and server can send chains (SSL_CTX_use_certificate_chain_file) +- CA loading can now parse multiple certificates per file +- Dynamic memory runtime hooks +- Runtime hooks for logging +- EDH on server side +- More informative error codes +- More informative logging messages +- Version downgrade more robust (use SSL_v23*) +- Shared build only by default through ./configure +- Compiler visibility is now used, internal functions not polluting namespace +- Single Makefile, no recursion, for faster and simpler building +- Turn on all warnings possible build option, warning fixes +- and more. + +Because of all the new features and the multiple OS, compiler, feature-set +options that CyaSSL allows, there may be some configuration fixes needed. +Please send any comments or questions to support@yassl.com. + +The CyaSSL manual is available at: +http://www.yassl.com/documentation/CyaSSL-Manual.pdf. For build instructions +and comments about the new features please check the manual. + +# CyaSSL Release 1.9.0 (3/2/2011) + +Release 1.9.0 for CyaSSL adds bug fixes, improved TLSv1.2 through testing and +better hash/sig algo ids, --enable-webServer for the yaSSL embedded web server, +improper AES key setup detection, user cert verify callback improvements, and +more. + +The CyaSSL manual offering is included in the doc/ directory. For build +instructions and comments about the new features please check the manual. + +Please send any comments or questions to support@yassl.com. + +# CyaSSL Release 1.8.0 (12/23/2010) + +Release 1.8.0 for CyaSSL adds bug fixes, x509 v3 CA signed certificate +generation, a C standard library abstraction layer, lower memory use, increased +portability through the os_settings.h file, and the ability to use NTRU cipher +suites when used in conjunction with an NTRU license and library. + +The initial CyaSSL manual offering is included in the doc/ directory. For +build instructions and comments about the new features please check the manual. + +Please send any comments or questions to support@yassl.com. + +Happy Holidays. + + +# CyaSSL Release 1.6.5 (9/9/2010) + +Release 1.6.5 for CyaSSL adds bug fixes and x509 v3 self signed certificate +generation. + +For general build instructions see doc/Building_CyaSSL.pdf. + +To enable certificate generation support add this option to ./configure +./configure --enable-certgen + +An example is included in ctaocrypt/test/test.c and documentation is provided +in doc/CyaSSL_Extensions_Reference.pdf item 11. + +# CyaSSL Release 1.6.0 (8/27/2010) + +Release 1.6.0 for CyaSSL adds bug fixes, RIPEMD-160, SHA-512, and RSA key +generation. + +For general build instructions see doc/Building_CyaSSL.pdf. + +To add RIPEMD-160 support add this option to ./configure +./configure --enable-ripemd + +To add SHA-512 support add this option to ./configure +./configure --enable-sha512 + +To add RSA key generation support add this option to ./configure +./configure --enable-keygen + +Please see ctaocrypt/test/test.c for examples and usage. + +For Windows, RIPEMD-160 and SHA-512 are enabled by default but key generation is +off by default. To turn key generation on add the define CYASSL_KEY_GEN to +CyaSSL. + + +# CyaSSL Release 1.5.6 (7/28/2010) + +Release 1.5.6 for CyaSSL adds bug fixes, compatibility for our JSSE provider, +and a fix for GCC builds on some systems. + +For general build instructions see doc/Building_CyaSSL.pdf. + +To add AES-NI support add this option to ./configure +./configure --enable-aesni + +You'll need GCC 4.4.3 or later to make use of the assembly. + +# CyaSSL Release 1.5.4 (7/7/2010) + +Release 1.5.4 for CyaSSL adds bug fixes, support for AES-NI, SHA1 speed +improvements from loop unrolling, and support for the Mongoose Web Server. + +For general build instructions see doc/Building_CyaSSL.pdf. + +To add AES-NI support add this option to ./configure +./configure --enable-aesni + +You'll need GCC 4.4.3 or later to make use of the assembly. + +# CyaSSL Release 1.5.0 (5/11/2010) + +Release 1.5.0 for CyaSSL adds bug fixes, GoAhead WebServer support, sniffer +support, and initial swig interface support. + +For general build instructions see doc/Building_CyaSSL.pdf. + +To add support for GoAhead WebServer either --enable-opensslExtra or if you +don't want all the features of opensslExtra you can just define GOAHEAD_WS +instead. GOAHEAD_WS can be added to ./configure with CFLAGS=-DGOAHEAD_WS or +you can define it yourself. + +To look at the sniffer support please see the sniffertest app in +sslSniffer/sslSnifferTest. Build with --enable-sniffer on *nix or use the +vcproj files on windows. You'll need to have pcap installed on *nix and +WinPcap on windows. + +A swig interface file is now located in the swig directory for using Python, +Java, Perl, and others with CyaSSL. This is initial support and experimental, +please send questions or comments to support@yassl.com. + +When doing load testing with CyaSSL, on the echoserver example say, the client +machine may run out of tcp ephemeral ports, they will end up in the TIME_WAIT +queue, and can't be reused by default. There are generally two ways to fix +this. + +1. Reduce the length sockets remain on the TIME_WAIT queue OR +2. Allow items on the TIME_WAIT queue to be reused. + + +To reduce the TIME_WAIT length in OS X to 3 seconds (3000 milliseconds) + +`sudo sysctl -w net.inet.tcp.msl=3000` + +In Linux + +`sudo sysctl -w net.ipv4.tcp_tw_reuse=1` + +allows reuse of sockets in TIME_WAIT + +`sudo sysctl -w net.ipv4.tcp_tw_recycle=1` + +works but seems to remove sockets from TIME_WAIT entirely? + +`sudo sysctl -w net.ipv4.tcp_fin_timeout=1` + +doen't control TIME_WAIT, it controls FIN_WAIT(2) contrary to some posts + + +# CyaSSL Release 1.4.0 (2/18/2010) + +Release 1.3.0 for CyaSSL adds bug fixes, better multi TLS/SSL version support +through SSLv23_server_method(), and improved documentation in the doc/ folder. + +For general build instructions doc/Building_CyaSSL.pdf. + +# CyaSSL Release 1.3.0 (1/21/2010) + +Release 1.3.0 for CyaSSL adds bug fixes, a potential security problem fix, +better porting support, removal of assert()s, and a complete THREADX port. + +For general build instructions see rc1 below. + +# CyaSSL Release 1.2.0 (11/2/2009) + +Release 1.2.0 for CyaSSL adds bug fixes and session negotiation if first use is +read or write. + +For general build instructions see rc1 below. + +# CyaSSL Release 1.1.0 (9/2/2009) + +Release 1.1.0 for CyaSSL adds bug fixes, a check against malicious session +cache use, support for lighttpd, and TLS 1.2. + +To get TLS 1.2 support please use the client and server functions: + +```c +SSL_METHOD *TLSv1_2_server_method(void); +SSL_METHOD *TLSv1_2_client_method(void); +``` + +CyaSSL was tested against lighttpd 1.4.23. To build CyaSSL for use with +lighttpd use the following commands from the CyaSSL install dir : + +``` +./configure --disable-shared --enable-opensslExtra --enable-fastmath --without-zlib + +make +make openssl-links +``` + +Then to build lighttpd with CyaSSL use the following commands from the +lighttpd install dir: + +``` +./configure --with-openssl --with-openssl-includes=/include --with-openssl-libs=/lib LDFLAGS=-lm + +make +``` + +On some systems you may get a linker error about a duplicate symbol for +MD5_Init or other MD5 calls. This seems to be caused by the lighttpd src file +md5.c, which defines MD5_Init(), and is included in liblightcomp_la-md5.o. +When liblightcomp is linked with the SSL_LIBs the linker may complain about +the duplicate symbol. This can be fixed by editing the lighttpd src file md5.c +and adding this line to the beginning of the file: + +\#if 0 + +and this line to the end of the file + +\#endif + +Then from the lighttpd src dir do a: + +``` +make clean +make +``` + +If you get link errors about undefined symbols more than likely the actual +OpenSSL libraries are found by the linker before the CyaSSL openssl-links that +point to the CyaSSL library, causing the linker confusion. This can be fixed +by editing the Makefile in the lighttpd src directory and changing the line: + +`SSL_LIB = -lssl -lcrypto` + +to + +`SSL_LIB = -lcyassl` + +Then from the lighttpd src dir do a: + +``` +make clean +make +``` + +This should remove any confusion the linker may be having with missing symbols. + +For any questions or concerns please contact support@yassl.com . + +For general build instructions see rc1 below. + +# CyaSSL Release 1.0.6 (8/03/2009) + +Release 1.0.6 for CyaSSL adds bug fixes, an improved session cache, and faster +math with a huge code option. + +The session cache now defaults to a client mode, also good for embedded servers. +For servers not under heavy load (less than 200 new sessions per minute), define +BIG_SESSION_CACHE. If the server will be under heavy load, define +HUGE_SESSION_CACHE. + +There is now a fasthugemath option for configure. This enables fastmath plus +even faster math by greatly increasing the code size of the math library. Use +the benchmark utility to compare public key operations. + + +For general build instructions see rc1 below. + +# CyaSSL Release 1.0.3 (5/10/2009) + +Release 1.0.3 for CyaSSL adds bug fixes and add increased support for OpenSSL +compatibility when building other applications. + +Release 1.0.3 includes an alpha release of DTLS for both client and servers. +This is only for testing purposes at this time. Rebroadcast and reordering +aren't fully implemented at this time but will be for the next release. + +For general build instructions see rc1 below. + +# CyaSSL Release 1.0.2 (4/3/2009) + +Release 1.0.2 for CyaSSL adds bug fixes for a couple I/O issues. Some systems +will send a SIGPIPE on socket recv() at any time and this should be handled by +the application by turning off SIGPIPE through setsockopt() or returning from +the handler. + +Release 1.0.2 includes an alpha release of DTLS for both client and servers. +This is only for testing purposes at this time. Rebroadcast and reordering +aren't fully implemented at this time but will be for the next release. + +For general build instructions see rc1 below. + +## CyaSSL Release Candidate 3 rc3-1.0.0 (2/25/2009) + + +Release Candidate 3 for CyaSSL 1.0.0 adds bug fixes and adds a project file for +iPhone development with Xcode. cyassl-iphone.xcodeproj is located in the root +directory. This release also includes a fix for supporting other +implementations that bundle multiple messages at the record layer, this was +lost when cyassl i/o was re-implemented but is now fixed. + +For general build instructions see rc1 below. + +## CyaSSL Release Candidate 2 rc2-1.0.0 (1/21/2009) + + +Release Candidate 2 for CyaSSL 1.0.0 adds bug fixes and adds two new stream +ciphers along with their respective cipher suites. CyaSSL adds support for +HC-128 and RABBIT stream ciphers. The new suites are: + +``` +TLS_RSA_WITH_HC_128_SHA +TLS_RSA_WITH_RABBIT_SHA +``` + +And the corresponding cipher names are + +``` +HC128-SHA +RABBIT-SHA +``` + +CyaSSL also adds support for building with devkitPro for PPC by changing the +library proper to use libogc. The examples haven't been changed yet but if +there's interest they can be. Here's an example ./configure to build CyaSSL +for devkitPro: + +``` +./configure --disable-shared CC=/pathTo/devkitpro/devkitPPC/bin/powerpc-gekko-gcc --host=ppc --without-zlib --enable-singleThreaded RANLIB=/pathTo/devkitpro/devkitPPC/bin/powerpc-gekko-ranlib CFLAGS="-DDEVKITPRO -DGEKKO" +``` + +For linking purposes you'll need + +`LDFLAGS="-g -mrvl -mcpu=750 -meabi -mhard-float -Wl,-Map,$(notdir $@).map"` + +For general build instructions see rc1 below. + + +## CyaSSL Release Candidate 1 rc1-1.0.0 (12/17/2008) + + +Release Candidate 1 for CyaSSL 1.0.0 contains major internal changes. Several +areas have optimization improvements, less dynamic memory use, and the I/O +strategy has been refactored to allow alternate I/O handling or Library use. +Many thanks to Thierry Fournier for providing these ideas and most of the work. + +Because of these changes, this release is only a candidate since some problems +are probably inevitable on some platform with some I/O use. Please report any +problems and we'll try to resolve them as soon as possible. You can contact us +at support@yassl.com or todd@yassl.com. + +Using TomsFastMath by passing --enable-fastmath to ./configure now uses assembly +on some platforms. This is new so please report any problems as every compiler, +mode, OS combination hasn't been tested. On ia32 all of the registers need to +be available so be sure to pass these options to CFLAGS: + +`CFLAGS="-O3 -fomit-frame-pointer"` + +OS X will also need -mdynamic-no-pic added to CFLAGS + +Also if you're building in shared mode for ia32 you'll need to pass options to +LDFLAGS as well on OS X: + +`LDFLAGS=-Wl,-read_only_relocs,warning` + +This gives warnings for some symbols but seems to work. + + +#### To build on Linux, Solaris, *BSD, Mac OS X, or Cygwin: + + ./configure + make + + from the ./testsuite/ directory run ./testsuite + +#### To make a debug build: + + ./configure --enable-debug --disable-shared + make + + + +#### To build on Win32 + +Choose (Re)Build All from the project workspace + +Run the testsuite program + + + + + +# CyaSSL version 0.9.9 (7/25/2008) + +This release of CyaSSL adds bug fixes, Pre-Shared Keys, over-rideable memory +handling, and optionally TomsFastMath. Thanks to Moisés Guimarães for the +work on TomsFastMath. + +To optionally use TomsFastMath pass --enable-fastmath to ./configure +Or define USE_FAST_MATH in each project from CyaSSL for MSVC. + +Please use the benchmark routine before and after to see the performance +difference, on some platforms the gains will be little but RSA encryption +always seems to be faster. On x86-64 machines with GCC the normal math library +may outperform the fast one when using CFLAGS=-m64 because TomsFastMath can't +yet use -m64 because of GCCs inability to do 128bit division. + + *** UPDATE GCC 4.2.1 can now do 128bit division *** + +See notes below (0.2.0) for complete build instructions. + + +# CyaSSL version 0.9.8 (5/7/2008) + +This release of CyaSSL adds bug fixes, client side Diffie-Hellman, and better +socket handling. + +See notes below (0.2.0) for complete build instructions. + + +# CyaSSL version 0.9.6 (1/31/2008) + +This release of CyaSSL adds bug fixes, increased session management, and a fix +for gnutls. + +See notes below (0.2.0) for complete build instructions. + + +# CyaSSL version 0.9.0 (10/15/2007) + +This release of CyaSSL adds bug fixes, MSVC 2005 support, GCC 4.2 support, +IPV6 support and test, and new test certificates. + +See notes below (0.2.0) for complete build instructions. + + +# CyaSSL version 0.8.0 (1/10/2007) + +This release of CyaSSL adds increased socket support, for non-blocking writes, +connects, and interrupted system calls. + +See notes below (0.2.0) for complete build instructions. + + +# CyaSSL version 0.6.3 (10/30/2006) + +This release of CyaSSL adds debug logging to stderr to aid in the debugging of +CyaSSL on systems that may not provide the best support. + +If CyaSSL is built with debugging support then you need to call +CyaSSL_Debugging_ON() to turn logging on. + +On Unix use ./configure --enable-debug + +On Windows define DEBUG_CYASSL when building CyaSSL + + +To turn logging back off call CyaSSL_Debugging_OFF() + +See notes below (0.2.0) for complete build instructions. + + +# CyaSSL version 0.6.2 (10/29/2006) + +This release of CyaSSL adds TLS 1.1. + +Note that CyaSSL has certificate verification on by default, unlike OpenSSL. +To emulate OpenSSL behavior, you must call SSL_CTX_set_verify() with +SSL_VERIFY_NONE. In order to have full security you should never do this, +provide CyaSSL with the proper certificates to eliminate impostors and call +CyaSSL_check_domain_name() to prevent man in the middle attacks. + +See notes below (0.2.0) for build instructions. + +# CyaSSL version 0.6.0 (10/25/2006) + +This release of CyaSSL adds more SSL functions, better autoconf, nonblocking +I/O for accept, connect, and read. There is now an --enable-small configure +option that turns off TLS, AES, DES3, HMAC, and ERROR_STRINGS, see configure.in +for the defines. Note that TLS requires HMAC and AES requires TLS. + +See notes below (0.2.0) for build instructions. + + +# CyaSSL version 0.5.5 (09/27/2006) + +This mini release of CyaSSL adds better input processing through buffered input +and big message support. Added SSL_pending() and some sanity checks on user +settings. + +See notes below (0.2.0) for build instructions. + + +# CyaSSL version 0.5.0 (03/27/2006) + +This release of CyaSSL adds AES support and minor bug fixes. + +See notes below (0.2.0) for build instructions. + + +# CyaSSL version 0.4.0 (03/15/2006) + +This release of CyaSSL adds TLSv1 client/server support and libtool. + +See notes below for build instructions. + + +# CyaSSL version 0.3.0 (02/26/2006) + +This release of CyaSSL adds SSLv3 server support and session resumption. + +See notes below for build instructions. + + +# CyaSSL version 0.2.0 (02/19/2006) + + +This is the first release of CyaSSL and its crypt brother, CTaoCrypt. CyaSSL +is written in ANSI C with the idea of a small code size, footprint, and memory +usage in mind. CTaoCrypt can be as small as 32K, and the current client +version of CyaSSL can be as small as 12K. + + +The first release of CTaoCrypt supports MD5, SHA-1, 3DES, ARC4, Big Integer +Support, RSA, ASN parsing, and basic x509 (en/de)coding. + +The first release of CyaSSL supports normal client RSA mode SSLv3 connections +with support for SHA-1 and MD5 digests. Ciphers include 3DES and RC4. + + +#### To build on Linux, Solaris, *BSD, Mac OS X, or Cygwin: + + ./configure + make + + from the ./testsuite/ directory run ./testsuite + +#### to make a debug build: + + ./configure --enable-debug --disable-shared + make + + + +#### To build on Win32 + +Choose (Re)Build All from the project workspace + +Run the testsuite program + + + +*** The next release of CyaSSL will support a server and more OpenSSL +compatibility functions. + + +Please send questions or comments to todd@wolfssl.com diff --git a/beken_os/beken378/func/wolfssl/README b/beken_os/beken378/func/wolfssl/README new file mode 100755 index 0000000..1cbce66 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/README @@ -0,0 +1,197 @@ +*** Description *** + +The wolfSSL embedded SSL library (formerly CyaSSL) is a lightweight SSL/TLS +library written in ANSI C and targeted for embedded, RTOS, and +resource-constrained environments - primarily because of its small size, speed, +and feature set. It is commonly used in standard operating environments as well +because of its royalty-free pricing and excellent cross platform support. +wolfSSL supports industry standards up to the current TLS 1.3 and DTLS 1.2 +levels, is up to 20 times smaller than OpenSSL, and offers progressive ciphers +such as ChaCha20, Curve25519, NTRU, and Blake2b. User benchmarking and feedback +reports dramatically better performance when using wolfSSL over OpenSSL. + +wolfSSL is powered by the wolfCrypt library. A version of the wolfCrypt +cryptography library has been FIPS 140-2 validated (Certificate #2425). For +additional information, visit the wolfCrypt FIPS FAQ +(https://www.wolfssl.com/license/fips/) or contact fips@wolfssl.com + +*** Why choose wolfSSL? *** + +There are many reasons to choose wolfSSL as your embedded SSL solution. Some of +the top reasons include size (typical footprint sizes range from 20-100 kB), +support for the newest standards (SSL 3.0, TLS 1.0, TLS 1.1, TLS 1.2, TLS 1.3, +DTLS 1.0, and DTLS 1.2), current and progressive cipher support (including +stream ciphers), multi-platform, royalty free, and an OpenSSL compatibility API +to ease porting into existing applications which have previously used the +OpenSSL package. For a complete feature list, see chapter 4 of the wolfSSL +manual. (https://www.wolfssl.com/docs/wolfssl-manual/ch4/) + +*** Notes, Please read *** + +Note 1) +wolfSSL as of 3.6.6 no longer enables SSLv3 by default. wolfSSL also no longer +supports static key cipher suites with PSK, RSA, or ECDH. This means if you +plan to use TLS cipher suites you must enable DH (DH is on by default), or +enable ECC (ECC is on by default), or you must enable static key cipher suites +with + + WOLFSSL_STATIC_DH + WOLFSSL_STATIC_RSA + or + WOLFSSL_STATIC_PSK + +though static key cipher suites are deprecated and will be removed from future +versions of TLS. They also lower your security by removing PFS. Since current +NTRU suites available do not use ephemeral keys, WOLFSSL_STATIC_RSA needs to be +used in order to build with NTRU suites. + +When compiling ssl.c, wolfSSL will now issue a compiler error if no cipher +suites are available. You can remove this error by defining +WOLFSSL_ALLOW_NO_SUITES in the event that you desire that, i.e., you're not +using TLS cipher suites. + +Note 2) +wolfSSL takes a different approach to certificate verification than OpenSSL +does. The default policy for the client is to verify the server, this means +that if you don't load CAs to verify the server you'll get a connect error, +no signer error to confirm failure (-188). + +If you want to mimic OpenSSL behavior of having SSL_connect succeed even if +verifying the server fails and reducing security you can do this by calling: + + wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0); + +before calling wolfSSL_new();. Though it's not recommended. + +Note 3) +The enum values SHA, SHA256, SHA384, SHA512 are no longer available when +wolfSSL is built with --enable-opensslextra (OPENSSL_EXTRA) or with the macro +NO_OLD_SHA_NAMES. These names get mapped to the OpenSSL API for a single call +hash function. Instead the name WC_SHA, WC_SHA256, WC_SHA384 and WC_SHA512 +should be used for the enum name. + +*** end Notes *** + + +********* wolfSSL Release 4.1.0 (07/22/2019) + +Release 4.1.0 of wolfSSL embedded TLS has bug fixes and new features including: + +* A fix for the check on return value when verifying PKCS7 bundle signatures, all users with applications using the function wc_PKCS7_VerifySignedData should update +* Adding the function wc_PKCS7_GetSignerSID for PKCS7 firmware bundles as a getter function for the signers SID +* PKCS7 callback functions for unwrapping of CEK and for decryption +* Adding the error value PKCS7_SIGNEEDS_CHECK when no certificates are available in a PKCS7 bundle to verify the signature +* TLS 1.3 fixes including if major version is TLS Draft then it is now ignored and if version negotiation occurs but none were matched then an alert is now sent +* Addition of the WOLFSSL_PSK_ONE_ID macro for indicating that only one identity in TLS 1.3 PSK is available and will be cached +* Adding sanity checks on length of PSK identity from a TLS 1.3 pre-shared key extension +* Additional sanity checks and alert messages added for TLS 1.3 +* Adding XTIME_MS macro to simplify the tls13.c time requirement +* Improvements and refactoring of code related to parsing and creating TLS 1.3 client hello packets +* TLS 1.3 version renegotiation now happens before interpreting ClientHello message +* Chacha20 algorithm optimizations on the ARM architecture for performance increase +* Poly1305 algorithm performance enhancements for the ARM architecture using the SIMD NEON extension +* Curve25519 and Ed25519 optimized for ARM architecture for performance increase +* SHA-512/384 optimizations for performance with ARM architecture using the SIMD NEON extension +* Sniffer updates including adding support for the null cipher and static ECDH key exchange and new SSLWatchCb callback +* Cipher suite TLS_RSA_WITH_NULL_MD5 for use with the sniffer (off by default) +* Sniffer statistic print outs with the macro WOLFSSL_SNIFFER_STATS defined +* A fix for wolfSSL_DH_generate_key when WOLFSSL_SMALL_STACK is defined +* wolfSSL_BN_Init implementation for opensslextra builds +* Updates to the function wolfSSL_i2d_RSAPrivateKey and additional automated tests +* Fixes for EVP_CipherFinal edge cases to match behavior desired +* Check for appropriate private vs public flag with ECC key decode in wolfSSL_EC_KEY_LoadDer_ex, thanks to Eric Miller for the report +* Implementation of the function wolfSSL_PEM_write_DHparams +* wolfSSL_RAND_seed is called in wolfSSL_Init now when opensslextra is enabled +* CryptoCell-310 support on nRF52840 added +* Fixes for atmel_ecc_create_pms to free the used slot. +* Fixes for building ATECC with ATCAPRINTF or WOLFSSL_PUBLIC_MP +* Cortex-M code changes to support IAR compiler +* Improvements to STM32 AES-GCM performance +* Fixes for 16-bit systems including PK callbacks, ATECC and LowResTimer function ptoto. +* IAR-EWARM compiler warning fix +* Clean up of user_settings for CS+ port +* Updating Renesas example projects to the latest version +* Micrium updates adjusting STATIC macro name and added inline flag +* Fixes for building with WOLFSSL_CUSTOM_CURVES on Windows +* Updates and refactor to the default build settings with Arduino +* Fixes for visibility tags with Cygwin build +* STSAFE Improvements to support wolfSSL Crypto Callbacks +* Improvements to NetBSD builds and mutex use in test case +* Updating TI hardware offload with WOLFSSL_TI_CRYPT build +* Maintaining Xilinx FreeRTOS port by adjusting time.h include in wolfSSL +* SiFive HiFive E31 RISC‐V core family port +* Port for Telit IoT AppZone SDK +* OCSP Response signed by issuer with identical SKID fix +* Fix for sending revoked certificate with OCSP +* Honor the status sent over connection with peers and do not perform an internal OCSP lookup +* Adding the build flag `--enable-ecccustcurves=all` to enable all curve types +* Support add for Ed25519ctx and Ed25519ph sign/verify algorithms as per RFC 8032 +* Addition of the macro WOLFSSL_NO_SIGALG to disable signature algorithms extension +* wc_AesCtrEncrypt in place addition, where input and output buffer can be the same buffer +* Single shot API added for SHA3; wc_Sha3_224Hash, wc_Sha3_256Hash, wc_Sha3_384Hash, wc_Sha3_512Hash +* Function additions for JSSE support some of which are wolfSSL_get_ciphers_iana and wolfSSL_X509_verify along with expansion of the --enable-jni option +* Macro guards for more modular SHA3 build (i.e. support for 384 size only) +* Benchmarking -thread argument support for asynchronous crypto +* Blake2s support (--enable-blake2s), which provides 32-bit Blake2 support +* Macro SHA256_MANY_REGISTERS addition to potentially speed up SHA256 depending on architecture +* Additional TLS alert messages sent with the macro WOLFSSL_EXTRA_ALERTS defined +* Feature to fail resumption of a session if the session’s cipher suite is not in the client’s list, this can be overridden by defining the macro NO_RESUME_SUITE_CHECK +* Fallback SCSV (Signaling Cipher Suite Value) support on Server only (--enable-fallback-scsv) +* DTLS export state only (wolfSSL_dtls_export_state_only) which is a subset of the information exported from previous DTLS export function +* Function wc_DhCheckPubValue added to perform simple validity checks on DH keys +* Support for RSA SHA-224 signatures with TLS added +* Additional option “-print” to the benchmark app for printing out a brief summary after benchmarks are complete +* Adding (--disable-pkcs12) option and improvements for disabled sections in pwdbased.c, asn.c, rsa.c, pkcs12.c and wc_encrypt +* Added DES3 support to the wolfSSL crypto callbacks +* Compile time fixes for build case with SP math and RSA only +* Fixes for Coverity static analysis report including explicit initialization of reported stack variables some additional Coverity fixes added thanks to Martin +* Fixes for scan build warnings (i.e possible null dereference in ecc.c) +* Resetting verify send value with a call to wolfSSL_clear function +* Fix for extern with sp_ModExp_2048 when building with --cpp option +* Fix for typo issue with --enable-sp=cortexm +* Adding #pragma warning disable 4127 for tfm.c when building with Visual Studio +* Improvements to the maximum ECC signature calculations +* Improvements to TLS write handling in error cases which helps user application not go through with a wolfSSL_write attempt after a wolfSSL_read failure +* Fix for read directory functions with Windows (wc_ReadDirFirst and wc_ReadDirNext) +* Sanity check on index before accessing domain component buffer in call to wolfSSL_X509_NAME_get_entry +* Sending fatal alert from client side on version error +* Fix for static RSA cipher suite with PK callback and no loaded private key +* Fix for potential memory leak in error case with the function wc_DsaKeyToDer, thanks to Chris H. for the report +* Adjusting STRING_USER macro to remove includes of standard lib or +* Bug fix for checking wrong allocation assignment in the function wc_PBKDF2 and handling potential leak on allocation failure. This case is only hit when the specific call to malloc fails in the function wc_PBKDF2. Thanks to Robert Altnoeder (Linbit) for the report +* Improved length checks when parsing ASN.1 certificates +* extern "C" additions to header files that were missing them +* Improved checking of return values with TLS extension functions and error codes +* Removing redundant calls to the generate function when instantiating and reseeding DRBG +* Refactoring and improvements to autoconf code with consolidating AM_CONDITIONAL statements +* Improvements for handling error return codes when reading input from transport layer +* Improvements to efficiency of SNI extension parsing and error checking with ALPN parsing +* Macro WOLFSSL_DEBUG_TLS addition for printing out extension data being parsed during a TLS connection +* Adjustment of prime testing with --disable-fastmath builds + + +This release of wolfSSL includes a fix for 2 security vulnerabilities. + +There is a fix for a potential buffer overflow case with the TLSv1.3 PSK extension parsing. This affects users that are enabling TLSv1.3 (--enable-tls13). Thanks to Robert Hoerr for the report. The CVE associated with the report is CVE-2019-11873. + +There is a fix for the potential leak of nonce sizes when performing ECDSA signing operations. The leak is considered to be difficult to exploit but it could potentially be used maliciously to perform a lattice based timing attack against previous wolfSSL versions. ECC operations with --enable-sp and --enable-sp-asm are not affected, users with private ECC keys in other builds that are performing ECDSA signing operations should update versions of wolfSSL along with private ECC keys. Thanks to Ján Jančár from Masaryk University for the report. + + +*** Resources *** + + +[wolfSSL Website](https://www.wolfssl.com/) + +[wolfSSL Wiki](https://github.com/wolfSSL/wolfssl/wiki) + +[FIPS FAQ](https://www.wolfssl.com/wolfSSL/fips.html) + +[wolfSSL Manual](https://wolfssl.com/wolfSSL/Docs-wolfssl-manual-toc.html) + +[wolfSSL API Reference] +(https://wolfssl.com/wolfSSL/Docs-wolfssl-manual-17-wolfssl-api-reference.html) + +[wolfCrypt API Reference] +(https://wolfssl.com/wolfSSL/Docs-wolfssl-manual-18-wolfcrypt-api-reference.html) + +[TLS 1.3](https://www.wolfssl.com/docs/tls13/) diff --git a/beken_os/beken378/func/wolfssl/README.md b/beken_os/beken378/func/wolfssl/README.md new file mode 100755 index 0000000..1cbce66 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/README.md @@ -0,0 +1,197 @@ +*** Description *** + +The wolfSSL embedded SSL library (formerly CyaSSL) is a lightweight SSL/TLS +library written in ANSI C and targeted for embedded, RTOS, and +resource-constrained environments - primarily because of its small size, speed, +and feature set. It is commonly used in standard operating environments as well +because of its royalty-free pricing and excellent cross platform support. +wolfSSL supports industry standards up to the current TLS 1.3 and DTLS 1.2 +levels, is up to 20 times smaller than OpenSSL, and offers progressive ciphers +such as ChaCha20, Curve25519, NTRU, and Blake2b. User benchmarking and feedback +reports dramatically better performance when using wolfSSL over OpenSSL. + +wolfSSL is powered by the wolfCrypt library. A version of the wolfCrypt +cryptography library has been FIPS 140-2 validated (Certificate #2425). For +additional information, visit the wolfCrypt FIPS FAQ +(https://www.wolfssl.com/license/fips/) or contact fips@wolfssl.com + +*** Why choose wolfSSL? *** + +There are many reasons to choose wolfSSL as your embedded SSL solution. Some of +the top reasons include size (typical footprint sizes range from 20-100 kB), +support for the newest standards (SSL 3.0, TLS 1.0, TLS 1.1, TLS 1.2, TLS 1.3, +DTLS 1.0, and DTLS 1.2), current and progressive cipher support (including +stream ciphers), multi-platform, royalty free, and an OpenSSL compatibility API +to ease porting into existing applications which have previously used the +OpenSSL package. For a complete feature list, see chapter 4 of the wolfSSL +manual. (https://www.wolfssl.com/docs/wolfssl-manual/ch4/) + +*** Notes, Please read *** + +Note 1) +wolfSSL as of 3.6.6 no longer enables SSLv3 by default. wolfSSL also no longer +supports static key cipher suites with PSK, RSA, or ECDH. This means if you +plan to use TLS cipher suites you must enable DH (DH is on by default), or +enable ECC (ECC is on by default), or you must enable static key cipher suites +with + + WOLFSSL_STATIC_DH + WOLFSSL_STATIC_RSA + or + WOLFSSL_STATIC_PSK + +though static key cipher suites are deprecated and will be removed from future +versions of TLS. They also lower your security by removing PFS. Since current +NTRU suites available do not use ephemeral keys, WOLFSSL_STATIC_RSA needs to be +used in order to build with NTRU suites. + +When compiling ssl.c, wolfSSL will now issue a compiler error if no cipher +suites are available. You can remove this error by defining +WOLFSSL_ALLOW_NO_SUITES in the event that you desire that, i.e., you're not +using TLS cipher suites. + +Note 2) +wolfSSL takes a different approach to certificate verification than OpenSSL +does. The default policy for the client is to verify the server, this means +that if you don't load CAs to verify the server you'll get a connect error, +no signer error to confirm failure (-188). + +If you want to mimic OpenSSL behavior of having SSL_connect succeed even if +verifying the server fails and reducing security you can do this by calling: + + wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0); + +before calling wolfSSL_new();. Though it's not recommended. + +Note 3) +The enum values SHA, SHA256, SHA384, SHA512 are no longer available when +wolfSSL is built with --enable-opensslextra (OPENSSL_EXTRA) or with the macro +NO_OLD_SHA_NAMES. These names get mapped to the OpenSSL API for a single call +hash function. Instead the name WC_SHA, WC_SHA256, WC_SHA384 and WC_SHA512 +should be used for the enum name. + +*** end Notes *** + + +********* wolfSSL Release 4.1.0 (07/22/2019) + +Release 4.1.0 of wolfSSL embedded TLS has bug fixes and new features including: + +* A fix for the check on return value when verifying PKCS7 bundle signatures, all users with applications using the function wc_PKCS7_VerifySignedData should update +* Adding the function wc_PKCS7_GetSignerSID for PKCS7 firmware bundles as a getter function for the signers SID +* PKCS7 callback functions for unwrapping of CEK and for decryption +* Adding the error value PKCS7_SIGNEEDS_CHECK when no certificates are available in a PKCS7 bundle to verify the signature +* TLS 1.3 fixes including if major version is TLS Draft then it is now ignored and if version negotiation occurs but none were matched then an alert is now sent +* Addition of the WOLFSSL_PSK_ONE_ID macro for indicating that only one identity in TLS 1.3 PSK is available and will be cached +* Adding sanity checks on length of PSK identity from a TLS 1.3 pre-shared key extension +* Additional sanity checks and alert messages added for TLS 1.3 +* Adding XTIME_MS macro to simplify the tls13.c time requirement +* Improvements and refactoring of code related to parsing and creating TLS 1.3 client hello packets +* TLS 1.3 version renegotiation now happens before interpreting ClientHello message +* Chacha20 algorithm optimizations on the ARM architecture for performance increase +* Poly1305 algorithm performance enhancements for the ARM architecture using the SIMD NEON extension +* Curve25519 and Ed25519 optimized for ARM architecture for performance increase +* SHA-512/384 optimizations for performance with ARM architecture using the SIMD NEON extension +* Sniffer updates including adding support for the null cipher and static ECDH key exchange and new SSLWatchCb callback +* Cipher suite TLS_RSA_WITH_NULL_MD5 for use with the sniffer (off by default) +* Sniffer statistic print outs with the macro WOLFSSL_SNIFFER_STATS defined +* A fix for wolfSSL_DH_generate_key when WOLFSSL_SMALL_STACK is defined +* wolfSSL_BN_Init implementation for opensslextra builds +* Updates to the function wolfSSL_i2d_RSAPrivateKey and additional automated tests +* Fixes for EVP_CipherFinal edge cases to match behavior desired +* Check for appropriate private vs public flag with ECC key decode in wolfSSL_EC_KEY_LoadDer_ex, thanks to Eric Miller for the report +* Implementation of the function wolfSSL_PEM_write_DHparams +* wolfSSL_RAND_seed is called in wolfSSL_Init now when opensslextra is enabled +* CryptoCell-310 support on nRF52840 added +* Fixes for atmel_ecc_create_pms to free the used slot. +* Fixes for building ATECC with ATCAPRINTF or WOLFSSL_PUBLIC_MP +* Cortex-M code changes to support IAR compiler +* Improvements to STM32 AES-GCM performance +* Fixes for 16-bit systems including PK callbacks, ATECC and LowResTimer function ptoto. +* IAR-EWARM compiler warning fix +* Clean up of user_settings for CS+ port +* Updating Renesas example projects to the latest version +* Micrium updates adjusting STATIC macro name and added inline flag +* Fixes for building with WOLFSSL_CUSTOM_CURVES on Windows +* Updates and refactor to the default build settings with Arduino +* Fixes for visibility tags with Cygwin build +* STSAFE Improvements to support wolfSSL Crypto Callbacks +* Improvements to NetBSD builds and mutex use in test case +* Updating TI hardware offload with WOLFSSL_TI_CRYPT build +* Maintaining Xilinx FreeRTOS port by adjusting time.h include in wolfSSL +* SiFive HiFive E31 RISC‐V core family port +* Port for Telit IoT AppZone SDK +* OCSP Response signed by issuer with identical SKID fix +* Fix for sending revoked certificate with OCSP +* Honor the status sent over connection with peers and do not perform an internal OCSP lookup +* Adding the build flag `--enable-ecccustcurves=all` to enable all curve types +* Support add for Ed25519ctx and Ed25519ph sign/verify algorithms as per RFC 8032 +* Addition of the macro WOLFSSL_NO_SIGALG to disable signature algorithms extension +* wc_AesCtrEncrypt in place addition, where input and output buffer can be the same buffer +* Single shot API added for SHA3; wc_Sha3_224Hash, wc_Sha3_256Hash, wc_Sha3_384Hash, wc_Sha3_512Hash +* Function additions for JSSE support some of which are wolfSSL_get_ciphers_iana and wolfSSL_X509_verify along with expansion of the --enable-jni option +* Macro guards for more modular SHA3 build (i.e. support for 384 size only) +* Benchmarking -thread argument support for asynchronous crypto +* Blake2s support (--enable-blake2s), which provides 32-bit Blake2 support +* Macro SHA256_MANY_REGISTERS addition to potentially speed up SHA256 depending on architecture +* Additional TLS alert messages sent with the macro WOLFSSL_EXTRA_ALERTS defined +* Feature to fail resumption of a session if the session’s cipher suite is not in the client’s list, this can be overridden by defining the macro NO_RESUME_SUITE_CHECK +* Fallback SCSV (Signaling Cipher Suite Value) support on Server only (--enable-fallback-scsv) +* DTLS export state only (wolfSSL_dtls_export_state_only) which is a subset of the information exported from previous DTLS export function +* Function wc_DhCheckPubValue added to perform simple validity checks on DH keys +* Support for RSA SHA-224 signatures with TLS added +* Additional option “-print” to the benchmark app for printing out a brief summary after benchmarks are complete +* Adding (--disable-pkcs12) option and improvements for disabled sections in pwdbased.c, asn.c, rsa.c, pkcs12.c and wc_encrypt +* Added DES3 support to the wolfSSL crypto callbacks +* Compile time fixes for build case with SP math and RSA only +* Fixes for Coverity static analysis report including explicit initialization of reported stack variables some additional Coverity fixes added thanks to Martin +* Fixes for scan build warnings (i.e possible null dereference in ecc.c) +* Resetting verify send value with a call to wolfSSL_clear function +* Fix for extern with sp_ModExp_2048 when building with --cpp option +* Fix for typo issue with --enable-sp=cortexm +* Adding #pragma warning disable 4127 for tfm.c when building with Visual Studio +* Improvements to the maximum ECC signature calculations +* Improvements to TLS write handling in error cases which helps user application not go through with a wolfSSL_write attempt after a wolfSSL_read failure +* Fix for read directory functions with Windows (wc_ReadDirFirst and wc_ReadDirNext) +* Sanity check on index before accessing domain component buffer in call to wolfSSL_X509_NAME_get_entry +* Sending fatal alert from client side on version error +* Fix for static RSA cipher suite with PK callback and no loaded private key +* Fix for potential memory leak in error case with the function wc_DsaKeyToDer, thanks to Chris H. for the report +* Adjusting STRING_USER macro to remove includes of standard lib or +* Bug fix for checking wrong allocation assignment in the function wc_PBKDF2 and handling potential leak on allocation failure. This case is only hit when the specific call to malloc fails in the function wc_PBKDF2. Thanks to Robert Altnoeder (Linbit) for the report +* Improved length checks when parsing ASN.1 certificates +* extern "C" additions to header files that were missing them +* Improved checking of return values with TLS extension functions and error codes +* Removing redundant calls to the generate function when instantiating and reseeding DRBG +* Refactoring and improvements to autoconf code with consolidating AM_CONDITIONAL statements +* Improvements for handling error return codes when reading input from transport layer +* Improvements to efficiency of SNI extension parsing and error checking with ALPN parsing +* Macro WOLFSSL_DEBUG_TLS addition for printing out extension data being parsed during a TLS connection +* Adjustment of prime testing with --disable-fastmath builds + + +This release of wolfSSL includes a fix for 2 security vulnerabilities. + +There is a fix for a potential buffer overflow case with the TLSv1.3 PSK extension parsing. This affects users that are enabling TLSv1.3 (--enable-tls13). Thanks to Robert Hoerr for the report. The CVE associated with the report is CVE-2019-11873. + +There is a fix for the potential leak of nonce sizes when performing ECDSA signing operations. The leak is considered to be difficult to exploit but it could potentially be used maliciously to perform a lattice based timing attack against previous wolfSSL versions. ECC operations with --enable-sp and --enable-sp-asm are not affected, users with private ECC keys in other builds that are performing ECDSA signing operations should update versions of wolfSSL along with private ECC keys. Thanks to Ján Jančár from Masaryk University for the report. + + +*** Resources *** + + +[wolfSSL Website](https://www.wolfssl.com/) + +[wolfSSL Wiki](https://github.com/wolfSSL/wolfssl/wiki) + +[FIPS FAQ](https://www.wolfssl.com/wolfSSL/fips.html) + +[wolfSSL Manual](https://wolfssl.com/wolfSSL/Docs-wolfssl-manual-toc.html) + +[wolfSSL API Reference] +(https://wolfssl.com/wolfSSL/Docs-wolfssl-manual-17-wolfssl-api-reference.html) + +[wolfCrypt API Reference] +(https://wolfssl.com/wolfSSL/Docs-wolfssl-manual-18-wolfcrypt-api-reference.html) + +[TLS 1.3](https://www.wolfssl.com/docs/tls13/) diff --git a/beken_os/beken378/func/wolfssl/src/bio.c b/beken_os/beken378/func/wolfssl/src/bio.c new file mode 100755 index 0000000..c4b2257 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/src/bio.c @@ -0,0 +1,1163 @@ +/* bio.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#include + +#if !defined(WOLFSSL_BIO_INCLUDED) + #ifndef WOLFSSL_IGNORE_FILE_WARN + #warning bio.c does not need to be compiled separately from ssl.c + #endif +#else + + +/* Helper function to decode a base64 input + * + * returns size of resulting buffer on success + */ +static int wolfSSL_BIO_BASE64_read(WOLFSSL_BIO* bio, void* buf, int len) +{ + word32 frmtSz = len; + + WOLFSSL_ENTER("wolfSSL_BIO_BASE64_read"); + + if (Base64_Decode((const byte*)buf, (word32)len, (byte*)buf, &frmtSz) !=0) { + WOLFSSL_MSG("Err doing base64 decode"); + return SSL_FATAL_ERROR; + } + + (void)bio; + return (int)frmtSz; +} + + +/* Helper function to read from WOLFSSL_BIO_BIO type + * + * returns amount in bytes read on success + */ +static int wolfSSL_BIO_BIO_read(WOLFSSL_BIO* bio, void* buf, int len) +{ + int sz; + char* pt; + + sz = wolfSSL_BIO_nread(bio, &pt, len); + + if (sz > 0) { + XMEMCPY(buf, pt, sz); + } + + return sz; +} + + +/* Handles reading from a memory type BIO and advancing the state. + * + * bio WOLFSSL_BIO to read from + * buf buffer to put data from bio in + * len amount of data to be read + * + * returns size read on success + */ +static int wolfSSL_BIO_MEMORY_read(WOLFSSL_BIO* bio, void* buf, int len) +{ + int sz; + + sz = wolfSSL_BIO_pending(bio); + if (sz > 0) { + const unsigned char* pt = NULL; + int memSz; + + if (sz > len) { + sz = len; + } + memSz = wolfSSL_BIO_get_mem_data(bio, (void*)&pt); + if (memSz >= sz && pt != NULL) { + byte* tmp; + + XMEMCPY(buf, (void*)pt, sz); + if (memSz - sz > 0) { + tmp = (byte*)XMALLOC(memSz-sz, bio->heap, DYNAMIC_TYPE_OPENSSL); + if (tmp == NULL) { + WOLFSSL_MSG("Memory error"); + return WOLFSSL_BIO_ERROR; + } + XMEMCPY(tmp, (void*)(pt + sz), memSz - sz); + + /* reset internal bio->mem */ + XFREE(bio->mem, bio->heap, DYNAMIC_TYPE_OPENSSL); + bio->mem = tmp; + bio->memLen = memSz-sz; + if (bio->mem_buf != NULL) { + bio->mem_buf->data = (char*)bio->mem; + bio->mem_buf->length = bio->memLen; + } + } + bio->wrSz -= sz; + } + else { + WOLFSSL_MSG("Issue with getting bio mem pointer"); + return 0; + } + } + else { + return WOLFSSL_BIO_ERROR; + } + + return sz; +} + + +/* Helper function to read from WOLFSSL_BIO_SSL type + * + * returns the number of bytes read on success + */ +static int wolfSSL_BIO_SSL_read(WOLFSSL_BIO* bio, void* buf, + int len, WOLFSSL_BIO* front) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_BIO_SSL_read"); + + /* already got eof, again is error */ + if ((front == NULL) || front->eof) + return WOLFSSL_FATAL_ERROR; + + ret = wolfSSL_read(bio->ssl, buf, len); + if (ret == 0) + front->eof = 1; + else if (ret < 0) { + int err = wolfSSL_get_error(bio->ssl, 0); + if ( !(err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) ) + front->eof = 1; + } + + return ret; +} + + + +/* Used to read data from a WOLFSSL_BIO structure + * + * bio structure to read data from + * buf buffer to hold the result + * len length of buf buffer + * + * returns the number of bytes read on success + */ +int wolfSSL_BIO_read(WOLFSSL_BIO* bio, void* buf, int len) +{ + int ret = 0; + WOLFSSL_BIO* front = bio; + int sz = 0; + + WOLFSSL_ENTER("wolfSSL_BIO_read"); + + /* start at end of list and work backwards */ + while ((bio != NULL) && (bio->next != NULL)) { + bio = bio->next; + } + + while (bio != NULL && ret >= 0) { + /* formating data */ + if (bio->type == WOLFSSL_BIO_BASE64 && ret > 0 && sz > 0) { + ret = wolfSSL_BIO_BASE64_read(bio, buf, sz); + } + + /* write BIOs */ + if (bio && bio->type == WOLFSSL_BIO_BIO) { + ret = wolfSSL_BIO_BIO_read(bio, buf, len); + } + + if (bio && bio->type == WOLFSSL_BIO_MEMORY) { + ret = wolfSSL_BIO_MEMORY_read(bio, buf, len); + } + + #ifndef NO_FILESYSTEM + if (bio && bio->type == WOLFSSL_BIO_FILE) { + ret = (int)XFREAD(buf, 1, len, bio->file); + } + #endif + + if (bio && bio->type == WOLFSSL_BIO_SSL) { + ret = wolfSSL_BIO_SSL_read(bio, buf, len, front); + } + + /* case where front of list is done */ + if (bio == front) { + break; /* at front of list so be done */ + } + + if (ret > 0) { + sz = ret; /* adjust size for formating */ + } + + /* previous WOLFSSL_BIO in list working towards head of list */ + bio = bio->prev; + } + + return ret; +} + + +/* Converts data into base64 output + * + * returns the resulting buffer size on success. + */ +static int wolfSSL_BIO_BASE64_write(WOLFSSL_BIO* bio, const void* data, + word32 inLen, byte* out, word32* outLen) +{ + byte* tmp = NULL; + int ret = 0; + + WOLFSSL_ENTER("wolfSSL_BIO_BASE64_write"); + + if (bio == NULL || data == NULL || out == NULL || outLen == NULL) { + return BAD_FUNC_ARG; + } + +#if defined(WOLFSSL_BASE64_ENCODE) + tmp = (byte*)XMALLOC(*outLen, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) { + return WOLFSSL_FATAL_ERROR; + } + + if ((bio->flags & WOLFSSL_BIO_FLAG_BASE64_NO_NL) == + WOLFSSL_BIO_FLAG_BASE64_NO_NL) { + if (Base64_Encode_NoNl((const byte*)data, inLen, + tmp, outLen) < 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + else { + if (Base64_Encode((const byte*)data, inLen, + tmp, outLen) < 0) { + ret = WOLFSSL_FATAL_ERROR; + } + } + + if (ret != WOLFSSL_FATAL_ERROR) { + ret = (int)*outLen; + XMEMCPY(out, tmp, *outLen); + + } + XFREE(tmp, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); +#else + (void)bio; + (void)data; + (void)inLen; + (void)out; + (void)outLen; + (void)tmp; + WOLFSSL_MSG("BASE64 encoding not compiled in"); +#endif + return ret; +} + + +/* Helper function for writing to a WOLFSSL_BIO_SSL type + * + * returns the amount written in bytes on success + */ +static int wolfSSL_BIO_SSL_write(WOLFSSL_BIO* bio, const void* data, + int len, WOLFSSL_BIO* front) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_BIO_SSL_write"); + + if (bio->ssl == 0) return BAD_FUNC_ARG; + + ret = wolfSSL_write(bio->ssl, data, len); + if (ret == 0) + front->eof = 1; + else if (ret < 0) { + int err = wolfSSL_get_error(bio->ssl, 0); + if ( !(err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) ) + front->eof = 1; + } + return ret; +} + + +/* Writes to a WOLFSSL_BIO_BIO type. + * + * returns the amount written on success + */ +static int wolfSSL_BIO_BIO_write(WOLFSSL_BIO* bio, const void* data, + int len) +{ + int sz; + char* buf; + + WOLFSSL_ENTER("wolfSSL_BIO_BIO_write"); + + /* adding in sanity checks for static analysis tools */ + if (bio == NULL || data == NULL) { + return BAD_FUNC_ARG; + } + + sz = wolfSSL_BIO_nwrite(bio, &buf, len); + + /* test space for write */ + if (sz <= 0) { + WOLFSSL_MSG("No room left to write"); + return sz; + } + + XMEMCPY(buf, data, sz); + + return sz; +} + + +/* for complete compatibility a bio memory write allocs its own memory + * until the application runs out .... + * + * bio structure to hold incoming data + * data buffer holding the data to be written + * len length of data buffer + * + * returns the amount of data written on success and WOLFSSL_FAILURE or + * WOLFSSL_BIO_ERROR for failure cases. + */ +static int wolfSSL_BIO_MEMORY_write(WOLFSSL_BIO* bio, const void* data, + int len) +{ + int sz; + const unsigned char* buf; + + WOLFSSL_ENTER("wolfSSL_BIO_MEMORY_write"); + + if (bio == NULL || data == NULL) { + return BAD_FUNC_ARG; + } + + sz = wolfSSL_BIO_pending(bio); + if (sz < 0) { + WOLFSSL_MSG("Error getting memory data"); + return sz; + } + + if (bio->mem == NULL) { + bio->mem = (byte*)XMALLOC(len, bio->heap, DYNAMIC_TYPE_OPENSSL); + if (bio->mem == NULL) { + WOLFSSL_MSG("Error on malloc"); + return WOLFSSL_FAILURE; + } + bio->memLen = len; + if (bio->mem_buf != NULL) { + bio->mem_buf->data = (char*)bio->mem; + bio->mem_buf->length = bio->memLen; + } + } + + /* check if will fit in current buffer size */ + if (wolfSSL_BIO_get_mem_data(bio, (void*)&buf) < 0) { + return WOLFSSL_BIO_ERROR; + } + if (bio->memLen < sz + len) { + bio->mem = (byte*)XREALLOC(bio->mem, sz + len, bio->heap, + DYNAMIC_TYPE_OPENSSL); + if (bio->mem == NULL) { + WOLFSSL_MSG("Error on realloc"); + return WOLFSSL_FAILURE; + } + bio->memLen = sz + len; + if (bio->mem_buf != NULL) { + bio->mem_buf->data = (char*)bio->mem; + bio->mem_buf->length = bio->memLen; + } + } + + XMEMCPY(bio->mem + sz, data, len); + bio->wrSz += len; + + return len; +} + + +/* Writes data to a WOLFSSL_BIO structure + * + * bio structure to write to + * data holds the data to be written + * len length of data buffer + * + * returns the amount written in bytes on success + */ +int wolfSSL_BIO_write(WOLFSSL_BIO* bio, const void* data, int len) +{ + int ret = 0; + WOLFSSL_BIO* front = bio; + void* frmt = NULL; + word32 frmtSz = 0; + + WOLFSSL_ENTER("wolfSSL_BIO_write"); + + while (bio != NULL && ret >= 0) { + /* check for formating */ + if (bio && bio->type == WOLFSSL_BIO_BASE64) { +#if defined(WOLFSSL_BASE64_ENCODE) + word32 sz = 0; + + if (bio->flags & WOLFSSL_BIO_FLAG_BASE64_NO_NL) { + if (Base64_Encode_NoNl((const byte*)data, len, NULL, + &sz) != LENGTH_ONLY_E) { + WOLFSSL_MSG("Error with base 64 get length"); + ret = SSL_FATAL_ERROR; + } + } + else { + if (Base64_Encode((const byte*)data, len, NULL, &sz) != + LENGTH_ONLY_E) { + WOLFSSL_MSG("Error with base 64 get length"); + ret = SSL_FATAL_ERROR; + } + } + + if (frmt == NULL && sz > 0 && ret != SSL_FATAL_ERROR) { + frmt = (void*)XMALLOC(sz, front->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (frmt == NULL) { + WOLFSSL_MSG("Memory error"); + ret = SSL_FATAL_ERROR; + } + frmtSz = sz; + } + else if (sz > frmtSz) { + frmt = (void*)XREALLOC(frmt, sz, front->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (frmt == NULL) { + WOLFSSL_MSG("Memory error"); + ret = SSL_FATAL_ERROR; + } + /* since frmt already existed then data should point to knew + formated buffer */ + data = frmt; + len = frmtSz; + frmtSz = sz; + } +#endif /* defined(WOLFSSL_BASE64_ENCODE) */ + + if (ret >= 0) { + /* change so that data is formated buffer */ + ret = wolfSSL_BIO_BASE64_write(bio, data, (word32)len, + (byte*)frmt, &frmtSz); + data = frmt; + len = frmtSz; + } + } + + /* write bios */ + if (bio && bio->type == WOLFSSL_BIO_BIO) { + ret = wolfSSL_BIO_BIO_write(bio, data, len); + } + + if (bio && bio->type == WOLFSSL_BIO_MEMORY) { + ret = wolfSSL_BIO_MEMORY_write(bio, data, len); + } + + #ifndef NO_FILESYSTEM + if (bio && bio->type == WOLFSSL_BIO_FILE) { + ret = (int)XFWRITE(data, 1, len, bio->file); + } + #endif + + if (bio && bio->type == WOLFSSL_BIO_SSL) { + /* already got eof, again is error */ + if (bio && front->eof) { + ret = SSL_FATAL_ERROR; + } + else { + ret = wolfSSL_BIO_SSL_write(bio, data, len, front); + } + } + + /* advance to the next bio in list */ + bio = bio->next; + } + + if (frmt != NULL) { + XFREE(frmt, front->heap, DYNAMIC_TYPE_TMP_BUFFER); + } + + return ret; +} + + +WOLFSSL_API long wolfSSL_BIO_ctrl(WOLFSSL_BIO *bio, int cmd, long larg, void *parg) +{ + (void)bio; + (void)cmd; + (void)larg; + (void)parg; + + WOLFSSL_STUB("BIO_ctrl"); + return 0; +} + + +/* helper function for wolfSSL_BIO_gets + * size till a newline is hit + * returns the number of bytes including the new line character + */ +static int wolfSSL_getLineLength(char* in, int inSz) +{ + int i; + + for (i = 0; i < inSz; i++) { + if (in[i] == '\n') { + return i + 1; /* includes new line character */ + } + } + + return inSz; /* rest of buffer is all one line */ +} + + +/* Gets the next line from bio. Goes until a new line character or end of + * buffer is reached. + * + * bio the structure to read a new line from + * buf buffer to hold the result + * sz the size of "buf" buffer + * + * returns the size of the result placed in buf on success and a 0 or negative + * value in an error case. + */ +int wolfSSL_BIO_gets(WOLFSSL_BIO* bio, char* buf, int sz) +{ + int ret = WOLFSSL_BIO_UNSET; + + WOLFSSL_ENTER("wolfSSL_BIO_gets"); + + if (bio == NULL || buf == NULL) { + return WOLFSSL_FAILURE; + } + + /* not enough space for character plus terminator */ + if (sz <= 1) { + return 0; + } + + switch (bio->type) { +#ifndef NO_FILESYSTEM + case WOLFSSL_BIO_FILE: + if (bio->file == XBADFILE) { + return WOLFSSL_BIO_ERROR; + } + + #if defined(MICRIUM) || defined(LSR_FS) || defined(EBSNET) + WOLFSSL_MSG("XFGETS not ported for this system yet"); + ret = XFGETS(buf, sz, bio->file); + #else + if (XFGETS(buf, sz, bio->file) != NULL) { + ret = (int)XSTRLEN(buf); + } + else { + ret = WOLFSSL_BIO_ERROR; + } + #endif + break; +#endif /* NO_FILESYSTEM */ + case WOLFSSL_BIO_MEMORY: + { + const byte* c; + int cSz; + cSz = wolfSSL_BIO_pending(bio); + if (cSz == 0) { + ret = 0; /* Nothing to read */ + buf[0] = '\0'; + break; + } + + if (wolfSSL_BIO_get_mem_data(bio, (void*)&c) <= 0) { + ret = WOLFSSL_BIO_ERROR; + break; + } + + cSz = wolfSSL_getLineLength((char*)c, cSz); + /* check case where line was bigger then buffer and buffer + * needs end terminator */ + if (cSz >= sz) { + cSz = sz - 1; + buf[cSz] = '\0'; + } + else { + /* not minus 1 here because placing terminator after + msg and have checked that sz is large enough */ + buf[cSz] = '\0'; + } + + ret = wolfSSL_BIO_MEMORY_read(bio, (void*)buf, cSz); + /* ret is read after the switch statement */ + break; + } + case WOLFSSL_BIO_BIO: + { + char* c; + int cSz; + cSz = wolfSSL_BIO_nread0(bio, &c); + if (cSz == 0) { + ret = 0; /* Nothing to read */ + buf[0] = '\0'; + break; + } + + cSz = wolfSSL_getLineLength(c, cSz); + /* check case where line was bigger then buffer and buffer + * needs end terminator */ + if (cSz >= sz) { + cSz = sz - 1; + buf[cSz] = '\0'; + } + else { + /* not minus 1 here because placing terminator after + msg and have checked that sz is large enough */ + buf[cSz] = '\0'; + } + + ret = wolfSSL_BIO_nread(bio, &c, cSz); + if (ret > 0 && ret < sz) { + XMEMCPY(buf, c, ret); + } + break; + } + + default: + WOLFSSL_MSG("BIO type not supported yet with wolfSSL_BIO_gets"); + } + + return ret; +} + + +/* searches through bio list for a BIO of type "type" + * returns NULL on failure to find a given type */ +WOLFSSL_BIO* wolfSSL_BIO_find_type(WOLFSSL_BIO* bio, int type) +{ + WOLFSSL_BIO* local = NULL; + WOLFSSL_BIO* current; + + WOLFSSL_ENTER("wolfSSL_BIO_find_type"); + + if (bio == NULL) { + return local; + } + + current = bio; + while (current != NULL) { + if (current->type == type) { + WOLFSSL_MSG("Found matching WOLFSSL_BIO type"); + local = current; + break; + } + current = current->next; + } + + return local; +} + + +/* returns a pointer to the next WOLFSSL_BIO in the chain on success. + * If a failure case then NULL is returned */ +WOLFSSL_BIO* wolfSSL_BIO_next(WOLFSSL_BIO* bio) +{ + WOLFSSL_ENTER("wolfSSL_BIO_next"); + + if (bio == NULL) { + WOLFSSL_MSG("Bad argument passed in"); + return NULL; + } + + return bio->next; +} + +/* BIO_wpending returns the number of bytes pending to be written. */ +size_t wolfSSL_BIO_wpending(const WOLFSSL_BIO *bio) +{ + WOLFSSL_ENTER("BIO_wpending"); + + if (bio == NULL) + return 0; + + if (bio->ssl != NULL) { + /* not supported case */ + return 0; + } + + if (bio->type == WOLFSSL_BIO_MEMORY) { + return bio->wrSz; + } + + /* type BIO_BIO then check paired buffer */ + if (bio->type == WOLFSSL_BIO_BIO && bio->pair != NULL) { + WOLFSSL_BIO* pair = bio->pair; + return pair->wrIdx; + } + + return 0; +} + +/* Return the number of pending bytes in read and write buffers */ +size_t wolfSSL_BIO_ctrl_pending(WOLFSSL_BIO *bio) +{ + WOLFSSL_ENTER("BIO_ctrl_pending"); + if (bio == NULL) { + return 0; + } + + if (bio->ssl != NULL) { + return (long)wolfSSL_pending(bio->ssl); + } + + if (bio->type == WOLFSSL_BIO_MEMORY) { + return bio->wrSz; + } + + /* type BIO_BIO then check paired buffer */ + if (bio->type == WOLFSSL_BIO_BIO && bio->pair != NULL) { + WOLFSSL_BIO* pair = bio->pair; + if (pair->wrIdx > 0 && pair->wrIdx <= pair->rdIdx) { + /* in wrap around state where beginning of buffer is being + * overwritten */ + return pair->wrSz - pair->rdIdx + pair->wrIdx; + } + else { + /* simple case where has not wrapped around */ + return pair->wrIdx - pair->rdIdx; + } + } + + return 0; +} + + +long wolfSSL_BIO_get_mem_ptr(WOLFSSL_BIO *bio, WOLFSSL_BUF_MEM **ptr) +{ + WOLFSSL_ENTER("wolfSSL_BIO_get_mem_ptr"); + + if (bio == NULL || ptr == NULL) { + return WOLFSSL_FAILURE; + } + + if (bio->type == WOLFSSL_BIO_FILE || bio->type == WOLFSSL_BIO_SOCKET) { + WOLFSSL_MSG("NO memory buffer for FILE type"); + return SSL_FAILURE; + } + + *ptr = bio->mem_buf; + + return SSL_SUCCESS; +} + +WOLFSSL_API long wolfSSL_BIO_int_ctrl(WOLFSSL_BIO *bp, int cmd, long larg, int iarg) +{ + (void) bp; + (void) cmd; + (void) larg; + (void) iarg; + WOLFSSL_STUB("BIO_int_ctrl"); + return 0; +} + + +int wolfSSL_BIO_set_write_buf_size(WOLFSSL_BIO *bio, long size) +{ + WOLFSSL_ENTER("wolfSSL_BIO_set_write_buf_size"); + + if (bio == NULL || bio->type != WOLFSSL_BIO_BIO || size < 0) { + return WOLFSSL_FAILURE; + } + + /* if already in pair then do not change size */ + if (bio->pair != NULL) { + WOLFSSL_MSG("WOLFSSL_BIO is paired, free from pair before changing"); + return WOLFSSL_FAILURE; + } + + bio->wrSz = (int)size; + if (bio->wrSz < 0) { + WOLFSSL_MSG("Unexpected negative size value"); + return WOLFSSL_FAILURE; + } + + if (bio->mem != NULL) { + XFREE(bio->mem, bio->heap, DYNAMIC_TYPE_OPENSSL); + } + + bio->mem = (byte*)XMALLOC(bio->wrSz, bio->heap, DYNAMIC_TYPE_OPENSSL); + if (bio->mem == NULL) { + WOLFSSL_MSG("Memory allocation error"); + return WOLFSSL_FAILURE; + } + bio->memLen = bio->wrSz; + bio->wrIdx = 0; + bio->rdIdx = 0; + if (bio->mem_buf != NULL) { + bio->mem_buf->data = (char*)bio->mem; + bio->mem_buf->length = bio->memLen; + } + + return WOLFSSL_SUCCESS; +} + + +/* Joins two BIO_BIO types. The write of b1 goes to the read of b2 and vise + * versa. Creating something similar to a two way pipe. + * Reading and writing between the two BIOs is not thread safe, they are + * expected to be used by the same thread. */ +int wolfSSL_BIO_make_bio_pair(WOLFSSL_BIO *b1, WOLFSSL_BIO *b2) +{ + WOLFSSL_ENTER("wolfSSL_BIO_make_bio_pair"); + + if (b1 == NULL || b2 == NULL) { + WOLFSSL_LEAVE("wolfSSL_BIO_make_bio_pair", BAD_FUNC_ARG); + return WOLFSSL_FAILURE; + } + + /* both are expected to be of type BIO and not already paired */ + if (b1->type != WOLFSSL_BIO_BIO || b2->type != WOLFSSL_BIO_BIO || + b1->pair != NULL || b2->pair != NULL) { + WOLFSSL_MSG("Expected type BIO and not already paired"); + return WOLFSSL_FAILURE; + } + + /* set default write size if not already set */ + if (b1->mem == NULL && wolfSSL_BIO_set_write_buf_size(b1, + WOLFSSL_BIO_SIZE) != WOLFSSL_SUCCESS) { + return WOLFSSL_FAILURE; + } + + if (b2->mem == NULL && wolfSSL_BIO_set_write_buf_size(b2, + WOLFSSL_BIO_SIZE) != WOLFSSL_SUCCESS) { + return WOLFSSL_FAILURE; + } + + b1->pair = b2; + b2->pair = b1; + + return WOLFSSL_SUCCESS; +} + + +int wolfSSL_BIO_ctrl_reset_read_request(WOLFSSL_BIO *b) +{ + WOLFSSL_ENTER("wolfSSL_BIO_ctrl_reset_read_request"); + + if (b == NULL || b->type == WOLFSSL_BIO_MEMORY) { + return SSL_FAILURE; + } + + b->readRq = 0; + + return WOLFSSL_SUCCESS; +} + + +/* Does not advance read index pointer */ +int wolfSSL_BIO_nread0(WOLFSSL_BIO *bio, char **buf) +{ + WOLFSSL_ENTER("wolfSSL_BIO_nread0"); + + if (bio == NULL || buf == NULL) { + WOLFSSL_MSG("NULL argument passed in"); + return 0; + } + + /* if paired read from pair */ + if (bio->pair != NULL) { + WOLFSSL_BIO* pair = bio->pair; + + /* case where have wrapped around write buffer */ + *buf = (char*)pair->mem + pair->rdIdx; + if (pair->wrIdx > 0 && pair->rdIdx >= pair->wrIdx) { + return pair->wrSz - pair->rdIdx; + } + else { + return pair->wrIdx - pair->rdIdx; + } + } + + return 0; +} + + +/* similar to wolfSSL_BIO_nread0 but advances the read index */ +int wolfSSL_BIO_nread(WOLFSSL_BIO *bio, char **buf, int num) +{ + int sz = WOLFSSL_BIO_UNSET; + + WOLFSSL_ENTER("wolfSSL_BIO_nread"); + + if (bio == NULL || buf == NULL) { + WOLFSSL_MSG("NULL argument passed in"); + return WOLFSSL_FAILURE; + } + + if (bio->type == WOLFSSL_BIO_MEMORY) { + return SSL_FAILURE; + } + + if (bio->pair != NULL) { + /* special case if asking to read 0 bytes */ + if (num == 0) { + *buf = (char*)bio->pair->mem + bio->pair->rdIdx; + return 0; + } + + /* get amount able to read and set buffer pointer */ + sz = wolfSSL_BIO_nread0(bio, buf); + if (sz == 0) { + return WOLFSSL_BIO_ERROR; + } + + if (num < sz) { + sz = num; + } + bio->pair->rdIdx += sz; + + /* check if have read to the end of the buffer and need to reset */ + if (bio->pair->rdIdx == bio->pair->wrSz) { + bio->pair->rdIdx = 0; + if (bio->pair->wrIdx == bio->pair->wrSz) { + bio->pair->wrIdx = 0; + } + } + + /* check if read up to write index, if so then reset indexs */ + if (bio->pair->rdIdx == bio->pair->wrIdx) { + bio->pair->rdIdx = 0; + bio->pair->wrIdx = 0; + } + } + + return sz; +} + + +int wolfSSL_BIO_nwrite(WOLFSSL_BIO *bio, char **buf, int num) +{ + int sz = WOLFSSL_BIO_UNSET; + + WOLFSSL_ENTER("wolfSSL_BIO_nwrite"); + + if (bio == NULL || buf == NULL) { + WOLFSSL_MSG("NULL argument passed in"); + return 0; + } + + if (bio->type != WOLFSSL_BIO_BIO) { + return SSL_FAILURE; + } + + if (bio->pair != NULL) { + if (num == 0) { + *buf = (char*)bio->mem + bio->wrIdx; + return 0; + } + + if (bio->wrIdx < bio->rdIdx) { + /* if wrapped around only write up to read index. In this case + * rdIdx is always greater then wrIdx so sz will not be negative. */ + sz = bio->rdIdx - bio->wrIdx; + } + else if (bio->rdIdx > 0 && bio->wrIdx == bio->rdIdx) { + return WOLFSSL_BIO_ERROR; /* no more room to write */ + } + else { + /* write index is past read index so write to end of buffer */ + sz = bio->wrSz - bio->wrIdx; + + if (sz <= 0) { + /* either an error has occured with write index or it is at the + * end of the write buffer. */ + if (bio->rdIdx == 0) { + /* no more room, nothing has been read */ + return WOLFSSL_BIO_ERROR; + } + + bio->wrIdx = 0; + + /* check case where read index is not at 0 */ + if (bio->rdIdx > 0) { + sz = bio->rdIdx; /* can write up to the read index */ + } + else { + sz = bio->wrSz; /* no restriction other then buffer size */ + } + } + } + + if (num < sz) { + sz = num; + } + *buf = (char*)bio->mem + bio->wrIdx; + bio->wrIdx += sz; + + /* if at the end of the buffer and space for wrap around then set + * write index back to 0 */ + if (bio->wrIdx == bio->wrSz && bio->rdIdx > 0) { + bio->wrIdx = 0; + } + } + + return sz; +} + + +/* Reset BIO to initial state */ +int wolfSSL_BIO_reset(WOLFSSL_BIO *bio) +{ + WOLFSSL_ENTER("wolfSSL_BIO_reset"); + + if (bio == NULL) { + WOLFSSL_MSG("NULL argument passed in"); + /* -1 is consistent failure even for FILE type */ + return WOLFSSL_BIO_ERROR; + } + + switch (bio->type) { + #ifndef NO_FILESYSTEM + case WOLFSSL_BIO_FILE: + XREWIND(bio->file); + return 0; + #endif + + case WOLFSSL_BIO_BIO: + bio->rdIdx = 0; + bio->wrIdx = 0; + return 0; + + case WOLFSSL_BIO_MEMORY: + bio->rdIdx = 0; + bio->wrIdx = 0; + bio->wrSz = 0; + XFREE(bio->mem, bio->heap, DYNAMIC_TYPE_OPENSSL); + bio->mem = NULL; + bio->memLen = 0; + if (bio->mem_buf != NULL) { + bio->mem_buf->data = (char*)bio->mem; + bio->mem_buf->length = bio->memLen; + } + return 0; + + default: + WOLFSSL_MSG("Unknown BIO type needs added to reset function"); + } + + return WOLFSSL_BIO_ERROR; +} + +#ifndef NO_FILESYSTEM +long wolfSSL_BIO_set_fp(WOLFSSL_BIO *bio, XFILE fp, int c) +{ + WOLFSSL_ENTER("wolfSSL_BIO_set_fp"); + + if (bio == NULL || fp == XBADFILE) { + WOLFSSL_LEAVE("wolfSSL_BIO_set_fp", BAD_FUNC_ARG); + return WOLFSSL_FAILURE; + } + + if (bio->type != WOLFSSL_BIO_FILE) { + return WOLFSSL_FAILURE; + } + + bio->close = (byte)c; + bio->file = fp; + + return WOLFSSL_SUCCESS; +} + + +long wolfSSL_BIO_get_fp(WOLFSSL_BIO *bio, XFILE* fp) +{ + WOLFSSL_ENTER("wolfSSL_BIO_get_fp"); + + if (bio == NULL || fp == XBADFILE) { + return WOLFSSL_FAILURE; + } + + if (bio->type != WOLFSSL_BIO_FILE) { + return SSL_FAILURE; + } + + *fp = bio->file; + + return WOLFSSL_SUCCESS; +} + +/* overwrites file */ +int wolfSSL_BIO_write_filename(WOLFSSL_BIO *bio, char *name) +{ + WOLFSSL_ENTER("wolfSSL_BIO_write_filename"); + + if (bio == NULL || name == NULL) { + return WOLFSSL_FAILURE; + } + + if (bio->type == WOLFSSL_BIO_FILE) { + if (bio->file != XBADFILE && bio->close == BIO_CLOSE) { + XFCLOSE(bio->file); + } + + bio->file = XFOPEN(name, "w"); + if (bio->file == XBADFILE) { + return WOLFSSL_FAILURE; + } + bio->close = BIO_CLOSE; + + return WOLFSSL_SUCCESS; + } + + return WOLFSSL_FAILURE; +} + + +int wolfSSL_BIO_seek(WOLFSSL_BIO *bio, int ofs) +{ + WOLFSSL_ENTER("wolfSSL_BIO_seek"); + + if (bio == NULL) { + return -1; + } + + /* offset ofs from beginning of file */ + if (bio->type == WOLFSSL_BIO_FILE && + XFSEEK(bio->file, ofs, SEEK_SET) < 0) { + return -1; + } + + return 0; +} +#endif /* NO_FILESYSTEM */ + + +long wolfSSL_BIO_set_mem_eof_return(WOLFSSL_BIO *bio, int v) +{ + WOLFSSL_ENTER("wolfSSL_BIO_set_mem_eof_return"); + + if (bio != NULL) { + bio->eof = v; + } + + return 0; +} +#endif /* WOLFSSL_BIO_INCLUDED */ + diff --git a/beken_os/beken378/func/wolfssl/src/crl.c b/beken_os/beken378/func/wolfssl/src/crl.c new file mode 100755 index 0000000..c9bb461 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/src/crl.c @@ -0,0 +1,1096 @@ +/* crl.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + /* Name change compatibility layer no longer needs included here */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifndef WOLFCRYPT_ONLY +#ifdef HAVE_CRL + +#include +#include + +#include + +#ifdef HAVE_CRL_MONITOR + #if (defined(__MACH__) || defined(__FreeBSD__) || defined(__linux__)) + static int StopMonitor(int mfd); + #else + #error "CRL monitor only currently supported on linux or mach" + #endif +#endif /* HAVE_CRL_MONITOR */ + + +/* Initialize CRL members */ +int InitCRL(WOLFSSL_CRL* crl, WOLFSSL_CERT_MANAGER* cm) +{ + WOLFSSL_ENTER("InitCRL"); + if(cm != NULL) + crl->heap = cm->heap; + else + crl->heap = NULL; + crl->cm = cm; + crl->crlList = NULL; + crl->monitors[0].path = NULL; + crl->monitors[1].path = NULL; +#ifdef HAVE_CRL_MONITOR + crl->tid = 0; + crl->mfd = -1; /* mfd for bsd is kqueue fd, eventfd for linux */ + crl->setup = 0; /* thread setup done predicate */ + if (pthread_cond_init(&crl->cond, 0) != 0) { + WOLFSSL_MSG("Pthread condition init failed"); + return BAD_COND_E; + } +#endif + if (wc_InitMutex(&crl->crlLock) != 0) { + WOLFSSL_MSG("Init Mutex failed"); + return BAD_MUTEX_E; + } + + return 0; +} + + +/* Initialize CRL Entry */ +static int InitCRL_Entry(CRL_Entry* crle, DecodedCRL* dcrl, const byte* buff, + int verified, void* heap) +{ + WOLFSSL_ENTER("InitCRL_Entry"); + + XMEMCPY(crle->issuerHash, dcrl->issuerHash, CRL_DIGEST_SIZE); + /* XMEMCPY(crle->crlHash, dcrl->crlHash, CRL_DIGEST_SIZE); + * copy the hash here if needed for optimized comparisons */ + XMEMCPY(crle->lastDate, dcrl->lastDate, MAX_DATE_SIZE); + XMEMCPY(crle->nextDate, dcrl->nextDate, MAX_DATE_SIZE); + crle->lastDateFormat = dcrl->lastDateFormat; + crle->nextDateFormat = dcrl->nextDateFormat; + + crle->certs = dcrl->certs; /* take ownsership */ + dcrl->certs = NULL; + crle->totalCerts = dcrl->totalCerts; + crle->verified = verified; + if (!verified) { + crle->tbsSz = dcrl->sigIndex - dcrl->certBegin; + crle->signatureSz = dcrl->sigLength; + crle->signatureOID = dcrl->signatureOID; + crle->toBeSigned = (byte*)XMALLOC(crle->tbsSz, heap, + DYNAMIC_TYPE_CRL_ENTRY); + if (crle->toBeSigned == NULL) + return -1; + crle->signature = (byte*)XMALLOC(crle->signatureSz, heap, + DYNAMIC_TYPE_CRL_ENTRY); + if (crle->signature == NULL) { + XFREE(crle->toBeSigned, heap, DYNAMIC_TYPE_CRL_ENTRY); + return -1; + } + XMEMCPY(crle->toBeSigned, buff + dcrl->certBegin, crle->tbsSz); + XMEMCPY(crle->signature, dcrl->signature, crle->signatureSz); + #if !defined(NO_SKID) && defined(CRL_SKID_READY) + crle->extAuthKeyIdSet = dcrl->extAuthKeyIdSet; + if (crle->extAuthKeyIdSet) + XMEMCPY(crle->extAuthKeyId, dcrl->extAuthKeyId, KEYID_SIZE); + #endif + } + else { + crle->toBeSigned = NULL; + crle->signature = NULL; + } + + (void)verified; + + return 0; +} + + +/* Free all CRL Entry resources */ +static void FreeCRL_Entry(CRL_Entry* crle, void* heap) +{ + RevokedCert* tmp = crle->certs; + RevokedCert* next; + + WOLFSSL_ENTER("FreeCRL_Entry"); + + while (tmp) { + next = tmp->next; + XFREE(tmp, heap, DYNAMIC_TYPE_REVOKED); + tmp = next; + } + if (crle->signature != NULL) + XFREE(crle->signature, heap, DYNAMIC_TYPE_REVOKED); + if (crle->toBeSigned != NULL) + XFREE(crle->toBeSigned, heap, DYNAMIC_TYPE_REVOKED); + + (void)heap; +} + + + +/* Free all CRL resources */ +void FreeCRL(WOLFSSL_CRL* crl, int dynamic) +{ + CRL_Entry* tmp = crl->crlList; + + WOLFSSL_ENTER("FreeCRL"); + if (crl->monitors[0].path) + XFREE(crl->monitors[0].path, crl->heap, DYNAMIC_TYPE_CRL_MONITOR); + + if (crl->monitors[1].path) + XFREE(crl->monitors[1].path, crl->heap, DYNAMIC_TYPE_CRL_MONITOR); + + while(tmp) { + CRL_Entry* next = tmp->next; + FreeCRL_Entry(tmp, crl->heap); + XFREE(tmp, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); + tmp = next; + } + +#ifdef HAVE_CRL_MONITOR + if (crl->tid != 0) { + WOLFSSL_MSG("stopping monitor thread"); + if (StopMonitor(crl->mfd) == 0) + pthread_join(crl->tid, NULL); + else { + WOLFSSL_MSG("stop monitor failed"); + } + } + pthread_cond_destroy(&crl->cond); +#endif + wc_FreeMutex(&crl->crlLock); + if (dynamic) /* free self */ + XFREE(crl, crl->heap, DYNAMIC_TYPE_CRL); +} + + +static int CheckCertCRLList(WOLFSSL_CRL* crl, DecodedCert* cert, int *pFoundEntry) +{ + CRL_Entry* crle; + int foundEntry = 0; + int ret = 0; + + if (wc_LockMutex(&crl->crlLock) != 0) { + WOLFSSL_MSG("wc_LockMutex failed"); + return BAD_MUTEX_E; + } + + crle = crl->crlList; + + while (crle) { + if (XMEMCMP(crle->issuerHash, cert->issuerHash, CRL_DIGEST_SIZE) == 0) { + int doNextDate = 1; + + WOLFSSL_MSG("Found CRL Entry on list"); + + if (crle->verified == 0) { + Signer* ca; + #if !defined(NO_SKID) && defined(CRL_SKID_READY) + byte extAuthKeyId[KEYID_SIZE] + #endif + byte issuerHash[CRL_DIGEST_SIZE]; + byte* tbs = NULL; + word32 tbsSz = crle->tbsSz; + byte* sig = NULL; + word32 sigSz = crle->signatureSz; + word32 sigOID = crle->signatureOID; + SignatureCtx sigCtx; + + tbs = (byte*)XMALLOC(tbsSz, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); + if (tbs == NULL) { + wc_UnLockMutex(&crl->crlLock); + return MEMORY_E; + } + sig = (byte*)XMALLOC(sigSz, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); + if (sig == NULL) { + XFREE(tbs, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); + wc_UnLockMutex(&crl->crlLock); + return MEMORY_E; + } + + XMEMCPY(tbs, crle->toBeSigned, tbsSz); + XMEMCPY(sig, crle->signature, sigSz); + #if !defined(NO_SKID) && defined(CRL_SKID_READY) + XMEMCMPY(extAuthKeyId, crle->extAuthKeyId, + sizeof(extAuthKeyId)); + #endif + XMEMCPY(issuerHash, crle->issuerHash, sizeof(issuerHash)); + + wc_UnLockMutex(&crl->crlLock); + + #if !defined(NO_SKID) && defined(CRL_SKID_READY) + if (crle->extAuthKeyIdSet) + ca = GetCA(crl->cm, extAuthKeyId); + if (ca == NULL) + ca = GetCAByName(crl->cm, issuerHash); + #else /* NO_SKID */ + ca = GetCA(crl->cm, issuerHash); + #endif /* NO_SKID */ + if (ca == NULL) { + XFREE(sig, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); + XFREE(tbs, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); + WOLFSSL_MSG("Did NOT find CRL issuer CA"); + return ASN_CRL_NO_SIGNER_E; + } + + ret = VerifyCRL_Signature(&sigCtx, tbs, tbsSz, sig, sigSz, + sigOID, ca, crl->heap); + + XFREE(sig, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); + XFREE(tbs, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); + + if (wc_LockMutex(&crl->crlLock) != 0) { + WOLFSSL_MSG("wc_LockMutex failed"); + return BAD_MUTEX_E; + } + + crle = crl->crlList; + while (crle) { + if (XMEMCMP(crle->issuerHash, cert->issuerHash, + CRL_DIGEST_SIZE) == 0) { + + if (ret == 0) + crle->verified = 1; + else + crle->verified = ret; + + XFREE(crle->toBeSigned, crl->heap, + DYNAMIC_TYPE_CRL_ENTRY); + crle->toBeSigned = NULL; + XFREE(crle->signature, crl->heap, + DYNAMIC_TYPE_CRL_ENTRY); + crle->signature = NULL; + break; + } + crle = crle->next; + } + if (crle == NULL || crle->verified < 0) + break; + } + else if (crle->verified < 0) { + WOLFSSL_MSG("Cannot use CRL as it didn't verify"); + ret = crle->verified; + break; + } + + WOLFSSL_MSG("Checking next date validity"); + + #ifdef WOLFSSL_NO_CRL_NEXT_DATE + if (crle->nextDateFormat == ASN_OTHER_TYPE) + doNextDate = 0; /* skip */ + #endif + + if (doNextDate) { + #ifndef NO_ASN_TIME + if (!XVALIDATE_DATE(crle->nextDate,crle->nextDateFormat, AFTER)) { + WOLFSSL_MSG("CRL next date is no longer valid"); + ret = ASN_AFTER_DATE_E; + } + #endif + } + if (ret == 0) { + foundEntry = 1; + } + break; + } + crle = crle->next; + } + + if (foundEntry) { + RevokedCert* rc = crle->certs; + + while (rc) { + if (rc->serialSz == cert->serialSz && + XMEMCMP(rc->serialNumber, cert->serial, rc->serialSz) == 0) { + WOLFSSL_MSG("Cert revoked"); + ret = CRL_CERT_REVOKED; + break; + } + rc = rc->next; + } + } + + wc_UnLockMutex(&crl->crlLock); + + *pFoundEntry = foundEntry; + + return ret; +} + +/* Is the cert ok with CRL, return 0 on success */ +int CheckCertCRL(WOLFSSL_CRL* crl, DecodedCert* cert) +{ + int foundEntry = 0; + int ret = 0; + + WOLFSSL_ENTER("CheckCertCRL"); + + ret = CheckCertCRLList(crl, cert, &foundEntry); + +#ifdef HAVE_CRL_IO + if (foundEntry == 0) { + /* perform embedded lookup */ + if (crl->crlIOCb) { + ret = crl->crlIOCb(crl, (const char*)cert->extCrlInfo, + cert->extCrlInfoSz); + if (ret == WOLFSSL_CBIO_ERR_WANT_READ) { + ret = WANT_READ; + } + else if (ret >= 0) { + /* try again */ + ret = CheckCertCRLList(crl, cert, &foundEntry); + } + } + } +#endif + + if (foundEntry == 0) { + WOLFSSL_MSG("Couldn't find CRL for status check"); + ret = CRL_MISSING; + + if (crl->cm->cbMissingCRL) { + char url[256]; + + WOLFSSL_MSG("Issuing missing CRL callback"); + url[0] = '\0'; + if (cert->extCrlInfo) { + if (cert->extCrlInfoSz < (int)sizeof(url) -1 ) { + XMEMCPY(url, cert->extCrlInfo, cert->extCrlInfoSz); + url[cert->extCrlInfoSz] = '\0'; + } + else { + WOLFSSL_MSG("CRL url too long"); + } + } + + crl->cm->cbMissingCRL(url); + } + } + + return ret; +} + + +/* Add Decoded CRL, 0 on success */ +static int AddCRL(WOLFSSL_CRL* crl, DecodedCRL* dcrl, const byte* buff, + int verified) +{ + CRL_Entry* crle; + + WOLFSSL_ENTER("AddCRL"); + + crle = (CRL_Entry*)XMALLOC(sizeof(CRL_Entry), crl->heap, DYNAMIC_TYPE_CRL_ENTRY); + if (crle == NULL) { + WOLFSSL_MSG("alloc CRL Entry failed"); + return -1; + } + + if (InitCRL_Entry(crle, dcrl, buff, verified, crl->heap) < 0) { + WOLFSSL_MSG("Init CRL Entry failed"); + XFREE(crle, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); + return -1; + } + + if (wc_LockMutex(&crl->crlLock) != 0) { + WOLFSSL_MSG("wc_LockMutex failed"); + FreeCRL_Entry(crle, crl->heap); + XFREE(crle, crl->heap, DYNAMIC_TYPE_CRL_ENTRY); + return BAD_MUTEX_E; + } + crle->next = crl->crlList; + crl->crlList = crle; + wc_UnLockMutex(&crl->crlLock); + + return 0; +} + + +/* Load CRL File of type, WOLFSSL_SUCCESS on ok */ +int BufferLoadCRL(WOLFSSL_CRL* crl, const byte* buff, long sz, int type, + int noVerify) +{ + int ret = WOLFSSL_SUCCESS; + const byte* myBuffer = buff; /* if DER ok, otherwise switch */ + DerBuffer* der = NULL; +#ifdef WOLFSSL_SMALL_STACK + DecodedCRL* dcrl; +#else + DecodedCRL dcrl[1]; +#endif + + WOLFSSL_ENTER("BufferLoadCRL"); + + if (crl == NULL || buff == NULL || sz == 0) + return BAD_FUNC_ARG; + + if (type == WOLFSSL_FILETYPE_PEM) { + #ifdef WOLFSSL_PEM_TO_DER + ret = PemToDer(buff, sz, CRL_TYPE, &der, NULL, NULL, NULL); + if (ret == 0) { + myBuffer = der->buffer; + sz = der->length; + } + else { + WOLFSSL_MSG("Pem to Der failed"); + FreeDer(&der); + return -1; + } + #else + ret = NOT_COMPILED_IN; + #endif + } + +#ifdef WOLFSSL_SMALL_STACK + dcrl = (DecodedCRL*)XMALLOC(sizeof(DecodedCRL), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (dcrl == NULL) { + FreeDer(&der); + return MEMORY_E; + } +#endif + + InitDecodedCRL(dcrl, crl->heap); + ret = ParseCRL(dcrl, myBuffer, (word32)sz, crl->cm); + if (ret != 0 && !(ret == ASN_CRL_NO_SIGNER_E && noVerify)) { + WOLFSSL_MSG("ParseCRL error"); + } + else { + ret = AddCRL(crl, dcrl, myBuffer, ret != ASN_CRL_NO_SIGNER_E); + if (ret != 0) { + WOLFSSL_MSG("AddCRL error"); + } + } + + FreeDecodedCRL(dcrl); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(dcrl, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + FreeDer(&der); + + return ret ? ret : WOLFSSL_SUCCESS; /* convert 0 to WOLFSSL_SUCCESS */ +} + +#if defined(OPENSSL_EXTRA) && defined(HAVE_CRL) +int wolfSSL_X509_STORE_add_crl(WOLFSSL_X509_STORE *store, WOLFSSL_X509_CRL *newcrl) +{ + CRL_Entry *crle; + WOLFSSL_CRL *crl; + + WOLFSSL_ENTER("wolfSSL_X509_STORE_add_crl"); + if (store == NULL || newcrl == NULL) + return BAD_FUNC_ARG; + + crl = store->crl; + crle = newcrl->crlList; + + if (wc_LockMutex(&crl->crlLock) != 0) + { + WOLFSSL_MSG("wc_LockMutex failed"); + return BAD_MUTEX_E; + } + crle->next = crl->crlList; + crl->crlList = crle; + newcrl->crlList = NULL; + wc_UnLockMutex(&crl->crlLock); + + WOLFSSL_LEAVE("wolfSSL_X509_STORE_add_crl", WOLFSSL_SUCCESS); + + return WOLFSSL_SUCCESS; +} +#endif + +#ifdef HAVE_CRL_MONITOR + + +/* Signal Monitor thread is setup, save status to setup flag, 0 on success */ +static int SignalSetup(WOLFSSL_CRL* crl, int status) +{ + int ret; + + /* signal to calling thread we're setup */ + if (wc_LockMutex(&crl->crlLock) != 0) { + WOLFSSL_MSG("wc_LockMutex crlLock failed"); + return BAD_MUTEX_E; + } + + crl->setup = status; + ret = pthread_cond_signal(&crl->cond); + + wc_UnLockMutex(&crl->crlLock); + + if (ret != 0) + return BAD_COND_E; + + return 0; +} + + +/* read in new CRL entries and save new list */ +static int SwapLists(WOLFSSL_CRL* crl) +{ + int ret; + CRL_Entry* newList; +#ifdef WOLFSSL_SMALL_STACK + WOLFSSL_CRL* tmp; +#else + WOLFSSL_CRL tmp[1]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + tmp = (WOLFSSL_CRL*)XMALLOC(sizeof(WOLFSSL_CRL), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) + return MEMORY_E; +#endif + + if (InitCRL(tmp, crl->cm) < 0) { + WOLFSSL_MSG("Init tmp CRL failed"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return -1; + } + + if (crl->monitors[0].path) { + ret = LoadCRL(tmp, crl->monitors[0].path, WOLFSSL_FILETYPE_PEM, 0); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("PEM LoadCRL on dir change failed"); + FreeCRL(tmp, 0); +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return -1; + } + } + + if (crl->monitors[1].path) { + ret = LoadCRL(tmp, crl->monitors[1].path, WOLFSSL_FILETYPE_ASN1, 0); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("DER LoadCRL on dir change failed"); + FreeCRL(tmp, 0); +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return -1; + } + } + + if (wc_LockMutex(&crl->crlLock) != 0) { + WOLFSSL_MSG("wc_LockMutex failed"); + FreeCRL(tmp, 0); +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return -1; + } + + newList = tmp->crlList; + + /* swap lists */ + tmp->crlList = crl->crlList; + crl->crlList = newList; + + wc_UnLockMutex(&crl->crlLock); + + FreeCRL(tmp, 0); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return 0; +} + + +#if (defined(__MACH__) || defined(__FreeBSD__)) + +#include +#include +#include +#include +#include + +#ifdef __MACH__ + #define XEVENT_MODE O_EVTONLY +#elif defined(__FreeBSD__) + #define XEVENT_MODE EVFILT_VNODE +#endif + + +/* we need a unique kqueue user filter fd for crl in case user is doing custom + * events too */ +#ifndef CRL_CUSTOM_FD + #define CRL_CUSTOM_FD 123456 +#endif + + +/* shutdown monitor thread, 0 on success */ +static int StopMonitor(int mfd) +{ + struct kevent change; + + /* trigger custom shutdown */ + EV_SET(&change, CRL_CUSTOM_FD, EVFILT_USER, 0, NOTE_TRIGGER, 0, NULL); + if (kevent(mfd, &change, 1, NULL, 0, NULL) < 0) { + WOLFSSL_MSG("kevent trigger customer event failed"); + return -1; + } + + return 0; +} + + +/* OS X monitoring */ +static void* DoMonitor(void* arg) +{ + int fPEM, fDER; + struct kevent change; + + WOLFSSL_CRL* crl = (WOLFSSL_CRL*)arg; + + WOLFSSL_ENTER("DoMonitor"); + + crl->mfd = kqueue(); + if (crl->mfd == -1) { + WOLFSSL_MSG("kqueue failed"); + SignalSetup(crl, MONITOR_SETUP_E); + return NULL; + } + + /* listen for custom shutdown event */ + EV_SET(&change, CRL_CUSTOM_FD, EVFILT_USER, EV_ADD, 0, 0, NULL); + if (kevent(crl->mfd, &change, 1, NULL, 0, NULL) < 0) { + WOLFSSL_MSG("kevent monitor customer event failed"); + SignalSetup(crl, MONITOR_SETUP_E); + close(crl->mfd); + return NULL; + } + + fPEM = -1; + fDER = -1; + + if (crl->monitors[0].path) { + fPEM = open(crl->monitors[0].path, XEVENT_MODE); + if (fPEM == -1) { + WOLFSSL_MSG("PEM event dir open failed"); + SignalSetup(crl, MONITOR_SETUP_E); + close(crl->mfd); + return NULL; + } + } + + if (crl->monitors[1].path) { + fDER = open(crl->monitors[1].path, XEVENT_MODE); + if (fDER == -1) { + WOLFSSL_MSG("DER event dir open failed"); + if (fPEM != -1) + close(fPEM); + close(crl->mfd); + SignalSetup(crl, MONITOR_SETUP_E); + return NULL; + } + } + + if (fPEM != -1) + EV_SET(&change, fPEM, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_ONESHOT, + NOTE_DELETE | NOTE_EXTEND | NOTE_WRITE | NOTE_ATTRIB, 0, 0); + + if (fDER != -1) + EV_SET(&change, fDER, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_ONESHOT, + NOTE_DELETE | NOTE_EXTEND | NOTE_WRITE | NOTE_ATTRIB, 0, 0); + + /* signal to calling thread we're setup */ + if (SignalSetup(crl, 1) != 0) { + if (fPEM != -1) + close(fPEM); + if (fDER != -1) + close(fDER); + close(crl->mfd); + return NULL; + } + + for (;;) { + struct kevent event; + int numEvents = kevent(crl->mfd, &change, 1, &event, 1, NULL); + + WOLFSSL_MSG("Got kevent"); + + if (numEvents == -1) { + WOLFSSL_MSG("kevent problem, continue"); + continue; + } + + if (event.filter == EVFILT_USER) { + WOLFSSL_MSG("Got user shutdown event, breaking out"); + break; + } + + if (SwapLists(crl) < 0) { + WOLFSSL_MSG("SwapLists problem, continue"); + } + } + + if (fPEM != -1) + close(fPEM); + if (fDER != -1) + close(fDER); + + close(crl->mfd); + + return NULL; +} + + +#elif defined(__linux__) + +#include +#include +#include +#include + + +#ifndef max + static WC_INLINE int max(int a, int b) + { + return a > b ? a : b; + } +#endif /* max */ + + +/* shutdown monitor thread, 0 on success */ +static int StopMonitor(int mfd) +{ + word64 w64 = 1; + + /* write to our custom event */ + if (write(mfd, &w64, sizeof(w64)) < 0) { + WOLFSSL_MSG("StopMonitor write failed"); + return -1; + } + + return 0; +} + + +/* linux monitoring */ +static void* DoMonitor(void* arg) +{ + int notifyFd; + int wd = -1; + WOLFSSL_CRL* crl = (WOLFSSL_CRL*)arg; +#ifdef WOLFSSL_SMALL_STACK + char* buff; +#else + char buff[8192]; +#endif + + WOLFSSL_ENTER("DoMonitor"); + + crl->mfd = eventfd(0, 0); /* our custom shutdown event */ + if (crl->mfd < 0) { + WOLFSSL_MSG("eventfd failed"); + SignalSetup(crl, MONITOR_SETUP_E); + return NULL; + } + + notifyFd = inotify_init(); + if (notifyFd < 0) { + WOLFSSL_MSG("inotify failed"); + close(crl->mfd); + SignalSetup(crl, MONITOR_SETUP_E); + return NULL; + } + + if (crl->monitors[0].path) { + wd = inotify_add_watch(notifyFd, crl->monitors[0].path, IN_CLOSE_WRITE | + IN_DELETE); + if (wd < 0) { + WOLFSSL_MSG("PEM notify add watch failed"); + close(crl->mfd); + close(notifyFd); + SignalSetup(crl, MONITOR_SETUP_E); + return NULL; + } + } + + if (crl->monitors[1].path) { + wd = inotify_add_watch(notifyFd, crl->monitors[1].path, IN_CLOSE_WRITE | + IN_DELETE); + if (wd < 0) { + WOLFSSL_MSG("DER notify add watch failed"); + close(crl->mfd); + close(notifyFd); + SignalSetup(crl, MONITOR_SETUP_E); + return NULL; + } + } + +#ifdef WOLFSSL_SMALL_STACK + buff = (char*)XMALLOC(8192, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (buff == NULL) + return NULL; +#endif + + /* signal to calling thread we're setup */ + if (SignalSetup(crl, 1) != 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + if (wd > 0) + inotify_rm_watch(notifyFd, wd); + close(crl->mfd); + close(notifyFd); + return NULL; + } + + for (;;) { + fd_set readfds; + int result; + int length; + + FD_ZERO(&readfds); + FD_SET(notifyFd, &readfds); + FD_SET(crl->mfd, &readfds); + + result = select(max(notifyFd, crl->mfd) + 1, &readfds, NULL, NULL,NULL); + + WOLFSSL_MSG("Got notify event"); + + if (result < 0) { + WOLFSSL_MSG("select problem, continue"); + continue; + } + + if (FD_ISSET(crl->mfd, &readfds)) { + WOLFSSL_MSG("got custom shutdown event, breaking out"); + break; + } + + length = (int) read(notifyFd, buff, 8192); + if (length < 0) { + WOLFSSL_MSG("notify read problem, continue"); + continue; + } + + if (SwapLists(crl) < 0) { + WOLFSSL_MSG("SwapLists problem, continue"); + } + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + if (wd > 0) + inotify_rm_watch(notifyFd, wd); + close(crl->mfd); + close(notifyFd); + + return NULL; +} + +#endif /* MACH or linux */ + + +/* Start Monitoring the CRL path(s) in a thread */ +static int StartMonitorCRL(WOLFSSL_CRL* crl) +{ + int ret = WOLFSSL_SUCCESS; + + WOLFSSL_ENTER("StartMonitorCRL"); + + if (crl == NULL) + return BAD_FUNC_ARG; + + if (crl->tid != 0) { + WOLFSSL_MSG("Monitor thread already running"); + return ret; /* that's ok, someone already started */ + } + + if (pthread_create(&crl->tid, NULL, DoMonitor, crl) != 0) { + WOLFSSL_MSG("Thread creation error"); + return THREAD_CREATE_E; + } + + /* wait for setup to complete */ + if (wc_LockMutex(&crl->crlLock) != 0) { + WOLFSSL_MSG("wc_LockMutex crlLock error"); + return BAD_MUTEX_E; + } + + while (crl->setup == 0) { + if (pthread_cond_wait(&crl->cond, &crl->crlLock) != 0) { + ret = BAD_COND_E; + break; + } + } + + if (crl->setup < 0) + ret = crl->setup; /* store setup error */ + + wc_UnLockMutex(&crl->crlLock); + + if (ret < 0) { + WOLFSSL_MSG("DoMonitor setup failure"); + crl->tid = 0; /* thread already done */ + } + + return ret; +} + + +#else /* HAVE_CRL_MONITOR */ + +#ifndef NO_FILESYSTEM + +static int StartMonitorCRL(WOLFSSL_CRL* crl) +{ + (void)crl; + + WOLFSSL_ENTER("StartMonitorCRL"); + WOLFSSL_MSG("Not compiled in"); + + return NOT_COMPILED_IN; +} + +#endif /* NO_FILESYSTEM */ + +#endif /* HAVE_CRL_MONITOR */ + +#if !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) + +/* Load CRL path files of type, WOLFSSL_SUCCESS on ok */ +int LoadCRL(WOLFSSL_CRL* crl, const char* path, int type, int monitor) +{ + int ret = WOLFSSL_SUCCESS; + char* name = NULL; +#ifdef WOLFSSL_SMALL_STACK + ReadDirCtx* readCtx = NULL; +#else + ReadDirCtx readCtx[1]; +#endif + + WOLFSSL_ENTER("LoadCRL"); + if (crl == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_SMALL_STACK + readCtx = (ReadDirCtx*)XMALLOC(sizeof(ReadDirCtx), crl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (readCtx == NULL) + return MEMORY_E; +#endif + + /* try to load each regular file in path */ + ret = wc_ReadDirFirst(readCtx, path, &name); + while (ret == 0 && name) { + int skip = 0; + if (type == WOLFSSL_FILETYPE_PEM) { + if (XSTRSTR(name, ".pem") == NULL) { + WOLFSSL_MSG("not .pem file, skipping"); + skip = 1; + } + } + else { + if (XSTRSTR(name, ".der") == NULL && + XSTRSTR(name, ".crl") == NULL) + { + WOLFSSL_MSG("not .der or .crl file, skipping"); + skip = 1; + } + } + + if (!skip && ProcessFile(NULL, name, type, CRL_TYPE, NULL, 0, crl) + != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("CRL file load failed, continuing"); + } + + ret = wc_ReadDirNext(readCtx, path, &name); + } + wc_ReadDirClose(readCtx); + ret = WOLFSSL_SUCCESS; /* load failures not reported, for backwards compat */ + +#ifdef WOLFSSL_SMALL_STACK + XFREE(readCtx, crl->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + if (monitor & WOLFSSL_CRL_MONITOR) { + word32 pathLen; + char* pathBuf; + + WOLFSSL_MSG("monitor path requested"); + + pathLen = (word32)XSTRLEN(path); + pathBuf = (char*)XMALLOC(pathLen+1, crl->heap,DYNAMIC_TYPE_CRL_MONITOR); + if (pathBuf) { + XSTRNCPY(pathBuf, path, pathLen+1); + + if (type == WOLFSSL_FILETYPE_PEM) { + /* free old path before setting a new one */ + if (crl->monitors[0].path) { + XFREE(crl->monitors[0].path, crl->heap, + DYNAMIC_TYPE_CRL_MONITOR); + } + crl->monitors[0].path = pathBuf; + crl->monitors[0].type = WOLFSSL_FILETYPE_PEM; + } else { + /* free old path before setting a new one */ + if (crl->monitors[1].path) { + XFREE(crl->monitors[1].path, crl->heap, + DYNAMIC_TYPE_CRL_MONITOR); + } + crl->monitors[1].path = pathBuf; + crl->monitors[1].type = WOLFSSL_FILETYPE_ASN1; + } + + if (monitor & WOLFSSL_CRL_START_MON) { + WOLFSSL_MSG("start monitoring requested"); + + ret = StartMonitorCRL(crl); + } + } + else { + ret = MEMORY_E; + } + } + + return ret; +} + +#else +int LoadCRL(WOLFSSL_CRL* crl, const char* path, int type, int monitor) +{ + (void)crl; + (void)path; + (void)type; + (void)monitor; + + /* stub for scenario where file system is not supported */ + return NOT_COMPILED_IN; +} +#endif /* !NO_FILESYSTEM && !NO_WOLFSSL_DIR */ + +#endif /* HAVE_CRL */ +#endif /* !WOLFCRYPT_ONLY */ diff --git a/beken_os/beken378/func/wolfssl/src/include.am b/beken_os/beken378/func/wolfssl/src/include.am new file mode 100755 index 0000000..de5ce74 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/src/include.am @@ -0,0 +1,467 @@ +# vim:ft=automake +# included from Top Level Makefile.am +# All paths should be given relative to the root + +lib_LTLIBRARIES+= src/libwolfssl.la +src_libwolfssl_la_SOURCES = +src_libwolfssl_la_LDFLAGS = ${AM_LDFLAGS} -no-undefined -version-info ${WOLFSSL_LIBRARY_VERSION} +src_libwolfssl_la_LIBADD = $(LIBM) $(LIB_ADD) $(LIB_STATIC_ADD) +src_libwolfssl_la_CFLAGS = -DBUILDING_WOLFSSL $(AM_CFLAGS) +src_libwolfssl_la_CPPFLAGS = -DBUILDING_WOLFSSL $(AM_CPPFLAGS) + +# install the packaged IPP libraries +if BUILD_FAST_RSA + +# Link needed IPP libraries +noinst_SCRIPTS+=IPP_links +IPP_links: + @$(IPPLINK) + +ippdir = $(libdir) +ipp_DATA = $(IPPLIBS) + +include_HEADERS+=$(IPPHEADERS) +endif # BUILD_FAST_RSA + +if BUILD_FIPS +if !BUILD_FIPS_V2 +# fips first file +src_libwolfssl_la_SOURCES += ctaocrypt/src/wolfcrypt_first.c + +src_libwolfssl_la_SOURCES += \ + ctaocrypt/src/hmac.c \ + ctaocrypt/src/random.c \ + ctaocrypt/src/sha256.c + +if BUILD_RSA +src_libwolfssl_la_SOURCES += ctaocrypt/src/rsa.c +endif + +if BUILD_AES +src_libwolfssl_la_SOURCES += ctaocrypt/src/aes.c +endif + +if BUILD_DES3 +src_libwolfssl_la_SOURCES += ctaocrypt/src/des3.c +endif + +if BUILD_SHA +src_libwolfssl_la_SOURCES += ctaocrypt/src/sha.c +endif + +if BUILD_SHA512 +src_libwolfssl_la_SOURCES += ctaocrypt/src/sha512.c +endif + +src_libwolfssl_la_SOURCES += ctaocrypt/src/fips.c +src_libwolfssl_la_SOURCES += ctaocrypt/src/fips_test.c + +# fips last file +src_libwolfssl_la_SOURCES += ctaocrypt/src/wolfcrypt_last.c + +else + +# FIPSv2 first file +src_libwolfssl_la_SOURCES += \ + wolfcrypt/src/wolfcrypt_first.c + +src_libwolfssl_la_SOURCES += \ + wolfcrypt/src/hmac.c \ + wolfcrypt/src/random.c \ + wolfcrypt/src/sha256.c + +if BUILD_RSA +src_libwolfssl_la_SOURCES += wolfcrypt/src/rsa.c +endif + +if BUILD_ECC +src_libwolfssl_la_SOURCES += wolfcrypt/src/ecc.c +endif + +if BUILD_AES +src_libwolfssl_la_SOURCES += wolfcrypt/src/aes.c +endif + +if BUILD_AESNI +src_libwolfssl_la_SOURCES += wolfcrypt/src/aes_asm.S +endif + +if BUILD_DES3 +src_libwolfssl_la_SOURCES += wolfcrypt/src/des3.c +endif + +if BUILD_SHA +src_libwolfssl_la_SOURCES += wolfcrypt/src/sha.c +endif + +if BUILD_SHA512 +src_libwolfssl_la_SOURCES += wolfcrypt/src/sha512.c +endif + +if BUILD_SHA3 +src_libwolfssl_la_SOURCES += wolfcrypt/src/sha3.c +endif + +if BUILD_DH +src_libwolfssl_la_SOURCES += wolfcrypt/src/dh.c +endif + +if BUILD_CMAC +src_libwolfssl_la_SOURCES += wolfcrypt/src/cmac.c +endif + +src_libwolfssl_la_SOURCES += wolfcrypt/src/fips.c \ + wolfcrypt/src/fips_test.c + +# fips last file +src_libwolfssl_la_SOURCES += wolfcrypt/src/wolfcrypt_last.c +endif +endif + +# For FIPSV2, exclude the wolfCrypt files included above. +# For old FIPS, keep the wolfCrypt versions of the +# CtaoCrypt files included above. +if !BUILD_FIPS_V2 +src_libwolfssl_la_SOURCES += wolfcrypt/src/hmac.c +endif + +# CAVP self test +if BUILD_SELFTEST +src_libwolfssl_la_SOURCES += wolfcrypt/src/selftest.c +endif + +src_libwolfssl_la_SOURCES += \ + wolfcrypt/src/hash.c \ + wolfcrypt/src/cpuid.c + +if !BUILD_FIPS_V2 +if BUILD_RNG +src_libwolfssl_la_SOURCES += wolfcrypt/src/random.c +endif +endif + +if !BUILD_FIPS_V2 +if BUILD_ARMASM +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/arm/armv8-sha256.c +else +src_libwolfssl_la_SOURCES += wolfcrypt/src/sha256.c +if BUILD_INTELASM +src_libwolfssl_la_SOURCES += wolfcrypt/src/sha256_asm.S +endif +endif +endif + +if BUILD_AFALG +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/af_alg/afalg_hash.c +endif + +if BUILD_WOLFEVENT +src_libwolfssl_la_SOURCES += wolfcrypt/src/wolfevent.c +endif + +if BUILD_ASYNCCRYPT +src_libwolfssl_la_SOURCES += wolfcrypt/src/async.c +endif + +if !BUILD_USER_RSA +if BUILD_RSA +if BUILD_FAST_RSA +src_libwolfssl_la_SOURCES += wolfcrypt/user-crypto/src/rsa.c +else +if !BUILD_FIPS_V2 +src_libwolfssl_la_SOURCES += wolfcrypt/src/rsa.c +endif +endif +endif +endif + +if BUILD_SP +if BUILD_SP_C +src_libwolfssl_la_SOURCES += wolfcrypt/src/sp_c32.c +src_libwolfssl_la_SOURCES += wolfcrypt/src/sp_c64.c +endif +if BUILD_SP_X86_64 +src_libwolfssl_la_SOURCES += wolfcrypt/src/sp_x86_64.c +src_libwolfssl_la_SOURCES += wolfcrypt/src/sp_x86_64_asm.S +endif +if BUILD_SP_ARM32 +src_libwolfssl_la_SOURCES += wolfcrypt/src/sp_arm32.c +endif +if BUILD_SP_ARM_THUMB +src_libwolfssl_la_SOURCES += wolfcrypt/src/sp_armthumb.c +endif +if BUILD_SP_ARM64 +src_libwolfssl_la_SOURCES += wolfcrypt/src/sp_arm64.c +endif +if BUILD_SP_INT +src_libwolfssl_la_SOURCES += wolfcrypt/src/sp_int.c +endif +if BUILD_SP_ARM_CORTEX +src_libwolfssl_la_SOURCES += wolfcrypt/src/sp_cortexm.c +endif +endif + +if !BUILD_FIPS_V2 +if BUILD_AES +src_libwolfssl_la_SOURCES += wolfcrypt/src/aes.c +if BUILD_ARMASM +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/arm/armv8-aes.c +endif +if BUILD_AFALG +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/af_alg/afalg_aes.c +endif +endif +endif + +if !BUILD_FIPS_V2 +if BUILD_CMAC +src_libwolfssl_la_SOURCES += wolfcrypt/src/cmac.c +endif +endif + +if !BUILD_FIPS_V2 +if BUILD_DES3 +src_libwolfssl_la_SOURCES += wolfcrypt/src/des3.c +endif +endif + +if !BUILD_FIPS_V2 +if BUILD_SHA +src_libwolfssl_la_SOURCES += wolfcrypt/src/sha.c +endif +endif + +if !BUILD_FIPS_V2 +if BUILD_SHA512 +if BUILD_ARMASM +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/arm/armv8-sha512.c +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/arm/armv8-sha512-asm.S +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/arm/armv8-32-sha512-asm.S +else +src_libwolfssl_la_SOURCES += wolfcrypt/src/sha512.c +if BUILD_INTELASM +src_libwolfssl_la_SOURCES += wolfcrypt/src/sha512_asm.S +endif +endif +endif +endif + +if !BUILD_FIPS_V2 +if BUILD_SHA3 +src_libwolfssl_la_SOURCES += wolfcrypt/src/sha3.c +endif +endif + +src_libwolfssl_la_SOURCES += \ + wolfcrypt/src/logging.c \ + wolfcrypt/src/wc_encrypt.c \ + wolfcrypt/src/wc_port.c \ + wolfcrypt/src/error.c \ + wolfcrypt/src/signature.c \ + wolfcrypt/src/wolfmath.c + +if BUILD_MEMORY +src_libwolfssl_la_SOURCES += wolfcrypt/src/memory.c +endif + +if !BUILD_FIPS_V2 +if BUILD_DH +src_libwolfssl_la_SOURCES += wolfcrypt/src/dh.c +endif +endif + +if BUILD_ASN +src_libwolfssl_la_SOURCES += wolfcrypt/src/asn.c +endif + +if BUILD_CODING +src_libwolfssl_la_SOURCES += wolfcrypt/src/coding.c +endif + +if BUILD_POLY1305 +if BUILD_ARMASM +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/arm/armv8-poly1305.c +endif +src_libwolfssl_la_SOURCES += wolfcrypt/src/poly1305.c +if BUILD_INTELASM +src_libwolfssl_la_SOURCES += wolfcrypt/src/poly1305_asm.S +endif +endif + +if BUILD_RC4 +src_libwolfssl_la_SOURCES += wolfcrypt/src/arc4.c +endif + +if BUILD_MD4 +src_libwolfssl_la_SOURCES += wolfcrypt/src/md4.c +endif + +if BUILD_MD5 +src_libwolfssl_la_SOURCES += wolfcrypt/src/md5.c +endif + +if BUILD_PWDBASED +src_libwolfssl_la_SOURCES += wolfcrypt/src/pwdbased.c +src_libwolfssl_la_SOURCES += wolfcrypt/src/pkcs12.c +endif + +if BUILD_DSA +src_libwolfssl_la_SOURCES += wolfcrypt/src/dsa.c +endif + +if !BUILD_FIPS_V2 +if BUILD_AESNI +src_libwolfssl_la_SOURCES += wolfcrypt/src/aes_asm.S +src_libwolfssl_la_SOURCES += wolfcrypt/src/aes_gcm_asm.S +endif +endif + +if BUILD_CAMELLIA +src_libwolfssl_la_SOURCES += wolfcrypt/src/camellia.c +endif + +if BUILD_MD2 +src_libwolfssl_la_SOURCES += wolfcrypt/src/md2.c +endif + +if BUILD_RIPEMD +src_libwolfssl_la_SOURCES += wolfcrypt/src/ripemd.c +endif + +if BUILD_BLAKE2 +src_libwolfssl_la_SOURCES += wolfcrypt/src/blake2b.c +endif +if BUILD_BLAKE2S +src_libwolfssl_la_SOURCES += wolfcrypt/src/blake2s.c +endif + +if BUILD_HC128 +src_libwolfssl_la_SOURCES += wolfcrypt/src/hc128.c +endif + +if BUILD_RABBIT +src_libwolfssl_la_SOURCES += wolfcrypt/src/rabbit.c +endif + +if BUILD_CHACHA +if BUILD_ARMASM +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/arm/armv8-chacha.c +else +src_libwolfssl_la_SOURCES += wolfcrypt/src/chacha.c +if BUILD_INTELASM +src_libwolfssl_la_SOURCES += wolfcrypt/src/chacha_asm.S +endif +endif +if BUILD_POLY1305 +src_libwolfssl_la_SOURCES += wolfcrypt/src/chacha20_poly1305.c +endif +endif + +if !BUILD_INLINE +src_libwolfssl_la_SOURCES += wolfcrypt/src/misc.c +endif + +if BUILD_FASTMATH +src_libwolfssl_la_SOURCES += wolfcrypt/src/tfm.c +endif + +if BUILD_SLOWMATH +src_libwolfssl_la_SOURCES += wolfcrypt/src/integer.c +endif + +if !BUILD_FIPS_V2 +if BUILD_ECC +src_libwolfssl_la_SOURCES += wolfcrypt/src/ecc.c +endif +endif + +if BUILD_CURVE25519 +src_libwolfssl_la_SOURCES += wolfcrypt/src/curve25519.c +endif + +if BUILD_ED25519 +src_libwolfssl_la_SOURCES += wolfcrypt/src/ed25519.c +endif + +if BUILD_FEMATH +if BUILD_CURVE25519_SMALL +src_libwolfssl_la_SOURCES += wolfcrypt/src/fe_low_mem.c +else +if BUILD_INTELASM +src_libwolfssl_la_SOURCES += wolfcrypt/src/fe_x25519_asm.S +else +if BUILD_ARMASM +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/arm/armv8-32-curve25519.S +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/arm/armv8-curve25519.S +else +src_libwolfssl_la_SOURCES += wolfcrypt/src/fe_operations.c +endif +endif +endif +endif + +if BUILD_GEMATH +if BUILD_ED25519_SMALL +src_libwolfssl_la_SOURCES += wolfcrypt/src/ge_low_mem.c +else +src_libwolfssl_la_SOURCES += wolfcrypt/src/ge_operations.c +if !BUILD_FEMATH +if BUILD_INTELASM +src_libwolfssl_la_SOURCES += wolfcrypt/src/fe_x25519_asm.S +else +if BUILD_ARMASM +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/arm/armv8-curve25519.S +else +src_libwolfssl_la_SOURCES += wolfcrypt/src/fe_operations.c +endif +endif +endif +endif +endif + +if BUILD_LIBZ +src_libwolfssl_la_SOURCES += wolfcrypt/src/compress.c +endif + +if BUILD_PKCS7 +src_libwolfssl_la_SOURCES += wolfcrypt/src/pkcs7.c +endif + +if BUILD_SRP +src_libwolfssl_la_SOURCES += wolfcrypt/src/srp.c +endif + +if BUILD_IDEA +src_libwolfssl_la_SOURCES += wolfcrypt/src/idea.c +endif + +if BUILD_AFALG +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/af_alg/wc_afalg.c +endif + +if !BUILD_CRYPTONLY +# ssl files +src_libwolfssl_la_SOURCES += \ + src/internal.c \ + src/wolfio.c \ + src/keys.c \ + src/ssl.c \ + src/tls.c + +if BUILD_TLS13 +src_libwolfssl_la_SOURCES += src/tls13.c +endif + +if BUILD_OCSP +src_libwolfssl_la_SOURCES += src/ocsp.c +endif + +if BUILD_CRL +src_libwolfssl_la_SOURCES += src/crl.c +endif + +if BUILD_SNIFFER +src_libwolfssl_la_SOURCES += src/sniffer.c +endif + +endif # !BUILD_CRYPTONLY diff --git a/beken_os/beken378/func/wolfssl/src/internal.c b/beken_os/beken378/func/wolfssl/src/internal.c new file mode 100755 index 0000000..64b16c4 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/src/internal.c @@ -0,0 +1,26641 @@ +/* internal.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +/* + * WOLFSSL_SMALL_CERT_VERIFY: + * Verify the certificate signature without using DecodedCert. Doubles up + * on some code but allows smaller peak heap memory usage. + * Cannot be used with WOLFSSL_NONBLOCK_OCSP. + * WOLFSSL_ALT_CERT_CHAINS: + * Allows CA's to be presented by peer, but not part of a valid chain. + * Default wolfSSL behavior is to require validation of all presented peer + * certificates. This also allows loading intermediate CA's as trusted + * and ignoring no signer failures for CA's up the chain to root. + */ + +#ifndef WOLFCRYPT_ONLY + +#include +#include +#include +#include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif +#if defined(OPENSSL_EXTRA) && defined(WOLFCRYPT_HAVE_SRP) && !defined(NO_SHA) + #include +#endif + +#ifdef HAVE_LIBZ + #include "zlib.h" +#endif + +#ifdef HAVE_NTRU + #include "libntruencrypt/ntru_crypto.h" +#endif + +#if defined(DEBUG_WOLFSSL) || defined(SHOW_SECRETS) || \ + defined(CHACHA_AEAD_TEST) || defined(WOLFSSL_SESSION_EXPORT_DEBUG) + #if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) + #if MQX_USE_IO_OLD + #include + #else + #include + #endif + #else + #include + #endif +#endif + +#ifdef __sun + #include +#endif + + +#define ERROR_OUT(err, eLabel) { ret = (err); goto eLabel; } + +#ifdef _MSC_VER + /* disable for while(0) cases at the .c level for now */ + #pragma warning(disable:4127) +#endif + +#if defined(WOLFSSL_CALLBACKS) && !defined(LARGE_STATIC_BUFFERS) + #error \ +WOLFSSL_CALLBACKS needs LARGE_STATIC_BUFFERS, please add LARGE_STATIC_BUFFERS +#endif + +#if defined(HAVE_SECURE_RENEGOTIATION) && defined(HAVE_RENEGOTIATION_INDICATION) + #error Cannot use both secure-renegotiation and renegotiation-indication +#endif + +#ifndef WOLFSSL_NO_TLS12 + +#ifndef NO_WOLFSSL_CLIENT + static int DoHelloVerifyRequest(WOLFSSL* ssl, const byte* input, word32*, + word32); + static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, word32*, + word32); + #ifndef NO_CERTS + static int DoCertificateRequest(WOLFSSL* ssl, const byte* input, word32*, + word32); + #endif + #ifdef HAVE_SESSION_TICKET + static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32*, + word32); + #endif +#endif + + +#ifndef NO_WOLFSSL_SERVER + static int DoClientKeyExchange(WOLFSSL* ssl, byte* input, word32*, word32); + #if (!defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519)) && \ + !defined(WOLFSSL_NO_CLIENT_AUTH) + static int DoCertificateVerify(WOLFSSL* ssl, byte*, word32*, word32); + #endif + #ifdef WOLFSSL_DTLS + static int SendHelloVerifyRequest(WOLFSSL*, const byte*, byte); + #endif /* WOLFSSL_DTLS */ +#endif + +#endif /* !WOLFSSL_NO_TLS12 */ + +#ifdef WOLFSSL_DTLS + static WC_INLINE int DtlsCheckWindow(WOLFSSL* ssl); + static WC_INLINE int DtlsUpdateWindow(WOLFSSL* ssl); +#endif + + +enum processReply { + doProcessInit = 0, +#ifndef NO_WOLFSSL_SERVER + runProcessOldClientHello, +#endif + getRecordLayerHeader, + getData, + decryptMessage, + verifyMessage, + runProcessingOneMessage +}; + + +#ifndef WOLFSSL_NO_TLS12 +#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_WOLFSSL_CLIENT) + +/* Server random bytes for TLS v1.3 described downgrade protection mechanism. */ +static const byte tls13Downgrade[7] = { + 0x44, 0x4f, 0x47, 0x4e, 0x47, 0x52, 0x44 +}; +#define TLS13_DOWNGRADE_SZ sizeof(tls13Downgrade) + +#endif /* !NO_WOLFSSL_SERVER || !NO_WOLFSSL_CLIENT */ + +#if !defined(NO_OLD_TLS) && !defined(WOLFSSL_AEAD_ONLY) +static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, + int padSz, int content, int verify); + +#endif + +#endif /* !WOLFSSL_NO_TLS12 */ + +#ifdef HAVE_QSH + int QSH_Init(WOLFSSL* ssl); +#endif + + +int IsTLS(const WOLFSSL* ssl) +{ + if (ssl->version.major == SSLv3_MAJOR && ssl->version.minor >=TLSv1_MINOR) + return 1; + + return 0; +} + + +int IsAtLeastTLSv1_2(const WOLFSSL* ssl) +{ + if (ssl->version.major == SSLv3_MAJOR && ssl->version.minor >=TLSv1_2_MINOR) + return 1; +#ifdef WOLFSSL_DTLS + if (ssl->version.major == DTLS_MAJOR && ssl->version.minor <= DTLSv1_2_MINOR) + return 1; +#endif + + return 0; +} + +int IsAtLeastTLSv1_3(const ProtocolVersion pv) +{ + return (pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_3_MINOR); +} + +static WC_INLINE int IsEncryptionOn(WOLFSSL* ssl, int isSend) +{ + (void)isSend; + + #ifdef WOLFSSL_DTLS + /* For DTLS, epoch 0 is always not encrypted. */ + if (ssl->options.dtls && !isSend && ssl->keys.curEpoch == 0) + return 0; + #endif /* WOLFSSL_DTLS */ + +#ifdef WOLFSSL_TLS13 + if (isSend) + return ssl->encrypt.setup; + else + return ssl->decrypt.setup; +#else + return ssl->keys.encryptionOn; +#endif +} + + +#if defined(WOLFSSL_DTLS) || !defined(WOLFSSL_NO_TLS12) +/* If SCTP is not enabled returns the state of the dtls option. + * If SCTP is enabled returns dtls && !sctp. */ +static WC_INLINE int IsDtlsNotSctpMode(WOLFSSL* ssl) +{ + int result = ssl->options.dtls; + + if (result) { +#ifdef WOLFSSL_SCTP + result = !ssl->options.dtlsSctp; +#endif + } + + return result; +} +#endif /* DTLS || !WOLFSSL_NO_TLS12 */ + + +#ifdef HAVE_QSH +/* free all structs that where used with QSH */ +static int QSH_FreeAll(WOLFSSL* ssl) +{ + QSHKey* key = ssl->QSH_Key; + QSHKey* preKey = NULL; + QSHSecret* secret = ssl->QSH_secret; + QSHScheme* list = NULL; + QSHScheme* preList = NULL; + + /* free elements in struct */ + while (key) { + preKey = key; + if (key->pri.buffer) { + ForceZero(key->pri.buffer, key->pri.length); + XFREE(key->pri.buffer, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + } + if (key->pub.buffer) + XFREE(key->pub.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + key = (QSHKey*)key->next; + + /* free struct */ + XFREE(preKey, ssl->heap, DYNAMIC_TYPE_QSH); + } + key = NULL; + + + /* free all of peers QSH keys */ + key = ssl->peerQSHKey; + while (key) { + preKey = key; + if (key->pri.buffer) { + ForceZero(key->pri.buffer, key->pri.length); + XFREE(key->pri.buffer, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + } + if (key->pub.buffer) + XFREE(key->pub.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + key = (QSHKey*)key->next; + + /* free struct */ + XFREE(preKey, ssl->heap, DYNAMIC_TYPE_QSH); + } + key = NULL; + + /* free secret information */ + if (secret) { + /* free up the QSHScheme list in QSHSecret */ + if (secret->list) + list = secret->list; + while (list) { + preList = list; + if (list->PK) + XFREE(list->PK, ssl->heap, DYNAMIC_TYPE_SECRET); + list = (QSHScheme*)list->next; + XFREE(preList, ssl->heap, DYNAMIC_TYPE_QSH); + } + + /* free secret buffers */ + if (secret->SerSi) { + if (secret->SerSi->buffer) { + /* clear extra secret material that supplemented Master Secret*/ + ForceZero(secret->SerSi->buffer, secret->SerSi->length); + XFREE(secret->SerSi->buffer, ssl->heap, DYNAMIC_TYPE_SECRET); + } + XFREE(secret->SerSi, ssl->heap, DYNAMIC_TYPE_SECRET); + } + if (secret->CliSi) { + if (secret->CliSi->buffer) { + /* clear extra secret material that supplemented Master Secret*/ + ForceZero(secret->CliSi->buffer, secret->CliSi->length); + XFREE(secret->CliSi->buffer, ssl->heap, DYNAMIC_TYPE_SECRET); + } + XFREE(secret->CliSi, ssl->heap, DYNAMIC_TYPE_SECRET); + } + } + XFREE(secret, ssl->heap, DYNAMIC_TYPE_QSH); + secret = NULL; + + return 0; +} +#endif + + +#ifdef HAVE_NTRU +static WC_RNG* rng; +static wolfSSL_Mutex* rngMutex; + +static word32 GetEntropy(unsigned char* out, word32 num_bytes) +{ + int ret = 0; + + if (rng == NULL) { + if ((rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), 0, + DYNAMIC_TYPE_RNG)) == NULL) + return DRBG_OUT_OF_MEMORY; + wc_InitRng(rng); + } + + if (rngMutex == NULL) { + if ((rngMutex = (wolfSSL_Mutex*)XMALLOC(sizeof(wolfSSL_Mutex), 0, + DYNAMIC_TYPE_MUTEX)) == NULL) + return DRBG_OUT_OF_MEMORY; + wc_InitMutex(rngMutex); + } + + ret |= wc_LockMutex(rngMutex); + ret |= wc_RNG_GenerateBlock(rng, out, num_bytes); + ret |= wc_UnLockMutex(rngMutex); + + if (ret != 0) + return DRBG_ENTROPY_FAIL; + + return DRBG_OK; +} +#endif /* HAVE_NTRU */ + +#ifdef HAVE_LIBZ + + /* alloc user allocs to work with zlib */ + static void* myAlloc(void* opaque, unsigned int item, unsigned int size) + { + (void)opaque; + return XMALLOC(item * size, opaque, DYNAMIC_TYPE_LIBZ); + } + + + static void myFree(void* opaque, void* memory) + { + (void)opaque; + XFREE(memory, opaque, DYNAMIC_TYPE_LIBZ); + } + + + /* init zlib comp/decomp streams, 0 on success */ + static int InitStreams(WOLFSSL* ssl) + { + ssl->c_stream.zalloc = (alloc_func)myAlloc; + ssl->c_stream.zfree = (free_func)myFree; + ssl->c_stream.opaque = (voidpf)ssl->heap; + + if (deflateInit(&ssl->c_stream, Z_DEFAULT_COMPRESSION) != Z_OK) + return ZLIB_INIT_ERROR; + + ssl->didStreamInit = 1; + + ssl->d_stream.zalloc = (alloc_func)myAlloc; + ssl->d_stream.zfree = (free_func)myFree; + ssl->d_stream.opaque = (voidpf)ssl->heap; + + if (inflateInit(&ssl->d_stream) != Z_OK) return ZLIB_INIT_ERROR; + + return 0; + } + + + static void FreeStreams(WOLFSSL* ssl) + { + if (ssl->didStreamInit) { + deflateEnd(&ssl->c_stream); + inflateEnd(&ssl->d_stream); + } + } + + + /* compress in to out, return out size or error */ + static int myCompress(WOLFSSL* ssl, byte* in, int inSz, byte* out, int outSz) + { + int err; + int currTotal = (int)ssl->c_stream.total_out; + + ssl->c_stream.next_in = in; + ssl->c_stream.avail_in = inSz; + ssl->c_stream.next_out = out; + ssl->c_stream.avail_out = outSz; + + err = deflate(&ssl->c_stream, Z_SYNC_FLUSH); + if (err != Z_OK && err != Z_STREAM_END) return ZLIB_COMPRESS_ERROR; + + return (int)ssl->c_stream.total_out - currTotal; + } + + + /* decompress in to out, return out size or error */ + static int myDeCompress(WOLFSSL* ssl, byte* in,int inSz, byte* out,int outSz) + { + int err; + int currTotal = (int)ssl->d_stream.total_out; + + ssl->d_stream.next_in = in; + ssl->d_stream.avail_in = inSz; + ssl->d_stream.next_out = out; + ssl->d_stream.avail_out = outSz; + + err = inflate(&ssl->d_stream, Z_SYNC_FLUSH); + if (err != Z_OK && err != Z_STREAM_END) return ZLIB_DECOMPRESS_ERROR; + + return (int)ssl->d_stream.total_out - currTotal; + } + +#endif /* HAVE_LIBZ */ + + +#ifdef WOLFSSL_SESSION_EXPORT +#ifdef WOLFSSL_DTLS +/* serializes the cipher specs struct for exporting */ +static int ExportCipherSpecState(WOLFSSL* ssl, byte* exp, word32 len, byte ver) +{ + word32 idx = 0; + CipherSpecs* specs; + + WOLFSSL_ENTER("ExportCipherSpecState"); + + if (exp == NULL || ssl == NULL) { + return BAD_FUNC_ARG; + } + + specs= &(ssl->specs); + + if (DTLS_EXPORT_SPC_SZ > len) { + return BUFFER_E; + } + + XMEMSET(exp, 0, DTLS_EXPORT_SPC_SZ); + + c16toa(specs->key_size, exp + idx); idx += OPAQUE16_LEN; + c16toa(specs->iv_size, exp + idx); idx += OPAQUE16_LEN; + c16toa(specs->block_size, exp + idx); idx += OPAQUE16_LEN; + c16toa(specs->aead_mac_size, exp + idx); idx += OPAQUE16_LEN; + exp[idx++] = specs->bulk_cipher_algorithm; + exp[idx++] = specs->cipher_type; + exp[idx++] = specs->mac_algorithm; + exp[idx++] = specs->kea; + exp[idx++] = specs->sig_algo; + exp[idx++] = specs->hash_size; + exp[idx++] = specs->pad_size; + exp[idx++] = specs->static_ecdh; + + if (idx != DTLS_EXPORT_SPC_SZ) { + WOLFSSL_MSG("DTLS_EXPORT_SPC_SZ needs updated and export version"); + return DTLS_EXPORT_VER_E; + } + + WOLFSSL_LEAVE("ExportCipherSpecState", idx); + (void)ver; + return idx; +} + + +/* serializes the key struct for exporting */ +static int ExportKeyState(WOLFSSL* ssl, byte* exp, word32 len, byte ver) +{ + word32 idx = 0; + byte sz; + Keys* keys; + + WOLFSSL_ENTER("ExportKeyState"); + + if (exp == NULL || ssl == NULL) { + return BAD_FUNC_ARG; + } + + keys = &(ssl->keys); + + if (DTLS_EXPORT_KEY_SZ > len) { + WOLFSSL_MSG("Buffer not large enough for max key struct size"); + return BUFFER_E; + } + + XMEMSET(exp, 0, DTLS_EXPORT_KEY_SZ); + + c32toa(keys->peer_sequence_number_hi, exp + idx); idx += OPAQUE32_LEN; + c32toa(keys->peer_sequence_number_lo, exp + idx); idx += OPAQUE32_LEN; + c32toa(keys->sequence_number_hi, exp + idx); idx += OPAQUE32_LEN; + c32toa(keys->sequence_number_lo, exp + idx); idx += OPAQUE32_LEN; + + c16toa(keys->peerSeq[0].nextEpoch, exp + idx); idx += OPAQUE16_LEN; + c16toa(keys->peerSeq[0].nextSeq_hi, exp + idx); idx += OPAQUE16_LEN; + c32toa(keys->peerSeq[0].nextSeq_lo, exp + idx); idx += OPAQUE32_LEN; + c16toa(keys->curEpoch, exp + idx); idx += OPAQUE16_LEN; + c16toa(keys->curSeq_hi, exp + idx); idx += OPAQUE16_LEN; + c32toa(keys->curSeq_lo, exp + idx); idx += OPAQUE32_LEN; + c16toa(keys->peerSeq[0].prevSeq_hi, exp + idx); idx += OPAQUE16_LEN; + c32toa(keys->peerSeq[0].prevSeq_lo, exp + idx); idx += OPAQUE32_LEN; + + c16toa(keys->dtls_peer_handshake_number, exp + idx); idx += OPAQUE16_LEN; + c16toa(keys->dtls_expected_peer_handshake_number, exp + idx); + idx += OPAQUE16_LEN; + + c16toa(keys->dtls_sequence_number_hi, exp + idx); idx += OPAQUE16_LEN; + c32toa(keys->dtls_sequence_number_lo, exp + idx); idx += OPAQUE32_LEN; + c16toa(keys->dtls_prev_sequence_number_hi, exp + idx); idx += OPAQUE16_LEN; + c32toa(keys->dtls_prev_sequence_number_lo, exp + idx); idx += OPAQUE32_LEN; + c16toa(keys->dtls_epoch, exp + idx); idx += OPAQUE16_LEN; + c16toa(keys->dtls_handshake_number, exp + idx); idx += OPAQUE16_LEN; + c32toa(keys->encryptSz, exp + idx); idx += OPAQUE32_LEN; + c32toa(keys->padSz, exp + idx); idx += OPAQUE32_LEN; + exp[idx++] = keys->encryptionOn; + exp[idx++] = keys->decryptedCur; + + { + word32 i; + + c16toa(WOLFSSL_DTLS_WINDOW_WORDS, exp + idx); idx += OPAQUE16_LEN; + for (i = 0; i < WOLFSSL_DTLS_WINDOW_WORDS; i++) { + c32toa(keys->peerSeq[0].window[i], exp + idx); + idx += OPAQUE32_LEN; + } + c16toa(WOLFSSL_DTLS_WINDOW_WORDS, exp + idx); idx += OPAQUE16_LEN; + for (i = 0; i < WOLFSSL_DTLS_WINDOW_WORDS; i++) { + c32toa(keys->peerSeq[0].prevWindow[i], exp + idx); + idx += OPAQUE32_LEN; + } + } + +#ifdef HAVE_TRUNCATED_HMAC + sz = ssl->truncated_hmac ? TRUNCATED_HMAC_SZ: ssl->specs.hash_size; + exp[idx++] = ssl->truncated_hmac; +#else + sz = ssl->specs.hash_size; + exp[idx++] = 0; /* no truncated hmac */ +#endif + exp[idx++] = sz; +#ifndef WOLFSSL_AEAD_ONLY + XMEMCPY(exp + idx, keys->client_write_MAC_secret, sz); idx += sz; + XMEMCPY(exp + idx, keys->server_write_MAC_secret, sz); idx += sz; +#else + XMEMSET(exp + idx, 0, sz); idx += sz; + XMEMSET(exp + idx, 0, sz); idx += sz; +#endif + + sz = ssl->specs.key_size; + exp[idx++] = sz; + XMEMCPY(exp + idx, keys->client_write_key, sz); idx += sz; + XMEMCPY(exp + idx, keys->server_write_key, sz); idx += sz; + + sz = ssl->specs.iv_size; + exp[idx++] = sz; + XMEMCPY(exp + idx, keys->client_write_IV, sz); idx += sz; + XMEMCPY(exp + idx, keys->server_write_IV, sz); idx += sz; + XMEMCPY(exp + idx, keys->aead_exp_IV, AEAD_MAX_EXP_SZ); + idx += AEAD_MAX_EXP_SZ; + + sz = AEAD_MAX_IMP_SZ; + exp[idx++] = sz; + XMEMCPY(exp + idx, keys->aead_enc_imp_IV, sz); idx += sz; + XMEMCPY(exp + idx, keys->aead_dec_imp_IV, sz); idx += sz; + + /* DTLS_EXPORT_KEY_SZ is max value. idx size can vary */ + if (idx > DTLS_EXPORT_KEY_SZ) { + WOLFSSL_MSG("DTLS_EXPORT_KEY_SZ needs updated and export version"); + return DTLS_EXPORT_VER_E; + } + + WOLFSSL_LEAVE("ExportKeyState", idx); + (void)ver; + return idx; +} + +static int ImportCipherSpecState(WOLFSSL* ssl, byte* exp, word32 len, byte ver) +{ + word32 idx = 0; + CipherSpecs* specs; + + WOLFSSL_ENTER("ImportCipherSpecState"); + + if (exp == NULL || ssl == NULL) { + return BAD_FUNC_ARG; + } + + specs= &(ssl->specs); + + if (DTLS_EXPORT_SPC_SZ > len) { + WOLFSSL_MSG("Buffer not large enough for max spec struct size"); + return BUFFER_E; + } + + ato16(exp + idx, &specs->key_size); idx += OPAQUE16_LEN; + ato16(exp + idx, &specs->iv_size); idx += OPAQUE16_LEN; + ato16(exp + idx, &specs->block_size); idx += OPAQUE16_LEN; + ato16(exp + idx, &specs->aead_mac_size); idx += OPAQUE16_LEN; + specs->bulk_cipher_algorithm = exp[idx++]; + specs->cipher_type = exp[idx++]; + specs->mac_algorithm = exp[idx++]; + specs->kea = exp[idx++]; + specs->sig_algo = exp[idx++]; + specs->hash_size = exp[idx++]; + specs->pad_size = exp[idx++]; + specs->static_ecdh = exp[idx++]; + + WOLFSSL_LEAVE("ImportCipherSpecState", idx); + (void)ver; + return idx; +} + + +static int ImportKeyState(WOLFSSL* ssl, byte* exp, word32 len, byte ver) +{ + word32 idx = 0; + byte sz; + Keys* keys; + + WOLFSSL_ENTER("ImportKeyState"); + + if (exp == NULL || ssl == NULL) { + return BAD_FUNC_ARG; + } + + keys = &(ssl->keys); + + /* check minimum length -- includes byte used for size indicators */ + if (len < DTLS_EXPORT_MIN_KEY_SZ) { + return BUFFER_E; + } + ato32(exp + idx, &keys->peer_sequence_number_hi); idx += OPAQUE32_LEN; + ato32(exp + idx, &keys->peer_sequence_number_lo); idx += OPAQUE32_LEN; + ato32(exp + idx, &keys->sequence_number_hi); idx += OPAQUE32_LEN; + ato32(exp + idx, &keys->sequence_number_lo); idx += OPAQUE32_LEN; + + ato16(exp + idx, &keys->peerSeq[0].nextEpoch); idx += OPAQUE16_LEN; + ato16(exp + idx, &keys->peerSeq[0].nextSeq_hi); idx += OPAQUE16_LEN; + ato32(exp + idx, &keys->peerSeq[0].nextSeq_lo); idx += OPAQUE32_LEN; + ato16(exp + idx, &keys->curEpoch); idx += OPAQUE16_LEN; + ato16(exp + idx, &keys->curSeq_hi); idx += OPAQUE16_LEN; + ato32(exp + idx, &keys->curSeq_lo); idx += OPAQUE32_LEN; + ato16(exp + idx, &keys->peerSeq[0].prevSeq_hi); idx += OPAQUE16_LEN; + ato32(exp + idx, &keys->peerSeq[0].prevSeq_lo); idx += OPAQUE32_LEN; + + ato16(exp + idx, &keys->dtls_peer_handshake_number); idx += OPAQUE16_LEN; + ato16(exp + idx, &keys->dtls_expected_peer_handshake_number); + idx += OPAQUE16_LEN; + + ato16(exp + idx, &keys->dtls_sequence_number_hi); idx += OPAQUE16_LEN; + ato32(exp + idx, &keys->dtls_sequence_number_lo); idx += OPAQUE32_LEN; + ato16(exp + idx, &keys->dtls_prev_sequence_number_hi); idx += OPAQUE16_LEN; + ato32(exp + idx, &keys->dtls_prev_sequence_number_lo); idx += OPAQUE32_LEN; + ato16(exp + idx, &keys->dtls_epoch); idx += OPAQUE16_LEN; + ato16(exp + idx, &keys->dtls_handshake_number); idx += OPAQUE16_LEN; + ato32(exp + idx, &keys->encryptSz); idx += OPAQUE32_LEN; + ato32(exp + idx, &keys->padSz); idx += OPAQUE32_LEN; + keys->encryptionOn = exp[idx++]; + keys->decryptedCur = exp[idx++]; + + { + word16 i, wordCount, wordAdj = 0; + + /* do window */ + ato16(exp + idx, &wordCount); + idx += OPAQUE16_LEN; + + if (wordCount > WOLFSSL_DTLS_WINDOW_WORDS) { + wordCount = WOLFSSL_DTLS_WINDOW_WORDS; + wordAdj = (WOLFSSL_DTLS_WINDOW_WORDS - wordCount) * sizeof(word32); + } + + XMEMSET(keys->peerSeq[0].window, 0xFF, DTLS_SEQ_SZ); + for (i = 0; i < wordCount; i++) { + ato32(exp + idx, &keys->peerSeq[0].window[i]); + idx += OPAQUE32_LEN; + } + idx += wordAdj; + + /* do prevWindow */ + ato16(exp + idx, &wordCount); + idx += OPAQUE16_LEN; + + if (wordCount > WOLFSSL_DTLS_WINDOW_WORDS) { + wordCount = WOLFSSL_DTLS_WINDOW_WORDS; + wordAdj = (WOLFSSL_DTLS_WINDOW_WORDS - wordCount) * sizeof(word32); + } + + XMEMSET(keys->peerSeq[0].prevWindow, 0xFF, DTLS_SEQ_SZ); + for (i = 0; i < wordCount; i++) { + ato32(exp + idx, &keys->peerSeq[0].prevWindow[i]); + idx += OPAQUE32_LEN; + } + idx += wordAdj; + + } + +#ifdef HAVE_TRUNCATED_HMAC + ssl->truncated_hmac = exp[idx++]; +#else + idx++; /* no truncated hmac */ +#endif + sz = exp[idx++]; +#ifndef WOLFSSL_AEAD_ONLY + if (sz > sizeof(keys->client_write_MAC_secret) || sz + idx > len) { + return BUFFER_E; + } + XMEMCPY(keys->client_write_MAC_secret, exp + idx, sz); idx += sz; + XMEMCPY(keys->server_write_MAC_secret, exp + idx, sz); idx += sz; +#else + if (sz + idx > len) { + return BUFFER_E; + } + idx += sz; idx += sz; +#endif + + sz = exp[idx++]; + if (sz > sizeof(keys->client_write_key) || sz + idx > len) { + return BUFFER_E; + } + XMEMCPY(keys->client_write_key, exp + idx, sz); idx += sz; + XMEMCPY(keys->server_write_key, exp + idx, sz); idx += sz; + + sz = exp[idx++]; + if (sz > sizeof(keys->client_write_IV) || sz + idx > len) { + return BUFFER_E; + } + XMEMCPY(keys->client_write_IV, exp + idx, sz); idx += sz; + XMEMCPY(keys->server_write_IV, exp + idx, sz); idx += sz; + XMEMCPY(keys->aead_exp_IV, exp + idx, AEAD_MAX_EXP_SZ); + idx += AEAD_MAX_EXP_SZ; + + sz = exp[idx++]; + if (sz > sizeof(keys->aead_enc_imp_IV) || sz + idx > len) { + return BUFFER_E; + } + XMEMCPY(keys->aead_enc_imp_IV, exp + idx, sz); idx += sz; + XMEMCPY(keys->aead_dec_imp_IV, exp + idx, sz); idx += sz; + + WOLFSSL_LEAVE("ImportKeyState", idx); + (void)ver; + return idx; +} + + +/* copy over necessary information from Options struct to buffer + * On success returns size of buffer used on failure returns a negative value */ +static int dtls_export_new(WOLFSSL* ssl, byte* exp, word32 len, byte ver) +{ + int idx = 0; + word16 zero = 0; + Options* options = &ssl->options; + + WOLFSSL_ENTER("dtls_export_new"); + + if (exp == NULL || options == NULL || len < DTLS_EXPORT_OPT_SZ) { + return BAD_FUNC_ARG; + } + + XMEMSET(exp, 0, DTLS_EXPORT_OPT_SZ); + + /* these options are kept and sent to indicate verify status and strength + * of handshake */ + exp[idx++] = options->sendVerify; + exp[idx++] = options->verifyPeer; + exp[idx++] = options->verifyNone; + exp[idx++] = options->downgrade; +#ifndef NO_DH + c16toa(options->minDhKeySz, exp + idx); idx += OPAQUE16_LEN; + c16toa(options->maxDhKeySz, exp + idx); idx += OPAQUE16_LEN; + c16toa(options->dhKeySz, exp + idx); idx += OPAQUE16_LEN; +#else + c16toa(zero, exp + idx); idx += OPAQUE16_LEN; + c16toa(zero, exp + idx); idx += OPAQUE16_LEN; + c16toa(zero, exp + idx); idx += OPAQUE16_LEN; +#endif +#ifndef NO_RSA + c16toa((word16)(options->minRsaKeySz), exp + idx); idx += OPAQUE16_LEN; +#else + c16toa(zero, exp + idx); idx += OPAQUE16_LEN; +#endif +#ifdef HAVE_ECC + c16toa((word16)(options->minEccKeySz), exp + idx); idx += OPAQUE16_LEN; +#else + c16toa(zero, exp + idx); idx += OPAQUE16_LEN; +#endif + + /* these options are kept to indicate state and behavior */ +#ifndef NO_PSK + exp[idx++] = options->havePSK; +#else + exp[idx++] = 0; +#endif + exp[idx++] = options->sessionCacheOff; + exp[idx++] = options->sessionCacheFlushOff; + exp[idx++] = options->side; + exp[idx++] = options->resuming; + exp[idx++] = options->haveSessionId; + exp[idx++] = options->tls; + exp[idx++] = options->tls1_1; + exp[idx++] = options->dtls; + exp[idx++] = options->connReset; + exp[idx++] = options->isClosed; + exp[idx++] = options->closeNotify; + exp[idx++] = options->sentNotify; + exp[idx++] = options->usingCompression; + exp[idx++] = options->haveRSA; + exp[idx++] = options->haveECC; + exp[idx++] = options->haveDH; + exp[idx++] = options->haveNTRU; + exp[idx++] = options->haveQSH; + exp[idx++] = options->haveECDSAsig; + exp[idx++] = options->haveStaticECC; + exp[idx++] = options->havePeerVerify; + exp[idx++] = options->usingPSK_cipher; + exp[idx++] = options->usingAnon_cipher; + exp[idx++] = options->sendAlertState; + exp[idx++] = options->partialWrite; + exp[idx++] = options->quietShutdown; + exp[idx++] = options->groupMessages; +#ifdef HAVE_POLY1305 + exp[idx++] = options->oldPoly; +#else + exp[idx++] = 0; +#endif +#ifdef HAVE_ANON + exp[idx++] = options->haveAnon; +#else + exp[idx++] = 0; +#endif +#ifdef HAVE_SESSION_TICKET + exp[idx++] = options->createTicket; + exp[idx++] = options->useTicket; +#ifdef WOLFSSL_TLS13 + if (ver > DTLS_EXPORT_VERSION_3) { + exp[idx++] = options->noTicketTls13; + } +#else + if (ver > DTLS_EXPORT_VERSION_3) { + exp[idx++] = 0; + } +#endif +#else + exp[idx++] = 0; + exp[idx++] = 0; + if (ver > DTLS_EXPORT_VERSION_3) { + exp[idx++] = 0; + } +#endif + exp[idx++] = options->processReply; + exp[idx++] = options->cipherSuite0; + exp[idx++] = options->cipherSuite; + exp[idx++] = options->serverState; + exp[idx++] = options->clientState; + exp[idx++] = options->handShakeState; + exp[idx++] = options->handShakeDone; + exp[idx++] = options->minDowngrade; + exp[idx++] = options->connectState; + exp[idx++] = options->acceptState; + exp[idx++] = options->asyncState; + + /* version of connection */ + exp[idx++] = ssl->version.major; + exp[idx++] = ssl->version.minor; + + (void)zero; + + /* check if changes were made and notify of need to update export version */ + switch (ver) { + case DTLS_EXPORT_VERSION_3: + if (idx != DTLS_EXPORT_OPT_SZ_3) { + WOLFSSL_MSG("Update DTLS_EXPORT_OPT_SZ and version of export"); + return DTLS_EXPORT_VER_E; + } + break; + + case DTLS_EXPORT_VERSION: + if (idx != DTLS_EXPORT_OPT_SZ) { + WOLFSSL_MSG("Update DTLS_EXPORT_OPT_SZ and version of export"); + return DTLS_EXPORT_VER_E; + } + break; + + default: + WOLFSSL_MSG("New version case needs added to wolfSSL export"); + return DTLS_EXPORT_VER_E; + } + + WOLFSSL_LEAVE("dtls_export_new", idx); + + return idx; +} + + +/* copy items from Export struct to Options struct + * On success returns size of buffer used on failure returns a negative value */ +static int dtls_export_load(WOLFSSL* ssl, byte* exp, word32 len, byte ver) +{ + int idx = 0; + Options* options = &ssl->options; + + switch (ver) { + case DTLS_EXPORT_VERSION: + if (len < DTLS_EXPORT_OPT_SZ) { + WOLFSSL_MSG("Sanity check on buffer size failed"); + return BAD_FUNC_ARG; + } + break; + + case DTLS_EXPORT_VERSION_3: + if (len < DTLS_EXPORT_OPT_SZ_3) { + WOLFSSL_MSG("Sanity check on buffer size failed"); + return BAD_FUNC_ARG; + } + break; + + default: + WOLFSSL_MSG("Export version not supported"); + return BAD_FUNC_ARG; + } + + if (exp == NULL || options == NULL) { + return BAD_FUNC_ARG; + } + + + /* these options are kept and sent to indicate verify status and strength + * of handshake */ + options->sendVerify = exp[idx++]; + options->verifyPeer = exp[idx++]; + options->verifyNone = exp[idx++]; + options->downgrade = exp[idx++]; +#ifndef NO_DH + ato16(exp + idx, &(options->minDhKeySz)); idx += OPAQUE16_LEN; + ato16(exp + idx, &(options->maxDhKeySz)); idx += OPAQUE16_LEN; + ato16(exp + idx, &(options->dhKeySz)); idx += OPAQUE16_LEN; +#else + idx += OPAQUE16_LEN; + idx += OPAQUE16_LEN; + idx += OPAQUE16_LEN; +#endif +#ifndef NO_RSA + ato16(exp + idx, (word16*)&(options->minRsaKeySz)); idx += OPAQUE16_LEN; +#else + idx += OPAQUE16_LEN; +#endif +#ifdef HAVE_ECC + ato16(exp + idx, (word16*)&(options->minEccKeySz)); idx += OPAQUE16_LEN; +#else + idx += OPAQUE16_LEN; +#endif + + /* these options are kept to indicate state and behavior */ +#ifndef NO_PSK + options->havePSK = exp[idx++]; +#else + idx++; +#endif + options->sessionCacheOff = exp[idx++]; + options->sessionCacheFlushOff = exp[idx++]; + options->side = exp[idx++]; + options->resuming = exp[idx++]; + options->haveSessionId = exp[idx++]; + options->tls = exp[idx++]; + options->tls1_1 = exp[idx++]; + options->dtls = exp[idx++]; + options->connReset = exp[idx++]; + options->isClosed = exp[idx++]; + options->closeNotify = exp[idx++]; + options->sentNotify = exp[idx++]; + options->usingCompression = exp[idx++]; + options->haveRSA = exp[idx++]; + options->haveECC = exp[idx++]; + options->haveDH = exp[idx++]; + options->haveNTRU = exp[idx++]; + options->haveQSH = exp[idx++]; + options->haveECDSAsig = exp[idx++]; + options->haveStaticECC = exp[idx++]; + options->havePeerVerify = exp[idx++]; + options->usingPSK_cipher = exp[idx++]; + options->usingAnon_cipher = exp[idx++]; + options->sendAlertState = exp[idx++]; + options->partialWrite = exp[idx++]; + options->quietShutdown = exp[idx++]; + options->groupMessages = exp[idx++]; +#ifdef HAVE_POLY1305 + options->oldPoly = exp[idx++]; /* set when to use old rfc way of poly*/ +#else + idx++; +#endif +#ifdef HAVE_ANON + options->haveAnon = exp[idx++]; /* User wants to allow Anon suites */ +#else + idx++; +#endif +#ifdef HAVE_SESSION_TICKET + options->createTicket = exp[idx++]; /* Server to create new Ticket */ + options->useTicket = exp[idx++]; /* Use Ticket not session cache */ +#ifdef WOLFSSL_TLS13 + if (ver > DTLS_EXPORT_VERSION_3) { + options->noTicketTls13 = exp[idx++];/* Server won't create new Ticket */ + } +#else + if (ver > DTLS_EXPORT_VERSION_3) { + exp[idx++] = 0; + } +#endif +#else + idx++; + idx++; + if (ver > DTLS_EXPORT_VERSION_3) { + idx++; + } +#endif + options->processReply = exp[idx++]; + options->cipherSuite0 = exp[idx++]; + options->cipherSuite = exp[idx++]; + options->serverState = exp[idx++]; + options->clientState = exp[idx++]; + options->handShakeState = exp[idx++]; + options->handShakeDone = exp[idx++]; + options->minDowngrade = exp[idx++]; + options->connectState = exp[idx++]; + options->acceptState = exp[idx++]; + options->asyncState = exp[idx++]; + + /* version of connection */ + if (ssl->version.major != exp[idx++] || ssl->version.minor != exp[idx++]) { + WOLFSSL_MSG("Version mismatch ie DTLS v1 vs v1.2"); + return VERSION_ERROR; + } + + return idx; +} + +static int ExportPeerInfo(WOLFSSL* ssl, byte* exp, word32 len, byte ver) +{ + int idx = 0; + int ipSz = DTLS_EXPORT_IP; /* start as max size */ + int fam = 0; + word16 port = 0; + char ip[DTLS_EXPORT_IP]; + + if (ver != DTLS_EXPORT_VERSION) { + WOLFSSL_MSG("Export version not supported"); + return BAD_FUNC_ARG; + } + + if (ssl == NULL || exp == NULL || len < sizeof(ip) + 3 * DTLS_EXPORT_LEN) { + return BAD_FUNC_ARG; + } + + if (ssl->ctx->CBGetPeer == NULL) { + WOLFSSL_MSG("No get peer call back set"); + return BAD_FUNC_ARG; + } + if (ssl->ctx->CBGetPeer(ssl, ip, &ipSz, &port, &fam) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Get peer callback error"); + return SOCKET_ERROR_E; + } + + /* check that ipSz/fam is not negative or too large since user can set cb */ + if (ipSz < 0 || ipSz > DTLS_EXPORT_IP || fam < 0) { + WOLFSSL_MSG("Bad ipSz or fam returned from get peer callback"); + return SOCKET_ERROR_E; + } + + c16toa((word16)fam, exp + idx); idx += DTLS_EXPORT_LEN; + c16toa((word16)ipSz, exp + idx); idx += DTLS_EXPORT_LEN; + XMEMCPY(exp + idx, ip, ipSz); idx += ipSz; + c16toa(port, exp + idx); idx += DTLS_EXPORT_LEN; + + return idx; +} + + +static int ImportPeerInfo(WOLFSSL* ssl, byte* buf, word32 len, byte ver) +{ + word16 idx = 0; + word16 ipSz; + word16 fam; + word16 port; + char ip[DTLS_EXPORT_IP]; + + if (ver != DTLS_EXPORT_VERSION && ver != DTLS_EXPORT_VERSION_3) { + WOLFSSL_MSG("Export version not supported"); + return BAD_FUNC_ARG; + } + + if (ssl == NULL || buf == NULL || len < 3 * DTLS_EXPORT_LEN) { + return BAD_FUNC_ARG; + } + + /* import sin family */ + ato16(buf + idx, &fam); idx += DTLS_EXPORT_LEN; + + /* import ip address idx, and ipSz are unsigned but cast for enum */ + ato16(buf + idx, &ipSz); idx += DTLS_EXPORT_LEN; + if (ipSz >= sizeof(ip) || (word16)(idx + ipSz + DTLS_EXPORT_LEN) > len) { + return BUFFER_E; + } + XMEMSET(ip, 0, sizeof(ip)); + XMEMCPY(ip, buf + idx, ipSz); idx += ipSz; + ip[ipSz] = '\0'; /* with check that ipSz less than ip this is valid */ + ato16(buf + idx, &port); idx += DTLS_EXPORT_LEN; + + /* sanity check for a function to call, then use it to import peer info */ + if (ssl->ctx->CBSetPeer == NULL) { + WOLFSSL_MSG("No set peer function"); + return BAD_FUNC_ARG; + } + if (ssl->ctx->CBSetPeer(ssl, ip, ipSz, port, fam) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Error setting peer info"); + return SOCKET_ERROR_E; + } + + return idx; +} + + +/* WOLFSSL_LOCAL function that serializes the current WOLFSSL session state only + * buf is used to hold the serialized WOLFSSL struct and sz is the size of buf + * passed in. + * On success returns the size of serialized session state.*/ +int wolfSSL_dtls_export_state_internal(WOLFSSL* ssl, byte* buf, word32 sz) +{ + int ret; + word32 idx = 0; + word32 totalLen = 0; + + WOLFSSL_ENTER("wolfSSL_dtls_export_state_internal"); + + if (buf == NULL || ssl == NULL) { + WOLFSSL_LEAVE("wolfSSL_dtls_export_state_internal", BAD_FUNC_ARG); + return BAD_FUNC_ARG; + } + + totalLen += DTLS_EXPORT_LEN * 2; /* 2 protocol bytes and 2 length bytes */ + /* each of the following have a 2 byte length before data */ + totalLen += DTLS_EXPORT_LEN + DTLS_EXPORT_KEY_SZ; + if (totalLen > sz) { + WOLFSSL_LEAVE("wolfSSL_dtls_export_state_internal", BUFFER_E); + return BUFFER_E; + } + + buf[idx++] = (byte)DTLS_EXPORT_STATE_PRO; + buf[idx++] = ((byte)DTLS_EXPORT_STATE_PRO & 0xF0) | + ((byte)DTLS_EXPORT_VERSION & 0X0F); + idx += DTLS_EXPORT_LEN; /* leave room for total length */ + + /* export keys struct and dtls state -- variable length stored in ret */ + idx += DTLS_EXPORT_LEN; /* leave room for length */ + if ((ret = ExportKeyState(ssl, buf + idx, sz - idx, + DTLS_EXPORT_VERSION)) < 0) { + WOLFSSL_LEAVE("wolfSSL_dtls_export_state_internal", ret); + return ret; + } + c16toa((word16)ret, buf + idx - DTLS_EXPORT_LEN); idx += ret; + + /* place total length of exported buffer minus 2 bytes protocol/version */ + c16toa((word16)(idx - DTLS_EXPORT_LEN), buf + DTLS_EXPORT_LEN); + +#ifdef WOLFSSL_SESSION_EXPORT_DEBUG + /* if compiled with debug options then print the version, protocol, size */ + { + char debug[256]; + XSNPRINTF(debug, sizeof(debug), "Exporting DTLS session state\n" + "\tVersion : %d\n\tProtocol : %02X%01X\n\tLength of: %d\n\n" + , (int)DTLS_EXPORT_VERSION, buf[0], (buf[1] >> 4), idx - 2); + WOLFSSL_MSG(debug); + } +#endif /* WOLFSSL_SESSION_EXPORT_DEBUG */ + + WOLFSSL_LEAVE("wolfSSL_dtls_export_state_internal", idx); + return idx; +} + + +/* WOLFSSL_LOCAL function that serializes the current WOLFSSL session + * buf is used to hold the serialized WOLFSSL struct and sz is the size of buf + * passed in. + * On success returns the size of serialized session.*/ +int wolfSSL_dtls_export_internal(WOLFSSL* ssl, byte* buf, word32 sz) +{ + int ret; + word32 idx = 0; + word32 totalLen = 0; + + WOLFSSL_ENTER("wolfSSL_dtls_export_internal"); + + if (buf == NULL || ssl == NULL) { + WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", BAD_FUNC_ARG); + return BAD_FUNC_ARG; + } + + totalLen += DTLS_EXPORT_LEN * 2; /* 2 protocol bytes and 2 length bytes */ + /* each of the following have a 2 byte length before data */ + totalLen += DTLS_EXPORT_LEN + DTLS_EXPORT_OPT_SZ; + totalLen += DTLS_EXPORT_LEN + DTLS_EXPORT_KEY_SZ; + totalLen += DTLS_EXPORT_LEN + DTLS_EXPORT_SPC_SZ; + totalLen += DTLS_EXPORT_LEN + ssl->buffers.dtlsCtx.peer.sz; + + if (totalLen > sz) { + WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", BUFFER_E); + return BUFFER_E; + } + + buf[idx++] = (byte)DTLS_EXPORT_PRO; + buf[idx++] = ((byte)DTLS_EXPORT_PRO & 0xF0) | + ((byte)DTLS_EXPORT_VERSION & 0X0F); + + idx += DTLS_EXPORT_LEN; /* leave spot for length */ + + c16toa((word16)DTLS_EXPORT_OPT_SZ, buf + idx); idx += DTLS_EXPORT_LEN; + if ((ret = dtls_export_new(ssl, buf + idx, sz - idx, + DTLS_EXPORT_VERSION)) < 0) { + WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", ret); + return ret; + } + idx += ret; + + /* export keys struct and dtls state -- variable length stored in ret */ + idx += DTLS_EXPORT_LEN; /* leave room for length */ + if ((ret = ExportKeyState(ssl, buf + idx, sz - idx, + DTLS_EXPORT_VERSION)) < 0) { + WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", ret); + return ret; + } + c16toa((word16)ret, buf + idx - DTLS_EXPORT_LEN); idx += ret; + + /* export of cipher specs struct */ + c16toa((word16)DTLS_EXPORT_SPC_SZ, buf + idx); idx += DTLS_EXPORT_LEN; + if ((ret = ExportCipherSpecState(ssl, buf + idx, sz - idx, + DTLS_EXPORT_VERSION)) < 0) { + WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", ret); + return ret; + } + idx += ret; + + /* export of dtls peer information */ + idx += DTLS_EXPORT_LEN; + if ((ret = ExportPeerInfo(ssl, buf + idx, sz - idx, + DTLS_EXPORT_VERSION)) < 0) { + WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", ret); + return ret; + } + c16toa(ret, buf + idx - DTLS_EXPORT_LEN); + idx += ret; + + /* place total length of exported buffer minus 2 bytes protocol/version */ + c16toa((word16)(idx - DTLS_EXPORT_LEN), buf + DTLS_EXPORT_LEN); + + /* if compiled with debug options then print the version, protocol, size */ +#ifdef WOLFSSL_SESSION_EXPORT_DEBUG + { + char debug[256]; + XSNPRINTF(debug, sizeof(debug), "Exporting DTLS session\n" + "\tVersion : %d\n\tProtocol : %02X%01X\n\tLength of: %d\n\n" + , (int)DTLS_EXPORT_VERSION, buf[0], (buf[1] >> 4), idx - 2); + WOLFSSL_MSG(debug); + } +#endif /* WOLFSSL_SESSION_EXPORT_DEBUG */ + + WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", idx); + return idx; +} + + +/* On success return amount of buffer consumed */ +int wolfSSL_dtls_import_state_internal(WOLFSSL* ssl, byte* buf, word32 sz) +{ + word32 idx = 0; + word16 length = 0; + int version; + int ret; + + WOLFSSL_ENTER("wolfSSL_dtls_import_state_internal"); + /* check at least enough room for protocol and length */ + if (sz < DTLS_EXPORT_LEN * 2 || ssl == NULL) { + WOLFSSL_LEAVE("wolfSSL_dtls_import_state_internal", BAD_FUNC_ARG); + return BAD_FUNC_ARG; + } + + if (buf[idx++] != (byte)DTLS_EXPORT_STATE_PRO || + (buf[idx] & 0xF0) != ((byte)DTLS_EXPORT_PRO & 0xF0)) { + WOLFSSL_MSG("Incorrect protocol"); + return BAD_FUNC_ARG; + } + version = buf[idx++] & 0x0F; + + ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN; + if (length > sz - DTLS_EXPORT_LEN) { /* subtract 2 for protocol */ + WOLFSSL_MSG("Buffer size sanity check failed"); + return BUFFER_E; + } + +#ifdef WOLFSSL_SESSION_EXPORT_DEBUG + /* if compiled with debug options then print the version, protocol, size */ + { + char debug[256]; + XSNPRINTF(debug, sizeof(debug), "Importing DTLS session state\n" + "\tVersion : %d\n\tProtocol : %02X%01X\n\tLength of: %d\n\n" + , (int)version, buf[0], (buf[1] >> 4), length); + WOLFSSL_MSG(debug); + } +#endif /* WOLFSSL_SESSION_EXPORT_DEBUG */ + + /* perform sanity checks and extract Options information used */ + switch (version) { + case DTLS_EXPORT_VERSION: + break; + + default: + WOLFSSL_MSG("Bad export state version"); + return BAD_FUNC_ARG; + + } + + /* perform sanity checks and extract Keys struct */ + if (DTLS_EXPORT_LEN + idx > sz) { + WOLFSSL_MSG("Import Key struct error"); + return BUFFER_E; + } + ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN; + if (length > DTLS_EXPORT_KEY_SZ || length + idx > sz) { + WOLFSSL_MSG("Import Key struct error"); + return BUFFER_E; + } + if ((ret = ImportKeyState(ssl, buf + idx, length, version)) < 0) { + WOLFSSL_MSG("Import Key struct error"); + WOLFSSL_LEAVE("wolfSSL_dtls_import_state_internal", ret); + return ret; + } + idx += ret; + + WOLFSSL_LEAVE("wolfSSL_dtls_import_state_internal", ret); + return ret; +} + + +/* On success return amount of buffer consumed */ +int wolfSSL_dtls_import_internal(WOLFSSL* ssl, byte* buf, word32 sz) +{ + word32 idx = 0; + word16 length = 0; + int version; + int ret; + int optSz; + + WOLFSSL_ENTER("wolfSSL_dtls_import_internal"); + /* check at least enough room for protocol and length */ + if (sz < DTLS_EXPORT_LEN * 2 || ssl == NULL) { + return BAD_FUNC_ARG; + } + + /* sanity check on protocol ID and size of buffer */ + if (buf[idx++] != (byte)DTLS_EXPORT_PRO || + (buf[idx] & 0xF0) != ((byte)DTLS_EXPORT_PRO & 0xF0)) { + /* don't increment on second idx to next get version */ + + /* check if importing state only */ + return wolfSSL_dtls_import_state_internal(ssl, buf, sz); + } + version = buf[idx++] & 0x0F; + + ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN; + if (length > sz - DTLS_EXPORT_LEN) { /* subtract 2 for protocol */ + return BUFFER_E; + } + + /* if compiled with debug options then print the version, protocol, size */ +#ifdef WOLFSSL_SESSION_EXPORT_DEBUG + { + char debug[256]; + XSNPRINTF(debug, sizeof(debug), "Importing DTLS session\n" + "\tVersion : %d\n\tProtocol : %02X%01X\n\tLength of: %d\n\n" + , (int)version, buf[0], (buf[1] >> 4), length); + WOLFSSL_MSG(debug); + } +#endif /* WOLFSSL_SESSION_EXPORT_DEBUG */ + + /* perform sanity checks and extract Options information used */ + switch (version) { + case DTLS_EXPORT_VERSION: + optSz = DTLS_EXPORT_OPT_SZ; + break; + + case DTLS_EXPORT_VERSION_3: + WOLFSSL_MSG("Importing older version 3"); + optSz = DTLS_EXPORT_OPT_SZ_3; + break; + + default: + WOLFSSL_MSG("Bad export version"); + return BAD_FUNC_ARG; + + } + + if (DTLS_EXPORT_LEN + optSz + idx > sz) { + WOLFSSL_MSG("Import Options struct error"); + return BUFFER_E; + } + ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN; + if (length != optSz) { + WOLFSSL_MSG("Import Options struct error"); + return BUFFER_E; + } + if ((ret = dtls_export_load(ssl, buf + idx, length, version)) < 0) { + WOLFSSL_MSG("Import Options struct error"); + return ret; + } + idx += length; + + /* perform sanity checks and extract Keys struct */ + if (DTLS_EXPORT_LEN + idx > sz) { + WOLFSSL_MSG("Import Key struct error"); + return BUFFER_E; + } + ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN; + if (length > DTLS_EXPORT_KEY_SZ || length + idx > sz) { + WOLFSSL_MSG("Import Key struct error"); + return BUFFER_E; + } + if ((ret = ImportKeyState(ssl, buf + idx, length, version)) < 0) { + WOLFSSL_MSG("Import Key struct error"); + return ret; + } + idx += ret; + + /* perform sanity checks and extract CipherSpecs struct */ + if (DTLS_EXPORT_LEN + DTLS_EXPORT_SPC_SZ + idx > sz) { + WOLFSSL_MSG("Import CipherSpecs struct error"); + return BUFFER_E; + } + ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN; + if ( length != DTLS_EXPORT_SPC_SZ) { + WOLFSSL_MSG("Import CipherSpecs struct error"); + return BUFFER_E; + } + if ((ret = ImportCipherSpecState(ssl, buf + idx, length, version)) < 0) { + WOLFSSL_MSG("Import CipherSpecs struct error"); + return ret; + } + idx += ret; + + /* perform sanity checks and extract DTLS peer info */ + if (DTLS_EXPORT_LEN + idx > sz) { + WOLFSSL_MSG("Import DTLS peer info error"); + return BUFFER_E; + } + ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN; + if (idx + length > sz) { + WOLFSSL_MSG("Import DTLS peer info error"); + return BUFFER_E; + } + if ((ret = ImportPeerInfo(ssl, buf + idx, length, version)) < 0) { + WOLFSSL_MSG("Import Peer Addr error"); + return ret; + } + idx += ret; + + SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE); + + /* set hmac function to use when verifying */ + if (ssl->options.tls == 1 || ssl->options.tls1_1 == 1 || + ssl->options.dtls == 1) { + ssl->hmac = TLS_hmac; + } + + /* make sure is a valid suite used */ + if (wolfSSL_get_cipher(ssl) == NULL) { + WOLFSSL_MSG("Can not match cipher suite imported"); + return MATCH_SUITE_ERROR; + } + + /* do not allow stream ciphers with DTLS, except for NULL cipher */ + if (ssl->specs.cipher_type == stream && + ssl->specs.bulk_cipher_algorithm != wolfssl_cipher_null) { + WOLFSSL_MSG("Can not import stream ciphers for DTLS"); + return SANITY_CIPHER_E; + } + + return idx; +} +#endif /* WOLFSSL_DTLS */ +#endif /* WOLFSSL_SESSION_EXPORT */ + + +void InitSSL_Method(WOLFSSL_METHOD* method, ProtocolVersion pv) +{ + method->version = pv; + method->side = WOLFSSL_CLIENT_END; + method->downgrade = 0; +} + +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) +int InitSSL_Side(WOLFSSL* ssl, word16 side) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + + /* set side */ + ssl->options.side = side; + + /* reset options that are side specific */ +#ifdef HAVE_NTRU + if (ssl->options.side == WOLFSSL_CLIENT_END) { + ssl->options.haveNTRU = 1; /* always on client side */ + /* server can turn on by loading key */ + } +#endif +#ifdef HAVE_ECC + if (ssl->options.side == WOLFSSL_CLIENT_END) { + ssl->options.haveECDSAsig = 1; /* always on client side */ + ssl->options.haveECC = 1; /* server turns on with ECC key cert */ + ssl->options.haveStaticECC = 1; /* server can turn on by loading key */ + } +#elif defined(HAVE_ED25519) + if (ssl->options.side == WOLFSSL_CLIENT_END) { + ssl->options.haveECDSAsig = 1; /* always on client side */ + ssl->options.haveECC = 1; /* server turns on with ECC key cert */ + } +#endif + +#if defined(HAVE_EXTENDED_MASTER) && !defined(NO_WOLFSSL_CLIENT) + if (ssl->options.side == WOLFSSL_CLIENT_END) { + if ((ssl->ctx->method->version.major == SSLv3_MAJOR) && + (ssl->ctx->method->version.minor >= TLSv1_MINOR)) { + ssl->options.haveEMS = 1; + } + #ifdef WOLFSSL_DTLS + if (ssl->ctx->method->version.major == DTLS_MAJOR) + ssl->options.haveEMS = 1; + #endif /* WOLFSSL_DTLS */ + } +#endif /* HAVE_EXTENDED_MASTER && !NO_WOLFSSL_CLIENT */ + + return InitSSL_Suites(ssl); +} +#endif /* OPENSSL_EXTRA || WOLFSSL_EITHER_SIDE */ + +/* Initialize SSL context, return 0 on success */ +int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method, void* heap) +{ + int ret = 0; + + XMEMSET(ctx, 0, sizeof(WOLFSSL_CTX)); + + ctx->method = method; + ctx->refCount = 1; /* so either CTX_free or SSL_free can release */ + ctx->heap = ctx; /* defaults to self */ + ctx->timeout = WOLFSSL_SESSION_TIMEOUT; + ctx->minDowngrade = WOLFSSL_MIN_DOWNGRADE; /* current default: TLSv1_MINOR */ + + if (wc_InitMutex(&ctx->countMutex) < 0) { + WOLFSSL_MSG("Mutex error on CTX init"); + ctx->err = CTX_INIT_MUTEX_E; + return BAD_MUTEX_E; + } + +#ifndef NO_DH + ctx->minDhKeySz = MIN_DHKEY_SZ; + ctx->maxDhKeySz = MAX_DHKEY_SZ; +#endif +#ifndef NO_RSA + ctx->minRsaKeySz = MIN_RSAKEY_SZ; +#endif +#ifdef HAVE_ECC + ctx->minEccKeySz = MIN_ECCKEY_SZ; + ctx->eccTempKeySz = ECDHE_SIZE; +#endif +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + ctx->verifyDepth = MAX_CHAIN_DEPTH; +#endif +#ifdef OPENSSL_EXTRA + ctx->cbioFlag = WOLFSSL_CBIO_NONE; +#endif + +#ifndef WOLFSSL_USER_IO + #ifdef MICRIUM + ctx->CBIORecv = MicriumReceive; + ctx->CBIOSend = MicriumSend; + #ifdef WOLFSSL_DTLS + if (method->version.major == DTLS_MAJOR) { + ctx->CBIORecv = MicriumReceiveFrom; + ctx->CBIOSend = MicriumSendTo; + } + #ifdef WOLFSSL_SESSION_EXPORT + #error Micrium port does not support DTLS session export yet + #endif + #endif + #elif defined WOLFSSL_UIP + ctx->CBIORecv = uIPReceive; + ctx->CBIOSend = uIPSend; + #ifdef WOLFSSL_DTLS + if (method->version.major == DTLS_MAJOR) { + ctx->CBIOSendTo = uIPSendTo; + ctx->CBIORecvFrom = uIPRecvFrom; + } + #endif + #else + ctx->CBIORecv = EmbedReceive; + ctx->CBIOSend = EmbedSend; + #ifdef WOLFSSL_DTLS + if (method->version.major == DTLS_MAJOR) { + ctx->CBIORecv = EmbedReceiveFrom; + ctx->CBIOSend = EmbedSendTo; + } + #ifdef WOLFSSL_SESSION_EXPORT + ctx->CBGetPeer = EmbedGetPeer; + ctx->CBSetPeer = EmbedSetPeer; + #endif + #endif + #endif /* MICRIUM */ +#endif /* WOLFSSL_USER_IO */ + +#ifdef HAVE_NETX + ctx->CBIORecv = NetX_Receive; + ctx->CBIOSend = NetX_Send; +#elif defined(WOLFSSL_APACHE_MYNEWT) && !defined(WOLFSSL_LWIP) + ctx->CBIORecv = Mynewt_Receive; + ctx->CBIOSend = Mynewt_Send; +#endif + +#ifdef HAVE_NTRU + if (method->side == WOLFSSL_CLIENT_END) + ctx->haveNTRU = 1; /* always on client side */ + /* server can turn on by loading key */ +#endif +#ifdef HAVE_ECC + if (method->side == WOLFSSL_CLIENT_END) { + ctx->haveECDSAsig = 1; /* always on client side */ + ctx->haveECC = 1; /* server turns on with ECC key cert */ + ctx->haveStaticECC = 1; /* server can turn on by loading key */ + } +#elif defined(HAVE_ED25519) + if (method->side == WOLFSSL_CLIENT_END) { + ctx->haveECDSAsig = 1; /* always on client side */ + ctx->haveECC = 1; /* server turns on with ECC key cert */ + } +#endif + + ctx->devId = INVALID_DEVID; + +#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SCTP) + ctx->dtlsMtuSz = MAX_RECORD_SIZE; +#endif + +#ifndef NO_CERTS + ctx->cm = wolfSSL_CertManagerNew_ex(heap); + if (ctx->cm == NULL) { + WOLFSSL_MSG("Bad Cert Manager New"); + return BAD_CERT_MANAGER_ERROR; + } + #ifdef OPENSSL_EXTRA + /* setup WOLFSSL_X509_STORE */ + ctx->x509_store.cm = ctx->cm; + #endif +#endif + +#if defined(HAVE_EXTENDED_MASTER) && !defined(NO_WOLFSSL_CLIENT) + if (method->side == WOLFSSL_CLIENT_END) { + if ((method->version.major == SSLv3_MAJOR) && + (method->version.minor >= TLSv1_MINOR)) { + + ctx->haveEMS = 1; + } +#ifdef WOLFSSL_DTLS + if (method->version.major == DTLS_MAJOR) + ctx->haveEMS = 1; +#endif /* WOLFSSL_DTLS */ + } +#endif /* HAVE_EXTENDED_MASTER && !NO_WOLFSSL_CLIENT */ + +#if defined(HAVE_SESSION_TICKET) && !defined(NO_WOLFSSL_SERVER) + ctx->ticketHint = SESSION_TICKET_HINT_DEFAULT; +#endif + +#ifdef HAVE_WOLF_EVENT + ret = wolfEventQueue_Init(&ctx->event_queue); +#endif /* HAVE_WOLF_EVENT */ + +#ifdef WOLFSSL_EARLY_DATA + ctx->maxEarlyDataSz = MAX_EARLY_DATA_SZ; +#endif + + ctx->heap = heap; /* wolfSSL_CTX_load_static_memory sets */ + ctx->verifyDepth = MAX_CHAIN_DEPTH; + + return ret; +} + + +/* In case contexts are held in array and don't want to free actual ctx */ +void SSL_CtxResourceFree(WOLFSSL_CTX* ctx) +{ +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + int i; +#endif + +#ifdef HAVE_WOLF_EVENT + wolfEventQueue_Free(&ctx->event_queue); +#endif /* HAVE_WOLF_EVENT */ + + XFREE(ctx->method, ctx->heap, DYNAMIC_TYPE_METHOD); + ctx->method = NULL; + if (ctx->suites) { + XFREE(ctx->suites, ctx->heap, DYNAMIC_TYPE_SUITES); + ctx->suites = NULL; + } + +#ifndef NO_DH + XFREE(ctx->serverDH_G.buffer, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); + ctx->serverDH_G.buffer = NULL; + XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); + ctx->serverDH_P.buffer = NULL; +#endif /* !NO_DH */ + +#ifdef SINGLE_THREADED + if (ctx->rng) { + wc_FreeRng(ctx->rng); + XFREE(ctx->rng, ctx->heap, DYNAMIC_TYPE_RNG); + ctx->rng = NULL; + } +#endif /* SINGLE_THREADED */ + +#ifndef NO_CERTS + FreeDer(&ctx->privateKey); + FreeDer(&ctx->certificate); + #ifdef KEEP_OUR_CERT + if (ctx->ourCert && ctx->ownOurCert) { + FreeX509(ctx->ourCert); + XFREE(ctx->ourCert, ctx->heap, DYNAMIC_TYPE_X509); + ctx->ourCert = NULL; + } + #endif /* KEEP_OUR_CERT */ + FreeDer(&ctx->certChain); + wolfSSL_CertManagerFree(ctx->cm); + ctx->cm = NULL; + #ifdef OPENSSL_EXTRA + /* ctx->cm was free'd so cm of x509 store should now be NULL */ + if (ctx->x509_store_pt != NULL) { + ctx->x509_store_pt->cm = NULL; + } + wolfSSL_X509_STORE_free(ctx->x509_store_pt); + while (ctx->ca_names != NULL) { + WOLFSSL_STACK *next = ctx->ca_names->next; + wolfSSL_X509_NAME_free(ctx->ca_names->data.name); + XFREE(ctx->ca_names, NULL, DYNAMIC_TYPE_OPENSSL); + ctx->ca_names = next; + } + #endif + #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + while (ctx->x509Chain != NULL) { + WOLFSSL_STACK *next = ctx->x509Chain->next; + wolfSSL_X509_free(ctx->x509Chain->data.x509); + XFREE(ctx->x509Chain, NULL, DYNAMIC_TYPE_OPENSSL); + ctx->x509Chain = next; + } + #endif +#endif /* !NO_CERTS */ + +#ifdef HAVE_TLS_EXTENSIONS + TLSX_FreeAll(ctx->extensions, ctx->heap); + +#ifndef NO_WOLFSSL_SERVER +#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + if (ctx->certOcspRequest) { + FreeOcspRequest(ctx->certOcspRequest); + XFREE(ctx->certOcspRequest, ctx->heap, DYNAMIC_TYPE_OCSP_REQUEST); + } +#endif + +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + for (i = 0; i < MAX_CHAIN_DEPTH; i++) { + if (ctx->chainOcspRequest[i]) { + FreeOcspRequest(ctx->chainOcspRequest[i]); + XFREE(ctx->chainOcspRequest[i], ctx->heap, DYNAMIC_TYPE_OCSP_REQUEST); + ctx->chainOcspRequest[i] = NULL; + } + } +#endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */ +#endif /* !NO_WOLFSSL_SERVER */ + +#endif /* HAVE_TLS_EXTENSIONS */ +#ifdef OPENSSL_EXTRA + if(ctx->alpn_cli_protos) { + XFREE((void *)ctx->alpn_cli_protos, NULL, DYNAMIC_TYPE_OPENSSL); + ctx->alpn_cli_protos = NULL; + } +#endif +#ifdef WOLFSSL_STATIC_MEMORY + if (ctx->heap != NULL) { +#ifdef WOLFSSL_HEAP_TEST + /* avoid derefrencing a test value */ + if (ctx->heap != (void*)WOLFSSL_HEAP_TEST) +#endif + { + WOLFSSL_HEAP_HINT* hint = (WOLFSSL_HEAP_HINT*)(ctx->heap); + wc_FreeMutex(&((WOLFSSL_HEAP*)(hint->memory))->memory_mutex); + } + } +#endif /* WOLFSSL_STATIC_MEMORY */ +} + + +void FreeSSL_Ctx(WOLFSSL_CTX* ctx) +{ + int doFree = 0; + + if (wc_LockMutex(&ctx->countMutex) != 0) { + WOLFSSL_MSG("Couldn't lock count mutex"); + + /* check error state, if mutex error code then mutex init failed but + * CTX was still malloc'd */ + if (ctx->err == CTX_INIT_MUTEX_E) { + SSL_CtxResourceFree(ctx); + XFREE(ctx, ctx->heap, DYNAMIC_TYPE_CTX); + } + return; + } + ctx->refCount--; + if (ctx->refCount == 0) + doFree = 1; + wc_UnLockMutex(&ctx->countMutex); + + if (doFree) { + WOLFSSL_MSG("CTX ref count down to 0, doing full free"); + SSL_CtxResourceFree(ctx); + wc_FreeMutex(&ctx->countMutex); + XFREE(ctx, ctx->heap, DYNAMIC_TYPE_CTX); + } + else { + (void)ctx; + WOLFSSL_MSG("CTX ref count not 0 yet, no free"); + } +} + + +/* Set cipher pointers to null */ +void InitCiphers(WOLFSSL* ssl) +{ +#ifdef BUILD_ARC4 + ssl->encrypt.arc4 = NULL; + ssl->decrypt.arc4 = NULL; +#endif +#ifdef BUILD_DES3 + ssl->encrypt.des3 = NULL; + ssl->decrypt.des3 = NULL; +#endif +#ifdef BUILD_AES + ssl->encrypt.aes = NULL; + ssl->decrypt.aes = NULL; +#endif +#ifdef HAVE_CAMELLIA + ssl->encrypt.cam = NULL; + ssl->decrypt.cam = NULL; +#endif +#ifdef HAVE_HC128 + ssl->encrypt.hc128 = NULL; + ssl->decrypt.hc128 = NULL; +#endif +#ifdef BUILD_RABBIT + ssl->encrypt.rabbit = NULL; + ssl->decrypt.rabbit = NULL; +#endif +#ifdef HAVE_CHACHA + ssl->encrypt.chacha = NULL; + ssl->decrypt.chacha = NULL; +#endif +#if defined(HAVE_POLY1305) && defined(HAVE_ONE_TIME_AUTH) + ssl->auth.poly1305 = NULL; +#endif + ssl->encrypt.setup = 0; + ssl->decrypt.setup = 0; +#ifdef HAVE_ONE_TIME_AUTH + ssl->auth.setup = 0; +#endif +#ifdef HAVE_IDEA + ssl->encrypt.idea = NULL; + ssl->decrypt.idea = NULL; +#endif +} + + +/* Free ciphers */ +void FreeCiphers(WOLFSSL* ssl) +{ + (void)ssl; +#ifdef BUILD_ARC4 + wc_Arc4Free(ssl->encrypt.arc4); + wc_Arc4Free(ssl->decrypt.arc4); + XFREE(ssl->encrypt.arc4, ssl->heap, DYNAMIC_TYPE_CIPHER); + XFREE(ssl->decrypt.arc4, ssl->heap, DYNAMIC_TYPE_CIPHER); +#endif +#ifdef BUILD_DES3 + wc_Des3Free(ssl->encrypt.des3); + wc_Des3Free(ssl->decrypt.des3); + XFREE(ssl->encrypt.des3, ssl->heap, DYNAMIC_TYPE_CIPHER); + XFREE(ssl->decrypt.des3, ssl->heap, DYNAMIC_TYPE_CIPHER); +#endif +#ifdef BUILD_AES + wc_AesFree(ssl->encrypt.aes); + wc_AesFree(ssl->decrypt.aes); + #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM) + XFREE(ssl->decrypt.additional, ssl->heap, DYNAMIC_TYPE_AES_BUFFER); + XFREE(ssl->decrypt.nonce, ssl->heap, DYNAMIC_TYPE_AES_BUFFER); + XFREE(ssl->encrypt.additional, ssl->heap, DYNAMIC_TYPE_AES_BUFFER); + XFREE(ssl->encrypt.nonce, ssl->heap, DYNAMIC_TYPE_AES_BUFFER); + #endif + XFREE(ssl->encrypt.aes, ssl->heap, DYNAMIC_TYPE_CIPHER); + XFREE(ssl->decrypt.aes, ssl->heap, DYNAMIC_TYPE_CIPHER); +#endif +#ifdef HAVE_CAMELLIA + XFREE(ssl->encrypt.cam, ssl->heap, DYNAMIC_TYPE_CIPHER); + XFREE(ssl->decrypt.cam, ssl->heap, DYNAMIC_TYPE_CIPHER); +#endif +#ifdef HAVE_HC128 + XFREE(ssl->encrypt.hc128, ssl->heap, DYNAMIC_TYPE_CIPHER); + XFREE(ssl->decrypt.hc128, ssl->heap, DYNAMIC_TYPE_CIPHER); +#endif +#ifdef BUILD_RABBIT + XFREE(ssl->encrypt.rabbit, ssl->heap, DYNAMIC_TYPE_CIPHER); + XFREE(ssl->decrypt.rabbit, ssl->heap, DYNAMIC_TYPE_CIPHER); +#endif +#ifdef HAVE_CHACHA + XFREE(ssl->encrypt.chacha, ssl->heap, DYNAMIC_TYPE_CIPHER); + XFREE(ssl->decrypt.chacha, ssl->heap, DYNAMIC_TYPE_CIPHER); +#endif +#if defined(HAVE_POLY1305) && defined(HAVE_ONE_TIME_AUTH) + XFREE(ssl->auth.poly1305, ssl->heap, DYNAMIC_TYPE_CIPHER); +#endif +#ifdef HAVE_IDEA + XFREE(ssl->encrypt.idea, ssl->heap, DYNAMIC_TYPE_CIPHER); + XFREE(ssl->decrypt.idea, ssl->heap, DYNAMIC_TYPE_CIPHER); +#endif +} + + +void InitCipherSpecs(CipherSpecs* cs) +{ + XMEMSET(cs, 0, sizeof(CipherSpecs)); + + cs->bulk_cipher_algorithm = INVALID_BYTE; + cs->cipher_type = INVALID_BYTE; + cs->mac_algorithm = INVALID_BYTE; + cs->kea = INVALID_BYTE; + cs->sig_algo = INVALID_BYTE; +} + +#ifdef USE_ECDSA_KEYSZ_HASH_ALGO +static int GetMacDigestSize(byte macAlgo) +{ + switch (macAlgo) { + #ifndef NO_SHA + case sha_mac: + return WC_SHA_DIGEST_SIZE; + #endif + #ifndef NO_SHA256 + case sha256_mac: + return WC_SHA256_DIGEST_SIZE; + #endif + #ifdef WOLFSSL_SHA384 + case sha384_mac: + return WC_SHA384_DIGEST_SIZE; + #endif + #ifdef WOLFSSL_SHA512 + case sha512_mac: + return WC_SHA512_DIGEST_SIZE; + #endif + default: + break; + } + return NOT_COMPILED_IN; +} +#endif /* USE_ECDSA_KEYSZ_HASH_ALGO */ + +static WC_INLINE void AddSuiteHashSigAlgo(Suites* suites, byte macAlgo, byte sigAlgo, + int keySz, word16* inOutIdx) +{ + int addSigAlgo = 1; + +#ifdef USE_ECDSA_KEYSZ_HASH_ALGO + if (sigAlgo == ecc_dsa_sa_algo) { + int digestSz = GetMacDigestSize(macAlgo); + /* do not add sig/algos with digest size larger than key size */ + if (digestSz <= 0 || (keySz > 0 && digestSz > keySz)) { + addSigAlgo = 0; + } + } +#else + (void)keySz; +#endif /* USE_ECDSA_KEYSZ_HASH_ALGO */ + + if (addSigAlgo) { +#ifdef WC_RSA_PSS + if (sigAlgo == rsa_pss_sa_algo) { + /* RSA PSS is sig then mac */ + suites->hashSigAlgo[*inOutIdx] = sigAlgo; + *inOutIdx += 1; + suites->hashSigAlgo[*inOutIdx] = macAlgo; + *inOutIdx += 1; + #ifdef WOLFSSL_TLS13 + /* Add the certificate algorithm as well */ + suites->hashSigAlgo[*inOutIdx] = sigAlgo; + *inOutIdx += 1; + suites->hashSigAlgo[*inOutIdx] = PSS_RSAE_TO_PSS_PSS(macAlgo); + *inOutIdx += 1; + #endif + } + else +#endif + { + suites->hashSigAlgo[*inOutIdx] = macAlgo; + *inOutIdx += 1; + suites->hashSigAlgo[*inOutIdx] = sigAlgo; + *inOutIdx += 1; + } + } +} + +void InitSuitesHashSigAlgo(Suites* suites, int haveECDSAsig, int haveRSAsig, + int haveAnon, int tls1_2, int keySz) +{ + word16 idx = 0; + + (void)tls1_2; + (void)keySz; + +#if defined(HAVE_ECC) || defined(HAVE_ED25519) + if (haveECDSAsig) { +#ifdef HAVE_ECC + #ifdef WOLFSSL_SHA512 + AddSuiteHashSigAlgo(suites, sha512_mac, ecc_dsa_sa_algo, keySz, &idx); + #endif + #ifdef WOLFSSL_SHA384 + AddSuiteHashSigAlgo(suites, sha384_mac, ecc_dsa_sa_algo, keySz, &idx); + #endif + #ifndef NO_SHA256 + AddSuiteHashSigAlgo(suites, sha256_mac, ecc_dsa_sa_algo, keySz, &idx); + #endif + #if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || \ + defined(WOLFSSL_ALLOW_TLS_SHA1)) + AddSuiteHashSigAlgo(suites, sha_mac, ecc_dsa_sa_algo, keySz, &idx); + #endif +#endif + #ifdef HAVE_ED25519 + AddSuiteHashSigAlgo(suites, ED25519_SA_MAJOR, ED25519_SA_MINOR, keySz, &idx); + #endif + } +#endif /* HAVE_ECC || HAVE_ED25519 */ + + if (haveRSAsig) { + #ifdef WC_RSA_PSS + if (tls1_2) { + #ifdef WOLFSSL_SHA512 + AddSuiteHashSigAlgo(suites, sha512_mac, rsa_pss_sa_algo, keySz, &idx); + #endif + #ifdef WOLFSSL_SHA384 + AddSuiteHashSigAlgo(suites, sha384_mac, rsa_pss_sa_algo, keySz, &idx); + #endif + #ifndef NO_SHA256 + AddSuiteHashSigAlgo(suites, sha256_mac, rsa_pss_sa_algo, keySz, &idx); + #endif + } + #endif + #ifdef WOLFSSL_SHA512 + AddSuiteHashSigAlgo(suites, sha512_mac, rsa_sa_algo, keySz, &idx); + #endif + #ifdef WOLFSSL_SHA384 + AddSuiteHashSigAlgo(suites, sha384_mac, rsa_sa_algo, keySz, &idx); + #endif + #ifndef NO_SHA256 + AddSuiteHashSigAlgo(suites, sha256_mac, rsa_sa_algo, keySz, &idx); + #endif + #ifdef WOLFSSL_SHA224 + AddSuiteHashSigAlgo(suites, sha224_mac, rsa_sa_algo, keySz, &idx); + #endif + #if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || \ + defined(WOLFSSL_ALLOW_TLS_SHA1)) + AddSuiteHashSigAlgo(suites, sha_mac, rsa_sa_algo, keySz, &idx); + #endif + } + +#ifdef HAVE_ANON + if (haveAnon) { + AddSuiteHashSigAlgo(suites, sha_mac, anonymous_sa_algo, keySz, &idx); + } +#endif + + (void)haveAnon; + (void)haveECDSAsig; + suites->hashSigAlgoSz = idx; +} + +void InitSuites(Suites* suites, ProtocolVersion pv, int keySz, word16 haveRSA, + word16 havePSK, word16 haveDH, word16 haveNTRU, + word16 haveECDSAsig, word16 haveECC, + word16 haveStaticECC, int side) +{ + word16 idx = 0; + int tls = pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_MINOR; + int tls1_2 = pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_2_MINOR; +#ifdef WOLFSSL_TLS13 + int tls1_3 = IsAtLeastTLSv1_3(pv); +#endif + int dtls = 0; + int haveRSAsig = 1; + + (void)tls; /* shut up compiler */ + (void)tls1_2; + (void)dtls; + (void)haveDH; + (void)havePSK; + (void)haveNTRU; + (void)haveStaticECC; + (void)haveECC; + (void)side; + (void)haveRSA; /* some builds won't read */ + (void)haveRSAsig; /* non ecc builds won't read */ + + if (suites == NULL) { + WOLFSSL_MSG("InitSuites pointer error"); + return; + } + + if (suites->setSuites) + return; /* trust user settings, don't override */ + +#ifdef WOLFSSL_TLS13 +#ifdef BUILD_TLS_AES_128_GCM_SHA256 + if (tls1_3) { + suites->suites[idx++] = TLS13_BYTE; + suites->suites[idx++] = TLS_AES_128_GCM_SHA256; + } +#endif + +#ifdef BUILD_TLS_AES_256_GCM_SHA384 + if (tls1_3) { + suites->suites[idx++] = TLS13_BYTE; + suites->suites[idx++] = TLS_AES_256_GCM_SHA384; + } +#endif + +#ifdef BUILD_TLS_CHACHA20_POLY1305_SHA256 + if (tls1_3) { + suites->suites[idx++] = TLS13_BYTE; + suites->suites[idx++] = TLS_CHACHA20_POLY1305_SHA256; + } +#endif + +#ifdef BUILD_TLS_AES_128_CCM_SHA256 + if (tls1_3) { + suites->suites[idx++] = TLS13_BYTE; + suites->suites[idx++] = TLS_AES_128_CCM_SHA256; + } +#endif + +#ifdef BUILD_TLS_AES_128_CCM_8_SHA256 + if (tls1_3) { + suites->suites[idx++] = TLS13_BYTE; + suites->suites[idx++] = TLS_AES_128_CCM_8_SHA256; + } +#endif +#endif /* WOLFSSL_TLS13 */ + +#ifndef WOLFSSL_NO_TLS12 + +#if !defined(NO_WOLFSSL_SERVER) && !defined(NO_RSA) + if (side == WOLFSSL_SERVER_END && haveStaticECC) { + haveRSA = 0; /* can't do RSA with ECDSA key */ + } + + if (side == WOLFSSL_SERVER_END && haveECDSAsig) { + haveRSAsig = 0; /* can't have RSA sig if signed by ECDSA */ + } +#endif /* !NO_WOLFSSL_SERVER */ + +#ifdef WOLFSSL_DTLS + if (pv.major == DTLS_MAJOR) { + dtls = 1; + tls = 1; + /* May be dead assignments dependant upon configuration */ + (void) dtls; + (void) tls; + tls1_2 = pv.minor <= DTLSv1_2_MINOR; + } +#endif + +#ifdef HAVE_RENEGOTIATION_INDICATION + if (side == WOLFSSL_CLIENT_END) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_EMPTY_RENEGOTIATION_INFO_SCSV; + } +#endif + +#ifdef BUILD_TLS_QSH + if (tls) { + suites->suites[idx++] = QSH_BYTE; + suites->suites[idx++] = TLS_QSH; + } +#endif + +#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA + if (tls && haveNTRU && haveRSA) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_NTRU_RSA_WITH_AES_256_CBC_SHA; + } +#endif + +#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA + if (tls && haveNTRU && haveRSA) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_NTRU_RSA_WITH_AES_128_CBC_SHA; + } +#endif + +#ifdef BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA + if (!dtls && tls && haveNTRU && haveRSA) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_NTRU_RSA_WITH_RC4_128_SHA; + } +#endif + +#ifdef BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA + if (tls && haveNTRU && haveRSA) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA; + } +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + if (tls1_2 && haveECC) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384; + } +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + if (tls1_2 && haveECC) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256; + } +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + if (tls1_2 && haveRSA) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384; + } +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + if (tls1_2 && haveRSA) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256; + } +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + if (tls1_2 && haveDH && haveRSA) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_256_GCM_SHA384; + } +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + if (tls1_2 && haveDH && haveRSA) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_128_GCM_SHA256; + } +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_256_GCM_SHA384 + if (tls1_2 && haveRSA) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_RSA_WITH_AES_256_GCM_SHA384; + } +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256 + if (tls1_2 && haveRSA) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_RSA_WITH_AES_128_GCM_SHA256; + } +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + if (tls1_2 && haveECC && haveStaticECC) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384; + } +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + if (tls1_2 && haveECC && haveStaticECC) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256; + } +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + if (tls1_2 && haveRSAsig && haveStaticECC) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384; + } +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + if (tls1_2 && haveRSAsig && haveStaticECC) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256; + } +#endif + +#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 + if (tls1_2 && haveDH && havePSK) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_DHE_PSK_WITH_AES_256_GCM_SHA384; + } +#endif + +#ifdef BUILD_TLS_DH_anon_WITH_AES_128_CBC_SHA + if (tls1_2 && haveDH) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_DH_anon_WITH_AES_128_CBC_SHA; + } +#endif + +#ifdef BUILD_TLS_DH_anon_WITH_AES_256_GCM_SHA384 + if (tls1_2 && haveDH) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_DH_anon_WITH_AES_256_GCM_SHA384; + } +#endif + +#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + if (tls1_2 && haveDH && havePSK) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_DHE_PSK_WITH_AES_128_GCM_SHA256; + } +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_256_GCM_SHA384 + if (tls1_2 && havePSK) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_PSK_WITH_AES_256_GCM_SHA384; + } +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_128_GCM_SHA256 + if (tls1_2 && havePSK) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_PSK_WITH_AES_128_GCM_SHA256; + } +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 + if (tls1_2 && haveECC) { + suites->suites[idx++] = CHACHA_BYTE; + suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256; + } +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 + if (tls1_2 && haveRSA) { + suites->suites[idx++] = CHACHA_BYTE; + suites->suites[idx++] = TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256; + } +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 + if (tls1_2 && haveRSA) { + suites->suites[idx++] = CHACHA_BYTE; + suites->suites[idx++] = TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256; + } +#endif + +/* Place as higher priority for MYSQL */ +#if defined(WOLFSSL_MYSQL_COMPATIBLE) +#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA + if (tls && haveDH && haveRSA) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_256_CBC_SHA; + } +#endif +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + if (tls1_2 && haveRSA) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256; + } +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + if (tls1_2 && haveECC) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256; + } +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + if (tls1_2 && haveRSAsig && haveStaticECC) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256; + } +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 + if (tls1_2 && haveECC && haveStaticECC) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256; + } +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + if (tls1_2 && haveRSA) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384; + } +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + if (tls1_2 && haveECC) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384; + } +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + if (tls1_2 && haveRSAsig && haveStaticECC) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384; + } +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 + if (tls1_2 && haveECC && haveStaticECC) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384; + } +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + if (tls && haveECC) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA; + } +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + if (tls && haveECC && haveStaticECC) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA; + } +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + if (tls && haveECC) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA; + } +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + if (tls && haveECC && haveStaticECC) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA; + } +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA + if (!dtls && tls && haveECC) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_RC4_128_SHA; + } +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_RC4_128_SHA + if (!dtls && tls && haveECC && haveStaticECC) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_RC4_128_SHA; + } +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA + if (tls && haveECC) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA; + } +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA + if (tls && haveECC && haveStaticECC) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA; + } +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + if (tls && haveRSA) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA; + } +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + if (tls && haveRSAsig && haveStaticECC) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_256_CBC_SHA; + } +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + if (tls && haveRSA) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA; + } +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + if (tls && haveRSAsig && haveStaticECC) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDH_RSA_WITH_AES_128_CBC_SHA; + } +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA + if (!dtls && tls && haveRSA) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDHE_RSA_WITH_RC4_128_SHA; + } +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_RC4_128_SHA + if (!dtls && tls && haveRSAsig && haveStaticECC) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDH_RSA_WITH_RC4_128_SHA; + } +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + if (tls && haveRSA) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA; + } +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA + if (tls && haveRSAsig && haveStaticECC) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA; + } +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM + if (tls1_2 && haveECC) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_128_CCM; + } +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 + if (tls1_2 && haveECC) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8; + } +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 + if (tls1_2 && haveECC) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8; + } +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_128_CCM_8 + if (tls1_2 && haveRSA) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_RSA_WITH_AES_128_CCM_8; + } +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_256_CCM_8 + if (tls1_2 && haveRSA) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_RSA_WITH_AES_256_CCM_8; + } +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + if (tls && haveDH && haveRSA) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_256_CBC_SHA256; + } +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + if (tls && haveDH && haveRSA) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_128_CBC_SHA256; + } +#endif + +/* Place as higher priority for MYSQL testing */ +#if !defined(WOLFSSL_MYSQL_COMPATIBLE) +#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA + if (tls && haveDH && haveRSA) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_256_CBC_SHA; + } +#endif +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA + if (tls && haveDH && haveRSA) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_DHE_RSA_WITH_AES_128_CBC_SHA; + } +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + if (tls && haveDH && haveRSA) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA; + } +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA256 + if (tls && haveRSA) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_RSA_WITH_AES_256_CBC_SHA256; + } +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA256 + if (tls && haveRSA) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_RSA_WITH_AES_128_CBC_SHA256; + } +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA + if (tls && haveRSA) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_RSA_WITH_AES_256_CBC_SHA; + } +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA + if (tls && haveRSA) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_RSA_WITH_AES_128_CBC_SHA; + } +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256 + if (tls1_2 && haveECC) { + suites->suites[idx++] = CHACHA_BYTE; + suites->suites[idx++] = + TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256; + } +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 + if (tls1_2 && haveRSA) { + suites->suites[idx++] = CHACHA_BYTE; + suites->suites[idx++] = TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256; + } +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 + if (tls1_2 && haveRSA) { + suites->suites[idx++] = CHACHA_BYTE; + suites->suites[idx++] = TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256; + } +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_NULL_SHA + if (tls && haveECC) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDHE_ECDSA_WITH_NULL_SHA; + } +#endif + +#ifdef BUILD_TLS_RSA_WITH_NULL_MD5 + if (tls && haveRSA) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_RSA_WITH_NULL_MD5; + } +#endif + +#ifdef BUILD_TLS_RSA_WITH_NULL_SHA + if (tls && haveRSA) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_RSA_WITH_NULL_SHA; + } +#endif + +#ifdef BUILD_TLS_RSA_WITH_NULL_SHA256 + if (tls && haveRSA) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_RSA_WITH_NULL_SHA256; + } +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA + if (tls && havePSK) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_PSK_WITH_AES_256_CBC_SHA; + } +#endif + +#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + if (tls && haveDH && havePSK) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_DHE_PSK_WITH_AES_256_CBC_SHA384; + } +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA384 + if (tls && havePSK) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_PSK_WITH_AES_256_CBC_SHA384; + } +#endif + +#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + if (tls && haveDH && havePSK) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_DHE_PSK_WITH_AES_128_CBC_SHA256; + } +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA256 + if (tls && havePSK) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_PSK_WITH_AES_128_CBC_SHA256; + } +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA + if (tls && havePSK) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_PSK_WITH_AES_128_CBC_SHA; + } +#endif + +#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CCM + if (tls && haveDH && havePSK) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_DHE_PSK_WITH_AES_128_CCM; + } +#endif + +#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_CCM + if (tls && haveDH && havePSK) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_DHE_PSK_WITH_AES_256_CCM; + } +#endif + +#ifdef BUILD_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 + if (tls && havePSK) { + suites->suites[idx++] = CHACHA_BYTE; + suites->suites[idx++] = TLS_PSK_WITH_CHACHA20_POLY1305_SHA256; + } +#endif + +#ifdef BUILD_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 + if (tls && havePSK) { + suites->suites[idx++] = CHACHA_BYTE; + suites->suites[idx++] = TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256; + } +#endif + +#ifdef BUILD_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 + if (tls && havePSK) { + suites->suites[idx++] = CHACHA_BYTE; + suites->suites[idx++] = TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256; + } +#endif + +#ifdef BUILD_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + if (tls && havePSK) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256; + } +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_128_CCM + if (tls && havePSK) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_PSK_WITH_AES_128_CCM; + } +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_256_CCM + if (tls && havePSK) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_PSK_WITH_AES_256_CCM; + } +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_128_CCM_8 + if (tls && havePSK) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_PSK_WITH_AES_128_CCM_8; + } +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_256_CCM_8 + if (tls && havePSK) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_PSK_WITH_AES_256_CCM_8; + } +#endif + +#ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA384 + if (tls && haveDH && havePSK) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_DHE_PSK_WITH_NULL_SHA384; + } +#endif + +#ifdef BUILD_TLS_PSK_WITH_NULL_SHA384 + if (tls && havePSK) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_PSK_WITH_NULL_SHA384; + } +#endif + +#ifdef BUILD_TLS_ECDHE_PSK_WITH_NULL_SHA256 + if (tls && havePSK) { + suites->suites[idx++] = ECC_BYTE; + suites->suites[idx++] = TLS_ECDHE_PSK_WITH_NULL_SHA256; + } +#endif + +#ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA256 + if (tls && haveDH && havePSK) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_DHE_PSK_WITH_NULL_SHA256; + } +#endif + +#ifdef BUILD_TLS_PSK_WITH_NULL_SHA256 + if (tls && havePSK) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_PSK_WITH_NULL_SHA256; + } +#endif + +#ifdef BUILD_TLS_PSK_WITH_NULL_SHA + if (tls && havePSK) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_PSK_WITH_NULL_SHA; + } +#endif + +#ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA + if (!dtls && haveRSA) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = SSL_RSA_WITH_RC4_128_SHA; + } +#endif + +#ifdef BUILD_SSL_RSA_WITH_RC4_128_MD5 + if (!dtls && haveRSA) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = SSL_RSA_WITH_RC4_128_MD5; + } +#endif + +#ifdef BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA + if (haveRSA ) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = SSL_RSA_WITH_3DES_EDE_CBC_SHA; + } +#endif + +#ifdef BUILD_TLS_RSA_WITH_HC_128_MD5 + if (!dtls && tls && haveRSA) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_RSA_WITH_HC_128_MD5; + } +#endif + +#ifdef BUILD_TLS_RSA_WITH_HC_128_SHA + if (!dtls && tls && haveRSA) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_RSA_WITH_HC_128_SHA; + } +#endif + +#ifdef BUILD_TLS_RSA_WITH_HC_128_B2B256 + if (!dtls && tls && haveRSA) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_RSA_WITH_HC_128_B2B256; + } +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_B2B256 + if (tls && haveRSA) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_RSA_WITH_AES_128_CBC_B2B256; + } +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_B2B256 + if (tls && haveRSA) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_RSA_WITH_AES_256_CBC_B2B256; + } +#endif + +#ifdef BUILD_TLS_RSA_WITH_RABBIT_SHA + if (!dtls && tls && haveRSA) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_RSA_WITH_RABBIT_SHA; + } +#endif + +#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + if (tls && haveRSA) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_RSA_WITH_CAMELLIA_128_CBC_SHA; + } +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + if (tls && haveDH && haveRSA) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA; + } +#endif + +#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA + if (tls && haveRSA) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_RSA_WITH_CAMELLIA_256_CBC_SHA; + } +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + if (tls && haveDH && haveRSA) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA; + } +#endif + +#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 + if (tls && haveRSA) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256; + } +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + if (tls && haveDH && haveRSA) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256; + } +#endif + +#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 + if (tls && haveRSA) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256; + } +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + if (tls && haveDH && haveRSA) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256; + } +#endif + +#ifdef BUILD_SSL_RSA_WITH_IDEA_CBC_SHA + if (haveRSA) { + suites->suites[idx++] = CIPHER_BYTE; + suites->suites[idx++] = SSL_RSA_WITH_IDEA_CBC_SHA; + } +#endif + +#endif /* !WOLFSSL_NO_TLS12 */ + + suites->suiteSz = idx; + + InitSuitesHashSigAlgo(suites, haveECDSAsig | haveECC, haveRSAsig | haveRSA, + 0, tls1_2, keySz); +} + +#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_CERTS) || \ + (!defined(NO_WOLFSSL_CLIENT) && (!defined(NO_DH) || defined(HAVE_ECC))) + +/* Decode the signature algorithm. + * + * input The encoded signature algorithm. + * hashalgo The hash algorithm. + * hsType The signature type. + */ +static WC_INLINE void DecodeSigAlg(const byte* input, byte* hashAlgo, byte* hsType) +{ + switch (input[0]) { + case NEW_SA_MAJOR: + #ifdef HAVE_ED25519 + /* ED25519: 0x0807 */ + if (input[1] == ED25519_SA_MINOR) { + *hsType = ed25519_sa_algo; + /* Hash performed as part of sign/verify operation. */ + *hashAlgo = sha512_mac; + } + else + #endif + #ifdef WC_RSA_PSS + /* PSS PSS signatures: 0x080[9-b] */ + if (input[1] >= pss_sha256 && input[1] <= pss_sha512) { + *hsType = rsa_pss_pss_algo; + *hashAlgo = PSS_PSS_HASH_TO_MAC(input[1]); + } + else + #endif + /* ED448: 0x0808 */ + { + *hsType = input[0]; + *hashAlgo = input[1]; + } + break; + default: + *hashAlgo = input[0]; + *hsType = input[1]; + break; + } +} +#endif /* !NO_WOLFSSL_SERVER || !NO_CERTS */ + +#ifndef WOLFSSL_NO_TLS12 +#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_WOLFSSL_CLIENT) +#if !defined(NO_DH) || defined(HAVE_ECC) || defined(HAVE_CURVE25519) || \ + (!defined(NO_RSA) && defined(WC_RSA_PSS)) + +static enum wc_HashType HashAlgoToType(int hashAlgo) +{ + switch (hashAlgo) { + #ifdef WOLFSSL_SHA512 + case sha512_mac: + return WC_HASH_TYPE_SHA512; + #endif + #ifdef WOLFSSL_SHA384 + case sha384_mac: + return WC_HASH_TYPE_SHA384; + #endif + #ifndef NO_SHA256 + case sha256_mac: + return WC_HASH_TYPE_SHA256; + #endif + #ifdef WOLFSSL_SHA224 + case sha224_mac: + return WC_HASH_TYPE_SHA224; + #endif + #if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || \ + defined(WOLFSSL_ALLOW_TLS_SHA1)) + case sha_mac: + return WC_HASH_TYPE_SHA; + #endif + default: + WOLFSSL_MSG("Bad hash sig algo"); + break; + } + + return WC_HASH_TYPE_NONE; +} +#endif /* !NO_DH || HAVE_ECC || (!NO_RSA && WC_RSA_PSS) */ +#endif /* !NO_WOLFSSL_SERVER || !NO_WOLFSSL_CLIENT */ +#endif /* !WOLFSSL_NO_TLS12 */ + +#ifndef NO_CERTS + +void InitX509Name(WOLFSSL_X509_NAME* name, int dynamicFlag) +{ + (void)dynamicFlag; + + if (name != NULL) { + name->name = name->staticName; + name->dynamicName = 0; + name->sz = 0; +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + XMEMSET(&name->fullName, 0, sizeof(DecodedName)); + XMEMSET(&name->cnEntry, 0, sizeof(WOLFSSL_X509_NAME_ENTRY)); + XMEMSET(&name->extra, 0, sizeof(name->extra)); + name->cnEntry.value = &(name->cnEntry.data); /* point to internal data*/ + name->cnEntry.nid = ASN_COMMON_NAME; + name->x509 = NULL; +#endif /* OPENSSL_EXTRA */ + } +} + + +void FreeX509Name(WOLFSSL_X509_NAME* name, void* heap) +{ + if (name != NULL) { + if (name->dynamicName) { + XFREE(name->name, heap, DYNAMIC_TYPE_SUBJECT_CN); + name->name = NULL; + } +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + { + int i; + if (name->fullName.fullName != NULL) { + XFREE(name->fullName.fullName, heap, DYNAMIC_TYPE_X509); + name->fullName.fullName = NULL; + } + for (i = 0; i < MAX_NAME_ENTRIES; i++) { + /* free ASN1 string data */ + if (name->extra[i].set && name->extra[i].data.data != NULL) { + XFREE(name->extra[i].data.data, heap, DYNAMIC_TYPE_OPENSSL); + } + } + wolfSSL_ASN1_OBJECT_free(&name->cnEntry.object); + } +#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ + } + (void)heap; +} + + +/* Initialize wolfSSL X509 type */ +void InitX509(WOLFSSL_X509* x509, int dynamicFlag, void* heap) +{ + if (x509 == NULL) { + WOLFSSL_MSG("Null parameter passed in!"); + return; + } + + XMEMSET(x509, 0, sizeof(WOLFSSL_X509)); + + x509->heap = heap; + InitX509Name(&x509->issuer, 0); + InitX509Name(&x509->subject, 0); + x509->dynamicMemory = (byte)dynamicFlag; +} + + +/* Free wolfSSL X509 type */ +void FreeX509(WOLFSSL_X509* x509) +{ + if (x509 == NULL) + return; + + FreeX509Name(&x509->issuer, x509->heap); + FreeX509Name(&x509->subject, x509->heap); + if (x509->pubKey.buffer) { + XFREE(x509->pubKey.buffer, x509->heap, DYNAMIC_TYPE_PUBLIC_KEY); + x509->pubKey.buffer = NULL; + } + FreeDer(&x509->derCert); + XFREE(x509->sig.buffer, x509->heap, DYNAMIC_TYPE_SIGNATURE); + x509->sig.buffer = NULL; + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + XFREE(x509->authKeyId, x509->heap, DYNAMIC_TYPE_X509_EXT); + x509->authKeyId = NULL; + XFREE(x509->subjKeyId, x509->heap, DYNAMIC_TYPE_X509_EXT); + x509->subjKeyId = NULL; + if (x509->authInfo != NULL) { + XFREE(x509->authInfo, x509->heap, DYNAMIC_TYPE_X509_EXT); + x509->authInfo = NULL; + } + if (x509->extKeyUsageSrc != NULL) { + XFREE(x509->extKeyUsageSrc, x509->heap, DYNAMIC_TYPE_X509_EXT); + x509->extKeyUsageSrc= NULL; + } + #endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ + if (x509->altNames) { + FreeAltNames(x509->altNames, x509->heap); + x509->altNames = NULL; + } +} + + +#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_WOLFSSL_CLIENT) +#if !defined(WOLFSSL_NO_TLS12) +/* Encode the signature algorithm into buffer. + * + * hashalgo The hash algorithm. + * hsType The signature type. + * output The buffer to encode into. + */ +static WC_INLINE void EncodeSigAlg(byte hashAlgo, byte hsType, byte* output) +{ + switch (hsType) { +#ifdef HAVE_ECC + case ecc_dsa_sa_algo: + output[0] = hashAlgo; + output[1] = ecc_dsa_sa_algo; + break; +#endif +#ifdef HAVE_ED25519 + case ed25519_sa_algo: + output[0] = ED25519_SA_MAJOR; + output[1] = ED25519_SA_MINOR; + (void)hashAlgo; + break; +#endif +#ifndef NO_RSA + case rsa_sa_algo: + output[0] = hashAlgo; + output[1] = rsa_sa_algo; + break; + #ifdef WC_RSA_PSS + /* PSS signatures: 0x080[4-6] */ + case rsa_pss_sa_algo: + output[0] = rsa_pss_sa_algo; + output[1] = hashAlgo; + break; + #endif +#endif + /* ED448: 0x0808 */ + } + (void)hashAlgo; + (void)output; +} +#endif + +#if !defined(WOLFSSL_NO_TLS12) && !defined(WOLFSSL_NO_CLIENT_AUTH) +static void SetDigest(WOLFSSL* ssl, int hashAlgo) +{ + switch (hashAlgo) { + #ifndef NO_SHA + case sha_mac: + ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha; + ssl->buffers.digest.length = WC_SHA_DIGEST_SIZE; + break; + #endif /* !NO_SHA */ + #ifndef NO_SHA256 + case sha256_mac: + ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha256; + ssl->buffers.digest.length = WC_SHA256_DIGEST_SIZE; + break; + #endif /* !NO_SHA256 */ + #ifdef WOLFSSL_SHA384 + case sha384_mac: + ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha384; + ssl->buffers.digest.length = WC_SHA384_DIGEST_SIZE; + break; + #endif /* WOLFSSL_SHA384 */ + #ifdef WOLFSSL_SHA512 + case sha512_mac: + ssl->buffers.digest.buffer = ssl->hsHashes->certHashes.sha512; + ssl->buffers.digest.length = WC_SHA512_DIGEST_SIZE; + break; + #endif /* WOLFSSL_SHA512 */ + } /* switch */ +} +#endif /* !WOLFSSL_NO_TLS12 && !WOLFSSL_NO_CLIENT_AUTH */ +#endif /* !NO_WOLFSSL_SERVER || !NO_WOLFSSL_CLIENT */ +#endif /* !NO_CERTS */ + +#ifndef NO_RSA +#ifndef WOLFSSL_NO_TLS12 +#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_WOLFSSL_CLIENT) +static int TypeHash(int hashAlgo) +{ + switch (hashAlgo) { + #ifdef WOLFSSL_SHA512 + case sha512_mac: + return SHA512h; + #endif + #ifdef WOLFSSL_SHA384 + case sha384_mac: + return SHA384h; + #endif + #ifndef NO_SHA256 + case sha256_mac: + return SHA256h; + #endif + #ifdef WOLFSSL_SHA224 + case sha224_mac: + return SHA224h; + #endif + #ifndef NO_SHA + case sha_mac: + return SHAh; + #endif + } + + return 0; +} +#endif /* !NO_WOLFSSL_SERVER && !NO_WOLFSSL_CLIENT */ +#endif /* !WOLFSSL_NO_TLS12 */ + +#if defined(WC_RSA_PSS) +int ConvertHashPss(int hashAlgo, enum wc_HashType* hashType, int* mgf) +{ + switch (hashAlgo) { + #ifdef WOLFSSL_SHA512 + case sha512_mac: + *hashType = WC_HASH_TYPE_SHA512; + if (mgf != NULL) + *mgf = WC_MGF1SHA512; + break; + #endif + #ifdef WOLFSSL_SHA384 + case sha384_mac: + *hashType = WC_HASH_TYPE_SHA384; + if (mgf != NULL) + *mgf = WC_MGF1SHA384; + break; + #endif + #ifndef NO_SHA256 + case sha256_mac: + *hashType = WC_HASH_TYPE_SHA256; + if (mgf != NULL) + *mgf = WC_MGF1SHA256; + break; + #endif + default: + return BAD_FUNC_ARG; + } + + return 0; +} +#endif + +int RsaSign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, + word32* outSz, int sigAlgo, int hashAlgo, RsaKey* key, + DerBuffer* keyBufInfo) +{ + int ret; +#ifdef HAVE_PK_CALLBACKS + const byte* keyBuf = NULL; + word32 keySz = 0; + + if (keyBufInfo) { + keyBuf = keyBufInfo->buffer; + keySz = keyBufInfo->length; + } +#endif + + (void)ssl; + (void)keyBufInfo; + (void)sigAlgo; + (void)hashAlgo; + + WOLFSSL_ENTER("RsaSign"); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* initialize event */ + if (key) { + ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + if (ret != 0) + return ret; + } +#endif + +#if defined(WC_RSA_PSS) + if (sigAlgo == rsa_pss_sa_algo) { + enum wc_HashType hashType = WC_HASH_TYPE_NONE; + int mgf = 0; + + ret = ConvertHashPss(hashAlgo, &hashType, &mgf); + if (ret != 0) + return ret; + + #if defined(HAVE_PK_CALLBACKS) + if (ssl->ctx->RsaPssSignCb) { + void* ctx = wolfSSL_GetRsaPssSignCtx(ssl); + ret = ssl->ctx->RsaPssSignCb(ssl, in, inSz, out, outSz, + TypeHash(hashAlgo), mgf, + keyBuf, keySz, ctx); + } + else + #endif + { + ret = wc_RsaPSS_Sign(in, inSz, out, *outSz, hashType, mgf, key, + ssl->rng); + } + } + else +#endif +#if defined(HAVE_PK_CALLBACKS) + if (ssl->ctx->RsaSignCb) { + void* ctx = wolfSSL_GetRsaSignCtx(ssl); + ret = ssl->ctx->RsaSignCb(ssl, in, inSz, out, outSz, keyBuf, keySz, + ctx); + } + else +#endif /*HAVE_PK_CALLBACKS */ + ret = wc_RsaSSL_Sign(in, inSz, out, *outSz, key, ssl->rng); + + /* Handle async pending response */ +#ifdef WOLFSSL_ASYNC_CRYPT + if (key && ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, &key->asyncDev); + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + /* For positive response return in outSz */ + if (ret > 0) { + *outSz = ret; + ret = 0; + } + + WOLFSSL_LEAVE("RsaSign", ret); + + return ret; +} + +int RsaVerify(WOLFSSL* ssl, byte* in, word32 inSz, byte** out, int sigAlgo, + int hashAlgo, RsaKey* key, buffer* keyBufInfo) +{ + int ret; +#ifdef HAVE_PK_CALLBACKS + const byte* keyBuf = NULL; + word32 keySz = 0; + + if (keyBufInfo) { + keyBuf = keyBufInfo->buffer; + keySz = keyBufInfo->length; + } +#endif + + (void)ssl; + (void)keyBufInfo; + (void)sigAlgo; + (void)hashAlgo; + + WOLFSSL_ENTER("RsaVerify"); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* initialize event */ + ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + if (ret != 0) + return ret; +#endif + +#if defined(WC_RSA_PSS) + if (sigAlgo == rsa_pss_sa_algo) { + enum wc_HashType hashType = WC_HASH_TYPE_NONE; + int mgf = 0; + + ret = ConvertHashPss(hashAlgo, &hashType, &mgf); + if (ret != 0) + return ret; +#ifdef HAVE_PK_CALLBACKS + if (ssl->ctx->RsaPssVerifyCb) { + void* ctx = wolfSSL_GetRsaPssVerifyCtx(ssl); + ret = ssl->ctx->RsaPssVerifyCb(ssl, in, inSz, out, + TypeHash(hashAlgo), mgf, + keyBuf, keySz, ctx); + } + else +#endif /*HAVE_PK_CALLBACKS */ + ret = wc_RsaPSS_VerifyInline(in, inSz, out, hashType, mgf, key); + } + else +#endif +#ifdef HAVE_PK_CALLBACKS + if (ssl->ctx->RsaVerifyCb) { + void* ctx = wolfSSL_GetRsaVerifyCtx(ssl); + ret = ssl->ctx->RsaVerifyCb(ssl, in, inSz, out, keyBuf, keySz, ctx); + } + else +#endif /*HAVE_PK_CALLBACKS */ + { + ret = wc_RsaSSL_VerifyInline(in, inSz, out, key); + } + + /* Handle async pending response */ +#ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, &key->asyncDev); + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + WOLFSSL_LEAVE("RsaVerify", ret); + + return ret; +} + +/* Verify RSA signature, 0 on success */ +/* This function is used to check the sign result */ +int VerifyRsaSign(WOLFSSL* ssl, byte* verifySig, word32 sigSz, + const byte* plain, word32 plainSz, int sigAlgo, int hashAlgo, RsaKey* key, + DerBuffer* keyBufInfo) +{ + byte* out = NULL; /* inline result */ + int ret; +#ifdef HAVE_PK_CALLBACKS + const byte* keyBuf = NULL; + word32 keySz = 0; + + if (keyBufInfo) { + keyBuf = keyBufInfo->buffer; + keySz = keyBufInfo->length; + } +#endif + + (void)ssl; + (void)keyBufInfo; + (void)sigAlgo; + (void)hashAlgo; + + WOLFSSL_ENTER("VerifyRsaSign"); + + if (verifySig == NULL || plain == NULL) { + return BAD_FUNC_ARG; + } + + if (sigSz > ENCRYPT_LEN) { + WOLFSSL_MSG("Signature buffer too big"); + return BUFFER_E; + } + +#ifdef WOLFSSL_ASYNC_CRYPT + /* initialize event */ + if (key) { + ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + if (ret != 0) + return ret; + } +#endif + +#if defined(WC_RSA_PSS) + if (sigAlgo == rsa_pss_sa_algo) { + enum wc_HashType hashType = WC_HASH_TYPE_NONE; + int mgf = 0; + + ret = ConvertHashPss(hashAlgo, &hashType, &mgf); + if (ret != 0) + return ret; + #ifdef HAVE_PK_CALLBACKS + if (ssl->ctx->RsaPssSignCheckCb) { + /* The key buffer includes private/public portion, + but only public is used */ + /* If HSM hardware is checking the signature result you can + optionally skip the sign check and return 0 */ + /* The ctx here is the RsaSignCtx set using wolfSSL_SetRsaSignCtx */ + void* ctx = wolfSSL_GetRsaPssSignCtx(ssl); + ret = ssl->ctx->RsaPssSignCheckCb(ssl, verifySig, sigSz, &out, + TypeHash(hashAlgo), mgf, + keyBuf, keySz, ctx); + } + else + #endif /* HAVE_PK_CALLBACKS */ + { + ret = wc_RsaPSS_VerifyInline(verifySig, sigSz, &out, hashType, mgf, + key); + } + + if (ret > 0) { + ret = wc_RsaPSS_CheckPadding(plain, plainSz, out, ret, hashType); + if (ret != 0) + ret = VERIFY_CERT_ERROR; + } + } + else +#endif /* WC_RSA_PSS */ + { + #ifdef HAVE_PK_CALLBACKS + if (ssl->ctx->RsaSignCheckCb) { + /* The key buffer includes private/public portion, + but only public is used */ + /* If HSM hardware is checking the signature result you can + optionally skip the sign check and return 0 */ + /* The ctx here is the RsaSignCtx set using wolfSSL_SetRsaSignCtx */ + void* ctx = wolfSSL_GetRsaSignCtx(ssl); + ret = ssl->ctx->RsaSignCheckCb(ssl, verifySig, sigSz, &out, + keyBuf, keySz, ctx); + } + else + #endif /* HAVE_PK_CALLBACKS */ + { + ret = wc_RsaSSL_VerifyInline(verifySig, sigSz, &out, key); + } + + if (ret > 0) { + if (ret != (int)plainSz || !out || + XMEMCMP(plain, out, plainSz) != 0) { + WOLFSSL_MSG("RSA Signature verification failed"); + ret = RSA_SIGN_FAULT; + } else { + ret = 0; /* RSA reset */ + } + } + } + + /* Handle async pending response */ +#ifdef WOLFSSL_ASYNC_CRYPT + if (key && ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, &key->asyncDev); + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + WOLFSSL_LEAVE("VerifyRsaSign", ret); + + return ret; +} + +#ifndef WOLFSSL_NO_TLS12 + +int RsaDec(WOLFSSL* ssl, byte* in, word32 inSz, byte** out, word32* outSz, + RsaKey* key, DerBuffer* keyBufInfo) +{ + int ret; +#ifdef HAVE_PK_CALLBACKS + const byte* keyBuf = NULL; + word32 keySz = 0; + + if (keyBufInfo) { + keyBuf = keyBufInfo->buffer; + keySz = keyBufInfo->length; + } +#endif + + (void)ssl; + (void)keyBufInfo; + + WOLFSSL_ENTER("RsaDec"); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* initialize event */ + ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + if (ret != 0) + return ret; +#endif + +#ifdef HAVE_PK_CALLBACKS + if (ssl->ctx->RsaDecCb) { + void* ctx = wolfSSL_GetRsaDecCtx(ssl); + ret = ssl->ctx->RsaDecCb(ssl, in, inSz, out, keyBuf, keySz, ctx); + } + else +#endif /* HAVE_PK_CALLBACKS */ + { + #ifdef WC_RSA_BLINDING + ret = wc_RsaSetRNG(key, ssl->rng); + if (ret != 0) + return ret; + #endif + ret = wc_RsaPrivateDecryptInline(in, inSz, out, key); + } + + /* Handle async pending response */ +#ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, &key->asyncDev); + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + /* For positive response return in outSz */ + if (ret > 0) { + *outSz = ret; + ret = 0; + } + + WOLFSSL_LEAVE("RsaDec", ret); + + return ret; +} + +int RsaEnc(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, word32* outSz, + RsaKey* key, buffer* keyBufInfo) +{ + int ret; +#ifdef HAVE_PK_CALLBACKS + const byte* keyBuf = NULL; + word32 keySz = 0; + + if (keyBufInfo) { + keyBuf = keyBufInfo->buffer; + keySz = keyBufInfo->length; + } +#endif + + (void)ssl; + (void)keyBufInfo; + + WOLFSSL_ENTER("RsaEnc"); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* initialize event */ + ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + if (ret != 0) + return ret; +#endif + +#ifdef HAVE_PK_CALLBACKS + if (ssl->ctx->RsaEncCb) { + void* ctx = wolfSSL_GetRsaEncCtx(ssl); + ret = ssl->ctx->RsaEncCb(ssl, in, inSz, out, outSz, keyBuf, keySz, ctx); + } + else +#endif /* HAVE_PK_CALLBACKS */ + { + ret = wc_RsaPublicEncrypt(in, inSz, out, *outSz, key, ssl->rng); + } + + /* Handle async pending response */ +#ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, &key->asyncDev); + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + /* For positive response return in outSz */ + if (ret > 0) { + *outSz = ret; + ret = 0; + } + + WOLFSSL_LEAVE("RsaEnc", ret); + + return ret; +} + +#endif /* !WOLFSSL_NO_TLS12 */ + +#endif /* NO_RSA */ + +#ifdef HAVE_ECC + +int EccSign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, + word32* outSz, ecc_key* key, DerBuffer* keyBufInfo) +{ + int ret; +#ifdef HAVE_PK_CALLBACKS + const byte* keyBuf = NULL; + word32 keySz = 0; + + if (keyBufInfo) { + keyBuf = keyBufInfo->buffer; + keySz = keyBufInfo->length; + } +#endif + + (void)ssl; + (void)keyBufInfo; + + WOLFSSL_ENTER("EccSign"); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* initialize event */ + if (key) { + ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + if (ret != 0) + return ret; + } +#endif + +#if defined(HAVE_PK_CALLBACKS) + if (ssl->ctx->EccSignCb) { + void* ctx = wolfSSL_GetEccSignCtx(ssl); + ret = ssl->ctx->EccSignCb(ssl, in, inSz, out, outSz, keyBuf, + keySz, ctx); + } + else +#endif /* HAVE_PK_CALLBACKS */ + { + ret = wc_ecc_sign_hash(in, inSz, out, outSz, ssl->rng, key); + } + + /* Handle async pending response */ +#ifdef WOLFSSL_ASYNC_CRYPT + if (key && ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, &key->asyncDev); + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + WOLFSSL_LEAVE("EccSign", ret); + + return ret; +} + +int EccVerify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* out, + word32 outSz, ecc_key* key, buffer* keyBufInfo) +{ + int ret; +#ifdef HAVE_PK_CALLBACKS + const byte* keyBuf = NULL; + word32 keySz = 0; + + if (keyBufInfo) { + keyBuf = keyBufInfo->buffer; + keySz = keyBufInfo->length; + } +#endif + + (void)ssl; + (void)keyBufInfo; + + WOLFSSL_ENTER("EccVerify"); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* initialize event */ + ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + if (ret != 0) + return ret; +#endif + +#ifdef HAVE_PK_CALLBACKS + if (ssl->ctx->EccVerifyCb) { + void* ctx = wolfSSL_GetEccVerifyCtx(ssl); + ret = ssl->ctx->EccVerifyCb(ssl, in, inSz, out, outSz, keyBuf, keySz, + &ssl->eccVerifyRes, ctx); + } + else +#endif /* HAVE_PK_CALLBACKS */ + { + ret = wc_ecc_verify_hash(in, inSz, out, outSz, &ssl->eccVerifyRes, key); + } + + /* Handle async pending response */ +#ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, &key->asyncDev); + } + else +#endif /* WOLFSSL_ASYNC_CRYPT */ + { + ret = (ret != 0 || ssl->eccVerifyRes == 0) ? VERIFY_SIGN_ERROR : 0; + } + + WOLFSSL_LEAVE("EccVerify", ret); + + return ret; +} + +#ifdef HAVE_PK_CALLBACKS + /* Gets ECC key for shared secret callback testing + * Client side: returns peer key + * Server side: returns private key + */ + static int EccGetKey(WOLFSSL* ssl, ecc_key** otherKey) + { + int ret = NO_PEER_KEY; + ecc_key* tmpKey = NULL; + + if (ssl == NULL || otherKey == NULL) { + return BAD_FUNC_ARG; + } + + if (ssl->options.side == WOLFSSL_CLIENT_END) { + if (ssl->specs.static_ecdh) { + if (!ssl->peerEccDsaKey || !ssl->peerEccDsaKeyPresent || + !ssl->peerEccDsaKey->dp) { + return NO_PEER_KEY; + } + tmpKey = (struct ecc_key*)ssl->peerEccDsaKey; + } + else { + if (!ssl->peerEccKey || !ssl->peerEccKeyPresent || + !ssl->peerEccKey->dp) { + return NO_PEER_KEY; + } + tmpKey = (struct ecc_key*)ssl->peerEccKey; + } + } + else if (ssl->options.side == WOLFSSL_SERVER_END) { + if (ssl->specs.static_ecdh) { + if (ssl->hsKey == NULL) { + return NO_PRIVATE_KEY; + } + tmpKey = (struct ecc_key*)ssl->hsKey; + } + else { + if (!ssl->eccTempKeyPresent) { + return NO_PRIVATE_KEY; + } + tmpKey = (struct ecc_key*)ssl->eccTempKey; + } + } + + if (tmpKey) { + *otherKey = tmpKey; + ret = 0; + } + + return ret; + } +#endif /* HAVE_PK_CALLBACKS */ + +int EccSharedSecret(WOLFSSL* ssl, ecc_key* priv_key, ecc_key* pub_key, + byte* pubKeyDer, word32* pubKeySz, byte* out, word32* outlen, + int side) +{ + int ret; +#ifdef HAVE_PK_CALLBACKS + ecc_key* otherKey = NULL; +#endif +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV* asyncDev = &priv_key->asyncDev; +#endif + + (void)ssl; + (void)pubKeyDer; + (void)pubKeySz; + (void)side; + + WOLFSSL_ENTER("EccSharedSecret"); + +#ifdef HAVE_PK_CALLBACKS + if (ssl->ctx->EccSharedSecretCb) { + ret = EccGetKey(ssl, &otherKey); + if (ret != 0) + return ret; + #ifdef WOLFSSL_ASYNC_CRYPT + asyncDev = &otherKey->asyncDev; + #endif + } +#endif + +#ifdef WOLFSSL_ASYNC_CRYPT + /* initialize event */ + ret = wolfSSL_AsyncInit(ssl, asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + if (ret != 0) + return ret; +#endif + +#ifdef HAVE_PK_CALLBACKS + if (ssl->ctx->EccSharedSecretCb) { + void* ctx = wolfSSL_GetEccSharedSecretCtx(ssl); + ret = ssl->ctx->EccSharedSecretCb(ssl, otherKey, pubKeyDer, + pubKeySz, out, outlen, side, ctx); + } + else +#endif + { + ret = wc_ecc_shared_secret(priv_key, pub_key, out, outlen); + } + + /* Handle async pending response */ +#ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, asyncDev); + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + WOLFSSL_LEAVE("EccSharedSecret", ret); + + return ret; +} + +int EccMakeKey(WOLFSSL* ssl, ecc_key* key, ecc_key* peer) +{ + int ret = 0; + int keySz = 0; + int ecc_curve = ECC_CURVE_DEF; + + WOLFSSL_ENTER("EccMakeKey"); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* initialize event */ + ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_NONE); + if (ret != 0) + return ret; +#endif + + /* get key size */ + if (peer == NULL) { + keySz = ssl->eccTempKeySz; + } + else { + keySz = peer->dp->size; + } + + /* get curve type */ + if (ssl->ecdhCurveOID > 0) { + ecc_curve = wc_ecc_get_oid(ssl->ecdhCurveOID, NULL, NULL); + } + +#ifdef HAVE_PK_CALLBACKS + if (ssl->ctx->EccKeyGenCb) { + void* ctx = wolfSSL_GetEccKeyGenCtx(ssl); + ret = ssl->ctx->EccKeyGenCb(ssl, key, keySz, ecc_curve, ctx); + } + else +#endif + { + ret = wc_ecc_make_key_ex(ssl->rng, keySz, key, ecc_curve); + } + + /* make sure the curve is set for TLS */ + if (ret == 0 && key->dp) { + ssl->ecdhCurveOID = key->dp->oidSum; + } + + /* Handle async pending response */ +#ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, &key->asyncDev); + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + WOLFSSL_LEAVE("EccMakeKey", ret); + + return ret; +} +#endif /* HAVE_ECC */ + +#ifdef HAVE_ED25519 +/* Check whether the key contains a public key. + * If not then pull it out of the leaf certificate. + * + * ssl SSL/TLS object. + * returns MEMORY_E when unable to allocate memory, a parsing error, otherwise + * 0 on success. + */ +int Ed25519CheckPubKey(WOLFSSL* ssl) +{ + ed25519_key* key = (ed25519_key*)ssl->hsKey; + int ret = 0; + + /* Public key required for signing. */ + if (!key->pubKeySet) { + DerBuffer* leaf = ssl->buffers.certificate; + DecodedCert* cert = (DecodedCert*)XMALLOC(sizeof(*cert), + ssl->heap, DYNAMIC_TYPE_DCERT); + if (cert == NULL) + ret = MEMORY_E; + + if (ret == 0) { + InitDecodedCert(cert, leaf->buffer, leaf->length, ssl->heap); + ret = DecodeToKey(cert, 0); + } + if (ret == 0) { + ret = wc_ed25519_import_public(cert->publicKey, cert->pubKeySize, + key); + } + if (cert != NULL) { + FreeDecodedCert(cert); + XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT); + } + } + + return ret; +} + +/* Sign the data using EdDSA and key using Ed25519. + * + * ssl SSL object. + * in Data or message to sign. + * inSz Length of the data. + * out Buffer to hold signature. + * outSz On entry, size of the buffer. On exit, the size of the signature. + * key The private Ed25519 key data. + * keySz The length of the private key data in bytes. + * ctx The callback context. + * returns 0 on success, otherwise the value is an error. + */ +int Ed25519Sign(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, + word32* outSz, ed25519_key* key, DerBuffer* keyBufInfo) +{ + int ret; +#ifdef HAVE_PK_CALLBACKS + const byte* keyBuf = NULL; + word32 keySz = 0; + + if (keyBufInfo) { + keyBuf = keyBufInfo->buffer; + keySz = keyBufInfo->length; + } +#endif + + (void)ssl; + (void)keyBufInfo; + + WOLFSSL_ENTER("Ed25519Sign"); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* initialize event */ + ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + if (ret != 0) + return ret; +#endif + +#if defined(HAVE_PK_CALLBACKS) + if (ssl->ctx->Ed25519SignCb) { + void* ctx = wolfSSL_GetEd25519SignCtx(ssl); + ret = ssl->ctx->Ed25519SignCb(ssl, in, inSz, out, outSz, keyBuf, + keySz, ctx); + } + else +#endif /* HAVE_PK_CALLBACKS */ + { + ret = wc_ed25519_sign_msg(in, inSz, out, outSz, key); + } + + /* Handle async pending response */ +#ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, &key->asyncDev); + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + WOLFSSL_LEAVE("Ed25519Sign", ret); + + return ret; +} + +/* Verify the data using EdDSA and key using Ed25519. + * + * ssl SSL object. + * in Signature data. + * inSz Length of the signature data in bytes. + * msg Message to verify. + * outSz Length of message in bytes. + * key The public Ed25519 key data. + * keySz The length of the private key data in bytes. + * ctx The callback context. + * returns 0 on success, otherwise the value is an error. + */ +int Ed25519Verify(WOLFSSL* ssl, const byte* in, word32 inSz, const byte* msg, + word32 msgSz, ed25519_key* key, buffer* keyBufInfo) +{ + int ret; +#ifdef HAVE_PK_CALLBACKS + const byte* keyBuf = NULL; + word32 keySz = 0; + + if (keyBufInfo) { + keyBuf = keyBufInfo->buffer; + keySz = keyBufInfo->length; + } +#endif + + (void)ssl; + (void)keyBufInfo; + + WOLFSSL_ENTER("Ed25519Verify"); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* initialize event */ + ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + if (ret != 0) + return ret; +#endif + +#ifdef HAVE_PK_CALLBACKS + if (ssl->ctx->Ed25519VerifyCb) { + void* ctx = wolfSSL_GetEd25519VerifyCtx(ssl); + ret = ssl->ctx->Ed25519VerifyCb(ssl, in, inSz, msg, msgSz, keyBuf, + keySz, &ssl->eccVerifyRes, ctx); + } + else +#endif /* HAVE_PK_CALLBACKS */ + { + ret = wc_ed25519_verify_msg(in, inSz, msg, msgSz, + &ssl->eccVerifyRes, key); + } + + /* Handle async pending response */ +#ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, &key->asyncDev); + } + else +#endif /* WOLFSSL_ASYNC_CRYPT */ + { + ret = (ret != 0 || ssl->eccVerifyRes == 0) ? VERIFY_SIGN_ERROR : 0; + } + + WOLFSSL_LEAVE("Ed25519Verify", ret); + + return ret; +} +#endif /* HAVE_ED25519 */ + +#ifndef WOLFSSL_NO_TLS12 + +#ifdef HAVE_CURVE25519 +#ifdef HAVE_PK_CALLBACKS + /* Gets X25519 key for shared secret callback testing + * Client side: returns peer key + * Server side: returns private key + */ + static int X25519GetKey(WOLFSSL* ssl, curve25519_key** otherKey) + { + int ret = NO_PEER_KEY; + struct curve25519_key* tmpKey = NULL; + + if (ssl == NULL || otherKey == NULL) { + return BAD_FUNC_ARG; + } + + if (ssl->options.side == WOLFSSL_CLIENT_END) { + if (!ssl->peerX25519Key || !ssl->peerX25519KeyPresent || + !ssl->peerX25519Key->dp) { + return NO_PEER_KEY; + } + tmpKey = (struct curve25519_key*)ssl->peerX25519Key; + } + else if (ssl->options.side == WOLFSSL_SERVER_END) { + if (!ssl->eccTempKeyPresent) { + return NO_PRIVATE_KEY; + } + tmpKey = (struct curve25519_key*)ssl->eccTempKey; + } + + if (tmpKey) { + *otherKey = (curve25519_key *)tmpKey; + ret = 0; + } + + return ret; + } +#endif /* HAVE_PK_CALLBACKS */ + +static int X25519SharedSecret(WOLFSSL* ssl, curve25519_key* priv_key, + curve25519_key* pub_key, byte* pubKeyDer, word32* pubKeySz, + byte* out, word32* outlen, int side) +{ + int ret; + + (void)ssl; + (void)pubKeyDer; + (void)pubKeySz; + (void)side; + + WOLFSSL_ENTER("X25519SharedSecret"); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* initialize event */ + ret = wolfSSL_AsyncInit(ssl, &priv_key->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + if (ret != 0) + return ret; +#endif + +#ifdef HAVE_PK_CALLBACKS + if (ssl->ctx->X25519SharedSecretCb) { + curve25519_key* otherKey = NULL; + + ret = X25519GetKey(ssl, &otherKey); + if (ret == 0) { + void* ctx = wolfSSL_GetX25519SharedSecretCtx(ssl); + ret = ssl->ctx->X25519SharedSecretCb(ssl, otherKey, pubKeyDer, + pubKeySz, out, outlen, side, ctx); + } + } + else +#endif + { + ret = wc_curve25519_shared_secret_ex(priv_key, pub_key, out, outlen, + EC25519_LITTLE_ENDIAN); + } + + /* Handle async pending response */ +#ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, &priv_key->asyncDev); + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + WOLFSSL_LEAVE("X25519SharedSecret", ret); + + return ret; +} + +static int X25519MakeKey(WOLFSSL* ssl, curve25519_key* key, + curve25519_key* peer) +{ + int ret = 0; + + (void)peer; + + WOLFSSL_ENTER("X25519MakeKey"); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* initialize event */ + ret = wolfSSL_AsyncInit(ssl, &key->asyncDev, WC_ASYNC_FLAG_NONE); + if (ret != 0) + return ret; +#endif + +#ifdef HAVE_PK_CALLBACKS + if (ssl->ctx->X25519KeyGenCb) { + void* ctx = wolfSSL_GetX25519KeyGenCtx(ssl); + ret = ssl->ctx->X25519KeyGenCb(ssl, key, CURVE25519_KEYSIZE, ctx); + } + else +#endif + { + ret = wc_curve25519_make_key(ssl->rng, CURVE25519_KEYSIZE, key); + } + + if (ret == 0) { + ssl->ecdhCurveOID = ECC_X25519_OID; + } + + /* Handle async pending response */ +#ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, &key->asyncDev); + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + WOLFSSL_LEAVE("X25519MakeKey", ret); + + return ret; +} +#endif /* HAVE_CURVE25519 */ + +#if !defined(NO_CERTS) || !defined(NO_PSK) +#if !defined(NO_DH) + +int DhGenKeyPair(WOLFSSL* ssl, DhKey* dhKey, + byte* priv, word32* privSz, + byte* pub, word32* pubSz) +{ + int ret; + + WOLFSSL_ENTER("DhGenKeyPair"); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* initialize event */ + ret = wolfSSL_AsyncInit(ssl, &dhKey->asyncDev, WC_ASYNC_FLAG_NONE); + if (ret != 0) + return ret; +#endif + + ret = wc_DhGenerateKeyPair(dhKey, ssl->rng, priv, privSz, pub, pubSz); + + /* Handle async pending response */ +#ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, &dhKey->asyncDev); + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + WOLFSSL_LEAVE("DhGenKeyPair", ret); + + return ret; +} + +int DhAgree(WOLFSSL* ssl, DhKey* dhKey, + const byte* priv, word32 privSz, + const byte* otherPub, word32 otherPubSz, + byte* agree, word32* agreeSz) +{ + int ret; + + (void)ssl; + + WOLFSSL_ENTER("DhAgree"); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* initialize event */ + ret = wolfSSL_AsyncInit(ssl, &dhKey->asyncDev, WC_ASYNC_FLAG_NONE); + if (ret != 0) + return ret; +#endif + +#ifdef HAVE_PK_CALLBACKS + if (ssl->ctx->DhAgreeCb) { + void* ctx = wolfSSL_GetDhAgreeCtx(ssl); + + WOLFSSL_MSG("Calling DhAgree Callback Function"); + ret = ssl->ctx->DhAgreeCb(ssl, dhKey, priv, privSz, + otherPub, otherPubSz, agree, agreeSz, ctx); + } + else +#endif + { +#if !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) + ret = wc_DhCheckPubValue(ssl->buffers.serverDH_P.buffer, + ssl->buffers.serverDH_P.length, otherPub, otherPubSz); + if (ret != 0) { + #ifdef OPENSSL_EXTRA + SendAlert(ssl, alert_fatal, illegal_parameter); + #endif + } + else +#endif + { + ret = wc_DhAgree(dhKey, agree, agreeSz, priv, privSz, otherPub, + otherPubSz); + } + } + + /* Handle async pending response */ +#ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, &dhKey->asyncDev); + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + WOLFSSL_LEAVE("DhAgree", ret); + + return ret; +} +#endif /* !NO_DH */ +#endif /* !NO_CERTS || !NO_PSK */ + +#endif /* !WOLFSSL_NO_TLS12 */ + + +#ifdef HAVE_PK_CALLBACKS +int wolfSSL_CTX_IsPrivatePkSet(WOLFSSL_CTX* ctx) +{ + int pkcbset = 0; + (void)ctx; +#if defined(HAVE_ECC) || defined(HAVE_ED25519) || !defined(NO_RSA) + if (0 + #ifdef HAVE_ECC + || ctx->EccSignCb != NULL + #endif + #ifdef HAVE_ED25519 + || ctx->Ed25519SignCb != NULL + #endif + #ifndef NO_RSA + || ctx->RsaSignCb != NULL + || ctx->RsaDecCb != NULL + #ifdef WC_RSA_PSS + || ctx->RsaPssSignCb != NULL + #endif + #endif + ) { + pkcbset = 1; + } +#endif + return pkcbset; +} +#endif /* HAVE_PK_CALLBACKS */ + + +int InitSSL_Suites(WOLFSSL* ssl) +{ + int keySz = 0; + byte havePSK = 0; + byte haveAnon = 0; + byte haveRSA = 0; + byte haveMcast = 0; + + (void)haveAnon; /* Squash unused var warnings */ + (void)haveMcast; + + if (!ssl) + return BAD_FUNC_ARG; + +#ifndef NO_RSA + haveRSA = 1; +#endif +#ifndef NO_PSK + havePSK = (byte)ssl->options.havePSK; +#endif /* NO_PSK */ +#ifdef HAVE_ANON + haveAnon = ssl->options.haveAnon; +#endif /* HAVE_ANON*/ +#ifdef WOLFSSL_MULTICAST + haveMcast = ssl->options.haveMcast; +#endif /* WOLFSSL_MULTICAST */ + +#ifdef WOLFSSL_EARLY_DATA + if (ssl->options.side == WOLFSSL_SERVER_END) + ssl->options.maxEarlyDataSz = ssl->ctx->maxEarlyDataSz; +#endif +#if !defined(WOLFSSL_NO_CLIENT_AUTH) && defined(HAVE_ED25519) && \ + !defined(NO_ED25519_CLIENT_AUTH) + ssl->options.cacheMessages = ssl->options.side == WOLFSSL_SERVER_END || + ssl->buffers.keyType == ed25519_sa_algo; +#endif + +#ifndef NO_CERTS + keySz = ssl->buffers.keySz; +#endif + + /* make sure server has DH parms, and add PSK if there, add NTRU too */ + if (ssl->options.side == WOLFSSL_SERVER_END) { + InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK, + ssl->options.haveDH, ssl->options.haveNTRU, + ssl->options.haveECDSAsig, ssl->options.haveECC, + ssl->options.haveStaticECC, ssl->options.side); + } + else { + InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK, + TRUE, ssl->options.haveNTRU, + ssl->options.haveECDSAsig, ssl->options.haveECC, + ssl->options.haveStaticECC, ssl->options.side); + } + +#if !defined(NO_CERTS) && !defined(WOLFSSL_SESSION_EXPORT) + /* make sure server has cert and key unless using PSK, Anon, or + * Multicast. This should be true even if just switching ssl ctx */ + if (ssl->options.side == WOLFSSL_SERVER_END && + !havePSK && !haveAnon && !haveMcast) { + + /* server certificate must be loaded */ + if (!ssl->buffers.certificate || !ssl->buffers.certificate->buffer) { + WOLFSSL_MSG("Server missing certificate"); + return NO_PRIVATE_KEY; + } + + /* allow no private key if using PK callbacks and CB is set */ + #ifdef HAVE_PK_CALLBACKS + if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) { + WOLFSSL_MSG("Using PK for server private key"); + } + else + #endif + if (!ssl->buffers.key || !ssl->buffers.key->buffer) { + WOLFSSL_MSG("Server missing private key"); + return NO_PRIVATE_KEY; + } + } +#endif + + return WOLFSSL_SUCCESS; +} + +/* This function inherits a WOLFSSL_CTX's fields into an SSL object. + It is used during initialization and to switch an ssl's CTX with + wolfSSL_Set_SSL_CTX. Requires ssl->suites alloc and ssl-arrays with PSK + unless writeDup is on. + + ssl object to initialize + ctx parent factory + writeDup flag indicating this is a write dup only + + WOLFSSL_SUCCESS return value on success */ +int SetSSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) +{ + int ret = WOLFSSL_SUCCESS; + byte newSSL; + + if (!ssl || !ctx) + return BAD_FUNC_ARG; + +#ifndef SINGLE_THREADED + if (ssl->suites == NULL && !writeDup) + return BAD_FUNC_ARG; +#endif + + newSSL = ssl->ctx == NULL; /* Assign after null check */ + +#ifndef NO_PSK + if (ctx->server_hint[0] && ssl->arrays == NULL && !writeDup) { + return BAD_FUNC_ARG; /* needed for copy below */ + } +#endif + + /* decrement previous CTX reference count if exists. + * This should only happen if switching ctxs!*/ + if (!newSSL) { + WOLFSSL_MSG("freeing old ctx to decrement reference count. Switching ctx."); + wolfSSL_CTX_free(ssl->ctx); + } + + /* increment CTX reference count */ + if (wc_LockMutex(&ctx->countMutex) != 0) { + WOLFSSL_MSG("Couldn't lock CTX count mutex"); + return BAD_MUTEX_E; + } + ctx->refCount++; + wc_UnLockMutex(&ctx->countMutex); + ssl->ctx = ctx; /* only for passing to calls, options could change */ + ssl->version = ctx->method->version; + +#ifdef HAVE_ECC + ssl->eccTempKeySz = ctx->eccTempKeySz; + ssl->ecdhCurveOID = ctx->ecdhCurveOID; +#endif +#if defined(HAVE_ECC) || defined(HAVE_ED25519) + ssl->pkCurveOID = ctx->pkCurveOID; +#endif + +#ifdef OPENSSL_EXTRA + ssl->options.mask = ctx->mask; + ssl->CBIS = ctx->CBIS; +#endif + ssl->timeout = ctx->timeout; + ssl->verifyCallback = ctx->verifyCallback; + ssl->options.side = ctx->method->side; + ssl->options.downgrade = ctx->method->downgrade; + ssl->options.minDowngrade = ctx->minDowngrade; + + ssl->options.haveDH = ctx->haveDH; + ssl->options.haveNTRU = ctx->haveNTRU; + ssl->options.haveECDSAsig = ctx->haveECDSAsig; + ssl->options.haveECC = ctx->haveECC; + ssl->options.haveStaticECC = ctx->haveStaticECC; + +#ifndef NO_PSK + ssl->options.havePSK = ctx->havePSK; + ssl->options.client_psk_cb = ctx->client_psk_cb; + ssl->options.server_psk_cb = ctx->server_psk_cb; +#ifdef WOLFSSL_TLS13 + ssl->options.client_psk_tls13_cb = ctx->client_psk_tls13_cb; + ssl->options.server_psk_tls13_cb = ctx->server_psk_tls13_cb; +#endif +#endif /* NO_PSK */ +#ifdef WOLFSSL_EARLY_DATA + if (ssl->options.side == WOLFSSL_SERVER_END) + ssl->options.maxEarlyDataSz = ctx->maxEarlyDataSz; +#endif + +#ifdef HAVE_ANON + ssl->options.haveAnon = ctx->haveAnon; +#endif +#ifndef NO_DH + ssl->options.minDhKeySz = ctx->minDhKeySz; + ssl->options.maxDhKeySz = ctx->maxDhKeySz; +#endif +#ifndef NO_RSA + ssl->options.minRsaKeySz = ctx->minRsaKeySz; +#endif +#ifdef HAVE_ECC + ssl->options.minEccKeySz = ctx->minEccKeySz; +#endif +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + ssl->options.verifyDepth = ctx->verifyDepth; +#endif + + ssl->options.sessionCacheOff = ctx->sessionCacheOff; + ssl->options.sessionCacheFlushOff = ctx->sessionCacheFlushOff; +#ifdef HAVE_EXT_CACHE + ssl->options.internalCacheOff = ctx->internalCacheOff; +#endif + + ssl->options.verifyPeer = ctx->verifyPeer; + ssl->options.verifyNone = ctx->verifyNone; + ssl->options.failNoCert = ctx->failNoCert; + ssl->options.failNoCertxPSK = ctx->failNoCertxPSK; + ssl->options.sendVerify = ctx->sendVerify; + + ssl->options.partialWrite = ctx->partialWrite; + ssl->options.quietShutdown = ctx->quietShutdown; + ssl->options.groupMessages = ctx->groupMessages; + +#ifndef NO_DH + #if !defined(WOLFSSL_OLD_PRIME_CHECK) && !defined(HAVE_FIPS) && \ + !defined(HAVE_SELFTEST) + ssl->options.dhKeyTested = ctx->dhKeyTested; + #endif + ssl->buffers.serverDH_P = ctx->serverDH_P; + ssl->buffers.serverDH_G = ctx->serverDH_G; +#endif + +#ifndef NO_CERTS + /* ctx still owns certificate, certChain, key, dh, and cm */ + ssl->buffers.certificate = ctx->certificate; + ssl->buffers.certChain = ctx->certChain; +#ifdef WOLFSSL_TLS13 + ssl->buffers.certChainCnt = ctx->certChainCnt; +#endif + ssl->buffers.key = ctx->privateKey; + ssl->buffers.keyType = ctx->privateKeyType; + ssl->buffers.keyId = ctx->privateKeyId; + ssl->buffers.keySz = ctx->privateKeySz; + ssl->buffers.keyDevId = ctx->privateKeyDevId; +#endif +#if !defined(WOLFSSL_NO_CLIENT_AUTH) && defined(HAVE_ED25519) && \ + !defined(NO_ED25519_CLIENT_AUTH) + ssl->options.cacheMessages = ssl->options.side == WOLFSSL_SERVER_END || + ssl->buffers.keyType == ed25519_sa_algo; +#endif + + +#ifdef WOLFSSL_ASYNC_CRYPT + ssl->devId = ctx->devId; +#endif + + if (writeDup == 0) { +#ifndef NO_PSK + if (ctx->server_hint[0]) { /* set in CTX */ + XSTRNCPY(ssl->arrays->server_hint, ctx->server_hint, + sizeof(ssl->arrays->server_hint)); + ssl->arrays->server_hint[MAX_PSK_ID_LEN] = '\0'; /* null term */ + } +#endif /* NO_PSK */ + + if (ctx->suites) { +#ifndef SINGLE_THREADED + *ssl->suites = *ctx->suites; +#else + ssl->suites = ctx->suites; +#endif + } + else { + XMEMSET(ssl->suites, 0, sizeof(Suites)); + } + + if (ssl->options.side != WOLFSSL_NEITHER_END) { + /* Defer initializing suites until accept or connect */ + ret = InitSSL_Suites(ssl); + } + } /* writeDup check */ + +#ifdef WOLFSSL_SESSION_EXPORT + #ifdef WOLFSSL_DTLS + ssl->dtls_export = ctx->dtls_export; /* export function for session */ + #endif +#endif + + ssl->CBIORecv = ctx->CBIORecv; + ssl->CBIOSend = ctx->CBIOSend; +#ifdef OPENSSL_EXTRA + ssl->readAhead = ctx->readAhead; +#endif + ssl->verifyDepth = ctx->verifyDepth; + + return ret; +} + +int InitHandshakeHashes(WOLFSSL* ssl) +{ + int ret; + + /* make sure existing handshake hashes are free'd */ + if (ssl->hsHashes != NULL) { + FreeHandshakeHashes(ssl); + } + + /* allocate handshake hashes */ + ssl->hsHashes = (HS_Hashes*)XMALLOC(sizeof(HS_Hashes), ssl->heap, + DYNAMIC_TYPE_HASHES); + if (ssl->hsHashes == NULL) { + WOLFSSL_MSG("HS_Hashes Memory error"); + return MEMORY_E; + } + XMEMSET(ssl->hsHashes, 0, sizeof(HS_Hashes)); + +#ifndef NO_OLD_TLS +#ifndef NO_MD5 + ret = wc_InitMd5_ex(&ssl->hsHashes->hashMd5, ssl->heap, ssl->devId); + if (ret != 0) + return ret; + #if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + wc_Md5SetFlags(&ssl->hsHashes->hashMd5, WC_HASH_FLAG_WILLCOPY); + #endif +#endif +#ifndef NO_SHA + ret = wc_InitSha_ex(&ssl->hsHashes->hashSha, ssl->heap, ssl->devId); + if (ret != 0) + return ret; + #if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + wc_ShaSetFlags(&ssl->hsHashes->hashSha, WC_HASH_FLAG_WILLCOPY); + #endif +#endif +#endif /* !NO_OLD_TLS */ +#ifndef NO_SHA256 + ret = wc_InitSha256_ex(&ssl->hsHashes->hashSha256, ssl->heap, ssl->devId); + if (ret != 0) + return ret; + #if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + wc_Sha256SetFlags(&ssl->hsHashes->hashSha256, WC_HASH_FLAG_WILLCOPY); + #endif +#endif +#ifdef WOLFSSL_SHA384 + ret = wc_InitSha384_ex(&ssl->hsHashes->hashSha384, ssl->heap, ssl->devId); + if (ret != 0) + return ret; + #if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + wc_Sha384SetFlags(&ssl->hsHashes->hashSha384, WC_HASH_FLAG_WILLCOPY); + #endif +#endif +#ifdef WOLFSSL_SHA512 + ret = wc_InitSha512_ex(&ssl->hsHashes->hashSha512, ssl->heap, ssl->devId); + if (ret != 0) + return ret; + #if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + wc_Sha512SetFlags(&ssl->hsHashes->hashSha512, WC_HASH_FLAG_WILLCOPY); + #endif +#endif + + return ret; +} + +void FreeHandshakeHashes(WOLFSSL* ssl) +{ + if (ssl->hsHashes) { +#ifndef NO_OLD_TLS + #ifndef NO_MD5 + wc_Md5Free(&ssl->hsHashes->hashMd5); + #endif + #ifndef NO_SHA + wc_ShaFree(&ssl->hsHashes->hashSha); + #endif +#endif /* !NO_OLD_TLS */ + #ifndef NO_SHA256 + wc_Sha256Free(&ssl->hsHashes->hashSha256); + #endif + #ifdef WOLFSSL_SHA384 + wc_Sha384Free(&ssl->hsHashes->hashSha384); + #endif + #ifdef WOLFSSL_SHA512 + wc_Sha512Free(&ssl->hsHashes->hashSha512); + #endif + #if defined(HAVE_ED25519) && !defined(WOLFSSL_NO_CLIENT_AUTH) + if (ssl->hsHashes->messages != NULL) { + XFREE(ssl->hsHashes->messages, ssl->heap, DYNAMIC_TYPE_HASHES); + ssl->hsHashes->messages = NULL; + } + #endif + + XFREE(ssl->hsHashes, ssl->heap, DYNAMIC_TYPE_HASHES); + ssl->hsHashes = NULL; + } +} + + +/* init everything to 0, NULL, default values before calling anything that may + fail so that destructor has a "good" state to cleanup + + ssl object to initialize + ctx parent factory + writeDup flag indicating this is a write dup only + + 0 on success */ +int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup) +{ + int ret; + + XMEMSET(ssl, 0, sizeof(WOLFSSL)); + +#if defined(WOLFSSL_STATIC_MEMORY) + if (ctx->heap != NULL) { + WOLFSSL_HEAP_HINT* ssl_hint; + WOLFSSL_HEAP_HINT* ctx_hint; + + /* avoid derefrencing a test value */ + #ifdef WOLFSSL_HEAP_TEST + if (ctx->heap == (void*)WOLFSSL_HEAP_TEST) { + ssl->heap = ctx->heap; + } + else { + #endif + ssl->heap = (WOLFSSL_HEAP_HINT*)XMALLOC(sizeof(WOLFSSL_HEAP_HINT), + ctx->heap, DYNAMIC_TYPE_SSL); + if (ssl->heap == NULL) { + return MEMORY_E; + } + XMEMSET(ssl->heap, 0, sizeof(WOLFSSL_HEAP_HINT)); + ssl_hint = ((WOLFSSL_HEAP_HINT*)(ssl->heap)); + ctx_hint = ((WOLFSSL_HEAP_HINT*)(ctx->heap)); + + /* lock and check IO count / handshake count */ + if (wc_LockMutex(&(ctx_hint->memory->memory_mutex)) != 0) { + WOLFSSL_MSG("Bad memory_mutex lock"); + XFREE(ssl->heap, ctx->heap, DYNAMIC_TYPE_SSL); + ssl->heap = NULL; /* free and set to NULL for IO counter */ + return BAD_MUTEX_E; + } + if (ctx_hint->memory->maxHa > 0 && + ctx_hint->memory->maxHa <= ctx_hint->memory->curHa) { + WOLFSSL_MSG("At max number of handshakes for static memory"); + wc_UnLockMutex(&(ctx_hint->memory->memory_mutex)); + XFREE(ssl->heap, ctx->heap, DYNAMIC_TYPE_SSL); + ssl->heap = NULL; /* free and set to NULL for IO counter */ + return MEMORY_E; + } + + if (ctx_hint->memory->maxIO > 0 && + ctx_hint->memory->maxIO <= ctx_hint->memory->curIO) { + WOLFSSL_MSG("At max number of IO allowed for static memory"); + wc_UnLockMutex(&(ctx_hint->memory->memory_mutex)); + XFREE(ssl->heap, ctx->heap, DYNAMIC_TYPE_SSL); + ssl->heap = NULL; /* free and set to NULL for IO counter */ + return MEMORY_E; + } + ctx_hint->memory->curIO++; + ctx_hint->memory->curHa++; + ssl_hint->memory = ctx_hint->memory; + ssl_hint->haFlag = 1; + wc_UnLockMutex(&(ctx_hint->memory->memory_mutex)); + + /* check if tracking stats */ + if (ctx_hint->memory->flag & WOLFMEM_TRACK_STATS) { + ssl_hint->stats = (WOLFSSL_MEM_CONN_STATS*)XMALLOC( + sizeof(WOLFSSL_MEM_CONN_STATS), ctx->heap, DYNAMIC_TYPE_SSL); + if (ssl_hint->stats == NULL) { + return MEMORY_E; + } + XMEMSET(ssl_hint->stats, 0, sizeof(WOLFSSL_MEM_CONN_STATS)); + } + + /* check if using fixed IO buffers */ + if (ctx_hint->memory->flag & WOLFMEM_IO_POOL_FIXED) { + if (wc_LockMutex(&(ctx_hint->memory->memory_mutex)) != 0) { + WOLFSSL_MSG("Bad memory_mutex lock"); + return BAD_MUTEX_E; + } + if (SetFixedIO(ctx_hint->memory, &(ssl_hint->inBuf)) != 1) { + wc_UnLockMutex(&(ctx_hint->memory->memory_mutex)); + return MEMORY_E; + } + if (SetFixedIO(ctx_hint->memory, &(ssl_hint->outBuf)) != 1) { + wc_UnLockMutex(&(ctx_hint->memory->memory_mutex)); + return MEMORY_E; + } + if (ssl_hint->outBuf == NULL || ssl_hint->inBuf == NULL) { + WOLFSSL_MSG("Not enough memory to create fixed IO buffers"); + wc_UnLockMutex(&(ctx_hint->memory->memory_mutex)); + return MEMORY_E; + } + wc_UnLockMutex(&(ctx_hint->memory->memory_mutex)); + } + #ifdef WOLFSSL_HEAP_TEST + } + #endif + } + else { + ssl->heap = ctx->heap; + } +#else + ssl->heap = ctx->heap; /* carry over user heap without static memory */ +#endif /* WOLFSSL_STATIC_MEMORY */ + + ssl->buffers.inputBuffer.buffer = ssl->buffers.inputBuffer.staticBuffer; + ssl->buffers.inputBuffer.bufferSize = STATIC_BUFFER_LEN; + + ssl->buffers.outputBuffer.buffer = ssl->buffers.outputBuffer.staticBuffer; + ssl->buffers.outputBuffer.bufferSize = STATIC_BUFFER_LEN; + +#ifdef KEEP_PEER_CERT + InitX509(&ssl->peerCert, 0, ssl->heap); +#endif + + ssl->rfd = -1; /* set to invalid descriptor */ + ssl->wfd = -1; + ssl->devId = ctx->devId; /* device for async HW (from wolfAsync_DevOpen) */ + + ssl->IOCB_ReadCtx = &ssl->rfd; /* prevent invalid pointer access if not */ + ssl->IOCB_WriteCtx = &ssl->wfd; /* correctly set */ + +#ifdef HAVE_NETX + ssl->IOCB_ReadCtx = &ssl->nxCtx; /* default NetX IO ctx, same for read */ + ssl->IOCB_WriteCtx = &ssl->nxCtx; /* and write */ +#elif defined(WOLFSSL_APACHE_MYNEWT) && !defined(WOLFSSL_LWIP) + ssl->mnCtx = mynewt_ctx_new(); + if(!ssl->mnCtx) { + return MEMORY_E; + } + ssl->IOCB_ReadCtx = ssl->mnCtx; /* default Mynewt IO ctx, same for read */ + ssl->IOCB_WriteCtx = ssl->mnCtx; /* and write */ +#endif + + /* initialize states */ + ssl->options.serverState = NULL_STATE; + ssl->options.clientState = NULL_STATE; + ssl->options.connectState = CONNECT_BEGIN; + ssl->options.acceptState = ACCEPT_BEGIN; + ssl->options.handShakeState = NULL_STATE; + ssl->options.processReply = doProcessInit; + ssl->options.asyncState = TLS_ASYNC_BEGIN; + ssl->options.buildMsgState = BUILD_MSG_BEGIN; + ssl->encrypt.state = CIPHER_STATE_BEGIN; + ssl->decrypt.state = CIPHER_STATE_BEGIN; +#ifndef NO_DH + #if !defined(WOLFSSL_OLD_PRIME_CHECK) && !defined(HAVE_FIPS) && \ + !defined(HAVE_SELFTEST) + ssl->options.dhDoKeyTest = 1; + #endif +#endif + +#ifdef WOLFSSL_DTLS + #ifdef WOLFSSL_SCTP + ssl->options.dtlsSctp = ctx->dtlsSctp; + ssl->dtlsMtuSz = ctx->dtlsMtuSz; + ssl->dtls_expected_rx = ssl->dtlsMtuSz; + #else + ssl->dtls_expected_rx = MAX_MTU; + #endif + ssl->dtls_timeout_init = DTLS_TIMEOUT_INIT; + ssl->dtls_timeout_max = DTLS_TIMEOUT_MAX; + ssl->dtls_timeout = ssl->dtls_timeout_init; + ssl->buffers.dtlsCtx.rfd = -1; + ssl->buffers.dtlsCtx.wfd = -1; +#endif + +#ifndef WOLFSSL_AEAD_ONLY + #ifndef NO_OLD_TLS + ssl->hmac = SSL_hmac; /* default to SSLv3 */ + #elif !defined(WOLFSSL_NO_TLS12) + ssl->hmac = TLS_hmac; + #endif +#endif + + + ssl->cipher.ssl = ssl; + +#ifdef HAVE_EXTENDED_MASTER + ssl->options.haveEMS = ctx->haveEMS; +#endif + ssl->options.useClientOrder = ctx->useClientOrder; + +#ifdef WOLFSSL_TLS13 + #ifdef HAVE_SESSION_TICKET + ssl->options.noTicketTls13 = ctx->noTicketTls13; + #endif + ssl->options.noPskDheKe = ctx->noPskDheKe; + #if defined(WOLFSSL_POST_HANDSHAKE_AUTH) + ssl->options.postHandshakeAuth = ctx->postHandshakeAuth; + #endif + + if (ctx->numGroups > 0) { + XMEMCPY(ssl->group, ctx->group, sizeof(*ctx->group) * ctx->numGroups); + ssl->numGroups = ctx->numGroups; + } +#endif + +#ifdef HAVE_TLS_EXTENSIONS +#ifdef HAVE_MAX_FRAGMENT + ssl->max_fragment = MAX_RECORD_SIZE; +#endif +#ifdef HAVE_ALPN + ssl->alpn_client_list = NULL; + #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + ssl->alpnSelect = ctx->alpnSelect; + ssl->alpnSelectArg = ctx->alpnSelectArg; + #endif +#endif +#ifdef HAVE_SUPPORTED_CURVES + ssl->options.userCurves = ctx->userCurves; +#endif +#endif /* HAVE_TLS_EXTENSIONS */ + + /* default alert state (none) */ + ssl->alert_history.last_rx.code = -1; + ssl->alert_history.last_rx.level = -1; + ssl->alert_history.last_tx.code = -1; + ssl->alert_history.last_tx.level = -1; + +#ifdef OPENSSL_EXTRA + /* copy over application session context ID */ + ssl->sessionCtxSz = ctx->sessionCtxSz; + XMEMCPY(ssl->sessionCtx, ctx->sessionCtx, ctx->sessionCtxSz); + ssl->cbioFlag = ctx->cbioFlag; +#endif + + InitCiphers(ssl); + InitCipherSpecs(&ssl->specs); + + /* all done with init, now can return errors, call other stuff */ + + if (!writeDup) { + /* arrays */ + ssl->arrays = (Arrays*)XMALLOC(sizeof(Arrays), ssl->heap, + DYNAMIC_TYPE_ARRAYS); + if (ssl->arrays == NULL) { + WOLFSSL_MSG("Arrays Memory error"); + return MEMORY_E; + } + XMEMSET(ssl->arrays, 0, sizeof(Arrays)); +#if defined(WOLFSSL_TLS13) || defined(WOLFSSL_SNIFFER) + ssl->arrays->preMasterSz = ENCRYPT_LEN; + ssl->arrays->preMasterSecret = (byte*)XMALLOC(ENCRYPT_LEN, ssl->heap, + DYNAMIC_TYPE_SECRET); + if (ssl->arrays->preMasterSecret == NULL) { + return MEMORY_E; + } + XMEMSET(ssl->arrays->preMasterSecret, 0, ENCRYPT_LEN); +#endif + +#ifdef SINGLE_THREADED + if (ctx->suites == NULL) +#endif + { + /* suites */ + ssl->suites = (Suites*)XMALLOC(sizeof(Suites), ssl->heap, + DYNAMIC_TYPE_SUITES); + if (ssl->suites == NULL) { + WOLFSSL_MSG("Suites Memory error"); + return MEMORY_E; + } +#ifdef SINGLE_THREADED + ssl->options.ownSuites = 1; +#endif + } +#ifdef SINGLE_THREADED + else { + ssl->options.ownSuites = 0; + } +#endif + } + + /* Initialize SSL with the appropriate fields from it's ctx */ + /* requires valid arrays and suites unless writeDup ing */ + if ((ret = SetSSL_CTX(ssl, ctx, writeDup)) != WOLFSSL_SUCCESS) + return ret; + + ssl->options.dtls = ssl->version.major == DTLS_MAJOR; + +#ifdef SINGLE_THREADED + ssl->rng = ctx->rng; /* CTX may have one, if so use it */ +#endif + + if (ssl->rng == NULL) { + /* RNG */ + ssl->rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), ssl->heap,DYNAMIC_TYPE_RNG); + if (ssl->rng == NULL) { + WOLFSSL_MSG("RNG Memory error"); + return MEMORY_E; + } + XMEMSET(ssl->rng, 0, sizeof(WC_RNG)); + ssl->options.weOwnRng = 1; + + /* FIPS RNG API does not accept a heap hint */ +#ifndef HAVE_FIPS + if ( (ret = wc_InitRng_ex(ssl->rng, ssl->heap, ssl->devId)) != 0) { + WOLFSSL_MSG("RNG Init error"); + return ret; + } +#else + if ( (ret = wc_InitRng(ssl->rng)) != 0) { + WOLFSSL_MSG("RNG Init error"); + return ret; + } +#endif + } + +#ifdef HAVE_WRITE_DUP + if (writeDup) { + /* all done */ + return 0; + } +#endif + + /* hsHashes */ + ret = InitHandshakeHashes(ssl); + if (ret != 0) + return ret; + +#if defined(WOLFSSL_DTLS) && !defined(NO_WOLFSSL_SERVER) + if (ssl->options.dtls && ssl->options.side == WOLFSSL_SERVER_END) { + ret = wolfSSL_DTLS_SetCookieSecret(ssl, NULL, 0); + if (ret != 0) { + WOLFSSL_MSG("DTLS Cookie Secret error"); + return ret; + } + } +#endif /* WOLFSSL_DTLS && !NO_WOLFSSL_SERVER */ + +#ifdef HAVE_SECRET_CALLBACK + ssl->sessionSecretCb = NULL; + ssl->sessionSecretCtx = NULL; +#endif + +#ifdef HAVE_SESSION_TICKET + ssl->session.ticket = ssl->session.staticTicket; +#endif + +#ifdef WOLFSSL_MULTICAST + if (ctx->haveMcast) { + int i; + + ssl->options.haveMcast = 1; + ssl->options.mcastID = ctx->mcastID; + + /* Force the state to look like handshake has completed. */ + /* Keying material is supplied externally. */ + ssl->options.serverState = SERVER_FINISHED_COMPLETE; + ssl->options.clientState = CLIENT_FINISHED_COMPLETE; + ssl->options.connectState = SECOND_REPLY_DONE; + ssl->options.acceptState = ACCEPT_THIRD_REPLY_DONE; + ssl->options.handShakeState = HANDSHAKE_DONE; + ssl->options.handShakeDone = 1; + + for (i = 0; i < WOLFSSL_DTLS_PEERSEQ_SZ; i++) + ssl->keys.peerSeq[i].peerId = INVALID_PEER_ID; + } +#endif + +#ifdef HAVE_SECURE_RENEGOTIATION + if (ssl->options.side == WOLFSSL_CLIENT_END) { + /* use secure renegotiation by default (not recommend) */ + #ifdef WOLFSSL_SECURE_RENEGOTIATION_ON_BY_DEFAULT + ret = wolfSSL_UseSecureRenegotiation(ssl); + if (ret != WOLFSSL_SUCCESS) + return ret; + #endif + } +#endif + + return 0; +} + + +/* free use of temporary arrays */ +void FreeArrays(WOLFSSL* ssl, int keep) +{ + if (ssl->arrays) { + if (keep) { + /* keeps session id for user retrieval */ + XMEMCPY(ssl->session.sessionID, ssl->arrays->sessionID, ID_LEN); + ssl->session.sessionIDSz = ssl->arrays->sessionIDSz; + } + if (ssl->arrays->preMasterSecret) { + XFREE(ssl->arrays->preMasterSecret, ssl->heap, DYNAMIC_TYPE_SECRET); + ssl->arrays->preMasterSecret = NULL; + } + XFREE(ssl->arrays->pendingMsg, ssl->heap, DYNAMIC_TYPE_ARRAYS); + ssl->arrays->pendingMsg = NULL; + ForceZero(ssl->arrays, sizeof(Arrays)); /* clear arrays struct */ + } + XFREE(ssl->arrays, ssl->heap, DYNAMIC_TYPE_ARRAYS); + ssl->arrays = NULL; +} + +void FreeKey(WOLFSSL* ssl, int type, void** pKey) +{ + if (ssl && pKey && *pKey) { + switch (type) { + #ifndef NO_RSA + case DYNAMIC_TYPE_RSA: + wc_FreeRsaKey((RsaKey*)*pKey); + break; + #endif /* ! NO_RSA */ + #ifdef HAVE_ECC + case DYNAMIC_TYPE_ECC: + wc_ecc_free((ecc_key*)*pKey); + break; + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case DYNAMIC_TYPE_ED25519: + wc_ed25519_free((ed25519_key*)*pKey); + break; + #endif /* HAVE_CURVE25519 */ + #ifdef HAVE_CURVE25519 + case DYNAMIC_TYPE_CURVE25519: + wc_curve25519_free((curve25519_key*)*pKey); + break; + #endif /* HAVE_CURVE25519 */ + #ifndef NO_DH + case DYNAMIC_TYPE_DH: + wc_FreeDhKey((DhKey*)*pKey); + break; + #endif /* !NO_DH */ + default: + break; + } + XFREE(*pKey, ssl->heap, type); + + /* Reset pointer */ + *pKey = NULL; + } +} + +int AllocKey(WOLFSSL* ssl, int type, void** pKey) +{ + int ret = BAD_FUNC_ARG; + int sz = 0; + + if (ssl == NULL || pKey == NULL) { + return BAD_FUNC_ARG; + } + + /* Sanity check key destination */ + if (*pKey != NULL) { + WOLFSSL_MSG("Key already present!"); + return BAD_STATE_E; + } + + /* Determine size */ + switch (type) { + #ifndef NO_RSA + case DYNAMIC_TYPE_RSA: + sz = sizeof(RsaKey); + break; + #endif /* ! NO_RSA */ + #ifdef HAVE_ECC + case DYNAMIC_TYPE_ECC: + sz = sizeof(ecc_key); + break; + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case DYNAMIC_TYPE_ED25519: + sz = sizeof(ed25519_key); + break; + #endif /* HAVE_ED25519 */ + #ifdef HAVE_CURVE25519 + case DYNAMIC_TYPE_CURVE25519: + sz = sizeof(curve25519_key); + break; + #endif /* HAVE_CURVE25519 */ + #ifndef NO_DH + case DYNAMIC_TYPE_DH: + sz = sizeof(DhKey); + break; + #endif /* !NO_DH */ + default: + return BAD_FUNC_ARG; + } + + if (sz == 0) { + return NOT_COMPILED_IN; + } + + /* Allocate memeory for key */ + *pKey = XMALLOC(sz, ssl->heap, type); + if (*pKey == NULL) { + return MEMORY_E; + } + + /* Initialize key */ + switch (type) { + #ifndef NO_RSA + case DYNAMIC_TYPE_RSA: + ret = wc_InitRsaKey_ex((RsaKey*)*pKey, ssl->heap, ssl->devId); + break; + #endif /* ! NO_RSA */ + #ifdef HAVE_ECC + case DYNAMIC_TYPE_ECC: + ret = wc_ecc_init_ex((ecc_key*)*pKey, ssl->heap, ssl->devId); + break; + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case DYNAMIC_TYPE_ED25519: + wc_ed25519_init((ed25519_key*)*pKey); + ret = 0; + break; + #endif /* HAVE_CURVE25519 */ + #ifdef HAVE_CURVE25519 + case DYNAMIC_TYPE_CURVE25519: + wc_curve25519_init((curve25519_key*)*pKey); + ret = 0; + break; + #endif /* HAVE_CURVE25519 */ + #ifndef NO_DH + case DYNAMIC_TYPE_DH: + ret = wc_InitDhKey_ex((DhKey*)*pKey, ssl->heap, ssl->devId); + break; + #endif /* !NO_DH */ + default: + return BAD_FUNC_ARG; + } + + /* On error free handshake key */ + if (ret != 0) { + FreeKey(ssl, type, pKey); + } + + return ret; +} + +#if !defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519) || \ + defined(HAVE_CURVE25519) +static int ReuseKey(WOLFSSL* ssl, int type, void* pKey) +{ + int ret = 0; + + (void)ssl; + + switch (type) { + #ifndef NO_RSA + case DYNAMIC_TYPE_RSA: + wc_FreeRsaKey((RsaKey*)pKey); + ret = wc_InitRsaKey_ex((RsaKey*)pKey, ssl->heap, ssl->devId); + break; + #endif /* ! NO_RSA */ + #ifdef HAVE_ECC + case DYNAMIC_TYPE_ECC: + wc_ecc_free((ecc_key*)pKey); + ret = wc_ecc_init_ex((ecc_key*)pKey, ssl->heap, ssl->devId); + break; + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case DYNAMIC_TYPE_ED25519: + wc_ed25519_free((ed25519_key*)pKey); + ret = wc_ed25519_init((ed25519_key*)pKey); + break; + #endif /* HAVE_CURVE25519 */ + #ifdef HAVE_CURVE25519 + case DYNAMIC_TYPE_CURVE25519: + wc_curve25519_free((curve25519_key*)pKey); + ret = wc_curve25519_init((curve25519_key*)pKey); + break; + #endif /* HAVE_CURVE25519 */ + #ifndef NO_DH + case DYNAMIC_TYPE_DH: + wc_FreeDhKey((DhKey*)pKey); + ret = wc_InitDhKey_ex((DhKey*)pKey, ssl->heap, ssl->devId); + break; + #endif /* !NO_DH */ + default: + return BAD_FUNC_ARG; + } + + return ret; +} +#endif + +void FreeKeyExchange(WOLFSSL* ssl) +{ + /* Cleanup signature buffer */ + if (ssl->buffers.sig.buffer) { + XFREE(ssl->buffers.sig.buffer, ssl->heap, DYNAMIC_TYPE_SIGNATURE); + ssl->buffers.sig.buffer = NULL; + ssl->buffers.sig.length = 0; + } + + /* Cleanup digest buffer */ + if (ssl->buffers.digest.buffer) { + XFREE(ssl->buffers.digest.buffer, ssl->heap, DYNAMIC_TYPE_DIGEST); + ssl->buffers.digest.buffer = NULL; + ssl->buffers.digest.length = 0; + } + + /* Free handshake key */ + FreeKey(ssl, ssl->hsType, &ssl->hsKey); + +#ifndef NO_DH + /* Free temp DH key */ + FreeKey(ssl, DYNAMIC_TYPE_DH, (void**)&ssl->buffers.serverDH_Key); +#endif + + /* Cleanup async */ +#ifdef WOLFSSL_ASYNC_CRYPT + if (ssl->async.freeArgs) { + ssl->async.freeArgs(ssl, ssl->async.args); + ssl->async.freeArgs = NULL; + } +#endif +} + +/* In case holding SSL object in array and don't want to free actual ssl */ +void SSL_ResourceFree(WOLFSSL* ssl) +{ + /* Note: any resources used during the handshake should be released in the + * function FreeHandshakeResources(). Be careful with the special cases + * like the RNG which may optionally be kept for the whole session. (For + * example with the RNG, it isn't used beyond the handshake except when + * using stream ciphers where it is retained. */ + + FreeCiphers(ssl); + FreeArrays(ssl, 0); + FreeKeyExchange(ssl); + if (ssl->options.weOwnRng) { + wc_FreeRng(ssl->rng); + XFREE(ssl->rng, ssl->heap, DYNAMIC_TYPE_RNG); + } +#ifdef SINGLE_THREADED + if (ssl->options.ownSuites) +#endif + { + XFREE(ssl->suites, ssl->heap, DYNAMIC_TYPE_SUITES); + } + ssl->suites = NULL; + + FreeHandshakeHashes(ssl); + XFREE(ssl->buffers.domainName.buffer, ssl->heap, DYNAMIC_TYPE_DOMAIN); + + /* clear keys struct after session */ + ForceZero(&ssl->keys, sizeof(Keys)); + +#ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) { + ForceZero(&ssl->clientSecret, sizeof(ssl->clientSecret)); + ForceZero(&ssl->serverSecret, sizeof(ssl->serverSecret)); + } +#endif + +#ifndef NO_DH + if (ssl->buffers.serverDH_Priv.buffer) { + ForceZero(ssl->buffers.serverDH_Priv.buffer, + ssl->buffers.serverDH_Priv.length); + } + XFREE(ssl->buffers.serverDH_Priv.buffer, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + XFREE(ssl->buffers.serverDH_Pub.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + /* parameters (p,g) may be owned by ctx */ + if (ssl->buffers.weOwnDH) { + XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + } +#endif /* !NO_DH */ +#ifndef NO_CERTS + ssl->keepCert = 0; /* make sure certificate is free'd */ + wolfSSL_UnloadCertsKeys(ssl); +#endif +#ifndef NO_RSA + FreeKey(ssl, DYNAMIC_TYPE_RSA, (void**)&ssl->peerRsaKey); + ssl->peerRsaKeyPresent = 0; +#endif + if (ssl->buffers.inputBuffer.dynamicFlag) + ShrinkInputBuffer(ssl, FORCED_FREE); + if (ssl->buffers.outputBuffer.dynamicFlag) + ShrinkOutputBuffer(ssl); +#if defined(WOLFSSL_SEND_HRR_COOKIE) && !defined(NO_WOLFSSL_SERVER) + XFREE(ssl->buffers.tls13CookieSecret.buffer, ssl->heap, + DYNAMIC_TYPE_COOKIE_PWD); +#endif +#ifdef WOLFSSL_DTLS + DtlsMsgPoolReset(ssl); + if (ssl->dtls_rx_msg_list != NULL) { + DtlsMsgListDelete(ssl->dtls_rx_msg_list, ssl->heap); + ssl->dtls_rx_msg_list = NULL; + ssl->dtls_rx_msg_list_sz = 0; + } + XFREE(ssl->buffers.dtlsCtx.peer.sa, ssl->heap, DYNAMIC_TYPE_SOCKADDR); + ssl->buffers.dtlsCtx.peer.sa = NULL; +#ifndef NO_WOLFSSL_SERVER + XFREE(ssl->buffers.dtlsCookieSecret.buffer, ssl->heap, + DYNAMIC_TYPE_COOKIE_PWD); +#endif +#endif /* WOLFSSL_DTLS */ +#ifdef OPENSSL_EXTRA + if (ssl->biord != ssl->biowr) /* only free write if different */ + wolfSSL_BIO_free(ssl->biowr); + wolfSSL_BIO_free(ssl->biord); /* always free read bio */ +#endif +#ifdef HAVE_LIBZ + FreeStreams(ssl); +#endif +#ifdef HAVE_ECC + FreeKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->peerEccKey); + ssl->peerEccKeyPresent = 0; + FreeKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->peerEccDsaKey); + ssl->peerEccDsaKeyPresent = 0; +#endif +#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) + { + int dtype; + #ifdef HAVE_ECC + dtype = DYNAMIC_TYPE_ECC; + #endif + #ifdef HAVE_CURVE25519 + #ifdef HAVE_ECC + if (ssl->peerX25519KeyPresent || + ssl->eccTempKeyPresent == DYNAMIC_TYPE_CURVE25519) + #endif /* HAVE_ECC */ + { + dtype = DYNAMIC_TYPE_CURVE25519; + } + #endif /* HAVE_CURVE25519 */ + FreeKey(ssl, dtype, (void**)&ssl->eccTempKey); + ssl->eccTempKeyPresent = 0; + } +#endif /* HAVE_ECC || HAVE_CURVE25519 */ +#ifdef HAVE_CURVE25519 + FreeKey(ssl, DYNAMIC_TYPE_CURVE25519, (void**)&ssl->peerX25519Key); + ssl->peerX25519KeyPresent = 0; +#endif +#ifdef HAVE_ED25519 + FreeKey(ssl, DYNAMIC_TYPE_ED25519, (void**)&ssl->peerEd25519Key); + ssl->peerEd25519KeyPresent = 0; + #ifdef HAVE_PK_CALLBACKS + if (ssl->buffers.peerEd25519Key.buffer != NULL) { + XFREE(ssl->buffers.peerEd25519Key.buffer, ssl->heap, + DYNAMIC_TYPE_ED25519); + ssl->buffers.peerEd25519Key.buffer = NULL; + } + #endif +#endif +#ifdef HAVE_PK_CALLBACKS + #ifdef HAVE_ECC + XFREE(ssl->buffers.peerEccDsaKey.buffer, ssl->heap, DYNAMIC_TYPE_ECC); + #endif /* HAVE_ECC */ + #ifndef NO_RSA + XFREE(ssl->buffers.peerRsaKey.buffer, ssl->heap, DYNAMIC_TYPE_RSA); + #endif /* NO_RSA */ +#endif /* HAVE_PK_CALLBACKS */ +#ifdef HAVE_TLS_EXTENSIONS + TLSX_FreeAll(ssl->extensions, ssl->heap); + +#ifdef HAVE_ALPN + if (ssl->alpn_client_list != NULL) { + XFREE(ssl->alpn_client_list, ssl->heap, DYNAMIC_TYPE_ALPN); + ssl->alpn_client_list = NULL; + } +#endif +#endif /* HAVE_TLS_EXTENSIONS */ +#if defined(WOLFSSL_APACHE_MYNEWT) && !defined(WOLFSSL_LWIP) + if (ssl->mnCtx) { + mynewt_ctx_clear(ssl->mnCtx); + ssl->mnCtx = NULL; + } +#endif +#ifdef HAVE_NETX + if (ssl->nxCtx.nxPacket) + nx_packet_release(ssl->nxCtx.nxPacket); +#endif +#ifdef KEEP_PEER_CERT + FreeX509(&ssl->peerCert); +#endif + +#ifdef HAVE_SESSION_TICKET + if (ssl->session.isDynamic) { + XFREE(ssl->session.ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); + ssl->session.ticket = ssl->session.staticTicket; + ssl->session.isDynamic = 0; + ssl->session.ticketLen = 0; + } +#endif +#ifdef HAVE_EXT_CACHE + wolfSSL_SESSION_free(ssl->extSession); +#endif +#ifdef HAVE_WRITE_DUP + if (ssl->dupWrite) { + FreeWriteDup(ssl); + } +#endif + +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) + while (ssl->certReqCtx != NULL) { + CertReqCtx* curr = ssl->certReqCtx; + ssl->certReqCtx = curr->next; + XFREE(curr, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + +#ifdef WOLFSSL_STATIC_MEMORY + /* check if using fixed io buffers and free them */ + if (ssl->heap != NULL) { + #ifdef WOLFSSL_HEAP_TEST + /* avoid dereferencing a test value */ + if (ssl->heap != (void*)WOLFSSL_HEAP_TEST) { + #endif + WOLFSSL_HEAP_HINT* ssl_hint = (WOLFSSL_HEAP_HINT*)ssl->heap; + WOLFSSL_HEAP* ctx_heap; + void* heap = ssl->ctx ? ssl->ctx->heap : ssl->heap; + + ctx_heap = ssl_hint->memory; + if (wc_LockMutex(&(ctx_heap->memory_mutex)) != 0) { + WOLFSSL_MSG("Bad memory_mutex lock"); + } + ctx_heap->curIO--; + if (FreeFixedIO(ctx_heap, &(ssl_hint->outBuf)) != 1) { + WOLFSSL_MSG("Error freeing fixed output buffer"); + } + if (FreeFixedIO(ctx_heap, &(ssl_hint->inBuf)) != 1) { + WOLFSSL_MSG("Error freeing fixed output buffer"); + } + if (ssl_hint->haFlag) { /* check if handshake count has been decreased*/ + ctx_heap->curHa--; + } + wc_UnLockMutex(&(ctx_heap->memory_mutex)); + + /* check if tracking stats */ + if (ctx_heap->flag & WOLFMEM_TRACK_STATS) { + XFREE(ssl_hint->stats, heap, DYNAMIC_TYPE_SSL); + } + XFREE(ssl->heap, heap, DYNAMIC_TYPE_SSL); + #ifdef WOLFSSL_HEAP_TEST + } + #endif + } +#endif /* WOLFSSL_STATIC_MEMORY */ +} + +/* Free any handshake resources no longer needed */ +void FreeHandshakeResources(WOLFSSL* ssl) +{ + +#ifdef HAVE_SECURE_RENEGOTIATION + if (ssl->secure_renegotiation && ssl->secure_renegotiation->enabled) { + WOLFSSL_MSG("Secure Renegotiation needs to retain handshake resources"); + #ifdef KEEP_PEER_CERT + /* free peer cert in preparation for new handshake */ + FreeX509(&ssl->peerCert); + #endif + return; + } +#endif + + /* input buffer */ + if (ssl->buffers.inputBuffer.dynamicFlag) + ShrinkInputBuffer(ssl, NO_FORCED_FREE); + +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) + if (!ssl->options.tls1_3) +#endif + { + /* suites */ +#ifdef SINGLE_THREADED + if (ssl->options.ownSuites) +#endif + { + XFREE(ssl->suites, ssl->heap, DYNAMIC_TYPE_SUITES); + } + ssl->suites = NULL; + + /* hsHashes */ + FreeHandshakeHashes(ssl); + } + + /* RNG */ + if (ssl->options.tls1_1 == 0 +#ifndef WOLFSSL_AEAD_ONLY + || ssl->specs.cipher_type == stream +#endif +#if defined(WOLFSSL_TLS13) + #if !defined(WOLFSSL_POST_HANDSHAKE_AUTH) + || ssl->options.tls1_3 + #elif !defined(HAVE_SESSION_TICKET) + || (ssl->options.tls1_3 && ssl->options.side == WOLFSSL_SERVER_END) + #endif +#endif + ) { + if (ssl->options.weOwnRng) { + wc_FreeRng(ssl->rng); + XFREE(ssl->rng, ssl->heap, DYNAMIC_TYPE_RNG); + ssl->rng = NULL; + ssl->options.weOwnRng = 0; + } + } + +#ifdef WOLFSSL_DTLS + /* DTLS_POOL */ + if (ssl->options.dtls) { + DtlsMsgPoolReset(ssl); + DtlsMsgListDelete(ssl->dtls_rx_msg_list, ssl->heap); + ssl->dtls_rx_msg_list = NULL; + ssl->dtls_rx_msg_list_sz = 0; + } +#endif + +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) && \ + defined(HAVE_SESSION_TICKET) + if (!ssl->options.tls1_3) +#endif + /* arrays */ + if (ssl->options.saveArrays == 0) + FreeArrays(ssl, 1); + +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) + if (!ssl->options.tls1_3 || ssl->options.side == WOLFSSL_CLIENT_END) +#endif + { +#ifndef NO_RSA + /* peerRsaKey */ + FreeKey(ssl, DYNAMIC_TYPE_RSA, (void**)&ssl->peerRsaKey); + ssl->peerRsaKeyPresent = 0; +#endif +#ifdef HAVE_ECC + FreeKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->peerEccDsaKey); + ssl->peerEccDsaKeyPresent = 0; +#endif /* HAVE_ECC */ +#ifdef HAVE_ED25519 + FreeKey(ssl, DYNAMIC_TYPE_ED25519, (void**)&ssl->peerEd25519Key); + ssl->peerEd25519KeyPresent = 0; +#endif /* HAVE_ED25519 */ + } + +#ifdef HAVE_ECC + FreeKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->peerEccKey); + ssl->peerEccKeyPresent = 0; +#endif +#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) + { + int dtype; + #ifdef HAVE_ECC + dtype = DYNAMIC_TYPE_ECC; + #endif + #ifdef HAVE_CURVE25519 + #ifdef HAVE_ECC + if (ssl->peerX25519KeyPresent || + ssl->eccTempKeyPresent == DYNAMIC_TYPE_CURVE25519) + #endif /* HAVE_ECC */ + { + dtype = DYNAMIC_TYPE_CURVE25519; + } + #endif /* HAVE_CURVE25519 */ + FreeKey(ssl, dtype, (void**)&ssl->eccTempKey); + ssl->eccTempKeyPresent = 0; + } +#endif /* HAVE_ECC || HAVE_CURVE25519 */ +#ifdef HAVE_CURVE25519 + FreeKey(ssl, DYNAMIC_TYPE_CURVE25519, (void**)&ssl->peerX25519Key); + ssl->peerX25519KeyPresent = 0; +#endif + +#ifndef NO_DH + if (ssl->buffers.serverDH_Priv.buffer) { + ForceZero(ssl->buffers.serverDH_Priv.buffer, + ssl->buffers.serverDH_Priv.length); + } + XFREE(ssl->buffers.serverDH_Priv.buffer, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + ssl->buffers.serverDH_Priv.buffer = NULL; + XFREE(ssl->buffers.serverDH_Pub.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + ssl->buffers.serverDH_Pub.buffer = NULL; + /* parameters (p,g) may be owned by ctx */ + if (ssl->buffers.weOwnDH) { + XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + ssl->buffers.serverDH_G.buffer = NULL; + XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + ssl->buffers.serverDH_P.buffer = NULL; + } +#endif /* !NO_DH */ + +#ifndef NO_CERTS + wolfSSL_UnloadCertsKeys(ssl); +#endif +#ifdef HAVE_PK_CALLBACKS +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) + if (!ssl->options.tls1_3 || ssl->options.side == WOLFSSL_CLIENT_END) +#endif + { + #ifdef HAVE_ECC + XFREE(ssl->buffers.peerEccDsaKey.buffer, ssl->heap, DYNAMIC_TYPE_ECC); + ssl->buffers.peerEccDsaKey.buffer = NULL; + #endif /* HAVE_ECC */ + #ifndef NO_RSA + XFREE(ssl->buffers.peerRsaKey.buffer, ssl->heap, DYNAMIC_TYPE_RSA); + ssl->buffers.peerRsaKey.buffer = NULL; + #endif /* NO_RSA */ + #ifdef HAVE_ED25519 + XFREE(ssl->buffers.peerEd25519Key.buffer, ssl->heap, + DYNAMIC_TYPE_ED25519); + ssl->buffers.peerEd25519Key.buffer = NULL; + #endif + } +#endif /* HAVE_PK_CALLBACKS */ + +#ifdef HAVE_QSH + QSH_FreeAll(ssl); +#endif + +#ifdef HAVE_SESSION_TICKET + if (ssl->session.isDynamic) { + XFREE(ssl->session.ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); + ssl->session.ticket = ssl->session.staticTicket; + ssl->session.isDynamic = 0; + ssl->session.ticketLen = 0; + } +#endif + +#if defined(HAVE_TLS_EXTENSIONS) && !defined(HAVE_SNI) && \ + !defined(HAVE_ALPN) && !defined(WOLFSSL_POST_HANDSHAKE_AUTH) + /* Some extensions need to be kept for post-handshake querying. */ + TLSX_FreeAll(ssl->extensions, ssl->heap); + ssl->extensions = NULL; +#endif + +#ifdef WOLFSSL_STATIC_MEMORY + /* when done with handshake decrement current handshake count */ + if (ssl->heap != NULL) { + #ifdef WOLFSSL_HEAP_TEST + /* avoid dereferencing a test value */ + if (ssl->heap != (void*)WOLFSSL_HEAP_TEST) { + #endif + WOLFSSL_HEAP_HINT* ssl_hint = (WOLFSSL_HEAP_HINT*)ssl->heap; + WOLFSSL_HEAP* ctx_heap; + + ctx_heap = ssl_hint->memory; + if (wc_LockMutex(&(ctx_heap->memory_mutex)) != 0) { + WOLFSSL_MSG("Bad memory_mutex lock"); + } + ctx_heap->curHa--; + ssl_hint->haFlag = 0; /* set to zero since handshake has been dec */ + wc_UnLockMutex(&(ctx_heap->memory_mutex)); + #ifdef WOLFSSL_HEAP_TEST + } + #endif + } +#endif /* WOLFSSL_STATIC_MEMORY */ +} + + +/* heap argument is the heap hint used when creating SSL */ +void FreeSSL(WOLFSSL* ssl, void* heap) +{ + if (ssl->ctx) { + FreeSSL_Ctx(ssl->ctx); /* will decrement and free underlying CTX if 0 */ + } + SSL_ResourceFree(ssl); + XFREE(ssl, heap, DYNAMIC_TYPE_SSL); + (void)heap; +} + +#if !defined(NO_OLD_TLS) || defined(WOLFSSL_DTLS) || \ + ((defined(HAVE_CHACHA) || defined(HAVE_AESCCM) || defined(HAVE_AESGCM)) \ + && defined(HAVE_AEAD)) + +#if defined(WOLFSSL_DTLS) || !defined(WOLFSSL_NO_TLS12) +static WC_INLINE void GetSEQIncrement(WOLFSSL* ssl, int verify, word32 seq[2]) +{ + if (verify) { + seq[0] = ssl->keys.peer_sequence_number_hi; + seq[1] = ssl->keys.peer_sequence_number_lo++; + if (seq[1] > ssl->keys.peer_sequence_number_lo) { + /* handle rollover */ + ssl->keys.peer_sequence_number_hi++; + } + } + else { + seq[0] = ssl->keys.sequence_number_hi; + seq[1] = ssl->keys.sequence_number_lo++; + if (seq[1] > ssl->keys.sequence_number_lo) { + /* handle rollover */ + ssl->keys.sequence_number_hi++; + } + } +} +#endif /* WOLFSSL_DTLS || !WOLFSSL_NO_TLS12 */ + + +#ifdef WOLFSSL_DTLS +static WC_INLINE void DtlsGetSEQ(WOLFSSL* ssl, int order, word32 seq[2]) +{ + if (order == PREV_ORDER) { + /* Previous epoch case */ + if (ssl->options.haveMcast) { + #ifdef WOLFSSL_MULTICAST + seq[0] = ((ssl->keys.dtls_epoch - 1) << 16) | + (ssl->options.mcastID << 8) | + (ssl->keys.dtls_prev_sequence_number_hi & 0xFF); + #endif + } + else + seq[0] = ((ssl->keys.dtls_epoch - 1) << 16) | + (ssl->keys.dtls_prev_sequence_number_hi & 0xFFFF); + seq[1] = ssl->keys.dtls_prev_sequence_number_lo; + } + else if (order == PEER_ORDER) { + if (ssl->options.haveMcast) { + #ifdef WOLFSSL_MULTICAST + seq[0] = (ssl->keys.curEpoch << 16) | + (ssl->keys.curPeerId << 8) | + (ssl->keys.curSeq_hi & 0xFF); + #endif + } + else + seq[0] = (ssl->keys.curEpoch << 16) | + (ssl->keys.curSeq_hi & 0xFFFF); + seq[1] = ssl->keys.curSeq_lo; /* explicit from peer */ + } + else { + if (ssl->options.haveMcast) { + #ifdef WOLFSSL_MULTICAST + seq[0] = (ssl->keys.dtls_epoch << 16) | + (ssl->options.mcastID << 8) | + (ssl->keys.dtls_sequence_number_hi & 0xFF); + #endif + } + else + seq[0] = (ssl->keys.dtls_epoch << 16) | + (ssl->keys.dtls_sequence_number_hi & 0xFFFF); + seq[1] = ssl->keys.dtls_sequence_number_lo; + } +} + +static WC_INLINE void DtlsSEQIncrement(WOLFSSL* ssl, int order) +{ + word32 seq; + + if (order == PREV_ORDER) { + seq = ssl->keys.dtls_prev_sequence_number_lo++; + if (seq > ssl->keys.dtls_prev_sequence_number_lo) { + /* handle rollover */ + ssl->keys.dtls_prev_sequence_number_hi++; + } + } + else if (order == PEER_ORDER) { + seq = ssl->keys.peer_sequence_number_lo++; + if (seq > ssl->keys.peer_sequence_number_lo) { + /* handle rollover */ + ssl->keys.peer_sequence_number_hi++; + } + } + else { + seq = ssl->keys.dtls_sequence_number_lo++; + if (seq > ssl->keys.dtls_sequence_number_lo) { + /* handle rollover */ + ssl->keys.dtls_sequence_number_hi++; + } + } +} +#endif /* WOLFSSL_DTLS */ + +#if defined(WOLFSSL_DTLS) || !defined(WOLFSSL_NO_TLS12) +static WC_INLINE void WriteSEQ(WOLFSSL* ssl, int verifyOrder, byte* out) +{ + word32 seq[2] = {0, 0}; + + if (!ssl->options.dtls) { + GetSEQIncrement(ssl, verifyOrder, seq); + } + else { +#ifdef WOLFSSL_DTLS + DtlsGetSEQ(ssl, verifyOrder, seq); +#endif + } + + c32toa(seq[0], out); + c32toa(seq[1], out + OPAQUE32_LEN); +} +#endif /* WOLFSSL_DTLS || !WOLFSSL_NO_TLS12 */ +#endif /* !NO_OLD_TLS || WOLFSSL_DTLS || + * ((HAVE_CHACHA || HAVE_AESCCM || HAVE_AESGCM) && HAVE_AEAD) */ + +#ifdef WOLFSSL_DTLS + +/* functions for managing DTLS datagram reordering */ + +/* Need to allocate space for the handshake message header. The hashing + * routines assume the message pointer is still within the buffer that + * has the headers, and will include those headers in the hash. The store + * routines need to take that into account as well. New will allocate + * extra space for the headers. */ +DtlsMsg* DtlsMsgNew(word32 sz, void* heap) +{ + DtlsMsg* msg = NULL; + + (void)heap; + msg = (DtlsMsg*)XMALLOC(sizeof(DtlsMsg), heap, DYNAMIC_TYPE_DTLS_MSG); + + if (msg != NULL) { + XMEMSET(msg, 0, sizeof(DtlsMsg)); + msg->buf = (byte*)XMALLOC(sz + DTLS_HANDSHAKE_HEADER_SZ, + heap, DYNAMIC_TYPE_DTLS_BUFFER); + if (msg->buf != NULL) { + msg->sz = sz; + msg->type = no_shake; + msg->msg = msg->buf + DTLS_HANDSHAKE_HEADER_SZ; + } + else { + XFREE(msg, heap, DYNAMIC_TYPE_DTLS_MSG); + msg = NULL; + } + } + + return msg; +} + +void DtlsMsgDelete(DtlsMsg* item, void* heap) +{ + (void)heap; + + if (item != NULL) { + DtlsFrag* cur = item->fragList; + while (cur != NULL) { + DtlsFrag* next = cur->next; + XFREE(cur, heap, DYNAMIC_TYPE_DTLS_FRAG); + cur = next; + } + if (item->buf != NULL) + XFREE(item->buf, heap, DYNAMIC_TYPE_DTLS_BUFFER); + XFREE(item, heap, DYNAMIC_TYPE_DTLS_MSG); + } +} + + +void DtlsMsgListDelete(DtlsMsg* head, void* heap) +{ + DtlsMsg* next; + while (head) { + next = head->next; + DtlsMsgDelete(head, heap); + head = next; + } +} + + +/* Create a DTLS Fragment from *begin - end, adjust new *begin and bytesLeft */ +static DtlsFrag* CreateFragment(word32* begin, word32 end, const byte* data, + byte* buf, word32* bytesLeft, void* heap) +{ + DtlsFrag* newFrag; + word32 added = end - *begin + 1; + + (void)heap; + newFrag = (DtlsFrag*)XMALLOC(sizeof(DtlsFrag), heap, + DYNAMIC_TYPE_DTLS_FRAG); + if (newFrag != NULL) { + newFrag->next = NULL; + newFrag->begin = *begin; + newFrag->end = end; + + XMEMCPY(buf + *begin, data, added); + *bytesLeft -= added; + *begin = newFrag->end + 1; + } + + return newFrag; +} + + +int DtlsMsgSet(DtlsMsg* msg, word32 seq, const byte* data, byte type, + word32 fragOffset, word32 fragSz, void* heap) +{ + if (msg != NULL && data != NULL && msg->fragSz <= msg->sz && + (fragOffset + fragSz) <= msg->sz) { + DtlsFrag* cur = msg->fragList; + DtlsFrag* prev = cur; + DtlsFrag* newFrag; + word32 bytesLeft = fragSz; /* could be overlapping fragment */ + word32 startOffset = fragOffset; + word32 added; + + msg->seq = seq; + msg->type = type; + + if (fragOffset == 0) { + XMEMCPY(msg->buf, data - DTLS_HANDSHAKE_HEADER_SZ, + DTLS_HANDSHAKE_HEADER_SZ); + c32to24(msg->sz, msg->msg - DTLS_HANDSHAKE_FRAG_SZ); + } + + /* if no message data, just return */ + if (fragSz == 0) + return 0; + + /* if list is empty add full fragment to front */ + if (cur == NULL) { + newFrag = CreateFragment(&fragOffset, fragOffset + fragSz - 1, data, + msg->msg, &bytesLeft, heap); + if (newFrag == NULL) + return MEMORY_E; + + msg->fragSz = fragSz; + msg->fragList = newFrag; + + return 0; + } + + /* add to front if before current front, up to next->begin */ + if (fragOffset < cur->begin) { + word32 end = fragOffset + fragSz - 1; + + if (end >= cur->begin) + end = cur->begin - 1; + + added = end - fragOffset + 1; + newFrag = CreateFragment(&fragOffset, end, data, msg->msg, + &bytesLeft, heap); + if (newFrag == NULL) + return MEMORY_E; + + msg->fragSz += added; + + newFrag->next = cur; + msg->fragList = newFrag; + } + + /* while we have bytes left, try to find a gap to fill */ + while (bytesLeft > 0) { + /* get previous packet in list */ + while (cur && (fragOffset >= cur->begin)) { + prev = cur; + cur = cur->next; + } + + /* don't add duplicate data */ + if (prev->end >= fragOffset) { + if ( (fragOffset + bytesLeft - 1) <= prev->end) + return 0; + fragOffset = prev->end + 1; + bytesLeft = startOffset + fragSz - fragOffset; + } + + if (cur == NULL) + /* we're at the end */ + added = bytesLeft; + else + /* we're in between two frames */ + added = min(bytesLeft, cur->begin - fragOffset); + + /* data already there */ + if (added == 0) + continue; + + newFrag = CreateFragment(&fragOffset, fragOffset + added - 1, + data + fragOffset - startOffset, + msg->msg, &bytesLeft, heap); + if (newFrag == NULL) + return MEMORY_E; + + msg->fragSz += added; + + newFrag->next = prev->next; + prev->next = newFrag; + } + } + + return 0; +} + + +DtlsMsg* DtlsMsgFind(DtlsMsg* head, word32 seq) +{ + while (head != NULL && head->seq != seq) { + head = head->next; + } + return head; +} + + +void DtlsMsgStore(WOLFSSL* ssl, word32 seq, const byte* data, + word32 dataSz, byte type, word32 fragOffset, word32 fragSz, void* heap) +{ + /* See if seq exists in the list. If it isn't in the list, make + * a new item of size dataSz, copy fragSz bytes from data to msg->msg + * starting at offset fragOffset, and add fragSz to msg->fragSz. If + * the seq is in the list and it isn't full, copy fragSz bytes from + * data to msg->msg starting at offset fragOffset, and add fragSz to + * msg->fragSz. Insertions take into account data already in the list + * in case there are overlaps in the handshake message due to retransmit + * messages. The new item should be inserted into the list in its + * proper position. + * + * 1. Find seq in list, or where seq should go in list. If seq not in + * list, create new item and insert into list. Either case, keep + * pointer to item. + * 2. Copy the data from the message to the stored message where it + * belongs without overlaps. + */ + + DtlsMsg* head = ssl->dtls_rx_msg_list; + + if (head != NULL) { + DtlsMsg* cur = DtlsMsgFind(head, seq); + if (cur == NULL) { + cur = DtlsMsgNew(dataSz, heap); + if (cur != NULL) { + if (DtlsMsgSet(cur, seq, data, type, + fragOffset, fragSz, heap) < 0) { + DtlsMsgDelete(cur, heap); + } + else { + ssl->dtls_rx_msg_list_sz++; + head = DtlsMsgInsert(head, cur); + } + } + } + else { + /* If this fails, the data is just dropped. */ + DtlsMsgSet(cur, seq, data, type, fragOffset, fragSz, heap); + } + } + else { + head = DtlsMsgNew(dataSz, heap); + if (DtlsMsgSet(head, seq, data, type, fragOffset, fragSz, heap) < 0) { + DtlsMsgDelete(head, heap); + head = NULL; + } + else { + ssl->dtls_rx_msg_list_sz++; + } + } + + ssl->dtls_rx_msg_list = head; +} + + +/* DtlsMsgInsert() is an in-order insert. */ +DtlsMsg* DtlsMsgInsert(DtlsMsg* head, DtlsMsg* item) +{ + if (head == NULL || item->seq < head->seq) { + item->next = head; + head = item; + } + else if (head->next == NULL) { + head->next = item; + } + else { + DtlsMsg* cur = head->next; + DtlsMsg* prev = head; + while (cur) { + if (item->seq < cur->seq) { + item->next = cur; + prev->next = item; + break; + } + prev = cur; + cur = cur->next; + } + if (cur == NULL) { + prev->next = item; + } + } + + return head; +} + + +/* DtlsMsgPoolSave() adds the message to the end of the stored transmit list. */ +int DtlsMsgPoolSave(WOLFSSL* ssl, const byte* data, word32 dataSz) +{ + DtlsMsg* item; + int ret = 0; + + WOLFSSL_ENTER("DtlsMsgPoolSave()"); + + if (ssl->dtls_tx_msg_list_sz > DTLS_POOL_SZ) { + WOLFSSL_ERROR(DTLS_POOL_SZ_E); + return DTLS_POOL_SZ_E; + } + + item = DtlsMsgNew(dataSz, ssl->heap); + + if (item != NULL) { + DtlsMsg* cur = ssl->dtls_tx_msg_list; + + XMEMCPY(item->buf, data, dataSz); + item->sz = dataSz; + item->seq = ssl->keys.dtls_epoch; + + if (cur == NULL) + ssl->dtls_tx_msg_list = item; + else { + while (cur->next) + cur = cur->next; + cur->next = item; + } + ssl->dtls_tx_msg_list_sz++; + } + else + ret = MEMORY_E; + + WOLFSSL_LEAVE("DtlsMsgPoolSave()", ret); + return ret; +} + + +/* DtlsMsgPoolTimeout() updates the timeout time. */ +int DtlsMsgPoolTimeout(WOLFSSL* ssl) +{ + int result = -1; + if (ssl->dtls_timeout < ssl->dtls_timeout_max) { + ssl->dtls_timeout *= DTLS_TIMEOUT_MULTIPLIER; + result = 0; + } + WOLFSSL_LEAVE("DtlsMsgPoolTimeout()", result); + return result; +} + + +/* DtlsMsgPoolReset() deletes the stored transmit list and resets the timeout + * value. */ +void DtlsMsgPoolReset(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("DtlsMsgPoolReset()"); + if (ssl->dtls_tx_msg_list) { + DtlsMsgListDelete(ssl->dtls_tx_msg_list, ssl->heap); + ssl->dtls_tx_msg_list = NULL; + ssl->dtls_tx_msg = NULL; + ssl->dtls_tx_msg_list_sz = 0; + ssl->dtls_timeout = ssl->dtls_timeout_init; + } +} + + +int VerifyForDtlsMsgPoolSend(WOLFSSL* ssl, byte type, word32 fragOffset) +{ + /** + * only the first message from previous flight should be valid + * to be used for triggering retransmission of whole DtlsMsgPool. + * change cipher suite type is not verified here + */ + return ((fragOffset == 0) && + (((ssl->options.side == WOLFSSL_SERVER_END) && + ((type == client_hello) || + ((ssl->options.verifyPeer) && (type == certificate)) || + ((!ssl->options.verifyPeer) && (type == client_key_exchange)))) || + ((ssl->options.side == WOLFSSL_CLIENT_END) && + (type == server_hello)))); +} + + +/* DtlsMsgPoolSend() will send the stored transmit list. The stored list is + * updated with new sequence numbers, and will be re-encrypted if needed. */ +int DtlsMsgPoolSend(WOLFSSL* ssl, int sendOnlyFirstPacket) +{ + int ret = 0; + DtlsMsg* pool; + + WOLFSSL_ENTER("DtlsMsgPoolSend()"); + + pool = ssl->dtls_tx_msg == NULL ? ssl->dtls_tx_msg_list : ssl->dtls_tx_msg; + + if (pool != NULL) { + if ((ssl->options.side == WOLFSSL_SERVER_END && + !(ssl->options.acceptState == SERVER_HELLO_DONE || + ssl->options.acceptState == ACCEPT_FINISHED_DONE)) || + (ssl->options.side == WOLFSSL_CLIENT_END && + !(ssl->options.connectState == CLIENT_HELLO_SENT || + ssl->options.connectState == HELLO_AGAIN_REPLY || + ssl->options.connectState == FINISHED_DONE))) { + + WOLFSSL_ERROR(DTLS_RETX_OVER_TX); + ssl->error = DTLS_RETX_OVER_TX; + return WOLFSSL_FATAL_ERROR; + } + + while (pool != NULL) { + if (pool->seq == 0) { + DtlsRecordLayerHeader* dtls; + int epochOrder; + + dtls = (DtlsRecordLayerHeader*)pool->buf; + /* If the stored record's epoch is 0, and the currently set + * epoch is 0, use the "current order" sequence number. + * If the stored record's epoch is 0 and the currently set + * epoch is not 0, the stored record is considered a "previous + * order" sequence number. */ + epochOrder = (ssl->keys.dtls_epoch == 0) ? + CUR_ORDER : PREV_ORDER; + + WriteSEQ(ssl, epochOrder, dtls->sequence_number); + DtlsSEQIncrement(ssl, epochOrder); + if ((ret = CheckAvailableSize(ssl, pool->sz)) != 0) { + WOLFSSL_ERROR(ret); + return ret; + } + + XMEMCPY(ssl->buffers.outputBuffer.buffer, + pool->buf, pool->sz); + ssl->buffers.outputBuffer.idx = 0; + ssl->buffers.outputBuffer.length = pool->sz; + } + else if (pool->seq == ssl->keys.dtls_epoch) { + byte* input; + byte* output; + int inputSz, sendSz; + + input = pool->buf; + inputSz = pool->sz; + sendSz = inputSz + MAX_MSG_EXTRA; + + if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) { + WOLFSSL_ERROR(ret); + return ret; + } + + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, + handshake, 0, 0, 0); + if (sendSz < 0) { + WOLFSSL_ERROR(BUILD_MSG_ERROR); + return BUILD_MSG_ERROR; + } + + ssl->buffers.outputBuffer.length += sendSz; + } + + ret = SendBuffered(ssl); + if (ret < 0) { + WOLFSSL_ERROR(ret); + return ret; + } + + /** + * on server side, retranmission is being triggered only by sending + * first message of given flight, in order to trigger client + * to retransmit its whole flight. Sending the whole previous flight + * could lead to retranmission of previous client flight for each + * server message from previous flight. Therefore one message should + * be enough to do the trick. + */ + if (sendOnlyFirstPacket && + ssl->options.side == WOLFSSL_SERVER_END) { + + pool = NULL; + } + else + pool = pool->next; + ssl->dtls_tx_msg = pool; + } + } + + WOLFSSL_LEAVE("DtlsMsgPoolSend()", ret); + return ret; +} + +#endif /* WOLFSSL_DTLS */ + +#if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS) + +ProtocolVersion MakeSSLv3(void) +{ + ProtocolVersion pv; + pv.major = SSLv3_MAJOR; + pv.minor = SSLv3_MINOR; + + return pv; +} + +#endif /* WOLFSSL_ALLOW_SSLV3 && !NO_OLD_TLS */ + + +#ifdef WOLFSSL_DTLS + +ProtocolVersion MakeDTLSv1(void) +{ + ProtocolVersion pv; + pv.major = DTLS_MAJOR; + pv.minor = DTLS_MINOR; + + return pv; +} + +#ifndef WOLFSSL_NO_TLS12 + +ProtocolVersion MakeDTLSv1_2(void) +{ + ProtocolVersion pv; + pv.major = DTLS_MAJOR; + pv.minor = DTLSv1_2_MINOR; + + return pv; +} + +#endif /* !WOLFSSL_NO_TLS12 */ + +#endif /* WOLFSSL_DTLS */ + + + + +#if defined(USER_TICKS) +#if 0 + word32 LowResTimer(void) + { + /* + write your own clock tick function if don't want time(0) + needs second accuracy but doesn't have to correlated to EPOCH + */ + } +#endif + +#elif defined(TIME_OVERRIDES) + + /* use same asn time overrides unless user wants tick override above */ + + #ifndef HAVE_TIME_T_TYPE + typedef long time_t; + #endif + extern time_t XTIME(time_t * timer); + + word32 LowResTimer(void) + { + return (word32) XTIME(0); + } + +#elif defined(USE_WINDOWS_API) + + word32 LowResTimer(void) + { + static int init = 0; + static LARGE_INTEGER freq; + LARGE_INTEGER count; + + if (!init) { + QueryPerformanceFrequency(&freq); + init = 1; + } + + QueryPerformanceCounter(&count); + + return (word32)(count.QuadPart / freq.QuadPart); + } + +#elif defined(HAVE_RTP_SYS) + + #include "rtptime.h" + + word32 LowResTimer(void) + { + return (word32)rtp_get_system_sec(); + } + +#elif defined(WOLFSSL_DEOS) + + word32 LowResTimer(void) + { + const uint32_t systemTickTimeInHz = 1000000 / systemTickInMicroseconds(); + uint32_t *systemTickPtr = systemTickPointer(); + + return (word32) *systemTickPtr/systemTickTimeInHz; + } + +#elif defined(MICRIUM) + + word32 LowResTimer(void) + { + OS_TICK ticks = 0; + OS_ERR err; + + ticks = OSTimeGet(&err); + + return (word32) (ticks / OSCfg_TickRate_Hz); + } + + +#elif defined(MICROCHIP_TCPIP_V5) + + word32 LowResTimer(void) + { + return (word32) (TickGet() / TICKS_PER_SECOND); + } + + +#elif defined(MICROCHIP_TCPIP) + + #if defined(MICROCHIP_MPLAB_HARMONY) + + #include + + word32 LowResTimer(void) + { + return (word32) (SYS_TMR_TickCountGet() / + SYS_TMR_TickCounterFrequencyGet()); + } + + #else + + word32 LowResTimer(void) + { + return (word32) (SYS_TICK_Get() / SYS_TICK_TicksPerSecondGet()); + } + + #endif + +#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) + + word32 LowResTimer(void) + { + TIME_STRUCT mqxTime; + + _time_get_elapsed(&mqxTime); + + return (word32) mqxTime.SECONDS; + } +#elif defined(FREESCALE_FREE_RTOS) || defined(FREESCALE_KSDK_FREERTOS) + + #include "include/task.h" + + unsigned int LowResTimer(void) + { + return (unsigned int)(((float)xTaskGetTickCount())/configTICK_RATE_HZ); + } + +#elif defined(FREESCALE_KSDK_BM) + + #include "lwip/sys.h" /* lwIP */ + word32 LowResTimer(void) + { + return sys_now()/1000; + } + +#elif defined(WOLFSSL_TIRTOS) + + word32 LowResTimer(void) + { + return (word32) Seconds_get(); + } +#elif defined(WOLFSSL_XILINX) + #include "xrtcpsu.h" + + word32 LowResTimer(void) + { + XRtcPsu_Config* con; + XRtcPsu rtc; + + con = XRtcPsu_LookupConfig(XPAR_XRTCPSU_0_DEVICE_ID); + if (con != NULL) { + if (XRtcPsu_CfgInitialize(&rtc, con, con->BaseAddr) + == XST_SUCCESS) { + return (word32)XRtcPsu_GetCurrentTime(&rtc); + } + else { + WOLFSSL_MSG("Unable to initialize RTC"); + } + } + + return 0; + } + +#elif defined(WOLFSSL_UTASKER) + + word32 LowResTimer(void) + { + return (word32)(uTaskerSystemTick / TICK_RESOLUTION); + } + +#elif defined(WOLFSSL_NUCLEUS_1_2) + + #define NU_TICKS_PER_SECOND 100 + + word32 LowResTimer(void) + { + /* returns number of 10ms ticks, so 100 ticks/sec */ + return NU_Retrieve_Clock() / NU_TICKS_PER_SECOND; + } +#elif defined(WOLFSSL_APACHE_MYNEWT) + + #include "os/os_time.h" + word32 LowResTimer(void) + { + word32 now; + struct os_timeval tv; + os_gettimeofday(&tv, NULL); + now = (word32)tv.tv_sec; + return now; + } + +#elif defined(WOLFSSL_ZEPHYR) + + word32 LowResTimer(void) + { + return k_uptime_get() / 1000; + } + +#else + /* Posix style time */ + #if !defined(USER_TIME) && !defined(USE_WOLF_TM) + #include + #endif + + word32 LowResTimer(void) + { + return (word32)XTIME(0); + } +#endif +#if !defined(WOLFSSL_NO_CLIENT_AUTH) && defined(HAVE_ED25519) && \ + !defined(NO_ED25519_CLIENT_AUTH) +/* Store the message for use with CertificateVerify using Ed25519. + * + * ssl SSL/TLS object. + * data Message to store. + * sz Size of message to store. + * returns MEMORY_E if not able to reallocate, otherwise 0. + */ +static int Ed25519Update(WOLFSSL* ssl, const byte* data, int sz) +{ + int ret = 0; + byte* msgs; + + if (ssl->options.cacheMessages) { + msgs = (byte*)XREALLOC(ssl->hsHashes->messages, + ssl->hsHashes->length + sz, + ssl->heap, DYNAMIC_TYPE_HASHES); + if (msgs == NULL) + ret = MEMORY_E; + if (ret == 0) { + ssl->hsHashes->messages = msgs; + XMEMCPY(msgs + ssl->hsHashes->length, data, sz); + ssl->hsHashes->prevLen = ssl->hsHashes->length; + ssl->hsHashes->length += sz; + } + } + + return ret; +} +#endif /* HAVE_ED25519 && !WOLFSSL_NO_CLIENT_AUTH */ + +#ifndef NO_CERTS +int HashOutputRaw(WOLFSSL* ssl, const byte* output, int sz) +{ + int ret = 0; + + (void)output; + (void)sz; + + if (ssl->hsHashes == NULL) + return BAD_FUNC_ARG; + +#ifdef HAVE_FUZZER + if (ssl->fuzzerCb) + ssl->fuzzerCb(ssl, output, sz, FUZZ_HASH, ssl->fuzzerCtx); +#endif +#ifndef NO_OLD_TLS + #ifndef NO_SHA + wc_ShaUpdate(&ssl->hsHashes->hashSha, output, sz); + #endif + #ifndef NO_MD5 + wc_Md5Update(&ssl->hsHashes->hashMd5, output, sz); + #endif +#endif /* NO_OLD_TLS */ + + if (IsAtLeastTLSv1_2(ssl)) { + #ifndef NO_SHA256 + ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, output, sz); + if (ret != 0) + return ret; + #endif + #ifdef WOLFSSL_SHA384 + ret = wc_Sha384Update(&ssl->hsHashes->hashSha384, output, sz); + if (ret != 0) + return ret; + #endif + #ifdef WOLFSSL_SHA512 + ret = wc_Sha512Update(&ssl->hsHashes->hashSha512, output, sz); + if (ret != 0) + return ret; + #endif + #if !defined(WOLFSSL_NO_CLIENT_AUTH) && defined(HAVE_ED25519) && \ + !defined(NO_ED25519_CLIENT_AUTH) + ret = Ed25519Update(ssl, output, sz); + if (ret != 0) + return ret; + #endif + } + + return ret; +} +#endif /* NO_CERTS */ + + +/* add output to md5 and sha handshake hashes, exclude record header */ +int HashOutput(WOLFSSL* ssl, const byte* output, int sz, int ivSz) +{ + int ret = 0; + const byte* adj; + + if (ssl->hsHashes == NULL) + return BAD_FUNC_ARG; + + adj = output + RECORD_HEADER_SZ + ivSz; + sz -= RECORD_HEADER_SZ; + +#ifdef HAVE_FUZZER + if (ssl->fuzzerCb) + ssl->fuzzerCb(ssl, output, sz, FUZZ_HASH, ssl->fuzzerCtx); +#endif +#ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + adj += DTLS_RECORD_EXTRA; + sz -= DTLS_RECORD_EXTRA; + } +#endif +#ifndef NO_OLD_TLS + #ifndef NO_SHA + wc_ShaUpdate(&ssl->hsHashes->hashSha, adj, sz); + #endif + #ifndef NO_MD5 + wc_Md5Update(&ssl->hsHashes->hashMd5, adj, sz); + #endif +#endif + + if (IsAtLeastTLSv1_2(ssl)) { + #ifndef NO_SHA256 + ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, adj, sz); + if (ret != 0) + return ret; + #endif + #ifdef WOLFSSL_SHA384 + ret = wc_Sha384Update(&ssl->hsHashes->hashSha384, adj, sz); + if (ret != 0) + return ret; + #endif + #ifdef WOLFSSL_SHA512 + ret = wc_Sha512Update(&ssl->hsHashes->hashSha512, adj, sz); + if (ret != 0) + return ret; + #endif + #if !defined(WOLFSSL_NO_CLIENT_AUTH) && defined(HAVE_ED25519) && \ + !defined(NO_ED25519_CLIENT_AUTH) + ret = Ed25519Update(ssl, adj, sz); + if (ret != 0) + return ret; + #endif + } + + return ret; +} + + +/* add input to md5 and sha handshake hashes, include handshake header */ +int HashInput(WOLFSSL* ssl, const byte* input, int sz) +{ + int ret = 0; + const byte* adj; + + adj = input - HANDSHAKE_HEADER_SZ; + sz += HANDSHAKE_HEADER_SZ; + + (void)adj; + +#ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + adj -= DTLS_HANDSHAKE_EXTRA; + sz += DTLS_HANDSHAKE_EXTRA; + } +#endif + + if (ssl->hsHashes == NULL) { + return BAD_FUNC_ARG; + } + +#ifndef NO_OLD_TLS + #ifndef NO_SHA + wc_ShaUpdate(&ssl->hsHashes->hashSha, adj, sz); + #endif + #ifndef NO_MD5 + wc_Md5Update(&ssl->hsHashes->hashMd5, adj, sz); + #endif +#endif + + if (IsAtLeastTLSv1_2(ssl)) { + #ifndef NO_SHA256 + ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, adj, sz); + if (ret != 0) + return ret; + #endif + #ifdef WOLFSSL_SHA384 + ret = wc_Sha384Update(&ssl->hsHashes->hashSha384, adj, sz); + if (ret != 0) + return ret; + #endif + #ifdef WOLFSSL_SHA512 + ret = wc_Sha512Update(&ssl->hsHashes->hashSha512, adj, sz); + if (ret != 0) + return ret; + #endif + #if !defined(WOLFSSL_NO_CLIENT_AUTH) && defined(HAVE_ED25519) && \ + !defined(NO_ED25519_CLIENT_AUTH) + ret = Ed25519Update(ssl, adj, sz); + if (ret != 0) + return ret; + #endif + } + + return ret; +} + + +/* add record layer header for message */ +static void AddRecordHeader(byte* output, word32 length, byte type, WOLFSSL* ssl) +{ + RecordLayerHeader* rl; + + /* record layer header */ + rl = (RecordLayerHeader*)output; + if (rl == NULL) { + return; + } + rl->type = type; + rl->pvMajor = ssl->version.major; /* type and version same in each */ +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version)) { +#ifdef WOLFSSL_TLS13_DRAFT_18 + rl->pvMinor = TLSv1_MINOR; +#else + rl->pvMinor = TLSv1_2_MINOR; +#endif + } + else +#endif + rl->pvMinor = ssl->version.minor; + +#ifdef WOLFSSL_ALTERNATIVE_DOWNGRADE + if (ssl->options.side == WOLFSSL_CLIENT_END + && ssl->options.connectState == CONNECT_BEGIN + && !ssl->options.resuming) { + rl->pvMinor = ssl->options.downgrade ? ssl->options.minDowngrade + : ssl->version.minor; + } +#endif + + if (!ssl->options.dtls) { + c16toa((word16)length, rl->length); + } + else { +#ifdef WOLFSSL_DTLS + DtlsRecordLayerHeader* dtls; + + /* dtls record layer header extensions */ + dtls = (DtlsRecordLayerHeader*)output; + WriteSEQ(ssl, 0, dtls->sequence_number); + c16toa((word16)length, dtls->length); +#endif + } +} + + +#if !defined(WOLFSSL_NO_TLS12) || (defined(HAVE_SESSION_TICKET) && \ + !defined(NO_WOLFSSL_SERVER)) +/* add handshake header for message */ +static void AddHandShakeHeader(byte* output, word32 length, + word32 fragOffset, word32 fragLength, + byte type, WOLFSSL* ssl) +{ + HandShakeHeader* hs; + (void)fragOffset; + (void)fragLength; + (void)ssl; + + /* handshake header */ + hs = (HandShakeHeader*)output; + if (hs == NULL) + return; + + hs->type = type; + c32to24(length, hs->length); /* type and length same for each */ +#ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + DtlsHandShakeHeader* dtls; + + /* dtls handshake header extensions */ + dtls = (DtlsHandShakeHeader*)output; + c16toa(ssl->keys.dtls_handshake_number++, dtls->message_seq); + c32to24(fragOffset, dtls->fragment_offset); + c32to24(fragLength, dtls->fragment_length); + } +#endif +} + +/* add both headers for handshake message */ +static void AddHeaders(byte* output, word32 length, byte type, WOLFSSL* ssl) +{ + word32 lengthAdj = HANDSHAKE_HEADER_SZ; + word32 outputAdj = RECORD_HEADER_SZ; + +#ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + lengthAdj += DTLS_HANDSHAKE_EXTRA; + outputAdj += DTLS_RECORD_EXTRA; + } +#endif + + AddRecordHeader(output, length + lengthAdj, handshake, ssl); + AddHandShakeHeader(output + outputAdj, length, 0, length, type, ssl); +} +#endif /* !WOLFSSL_NO_TLS12 || (HAVE_SESSION_TICKET && !NO_WOLFSSL_SERVER) */ + + +#ifndef WOLFSSL_NO_TLS12 +#ifndef NO_CERTS +static void AddFragHeaders(byte* output, word32 fragSz, word32 fragOffset, + word32 length, byte type, WOLFSSL* ssl) +{ + word32 lengthAdj = HANDSHAKE_HEADER_SZ; + word32 outputAdj = RECORD_HEADER_SZ; + (void)fragSz; + +#ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + lengthAdj += DTLS_HANDSHAKE_EXTRA; + outputAdj += DTLS_RECORD_EXTRA; + } +#endif + + AddRecordHeader(output, fragSz + lengthAdj, handshake, ssl); + AddHandShakeHeader(output + outputAdj, length, fragOffset, fragSz, type, ssl); +} +#endif /* NO_CERTS */ +#endif /* !WOLFSSL_NO_TLS12 */ + + +/* return bytes received, -1 on error */ +static int wolfSSLReceive(WOLFSSL* ssl, byte* buf, word32 sz) +{ + int recvd; + + if (ssl->CBIORecv == NULL) { + WOLFSSL_MSG("Your IO Recv callback is null, please set"); + return -1; + } + +retry: + recvd = ssl->CBIORecv(ssl, (char *)buf, (int)sz, ssl->IOCB_ReadCtx); + if (recvd < 0) { + switch (recvd) { + case WOLFSSL_CBIO_ERR_GENERAL: /* general/unknown error */ + return -1; + + case WOLFSSL_CBIO_ERR_WANT_READ: /* want read, would block */ + return WANT_READ; + + case WOLFSSL_CBIO_ERR_CONN_RST: /* connection reset */ + #ifdef USE_WINDOWS_API + if (ssl->options.dtls) { + goto retry; + } + #endif + ssl->options.connReset = 1; + return -1; + + case WOLFSSL_CBIO_ERR_ISR: /* interrupt */ + /* see if we got our timeout */ + #ifdef WOLFSSL_CALLBACKS + if (ssl->toInfoOn) { + struct itimerval timeout; + getitimer(ITIMER_REAL, &timeout); + if (timeout.it_value.tv_sec == 0 && + timeout.it_value.tv_usec == 0) { + XSTRNCPY(ssl->timeoutInfo.timeoutName, + "recv() timeout", MAX_TIMEOUT_NAME_SZ); + ssl->timeoutInfo.timeoutName[ + MAX_TIMEOUT_NAME_SZ] = '\0'; + + WOLFSSL_MSG("Got our timeout"); + return WANT_READ; + } + } + #endif + goto retry; + + case WOLFSSL_CBIO_ERR_CONN_CLOSE: /* peer closed connection */ + ssl->options.isClosed = 1; + return -1; + + case WOLFSSL_CBIO_ERR_TIMEOUT: + #ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl) && + !ssl->options.handShakeDone && + DtlsMsgPoolTimeout(ssl) == 0 && + DtlsMsgPoolSend(ssl, 0) == 0) { + + /* retry read for DTLS during handshake only */ + goto retry; + } + #endif + return -1; + + default: + WOLFSSL_MSG("Unexpected recv return code"); + return recvd; + } + } + + return recvd; +} + + +/* Switch dynamic output buffer back to static, buffer is assumed clear */ +void ShrinkOutputBuffer(WOLFSSL* ssl) +{ + WOLFSSL_MSG("Shrinking output buffer\n"); + XFREE(ssl->buffers.outputBuffer.buffer - ssl->buffers.outputBuffer.offset, + ssl->heap, DYNAMIC_TYPE_OUT_BUFFER); + ssl->buffers.outputBuffer.buffer = ssl->buffers.outputBuffer.staticBuffer; + ssl->buffers.outputBuffer.bufferSize = STATIC_BUFFER_LEN; + ssl->buffers.outputBuffer.dynamicFlag = 0; + ssl->buffers.outputBuffer.offset = 0; +} + + +/* Switch dynamic input buffer back to static, keep any remaining input */ +/* forced free means cleaning up */ +void ShrinkInputBuffer(WOLFSSL* ssl, int forcedFree) +{ + int usedLength = ssl->buffers.inputBuffer.length - + ssl->buffers.inputBuffer.idx; + if (!forcedFree && usedLength > STATIC_BUFFER_LEN) + return; + + WOLFSSL_MSG("Shrinking input buffer\n"); + + if (!forcedFree && usedLength > 0) + XMEMCPY(ssl->buffers.inputBuffer.staticBuffer, + ssl->buffers.inputBuffer.buffer + ssl->buffers.inputBuffer.idx, + usedLength); + + XFREE(ssl->buffers.inputBuffer.buffer - ssl->buffers.inputBuffer.offset, + ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + ssl->buffers.inputBuffer.buffer = ssl->buffers.inputBuffer.staticBuffer; + ssl->buffers.inputBuffer.bufferSize = STATIC_BUFFER_LEN; + ssl->buffers.inputBuffer.dynamicFlag = 0; + ssl->buffers.inputBuffer.offset = 0; + ssl->buffers.inputBuffer.idx = 0; + ssl->buffers.inputBuffer.length = usedLength; +} + +int SendBuffered(WOLFSSL* ssl) +{ + if (ssl->CBIOSend == NULL) { + WOLFSSL_MSG("Your IO Send callback is null, please set"); + return SOCKET_ERROR_E; + } + +#ifdef WOLFSSL_DEBUG_TLS + if (ssl->buffers.outputBuffer.idx == 0) { + WOLFSSL_MSG("Data to send"); + WOLFSSL_BUFFER(ssl->buffers.outputBuffer.buffer, + ssl->buffers.outputBuffer.length); + } +#endif + + while (ssl->buffers.outputBuffer.length > 0) { + int sent = ssl->CBIOSend(ssl, + (char*)ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.idx, + (int)ssl->buffers.outputBuffer.length, + ssl->IOCB_WriteCtx); + if (sent < 0) { + switch (sent) { + + case WOLFSSL_CBIO_ERR_WANT_WRITE: /* would block */ + return WANT_WRITE; + + case WOLFSSL_CBIO_ERR_CONN_RST: /* connection reset */ + ssl->options.connReset = 1; + break; + + case WOLFSSL_CBIO_ERR_ISR: /* interrupt */ + /* see if we got our timeout */ + #ifdef WOLFSSL_CALLBACKS + if (ssl->toInfoOn) { + struct itimerval timeout; + getitimer(ITIMER_REAL, &timeout); + if (timeout.it_value.tv_sec == 0 && + timeout.it_value.tv_usec == 0) { + XSTRNCPY(ssl->timeoutInfo.timeoutName, + "send() timeout", MAX_TIMEOUT_NAME_SZ); + ssl->timeoutInfo.timeoutName[ + MAX_TIMEOUT_NAME_SZ] = '\0'; + + WOLFSSL_MSG("Got our timeout"); + return WANT_WRITE; + } + } + #endif + continue; + + case WOLFSSL_CBIO_ERR_CONN_CLOSE: /* epipe / conn closed */ + ssl->options.connReset = 1; /* treat same as reset */ + break; + + default: + return SOCKET_ERROR_E; + } + + return SOCKET_ERROR_E; + } + + if (sent > (int)ssl->buffers.outputBuffer.length) { + WOLFSSL_MSG("SendBuffered() out of bounds read"); + return SEND_OOB_READ_E; + } + + ssl->buffers.outputBuffer.idx += sent; + ssl->buffers.outputBuffer.length -= sent; + } + + ssl->buffers.outputBuffer.idx = 0; + + if (ssl->buffers.outputBuffer.dynamicFlag) + ShrinkOutputBuffer(ssl); + + return 0; +} + + +/* Grow the output buffer */ +static WC_INLINE int GrowOutputBuffer(WOLFSSL* ssl, int size) +{ + byte* tmp; +#if WOLFSSL_GENERAL_ALIGNMENT > 0 + byte hdrSz = ssl->options.dtls ? DTLS_RECORD_HEADER_SZ : + RECORD_HEADER_SZ; + byte align = WOLFSSL_GENERAL_ALIGNMENT; +#else + const byte align = WOLFSSL_GENERAL_ALIGNMENT; +#endif + +#if WOLFSSL_GENERAL_ALIGNMENT > 0 + /* the encrypted data will be offset from the front of the buffer by + the header, if the user wants encrypted alignment they need + to define their alignment requirement */ + + if (align) { + while (align < hdrSz) + align *= 2; + } +#endif + + tmp = (byte*)XMALLOC(size + ssl->buffers.outputBuffer.length + align, + ssl->heap, DYNAMIC_TYPE_OUT_BUFFER); + WOLFSSL_MSG("growing output buffer\n"); + + if (tmp == NULL) + return MEMORY_E; + +#if WOLFSSL_GENERAL_ALIGNMENT > 0 + if (align) + tmp += align - hdrSz; +#endif + + if (ssl->buffers.outputBuffer.length) + XMEMCPY(tmp, ssl->buffers.outputBuffer.buffer, + ssl->buffers.outputBuffer.length); + + if (ssl->buffers.outputBuffer.dynamicFlag) + XFREE(ssl->buffers.outputBuffer.buffer - + ssl->buffers.outputBuffer.offset, ssl->heap, + DYNAMIC_TYPE_OUT_BUFFER); + ssl->buffers.outputBuffer.dynamicFlag = 1; + +#if WOLFSSL_GENERAL_ALIGNMENT > 0 + if (align) + ssl->buffers.outputBuffer.offset = align - hdrSz; + else +#endif + ssl->buffers.outputBuffer.offset = 0; + + ssl->buffers.outputBuffer.buffer = tmp; + ssl->buffers.outputBuffer.bufferSize = size + + ssl->buffers.outputBuffer.length; + return 0; +} + + +/* Grow the input buffer, should only be to read cert or big app data */ +int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength) +{ + byte* tmp; +#if defined(WOLFSSL_DTLS) || WOLFSSL_GENERAL_ALIGNMENT > 0 + byte align = ssl->options.dtls ? WOLFSSL_GENERAL_ALIGNMENT : 0; + byte hdrSz = DTLS_RECORD_HEADER_SZ; +#else + const byte align = WOLFSSL_GENERAL_ALIGNMENT; +#endif + +#if defined(WOLFSSL_DTLS) || WOLFSSL_GENERAL_ALIGNMENT > 0 + /* the encrypted data will be offset from the front of the buffer by + the dtls record header, if the user wants encrypted alignment they need + to define their alignment requirement. in tls we read record header + to get size of record and put actual data back at front, so don't need */ + + if (align) { + while (align < hdrSz) + align *= 2; + } +#endif + + if (usedLength < 0 || size < 0) { + WOLFSSL_MSG("GrowInputBuffer() called with negative number"); + return BAD_FUNC_ARG; + } + + tmp = (byte*)XMALLOC(size + usedLength + align, + ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + WOLFSSL_MSG("growing input buffer\n"); + + if (tmp == NULL) + return MEMORY_E; + +#if defined(WOLFSSL_DTLS) || WOLFSSL_GENERAL_ALIGNMENT > 0 + if (align) + tmp += align - hdrSz; +#endif + + if (usedLength) + XMEMCPY(tmp, ssl->buffers.inputBuffer.buffer + + ssl->buffers.inputBuffer.idx, usedLength); + + if (ssl->buffers.inputBuffer.dynamicFlag) + XFREE(ssl->buffers.inputBuffer.buffer - ssl->buffers.inputBuffer.offset, + ssl->heap,DYNAMIC_TYPE_IN_BUFFER); + + ssl->buffers.inputBuffer.dynamicFlag = 1; +#if defined(WOLFSSL_DTLS) || WOLFSSL_GENERAL_ALIGNMENT > 0 + if (align) + ssl->buffers.inputBuffer.offset = align - hdrSz; + else +#endif + ssl->buffers.inputBuffer.offset = 0; + + ssl->buffers.inputBuffer.buffer = tmp; + ssl->buffers.inputBuffer.bufferSize = size + usedLength; + ssl->buffers.inputBuffer.idx = 0; + ssl->buffers.inputBuffer.length = usedLength; + + return 0; +} + + +/* check available size into output buffer, make room if needed */ +int CheckAvailableSize(WOLFSSL *ssl, int size) +{ + if (size < 0) { + WOLFSSL_MSG("CheckAvailableSize() called with negative number"); + return BAD_FUNC_ARG; + } + + if (ssl->buffers.outputBuffer.bufferSize - ssl->buffers.outputBuffer.length + < (word32)size) { + if (GrowOutputBuffer(ssl, size) < 0) + return MEMORY_E; + } + + return 0; +} + + +/* do all verify and sanity checks on record header */ +static int GetRecordHeader(WOLFSSL* ssl, const byte* input, word32* inOutIdx, + RecordLayerHeader* rh, word16 *size) +{ + if (!ssl->options.dtls) { +#ifdef HAVE_FUZZER + if (ssl->fuzzerCb) + ssl->fuzzerCb(ssl, input + *inOutIdx, RECORD_HEADER_SZ, FUZZ_HEAD, + ssl->fuzzerCtx); +#endif + XMEMCPY(rh, input + *inOutIdx, RECORD_HEADER_SZ); + *inOutIdx += RECORD_HEADER_SZ; + ato16(rh->length, size); + } + else { +#ifdef WOLFSSL_DTLS +#ifdef HAVE_FUZZER + if (ssl->fuzzerCb) + ssl->fuzzerCb(ssl, input + *inOutIdx, DTLS_RECORD_HEADER_SZ, + FUZZ_HEAD, ssl->fuzzerCtx); +#endif + /* type and version in same sport */ + XMEMCPY(rh, input + *inOutIdx, ENUM_LEN + VERSION_SZ); + *inOutIdx += ENUM_LEN + VERSION_SZ; + ato16(input + *inOutIdx, &ssl->keys.curEpoch); + *inOutIdx += OPAQUE16_LEN; + if (ssl->options.haveMcast) { + #ifdef WOLFSSL_MULTICAST + ssl->keys.curPeerId = input[*inOutIdx]; + ssl->keys.curSeq_hi = input[*inOutIdx+1]; + #endif + } + else + ato16(input + *inOutIdx, &ssl->keys.curSeq_hi); + *inOutIdx += OPAQUE16_LEN; + ato32(input + *inOutIdx, &ssl->keys.curSeq_lo); + *inOutIdx += OPAQUE32_LEN; /* advance past rest of seq */ + ato16(input + *inOutIdx, size); + *inOutIdx += LENGTH_SZ; +#endif + } + +#ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl) && + (!DtlsCheckWindow(ssl) || + (ssl->options.handShakeDone && ssl->keys.curEpoch == 0))) { + WOLFSSL_LEAVE("GetRecordHeader()", SEQUENCE_ERROR); + return SEQUENCE_ERROR; + } +#endif + + /* catch version mismatch */ +#ifndef WOLFSSL_TLS13 + if (rh->pvMajor != ssl->version.major || rh->pvMinor != ssl->version.minor) +#else + if (rh->pvMajor != ssl->version.major || + (rh->pvMinor != ssl->version.minor && +#ifdef WOLFSSL_TLS13_DRAFT_18 + (!IsAtLeastTLSv1_3(ssl->version) || rh->pvMinor != TLSv1_MINOR) +#else + (!IsAtLeastTLSv1_3(ssl->version) || rh->pvMinor != TLSv1_2_MINOR) +#endif + )) +#endif + { + if (ssl->options.side == WOLFSSL_SERVER_END && + ssl->options.acceptState < ACCEPT_FIRST_REPLY_DONE) + + WOLFSSL_MSG("Client attempting to connect with different version"); + else if (ssl->options.side == WOLFSSL_CLIENT_END && + ssl->options.downgrade && + ssl->options.connectState < FIRST_REPLY_DONE) + WOLFSSL_MSG("Server attempting to accept with different version"); + else if (ssl->options.dtls && rh->type == handshake) + /* Check the DTLS handshake message RH version later. */ + WOLFSSL_MSG("DTLS handshake, skip RH version number check"); + else { + WOLFSSL_MSG("SSL version error"); + /* send alert per RFC5246 Appendix E. Backward Compatibility */ + if (ssl->options.side == WOLFSSL_CLIENT_END) { +#ifdef WOLFSSL_MYSQL_COMPATIBLE + SendAlert(ssl, alert_fatal, wc_protocol_version); +#else + SendAlert(ssl, alert_fatal, protocol_version); +#endif + } + return VERSION_ERROR; /* only use requested version */ + } + } + + /* record layer length check */ +#ifdef HAVE_MAX_FRAGMENT + if (*size > (ssl->max_fragment + MAX_COMP_EXTRA + MAX_MSG_EXTRA)) { + SendAlert(ssl, alert_fatal, record_overflow); + return LENGTH_ERROR; + } +#else + if (*size > (MAX_RECORD_SIZE + MAX_COMP_EXTRA + MAX_MSG_EXTRA)) + return LENGTH_ERROR; +#endif + + /* verify record type here as well */ + switch (rh->type) { + case handshake: + case change_cipher_spec: + case application_data: + case alert: + break; + case no_type: + default: + WOLFSSL_MSG("Unknown Record Type"); + return UNKNOWN_RECORD_TYPE; + } + + /* haven't decrypted this record yet */ + ssl->keys.decryptedCur = 0; + + return 0; +} + +#ifndef WOLFSSL_NO_TLS12 +static int GetHandShakeHeader(WOLFSSL* ssl, const byte* input, word32* inOutIdx, + byte *type, word32 *size, word32 totalSz) +{ + const byte *ptr = input + *inOutIdx; + (void)ssl; + + *inOutIdx += HANDSHAKE_HEADER_SZ; + if (*inOutIdx > totalSz) + return BUFFER_E; + + *type = ptr[0]; + c24to32(&ptr[1], size); + + return 0; +} +#endif + +#ifdef WOLFSSL_DTLS +static int GetDtlsHandShakeHeader(WOLFSSL* ssl, const byte* input, + word32* inOutIdx, byte *type, word32 *size, + word32 *fragOffset, word32 *fragSz, + word32 totalSz) +{ + word32 idx = *inOutIdx; + + *inOutIdx += HANDSHAKE_HEADER_SZ + DTLS_HANDSHAKE_EXTRA; + if (*inOutIdx > totalSz) { + WOLFSSL_ERROR(BUFFER_E); + return BUFFER_E; + } + + *type = input[idx++]; + c24to32(input + idx, size); + idx += OPAQUE24_LEN; + + ato16(input + idx, &ssl->keys.dtls_peer_handshake_number); + idx += DTLS_HANDSHAKE_SEQ_SZ; + + c24to32(input + idx, fragOffset); + idx += DTLS_HANDSHAKE_FRAG_SZ; + c24to32(input + idx, fragSz); + + if (ssl->curRL.pvMajor != ssl->version.major || + ssl->curRL.pvMinor != ssl->version.minor) { + + if (*type != client_hello && *type != hello_verify_request) { + WOLFSSL_ERROR(VERSION_ERROR); + return VERSION_ERROR; + } + else { + WOLFSSL_MSG("DTLS Handshake ignoring hello or verify version"); + } + } + return 0; +} +#endif + + +#if !defined(NO_OLD_TLS) || \ + (defined(NO_OLD_TLS) && defined(WOLFSSL_ALLOW_TLS_SHA1)) +/* fill with MD5 pad size since biggest required */ +static const byte PAD1[PAD_MD5] = + { 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, + 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36 + }; +static const byte PAD2[PAD_MD5] = + { 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, + 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, + 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, + 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, + 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, + 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c + }; +#endif /* !NO_OLD_TLS || (NO_OLD_TLS && WOLFSSL_ALLOW_TLS_SHA1) */ + +#ifndef NO_OLD_TLS + +/* calculate MD5 hash for finished */ +#ifdef WOLFSSL_TI_HASH +#include +#endif + +static int BuildMD5(WOLFSSL* ssl, Hashes* hashes, const byte* sender) +{ + int ret; + byte md5_result[WC_MD5_DIGEST_SIZE]; +#ifdef WOLFSSL_SMALL_STACK + wc_Md5* md5 = (wc_Md5*)XMALLOC(sizeof(wc_Md5), ssl->heap, DYNAMIC_TYPE_HASHCTX); + if (md5 == NULL) + return MEMORY_E; +#else + wc_Md5 md5[1]; +#endif + + /* make md5 inner */ + ret = wc_Md5Copy(&ssl->hsHashes->hashMd5, md5); + if (ret == 0) + ret = wc_Md5Update(md5, sender, SIZEOF_SENDER); + if (ret == 0) + ret = wc_Md5Update(md5, ssl->arrays->masterSecret,SECRET_LEN); + if (ret == 0) + ret = wc_Md5Update(md5, PAD1, PAD_MD5); + if (ret == 0) + ret = wc_Md5Final(md5, md5_result); + + /* make md5 outer */ + if (ret == 0) { + ret = wc_InitMd5_ex(md5, ssl->heap, ssl->devId); + if (ret == 0) { + ret = wc_Md5Update(md5, ssl->arrays->masterSecret,SECRET_LEN); + if (ret == 0) + ret = wc_Md5Update(md5, PAD2, PAD_MD5); + if (ret == 0) + ret = wc_Md5Update(md5, md5_result, WC_MD5_DIGEST_SIZE); + if (ret == 0) + ret = wc_Md5Final(md5, hashes->md5); + wc_Md5Free(md5); + } + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(md5, ssl->heap, DYNAMIC_TYPE_HASHCTX); +#endif + + return ret; +} + + +/* calculate SHA hash for finished */ +static int BuildSHA(WOLFSSL* ssl, Hashes* hashes, const byte* sender) +{ + int ret; + byte sha_result[WC_SHA_DIGEST_SIZE]; +#ifdef WOLFSSL_SMALL_STACK + wc_Sha* sha = (wc_Sha*)XMALLOC(sizeof(wc_Sha), ssl->heap, DYNAMIC_TYPE_HASHCTX); + if (sha == NULL) + return MEMORY_E; +#else + wc_Sha sha[1]; +#endif + /* make sha inner */ + ret = wc_ShaCopy(&ssl->hsHashes->hashSha, sha); /* Save current position */ + if (ret == 0) + ret = wc_ShaUpdate(sha, sender, SIZEOF_SENDER); + if (ret == 0) + ret = wc_ShaUpdate(sha, ssl->arrays->masterSecret,SECRET_LEN); + if (ret == 0) + ret = wc_ShaUpdate(sha, PAD1, PAD_SHA); + if (ret == 0) + ret = wc_ShaFinal(sha, sha_result); + + /* make sha outer */ + if (ret == 0) { + ret = wc_InitSha_ex(sha, ssl->heap, ssl->devId); + if (ret == 0) { + ret = wc_ShaUpdate(sha, ssl->arrays->masterSecret,SECRET_LEN); + if (ret == 0) + ret = wc_ShaUpdate(sha, PAD2, PAD_SHA); + if (ret == 0) + ret = wc_ShaUpdate(sha, sha_result, WC_SHA_DIGEST_SIZE); + if (ret == 0) + ret = wc_ShaFinal(sha, hashes->sha); + wc_ShaFree(sha); + } + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(sha, ssl->heap, DYNAMIC_TYPE_HASHCTX); +#endif + + return ret; +} +#endif + +#ifndef WOLFSSL_NO_TLS12 + +/* Finished doesn't support SHA512, not SHA512 cipher suites yet */ +static int BuildFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) +{ + int ret = 0; + + if (ssl == NULL) + return BAD_FUNC_ARG; + +#ifndef NO_TLS + if (ssl->options.tls) { + ret = BuildTlsFinished(ssl, hashes, sender); + } +#endif +#ifndef NO_OLD_TLS + if (!ssl->options.tls) { + ret = BuildMD5(ssl, hashes, sender); + if (ret == 0) { + ret = BuildSHA(ssl, hashes, sender); + } + } +#endif + + return ret; +} + +#endif /* WOLFSSL_NO_TLS12 */ + +#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_WOLFSSL_CLIENT) + /* cipher requirements */ + enum { + REQUIRES_RSA, + REQUIRES_DHE, + REQUIRES_ECC, + REQUIRES_ECC_STATIC, + REQUIRES_PSK, + REQUIRES_NTRU, + REQUIRES_RSA_SIG + }; + + + + /* Does this cipher suite (first, second) have the requirement + an ephemeral key exchange will still require the key for signing + the key exchange so ECHDE_RSA requires an rsa key thus rsa_kea */ + static int CipherRequires(byte first, byte second, int requirement) + { + + (void)requirement; + +#ifndef WOLFSSL_NO_TLS12 + +#ifdef HAVE_CHACHA + if (first == CHACHA_BYTE) { + + switch (second) { + case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 : + if (requirement == REQUIRES_RSA) + return 1; + break; + + case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 : + if (requirement == REQUIRES_ECC) + return 1; + break; + + case TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 : + if (requirement == REQUIRES_RSA) + return 1; + if (requirement == REQUIRES_DHE) + return 1; + break; + + case TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 : + if (requirement == REQUIRES_RSA) + return 1; + break; + + case TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256 : + if (requirement == REQUIRES_ECC) + return 1; + break; + + case TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 : + if (requirement == REQUIRES_RSA) + return 1; + if (requirement == REQUIRES_DHE) + return 1; + break; + + + case TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 : + if (requirement == REQUIRES_PSK) + return 1; + break; + + case TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 : + if (requirement == REQUIRES_PSK) + return 1; + break; + + case TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 : + if (requirement == REQUIRES_PSK) + return 1; + if (requirement == REQUIRES_DHE) + return 1; + break; + } + } +#endif /* HAVE_CHACHA */ + + /* ECC extensions */ + if (first == ECC_BYTE) { + + switch (second) { +#ifdef HAVE_ECC + #ifndef NO_RSA + case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA : + if (requirement == REQUIRES_RSA) + return 1; + break; + + case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA : + if (requirement == REQUIRES_ECC_STATIC) + return 1; + if (requirement == REQUIRES_RSA_SIG) + return 1; + break; + + #ifndef NO_DES3 + case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA : + if (requirement == REQUIRES_RSA) + return 1; + break; + + case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA : + if (requirement == REQUIRES_ECC_STATIC) + return 1; + if (requirement == REQUIRES_RSA_SIG) + return 1; + break; + #endif /* !NO_DES3 */ + + #ifndef NO_RC4 + case TLS_ECDHE_RSA_WITH_RC4_128_SHA : + if (requirement == REQUIRES_RSA) + return 1; + break; + + case TLS_ECDH_RSA_WITH_RC4_128_SHA : + if (requirement == REQUIRES_ECC_STATIC) + return 1; + if (requirement == REQUIRES_RSA_SIG) + return 1; + break; + #endif /* !NO_RC4 */ + #endif /* NO_RSA */ + + #ifndef NO_DES3 + case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA : + if (requirement == REQUIRES_ECC) + return 1; + break; + + case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA : + if (requirement == REQUIRES_ECC_STATIC) + return 1; + break; + #endif /* !NO_DES3 */ + #ifndef NO_RC4 + case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA : + if (requirement == REQUIRES_ECC) + return 1; + break; + + case TLS_ECDH_ECDSA_WITH_RC4_128_SHA : + if (requirement == REQUIRES_ECC_STATIC) + return 1; + break; + #endif /* !NO_RC4 */ + #ifndef NO_RSA + case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA : + if (requirement == REQUIRES_RSA) + return 1; + break; + + case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA : + if (requirement == REQUIRES_ECC_STATIC) + return 1; + if (requirement == REQUIRES_RSA_SIG) + return 1; + break; + #endif /* !NO_RSA */ + + case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA : + if (requirement == REQUIRES_ECC) + return 1; + break; + + case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA : + if (requirement == REQUIRES_ECC_STATIC) + return 1; + break; + + case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA : + if (requirement == REQUIRES_ECC) + return 1; + break; + + case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA : + if (requirement == REQUIRES_ECC_STATIC) + return 1; + break; + + case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 : + if (requirement == REQUIRES_ECC) + return 1; + break; + + case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 : + if (requirement == REQUIRES_ECC) + return 1; + break; + + case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 : + if (requirement == REQUIRES_ECC_STATIC) + return 1; + break; + + case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 : + if (requirement == REQUIRES_ECC_STATIC) + return 1; + break; +#endif /* HAVE_ECC */ + +#ifndef NO_RSA + #ifdef HAVE_ECC + case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 : + if (requirement == REQUIRES_RSA) + return 1; + break; + + case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 : + if (requirement == REQUIRES_RSA) + return 1; + break; + + case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 : + if (requirement == REQUIRES_ECC_STATIC) + return 1; + if (requirement == REQUIRES_RSA_SIG) + return 1; + break; + + case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 : + if (requirement == REQUIRES_ECC_STATIC) + return 1; + if (requirement == REQUIRES_RSA_SIG) + return 1; + break; + #endif /* HAVE_ECC */ + #ifdef HAVE_AESCCM + case TLS_RSA_WITH_AES_128_CCM_8 : + case TLS_RSA_WITH_AES_256_CCM_8 : + if (requirement == REQUIRES_RSA) + return 1; + if (requirement == REQUIRES_RSA_SIG) + return 1; + break; + #endif /* HAVE_AESCCM */ + #ifdef HAVE_ECC + + case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 : + case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 : + if (requirement == REQUIRES_RSA) + return 1; + break; + + case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 : + case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 : + if (requirement == REQUIRES_RSA_SIG) + return 1; + if (requirement == REQUIRES_ECC_STATIC) + return 1; + break; + #endif /* HAVE_ECC */ +#endif /* !NO_RSA */ + +#ifdef HAVE_ECC + case TLS_ECDHE_ECDSA_WITH_AES_128_CCM : + case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 : + case TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 : + if (requirement == REQUIRES_ECC) + return 1; + break; + + case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 : + case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : + if (requirement == REQUIRES_ECC) + return 1; + break; + + case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 : + case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 : + if (requirement == REQUIRES_ECC) + return 1; + if (requirement == REQUIRES_ECC_STATIC) + return 1; + break; +#endif /* HAVE_ECC */ + +#ifndef NO_PSK + case TLS_PSK_WITH_AES_128_CCM: + case TLS_PSK_WITH_AES_256_CCM: + case TLS_PSK_WITH_AES_128_CCM_8: + case TLS_PSK_WITH_AES_256_CCM_8: + if (requirement == REQUIRES_PSK) + return 1; + break; + + case TLS_DHE_PSK_WITH_AES_128_CCM: + case TLS_DHE_PSK_WITH_AES_256_CCM: + if (requirement == REQUIRES_PSK) + return 1; + if (requirement == REQUIRES_DHE) + return 1; + break; +#endif /* !NO_PSK */ +#ifdef HAVE_ECC + case TLS_ECDHE_ECDSA_WITH_NULL_SHA : + if (requirement == REQUIRES_ECC) + return 1; + break; + + case TLS_ECDHE_PSK_WITH_NULL_SHA256 : + if (requirement == REQUIRES_PSK) + return 1; + break; + + case TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 : + if (requirement == REQUIRES_PSK) + return 1; + break; +#endif /* HAVE_ECC */ + default: + WOLFSSL_MSG("Unsupported cipher suite, CipherRequires ECC"); + return 0; + } /* switch */ + } /* if */ + +#endif /* !WOLFSSL_NO_TLS12 */ + + /* Distinct TLS v1.3 cipher suites with cipher and digest only. */ + if (first == TLS13_BYTE) { + + switch (second) { +#ifdef WOLFSSL_TLS13 + case TLS_AES_128_GCM_SHA256: + case TLS_AES_256_GCM_SHA384: + case TLS_CHACHA20_POLY1305_SHA256: + case TLS_AES_128_CCM_SHA256: + case TLS_AES_128_CCM_8_SHA256: + break; +#endif + + default: + WOLFSSL_MSG("Unsupported cipher suite, CipherRequires " + "TLS v1.3"); + return 0; + } + } + +#ifndef WOLFSSL_NO_TLS12 + + if (first != ECC_BYTE && first != CHACHA_BYTE && + first != TLS13_BYTE) { /* normal suites */ + switch (second) { + +#ifndef NO_RSA + #ifndef NO_RC4 + case SSL_RSA_WITH_RC4_128_SHA : + if (requirement == REQUIRES_RSA) + return 1; + break; + + case SSL_RSA_WITH_RC4_128_MD5 : + if (requirement == REQUIRES_RSA) + return 1; + break; + #endif /* NO_RC4 */ + + case SSL_RSA_WITH_3DES_EDE_CBC_SHA : + if (requirement == REQUIRES_RSA) + return 1; + break; + + #ifdef HAVE_NTRU + case TLS_NTRU_RSA_WITH_RC4_128_SHA : + if (requirement == REQUIRES_NTRU) + return 1; + break; + #endif /* HAVE_NTRU */ + + case TLS_RSA_WITH_AES_128_CBC_SHA : + if (requirement == REQUIRES_RSA) + return 1; + break; + + case TLS_RSA_WITH_AES_128_CBC_SHA256 : + if (requirement == REQUIRES_RSA) + return 1; + break; + + #ifdef HAVE_NTRU + case TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA : + if (requirement == REQUIRES_NTRU) + return 1; + break; + #endif /* HAVE_NTRU */ + + case TLS_RSA_WITH_AES_256_CBC_SHA : + if (requirement == REQUIRES_RSA) + return 1; + break; + + #ifdef HAVE_NTRU + case TLS_NTRU_RSA_WITH_AES_128_CBC_SHA : + if (requirement == REQUIRES_NTRU) + return 1; + break; + #endif /* HAVE_NTRU */ + + case TLS_RSA_WITH_AES_256_CBC_SHA256 : + if (requirement == REQUIRES_RSA) + return 1; + break; + + case TLS_RSA_WITH_NULL_MD5 : + case TLS_RSA_WITH_NULL_SHA : + case TLS_RSA_WITH_NULL_SHA256 : + if (requirement == REQUIRES_RSA) + return 1; + break; + + #ifdef HAVE_NTRU + case TLS_NTRU_RSA_WITH_AES_256_CBC_SHA : + if (requirement == REQUIRES_NTRU) + return 1; + break; + #endif /* HAVE_NTRU */ + + #ifdef HAVE_IDEA + case SSL_RSA_WITH_IDEA_CBC_SHA : + if (requirement == REQUIRES_RSA) + return 1; + break; + #endif /* HAVE_IDEA */ +#endif /* !NO_RSA */ + +#ifndef NO_PSK + case TLS_PSK_WITH_AES_128_GCM_SHA256 : + case TLS_PSK_WITH_AES_256_GCM_SHA384 : + case TLS_PSK_WITH_AES_128_CBC_SHA256 : + case TLS_PSK_WITH_AES_256_CBC_SHA384 : + case TLS_PSK_WITH_AES_128_CBC_SHA : + case TLS_PSK_WITH_AES_256_CBC_SHA : + case TLS_PSK_WITH_NULL_SHA384 : + case TLS_PSK_WITH_NULL_SHA256 : + case TLS_PSK_WITH_NULL_SHA : + if (requirement == REQUIRES_PSK) + return 1; + break; + + case TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 : + case TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 : + case TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 : + case TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 : + case TLS_DHE_PSK_WITH_NULL_SHA384 : + case TLS_DHE_PSK_WITH_NULL_SHA256 : + if (requirement == REQUIRES_DHE) + return 1; + if (requirement == REQUIRES_PSK) + return 1; + break; +#endif /* NO_PSK */ + +#ifndef NO_RSA + case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 : + if (requirement == REQUIRES_RSA) + return 1; + if (requirement == REQUIRES_DHE) + return 1; + break; + + case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 : + if (requirement == REQUIRES_RSA) + return 1; + if (requirement == REQUIRES_DHE) + return 1; + break; + + case TLS_DHE_RSA_WITH_AES_128_CBC_SHA : + if (requirement == REQUIRES_RSA) + return 1; + if (requirement == REQUIRES_DHE) + return 1; + break; + + case TLS_DHE_RSA_WITH_AES_256_CBC_SHA : + if (requirement == REQUIRES_RSA) + return 1; + if (requirement == REQUIRES_DHE) + return 1; + break; + +#ifndef NO_HC128 + case TLS_RSA_WITH_HC_128_MD5 : + if (requirement == REQUIRES_RSA) + return 1; + break; + + case TLS_RSA_WITH_HC_128_SHA : + if (requirement == REQUIRES_RSA) + return 1; + break; + + case TLS_RSA_WITH_HC_128_B2B256: + if (requirement == REQUIRES_RSA) + return 1; + break; +#endif /* NO_HC128 */ + +#ifdef HAVE_BLAKE2 + case TLS_RSA_WITH_AES_128_CBC_B2B256: + case TLS_RSA_WITH_AES_256_CBC_B2B256: + if (requirement == REQUIRES_RSA) + return 1; + break; +#endif /* HAVE_BLAKE2 */ + +#ifndef NO_RABBIT + case TLS_RSA_WITH_RABBIT_SHA : + if (requirement == REQUIRES_RSA) + return 1; + break; +#endif /* !NO_RABBIT */ + + case TLS_RSA_WITH_AES_128_GCM_SHA256 : + case TLS_RSA_WITH_AES_256_GCM_SHA384 : + if (requirement == REQUIRES_RSA) + return 1; + break; + + case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 : + case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 : + if (requirement == REQUIRES_RSA) + return 1; + if (requirement == REQUIRES_DHE) + return 1; + break; + +#ifdef HAVE_CAMELLIA + case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA : + case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA : + case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 : + case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 : + if (requirement == REQUIRES_RSA) + return 1; + break; + + case TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA : + case TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA : + case TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 : + case TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 : + if (requirement == REQUIRES_RSA) + return 1; + if (requirement == REQUIRES_RSA_SIG) + return 1; + if (requirement == REQUIRES_DHE) + return 1; + break; +#endif /* HAVE_CAMELLIA */ + + case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA: + if (requirement == REQUIRES_RSA) + return 1; + if (requirement == REQUIRES_RSA_SIG) + return 1; + if (requirement == REQUIRES_DHE) + return 1; + break; +#endif +#ifdef HAVE_ANON + case TLS_DH_anon_WITH_AES_128_CBC_SHA : + if (requirement == REQUIRES_DHE) + return 1; + break; + case TLS_DH_anon_WITH_AES_256_GCM_SHA384: + if (requirement == REQUIRES_DHE) + return 1; + break; +#endif +#ifdef WOLFSSL_MULTICAST + case WDM_WITH_NULL_SHA256 : + break; +#endif + + default: + WOLFSSL_MSG("Unsupported cipher suite, CipherRequires"); + return 0; + } /* switch */ + } /* if ECC / Normal suites else */ + +#endif /* !WOLFSSL_NO_TLS12 */ + + return 0; + } + +#endif /* !NO_WOLFSSL_SERVER && !NO_WOLFSSL_CLIENT */ + + +#ifndef NO_CERTS + + +/* Match names with wildcards, each wildcard can represent a single name + component or fragment but not mulitple names, i.e., + *.z.com matches y.z.com but not x.y.z.com + + return 1 on success */ +int MatchDomainName(const char* pattern, int len, const char* str) +{ + int ret = 0; + char p, s; + + if (pattern == NULL || str == NULL || len <= 0) + return 0; + + while (len > 0) { + + p = (char)XTOLOWER((unsigned char)*pattern++); + if (p == '\0') + break; + + if (p == '*') { + while (--len > 0 && + (p = (char)XTOLOWER((unsigned char)*pattern++)) == '*') { + } + + if (len == 0) + p = '\0'; + + while ( (s = (char)XTOLOWER((unsigned char) *str)) != '\0') { + if (s == p) + break; + if (s == '.') + return 0; + str++; + } + } + else { + if (p != (char)XTOLOWER((unsigned char) *str)) + return 0; + } + + + if (len > 0) { + str++; + len--; + } + } + + if (*str == '\0' && len == 0) { + ret = 1; /* success */ + } + + return ret; +} + + +/* try to find an altName match to domain, return 1 on success */ +int CheckAltNames(DecodedCert* dCert, char* domain) +{ + int match = 0; + DNS_entry* altName = NULL; + + WOLFSSL_MSG("Checking AltNames"); + + if (dCert) + altName = dCert->altNames; + + while (altName) { + WOLFSSL_MSG("\tindividual AltName check"); + + if (MatchDomainName(altName->name, altName->len, domain)){ + match = 1; + break; + } + + altName = altName->next; + } + + return match; +} + + +#ifdef OPENSSL_EXTRA +/* Check that alternative names, if they exists, match the domain. + * Fail if there are wild patterns and they didn't match. + * Check the common name if no alternative names matched. + * + * dCert Decoded cert to get the alternative names from. + * domain Domain name to compare against. + * checkCN Whether to check the common name. + * returns whether there was a problem in matching. + */ +static int CheckForAltNames(DecodedCert* dCert, char* domain, int* checkCN) +{ + int match; + DNS_entry* altName = NULL; + + WOLFSSL_MSG("Checking AltNames"); + + if (dCert) + altName = dCert->altNames; + + *checkCN = altName == NULL; + match = 0; + while (altName) { + WOLFSSL_MSG("\tindividual AltName check"); + + if (MatchDomainName(altName->name, altName->len, domain)) { + match = 1; + *checkCN = 0; + break; + } + /* No matches and wild pattern match failed. */ + else if (altName->name[0] == '*' && match == 0) + match = -1; + + altName = altName->next; + } + + return match != -1; +} + +/* Check the domain name matches the subject alternative name or the subject + * name. + * + * dcert Decoded certificate. + * domainName The domain name. + * domainNameLen The length of the domain name. + * returns DOMAIN_NAME_MISMATCH when no match found and 0 on success. + */ +int CheckHostName(DecodedCert* dCert, char *domainName, size_t domainNameLen) +{ + int checkCN; + + /* Assume name is NUL terminated. */ + (void)domainNameLen; + + if (CheckForAltNames(dCert, domainName, &checkCN) == 0) { + WOLFSSL_MSG("DomainName match on alt names failed too"); + return DOMAIN_NAME_MISMATCH; + } + if (checkCN == 1) { + if (MatchDomainName(dCert->subjectCN, dCert->subjectCNLen, + domainName) == 0) { + WOLFSSL_MSG("DomainName match on common name failed"); + return DOMAIN_NAME_MISMATCH; + } + } + + return 0; +} +#endif + +#ifdef SESSION_CERTS +static void AddSessionCertToChain(WOLFSSL_X509_CHAIN* chain, + byte* certBuf, word32 certSz) +{ + if (chain->count < MAX_CHAIN_DEPTH && + certSz < MAX_X509_SIZE) { + chain->certs[chain->count].length = certSz; + XMEMCPY(chain->certs[chain->count].buffer, certBuf, certSz); + chain->count++; + } + else { + WOLFSSL_MSG("Couldn't store chain cert for session"); + } +} +#endif + +#if defined(KEEP_PEER_CERT) || defined(SESSION_CERTS) || \ + defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) +/* Copy parts X509 needs from Decoded cert, 0 on success */ +/* The same DecodedCert cannot be copied to WOLFSSL_X509 twice otherwise the + * altNames pointers could be free'd by second x509 still active by first */ +int CopyDecodedToX509(WOLFSSL_X509* x509, DecodedCert* dCert) +{ + int ret = 0; + + if (x509 == NULL || dCert == NULL || + dCert->subjectCNLen < 0) + return BAD_FUNC_ARG; + + x509->version = dCert->version + 1; + + XSTRNCPY(x509->issuer.name, dCert->issuer, ASN_NAME_MAX); + x509->issuer.name[ASN_NAME_MAX - 1] = '\0'; + x509->issuer.sz = (int)XSTRLEN(x509->issuer.name) + 1; +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + if (dCert->issuerName.fullName != NULL) { + XMEMCPY(&x509->issuer.fullName, + &dCert->issuerName, sizeof(DecodedName)); + x509->issuer.fullName.fullName = (char*)XMALLOC( + dCert->issuerName.fullNameLen, x509->heap, + DYNAMIC_TYPE_X509); + if (x509->issuer.fullName.fullName != NULL) + XMEMCPY(x509->issuer.fullName.fullName, + dCert->issuerName.fullName, dCert->issuerName.fullNameLen); + } + x509->issuer.x509 = x509; +#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ + + XSTRNCPY(x509->subject.name, dCert->subject, ASN_NAME_MAX); + x509->subject.name[ASN_NAME_MAX - 1] = '\0'; + x509->subject.sz = (int)XSTRLEN(x509->subject.name) + 1; +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + if (dCert->subjectName.fullName != NULL) { + XMEMCPY(&x509->subject.fullName, + &dCert->subjectName, sizeof(DecodedName)); + x509->subject.fullName.fullName = (char*)XMALLOC( + dCert->subjectName.fullNameLen, x509->heap, DYNAMIC_TYPE_X509); + if (x509->subject.fullName.fullName != NULL) + XMEMCPY(x509->subject.fullName.fullName, + dCert->subjectName.fullName, dCert->subjectName.fullNameLen); + } + x509->subject.x509 = x509; +#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) + x509->subject.rawLen = min(dCert->subjectRawLen, sizeof(x509->subject.raw)); + XMEMCPY(x509->subject.raw, dCert->subjectRaw, x509->subject.rawLen); +#ifdef WOLFSSL_CERT_EXT + x509->issuer.rawLen = min(dCert->issuerRawLen, sizeof(x509->issuer.raw)); + XMEMCPY(x509->issuer.raw, dCert->issuerRaw, x509->issuer.rawLen); +#endif +#endif + + XMEMCPY(x509->serial, dCert->serial, EXTERNAL_SERIAL_SIZE); + x509->serialSz = dCert->serialSz; + if (dCert->subjectCN && dCert->subjectCNLen < ASN_NAME_MAX) { + XMEMCPY(x509->subjectCN, dCert->subjectCN, dCert->subjectCNLen); + x509->subjectCN[dCert->subjectCNLen] = '\0'; + } + else + x509->subjectCN[0] = '\0'; + +#ifdef WOLFSSL_SEP + { + int minSz = min(dCert->deviceTypeSz, EXTERNAL_SERIAL_SIZE); + if (minSz > 0) { + x509->deviceTypeSz = minSz; + XMEMCPY(x509->deviceType, dCert->deviceType, minSz); + } + else + x509->deviceTypeSz = 0; + minSz = min(dCert->hwTypeSz, EXTERNAL_SERIAL_SIZE); + if (minSz > 0) { + x509->hwTypeSz = minSz; + XMEMCPY(x509->hwType, dCert->hwType, minSz); + } + else + x509->hwTypeSz = 0; + minSz = min(dCert->hwSerialNumSz, EXTERNAL_SERIAL_SIZE); + if (minSz > 0) { + x509->hwSerialNumSz = minSz; + XMEMCPY(x509->hwSerialNum, dCert->hwSerialNum, minSz); + } + else + x509->hwSerialNumSz = 0; + } +#endif /* WOLFSSL_SEP */ + { + int minSz = min(dCert->beforeDateLen, MAX_DATE_SZ); + if (minSz > 0) { + x509->notBeforeSz = minSz; + XMEMCPY(x509->notBefore, dCert->beforeDate, minSz); + } + else + x509->notBeforeSz = 0; + minSz = min(dCert->afterDateLen, MAX_DATE_SZ); + if (minSz > 0) { + x509->notAfterSz = minSz; + XMEMCPY(x509->notAfter, dCert->afterDate, minSz); + } + else + x509->notAfterSz = 0; + } + + if (dCert->publicKey != NULL && dCert->pubKeySize != 0) { + x509->pubKey.buffer = (byte*)XMALLOC( + dCert->pubKeySize, x509->heap, DYNAMIC_TYPE_PUBLIC_KEY); + if (x509->pubKey.buffer != NULL) { + x509->pubKeyOID = dCert->keyOID; + x509->pubKey.length = dCert->pubKeySize; + XMEMCPY(x509->pubKey.buffer, dCert->publicKey, dCert->pubKeySize); + } + else + ret = MEMORY_E; + } + + if (dCert->signature != NULL && dCert->sigLength != 0 && + dCert->sigLength <= MAX_ENCODED_SIG_SZ) { + x509->sig.buffer = (byte*)XMALLOC( + dCert->sigLength, x509->heap, DYNAMIC_TYPE_SIGNATURE); + if (x509->sig.buffer == NULL) { + ret = MEMORY_E; + } + else { + XMEMCPY(x509->sig.buffer, dCert->signature, dCert->sigLength); + x509->sig.length = dCert->sigLength; + x509->sigOID = dCert->signatureOID; + } + } + + /* store cert for potential retrieval */ + if (AllocDer(&x509->derCert, dCert->maxIdx, CERT_TYPE, x509->heap) == 0) { + XMEMCPY(x509->derCert->buffer, dCert->source, dCert->maxIdx); + } + else { + ret = MEMORY_E; + } + + x509->altNames = dCert->altNames; + dCert->weOwnAltNames = 0; + x509->altNamesNext = x509->altNames; /* index hint */ + +#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \ + !defined(IGNORE_NAME_CONSTRAINTS) + /* add copies of alternate emails from dCert to X509 */ + if (dCert->altEmailNames != NULL) { + DNS_entry* cur = dCert->altEmailNames; + + while (cur != NULL) { + if (cur->type == ASN_RFC822_TYPE) { + DNS_entry* dnsEntry; + int strLen = cur->len; + + dnsEntry = (DNS_entry*)XMALLOC(sizeof(DNS_entry), x509->heap, + DYNAMIC_TYPE_ALTNAME); + if (dnsEntry == NULL) { + WOLFSSL_MSG("\tOut of Memory"); + return MEMORY_E; + } + + dnsEntry->type = ASN_RFC822_TYPE; + dnsEntry->name = (char*)XMALLOC(strLen + 1, x509->heap, + DYNAMIC_TYPE_ALTNAME); + if (dnsEntry->name == NULL) { + WOLFSSL_MSG("\tOut of Memory"); + XFREE(dnsEntry, x509->heap, DYNAMIC_TYPE_ALTNAME); + return MEMORY_E; + } + dnsEntry->len = strLen; + XMEMCPY(dnsEntry->name, cur->name, strLen); + dnsEntry->name[strLen] = '\0'; + + dnsEntry->next = x509->altNames; + x509->altNames = dnsEntry; + } + cur = cur->next; + } + } +#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ + + x509->isCa = dCert->isCA; +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + x509->pathLength = dCert->pathLength; + x509->keyUsage = dCert->extKeyUsage; + + x509->CRLdistSet = dCert->extCRLdistSet; + x509->CRLdistCrit = dCert->extCRLdistCrit; + x509->CRLInfo = dCert->extCrlInfo; + x509->CRLInfoSz = dCert->extCrlInfoSz; + x509->authInfoSet = dCert->extAuthInfoSet; + x509->authInfoCrit = dCert->extAuthInfoCrit; + if (dCert->extAuthInfo != NULL && dCert->extAuthInfoSz > 0) { + x509->authInfo = (byte*)XMALLOC(dCert->extAuthInfoSz, x509->heap, + DYNAMIC_TYPE_X509_EXT); + if (x509->authInfo != NULL) { + XMEMCPY(x509->authInfo, dCert->extAuthInfo, dCert->extAuthInfoSz); + x509->authInfoSz = dCert->extAuthInfoSz; + } + else { + ret = MEMORY_E; + } + } + x509->basicConstSet = dCert->extBasicConstSet; + x509->basicConstCrit = dCert->extBasicConstCrit; + x509->basicConstPlSet = dCert->pathLengthSet; + x509->subjAltNameSet = dCert->extSubjAltNameSet; + x509->subjAltNameCrit = dCert->extSubjAltNameCrit; + x509->authKeyIdSet = dCert->extAuthKeyIdSet; + x509->authKeyIdCrit = dCert->extAuthKeyIdCrit; + if (dCert->extAuthKeyIdSrc != NULL && dCert->extAuthKeyIdSz != 0) { + x509->authKeyId = (byte*)XMALLOC(dCert->extAuthKeyIdSz, x509->heap, + DYNAMIC_TYPE_X509_EXT); + if (x509->authKeyId != NULL) { + XMEMCPY(x509->authKeyId, + dCert->extAuthKeyIdSrc, dCert->extAuthKeyIdSz); + x509->authKeyIdSz = dCert->extAuthKeyIdSz; + } + else + ret = MEMORY_E; + } + x509->subjKeyIdSet = dCert->extSubjKeyIdSet; + x509->subjKeyIdCrit = dCert->extSubjKeyIdCrit; + if (dCert->extSubjKeyIdSrc != NULL && dCert->extSubjKeyIdSz != 0) { + x509->subjKeyId = (byte*)XMALLOC(dCert->extSubjKeyIdSz, x509->heap, + DYNAMIC_TYPE_X509_EXT); + if (x509->subjKeyId != NULL) { + XMEMCPY(x509->subjKeyId, + dCert->extSubjKeyIdSrc, dCert->extSubjKeyIdSz); + x509->subjKeyIdSz = dCert->extSubjKeyIdSz; + } + else + ret = MEMORY_E; + } + x509->keyUsageSet = dCert->extKeyUsageSet; + x509->keyUsageCrit = dCert->extKeyUsageCrit; + if (dCert->extExtKeyUsageSrc != NULL && dCert->extExtKeyUsageSz > 0) { + x509->extKeyUsageSrc = (byte*)XMALLOC(dCert->extExtKeyUsageSz, + x509->heap, DYNAMIC_TYPE_X509_EXT); + if (x509->extKeyUsageSrc != NULL) { + XMEMCPY(x509->extKeyUsageSrc, dCert->extExtKeyUsageSrc, + dCert->extExtKeyUsageSz); + x509->extKeyUsageSz = dCert->extExtKeyUsageSz; + x509->extKeyUsageCrit = dCert->extExtKeyUsageCrit; + x509->extKeyUsageCount = dCert->extExtKeyUsageCount; + } + else { + ret = MEMORY_E; + } + } + #ifdef WOLFSSL_SEP + x509->certPolicySet = dCert->extCertPolicySet; + x509->certPolicyCrit = dCert->extCertPolicyCrit; + #endif /* WOLFSSL_SEP */ + #ifdef WOLFSSL_CERT_EXT + { + int i; + for (i = 0; i < dCert->extCertPoliciesNb && i < MAX_CERTPOL_NB; i++) + XMEMCPY(x509->certPolicies[i], dCert->extCertPolicies[i], + MAX_CERTPOL_SZ); + x509->certPoliciesNb = dCert->extCertPoliciesNb; + } + #endif /* WOLFSSL_CERT_EXT */ +#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ +#if defined(HAVE_ECC) || defined(HAVE_ED25519) + x509->pkCurveOID = dCert->pkCurveOID; +#endif /* HAVE_ECC */ + + return ret; +} + +#endif /* KEEP_PEER_CERT || SESSION_CERTS */ + +#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \ + (defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) && !defined(WOLFSSL_NO_TLS12)) +static int ProcessCSR(WOLFSSL* ssl, byte* input, word32* inOutIdx, + word32 status_length) +{ + int ret = 0; + OcspRequest* request; + + #ifdef WOLFSSL_SMALL_STACK + CertStatus* status; + OcspResponse* response; + #else + CertStatus status[1]; + OcspResponse response[1]; + #endif + + do { + #ifdef HAVE_CERTIFICATE_STATUS_REQUEST + if (ssl->status_request) { + request = (OcspRequest*)TLSX_CSR_GetRequest(ssl->extensions); + ssl->status_request = 0; + break; + } + #endif + + #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + if (ssl->status_request_v2) { + request = (OcspRequest*)TLSX_CSR2_GetRequest(ssl->extensions, + WOLFSSL_CSR2_OCSP, 0); + ssl->status_request_v2 = 0; + break; + } + #endif + + return BUFFER_ERROR; + } while(0); + + if (request == NULL) + return BAD_CERTIFICATE_STATUS_ERROR; /* not expected */ + + #ifdef WOLFSSL_SMALL_STACK + status = (CertStatus*)XMALLOC(sizeof(CertStatus), ssl->heap, + DYNAMIC_TYPE_OCSP_STATUS); + response = (OcspResponse*)XMALLOC(sizeof(OcspResponse), ssl->heap, + DYNAMIC_TYPE_OCSP_REQUEST); + + if (status == NULL || response == NULL) { + if (status) + XFREE(status, NULL, DYNAMIC_TYPE_OCSP_STATUS); + if (response) + XFREE(response, NULL, DYNAMIC_TYPE_OCSP_REQUEST); + + return MEMORY_ERROR; + } + #endif + + InitOcspResponse(response, status, input +*inOutIdx, status_length); + + if (OcspResponseDecode(response, ssl->ctx->cm, ssl->heap, 0) != 0) + ret = BAD_CERTIFICATE_STATUS_ERROR; + else if (CompareOcspReqResp(request, response) != 0) + ret = BAD_CERTIFICATE_STATUS_ERROR; + else if (response->responseStatus != OCSP_SUCCESSFUL) + ret = BAD_CERTIFICATE_STATUS_ERROR; + else if (response->status->status == CERT_REVOKED) + ret = OCSP_CERT_REVOKED; + else if (response->status->status != CERT_GOOD) + ret = BAD_CERTIFICATE_STATUS_ERROR; + + *inOutIdx += status_length; + + #ifdef WOLFSSL_SMALL_STACK + XFREE(status, ssl->heap, DYNAMIC_TYPE_OCSP_STATUS); + XFREE(response, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); + #endif + + return ret; +} +#endif + + + +#ifdef HAVE_PK_CALLBACKS + +#ifdef HAVE_ECC + static int SigPkCbEccVerify(const unsigned char* sig, unsigned int sigSz, + const unsigned char* hash, unsigned int hashSz, + const unsigned char* keyDer, unsigned int keySz, + int* result, void* ctx) + { + int ret = NOT_COMPILED_IN; + WOLFSSL* ssl = (WOLFSSL*)ctx; + + if (ssl && ssl->ctx->EccVerifyCb) { + ret = ssl->ctx->EccVerifyCb(ssl, sig, sigSz, hash, hashSz, + keyDer, keySz, result, ssl->EccVerifyCtx); + } + return ret; + } +#endif +#ifndef NO_RSA + static int SigPkCbRsaVerify(unsigned char* sig, unsigned int sigSz, + unsigned char** out, const unsigned char* keyDer, unsigned int keySz, + void* ctx) + { + int ret = NOT_COMPILED_IN; + WOLFSSL* ssl = (WOLFSSL*)ctx; + + if (ssl && ssl->ctx->RsaVerifyCb) { + ret = ssl->ctx->RsaVerifyCb(ssl, sig, sigSz, out, keyDer, keySz, + ssl->RsaVerifyCtx); + } + return ret; + } +#endif + +int InitSigPkCb(WOLFSSL* ssl, SignatureCtx* sigCtx) +{ + if (ssl == NULL || sigCtx == NULL) + return BAD_FUNC_ARG; + + /* only setup the verify callback if a PK is set */ +#ifdef HAVE_ECC + if (ssl->ctx->EccVerifyCb) { + sigCtx->pkCbEcc = SigPkCbEccVerify; + sigCtx->pkCtxEcc = ssl; + } +#endif +#ifndef NO_RSA + /* only setup the verify callback if a PK is set */ + if (ssl->ctx->RsaVerifyCb) { + sigCtx->pkCbRsa = SigPkCbRsaVerify; + sigCtx->pkCtxRsa = ssl; + } +#endif + + return 0; +} + +#endif /* HAVE_PK_CALLBACKS */ + + +#if !defined(NO_WOLFSSL_CLIENT) || !defined(WOLFSSL_NO_CLIENT_AUTH) +typedef struct ProcPeerCertArgs { + buffer* certs; +#ifdef WOLFSSL_TLS13 + buffer* exts; /* extensions */ +#endif + DecodedCert* dCert; + word32 idx; + word32 begin; + int totalCerts; /* number of certs in certs buffer */ + int count; + int certIdx; + int lastErr; +#ifdef WOLFSSL_TLS13 + byte ctxSz; +#endif +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + char untrustedDepth; +#endif + word16 fatal:1; + word16 verifyErr:1; + word16 dCertInit:1; +#ifdef WOLFSSL_TRUST_PEER_CERT + word16 haveTrustPeer:1; /* was cert verified by loaded trusted peer cert */ +#endif +} ProcPeerCertArgs; + +/* WOLFSSL_ALWAYS_VERIFY_CB: Use verify callback for success or failure cases */ +/* WOLFSSL_VERIFY_CB_ALL_CERTS: Issue callback for all intermediate certificates */ + +/* Callback is issued for certificate presented in TLS Certificate (11) packet. + * The intermediates are done first then peer leaf cert last. Use the + * store->error_depth member to determine index (0=peer, >1 intermediates) + */ + +static int DoVerifyCallback(WOLFSSL* ssl, int ret, ProcPeerCertArgs* args) +{ + int verify_ok = 0, alertWhy = 0, use_cb = 0; + + /* Determine return code and alert reason */ + if (ret != 0) { + alertWhy = bad_certificate; + if (ret == ASN_AFTER_DATE_E || + ret == ASN_BEFORE_DATE_E) { + alertWhy = certificate_expired; + } + } + else { + verify_ok = 1; + } + + /* Determine if verify callback should be used */ + if (ret != 0) { + if (!ssl->options.verifyNone) { + use_cb = 1; /* always report errors */ + } + } +#ifdef WOLFSSL_ALWAYS_VERIFY_CB + /* always use verify callback on peer leaf cert */ + if (args->certIdx == 0) { + use_cb = 1; + } +#endif +#ifdef WOLFSSL_VERIFY_CB_ALL_CERTS + /* perform verify callback on other intermediate certs (not just peer) */ + if (args->certIdx > 0) { + use_cb = 1; + } +#endif + + /* if verify callback has been set */ + if (use_cb && ssl->verifyCallback) { + #ifdef WOLFSSL_SMALL_STACK + WOLFSSL_X509_STORE_CTX* store; + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + WOLFSSL_X509* x509; + #endif + char* domain = NULL; + #else + WOLFSSL_X509_STORE_CTX store[1]; + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + WOLFSSL_X509 x509[1]; + #endif + char domain[ASN_NAME_MAX]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + store = (WOLFSSL_X509_STORE_CTX*)XMALLOC( + sizeof(WOLFSSL_X509_STORE_CTX), ssl->heap, DYNAMIC_TYPE_X509_STORE); + if (store == NULL) { + return MEMORY_E; + } + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), ssl->heap, + DYNAMIC_TYPE_X509); + if (x509 == NULL) { + XFREE(store, ssl->heap, DYNAMIC_TYPE_X509); + return MEMORY_E; + } + #endif + domain = (char*)XMALLOC(ASN_NAME_MAX, ssl->heap, DYNAMIC_TYPE_STRING); + if (domain == NULL) { + XFREE(store, ssl->heap, DYNAMIC_TYPE_X509); + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + XFREE(x509, ssl->heap, DYNAMIC_TYPE_X509); + #endif + return MEMORY_E; + } + #endif /* WOLFSSL_SMALL_STACK */ + + XMEMSET(store, 0, sizeof(WOLFSSL_X509_STORE_CTX)); + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + XMEMSET(x509, 0, sizeof(WOLFSSL_X509)); + #endif + domain[0] = '\0'; + + /* build subject CN as string to return in store */ + if (args->dCertInit && args->dCert && args->dCert->subjectCN) { + int subjectCNLen = args->dCert->subjectCNLen; + if (subjectCNLen > ASN_NAME_MAX-1) + subjectCNLen = ASN_NAME_MAX-1; + if (subjectCNLen > 0) { + XMEMCPY(domain, args->dCert->subjectCN, subjectCNLen); + domain[subjectCNLen] = '\0'; + } + } + + store->error = ret; + store->error_depth = args->certIdx; + store->discardSessionCerts = 0; + store->domain = domain; + store->userCtx = ssl->verifyCbCtx; + store->certs = args->certs; + store->totalCerts = args->totalCerts; + store->ex_data = ssl; + + #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + if (ssl->ctx->x509_store_pt != NULL) { + store->store = ssl->ctx->x509_store_pt; + } + else { + store->store = &ssl->ctx->x509_store; + } + #endif + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + #ifdef KEEP_PEER_CERT + if (args->certIdx == 0) { + store->current_cert = &ssl->peerCert; /* use existing X509 */ + } + else + #endif + { + InitX509(x509, 0, ssl->heap); + if (CopyDecodedToX509(x509, args->dCert) == 0) { + store->current_cert = x509; + } + else { + FreeX509(x509); + } + } + #endif + #ifdef SESSION_CERTS + store->sesChain = &ssl->session.chain; + #endif + /* non-zero return code indicates failure override */ + if (ssl->verifyCallback(verify_ok, store)) { + if (ret != 0) { + WOLFSSL_MSG("Verify callback overriding error!"); + ret = 0; + } + } + else { + /* induce error if one not present */ + if (ret == 0) { + ret = VERIFY_CERT_ERROR; + } + + /* mark as verify error */ + args->verifyErr = 1; + } + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + if (args->certIdx > 0) + FreeX509(x509); + #endif + #if defined(SESSION_CERTS) && defined(OPENSSL_EXTRA) + wolfSSL_sk_X509_free(store->chain); + store->chain = NULL; + #endif + #ifdef SESSION_CERTS + if (store->discardSessionCerts) { + WOLFSSL_MSG("Verify callback requested discard sess certs"); + ssl->session.chain.count = 0; + #ifdef WOLFSSL_ALT_CERT_CHAINS + ssl->session.altChain.count = 0; + #endif + } + #endif /* SESSION_CERTS */ + #ifdef WOLFSSL_SMALL_STACK + XFREE(domain, ssl->heap, DYNAMIC_TYPE_STRING); + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + XFREE(x509, ssl->heap, DYNAMIC_TYPE_X509); + #endif + XFREE(store, ssl->heap, DYNAMIC_TYPE_X509_STORE); + #endif + } + + if (ret != 0) { + if (!ssl->options.verifyNone) { + /* handle failure */ + SendAlert(ssl, alert_fatal, alertWhy); /* try to send */ + ssl->options.isClosed = 1; + } + + /* Report SSL error */ + ssl->error = ret; + } + + return ret; +} + +static void FreeProcPeerCertArgs(WOLFSSL* ssl, void* pArgs) +{ + ProcPeerCertArgs* args = (ProcPeerCertArgs*)pArgs; + + (void)ssl; + + if (args->certs) { + XFREE(args->certs, ssl->heap, DYNAMIC_TYPE_DER); + args->certs = NULL; + } +#ifdef WOLFSSL_TLS13 + if (args->exts) { + XFREE(args->exts, ssl->heap, DYNAMIC_TYPE_CERT_EXT); + args->exts = NULL; + } +#endif + if (args->dCert) { + if (args->dCertInit) { + FreeDecodedCert(args->dCert); + args->dCertInit = 0; + } + XFREE(args->dCert, ssl->heap, DYNAMIC_TYPE_DCERT); + args->dCert = NULL; + } +} + +static int ProcessPeerCertParse(WOLFSSL* ssl, ProcPeerCertArgs* args, + int certType, int verify, byte** pSubjectHash, int* pAlreadySigner) +{ + int ret = 0; + buffer* cert; + byte* subjectHash = NULL; + int alreadySigner = 0; +#ifdef WOLFSSL_SMALL_CERT_VERIFY + int sigRet = 0; +#endif + + if (ssl == NULL || args == NULL) + return BAD_FUNC_ARG; + + /* check to make sure certificate index is valid */ + if (args->certIdx > args->count) + return BUFFER_E; + + /* check if returning from non-blocking OCSP */ + /* skip this section because cert is already initialized and parsed */ +#ifdef WOLFSSL_NONBLOCK_OCSP + if (args->lastErr == OCSP_WANT_READ) { + args->lastErr = 0; /* clear error */ + return 0; + } +#endif + +#ifdef WOLFSSL_TRUST_PEER_CERT + /* we have trusted peer */ + if (args->haveTrustPeer) { + return 0; + } +#endif + + /* get certificate buffer */ + cert = &args->certs[args->certIdx]; + +#ifdef WOLFSSL_SMALL_CERT_VERIFY + if (verify == VERIFY) { + /* for small cert verify, release decoded cert during signature check to + reduce peak memory usage */ + if (args->dCert != NULL) { + if (args->dCertInit) { + FreeDecodedCert(args->dCert); + args->dCertInit = 0; + } + XFREE(args->dCert, ssl->heap, DYNAMIC_TYPE_DCERT); + args->dCert = NULL; + } + + /* perform cert parsing and signature check */ + sigRet = CheckCertSignature(cert->buffer, cert->length, + ssl->heap, ssl->ctx->cm); + /* fail on errors here after the ParseCertRelative call, so dCert is populated */ + + /* verify name only in ParseCertRelative below, signature check done */ + verify = VERIFY_NAME; + } +#endif /* WOLFSSL_SMALL_CERT_VERIFY */ + + /* make sure the decoded cert structure is allocated and initialized */ + if (!args->dCertInit + #ifdef WOLFSSL_SMALL_CERT_VERIFY + || args->dCert == NULL + #endif + ) { + #ifdef WOLFSSL_SMALL_CERT_VERIFY + if (args->dCert == NULL) { + args->dCert = (DecodedCert*)XMALLOC( + sizeof(DecodedCert), ssl->heap, + DYNAMIC_TYPE_DCERT); + if (args->dCert == NULL) { + return MEMORY_E; + } + } + #endif + + InitDecodedCert(args->dCert, cert->buffer, cert->length, ssl->heap); + + args->dCertInit = 1; + args->dCert->sigCtx.devId = ssl->devId; + #ifdef WOLFSSL_ASYNC_CRYPT + args->dCert->sigCtx.asyncCtx = ssl; + #endif + + #ifdef HAVE_PK_CALLBACKS + /* setup the PK callback context */ + ret = InitSigPkCb(ssl, &args->dCert->sigCtx); + if (ret != 0) + return ret; + #endif + } + + /* Parse Certificate */ + ret = ParseCertRelative(args->dCert, certType, verify, ssl->ctx->cm); + if (ret == 0) { + /* get subject and determine if already loaded */ + #ifndef NO_SKID + if (args->dCert->extAuthKeyIdSet) + subjectHash = args->dCert->extSubjKeyId; + else + #endif + subjectHash = args->dCert->subjectHash; + alreadySigner = AlreadySigner(ssl->ctx->cm, subjectHash); + } + +#ifdef WOLFSSL_SMALL_CERT_VERIFY + /* get signature check failures from above */ + if (ret == 0) + ret = sigRet; +#endif + + if (pSubjectHash) + *pSubjectHash = subjectHash; + if (pAlreadySigner) + *pAlreadySigner = alreadySigner; + +#ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, + args->dCert->sigCtx.asyncDev); + } +#endif + + return ret; +} + +/* Check key sizes for certs. Is redundant check since + ProcessBuffer also performs this check. */ +static int ProcessPeerCertCheckKey(WOLFSSL* ssl, ProcPeerCertArgs* args) +{ + int ret = 0; + + if (ssl->options.verifyNone) { + return ret; + } + + switch (args->dCert->keyOID) { + #ifndef NO_RSA + case RSAk: + if (ssl->options.minRsaKeySz < 0 || + args->dCert->pubKeySize < + (word16)ssl->options.minRsaKeySz) { + WOLFSSL_MSG( + "RSA key size in cert chain error"); + ret = RSA_KEY_SIZE_E; + } + break; + #endif /* !NO_RSA */ + #ifdef HAVE_ECC + case ECDSAk: + if (ssl->options.minEccKeySz < 0 || + args->dCert->pubKeySize < + (word16)ssl->options.minEccKeySz) { + WOLFSSL_MSG( + "ECC key size in cert chain error"); + ret = ECC_KEY_SIZE_E; + } + break; + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ED25519k: + if (ssl->options.minEccKeySz < 0 || + ED25519_KEY_SIZE < + (word16)ssl->options.minEccKeySz) { + WOLFSSL_MSG( + "ECC key size in cert chain error"); + ret = ECC_KEY_SIZE_E; + } + break; + #endif /* HAVE_ED25519 */ + default: + WOLFSSL_MSG("Key size not checked"); + /* key not being checked for size if not in + switch */ + break; + } + + return ret; +} + +int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, + word32 totalSz) +{ + int ret = 0; +#ifdef WOLFSSL_ASYNC_CRYPT + ProcPeerCertArgs* args = (ProcPeerCertArgs*)ssl->async.args; + typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1]; + (void)sizeof(args_test); +#elif defined(WOLFSSL_NONBLOCK_OCSP) + ProcPeerCertArgs* args = ssl->nonblockarg; +#elif defined(WOLFSSL_SMALL_STACK) + ProcPeerCertArgs* args = NULL; +#else + ProcPeerCertArgs args[1]; +#endif + byte* subjectHash = NULL; + int alreadySigner = 0; + + WOLFSSL_ENTER("ProcessPeerCerts"); + +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); + if (ret != WC_NOT_PENDING_E) { + /* Check for error */ + if (ret < 0) + goto exit_ppc; + } + else +#elif defined(WOLFSSL_NONBLOCK_OCSP) + if (args == NULL) { + args = (ProcPeerCertArgs*)XMALLOC( + sizeof(ProcPeerCertArgs), ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (args == NULL) { + ERROR_OUT(MEMORY_E, exit_ppc); + } + } + if (ssl->nonblockarg == NULL) /* new args */ +#elif defined(WOLFSSL_SMALL_STACK) + args = (ProcPeerCertArgs*)XMALLOC( + sizeof(ProcPeerCertArgs), ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (args == NULL) { + ERROR_OUT(MEMORY_E, exit_ppc); + } +#endif + { + /* Reset state */ + ret = 0; + ssl->options.asyncState = TLS_ASYNC_BEGIN; + XMEMSET(args, 0, sizeof(ProcPeerCertArgs)); + args->idx = *inOutIdx; + args->begin = *inOutIdx; + #ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = FreeProcPeerCertArgs; + #elif defined(WOLFSSL_NONBLOCK_OCSP) + ssl->nonblockarg = args; + #endif + } + + switch (ssl->options.asyncState) + { + case TLS_ASYNC_BEGIN: + { + word32 listSz; + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName(ssl, "Certificate"); + if (ssl->toInfoOn) + AddLateName("Certificate", &ssl->timeoutInfo); + #endif + + #ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) { + byte ctxSz; + + /* Certificate Request Context */ + if ((args->idx - args->begin) + OPAQUE8_LEN > totalSz) + return BUFFER_ERROR; + ctxSz = *(input + args->idx); + args->idx++; + if ((args->idx - args->begin) + ctxSz > totalSz) + return BUFFER_ERROR; + #ifndef NO_WOLFSSL_CLIENT + /* Must be empty when received from server. */ + if (ssl->options.side == WOLFSSL_CLIENT_END) { + if (ctxSz != 0) { + return INVALID_CERT_CTX_E; + } + } + #endif + #ifndef NO_WOLFSSL_SERVER + /* Must contain value sent in request. */ + if (ssl->options.side == WOLFSSL_SERVER_END) { + if (ssl->options.handShakeState != HANDSHAKE_DONE && + ctxSz != 0) { + return INVALID_CERT_CTX_E; + } + else if (ssl->options.handShakeState == HANDSHAKE_DONE) { + #ifdef WOLFSSL_POST_HANDSHAKE_AUTH + CertReqCtx* curr = ssl->certReqCtx; + CertReqCtx* prev = NULL; + while (curr != NULL) { + if ((ctxSz == curr->len) && + XMEMCMP(&curr->ctx, input + args->idx, ctxSz) + == 0) { + if (prev != NULL) + prev->next = curr->next; + else + ssl->certReqCtx = curr->next; + XFREE(curr, ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + break; + } + prev = curr; + curr = curr->next; + } + if (curr == NULL) + #endif + return INVALID_CERT_CTX_E; + } + } + #endif + args->idx += ctxSz; + + /* allocate buffer for cert extensions */ + args->exts = (buffer*)XMALLOC(sizeof(buffer) * MAX_CHAIN_DEPTH, + ssl->heap, DYNAMIC_TYPE_CERT_EXT); + if (args->exts == NULL) { + ERROR_OUT(MEMORY_E, exit_ppc); + } + } + #endif + + /* allocate buffer for certs */ + #ifdef OPENSSL_EXTRA + args->certs = (buffer*)XMALLOC(sizeof(buffer) * + (ssl->verifyDepth + 1), ssl->heap, DYNAMIC_TYPE_DER); + if (args->certs == NULL) { + ERROR_OUT(MEMORY_E, exit_ppc); + } + XMEMSET(args->certs, 0, sizeof(buffer) * (ssl->verifyDepth + 1)); + #else + args->certs = (buffer*)XMALLOC(sizeof(buffer) * MAX_CHAIN_DEPTH, + ssl->heap, DYNAMIC_TYPE_DER); + if (args->certs == NULL) { + ERROR_OUT(MEMORY_E, exit_ppc); + } + XMEMSET(args->certs, 0, sizeof(buffer) * MAX_CHAIN_DEPTH); + #endif /* OPENSSL_EXTRA */ + + /* Certificate List */ + if ((args->idx - args->begin) + OPAQUE24_LEN > totalSz) { + ERROR_OUT(BUFFER_ERROR, exit_ppc); + } + c24to32(input + args->idx, &listSz); + args->idx += OPAQUE24_LEN; + if (listSz > MAX_CERTIFICATE_SZ) { + ERROR_OUT(BUFFER_ERROR, exit_ppc); + } + if ((args->idx - args->begin) + listSz != totalSz) { + ERROR_OUT(BUFFER_ERROR, exit_ppc); + } + + WOLFSSL_MSG("Loading peer's cert chain"); + /* first put cert chain into buffer so can verify top down + we're sent bottom up */ + while (listSz) { + word32 certSz; + + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + if (args->totalCerts > ssl->verifyDepth) { + ssl->peerVerifyRet = X509_V_ERR_CERT_CHAIN_TOO_LONG; + ERROR_OUT(MAX_CHAIN_ERROR, exit_ppc); + } + #else + if (args->totalCerts >= ssl->verifyDepth || + args->totalCerts >= MAX_CHAIN_DEPTH) { + ERROR_OUT(MAX_CHAIN_ERROR, exit_ppc); + } + #endif + + if ((args->idx - args->begin) + OPAQUE24_LEN > totalSz) { + ERROR_OUT(BUFFER_ERROR, exit_ppc); + } + + c24to32(input + args->idx, &certSz); + args->idx += OPAQUE24_LEN; + + if ((args->idx - args->begin) + certSz > totalSz) { + ERROR_OUT(BUFFER_ERROR, exit_ppc); + } + + args->certs[args->totalCerts].length = certSz; + args->certs[args->totalCerts].buffer = input + args->idx; + + #ifdef SESSION_CERTS + AddSessionCertToChain(&ssl->session.chain, + input + args->idx, certSz); + #endif /* SESSION_CERTS */ + + args->idx += certSz; + listSz -= certSz + CERT_HEADER_SZ; + + #ifdef WOLFSSL_TLS13 + /* Extensions */ + if (ssl->options.tls1_3) { + word16 extSz; + + if ((args->idx - args->begin) + OPAQUE16_LEN > totalSz) + return BUFFER_ERROR; + ato16(input + args->idx, &extSz); + args->idx += OPAQUE16_LEN; + if ((args->idx - args->begin) + extSz > totalSz) + return BUFFER_ERROR; + /* Store extension data info for later processing. */ + args->exts[args->totalCerts].length = extSz; + args->exts[args->totalCerts].buffer = input + args->idx; + args->idx += extSz; + listSz -= extSz + OPAQUE16_LEN; + ret = TLSX_Parse(ssl, args->exts[args->totalCerts].buffer, + args->exts[args->totalCerts].length, certificate, NULL); + if (ret < 0) + return ret; + } + #endif + + args->totalCerts++; + WOLFSSL_MSG("\tPut another cert into chain"); + } /* while (listSz) */ + + args->count = args->totalCerts; + args->certIdx = 0; /* select peer cert (first one) */ + + args->dCertInit = 0; + #ifndef WOLFSSL_SMALL_CERT_VERIFY + args->dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), ssl->heap, + DYNAMIC_TYPE_DCERT); + if (args->dCert == NULL) { + ERROR_OUT(MEMORY_E, exit_ppc); + } + XMEMSET(args->dCert, 0, sizeof(DecodedCert)); + #endif + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_BUILD; + } /* case TLS_ASYNC_BEGIN */ + FALL_THROUGH; + + case TLS_ASYNC_BUILD: + { + if (args->count > 0) { + + /* check for trusted peer and get untrustedDepth */ + #if defined(WOLFSSL_TRUST_PEER_CERT) || defined(OPENSSL_EXTRA) + if (args->certIdx == 0) { + #ifdef WOLFSSL_TRUST_PEER_CERT + TrustedPeerCert* tp; + int matchType = WC_MATCH_NAME; + #endif + + ret = ProcessPeerCertParse(ssl, args, CERT_TYPE, NO_VERIFY, + &subjectHash, &alreadySigner); + if (ret != 0) + goto exit_ppc; + + #ifdef OPENSSL_EXTRA + /* Determine untrusted depth */ + if (!alreadySigner) { + args->untrustedDepth = 1; + } + #endif + + #ifdef WOLFSSL_TRUST_PEER_CERT + #ifndef NO_SKID + if (args->dCert->extAuthKeyIdSet) + matchType = WC_MATCH_SKID; + #endif + tp = GetTrustedPeer(ssl->ctx->cm, subjectHash, matchType); + WOLFSSL_MSG("Checking for trusted peer cert"); + + if (tp && MatchTrustedPeer(tp, args->dCert)) { + WOLFSSL_MSG("Found matching trusted peer cert"); + args->haveTrustPeer = 1; + } + else if (tp == NULL) { + /* no trusted peer cert */ + WOLFSSL_MSG("No matching trusted peer cert. Checking CAs"); + } + else { + WOLFSSL_MSG("Trusted peer cert did not match!"); + } + if (!args->haveTrustPeer) + #endif + { + /* free cert if not trusted peer */ + FreeDecodedCert(args->dCert); + args->dCertInit = 0; + } + } + #endif /* WOLFSSL_TRUST_PEER_CERT || OPENSSL_EXTRA */ + + /* check certificate up to peer's first */ + /* do not verify chain if trusted peer cert found */ + while (args->count > 1 + #ifdef WOLFSSL_TRUST_PEER_CERT + && !args->haveTrustPeer + #endif /* WOLFSSL_TRUST_PEER_CERT */ + ) { + /* select last certificate */ + args->certIdx = args->count - 1; + + ret = ProcessPeerCertParse(ssl, args, CERT_TYPE, + !ssl->options.verifyNone ? VERIFY : NO_VERIFY, + &subjectHash, &alreadySigner); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) + goto exit_ppc; + #endif + if (ret == 0) { + ret = ProcessPeerCertCheckKey(ssl, args); + } + + if (ret == 0 && args->dCert->isCA == 0) { + WOLFSSL_MSG("Chain cert is not a CA, not adding as one"); + } + else if (ret == 0 && ssl->options.verifyNone) { + WOLFSSL_MSG("Chain cert not verified by option, " + "not adding as CA"); + } + else if (ret == 0) { + buffer* cert = &args->certs[args->certIdx]; + + /* Is valid CA */ + #if defined(SESSION_CERTS) && defined(WOLFSSL_ALT_CERT_CHAINS) + /* if using alternate chain, store the cert used */ + if (ssl->options.usingAltCertChain) { + AddSessionCertToChain(&ssl->session.altChain, + cert->buffer, cert->length); + } + #endif /* SESSION_CERTS && WOLFSSL_ALT_CERT_CHAINS */ + #ifdef OPENSSL_EXTRA + if (args->certIdx > args->untrustedDepth) { + args->untrustedDepth = (char)args->certIdx + 1; + } + #endif + + if (!alreadySigner) { + DerBuffer* add = NULL; + ret = AllocDer(&add, cert->length, CA_TYPE, ssl->heap); + if (ret < 0) + goto exit_ppc; + + XMEMCPY(add->buffer, cert->buffer, cert->length); + + /* CA already verified above in ParseCertRelative */ + WOLFSSL_MSG("Adding CA from chain"); + ret = AddCA(ssl->ctx->cm, &add, WOLFSSL_CHAIN_CA, 0); + if (ret == WOLFSSL_SUCCESS) { + ret = 0; + } + } + else { + WOLFSSL_MSG("Verified CA from chain and already had it"); + } + } + else { + WOLFSSL_MSG("Failed to verify CA from chain"); + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + ssl->peerVerifyRet = X509_V_ERR_INVALID_CA; + #endif + } + + #if defined(HAVE_OCSP) || defined(HAVE_CRL) + if (ret == 0) { + int doCrlLookup = 1; + #ifdef HAVE_OCSP + #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + if (ssl->status_request_v2) { + ret = TLSX_CSR2_InitRequests(ssl->extensions, + args->dCert, 0, ssl->heap); + } + else /* skips OCSP and force CRL check */ + #endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */ + if (ssl->ctx->cm->ocspEnabled && + ssl->ctx->cm->ocspCheckAll) { + WOLFSSL_MSG("Doing Non Leaf OCSP check"); + ret = CheckCertOCSP_ex(ssl->ctx->cm->ocsp, + args->dCert, NULL, ssl); + #ifdef WOLFSSL_NONBLOCK_OCSP + if (ret == OCSP_WANT_READ) { + args->lastErr = ret; + goto exit_ppc; + } + #endif + doCrlLookup = (ret == OCSP_CERT_UNKNOWN); + if (ret != 0) { + doCrlLookup = 0; + WOLFSSL_MSG("\tOCSP Lookup not ok"); + } + } + #endif /* HAVE_OCSP */ + + #ifdef HAVE_CRL + if (ret == 0 && doCrlLookup && + ssl->ctx->cm->crlEnabled && + ssl->ctx->cm->crlCheckAll) { + WOLFSSL_MSG("Doing Non Leaf CRL check"); + ret = CheckCertCRL(ssl->ctx->cm->crl, args->dCert); + #ifdef WOLFSSL_NONBLOCK_OCSP + if (ret == OCSP_WANT_READ) { + args->lastErr = ret; + goto exit_ppc; + } + #endif + if (ret != 0) { + WOLFSSL_MSG("\tCRL check not ok"); + } + } + #endif /* HAVE_CRL */ + (void)doCrlLookup; + } + #endif /* HAVE_OCSP || HAVE_CRL */ + + #ifdef WOLFSSL_ALT_CERT_CHAINS + /* For alternate cert chain, its okay for a CA cert to fail + with ASN_NO_SIGNER_E here. The "alternate" certificate + chain mode only requires that the peer certificate + validate to a trusted CA */ + if (ret != 0) { + if (ret == ASN_NO_SIGNER_E) { + if (!ssl->options.usingAltCertChain) { + WOLFSSL_MSG("Trying alternate cert chain"); + ssl->options.usingAltCertChain = 1; + } + + ret = 0; /* clear error and continue */ + } + } + #endif /* WOLFSSL_ALT_CERT_CHAINS */ + + /* Do verify callback */ + ret = DoVerifyCallback(ssl, ret, args); + + /* Handle error codes */ + if (ret != 0 && args->lastErr == 0) { + args->lastErr = ret; /* save error from last time */ + ret = 0; /* reset error */ + } + + FreeDecodedCert(args->dCert); + args->dCertInit = 0; + args->count--; + } /* while (count > 0 && !args->haveTrustPeer) */ + } /* if (count > 0) */ + + /* Check for error */ + if (ret != 0) { + goto exit_ppc; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_DO; + } /* case TLS_ASYNC_BUILD */ + FALL_THROUGH; + + case TLS_ASYNC_DO: + { + /* peer's, may not have one if blank client cert sent by TLSv1.2 */ + if (args->count > 0) { + WOLFSSL_MSG("Verifying Peer's cert"); + + /* select peer cert (first one) */ + args->certIdx = 0; + + ret = ProcessPeerCertParse(ssl, args, CERT_TYPE, + !ssl->options.verifyNone ? VERIFY : NO_VERIFY, + &subjectHash, &alreadySigner); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) + goto exit_ppc; + #endif + if (ret == 0) { + WOLFSSL_MSG("Verified Peer's cert"); + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + ssl->peerVerifyRet = X509_V_OK; + #endif + #if defined(SESSION_CERTS) && defined(WOLFSSL_ALT_CERT_CHAINS) + /* if using alternate chain, store the cert used */ + if (ssl->options.usingAltCertChain) { + buffer* cert = &args->certs[args->certIdx]; + AddSessionCertToChain(&ssl->session.altChain, + cert->buffer, cert->length); + } + #endif /* SESSION_CERTS && WOLFSSL_ALT_CERT_CHAINS */ + + /* check if fatal error */ + if (args->verifyErr) { + args->fatal = 1; + if (ret == 0) { + ret = args->lastErr; + } + } + else { + args->fatal = 0; + } + } + else if (ret == ASN_PARSE_E || ret == BUFFER_E) { + WOLFSSL_MSG("Got Peer cert ASN PARSE or BUFFER ERROR"); + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + SendAlert(ssl, alert_fatal, bad_certificate); + ssl->peerVerifyRet = X509_V_ERR_CERT_REJECTED; + #endif + args->fatal = 1; + } + else { + WOLFSSL_MSG("Failed to verify Peer's cert"); + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + ssl->peerVerifyRet = X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE; + #endif + if (ssl->verifyCallback) { + WOLFSSL_MSG( + "\tCallback override available, will continue"); + /* check if fatal error */ + args->fatal = (args->verifyErr) ? 1 : 0; + } + else { + WOLFSSL_MSG("\tNo callback override available, fatal"); + args->fatal = 1; + #ifdef OPENSSL_EXTRA + SendAlert(ssl, alert_fatal, bad_certificate); + #endif + } + } + + #ifdef HAVE_SECURE_RENEGOTIATION + if (args->fatal == 0 && !IsAtLeastTLSv1_3(ssl->version) + && ssl->secure_renegotiation + && ssl->secure_renegotiation->enabled) { + + if (IsEncryptionOn(ssl, 0)) { + /* compare against previous time */ + if (XMEMCMP(args->dCert->subjectHash, + ssl->secure_renegotiation->subject_hash, + KEYID_SIZE) != 0) { + WOLFSSL_MSG( + "Peer sent different cert during scr, fatal"); + args->fatal = 1; + ret = SCR_DIFFERENT_CERT_E; + } + } + + /* cache peer's hash */ + if (args->fatal == 0) { + XMEMCPY(ssl->secure_renegotiation->subject_hash, + args->dCert->subjectHash, KEYID_SIZE); + } + } + #endif /* HAVE_SECURE_RENEGOTIATION */ + } /* if (count > 0) */ + + /* Check for error */ + if (args->fatal && ret != 0) { + goto exit_ppc; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_VERIFY; + } /* case TLS_ASYNC_DO */ + FALL_THROUGH; + + case TLS_ASYNC_VERIFY: + { + if (args->count > 0) { + #if defined(HAVE_OCSP) || defined(HAVE_CRL) + if (args->fatal == 0) { + int doLookup = 1; + + if (ssl->options.side == WOLFSSL_CLIENT_END) { + #ifdef HAVE_CERTIFICATE_STATUS_REQUEST + if (ssl->status_request) { + args->fatal = TLSX_CSR_InitRequest(ssl->extensions, + args->dCert, ssl->heap); + doLookup = 0; + #ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) { + TLSX* ext = TLSX_Find(ssl->extensions, + TLSX_STATUS_REQUEST); + if (ext != NULL) { + word32 idx = 0; + CertificateStatusRequest* csr = + (CertificateStatusRequest*)ext->data; + ret = ProcessCSR(ssl, csr->response.buffer, + &idx, csr->response.length); + if (ret < 0) + goto exit_ppc; + } + } + #endif + } + #endif /* HAVE_CERTIFICATE_STATUS_REQUEST */ + #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + if (ssl->status_request_v2) { + args->fatal = TLSX_CSR2_InitRequests(ssl->extensions, + args->dCert, 1, ssl->heap); + doLookup = 0; + } + #endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */ + } + + #ifdef HAVE_OCSP + if (doLookup && ssl->ctx->cm->ocspEnabled) { + WOLFSSL_MSG("Doing Leaf OCSP check"); + ret = CheckCertOCSP_ex(ssl->ctx->cm->ocsp, + args->dCert, NULL, ssl); + #ifdef WOLFSSL_NONBLOCK_OCSP + if (ret == OCSP_WANT_READ) { + goto exit_ppc; + } + #endif + doLookup = (ret == OCSP_CERT_UNKNOWN); + if (ret != 0) { + WOLFSSL_MSG("\tOCSP Lookup not ok"); + args->fatal = 0; + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + ssl->peerVerifyRet = X509_V_ERR_CERT_REJECTED; + #endif + } + } + #endif /* HAVE_OCSP */ + + #ifdef HAVE_CRL + if (doLookup && ssl->ctx->cm->crlEnabled) { + WOLFSSL_MSG("Doing Leaf CRL check"); + ret = CheckCertCRL(ssl->ctx->cm->crl, args->dCert); + #ifdef WOLFSSL_NONBLOCK_OCSP + if (ret == OCSP_WANT_READ) { + goto exit_ppc; + } + #endif + if (ret != 0) { + WOLFSSL_MSG("\tCRL check not ok"); + args->fatal = 0; + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + ssl->peerVerifyRet = X509_V_ERR_CERT_REJECTED; + #endif + } + } + #endif /* HAVE_CRL */ + (void)doLookup; + } + #endif /* HAVE_OCSP || HAVE_CRL */ + + #ifdef KEEP_PEER_CERT + if (args->fatal == 0) { + /* set X509 format for peer cert */ + int copyRet = CopyDecodedToX509(&ssl->peerCert, + args->dCert); + if (copyRet == MEMORY_E) { + args->fatal = 1; + } + } + #endif /* KEEP_PEER_CERT */ + + #ifndef IGNORE_KEY_EXTENSIONS + #if defined(OPENSSL_EXTRA) + /* when compatibility layer is turned on and no verify is + * set then ignore the certificate key extension */ + if (args->dCert->extKeyUsageSet && + args->dCert->extKeyUsageCrit == 0 && + ssl->options.verifyNone) { + WOLFSSL_MSG("Not verifying certificate key usage"); + } + else + #endif + if (args->dCert->extKeyUsageSet) { + if ((ssl->specs.kea == rsa_kea) && + (ssl->options.side == WOLFSSL_CLIENT_END) && + (args->dCert->extKeyUsage & KEYUSE_KEY_ENCIPHER) == 0) { + ret = KEYUSE_ENCIPHER_E; + } + if ((ssl->specs.sig_algo == rsa_sa_algo || + (ssl->specs.sig_algo == ecc_dsa_sa_algo && + !ssl->specs.static_ecdh)) && + (args->dCert->extKeyUsage & KEYUSE_DIGITAL_SIG) == 0) { + WOLFSSL_MSG("KeyUse Digital Sig not set"); + ret = KEYUSE_SIGNATURE_E; + } + } + + #if defined(OPENSSL_EXTRA) + /* when compatibility layer is turned on and no verify is + * set then ignore the certificate key extension */ + if (args->dCert->extExtKeyUsageSet && + args->dCert->extExtKeyUsageCrit == 0 && + ssl->options.verifyNone) { + WOLFSSL_MSG("Not verifying certificate ext key usage"); + } + else + #endif + if (args->dCert->extExtKeyUsageSet) { + if (ssl->options.side == WOLFSSL_CLIENT_END) { + if ((args->dCert->extExtKeyUsage & + (EXTKEYUSE_ANY | EXTKEYUSE_SERVER_AUTH)) == 0) { + WOLFSSL_MSG("ExtKeyUse Server Auth not set"); + ret = EXTKEYUSE_AUTH_E; + } + } + else { + if ((args->dCert->extExtKeyUsage & + (EXTKEYUSE_ANY | EXTKEYUSE_CLIENT_AUTH)) == 0) { + WOLFSSL_MSG("ExtKeyUse Client Auth not set"); + ret = EXTKEYUSE_AUTH_E; + } + } + } + #endif /* IGNORE_KEY_EXTENSIONS */ + + if (args->fatal) { + ssl->error = ret; + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + SendAlert(ssl, alert_fatal, bad_certificate); + ssl->peerVerifyRet = X509_V_ERR_CERT_REJECTED; + #endif + goto exit_ppc; + } + + ssl->options.havePeerCert = 1; + + if (!ssl->options.verifyNone && ssl->buffers.domainName.buffer) { + #ifndef WOLFSSL_ALLOW_NO_CN_IN_SAN + /* Per RFC 5280 section 4.2.1.6, "Whenever such identities + * are to be bound into a certificate, the subject + * alternative name extension MUST be used." */ + if (args->dCert->altNames) { + if (CheckAltNames(args->dCert, + (char*)ssl->buffers.domainName.buffer) == 0 ) { + WOLFSSL_MSG("DomainName match on alt names failed"); + /* try to get peer key still */ + ret = DOMAIN_NAME_MISMATCH; + } + } + else { + if (MatchDomainName( + args->dCert->subjectCN, + args->dCert->subjectCNLen, + (char*)ssl->buffers.domainName.buffer) == 0) { + WOLFSSL_MSG("DomainName match on common name failed"); + ret = DOMAIN_NAME_MISMATCH; + } + } + #else /* WOLFSSL_ALL_NO_CN_IN_SAN */ + /* Old behavior. */ + if (MatchDomainName(args->dCert->subjectCN, + args->dCert->subjectCNLen, + (char*)ssl->buffers.domainName.buffer) == 0) { + WOLFSSL_MSG("DomainName match on common name failed"); + if (CheckAltNames(args->dCert, + (char*)ssl->buffers.domainName.buffer) == 0 ) { + WOLFSSL_MSG( + "DomainName match on alt names failed too"); + /* try to get peer key still */ + ret = DOMAIN_NAME_MISMATCH; + } + } + #endif /* WOLFSSL_ALL_NO_CN_IN_SAN */ + } + + /* decode peer key */ + switch (args->dCert->keyOID) { + #ifndef NO_RSA + case RSAk: + { + word32 keyIdx = 0; + int keyRet = 0; + + if (ssl->peerRsaKey == NULL) { + keyRet = AllocKey(ssl, DYNAMIC_TYPE_RSA, + (void**)&ssl->peerRsaKey); + } else if (ssl->peerRsaKeyPresent) { + keyRet = ReuseKey(ssl, DYNAMIC_TYPE_RSA, + ssl->peerRsaKey); + ssl->peerRsaKeyPresent = 0; + } + + if (keyRet != 0 || wc_RsaPublicKeyDecode( + args->dCert->publicKey, &keyIdx, ssl->peerRsaKey, + args->dCert->pubKeySize) != 0) { + ret = PEER_KEY_ERROR; + } + else { + ssl->peerRsaKeyPresent = 1; + #ifdef HAVE_PK_CALLBACKS + #ifndef NO_RSA + #ifdef HAVE_SECURE_RENEGOTIATION + if (ssl->buffers.peerRsaKey.buffer) { + XFREE(ssl->buffers.peerRsaKey.buffer, + ssl->heap, DYNAMIC_TYPE_RSA); + ssl->buffers.peerRsaKey.buffer = NULL; + } + #endif + + + ssl->buffers.peerRsaKey.buffer = + (byte*)XMALLOC(args->dCert->pubKeySize, + ssl->heap, DYNAMIC_TYPE_RSA); + if (ssl->buffers.peerRsaKey.buffer == NULL) { + ret = MEMORY_ERROR; + } + else { + XMEMCPY(ssl->buffers.peerRsaKey.buffer, + args->dCert->publicKey, + args->dCert->pubKeySize); + ssl->buffers.peerRsaKey.length = + args->dCert->pubKeySize; + } + #endif /* NO_RSA */ + #endif /* HAVE_PK_CALLBACKS */ + } + + /* check size of peer RSA key */ + if (ret == 0 && ssl->peerRsaKeyPresent && + !ssl->options.verifyNone && + wc_RsaEncryptSize(ssl->peerRsaKey) + < ssl->options.minRsaKeySz) { + ret = RSA_KEY_SIZE_E; + WOLFSSL_MSG("Peer RSA key is too small"); + } + break; + } + #endif /* NO_RSA */ + #ifdef HAVE_NTRU + case NTRUk: + { + if (args->dCert->pubKeySize > sizeof(ssl->peerNtruKey)) { + ret = PEER_KEY_ERROR; + } + else { + XMEMCPY(ssl->peerNtruKey, args->dCert->publicKey, + args->dCert->pubKeySize); + ssl->peerNtruKeyLen = + (word16)args->dCert->pubKeySize; + ssl->peerNtruKeyPresent = 1; + } + break; + } + #endif /* HAVE_NTRU */ + #ifdef HAVE_ECC + case ECDSAk: + { + int keyRet = 0; + word32 idx = 0; + + if (ssl->peerEccDsaKey == NULL) { + /* alloc/init on demand */ + keyRet = AllocKey(ssl, DYNAMIC_TYPE_ECC, + (void**)&ssl->peerEccDsaKey); + } else if (ssl->peerEccDsaKeyPresent) { + keyRet = ReuseKey(ssl, DYNAMIC_TYPE_ECC, + ssl->peerEccDsaKey); + ssl->peerEccDsaKeyPresent = 0; + } + + if (keyRet != 0 || + wc_EccPublicKeyDecode(args->dCert->publicKey, &idx, + ssl->peerEccDsaKey, + args->dCert->pubKeySize) != 0) { + ret = PEER_KEY_ERROR; + } + else { + ssl->peerEccDsaKeyPresent = 1; + #ifdef HAVE_PK_CALLBACKS + ssl->buffers.peerEccDsaKey.buffer = + (byte*)XMALLOC(args->dCert->pubKeySize, + ssl->heap, DYNAMIC_TYPE_ECC); + if (ssl->buffers.peerEccDsaKey.buffer == NULL) { + ERROR_OUT(MEMORY_ERROR, exit_ppc); + } + else { + XMEMCPY(ssl->buffers.peerEccDsaKey.buffer, + args->dCert->publicKey, + args->dCert->pubKeySize); + ssl->buffers.peerEccDsaKey.length = + args->dCert->pubKeySize; + } + #endif /* HAVE_PK_CALLBACKS */ + } + + /* check size of peer ECC key */ + if (ret == 0 && ssl->peerEccDsaKeyPresent && + !ssl->options.verifyNone && + wc_ecc_size(ssl->peerEccDsaKey) + < ssl->options.minEccKeySz) { + ret = ECC_KEY_SIZE_E; + WOLFSSL_MSG("Peer ECC key is too small"); + } + break; + } + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ED25519k: + { + int keyRet = 0; + if (ssl->peerEd25519Key == NULL) { + /* alloc/init on demand */ + keyRet = AllocKey(ssl, DYNAMIC_TYPE_ED25519, + (void**)&ssl->peerEd25519Key); + } else if (ssl->peerEd25519KeyPresent) { + keyRet = ReuseKey(ssl, DYNAMIC_TYPE_ED25519, + ssl->peerEd25519Key); + ssl->peerEd25519KeyPresent = 0; + } + + if (keyRet != 0 || + wc_ed25519_import_public(args->dCert->publicKey, + args->dCert->pubKeySize, + ssl->peerEd25519Key) + != 0) { + ret = PEER_KEY_ERROR; + } + else { + ssl->peerEd25519KeyPresent = 1; + #ifdef HAVE_PK_CALLBACKS + ssl->buffers.peerEd25519Key.buffer = + (byte*)XMALLOC(args->dCert->pubKeySize, + ssl->heap, DYNAMIC_TYPE_ED25519); + if (ssl->buffers.peerEd25519Key.buffer == NULL) { + ERROR_OUT(MEMORY_ERROR, exit_ppc); + } + else { + XMEMCPY(ssl->buffers.peerEd25519Key.buffer, + args->dCert->publicKey, + args->dCert->pubKeySize); + ssl->buffers.peerEd25519Key.length = + args->dCert->pubKeySize; + } + #endif /*HAVE_PK_CALLBACKS */ + } + + /* check size of peer ECC key */ + if (ret == 0 && ssl->peerEd25519KeyPresent && + !ssl->options.verifyNone && + ED25519_KEY_SIZE < ssl->options.minEccKeySz) { + ret = ECC_KEY_SIZE_E; + WOLFSSL_MSG("Peer ECC key is too small"); + } + break; + } + #endif /* HAVE_ED25519 */ + default: + break; + } + + /* args->dCert free'd in function cleanup after callback */ + } /* if (count > 0) */ + + /* Check for error */ + if (args->fatal && ret != 0) { + goto exit_ppc; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_FINALIZE; + } /* case TLS_ASYNC_VERIFY */ + FALL_THROUGH; + + case TLS_ASYNC_FINALIZE: + { + /* load last error */ + if (args->lastErr != 0 && ret == 0) { + ret = args->lastErr; + } + + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + if (args->untrustedDepth > ssl->options.verifyDepth) { + ssl->peerVerifyRet = X509_V_ERR_CERT_CHAIN_TOO_LONG; + ret = MAX_CHAIN_ERROR; + } + #endif + + /* Do verify callback */ + ret = DoVerifyCallback(ssl, ret, args); + + if (ssl->options.verifyNone && + (ret == CRL_MISSING || ret == CRL_CERT_REVOKED)) { + WOLFSSL_MSG("Ignoring CRL problem based on verify setting"); + ret = ssl->error = 0; + } + + if (ret == 0 && ssl->options.side == WOLFSSL_CLIENT_END) { + ssl->options.serverState = SERVER_CERT_COMPLETE; + } + + if (IsEncryptionOn(ssl, 0)) { + args->idx += ssl->keys.padSz; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_END; + } /* case TLS_ASYNC_FINALIZE */ + FALL_THROUGH; + + case TLS_ASYNC_END: + { + /* Set final index */ + *inOutIdx = args->idx; + + break; + } + default: + ret = INPUT_CASE_ERROR; + break; + } /* switch(ssl->options.asyncState) */ + +exit_ppc: + + WOLFSSL_LEAVE("ProcessPeerCerts", ret); + + +#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLFSSL_NONBLOCK_OCSP) + if (ret == WC_PENDING_E || ret == OCSP_WANT_READ) { + /* Mark message as not received so it can process again */ + ssl->msgsReceived.got_certificate = 0; + + return ret; + } +#endif /* WOLFSSL_ASYNC_CRYPT || WOLFSSL_NONBLOCK_OCSP */ + + FreeProcPeerCertArgs(ssl, args); + +#if defined(WOLFSSL_ASYNC_CRYPT) +#elif defined(WOLFSSL_NONBLOCK_OCSP) + XFREE(args, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + ssl->nonblockarg = NULL; +#elif defined(WOLFSSL_SMALL_STACK) + XFREE(args, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + FreeKeyExchange(ssl); + + return ret; +} +#endif + +#ifndef WOLFSSL_NO_TLS12 +#if !defined(NO_WOLFSSL_CLIENT) || !defined(WOLFSSL_NO_CLIENT_AUTH) + +/* handle processing of certificate (11) */ +static int DoCertificate(WOLFSSL* ssl, byte* input, word32* inOutIdx, + word32 size) +{ + int ret; + + WOLFSSL_START(WC_FUNC_CERTIFICATE_DO); + WOLFSSL_ENTER("DoCertificate"); + +#ifdef SESSION_CERTS + /* Reset the session cert chain count in case the session resume failed. */ + ssl->session.chain.count = 0; + #ifdef WOLFSSL_ALT_CERT_CHAINS + ssl->session.altChain.count = 0; + #endif +#endif /* SESSION_CERTS */ + + ret = ProcessPeerCerts(ssl, input, inOutIdx, size); +#ifdef WOLFSSL_EXTRA_ALERTS + if (ret == BUFFER_ERROR || ret == ASN_PARSE_E) + SendAlert(ssl, alert_fatal, decode_error); +#endif + +#ifdef OPENSSL_EXTRA + ssl->options.serverState = SERVER_CERT_COMPLETE; +#endif + + WOLFSSL_LEAVE("DoCertificate", ret); + WOLFSSL_END(WC_FUNC_CERTIFICATE_DO); + + return ret; +} + +/* handle processing of certificate_status (22) */ +static int DoCertificateStatus(WOLFSSL* ssl, byte* input, word32* inOutIdx, + word32 size) +{ + int ret = 0; + byte status_type; + word32 status_length; + + WOLFSSL_START(WC_FUNC_CERTIFICATE_STATUS_DO); + WOLFSSL_ENTER("DoCertificateStatus"); + + if (size < ENUM_LEN + OPAQUE24_LEN) + return BUFFER_ERROR; + + status_type = input[(*inOutIdx)++]; + + c24to32(input + *inOutIdx, &status_length); + *inOutIdx += OPAQUE24_LEN; + + if (size != ENUM_LEN + OPAQUE24_LEN + status_length) + return BUFFER_ERROR; + + switch (status_type) { + + #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + + /* WOLFSSL_CSR_OCSP overlaps with WOLFSSL_CSR2_OCSP */ + case WOLFSSL_CSR2_OCSP: + ret = ProcessCSR(ssl, input, inOutIdx, status_length); + break; + + #endif + + #if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + + case WOLFSSL_CSR2_OCSP_MULTI: { + OcspRequest* request; + word32 list_length = status_length; + byte idx = 0; + + #ifdef WOLFSSL_SMALL_STACK + CertStatus* status; + OcspResponse* response; + #else + CertStatus status[1]; + OcspResponse response[1]; + #endif + + do { + if (ssl->status_request_v2) { + ssl->status_request_v2 = 0; + break; + } + + return BUFFER_ERROR; + } while(0); + + #ifdef WOLFSSL_SMALL_STACK + status = (CertStatus*)XMALLOC(sizeof(CertStatus), ssl->heap, + DYNAMIC_TYPE_OCSP_STATUS); + response = (OcspResponse*)XMALLOC(sizeof(OcspResponse), ssl->heap, + DYNAMIC_TYPE_OCSP_REQUEST); + + if (status == NULL || response == NULL) { + if (status) + XFREE(status, ssl->heap, DYNAMIC_TYPE_OCSP_STATUS); + if (response) + XFREE(response, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); + + return MEMORY_ERROR; + } + #endif + + while (list_length && ret == 0) { + if (OPAQUE24_LEN > list_length) { + ret = BUFFER_ERROR; + break; + } + + c24to32(input + *inOutIdx, &status_length); + *inOutIdx += OPAQUE24_LEN; + list_length -= OPAQUE24_LEN; + + if (status_length > list_length) { + ret = BUFFER_ERROR; + break; + } + + if (status_length) { + InitOcspResponse(response, status, input +*inOutIdx, + status_length); + + if ((OcspResponseDecode(response, ssl->ctx->cm, ssl->heap, + 0) != 0) + || (response->responseStatus != OCSP_SUCCESSFUL) + || (response->status->status != CERT_GOOD)) + ret = BAD_CERTIFICATE_STATUS_ERROR; + + while (ret == 0) { + request = (OcspRequest*)TLSX_CSR2_GetRequest( + ssl->extensions, status_type, idx++); + + if (request == NULL) + ret = BAD_CERTIFICATE_STATUS_ERROR; + else if (CompareOcspReqResp(request, response) == 0) + break; + else if (idx == 1) /* server cert must be OK */ + ret = BAD_CERTIFICATE_STATUS_ERROR; + } + + *inOutIdx += status_length; + list_length -= status_length; + } + } + + #if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + ssl->status_request_v2 = 0; + #endif + + #ifdef WOLFSSL_SMALL_STACK + XFREE(status, NULL, DYNAMIC_TYPE_OCSP_STATUS); + XFREE(response, NULL, DYNAMIC_TYPE_OCSP_REQUEST); + #endif + + } + break; + + #endif + + default: + ret = BUFFER_ERROR; + } + + if (ret != 0) + SendAlert(ssl, alert_fatal, bad_certificate_status_response); + + if (IsEncryptionOn(ssl, 0)) { + if (*inOutIdx + ssl->keys.padSz > size) + return BUFFER_E; + *inOutIdx += ssl->keys.padSz; + } + + WOLFSSL_LEAVE("DoCertificateStatus", ret); + WOLFSSL_END(WC_FUNC_CERTIFICATE_STATUS_DO); + + return ret; +} + +#endif + +#endif /* !WOLFSSL_NO_TLS12 */ + +#endif /* !NO_CERTS */ + +#ifndef WOLFSSL_NO_TLS12 + +static int DoHelloRequest(WOLFSSL* ssl, const byte* input, word32* inOutIdx, + word32 size, word32 totalSz) +{ + (void)input; + + WOLFSSL_START(WC_FUNC_HELLO_REQUEST_DO); + WOLFSSL_ENTER("DoHelloRequest"); + + if (size) /* must be 0 */ + return BUFFER_ERROR; + + if (IsEncryptionOn(ssl, 0)) { + /* access beyond input + size should be checked against totalSz */ + if (*inOutIdx + ssl->keys.padSz > totalSz) + return BUFFER_E; + + *inOutIdx += ssl->keys.padSz; + } + + if (ssl->options.side == WOLFSSL_SERVER_END) { + SendAlert(ssl, alert_fatal, unexpected_message); /* try */ + return FATAL_ERROR; + } +#ifdef HAVE_SECURE_RENEGOTIATION + else if (ssl->secure_renegotiation && ssl->secure_renegotiation->enabled) { + ssl->secure_renegotiation->startScr = 1; + WOLFSSL_LEAVE("DoHelloRequest", 0); + WOLFSSL_END(WC_FUNC_HELLO_REQUEST_DO); + return 0; + } +#endif + else { + return SendAlert(ssl, alert_warning, no_renegotiation); + } +} + + +int DoFinished(WOLFSSL* ssl, const byte* input, word32* inOutIdx, word32 size, + word32 totalSz, int sniff) +{ + word32 finishedSz = (ssl->options.tls ? TLS_FINISHED_SZ : FINISHED_SZ); + + WOLFSSL_START(WC_FUNC_FINISHED_DO); + WOLFSSL_ENTER("DoFinished"); + + if (finishedSz != size) + return BUFFER_ERROR; + + /* check against totalSz */ + if (*inOutIdx + size + ssl->keys.padSz > totalSz) + return BUFFER_E; + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName(ssl, "Finished"); + if (ssl->toInfoOn) AddLateName("Finished", &ssl->timeoutInfo); + #endif + + if (sniff == NO_SNIFF) { + if (XMEMCMP(input + *inOutIdx, &ssl->hsHashes->verifyHashes,size) != 0){ + WOLFSSL_MSG("Verify finished error on hashes"); + #ifdef WOLFSSL_EXTRA_ALERTS + SendAlert(ssl, alert_fatal, decrypt_error); + #endif + return VERIFY_FINISHED_ERROR; + } + } + +#ifdef HAVE_SECURE_RENEGOTIATION + if (ssl->secure_renegotiation) { + /* save peer's state */ + if (ssl->options.side == WOLFSSL_CLIENT_END) + XMEMCPY(ssl->secure_renegotiation->server_verify_data, + input + *inOutIdx, TLS_FINISHED_SZ); + else + XMEMCPY(ssl->secure_renegotiation->client_verify_data, + input + *inOutIdx, TLS_FINISHED_SZ); + ssl->secure_renegotiation->verifySet = 1; + } +#endif + + /* force input exhaustion at ProcessReply consuming padSz */ + *inOutIdx += size + ssl->keys.padSz; + + if (ssl->options.side == WOLFSSL_CLIENT_END) { + ssl->options.serverState = SERVER_FINISHED_COMPLETE; +#ifdef OPENSSL_EXTRA + ssl->cbmode = SSL_CB_MODE_WRITE; + ssl->options.clientState = CLIENT_FINISHED_COMPLETE; +#endif + if (!ssl->options.resuming) { +#ifdef OPENSSL_EXTRA + if (ssl->CBIS != NULL) { + ssl->CBIS(ssl, SSL_CB_CONNECT_LOOP, SSL_SUCCESS); + } +#endif + ssl->options.handShakeState = HANDSHAKE_DONE; + ssl->options.handShakeDone = 1; + } + } + else { + ssl->options.clientState = CLIENT_FINISHED_COMPLETE; +#ifdef OPENSSL_EXTRA + ssl->cbmode = SSL_CB_MODE_READ; + ssl->options.serverState = SERVER_FINISHED_COMPLETE; +#endif + if (ssl->options.resuming) { +#ifdef OPENSSL_EXTRA + if (ssl->CBIS != NULL) { + ssl->CBIS(ssl, SSL_CB_ACCEPT_LOOP, SSL_SUCCESS); + } +#endif + ssl->options.handShakeState = HANDSHAKE_DONE; + ssl->options.handShakeDone = 1; + } + } + + WOLFSSL_LEAVE("DoFinished", 0); + WOLFSSL_END(WC_FUNC_FINISHED_DO); + + return 0; +} + + +/* Make sure no duplicates, no fast forward, or other problems; 0 on success */ +static int SanityCheckMsgReceived(WOLFSSL* ssl, byte type) +{ + /* verify not a duplicate, mark received, check state */ + switch (type) { + +#ifndef NO_WOLFSSL_CLIENT + case hello_request: + if (ssl->msgsReceived.got_hello_request) { + WOLFSSL_MSG("Duplicate HelloRequest received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_hello_request = 1; + + break; +#endif + +#ifndef NO_WOLFSSL_SERVER + case client_hello: + if (ssl->msgsReceived.got_client_hello) { + WOLFSSL_MSG("Duplicate ClientHello received"); + #ifdef WOLFSSL_EXTRA_ALERTS + SendAlert(ssl, alert_fatal, unexpected_message); + #endif + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_client_hello = 1; + + break; +#endif + +#ifndef NO_WOLFSSL_CLIENT + case server_hello: + if (ssl->msgsReceived.got_server_hello) { + WOLFSSL_MSG("Duplicate ServerHello received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_server_hello = 1; + + break; +#endif + +#ifndef NO_WOLFSSL_CLIENT + case hello_verify_request: + if (ssl->msgsReceived.got_hello_verify_request) { + WOLFSSL_MSG("Duplicate HelloVerifyRequest received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_hello_verify_request = 1; + + break; +#endif + +#ifndef NO_WOLFSSL_CLIENT + case session_ticket: + if (ssl->msgsReceived.got_session_ticket) { + WOLFSSL_MSG("Duplicate SessionTicket received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_session_ticket = 1; + + break; +#endif + + case certificate: + if (ssl->msgsReceived.got_certificate) { + WOLFSSL_MSG("Duplicate Certificate received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_certificate = 1; + +#ifndef NO_WOLFSSL_CLIENT + if (ssl->options.side == WOLFSSL_CLIENT_END) { + if ( ssl->msgsReceived.got_server_hello == 0) { + WOLFSSL_MSG("No ServerHello before Cert"); + return OUT_OF_ORDER_E; + } + } +#endif +#ifndef NO_WOLFSSL_SERVER + if (ssl->options.side == WOLFSSL_SERVER_END) { + if ( ssl->msgsReceived.got_client_hello == 0) { + WOLFSSL_MSG("No ClientHello before Cert"); + return OUT_OF_ORDER_E; + } + } +#endif + break; + +#ifndef NO_WOLFSSL_CLIENT + case certificate_status: + if (ssl->msgsReceived.got_certificate_status) { + WOLFSSL_MSG("Duplicate CertificateSatatus received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_certificate_status = 1; + + if (ssl->msgsReceived.got_certificate == 0) { + WOLFSSL_MSG("No Certificate before CertificateStatus"); + return OUT_OF_ORDER_E; + } + if (ssl->msgsReceived.got_server_key_exchange != 0) { + WOLFSSL_MSG("CertificateStatus after ServerKeyExchange"); + return OUT_OF_ORDER_E; + } + + break; +#endif + +#ifndef NO_WOLFSSL_CLIENT + case server_key_exchange: + if (ssl->msgsReceived.got_server_key_exchange) { + WOLFSSL_MSG("Duplicate ServerKeyExchange received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_server_key_exchange = 1; + + if (ssl->msgsReceived.got_server_hello == 0) { + WOLFSSL_MSG("No ServerHello before ServerKeyExchange"); + return OUT_OF_ORDER_E; + } + if (ssl->msgsReceived.got_certificate_status == 0) { +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST + if (ssl->status_request) { + int ret; + + WOLFSSL_MSG("No CertificateStatus before ServerKeyExchange"); + if ((ret = TLSX_CSR_ForceRequest(ssl)) != 0) + return ret; + } +#endif +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + if (ssl->status_request_v2) { + int ret; + + WOLFSSL_MSG("No CertificateStatus before ServerKeyExchange"); + if ((ret = TLSX_CSR2_ForceRequest(ssl)) != 0) + return ret; + } +#endif + } + + break; +#endif + +#ifndef NO_WOLFSSL_CLIENT + case certificate_request: + if (ssl->msgsReceived.got_certificate_request) { + WOLFSSL_MSG("Duplicate CertificateRequest received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_certificate_request = 1; + + break; +#endif + +#ifndef NO_WOLFSSL_CLIENT + case server_hello_done: + if (ssl->msgsReceived.got_server_hello_done) { + WOLFSSL_MSG("Duplicate ServerHelloDone received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_server_hello_done = 1; + + if (ssl->msgsReceived.got_certificate == 0) { + if (ssl->specs.kea == psk_kea || + ssl->specs.kea == dhe_psk_kea || + ssl->specs.kea == ecdhe_psk_kea || + ssl->options.usingAnon_cipher) { + WOLFSSL_MSG("No Cert required"); + } else { + WOLFSSL_MSG("No Certificate before ServerHelloDone"); + return OUT_OF_ORDER_E; + } + } + if (ssl->msgsReceived.got_server_key_exchange == 0) { + int pskNoServerHint = 0; /* not required in this case */ + + #ifndef NO_PSK + if (ssl->specs.kea == psk_kea && + ssl->arrays->server_hint[0] == 0) + pskNoServerHint = 1; + #endif + if (ssl->specs.static_ecdh == 1 || + ssl->specs.kea == rsa_kea || + ssl->specs.kea == ntru_kea || + pskNoServerHint) { + WOLFSSL_MSG("No KeyExchange required"); + } else { + WOLFSSL_MSG("No ServerKeyExchange before ServerDone"); + return OUT_OF_ORDER_E; + } + } + break; +#endif + +#ifndef NO_WOLFSSL_SERVER + case certificate_verify: + if (ssl->msgsReceived.got_certificate_verify) { + WOLFSSL_MSG("Duplicate CertificateVerify received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_certificate_verify = 1; + + if ( ssl->msgsReceived.got_certificate == 0) { + WOLFSSL_MSG("No Cert before CertVerify"); + return OUT_OF_ORDER_E; + } + break; +#endif + +#ifndef NO_WOLFSSL_SERVER + case client_key_exchange: + if (ssl->msgsReceived.got_client_key_exchange) { + WOLFSSL_MSG("Duplicate ClientKeyExchange received"); + #ifdef WOLFSSL_EXTRA_ALERTS + SendAlert(ssl, alert_fatal, unexpected_message); + #endif + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_client_key_exchange = 1; + + if (ssl->msgsReceived.got_client_hello == 0) { + WOLFSSL_MSG("No ClientHello before ClientKeyExchange"); + return OUT_OF_ORDER_E; + } + break; +#endif + + case finished: + if (ssl->msgsReceived.got_finished) { + WOLFSSL_MSG("Duplicate Finished received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_finished = 1; + + if (ssl->msgsReceived.got_change_cipher == 0) { + WOLFSSL_MSG("Finished received before ChangeCipher"); + #ifdef WOLFSSL_EXTRA_ALERTS + SendAlert(ssl, alert_fatal, unexpected_message); + #endif + return NO_CHANGE_CIPHER_E; + } + break; + + case change_cipher_hs: + if (ssl->msgsReceived.got_change_cipher) { + WOLFSSL_MSG("Duplicate ChangeCipher received"); + #ifdef WOLFSSL_EXTRA_ALERTS + SendAlert(ssl, alert_fatal, unexpected_message); + #endif + return DUPLICATE_MSG_E; + } + /* DTLS is going to ignore the CCS message if the client key + * exchange message wasn't received yet. */ + if (!ssl->options.dtls) + ssl->msgsReceived.got_change_cipher = 1; + +#ifndef NO_WOLFSSL_CLIENT + if (ssl->options.side == WOLFSSL_CLIENT_END) { + if (!ssl->options.resuming) { + if (ssl->msgsReceived.got_server_hello_done == 0) { + WOLFSSL_MSG("No ServerHelloDone before ChangeCipher"); + return OUT_OF_ORDER_E; + } + } + else { + if (ssl->msgsReceived.got_server_hello == 0) { + WOLFSSL_MSG("No ServerHello before ChangeCipher on Resume"); + return OUT_OF_ORDER_E; + } + } + #ifdef HAVE_SESSION_TICKET + if (ssl->expect_session_ticket) { + WOLFSSL_MSG("Expected session ticket missing"); + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + return OUT_OF_ORDER_E; + #endif + return SESSION_TICKET_EXPECT_E; + } + #endif + } +#endif +#ifndef NO_WOLFSSL_SERVER + if (ssl->options.side == WOLFSSL_SERVER_END) { + if (!ssl->options.resuming && + ssl->msgsReceived.got_client_key_exchange == 0) { + WOLFSSL_MSG("No ClientKeyExchange before ChangeCipher"); + #ifdef WOLFSSL_EXTRA_ALERTS + SendAlert(ssl, alert_fatal, unexpected_message); + #endif + return OUT_OF_ORDER_E; + } + #ifndef NO_CERTS + if (ssl->options.verifyPeer && + ssl->options.havePeerCert) { + + if (!ssl->options.havePeerVerify) { + WOLFSSL_MSG("client didn't send cert verify"); + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + return OUT_OF_ORDER_E; + #endif + return NO_PEER_VERIFY; + } + } + #endif + } +#endif + if (ssl->options.dtls) + ssl->msgsReceived.got_change_cipher = 1; + break; + + default: + WOLFSSL_MSG("Unknown message type"); + return SANITY_MSG_E; + } + + return 0; +} + + +static int DoHandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, + byte type, word32 size, word32 totalSz) +{ + int ret = 0; + word32 expectedIdx; + + WOLFSSL_ENTER("DoHandShakeMsgType"); + +#ifdef WOLFSSL_TLS13 + if (type == hello_retry_request) { + return DoTls13HandShakeMsgType(ssl, input, inOutIdx, type, size, + totalSz); + } +#endif + + /* make sure can read the message */ + if (*inOutIdx + size > totalSz) { + WOLFSSL_MSG("Incomplete Data"); + return INCOMPLETE_DATA; + } + + expectedIdx = *inOutIdx + size + + (ssl->keys.encryptionOn ? ssl->keys.padSz : 0); + +#if !defined(WOLFSSL_NO_SERVER) && \ + defined(HAVE_SECURE_RENEGOTIATION) && \ + defined(HAVE_SERVER_RENEGOTIATION_INFO) + if (ssl->options.handShakeDone && type == client_hello && + ssl->secure_renegotiation && + ssl->secure_renegotiation->enabled) + { + WOLFSSL_MSG("Reset handshake state"); + XMEMSET(&ssl->msgsReceived, 0, sizeof(MsgsReceived)); + ssl->options.serverState = NULL_STATE; + ssl->options.clientState = NULL_STATE; + ssl->options.connectState = CONNECT_BEGIN; + ssl->options.acceptState = ACCEPT_FIRST_REPLY_DONE; + ssl->options.handShakeState = NULL_STATE; + ssl->secure_renegotiation->cache_status = SCR_CACHE_NEEDED; + + ret = InitHandshakeHashes(ssl); + if (ret != 0) + return ret; + } +#endif + + /* sanity check msg received */ + if ( (ret = SanityCheckMsgReceived(ssl, type)) != 0) { + WOLFSSL_MSG("Sanity Check on handshake message type received failed"); + return ret; + } + +#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) + /* add name later, add on record and handshake header part back on */ + if (ssl->toInfoOn) { + int add = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + AddPacketInfo(ssl, 0, handshake, input + *inOutIdx - add, + size + add, READ_PROTO, ssl->heap); + #ifdef WOLFSSL_CALLBACKS + AddLateRecordHeader(&ssl->curRL, &ssl->timeoutInfo); + #endif + } +#endif + + if (ssl->options.handShakeState == HANDSHAKE_DONE && type != hello_request){ + WOLFSSL_MSG("HandShake message after handshake complete"); + SendAlert(ssl, alert_fatal, unexpected_message); + return OUT_OF_ORDER_E; + } + + if (ssl->options.side == WOLFSSL_CLIENT_END && ssl->options.dtls == 0 && + ssl->options.serverState == NULL_STATE && type != server_hello) { + WOLFSSL_MSG("First server message not server hello"); + SendAlert(ssl, alert_fatal, unexpected_message); + return OUT_OF_ORDER_E; + } + + if (ssl->options.side == WOLFSSL_CLIENT_END && ssl->options.dtls && + type == server_hello_done && + ssl->options.serverState < SERVER_HELLO_COMPLETE) { + WOLFSSL_MSG("Server hello done received before server hello in DTLS"); + SendAlert(ssl, alert_fatal, unexpected_message); + return OUT_OF_ORDER_E; + } + + if (ssl->options.side == WOLFSSL_SERVER_END && + ssl->options.clientState == NULL_STATE && type != client_hello) { + WOLFSSL_MSG("First client message not client hello"); + SendAlert(ssl, alert_fatal, unexpected_message); + return OUT_OF_ORDER_E; + } + + /* above checks handshake state */ + /* hello_request not hashed */ + /* Also, skip hashing the client_hello message here for DTLS. It will be + * hashed later if the DTLS cookie is correct. */ + if (type != hello_request && + !(IsDtlsNotSctpMode(ssl) && type == client_hello) + #ifdef WOLFSSL_ASYNC_CRYPT + && ssl->error != WC_PENDING_E + #endif + #ifdef WOLFSSL_NONBLOCK_OCSP + && ssl->error != OCSP_WANT_READ + #endif + ) { + ret = HashInput(ssl, input + *inOutIdx, size); + if (ret != 0) { + WOLFSSL_MSG("Incomplete handshake hashes"); + return ret; + } + } + +#ifdef OPENSSL_EXTRA + if (ssl->CBIS != NULL){ + ssl->cbmode = SSL_CB_MODE_READ; + ssl->cbtype = type; + ssl->CBIS(ssl, SSL_CB_ACCEPT_LOOP, SSL_SUCCESS); + } +#endif + + switch (type) { + + case hello_request: + WOLFSSL_MSG("processing hello request"); + ret = DoHelloRequest(ssl, input, inOutIdx, size, totalSz); + break; + +#ifndef NO_WOLFSSL_CLIENT + case hello_verify_request: + WOLFSSL_MSG("processing hello verify request"); + ret = DoHelloVerifyRequest(ssl, input,inOutIdx, size); + break; + + case server_hello: + WOLFSSL_MSG("processing server hello"); + ret = DoServerHello(ssl, input, inOutIdx, size); + #if !defined(WOLFSSL_NO_CLIENT_AUTH) && defined(HAVE_ED25519) && \ + !defined(NO_ED25519_CLIENT_AUTH) + if (ssl->options.resuming || !IsAtLeastTLSv1_2(ssl) || + IsAtLeastTLSv1_3(ssl->version)) { + + #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLFSSL_NONBLOCK_OCSP) + if (ret != WC_PENDING_E && ret != OCSP_WANT_READ) + #endif + { + ssl->options.cacheMessages = 0; + if (ssl->hsHashes->messages != NULL) { + XFREE(ssl->hsHashes->messages, ssl->heap, + DYNAMIC_TYPE_HASHES); + ssl->hsHashes->messages = NULL; + } + } + } + #endif + break; + +#ifndef NO_CERTS + case certificate_request: + WOLFSSL_MSG("processing certificate request"); + ret = DoCertificateRequest(ssl, input, inOutIdx, size); + break; +#endif + + case server_key_exchange: + WOLFSSL_MSG("processing server key exchange"); + ret = DoServerKeyExchange(ssl, input, inOutIdx, size); + break; + +#ifdef HAVE_SESSION_TICKET + case session_ticket: + WOLFSSL_MSG("processing session ticket"); + ret = DoSessionTicket(ssl, input, inOutIdx, size); + break; +#endif /* HAVE_SESSION_TICKET */ +#endif + +#if !defined(NO_CERTS) && (!defined(NO_WOLFSSL_CLIENT) || \ + !defined(WOLFSSL_NO_CLIENT_AUTH)) + case certificate: + WOLFSSL_MSG("processing certificate"); + ret = DoCertificate(ssl, input, inOutIdx, size); + break; + + case certificate_status: + WOLFSSL_MSG("processing certificate status"); + ret = DoCertificateStatus(ssl, input, inOutIdx, size); + break; +#endif + + case server_hello_done: + WOLFSSL_MSG("processing server hello done"); + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName(ssl, "ServerHelloDone"); + if (ssl->toInfoOn) + AddLateName("ServerHelloDone", &ssl->timeoutInfo); + #endif + ssl->options.serverState = SERVER_HELLODONE_COMPLETE; + if (IsEncryptionOn(ssl, 0)) { + *inOutIdx += ssl->keys.padSz; + } + if (ssl->options.resuming) { + WOLFSSL_MSG("Not resuming as thought"); + ssl->options.resuming = 0; + } + break; + + case finished: + WOLFSSL_MSG("processing finished"); + ret = DoFinished(ssl, input, inOutIdx, size, totalSz, NO_SNIFF); + break; + +#ifndef NO_WOLFSSL_SERVER + case client_hello: + WOLFSSL_MSG("processing client hello"); + ret = DoClientHello(ssl, input, inOutIdx, size); + #if !defined(WOLFSSL_NO_CLIENT_AUTH) && defined(HAVE_ED25519) && \ + !defined(NO_ED25519_CLIENT_AUTH) + if (ssl->options.resuming || !ssl->options.verifyPeer || \ + !IsAtLeastTLSv1_2(ssl) || IsAtLeastTLSv1_3(ssl->version)) { + #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLFSSL_NONBLOCK_OCSP) + if (ret != WC_PENDING_E && ret != OCSP_WANT_READ) + #endif + { + ssl->options.cacheMessages = 0; + if (ssl->hsHashes->messages != NULL) { + XFREE(ssl->hsHashes->messages, ssl->heap, DYNAMIC_TYPE_HASHES); + ssl->hsHashes->messages = NULL; + } + } + } + #endif + if (IsEncryptionOn(ssl, 0)) { + /* access beyond input + size should be checked against totalSz */ + if (*inOutIdx + ssl->keys.padSz > totalSz) + return BUFFER_E; + + *inOutIdx += ssl->keys.padSz; + } + break; + + case client_key_exchange: + WOLFSSL_MSG("processing client key exchange"); + ret = DoClientKeyExchange(ssl, input, inOutIdx, size); + break; + +#if (!defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519)) && \ + !defined(WOLFSSL_NO_CLIENT_AUTH) + case certificate_verify: + WOLFSSL_MSG("processing certificate verify"); + ret = DoCertificateVerify(ssl, input, inOutIdx, size); + break; +#endif /* (!NO_RSA || HAVE_ECC || HAVE_ED25519) && !WOLFSSL_NO_CLIENT_AUTH */ + +#endif /* !NO_WOLFSSL_SERVER */ + + default: + WOLFSSL_MSG("Unknown handshake message type"); + ret = UNKNOWN_HANDSHAKE_TYPE; + break; + } + if (ret == 0 && expectedIdx != *inOutIdx) { + WOLFSSL_MSG("Extra data in handshake message"); + if (!ssl->options.dtls) + SendAlert(ssl, alert_fatal, decode_error); + ret = DECODE_E; + } + + if (ret == 0 && ssl->buffers.inputBuffer.dynamicFlag + #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLFSSL_NONBLOCK_OCSP) + /* do not shrink input for async or non-block */ + && ssl->error != WC_PENDING_E && ssl->error != OCSP_WANT_READ + #endif + ) { + ShrinkInputBuffer(ssl, NO_FORCED_FREE); + } + +#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLFSSL_NONBLOCK_OCSP) + /* if async, offset index so this msg will be processed again */ + if ((ret == WC_PENDING_E || ret == OCSP_WANT_READ) && *inOutIdx > 0) { + *inOutIdx -= HANDSHAKE_HEADER_SZ; + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + *inOutIdx -= DTLS_HANDSHAKE_EXTRA; + } + #endif + } + + /* make sure async error is cleared */ + if (ret == 0 && (ssl->error == WC_PENDING_E || ssl->error == OCSP_WANT_READ)) { + ssl->error = 0; + } +#endif /* WOLFSSL_ASYNC_CRYPT || WOLFSSL_NONBLOCK_OCSP */ + + WOLFSSL_LEAVE("DoHandShakeMsgType()", ret); + return ret; +} + + +static int DoHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, + word32 totalSz) +{ + int ret = 0; + word32 inputLength; + + WOLFSSL_ENTER("DoHandShakeMsg()"); + + if (ssl->arrays == NULL) { + byte type; + word32 size; + + if (GetHandShakeHeader(ssl,input,inOutIdx,&type, &size, totalSz) != 0) + return PARSE_ERROR; + + ssl->options.handShakeState = type; + + return DoHandShakeMsgType(ssl, input, inOutIdx, type, size, totalSz); + } + + inputLength = ssl->buffers.inputBuffer.length - *inOutIdx; + + /* If there is a pending fragmented handshake message, + * pending message size will be non-zero. */ + if (ssl->arrays->pendingMsgSz == 0) { + byte type; + word32 size; + + if (GetHandShakeHeader(ssl,input, inOutIdx, &type, &size, totalSz) != 0) + return PARSE_ERROR; + + /* Cap the maximum size of a handshake message to something reasonable. + * By default is the maximum size of a certificate message assuming + * nine 2048-bit RSA certificates in the chain. */ + if (size > MAX_HANDSHAKE_SZ) { + WOLFSSL_MSG("Handshake message too large"); + return HANDSHAKE_SIZE_ERROR; + } + + /* size is the size of the certificate message payload */ + if (inputLength - HANDSHAKE_HEADER_SZ < size) { + ssl->arrays->pendingMsgType = type; + ssl->arrays->pendingMsgSz = size + HANDSHAKE_HEADER_SZ; + ssl->arrays->pendingMsg = (byte*)XMALLOC(size + HANDSHAKE_HEADER_SZ, + ssl->heap, + DYNAMIC_TYPE_ARRAYS); + if (ssl->arrays->pendingMsg == NULL) + return MEMORY_E; + XMEMCPY(ssl->arrays->pendingMsg, + input + *inOutIdx - HANDSHAKE_HEADER_SZ, + inputLength); + ssl->arrays->pendingMsgOffset = inputLength; + *inOutIdx += inputLength - HANDSHAKE_HEADER_SZ; + return 0; + } + + ret = DoHandShakeMsgType(ssl, input, inOutIdx, type, size, totalSz); + } + else { + word32 pendSz = + ssl->arrays->pendingMsgSz - ssl->arrays->pendingMsgOffset; + + /* Catch the case where there may be the remainder of a fragmented + * handshake message and the next handshake message in the same + * record. */ + if (inputLength > pendSz) + inputLength = pendSz; + + XMEMCPY(ssl->arrays->pendingMsg + ssl->arrays->pendingMsgOffset, + input + *inOutIdx, inputLength); + ssl->arrays->pendingMsgOffset += inputLength; + *inOutIdx += inputLength; + + if (ssl->arrays->pendingMsgOffset == ssl->arrays->pendingMsgSz) + { + word32 idx = HANDSHAKE_HEADER_SZ; + ret = DoHandShakeMsgType(ssl, + ssl->arrays->pendingMsg, + &idx, ssl->arrays->pendingMsgType, + ssl->arrays->pendingMsgSz - idx, + ssl->arrays->pendingMsgSz); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + /* setup to process fragment again */ + ssl->arrays->pendingMsgOffset -= inputLength; + *inOutIdx -= inputLength; + } + else + #endif + { + XFREE(ssl->arrays->pendingMsg, ssl->heap, DYNAMIC_TYPE_ARRAYS); + ssl->arrays->pendingMsg = NULL; + ssl->arrays->pendingMsgSz = 0; + } + } + } + + WOLFSSL_LEAVE("DoHandShakeMsg()", ret); + return ret; +} + +#endif /* !WOLFSSL_NO_TLS12 */ + +#ifdef WOLFSSL_DTLS + +static WC_INLINE int DtlsCheckWindow(WOLFSSL* ssl) +{ + word32* window; + word16 cur_hi, next_hi; + word32 cur_lo, next_lo, diff; + int curLT; + WOLFSSL_DTLS_PEERSEQ* peerSeq = NULL; + + if (!ssl->options.haveMcast) + peerSeq = ssl->keys.peerSeq; + else { +#ifdef WOLFSSL_MULTICAST + WOLFSSL_DTLS_PEERSEQ* p; + int i; + + for (i = 0, p = ssl->keys.peerSeq; + i < WOLFSSL_DTLS_PEERSEQ_SZ; + i++, p++) { + + if (p->peerId == ssl->keys.curPeerId) { + peerSeq = p; + break; + } + } +#endif + } + + if (peerSeq == NULL) { + WOLFSSL_MSG("Could not find peer sequence"); + return 0; + } + + if (ssl->keys.curEpoch == peerSeq->nextEpoch) { + next_hi = peerSeq->nextSeq_hi; + next_lo = peerSeq->nextSeq_lo; + window = peerSeq->window; + } + else if (ssl->keys.curEpoch == peerSeq->nextEpoch - 1) { + next_hi = peerSeq->prevSeq_hi; + next_lo = peerSeq->prevSeq_lo; + window = peerSeq->prevWindow; + } + else { + return 0; + } + + cur_hi = ssl->keys.curSeq_hi; + cur_lo = ssl->keys.curSeq_lo; + + /* If the difference between next and cur is > 2^32, way outside window. */ + if ((cur_hi > next_hi + 1) || (next_hi > cur_hi + 1)) { + WOLFSSL_MSG("Current record from way too far in the future."); + return 0; + } + + if (cur_hi == next_hi) { + curLT = cur_lo < next_lo; + diff = curLT ? next_lo - cur_lo : cur_lo - next_lo; + } + else { + curLT = cur_hi < next_hi; + diff = curLT ? cur_lo - next_lo : next_lo - cur_lo; + } + + /* Check to see that the next value is greater than the number of messages + * trackable in the window, and that the difference between the next + * expected sequence number and the received sequence number is inside the + * window. */ + if ((next_hi || next_lo > DTLS_SEQ_BITS) && + curLT && (diff > DTLS_SEQ_BITS)) { + + WOLFSSL_MSG("Current record sequence number from the past."); + return 0; + } +#ifndef WOLFSSL_DTLS_ALLOW_FUTURE + else if (!curLT && (diff > DTLS_SEQ_BITS)) { + WOLFSSL_MSG("Rejecting message too far into the future."); + return 0; + } +#endif + else if (curLT) { + word32 idx = diff / DTLS_WORD_BITS; + word32 newDiff = diff % DTLS_WORD_BITS; + + /* verify idx is valid for window array */ + if (idx >= WOLFSSL_DTLS_WINDOW_WORDS) { + WOLFSSL_MSG("Invalid DTLS windows index"); + return 0; + } + + if (window[idx] & (1 << (newDiff - 1))) { + WOLFSSL_MSG("Current record sequence number already received."); + return 0; + } + } + + return 1; +} + + +#ifdef WOLFSSL_MULTICAST +static WC_INLINE word32 UpdateHighwaterMark(word32 cur, word32 first, + word32 second, word32 max) +{ + word32 newCur = 0; + + if (cur < first) + newCur = first; + else if (cur < second) + newCur = second; + else if (cur < max) + newCur = max; + + return newCur; +} +#endif /* WOLFSSL_MULTICAST */ + + +static WC_INLINE int DtlsUpdateWindow(WOLFSSL* ssl) +{ + word32* window; + word32* next_lo; + word16* next_hi; + int curLT; + word32 cur_lo, diff; + word16 cur_hi; + WOLFSSL_DTLS_PEERSEQ* peerSeq = ssl->keys.peerSeq; + + cur_hi = ssl->keys.curSeq_hi; + cur_lo = ssl->keys.curSeq_lo; + +#ifdef WOLFSSL_MULTICAST + if (ssl->options.haveMcast) { + WOLFSSL_DTLS_PEERSEQ* p; + int i; + + peerSeq = NULL; + for (i = 0, p = ssl->keys.peerSeq; + i < WOLFSSL_DTLS_PEERSEQ_SZ; + i++, p++) { + + if (p->peerId == ssl->keys.curPeerId) { + peerSeq = p; + break; + } + } + + if (peerSeq == NULL) { + WOLFSSL_MSG("Couldn't find that peer ID to update window."); + return 0; + } + + if (p->highwaterMark && cur_lo >= p->highwaterMark) { + int cbError = 0; + + if (ssl->ctx->mcastHwCb) + cbError = ssl->ctx->mcastHwCb(p->peerId, + ssl->ctx->mcastMaxSeq, + cur_lo, ssl->mcastHwCbCtx); + if (cbError) { + WOLFSSL_MSG("Multicast highwater callback returned an error."); + return MCAST_HIGHWATER_CB_E; + } + + p->highwaterMark = UpdateHighwaterMark(cur_lo, + ssl->ctx->mcastFirstSeq, + ssl->ctx->mcastSecondSeq, + ssl->ctx->mcastMaxSeq); + } + } +#endif + + if (ssl->keys.curEpoch == peerSeq->nextEpoch) { + next_hi = &peerSeq->nextSeq_hi; + next_lo = &peerSeq->nextSeq_lo; + window = peerSeq->window; + } + else { + next_hi = &peerSeq->prevSeq_hi; + next_lo = &peerSeq->prevSeq_lo; + window = peerSeq->prevWindow; + } + + if (cur_hi == *next_hi) { + curLT = cur_lo < *next_lo; + diff = curLT ? *next_lo - cur_lo : cur_lo - *next_lo; + } + else { + curLT = cur_hi < *next_hi; + diff = curLT ? cur_lo - *next_lo : *next_lo - cur_lo; + } + + if (curLT) { + word32 idx = diff / DTLS_WORD_BITS; + word32 newDiff = diff % DTLS_WORD_BITS; + + if (idx < WOLFSSL_DTLS_WINDOW_WORDS) + window[idx] |= (1 << (newDiff - 1)); + } + else { + if (diff >= DTLS_SEQ_BITS) + XMEMSET(window, 0, DTLS_SEQ_SZ); + else { + word32 idx, newDiff, temp, i; + word32 oldWindow[WOLFSSL_DTLS_WINDOW_WORDS]; + + temp = 0; + diff++; + idx = diff / DTLS_WORD_BITS; + newDiff = diff % DTLS_WORD_BITS; + + XMEMCPY(oldWindow, window, sizeof(oldWindow)); + + for (i = 0; i < WOLFSSL_DTLS_WINDOW_WORDS; i++) { + if (i < idx) + window[i] = 0; + else { + temp |= (oldWindow[i-idx] << newDiff); + window[i] = temp; + temp = oldWindow[i-idx] >> (DTLS_WORD_BITS - newDiff); + } + } + } + window[0] |= 1; + *next_lo = cur_lo + 1; + if (*next_lo < cur_lo) + (*next_hi)++; + } + + return 1; +} + + +static int DtlsMsgDrain(WOLFSSL* ssl) +{ + DtlsMsg* item = ssl->dtls_rx_msg_list; + int ret = 0; + + WOLFSSL_ENTER("DtlsMsgDrain()"); + + /* While there is an item in the store list, and it is the expected + * message, and it is complete, and there hasn't been an error in the + * last message... */ + while (item != NULL && + ssl->keys.dtls_expected_peer_handshake_number == item->seq && + item->fragSz == item->sz && + ret == 0) { + word32 idx = 0; + ssl->keys.dtls_expected_peer_handshake_number++; + ret = DoHandShakeMsgType(ssl, item->msg, + &idx, item->type, item->sz, item->sz); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ssl->keys.dtls_expected_peer_handshake_number--; + break; + } + #endif + ssl->dtls_rx_msg_list = item->next; + DtlsMsgDelete(item, ssl->heap); + item = ssl->dtls_rx_msg_list; + ssl->dtls_rx_msg_list_sz--; + } + + WOLFSSL_LEAVE("DtlsMsgDrain()", ret); + return ret; +} + + +static int DoDtlsHandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, + word32 totalSz) +{ + byte type; + word32 size; + word32 fragOffset, fragSz; + int ret = 0; + + WOLFSSL_ENTER("DoDtlsHandShakeMsg()"); + + /* process any pending DTLS messages - this flow can happen with async */ + if (ssl->dtls_rx_msg_list != NULL) { + ret = DtlsMsgDrain(ssl); + if (ret != 0) + return ret; + + /* if done processing fragment exit with success */ + if (totalSz == *inOutIdx) + return ret; + } + + /* parse header */ + if (GetDtlsHandShakeHeader(ssl, input, inOutIdx, &type, + &size, &fragOffset, &fragSz, totalSz) != 0) { + WOLFSSL_ERROR(PARSE_ERROR); + return PARSE_ERROR; + } + + /* check that we have complete fragment */ + if (*inOutIdx + fragSz > totalSz) { + WOLFSSL_ERROR(INCOMPLETE_DATA); + return INCOMPLETE_DATA; + } + + /* Check the handshake sequence number first. If out of order, + * add the current message to the list. If the message is in order, + * but it is a fragment, add the current message to the list, then + * check the head of the list to see if it is complete, if so, pop + * it out as the current message. If the message is complete and in + * order, process it. Check the head of the list to see if it is in + * order, if so, process it. (Repeat until list exhausted.) If the + * head is out of order, return for more processing. + */ + if (ssl->keys.dtls_peer_handshake_number > + ssl->keys.dtls_expected_peer_handshake_number) { + /* Current message is out of order. It will get stored in the list. + * Storing also takes care of defragmentation. If the messages is a + * client hello, we need to process this out of order; the server + * is not supposed to keep state, but the second client hello will + * have a different handshake sequence number than is expected, and + * the server shouldn't be expecting any particular handshake sequence + * number. (If the cookie changes multiple times in quick succession, + * the client could be sending multiple new client hello messages + * with newer and newer cookies.) */ + if (type != client_hello) { + if (ssl->dtls_rx_msg_list_sz < DTLS_POOL_SZ) { + DtlsMsgStore(ssl, ssl->keys.dtls_peer_handshake_number, + input + *inOutIdx, size, type, + fragOffset, fragSz, ssl->heap); + } + *inOutIdx += fragSz; + ret = 0; + } + else { + ret = DoHandShakeMsgType(ssl, input, inOutIdx, type, size, totalSz); + if (ret == 0) { + ssl->keys.dtls_expected_peer_handshake_number = + ssl->keys.dtls_peer_handshake_number + 1; + } + } + } + else if (ssl->keys.dtls_peer_handshake_number < + ssl->keys.dtls_expected_peer_handshake_number) { + /* Already saw this message and processed it. It can be ignored. */ + *inOutIdx += fragSz; + if(type == finished ) { + if (*inOutIdx + ssl->keys.padSz > totalSz) { + WOLFSSL_ERROR(BUFFER_E); + return BUFFER_E; + } + *inOutIdx += ssl->keys.padSz; + } + if (IsDtlsNotSctpMode(ssl) && + VerifyForDtlsMsgPoolSend(ssl, type, fragOffset)) { + + ret = DtlsMsgPoolSend(ssl, 0); + } + } + else if (fragSz < size) { + /* Since this branch is in order, but fragmented, dtls_rx_msg_list will + * be pointing to the message with this fragment in it. Check it to see + * if it is completed. */ + if (ssl->dtls_rx_msg_list_sz < DTLS_POOL_SZ) { + DtlsMsgStore(ssl, ssl->keys.dtls_peer_handshake_number, + input + *inOutIdx, size, type, + fragOffset, fragSz, ssl->heap); + } + *inOutIdx += fragSz; + ret = 0; + if (ssl->dtls_rx_msg_list != NULL && + ssl->dtls_rx_msg_list->fragSz >= ssl->dtls_rx_msg_list->sz) + ret = DtlsMsgDrain(ssl); + } + else { + /* This branch is in order next, and a complete message. */ + ret = DoHandShakeMsgType(ssl, input, inOutIdx, type, size, totalSz); + if (ret == 0) { + if (type != client_hello || !IsDtlsNotSctpMode(ssl)) + ssl->keys.dtls_expected_peer_handshake_number++; + if (ssl->dtls_rx_msg_list != NULL) { + ret = DtlsMsgDrain(ssl); + } + } + } + + WOLFSSL_LEAVE("DoDtlsHandShakeMsg()", ret); + return ret; +} +#endif + +#ifndef WOLFSSL_NO_TLS12 + +#ifdef HAVE_AEAD + +#if !defined(NO_PUBLIC_GCM_SET_IV) && \ + (((defined(HAVE_FIPS) || defined(HAVE_SELFTEST)) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))) || \ + (defined(HAVE_POLY1305) && defined(HAVE_CHACHA))) +static WC_INLINE void AeadIncrementExpIV(WOLFSSL* ssl) +{ + int i; + for (i = AEAD_MAX_EXP_SZ-1; i >= 0; i--) { + if (++ssl->keys.aead_exp_IV[i]) return; + } +} +#endif + + +#if defined(HAVE_POLY1305) && defined(HAVE_CHACHA) +/* Used for the older version of creating AEAD tags with Poly1305 */ +static int Poly1305TagOld(WOLFSSL* ssl, byte* additional, const byte* out, + byte* cipher, word16 sz, byte* tag) +{ + int ret = 0; + int msglen = (sz - ssl->specs.aead_mac_size); + word32 keySz = 32; + byte padding[8]; /* used to temporarily store lengths */ + +#ifdef CHACHA_AEAD_TEST + printf("Using old version of poly1305 input.\n"); +#endif + + if (msglen < 0) + return INPUT_CASE_ERROR; + + if ((ret = wc_Poly1305SetKey(ssl->auth.poly1305, cipher, keySz)) != 0) + return ret; + + if ((ret = wc_Poly1305Update(ssl->auth.poly1305, additional, + AEAD_AUTH_DATA_SZ)) != 0) + return ret; + + /* length of additional input plus padding */ + XMEMSET(padding, 0, sizeof(padding)); + padding[0] = AEAD_AUTH_DATA_SZ; + if ((ret = wc_Poly1305Update(ssl->auth.poly1305, padding, + sizeof(padding))) != 0) + return ret; + + + /* add cipher info and then its length */ + XMEMSET(padding, 0, sizeof(padding)); + if ((ret = wc_Poly1305Update(ssl->auth.poly1305, out, msglen)) != 0) + return ret; + + /* 32 bit size of cipher to 64 bit endian */ + padding[0] = msglen & 0xff; + padding[1] = (msglen >> 8) & 0xff; + padding[2] = ((word32)msglen >> 16) & 0xff; + padding[3] = ((word32)msglen >> 24) & 0xff; + if ((ret = wc_Poly1305Update(ssl->auth.poly1305, padding, sizeof(padding))) + != 0) + return ret; + + /* generate tag */ + if ((ret = wc_Poly1305Final(ssl->auth.poly1305, tag)) != 0) + return ret; + + return ret; +} + + +/* When the flag oldPoly is not set this follows RFC7905. When oldPoly is set + * the implementation follows an older draft for creating the nonce and MAC. + * The flag oldPoly gets set automatically depending on what cipher suite was + * negotiated in the handshake. This is able to be done because the IDs for the + * cipher suites was updated in RFC7905 giving unique values for the older + * draft in comparison to the more recent RFC. + * + * ssl WOLFSSL structure to get cipher and TLS state from + * out output buffer to hold encrypted data + * input data to encrypt + * sz size of input + * + * Return 0 on success negative values in error case + */ +static int ChachaAEADEncrypt(WOLFSSL* ssl, byte* out, const byte* input, + word16 sz) +{ + const byte* additionalSrc = input - RECORD_HEADER_SZ; + int ret = 0; + word32 msgLen = (sz - ssl->specs.aead_mac_size); + byte tag[POLY1305_AUTH_SZ]; + byte add[AEAD_AUTH_DATA_SZ]; + byte nonce[CHACHA20_NONCE_SZ]; + byte poly[CHACHA20_256_KEY_SIZE]; /* generated key for poly1305 */ + #ifdef CHACHA_AEAD_TEST + int i; + #endif + + XMEMSET(tag, 0, sizeof(tag)); + XMEMSET(nonce, 0, sizeof(nonce)); + XMEMSET(poly, 0, sizeof(poly)); + XMEMSET(add, 0, sizeof(add)); + + /* opaque SEQ number stored for AD */ + WriteSEQ(ssl, CUR_ORDER, add); + + if (ssl->options.oldPoly != 0) { + /* get nonce. SEQ should not be incremented again here */ + XMEMCPY(nonce + CHACHA20_OLD_OFFSET, add, OPAQUE32_LEN * 2); + } + + /* Store the type, version. Unfortunately, they are in + * the input buffer ahead of the plaintext. */ + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + additionalSrc -= DTLS_HANDSHAKE_EXTRA; + DtlsSEQIncrement(ssl, CUR_ORDER); + } + #endif + + /* add TLS message size to additional data */ + add[AEAD_AUTH_DATA_SZ - 2] = (msgLen >> 8) & 0xff; + add[AEAD_AUTH_DATA_SZ - 1] = msgLen & 0xff; + + XMEMCPY(add + AEAD_TYPE_OFFSET, additionalSrc, 3); + + #ifdef CHACHA_AEAD_TEST + printf("Encrypt Additional : "); + for (i = 0; i < AEAD_AUTH_DATA_SZ; i++) { + printf("%02x", add[i]); + } + printf("\n\n"); + printf("input before encryption :\n"); + for (i = 0; i < sz; i++) { + printf("%02x", input[i]); + if ((i + 1) % 16 == 0) + printf("\n"); + } + printf("\n"); + #endif + + if (ssl->options.oldPoly == 0) { + /* nonce is formed by 4 0x00 byte padded to the left followed by 8 byte + * record sequence number XORed with client_write_IV/server_write_IV */ + XMEMCPY(nonce, ssl->keys.aead_enc_imp_IV, CHACHA20_IMP_IV_SZ); + nonce[4] ^= add[0]; + nonce[5] ^= add[1]; + nonce[6] ^= add[2]; + nonce[7] ^= add[3]; + nonce[8] ^= add[4]; + nonce[9] ^= add[5]; + nonce[10] ^= add[6]; + nonce[11] ^= add[7]; + } + + /* set the nonce for chacha and get poly1305 key */ + if ((ret = wc_Chacha_SetIV(ssl->encrypt.chacha, nonce, 0)) != 0) { + ForceZero(nonce, CHACHA20_NONCE_SZ); + return ret; + } + + ForceZero(nonce, CHACHA20_NONCE_SZ); /* done with nonce, clear it */ + /* create Poly1305 key using chacha20 keystream */ + if ((ret = wc_Chacha_Process(ssl->encrypt.chacha, poly, + poly, sizeof(poly))) != 0) + return ret; + + /* encrypt the plain text */ + if ((ret = wc_Chacha_Process(ssl->encrypt.chacha, out, + input, msgLen)) != 0) { + ForceZero(poly, sizeof(poly)); + return ret; + } + + /* get the poly1305 tag using either old padding scheme or more recent */ + if (ssl->options.oldPoly != 0) { + if ((ret = Poly1305TagOld(ssl, add, (const byte* )out, + poly, sz, tag)) != 0) { + ForceZero(poly, sizeof(poly)); + return ret; + } + } + else { + if ((ret = wc_Poly1305SetKey(ssl->auth.poly1305, poly, + sizeof(poly))) != 0) { + ForceZero(poly, sizeof(poly)); + return ret; + } + if ((ret = wc_Poly1305_MAC(ssl->auth.poly1305, add, + sizeof(add), out, msgLen, tag, sizeof(tag))) != 0) { + ForceZero(poly, sizeof(poly)); + return ret; + } + } + ForceZero(poly, sizeof(poly)); /* done with poly1305 key, clear it */ + + /* append tag to ciphertext */ + XMEMCPY(out + msgLen, tag, sizeof(tag)); + + AeadIncrementExpIV(ssl); + + #ifdef CHACHA_AEAD_TEST + printf("mac tag :\n"); + for (i = 0; i < 16; i++) { + printf("%02x", tag[i]); + if ((i + 1) % 16 == 0) + printf("\n"); + } + printf("\n\noutput after encrypt :\n"); + for (i = 0; i < sz; i++) { + printf("%02x", out[i]); + if ((i + 1) % 16 == 0) + printf("\n"); + } + printf("\n"); + #endif + + return ret; +} + + +/* When the flag oldPoly is not set this follows RFC7905. When oldPoly is set + * the implementation follows an older draft for creating the nonce and MAC. + * The flag oldPoly gets set automatically depending on what cipher suite was + * negotiated in the handshake. This is able to be done because the IDs for the + * cipher suites was updated in RFC7905 giving unique values for the older + * draft in comparison to the more recent RFC. + * + * ssl WOLFSSL structure to get cipher and TLS state from + * plain output buffer to hold decrypted data + * input data to decrypt + * sz size of input + * + * Return 0 on success negative values in error case + */ +static int ChachaAEADDecrypt(WOLFSSL* ssl, byte* plain, const byte* input, + word16 sz) +{ + byte add[AEAD_AUTH_DATA_SZ]; + byte nonce[CHACHA20_NONCE_SZ]; + byte tag[POLY1305_AUTH_SZ]; + byte poly[CHACHA20_256_KEY_SIZE]; /* generated key for mac */ + int ret = 0; + int msgLen = (sz - ssl->specs.aead_mac_size); + + #ifdef CHACHA_AEAD_TEST + int i; + printf("input before decrypt :\n"); + for (i = 0; i < sz; i++) { + printf("%02x", input[i]); + if ((i + 1) % 16 == 0) + printf("\n"); + } + printf("\n"); + #endif + + XMEMSET(tag, 0, sizeof(tag)); + XMEMSET(poly, 0, sizeof(poly)); + XMEMSET(nonce, 0, sizeof(nonce)); + XMEMSET(add, 0, sizeof(add)); + + /* sequence number field is 64-bits */ + WriteSEQ(ssl, PEER_ORDER, add); + + if (ssl->options.oldPoly != 0) { + /* get nonce, SEQ should not be incremented again here */ + XMEMCPY(nonce + CHACHA20_OLD_OFFSET, add, OPAQUE32_LEN * 2); + } + + /* get AD info */ + /* Store the type, version. */ + add[AEAD_TYPE_OFFSET] = ssl->curRL.type; + add[AEAD_VMAJ_OFFSET] = ssl->curRL.pvMajor; + add[AEAD_VMIN_OFFSET] = ssl->curRL.pvMinor; + + /* add TLS message size to additional data */ + add[AEAD_AUTH_DATA_SZ - 2] = (msgLen >> 8) & 0xff; + add[AEAD_AUTH_DATA_SZ - 1] = msgLen & 0xff; + + #ifdef CHACHA_AEAD_TEST + printf("Decrypt Additional : "); + for (i = 0; i < AEAD_AUTH_DATA_SZ; i++) { + printf("%02x", add[i]); + } + printf("\n\n"); + #endif + + if (ssl->options.oldPoly == 0) { + /* nonce is formed by 4 0x00 byte padded to the left followed by 8 byte + * record sequence number XORed with client_write_IV/server_write_IV */ + XMEMCPY(nonce, ssl->keys.aead_dec_imp_IV, CHACHA20_IMP_IV_SZ); + nonce[4] ^= add[0]; + nonce[5] ^= add[1]; + nonce[6] ^= add[2]; + nonce[7] ^= add[3]; + nonce[8] ^= add[4]; + nonce[9] ^= add[5]; + nonce[10] ^= add[6]; + nonce[11] ^= add[7]; + } + + /* set nonce and get poly1305 key */ + if ((ret = wc_Chacha_SetIV(ssl->decrypt.chacha, nonce, 0)) != 0) { + ForceZero(nonce, CHACHA20_NONCE_SZ); + return ret; + } + + ForceZero(nonce, CHACHA20_NONCE_SZ); /* done with nonce, clear it */ + /* use chacha20 keystream to get poly1305 key for tag */ + if ((ret = wc_Chacha_Process(ssl->decrypt.chacha, poly, + poly, sizeof(poly))) != 0) + return ret; + + /* get the tag using Poly1305 */ + if (ssl->options.oldPoly != 0) { + if ((ret = Poly1305TagOld(ssl, add, input, poly, sz, tag)) != 0) { + ForceZero(poly, sizeof(poly)); + return ret; + } + } + else { + if ((ret = wc_Poly1305SetKey(ssl->auth.poly1305, poly, + sizeof(poly))) != 0) { + ForceZero(poly, sizeof(poly)); + return ret; + } + if ((ret = wc_Poly1305_MAC(ssl->auth.poly1305, add, + sizeof(add), (byte*)input, msgLen, tag, sizeof(tag))) != 0) { + ForceZero(poly, sizeof(poly)); + return ret; + } + } + ForceZero(poly, sizeof(poly)); /* done with poly1305 key, clear it */ + + /* check tag sent along with packet */ + if (ConstantCompare(input + msgLen, tag, ssl->specs.aead_mac_size) != 0) { + WOLFSSL_MSG("MAC did not match"); + if (!ssl->options.dtls) + SendAlert(ssl, alert_fatal, bad_record_mac); + return VERIFY_MAC_ERROR; + } + + /* if the tag was good decrypt message */ + if ((ret = wc_Chacha_Process(ssl->decrypt.chacha, plain, + input, msgLen)) != 0) + return ret; + + #ifdef CHACHA_AEAD_TEST + printf("plain after decrypt :\n"); + for (i = 0; i < sz; i++) { + printf("%02x", plain[i]); + if ((i + 1) % 16 == 0) + printf("\n"); + } + printf("\n"); + #endif + + return ret; +} +#endif /* HAVE_CHACHA && HAVE_POLY1305 */ +#endif /* HAVE_AEAD */ + + +#if defined(BUILD_AESGCM) || defined(HAVE_AESCCM) + +#if !defined(NO_GCM_ENCRYPT_EXTRA) && \ + ((!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2))) +/* The following type is used to share code between AES-GCM and AES-CCM. */ + typedef int (*AesAuthEncryptFunc)(Aes* aes, byte* out, + const byte* in, word32 sz, + byte* iv, word32 ivSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz); + #define AES_AUTH_ENCRYPT_FUNC AesAuthEncryptFunc + #define AES_GCM_ENCRYPT wc_AesGcmEncrypt_ex + #define AES_CCM_ENCRYPT wc_AesCcmEncrypt_ex +#else + #define AES_AUTH_ENCRYPT_FUNC wc_AesAuthEncryptFunc + #define AES_GCM_ENCRYPT wc_AesGcmEncrypt + #define AES_CCM_ENCRYPT wc_AesCcmEncrypt +#endif + +#endif + + +static WC_INLINE int EncryptDo(WOLFSSL* ssl, byte* out, const byte* input, + word16 sz, int asyncOkay) +{ + int ret = 0; +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV* asyncDev = NULL; + word32 event_flags = WC_ASYNC_FLAG_CALL_AGAIN; +#else + (void)asyncOkay; +#endif + + (void)out; + (void)input; + (void)sz; + + switch (ssl->specs.bulk_cipher_algorithm) { + #ifdef BUILD_ARC4 + case wolfssl_rc4: + wc_Arc4Process(ssl->encrypt.arc4, out, input, sz); + break; + #endif + + #ifdef BUILD_DES3 + case wolfssl_triple_des: + #ifdef WOLFSSL_ASYNC_CRYPT + /* initialize event */ + asyncDev = &ssl->encrypt.des3->asyncDev; + ret = wolfSSL_AsyncInit(ssl, asyncDev, event_flags); + if (ret != 0) + break; + #endif + + ret = wc_Des3_CbcEncrypt(ssl->encrypt.des3, out, input, sz); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E && asyncOkay) { + ret = wolfSSL_AsyncPush(ssl, asyncDev); + } + #endif + break; + #endif + + #if defined(BUILD_AES) && defined(HAVE_AES_CBC) + case wolfssl_aes: + #ifdef WOLFSSL_ASYNC_CRYPT + /* initialize event */ + asyncDev = &ssl->encrypt.aes->asyncDev; + ret = wolfSSL_AsyncInit(ssl, asyncDev, event_flags); + if (ret != 0) + break; + #endif + + ret = wc_AesCbcEncrypt(ssl->encrypt.aes, out, input, sz); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E && asyncOkay) { + ret = wolfSSL_AsyncPush(ssl, asyncDev); + } + #endif + break; + #endif + + #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM) + case wolfssl_aes_gcm: + case wolfssl_aes_ccm:/* GCM AEAD macros use same size as CCM */ + { + AES_AUTH_ENCRYPT_FUNC aes_auth_fn; + const byte* additionalSrc; + + #ifdef WOLFSSL_ASYNC_CRYPT + /* initialize event */ + asyncDev = &ssl->encrypt.aes->asyncDev; + ret = wolfSSL_AsyncInit(ssl, asyncDev, event_flags); + if (ret != 0) + break; + #endif + + #if defined(BUILD_AESGCM) && defined(HAVE_AESCCM) + aes_auth_fn = (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm) + ? AES_GCM_ENCRYPT : AES_CCM_ENCRYPT; + #elif defined(BUILD_AESGCM) + aes_auth_fn = AES_GCM_ENCRYPT; + #else + aes_auth_fn = AES_CCM_ENCRYPT; + #endif + additionalSrc = input - 5; + + XMEMSET(ssl->encrypt.additional, 0, AEAD_AUTH_DATA_SZ); + + /* sequence number field is 64-bits */ + WriteSEQ(ssl, CUR_ORDER, ssl->encrypt.additional); + + /* Store the type, version. Unfortunately, they are in + * the input buffer ahead of the plaintext. */ + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + additionalSrc -= DTLS_HANDSHAKE_EXTRA; + } + #endif + XMEMCPY(ssl->encrypt.additional + AEAD_TYPE_OFFSET, + additionalSrc, 3); + + /* Store the length of the plain text minus the explicit + * IV length minus the authentication tag size. */ + c16toa(sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, + ssl->encrypt.additional + AEAD_LEN_OFFSET); +#if !defined(NO_PUBLIC_GCM_SET_IV) && \ + ((defined(HAVE_FIPS) || defined(HAVE_SELFTEST)) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))) + XMEMCPY(ssl->encrypt.nonce, + ssl->keys.aead_enc_imp_IV, AESGCM_IMP_IV_SZ); + XMEMCPY(ssl->encrypt.nonce + AESGCM_IMP_IV_SZ, + ssl->keys.aead_exp_IV, AESGCM_EXP_IV_SZ); +#endif + ret = aes_auth_fn(ssl->encrypt.aes, + out + AESGCM_EXP_IV_SZ, input + AESGCM_EXP_IV_SZ, + sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, + ssl->encrypt.nonce, AESGCM_NONCE_SZ, + out + sz - ssl->specs.aead_mac_size, + ssl->specs.aead_mac_size, + ssl->encrypt.additional, AEAD_AUTH_DATA_SZ); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E && asyncOkay) { + ret = wolfSSL_AsyncPush(ssl, asyncDev); + } + #endif +#if !defined(NO_PUBLIC_GCM_SET_IV) && \ + ((!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2))) + XMEMCPY(out, + ssl->encrypt.nonce + AESGCM_IMP_IV_SZ, AESGCM_EXP_IV_SZ); +#endif + } + break; + #endif /* BUILD_AESGCM || HAVE_AESCCM */ + + #ifdef HAVE_CAMELLIA + case wolfssl_camellia: + ret = wc_CamelliaCbcEncrypt(ssl->encrypt.cam, out, input, sz); + break; + #endif + + #ifdef HAVE_HC128 + case wolfssl_hc128: + ret = wc_Hc128_Process(ssl->encrypt.hc128, out, input, sz); + break; + #endif + + #ifdef BUILD_RABBIT + case wolfssl_rabbit: + ret = wc_RabbitProcess(ssl->encrypt.rabbit, out, input, sz); + break; + #endif + + #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) + case wolfssl_chacha: + ret = ChachaAEADEncrypt(ssl, out, input, sz); + break; + #endif + + #ifdef HAVE_NULL_CIPHER + case wolfssl_cipher_null: + if (input != out) { + XMEMMOVE(out, input, sz); + } + break; + #endif + + #ifdef HAVE_IDEA + case wolfssl_idea: + ret = wc_IdeaCbcEncrypt(ssl->encrypt.idea, out, input, sz); + break; + #endif + + default: + WOLFSSL_MSG("wolfSSL Encrypt programming error"); + ret = ENCRYPT_ERROR; + } + +#ifdef WOLFSSL_ASYNC_CRYPT + /* if async is not okay, then block */ + if (ret == WC_PENDING_E && !asyncOkay) { + ret = wc_AsyncWait(ret, asyncDev, event_flags); + } +#endif + + return ret; +} + +static WC_INLINE int Encrypt(WOLFSSL* ssl, byte* out, const byte* input, word16 sz, + int asyncOkay) +{ + int ret = 0; + +#ifdef WOLFSSL_ASYNC_CRYPT + if (ssl->error == WC_PENDING_E) { + ssl->error = 0; /* clear async */ + } +#endif + + switch (ssl->encrypt.state) { + case CIPHER_STATE_BEGIN: + { + if (ssl->encrypt.setup == 0) { + WOLFSSL_MSG("Encrypt ciphers not setup"); + return ENCRYPT_ERROR; + } + + #ifdef HAVE_FUZZER + if (ssl->fuzzerCb) + ssl->fuzzerCb(ssl, input, sz, FUZZ_ENCRYPT, ssl->fuzzerCtx); + #endif + + #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM) + /* make sure AES GCM/CCM memory is allocated */ + /* free for these happens in FreeCiphers */ + if (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_ccm || + ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm) { + /* make sure auth iv and auth are allocated */ + if (ssl->encrypt.additional == NULL) + ssl->encrypt.additional = (byte*)XMALLOC(AEAD_AUTH_DATA_SZ, + ssl->heap, DYNAMIC_TYPE_AES_BUFFER); + if (ssl->encrypt.nonce == NULL) + ssl->encrypt.nonce = (byte*)XMALLOC(AESGCM_NONCE_SZ, + ssl->heap, DYNAMIC_TYPE_AES_BUFFER); + if (ssl->encrypt.additional == NULL || + ssl->encrypt.nonce == NULL) { + return MEMORY_E; + } + } + #endif /* BUILD_AESGCM || HAVE_AESCCM */ + + /* Advance state and proceed */ + ssl->encrypt.state = CIPHER_STATE_DO; + } + FALL_THROUGH; + + case CIPHER_STATE_DO: + { + ret = EncryptDo(ssl, out, input, sz, asyncOkay); + + /* Advance state */ + ssl->encrypt.state = CIPHER_STATE_END; + + #ifdef WOLFSSL_ASYNC_CRYPT + /* If pending, then leave and return will resume below */ + if (ret == WC_PENDING_E) { + return ret; + } + #endif + } + FALL_THROUGH; + + case CIPHER_STATE_END: + { + #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM) + if (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_ccm || + ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm) + { + /* finalize authentication cipher */ +#if !defined(NO_PUBLIC_GCM_SET_IV) && \ + ((defined(HAVE_FIPS) || defined(HAVE_SELFTEST)) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))) + AeadIncrementExpIV(ssl); +#endif + if (ssl->encrypt.nonce) + ForceZero(ssl->encrypt.nonce, AESGCM_NONCE_SZ); + + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + DtlsSEQIncrement(ssl, CUR_ORDER); + #endif + } + #endif /* BUILD_AESGCM || HAVE_AESCCM */ + break; + } + } + + /* Reset state */ + ssl->encrypt.state = CIPHER_STATE_BEGIN; + + return ret; +} + + +static WC_INLINE int DecryptDo(WOLFSSL* ssl, byte* plain, const byte* input, + word16 sz) +{ + int ret = 0; + + (void)plain; + (void)input; + (void)sz; + + switch (ssl->specs.bulk_cipher_algorithm) + { + #ifdef BUILD_ARC4 + case wolfssl_rc4: + wc_Arc4Process(ssl->decrypt.arc4, plain, input, sz); + break; + #endif + + #ifdef BUILD_DES3 + case wolfssl_triple_des: + #ifdef WOLFSSL_ASYNC_CRYPT + /* initialize event */ + ret = wolfSSL_AsyncInit(ssl, &ssl->decrypt.des3->asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + if (ret != 0) + break; + #endif + + ret = wc_Des3_CbcDecrypt(ssl->decrypt.des3, plain, input, sz); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, &ssl->decrypt.des3->asyncDev); + } + #endif + break; + #endif + + #if defined(BUILD_AES) && defined(HAVE_AES_CBC) + case wolfssl_aes: + #ifdef WOLFSSL_ASYNC_CRYPT + /* initialize event */ + ret = wolfSSL_AsyncInit(ssl, &ssl->decrypt.aes->asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + if (ret != 0) + break; + #endif + + ret = wc_AesCbcDecrypt(ssl->decrypt.aes, plain, input, sz); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, &ssl->decrypt.aes->asyncDev); + } + #endif + break; + #endif + + #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM) + case wolfssl_aes_gcm: + case wolfssl_aes_ccm: /* GCM AEAD macros use same size as CCM */ + { + wc_AesAuthDecryptFunc aes_auth_fn; + + #ifdef WOLFSSL_ASYNC_CRYPT + /* initialize event */ + ret = wolfSSL_AsyncInit(ssl, &ssl->decrypt.aes->asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + if (ret != 0) + break; + #endif + + #if defined(BUILD_AESGCM) && defined(HAVE_AESCCM) + aes_auth_fn = (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm) + ? wc_AesGcmDecrypt : wc_AesCcmDecrypt; + #elif defined(BUILD_AESGCM) + aes_auth_fn = wc_AesGcmDecrypt; + #else + aes_auth_fn = wc_AesCcmDecrypt; + #endif + + XMEMSET(ssl->decrypt.additional, 0, AEAD_AUTH_DATA_SZ); + + /* sequence number field is 64-bits */ + WriteSEQ(ssl, PEER_ORDER, ssl->decrypt.additional); + + ssl->decrypt.additional[AEAD_TYPE_OFFSET] = ssl->curRL.type; + ssl->decrypt.additional[AEAD_VMAJ_OFFSET] = ssl->curRL.pvMajor; + ssl->decrypt.additional[AEAD_VMIN_OFFSET] = ssl->curRL.pvMinor; + + c16toa(sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, + ssl->decrypt.additional + AEAD_LEN_OFFSET); + XMEMCPY(ssl->decrypt.nonce, ssl->keys.aead_dec_imp_IV, + AESGCM_IMP_IV_SZ); + XMEMCPY(ssl->decrypt.nonce + AESGCM_IMP_IV_SZ, input, + AESGCM_EXP_IV_SZ); + if ((ret = aes_auth_fn(ssl->decrypt.aes, + plain + AESGCM_EXP_IV_SZ, + input + AESGCM_EXP_IV_SZ, + sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, + ssl->decrypt.nonce, AESGCM_NONCE_SZ, + input + sz - ssl->specs.aead_mac_size, + ssl->specs.aead_mac_size, + ssl->decrypt.additional, AEAD_AUTH_DATA_SZ)) < 0) { + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, &ssl->decrypt.aes->asyncDev); + } + #endif + } + } + break; + #endif /* BUILD_AESGCM || HAVE_AESCCM */ + + #ifdef HAVE_CAMELLIA + case wolfssl_camellia: + ret = wc_CamelliaCbcDecrypt(ssl->decrypt.cam, plain, input, sz); + break; + #endif + + #ifdef HAVE_HC128 + case wolfssl_hc128: + ret = wc_Hc128_Process(ssl->decrypt.hc128, plain, input, sz); + break; + #endif + + #ifdef BUILD_RABBIT + case wolfssl_rabbit: + ret = wc_RabbitProcess(ssl->decrypt.rabbit, plain, input, sz); + break; + #endif + + #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) + case wolfssl_chacha: + ret = ChachaAEADDecrypt(ssl, plain, input, sz); + break; + #endif + + #ifdef HAVE_NULL_CIPHER + case wolfssl_cipher_null: + if (input != plain) { + XMEMMOVE(plain, input, sz); + } + break; + #endif + + #ifdef HAVE_IDEA + case wolfssl_idea: + ret = wc_IdeaCbcDecrypt(ssl->decrypt.idea, plain, input, sz); + break; + #endif + + default: + WOLFSSL_MSG("wolfSSL Decrypt programming error"); + ret = DECRYPT_ERROR; + } + + return ret; +} + +static WC_INLINE int Decrypt(WOLFSSL* ssl, byte* plain, const byte* input, + word16 sz) +{ + int ret = 0; + +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfSSL_AsyncPop(ssl, &ssl->decrypt.state); + if (ret != WC_NOT_PENDING_E) { + /* check for still pending */ + if (ret == WC_PENDING_E) + return ret; + + ssl->error = 0; /* clear async */ + + /* let failures through so CIPHER_STATE_END logic is run */ + } + else +#endif + { + /* Reset state */ + ret = 0; + ssl->decrypt.state = CIPHER_STATE_BEGIN; + } + + switch (ssl->decrypt.state) { + case CIPHER_STATE_BEGIN: + { + if (ssl->decrypt.setup == 0) { + WOLFSSL_MSG("Decrypt ciphers not setup"); + return DECRYPT_ERROR; + } + + #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM) + /* make sure AES GCM/CCM memory is allocated */ + /* free for these happens in FreeCiphers */ + if (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_ccm || + ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm) { + /* make sure auth iv and auth are allocated */ + if (ssl->decrypt.additional == NULL) + ssl->decrypt.additional = (byte*)XMALLOC(AEAD_AUTH_DATA_SZ, + ssl->heap, DYNAMIC_TYPE_AES_BUFFER); + if (ssl->decrypt.nonce == NULL) + ssl->decrypt.nonce = (byte*)XMALLOC(AESGCM_NONCE_SZ, + ssl->heap, DYNAMIC_TYPE_AES_BUFFER); + if (ssl->decrypt.additional == NULL || + ssl->decrypt.nonce == NULL) { + return MEMORY_E; + } + } + #endif /* BUILD_AESGCM || HAVE_AESCCM */ + + /* Advance state and proceed */ + ssl->decrypt.state = CIPHER_STATE_DO; + } + FALL_THROUGH; + case CIPHER_STATE_DO: + { + ret = DecryptDo(ssl, plain, input, sz); + + /* Advance state */ + ssl->decrypt.state = CIPHER_STATE_END; + + #ifdef WOLFSSL_ASYNC_CRYPT + /* If pending, leave and return below */ + if (ret == WC_PENDING_E) { + return ret; + } + #endif + } + FALL_THROUGH; + case CIPHER_STATE_END: + { + #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM) + /* make sure AES GCM/CCM nonce is cleared */ + if (ssl->specs.bulk_cipher_algorithm == wolfssl_aes_ccm || + ssl->specs.bulk_cipher_algorithm == wolfssl_aes_gcm) { + if (ssl->decrypt.nonce) + ForceZero(ssl->decrypt.nonce, AESGCM_NONCE_SZ); + + if (ret < 0) + ret = VERIFY_MAC_ERROR; + } + #endif /* BUILD_AESGCM || HAVE_AESCCM */ + break; + } + } + + /* Reset state */ + ssl->decrypt.state = CIPHER_STATE_BEGIN; + + /* handle mac error case */ + if (ret == VERIFY_MAC_ERROR) { + if (!ssl->options.dtls) + SendAlert(ssl, alert_fatal, bad_record_mac); + + #ifdef WOLFSSL_DTLS_DROP_STATS + ssl->macDropCount++; + #endif /* WOLFSSL_DTLS_DROP_STATS */ + } + + return ret; +} + +#endif /* !WOLFSSL_NO_TLS12 */ + +/* Check conditions for a cipher to have an explicit IV. + * + * ssl The SSL/TLS object. + * returns 1 if the cipher in use has an explicit IV and 0 otherwise. + */ +static WC_INLINE int CipherHasExpIV(WOLFSSL *ssl) +{ +#ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) + return 0; +#endif + return (ssl->specs.cipher_type == aead) && + (ssl->specs.bulk_cipher_algorithm != wolfssl_chacha); +} + +/* check cipher text size for sanity */ +static int SanityCheckCipherText(WOLFSSL* ssl, word32 encryptSz) +{ +#ifdef HAVE_TRUNCATED_HMAC + word32 minLength = ssl->truncated_hmac ? (byte)TRUNCATED_HMAC_SZ + : ssl->specs.hash_size; +#else + word32 minLength = ssl->specs.hash_size; /* covers stream */ +#endif + +#ifndef WOLFSSL_AEAD_ONLY + if (ssl->specs.cipher_type == block) { + if (encryptSz % ssl->specs.block_size) { + WOLFSSL_MSG("Block ciphertext not block size"); + return SANITY_CIPHER_E; + } + + minLength++; /* pad byte */ + + if (ssl->specs.block_size > minLength) + minLength = ssl->specs.block_size; + + if (ssl->options.tls1_1) + minLength += ssl->specs.block_size; /* explicit IV */ + } + else +#endif + if (ssl->specs.cipher_type == aead) { + minLength = ssl->specs.aead_mac_size; /* authTag size */ + if (CipherHasExpIV(ssl)) + minLength += AESGCM_EXP_IV_SZ; /* explicit IV */ + } + + if (encryptSz < minLength) { + WOLFSSL_MSG("Ciphertext not minimum size"); + return SANITY_CIPHER_E; + } + + return 0; +} + + +#ifndef WOLFSSL_AEAD_ONLY +/* check all length bytes for the pad value, return 0 on success */ +static int PadCheck(const byte* a, byte pad, int length) +{ + int i; + int compareSum = 0; + + for (i = 0; i < length; i++) { + compareSum |= a[i] ^ pad; + } + + return compareSum; +} + + +/* Mask the padding bytes with the expected values. + * Constant time implementation - does maximum pad size possible. + * + * data Message data. + * sz Size of the message including MAC and padding and padding length. + * macSz Size of the MAC. + * returns 0 on success, otherwise failure. + */ +static byte MaskPadding(const byte* data, int sz, int macSz) +{ + int i; + int checkSz = sz - 1; + byte paddingSz = data[sz - 1]; + byte mask; + byte good = ctMaskGT(paddingSz, sz - 1 - macSz); + + if (checkSz > TLS_MAX_PAD_SZ) + checkSz = TLS_MAX_PAD_SZ; + + for (i = 0; i < checkSz; i++) { + mask = ctMaskLTE(i, paddingSz); + good |= mask & (data[sz - 1 - i] ^ paddingSz); + } + + return good; +} + +/* Mask the MAC in the message with the MAC calculated. + * Constant time implementation - starts looking for MAC where maximum padding + * size has it. + * + * data Message data. + * sz Size of the message including MAC and padding and padding length. + * macSz Size of the MAC data. + * expMac Expected MAC value. + * returns 0 on success, otherwise failure. + */ +static byte MaskMac(const byte* data, int sz, int macSz, byte* expMac) +{ + int i, j; + unsigned char mac[WC_MAX_DIGEST_SIZE]; + int scanStart = sz - 1 - TLS_MAX_PAD_SZ - macSz; + int macEnd = sz - 1 - data[sz - 1]; + int macStart = macEnd - macSz; + int r = 0; + unsigned char started, notEnded; + unsigned char good = 0; + + scanStart &= (~scanStart) >> (sizeof(int) * 8 - 1); + macStart &= (~macStart) >> (sizeof(int) * 8 - 1); + + /* Div on Intel has different speeds depending on value. + * Use a bitwise AND or mod a specific value (converted to mul). */ + if ((macSz & (macSz - 1)) == 0) + r = (macSz - (scanStart - macStart)) & (macSz - 1); +#ifndef NO_SHA + else if (macSz == WC_SHA_DIGEST_SIZE) + r = (macSz - (scanStart - macStart)) % WC_SHA_DIGEST_SIZE; +#endif +#ifdef WOLFSSL_SHA384 + else if (macSz == WC_SHA384_DIGEST_SIZE) + r = (macSz - (scanStart - macStart)) % WC_SHA384_DIGEST_SIZE; +#endif + + XMEMSET(mac, 0, macSz); + for (i = scanStart; i < sz; i += macSz) { + for (j = 0; j < macSz && j + i < sz; j++) { + started = ctMaskGTE(i + j, macStart); + notEnded = ctMaskLT(i + j, macEnd); + mac[j] |= started & notEnded & data[i + j]; + } + } + + if ((macSz & (macSz - 1)) == 0) { + for (i = 0; i < macSz; i++) + good |= expMac[i] ^ mac[(i + r) & (macSz - 1)]; + } +#ifndef NO_SHA + else if (macSz == WC_SHA_DIGEST_SIZE) { + for (i = 0; i < macSz; i++) + good |= expMac[i] ^ mac[(i + r) % WC_SHA_DIGEST_SIZE]; + } +#endif +#ifdef WOLFSSL_SHA384 + else if (macSz == WC_SHA384_DIGEST_SIZE) { + for (i = 0; i < macSz; i++) + good |= expMac[i] ^ mac[(i + r) % WC_SHA384_DIGEST_SIZE]; + } +#endif + + return good; +} + +/* timing resistant pad/verify check, return 0 on success */ +int TimingPadVerify(WOLFSSL* ssl, const byte* input, int padLen, int macSz, + int pLen, int content) +{ + byte verify[WC_MAX_DIGEST_SIZE]; + byte good; + int ret = 0; + + good = MaskPadding(input, pLen, macSz); + /* 4th argument has potential to underflow, ssl->hmac function should + * either increment the size by (macSz + padLen + 1) before use or check on + * the size to make sure is valid. */ + ret = ssl->hmac(ssl, verify, input, pLen - macSz - padLen - 1, padLen, + content, 1); + good |= MaskMac(input, pLen, ssl->specs.hash_size, verify); + + /* Non-zero on failure. */ + good = (byte)~(word32)good; + good &= good >> 4; + good &= good >> 2; + good &= good >> 1; + /* Make ret negative on masking failure. */ + ret -= 1 - good; + + /* Treat any faulure as verify MAC error. */ + if (ret != 0) + ret = VERIFY_MAC_ERROR; + + return ret; +} +#endif + + +int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx) +{ + word32 msgSz = ssl->keys.encryptSz; + word32 idx = *inOutIdx; + int dataSz; + int ivExtra = 0; + byte* rawData = input + idx; /* keep current for hmac */ +#ifdef HAVE_LIBZ + byte decomp[MAX_RECORD_SIZE + MAX_COMP_EXTRA]; +#endif + +#ifdef WOLFSSL_EARLY_DATA + if (ssl->earlyData != no_early_data) { + } + else +#endif + if (ssl->options.handShakeDone == 0) { + WOLFSSL_MSG("Received App data before a handshake completed"); + SendAlert(ssl, alert_fatal, unexpected_message); + return OUT_OF_ORDER_E; + } + +#ifndef WOLFSSL_AEAD_ONLY + if (ssl->specs.cipher_type == block) { + if (ssl->options.tls1_1) + ivExtra = ssl->specs.block_size; + } + else +#endif + if (ssl->specs.cipher_type == aead) { + if (CipherHasExpIV(ssl)) + ivExtra = AESGCM_EXP_IV_SZ; + } + + dataSz = msgSz - ivExtra - ssl->keys.padSz; + if (dataSz < 0) { + WOLFSSL_MSG("App data buffer error, malicious input?"); + SendAlert(ssl, alert_fatal, unexpected_message); + return BUFFER_ERROR; + } +#ifdef WOLFSSL_EARLY_DATA + if (ssl->earlyData != no_early_data) { + if (ssl->earlyDataSz + dataSz > ssl->options.maxEarlyDataSz) { + SendAlert(ssl, alert_fatal, unexpected_message); + return WOLFSSL_FATAL_ERROR; + } + ssl->earlyDataSz += dataSz; + } +#endif + + /* read data */ + if (dataSz) { + int rawSz = dataSz; /* keep raw size for idx adjustment */ + +#ifdef HAVE_LIBZ + if (ssl->options.usingCompression) { + dataSz = myDeCompress(ssl, rawData, dataSz, decomp, sizeof(decomp)); + if (dataSz < 0) return dataSz; + } +#endif + idx += rawSz; + + ssl->buffers.clearOutputBuffer.buffer = rawData; + ssl->buffers.clearOutputBuffer.length = dataSz; + } + + idx += ssl->keys.padSz; + +#ifdef HAVE_LIBZ + /* decompress could be bigger, overwrite after verify */ + if (ssl->options.usingCompression) + XMEMMOVE(rawData, decomp, dataSz); +#endif + + *inOutIdx = idx; + return 0; +} + + +/* process alert, return level */ +static int DoAlert(WOLFSSL* ssl, byte* input, word32* inOutIdx, int* type, + word32 totalSz) +{ + byte level; + byte code; + word32 dataSz = totalSz - *inOutIdx; + + #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) + if (ssl->hsInfoOn) + AddPacketName(ssl, "Alert"); + if (ssl->toInfoOn) + /* add record header back on to info + alert bytes level/code */ + AddPacketInfo(ssl, "Alert", alert, input + *inOutIdx - + RECORD_HEADER_SZ, RECORD_HEADER_SZ + ALERT_SIZE, + READ_PROTO, ssl->heap); + #endif + + if (IsEncryptionOn(ssl, 0)) + dataSz -= ssl->keys.padSz; + + /* make sure can read the message */ + if (dataSz != ALERT_SIZE) { +#ifdef WOLFSSL_EXTRA_ALERTS + SendAlert(ssl, alert_fatal, unexpected_message); +#endif + return BUFFER_E; + } + + level = input[(*inOutIdx)++]; + code = input[(*inOutIdx)++]; + ssl->alert_history.last_rx.code = code; + ssl->alert_history.last_rx.level = level; + *type = code; + if (level == alert_fatal) { + ssl->options.isClosed = 1; /* Don't send close_notify */ + } + + if (++ssl->options.alertCount >= WOLFSSL_ALERT_COUNT_MAX) { + WOLFSSL_MSG("Alert count exceeded"); +#ifdef WOLFSSL_EXTRA_ALERTS + if (level != alert_warning || code != close_notify) + SendAlert(ssl, alert_fatal, unexpected_message); +#endif + return ALERT_COUNT_E; + } + + WOLFSSL_MSG("Got alert"); + if (*type == close_notify) { + WOLFSSL_MSG("\tclose notify"); + ssl->options.closeNotify = 1; + } +#ifdef WOLFSSL_TLS13 + if (*type == decode_error) { + WOLFSSL_MSG("\tdecode error"); + } + if (*type == illegal_parameter) { + WOLFSSL_MSG("\tillegal parameter"); + } +#endif + WOLFSSL_ERROR(*type); + if (IsEncryptionOn(ssl, 0)) + *inOutIdx += ssl->keys.padSz; + + return level; +} + +static int GetInputData(WOLFSSL *ssl, word32 size) +{ + int in; + int inSz; + int maxLength; + int usedLength; + int dtlsExtra = 0; + + + /* check max input length */ + usedLength = ssl->buffers.inputBuffer.length - ssl->buffers.inputBuffer.idx; + maxLength = ssl->buffers.inputBuffer.bufferSize - usedLength; + inSz = (int)(size - usedLength); /* from last partial read */ + +#ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + if (size < ssl->dtls_expected_rx) + dtlsExtra = (int)(ssl->dtls_expected_rx - size); + inSz = ssl->dtls_expected_rx; + } +#endif + + /* check that no lengths or size values are negative */ + if (usedLength < 0 || maxLength < 0 || inSz <= 0) { + return BUFFER_ERROR; + } + + if (inSz > maxLength) { + if (GrowInputBuffer(ssl, size + dtlsExtra, usedLength) < 0) + return MEMORY_E; + } + + /* Put buffer data at start if not there */ + if (usedLength > 0 && ssl->buffers.inputBuffer.idx != 0) + XMEMMOVE(ssl->buffers.inputBuffer.buffer, + ssl->buffers.inputBuffer.buffer + ssl->buffers.inputBuffer.idx, + usedLength); + + /* remove processed data */ + ssl->buffers.inputBuffer.idx = 0; + ssl->buffers.inputBuffer.length = usedLength; + + /* read data from network */ + do { + in = wolfSSLReceive(ssl, + ssl->buffers.inputBuffer.buffer + + ssl->buffers.inputBuffer.length, + inSz); + if (in == WANT_READ) + return WANT_READ; + + if (in < 0) + return SOCKET_ERROR_E; + + if (in > inSz) + return RECV_OVERFLOW_E; + + ssl->buffers.inputBuffer.length += in; + inSz -= in; + + } while (ssl->buffers.inputBuffer.length < size); + +#ifdef WOLFSSL_DEBUG_TLS + if (ssl->buffers.inputBuffer.idx == 0) { + WOLFSSL_MSG("Data received"); + WOLFSSL_BUFFER(ssl->buffers.inputBuffer.buffer, + ssl->buffers.inputBuffer.length); + } +#endif + + return 0; +} + + +static WC_INLINE int VerifyMac(WOLFSSL* ssl, const byte* input, word32 msgSz, + int content, word32* padSz) +{ +#if !defined(WOLFSSL_NO_TLS12) && !defined(WOLFSSL_AEAD_ONLY) + int ivExtra = 0; + int ret; + word32 pad = 0; + word32 padByte = 0; +#ifdef HAVE_TRUNCATED_HMAC + word32 digestSz = ssl->truncated_hmac ? (byte)TRUNCATED_HMAC_SZ + : ssl->specs.hash_size; +#else + word32 digestSz = ssl->specs.hash_size; +#endif + byte verify[WC_MAX_DIGEST_SIZE]; + + + if (ssl->specs.cipher_type == block) { + if (ssl->options.tls1_1) + ivExtra = ssl->specs.block_size; + pad = *(input + msgSz - ivExtra - 1); + padByte = 1; + + if (ssl->options.tls) { + ret = TimingPadVerify(ssl, input, pad, digestSz, msgSz - ivExtra, + content); + if (ret != 0) + return ret; + } + else { /* sslv3, some implementations have bad padding, but don't + * allow bad read */ + int badPadLen = 0; + byte dmy[sizeof(WOLFSSL) >= MAX_PAD_SIZE ? 1 : MAX_PAD_SIZE] = {0}; + byte* dummy = sizeof(dmy) < MAX_PAD_SIZE ? (byte*) ssl : dmy; + + (void)dmy; + + if (pad > (msgSz - digestSz - 1)) { + WOLFSSL_MSG("Plain Len not long enough for pad/mac"); + pad = 0; /* no bad read */ + badPadLen = 1; + } + PadCheck(dummy, (byte)pad, MAX_PAD_SIZE); /* timing only */ + ret = ssl->hmac(ssl, verify, input, msgSz - digestSz - pad - 1, pad, + content, 1); + if (ConstantCompare(verify, input + msgSz - digestSz - pad - 1, + digestSz) != 0) + return VERIFY_MAC_ERROR; + if (ret != 0 || badPadLen) + return VERIFY_MAC_ERROR; + } + } + else if (ssl->specs.cipher_type == stream) { + ret = ssl->hmac(ssl, verify, input, msgSz - digestSz, -1, content, 1); + if (ConstantCompare(verify, input + msgSz - digestSz, digestSz) != 0){ + return VERIFY_MAC_ERROR; + } + if (ret != 0) + return VERIFY_MAC_ERROR; + } +#endif /* !WOLFSSL_NO_TLS12 && !WOLFSSL_AEAD_ONLY */ + + if (ssl->specs.cipher_type == aead) { + *padSz = ssl->specs.aead_mac_size; + } +#if !defined(WOLFSSL_NO_TLS12) && !defined(WOLFSSL_AEAD_ONLY) + else { + *padSz = digestSz + pad + padByte; + } +#endif /* !WOLFSSL_NO_TLS12 && !WOLFSSL_AEAD_ONLY */ + + (void)input; + (void)msgSz; + (void)content; + + return 0; +} + + +/* process input requests, return 0 is done, 1 is call again to complete, and + negative number is error */ +int ProcessReply(WOLFSSL* ssl) +{ + int ret = 0, type, readSz; + int atomicUser = 0; + word32 startIdx = 0; +#if defined(WOLFSSL_DTLS) + int used; +#endif + +#ifdef ATOMIC_USER + if (ssl->ctx->DecryptVerifyCb) + atomicUser = 1; +#endif + + if (ssl->error != 0 && ssl->error != WANT_READ && ssl->error != WANT_WRITE + #ifdef WOLFSSL_ASYNC_CRYPT + && ssl->error != WC_PENDING_E + #endif + #ifdef WOLFSSL_NONBLOCK_OCSP + && ssl->error != OCSP_WANT_READ + #endif + ) { + WOLFSSL_MSG("ProcessReply retry in error state, not allowed"); + return ssl->error; + } + + for (;;) { + switch (ssl->options.processReply) { + + /* in the WOLFSSL_SERVER case, get the first byte for detecting + * old client hello */ + case doProcessInit: + + readSz = RECORD_HEADER_SZ; + + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + readSz = DTLS_RECORD_HEADER_SZ; + #endif + + /* get header or return error */ + if (!ssl->options.dtls) { + if ((ret = GetInputData(ssl, readSz)) < 0) + return ret; + } else { + #ifdef WOLFSSL_DTLS + /* read ahead may already have header */ + used = ssl->buffers.inputBuffer.length - + ssl->buffers.inputBuffer.idx; + if (used < readSz) { + if ((ret = GetInputData(ssl, readSz)) < 0) + return ret; + } + #endif + } + +#ifdef OLD_HELLO_ALLOWED + + /* see if sending SSLv2 client hello */ + if ( ssl->options.side == WOLFSSL_SERVER_END && + ssl->options.clientState == NULL_STATE && + ssl->buffers.inputBuffer.buffer[ssl->buffers.inputBuffer.idx] + != handshake) { + byte b0, b1; + + ssl->options.processReply = runProcessOldClientHello; + + /* sanity checks before getting size at front */ + if (ssl->buffers.inputBuffer.buffer[ + ssl->buffers.inputBuffer.idx + OPAQUE16_LEN] != OLD_HELLO_ID) { + WOLFSSL_MSG("Not a valid old client hello"); + return PARSE_ERROR; + } + + if (ssl->buffers.inputBuffer.buffer[ + ssl->buffers.inputBuffer.idx + OPAQUE24_LEN] != SSLv3_MAJOR && + ssl->buffers.inputBuffer.buffer[ + ssl->buffers.inputBuffer.idx + OPAQUE24_LEN] != DTLS_MAJOR) { + WOLFSSL_MSG("Not a valid version in old client hello"); + return PARSE_ERROR; + } + + /* how many bytes need ProcessOldClientHello */ + b0 = + ssl->buffers.inputBuffer.buffer[ssl->buffers.inputBuffer.idx++]; + b1 = + ssl->buffers.inputBuffer.buffer[ssl->buffers.inputBuffer.idx++]; + ssl->curSize = (word16)(((b0 & 0x7f) << 8) | b1); + } + else { + ssl->options.processReply = getRecordLayerHeader; + continue; + } + FALL_THROUGH; + + /* in the WOLFSSL_SERVER case, run the old client hello */ + case runProcessOldClientHello: + + /* get sz bytes or return error */ + if (!ssl->options.dtls) { + if ((ret = GetInputData(ssl, ssl->curSize)) < 0) + return ret; + } else { + #ifdef WOLFSSL_DTLS + /* read ahead may already have */ + used = ssl->buffers.inputBuffer.length - + ssl->buffers.inputBuffer.idx; + if (used < ssl->curSize) + if ((ret = GetInputData(ssl, ssl->curSize)) < 0) + return ret; + #endif /* WOLFSSL_DTLS */ + } + + ret = ProcessOldClientHello(ssl, ssl->buffers.inputBuffer.buffer, + &ssl->buffers.inputBuffer.idx, + ssl->buffers.inputBuffer.length - + ssl->buffers.inputBuffer.idx, + ssl->curSize); + if (ret < 0) + return ret; + + else if (ssl->buffers.inputBuffer.idx == + ssl->buffers.inputBuffer.length) { + ssl->options.processReply = doProcessInit; + return 0; + } + +#endif /* OLD_HELLO_ALLOWED */ + FALL_THROUGH; + + /* get the record layer header */ + case getRecordLayerHeader: + + ret = GetRecordHeader(ssl, ssl->buffers.inputBuffer.buffer, + &ssl->buffers.inputBuffer.idx, + &ssl->curRL, &ssl->curSize); +#ifdef WOLFSSL_DTLS + if (ssl->options.dtls && ret == SEQUENCE_ERROR) { + WOLFSSL_MSG("Silently dropping out of order DTLS message"); + ssl->options.processReply = doProcessInit; + ssl->buffers.inputBuffer.length = 0; + ssl->buffers.inputBuffer.idx = 0; +#ifdef WOLFSSL_DTLS_DROP_STATS + ssl->replayDropCount++; +#endif /* WOLFSSL_DTLS_DROP_STATS */ + + if (IsDtlsNotSctpMode(ssl) && ssl->options.dtlsHsRetain) { + ret = DtlsMsgPoolSend(ssl, 0); + if (ret != 0) + return ret; + } + + continue; + } +#endif + if (ret != 0) + return ret; + +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && IsEncryptionOn(ssl, 0) && + ssl->curRL.type != application_data && + ssl->curRL.type != change_cipher_spec) { + SendAlert(ssl, alert_fatal, unexpected_message); + return PARSE_ERROR; + } +#endif + + ssl->options.processReply = getData; + FALL_THROUGH; + + /* retrieve record layer data */ + case getData: + + /* get sz bytes or return error */ + if (!ssl->options.dtls) { + if ((ret = GetInputData(ssl, ssl->curSize)) < 0) { +#ifdef WOLFSSL_EXTRA_ALERTS + if (ret != WANT_READ) + SendAlert(ssl, alert_fatal, bad_record_mac); +#endif + return ret; + } + } + else { +#ifdef WOLFSSL_DTLS + /* read ahead may already have */ + used = ssl->buffers.inputBuffer.length - + ssl->buffers.inputBuffer.idx; + if (used < ssl->curSize) + if ((ret = GetInputData(ssl, ssl->curSize)) < 0) + return ret; +#endif + } + + if (IsEncryptionOn(ssl, 0)) { + int tooLong = 0; + +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version)) { + tooLong = ssl->curSize > MAX_TLS13_ENC_SZ; + tooLong |= ssl->curSize - ssl->specs.aead_mac_size > + MAX_TLS13_PLAIN_SZ; + } +#endif +#ifdef WOLFSSL_EXTRA_ALERTS + if (!IsAtLeastTLSv1_3(ssl->version)) + tooLong = ssl->curSize > MAX_TLS_CIPHER_SZ; +#endif + if (tooLong) { + WOLFSSL_MSG("Encrypted data too long"); +#if defined(WOLFSSL_TLS13) || defined(WOLFSSL_EXTRA_ALERTS) + SendAlert(ssl, alert_fatal, record_overflow); +#endif + return BUFFER_ERROR; + } + } + ssl->keys.padSz = 0; + + ssl->options.processReply = decryptMessage; + startIdx = ssl->buffers.inputBuffer.idx; /* in case > 1 msg per */ + FALL_THROUGH; + + /* decrypt message */ + case decryptMessage: + +#if !defined(WOLFSSL_TLS13) || defined(WOLFSSL_TLS13_DRAFT_18) + if (IsEncryptionOn(ssl, 0) && ssl->keys.decryptedCur == 0) +#else + if (IsEncryptionOn(ssl, 0) && ssl->keys.decryptedCur == 0 && + (!IsAtLeastTLSv1_3(ssl->version) || + ssl->curRL.type != change_cipher_spec)) +#endif + { + bufferStatic* in = &ssl->buffers.inputBuffer; + + ret = SanityCheckCipherText(ssl, ssl->curSize); + if (ret < 0) { + #ifdef WOLFSSL_EXTRA_ALERTS + SendAlert(ssl, alert_fatal, bad_record_mac); + #endif + return ret; + } + + if (atomicUser) { + #ifdef ATOMIC_USER + ret = ssl->ctx->DecryptVerifyCb(ssl, + in->buffer + in->idx, + in->buffer + in->idx, + ssl->curSize, ssl->curRL.type, 1, + &ssl->keys.padSz, ssl->DecryptVerifyCtx); + #endif /* ATOMIC_USER */ + } + else { + if (!ssl->options.tls1_3) { + #ifndef WOLFSSL_NO_TLS12 + ret = Decrypt(ssl, + in->buffer + in->idx, + in->buffer + in->idx, + ssl->curSize); + #else + ret = DECRYPT_ERROR; + #endif + } + else + { + #ifdef WOLFSSL_TLS13 + #if defined(WOLFSSL_TLS13_DRAFT_18) || \ + defined(WOLFSSL_TLS13_DRAFT_22) || \ + defined(WOLFSSL_TLS13_DRAFT_23) + ret = DecryptTls13(ssl, + in->buffer + in->idx, + in->buffer + in->idx, + ssl->curSize, NULL, 0); + #else + ret = DecryptTls13(ssl, + in->buffer + in->idx, + in->buffer + in->idx, + ssl->curSize, + (byte*)&ssl->curRL, RECORD_HEADER_SZ); + #endif + #else + ret = DECRYPT_ERROR; + #endif /* WOLFSSL_TLS13 */ + } + } + + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) + return ret; + #endif + + if (ret >= 0) { + #ifndef WOLFSSL_NO_TLS12 + /* handle success */ + #ifndef WOLFSSL_AEAD_ONLY + if (ssl->options.tls1_1 && ssl->specs.cipher_type == block) + ssl->buffers.inputBuffer.idx += ssl->specs.block_size; + #endif + /* go past TLSv1.1 IV */ + if (CipherHasExpIV(ssl)) + ssl->buffers.inputBuffer.idx += AESGCM_EXP_IV_SZ; + #endif + } + else { + WOLFSSL_MSG("Decrypt failed"); + WOLFSSL_ERROR(ret); + #ifdef WOLFSSL_EARLY_DATA + if (ssl->options.tls1_3) { + ssl->earlyDataSz += ssl->curSize; + if (ssl->earlyDataSz <= ssl->options.maxEarlyDataSz) { + if (ssl->keys.peer_sequence_number_lo-- == 0) + ssl->keys.peer_sequence_number_hi--; + ssl->options.processReply = doProcessInit; + ssl->buffers.inputBuffer.idx = + ssl->buffers.inputBuffer.length; + return 0; + } + } + #endif + #ifdef WOLFSSL_DTLS + /* If in DTLS mode, if the decrypt fails for any + * reason, pretend the datagram never happened. */ + if (ssl->options.dtls) { + ssl->options.processReply = doProcessInit; + ssl->buffers.inputBuffer.idx = + ssl->buffers.inputBuffer.length; + #ifdef WOLFSSL_DTLS_DROP_STATS + ssl->macDropCount++; + #endif /* WOLFSSL_DTLS_DROP_STATS */ + } + #endif /* WOLFSSL_DTLS */ + + return DECRYPT_ERROR; + } + } + + ssl->options.processReply = verifyMessage; + FALL_THROUGH; + + /* verify digest of message */ + case verifyMessage: + +#if !defined(WOLFSSL_TLS13) || defined(WOLFSSL_TLS13_DRAFT_18) + if (IsEncryptionOn(ssl, 0) && ssl->keys.decryptedCur == 0) +#else + if (IsEncryptionOn(ssl, 0) && ssl->keys.decryptedCur == 0 && + (!IsAtLeastTLSv1_3(ssl->version) || + ssl->curRL.type != change_cipher_spec)) +#endif + { + if (!atomicUser) { + ret = VerifyMac(ssl, ssl->buffers.inputBuffer.buffer + + ssl->buffers.inputBuffer.idx, + ssl->curSize, ssl->curRL.type, + &ssl->keys.padSz); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) + return ret; + #endif + if (ret < 0) { + WOLFSSL_MSG("VerifyMac failed"); + WOLFSSL_ERROR(ret); + #ifdef WOLFSSL_DTLS + /* If in DTLS mode, if the decrypt fails for any + * reason, pretend the datagram never happened. */ + if (ssl->options.dtls) { + ssl->options.processReply = doProcessInit; + ssl->buffers.inputBuffer.idx = + ssl->buffers.inputBuffer.length; + #ifdef WOLFSSL_DTLS_DROP_STATS + ssl->macDropCount++; + #endif /* WOLFSSL_DTLS_DROP_STATS */ + } + #endif /* WOLFSSL_DTLS */ + #ifdef WOLFSSL_EXTRA_ALERTS + if (!ssl->options.dtls) + SendAlert(ssl, alert_fatal, bad_record_mac); + #endif + return DECRYPT_ERROR; + } + } + + ssl->keys.encryptSz = ssl->curSize; + ssl->keys.decryptedCur = 1; +#ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) { + word16 i = (word16)(ssl->buffers.inputBuffer.length - + ssl->keys.padSz); + /* Remove padding from end of plain text. */ + for (--i; i > ssl->buffers.inputBuffer.idx; i--) { + if (ssl->buffers.inputBuffer.buffer[i] != 0) + break; + } + /* Get the real content type from the end of the data. */ + ssl->curRL.type = ssl->buffers.inputBuffer.buffer[i]; + ssl->keys.padSz = ssl->buffers.inputBuffer.length - i; + } +#endif + } + + ssl->options.processReply = runProcessingOneMessage; + FALL_THROUGH; + + /* the record layer is here */ + case runProcessingOneMessage: + + if (ssl->buffers.inputBuffer.length - ssl->keys.padSz - + ssl->buffers.inputBuffer.idx > MAX_PLAINTEXT_SZ) { + WOLFSSL_MSG("Plaintext too long"); +#if defined(WOLFSSL_TLS13) || defined(WOLFSSL_EXTRA_ALERTS) + SendAlert(ssl, alert_fatal, record_overflow); +#endif + return BUFFER_ERROR; + } + + #ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl)) { + DtlsUpdateWindow(ssl); + } + #endif /* WOLFSSL_DTLS */ + + WOLFSSL_MSG("received record layer msg"); + + switch (ssl->curRL.type) { + case handshake : + /* debugging in DoHandShakeMsg */ + if (ssl->options.dtls) { +#ifdef WOLFSSL_DTLS + ret = DoDtlsHandShakeMsg(ssl, + ssl->buffers.inputBuffer.buffer, + &ssl->buffers.inputBuffer.idx, + ssl->buffers.inputBuffer.length); +#endif + } + else if (!IsAtLeastTLSv1_3(ssl->version)) { +#ifndef WOLFSSL_NO_TLS12 + ret = DoHandShakeMsg(ssl, + ssl->buffers.inputBuffer.buffer, + &ssl->buffers.inputBuffer.idx, + ssl->buffers.inputBuffer.length); +#else + ret = BUFFER_ERROR; +#endif + } + else { +#ifdef WOLFSSL_TLS13 + ret = DoTls13HandShakeMsg(ssl, + ssl->buffers.inputBuffer.buffer, + &ssl->buffers.inputBuffer.idx, + ssl->buffers.inputBuffer.length); + #ifdef WOLFSSL_EARLY_DATA + if (ret != 0) + return ret; + if (ssl->options.side == WOLFSSL_SERVER_END && + ssl->earlyData && + ssl->options.handShakeState == HANDSHAKE_DONE) { + ssl->earlyData = no_early_data; + ssl->options.processReply = doProcessInit; + return ZERO_RETURN; + } + #endif +#else + ret = BUFFER_ERROR; +#endif + } + if (ret != 0) { + WOLFSSL_ERROR(ret); + return ret; + } + break; + + case change_cipher_spec: + WOLFSSL_MSG("got CHANGE CIPHER SPEC"); + #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) + if (ssl->hsInfoOn) + AddPacketName(ssl, "ChangeCipher"); + /* add record header back on info */ + if (ssl->toInfoOn) { + AddPacketInfo(ssl, "ChangeCipher", + change_cipher_spec, + ssl->buffers.inputBuffer.buffer + + ssl->buffers.inputBuffer.idx - RECORD_HEADER_SZ, + 1 + RECORD_HEADER_SZ, READ_PROTO, ssl->heap); + #ifdef WOLFSSL_CALLBACKS + AddLateRecordHeader(&ssl->curRL, &ssl->timeoutInfo); + #endif + } + #endif + +#ifdef WOLFSSL_TLS13 + #ifdef WOLFSSL_TLS13_DRAFT_18 + if (IsAtLeastTLSv1_3(ssl->version)) { + SendAlert(ssl, alert_fatal, illegal_parameter); + return UNKNOWN_RECORD_TYPE; + } + #else + if (IsAtLeastTLSv1_3(ssl->version)) { + word32 i = ssl->buffers.inputBuffer.idx; + if (ssl->options.handShakeState == HANDSHAKE_DONE) { + SendAlert(ssl, alert_fatal, unexpected_message); + return UNKNOWN_RECORD_TYPE; + } + if (ssl->curSize != 1 || + ssl->buffers.inputBuffer.buffer[i] != 1) { + SendAlert(ssl, alert_fatal, illegal_parameter); + return UNKNOWN_RECORD_TYPE; + } + ssl->buffers.inputBuffer.idx++; + break; + } + #endif +#endif + +#ifndef WOLFSSL_NO_TLS12 + ret = SanityCheckMsgReceived(ssl, change_cipher_hs); + if (ret != 0) { + if (!ssl->options.dtls) { + return ret; + } + else { + #ifdef WOLFSSL_DTLS + /* Check for duplicate CCS message in DTLS mode. + * DTLS allows for duplicate messages, and it should be + * skipped. Also skip if out of order. */ + if (ret != DUPLICATE_MSG_E && ret != OUT_OF_ORDER_E) + return ret; + + if (IsDtlsNotSctpMode(ssl)) { + ret = DtlsMsgPoolSend(ssl, 1); + if (ret != 0) + return ret; + } + + if (ssl->curSize != 1) { + WOLFSSL_MSG("Malicious or corrupted" + " duplicate ChangeCipher msg"); + return LENGTH_ERROR; + } + ssl->buffers.inputBuffer.idx++; + break; + #endif /* WOLFSSL_DTLS */ + } + } + + if (IsEncryptionOn(ssl, 0) && ssl->options.handShakeDone) { + ssl->buffers.inputBuffer.idx += ssl->keys.padSz; + ssl->curSize -= (word16) ssl->buffers.inputBuffer.idx; + } + + if (ssl->curSize != 1) { + WOLFSSL_MSG("Malicious or corrupted ChangeCipher msg"); + return LENGTH_ERROR; + } + + ssl->buffers.inputBuffer.idx++; + ssl->keys.encryptionOn = 1; + + /* setup decrypt keys for following messages */ + /* XXX This might not be what we want to do when + * receiving a CCS with multicast. We update the + * key when the application updates them. */ + if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0) + return ret; + + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + WOLFSSL_DTLS_PEERSEQ* peerSeq = ssl->keys.peerSeq; +#ifdef WOLFSSL_MULTICAST + if (ssl->options.haveMcast) { + peerSeq += ssl->keys.curPeerId; + peerSeq->highwaterMark = UpdateHighwaterMark(0, + ssl->ctx->mcastFirstSeq, + ssl->ctx->mcastSecondSeq, + ssl->ctx->mcastMaxSeq); + } +#endif + DtlsMsgPoolReset(ssl); + peerSeq->nextEpoch++; + peerSeq->prevSeq_lo = peerSeq->nextSeq_lo; + peerSeq->prevSeq_hi = peerSeq->nextSeq_hi; + peerSeq->nextSeq_lo = 0; + peerSeq->nextSeq_hi = 0; + XMEMCPY(peerSeq->prevWindow, peerSeq->window, + DTLS_SEQ_SZ); + XMEMSET(peerSeq->window, 0, DTLS_SEQ_SZ); + } + #endif + + #ifdef HAVE_LIBZ + if (ssl->options.usingCompression) + if ( (ret = InitStreams(ssl)) != 0) + return ret; + #endif + ret = BuildFinished(ssl, &ssl->hsHashes->verifyHashes, + ssl->options.side == WOLFSSL_CLIENT_END ? + server : client); + if (ret != 0) + return ret; +#endif /* !WOLFSSL_NO_TLS12 */ + break; + + case application_data: + WOLFSSL_MSG("got app DATA"); + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls && ssl->options.dtlsHsRetain) { + FreeHandshakeResources(ssl); + ssl->options.dtlsHsRetain = 0; + } + #endif + #ifdef WOLFSSL_TLS13 + if (ssl->keys.keyUpdateRespond) { + WOLFSSL_MSG("No KeyUpdate from peer seen"); + return SANITY_MSG_E; + } + #endif + if ((ret = DoApplicationData(ssl, + ssl->buffers.inputBuffer.buffer, + &ssl->buffers.inputBuffer.idx)) + != 0) { + WOLFSSL_ERROR(ret); + return ret; + } + break; + + case alert: + WOLFSSL_MSG("got ALERT!"); + ret = DoAlert(ssl, ssl->buffers.inputBuffer.buffer, + &ssl->buffers.inputBuffer.idx, &type, + ssl->buffers.inputBuffer.length); + if (ret == alert_fatal) + return FATAL_ERROR; + else if (ret < 0) + return ret; + + /* catch warnings that are handled as errors */ + if (type == close_notify) + return ssl->error = ZERO_RETURN; + + if (type == decrypt_error) + return FATAL_ERROR; + break; + + default: + WOLFSSL_ERROR(UNKNOWN_RECORD_TYPE); + return UNKNOWN_RECORD_TYPE; + } + + ssl->options.processReply = doProcessInit; + + /* input exhausted? */ + if (ssl->buffers.inputBuffer.idx >= ssl->buffers.inputBuffer.length) + return 0; + + /* more messages per record */ + else if ((ssl->buffers.inputBuffer.idx - startIdx) < ssl->curSize) { + WOLFSSL_MSG("More messages in record"); + + ssl->options.processReply = runProcessingOneMessage; + + if (IsEncryptionOn(ssl, 0)) { + WOLFSSL_MSG("Bundled encrypted messages, remove middle pad"); + if (ssl->buffers.inputBuffer.idx >= ssl->keys.padSz) { + ssl->buffers.inputBuffer.idx -= ssl->keys.padSz; + } + else { + WOLFSSL_MSG("\tmiddle padding error"); + return FATAL_ERROR; + } + } + + continue; + } + /* more records */ + else { + WOLFSSL_MSG("More records in input"); + ssl->options.processReply = doProcessInit; + continue; + } + + default: + WOLFSSL_MSG("Bad process input state, programming error"); + return INPUT_CASE_ERROR; + } + } +} + + +int SendChangeCipher(WOLFSSL* ssl) +{ + byte *output; + int sendSz = RECORD_HEADER_SZ + ENUM_LEN; + int idx = RECORD_HEADER_SZ; + int ret; + + #ifdef OPENSSL_EXTRA + ssl->cbmode = SSL_CB_MODE_WRITE; + if (ssl->options.side == WOLFSSL_SERVER_END){ + ssl->options.serverState = SERVER_CHANGECIPHERSPEC_COMPLETE; + if (ssl->CBIS != NULL) + ssl->CBIS(ssl, SSL_CB_ACCEPT_LOOP, SSL_SUCCESS); + } + else{ + ssl->options.clientState = + CLIENT_CHANGECIPHERSPEC_COMPLETE; + if (ssl->CBIS != NULL) + ssl->CBIS(ssl, SSL_CB_CONNECT_LOOP, SSL_SUCCESS); + } + #endif + + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + sendSz += DTLS_RECORD_EXTRA; + idx += DTLS_RECORD_EXTRA; + } + #endif + + /* are we in scr */ + if (IsEncryptionOn(ssl, 1) && ssl->options.handShakeDone) { + sendSz += MAX_MSG_EXTRA; + } + + /* check for available size */ + if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) + return ret; + + /* get output buffer */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + AddRecordHeader(output, 1, change_cipher_spec, ssl); + + output[idx] = 1; /* turn it on */ + + if (IsEncryptionOn(ssl, 1) && ssl->options.handShakeDone) { + byte input[ENUM_LEN]; + int inputSz = ENUM_LEN; + + input[0] = 1; /* turn it on */ + sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, + change_cipher_spec, 0, 0, 0); + if (sendSz < 0) { + return sendSz; + } + } + + #ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl)) { + DtlsSEQIncrement(ssl, CUR_ORDER); + if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) + return ret; + } + #endif + #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) + if (ssl->hsInfoOn) AddPacketName(ssl, "ChangeCipher"); + if (ssl->toInfoOn) + AddPacketInfo(ssl, "ChangeCipher", change_cipher_spec, output, + sendSz, WRITE_PROTO, ssl->heap); + #endif + ssl->buffers.outputBuffer.length += sendSz; + + if (ssl->options.groupMessages) + return 0; + #if defined(WOLFSSL_DTLS) && !defined(WOLFSSL_DEBUG_DTLS) + else if (ssl->options.dtls) { + /* If using DTLS, force the ChangeCipherSpec message to be in the + * same datagram as the finished message. */ + return 0; + } + #endif + else + return SendBuffered(ssl); +} + + +#if !defined(NO_OLD_TLS) && !defined(WOLFSSL_AEAD_ONLY) +static int SSL_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, + int padLen, int content, int verify) +{ + byte result[WC_MAX_DIGEST_SIZE]; + word32 digestSz = ssl->specs.hash_size; /* actual sizes */ + word32 padSz = ssl->specs.pad_size; + int ret = 0; + + wc_Md5 md5; + wc_Sha sha; + + /* data */ + byte seq[SEQ_SZ]; + byte conLen[ENUM_LEN + LENGTH_SZ]; /* content & length */ + const byte* macSecret = wolfSSL_GetMacSecret(ssl, verify); + + (void)padLen; + +#ifdef HAVE_FUZZER + if (ssl->fuzzerCb) + ssl->fuzzerCb(ssl, in, sz, FUZZ_HMAC, ssl->fuzzerCtx); +#endif + + XMEMSET(seq, 0, SEQ_SZ); + conLen[0] = (byte)content; + c16toa((word16)sz, &conLen[ENUM_LEN]); + WriteSEQ(ssl, verify, seq); + + if (ssl->specs.mac_algorithm == md5_mac) { + ret = wc_InitMd5_ex(&md5, ssl->heap, ssl->devId); + if (ret != 0) + return ret; + + /* inner */ + ret = wc_Md5Update(&md5, macSecret, digestSz); + ret |= wc_Md5Update(&md5, PAD1, padSz); + ret |= wc_Md5Update(&md5, seq, SEQ_SZ); + ret |= wc_Md5Update(&md5, conLen, sizeof(conLen)); + /* in buffer */ + ret |= wc_Md5Update(&md5, in, sz); + if (ret != 0) + return VERIFY_MAC_ERROR; + ret = wc_Md5Final(&md5, result); + #ifdef WOLFSSL_ASYNC_CRYPT + /* TODO: Make non-blocking */ + if (ret == WC_PENDING_E) { + ret = wc_AsyncWait(ret, &md5.asyncDev, WC_ASYNC_FLAG_NONE); + } + #endif + if (ret != 0) + return VERIFY_MAC_ERROR; + + /* outer */ + ret = wc_Md5Update(&md5, macSecret, digestSz); + ret |= wc_Md5Update(&md5, PAD2, padSz); + ret |= wc_Md5Update(&md5, result, digestSz); + if (ret != 0) + return VERIFY_MAC_ERROR; + ret = wc_Md5Final(&md5, digest); + #ifdef WOLFSSL_ASYNC_CRYPT + /* TODO: Make non-blocking */ + if (ret == WC_PENDING_E) { + ret = wc_AsyncWait(ret, &md5.asyncDev, WC_ASYNC_FLAG_NONE); + } + #endif + if (ret != 0) + return VERIFY_MAC_ERROR; + + wc_Md5Free(&md5); + } + else { + ret = wc_InitSha_ex(&sha, ssl->heap, ssl->devId); + if (ret != 0) + return ret; + + /* inner */ + ret = wc_ShaUpdate(&sha, macSecret, digestSz); + ret |= wc_ShaUpdate(&sha, PAD1, padSz); + ret |= wc_ShaUpdate(&sha, seq, SEQ_SZ); + ret |= wc_ShaUpdate(&sha, conLen, sizeof(conLen)); + /* in buffer */ + ret |= wc_ShaUpdate(&sha, in, sz); + if (ret != 0) + return VERIFY_MAC_ERROR; + ret = wc_ShaFinal(&sha, result); + #ifdef WOLFSSL_ASYNC_CRYPT + /* TODO: Make non-blocking */ + if (ret == WC_PENDING_E) { + ret = wc_AsyncWait(ret, &sha.asyncDev, WC_ASYNC_FLAG_NONE); + } + #endif + if (ret != 0) + return VERIFY_MAC_ERROR; + + /* outer */ + ret = wc_ShaUpdate(&sha, macSecret, digestSz); + ret |= wc_ShaUpdate(&sha, PAD2, padSz); + ret |= wc_ShaUpdate(&sha, result, digestSz); + if (ret != 0) + return VERIFY_MAC_ERROR; + ret = wc_ShaFinal(&sha, digest); + #ifdef WOLFSSL_ASYNC_CRYPT + /* TODO: Make non-blocking */ + if (ret == WC_PENDING_E) { + ret = wc_AsyncWait(ret, &sha.asyncDev, WC_ASYNC_FLAG_NONE); + } + #endif + if (ret != 0) + return VERIFY_MAC_ERROR; + + wc_ShaFree(&sha); + } + return 0; +} +#endif /* !NO_OLD_TLS && !WOLFSSL_AEAD_ONLY */ + + +#ifndef NO_CERTS + +#if !defined(NO_MD5) && !defined(NO_OLD_TLS) +static int BuildMD5_CertVerify(WOLFSSL* ssl, byte* digest) +{ + int ret; + byte md5_result[WC_MD5_DIGEST_SIZE]; +#ifdef WOLFSSL_SMALL_STACK + wc_Md5* md5 = (wc_Md5*)XMALLOC(sizeof(wc_Md5), ssl->heap, DYNAMIC_TYPE_HASHCTX); +#else + wc_Md5 md5[1]; +#endif + + /* make md5 inner */ + ret = wc_Md5Copy(&ssl->hsHashes->hashMd5, md5); /* Save current position */ + if (ret == 0) + ret = wc_Md5Update(md5, ssl->arrays->masterSecret,SECRET_LEN); + if (ret == 0) + ret = wc_Md5Update(md5, PAD1, PAD_MD5); + if (ret == 0) + ret = wc_Md5Final(md5, md5_result); + + /* make md5 outer */ + if (ret == 0) { + ret = wc_InitMd5_ex(md5, ssl->heap, ssl->devId); + if (ret == 0) { + ret = wc_Md5Update(md5, ssl->arrays->masterSecret, SECRET_LEN); + if (ret == 0) + ret = wc_Md5Update(md5, PAD2, PAD_MD5); + if (ret == 0) + ret = wc_Md5Update(md5, md5_result, WC_MD5_DIGEST_SIZE); + if (ret == 0) + ret = wc_Md5Final(md5, digest); + wc_Md5Free(md5); + } + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(md5, ssl->heap, DYNAMIC_TYPE_HASHCTX); +#endif + + return ret; +} +#endif /* !NO_MD5 && !NO_OLD_TLS */ + +#if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || \ + defined(WOLFSSL_ALLOW_TLS_SHA1)) +static int BuildSHA_CertVerify(WOLFSSL* ssl, byte* digest) +{ + int ret; + byte sha_result[WC_SHA_DIGEST_SIZE]; +#ifdef WOLFSSL_SMALL_STACK + wc_Sha* sha = (wc_Sha*)XMALLOC(sizeof(wc_Sha), ssl->heap, DYNAMIC_TYPE_HASHCTX); +#else + wc_Sha sha[1]; +#endif + + /* make sha inner */ + ret = wc_ShaCopy(&ssl->hsHashes->hashSha, sha); /* Save current position */ + if (ret == 0) + ret = wc_ShaUpdate(sha, ssl->arrays->masterSecret,SECRET_LEN); + if (ret == 0) + ret = wc_ShaUpdate(sha, PAD1, PAD_SHA); + if (ret == 0) + ret = wc_ShaFinal(sha, sha_result); + + /* make sha outer */ + if (ret == 0) { + ret = wc_InitSha_ex(sha, ssl->heap, ssl->devId); + if (ret == 0) { + ret = wc_ShaUpdate(sha, ssl->arrays->masterSecret,SECRET_LEN); + if (ret == 0) + ret = wc_ShaUpdate(sha, PAD2, PAD_SHA); + if (ret == 0) + ret = wc_ShaUpdate(sha, sha_result, WC_SHA_DIGEST_SIZE); + if (ret == 0) + ret = wc_ShaFinal(sha, digest); + wc_ShaFree(sha); + } + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(sha, ssl->heap, DYNAMIC_TYPE_HASHCTX); +#endif + + return ret; +} +#endif /* !NO_SHA && (!NO_OLD_TLS || WOLFSSL_ALLOW_TLS_SHA1) */ + +int BuildCertHashes(WOLFSSL* ssl, Hashes* hashes) +{ + int ret = 0; + + (void)hashes; + + if (ssl->options.tls) { + #if !defined(NO_MD5) && !defined(NO_OLD_TLS) + ret = wc_Md5GetHash(&ssl->hsHashes->hashMd5, hashes->md5); + if (ret != 0) + return ret; + #endif + #if !defined(NO_SHA) + ret = wc_ShaGetHash(&ssl->hsHashes->hashSha, hashes->sha); + if (ret != 0) + return ret; + #endif + if (IsAtLeastTLSv1_2(ssl)) { + #ifndef NO_SHA256 + ret = wc_Sha256GetHash(&ssl->hsHashes->hashSha256, + hashes->sha256); + if (ret != 0) + return ret; + #endif + #ifdef WOLFSSL_SHA384 + ret = wc_Sha384GetHash(&ssl->hsHashes->hashSha384, + hashes->sha384); + if (ret != 0) + return ret; + #endif + #ifdef WOLFSSL_SHA512 + ret = wc_Sha512GetHash(&ssl->hsHashes->hashSha512, + hashes->sha512); + if (ret != 0) + return ret; + #endif + } + } + else { + #if !defined(NO_MD5) && !defined(NO_OLD_TLS) + ret = BuildMD5_CertVerify(ssl, hashes->md5); + if (ret != 0) + return ret; + #endif + #if !defined(NO_SHA) && (!defined(NO_OLD_TLS) || \ + defined(WOLFSSL_ALLOW_TLS_SHA1)) + ret = BuildSHA_CertVerify(ssl, hashes->sha); + if (ret != 0) + return ret; + #endif + } + + return ret; +} + +#endif /* !NO_CERTS */ + +#ifndef WOLFSSL_NO_TLS12 +/* Persistable BuildMessage arguments */ +typedef struct BuildMsgArgs { + word32 digestSz; + word32 sz; + word32 pad; + word32 idx; + word32 headerSz; + word16 size; + word32 ivSz; /* TLSv1.1 IV */ + byte* iv; +} BuildMsgArgs; + +static void FreeBuildMsgArgs(WOLFSSL* ssl, void* pArgs) +{ + BuildMsgArgs* args = (BuildMsgArgs*)pArgs; + + (void)ssl; + (void)args; + + if (args->iv) { + XFREE(args->iv, ssl->heap, DYNAMIC_TYPE_SALT); + args->iv = NULL; + } +} +#endif + +/* Build SSL Message, encrypted */ +int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, const byte* input, + int inSz, int type, int hashOutput, int sizeOnly, int asyncOkay) +{ +#ifndef WOLFSSL_NO_TLS12 + int ret = 0; + BuildMsgArgs* args; + BuildMsgArgs lcl_args; +#ifdef WOLFSSL_ASYNC_CRYPT + args = (BuildMsgArgs*)ssl->async.args; + typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1]; + (void)sizeof(args_test); +#endif +#endif + + WOLFSSL_ENTER("BuildMessage"); + + if (ssl == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_NO_TLS12 + return BuildTls13Message(ssl, output, outSz, input, inSz, type, + hashOutput, sizeOnly, asyncOkay); +#else +#ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) { + return BuildTls13Message(ssl, output, outSz, input, inSz, type, + hashOutput, sizeOnly, asyncOkay); + } +#endif + + ret = WC_NOT_PENDING_E; +#ifdef WOLFSSL_ASYNC_CRYPT + if (asyncOkay) { + ret = wolfSSL_AsyncPop(ssl, &ssl->options.buildMsgState); + if (ret != WC_NOT_PENDING_E) { + /* Check for error */ + if (ret < 0) + goto exit_buildmsg; + } + } + else +#endif + { + args = &lcl_args; + } + + /* Reset state */ + if (ret == WC_NOT_PENDING_E) { + ret = 0; + ssl->options.buildMsgState = BUILD_MSG_BEGIN; + XMEMSET(args, 0, sizeof(BuildMsgArgs)); + + args->sz = RECORD_HEADER_SZ + inSz; + args->idx = RECORD_HEADER_SZ; + args->headerSz = RECORD_HEADER_SZ; + #ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = FreeBuildMsgArgs; + #endif + } + + switch (ssl->options.buildMsgState) { + case BUILD_MSG_BEGIN: + { + /* catch mistaken sizeOnly parameter */ + if (!sizeOnly && (output == NULL || input == NULL) ) { + ERROR_OUT(BAD_FUNC_ARG, exit_buildmsg); + } + if (sizeOnly && (output || input) ) { + WOLFSSL_MSG("BuildMessage w/sizeOnly doesn't need input/output"); + ERROR_OUT(BAD_FUNC_ARG, exit_buildmsg); + } + + ssl->options.buildMsgState = BUILD_MSG_SIZE; + } + FALL_THROUGH; + case BUILD_MSG_SIZE: + { + args->digestSz = ssl->specs.hash_size; + #ifdef HAVE_TRUNCATED_HMAC + if (ssl->truncated_hmac) + args->digestSz = min(TRUNCATED_HMAC_SZ, args->digestSz); + #endif + args->sz += args->digestSz; + + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + args->sz += DTLS_RECORD_EXTRA; + args->idx += DTLS_RECORD_EXTRA; + args->headerSz += DTLS_RECORD_EXTRA; + } + #endif + + #ifndef WOLFSSL_AEAD_ONLY + if (ssl->specs.cipher_type == block) { + word32 blockSz = ssl->specs.block_size; + if (ssl->options.tls1_1) { + args->ivSz = blockSz; + args->sz += args->ivSz; + + if (args->ivSz > MAX_IV_SZ) + ERROR_OUT(BUFFER_E, exit_buildmsg); + } + args->sz += 1; /* pad byte */ + args->pad = (args->sz - args->headerSz) % blockSz; + #ifdef OPENSSL_EXTRA + if(args->pad != 0) + #endif + args->pad = blockSz - args->pad; + args->sz += args->pad; + } + #endif /* WOLFSSL_AEAD_ONLY */ + + #ifdef HAVE_AEAD + if (ssl->specs.cipher_type == aead) { + if (ssl->specs.bulk_cipher_algorithm != wolfssl_chacha) + args->ivSz = AESGCM_EXP_IV_SZ; + + args->sz += (args->ivSz + ssl->specs.aead_mac_size - args->digestSz); + } + #endif + + /* done with size calculations */ + if (sizeOnly) + goto exit_buildmsg; + + if (args->sz > (word32)outSz) { + WOLFSSL_MSG("Oops, want to write past output buffer size"); + ERROR_OUT(BUFFER_E, exit_buildmsg); + } + + if (args->ivSz > 0) { + args->iv = (byte*)XMALLOC(args->ivSz, ssl->heap, DYNAMIC_TYPE_SALT); + if (args->iv == NULL) + ERROR_OUT(MEMORY_E, exit_buildmsg); + + ret = wc_RNG_GenerateBlock(ssl->rng, args->iv, args->ivSz); + if (ret != 0) + goto exit_buildmsg; + + } +#if !defined(NO_PUBLIC_GCM_SET_IV) && \ + ((defined(HAVE_FIPS) || defined(HAVE_SELFTEST)) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) && \ + defined(HAVE_AEAD)) + if (ssl->specs.cipher_type == aead) { + if (ssl->specs.bulk_cipher_algorithm != wolfssl_chacha) + XMEMCPY(args->iv, ssl->keys.aead_exp_IV, AESGCM_EXP_IV_SZ); + } +#endif + + args->size = (word16)(args->sz - args->headerSz); /* include mac and digest */ + AddRecordHeader(output, args->size, (byte)type, ssl); + + /* write to output */ + if (args->ivSz > 0) { + XMEMCPY(output + args->idx, args->iv, + min(args->ivSz, MAX_IV_SZ)); + args->idx += args->ivSz; + } + XMEMCPY(output + args->idx, input, inSz); + args->idx += inSz; + + ssl->options.buildMsgState = BUILD_MSG_HASH; + } + FALL_THROUGH; + case BUILD_MSG_HASH: + { + if (type == handshake && hashOutput) { + ret = HashOutput(ssl, output, args->headerSz + inSz, args->ivSz); + if (ret != 0) + goto exit_buildmsg; + } + #ifndef WOLFSSL_AEAD_ONLY + if (ssl->specs.cipher_type == block) { + word32 tmpIdx = args->idx + args->digestSz; + word32 i; + + for (i = 0; i <= args->pad; i++) + output[tmpIdx++] = (byte)args->pad; /* pad byte gets pad value */ + } + #endif + + ssl->options.buildMsgState = BUILD_MSG_VERIFY_MAC; + } + FALL_THROUGH; + case BUILD_MSG_VERIFY_MAC: + { + /* User Record Layer Callback handling */ + #ifdef ATOMIC_USER + if (ssl->ctx->MacEncryptCb) { + ret = ssl->ctx->MacEncryptCb(ssl, output + args->idx, + output + args->headerSz + args->ivSz, inSz, type, 0, + output + args->headerSz, output + args->headerSz, args->size, + ssl->MacEncryptCtx); + goto exit_buildmsg; + } + #endif + + #ifndef WOLFSSL_AEAD_ONLY + if (ssl->specs.cipher_type != aead) { + #ifdef HAVE_TRUNCATED_HMAC + if (ssl->truncated_hmac && + ssl->specs.hash_size > args->digestSz) { + #ifdef WOLFSSL_SMALL_STACK + byte* hmac = NULL; + #else + byte hmac[WC_MAX_DIGEST_SIZE]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + hmac = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, ssl->heap, + DYNAMIC_TYPE_DIGEST); + if (hmac == NULL) + ERROR_OUT(MEMORY_E, exit_buildmsg); + #endif + + ret = ssl->hmac(ssl, hmac, + output + args->headerSz + args->ivSz, inSz, + -1, type, 0); + XMEMCPY(output + args->idx, hmac, args->digestSz); + + #ifdef WOLFSSL_SMALL_STACK + XFREE(hmac, ssl->heap, DYNAMIC_TYPE_DIGEST); + #endif + } + else + #endif + { + ret = ssl->hmac(ssl, output + args->idx, output + + args->headerSz + args->ivSz, inSz, -1, type, 0); + } + } + #endif /* WOLFSSL_AEAD_ONLY */ + if (ret != 0) + goto exit_buildmsg; + + ssl->options.buildMsgState = BUILD_MSG_ENCRYPT; + } + FALL_THROUGH; + case BUILD_MSG_ENCRYPT: + { + ret = Encrypt(ssl, output + args->headerSz, output + args->headerSz, args->size, + asyncOkay); + break; + } + } + +exit_buildmsg: + + WOLFSSL_LEAVE("BuildMessage", ret); + +#ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + return ret; + } +#endif + + /* make sure build message state is reset */ + ssl->options.buildMsgState = BUILD_MSG_BEGIN; + + #ifdef WOLFSSL_DTLS + if (ret == 0 && ssl->options.dtls) + DtlsSEQIncrement(ssl, CUR_ORDER); + #endif + + /* return sz on success */ + if (ret == 0) + ret = args->sz; + + /* Final cleanup */ + FreeBuildMsgArgs(ssl, args); +#ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = NULL; +#endif + + return ret; +#endif /* !WOLFSSL_NO_TLS12 */ +} + +#ifndef WOLFSSL_NO_TLS12 + +int SendFinished(WOLFSSL* ssl) +{ + int sendSz, + finishedSz = ssl->options.tls ? TLS_FINISHED_SZ : + FINISHED_SZ; + byte input[FINISHED_SZ + DTLS_HANDSHAKE_HEADER_SZ]; /* max */ + byte *output; + Hashes* hashes; + int ret; + int headerSz = HANDSHAKE_HEADER_SZ; + int outputSz; + + WOLFSSL_START(WC_FUNC_FINISHED_SEND); + WOLFSSL_ENTER("SendFinished"); + + /* setup encrypt keys */ + if ((ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY)) != 0) + return ret; + + /* check for available size */ + outputSz = sizeof(input) + MAX_MSG_EXTRA; + if ((ret = CheckAvailableSize(ssl, outputSz)) != 0) + return ret; + + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + headerSz += DTLS_HANDSHAKE_EXTRA; + ssl->keys.dtls_epoch++; + ssl->keys.dtls_prev_sequence_number_hi = + ssl->keys.dtls_sequence_number_hi; + ssl->keys.dtls_prev_sequence_number_lo = + ssl->keys.dtls_sequence_number_lo; + ssl->keys.dtls_sequence_number_hi = 0; + ssl->keys.dtls_sequence_number_lo = 0; + } + #endif + + /* get output buffer */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + AddHandShakeHeader(input, finishedSz, 0, finishedSz, finished, ssl); + + /* make finished hashes */ + hashes = (Hashes*)&input[headerSz]; + ret = BuildFinished(ssl, hashes, + ssl->options.side == WOLFSSL_CLIENT_END ? client : server); + if (ret != 0) return ret; + +#ifdef HAVE_SECURE_RENEGOTIATION + if (ssl->secure_renegotiation) { + if (ssl->options.side == WOLFSSL_CLIENT_END) + XMEMCPY(ssl->secure_renegotiation->client_verify_data, hashes, + TLS_FINISHED_SZ); + else + XMEMCPY(ssl->secure_renegotiation->server_verify_data, hashes, + TLS_FINISHED_SZ); + } +#endif + + #ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl)) { + if ((ret = DtlsMsgPoolSave(ssl, input, headerSz + finishedSz)) != 0) + return ret; + } + #endif + + sendSz = BuildMessage(ssl, output, outputSz, input, headerSz + finishedSz, + handshake, 1, 0, 0); + if (sendSz < 0) + return BUILD_MSG_ERROR; + + if (!ssl->options.resuming) { +#ifndef NO_SESSION_CACHE + AddSession(ssl); /* just try */ +#endif + if (ssl->options.side == WOLFSSL_SERVER_END) { + #ifdef OPENSSL_EXTRA + ssl->options.serverState = SERVER_FINISHED_COMPLETE; + ssl->cbmode = SSL_CB_MODE_WRITE; + if (ssl->CBIS != NULL) + ssl->CBIS(ssl, SSL_CB_HANDSHAKE_DONE, SSL_SUCCESS); + #endif + ssl->options.handShakeState = HANDSHAKE_DONE; + ssl->options.handShakeDone = 1; + } + } + else { + if (ssl->options.side == WOLFSSL_CLIENT_END) { + #ifdef OPENSSL_EXTRA + ssl->options.clientState = CLIENT_FINISHED_COMPLETE; + ssl->cbmode = SSL_CB_MODE_WRITE; + if (ssl->CBIS != NULL) + ssl->CBIS(ssl, SSL_CB_HANDSHAKE_DONE, SSL_SUCCESS); + #endif + ssl->options.handShakeState = HANDSHAKE_DONE; + ssl->options.handShakeDone = 1; + } + } + + #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) + if (ssl->hsInfoOn) AddPacketName(ssl, "Finished"); + if (ssl->toInfoOn) + AddPacketInfo(ssl, "Finished", handshake, output, sendSz, + WRITE_PROTO, ssl->heap); + #endif + + ssl->buffers.outputBuffer.length += sendSz; + + ret = SendBuffered(ssl); + + WOLFSSL_LEAVE("SendFinished", ret); + WOLFSSL_END(WC_FUNC_FINISHED_SEND); + + return ret; +} +#endif /* WOLFSSL_NO_TLS12 */ + +#ifndef NO_WOLFSSL_SERVER +#if (!defined(WOLFSSL_NO_TLS12) && \ + (defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \ + defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2))) || \ + (defined(WOLFSSL_TLS13) && defined(HAVE_CERTIFICATE_STATUS_REQUEST)) +/* Parses and decodes the certificate then initializes "request". In the case + * of !ssl->buffers.weOwnCert, ssl->ctx->certOcspRequest gets set to "request". + * + * Returns 0 on success + */ +static int CreateOcspRequest(WOLFSSL* ssl, OcspRequest* request, + DecodedCert* cert, byte* certData, word32 length) +{ + int ret; + + if (request != NULL) + XMEMSET(request, 0, sizeof(OcspRequest)); + + InitDecodedCert(cert, certData, length, ssl->heap); + /* TODO: Setup async support here */ + ret = ParseCertRelative(cert, CERT_TYPE, VERIFY, ssl->ctx->cm); + if (ret != 0) { + WOLFSSL_MSG("ParseCert failed"); + } + if (ret == 0) + ret = InitOcspRequest(request, cert, 0, ssl->heap); + if (ret == 0) { + /* make sure ctx OCSP request is updated */ + if (!ssl->buffers.weOwnCert) { + wolfSSL_Mutex* ocspLock = &ssl->ctx->cm->ocsp_stapling->ocspLock; + if (wc_LockMutex(ocspLock) == 0) { + if (ssl->ctx->certOcspRequest == NULL) + ssl->ctx->certOcspRequest = request; + wc_UnLockMutex(ocspLock); + } + } + } + + FreeDecodedCert(cert); + + return ret; +} + + +/* Creates OCSP response and places it in variable "response". Memory + * management for "buffer* response" is up to the caller. + * + * Also creates an OcspRequest in the case that ocspRequest is null or that + * ssl->buffers.weOwnCert is set. In those cases managing ocspRequest free'ing + * is up to the caller. NOTE: in OcspCreateRequest ssl->ctx->certOcspRequest can + * be set to point to "ocspRequest" and it then should not be free'd since + * wolfSSL_CTX_free will take care of it. + * + * Returns 0 on success + */ +int CreateOcspResponse(WOLFSSL* ssl, OcspRequest** ocspRequest, + buffer* response) +{ + int ret = 0; + OcspRequest* request = NULL; + byte createdRequest = 0; + + if (ssl == NULL || ocspRequest == NULL || response == NULL) + return BAD_FUNC_ARG; + + XMEMSET(response, 0, sizeof(*response)); + request = *ocspRequest; + + /* unable to fetch status. skip. */ + if (ssl->ctx->cm == NULL || ssl->ctx->cm->ocspStaplingEnabled == 0) + return 0; + + if (request == NULL || ssl->buffers.weOwnCert) { + DerBuffer* der = ssl->buffers.certificate; + #ifdef WOLFSSL_SMALL_STACK + DecodedCert* cert = NULL; + #else + DecodedCert cert[1]; + #endif + + /* unable to fetch status. skip. */ + if (der->buffer == NULL || der->length == 0) + return 0; + + #ifdef WOLFSSL_SMALL_STACK + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), ssl->heap, + DYNAMIC_TYPE_DCERT); + if (cert == NULL) + return MEMORY_E; + #endif + request = (OcspRequest*)XMALLOC(sizeof(OcspRequest), ssl->heap, + DYNAMIC_TYPE_OCSP_REQUEST); + if (request == NULL) + ret = MEMORY_E; + + createdRequest = 1; + if (ret == 0) { + ret = CreateOcspRequest(ssl, request, cert, der->buffer, + der->length); + } + + if (ret != 0) { + XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); + request = NULL; + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT); + #endif + } + + if (ret == 0) { + request->ssl = ssl; + ret = CheckOcspRequest(ssl->ctx->cm->ocsp_stapling, request, response); + + /* Suppressing, not critical */ + if (ret == OCSP_CERT_REVOKED || + ret == OCSP_CERT_UNKNOWN || + ret == OCSP_LOOKUP_FAIL) { + ret = 0; + } + } + + /* free request up if error case found otherwise return it */ + if (ret != 0 && createdRequest) { + FreeOcspRequest(request); + XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); + } + + if (ret == 0) + *ocspRequest = request; + + return ret; +} +#endif +#endif /* !NO_WOLFSSL_SERVER */ + +#ifndef WOLFSSL_NO_TLS12 + +#ifndef NO_CERTS +#if !defined(NO_WOLFSSL_SERVER) || !defined(WOLFSSL_NO_CLIENT_AUTH) +/* handle generation of certificate (11) */ +int SendCertificate(WOLFSSL* ssl) +{ + int ret = 0; + word32 certSz, certChainSz, headerSz, listSz, payloadSz; + word32 length, maxFragment; + + WOLFSSL_START(WC_FUNC_CERTIFICATE_SEND); + WOLFSSL_ENTER("SendCertificate"); + + if (ssl->options.usingPSK_cipher || ssl->options.usingAnon_cipher) + return 0; /* not needed */ + + if (ssl->options.sendVerify == SEND_BLANK_CERT) { + #ifdef OPENSSL_EXTRA + if (ssl->version.major == SSLv3_MAJOR + && ssl->version.minor == SSLv3_MINOR){ + SendAlert(ssl, alert_warning, no_certificate); + return 0; + } else { + #endif + certSz = 0; + certChainSz = 0; + headerSz = CERT_HEADER_SZ; + length = CERT_HEADER_SZ; + listSz = 0; + #ifdef OPENSSL_EXTRA + } + #endif + } + else { + if (!ssl->buffers.certificate) { + WOLFSSL_MSG("Send Cert missing certificate buffer"); + return BUFFER_ERROR; + } + certSz = ssl->buffers.certificate->length; + headerSz = 2 * CERT_HEADER_SZ; + /* list + cert size */ + length = certSz + headerSz; + listSz = certSz + CERT_HEADER_SZ; + + /* may need to send rest of chain, already has leading size(s) */ + if (certSz && ssl->buffers.certChain) { + certChainSz = ssl->buffers.certChain->length; + length += certChainSz; + listSz += certChainSz; + } + else + certChainSz = 0; + } + + payloadSz = length; + + if (ssl->fragOffset != 0) + length -= (ssl->fragOffset + headerSz); + + maxFragment = MAX_RECORD_SIZE; + + if (ssl->options.dtls) { + #ifdef WOLFSSL_DTLS + /* The 100 bytes is used to account for the UDP and IP headers. + It can also include the record padding and MAC if the + SendCertificate is called for a secure renegotiation. */ + maxFragment = MAX_MTU - DTLS_RECORD_HEADER_SZ + - DTLS_HANDSHAKE_HEADER_SZ - 100; + #endif /* WOLFSSL_DTLS */ + } + + maxFragment = wolfSSL_GetMaxRecordSize(ssl, maxFragment); + + while (length > 0 && ret == 0) { + byte* output = NULL; + word32 fragSz = 0; + word32 i = RECORD_HEADER_SZ; + int sendSz = RECORD_HEADER_SZ; + + if (!ssl->options.dtls) { + if (ssl->fragOffset == 0) { + if (headerSz + certSz + certChainSz <= + maxFragment - HANDSHAKE_HEADER_SZ) { + + fragSz = headerSz + certSz + certChainSz; + } + else { + fragSz = maxFragment - HANDSHAKE_HEADER_SZ; + } + sendSz += fragSz + HANDSHAKE_HEADER_SZ; + i += HANDSHAKE_HEADER_SZ; + } + else { + fragSz = min(length, maxFragment); + sendSz += fragSz; + } + + if (IsEncryptionOn(ssl, 1)) + sendSz += MAX_MSG_EXTRA; + } + else { + #ifdef WOLFSSL_DTLS + fragSz = min(length, maxFragment); + sendSz += fragSz + DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA + + HANDSHAKE_HEADER_SZ; + i += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA + + HANDSHAKE_HEADER_SZ; + #endif + } + + /* check for available size */ + if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) + return ret; + + /* get output buffer */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + if (ssl->fragOffset == 0) { + if (!ssl->options.dtls) { + AddFragHeaders(output, fragSz, 0, payloadSz, certificate, ssl); + if (!IsEncryptionOn(ssl, 1)) + HashOutputRaw(ssl, output + RECORD_HEADER_SZ, + HANDSHAKE_HEADER_SZ); + } + else { + #ifdef WOLFSSL_DTLS + AddHeaders(output, payloadSz, certificate, ssl); + if (!IsEncryptionOn(ssl, 1)) + HashOutputRaw(ssl, + output + RECORD_HEADER_SZ + DTLS_RECORD_EXTRA, + HANDSHAKE_HEADER_SZ + DTLS_HANDSHAKE_EXTRA); + /* Adding the headers increments these, decrement them for + * actual message header. */ + ssl->keys.dtls_handshake_number--; + AddFragHeaders(output, fragSz, 0, payloadSz, certificate, ssl); + ssl->keys.dtls_handshake_number--; + #endif /* WOLFSSL_DTLS */ + } + + /* list total */ + c32to24(listSz, output + i); + if (!IsEncryptionOn(ssl, 1)) + HashOutputRaw(ssl, output + i, CERT_HEADER_SZ); + i += CERT_HEADER_SZ; + length -= CERT_HEADER_SZ; + fragSz -= CERT_HEADER_SZ; + if (certSz) { + c32to24(certSz, output + i); + if (!IsEncryptionOn(ssl, 1)) + HashOutputRaw(ssl, output + i, CERT_HEADER_SZ); + i += CERT_HEADER_SZ; + length -= CERT_HEADER_SZ; + fragSz -= CERT_HEADER_SZ; + + if (!IsEncryptionOn(ssl, 1)) { + HashOutputRaw(ssl, ssl->buffers.certificate->buffer, certSz); + if (certChainSz) + HashOutputRaw(ssl, ssl->buffers.certChain->buffer, + certChainSz); + } + } + } + else { + if (!ssl->options.dtls) { + AddRecordHeader(output, fragSz, handshake, ssl); + } + else { + #ifdef WOLFSSL_DTLS + AddFragHeaders(output, fragSz, ssl->fragOffset + headerSz, + payloadSz, certificate, ssl); + ssl->keys.dtls_handshake_number--; + #endif /* WOLFSSL_DTLS */ + } + } + + /* member */ + if (certSz && ssl->fragOffset < certSz) { + word32 copySz = min(certSz - ssl->fragOffset, fragSz); + XMEMCPY(output + i, + ssl->buffers.certificate->buffer + ssl->fragOffset, copySz); + i += copySz; + ssl->fragOffset += copySz; + length -= copySz; + fragSz -= copySz; + } + if (certChainSz && fragSz) { + word32 copySz = min(certChainSz + certSz - ssl->fragOffset, fragSz); + XMEMCPY(output + i, + ssl->buffers.certChain->buffer + ssl->fragOffset - certSz, + copySz); + i += copySz; + ssl->fragOffset += copySz; + length -= copySz; + } + + if (IsEncryptionOn(ssl, 1)) { + byte* input = NULL; + int inputSz = i - RECORD_HEADER_SZ; /* build msg adds rec hdr */ + + if (inputSz < 0) { + WOLFSSL_MSG("Send Cert bad inputSz"); + return BUFFER_E; + } + + if (inputSz > 0) { /* clang thinks could be zero, let's help */ + input = (byte*)XMALLOC(inputSz, ssl->heap, + DYNAMIC_TYPE_IN_BUFFER); + if (input == NULL) + return MEMORY_E; + XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz); + } + + sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, + handshake, 1, 0, 0); + + if (inputSz > 0) + XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + + if (sendSz < 0) + return sendSz; + } + else { + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + DtlsSEQIncrement(ssl, CUR_ORDER); + #endif + } + + #ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl)) { + if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) + return ret; + } + #endif + + #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) + if (ssl->hsInfoOn) + AddPacketName(ssl, "Certificate"); + if (ssl->toInfoOn) + AddPacketInfo(ssl, "Certificate", handshake, output, sendSz, + WRITE_PROTO, ssl->heap); + #endif + + ssl->buffers.outputBuffer.length += sendSz; + if (!ssl->options.groupMessages) + ret = SendBuffered(ssl); + } + + if (ret != WANT_WRITE) { + /* Clean up the fragment offset. */ + ssl->fragOffset = 0; + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + ssl->keys.dtls_handshake_number++; + #endif + if (ssl->options.side == WOLFSSL_SERVER_END){ + ssl->options.serverState = SERVER_CERT_COMPLETE; + } + } + + WOLFSSL_LEAVE("SendCertificate", ret); + WOLFSSL_END(WC_FUNC_CERTIFICATE_SEND); + + return ret; +} +#endif /* !NO_WOLFSSL_SERVER || !WOLFSSL_NO_CLIENT_AUTH */ + +/* handle generation of certificate_request (13) */ +int SendCertificateRequest(WOLFSSL* ssl) +{ + byte *output; + int ret; + int sendSz; + word32 i = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + word32 dnLen = 0; +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) + WOLF_STACK_OF(WOLFSSL_X509_NAME)* names; +#endif + + int typeTotal = 1; /* only 1 for now */ + int reqSz = ENUM_LEN + typeTotal + REQ_HEADER_SZ; /* add auth later */ + + WOLFSSL_START(WC_FUNC_CERTIFICATE_REQUEST_SEND); + WOLFSSL_ENTER("SendCertificateRequest"); + + if (IsAtLeastTLSv1_2(ssl)) + reqSz += LENGTH_SZ + ssl->suites->hashSigAlgoSz; + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) + /* Certificate Authorities */ + names = ssl->ctx->ca_names; + while (names != NULL) { + byte seq[MAX_SEQ_SZ]; + + /* 16-bit length | SEQ | Len | DER of name */ + dnLen += OPAQUE16_LEN + SetSequence(names->data.name->rawLen, seq) + + names->data.name->rawLen; + names = names->next; + } + reqSz += dnLen; +#endif + + if (ssl->options.usingPSK_cipher || ssl->options.usingAnon_cipher) + return 0; /* not needed */ + + sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + reqSz; + + if (!ssl->options.dtls) { + if (IsEncryptionOn(ssl, 1)) + sendSz += MAX_MSG_EXTRA; + } + else { + #ifdef WOLFSSL_DTLS + sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + i += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + #endif + } + /* check for available size */ + if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) + return ret; + + /* get output buffer */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + AddHeaders(output, reqSz, certificate_request, ssl); + + /* write to output */ + output[i++] = (byte)typeTotal; /* # of types */ +#ifdef HAVE_ECC + if ((ssl->options.cipherSuite0 == ECC_BYTE || + ssl->options.cipherSuite0 == CHACHA_BYTE) && + ssl->specs.sig_algo == ecc_dsa_sa_algo) { + output[i++] = ecdsa_sign; + } else +#endif /* HAVE_ECC */ + { + output[i++] = rsa_sign; + } + + /* supported hash/sig */ + if (IsAtLeastTLSv1_2(ssl)) { + c16toa(ssl->suites->hashSigAlgoSz, &output[i]); + i += OPAQUE16_LEN; + + XMEMCPY(&output[i], + ssl->suites->hashSigAlgo, ssl->suites->hashSigAlgoSz); + i += ssl->suites->hashSigAlgoSz; + } + + /* Certificate Authorities */ + c16toa((word16)dnLen, &output[i]); /* auth's */ + i += REQ_HEADER_SZ; +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) + names = ssl->ctx->ca_names; + while (names != NULL) { + byte seq[MAX_SEQ_SZ]; + + c16toa((word16)names->data.name->rawLen + + SetSequence(names->data.name->rawLen, seq), &output[i]); + i += OPAQUE16_LEN; + i += SetSequence(names->data.name->rawLen, output + i); + XMEMCPY(output + i, names->data.name->raw, names->data.name->rawLen); + i += names->data.name->rawLen; + names = names->next; + } +#endif + (void)i; + + if (IsEncryptionOn(ssl, 1)) { + byte* input; + int inputSz = i - RECORD_HEADER_SZ; /* build msg adds rec hdr */ + + input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + if (input == NULL) + return MEMORY_E; + + XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz); + sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, + handshake, 1, 0, 0); + XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + + if (sendSz < 0) + return sendSz; + } else { + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + DtlsSEQIncrement(ssl, CUR_ORDER); + if (IsDtlsNotSctpMode(ssl)) { + if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) + return ret; + } + #endif + ret = HashOutput(ssl, output, sendSz, 0); + if (ret != 0) + return ret; + } + + #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) + if (ssl->hsInfoOn) + AddPacketName(ssl, "CertificateRequest"); + if (ssl->toInfoOn) + AddPacketInfo(ssl, "CertificateRequest", handshake, output, sendSz, + WRITE_PROTO, ssl->heap); + #endif + ssl->buffers.outputBuffer.length += sendSz; + if (ssl->options.groupMessages) + ret = 0; + else + ret = SendBuffered(ssl); + + WOLFSSL_LEAVE("SendCertificateRequest", ret); + WOLFSSL_END(WC_FUNC_CERTIFICATE_REQUEST_SEND); + + return ret; +} + +#ifndef NO_WOLFSSL_SERVER +#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) +static int BuildCertificateStatus(WOLFSSL* ssl, byte type, buffer* status, + byte count) +{ + byte* output = NULL; + word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + word32 length = ENUM_LEN; + int sendSz = 0; + int ret = 0; + int i = 0; + + WOLFSSL_ENTER("BuildCertificateStatus"); + + switch (type) { + case WOLFSSL_CSR2_OCSP_MULTI: + length += OPAQUE24_LEN; + FALL_THROUGH; /* followed by */ + + case WOLFSSL_CSR2_OCSP: + for (i = 0; i < count; i++) + length += OPAQUE24_LEN + status[i].length; + break; + + default: + return 0; + } + + sendSz = idx + length; + + if (ssl->keys.encryptionOn) + sendSz += MAX_MSG_EXTRA; + + if ((ret = CheckAvailableSize(ssl, sendSz)) == 0) { + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + AddHeaders(output, length, certificate_status, ssl); + + output[idx++] = type; + + if (type == WOLFSSL_CSR2_OCSP_MULTI) { + c32to24(length - (ENUM_LEN + OPAQUE24_LEN), output + idx); + idx += OPAQUE24_LEN; + } + + for (i = 0; i < count; i++) { + c32to24(status[i].length, output + idx); + idx += OPAQUE24_LEN; + + XMEMCPY(output + idx, status[i].buffer, status[i].length); + idx += status[i].length; + } + + if (IsEncryptionOn(ssl, 1)) { + byte* input; + int inputSz = idx - RECORD_HEADER_SZ; + + input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + if (input == NULL) + return MEMORY_E; + + XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz); + sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, + handshake, 1, 0, 0); + XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + + if (sendSz < 0) + ret = sendSz; + } + else { + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + DtlsSEQIncrement(ssl, CUR_ORDER); + #endif + ret = HashOutput(ssl, output, sendSz, 0); + } + + #ifdef WOLFSSL_DTLS + if (ret == 0 && IsDtlsNotSctpMode(ssl)) + ret = DtlsMsgPoolSave(ssl, output, sendSz); + #endif + + #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) + if (ret == 0 && ssl->hsInfoOn) + AddPacketName(ssl, "CertificateStatus"); + if (ret == 0 && ssl->toInfoOn) + AddPacketInfo(ssl, "CertificateStatus", handshake, output, sendSz, + WRITE_PROTO, ssl->heap); + #endif + + if (ret == 0) { + ssl->buffers.outputBuffer.length += sendSz; + if (!ssl->options.groupMessages) + ret = SendBuffered(ssl); + } + } + + WOLFSSL_LEAVE("BuildCertificateStatus", ret); + return ret; +} +#endif +#endif /* NO_WOLFSSL_SERVER */ + +/* handle generation of certificate_status (22) */ +int SendCertificateStatus(WOLFSSL* ssl) +{ + int ret = 0; + byte status_type = 0; + + WOLFSSL_START(WC_FUNC_CERTIFICATE_STATUS_SEND); + WOLFSSL_ENTER("SendCertificateStatus"); + + (void) ssl; + +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST + status_type = ssl->status_request; +#endif + +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + status_type = status_type ? status_type : ssl->status_request_v2; +#endif + + switch (status_type) { + + #ifndef NO_WOLFSSL_SERVER + #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + /* case WOLFSSL_CSR_OCSP: */ + case WOLFSSL_CSR2_OCSP: + { + OcspRequest* request = ssl->ctx->certOcspRequest; + buffer response; + + ret = CreateOcspResponse(ssl, &request, &response); + + /* if a request was successfully created and not stored in + * ssl->ctx then free it */ + if (ret == 0 && request != ssl->ctx->certOcspRequest) { + FreeOcspRequest(request); + XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); + request = NULL; + } + + if (ret == 0 && response.buffer) { + ret = BuildCertificateStatus(ssl, status_type, &response, 1); + + XFREE(response.buffer, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); + response.buffer = NULL; + } + break; + } + + #endif /* HAVE_CERTIFICATE_STATUS_REQUEST */ + /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */ + + #if defined HAVE_CERTIFICATE_STATUS_REQUEST_V2 + case WOLFSSL_CSR2_OCSP_MULTI: + { + OcspRequest* request = ssl->ctx->certOcspRequest; + buffer responses[1 + MAX_CHAIN_DEPTH]; + int i = 0; + + XMEMSET(responses, 0, sizeof(responses)); + + ret = CreateOcspResponse(ssl, &request, &responses[0]); + + /* if a request was successfully created and not stored in + * ssl->ctx then free it */ + if (ret == 0 && request != ssl->ctx->certOcspRequest) { + FreeOcspRequest(request); + XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); + request = NULL; + } + + if (ret == 0 && (!ssl->ctx->chainOcspRequest[0] + || ssl->buffers.weOwnCertChain)) { + buffer der; + word32 idx = 0; + #ifdef WOLFSSL_SMALL_STACK + DecodedCert* cert = NULL; + #else + DecodedCert cert[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), ssl->heap, + DYNAMIC_TYPE_DCERT); + if (cert == NULL) + return MEMORY_E; + #endif + request = (OcspRequest*)XMALLOC(sizeof(OcspRequest), ssl->heap, + DYNAMIC_TYPE_OCSP_REQUEST); + if (request == NULL) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT); + #endif + return MEMORY_E; + } + + while (idx + OPAQUE24_LEN < ssl->buffers.certChain->length) { + c24to32(ssl->buffers.certChain->buffer + idx, &der.length); + idx += OPAQUE24_LEN; + + der.buffer = ssl->buffers.certChain->buffer + idx; + idx += der.length; + + if (idx > ssl->buffers.certChain->length) + break; + + ret = CreateOcspRequest(ssl, request, cert, der.buffer, + der.length); + if (ret == 0) { + request->ssl = ssl; + ret = CheckOcspRequest(ssl->ctx->cm->ocsp_stapling, + request, &responses[i + 1]); + + /* Suppressing, not critical */ + if (ret == OCSP_CERT_REVOKED || + ret == OCSP_CERT_UNKNOWN || + ret == OCSP_LOOKUP_FAIL) { + ret = 0; + } + + + i++; + FreeOcspRequest(request); + } + } + + XFREE(request, ssl->heap, DYNAMIC_TYPE_OCSP_REQUEST); + #ifdef WOLFSSL_SMALL_STACK + XFREE(cert, ssl->heap, DYNAMIC_TYPE_DCERT); + #endif + } + else { + while (ret == 0 && + NULL != (request = ssl->ctx->chainOcspRequest[i])) { + request->ssl = ssl; + ret = CheckOcspRequest(ssl->ctx->cm->ocsp_stapling, + request, &responses[++i]); + + /* Suppressing, not critical */ + if (ret == OCSP_CERT_REVOKED || + ret == OCSP_CERT_UNKNOWN || + ret == OCSP_LOOKUP_FAIL) { + ret = 0; + } + } + } + + if (responses[0].buffer) { + if (ret == 0) { + ret = BuildCertificateStatus(ssl, status_type, responses, + (byte)i + 1); + } + + for (i = 0; i < 1 + MAX_CHAIN_DEPTH; i++) { + if (responses[i].buffer) { + XFREE(responses[i].buffer, ssl->heap, + DYNAMIC_TYPE_OCSP_REQUEST); + } + } + } + + break; + } + #endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */ + #endif /* NO_WOLFSSL_SERVER */ + + default: + break; + } + + WOLFSSL_LEAVE("SendCertificateStatus", ret); + WOLFSSL_END(WC_FUNC_CERTIFICATE_STATUS_SEND); + + return ret; +} + +#endif /* !NO_CERTS */ + +#endif /* WOLFSSL_NO_TLS12 */ + +int SendData(WOLFSSL* ssl, const void* data, int sz) +{ + int sent = 0, /* plainText size */ + sendSz, + ret, + dtlsExtra = 0; + int groupMsgs = 0; + + if (ssl->error == WANT_WRITE + #ifdef WOLFSSL_ASYNC_CRYPT + || ssl->error == WC_PENDING_E + #endif + ) { + ssl->error = 0; + } + + /* don't allow write after decrypt or mac error */ + if (ssl->error == VERIFY_MAC_ERROR || ssl->error == DECRYPT_ERROR) { + /* For DTLS allow these possible errors and allow the session + to continue despite them */ + if (ssl->options.dtls) { + ssl->error = 0; + } + else { + WOLFSSL_MSG("Not allowing write after decrypt or mac error"); + return WOLFSSL_FATAL_ERROR; + } + } + +#ifdef WOLFSSL_EARLY_DATA + if (ssl->earlyData != no_early_data) { + if (ssl->options.handShakeState == HANDSHAKE_DONE) { + WOLFSSL_MSG("handshake complete, trying to send early data"); + return BUILD_MSG_ERROR; + } + #ifdef WOLFSSL_EARLY_DATA_GROUP + groupMsgs = 1; + #endif + } + else +#endif + if (ssl->options.handShakeState != HANDSHAKE_DONE) { + int err; + WOLFSSL_MSG("handshake not complete, trying to finish"); + if ( (err = wolfSSL_negotiate(ssl)) != WOLFSSL_SUCCESS) { + #ifdef WOLFSSL_ASYNC_CRYPT + /* if async would block return WANT_WRITE */ + if (ssl->error == WC_PENDING_E) { + return WOLFSSL_CBIO_ERR_WANT_WRITE; + } + #endif + return err; + } + } + + /* last time system socket output buffer was full, try again to send */ + if (!groupMsgs && ssl->buffers.outputBuffer.length > 0) { + WOLFSSL_MSG("output buffer was full, trying to send again"); + if ( (ssl->error = SendBuffered(ssl)) < 0) { + WOLFSSL_ERROR(ssl->error); + if (ssl->error == SOCKET_ERROR_E && (ssl->options.connReset || + ssl->options.isClosed)) { + ssl->error = SOCKET_PEER_CLOSED_E; + WOLFSSL_ERROR(ssl->error); + return 0; /* peer reset or closed */ + } + return ssl->error; + } + else { + /* advance sent to previous sent + plain size just sent */ + sent = ssl->buffers.prevSent + ssl->buffers.plainSz; + WOLFSSL_MSG("sent write buffered data"); + + if (sent > sz) { + WOLFSSL_MSG("error: write() after WANT_WRITE with short size"); + return ssl->error = BAD_FUNC_ARG; + } + } + } + +#ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + dtlsExtra = DTLS_RECORD_EXTRA; + } +#endif + + for (;;) { + int len; + byte* out; + byte* sendBuffer = (byte*)data + sent; /* may switch on comp */ + int buffSz; /* may switch on comp */ + int outputSz; +#ifdef HAVE_LIBZ + byte comp[MAX_RECORD_SIZE + MAX_COMP_EXTRA]; +#endif + + if (sent == sz) break; + + len = wolfSSL_GetMaxRecordSize(ssl, sz - sent); + +#ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl)) { + len = min(len, MAX_UDP_SIZE); + } +#endif + buffSz = len; + + /* check for available size */ + outputSz = len + COMP_EXTRA + dtlsExtra + MAX_MSG_EXTRA; + if ((ret = CheckAvailableSize(ssl, outputSz)) != 0) + return ssl->error = ret; + + /* get output buffer */ + out = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + +#ifdef HAVE_LIBZ + if (ssl->options.usingCompression) { + buffSz = myCompress(ssl, sendBuffer, buffSz, comp, sizeof(comp)); + if (buffSz < 0) { + return buffSz; + } + sendBuffer = comp; + } +#endif + if (!ssl->options.tls1_3) { + sendSz = BuildMessage(ssl, out, outputSz, sendBuffer, buffSz, + application_data, 0, 0, 1); + } + else { +#ifdef WOLFSSL_TLS13 + sendSz = BuildTls13Message(ssl, out, outputSz, sendBuffer, buffSz, + application_data, 0, 0, 1); +#else + sendSz = BUFFER_ERROR; +#endif + } + if (sendSz < 0) { + #ifdef WOLFSSL_ASYNC_CRYPT + if (sendSz == WC_PENDING_E) + ssl->error = sendSz; + #endif + return BUILD_MSG_ERROR; + } + + ssl->buffers.outputBuffer.length += sendSz; + + if ( (ssl->error = SendBuffered(ssl)) < 0) { + WOLFSSL_ERROR(ssl->error); + /* store for next call if WANT_WRITE or user embedSend() that + doesn't present like WANT_WRITE */ + ssl->buffers.plainSz = len; + ssl->buffers.prevSent = sent; + if (ssl->error == SOCKET_ERROR_E && (ssl->options.connReset || + ssl->options.isClosed)) { + ssl->error = SOCKET_PEER_CLOSED_E; + WOLFSSL_ERROR(ssl->error); + return 0; /* peer reset or closed */ + } + return ssl->error; + } + + sent += len; + + /* only one message per attempt */ + if (ssl->options.partialWrite == 1) { + WOLFSSL_MSG("Partial Write on, only sending one record"); + break; + } + } + + return sent; +} + +/* process input data */ +int ReceiveData(WOLFSSL* ssl, byte* output, int sz, int peek) +{ + int size; + + WOLFSSL_ENTER("ReceiveData()"); + + /* reset error state */ + if (ssl->error == WANT_READ + #ifdef WOLFSSL_ASYNC_CRYPT + || ssl->error == WC_PENDING_E + #endif + ) { + ssl->error = 0; + } + +#ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + /* In DTLS mode, we forgive some errors and allow the session + * to continue despite them. */ + if (ssl->error == VERIFY_MAC_ERROR || ssl->error == DECRYPT_ERROR) + ssl->error = 0; + } +#endif /* WOLFSSL_DTLS */ + + if (ssl->error != 0 && ssl->error != WANT_WRITE) { + WOLFSSL_MSG("User calling wolfSSL_read in error state, not allowed"); + return ssl->error; + } + +#ifdef WOLFSSL_EARLY_DATA + if (ssl->earlyData != no_early_data) { + } + else +#endif + if (ssl->options.handShakeState != HANDSHAKE_DONE) { + int err; + WOLFSSL_MSG("Handshake not complete, trying to finish"); + if ( (err = wolfSSL_negotiate(ssl)) != WOLFSSL_SUCCESS) { + #ifdef WOLFSSL_ASYNC_CRYPT + /* if async would block return WANT_WRITE */ + if (ssl->error == WC_PENDING_E) { + return WOLFSSL_CBIO_ERR_WANT_READ; + } + #endif + return err; + } + } + +#ifdef HAVE_SECURE_RENEGOTIATION +startScr: + if (ssl->secure_renegotiation && ssl->secure_renegotiation->startScr) { + int err; + WOLFSSL_MSG("Need to start scr, server requested"); + if ( (err = wolfSSL_Rehandshake(ssl)) != WOLFSSL_SUCCESS) + return err; + ssl->secure_renegotiation->startScr = 0; /* only start once */ + } +#endif + + while (ssl->buffers.clearOutputBuffer.length == 0) { + if ( (ssl->error = ProcessReply(ssl)) < 0) { + WOLFSSL_ERROR(ssl->error); + if (ssl->error == ZERO_RETURN) { + WOLFSSL_MSG("Zero return, no more data coming"); + return 0; /* no more data coming */ + } + if (ssl->error == SOCKET_ERROR_E) { + if (ssl->options.connReset || ssl->options.isClosed) { + WOLFSSL_MSG("Peer reset or closed, connection done"); + ssl->error = SOCKET_PEER_CLOSED_E; + WOLFSSL_ERROR(ssl->error); + return 0; /* peer reset or closed */ + } + } + return ssl->error; + } + #ifdef HAVE_SECURE_RENEGOTIATION + if (ssl->secure_renegotiation && + ssl->secure_renegotiation->startScr) { + goto startScr; + } + #endif + } + + if (sz < (int)ssl->buffers.clearOutputBuffer.length) + size = sz; + else + size = ssl->buffers.clearOutputBuffer.length; + + XMEMCPY(output, ssl->buffers.clearOutputBuffer.buffer, size); + + if (peek == 0) { + ssl->buffers.clearOutputBuffer.length -= size; + ssl->buffers.clearOutputBuffer.buffer += size; + } + + if (ssl->buffers.clearOutputBuffer.length == 0 && + ssl->buffers.inputBuffer.dynamicFlag) + ShrinkInputBuffer(ssl, NO_FORCED_FREE); + + WOLFSSL_LEAVE("ReceiveData()", size); + return size; +} + + +/* send alert message */ +int SendAlert(WOLFSSL* ssl, int severity, int type) +{ + byte input[ALERT_SIZE]; + byte *output; + int sendSz; + int ret; + int outputSz; + int dtlsExtra = 0; + +#ifdef HAVE_WRITE_DUP + if (ssl->dupWrite && ssl->dupSide == READ_DUP_SIDE) { + int notifyErr = 0; + + WOLFSSL_MSG("Read dup side cannot write alerts, notifying sibling"); + + if (type == close_notify) { + notifyErr = ZERO_RETURN; + } else if (severity == alert_fatal) { + notifyErr = FATAL_ERROR; + } + + if (notifyErr != 0) { + return NotifyWriteSide(ssl, notifyErr); + } + + return 0; + } +#endif + + /* if sendalert is called again for nonblocking */ + if (ssl->options.sendAlertState != 0) { + ret = SendBuffered(ssl); + if (ret == 0) + ssl->options.sendAlertState = 0; + return ret; + } + + #ifdef OPENSSL_EXTRA + if (ssl->CBIS != NULL) { + ssl->CBIS(ssl, SSL_CB_ALERT, type); + } + #endif + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + dtlsExtra = DTLS_RECORD_EXTRA; + #endif + + /* check for available size */ + outputSz = ALERT_SIZE + MAX_MSG_EXTRA + dtlsExtra; + if ((ret = CheckAvailableSize(ssl, outputSz)) != 0) + return ret; + + /* Check output buffer */ + if (ssl->buffers.outputBuffer.buffer == NULL) + return BUFFER_E; + + /* get output buffer */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + input[0] = (byte)severity; + input[1] = (byte)type; + ssl->alert_history.last_tx.code = type; + ssl->alert_history.last_tx.level = severity; + if (severity == alert_fatal) { + ssl->options.isClosed = 1; /* Don't send close_notify */ + } + + /* only send encrypted alert if handshake actually complete, otherwise + other side may not be able to handle it */ + if (IsEncryptionOn(ssl, 1) && (IsAtLeastTLSv1_3(ssl->version) || + ssl->options.handShakeDone)) { + sendSz = BuildMessage(ssl, output, outputSz, input, ALERT_SIZE, alert, + 0, 0, 0); + } + else { + + AddRecordHeader(output, ALERT_SIZE, alert, ssl); + output += RECORD_HEADER_SZ; + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + output += DTLS_RECORD_EXTRA; + #endif + XMEMCPY(output, input, ALERT_SIZE); + + sendSz = RECORD_HEADER_SZ + ALERT_SIZE; + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + sendSz += DTLS_RECORD_EXTRA; + #endif + } + if (sendSz < 0) + return BUILD_MSG_ERROR; + + #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) + if (ssl->hsInfoOn) + AddPacketName(ssl, "Alert"); + if (ssl->toInfoOn) + AddPacketInfo(ssl, "Alert", alert, output, sendSz, WRITE_PROTO, + ssl->heap); + #endif + + ssl->buffers.outputBuffer.length += sendSz; + ssl->options.sendAlertState = 1; + + return SendBuffered(ssl); +} + +const char* wolfSSL_ERR_reason_error_string(unsigned long e) +{ +#ifdef NO_ERROR_STRINGS + + (void)e; + return "no support for error strings built in"; + +#else + + int error = (int)e; + + /* pass to wolfCrypt */ + if (error < MAX_CODE_E && error > MIN_CODE_E) { + return wc_GetErrorString(error); + } + + switch (error) { + +#ifdef WOLFSSL_WPAS + case 0 : + return "ok"; +#endif + + case UNSUPPORTED_SUITE : + return "unsupported cipher suite"; + + case INPUT_CASE_ERROR : + return "input state error"; + + case PREFIX_ERROR : + return "bad index to key rounds"; + + case MEMORY_ERROR : + return "out of memory"; + + case VERIFY_FINISHED_ERROR : + return "verify problem on finished"; + + case VERIFY_MAC_ERROR : + return "verify mac problem"; + + case PARSE_ERROR : + return "parse error on header"; + + case SIDE_ERROR : + return "wrong client/server type"; + + case NO_PEER_CERT : + return "peer didn't send cert"; + + case UNKNOWN_HANDSHAKE_TYPE : + return "weird handshake type"; + + case SOCKET_ERROR_E : + return "error state on socket"; + + case SOCKET_NODATA : + return "expected data, not there"; + + case INCOMPLETE_DATA : + return "don't have enough data to complete task"; + + case UNKNOWN_RECORD_TYPE : + return "unknown type in record hdr"; + + case DECRYPT_ERROR : + return "error during decryption"; + + case FATAL_ERROR : + return "received alert fatal error"; + + case ENCRYPT_ERROR : + return "error during encryption"; + + case FREAD_ERROR : + return "fread problem"; + + case NO_PEER_KEY : + return "need peer's key"; + + case NO_PRIVATE_KEY : + return "need the private key"; + + case NO_DH_PARAMS : + return "server missing DH params"; + + case RSA_PRIVATE_ERROR : + return "error during rsa priv op"; + + case MATCH_SUITE_ERROR : + return "can't match cipher suite"; + + case COMPRESSION_ERROR : + return "compression mismatch error"; + + case BUILD_MSG_ERROR : + return "build message failure"; + + case BAD_HELLO : + return "client hello malformed"; + + case DOMAIN_NAME_MISMATCH : + return "peer subject name mismatch"; + + case WANT_READ : + case WOLFSSL_ERROR_WANT_READ : + return "non-blocking socket wants data to be read"; + + case NOT_READY_ERROR : + return "handshake layer not ready yet, complete first"; + + case VERSION_ERROR : + return "record layer version error"; + + case WANT_WRITE : + case WOLFSSL_ERROR_WANT_WRITE : + return "non-blocking socket write buffer full"; + + case BUFFER_ERROR : + return "malformed buffer input error"; + + case VERIFY_CERT_ERROR : + return "verify problem on certificate"; + + case VERIFY_SIGN_ERROR : + return "verify problem based on signature"; + + case CLIENT_ID_ERROR : + return "psk client identity error"; + + case SERVER_HINT_ERROR: + return "psk server hint error"; + + case PSK_KEY_ERROR: + return "psk key callback error"; + + case NTRU_KEY_ERROR: + return "NTRU key error"; + + case NTRU_DRBG_ERROR: + return "NTRU drbg error"; + + case NTRU_ENCRYPT_ERROR: + return "NTRU encrypt error"; + + case NTRU_DECRYPT_ERROR: + return "NTRU decrypt error"; + + case GETTIME_ERROR: + return "gettimeofday() error"; + + case GETITIMER_ERROR: + return "getitimer() error"; + + case SIGACT_ERROR: + return "sigaction() error"; + + case SETITIMER_ERROR: + return "setitimer() error"; + + case LENGTH_ERROR: + return "record layer length error"; + + case PEER_KEY_ERROR: + return "cant decode peer key"; + + case ZERO_RETURN: + case WOLFSSL_ERROR_ZERO_RETURN: + return "peer sent close notify alert"; + + case ECC_CURVETYPE_ERROR: + return "Bad ECC Curve Type or unsupported"; + + case ECC_CURVE_ERROR: + return "Bad ECC Curve or unsupported"; + + case ECC_PEERKEY_ERROR: + return "Bad ECC Peer Key"; + + case ECC_MAKEKEY_ERROR: + return "ECC Make Key failure"; + + case ECC_EXPORT_ERROR: + return "ECC Export Key failure"; + + case ECC_SHARED_ERROR: + return "ECC DHE shared failure"; + + case NOT_CA_ERROR: + return "Not a CA by basic constraint error"; + + case HTTP_TIMEOUT: + return "HTTP timeout for OCSP or CRL req"; + + case BAD_CERT_MANAGER_ERROR: + return "Bad Cert Manager error"; + + case OCSP_CERT_REVOKED: + return "OCSP Cert revoked"; + + case CRL_CERT_REVOKED: + return "CRL Cert revoked"; + + case CRL_MISSING: + return "CRL missing, not loaded"; + + case MONITOR_SETUP_E: + return "CRL monitor setup error"; + + case THREAD_CREATE_E: + return "Thread creation problem"; + + case OCSP_NEED_URL: + return "OCSP need URL"; + + case OCSP_CERT_UNKNOWN: + return "OCSP Cert unknown"; + + case OCSP_LOOKUP_FAIL: + return "OCSP Responder lookup fail"; + + case MAX_CHAIN_ERROR: + return "Maximum Chain Depth Exceeded"; + + case COOKIE_ERROR: + return "DTLS Cookie Error"; + + case SEQUENCE_ERROR: + return "DTLS Sequence Error"; + + case SUITES_ERROR: + return "Suites Pointer Error"; + + case OUT_OF_ORDER_E: + return "Out of order message, fatal"; + + case BAD_KEA_TYPE_E: + return "Bad KEA type found"; + + case SANITY_CIPHER_E: + return "Sanity check on ciphertext failed"; + + case RECV_OVERFLOW_E: + return "Receive callback returned more than requested"; + + case GEN_COOKIE_E: + return "Generate Cookie Error"; + + case NO_PEER_VERIFY: + return "Need peer certificate verify Error"; + + case FWRITE_ERROR: + return "fwrite Error"; + + case CACHE_MATCH_ERROR: + return "Cache restore header match Error"; + + case UNKNOWN_SNI_HOST_NAME_E: + return "Unrecognized host name Error"; + + case UNKNOWN_MAX_FRAG_LEN_E: + return "Unrecognized max frag len Error"; + + case KEYUSE_SIGNATURE_E: + return "Key Use digitalSignature not set Error"; + + case KEYUSE_ENCIPHER_E: + return "Key Use keyEncipherment not set Error"; + + case EXTKEYUSE_AUTH_E: + return "Ext Key Use server/client auth not set Error"; + + case SEND_OOB_READ_E: + return "Send Callback Out of Bounds Read Error"; + + case SECURE_RENEGOTIATION_E: + return "Invalid Renegotiation Error"; + + case SESSION_TICKET_LEN_E: + return "Session Ticket Too Long Error"; + + case SESSION_TICKET_EXPECT_E: + return "Session Ticket Error"; + + case SESSION_SECRET_CB_E: + return "Session Secret Callback Error"; + + case NO_CHANGE_CIPHER_E: + return "Finished received from peer before Change Cipher Error"; + + case SANITY_MSG_E: + return "Sanity Check on message order Error"; + + case DUPLICATE_MSG_E: + return "Duplicate HandShake message Error"; + + case SNI_UNSUPPORTED: + return "Protocol version does not support SNI Error"; + + case SOCKET_PEER_CLOSED_E: + return "Peer closed underlying transport Error"; + + case BAD_TICKET_KEY_CB_SZ: + return "Bad user session ticket key callback Size Error"; + + case BAD_TICKET_MSG_SZ: + return "Bad session ticket message Size Error"; + + case BAD_TICKET_ENCRYPT: + return "Bad user ticket callback encrypt Error"; + + case DH_KEY_SIZE_E: + return "DH key too small Error"; + + case SNI_ABSENT_ERROR: + return "No Server Name Indication extension Error"; + + case RSA_SIGN_FAULT: + return "RSA Signature Fault Error"; + + case HANDSHAKE_SIZE_ERROR: + return "Handshake message too large Error"; + + case UNKNOWN_ALPN_PROTOCOL_NAME_E: + return "Unrecognized protocol name Error"; + + case BAD_CERTIFICATE_STATUS_ERROR: + return "Bad Certificate Status Message Error"; + + case OCSP_INVALID_STATUS: + return "Invalid OCSP Status Error"; + + case OCSP_WANT_READ: + return "OCSP nonblock wants read"; + + case RSA_KEY_SIZE_E: + return "RSA key too small"; + + case ECC_KEY_SIZE_E: + return "ECC key too small"; + + case DTLS_EXPORT_VER_E: + return "Version needs updated after code change or version mismatch"; + + case INPUT_SIZE_E: + return "Input size too large Error"; + + case CTX_INIT_MUTEX_E: + return "Initialize ctx mutex error"; + + case EXT_MASTER_SECRET_NEEDED_E: + return "Extended Master Secret must be enabled to resume EMS session"; + + case DTLS_POOL_SZ_E: + return "Maximum DTLS pool size exceeded"; + + case DECODE_E: + return "Decode handshake message error"; + + case WRITE_DUP_READ_E: + return "Write dup write side can't read error"; + + case WRITE_DUP_WRITE_E: + return "Write dup read side can't write error"; + + case INVALID_CERT_CTX_E: + return "Certificate context does not match request or not empty"; + + case BAD_KEY_SHARE_DATA: + return "The Key Share data contains group that wasn't in Client Hello"; + + case MISSING_HANDSHAKE_DATA: + return "The handshake message is missing required data"; + + case BAD_BINDER: + return "Binder value does not match value server calculated"; + + case EXT_NOT_ALLOWED: + return "Extension type not allowed in handshake message type"; + + case INVALID_PARAMETER: + return "The security parameter is invalid"; + + case UNSUPPORTED_EXTENSION: + return "TLS Extension not requested by the client"; + + case PRF_MISSING: + return "Pseudo-random function is not enabled"; + + case KEY_SHARE_ERROR: + return "Key share extension did not contain a valid named group"; + + case POST_HAND_AUTH_ERROR: + return "Client will not do post handshake authentication"; + + case HRR_COOKIE_ERROR: + return "Cookie does not match one sent in HelloRetryRequest"; + + case MCAST_HIGHWATER_CB_E: + return "Multicast highwater callback returned error"; + + case ALERT_COUNT_E: + return "Alert Count exceeded error"; + + case EXT_MISSING: + return "Required TLS extension missing"; + + case DTLS_RETX_OVER_TX: + return "DTLS interrupting flight transmit with retransmit"; + + case DH_PARAMS_NOT_FFDHE_E: + return "Server DH parameters were not from the FFDHE set as required"; + + case TCA_INVALID_ID_TYPE: + return "TLS Extension Trusted CA ID type invalid"; + + case TCA_ABSENT_ERROR: + return "TLS Extension Trusted CA ID response absent"; + + default : + return "unknown error number"; + } + +#endif /* NO_ERROR_STRINGS */ +} + +void SetErrorString(int error, char* str) +{ + XSTRNCPY(str, wolfSSL_ERR_reason_error_string(error), WOLFSSL_MAX_ERROR_SZ); +} + +#ifndef NO_ERROR_STRINGS + #define SUITE_INFO(x,y,z,w) {(x),(y),(z),(w)} +#else + #define SUITE_INFO(x,y,z,w) {(x),(z),(w)} +#endif + +static const CipherSuiteInfo cipher_names[] = +{ + +#ifdef BUILD_TLS_AES_128_GCM_SHA256 + SUITE_INFO("TLS13-AES128-GCM-SHA256","TLS_AES_128_GCM_SHA256",TLS13_BYTE,TLS_AES_128_GCM_SHA256), +#endif + +#ifdef BUILD_TLS_AES_256_GCM_SHA384 + SUITE_INFO("TLS13-AES256-GCM-SHA384","TLS_AES_256_GCM_SHA384",TLS13_BYTE,TLS_AES_256_GCM_SHA384), +#endif + +#ifdef BUILD_TLS_CHACHA20_POLY1305_SHA256 + SUITE_INFO("TLS13-CHACHA20-POLY1305-SHA256","TLS_CHACHA20_POLY1305_SHA256",TLS13_BYTE,TLS_CHACHA20_POLY1305_SHA256), +#endif + +#ifdef BUILD_TLS_AES_128_CCM_SHA256 + SUITE_INFO("TLS13-AES128-CCM-SHA256","TLS_AES_128_CCM_SHA256",TLS13_BYTE,TLS_AES_128_CCM_SHA256), +#endif + +#ifdef BUILD_TLS_AES_128_CCM_8_SHA256 + SUITE_INFO("TLS13-AES128-CCM-8-SHA256","TLS_AES_128_CCM_8_SHA256",TLS13_BYTE,TLS_AES_128_CCM_8_SHA256), +#endif + +#ifndef WOLFSSL_NO_TLS12 + +#ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA + SUITE_INFO("RC4-SHA","SSL_RSA_WITH_RC4_128_SHA",CIPHER_BYTE,SSL_RSA_WITH_RC4_128_SHA), +#endif + +#ifdef BUILD_SSL_RSA_WITH_RC4_128_MD5 + SUITE_INFO("RC4-MD5","SSL_RSA_WITH_RC4_128_MD5",CIPHER_BYTE,SSL_RSA_WITH_RC4_128_MD5), +#endif + +#ifdef BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA + SUITE_INFO("DES-CBC3-SHA","SSL_RSA_WITH_3DES_EDE_CBC_SHA",CIPHER_BYTE,SSL_RSA_WITH_3DES_EDE_CBC_SHA), +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA + SUITE_INFO("AES128-SHA","TLS_RSA_WITH_AES_128_CBC_SHA",CIPHER_BYTE,TLS_RSA_WITH_AES_128_CBC_SHA), +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA + SUITE_INFO("AES256-SHA","TLS_RSA_WITH_AES_256_CBC_SHA",CIPHER_BYTE,TLS_RSA_WITH_AES_256_CBC_SHA), +#endif + +#ifdef BUILD_TLS_RSA_WITH_NULL_MD5 + SUITE_INFO("NULL-MD5","TLS_RSA_WITH_NULL_MD5",CIPHER_BYTE,TLS_RSA_WITH_NULL_MD5), +#endif + +#ifdef BUILD_TLS_RSA_WITH_NULL_SHA + SUITE_INFO("NULL-SHA","TLS_RSA_WITH_NULL_SHA",CIPHER_BYTE,TLS_RSA_WITH_NULL_SHA), +#endif + +#ifdef BUILD_TLS_RSA_WITH_NULL_SHA256 + SUITE_INFO("NULL-SHA256","TLS_RSA_WITH_NULL_SHA256",CIPHER_BYTE,TLS_RSA_WITH_NULL_SHA256), +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA + SUITE_INFO("DHE-RSA-AES128-SHA","TLS_DHE_RSA_WITH_AES_128_CBC_SHA",CIPHER_BYTE,TLS_DHE_RSA_WITH_AES_128_CBC_SHA), +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA + SUITE_INFO("DHE-RSA-AES256-SHA","TLS_DHE_RSA_WITH_AES_256_CBC_SHA",CIPHER_BYTE,TLS_DHE_RSA_WITH_AES_256_CBC_SHA), +#endif + +#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 + SUITE_INFO("DHE-PSK-AES256-GCM-SHA384","TLS_DHE_PSK_WITH_AES_256_GCM_SHA384",CIPHER_BYTE,TLS_DHE_PSK_WITH_AES_256_GCM_SHA384), +#endif + +#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + SUITE_INFO("DHE-PSK-AES128-GCM-SHA256","TLS_DHE_PSK_WITH_AES_128_GCM_SHA256",CIPHER_BYTE,TLS_DHE_PSK_WITH_AES_128_GCM_SHA256), +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_256_GCM_SHA384 + SUITE_INFO("PSK-AES256-GCM-SHA384","TLS_PSK_WITH_AES_256_GCM_SHA384",CIPHER_BYTE,TLS_PSK_WITH_AES_256_GCM_SHA384), +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_128_GCM_SHA256 + SUITE_INFO("PSK-AES128-GCM-SHA256","TLS_PSK_WITH_AES_128_GCM_SHA256",CIPHER_BYTE,TLS_PSK_WITH_AES_128_GCM_SHA256), +#endif + +#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + SUITE_INFO("DHE-PSK-AES256-CBC-SHA384","TLS_DHE_PSK_WITH_AES_256_CBC_SHA384",CIPHER_BYTE,TLS_DHE_PSK_WITH_AES_256_CBC_SHA384), +#endif + +#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + SUITE_INFO("DHE-PSK-AES128-CBC-SHA256","TLS_DHE_PSK_WITH_AES_128_CBC_SHA256",CIPHER_BYTE,TLS_DHE_PSK_WITH_AES_128_CBC_SHA256), +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA384 + SUITE_INFO("PSK-AES256-CBC-SHA384","TLS_PSK_WITH_AES_256_CBC_SHA384",CIPHER_BYTE,TLS_PSK_WITH_AES_256_CBC_SHA384), +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA256 + SUITE_INFO("PSK-AES128-CBC-SHA256","TLS_PSK_WITH_AES_128_CBC_SHA256",CIPHER_BYTE,TLS_PSK_WITH_AES_128_CBC_SHA256), +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA + SUITE_INFO("PSK-AES128-CBC-SHA","TLS_PSK_WITH_AES_128_CBC_SHA",CIPHER_BYTE,TLS_PSK_WITH_AES_128_CBC_SHA), +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA + SUITE_INFO("PSK-AES256-CBC-SHA","TLS_PSK_WITH_AES_256_CBC_SHA",CIPHER_BYTE,TLS_PSK_WITH_AES_256_CBC_SHA), +#endif + +#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CCM + SUITE_INFO("DHE-PSK-AES128-CCM","TLS_DHE_PSK_WITH_AES_128_CCM",ECC_BYTE,TLS_DHE_PSK_WITH_AES_128_CCM), +#endif + +#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_CCM + SUITE_INFO("DHE-PSK-AES256-CCM","TLS_DHE_PSK_WITH_AES_256_CCM",ECC_BYTE,TLS_DHE_PSK_WITH_AES_256_CCM), +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_128_CCM + SUITE_INFO("PSK-AES128-CCM","TLS_PSK_WITH_AES_128_CCM",ECC_BYTE,TLS_PSK_WITH_AES_128_CCM), +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_256_CCM + SUITE_INFO("PSK-AES256-CCM","TLS_PSK_WITH_AES_256_CCM",ECC_BYTE,TLS_PSK_WITH_AES_256_CCM), +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_128_CCM_8 + SUITE_INFO("PSK-AES128-CCM-8","TLS_PSK_WITH_AES_128_CCM_8",ECC_BYTE,TLS_PSK_WITH_AES_128_CCM_8), +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_256_CCM_8 + SUITE_INFO("PSK-AES256-CCM-8","TLS_PSK_WITH_AES_256_CCM_8",ECC_BYTE,TLS_PSK_WITH_AES_256_CCM_8), +#endif + +#ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA384 + SUITE_INFO("DHE-PSK-NULL-SHA384","TLS_DHE_PSK_WITH_NULL_SHA384",CIPHER_BYTE,TLS_DHE_PSK_WITH_NULL_SHA384), +#endif + +#ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA256 + SUITE_INFO("DHE-PSK-NULL-SHA256","TLS_DHE_PSK_WITH_NULL_SHA256",CIPHER_BYTE,TLS_DHE_PSK_WITH_NULL_SHA256), +#endif + +#ifdef BUILD_TLS_PSK_WITH_NULL_SHA384 + SUITE_INFO("PSK-NULL-SHA384","TLS_PSK_WITH_NULL_SHA384",CIPHER_BYTE,TLS_PSK_WITH_NULL_SHA384), +#endif + +#ifdef BUILD_TLS_PSK_WITH_NULL_SHA256 + SUITE_INFO("PSK-NULL-SHA256","TLS_PSK_WITH_NULL_SHA256",CIPHER_BYTE,TLS_PSK_WITH_NULL_SHA256), +#endif + +#ifdef BUILD_TLS_PSK_WITH_NULL_SHA + SUITE_INFO("PSK-NULL-SHA","TLS_PSK_WITH_NULL_SHA",CIPHER_BYTE,TLS_PSK_WITH_NULL_SHA), +#endif + +#ifdef BUILD_TLS_RSA_WITH_HC_128_MD5 + SUITE_INFO("HC128-MD5","TLS_RSA_WITH_HC_128_MD5",CIPHER_BYTE,TLS_RSA_WITH_HC_128_MD5), +#endif + +#ifdef BUILD_TLS_RSA_WITH_HC_128_SHA + SUITE_INFO("HC128-SHA","TLS_RSA_WITH_HC_128_SHA",CIPHER_BYTE,TLS_RSA_WITH_HC_128_SHA), +#endif + +#ifdef BUILD_TLS_RSA_WITH_HC_128_B2B256 + SUITE_INFO("HC128-B2B256","TLS_RSA_WITH_HC_128_B2B256",CIPHER_BYTE,TLS_RSA_WITH_HC_128_B2B256), +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_B2B256 + SUITE_INFO("AES128-B2B256","TLS_RSA_WITH_AES_128_CBC_B2B256",CIPHER_BYTE,TLS_RSA_WITH_AES_128_CBC_B2B256), +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_B2B256 + SUITE_INFO("AES256-B2B256","TLS_RSA_WITH_AES_256_CBC_B2B256",CIPHER_BYTE,TLS_RSA_WITH_AES_256_CBC_B2B256), +#endif + +#ifdef BUILD_TLS_RSA_WITH_RABBIT_SHA + SUITE_INFO("RABBIT-SHA","TLS_RSA_WITH_RABBIT_SHA",CIPHER_BYTE,TLS_RSA_WITH_RABBIT_SHA), +#endif + +#ifdef BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA + SUITE_INFO("NTRU-RC4-SHA","TLS_NTRU_RSA_WITH_RC4_128_SHA",CIPHER_BYTE,TLS_NTRU_RSA_WITH_RC4_128_SHA), +#endif + +#ifdef BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA + SUITE_INFO("NTRU-DES-CBC3-SHA","TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA",CIPHER_BYTE,TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA), +#endif + +#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA + SUITE_INFO("NTRU-AES128-SHA","TLS_NTRU_RSA_WITH_AES_128_CBC_SHA",CIPHER_BYTE,TLS_NTRU_RSA_WITH_AES_128_CBC_SHA), +#endif + +#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA + SUITE_INFO("NTRU-AES256-SHA","TLS_NTRU_RSA_WITH_AES_256_CBC_SHA",CIPHER_BYTE,TLS_NTRU_RSA_WITH_AES_256_CBC_SHA), +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_128_CCM_8 + SUITE_INFO("AES128-CCM-8","TLS_RSA_WITH_AES_128_CCM_8",ECC_BYTE,TLS_RSA_WITH_AES_128_CCM_8), +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_256_CCM_8 + SUITE_INFO("AES256-CCM-8","TLS_RSA_WITH_AES_256_CCM_8",ECC_BYTE,TLS_RSA_WITH_AES_256_CCM_8), +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM + SUITE_INFO("ECDHE-ECDSA-AES128-CCM","TLS_ECDHE_ECDSA_WITH_AES_128_CCM",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_128_CCM), +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 + SUITE_INFO("ECDHE-ECDSA-AES128-CCM-8","TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8), +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 + SUITE_INFO("ECDHE-ECDSA-AES256-CCM-8","TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8), +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + SUITE_INFO("ECDHE-RSA-AES128-SHA","TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",ECC_BYTE,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA), +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + SUITE_INFO("ECDHE-RSA-AES256-SHA","TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",ECC_BYTE,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA), +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + SUITE_INFO("ECDHE-ECDSA-AES128-SHA","TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA), +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + SUITE_INFO("ECDHE-ECDSA-AES256-SHA","TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA), +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA + SUITE_INFO("ECDHE-RSA-RC4-SHA","TLS_ECDHE_RSA_WITH_RC4_128_SHA",ECC_BYTE,TLS_ECDHE_RSA_WITH_RC4_128_SHA), +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + SUITE_INFO("ECDHE-RSA-DES-CBC3-SHA","TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",ECC_BYTE,TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA), +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA + SUITE_INFO("ECDHE-ECDSA-RC4-SHA","TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_RC4_128_SHA), +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA + SUITE_INFO("ECDHE-ECDSA-DES-CBC3-SHA","TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA), +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA256 + SUITE_INFO("AES128-SHA256","TLS_RSA_WITH_AES_128_CBC_SHA256",CIPHER_BYTE,TLS_RSA_WITH_AES_128_CBC_SHA256), +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA256 + SUITE_INFO("AES256-SHA256","TLS_RSA_WITH_AES_256_CBC_SHA256",CIPHER_BYTE,TLS_RSA_WITH_AES_256_CBC_SHA256), +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + SUITE_INFO("DHE-RSA-AES128-SHA256","TLS_DHE_RSA_WITH_AES_128_CBC_SHA256",CIPHER_BYTE,TLS_DHE_RSA_WITH_AES_128_CBC_SHA256), +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + SUITE_INFO("DHE-RSA-AES256-SHA256","TLS_DHE_RSA_WITH_AES_256_CBC_SHA256",CIPHER_BYTE,TLS_DHE_RSA_WITH_AES_256_CBC_SHA256), +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + SUITE_INFO("ECDH-RSA-AES128-SHA","TLS_ECDH_RSA_WITH_AES_128_CBC_SHA",ECC_BYTE,TLS_ECDH_RSA_WITH_AES_128_CBC_SHA), +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + SUITE_INFO("ECDH-RSA-AES256-SHA","TLS_ECDH_RSA_WITH_AES_256_CBC_SHA",ECC_BYTE,TLS_ECDH_RSA_WITH_AES_256_CBC_SHA), +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + SUITE_INFO("ECDH-ECDSA-AES128-SHA","TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA",ECC_BYTE,TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA), +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + SUITE_INFO("ECDH-ECDSA-AES256-SHA","TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA",ECC_BYTE,TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA), +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_RC4_128_SHA + SUITE_INFO("ECDH-RSA-RC4-SHA","TLS_ECDH_RSA_WITH_RC4_128_SHA",ECC_BYTE,TLS_ECDH_RSA_WITH_RC4_128_SHA), +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA + SUITE_INFO("ECDH-RSA-DES-CBC3-SHA","TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA",ECC_BYTE,TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA), +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_RC4_128_SHA + SUITE_INFO("ECDH-ECDSA-RC4-SHA","TLS_ECDH_ECDSA_WITH_RC4_128_SHA",ECC_BYTE,TLS_ECDH_ECDSA_WITH_RC4_128_SHA), +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA + SUITE_INFO("ECDH-ECDSA-DES-CBC3-SHA","TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA",ECC_BYTE,TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA), +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256 + SUITE_INFO("AES128-GCM-SHA256","TLS_RSA_WITH_AES_128_GCM_SHA256",CIPHER_BYTE,TLS_RSA_WITH_AES_128_GCM_SHA256), +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_256_GCM_SHA384 + SUITE_INFO("AES256-GCM-SHA384","TLS_RSA_WITH_AES_256_GCM_SHA384",CIPHER_BYTE,TLS_RSA_WITH_AES_256_GCM_SHA384), +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + SUITE_INFO("DHE-RSA-AES128-GCM-SHA256","TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",CIPHER_BYTE,TLS_DHE_RSA_WITH_AES_128_GCM_SHA256), +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + SUITE_INFO("DHE-RSA-AES256-GCM-SHA384","TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",CIPHER_BYTE,TLS_DHE_RSA_WITH_AES_256_GCM_SHA384), +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + SUITE_INFO("ECDHE-RSA-AES128-GCM-SHA256","TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",ECC_BYTE,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256), +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + SUITE_INFO("ECDHE-RSA-AES256-GCM-SHA384","TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",ECC_BYTE,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384), +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + SUITE_INFO("ECDHE-ECDSA-AES128-GCM-SHA256","TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256), +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + SUITE_INFO("ECDHE-ECDSA-AES256-GCM-SHA384","TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384), +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + SUITE_INFO("ECDH-RSA-AES128-GCM-SHA256","TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256",ECC_BYTE,TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256), +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + SUITE_INFO("ECDH-RSA-AES256-GCM-SHA384","TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384",ECC_BYTE,TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384), +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + SUITE_INFO("ECDH-ECDSA-AES128-GCM-SHA256","TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256",ECC_BYTE,TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256), +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + SUITE_INFO("ECDH-ECDSA-AES256-GCM-SHA384","TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384",ECC_BYTE,TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384), +#endif + +#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + SUITE_INFO("CAMELLIA128-SHA","TLS_RSA_WITH_CAMELLIA_128_CBC_SHA",CIPHER_BYTE,TLS_RSA_WITH_CAMELLIA_128_CBC_SHA), +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + SUITE_INFO("DHE-RSA-CAMELLIA128-SHA","TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA",CIPHER_BYTE,TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA), +#endif + +#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA + SUITE_INFO("CAMELLIA256-SHA","TLS_RSA_WITH_CAMELLIA_256_CBC_SHA",CIPHER_BYTE,TLS_RSA_WITH_CAMELLIA_256_CBC_SHA), +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + SUITE_INFO("DHE-RSA-CAMELLIA256-SHA","TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA",CIPHER_BYTE,TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA), +#endif + +#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 + SUITE_INFO("CAMELLIA128-SHA256","TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256",CIPHER_BYTE,TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256), +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + SUITE_INFO("DHE-RSA-CAMELLIA128-SHA256","TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256",CIPHER_BYTE,TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256), +#endif + +#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 + SUITE_INFO("CAMELLIA256-SHA256","TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256",CIPHER_BYTE,TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256), +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + SUITE_INFO("DHE-RSA-CAMELLIA256-SHA256","TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256",CIPHER_BYTE,TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256), +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + SUITE_INFO("ECDHE-RSA-AES128-SHA256","TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",ECC_BYTE,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256), +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + SUITE_INFO("ECDHE-ECDSA-AES128-SHA256","TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256), +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + SUITE_INFO("ECDH-RSA-AES128-SHA256","TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256",ECC_BYTE,TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256), +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 + SUITE_INFO("ECDH-ECDSA-AES128-SHA256","TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256",ECC_BYTE,TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256), +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + SUITE_INFO("ECDHE-RSA-AES256-SHA384","TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384",ECC_BYTE,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384), +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + SUITE_INFO("ECDHE-ECDSA-AES256-SHA384","TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384), +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + SUITE_INFO("ECDH-RSA-AES256-SHA384","TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384",ECC_BYTE,TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384), +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 + SUITE_INFO("ECDH-ECDSA-AES256-SHA384","TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384",ECC_BYTE,TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384), +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 + SUITE_INFO("ECDHE-RSA-CHACHA20-POLY1305","TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",CHACHA_BYTE,TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256), +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 + SUITE_INFO("ECDHE-ECDSA-CHACHA20-POLY1305","TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",CHACHA_BYTE,TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256), +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 + SUITE_INFO("DHE-RSA-CHACHA20-POLY1305","TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256",CHACHA_BYTE,TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256), +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 + SUITE_INFO("ECDHE-RSA-CHACHA20-POLY1305-OLD","TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256",CHACHA_BYTE,TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256), +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256 + SUITE_INFO("ECDHE-ECDSA-CHACHA20-POLY1305-OLD","TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256",CHACHA_BYTE,TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256), +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 + SUITE_INFO("DHE-RSA-CHACHA20-POLY1305-OLD","TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256",CHACHA_BYTE,TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256), +#endif + +#ifdef BUILD_TLS_DH_anon_WITH_AES_128_CBC_SHA + SUITE_INFO("ADH-AES128-SHA","TLS_DH_anon_WITH_AES_128_CBC_SHA",CIPHER_BYTE,TLS_DH_anon_WITH_AES_128_CBC_SHA), +#endif + +#ifdef BUILD_TLS_DH_anon_WITH_AES_256_GCM_SHA384 + SUITE_INFO("ADH-AES256-GCM-SHA384","TLS_DH_anon_WITH_AES_256_GCM_SHA384",CIPHER_BYTE,TLS_DH_anon_WITH_AES_256_GCM_SHA384), +#endif + +#ifdef BUILD_TLS_QSH + SUITE_INFO("QSH","TLS_QSH",QSH_BYTE,TLS_QSH), +#endif + +#ifdef HAVE_RENEGOTIATION_INDICATION + SUITE_INFO("RENEGOTIATION-INFO","TLS_EMPTY_RENEGOTIATION_INFO_SCSV",CIPHER_BYTE,TLS_EMPTY_RENEGOTIATION_INFO_SCSV), +#endif + +#ifdef BUILD_SSL_RSA_WITH_IDEA_CBC_SHA + SUITE_INFO("IDEA-CBC-SHA","SSL_RSA_WITH_IDEA_CBC_SHA",CIPHER_BYTE,SSL_RSA_WITH_IDEA_CBC_SHA), +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_NULL_SHA + SUITE_INFO("ECDHE-ECDSA-NULL-SHA","TLS_ECDHE_ECDSA_WITH_NULL_SHA",ECC_BYTE,TLS_ECDHE_ECDSA_WITH_NULL_SHA), +#endif + +#ifdef BUILD_TLS_ECDHE_PSK_WITH_NULL_SHA256 + SUITE_INFO("ECDHE-PSK-NULL-SHA256","TLS_ECDHE_PSK_WITH_NULL_SHA256",ECC_BYTE,TLS_ECDHE_PSK_WITH_NULL_SHA256), +#endif + +#ifdef BUILD_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + SUITE_INFO("ECDHE-PSK-AES128-CBC-SHA256","TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256",ECC_BYTE,TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256), +#endif + +#ifdef BUILD_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 + SUITE_INFO("PSK-CHACHA20-POLY1305","TLS_PSK_WITH_CHACHA20_POLY1305_SHA256",CHACHA_BYTE,TLS_PSK_WITH_CHACHA20_POLY1305_SHA256), +#endif + +#ifdef BUILD_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 + SUITE_INFO("ECDHE-PSK-CHACHA20-POLY1305","TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256",CHACHA_BYTE,TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256), +#endif + +#ifdef BUILD_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 + SUITE_INFO("DHE-PSK-CHACHA20-POLY1305","TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256",CHACHA_BYTE,TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256), +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + SUITE_INFO("EDH-RSA-DES-CBC3-SHA","TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA",CIPHER_BYTE,TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA), +#endif + +#ifdef BUILD_WDM_WITH_NULL_SHA256 + SUITE_INFO("WDM-NULL-SHA256","WDM_WITH_NULL_SHA256",CIPHER_BYTE,WDM_WITH_NULL_SHA256), +#endif + +#endif /* WOLFSSL_NO_TLS12 */ +}; + + +/* returns the cipher_names array */ +const CipherSuiteInfo* GetCipherNames(void) +{ + return cipher_names; +} + + +/* returns the number of elements in the cipher_names array */ +int GetCipherNamesSize(void) +{ + return (int)(sizeof(cipher_names) / sizeof(CipherSuiteInfo)); +} + + +const char* GetCipherNameInternal(const byte cipherSuite0, const byte cipherSuite) +{ + int i; + const char* nameInternal = NULL; + + for (i = 0; i < GetCipherNamesSize(); i++) { + if ((cipher_names[i].cipherSuite0 == cipherSuite0) && + (cipher_names[i].cipherSuite == cipherSuite)) { + nameInternal = cipher_names[i].name; + break; + } + } + return nameInternal; +} + +const char* GetCipherNameIana(const byte cipherSuite0, const byte cipherSuite) +{ +#ifndef NO_ERROR_STRINGS + int i; + const char* nameIana = "NONE"; + + for (i = 0; i < GetCipherNamesSize(); i++) { + if ((cipher_names[i].cipherSuite0 == cipherSuite0) && + (cipher_names[i].cipherSuite == cipherSuite)) { + nameIana = cipher_names[i].name_iana; + break; + } + } + return nameIana; +#else + (void)cipherSuite0; + (void)cipherSuite; + return NULL; +#endif +} + +const char* wolfSSL_get_cipher_name_internal(WOLFSSL* ssl) +{ + if (ssl == NULL) { + return NULL; + } + + return GetCipherNameInternal(ssl->options.cipherSuite0, ssl->options.cipherSuite); +} + +const char* wolfSSL_get_cipher_name_iana(WOLFSSL* ssl) +{ + if (ssl == NULL) { + return NULL; + } + + return GetCipherNameIana(ssl->options.cipherSuite0, ssl->options.cipherSuite); +} + +int GetCipherSuiteFromName(const char* name, byte* cipherSuite0, + byte* cipherSuite) +{ + int ret = BAD_FUNC_ARG; + int i; + unsigned long len = (unsigned long)XSTRLEN(name); + + for (i = 0; i < GetCipherNamesSize(); i++) { + if (XSTRNCMP(name, cipher_names[i].name, len) == 0) { + *cipherSuite0 = cipher_names[i].cipherSuite0; + *cipherSuite = cipher_names[i].cipherSuite; + ret = 0; + break; + } + } + + return ret; +} + +/** +Set the enabled cipher suites. + +@param [out] suites Suites structure. +@param [in] list List of cipher suites, only supports full name from + cipher_names[] delimited by ':'. + +@return true on success, else false. +*/ +int SetCipherList(WOLFSSL_CTX* ctx, Suites* suites, const char* list) +{ + int ret = 0; + int idx = 0; + int haveRSAsig = 0; + int haveECDSAsig = 0; + int haveAnon = 0; + const int suiteSz = GetCipherNamesSize(); + char* next = (char*)list; + + if (suites == NULL || list == NULL) { + WOLFSSL_MSG("SetCipherList parameter error"); + return 0; + } + + if (next[0] == 0 || XSTRNCMP(next, "ALL", 3) == 0 || + XSTRNCMP(next, "DEFAULT", 7) == 0) + return 1; /* wolfSSL default */ + + do { + char* current = next; + char name[MAX_SUITE_NAME + 1]; + int i; + word32 length; + + next = XSTRSTR(next, ":"); + length = min(sizeof(name), !next ? (word32)XSTRLEN(current) /* last */ + : (word32)(next - current)); + + XSTRNCPY(name, current, length); + name[(length == sizeof(name)) ? length - 1 : length] = 0; + + for (i = 0; i < suiteSz; i++) { + if (XSTRNCMP(name, cipher_names[i].name, sizeof(name)) == 0 + #ifndef NO_ERROR_STRINGS + || XSTRNCMP(name, cipher_names[i].name_iana, sizeof(name)) == 0 + #endif + ) { + #ifdef WOLFSSL_DTLS + /* don't allow stream ciphers with DTLS */ + if (ctx->method->version.major == DTLS_MAJOR) { + if (XSTRSTR(name, "RC4") || + XSTRSTR(name, "HC128") || + XSTRSTR(name, "RABBIT")) + { + WOLFSSL_MSG("Stream ciphers not supported with DTLS"); + continue; + } + + } + #endif /* WOLFSSL_DTLS */ + + if (idx + 1 >= WOLFSSL_MAX_SUITE_SZ) { + WOLFSSL_MSG("WOLFSSL_MAX_SUITE_SZ set too low"); + return 0; /* suites buffer not large enough, error out */ + } + + suites->suites[idx++] = cipher_names[i].cipherSuite0; + suites->suites[idx++] = cipher_names[i].cipherSuite; + /* The suites are either ECDSA, RSA, PSK, or Anon. The RSA + * suites don't necessarily have RSA in the name. */ + #ifdef WOLFSSL_TLS13 + if (cipher_names[i].cipherSuite0 == TLS13_BYTE) { + #ifndef NO_RSA + haveRSAsig = 1; + #endif + #if defined(HAVE_ECC) || defined(HAVE_ED25519) + haveECDSAsig = 1; + #endif + } + else + #endif + #if defined(HAVE_ECC) || defined(HAVE_ED25519) + if ((haveECDSAsig == 0) && XSTRSTR(name, "ECDSA")) + haveECDSAsig = 1; + else + #endif + #ifdef HAVE_ANON + if (XSTRSTR(name, "ADH")) + haveAnon = 1; + else + #endif + if (haveRSAsig == 0 + #ifndef NO_PSK + && (XSTRSTR(name, "PSK") == NULL) + #endif + ) { + haveRSAsig = 1; + } + + ret = 1; /* found at least one */ + break; + } + } + } + while (next++); /* ++ needed to skip ':' */ + + if (ret) { + int keySz = 0; + #ifndef NO_CERTS + keySz = ctx->privateKeySz; + #endif + suites->setSuites = 1; + suites->suiteSz = (word16)idx; + InitSuitesHashSigAlgo(suites, haveECDSAsig, haveRSAsig, haveAnon, 1, + keySz); + } + + (void)ctx; + + return ret; +} + + +#if !defined(NO_WOLFSSL_SERVER) || !defined(NO_CERTS) +int PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, word32 hashSigAlgoSz) +{ + word32 i; + int ret = MATCH_SUITE_ERROR; + + ssl->suites->sigAlgo = ssl->specs.sig_algo; + + /* set defaults */ + if (IsAtLeastTLSv1_3(ssl->version)) { + ssl->suites->hashAlgo = sha256_mac; + #ifndef NO_CERTS + ssl->suites->sigAlgo = ssl->buffers.keyType; + #endif + } +#ifndef WOLFSSL_NO_TLS12 + else if (IsAtLeastTLSv1_2(ssl)) { + #ifdef WOLFSSL_ALLOW_TLS_SHA1 + ssl->suites->hashAlgo = sha_mac; + #else + ssl->suites->hashAlgo = sha256_mac; + #endif + } + else { + ssl->suites->hashAlgo = sha_mac; + } +#endif + + if (hashSigAlgoSz == 0) + return 0; + + /* i+1 since peek a byte ahead for type */ + for (i = 0; (i+1) < hashSigAlgoSz; i += HELLO_EXT_SIGALGO_SZ) { + byte hashAlgo = 0, sigAlgo = 0; + + DecodeSigAlg(&hashSigAlgo[i], &hashAlgo, &sigAlgo); + #ifdef HAVE_ED25519 + if (ssl->pkCurveOID == ECC_ED25519_OID && sigAlgo != ed25519_sa_algo) + continue; + + if (sigAlgo == ed25519_sa_algo && + ssl->suites->sigAlgo == ecc_dsa_sa_algo) { + ssl->suites->sigAlgo = sigAlgo; + ssl->suites->hashAlgo = sha512_mac; + ret = 0; + break; + } + #endif + /* For ECDSA the `USE_ECDSA_KEYSZ_HASH_ALGO` build option will choose a hash + * algorithm that matches the ephemeral ECDHE key size or the next higest + * available. This workaround resolves issue with some peer's that do not + * properly support scenarios such as a P-256 key hashed with SHA512. + */ + #if defined(HAVE_ECC) && defined(USE_ECDSA_KEYSZ_HASH_ALGO) + if (sigAlgo == ssl->suites->sigAlgo && sigAlgo == ecc_dsa_sa_algo) { + int digestSz = GetMacDigestSize(hashAlgo); + if (digestSz <= 0) + continue; + + /* For ecc_dsa_sa_algo, pick hash algo that is curve size unless + algorithm in not compiled in, then choose next highest */ + if (digestSz == ssl->eccTempKeySz) { + ssl->suites->hashAlgo = hashAlgo; + ssl->suites->sigAlgo = sigAlgo; + ret = 0; + break; /* done selected sig/hash algorithms */ + } + /* not strong enough, so keep checking hashSigAlso list */ + if (digestSz < ssl->eccTempKeySz) + continue; + + /* mark as highest and check remainder of hashSigAlgo list */ + ssl->suites->hashAlgo = hashAlgo; + ssl->suites->sigAlgo = sigAlgo; + ret = 0; + } + else + #endif + #ifdef WC_RSA_PSS + if (sigAlgo == ssl->suites->sigAlgo || (sigAlgo == rsa_pss_sa_algo && + ssl->suites->sigAlgo == rsa_sa_algo)) + #else + if (sigAlgo == ssl->suites->sigAlgo) + #endif + { + /* pick highest available between both server and client */ + switch (hashAlgo) { + case sha_mac: + #ifdef WOLFSSL_SHA224 + case sha224_mac: + #endif + #ifndef NO_SHA256 + case sha256_mac: + #endif + #ifdef WOLFSSL_SHA384 + case sha384_mac: + #endif + #ifdef WOLFSSL_SHA512 + case sha512_mac: + #endif + /* not strong enough, so keep checking hashSigAlso list */ + if (hashAlgo < ssl->suites->hashAlgo) { + ret = 0; + continue; + } + /* mark as highest and check remainder of hashSigAlgo list */ + ssl->suites->hashAlgo = hashAlgo; + ssl->suites->sigAlgo = sigAlgo; + break; + default: + continue; + } + ret = 0; + break; + } + else if (ssl->specs.sig_algo == 0 && !IsAtLeastTLSv1_3(ssl->version)) { + ssl->suites->hashAlgo = ssl->specs.mac_algorithm; + ret = 0; + } + } + + return ret; +} +#endif /* !defined(NO_WOLFSSL_SERVER) || !defined(NO_CERTS) */ + +#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) + + /* Initialize HandShakeInfo */ + void InitHandShakeInfo(HandShakeInfo* info, WOLFSSL* ssl) + { + int i; + + info->ssl = ssl; + info->cipherName[0] = 0; + for (i = 0; i < MAX_PACKETS_HANDSHAKE; i++) + info->packetNames[i][0] = 0; + info->numberPackets = 0; + info->negotiationError = 0; + } + + /* Set Final HandShakeInfo parameters */ + void FinishHandShakeInfo(HandShakeInfo* info) + { + int i; + int sz = GetCipherNamesSize(); + + for (i = 0; i < sz; i++) + if (info->ssl->options.cipherSuite == + (byte)cipher_names[i].cipherSuite) { + if (info->ssl->options.cipherSuite0 == ECC_BYTE) + continue; /* ECC suites at end */ + XSTRNCPY(info->cipherName, cipher_names[i].name, MAX_CIPHERNAME_SZ); + info->cipherName[MAX_CIPHERNAME_SZ] = '\0'; + break; + } + + /* error max and min are negative numbers */ + if (info->ssl->error <= MIN_PARAM_ERR && info->ssl->error >= MAX_PARAM_ERR) + info->negotiationError = info->ssl->error; + } + + + /* Add name to info packet names, increase packet name count */ + void AddPacketName(WOLFSSL* ssl, const char* name) + { + #ifdef WOLFSSL_CALLBACKS + HandShakeInfo* info = &ssl->handShakeInfo; + if (info->numberPackets < MAX_PACKETS_HANDSHAKE) { + char* packetName = info->packetNames[info->numberPackets]; + XSTRNCPY(packetName, name, MAX_PACKETNAME_SZ); + packetName[MAX_PACKETNAME_SZ] = '\0'; + info->numberPackets++; + } + #endif + (void)ssl; + (void)name; + } + + + #ifdef WOLFSSL_CALLBACKS + /* Initialize TimeoutInfo */ + void InitTimeoutInfo(TimeoutInfo* info) + { + int i; + + info->timeoutName[0] = 0; + info->flags = 0; + + for (i = 0; i < MAX_PACKETS_HANDSHAKE; i++) { + info->packets[i].packetName[0] = 0; + info->packets[i].timestamp.tv_sec = 0; + info->packets[i].timestamp.tv_usec = 0; + info->packets[i].bufferValue = 0; + info->packets[i].valueSz = 0; + } + info->numberPackets = 0; + info->timeoutValue.tv_sec = 0; + info->timeoutValue.tv_usec = 0; + } + + + /* Free TimeoutInfo */ + void FreeTimeoutInfo(TimeoutInfo* info, void* heap) + { + int i; + (void)heap; + for (i = 0; i < MAX_PACKETS_HANDSHAKE; i++) + if (info->packets[i].bufferValue) { + XFREE(info->packets[i].bufferValue, heap, DYNAMIC_TYPE_INFO); + info->packets[i].bufferValue = 0; + } + + } + + /* Add packet name to previsouly added packet info */ + void AddLateName(const char* name, TimeoutInfo* info) + { + /* make sure we have a valid previous one */ + if (info->numberPackets > 0 && info->numberPackets < + MAX_PACKETS_HANDSHAKE) { + char* packetName = info->packets[info->numberPackets-1].packetName; + XSTRNCPY(packetName, name, MAX_PACKETNAME_SZ); + packetName[MAX_PACKETNAME_SZ] = '\0'; + } + } + + /* Add record header to previsouly added packet info */ + void AddLateRecordHeader(const RecordLayerHeader* rl, TimeoutInfo* info) + { + /* make sure we have a valid previous one */ + if (info->numberPackets > 0 && info->numberPackets < + MAX_PACKETS_HANDSHAKE) { + if (info->packets[info->numberPackets - 1].bufferValue) + XMEMCPY(info->packets[info->numberPackets - 1].bufferValue, rl, + RECORD_HEADER_SZ); + else + XMEMCPY(info->packets[info->numberPackets - 1].value, rl, + RECORD_HEADER_SZ); + } + } + + #endif /* WOLFSSL_CALLBACKS */ + + + /* Add PacketInfo to TimeoutInfo + * + * ssl WOLFSSL structure sending or receiving packet + * name name of packet being sent + * type type of packet being sent + * data data bing sent with packet + * sz size of data buffer + * written 1 if this packet is being written to wire, 0 if being read + * heap custom heap to use for mallocs/frees + */ + void AddPacketInfo(WOLFSSL* ssl, const char* name, int type, + const byte* data, int sz, int written, void* heap) + { + #ifdef WOLFSSL_CALLBACKS + TimeoutInfo* info = &ssl->timeoutInfo; + + if (info->numberPackets < (MAX_PACKETS_HANDSHAKE - 1)) { + Timeval currTime; + + /* may add name after */ + if (name) { + char* packetName = info->packets[info->numberPackets].packetName; + XSTRNCPY(packetName, name, MAX_PACKETNAME_SZ); + packetName[MAX_PACKETNAME_SZ] = '\0'; + } + + /* add data, put in buffer if bigger than static buffer */ + info->packets[info->numberPackets].valueSz = sz; + if (sz < MAX_VALUE_SZ) + XMEMCPY(info->packets[info->numberPackets].value, data, sz); + else { + info->packets[info->numberPackets].bufferValue = + (byte*)XMALLOC(sz, heap, DYNAMIC_TYPE_INFO); + if (!info->packets[info->numberPackets].bufferValue) + /* let next alloc catch, just don't fill, not fatal here */ + info->packets[info->numberPackets].valueSz = 0; + else + XMEMCPY(info->packets[info->numberPackets].bufferValue, + data, sz); + } + gettimeofday(&currTime, 0); + info->packets[info->numberPackets].timestamp.tv_sec = + currTime.tv_sec; + info->packets[info->numberPackets].timestamp.tv_usec = + currTime.tv_usec; + info->numberPackets++; + } + #endif /* WOLFSSL_CALLBACKS */ + #ifdef OPENSSL_EXTRA + if (ssl->protoMsgCb != NULL && sz > RECORD_HEADER_SZ) { + /* version from hex to dec 16 is 16^1, 256 from 16^2 and + 4096 from 16^3 */ + int version = (ssl->version.minor & 0X0F) + + (ssl->version.minor & 0xF0) * 16 + + (ssl->version.major & 0X0F) * 256 + + (ssl->version.major & 0xF0) * 4096; + + ssl->protoMsgCb(written, version, type, + (const void *)(data + RECORD_HEADER_SZ), + (size_t)(sz - RECORD_HEADER_SZ), + ssl, ssl->protoMsgCtx); + } + #endif /* OPENSSL_EXTRA */ + (void)written; + (void)name; + (void)heap; + (void)type; + (void)ssl; + } + +#endif /* WOLFSSL_CALLBACKS */ + +#if !defined(NO_CERTS) + +/* Decode the private key - RSA, ECC, or Ed25519 - and creates a key object. + * The signature type is set as well. + * The maximum length of a signature is returned. + * + * ssl The SSL/TLS object. + * length The length of a signature. + * returns 0 on success, otherwise failure. + */ +int DecodePrivateKey(WOLFSSL *ssl, word16* length) +{ + int ret = BAD_FUNC_ARG; + int keySz; + word32 idx; + +#ifdef HAVE_PK_CALLBACKS + /* allow no private key if using PK callbacks and CB is set */ + if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) { + *length = GetPrivateKeySigSize(ssl); + return 0; + } + else +#endif + + /* make sure private key exists */ + if (ssl->buffers.key == NULL || ssl->buffers.key->buffer == NULL) { + WOLFSSL_MSG("Private key missing!"); + ERROR_OUT(NO_PRIVATE_KEY, exit_dpk); + } + +#ifdef HAVE_PKCS11 + if (ssl->buffers.keyDevId != INVALID_DEVID && ssl->buffers.keyId) { + if (ssl->buffers.keyType == rsa_sa_algo) + ssl->hsType = DYNAMIC_TYPE_RSA; + else if (ssl->buffers.keyType == ecc_dsa_sa_algo) + ssl->hsType = DYNAMIC_TYPE_ECC; + ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); + if (ret != 0) { + goto exit_dpk; + } + + if (ssl->buffers.keyType == rsa_sa_algo) { + #ifndef NO_RSA + ret = wc_InitRsaKey_Id((RsaKey*)ssl->hsKey, + ssl->buffers.key->buffer, ssl->buffers.key->length, + ssl->heap, ssl->buffers.keyDevId); + if (ret == 0) { + if (ssl->buffers.keySz < ssl->options.minRsaKeySz) { + WOLFSSL_MSG("RSA key size too small"); + ERROR_OUT(RSA_KEY_SIZE_E, exit_dpk); + } + + /* Return the maximum signature length. */ + *length = (word16)ssl->buffers.keySz; + } + #else + ret = NOT_COMPILED_IN; + #endif + } + else if (ssl->buffers.keyType == ecc_dsa_sa_algo) { + #ifdef HAVE_ECC + ret = wc_ecc_init_id((ecc_key*)ssl->hsKey, ssl->buffers.key->buffer, + ssl->buffers.key->length, ssl->heap, + ssl->buffers.keyDevId); + if (ret == 0) { + if (ssl->buffers.keySz < ssl->options.minEccKeySz) { + WOLFSSL_MSG("ECC key size too small"); + ERROR_OUT(ECC_KEY_SIZE_E, exit_dpk); + } + + /* Return the maximum signature length. */ + *length = (word16)wc_ecc_sig_size_calc(ssl->buffers.keySz); + } + #else + ret = NOT_COMPILED_IN; + #endif + } + goto exit_dpk; + } +#endif + +#ifndef NO_RSA + if (ssl->buffers.keyType == rsa_sa_algo || ssl->buffers.keyType == 0) { + ssl->hsType = DYNAMIC_TYPE_RSA; + ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); + if (ret != 0) { + goto exit_dpk; + } + + WOLFSSL_MSG("Trying RSA private key"); + + /* Set start of data to beginning of buffer. */ + idx = 0; + /* Decode the key assuming it is an RSA private key. */ + ret = wc_RsaPrivateKeyDecode(ssl->buffers.key->buffer, &idx, + (RsaKey*)ssl->hsKey, ssl->buffers.key->length); + if (ret == 0) { + WOLFSSL_MSG("Using RSA private key"); + + /* It worked so check it meets minimum key size requirements. */ + keySz = wc_RsaEncryptSize((RsaKey*)ssl->hsKey); + if (keySz < 0) { /* check if keySz has error case */ + ERROR_OUT(keySz, exit_dpk); + } + + if (keySz < ssl->options.minRsaKeySz) { + WOLFSSL_MSG("RSA key size too small"); + ERROR_OUT(RSA_KEY_SIZE_E, exit_dpk); + } + + /* Return the maximum signature length. */ + *length = (word16)keySz; + + goto exit_dpk; + } + } +#endif /* !NO_RSA */ + +#ifdef HAVE_ECC +#ifndef NO_RSA + FreeKey(ssl, ssl->hsType, (void**)&ssl->hsKey); +#endif /* !NO_RSA */ + + if (ssl->buffers.keyType == ecc_dsa_sa_algo || ssl->buffers.keyType == 0) { + ssl->hsType = DYNAMIC_TYPE_ECC; + ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); + if (ret != 0) { + goto exit_dpk; + } + + #ifndef NO_RSA + WOLFSSL_MSG("Trying ECC private key, RSA didn't work"); + #else + WOLFSSL_MSG("Trying ECC private key"); + #endif + + /* Set start of data to beginning of buffer. */ + idx = 0; + /* Decode the key assuming it is an ECC private key. */ + ret = wc_EccPrivateKeyDecode(ssl->buffers.key->buffer, &idx, + (ecc_key*)ssl->hsKey, + ssl->buffers.key->length); + if (ret == 0) { + WOLFSSL_MSG("Using ECC private key"); + + /* Check it meets the minimum ECC key size requirements. */ + keySz = wc_ecc_size((ecc_key*)ssl->hsKey); + if (keySz < ssl->options.minEccKeySz) { + WOLFSSL_MSG("ECC key size too small"); + ERROR_OUT(ECC_KEY_SIZE_E, exit_dpk); + } + + /* Return the maximum signature length. */ + *length = (word16)wc_ecc_sig_size((ecc_key*)ssl->hsKey); + + goto exit_dpk; + } + } +#endif +#ifdef HAVE_ED25519 + #if !defined(NO_RSA) || defined(HAVE_ECC) + FreeKey(ssl, ssl->hsType, (void**)&ssl->hsKey); + #endif + + if (ssl->buffers.keyType == ed25519_sa_algo || ssl->buffers.keyType == 0) { + ssl->hsType = DYNAMIC_TYPE_ED25519; + ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); + if (ret != 0) { + goto exit_dpk; + } + + #ifdef HAVE_ECC + WOLFSSL_MSG("Trying ED25519 private key, ECC didn't work"); + #elif !defined(NO_RSA) + WOLFSSL_MSG("Trying ED25519 private key, RSA didn't work"); + #else + WOLFSSL_MSG("Trying ED25519 private key"); + #endif + + /* Set start of data to beginning of buffer. */ + idx = 0; + /* Decode the key assuming it is an ED25519 private key. */ + ret = wc_Ed25519PrivateKeyDecode(ssl->buffers.key->buffer, &idx, + (ed25519_key*)ssl->hsKey, + ssl->buffers.key->length); + if (ret == 0) { + WOLFSSL_MSG("Using ED25519 private key"); + + /* Check it meets the minimum ECC key size requirements. */ + if (ED25519_KEY_SIZE < ssl->options.minEccKeySz) { + WOLFSSL_MSG("ED25519 key size too small"); + ERROR_OUT(ECC_KEY_SIZE_E, exit_dpk); + } + + /* Return the maximum signature length. */ + *length = ED25519_SIG_SIZE; + + goto exit_dpk; + } + } +#endif /* HAVE_ED25519 */ + + (void)idx; + (void)keySz; + (void)length; +exit_dpk: + return ret; +} + +#endif /* WOLFSSL_TLS13 || !NO_WOLFSSL_CLIENT */ + +/* client only parts */ +#ifndef NO_WOLFSSL_CLIENT + +#ifndef WOLFSSL_NO_TLS12 + + /* handle generation of client_hello (1) */ + int SendClientHello(WOLFSSL* ssl) + { + byte *output; + word32 length, idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + int sendSz; + int idSz = ssl->options.resuming + ? ssl->session.sessionIDSz + : 0; + int ret; + word16 extSz = 0; + +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version)) + return SendTls13ClientHello(ssl); +#endif + + WOLFSSL_START(WC_FUNC_CLIENT_HELLO_SEND); + WOLFSSL_ENTER("SendClientHello"); + + if (ssl->suites == NULL) { + WOLFSSL_MSG("Bad suites pointer in SendClientHello"); + return SUITES_ERROR; + } + +#ifdef HAVE_SESSION_TICKET + if (ssl->options.resuming && ssl->session.ticketLen > 0) { + SessionTicket* ticket; + + ticket = TLSX_SessionTicket_Create(0, ssl->session.ticket, + ssl->session.ticketLen, ssl->heap); + if (ticket == NULL) return MEMORY_E; + + ret = TLSX_UseSessionTicket(&ssl->extensions, ticket, ssl->heap); + if (ret != WOLFSSL_SUCCESS) { + TLSX_SessionTicket_Free(ticket, ssl->heap); + return ret; + } + + idSz = 0; + } +#endif + length = VERSION_SZ + RAN_LEN + + idSz + ENUM_LEN + + ssl->suites->suiteSz + SUITE_LEN + + COMP_LEN + ENUM_LEN; + +#ifdef HAVE_TLS_EXTENSIONS + /* auto populate extensions supported unless user defined */ + if ((ret = TLSX_PopulateExtensions(ssl, 0)) != 0) + return ret; + #ifdef HAVE_QSH + if (QSH_Init(ssl) != 0) + return MEMORY_E; + #endif + extSz = 0; + ret = TLSX_GetRequestSize(ssl, client_hello, &extSz); + if (ret != 0) + return ret; + length += extSz; +#else + if (IsAtLeastTLSv1_2(ssl) && ssl->suites->hashSigAlgoSz) + extSz += HELLO_EXT_SZ + HELLO_EXT_SIGALGO_SZ + + ssl->suites->hashSigAlgoSz; +#ifdef HAVE_EXTENDED_MASTER + if (ssl->options.haveEMS) + extSz += HELLO_EXT_SZ; +#endif + if (extSz != 0) + length += extSz + HELLO_EXT_SZ_SZ; +#endif + sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; + +#ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + length += ENUM_LEN; /* cookie */ + if (ssl->arrays->cookieSz != 0) length += ssl->arrays->cookieSz; + sendSz = length + DTLS_HANDSHAKE_HEADER_SZ + DTLS_RECORD_HEADER_SZ; + idx += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA; + } +#endif + + if (IsEncryptionOn(ssl, 1)) + sendSz += MAX_MSG_EXTRA; + + /* check for available size */ + if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) + return ret; + + /* get output buffer */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + AddHeaders(output, length, client_hello, ssl); + + /* client hello, first version */ + output[idx++] = ssl->version.major; + output[idx++] = ssl->version.minor; + ssl->chVersion = ssl->version; /* store in case changed */ + + /* then random */ + if (ssl->options.connectState == CONNECT_BEGIN) { + ret = wc_RNG_GenerateBlock(ssl->rng, output + idx, RAN_LEN); + if (ret != 0) + return ret; + + /* store random */ + XMEMCPY(ssl->arrays->clientRandom, output + idx, RAN_LEN); + } else { +#ifdef WOLFSSL_DTLS + /* send same random on hello again */ + XMEMCPY(output + idx, ssl->arrays->clientRandom, RAN_LEN); +#endif + } + idx += RAN_LEN; + + /* then session id */ + output[idx++] = (byte)idSz; + if (idSz) { + XMEMCPY(output + idx, ssl->session.sessionID, + ssl->session.sessionIDSz); + idx += ssl->session.sessionIDSz; + } + + /* then DTLS cookie */ +#ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + byte cookieSz = ssl->arrays->cookieSz; + + output[idx++] = cookieSz; + if (cookieSz) { + XMEMCPY(&output[idx], ssl->arrays->cookie, cookieSz); + idx += cookieSz; + } + } +#endif + /* then cipher suites */ + c16toa(ssl->suites->suiteSz, output + idx); + idx += OPAQUE16_LEN; + XMEMCPY(output + idx, &ssl->suites->suites, ssl->suites->suiteSz); + idx += ssl->suites->suiteSz; + + /* last, compression */ + output[idx++] = COMP_LEN; + if (ssl->options.usingCompression) + output[idx++] = ZLIB_COMPRESSION; + else + output[idx++] = NO_COMPRESSION; + +#ifdef HAVE_TLS_EXTENSIONS + extSz = 0; + ret = TLSX_WriteRequest(ssl, output + idx, client_hello, &extSz); + if (ret != 0) + return ret; + idx += extSz; + + (void)idx; /* suppress analyzer warning, keep idx current */ +#else + if (extSz != 0) { + c16toa(extSz, output + idx); + idx += HELLO_EXT_SZ_SZ; + + if (IsAtLeastTLSv1_2(ssl)) { + if (ssl->suites->hashSigAlgoSz) { + word16 i; + /* extension type */ + c16toa(HELLO_EXT_SIG_ALGO, output + idx); + idx += HELLO_EXT_TYPE_SZ; + /* extension data length */ + c16toa(HELLO_EXT_SIGALGO_SZ + ssl->suites->hashSigAlgoSz, + output + idx); + idx += HELLO_EXT_SZ_SZ; + /* sig algos length */ + c16toa(ssl->suites->hashSigAlgoSz, output + idx); + idx += HELLO_EXT_SIGALGO_SZ; + for (i=0; i < ssl->suites->hashSigAlgoSz; i++, idx++) { + output[idx] = ssl->suites->hashSigAlgo[i]; + } + } + } +#ifdef HAVE_EXTENDED_MASTER + if (ssl->options.haveEMS) { + c16toa(HELLO_EXT_EXTMS, output + idx); + idx += HELLO_EXT_TYPE_SZ; + c16toa(0, output + idx); + idx += HELLO_EXT_SZ_SZ; + } +#endif + } +#endif + + if (IsEncryptionOn(ssl, 1)) { + byte* input; + int inputSz = idx - RECORD_HEADER_SZ; /* build msg adds rec hdr */ + + input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + if (input == NULL) + return MEMORY_E; + + XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz); + sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, + handshake, 1, 0, 0); + XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + + if (sendSz < 0) + return sendSz; + } else { + #ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl)) { + if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) + return ret; + } + if (ssl->options.dtls) + DtlsSEQIncrement(ssl, CUR_ORDER); + #endif + ret = HashOutput(ssl, output, sendSz, 0); + if (ret != 0) + return ret; + } + + ssl->options.clientState = CLIENT_HELLO_COMPLETE; +#ifdef OPENSSL_EXTRA + ssl->cbmode = SSL_CB_MODE_WRITE; + if (ssl->CBIS != NULL) + ssl->CBIS(ssl, SSL_CB_CONNECT_LOOP, SSL_SUCCESS); +#endif + +#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) + if (ssl->hsInfoOn) AddPacketName(ssl, "ClientHello"); + if (ssl->toInfoOn) + AddPacketInfo(ssl, "ClientHello", handshake, output, sendSz, + WRITE_PROTO, ssl->heap); +#endif + + ssl->buffers.outputBuffer.length += sendSz; + + ret = SendBuffered(ssl); + + WOLFSSL_LEAVE("SendClientHello", ret); + WOLFSSL_END(WC_FUNC_CLIENT_HELLO_SEND); + + return ret; + } + + + /* handle processing of DTLS hello_verify_request (3) */ + static int DoHelloVerifyRequest(WOLFSSL* ssl, const byte* input, + word32* inOutIdx, word32 size) + { + ProtocolVersion pv; + byte cookieSz; + word32 begin = *inOutIdx; + +#ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName(ssl, "HelloVerifyRequest"); + if (ssl->toInfoOn) AddLateName("HelloVerifyRequest", &ssl->timeoutInfo); +#endif + +#ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + DtlsMsgPoolReset(ssl); + } +#endif + + if ((*inOutIdx - begin) + OPAQUE16_LEN + OPAQUE8_LEN > size) + return BUFFER_ERROR; + + XMEMCPY(&pv, input + *inOutIdx, OPAQUE16_LEN); + *inOutIdx += OPAQUE16_LEN; + + if (pv.major != DTLS_MAJOR || + (pv.minor != DTLS_MINOR && pv.minor != DTLSv1_2_MINOR)) + return VERSION_ERROR; + + cookieSz = input[(*inOutIdx)++]; + + if (cookieSz) { + if ((*inOutIdx - begin) + cookieSz > size) + return BUFFER_ERROR; + +#ifdef WOLFSSL_DTLS + if (cookieSz <= MAX_COOKIE_LEN) { + XMEMCPY(ssl->arrays->cookie, input + *inOutIdx, cookieSz); + ssl->arrays->cookieSz = cookieSz; + } +#endif + *inOutIdx += cookieSz; + } + + ssl->options.serverState = SERVER_HELLOVERIFYREQUEST_COMPLETE; + return 0; + } + + + static WC_INLINE int DSH_CheckSessionId(WOLFSSL* ssl) + { + int ret = 0; + +#ifdef HAVE_SECRET_CALLBACK + /* If a session secret callback exists, we are using that + * key instead of the saved session key. */ + ret = ret || (ssl->sessionSecretCb != NULL); +#endif + +#ifdef HAVE_SESSION_TICKET + /* server may send blank ticket which may not be expected to indicate + * existing one ok but will also be sending a new one */ + ret = ret || (ssl->session.ticketLen > 0); +#endif + + ret = ret || + (ssl->options.haveSessionId && XMEMCMP(ssl->arrays->sessionID, + ssl->session.sessionID, ID_LEN) == 0); + + return ret; + } + + /* Check the version in the received message is valid and set protocol + * version to use. + * + * ssl The SSL/TLS object. + * pv The protocol version from the packet. + * returns 0 on success, otherwise failure. + */ + int CheckVersion(WOLFSSL *ssl, ProtocolVersion pv) + { + #ifdef WOLFSSL_TLS13_DRAFT + if (pv.major == TLS_DRAFT_MAJOR) { + pv.major = SSLv3_MAJOR; + pv.minor = TLSv1_3_MINOR; + } + #endif + + #ifdef OPENSSL_EXTRA + if (ssl->CBIS != NULL) { + ssl->CBIS(ssl, SSL_CB_HANDSHAKE_START, SSL_SUCCESS); + } + #endif + + if (pv.minor > ssl->version.minor) { + WOLFSSL_MSG("Server using higher version, fatal error"); + return VERSION_ERROR; + } + if (pv.minor < ssl->version.minor) { + WOLFSSL_MSG("server using lower version"); + + /* Check for downgrade attack. */ + if (!ssl->options.downgrade) { + WOLFSSL_MSG("\tno downgrade allowed, fatal error"); + return VERSION_ERROR; + } + if (pv.minor < ssl->options.minDowngrade) { + WOLFSSL_MSG("\tversion below minimum allowed, fatal error"); + return VERSION_ERROR; + } + + #ifdef HAVE_SECURE_RENEGOTIATION + if (ssl->secure_renegotiation && + ssl->secure_renegotiation->enabled && + ssl->options.handShakeDone) { + WOLFSSL_MSG("Server changed version during scr"); + return VERSION_ERROR; + } + #endif + + /* Checks made - OK to downgrade. */ + if (pv.minor == SSLv3_MINOR) { + /* turn off tls */ + WOLFSSL_MSG("\tdowngrading to SSLv3"); + ssl->options.tls = 0; + ssl->options.tls1_1 = 0; + ssl->version.minor = SSLv3_MINOR; + } + else if (pv.minor == TLSv1_MINOR) { + /* turn off tls 1.1+ */ + WOLFSSL_MSG("\tdowngrading to TLSv1"); + ssl->options.tls1_1 = 0; + ssl->version.minor = TLSv1_MINOR; + } + else if (pv.minor == TLSv1_1_MINOR) { + WOLFSSL_MSG("\tdowngrading to TLSv1.1"); + ssl->version.minor = TLSv1_1_MINOR; + } + else if (pv.minor == TLSv1_2_MINOR) { + WOLFSSL_MSG(" downgrading to TLSv1.2"); + ssl->version.minor = TLSv1_2_MINOR; + } + } + +#ifdef OPENSSL_EXTRA + /* check if option is set to not allow the current version + * set from either wolfSSL_set_options or wolfSSL_CTX_set_options */ + if (!ssl->options.dtls && ssl->options.downgrade && + ssl->options.mask > 0) { + if (ssl->version.minor == TLSv1_2_MINOR && + (ssl->options.mask & SSL_OP_NO_TLSv1_2) == SSL_OP_NO_TLSv1_2) { + WOLFSSL_MSG("\tOption set to not allow TLSv1.2, Downgrading"); + ssl->version.minor = TLSv1_1_MINOR; + } + if (ssl->version.minor == TLSv1_1_MINOR && + (ssl->options.mask & SSL_OP_NO_TLSv1_1) == SSL_OP_NO_TLSv1_1) { + WOLFSSL_MSG("\tOption set to not allow TLSv1.1, Downgrading"); + ssl->options.tls1_1 = 0; + ssl->version.minor = TLSv1_MINOR; + } + if (ssl->version.minor == TLSv1_MINOR && + (ssl->options.mask & SSL_OP_NO_TLSv1) == SSL_OP_NO_TLSv1) { + WOLFSSL_MSG("\tOption set to not allow TLSv1, Downgrading"); + ssl->options.tls = 0; + ssl->options.tls1_1 = 0; + ssl->version.minor = SSLv3_MINOR; + } + if (ssl->version.minor == SSLv3_MINOR && + (ssl->options.mask & SSL_OP_NO_SSLv3) == SSL_OP_NO_SSLv3) { + WOLFSSL_MSG("\tError, option set to not allow SSLv3"); + return VERSION_ERROR; + } + + if (ssl->version.minor < ssl->options.minDowngrade) { + WOLFSSL_MSG("\tversion below minimum allowed, fatal error"); + return VERSION_ERROR; + } + } +#endif + + return 0; + } + + /* handle processing of server_hello (2) */ + int DoServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, + word32 helloSz) + { + byte cs0; /* cipher suite bytes 0, 1 */ + byte cs1; + ProtocolVersion pv; + byte compression; + word32 i = *inOutIdx; + word32 begin = i; + int ret; + + WOLFSSL_START(WC_FUNC_SERVER_HELLO_DO); + WOLFSSL_ENTER("DoServerHello"); + +#ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName(ssl, "ServerHello"); + if (ssl->toInfoOn) AddLateName("ServerHello", &ssl->timeoutInfo); +#endif + + /* protocol version, random and session id length check */ + if (OPAQUE16_LEN + RAN_LEN + OPAQUE8_LEN > helloSz) + return BUFFER_ERROR; + + /* protocol version */ + XMEMCPY(&pv, input + i, OPAQUE16_LEN); + i += OPAQUE16_LEN; + + ret = CheckVersion(ssl, pv); + if (ret != 0) + return ret; + +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(pv)) { + byte type = server_hello; + return DoTls13ServerHello(ssl, input, inOutIdx, helloSz, &type); + } +#endif + + /* random */ + XMEMCPY(ssl->arrays->serverRandom, input + i, RAN_LEN); + i += RAN_LEN; + + /* session id */ + ssl->arrays->sessionIDSz = input[i++]; + + if (ssl->arrays->sessionIDSz > ID_LEN) { + WOLFSSL_MSG("Invalid session ID size"); + ssl->arrays->sessionIDSz = 0; + return BUFFER_ERROR; + } + else if (ssl->arrays->sessionIDSz) { + if ((i - begin) + ssl->arrays->sessionIDSz > helloSz) + return BUFFER_ERROR; + + XMEMCPY(ssl->arrays->sessionID, input + i, + ssl->arrays->sessionIDSz); + i += ssl->arrays->sessionIDSz; + ssl->options.haveSessionId = 1; + } + + + /* suite and compression */ + if ((i - begin) + OPAQUE16_LEN + OPAQUE8_LEN > helloSz) + return BUFFER_ERROR; + + cs0 = input[i++]; + cs1 = input[i++]; + +#ifdef HAVE_SECURE_RENEGOTIATION + if (ssl->secure_renegotiation && ssl->secure_renegotiation->enabled && + ssl->options.handShakeDone) { + if (ssl->options.cipherSuite0 != cs0 || + ssl->options.cipherSuite != cs1) { + WOLFSSL_MSG("Server changed cipher suite during scr"); + return MATCH_SUITE_ERROR; + } + } +#endif + + ssl->options.cipherSuite0 = cs0; + ssl->options.cipherSuite = cs1; + compression = input[i++]; + + if (compression != NO_COMPRESSION && !ssl->options.usingCompression) { + WOLFSSL_MSG("Server forcing compression w/o support"); + return COMPRESSION_ERROR; + } + + if (compression != ZLIB_COMPRESSION && ssl->options.usingCompression) { + WOLFSSL_MSG("Server refused compression, turning off"); + ssl->options.usingCompression = 0; /* turn off if server refused */ + } + + *inOutIdx = i; + +#ifdef HAVE_TLS_EXTENSIONS + if ( (i - begin) < helloSz) { + if (TLSX_SupportExtensions(ssl)) { + word16 totalExtSz; + + if ((i - begin) + OPAQUE16_LEN > helloSz) + return BUFFER_ERROR; + + ato16(&input[i], &totalExtSz); + i += OPAQUE16_LEN; + + if ((i - begin) + totalExtSz > helloSz) + return BUFFER_ERROR; + + if ((ret = TLSX_Parse(ssl, (byte *) input + i, totalExtSz, + server_hello, NULL))) + return ret; + + i += totalExtSz; + *inOutIdx = i; + } + else + *inOutIdx = begin + helloSz; /* skip extensions */ + } + else + ssl->options.haveEMS = 0; /* If no extensions, no EMS */ +#else + { + int allowExt = 0; + byte pendingEMS = 0; + + if ( (i - begin) < helloSz) { + if (ssl->version.major == SSLv3_MAJOR && + ssl->version.minor >= TLSv1_MINOR) { + + allowExt = 1; + } +#ifdef WOLFSSL_DTLS + if (ssl->version.major == DTLS_MAJOR) + allowExt = 1; +#endif + + if (allowExt) { + word16 totalExtSz; + + if ((i - begin) + OPAQUE16_LEN > helloSz) + return BUFFER_ERROR; + + ato16(&input[i], &totalExtSz); + i += OPAQUE16_LEN; + + if ((i - begin) + totalExtSz > helloSz) + return BUFFER_ERROR; + + while (totalExtSz) { + word16 extId, extSz; + + if (OPAQUE16_LEN + OPAQUE16_LEN > totalExtSz) + return BUFFER_ERROR; + + ato16(&input[i], &extId); + i += OPAQUE16_LEN; + ato16(&input[i], &extSz); + i += OPAQUE16_LEN; + + if (OPAQUE16_LEN + OPAQUE16_LEN + extSz > totalExtSz) + return BUFFER_ERROR; + + if (extId == HELLO_EXT_EXTMS) + pendingEMS = 1; + else + i += extSz; + + totalExtSz -= OPAQUE16_LEN + OPAQUE16_LEN + extSz; + } + + *inOutIdx = i; + } + else + *inOutIdx = begin + helloSz; /* skip extensions */ + } + + if (!pendingEMS && ssl->options.haveEMS) + ssl->options.haveEMS = 0; + } +#endif + + ssl->options.serverState = SERVER_HELLO_COMPLETE; + + if (IsEncryptionOn(ssl, 0)) { + *inOutIdx += ssl->keys.padSz; + } + +#ifdef HAVE_SECRET_CALLBACK + if (ssl->sessionSecretCb != NULL) { + int secretSz = SECRET_LEN; + ret = ssl->sessionSecretCb(ssl, ssl->session.masterSecret, + &secretSz, ssl->sessionSecretCtx); + if (ret != 0 || secretSz != SECRET_LEN) + return SESSION_SECRET_CB_E; + } +#endif /* HAVE_SECRET_CALLBACK */ + + ret = CompleteServerHello(ssl); + + WOLFSSL_LEAVE("DoServerHello", ret); + WOLFSSL_END(WC_FUNC_SERVER_HELLO_DO); + + return ret; + } + +#ifdef WOLFSSL_TLS13 + /* returns 1 if able to do TLS 1.3 otherwise 0 */ + static int TLSv1_3_Capable(WOLFSSL* ssl) + { + #ifndef WOLFSSL_TLS13 + return 0; + #else + int ret = 0; + + if (IsAtLeastTLSv1_3(ssl->ctx->method->version)) { + ret = 1; + } + + #ifdef OPENSSL_EXTRA + if ((wolfSSL_get_options(ssl) & SSL_OP_NO_TLSv1_3)) { + /* option set at run time to disable TLS 1.3 */ + ret = 0; + } + #endif + return ret; + #endif + } +#endif /* WOLFSSL_TLS13 */ + + int CompleteServerHello(WOLFSSL* ssl) + { + int ret; + + if (!ssl->options.resuming) { + byte* down = ssl->arrays->serverRandom + RAN_LEN - + TLS13_DOWNGRADE_SZ - 1; + byte vers = ssl->arrays->serverRandom[RAN_LEN - 1]; + #ifdef WOLFSSL_TLS13 + if (TLSv1_3_Capable(ssl)) { + /* TLS v1.3 capable client not allowed to downgrade when + * connecting to TLS v1.3 capable server unless cipher suite + * demands it. + */ + if (XMEMCMP(down, tls13Downgrade, TLS13_DOWNGRADE_SZ) == 0 && + (vers == 0 || vers == 1)) { + SendAlert(ssl, alert_fatal, illegal_parameter); + return VERSION_ERROR; + } + } + else + #endif + if (ssl->ctx->method->version.major == SSLv3_MAJOR && + ssl->ctx->method->version.minor == TLSv1_2_MINOR) { + /* TLS v1.2 capable client not allowed to downgrade when + * connecting to TLS v1.2 capable server. + */ + if (XMEMCMP(down, tls13Downgrade, TLS13_DOWNGRADE_SZ) == 0 && + vers == 0) { + SendAlert(ssl, alert_fatal, illegal_parameter); + return VERSION_ERROR; + } + } + } + else { + if (DSH_CheckSessionId(ssl)) { + if (SetCipherSpecs(ssl) == 0) { + + XMEMCPY(ssl->arrays->masterSecret, + ssl->session.masterSecret, SECRET_LEN); + #ifdef NO_OLD_TLS + ret = DeriveTlsKeys(ssl); + #else + ret = -1; /* default value */ + #ifndef NO_TLS + if (ssl->options.tls) + ret = DeriveTlsKeys(ssl); + #endif + if (!ssl->options.tls) + ret = DeriveKeys(ssl); + #endif /* NO_OLD_TLS */ + ssl->options.serverState = SERVER_HELLODONE_COMPLETE; + + return ret; + } + else { + WOLFSSL_MSG("Unsupported cipher suite, DoServerHello"); + return UNSUPPORTED_SUITE; + } + } + else { + WOLFSSL_MSG("Server denied resumption attempt"); + ssl->options.resuming = 0; /* server denied resumption try */ + } + } + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + DtlsMsgPoolReset(ssl); + } + #endif + + return SetCipherSpecs(ssl); + } + +#endif /* WOLFSSL_NO_TLS12 */ + + + /* Make sure client setup is valid for this suite, true on success */ + int VerifyClientSuite(WOLFSSL* ssl) + { + int havePSK = 0; + byte first = ssl->options.cipherSuite0; + byte second = ssl->options.cipherSuite; + + WOLFSSL_ENTER("VerifyClientSuite"); + + #ifndef NO_PSK + havePSK = ssl->options.havePSK; + #endif + + if (CipherRequires(first, second, REQUIRES_PSK)) { + WOLFSSL_MSG("Requires PSK"); + if (havePSK == 0) { + WOLFSSL_MSG("Don't have PSK"); + return 0; + } + } + + return 1; /* success */ + } + +#ifndef WOLFSSL_NO_TLS12 + +#ifndef NO_CERTS + /* handle processing of certificate_request (13) */ + static int DoCertificateRequest(WOLFSSL* ssl, const byte* input, word32* + inOutIdx, word32 size) + { + word16 len; + word32 begin = *inOutIdx; + + WOLFSSL_START(WC_FUNC_CERTIFICATE_REQUEST_DO); + WOLFSSL_ENTER("DoCertificateRequest"); + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName(ssl, "CertificateRequest"); + if (ssl->toInfoOn) + AddLateName("CertificateRequest", &ssl->timeoutInfo); + #endif + + if ((*inOutIdx - begin) + OPAQUE8_LEN > size) + return BUFFER_ERROR; + + len = input[(*inOutIdx)++]; + + if ((*inOutIdx - begin) + len > size) + return BUFFER_ERROR; + + /* types, read in here */ + *inOutIdx += len; + + /* signature and hash signature algorithm */ + if (IsAtLeastTLSv1_2(ssl)) { + if ((*inOutIdx - begin) + OPAQUE16_LEN > size) + return BUFFER_ERROR; + + ato16(input + *inOutIdx, &len); + *inOutIdx += OPAQUE16_LEN; + + if ((*inOutIdx - begin) + len > size) + return BUFFER_ERROR; + + if (PickHashSigAlgo(ssl, input + *inOutIdx, len) != 0 && + ssl->buffers.certificate && + ssl->buffers.certificate->buffer) { + #ifdef HAVE_PK_CALLBACKS + if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) { + WOLFSSL_MSG("Using PK for client private key"); + return INVALID_PARAMETER; + } + #endif + if (ssl->buffers.key && ssl->buffers.key->buffer) { + return INVALID_PARAMETER; + } + } + *inOutIdx += len; + #ifdef WC_RSA_PSS + ssl->pssAlgo = 0; + if (ssl->suites->sigAlgo == rsa_pss_sa_algo) + ssl->pssAlgo |= 1 << ssl->suites->hashAlgo; + #endif + } + + /* authorities */ + if ((*inOutIdx - begin) + OPAQUE16_LEN > size) + return BUFFER_ERROR; + + ato16(input + *inOutIdx, &len); + *inOutIdx += OPAQUE16_LEN; + + if ((*inOutIdx - begin) + len > size) + return BUFFER_ERROR; + + while (len) { + word16 dnSz; + + if ((*inOutIdx - begin) + OPAQUE16_LEN > size) + return BUFFER_ERROR; + + ato16(input + *inOutIdx, &dnSz); + *inOutIdx += OPAQUE16_LEN; + + if ((*inOutIdx - begin) + dnSz > size) + return BUFFER_ERROR; + + *inOutIdx += dnSz; + len -= OPAQUE16_LEN + dnSz; + } + + /* don't send client cert or cert verify if user hasn't provided + cert and private key */ + if (ssl->buffers.certificate && ssl->buffers.certificate->buffer) { + #ifdef HAVE_PK_CALLBACKS + if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) { + WOLFSSL_MSG("Using PK for client private key"); + ssl->options.sendVerify = SEND_CERT; + } + #endif + if (ssl->buffers.key && ssl->buffers.key->buffer) { + ssl->options.sendVerify = SEND_CERT; + } + } + #ifdef OPENSSL_EXTRA + else + #else + else if (IsTLS(ssl)) + #endif + { + ssl->options.sendVerify = SEND_BLANK_CERT; + } + + if (IsEncryptionOn(ssl, 0)) + *inOutIdx += ssl->keys.padSz; + + WOLFSSL_LEAVE("DoCertificateRequest", 0); + WOLFSSL_END(WC_FUNC_CERTIFICATE_REQUEST_DO); + + return 0; + } +#endif /* !NO_CERTS */ + + +#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) + + static int CheckCurveId(int tlsCurveId) + { + int ret = ECC_CURVE_ERROR; + + switch (tlsCurveId) { + #if defined(HAVE_ECC160) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP160R1: return ECC_SECP160R1_OID; + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_SECPR2 + case WOLFSSL_ECC_SECP160R2: return ECC_SECP160R2_OID; + #endif /* HAVE_ECC_SECPR2 */ + #ifdef HAVE_ECC_KOBLITZ + case WOLFSSL_ECC_SECP160K1: return ECC_SECP160K1_OID; + #endif /* HAVE_ECC_KOBLITZ */ + #endif + #if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP192R1: return ECC_SECP192R1_OID; + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_KOBLITZ + case WOLFSSL_ECC_SECP192K1: return ECC_SECP192K1_OID; + #endif /* HAVE_ECC_KOBLITZ */ + #endif + #if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP224R1: return ECC_SECP224R1_OID; + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_KOBLITZ + case WOLFSSL_ECC_SECP224K1: return ECC_SECP224K1_OID; + #endif /* HAVE_ECC_KOBLITZ */ + #endif + #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) + #ifdef HAVE_CURVE25519 + case WOLFSSL_ECC_X25519: return ECC_X25519_OID; + #endif + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP256R1: return ECC_SECP256R1_OID; + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_KOBLITZ + case WOLFSSL_ECC_SECP256K1: return ECC_SECP256K1_OID; + #endif /* HAVE_ECC_KOBLITZ */ + #ifdef HAVE_ECC_BRAINPOOL + case WOLFSSL_ECC_BRAINPOOLP256R1: return ECC_BRAINPOOLP256R1_OID; + #endif /* HAVE_ECC_BRAINPOOL */ + #endif + #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP384R1: return ECC_SECP384R1_OID; + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_BRAINPOOL + case WOLFSSL_ECC_BRAINPOOLP384R1: return ECC_BRAINPOOLP384R1_OID; + #endif /* HAVE_ECC_BRAINPOOL */ + #endif + #if defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES) + #ifdef HAVE_ECC_BRAINPOOL + case WOLFSSL_ECC_BRAINPOOLP512R1: return ECC_BRAINPOOLP512R1_OID; + #endif /* HAVE_ECC_BRAINPOOL */ + #endif + #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP521R1: return ECC_SECP521R1_OID; + #endif /* !NO_ECC_SECP */ + #endif + } + + return ret; + } + +#endif /* HAVE_ECC */ + +/* Persistable DoServerKeyExchange arguments */ +typedef struct DskeArgs { + byte* output; /* not allocated */ +#if !defined(NO_DH) || defined(HAVE_ECC) || defined(HAVE_ED25519) + byte* verifySig; +#endif + word32 idx; + word32 begin; +#if !defined(NO_DH) || defined(HAVE_ECC) || defined(HAVE_ED25519) + word16 verifySigSz; +#endif + word16 sigSz; + byte sigAlgo; + byte hashAlgo; +} DskeArgs; + +static void FreeDskeArgs(WOLFSSL* ssl, void* pArgs) +{ + DskeArgs* args = (DskeArgs*)pArgs; + + (void)ssl; + (void)args; + +#if !defined(NO_DH) || defined(HAVE_ECC) || defined(HAVE_ED25519) + if (args->verifySig) { + XFREE(args->verifySig, ssl->heap, DYNAMIC_TYPE_SIGNATURE); + args->verifySig = NULL; + } +#endif +} + +#ifndef NO_DH +static int GetDhPublicKey(WOLFSSL* ssl, const byte* input, word32 size, + DskeArgs* args) +{ + int ret = 0; + word16 length; +#ifdef HAVE_FFDHE + const DhParams* params = NULL; + int group; +#endif + + /* p */ + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_gdpk); + } + + ato16(input + args->idx, &length); + args->idx += OPAQUE16_LEN; + + if ((args->idx - args->begin) + length > size) { + ERROR_OUT(BUFFER_ERROR, exit_gdpk); + } + + if (length < ssl->options.minDhKeySz) { + WOLFSSL_MSG("Server using a DH key that is too small"); + SendAlert(ssl, alert_fatal, handshake_failure); + ERROR_OUT(DH_KEY_SIZE_E, exit_gdpk); + } + if (length > ssl->options.maxDhKeySz) { + WOLFSSL_MSG("Server using a DH key that is too big"); + SendAlert(ssl, alert_fatal, handshake_failure); + ERROR_OUT(DH_KEY_SIZE_E, exit_gdpk); + } + + ssl->buffers.serverDH_P.buffer = + (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + if (ssl->buffers.serverDH_P.buffer) { + ssl->buffers.serverDH_P.length = length; + } + else { + ERROR_OUT(MEMORY_ERROR, exit_gdpk); + } + + XMEMCPY(ssl->buffers.serverDH_P.buffer, input + args->idx, + length); + args->idx += length; + + ssl->options.dhKeySz = length; + + /* g */ + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_gdpk); + } + + ato16(input + args->idx, &length); + args->idx += OPAQUE16_LEN; + + if ((args->idx - args->begin) + length > size) { + ERROR_OUT(BUFFER_ERROR, exit_gdpk); + } + + ssl->buffers.serverDH_G.buffer = + (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + if (ssl->buffers.serverDH_G.buffer) { + ssl->buffers.serverDH_G.length = length; + } + else { + ERROR_OUT(MEMORY_ERROR, exit_gdpk); + } + + XMEMCPY(ssl->buffers.serverDH_G.buffer, input + args->idx, + length); + args->idx += length; + + ssl->buffers.weOwnDH = 1; + + /* pub */ + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_gdpk); + } + + ato16(input + args->idx, &length); + args->idx += OPAQUE16_LEN; + + if ((args->idx - args->begin) + length > size) { + ERROR_OUT(BUFFER_ERROR, exit_gdpk); + } + + ssl->buffers.serverDH_Pub.buffer = + (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + if (ssl->buffers.serverDH_Pub.buffer) { + ssl->buffers.serverDH_Pub.length = length; + } + else { + ERROR_OUT(MEMORY_ERROR, exit_gdpk); + } + + XMEMCPY(ssl->buffers.serverDH_Pub.buffer, input + args->idx, + length); + args->idx += length; + +#ifdef HAVE_FFDHE + switch (ssl->options.dhKeySz) { + #ifdef HAVE_FFDHE_2048 + case 2048/8: + params = wc_Dh_ffdhe2048_Get(); + group = WOLFSSL_FFDHE_2048; + break; + #endif + #ifdef HAVE_FFDHE_3072 + case 3072/8: + params = wc_Dh_ffdhe3072_Get(); + group = WOLFSSL_FFDHE_3072; + break; + #endif + #ifdef HAVE_FFDHE_4096 + case 4096/8: + params = wc_Dh_ffdhe4096_Get(); + group = WOLFSSL_FFDHE_4096; + break; + #endif + #ifdef HAVE_FFDHE_6144 + case 6144/8: + params = wc_Dh_ffdhe6144_Get(); + group = WOLFSSL_FFDHE_6144; + break; + #endif + #ifdef HAVE_FFDHE_8192 + case 8192/8: + params = wc_Dh_ffdhe8192_Get(); + group = WOLFSSL_FFDHE_8192; + break; + #endif + default: + break; + } + + if (params == NULL || params->g_len != ssl->buffers.serverDH_G.length || + (XMEMCMP(ssl->buffers.serverDH_G.buffer, params->g, + params->g_len) != 0) || + (XMEMCMP(ssl->buffers.serverDH_P.buffer, params->p, + params->p_len) != 0)) { + WOLFSSL_MSG("Server not using FFDHE parameters"); + #ifdef WOLFSSL_REQUIRE_FFDHE + SendAlert(ssl, alert_fatal, handshake_failure); + ERROR_OUT(DH_PARAMS_NOT_FFDHE_E, exit_gdpk); + #endif + } + else { + ssl->namedGroup = group; + #if !defined(WOLFSSL_OLD_PRIME_CHECK) && !defined(HAVE_FIPS) && \ + !defined(HAVE_SELFTEST) + ssl->options.dhDoKeyTest = 0; + #endif + } +#endif /* HAVE_FFDHE */ + +exit_gdpk: + return ret; +} +#endif + +/* handle processing of server_key_exchange (12) */ +static int DoServerKeyExchange(WOLFSSL* ssl, const byte* input, + word32* inOutIdx, word32 size) +{ + int ret = 0; +#ifdef WOLFSSL_ASYNC_CRYPT + DskeArgs* args = (DskeArgs*)ssl->async.args; + typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1]; + (void)sizeof(args_test); +#else + DskeArgs args[1]; +#endif + + (void)input; + (void)size; + + WOLFSSL_START(WC_FUNC_SERVER_KEY_EXCHANGE_DO); + WOLFSSL_ENTER("DoServerKeyExchange"); + +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); + if (ret != WC_NOT_PENDING_E) { + /* Check for error */ + if (ret < 0) + goto exit_dske; + } + else +#endif + { + /* Reset state */ + ret = 0; + ssl->options.asyncState = TLS_ASYNC_BEGIN; + XMEMSET(args, 0, sizeof(DskeArgs)); + args->idx = *inOutIdx; + args->begin = *inOutIdx; + args->sigAlgo = ssl->specs.sig_algo; + args->hashAlgo = sha_mac; + #ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = FreeDskeArgs; + #endif + } + + switch(ssl->options.asyncState) + { + case TLS_ASYNC_BEGIN: + { + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName(ssl, "ServerKeyExchange"); + if (ssl->toInfoOn) + AddLateName("ServerKeyExchange", &ssl->timeoutInfo); + #endif + + switch(ssl->specs.kea) + { + #ifndef NO_PSK + case psk_kea: + { + int srvHintLen; + word16 length; + + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } + + ato16(input + args->idx, &length); + args->idx += OPAQUE16_LEN; + + if ((args->idx - args->begin) + length > size) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } + + /* get PSK server hint from the wire */ + srvHintLen = min(length, MAX_PSK_ID_LEN); + XMEMCPY(ssl->arrays->server_hint, input + args->idx, + srvHintLen); + ssl->arrays->server_hint[srvHintLen] = '\0'; /* null term */ + args->idx += length; + break; + } + #endif /* !NO_PSK */ + #ifndef NO_DH + case diffie_hellman_kea: + { + ret = GetDhPublicKey(ssl, input, size, args); + if (ret != 0) + goto exit_dske; + break; + } + #endif /* !NO_DH */ + #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) + case ecc_diffie_hellman_kea: + { + byte b; + #ifdef HAVE_ECC + int curveId; + #endif + int curveOid; + word16 length; + + if ((args->idx - args->begin) + ENUM_LEN + OPAQUE16_LEN + + OPAQUE8_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } + + b = input[args->idx++]; + if (b != named_curve) { + ERROR_OUT(ECC_CURVETYPE_ERROR, exit_dske); + } + + args->idx += 1; /* curve type, eat leading 0 */ + b = input[args->idx++]; + if ((curveOid = CheckCurveId(b)) < 0) { + ERROR_OUT(ECC_CURVE_ERROR, exit_dske); + } + ssl->ecdhCurveOID = curveOid; + + length = input[args->idx++]; + if ((args->idx - args->begin) + length > size) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } + + #ifdef HAVE_CURVE25519 + if (ssl->ecdhCurveOID == ECC_X25519_OID) { + if (ssl->peerX25519Key == NULL) { + ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE25519, + (void**)&ssl->peerX25519Key); + if (ret != 0) { + goto exit_dske; + } + } else if (ssl->peerX25519KeyPresent) { + ret = ReuseKey(ssl, DYNAMIC_TYPE_CURVE25519, + ssl->peerX25519Key); + ssl->peerX25519KeyPresent = 0; + if (ret != 0) { + goto exit_dske; + } + } + + if (wc_curve25519_import_public_ex(input + args->idx, + length, ssl->peerX25519Key, + EC25519_LITTLE_ENDIAN) != 0) { + ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske); + } + + args->idx += length; + ssl->peerX25519KeyPresent = 1; + break; + } + #endif + #ifdef HAVE_ECC + if (ssl->peerEccKey == NULL) { + ret = AllocKey(ssl, DYNAMIC_TYPE_ECC, + (void**)&ssl->peerEccKey); + if (ret != 0) { + goto exit_dske; + } + } else if (ssl->peerEccKeyPresent) { + ret = ReuseKey(ssl, DYNAMIC_TYPE_ECC, ssl->peerEccKey); + ssl->peerEccKeyPresent = 0; + if (ret != 0) { + goto exit_dske; + } + } + + curveId = wc_ecc_get_oid(curveOid, NULL, NULL); + if (wc_ecc_import_x963_ex(input + args->idx, length, + ssl->peerEccKey, curveId) != 0) { + ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske); + } + + args->idx += length; + ssl->peerEccKeyPresent = 1; + #endif + break; + } + #endif /* HAVE_ECC || HAVE_CURVE25519 */ + #if !defined(NO_DH) && !defined(NO_PSK) + case dhe_psk_kea: + { + int srvHintLen; + word16 length; + + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } + + ato16(input + args->idx, &length); + args->idx += OPAQUE16_LEN; + + if ((args->idx - args->begin) + length > size) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } + + /* get PSK server hint from the wire */ + srvHintLen = min(length, MAX_PSK_ID_LEN); + XMEMCPY(ssl->arrays->server_hint, input + args->idx, + srvHintLen); + ssl->arrays->server_hint[srvHintLen] = '\0'; /* null term */ + args->idx += length; + + ret = GetDhPublicKey(ssl, input, size, args); + if (ret != 0) + goto exit_dske; + break; + } + #endif /* !NO_DH && !NO_PSK */ + #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \ + !defined(NO_PSK) + case ecdhe_psk_kea: + { + byte b; + int curveOid, curveId; + int srvHintLen; + word16 length; + + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } + + ato16(input + args->idx, &length); + args->idx += OPAQUE16_LEN; + + if ((args->idx - args->begin) + length > size) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } + + /* get PSK server hint from the wire */ + srvHintLen = min(length, MAX_PSK_ID_LEN); + XMEMCPY(ssl->arrays->server_hint, input + args->idx, + srvHintLen); + ssl->arrays->server_hint[srvHintLen] = '\0'; /* null term */ + + args->idx += length; + + if ((args->idx - args->begin) + ENUM_LEN + OPAQUE16_LEN + + OPAQUE8_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } + + /* Check curve name and ID */ + b = input[args->idx++]; + if (b != named_curve) { + ERROR_OUT(ECC_CURVETYPE_ERROR, exit_dske); + } + + args->idx += 1; /* curve type, eat leading 0 */ + b = input[args->idx++]; + if ((curveOid = CheckCurveId(b)) < 0) { + ERROR_OUT(ECC_CURVE_ERROR, exit_dske); + } + + length = input[args->idx++]; + if ((args->idx - args->begin) + length > size) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } + + #ifdef HAVE_CURVE25519 + if (ssl->ecdhCurveOID == ECC_X25519_OID) { + if (ssl->peerX25519Key == NULL) { + ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE25519, + (void**)&ssl->peerX25519Key); + if (ret != 0) { + goto exit_dske; + } + } else if (ssl->peerEccKeyPresent) { + ret = ReuseKey(ssl, DYNAMIC_TYPE_CURVE25519, + ssl->peerX25519Key); + ssl->peerX25519KeyPresent = 0; + if (ret != 0) { + goto exit_dske; + } + } + + if (wc_curve25519_import_public_ex(input + args->idx, + length, ssl->peerX25519Key, + EC25519_LITTLE_ENDIAN) != 0) { + ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske); + } + + args->idx += length; + ssl->peerX25519KeyPresent = 1; + break; + } + #endif + + if (ssl->peerEccKey == NULL) { + ret = AllocKey(ssl, DYNAMIC_TYPE_ECC, + (void**)&ssl->peerEccKey); + if (ret != 0) { + goto exit_dske; + } + } else if (ssl->peerEccKeyPresent) { + ret = ReuseKey(ssl, DYNAMIC_TYPE_ECC, ssl->peerEccKey); + ssl->peerEccKeyPresent = 0; + if (ret != 0) { + goto exit_dske; + } + } + + curveId = wc_ecc_get_oid(curveOid, NULL, NULL); + if (wc_ecc_import_x963_ex(input + args->idx, length, + ssl->peerEccKey, curveId) != 0) { + ERROR_OUT(ECC_PEERKEY_ERROR, exit_dske); + } + + args->idx += length; + ssl->peerEccKeyPresent = 1; + break; + } + #endif /* (HAVE_ECC || HAVE_CURVE25519) && !NO_PSK */ + default: + ret = BAD_KEA_TYPE_E; + } /* switch(ssl->specs.kea) */ + + /* Check for error */ + if (ret != 0) { + goto exit_dske; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_BUILD; + } /* case TLS_ASYNC_BEGIN */ + FALL_THROUGH; + + case TLS_ASYNC_BUILD: + { + switch(ssl->specs.kea) + { + case psk_kea: + case dhe_psk_kea: + case ecdhe_psk_kea: + { + /* Nothing to do in this sub-state */ + break; + } + + case diffie_hellman_kea: + case ecc_diffie_hellman_kea: + { + #if defined(NO_DH) && !defined(HAVE_ECC) && !defined(HAVE_ED25519) + ERROR_OUT(NOT_COMPILED_IN, exit_dske); + #else + enum wc_HashType hashType; + word16 verifySz; + + if (ssl->options.usingAnon_cipher) { + break; + } + + verifySz = (word16)(args->idx - args->begin); + if (verifySz > MAX_DH_SZ) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } + + if (IsAtLeastTLSv1_2(ssl)) { + if ((args->idx - args->begin) + ENUM_LEN + ENUM_LEN > + size) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } + + DecodeSigAlg(&input[args->idx], &args->hashAlgo, + &args->sigAlgo); + args->idx += 2; + hashType = HashAlgoToType(args->hashAlgo); + if (hashType == WC_HASH_TYPE_NONE) { + ERROR_OUT(ALGO_ID_E, exit_dske); + } + } else { + /* only using sha and md5 for rsa */ + #ifndef NO_OLD_TLS + hashType = WC_HASH_TYPE_SHA; + if (args->sigAlgo == rsa_sa_algo) { + hashType = WC_HASH_TYPE_MD5_SHA; + } + #else + ERROR_OUT(ALGO_ID_E, exit_dske); + #endif + } + + /* signature */ + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } + + ato16(input + args->idx, &args->verifySigSz); + args->idx += OPAQUE16_LEN; + + if ((args->idx - args->begin) + args->verifySigSz > size) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } + + /* buffer for signature */ + ssl->buffers.sig.buffer = (byte*)XMALLOC(SEED_LEN + verifySz, + ssl->heap, DYNAMIC_TYPE_SIGNATURE); + if (ssl->buffers.sig.buffer == NULL) { + ERROR_OUT(MEMORY_E, exit_dske); + } + ssl->buffers.sig.length = SEED_LEN + verifySz; + + /* build message to hash */ + XMEMCPY(ssl->buffers.sig.buffer, + ssl->arrays->clientRandom, RAN_LEN); + XMEMCPY(&ssl->buffers.sig.buffer[RAN_LEN], + ssl->arrays->serverRandom, RAN_LEN); + XMEMCPY(&ssl->buffers.sig.buffer[RAN_LEN * 2], + input + args->begin, verifySz); /* message */ + + if (args->sigAlgo != ed25519_sa_algo) { + int digest_sz = wc_HashGetDigestSize(hashType); + if (digest_sz <= 0) { + ERROR_OUT(BUFFER_ERROR, exit_dske); + } + ssl->buffers.digest.length = (unsigned int)digest_sz; + + /* buffer for hash */ + ssl->buffers.digest.buffer = (byte*)XMALLOC( + ssl->buffers.digest.length, ssl->heap, + DYNAMIC_TYPE_DIGEST); + if (ssl->buffers.digest.buffer == NULL) { + ERROR_OUT(MEMORY_E, exit_dske); + } + + /* Perform hash */ + ret = wc_Hash(hashType, ssl->buffers.sig.buffer, + ssl->buffers.sig.length, + ssl->buffers.digest.buffer, + ssl->buffers.digest.length); + if (ret != 0) { + goto exit_dske; + } + } + + switch (args->sigAlgo) + { + #ifndef NO_RSA + #ifdef WC_RSA_PSS + case rsa_pss_sa_algo: + #endif + case rsa_sa_algo: + { + if (ssl->peerRsaKey == NULL || + !ssl->peerRsaKeyPresent) { + ERROR_OUT(NO_PEER_KEY, exit_dske); + } + break; + } + #endif /* !NO_RSA */ + #ifdef HAVE_ECC + case ecc_dsa_sa_algo: + { + if (!ssl->peerEccDsaKeyPresent) { + ERROR_OUT(NO_PEER_KEY, exit_dske); + } + break; + } + #endif /* HAVE_ECC */ + #if defined(HAVE_ED25519) + case ed25519_sa_algo: + { + if (!ssl->peerEd25519KeyPresent) { + ERROR_OUT(NO_PEER_KEY, exit_dske); + } + break; + } + #endif /* HAVE_ED25519 */ + + default: + ret = ALGO_ID_E; + } /* switch (args->sigAlgo) */ + + #endif /* NO_DH && !HAVE_ECC && !HAVE_ED25519 */ + break; + } + default: + ret = BAD_KEA_TYPE_E; + } /* switch(ssl->specs.kea) */ + + /* Check for error */ + if (ret != 0) { + goto exit_dske; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_DO; + } /* case TLS_ASYNC_BUILD */ + FALL_THROUGH; + + case TLS_ASYNC_DO: + { + switch(ssl->specs.kea) + { + case psk_kea: + case dhe_psk_kea: + case ecdhe_psk_kea: + { + /* Nothing to do in this sub-state */ + break; + } + + case diffie_hellman_kea: + case ecc_diffie_hellman_kea: + { + #if defined(NO_DH) && !defined(HAVE_ECC) && !defined(HAVE_ED25519) + ERROR_OUT(NOT_COMPILED_IN, exit_dske); + #else + if (ssl->options.usingAnon_cipher) { + break; + } + + if (args->verifySig == NULL) { + args->verifySig = (byte*)XMALLOC(args->verifySigSz, + ssl->heap, DYNAMIC_TYPE_SIGNATURE); + if (args->verifySig == NULL) { + ERROR_OUT(MEMORY_E, exit_dske); + } + XMEMCPY(args->verifySig, input + args->idx, + args->verifySigSz); + } + + switch (args->sigAlgo) + { + #ifndef NO_RSA + #ifdef WC_RSA_PSS + case rsa_pss_sa_algo: + #endif + case rsa_sa_algo: + { + ret = RsaVerify(ssl, + args->verifySig, args->verifySigSz, + &args->output, + args->sigAlgo, args->hashAlgo, + ssl->peerRsaKey, + #ifdef HAVE_PK_CALLBACKS + &ssl->buffers.peerRsaKey + #else + NULL + #endif + ); + + if (ret >= 0) { + args->sigSz = (word16)ret; + ret = 0; + } + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret != WC_PENDING_E) + #endif + { + /* peerRsaKey */ + FreeKey(ssl, DYNAMIC_TYPE_RSA, + (void**)&ssl->peerRsaKey); + ssl->peerRsaKeyPresent = 0; + } + break; + } + #endif /* !NO_RSA */ + #ifdef HAVE_ECC + case ecc_dsa_sa_algo: + { + ret = EccVerify(ssl, + args->verifySig, args->verifySigSz, + ssl->buffers.digest.buffer, + ssl->buffers.digest.length, + ssl->peerEccDsaKey, + #ifdef HAVE_PK_CALLBACKS + &ssl->buffers.peerEccDsaKey + #else + NULL + #endif + ); + + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret != WC_PENDING_E) + #endif + { + /* peerEccDsaKey */ + FreeKey(ssl, DYNAMIC_TYPE_ECC, + (void**)&ssl->peerEccDsaKey); + ssl->peerEccDsaKeyPresent = 0; + } + break; + } + #endif /* HAVE_ECC */ + #if defined(HAVE_ED25519) + case ed25519_sa_algo: + { + ret = Ed25519Verify(ssl, + args->verifySig, args->verifySigSz, + ssl->buffers.sig.buffer, + ssl->buffers.sig.length, + ssl->peerEd25519Key, + #ifdef HAVE_PK_CALLBACKS + &ssl->buffers.peerEd25519Key + #else + NULL + #endif + ); + + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret != WC_PENDING_E) + #endif + { + /* peerEccDsaKey */ + FreeKey(ssl, DYNAMIC_TYPE_ED25519, + (void**)&ssl->peerEd25519Key); + ssl->peerEd25519KeyPresent = 0; + } + break; + } + #endif /* HAVE_ED25519 */ + + default: + ret = ALGO_ID_E; + } /* switch (sigAlgo) */ + #endif /* NO_DH && !HAVE_ECC && !HAVE_ED25519 */ + break; + } + default: + ret = BAD_KEA_TYPE_E; + } /* switch(ssl->specs.kea) */ + + /* Check for error */ + if (ret != 0) { + goto exit_dske; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_VERIFY; + } /* case TLS_ASYNC_DO */ + FALL_THROUGH; + + case TLS_ASYNC_VERIFY: + { + switch(ssl->specs.kea) + { + case psk_kea: + case dhe_psk_kea: + case ecdhe_psk_kea: + { + /* Nothing to do in this sub-state */ + break; + } + + case diffie_hellman_kea: + case ecc_diffie_hellman_kea: + { + #if defined(NO_DH) && !defined(HAVE_ECC) && !defined(HAVE_ED25519) + ERROR_OUT(NOT_COMPILED_IN, exit_dske); + #else + if (ssl->options.usingAnon_cipher) { + break; + } + + /* increment index after verify is done */ + args->idx += args->verifySigSz; + + switch(args->sigAlgo) + { + #ifndef NO_RSA + #ifdef WC_RSA_PSS + case rsa_pss_sa_algo: + ret = wc_RsaPSS_CheckPadding( + ssl->buffers.digest.buffer, + ssl->buffers.digest.length, + args->output, args->sigSz, + HashAlgoToType(args->hashAlgo)); + if (ret != 0) + return ret; + break; + #endif + case rsa_sa_algo: + { + if (IsAtLeastTLSv1_2(ssl)) { + #ifdef WOLFSSL_SMALL_STACK + byte* encodedSig = NULL; + #else + byte encodedSig[MAX_ENCODED_SIG_SZ]; + #endif + word32 encSigSz; + + #ifdef WOLFSSL_SMALL_STACK + encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, + ssl->heap, DYNAMIC_TYPE_SIGNATURE); + if (encodedSig == NULL) { + ERROR_OUT(MEMORY_E, exit_dske); + } + #endif + + encSigSz = wc_EncodeSignature(encodedSig, + ssl->buffers.digest.buffer, + ssl->buffers.digest.length, + TypeHash(args->hashAlgo)); + if (encSigSz != args->sigSz || !args->output || + XMEMCMP(args->output, encodedSig, + min(encSigSz, MAX_ENCODED_SIG_SZ)) != 0) { + ret = VERIFY_SIGN_ERROR; + } + #ifdef WOLFSSL_SMALL_STACK + XFREE(encodedSig, ssl->heap, DYNAMIC_TYPE_SIGNATURE); + #endif + if (ret != 0) { + goto exit_dske; + } + } + else if (args->sigSz != FINISHED_SZ || + !args->output || + XMEMCMP(args->output, + ssl->buffers.digest.buffer, + FINISHED_SZ) != 0) { + ERROR_OUT(VERIFY_SIGN_ERROR, exit_dske); + } + break; + } + #endif /* !NO_RSA */ + #ifdef HAVE_ECC + case ecc_dsa_sa_algo: + /* Nothing to do in this algo */ + break; + #endif /* HAVE_ECC */ + #if defined(HAVE_ED25519) + case ed25519_sa_algo: + /* Nothing to do in this algo */ + break; + #endif /* HAVE_ED25519 */ + default: + ret = ALGO_ID_E; + } /* switch (sigAlgo) */ + #endif /* NO_DH && !HAVE_ECC && !HAVE_ED25519 */ + break; + } + default: + ret = BAD_KEA_TYPE_E; + } /* switch(ssl->specs.kea) */ + + /* Check for error */ + if (ret != 0) { + goto exit_dske; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_FINALIZE; + } /* case TLS_ASYNC_VERIFY */ + FALL_THROUGH; + + case TLS_ASYNC_FINALIZE: + { + if (IsEncryptionOn(ssl, 0)) { + args->idx += ssl->keys.padSz; + } + + /* QSH extensions */ + #ifdef HAVE_QSH + if (ssl->peerQSHKeyPresent) { + word16 name; + int qshSz; + + /* extension name */ + ato16(input + args->idx, &name); + args->idx += OPAQUE16_LEN; + + if (name == TLSX_QUANTUM_SAFE_HYBRID) { + /* if qshSz is larger than 0 it is the length of + buffer used */ + if ((qshSz = TLSX_QSHCipher_Parse(ssl, input + args->idx, + size, 0)) < 0) { + ERROR_OUT(qshSz, exit_dske); + } + args->idx += qshSz; + } + else { + /* unknown extension sent server ignored handshake */ + ERROR_OUT(BUFFER_ERROR, exit_dske); + } + } + #endif + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_END; + } /* case TLS_ASYNC_FINALIZE */ + FALL_THROUGH; + + case TLS_ASYNC_END: + { + /* return index */ + *inOutIdx = args->idx; + + ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE; + break; + } + default: + ret = INPUT_CASE_ERROR; + } /* switch(ssl->options.asyncState) */ + +exit_dske: + + WOLFSSL_LEAVE("DoServerKeyExchange", ret); + WOLFSSL_END(WC_FUNC_SERVER_KEY_EXCHANGE_DO); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* Handle async operation */ + if (ret == WC_PENDING_E) { + /* Mark message as not received so it can process again */ + ssl->msgsReceived.got_server_key_exchange = 0; + + return ret; + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + /* Final cleanup */ + FreeDskeArgs(ssl, args); + FreeKeyExchange(ssl); + + return ret; +} + + +#ifdef HAVE_QSH + +#ifdef HAVE_NTRU +/* Encrypt a byte array using ntru + key a struct containing the public key to use + bufIn array to be encrypted + inSz size of bufIn array + bufOut cipher text out + outSz will be set to the new size of cipher text + */ +static int NtruSecretEncrypt(QSHKey* key, byte* bufIn, word32 inSz, + byte* bufOut, word16* outSz) +{ + int ret; + DRBG_HANDLE drbg; + + /* sanity checks on input arguments */ + if (key == NULL || bufIn == NULL || bufOut == NULL || outSz == NULL) + return BAD_FUNC_ARG; + + if (key->pub.buffer == NULL) + return BAD_FUNC_ARG; + + switch (key->name) { + case WOLFSSL_NTRU_EESS439: + case WOLFSSL_NTRU_EESS593: + case WOLFSSL_NTRU_EESS743: + break; + default: + WOLFSSL_MSG("Unknown QSH encryption key!"); + return -1; + } + + /* set up ntru drbg */ + ret = ntru_crypto_drbg_external_instantiate(GetEntropy, &drbg); + if (ret != DRBG_OK) + return NTRU_DRBG_ERROR; + + /* encrypt the byte array */ + ret = ntru_crypto_ntru_encrypt(drbg, key->pub.length, key->pub.buffer, + inSz, bufIn, outSz, bufOut); + ntru_crypto_drbg_uninstantiate(drbg); + if (ret != NTRU_OK) + return NTRU_ENCRYPT_ERROR; + + return ret; +} + +/* Decrypt a byte array using ntru + key a struct containing the private key to use + bufIn array to be decrypted + inSz size of bufIn array + bufOut plain text out + outSz will be set to the new size of plain text + */ + +static int NtruSecretDecrypt(QSHKey* key, byte* bufIn, word32 inSz, + byte* bufOut, word16* outSz) +{ + int ret; + DRBG_HANDLE drbg; + + /* sanity checks on input arguments */ + if (key == NULL || bufIn == NULL || bufOut == NULL || outSz == NULL) + return BAD_FUNC_ARG; + + if (key->pri.buffer == NULL) + return BAD_FUNC_ARG; + + switch (key->name) { + case WOLFSSL_NTRU_EESS439: + case WOLFSSL_NTRU_EESS593: + case WOLFSSL_NTRU_EESS743: + break; + default: + WOLFSSL_MSG("Unknown QSH decryption key!"); + return -1; + } + + + /* set up drbg */ + ret = ntru_crypto_drbg_external_instantiate(GetEntropy, &drbg); + if (ret != DRBG_OK) + return NTRU_DRBG_ERROR; + + /* decrypt cipher text */ + ret = ntru_crypto_ntru_decrypt(key->pri.length, key->pri.buffer, + inSz, bufIn, outSz, bufOut); + ntru_crypto_drbg_uninstantiate(drbg); + if (ret != NTRU_OK) + return NTRU_ENCRYPT_ERROR; + + return ret; +} +#endif /* HAVE_NTRU */ + +int QSH_Init(WOLFSSL* ssl) +{ + /* check so not initialising twice when running DTLS */ + if (ssl->QSH_secret != NULL) + return 0; + + /* malloc memory for holding generated secret information */ + if ((ssl->QSH_secret = (QSHSecret*)XMALLOC(sizeof(QSHSecret), ssl->heap, + DYNAMIC_TYPE_QSH)) == NULL) + return MEMORY_E; + + ssl->QSH_secret->CliSi = (buffer*)XMALLOC(sizeof(buffer), ssl->heap, + DYNAMIC_TYPE_SECRET); + if (ssl->QSH_secret->CliSi == NULL) + return MEMORY_E; + + ssl->QSH_secret->SerSi = (buffer*)XMALLOC(sizeof(buffer), ssl->heap, + DYNAMIC_TYPE_SECRET); + if (ssl->QSH_secret->SerSi == NULL) + return MEMORY_E; + + /* initialize variables */ + ssl->QSH_secret->list = NULL; + ssl->QSH_secret->CliSi->length = 0; + ssl->QSH_secret->CliSi->buffer = NULL; + ssl->QSH_secret->SerSi->length = 0; + ssl->QSH_secret->SerSi->buffer = NULL; + + return 0; +} + + +static int QSH_Encrypt(QSHKey* key, byte* in, word32 szIn, + byte* out, word32* szOut) +{ + int ret = 0; + word16 size = *szOut; + + (void)in; + (void)szIn; + (void)out; + (void)szOut; + + WOLFSSL_MSG("Encrypting QSH key material"); + + switch (key->name) { + #ifdef HAVE_NTRU + case WOLFSSL_NTRU_EESS439: + case WOLFSSL_NTRU_EESS593: + case WOLFSSL_NTRU_EESS743: + ret = NtruSecretEncrypt(key, in, szIn, out, &size); + break; + #endif + default: + WOLFSSL_MSG("Unknown QSH encryption key!"); + return -1; + } + + *szOut = size; + + return ret; +} + + +/* Decrypt using Quantum Safe Handshake algorithms */ +int QSH_Decrypt(QSHKey* key, byte* in, word32 szIn, byte* out, word16* szOut) +{ + int ret = 0; + word16 size = *szOut; + + (void)in; + (void)szIn; + (void)out; + (void)szOut; + + WOLFSSL_MSG("Decrypting QSH key material"); + + switch (key->name) { + #ifdef HAVE_NTRU + case WOLFSSL_NTRU_EESS439: + case WOLFSSL_NTRU_EESS593: + case WOLFSSL_NTRU_EESS743: + ret = NtruSecretDecrypt(key, in, szIn, out, &size); + break; + #endif + default: + WOLFSSL_MSG("Unknown QSH decryption key!"); + return -1; + } + + *szOut = size; + + return ret; +} + + +/* Get the max cipher text for corresponding encryption scheme + (encrypting 48 or max plain text whichever is smaller) + */ +static word32 QSH_MaxSecret(QSHKey* key) +{ + int ret = 0; +#ifdef HAVE_NTRU + byte isNtru = 0; + word16 inSz = 48; + word16 outSz; + DRBG_HANDLE drbg = 0; + byte bufIn[48]; +#endif + + if (key == NULL || key->pub.length == 0) + return 0; + + switch(key->name) { +#ifdef HAVE_NTRU + case WOLFSSL_NTRU_EESS439: + isNtru = 1; + break; + case WOLFSSL_NTRU_EESS593: + isNtru = 1; + break; + case WOLFSSL_NTRU_EESS743: + isNtru = 1; + break; +#endif + default: + WOLFSSL_MSG("Unknown QSH encryption scheme size!"); + return 0; + } + +#ifdef HAVE_NTRU + if (isNtru) { + ret = ntru_crypto_drbg_external_instantiate(GetEntropy, &drbg); + if (ret != DRBG_OK) + return NTRU_DRBG_ERROR; + ret = ntru_crypto_ntru_encrypt(drbg, key->pub.length, + key->pub.buffer, inSz, bufIn, &outSz, NULL); + if (ret != NTRU_OK) { + return NTRU_ENCRYPT_ERROR; + } + ntru_crypto_drbg_uninstantiate(drbg); + ret = outSz; + } +#endif + + return ret; +} + +/* Generate the secret byte material for pms + returns length on success and -1 on fail + */ +static int QSH_GenerateSerCliSecret(WOLFSSL* ssl, byte isServer) +{ + int sz = 0; + int plainSz = 48; /* lesser of 48 and max plain text able to encrypt */ + int offset = 0; + word32 tmpSz = 0; + buffer* buf; + QSHKey* current = ssl->peerQSHKey; + QSHScheme* schmPre = NULL; + QSHScheme* schm = NULL; + + if (ssl == NULL) + return -1; + + WOLFSSL_MSG("Generating QSH secret key material"); + + /* get size of buffer needed */ + while (current) { + if (current->pub.length != 0) { + sz += plainSz; + } + current = (QSHKey*)current->next; + } + + /* allocate memory for buffer */ + if (isServer) { + buf = ssl->QSH_secret->SerSi; + } + else { + buf = ssl->QSH_secret->CliSi; + } + buf->length = sz; + buf->buffer = (byte*)XMALLOC(sz, ssl->heap, DYNAMIC_TYPE_SECRET); + if (buf->buffer == NULL) { + WOLFSSL_ERROR(MEMORY_E); + } + + /* create secret information */ + sz = 0; + current = ssl->peerQSHKey; + while (current) { + schm = (QSHScheme*)XMALLOC(sizeof(QSHScheme), ssl->heap, + DYNAMIC_TYPE_QSH); + if (schm == NULL) + return MEMORY_E; + + /* initialize variables */ + schm->name = 0; + schm->PK = NULL; + schm->PKLen = 0; + schm->next = NULL; + if (ssl->QSH_secret->list == NULL) { + ssl->QSH_secret->list = schm; + } + else { + if (schmPre) + schmPre->next = schm; + } + + tmpSz = QSH_MaxSecret(current); + + if ((schm->PK = (byte*)XMALLOC(tmpSz, ssl->heap, + DYNAMIC_TYPE_SECRET)) == NULL) + return -1; + + /* store info for writing extension */ + schm->name = current->name; + + /* no key to use for encryption */ + if (tmpSz == 0) { + current = (QSHKey*)current->next; + continue; + } + + if (wc_RNG_GenerateBlock(ssl->rng, buf->buffer + offset, plainSz) + != 0) { + return -1; + } + if (QSH_Encrypt(current, buf->buffer + offset, plainSz, schm->PK, + &tmpSz) != 0) { + return -1; + } + schm->PKLen = tmpSz; + + sz += tmpSz; + offset += plainSz; + schmPre = schm; + current = (QSHKey*)current->next; + } + + return sz; +} + + +static word32 QSH_KeyGetSize(WOLFSSL* ssl) +{ + word32 sz = 0; + QSHKey* current = ssl->peerQSHKey; + + if (ssl == NULL) + return -1; + + sz += OPAQUE16_LEN; /* type of extension ie 0x00 0x18 */ + sz += OPAQUE24_LEN; + /* get size of buffer needed */ + while (current) { + sz += OPAQUE16_LEN; /* scheme id */ + sz += OPAQUE16_LEN; /* encrypted key len*/ + sz += QSH_MaxSecret(current); + current = (QSHKey*)current->next; + } + + return sz; +} + + +/* handle QSH key Exchange + return 0 on success + */ +static word32 QSH_KeyExchangeWrite(WOLFSSL* ssl, byte isServer) +{ + int ret = 0; + + WOLFSSL_ENTER("QSH KeyExchange"); + + ret = QSH_GenerateSerCliSecret(ssl, isServer); + if (ret < 0) + return MEMORY_E; + + return 0; +} + +#endif /* HAVE_QSH */ + + +typedef struct SckeArgs { + byte* output; /* not allocated */ + byte* encSecret; + byte* input; + word32 encSz; + word32 length; + int sendSz; + int inputSz; +} SckeArgs; + +static void FreeSckeArgs(WOLFSSL* ssl, void* pArgs) +{ + SckeArgs* args = (SckeArgs*)pArgs; + + (void)ssl; + + if (args->encSecret) { + XFREE(args->encSecret, ssl->heap, DYNAMIC_TYPE_SECRET); + args->encSecret = NULL; + } + if (args->input) { + XFREE(args->input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + args->input = NULL; + } +} + +/* handle generation client_key_exchange (16) */ +int SendClientKeyExchange(WOLFSSL* ssl) +{ + int ret = 0; +#ifdef WOLFSSL_ASYNC_CRYPT + SckeArgs* args = (SckeArgs*)ssl->async.args; + typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1]; + (void)sizeof(args_test); +#else + SckeArgs args[1]; +#endif + + WOLFSSL_START(WC_FUNC_CLIENT_KEY_EXCHANGE_SEND); + WOLFSSL_ENTER("SendClientKeyExchange"); + +#ifdef OPENSSL_EXTRA + ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE; + ssl->cbmode = SSL_CB_MODE_WRITE; + if (ssl->CBIS != NULL) + ssl->CBIS(ssl, SSL_CB_CONNECT_LOOP, SSL_SUCCESS); +#endif + +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); + if (ret != WC_NOT_PENDING_E) { + /* Check for error */ + if (ret < 0) + goto exit_scke; + } + else +#endif + { + /* Reset state */ + ret = 0; + ssl->options.asyncState = TLS_ASYNC_BEGIN; + XMEMSET(args, 0, sizeof(SckeArgs)); + #ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = FreeSckeArgs; + #endif + } + + switch(ssl->options.asyncState) + { + case TLS_ASYNC_BEGIN: + { + switch (ssl->specs.kea) { + #ifndef NO_RSA + case rsa_kea: + if (ssl->peerRsaKey == NULL || + ssl->peerRsaKeyPresent == 0) { + ERROR_OUT(NO_PEER_KEY, exit_scke); + } + break; + #endif + #ifndef NO_DH + case diffie_hellman_kea: + if (ssl->buffers.serverDH_P.buffer == NULL || + ssl->buffers.serverDH_G.buffer == NULL || + ssl->buffers.serverDH_Pub.buffer == NULL) { + ERROR_OUT(NO_PEER_KEY, exit_scke); + } + break; + #endif /* NO_DH */ + #ifndef NO_PSK + case psk_kea: + /* sanity check that PSK client callback has been set */ + if (ssl->options.client_psk_cb == NULL) { + WOLFSSL_MSG("No client PSK callback set"); + ERROR_OUT(PSK_KEY_ERROR, exit_scke); + } + break; + #endif /* NO_PSK */ + #if !defined(NO_DH) && !defined(NO_PSK) + case dhe_psk_kea: + if (ssl->buffers.serverDH_P.buffer == NULL || + ssl->buffers.serverDH_G.buffer == NULL || + ssl->buffers.serverDH_Pub.buffer == NULL) { + ERROR_OUT(NO_PEER_KEY, exit_scke); + } + + /* sanity check that PSK client callback has been set */ + if (ssl->options.client_psk_cb == NULL) { + WOLFSSL_MSG("No client PSK callback set"); + ERROR_OUT(PSK_KEY_ERROR, exit_scke); + } + break; + #endif /* !NO_DH && !NO_PSK */ + #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \ + !defined(NO_PSK) + case ecdhe_psk_kea: + /* sanity check that PSK client callback has been set */ + if (ssl->options.client_psk_cb == NULL) { + WOLFSSL_MSG("No client PSK callback set"); + ERROR_OUT(PSK_KEY_ERROR, exit_scke); + } + + #ifdef HAVE_CURVE25519 + if (ssl->peerX25519KeyPresent) { + /* Check client ECC public key */ + if (!ssl->peerX25519Key || !ssl->peerX25519Key->dp) { + ERROR_OUT(NO_PEER_KEY, exit_scke); + } + + #ifdef HAVE_PK_CALLBACKS + /* if callback then use it for shared secret */ + if (ssl->ctx->X25519SharedSecretCb != NULL) { + break; + } + #endif + + /* create private key */ + ssl->hsType = DYNAMIC_TYPE_CURVE25519; + ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); + if (ret != 0) { + goto exit_scke; + } + + ret = X25519MakeKey(ssl, (curve25519_key*)ssl->hsKey, + ssl->peerX25519Key); + break; + } + #endif + /* Check client ECC public key */ + if (!ssl->peerEccKey || !ssl->peerEccKeyPresent || + !ssl->peerEccKey->dp) { + ERROR_OUT(NO_PEER_KEY, exit_scke); + } + + #ifdef HAVE_PK_CALLBACKS + /* if callback then use it for shared secret */ + if (ssl->ctx->EccSharedSecretCb != NULL) { + break; + } + #endif + + /* create ephemeral private key */ + ssl->hsType = DYNAMIC_TYPE_ECC; + ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); + if (ret != 0) { + goto exit_scke; + } + + ret = EccMakeKey(ssl, (ecc_key*)ssl->hsKey, ssl->peerEccKey); + + break; + #endif /* (HAVE_ECC || HAVE_CURVE25519) && !NO_PSK */ + #ifdef HAVE_NTRU + case ntru_kea: + if (ssl->peerNtruKeyPresent == 0) { + ERROR_OUT(NO_PEER_KEY, exit_scke); + } + break; + #endif /* HAVE_NTRU */ + #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) + case ecc_diffie_hellman_kea: + { + #ifdef HAVE_ECC + ecc_key* peerKey; + #endif + + #ifdef HAVE_PK_CALLBACKS + /* if callback then use it for shared secret */ + #ifdef HAVE_CURVE25519 + if (ssl->ecdhCurveOID == ECC_X25519_OID) { + if (ssl->ctx->X25519SharedSecretCb != NULL) + break; + } + else + #endif + if (ssl->ctx->EccSharedSecretCb != NULL) { + break; + } + #endif /* HAVE_PK_CALLBACKS */ + + #ifdef HAVE_CURVE25519 + if (ssl->peerX25519KeyPresent) { + if (!ssl->peerX25519Key || !ssl->peerX25519Key->dp) { + ERROR_OUT(NO_PEER_KEY, exit_scke); + } + + /* create private key */ + ssl->hsType = DYNAMIC_TYPE_CURVE25519; + ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); + if (ret != 0) { + goto exit_scke; + } + + ret = X25519MakeKey(ssl, (curve25519_key*)ssl->hsKey, + ssl->peerX25519Key); + break; + } + #endif + #ifdef HAVE_ECC + if (ssl->specs.static_ecdh) { + /* Note: EccDsa is really fixed Ecc key here */ + if (!ssl->peerEccDsaKey || !ssl->peerEccDsaKeyPresent || + !ssl->peerEccDsaKey->dp) { + ERROR_OUT(NO_PEER_KEY, exit_scke); + } + peerKey = ssl->peerEccDsaKey; + } + else { + if (!ssl->peerEccKey || !ssl->peerEccKeyPresent || + !ssl->peerEccKey->dp) { + ERROR_OUT(NO_PEER_KEY, exit_scke); + } + peerKey = ssl->peerEccKey; + } + if (peerKey == NULL) { + ERROR_OUT(NO_PEER_KEY, exit_scke); + } + + /* create ephemeral private key */ + ssl->hsType = DYNAMIC_TYPE_ECC; + ret = AllocKey(ssl, ssl->hsType, &ssl->hsKey); + if (ret != 0) { + goto exit_scke; + } + + ret = EccMakeKey(ssl, (ecc_key*)ssl->hsKey, peerKey); + #endif + + break; + } + #endif /* HAVE_ECC || HAVE_CURVE25519 */ + + default: + ret = BAD_KEA_TYPE_E; + } /* switch(ssl->specs.kea) */ + + /* Check for error */ + if (ret != 0) { + goto exit_scke; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_BUILD; + } /* case TLS_ASYNC_BEGIN */ + FALL_THROUGH; + + case TLS_ASYNC_BUILD: + { + args->encSz = MAX_ENCRYPT_SZ; + args->encSecret = (byte*)XMALLOC(args->encSz, ssl->heap, + DYNAMIC_TYPE_SECRET); + if (args->encSecret == NULL) { + ERROR_OUT(MEMORY_E, exit_scke); + } + if (ssl->arrays->preMasterSecret == NULL) { + ssl->arrays->preMasterSz = ENCRYPT_LEN; + ssl->arrays->preMasterSecret = (byte*)XMALLOC(ENCRYPT_LEN, + ssl->heap, DYNAMIC_TYPE_SECRET); + if (ssl->arrays->preMasterSecret == NULL) { + ERROR_OUT(MEMORY_E, exit_scke); + } + XMEMSET(ssl->arrays->preMasterSecret, 0, ENCRYPT_LEN); + } + + switch(ssl->specs.kea) + { + #ifndef NO_RSA + case rsa_kea: + { + /* build PreMasterSecret with RNG data */ + ret = wc_RNG_GenerateBlock(ssl->rng, + &ssl->arrays->preMasterSecret[VERSION_SZ], + SECRET_LEN - VERSION_SZ); + if (ret != 0) { + goto exit_scke; + } + + ssl->arrays->preMasterSecret[0] = ssl->chVersion.major; + ssl->arrays->preMasterSecret[1] = ssl->chVersion.minor; + ssl->arrays->preMasterSz = SECRET_LEN; + break; + } + #endif /* !NO_RSA */ + #ifndef NO_DH + case diffie_hellman_kea: + { + ssl->buffers.sig.length = ENCRYPT_LEN; + ssl->buffers.sig.buffer = (byte*)XMALLOC(ENCRYPT_LEN, + ssl->heap, DYNAMIC_TYPE_SIGNATURE); + if (ssl->buffers.sig.buffer == NULL) { + ERROR_OUT(MEMORY_E, exit_scke); + } + + ret = AllocKey(ssl, DYNAMIC_TYPE_DH, + (void**)&ssl->buffers.serverDH_Key); + if (ret != 0) { + goto exit_scke; + } + + #if !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) && \ + !defined(WOLFSSL_OLD_PRIME_CHECK) + if (ssl->options.dhDoKeyTest && + !ssl->options.dhKeyTested) + { + ret = wc_DhSetCheckKey(ssl->buffers.serverDH_Key, + ssl->buffers.serverDH_P.buffer, + ssl->buffers.serverDH_P.length, + ssl->buffers.serverDH_G.buffer, + ssl->buffers.serverDH_G.length, + NULL, 0, 0, ssl->rng); + if (ret != 0) { + goto exit_scke; + } + ssl->options.dhKeyTested = 1; + } + else + #endif + { + ret = wc_DhSetKey(ssl->buffers.serverDH_Key, + ssl->buffers.serverDH_P.buffer, + ssl->buffers.serverDH_P.length, + ssl->buffers.serverDH_G.buffer, + ssl->buffers.serverDH_G.length); + if (ret != 0) { + goto exit_scke; + } + } + + /* for DH, encSecret is Yc, agree is pre-master */ + ret = DhGenKeyPair(ssl, ssl->buffers.serverDH_Key, + ssl->buffers.sig.buffer, (word32*)&ssl->buffers.sig.length, + args->encSecret, &args->encSz); + + /* set the max agree result size */ + ssl->arrays->preMasterSz = ENCRYPT_LEN; + break; + } + #endif /* !NO_DH */ + #ifndef NO_PSK + case psk_kea: + { + byte* pms = ssl->arrays->preMasterSecret; + ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl, + ssl->arrays->server_hint, ssl->arrays->client_identity, + MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN); + if (ssl->arrays->psk_keySz == 0 || + ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) { + ERROR_OUT(PSK_KEY_ERROR, exit_scke); + } + ssl->arrays->client_identity[MAX_PSK_ID_LEN] = '\0'; /* null term */ + args->encSz = (word32)XSTRLEN(ssl->arrays->client_identity); + if (args->encSz > MAX_PSK_ID_LEN) { + ERROR_OUT(CLIENT_ID_ERROR, exit_scke); + } + XMEMCPY(args->encSecret, ssl->arrays->client_identity, + args->encSz); + + /* make psk pre master secret */ + /* length of key + length 0s + length of key + key */ + c16toa((word16)ssl->arrays->psk_keySz, pms); + pms += OPAQUE16_LEN; + XMEMSET(pms, 0, ssl->arrays->psk_keySz); + pms += ssl->arrays->psk_keySz; + c16toa((word16)ssl->arrays->psk_keySz, pms); + pms += OPAQUE16_LEN; + XMEMCPY(pms, ssl->arrays->psk_key, ssl->arrays->psk_keySz); + ssl->arrays->preMasterSz = (ssl->arrays->psk_keySz * 2) + + (2 * OPAQUE16_LEN); + ForceZero(ssl->arrays->psk_key, ssl->arrays->psk_keySz); + ssl->arrays->psk_keySz = 0; /* No further need */ + break; + } + #endif /* !NO_PSK */ + #if !defined(NO_DH) && !defined(NO_PSK) + case dhe_psk_kea: + { + word32 esSz = 0; + args->output = args->encSecret; + + ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl, + ssl->arrays->server_hint, ssl->arrays->client_identity, + MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN); + if (ssl->arrays->psk_keySz == 0 || + ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) { + ERROR_OUT(PSK_KEY_ERROR, exit_scke); + } + ssl->arrays->client_identity[MAX_PSK_ID_LEN] = '\0'; /* null term */ + esSz = (word32)XSTRLEN(ssl->arrays->client_identity); + + if (esSz > MAX_PSK_ID_LEN) { + ERROR_OUT(CLIENT_ID_ERROR, exit_scke); + } + + ssl->buffers.sig.length = ENCRYPT_LEN; + ssl->buffers.sig.buffer = (byte*)XMALLOC(ENCRYPT_LEN, + ssl->heap, DYNAMIC_TYPE_SIGNATURE); + if (ssl->buffers.sig.buffer == NULL) { + ERROR_OUT(MEMORY_E, exit_scke); + } + + c16toa((word16)esSz, args->output); + args->output += OPAQUE16_LEN; + XMEMCPY(args->output, ssl->arrays->client_identity, esSz); + args->output += esSz; + args->encSz = esSz + OPAQUE16_LEN; + + args->length = 0; + + ret = AllocKey(ssl, DYNAMIC_TYPE_DH, + (void**)&ssl->buffers.serverDH_Key); + if (ret != 0) { + goto exit_scke; + } + + #if !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) && \ + !defined(WOLFSSL_OLD_PRIME_CHECK) + if (ssl->options.dhDoKeyTest && + !ssl->options.dhKeyTested) + { + ret = wc_DhSetCheckKey(ssl->buffers.serverDH_Key, + ssl->buffers.serverDH_P.buffer, + ssl->buffers.serverDH_P.length, + ssl->buffers.serverDH_G.buffer, + ssl->buffers.serverDH_G.length, + NULL, 0, 0, ssl->rng); + if (ret != 0) { + goto exit_scke; + } + ssl->options.dhKeyTested = 1; + } + else + #endif + { + ret = wc_DhSetKey(ssl->buffers.serverDH_Key, + ssl->buffers.serverDH_P.buffer, + ssl->buffers.serverDH_P.length, + ssl->buffers.serverDH_G.buffer, + ssl->buffers.serverDH_G.length); + if (ret != 0) { + goto exit_scke; + } + } + + /* for DH, encSecret is Yc, agree is pre-master */ + ret = DhGenKeyPair(ssl, ssl->buffers.serverDH_Key, + ssl->buffers.sig.buffer, (word32*)&ssl->buffers.sig.length, + args->output + OPAQUE16_LEN, &args->length); + break; + } + #endif /* !NO_DH && !NO_PSK */ + #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \ + !defined(NO_PSK) + case ecdhe_psk_kea: + { + word32 esSz = 0; + args->output = args->encSecret; + + /* Send PSK client identity */ + ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl, + ssl->arrays->server_hint, ssl->arrays->client_identity, + MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN); + if (ssl->arrays->psk_keySz == 0 || + ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) { + ERROR_OUT(PSK_KEY_ERROR, exit_scke); + } + ssl->arrays->client_identity[MAX_PSK_ID_LEN] = '\0'; /* null term */ + esSz = (word32)XSTRLEN(ssl->arrays->client_identity); + if (esSz > MAX_PSK_ID_LEN) { + ERROR_OUT(CLIENT_ID_ERROR, exit_scke); + } + + /* place size and identity in output buffer sz:identity */ + c16toa((word16)esSz, args->output); + args->output += OPAQUE16_LEN; + XMEMCPY(args->output, ssl->arrays->client_identity, esSz); + args->output += esSz; + args->encSz = esSz + OPAQUE16_LEN; + + /* length is used for public key size */ + args->length = MAX_ENCRYPT_SZ; + + /* Create shared ECC key leaving room at the beginning + of buffer for size of shared key. */ + ssl->arrays->preMasterSz = ENCRYPT_LEN - OPAQUE16_LEN; + + #ifdef HAVE_CURVE25519 + if (ssl->ecdhCurveOID == ECC_X25519_OID) { + #ifdef HAVE_PK_CALLBACKS + /* if callback then use it for shared secret */ + if (ssl->ctx->X25519SharedSecretCb != NULL) { + break; + } + #endif + + ret = wc_curve25519_export_public_ex( + (curve25519_key*)ssl->hsKey, + args->output + OPAQUE8_LEN, &args->length, + EC25519_LITTLE_ENDIAN); + if (ret != 0) { + ERROR_OUT(ECC_EXPORT_ERROR, exit_scke); + } + + break; + } + #endif + #ifdef HAVE_PK_CALLBACKS + /* if callback then use it for shared secret */ + if (ssl->ctx->EccSharedSecretCb != NULL) { + break; + } + #endif + + /* Place ECC key in output buffer, leaving room for size */ + ret = wc_ecc_export_x963((ecc_key*)ssl->hsKey, + args->output + OPAQUE8_LEN, &args->length); + if (ret != 0) { + ERROR_OUT(ECC_EXPORT_ERROR, exit_scke); + } + + break; + } + #endif /* (HAVE_ECC || HAVE_CURVE25519) && !NO_PSK */ + #ifdef HAVE_NTRU + case ntru_kea: + { + ret = wc_RNG_GenerateBlock(ssl->rng, + ssl->arrays->preMasterSecret, SECRET_LEN); + if (ret != 0) { + goto exit_scke; + } + + ssl->arrays->preMasterSz = SECRET_LEN; + args->encSz = MAX_ENCRYPT_SZ; + break; + } + #endif /* HAVE_NTRU */ + #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) + case ecc_diffie_hellman_kea: + { + ssl->arrays->preMasterSz = ENCRYPT_LEN; + + #ifdef HAVE_CURVE25519 + if (ssl->hsType == DYNAMIC_TYPE_CURVE25519) { + #ifdef HAVE_PK_CALLBACKS + /* if callback then use it for shared secret */ + if (ssl->ctx->X25519SharedSecretCb != NULL) { + break; + } + #endif + + ret = wc_curve25519_export_public_ex( + (curve25519_key*)ssl->hsKey, + args->encSecret + OPAQUE8_LEN, &args->encSz, + EC25519_LITTLE_ENDIAN); + if (ret != 0) { + ERROR_OUT(ECC_EXPORT_ERROR, exit_scke); + } + + break; + } + #endif + #if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT) + #ifdef HAVE_PK_CALLBACKS + /* if callback then use it for shared secret */ + if (ssl->ctx->EccSharedSecretCb != NULL) { + break; + } + #endif + + /* Place ECC key in buffer, leaving room for size */ + ret = wc_ecc_export_x963((ecc_key*)ssl->hsKey, + args->encSecret + OPAQUE8_LEN, &args->encSz); + if (ret != 0) { + ERROR_OUT(ECC_EXPORT_ERROR, exit_scke); + } + #endif /* HAVE_ECC */ + break; + } + #endif /* HAVE_ECC || HAVE_CURVE25519 */ + + default: + ret = BAD_KEA_TYPE_E; + } /* switch(ssl->specs.kea) */ + + /* Check for error */ + if (ret != 0) { + goto exit_scke; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_DO; + } /* case TLS_ASYNC_BUILD */ + FALL_THROUGH; + + case TLS_ASYNC_DO: + { + switch(ssl->specs.kea) + { + #ifndef NO_RSA + case rsa_kea: + { + ret = RsaEnc(ssl, + ssl->arrays->preMasterSecret, SECRET_LEN, + args->encSecret, &args->encSz, + ssl->peerRsaKey, + #if defined(HAVE_PK_CALLBACKS) + &ssl->buffers.peerRsaKey + #else + NULL + #endif + ); + + break; + } + #endif /* !NO_RSA */ + #ifndef NO_DH + case diffie_hellman_kea: + { + ret = DhAgree(ssl, ssl->buffers.serverDH_Key, + ssl->buffers.sig.buffer, ssl->buffers.sig.length, + ssl->buffers.serverDH_Pub.buffer, + ssl->buffers.serverDH_Pub.length, + ssl->arrays->preMasterSecret, + &ssl->arrays->preMasterSz); + break; + } + #endif /* !NO_DH */ + #ifndef NO_PSK + case psk_kea: + { + break; + } + #endif /* !NO_PSK */ + #if !defined(NO_DH) && !defined(NO_PSK) + case dhe_psk_kea: + { + ret = DhAgree(ssl, ssl->buffers.serverDH_Key, + ssl->buffers.sig.buffer, ssl->buffers.sig.length, + ssl->buffers.serverDH_Pub.buffer, + ssl->buffers.serverDH_Pub.length, + ssl->arrays->preMasterSecret + OPAQUE16_LEN, + &ssl->arrays->preMasterSz); + break; + } + #endif /* !NO_DH && !NO_PSK */ + #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \ + !defined(NO_PSK) + case ecdhe_psk_kea: + { + #ifdef HAVE_CURVE25519 + if (ssl->peerX25519KeyPresent) { + ret = X25519SharedSecret(ssl, + (curve25519_key*)ssl->hsKey, ssl->peerX25519Key, + args->output + OPAQUE8_LEN, &args->length, + ssl->arrays->preMasterSecret + OPAQUE16_LEN, + &ssl->arrays->preMasterSz, + WOLFSSL_CLIENT_END + ); + if (!ssl->specs.static_ecdh + #ifdef WOLFSSL_ASYNC_CRYPT + && ret != WC_PENDING_E + #endif + ) { + FreeKey(ssl, DYNAMIC_TYPE_CURVE25519, + (void**)&ssl->peerX25519Key); + ssl->peerX25519KeyPresent = 0; + } + break; + } + #endif + ret = EccSharedSecret(ssl, + (ecc_key*)ssl->hsKey, ssl->peerEccKey, + args->output + OPAQUE8_LEN, &args->length, + ssl->arrays->preMasterSecret + OPAQUE16_LEN, + &ssl->arrays->preMasterSz, + WOLFSSL_CLIENT_END + ); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret != WC_PENDING_E) + #endif + { + FreeKey(ssl, DYNAMIC_TYPE_ECC, + (void**)&ssl->peerEccKey); + ssl->peerEccKeyPresent = 0; + } + break; + } + #endif /* (HAVE_ECC || HAVE_CURVE25519) && !NO_PSK */ + #ifdef HAVE_NTRU + case ntru_kea: + { + word32 rc; + word16 tmpEncSz = (word16)args->encSz; + DRBG_HANDLE drbg; + + rc = ntru_crypto_drbg_external_instantiate(GetEntropy, &drbg); + if (rc != DRBG_OK) { + ERROR_OUT(NTRU_DRBG_ERROR, exit_scke); + } + rc = ntru_crypto_ntru_encrypt(drbg, ssl->peerNtruKeyLen, + ssl->peerNtruKey, + ssl->arrays->preMasterSz, + ssl->arrays->preMasterSecret, + &tmpEncSz, + args->encSecret); + args->encSz = tmpEncSz; + ntru_crypto_drbg_uninstantiate(drbg); + if (rc != NTRU_OK) { + ERROR_OUT(NTRU_ENCRYPT_ERROR, exit_scke); + } + ret = 0; + break; + } + #endif /* HAVE_NTRU */ + #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) + case ecc_diffie_hellman_kea: + { + #ifdef HAVE_ECC + ecc_key* peerKey; + #endif + + #ifdef HAVE_CURVE25519 + if (ssl->peerX25519KeyPresent) { + ret = X25519SharedSecret(ssl, + (curve25519_key*)ssl->hsKey, ssl->peerX25519Key, + args->encSecret + OPAQUE8_LEN, &args->encSz, + ssl->arrays->preMasterSecret, + &ssl->arrays->preMasterSz, + WOLFSSL_CLIENT_END + ); + if (!ssl->specs.static_ecdh + #ifdef WOLFSSL_ASYNC_CRYPT + && ret != WC_PENDING_E + #endif + ) { + FreeKey(ssl, DYNAMIC_TYPE_CURVE25519, + (void**)&ssl->peerX25519Key); + ssl->peerX25519KeyPresent = 0; + } + break; + } + #endif + #ifdef HAVE_ECC + peerKey = (ssl->specs.static_ecdh) ? + ssl->peerEccDsaKey : ssl->peerEccKey; + + ret = EccSharedSecret(ssl, + (ecc_key*)ssl->hsKey, peerKey, + args->encSecret + OPAQUE8_LEN, &args->encSz, + ssl->arrays->preMasterSecret, + &ssl->arrays->preMasterSz, + WOLFSSL_CLIENT_END + ); + if (!ssl->specs.static_ecdh + #ifdef WOLFSSL_ASYNC_CRYPT + && ret != WC_PENDING_E + #endif + ) { + FreeKey(ssl, DYNAMIC_TYPE_ECC, + (void**)&ssl->peerEccKey); + ssl->peerEccKeyPresent = 0; + } + #endif + + break; + } + #endif /* HAVE_ECC || HAVE_CURVE25519 */ + + default: + ret = BAD_KEA_TYPE_E; + } /* switch(ssl->specs.kea) */ + + /* Check for error */ + if (ret != 0) { + goto exit_scke; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_VERIFY; + } /* case TLS_ASYNC_DO */ + FALL_THROUGH; + + case TLS_ASYNC_VERIFY: + { + switch(ssl->specs.kea) + { + #ifndef NO_RSA + case rsa_kea: + { + break; + } + #endif /* !NO_RSA */ + #ifndef NO_DH + case diffie_hellman_kea: + { + break; + } + #endif /* !NO_DH */ + #ifndef NO_PSK + case psk_kea: + { + break; + } + #endif /* !NO_PSK */ + #if !defined(NO_DH) && !defined(NO_PSK) + case dhe_psk_kea: + { + byte* pms = ssl->arrays->preMasterSecret; + + /* validate args */ + if (args->output == NULL || args->length == 0) { + ERROR_OUT(BAD_FUNC_ARG, exit_scke); + } + + c16toa((word16)args->length, args->output); + args->encSz += args->length + OPAQUE16_LEN; + c16toa((word16)ssl->arrays->preMasterSz, pms); + ssl->arrays->preMasterSz += OPAQUE16_LEN; + pms += ssl->arrays->preMasterSz; + + /* make psk pre master secret */ + /* length of key + length 0s + length of key + key */ + c16toa((word16)ssl->arrays->psk_keySz, pms); + pms += OPAQUE16_LEN; + XMEMCPY(pms, ssl->arrays->psk_key, ssl->arrays->psk_keySz); + ssl->arrays->preMasterSz += + ssl->arrays->psk_keySz + OPAQUE16_LEN; + ForceZero(ssl->arrays->psk_key, ssl->arrays->psk_keySz); + ssl->arrays->psk_keySz = 0; /* No further need */ + break; + } + #endif /* !NO_DH && !NO_PSK */ + #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \ + !defined(NO_PSK) + case ecdhe_psk_kea: + { + byte* pms = ssl->arrays->preMasterSecret; + + /* validate args */ + if (args->output == NULL || args->length > ENCRYPT_LEN) { + ERROR_OUT(BAD_FUNC_ARG, exit_scke); + } + + /* place size of public key in output buffer */ + *args->output = (byte)args->length; + args->encSz += args->length + OPAQUE8_LEN; + + /* Create pre master secret is the concatenation of + eccSize + eccSharedKey + pskSize + pskKey */ + c16toa((word16)ssl->arrays->preMasterSz, pms); + ssl->arrays->preMasterSz += OPAQUE16_LEN; + pms += ssl->arrays->preMasterSz; + + c16toa((word16)ssl->arrays->psk_keySz, pms); + pms += OPAQUE16_LEN; + XMEMCPY(pms, ssl->arrays->psk_key, ssl->arrays->psk_keySz); + ssl->arrays->preMasterSz += + ssl->arrays->psk_keySz + OPAQUE16_LEN; + + ForceZero(ssl->arrays->psk_key, ssl->arrays->psk_keySz); + ssl->arrays->psk_keySz = 0; /* No further need */ + break; + } + #endif /* (HAVE_ECC || HAVE_CURVE25519) && !NO_PSK */ + #ifdef HAVE_NTRU + case ntru_kea: + { + break; + } + #endif /* HAVE_NTRU */ + #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) + case ecc_diffie_hellman_kea: + { + /* place size of public key in buffer */ + *args->encSecret = (byte)args->encSz; + args->encSz += OPAQUE8_LEN; + break; + } + #endif /* HAVE_ECC || HAVE_CURVE25519 */ + + default: + ret = BAD_KEA_TYPE_E; + } /* switch(ssl->specs.kea) */ + + /* Check for error */ + if (ret != 0) { + goto exit_scke; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_FINALIZE; + } /* case TLS_ASYNC_VERIFY */ + FALL_THROUGH; + + case TLS_ASYNC_FINALIZE: + { + word32 tlsSz = 0; + word32 idx = 0; + + #ifdef HAVE_QSH + word32 qshSz = 0; + if (ssl->peerQSHKeyPresent) { + qshSz = QSH_KeyGetSize(ssl); + } + #endif + + if (ssl->options.tls || ssl->specs.kea == diffie_hellman_kea) { + tlsSz = 2; + } + + if (ssl->specs.kea == ecc_diffie_hellman_kea || + ssl->specs.kea == dhe_psk_kea || + ssl->specs.kea == ecdhe_psk_kea) { /* always off */ + tlsSz = 0; + } + + idx = HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; + args->sendSz = args->encSz + tlsSz + idx; + + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + idx += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA; + args->sendSz += DTLS_HANDSHAKE_EXTRA + DTLS_RECORD_EXTRA; + } + #endif + + if (IsEncryptionOn(ssl, 1)) { + args->sendSz += MAX_MSG_EXTRA; + } + + #ifdef HAVE_QSH + args->encSz += qshSz; + args->sendSz += qshSz; + #endif + + /* check for available size */ + if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) { + goto exit_scke; + } + + /* get output buffer */ + args->output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + #ifdef HAVE_QSH + if (ssl->peerQSHKeyPresent) { + byte idxSave = idx; + idx = args->sendSz - qshSz; + + if (QSH_KeyExchangeWrite(ssl, 0) != 0) { + ERROR_OUT(MEMORY_E, exit_scke); + } + + /* extension type */ + c16toa(TLSX_QUANTUM_SAFE_HYBRID, args->output + idx); + idx += OPAQUE16_LEN; + + /* write to output and check amount written */ + if (TLSX_QSHPK_Write(ssl->QSH_secret->list, + args->output + idx) > qshSz - OPAQUE16_LEN) { + ERROR_OUT(MEMORY_E, exit_scke); + } + + idx = idxSave; + } + #endif + + AddHeaders(args->output, args->encSz + tlsSz, client_key_exchange, ssl); + + #ifdef HAVE_QSH + if (ssl->peerQSHKeyPresent) { + args->encSz -= qshSz; + } + #endif + if (tlsSz) { + c16toa((word16)args->encSz, &args->output[idx]); + idx += OPAQUE16_LEN; + } + XMEMCPY(args->output + idx, args->encSecret, args->encSz); + idx += args->encSz; + + if (IsEncryptionOn(ssl, 1)) { + args->inputSz = idx - RECORD_HEADER_SZ; /* buildmsg adds rechdr */ + args->input = (byte*)XMALLOC(args->inputSz, ssl->heap, + DYNAMIC_TYPE_IN_BUFFER); + if (args->input == NULL) { + ERROR_OUT(MEMORY_E, exit_scke); + } + + XMEMCPY(args->input, args->output + RECORD_HEADER_SZ, + args->inputSz); + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_END; + } /* case TLS_ASYNC_FINALIZE */ + FALL_THROUGH; + + case TLS_ASYNC_END: + { + if (IsEncryptionOn(ssl, 1)) { + ret = BuildMessage(ssl, args->output, args->sendSz, + args->input, args->inputSz, handshake, 1, 0, 0); + XFREE(args->input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + args->input = NULL; /* make sure its not double free'd on cleanup */ + + if (ret >= 0) { + args->sendSz = ret; + ret = 0; + } + } + else { + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + DtlsSEQIncrement(ssl, CUR_ORDER); + #endif + ret = HashOutput(ssl, args->output, args->sendSz, 0); + } + + if (ret != 0) { + goto exit_scke; + } + + #ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl)) { + if ((ret = DtlsMsgPoolSave(ssl, args->output, args->sendSz)) != 0) { + goto exit_scke; + } + } + #endif + + #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) + if (ssl->hsInfoOn) + AddPacketName(ssl, "ClientKeyExchange"); + if (ssl->toInfoOn) + AddPacketInfo(ssl, "ClientKeyExchange", handshake, + args->output, args->sendSz, WRITE_PROTO, ssl->heap); + #endif + + ssl->buffers.outputBuffer.length += args->sendSz; + + if (!ssl->options.groupMessages) { + ret = SendBuffered(ssl); + } + if (ret == 0 || ret == WANT_WRITE) { + int tmpRet = MakeMasterSecret(ssl); + if (tmpRet != 0) { + ret = tmpRet; /* save WANT_WRITE unless more serious */ + } + ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE; + } + break; + } + default: + ret = INPUT_CASE_ERROR; + } /* switch(ssl->options.asyncState) */ + +exit_scke: + + WOLFSSL_LEAVE("SendClientKeyExchange", ret); + WOLFSSL_END(WC_FUNC_CLIENT_KEY_EXCHANGE_SEND); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* Handle async operation */ + if (ret == WC_PENDING_E) + return ret; +#endif + + /* No further need for PMS */ + if (ssl->arrays->preMasterSecret != NULL) { + ForceZero(ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz); + } + ssl->arrays->preMasterSz = 0; + + /* Final cleanup */ + FreeSckeArgs(ssl, args); + FreeKeyExchange(ssl); + + return ret; +} + +#endif /* !WOLFSSL_NO_TLS12 */ + +#ifndef NO_CERTS + +#ifdef HAVE_PK_CALLBACKS + int GetPrivateKeySigSize(WOLFSSL* ssl) + { + int sigSz = 0; + + if (ssl == NULL) + return 0; + + switch (ssl->buffers.keyType) { + #ifndef NO_RSA + #ifdef WC_RSA_PSS + case rsa_pss_sa_algo: + #endif + case rsa_sa_algo: + sigSz = ssl->buffers.keySz; + ssl->hsType = DYNAMIC_TYPE_RSA; + break; + #endif + #ifdef HAVE_ECC + case ecc_dsa_sa_algo: + sigSz = wc_ecc_sig_size_calc(ssl->buffers.keySz); + ssl->hsType = DYNAMIC_TYPE_ECC; + break; + #endif + #ifdef HAVE_ED25519 + case ed25519_sa_algo: + sigSz = ED25519_SIG_SIZE; /* fixed known value */ + ssl->hsType = DYNAMIC_TYPE_ED25519; + break; + #endif + default: + break; + } + return sigSz; + } +#endif /* HAVE_PK_CALLBACKS */ + +#ifndef WOLFSSL_NO_TLS12 + +#ifndef WOLFSSL_NO_CLIENT_AUTH +typedef struct ScvArgs { + byte* output; /* not allocated */ +#ifndef NO_RSA + byte* verifySig; +#endif + byte* verify; /* not allocated */ + byte* input; + word32 idx; + word32 extraSz; + word32 sigSz; + int sendSz; + int inputSz; + word16 length; + byte sigAlgo; +} ScvArgs; + +static void FreeScvArgs(WOLFSSL* ssl, void* pArgs) +{ + ScvArgs* args = (ScvArgs*)pArgs; + + (void)ssl; + +#ifndef NO_RSA + if (args->verifySig) { + XFREE(args->verifySig, ssl->heap, DYNAMIC_TYPE_SIGNATURE); + args->verifySig = NULL; + } +#endif + if (args->input) { + XFREE(args->input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + args->input = NULL; + } +} + +/* handle generation of certificate_verify (15) */ +int SendCertificateVerify(WOLFSSL* ssl) +{ + int ret = 0; +#ifdef WOLFSSL_ASYNC_CRYPT + ScvArgs* args = (ScvArgs*)ssl->async.args; + typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1]; + (void)sizeof(args_test); +#else + ScvArgs args[1]; +#endif + + WOLFSSL_START(WC_FUNC_CERTIFICATE_VERIFY_SEND); + WOLFSSL_ENTER("SendCertificateVerify"); + +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); + if (ret != WC_NOT_PENDING_E) { + /* Check for error */ + if (ret < 0) + goto exit_scv; + } + else +#endif + { + /* Reset state */ + ret = 0; + ssl->options.asyncState = TLS_ASYNC_BEGIN; + XMEMSET(args, 0, sizeof(ScvArgs)); + #ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = FreeScvArgs; + #endif + } + + switch(ssl->options.asyncState) + { + case TLS_ASYNC_BEGIN: + { + if (ssl->options.sendVerify == SEND_BLANK_CERT) { + return 0; /* sent blank cert, can't verify */ + } + + args->sendSz = MAX_CERT_VERIFY_SZ + MAX_MSG_EXTRA; + if (IsEncryptionOn(ssl, 1)) { + args->sendSz += MAX_MSG_EXTRA; + } + + /* check for available size */ + if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) { + goto exit_scv; + } + + /* get output buffer */ + args->output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_BUILD; + } /* case TLS_ASYNC_BEGIN */ + FALL_THROUGH; + + case TLS_ASYNC_BUILD: + { + ret = BuildCertHashes(ssl, &ssl->hsHashes->certHashes); + if (ret != 0) { + goto exit_scv; + } + + if (ssl->buffers.key == NULL) { + #ifdef HAVE_PK_CALLBACKS + if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) + args->length = GetPrivateKeySigSize(ssl); + else + #endif + ERROR_OUT(NO_PRIVATE_KEY, exit_scv); + } + else { + /* Decode private key. */ + ret = DecodePrivateKey(ssl, &args->length); + if (ret != 0) { + goto exit_scv; + } + } + + if (args->length <= 0) { + ERROR_OUT(NO_PRIVATE_KEY, exit_scv); + } + + /* idx is used to track verify pointer offset to output */ + args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + args->verify = &args->output[RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ]; + args->extraSz = 0; /* tls 1.2 hash/sig */ + + /* build encoded signature buffer */ + ssl->buffers.sig.length = MAX_ENCODED_SIG_SZ; + ssl->buffers.sig.buffer = (byte*)XMALLOC(ssl->buffers.sig.length, + ssl->heap, DYNAMIC_TYPE_SIGNATURE); + if (ssl->buffers.sig.buffer == NULL) { + ERROR_OUT(MEMORY_E, exit_scv); + } + + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + args->idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + args->verify += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + } + #endif + + #ifndef NO_OLD_TLS + #ifndef NO_SHA + /* old tls default */ + SetDigest(ssl, sha_mac); + #endif + #else + #ifndef NO_SHA256 + /* new tls default */ + SetDigest(ssl, sha256_mac); + #endif + #endif /* !NO_OLD_TLS */ + + if (ssl->hsType == DYNAMIC_TYPE_RSA) { + #ifdef WC_RSA_PSS + if (IsAtLeastTLSv1_2(ssl) && + (ssl->pssAlgo & (1 << ssl->suites->hashAlgo))) { + args->sigAlgo = rsa_pss_sa_algo; + } + else + #endif + args->sigAlgo = rsa_sa_algo; + } + else if (ssl->hsType == DYNAMIC_TYPE_ECC) + args->sigAlgo = ecc_dsa_sa_algo; + else if (ssl->hsType == DYNAMIC_TYPE_ED25519) + args->sigAlgo = ed25519_sa_algo; + + if (IsAtLeastTLSv1_2(ssl)) { + EncodeSigAlg(ssl->suites->hashAlgo, args->sigAlgo, + args->verify); + args->extraSz = HASH_SIG_SIZE; + SetDigest(ssl, ssl->suites->hashAlgo); + } + #ifndef NO_OLD_TLS + else { + /* if old TLS load MD5 and SHA hash as value to sign */ + XMEMCPY(ssl->buffers.sig.buffer, + (byte*)ssl->hsHashes->certHashes.md5, FINISHED_SZ); + } + #endif + + #ifndef NO_RSA + if (args->sigAlgo == rsa_sa_algo) { + ssl->buffers.sig.length = FINISHED_SZ; + args->sigSz = ENCRYPT_LEN; + + if (IsAtLeastTLSv1_2(ssl)) { + ssl->buffers.sig.length = wc_EncodeSignature( + ssl->buffers.sig.buffer, ssl->buffers.digest.buffer, + ssl->buffers.digest.length, + TypeHash(ssl->suites->hashAlgo)); + } + + /* prepend hdr */ + c16toa(args->length, args->verify + args->extraSz); + } + #ifdef WC_RSA_PSS + else if (args->sigAlgo == rsa_pss_sa_algo) { + XMEMCPY(ssl->buffers.sig.buffer, ssl->buffers.digest.buffer, + ssl->buffers.digest.length); + ssl->buffers.sig.length = ssl->buffers.digest.length; + args->sigSz = ENCRYPT_LEN; + + /* prepend hdr */ + c16toa(args->length, args->verify + args->extraSz); + } + #endif + #endif /* !NO_RSA */ + #if defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH) + if (args->sigAlgo == ed25519_sa_algo) { + ret = Ed25519CheckPubKey(ssl); + if (ret != 0) + goto exit_scv; + } + #endif /* HAVE_ED25519 && !NO_ED25519_CLIENT_AUTH */ + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_DO; + } /* case TLS_ASYNC_BUILD */ + FALL_THROUGH; + + case TLS_ASYNC_DO: + { + #ifdef HAVE_ECC + if (ssl->hsType == DYNAMIC_TYPE_ECC) { + ecc_key* key = (ecc_key*)ssl->hsKey; + + ret = EccSign(ssl, + ssl->buffers.digest.buffer, ssl->buffers.digest.length, + ssl->buffers.sig.buffer, (word32*)&ssl->buffers.sig.length, + key, + #ifdef HAVE_PK_CALLBACKS + ssl->buffers.key + #else + NULL + #endif + ); + } + #endif /* HAVE_ECC */ + #if defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH) + if (ssl->hsType == DYNAMIC_TYPE_ED25519) { + ed25519_key* key = (ed25519_key*)ssl->hsKey; + + ret = Ed25519Sign(ssl, + ssl->hsHashes->messages, ssl->hsHashes->length, + ssl->buffers.sig.buffer, (word32*)&ssl->buffers.sig.length, + key, + #ifdef HAVE_PK_CALLBACKS + ssl->buffers.key + #else + NULL + #endif + ); + } + #endif /* HAVE_ED25519 && !NO_ED25519_CLIENT_AUTH */ + #ifndef NO_RSA + if (ssl->hsType == DYNAMIC_TYPE_RSA) { + RsaKey* key = (RsaKey*)ssl->hsKey; + + /* restore verify pointer */ + args->verify = &args->output[args->idx]; + + ret = RsaSign(ssl, + ssl->buffers.sig.buffer, ssl->buffers.sig.length, + args->verify + args->extraSz + VERIFY_HEADER, &args->sigSz, + args->sigAlgo, ssl->suites->hashAlgo, key, + ssl->buffers.key + ); + } + #endif /* !NO_RSA */ + + /* Check for error */ + if (ret != 0) { + goto exit_scv; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_VERIFY; + } /* case TLS_ASYNC_DO */ + FALL_THROUGH; + + case TLS_ASYNC_VERIFY: + { + /* restore verify pointer */ + args->verify = &args->output[args->idx]; + + #ifdef HAVE_ECC + if (ssl->hsType == DYNAMIC_TYPE_ECC) { + args->length = (word16)ssl->buffers.sig.length; + /* prepend hdr */ + c16toa(args->length, args->verify + args->extraSz); + XMEMCPY(args->verify + args->extraSz + VERIFY_HEADER, + ssl->buffers.sig.buffer, ssl->buffers.sig.length); + } + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + if (ssl->hsType == DYNAMIC_TYPE_ED25519) { + args->length = (word16)ssl->buffers.sig.length; + /* prepend hdr */ + c16toa(args->length, args->verify + args->extraSz); + XMEMCPY(args->verify + args->extraSz + VERIFY_HEADER, + ssl->buffers.sig.buffer, ssl->buffers.sig.length); + } + #endif /* HAVE_ED25519 */ + #ifndef NO_RSA + if (ssl->hsType == DYNAMIC_TYPE_RSA) { + RsaKey* key = (RsaKey*)ssl->hsKey; + + if (args->verifySig == NULL) { + args->verifySig = (byte*)XMALLOC(args->sigSz, ssl->heap, + DYNAMIC_TYPE_SIGNATURE); + if (args->verifySig == NULL) { + ERROR_OUT(MEMORY_E, exit_scv); + } + XMEMCPY(args->verifySig, args->verify + args->extraSz + + VERIFY_HEADER, args->sigSz); + } + + /* check for signature faults */ + ret = VerifyRsaSign(ssl, + args->verifySig, args->sigSz, + ssl->buffers.sig.buffer, ssl->buffers.sig.length, + args->sigAlgo, ssl->suites->hashAlgo, key, + ssl->buffers.key + ); + } + #endif /* !NO_RSA */ + + /* Check for error */ + if (ret != 0) { + goto exit_scv; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_FINALIZE; + } /* case TLS_ASYNC_VERIFY */ + FALL_THROUGH; + + case TLS_ASYNC_FINALIZE: + { + if (args->output == NULL) { + ERROR_OUT(BUFFER_ERROR, exit_scv); + } + AddHeaders(args->output, (word32)args->length + args->extraSz + + VERIFY_HEADER, certificate_verify, ssl); + + args->sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + + (word32)args->length + args->extraSz + VERIFY_HEADER; + + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + } + #endif + + if (IsEncryptionOn(ssl, 1)) { + args->inputSz = args->sendSz - RECORD_HEADER_SZ; + /* build msg adds rec hdr */ + args->input = (byte*)XMALLOC(args->inputSz, ssl->heap, + DYNAMIC_TYPE_IN_BUFFER); + if (args->input == NULL) { + ERROR_OUT(MEMORY_E, exit_scv); + } + + XMEMCPY(args->input, args->output + RECORD_HEADER_SZ, + args->inputSz); + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_END; + } /* case TLS_ASYNC_FINALIZE */ + FALL_THROUGH; + + case TLS_ASYNC_END: + { + if (IsEncryptionOn(ssl, 1)) { + ret = BuildMessage(ssl, args->output, + MAX_CERT_VERIFY_SZ + MAX_MSG_EXTRA, + args->input, args->inputSz, handshake, + 1, 0, 1); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) + goto exit_scv; + #endif + + XFREE(args->input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + args->input = NULL; /* make sure its not double free'd on cleanup */ + + if (ret >= 0) { + args->sendSz = ret; + ret = 0; + } + } + else { + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + DtlsSEQIncrement(ssl, CUR_ORDER); + #endif + ret = HashOutput(ssl, args->output, args->sendSz, 0); + } + + if (ret != 0) { + goto exit_scv; + } + + #ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl)) { + ret = DtlsMsgPoolSave(ssl, args->output, args->sendSz); + } + #endif + + + #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) + if (ssl->hsInfoOn) + AddPacketName(ssl, "CertificateVerify"); + if (ssl->toInfoOn) + AddPacketInfo(ssl, "CertificateVerify", handshake, + args->output, args->sendSz, WRITE_PROTO, ssl->heap); + #endif + + ssl->buffers.outputBuffer.length += args->sendSz; + + if (!ssl->options.groupMessages) { + ret = SendBuffered(ssl); + } + break; + } + default: + ret = INPUT_CASE_ERROR; + } /* switch(ssl->options.asyncState) */ + +exit_scv: + + WOLFSSL_LEAVE("SendCertificateVerify", ret); + WOLFSSL_END(WC_FUNC_CERTIFICATE_VERIFY_SEND); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* Handle async operation */ + if (ret == WC_PENDING_E) { + return ret; + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + /* Digest is not allocated, so do this to prevent free */ + ssl->buffers.digest.buffer = NULL; + ssl->buffers.digest.length = 0; + + /* Final cleanup */ + FreeScvArgs(ssl, args); + FreeKeyExchange(ssl); + + return ret; +} +#endif /* WOLFSSL_NO_CLIENT_AUTH */ + +#endif /* WOLFSSL_NO_TLS12 */ + +#endif /* NO_CERTS */ + + +#ifdef HAVE_SESSION_TICKET +int SetTicket(WOLFSSL* ssl, const byte* ticket, word32 length) +{ + /* Free old dynamic ticket if we already had one */ + if (ssl->session.isDynamic) { + XFREE(ssl->session.ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); + ssl->session.ticket = ssl->session.staticTicket; + ssl->session.isDynamic = 0; + } + + if (length > sizeof(ssl->session.staticTicket)) { + byte* sessionTicket = + (byte*)XMALLOC(length, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); + if (sessionTicket == NULL) + return MEMORY_E; + ssl->session.ticket = sessionTicket; + ssl->session.isDynamic = 1; + } + ssl->session.ticketLen = (word16)length; + + if (length > 0) { + XMEMCPY(ssl->session.ticket, ticket, length); + if (ssl->session_ticket_cb != NULL) { + ssl->session_ticket_cb(ssl, + ssl->session.ticket, ssl->session.ticketLen, + ssl->session_ticket_ctx); + } + /* Create a fake sessionID based on the ticket, this will + * supercede the existing session cache info. */ + ssl->options.haveSessionId = 1; +#ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) { + XMEMCPY(ssl->session.sessionID, + ssl->session.ticket + length - ID_LEN, ID_LEN); + } + else +#endif + XMEMCPY(ssl->arrays->sessionID, + ssl->session.ticket + length - ID_LEN, ID_LEN); + } + + return 0; +} + +#ifndef WOLFSSL_NO_TLS12 + +/* handle processing of session_ticket (4) */ +static int DoSessionTicket(WOLFSSL* ssl, const byte* input, word32* inOutIdx, + word32 size) +{ + word32 begin = *inOutIdx; + word32 lifetime; + word16 length; + int ret; + + if (ssl->expect_session_ticket == 0) { + WOLFSSL_MSG("Unexpected session ticket"); + return SESSION_TICKET_EXPECT_E; + } + + if ((*inOutIdx - begin) + OPAQUE32_LEN > size) + return BUFFER_ERROR; + + ato32(input + *inOutIdx, &lifetime); + *inOutIdx += OPAQUE32_LEN; + + if ((*inOutIdx - begin) + OPAQUE16_LEN > size) + return BUFFER_ERROR; + + ato16(input + *inOutIdx, &length); + *inOutIdx += OPAQUE16_LEN; + + if ((*inOutIdx - begin) + length > size) + return BUFFER_ERROR; + + if ((ret = SetTicket(ssl, input + *inOutIdx, length)) != 0) + return ret; + *inOutIdx += length; + if (length > 0) { + ssl->timeout = lifetime; +#ifndef NO_SESSION_CACHE + AddSession(ssl); +#endif + } + + if (IsEncryptionOn(ssl, 0)) { + *inOutIdx += ssl->keys.padSz; + } + + ssl->expect_session_ticket = 0; + + return 0; +} + +#endif /* !WOLFSSL_NO_TLS12 */ + +#endif /* HAVE_SESSION_TICKET */ + +#endif /* NO_WOLFSSL_CLIENT */ + +#ifndef NO_WOLFSSL_SERVER + +#ifndef WOLFSSL_NO_TLS12 + + /* handle generation of server_hello (2) */ + int SendServerHello(WOLFSSL* ssl) + { + int ret; + byte *output; + word16 length; + word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + int sendSz; + byte sessIdSz = ID_LEN; + byte echoId = 0; /* ticket echo id flag */ + byte cacheOff = 0; /* session cache off flag */ + + WOLFSSL_START(WC_FUNC_SERVER_HELLO_SEND); + WOLFSSL_ENTER("SendServerHello"); + + length = VERSION_SZ + RAN_LEN + + ID_LEN + ENUM_LEN + + SUITE_LEN + + ENUM_LEN; + +#ifdef HAVE_TLS_EXTENSIONS + ret = TLSX_GetResponseSize(ssl, server_hello, &length); + if (ret != 0) + return ret; + #ifdef HAVE_SESSION_TICKET + if (ssl->options.useTicket) { + /* echo session id sz can be 0,32 or bogus len in between */ + sessIdSz = ssl->arrays->sessionIDSz; + if (sessIdSz > ID_LEN) { + WOLFSSL_MSG("Bad bogus session id len"); + return BUFFER_ERROR; + } + if (!IsAtLeastTLSv1_3(ssl->version)) + length -= (ID_LEN - sessIdSz); /* adjust ID_LEN assumption */ + echoId = 1; + } + #endif /* HAVE_SESSION_TICKET */ +#else + if (ssl->options.haveEMS) { + length += HELLO_EXT_SZ_SZ + HELLO_EXT_SZ; + } +#endif + + /* is the session cache off at build or runtime */ +#ifdef NO_SESSION_CACHE + cacheOff = 1; +#else + if (ssl->options.sessionCacheOff == 1) { + cacheOff = 1; + } +#endif + + /* if no session cache don't send a session ID unless we're echoing + * an ID as part of session tickets */ + if (echoId == 0 && cacheOff == 1) { + length -= ID_LEN; /* adjust ID_LEN assumption */ + sessIdSz = 0; + } + + sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + /* Server Hello should use the same sequence number as the + * Client Hello. */ + ssl->keys.dtls_sequence_number_hi = ssl->keys.curSeq_hi; + ssl->keys.dtls_sequence_number_lo = ssl->keys.curSeq_lo; + idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + } + #endif /* WOLFSSL_DTLS */ + + if (IsEncryptionOn(ssl, 1)) + sendSz += MAX_MSG_EXTRA; + + /* check for available size */ + if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) + return ret; + + /* get output buffer */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + AddHeaders(output, length, server_hello, ssl); + + /* now write to output */ + /* first version */ + output[idx++] = (byte)ssl->version.major; + output[idx++] = (byte)ssl->version.minor; + + /* then random and session id */ + if (!ssl->options.resuming) { + /* generate random part and session id */ + ret = wc_RNG_GenerateBlock(ssl->rng, output + idx, + RAN_LEN + sizeof(sessIdSz) + sessIdSz); + if (ret != 0) + return ret; + +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->ctx->method->version)) { + /* TLS v1.3 capable server downgraded. */ + XMEMCPY(output + idx + RAN_LEN - (TLS13_DOWNGRADE_SZ + 1), + tls13Downgrade, TLS13_DOWNGRADE_SZ); + output[idx + RAN_LEN - 1] = (byte)IsAtLeastTLSv1_2(ssl); + } + else +#endif + if (ssl->ctx->method->version.major == SSLv3_MAJOR && + ssl->ctx->method->version.minor == TLSv1_2_MINOR && + !IsAtLeastTLSv1_2(ssl)) { + /* TLS v1.2 capable server downgraded. */ + XMEMCPY(output + idx + RAN_LEN - (TLS13_DOWNGRADE_SZ + 1), + tls13Downgrade, TLS13_DOWNGRADE_SZ); + output[idx + RAN_LEN - 1] = 0; + } + + /* store info in SSL for later */ + XMEMCPY(ssl->arrays->serverRandom, output + idx, RAN_LEN); + idx += RAN_LEN; + output[idx++] = sessIdSz; + XMEMCPY(ssl->arrays->sessionID, output + idx, sessIdSz); + ssl->arrays->sessionIDSz = sessIdSz; + } + else { + /* If resuming, use info from SSL */ + XMEMCPY(output + idx, ssl->arrays->serverRandom, RAN_LEN); + idx += RAN_LEN; + output[idx++] = sessIdSz; + XMEMCPY(output + idx, ssl->arrays->sessionID, sessIdSz); + } + idx += sessIdSz; + +#ifdef SHOW_SECRETS + { + int j; + printf("server random: "); + for (j = 0; j < RAN_LEN; j++) + printf("%02x", ssl->arrays->serverRandom[j]); + printf("\n"); + } +#endif + + /* then cipher suite */ + output[idx++] = ssl->options.cipherSuite0; + output[idx++] = ssl->options.cipherSuite; + + /* then compression */ + if (ssl->options.usingCompression) + output[idx++] = ZLIB_COMPRESSION; + else + output[idx++] = NO_COMPRESSION; + + /* last, extensions */ +#ifdef HAVE_TLS_EXTENSIONS + { + word16 offset = 0; + ret = TLSX_WriteResponse(ssl, output + idx, server_hello, &offset); + if (ret != 0) + return ret; + idx += offset; + } +#else +#ifdef HAVE_EXTENDED_MASTER + if (ssl->options.haveEMS) { + c16toa(HELLO_EXT_SZ, output + idx); + idx += HELLO_EXT_SZ_SZ; + + c16toa(HELLO_EXT_EXTMS, output + idx); + idx += HELLO_EXT_TYPE_SZ; + c16toa(0, output + idx); + /*idx += HELLO_EXT_SZ_SZ;*/ + /* idx is not used after this point. uncomment the line above + * if adding any more extensions in the future. */ + } +#endif +#endif + + if (IsEncryptionOn(ssl, 1)) { + byte* input; + int inputSz = idx - RECORD_HEADER_SZ; /* build msg adds rec hdr */ + + input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + if (input == NULL) + return MEMORY_E; + + XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz); + sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, + handshake, 1, 0, 0); + XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + + if (sendSz < 0) + return sendSz; + } else { + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + DtlsSEQIncrement(ssl, CUR_ORDER); + #endif + ret = HashOutput(ssl, output, sendSz, 0); + if (ret != 0) + return ret; + } + + #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) + if (ssl->hsInfoOn) + AddPacketName(ssl, "ServerHello"); + if (ssl->toInfoOn) + AddPacketInfo(ssl, "ServerHello", handshake, output, sendSz, + WRITE_PROTO, ssl->heap); + #endif + + ssl->options.serverState = SERVER_HELLO_COMPLETE; + ssl->buffers.outputBuffer.length += sendSz; + + #ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl)) { + if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) + return ret; + } + + if (ssl->options.dtls) { + DtlsSEQIncrement(ssl, CUR_ORDER); + } + #endif + + if (ssl->options.groupMessages) + ret = 0; + else + ret = SendBuffered(ssl); + + WOLFSSL_LEAVE("SendServerHello", ret); + WOLFSSL_END(WC_FUNC_SERVER_HELLO_SEND); + + return ret; + } + + +#if defined(HAVE_ECC) + + static byte SetCurveId(ecc_key* key) + { + if (key == NULL || key->dp == NULL) { + WOLFSSL_MSG("SetCurveId: Invalid key!"); + return 0; + } + + switch(key->dp->oidSum) { + #if defined(HAVE_ECC160) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case ECC_SECP160R1_OID: + return WOLFSSL_ECC_SECP160R1; + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_SECPR2 + case ECC_SECP160R2_OID: + return WOLFSSL_ECC_SECP160R2; + #endif /* HAVE_ECC_SECPR2 */ + #ifdef HAVE_ECC_KOBLITZ + case ECC_SECP160K1_OID: + return WOLFSSL_ECC_SECP160K1; + #endif /* HAVE_ECC_KOBLITZ */ + #endif + #if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case ECC_SECP192R1_OID: + return WOLFSSL_ECC_SECP192R1; + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_KOBLITZ + case ECC_SECP192K1_OID: + return WOLFSSL_ECC_SECP192K1; + #endif /* HAVE_ECC_KOBLITZ */ + #endif + #if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case ECC_SECP224R1_OID: + return WOLFSSL_ECC_SECP224R1; + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_KOBLITZ + case ECC_SECP224K1_OID: + return WOLFSSL_ECC_SECP224K1; + #endif /* HAVE_ECC_KOBLITZ */ + #endif + #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case ECC_SECP256R1_OID: + return WOLFSSL_ECC_SECP256R1; + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_KOBLITZ + case ECC_SECP256K1_OID: + return WOLFSSL_ECC_SECP256K1; + #endif /* HAVE_ECC_KOBLITZ */ + #ifdef HAVE_ECC_BRAINPOOL + case ECC_BRAINPOOLP256R1_OID: + return WOLFSSL_ECC_BRAINPOOLP256R1; + #endif /* HAVE_ECC_BRAINPOOL */ + #endif + #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case ECC_SECP384R1_OID: + return WOLFSSL_ECC_SECP384R1; + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_BRAINPOOL + case ECC_BRAINPOOLP384R1_OID: + return WOLFSSL_ECC_BRAINPOOLP384R1; + #endif /* HAVE_ECC_BRAINPOOL */ + #endif + #if defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES) + #ifdef HAVE_ECC_BRAINPOOL + case ECC_BRAINPOOLP512R1_OID: + return WOLFSSL_ECC_BRAINPOOLP512R1; + #endif /* HAVE_ECC_BRAINPOOL */ + #endif + #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case ECC_SECP521R1_OID: + return WOLFSSL_ECC_SECP521R1; + #endif /* !NO_ECC_SECP */ + #endif + default: + return 0; + } + } + +#endif /* HAVE_ECC || HAVE_CURVE25519 */ + + typedef struct SskeArgs { + byte* output; /* not allocated */ + #if defined(HAVE_ECC) || defined(HAVE_ED25519) || \ + (!defined(NO_DH) && !defined(NO_RSA)) + byte* sigDataBuf; + #endif + #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) + byte* exportBuf; + #endif + #ifndef NO_RSA + byte* verifySig; + #endif + byte* input; + word32 idx; + word32 tmpSigSz; + word32 length; + word32 sigSz; + #if defined(HAVE_ECC) || defined(HAVE_ED25519) || \ + (!defined(NO_DH) && !defined(NO_RSA)) + word32 sigDataSz; + #endif + #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) + word32 exportSz; + #endif + #ifdef HAVE_QSH + word32 qshSz; + #endif + int sendSz; + int inputSz; + } SskeArgs; + + static void FreeSskeArgs(WOLFSSL* ssl, void* pArgs) + { + SskeArgs* args = (SskeArgs*)pArgs; + + (void)ssl; + + #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) + if (args->exportBuf) { + XFREE(args->exportBuf, ssl->heap, DYNAMIC_TYPE_DER); + args->exportBuf = NULL; + } + #endif + #if defined(HAVE_ECC) || defined(HAVE_ED25519) || \ + (!defined(NO_DH) && !defined(NO_RSA)) + if (args->sigDataBuf) { + XFREE(args->sigDataBuf, ssl->heap, DYNAMIC_TYPE_SIGNATURE); + args->sigDataBuf = NULL; + } + #endif + #ifndef NO_RSA + if (args->verifySig) { + XFREE(args->verifySig, ssl->heap, DYNAMIC_TYPE_SIGNATURE); + args->verifySig = NULL; + } + #endif + (void)args; + } + + /* handle generation of server_key_exchange (12) */ + int SendServerKeyExchange(WOLFSSL* ssl) + { + int ret; + #ifdef WOLFSSL_ASYNC_CRYPT + SskeArgs* args = (SskeArgs*)ssl->async.args; + typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1]; + (void)sizeof(args_test); + #else + SskeArgs args[1]; + #endif + + WOLFSSL_START(WC_FUNC_SERVER_KEY_EXCHANGE_SEND); + WOLFSSL_ENTER("SendServerKeyExchange"); + + #ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); + if (ret != WC_NOT_PENDING_E) { + /* Check for error */ + if (ret < 0) + goto exit_sske; + } + else + #endif + { + /* Reset state */ + ret = 0; + ssl->options.asyncState = TLS_ASYNC_BEGIN; + XMEMSET(args, 0, sizeof(SskeArgs)); + #ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = FreeSskeArgs; + #endif + } + + switch(ssl->options.asyncState) + { + case TLS_ASYNC_BEGIN: + { + #ifdef HAVE_QSH + if (ssl->peerQSHKeyPresent && ssl->options.haveQSH) { + args->qshSz = QSH_KeyGetSize(ssl); + } + #endif + + /* Do some checks / debug msgs */ + switch(ssl->specs.kea) + { + #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \ + !defined(NO_PSK) + case ecdhe_psk_kea: + { + WOLFSSL_MSG("Using ephemeral ECDH PSK"); + break; + } + #endif /* (HAVE_ECC || CURVE25519) && !NO_PSK */ + #if defined(HAVE_ECC) + case ecc_diffie_hellman_kea: + { + if (ssl->specs.static_ecdh) { + WOLFSSL_MSG("Using Static ECDH, not sending ServerKeyExchange"); + ERROR_OUT(0, exit_sske); + } + + WOLFSSL_MSG("Using ephemeral ECDH"); + break; + } + #endif /* HAVE_ECC */ + } + + /* Preparing keys */ + switch(ssl->specs.kea) + { + #ifndef NO_PSK + case psk_kea: + { + /* Nothing to do in this sub-state */ + break; + } + #endif /* !NO_PSK */ + #if !defined(NO_DH) && (!defined(NO_PSK) || !defined(NO_RSA)) + #if !defined(NO_PSK) + case dhe_psk_kea: + #endif + #if !defined(NO_RSA) + case diffie_hellman_kea: + #endif + { + /* Allocate DH key buffers and generate key */ + if (ssl->buffers.serverDH_P.buffer == NULL || + ssl->buffers.serverDH_G.buffer == NULL) { + ERROR_OUT(NO_DH_PARAMS, exit_sske); + } + + if (ssl->buffers.serverDH_Pub.buffer == NULL) { + /* Free'd in SSL_ResourceFree and FreeHandshakeResources */ + ssl->buffers.serverDH_Pub.buffer = (byte*)XMALLOC( + ssl->buffers.serverDH_P.length + OPAQUE16_LEN, + ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + if (ssl->buffers.serverDH_Pub.buffer == NULL) { + ERROR_OUT(MEMORY_E, exit_sske); + } + } + + if (ssl->buffers.serverDH_Priv.buffer == NULL) { + /* Free'd in SSL_ResourceFree and FreeHandshakeResources */ + ssl->buffers.serverDH_Priv.buffer = (byte*)XMALLOC( + ssl->buffers.serverDH_P.length + OPAQUE16_LEN, + ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + if (ssl->buffers.serverDH_Priv.buffer == NULL) { + ERROR_OUT(MEMORY_E, exit_sske); + } + } + + ssl->options.dhKeySz = + (word16)ssl->buffers.serverDH_P.length; + + ret = AllocKey(ssl, DYNAMIC_TYPE_DH, + (void**)&ssl->buffers.serverDH_Key); + if (ret != 0) { + goto exit_sske; + } + + #if !defined(WOLFSSL_OLD_PRIME_CHECK) && \ + !defined(HAVE_FIPS) && \ + !defined(HAVE_SELFTEST) + if (ssl->options.dhDoKeyTest && + !ssl->options.dhKeyTested) + { + ret = wc_DhSetCheckKey( + ssl->buffers.serverDH_Key, + ssl->buffers.serverDH_P.buffer, + ssl->buffers.serverDH_P.length, + ssl->buffers.serverDH_G.buffer, + ssl->buffers.serverDH_G.length, + NULL, 0, 0, ssl->rng); + if (ret != 0) { + goto exit_sske; + } + ssl->options.dhKeyTested = 1; + } + else + #endif + { + ret = wc_DhSetKey(ssl->buffers.serverDH_Key, + ssl->buffers.serverDH_P.buffer, + ssl->buffers.serverDH_P.length, + ssl->buffers.serverDH_G.buffer, + ssl->buffers.serverDH_G.length); + if (ret != 0) { + goto exit_sske; + } + } + + ret = DhGenKeyPair(ssl, ssl->buffers.serverDH_Key, + ssl->buffers.serverDH_Priv.buffer, + (word32*)&ssl->buffers.serverDH_Priv.length, + ssl->buffers.serverDH_Pub.buffer, + (word32*)&ssl->buffers.serverDH_Pub.length); + break; + } + #endif /* !NO_DH && (!NO_PSK || !NO_RSA) */ + #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \ + !defined(NO_PSK) + case ecdhe_psk_kea: + /* Fall through to create temp ECC key */ + #endif /* (HAVE_ECC || CURVE25519) && !NO_PSK */ + #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) + case ecc_diffie_hellman_kea: + { + #ifdef HAVE_CURVE25519 + if (ssl->ecdhCurveOID == ECC_X25519_OID) { + /* need ephemeral key now, create it if missing */ + if (ssl->eccTempKey == NULL) { + /* alloc/init on demand */ + ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE25519, + (void**)&ssl->eccTempKey); + if (ret != 0) { + goto exit_sske; + } + } + + if (ssl->eccTempKeyPresent == 0) { + ret = X25519MakeKey(ssl, + (curve25519_key*)ssl->eccTempKey, NULL); + if (ret == 0 || ret == WC_PENDING_E) { + ssl->eccTempKeyPresent = + DYNAMIC_TYPE_CURVE25519; + } + } + break; + } + #endif + #ifdef HAVE_ECC + /* need ephemeral key now, create it if missing */ + if (ssl->eccTempKey == NULL) { + /* alloc/init on demand */ + ret = AllocKey(ssl, DYNAMIC_TYPE_ECC, + (void**)&ssl->eccTempKey); + if (ret != 0) { + goto exit_sske; + } + } + + if (ssl->eccTempKeyPresent == 0) { + ret = EccMakeKey(ssl, ssl->eccTempKey, NULL); + if (ret == 0 || ret == WC_PENDING_E) { + ssl->eccTempKeyPresent = DYNAMIC_TYPE_ECC; + } + } + #endif + break; + } + #endif /* HAVE_ECC || HAVE_CURVE25519 */ + default: + /* Skip ServerKeyExchange */ + goto exit_sske; + } /* switch(ssl->specs.kea) */ + + /* Check for error */ + if (ret != 0) { + goto exit_sske; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_BUILD; + } /* case TLS_ASYNC_BEGIN */ + FALL_THROUGH; + + case TLS_ASYNC_BUILD: + { + #if (!defined(NO_DH) && !defined(NO_RSA)) || (defined(HAVE_ECC) || \ + defined(HAVE_CURVE25519)) + word32 preSigSz, preSigIdx; + #endif + + switch(ssl->specs.kea) + { + #ifndef NO_PSK + case psk_kea: + { + args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + + if (ssl->arrays->server_hint[0] == 0) { + ERROR_OUT(0, exit_sske); /* don't send */ + } + + /* include size part */ + args->length = (word32)XSTRLEN(ssl->arrays->server_hint); + if (args->length > MAX_PSK_ID_LEN) { + ERROR_OUT(SERVER_HINT_ERROR, exit_sske); + } + + args->length += HINT_LEN_SZ; + args->sendSz = args->length + HANDSHAKE_HEADER_SZ + + RECORD_HEADER_SZ; + + #ifdef HAVE_QSH + args->length += args->qshSz; + args->sendSz += args->qshSz; + #endif + + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + args->idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + } + #endif + + if (IsEncryptionOn(ssl, 1)) { + args->sendSz += MAX_MSG_EXTRA; + } + + /* check for available size */ + if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) { + goto exit_sske; + } + + /* get ouput buffer */ + args->output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + AddHeaders(args->output, args->length, + server_key_exchange, ssl); + + /* key data */ + #ifdef HAVE_QSH + c16toa((word16)(args->length - args->qshSz - + HINT_LEN_SZ), args->output + args->idx); + #else + c16toa((word16)(args->length - HINT_LEN_SZ), + args->output + args->idx); + #endif + + args->idx += HINT_LEN_SZ; + XMEMCPY(args->output + args->idx, + ssl->arrays->server_hint, + args->length - HINT_LEN_SZ); + break; + } + #endif /* !NO_PSK */ + #if !defined(NO_DH) && !defined(NO_PSK) + case dhe_psk_kea: + { + word32 hintLen; + + args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + args->length = LENGTH_SZ * 3 + /* p, g, pub */ + ssl->buffers.serverDH_P.length + + ssl->buffers.serverDH_G.length + + ssl->buffers.serverDH_Pub.length; + + /* include size part */ + hintLen = (word32)XSTRLEN(ssl->arrays->server_hint); + if (hintLen > MAX_PSK_ID_LEN) { + ERROR_OUT(SERVER_HINT_ERROR, exit_sske); + } + args->length += hintLen + HINT_LEN_SZ; + args->sendSz = args->length + HANDSHAKE_HEADER_SZ + + RECORD_HEADER_SZ; + + #ifdef HAVE_QSH + args->length += args->qshSz; + args->sendSz += args->qshSz; + #endif + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + args->idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + } + #endif + + if (IsEncryptionOn(ssl, 1)) { + args->sendSz += MAX_MSG_EXTRA; + } + + /* check for available size */ + if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) { + goto exit_sske; + } + + /* get ouput buffer */ + args->output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + AddHeaders(args->output, args->length, + server_key_exchange, ssl); + + /* key data */ + c16toa((word16)hintLen, args->output + args->idx); + args->idx += HINT_LEN_SZ; + XMEMCPY(args->output + args->idx, + ssl->arrays->server_hint, hintLen); + args->idx += hintLen; + + /* add p, g, pub */ + c16toa((word16)ssl->buffers.serverDH_P.length, + args->output + args->idx); + args->idx += LENGTH_SZ; + XMEMCPY(args->output + args->idx, + ssl->buffers.serverDH_P.buffer, + ssl->buffers.serverDH_P.length); + args->idx += ssl->buffers.serverDH_P.length; + + /* g */ + c16toa((word16)ssl->buffers.serverDH_G.length, + args->output + args->idx); + args->idx += LENGTH_SZ; + XMEMCPY(args->output + args->idx, + ssl->buffers.serverDH_G.buffer, + ssl->buffers.serverDH_G.length); + args->idx += ssl->buffers.serverDH_G.length; + + /* pub */ + c16toa((word16)ssl->buffers.serverDH_Pub.length, + args->output + args->idx); + args->idx += LENGTH_SZ; + XMEMCPY(args->output + args->idx, + ssl->buffers.serverDH_Pub.buffer, + ssl->buffers.serverDH_Pub.length); + /* No need to update idx, since sizes are already set */ + /* args->idx += ssl->buffers.serverDH_Pub.length; */ + break; + } + #endif /* !defined(NO_DH) && !defined(NO_PSK) */ + #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \ + !defined(NO_PSK) + case ecdhe_psk_kea: + { + word32 hintLen; + + /* curve type, named curve, length(1) */ + args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + args->length = ENUM_LEN + CURVE_LEN + ENUM_LEN; + + args->exportSz = MAX_EXPORT_ECC_SZ; + args->exportBuf = (byte*)XMALLOC(args->exportSz, + ssl->heap, DYNAMIC_TYPE_DER); + if (args->exportBuf == NULL) { + ERROR_OUT(MEMORY_E, exit_sske); + } + #ifdef HAVE_CURVE25519 + if (ssl->ecdhCurveOID == ECC_X25519_OID) { + if (wc_curve25519_export_public_ex( + (curve25519_key*)ssl->eccTempKey, + args->exportBuf, &args->exportSz, + EC25519_LITTLE_ENDIAN) != 0) { + ERROR_OUT(ECC_EXPORT_ERROR, exit_sske); + } + } + else + #endif + { + if (wc_ecc_export_x963(ssl->eccTempKey, + args->exportBuf, &args->exportSz) != 0) { + ERROR_OUT(ECC_EXPORT_ERROR, exit_sske); + } + } + args->length += args->exportSz; + + /* include size part */ + hintLen = (word32)XSTRLEN(ssl->arrays->server_hint); + if (hintLen > MAX_PSK_ID_LEN) { + ERROR_OUT(SERVER_HINT_ERROR, exit_sske); + } + args->length += hintLen + HINT_LEN_SZ; + args->sendSz = args->length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; + + #ifdef HAVE_QSH + args->length += args->qshSz; + args->sendSz += args->qshSz; + #endif + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + args->idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + } + #endif + + if (IsEncryptionOn(ssl, 1)) { + args->sendSz += MAX_MSG_EXTRA; + } + + /* check for available size */ + if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) { + goto exit_sske; + } + + /* get output buffer */ + args->output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + /* key data */ + c16toa((word16)hintLen, args->output + args->idx); + args->idx += HINT_LEN_SZ; + XMEMCPY(args->output + args->idx, + ssl->arrays->server_hint, hintLen); + args->idx += hintLen; + + /* ECC key exchange data */ + args->output[args->idx++] = named_curve; + args->output[args->idx++] = 0x00; /* leading zero */ + #ifdef HAVE_CURVE25519 + if (ssl->ecdhCurveOID == ECC_X25519_OID) + args->output[args->idx++] = WOLFSSL_ECC_X25519; + else + #endif + { + #ifdef HAVE_ECC + args->output[args->idx++] = + SetCurveId(ssl->eccTempKey); + #endif + } + args->output[args->idx++] = (byte)args->exportSz; + XMEMCPY(args->output + args->idx, args->exportBuf, + args->exportSz); + break; + } + #endif /* (HAVE_ECC || HAVE_CURVE25519) && !NO_PSK */ + #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) + case ecc_diffie_hellman_kea: + { + enum wc_HashType hashType; + + /* curve type, named curve, length(1) */ + args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + args->length = ENUM_LEN + CURVE_LEN + ENUM_LEN; + + /* Export temp ECC key and add to length */ + args->exportSz = MAX_EXPORT_ECC_SZ; + args->exportBuf = (byte*)XMALLOC(args->exportSz, + ssl->heap, DYNAMIC_TYPE_DER); + if (args->exportBuf == NULL) { + ERROR_OUT(MEMORY_E, exit_sske); + } + #ifdef HAVE_CURVE25519 + if (ssl->ecdhCurveOID == ECC_X25519_OID) { + if (wc_curve25519_export_public_ex( + (curve25519_key*)ssl->eccTempKey, + args->exportBuf, &args->exportSz, + EC25519_LITTLE_ENDIAN) != 0) { + ERROR_OUT(ECC_EXPORT_ERROR, exit_sske); + } + } + else + #endif + { + #if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT) + if (wc_ecc_export_x963(ssl->eccTempKey, + args->exportBuf, &args->exportSz) != 0) { + ERROR_OUT(ECC_EXPORT_ERROR, exit_sske); + } + #endif + } + args->length += args->exportSz; + + preSigSz = args->length; + preSigIdx = args->idx; + + if (ssl->buffers.key == NULL) { + #ifdef HAVE_PK_CALLBACKS + if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) { + args->tmpSigSz = GetPrivateKeySigSize(ssl); + if (args->tmpSigSz <= 0) { + ERROR_OUT(NO_PRIVATE_KEY, exit_sske); + } + } + else + #endif + ERROR_OUT(NO_PRIVATE_KEY, exit_sske); + } + else { + switch(ssl->suites->sigAlgo) { + #ifndef NO_RSA + #ifdef WC_RSA_PSS + case rsa_pss_sa_algo: + #endif + case rsa_sa_algo: + { + word16 keySz; + + ssl->buffers.keyType = rsa_sa_algo; + ret = DecodePrivateKey(ssl, &keySz); + if (ret != 0) { + goto exit_sske; + } + + args->tmpSigSz = (word32)keySz; + break; + } + #endif /* !NO_RSA */ + #ifdef HAVE_ECC + case ecc_dsa_sa_algo: + { + word16 keySz; + + ssl->buffers.keyType = ecc_dsa_sa_algo; + ret = DecodePrivateKey(ssl, &keySz); + if (ret != 0) { + goto exit_sske; + } + /* worst case estimate */ + args->tmpSigSz = keySz; + break; + } + #endif + #ifdef HAVE_ED25519 + case ed25519_sa_algo: + { + word16 keySz; + + ssl->buffers.keyType = ed25519_sa_algo; + ret = DecodePrivateKey(ssl, &keySz); + if (ret != 0) { + goto exit_sske; + } + + /* worst case estimate */ + args->tmpSigSz = ED25519_SIG_SIZE; + break; + } + #endif /* HAVE_ED25519 */ + default: + ERROR_OUT(ALGO_ID_E, exit_sske); /* unsupported type */ + } /* switch(ssl->specs.sig_algo) */ + } + + /* sig length */ + args->length += LENGTH_SZ; + args->length += args->tmpSigSz; + + if (IsAtLeastTLSv1_2(ssl)) { + args->length += HASH_SIG_SIZE; + } + + args->sendSz = args->length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; + + #ifdef HAVE_QSH + args->length += args->qshSz; + args->sendSz += args->qshSz; + #endif + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + args->idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + preSigIdx = args->idx; + } + #endif + if (IsEncryptionOn(ssl, 1)) { + args->sendSz += MAX_MSG_EXTRA; + } + + /* check for available size */ + if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) { + goto exit_sske; + } + + /* get ouput buffer */ + args->output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + /* record and message headers will be added below, when we're sure + of the sig length */ + + /* key exchange data */ + args->output[args->idx++] = named_curve; + args->output[args->idx++] = 0x00; /* leading zero */ + #ifdef HAVE_CURVE25519 + if (ssl->ecdhCurveOID == ECC_X25519_OID) + args->output[args->idx++] = WOLFSSL_ECC_X25519; + else + #endif + { + #ifdef HAVE_ECC + args->output[args->idx++] = + SetCurveId(ssl->eccTempKey); + #endif + } + args->output[args->idx++] = (byte)args->exportSz; + XMEMCPY(args->output + args->idx, args->exportBuf, args->exportSz); + args->idx += args->exportSz; + + /* Determine hash type */ + if (IsAtLeastTLSv1_2(ssl)) { + EncodeSigAlg(ssl->suites->hashAlgo, + ssl->suites->sigAlgo, + &args->output[args->idx]); + args->idx += 2; + + hashType = HashAlgoToType(ssl->suites->hashAlgo); + if (hashType == WC_HASH_TYPE_NONE) { + ERROR_OUT(ALGO_ID_E, exit_sske); + } + + } else { + /* only using sha and md5 for rsa */ + #ifndef NO_OLD_TLS + hashType = WC_HASH_TYPE_SHA; + if (ssl->suites->sigAlgo == rsa_sa_algo) { + hashType = WC_HASH_TYPE_MD5_SHA; + } + #else + ERROR_OUT(ALGO_ID_E, exit_sske); + #endif + } + + /* Signature length will be written later, when we're sure what it is */ + + #ifdef HAVE_FUZZER + if (ssl->fuzzerCb) { + ssl->fuzzerCb(ssl, args->output + preSigIdx, + preSigSz, FUZZ_SIGNATURE, ssl->fuzzerCtx); + } + #endif + + /* Assemble buffer to hash for signature */ + args->sigDataSz = RAN_LEN + RAN_LEN + preSigSz; + args->sigDataBuf = (byte*)XMALLOC(args->sigDataSz, + ssl->heap, DYNAMIC_TYPE_SIGNATURE); + if (args->sigDataBuf == NULL) { + ERROR_OUT(MEMORY_E, exit_sske); + } + XMEMCPY(args->sigDataBuf, ssl->arrays->clientRandom, + RAN_LEN); + XMEMCPY(args->sigDataBuf+RAN_LEN, + ssl->arrays->serverRandom, RAN_LEN); + XMEMCPY(args->sigDataBuf+RAN_LEN+RAN_LEN, + args->output + preSigIdx, preSigSz); + + if (ssl->suites->sigAlgo != ed25519_sa_algo) { + ssl->buffers.sig.length = + wc_HashGetDigestSize(hashType); + if ((int)ssl->buffers.sig.length < 0) { + ERROR_OUT(HASH_TYPE_E, exit_sske); + } + ssl->buffers.sig.buffer = (byte*)XMALLOC( + ssl->buffers.sig.length, + ssl->heap, DYNAMIC_TYPE_SIGNATURE); + if (ssl->buffers.sig.buffer == NULL) { + ERROR_OUT(MEMORY_E, exit_sske); + } + + /* Perform hash */ + ret = wc_Hash(hashType, args->sigDataBuf, + args->sigDataSz, + ssl->buffers.sig.buffer, + ssl->buffers.sig.length); + if (ret != 0) { + goto exit_sske; + } + } + + args->sigSz = args->tmpSigSz; + + /* Sign hash to create signature */ + switch (ssl->suites->sigAlgo) + { + #ifndef NO_RSA + case rsa_sa_algo: + { + /* For TLS 1.2 re-encode signature */ + if (IsAtLeastTLSv1_2(ssl)) { + byte* encodedSig = (byte*)XMALLOC( + MAX_ENCODED_SIG_SZ, ssl->heap, + DYNAMIC_TYPE_SIGNATURE); + if (encodedSig == NULL) { + ERROR_OUT(MEMORY_E, exit_sske); + } + + ssl->buffers.sig.length = + wc_EncodeSignature(encodedSig, + ssl->buffers.sig.buffer, + ssl->buffers.sig.length, + TypeHash(ssl->suites->hashAlgo)); + + /* Replace sig buffer with new one */ + XFREE(ssl->buffers.sig.buffer, ssl->heap, + DYNAMIC_TYPE_SIGNATURE); + ssl->buffers.sig.buffer = encodedSig; + } + + /* write sig size here */ + c16toa((word16)args->sigSz, + args->output + args->idx); + args->idx += LENGTH_SZ; + break; + } + #ifdef WC_RSA_PSS + case rsa_pss_sa_algo: + /* write sig size here */ + c16toa((word16)args->sigSz, + args->output + args->idx); + args->idx += LENGTH_SZ; + break; + #endif + #endif /* !NO_RSA */ + case ecc_dsa_sa_algo: + { + break; + } + #ifdef HAVE_ED25519 + case ed25519_sa_algo: + ret = Ed25519CheckPubKey(ssl); + if (ret != 0) + goto exit_sske; + break; + #endif /* HAVE_ED25519 */ + } /* switch(ssl->specs.sig_algo) */ + break; + } + #endif /* HAVE_ECC || HAVE_CURVE25519 */ + #if !defined(NO_DH) && !defined(NO_RSA) + case diffie_hellman_kea: + { + enum wc_HashType hashType; + + args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + args->length = LENGTH_SZ * 3; /* p, g, pub */ + args->length += ssl->buffers.serverDH_P.length + + ssl->buffers.serverDH_G.length + + ssl->buffers.serverDH_Pub.length; + + preSigIdx = args->idx; + preSigSz = args->length; + + if (!ssl->options.usingAnon_cipher) { + word16 keySz; + + /* sig length */ + args->length += LENGTH_SZ; + + if (ssl->buffers.key == NULL) { + #ifdef HAVE_PK_CALLBACKS + if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) + keySz = (word32)GetPrivateKeySigSize(ssl); + else + #endif + ERROR_OUT(NO_PRIVATE_KEY, exit_sske); + } + else + { + if (ssl->buffers.keyType == 0) + ssl->buffers.keyType = rsa_sa_algo; + ret = DecodePrivateKey(ssl, &keySz); + if (ret != 0) { + goto exit_sske; + } + } + + if (keySz <= 0) { /* test if keySz has error */ + ERROR_OUT(keySz, exit_sske); + } + + args->tmpSigSz = (word32)keySz; + args->length += args->tmpSigSz; + + if (IsAtLeastTLSv1_2(ssl)) { + args->length += HASH_SIG_SIZE; + } + } + + args->sendSz = args->length + HANDSHAKE_HEADER_SZ + + RECORD_HEADER_SZ; + + #ifdef HAVE_QSH + args->length += args->qshSz; + args->sendSz += args->qshSz; + #endif + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + args->sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + args->idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + preSigIdx = args->idx; + } + #endif + + if (IsEncryptionOn(ssl, 1)) { + args->sendSz += MAX_MSG_EXTRA; + } + + /* check for available size */ + if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) { + goto exit_sske; + } + + /* get ouput buffer */ + args->output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + AddHeaders(args->output, args->length, + server_key_exchange, ssl); + + /* add p, g, pub */ + c16toa((word16)ssl->buffers.serverDH_P.length, + args->output + args->idx); + args->idx += LENGTH_SZ; + XMEMCPY(args->output + args->idx, + ssl->buffers.serverDH_P.buffer, + ssl->buffers.serverDH_P.length); + args->idx += ssl->buffers.serverDH_P.length; + + /* g */ + c16toa((word16)ssl->buffers.serverDH_G.length, + args->output + args->idx); + args->idx += LENGTH_SZ; + XMEMCPY(args->output + args->idx, + ssl->buffers.serverDH_G.buffer, + ssl->buffers.serverDH_G.length); + args->idx += ssl->buffers.serverDH_G.length; + + /* pub */ + c16toa((word16)ssl->buffers.serverDH_Pub.length, + args->output + args->idx); + args->idx += LENGTH_SZ; + XMEMCPY(args->output + args->idx, + ssl->buffers.serverDH_Pub.buffer, + ssl->buffers.serverDH_Pub.length); + args->idx += ssl->buffers.serverDH_Pub.length; + + #ifdef HAVE_FUZZER + if (ssl->fuzzerCb) { + ssl->fuzzerCb(ssl, args->output + preSigIdx, + preSigSz, FUZZ_SIGNATURE, ssl->fuzzerCtx); + } + #endif + + if (ssl->options.usingAnon_cipher) { + break; + } + + /* Determine hash type */ + if (IsAtLeastTLSv1_2(ssl)) { + EncodeSigAlg(ssl->suites->hashAlgo, + ssl->suites->sigAlgo, + &args->output[args->idx]); + args->idx += 2; + + hashType = HashAlgoToType(ssl->suites->hashAlgo); + if (hashType == WC_HASH_TYPE_NONE) { + ERROR_OUT(ALGO_ID_E, exit_sske); + } + } else { + /* only using sha and md5 for rsa */ + #ifndef NO_OLD_TLS + hashType = WC_HASH_TYPE_SHA; + if (ssl->suites->sigAlgo == rsa_sa_algo) { + hashType = WC_HASH_TYPE_MD5_SHA; + } + #else + ERROR_OUT(ALGO_ID_E, exit_sske); + #endif + } + + /* signature size */ + c16toa((word16)args->tmpSigSz, args->output + args->idx); + args->idx += LENGTH_SZ; + + /* Assemble buffer to hash for signature */ + args->sigDataSz = RAN_LEN + RAN_LEN + preSigSz; + args->sigDataBuf = (byte*)XMALLOC(args->sigDataSz, + ssl->heap, DYNAMIC_TYPE_SIGNATURE); + if (args->sigDataBuf == NULL) { + ERROR_OUT(MEMORY_E, exit_sske); + } + XMEMCPY(args->sigDataBuf, ssl->arrays->clientRandom, + RAN_LEN); + XMEMCPY(args->sigDataBuf+RAN_LEN, + ssl->arrays->serverRandom, RAN_LEN); + XMEMCPY(args->sigDataBuf+RAN_LEN+RAN_LEN, + args->output + preSigIdx, preSigSz); + + if (ssl->suites->sigAlgo != ed25519_sa_algo) { + ssl->buffers.sig.length = + wc_HashGetDigestSize(hashType); + ssl->buffers.sig.buffer = (byte*)XMALLOC( + ssl->buffers.sig.length, ssl->heap, + DYNAMIC_TYPE_SIGNATURE); + if (ssl->buffers.sig.buffer == NULL) { + ERROR_OUT(MEMORY_E, exit_sske); + } + + /* Perform hash */ + ret = wc_Hash(hashType, args->sigDataBuf, + args->sigDataSz, + ssl->buffers.sig.buffer, + ssl->buffers.sig.length); + if (ret != 0) { + goto exit_sske; + } + } + + args->sigSz = args->tmpSigSz; + + /* Sign hash to create signature */ + switch (ssl->suites->sigAlgo) + { + #ifndef NO_RSA + case rsa_sa_algo: + { + /* For TLS 1.2 re-encode signature */ + if (IsAtLeastTLSv1_2(ssl)) { + byte* encodedSig = (byte*)XMALLOC( + MAX_ENCODED_SIG_SZ, ssl->heap, + DYNAMIC_TYPE_SIGNATURE); + if (encodedSig == NULL) { + ERROR_OUT(MEMORY_E, exit_sske); + } + + ssl->buffers.sig.length = + wc_EncodeSignature(encodedSig, + ssl->buffers.sig.buffer, + ssl->buffers.sig.length, + TypeHash(ssl->suites->hashAlgo)); + + /* Replace sig buffer with new one */ + XFREE(ssl->buffers.sig.buffer, ssl->heap, + DYNAMIC_TYPE_SIGNATURE); + ssl->buffers.sig.buffer = encodedSig; + } + break; + } + #endif /* NO_RSA */ + } /* switch (ssl->suites->sigAlgo) */ + break; + } + #endif /* !defined(NO_DH) && !defined(NO_RSA) */ + } /* switch(ssl->specs.kea) */ + + /* Check for error */ + if (ret != 0) { + goto exit_sske; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_DO; + } /* case TLS_ASYNC_BUILD */ + FALL_THROUGH; + + case TLS_ASYNC_DO: + { + switch(ssl->specs.kea) + { + #ifndef NO_PSK + case psk_kea: + { + break; + } + #endif /* !NO_PSK */ + #if !defined(NO_DH) && !defined(NO_PSK) + case dhe_psk_kea: + { + break; + } + #endif /* !defined(NO_DH) && !defined(NO_PSK) */ + #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \ + !defined(NO_PSK) + case ecdhe_psk_kea: + { + break; + } + #endif /* (HAVE_ECC || HAVE_CURVE25519) && !NO_PSK */ + #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) + case ecc_diffie_hellman_kea: + { + /* Sign hash to create signature */ + switch (ssl->suites->sigAlgo) + { + #ifndef NO_RSA + #ifdef WC_RSA_PSS + case rsa_pss_sa_algo: + #endif + case rsa_sa_algo: + { + RsaKey* key = (RsaKey*)ssl->hsKey; + + ret = RsaSign(ssl, + ssl->buffers.sig.buffer, + ssl->buffers.sig.length, + args->output + args->idx, + &args->sigSz, + ssl->suites->sigAlgo, ssl->suites->hashAlgo, + key, + ssl->buffers.key + ); + break; + } + #endif /* !NO_RSA */ + #ifdef HAVE_ECC + case ecc_dsa_sa_algo: + { + ecc_key* key = (ecc_key*)ssl->hsKey; + + ret = EccSign(ssl, + ssl->buffers.sig.buffer, + ssl->buffers.sig.length, + args->output + LENGTH_SZ + args->idx, + &args->sigSz, + key, + #ifdef HAVE_PK_CALLBACKS + ssl->buffers.key + #else + NULL + #endif + ); + break; + } + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ed25519_sa_algo: + { + ed25519_key* key = (ed25519_key*)ssl->hsKey; + + ret = Ed25519Sign(ssl, + args->sigDataBuf, args->sigDataSz, + args->output + LENGTH_SZ + args->idx, + &args->sigSz, + key, + #ifdef HAVE_PK_CALLBACKS + ssl->buffers.key + #else + NULL + #endif + ); + break; + } + #endif + } /* switch(ssl->specs.sig_algo) */ + break; + } + #endif /* HAVE_ECC || HAVE_CURVE25519 */ + #if !defined(NO_DH) && !defined(NO_RSA) + case diffie_hellman_kea: + { + /* Sign hash to create signature */ + switch (ssl->suites->sigAlgo) + { + #ifndef NO_RSA + #ifdef WC_RSA_PSS + case rsa_pss_sa_algo: + #endif + case rsa_sa_algo: + { + RsaKey* key = (RsaKey*)ssl->hsKey; + + if (ssl->options.usingAnon_cipher) { + break; + } + + ret = RsaSign(ssl, + ssl->buffers.sig.buffer, + ssl->buffers.sig.length, + args->output + args->idx, + &args->sigSz, + ssl->suites->sigAlgo, ssl->suites->hashAlgo, + key, + ssl->buffers.key + ); + break; + } + #endif /* NO_RSA */ + } /* switch (ssl->suites->sigAlgo) */ + + break; + } + #endif /* !defined(NO_DH) && !defined(NO_RSA) */ + } /* switch(ssl->specs.kea) */ + + /* Check for error */ + if (ret != 0) { + goto exit_sske; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_VERIFY; + } /* case TLS_ASYNC_DO */ + FALL_THROUGH; + + case TLS_ASYNC_VERIFY: + { + switch(ssl->specs.kea) + { + #ifndef NO_PSK + case psk_kea: + { + /* Nothing to do in this sub-state */ + break; + } + #endif /* !NO_PSK */ + #if !defined(NO_DH) && !defined(NO_PSK) + case dhe_psk_kea: + { + /* Nothing to do in this sub-state */ + break; + } + #endif /* !defined(NO_DH) && !defined(NO_PSK) */ + #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \ + !defined(NO_PSK) + case ecdhe_psk_kea: + { + /* Nothing to do in this sub-state */ + break; + } + #endif /* (HAVE_ECC || HAVE_CURVE25519) && !NO_PSK */ + #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) + case ecc_diffie_hellman_kea: + { + switch(ssl->suites->sigAlgo) + { + #ifndef NO_RSA + #ifdef WC_RSA_PSS + case rsa_pss_sa_algo: + #endif + case rsa_sa_algo: + { + RsaKey* key = (RsaKey*)ssl->hsKey; + + if (args->verifySig == NULL) { + if (args->sigSz == 0) { + ERROR_OUT(BAD_COND_E, exit_sske); + } + args->verifySig = (byte*)XMALLOC( + args->sigSz, ssl->heap, + DYNAMIC_TYPE_SIGNATURE); + if (!args->verifySig) { + ERROR_OUT(MEMORY_E, exit_sske); + } + XMEMCPY(args->verifySig, + args->output + args->idx, args->sigSz); + } + + /* check for signature faults */ + ret = VerifyRsaSign(ssl, + args->verifySig, args->sigSz, + ssl->buffers.sig.buffer, + ssl->buffers.sig.length, + ssl->suites->sigAlgo, ssl->suites->hashAlgo, + key, ssl->buffers.key + ); + break; + } + #endif + case ecc_dsa_sa_algo: + #ifdef HAVE_ED25519 + case ed25519_sa_algo: + #endif + { + /* Now that we know the real sig size, write it. */ + c16toa((word16)args->sigSz, + args->output + args->idx); + + /* And adjust length and sendSz from estimates */ + args->length += args->sigSz - args->tmpSigSz; + args->sendSz += args->sigSz - args->tmpSigSz; + break; + } + default: + ERROR_OUT(ALGO_ID_E, exit_sske); /* unsupported type */ + } /* switch(ssl->specs.sig_algo) */ + break; + } + #endif /* HAVE_ECC || HAVE_CURVE25519 */ + #if !defined(NO_DH) && !defined(NO_RSA) + case diffie_hellman_kea: + { + switch (ssl->suites->sigAlgo) + { + #ifndef NO_RSA + #ifndef WC_RSA_PSS + case rsa_pss_sa_algo: + #endif + case rsa_sa_algo: + { + RsaKey* key = (RsaKey*)ssl->hsKey; + + if (ssl->options.usingAnon_cipher) { + break; + } + + if (args->verifySig == NULL) { + if (args->sigSz == 0) { + ERROR_OUT(BAD_COND_E, exit_sske); + } + args->verifySig = (byte*)XMALLOC( + args->sigSz, ssl->heap, + DYNAMIC_TYPE_SIGNATURE); + if (!args->verifySig) { + ERROR_OUT(MEMORY_E, exit_sske); + } + XMEMCPY(args->verifySig, + args->output + args->idx, args->sigSz); + } + + /* check for signature faults */ + ret = VerifyRsaSign(ssl, + args->verifySig, args->sigSz, + ssl->buffers.sig.buffer, + ssl->buffers.sig.length, + ssl->suites->sigAlgo, ssl->suites->hashAlgo, + key, ssl->buffers.key + ); + break; + } + #endif + } /* switch (ssl->suites->sigAlgo) */ + break; + } + #endif /* !defined(NO_DH) && !defined(NO_RSA) */ + } /* switch(ssl->specs.kea) */ + + /* Check for error */ + if (ret != 0) { + goto exit_sske; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_FINALIZE; + } /* case TLS_ASYNC_VERIFY */ + FALL_THROUGH; + + case TLS_ASYNC_FINALIZE: + { + #ifdef HAVE_QSH + if (ssl->peerQSHKeyPresent) { + if (args->qshSz > 0) { + args->idx = args->sendSz - args->qshSz; + if (QSH_KeyExchangeWrite(ssl, 1) != 0) { + ERROR_OUT(MEMORY_E, exit_sske); + } + + /* extension type */ + c16toa(TLSX_QUANTUM_SAFE_HYBRID, + args->output + args->idx); + args->idx += OPAQUE16_LEN; + + /* write to output and check amount written */ + if (TLSX_QSHPK_Write(ssl->QSH_secret->list, + args->output + args->idx) > + args->qshSz - OPAQUE16_LEN) { + ERROR_OUT(MEMORY_E, exit_sske); + } + } + } + #endif + + #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) + if (ssl->specs.kea == ecdhe_psk_kea || + ssl->specs.kea == ecc_diffie_hellman_kea) { + /* Check output to make sure it was set */ + if (args->output) { + AddHeaders(args->output, args->length, + server_key_exchange, ssl); + } + else { + ERROR_OUT(BUFFER_ERROR, exit_sske); + } + } + #endif /* HAVE_ECC || HAVE_CURVE25519 */ + + if (IsEncryptionOn(ssl, 1)) { + args->inputSz = args->length + HANDSHAKE_HEADER_SZ; + /* buildmsg adds rechdr */ + args->input = (byte*)XMALLOC(args->inputSz, ssl->heap, + DYNAMIC_TYPE_IN_BUFFER); + if (args->input == NULL) { + ERROR_OUT(MEMORY_E, exit_sske); + } + + XMEMCPY(args->input, args->output + RECORD_HEADER_SZ, + args->inputSz); + ret = BuildMessage(ssl, args->output, args->sendSz, + args->input, args->inputSz, handshake, 1, 0, 0); + XFREE(args->input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + args->input = NULL; + /* make sure its not double free'd on cleanup */ + + if (ret >= 0) { + args->sendSz = ret; + ret = 0; + } + } + else { + #ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl)) { + if ((ret = DtlsMsgPoolSave(ssl, + args->output, args->sendSz)) != 0) { + goto exit_sske; + } + } + + if (ssl->options.dtls) + DtlsSEQIncrement(ssl, CUR_ORDER); + #endif + + ret = HashOutput(ssl, args->output, args->sendSz, 0); + if (ret != 0) { + goto exit_sske; + } + } + + #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) + if (ssl->hsInfoOn) { + AddPacketName(ssl, "ServerKeyExchange"); + } + if (ssl->toInfoOn) { + AddPacketInfo(ssl, "ServerKeyExchange", handshake, + args->output, args->sendSz, WRITE_PROTO, ssl->heap); + } + #endif + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_END; + } /* case TLS_ASYNC_FINALIZE */ + FALL_THROUGH; + + case TLS_ASYNC_END: + { + ssl->buffers.outputBuffer.length += args->sendSz; + if (!ssl->options.groupMessages) { + ret = SendBuffered(ssl); + } + + ssl->options.serverState = SERVER_KEYEXCHANGE_COMPLETE; + break; + } + default: + ret = INPUT_CASE_ERROR; + } /* switch(ssl->options.asyncState) */ + + exit_sske: + + WOLFSSL_LEAVE("SendServerKeyExchange", ret); + WOLFSSL_END(WC_FUNC_SERVER_KEY_EXCHANGE_SEND); + + #ifdef WOLFSSL_ASYNC_CRYPT + /* Handle async operation */ + if (ret == WC_PENDING_E) + return ret; + #endif /* WOLFSSL_ASYNC_CRYPT */ + + /* Final cleanup */ + FreeSskeArgs(ssl, args); + FreeKeyExchange(ssl); + + return ret; + } + +#if defined(HAVE_SERVER_RENEGOTIATION_INFO) || defined(HAVE_FALLBACK_SCSV) || \ + defined(OPENSSL_ALL) + + /* search suites for specific one, idx on success, negative on error */ +#ifndef WOLFSSL_TLS13 + static +#endif + int FindSuite(Suites* suites, byte first, byte second) + { + int i; + + if (suites == NULL || suites->suiteSz == 0) { + WOLFSSL_MSG("Suites pointer error or suiteSz 0"); + return SUITES_ERROR; + } + + for (i = 0; i < suites->suiteSz-1; i += SUITE_LEN) { + if (suites->suites[i] == first && + suites->suites[i+1] == second ) + return i; + } + + return MATCH_SUITE_ERROR; + } + +#endif + +#endif /* !WOLFSSL_NO_TLS12 */ + + /* Make sure server cert/key are valid for this suite, true on success */ + static int VerifyServerSuite(WOLFSSL* ssl, word16 idx) + { + int haveRSA = !ssl->options.haveStaticECC; + int havePSK = 0; + byte first; + byte second; + + WOLFSSL_ENTER("VerifyServerSuite"); + + if (ssl->suites == NULL) { + WOLFSSL_MSG("Suites pointer error"); + return 0; + } + + first = ssl->suites->suites[idx]; + second = ssl->suites->suites[idx+1]; + + #ifndef NO_PSK + havePSK = ssl->options.havePSK; + #endif + + if (ssl->options.haveNTRU) + haveRSA = 0; + + if (CipherRequires(first, second, REQUIRES_RSA)) { + WOLFSSL_MSG("Requires RSA"); + if (haveRSA == 0) { + WOLFSSL_MSG("Don't have RSA"); + return 0; + } + } + + if (CipherRequires(first, second, REQUIRES_DHE)) { + WOLFSSL_MSG("Requires DHE"); + if (ssl->options.haveDH == 0) { + WOLFSSL_MSG("Don't have DHE"); + return 0; + } + } + + if (CipherRequires(first, second, REQUIRES_ECC)) { + WOLFSSL_MSG("Requires ECC"); + if (ssl->options.haveECC == 0) { + WOLFSSL_MSG("Don't have ECC"); + return 0; + } + } + + if (CipherRequires(first, second, REQUIRES_ECC_STATIC)) { + WOLFSSL_MSG("Requires static ECC"); + if (ssl->options.haveStaticECC == 0) { + WOLFSSL_MSG("Don't have static ECC"); + return 0; + } + } + + if (CipherRequires(first, second, REQUIRES_PSK)) { + WOLFSSL_MSG("Requires PSK"); + if (havePSK == 0) { + WOLFSSL_MSG("Don't have PSK"); + return 0; + } + } + + if (CipherRequires(first, second, REQUIRES_NTRU)) { + WOLFSSL_MSG("Requires NTRU"); + if (ssl->options.haveNTRU == 0) { + WOLFSSL_MSG("Don't have NTRU"); + return 0; + } + } + + if (CipherRequires(first, second, REQUIRES_RSA_SIG)) { + WOLFSSL_MSG("Requires RSA Signature"); + if (ssl->options.side == WOLFSSL_SERVER_END && + ssl->options.haveECDSAsig == 1) { + WOLFSSL_MSG("Don't have RSA Signature"); + return 0; + } + } + +#if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \ + defined(HAVE_SUPPORTED_CURVES) + if (!TLSX_ValidateSupportedCurves(ssl, first, second)) { + WOLFSSL_MSG("Don't have matching curves"); + return 0; + } +#endif + + /* ECCDHE is always supported if ECC on */ + +#ifdef HAVE_QSH + /* need to negotiate a classic suite in addition to TLS_QSH */ + if (first == QSH_BYTE && second == TLS_QSH) { + if (TLSX_SupportExtensions(ssl)) { + ssl->options.haveQSH = 1; /* matched TLS_QSH */ + } + else { + WOLFSSL_MSG("Version of SSL connection does not support " + "TLS_QSH"); + } + return 0; + } +#endif + +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && + ssl->options.side == WOLFSSL_SERVER_END) { + /* Try to establish a key share. */ + int ret = TLSX_KeyShare_Establish(ssl); + if (ret == KEY_SHARE_ERROR) + ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST_COMPLETE; + else if (ret != 0) + return 0; + } + else if (first == TLS13_BYTE) { + /* Can't negotiate TLS 1.3 cipher suites with lower protocol + * version. */ + return 0; + } +#endif + + return 1; + } + +#ifndef NO_WOLFSSL_SERVER + static int CompareSuites(WOLFSSL* ssl, Suites* peerSuites, word16 i, + word16 j) + { + if (ssl->suites->suites[i] == peerSuites->suites[j] && + ssl->suites->suites[i+1] == peerSuites->suites[j+1] ) { + + if (VerifyServerSuite(ssl, i)) { + int result; + WOLFSSL_MSG("Verified suite validity"); + ssl->options.cipherSuite0 = ssl->suites->suites[i]; + ssl->options.cipherSuite = ssl->suites->suites[i+1]; + result = SetCipherSpecs(ssl); + if (result == 0) { + result = PickHashSigAlgo(ssl, peerSuites->hashSigAlgo, + peerSuites->hashSigAlgoSz); + } + return result; + } + else { + WOLFSSL_MSG("Could not verify suite validity, continue"); + } + } + + return MATCH_SUITE_ERROR; + } + + int MatchSuite(WOLFSSL* ssl, Suites* peerSuites) + { + int ret; + word16 i, j; + + WOLFSSL_ENTER("MatchSuite"); + + /* & 0x1 equivalent % 2 */ + if (peerSuites->suiteSz == 0 || peerSuites->suiteSz & 0x1) + return BUFFER_ERROR; + + if (ssl->suites == NULL) + return SUITES_ERROR; + + if (!ssl->options.useClientOrder) { + /* Server order */ + for (i = 0; i < ssl->suites->suiteSz; i += 2) { + for (j = 0; j < peerSuites->suiteSz; j += 2) { + ret = CompareSuites(ssl, peerSuites, i, j); + if (ret != MATCH_SUITE_ERROR) + return ret; + } + } + } + else { + /* Client order */ + for (j = 0; j < peerSuites->suiteSz; j += 2) { + for (i = 0; i < ssl->suites->suiteSz; i += 2) { + ret = CompareSuites(ssl, peerSuites, i, j); + if (ret != MATCH_SUITE_ERROR) + return ret; + } + } + } + + return MATCH_SUITE_ERROR; + } +#endif + +#ifdef OLD_HELLO_ALLOWED + + /* process old style client hello, deprecate? */ + int ProcessOldClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, + word32 inSz, word16 sz) + { + word32 idx = *inOutIdx; + word16 sessionSz; + word16 randomSz; + word16 i, j; + ProtocolVersion pv; + Suites clSuites; + int ret = -1; + + (void)inSz; + WOLFSSL_MSG("Got old format client hello"); +#ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName(ssl, "ClientHello"); + if (ssl->toInfoOn) + AddLateName("ClientHello", &ssl->timeoutInfo); +#endif + + /* manually hash input since different format */ +#ifndef NO_OLD_TLS +#ifndef NO_MD5 + wc_Md5Update(&ssl->hsHashes->hashMd5, input + idx, sz); +#endif +#ifndef NO_SHA + wc_ShaUpdate(&ssl->hsHashes->hashSha, input + idx, sz); +#endif +#endif +#ifndef NO_SHA256 + if (IsAtLeastTLSv1_2(ssl)) { + int shaRet = wc_Sha256Update(&ssl->hsHashes->hashSha256, + input + idx, sz); + if (shaRet != 0) + return shaRet; + } +#endif + + /* does this value mean client_hello? */ + idx++; + + /* version */ + pv.major = input[idx++]; + pv.minor = input[idx++]; + ssl->chVersion = pv; /* store */ + + if (ssl->version.minor > pv.minor) { + byte haveRSA = 0; + byte havePSK = 0; + int keySz = 0; + + if (!ssl->options.downgrade) { + WOLFSSL_MSG("Client trying to connect with lesser version"); + return VERSION_ERROR; + } + if (pv.minor < ssl->options.minDowngrade) { + WOLFSSL_MSG("\tversion below minimum allowed, fatal error"); + return VERSION_ERROR; + } + if (pv.minor == SSLv3_MINOR) { + /* turn off tls */ + WOLFSSL_MSG("\tdowngrading to SSLv3"); + ssl->options.tls = 0; + ssl->options.tls1_1 = 0; + ssl->version.minor = SSLv3_MINOR; + } + else if (pv.minor == TLSv1_MINOR) { + WOLFSSL_MSG("\tdowngrading to TLSv1"); + /* turn off tls 1.1+ */ + ssl->options.tls1_1 = 0; + ssl->version.minor = TLSv1_MINOR; + } + else if (pv.minor == TLSv1_1_MINOR) { + WOLFSSL_MSG("\tdowngrading to TLSv1.1"); + ssl->version.minor = TLSv1_1_MINOR; + } + else if (pv.minor == TLSv1_2_MINOR) { + WOLFSSL_MSG(" downgrading to TLSv1.2"); + ssl->version.minor = TLSv1_2_MINOR; + } +#ifndef NO_RSA + haveRSA = 1; +#endif +#ifndef NO_PSK + havePSK = ssl->options.havePSK; +#endif +#ifndef NO_CERTS + keySz = ssl->buffers.keySz; +#endif + + InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK, + ssl->options.haveDH, ssl->options.haveNTRU, + ssl->options.haveECDSAsig, ssl->options.haveECC, + ssl->options.haveStaticECC, ssl->options.side); + } + + /* suite size */ + ato16(&input[idx], &clSuites.suiteSz); + idx += OPAQUE16_LEN; + + if (clSuites.suiteSz > WOLFSSL_MAX_SUITE_SZ) + return BUFFER_ERROR; + clSuites.hashSigAlgoSz = 0; + + /* session size */ + ato16(&input[idx], &sessionSz); + idx += OPAQUE16_LEN; + + if (sessionSz > ID_LEN) + return BUFFER_ERROR; + + /* random size */ + ato16(&input[idx], &randomSz); + idx += OPAQUE16_LEN; + + if (randomSz > RAN_LEN) + return BUFFER_ERROR; + + /* suites */ + for (i = 0, j = 0; i < clSuites.suiteSz; i += 3) { + byte first = input[idx++]; + if (!first) { /* implicit: skip sslv2 type */ + XMEMCPY(&clSuites.suites[j], &input[idx], SUITE_LEN); + j += SUITE_LEN; + } + idx += SUITE_LEN; + } + clSuites.suiteSz = j; + + /* session id */ + if (sessionSz) { + XMEMCPY(ssl->arrays->sessionID, input + idx, sessionSz); + ssl->arrays->sessionIDSz = (byte)sessionSz; + idx += sessionSz; + ssl->options.resuming = 1; + } + + /* random */ + if (randomSz < RAN_LEN) + XMEMSET(ssl->arrays->clientRandom, 0, RAN_LEN - randomSz); + XMEMCPY(&ssl->arrays->clientRandom[RAN_LEN - randomSz], input + idx, + randomSz); + idx += randomSz; + + if (ssl->options.usingCompression) + ssl->options.usingCompression = 0; /* turn off */ + + ssl->options.clientState = CLIENT_HELLO_COMPLETE; + ssl->cbmode = SSL_CB_MODE_WRITE; + *inOutIdx = idx; + + ssl->options.haveSessionId = 1; + /* DoClientHello uses same resume code */ + if (ssl->options.resuming) { /* let's try */ + WOLFSSL_SESSION* session = GetSession(ssl, + ssl->arrays->masterSecret, 1); + #ifdef HAVE_SESSION_TICKET + if (ssl->options.useTicket == 1) { + session = &ssl->session; + } + #endif + + if (!session) { + WOLFSSL_MSG("Session lookup for resume failed"); + ssl->options.resuming = 0; + } else { + #ifdef HAVE_EXT_CACHE + wolfSSL_SESSION_free(session); + #endif + if (MatchSuite(ssl, &clSuites) < 0) { + WOLFSSL_MSG("Unsupported cipher suite, OldClientHello"); + return UNSUPPORTED_SUITE; + } + + ret = wc_RNG_GenerateBlock(ssl->rng, ssl->arrays->serverRandom, + RAN_LEN); + if (ret != 0) + return ret; + + #ifdef NO_OLD_TLS + ret = DeriveTlsKeys(ssl); + #else + #ifndef NO_TLS + if (ssl->options.tls) + ret = DeriveTlsKeys(ssl); + #endif + if (!ssl->options.tls) + ret = DeriveKeys(ssl); + #endif + ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE; + + return ret; + } + } + + ret = MatchSuite(ssl, &clSuites); + if (ret != 0)return ret; + return SanityCheckMsgReceived(ssl, client_hello); + } + +#endif /* OLD_HELLO_ALLOWED */ + +#ifndef WOLFSSL_NO_TLS12 + + int HandleTlsResumption(WOLFSSL* ssl, int bogusID, Suites* clSuites) + { + int ret = 0; + WOLFSSL_SESSION* session; + + (void)bogusID; + + session = GetSession(ssl, ssl->arrays->masterSecret, 1); + #ifdef HAVE_SESSION_TICKET + if (ssl->options.useTicket == 1) { + session = &ssl->session; + } else if (bogusID == 1 && ssl->options.rejectTicket == 0) { + WOLFSSL_MSG("Bogus session ID without session ticket"); + return BUFFER_ERROR; + } + #endif + + if (!session) { + WOLFSSL_MSG("Session lookup for resume failed"); + ssl->options.resuming = 0; + } + else if (session->haveEMS != ssl->options.haveEMS) { + /* RFC 7627, 5.3, server-side */ + /* if old sess didn't have EMS, but new does, full handshake */ + if (!session->haveEMS && ssl->options.haveEMS) { + WOLFSSL_MSG("Attempting to resume a session that didn't " + "use EMS with a new session with EMS. Do full " + "handshake."); + ssl->options.resuming = 0; + } + /* if old sess used EMS, but new doesn't, MUST abort */ + else if (session->haveEMS && !ssl->options.haveEMS) { + WOLFSSL_MSG("Trying to resume a session with EMS without " + "using EMS"); + #ifdef WOLFSSL_EXTRA_ALERTS + SendAlert(ssl, alert_fatal, handshake_failure); + #endif + return EXT_MASTER_SECRET_NEEDED_E; + } + #ifdef HAVE_EXT_CACHE + wolfSSL_SESSION_free(session); + #endif + } + else { + #ifndef NO_RESUME_SUITE_CHECK + int j; + + /* Check client suites include the one in session */ + for (j = 0; j < clSuites->suiteSz; j += 2) { + if (clSuites->suites[j] == session->cipherSuite0 && + clSuites->suites[j+1] == session->cipherSuite) { + break; + } + } + if (j == clSuites->suiteSz) { + WOLFSSL_MSG("Prev session's cipher suite not in ClientHello"); + #ifdef WOLFSSL_EXTRA_ALERTS + SendAlert(ssl, alert_fatal, illegal_parameter); + #endif + return UNSUPPORTED_SUITE; + } + #endif + + #ifdef HAVE_EXT_CACHE + wolfSSL_SESSION_free(session); + #endif + if (MatchSuite(ssl, clSuites) < 0) { + WOLFSSL_MSG("Unsupported cipher suite, ClientHello"); + return UNSUPPORTED_SUITE; + } + + ret = wc_RNG_GenerateBlock(ssl->rng, ssl->arrays->serverRandom, + RAN_LEN); + if (ret != 0) + return ret; + + #ifdef NO_OLD_TLS + ret = DeriveTlsKeys(ssl); + #else + #ifndef NO_TLS + if (ssl->options.tls) + ret = DeriveTlsKeys(ssl); + #endif + if (!ssl->options.tls) + ret = DeriveKeys(ssl); + #endif + ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE; + } + + return ret; + } + + + /* handle processing of client_hello (1) */ + int DoClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, + word32 helloSz) + { + byte b; + byte bogusID = 0; /* flag for a bogus session id */ + ProtocolVersion pv; + Suites clSuites; + word32 i = *inOutIdx; + word32 begin = i; + int ret = 0; +#ifdef WOLFSSL_DTLS + Hmac cookieHmac; + byte peerCookie[MAX_COOKIE_LEN]; + byte peerCookieSz = 0; + byte cookieType; + byte cookieSz = 0; + + XMEMSET(&cookieHmac, 0, sizeof(Hmac)); +#endif /* WOLFSSL_DTLS */ + + WOLFSSL_START(WC_FUNC_CLIENT_HELLO_DO); + WOLFSSL_ENTER("DoClientHello"); + +#ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName(ssl, "ClientHello"); + if (ssl->toInfoOn) AddLateName("ClientHello", &ssl->timeoutInfo); +#endif + /* protocol version, random and session id length check */ + if ((i - begin) + OPAQUE16_LEN + RAN_LEN + OPAQUE8_LEN > helloSz) + return BUFFER_ERROR; + + /* protocol version */ + XMEMCPY(&pv, input + i, OPAQUE16_LEN); + ssl->chVersion = pv; /* store */ +#ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl)) { + #if defined(NO_SHA) && defined(NO_SHA256) + #error "DTLS needs either SHA or SHA-256" + #endif /* NO_SHA && NO_SHA256 */ + + #if !defined(NO_SHA) && defined(NO_SHA256) + cookieType = WC_SHA; + cookieSz = WC_SHA_DIGEST_SIZE; + #endif /* NO_SHA */ + #ifndef NO_SHA256 + cookieType = WC_SHA256; + cookieSz = WC_SHA256_DIGEST_SIZE; + #endif /* NO_SHA256 */ + ret = wc_HmacSetKey(&cookieHmac, cookieType, + ssl->buffers.dtlsCookieSecret.buffer, + ssl->buffers.dtlsCookieSecret.length); + if (ret != 0) return ret; + ret = wc_HmacUpdate(&cookieHmac, + (const byte*)ssl->buffers.dtlsCtx.peer.sa, + ssl->buffers.dtlsCtx.peer.sz); + if (ret != 0) return ret; + ret = wc_HmacUpdate(&cookieHmac, input + i, OPAQUE16_LEN); + if (ret != 0) return ret; + } +#endif /* WOLFSSL_DTLS */ + i += OPAQUE16_LEN; + + /* Legacy protocol version cannot negotiate TLS 1.3 or higher. */ + if (pv.major == SSLv3_MAJOR && pv.minor >= TLSv1_3_MINOR) + pv.minor = TLSv1_2_MINOR; + + if ((!ssl->options.dtls && ssl->version.minor > pv.minor) || + (ssl->options.dtls && ssl->version.minor != DTLS_MINOR + && ssl->version.minor != DTLSv1_2_MINOR && pv.minor != DTLS_MINOR + && pv.minor != DTLSv1_2_MINOR)) { + + word16 haveRSA = 0; + word16 havePSK = 0; + int keySz = 0; + + if (!ssl->options.downgrade) { + WOLFSSL_MSG("Client trying to connect with lesser version"); + return VERSION_ERROR; + } + if (pv.minor < ssl->options.minDowngrade) { + WOLFSSL_MSG("\tversion below minimum allowed, fatal error"); + return VERSION_ERROR; + } + + if (pv.minor == SSLv3_MINOR) { + /* turn off tls */ + WOLFSSL_MSG("\tdowngrading to SSLv3"); + ssl->options.tls = 0; + ssl->options.tls1_1 = 0; + ssl->version.minor = SSLv3_MINOR; + } + else if (pv.minor == TLSv1_MINOR) { + /* turn off tls 1.1+ */ + WOLFSSL_MSG("\tdowngrading to TLSv1"); + ssl->options.tls1_1 = 0; + ssl->version.minor = TLSv1_MINOR; + } + else if (pv.minor == TLSv1_1_MINOR) { + WOLFSSL_MSG("\tdowngrading to TLSv1.1"); + ssl->version.minor = TLSv1_1_MINOR; + } + else if (pv.minor == TLSv1_2_MINOR) { + WOLFSSL_MSG(" downgrading to TLSv1.2"); + ssl->version.minor = TLSv1_2_MINOR; + } +#ifndef NO_RSA + haveRSA = 1; +#endif +#ifndef NO_PSK + havePSK = ssl->options.havePSK; +#endif +#ifndef NO_CERTS + keySz = ssl->buffers.keySz; +#endif + InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK, + ssl->options.haveDH, ssl->options.haveNTRU, + ssl->options.haveECDSAsig, ssl->options.haveECC, + ssl->options.haveStaticECC, ssl->options.side); + } + +#ifdef OPENSSL_EXTRA + /* check if option is set to not allow the current version + * set from either wolfSSL_set_options or wolfSSL_CTX_set_options */ + if (!ssl->options.dtls && ssl->options.downgrade && + ssl->options.mask > 0) { + int reset = 0; + if (ssl->version.minor == TLSv1_2_MINOR && + (ssl->options.mask & SSL_OP_NO_TLSv1_2) == SSL_OP_NO_TLSv1_2) { + WOLFSSL_MSG("\tOption set to not allow TLSv1.2, Downgrading"); + ssl->version.minor = TLSv1_1_MINOR; + reset = 1; + } + if (ssl->version.minor == TLSv1_1_MINOR && + (ssl->options.mask & SSL_OP_NO_TLSv1_1) == SSL_OP_NO_TLSv1_1) { + WOLFSSL_MSG("\tOption set to not allow TLSv1.1, Downgrading"); + ssl->options.tls1_1 = 0; + ssl->version.minor = TLSv1_MINOR; + reset = 1; + } + if (ssl->version.minor == TLSv1_MINOR && + (ssl->options.mask & SSL_OP_NO_TLSv1) == SSL_OP_NO_TLSv1) { + WOLFSSL_MSG("\tOption set to not allow TLSv1, Downgrading"); + ssl->options.tls = 0; + ssl->options.tls1_1 = 0; + ssl->version.minor = SSLv3_MINOR; + reset = 1; + } + if (ssl->version.minor == SSLv3_MINOR && + (ssl->options.mask & SSL_OP_NO_SSLv3) == SSL_OP_NO_SSLv3) { + WOLFSSL_MSG("\tError, option set to not allow SSLv3"); + return VERSION_ERROR; + } + + if (ssl->version.minor < ssl->options.minDowngrade) { + WOLFSSL_MSG("\tversion below minimum allowed, fatal error"); + return VERSION_ERROR; + } + + if (reset) { + word16 haveRSA = 0; + word16 havePSK = 0; + int keySz = 0; + + #ifndef NO_RSA + haveRSA = 1; + #endif + #ifndef NO_PSK + havePSK = ssl->options.havePSK; + #endif + #ifndef NO_CERTS + keySz = ssl->buffers.keySz; + #endif + + /* reset cipher suites to account for TLS version change */ + InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK, + ssl->options.haveDH, ssl->options.haveNTRU, + ssl->options.haveECDSAsig, ssl->options.haveECC, + ssl->options.haveStaticECC, ssl->options.side); + } + } +#endif + + /* random */ + XMEMCPY(ssl->arrays->clientRandom, input + i, RAN_LEN); +#ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl)) { + ret = wc_HmacUpdate(&cookieHmac, input + i, RAN_LEN); + if (ret != 0) return ret; + } +#endif /* WOLFSSL_DTLS */ + i += RAN_LEN; + +#ifdef SHOW_SECRETS + { + int j; + printf("client random: "); + for (j = 0; j < RAN_LEN; j++) + printf("%02x", ssl->arrays->clientRandom[j]); + printf("\n"); + } +#endif + + /* session id */ + b = input[i++]; + +#ifdef HAVE_SESSION_TICKET + if (b > 0 && b < ID_LEN) { + bogusID = 1; + WOLFSSL_MSG("Client sent bogus session id, let's allow for echo"); + } +#endif + + if (b == ID_LEN || bogusID) { + if ((i - begin) + b > helloSz) + return BUFFER_ERROR; + + XMEMCPY(ssl->arrays->sessionID, input + i, b); +#ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl)) { + ret = wc_HmacUpdate(&cookieHmac, input + i - 1, b + 1); + if (ret != 0) return ret; + } +#endif /* WOLFSSL_DTLS */ + ssl->arrays->sessionIDSz = b; + i += b; + ssl->options.resuming = 1; /* client wants to resume */ + WOLFSSL_MSG("Client wants to resume session"); + } + else if (b) { + WOLFSSL_MSG("Invalid session ID size"); + return BUFFER_ERROR; /* session ID nor 0 neither 32 bytes long */ + } + + #ifdef WOLFSSL_DTLS + /* cookie */ + if (ssl->options.dtls) { + + if ((i - begin) + OPAQUE8_LEN > helloSz) + return BUFFER_ERROR; + + peerCookieSz = input[i++]; + + if (peerCookieSz) { + if (peerCookieSz > MAX_COOKIE_LEN) + return BUFFER_ERROR; + + if ((i - begin) + peerCookieSz > helloSz) + return BUFFER_ERROR; + + XMEMCPY(peerCookie, input + i, peerCookieSz); + + i += peerCookieSz; + } + } + #endif + + /* suites */ + if ((i - begin) + OPAQUE16_LEN > helloSz) + return BUFFER_ERROR; + + ato16(&input[i], &clSuites.suiteSz); + i += OPAQUE16_LEN; + + /* suites and compression length check */ + if ((i - begin) + clSuites.suiteSz + OPAQUE8_LEN > helloSz) + return BUFFER_ERROR; + + if (clSuites.suiteSz > WOLFSSL_MAX_SUITE_SZ) + return BUFFER_ERROR; + + XMEMCPY(clSuites.suites, input + i, clSuites.suiteSz); + +#ifdef HAVE_SERVER_RENEGOTIATION_INFO + /* check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV suite */ + if (FindSuite(&clSuites, 0, TLS_EMPTY_RENEGOTIATION_INFO_SCSV) >= 0) { + TLSX* extension; + + /* check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV suite */ + ret = TLSX_AddEmptyRenegotiationInfo(&ssl->extensions, ssl->heap); + if (ret != WOLFSSL_SUCCESS) + return ret; + + extension = TLSX_Find(ssl->extensions, TLSX_RENEGOTIATION_INFO); + if (extension) { + ssl->secure_renegotiation = + (SecureRenegotiation*)extension->data; + ssl->secure_renegotiation->enabled = 1; + } + } +#endif /* HAVE_SERVER_RENEGOTIATION_INFO */ +#if defined(HAVE_FALLBACK_SCSV) || defined(OPENSSL_ALL) + /* check for TLS_FALLBACK_SCSV suite */ + if (FindSuite(&clSuites, TLS_FALLBACK_SCSV, 0) >= 0) { + WOLFSSL_MSG("Found Fallback SCSV"); + if (ssl->ctx->method->version.minor > pv.minor) { + WOLFSSL_MSG("Client trying to connect with lesser version"); + SendAlert(ssl, alert_fatal, inappropriate_fallback); + return VERSION_ERROR; + } + } +#endif + +#ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl)) { + ret = wc_HmacUpdate(&cookieHmac, + input + i - OPAQUE16_LEN, + clSuites.suiteSz + OPAQUE16_LEN); + if (ret != 0) return ret; + } +#endif /* WOLFSSL_DTLS */ + i += clSuites.suiteSz; + clSuites.hashSigAlgoSz = 0; + + /* compression length */ + b = input[i++]; + + if ((i - begin) + b > helloSz) + return BUFFER_ERROR; + + if (b == 0) { + WOLFSSL_MSG("No compression types in list"); +#ifdef WOLFSSL_EXTRA_ALERTS + SendAlert(ssl, alert_fatal, decode_error); +#endif + return COMPRESSION_ERROR; + } + +#ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl)) { + byte newCookie[MAX_COOKIE_LEN]; + + ret = wc_HmacUpdate(&cookieHmac, input + i - 1, b + 1); + if (ret != 0) return ret; + ret = wc_HmacFinal(&cookieHmac, newCookie); + if (ret != 0) return ret; + + /* If a cookie callback is set, call it to overwrite the cookie. + * This should be deprecated. The code now calculates the cookie + * using an HMAC as expected. */ + if (ssl->ctx->CBIOCookie != NULL && + ssl->ctx->CBIOCookie(ssl, newCookie, cookieSz, + ssl->IOCB_CookieCtx) != cookieSz) { + return COOKIE_ERROR; + } + + /* Check the cookie, see if we progress the state machine. */ + if (peerCookieSz != cookieSz || + XMEMCMP(peerCookie, newCookie, cookieSz) != 0) { + + /* Send newCookie to client in a HelloVerifyRequest message + * and let the state machine alone. */ + ssl->msgsReceived.got_client_hello = 0; + ssl->keys.dtls_handshake_number = 0; + ssl->keys.dtls_expected_peer_handshake_number = 0; + *inOutIdx += helloSz; + return SendHelloVerifyRequest(ssl, newCookie, cookieSz); + } + + /* This was skipped in the DTLS case so we could handle the hello + * verify request. */ + ret = HashInput(ssl, input + *inOutIdx, helloSz); + if (ret != 0) return ret; + } +#endif /* WOLFSSL_DTLS */ + + { + /* compression match types */ + int matchNo = 0; + int matchZlib = 0; + + while (b--) { + byte comp = input[i++]; + + if (comp == NO_COMPRESSION) { + matchNo = 1; + } + if (comp == ZLIB_COMPRESSION) { + matchZlib = 1; + } + } + + if (ssl->options.usingCompression == 0 && matchNo) { + WOLFSSL_MSG("Matched No Compression"); + } else if (ssl->options.usingCompression && matchZlib) { + WOLFSSL_MSG("Matched zlib Compression"); + } else if (ssl->options.usingCompression && matchNo) { + WOLFSSL_MSG("Could only match no compression, turning off"); + ssl->options.usingCompression = 0; /* turn off */ + } else { + WOLFSSL_MSG("Could not match compression"); +#ifdef WOLFSSL_EXTRA_ALERTS + SendAlert(ssl, alert_fatal, illegal_parameter); +#endif + return COMPRESSION_ERROR; + } + } + + *inOutIdx = i; + + /* tls extensions */ + if ((i - begin) < helloSz) { +#ifdef HAVE_TLS_EXTENSIONS + #ifdef HAVE_QSH + QSH_Init(ssl); + #endif + if (TLSX_SupportExtensions(ssl)) +#else + if (IsAtLeastTLSv1_2(ssl)) +#endif + { + /* Process the hello extension. Skip unsupported. */ + word16 totalExtSz; + +#ifdef HAVE_TLS_EXTENSIONS + /* auto populate extensions supported unless user defined */ + if ((ret = TLSX_PopulateExtensions(ssl, 1)) != 0) + return ret; +#endif + + if ((i - begin) + OPAQUE16_LEN > helloSz) + return BUFFER_ERROR; + + ato16(&input[i], &totalExtSz); + i += OPAQUE16_LEN; + + if ((i - begin) + totalExtSz > helloSz) + return BUFFER_ERROR; + +#ifdef HAVE_TLS_EXTENSIONS + /* tls extensions */ + if ((ret = TLSX_Parse(ssl, (byte *) input + i, totalExtSz, + client_hello, &clSuites))) + return ret; + #ifdef WOLFSSL_TLS13 + if (TLSX_Find(ssl->extensions, + TLSX_SUPPORTED_VERSIONS) != NULL) { + WOLFSSL_MSG( + "Client attempting to connect with higher version"); + return VERSION_ERROR; + } + #endif + #if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + if((ret=SNI_Callback(ssl))) + return ret; + ssl->options.side = WOLFSSL_SERVER_END; + #endif + + i += totalExtSz; +#else + while (totalExtSz) { + word16 extId, extSz; + + if (OPAQUE16_LEN + OPAQUE16_LEN > totalExtSz) + return BUFFER_ERROR; + + ato16(&input[i], &extId); + i += OPAQUE16_LEN; + ato16(&input[i], &extSz); + i += OPAQUE16_LEN; + + if (OPAQUE16_LEN + OPAQUE16_LEN + extSz > totalExtSz) + return BUFFER_ERROR; + + if (extId == HELLO_EXT_SIG_ALGO) { + word16 hashSigAlgoSz; + + ato16(&input[i], &hashSigAlgoSz); + i += OPAQUE16_LEN; + + if (OPAQUE16_LEN + hashSigAlgoSz > extSz) + return BUFFER_ERROR; + + clSuites.hashSigAlgoSz = hashSigAlgoSz; + if (clSuites.hashSigAlgoSz > WOLFSSL_MAX_SIGALGO) { + WOLFSSL_MSG("ClientHello SigAlgo list exceeds max, " + "truncating"); + clSuites.hashSigAlgoSz = WOLFSSL_MAX_SIGALGO; + } + + XMEMCPY(clSuites.hashSigAlgo, &input[i], + clSuites.hashSigAlgoSz); + + i += hashSigAlgoSz; + } +#ifdef HAVE_EXTENDED_MASTER + else if (extId == HELLO_EXT_EXTMS) + ssl->options.haveEMS = 1; +#endif + else + i += extSz; + + totalExtSz -= OPAQUE16_LEN + OPAQUE16_LEN + extSz; + } +#endif + *inOutIdx = i; + } + else + *inOutIdx = begin + helloSz; /* skip extensions */ + } + + ssl->options.clientState = CLIENT_HELLO_COMPLETE; + ssl->options.haveSessionId = 1; + + /* ProcessOld uses same resume code */ + if (ssl->options.resuming) { + ret = HandleTlsResumption(ssl, bogusID, &clSuites); + if (ret != 0) + return ret; + + #ifdef HAVE_SECURE_RENEGOTIATION + if (ssl->secure_renegotiation && + ssl->secure_renegotiation->enabled && + IsEncryptionOn(ssl, 0)) + ssl->secure_renegotiation->startScr = 1; + #endif + + if (ssl->options.clientState == CLIENT_KEYEXCHANGE_COMPLETE) { + WOLFSSL_LEAVE("DoClientHello", ret); + WOLFSSL_END(WC_FUNC_CLIENT_HELLO_DO); + + return ret; + } + } + +#ifdef HAVE_TLS_EXTENSIONS + #if defined(HAVE_FFDHE) && defined(HAVE_SUPPORTED_CURVES) + if (TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS) != NULL) { + /* Set FFDHE parameters or clear DHE parameters if FFDH parameters + * present and no matches in the server's list. */ + ret = TLSX_SupportedFFDHE_Set(ssl); + if (ret != 0) + return ret; + } + #endif +#endif + + ret = MatchSuite(ssl, &clSuites); +#ifdef WOLFSSL_EXTRA_ALERTS + if (ret == BUFFER_ERROR) + SendAlert(ssl, alert_fatal, decode_error); + else if (ret < 0) + SendAlert(ssl, alert_fatal, handshake_failure); +#endif + +#ifdef HAVE_SECURE_RENEGOTIATION + if (ssl->secure_renegotiation && ssl->secure_renegotiation->enabled && + IsEncryptionOn(ssl, 0)) { + ssl->secure_renegotiation->startScr = 1; + } +#endif + WOLFSSL_LEAVE("DoClientHello", ret); + WOLFSSL_END(WC_FUNC_CLIENT_HELLO_DO); + + return ret; + } + + +#if (!defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519)) && \ + !defined(WOLFSSL_NO_CLIENT_AUTH) + + typedef struct DcvArgs { + byte* output; /* not allocated */ + word32 sendSz; + word16 sz; + word32 sigSz; + word32 idx; + word32 begin; + byte hashAlgo; + byte sigAlgo; + } DcvArgs; + + static void FreeDcvArgs(WOLFSSL* ssl, void* pArgs) + { + DcvArgs* args = (DcvArgs*)pArgs; + + (void)ssl; + (void)args; + } + + /* handle processing of certificate_verify (15) */ + static int DoCertificateVerify(WOLFSSL* ssl, byte* input, + word32* inOutIdx, word32 size) + { + int ret = 0; + #ifdef WOLFSSL_ASYNC_CRYPT + DcvArgs* args = (DcvArgs*)ssl->async.args; + typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1]; + (void)sizeof(args_test); + #else + DcvArgs args[1]; + #endif + + WOLFSSL_START(WC_FUNC_CERTIFICATE_VERIFY_DO); + WOLFSSL_ENTER("DoCertificateVerify"); + + #ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); + if (ret != WC_NOT_PENDING_E) { + /* Check for error */ + if (ret < 0) + goto exit_dcv; + } + else + #endif + { + /* Reset state */ + ret = 0; + ssl->options.asyncState = TLS_ASYNC_BEGIN; + XMEMSET(args, 0, sizeof(DcvArgs)); + args->hashAlgo = sha_mac; + args->sigAlgo = anonymous_sa_algo; + args->idx = *inOutIdx; + args->begin = *inOutIdx; + #ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = FreeDcvArgs; + #endif + } + + switch(ssl->options.asyncState) + { + case TLS_ASYNC_BEGIN: + { + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName(ssl, "CertificateVerify"); + if (ssl->toInfoOn) + AddLateName("CertificateVerify", &ssl->timeoutInfo); + #endif + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_BUILD; + } /* case TLS_ASYNC_BEGIN */ + FALL_THROUGH; + + case TLS_ASYNC_BUILD: + { + if (IsAtLeastTLSv1_2(ssl)) { + if ((args->idx - args->begin) + ENUM_LEN + ENUM_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_dcv); + } + + DecodeSigAlg(&input[args->idx], &args->hashAlgo, + &args->sigAlgo); + args->idx += 2; + } + #ifndef NO_RSA + else if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0) + args->sigAlgo = rsa_sa_algo; + #endif + #ifdef HAVE_ECC + else if (ssl->peerEccDsaKeyPresent) + args->sigAlgo = ecc_dsa_sa_algo; + #endif + #if defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH) + else if (ssl->peerEd25519KeyPresent) + args->sigAlgo = ed25519_sa_algo; + #endif /* HAVE_ED25519 && !NO_ED25519_CLIENT_AUTH */ + + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_dcv); + } + + ato16(input + args->idx, &args->sz); + args->idx += OPAQUE16_LEN; + + if ((args->idx - args->begin) + args->sz > size || + args->sz > ENCRYPT_LEN) { + ERROR_OUT(BUFFER_ERROR, exit_dcv); + } + + #ifdef HAVE_ECC + if (ssl->peerEccDsaKeyPresent) { + + WOLFSSL_MSG("Doing ECC peer cert verify"); + + /* make sure a default is defined */ + #if !defined(NO_SHA) + SetDigest(ssl, sha_mac); + #elif !defined(NO_SHA256) + SetDigest(ssl, sha256_mac); + #elif defined(WOLFSSL_SHA384) + SetDigest(ssl, sha384_mac); + #elif defined(WOLFSSL_SHA512) + SetDigest(ssl, sha512_mac); + #else + #error No digest enabled for ECC sig verify + #endif + + if (IsAtLeastTLSv1_2(ssl)) { + if (args->sigAlgo != ecc_dsa_sa_algo) { + WOLFSSL_MSG("Oops, peer sent ECC key but not in verify"); + } + + SetDigest(ssl, args->hashAlgo); + } + } + #endif /* HAVE_ECC */ + #if defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH) + if (ssl->peerEd25519KeyPresent) { + WOLFSSL_MSG("Doing ED25519 peer cert verify"); + if (IsAtLeastTLSv1_2(ssl) && + args->sigAlgo != ed25519_sa_algo) { + WOLFSSL_MSG( + "Oops, peer sent ED25519 key but not in verify"); + } + } + #endif /* HAVE_ED25519 && !NO_ED25519_CLIENT_AUTH */ + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_DO; + } /* case TLS_ASYNC_BUILD */ + FALL_THROUGH; + + case TLS_ASYNC_DO: + { + #ifndef NO_RSA + if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0) { + WOLFSSL_MSG("Doing RSA peer cert verify"); + + ret = RsaVerify(ssl, + input + args->idx, + args->sz, + &args->output, + args->sigAlgo, args->hashAlgo, + ssl->peerRsaKey, + #ifdef HAVE_PK_CALLBACKS + &ssl->buffers.peerRsaKey + #else + NULL + #endif + ); + if (ret >= 0) { + if (args->sigAlgo == rsa_sa_algo) + args->sendSz = ret; + else { + args->sigSz = ret; + args->sendSz = ssl->buffers.digest.length; + } + ret = 0; + } + } + #endif /* !NO_RSA */ + #ifdef HAVE_ECC + if (ssl->peerEccDsaKeyPresent) { + WOLFSSL_MSG("Doing ECC peer cert verify"); + + ret = EccVerify(ssl, + input + args->idx, args->sz, + ssl->buffers.digest.buffer, ssl->buffers.digest.length, + ssl->peerEccDsaKey, + #ifdef HAVE_PK_CALLBACKS + &ssl->buffers.peerEccDsaKey + #else + NULL + #endif + ); + } + #endif /* HAVE_ECC */ + #if defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH) + if (ssl->peerEd25519KeyPresent) { + WOLFSSL_MSG("Doing Ed25519 peer cert verify"); + + ret = Ed25519Verify(ssl, + input + args->idx, args->sz, + ssl->hsHashes->messages, ssl->hsHashes->prevLen, + ssl->peerEd25519Key, + #ifdef HAVE_PK_CALLBACKS + &ssl->buffers.peerEd25519Key + #else + NULL + #endif + ); + } + #endif /* HAVE_ED25519 && !NO_ED25519_CLIENT_AUTH */ + + #ifdef WOLFSSL_ASYNC_CRYPT + /* handle async pending */ + if (ret == WC_PENDING_E) + goto exit_dcv; + #endif + + /* Check for error */ + if (ret != 0) { + ret = SIG_VERIFY_E; + goto exit_dcv; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_VERIFY; + } /* case TLS_ASYNC_DO */ + FALL_THROUGH; + + case TLS_ASYNC_VERIFY: + { + #ifndef NO_RSA + if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0) { + if (IsAtLeastTLSv1_2(ssl)) { + #ifdef WC_RSA_PSS + if (args->sigAlgo == rsa_pss_sa_algo) { + SetDigest(ssl, args->hashAlgo); + + ret = wc_RsaPSS_CheckPadding( + ssl->buffers.digest.buffer, + ssl->buffers.digest.length, + args->output, args->sigSz, + HashAlgoToType(args->hashAlgo)); + if (ret != 0) { + ret = SIG_VERIFY_E; + goto exit_dcv; + } + } + else + #endif + { + #ifdef WOLFSSL_SMALL_STACK + byte* encodedSig = NULL; + #else + byte encodedSig[MAX_ENCODED_SIG_SZ]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, + ssl->heap, DYNAMIC_TYPE_SIGNATURE); + if (encodedSig == NULL) { + ERROR_OUT(MEMORY_E, exit_dcv); + } + #endif + + if (args->sigAlgo != rsa_sa_algo) { + WOLFSSL_MSG("Oops, peer sent RSA key but not " + "in verify"); + } + + SetDigest(ssl, args->hashAlgo); + + args->sigSz = wc_EncodeSignature(encodedSig, + ssl->buffers.digest.buffer, + ssl->buffers.digest.length, + TypeHash(args->hashAlgo)); + + if (args->sendSz != args->sigSz || !args->output || + XMEMCMP(args->output, encodedSig, + min(args->sigSz, MAX_ENCODED_SIG_SZ)) != 0) { + ret = VERIFY_CERT_ERROR; + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(encodedSig, ssl->heap, DYNAMIC_TYPE_SIGNATURE); + #endif + } + } + else { + if (args->sendSz != FINISHED_SZ || !args->output || + XMEMCMP(args->output, + &ssl->hsHashes->certHashes, FINISHED_SZ) != 0) { + ret = VERIFY_CERT_ERROR; + } + } + } + #endif /* !NO_RSA */ + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_FINALIZE; + } /* case TLS_ASYNC_VERIFY */ + FALL_THROUGH; + + case TLS_ASYNC_FINALIZE: + { + if (IsEncryptionOn(ssl, 0)) { + args->idx += ssl->keys.padSz; + } + + ssl->options.havePeerVerify = 1; + + /* Set final index */ + args->idx += args->sz; + *inOutIdx = args->idx; + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_END; + } /* case TLS_ASYNC_FINALIZE */ + + case TLS_ASYNC_END: + { + break; + } + default: + ret = INPUT_CASE_ERROR; + } /* switch(ssl->options.asyncState) */ + + exit_dcv: + + WOLFSSL_LEAVE("DoCertificateVerify", ret); + WOLFSSL_END(WC_FUNC_CERTIFICATE_VERIFY_DO); + + #ifdef WOLFSSL_ASYNC_CRYPT + /* Handle async operation */ + if (ret == WC_PENDING_E) { + /* Mark message as not received so it can process again */ + ssl->msgsReceived.got_certificate_verify = 0; + + return ret; + } + #endif /* WOLFSSL_ASYNC_CRYPT */ + #ifdef WOLFSSL_EXTRA_ALERTS + if (ret == SIG_VERIFY_E) + SendAlert(ssl, alert_fatal, decrypt_error); + else if (ret != 0) + SendAlert(ssl, alert_fatal, bad_certificate); + #endif + /* Digest is not allocated, so do this to prevent free */ + ssl->buffers.digest.buffer = NULL; + ssl->buffers.digest.length = 0; + + /* Final cleanup */ + FreeDcvArgs(ssl, args); + FreeKeyExchange(ssl); + + return ret; + } + +#endif /* (!NO_RSA || HAVE_ECC || HAVE_ED25519) && !WOLFSSL_NO_CLIENT_AUTH */ + + /* handle generation of server_hello_done (14) */ + int SendServerHelloDone(WOLFSSL* ssl) + { + byte* output; + int sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + int ret; + + WOLFSSL_START(WC_FUNC_SERVER_HELLO_DONE_SEND); + WOLFSSL_ENTER("SendServerHelloDone"); + + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) + sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + #endif + + if (IsEncryptionOn(ssl, 1)) + sendSz += MAX_MSG_EXTRA; + + /* check for available size */ + if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) + return ret; + + /* get output buffer */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + AddHeaders(output, 0, server_hello_done, ssl); + + if (IsEncryptionOn(ssl, 1)) { + byte* input; + int inputSz = HANDSHAKE_HEADER_SZ; /* build msg adds rec hdr */ + + input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + if (input == NULL) + return MEMORY_E; + + XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz); + sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, + handshake, 1, 0, 0); + XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + + if (sendSz < 0) + return sendSz; + } else { + #ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl)) { + if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) + return ret; + } + if (ssl->options.dtls) + DtlsSEQIncrement(ssl, CUR_ORDER); + #endif + ret = HashOutput(ssl, output, sendSz, 0); + if (ret != 0) + return ret; + } + + #if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) + if (ssl->hsInfoOn) + AddPacketName(ssl, "ServerHelloDone"); + if (ssl->toInfoOn) + AddPacketInfo(ssl, "ServerHelloDone", handshake, output, sendSz, + WRITE_PROTO, ssl->heap); + #endif + ssl->options.serverState = SERVER_HELLODONE_COMPLETE; + + ssl->buffers.outputBuffer.length += sendSz; + + ret = SendBuffered(ssl); + + WOLFSSL_LEAVE("SendServerHelloDone", ret); + WOLFSSL_END(WC_FUNC_SERVER_HELLO_DONE_SEND); + + return ret; + } + +#endif /* !WOLFSSL_NO_TLS12 */ + +#ifdef HAVE_SESSION_TICKET + +#define WOLFSSL_TICKET_FIXED_SZ (WOLFSSL_TICKET_NAME_SZ + \ + WOLFSSL_TICKET_IV_SZ + WOLFSSL_TICKET_MAC_SZ + LENGTH_SZ) +#define WOLFSSL_TICKET_ENC_SZ (SESSION_TICKET_LEN - WOLFSSL_TICKET_FIXED_SZ) + + /* our ticket format */ + typedef struct InternalTicket { + ProtocolVersion pv; /* version when ticket created */ + byte suite[SUITE_LEN]; /* cipher suite when created */ + byte msecret[SECRET_LEN]; /* master secret */ + word32 timestamp; /* born on */ + word16 haveEMS; /* have extended master secret */ +#ifdef WOLFSSL_TLS13 + word32 ageAdd; /* Obfuscation of age */ + word16 namedGroup; /* Named group used */ + #ifndef WOLFSSL_TLS13_DRAFT_18 + TicketNonce ticketNonce; /* Ticket nonce */ + #endif + #ifdef WOLFSSL_EARLY_DATA + word32 maxEarlyDataSz; /* Max size of early data */ + #endif +#endif + } InternalTicket; + + /* fit within SESSION_TICKET_LEN */ + typedef struct ExternalTicket { + byte key_name[WOLFSSL_TICKET_NAME_SZ]; /* key context name */ + byte iv[WOLFSSL_TICKET_IV_SZ]; /* this ticket's iv */ + byte enc_len[LENGTH_SZ]; /* encrypted length */ + byte enc_ticket[WOLFSSL_TICKET_ENC_SZ]; /* encrypted internal ticket */ + byte mac[WOLFSSL_TICKET_MAC_SZ]; /* total mac */ + /* !! if add to structure, add to TICKET_FIXED_SZ !! */ + } ExternalTicket; + + /* create a new session ticket, 0 on success */ + int CreateTicket(WOLFSSL* ssl) + { + InternalTicket it; + ExternalTicket* et = (ExternalTicket*)ssl->session.ticket; + int encLen; + int ret; + byte zeros[WOLFSSL_TICKET_MAC_SZ]; /* biggest cmp size */ + + XMEMSET(&it, 0, sizeof(it)); + + /* build internal */ + it.pv.major = ssl->version.major; + it.pv.minor = ssl->version.minor; + + it.suite[0] = ssl->options.cipherSuite0; + it.suite[1] = ssl->options.cipherSuite; + + #ifdef WOLFSSL_EARLY_DATA + it.maxEarlyDataSz = ssl->options.maxEarlyDataSz; + #endif + + if (!ssl->options.tls1_3) { + XMEMCPY(it.msecret, ssl->arrays->masterSecret, SECRET_LEN); + c32toa(LowResTimer(), (byte*)&it.timestamp); + it.haveEMS = ssl->options.haveEMS; + } + else { +#ifdef WOLFSSL_TLS13 + /* Client adds to ticket age to obfuscate. */ + ret = wc_RNG_GenerateBlock(ssl->rng, (byte*)&it.ageAdd, + sizeof(it.ageAdd)); + if (ret != 0) + return BAD_TICKET_ENCRYPT; + ssl->session.ticketAdd = it.ageAdd; + it.namedGroup = ssl->session.namedGroup; + it.timestamp = TimeNowInMilliseconds(); + /* Resumption master secret. */ + XMEMCPY(it.msecret, ssl->session.masterSecret, SECRET_LEN); + #ifndef WOLFSSL_TLS13_DRAFT_18 + XMEMCPY(&it.ticketNonce, &ssl->session.ticketNonce, + sizeof(TicketNonce)); + #endif +#endif + } + + /* build external */ + XMEMCPY(et->enc_ticket, &it, sizeof(InternalTicket)); + + /* encrypt */ + encLen = WOLFSSL_TICKET_ENC_SZ; /* max size user can use */ + ret = ssl->ctx->ticketEncCb(ssl, et->key_name, et->iv, et->mac, 1, + et->enc_ticket, sizeof(InternalTicket), + &encLen, ssl->ctx->ticketEncCtx); + if (ret == WOLFSSL_TICKET_RET_OK) { + if (encLen < (int)sizeof(InternalTicket) || + encLen > WOLFSSL_TICKET_ENC_SZ) { + WOLFSSL_MSG("Bad user ticket encrypt size"); + return BAD_TICKET_KEY_CB_SZ; + } + + /* sanity checks on encrypt callback */ + + /* internal ticket can't be the same if encrypted */ + if (XMEMCMP(et->enc_ticket, &it, sizeof(InternalTicket)) == 0) { + WOLFSSL_MSG("User ticket encrypt didn't encrypt"); + return BAD_TICKET_ENCRYPT; + } + + XMEMSET(zeros, 0, sizeof(zeros)); + + /* name */ + if (XMEMCMP(et->key_name, zeros, WOLFSSL_TICKET_NAME_SZ) == 0) { + WOLFSSL_MSG("User ticket encrypt didn't set name"); + return BAD_TICKET_ENCRYPT; + } + + /* iv */ + if (XMEMCMP(et->iv, zeros, WOLFSSL_TICKET_IV_SZ) == 0) { + WOLFSSL_MSG("User ticket encrypt didn't set iv"); + return BAD_TICKET_ENCRYPT; + } + + /* mac */ + if (XMEMCMP(et->mac, zeros, WOLFSSL_TICKET_MAC_SZ) == 0) { + WOLFSSL_MSG("User ticket encrypt didn't set mac"); + return BAD_TICKET_ENCRYPT; + } + + /* set size */ + c16toa((word16)encLen, et->enc_len); + ssl->session.ticketLen = (word16)(encLen + WOLFSSL_TICKET_FIXED_SZ); + if (encLen < WOLFSSL_TICKET_ENC_SZ) { + /* move mac up since whole enc buffer not used */ + XMEMMOVE(et->enc_ticket +encLen, et->mac,WOLFSSL_TICKET_MAC_SZ); + } + } + + return ret; + } + + + /* Parse ticket sent by client, returns callback return value */ + int DoClientTicket(WOLFSSL* ssl, const byte* input, word32 len) + { + ExternalTicket* et; + InternalTicket* it; + int ret; + int outLen; + word16 inLen; + + WOLFSSL_START(WC_FUNC_TICKET_DO); + WOLFSSL_ENTER("DoClientTicket"); + + if (len > SESSION_TICKET_LEN || + len < (word32)(sizeof(InternalTicket) + WOLFSSL_TICKET_FIXED_SZ)) { + return BAD_TICKET_MSG_SZ; + } + + et = (ExternalTicket*)input; + it = (InternalTicket*)et->enc_ticket; + + /* decrypt */ + ato16(et->enc_len, &inLen); + if (inLen > (word16)(len - WOLFSSL_TICKET_FIXED_SZ)) { + return BAD_TICKET_MSG_SZ; + } + outLen = inLen; /* may be reduced by user padding */ + ret = ssl->ctx->ticketEncCb(ssl, et->key_name, et->iv, + et->enc_ticket + inLen, 0, + et->enc_ticket, inLen, &outLen, + ssl->ctx->ticketEncCtx); + if (ret == WOLFSSL_TICKET_RET_FATAL || ret < 0) return ret; + if (outLen > (int)inLen || outLen < (int)sizeof(InternalTicket)) { + WOLFSSL_MSG("Bad user ticket decrypt len"); + return BAD_TICKET_KEY_CB_SZ; + } + + /* get master secret */ + if (ret == WOLFSSL_TICKET_RET_OK || ret == WOLFSSL_TICKET_RET_CREATE) { + if (ssl->version.minor < it->pv.minor) { + WOLFSSL_MSG("Ticket has greater version"); + return VERSION_ERROR; + } + else if (ssl->version.minor > it->pv.minor) { + if (!ssl->options.downgrade) { + WOLFSSL_MSG("Ticket has lesser version"); + return VERSION_ERROR; + } + + WOLFSSL_MSG("Downgrading protocol due to ticket"); + + if (it->pv.minor < ssl->options.minDowngrade) + return VERSION_ERROR; + ssl->version.minor = it->pv.minor; + } + + + if (!IsAtLeastTLSv1_3(ssl->version)) { + XMEMCPY(ssl->arrays->masterSecret, it->msecret, SECRET_LEN); + /* Copy the haveExtendedMasterSecret property from the ticket to + * the saved session, so the property may be checked later. */ + ssl->session.haveEMS = it->haveEMS; + #ifndef NO_RESUME_SUITE_CHECK + ssl->session.cipherSuite0 = it->suite[0]; + ssl->session.cipherSuite = it->suite[1]; + #endif + } + else { +#ifdef WOLFSSL_TLS13 + /* Restore information to renegotiate. */ + ssl->session.ticketSeen = it->timestamp; + ssl->session.ticketAdd = it->ageAdd; + ssl->session.cipherSuite0 = it->suite[0]; + ssl->session.cipherSuite = it->suite[1]; + #ifdef WOLFSSL_EARLY_DATA + ssl->session.maxEarlyDataSz = it->maxEarlyDataSz; + #endif + /* Resumption master secret. */ + XMEMCPY(ssl->session.masterSecret, it->msecret, SECRET_LEN); + #ifndef WOLFSSL_TLS13_DRAFT_18 + XMEMCPY(&ssl->session.ticketNonce, &it->ticketNonce, + sizeof(TicketNonce)); + #endif + ssl->session.namedGroup = it->namedGroup; +#endif + } + } + + WOLFSSL_LEAVE("DoClientTicket", ret); + WOLFSSL_END(WC_FUNC_TICKET_DO); + + return ret; + } + + + /* send Session Ticket */ + int SendTicket(WOLFSSL* ssl) + { + byte* output; + int ret; + int sendSz; + word32 length = SESSION_HINT_SZ + LENGTH_SZ; + word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + + WOLFSSL_START(WC_FUNC_TICKET_SEND); + WOLFSSL_ENTER("SendTicket"); + + if (ssl->options.createTicket) { + ret = CreateTicket(ssl); + if (ret != 0) return ret; + } + + length += ssl->session.ticketLen; + sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; + + if (!ssl->options.dtls) { + if (IsEncryptionOn(ssl, 1) && ssl->options.handShakeDone) + sendSz += MAX_MSG_EXTRA; + } + else { + #ifdef WOLFSSL_DTLS + sendSz += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + idx += DTLS_RECORD_EXTRA + DTLS_HANDSHAKE_EXTRA; + #endif + } + /* check for available size */ + if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) + return ret; + + /* get output buffer */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + AddHeaders(output, length, session_ticket, ssl); + + /* hint */ + c32toa(ssl->ctx->ticketHint, output + idx); + idx += SESSION_HINT_SZ; + + /* length */ + c16toa(ssl->session.ticketLen, output + idx); + idx += LENGTH_SZ; + + /* ticket */ + XMEMCPY(output + idx, ssl->session.ticket, ssl->session.ticketLen); + idx += ssl->session.ticketLen; + + if (IsEncryptionOn(ssl, 1) && ssl->options.handShakeDone) { + byte* input; + int inputSz = idx - RECORD_HEADER_SZ; /* build msg adds rec hdr */ + + input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + if (input == NULL) + return MEMORY_E; + + XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz); + sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, + handshake, 1, 0, 0); + XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + + if (sendSz < 0) + return sendSz; + } + else { + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + if ((ret = DtlsMsgPoolSave(ssl, output, sendSz)) != 0) + return ret; + + DtlsSEQIncrement(ssl, CUR_ORDER); + } + #endif + ret = HashOutput(ssl, output, sendSz, 0); + if (ret != 0) + return ret; + } + + ssl->buffers.outputBuffer.length += sendSz; + + ret = SendBuffered(ssl); + + WOLFSSL_LEAVE("SendTicket", ret); + WOLFSSL_END(WC_FUNC_TICKET_SEND); + + return ret; + } + +#endif /* HAVE_SESSION_TICKET */ + +#ifndef WOLFSSL_NO_TLS12 + +#if defined(HAVE_SECURE_RENEGOTIATION) && \ + defined(HAVE_SERVER_RENEGOTIATION_INFO) && \ + !defined(WOLFSSL_NO_SERVER) + + /* handle generation of server's hello_request (0) */ + int SendHelloRequest(WOLFSSL* ssl) + { + byte* output; + int sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + int ret; + + WOLFSSL_START(WC_FUNC_HELLO_REQUEST_SEND); + WOLFSSL_ENTER("SendHelloRequest"); + + if (IsEncryptionOn(ssl, 1)) + sendSz += MAX_MSG_EXTRA; + + /* check for available size */ + if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) + return ret; + + /* get output buffer */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + AddHeaders(output, 0, hello_request, ssl); + + if (IsEncryptionOn(ssl, 1)) { + byte* input; + int inputSz = HANDSHAKE_HEADER_SZ; /* build msg adds rec hdr */ + + input = (byte*)XMALLOC(inputSz, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + if (input == NULL) + return MEMORY_E; + + XMEMCPY(input, output + RECORD_HEADER_SZ, inputSz); + sendSz = BuildMessage(ssl, output, sendSz, input, inputSz, + handshake, 0, 0, 0); + XFREE(input, ssl->heap, DYNAMIC_TYPE_IN_BUFFER); + + if (sendSz < 0) + return sendSz; + } + + ssl->buffers.outputBuffer.length += sendSz; + + ret = SendBuffered(ssl); + + WOLFSSL_LEAVE("SendHelloRequest", ret); + WOLFSSL_END(WC_FUNC_HELLO_REQUEST_SEND); + + return ret; + } + +#endif /* HAVE_SECURE_RENEGOTIATION && HAVE_SERVER_RENEGOTIATION_INFO */ + +#ifdef WOLFSSL_DTLS + /* handle generation of DTLS hello_verify_request (3) */ + static int SendHelloVerifyRequest(WOLFSSL* ssl, + const byte* cookie, byte cookieSz) + { + byte* output; + int length = VERSION_SZ + ENUM_LEN + cookieSz; + int idx = DTLS_RECORD_HEADER_SZ + DTLS_HANDSHAKE_HEADER_SZ; + int sendSz = length + idx; + int ret; + + /* check for available size */ + if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) + return ret; + + /* get output buffer */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + /* Hello Verify Request should use the same sequence number as the + * Client Hello. */ + ssl->keys.dtls_sequence_number_hi = ssl->keys.curSeq_hi; + ssl->keys.dtls_sequence_number_lo = ssl->keys.curSeq_lo; + AddHeaders(output, length, hello_verify_request, ssl); + +#ifdef OPENSSL_EXTRA + output[idx++] = DTLS_MAJOR; + output[idx++] = DTLS_MINOR; +#else + output[idx++] = ssl->version.major; + output[idx++] = ssl->version.minor; +#endif + + output[idx++] = cookieSz; + if (cookie == NULL || cookieSz == 0) + return COOKIE_ERROR; + + XMEMCPY(output + idx, cookie, cookieSz); + +#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) + if (ssl->hsInfoOn) + AddPacketName(ssl, "HelloVerifyRequest"); + if (ssl->toInfoOn) + AddPacketInfo(ssl, "HelloVerifyRequest", handshake, output, + sendSz, WRITE_PROTO, ssl->heap); +#endif + + ssl->buffers.outputBuffer.length += sendSz; + + return SendBuffered(ssl); + } +#endif /* WOLFSSL_DTLS */ + + typedef struct DckeArgs { + byte* output; /* not allocated */ + word32 length; + word32 idx; + word32 begin; + word32 sigSz; + #ifndef NO_RSA + int lastErr; + #endif + } DckeArgs; + + static void FreeDckeArgs(WOLFSSL* ssl, void* pArgs) + { + DckeArgs* args = (DckeArgs*)pArgs; + + (void)ssl; + (void)args; + } + + /* handle processing client_key_exchange (16) */ + static int DoClientKeyExchange(WOLFSSL* ssl, byte* input, word32* inOutIdx, + word32 size) + { + int ret; + #ifdef WOLFSSL_ASYNC_CRYPT + DckeArgs* args = (DckeArgs*)ssl->async.args; + typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1]; + (void)sizeof(args_test); + #else + DckeArgs args[1]; + #endif + + (void)size; + (void)input; + + WOLFSSL_START(WC_FUNC_CLIENT_KEY_EXCHANGE_DO); + WOLFSSL_ENTER("DoClientKeyExchange"); + + #ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); + if (ret != WC_NOT_PENDING_E) { + /* Check for error */ + if (ret < 0) + goto exit_dcke; + } + else + #endif /* WOLFSSL_ASYNC_CRYPT */ + { + /* Reset state */ + ret = 0; + ssl->options.asyncState = TLS_ASYNC_BEGIN; + XMEMSET(args, 0, sizeof(DckeArgs)); + args->idx = *inOutIdx; + args->begin = *inOutIdx; + #ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = FreeDckeArgs; + #endif + } + + /* Do Client Key Exchange State Machine */ + switch(ssl->options.asyncState) + { + case TLS_ASYNC_BEGIN: + { + /* Sanity checks */ + if (ssl->options.side != WOLFSSL_SERVER_END) { + WOLFSSL_MSG("Client received client keyexchange, attack?"); + WOLFSSL_ERROR(ssl->error = SIDE_ERROR); + ERROR_OUT(WOLFSSL_FATAL_ERROR, exit_dcke); + } + + if (ssl->options.clientState < CLIENT_HELLO_COMPLETE) { + WOLFSSL_MSG("Client sending keyexchange at wrong time"); + SendAlert(ssl, alert_fatal, unexpected_message); + ERROR_OUT(OUT_OF_ORDER_E, exit_dcke); + } + + #ifndef NO_CERTS + if (ssl->options.verifyPeer && ssl->options.failNoCert) { + if (!ssl->options.havePeerCert) { + WOLFSSL_MSG("client didn't present peer cert"); + ERROR_OUT(NO_PEER_CERT, exit_dcke); + } + } + + if (ssl->options.verifyPeer && ssl->options.failNoCertxPSK) { + if (!ssl->options.havePeerCert && + !ssl->options.usingPSK_cipher) { + WOLFSSL_MSG("client didn't present peer cert"); + return NO_PEER_CERT; + } + } + #endif /* !NO_CERTS */ + + #if defined(WOLFSSL_CALLBACKS) + if (ssl->hsInfoOn) { + AddPacketName(ssl, "ClientKeyExchange"); + } + if (ssl->toInfoOn) { + AddLateName("ClientKeyExchange", &ssl->timeoutInfo); + } + #endif + + if (ssl->arrays->preMasterSecret == NULL) { + ssl->arrays->preMasterSz = ENCRYPT_LEN; + ssl->arrays->preMasterSecret = (byte*)XMALLOC(ENCRYPT_LEN, + ssl->heap, DYNAMIC_TYPE_SECRET); + if (ssl->arrays->preMasterSecret == NULL) { + ERROR_OUT(MEMORY_E, exit_dcke); + } + XMEMSET(ssl->arrays->preMasterSecret, 0, ENCRYPT_LEN); + } + + switch (ssl->specs.kea) { + #ifndef NO_RSA + case rsa_kea: + { + break; + } /* rsa_kea */ + #endif /* !NO_RSA */ + #ifndef NO_PSK + case psk_kea: + { + /* sanity check that PSK server callback has been set */ + if (ssl->options.server_psk_cb == NULL) { + WOLFSSL_MSG("No server PSK callback set"); + ERROR_OUT(PSK_KEY_ERROR, exit_dcke); + } + break; + } + #endif /* !NO_PSK */ + #ifdef HAVE_NTRU + case ntru_kea: + { + /* make sure private key exists */ + if (ssl->buffers.key == NULL || + ssl->buffers.key->buffer == NULL) { + ERROR_OUT(NO_PRIVATE_KEY, exit_dcke); + } + break; + } + #endif /* HAVE_NTRU */ + #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) + case ecc_diffie_hellman_kea: + { + break; + } + #endif /* HAVE_ECC || HAVE_CURVE25519 */ + #ifndef NO_DH + case diffie_hellman_kea: + { + break; + } + #endif /* !NO_DH */ + #if !defined(NO_DH) && !defined(NO_PSK) + case dhe_psk_kea: + { + /* sanity check that PSK server callback has been set */ + if (ssl->options.server_psk_cb == NULL) { + WOLFSSL_MSG("No server PSK callback set"); + ERROR_OUT(PSK_KEY_ERROR, exit_dcke); + } + break; + } + #endif /* !NO_DH && !NO_PSK */ + #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \ + !defined(NO_PSK) + case ecdhe_psk_kea: + { + /* sanity check that PSK server callback has been set */ + if (ssl->options.server_psk_cb == NULL) { + WOLFSSL_MSG("No server PSK callback set"); + ERROR_OUT(PSK_KEY_ERROR, exit_dcke); + } + break; + } + #endif /* (HAVE_ECC || HAVE_CURVE25519) && !NO_PSK */ + default: + WOLFSSL_MSG("Bad kea type"); + ret = BAD_KEA_TYPE_E; + } /* switch (ssl->specs.kea) */ + + /* Check for error */ + if (ret != 0) { + goto exit_dcke; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_BUILD; + } /* TLS_ASYNC_BEGIN */ + FALL_THROUGH; + + case TLS_ASYNC_BUILD: + { + switch (ssl->specs.kea) { + #ifndef NO_RSA + case rsa_kea: + { + word16 keySz; + + ssl->buffers.keyType = rsa_sa_algo; + ret = DecodePrivateKey(ssl, &keySz); + if (ret != 0) { + goto exit_dcke; + } + args->length = (word32)keySz; + ssl->arrays->preMasterSz = SECRET_LEN; + + if (ssl->options.tls) { + word16 check; + + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_dcke); + } + + ato16(input + args->idx, &check); + args->idx += OPAQUE16_LEN; + + if ((word32)check != args->length) { + WOLFSSL_MSG("RSA explicit size doesn't match"); + #ifdef WOLFSSL_EXTRA_ALERTS + SendAlert(ssl, alert_fatal, bad_record_mac); + #endif + ERROR_OUT(RSA_PRIVATE_ERROR, exit_dcke); + } + } + + if ((args->idx - args->begin) + args->length > size) { + WOLFSSL_MSG("RSA message too big"); + ERROR_OUT(BUFFER_ERROR, exit_dcke); + } + + /* pre-load PreMasterSecret with RNG data */ + ret = wc_RNG_GenerateBlock(ssl->rng, + &ssl->arrays->preMasterSecret[VERSION_SZ], + SECRET_LEN - VERSION_SZ); + if (ret != 0) { + goto exit_dcke; + } + + args->output = NULL; + break; + } /* rsa_kea */ + #endif /* !NO_RSA */ + #ifndef NO_PSK + case psk_kea: + { + byte* pms = ssl->arrays->preMasterSecret; + word16 ci_sz; + + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_dcke); + } + + ato16(input + args->idx, &ci_sz); + args->idx += OPAQUE16_LEN; + + if (ci_sz > MAX_PSK_ID_LEN) { + ERROR_OUT(CLIENT_ID_ERROR, exit_dcke); + } + + if ((args->idx - args->begin) + ci_sz > size) { + ERROR_OUT(BUFFER_ERROR, exit_dcke); + } + + XMEMCPY(ssl->arrays->client_identity, + input + args->idx, ci_sz); + args->idx += ci_sz; + + ssl->arrays->client_identity[ci_sz] = '\0'; /* null term */ + ssl->arrays->psk_keySz = ssl->options.server_psk_cb(ssl, + ssl->arrays->client_identity, ssl->arrays->psk_key, + MAX_PSK_KEY_LEN); + + if (ssl->arrays->psk_keySz == 0 || + ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) { + ERROR_OUT(PSK_KEY_ERROR, exit_dcke); + } + + /* make psk pre master secret */ + /* length of key + length 0s + length of key + key */ + c16toa((word16) ssl->arrays->psk_keySz, pms); + pms += OPAQUE16_LEN; + + XMEMSET(pms, 0, ssl->arrays->psk_keySz); + pms += ssl->arrays->psk_keySz; + + c16toa((word16) ssl->arrays->psk_keySz, pms); + pms += OPAQUE16_LEN; + + XMEMCPY(pms, ssl->arrays->psk_key, ssl->arrays->psk_keySz); + ssl->arrays->preMasterSz = + (ssl->arrays->psk_keySz * 2) + (OPAQUE16_LEN * 2); + break; + } + #endif /* !NO_PSK */ + #ifdef HAVE_NTRU + case ntru_kea: + { + word16 cipherLen; + word16 plainLen = ENCRYPT_LEN; + + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_dcke); + } + + ato16(input + args->idx, &cipherLen); + args->idx += OPAQUE16_LEN; + + if (cipherLen > MAX_NTRU_ENCRYPT_SZ) { + ERROR_OUT(NTRU_KEY_ERROR, exit_dcke); + } + + if ((args->idx - args->begin) + cipherLen > size) { + ERROR_OUT(BUFFER_ERROR, exit_dcke); + } + + if (NTRU_OK != ntru_crypto_ntru_decrypt( + (word16) ssl->buffers.key->length, + ssl->buffers.key->buffer, cipherLen, + input + args->idx, &plainLen, + ssl->arrays->preMasterSecret)) { + ERROR_OUT(NTRU_DECRYPT_ERROR, exit_dcke); + } + + if (plainLen != SECRET_LEN) { + ERROR_OUT(NTRU_DECRYPT_ERROR, exit_dcke); + } + + args->idx += cipherLen; + ssl->arrays->preMasterSz = plainLen; + break; + } + #endif /* HAVE_NTRU */ + #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) + case ecc_diffie_hellman_kea: + { + #ifdef HAVE_ECC + ecc_key* private_key = ssl->eccTempKey; + + /* handle static private key */ + if (ssl->specs.static_ecdh && + ssl->ecdhCurveOID != ECC_X25519_OID) { + word16 keySz; + + ssl->buffers.keyType = ecc_dsa_sa_algo; + ret = DecodePrivateKey(ssl, &keySz); + if (ret != 0) { + goto exit_dcke; + } + private_key = (ecc_key*)ssl->hsKey; + } + #endif + + /* import peer ECC key */ + if ((args->idx - args->begin) + OPAQUE8_LEN > size) { + #ifdef WOLFSSL_EXTRA_ALERTS + SendAlert(ssl, alert_fatal, decode_error); + #endif + ERROR_OUT(BUFFER_ERROR, exit_dcke); + } + + args->length = input[args->idx++]; + + if ((args->idx - args->begin) + args->length > size) { + #ifdef WOLFSSL_EXTRA_ALERTS + SendAlert(ssl, alert_fatal, decode_error); + #endif + ERROR_OUT(BUFFER_ERROR, exit_dcke); + } + + #ifdef HAVE_CURVE25519 + if (ssl->ecdhCurveOID == ECC_X25519_OID) { + #ifdef HAVE_PK_CALLBACKS + /* if callback then use it for shared secret */ + if (ssl->ctx->X25519SharedSecretCb != NULL) { + break; + } + #endif + if (ssl->peerX25519Key == NULL) { + /* alloc/init on demand */ + ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE25519, + (void**)&ssl->peerX25519Key); + if (ret != 0) { + goto exit_dcke; + } + } else if (ssl->peerX25519KeyPresent) { + ret = ReuseKey(ssl, DYNAMIC_TYPE_CURVE25519, + ssl->peerX25519Key); + ssl->peerX25519KeyPresent = 0; + if (ret != 0) { + goto exit_dcke; + } + } + + if (wc_curve25519_import_public_ex( + input + args->idx, args->length, + ssl->peerX25519Key, + EC25519_LITTLE_ENDIAN)) { + #ifdef WOLFSSL_EXTRA_ALERTS + SendAlert(ssl, alert_fatal, illegal_parameter); + #endif + ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke); + } + + ssl->arrays->preMasterSz = CURVE25519_KEYSIZE; + + ssl->peerX25519KeyPresent = 1; + + break; + } + #endif + #ifdef HAVE_ECC + #ifdef HAVE_PK_CALLBACKS + /* if callback then use it for shared secret */ + if (ssl->ctx->EccSharedSecretCb != NULL) { + break; + } + #endif + + if (!ssl->specs.static_ecdh && + ssl->eccTempKeyPresent == 0) { + WOLFSSL_MSG("Ecc ephemeral key not made correctly"); + ERROR_OUT(ECC_MAKEKEY_ERROR, exit_dcke); + } + + if (ssl->peerEccKey == NULL) { + /* alloc/init on demand */ + ret = AllocKey(ssl, DYNAMIC_TYPE_ECC, + (void**)&ssl->peerEccKey); + if (ret != 0) { + goto exit_dcke; + } + } else if (ssl->peerEccKeyPresent) { + ret = ReuseKey(ssl, DYNAMIC_TYPE_ECC, + ssl->peerEccKey); + ssl->peerEccKeyPresent = 0; + if (ret != 0) { + goto exit_dcke; + } + } + + if (wc_ecc_import_x963_ex(input + args->idx, args->length, + ssl->peerEccKey, private_key->dp->id)) { + ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke); + } + + ssl->arrays->preMasterSz = private_key->dp->size; + + ssl->peerEccKeyPresent = 1; + #endif /* HAVE_ECC */ + + break; + } + #endif /* HAVE_ECC || HAVE_CURVE25519 */ + #ifndef NO_DH + case diffie_hellman_kea: + { + word16 clientPubSz; + + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_dcke); + } + + ato16(input + args->idx, &clientPubSz); + args->idx += OPAQUE16_LEN; + + if ((args->idx - args->begin) + clientPubSz > size) { + #ifdef WOLFSSL_EXTRA_ALERTS + SendAlert(ssl, alert_fatal, decode_error); + #endif + ERROR_OUT(BUFFER_ERROR, exit_dcke); + } + + args->sigSz = clientPubSz; + + ret = AllocKey(ssl, DYNAMIC_TYPE_DH, + (void**)&ssl->buffers.serverDH_Key); + if (ret != 0) { + goto exit_dcke; + } + + ret = wc_DhSetKey(ssl->buffers.serverDH_Key, + ssl->buffers.serverDH_P.buffer, + ssl->buffers.serverDH_P.length, + ssl->buffers.serverDH_G.buffer, + ssl->buffers.serverDH_G.length); + + /* set the max agree result size */ + ssl->arrays->preMasterSz = ENCRYPT_LEN; + break; + } + #endif /* !NO_DH */ + #if !defined(NO_DH) && !defined(NO_PSK) + case dhe_psk_kea: + { + word16 clientSz; + + /* Read in the PSK hint */ + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_dcke); + } + + ato16(input + args->idx, &clientSz); + args->idx += OPAQUE16_LEN; + if (clientSz > MAX_PSK_ID_LEN) { + ERROR_OUT(CLIENT_ID_ERROR, exit_dcke); + } + + if ((args->idx - args->begin) + clientSz > size) { + ERROR_OUT(BUFFER_ERROR, exit_dcke); + } + + XMEMCPY(ssl->arrays->client_identity, input + args->idx, + clientSz); + args->idx += clientSz; + ssl->arrays->client_identity[clientSz] = '\0'; /* null term */ + + /* Read in the DHE business */ + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_dcke); + } + + ato16(input + args->idx, &clientSz); + args->idx += OPAQUE16_LEN; + + if ((args->idx - args->begin) + clientSz > size) { + ERROR_OUT(BUFFER_ERROR, exit_dcke); + } + + args->sigSz = clientSz; + + ret = AllocKey(ssl, DYNAMIC_TYPE_DH, + (void**)&ssl->buffers.serverDH_Key); + if (ret != 0) { + goto exit_dcke; + } + + ret = wc_DhSetKey(ssl->buffers.serverDH_Key, + ssl->buffers.serverDH_P.buffer, + ssl->buffers.serverDH_P.length, + ssl->buffers.serverDH_G.buffer, + ssl->buffers.serverDH_G.length); + + break; + } + #endif /* !NO_DH && !NO_PSK */ + #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \ + !defined(NO_PSK) + case ecdhe_psk_kea: + { + word16 clientSz; + + /* Read in the PSK hint */ + if ((args->idx - args->begin) + OPAQUE16_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_dcke); + } + + ato16(input + args->idx, &clientSz); + args->idx += OPAQUE16_LEN; + if (clientSz > MAX_PSK_ID_LEN) { + ERROR_OUT(CLIENT_ID_ERROR, exit_dcke); + } + if ((args->idx - args->begin) + clientSz > size) { + ERROR_OUT(BUFFER_ERROR, exit_dcke); + } + + XMEMCPY(ssl->arrays->client_identity, + input + args->idx, clientSz); + args->idx += clientSz; + ssl->arrays->client_identity[clientSz] = '\0'; /* null term */ + + /* import peer ECC key */ + if ((args->idx - args->begin) + OPAQUE8_LEN > size) { + ERROR_OUT(BUFFER_ERROR, exit_dcke); + } + + args->length = input[args->idx++]; + + if ((args->idx - args->begin) + args->length > size) { + ERROR_OUT(BUFFER_ERROR, exit_dcke); + } + + args->sigSz = ENCRYPT_LEN - OPAQUE16_LEN; + + #ifdef HAVE_CURVE25519 + if (ssl->ecdhCurveOID == ECC_X25519_OID) { + #ifdef HAVE_PK_CALLBACKS + /* if callback then use it for shared secret */ + if (ssl->ctx->X25519SharedSecretCb != NULL) { + break; + } + #endif + + if (ssl->eccTempKeyPresent == 0) { + WOLFSSL_MSG( + "X25519 ephemeral key not made correctly"); + ERROR_OUT(ECC_MAKEKEY_ERROR, exit_dcke); + } + + if (ssl->peerX25519Key == NULL) { + /* alloc/init on demand */ + ret = AllocKey(ssl, DYNAMIC_TYPE_CURVE25519, + (void**)&ssl->peerX25519Key); + if (ret != 0) { + goto exit_dcke; + } + } else if (ssl->peerX25519KeyPresent) { + ret = ReuseKey(ssl, DYNAMIC_TYPE_CURVE25519, + ssl->peerX25519Key); + ssl->peerX25519KeyPresent = 0; + if (ret != 0) { + goto exit_dcke; + } + } + + if (wc_curve25519_import_public_ex( + input + args->idx, args->length, + ssl->peerX25519Key, + EC25519_LITTLE_ENDIAN)) { + ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke); + } + + ssl->peerX25519KeyPresent = 1; + + break; + } + #endif + #ifdef HAVE_PK_CALLBACKS + /* if callback then use it for shared secret */ + if (ssl->ctx->EccSharedSecretCb != NULL) { + break; + } + #endif + + if (ssl->eccTempKeyPresent == 0) { + WOLFSSL_MSG("Ecc ephemeral key not made correctly"); + ERROR_OUT(ECC_MAKEKEY_ERROR, exit_dcke); + } + + if (ssl->peerEccKey == NULL) { + /* alloc/init on demand */ + ret = AllocKey(ssl, DYNAMIC_TYPE_ECC, + (void**)&ssl->peerEccKey); + if (ret != 0) { + goto exit_dcke; + } + } + else if (ssl->peerEccKeyPresent) { + ret = ReuseKey(ssl, DYNAMIC_TYPE_ECC, + ssl->peerEccKey); + ssl->peerEccKeyPresent = 0; + if (ret != 0) { + goto exit_dcke; + } + } + if (wc_ecc_import_x963_ex(input + args->idx, args->length, + ssl->peerEccKey, ssl->eccTempKey->dp->id)) { + ERROR_OUT(ECC_PEERKEY_ERROR, exit_dcke); + } + + ssl->peerEccKeyPresent = 1; + break; + } + #endif /* (HAVE_ECC || HAVE_CURVE25519) && !NO_PSK */ + default: + ret = BAD_KEA_TYPE_E; + } /* switch (ssl->specs.kea) */ + + /* Check for error */ + if (ret != 0) { + goto exit_dcke; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_DO; + } /* TLS_ASYNC_BUILD */ + FALL_THROUGH; + + case TLS_ASYNC_DO: + { + switch (ssl->specs.kea) { + #ifndef NO_RSA + case rsa_kea: + { + RsaKey* key = (RsaKey*)ssl->hsKey; + + ret = RsaDec(ssl, + input + args->idx, + args->length, + &args->output, + &args->sigSz, + key, + #ifdef HAVE_PK_CALLBACKS + ssl->buffers.key + #else + NULL + #endif + ); + + /* Errors that can occur here that should be + * indistinguishable: + * RSA_BUFFER_E, RSA_PAD_E and RSA_PRIVATE_ERROR + */ + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) + goto exit_dcke; + #endif + if (ret == BAD_FUNC_ARG) + goto exit_dcke; + + args->lastErr = ret - (SECRET_LEN - args->sigSz); + ret = 0; + break; + } /* rsa_kea */ + #endif /* !NO_RSA */ + #ifndef NO_PSK + case psk_kea: + { + break; + } + #endif /* !NO_PSK */ + #ifdef HAVE_NTRU + case ntru_kea: + { + break; + } + #endif /* HAVE_NTRU */ + #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) + case ecc_diffie_hellman_kea: + { + void* private_key = ssl->eccTempKey; + (void)private_key; + + #ifdef HAVE_CURVE25519 + if (ssl->ecdhCurveOID == ECC_X25519_OID) { + ret = X25519SharedSecret(ssl, + (curve25519_key*)private_key, + ssl->peerX25519Key, + input + args->idx, &args->length, + ssl->arrays->preMasterSecret, + &ssl->arrays->preMasterSz, + WOLFSSL_SERVER_END + ); + break; + } + #endif + #ifdef HAVE_ECC + if (ssl->specs.static_ecdh) { + private_key = ssl->hsKey; + } + + /* Generate shared secret */ + ret = EccSharedSecret(ssl, + (ecc_key*)private_key, ssl->peerEccKey, + input + args->idx, &args->length, + ssl->arrays->preMasterSecret, + &ssl->arrays->preMasterSz, + WOLFSSL_SERVER_END + ); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret != WC_PENDING_E) + #endif + { + FreeKey(ssl, DYNAMIC_TYPE_ECC, + (void**)&ssl->peerEccKey); + ssl->peerEccKeyPresent = 0; + } + #endif + break; + } + #endif /* HAVE_ECC || HAVE_CURVE25519 */ + #ifndef NO_DH + case diffie_hellman_kea: + { + ret = DhAgree(ssl, ssl->buffers.serverDH_Key, + ssl->buffers.serverDH_Priv.buffer, + ssl->buffers.serverDH_Priv.length, + input + args->idx, + (word16)args->sigSz, + ssl->arrays->preMasterSecret, + &ssl->arrays->preMasterSz); + break; + } + #endif /* !NO_DH */ + #if !defined(NO_DH) && !defined(NO_PSK) + case dhe_psk_kea: + { + ret = DhAgree(ssl, ssl->buffers.serverDH_Key, + ssl->buffers.serverDH_Priv.buffer, + ssl->buffers.serverDH_Priv.length, + input + args->idx, + (word16)args->sigSz, + ssl->arrays->preMasterSecret + OPAQUE16_LEN, + &ssl->arrays->preMasterSz); + break; + } + #endif /* !NO_DH && !NO_PSK */ + #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \ + !defined(NO_PSK) + case ecdhe_psk_kea: + { + #ifdef HAVE_CURVE25519 + if (ssl->ecdhCurveOID == ECC_X25519_OID) { + ret = X25519SharedSecret(ssl, + (curve25519_key*)ssl->eccTempKey, + ssl->peerX25519Key, + input + args->idx, &args->length, + ssl->arrays->preMasterSecret + OPAQUE16_LEN, + &args->sigSz, + WOLFSSL_SERVER_END + ); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret != WC_PENDING_E) + #endif + { + FreeKey(ssl, DYNAMIC_TYPE_CURVE25519, + (void**)&ssl->peerX25519Key); + ssl->peerX25519KeyPresent = 0; + } + break; + } + #endif + /* Generate shared secret */ + ret = EccSharedSecret(ssl, + ssl->eccTempKey, ssl->peerEccKey, + input + args->idx, &args->length, + ssl->arrays->preMasterSecret + OPAQUE16_LEN, + &args->sigSz, + WOLFSSL_SERVER_END + ); + if (!ssl->specs.static_ecdh + #ifdef WOLFSSL_ASYNC_CRYPT + && ret != WC_PENDING_E + #endif + ) { + FreeKey(ssl, DYNAMIC_TYPE_ECC, + (void**)&ssl->peerEccKey); + ssl->peerEccKeyPresent = 0; + } + break; + } + #endif /* (HAVE_ECC || HAVE_CURVE25519) && !NO_PSK */ + default: + ret = BAD_KEA_TYPE_E; + } /* switch (ssl->specs.kea) */ + + /* Check for error */ + if (ret != 0) { + goto exit_dcke; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_VERIFY; + } /* TLS_ASYNC_DO */ + FALL_THROUGH; + + case TLS_ASYNC_VERIFY: + { + switch (ssl->specs.kea) { + #ifndef NO_RSA + case rsa_kea: + { + byte mask; + int i; + + /* Add the signature length to idx */ + args->idx += args->length; + + #ifdef DEBUG_WOLFSSL + /* check version (debug warning message only) */ + if (args->output != NULL) { + if (args->output[0] != ssl->chVersion.major || + args->output[1] != ssl->chVersion.minor) { + WOLFSSL_MSG("preMasterSecret version mismatch"); + } + } + #endif + + /* RFC5246 7.4.7.1: + * Treat incorrectly formatted message blocks and/or + * mismatched version numbers in a manner + * indistinguishable from correctly formatted RSA blocks + */ + + ret = args->lastErr; + args->lastErr = 0; /* reset */ + /* On error 'ret' will be negative - top bit set */ + mask = (ret >> ((sizeof(ret) * 8) - 1)) - 1; + + /* build PreMasterSecret */ + ssl->arrays->preMasterSecret[0] = ssl->chVersion.major; + ssl->arrays->preMasterSecret[1] = ssl->chVersion.minor; + + if (args->output != NULL) { + /* Use random secret on error */ + for (i = VERSION_SZ; i < SECRET_LEN; i++) { + ssl->arrays->preMasterSecret[i] = + ctMaskSel(mask, args->output[i], + ssl->arrays->preMasterSecret[i]); + } + } + /* preMasterSecret has RNG and version set + * return proper length and ignore error + * error will be caught as decryption error + */ + args->sigSz = SECRET_LEN; + ret = 0; + break; + } /* rsa_kea */ + #endif /* !NO_RSA */ + #ifndef NO_PSK + case psk_kea: + { + break; + } + #endif /* !NO_PSK */ + #ifdef HAVE_NTRU + case ntru_kea: + { + break; + } + #endif /* HAVE_NTRU */ + #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) + case ecc_diffie_hellman_kea: + { + /* skip past the imported peer key */ + args->idx += args->length; + break; + } + #endif /* HAVE_ECC || HAVE_CURVE25519 */ + #ifndef NO_DH + case diffie_hellman_kea: + { + args->idx += (word16)args->sigSz; + break; + } + #endif /* !NO_DH */ + #if !defined(NO_DH) && !defined(NO_PSK) + case dhe_psk_kea: + { + byte* pms = ssl->arrays->preMasterSecret; + word16 clientSz = (word16)args->sigSz; + + args->idx += clientSz; + c16toa((word16)ssl->arrays->preMasterSz, pms); + ssl->arrays->preMasterSz += OPAQUE16_LEN; + pms += ssl->arrays->preMasterSz; + + /* Use the PSK hint to look up the PSK and add it to the + * preMasterSecret here. */ + ssl->arrays->psk_keySz = ssl->options.server_psk_cb(ssl, + ssl->arrays->client_identity, ssl->arrays->psk_key, + MAX_PSK_KEY_LEN); + + if (ssl->arrays->psk_keySz == 0 || + ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) { + ERROR_OUT(PSK_KEY_ERROR, exit_dcke); + } + + c16toa((word16) ssl->arrays->psk_keySz, pms); + pms += OPAQUE16_LEN; + + XMEMCPY(pms, ssl->arrays->psk_key, + ssl->arrays->psk_keySz); + ssl->arrays->preMasterSz += ssl->arrays->psk_keySz + + OPAQUE16_LEN; + break; + } + #endif /* !NO_DH && !NO_PSK */ + #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \ + !defined(NO_PSK) + case ecdhe_psk_kea: + { + byte* pms = ssl->arrays->preMasterSecret; + word16 clientSz = (word16)args->sigSz; + + /* skip past the imported peer key */ + args->idx += args->length; + + /* Add preMasterSecret */ + c16toa(clientSz, pms); + ssl->arrays->preMasterSz = OPAQUE16_LEN + clientSz; + pms += ssl->arrays->preMasterSz; + + /* Use the PSK hint to look up the PSK and add it to the + * preMasterSecret here. */ + ssl->arrays->psk_keySz = ssl->options.server_psk_cb(ssl, + ssl->arrays->client_identity, ssl->arrays->psk_key, + MAX_PSK_KEY_LEN); + + if (ssl->arrays->psk_keySz == 0 || + ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) { + ERROR_OUT(PSK_KEY_ERROR, exit_dcke); + } + + c16toa((word16) ssl->arrays->psk_keySz, pms); + pms += OPAQUE16_LEN; + + XMEMCPY(pms, ssl->arrays->psk_key, ssl->arrays->psk_keySz); + ssl->arrays->preMasterSz += + ssl->arrays->psk_keySz + OPAQUE16_LEN; + break; + } + #endif /* (HAVE_ECC || HAVE_CURVE25519) && !NO_PSK */ + default: + ret = BAD_KEA_TYPE_E; + } /* switch (ssl->specs.kea) */ + + /* Check for error */ + if (ret != 0) { + goto exit_dcke; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_FINALIZE; + } /* TLS_ASYNC_VERIFY */ + FALL_THROUGH; + + case TLS_ASYNC_FINALIZE: + { + if (IsEncryptionOn(ssl, 0)) { + args->idx += ssl->keys.padSz; + } + + #ifdef HAVE_QSH + word16 name; + + if (ssl->options.haveQSH) { + /* extension name */ + ato16(input + args->idx, &name); + args->idx += OPAQUE16_LEN; + + if (name == TLSX_QUANTUM_SAFE_HYBRID) { + int qshSz; + /* if qshSz is larger than 0 it is the + length of buffer used */ + if ((qshSz = TLSX_QSHCipher_Parse(ssl, + input + args->idx, + size - args->idx + args->begin, 1)) < 0) { + ERROR_OUT(qshSz, exit_dcke); + } + args->idx += qshSz; + } + else { + /* unknown extension sent client ignored handshake */ + ERROR_OUT(BUFFER_ERROR, exit_dcke); + } + } + #endif /* HAVE_QSH */ + ret = MakeMasterSecret(ssl); + + /* Check for error */ + if (ret != 0) { + goto exit_dcke; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_END; + } /* TLS_ASYNC_FINALIZE */ + FALL_THROUGH; + + case TLS_ASYNC_END: + { + /* Set final index */ + *inOutIdx = args->idx; + + ssl->options.clientState = CLIENT_KEYEXCHANGE_COMPLETE; + #ifndef NO_CERTS + if (ssl->options.verifyPeer) { + ret = BuildCertHashes(ssl, &ssl->hsHashes->certHashes); + } + #endif + break; + } /* TLS_ASYNC_END */ + default: + ret = INPUT_CASE_ERROR; + } /* switch(ssl->options.asyncState) */ + + exit_dcke: + + WOLFSSL_LEAVE("DoClientKeyExchange", ret); + WOLFSSL_END(WC_FUNC_CLIENT_KEY_EXCHANGE_DO); + + #ifdef WOLFSSL_ASYNC_CRYPT + /* Handle async operation */ + if (ret == WC_PENDING_E) { + /* Mark message as not received so it can process again */ + ssl->msgsReceived.got_client_key_exchange = 0; + + return ret; + } + #endif /* WOLFSSL_ASYNC_CRYPT */ + + /* Cleanup PMS */ + if (ssl->arrays->preMasterSecret != NULL) { + ForceZero(ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz); + } + ssl->arrays->preMasterSz = 0; + + /* Final cleanup */ + FreeDckeArgs(ssl, args); + FreeKeyExchange(ssl); + + return ret; + } + +#endif /* !WOLFSSL_NO_TLS12 */ + +#if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \ + defined(WOLFSSL_HAPROXY) + int SNI_Callback(WOLFSSL* ssl) + { + /* Stunnel supports a custom sni callback to switch an SSL's ctx + * when SNI is received. Call it now if exists */ + if(ssl && ssl->ctx && ssl->ctx->sniRecvCb) { + WOLFSSL_MSG("Calling custom sni callback"); + if(ssl->ctx->sniRecvCb(ssl, NULL, ssl->ctx->sniRecvCbArg) + == alert_fatal) { + WOLFSSL_MSG("Error in custom sni callback. Fatal alert"); + SendAlert(ssl, alert_fatal, unrecognized_name); + return FATAL_ERROR; + } + } + return 0; + } +#endif /* OPENSSL_ALL || HAVE_STUNNEL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */ + +#endif /* NO_WOLFSSL_SERVER */ + + +#ifdef WOLFSSL_ASYNC_CRYPT +int wolfSSL_AsyncPop(WOLFSSL* ssl, byte* state) +{ + int ret = 0; + WC_ASYNC_DEV* asyncDev; + WOLF_EVENT* event; + + if (ssl == NULL) { + return BAD_FUNC_ARG; + } + + /* check for pending async */ + asyncDev = ssl->async.dev; + if (asyncDev) { + /* grab event pointer */ + event = &asyncDev->event; + + ret = wolfAsync_EventPop(event, WOLF_EVENT_TYPE_ASYNC_WOLFSSL); + if (ret != WC_NOT_PENDING_E && ret != WC_PENDING_E) { + + /* advance key share state if doesn't need called again */ + if (state && (asyncDev->event.flags & WC_ASYNC_FLAG_CALL_AGAIN) == 0) { + (*state)++; + } + + /* clear event */ + XMEMSET(&asyncDev->event, 0, sizeof(WOLF_EVENT)); + + /* clear async dev */ + ssl->async.dev = NULL; + } + } + else { + ret = WC_NOT_PENDING_E; + } + + WOLFSSL_LEAVE("wolfSSL_AsyncPop", ret); + + return ret; +} + +int wolfSSL_AsyncInit(WOLFSSL* ssl, WC_ASYNC_DEV* asyncDev, word32 flags) +{ + int ret; + WOLF_EVENT* event; + + if (ssl == NULL || asyncDev == NULL) { + return BAD_FUNC_ARG; + } + + /* grab event pointer */ + event = &asyncDev->event; + + /* init event */ + ret = wolfAsync_EventInit(event, WOLF_EVENT_TYPE_ASYNC_WOLFSSL, ssl, flags); + + WOLFSSL_LEAVE("wolfSSL_AsyncInit", ret); + + return ret; +} + +int wolfSSL_AsyncPush(WOLFSSL* ssl, WC_ASYNC_DEV* asyncDev) +{ + int ret; + WOLF_EVENT* event; + + if (ssl == NULL || asyncDev == NULL) { + return BAD_FUNC_ARG; + } + + /* grab event pointer */ + event = &asyncDev->event; + + /* store reference to active async operation */ + ssl->async.dev = asyncDev; + + /* place event into queue */ + ret = wolfAsync_EventQueuePush(&ssl->ctx->event_queue, event); + + /* success means return WC_PENDING_E */ + if (ret == 0) { + ret = WC_PENDING_E; + } + + WOLFSSL_LEAVE("wolfSSL_AsyncPush", ret); + + return ret; +} + +#endif /* WOLFSSL_ASYNC_CRYPT */ + + +/* return the max record size */ +int wolfSSL_GetMaxRecordSize(WOLFSSL* ssl, int maxFragment) +{ + (void) ssl; /* Avoid compiler warnings */ + + if (maxFragment > MAX_RECORD_SIZE) { + maxFragment = MAX_RECORD_SIZE; + } + +#ifdef HAVE_MAX_FRAGMENT + if ((ssl->max_fragment != 0) && ((word16)maxFragment > ssl->max_fragment)) { + maxFragment = ssl->max_fragment; + } +#endif /* HAVE_MAX_FRAGMENT */ +#ifdef WOLFSSL_DTLS + if ((ssl->options.dtls) && (maxFragment > MAX_UDP_SIZE)) { + maxFragment = MAX_UDP_SIZE; + } +#endif + + return maxFragment; +} + + +#undef ERROR_OUT + +#endif /* WOLFCRYPT_ONLY */ diff --git a/beken_os/beken378/func/wolfssl/src/keys.c b/beken_os/beken378/func/wolfssl/src/keys.c new file mode 100755 index 0000000..b8070ea --- /dev/null +++ b/beken_os/beken378/func/wolfssl/src/keys.c @@ -0,0 +1,3540 @@ +/* keys.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +/* Name change compatibility layer no longer needs to be included here */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifndef WOLFCRYPT_ONLY + +#include +#include +#if defined(SHOW_SECRETS) || defined(CHACHA_AEAD_TEST) + #if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) + #if MQX_USE_IO_OLD + #include + #else + #include + #endif + #else + #include + #endif +#endif + + +int SetCipherSpecs(WOLFSSL* ssl) +{ +#ifndef NO_WOLFSSL_CLIENT + if (ssl->options.side == WOLFSSL_CLIENT_END) { + /* server side verified before SetCipherSpecs call */ + if (VerifyClientSuite(ssl) != 1) { + WOLFSSL_MSG("SetCipherSpecs() client has an unusuable suite"); + return UNSUPPORTED_SUITE; + } + } +#endif /* NO_WOLFSSL_CLIENT */ + + /* Chacha extensions, 0xcc */ + if (ssl->options.cipherSuite0 == CHACHA_BYTE) { + + switch (ssl->options.cipherSuite) { +#ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 + case TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256: + ssl->specs.bulk_cipher_algorithm = wolfssl_chacha; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = CHACHA20_256_KEY_SIZE; + ssl->specs.block_size = CHACHA20_BLOCK_SIZE; + ssl->specs.iv_size = CHACHA20_IV_SIZE; + ssl->specs.aead_mac_size = POLY1305_AUTH_SZ; + ssl->options.oldPoly = 1; /* use old poly1305 padding */ + + break; +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256 + case TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256: + ssl->specs.bulk_cipher_algorithm = wolfssl_chacha; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = ecc_dsa_sa_algo; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = CHACHA20_256_KEY_SIZE; + ssl->specs.block_size = CHACHA20_BLOCK_SIZE; + ssl->specs.iv_size = CHACHA20_IV_SIZE; + ssl->specs.aead_mac_size = POLY1305_AUTH_SZ; + ssl->options.oldPoly = 1; /* use old poly1305 padding */ + + break; +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 + case TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256: + ssl->specs.bulk_cipher_algorithm = wolfssl_chacha; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = CHACHA20_256_KEY_SIZE; + ssl->specs.block_size = CHACHA20_BLOCK_SIZE; + ssl->specs.iv_size = CHACHA20_IV_SIZE; + ssl->specs.aead_mac_size = POLY1305_AUTH_SZ; + ssl->options.oldPoly = 1; /* use old poly1305 padding */ + + break; +#endif +#ifdef BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 + case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: + ssl->specs.bulk_cipher_algorithm = wolfssl_chacha; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = CHACHA20_256_KEY_SIZE; + ssl->specs.block_size = CHACHA20_BLOCK_SIZE; + ssl->specs.iv_size = CHACHA20_IV_SIZE; + ssl->specs.aead_mac_size = POLY1305_AUTH_SZ; + ssl->options.oldPoly = 0; /* use recent padding RFC */ + + break; +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 + case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: + ssl->specs.bulk_cipher_algorithm = wolfssl_chacha; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = ecc_dsa_sa_algo; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = CHACHA20_256_KEY_SIZE; + ssl->specs.block_size = CHACHA20_BLOCK_SIZE; + ssl->specs.iv_size = CHACHA20_IV_SIZE; + ssl->specs.aead_mac_size = POLY1305_AUTH_SZ; + ssl->options.oldPoly = 0; /* use recent padding RFC */ + + break; +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 + case TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256: + ssl->specs.bulk_cipher_algorithm = wolfssl_chacha; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = CHACHA20_256_KEY_SIZE; + ssl->specs.block_size = CHACHA20_BLOCK_SIZE; + ssl->specs.iv_size = CHACHA20_IV_SIZE; + ssl->specs.aead_mac_size = POLY1305_AUTH_SZ; + ssl->options.oldPoly = 0; /* use recent padding RFC */ + + break; +#endif + +#ifdef BUILD_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 + case TLS_PSK_WITH_CHACHA20_POLY1305_SHA256: + ssl->specs.bulk_cipher_algorithm = wolfssl_chacha; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = psk_kea; + ssl->specs.sig_algo = anonymous_sa_algo; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = CHACHA20_256_KEY_SIZE; + ssl->specs.block_size = CHACHA20_BLOCK_SIZE; + ssl->specs.iv_size = CHACHA20_IV_SIZE; + ssl->specs.aead_mac_size = POLY1305_AUTH_SZ; + + ssl->options.oldPoly = 0; /* use recent padding RFC */ + ssl->options.usingPSK_cipher = 1; + break; +#endif + +#ifdef BUILD_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 + case TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256: + ssl->specs.bulk_cipher_algorithm = wolfssl_chacha; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = ecdhe_psk_kea; + ssl->specs.sig_algo = anonymous_sa_algo; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = CHACHA20_256_KEY_SIZE; + ssl->specs.block_size = CHACHA20_BLOCK_SIZE; + ssl->specs.iv_size = CHACHA20_IV_SIZE; + ssl->specs.aead_mac_size = POLY1305_AUTH_SZ; + + ssl->options.oldPoly = 0; /* use recent padding RFC */ + ssl->options.usingPSK_cipher = 1; + break; +#endif + +#ifdef BUILD_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 + case TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256: + ssl->specs.bulk_cipher_algorithm = wolfssl_chacha; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = dhe_psk_kea; + ssl->specs.sig_algo = anonymous_sa_algo; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = CHACHA20_256_KEY_SIZE; + ssl->specs.block_size = CHACHA20_BLOCK_SIZE; + ssl->specs.iv_size = CHACHA20_IV_SIZE; + ssl->specs.aead_mac_size = POLY1305_AUTH_SZ; + + ssl->options.oldPoly = 0; /* use recent padding RFC */ + ssl->options.usingPSK_cipher = 1; + break; +#endif + default: + WOLFSSL_MSG("Unsupported cipher suite, SetCipherSpecs ChaCha"); + return UNSUPPORTED_SUITE; + } + } + + /* ECC extensions, or AES-CCM */ + if (ssl->options.cipherSuite0 == ECC_BYTE) { + + switch (ssl->options.cipherSuite) { + +#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha384_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_256_KEY_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_triple_des; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = DES3_KEY_SIZE; + ssl->specs.block_size = DES_BLOCK_SIZE; + ssl->specs.iv_size = DES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA + case TLS_ECDHE_RSA_WITH_RC4_128_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_rc4; + ssl->specs.cipher_type = stream; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = RC4_KEY_SIZE; + ssl->specs.iv_size = 0; + ssl->specs.block_size = 0; + + break; +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_256_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; + ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; + + break; +#endif + +#ifdef BUILD_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha384_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_256_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; + ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; + + break; +#endif + +#ifdef BUILD_TLS_ECDHE_PSK_WITH_NULL_SHA256 + case TLS_ECDHE_PSK_WITH_NULL_SHA256 : + ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null; + ssl->specs.cipher_type = stream; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = ecdhe_psk_kea; + ssl->specs.sig_algo = anonymous_sa_algo; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = 0; + ssl->specs.block_size = 0; + ssl->specs.iv_size = 0; + + ssl->options.usingPSK_cipher = 1; + break; +#endif + +#ifdef BUILD_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + case TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = ecdhe_psk_kea; + ssl->specs.sig_algo = anonymous_sa_algo; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + + ssl->options.usingPSK_cipher = 1; + break; +#endif + +#endif /* HAVE_ECC || HAVE_CURVE25519 */ + +#if defined(HAVE_ECC) || (defined(HAVE_CURVE25519) && defined(HAVE_ED25519)) + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = ecc_dsa_sa_algo; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha384_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = ecc_dsa_sa_algo; + ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_256_KEY_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA + case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_triple_des; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = ecc_dsa_sa_algo; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = DES3_KEY_SIZE; + ssl->specs.block_size = DES_BLOCK_SIZE; + ssl->specs.iv_size = DES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA + case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_rc4; + ssl->specs.cipher_type = stream; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = ecc_dsa_sa_algo; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = RC4_KEY_SIZE; + ssl->specs.iv_size = 0; + ssl->specs.block_size = 0; + + break; +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = ecc_dsa_sa_algo; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = ecc_dsa_sa_algo; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_256_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = ecc_dsa_sa_algo; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; + ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; + + break; +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha384_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = ecc_dsa_sa_algo; + ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_256_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; + ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; + + break; +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM + case TLS_ECDHE_ECDSA_WITH_AES_128_CCM : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = ecc_dsa_sa_algo; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; + ssl->specs.aead_mac_size = AES_CCM_16_AUTH_SZ; + + break; +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 + case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = ecc_dsa_sa_algo; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; + ssl->specs.aead_mac_size = AES_CCM_8_AUTH_SZ; + + break; +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 + case TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = ecc_dsa_sa_algo; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_256_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; + ssl->specs.aead_mac_size = AES_CCM_8_AUTH_SZ; + + break; +#endif + +#ifdef BUILD_TLS_ECDHE_ECDSA_WITH_NULL_SHA + case TLS_ECDHE_ECDSA_WITH_NULL_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null; + ssl->specs.cipher_type = stream; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = ecc_dsa_sa_algo; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = 0; + ssl->specs.block_size = 0; + ssl->specs.iv_size = 0; + + break; +#endif + +#endif /* HAVE_ECC || (HAVE_CURVE25519 && HAVE_ED25519) */ + +#if defined(HAVE_ECC) + +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 1; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 + case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = ecc_dsa_sa_algo; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 1; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha384_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 1; + ssl->specs.key_size = AES_256_KEY_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 + case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha384_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = ecc_dsa_sa_algo; + ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 1; + ssl->specs.key_size = AES_256_KEY_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 1; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA + case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_triple_des; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 1; + ssl->specs.key_size = DES3_KEY_SIZE; + ssl->specs.block_size = DES_BLOCK_SIZE; + ssl->specs.iv_size = DES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_RC4_128_SHA + case TLS_ECDH_RSA_WITH_RC4_128_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_rc4; + ssl->specs.cipher_type = stream; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 1; + ssl->specs.key_size = RC4_KEY_SIZE; + ssl->specs.iv_size = 0; + ssl->specs.block_size = 0; + + break; +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA + case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_triple_des; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = ecc_dsa_sa_algo; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 1; + ssl->specs.key_size = DES3_KEY_SIZE; + ssl->specs.block_size = DES_BLOCK_SIZE; + ssl->specs.iv_size = DES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_RC4_128_SHA + case TLS_ECDH_ECDSA_WITH_RC4_128_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_rc4; + ssl->specs.cipher_type = stream; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = ecc_dsa_sa_algo; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 1; + ssl->specs.key_size = RC4_KEY_SIZE; + ssl->specs.iv_size = 0; + ssl->specs.block_size = 0; + + break; +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 1; + ssl->specs.key_size = AES_256_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = ecc_dsa_sa_algo; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 1; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = ecc_dsa_sa_algo; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 1; + ssl->specs.key_size = AES_256_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 1; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; + ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; + + break; +#endif + +#ifdef BUILD_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha384_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 1; + ssl->specs.key_size = AES_256_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; + ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; + + break; +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = ecc_dsa_sa_algo; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 1; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; + ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; + + break; +#endif + +#ifdef BUILD_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha384_mac; + ssl->specs.kea = ecc_diffie_hellman_kea; + ssl->specs.sig_algo = ecc_dsa_sa_algo; + ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 1; + ssl->specs.key_size = AES_256_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; + ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; + + break; +#endif + +#endif /* HAVE_ECC */ + +#ifdef BUILD_TLS_RSA_WITH_AES_128_CCM_8 + case TLS_RSA_WITH_AES_128_CCM_8 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = rsa_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; + ssl->specs.aead_mac_size = AES_CCM_8_AUTH_SZ; + + break; +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_256_CCM_8 + case TLS_RSA_WITH_AES_256_CCM_8 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = rsa_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_256_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; + ssl->specs.aead_mac_size = AES_CCM_8_AUTH_SZ; + + break; +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_128_CCM_8 + case TLS_PSK_WITH_AES_128_CCM_8 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = psk_kea; + ssl->specs.sig_algo = anonymous_sa_algo; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; + ssl->specs.aead_mac_size = AES_CCM_8_AUTH_SZ; + + ssl->options.usingPSK_cipher = 1; + break; +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_256_CCM_8 + case TLS_PSK_WITH_AES_256_CCM_8 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = psk_kea; + ssl->specs.sig_algo = anonymous_sa_algo; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_256_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; + ssl->specs.aead_mac_size = AES_CCM_8_AUTH_SZ; + + ssl->options.usingPSK_cipher = 1; + break; +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_128_CCM + case TLS_PSK_WITH_AES_128_CCM : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = psk_kea; + ssl->specs.sig_algo = anonymous_sa_algo; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; + ssl->specs.aead_mac_size = AES_CCM_16_AUTH_SZ; + + ssl->options.usingPSK_cipher = 1; + break; +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_256_CCM + case TLS_PSK_WITH_AES_256_CCM : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = psk_kea; + ssl->specs.sig_algo = anonymous_sa_algo; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_256_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; + ssl->specs.aead_mac_size = AES_CCM_16_AUTH_SZ; + + ssl->options.usingPSK_cipher = 1; + break; +#endif + +#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CCM + case TLS_DHE_PSK_WITH_AES_128_CCM : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = dhe_psk_kea; + ssl->specs.sig_algo = anonymous_sa_algo; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; + ssl->specs.aead_mac_size = AES_CCM_16_AUTH_SZ; + + ssl->options.usingPSK_cipher = 1; + break; +#endif + +#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_CCM + case TLS_DHE_PSK_WITH_AES_256_CCM : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = dhe_psk_kea; + ssl->specs.sig_algo = anonymous_sa_algo; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_256_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; + ssl->specs.aead_mac_size = AES_CCM_16_AUTH_SZ; + + ssl->options.usingPSK_cipher = 1; + break; +#endif + + default: + WOLFSSL_MSG("Unsupported cipher suite, SetCipherSpecs ECC"); + return UNSUPPORTED_SUITE; + } /* switch */ + } /* if */ + + /* TLSi v1.3 cipher suites, 0x13 */ + if (ssl->options.cipherSuite0 == TLS13_BYTE) { + switch (ssl->options.cipherSuite) { + +#ifdef WOLFSSL_TLS13 + #ifdef BUILD_TLS_AES_128_GCM_SHA256 + case TLS_AES_128_GCM_SHA256 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = 0; + ssl->specs.sig_algo = 0; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AESGCM_NONCE_SZ; + ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; + + break; + #endif + + #ifdef BUILD_TLS_AES_256_GCM_SHA384 + case TLS_AES_256_GCM_SHA384 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha384_mac; + ssl->specs.kea = 0; + ssl->specs.sig_algo = 0; + ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_256_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AESGCM_NONCE_SZ; + ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; + + break; + #endif + + #ifdef BUILD_TLS_CHACHA20_POLY1305_SHA256 + case TLS_CHACHA20_POLY1305_SHA256 : + ssl->specs.bulk_cipher_algorithm = wolfssl_chacha; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = 0; + ssl->specs.sig_algo = 0; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = CHACHA20_256_KEY_SIZE; + ssl->specs.block_size = CHACHA20_BLOCK_SIZE; + ssl->specs.iv_size = CHACHA20_IV_SIZE; + ssl->specs.aead_mac_size = POLY1305_AUTH_SZ; + ssl->options.oldPoly = 0; /* use recent padding RFC */ + + break; + #endif + + #ifdef BUILD_TLS_AES_128_CCM_SHA256 + case TLS_AES_128_CCM_SHA256 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = 0; + ssl->specs.sig_algo = 0; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AESGCM_NONCE_SZ; + ssl->specs.aead_mac_size = AES_CCM_16_AUTH_SZ; + + break; + #endif + + #ifdef BUILD_TLS_AES_128_CCM_8_SHA256 + case TLS_AES_128_CCM_8_SHA256 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes_ccm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = 0; + ssl->specs.sig_algo = 0; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AESGCM_NONCE_SZ; + ssl->specs.aead_mac_size = AES_CCM_8_AUTH_SZ; + + break; + #endif +#endif /* WOLFSSL_TLS13 */ + } + } + + if (ssl->options.cipherSuite0 != ECC_BYTE && + ssl->options.cipherSuite0 != CHACHA_BYTE && + ssl->options.cipherSuite0 != TLS13_BYTE) { /* normal suites */ + switch (ssl->options.cipherSuite) { + +#ifdef BUILD_SSL_RSA_WITH_RC4_128_SHA + case SSL_RSA_WITH_RC4_128_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_rc4; + ssl->specs.cipher_type = stream; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = rsa_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = RC4_KEY_SIZE; + ssl->specs.iv_size = 0; + ssl->specs.block_size = 0; + + break; +#endif + +#ifdef BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA + case TLS_NTRU_RSA_WITH_RC4_128_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_rc4; + ssl->specs.cipher_type = stream; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = ntru_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = RC4_KEY_SIZE; + ssl->specs.iv_size = 0; + ssl->specs.block_size = 0; + + break; +#endif + +#ifdef BUILD_SSL_RSA_WITH_RC4_128_MD5 + case SSL_RSA_WITH_RC4_128_MD5 : + ssl->specs.bulk_cipher_algorithm = wolfssl_rc4; + ssl->specs.cipher_type = stream; + ssl->specs.mac_algorithm = md5_mac; + ssl->specs.kea = rsa_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_MD5_DIGEST_SIZE; + ssl->specs.pad_size = PAD_MD5; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = RC4_KEY_SIZE; + ssl->specs.iv_size = 0; + ssl->specs.block_size = 0; + + break; +#endif + +#ifdef BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA + case SSL_RSA_WITH_3DES_EDE_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_triple_des; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = rsa_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = DES3_KEY_SIZE; + ssl->specs.block_size = DES_BLOCK_SIZE; + ssl->specs.iv_size = DES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA + case TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_triple_des; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = ntru_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = DES3_KEY_SIZE; + ssl->specs.block_size = DES_BLOCK_SIZE; + ssl->specs.iv_size = DES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA + case TLS_RSA_WITH_AES_128_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = rsa_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_SHA256 + case TLS_RSA_WITH_AES_128_CBC_SHA256 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = rsa_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_RSA_WITH_NULL_MD5 + case TLS_RSA_WITH_NULL_MD5 : + ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null; + ssl->specs.cipher_type = stream; + ssl->specs.mac_algorithm = md5_mac; + ssl->specs.kea = rsa_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_MD5_DIGEST_SIZE; + ssl->specs.pad_size = PAD_MD5; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = 0; + ssl->specs.block_size = 0; + ssl->specs.iv_size = 0; + + break; +#endif + +#ifdef BUILD_TLS_RSA_WITH_NULL_SHA + case TLS_RSA_WITH_NULL_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null; + ssl->specs.cipher_type = stream; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = rsa_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = 0; + ssl->specs.block_size = 0; + ssl->specs.iv_size = 0; + + break; +#endif + +#ifdef BUILD_TLS_RSA_WITH_NULL_SHA256 + case TLS_RSA_WITH_NULL_SHA256 : + ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null; + ssl->specs.cipher_type = stream; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = rsa_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = 0; + ssl->specs.block_size = 0; + ssl->specs.iv_size = 0; + + break; +#endif + +#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA + case TLS_NTRU_RSA_WITH_AES_128_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = ntru_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA + case TLS_RSA_WITH_AES_256_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = rsa_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_256_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_SHA256 + case TLS_RSA_WITH_AES_256_CBC_SHA256 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = rsa_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_256_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA + case TLS_NTRU_RSA_WITH_AES_256_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = ntru_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_256_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_128_GCM_SHA256 + case TLS_PSK_WITH_AES_128_GCM_SHA256 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = psk_kea; + ssl->specs.sig_algo = anonymous_sa_algo; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; + ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; + + ssl->options.usingPSK_cipher = 1; + break; +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_256_GCM_SHA384 + case TLS_PSK_WITH_AES_256_GCM_SHA384 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha384_mac; + ssl->specs.kea = psk_kea; + ssl->specs.sig_algo = anonymous_sa_algo; + ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_256_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; + ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; + + ssl->options.usingPSK_cipher = 1; + break; +#endif + +#ifdef BUILD_TLS_DH_anon_WITH_AES_256_GCM_SHA384 + case TLS_DH_anon_WITH_AES_256_GCM_SHA384: + ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha384_mac; + ssl->specs.kea = diffie_hellman_kea; + ssl->specs.sig_algo = anonymous_sa_algo; + ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_256_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; + ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; + + ssl->options.usingAnon_cipher = 1; + break; +#endif + +#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + case TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = dhe_psk_kea; + ssl->specs.sig_algo = anonymous_sa_algo; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; + ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; + + ssl->options.usingPSK_cipher = 1; + break; +#endif + +#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 + case TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha384_mac; + ssl->specs.kea = dhe_psk_kea; + ssl->specs.sig_algo = anonymous_sa_algo; + ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_256_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; + ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; + + ssl->options.usingPSK_cipher = 1; + break; +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA256 + case TLS_PSK_WITH_AES_128_CBC_SHA256 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = psk_kea; + ssl->specs.sig_algo = anonymous_sa_algo; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + + ssl->options.usingPSK_cipher = 1; + break; +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA384 + case TLS_PSK_WITH_AES_256_CBC_SHA384 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha384_mac; + ssl->specs.kea = psk_kea; + ssl->specs.sig_algo = anonymous_sa_algo; + ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_256_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + + ssl->options.usingPSK_cipher = 1; + break; +#endif + +#ifdef BUILD_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + case TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = dhe_psk_kea; + ssl->specs.sig_algo = anonymous_sa_algo; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + + ssl->options.usingPSK_cipher = 1; + break; +#endif + +#ifdef BUILD_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + case TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha384_mac; + ssl->specs.kea = dhe_psk_kea; + ssl->specs.sig_algo = anonymous_sa_algo; + ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_256_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + + ssl->options.usingPSK_cipher = 1; + break; +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_128_CBC_SHA + case TLS_PSK_WITH_AES_128_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = psk_kea; + ssl->specs.sig_algo = anonymous_sa_algo; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + + ssl->options.usingPSK_cipher = 1; + break; +#endif + +#ifdef BUILD_TLS_PSK_WITH_AES_256_CBC_SHA + case TLS_PSK_WITH_AES_256_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = psk_kea; + ssl->specs.sig_algo = anonymous_sa_algo; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_256_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + + ssl->options.usingPSK_cipher = 1; + break; +#endif + +#ifdef BUILD_TLS_PSK_WITH_NULL_SHA256 + case TLS_PSK_WITH_NULL_SHA256 : + ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null; + ssl->specs.cipher_type = stream; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = psk_kea; + ssl->specs.sig_algo = anonymous_sa_algo; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = 0; + ssl->specs.block_size = 0; + ssl->specs.iv_size = 0; + + ssl->options.usingPSK_cipher = 1; + break; +#endif + +#ifdef BUILD_TLS_PSK_WITH_NULL_SHA384 + case TLS_PSK_WITH_NULL_SHA384 : + ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null; + ssl->specs.cipher_type = stream; + ssl->specs.mac_algorithm = sha384_mac; + ssl->specs.kea = psk_kea; + ssl->specs.sig_algo = anonymous_sa_algo; + ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = 0; + ssl->specs.block_size = 0; + ssl->specs.iv_size = 0; + + ssl->options.usingPSK_cipher = 1; + break; +#endif + +#ifdef BUILD_TLS_PSK_WITH_NULL_SHA + case TLS_PSK_WITH_NULL_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null; + ssl->specs.cipher_type = stream; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = psk_kea; + ssl->specs.sig_algo = anonymous_sa_algo; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = 0; + ssl->specs.block_size = 0; + ssl->specs.iv_size = 0; + + ssl->options.usingPSK_cipher = 1; + break; +#endif + +#ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA256 + case TLS_DHE_PSK_WITH_NULL_SHA256 : + ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null; + ssl->specs.cipher_type = stream; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = dhe_psk_kea; + ssl->specs.sig_algo = anonymous_sa_algo; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = 0; + ssl->specs.block_size = 0; + ssl->specs.iv_size = 0; + + ssl->options.usingPSK_cipher = 1; + break; +#endif + +#ifdef BUILD_TLS_DHE_PSK_WITH_NULL_SHA384 + case TLS_DHE_PSK_WITH_NULL_SHA384 : + ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null; + ssl->specs.cipher_type = stream; + ssl->specs.mac_algorithm = sha384_mac; + ssl->specs.kea = dhe_psk_kea; + ssl->specs.sig_algo = anonymous_sa_algo; + ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = 0; + ssl->specs.block_size = 0; + ssl->specs.iv_size = 0; + + ssl->options.usingPSK_cipher = 1; + break; +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_triple_des; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = DES3_KEY_SIZE; + ssl->specs.block_size = DES_BLOCK_SIZE; + ssl->specs.iv_size = DES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_256_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA + case TLS_DHE_RSA_WITH_AES_128_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA + case TLS_DHE_RSA_WITH_AES_256_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_256_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_RSA_WITH_HC_128_MD5 + case TLS_RSA_WITH_HC_128_MD5 : + ssl->specs.bulk_cipher_algorithm = wolfssl_hc128; + ssl->specs.cipher_type = stream; + ssl->specs.mac_algorithm = md5_mac; + ssl->specs.kea = rsa_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_MD5_DIGEST_SIZE; + ssl->specs.pad_size = PAD_MD5; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = HC_128_KEY_SIZE; + ssl->specs.block_size = 0; + ssl->specs.iv_size = HC_128_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_RSA_WITH_HC_128_SHA + case TLS_RSA_WITH_HC_128_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_hc128; + ssl->specs.cipher_type = stream; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = rsa_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = HC_128_KEY_SIZE; + ssl->specs.block_size = 0; + ssl->specs.iv_size = HC_128_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_RSA_WITH_HC_128_B2B256 + case TLS_RSA_WITH_HC_128_B2B256: + ssl->specs.bulk_cipher_algorithm = wolfssl_hc128; + ssl->specs.cipher_type = stream; + ssl->specs.mac_algorithm = blake2b_mac; + ssl->specs.kea = rsa_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = BLAKE2B_256; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = HC_128_KEY_SIZE; + ssl->specs.block_size = 0; + ssl->specs.iv_size = HC_128_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_128_CBC_B2B256 + case TLS_RSA_WITH_AES_128_CBC_B2B256: + ssl->specs.bulk_cipher_algorithm = wolfssl_aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = blake2b_mac; + ssl->specs.kea = rsa_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = BLAKE2B_256; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_256_CBC_B2B256 + case TLS_RSA_WITH_AES_256_CBC_B2B256: + ssl->specs.bulk_cipher_algorithm = wolfssl_aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = blake2b_mac; + ssl->specs.kea = rsa_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = BLAKE2B_256; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_256_KEY_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_RSA_WITH_RABBIT_SHA + case TLS_RSA_WITH_RABBIT_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_rabbit; + ssl->specs.cipher_type = stream; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = rsa_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = RABBIT_KEY_SIZE; + ssl->specs.block_size = 0; + ssl->specs.iv_size = RABBIT_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256 + case TLS_RSA_WITH_AES_128_GCM_SHA256 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = rsa_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; + ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; + + break; +#endif + +#ifdef BUILD_TLS_RSA_WITH_AES_256_GCM_SHA384 + case TLS_RSA_WITH_AES_256_GCM_SHA384 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha384_mac; + ssl->specs.kea = rsa_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_256_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; + ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; + + break; +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + case TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; + ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; + + break; +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + case TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes_gcm; + ssl->specs.cipher_type = aead; + ssl->specs.mac_algorithm = sha384_mac; + ssl->specs.kea = diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA384_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_256_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AESGCM_IMP_IV_SZ; + ssl->specs.aead_mac_size = AES_GCM_AUTH_SZ; + + break; +#endif + +#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_camellia; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = rsa_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = CAMELLIA_128_KEY_SIZE; + ssl->specs.block_size = CAMELLIA_BLOCK_SIZE; + ssl->specs.iv_size = CAMELLIA_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA + case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_camellia; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = rsa_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = CAMELLIA_256_KEY_SIZE; + ssl->specs.block_size = CAMELLIA_BLOCK_SIZE; + ssl->specs.iv_size = CAMELLIA_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 + case TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 : + ssl->specs.bulk_cipher_algorithm = wolfssl_camellia; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = rsa_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = CAMELLIA_128_KEY_SIZE; + ssl->specs.block_size = CAMELLIA_BLOCK_SIZE; + ssl->specs.iv_size = CAMELLIA_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 + case TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 : + ssl->specs.bulk_cipher_algorithm = wolfssl_camellia; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = rsa_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = CAMELLIA_256_KEY_SIZE; + ssl->specs.block_size = CAMELLIA_BLOCK_SIZE; + ssl->specs.iv_size = CAMELLIA_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + case TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_camellia; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = CAMELLIA_128_KEY_SIZE; + ssl->specs.block_size = CAMELLIA_BLOCK_SIZE; + ssl->specs.iv_size = CAMELLIA_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + case TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_camellia; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = CAMELLIA_256_KEY_SIZE; + ssl->specs.block_size = CAMELLIA_BLOCK_SIZE; + ssl->specs.iv_size = CAMELLIA_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + case TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 : + ssl->specs.bulk_cipher_algorithm = wolfssl_camellia; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = CAMELLIA_128_KEY_SIZE; + ssl->specs.block_size = CAMELLIA_BLOCK_SIZE; + ssl->specs.iv_size = CAMELLIA_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + case TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 : + ssl->specs.bulk_cipher_algorithm = wolfssl_camellia; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = diffie_hellman_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = CAMELLIA_256_KEY_SIZE; + ssl->specs.block_size = CAMELLIA_BLOCK_SIZE; + ssl->specs.iv_size = CAMELLIA_IV_SIZE; + + break; +#endif + +#ifdef BUILD_TLS_DH_anon_WITH_AES_128_CBC_SHA + case TLS_DH_anon_WITH_AES_128_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_aes; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = diffie_hellman_kea; + ssl->specs.sig_algo = anonymous_sa_algo; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = AES_128_KEY_SIZE; + ssl->specs.block_size = AES_BLOCK_SIZE; + ssl->specs.iv_size = AES_IV_SIZE; + + ssl->options.usingAnon_cipher = 1; + break; +#endif + +#ifdef BUILD_SSL_RSA_WITH_IDEA_CBC_SHA + case SSL_RSA_WITH_IDEA_CBC_SHA : + ssl->specs.bulk_cipher_algorithm = wolfssl_idea; + ssl->specs.cipher_type = block; + ssl->specs.mac_algorithm = sha_mac; + ssl->specs.kea = rsa_kea; + ssl->specs.sig_algo = rsa_sa_algo; + ssl->specs.hash_size = WC_SHA_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + ssl->specs.static_ecdh = 0; + ssl->specs.key_size = IDEA_KEY_SIZE; + ssl->specs.block_size = IDEA_BLOCK_SIZE; + ssl->specs.iv_size = IDEA_IV_SIZE; + + break; +#endif + +#ifdef BUILD_WDM_WITH_NULL_SHA256 + case WDM_WITH_NULL_SHA256 : + ssl->specs.bulk_cipher_algorithm = wolfssl_cipher_null; + ssl->specs.cipher_type = stream; + ssl->specs.mac_algorithm = sha256_mac; + ssl->specs.kea = no_kea; + ssl->specs.sig_algo = anonymous_sa_algo; + ssl->specs.hash_size = WC_SHA256_DIGEST_SIZE; + ssl->specs.pad_size = PAD_SHA; + + break; +#endif + + default: + WOLFSSL_MSG("Unsupported cipher suite, SetCipherSpecs"); + return UNSUPPORTED_SUITE; + } /* switch */ + } /* if ECC / Normal suites else */ + + /* set TLS if it hasn't been turned off */ + if (ssl->version.major == 3 && ssl->version.minor >= 1) { +#ifndef NO_TLS + ssl->options.tls = 1; + #if !defined(WOLFSSL_NO_TLS12) && !defined(WOLFSSL_AEAD_ONLY) + ssl->hmac = TLS_hmac; + #endif + if (ssl->version.minor >= 2) { + ssl->options.tls1_1 = 1; + if (ssl->version.minor >= 4) + ssl->options.tls1_3 = 1; + } +#endif + } + +#if defined(WOLFSSL_DTLS) && !defined(WOLFSSL_AEAD_ONLY) + if (ssl->options.dtls) + ssl->hmac = TLS_hmac; +#endif + + return 0; +} + + +enum KeyStuff { + MASTER_ROUNDS = 3, + PREFIX = 3, /* up to three letters for master prefix */ + KEY_PREFIX = 9 /* up to 9 prefix letters for key rounds */ + + +}; + +#ifndef NO_OLD_TLS +/* true or false, zero for error */ +static int SetPrefix(byte* sha_input, int idx) +{ + switch (idx) { + case 0: + XMEMCPY(sha_input, "A", 1); + break; + case 1: + XMEMCPY(sha_input, "BB", 2); + break; + case 2: + XMEMCPY(sha_input, "CCC", 3); + break; + case 3: + XMEMCPY(sha_input, "DDDD", 4); + break; + case 4: + XMEMCPY(sha_input, "EEEEE", 5); + break; + case 5: + XMEMCPY(sha_input, "FFFFFF", 6); + break; + case 6: + XMEMCPY(sha_input, "GGGGGGG", 7); + break; + case 7: + XMEMCPY(sha_input, "HHHHHHHH", 8); + break; + case 8: + XMEMCPY(sha_input, "IIIIIIIII", 9); + break; + default: + WOLFSSL_MSG("Set Prefix error, bad input"); + return 0; + } + return 1; +} +#endif + + +static int SetKeys(Ciphers* enc, Ciphers* dec, Keys* keys, CipherSpecs* specs, + int side, void* heap, int devId, WC_RNG* rng, int skipIv) +{ + (void)rng; + (void)skipIv; + +#ifdef BUILD_ARC4 + if (specs->bulk_cipher_algorithm == wolfssl_rc4) { + word32 sz = specs->key_size; + if (enc && enc->arc4 == NULL) + enc->arc4 = (Arc4*)XMALLOC(sizeof(Arc4), heap, DYNAMIC_TYPE_CIPHER); + if (enc && enc->arc4 == NULL) + return MEMORY_E; + if (dec && dec->arc4 == NULL) + dec->arc4 = (Arc4*)XMALLOC(sizeof(Arc4), heap, DYNAMIC_TYPE_CIPHER); + if (dec && dec->arc4 == NULL) + return MEMORY_E; + + if (enc) { + if (wc_Arc4Init(enc->arc4, heap, devId) != 0) { + WOLFSSL_MSG("Arc4Init failed in SetKeys"); + return ASYNC_INIT_E; + } + } + if (dec) { + if (wc_Arc4Init(dec->arc4, heap, devId) != 0) { + WOLFSSL_MSG("Arc4Init failed in SetKeys"); + return ASYNC_INIT_E; + } + } + + if (side == WOLFSSL_CLIENT_END) { + if (enc) + wc_Arc4SetKey(enc->arc4, keys->client_write_key, sz); + if (dec) + wc_Arc4SetKey(dec->arc4, keys->server_write_key, sz); + } + else { + if (enc) + wc_Arc4SetKey(enc->arc4, keys->server_write_key, sz); + if (dec) + wc_Arc4SetKey(dec->arc4, keys->client_write_key, sz); + } + if (enc) + enc->setup = 1; + if (dec) + dec->setup = 1; + } +#endif /* BUILD_ARC4 */ + + +#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) + /* Check that the max implicit iv size is suffecient */ + #if (AEAD_MAX_IMP_SZ < 12) /* CHACHA20_IMP_IV_SZ */ + #error AEAD_MAX_IMP_SZ is too small for ChaCha20 + #endif + #if (MAX_WRITE_IV_SZ < 12) /* CHACHA20_IMP_IV_SZ */ + #error MAX_WRITE_IV_SZ is too small for ChaCha20 + #endif + + if (specs->bulk_cipher_algorithm == wolfssl_chacha) { + int chachaRet; + if (enc && enc->chacha == NULL) + enc->chacha = + (ChaCha*)XMALLOC(sizeof(ChaCha), heap, DYNAMIC_TYPE_CIPHER); + if (enc && enc->chacha == NULL) + return MEMORY_E; + if (dec && dec->chacha == NULL) + dec->chacha = + (ChaCha*)XMALLOC(sizeof(ChaCha), heap, DYNAMIC_TYPE_CIPHER); + if (dec && dec->chacha == NULL) + return MEMORY_E; + if (side == WOLFSSL_CLIENT_END) { + if (enc) { + chachaRet = wc_Chacha_SetKey(enc->chacha, keys->client_write_key, + specs->key_size); + XMEMCPY(keys->aead_enc_imp_IV, keys->client_write_IV, + CHACHA20_IMP_IV_SZ); + if (chachaRet != 0) return chachaRet; + } + if (dec) { + chachaRet = wc_Chacha_SetKey(dec->chacha, keys->server_write_key, + specs->key_size); + XMEMCPY(keys->aead_dec_imp_IV, keys->server_write_IV, + CHACHA20_IMP_IV_SZ); + if (chachaRet != 0) return chachaRet; + } + } + else { + if (enc) { + chachaRet = wc_Chacha_SetKey(enc->chacha, keys->server_write_key, + specs->key_size); + XMEMCPY(keys->aead_enc_imp_IV, keys->server_write_IV, + CHACHA20_IMP_IV_SZ); + if (chachaRet != 0) return chachaRet; + } + if (dec) { + chachaRet = wc_Chacha_SetKey(dec->chacha, keys->client_write_key, + specs->key_size); + XMEMCPY(keys->aead_dec_imp_IV, keys->client_write_IV, + CHACHA20_IMP_IV_SZ); + if (chachaRet != 0) return chachaRet; + } + } + + if (enc) + enc->setup = 1; + if (dec) + dec->setup = 1; + } +#endif /* HAVE_CHACHA && HAVE_POLY1305 */ + + +#ifdef HAVE_HC128 + /* check that buffer sizes are sufficient */ + #if (MAX_WRITE_IV_SZ < 16) /* HC_128_IV_SIZE */ + #error MAX_WRITE_IV_SZ too small for HC128 + #endif + + if (specs->bulk_cipher_algorithm == wolfssl_hc128) { + int hcRet; + if (enc && enc->hc128 == NULL) + enc->hc128 = + (HC128*)XMALLOC(sizeof(HC128), heap, DYNAMIC_TYPE_CIPHER); + if (enc && enc->hc128 == NULL) + return MEMORY_E; + if (dec && dec->hc128 == NULL) + dec->hc128 = + (HC128*)XMALLOC(sizeof(HC128), heap, DYNAMIC_TYPE_CIPHER); + if (dec && dec->hc128 == NULL) + return MEMORY_E; + if (side == WOLFSSL_CLIENT_END) { + if (enc) { + hcRet = wc_Hc128_SetKey(enc->hc128, keys->client_write_key, + keys->client_write_IV); + if (hcRet != 0) return hcRet; + } + if (dec) { + hcRet = wc_Hc128_SetKey(dec->hc128, keys->server_write_key, + keys->server_write_IV); + if (hcRet != 0) return hcRet; + } + } + else { + if (enc) { + hcRet = wc_Hc128_SetKey(enc->hc128, keys->server_write_key, + keys->server_write_IV); + if (hcRet != 0) return hcRet; + } + if (dec) { + hcRet = wc_Hc128_SetKey(dec->hc128, keys->client_write_key, + keys->client_write_IV); + if (hcRet != 0) return hcRet; + } + } + if (enc) + enc->setup = 1; + if (dec) + dec->setup = 1; + } +#endif /* HAVE_HC128 */ + +#ifdef BUILD_RABBIT + /* check that buffer sizes are sufficient */ + #if (MAX_WRITE_IV_SZ < 8) /* RABBIT_IV_SIZE */ + #error MAX_WRITE_IV_SZ too small for RABBIT + #endif + + if (specs->bulk_cipher_algorithm == wolfssl_rabbit) { + int rabRet; + if (enc && enc->rabbit == NULL) + enc->rabbit = + (Rabbit*)XMALLOC(sizeof(Rabbit), heap, DYNAMIC_TYPE_CIPHER); + if (enc && enc->rabbit == NULL) + return MEMORY_E; + if (dec && dec->rabbit == NULL) + dec->rabbit = + (Rabbit*)XMALLOC(sizeof(Rabbit), heap, DYNAMIC_TYPE_CIPHER); + if (dec && dec->rabbit == NULL) + return MEMORY_E; + if (side == WOLFSSL_CLIENT_END) { + if (enc) { + rabRet = wc_RabbitSetKey(enc->rabbit, keys->client_write_key, + keys->client_write_IV); + if (rabRet != 0) return rabRet; + } + if (dec) { + rabRet = wc_RabbitSetKey(dec->rabbit, keys->server_write_key, + keys->server_write_IV); + if (rabRet != 0) return rabRet; + } + } + else { + if (enc) { + rabRet = wc_RabbitSetKey(enc->rabbit, keys->server_write_key, + keys->server_write_IV); + if (rabRet != 0) return rabRet; + } + if (dec) { + rabRet = wc_RabbitSetKey(dec->rabbit, keys->client_write_key, + keys->client_write_IV); + if (rabRet != 0) return rabRet; + } + } + if (enc) + enc->setup = 1; + if (dec) + dec->setup = 1; + } +#endif /* BUILD_RABBIT */ + +#ifdef BUILD_DES3 + /* check that buffer sizes are sufficient */ + #if (MAX_WRITE_IV_SZ < 8) /* DES_IV_SIZE */ + #error MAX_WRITE_IV_SZ too small for 3DES + #endif + + if (specs->bulk_cipher_algorithm == wolfssl_triple_des) { + int desRet = 0; + + if (enc) { + if (enc->des3 == NULL) + enc->des3 = (Des3*)XMALLOC(sizeof(Des3), heap, DYNAMIC_TYPE_CIPHER); + if (enc->des3 == NULL) + return MEMORY_E; + XMEMSET(enc->des3, 0, sizeof(Des3)); + } + if (dec) { + if (dec->des3 == NULL) + dec->des3 = (Des3*)XMALLOC(sizeof(Des3), heap, DYNAMIC_TYPE_CIPHER); + if (dec->des3 == NULL) + return MEMORY_E; + XMEMSET(dec->des3, 0, sizeof(Des3)); + } + + if (enc) { + if (wc_Des3Init(enc->des3, heap, devId) != 0) { + WOLFSSL_MSG("Des3Init failed in SetKeys"); + return ASYNC_INIT_E; + } + } + if (dec) { + if (wc_Des3Init(dec->des3, heap, devId) != 0) { + WOLFSSL_MSG("Des3Init failed in SetKeys"); + return ASYNC_INIT_E; + } + } + + if (side == WOLFSSL_CLIENT_END) { + if (enc) { + desRet = wc_Des3_SetKey(enc->des3, keys->client_write_key, + keys->client_write_IV, DES_ENCRYPTION); + if (desRet != 0) return desRet; + } + if (dec) { + desRet = wc_Des3_SetKey(dec->des3, keys->server_write_key, + keys->server_write_IV, DES_DECRYPTION); + if (desRet != 0) return desRet; + } + } + else { + if (enc) { + desRet = wc_Des3_SetKey(enc->des3, keys->server_write_key, + keys->server_write_IV, DES_ENCRYPTION); + if (desRet != 0) return desRet; + } + if (dec) { + desRet = wc_Des3_SetKey(dec->des3, keys->client_write_key, + keys->client_write_IV, DES_DECRYPTION); + if (desRet != 0) return desRet; + } + } + if (enc) + enc->setup = 1; + if (dec) + dec->setup = 1; + } +#endif /* BUILD_DES3 */ + +#ifdef BUILD_AES + /* check that buffer sizes are sufficient */ + #if (MAX_WRITE_IV_SZ < 16) /* AES_IV_SIZE */ + #error MAX_WRITE_IV_SZ too small for AES + #endif + + if (specs->bulk_cipher_algorithm == wolfssl_aes) { + int aesRet = 0; + + if (enc) { + if (enc->aes == NULL) + enc->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); + if (enc->aes == NULL) + return MEMORY_E; + XMEMSET(enc->aes, 0, sizeof(Aes)); + } + if (dec) { + if (dec->aes == NULL) + dec->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); + if (dec->aes == NULL) + return MEMORY_E; + XMEMSET(dec->aes, 0, sizeof(Aes)); + } + if (enc) { + if (wc_AesInit(enc->aes, heap, devId) != 0) { + WOLFSSL_MSG("AesInit failed in SetKeys"); + return ASYNC_INIT_E; + } + } + if (dec) { + if (wc_AesInit(dec->aes, heap, devId) != 0) { + WOLFSSL_MSG("AesInit failed in SetKeys"); + return ASYNC_INIT_E; + } + } + + if (side == WOLFSSL_CLIENT_END) { + if (enc) { + aesRet = wc_AesSetKey(enc->aes, keys->client_write_key, + specs->key_size, keys->client_write_IV, + AES_ENCRYPTION); + if (aesRet != 0) return aesRet; + } + if (dec) { + aesRet = wc_AesSetKey(dec->aes, keys->server_write_key, + specs->key_size, keys->server_write_IV, + AES_DECRYPTION); + if (aesRet != 0) return aesRet; + } + } + else { + if (enc) { + aesRet = wc_AesSetKey(enc->aes, keys->server_write_key, + specs->key_size, keys->server_write_IV, + AES_ENCRYPTION); + if (aesRet != 0) return aesRet; + } + if (dec) { + aesRet = wc_AesSetKey(dec->aes, keys->client_write_key, + specs->key_size, keys->client_write_IV, + AES_DECRYPTION); + if (aesRet != 0) return aesRet; + } + } + if (enc) + enc->setup = 1; + if (dec) + dec->setup = 1; + } +#endif /* BUILD_AES */ + +#ifdef BUILD_AESGCM + /* check that buffer sizes are sufficient */ + #if (AEAD_MAX_IMP_SZ < 4) /* AESGCM_IMP_IV_SZ */ + #error AEAD_MAX_IMP_SZ too small for AESGCM + #endif + #if (AEAD_MAX_EXP_SZ < 8) /* AESGCM_EXP_IV_SZ */ + #error AEAD_MAX_EXP_SZ too small for AESGCM + #endif + #if (MAX_WRITE_IV_SZ < 4) /* AESGCM_IMP_IV_SZ */ + #error MAX_WRITE_IV_SZ too small for AESGCM + #endif + + if (specs->bulk_cipher_algorithm == wolfssl_aes_gcm) { + int gcmRet; + + if (enc) { + if (enc->aes == NULL) + enc->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); + if (enc->aes == NULL) + return MEMORY_E; + XMEMSET(enc->aes, 0, sizeof(Aes)); + } + if (dec) { + if (dec->aes == NULL) + dec->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); + if (dec->aes == NULL) + return MEMORY_E; + XMEMSET(dec->aes, 0, sizeof(Aes)); + } + + if (enc) { + if (wc_AesInit(enc->aes, heap, devId) != 0) { + WOLFSSL_MSG("AesInit failed in SetKeys"); + return ASYNC_INIT_E; + } + } + if (dec) { + if (wc_AesInit(dec->aes, heap, devId) != 0) { + WOLFSSL_MSG("AesInit failed in SetKeys"); + return ASYNC_INIT_E; + } + } + + if (side == WOLFSSL_CLIENT_END) { + if (enc) { + gcmRet = wc_AesGcmSetKey(enc->aes, keys->client_write_key, + specs->key_size); + if (gcmRet != 0) return gcmRet; + XMEMCPY(keys->aead_enc_imp_IV, keys->client_write_IV, + AEAD_MAX_IMP_SZ); +#if !defined(NO_PUBLIC_GCM_SET_IV) && \ + ((!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2))) + if (!skipIv) { + gcmRet = wc_AesGcmSetIV(enc->aes, AESGCM_NONCE_SZ, + keys->client_write_IV, AESGCM_IMP_IV_SZ, rng); + if (gcmRet != 0) return gcmRet; + } +#endif + } + if (dec) { + gcmRet = wc_AesGcmSetKey(dec->aes, keys->server_write_key, + specs->key_size); + if (gcmRet != 0) return gcmRet; + XMEMCPY(keys->aead_dec_imp_IV, keys->server_write_IV, + AEAD_MAX_IMP_SZ); + } + } + else { + if (enc) { + gcmRet = wc_AesGcmSetKey(enc->aes, keys->server_write_key, + specs->key_size); + if (gcmRet != 0) return gcmRet; + XMEMCPY(keys->aead_enc_imp_IV, keys->server_write_IV, + AEAD_MAX_IMP_SZ); +#if !defined(NO_PUBLIC_GCM_SET_IV) && \ + ((!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2))) + if (!skipIv) { + gcmRet = wc_AesGcmSetIV(enc->aes, AESGCM_NONCE_SZ, + keys->server_write_IV, AESGCM_IMP_IV_SZ, rng); + if (gcmRet != 0) return gcmRet; + } +#endif + } + if (dec) { + gcmRet = wc_AesGcmSetKey(dec->aes, keys->client_write_key, + specs->key_size); + if (gcmRet != 0) return gcmRet; + XMEMCPY(keys->aead_dec_imp_IV, keys->client_write_IV, + AEAD_MAX_IMP_SZ); + } + } + if (enc) + enc->setup = 1; + if (dec) + dec->setup = 1; + } +#endif /* BUILD_AESGCM */ + +#ifdef HAVE_AESCCM + /* check that buffer sizes are sufficient (CCM is same size as GCM) */ + #if (AEAD_MAX_IMP_SZ < 4) /* AESGCM_IMP_IV_SZ */ + #error AEAD_MAX_IMP_SZ too small for AESCCM + #endif + #if (AEAD_MAX_EXP_SZ < 8) /* AESGCM_EXP_IV_SZ */ + #error AEAD_MAX_EXP_SZ too small for AESCCM + #endif + #if (MAX_WRITE_IV_SZ < 4) /* AESGCM_IMP_IV_SZ */ + #error MAX_WRITE_IV_SZ too small for AESCCM + #endif + + if (specs->bulk_cipher_algorithm == wolfssl_aes_ccm) { + int CcmRet; + + if (enc) { + if (enc->aes == NULL) + enc->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); + if (enc->aes == NULL) + return MEMORY_E; + XMEMSET(enc->aes, 0, sizeof(Aes)); + } + if (dec) { + if (dec->aes == NULL) + dec->aes = (Aes*)XMALLOC(sizeof(Aes), heap, DYNAMIC_TYPE_CIPHER); + if (dec->aes == NULL) + return MEMORY_E; + XMEMSET(dec->aes, 0, sizeof(Aes)); + } + + if (enc) { + if (wc_AesInit(enc->aes, heap, devId) != 0) { + WOLFSSL_MSG("AesInit failed in SetKeys"); + return ASYNC_INIT_E; + } + } + if (dec) { + if (wc_AesInit(dec->aes, heap, devId) != 0) { + WOLFSSL_MSG("AesInit failed in SetKeys"); + return ASYNC_INIT_E; + } + } + + if (side == WOLFSSL_CLIENT_END) { + if (enc) { + CcmRet = wc_AesCcmSetKey(enc->aes, keys->client_write_key, + specs->key_size); + if (CcmRet != 0) { + return CcmRet; + } + XMEMCPY(keys->aead_enc_imp_IV, keys->client_write_IV, + AEAD_MAX_IMP_SZ); +#if !defined(NO_PUBLIC_CCM_SET_NONCE) && \ + ((!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2))) + if (!skipIv) { + CcmRet = wc_AesCcmSetNonce(enc->aes, keys->client_write_IV, + AEAD_MAX_IMP_SZ); + if (CcmRet != 0) return CcmRet; + } +#endif + } + if (dec) { + CcmRet = wc_AesCcmSetKey(dec->aes, keys->server_write_key, + specs->key_size); + if (CcmRet != 0) { + return CcmRet; + } + XMEMCPY(keys->aead_dec_imp_IV, keys->server_write_IV, + AEAD_MAX_IMP_SZ); + } + } + else { + if (enc) { + CcmRet = wc_AesCcmSetKey(enc->aes, keys->server_write_key, + specs->key_size); + if (CcmRet != 0) { + return CcmRet; + } + XMEMCPY(keys->aead_enc_imp_IV, keys->server_write_IV, + AEAD_MAX_IMP_SZ); +#if !defined(NO_PUBLIC_CCM_SET_NONCE) && \ + ((!defined(HAVE_FIPS) && !defined(HAVE_SELFTEST)) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2))) + if (!skipIv) { + CcmRet = wc_AesCcmSetNonce(enc->aes, keys->server_write_IV, + AEAD_MAX_IMP_SZ); + if (CcmRet != 0) return CcmRet; + } +#endif + } + if (dec) { + CcmRet = wc_AesCcmSetKey(dec->aes, keys->client_write_key, + specs->key_size); + if (CcmRet != 0) { + return CcmRet; + } + XMEMCPY(keys->aead_dec_imp_IV, keys->client_write_IV, + AEAD_MAX_IMP_SZ); + } + } + if (enc) + enc->setup = 1; + if (dec) + dec->setup = 1; + } +#endif /* HAVE_AESCCM */ + +#ifdef HAVE_CAMELLIA + /* check that buffer sizes are sufficient */ + #if (MAX_WRITE_IV_SZ < 16) /* CAMELLIA_IV_SIZE */ + #error MAX_WRITE_IV_SZ too small for CAMELLIA + #endif + + if (specs->bulk_cipher_algorithm == wolfssl_camellia) { + int camRet; + + if (enc && enc->cam == NULL) + enc->cam = + (Camellia*)XMALLOC(sizeof(Camellia), heap, DYNAMIC_TYPE_CIPHER); + if (enc && enc->cam == NULL) + return MEMORY_E; + + if (dec && dec->cam == NULL) + dec->cam = + (Camellia*)XMALLOC(sizeof(Camellia), heap, DYNAMIC_TYPE_CIPHER); + if (dec && dec->cam == NULL) + return MEMORY_E; + + if (side == WOLFSSL_CLIENT_END) { + if (enc) { + camRet = wc_CamelliaSetKey(enc->cam, keys->client_write_key, + specs->key_size, keys->client_write_IV); + if (camRet != 0) return camRet; + } + if (dec) { + camRet = wc_CamelliaSetKey(dec->cam, keys->server_write_key, + specs->key_size, keys->server_write_IV); + if (camRet != 0) return camRet; + } + } + else { + if (enc) { + camRet = wc_CamelliaSetKey(enc->cam, keys->server_write_key, + specs->key_size, keys->server_write_IV); + if (camRet != 0) return camRet; + } + if (dec) { + camRet = wc_CamelliaSetKey(dec->cam, keys->client_write_key, + specs->key_size, keys->client_write_IV); + if (camRet != 0) return camRet; + } + } + if (enc) + enc->setup = 1; + if (dec) + dec->setup = 1; + } +#endif /* HAVE_CAMELLIA */ + +#ifdef HAVE_IDEA + /* check that buffer sizes are sufficient */ + #if (MAX_WRITE_IV_SZ < 8) /* IDEA_IV_SIZE */ + #error MAX_WRITE_IV_SZ too small for IDEA + #endif + + if (specs->bulk_cipher_algorithm == wolfssl_idea) { + int ideaRet; + + if (enc && enc->idea == NULL) + enc->idea = (Idea*)XMALLOC(sizeof(Idea), heap, DYNAMIC_TYPE_CIPHER); + if (enc && enc->idea == NULL) + return MEMORY_E; + + if (dec && dec->idea == NULL) + dec->idea = (Idea*)XMALLOC(sizeof(Idea), heap, DYNAMIC_TYPE_CIPHER); + if (dec && dec->idea == NULL) + return MEMORY_E; + + if (side == WOLFSSL_CLIENT_END) { + if (enc) { + ideaRet = wc_IdeaSetKey(enc->idea, keys->client_write_key, + specs->key_size, keys->client_write_IV, + IDEA_ENCRYPTION); + if (ideaRet != 0) return ideaRet; + } + if (dec) { + ideaRet = wc_IdeaSetKey(dec->idea, keys->server_write_key, + specs->key_size, keys->server_write_IV, + IDEA_DECRYPTION); + if (ideaRet != 0) return ideaRet; + } + } + else { + if (enc) { + ideaRet = wc_IdeaSetKey(enc->idea, keys->server_write_key, + specs->key_size, keys->server_write_IV, + IDEA_ENCRYPTION); + if (ideaRet != 0) return ideaRet; + } + if (dec) { + ideaRet = wc_IdeaSetKey(dec->idea, keys->client_write_key, + specs->key_size, keys->client_write_IV, + IDEA_DECRYPTION); + if (ideaRet != 0) return ideaRet; + } + } + if (enc) + enc->setup = 1; + if (dec) + dec->setup = 1; + } +#endif /* HAVE_IDEA */ + +#ifdef HAVE_NULL_CIPHER + if (specs->bulk_cipher_algorithm == wolfssl_cipher_null) { + if (enc) + enc->setup = 1; + if (dec) + dec->setup = 1; + } +#endif + + if (enc) { + keys->sequence_number_hi = 0; + keys->sequence_number_lo = 0; + } + if (dec) { + keys->peer_sequence_number_hi = 0; + keys->peer_sequence_number_lo = 0; + } + (void)side; + (void)heap; + (void)enc; + (void)dec; + (void)specs; + (void)devId; + + return 0; +} + + +#ifdef HAVE_ONE_TIME_AUTH +/* set one time authentication keys */ +static int SetAuthKeys(OneTimeAuth* authentication, Keys* keys, + CipherSpecs* specs, void* heap, int devId) +{ + +#ifdef HAVE_POLY1305 + /* set up memory space for poly1305 */ + if (authentication && authentication->poly1305 == NULL) + authentication->poly1305 = + (Poly1305*)XMALLOC(sizeof(Poly1305), heap, DYNAMIC_TYPE_CIPHER); + if (authentication && authentication->poly1305 == NULL) + return MEMORY_E; + if (authentication) + authentication->setup = 1; +#endif + (void)authentication; + (void)heap; + (void)keys; + (void)specs; + (void)devId; + + return 0; +} +#endif /* HAVE_ONE_TIME_AUTH */ + +#ifdef HAVE_SECURE_RENEGOTIATION +/* function name is for cache_status++ + * This function was added because of error incrementing enum type when + * compiling with a C++ compiler. + */ +static void CacheStatusPP(SecureRenegotiation* cache) +{ + switch (cache->cache_status) { + case SCR_CACHE_NULL: + cache->cache_status = SCR_CACHE_NEEDED; + break; + + case SCR_CACHE_NEEDED: + cache->cache_status = SCR_CACHE_COPY; + break; + + case SCR_CACHE_COPY: + cache->cache_status = SCR_CACHE_PARTIAL; + break; + + case SCR_CACHE_PARTIAL: + cache->cache_status = SCR_CACHE_COMPLETE; + break; + + case SCR_CACHE_COMPLETE: + WOLFSSL_MSG("SCR Cache state Complete"); + break; + + default: + WOLFSSL_MSG("Unknown cache state!!"); + } +} +#endif /* HAVE_SECURE_RENEGOTIATION */ + + +/* Set wc_encrypt/wc_decrypt or both sides of key setup + * note: use wc_encrypt to avoid shadowing global encrypt + * declared in unistd.h + */ +int SetKeysSide(WOLFSSL* ssl, enum encrypt_side side) +{ + int ret, copy = 0; + Ciphers* wc_encrypt = NULL; + Ciphers* wc_decrypt = NULL; + Keys* keys = &ssl->keys; + + (void)copy; + +#ifdef HAVE_SECURE_RENEGOTIATION + if (ssl->secure_renegotiation && ssl->secure_renegotiation->cache_status) { + keys = &ssl->secure_renegotiation->tmp_keys; + copy = 1; + } +#endif /* HAVE_SECURE_RENEGOTIATION */ + + switch (side) { + case ENCRYPT_SIDE_ONLY: +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Provisioning ENCRYPT key"); + if (ssl->options.side == WOLFSSL_CLIENT_END) { + WOLFSSL_BUFFER(ssl->keys.client_write_key, AES_256_KEY_SIZE); + } + else { + WOLFSSL_BUFFER(ssl->keys.server_write_key, AES_256_KEY_SIZE); + } +#endif + wc_encrypt = &ssl->encrypt; + break; + + case DECRYPT_SIDE_ONLY: +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Provisioning DECRYPT key"); + if (ssl->options.side == WOLFSSL_CLIENT_END) { + WOLFSSL_BUFFER(ssl->keys.server_write_key, AES_256_KEY_SIZE); + } + else { + WOLFSSL_BUFFER(ssl->keys.client_write_key, AES_256_KEY_SIZE); + } +#endif + wc_decrypt = &ssl->decrypt; + break; + + case ENCRYPT_AND_DECRYPT_SIDE: +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Provisioning ENCRYPT key"); + if (ssl->options.side == WOLFSSL_CLIENT_END) { + WOLFSSL_BUFFER(ssl->keys.client_write_key, AES_256_KEY_SIZE); + } + else { + WOLFSSL_BUFFER(ssl->keys.server_write_key, AES_256_KEY_SIZE); + } + WOLFSSL_MSG("Provisioning DECRYPT key"); + if (ssl->options.side == WOLFSSL_CLIENT_END) { + WOLFSSL_BUFFER(ssl->keys.server_write_key, AES_256_KEY_SIZE); + } + else { + WOLFSSL_BUFFER(ssl->keys.client_write_key, AES_256_KEY_SIZE); + } +#endif + wc_encrypt = &ssl->encrypt; + wc_decrypt = &ssl->decrypt; + break; + + default: + return BAD_FUNC_ARG; + } + +#ifdef HAVE_ONE_TIME_AUTH + if (!ssl->auth.setup && ssl->specs.bulk_cipher_algorithm == wolfssl_chacha){ + ret = SetAuthKeys(&ssl->auth, keys, &ssl->specs, ssl->heap, ssl->devId); + if (ret != 0) + return ret; + } +#endif + + ret = SetKeys(wc_encrypt, wc_decrypt, keys, &ssl->specs, ssl->options.side, + ssl->heap, ssl->devId, ssl->rng, ssl->options.tls1_3); + +#ifdef HAVE_SECURE_RENEGOTIATION + if (copy) { + int clientCopy = 0; + + if (ssl->options.side == WOLFSSL_CLIENT_END && wc_encrypt) + clientCopy = 1; + else if (ssl->options.side == WOLFSSL_SERVER_END && wc_decrypt) + clientCopy = 1; + + if (clientCopy) { + #ifndef WOLFSSL_AEAD_ONLY + XMEMCPY(ssl->keys.client_write_MAC_secret, + keys->client_write_MAC_secret, WC_MAX_DIGEST_SIZE); + #endif + XMEMCPY(ssl->keys.client_write_key, + keys->client_write_key, AES_256_KEY_SIZE); + XMEMCPY(ssl->keys.client_write_IV, + keys->client_write_IV, MAX_WRITE_IV_SZ); + } else { + #ifndef WOLFSSL_AEAD_ONLY + XMEMCPY(ssl->keys.server_write_MAC_secret, + keys->server_write_MAC_secret, WC_MAX_DIGEST_SIZE); + #endif + XMEMCPY(ssl->keys.server_write_key, + keys->server_write_key, AES_256_KEY_SIZE); + XMEMCPY(ssl->keys.server_write_IV, + keys->server_write_IV, MAX_WRITE_IV_SZ); + } + if (wc_encrypt) { + ssl->keys.sequence_number_hi = keys->sequence_number_hi; + ssl->keys.sequence_number_lo = keys->sequence_number_lo; + #ifdef HAVE_AEAD + if (ssl->specs.cipher_type == aead) { + /* Initialize the AES-GCM/CCM explicit IV to a zero. */ + XMEMCPY(ssl->keys.aead_exp_IV, keys->aead_exp_IV, + AEAD_MAX_EXP_SZ); + + /* Initialize encrypt implicit IV by encrypt side */ + if (ssl->options.side == WOLFSSL_CLIENT_END) { + XMEMCPY(ssl->keys.aead_enc_imp_IV, + keys->client_write_IV, AEAD_MAX_IMP_SZ); + } else { + XMEMCPY(ssl->keys.aead_enc_imp_IV, + keys->server_write_IV, AEAD_MAX_IMP_SZ); + } + } + #endif + } + if (wc_decrypt) { + ssl->keys.peer_sequence_number_hi = keys->peer_sequence_number_hi; + ssl->keys.peer_sequence_number_lo = keys->peer_sequence_number_lo; + #ifdef HAVE_AEAD + if (ssl->specs.cipher_type == aead) { + /* Initialize decrypt implicit IV by decrypt side */ + if (ssl->options.side == WOLFSSL_SERVER_END) { + XMEMCPY(ssl->keys.aead_dec_imp_IV, + keys->client_write_IV, AEAD_MAX_IMP_SZ); + } else { + XMEMCPY(ssl->keys.aead_dec_imp_IV, + keys->server_write_IV, AEAD_MAX_IMP_SZ); + } + } + #endif + } + CacheStatusPP(ssl->secure_renegotiation); + } +#endif /* HAVE_SECURE_RENEGOTIATION */ + + return ret; +} + + +/* TLS can call too */ +int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side) +{ + int sz, i = 0; + Keys* keys = &ssl->keys; + +#ifdef HAVE_SECURE_RENEGOTIATION + if (ssl->secure_renegotiation && ssl->secure_renegotiation->cache_status == + SCR_CACHE_NEEDED) { + keys = &ssl->secure_renegotiation->tmp_keys; + CacheStatusPP(ssl->secure_renegotiation); + } +#endif /* HAVE_SECURE_RENEGOTIATION */ + +#ifdef WOLFSSL_MULTICAST + if (ssl->options.haveMcast) { + /* Use the same keys for encrypt and decrypt. */ + if (ssl->specs.cipher_type != aead) { + sz = ssl->specs.hash_size; + #ifndef WOLFSSL_AEAD_ONLY + XMEMCPY(keys->client_write_MAC_secret,&keyData[i], sz); + XMEMCPY(keys->server_write_MAC_secret,&keyData[i], sz); + #endif + i += sz; + } + sz = ssl->specs.key_size; + XMEMCPY(keys->client_write_key, &keyData[i], sz); + XMEMCPY(keys->server_write_key, &keyData[i], sz); + i += sz; + + sz = ssl->specs.iv_size; + XMEMCPY(keys->client_write_IV, &keyData[i], sz); + XMEMCPY(keys->server_write_IV, &keyData[i], sz); + +#ifdef HAVE_AEAD + if (ssl->specs.cipher_type == aead) { + /* Initialize the AES-GCM/CCM explicit IV to a zero. */ + XMEMSET(keys->aead_exp_IV, 0, AEAD_MAX_EXP_SZ); + } +#endif /* HAVE_AEAD */ + + return 0; + } +#endif /* WOLFSSL_MULTICAST */ + + if (ssl->specs.cipher_type != aead) { + sz = ssl->specs.hash_size; + if (side & PROVISION_CLIENT) { + #ifndef WOLFSSL_AEAD_ONLY + XMEMCPY(keys->client_write_MAC_secret,&keyData[i], sz); + #endif + i += sz; + } + if (side & PROVISION_SERVER) { + #ifndef WOLFSSL_AEAD_ONLY + XMEMCPY(keys->server_write_MAC_secret,&keyData[i], sz); + #endif + i += sz; + } + } + sz = ssl->specs.key_size; + if (side & PROVISION_CLIENT) { + XMEMCPY(keys->client_write_key, &keyData[i], sz); + i += sz; + } + if (side & PROVISION_SERVER) { + XMEMCPY(keys->server_write_key, &keyData[i], sz); + i += sz; + } + + sz = ssl->specs.iv_size; + if (side & PROVISION_CLIENT) { + XMEMCPY(keys->client_write_IV, &keyData[i], sz); + i += sz; + } + if (side & PROVISION_SERVER) + XMEMCPY(keys->server_write_IV, &keyData[i], sz); + +#ifdef HAVE_AEAD + if (ssl->specs.cipher_type == aead) { + /* Initialize the AES-GCM/CCM explicit IV to a zero. */ + XMEMSET(keys->aead_exp_IV, 0, AEAD_MAX_EXP_SZ); + } +#endif + + return 0; +} + +#ifndef NO_OLD_TLS +int DeriveKeys(WOLFSSL* ssl) +{ + int length = 2 * ssl->specs.hash_size + + 2 * ssl->specs.key_size + + 2 * ssl->specs.iv_size; + int rounds = (length + WC_MD5_DIGEST_SIZE - 1 ) / WC_MD5_DIGEST_SIZE, i; + int ret = 0; + +#ifdef WOLFSSL_SMALL_STACK + byte* shaOutput; + byte* md5Input; + byte* shaInput; + byte* keyData; + wc_Md5* md5; + wc_Sha* sha; +#else + byte shaOutput[WC_SHA_DIGEST_SIZE]; + byte md5Input[SECRET_LEN + WC_SHA_DIGEST_SIZE]; + byte shaInput[KEY_PREFIX + SECRET_LEN + 2 * RAN_LEN]; + byte keyData[KEY_PREFIX * WC_MD5_DIGEST_SIZE]; + wc_Md5 md5[1]; + wc_Sha sha[1]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + shaOutput = (byte*)XMALLOC(WC_SHA_DIGEST_SIZE, + NULL, DYNAMIC_TYPE_TMP_BUFFER); + md5Input = (byte*)XMALLOC(SECRET_LEN + WC_SHA_DIGEST_SIZE, + NULL, DYNAMIC_TYPE_TMP_BUFFER); + shaInput = (byte*)XMALLOC(KEY_PREFIX + SECRET_LEN + 2 * RAN_LEN, + NULL, DYNAMIC_TYPE_TMP_BUFFER); + keyData = (byte*)XMALLOC(KEY_PREFIX * WC_MD5_DIGEST_SIZE, + NULL, DYNAMIC_TYPE_TMP_BUFFER); + md5 = (wc_Md5*)XMALLOC(sizeof(wc_Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER); + sha = (wc_Sha*)XMALLOC(sizeof(wc_Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER); + + if (shaOutput == NULL || md5Input == NULL || shaInput == NULL || + keyData == NULL || md5 == NULL || sha == NULL) { + if (shaOutput) XFREE(shaOutput, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (md5Input) XFREE(md5Input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (shaInput) XFREE(shaInput, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (keyData) XFREE(keyData, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (md5) XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (sha) XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return MEMORY_E; + } +#endif + + ret = wc_InitMd5(md5); + if (ret == 0) { + ret = wc_InitSha(sha); + } + if (ret == 0) { + XMEMCPY(md5Input, ssl->arrays->masterSecret, SECRET_LEN); + + for (i = 0; i < rounds; ++i) { + int j = i + 1; + int idx = j; + + if (!SetPrefix(shaInput, i)) { + ret = PREFIX_ERROR; + break; + } + + XMEMCPY(shaInput + idx, ssl->arrays->masterSecret, SECRET_LEN); + idx += SECRET_LEN; + XMEMCPY(shaInput + idx, ssl->arrays->serverRandom, RAN_LEN); + idx += RAN_LEN; + XMEMCPY(shaInput + idx, ssl->arrays->clientRandom, RAN_LEN); + if (ret == 0) { + ret = wc_ShaUpdate(sha, shaInput, + (KEY_PREFIX + SECRET_LEN + 2 * RAN_LEN) - KEY_PREFIX + j); + } + if (ret == 0) { + ret = wc_ShaFinal(sha, shaOutput); + } + + XMEMCPY(md5Input + SECRET_LEN, shaOutput, WC_SHA_DIGEST_SIZE); + if (ret == 0) { + ret = wc_Md5Update(md5, md5Input, SECRET_LEN + WC_SHA_DIGEST_SIZE); + } + if (ret == 0) { + ret = wc_Md5Final(md5, keyData + i * WC_MD5_DIGEST_SIZE); + } + } + + if (ret == 0) + ret = StoreKeys(ssl, keyData, PROVISION_CLIENT_SERVER); + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(shaOutput, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(md5Input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(shaInput, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyData, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + + +static int CleanPreMaster(WOLFSSL* ssl) +{ + int i, ret, sz = ssl->arrays->preMasterSz; + + for (i = 0; i < sz; i++) + ssl->arrays->preMasterSecret[i] = 0; + + ret = wc_RNG_GenerateBlock(ssl->rng, ssl->arrays->preMasterSecret, sz); + if (ret != 0) + return ret; + + for (i = 0; i < sz; i++) + ssl->arrays->preMasterSecret[i] = 0; + + XFREE(ssl->arrays->preMasterSecret, ssl->heap, DYNAMIC_TYPE_SECRET); + ssl->arrays->preMasterSecret = NULL; + ssl->arrays->preMasterSz = 0; + + return 0; +} + + +/* Create and store the master secret see page 32, 6.1 */ +static int MakeSslMasterSecret(WOLFSSL* ssl) +{ + int i, ret; + word32 idx; + word32 pmsSz = ssl->arrays->preMasterSz; + +#ifdef WOLFSSL_SMALL_STACK + byte* shaOutput; + byte* md5Input; + byte* shaInput; + wc_Md5* md5; + wc_Sha* sha; +#else + byte shaOutput[WC_SHA_DIGEST_SIZE]; + byte md5Input[ENCRYPT_LEN + WC_SHA_DIGEST_SIZE]; + byte shaInput[PREFIX + ENCRYPT_LEN + 2 * RAN_LEN]; + wc_Md5 md5[1]; + wc_Sha sha[1]; +#endif + +#ifdef SHOW_SECRETS + { + word32 j; + printf("pre master secret: "); + for (j = 0; j < pmsSz; j++) + printf("%02x", ssl->arrays->preMasterSecret[j]); + printf("\n"); + } +#endif + +#ifdef WOLFSSL_SMALL_STACK + shaOutput = (byte*)XMALLOC(WC_SHA_DIGEST_SIZE, + NULL, DYNAMIC_TYPE_TMP_BUFFER); + md5Input = (byte*)XMALLOC(ENCRYPT_LEN + WC_SHA_DIGEST_SIZE, + NULL, DYNAMIC_TYPE_TMP_BUFFER); + shaInput = (byte*)XMALLOC(PREFIX + ENCRYPT_LEN + 2 * RAN_LEN, + NULL, DYNAMIC_TYPE_TMP_BUFFER); + md5 = (wc_Md5*)XMALLOC(sizeof(wc_Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER); + sha = (wc_Sha*)XMALLOC(sizeof(wc_Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER); + + if (shaOutput == NULL || md5Input == NULL || shaInput == NULL || + md5 == NULL || sha == NULL) { + if (shaOutput) XFREE(shaOutput, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (md5Input) XFREE(md5Input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (shaInput) XFREE(shaInput, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (md5) XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (sha) XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return MEMORY_E; + } +#endif + + ret = wc_InitMd5(md5); + if (ret == 0) { + ret = wc_InitSha(sha); + } + if (ret == 0) { + XMEMCPY(md5Input, ssl->arrays->preMasterSecret, pmsSz); + + for (i = 0; i < MASTER_ROUNDS; ++i) { + byte prefix[KEY_PREFIX]; /* only need PREFIX bytes but static */ + if (!SetPrefix(prefix, i)) { /* analysis thinks will overrun */ + ret = PREFIX_ERROR; + break; + } + + idx = 0; + XMEMCPY(shaInput, prefix, i + 1); + idx += i + 1; + + XMEMCPY(shaInput + idx, ssl->arrays->preMasterSecret, pmsSz); + idx += pmsSz; + XMEMCPY(shaInput + idx, ssl->arrays->clientRandom, RAN_LEN); + idx += RAN_LEN; + XMEMCPY(shaInput + idx, ssl->arrays->serverRandom, RAN_LEN); + idx += RAN_LEN; + if (ret == 0) { + ret = wc_ShaUpdate(sha, shaInput, idx); + } + if (ret == 0) { + ret = wc_ShaFinal(sha, shaOutput); + } + idx = pmsSz; /* preSz */ + XMEMCPY(md5Input + idx, shaOutput, WC_SHA_DIGEST_SIZE); + idx += WC_SHA_DIGEST_SIZE; + if (ret == 0) { + ret = wc_Md5Update(md5, md5Input, idx); + } + if (ret == 0) { + ret = wc_Md5Final(md5, + &ssl->arrays->masterSecret[i * WC_MD5_DIGEST_SIZE]); + } + } + +#ifdef SHOW_SECRETS + { + word32 j; + printf("master secret: "); + for (j = 0; j < SECRET_LEN; j++) + printf("%02x", ssl->arrays->masterSecret[j]); + printf("\n"); + } +#endif + + if (ret == 0) + ret = DeriveKeys(ssl); + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(shaOutput, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(md5Input, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(shaInput, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + if (ret == 0) + ret = CleanPreMaster(ssl); + else + CleanPreMaster(ssl); + + return ret; +} +#endif + + +/* Master wrapper, doesn't use SSL stack space in TLS mode */ +int MakeMasterSecret(WOLFSSL* ssl) +{ + /* append secret to premaster : premaster | SerSi | CliSi */ +#ifdef HAVE_QSH + word32 offset = 0; + + if (ssl->peerQSHKeyPresent) { + offset += ssl->arrays->preMasterSz; + ssl->arrays->preMasterSz += ssl->QSH_secret->CliSi->length + + ssl->QSH_secret->SerSi->length; + /* test and set flag if QSH has been used */ + if (ssl->QSH_secret->CliSi->length > 0 || + ssl->QSH_secret->SerSi->length > 0) + ssl->isQSH = 1; + + /* append secrets to the premaster */ + if (ssl->QSH_secret->SerSi != NULL) { + XMEMCPY(ssl->arrays->preMasterSecret + offset, + ssl->QSH_secret->SerSi->buffer, ssl->QSH_secret->SerSi->length); + } + offset += ssl->QSH_secret->SerSi->length; + if (ssl->QSH_secret->CliSi != NULL) { + XMEMCPY(ssl->arrays->preMasterSecret + offset, + ssl->QSH_secret->CliSi->buffer, ssl->QSH_secret->CliSi->length); + } + + /* show secret SerSi and CliSi */ + #ifdef SHOW_SECRETS + { + word32 j; + printf("QSH generated secret material\n"); + printf("SerSi : "); + for (j = 0; j < ssl->QSH_secret->SerSi->length; j++) { + printf("%02x", ssl->QSH_secret->SerSi->buffer[j]); + } + printf("\n"); + printf("CliSi : "); + for (j = 0; j < ssl->QSH_secret->CliSi->length; j++) { + printf("%02x", ssl->QSH_secret->CliSi->buffer[j]); + } + printf("\n"); + } + #endif + } +#endif + +#ifndef NO_OLD_TLS + if (ssl->options.tls) return MakeTlsMasterSecret(ssl); + return MakeSslMasterSecret(ssl); +#elif !defined(WOLFSSL_NO_TLS12) + return MakeTlsMasterSecret(ssl); +#else + (void)ssl; + return 0; +#endif +} + +#endif /* WOLFCRYPT_ONLY */ + diff --git a/beken_os/beken378/func/wolfssl/src/ocsp.c b/beken_os/beken378/func/wolfssl/src/ocsp.c new file mode 100755 index 0000000..17c4a83 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/src/ocsp.c @@ -0,0 +1,879 @@ +/* ocsp.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + /* Name change compatibility layer no longer needs to be included here */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifndef WOLFCRYPT_ONLY +#ifdef HAVE_OCSP + +#include +#include +#include + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + + +int InitOCSP(WOLFSSL_OCSP* ocsp, WOLFSSL_CERT_MANAGER* cm) +{ + WOLFSSL_ENTER("InitOCSP"); + + ForceZero(ocsp, sizeof(WOLFSSL_OCSP)); + + if (wc_InitMutex(&ocsp->ocspLock) != 0) + return BAD_MUTEX_E; + + ocsp->cm = cm; + + return 0; +} + + +static int InitOcspEntry(OcspEntry* entry, OcspRequest* request) +{ + WOLFSSL_ENTER("InitOcspEntry"); + + ForceZero(entry, sizeof(OcspEntry)); + + XMEMCPY(entry->issuerHash, request->issuerHash, OCSP_DIGEST_SIZE); + XMEMCPY(entry->issuerKeyHash, request->issuerKeyHash, OCSP_DIGEST_SIZE); + + return 0; +} + + +static void FreeOcspEntry(OcspEntry* entry, void* heap) +{ + CertStatus *status, *next; + + WOLFSSL_ENTER("FreeOcspEntry"); + + for (status = entry->status; status; status = next) { + next = status->next; + + if (status->rawOcspResponse) + XFREE(status->rawOcspResponse, heap, DYNAMIC_TYPE_OCSP_STATUS); + + XFREE(status, heap, DYNAMIC_TYPE_OCSP_STATUS); + } + + (void)heap; +} + + +void FreeOCSP(WOLFSSL_OCSP* ocsp, int dynamic) +{ + OcspEntry *entry, *next; + + WOLFSSL_ENTER("FreeOCSP"); + + for (entry = ocsp->ocspList; entry; entry = next) { + next = entry->next; + FreeOcspEntry(entry, ocsp->cm->heap); + XFREE(entry, ocsp->cm->heap, DYNAMIC_TYPE_OCSP_ENTRY); + } + + wc_FreeMutex(&ocsp->ocspLock); + + if (dynamic) + XFREE(ocsp, ocsp->cm->heap, DYNAMIC_TYPE_OCSP); + +} + + +static int xstat2err(int st) +{ + switch (st) { + case CERT_GOOD: + return 0; + case CERT_REVOKED: + return OCSP_CERT_REVOKED; + default: + return OCSP_CERT_UNKNOWN; + } +} + +int CheckCertOCSP_ex(WOLFSSL_OCSP* ocsp, DecodedCert* cert, buffer* responseBuffer, WOLFSSL* ssl) +{ + int ret = OCSP_LOOKUP_FAIL; + +#ifdef WOLFSSL_SMALL_STACK + OcspRequest* ocspRequest; +#else + OcspRequest ocspRequest[1]; +#endif + + WOLFSSL_ENTER("CheckCertOCSP"); + + +#ifdef WOLFSSL_SMALL_STACK + ocspRequest = (OcspRequest*)XMALLOC(sizeof(OcspRequest), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (ocspRequest == NULL) { + WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR); + return MEMORY_E; + } +#endif + + if (InitOcspRequest(ocspRequest, cert, ocsp->cm->ocspSendNonce, + ocsp->cm->heap) == 0) { + ocspRequest->ssl = ssl; + ret = CheckOcspRequest(ocsp, ocspRequest, responseBuffer); + + FreeOcspRequest(ocspRequest); + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(ocspRequest, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + WOLFSSL_LEAVE("CheckCertOCSP", ret); + return ret; +} +int CheckCertOCSP(WOLFSSL_OCSP* ocsp, DecodedCert* cert, buffer* responseBuffer) +{ + return CheckCertOCSP_ex(ocsp, cert, responseBuffer, NULL); +} + +static int GetOcspEntry(WOLFSSL_OCSP* ocsp, OcspRequest* request, + OcspEntry** entry) +{ + WOLFSSL_ENTER("GetOcspEntry"); + + *entry = NULL; + + if (wc_LockMutex(&ocsp->ocspLock) != 0) { + WOLFSSL_LEAVE("CheckCertOCSP", BAD_MUTEX_E); + return BAD_MUTEX_E; + } + + for (*entry = ocsp->ocspList; *entry; *entry = (*entry)->next) + if (XMEMCMP((*entry)->issuerHash, request->issuerHash, + OCSP_DIGEST_SIZE) == 0 + && XMEMCMP((*entry)->issuerKeyHash, request->issuerKeyHash, + OCSP_DIGEST_SIZE) == 0) + break; + + if (*entry == NULL) { + *entry = (OcspEntry*)XMALLOC(sizeof(OcspEntry), + ocsp->cm->heap, DYNAMIC_TYPE_OCSP_ENTRY); + if (*entry) { + InitOcspEntry(*entry, request); + (*entry)->next = ocsp->ocspList; + ocsp->ocspList = *entry; + } + } + + wc_UnLockMutex(&ocsp->ocspLock); + + return *entry ? 0 : MEMORY_ERROR; +} + + +/* Mallocs responseBuffer->buffer and is up to caller to free on success + * + * Returns OCSP status + */ +static int GetOcspStatus(WOLFSSL_OCSP* ocsp, OcspRequest* request, + OcspEntry* entry, CertStatus** status, buffer* responseBuffer) +{ + int ret = OCSP_INVALID_STATUS; + + WOLFSSL_ENTER("GetOcspStatus"); + + *status = NULL; + + if (wc_LockMutex(&ocsp->ocspLock) != 0) { + WOLFSSL_LEAVE("CheckCertOCSP", BAD_MUTEX_E); + return BAD_MUTEX_E; + } + + for (*status = entry->status; *status; *status = (*status)->next) + if ((*status)->serialSz == request->serialSz + && !XMEMCMP((*status)->serial, request->serial, (*status)->serialSz)) + break; + + if (responseBuffer && *status && !(*status)->rawOcspResponse) { + /* force fetching again */ + ret = OCSP_INVALID_STATUS; + } + else if (*status) { +#ifndef NO_ASN_TIME + if (XVALIDATE_DATE((*status)->thisDate, + (*status)->thisDateFormat, BEFORE) + && ((*status)->nextDate[0] != 0) + && XVALIDATE_DATE((*status)->nextDate, + (*status)->nextDateFormat, AFTER)) +#endif + { + ret = xstat2err((*status)->status); + + if (responseBuffer) { + responseBuffer->buffer = (byte*)XMALLOC( + (*status)->rawOcspResponseSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + if (responseBuffer->buffer) { + responseBuffer->length = (*status)->rawOcspResponseSz; + XMEMCPY(responseBuffer->buffer, + (*status)->rawOcspResponse, + (*status)->rawOcspResponseSz); + } + } + } + } + + wc_UnLockMutex(&ocsp->ocspLock); + + return ret; +} + +/* Check that the response for validity. Store result in status. + * + * ocsp Context object for OCSP status. + * response OCSP response message data. + * responseSz Length of OCSP response message data. + * reponseBuffer Buffer object to return the response with. + * status The certificate status object. + * entry The OCSP entry for this certificate. + * returns OCSP_LOOKUP_FAIL when the response is bad and 0 otherwise. + */ +WOLFSSL_LOCAL int CheckOcspResponse(WOLFSSL_OCSP *ocsp, byte *response, int responseSz, + WOLFSSL_BUFFER_INFO *responseBuffer, CertStatus *status, + OcspEntry *entry, OcspRequest *ocspRequest) +{ +#ifdef WOLFSSL_SMALL_STACK + CertStatus* newStatus; + OcspResponse* ocspResponse; +#else + CertStatus newStatus[1]; + OcspResponse ocspResponse[1]; +#endif + int ret; + int validated = 0; /* ocsp validation flag */ + +#ifdef WOLFSSL_SMALL_STACK + newStatus = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + ocspResponse = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + + if (newStatus == NULL || ocspResponse == NULL) { + if (newStatus) XFREE(newStatus, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (ocspResponse) XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR); + return MEMORY_E; + } +#endif + XMEMSET(newStatus, 0, sizeof(CertStatus)); + + InitOcspResponse(ocspResponse, newStatus, response, responseSz); + ret = OcspResponseDecode(ocspResponse, ocsp->cm, ocsp->cm->heap, 0); + if (ret != 0) { + WOLFSSL_MSG("OcspResponseDecode failed"); + goto end; + } + + if (ocspResponse->responseStatus != OCSP_SUCCESSFUL) { + WOLFSSL_MSG("OcspResponse status bad"); + goto end; + } + if (ocspRequest != NULL) { + ret = CompareOcspReqResp(ocspRequest, ocspResponse); + if (ret != 0) { + goto end; + } + } + + if (responseBuffer) { + responseBuffer->buffer = (byte*)XMALLOC(responseSz, ocsp->cm->heap, + DYNAMIC_TYPE_TMP_BUFFER); + + if (responseBuffer->buffer) { + responseBuffer->length = responseSz; + XMEMCPY(responseBuffer->buffer, response, responseSz); + } + } + + ret = xstat2err(ocspResponse->status->status); + if (ret == 0) { + validated = 1; + } + + if (wc_LockMutex(&ocsp->ocspLock) != 0) { + ret = BAD_MUTEX_E; + goto end; + } + + if (status != NULL) { + if (status->rawOcspResponse) { + XFREE(status->rawOcspResponse, ocsp->cm->heap, + DYNAMIC_TYPE_OCSP_STATUS); + } + + /* Replace existing certificate entry with updated */ + newStatus->next = status->next; + XMEMCPY(status, newStatus, sizeof(CertStatus)); + } + else { + /* Save new certificate entry */ + status = (CertStatus*)XMALLOC(sizeof(CertStatus), + ocsp->cm->heap, DYNAMIC_TYPE_OCSP_STATUS); + if (status != NULL) { + XMEMCPY(status, newStatus, sizeof(CertStatus)); + status->next = entry->status; + entry->status = status; + entry->totalStatus++; + } + } + + if (status && responseBuffer && responseBuffer->buffer) { + status->rawOcspResponse = (byte*)XMALLOC(responseBuffer->length, + ocsp->cm->heap, + DYNAMIC_TYPE_OCSP_STATUS); + + if (status->rawOcspResponse) { + status->rawOcspResponseSz = responseBuffer->length; + XMEMCPY(status->rawOcspResponse, responseBuffer->buffer, + responseBuffer->length); + } + } + + wc_UnLockMutex(&ocsp->ocspLock); + +end: + if (ret == 0 && validated == 1) { + WOLFSSL_MSG("New OcspResponse validated"); + } else if (ret != OCSP_CERT_REVOKED) { + ret = OCSP_LOOKUP_FAIL; + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(newStatus, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(ocspResponse, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; +} + +/* 0 on success */ +int CheckOcspRequest(WOLFSSL_OCSP* ocsp, OcspRequest* ocspRequest, + buffer* responseBuffer) +{ + OcspEntry* entry = NULL; + CertStatus* status = NULL; + byte* request = NULL; + int requestSz = 2048; + int responseSz = 0; + byte* response = NULL; + const char* url = NULL; + int urlSz = 0; + int ret = -1; + WOLFSSL* ssl; + void* ioCtx; + + WOLFSSL_ENTER("CheckOcspRequest"); + + if (ocsp == NULL || ocspRequest == NULL) + return BAD_FUNC_ARG; + + if (responseBuffer) { + responseBuffer->buffer = NULL; + responseBuffer->length = 0; + } + + ret = GetOcspEntry(ocsp, ocspRequest, &entry); + if (ret != 0) + return ret; + + ret = GetOcspStatus(ocsp, ocspRequest, entry, &status, responseBuffer); + if (ret != OCSP_INVALID_STATUS) + return ret; + + /* get SSL and IOCtx */ + ssl = (WOLFSSL*)ocspRequest->ssl; + ioCtx = (ssl && ssl->ocspIOCtx != NULL) ? + ssl->ocspIOCtx : ocsp->cm->ocspIOCtx; + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + if (ocsp->statusCb != NULL && ssl != NULL) { + ret = ocsp->statusCb(ssl, ioCtx); + if (ret == 0) { + ret = wolfSSL_get_ocsp_response(ssl, &response); + ret = CheckOcspResponse(ocsp, response, ret, responseBuffer, status, + entry, NULL); + if (response != NULL) + XFREE(response, NULL, DYNAMIC_TYPE_OPENSSL); + return ret; + } + return OCSP_LOOKUP_FAIL; + } +#endif + + if (ocsp->cm->ocspUseOverrideURL) { + url = ocsp->cm->ocspOverrideURL; + if (url != NULL && url[0] != '\0') + urlSz = (int)XSTRLEN(url); + else + return OCSP_NEED_URL; + } + else if (ocspRequest->urlSz != 0 && ocspRequest->url != NULL) { + url = (const char *)ocspRequest->url; + urlSz = ocspRequest->urlSz; + } + else { + /* cert doesn't have extAuthInfo, assuming CERT_GOOD */ + return 0; + } + + request = (byte*)XMALLOC(requestSz, ocsp->cm->heap, DYNAMIC_TYPE_OCSP); + if (request == NULL) { + WOLFSSL_LEAVE("CheckCertOCSP", MEMORY_ERROR); + if (responseBuffer) { + XFREE(responseBuffer->buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER); + responseBuffer->buffer = NULL; + } + return MEMORY_ERROR; + } + + requestSz = EncodeOcspRequest(ocspRequest, request, requestSz); + if (requestSz > 0 && ocsp->cm->ocspIOCb) { + responseSz = ocsp->cm->ocspIOCb(ioCtx, url, urlSz, + request, requestSz, &response); + } + if (responseSz == WOLFSSL_CBIO_ERR_WANT_READ) { + ret = OCSP_WANT_READ; + } + + XFREE(request, ocsp->cm->heap, DYNAMIC_TYPE_OCSP); + + if (responseSz >= 0 && response) { + ret = CheckOcspResponse(ocsp, response, responseSz, responseBuffer, status, + entry, ocspRequest); + } + + if (response != NULL && ocsp->cm->ocspRespFreeCb) + ocsp->cm->ocspRespFreeCb(ioCtx, response); + + /* Keep responseBuffer in the case of getting to response check. Caller + * should free responseBuffer after checking OCSP return value in "ret" */ + WOLFSSL_LEAVE("CheckOcspRequest", ret); + return ret; +} + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + +int wolfSSL_OCSP_resp_find_status(WOLFSSL_OCSP_BASICRESP *bs, + WOLFSSL_OCSP_CERTID* id, int* status, int* reason, + WOLFSSL_ASN1_TIME** revtime, WOLFSSL_ASN1_TIME** thisupd, + WOLFSSL_ASN1_TIME** nextupd) +{ + if (bs == NULL || id == NULL) + return WOLFSSL_FAILURE; + + /* Only supporting one certificate status in asn.c. */ + if (CompareOcspReqResp(id, bs) != 0) + return WOLFSSL_FAILURE; + + if (status != NULL) + *status = bs->status->status; + if (thisupd != NULL) + *thisupd = (WOLFSSL_ASN1_TIME*)bs->status->thisDateAsn; + if (nextupd != NULL) + *nextupd = (WOLFSSL_ASN1_TIME*)bs->status->nextDateAsn; + + /* TODO: Not needed for Nginx. */ + if (reason != NULL) + *reason = 0; + if (revtime != NULL) + *revtime = NULL; + + return WOLFSSL_SUCCESS; +} + +const char *wolfSSL_OCSP_cert_status_str(long s) +{ + switch (s) { + case CERT_GOOD: + return "good"; + case CERT_REVOKED: + return "revoked"; + case CERT_UNKNOWN: + return "unknown"; + default: + return "(UNKNOWN)"; + } +} + +int wolfSSL_OCSP_check_validity(WOLFSSL_ASN1_TIME* thisupd, + WOLFSSL_ASN1_TIME* nextupd, long sec, long maxsec) +{ + (void)thisupd; + (void)nextupd; + (void)sec; + (void)maxsec; + /* Dates validated in DecodeSingleResponse. */ + return WOLFSSL_SUCCESS; +} + +void wolfSSL_OCSP_CERTID_free(WOLFSSL_OCSP_CERTID* certId) +{ + FreeOcspRequest(certId); + XFREE(certId, NULL, DYNAMIC_TYPE_OPENSSL); +} + +WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_cert_to_id( + const WOLFSSL_EVP_MD *dgst, const WOLFSSL_X509 *subject, + const WOLFSSL_X509 *issuer) +{ + WOLFSSL_OCSP_CERTID* certId; + DecodedCert cert; + WOLFSSL_CERT_MANAGER* cm; + int ret; + DerBuffer* derCert = NULL; + + (void)dgst; + + cm = wolfSSL_CertManagerNew(); + if (cm == NULL) + return NULL; + + ret = AllocDer(&derCert, issuer->derCert->length, + issuer->derCert->type, NULL); + if (ret == 0) { + /* AddCA() frees the buffer. */ + XMEMCPY(derCert->buffer, issuer->derCert->buffer, + issuer->derCert->length); + AddCA(cm, &derCert, WOLFSSL_USER_CA, 1); + } + + certId = (WOLFSSL_OCSP_CERTID*)XMALLOC(sizeof(WOLFSSL_OCSP_CERTID), NULL, + DYNAMIC_TYPE_OPENSSL); + if (certId != NULL) { + InitDecodedCert(&cert, subject->derCert->buffer, + subject->derCert->length, NULL); + if (ParseCertRelative(&cert, CERT_TYPE, VERIFY_OCSP, cm) != 0) { + XFREE(certId, NULL, DYNAMIC_TYPE_OPENSSL); + certId = NULL; + } + else { + ret = InitOcspRequest(certId, &cert, 0, NULL); + if (ret != 0) { + XFREE(certId, NULL, DYNAMIC_TYPE_OPENSSL); + certId = NULL; + } + } + FreeDecodedCert(&cert); + } + + wolfSSL_CertManagerFree(cm); + + return certId; +} + +void wolfSSL_OCSP_BASICRESP_free(WOLFSSL_OCSP_BASICRESP* basicResponse) +{ + wolfSSL_OCSP_RESPONSE_free(basicResponse); +} + +/* Signature verified in DecodeBasicOcspResponse. + * But no store available to verify certificate. */ +int wolfSSL_OCSP_basic_verify(WOLFSSL_OCSP_BASICRESP *bs, + WOLF_STACK_OF(WOLFSSL_X509) *certs, WOLFSSL_X509_STORE *st, unsigned long flags) +{ + DecodedCert cert; + int ret = WOLFSSL_SUCCESS; + + (void)certs; + + if (flags & OCSP_NOVERIFY) + return WOLFSSL_SUCCESS; + +#ifdef OPENSSL_EXTRA + if (bs->verifyError != OCSP_VERIFY_ERROR_NONE) + return WOLFSSL_FAILURE; +#endif + + InitDecodedCert(&cert, bs->cert, bs->certSz, NULL); + if (ParseCertRelative(&cert, CERT_TYPE, VERIFY, st->cm) < 0) + ret = WOLFSSL_FAILURE; + FreeDecodedCert(&cert); + + return ret; +} + +void wolfSSL_OCSP_RESPONSE_free(OcspResponse* response) +{ + if (response->status != NULL) + XFREE(response->status, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (response->source != NULL) + XFREE(response->source, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(response, NULL, DYNAMIC_TYPE_OPENSSL); +} + +OcspResponse* wolfSSL_d2i_OCSP_RESPONSE_bio(WOLFSSL_BIO* bio, + OcspResponse** response) +{ + byte* data; + byte* p; + int len; + int dataAlloced = 0; + OcspResponse* ret = NULL; + + if (bio == NULL) + return NULL; + + if (bio->type == WOLFSSL_BIO_MEMORY) { + len = wolfSSL_BIO_get_mem_data(bio, &data); + if (len <= 0 || data == NULL) { + return NULL; + } + } +#ifndef NO_FILESYSTEM + else if (bio->type == WOLFSSL_BIO_FILE) { + long i; + long l; + + i = XFTELL(bio->file); + if (i < 0) + return NULL; + if(XFSEEK(bio->file, 0, SEEK_END) != 0) + return NULL; + l = XFTELL(bio->file); + if (l < 0) + return NULL; + if (XFSEEK(bio->file, i, SEEK_SET) != 0) + return NULL; + + /* check calculated length */ + if (l - i <= 0) + return NULL; + + data = (byte*)XMALLOC(l - i, 0, DYNAMIC_TYPE_TMP_BUFFER); + if (data == NULL) + return NULL; + dataAlloced = 1; + + len = wolfSSL_BIO_read(bio, (char *)data, (int)l); + } +#endif + else + return NULL; + + if (len > 0) { + p = data; + ret = wolfSSL_d2i_OCSP_RESPONSE(response, (const unsigned char **)&p, len); + } + + if (dataAlloced) + XFREE(data, 0, DYNAMIC_TYPE_TMP_BUFFER); + + return ret; +} + +OcspResponse* wolfSSL_d2i_OCSP_RESPONSE(OcspResponse** response, + const unsigned char** data, int len) +{ + OcspResponse *resp = NULL; + word32 idx = 0; + int length = 0; + + if (data == NULL) + return NULL; + + if (response != NULL) + resp = *response; + if (resp == NULL) { + resp = (OcspResponse*)XMALLOC(sizeof(OcspResponse), NULL, + DYNAMIC_TYPE_OPENSSL); + if (resp == NULL) + return NULL; + XMEMSET(resp, 0, sizeof(OcspResponse)); + } + + resp->source = (byte*)XMALLOC(len, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (resp->source == NULL) { + XFREE(resp, NULL, DYNAMIC_TYPE_OPENSSL); + return NULL; + } + resp->status = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (resp->status == NULL) { + XFREE(resp->source, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(resp, NULL, DYNAMIC_TYPE_OPENSSL); + return NULL; + } + + XMEMCPY(resp->source, *data, len); + resp->maxIdx = len; + + if (OcspResponseDecode(resp, NULL, NULL, 1) != 0) { + wolfSSL_OCSP_RESPONSE_free(resp); + return NULL; + } + + if (GetSequence(*data, &idx, &length, len) >= 0) + (*data) += idx + length; + + return resp; +} + +int wolfSSL_i2d_OCSP_RESPONSE(OcspResponse* response, + unsigned char** data) +{ + if (data == NULL) + return response->maxIdx; + + XMEMCPY(*data, response->source, response->maxIdx); + return response->maxIdx; +} + +int wolfSSL_OCSP_response_status(OcspResponse *response) +{ + return response->responseStatus; +} + +const char *wolfSSL_OCSP_response_status_str(long s) +{ + switch (s) { + case OCSP_SUCCESSFUL: + return "successful"; + case OCSP_MALFORMED_REQUEST: + return "malformedrequest"; + case OCSP_INTERNAL_ERROR: + return "internalerror"; + case OCSP_TRY_LATER: + return "trylater"; + case OCSP_SIG_REQUIRED: + return "sigrequired"; + case OCSP_UNAUTHROIZED: + return "unauthorized"; + default: + return "(UNKNOWN)"; + } +} + +WOLFSSL_OCSP_BASICRESP* wolfSSL_OCSP_response_get1_basic(OcspResponse* response) +{ + WOLFSSL_OCSP_BASICRESP* bs; + + bs = (WOLFSSL_OCSP_BASICRESP*)XMALLOC(sizeof(WOLFSSL_OCSP_BASICRESP), NULL, + DYNAMIC_TYPE_OPENSSL); + if (bs == NULL) + return NULL; + + XMEMCPY(bs, response, sizeof(OcspResponse)); + bs->status = (CertStatus*)XMALLOC(sizeof(CertStatus), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + bs->source = (byte*)XMALLOC(bs->maxIdx, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (bs->status == NULL || bs->source == NULL) { + if (bs->status) XFREE(bs->status, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (bs->source) XFREE(bs->source, NULL, DYNAMIC_TYPE_TMP_BUFFER); + wolfSSL_OCSP_RESPONSE_free(bs); + bs = NULL; + } + else { + XMEMCPY(bs->status, response->status, sizeof(CertStatus)); + XMEMCPY(bs->source, response->source, response->maxIdx); + } + return bs; +} + +OcspRequest* wolfSSL_OCSP_REQUEST_new(void) +{ + OcspRequest* request; + + request = (OcspRequest*)XMALLOC(sizeof(OcspRequest), NULL, + DYNAMIC_TYPE_OPENSSL); + if (request != NULL) + XMEMSET(request, 0, sizeof(OcspRequest)); + + return request; +} + +void wolfSSL_OCSP_REQUEST_free(OcspRequest* request) +{ + FreeOcspRequest(request); + XFREE(request, NULL, DYNAMIC_TYPE_OPENSSL); +} + +int wolfSSL_i2d_OCSP_REQUEST(OcspRequest* request, unsigned char** data) +{ + word32 size; + + size = EncodeOcspRequest(request, NULL, 0); + if (size <= 0 || data == NULL) + return size; + + return EncodeOcspRequest(request, *data, size); +} + +WOLFSSL_OCSP_ONEREQ* wolfSSL_OCSP_request_add0_id(OcspRequest *req, + WOLFSSL_OCSP_CERTID *cid) +{ + if (req == NULL || cid == NULL) + return NULL; + + FreeOcspRequest(req); + XMEMCPY(req, cid, sizeof(OcspRequest)); + + if (cid->serial != NULL) { + req->serial = (byte*)XMALLOC(cid->serialSz, NULL, + DYNAMIC_TYPE_OCSP_REQUEST); + req->url = (byte*)XMALLOC(cid->urlSz, NULL, DYNAMIC_TYPE_OCSP_REQUEST); + if (req->serial == NULL || req->url == NULL) { + FreeOcspRequest(req); + return NULL; + } + + XMEMCPY(req->serial, cid->serial, cid->serialSz); + XMEMCPY(req->url, cid->url, cid->urlSz); + } + + wolfSSL_OCSP_REQUEST_free(cid); + + return req; +} + +#endif + +#else /* HAVE_OCSP */ + + +#ifdef _MSC_VER + /* 4206 warning for blank file */ + #pragma warning(disable: 4206) +#endif + + +#endif /* HAVE_OCSP */ +#endif /* WOLFCRYPT_ONLY */ + diff --git a/beken_os/beken378/func/wolfssl/src/sniffer.c b/beken_os/beken378/func/wolfssl/src/sniffer.c new file mode 100755 index 0000000..65c3e82 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/src/sniffer.c @@ -0,0 +1,4237 @@ +/* sniffer.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifndef WOLFCRYPT_ONLY +#ifdef WOLFSSL_SNIFFER + +#include +#include + +#ifndef _WIN32 + #include +#endif + +#ifdef _WIN32 + #define SNPRINTF _snprintf +#else + #define SNPRINTF snprintf +#endif + +#include +#include +#include +#include +#include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + + +#ifndef WOLFSSL_SNIFFER_TIMEOUT + #define WOLFSSL_SNIFFER_TIMEOUT 900 + /* Cache unclosed Sessions for 15 minutes since last used */ +#endif + +/* Misc constants */ +enum { + MAX_SERVER_ADDRESS = 128, /* maximum server address length */ + MAX_SERVER_NAME = 128, /* maximum server name length */ + MAX_ERROR_LEN = 80, /* maximum error length */ + ETHER_IF_ADDR_LEN = 6, /* ethernet interface address length */ + LOCAL_IF_ADDR_LEN = 4, /* localhost interface address length, !windows */ + TCP_PROTO = 6, /* TCP_PROTOCOL */ + IP_HDR_SZ = 20, /* IP header length, min */ + TCP_HDR_SZ = 20, /* TCP header length, min */ + IPV4 = 4, /* IP version 4 */ + TCP_PROTOCOL = 6, /* TCP Protocol id */ + TRACE_MSG_SZ = 80, /* Trace Message buffer size */ + HASH_SIZE = 499, /* Session Hash Table Rows */ + PSEUDO_HDR_SZ = 12, /* TCP Pseudo Header size in bytes */ + FATAL_ERROR_STATE = 1, /* SnifferSession fatal error state */ + TICKET_HINT_LEN = 4, /* Session Ticket Hint length */ + EXT_TYPE_SZ = 2, /* Extension length */ + MAX_INPUT_SZ = MAX_RECORD_SIZE + COMP_EXTRA + MAX_MSG_EXTRA + + MTU_EXTRA, /* Max input sz of reassembly */ + EXT_MASTER_SECRET = 0x17, /* Extended Master Secret Extension ID */ + TICKET_EXT_ID = 0x23 /* Session Ticket Extension ID */ +}; + + +#ifdef _WIN32 + +static HMODULE dllModule; /* for error string resources */ + +BOOL APIENTRY DllMain( HMODULE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved + ) +{ + static int didInit = 0; + + switch (ul_reason_for_call) + { + case DLL_PROCESS_ATTACH: + if (didInit == 0) { + dllModule = hModule; + ssl_InitSniffer(); + didInit = 1; + } + break; + case DLL_THREAD_ATTACH: + break; + case DLL_THREAD_DETACH: + break; + case DLL_PROCESS_DETACH: + if (didInit) { + ssl_FreeSniffer(); + didInit = 0; + } + break; + } + return TRUE; +} + +#endif /* _WIN32 */ + + +static int TraceOn = 0; /* Trace is off by default */ +static FILE* TraceFile = 0; + + +/* windows uses .rc table for this */ +#ifndef _WIN32 + +static const char* const msgTable[] = +{ + /* 1 */ + "Out of Memory", + "New SSL Sniffer Server Registered", + "Checking IP Header", + "SSL Sniffer Server Not Registered", + "Checking TCP Header", + + /* 6 */ + "SSL Sniffer Server Port Not Registered", + "RSA Private Decrypt Error", + "RSA Private Decode Error", + "Set Cipher Spec Error", + "Server Hello Input Malformed", + + /* 11 */ + "Couldn't Resume Session Error", + "Server Did Resumption", + "Client Hello Input Malformed", + "Client Trying to Resume", + "Handshake Input Malformed", + + /* 16 */ + "Got Hello Verify msg", + "Got Server Hello msg", + "Got Cert Request msg", + "Got Server Key Exchange msg", + "Got Cert msg", + + /* 21 */ + "Got Server Hello Done msg", + "Got Finished msg", + "Got Client Hello msg", + "Got Client Key Exchange msg", + "Got Cert Verify msg", + + /* 26 */ + "Got Unknown Handshake msg", + "New SSL Sniffer Session created", + "Couldn't create new SSL", + "Got a Packet to decode", + "No data present", + + /* 31 */ + "Session Not Found", + "Got an Old Client Hello msg", + "Old Client Hello Input Malformed", + "Old Client Hello OK", + "Bad Old Client Hello", + + /* 36 */ + "Bad Record Header", + "Record Header Input Malformed", + "Got a HandShake msg", + "Bad HandShake msg", + "Got a Change Cipher Spec msg", + + /* 41 */ + "Got Application Data msg", + "Bad Application Data", + "Got an Alert msg", + "Another msg to Process", + "Removing Session From Table", + + /* 46 */ + "Bad Key File", + "Wrong IP Version", + "Wrong Protocol type", + "Packet Short for header processing", + "Got Unknown Record Type", + + /* 51 */ + "Can't Open Trace File", + "Session in Fatal Error State", + "Partial SSL record received", + "Buffer Error, malformed input", + "Added to Partial Input", + + /* 56 */ + "Received a Duplicate Packet", + "Received an Out of Order Packet", + "Received an Overlap Duplicate Packet", + "Received an Overlap Reassembly Begin Duplicate Packet", + "Received an Overlap Reassembly End Duplicate Packet", + + /* 61 */ + "Missed the Client Hello Entirely", + "Got Hello Request msg", + "Got Session Ticket msg", + "Bad Input", + "Bad Decrypt Type", + + /* 66 */ + "Bad Finished Message Processing", + "Bad Compression Type", + "Bad DeriveKeys Error", + "Saw ACK for Missing Packet Error", + "Bad Decrypt Operation", + + /* 71 */ + "Decrypt Keys Not Set Up", + "Late Key Load Error", + "Got Certificate Status msg", + "RSA Key Missing Error", + "Secure Renegotiation Not Supported", + + /* 76 */ + "Get Session Stats Failure", + "Reassembly Buffer Size Exceeded", + "Dropping Lost Fragment", + "Dropping Partial Record", + "Clear ACK Fault", + + /* 81 */ + "Bad Decrypt Size", + "Extended Master Secret Hash Error", + "Handshake Message Split Across TLS Records", + "ECC Private Decode Error", + "ECC Public Decode Error", + + /* 86 */ + "Watch callback not set", + "Watch hash failed", + "Watch callback failed", + "Bad Certificate Message" +}; + + +/* *nix version uses table above */ +static void GetError(int idx, char* str) +{ + XSTRNCPY(str, msgTable[idx - 1], MAX_ERROR_LEN-1); + str[MAX_ERROR_LEN-1] = '\0'; +} + + +#else /* _WIN32 */ + + +/* Windows version uses .rc table */ +static void GetError(int idx, char* buffer) +{ + if (!LoadStringA(dllModule, idx, buffer, MAX_ERROR_LEN)) + buffer[0] = 0; +} + + +#endif /* _WIN32 */ + + +/* Packet Buffer for reassembly list and ready list */ +typedef struct PacketBuffer { + word32 begin; /* relative sequence begin */ + word32 end; /* relative sequence end */ + byte* data; /* actual data */ + struct PacketBuffer* next; /* next on reassembly list or ready list */ +} PacketBuffer; + + +#ifdef HAVE_SNI + +/* NamedKey maps a SNI name to a specific private key */ +typedef struct NamedKey { + char name[MAX_SERVER_NAME]; /* server DNS name */ + word32 nameSz; /* size of server DNS name */ + byte* key; /* DER private key */ + word32 keySz; /* size of DER private key */ + struct NamedKey* next; /* for list */ +} NamedKey; + +#endif + + +/* Sniffer Server holds info for each server/port monitored */ +typedef struct SnifferServer { + SSL_CTX* ctx; /* SSL context */ + char address[MAX_SERVER_ADDRESS]; /* passed in server address */ + word32 server; /* netowrk order address */ + int port; /* server port */ +#ifdef HAVE_SNI + NamedKey* namedKeys; /* mapping of names and keys */ + wolfSSL_Mutex namedKeysMutex; /* mutex for namedKey list */ +#endif + struct SnifferServer* next; /* for list */ +} SnifferServer; + + +/* Session Flags */ +typedef struct Flags { + byte side; /* which end is current packet headed */ + byte serverCipherOn; /* indicates whether cipher is active */ + byte clientCipherOn; /* indicates whether cipher is active */ + byte resuming; /* did this session come from resumption */ + byte cached; /* have we cached this session yet */ + byte clientHello; /* processed client hello yet, for SSLv2 */ + byte finCount; /* get both FINs before removing */ + byte fatalError; /* fatal error state */ + byte cliAckFault; /* client acked unseen data from server */ + byte srvAckFault; /* server acked unseen data from client */ + byte cliSkipPartial; /* client skips partial data to catch up */ + byte srvSkipPartial; /* server skips partial data to catch up */ +#ifdef HAVE_EXTENDED_MASTER + byte expectEms; /* expect extended master secret */ +#endif +} Flags; + + +/* Out of Order FIN caputre */ +typedef struct FinCaputre { + word32 cliFinSeq; /* client relative sequence FIN 0 is no */ + word32 srvFinSeq; /* server relative sequence FIN, 0 is no */ + byte cliCounted; /* did we count yet, detects duplicates */ + byte srvCounted; /* did we count yet, detects duplicates */ +} FinCaputre; + + +typedef struct HsHashes { +#ifndef NO_OLD_TLS +#ifndef NO_SHA + wc_Sha hashSha; +#endif +#ifndef NO_MD5 + wc_Md5 hashMd5; +#endif +#endif +#ifndef NO_SHA256 + wc_Sha256 hashSha256; +#endif +#ifdef WOLFSSL_SHA384 + wc_Sha384 hashSha384; +#endif +} HsHashes; + + +/* Sniffer Session holds info for each client/server SSL/TLS session */ +typedef struct SnifferSession { + SnifferServer* context; /* server context */ + SSL* sslServer; /* SSL server side decode */ + SSL* sslClient; /* SSL client side decode */ + word32 server; /* server address in network byte order */ + word32 client; /* client address in network byte order */ + word16 srvPort; /* server port */ + word16 cliPort; /* client port */ + word32 cliSeqStart; /* client start sequence */ + word32 srvSeqStart; /* server start sequence */ + word32 cliExpected; /* client expected sequence (relative) */ + word32 srvExpected; /* server expected sequence (relative) */ + FinCaputre finCaputre; /* retain out of order FIN s */ + Flags flags; /* session flags */ + time_t lastUsed; /* last used ticks */ + word32 keySz; /* size of the private key */ + PacketBuffer* cliReassemblyList; /* client out of order packets */ + PacketBuffer* srvReassemblyList; /* server out of order packets */ + word32 cliReassemblyMemory; /* client packet memory used */ + word32 srvReassemblyMemory; /* server packet memory used */ + struct SnifferSession* next; /* for hash table list */ + byte* ticketID; /* mac ID of session ticket */ +#ifdef HAVE_SNI + const char* sni; /* server name indication */ +#endif +#ifdef HAVE_EXTENDED_MASTER + HsHashes* hash; +#endif +} SnifferSession; + + +/* Sniffer Server List and mutex */ +static SnifferServer* ServerList = 0; +static wolfSSL_Mutex ServerListMutex; + + +/* Session Hash Table, mutex, and count */ +static SnifferSession* SessionTable[HASH_SIZE]; +static wolfSSL_Mutex SessionMutex; +static int SessionCount = 0; + +/* Recovery of missed data switches and stats */ +static wolfSSL_Mutex RecoveryMutex; /* for stats */ +static int RecoveryEnabled = 0; /* global switch */ +static int MaxRecoveryMemory = -1; /* per session max recovery memory */ +static word32 MissedDataSessions = 0; /* # of sessions with missed data */ + +/* Connection Info Callback */ +static SSLConnCb ConnectionCb; +static void* ConnectionCbCtx = NULL; + +#ifdef WOLFSSL_SNIFFER_STATS +/* Sessions Statistics */ +static SSLStats SnifferStats; +static wolfSSL_Mutex StatsMutex; +#endif + +#ifdef WOLFSSL_SNIFFER_WATCH +/* Watch Key Callback */ +static SSLWatchCb WatchCb; +static void* WatchCbCtx = NULL; +#endif + + +static void UpdateMissedDataSessions(void) +{ + wc_LockMutex(&RecoveryMutex); + MissedDataSessions += 1; + wc_UnLockMutex(&RecoveryMutex); +} + + +#ifdef WOLFSSL_SNIFFER_STATS +#define LOCK_STAT() do { wc_LockMutex(&StatsMutex); } while (0) +#define UNLOCK_STAT() do { wc_UnLockMutex(&StatsMutex); } while (0) +#define NOLOCK_ADD_TO_STAT(x,y) do { TraceStat(#x, y); x += y; } while (0) +#define NOLOCK_INC_STAT(x) NOLOCK_ADD_TO_STAT(x,1) +#define ADD_TO_STAT(x,y) do { LOCK_STAT(); \ + NOLOCK_ADD_TO_STAT(x,y); UNLOCK_STAT(); } while (0) +#define INC_STAT(x) do { LOCK_STAT(); \ + NOLOCK_INC_STAT(x); UNLOCK_STAT(); } while (0) +#endif + + +/* Initialize overall Sniffer */ +void ssl_InitSniffer(void) +{ + wolfSSL_Init(); + wc_InitMutex(&ServerListMutex); + wc_InitMutex(&SessionMutex); + wc_InitMutex(&RecoveryMutex); +#ifdef WOLFSSL_SNIFFER_STATS + XMEMSET(&SnifferStats, 0, sizeof(SSLStats)); + wc_InitMutex(&StatsMutex); +#endif +} + + +#ifdef HAVE_SNI + +/* Free Named Key and the zero out the private key it holds */ +static void FreeNamedKey(NamedKey* in) +{ + if (in) { + if (in->key) { + ForceZero(in->key, in->keySz); + free(in->key); + } + free(in); + } +} + + +static void FreeNamedKeyList(NamedKey* in) +{ + NamedKey* next; + + while (in) { + next = in->next; + FreeNamedKey(in); + in = next; + } +} + +#endif + + +/* Free Sniffer Server's resources/self */ +static void FreeSnifferServer(SnifferServer* srv) +{ + if (srv) { +#ifdef HAVE_SNI + wc_LockMutex(&srv->namedKeysMutex); + FreeNamedKeyList(srv->namedKeys); + wc_UnLockMutex(&srv->namedKeysMutex); + wc_FreeMutex(&srv->namedKeysMutex); +#endif + SSL_CTX_free(srv->ctx); + } + free(srv); +} + + +/* free PacketBuffer's resources/self */ +static void FreePacketBuffer(PacketBuffer* del) +{ + if (del) { + free(del->data); + free(del); + } +} + + +/* remove PacketBuffer List */ +static void FreePacketList(PacketBuffer* in) +{ + if (in) { + PacketBuffer* del; + PacketBuffer* packet = in; + + while (packet) { + del = packet; + packet = packet->next; + FreePacketBuffer(del); + } + } +} + + +/* Free Sniffer Session's resources/self */ +static void FreeSnifferSession(SnifferSession* session) +{ + if (session) { + SSL_free(session->sslClient); + SSL_free(session->sslServer); + + FreePacketList(session->cliReassemblyList); + FreePacketList(session->srvReassemblyList); + + free(session->ticketID); +#ifdef HAVE_EXTENDED_MASTER + free(session->hash); +#endif + } + free(session); +} + + +/* Free overall Sniffer */ +void ssl_FreeSniffer(void) +{ + SnifferServer* srv; + SnifferServer* removeServer; + SnifferSession* session; + SnifferSession* removeSession; + int i; + + wc_LockMutex(&ServerListMutex); + wc_LockMutex(&SessionMutex); + + srv = ServerList; + while (srv) { + removeServer = srv; + srv = srv->next; + FreeSnifferServer(removeServer); + } + + for (i = 0; i < HASH_SIZE; i++) { + session = SessionTable[i]; + while (session) { + removeSession = session; + session = session->next; + FreeSnifferSession(removeSession); + } + } + + wc_UnLockMutex(&SessionMutex); + wc_UnLockMutex(&ServerListMutex); + + wc_FreeMutex(&RecoveryMutex); + wc_FreeMutex(&SessionMutex); + wc_FreeMutex(&ServerListMutex); + + if (TraceFile) { + TraceOn = 0; + fclose(TraceFile); + TraceFile = NULL; + } + + wolfSSL_Cleanup(); +} + + +#ifdef HAVE_EXTENDED_MASTER + +static int HashInit(HsHashes* hash) +{ + int ret = 0; + + XMEMSET(hash, 0, sizeof(HsHashes)); + +#ifndef NO_OLD_TLS +#ifndef NO_SHA + if (ret == 0) + ret = wc_InitSha(&hash->hashSha); +#endif +#ifndef NO_MD5 + if (ret == 0) { + ret = wc_InitMd5(&hash->hashMd5); + } +#endif +#endif +#ifndef NO_SHA256 + if (ret == 0) + ret = wc_InitSha256(&hash->hashSha256); +#endif +#ifdef WOLFSSL_SHA384 + if (ret == 0) + ret = wc_InitSha384(&hash->hashSha384); +#endif + + return ret; +} + + +static int HashUpdate(HsHashes* hash, const byte* input, int sz) +{ + int ret = 0; + + input -= HANDSHAKE_HEADER_SZ; + sz += HANDSHAKE_HEADER_SZ; + +#ifndef NO_OLD_TLS +#ifndef NO_SHA + if (ret == 0) + ret = wc_ShaUpdate(&hash->hashSha, input, sz); +#endif +#ifndef NO_MD5 + if (ret == 0) { + ret = wc_Md5Update(&hash->hashMd5, input, sz); + } +#endif +#endif +#ifndef NO_SHA256 + if (ret == 0) + ret = wc_Sha256Update(&hash->hashSha256, input, sz); +#endif +#ifdef WOLFSSL_SHA384 + if (ret == 0) + ret = wc_Sha384Update(&hash->hashSha384, input, sz); +#endif + + return ret; +} + + +static int HashCopy(HS_Hashes* d, HsHashes* s) +{ +#ifndef NO_OLD_TLS +#ifndef NO_SHA + XMEMCPY(&d->hashSha, &s->hashSha, sizeof(wc_Sha)); +#endif +#ifndef NO_MD5 + XMEMCPY(&d->hashMd5, &s->hashMd5, sizeof(wc_Md5)); +#endif +#endif + +#ifndef NO_SHA256 + XMEMCPY(&d->hashSha256, &s->hashSha256, sizeof(wc_Sha256)); +#endif +#ifdef WOLFSSL_SHA384 + XMEMCPY(&d->hashSha384, &s->hashSha384, sizeof(wc_Sha384)); +#endif + + return 0; +} + +#endif + + +/* Initialize a SnifferServer */ +static void InitSnifferServer(SnifferServer* sniffer) +{ + sniffer->ctx = 0; + XMEMSET(sniffer->address, 0, MAX_SERVER_ADDRESS); + sniffer->server = 0; + sniffer->port = 0; +#ifdef HAVE_SNI + sniffer->namedKeys = 0; + wc_InitMutex(&sniffer->namedKeysMutex); +#endif + sniffer->next = 0; +} + + +/* Initialize session flags */ +static void InitFlags(Flags* flags) +{ + flags->side = 0; + flags->serverCipherOn = 0; + flags->clientCipherOn = 0; + flags->resuming = 0; + flags->cached = 0; + flags->clientHello = 0; + flags->finCount = 0; + flags->fatalError = 0; + flags->cliAckFault = 0; + flags->srvAckFault = 0; + flags->cliSkipPartial = 0; + flags->srvSkipPartial = 0; +#ifdef HAVE_EXTENDED_MASTER + flags->expectEms = 0; +#endif +} + + +/* Initialize FIN Capture */ +static void InitFinCapture(FinCaputre* cap) +{ + cap->cliFinSeq = 0; + cap->srvFinSeq = 0; + cap->cliCounted = 0; + cap->srvCounted = 0; +} + + +/* Initialize a Sniffer Session */ +static void InitSession(SnifferSession* session) +{ + session->context = 0; + session->sslServer = 0; + session->sslClient = 0; + session->server = 0; + session->client = 0; + session->srvPort = 0; + session->cliPort = 0; + session->cliSeqStart = 0; + session->srvSeqStart = 0; + session->cliExpected = 0; + session->srvExpected = 0; + session->lastUsed = 0; + session->cliReassemblyList = 0; + session->srvReassemblyList = 0; + session->cliReassemblyMemory = 0; + session->srvReassemblyMemory = 0; + session->next = 0; + session->ticketID = 0; + + InitFlags(&session->flags); + InitFinCapture(&session->finCaputre); +#ifdef HAVE_EXTENDED_MASTER + session->hash = 0; +#endif +} + + +/* IP Info from IP Header */ +typedef struct IpInfo { + int length; /* length of this header */ + int total; /* total length of fragment */ + word32 src; /* network order source address */ + word32 dst; /* network order destination address */ +} IpInfo; + + +/* TCP Info from TCP Header */ +typedef struct TcpInfo { + int srcPort; /* source port */ + int dstPort; /* source port */ + int length; /* length of this header */ + word32 sequence; /* sequence number */ + word32 ackNumber; /* ack number */ + byte fin; /* FIN set */ + byte rst; /* RST set */ + byte syn; /* SYN set */ + byte ack; /* ACK set */ +} TcpInfo; + + +/* Tcp Pseudo Header for Checksum calculation */ +typedef struct TcpPseudoHdr { + word32 src; /* source address */ + word32 dst; /* destination address */ + byte rsv; /* reserved, always 0 */ + byte protocol; /* IP protocol */ + word16 length; /* tcp header length + data length (doesn't include */ + /* pseudo header length) network order */ +} TcpPseudoHdr; + + +/* Password Setting Callback */ +static int SetPassword(char* passwd, int sz, int rw, void* userdata) +{ + (void)rw; + XSTRNCPY(passwd, (const char*)userdata, sz); + return (int)XSTRLEN((const char*)userdata); +} + + +/* Ethernet Header */ +typedef struct EthernetHdr { + byte dst[ETHER_IF_ADDR_LEN]; /* destination host address */ + byte src[ETHER_IF_ADDR_LEN]; /* source host address */ + word16 type; /* IP, ARP, etc */ +} EthernetHdr; + + +/* IP Header */ +typedef struct IpHdr { + byte ver_hl; /* version/header length */ + byte tos; /* type of service */ + word16 length; /* total length */ + word16 id; /* identification */ + word16 offset; /* fragment offset field */ + byte ttl; /* time to live */ + byte protocol; /* protocol */ + word16 sum; /* checksum */ + word32 src; /* source address */ + word32 dst; /* destination address */ +} IpHdr; + + +#define IP_HL(ip) ( (((ip)->ver_hl) & 0x0f) * 4) +#define IP_V(ip) ( ((ip)->ver_hl) >> 4) + +/* TCP Header */ +typedef struct TcpHdr { + word16 srcPort; /* source port */ + word16 dstPort; /* destination port */ + word32 sequence; /* sequence number */ + word32 ack; /* acknoledgment number */ + byte offset; /* data offset, reserved */ + byte flags; /* option flags */ + word16 window; /* window */ + word16 sum; /* checksum */ + word16 urgent; /* urgent pointer */ +} TcpHdr; + +#define TCP_LEN(tcp) ( (((tcp)->offset & 0xf0) >> 4) * 4) +#define TCP_FIN 0x01 +#define TCP_SYN 0x02 +#define TCP_RST 0x04 +#define TCP_ACK 0x10 + + + + + +/* Use platform specific GetError to write to tracfile if tracing */ +static void Trace(int idx) +{ + if (TraceOn) { + char myBuffer[MAX_ERROR_LEN]; + GetError(idx, myBuffer); + fprintf(TraceFile, "\t%s\n", myBuffer); +#ifdef DEBUG_SNIFFER + fprintf(stderr, "\t%s\n", myBuffer); +#endif + } +} + + +/* Show TimeStamp for beginning of packet Trace */ +static void TraceHeader(void) +{ + if (TraceOn) { + time_t ticks = time(NULL); + fprintf(TraceFile, "\n%s", ctime(&ticks)); + } +} + + +/* Show Set Server info for Trace */ +static void TraceSetServer(const char* srv, int port, const char* keyFile) +{ + if (TraceOn) { + fprintf(TraceFile, "\tTrying to install a new Sniffer Server with\n"); + fprintf(TraceFile, "\tserver: %s, port: %d, keyFile: %s\n", srv, port, + keyFile); + } +} + + +#ifdef HAVE_SNI + +/* Show Set Named Server info for Trace */ +static void TraceSetNamedServer(const char* name, + const char* srv, int port, const char* keyFile) +{ + if (TraceOn) { + fprintf(TraceFile, "\tTrying to install a new Sniffer Server with\n"); + fprintf(TraceFile, "\tname: %s, server: %s, port: %d, keyFile: %s\n", + name, srv, port, keyFile); + } +} + +#endif + + +/* Trace got packet number */ +static void TracePacket(void) +{ + if (TraceOn) { + static word32 packetNumber = 0; + fprintf(TraceFile, "\tGot a Packet to decode, packet %u\n", + ++packetNumber); + } +} + + +/* Convert network byte order address into human readable */ +static char* IpToS(word32 addr, char* str) +{ + byte* p = (byte*)&addr; + + SNPRINTF(str, TRACE_MSG_SZ, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); + + return str; +} + + +/* Show destination and source address from Ip Hdr for packet Trace */ +static void TraceIP(IpHdr* iphdr) +{ + if (TraceOn) { + char src[TRACE_MSG_SZ]; + char dst[TRACE_MSG_SZ]; + fprintf(TraceFile, "\tdst:%s src:%s\n", IpToS(iphdr->dst, dst), + IpToS(iphdr->src, src)); + } +} + + +/* Show destination and source port from Tcp Hdr for packet Trace */ +static void TraceTcp(TcpHdr* tcphdr) +{ + if (TraceOn) { + fprintf(TraceFile, "\tdstPort:%u srcPort:%u\n", ntohs(tcphdr->dstPort), + ntohs(tcphdr->srcPort)); + } +} + + +/* Show sequence and payload length for Trace */ +static void TraceSequence(word32 seq, int len) +{ + if (TraceOn) { + fprintf(TraceFile, "\tSequence:%u, payload length:%d\n", seq, len); + } +} + + +/* Show sequence and payload length for Trace */ +static void TraceAck(word32 ack, word32 expected) +{ + if (TraceOn) { + fprintf(TraceFile, "\tAck:%u Expected:%u\n", ack, expected); + } +} + + +/* Show relative expected and relative received sequences */ +static void TraceRelativeSequence(word32 expected, word32 got) +{ + if (TraceOn) { + fprintf(TraceFile, "\tExpected sequence:%u, received sequence:%u\n", + expected, got); + } +} + + +/* Show server sequence startup from SYN */ +static void TraceServerSyn(word32 seq) +{ + if (TraceOn) { + fprintf(TraceFile, "\tServer SYN, Sequence Start:%u\n", seq); + } +} + + +/* Show client sequence startup from SYN */ +static void TraceClientSyn(word32 seq) +{ + if (TraceOn) { + fprintf(TraceFile, "\tClient SYN, Sequence Start:%u\n", seq); + } +} + + +/* Show client FIN capture */ +static void TraceClientFin(word32 finSeq, word32 relSeq) +{ + if (TraceOn) { + fprintf(TraceFile, "\tClient FIN capture:%u, current SEQ:%u\n", + finSeq, relSeq); + } +} + + +/* Show server FIN capture */ +static void TraceServerFin(word32 finSeq, word32 relSeq) +{ + if (TraceOn) { + fprintf(TraceFile, "\tServer FIN capture:%u, current SEQ:%u\n", + finSeq, relSeq); + } +} + + +/* Show number of SSL data bytes decoded, could be 0 (ok) */ +static void TraceGotData(int bytes) +{ + if (TraceOn) { + fprintf(TraceFile, "\t%d bytes of SSL App data processed\n", bytes); + } +} + + +/* Show bytes added to old SSL App data */ +static void TraceAddedData(int newBytes, int existingBytes) +{ + if (TraceOn) { + fprintf(TraceFile, + "\t%d bytes added to %d existing bytes in User Buffer\n", + newBytes, existingBytes); + } +} + + +/* Show Stale Session */ +static void TraceStaleSession(void) +{ + if (TraceOn) { + fprintf(TraceFile, "\tFound a stale session\n"); + } +} + + +/* Show Finding Stale Sessions */ +static void TraceFindingStale(void) +{ + if (TraceOn) { + fprintf(TraceFile, "\tTrying to find Stale Sessions\n"); + } +} + + +/* Show Removed Session */ +static void TraceRemovedSession(void) +{ + if (TraceOn) { + fprintf(TraceFile, "\tRemoved it\n"); + } +} + + +/* Show SSLInfo if provided and is valid. */ +static void TraceSessionInfo(SSLInfo* sslInfo) +{ + if (TraceOn) { + if (sslInfo != NULL && sslInfo->isValid) { + fprintf(TraceFile, + "\tver:(%u %u) suiteId:(%02x %02x) suiteName:(%s) " + #ifdef HAVE_SNI + "sni:(%s) " + #endif + "keySize:(%u)\n", + sslInfo->protocolVersionMajor, + sslInfo->protocolVersionMinor, + sslInfo->serverCipherSuite0, + sslInfo->serverCipherSuite, + sslInfo->serverCipherSuiteName, + #ifdef HAVE_SNI + sslInfo->serverNameIndication, + #endif + sslInfo->keySize); + } + } +} + + +#ifdef WOLFSSL_SNIFFER_STATS + +/* Show value added to a named statistic. */ +static void TraceStat(const char* name, int add) +{ + if (TraceOn) { + fprintf(TraceFile, "\tAdding %d to %s\n", add, name); + } +} + +#endif + + +/* Set user error string */ +static void SetError(int idx, char* error, SnifferSession* session, int fatal) +{ + GetError(idx, error); + Trace(idx); + if (session && fatal == FATAL_ERROR_STATE) + session->flags.fatalError = 1; +} + + +#ifndef WOLFSSL_SNIFFER_WATCH + +/* See if this IPV4 network order address has been registered */ +/* return 1 is true, 0 is false */ +static int IsServerRegistered(word32 addr) +{ + int ret = 0; /* false */ + SnifferServer* sniffer; + + wc_LockMutex(&ServerListMutex); + + sniffer = ServerList; + while (sniffer) { + if (sniffer->server == addr) { + ret = 1; + break; + } + sniffer = sniffer->next; + } + + wc_UnLockMutex(&ServerListMutex); + + return ret; +} + + +/* See if this port has been registered to watch */ +/* return 1 is true, 0 is false */ +static int IsPortRegistered(word32 port) +{ + int ret = 0; /* false */ + SnifferServer* sniffer; + + wc_LockMutex(&ServerListMutex); + + sniffer = ServerList; + while (sniffer) { + if (sniffer->port == (int)port) { + ret = 1; + break; + } + sniffer = sniffer->next; + } + + wc_UnLockMutex(&ServerListMutex); + + return ret; +} + +#endif + + +/* Get SnifferServer from IP and Port */ +static SnifferServer* GetSnifferServer(IpInfo* ipInfo, TcpInfo* tcpInfo) +{ + SnifferServer* sniffer; + + wc_LockMutex(&ServerListMutex); + + sniffer = ServerList; + +#ifndef WOLFSSL_SNIFFER_WATCH + while (sniffer) { + if (sniffer->port == tcpInfo->srcPort && sniffer->server == ipInfo->src) + break; + if (sniffer->port == tcpInfo->dstPort && sniffer->server == ipInfo->dst) + break; + sniffer = sniffer->next; + } +#else + (void)ipInfo; + (void)tcpInfo; +#endif + + wc_UnLockMutex(&ServerListMutex); + + return sniffer; +} + + +/* Hash the Session Info, return hash row */ +static word32 SessionHash(IpInfo* ipInfo, TcpInfo* tcpInfo) +{ + word32 hash = ipInfo->src * ipInfo->dst; + hash *= tcpInfo->srcPort * tcpInfo->dstPort; + + return hash % HASH_SIZE; +} + + +/* Get Exisiting SnifferSession from IP and Port */ +static SnifferSession* GetSnifferSession(IpInfo* ipInfo, TcpInfo* tcpInfo) +{ + SnifferSession* session; + time_t currTime = time(NULL); + word32 row = SessionHash(ipInfo, tcpInfo); + + assert(row <= HASH_SIZE); + + wc_LockMutex(&SessionMutex); + + session = SessionTable[row]; + while (session) { + if (session->server == ipInfo->src && session->client == ipInfo->dst && + session->srvPort == tcpInfo->srcPort && + session->cliPort == tcpInfo->dstPort) + break; + if (session->client == ipInfo->src && session->server == ipInfo->dst && + session->cliPort == tcpInfo->srcPort && + session->srvPort == tcpInfo->dstPort) + break; + + session = session->next; + } + + if (session) + session->lastUsed= currTime; /* keep session alive, remove stale will */ + /* leave alone */ + wc_UnLockMutex(&SessionMutex); + + /* determine side */ + if (session) { + if (ipInfo->dst == session->server && + tcpInfo->dstPort == session->srvPort) + session->flags.side = WOLFSSL_SERVER_END; + else + session->flags.side = WOLFSSL_CLIENT_END; + } + + return session; +} + + +#if defined(HAVE_SNI) || defined(WOLFSSL_SNIFFER_WATCH) + +static int LoadKeyFile(byte** keyBuf, word32* keyBufSz, + const char* keyFile, int typeKey, + const char* password) +{ + byte* loadBuf; + long fileSz = 0; + XFILE file; + int ret; + + if (keyBuf == NULL || keyBufSz == NULL || keyFile == NULL) { + return -1; + } + + file = XFOPEN(keyFile, "rb"); + if (file == XBADFILE) return -1; + if(XFSEEK(file, 0, XSEEK_END) != 0) return -1; + fileSz = XFTELL(file); + XREWIND(file); + + loadBuf = (byte*)malloc(fileSz); + if (loadBuf == NULL) { + XFCLOSE(file); + return -1; + } + + ret = (int)XFREAD(loadBuf, 1, fileSz, file); + XFCLOSE(file); + + if (ret != fileSz) { + free(loadBuf); + return -1; + } + + if (typeKey == WOLFSSL_FILETYPE_PEM) { + byte* saveBuf = (byte*)malloc(fileSz); + int saveBufSz = 0; + + ret = -1; + if (saveBuf != NULL) { + saveBufSz = wc_KeyPemToDer(loadBuf, (int)fileSz, + saveBuf, (int)fileSz, password); + if (saveBufSz < 0) { + saveBufSz = 0; + free(saveBuf); + saveBuf = NULL; + } + else + ret = 0; + } + + ForceZero(loadBuf, (word32)fileSz); + free(loadBuf); + + if (saveBuf) { + *keyBuf = saveBuf; + *keyBufSz = (word32)saveBufSz; + } + } + else { + *keyBuf = loadBuf; + *keyBufSz = (word32)fileSz; + } + + if (ret < 0) { + return -1; + } + + return ret; +} + +#endif + + +#ifdef WOLFSSL_SNIFFER_WATCH + +static int CreateWatchSnifferServer(char* error) +{ + SnifferServer* sniffer; + + sniffer = (SnifferServer*)malloc(sizeof(SnifferServer)); + if (sniffer == NULL) { + SetError(MEMORY_STR, error, NULL, 0); + return -1; + } + InitSnifferServer(sniffer); + sniffer->ctx = SSL_CTX_new(TLSv1_2_client_method()); + if (!sniffer->ctx) { + SetError(MEMORY_STR, error, NULL, 0); + FreeSnifferServer(sniffer); + return -1; + } + ServerList = sniffer; + + return 0; +} + +#endif + + +static int SetNamedPrivateKey(const char* name, const char* address, int port, + const char* keyFile, int typeKey, const char* password, char* error) +{ + SnifferServer* sniffer; + int ret; + int type = (typeKey == FILETYPE_PEM) ? WOLFSSL_FILETYPE_PEM : + WOLFSSL_FILETYPE_ASN1; + int isNew = 0; + word32 serverIp; + +#ifdef HAVE_SNI + NamedKey* namedKey = NULL; +#endif + + (void)name; +#ifdef HAVE_SNI + if (name != NULL) { + namedKey = (NamedKey*)malloc(sizeof(NamedKey)); + if (namedKey == NULL) { + SetError(MEMORY_STR, error, NULL, 0); + return -1; + } + XMEMSET(namedKey, 0, sizeof(NamedKey)); + + namedKey->nameSz = (word32)XSTRLEN(name); + if (namedKey->nameSz > sizeof(namedKey->name)-1) + namedKey->nameSz = sizeof(namedKey->name)-1; + XSTRNCPY(namedKey->name, name, namedKey->nameSz); + namedKey->name[MAX_SERVER_NAME-1] = '\0'; + + ret = LoadKeyFile(&namedKey->key, &namedKey->keySz, + keyFile, type, password); + if (ret < 0) { + SetError(KEY_FILE_STR, error, NULL, 0); + FreeNamedKey(namedKey); + return -1; + } + } +#endif + + serverIp = inet_addr(address); + sniffer = ServerList; + while (sniffer != NULL && + (sniffer->server != serverIp || sniffer->port != port)) { + sniffer = sniffer->next; + } + + if (sniffer == NULL) { + isNew = 1; + sniffer = (SnifferServer*)malloc(sizeof(SnifferServer)); + if (sniffer == NULL) { + SetError(MEMORY_STR, error, NULL, 0); +#ifdef HAVE_SNI + FreeNamedKey(namedKey); +#endif + return -1; + } + InitSnifferServer(sniffer); + + XSTRNCPY(sniffer->address, address, MAX_SERVER_ADDRESS-1); + sniffer->address[MAX_SERVER_ADDRESS-1] = '\0'; + sniffer->server = serverIp; + sniffer->port = port; + + sniffer->ctx = SSL_CTX_new(TLSv1_2_client_method()); + if (!sniffer->ctx) { + SetError(MEMORY_STR, error, NULL, 0); +#ifdef HAVE_SNI + FreeNamedKey(namedKey); +#endif + FreeSnifferServer(sniffer); + return -1; + } + } + + if (name == NULL) { + if (password) { + #ifdef WOLFSSL_ENCRYPTED_KEYS + SSL_CTX_set_default_passwd_cb(sniffer->ctx, SetPassword); + SSL_CTX_set_default_passwd_cb_userdata( + sniffer->ctx, (void*)password); + #endif + } + ret = SSL_CTX_use_PrivateKey_file(sniffer->ctx, keyFile, type); + if (ret != WOLFSSL_SUCCESS) { + SetError(KEY_FILE_STR, error, NULL, 0); + if (isNew) + FreeSnifferServer(sniffer); + return -1; + } + } +#ifdef HAVE_SNI + else { + wc_LockMutex(&sniffer->namedKeysMutex); + namedKey->next = sniffer->namedKeys; + sniffer->namedKeys = namedKey; + wc_UnLockMutex(&sniffer->namedKeysMutex); + } +#endif + + if (isNew) { + sniffer->next = ServerList; + ServerList = sniffer; + } + + return 0; +} + + +#ifdef HAVE_SNI + +/* Sets the private key for a specific name, server and port */ +/* returns 0 on success, -1 on error */ +int ssl_SetNamedPrivateKey(const char* name, + const char* address, int port, + const char* keyFile, int typeKey, + const char* password, char* error) +{ + int ret; + + TraceHeader(); + TraceSetNamedServer(name, address, port, keyFile); + + wc_LockMutex(&ServerListMutex); + ret = SetNamedPrivateKey(name, address, port, keyFile, + typeKey, password, error); + wc_UnLockMutex(&ServerListMutex); + + if (ret == 0) + Trace(NEW_SERVER_STR); + + return ret; +} + +#endif + + +/* Sets the private key for a specific server and port */ +/* returns 0 on success, -1 on error */ +int ssl_SetPrivateKey(const char* address, int port, const char* keyFile, + int typeKey, const char* password, char* error) +{ + int ret; + + TraceHeader(); + TraceSetServer(address, port, keyFile); + + wc_LockMutex(&ServerListMutex); + ret = SetNamedPrivateKey(NULL, address, port, keyFile, + typeKey, password, error); + wc_UnLockMutex(&ServerListMutex); + + if (ret == 0) + Trace(NEW_SERVER_STR); + + return ret; +} + + +/* Check IP Header for IPV4, TCP, and a registered server address */ +/* returns 0 on success, -1 on error */ +static int CheckIpHdr(IpHdr* iphdr, IpInfo* info, int length, char* error) +{ + int version = IP_V(iphdr); + + TraceIP(iphdr); + Trace(IP_CHECK_STR); + + if (version != IPV4) { + SetError(BAD_IPVER_STR, error, NULL, 0); + return -1; + } + + if (iphdr->protocol != TCP_PROTOCOL) { + SetError(BAD_PROTO_STR, error, NULL, 0); + return -1; + } + +#ifndef WOLFSSL_SNIFFER_WATCH + if (!IsServerRegistered(iphdr->src) && !IsServerRegistered(iphdr->dst)) { + SetError(SERVER_NOT_REG_STR, error, NULL, 0); + return -1; + } +#endif + + info->length = IP_HL(iphdr); + info->total = ntohs(iphdr->length); + info->src = iphdr->src; + info->dst = iphdr->dst; + + if (info->total == 0) + info->total = length; /* reassembled may be off */ + + return 0; +} + + +/* Check TCP Header for a registered port */ +/* returns 0 on success, -1 on error */ +static int CheckTcpHdr(TcpHdr* tcphdr, TcpInfo* info, char* error) +{ + TraceTcp(tcphdr); + Trace(TCP_CHECK_STR); + info->srcPort = ntohs(tcphdr->srcPort); + info->dstPort = ntohs(tcphdr->dstPort); + info->length = TCP_LEN(tcphdr); + info->sequence = ntohl(tcphdr->sequence); + info->fin = tcphdr->flags & TCP_FIN; + info->rst = tcphdr->flags & TCP_RST; + info->syn = tcphdr->flags & TCP_SYN; + info->ack = tcphdr->flags & TCP_ACK; + if (info->ack) + info->ackNumber = ntohl(tcphdr->ack); + +#ifndef WOLFSSL_SNIFFER_WATCH + if (!IsPortRegistered(info->srcPort) && !IsPortRegistered(info->dstPort)) { + SetError(SERVER_PORT_NOT_REG_STR, error, NULL, 0); + return -1; + } +#else + (void)error; +#endif + + return 0; +} + + +/* Decode Record Layer Header */ +static int GetRecordHeader(const byte* input, RecordLayerHeader* rh, int* size) +{ + XMEMCPY(rh, input, RECORD_HEADER_SZ); + *size = (rh->length[0] << 8) | rh->length[1]; + + if (*size > (MAX_RECORD_SIZE + COMP_EXTRA + MAX_MSG_EXTRA)) + return LENGTH_ERROR; + + return 0; +} + + +/* Copies the session's infomation to the provided sslInfo. Skip copy if + * SSLInfo is not provided. */ +static void CopySessionInfo(SnifferSession* session, SSLInfo* sslInfo) +{ + if (NULL != sslInfo) { + XMEMSET(sslInfo, 0, sizeof(SSLInfo)); + + /* Pass back Session Info after we have processed the Server Hello. */ + if (0 != session->sslServer->options.cipherSuite) { + const char* pCipher; + + sslInfo->isValid = 1; + sslInfo->protocolVersionMajor = session->sslServer->version.major; + sslInfo->protocolVersionMinor = session->sslServer->version.minor; + sslInfo->serverCipherSuite0 = + session->sslServer->options.cipherSuite0; + sslInfo->serverCipherSuite = + session->sslServer->options.cipherSuite; + + pCipher = wolfSSL_get_cipher(session->sslServer); + if (NULL != pCipher) { + XSTRNCPY((char*)sslInfo->serverCipherSuiteName, pCipher, + sizeof(sslInfo->serverCipherSuiteName)); + sslInfo->serverCipherSuiteName + [sizeof(sslInfo->serverCipherSuiteName) - 1] = '\0'; + } + sslInfo->keySize = session->keySz; + #ifdef HAVE_SNI + if (NULL != session->sni) { + XSTRNCPY((char*)sslInfo->serverNameIndication, + session->sni, sizeof(sslInfo->serverNameIndication)); + sslInfo->serverNameIndication + [sizeof(sslInfo->serverNameIndication) - 1] = '\0'; + } + #endif + TraceSessionInfo(sslInfo); + } + } +} + + +/* Call the session connection start callback. */ +static void CallConnectionCb(SnifferSession* session) +{ + if (ConnectionCb != NULL) { + SSLInfo info; + CopySessionInfo(session, &info); + ConnectionCb((const void*)session, &info, ConnectionCbCtx); + } +} + + +/* Process Client Key Exchange, RSA or static ECDH */ +static int ProcessClientKeyExchange(const byte* input, int* sslBytes, + SnifferSession* session, char* error) +{ + word32 idx = 0; + int tryEcc = 0; + int ret; + + if (session->sslServer->buffers.key == NULL || + session->sslServer->buffers.key->buffer == NULL || + session->sslServer->buffers.key->length == 0) { + + SetError(RSA_KEY_MISSING_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + + { + RsaKey key; + int length; + + ret = wc_InitRsaKey(&key, 0); + if (ret == 0) { + ret = wc_RsaPrivateKeyDecode( + session->sslServer->buffers.key->buffer, + &idx, &key, session->sslServer->buffers.key->length); + if (ret != 0) { + tryEcc = 1; + #ifndef HAVE_ECC + SetError(RSA_DECODE_STR, error, session, FATAL_ERROR_STATE); + #else + /* If we can do ECC, this isn't fatal. Not loading an ECC + * key will be fatal, though. */ + SetError(RSA_DECODE_STR, error, session, 0); + #endif + } + } + + if (ret == 0) { + length = wc_RsaEncryptSize(&key); + if (IsTLS(session->sslServer)) { + input += 2; /* tls pre length */ + } + + if (length > *sslBytes) { + SetError(PARTIAL_INPUT_STR, error, session, FATAL_ERROR_STATE); + ret = -1; + } + } + + if (ret == 0) { + #ifdef WC_RSA_BLINDING + ret = wc_RsaSetRNG(&key, session->sslServer->rng); + if (ret != 0) { + SetError(RSA_DECRYPT_STR, error, session, FATAL_ERROR_STATE); + } + #endif + } + + if (ret == 0) { + session->keySz = length * WOLFSSL_BIT_SIZE; + /* length is the key size in bytes */ + session->sslServer->arrays->preMasterSz = SECRET_LEN; + + do { + #ifdef WOLFSSL_ASYNC_CRYPT + ret = wc_AsyncWait(ret, &key.asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) { + ret = wc_RsaPrivateDecrypt(input, length, + session->sslServer->arrays->preMasterSecret, + session->sslServer->arrays->preMasterSz, &key); + } + } while (ret == WC_PENDING_E); + + if (ret != SECRET_LEN) { + SetError(RSA_DECRYPT_STR, error, session, FATAL_ERROR_STATE); + } + } + + wc_FreeRsaKey(&key); + } + + if (tryEcc) { +#ifdef HAVE_ECC + ecc_key key; + ecc_key pubKey; + int length, keyInit = 0, pubKeyInit = 0; + + idx = 0; + ret = wc_ecc_init(&key); + if (ret == 0) { + keyInit = 1; + ret = wc_ecc_init(&pubKey); + } + if (ret == 0) { + pubKeyInit = 1; + ret = wc_EccPrivateKeyDecode( + session->sslServer->buffers.key->buffer, + &idx, &key, session->sslServer->buffers.key->length); + if (ret != 0) { + SetError(ECC_DECODE_STR, error, session, FATAL_ERROR_STATE); + } + } + + if (ret == 0) { + length = wc_ecc_size(&key) * 2 + 1; + /* The length should be 2 times the key size (x and y), plus 1 + * for the type byte. */ + if (IsTLS(session->sslServer)) { + input += 1; /* Don't include the TLS length for the key. */ + } + + if (length + 1 > *sslBytes) { + SetError(PARTIAL_INPUT_STR, + error, session, FATAL_ERROR_STATE); + ret = -1; + } + } + + if (ret == 0) { + ret = wc_ecc_import_x963_ex(input, length, &pubKey, ECC_CURVE_DEF); + if (ret != 0) { + SetError(ECC_PUB_DECODE_STR, error, session, FATAL_ERROR_STATE); + } + } + + if (ret == 0) { + session->keySz = ((length - 1) / 2) * WOLFSSL_BIT_SIZE; + /* Length is in bytes. Subtract 1 for the ECC key type. Divide + * by two as the key is in (x,y) coordinates, where x and y are + * the same size, the key size. Convert from bytes to bits. */ + session->sslServer->arrays->preMasterSz = ENCRYPT_LEN; + + do { + #ifdef WOLFSSL_ASYNC_CRYPT + ret = wc_AsyncWait(ret, &key.asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) { + ret = wc_ecc_shared_secret(&key, &pubKey, + session->sslServer->arrays->preMasterSecret, + &session->sslServer->arrays->preMasterSz); + } + } while (ret == WC_PENDING_E); + } + +#ifdef WOLFSSL_SNIFFER_STATS + if (ret != 0) + INC_STAT(SnifferStats.sslKeyFails); +#endif + + if (keyInit) + wc_ecc_free(&key); + if (pubKeyInit) + wc_ecc_free(&pubKey); +#endif + } + + /* store for client side as well */ + XMEMCPY(session->sslClient->arrays->preMasterSecret, + session->sslServer->arrays->preMasterSecret, + session->sslServer->arrays->preMasterSz); + session->sslClient->arrays->preMasterSz = + session->sslServer->arrays->preMasterSz; + + #ifdef SHOW_SECRETS + { + int i; + printf("pre master secret: "); + for (i = 0; i < session->sslServer->arrays->preMasterSz; i++) + printf("%02x", session->sslServer->arrays->preMasterSecret[i]); + printf("\n"); + } + #endif + + if (SetCipherSpecs(session->sslServer) != 0) { + SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + + if (SetCipherSpecs(session->sslClient) != 0) { + SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + + ret = MakeMasterSecret(session->sslServer); + ret += MakeMasterSecret(session->sslClient); + ret += SetKeysSide(session->sslServer, ENCRYPT_AND_DECRYPT_SIDE); + ret += SetKeysSide(session->sslClient, ENCRYPT_AND_DECRYPT_SIDE); + + if (ret != 0) { + SetError(BAD_DERIVE_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + +#ifdef SHOW_SECRETS + { + int i; + printf("server master secret: "); + for (i = 0; i < SECRET_LEN; i++) + printf("%02x", session->sslServer->arrays->masterSecret[i]); + printf("\n"); + + printf("client master secret: "); + for (i = 0; i < SECRET_LEN; i++) + printf("%02x", session->sslClient->arrays->masterSecret[i]); + printf("\n"); + + printf("server suite = %d\n", session->sslServer->options.cipherSuite); + printf("client suite = %d\n", session->sslClient->options.cipherSuite); + } +#endif + + CallConnectionCb(session); + + return ret; +} + + +/* Process Session Ticket */ +static int ProcessSessionTicket(const byte* input, int* sslBytes, + SnifferSession* session, char* error) +{ + word16 len; + + /* make sure can read through hint and len */ + if (TICKET_HINT_LEN + LENGTH_SZ > *sslBytes) { + SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + + input += TICKET_HINT_LEN; /* skip over hint */ + *sslBytes -= TICKET_HINT_LEN; + + len = (word16)((input[0] << 8) | input[1]); + input += LENGTH_SZ; + *sslBytes -= LENGTH_SZ; + + /* make sure can read through ticket */ + if (len > *sslBytes || len < ID_LEN) { + SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + + /* store session with macID as sessionID */ + session->sslServer->options.haveSessionId = 1; + XMEMCPY(session->sslServer->arrays->sessionID, input + len - ID_LEN,ID_LEN); + + return 0; +} + + +/* Process Server Hello */ +static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes, + SnifferSession* session, char* error) +{ + ProtocolVersion pv; + byte b, b0; + int toRead = VERSION_SZ + RAN_LEN + ENUM_LEN; + int doResume = 0; + int initialBytes = *sslBytes; + + (void)msgSz; + (void)initialBytes; + + /* make sure we didn't miss ClientHello */ + if (session->flags.clientHello == 0) { + SetError(MISSED_CLIENT_HELLO_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + + /* make sure can read through session len */ + if (toRead > *sslBytes) { + SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + + XMEMCPY(&pv, input, VERSION_SZ); + input += VERSION_SZ; + *sslBytes -= VERSION_SZ; + + session->sslServer->version = pv; + session->sslClient->version = pv; + + XMEMCPY(session->sslServer->arrays->serverRandom, input, RAN_LEN); + XMEMCPY(session->sslClient->arrays->serverRandom, input, RAN_LEN); + input += RAN_LEN; + *sslBytes -= RAN_LEN; + + b = *input++; + *sslBytes -= 1; + + /* make sure can read through compression */ + if ( (b + SUITE_LEN + ENUM_LEN) > *sslBytes) { + SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + if (b) { + XMEMCPY(session->sslServer->arrays->sessionID, input, ID_LEN); + session->sslServer->options.haveSessionId = 1; + } + input += b; + *sslBytes -= b; + + /* cipher suite */ + b0 = *input++; /* first byte, ECC or not */ + session->sslServer->options.cipherSuite0 = b0; + session->sslClient->options.cipherSuite0 = b0; + b = *input++; + session->sslServer->options.cipherSuite = b; + session->sslClient->options.cipherSuite = b; + *sslBytes -= SUITE_LEN; + +#ifdef WOLFSSL_SNIFFER_STATS + { + const CipherSuiteInfo* suites = GetCipherNames(); + int suitesSz = GetCipherNamesSize(); + int match = 0; + + while (suitesSz) { + if (b0 == suites->cipherSuite0 && b == suites->cipherSuite) { + match = 1; + break; + } + suites++; + suitesSz--; + } + if (!match) + INC_STAT(SnifferStats.sslCiphersUnsupported); + } +#endif /* WOLFSSL_SNIFFER_STATS */ + + /* compression */ + b = *input++; + *sslBytes -= ENUM_LEN; + + if (b) { + SetError(BAD_COMPRESSION_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + +#ifdef HAVE_EXTENDED_MASTER + /* extensions */ + if ((initialBytes - *sslBytes) < msgSz) { + word16 len; + + /* skip extensions until extended master secret */ + /* make sure can read len */ + if (SUITE_LEN > *sslBytes) { + SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + len = (word16)((input[0] << 8) | input[1]); + input += SUITE_LEN; + *sslBytes -= SUITE_LEN; + /* make sure can read through all extensions */ + if (len > *sslBytes) { + SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + + while (len >= EXT_TYPE_SZ + LENGTH_SZ) { + byte extType[EXT_TYPE_SZ]; + word16 extLen; + + extType[0] = input[0]; + extType[1] = input[1]; + input += EXT_TYPE_SZ; + *sslBytes -= EXT_TYPE_SZ; + + extLen = (word16)((input[0] << 8) | input[1]); + input += LENGTH_SZ; + *sslBytes -= LENGTH_SZ; + + /* make sure can read through individual extension */ + if (extLen > *sslBytes) { + SetError(SERVER_HELLO_INPUT_STR, error, session, + FATAL_ERROR_STATE); + return -1; + } + + if (extType[0] == 0x00 && extType[1] == EXT_MASTER_SECRET) { + session->flags.expectEms = 1; + } + + input += extLen; + *sslBytes -= extLen; + len -= extLen + EXT_TYPE_SZ + LENGTH_SZ; + } + } + + if (!session->flags.expectEms) { + free(session->hash); + session->hash = NULL; + } +#endif + + if (session->sslServer->options.haveSessionId) { + if (XMEMCMP(session->sslServer->arrays->sessionID, + session->sslClient->arrays->sessionID, ID_LEN) == 0) + doResume = 1; + else if (session->sslClient->options.haveSessionId) { +#ifdef WOLFSSL_SNIFFER_STATS + INC_STAT(SnifferStats.sslResumeMisses); +#endif + } + } + else if (session->sslClient->options.haveSessionId == 0 && + session->sslServer->options.haveSessionId == 0 && + session->ticketID) + doResume = 1; + + if (session->ticketID && doResume) { + /* use ticketID to retrieve from session, prefer over sessionID */ + XMEMCPY(session->sslServer->arrays->sessionID,session->ticketID,ID_LEN); + session->sslServer->options.haveSessionId = 1; /* may not have + actual sessionID */ + } + + if (doResume ) { + int ret = 0; + SSL_SESSION* resume = GetSession(session->sslServer, + session->sslServer->arrays->masterSecret, 0); + if (resume == NULL) { + SetError(BAD_SESSION_RESUME_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + /* make sure client has master secret too */ + XMEMCPY(session->sslClient->arrays->masterSecret, + session->sslServer->arrays->masterSecret, SECRET_LEN); + session->flags.resuming = 1; + + Trace(SERVER_DID_RESUMPTION_STR); +#ifdef WOLFSSL_SNIFFER_STATS + INC_STAT(SnifferStats.sslResumedConns); +#endif + if (SetCipherSpecs(session->sslServer) != 0) { + SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + + if (SetCipherSpecs(session->sslClient) != 0) { + SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + + if (session->sslServer->options.tls) { + ret = DeriveTlsKeys(session->sslServer); + ret += DeriveTlsKeys(session->sslClient); + } + else { + ret = DeriveKeys(session->sslServer); + ret += DeriveKeys(session->sslClient); + } + ret += SetKeysSide(session->sslServer, ENCRYPT_AND_DECRYPT_SIDE); + ret += SetKeysSide(session->sslClient, ENCRYPT_AND_DECRYPT_SIDE); + + if (ret != 0) { + SetError(BAD_DERIVE_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + } + else { +#ifdef WOLFSSL_SNIFFER_STATS + INC_STAT(SnifferStats.sslStandardConns); +#endif + } +#ifdef SHOW_SECRETS + { + int i; + printf("cipher suite = 0x%02x\n", + session->sslServer->options.cipherSuite); + printf("server random: "); + for (i = 0; i < RAN_LEN; i++) + printf("%02x", session->sslServer->arrays->serverRandom[i]); + printf("\n"); + } +#endif + return 0; +} + + +/* Process normal Client Hello */ +static int ProcessClientHello(const byte* input, int* sslBytes, + SnifferSession* session, char* error) +{ + byte bLen; + word16 len; + int toRead = VERSION_SZ + RAN_LEN + ENUM_LEN; + +#ifdef HAVE_SNI + { + byte name[MAX_SERVER_NAME]; + word32 nameSz = sizeof(name); + int ret; + + ret = wolfSSL_SNI_GetFromBuffer( + input - HANDSHAKE_HEADER_SZ - RECORD_HEADER_SZ, + *sslBytes + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ, + WOLFSSL_SNI_HOST_NAME, name, &nameSz); + + if (ret == WOLFSSL_SUCCESS) { + NamedKey* namedKey; + + if (nameSz > sizeof(name) - 1) + nameSz = sizeof(name) - 1; + name[nameSz] = 0; + wc_LockMutex(&session->context->namedKeysMutex); + namedKey = session->context->namedKeys; + while (namedKey != NULL) { + if (nameSz == namedKey->nameSz && + XSTRNCMP((char*)name, namedKey->name, nameSz) == 0) { + if (wolfSSL_use_PrivateKey_buffer(session->sslServer, + namedKey->key, namedKey->keySz, + WOLFSSL_FILETYPE_ASN1) != WOLFSSL_SUCCESS) { + wc_UnLockMutex(&session->context->namedKeysMutex); + SetError(CLIENT_HELLO_LATE_KEY_STR, error, session, + FATAL_ERROR_STATE); + return -1; + } + session->sni = namedKey->name; + break; + } + else + namedKey = namedKey->next; + } + wc_UnLockMutex(&session->context->namedKeysMutex); + } + } +#endif + + session->flags.clientHello = 1; /* don't process again */ + + /* make sure can read up to session len */ + if (toRead > *sslBytes) { + SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + + /* skip, get negotiated one from server hello */ + input += VERSION_SZ; + *sslBytes -= VERSION_SZ; + + XMEMCPY(session->sslServer->arrays->clientRandom, input, RAN_LEN); + XMEMCPY(session->sslClient->arrays->clientRandom, input, RAN_LEN); + + input += RAN_LEN; + *sslBytes -= RAN_LEN; + + /* store session in case trying to resume */ + bLen = *input++; + *sslBytes -= ENUM_LEN; + if (bLen) { + if (ID_LEN > *sslBytes) { + SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + Trace(CLIENT_RESUME_TRY_STR); + XMEMCPY(session->sslClient->arrays->sessionID, input, ID_LEN); + session->sslClient->options.haveSessionId = 1; + } +#ifdef SHOW_SECRETS + { + int i; + printf("client random: "); + for (i = 0; i < RAN_LEN; i++) + printf("%02x", session->sslServer->arrays->clientRandom[i]); + printf("\n"); + } +#endif + + input += bLen; + *sslBytes -= bLen; + + /* skip cipher suites */ + /* make sure can read len */ + if (SUITE_LEN > *sslBytes) { + SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + len = (word16)((input[0] << 8) | input[1]); + input += SUITE_LEN; + *sslBytes -= SUITE_LEN; + /* make sure can read suites + comp len */ + if (len + ENUM_LEN > *sslBytes) { + SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + input += len; + *sslBytes -= len; + + /* skip compression */ + bLen = *input++; + *sslBytes -= ENUM_LEN; + /* make sure can read len */ + if (bLen > *sslBytes) { + SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + input += bLen; + *sslBytes -= bLen; + + if (*sslBytes == 0) { + /* no extensions */ + return 0; + } + + /* skip extensions until session ticket */ + /* make sure can read len */ + if (SUITE_LEN > *sslBytes) { + SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + len = (word16)((input[0] << 8) | input[1]); + input += SUITE_LEN; + *sslBytes -= SUITE_LEN; + /* make sure can read through all extensions */ + if (len > *sslBytes) { + SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + + while (len >= EXT_TYPE_SZ + LENGTH_SZ) { + byte extType[EXT_TYPE_SZ]; + word16 extLen; + + extType[0] = input[0]; + extType[1] = input[1]; + input += EXT_TYPE_SZ; + *sslBytes -= EXT_TYPE_SZ; + + extLen = (word16)((input[0] << 8) | input[1]); + input += LENGTH_SZ; + *sslBytes -= LENGTH_SZ; + + /* make sure can read through individual extension */ + if (extLen > *sslBytes) { + SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + + if (extType[0] == 0x00 && extType[1] == TICKET_EXT_ID) { + + /* make sure can read through ticket if there is a non blank one */ + if (extLen && extLen < ID_LEN) { + SetError(CLIENT_HELLO_INPUT_STR, error, session, + FATAL_ERROR_STATE); + return -1; + } + + if (extLen) { + if (session->ticketID == 0) { + session->ticketID = (byte*)malloc(ID_LEN); + if (session->ticketID == 0) { + SetError(MEMORY_STR, error, session, + FATAL_ERROR_STATE); + return -1; + } + } + XMEMCPY(session->ticketID, input + extLen - ID_LEN, ID_LEN); + } + } + + input += extLen; + *sslBytes -= extLen; + len -= extLen + EXT_TYPE_SZ + LENGTH_SZ; + } + + return 0; +} + + +#ifdef WOLFSSL_SNIFFER_WATCH + +/* Process Certificate */ +static int ProcessCertificate(const byte* input, int* sslBytes, + SnifferSession* session, char* error) +{ + Sha256 sha; + const byte* certChain; + word32 certChainSz; + word32 certSz; + int ret; + byte digest[SHA256_DIGEST_SIZE]; + + /* If the receiver is the server, this is the client certificate message, + * and it should be ignored at this point. */ + if (session->flags.side == WOLFSSL_SERVER_END) + return 0; + + if (WatchCb == NULL) { + SetError(WATCH_CB_MISSING_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + + if (*sslBytes < CERT_HEADER_SZ) { + SetError(BAD_CERT_MSG_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + ato24(input, &certChainSz); + *sslBytes -= CERT_HEADER_SZ; + input += CERT_HEADER_SZ; + + if (*sslBytes < (int)certChainSz) { + SetError(BAD_CERT_MSG_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + certChain = input; + + ato24(input, &certSz); + input += OPAQUE24_LEN; + if (*sslBytes < (int)certSz) { + SetError(BAD_CERT_MSG_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + + *sslBytes -= certChainSz; + + ret = wc_InitSha256(&sha); + if (ret == 0) + ret = wc_Sha256Update(&sha, input, certSz); + if (ret == 0) + ret = wc_Sha256Final(&sha, digest); + if (ret != 0) { + SetError(WATCH_HASH_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + + ret = WatchCb((void*)session, digest, sizeof(digest), + certChain, certChainSz, WatchCbCtx, error); + if (ret != 0) { +#ifdef WOLFSSL_SNIFFER_STATS + INC_STAT(SnifferStats.sslKeysUnmatched); +#endif + SetError(WATCH_FAIL_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + else { +#ifdef WOLFSSL_SNIFFER_STATS + INC_STAT(SnifferStats.sslKeyMatches); +#endif + } + + return 0; +} + +#endif + + +/* Process Finished */ +static int ProcessFinished(const byte* input, int size, int* sslBytes, + SnifferSession* session, char* error) +{ + SSL* ssl; + word32 inOutIdx = 0; + int ret; + + if (session->flags.side == WOLFSSL_SERVER_END) + ssl = session->sslServer; + else + ssl = session->sslClient; + + ret = DoFinished(ssl, input, &inOutIdx, (word32) size, (word32) *sslBytes, + SNIFF); + *sslBytes -= (int)inOutIdx; + + if (ret < 0) { + SetError(BAD_FINISHED_MSG, error, session, FATAL_ERROR_STATE); + return ret; + } + + if (ret == 0 && session->flags.cached == 0) { + if (session->sslServer->options.haveSessionId) { + WOLFSSL_SESSION* sess = GetSession(session->sslServer, NULL, 0); + if (sess == NULL) + AddSession(session->sslServer); /* don't re add */ + session->flags.cached = 1; + } + } + + /* If receiving a finished message from one side, free the resources + * from the other side's tracker. */ + if (session->flags.side == WOLFSSL_SERVER_END) + FreeHandshakeResources(session->sslClient); + else + FreeHandshakeResources(session->sslServer); + + return ret; +} + + +/* Process HandShake input */ +static int DoHandShake(const byte* input, int* sslBytes, + SnifferSession* session, char* error) +{ + byte type; + int size; + int ret = 0; + int startBytes; + + if (*sslBytes < HANDSHAKE_HEADER_SZ) { + SetError(HANDSHAKE_INPUT_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + type = input[0]; + size = (input[1] << 16) | (input[2] << 8) | input[3]; + + input += HANDSHAKE_HEADER_SZ; + *sslBytes -= HANDSHAKE_HEADER_SZ; + startBytes = *sslBytes; + + if (*sslBytes < size) { + Trace(SPLIT_HANDSHAKE_MSG_STR); + *sslBytes = 0; + return ret; + } + + /* A session's arrays are released when the handshake is completed. */ + if (session->sslServer->arrays == NULL && + session->sslClient->arrays == NULL) { + + SetError(NO_SECURE_RENEGOTIATION, error, session, FATAL_ERROR_STATE); + return -1; + } + +#ifdef HAVE_EXTENDED_MASTER + if (session->hash) { + if (HashUpdate(session->hash, input, size) != 0) { + SetError(EXTENDED_MASTER_HASH_STR, error, + session, FATAL_ERROR_STATE); + return -1; + } + } +#endif + + switch (type) { + case hello_verify_request: + Trace(GOT_HELLO_VERIFY_STR); + break; + case hello_request: + Trace(GOT_HELLO_REQUEST_STR); + break; + case session_ticket: + Trace(GOT_SESSION_TICKET_STR); + ret = ProcessSessionTicket(input, sslBytes, session, error); + break; + case server_hello: + Trace(GOT_SERVER_HELLO_STR); + ret = ProcessServerHello(size, input, sslBytes, session, error); + break; + case certificate_request: + Trace(GOT_CERT_REQ_STR); + break; + case server_key_exchange: +#ifdef WOLFSSL_SNIFFER_STATS + INC_STAT(SnifferStats.sslEphemeralMisses); +#endif + Trace(GOT_SERVER_KEY_EX_STR); + /* can't know temp key passively */ + SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE); + ret = -1; + break; + case certificate: + Trace(GOT_CERT_STR); + if (session->flags.side == WOLFSSL_SERVER_END) { +#ifdef WOLFSSL_SNIFFER_STATS + INC_STAT(SnifferStats.sslClientAuthConns); +#endif + } +#ifdef WOLFSSL_SNIFFER_WATCH + ret = ProcessCertificate(input, sslBytes, session, error); +#endif + break; + case server_hello_done: + Trace(GOT_SERVER_HELLO_DONE_STR); + break; + case finished: + Trace(GOT_FINISHED_STR); + ret = ProcessFinished(input, size, sslBytes, session, error); + break; + case client_hello: + Trace(GOT_CLIENT_HELLO_STR); + ret = ProcessClientHello(input, sslBytes, session, error); + break; + case client_key_exchange: + Trace(GOT_CLIENT_KEY_EX_STR); +#ifdef HAVE_EXTENDED_MASTER + if (session->flags.expectEms && session->hash != NULL) { + if (HashCopy(session->sslServer->hsHashes, + session->hash) == 0 && + HashCopy(session->sslClient->hsHashes, + session->hash) == 0) { + + session->sslServer->options.haveEMS = 1; + session->sslClient->options.haveEMS = 1; + } + else { + SetError(EXTENDED_MASTER_HASH_STR, error, + session, FATAL_ERROR_STATE); + ret = -1; + } + XMEMSET(session->hash, 0, sizeof(HsHashes)); + free(session->hash); + session->hash = NULL; + } + else { + session->sslServer->options.haveEMS = 0; + session->sslClient->options.haveEMS = 0; + } +#endif + if (ret == 0) + ret = ProcessClientKeyExchange(input, sslBytes, session, error); + break; + case certificate_verify: + Trace(GOT_CERT_VER_STR); + break; + case certificate_status: + Trace(GOT_CERT_STATUS_STR); + break; + default: + SetError(GOT_UNKNOWN_HANDSHAKE_STR, error, session, 0); + return -1; + } + + *sslBytes = startBytes - size; /* actual bytes of full process */ + + return ret; +} + + +/* Decrypt input into plain output, 0 on success */ +static int Decrypt(SSL* ssl, byte* output, const byte* input, word32 sz) +{ + int ret = 0; + + (void)output; + (void)input; + (void)sz; + + switch (ssl->specs.bulk_cipher_algorithm) { + #ifdef BUILD_ARC4 + case wolfssl_rc4: + wc_Arc4Process(ssl->decrypt.arc4, output, input, sz); + break; + #endif + + #ifdef BUILD_DES3 + case wolfssl_triple_des: + ret = wc_Des3_CbcDecrypt(ssl->decrypt.des3, output, input, sz); + break; + #endif + + #ifdef BUILD_AES + case wolfssl_aes: + ret = wc_AesCbcDecrypt(ssl->decrypt.aes, output, input, sz); + break; + #endif + + #ifdef HAVE_HC128 + case wolfssl_hc128: + wc_Hc128_Process(ssl->decrypt.hc128, output, input, sz); + break; + #endif + + #ifdef BUILD_RABBIT + case wolfssl_rabbit: + wc_RabbitProcess(ssl->decrypt.rabbit, output, input, sz); + break; + #endif + + #ifdef HAVE_CAMELLIA + case wolfssl_camellia: + wc_CamelliaCbcDecrypt(ssl->decrypt.cam, output, input, sz); + break; + #endif + + #ifdef HAVE_IDEA + case wolfssl_idea: + wc_IdeaCbcDecrypt(ssl->decrypt.idea, output, input, sz); + break; + #endif + + #ifdef HAVE_AESGCM + case wolfssl_aes_gcm: + if (sz >= (word32)(AESGCM_EXP_IV_SZ + ssl->specs.aead_mac_size)) + { + /* scratch buffer, sniffer ignores auth tag*/ + byte authTag[WOLFSSL_MIN_AUTH_TAG_SZ]; + + byte nonce[AESGCM_NONCE_SZ]; + XMEMCPY(nonce, ssl->keys.aead_dec_imp_IV, AESGCM_IMP_IV_SZ); + XMEMCPY(nonce + AESGCM_IMP_IV_SZ, input, AESGCM_EXP_IV_SZ); + + if (wc_AesGcmEncrypt(ssl->decrypt.aes, + output, + input + AESGCM_EXP_IV_SZ, + sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size, + nonce, AESGCM_NONCE_SZ, + authTag, sizeof(authTag), + NULL, 0) < 0) { + Trace(BAD_DECRYPT); + ret = -1; + } + ForceZero(nonce, AESGCM_NONCE_SZ); + } + else { + Trace(BAD_DECRYPT_SIZE); + ret = -1; + } + break; + #endif + + #ifdef HAVE_NULL_CIPHER + case wolfssl_cipher_null: + XMEMCPY(output, input, sz); + break; + #endif + + default: + Trace(BAD_DECRYPT_TYPE); + ret = -1; + break; + } + + return ret; +} + + +/* Decrypt input message into output, adjust output steam if needed */ +static const byte* DecryptMessage(SSL* ssl, const byte* input, word32 sz, + byte* output, int* error, int* advance) +{ + int ivExtra = 0; + + int ret = Decrypt(ssl, output, input, sz); + if (ret != 0) { + *error = ret; + return NULL; + } + ssl->keys.encryptSz = sz; + if (ssl->options.tls1_1 && ssl->specs.cipher_type == block) { + output += ssl->specs.block_size; /* go past TLSv1.1 IV */ + ivExtra = ssl->specs.block_size; + *advance = ssl->specs.block_size; + } + + if (ssl->specs.cipher_type == aead) { + *advance = ssl->specs.aead_mac_size; + ssl->keys.padSz = ssl->specs.aead_mac_size; + } + else + ssl->keys.padSz = ssl->specs.hash_size; + + if (ssl->specs.cipher_type == block) + ssl->keys.padSz += *(output + sz - ivExtra - 1) + 1; + + return output; +} + + +/* remove session from table, use rowHint if no info (means we have a lock) */ +static void RemoveSession(SnifferSession* session, IpInfo* ipInfo, + TcpInfo* tcpInfo, word32 rowHint) +{ + SnifferSession* previous = 0; + SnifferSession* current; + word32 row = rowHint; + int haveLock = 0; + + if (ipInfo && tcpInfo) + row = SessionHash(ipInfo, tcpInfo); + else + haveLock = 1; + + assert(row <= HASH_SIZE); + Trace(REMOVE_SESSION_STR); + + if (!haveLock) + wc_LockMutex(&SessionMutex); + + current = SessionTable[row]; + + while (current) { + if (current == session) { + if (previous) + previous->next = current->next; + else + SessionTable[row] = current->next; + FreeSnifferSession(session); + TraceRemovedSession(); + break; + } + previous = current; + current = current->next; + } + + if (!haveLock) + wc_UnLockMutex(&SessionMutex); +} + + +/* Remove stale sessions from the Session Table, have a lock */ +static void RemoveStaleSessions(void) +{ + word32 i; + SnifferSession* session; + + for (i = 0; i < HASH_SIZE; i++) { + session = SessionTable[i]; + while (session) { + SnifferSession* next = session->next; + if (time(NULL) >= session->lastUsed + WOLFSSL_SNIFFER_TIMEOUT) { + TraceStaleSession(); + RemoveSession(session, NULL, NULL, i); + } + session = next; + } + } +} + + +/* Create a new Sniffer Session */ +static SnifferSession* CreateSession(IpInfo* ipInfo, TcpInfo* tcpInfo, + char* error) +{ + SnifferSession* session = 0; + int row; + + Trace(NEW_SESSION_STR); + /* create a new one */ + session = (SnifferSession*)malloc(sizeof(SnifferSession)); + if (session == NULL) { + SetError(MEMORY_STR, error, NULL, 0); + return 0; + } + InitSession(session); +#ifdef HAVE_EXTENDED_MASTER + { + HsHashes* newHash = (HsHashes*)malloc(sizeof(HsHashes)); + if (newHash == NULL) { + SetError(MEMORY_STR, error, NULL, 0); + free(session); + return 0; + } + if (HashInit(newHash) != 0) { + SetError(EXTENDED_MASTER_HASH_STR, error, NULL, 0); + free(session); + return 0; + } + session->hash = newHash; + } +#endif + session->server = ipInfo->dst; + session->client = ipInfo->src; + session->srvPort = (word16)tcpInfo->dstPort; + session->cliPort = (word16)tcpInfo->srcPort; + session->cliSeqStart = tcpInfo->sequence; + session->cliExpected = 1; /* relative */ + session->lastUsed= time(NULL); + session->keySz = 0; +#ifdef HAVE_SNI + session->sni = NULL; +#endif + + session->context = GetSnifferServer(ipInfo, tcpInfo); + if (session->context == NULL) { + SetError(SERVER_NOT_REG_STR, error, NULL, 0); + free(session); + return 0; + } + + session->sslServer = SSL_new(session->context->ctx); + if (session->sslServer == NULL) { + SetError(BAD_NEW_SSL_STR, error, session, FATAL_ERROR_STATE); + free(session); + return 0; + } + session->sslClient = SSL_new(session->context->ctx); + if (session->sslClient == NULL) { + SSL_free(session->sslServer); + session->sslServer = 0; + + SetError(BAD_NEW_SSL_STR, error, session, FATAL_ERROR_STATE); + free(session); + return 0; + } + /* put server back into server mode */ + session->sslServer->options.side = WOLFSSL_SERVER_END; + + row = SessionHash(ipInfo, tcpInfo); + + /* add it to the session table */ + wc_LockMutex(&SessionMutex); + + session->next = SessionTable[row]; + SessionTable[row] = session; + + SessionCount++; + + if ( (SessionCount % HASH_SIZE) == 0) { + TraceFindingStale(); + RemoveStaleSessions(); + } + + wc_UnLockMutex(&SessionMutex); + + /* CreateSession is called in response to a SYN packet, we know this + * is headed to the server. Also we know the server is one we care + * about as we've passed the GetSnifferServer() successfully. */ + session->flags.side = WOLFSSL_SERVER_END; + + return session; +} + + +#ifdef OLD_HELLO_ALLOWED + +/* Process Old Client Hello Input */ +static int DoOldHello(SnifferSession* session, const byte* sslFrame, + int* rhSize, int* sslBytes, char* error) +{ + const byte* input = sslFrame; + byte b0, b1; + word32 idx = 0; + int ret; + + Trace(GOT_OLD_CLIENT_HELLO_STR); + session->flags.clientHello = 1; /* don't process again */ + b0 = *input++; + b1 = *input++; + *sslBytes -= 2; + *rhSize = ((b0 & 0x7f) << 8) | b1; + + if (*rhSize > *sslBytes) { + SetError(OLD_CLIENT_INPUT_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + + ret = ProcessOldClientHello(session->sslServer, input, &idx, *sslBytes, + (word16)*rhSize); + if (ret < 0 && ret != MATCH_SUITE_ERROR) { + SetError(BAD_OLD_CLIENT_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + + Trace(OLD_CLIENT_OK_STR); + XMEMCPY(session->sslClient->arrays->clientRandom, + session->sslServer->arrays->clientRandom, RAN_LEN); + + *sslBytes -= *rhSize; + return 0; +} + +#endif /* OLD_HELLO_ALLOWED */ + + +#if 0 +/* Calculate the TCP checksum, see RFC 1071 */ +/* return 0 for success, -1 on error */ +/* can be called from decode() with + TcpChecksum(&ipInfo, &tcpInfo, sslBytes, packet + ipInfo.length); + could also add a 64bit version if type available and using this +*/ +int TcpChecksum(IpInfo* ipInfo, TcpInfo* tcpInfo, int dataLen, + const byte* packet) +{ + TcpPseudoHdr pseudo; + int count = PSEUDO_HDR_SZ; + const word16* data = (word16*)&pseudo; + word32 sum = 0; + word16 checksum; + + pseudo.src = ipInfo->src; + pseudo.dst = ipInfo->dst; + pseudo.rsv = 0; + pseudo.protocol = TCP_PROTO; + pseudo.length = htons(tcpInfo->length + dataLen); + + /* pseudo header sum */ + while (count >= 2) { + sum += *data++; + count -= 2; + } + + count = tcpInfo->length + dataLen; + data = (word16*)packet; + + /* main sum */ + while (count > 1) { + sum += *data++; + count -=2; + } + + /* get left-over, if any */ + packet = (byte*)data; + if (count > 0) { + sum += *packet; + } + + /* fold 32bit sum into 16 bits */ + while (sum >> 16) + sum = (sum & 0xffff) + (sum >> 16); + + checksum = (word16)~sum; + /* checksum should now equal 0, since included already calcd checksum */ + /* field, but tcp checksum offloading could negate calculation */ + if (checksum == 0) + return 0; + return -1; +} +#endif + + +/* Check IP and TCP headers, set payload */ +/* returns 0 on success, -1 on error */ +static int CheckHeaders(IpInfo* ipInfo, TcpInfo* tcpInfo, const byte* packet, + int length, const byte** sslFrame, int* sslBytes, char* error) +{ + TraceHeader(); + TracePacket(); + + /* ip header */ + if (length < IP_HDR_SZ) { + SetError(PACKET_HDR_SHORT_STR, error, NULL, 0); + return -1; + } + if (CheckIpHdr((IpHdr*)packet, ipInfo, length, error) != 0) + return -1; + + /* tcp header */ + if (length < (ipInfo->length + TCP_HDR_SZ)) { + SetError(PACKET_HDR_SHORT_STR, error, NULL, 0); + return -1; + } + if (CheckTcpHdr((TcpHdr*)(packet + ipInfo->length), tcpInfo, error) != 0) + return -1; + + /* setup */ + *sslFrame = packet + ipInfo->length + tcpInfo->length; + if (*sslFrame > packet + length) { + SetError(PACKET_HDR_SHORT_STR, error, NULL, 0); + return -1; + } + *sslBytes = (int)(packet + length - *sslFrame); + + return 0; +} + + +/* Create or Find existing session */ +/* returns 0 on success (continue), -1 on error, 1 on success (end) */ +static int CheckSession(IpInfo* ipInfo, TcpInfo* tcpInfo, int sslBytes, + SnifferSession** session, char* error) +{ + /* create a new SnifferSession on client SYN */ + if (tcpInfo->syn && !tcpInfo->ack) { + TraceClientSyn(tcpInfo->sequence); +#ifdef WOLFSSL_SNIFFER_STATS + INC_STAT(SnifferStats.sslEncryptedConns); +#endif + *session = CreateSession(ipInfo, tcpInfo, error); + if (*session == NULL) { + *session = GetSnifferSession(ipInfo, tcpInfo); + /* already had existing, so OK */ + if (*session) + return 1; + + SetError(MEMORY_STR, error, NULL, 0); + return -1; + } + return 1; + } + /* get existing sniffer session */ + else { + *session = GetSnifferSession(ipInfo, tcpInfo); + if (*session == NULL) { + /* don't worry about extraneous RST or duplicate FINs */ + if (tcpInfo->fin || tcpInfo->rst) + return 1; + /* don't worry about duplicate ACKs either */ + if (sslBytes == 0 && tcpInfo->ack) + return 1; + +#ifdef WOLFSSL_SNIFFER_STATS + LOCK_STAT(); + NOLOCK_INC_STAT(SnifferStats.sslDecryptedPackets); + NOLOCK_ADD_TO_STAT(SnifferStats.sslDecryptedBytes, sslBytes); + UNLOCK_STAT(); +#endif + + SetError(BAD_SESSION_STR, error, NULL, 0); + return -1; + } + } + return 0; +} + + +/* Create a Packet Buffer from *begin - end, adjust new *begin and bytesLeft */ +static PacketBuffer* CreateBuffer(word32* begin, word32 end, const byte* data, + int* bytesLeft) +{ + PacketBuffer* pb; + + int added = end - *begin + 1; + assert(*begin <= end); + + pb = (PacketBuffer*)malloc(sizeof(PacketBuffer)); + if (pb == NULL) return NULL; + + pb->next = 0; + pb->begin = *begin; + pb->end = end; + pb->data = (byte*)malloc(added); + + if (pb->data == NULL) { + free(pb); + return NULL; + } + XMEMCPY(pb->data, data, added); + + *bytesLeft -= added; + *begin = pb->end + 1; + + return pb; +} + + +/* Add sslFrame to Reassembly List */ +/* returns 1 (end) on success, -1, on error */ +static int AddToReassembly(byte from, word32 seq, const byte* sslFrame, + int sslBytes, SnifferSession* session, char* error) +{ + PacketBuffer* add; + PacketBuffer** front = (from == WOLFSSL_SERVER_END) ? + &session->cliReassemblyList: &session->srvReassemblyList; + PacketBuffer* curr = *front; + PacketBuffer* prev = curr; + + word32* reassemblyMemory = (from == WOLFSSL_SERVER_END) ? + &session->cliReassemblyMemory : &session->srvReassemblyMemory; + word32 startSeq = seq; + word32 added; + int bytesLeft = sslBytes; /* could be overlapping fragment */ + + /* if list is empty add full frame to front */ + if (!curr) { + if (MaxRecoveryMemory != -1 && + (int)(*reassemblyMemory + sslBytes) > MaxRecoveryMemory) { + SetError(REASSEMBLY_MAX_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + add = CreateBuffer(&seq, seq + sslBytes - 1, sslFrame, &bytesLeft); + if (add == NULL) { + SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + *front = add; + *reassemblyMemory += sslBytes; + return 1; + } + + /* add to front if before current front, up to next->begin */ + if (seq < curr->begin) { + word32 end = seq + sslBytes - 1; + + if (end >= curr->begin) + end = curr->begin - 1; + + if (MaxRecoveryMemory -1 && + (int)(*reassemblyMemory + sslBytes) > MaxRecoveryMemory) { + SetError(REASSEMBLY_MAX_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + add = CreateBuffer(&seq, end, sslFrame, &bytesLeft); + if (add == NULL) { + SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + add->next = curr; + *front = add; + *reassemblyMemory += sslBytes; + } + + /* while we have bytes left, try to find a gap to fill */ + while (bytesLeft > 0) { + /* get previous packet in list */ + while (curr && (seq >= curr->begin)) { + prev = curr; + curr = curr->next; + } + + /* don't add duplicate data */ + if (prev->end >= seq) { + if ( (seq + bytesLeft - 1) <= prev->end) + return 1; + seq = prev->end + 1; + bytesLeft = startSeq + sslBytes - seq; + } + + if (!curr) + /* we're at the end */ + added = bytesLeft; + else + /* we're in between two frames */ + added = min((word32)bytesLeft, curr->begin - seq); + + /* data already there */ + if (added == 0) + continue; + + if (MaxRecoveryMemory != -1 && + (int)(*reassemblyMemory + added) > MaxRecoveryMemory) { + SetError(REASSEMBLY_MAX_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + add = CreateBuffer(&seq, seq + added - 1, &sslFrame[seq - startSeq], + &bytesLeft); + if (add == NULL) { + SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + add->next = prev->next; + prev->next = add; + *reassemblyMemory += added; + } + return 1; +} + + +/* Add out of order FIN capture */ +/* returns 1 for success (end) */ +static int AddFinCapture(SnifferSession* session, word32 sequence) +{ + if (session->flags.side == WOLFSSL_SERVER_END) { + if (session->finCaputre.cliCounted == 0) + session->finCaputre.cliFinSeq = sequence; + } + else { + if (session->finCaputre.srvCounted == 0) + session->finCaputre.srvFinSeq = sequence; + } + return 1; +} + + +/* Adjust incoming sequence based on side */ +/* returns 0 on success (continue), -1 on error, 1 on success (end) */ +static int AdjustSequence(TcpInfo* tcpInfo, SnifferSession* session, + int* sslBytes, const byte** sslFrame, char* error) +{ + word32 seqStart = (session->flags.side == WOLFSSL_SERVER_END) ? + session->cliSeqStart :session->srvSeqStart; + word32 real = tcpInfo->sequence - seqStart; + word32* expected = (session->flags.side == WOLFSSL_SERVER_END) ? + &session->cliExpected : &session->srvExpected; + PacketBuffer* reassemblyList = (session->flags.side == WOLFSSL_SERVER_END) ? + session->cliReassemblyList : session->srvReassemblyList; + byte skipPartial = (session->flags.side == WOLFSSL_SERVER_END) ? + session->flags.srvSkipPartial : + session->flags.cliSkipPartial; + + /* handle rollover of sequence */ + if (tcpInfo->sequence < seqStart) + real = 0xffffffffU - seqStart + tcpInfo->sequence; + + TraceRelativeSequence(*expected, real); + + if (real < *expected) { + Trace(DUPLICATE_STR); + if (real + *sslBytes > *expected) { + int overlap = *expected - real; + Trace(OVERLAP_DUPLICATE_STR); + + /* adjust to expected, remove duplicate */ + *sslFrame += overlap; + *sslBytes -= overlap; + + /* The following conditional block is duplicated below. It is the + * same action but for a different setup case. If changing this + * block be sure to also update the block below. */ + if (reassemblyList) { + word32 newEnd = *expected + *sslBytes; + + if (newEnd > reassemblyList->begin) { + Trace(OVERLAP_REASSEMBLY_BEGIN_STR); + + /* remove bytes already on reassembly list */ + *sslBytes -= newEnd - reassemblyList->begin; + } + if (newEnd > reassemblyList->end) { + Trace(OVERLAP_REASSEMBLY_END_STR); + + /* may be past reassembly list end (could have more on list) + so try to add what's past the front->end */ + AddToReassembly(session->flags.side, reassemblyList->end +1, + *sslFrame + reassemblyList->end - *expected + 1, + newEnd - reassemblyList->end, session, error); + } + } + } + else + return 1; + } + else if (real > *expected) { + Trace(OUT_OF_ORDER_STR); + if (*sslBytes > 0) { + int addResult = AddToReassembly(session->flags.side, real, + *sslFrame, *sslBytes, session, error); + if (skipPartial) { + *sslBytes = 0; + return 0; + } + else + return addResult; + } + else if (tcpInfo->fin) + return AddFinCapture(session, real); + } + else if (*sslBytes > 0) { + if (skipPartial) { + AddToReassembly(session->flags.side, real, + *sslFrame, *sslBytes, session, error); + *expected += *sslBytes; + *sslBytes = 0; + if (tcpInfo->fin) + *expected += 1; + return 0; + } + /* The following conditional block is duplicated above. It is the + * same action but for a different setup case. If changing this + * block be sure to also update the block above. */ + else if (reassemblyList) { + word32 newEnd = *expected + *sslBytes; + + if (newEnd > reassemblyList->begin) { + Trace(OVERLAP_REASSEMBLY_BEGIN_STR); + + /* remove bytes already on reassembly list */ + *sslBytes -= newEnd - reassemblyList->begin; + } + if (newEnd > reassemblyList->end) { + Trace(OVERLAP_REASSEMBLY_END_STR); + + /* may be past reassembly list end (could have more on list) + so try to add what's past the front->end */ + AddToReassembly(session->flags.side, reassemblyList->end +1, + *sslFrame + reassemblyList->end - *expected + 1, + newEnd - reassemblyList->end, session, error); + } + } + } + /* got expected sequence */ + *expected += *sslBytes; + if (tcpInfo->fin) + *expected += 1; + + return 0; +} + + +static int FindNextRecordInAssembly(SnifferSession* session, + const byte** sslFrame, int* sslBytes, + const byte** end, char* error) +{ + PacketBuffer** front = (session->flags.side == WOLFSSL_SERVER_END) ? + &session->cliReassemblyList : + &session->srvReassemblyList; + PacketBuffer* curr = *front; + PacketBuffer* prev = NULL; + byte* skipPartial = (session->flags.side == WOLFSSL_SERVER_END) ? + &session->flags.srvSkipPartial : + &session->flags.cliSkipPartial; + word32* reassemblyMemory = (session->flags.side == WOLFSSL_SERVER_END) ? + &session->cliReassemblyMemory : + &session->srvReassemblyMemory; + SSL* ssl = (session->flags.side == WOLFSSL_SERVER_END) ? + session->sslServer : + session->sslClient; + ProtocolVersion pv = ssl->version; + word32* expected = (session->flags.side == WOLFSSL_SERVER_END) ? + &session->cliExpected : + &session->srvExpected; + + while (curr != NULL) { + *expected = curr->end + 1; + + if (curr->data[0] == application_data && + curr->data[1] == pv.major && + curr->data[2] == pv.minor) { + + if (ssl->buffers.inputBuffer.length > 0) + Trace(DROPPING_PARTIAL_RECORD); + + *sslBytes = curr->end - curr->begin + 1; + if ( (word32)*sslBytes > ssl->buffers.inputBuffer.bufferSize) { + if (GrowInputBuffer(ssl, *sslBytes, 0) < 0) { + SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + } + + XMEMCPY(ssl->buffers.inputBuffer.buffer, curr->data, *sslBytes); + + *front = curr->next; + *reassemblyMemory -= *sslBytes; + FreePacketBuffer(curr); + + ssl->buffers.inputBuffer.length = *sslBytes; + *sslFrame = ssl->buffers.inputBuffer.buffer; + *end = *sslFrame + *sslBytes; + *skipPartial = 0; + + return 0; + } + else if (ssl->specs.cipher_type == block) { + if (ssl->specs.bulk_cipher_algorithm == wolfssl_aes) { +#ifdef BUILD_AES + wc_AesSetIV(ssl->decrypt.aes, + curr->data + curr->end - curr->begin + - ssl->specs.block_size + 1); +#endif + } + else if (ssl->specs.bulk_cipher_algorithm == wolfssl_triple_des) { +#ifdef BUILD_DES3 + wc_Des3_SetIV(ssl->decrypt.des3, + curr->data + curr->end - curr->begin + - ssl->specs.block_size + 1); +#endif + } + } + + Trace(DROPPING_LOST_FRAG_STR); +#ifdef WOLFSSL_SNIFFER_STATS + INC_STAT(SnifferStats.sslDecodeFails); +#endif + prev = curr; + curr = curr->next; + *reassemblyMemory -= (prev->end - prev->begin + 1); + FreePacketBuffer(prev); + } + + *front = curr; + + return 0; +} + + +static int FixSequence(TcpInfo* tcpInfo, SnifferSession* session) +{ + word32* expected = (session->flags.side == WOLFSSL_SERVER_END) ? + &session->srvExpected : &session->cliExpected; + PacketBuffer* list = (session->flags.side == WOLFSSL_SERVER_END) ? + session->srvReassemblyList : + session->cliReassemblyList; + byte* skipPartial = (session->flags.side != WOLFSSL_SERVER_END) ? + &session->flags.srvSkipPartial : + &session->flags.cliSkipPartial; + + *skipPartial = 1; + if (list != NULL) + *expected = list->begin; + else { + word32 seqStart = (session->flags.side == WOLFSSL_SERVER_END) ? + session->srvSeqStart : session->cliSeqStart; + word32 real = tcpInfo->ackNumber - seqStart; + + *expected = real; + } + + return 1; +} + + +/* Check latest ack number for missing packets + return 0 ok, <0 on error */ +static int CheckAck(TcpInfo* tcpInfo, SnifferSession* session) +{ + if (tcpInfo->ack) { + word32 seqStart = (session->flags.side == WOLFSSL_SERVER_END) ? + session->srvSeqStart :session->cliSeqStart; + word32 real = tcpInfo->ackNumber - seqStart; + word32 expected = (session->flags.side == WOLFSSL_SERVER_END) ? + session->srvExpected : session->cliExpected; + + /* handle rollover of sequence */ + if (tcpInfo->ackNumber < seqStart) + real = 0xffffffffU - seqStart + tcpInfo->ackNumber; + + TraceAck(real, expected); + + if (real > expected) + return -1; /* we missed a packet, ACKing data we never saw */ + } + return 0; +} + + +/* Check TCP Sequence status */ +/* returns 0 on success (continue), -1 on error, 1 on success (end) */ +static int CheckSequence(IpInfo* ipInfo, TcpInfo* tcpInfo, + SnifferSession* session, int* sslBytes, + const byte** sslFrame, char* error) +{ + int actualLen; + byte* ackFault = (session->flags.side == WOLFSSL_SERVER_END) ? + &session->flags.cliAckFault : + &session->flags.srvAckFault; + + /* init SEQ from server to client */ + if (tcpInfo->syn && tcpInfo->ack) { + session->srvSeqStart = tcpInfo->sequence; + session->srvExpected = 1; + TraceServerSyn(tcpInfo->sequence); + return 1; + } + + /* adjust potential ethernet trailer */ + actualLen = ipInfo->total - ipInfo->length - tcpInfo->length; + if (*sslBytes > actualLen) { + *sslBytes = actualLen; + } + + TraceSequence(tcpInfo->sequence, *sslBytes); + if (CheckAck(tcpInfo, session) < 0) { + if (!RecoveryEnabled) { + UpdateMissedDataSessions(); + SetError(ACK_MISSED_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + else { + SetError(ACK_MISSED_STR, error, session, 0); + if (*ackFault == 0) { + *ackFault = 1; + UpdateMissedDataSessions(); + } + return FixSequence(tcpInfo, session); + } + } + + if (*ackFault) { + Trace(CLEAR_ACK_FAULT); + *ackFault = 0; + } + + return AdjustSequence(tcpInfo, session, sslBytes, sslFrame, error); +} + + +/* Check Status before record processing */ +/* returns 0 on success (continue), -1 on error, 1 on success (end) */ +static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo, + const byte** sslFrame, SnifferSession** session, + int* sslBytes, const byte** end, char* error) +{ + word32 length; + SSL* ssl = ((*session)->flags.side == WOLFSSL_SERVER_END) ? + (*session)->sslServer : (*session)->sslClient; + byte skipPartial = ((*session)->flags.side == WOLFSSL_SERVER_END) ? + (*session)->flags.srvSkipPartial : + (*session)->flags.cliSkipPartial; + /* remove SnifferSession on 2nd FIN or RST */ + if (tcpInfo->fin || tcpInfo->rst) { + /* flag FIN and RST */ + if (tcpInfo->fin) + (*session)->flags.finCount += 1; + else if (tcpInfo->rst) + (*session)->flags.finCount += 2; + + if ((*session)->flags.finCount >= 2) { + RemoveSession(*session, ipInfo, tcpInfo, 0); + *session = NULL; + return 1; + } + } + + if ((*session)->flags.fatalError == FATAL_ERROR_STATE) { + SetError(FATAL_ERROR_STR, error, NULL, 0); + return -1; + } + + if (skipPartial) { + if (FindNextRecordInAssembly(*session, + sslFrame, sslBytes, end, error) < 0) { + return -1; + } + } + + if (*sslBytes == 0) { + Trace(NO_DATA_STR); + return 1; + } + + /* if current partial data, add to end of partial */ + /* if skipping, the data is already at the end of partial */ + if ( !skipPartial && + (length = ssl->buffers.inputBuffer.length) ) { + Trace(PARTIAL_ADD_STR); + + if ( (*sslBytes + length) > ssl->buffers.inputBuffer.bufferSize) { + if (GrowInputBuffer(ssl, *sslBytes, length) < 0) { + SetError(MEMORY_STR, error, *session, FATAL_ERROR_STATE); + return -1; + } + } + XMEMCPY(&ssl->buffers.inputBuffer.buffer[length], *sslFrame, *sslBytes); + *sslBytes += length; + ssl->buffers.inputBuffer.length = *sslBytes; + *sslFrame = ssl->buffers.inputBuffer.buffer; + *end = *sslFrame + *sslBytes; + } + + if ((*session)->flags.clientHello == 0 && **sslFrame != handshake) { + /* Sanity check the packet for an old style client hello. */ + int rhSize = (((*sslFrame)[0] & 0x7f) << 8) | ((*sslFrame)[1]); + + if ((rhSize <= (*sslBytes - 2)) && + (*sslFrame)[2] == OLD_HELLO_ID && (*sslFrame)[3] == SSLv3_MAJOR) { +#ifdef OLD_HELLO_ALLOWED + int ret = DoOldHello(*session, *sslFrame, &rhSize, sslBytes, error); + if (ret < 0) + return -1; /* error already set */ + if (*sslBytes <= 0) + return 1; +#endif + } + else { +#ifdef STARTTLS_ALLOWED + return 1; +#endif + } + } + + return 0; +} + + +/* See if input on the reassembly list is ready for consuming */ +/* returns 1 for TRUE, 0 for FALSE */ +static int HaveMoreInput(SnifferSession* session, const byte** sslFrame, + int* sslBytes, const byte** end, char* error) +{ + /* sequence and reassembly based on from, not to */ + int moreInput = 0; + PacketBuffer** front = (session->flags.side == WOLFSSL_SERVER_END) ? + &session->cliReassemblyList : &session->srvReassemblyList; + word32* expected = (session->flags.side == WOLFSSL_SERVER_END) ? + &session->cliExpected : &session->srvExpected; + /* buffer is on receiving end */ + word32* length = (session->flags.side == WOLFSSL_SERVER_END) ? + &session->sslServer->buffers.inputBuffer.length : + &session->sslClient->buffers.inputBuffer.length; + byte** myBuffer = (session->flags.side == WOLFSSL_SERVER_END) ? + &session->sslServer->buffers.inputBuffer.buffer : + &session->sslClient->buffers.inputBuffer.buffer; + word32* bufferSize = (session->flags.side == WOLFSSL_SERVER_END) ? + &session->sslServer->buffers.inputBuffer.bufferSize : + &session->sslClient->buffers.inputBuffer.bufferSize; + SSL* ssl = (session->flags.side == WOLFSSL_SERVER_END) ? + session->sslServer : session->sslClient; + word32* reassemblyMemory = (session->flags.side == WOLFSSL_SERVER_END) ? + &session->cliReassemblyMemory : &session->srvReassemblyMemory; + + while (*front && ((*front)->begin == *expected) ) { + word32 room = *bufferSize - *length; + word32 packetLen = (*front)->end - (*front)->begin + 1; + + if (packetLen > room && *bufferSize < MAX_INPUT_SZ) { + if (GrowInputBuffer(ssl, packetLen, *length) < 0) { + SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE); + return 0; + } + room = *bufferSize - *length; /* bufferSize is now bigger */ + } + + if (packetLen <= room) { + PacketBuffer* del = *front; + byte* buf = *myBuffer; + + XMEMCPY(&buf[*length], (*front)->data, packetLen); + *length += packetLen; + *expected += packetLen; + + /* remove used packet */ + *front = (*front)->next; + + *reassemblyMemory -= packetLen; + FreePacketBuffer(del); + + moreInput = 1; + } + else + break; + } + if (moreInput) { + *sslFrame = *myBuffer; + *sslBytes = *length; + *end = *myBuffer + *length; + } + return moreInput; +} + + + +/* Process Message(s) from sslFrame */ +/* return Number of bytes on success, 0 for no data yet, and -1 on error */ +static int ProcessMessage(const byte* sslFrame, SnifferSession* session, + int sslBytes, byte** data, const byte* end, + char* error) +{ + const byte* sslBegin = sslFrame; + const byte* recordEnd; /* end of record indicator */ + const byte* inRecordEnd; /* indicator from input stream not decrypt */ + RecordLayerHeader rh; + int rhSize = 0; + int ret; + int errCode = 0; + int decoded = 0; /* bytes stored for user in data */ + int notEnough; /* notEnough bytes yet flag */ + int decrypted = 0; /* was current msg decrypted */ + SSL* ssl = (session->flags.side == WOLFSSL_SERVER_END) ? + session->sslServer : session->sslClient; +doMessage: + notEnough = 0; + if (sslBytes < 0) { + SetError(PACKET_HDR_SHORT_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + if (sslBytes >= RECORD_HEADER_SZ) { + if (GetRecordHeader(sslFrame, &rh, &rhSize) != 0) { + SetError(BAD_RECORD_HDR_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + } + else + notEnough = 1; + + if (notEnough || rhSize > (sslBytes - RECORD_HEADER_SZ)) { + /* don't have enough input yet to process full SSL record */ + Trace(PARTIAL_INPUT_STR); + + /* store partial if not there already or we advanced */ + if (ssl->buffers.inputBuffer.length == 0 || sslBegin != sslFrame) { + if (sslBytes > (int)ssl->buffers.inputBuffer.bufferSize) { + if (GrowInputBuffer(ssl, sslBytes, 0) < 0) { + SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + } + XMEMMOVE(ssl->buffers.inputBuffer.buffer, sslFrame, sslBytes); + ssl->buffers.inputBuffer.length = sslBytes; + } + if (HaveMoreInput(session, &sslFrame, &sslBytes, &end, error)) + goto doMessage; + return decoded; + } + sslFrame += RECORD_HEADER_SZ; + sslBytes -= RECORD_HEADER_SZ; + recordEnd = sslFrame + rhSize; /* may have more than one record */ + inRecordEnd = recordEnd; + + /* decrypt if needed */ + if ((session->flags.side == WOLFSSL_SERVER_END && + session->flags.serverCipherOn) + || (session->flags.side == WOLFSSL_CLIENT_END && + session->flags.clientCipherOn)) { + int ivAdvance = 0; /* TLSv1.1 advance amount */ + if (ssl->decrypt.setup != 1) { + SetError(DECRYPT_KEYS_NOT_SETUP, error, session, FATAL_ERROR_STATE); + return -1; + } + if (CheckAvailableSize(ssl, rhSize) < 0) { + SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + sslFrame = DecryptMessage(ssl, sslFrame, rhSize, + ssl->buffers.outputBuffer.buffer, &errCode, + &ivAdvance); + recordEnd = sslFrame - ivAdvance + rhSize; /* sslFrame moved so + should recordEnd */ + decrypted = 1; + if (errCode != 0) { + SetError(BAD_DECRYPT, error, session, FATAL_ERROR_STATE); + return -1; + } + } + +doPart: + + switch ((enum ContentType)rh.type) { + case handshake: + { + int startIdx = sslBytes; + int used; + + Trace(GOT_HANDSHAKE_STR); + ret = DoHandShake(sslFrame, &sslBytes, session, error); + if (ret != 0) { + if (session->flags.fatalError == 0) + SetError(BAD_HANDSHAKE_STR, error, session, + FATAL_ERROR_STATE); + return -1; + } + + /* DoHandShake now fully decrements sslBytes to remaining */ + used = startIdx - sslBytes; + sslFrame += used; + if (decrypted) + sslFrame += ssl->keys.padSz; + } + break; + case change_cipher_spec: + if (session->flags.side == WOLFSSL_SERVER_END) + session->flags.serverCipherOn = 1; + else + session->flags.clientCipherOn = 1; + Trace(GOT_CHANGE_CIPHER_STR); + ssl->options.handShakeState = HANDSHAKE_DONE; + ssl->options.handShakeDone = 1; + + sslFrame += 1; + sslBytes -= 1; + + break; + case application_data: + Trace(GOT_APP_DATA_STR); + { + word32 inOutIdx = 0; + + ret = DoApplicationData(ssl, (byte*)sslFrame, &inOutIdx); + if (ret == 0) { + ret = ssl->buffers.clearOutputBuffer.length; + TraceGotData(ret); + if (ret) { /* may be blank message */ + byte* tmpData; /* don't leak on realloc free */ + /* add an extra byte at end of allocation in case user + * wants to null terminate plaintext */ + tmpData = (byte*)realloc(*data, decoded + ret + 1); + if (tmpData == NULL) { + ForceZero(*data, decoded); + free(*data); + *data = NULL; + SetError(MEMORY_STR, error, session, + FATAL_ERROR_STATE); + return -1; + } + *data = tmpData; + XMEMCPY(*data + decoded, + ssl->buffers.clearOutputBuffer.buffer, ret); + TraceAddedData(ret, decoded); + decoded += ret; + ssl->buffers.clearOutputBuffer.length = 0; + } + } + else { + SetError(BAD_APP_DATA_STR, error,session,FATAL_ERROR_STATE); + return -1; + } + if (ssl->buffers.outputBuffer.dynamicFlag) + ShrinkOutputBuffer(ssl); + + sslFrame += inOutIdx; + sslBytes -= inOutIdx; + } + break; + case alert: + Trace(GOT_ALERT_STR); +#ifdef WOLFSSL_SNIFFER_STATS + INC_STAT(SnifferStats.sslAlerts); +#endif + sslFrame += rhSize; + sslBytes -= rhSize; + break; + case no_type: + default: + SetError(GOT_UNKNOWN_RECORD_STR, error, session, FATAL_ERROR_STATE); + return -1; + } + + /* do we have another msg in record ? */ + if (sslFrame < recordEnd) { + Trace(ANOTHER_MSG_STR); + goto doPart; + } + + /* back to input stream instead of potential decrypt buffer */ + recordEnd = inRecordEnd; + + /* do we have more records ? */ + if (recordEnd < end) { + Trace(ANOTHER_MSG_STR); + sslFrame = recordEnd; + sslBytes = (int)(end - recordEnd); + goto doMessage; + } + + /* clear used input */ + ssl->buffers.inputBuffer.length = 0; + + /* could have more input ready now */ + if (HaveMoreInput(session, &sslFrame, &sslBytes, &end, error)) + goto doMessage; + + if (ssl->buffers.inputBuffer.dynamicFlag) + ShrinkInputBuffer(ssl, NO_FORCED_FREE); + + return decoded; +} + + +/* See if we need to process any pending FIN captures */ +/* Return 0=normal, else = session removed */ +static int CheckFinCapture(IpInfo* ipInfo, TcpInfo* tcpInfo, + SnifferSession* session) +{ + int ret = 0; + if (session->finCaputre.cliFinSeq && session->finCaputre.cliFinSeq <= + session->cliExpected) { + if (session->finCaputre.cliCounted == 0) { + session->flags.finCount += 1; + session->finCaputre.cliCounted = 1; + TraceClientFin(session->finCaputre.cliFinSeq, session->cliExpected); + } + } + + if (session->finCaputre.srvFinSeq && session->finCaputre.srvFinSeq <= + session->srvExpected) { + if (session->finCaputre.srvCounted == 0) { + session->flags.finCount += 1; + session->finCaputre.srvCounted = 1; + TraceServerFin(session->finCaputre.srvFinSeq, session->srvExpected); + } + } + + if (session->flags.finCount >= 2) { + RemoveSession(session, ipInfo, tcpInfo, 0); + ret = 1; + } + return ret; +} + + +/* If session is in fatal error state free resources now + return true if removed, 0 otherwise */ +static int RemoveFatalSession(IpInfo* ipInfo, TcpInfo* tcpInfo, + SnifferSession* session, char* error) +{ + if (session && session->flags.fatalError == FATAL_ERROR_STATE) { + RemoveSession(session, ipInfo, tcpInfo, 0); + SetError(FATAL_ERROR_STR, error, NULL, 0); + return 1; + } + return 0; +} + + +/* Passes in an IP/TCP packet for decoding (ethernet/localhost frame) removed */ +/* returns Number of bytes on success, 0 for no data yet, and -1 on error */ +static int ssl_DecodePacketInternal(const byte* packet, int length, + byte** data, SSLInfo* sslInfo, char* error) +{ + TcpInfo tcpInfo; + IpInfo ipInfo; + const byte* sslFrame; + const byte* end = packet + length; + int sslBytes; /* ssl bytes unconsumed */ + int ret; + SnifferSession* session = 0; + + if (CheckHeaders(&ipInfo, &tcpInfo, packet, length, &sslFrame, &sslBytes, + error) != 0) + return -1; + + ret = CheckSession(&ipInfo, &tcpInfo, sslBytes, &session, error); + if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1; + else if (ret == -1) return -1; + else if (ret == 1) { +#ifdef WOLFSSL_SNIFFER_STATS + if (sslBytes > 0) { + LOCK_STAT(); + NOLOCK_INC_STAT(SnifferStats.sslEncryptedPackets); + NOLOCK_ADD_TO_STAT(SnifferStats.sslEncryptedBytes, sslBytes); + UNLOCK_STAT(); + } + else + INC_STAT(SnifferStats.sslDecryptedPackets); +#endif + return 0; /* done for now */ + } + + ret = CheckSequence(&ipInfo, &tcpInfo, session, &sslBytes, &sslFrame,error); + if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1; + else if (ret == -1) return -1; + else if (ret == 1) { +#ifdef WOLFSSL_SNIFFER_STATS + INC_STAT(SnifferStats.sslDecryptedPackets); +#endif + return 0; /* done for now */ + } + + ret = CheckPreRecord(&ipInfo, &tcpInfo, &sslFrame, &session, &sslBytes, + &end, error); + if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1; + else if (ret == -1) return -1; + else if (ret == 1) { +#ifdef WOLFSSL_SNIFFER_STATS + INC_STAT(SnifferStats.sslDecryptedPackets); +#endif + return 0; /* done for now */ + } + +#ifdef WOLFSSL_SNIFFER_STATS + if (sslBytes > 0) { + LOCK_STAT(); + NOLOCK_INC_STAT(SnifferStats.sslEncryptedPackets); + NOLOCK_ADD_TO_STAT(SnifferStats.sslEncryptedBytes, sslBytes); + UNLOCK_STAT(); + } + else + INC_STAT(SnifferStats.sslDecryptedPackets); +#endif + + ret = ProcessMessage(sslFrame, session, sslBytes, data, end, error); + if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1; + if (CheckFinCapture(&ipInfo, &tcpInfo, session) == 0) { + CopySessionInfo(session, sslInfo); + } + + return ret; +} + + +/* Passes in an IP/TCP packet for decoding (ethernet/localhost frame) removed */ +/* returns Number of bytes on success, 0 for no data yet, and -1 on error */ +/* Also returns Session Info if available */ +int ssl_DecodePacketWithSessionInfo(const unsigned char* packet, int length, + unsigned char** data, SSLInfo* sslInfo, char* error) +{ + return ssl_DecodePacketInternal(packet, length, data, sslInfo, error); +} + + +/* Passes in an IP/TCP packet for decoding (ethernet/localhost frame) removed */ +/* returns Number of bytes on success, 0 for no data yet, and -1 on error */ +int ssl_DecodePacket(const byte* packet, int length, byte** data, char* error) +{ + return ssl_DecodePacketInternal(packet, length, data, NULL, error); +} + + +/* Deallocator for the decoded data buffer. */ +/* returns 0 on success, -1 on error */ +int ssl_FreeDecodeBuffer(byte** data, char* error) +{ + return ssl_FreeZeroDecodeBuffer(data, 0, error); +} + + +/* Deallocator for the decoded data buffer, zeros out buffer. */ +/* returns 0 on success, -1 on error */ +int ssl_FreeZeroDecodeBuffer(byte** data, int sz, char* error) +{ + (void)error; + + if (sz < 0) { + return -1; + } + + if (data != NULL) { + ForceZero(*data, (word32)sz); + free(*data); + *data = NULL; + } + + return 0; +} + + +/* Enables (if traceFile)/ Disables debug tracing */ +/* returns 0 on success, -1 on error */ +int ssl_Trace(const char* traceFile, char* error) +{ + if (traceFile) { + TraceFile = fopen(traceFile, "a"); + if (!TraceFile) { + SetError(BAD_TRACE_FILE_STR, error, NULL, 0); + return -1; + } + TraceOn = 1; + } + else + TraceOn = 0; + + return 0; +} + + +/* Enables/Disables Recovery of missed data if later packets allow + * maxMemory is number of bytes to use for reassembly buffering per session, + * -1 means unlimited + * returns 0 on success, -1 on error */ +int ssl_EnableRecovery(int onOff, int maxMemory, char* error) +{ + (void)error; + + RecoveryEnabled = onOff; + if (onOff) + MaxRecoveryMemory = maxMemory; + + return 0; +} + + + +int ssl_GetSessionStats(unsigned int* active, unsigned int* total, + unsigned int* peak, unsigned int* maxSessions, + unsigned int* missedData, unsigned int* reassemblyMem, + char* error) +{ + int ret; + + if (missedData) { + wc_LockMutex(&RecoveryMutex); + *missedData = MissedDataSessions; + wc_UnLockMutex(&RecoveryMutex); + } + + if (reassemblyMem) { + SnifferSession* session; + int i; + + *reassemblyMem = 0; + wc_LockMutex(&SessionMutex); + for (i = 0; i < HASH_SIZE; i++) { + session = SessionTable[i]; + while (session) { + *reassemblyMem += session->cliReassemblyMemory; + *reassemblyMem += session->srvReassemblyMemory; + session = session->next; + } + } + wc_UnLockMutex(&SessionMutex); + } + + ret = wolfSSL_get_session_stats(active, total, peak, maxSessions); + + if (ret == WOLFSSL_SUCCESS) + return 0; + else { + SetError(BAD_SESSION_STATS, error, NULL, 0); + return -1; + } +} + + + +int ssl_SetConnectionCb(SSLConnCb cb) +{ + ConnectionCb = cb; + return 0; +} + + + +int ssl_SetConnectionCtx(void* ctx) +{ + ConnectionCbCtx = ctx; + return 0; +} + + +#ifdef WOLFSSL_SNIFFER_STATS + +/* Resets the statistics tracking global structure. + * returns 0 on success, -1 on error */ +int ssl_ResetStatistics(void) +{ + wc_LockMutex(&StatsMutex); + XMEMSET(&SnifferStats, 0, sizeof(SSLStats)); + wc_UnLockMutex(&StatsMutex); + return 0; +} + + +/* Copies the SSL statistics into the provided stats record. + * returns 0 on success, -1 on error */ +int ssl_ReadStatistics(SSLStats* stats) +{ + if (stats == NULL) + return -1; + + wc_LockMutex(&StatsMutex); + XMEMCPY(stats, &SnifferStats, sizeof(SSLStats)); + wc_UnLockMutex(&StatsMutex); + return 0; +} + +/* Copies the SSL statistics into the provided stats record then + * resets the statistics tracking global structure. + * returns 0 on success, -1 on error */ +int ssl_ReadResetStatistics(SSLStats* stats) +{ + if (stats == NULL) + return -1; + + wc_LockMutex(&StatsMutex); + XMEMCPY(stats, &SnifferStats, sizeof(SSLStats)); + XMEMSET(&SnifferStats, 0, sizeof(SSLStats)); + wc_UnLockMutex(&StatsMutex); + return 0; +} + +#endif /* WOLFSSL_SNIFFER_STATS */ + + +#ifdef WOLFSSL_SNIFFER_WATCH + +int ssl_SetWatchKeyCallback(SSLWatchCb cb, char* error) +{ + WatchCb = cb; + return CreateWatchSnifferServer(error); +} + + +int ssl_SetWatchKeyCtx(void* ctx, char* error) +{ + (void)error; + WatchCbCtx = ctx; + return 0; +} + + +int ssl_SetWatchKey_buffer(void* vSniffer, const byte* key, word32 keySz, + int keyType, char* error) +{ + SnifferSession* sniffer; + int ret; + + if (vSniffer == NULL) { + return -1; + } + if (key == NULL || keySz == 0) { + return -1; + } + + sniffer = (SnifferSession*)vSniffer; + /* Remap the keyType from what the user can use to + * what wolfSSL_use_PrivateKey_buffer expects. */ + keyType = (keyType == FILETYPE_PEM) ? WOLFSSL_FILETYPE_PEM : + WOLFSSL_FILETYPE_ASN1; + + ret = wolfSSL_use_PrivateKey_buffer(sniffer->sslServer, + key, keySz, keyType); + if (ret != WOLFSSL_SUCCESS) { + SetError(KEY_FILE_STR, error, sniffer, FATAL_ERROR_STATE); + return -1; + } + + return 0; +} + + +int ssl_SetWatchKey_file(void* vSniffer, const char* keyFile, int keyType, + const char* password, char* error) +{ + byte* keyBuf = NULL; + word32 keyBufSz = 0; + int ret; + + if (vSniffer == NULL) { + return -1; + } + if (keyFile == NULL) { + return -1; + } + + /* Remap the keyType from what the user can use to + * what LoadKeyFile expects. */ + keyType = (keyType == FILETYPE_PEM) ? WOLFSSL_FILETYPE_PEM : + WOLFSSL_FILETYPE_ASN1; + + ret = LoadKeyFile(&keyBuf, &keyBufSz, keyFile, keyType, password); + if (ret < 0) { + SetError(KEY_FILE_STR, error, NULL, 0); + free(keyBuf); + return -1; + } + + ret = ssl_SetWatchKey_buffer(vSniffer, keyBuf, keyBufSz, FILETYPE_DER, + error); + free(keyBuf); + + return ret; +} + +#endif /* WOLFSSL_SNIFFER_WATCH */ + +#endif /* WOLFSSL_SNIFFER */ +#endif /* WOLFCRYPT_ONLY */ diff --git a/beken_os/beken378/func/wolfssl/src/ssl.c b/beken_os/beken378/func/wolfssl/src/ssl.c new file mode 100755 index 0000000..7770f94 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/src/ssl.c @@ -0,0 +1,37001 @@ +/* ssl.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifndef WOLFCRYPT_ONLY + +#ifdef HAVE_ERRNO_H + #include +#endif + +#include +#include +#include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + + +#ifndef WOLFSSL_ALLOW_NO_SUITES + #if defined(NO_DH) && !defined(HAVE_ECC) && !defined(WOLFSSL_STATIC_RSA) \ + && !defined(WOLFSSL_STATIC_DH) && !defined(WOLFSSL_STATIC_PSK) \ + && !defined(HAVE_ED25519) + #error "No cipher suites defined because DH disabled, ECC disabled, and no static suites defined. Please see top of README" + #endif +#endif + +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || \ + defined(HAVE_WEBSERVER) || defined(WOLFSSL_KEY_GEN) + #include + /* openssl headers end, wolfssl internal headers next */ +#endif + +#include + +#ifdef OPENSSL_EXTRA + /* openssl headers begin */ + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + /* openssl headers end, wolfssl internal headers next */ + #include + #include + #include + #include + #include + #include + #include + #include + #include + #if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) + #include + #endif /* WITH_STUNNEL */ + #if defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384) + #include + #endif + #if defined(WOLFCRYPT_HAVE_SRP) && !defined(NO_SHA256) \ + && !defined(WC_NO_RNG) + #include + #endif + #if defined(OPENSSL_ALL) && defined(HAVE_PKCS7) + #include + #endif /* OPENSSL_ALL && HAVE_PKCS7 */ +#endif + +#ifdef NO_ASN + #include +#endif + + +#ifdef WOLFSSL_SESSION_EXPORT +#ifdef WOLFSSL_DTLS +int wolfSSL_dtls_import(WOLFSSL* ssl, unsigned char* buf, unsigned int sz) +{ + WOLFSSL_ENTER("wolfSSL_session_import"); + + if (ssl == NULL || buf == NULL) { + return BAD_FUNC_ARG; + } + + /* sanity checks on buffer and protocol are done in internal function */ + return wolfSSL_dtls_import_internal(ssl, buf, sz); +} + + +/* Sets the function to call for serializing the session. This function is + * called right after the handshake is completed. */ +int wolfSSL_CTX_dtls_set_export(WOLFSSL_CTX* ctx, wc_dtls_export func) +{ + + WOLFSSL_ENTER("wolfSSL_CTX_dtls_set_export"); + + /* purposefully allow func to be NULL */ + if (ctx == NULL) { + return BAD_FUNC_ARG; + } + + ctx->dtls_export = func; + + return WOLFSSL_SUCCESS; +} + + +/* Sets the function in WOLFSSL struct to call for serializing the session. This + * function is called right after the handshake is completed. */ +int wolfSSL_dtls_set_export(WOLFSSL* ssl, wc_dtls_export func) +{ + + WOLFSSL_ENTER("wolfSSL_dtls_set_export"); + + /* purposefully allow func to be NULL */ + if (ssl == NULL) { + return BAD_FUNC_ARG; + } + + ssl->dtls_export = func; + + return WOLFSSL_SUCCESS; +} + + +/* This function allows for directly serializing a session rather than using + * callbacks. It has less overhead by removing a temporary buffer and gives + * control over when the session gets serialized. When using callbacks the + * session is always serialized immediately after the handshake is finished. + * + * buf is the argument to contain the serialized session + * sz is the size of the buffer passed in + * ssl is the WOLFSSL struct to serialize + * returns the size of serialized session on success, 0 on no action, and + * negative value on error */ +int wolfSSL_dtls_export(WOLFSSL* ssl, unsigned char* buf, unsigned int* sz) +{ + WOLFSSL_ENTER("wolfSSL_dtls_export"); + + if (ssl == NULL || sz == NULL) { + return BAD_FUNC_ARG; + } + + if (buf == NULL) { + *sz = MAX_EXPORT_BUFFER; + return 0; + } + + /* if not DTLS do nothing */ + if (!ssl->options.dtls) { + WOLFSSL_MSG("Currently only DTLS export is supported"); + return 0; + } + + /* copy over keys, options, and dtls state struct */ + return wolfSSL_dtls_export_internal(ssl, buf, *sz); +} + + +/* This function is similar to wolfSSL_dtls_export but only exports the portion + * of the WOLFSSL structure related to the state of the connection, i.e. peer + * sequence number, epoch, AEAD state etc. + * + * buf is the argument to contain the serialized state, if null then set "sz" to + * buffer size required + * sz is the size of the buffer passed in + * ssl is the WOLFSSL struct to serialize + * returns the size of serialized session on success, 0 on no action, and + * negative value on error */ +int wolfSSL_dtls_export_state_only(WOLFSSL* ssl, unsigned char* buf, + unsigned int* sz) +{ + WOLFSSL_ENTER("wolfSSL_dtls_export_state_only"); + + if (ssl == NULL || sz == NULL) { + return BAD_FUNC_ARG; + } + + if (buf == NULL) { + *sz = MAX_EXPORT_STATE_BUFFER; + return 0; + } + + /* if not DTLS do nothing */ + if (!ssl->options.dtls) { + WOLFSSL_MSG("Currently only DTLS export state is supported"); + return 0; + } + + /* copy over keys, options, and dtls state struct */ + return wolfSSL_dtls_export_state_internal(ssl, buf, *sz); +} + + +/* returns 0 on success */ +int wolfSSL_send_session(WOLFSSL* ssl) +{ + int ret; + byte* buf; + word16 bufSz = MAX_EXPORT_BUFFER; + + WOLFSSL_ENTER("wolfSSL_send_session"); + + if (ssl == NULL) { + return BAD_FUNC_ARG; + } + + buf = (byte*)XMALLOC(bufSz, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (buf == NULL) { + return MEMORY_E; + } + + /* if not DTLS do nothing */ + if (!ssl->options.dtls) { + XFREE(buf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + WOLFSSL_MSG("Currently only DTLS export is supported"); + return 0; + } + + /* copy over keys, options, and dtls state struct */ + ret = wolfSSL_dtls_export_internal(ssl, buf, bufSz); + if (ret < 0) { + XFREE(buf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + + /* if no error ret has size of buffer */ + ret = ssl->dtls_export(ssl, buf, ret, NULL); + if (ret != WOLFSSL_SUCCESS) { + XFREE(buf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + + XFREE(buf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + return 0; +} +#endif /* WOLFSSL_DTLS */ +#endif /* WOLFSSL_SESSION_EXPORT */ + + +/* prevent multiple mutex initializations */ +static volatile int initRefCount = 0; +static wolfSSL_Mutex count_mutex; /* init ref count mutex */ + +/* Create a new WOLFSSL_CTX struct and return the pointer to created struct. + WOLFSSL_METHOD pointer passed in is given to ctx to manage. + This function frees the passed in WOLFSSL_METHOD struct on failure and on + success is freed when ctx is freed. + */ +WOLFSSL_CTX* wolfSSL_CTX_new_ex(WOLFSSL_METHOD* method, void* heap) +{ + WOLFSSL_CTX* ctx = NULL; + + WOLFSSL_ENTER("wolfSSL_CTX_new_ex"); + + if (initRefCount == 0) { + /* user no longer forced to call Init themselves */ + int ret = wolfSSL_Init(); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_Init failed"); + WOLFSSL_LEAVE("WOLFSSL_CTX_new", 0); + if (method != NULL) { + XFREE(method, heap, DYNAMIC_TYPE_METHOD); + } + return NULL; + } + } + + if (method == NULL) + return ctx; + + ctx = (WOLFSSL_CTX*) XMALLOC(sizeof(WOLFSSL_CTX), heap, DYNAMIC_TYPE_CTX); + if (ctx) { + if (InitSSL_Ctx(ctx, method, heap) < 0) { + WOLFSSL_MSG("Init CTX failed"); + wolfSSL_CTX_free(ctx); + ctx = NULL; + } +#if defined(OPENSSL_EXTRA) && defined(WOLFCRYPT_HAVE_SRP) \ + && !defined(NO_SHA256) && !defined(WC_NO_RNG) + else { + ctx->srp = (Srp*) XMALLOC(sizeof(Srp), heap, DYNAMIC_TYPE_SRP); + if (ctx->srp == NULL){ + WOLFSSL_MSG("Init CTX failed"); + wolfSSL_CTX_free(ctx); + return NULL; + } + XMEMSET(ctx->srp, 0, sizeof(Srp)); + } +#endif + } + else { + WOLFSSL_MSG("Alloc CTX failed, method freed"); + XFREE(method, heap, DYNAMIC_TYPE_METHOD); + } + + + WOLFSSL_LEAVE("WOLFSSL_CTX_new", 0); + return ctx; +} + + +WOLFSSL_CTX* wolfSSL_CTX_new(WOLFSSL_METHOD* method) +{ +#ifdef WOLFSSL_HEAP_TEST + /* if testing the heap hint then set top level CTX to have test value */ + return wolfSSL_CTX_new_ex(method, (void*)WOLFSSL_HEAP_TEST); +#else + return wolfSSL_CTX_new_ex(method, NULL); +#endif +} + + +void wolfSSL_CTX_free(WOLFSSL_CTX* ctx) +{ + WOLFSSL_ENTER("SSL_CTX_free"); + if (ctx) { +#if defined(OPENSSL_EXTRA) && defined(WOLFCRYPT_HAVE_SRP) \ +&& !defined(NO_SHA256) && !defined(WC_NO_RNG) + if (ctx->srp != NULL){ + if (ctx->srp_password != NULL){ + XFREE(ctx->srp_password, ctx->heap, DYNAMIC_TYPE_SRP); + ctx->srp_password = NULL; + } + wc_SrpTerm(ctx->srp); + XFREE(ctx->srp, ctx->heap, DYNAMIC_TYPE_SRP); + ctx->srp = NULL; + } +#endif + FreeSSL_Ctx(ctx); + } + + WOLFSSL_LEAVE("SSL_CTX_free", 0); +} + + +#ifdef SINGLE_THREADED +/* no locking in single threaded mode, allow a CTX level rng to be shared with + * WOLFSSL objects, WOLFSSL_SUCCESS on ok */ +int wolfSSL_CTX_new_rng(WOLFSSL_CTX* ctx) +{ + WC_RNG* rng; + int ret; + + if (ctx == NULL) { + return BAD_FUNC_ARG; + } + + rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), ctx->heap, DYNAMIC_TYPE_RNG); + if (rng == NULL) { + return MEMORY_E; + } + +#ifndef HAVE_FIPS + ret = wc_InitRng_ex(rng, ctx->heap, ctx->devId); +#else + ret = wc_InitRng(rng); +#endif + if (ret != 0) { + XFREE(rng, ctx->heap, DYNAMIC_TYPE_RNG); + return ret; + } + + ctx->rng = rng; + return WOLFSSL_SUCCESS; +} +#endif + + +WOLFSSL* wolfSSL_new(WOLFSSL_CTX* ctx) +{ + WOLFSSL* ssl = NULL; + int ret = 0; + + (void)ret; + WOLFSSL_ENTER("SSL_new"); + + if (ctx == NULL) + return ssl; + + ssl = (WOLFSSL*) XMALLOC(sizeof(WOLFSSL), ctx->heap, DYNAMIC_TYPE_SSL); + if (ssl) + if ( (ret = InitSSL(ssl, ctx, 0)) < 0) { + FreeSSL(ssl, ctx->heap); + ssl = 0; + } + + WOLFSSL_LEAVE("SSL_new", ret); + return ssl; +} + + +void wolfSSL_free(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("SSL_free"); + if (ssl) + FreeSSL(ssl, ssl->ctx->heap); + WOLFSSL_LEAVE("SSL_free", 0); +} + + +int wolfSSL_is_server(WOLFSSL* ssl) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + return ssl->options.side == WOLFSSL_SERVER_END; +} + +#ifdef HAVE_WRITE_DUP + +/* + * Release resources around WriteDup object + * + * ssl WOLFSSL object + * + * no return, destruction so make best attempt +*/ +void FreeWriteDup(WOLFSSL* ssl) +{ + int doFree = 0; + + WOLFSSL_ENTER("FreeWriteDup"); + + if (ssl->dupWrite) { + if (wc_LockMutex(&ssl->dupWrite->dupMutex) == 0) { + ssl->dupWrite->dupCount--; + if (ssl->dupWrite->dupCount == 0) { + doFree = 1; + } else { + WOLFSSL_MSG("WriteDup count not zero, no full free"); + } + wc_UnLockMutex(&ssl->dupWrite->dupMutex); + } + } + + if (doFree) { + WOLFSSL_MSG("Doing WriteDup full free, count to zero"); + wc_FreeMutex(&ssl->dupWrite->dupMutex); + XFREE(ssl->dupWrite, ssl->heap, DYNAMIC_TYPE_WRITEDUP); + } +} + + +/* + * duplicate existing ssl members into dup needed for writing + * + * dup write only WOLFSSL + * ssl exisiting WOLFSSL + * + * 0 on success +*/ +static int DupSSL(WOLFSSL* dup, WOLFSSL* ssl) +{ + /* shared dupWrite setup */ + ssl->dupWrite = (WriteDup*)XMALLOC(sizeof(WriteDup), ssl->heap, + DYNAMIC_TYPE_WRITEDUP); + if (ssl->dupWrite == NULL) { + return MEMORY_E; + } + XMEMSET(ssl->dupWrite, 0, sizeof(WriteDup)); + + if (wc_InitMutex(&ssl->dupWrite->dupMutex) != 0) { + XFREE(ssl->dupWrite, ssl->heap, DYNAMIC_TYPE_WRITEDUP); + ssl->dupWrite = NULL; + return BAD_MUTEX_E; + } + ssl->dupWrite->dupCount = 2; /* both sides have a count to start */ + dup->dupWrite = ssl->dupWrite; /* each side uses */ + + /* copy write parts over to dup writer */ + XMEMCPY(&dup->specs, &ssl->specs, sizeof(CipherSpecs)); + XMEMCPY(&dup->options, &ssl->options, sizeof(Options)); + XMEMCPY(&dup->keys, &ssl->keys, sizeof(Keys)); + XMEMCPY(&dup->encrypt, &ssl->encrypt, sizeof(Ciphers)); + /* dup side now owns encrypt/write ciphers */ + XMEMSET(&ssl->encrypt, 0, sizeof(Ciphers)); + + dup->IOCB_WriteCtx = ssl->IOCB_WriteCtx; + dup->wfd = ssl->wfd; + dup->wflags = ssl->wflags; + dup->hmac = ssl->hmac; +#ifdef HAVE_TRUNCATED_HMAC + dup->truncated_hmac = ssl->truncated_hmac; +#endif + + /* unique side dup setup */ + dup->dupSide = WRITE_DUP_SIDE; + ssl->dupSide = READ_DUP_SIDE; + + return 0; +} + + +/* + * duplicate a WOLFSSL object post handshake for writing only + * turn exisitng object into read only. Allows concurrent access from two + * different threads. + * + * ssl exisiting WOLFSSL object + * + * return dup'd WOLFSSL object on success +*/ +WOLFSSL* wolfSSL_write_dup(WOLFSSL* ssl) +{ + WOLFSSL* dup = NULL; + int ret = 0; + + (void)ret; + WOLFSSL_ENTER("wolfSSL_write_dup"); + + if (ssl == NULL) { + return ssl; + } + + if (ssl->options.handShakeDone == 0) { + WOLFSSL_MSG("wolfSSL_write_dup called before handshake complete"); + return NULL; + } + + if (ssl->dupWrite) { + WOLFSSL_MSG("wolfSSL_write_dup already called once"); + return NULL; + } + + dup = (WOLFSSL*) XMALLOC(sizeof(WOLFSSL), ssl->ctx->heap, DYNAMIC_TYPE_SSL); + if (dup) { + if ( (ret = InitSSL(dup, ssl->ctx, 1)) < 0) { + FreeSSL(dup, ssl->ctx->heap); + dup = NULL; + } else if ( (ret = DupSSL(dup, ssl) < 0)) { + FreeSSL(dup, ssl->ctx->heap); + dup = NULL; + } + } + + WOLFSSL_LEAVE("wolfSSL_write_dup", ret); + + return dup; +} + + +/* + * Notify write dup side of fatal error or close notify + * + * ssl WOLFSSL object + * err Notify err + * + * 0 on success +*/ +int NotifyWriteSide(WOLFSSL* ssl, int err) +{ + int ret; + + WOLFSSL_ENTER("NotifyWriteSide"); + + ret = wc_LockMutex(&ssl->dupWrite->dupMutex); + if (ret == 0) { + ssl->dupWrite->dupErr = err; + ret = wc_UnLockMutex(&ssl->dupWrite->dupMutex); + } + + return ret; +} + + +#endif /* HAVE_WRITE_DUP */ + + +#ifdef HAVE_POLY1305 +/* set if to use old poly 1 for yes 0 to use new poly */ +int wolfSSL_use_old_poly(WOLFSSL* ssl, int value) +{ + (void)ssl; + (void)value; + +#ifndef WOLFSSL_NO_TLS12 + WOLFSSL_ENTER("SSL_use_old_poly"); + WOLFSSL_MSG("Warning SSL connection auto detects old/new and this function" + "is depreciated"); + ssl->options.oldPoly = (word16)value; + WOLFSSL_LEAVE("SSL_use_old_poly", 0); +#endif + return 0; +} +#endif + + +int wolfSSL_set_fd(WOLFSSL* ssl, int fd) +{ + int ret; + + WOLFSSL_ENTER("SSL_set_fd"); + + if (ssl == NULL) { + return BAD_FUNC_ARG; + } + + ret = wolfSSL_set_read_fd(ssl, fd); + if (ret == WOLFSSL_SUCCESS) { + ret = wolfSSL_set_write_fd(ssl, fd); + } + + return ret; +} + + +int wolfSSL_set_read_fd(WOLFSSL* ssl, int fd) +{ + WOLFSSL_ENTER("SSL_set_read_fd"); + + if (ssl == NULL) { + return BAD_FUNC_ARG; + } + + ssl->rfd = fd; /* not used directly to allow IO callbacks */ + ssl->IOCB_ReadCtx = &ssl->rfd; + + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + ssl->IOCB_ReadCtx = &ssl->buffers.dtlsCtx; + ssl->buffers.dtlsCtx.rfd = fd; + } + #endif + + WOLFSSL_LEAVE("SSL_set_read_fd", WOLFSSL_SUCCESS); + return WOLFSSL_SUCCESS; +} + + +int wolfSSL_set_write_fd(WOLFSSL* ssl, int fd) +{ + WOLFSSL_ENTER("SSL_set_write_fd"); + + if (ssl == NULL) { + return BAD_FUNC_ARG; + } + + ssl->wfd = fd; /* not used directly to allow IO callbacks */ + ssl->IOCB_WriteCtx = &ssl->wfd; + + #ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + ssl->IOCB_WriteCtx = &ssl->buffers.dtlsCtx; + ssl->buffers.dtlsCtx.wfd = fd; + } + #endif + + WOLFSSL_LEAVE("SSL_set_write_fd", WOLFSSL_SUCCESS); + return WOLFSSL_SUCCESS; +} + + +/** + * Get the name of cipher at priority level passed in. + */ +char* wolfSSL_get_cipher_list(int priority) +{ + const CipherSuiteInfo* ciphers = GetCipherNames(); + + if (priority >= GetCipherNamesSize() || priority < 0) { + return 0; + } + + return (char*)ciphers[priority].name; +} + + +/** + * Get the name of cipher at priority level passed in. + */ +char* wolfSSL_get_cipher_list_ex(WOLFSSL* ssl, int priority) +{ + + if (ssl == NULL) { + return NULL; + } + else { + const char* cipher; + + if ((cipher = wolfSSL_get_cipher_name_internal(ssl)) != NULL) { + if (priority == 0) { + return (char*)cipher; + } + else { + return NULL; + } + } + else { + return wolfSSL_get_cipher_list(priority); + } + } +} + + +int wolfSSL_get_ciphers(char* buf, int len) +{ + const CipherSuiteInfo* ciphers = GetCipherNames(); + int ciphersSz = GetCipherNamesSize(); + int i; + int cipherNameSz; + + if (buf == NULL || len <= 0) + return BAD_FUNC_ARG; + + /* Add each member to the buffer delimited by a : */ + for (i = 0; i < ciphersSz; i++) { + cipherNameSz = (int)XSTRLEN(ciphers[i].name); + if (cipherNameSz + 1 < len) { + XSTRNCPY(buf, ciphers[i].name, len); + buf += cipherNameSz; + + if (i < ciphersSz - 1) + *buf++ = ':'; + *buf = 0; + + len -= cipherNameSz + 1; + } + else + return BUFFER_E; + } + return WOLFSSL_SUCCESS; +} + + +#ifndef NO_ERROR_STRINGS +/* places a list of all supported cipher suites in TLS_* format into "buf" + * return WOLFSSL_SUCCESS on success */ +int wolfSSL_get_ciphers_iana(char* buf, int len) +{ + const CipherSuiteInfo* ciphers = GetCipherNames(); + int ciphersSz = GetCipherNamesSize(); + int i; + int cipherNameSz; + + if (buf == NULL || len <= 0) + return BAD_FUNC_ARG; + + /* Add each member to the buffer delimited by a : */ + for (i = 0; i < ciphersSz; i++) { + cipherNameSz = (int)XSTRLEN(ciphers[i].name_iana); + if (cipherNameSz + 1 < len) { + XSTRNCPY(buf, ciphers[i].name_iana, len); + buf += cipherNameSz; + + if (i < ciphersSz - 1) + *buf++ = ':'; + *buf = 0; + + len -= cipherNameSz + 1; + } + else + return BUFFER_E; + } + return WOLFSSL_SUCCESS; +} +#endif /* NO_ERROR_STRINGS */ + + +const char* wolfSSL_get_shared_ciphers(WOLFSSL* ssl, char* buf, int len) +{ + const char* cipher; + + if (ssl == NULL) + return NULL; + + cipher = wolfSSL_get_cipher_name_iana(ssl); + len = min(len, (int)(XSTRLEN(cipher) + 1)); + XMEMCPY(buf, cipher, len); + return buf; +} + +int wolfSSL_get_fd(const WOLFSSL* ssl) +{ + int fd = -1; + WOLFSSL_ENTER("SSL_get_fd"); + if (ssl) { + fd = ssl->rfd; + } + WOLFSSL_LEAVE("SSL_get_fd", fd); + return fd; +} + + +int wolfSSL_dtls(WOLFSSL* ssl) +{ + int dtlsOpt = 0; + if (ssl) + dtlsOpt = ssl->options.dtls; + return dtlsOpt; +} + + +#ifndef WOLFSSL_LEANPSK +int wolfSSL_dtls_set_peer(WOLFSSL* ssl, void* peer, unsigned int peerSz) +{ +#ifdef WOLFSSL_DTLS + void* sa; + + if (ssl == NULL) + return WOLFSSL_FAILURE; + + sa = (void*)XMALLOC(peerSz, ssl->heap, DYNAMIC_TYPE_SOCKADDR); + if (sa != NULL) { + if (ssl->buffers.dtlsCtx.peer.sa != NULL) { + XFREE(ssl->buffers.dtlsCtx.peer.sa,ssl->heap,DYNAMIC_TYPE_SOCKADDR); + ssl->buffers.dtlsCtx.peer.sa = NULL; + } + XMEMCPY(sa, peer, peerSz); + ssl->buffers.dtlsCtx.peer.sa = sa; + ssl->buffers.dtlsCtx.peer.sz = peerSz; + return WOLFSSL_SUCCESS; + } + return WOLFSSL_FAILURE; +#else + (void)ssl; + (void)peer; + (void)peerSz; + return WOLFSSL_NOT_IMPLEMENTED; +#endif +} + +int wolfSSL_dtls_get_peer(WOLFSSL* ssl, void* peer, unsigned int* peerSz) +{ +#ifdef WOLFSSL_DTLS + if (ssl == NULL) { + return WOLFSSL_FAILURE; + } + + if (peer != NULL && peerSz != NULL + && *peerSz >= ssl->buffers.dtlsCtx.peer.sz + && ssl->buffers.dtlsCtx.peer.sa != NULL) { + *peerSz = ssl->buffers.dtlsCtx.peer.sz; + XMEMCPY(peer, ssl->buffers.dtlsCtx.peer.sa, *peerSz); + return WOLFSSL_SUCCESS; + } + return WOLFSSL_FAILURE; +#else + (void)ssl; + (void)peer; + (void)peerSz; + return WOLFSSL_NOT_IMPLEMENTED; +#endif +} + + +#if defined(WOLFSSL_SCTP) && defined(WOLFSSL_DTLS) + +int wolfSSL_CTX_dtls_set_sctp(WOLFSSL_CTX* ctx) +{ + WOLFSSL_ENTER("wolfSSL_CTX_dtls_set_sctp()"); + + if (ctx == NULL) + return BAD_FUNC_ARG; + + ctx->dtlsSctp = 1; + return WOLFSSL_SUCCESS; +} + + +int wolfSSL_dtls_set_sctp(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_dtls_set_sctp()"); + + if (ssl == NULL) + return BAD_FUNC_ARG; + + ssl->options.dtlsSctp = 1; + return WOLFSSL_SUCCESS; +} + + +int wolfSSL_CTX_dtls_set_mtu(WOLFSSL_CTX* ctx, word16 newMtu) +{ + if (ctx == NULL || newMtu > MAX_RECORD_SIZE) + return BAD_FUNC_ARG; + + ctx->dtlsMtuSz = newMtu; + return WOLFSSL_SUCCESS; +} + + +int wolfSSL_dtls_set_mtu(WOLFSSL* ssl, word16 newMtu) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + + if (newMtu > MAX_RECORD_SIZE) { + ssl->error = BAD_FUNC_ARG; + return WOLFSSL_FAILURE; + } + + ssl->dtlsMtuSz = newMtu; + return WOLFSSL_SUCCESS; +} + + +#endif /* WOLFSSL_DTLS && WOLFSSL_SCTP */ + + +#ifdef WOLFSSL_DTLS_DROP_STATS + +int wolfSSL_dtls_get_drop_stats(WOLFSSL* ssl, + word32* macDropCount, word32* replayDropCount) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_dtls_get_drop_stats()"); + + if (ssl == NULL) + ret = BAD_FUNC_ARG; + else { + ret = WOLFSSL_SUCCESS; + if (macDropCount != NULL) + *macDropCount = ssl->macDropCount; + if (replayDropCount != NULL) + *replayDropCount = ssl->replayDropCount; + } + + WOLFSSL_LEAVE("wolfSSL_dtls_get_drop_stats()", ret); + return ret; +} + +#endif /* WOLFSSL_DTLS_DROP_STATS */ + + +#if defined(WOLFSSL_MULTICAST) + +int wolfSSL_CTX_mcast_set_member_id(WOLFSSL_CTX* ctx, word16 id) +{ + int ret = 0; + + WOLFSSL_ENTER("wolfSSL_CTX_mcast_set_member_id()"); + + if (ctx == NULL || id > 255) + ret = BAD_FUNC_ARG; + + if (ret == 0) { + ctx->haveEMS = 0; + ctx->haveMcast = 1; + ctx->mcastID = id; +#ifndef WOLFSSL_USER_IO + ctx->CBIORecv = EmbedReceiveFromMcast; +#endif /* WOLFSSL_USER_IO */ + } + + if (ret == 0) + ret = WOLFSSL_SUCCESS; + WOLFSSL_LEAVE("wolfSSL_CTX_mcast_set_member_id()", ret); + return ret; +} + +int wolfSSL_mcast_get_max_peers(void) +{ + return WOLFSSL_MULTICAST_PEERS; +} + +#ifdef WOLFSSL_DTLS +static WC_INLINE word32 UpdateHighwaterMark(word32 cur, word32 first, + word32 second, word32 max) +{ + word32 newCur = 0; + + if (cur < first) + newCur = first; + else if (cur < second) + newCur = second; + else if (cur < max) + newCur = max; + + return newCur; +} +#endif /* WOLFSSL_DTLS */ + + +int wolfSSL_set_secret(WOLFSSL* ssl, word16 epoch, + const byte* preMasterSecret, word32 preMasterSz, + const byte* clientRandom, const byte* serverRandom, + const byte* suite) +{ + int ret = 0; + + WOLFSSL_ENTER("wolfSSL_set_secret()"); + + if (ssl == NULL || preMasterSecret == NULL || + preMasterSz == 0 || preMasterSz > ENCRYPT_LEN || + clientRandom == NULL || serverRandom == NULL || suite == NULL) { + + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + XMEMCPY(ssl->arrays->preMasterSecret, preMasterSecret, preMasterSz); + ssl->arrays->preMasterSz = preMasterSz; + XMEMCPY(ssl->arrays->clientRandom, clientRandom, RAN_LEN); + XMEMCPY(ssl->arrays->serverRandom, serverRandom, RAN_LEN); + ssl->options.cipherSuite0 = suite[0]; + ssl->options.cipherSuite = suite[1]; + + ret = SetCipherSpecs(ssl); + } + + if (ret == 0) + ret = MakeTlsMasterSecret(ssl); + + if (ret == 0) { + ssl->keys.encryptionOn = 1; + ret = SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE); + } + + if (ret == 0) { + if (ssl->options.dtls) { + #ifdef WOLFSSL_DTLS + WOLFSSL_DTLS_PEERSEQ* peerSeq; + int i; + + ssl->keys.dtls_epoch = epoch; + for (i = 0, peerSeq = ssl->keys.peerSeq; + i < WOLFSSL_DTLS_PEERSEQ_SZ; + i++, peerSeq++) { + + peerSeq->nextEpoch = epoch; + peerSeq->prevSeq_lo = peerSeq->nextSeq_lo; + peerSeq->prevSeq_hi = peerSeq->nextSeq_hi; + peerSeq->nextSeq_lo = 0; + peerSeq->nextSeq_hi = 0; + XMEMCPY(peerSeq->prevWindow, peerSeq->window, DTLS_SEQ_SZ); + XMEMSET(peerSeq->window, 0, DTLS_SEQ_SZ); + peerSeq->highwaterMark = UpdateHighwaterMark(0, + ssl->ctx->mcastFirstSeq, + ssl->ctx->mcastSecondSeq, + ssl->ctx->mcastMaxSeq); + } + #else + (void)epoch; + #endif + } + FreeHandshakeResources(ssl); + ret = WOLFSSL_SUCCESS; + } + else { + if (ssl) + ssl->error = ret; + ret = WOLFSSL_FATAL_ERROR; + } + WOLFSSL_LEAVE("wolfSSL_set_secret()", ret); + return ret; +} + + +#ifdef WOLFSSL_DTLS + +int wolfSSL_mcast_peer_add(WOLFSSL* ssl, word16 peerId, int remove) +{ + WOLFSSL_DTLS_PEERSEQ* p = NULL; + int ret = WOLFSSL_SUCCESS; + int i; + + WOLFSSL_ENTER("wolfSSL_mcast_peer_add()"); + if (ssl == NULL || peerId > 255) + return BAD_FUNC_ARG; + + if (!remove) { + /* Make sure it isn't already present, while keeping the first + * open spot. */ + for (i = 0; i < WOLFSSL_DTLS_PEERSEQ_SZ; i++) { + if (ssl->keys.peerSeq[i].peerId == INVALID_PEER_ID) + p = &ssl->keys.peerSeq[i]; + if (ssl->keys.peerSeq[i].peerId == peerId) { + WOLFSSL_MSG("Peer ID already in multicast peer list."); + p = NULL; + } + } + + if (p != NULL) { + XMEMSET(p, 0, sizeof(WOLFSSL_DTLS_PEERSEQ)); + p->peerId = peerId; + p->highwaterMark = UpdateHighwaterMark(0, + ssl->ctx->mcastFirstSeq, + ssl->ctx->mcastSecondSeq, + ssl->ctx->mcastMaxSeq); + } + else { + WOLFSSL_MSG("No room in peer list."); + ret = -1; + } + } + else { + for (i = 0; i < WOLFSSL_DTLS_PEERSEQ_SZ; i++) { + if (ssl->keys.peerSeq[i].peerId == peerId) + p = &ssl->keys.peerSeq[i]; + } + + if (p != NULL) { + p->peerId = INVALID_PEER_ID; + } + else { + WOLFSSL_MSG("Peer not found in list."); + } + } + + WOLFSSL_LEAVE("wolfSSL_mcast_peer_add()", ret); + return ret; +} + + +/* If peerId is in the list of peers and its last sequence number is non-zero, + * return 1, otherwise return 0. */ +int wolfSSL_mcast_peer_known(WOLFSSL* ssl, unsigned short peerId) +{ + int known = 0; + int i; + + WOLFSSL_ENTER("wolfSSL_mcast_peer_known()"); + + if (ssl == NULL || peerId > 255) { + return BAD_FUNC_ARG; + } + + for (i = 0; i < WOLFSSL_DTLS_PEERSEQ_SZ; i++) { + if (ssl->keys.peerSeq[i].peerId == peerId) { + if (ssl->keys.peerSeq[i].nextSeq_hi || + ssl->keys.peerSeq[i].nextSeq_lo) { + + known = 1; + } + break; + } + } + + WOLFSSL_LEAVE("wolfSSL_mcast_peer_known()", known); + return known; +} + + +int wolfSSL_CTX_mcast_set_highwater_cb(WOLFSSL_CTX* ctx, word32 maxSeq, + word32 first, word32 second, + CallbackMcastHighwater cb) +{ + if (ctx == NULL || (second && first > second) || + first > maxSeq || second > maxSeq || cb == NULL) { + + return BAD_FUNC_ARG; + } + + ctx->mcastHwCb = cb; + ctx->mcastFirstSeq = first; + ctx->mcastSecondSeq = second; + ctx->mcastMaxSeq = maxSeq; + + return WOLFSSL_SUCCESS; +} + + +int wolfSSL_mcast_set_highwater_ctx(WOLFSSL* ssl, void* ctx) +{ + if (ssl == NULL || ctx == NULL) + return BAD_FUNC_ARG; + + ssl->mcastHwCbCtx = ctx; + + return WOLFSSL_SUCCESS; +} + +#endif /* WOLFSSL_DTLS */ + +#endif /* WOLFSSL_MULTICAST */ + + +#endif /* WOLFSSL_LEANPSK */ + + +/* return underlying connect or accept, WOLFSSL_SUCCESS on ok */ +int wolfSSL_negotiate(WOLFSSL* ssl) +{ + int err = WOLFSSL_FATAL_ERROR; + + WOLFSSL_ENTER("wolfSSL_negotiate"); +#ifndef NO_WOLFSSL_SERVER + if (ssl->options.side == WOLFSSL_SERVER_END) { +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version)) + err = wolfSSL_accept_TLSv13(ssl); + else +#endif + err = wolfSSL_accept(ssl); + } +#endif + +#ifndef NO_WOLFSSL_CLIENT + if (ssl->options.side == WOLFSSL_CLIENT_END) { +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version)) + err = wolfSSL_connect_TLSv13(ssl); + else +#endif + err = wolfSSL_connect(ssl); + } +#endif + + (void)ssl; + + WOLFSSL_LEAVE("wolfSSL_negotiate", err); + + return err; +} + + +WC_RNG* wolfSSL_GetRNG(WOLFSSL* ssl) +{ + if (ssl) { + return ssl->rng; + } + + return NULL; +} + + +#ifndef WOLFSSL_LEANPSK +/* object size based on build */ +int wolfSSL_GetObjectSize(void) +{ +#ifdef SHOW_SIZES + printf("sizeof suites = %lu\n", sizeof(Suites)); + printf("sizeof ciphers(2) = %lu\n", sizeof(Ciphers)); +#ifndef NO_RC4 + printf("\tsizeof arc4 = %lu\n", sizeof(Arc4)); +#endif + printf("\tsizeof aes = %lu\n", sizeof(Aes)); +#ifndef NO_DES3 + printf("\tsizeof des3 = %lu\n", sizeof(Des3)); +#endif +#ifndef NO_RABBIT + printf("\tsizeof rabbit = %lu\n", sizeof(Rabbit)); +#endif +#ifdef HAVE_CHACHA + printf("\tsizeof chacha = %lu\n", sizeof(ChaCha)); +#endif + printf("sizeof cipher specs = %lu\n", sizeof(CipherSpecs)); + printf("sizeof keys = %lu\n", sizeof(Keys)); + printf("sizeof Hashes(2) = %lu\n", sizeof(Hashes)); +#ifndef NO_MD5 + printf("\tsizeof MD5 = %lu\n", sizeof(wc_Md5)); +#endif +#ifndef NO_SHA + printf("\tsizeof SHA = %lu\n", sizeof(wc_Sha)); +#endif +#ifdef WOLFSSL_SHA224 + printf("\tsizeof SHA224 = %lu\n", sizeof(wc_Sha224)); +#endif +#ifndef NO_SHA256 + printf("\tsizeof SHA256 = %lu\n", sizeof(wc_Sha256)); +#endif +#ifdef WOLFSSL_SHA384 + printf("\tsizeof SHA384 = %lu\n", sizeof(wc_Sha384)); +#endif +#ifdef WOLFSSL_SHA384 + printf("\tsizeof SHA512 = %lu\n", sizeof(wc_Sha512)); +#endif + printf("sizeof Buffers = %lu\n", sizeof(Buffers)); + printf("sizeof Options = %lu\n", sizeof(Options)); + printf("sizeof Arrays = %lu\n", sizeof(Arrays)); +#ifndef NO_RSA + printf("sizeof RsaKey = %lu\n", sizeof(RsaKey)); +#endif +#ifdef HAVE_ECC + printf("sizeof ecc_key = %lu\n", sizeof(ecc_key)); +#endif + printf("sizeof WOLFSSL_CIPHER = %lu\n", sizeof(WOLFSSL_CIPHER)); + printf("sizeof WOLFSSL_SESSION = %lu\n", sizeof(WOLFSSL_SESSION)); + printf("sizeof WOLFSSL = %lu\n", sizeof(WOLFSSL)); + printf("sizeof WOLFSSL_CTX = %lu\n", sizeof(WOLFSSL_CTX)); +#endif + + return sizeof(WOLFSSL); +} + +int wolfSSL_CTX_GetObjectSize(void) +{ + return sizeof(WOLFSSL_CTX); +} + +int wolfSSL_METHOD_GetObjectSize(void) +{ + return sizeof(WOLFSSL_METHOD); +} +#endif + + +#ifdef WOLFSSL_STATIC_MEMORY + +int wolfSSL_CTX_load_static_memory(WOLFSSL_CTX** ctx, wolfSSL_method_func method, + unsigned char* buf, unsigned int sz, + int flag, int max) +{ + WOLFSSL_HEAP* heap; + WOLFSSL_HEAP_HINT* hint; + word32 idx = 0; + + if (ctx == NULL || buf == NULL) { + return BAD_FUNC_ARG; + } + + if (*ctx == NULL && method == NULL) { + return BAD_FUNC_ARG; + } + + if (*ctx == NULL || (*ctx)->heap == NULL) { + if (sizeof(WOLFSSL_HEAP) + sizeof(WOLFSSL_HEAP_HINT) > sz - idx) { + return BUFFER_E; /* not enough memory for structures */ + } + heap = (WOLFSSL_HEAP*)buf; + idx += sizeof(WOLFSSL_HEAP); + if (wolfSSL_init_memory_heap(heap) != 0) { + return WOLFSSL_FAILURE; + } + hint = (WOLFSSL_HEAP_HINT*)(buf + idx); + idx += sizeof(WOLFSSL_HEAP_HINT); + XMEMSET(hint, 0, sizeof(WOLFSSL_HEAP_HINT)); + hint->memory = heap; + + if (*ctx && (*ctx)->heap == NULL) { + (*ctx)->heap = (void*)hint; + } + } + else { +#ifdef WOLFSSL_HEAP_TEST + /* do not load in memory if test has been set */ + if ((*ctx)->heap == (void*)WOLFSSL_HEAP_TEST) { + return WOLFSSL_SUCCESS; + } +#endif + hint = (WOLFSSL_HEAP_HINT*)((*ctx)->heap); + heap = hint->memory; + } + + if (wolfSSL_load_static_memory(buf + idx, sz - idx, flag, heap) != 1) { + WOLFSSL_MSG("Error partitioning memory"); + return WOLFSSL_FAILURE; + } + + /* create ctx if needed */ + if (*ctx == NULL) { + *ctx = wolfSSL_CTX_new_ex(method(hint), hint); + if (*ctx == NULL) { + WOLFSSL_MSG("Error creating ctx"); + return WOLFSSL_FAILURE; + } + } + + /* determine what max applies too */ + if (flag & WOLFMEM_IO_POOL || flag & WOLFMEM_IO_POOL_FIXED) { + heap->maxIO = max; + } + else { /* general memory used in handshakes */ + heap->maxHa = max; + } + + heap->flag |= flag; + + (void)max; + (void)method; + + return WOLFSSL_SUCCESS; +} + + +int wolfSSL_is_static_memory(WOLFSSL* ssl, WOLFSSL_MEM_CONN_STATS* mem_stats) +{ + if (ssl == NULL) { + return BAD_FUNC_ARG; + } + WOLFSSL_ENTER("wolfSSL_is_static_memory"); + + /* fill out statistics if wanted and WOLFMEM_TRACK_STATS flag */ + if (mem_stats != NULL && ssl->heap != NULL) { + WOLFSSL_HEAP_HINT* hint = ((WOLFSSL_HEAP_HINT*)(ssl->heap)); + WOLFSSL_HEAP* heap = hint->memory; + if (heap->flag & WOLFMEM_TRACK_STATS && hint->stats != NULL) { + XMEMCPY(mem_stats, hint->stats, sizeof(WOLFSSL_MEM_CONN_STATS)); + } + } + + return (ssl->heap) ? 1 : 0; +} + + +int wolfSSL_CTX_is_static_memory(WOLFSSL_CTX* ctx, WOLFSSL_MEM_STATS* mem_stats) +{ + if (ctx == NULL) { + return BAD_FUNC_ARG; + } + WOLFSSL_ENTER("wolfSSL_CTX_is_static_memory"); + + /* fill out statistics if wanted */ + if (mem_stats != NULL && ctx->heap != NULL) { + WOLFSSL_HEAP* heap = ((WOLFSSL_HEAP_HINT*)(ctx->heap))->memory; + if (wolfSSL_GetMemStats(heap, mem_stats) != 1) { + return MEMORY_E; + } + } + + return (ctx->heap) ? 1 : 0; +} + +#endif /* WOLFSSL_STATIC_MEMORY */ + + +/* return max record layer size plaintext input size */ +int wolfSSL_GetMaxOutputSize(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_GetMaxOutputSize"); + + if (ssl == NULL) + return BAD_FUNC_ARG; + + if (ssl->options.handShakeState != HANDSHAKE_DONE) { + WOLFSSL_MSG("Handshake not complete yet"); + return BAD_FUNC_ARG; + } + + return wolfSSL_GetMaxRecordSize(ssl, OUTPUT_RECORD_SIZE); +} + + +/* return record layer size of plaintext input size */ +int wolfSSL_GetOutputSize(WOLFSSL* ssl, int inSz) +{ + int maxSize; + + WOLFSSL_ENTER("wolfSSL_GetOutputSize"); + + if (inSz < 0) + return BAD_FUNC_ARG; + + maxSize = wolfSSL_GetMaxOutputSize(ssl); + if (maxSize < 0) + return maxSize; /* error */ + if (inSz > maxSize) + return INPUT_SIZE_E; + + return BuildMessage(ssl, NULL, 0, NULL, inSz, application_data, 0, 1, 0); +} + + +#ifdef HAVE_ECC +int wolfSSL_CTX_SetMinEccKey_Sz(WOLFSSL_CTX* ctx, short keySz) +{ + if (ctx == NULL || keySz < 0 || keySz % 8 != 0) { + WOLFSSL_MSG("Key size must be divisible by 8 or ctx was null"); + return BAD_FUNC_ARG; + } + + ctx->minEccKeySz = keySz / 8; +#ifndef NO_CERTS + ctx->cm->minEccKeySz = keySz / 8; +#endif + return WOLFSSL_SUCCESS; +} + + +int wolfSSL_SetMinEccKey_Sz(WOLFSSL* ssl, short keySz) +{ + if (ssl == NULL || keySz < 0 || keySz % 8 != 0) { + WOLFSSL_MSG("Key size must be divisible by 8 or ssl was null"); + return BAD_FUNC_ARG; + } + + ssl->options.minEccKeySz = keySz / 8; + return WOLFSSL_SUCCESS; +} + +#endif /* !NO_RSA */ + +#ifndef NO_RSA +int wolfSSL_CTX_SetMinRsaKey_Sz(WOLFSSL_CTX* ctx, short keySz) +{ + if (ctx == NULL || keySz < 0 || keySz % 8 != 0) { + WOLFSSL_MSG("Key size must be divisible by 8 or ctx was null"); + return BAD_FUNC_ARG; + } + + ctx->minRsaKeySz = keySz / 8; + ctx->cm->minRsaKeySz = keySz / 8; + return WOLFSSL_SUCCESS; +} + + +int wolfSSL_SetMinRsaKey_Sz(WOLFSSL* ssl, short keySz) +{ + if (ssl == NULL || keySz < 0 || keySz % 8 != 0) { + WOLFSSL_MSG("Key size must be divisible by 8 or ssl was null"); + return BAD_FUNC_ARG; + } + + ssl->options.minRsaKeySz = keySz / 8; + return WOLFSSL_SUCCESS; +} +#endif /* !NO_RSA */ + +#ifndef NO_DH +/* server Diffie-Hellman parameters, WOLFSSL_SUCCESS on ok */ +int wolfSSL_SetTmpDH(WOLFSSL* ssl, const unsigned char* p, int pSz, + const unsigned char* g, int gSz) +{ + WOLFSSL_ENTER("wolfSSL_SetTmpDH"); + + if (ssl == NULL || p == NULL || g == NULL) + return BAD_FUNC_ARG; + + if ((word16)pSz < ssl->options.minDhKeySz) + return DH_KEY_SIZE_E; + if ((word16)pSz > ssl->options.maxDhKeySz) + return DH_KEY_SIZE_E; + + /* this function is for server only */ + if (ssl->options.side == WOLFSSL_CLIENT_END) + return SIDE_ERROR; + + #if !defined(WOLFSSL_OLD_PRIME_CHECK) && !defined(HAVE_FIPS) && \ + !defined(HAVE_SELFTEST) + ssl->options.dhKeyTested = 0; + ssl->options.dhDoKeyTest = 1; + #endif + + if (ssl->buffers.serverDH_P.buffer && ssl->buffers.weOwnDH) { + XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + ssl->buffers.serverDH_P.buffer = NULL; + } + if (ssl->buffers.serverDH_G.buffer && ssl->buffers.weOwnDH) { + XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + ssl->buffers.serverDH_G.buffer = NULL; + } + + ssl->buffers.weOwnDH = 1; /* SSL owns now */ + ssl->buffers.serverDH_P.buffer = (byte*)XMALLOC(pSz, ssl->heap, + DYNAMIC_TYPE_PUBLIC_KEY); + if (ssl->buffers.serverDH_P.buffer == NULL) + return MEMORY_E; + + ssl->buffers.serverDH_G.buffer = (byte*)XMALLOC(gSz, ssl->heap, + DYNAMIC_TYPE_PUBLIC_KEY); + if (ssl->buffers.serverDH_G.buffer == NULL) { + XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + ssl->buffers.serverDH_P.buffer = NULL; + return MEMORY_E; + } + + ssl->buffers.serverDH_P.length = pSz; + ssl->buffers.serverDH_G.length = gSz; + + XMEMCPY(ssl->buffers.serverDH_P.buffer, p, pSz); + XMEMCPY(ssl->buffers.serverDH_G.buffer, g, gSz); + + ssl->options.haveDH = 1; + + if (ssl->options.side != WOLFSSL_NEITHER_END) { + word16 havePSK = 0; + word16 haveRSA = 1; + int keySz = 0; + + #ifndef NO_PSK + havePSK = ssl->options.havePSK; + #endif + #ifdef NO_RSA + haveRSA = 0; + #endif + #ifndef NO_CERTS + keySz = ssl->buffers.keySz; + #endif + InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK, + ssl->options.haveDH, ssl->options.haveNTRU, + ssl->options.haveECDSAsig, ssl->options.haveECC, + ssl->options.haveStaticECC, ssl->options.side); + } + + WOLFSSL_LEAVE("wolfSSL_SetTmpDH", 0); + + return WOLFSSL_SUCCESS; +} + + +#if !defined(WOLFSSL_OLD_PRIME_CHECK) && !defined(HAVE_FIPS) && \ + !defined(HAVE_SELFTEST) +/* Enables or disables the session's DH key prime test. */ +int wolfSSL_SetEnableDhKeyTest(WOLFSSL* ssl, int enable) +{ + WOLFSSL_ENTER("wolfSSL_SetEnableDhKeyTest"); + + if (ssl == NULL) + return BAD_FUNC_ARG; + + if (!enable) + ssl->options.dhDoKeyTest = 0; + else + ssl->options.dhDoKeyTest = 1; + + WOLFSSL_LEAVE("wolfSSL_SetEnableDhKeyTest", WOLFSSL_SUCCESS); + return WOLFSSL_SUCCESS; +} +#endif + + +/* server ctx Diffie-Hellman parameters, WOLFSSL_SUCCESS on ok */ +int wolfSSL_CTX_SetTmpDH(WOLFSSL_CTX* ctx, const unsigned char* p, int pSz, + const unsigned char* g, int gSz) +{ + WOLFSSL_ENTER("wolfSSL_CTX_SetTmpDH"); + if (ctx == NULL || p == NULL || g == NULL) return BAD_FUNC_ARG; + + if ((word16)pSz < ctx->minDhKeySz) + return DH_KEY_SIZE_E; + if ((word16)pSz > ctx->maxDhKeySz) + return DH_KEY_SIZE_E; + + #if !defined(WOLFSSL_OLD_PRIME_CHECK) && !defined(HAVE_FIPS) && \ + !defined(HAVE_SELFTEST) + { + DhKey checkKey; + WC_RNG rng; + int error, freeKey = 0; + + error = wc_InitRng(&rng); + if (!error) + error = wc_InitDhKey(&checkKey); + if (!error) { + freeKey = 1; + error = wc_DhSetCheckKey(&checkKey, + p, pSz, g, gSz, NULL, 0, 0, &rng); + } + if (freeKey) + wc_FreeDhKey(&checkKey); + wc_FreeRng(&rng); + if (error) + return error; + + ctx->dhKeyTested = 1; + } + #endif + + XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); + ctx->serverDH_P.buffer = NULL; + XFREE(ctx->serverDH_G.buffer, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); + ctx->serverDH_G.buffer = NULL; + + ctx->serverDH_P.buffer = (byte*)XMALLOC(pSz, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); + if (ctx->serverDH_P.buffer == NULL) + return MEMORY_E; + + ctx->serverDH_G.buffer = (byte*)XMALLOC(gSz, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); + if (ctx->serverDH_G.buffer == NULL) { + XFREE(ctx->serverDH_P.buffer, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); + ctx->serverDH_P.buffer = NULL; + return MEMORY_E; + } + + ctx->serverDH_P.length = pSz; + ctx->serverDH_G.length = gSz; + + XMEMCPY(ctx->serverDH_P.buffer, p, pSz); + XMEMCPY(ctx->serverDH_G.buffer, g, gSz); + + ctx->haveDH = 1; + + WOLFSSL_LEAVE("wolfSSL_CTX_SetTmpDH", 0); + return WOLFSSL_SUCCESS; +} + + +int wolfSSL_CTX_SetMinDhKey_Sz(WOLFSSL_CTX* ctx, word16 keySz) +{ + if (ctx == NULL || keySz > 16000 || keySz % 8 != 0) + return BAD_FUNC_ARG; + + ctx->minDhKeySz = keySz / 8; + return WOLFSSL_SUCCESS; +} + + +int wolfSSL_SetMinDhKey_Sz(WOLFSSL* ssl, word16 keySz) +{ + if (ssl == NULL || keySz > 16000 || keySz % 8 != 0) + return BAD_FUNC_ARG; + + ssl->options.minDhKeySz = keySz / 8; + return WOLFSSL_SUCCESS; +} + + +int wolfSSL_CTX_SetMaxDhKey_Sz(WOLFSSL_CTX* ctx, word16 keySz) +{ + if (ctx == NULL || keySz > 16000 || keySz % 8 != 0) + return BAD_FUNC_ARG; + + ctx->maxDhKeySz = keySz / 8; + return WOLFSSL_SUCCESS; +} + + +int wolfSSL_SetMaxDhKey_Sz(WOLFSSL* ssl, word16 keySz) +{ + if (ssl == NULL || keySz > 16000 || keySz % 8 != 0) + return BAD_FUNC_ARG; + + ssl->options.maxDhKeySz = keySz / 8; + return WOLFSSL_SUCCESS; +} + + +int wolfSSL_GetDhKey_Sz(WOLFSSL* ssl) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + + return (ssl->options.dhKeySz * 8); +} + +#endif /* !NO_DH */ + + +int wolfSSL_write(WOLFSSL* ssl, const void* data, int sz) +{ + int ret; + + WOLFSSL_ENTER("SSL_write()"); + + if (ssl == NULL || data == NULL || sz < 0) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_EARLY_DATA + if (ssl->earlyData != no_early_data && (ret = wolfSSL_negotiate(ssl)) < 0) { + ssl->error = ret; + return WOLFSSL_FATAL_ERROR; + } + ssl->earlyData = no_early_data; +#endif + +#ifdef HAVE_WRITE_DUP + { /* local variable scope */ + int dupErr = 0; /* local copy */ + + ret = 0; + + if (ssl->dupWrite && ssl->dupSide == READ_DUP_SIDE) { + WOLFSSL_MSG("Read dup side cannot write"); + return WRITE_DUP_WRITE_E; + } + if (ssl->dupWrite) { + if (wc_LockMutex(&ssl->dupWrite->dupMutex) != 0) { + return BAD_MUTEX_E; + } + dupErr = ssl->dupWrite->dupErr; + ret = wc_UnLockMutex(&ssl->dupWrite->dupMutex); + } + + if (ret != 0) { + ssl->error = ret; /* high priority fatal error */ + return WOLFSSL_FATAL_ERROR; + } + if (dupErr != 0) { + WOLFSSL_MSG("Write dup error from other side"); + ssl->error = dupErr; + return WOLFSSL_FATAL_ERROR; + } + } +#endif + +#ifdef HAVE_ERRNO_H + errno = 0; +#endif + + #ifdef OPENSSL_EXTRA + if (ssl->CBIS != NULL) { + ssl->CBIS(ssl, SSL_CB_WRITE, SSL_SUCCESS); + ssl->cbmode = SSL_CB_WRITE; + } + #endif + ret = SendData(ssl, data, sz); + + WOLFSSL_LEAVE("SSL_write()", ret); + + if (ret < 0) + return WOLFSSL_FATAL_ERROR; + else + return ret; +} + +static int wolfSSL_read_internal(WOLFSSL* ssl, void* data, int sz, int peek) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_read_internal()"); + + if (ssl == NULL || data == NULL || sz < 0) + return BAD_FUNC_ARG; + +#ifdef HAVE_WRITE_DUP + if (ssl->dupWrite && ssl->dupSide == WRITE_DUP_SIDE) { + WOLFSSL_MSG("Write dup side cannot read"); + return WRITE_DUP_READ_E; + } +#endif + +#ifdef HAVE_ERRNO_H + errno = 0; +#endif + +#ifdef WOLFSSL_DTLS + if (ssl->options.dtls) { + ssl->dtls_expected_rx = max(sz + 100, MAX_MTU); +#ifdef WOLFSSL_SCTP + if (ssl->options.dtlsSctp) + ssl->dtls_expected_rx = max(ssl->dtls_expected_rx, ssl->dtlsMtuSz); +#endif + } +#endif + + sz = wolfSSL_GetMaxRecordSize(ssl, sz); + + ret = ReceiveData(ssl, (byte*)data, sz, peek); + +#ifdef HAVE_WRITE_DUP + if (ssl->dupWrite) { + if (ssl->error != 0 && ssl->error != WANT_READ + #ifdef WOLFSSL_ASYNC_CRYPT + && ssl->error != WC_PENDING_E + #endif + ) { + int notifyErr; + + WOLFSSL_MSG("Notifying write side of fatal read error"); + notifyErr = NotifyWriteSide(ssl, ssl->error); + if (notifyErr < 0) { + ret = ssl->error = notifyErr; + } + } + } +#endif + + WOLFSSL_LEAVE("wolfSSL_read_internal()", ret); + + if (ret < 0) + return WOLFSSL_FATAL_ERROR; + else + return ret; +} + + +int wolfSSL_peek(WOLFSSL* ssl, void* data, int sz) +{ + WOLFSSL_ENTER("wolfSSL_peek()"); + + return wolfSSL_read_internal(ssl, data, sz, TRUE); +} + + +int wolfSSL_read(WOLFSSL* ssl, void* data, int sz) +{ + WOLFSSL_ENTER("wolfSSL_read()"); + + #ifdef OPENSSL_EXTRA + if (ssl->CBIS != NULL) { + ssl->CBIS(ssl, SSL_CB_READ, SSL_SUCCESS); + ssl->cbmode = SSL_CB_READ; + } + #endif + return wolfSSL_read_internal(ssl, data, sz, FALSE); +} + + +#ifdef WOLFSSL_MULTICAST + +int wolfSSL_mcast_read(WOLFSSL* ssl, word16* id, void* data, int sz) +{ + int ret = 0; + + WOLFSSL_ENTER("wolfSSL_mcast_read()"); + + if (ssl == NULL) + return BAD_FUNC_ARG; + + ret = wolfSSL_read_internal(ssl, data, sz, FALSE); + if (ssl->options.dtls && ssl->options.haveMcast && id != NULL) + *id = ssl->keys.curPeerId; + return ret; +} + +#endif /* WOLFSSL_MULTICAST */ + + +/* helpers to set the device id, WOLFSSL_SUCCESS on ok */ +int wolfSSL_SetDevId(WOLFSSL* ssl, int devId) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + + ssl->devId = devId; + + return WOLFSSL_SUCCESS; +} +int wolfSSL_CTX_SetDevId(WOLFSSL_CTX* ctx, int devId) +{ + if (ctx == NULL) + return BAD_FUNC_ARG; + + ctx->devId = devId; + + return WOLFSSL_SUCCESS; +} + +/* helpers to get device id and heap */ +int wolfSSL_CTX_GetDevId(WOLFSSL_CTX* ctx, WOLFSSL* ssl) +{ + int devId = INVALID_DEVID; + if (ctx != NULL) + devId = ctx->devId; + else if (ssl != NULL) + devId = ssl->devId; + return devId; +} +void* wolfSSL_CTX_GetHeap(WOLFSSL_CTX* ctx, WOLFSSL* ssl) +{ + void* heap = NULL; + if (ctx != NULL) + heap = ctx->heap; + else if (ssl != NULL) + heap = ssl->heap; + return heap; +} + + +#ifdef HAVE_SNI + +int wolfSSL_UseSNI(WOLFSSL* ssl, byte type, const void* data, word16 size) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + + return TLSX_UseSNI(&ssl->extensions, type, data, size, ssl->heap); +} + + +int wolfSSL_CTX_UseSNI(WOLFSSL_CTX* ctx, byte type, const void* data, + word16 size) +{ + if (ctx == NULL) + return BAD_FUNC_ARG; + + return TLSX_UseSNI(&ctx->extensions, type, data, size, ctx->heap); +} + +#ifndef NO_WOLFSSL_SERVER + +void wolfSSL_SNI_SetOptions(WOLFSSL* ssl, byte type, byte options) +{ + if (ssl && ssl->extensions) + TLSX_SNI_SetOptions(ssl->extensions, type, options); +} + + +void wolfSSL_CTX_SNI_SetOptions(WOLFSSL_CTX* ctx, byte type, byte options) +{ + if (ctx && ctx->extensions) + TLSX_SNI_SetOptions(ctx->extensions, type, options); +} + + +byte wolfSSL_SNI_Status(WOLFSSL* ssl, byte type) +{ + return TLSX_SNI_Status(ssl ? ssl->extensions : NULL, type); +} + + +word16 wolfSSL_SNI_GetRequest(WOLFSSL* ssl, byte type, void** data) +{ + if (data) + *data = NULL; + + if (ssl && ssl->extensions) + return TLSX_SNI_GetRequest(ssl->extensions, type, data); + + return 0; +} + + +int wolfSSL_SNI_GetFromBuffer(const byte* clientHello, word32 helloSz, + byte type, byte* sni, word32* inOutSz) +{ + if (clientHello && helloSz > 0 && sni && inOutSz && *inOutSz > 0) + return TLSX_SNI_GetFromBuffer(clientHello, helloSz, type, sni, inOutSz); + + return BAD_FUNC_ARG; +} + +#endif /* NO_WOLFSSL_SERVER */ + +#endif /* HAVE_SNI */ + + +#ifdef HAVE_TRUSTED_CA + +WOLFSSL_API int wolfSSL_UseTrustedCA(WOLFSSL* ssl, byte type, + const byte* certId, word32 certIdSz) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + + if (type == WOLFSSL_TRUSTED_CA_PRE_AGREED) { + if (certId != NULL || certIdSz != 0) + return BAD_FUNC_ARG; + } + else if (type == WOLFSSL_TRUSTED_CA_X509_NAME) { + if (certId == NULL || certIdSz == 0) + return BAD_FUNC_ARG; + } + #ifndef NO_SHA + else if (type == WOLFSSL_TRUSTED_CA_KEY_SHA1 || + type == WOLFSSL_TRUSTED_CA_CERT_SHA1) { + if (certId == NULL || certIdSz != SHA_DIGEST_SIZE) + return BAD_FUNC_ARG; + } + #endif + else + return BAD_FUNC_ARG; + + return TLSX_UseTrustedCA(&ssl->extensions, + type, certId, certIdSz, ssl->heap); +} + +#endif /* HAVE_TRUSTED_CA */ + + +#ifdef HAVE_MAX_FRAGMENT +#ifndef NO_WOLFSSL_CLIENT + +int wolfSSL_UseMaxFragment(WOLFSSL* ssl, byte mfl) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_ALLOW_MAX_FRAGMENT_ADJUST + /* The following is a non-standard way to reconfigure the max packet size + post-handshake for wolfSSL_write/woflSSL_read */ + if (ssl->options.handShakeState == HANDSHAKE_DONE) { + switch (mfl) { + case WOLFSSL_MFL_2_8 : ssl->max_fragment = 256; break; + case WOLFSSL_MFL_2_9 : ssl->max_fragment = 512; break; + case WOLFSSL_MFL_2_10: ssl->max_fragment = 1024; break; + case WOLFSSL_MFL_2_11: ssl->max_fragment = 2048; break; + case WOLFSSL_MFL_2_12: ssl->max_fragment = 4096; break; + case WOLFSSL_MFL_2_13: ssl->max_fragment = 8192; break; + default: ssl->max_fragment = MAX_RECORD_SIZE; break; + } + return WOLFSSL_SUCCESS; + } +#endif /* WOLFSSL_MAX_FRAGMENT_ADJUST */ + + /* This call sets the max fragment TLS extension, which gets sent to server. + The server_hello response is what sets the `ssl->max_fragment` in + TLSX_MFL_Parse */ + return TLSX_UseMaxFragment(&ssl->extensions, mfl, ssl->heap); +} + + +int wolfSSL_CTX_UseMaxFragment(WOLFSSL_CTX* ctx, byte mfl) +{ + if (ctx == NULL) + return BAD_FUNC_ARG; + + return TLSX_UseMaxFragment(&ctx->extensions, mfl, ctx->heap); +} + +#endif /* NO_WOLFSSL_CLIENT */ +#endif /* HAVE_MAX_FRAGMENT */ + +#ifdef HAVE_TRUNCATED_HMAC +#ifndef NO_WOLFSSL_CLIENT + +int wolfSSL_UseTruncatedHMAC(WOLFSSL* ssl) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + + return TLSX_UseTruncatedHMAC(&ssl->extensions, ssl->heap); +} + + +int wolfSSL_CTX_UseTruncatedHMAC(WOLFSSL_CTX* ctx) +{ + if (ctx == NULL) + return BAD_FUNC_ARG; + + return TLSX_UseTruncatedHMAC(&ctx->extensions, ctx->heap); +} + +#endif /* NO_WOLFSSL_CLIENT */ +#endif /* HAVE_TRUNCATED_HMAC */ + +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST + +int wolfSSL_UseOCSPStapling(WOLFSSL* ssl, byte status_type, byte options) +{ + if (ssl == NULL || ssl->options.side != WOLFSSL_CLIENT_END) + return BAD_FUNC_ARG; + + return TLSX_UseCertificateStatusRequest(&ssl->extensions, status_type, + options, NULL, ssl->heap, ssl->devId); +} + + +int wolfSSL_CTX_UseOCSPStapling(WOLFSSL_CTX* ctx, byte status_type, + byte options) +{ + if (ctx == NULL || ctx->method->side != WOLFSSL_CLIENT_END) + return BAD_FUNC_ARG; + + return TLSX_UseCertificateStatusRequest(&ctx->extensions, status_type, + options, NULL, ctx->heap, ctx->devId); +} + +#endif /* HAVE_CERTIFICATE_STATUS_REQUEST */ + +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + +int wolfSSL_UseOCSPStaplingV2(WOLFSSL* ssl, byte status_type, byte options) +{ + if (ssl == NULL || ssl->options.side != WOLFSSL_CLIENT_END) + return BAD_FUNC_ARG; + + return TLSX_UseCertificateStatusRequestV2(&ssl->extensions, status_type, + options, ssl->heap, ssl->devId); +} + + +int wolfSSL_CTX_UseOCSPStaplingV2(WOLFSSL_CTX* ctx, byte status_type, + byte options) +{ + if (ctx == NULL || ctx->method->side != WOLFSSL_CLIENT_END) + return BAD_FUNC_ARG; + + return TLSX_UseCertificateStatusRequestV2(&ctx->extensions, status_type, + options, ctx->heap, ctx->devId); +} + +#endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */ + +/* Elliptic Curves */ +#ifdef HAVE_SUPPORTED_CURVES +#ifndef NO_WOLFSSL_CLIENT + +int wolfSSL_UseSupportedCurve(WOLFSSL* ssl, word16 name) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + + switch (name) { + case WOLFSSL_ECC_SECP160K1: + case WOLFSSL_ECC_SECP160R1: + case WOLFSSL_ECC_SECP160R2: + case WOLFSSL_ECC_SECP192K1: + case WOLFSSL_ECC_SECP192R1: + case WOLFSSL_ECC_SECP224K1: + case WOLFSSL_ECC_SECP224R1: + case WOLFSSL_ECC_SECP256K1: + case WOLFSSL_ECC_SECP256R1: + case WOLFSSL_ECC_SECP384R1: + case WOLFSSL_ECC_SECP521R1: + case WOLFSSL_ECC_BRAINPOOLP256R1: + case WOLFSSL_ECC_BRAINPOOLP384R1: + case WOLFSSL_ECC_BRAINPOOLP512R1: + case WOLFSSL_ECC_X25519: + + case WOLFSSL_FFDHE_2048: + case WOLFSSL_FFDHE_3072: + case WOLFSSL_FFDHE_4096: + case WOLFSSL_FFDHE_6144: + case WOLFSSL_FFDHE_8192: + break; + + default: + return BAD_FUNC_ARG; + } + + ssl->options.userCurves = 1; + + return TLSX_UseSupportedCurve(&ssl->extensions, name, ssl->heap); +} + + +int wolfSSL_CTX_UseSupportedCurve(WOLFSSL_CTX* ctx, word16 name) +{ + if (ctx == NULL) + return BAD_FUNC_ARG; + + switch (name) { + case WOLFSSL_ECC_SECP160K1: + case WOLFSSL_ECC_SECP160R1: + case WOLFSSL_ECC_SECP160R2: + case WOLFSSL_ECC_SECP192K1: + case WOLFSSL_ECC_SECP192R1: + case WOLFSSL_ECC_SECP224K1: + case WOLFSSL_ECC_SECP224R1: + case WOLFSSL_ECC_SECP256K1: + case WOLFSSL_ECC_SECP256R1: + case WOLFSSL_ECC_SECP384R1: + case WOLFSSL_ECC_SECP521R1: + case WOLFSSL_ECC_BRAINPOOLP256R1: + case WOLFSSL_ECC_BRAINPOOLP384R1: + case WOLFSSL_ECC_BRAINPOOLP512R1: + case WOLFSSL_ECC_X25519: + case WOLFSSL_FFDHE_2048: + case WOLFSSL_FFDHE_3072: + case WOLFSSL_FFDHE_4096: + case WOLFSSL_FFDHE_6144: + case WOLFSSL_FFDHE_8192: + break; + + default: + return BAD_FUNC_ARG; + } + + ctx->userCurves = 1; + + return TLSX_UseSupportedCurve(&ctx->extensions, name, ctx->heap); +} + +#endif /* NO_WOLFSSL_CLIENT */ +#endif /* HAVE_SUPPORTED_CURVES */ + +/* QSH quantum safe handshake */ +#ifdef HAVE_QSH +/* returns 1 if QSH has been used 0 otherwise */ +int wolfSSL_isQSH(WOLFSSL* ssl) +{ + /* if no ssl struct than QSH was not used */ + if (ssl == NULL) + return 0; + + return ssl->isQSH; +} + + +int wolfSSL_UseSupportedQSH(WOLFSSL* ssl, word16 name) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + + switch (name) { + #ifdef HAVE_NTRU + case WOLFSSL_NTRU_EESS439: + case WOLFSSL_NTRU_EESS593: + case WOLFSSL_NTRU_EESS743: + break; + #endif + default: + return BAD_FUNC_ARG; + } + + ssl->user_set_QSHSchemes = 1; + + return TLSX_UseQSHScheme(&ssl->extensions, name, NULL, 0, ssl->heap); +} + +#ifndef NO_WOLFSSL_CLIENT + /* user control over sending client public key in hello + when flag = 1 will send keys if flag is 0 or function is not called + then will not send keys in the hello extension + return 0 on success + */ + int wolfSSL_UseClientQSHKeys(WOLFSSL* ssl, unsigned char flag) + { + if (ssl == NULL) + return BAD_FUNC_ARG; + + ssl->sendQSHKeys = flag; + + return 0; + } +#endif /* NO_WOLFSSL_CLIENT */ +#endif /* HAVE_QSH */ + +/* Application-Layer Protocol Negotiation */ +#ifdef HAVE_ALPN + +int wolfSSL_UseALPN(WOLFSSL* ssl, char *protocol_name_list, + word32 protocol_name_listSz, byte options) +{ + char *list, *ptr, *token[10]; + word16 len; + int idx = 0; + int ret = WOLFSSL_FAILURE; + + WOLFSSL_ENTER("wolfSSL_UseALPN"); + + if (ssl == NULL || protocol_name_list == NULL) + return BAD_FUNC_ARG; + + if (protocol_name_listSz > (WOLFSSL_MAX_ALPN_NUMBER * + WOLFSSL_MAX_ALPN_PROTO_NAME_LEN + + WOLFSSL_MAX_ALPN_NUMBER)) { + WOLFSSL_MSG("Invalid arguments, protocol name list too long"); + return BAD_FUNC_ARG; + } + + if (!(options & WOLFSSL_ALPN_CONTINUE_ON_MISMATCH) && + !(options & WOLFSSL_ALPN_FAILED_ON_MISMATCH)) { + WOLFSSL_MSG("Invalid arguments, options not supported"); + return BAD_FUNC_ARG; + } + + + list = (char *)XMALLOC(protocol_name_listSz+1, ssl->heap, + DYNAMIC_TYPE_ALPN); + if (list == NULL) { + WOLFSSL_MSG("Memory failure"); + return MEMORY_ERROR; + } + + XSTRNCPY(list, protocol_name_list, protocol_name_listSz); + list[protocol_name_listSz] = '\0'; + + /* read all protocol name from the list */ + token[idx] = XSTRTOK(list, ",", &ptr); + while (token[idx] != NULL) + token[++idx] = XSTRTOK(NULL, ",", &ptr); + + /* add protocol name list in the TLS extension in reverse order */ + while ((idx--) > 0) { + len = (word16)XSTRLEN(token[idx]); + + ret = TLSX_UseALPN(&ssl->extensions, token[idx], len, options, + ssl->heap); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("TLSX_UseALPN failure"); + break; + } + } + + XFREE(list, ssl->heap, DYNAMIC_TYPE_ALPN); + + return ret; +} + +int wolfSSL_ALPN_GetProtocol(WOLFSSL* ssl, char **protocol_name, word16 *size) +{ + return TLSX_ALPN_GetRequest(ssl ? ssl->extensions : NULL, + (void **)protocol_name, size); +} + +int wolfSSL_ALPN_GetPeerProtocol(WOLFSSL* ssl, char **list, word16 *listSz) +{ + if (list == NULL || listSz == NULL) + return BAD_FUNC_ARG; + + if (ssl->alpn_client_list == NULL) + return BUFFER_ERROR; + + *listSz = (word16)XSTRLEN(ssl->alpn_client_list); + if (*listSz == 0) + return BUFFER_ERROR; + + *list = (char *)XMALLOC((*listSz)+1, ssl->heap, DYNAMIC_TYPE_TLSX); + if (*list == NULL) + return MEMORY_ERROR; + + XSTRNCPY(*list, ssl->alpn_client_list, (*listSz)+1); + (*list)[*listSz] = 0; + + return WOLFSSL_SUCCESS; +} + + +/* used to free memory allocated by wolfSSL_ALPN_GetPeerProtocol */ +int wolfSSL_ALPN_FreePeerProtocol(WOLFSSL* ssl, char **list) +{ + if (ssl == NULL) { + return BAD_FUNC_ARG; + } + + XFREE(*list, ssl->heap, DYNAMIC_TYPE_TLSX); + *list = NULL; + + return WOLFSSL_SUCCESS; +} + +#endif /* HAVE_ALPN */ + +/* Secure Renegotiation */ +#ifdef HAVE_SECURE_RENEGOTIATION + +/* user is forcing ability to use secure renegotiation, we discourage it */ +int wolfSSL_UseSecureRenegotiation(WOLFSSL* ssl) +{ + int ret = BAD_FUNC_ARG; + + if (ssl) + ret = TLSX_UseSecureRenegotiation(&ssl->extensions, ssl->heap); + + if (ret == WOLFSSL_SUCCESS) { + TLSX* extension = TLSX_Find(ssl->extensions, TLSX_RENEGOTIATION_INFO); + + if (extension) + ssl->secure_renegotiation = (SecureRenegotiation*)extension->data; + } + + return ret; +} + + +/* do a secure renegotiation handshake, user forced, we discourage */ +int wolfSSL_Rehandshake(WOLFSSL* ssl) +{ + int ret; + + if (ssl == NULL) + return BAD_FUNC_ARG; + + if (ssl->secure_renegotiation == NULL) { + WOLFSSL_MSG("Secure Renegotiation not forced on by user"); + return SECURE_RENEGOTIATION_E; + } + + if (ssl->secure_renegotiation->enabled == 0) { + WOLFSSL_MSG("Secure Renegotiation not enabled at extension level"); + return SECURE_RENEGOTIATION_E; + } + + /* If the client started the renegotiation, the server will already + * have processed the client's hello. */ + if (ssl->options.side != WOLFSSL_SERVER_END || + ssl->options.acceptState != ACCEPT_FIRST_REPLY_DONE) { + + if (ssl->options.handShakeState != HANDSHAKE_DONE) { + WOLFSSL_MSG("Can't renegotiate until previous handshake complete"); + return SECURE_RENEGOTIATION_E; + } + +#ifndef NO_FORCE_SCR_SAME_SUITE + /* force same suite */ + if (ssl->suites) { + ssl->suites->suiteSz = SUITE_LEN; + ssl->suites->suites[0] = ssl->options.cipherSuite0; + ssl->suites->suites[1] = ssl->options.cipherSuite; + } +#endif + + /* reset handshake states */ + ssl->options.sendVerify = 0; + ssl->options.serverState = NULL_STATE; + ssl->options.clientState = NULL_STATE; + ssl->options.connectState = CONNECT_BEGIN; + ssl->options.acceptState = ACCEPT_BEGIN; + ssl->options.handShakeState = NULL_STATE; + ssl->options.processReply = 0; /* TODO, move states in internal.h */ + + XMEMSET(&ssl->msgsReceived, 0, sizeof(ssl->msgsReceived)); + + ssl->secure_renegotiation->cache_status = SCR_CACHE_NEEDED; + +#if !defined(NO_WOLFSSL_SERVER) && defined(HAVE_SERVER_RENEGOTIATION_INFO) + if (ssl->options.side == WOLFSSL_SERVER_END) { + ret = SendHelloRequest(ssl); + if (ret != 0) { + ssl->error = ret; + return WOLFSSL_FATAL_ERROR; + } + } +#endif /* NO_WOLFSSL_SERVER && HAVE_SERVER_RENEGOTIATION_INFO */ + + ret = InitHandshakeHashes(ssl); + if (ret != 0) { + ssl->error = ret; + return WOLFSSL_FATAL_ERROR; + } + } + ret = wolfSSL_negotiate(ssl); + return ret; +} + + +#ifndef NO_WOLFSSL_CLIENT + +/* do a secure resumption handshake, user forced, we discourage */ +int wolfSSL_SecureResume(WOLFSSL* ssl) +{ + WOLFSSL_SESSION* session; + int ret; + + WOLFSSL_ENTER("wolfSSL_SecureResume()"); + + if (ssl == NULL) + return BAD_FUNC_ARG; + + if (ssl->options.side == WOLFSSL_SERVER_END) { + ssl->error = SIDE_ERROR; + return SSL_FATAL_ERROR; + } + + session = wolfSSL_get_session(ssl); + ret = wolfSSL_set_session(ssl, session); + session = NULL; + if (ret == WOLFSSL_SUCCESS) + ret = wolfSSL_Rehandshake(ssl); + + return ret; +} + +#endif /* NO_WOLFSSL_CLIENT */ + +#endif /* HAVE_SECURE_RENEGOTIATION */ + +/* Session Ticket */ +#if !defined(NO_WOLFSSL_SERVER) && defined(HAVE_SESSION_TICKET) +/* WOLFSSL_SUCCESS on ok */ +int wolfSSL_CTX_set_TicketEncCb(WOLFSSL_CTX* ctx, SessionTicketEncCb cb) +{ + if (ctx == NULL) + return BAD_FUNC_ARG; + + ctx->ticketEncCb = cb; + + return WOLFSSL_SUCCESS; +} + +/* set hint interval, WOLFSSL_SUCCESS on ok */ +int wolfSSL_CTX_set_TicketHint(WOLFSSL_CTX* ctx, int hint) +{ + if (ctx == NULL) + return BAD_FUNC_ARG; + + ctx->ticketHint = hint; + + return WOLFSSL_SUCCESS; +} + +/* set user context, WOLFSSL_SUCCESS on ok */ +int wolfSSL_CTX_set_TicketEncCtx(WOLFSSL_CTX* ctx, void* userCtx) +{ + if (ctx == NULL) + return BAD_FUNC_ARG; + + ctx->ticketEncCtx = userCtx; + + return WOLFSSL_SUCCESS; +} + +#endif /* !defined(NO_WOLFSSL_CLIENT) && defined(HAVE_SESSION_TICKET) */ + +/* Session Ticket */ +#if !defined(NO_WOLFSSL_CLIENT) && defined(HAVE_SESSION_TICKET) +int wolfSSL_UseSessionTicket(WOLFSSL* ssl) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + + return TLSX_UseSessionTicket(&ssl->extensions, NULL, ssl->heap); +} + +int wolfSSL_CTX_UseSessionTicket(WOLFSSL_CTX* ctx) +{ + if (ctx == NULL) + return BAD_FUNC_ARG; + + return TLSX_UseSessionTicket(&ctx->extensions, NULL, ctx->heap); +} + +WOLFSSL_API int wolfSSL_get_SessionTicket(WOLFSSL* ssl, + byte* buf, word32* bufSz) +{ + if (ssl == NULL || buf == NULL || bufSz == NULL || *bufSz == 0) + return BAD_FUNC_ARG; + + if (ssl->session.ticketLen <= *bufSz) { + XMEMCPY(buf, ssl->session.ticket, ssl->session.ticketLen); + *bufSz = ssl->session.ticketLen; + } + else + *bufSz = 0; + + return WOLFSSL_SUCCESS; +} + +WOLFSSL_API int wolfSSL_set_SessionTicket(WOLFSSL* ssl, const byte* buf, + word32 bufSz) +{ + if (ssl == NULL || (buf == NULL && bufSz > 0)) + return BAD_FUNC_ARG; + + if (bufSz > 0) { + /* Ticket will fit into static ticket */ + if(bufSz <= SESSION_TICKET_LEN) { + if (ssl->session.isDynamic) { + XFREE(ssl->session.ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); + ssl->session.isDynamic = 0; + ssl->session.ticket = ssl->session.staticTicket; + } + } else { /* Ticket requires dynamic ticket storage */ + if (ssl->session.ticketLen < bufSz) { /* is dyn buffer big enough */ + if(ssl->session.isDynamic) + XFREE(ssl->session.ticket, ssl->heap, + DYNAMIC_TYPE_SESSION_TICK); + ssl->session.ticket = (byte*)XMALLOC(bufSz, ssl->heap, + DYNAMIC_TYPE_SESSION_TICK); + if(!ssl->session.ticket) { + ssl->session.ticket = ssl->session.staticTicket; + ssl->session.isDynamic = 0; + return MEMORY_ERROR; + } + ssl->session.isDynamic = 1; + } + } + XMEMCPY(ssl->session.ticket, buf, bufSz); + } + ssl->session.ticketLen = (word16)bufSz; + + return WOLFSSL_SUCCESS; +} + + +WOLFSSL_API int wolfSSL_set_SessionTicket_cb(WOLFSSL* ssl, + CallbackSessionTicket cb, void* ctx) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + + ssl->session_ticket_cb = cb; + ssl->session_ticket_ctx = ctx; + + return WOLFSSL_SUCCESS; +} +#endif + + +#ifdef HAVE_EXTENDED_MASTER +#ifndef NO_WOLFSSL_CLIENT + +int wolfSSL_CTX_DisableExtendedMasterSecret(WOLFSSL_CTX* ctx) +{ + if (ctx == NULL) + return BAD_FUNC_ARG; + + ctx->haveEMS = 0; + + return WOLFSSL_SUCCESS; +} + + +int wolfSSL_DisableExtendedMasterSecret(WOLFSSL* ssl) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + + ssl->options.haveEMS = 0; + + return WOLFSSL_SUCCESS; +} + +#endif +#endif + + +#ifndef WOLFSSL_LEANPSK + +int wolfSSL_send(WOLFSSL* ssl, const void* data, int sz, int flags) +{ + int ret; + int oldFlags; + + WOLFSSL_ENTER("wolfSSL_send()"); + + if (ssl == NULL || data == NULL || sz < 0) + return BAD_FUNC_ARG; + + oldFlags = ssl->wflags; + + ssl->wflags = flags; + ret = wolfSSL_write(ssl, data, sz); + ssl->wflags = oldFlags; + + WOLFSSL_LEAVE("wolfSSL_send()", ret); + + return ret; +} + + +int wolfSSL_recv(WOLFSSL* ssl, void* data, int sz, int flags) +{ + int ret; + int oldFlags; + + WOLFSSL_ENTER("wolfSSL_recv()"); + + if (ssl == NULL || data == NULL || sz < 0) + return BAD_FUNC_ARG; + + oldFlags = ssl->rflags; + + ssl->rflags = flags; + ret = wolfSSL_read(ssl, data, sz); + ssl->rflags = oldFlags; + + WOLFSSL_LEAVE("wolfSSL_recv()", ret); + + return ret; +} +#endif + + +/* WOLFSSL_SUCCESS on ok */ +int wolfSSL_shutdown(WOLFSSL* ssl) +{ + int ret = WOLFSSL_FATAL_ERROR; + byte tmp; + WOLFSSL_ENTER("SSL_shutdown()"); + + if (ssl == NULL) + return WOLFSSL_FATAL_ERROR; + + if (ssl->options.quietShutdown) { + WOLFSSL_MSG("quiet shutdown, no close notify sent"); + ret = WOLFSSL_SUCCESS; + } + else { + /* try to send close notify, not an error if can't */ + if (!ssl->options.isClosed && !ssl->options.connReset && + !ssl->options.sentNotify) { + ssl->error = SendAlert(ssl, alert_warning, close_notify); + if (ssl->error < 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + ssl->options.sentNotify = 1; /* don't send close_notify twice */ + if (ssl->options.closeNotify) + ret = WOLFSSL_SUCCESS; + else { + ret = WOLFSSL_SHUTDOWN_NOT_DONE; + WOLFSSL_LEAVE("SSL_shutdown()", ret); + return ret; + } + } + + /* call wolfSSL_shutdown again for bidirectional shutdown */ + if (ssl->options.sentNotify && !ssl->options.closeNotify) { + ret = wolfSSL_read(ssl, &tmp, 0); + if (ret < 0) { + WOLFSSL_ERROR(ssl->error); + ret = WOLFSSL_FATAL_ERROR; + } else if (ssl->options.closeNotify) { + ssl->error = WOLFSSL_ERROR_SYSCALL; /* simulate OpenSSL behavior */ + ret = WOLFSSL_SUCCESS; + } else if ((ssl->error == WOLFSSL_ERROR_NONE) && + (ret < WOLFSSL_SUCCESS)) { + ret = WOLFSSL_SHUTDOWN_NOT_DONE; + } + } + } + +#ifdef OPENSSL_EXTRA + /* reset WOLFSSL structure state for possible re-use */ + if (ret == WOLFSSL_SUCCESS) { + if (wolfSSL_clear(ssl) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("could not clear WOLFSSL"); + ret = WOLFSSL_FATAL_ERROR; + } + } +#endif + + WOLFSSL_LEAVE("SSL_shutdown()", ret); + + return ret; +} + + +/* get current error state value */ +int wolfSSL_state(WOLFSSL* ssl) +{ + if (ssl == NULL) { + return BAD_FUNC_ARG; + } + + return ssl->error; +} + + +int wolfSSL_get_error(WOLFSSL* ssl, int ret) +{ + WOLFSSL_ENTER("SSL_get_error"); + + if (ret > 0) + return WOLFSSL_ERROR_NONE; + if (ssl == NULL) + return BAD_FUNC_ARG; + + WOLFSSL_LEAVE("SSL_get_error", ssl->error); + + /* make sure converted types are handled in SetErrorString() too */ + if (ssl->error == WANT_READ) + return WOLFSSL_ERROR_WANT_READ; /* convert to OpenSSL type */ + else if (ssl->error == WANT_WRITE) + return WOLFSSL_ERROR_WANT_WRITE; /* convert to OpenSSL type */ + else if (ssl->error == ZERO_RETURN) + return WOLFSSL_ERROR_ZERO_RETURN; /* convert to OpenSSL type */ + return ssl->error; +} + + +/* retrieve alert history, WOLFSSL_SUCCESS on ok */ +int wolfSSL_get_alert_history(WOLFSSL* ssl, WOLFSSL_ALERT_HISTORY *h) +{ + if (ssl && h) { + *h = ssl->alert_history; + } + return WOLFSSL_SUCCESS; +} + + +/* return TRUE if current error is want read */ +int wolfSSL_want_read(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("SSL_want_read"); + if (ssl->error == WANT_READ) + return 1; + + return 0; +} + + +/* return TRUE if current error is want write */ +int wolfSSL_want_write(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("SSL_want_write"); + if (ssl->error == WANT_WRITE) + return 1; + + return 0; +} + + +char* wolfSSL_ERR_error_string(unsigned long errNumber, char* data) +{ + static const char* const msg = "Please supply a buffer for error string"; + + WOLFSSL_ENTER("ERR_error_string"); + if (data) { + SetErrorString((int)errNumber, data); + return data; + } + + return (char*)msg; +} + + +void wolfSSL_ERR_error_string_n(unsigned long e, char* buf, unsigned long len) +{ + WOLFSSL_ENTER("wolfSSL_ERR_error_string_n"); + if (len >= WOLFSSL_MAX_ERROR_SZ) + wolfSSL_ERR_error_string(e, buf); + else { + char tmp[WOLFSSL_MAX_ERROR_SZ]; + + WOLFSSL_MSG("Error buffer too short, truncating"); + if (len) { + wolfSSL_ERR_error_string(e, tmp); + XMEMCPY(buf, tmp, len-1); + buf[len-1] = '\0'; + } + } +} + + +/* don't free temporary arrays at end of handshake */ +void wolfSSL_KeepArrays(WOLFSSL* ssl) +{ + if (ssl) + ssl->options.saveArrays = 1; +} + + +/* user doesn't need temporary arrays anymore, Free */ +void wolfSSL_FreeArrays(WOLFSSL* ssl) +{ + if (ssl && ssl->options.handShakeState == HANDSHAKE_DONE) { + ssl->options.saveArrays = 0; + FreeArrays(ssl, 1); + } +} + +/* Set option to indicate that the resources are not to be freed after + * handshake. + * + * ssl The SSL/TLS object. + * returns BAD_FUNC_ARG when ssl is NULL and 0 on success. + */ +int wolfSSL_KeepHandshakeResources(WOLFSSL* ssl) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + + ssl->options.keepResources = 1; + + return 0; +} + +/* Free the handshake resources after handshake. + * + * ssl The SSL/TLS object. + * returns BAD_FUNC_ARG when ssl is NULL and 0 on success. + */ +int wolfSSL_FreeHandshakeResources(WOLFSSL* ssl) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + + FreeHandshakeResources(ssl); + + return 0; +} + +/* Use the client's order of preference when matching cipher suites. + * + * ssl The SSL/TLS context object. + * returns BAD_FUNC_ARG when ssl is NULL and 0 on success. + */ +int wolfSSL_CTX_UseClientSuites(WOLFSSL_CTX* ctx) +{ + if (ctx == NULL) + return BAD_FUNC_ARG; + + ctx->useClientOrder = 1; + + return 0; +} + +/* Use the client's order of preference when matching cipher suites. + * + * ssl The SSL/TLS object. + * returns BAD_FUNC_ARG when ssl is NULL and 0 on success. + */ +int wolfSSL_UseClientSuites(WOLFSSL* ssl) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + + ssl->options.useClientOrder = 1; + + return 0; +} + +const byte* wolfSSL_GetMacSecret(WOLFSSL* ssl, int verify) +{ +#ifndef WOLFSSL_AEAD_ONLY + if (ssl == NULL) + return NULL; + + if ( (ssl->options.side == WOLFSSL_CLIENT_END && !verify) || + (ssl->options.side == WOLFSSL_SERVER_END && verify) ) + return ssl->keys.client_write_MAC_secret; + else + return ssl->keys.server_write_MAC_secret; +#else + (void)ssl; + (void)verify; + + return NULL; +#endif +} + + +#ifdef ATOMIC_USER + +void wolfSSL_CTX_SetMacEncryptCb(WOLFSSL_CTX* ctx, CallbackMacEncrypt cb) +{ + if (ctx) + ctx->MacEncryptCb = cb; +} + + +void wolfSSL_SetMacEncryptCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->MacEncryptCtx = ctx; +} + + +void* wolfSSL_GetMacEncryptCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->MacEncryptCtx; + + return NULL; +} + + +void wolfSSL_CTX_SetDecryptVerifyCb(WOLFSSL_CTX* ctx, CallbackDecryptVerify cb) +{ + if (ctx) + ctx->DecryptVerifyCb = cb; +} + + +void wolfSSL_SetDecryptVerifyCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->DecryptVerifyCtx = ctx; +} + + +void* wolfSSL_GetDecryptVerifyCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->DecryptVerifyCtx; + + return NULL; +} + + +const byte* wolfSSL_GetClientWriteKey(WOLFSSL* ssl) +{ + if (ssl) + return ssl->keys.client_write_key; + + return NULL; +} + + +const byte* wolfSSL_GetClientWriteIV(WOLFSSL* ssl) +{ + if (ssl) + return ssl->keys.client_write_IV; + + return NULL; +} + + +const byte* wolfSSL_GetServerWriteKey(WOLFSSL* ssl) +{ + if (ssl) + return ssl->keys.server_write_key; + + return NULL; +} + + +const byte* wolfSSL_GetServerWriteIV(WOLFSSL* ssl) +{ + if (ssl) + return ssl->keys.server_write_IV; + + return NULL; +} + +int wolfSSL_GetKeySize(WOLFSSL* ssl) +{ + if (ssl) + return ssl->specs.key_size; + + return BAD_FUNC_ARG; +} + + +int wolfSSL_GetIVSize(WOLFSSL* ssl) +{ + if (ssl) + return ssl->specs.iv_size; + + return BAD_FUNC_ARG; +} + + +int wolfSSL_GetBulkCipher(WOLFSSL* ssl) +{ + if (ssl) + return ssl->specs.bulk_cipher_algorithm; + + return BAD_FUNC_ARG; +} + + +int wolfSSL_GetCipherType(WOLFSSL* ssl) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + + if (ssl->specs.cipher_type == block) + return WOLFSSL_BLOCK_TYPE; + if (ssl->specs.cipher_type == stream) + return WOLFSSL_STREAM_TYPE; + if (ssl->specs.cipher_type == aead) + return WOLFSSL_AEAD_TYPE; + + return -1; +} + + +int wolfSSL_GetCipherBlockSize(WOLFSSL* ssl) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + + return ssl->specs.block_size; +} + + +int wolfSSL_GetAeadMacSize(WOLFSSL* ssl) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + + return ssl->specs.aead_mac_size; +} + + +int wolfSSL_IsTLSv1_1(WOLFSSL* ssl) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + + if (ssl->options.tls1_1) + return 1; + + return 0; +} + + +int wolfSSL_GetSide(WOLFSSL* ssl) +{ + if (ssl) + return ssl->options.side; + + return BAD_FUNC_ARG; +} + + +int wolfSSL_GetHmacSize(WOLFSSL* ssl) +{ + /* AEAD ciphers don't have HMAC keys */ + if (ssl) + return (ssl->specs.cipher_type != aead) ? ssl->specs.hash_size : 0; + + return BAD_FUNC_ARG; +} + +#endif /* ATOMIC_USER */ + +#ifndef NO_CERTS + +WOLFSSL_CERT_MANAGER* wolfSSL_CTX_GetCertManager(WOLFSSL_CTX* ctx) +{ + WOLFSSL_CERT_MANAGER* cm = NULL; + if (ctx) + cm = ctx->cm; + return cm; +} + +WOLFSSL_CERT_MANAGER* wolfSSL_CertManagerNew_ex(void* heap) +{ + WOLFSSL_CERT_MANAGER* cm = NULL; + + WOLFSSL_ENTER("wolfSSL_CertManagerNew"); + + cm = (WOLFSSL_CERT_MANAGER*) XMALLOC(sizeof(WOLFSSL_CERT_MANAGER), heap, + DYNAMIC_TYPE_CERT_MANAGER); + if (cm) { + XMEMSET(cm, 0, sizeof(WOLFSSL_CERT_MANAGER)); + + if (wc_InitMutex(&cm->caLock) != 0) { + WOLFSSL_MSG("Bad mutex init"); + wolfSSL_CertManagerFree(cm); + return NULL; + } + + #ifdef WOLFSSL_TRUST_PEER_CERT + if (wc_InitMutex(&cm->tpLock) != 0) { + WOLFSSL_MSG("Bad mutex init"); + wolfSSL_CertManagerFree(cm); + return NULL; + } + #endif + + /* set default minimum key size allowed */ + #ifndef NO_RSA + cm->minRsaKeySz = MIN_RSAKEY_SZ; + #endif + #ifdef HAVE_ECC + cm->minEccKeySz = MIN_ECCKEY_SZ; + #endif + cm->heap = heap; + } + + return cm; +} + + +WOLFSSL_CERT_MANAGER* wolfSSL_CertManagerNew(void) +{ + return wolfSSL_CertManagerNew_ex(NULL); +} + + +void wolfSSL_CertManagerFree(WOLFSSL_CERT_MANAGER* cm) +{ + WOLFSSL_ENTER("wolfSSL_CertManagerFree"); + + if (cm) { + #ifdef HAVE_CRL + if (cm->crl) + FreeCRL(cm->crl, 1); + #endif + #ifdef HAVE_OCSP + if (cm->ocsp) + FreeOCSP(cm->ocsp, 1); + XFREE(cm->ocspOverrideURL, cm->heap, DYNAMIC_TYPE_URL); + #if !defined(NO_WOLFSSL_SERVER) && \ + (defined(HAVE_CERTIFICATE_STATUS_REQUEST) || \ + defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)) + if (cm->ocsp_stapling) + FreeOCSP(cm->ocsp_stapling, 1); + #endif + #endif + FreeSignerTable(cm->caTable, CA_TABLE_SIZE, cm->heap); + wc_FreeMutex(&cm->caLock); + + #ifdef WOLFSSL_TRUST_PEER_CERT + FreeTrustedPeerTable(cm->tpTable, TP_TABLE_SIZE, cm->heap); + wc_FreeMutex(&cm->tpLock); + #endif + + XFREE(cm, cm->heap, DYNAMIC_TYPE_CERT_MANAGER); + } + +} + + +/* Unload the CA signer list */ +int wolfSSL_CertManagerUnloadCAs(WOLFSSL_CERT_MANAGER* cm) +{ + WOLFSSL_ENTER("wolfSSL_CertManagerUnloadCAs"); + + if (cm == NULL) + return BAD_FUNC_ARG; + + if (wc_LockMutex(&cm->caLock) != 0) + return BAD_MUTEX_E; + + FreeSignerTable(cm->caTable, CA_TABLE_SIZE, cm->heap); + + wc_UnLockMutex(&cm->caLock); + + + return WOLFSSL_SUCCESS; +} + + +#ifdef WOLFSSL_TRUST_PEER_CERT +int wolfSSL_CertManagerUnload_trust_peers(WOLFSSL_CERT_MANAGER* cm) +{ + WOLFSSL_ENTER("wolfSSL_CertManagerUnload_trust_peers"); + + if (cm == NULL) + return BAD_FUNC_ARG; + + if (wc_LockMutex(&cm->tpLock) != 0) + return BAD_MUTEX_E; + + FreeTrustedPeerTable(cm->tpTable, TP_TABLE_SIZE, cm->heap); + + wc_UnLockMutex(&cm->tpLock); + + + return WOLFSSL_SUCCESS; +} +#endif /* WOLFSSL_TRUST_PEER_CERT */ + +#endif /* NO_CERTS */ + +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || \ + defined(HAVE_WEBSERVER) + +static const struct cipher{ + unsigned char type; + const char *name; +} cipher_tbl[] = { + +#ifndef NO_AES + #ifdef WOLFSSL_AES_128 + {AES_128_CBC_TYPE, "AES-128-CBC"}, + #endif + #ifdef WOLFSSL_AES_192 + {AES_192_CBC_TYPE, "AES-192-CBC"}, + #endif + #ifdef WOLFSSL_AES_256 + {AES_256_CBC_TYPE, "AES-256-CBC"}, + #endif +#if defined(OPENSSL_EXTRA) + #ifdef WOLFSSL_AES_128 + {AES_128_CTR_TYPE, "AES-128-CTR"}, + #endif + #ifdef WOLFSSL_AES_192 + {AES_192_CTR_TYPE, "AES-192-CTR"}, + #endif + #ifdef WOLFSSL_AES_256 + {AES_256_CTR_TYPE, "AES-256-CTR"}, + #endif + + #ifdef WOLFSSL_AES_128 + {AES_128_ECB_TYPE, "AES-128-ECB"}, + #endif + #ifdef WOLFSSL_AES_192 + {AES_192_ECB_TYPE, "AES-192-ECB"}, + #endif + #ifdef WOLFSSL_AES_256 + {AES_256_ECB_TYPE, "AES-256-ECB"}, + #endif +#endif + +#endif + +#ifndef NO_DES3 + {DES_CBC_TYPE, "DES-CBC"}, + {DES_ECB_TYPE, "DES-ECB"}, + + {DES_EDE3_CBC_TYPE, "DES-EDE3-CBC"}, + {DES_EDE3_ECB_TYPE, "DES-EDE3-ECB"}, +#endif + +#ifndef NO_RC4 + {ARC4_TYPE, "ARC4"}, +#endif + +#ifdef HAVE_IDEA + {IDEA_CBC_TYPE, "IDEA-CBC"}, +#endif + { 0, NULL} +}; + +const WOLFSSL_EVP_CIPHER *wolfSSL_EVP_get_cipherbyname(const char *name) +{ + + static const struct alias { + const char *name; + const char *alias; + } alias_tbl[] = + { +#ifndef NO_DES3 + {"DES-CBC", "DES"}, + {"DES-CBC", "des"}, + {"DES-ECB", "DES-ECB"}, + {"DES-ECB", "des-ecb"}, + {"DES-EDE3-CBC", "DES3"}, + {"DES-EDE3-CBC", "des3"}, + {"DES-EDE3-ECB", "DES-EDE3"}, + {"DES-EDE3-ECB", "des-ede3"}, + {"DES-EDE3-ECB", "des-ede3-ecb"}, +#endif +#ifdef HAVE_IDEA + {"IDEA-CBC", "IDEA"}, + {"IDEA-CBC", "idea"}, +#endif +#ifndef NO_AES + #ifdef HAVE_AES_CBC + #ifdef WOLFSSL_AES_128 + {"AES-128-CBC", "AES128-CBC"}, + {"AES-128-CBC", "aes128-cbc"}, + #endif + #ifdef WOLFSSL_AES_192 + {"AES-192-CBC", "AES192-CBC"}, + {"AES-192-CBC", "aes192-cbc"}, + #endif + #ifdef WOLFSSL_AES_256 + {"AES-256-CBC", "AES256-CBC"}, + {"AES-256-CBC", "aes256-cbc"}, + #endif + #endif + #ifdef WOLFSSL_AES_128 + {"AES-128-ECB", "AES128-ECB"}, + {"AES-128-ECB", "aes128-ecb"}, + #endif + #ifdef WOLFSSL_AES_192 + {"AES-192-ECB", "AES192-ECB"}, + {"AES-192-ECB", "aes192-ecb"}, + #endif + #ifdef WOLFSSL_AES_256 + {"AES-256-ECB", "AES256-ECB"}, + {"AES-256-EBC", "aes256-ecb"}, + #endif +#endif +#ifndef NO_RC4 + {"ARC4", "RC4"}, +#endif + { NULL, NULL} + }; + + const struct cipher *ent; + const struct alias *al; + + WOLFSSL_ENTER("EVP_get_cipherbyname"); + + for( al = alias_tbl; al->name != NULL; al++) + if(XSTRNCMP(name, al->alias, XSTRLEN(al->alias)+1) == 0) { + name = al->name; + break; + } + + for( ent = cipher_tbl; ent->name != NULL; ent++) + if(XSTRNCMP(name, ent->name, XSTRLEN(ent->name)+1) == 0) { + return (WOLFSSL_EVP_CIPHER *)ent->name; + } + + return NULL; +} + +/* + * return an EVP_CIPHER structure when cipher NID is passed. + * + * id cipher NID + * + * retrun WOLFSSL_EVP_CIPHER +*/ +const WOLFSSL_EVP_CIPHER *wolfSSL_EVP_get_cipherbynid(int id) +{ + WOLFSSL_ENTER("EVP_get_cipherbynid"); + + switch(id) { + +#if defined(OPENSSL_EXTRA) +#ifndef NO_AES + #ifdef HAVE_AES_CBC + #ifdef WOLFSSL_AES_128 + case NID_aes_128_cbc: + return wolfSSL_EVP_aes_128_cbc(); + #endif + #ifdef WOLFSSL_AES_192 + case NID_aes_192_cbc: + return wolfSSL_EVP_aes_192_cbc(); + #endif + #ifdef WOLFSSL_AES_256 + case NID_aes_256_cbc: + return wolfSSL_EVP_aes_256_cbc(); + #endif + #endif + #ifdef WOLFSSL_AES_COUNTER + #ifdef WOLFSSL_AES_128 + case NID_aes_128_ctr: + return wolfSSL_EVP_aes_128_ctr(); + #endif + #ifdef WOLFSSL_AES_192 + case NID_aes_192_ctr: + return wolfSSL_EVP_aes_192_ctr(); + #endif + #ifdef WOLFSSL_AES_256 + case NID_aes_256_ctr: + return wolfSSL_EVP_aes_256_ctr(); + #endif + #endif /* WOLFSSL_AES_COUNTER */ + #ifdef HAVE_AES_ECB + #ifdef WOLFSSL_AES_128 + case NID_aes_128_ecb: + return wolfSSL_EVP_aes_128_ecb(); + #endif + #ifdef WOLFSSL_AES_192 + case NID_aes_192_ecb: + return wolfSSL_EVP_aes_192_ecb(); + #endif + #ifdef WOLFSSL_AES_256 + case NID_aes_256_ecb: + return wolfSSL_EVP_aes_256_ecb(); + #endif + #endif /* HAVE_AES_ECB */ +#endif + +#ifndef NO_DES3 + case NID_des_cbc: + return wolfSSL_EVP_des_cbc(); +#ifdef WOLFSSL_DES_ECB + case NID_des_ecb: + return wolfSSL_EVP_des_ecb(); +#endif + case NID_des_ede3_cbc: + return wolfSSL_EVP_des_ede3_cbc(); +#ifdef WOLFSSL_DES_ECB + case NID_des_ede3_ecb: + return wolfSSL_EVP_des_ede3_ecb(); +#endif +#endif /*NO_DES3*/ + +#ifdef HAVE_IDEA + case NID_idea_cbc: + return wolfSSL_EVP_idea_cbc(); +#endif +#endif /*OPENSSL_EXTRA*/ + + default: + WOLFSSL_MSG("Bad cipher id value"); + } + + return NULL; +} + +#ifndef NO_AES + #ifdef HAVE_AES_CBC + #ifdef WOLFSSL_AES_128 + static char *EVP_AES_128_CBC; + #endif + #ifdef WOLFSSL_AES_192 + static char *EVP_AES_192_CBC; + #endif + #ifdef WOLFSSL_AES_256 + static char *EVP_AES_256_CBC; + #endif + #endif /* HAVE_AES_CBC */ +#if defined(OPENSSL_EXTRA) + #ifdef WOLFSSL_AES_128 + static char *EVP_AES_128_CTR; + #endif + #ifdef WOLFSSL_AES_192 + static char *EVP_AES_192_CTR; + #endif + #ifdef WOLFSSL_AES_256 + static char *EVP_AES_256_CTR; + #endif + + #ifdef WOLFSSL_AES_128 + static char *EVP_AES_128_ECB; + #endif + #ifdef WOLFSSL_AES_192 + static char *EVP_AES_192_ECB; + #endif + #ifdef WOLFSSL_AES_256 + static char *EVP_AES_256_ECB; + #endif + static const int EVP_AES_SIZE = 11; +#endif +#endif + +#ifndef NO_DES3 +static char *EVP_DES_CBC; +static char *EVP_DES_ECB; + +static char *EVP_DES_EDE3_CBC; +static char *EVP_DES_EDE3_ECB; + +#ifdef OPENSSL_EXTRA +static const int EVP_DES_SIZE = 7; +static const int EVP_DES_EDE3_SIZE = 12; +#endif + +#endif + +#ifdef HAVE_IDEA +static char *EVP_IDEA_CBC; +#if defined(OPENSSL_EXTRA) +static const int EVP_IDEA_SIZE = 8; +#endif +#endif + +void wolfSSL_EVP_init(void) +{ +#ifndef NO_AES + #ifdef HAVE_AES_CBC + #ifdef WOLFSSL_AES_128 + EVP_AES_128_CBC = (char *)EVP_get_cipherbyname("AES-128-CBC"); + #endif + #ifdef WOLFSSL_AES_192 + EVP_AES_192_CBC = (char *)EVP_get_cipherbyname("AES-192-CBC"); + #endif + #ifdef WOLFSSL_AES_256 + EVP_AES_256_CBC = (char *)EVP_get_cipherbyname("AES-256-CBC"); + #endif + #endif /* HAVE_AES_CBC */ + +#if defined(OPENSSL_EXTRA) + #ifdef WOLFSSL_AES_128 + EVP_AES_128_CTR = (char *)EVP_get_cipherbyname("AES-128-CTR"); + #endif + #ifdef WOLFSSL_AES_192 + EVP_AES_192_CTR = (char *)EVP_get_cipherbyname("AES-192-CTR"); + #endif + #ifdef WOLFSSL_AES_256 + EVP_AES_256_CTR = (char *)EVP_get_cipherbyname("AES-256-CTR"); + #endif + + #ifdef WOLFSSL_AES_128 + EVP_AES_128_ECB = (char *)EVP_get_cipherbyname("AES-128-ECB"); + #endif + #ifdef WOLFSSL_AES_192 + EVP_AES_192_ECB = (char *)EVP_get_cipherbyname("AES-192-ECB"); + #endif + #ifdef WOLFSSL_AES_256 + EVP_AES_256_ECB = (char *)EVP_get_cipherbyname("AES-256-ECB"); + #endif +#endif +#endif + +#ifndef NO_DES3 + EVP_DES_CBC = (char *)EVP_get_cipherbyname("DES-CBC"); + EVP_DES_ECB = (char *)EVP_get_cipherbyname("DES-ECB"); + + EVP_DES_EDE3_CBC = (char *)EVP_get_cipherbyname("DES-EDE3-CBC"); + EVP_DES_EDE3_ECB = (char *)EVP_get_cipherbyname("DES-EDE3-ECB"); +#endif + +#ifdef HAVE_IDEA + EVP_IDEA_CBC = (char *)EVP_get_cipherbyname("IDEA-CBC"); +#endif +} + +#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL || HAVE_WEBSERVER */ + + +#if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM) + +void wolfSSL_ERR_print_errors_fp(XFILE fp, int err) +{ + char data[WOLFSSL_MAX_ERROR_SZ + 1]; + + WOLFSSL_ENTER("wolfSSL_ERR_print_errors_fp"); + SetErrorString(err, data); + fprintf(fp, "%s", data); +} + +#if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) +void wolfSSL_ERR_dump_errors_fp(XFILE fp) +{ + wc_ERR_print_errors_fp(fp); +} +#endif +#endif + + +int wolfSSL_pending(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("SSL_pending"); + return ssl->buffers.clearOutputBuffer.length; +} + + +#ifndef WOLFSSL_LEANPSK +/* turn on handshake group messages for context */ +int wolfSSL_CTX_set_group_messages(WOLFSSL_CTX* ctx) +{ + if (ctx == NULL) + return BAD_FUNC_ARG; + + ctx->groupMessages = 1; + + return WOLFSSL_SUCCESS; +} +#endif + + +#ifndef NO_WOLFSSL_CLIENT +/* connect enough to get peer cert chain */ +int wolfSSL_connect_cert(WOLFSSL* ssl) +{ + int ret; + + if (ssl == NULL) + return WOLFSSL_FAILURE; + + ssl->options.certOnly = 1; + ret = wolfSSL_connect(ssl); + ssl->options.certOnly = 0; + + return ret; +} +#endif + + +#ifndef WOLFSSL_LEANPSK +/* turn on handshake group messages for ssl object */ +int wolfSSL_set_group_messages(WOLFSSL* ssl) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + + ssl->options.groupMessages = 1; + + return WOLFSSL_SUCCESS; +} + + +/* make minVersion the internal equivalent SSL version */ +static int SetMinVersionHelper(byte* minVersion, int version) +{ +#ifdef NO_TLS + (void)minVersion; +#endif + + switch (version) { +#if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS) + case WOLFSSL_SSLV3: + *minVersion = SSLv3_MINOR; + break; +#endif + +#ifndef NO_TLS + #ifndef NO_OLD_TLS + case WOLFSSL_TLSV1: + *minVersion = TLSv1_MINOR; + break; + + case WOLFSSL_TLSV1_1: + *minVersion = TLSv1_1_MINOR; + break; + #endif + #ifndef WOLFSSL_NO_TLS12 + case WOLFSSL_TLSV1_2: + *minVersion = TLSv1_2_MINOR; + break; + #endif +#endif + #ifdef WOLFSSL_TLS13 + case WOLFSSL_TLSV1_3: + *minVersion = TLSv1_3_MINOR; + break; + #endif + + default: + WOLFSSL_MSG("Bad function argument"); + return BAD_FUNC_ARG; + } + + return WOLFSSL_SUCCESS; +} + + +/* Set minimum downgrade version allowed, WOLFSSL_SUCCESS on ok */ +int wolfSSL_CTX_SetMinVersion(WOLFSSL_CTX* ctx, int version) +{ + WOLFSSL_ENTER("wolfSSL_CTX_SetMinVersion"); + + if (ctx == NULL) { + WOLFSSL_MSG("Bad function argument"); + return BAD_FUNC_ARG; + } + + return SetMinVersionHelper(&ctx->minDowngrade, version); +} + + +/* Set minimum downgrade version allowed, WOLFSSL_SUCCESS on ok */ +int wolfSSL_SetMinVersion(WOLFSSL* ssl, int version) +{ + WOLFSSL_ENTER("wolfSSL_SetMinVersion"); + + if (ssl == NULL) { + WOLFSSL_MSG("Bad function argument"); + return BAD_FUNC_ARG; + } + + return SetMinVersionHelper(&ssl->options.minDowngrade, version); +} + + +/* Function to get version as WOLFSSL_ enum value for wolfSSL_SetVersion */ +int wolfSSL_GetVersion(WOLFSSL* ssl) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + + if (ssl->version.major == SSLv3_MAJOR) { + switch (ssl->version.minor) { + case SSLv3_MINOR : + return WOLFSSL_SSLV3; + case TLSv1_MINOR : + return WOLFSSL_TLSV1; + case TLSv1_1_MINOR : + return WOLFSSL_TLSV1_1; + case TLSv1_2_MINOR : + return WOLFSSL_TLSV1_2; + case TLSv1_3_MINOR : + return WOLFSSL_TLSV1_3; + default: + break; + } + } + + return VERSION_ERROR; +} + +int wolfSSL_SetVersion(WOLFSSL* ssl, int version) +{ + word16 haveRSA = 1; + word16 havePSK = 0; + int keySz = 0; + + WOLFSSL_ENTER("wolfSSL_SetVersion"); + + if (ssl == NULL) { + WOLFSSL_MSG("Bad function argument"); + return BAD_FUNC_ARG; + } + + switch (version) { +#if defined(WOLFSSL_ALLOW_SSLV3) && !defined(NO_OLD_TLS) + case WOLFSSL_SSLV3: + ssl->version = MakeSSLv3(); + break; +#endif + +#ifndef NO_TLS + #ifndef NO_OLD_TLS + #ifdef WOLFSSL_ALLOW_TLSV10 + case WOLFSSL_TLSV1: + ssl->version = MakeTLSv1(); + break; + #endif + + case WOLFSSL_TLSV1_1: + ssl->version = MakeTLSv1_1(); + break; + #endif + #ifndef WOLFSSL_NO_TLS12 + case WOLFSSL_TLSV1_2: + ssl->version = MakeTLSv1_2(); + break; + #endif +#endif +#ifdef WOLFSSL_TLS13 + case WOLFSSL_TLSV1_3: + ssl->version = MakeTLSv1_3(); + break; + +#endif + + default: + WOLFSSL_MSG("Bad function argument"); + return BAD_FUNC_ARG; + } + + #ifdef NO_RSA + haveRSA = 0; + #endif + #ifndef NO_PSK + havePSK = ssl->options.havePSK; + #endif + #ifndef NO_CERTS + keySz = ssl->buffers.keySz; + #endif + + InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK, + ssl->options.haveDH, ssl->options.haveNTRU, + ssl->options.haveECDSAsig, ssl->options.haveECC, + ssl->options.haveStaticECC, ssl->options.side); + + return WOLFSSL_SUCCESS; +} +#endif /* !leanpsk */ + + +#if !defined(NO_CERTS) || !defined(NO_SESSION_CACHE) + +/* Make a work from the front of random hash */ +static WC_INLINE word32 MakeWordFromHash(const byte* hashID) +{ + return ((word32)hashID[0] << 24) | ((word32)hashID[1] << 16) | + (hashID[2] << 8) | hashID[3]; +} + +#endif /* !NO_CERTS || !NO_SESSION_CACHE */ + + +#ifndef NO_CERTS + +/* hash is the SHA digest of name, just use first 32 bits as hash */ +static WC_INLINE word32 HashSigner(const byte* hash) +{ + return MakeWordFromHash(hash) % CA_TABLE_SIZE; +} + + +/* does CA already exist on signer list */ +int AlreadySigner(WOLFSSL_CERT_MANAGER* cm, byte* hash) +{ + Signer* signers; + int ret = 0; + word32 row; + + if (cm == NULL || hash == NULL) { + return ret; + } + + row = HashSigner(hash); + + if (wc_LockMutex(&cm->caLock) != 0) { + return ret; + } + signers = cm->caTable[row]; + while (signers) { + byte* subjectHash; + + #ifndef NO_SKID + subjectHash = signers->subjectKeyIdHash; + #else + subjectHash = signers->subjectNameHash; + #endif + + if (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0) { + ret = 1; /* success */ + break; + } + signers = signers->next; + } + wc_UnLockMutex(&cm->caLock); + + return ret; +} + + +#ifdef WOLFSSL_TRUST_PEER_CERT +/* hash is the SHA digest of name, just use first 32 bits as hash */ +static WC_INLINE word32 TrustedPeerHashSigner(const byte* hash) +{ + return MakeWordFromHash(hash) % TP_TABLE_SIZE; +} + +/* does trusted peer already exist on signer list */ +int AlreadyTrustedPeer(WOLFSSL_CERT_MANAGER* cm, byte* hash) +{ + TrustedPeerCert* tp; + int ret = 0; + word32 row = TrustedPeerHashSigner(hash); + + if (wc_LockMutex(&cm->tpLock) != 0) + return ret; + tp = cm->tpTable[row]; + while (tp) { + byte* subjectHash; + #ifndef NO_SKID + subjectHash = tp->subjectKeyIdHash; + #else + subjectHash = tp->subjectNameHash; + #endif + if (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0) { + ret = 1; + break; + } + tp = tp->next; + } + wc_UnLockMutex(&cm->tpLock); + + return ret; +} + + +/* return Trusted Peer if found, otherwise NULL + type is what to match on + */ +TrustedPeerCert* GetTrustedPeer(void* vp, byte* hash, int type) +{ + WOLFSSL_CERT_MANAGER* cm = (WOLFSSL_CERT_MANAGER*)vp; + TrustedPeerCert* ret = NULL; + TrustedPeerCert* tp = NULL; + word32 row; + + if (cm == NULL || hash == NULL) + return NULL; + + row = TrustedPeerHashSigner(hash); + + if (wc_LockMutex(&cm->tpLock) != 0) + return ret; + + tp = cm->tpTable[row]; + while (tp) { + byte* subjectHash; + switch (type) { + #ifndef NO_SKID + case WC_MATCH_SKID: + subjectHash = tp->subjectKeyIdHash; + break; + #endif + case WC_MATCH_NAME: + subjectHash = tp->subjectNameHash; + break; + default: + WOLFSSL_MSG("Unknown search type"); + wc_UnLockMutex(&cm->tpLock); + return NULL; + } + if (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0) { + ret = tp; + break; + } + tp = tp->next; + } + wc_UnLockMutex(&cm->tpLock); + + return ret; +} + + +int MatchTrustedPeer(TrustedPeerCert* tp, DecodedCert* cert) +{ + if (tp == NULL || cert == NULL) + return BAD_FUNC_ARG; + + /* subject key id or subject hash has been compared when searching + tpTable for the cert from function GetTrustedPeer */ + + /* compare signatures */ + if (tp->sigLen == cert->sigLength) { + if (XMEMCMP(tp->sig, cert->signature, cert->sigLength)) { + return WOLFSSL_FAILURE; + } + } + else { + return WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; +} +#endif /* WOLFSSL_TRUST_PEER_CERT */ + + +/* return CA if found, otherwise NULL */ +Signer* GetCA(void* vp, byte* hash) +{ + WOLFSSL_CERT_MANAGER* cm = (WOLFSSL_CERT_MANAGER*)vp; + Signer* ret = NULL; + Signer* signers; + word32 row = HashSigner(hash); + + if (cm == NULL) + return NULL; + + if (wc_LockMutex(&cm->caLock) != 0) + return ret; + + signers = cm->caTable[row]; + while (signers) { + byte* subjectHash; + #ifndef NO_SKID + subjectHash = signers->subjectKeyIdHash; + #else + subjectHash = signers->subjectNameHash; + #endif + if (XMEMCMP(hash, subjectHash, SIGNER_DIGEST_SIZE) == 0) { + ret = signers; + break; + } + signers = signers->next; + } + wc_UnLockMutex(&cm->caLock); + + return ret; +} + + +#ifndef NO_SKID +/* return CA if found, otherwise NULL. Walk through hash table. */ +Signer* GetCAByName(void* vp, byte* hash) +{ + WOLFSSL_CERT_MANAGER* cm = (WOLFSSL_CERT_MANAGER*)vp; + Signer* ret = NULL; + Signer* signers; + word32 row; + + if (cm == NULL) + return NULL; + + if (wc_LockMutex(&cm->caLock) != 0) + return ret; + + for (row = 0; row < CA_TABLE_SIZE && ret == NULL; row++) { + signers = cm->caTable[row]; + while (signers && ret == NULL) { + if (XMEMCMP(hash, signers->subjectNameHash, + SIGNER_DIGEST_SIZE) == 0) { + ret = signers; + } + signers = signers->next; + } + } + wc_UnLockMutex(&cm->caLock); + + return ret; +} +#endif + + +#ifdef WOLFSSL_TRUST_PEER_CERT +/* add a trusted peer cert to linked list */ +int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int verify) +{ + int ret, row; + TrustedPeerCert* peerCert; + DecodedCert* cert = NULL; + DerBuffer* der = *pDer; + byte* subjectHash = NULL; + + WOLFSSL_MSG("Adding a Trusted Peer Cert"); + + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), cm->heap, + DYNAMIC_TYPE_DCERT); + if (cert == NULL) + return MEMORY_E; + + InitDecodedCert(cert, der->buffer, der->length, cm->heap); + if ((ret = ParseCert(cert, TRUSTED_PEER_TYPE, verify, cm)) != 0) { + XFREE(cert, NULL, DYNAMIC_TYPE_DCERT); + return ret; + } + WOLFSSL_MSG("\tParsed new trusted peer cert"); + + peerCert = (TrustedPeerCert*)XMALLOC(sizeof(TrustedPeerCert), cm->heap, + DYNAMIC_TYPE_CERT); + if (peerCert == NULL) { + FreeDecodedCert(cert); + XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT); + return MEMORY_E; + } + XMEMSET(peerCert, 0, sizeof(TrustedPeerCert)); + +#ifndef NO_SKID + if (cert->extAuthKeyIdSet) { + subjectHash = cert->extSubjKeyId; + } + else { + subjectHash = cert->subjectHash; + } +#else + subjectHash = cert->subjectHash; +#endif + + #ifndef IGNORE_NAME_CONSTRAINTS + if (peerCert->permittedNames) + FreeNameSubtrees(peerCert->permittedNames, cm->heap); + if (peerCert->excludedNames) + FreeNameSubtrees(peerCert->excludedNames, cm->heap); + #endif + + if (AlreadyTrustedPeer(cm, subjectHash)) { + WOLFSSL_MSG("\tAlready have this CA, not adding again"); + (void)ret; + } + else { + /* add trusted peer signature */ + peerCert->sigLen = cert->sigLength; + peerCert->sig = XMALLOC(cert->sigLength, cm->heap, + DYNAMIC_TYPE_SIGNATURE); + if (peerCert->sig == NULL) { + FreeDecodedCert(cert); + XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT); + FreeTrustedPeer(peerCert, cm->heap); + return MEMORY_E; + } + XMEMCPY(peerCert->sig, cert->signature, cert->sigLength); + + /* add trusted peer name */ + peerCert->nameLen = cert->subjectCNLen; + peerCert->name = cert->subjectCN; + #ifndef IGNORE_NAME_CONSTRAINTS + peerCert->permittedNames = cert->permittedNames; + peerCert->excludedNames = cert->excludedNames; + #endif + + /* add SKID when available and hash of name */ + #ifndef NO_SKID + XMEMCPY(peerCert->subjectKeyIdHash, cert->extSubjKeyId, + SIGNER_DIGEST_SIZE); + #endif + XMEMCPY(peerCert->subjectNameHash, cert->subjectHash, + SIGNER_DIGEST_SIZE); + peerCert->next = NULL; /* If Key Usage not set, all uses valid. */ + cert->subjectCN = 0; + #ifndef IGNORE_NAME_CONSTRAINTS + cert->permittedNames = NULL; + cert->excludedNames = NULL; + #endif + + #ifndef NO_SKID + if (cert->extAuthKeyIdSet) { + row = TrustedPeerHashSigner(peerCert->subjectKeyIdHash); + } + else { + row = TrustedPeerHashSigner(peerCert->subjectNameHash); + } + #else + row = TrustedPeerHashSigner(peerCert->subjectNameHash); + #endif + + if (wc_LockMutex(&cm->tpLock) == 0) { + peerCert->next = cm->tpTable[row]; + cm->tpTable[row] = peerCert; /* takes ownership */ + wc_UnLockMutex(&cm->tpLock); + } + else { + WOLFSSL_MSG("\tTrusted Peer Cert Mutex Lock failed"); + FreeDecodedCert(cert); + XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT); + FreeTrustedPeer(peerCert, cm->heap); + return BAD_MUTEX_E; + } + } + + WOLFSSL_MSG("\tFreeing parsed trusted peer cert"); + FreeDecodedCert(cert); + XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT); + WOLFSSL_MSG("\tFreeing der trusted peer cert"); + FreeDer(&der); + WOLFSSL_MSG("\t\tOK Freeing der trusted peer cert"); + WOLFSSL_LEAVE("AddTrustedPeer", ret); + + return WOLFSSL_SUCCESS; +} +#endif /* WOLFSSL_TRUST_PEER_CERT */ + + +/* owns der, internal now uses too */ +/* type flag ids from user or from chain received during verify + don't allow chain ones to be added w/o isCA extension */ +int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify) +{ + int ret; + Signer* signer = NULL; + word32 row; + byte* subjectHash; +#ifdef WOLFSSL_SMALL_STACK + DecodedCert* cert = NULL; +#else + DecodedCert cert[1]; +#endif + DerBuffer* der = *pDer; + + WOLFSSL_MSG("Adding a CA"); + + if (cm == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_SMALL_STACK + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, + DYNAMIC_TYPE_DCERT); + if (cert == NULL) + return MEMORY_E; +#endif + + InitDecodedCert(cert, der->buffer, der->length, cm->heap); + ret = ParseCert(cert, CA_TYPE, verify, cm); + WOLFSSL_MSG("\tParsed new CA"); + +#ifndef NO_SKID + subjectHash = cert->extSubjKeyId; +#else + subjectHash = cert->subjectHash; +#endif + + /* check CA key size */ + if (verify) { + switch (cert->keyOID) { + #ifndef NO_RSA + case RSAk: + if (cm->minRsaKeySz < 0 || + cert->pubKeySize < (word16)cm->minRsaKeySz) { + ret = RSA_KEY_SIZE_E; + WOLFSSL_MSG("\tCA RSA key size error"); + } + break; + #endif /* !NO_RSA */ + #ifdef HAVE_ECC + case ECDSAk: + if (cm->minEccKeySz < 0 || + cert->pubKeySize < (word16)cm->minEccKeySz) { + ret = ECC_KEY_SIZE_E; + WOLFSSL_MSG("\tCA ECC key size error"); + } + break; + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ED25519k: + if (cm->minEccKeySz < 0 || + ED25519_KEY_SIZE < (word16)cm->minEccKeySz) { + ret = ECC_KEY_SIZE_E; + WOLFSSL_MSG("\tCA ECC key size error"); + } + break; + #endif /* HAVE_ED25519 */ + + default: + WOLFSSL_MSG("\tNo key size check done on CA"); + break; /* no size check if key type is not in switch */ + } + } + + if (ret == 0 && cert->isCA == 0 && type != WOLFSSL_USER_CA) { + WOLFSSL_MSG("\tCan't add as CA if not actually one"); + ret = NOT_CA_ERROR; + } +#ifndef ALLOW_INVALID_CERTSIGN + else if (ret == 0 && cert->isCA == 1 && type != WOLFSSL_USER_CA && + (cert->extKeyUsage & KEYUSE_KEY_CERT_SIGN) == 0) { + /* Intermediate CA certs are required to have the keyCertSign + * extension set. User loaded root certs are not. */ + WOLFSSL_MSG("\tDoesn't have key usage certificate signing"); + ret = NOT_CA_ERROR; + } +#endif + else if (ret == 0 && AlreadySigner(cm, subjectHash)) { + WOLFSSL_MSG("\tAlready have this CA, not adding again"); + (void)ret; + } + else if (ret == 0) { + /* take over signer parts */ + signer = MakeSigner(cm->heap); + if (!signer) + ret = MEMORY_ERROR; + } + if (ret == 0 && signer != NULL) { + #ifdef WOLFSSL_SIGNER_DER_CERT + ret = AllocDer(&signer->derCert, der->length, der->type, NULL); + } + if (ret == 0 && signer != NULL) { + XMEMCPY(signer->derCert->buffer, der->buffer, der->length); + #endif + signer->keyOID = cert->keyOID; + if (cert->pubKeyStored) { + signer->publicKey = cert->publicKey; + signer->pubKeySize = cert->pubKeySize; + } + if (cert->subjectCNStored) { + signer->nameLen = cert->subjectCNLen; + signer->name = cert->subjectCN; + } + signer->pathLength = cert->pathLength; + signer->pathLengthSet = cert->pathLengthSet; + signer->selfSigned = cert->selfSigned; + #ifndef IGNORE_NAME_CONSTRAINTS + signer->permittedNames = cert->permittedNames; + signer->excludedNames = cert->excludedNames; + #endif + #ifndef NO_SKID + XMEMCPY(signer->subjectKeyIdHash, cert->extSubjKeyId, + SIGNER_DIGEST_SIZE); + #endif + XMEMCPY(signer->subjectNameHash, cert->subjectHash, + SIGNER_DIGEST_SIZE); + #ifdef HAVE_OCSP + XMEMCPY(signer->subjectKeyHash, cert->subjectKeyHash, + KEYID_SIZE); + #endif + signer->keyUsage = cert->extKeyUsageSet ? cert->extKeyUsage + : 0xFFFF; + signer->next = NULL; /* If Key Usage not set, all uses valid. */ + cert->publicKey = 0; /* in case lock fails don't free here. */ + cert->subjectCN = 0; + #ifndef IGNORE_NAME_CONSTRAINTS + cert->permittedNames = NULL; + cert->excludedNames = NULL; + #endif + + #ifndef NO_SKID + row = HashSigner(signer->subjectKeyIdHash); + #else + row = HashSigner(signer->subjectNameHash); + #endif + + if (wc_LockMutex(&cm->caLock) == 0) { + signer->next = cm->caTable[row]; + cm->caTable[row] = signer; /* takes ownership */ + wc_UnLockMutex(&cm->caLock); + if (cm->caCacheCallback) + cm->caCacheCallback(der->buffer, (int)der->length, type); + } + else { + WOLFSSL_MSG("\tCA Mutex Lock failed"); + ret = BAD_MUTEX_E; + FreeSigner(signer, cm->heap); + } + } + + WOLFSSL_MSG("\tFreeing Parsed CA"); + FreeDecodedCert(cert); +#ifdef WOLFSSL_SMALL_STACK + XFREE(cert, NULL, DYNAMIC_TYPE_DCERT); +#endif + WOLFSSL_MSG("\tFreeing der CA"); + FreeDer(pDer); + WOLFSSL_MSG("\t\tOK Freeing der CA"); + + WOLFSSL_LEAVE("AddCA", ret); + + return ret == 0 ? WOLFSSL_SUCCESS : ret; +} + +#endif /* !NO_CERTS */ + + +#ifndef NO_SESSION_CACHE + + /* basic config gives a cache with 33 sessions, adequate for clients and + embedded servers + + MEDIUM_SESSION_CACHE allows 1055 sessions, adequate for servers that + aren't under heavy load, basically allows 200 new sessions per minute + + BIG_SESSION_CACHE yields 20,027 sessions + + HUGE_SESSION_CACHE yields 65,791 sessions, for servers under heavy load, + allows over 13,000 new sessions per minute or over 200 new sessions per + second + + SMALL_SESSION_CACHE only stores 6 sessions, good for embedded clients + or systems where the default of nearly 3kB is too much RAM, this define + uses less than 500 bytes RAM + + default SESSION_CACHE stores 33 sessions (no XXX_SESSION_CACHE defined) + */ + #ifdef HUGE_SESSION_CACHE + #define SESSIONS_PER_ROW 11 + #define SESSION_ROWS 5981 + #elif defined(BIG_SESSION_CACHE) + #define SESSIONS_PER_ROW 7 + #define SESSION_ROWS 2861 + #elif defined(MEDIUM_SESSION_CACHE) + #define SESSIONS_PER_ROW 5 + #define SESSION_ROWS 211 + #elif defined(SMALL_SESSION_CACHE) + #define SESSIONS_PER_ROW 2 + #define SESSION_ROWS 3 + #else + #define SESSIONS_PER_ROW 3 + #define SESSION_ROWS 11 + #endif + + typedef struct SessionRow { + int nextIdx; /* where to place next one */ + int totalCount; /* sessions ever on this row */ + WOLFSSL_SESSION Sessions[SESSIONS_PER_ROW]; + } SessionRow; + + static SessionRow SessionCache[SESSION_ROWS]; + + #if defined(WOLFSSL_SESSION_STATS) && defined(WOLFSSL_PEAK_SESSIONS) + static word32 PeakSessions; + #endif + + static wolfSSL_Mutex session_mutex; /* SessionCache mutex */ + + #ifndef NO_CLIENT_CACHE + + typedef struct ClientSession { + word16 serverRow; /* SessionCache Row id */ + word16 serverIdx; /* SessionCache Idx (column) */ + } ClientSession; + + typedef struct ClientRow { + int nextIdx; /* where to place next one */ + int totalCount; /* sessions ever on this row */ + ClientSession Clients[SESSIONS_PER_ROW]; + } ClientRow; + + static ClientRow ClientCache[SESSION_ROWS]; /* Client Cache */ + /* uses session mutex */ + #endif /* NO_CLIENT_CACHE */ + +#endif /* NO_SESSION_CACHE */ + +int wolfSSL_Init(void) +{ + WOLFSSL_ENTER("wolfSSL_Init"); + + if (initRefCount == 0) { + /* Initialize crypto for use with TLS connection */ + if (wolfCrypt_Init() != 0) { + WOLFSSL_MSG("Bad wolfCrypt Init"); + return WC_INIT_E; + } + +#ifdef OPENSSL_EXTRA + if (wolfSSL_RAND_seed(NULL, 0) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_RAND_Seed failed"); + return WC_INIT_E; + } +#endif + +#ifndef NO_SESSION_CACHE + if (wc_InitMutex(&session_mutex) != 0) { + WOLFSSL_MSG("Bad Init Mutex session"); + return BAD_MUTEX_E; + } +#endif + if (wc_InitMutex(&count_mutex) != 0) { + WOLFSSL_MSG("Bad Init Mutex count"); + return BAD_MUTEX_E; + } + } + + if (wc_LockMutex(&count_mutex) != 0) { + WOLFSSL_MSG("Bad Lock Mutex count"); + return BAD_MUTEX_E; + } + + initRefCount++; + wc_UnLockMutex(&count_mutex); + + return WOLFSSL_SUCCESS; +} + + + +#ifndef NO_CERTS + +/* process user cert chain to pass during the handshake */ +static int ProcessUserChain(WOLFSSL_CTX* ctx, const unsigned char* buff, + long sz, int format, int type, WOLFSSL* ssl, + long* used, EncryptedInfo* info) +{ + int ret = 0; + void* heap = wolfSSL_CTX_GetHeap(ctx, ssl); +#ifdef WOLFSSL_TLS13 + int cnt = 0; +#endif + + if ((type == CA_TYPE) && (ctx == NULL)) { + WOLFSSL_MSG("Need context for CA load"); + return BAD_FUNC_ARG; + } + + /* we may have a user cert chain, try to consume */ + if ((type == CERT_TYPE || type == CA_TYPE) && (info->consumed < sz)) { + #ifdef WOLFSSL_SMALL_STACK + byte staticBuffer[1]; /* force heap usage */ + #else + byte staticBuffer[FILE_BUFFER_SIZE]; /* tmp chain buffer */ + #endif + byte* chainBuffer = staticBuffer; + int dynamicBuffer = 0; + word32 bufferSz; + long consumed = info->consumed; + word32 idx = 0; + int gotOne = 0; + + /* Calculate max possible size, including max headers */ + bufferSz = (word32)(sz - consumed) + (CERT_HEADER_SZ * MAX_CHAIN_DEPTH); + if (bufferSz > sizeof(staticBuffer)) { + WOLFSSL_MSG("Growing Tmp Chain Buffer"); + /* will shrink to actual size */ + chainBuffer = (byte*)XMALLOC(bufferSz, heap, DYNAMIC_TYPE_FILE); + if (chainBuffer == NULL) { + return MEMORY_E; + } + dynamicBuffer = 1; + } + + WOLFSSL_MSG("Processing Cert Chain"); + while (consumed < sz) { + DerBuffer* part = NULL; + word32 remain = (word32)(sz - consumed); + info->consumed = 0; + + if (format == WOLFSSL_FILETYPE_PEM) { + #ifdef WOLFSSL_PEM_TO_DER + ret = PemToDer(buff + consumed, remain, type, &part, + heap, info, NULL); + #else + ret = NOT_COMPILED_IN; + #endif + } + else { + int length = remain; + if (format == WOLFSSL_FILETYPE_ASN1) { + /* get length of der (read sequence) */ + word32 inOutIdx = 0; + if (GetSequence(buff + consumed, &inOutIdx, &length, + remain) < 0) { + ret = ASN_NO_PEM_HEADER; + } + length += inOutIdx; /* include leading sequence */ + } + info->consumed = length; + if (ret == 0) { + ret = AllocDer(&part, length, type, heap); + if (ret == 0) { + XMEMCPY(part->buffer, buff + consumed, length); + } + } + } + if (ret == 0) { + gotOne = 1; +#ifdef WOLFSSL_TLS13 + cnt++; +#endif + if ((idx + part->length + CERT_HEADER_SZ) > bufferSz) { + WOLFSSL_MSG(" Cert Chain bigger than buffer"); + ret = BUFFER_E; + } + else { + c32to24(part->length, &chainBuffer[idx]); + idx += CERT_HEADER_SZ; + XMEMCPY(&chainBuffer[idx], part->buffer, part->length); + idx += part->length; + consumed += info->consumed; + if (used) + *used += info->consumed; + } + + /* add CA's to certificate manager */ + if (type == CA_TYPE) { + /* verify CA unless user set to no verify */ + ret = AddCA(ctx->cm, &part, WOLFSSL_USER_CA, + !ctx->verifyNone); + gotOne = 0; /* don't exit loop for CA type */ + } + } + + FreeDer(&part); + + if (ret == ASN_NO_PEM_HEADER && gotOne) { + WOLFSSL_MSG("We got one good cert, so stuff at end ok"); + break; + } + + if (ret < 0) { + WOLFSSL_MSG(" Error in Cert in Chain"); + if (dynamicBuffer) + XFREE(chainBuffer, heap, DYNAMIC_TYPE_FILE); + return ret; + } + WOLFSSL_MSG(" Consumed another Cert in Chain"); + } + WOLFSSL_MSG("Finished Processing Cert Chain"); + + /* only retain actual size used */ + ret = 0; + if (idx > 0) { + if (ssl) { + if (ssl->buffers.weOwnCertChain) { + FreeDer(&ssl->buffers.certChain); + } + ret = AllocDer(&ssl->buffers.certChain, idx, type, heap); + if (ret == 0) { + XMEMCPY(ssl->buffers.certChain->buffer, chainBuffer, + idx); + ssl->buffers.weOwnCertChain = 1; + } + #ifdef WOLFSSL_TLS13 + ssl->buffers.certChainCnt = cnt; + #endif + } else if (ctx) { + FreeDer(&ctx->certChain); + ret = AllocDer(&ctx->certChain, idx, type, heap); + if (ret == 0) { + XMEMCPY(ctx->certChain->buffer, chainBuffer, idx); + } + #ifdef WOLFSSL_TLS13 + ctx->certChainCnt = cnt; + #endif + } + } + + if (dynamicBuffer) + XFREE(chainBuffer, heap, DYNAMIC_TYPE_FILE); + } + + return ret; +} +/* process the buffer buff, length sz, into ctx of format and type + used tracks bytes consumed, userChain specifies a user cert chain + to pass during the handshake */ +int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, + long sz, int format, int type, WOLFSSL* ssl, + long* used, int userChain) +{ + DerBuffer* der = NULL; /* holds DER or RAW (for NTRU) */ + int ret = 0; + int eccKey = 0; + int ed25519Key = 0; + int rsaKey = 0; + int resetSuites = 0; + void* heap = wolfSSL_CTX_GetHeap(ctx, ssl); + int devId = wolfSSL_CTX_GetDevId(ctx, ssl); + word32 idx = 0; + int keySz = 0; +#ifdef WOLFSSL_SMALL_STACK + EncryptedInfo* info = NULL; +#else + EncryptedInfo info[1]; +#endif + + (void)rsaKey; + (void)devId; + (void)idx; + (void)keySz; + + if (used) + *used = sz; /* used bytes default to sz, PEM chain may shorten*/ + + /* check args */ + if (format != WOLFSSL_FILETYPE_ASN1 && format != WOLFSSL_FILETYPE_PEM + && format != WOLFSSL_FILETYPE_RAW) + return WOLFSSL_BAD_FILETYPE; + + if (ctx == NULL && ssl == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_SMALL_STACK + info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), heap, + DYNAMIC_TYPE_ENCRYPTEDINFO); + if (info == NULL) + return MEMORY_E; +#endif + + XMEMSET(info, 0, sizeof(EncryptedInfo)); +#ifdef WOLFSSL_ENCRYPTED_KEYS + if (ctx) { + info->passwd_cb = ctx->passwd_cb; + info->passwd_userdata = ctx->passwd_userdata; + } +#endif + + if (format == WOLFSSL_FILETYPE_PEM) { + #ifdef WOLFSSL_PEM_TO_DER + ret = PemToDer(buff, sz, type, &der, heap, info, &eccKey); + #else + ret = NOT_COMPILED_IN; + #endif + } + else { + /* ASN1 (DER) or RAW (NTRU) */ + int length = (int)sz; + if (format == WOLFSSL_FILETYPE_ASN1) { + /* get length of der (read sequence) */ + word32 inOutIdx = 0; + if (GetSequence(buff, &inOutIdx, &length, (word32)sz) < 0) { + ret = ASN_PARSE_E; + } + length += inOutIdx; /* include leading sequence */ + } + + info->consumed = length; + + if (ret == 0) { + ret = AllocDer(&der, (word32)length, type, heap); + if (ret == 0) { + XMEMCPY(der->buffer, buff, length); + } + } + } + + if (used) { + *used = info->consumed; + } + + /* process user chain */ + if (ret >= 0) { + /* Chain should have server cert first, then intermediates, then root. + * First certificate in chain is processed below after ProcessUserChain + * and is loaded into ssl->buffers.certificate. + * Remainder are processed using ProcessUserChain and are loaded into + * ssl->buffers.certChain. */ + if (userChain) { + ret = ProcessUserChain(ctx, buff, sz, format, type, ssl, used, info); + } + } + +#ifdef WOLFSSL_ENCRYPTED_KEYS + /* for WOLFSSL_FILETYPE_PEM, PemToDer manage the decryption if required */ + if (ret >= 0 && info->set && format != WOLFSSL_FILETYPE_PEM) { + /* decrypt */ + int passwordSz = NAME_SZ; +#ifdef WOLFSSL_SMALL_STACK + char* password = NULL; +#else + char password[NAME_SZ]; +#endif + + #ifdef WOLFSSL_SMALL_STACK + password = (char*)XMALLOC(passwordSz, heap, DYNAMIC_TYPE_STRING); + if (password == NULL) + ret = MEMORY_E; + else + #endif + if (info->passwd_cb == NULL) { + WOLFSSL_MSG("No password callback set"); + ret = NO_PASSWORD; + } + else { + ret = info->passwd_cb(password, passwordSz, PEM_PASS_READ, + info->passwd_userdata); + if (ret >= 0) { + passwordSz = ret; + + /* decrypt the key */ + ret = wc_BufferKeyDecrypt(info, der->buffer, der->length, + (byte*)password, passwordSz, WC_MD5); + + ForceZero(password, passwordSz); + } + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(password, heap, DYNAMIC_TYPE_STRING); + #endif + } +#endif /* WOLFSSL_ENCRYPTED_KEYS */ + +#ifdef WOLFSSL_SMALL_STACK + XFREE(info, heap, DYNAMIC_TYPE_ENCRYPTEDINFO); +#endif + + /* check for error */ + if (ret < 0) { + FreeDer(&der); + return ret; + } + + /* Handle DER owner */ + if (type == CA_TYPE) { + if (ctx == NULL) { + WOLFSSL_MSG("Need context for CA load"); + FreeDer(&der); + return BAD_FUNC_ARG; + } + /* verify CA unless user set to no verify */ + return AddCA(ctx->cm, &der, WOLFSSL_USER_CA, !ctx->verifyNone); + } +#ifdef WOLFSSL_TRUST_PEER_CERT + else if (type == TRUSTED_PEER_TYPE) { + if (ctx == NULL) { + WOLFSSL_MSG("Need context for trusted peer cert load"); + FreeDer(&der); + return BAD_FUNC_ARG; + } + /* add trusted peer cert */ + return AddTrustedPeer(ctx->cm, &der, !ctx->verifyNone); + } +#endif /* WOLFSSL_TRUST_PEER_CERT */ + else if (type == CERT_TYPE) { + if (ssl) { + /* Make sure previous is free'd */ + if (ssl->buffers.weOwnCert) { + FreeDer(&ssl->buffers.certificate); + #ifdef KEEP_OUR_CERT + FreeX509(ssl->ourCert); + if (ssl->ourCert) { + XFREE(ssl->ourCert, ssl->heap, DYNAMIC_TYPE_X509); + ssl->ourCert = NULL; + } + #endif + } + ssl->buffers.certificate = der; + #ifdef KEEP_OUR_CERT + ssl->keepCert = 1; /* hold cert for ssl lifetime */ + #endif + ssl->buffers.weOwnCert = 1; + } + else if (ctx) { + FreeDer(&ctx->certificate); /* Make sure previous is free'd */ + #ifdef KEEP_OUR_CERT + if (ctx->ourCert) { + if (ctx->ownOurCert) { + FreeX509(ctx->ourCert); + XFREE(ctx->ourCert, ctx->heap, DYNAMIC_TYPE_X509); + } + ctx->ourCert = NULL; + } + #endif + ctx->certificate = der; + } + } + else if (type == PRIVATEKEY_TYPE) { + if (ssl) { + /* Make sure previous is free'd */ + if (ssl->buffers.weOwnKey) { + FreeDer(&ssl->buffers.key); + } + ssl->buffers.key = der; + ssl->buffers.weOwnKey = 1; + } + else if (ctx) { + FreeDer(&ctx->privateKey); + ctx->privateKey = der; + } + } + else { + FreeDer(&der); + return WOLFSSL_BAD_CERTTYPE; + } + + if (type == PRIVATEKEY_TYPE && format != WOLFSSL_FILETYPE_RAW) { + #ifndef NO_RSA + if (!eccKey && !ed25519Key) { + /* make sure RSA key can be used */ + #ifdef WOLFSSL_SMALL_STACK + RsaKey* key = NULL; + #else + RsaKey key[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + key = (RsaKey*)XMALLOC(sizeof(RsaKey), heap, DYNAMIC_TYPE_RSA); + if (key == NULL) + return MEMORY_E; + #endif + + ret = wc_InitRsaKey_ex(key, heap, devId); + if (ret == 0) { + idx = 0; + if (wc_RsaPrivateKeyDecode(der->buffer, &idx, key, der->length) + != 0) { + #ifdef HAVE_ECC + /* could have DER ECC (or pkcs8 ecc), no easy way to tell */ + eccKey = 1; /* try it next */ + #elif defined(HAVE_ED25519) + ed25519Key = 1; /* try it next */ + #else + WOLFSSL_MSG("RSA decode failed and ECC not enabled to try"); + ret = WOLFSSL_BAD_FILE; + #endif + } + else { + /* check that the size of the RSA key is enough */ + int minRsaSz = ssl ? ssl->options.minRsaKeySz : + ctx->minRsaKeySz; + keySz = wc_RsaEncryptSize((RsaKey*)key); + if (keySz < minRsaSz) { + ret = RSA_KEY_SIZE_E; + WOLFSSL_MSG("Private Key size too small"); + } + + if (ssl) { + ssl->buffers.keyType = rsa_sa_algo; + ssl->buffers.keySz = keySz; + } + else if(ctx) { + ctx->privateKeyType = rsa_sa_algo; + ctx->privateKeySz = keySz; + } + + rsaKey = 1; + (void)rsaKey; /* for no ecc builds */ + + if (ssl && ssl->options.side == WOLFSSL_SERVER_END) { + ssl->options.haveStaticECC = 0; + resetSuites = 1; + } + } + + wc_FreeRsaKey(key); + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(key, heap, DYNAMIC_TYPE_RSA); + #endif + + if (ret != 0) + return ret; + } + #endif + #ifdef HAVE_ECC + if (!rsaKey && !ed25519Key) { + /* make sure ECC key can be used */ + #ifdef WOLFSSL_SMALL_STACK + ecc_key* key = NULL; + #else + ecc_key key[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + key = (ecc_key*)XMALLOC(sizeof(ecc_key), heap, DYNAMIC_TYPE_ECC); + if (key == NULL) + return MEMORY_E; + #endif + + if (wc_ecc_init_ex(key, heap, devId) == 0) { + idx = 0; + if (wc_EccPrivateKeyDecode(der->buffer, &idx, key, + der->length) == 0) { + /* check for minimum ECC key size and then free */ + int minKeySz = ssl ? ssl->options.minEccKeySz : + ctx->minEccKeySz; + keySz = wc_ecc_size(key); + if (keySz < minKeySz) { + WOLFSSL_MSG("ECC private key too small"); + ret = ECC_KEY_SIZE_E; + } + + eccKey = 1; + if (ssl) { + ssl->options.haveStaticECC = 1; + ssl->buffers.keyType = ecc_dsa_sa_algo; + ssl->buffers.keySz = keySz; + } + else if (ctx) { + ctx->haveStaticECC = 1; + ctx->privateKeyType = ecc_dsa_sa_algo; + ctx->privateKeySz = keySz; + } + + if (ssl && ssl->options.side == WOLFSSL_SERVER_END) { + resetSuites = 1; + } + } + else + eccKey = 0; + + wc_ecc_free(key); + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(key, heap, DYNAMIC_TYPE_ECC); + #endif + + if (ret != 0) + return ret; + } + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + if (!rsaKey && !eccKey) { + /* make sure Ed25519 key can be used */ + #ifdef WOLFSSL_SMALL_STACK + ed25519_key* key = NULL; + #else + ed25519_key key[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + key = (ed25519_key*)XMALLOC(sizeof(ed25519_key), heap, + DYNAMIC_TYPE_ED25519); + if (key == NULL) + return MEMORY_E; + #endif + + ret = wc_ed25519_init(key); + if (ret == 0) { + idx = 0; + if (wc_Ed25519PrivateKeyDecode(der->buffer, &idx, key, + der->length) != 0) { + ret = WOLFSSL_BAD_FILE; + } + + if (ret == 0) { + /* check for minimum key size and then free */ + int minKeySz = ssl ? ssl->options.minEccKeySz : + ctx->minEccKeySz; + keySz = ED25519_KEY_SIZE; + if (keySz < minKeySz) { + WOLFSSL_MSG("ED25519 private key too small"); + ret = ECC_KEY_SIZE_E; + } + } + if (ret == 0) { + if (ssl) { + ssl->buffers.keyType = ed25519_sa_algo; + ssl->buffers.keySz = keySz; + } + else if (ctx) { + ctx->privateKeyType = ed25519_sa_algo; + ctx->privateKeySz = keySz; + } + + ed25519Key = 1; + if (ssl && ssl->options.side == WOLFSSL_SERVER_END) { + resetSuites = 1; + } + } + + wc_ed25519_free(key); + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(key, heap, DYNAMIC_TYPE_ED25519); + #endif + if (ret != 0) + return ret; + } + #else + if (!rsaKey && !eccKey && !ed25519Key) + return WOLFSSL_BAD_FILE; + #endif + (void)ed25519Key; + (void)devId; + } + else if (type == CERT_TYPE) { + #ifdef WOLFSSL_SMALL_STACK + DecodedCert* cert = NULL; + #else + DecodedCert cert[1]; + #endif + #ifdef HAVE_PK_CALLBACKS + int keyType = 0; + #endif + + #ifdef WOLFSSL_SMALL_STACK + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), heap, + DYNAMIC_TYPE_DCERT); + if (cert == NULL) + return MEMORY_E; + #endif + + WOLFSSL_MSG("Checking cert signature type"); + InitDecodedCert(cert, der->buffer, der->length, heap); + + if (DecodeToKey(cert, 0) < 0) { + WOLFSSL_MSG("Decode to key failed"); + FreeDecodedCert(cert); + #ifdef WOLFSSL_SMALL_STACK + XFREE(cert, heap, DYNAMIC_TYPE_DCERT); + #endif + return WOLFSSL_BAD_FILE; + } + + if (ssl && ssl->options.side == WOLFSSL_SERVER_END) { + resetSuites = 1; + } + if (ssl && ssl->ctx->haveECDSAsig) { + WOLFSSL_MSG("SSL layer setting cert, CTX had ECDSA, turning off"); + ssl->options.haveECDSAsig = 0; /* may turn back on next */ + } + + switch (cert->signatureOID) { + case CTC_SHAwECDSA: + case CTC_SHA256wECDSA: + case CTC_SHA384wECDSA: + case CTC_SHA512wECDSA: + WOLFSSL_MSG("ECDSA cert signature"); + if (ssl) + ssl->options.haveECDSAsig = 1; + else if (ctx) + ctx->haveECDSAsig = 1; + break; + case CTC_ED25519: + WOLFSSL_MSG("ED25519 cert signature"); + if (ssl) + ssl->options.haveECDSAsig = 1; + else if (ctx) + ctx->haveECDSAsig = 1; + break; + default: + WOLFSSL_MSG("Not ECDSA cert signature"); + break; + } + + #if defined(HAVE_ECC) || defined(HAVE_ED25519) + if (ssl) { + ssl->pkCurveOID = cert->pkCurveOID; + #ifndef WC_STRICT_SIG + if (cert->keyOID == ECDSAk) { + ssl->options.haveECC = 1; + } + #ifdef HAVE_ED25519 + else if (cert->keyOID == ED25519k) { + ssl->options.haveECC = 1; + } + #endif + #else + ssl->options.haveECC = ssl->options.haveECDSAsig; + #endif + } + else if (ctx) { + ctx->pkCurveOID = cert->pkCurveOID; + #ifndef WC_STRICT_SIG + if (cert->keyOID == ECDSAk) { + ctx->haveECC = 1; + } + #ifdef HAVE_ED25519 + else if (cert->keyOID == ED25519k) { + ctx->haveECC = 1; + } + #endif + #else + ctx->haveECC = ctx->haveECDSAsig; + #endif + } + #endif + + /* check key size of cert unless specified not to */ + switch (cert->keyOID) { + #ifndef NO_RSA + case RSAk: + #ifdef HAVE_PK_CALLBACKS + keyType = rsa_sa_algo; + #endif + /* Determine RSA key size by parsing public key */ + idx = 0; + ret = wc_RsaPublicKeyDecode_ex(cert->publicKey, &idx, + cert->pubKeySize, NULL, (word32*)&keySz, NULL, NULL); + if (ret < 0) + break; + + if (ssl && !ssl->options.verifyNone) { + if (ssl->options.minRsaKeySz < 0 || + keySz < (int)ssl->options.minRsaKeySz) { + ret = RSA_KEY_SIZE_E; + WOLFSSL_MSG("Certificate RSA key size too small"); + } + } + else if (ctx && !ctx->verifyNone) { + if (ctx->minRsaKeySz < 0 || + keySz < (int)ctx->minRsaKeySz) { + ret = RSA_KEY_SIZE_E; + WOLFSSL_MSG("Certificate RSA key size too small"); + } + } + break; + #endif /* !NO_RSA */ + #ifdef HAVE_ECC + case ECDSAk: + #ifdef HAVE_PK_CALLBACKS + keyType = ecc_dsa_sa_algo; + #endif + /* Determine ECC key size based on curve */ + keySz = wc_ecc_get_curve_size_from_id( + wc_ecc_get_oid(cert->pkCurveOID, NULL, NULL)); + + if (ssl && !ssl->options.verifyNone) { + if (ssl->options.minEccKeySz < 0 || + keySz < (int)ssl->options.minEccKeySz) { + ret = ECC_KEY_SIZE_E; + WOLFSSL_MSG("Certificate ECC key size error"); + } + } + else if (ctx && !ctx->verifyNone) { + if (ctx->minEccKeySz < 0 || + keySz < (int)ctx->minEccKeySz) { + ret = ECC_KEY_SIZE_E; + WOLFSSL_MSG("Certificate ECC key size error"); + } + } + break; + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ED25519k: + #ifdef HAVE_PK_CALLBACKS + keyType = ed25519_sa_algo; + #endif + /* ED25519 is fixed key size */ + keySz = ED25519_KEY_SIZE; + if (ssl && !ssl->options.verifyNone) { + if (ssl->options.minEccKeySz < 0 || + keySz < (int)ssl->options.minEccKeySz) { + ret = ECC_KEY_SIZE_E; + WOLFSSL_MSG("Certificate Ed key size error"); + } + } + else if (ctx && !ctx->verifyNone) { + if (ctx->minEccKeySz < 0 || + keySz < (int)ctx->minEccKeySz) { + ret = ECC_KEY_SIZE_E; + WOLFSSL_MSG("Certificate ECC key size error"); + } + } + break; + #endif /* HAVE_ED25519 */ + + default: + WOLFSSL_MSG("No key size check done on certificate"); + break; /* do no check if not a case for the key */ + } + + #ifdef HAVE_PK_CALLBACKS + if (ssl && ssl->buffers.keyType == 0) { + ssl->buffers.keyType = keyType; + ssl->buffers.keySz = keySz; + } + else if (ctx && ctx->privateKeyType == 0) { + ctx->privateKeyType = keyType; + ctx->privateKeySz = keySz; + } + #endif + + FreeDecodedCert(cert); + #ifdef WOLFSSL_SMALL_STACK + XFREE(cert, heap, DYNAMIC_TYPE_DCERT); + #endif + + if (ret != 0) { + return ret; + } + } + + if (ssl && resetSuites) { + word16 havePSK = 0; + word16 haveRSA = 0; + + #ifndef NO_PSK + if (ssl->options.havePSK) { + havePSK = 1; + } + #endif + #ifndef NO_RSA + haveRSA = 1; + #endif + #ifndef NO_CERTS + keySz = ssl->buffers.keySz; + #endif + + /* let's reset suites */ + InitSuites(ssl->suites, ssl->version, keySz, haveRSA, + havePSK, ssl->options.haveDH, ssl->options.haveNTRU, + ssl->options.haveECDSAsig, ssl->options.haveECC, + ssl->options.haveStaticECC, ssl->options.side); + } + + return WOLFSSL_SUCCESS; +} + + +/* CA PEM file for verification, may have multiple/chain certs to process */ +static int ProcessChainBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, + long sz, int format, int type, WOLFSSL* ssl) +{ + long used = 0; + int ret = 0; + int gotOne = 0; + + WOLFSSL_MSG("Processing CA PEM file"); + while (used < sz) { + long consumed = 0; + + ret = ProcessBuffer(ctx, buff + used, sz - used, format, type, ssl, + &consumed, 0); + +#ifdef WOLFSSL_WPAS +#ifdef HAVE_CRL + if (ret < 0) { + DerBuffer* der = NULL; + EncryptedInfo info; + + WOLFSSL_MSG("Trying a CRL"); + if (PemToDer(buff + used, sz - used, CRL_TYPE, &der, NULL, &info, + NULL) == 0) { + WOLFSSL_MSG(" Processed a CRL"); + wolfSSL_CertManagerLoadCRLBuffer(ctx->cm, der->buffer, + der->length, WOLFSSL_FILETYPE_ASN1); + FreeDer(&der); + used += info.consumed; + continue; + } + } +#endif +#endif + if (ret < 0) { + if (consumed > 0) { /* Made progress in file */ + WOLFSSL_ERROR(ret); + WOLFSSL_MSG("CA Parse failed, with progress in file."); + WOLFSSL_MSG("Search for other certs in file"); + } + else { + WOLFSSL_MSG("CA Parse failed, no progress in file."); + WOLFSSL_MSG("Do not continue search for other certs in file"); + break; + } + } + else { + WOLFSSL_MSG(" Processed a CA"); + gotOne = 1; + } + used += consumed; + } + + if (gotOne) { + WOLFSSL_MSG("Processed at least one valid CA. Other stuff OK"); + return WOLFSSL_SUCCESS; + } + return ret; +} + + +static WC_INLINE WOLFSSL_METHOD* cm_pick_method(void) +{ + #ifndef NO_WOLFSSL_CLIENT + #if !defined(NO_OLD_TLS) && defined(WOLFSSL_ALLOW_SSLV3) + return wolfSSLv3_client_method(); + #elif !defined(NO_OLD_TLS) && defined(WOLFSSL_ALLOW_TLSV10) + return wolfTLSv1_client_method(); + #elif !defined(NO_OLD_TLS) + return wolfTLSv1_1_client_method(); + #elif !defined(WOLFSSL_NO_TLS12) + return wolfTLSv1_2_client_method(); + #elif defined(WOLFSSL_TLS13) + return wolfTLSv1_3_client_method(); + #else + return NULL; + #endif + #elif !defined(NO_WOLFSSL_SERVER) + #if !defined(NO_OLD_TLS) && defined(WOLFSSL_ALLOW_SSLV3) + return wolfSSLv3_server_method(); + #elif !defined(NO_OLD_TLS) && defined(WOLFSSL_ALLOW_TLSV10) + return wolfTLSv1_server_method(); + #elif !defined(NO_OLD_TLS) + return wolfTLSv1_1_server_method(); + #elif !defined(WOLFSSL_NO_TLS12) + return wolfTLSv1_2_server_method(); + #elif defined(WOLFSSL_TLS13) + return wolfTLSv1_3_server_method(); + #else + return NULL; + #endif + #else + return NULL; + #endif +} + + +/* like load verify locations, 1 for success, < 0 for error */ +int wolfSSL_CertManagerLoadCABuffer(WOLFSSL_CERT_MANAGER* cm, + const unsigned char* in, long sz, int format) +{ + int ret = WOLFSSL_FATAL_ERROR; + WOLFSSL_CTX* tmp; + + WOLFSSL_ENTER("wolfSSL_CertManagerLoadCABuffer"); + + if (cm == NULL) { + WOLFSSL_MSG("No CertManager error"); + return ret; + } + tmp = wolfSSL_CTX_new(cm_pick_method()); + + if (tmp == NULL) { + WOLFSSL_MSG("CTX new failed"); + return ret; + } + + /* for tmp use */ + wolfSSL_CertManagerFree(tmp->cm); + tmp->cm = cm; + + ret = wolfSSL_CTX_load_verify_buffer(tmp, in, sz, format); + + /* don't loose our good one */ + tmp->cm = NULL; + wolfSSL_CTX_free(tmp); + + return ret; +} + +#ifdef HAVE_CRL + +int wolfSSL_CertManagerLoadCRLBuffer(WOLFSSL_CERT_MANAGER* cm, + const unsigned char* buff, long sz, int type) +{ + WOLFSSL_ENTER("wolfSSL_CertManagerLoadCRLBuffer"); + if (cm == NULL) + return BAD_FUNC_ARG; + + if (cm->crl == NULL) { + if (wolfSSL_CertManagerEnableCRL(cm, 0) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Enable CRL failed"); + return WOLFSSL_FATAL_ERROR; + } + } + + return BufferLoadCRL(cm->crl, buff, sz, type, 0); +} + +int wolfSSL_CertManagerFreeCRL(WOLFSSL_CERT_MANAGER* cm) +{ + WOLFSSL_ENTER("wolfSSL_CertManagerFreeCRL"); + if (cm == NULL) + return BAD_FUNC_ARG; + if (cm->crl != NULL){ + FreeCRL(cm->crl, 1); + cm->crl = NULL; + } + return WOLFSSL_SUCCESS; +} + +int wolfSSL_CTX_LoadCRLBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, + long sz, int type) +{ + WOLFSSL_ENTER("wolfSSL_CTX_LoadCRLBuffer"); + + if (ctx == NULL) + return BAD_FUNC_ARG; + + return wolfSSL_CertManagerLoadCRLBuffer(ctx->cm, buff, sz, type); +} + + +int wolfSSL_LoadCRLBuffer(WOLFSSL* ssl, const unsigned char* buff, + long sz, int type) +{ + WOLFSSL_ENTER("wolfSSL_LoadCRLBuffer"); + + if (ssl == NULL || ssl->ctx == NULL) + return BAD_FUNC_ARG; + + return wolfSSL_CertManagerLoadCRLBuffer(ssl->ctx->cm, buff, sz, type); +} + + +#endif /* HAVE_CRL */ + +/* turn on CRL if off and compiled in, set options */ +int wolfSSL_CertManagerEnableCRL(WOLFSSL_CERT_MANAGER* cm, int options) +{ + int ret = WOLFSSL_SUCCESS; + + (void)options; + + WOLFSSL_ENTER("wolfSSL_CertManagerEnableCRL"); + if (cm == NULL) + return BAD_FUNC_ARG; + + #ifdef HAVE_CRL + if (cm->crl == NULL) { + cm->crl = (WOLFSSL_CRL*)XMALLOC(sizeof(WOLFSSL_CRL), cm->heap, + DYNAMIC_TYPE_CRL); + if (cm->crl == NULL) + return MEMORY_E; + + if (InitCRL(cm->crl, cm) != 0) { + WOLFSSL_MSG("Init CRL failed"); + FreeCRL(cm->crl, 1); + cm->crl = NULL; + return WOLFSSL_FAILURE; + } + + #ifdef HAVE_CRL_IO + cm->crl->crlIOCb = EmbedCrlLookup; + #endif + } + + cm->crlEnabled = 1; + if (options & WOLFSSL_CRL_CHECKALL) + cm->crlCheckAll = 1; + #else + ret = NOT_COMPILED_IN; + #endif + + return ret; +} + + +int wolfSSL_CertManagerDisableCRL(WOLFSSL_CERT_MANAGER* cm) +{ + WOLFSSL_ENTER("wolfSSL_CertManagerDisableCRL"); + if (cm == NULL) + return BAD_FUNC_ARG; + + cm->crlEnabled = 0; + + return WOLFSSL_SUCCESS; +} +/* Verify the certificate, WOLFSSL_SUCCESS for ok, < 0 for error */ +int wolfSSL_CertManagerVerifyBuffer(WOLFSSL_CERT_MANAGER* cm, const byte* buff, + long sz, int format) +{ + int ret = 0; + DerBuffer* der = NULL; +#ifdef WOLFSSL_SMALL_STACK + DecodedCert* cert = NULL; +#else + DecodedCert cert[1]; +#endif + + WOLFSSL_ENTER("wolfSSL_CertManagerVerifyBuffer"); + +#ifdef WOLFSSL_SMALL_STACK + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), cm->heap, + DYNAMIC_TYPE_DCERT); + if (cert == NULL) + return MEMORY_E; +#endif + + if (format == WOLFSSL_FILETYPE_PEM) { +#ifdef WOLFSSL_PEM_TO_DER + ret = PemToDer(buff, sz, CERT_TYPE, &der, cm->heap, NULL, NULL); + if (ret != 0) { + FreeDer(&der); + #ifdef WOLFSSL_SMALL_STACK + XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT); + #endif + return ret; + } + InitDecodedCert(cert, der->buffer, der->length, cm->heap); +#else + ret = NOT_COMPILED_IN; +#endif + } + else { + InitDecodedCert(cert, (byte*)buff, (word32)sz, cm->heap); + } + + if (ret == 0) + ret = ParseCertRelative(cert, CERT_TYPE, 1, cm); + +#ifdef HAVE_CRL + if (ret == 0 && cm->crlEnabled) + ret = CheckCertCRL(cm->crl, cert); +#endif + + FreeDecodedCert(cert); + FreeDer(&der); +#ifdef WOLFSSL_SMALL_STACK + XFREE(cert, cm->heap, DYNAMIC_TYPE_DCERT); +#endif + + return ret == 0 ? WOLFSSL_SUCCESS : ret; +} + + +/* turn on OCSP if off and compiled in, set options */ +int wolfSSL_CertManagerEnableOCSP(WOLFSSL_CERT_MANAGER* cm, int options) +{ + int ret = WOLFSSL_SUCCESS; + + (void)options; + + WOLFSSL_ENTER("wolfSSL_CertManagerEnableOCSP"); + if (cm == NULL) + return BAD_FUNC_ARG; + + #ifdef HAVE_OCSP + if (cm->ocsp == NULL) { + cm->ocsp = (WOLFSSL_OCSP*)XMALLOC(sizeof(WOLFSSL_OCSP), cm->heap, + DYNAMIC_TYPE_OCSP); + if (cm->ocsp == NULL) + return MEMORY_E; + + if (InitOCSP(cm->ocsp, cm) != 0) { + WOLFSSL_MSG("Init OCSP failed"); + FreeOCSP(cm->ocsp, 1); + cm->ocsp = NULL; + return WOLFSSL_FAILURE; + } + } + cm->ocspEnabled = 1; + if (options & WOLFSSL_OCSP_URL_OVERRIDE) + cm->ocspUseOverrideURL = 1; + if (options & WOLFSSL_OCSP_NO_NONCE) + cm->ocspSendNonce = 0; + else + cm->ocspSendNonce = 1; + if (options & WOLFSSL_OCSP_CHECKALL) + cm->ocspCheckAll = 1; + #ifndef WOLFSSL_USER_IO + cm->ocspIOCb = EmbedOcspLookup; + cm->ocspRespFreeCb = EmbedOcspRespFree; + cm->ocspIOCtx = cm->heap; + #endif /* WOLFSSL_USER_IO */ + #else + ret = NOT_COMPILED_IN; + #endif + + return ret; +} + + +int wolfSSL_CertManagerDisableOCSP(WOLFSSL_CERT_MANAGER* cm) +{ + WOLFSSL_ENTER("wolfSSL_CertManagerDisableOCSP"); + if (cm == NULL) + return BAD_FUNC_ARG; + + cm->ocspEnabled = 0; + + return WOLFSSL_SUCCESS; +} + +/* turn on OCSP Stapling if off and compiled in, set options */ +int wolfSSL_CertManagerEnableOCSPStapling(WOLFSSL_CERT_MANAGER* cm) +{ + int ret = WOLFSSL_SUCCESS; + + WOLFSSL_ENTER("wolfSSL_CertManagerEnableOCSPStapling"); + + if (cm == NULL) + return BAD_FUNC_ARG; + +#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + #ifndef NO_WOLFSSL_SERVER + if (cm->ocsp_stapling == NULL) { + cm->ocsp_stapling = (WOLFSSL_OCSP*)XMALLOC(sizeof(WOLFSSL_OCSP), + cm->heap, DYNAMIC_TYPE_OCSP); + if (cm->ocsp_stapling == NULL) + return MEMORY_E; + + if (InitOCSP(cm->ocsp_stapling, cm) != 0) { + WOLFSSL_MSG("Init OCSP failed"); + FreeOCSP(cm->ocsp_stapling, 1); + cm->ocsp_stapling = NULL; + return WOLFSSL_FAILURE; + } + } + + #ifndef WOLFSSL_USER_IO + cm->ocspIOCb = EmbedOcspLookup; + cm->ocspRespFreeCb = EmbedOcspRespFree; + cm->ocspIOCtx = cm->heap; + #endif /* WOLFSSL_USER_IO */ + #endif /* NO_WOLFSSL_SERVER */ + cm->ocspStaplingEnabled = 1; +#else + ret = NOT_COMPILED_IN; +#endif + + return ret; +} + +int wolfSSL_CertManagerDisableOCSPStapling(WOLFSSL_CERT_MANAGER* cm) +{ + int ret = WOLFSSL_SUCCESS; + + WOLFSSL_ENTER("wolfSSL_CertManagerDisableOCSPStapling"); + + if (cm == NULL) + return BAD_FUNC_ARG; + +#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + cm->ocspStaplingEnabled = 0; +#else + ret = NOT_COMPILED_IN; +#endif + return ret; +} +#if defined(SESSION_CERTS) +WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_get_peer_cert_chain(const WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_get_peer_cert_chain"); + if ((ssl == NULL) || (ssl->session.chain.count == 0)) + return NULL; + else + return (WOLF_STACK_OF(WOLFSSL_X509)* )&ssl->session.chain; +} +#endif +#ifdef HAVE_OCSP + +/* check CRL if enabled, WOLFSSL_SUCCESS */ +int wolfSSL_CertManagerCheckOCSP(WOLFSSL_CERT_MANAGER* cm, byte* der, int sz) +{ + int ret; +#ifdef WOLFSSL_SMALL_STACK + DecodedCert* cert = NULL; +#else + DecodedCert cert[1]; +#endif + + WOLFSSL_ENTER("wolfSSL_CertManagerCheckOCSP"); + + if (cm == NULL) + return BAD_FUNC_ARG; + + if (cm->ocspEnabled == 0) + return WOLFSSL_SUCCESS; + +#ifdef WOLFSSL_SMALL_STACK + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, DYNAMIC_TYPE_DCERT); + if (cert == NULL) + return MEMORY_E; +#endif + + InitDecodedCert(cert, der, sz, NULL); + + if ((ret = ParseCertRelative(cert, CERT_TYPE, VERIFY_OCSP, cm)) != 0) { + WOLFSSL_MSG("ParseCert failed"); + } + else if ((ret = CheckCertOCSP(cm->ocsp, cert, NULL)) != 0) { + WOLFSSL_MSG("CheckCertOCSP failed"); + } + + FreeDecodedCert(cert); +#ifdef WOLFSSL_SMALL_STACK + XFREE(cert, NULL, DYNAMIC_TYPE_DCERT); +#endif + + return ret == 0 ? WOLFSSL_SUCCESS : ret; +} + +WOLFSSL_API int wolfSSL_CertManagerCheckOCSPResponse(WOLFSSL_CERT_MANAGER *cm, + byte *response, int responseSz, buffer *responseBuffer, + CertStatus *status, OcspEntry *entry, OcspRequest *ocspRequest) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_CertManagerCheckOCSP_Staple"); + if (cm == NULL || response == NULL) + return BAD_FUNC_ARG; + if (cm->ocspEnabled == 0) + return WOLFSSL_SUCCESS; + + ret = CheckOcspResponse(cm->ocsp, response, responseSz, responseBuffer, status, + entry, ocspRequest); + + return ret == 0 ? WOLFSSL_SUCCESS : ret; +} + +int wolfSSL_CertManagerSetOCSPOverrideURL(WOLFSSL_CERT_MANAGER* cm, + const char* url) +{ + WOLFSSL_ENTER("wolfSSL_CertManagerSetOCSPOverrideURL"); + if (cm == NULL) + return BAD_FUNC_ARG; + + XFREE(cm->ocspOverrideURL, cm->heap, DYNAMIC_TYPE_URL); + if (url != NULL) { + int urlSz = (int)XSTRLEN(url) + 1; + cm->ocspOverrideURL = (char*)XMALLOC(urlSz, cm->heap, DYNAMIC_TYPE_URL); + if (cm->ocspOverrideURL != NULL) { + XMEMCPY(cm->ocspOverrideURL, url, urlSz); + } + else + return MEMORY_E; + } + else + cm->ocspOverrideURL = NULL; + + return WOLFSSL_SUCCESS; +} + + +int wolfSSL_CertManagerSetOCSP_Cb(WOLFSSL_CERT_MANAGER* cm, + CbOCSPIO ioCb, CbOCSPRespFree respFreeCb, void* ioCbCtx) +{ + WOLFSSL_ENTER("wolfSSL_CertManagerSetOCSP_Cb"); + if (cm == NULL) + return BAD_FUNC_ARG; + + cm->ocspIOCb = ioCb; + cm->ocspRespFreeCb = respFreeCb; + cm->ocspIOCtx = ioCbCtx; + + return WOLFSSL_SUCCESS; +} + + +int wolfSSL_EnableOCSP(WOLFSSL* ssl, int options) +{ + WOLFSSL_ENTER("wolfSSL_EnableOCSP"); + if (ssl) + return wolfSSL_CertManagerEnableOCSP(ssl->ctx->cm, options); + else + return BAD_FUNC_ARG; +} + +int wolfSSL_DisableOCSP(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_DisableOCSP"); + if (ssl) + return wolfSSL_CertManagerDisableOCSP(ssl->ctx->cm); + else + return BAD_FUNC_ARG; +} + + +int wolfSSL_EnableOCSPStapling(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_EnableOCSPStapling"); + if (ssl) + return wolfSSL_CertManagerEnableOCSPStapling(ssl->ctx->cm); + else + return BAD_FUNC_ARG; +} + +int wolfSSL_DisableOCSPStapling(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_DisableOCSPStapling"); + if (ssl) + return wolfSSL_CertManagerDisableOCSPStapling(ssl->ctx->cm); + else + return BAD_FUNC_ARG; +} + +int wolfSSL_SetOCSP_OverrideURL(WOLFSSL* ssl, const char* url) +{ + WOLFSSL_ENTER("wolfSSL_SetOCSP_OverrideURL"); + if (ssl) + return wolfSSL_CertManagerSetOCSPOverrideURL(ssl->ctx->cm, url); + else + return BAD_FUNC_ARG; +} + + +int wolfSSL_SetOCSP_Cb(WOLFSSL* ssl, + CbOCSPIO ioCb, CbOCSPRespFree respFreeCb, void* ioCbCtx) +{ + WOLFSSL_ENTER("wolfSSL_SetOCSP_Cb"); + if (ssl) { + ssl->ocspIOCtx = ioCbCtx; /* use SSL specific ioCbCtx */ + return wolfSSL_CertManagerSetOCSP_Cb(ssl->ctx->cm, + ioCb, respFreeCb, NULL); + } + else + return BAD_FUNC_ARG; +} + + +int wolfSSL_CTX_EnableOCSP(WOLFSSL_CTX* ctx, int options) +{ + WOLFSSL_ENTER("wolfSSL_CTX_EnableOCSP"); + if (ctx) + return wolfSSL_CertManagerEnableOCSP(ctx->cm, options); + else + return BAD_FUNC_ARG; +} + + +int wolfSSL_CTX_DisableOCSP(WOLFSSL_CTX* ctx) +{ + WOLFSSL_ENTER("wolfSSL_CTX_DisableOCSP"); + if (ctx) + return wolfSSL_CertManagerDisableOCSP(ctx->cm); + else + return BAD_FUNC_ARG; +} + + +int wolfSSL_CTX_SetOCSP_OverrideURL(WOLFSSL_CTX* ctx, const char* url) +{ + WOLFSSL_ENTER("wolfSSL_SetOCSP_OverrideURL"); + if (ctx) + return wolfSSL_CertManagerSetOCSPOverrideURL(ctx->cm, url); + else + return BAD_FUNC_ARG; +} + + +int wolfSSL_CTX_SetOCSP_Cb(WOLFSSL_CTX* ctx, CbOCSPIO ioCb, + CbOCSPRespFree respFreeCb, void* ioCbCtx) +{ + WOLFSSL_ENTER("wolfSSL_CTX_SetOCSP_Cb"); + if (ctx) + return wolfSSL_CertManagerSetOCSP_Cb(ctx->cm, ioCb, + respFreeCb, ioCbCtx); + else + return BAD_FUNC_ARG; +} + +#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) +int wolfSSL_CTX_EnableOCSPStapling(WOLFSSL_CTX* ctx) +{ + WOLFSSL_ENTER("wolfSSL_CTX_EnableOCSPStapling"); + if (ctx) + return wolfSSL_CertManagerEnableOCSPStapling(ctx->cm); + else + return BAD_FUNC_ARG; +} + +int wolfSSL_CTX_DisableOCSPStapling(WOLFSSL_CTX* ctx) +{ + WOLFSSL_ENTER("wolfSSL_CTX_DisableOCSPStapling"); + if (ctx) + return wolfSSL_CertManagerDisableOCSPStapling(ctx->cm); + else + return BAD_FUNC_ARG; +} +#endif /* HAVE_CERTIFICATE_STATUS_REQUEST || HAVE_CERTIFICATE_STATUS_REQUEST_V2 */ + +#endif /* HAVE_OCSP */ + + +#ifndef NO_FILESYSTEM + +/* process a file with name fname into ctx of format and type + userChain specifies a user certificate chain to pass during handshake */ +int ProcessFile(WOLFSSL_CTX* ctx, const char* fname, int format, int type, + WOLFSSL* ssl, int userChain, WOLFSSL_CRL* crl) +{ +#ifdef WOLFSSL_SMALL_STACK + byte staticBuffer[1]; /* force heap usage */ +#else + byte staticBuffer[FILE_BUFFER_SIZE]; +#endif + byte* myBuffer = staticBuffer; + int dynamic = 0; + int ret; + long sz = 0; + XFILE file; + void* heapHint = wolfSSL_CTX_GetHeap(ctx, ssl); + + (void)crl; + (void)heapHint; + + if (fname == NULL) return WOLFSSL_BAD_FILE; + + file = XFOPEN(fname, "rb"); + if (file == XBADFILE) return WOLFSSL_BAD_FILE; + if (XFSEEK(file, 0, XSEEK_END) != 0) { + XFCLOSE(file); + return WOLFSSL_BAD_FILE; + } + sz = XFTELL(file); + XREWIND(file); + + if (sz > (long)sizeof(staticBuffer)) { + WOLFSSL_MSG("Getting dynamic buffer"); + myBuffer = (byte*)XMALLOC(sz, heapHint, DYNAMIC_TYPE_FILE); + if (myBuffer == NULL) { + XFCLOSE(file); + return WOLFSSL_BAD_FILE; + } + dynamic = 1; + } + else if (sz <= 0) { + XFCLOSE(file); + return WOLFSSL_BAD_FILE; + } + + if ( (ret = (int)XFREAD(myBuffer, 1, sz, file)) != sz) + ret = WOLFSSL_BAD_FILE; + else { + if ((type == CA_TYPE || type == TRUSTED_PEER_TYPE) + && format == WOLFSSL_FILETYPE_PEM) + ret = ProcessChainBuffer(ctx, myBuffer, sz, format, type, ssl); +#ifdef HAVE_CRL + else if (type == CRL_TYPE) + ret = BufferLoadCRL(crl, myBuffer, sz, format, 0); +#endif + else + ret = ProcessBuffer(ctx, myBuffer, sz, format, type, ssl, NULL, + userChain); + } + + XFCLOSE(file); + if (dynamic) + XFREE(myBuffer, heapHint, DYNAMIC_TYPE_FILE); + + return ret; +} + +/* loads file then loads each file in path, no c_rehash */ +int wolfSSL_CTX_load_verify_locations_ex(WOLFSSL_CTX* ctx, const char* file, + const char* path, word32 flags) +{ + int ret = WOLFSSL_SUCCESS; +#ifndef NO_WOLFSSL_DIR + int fileRet; + int successCount = 0; + int failCount = 0; +#endif + + WOLFSSL_MSG("wolfSSL_CTX_load_verify_locations_ex"); + + if (ctx == NULL || (file == NULL && path == NULL) ) + return WOLFSSL_FAILURE; + + if (file) + ret = ProcessFile(ctx, file, WOLFSSL_FILETYPE_PEM, CA_TYPE, NULL, 0, NULL); + + if (ret == WOLFSSL_SUCCESS && path) { +#ifndef NO_WOLFSSL_DIR + char* name = NULL; + #ifdef WOLFSSL_SMALL_STACK + ReadDirCtx* readCtx = NULL; + readCtx = (ReadDirCtx*)XMALLOC(sizeof(ReadDirCtx), ctx->heap, + DYNAMIC_TYPE_DIRCTX); + if (readCtx == NULL) + return MEMORY_E; + #else + ReadDirCtx readCtx[1]; + #endif + + /* try to load each regular file in path */ + fileRet = wc_ReadDirFirst(readCtx, path, &name); + while (fileRet == 0 && name) { + WOLFSSL_MSG(name); /* log file name */ + ret = ProcessFile(ctx, name, WOLFSSL_FILETYPE_PEM, CA_TYPE, + NULL, 0, NULL); + if (ret != WOLFSSL_SUCCESS) { + /* handle flags for ignoring errors, skipping expired certs or + by PEM certificate header error */ + if ( (flags & WOLFSSL_LOAD_FLAG_IGNORE_ERR) || + ((flags & WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY) && + (ret == ASN_BEFORE_DATE_E || ret == ASN_AFTER_DATE_E)) || + ((flags & WOLFSSL_LOAD_FLAG_PEM_CA_ONLY) && + (ret == ASN_NO_PEM_HEADER))) { + /* Do not fail here if a certificate fails to load, + continue to next file */ + ret = WOLFSSL_SUCCESS; + } + else { + WOLFSSL_ERROR(ret); + WOLFSSL_MSG("Load CA file failed, continuing"); + failCount++; + } + } + else { + successCount++; + } + fileRet = wc_ReadDirNext(readCtx, path, &name); + } + wc_ReadDirClose(readCtx); + + /* pass directory read failure to response code */ + if (fileRet != WC_READDIR_NOFILE) { + ret = fileRet; + } + /* report failure if no files were loaded or there were failures */ + else if (successCount == 0 || failCount > 0) { + /* use existing error code if exists */ + if (ret == WOLFSSL_SUCCESS) + ret = WOLFSSL_FAILURE; + } + else { + ret = WOLFSSL_SUCCESS; + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(readCtx, ctx->heap, DYNAMIC_TYPE_DIRCTX); + #endif +#else + ret = NOT_COMPILED_IN; + (void)flags; +#endif + } + + return ret; +} + +#ifndef WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS +#define WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS WOLFSSL_LOAD_FLAG_NONE +#endif +int wolfSSL_CTX_load_verify_locations(WOLFSSL_CTX* ctx, const char* file, + const char* path) +{ + return wolfSSL_CTX_load_verify_locations_ex(ctx, file, path, + WOLFSSL_LOAD_VERIFY_DEFAULT_FLAGS); +} + + +#ifdef WOLFSSL_TRUST_PEER_CERT +/* Used to specify a peer cert to match when connecting + ctx : the ctx structure to load in peer cert + file: the string name of cert file + type: type of format such as PEM/DER + */ +int wolfSSL_CTX_trust_peer_cert(WOLFSSL_CTX* ctx, const char* file, int type) +{ + WOLFSSL_ENTER("wolfSSL_CTX_trust_peer_cert"); + + if (ctx == NULL || file == NULL) { + return WOLFSSL_FAILURE; + } + + return ProcessFile(ctx, file, type, TRUSTED_PEER_TYPE, NULL, 0, NULL); +} +#endif /* WOLFSSL_TRUST_PEER_CERT */ + + +/* Verify the certificate, WOLFSSL_SUCCESS for ok, < 0 for error */ +int wolfSSL_CertManagerVerify(WOLFSSL_CERT_MANAGER* cm, const char* fname, + int format) +{ + int ret = WOLFSSL_FATAL_ERROR; +#ifdef WOLFSSL_SMALL_STACK + byte staticBuffer[1]; /* force heap usage */ +#else + byte staticBuffer[FILE_BUFFER_SIZE]; +#endif + byte* myBuffer = staticBuffer; + int dynamic = 0; + long sz = 0; + XFILE file = XFOPEN(fname, "rb"); + + WOLFSSL_ENTER("wolfSSL_CertManagerVerify"); + + if (file == XBADFILE) return WOLFSSL_BAD_FILE; + if(XFSEEK(file, 0, XSEEK_END) != 0) { + XFCLOSE(file); + return WOLFSSL_BAD_FILE; + } + sz = XFTELL(file); + XREWIND(file); + + if (sz > MAX_WOLFSSL_FILE_SIZE || sz <= 0) { + WOLFSSL_MSG("CertManagerVerify file bad size"); + XFCLOSE(file); + return WOLFSSL_BAD_FILE; + } + + if (sz > (long)sizeof(staticBuffer)) { + WOLFSSL_MSG("Getting dynamic buffer"); + myBuffer = (byte*) XMALLOC(sz, cm->heap, DYNAMIC_TYPE_FILE); + if (myBuffer == NULL) { + XFCLOSE(file); + return WOLFSSL_BAD_FILE; + } + dynamic = 1; + } + + if ( (ret = (int)XFREAD(myBuffer, 1, sz, file)) != sz) + ret = WOLFSSL_BAD_FILE; + else + ret = wolfSSL_CertManagerVerifyBuffer(cm, myBuffer, sz, format); + + XFCLOSE(file); + if (dynamic) + XFREE(myBuffer, cm->heap, DYNAMIC_TYPE_FILE); + + return ret; +} + + +/* like load verify locations, 1 for success, < 0 for error */ +int wolfSSL_CertManagerLoadCA(WOLFSSL_CERT_MANAGER* cm, const char* file, + const char* path) +{ + int ret = WOLFSSL_FATAL_ERROR; + WOLFSSL_CTX* tmp; + + WOLFSSL_ENTER("wolfSSL_CertManagerLoadCA"); + + if (cm == NULL) { + WOLFSSL_MSG("No CertManager error"); + return ret; + } + tmp = wolfSSL_CTX_new(cm_pick_method()); + + if (tmp == NULL) { + WOLFSSL_MSG("CTX new failed"); + return ret; + } + + /* for tmp use */ + wolfSSL_CertManagerFree(tmp->cm); + tmp->cm = cm; + + ret = wolfSSL_CTX_load_verify_locations(tmp, file, path); + + /* don't loose our good one */ + tmp->cm = NULL; + wolfSSL_CTX_free(tmp); + + return ret; +} + + +/* Check private against public in certificate for match + * + * ctx WOLFSSL_CTX structure to check private key in + * + * Returns SSL_SUCCESS on good private key and SSL_FAILURE if miss matched. */ +int wolfSSL_CTX_check_private_key(const WOLFSSL_CTX* ctx) +{ +#ifdef WOLFSSL_SMALL_STACK + DecodedCert* der = NULL; +#else + DecodedCert der[1]; +#endif + word32 size; + byte* buff; + int ret; + + WOLFSSL_ENTER("wolfSSL_CTX_check_private_key"); + + if (ctx == NULL) { + return WOLFSSL_FAILURE; + } + +#ifndef NO_CERTS +#ifdef WOLFSSL_SMALL_STACK + der = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, DYNAMIC_TYPE_DCERT); + if (der == NULL) + return MEMORY_E; +#endif + + size = ctx->certificate->length; + buff = ctx->certificate->buffer; + InitDecodedCert(der, buff, size, ctx->heap); + if (ParseCertRelative(der, CERT_TYPE, NO_VERIFY, NULL) != 0) { + FreeDecodedCert(der); + #ifdef WOLFSSL_SMALL_STACK + XFREE(der, NULL, DYNAMIC_TYPE_DCERT); + #endif + return WOLFSSL_FAILURE; + } + + size = ctx->privateKey->length; + buff = ctx->privateKey->buffer; + ret = wc_CheckPrivateKey(buff, size, der); + FreeDecodedCert(der); +#ifdef WOLFSSL_SMALL_STACK + XFREE(der, NULL, DYNAMIC_TYPE_DCERT); +#endif + + if (ret == 1) { + return WOLFSSL_SUCCESS; + } + else { + return WOLFSSL_FAILURE; + } +#else + WOLFSSL_MSG("NO_CERTS is defined, can not check private key"); + return WOLFSSL_FAILURE; +#endif +} + +#ifdef HAVE_CRL + + +/* check CRL if enabled, WOLFSSL_SUCCESS */ +int wolfSSL_CertManagerCheckCRL(WOLFSSL_CERT_MANAGER* cm, byte* der, int sz) +{ + int ret = 0; +#ifdef WOLFSSL_SMALL_STACK + DecodedCert* cert = NULL; +#else + DecodedCert cert[1]; +#endif + + WOLFSSL_ENTER("wolfSSL_CertManagerCheckCRL"); + + if (cm == NULL) + return BAD_FUNC_ARG; + + if (cm->crlEnabled == 0) + return WOLFSSL_SUCCESS; + +#ifdef WOLFSSL_SMALL_STACK + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, DYNAMIC_TYPE_DCERT); + if (cert == NULL) + return MEMORY_E; +#endif + + InitDecodedCert(cert, der, sz, NULL); + + if ((ret = ParseCertRelative(cert, CERT_TYPE, VERIFY_CRL, cm)) != 0) { + WOLFSSL_MSG("ParseCert failed"); + } + else if ((ret = CheckCertCRL(cm->crl, cert)) != 0) { + WOLFSSL_MSG("CheckCertCRL failed"); + } + + FreeDecodedCert(cert); +#ifdef WOLFSSL_SMALL_STACK + XFREE(cert, NULL, DYNAMIC_TYPE_DCERT); +#endif + + return ret == 0 ? WOLFSSL_SUCCESS : ret; +} + + +int wolfSSL_CertManagerSetCRL_Cb(WOLFSSL_CERT_MANAGER* cm, CbMissingCRL cb) +{ + WOLFSSL_ENTER("wolfSSL_CertManagerSetCRL_Cb"); + if (cm == NULL) + return BAD_FUNC_ARG; + + cm->cbMissingCRL = cb; + + return WOLFSSL_SUCCESS; +} + +#ifdef HAVE_CRL_IO +int wolfSSL_CertManagerSetCRL_IOCb(WOLFSSL_CERT_MANAGER* cm, CbCrlIO cb) +{ + if (cm == NULL) + return BAD_FUNC_ARG; + + cm->crl->crlIOCb = cb; + + return WOLFSSL_SUCCESS; +} +#endif + +int wolfSSL_CertManagerLoadCRL(WOLFSSL_CERT_MANAGER* cm, const char* path, + int type, int monitor) +{ + WOLFSSL_ENTER("wolfSSL_CertManagerLoadCRL"); + if (cm == NULL) + return BAD_FUNC_ARG; + + if (cm->crl == NULL) { + if (wolfSSL_CertManagerEnableCRL(cm, 0) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Enable CRL failed"); + return WOLFSSL_FATAL_ERROR; + } + } + + return LoadCRL(cm->crl, path, type, monitor); +} + + +int wolfSSL_EnableCRL(WOLFSSL* ssl, int options) +{ + WOLFSSL_ENTER("wolfSSL_EnableCRL"); + if (ssl) + return wolfSSL_CertManagerEnableCRL(ssl->ctx->cm, options); + else + return BAD_FUNC_ARG; +} + + +int wolfSSL_DisableCRL(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_DisableCRL"); + if (ssl) + return wolfSSL_CertManagerDisableCRL(ssl->ctx->cm); + else + return BAD_FUNC_ARG; +} + + +int wolfSSL_LoadCRL(WOLFSSL* ssl, const char* path, int type, int monitor) +{ + WOLFSSL_ENTER("wolfSSL_LoadCRL"); + if (ssl) + return wolfSSL_CertManagerLoadCRL(ssl->ctx->cm, path, type, monitor); + else + return BAD_FUNC_ARG; +} + + +int wolfSSL_SetCRL_Cb(WOLFSSL* ssl, CbMissingCRL cb) +{ + WOLFSSL_ENTER("wolfSSL_SetCRL_Cb"); + if (ssl) + return wolfSSL_CertManagerSetCRL_Cb(ssl->ctx->cm, cb); + else + return BAD_FUNC_ARG; +} + +#ifdef HAVE_CRL_IO +int wolfSSL_SetCRL_IOCb(WOLFSSL* ssl, CbCrlIO cb) +{ + WOLFSSL_ENTER("wolfSSL_SetCRL_Cb"); + if (ssl) + return wolfSSL_CertManagerSetCRL_IOCb(ssl->ctx->cm, cb); + else + return BAD_FUNC_ARG; +} +#endif + +int wolfSSL_CTX_EnableCRL(WOLFSSL_CTX* ctx, int options) +{ + WOLFSSL_ENTER("wolfSSL_CTX_EnableCRL"); + if (ctx) + return wolfSSL_CertManagerEnableCRL(ctx->cm, options); + else + return BAD_FUNC_ARG; +} + + +int wolfSSL_CTX_DisableCRL(WOLFSSL_CTX* ctx) +{ + WOLFSSL_ENTER("wolfSSL_CTX_DisableCRL"); + if (ctx) + return wolfSSL_CertManagerDisableCRL(ctx->cm); + else + return BAD_FUNC_ARG; +} + + +int wolfSSL_CTX_LoadCRL(WOLFSSL_CTX* ctx, const char* path, + int type, int monitor) +{ + WOLFSSL_ENTER("wolfSSL_CTX_LoadCRL"); + if (ctx) + return wolfSSL_CertManagerLoadCRL(ctx->cm, path, type, monitor); + else + return BAD_FUNC_ARG; +} + + +int wolfSSL_CTX_SetCRL_Cb(WOLFSSL_CTX* ctx, CbMissingCRL cb) +{ + WOLFSSL_ENTER("wolfSSL_CTX_SetCRL_Cb"); + if (ctx) + return wolfSSL_CertManagerSetCRL_Cb(ctx->cm, cb); + else + return BAD_FUNC_ARG; +} + +#ifdef HAVE_CRL_IO +int wolfSSL_CTX_SetCRL_IOCb(WOLFSSL_CTX* ctx, CbCrlIO cb) +{ + WOLFSSL_ENTER("wolfSSL_CTX_SetCRL_IOCb"); + if (ctx) + return wolfSSL_CertManagerSetCRL_IOCb(ctx->cm, cb); + else + return BAD_FUNC_ARG; +} +#endif + + +#endif /* HAVE_CRL */ + + +#ifdef WOLFSSL_DER_LOAD + +/* Add format parameter to allow DER load of CA files */ +int wolfSSL_CTX_der_load_verify_locations(WOLFSSL_CTX* ctx, const char* file, + int format) +{ + WOLFSSL_ENTER("wolfSSL_CTX_der_load_verify_locations"); + if (ctx == NULL || file == NULL) + return WOLFSSL_FAILURE; + + if (ProcessFile(ctx, file, format, CA_TYPE, NULL, 0, NULL) == WOLFSSL_SUCCESS) + return WOLFSSL_SUCCESS; + + return WOLFSSL_FAILURE; +} + +#endif /* WOLFSSL_DER_LOAD */ + + + +int wolfSSL_CTX_use_certificate_file(WOLFSSL_CTX* ctx, const char* file, + int format) +{ + WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_file"); + if (ProcessFile(ctx, file, format, CERT_TYPE, NULL, 0, NULL) == WOLFSSL_SUCCESS) + return WOLFSSL_SUCCESS; + + return WOLFSSL_FAILURE; +} + + +int wolfSSL_CTX_use_PrivateKey_file(WOLFSSL_CTX* ctx, const char* file, + int format) +{ + WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey_file"); + if (ProcessFile(ctx, file, format, PRIVATEKEY_TYPE, NULL, 0, NULL) + == WOLFSSL_SUCCESS) + return WOLFSSL_SUCCESS; + + return WOLFSSL_FAILURE; +} + + +/* Sets the max chain depth when verifying a certificate chain. Default depth + * is set to MAX_CHAIN_DEPTH. + * + * ctx WOLFSSL_CTX structure to set depth in + * depth max depth + */ +void wolfSSL_CTX_set_verify_depth(WOLFSSL_CTX *ctx, int depth) { + WOLFSSL_ENTER("wolfSSL_CTX_set_verify_depth"); + + if (ctx == NULL || depth < 0 || depth > MAX_CHAIN_DEPTH) { + WOLFSSL_MSG("Bad depth argument, too large or less than 0"); + return; + } + + ctx->verifyDepth = (byte)depth; +} + + +/* get cert chaining depth using ssl struct */ +long wolfSSL_get_verify_depth(WOLFSSL* ssl) +{ + if(ssl == NULL) { + return BAD_FUNC_ARG; + } +#ifndef OPENSSL_EXTRA + return MAX_CHAIN_DEPTH; +#else + return ssl->options.verifyDepth; +#endif +} + + +/* get cert chaining depth using ctx struct */ +long wolfSSL_CTX_get_verify_depth(WOLFSSL_CTX* ctx) +{ + if(ctx == NULL) { + return BAD_FUNC_ARG; + } +#ifndef OPENSSL_EXTRA + return MAX_CHAIN_DEPTH; +#else + return ctx->verifyDepth; +#endif +} + + +int wolfSSL_CTX_use_certificate_chain_file(WOLFSSL_CTX* ctx, const char* file) +{ + /* process up to MAX_CHAIN_DEPTH plus subject cert */ + WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_chain_file"); + if (ProcessFile(ctx, file, WOLFSSL_FILETYPE_PEM,CERT_TYPE,NULL,1, NULL) + == WOLFSSL_SUCCESS) + return WOLFSSL_SUCCESS; + + return WOLFSSL_FAILURE; +} + + +int wolfSSL_CTX_use_certificate_chain_file_format(WOLFSSL_CTX* ctx, + const char* file, int format) +{ + /* process up to MAX_CHAIN_DEPTH plus subject cert */ + WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_chain_file_format"); + if (ProcessFile(ctx, file, format, CERT_TYPE, NULL, 1, NULL) + == WOLFSSL_SUCCESS) + return WOLFSSL_SUCCESS; + + return WOLFSSL_FAILURE; +} + + +#ifndef NO_DH + +/* server Diffie-Hellman parameters */ +static int wolfSSL_SetTmpDH_file_wrapper(WOLFSSL_CTX* ctx, WOLFSSL* ssl, + const char* fname, int format) +{ +#ifdef WOLFSSL_SMALL_STACK + byte staticBuffer[1]; /* force heap usage */ +#else + byte staticBuffer[FILE_BUFFER_SIZE]; +#endif + byte* myBuffer = staticBuffer; + int dynamic = 0; + int ret; + long sz = 0; + XFILE file; + + if (ctx == NULL || fname == NULL) + return BAD_FUNC_ARG; + + file = XFOPEN(fname, "rb"); + if (file == XBADFILE) return WOLFSSL_BAD_FILE; + if(XFSEEK(file, 0, XSEEK_END) != 0) { + XFCLOSE(file); + return WOLFSSL_BAD_FILE; + } + sz = XFTELL(file); + XREWIND(file); + + if (sz > (long)sizeof(staticBuffer)) { + WOLFSSL_MSG("Getting dynamic buffer"); + myBuffer = (byte*) XMALLOC(sz, ctx->heap, DYNAMIC_TYPE_FILE); + if (myBuffer == NULL) { + XFCLOSE(file); + return WOLFSSL_BAD_FILE; + } + dynamic = 1; + } + else if (sz <= 0) { + XFCLOSE(file); + return WOLFSSL_BAD_FILE; + } + + if ( (ret = (int)XFREAD(myBuffer, 1, sz, file)) != sz) + ret = WOLFSSL_BAD_FILE; + else { + if (ssl) + ret = wolfSSL_SetTmpDH_buffer(ssl, myBuffer, sz, format); + else + ret = wolfSSL_CTX_SetTmpDH_buffer(ctx, myBuffer, sz, format); + } + + XFCLOSE(file); + if (dynamic) + XFREE(myBuffer, ctx->heap, DYNAMIC_TYPE_FILE); + + return ret; +} + +/* server Diffie-Hellman parameters */ +int wolfSSL_SetTmpDH_file(WOLFSSL* ssl, const char* fname, int format) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + + return wolfSSL_SetTmpDH_file_wrapper(ssl->ctx, ssl, fname, format); +} + + +/* server Diffie-Hellman parameters */ +int wolfSSL_CTX_SetTmpDH_file(WOLFSSL_CTX* ctx, const char* fname, int format) +{ + return wolfSSL_SetTmpDH_file_wrapper(ctx, NULL, fname, format); +} + +#endif /* NO_DH */ + +#endif /* NO_FILESYSTEM */ + + +#if defined(OPENSSL_EXTRA) || !defined(NO_PWDBASED) && \ + (defined(OPENSSL_EXTRA_X509_SMALL) || defined(HAVE_WEBSERVER)) + +static int wolfSSL_EVP_get_hashinfo(const WOLFSSL_EVP_MD* evp, + int* pHash, int* pHashSz) +{ + enum wc_HashType hash = WC_HASH_TYPE_NONE; + int hashSz; + + if (XSTRLEN(evp) < 3) { + /* do not try comparing strings if size is too small */ + return WOLFSSL_FAILURE; + } + + if (XSTRNCMP("SHA", evp, 3) == 0) { + if (XSTRLEN(evp) > 3) { + #ifndef NO_SHA256 + if (XSTRNCMP("SHA256", evp, 6) == 0) { + hash = WC_HASH_TYPE_SHA256; + } + else + #endif + #ifdef WOLFSSL_SHA384 + if (XSTRNCMP("SHA384", evp, 6) == 0) { + hash = WC_HASH_TYPE_SHA384; + } + else + #endif + #ifdef WOLFSSL_SHA512 + if (XSTRNCMP("SHA512", evp, 6) == 0) { + hash = WC_HASH_TYPE_SHA512; + } + else + #endif + { + WOLFSSL_MSG("Unknown SHA hash"); + } + } + else { + hash = WC_HASH_TYPE_SHA; + } + } +#ifdef WOLFSSL_MD2 + else if (XSTRNCMP("MD2", evp, 3) == 0) { + hash = WC_HASH_TYPE_MD2; + } +#endif +#ifndef NO_MD4 + else if (XSTRNCMP("MD4", evp, 3) == 0) { + hash = WC_HASH_TYPE_MD4; + } +#endif +#ifndef NO_MD5 + else if (XSTRNCMP("MD5", evp, 3) == 0) { + hash = WC_HASH_TYPE_MD5; + } +#endif + + if (pHash) + *pHash = hash; + + hashSz = wc_HashGetDigestSize(hash); + if (pHashSz) + *pHashSz = hashSz; + + if (hashSz < 0) { + return WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; +} + +#endif + + +#ifdef OPENSSL_EXTRA +/* put SSL type in extra for now, not very common */ + +/* Converts a DER format key read from "bio" to a PKCS8 structure. + * + * bio input bio to read DER from + * pkey If not NULL then this pointer will be overwritten with a new PKCS8 + * structure. + * + * returns a WOLFSSL_PKCS8_PRIV_KEY_INFO pointer on success and NULL in fail + * case. + */ +WOLFSSL_PKCS8_PRIV_KEY_INFO* wolfSSL_d2i_PKCS8_PKEY_bio(WOLFSSL_BIO* bio, + WOLFSSL_PKCS8_PRIV_KEY_INFO** pkey) +{ + WOLFSSL_PKCS8_PRIV_KEY_INFO* pkcs8 = NULL; +#ifdef WOLFSSL_PEM_TO_DER + unsigned char* mem; + int memSz; + int keySz; + word32 algId; + + WOLFSSL_MSG("wolfSSL_d2i_PKCS8_PKEY_bio()"); + + if (bio == NULL) { + return NULL; + } + + if ((memSz = wolfSSL_BIO_get_mem_data(bio, &mem)) < 0) { + return NULL; + } + + if ((keySz = wc_KeyPemToDer(mem, memSz, mem, memSz, NULL)) < 0) { + WOLFSSL_MSG("Not PEM format"); + keySz = memSz; + if ((keySz = ToTraditional_ex((byte*)mem, (word32)keySz, &algId)) < 0) { + return NULL; + } + } + + pkcs8 = wolfSSL_PKEY_new(); + if (pkcs8 == NULL) { + return NULL; + } + + pkcs8->pkey.ptr = (char*)XMALLOC(keySz, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + if (pkcs8->pkey.ptr == NULL) { + wolfSSL_EVP_PKEY_free(pkcs8); + return NULL; + } + XMEMCPY(pkcs8->pkey.ptr, mem, keySz); + pkcs8->pkey_sz = keySz; + + if (pkey != NULL) { + *pkey = pkcs8; + } +#else + (void)bio; + (void)pkey; +#endif /* WOLFSSL_PEM_TO_DER */ + + return pkcs8; +} + + +/* expecting DER format public key + * + * bio input bio to read DER from + * out If not NULL then this pointer will be overwritten with a new + * WOLFSSL_EVP_PKEY pointer + * + * returns a WOLFSSL_EVP_PKEY pointer on success and NULL in fail case. + */ +WOLFSSL_EVP_PKEY* wolfSSL_d2i_PUBKEY_bio(WOLFSSL_BIO* bio, + WOLFSSL_EVP_PKEY** out) +{ + unsigned char* mem; + long memSz; + WOLFSSL_EVP_PKEY* pkey = NULL; + + WOLFSSL_ENTER("wolfSSL_d2i_PUBKEY_bio()"); + + if (bio == NULL) { + return NULL; + } + (void)out; + + memSz = wolfSSL_BIO_pending(bio); + if (memSz <= 0) { + return NULL; + } + + mem = (unsigned char*)XMALLOC(memSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (mem == NULL) { + return NULL; + } + + if (wolfSSL_BIO_read(bio, mem, (int)memSz) == memSz) { + pkey = wolfSSL_d2i_PUBKEY(NULL, &mem, memSz); + if (out != NULL && pkey != NULL) { + *out = pkey; + } + } + + XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + return pkey; +} + + + +/* Converts a DER encoded public key to a WOLFSSL_EVP_PKEY structure. + * + * out pointer to new WOLFSSL_EVP_PKEY structure. Can be NULL + * in DER buffer to convert + * inSz size of in buffer + * + * returns a pointer to a new WOLFSSL_EVP_PKEY structure on success and NULL + * on fail + */ +WOLFSSL_EVP_PKEY* wolfSSL_d2i_PUBKEY(WOLFSSL_EVP_PKEY** out, unsigned char** in, + long inSz) +{ + WOLFSSL_EVP_PKEY* pkey = NULL; + const unsigned char* mem; + long memSz = inSz; + + WOLFSSL_ENTER("wolfSSL_d2i_PUBKEY"); + + if (in == NULL || inSz < 0) { + WOLFSSL_MSG("Bad argument"); + return NULL; + } + mem = *in; + + #if !defined(NO_RSA) + { + RsaKey rsa; + word32 keyIdx = 0; + + /* test if RSA key */ + if (wc_InitRsaKey(&rsa, NULL) == 0 && + wc_RsaPublicKeyDecode(mem, &keyIdx, &rsa, (word32)memSz) == 0) { + wc_FreeRsaKey(&rsa); + pkey = wolfSSL_PKEY_new(); + if (pkey != NULL) { + pkey->pkey_sz = keyIdx; + pkey->pkey.ptr = (char*)XMALLOC(memSz, NULL, + DYNAMIC_TYPE_PUBLIC_KEY); + if (pkey->pkey.ptr == NULL) { + wolfSSL_EVP_PKEY_free(pkey); + return NULL; + } + XMEMCPY(pkey->pkey.ptr, mem, keyIdx); + pkey->type = EVP_PKEY_RSA; + if (out != NULL) { + *out = pkey; + } + + pkey->ownRsa = 1; + pkey->rsa = wolfSSL_RSA_new(); + if (pkey->rsa == NULL) { + wolfSSL_EVP_PKEY_free(pkey); + return NULL; + } + + if (wolfSSL_RSA_LoadDer_ex(pkey->rsa, + (const unsigned char*)pkey->pkey.ptr, + pkey->pkey_sz, WOLFSSL_RSA_LOAD_PUBLIC) != 1) { + wolfSSL_EVP_PKEY_free(pkey); + return NULL; + } + + return pkey; + } + } + wc_FreeRsaKey(&rsa); + } + #endif /* NO_RSA */ + + #ifdef HAVE_ECC + { + word32 keyIdx = 0; + ecc_key ecc; + + if (wc_ecc_init(&ecc) == 0 && + wc_EccPublicKeyDecode(mem, &keyIdx, &ecc, (word32)memSz) == 0) { + wc_ecc_free(&ecc); + pkey = wolfSSL_PKEY_new(); + if (pkey != NULL) { + pkey->pkey_sz = keyIdx; + pkey->pkey.ptr = (char*)XMALLOC(keyIdx, NULL, + DYNAMIC_TYPE_PUBLIC_KEY); + if (pkey->pkey.ptr == NULL) { + wolfSSL_EVP_PKEY_free(pkey); + return NULL; + } + XMEMCPY(pkey->pkey.ptr, mem, keyIdx); + pkey->type = EVP_PKEY_EC; + if (out != NULL) { + *out = pkey; + } + + pkey->ownEcc = 1; + pkey->ecc = wolfSSL_EC_KEY_new(); + if (pkey->ecc == NULL) { + wolfSSL_EVP_PKEY_free(pkey); + return NULL; + } + + if (wolfSSL_EC_KEY_LoadDer_ex(pkey->ecc, + (const unsigned char*)pkey->pkey.ptr, + pkey->pkey_sz, WOLFSSL_EC_KEY_LOAD_PUBLIC) != 1) { + wolfSSL_EVP_PKEY_free(pkey); + return NULL; + } + + return pkey; + } + } + wc_ecc_free(&ecc); + } + #endif /* HAVE_ECC */ + + return pkey; + +} + + +/* Reads in a DER format key. If PKCS8 headers are found they are stripped off. + * + * type type of key + * out newly created WOLFSSL_EVP_PKEY structure + * in pointer to input key DER + * inSz size of in buffer + * + * On success a non null pointer is returned and the pointer in is advanced the + * same number of bytes read. + */ +WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey(int type, WOLFSSL_EVP_PKEY** out, + const unsigned char **in, long inSz) +{ + WOLFSSL_EVP_PKEY* local; + word32 idx = 0; + int ret; + word32 algId; + + WOLFSSL_ENTER("wolfSSL_d2i_PrivateKey"); + + if (in == NULL || inSz < 0) { + WOLFSSL_MSG("Bad argument"); + return NULL; + } + + /* Check if input buffer has PKCS8 header. In the case that it does not + * have a PKCS8 header then do not error out. */ + if ((ret = ToTraditionalInline_ex((const byte*)(*in), &idx, (word32)inSz, + &algId)) > 0) { + WOLFSSL_MSG("Found and removed PKCS8 header"); + } + else { + if (ret != ASN_PARSE_E) { + WOLFSSL_MSG("Unexpected error with trying to remove PKCS8 header"); + return NULL; + } + } + + if (out != NULL && *out != NULL) { + wolfSSL_EVP_PKEY_free(*out); + *out = NULL; + } + local = wolfSSL_PKEY_new(); + if (local == NULL) { + return NULL; + } + + /* sanity check on idx before use */ + if ((int)idx > inSz) { + WOLFSSL_MSG("Issue with index pointer"); + wolfSSL_EVP_PKEY_free(local); + local = NULL; + return NULL; + } + + local->type = type; + local->pkey_sz = (int)inSz - idx; + local->pkey.ptr = (char*)XMALLOC(inSz - idx, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + if (local->pkey.ptr == NULL) { + wolfSSL_EVP_PKEY_free(local); + local = NULL; + return NULL; + } + else { + XMEMCPY(local->pkey.ptr, *in + idx, inSz - idx); + } + + switch (type) { +#ifndef NO_RSA + case EVP_PKEY_RSA: + local->ownRsa = 1; + local->rsa = wolfSSL_RSA_new(); + if (local->rsa == NULL) { + wolfSSL_EVP_PKEY_free(local); + return NULL; + } + if (wolfSSL_RSA_LoadDer_ex(local->rsa, + (const unsigned char*)local->pkey.ptr, local->pkey_sz, + WOLFSSL_RSA_LOAD_PRIVATE) != SSL_SUCCESS) { + wolfSSL_EVP_PKEY_free(local); + return NULL; + } + break; +#endif /* NO_RSA */ +#ifdef HAVE_ECC + case EVP_PKEY_EC: + local->ownEcc = 1; + local->ecc = wolfSSL_EC_KEY_new(); + if (local->ecc == NULL) { + wolfSSL_EVP_PKEY_free(local); + return NULL; + } + if (wolfSSL_EC_KEY_LoadDer(local->ecc, + (const unsigned char*)local->pkey.ptr, local->pkey_sz) + != SSL_SUCCESS) { + wolfSSL_EVP_PKEY_free(local); + return NULL; + } + break; +#endif /* HAVE_ECC */ + + default: + WOLFSSL_MSG("Unsupported key type"); + wolfSSL_EVP_PKEY_free(local); + return NULL; + } + + /* advance pointer with success */ + if (local != NULL) { + if ((idx + local->pkey_sz) <= (word32)inSz) { + *in = *in + idx + local->pkey_sz; + } + + if (out != NULL) { + *out = local; + } + } + + return local; +} + +#ifndef NO_WOLFSSL_STUB +long wolfSSL_ctrl(WOLFSSL* ssl, int cmd, long opt, void* pt) +{ + WOLFSSL_STUB("SSL_ctrl"); + (void)ssl; + (void)cmd; + (void)opt; + (void)pt; + return WOLFSSL_FAILURE; +} +#endif + +#ifndef NO_WOLFSSL_STUB +long wolfSSL_CTX_ctrl(WOLFSSL_CTX* ctx, int cmd, long opt, void* pt) +{ + WOLFSSL_STUB("SSL_CTX_ctrl"); + (void)ctx; + (void)cmd; + (void)opt; + (void)pt; + return WOLFSSL_FAILURE; +} +#endif + +#ifndef NO_CERTS + +int wolfSSL_check_private_key(const WOLFSSL* ssl) +{ + DecodedCert der; + word32 size; + byte* buff; + int ret; + + if (ssl == NULL) { + return WOLFSSL_FAILURE; + } + + size = ssl->buffers.certificate->length; + buff = ssl->buffers.certificate->buffer; + InitDecodedCert(&der, buff, size, ssl->heap); +#ifdef HAVE_PK_CALLBACKS + ret = InitSigPkCb((WOLFSSL*)ssl, &der.sigCtx); + if (ret != 0) { + FreeDecodedCert(&der); + return ret; + } +#endif + + if (ParseCertRelative(&der, CERT_TYPE, NO_VERIFY, NULL) != 0) { + FreeDecodedCert(&der); + return WOLFSSL_FAILURE; + } + + size = ssl->buffers.key->length; + buff = ssl->buffers.key->buffer; + ret = wc_CheckPrivateKey(buff, size, &der); + FreeDecodedCert(&der); + return ret; +} + + +/* Looks for the extension matching the passed in nid + * + * c : if not null then is set to status value -2 if multiple occurrences + * of the extension are found, -1 if not found, 0 if found and not + * critical, and 1 if found and critical. + * nid : Extension OID to be found. + * idx : if NULL return first extension found match, otherwise start search at + * idx location and set idx to the location of extension returned. + * returns NULL or a pointer to an WOLFSSL_STACK holding extension structure + * + * NOTE code for decoding extensions is in asn.c DecodeCertExtensions -- + * use already decoded extension in this function to avoid decoding twice. + * Currently we do not make use of idx since getting pre decoded extensions. + */ +void* wolfSSL_X509_get_ext_d2i(const WOLFSSL_X509* x509, + int nid, int* c, int* idx) +{ + WOLFSSL_STACK* sk = NULL; + WOLFSSL_ASN1_OBJECT* obj = NULL; + + WOLFSSL_ENTER("wolfSSL_X509_get_ext_d2i"); + + if (x509 == NULL) { + return NULL; + } + + if (c != NULL) { + *c = -1; /* default to not found */ + } + + sk = (WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)*)XMALLOC( + sizeof(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)), NULL, DYNAMIC_TYPE_ASN1); + if (sk == NULL) { + return NULL; + } + XMEMSET(sk, 0, sizeof(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT))); + + switch (nid) { + case BASIC_CA_OID: + if (x509->basicConstSet) { + obj = wolfSSL_ASN1_OBJECT_new(); + if (obj == NULL) { + WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct"); + wolfSSL_sk_ASN1_OBJECT_free(sk); + return NULL; + } + if (c != NULL) { + *c = x509->basicConstCrit; + } + obj->type = BASIC_CA_OID; + obj->grp = oidCertExtType; + obj->dynamic |= WOLFSSL_ASN1_DYNAMIC; + } + else { + WOLFSSL_MSG("No Basic Constraint set"); + } + break; + + case ALT_NAMES_OID: + { + DNS_entry* dns = NULL; + + if (x509->subjAltNameSet && x509->altNames != NULL) { + /* alt names are DNS_entry structs */ + if (c != NULL) { + if (x509->altNames->next != NULL) { + *c = -2; /* more then one found */ + } + else { + *c = x509->subjAltNameCrit; + } + } + + dns = x509->altNames; + while (dns != NULL) { + obj = wolfSSL_ASN1_OBJECT_new(); + if (obj == NULL) { + WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct"); + wolfSSL_sk_ASN1_OBJECT_free(sk); + return NULL; + } + obj->type = dns->type; + obj->grp = oidCertExtType; + obj->obj = (byte*)dns->name; + obj->dynamic |= WOLFSSL_ASN1_DYNAMIC; + obj->dynamic &= ~WOLFSSL_ASN1_DYNAMIC_DATA ; + + /* set app derefrenced pointers */ + obj->d.ia5_internal.data = dns->name; + obj->d.ia5_internal.length = (int)XSTRLEN(dns->name); + dns = dns->next; + /* last dns in list add at end of function */ + if (dns != NULL) { + if (wolfSSL_sk_ASN1_OBJECT_push(sk, obj) != + WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Error pushing ASN1 object onto stack"); + wolfSSL_ASN1_OBJECT_free(obj); + wolfSSL_sk_ASN1_OBJECT_free(sk); + sk = NULL; + } + } + } + } + else { + WOLFSSL_MSG("No Alt Names set"); + } + } + break; + + case CRL_DIST_OID: + if (x509->CRLdistSet && x509->CRLInfo != NULL) { + if (c != NULL) { + *c = x509->CRLdistCrit; + } + obj = wolfSSL_ASN1_OBJECT_new(); + if (obj == NULL) { + WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct"); + wolfSSL_sk_ASN1_OBJECT_free(sk); + return NULL; + } + obj->type = CRL_DIST_OID; + obj->grp = oidCertExtType; + obj->obj = x509->CRLInfo; + obj->objSz = x509->CRLInfoSz; + obj->dynamic |= WOLFSSL_ASN1_DYNAMIC; + obj->dynamic &= ~WOLFSSL_ASN1_DYNAMIC_DATA ; + } + else { + WOLFSSL_MSG("No CRL dist set"); + } + break; + + case AUTH_INFO_OID: + if (x509->authInfoSet && x509->authInfo != NULL) { + if (c != NULL) { + *c = x509->authInfoCrit; + } + obj = wolfSSL_ASN1_OBJECT_new(); + if (obj == NULL) { + WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct"); + wolfSSL_sk_ASN1_OBJECT_free(sk); + return NULL; + } + obj->type = AUTH_INFO_OID; + obj->grp = oidCertExtType; + obj->obj = x509->authInfo; + obj->objSz = x509->authInfoSz; + obj->dynamic |= WOLFSSL_ASN1_DYNAMIC; + obj->dynamic &= ~WOLFSSL_ASN1_DYNAMIC_DATA; + } + else { + WOLFSSL_MSG("No Auth Info set"); + } + break; + + case AUTH_KEY_OID: + if (x509->authKeyIdSet) { + if (c != NULL) { + *c = x509->authKeyIdCrit; + } + obj = wolfSSL_ASN1_OBJECT_new(); + if (obj == NULL) { + WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct"); + wolfSSL_sk_ASN1_OBJECT_free(sk); + return NULL; + } + obj->type = AUTH_KEY_OID; + obj->grp = oidCertExtType; + obj->obj = x509->authKeyId; + obj->objSz = x509->authKeyIdSz; + obj->dynamic |= WOLFSSL_ASN1_DYNAMIC; + obj->dynamic &= ~WOLFSSL_ASN1_DYNAMIC_DATA; + } + else { + WOLFSSL_MSG("No Auth Key set"); + } + break; + + case SUBJ_KEY_OID: + if (x509->subjKeyIdSet) { + if (c != NULL) { + *c = x509->subjKeyIdCrit; + } + obj = wolfSSL_ASN1_OBJECT_new(); + if (obj == NULL) { + WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct"); + wolfSSL_sk_ASN1_OBJECT_free(sk); + return NULL; + } + obj->type = SUBJ_KEY_OID; + obj->grp = oidCertExtType; + obj->obj = x509->subjKeyId; + obj->objSz = x509->subjKeyIdSz; + obj->dynamic |= WOLFSSL_ASN1_DYNAMIC; + obj->dynamic &= ~WOLFSSL_ASN1_DYNAMIC_DATA; + } + else { + WOLFSSL_MSG("No Subject Key set"); + } + break; + + case CERT_POLICY_OID: + #ifdef WOLFSSL_CERT_EXT + { + int i; + + if (x509->certPoliciesNb > 0) { + if (c != NULL) { + if (x509->certPoliciesNb > 1) { + *c = -2; + } + else { + *c = 0; + } + } + + for (i = 0; i < x509->certPoliciesNb - 1; i++) { + obj = wolfSSL_ASN1_OBJECT_new(); + if (obj == NULL) { + WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct"); + wolfSSL_sk_ASN1_OBJECT_free(sk); + return NULL; + } + obj->type = CERT_POLICY_OID; + obj->grp = oidCertExtType; + obj->obj = (byte*)(x509->certPolicies[i]); + obj->objSz = MAX_CERTPOL_SZ; + obj->dynamic |= WOLFSSL_ASN1_DYNAMIC; + obj->dynamic &= ~WOLFSSL_ASN1_DYNAMIC_DATA; + if (wolfSSL_sk_ASN1_OBJECT_push(sk, obj) + != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Error pushing ASN1 object onto stack"); + wolfSSL_ASN1_OBJECT_free(obj); + wolfSSL_sk_ASN1_OBJECT_free(sk); + sk = NULL; + } + } + obj = wolfSSL_ASN1_OBJECT_new(); + if (obj == NULL) { + WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct"); + wolfSSL_sk_ASN1_OBJECT_free(sk); + return NULL; + } + obj->type = CERT_POLICY_OID; + obj->grp = oidCertExtType; + obj->obj = (byte*)(x509->certPolicies[i]); + obj->objSz = MAX_CERTPOL_SZ; + obj->dynamic |= WOLFSSL_ASN1_DYNAMIC; + obj->dynamic &= ~WOLFSSL_ASN1_DYNAMIC_DATA; + } + else { + WOLFSSL_MSG("No Cert Policy set"); + } + } + #else + #ifdef WOLFSSL_SEP + if (x509->certPolicySet) { + if (c != NULL) { + *c = x509->certPolicyCrit; + } + obj = wolfSSL_ASN1_OBJECT_new(); + if (obj == NULL) { + WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct"); + wolfSSL_sk_ASN1_OBJECT_free(sk); + return NULL; + } + obj->type = CERT_POLICY_OID; + obj->grp = oidCertExtType; + obj->dynamic |= WOLFSSL_ASN1_DYNAMIC; + } + else { + WOLFSSL_MSG("No Cert Policy set"); + } + #else + WOLFSSL_MSG("wolfSSL not built with WOLFSSL_SEP or WOLFSSL_CERT_EXT"); + #endif /* WOLFSSL_SEP */ + #endif /* WOLFSSL_CERT_EXT */ + break; + + case KEY_USAGE_OID: + if (x509->keyUsageSet) { + if (c != NULL) { + *c = x509->keyUsageCrit; + } + obj = wolfSSL_ASN1_OBJECT_new(); + if (obj == NULL) { + WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct"); + wolfSSL_sk_ASN1_OBJECT_free(sk); + return NULL; + } + obj->type = KEY_USAGE_OID; + obj->grp = oidCertExtType; + obj->obj = (byte*)&(x509->keyUsage); + obj->objSz = sizeof(word16); + obj->dynamic |= WOLFSSL_ASN1_DYNAMIC; + obj->dynamic &= ~WOLFSSL_ASN1_DYNAMIC_DATA; + } + else { + WOLFSSL_MSG("No Key Usage set"); + } + break; + + case INHIBIT_ANY_OID: + WOLFSSL_MSG("INHIBIT ANY extension not supported"); + break; + + case EXT_KEY_USAGE_OID: + if (x509->extKeyUsageSrc != NULL) { + if (c != NULL) { + if (x509->extKeyUsageCount > 1) { + *c = -2; + } + else { + *c = x509->extKeyUsageCrit; + } + } + obj = wolfSSL_ASN1_OBJECT_new(); + if (obj == NULL) { + WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct"); + wolfSSL_sk_ASN1_OBJECT_free(sk); + return NULL; + } + obj->type = EXT_KEY_USAGE_OID; + obj->grp = oidCertExtType; + obj->obj = x509->extKeyUsageSrc; + obj->objSz = x509->extKeyUsageSz; + obj->dynamic |= WOLFSSL_ASN1_DYNAMIC; + obj->dynamic &= ~WOLFSSL_ASN1_DYNAMIC_DATA; + } + else { + WOLFSSL_MSG("No Extended Key Usage set"); + } + break; + + case NAME_CONS_OID: + WOLFSSL_MSG("Name Constraint OID extension not supported"); + break; + + case PRIV_KEY_USAGE_PERIOD_OID: + WOLFSSL_MSG("Private Key Usage Period extension not supported"); + break; + + case SUBJECT_INFO_ACCESS: + WOLFSSL_MSG("Subject Info Access extension not supported"); + break; + + case POLICY_MAP_OID: + WOLFSSL_MSG("Policy Map extension not supported"); + break; + + case POLICY_CONST_OID: + WOLFSSL_MSG("Policy Constraint extension not supported"); + break; + + case ISSUE_ALT_NAMES_OID: + WOLFSSL_MSG("Issue Alt Names extension not supported"); + break; + + case TLS_FEATURE_OID: + WOLFSSL_MSG("TLS Feature extension not supported"); + break; + + default: + WOLFSSL_MSG("Unsupported/Unknown extension OID"); + } + + if (obj != NULL) { + if (wolfSSL_sk_ASN1_OBJECT_push(sk, obj) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Error pushing ASN1 object onto stack"); + wolfSSL_ASN1_OBJECT_free(obj); + wolfSSL_sk_ASN1_OBJECT_free(sk); + sk = NULL; + } + } + else { /* no ASN1 object found for extension, free stack */ + wolfSSL_sk_ASN1_OBJECT_free(sk); + sk = NULL; + } + + (void)idx; + + return sk; +} + + +/* this function makes the assumption that out buffer is big enough for digest*/ +int wolfSSL_EVP_Digest(unsigned char* in, int inSz, unsigned char* out, + unsigned int* outSz, const WOLFSSL_EVP_MD* evp, + WOLFSSL_ENGINE* eng) +{ + int err; + int hashType = WC_HASH_TYPE_NONE; + int hashSz; + + (void)eng; + + err = wolfSSL_EVP_get_hashinfo(evp, &hashType, &hashSz); + if (err != WOLFSSL_SUCCESS) + return err; + + *outSz = hashSz; + + if (wc_Hash((enum wc_HashType)hashType, in, inSz, out, *outSz) != 0) { + return WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; +} + + +int wolfSSL_X509_digest(const WOLFSSL_X509* x509, const WOLFSSL_EVP_MD* digest, + unsigned char* buf, unsigned int* len) +{ + WOLFSSL_ENTER("wolfSSL_X509_digest"); + + if (x509 == NULL || digest == NULL) { + return WOLFSSL_FAILURE; + } + + return wolfSSL_EVP_Digest(x509->derCert->buffer, x509->derCert->length, buf, + len, digest, NULL); +} + + +int wolfSSL_use_PrivateKey(WOLFSSL* ssl, WOLFSSL_EVP_PKEY* pkey) +{ + WOLFSSL_ENTER("wolfSSL_use_PrivateKey"); + if (ssl == NULL || pkey == NULL ) { + return WOLFSSL_FAILURE; + } + + return wolfSSL_use_PrivateKey_buffer(ssl, (unsigned char*)pkey->pkey.ptr, + pkey->pkey_sz, WOLFSSL_FILETYPE_ASN1); +} + + +int wolfSSL_use_PrivateKey_ASN1(int pri, WOLFSSL* ssl, unsigned char* der, + long derSz) +{ + WOLFSSL_ENTER("wolfSSL_use_PrivateKey_ASN1"); + if (ssl == NULL || der == NULL ) { + return WOLFSSL_FAILURE; + } + + (void)pri; /* type of private key */ + return wolfSSL_use_PrivateKey_buffer(ssl, der, derSz, WOLFSSL_FILETYPE_ASN1); +} + + +#ifndef NO_RSA +int wolfSSL_use_RSAPrivateKey_ASN1(WOLFSSL* ssl, unsigned char* der, long derSz) +{ + WOLFSSL_ENTER("wolfSSL_use_RSAPrivateKey_ASN1"); + if (ssl == NULL || der == NULL ) { + return WOLFSSL_FAILURE; + } + + return wolfSSL_use_PrivateKey_buffer(ssl, der, derSz, WOLFSSL_FILETYPE_ASN1); +} +#endif + +int wolfSSL_use_certificate(WOLFSSL* ssl, WOLFSSL_X509* x509) +{ + long idx; + + WOLFSSL_ENTER("wolfSSL_use_certificate"); + if (x509 != NULL && ssl != NULL && x509->derCert != NULL) { + if (ProcessBuffer(NULL, x509->derCert->buffer, x509->derCert->length, + WOLFSSL_FILETYPE_ASN1, CERT_TYPE, ssl, &idx, 0) == WOLFSSL_SUCCESS) { + return WOLFSSL_SUCCESS; + } + } + + (void)idx; + return WOLFSSL_FAILURE; +} + +#endif /* NO_CERTS */ + +#endif /* OPENSSL_EXTRA */ + +#ifndef NO_CERTS +int wolfSSL_use_certificate_ASN1(WOLFSSL* ssl, unsigned char* der, int derSz) +{ + long idx; + + WOLFSSL_ENTER("wolfSSL_use_certificate_ASN1"); + if (der != NULL && ssl != NULL) { + if (ProcessBuffer(NULL, der, derSz, WOLFSSL_FILETYPE_ASN1, CERT_TYPE, + ssl, &idx, 0) == WOLFSSL_SUCCESS) { + return WOLFSSL_SUCCESS; + } + } + + (void)idx; + return WOLFSSL_FAILURE; +} + +#ifndef NO_FILESYSTEM + +int wolfSSL_use_certificate_file(WOLFSSL* ssl, const char* file, int format) +{ + WOLFSSL_ENTER("wolfSSL_use_certificate_file"); + if (ProcessFile(ssl->ctx, file, format, CERT_TYPE, + ssl, 0, NULL) == WOLFSSL_SUCCESS) + return WOLFSSL_SUCCESS; + + return WOLFSSL_FAILURE; +} + + +int wolfSSL_use_PrivateKey_file(WOLFSSL* ssl, const char* file, int format) +{ + WOLFSSL_ENTER("wolfSSL_use_PrivateKey_file"); + if (ProcessFile(ssl->ctx, file, format, PRIVATEKEY_TYPE, + ssl, 0, NULL) == WOLFSSL_SUCCESS) + return WOLFSSL_SUCCESS; + + return WOLFSSL_FAILURE; +} + + +int wolfSSL_use_certificate_chain_file(WOLFSSL* ssl, const char* file) +{ + /* process up to MAX_CHAIN_DEPTH plus subject cert */ + WOLFSSL_ENTER("wolfSSL_use_certificate_chain_file"); + if (ProcessFile(ssl->ctx, file, WOLFSSL_FILETYPE_PEM, CERT_TYPE, + ssl, 1, NULL) == WOLFSSL_SUCCESS) + return WOLFSSL_SUCCESS; + + return WOLFSSL_FAILURE; +} + +int wolfSSL_use_certificate_chain_file_format(WOLFSSL* ssl, const char* file, + int format) +{ + /* process up to MAX_CHAIN_DEPTH plus subject cert */ + WOLFSSL_ENTER("wolfSSL_use_certificate_chain_file_format"); + if (ProcessFile(ssl->ctx, file, format, CERT_TYPE, ssl, 1, + NULL) == WOLFSSL_SUCCESS) + return WOLFSSL_SUCCESS; + + return WOLFSSL_FAILURE; +} + +#endif /* !NO_FILESYSTEM */ +#endif /* !NO_CERTS */ + +#ifdef HAVE_ECC + +/* Set Temp CTX EC-DHE size in octets, should be 20 - 66 for 160 - 521 bit */ +int wolfSSL_CTX_SetTmpEC_DHE_Sz(WOLFSSL_CTX* ctx, word16 sz) +{ + if (ctx == NULL) + return BAD_FUNC_ARG; + + if (sz == 0) { + /* applies only to ECDSA */ + if (ctx->privateKeyType != ecc_dsa_sa_algo) + return WOLFSSL_SUCCESS; + + if (ctx->privateKeySz == 0) { + WOLFSSL_MSG("Must set private key/cert first"); + return BAD_FUNC_ARG; + } + + sz = (word16)ctx->privateKeySz; + } + + /* check size */ + if (sz < ECC_MINSIZE || sz > ECC_MAXSIZE) + return BAD_FUNC_ARG; + + ctx->eccTempKeySz = sz; + + return WOLFSSL_SUCCESS; +} + + +/* Set Temp SSL EC-DHE size in octets, should be 20 - 66 for 160 - 521 bit */ +int wolfSSL_SetTmpEC_DHE_Sz(WOLFSSL* ssl, word16 sz) +{ + if (ssl == NULL || sz < ECC_MINSIZE || sz > ECC_MAXSIZE) + return BAD_FUNC_ARG; + + ssl->eccTempKeySz = sz; + + return WOLFSSL_SUCCESS; +} + +#endif /* HAVE_ECC */ + + +#ifdef OPENSSL_EXTRA + +#ifndef NO_FILESYSTEM +int wolfSSL_CTX_use_RSAPrivateKey_file(WOLFSSL_CTX* ctx,const char* file, + int format) +{ + WOLFSSL_ENTER("SSL_CTX_use_RSAPrivateKey_file"); + + return wolfSSL_CTX_use_PrivateKey_file(ctx, file, format); +} + + +int wolfSSL_use_RSAPrivateKey_file(WOLFSSL* ssl, const char* file, int format) +{ + WOLFSSL_ENTER("wolfSSL_use_RSAPrivateKey_file"); + + return wolfSSL_use_PrivateKey_file(ssl, file, format); +} +#endif /* NO_FILESYSTEM */ + + +/* Copies the master secret over to out buffer. If outSz is 0 returns the size + * of master secret. + * + * ses : a session from completed TLS/SSL handshake + * out : buffer to hold copy of master secret + * outSz : size of out buffer + * returns : number of bytes copied into out buffer on success + * less then or equal to 0 is considered a failure case + */ +int wolfSSL_SESSION_get_master_key(const WOLFSSL_SESSION* ses, + unsigned char* out, int outSz) +{ + int size; + + if (outSz == 0) { + return SECRET_LEN; + } + + if (ses == NULL || out == NULL || outSz < 0) { + return 0; + } + + if (outSz > SECRET_LEN) { + size = SECRET_LEN; + } + else { + size = outSz; + } + + XMEMCPY(out, ses->masterSecret, size); + return size; +} + + +int wolfSSL_SESSION_get_master_key_length(const WOLFSSL_SESSION* ses) +{ + (void)ses; + return SECRET_LEN; +} + +#endif /* OPENSSL_EXTRA */ + +#ifndef NO_FILESYSTEM +#ifdef HAVE_NTRU + +int wolfSSL_CTX_use_NTRUPrivateKey_file(WOLFSSL_CTX* ctx, const char* file) +{ + WOLFSSL_ENTER("wolfSSL_CTX_use_NTRUPrivateKey_file"); + if (ctx == NULL) + return WOLFSSL_FAILURE; + + if (ProcessFile(ctx, file, WOLFSSL_FILETYPE_RAW, PRIVATEKEY_TYPE, NULL, 0, NULL) + == WOLFSSL_SUCCESS) { + ctx->haveNTRU = 1; + return WOLFSSL_SUCCESS; + } + + return WOLFSSL_FAILURE; +} + +#endif /* HAVE_NTRU */ + + +#endif /* NO_FILESYSTEM */ + + +void wolfSSL_CTX_set_verify(WOLFSSL_CTX* ctx, int mode, VerifyCallback vc) +{ + WOLFSSL_ENTER("wolfSSL_CTX_set_verify"); + if (ctx == NULL) + return; + + if (mode & WOLFSSL_VERIFY_PEER) { + ctx->verifyPeer = 1; + ctx->verifyNone = 0; /* in case previously set */ + } + + if (mode == WOLFSSL_VERIFY_NONE) { + ctx->verifyNone = 1; + ctx->verifyPeer = 0; /* in case previously set */ + } + + if (mode & WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT) + ctx->failNoCert = 1; + + if (mode & WOLFSSL_VERIFY_FAIL_EXCEPT_PSK) { + ctx->failNoCert = 0; /* fail on all is set to fail on PSK */ + ctx->failNoCertxPSK = 1; + } + + ctx->verifyCallback = vc; +} + + +void wolfSSL_set_verify(WOLFSSL* ssl, int mode, VerifyCallback vc) +{ + WOLFSSL_ENTER("wolfSSL_set_verify"); + if (ssl == NULL) + return; + + if (mode & WOLFSSL_VERIFY_PEER) { + ssl->options.verifyPeer = 1; + ssl->options.verifyNone = 0; /* in case previously set */ + } + + if (mode == WOLFSSL_VERIFY_NONE) { + ssl->options.verifyNone = 1; + ssl->options.verifyPeer = 0; /* in case previously set */ + } + + if (mode & WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT) + ssl->options.failNoCert = 1; + + if (mode & WOLFSSL_VERIFY_FAIL_EXCEPT_PSK) { + ssl->options.failNoCert = 0; /* fail on all is set to fail on PSK */ + ssl->options.failNoCertxPSK = 1; + } + + ssl->verifyCallback = vc; +} + + +/* store user ctx for verify callback */ +void wolfSSL_SetCertCbCtx(WOLFSSL* ssl, void* ctx) +{ + WOLFSSL_ENTER("wolfSSL_SetCertCbCtx"); + if (ssl) + ssl->verifyCbCtx = ctx; +} + + +/* store context CA Cache addition callback */ +void wolfSSL_CTX_SetCACb(WOLFSSL_CTX* ctx, CallbackCACache cb) +{ + if (ctx && ctx->cm) + ctx->cm->caCacheCallback = cb; +} + + +#if defined(PERSIST_CERT_CACHE) + +#if !defined(NO_FILESYSTEM) + +/* Persist cert cache to file */ +int wolfSSL_CTX_save_cert_cache(WOLFSSL_CTX* ctx, const char* fname) +{ + WOLFSSL_ENTER("wolfSSL_CTX_save_cert_cache"); + + if (ctx == NULL || fname == NULL) + return BAD_FUNC_ARG; + + return CM_SaveCertCache(ctx->cm, fname); +} + + +/* Persist cert cache from file */ +int wolfSSL_CTX_restore_cert_cache(WOLFSSL_CTX* ctx, const char* fname) +{ + WOLFSSL_ENTER("wolfSSL_CTX_restore_cert_cache"); + + if (ctx == NULL || fname == NULL) + return BAD_FUNC_ARG; + + return CM_RestoreCertCache(ctx->cm, fname); +} + +#endif /* NO_FILESYSTEM */ + +/* Persist cert cache to memory */ +int wolfSSL_CTX_memsave_cert_cache(WOLFSSL_CTX* ctx, void* mem, + int sz, int* used) +{ + WOLFSSL_ENTER("wolfSSL_CTX_memsave_cert_cache"); + + if (ctx == NULL || mem == NULL || used == NULL || sz <= 0) + return BAD_FUNC_ARG; + + return CM_MemSaveCertCache(ctx->cm, mem, sz, used); +} + + +/* Restore cert cache from memory */ +int wolfSSL_CTX_memrestore_cert_cache(WOLFSSL_CTX* ctx, const void* mem, int sz) +{ + WOLFSSL_ENTER("wolfSSL_CTX_memrestore_cert_cache"); + + if (ctx == NULL || mem == NULL || sz <= 0) + return BAD_FUNC_ARG; + + return CM_MemRestoreCertCache(ctx->cm, mem, sz); +} + + +/* get how big the the cert cache save buffer needs to be */ +int wolfSSL_CTX_get_cert_cache_memsize(WOLFSSL_CTX* ctx) +{ + WOLFSSL_ENTER("wolfSSL_CTX_get_cert_cache_memsize"); + + if (ctx == NULL) + return BAD_FUNC_ARG; + + return CM_GetCertCacheMemSize(ctx->cm); +} + +#endif /* PERSIST_CERT_CACHE */ +#endif /* !NO_CERTS */ + + +#ifndef NO_SESSION_CACHE + +WOLFSSL_SESSION* wolfSSL_get_session(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("SSL_get_session"); + if (ssl) + return GetSession(ssl, 0, 0); + + return NULL; +} + + +int wolfSSL_set_session(WOLFSSL* ssl, WOLFSSL_SESSION* session) +{ + WOLFSSL_ENTER("SSL_set_session"); + if (session) + return SetSession(ssl, session); + + return WOLFSSL_FAILURE; +} + + +#ifndef NO_CLIENT_CACHE + +/* Associate client session with serverID, find existing or store for saving + if newSession flag on, don't reuse existing session + WOLFSSL_SUCCESS on ok */ +int wolfSSL_SetServerID(WOLFSSL* ssl, const byte* id, int len, int newSession) +{ + WOLFSSL_SESSION* session = NULL; + + WOLFSSL_ENTER("wolfSSL_SetServerID"); + + if (ssl == NULL || id == NULL || len <= 0) + return BAD_FUNC_ARG; + + if (newSession == 0) { + session = GetSessionClient(ssl, id, len); + if (session) { + if (SetSession(ssl, session) != WOLFSSL_SUCCESS) { + #ifdef HAVE_EXT_CACHE + wolfSSL_SESSION_free(session); + #endif + WOLFSSL_MSG("SetSession failed"); + session = NULL; + } + } + } + + if (session == NULL) { + WOLFSSL_MSG("Valid ServerID not cached already"); + + ssl->session.idLen = (word16)min(SERVER_ID_LEN, (word32)len); + XMEMCPY(ssl->session.serverID, id, ssl->session.idLen); + } + #ifdef HAVE_EXT_CACHE + else + wolfSSL_SESSION_free(session); + #endif + + return WOLFSSL_SUCCESS; +} + +#endif /* NO_CLIENT_CACHE */ + +#if defined(PERSIST_SESSION_CACHE) + +/* for persistence, if changes to layout need to increment and modify + save_session_cache() and restore_session_cache and memory versions too */ +#define WOLFSSL_CACHE_VERSION 2 + +/* Session Cache Header information */ +typedef struct { + int version; /* cache layout version id */ + int rows; /* session rows */ + int columns; /* session columns */ + int sessionSz; /* sizeof WOLFSSL_SESSION */ +} cache_header_t; + +/* current persistence layout is: + + 1) cache_header_t + 2) SessionCache + 3) ClientCache + + update WOLFSSL_CACHE_VERSION if change layout for the following + PERSISTENT_SESSION_CACHE functions +*/ + + +/* get how big the the session cache save buffer needs to be */ +int wolfSSL_get_session_cache_memsize(void) +{ + int sz = (int)(sizeof(SessionCache) + sizeof(cache_header_t)); + + #ifndef NO_CLIENT_CACHE + sz += (int)(sizeof(ClientCache)); + #endif + + return sz; +} + + +/* Persist session cache to memory */ +int wolfSSL_memsave_session_cache(void* mem, int sz) +{ + int i; + cache_header_t cache_header; + SessionRow* row = (SessionRow*)((byte*)mem + sizeof(cache_header)); +#ifndef NO_CLIENT_CACHE + ClientRow* clRow; +#endif + + WOLFSSL_ENTER("wolfSSL_memsave_session_cache"); + + if (sz < wolfSSL_get_session_cache_memsize()) { + WOLFSSL_MSG("Memory buffer too small"); + return BUFFER_E; + } + + cache_header.version = WOLFSSL_CACHE_VERSION; + cache_header.rows = SESSION_ROWS; + cache_header.columns = SESSIONS_PER_ROW; + cache_header.sessionSz = (int)sizeof(WOLFSSL_SESSION); + XMEMCPY(mem, &cache_header, sizeof(cache_header)); + + if (wc_LockMutex(&session_mutex) != 0) { + WOLFSSL_MSG("Session cache mutex lock failed"); + return BAD_MUTEX_E; + } + + for (i = 0; i < cache_header.rows; ++i) + XMEMCPY(row++, SessionCache + i, sizeof(SessionRow)); + +#ifndef NO_CLIENT_CACHE + clRow = (ClientRow*)row; + for (i = 0; i < cache_header.rows; ++i) + XMEMCPY(clRow++, ClientCache + i, sizeof(ClientRow)); +#endif + + wc_UnLockMutex(&session_mutex); + + WOLFSSL_LEAVE("wolfSSL_memsave_session_cache", WOLFSSL_SUCCESS); + + return WOLFSSL_SUCCESS; +} + + +/* Restore the persistent session cache from memory */ +int wolfSSL_memrestore_session_cache(const void* mem, int sz) +{ + int i; + cache_header_t cache_header; + SessionRow* row = (SessionRow*)((byte*)mem + sizeof(cache_header)); +#ifndef NO_CLIENT_CACHE + ClientRow* clRow; +#endif + + WOLFSSL_ENTER("wolfSSL_memrestore_session_cache"); + + if (sz < wolfSSL_get_session_cache_memsize()) { + WOLFSSL_MSG("Memory buffer too small"); + return BUFFER_E; + } + + XMEMCPY(&cache_header, mem, sizeof(cache_header)); + if (cache_header.version != WOLFSSL_CACHE_VERSION || + cache_header.rows != SESSION_ROWS || + cache_header.columns != SESSIONS_PER_ROW || + cache_header.sessionSz != (int)sizeof(WOLFSSL_SESSION)) { + + WOLFSSL_MSG("Session cache header match failed"); + return CACHE_MATCH_ERROR; + } + + if (wc_LockMutex(&session_mutex) != 0) { + WOLFSSL_MSG("Session cache mutex lock failed"); + return BAD_MUTEX_E; + } + + for (i = 0; i < cache_header.rows; ++i) + XMEMCPY(SessionCache + i, row++, sizeof(SessionRow)); + +#ifndef NO_CLIENT_CACHE + clRow = (ClientRow*)row; + for (i = 0; i < cache_header.rows; ++i) + XMEMCPY(ClientCache + i, clRow++, sizeof(ClientRow)); +#endif + + wc_UnLockMutex(&session_mutex); + + WOLFSSL_LEAVE("wolfSSL_memrestore_session_cache", WOLFSSL_SUCCESS); + + return WOLFSSL_SUCCESS; +} + +#if !defined(NO_FILESYSTEM) + +/* Persist session cache to file */ +/* doesn't use memsave because of additional memory use */ +int wolfSSL_save_session_cache(const char *fname) +{ + XFILE file; + int ret; + int rc = WOLFSSL_SUCCESS; + int i; + cache_header_t cache_header; + + WOLFSSL_ENTER("wolfSSL_save_session_cache"); + + file = XFOPEN(fname, "w+b"); + if (file == XBADFILE) { + WOLFSSL_MSG("Couldn't open session cache save file"); + return WOLFSSL_BAD_FILE; + } + cache_header.version = WOLFSSL_CACHE_VERSION; + cache_header.rows = SESSION_ROWS; + cache_header.columns = SESSIONS_PER_ROW; + cache_header.sessionSz = (int)sizeof(WOLFSSL_SESSION); + + /* cache header */ + ret = (int)XFWRITE(&cache_header, sizeof cache_header, 1, file); + if (ret != 1) { + WOLFSSL_MSG("Session cache header file write failed"); + XFCLOSE(file); + return FWRITE_ERROR; + } + + if (wc_LockMutex(&session_mutex) != 0) { + WOLFSSL_MSG("Session cache mutex lock failed"); + XFCLOSE(file); + return BAD_MUTEX_E; + } + + /* session cache */ + for (i = 0; i < cache_header.rows; ++i) { + ret = (int)XFWRITE(SessionCache + i, sizeof(SessionRow), 1, file); + if (ret != 1) { + WOLFSSL_MSG("Session cache member file write failed"); + rc = FWRITE_ERROR; + break; + } + } + +#ifndef NO_CLIENT_CACHE + /* client cache */ + for (i = 0; i < cache_header.rows; ++i) { + ret = (int)XFWRITE(ClientCache + i, sizeof(ClientRow), 1, file); + if (ret != 1) { + WOLFSSL_MSG("Client cache member file write failed"); + rc = FWRITE_ERROR; + break; + } + } +#endif /* NO_CLIENT_CACHE */ + + wc_UnLockMutex(&session_mutex); + + XFCLOSE(file); + WOLFSSL_LEAVE("wolfSSL_save_session_cache", rc); + + return rc; +} + + +/* Restore the persistent session cache from file */ +/* doesn't use memstore because of additional memory use */ +int wolfSSL_restore_session_cache(const char *fname) +{ + XFILE file; + int rc = WOLFSSL_SUCCESS; + int ret; + int i; + cache_header_t cache_header; + + WOLFSSL_ENTER("wolfSSL_restore_session_cache"); + + file = XFOPEN(fname, "rb"); + if (file == XBADFILE) { + WOLFSSL_MSG("Couldn't open session cache save file"); + return WOLFSSL_BAD_FILE; + } + /* cache header */ + ret = (int)XFREAD(&cache_header, sizeof cache_header, 1, file); + if (ret != 1) { + WOLFSSL_MSG("Session cache header file read failed"); + XFCLOSE(file); + return FREAD_ERROR; + } + if (cache_header.version != WOLFSSL_CACHE_VERSION || + cache_header.rows != SESSION_ROWS || + cache_header.columns != SESSIONS_PER_ROW || + cache_header.sessionSz != (int)sizeof(WOLFSSL_SESSION)) { + + WOLFSSL_MSG("Session cache header match failed"); + XFCLOSE(file); + return CACHE_MATCH_ERROR; + } + + if (wc_LockMutex(&session_mutex) != 0) { + WOLFSSL_MSG("Session cache mutex lock failed"); + XFCLOSE(file); + return BAD_MUTEX_E; + } + + /* session cache */ + for (i = 0; i < cache_header.rows; ++i) { + ret = (int)XFREAD(SessionCache + i, sizeof(SessionRow), 1, file); + if (ret != 1) { + WOLFSSL_MSG("Session cache member file read failed"); + XMEMSET(SessionCache, 0, sizeof SessionCache); + rc = FREAD_ERROR; + break; + } + } + +#ifndef NO_CLIENT_CACHE + /* client cache */ + for (i = 0; i < cache_header.rows; ++i) { + ret = (int)XFREAD(ClientCache + i, sizeof(ClientRow), 1, file); + if (ret != 1) { + WOLFSSL_MSG("Client cache member file read failed"); + XMEMSET(ClientCache, 0, sizeof ClientCache); + rc = FREAD_ERROR; + break; + } + } + +#endif /* NO_CLIENT_CACHE */ + + wc_UnLockMutex(&session_mutex); + + XFCLOSE(file); + WOLFSSL_LEAVE("wolfSSL_restore_session_cache", rc); + + return rc; +} + +#endif /* !NO_FILESYSTEM */ +#endif /* PERSIST_SESSION_CACHE */ +#endif /* NO_SESSION_CACHE */ + + +void wolfSSL_load_error_strings(void) /* compatibility only */ +{} + + +int wolfSSL_library_init(void) +{ + WOLFSSL_ENTER("SSL_library_init"); + if (wolfSSL_Init() == WOLFSSL_SUCCESS) + return WOLFSSL_SUCCESS; + else + return WOLFSSL_FATAL_ERROR; +} + + +#ifdef HAVE_SECRET_CALLBACK + +int wolfSSL_set_session_secret_cb(WOLFSSL* ssl, SessionSecretCb cb, void* ctx) +{ + WOLFSSL_ENTER("wolfSSL_set_session_secret_cb"); + if (ssl == NULL) + return WOLFSSL_FATAL_ERROR; + + ssl->sessionSecretCb = cb; + ssl->sessionSecretCtx = ctx; + /* If using a pre-set key, assume session resumption. */ + ssl->session.sessionIDSz = 0; + ssl->options.resuming = 1; + + return WOLFSSL_SUCCESS; +} + +#endif + + +#ifndef NO_SESSION_CACHE + +/* on by default if built in but allow user to turn off */ +long wolfSSL_CTX_set_session_cache_mode(WOLFSSL_CTX* ctx, long mode) +{ + WOLFSSL_ENTER("SSL_CTX_set_session_cache_mode"); + if (mode == WOLFSSL_SESS_CACHE_OFF) + ctx->sessionCacheOff = 1; + + if ((mode & WOLFSSL_SESS_CACHE_NO_AUTO_CLEAR) != 0) + ctx->sessionCacheFlushOff = 1; + +#ifdef HAVE_EXT_CACHE + if ((mode & WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE) != 0) + ctx->internalCacheOff = 1; +#endif + + return WOLFSSL_SUCCESS; +} + +#endif /* NO_SESSION_CACHE */ + + +#if !defined(NO_CERTS) +#if defined(PERSIST_CERT_CACHE) + + +#define WOLFSSL_CACHE_CERT_VERSION 1 + +typedef struct { + int version; /* cache cert layout version id */ + int rows; /* hash table rows, CA_TABLE_SIZE */ + int columns[CA_TABLE_SIZE]; /* columns per row on list */ + int signerSz; /* sizeof Signer object */ +} CertCacheHeader; + +/* current cert persistence layout is: + + 1) CertCacheHeader + 2) caTable + + update WOLFSSL_CERT_CACHE_VERSION if change layout for the following + PERSIST_CERT_CACHE functions +*/ + + +/* Return memory needed to persist this signer, have lock */ +static WC_INLINE int GetSignerMemory(Signer* signer) +{ + int sz = sizeof(signer->pubKeySize) + sizeof(signer->keyOID) + + sizeof(signer->nameLen) + sizeof(signer->subjectNameHash); + +#if !defined(NO_SKID) + sz += (int)sizeof(signer->subjectKeyIdHash); +#endif + + /* add dynamic bytes needed */ + sz += signer->pubKeySize; + sz += signer->nameLen; + + return sz; +} + + +/* Return memory needed to persist this row, have lock */ +static WC_INLINE int GetCertCacheRowMemory(Signer* row) +{ + int sz = 0; + + while (row) { + sz += GetSignerMemory(row); + row = row->next; + } + + return sz; +} + + +/* get the size of persist cert cache, have lock */ +static WC_INLINE int GetCertCacheMemSize(WOLFSSL_CERT_MANAGER* cm) +{ + int sz; + int i; + + sz = sizeof(CertCacheHeader); + + for (i = 0; i < CA_TABLE_SIZE; i++) + sz += GetCertCacheRowMemory(cm->caTable[i]); + + return sz; +} + + +/* Store cert cache header columns with number of items per list, have lock */ +static WC_INLINE void SetCertHeaderColumns(WOLFSSL_CERT_MANAGER* cm, int* columns) +{ + int i; + Signer* row; + + for (i = 0; i < CA_TABLE_SIZE; i++) { + int count = 0; + row = cm->caTable[i]; + + while (row) { + ++count; + row = row->next; + } + columns[i] = count; + } +} + + +/* Restore whole cert row from memory, have lock, return bytes consumed, + < 0 on error, have lock */ +static WC_INLINE int RestoreCertRow(WOLFSSL_CERT_MANAGER* cm, byte* current, + int row, int listSz, const byte* end) +{ + int idx = 0; + + if (listSz < 0) { + WOLFSSL_MSG("Row header corrupted, negative value"); + return PARSE_ERROR; + } + + while (listSz) { + Signer* signer; + byte* publicKey; + byte* start = current + idx; /* for end checks on this signer */ + int minSz = sizeof(signer->pubKeySize) + sizeof(signer->keyOID) + + sizeof(signer->nameLen) + sizeof(signer->subjectNameHash); + #ifndef NO_SKID + minSz += (int)sizeof(signer->subjectKeyIdHash); + #endif + + if (start + minSz > end) { + WOLFSSL_MSG("Would overread restore buffer"); + return BUFFER_E; + } + signer = MakeSigner(cm->heap); + if (signer == NULL) + return MEMORY_E; + + /* pubKeySize */ + XMEMCPY(&signer->pubKeySize, current + idx, sizeof(signer->pubKeySize)); + idx += (int)sizeof(signer->pubKeySize); + + /* keyOID */ + XMEMCPY(&signer->keyOID, current + idx, sizeof(signer->keyOID)); + idx += (int)sizeof(signer->keyOID); + + /* pulicKey */ + if (start + minSz + signer->pubKeySize > end) { + WOLFSSL_MSG("Would overread restore buffer"); + FreeSigner(signer, cm->heap); + return BUFFER_E; + } + publicKey = (byte*)XMALLOC(signer->pubKeySize, cm->heap, + DYNAMIC_TYPE_KEY); + if (publicKey == NULL) { + FreeSigner(signer, cm->heap); + return MEMORY_E; + } + + XMEMCPY(publicKey, current + idx, signer->pubKeySize); + signer->publicKey = publicKey; + idx += signer->pubKeySize; + + /* nameLen */ + XMEMCPY(&signer->nameLen, current + idx, sizeof(signer->nameLen)); + idx += (int)sizeof(signer->nameLen); + + /* name */ + if (start + minSz + signer->pubKeySize + signer->nameLen > end) { + WOLFSSL_MSG("Would overread restore buffer"); + FreeSigner(signer, cm->heap); + return BUFFER_E; + } + signer->name = (char*)XMALLOC(signer->nameLen, cm->heap, + DYNAMIC_TYPE_SUBJECT_CN); + if (signer->name == NULL) { + FreeSigner(signer, cm->heap); + return MEMORY_E; + } + + XMEMCPY(signer->name, current + idx, signer->nameLen); + idx += signer->nameLen; + + /* subjectNameHash */ + XMEMCPY(signer->subjectNameHash, current + idx, SIGNER_DIGEST_SIZE); + idx += SIGNER_DIGEST_SIZE; + + #ifndef NO_SKID + /* subjectKeyIdHash */ + XMEMCPY(signer->subjectKeyIdHash, current + idx,SIGNER_DIGEST_SIZE); + idx += SIGNER_DIGEST_SIZE; + #endif + + signer->next = cm->caTable[row]; + cm->caTable[row] = signer; + + --listSz; + } + + return idx; +} + + +/* Store whole cert row into memory, have lock, return bytes added */ +static WC_INLINE int StoreCertRow(WOLFSSL_CERT_MANAGER* cm, byte* current, int row) +{ + int added = 0; + Signer* list = cm->caTable[row]; + + while (list) { + XMEMCPY(current + added, &list->pubKeySize, sizeof(list->pubKeySize)); + added += (int)sizeof(list->pubKeySize); + + XMEMCPY(current + added, &list->keyOID, sizeof(list->keyOID)); + added += (int)sizeof(list->keyOID); + + XMEMCPY(current + added, list->publicKey, list->pubKeySize); + added += list->pubKeySize; + + XMEMCPY(current + added, &list->nameLen, sizeof(list->nameLen)); + added += (int)sizeof(list->nameLen); + + XMEMCPY(current + added, list->name, list->nameLen); + added += list->nameLen; + + XMEMCPY(current + added, list->subjectNameHash, SIGNER_DIGEST_SIZE); + added += SIGNER_DIGEST_SIZE; + + #ifndef NO_SKID + XMEMCPY(current + added, list->subjectKeyIdHash,SIGNER_DIGEST_SIZE); + added += SIGNER_DIGEST_SIZE; + #endif + + list = list->next; + } + + return added; +} + + +/* Persist cert cache to memory, have lock */ +static WC_INLINE int DoMemSaveCertCache(WOLFSSL_CERT_MANAGER* cm, + void* mem, int sz) +{ + int realSz; + int ret = WOLFSSL_SUCCESS; + int i; + + WOLFSSL_ENTER("DoMemSaveCertCache"); + + realSz = GetCertCacheMemSize(cm); + if (realSz > sz) { + WOLFSSL_MSG("Mem output buffer too small"); + ret = BUFFER_E; + } + else { + byte* current; + CertCacheHeader hdr; + + hdr.version = WOLFSSL_CACHE_CERT_VERSION; + hdr.rows = CA_TABLE_SIZE; + SetCertHeaderColumns(cm, hdr.columns); + hdr.signerSz = (int)sizeof(Signer); + + XMEMCPY(mem, &hdr, sizeof(CertCacheHeader)); + current = (byte*)mem + sizeof(CertCacheHeader); + + for (i = 0; i < CA_TABLE_SIZE; ++i) + current += StoreCertRow(cm, current, i); + } + + return ret; +} + + +#if !defined(NO_FILESYSTEM) + +/* Persist cert cache to file */ +int CM_SaveCertCache(WOLFSSL_CERT_MANAGER* cm, const char* fname) +{ + XFILE file; + int rc = WOLFSSL_SUCCESS; + int memSz; + byte* mem; + + WOLFSSL_ENTER("CM_SaveCertCache"); + + file = XFOPEN(fname, "w+b"); + if (file == XBADFILE) { + WOLFSSL_MSG("Couldn't open cert cache save file"); + return WOLFSSL_BAD_FILE; + } + + if (wc_LockMutex(&cm->caLock) != 0) { + WOLFSSL_MSG("wc_LockMutex on caLock failed"); + XFCLOSE(file); + return BAD_MUTEX_E; + } + + memSz = GetCertCacheMemSize(cm); + mem = (byte*)XMALLOC(memSz, cm->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (mem == NULL) { + WOLFSSL_MSG("Alloc for tmp buffer failed"); + rc = MEMORY_E; + } else { + rc = DoMemSaveCertCache(cm, mem, memSz); + if (rc == WOLFSSL_SUCCESS) { + int ret = (int)XFWRITE(mem, memSz, 1, file); + if (ret != 1) { + WOLFSSL_MSG("Cert cache file write failed"); + rc = FWRITE_ERROR; + } + } + XFREE(mem, cm->heap, DYNAMIC_TYPE_TMP_BUFFER); + } + + wc_UnLockMutex(&cm->caLock); + XFCLOSE(file); + + return rc; +} + + +/* Restore cert cache from file */ +int CM_RestoreCertCache(WOLFSSL_CERT_MANAGER* cm, const char* fname) +{ + XFILE file; + int rc = WOLFSSL_SUCCESS; + int ret; + int memSz; + byte* mem; + + WOLFSSL_ENTER("CM_RestoreCertCache"); + + file = XFOPEN(fname, "rb"); + if (file == XBADFILE) { + WOLFSSL_MSG("Couldn't open cert cache save file"); + return WOLFSSL_BAD_FILE; + } + + if(XFSEEK(file, 0, XSEEK_END) != 0) { + XFCLOSE(file); + return WOLFSSL_BAD_FILE; + } + memSz = (int)XFTELL(file); + XREWIND(file); + + if (memSz <= 0) { + WOLFSSL_MSG("Bad file size"); + XFCLOSE(file); + return WOLFSSL_BAD_FILE; + } + + mem = (byte*)XMALLOC(memSz, cm->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (mem == NULL) { + WOLFSSL_MSG("Alloc for tmp buffer failed"); + XFCLOSE(file); + return MEMORY_E; + } + + ret = (int)XFREAD(mem, memSz, 1, file); + if (ret != 1) { + WOLFSSL_MSG("Cert file read error"); + rc = FREAD_ERROR; + } else { + rc = CM_MemRestoreCertCache(cm, mem, memSz); + if (rc != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Mem restore cert cache failed"); + } + } + + XFREE(mem, cm->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFCLOSE(file); + + return rc; +} + +#endif /* NO_FILESYSTEM */ + + +/* Persist cert cache to memory */ +int CM_MemSaveCertCache(WOLFSSL_CERT_MANAGER* cm, void* mem, int sz, int* used) +{ + int ret = WOLFSSL_SUCCESS; + + WOLFSSL_ENTER("CM_MemSaveCertCache"); + + if (wc_LockMutex(&cm->caLock) != 0) { + WOLFSSL_MSG("wc_LockMutex on caLock failed"); + return BAD_MUTEX_E; + } + + ret = DoMemSaveCertCache(cm, mem, sz); + if (ret == WOLFSSL_SUCCESS) + *used = GetCertCacheMemSize(cm); + + wc_UnLockMutex(&cm->caLock); + + return ret; +} + + +/* Restore cert cache from memory */ +int CM_MemRestoreCertCache(WOLFSSL_CERT_MANAGER* cm, const void* mem, int sz) +{ + int ret = WOLFSSL_SUCCESS; + int i; + CertCacheHeader* hdr = (CertCacheHeader*)mem; + byte* current = (byte*)mem + sizeof(CertCacheHeader); + byte* end = (byte*)mem + sz; /* don't go over */ + + WOLFSSL_ENTER("CM_MemRestoreCertCache"); + + if (current > end) { + WOLFSSL_MSG("Cert Cache Memory buffer too small"); + return BUFFER_E; + } + + if (hdr->version != WOLFSSL_CACHE_CERT_VERSION || + hdr->rows != CA_TABLE_SIZE || + hdr->signerSz != (int)sizeof(Signer)) { + + WOLFSSL_MSG("Cert Cache Memory header mismatch"); + return CACHE_MATCH_ERROR; + } + + if (wc_LockMutex(&cm->caLock) != 0) { + WOLFSSL_MSG("wc_LockMutex on caLock failed"); + return BAD_MUTEX_E; + } + + FreeSignerTable(cm->caTable, CA_TABLE_SIZE, cm->heap); + + for (i = 0; i < CA_TABLE_SIZE; ++i) { + int added = RestoreCertRow(cm, current, i, hdr->columns[i], end); + if (added < 0) { + WOLFSSL_MSG("RestoreCertRow error"); + ret = added; + break; + } + current += added; + } + + wc_UnLockMutex(&cm->caLock); + + return ret; +} + + +/* get how big the the cert cache save buffer needs to be */ +int CM_GetCertCacheMemSize(WOLFSSL_CERT_MANAGER* cm) +{ + int sz; + + WOLFSSL_ENTER("CM_GetCertCacheMemSize"); + + if (wc_LockMutex(&cm->caLock) != 0) { + WOLFSSL_MSG("wc_LockMutex on caLock failed"); + return BAD_MUTEX_E; + } + + sz = GetCertCacheMemSize(cm); + + wc_UnLockMutex(&cm->caLock); + + return sz; +} + +#endif /* PERSIST_CERT_CACHE */ +#endif /* NO_CERTS */ + + +int wolfSSL_CTX_set_cipher_list(WOLFSSL_CTX* ctx, const char* list) +{ + WOLFSSL_ENTER("wolfSSL_CTX_set_cipher_list"); + + if (ctx == NULL) + return WOLFSSL_FAILURE; + + /* alloc/init on demand only */ + if (ctx->suites == NULL) { + ctx->suites = (Suites*)XMALLOC(sizeof(Suites), ctx->heap, + DYNAMIC_TYPE_SUITES); + if (ctx->suites == NULL) { + WOLFSSL_MSG("Memory alloc for Suites failed"); + return WOLFSSL_FAILURE; + } + XMEMSET(ctx->suites, 0, sizeof(Suites)); + } + + return (SetCipherList(ctx, ctx->suites, list)) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE; +} + + +int wolfSSL_set_cipher_list(WOLFSSL* ssl, const char* list) +{ + WOLFSSL_ENTER("wolfSSL_set_cipher_list"); +#ifdef SINGLE_THREADED + if (ssl->ctx->suites == ssl->suites) { + ssl->suites = (Suites*)XMALLOC(sizeof(Suites), ssl->heap, + DYNAMIC_TYPE_SUITES); + if (ssl->suites == NULL) { + WOLFSSL_MSG("Suites Memory error"); + return MEMORY_E; + } + ssl->options.ownSuites = 1; + } +#endif + + return (SetCipherList(ssl->ctx, ssl->suites, list)) ? WOLFSSL_SUCCESS : WOLFSSL_FAILURE; +} + + +int wolfSSL_dtls_get_using_nonblock(WOLFSSL* ssl) +{ + int useNb = 0; + + if (ssl == NULL) + return WOLFSSL_FAILURE; + + WOLFSSL_ENTER("wolfSSL_dtls_get_using_nonblock"); + if (ssl->options.dtls) { +#ifdef WOLFSSL_DTLS + useNb = ssl->options.dtlsUseNonblock; +#endif + } + else { + WOLFSSL_MSG("wolfSSL_dtls_get_using_nonblock() is " + "DEPRECATED for non-DTLS use."); + } + return useNb; +} + + +#ifndef WOLFSSL_LEANPSK + +void wolfSSL_dtls_set_using_nonblock(WOLFSSL* ssl, int nonblock) +{ + (void)nonblock; + + WOLFSSL_ENTER("wolfSSL_dtls_set_using_nonblock"); + + if (ssl == NULL) + return; + + if (ssl->options.dtls) { +#ifdef WOLFSSL_DTLS + ssl->options.dtlsUseNonblock = (nonblock != 0); +#endif + } + else { + WOLFSSL_MSG("wolfSSL_dtls_set_using_nonblock() is " + "DEPRECATED for non-DTLS use."); + } +} + + +#ifdef WOLFSSL_DTLS + +int wolfSSL_dtls_get_current_timeout(WOLFSSL* ssl) +{ + int timeout = 0; + if (ssl) + timeout = ssl->dtls_timeout; + + WOLFSSL_LEAVE("wolfSSL_dtls_get_current_timeout()", timeout); + return timeout; +} + + +/* user may need to alter init dtls recv timeout, WOLFSSL_SUCCESS on ok */ +int wolfSSL_dtls_set_timeout_init(WOLFSSL* ssl, int timeout) +{ + if (ssl == NULL || timeout < 0) + return BAD_FUNC_ARG; + + if (timeout > ssl->dtls_timeout_max) { + WOLFSSL_MSG("Can't set dtls timeout init greater than dtls timeout max"); + return BAD_FUNC_ARG; + } + + ssl->dtls_timeout_init = timeout; + ssl->dtls_timeout = timeout; + + return WOLFSSL_SUCCESS; +} + + +/* user may need to alter max dtls recv timeout, WOLFSSL_SUCCESS on ok */ +int wolfSSL_dtls_set_timeout_max(WOLFSSL* ssl, int timeout) +{ + if (ssl == NULL || timeout < 0) + return BAD_FUNC_ARG; + + if (timeout < ssl->dtls_timeout_init) { + WOLFSSL_MSG("Can't set dtls timeout max less than dtls timeout init"); + return BAD_FUNC_ARG; + } + + ssl->dtls_timeout_max = timeout; + + return WOLFSSL_SUCCESS; +} + + +int wolfSSL_dtls_got_timeout(WOLFSSL* ssl) +{ + int result = WOLFSSL_SUCCESS; + WOLFSSL_ENTER("wolfSSL_dtls_got_timeout()"); + + if (ssl == NULL) + return WOLFSSL_FATAL_ERROR; + + if (!ssl->options.handShakeDone && + (DtlsMsgPoolTimeout(ssl) < 0 || DtlsMsgPoolSend(ssl, 0) < 0)) { + + result = WOLFSSL_FATAL_ERROR; + } + + WOLFSSL_LEAVE("wolfSSL_dtls_got_timeout()", result); + return result; +} + + +/* retransmit all the saves messages, WOLFSSL_SUCCESS on ok */ +int wolfSSL_dtls_retransmit(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_dtls_retransmit()"); + + if (ssl == NULL) + return WOLFSSL_FATAL_ERROR; + + if (!ssl->options.handShakeDone) { + int result = DtlsMsgPoolSend(ssl, 0); + if (result < 0) { + ssl->error = result; + WOLFSSL_ERROR(result); + return WOLFSSL_FATAL_ERROR; + } + } + + return 0; +} + +#endif /* DTLS */ +#endif /* LEANPSK */ + + +#if defined(WOLFSSL_DTLS) && !defined(NO_WOLFSSL_SERVER) + +/* Not an SSL function, return 0 for success, error code otherwise */ +/* Prereq: ssl's RNG needs to be initialized. */ +int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl, + const byte* secret, word32 secretSz) +{ + int ret = 0; + + WOLFSSL_ENTER("wolfSSL_DTLS_SetCookieSecret"); + + if (ssl == NULL) { + WOLFSSL_MSG("need a SSL object"); + return BAD_FUNC_ARG; + } + + if (secret != NULL && secretSz == 0) { + WOLFSSL_MSG("can't have a new secret without a size"); + return BAD_FUNC_ARG; + } + + /* If secretSz is 0, use the default size. */ + if (secretSz == 0) + secretSz = COOKIE_SECRET_SZ; + + if (secretSz != ssl->buffers.dtlsCookieSecret.length) { + byte* newSecret; + + if (ssl->buffers.dtlsCookieSecret.buffer != NULL) { + ForceZero(ssl->buffers.dtlsCookieSecret.buffer, + ssl->buffers.dtlsCookieSecret.length); + XFREE(ssl->buffers.dtlsCookieSecret.buffer, + ssl->heap, DYNAMIC_TYPE_NONE); + } + + newSecret = (byte*)XMALLOC(secretSz, ssl->heap,DYNAMIC_TYPE_COOKIE_PWD); + if (newSecret == NULL) { + ssl->buffers.dtlsCookieSecret.buffer = NULL; + ssl->buffers.dtlsCookieSecret.length = 0; + WOLFSSL_MSG("couldn't allocate new cookie secret"); + return MEMORY_ERROR; + } + ssl->buffers.dtlsCookieSecret.buffer = newSecret; + ssl->buffers.dtlsCookieSecret.length = secretSz; + } + + /* If the supplied secret is NULL, randomly generate a new secret. */ + if (secret == NULL) { + ret = wc_RNG_GenerateBlock(ssl->rng, + ssl->buffers.dtlsCookieSecret.buffer, secretSz); + } + else + XMEMCPY(ssl->buffers.dtlsCookieSecret.buffer, secret, secretSz); + + WOLFSSL_LEAVE("wolfSSL_DTLS_SetCookieSecret", 0); + return ret; +} + +#endif /* WOLFSSL_DTLS && !NO_WOLFSSL_SERVER */ + + +/* EITHER SIDE METHODS */ +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) + WOLFSSL_METHOD* wolfSSLv23_method(void) + { + return wolfSSLv23_method_ex(NULL); + } + WOLFSSL_METHOD* wolfSSLv23_method_ex(void* heap) + { + WOLFSSL_METHOD* m = NULL; + WOLFSSL_ENTER("SSLv23_method"); + #if !defined(NO_WOLFSSL_CLIENT) + m = wolfSSLv23_client_method_ex(heap); + #elif !defined(NO_WOLFSSL_SERVER) + m = wolfSSLv23_server_method_ex(heap); + #endif + if (m != NULL) { + m->side = WOLFSSL_NEITHER_END; + } + + return m; + } +#endif /* OPENSSL_EXTRA || WOLFSSL_EITHER_SIDE */ + +/* client only parts */ +#ifndef NO_WOLFSSL_CLIENT + + #ifdef OPENSSL_EXTRA + WOLFSSL_METHOD* wolfSSLv2_client_method(void) + { + WOLFSSL_STUB("wolfSSLv2_client_method"); + return NULL; + } + #endif + + #ifdef WOLFSSL_ALLOW_SSLV3 + WOLFSSL_METHOD* wolfSSLv3_client_method(void) + { + return wolfSSLv3_client_method_ex(NULL); + } + WOLFSSL_METHOD* wolfSSLv3_client_method_ex(void* heap) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + heap, DYNAMIC_TYPE_METHOD); + (void)heap; + WOLFSSL_ENTER("SSLv3_client_method_ex"); + if (method) + InitSSL_Method(method, MakeSSLv3()); + return method; + } + #endif /* WOLFSSL_ALLOW_SSLV3 */ + + + WOLFSSL_METHOD* wolfSSLv23_client_method(void) + { + return wolfSSLv23_client_method_ex(NULL); + } + WOLFSSL_METHOD* wolfSSLv23_client_method_ex(void* heap) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + heap, DYNAMIC_TYPE_METHOD); + (void)heap; + WOLFSSL_ENTER("SSLv23_client_method_ex"); + if (method) { + #if !defined(NO_SHA256) || defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512) + #if defined(WOLFSSL_TLS13) + InitSSL_Method(method, MakeTLSv1_3()); + #elif !defined(WOLFSSL_NO_TLS12) + InitSSL_Method(method, MakeTLSv1_2()); + #elif !defined(NO_OLD_TLS) + InitSSL_Method(method, MakeTLSv1_1()); + #endif + #else + #ifndef NO_OLD_TLS + InitSSL_Method(method, MakeTLSv1_1()); + #endif + #endif + #if !defined(NO_OLD_TLS) || defined(WOLFSSL_TLS13) + method->downgrade = 1; + #endif + } + return method; + } + + + #if defined(WOLFSSL_DTLS) || !defined(WOLFSSL_NO_TLS12) || !defined(NO_OLD_TLS) || \ + defined(WOLFSSL_ALLOW_SSLV3) + /* If SCTP is not enabled returns the state of the dtls option. + * If SCTP is enabled returns dtls && !sctp. */ + static WC_INLINE int IsDtlsNotSctpMode(WOLFSSL* ssl) + { + int result = ssl->options.dtls; + + if (result) { + #ifdef WOLFSSL_SCTP + result = !ssl->options.dtlsSctp; + #endif + } + + return result; + } + #endif /* WOLFSSL_DTLS || !WOLFSSL_NO_TLS12 || !NO_OLD_TLS */ + + + /* please see note at top of README if you get an error from connect */ + int wolfSSL_connect(WOLFSSL* ssl) + { + #if !(defined(WOLFSSL_NO_TLS12) && defined(NO_OLD_TLS) && defined(WOLFSSL_TLS13)) + int neededState; + #endif + + WOLFSSL_ENTER("SSL_connect()"); + + #ifdef HAVE_ERRNO_H + errno = 0; + #endif + + if (ssl == NULL) + return BAD_FUNC_ARG; + + #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) + if (ssl->options.side == WOLFSSL_NEITHER_END) { + ssl->error = InitSSL_Side(ssl, WOLFSSL_CLIENT_END); + if (ssl->error != WOLFSSL_SUCCESS) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + ssl->error = 0; /* expected to be zero here */ + } + + #ifdef OPENSSL_EXTRA + if (ssl->CBIS != NULL) { + ssl->CBIS(ssl, SSL_ST_CONNECT, SSL_SUCCESS); + ssl->cbmode = SSL_CB_WRITE; + } + #endif + #endif /* OPENSSL_EXTRA || WOLFSSL_EITHER_SIDE */ + + #if defined(WOLFSSL_NO_TLS12) && defined(NO_OLD_TLS) && defined(WOLFSSL_TLS13) + return wolfSSL_connect_TLSv13(ssl); + #else + #ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) + return wolfSSL_connect_TLSv13(ssl); + #endif + + if (ssl->options.side != WOLFSSL_CLIENT_END) { + WOLFSSL_ERROR(ssl->error = SIDE_ERROR); + return WOLFSSL_FATAL_ERROR; + } + + #ifdef WOLFSSL_DTLS + if (ssl->version.major == DTLS_MAJOR) { + ssl->options.dtls = 1; + ssl->options.tls = 1; + ssl->options.tls1_1 = 1; + } + #endif + + if (ssl->buffers.outputBuffer.length > 0) { + if ( (ssl->error = SendBuffered(ssl)) == 0) { + /* fragOffset is non-zero when sending fragments. On the last + * fragment, fragOffset is zero again, and the state can be + * advanced. */ + if (ssl->fragOffset == 0) { + ssl->options.connectState++; + WOLFSSL_MSG("connect state: " + "Advanced from last buffered fragment send"); + } + else { + WOLFSSL_MSG("connect state: " + "Not advanced, more fragments to send"); + } + } + else { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } + + switch (ssl->options.connectState) { + + case CONNECT_BEGIN : + /* always send client hello first */ + if ( (ssl->error = SendClientHello(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + ssl->options.connectState = CLIENT_HELLO_SENT; + WOLFSSL_MSG("connect state: CLIENT_HELLO_SENT"); + FALL_THROUGH; + + case CLIENT_HELLO_SENT : + neededState = ssl->options.resuming ? SERVER_FINISHED_COMPLETE : + SERVER_HELLODONE_COMPLETE; + #ifdef WOLFSSL_DTLS + /* In DTLS, when resuming, we can go straight to FINISHED, + * or do a cookie exchange and then skip to FINISHED, assume + * we need the cookie exchange first. */ + if (IsDtlsNotSctpMode(ssl)) + neededState = SERVER_HELLOVERIFYREQUEST_COMPLETE; + #endif + /* get response */ + while (ssl->options.serverState < neededState) { + #ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) + return wolfSSL_connect_TLSv13(ssl); + #endif + if ( (ssl->error = ProcessReply(ssl)) < 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + /* if resumption failed, reset needed state */ + else if (neededState == SERVER_FINISHED_COMPLETE) + if (!ssl->options.resuming) { + if (!IsDtlsNotSctpMode(ssl)) + neededState = SERVER_HELLODONE_COMPLETE; + else + neededState = SERVER_HELLOVERIFYREQUEST_COMPLETE; + } + } + + ssl->options.connectState = HELLO_AGAIN; + WOLFSSL_MSG("connect state: HELLO_AGAIN"); + FALL_THROUGH; + + case HELLO_AGAIN : + if (ssl->options.certOnly) + return WOLFSSL_SUCCESS; + + #ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) + return wolfSSL_connect_TLSv13(ssl); + #endif + + #ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl)) { + /* re-init hashes, exclude first hello and verify request */ + if ((ssl->error = InitHandshakeHashes(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + if ( (ssl->error = SendClientHello(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } + #endif + + ssl->options.connectState = HELLO_AGAIN_REPLY; + WOLFSSL_MSG("connect state: HELLO_AGAIN_REPLY"); + FALL_THROUGH; + + case HELLO_AGAIN_REPLY : + #ifdef WOLFSSL_DTLS + if (IsDtlsNotSctpMode(ssl)) { + neededState = ssl->options.resuming ? + SERVER_FINISHED_COMPLETE : SERVER_HELLODONE_COMPLETE; + + /* get response */ + while (ssl->options.serverState < neededState) { + if ( (ssl->error = ProcessReply(ssl)) < 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + /* if resumption failed, reset needed state */ + if (neededState == SERVER_FINISHED_COMPLETE) { + if (!ssl->options.resuming) + neededState = SERVER_HELLODONE_COMPLETE; + } + } + } + #endif + + ssl->options.connectState = FIRST_REPLY_DONE; + WOLFSSL_MSG("connect state: FIRST_REPLY_DONE"); + FALL_THROUGH; + + case FIRST_REPLY_DONE : + #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CLIENT_AUTH) + #ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) + return wolfSSL_connect_TLSv13(ssl); + #endif + if (ssl->options.sendVerify) { + if ( (ssl->error = SendCertificate(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + WOLFSSL_MSG("sent: certificate"); + } + + #endif + ssl->options.connectState = FIRST_REPLY_FIRST; + WOLFSSL_MSG("connect state: FIRST_REPLY_FIRST"); + FALL_THROUGH; + + case FIRST_REPLY_FIRST : + #ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) + return wolfSSL_connect_TLSv13(ssl); + #endif + if (!ssl->options.resuming) { + if ( (ssl->error = SendClientKeyExchange(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + WOLFSSL_MSG("sent: client key exchange"); + } + + ssl->options.connectState = FIRST_REPLY_SECOND; + WOLFSSL_MSG("connect state: FIRST_REPLY_SECOND"); + FALL_THROUGH; + + case FIRST_REPLY_SECOND : + #if !defined(NO_CERTS) && !defined(WOLFSSL_NO_CLIENT_AUTH) + if (ssl->options.sendVerify) { + if ( (ssl->error = SendCertificateVerify(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + WOLFSSL_MSG("sent: certificate verify"); + } + #endif /* !NO_CERTS && !WOLFSSL_NO_CLIENT_AUTH */ + ssl->options.connectState = FIRST_REPLY_THIRD; + WOLFSSL_MSG("connect state: FIRST_REPLY_THIRD"); + FALL_THROUGH; + + case FIRST_REPLY_THIRD : + if ( (ssl->error = SendChangeCipher(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + WOLFSSL_MSG("sent: change cipher spec"); + ssl->options.connectState = FIRST_REPLY_FOURTH; + WOLFSSL_MSG("connect state: FIRST_REPLY_FOURTH"); + FALL_THROUGH; + + case FIRST_REPLY_FOURTH : + if ( (ssl->error = SendFinished(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + WOLFSSL_MSG("sent: finished"); + ssl->options.connectState = FINISHED_DONE; + WOLFSSL_MSG("connect state: FINISHED_DONE"); + FALL_THROUGH; + + case FINISHED_DONE : + /* get response */ + while (ssl->options.serverState < SERVER_FINISHED_COMPLETE) + if ( (ssl->error = ProcessReply(ssl)) < 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + + ssl->options.connectState = SECOND_REPLY_DONE; + WOLFSSL_MSG("connect state: SECOND_REPLY_DONE"); + FALL_THROUGH; + + case SECOND_REPLY_DONE: +#ifndef NO_HANDSHAKE_DONE_CB + if (ssl->hsDoneCb) { + int cbret = ssl->hsDoneCb(ssl, ssl->hsDoneCtx); + if (cbret < 0) { + ssl->error = cbret; + WOLFSSL_MSG("HandShake Done Cb don't continue error"); + return WOLFSSL_FATAL_ERROR; + } + } +#endif /* NO_HANDSHAKE_DONE_CB */ + + if (!ssl->options.dtls) { + if (!ssl->options.keepResources) { + FreeHandshakeResources(ssl); + } + } +#ifdef WOLFSSL_DTLS + else { + ssl->options.dtlsHsRetain = 1; + } +#endif /* WOLFSSL_DTLS */ + + WOLFSSL_LEAVE("SSL_connect()", WOLFSSL_SUCCESS); + return WOLFSSL_SUCCESS; + + default: + WOLFSSL_MSG("Unknown connect state ERROR"); + return WOLFSSL_FATAL_ERROR; /* unknown connect state */ + } + #endif /* !WOLFSSL_NO_TLS12 */ + } + +#endif /* NO_WOLFSSL_CLIENT */ + + +/* server only parts */ +#ifndef NO_WOLFSSL_SERVER + + #ifdef OPENSSL_EXTRA + WOLFSSL_METHOD* wolfSSLv2_server_method(void) + { + WOLFSSL_STUB("wolfSSLv2_server_method"); + return 0; + } + #endif + + #ifdef WOLFSSL_ALLOW_SSLV3 + WOLFSSL_METHOD* wolfSSLv3_server_method(void) + { + return wolfSSLv3_server_method_ex(NULL); + } + WOLFSSL_METHOD* wolfSSLv3_server_method_ex(void* heap) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + heap, DYNAMIC_TYPE_METHOD); + (void)heap; + WOLFSSL_ENTER("SSLv3_server_method_ex"); + if (method) { + InitSSL_Method(method, MakeSSLv3()); + method->side = WOLFSSL_SERVER_END; + } + return method; + } + #endif /* WOLFSSL_ALLOW_SSLV3 */ + + WOLFSSL_METHOD* wolfSSLv23_server_method(void) + { + return wolfSSLv23_server_method_ex(NULL); + } + + WOLFSSL_METHOD* wolfSSLv23_server_method_ex(void* heap) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + heap, DYNAMIC_TYPE_METHOD); + (void)heap; + WOLFSSL_ENTER("SSLv23_server_method_ex"); + if (method) { + #if !defined(NO_SHA256) || defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512) + #ifdef WOLFSSL_TLS13 + InitSSL_Method(method, MakeTLSv1_3()); + #elif !defined(WOLFSSL_NO_TLS12) + InitSSL_Method(method, MakeTLSv1_2()); + #elif !defined(NO_OLD_TLS) + InitSSL_Method(method, MakeTLSv1_1()); + #endif + #else + #ifndef NO_OLD_TLS + InitSSL_Method(method, MakeTLSv1_1()); + #else + #error Must have SHA256, SHA384 or SHA512 enabled for TLS 1.2 + #endif + #endif + #if !defined(NO_OLD_TLS) || defined(WOLFSSL_TLS13) + method->downgrade = 1; + #endif + method->side = WOLFSSL_SERVER_END; + } + return method; + } + + + int wolfSSL_accept(WOLFSSL* ssl) + { +#if !(defined(WOLFSSL_NO_TLS12) && defined(NO_OLD_TLS) && defined(WOLFSSL_TLS13)) + word16 havePSK = 0; + word16 haveAnon = 0; + word16 haveMcast = 0; +#endif + + if (ssl == NULL) + return WOLFSSL_FATAL_ERROR; + + #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) + if (ssl->options.side == WOLFSSL_NEITHER_END) { + ssl->error = InitSSL_Side(ssl, WOLFSSL_SERVER_END); + if (ssl->error != WOLFSSL_SUCCESS) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + ssl->error = 0; /* expected to be zero here */ + } + #endif /* OPENSSL_EXTRA || WOLFSSL_EITHER_SIDE */ + +#if defined(WOLFSSL_NO_TLS12) && defined(NO_OLD_TLS) && defined(WOLFSSL_TLS13) + return wolfSSL_accept_TLSv13(ssl); +#else + #ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) + return wolfSSL_accept_TLSv13(ssl); + #endif + WOLFSSL_ENTER("SSL_accept()"); + + #ifdef HAVE_ERRNO_H + errno = 0; + #endif + + #ifndef NO_PSK + havePSK = ssl->options.havePSK; + #endif + (void)havePSK; + + #ifdef HAVE_ANON + haveAnon = ssl->options.haveAnon; + #endif + (void)haveAnon; + + #ifdef WOLFSSL_MULTICAST + haveMcast = ssl->options.haveMcast; + #endif + (void)haveMcast; + + if (ssl->options.side != WOLFSSL_SERVER_END) { + WOLFSSL_ERROR(ssl->error = SIDE_ERROR); + return WOLFSSL_FATAL_ERROR; + } + + #ifndef NO_CERTS + /* in case used set_accept_state after init */ + /* allow no private key if using PK callbacks and CB is set */ + if (!havePSK && !haveAnon && !haveMcast) { + if (!ssl->buffers.certificate || + !ssl->buffers.certificate->buffer) { + + WOLFSSL_MSG("accept error: server cert required"); + WOLFSSL_ERROR(ssl->error = NO_PRIVATE_KEY); + return WOLFSSL_FATAL_ERROR; + } + + #ifdef HAVE_PK_CALLBACKS + if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) { + WOLFSSL_MSG("Using PK for server private key"); + } + else + #endif + if (!ssl->buffers.key || !ssl->buffers.key->buffer) { + WOLFSSL_MSG("accept error: server key required"); + WOLFSSL_ERROR(ssl->error = NO_PRIVATE_KEY); + return WOLFSSL_FATAL_ERROR; + } + } + #endif + + #ifdef WOLFSSL_DTLS + if (ssl->version.major == DTLS_MAJOR) { + ssl->options.dtls = 1; + ssl->options.tls = 1; + ssl->options.tls1_1 = 1; + } + #endif + + if (ssl->buffers.outputBuffer.length > 0) { + if ( (ssl->error = SendBuffered(ssl)) == 0) { + /* fragOffset is non-zero when sending fragments. On the last + * fragment, fragOffset is zero again, and the state can be + * advanced. */ + if (ssl->fragOffset == 0) { + ssl->options.acceptState++; + WOLFSSL_MSG("accept state: " + "Advanced from last buffered fragment send"); + } + else { + WOLFSSL_MSG("accept state: " + "Not advanced, more fragments to send"); + } + } + else { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } + + switch (ssl->options.acceptState) { + + case ACCEPT_BEGIN : + /* get response */ + while (ssl->options.clientState < CLIENT_HELLO_COMPLETE) + if ( (ssl->error = ProcessReply(ssl)) < 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } +#ifdef WOLFSSL_TLS13 + ssl->options.acceptState = ACCEPT_CLIENT_HELLO_DONE; + WOLFSSL_MSG("accept state ACCEPT_CLIENT_HELLO_DONE"); + FALL_THROUGH; + + case ACCEPT_CLIENT_HELLO_DONE : + if (ssl->options.tls1_3) { + return wolfSSL_accept_TLSv13(ssl); + } +#endif + ssl->options.acceptState = ACCEPT_FIRST_REPLY_DONE; + WOLFSSL_MSG("accept state ACCEPT_FIRST_REPLY_DONE"); + FALL_THROUGH; + + case ACCEPT_FIRST_REPLY_DONE : + if ( (ssl->error = SendServerHello(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + ssl->options.acceptState = SERVER_HELLO_SENT; + WOLFSSL_MSG("accept state SERVER_HELLO_SENT"); + FALL_THROUGH; + + case SERVER_HELLO_SENT : + #ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) { + return wolfSSL_accept_TLSv13(ssl); + } + #endif + #ifndef NO_CERTS + if (!ssl->options.resuming) + if ( (ssl->error = SendCertificate(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + #endif + ssl->options.acceptState = CERT_SENT; + WOLFSSL_MSG("accept state CERT_SENT"); + FALL_THROUGH; + + case CERT_SENT : + #ifndef NO_CERTS + if (!ssl->options.resuming) + if ( (ssl->error = SendCertificateStatus(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + #endif + ssl->options.acceptState = CERT_STATUS_SENT; + WOLFSSL_MSG("accept state CERT_STATUS_SENT"); + FALL_THROUGH; + + case CERT_STATUS_SENT : + #ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) { + return wolfSSL_accept_TLSv13(ssl); + } + #endif + if (!ssl->options.resuming) + if ( (ssl->error = SendServerKeyExchange(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + ssl->options.acceptState = KEY_EXCHANGE_SENT; + WOLFSSL_MSG("accept state KEY_EXCHANGE_SENT"); + FALL_THROUGH; + + case KEY_EXCHANGE_SENT : + #ifndef NO_CERTS + if (!ssl->options.resuming) { + if (ssl->options.verifyPeer) { + if ( (ssl->error = SendCertificateRequest(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } + } + #endif + ssl->options.acceptState = CERT_REQ_SENT; + WOLFSSL_MSG("accept state CERT_REQ_SENT"); + FALL_THROUGH; + + case CERT_REQ_SENT : + if (!ssl->options.resuming) + if ( (ssl->error = SendServerHelloDone(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + ssl->options.acceptState = SERVER_HELLO_DONE; + WOLFSSL_MSG("accept state SERVER_HELLO_DONE"); + FALL_THROUGH; + + case SERVER_HELLO_DONE : + if (!ssl->options.resuming) { + while (ssl->options.clientState < CLIENT_FINISHED_COMPLETE) + if ( (ssl->error = ProcessReply(ssl)) < 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } + ssl->options.acceptState = ACCEPT_SECOND_REPLY_DONE; + WOLFSSL_MSG("accept state ACCEPT_SECOND_REPLY_DONE"); + FALL_THROUGH; + + case ACCEPT_SECOND_REPLY_DONE : +#ifdef HAVE_SESSION_TICKET + if (ssl->options.createTicket) { + if ( (ssl->error = SendTicket(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } +#endif /* HAVE_SESSION_TICKET */ + ssl->options.acceptState = TICKET_SENT; + WOLFSSL_MSG("accept state TICKET_SENT"); + FALL_THROUGH; + + case TICKET_SENT: + if ( (ssl->error = SendChangeCipher(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + ssl->options.acceptState = CHANGE_CIPHER_SENT; + WOLFSSL_MSG("accept state CHANGE_CIPHER_SENT"); + FALL_THROUGH; + + case CHANGE_CIPHER_SENT : + if ( (ssl->error = SendFinished(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + + ssl->options.acceptState = ACCEPT_FINISHED_DONE; + WOLFSSL_MSG("accept state ACCEPT_FINISHED_DONE"); + FALL_THROUGH; + + case ACCEPT_FINISHED_DONE : + if (ssl->options.resuming) + while (ssl->options.clientState < CLIENT_FINISHED_COMPLETE) + if ( (ssl->error = ProcessReply(ssl)) < 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + + ssl->options.acceptState = ACCEPT_THIRD_REPLY_DONE; + WOLFSSL_MSG("accept state ACCEPT_THIRD_REPLY_DONE"); + FALL_THROUGH; + + case ACCEPT_THIRD_REPLY_DONE : +#ifndef NO_HANDSHAKE_DONE_CB + if (ssl->hsDoneCb) { + int cbret = ssl->hsDoneCb(ssl, ssl->hsDoneCtx); + if (cbret < 0) { + ssl->error = cbret; + WOLFSSL_MSG("HandShake Done Cb don't continue error"); + return WOLFSSL_FATAL_ERROR; + } + } +#endif /* NO_HANDSHAKE_DONE_CB */ + + if (!ssl->options.dtls) { + if (!ssl->options.keepResources) { + FreeHandshakeResources(ssl); + } + } +#ifdef WOLFSSL_DTLS + else { + ssl->options.dtlsHsRetain = 1; + } +#endif /* WOLFSSL_DTLS */ + +#ifdef WOLFSSL_SESSION_EXPORT + if (ssl->dtls_export) { + if ((ssl->error = wolfSSL_send_session(ssl)) != 0) { + WOLFSSL_MSG("Export DTLS session error"); + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } +#endif + + WOLFSSL_LEAVE("SSL_accept()", WOLFSSL_SUCCESS); + return WOLFSSL_SUCCESS; + + default : + WOLFSSL_MSG("Unknown accept state ERROR"); + return WOLFSSL_FATAL_ERROR; + } +#endif /* !WOLFSSL_NO_TLS12 */ + } + +#endif /* NO_WOLFSSL_SERVER */ + + +#ifndef NO_HANDSHAKE_DONE_CB + +int wolfSSL_SetHsDoneCb(WOLFSSL* ssl, HandShakeDoneCb cb, void* user_ctx) +{ + WOLFSSL_ENTER("wolfSSL_SetHsDoneCb"); + + if (ssl == NULL) + return BAD_FUNC_ARG; + + ssl->hsDoneCb = cb; + ssl->hsDoneCtx = user_ctx; + + + return WOLFSSL_SUCCESS; +} + +#endif /* NO_HANDSHAKE_DONE_CB */ + +int wolfSSL_Cleanup(void) +{ + int ret = WOLFSSL_SUCCESS; + int release = 0; + + WOLFSSL_ENTER("wolfSSL_Cleanup"); + + if (initRefCount == 0) + return ret; /* possibly no init yet, but not failure either way */ + + if (wc_LockMutex(&count_mutex) != 0) { + WOLFSSL_MSG("Bad Lock Mutex count"); + return BAD_MUTEX_E; + } + + release = initRefCount-- == 1; + if (initRefCount < 0) + initRefCount = 0; + + wc_UnLockMutex(&count_mutex); + + if (!release) + return ret; + +#ifndef NO_SESSION_CACHE + if (wc_FreeMutex(&session_mutex) != 0) + ret = BAD_MUTEX_E; +#endif + if (wc_FreeMutex(&count_mutex) != 0) + ret = BAD_MUTEX_E; + +#ifdef OPENSSL_EXTRA + wolfSSL_RAND_Cleanup(); +#endif + + if (wolfCrypt_Cleanup() != 0) { + WOLFSSL_MSG("Error with wolfCrypt_Cleanup call"); + ret = WC_CLEANUP_E; + } + + return ret; +} + + +#ifndef NO_SESSION_CACHE + + +/* some session IDs aren't random after all, let's make them random */ +static WC_INLINE word32 HashSession(const byte* sessionID, word32 len, int* error) +{ + byte digest[WC_MAX_DIGEST_SIZE]; + +#ifndef NO_MD5 + *error = wc_Md5Hash(sessionID, len, digest); +#elif !defined(NO_SHA) + *error = wc_ShaHash(sessionID, len, digest); +#elif !defined(NO_SHA256) + *error = wc_Sha256Hash(sessionID, len, digest); +#else + #error "We need a digest to hash the session IDs" +#endif + + return *error == 0 ? MakeWordFromHash(digest) : 0; /* 0 on failure */ +} + + +void wolfSSL_flush_sessions(WOLFSSL_CTX* ctx, long tm) +{ + /* static table now, no flushing needed */ + (void)ctx; + (void)tm; +} + + +/* set ssl session timeout in seconds */ +int wolfSSL_set_timeout(WOLFSSL* ssl, unsigned int to) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + + if (to == 0) + to = WOLFSSL_SESSION_TIMEOUT; + ssl->timeout = to; + + return WOLFSSL_SUCCESS; +} + + +/* set ctx session timeout in seconds */ +int wolfSSL_CTX_set_timeout(WOLFSSL_CTX* ctx, unsigned int to) +{ + if (ctx == NULL) + return BAD_FUNC_ARG; + + if (to == 0) + to = WOLFSSL_SESSION_TIMEOUT; + ctx->timeout = to; + + return WOLFSSL_SUCCESS; +} + + +#ifndef NO_CLIENT_CACHE + +/* Get Session from Client cache based on id/len, return NULL on failure */ +WOLFSSL_SESSION* GetSessionClient(WOLFSSL* ssl, const byte* id, int len) +{ + WOLFSSL_SESSION* ret = NULL; + word32 row; + int idx; + int count; + int error = 0; + + WOLFSSL_ENTER("GetSessionClient"); + + if (ssl->ctx->sessionCacheOff) + return NULL; + + if (ssl->options.side == WOLFSSL_SERVER_END) + return NULL; + + len = min(SERVER_ID_LEN, (word32)len); + +#ifdef HAVE_EXT_CACHE + if (ssl->ctx->get_sess_cb != NULL) { + int copy = 0; + ret = ssl->ctx->get_sess_cb(ssl, (byte*)id, len, ©); + if (ret != NULL) + return ret; + } + + if (ssl->ctx->internalCacheOff) + return NULL; +#endif + + row = HashSession(id, len, &error) % SESSION_ROWS; + if (error != 0) { + WOLFSSL_MSG("Hash session failed"); + return NULL; + } + + if (wc_LockMutex(&session_mutex) != 0) { + WOLFSSL_MSG("Lock session mutex failed"); + return NULL; + } + + /* start from most recently used */ + count = min((word32)ClientCache[row].totalCount, SESSIONS_PER_ROW); + idx = ClientCache[row].nextIdx - 1; + if (idx < 0) + idx = SESSIONS_PER_ROW - 1; /* if back to front, the previous was end */ + + for (; count > 0; --count, idx = idx ? idx - 1 : SESSIONS_PER_ROW - 1) { + WOLFSSL_SESSION* current; + ClientSession clSess; + + if (idx >= SESSIONS_PER_ROW || idx < 0) { /* sanity check */ + WOLFSSL_MSG("Bad idx"); + break; + } + + clSess = ClientCache[row].Clients[idx]; + + current = &SessionCache[clSess.serverRow].Sessions[clSess.serverIdx]; + if (XMEMCMP(current->serverID, id, len) == 0) { + WOLFSSL_MSG("Found a serverid match for client"); + if (LowResTimer() < (current->bornOn + current->timeout)) { + WOLFSSL_MSG("Session valid"); + ret = current; + break; + } else { + WOLFSSL_MSG("Session timed out"); /* could have more for id */ + } + } else { + WOLFSSL_MSG("ServerID not a match from client table"); + } + } + + wc_UnLockMutex(&session_mutex); + + return ret; +} + +#endif /* NO_CLIENT_CACHE */ + +/* Restore the master secret and session information for certificates. + * + * ssl The SSL/TLS object. + * session The cached session to restore. + * masterSecret The master secret from the cached session. + * restoreSessionCerts Restoring session certificates is required. + */ +static WC_INLINE void RestoreSession(WOLFSSL* ssl, WOLFSSL_SESSION* session, + byte* masterSecret, byte restoreSessionCerts) +{ + (void)ssl; + (void)restoreSessionCerts; + + if (masterSecret) + XMEMCPY(masterSecret, session->masterSecret, SECRET_LEN); +#ifdef SESSION_CERTS + /* If set, we should copy the session certs into the ssl object + * from the session we are returning so we can resume */ + if (restoreSessionCerts) { + ssl->session.chain = session->chain; + ssl->session.version = session->version; + #ifdef NO_RESUME_SUITE_CHECK + ssl->session.cipherSuite0 = session->cipherSuite0; + ssl->session.cipherSuite = session->cipherSuite; + #endif + } +#endif /* SESSION_CERTS */ +#ifndef NO_RESUME_SUITE_CHECK + ssl->session.cipherSuite0 = session->cipherSuite0; + ssl->session.cipherSuite = session->cipherSuite; +#endif +} + +WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret, + byte restoreSessionCerts) +{ + WOLFSSL_SESSION* ret = 0; + const byte* id = NULL; + word32 row; + int idx; + int count; + int error = 0; + + (void) restoreSessionCerts; + + if (ssl->options.sessionCacheOff) + return NULL; + + if (ssl->options.haveSessionId == 0) + return NULL; + +#ifdef HAVE_SESSION_TICKET + if (ssl->options.side == WOLFSSL_SERVER_END && ssl->options.useTicket == 1) + return NULL; +#endif + + if (!ssl->options.tls1_3 && ssl->arrays != NULL) + id = ssl->arrays->sessionID; + else + id = ssl->session.sessionID; + +#ifdef HAVE_EXT_CACHE + if (ssl->ctx->get_sess_cb != NULL) { + int copy = 0; + /* Attempt to retrieve the session from the external cache. */ + ret = ssl->ctx->get_sess_cb(ssl, (byte*)id, ID_LEN, ©); + if (ret != NULL) { + RestoreSession(ssl, ret, masterSecret, restoreSessionCerts); + return ret; + } + } + + if (ssl->ctx->internalCacheOff) + return NULL; +#endif + + row = HashSession(id, ID_LEN, &error) % SESSION_ROWS; + if (error != 0) { + WOLFSSL_MSG("Hash session failed"); + return NULL; + } + + if (wc_LockMutex(&session_mutex) != 0) + return 0; + + /* start from most recently used */ + count = min((word32)SessionCache[row].totalCount, SESSIONS_PER_ROW); + idx = SessionCache[row].nextIdx - 1; + if (idx < 0) + idx = SESSIONS_PER_ROW - 1; /* if back to front, the previous was end */ + + for (; count > 0; --count, idx = idx ? idx - 1 : SESSIONS_PER_ROW - 1) { + WOLFSSL_SESSION* current; + + if (idx >= SESSIONS_PER_ROW || idx < 0) { /* sanity check */ + WOLFSSL_MSG("Bad idx"); + break; + } + + current = &SessionCache[row].Sessions[idx]; + if (XMEMCMP(current->sessionID, id, ID_LEN) == 0) { + WOLFSSL_MSG("Found a session match"); + if (LowResTimer() < (current->bornOn + current->timeout)) { + WOLFSSL_MSG("Session valid"); + ret = current; + RestoreSession(ssl, ret, masterSecret, restoreSessionCerts); + } else { + WOLFSSL_MSG("Session timed out"); + } + break; /* no more sessionIDs whether valid or not that match */ + } else { + WOLFSSL_MSG("SessionID not a match at this idx"); + } + } + + wc_UnLockMutex(&session_mutex); + + return ret; +} + + +static int GetDeepCopySession(WOLFSSL* ssl, WOLFSSL_SESSION* copyFrom) +{ + WOLFSSL_SESSION* copyInto = &ssl->session; + void* tmpBuff = NULL; + int ticketLen = 0; + int doDynamicCopy = 0; + int ret = WOLFSSL_SUCCESS; + + (void)ticketLen; + (void)doDynamicCopy; + (void)tmpBuff; + + if (!ssl || !copyFrom) + return BAD_FUNC_ARG; + +#ifdef HAVE_SESSION_TICKET + /* Free old dynamic ticket if we had one to avoid leak */ + if (copyInto->isDynamic) { + XFREE(copyInto->ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); + copyInto->ticket = copyInto->staticTicket; + copyInto->isDynamic = 0; + } +#endif + + if (wc_LockMutex(&session_mutex) != 0) + return BAD_MUTEX_E; + +#ifdef HAVE_SESSION_TICKET + /* Size of ticket to alloc if needed; Use later for alloc outside lock */ + doDynamicCopy = copyFrom->isDynamic; + ticketLen = copyFrom->ticketLen; +#endif + + *copyInto = *copyFrom; + + /* Default ticket to non dynamic. This will avoid crash if we fail below */ +#ifdef HAVE_SESSION_TICKET + copyInto->ticket = copyInto->staticTicket; + copyInto->isDynamic = 0; +#endif + +#ifndef NO_RESUME_SUITE_CHECK + copyInto->cipherSuite0 = copyFrom->cipherSuite0; + copyInto->cipherSuite = copyFrom->cipherSuite; +#endif + + if (wc_UnLockMutex(&session_mutex) != 0) { + return BAD_MUTEX_E; + } + +#ifdef HAVE_SESSION_TICKET +#ifdef WOLFSSL_TLS13 + if (wc_LockMutex(&session_mutex) != 0) { + XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); + return BAD_MUTEX_E; + } + +#ifdef NO_RESUME_SUITE_CHECK + copyInto->cipherSuite0 = copyFrom->cipherSuite0; + copyInto->cipherSuite = copyFrom->cipherSuite; +#endif + copyInto->namedGroup = copyFrom->namedGroup; + copyInto->ticketSeen = copyFrom->ticketSeen; + copyInto->ticketAdd = copyFrom->ticketAdd; +#ifndef WOLFSSL_TLS13_DRAFT_18 + XMEMCPY(©Into->ticketNonce, ©From->ticketNonce, + sizeof(TicketNonce)); +#endif +#ifdef WOLFSSL_EARLY_DATA + copyInto->maxEarlyDataSz = copyFrom->maxEarlyDataSz; +#endif + XMEMCPY(copyInto->masterSecret, copyFrom->masterSecret, SECRET_LEN); + + if (wc_UnLockMutex(&session_mutex) != 0) { + if (ret == WOLFSSL_SUCCESS) + ret = BAD_MUTEX_E; + } +#endif + /* If doing dynamic copy, need to alloc outside lock, then inside a lock + * confirm the size still matches and memcpy */ + if (doDynamicCopy) { + tmpBuff = (byte*)XMALLOC(ticketLen, ssl->heap, + DYNAMIC_TYPE_SESSION_TICK); + if (!tmpBuff) + return MEMORY_ERROR; + + if (wc_LockMutex(&session_mutex) != 0) { + XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); + return BAD_MUTEX_E; + } + + if ((word16)ticketLen != copyFrom->ticketLen) { + /* Another thread modified the ssl-> session ticket during alloc. + * Treat as error, since ticket different than when copy requested */ + ret = VAR_STATE_CHANGE_E; + } + + if (ret == WOLFSSL_SUCCESS) { + copyInto->ticket = (byte*)tmpBuff; + copyInto->isDynamic = 1; + XMEMCPY(copyInto->ticket, copyFrom->ticket, ticketLen); + } + } else { + /* Need to ensure ticket pointer gets updated to own buffer + * and is not pointing to buff of session copied from */ + copyInto->ticket = copyInto->staticTicket; + } + + if (doDynamicCopy) { + if (wc_UnLockMutex(&session_mutex) != 0) { + if (ret == WOLFSSL_SUCCESS) + ret = BAD_MUTEX_E; + } + } + + if (ret != WOLFSSL_SUCCESS) { + /* cleanup */ + if (tmpBuff) + XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); + copyInto->ticket = copyInto->staticTicket; + copyInto->isDynamic = 0; + } +#endif /* HAVE_SESSION_TICKET */ + return ret; +} + + +int SetSession(WOLFSSL* ssl, WOLFSSL_SESSION* session) +{ + if (ssl->options.sessionCacheOff) + return WOLFSSL_FAILURE; + +#ifdef OPENSSL_EXTRA + /* check for application context id */ + if (ssl->sessionCtxSz > 0) { + if (XMEMCMP(ssl->sessionCtx, session->sessionCtx, ssl->sessionCtxSz)) { + /* context id did not match! */ + WOLFSSL_MSG("Session context did not match"); + return SSL_FAILURE; + } + } +#endif /* OPENSSL_EXTRA */ + + if (LowResTimer() < (session->bornOn + session->timeout)) { + int ret = GetDeepCopySession(ssl, session); + if (ret == WOLFSSL_SUCCESS) { + ssl->options.resuming = 1; + +#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \ + defined(HAVE_SESSION_TICKET)) + ssl->version = session->version; +#endif +#if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) || \ + (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)) + ssl->options.cipherSuite0 = session->cipherSuite0; + ssl->options.cipherSuite = session->cipherSuite; +#endif + } + + return ret; + } + return WOLFSSL_FAILURE; /* session timed out */ +} + + +#ifdef WOLFSSL_SESSION_STATS +static int get_locked_session_stats(word32* active, word32* total, + word32* peak); +#endif + +int AddSession(WOLFSSL* ssl) +{ + word32 row = 0; + word32 idx = 0; + int error = 0; +#ifdef HAVE_SESSION_TICKET + byte* tmpBuff = NULL; + int ticLen = 0; +#endif + WOLFSSL_SESSION* session; + + if (ssl->options.sessionCacheOff) + return 0; + + if (ssl->options.haveSessionId == 0) + return 0; + +#ifdef HAVE_SESSION_TICKET + if (ssl->options.side == WOLFSSL_SERVER_END && ssl->options.useTicket == 1) + return 0; +#endif + +#ifdef HAVE_SESSION_TICKET + ticLen = ssl->session.ticketLen; + /* Alloc Memory here so if Malloc fails can exit outside of lock */ + if(ticLen > SESSION_TICKET_LEN) { + tmpBuff = (byte*)XMALLOC(ticLen, ssl->heap, + DYNAMIC_TYPE_SESSION_TICK); + if(!tmpBuff) + return MEMORY_E; + } +#endif + +#ifdef HAVE_EXT_CACHE + if (ssl->options.internalCacheOff) { + /* Create a new session object to be stored. */ + session = (WOLFSSL_SESSION*)XMALLOC(sizeof(WOLFSSL_SESSION), NULL, + DYNAMIC_TYPE_OPENSSL); + if (session == NULL) { +#ifdef HAVE_SESSION_TICKET + XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); +#endif + return MEMORY_E; + } + XMEMSET(session, 0, sizeof(WOLFSSL_SESSION)); + session->isAlloced = 1; + } + else +#endif + { + /* Use the session object in the cache for external cache if required. + */ +#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) + if (ssl->options.tls1_3) { + row = HashSession(ssl->session.sessionID, ID_LEN, &error) % + SESSION_ROWS; + } + else +#endif + { + row = HashSession(ssl->arrays->sessionID, ID_LEN, &error) % + SESSION_ROWS; + } + if (error != 0) { + WOLFSSL_MSG("Hash session failed"); +#ifdef HAVE_SESSION_TICKET + XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); +#endif + return error; + } + + if (wc_LockMutex(&session_mutex) != 0) { +#ifdef HAVE_SESSION_TICKET + XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); +#endif + return BAD_MUTEX_E; + } + + idx = SessionCache[row].nextIdx++; +#ifdef SESSION_INDEX + ssl->sessionIndex = (row << SESSIDX_ROW_SHIFT) | idx; +#endif + session = &SessionCache[row].Sessions[idx]; + } + + if (!ssl->options.tls1_3) + XMEMCPY(session->masterSecret, ssl->arrays->masterSecret, SECRET_LEN); + else + XMEMCPY(session->masterSecret, ssl->session.masterSecret, SECRET_LEN); + session->haveEMS = ssl->options.haveEMS; +#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) + if (ssl->options.tls1_3) { + XMEMCPY(session->sessionID, ssl->session.sessionID, ID_LEN); + session->sessionIDSz = ID_LEN; + } + else +#endif + { + XMEMCPY(session->sessionID, ssl->arrays->sessionID, ID_LEN); + session->sessionIDSz = ssl->arrays->sessionIDSz; + } + +#ifdef OPENSSL_EXTRA + /* If using compatibility layer then check for and copy over session context + * id. */ + if (ssl->sessionCtxSz > 0 && ssl->sessionCtxSz < ID_LEN) { + XMEMCPY(session->sessionCtx, ssl->sessionCtx, ssl->sessionCtxSz); + } +#endif + + session->timeout = ssl->timeout; + session->bornOn = LowResTimer(); + +#ifdef HAVE_SESSION_TICKET + /* Check if another thread modified ticket since alloc */ + if ((word16)ticLen != ssl->session.ticketLen) { + error = VAR_STATE_CHANGE_E; + } + + if (error == 0) { + /* Cleanup cache row's old Dynamic buff if exists */ + if(session->isDynamic) { + XFREE(session->ticket, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); + session->ticket = NULL; + } + + /* If too large to store in static buffer, use dyn buffer */ + if (ticLen > SESSION_TICKET_LEN) { + session->ticket = tmpBuff; + session->isDynamic = 1; + } else { + session->ticket = session->staticTicket; + session->isDynamic = 0; + } + } + + if (error == 0) { + session->ticketLen = (word16)ticLen; + XMEMCPY(session->ticket, ssl->session.ticket, ticLen); + } else { /* cleanup, reset state */ + session->ticket = session->staticTicket; + session->isDynamic = 0; + session->ticketLen = 0; + if (tmpBuff) { + XFREE(tmpBuff, ssl->heap, DYNAMIC_TYPE_SESSION_TICK); + tmpBuff = NULL; + } + } +#endif + +#ifdef SESSION_CERTS + if (error == 0) { + session->chain.count = ssl->session.chain.count; + XMEMCPY(session->chain.certs, ssl->session.chain.certs, + sizeof(x509_buffer) * MAX_CHAIN_DEPTH); + } +#endif /* SESSION_CERTS */ +#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \ + defined(HAVE_SESSION_TICKET)) + if (error == 0) { + session->version = ssl->version; + } +#endif /* SESSION_CERTS || (WOLFSSL_TLS13 & HAVE_SESSION_TICKET) */ +#if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) || \ + (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)) + if (error == 0) { + session->cipherSuite0 = ssl->options.cipherSuite0; + session->cipherSuite = ssl->options.cipherSuite; + } +#endif +#if defined(WOLFSSL_TLS13) + if (error == 0) { + session->namedGroup = ssl->session.namedGroup; + } +#endif +#if defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET) + if (error == 0) { + session->ticketSeen = ssl->session.ticketSeen; + session->ticketAdd = ssl->session.ticketAdd; +#ifndef WOLFSSL_TLS13_DRAFT_18 + XMEMCPY(&session->ticketNonce, &ssl->session.ticketNonce, + sizeof(TicketNonce)); +#endif + #ifdef WOLFSSL_EARLY_DATA + session->maxEarlyDataSz = ssl->session.maxEarlyDataSz; + #endif + } +#endif /* WOLFSSL_TLS13 && HAVE_SESSION_TICKET */ +#ifdef HAVE_EXT_CACHE + if (!ssl->options.internalCacheOff) +#endif + { + if (error == 0) { + SessionCache[row].totalCount++; + if (SessionCache[row].nextIdx == SESSIONS_PER_ROW) + SessionCache[row].nextIdx = 0; + } + } +#ifndef NO_CLIENT_CACHE + if (error == 0) { + if (ssl->options.side == WOLFSSL_CLIENT_END && ssl->session.idLen) { + word32 clientRow, clientIdx; + + WOLFSSL_MSG("Adding client cache entry"); + + session->idLen = ssl->session.idLen; + XMEMCPY(session->serverID, ssl->session.serverID, + ssl->session.idLen); + +#ifdef HAVE_EXT_CACHE + if (!ssl->options.internalCacheOff) +#endif + { + clientRow = HashSession(ssl->session.serverID, + ssl->session.idLen, &error) % SESSION_ROWS; + if (error != 0) { + WOLFSSL_MSG("Hash session failed"); + } else { + clientIdx = ClientCache[clientRow].nextIdx++; + + ClientCache[clientRow].Clients[clientIdx].serverRow = + (word16)row; + ClientCache[clientRow].Clients[clientIdx].serverIdx = + (word16)idx; + + ClientCache[clientRow].totalCount++; + if (ClientCache[clientRow].nextIdx == SESSIONS_PER_ROW) + ClientCache[clientRow].nextIdx = 0; + } + } + } + else + session->idLen = 0; + } +#endif /* NO_CLIENT_CACHE */ + +#if defined(WOLFSSL_SESSION_STATS) && defined(WOLFSSL_PEAK_SESSIONS) +#ifdef HAVE_EXT_CACHE + if (!ssl->options.internalCacheOff) +#endif + { + if (error == 0) { + word32 active = 0; + + error = get_locked_session_stats(&active, NULL, NULL); + if (error == WOLFSSL_SUCCESS) { + error = 0; /* back to this function ok */ + + if (active > PeakSessions) + PeakSessions = active; + } + } + } +#endif /* defined(WOLFSSL_SESSION_STATS) && defined(WOLFSSL_PEAK_SESSIONS) */ + +#ifdef HAVE_EXT_CACHE + if (!ssl->options.internalCacheOff) +#endif + { + if (wc_UnLockMutex(&session_mutex) != 0) + return BAD_MUTEX_E; + } + +#ifdef HAVE_EXT_CACHE + if (error == 0 && ssl->ctx->new_sess_cb != NULL) + ssl->ctx->new_sess_cb(ssl, session); + if (ssl->options.internalCacheOff) + wolfSSL_SESSION_free(session); +#endif + + return error; +} + + +#ifdef SESSION_INDEX + +int wolfSSL_GetSessionIndex(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_GetSessionIndex"); + WOLFSSL_LEAVE("wolfSSL_GetSessionIndex", ssl->sessionIndex); + return ssl->sessionIndex; +} + + +int wolfSSL_GetSessionAtIndex(int idx, WOLFSSL_SESSION* session) +{ + int row, col, result = WOLFSSL_FAILURE; + + WOLFSSL_ENTER("wolfSSL_GetSessionAtIndex"); + + row = idx >> SESSIDX_ROW_SHIFT; + col = idx & SESSIDX_IDX_MASK; + + if (wc_LockMutex(&session_mutex) != 0) { + return BAD_MUTEX_E; + } + + if (row < SESSION_ROWS && + col < (int)min(SessionCache[row].totalCount, SESSIONS_PER_ROW)) { + XMEMCPY(session, + &SessionCache[row].Sessions[col], sizeof(WOLFSSL_SESSION)); + result = WOLFSSL_SUCCESS; + } + + if (wc_UnLockMutex(&session_mutex) != 0) + result = BAD_MUTEX_E; + + WOLFSSL_LEAVE("wolfSSL_GetSessionAtIndex", result); + return result; +} + +#endif /* SESSION_INDEX */ + +#if defined(SESSION_INDEX) && defined(SESSION_CERTS) + +WOLFSSL_X509_CHAIN* wolfSSL_SESSION_get_peer_chain(WOLFSSL_SESSION* session) +{ + WOLFSSL_X509_CHAIN* chain = NULL; + + WOLFSSL_ENTER("wolfSSL_SESSION_get_peer_chain"); + if (session) + chain = &session->chain; + + WOLFSSL_LEAVE("wolfSSL_SESSION_get_peer_chain", chain ? 1 : 0); + return chain; +} + +#endif /* SESSION_INDEX && SESSION_CERTS */ + + +#ifdef WOLFSSL_SESSION_STATS + +/* requires session_mutex lock held, WOLFSSL_SUCCESS on ok */ +static int get_locked_session_stats(word32* active, word32* total, word32* peak) +{ + int result = WOLFSSL_SUCCESS; + int i; + int count; + int idx; + word32 now = 0; + word32 seen = 0; + word32 ticks = LowResTimer(); + + (void)peak; + + WOLFSSL_ENTER("get_locked_session_stats"); + + for (i = 0; i < SESSION_ROWS; i++) { + seen += SessionCache[i].totalCount; + + if (active == NULL) + continue; /* no need to calculate what we can't set */ + + count = min((word32)SessionCache[i].totalCount, SESSIONS_PER_ROW); + idx = SessionCache[i].nextIdx - 1; + if (idx < 0) + idx = SESSIONS_PER_ROW - 1; /* if back to front previous was end */ + + for (; count > 0; --count, idx = idx ? idx - 1 : SESSIONS_PER_ROW - 1) { + if (idx >= SESSIONS_PER_ROW || idx < 0) { /* sanity check */ + WOLFSSL_MSG("Bad idx"); + break; + } + + /* if not expired then good */ + if (ticks < (SessionCache[i].Sessions[idx].bornOn + + SessionCache[i].Sessions[idx].timeout) ) { + now++; + } + } + } + + if (active) + *active = now; + + if (total) + *total = seen; + +#ifdef WOLFSSL_PEAK_SESSIONS + if (peak) + *peak = PeakSessions; +#endif + + WOLFSSL_LEAVE("get_locked_session_stats", result); + + return result; +} + + +/* return WOLFSSL_SUCCESS on ok */ +int wolfSSL_get_session_stats(word32* active, word32* total, word32* peak, + word32* maxSessions) +{ + int result = WOLFSSL_SUCCESS; + + WOLFSSL_ENTER("wolfSSL_get_session_stats"); + + if (maxSessions) { + *maxSessions = SESSIONS_PER_ROW * SESSION_ROWS; + + if (active == NULL && total == NULL && peak == NULL) + return result; /* we're done */ + } + + /* user must provide at least one query value */ + if (active == NULL && total == NULL && peak == NULL) + return BAD_FUNC_ARG; + + if (wc_LockMutex(&session_mutex) != 0) { + return BAD_MUTEX_E; + } + + result = get_locked_session_stats(active, total, peak); + + if (wc_UnLockMutex(&session_mutex) != 0) + result = BAD_MUTEX_E; + + WOLFSSL_LEAVE("wolfSSL_get_session_stats", result); + + return result; +} + +#endif /* WOLFSSL_SESSION_STATS */ + + + #ifdef PRINT_SESSION_STATS + + /* WOLFSSL_SUCCESS on ok */ + int wolfSSL_PrintSessionStats(void) + { + word32 totalSessionsSeen = 0; + word32 totalSessionsNow = 0; + word32 peak = 0; + word32 maxSessions = 0; + int i; + int ret; + double E; /* expected freq */ + double chiSquare = 0; + + ret = wolfSSL_get_session_stats(&totalSessionsNow, &totalSessionsSeen, + &peak, &maxSessions); + if (ret != WOLFSSL_SUCCESS) + return ret; + printf("Total Sessions Seen = %d\n", totalSessionsSeen); + printf("Total Sessions Now = %d\n", totalSessionsNow); +#ifdef WOLFSSL_PEAK_SESSIONS + printf("Peak Sessions = %d\n", peak); +#endif + printf("Max Sessions = %d\n", maxSessions); + + E = (double)totalSessionsSeen / SESSION_ROWS; + + for (i = 0; i < SESSION_ROWS; i++) { + double diff = SessionCache[i].totalCount - E; + diff *= diff; /* square */ + diff /= E; /* normalize */ + + chiSquare += diff; + } + printf(" chi-square = %5.1f, d.f. = %d\n", chiSquare, + SESSION_ROWS - 1); + #if (SESSION_ROWS == 11) + printf(" .05 p value = 18.3, chi-square should be less\n"); + #elif (SESSION_ROWS == 211) + printf(".05 p value = 244.8, chi-square should be less\n"); + #elif (SESSION_ROWS == 5981) + printf(".05 p value = 6161.0, chi-square should be less\n"); + #elif (SESSION_ROWS == 3) + printf(".05 p value = 6.0, chi-square should be less\n"); + #elif (SESSION_ROWS == 2861) + printf(".05 p value = 2985.5, chi-square should be less\n"); + #endif + printf("\n"); + + return ret; + } + + #endif /* SESSION_STATS */ + +#else /* NO_SESSION_CACHE */ + +/* No session cache version */ +WOLFSSL_SESSION* GetSession(WOLFSSL* ssl, byte* masterSecret, + byte restoreSessionCerts) +{ + (void)ssl; + (void)masterSecret; + (void)restoreSessionCerts; + + return NULL; +} + +#endif /* NO_SESSION_CACHE */ + + +/* call before SSL_connect, if verifying will add name check to + date check and signature check */ +int wolfSSL_check_domain_name(WOLFSSL* ssl, const char* dn) +{ + WOLFSSL_ENTER("wolfSSL_check_domain_name"); + + if (ssl == NULL || dn == NULL) { + WOLFSSL_MSG("Bad function argument: NULL"); + return WOLFSSL_FAILURE; + } + + if (ssl->buffers.domainName.buffer) + XFREE(ssl->buffers.domainName.buffer, ssl->heap, DYNAMIC_TYPE_DOMAIN); + + ssl->buffers.domainName.length = (word32)XSTRLEN(dn); + ssl->buffers.domainName.buffer = (byte*)XMALLOC( + ssl->buffers.domainName.length + 1, ssl->heap, DYNAMIC_TYPE_DOMAIN); + + if (ssl->buffers.domainName.buffer) { + unsigned char* domainName = ssl->buffers.domainName.buffer; + XMEMCPY(domainName, dn, ssl->buffers.domainName.length); + domainName[ssl->buffers.domainName.length] = '\0'; + return WOLFSSL_SUCCESS; + } + else { + ssl->error = MEMORY_ERROR; + return WOLFSSL_FAILURE; + } +} + + +/* turn on wolfSSL zlib compression + returns WOLFSSL_SUCCESS for success, else error (not built in) +*/ +int wolfSSL_set_compression(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_set_compression"); + (void)ssl; +#ifdef HAVE_LIBZ + ssl->options.usingCompression = 1; + return WOLFSSL_SUCCESS; +#else + return NOT_COMPILED_IN; +#endif +} + + +#ifndef USE_WINDOWS_API + #ifndef NO_WRITEV + + /* simulate writev semantics, doesn't actually do block at a time though + because of SSL_write behavior and because front adds may be small */ + int wolfSSL_writev(WOLFSSL* ssl, const struct iovec* iov, int iovcnt) + { + #ifdef WOLFSSL_SMALL_STACK + byte staticBuffer[1]; /* force heap usage */ + #else + byte staticBuffer[FILE_BUFFER_SIZE]; + #endif + byte* myBuffer = staticBuffer; + int dynamic = 0; + int sending = 0; + int idx = 0; + int i; + int ret; + + WOLFSSL_ENTER("wolfSSL_writev"); + + for (i = 0; i < iovcnt; i++) + sending += (int)iov[i].iov_len; + + if (sending > (int)sizeof(staticBuffer)) { + myBuffer = (byte*)XMALLOC(sending, ssl->heap, + DYNAMIC_TYPE_WRITEV); + if (!myBuffer) + return MEMORY_ERROR; + + dynamic = 1; + } + + for (i = 0; i < iovcnt; i++) { + XMEMCPY(&myBuffer[idx], iov[i].iov_base, iov[i].iov_len); + idx += (int)iov[i].iov_len; + } + + ret = wolfSSL_write(ssl, myBuffer, sending); + + if (dynamic) + XFREE(myBuffer, ssl->heap, DYNAMIC_TYPE_WRITEV); + + return ret; + } + #endif +#endif + + +#ifdef WOLFSSL_CALLBACKS + + typedef struct itimerval Itimerval; + + /* don't keep calling simple functions while setting up timer and signals + if no inlining these are the next best */ + + #define AddTimes(a, b, c) \ + do { \ + c.tv_sec = a.tv_sec + b.tv_sec; \ + c.tv_usec = a.tv_usec + b.tv_usec; \ + if (c.tv_usec >= 1000000) { \ + c.tv_sec++; \ + c.tv_usec -= 1000000; \ + } \ + } while (0) + + + #define SubtractTimes(a, b, c) \ + do { \ + c.tv_sec = a.tv_sec - b.tv_sec; \ + c.tv_usec = a.tv_usec - b.tv_usec; \ + if (c.tv_usec < 0) { \ + c.tv_sec--; \ + c.tv_usec += 1000000; \ + } \ + } while (0) + + #define CmpTimes(a, b, cmp) \ + ((a.tv_sec == b.tv_sec) ? \ + (a.tv_usec cmp b.tv_usec) : \ + (a.tv_sec cmp b.tv_sec)) \ + + + /* do nothing handler */ + static void myHandler(int signo) + { + (void)signo; + return; + } + + + static int wolfSSL_ex_wrapper(WOLFSSL* ssl, HandShakeCallBack hsCb, + TimeoutCallBack toCb, Timeval timeout) + { + int ret = WOLFSSL_FATAL_ERROR; + int oldTimerOn = 0; /* was timer already on */ + Timeval startTime; + Timeval endTime; + Timeval totalTime; + Itimerval myTimeout; + Itimerval oldTimeout; /* if old timer adjust from total time to reset */ + struct sigaction act, oact; + + #define ERR_OUT(x) { ssl->hsInfoOn = 0; ssl->toInfoOn = 0; return x; } + + if (hsCb) { + ssl->hsInfoOn = 1; + InitHandShakeInfo(&ssl->handShakeInfo, ssl); + } + if (toCb) { + ssl->toInfoOn = 1; + InitTimeoutInfo(&ssl->timeoutInfo); + + if (gettimeofday(&startTime, 0) < 0) + ERR_OUT(GETTIME_ERROR); + + /* use setitimer to simulate getitimer, init 0 myTimeout */ + myTimeout.it_interval.tv_sec = 0; + myTimeout.it_interval.tv_usec = 0; + myTimeout.it_value.tv_sec = 0; + myTimeout.it_value.tv_usec = 0; + if (setitimer(ITIMER_REAL, &myTimeout, &oldTimeout) < 0) + ERR_OUT(SETITIMER_ERROR); + + if (oldTimeout.it_value.tv_sec || oldTimeout.it_value.tv_usec) { + oldTimerOn = 1; + + /* is old timer going to expire before ours */ + if (CmpTimes(oldTimeout.it_value, timeout, <)) { + timeout.tv_sec = oldTimeout.it_value.tv_sec; + timeout.tv_usec = oldTimeout.it_value.tv_usec; + } + } + myTimeout.it_value.tv_sec = timeout.tv_sec; + myTimeout.it_value.tv_usec = timeout.tv_usec; + + /* set up signal handler, don't restart socket send/recv */ + act.sa_handler = myHandler; + sigemptyset(&act.sa_mask); + act.sa_flags = 0; +#ifdef SA_INTERRUPT + act.sa_flags |= SA_INTERRUPT; +#endif + if (sigaction(SIGALRM, &act, &oact) < 0) + ERR_OUT(SIGACT_ERROR); + + if (setitimer(ITIMER_REAL, &myTimeout, 0) < 0) + ERR_OUT(SETITIMER_ERROR); + } + + /* do main work */ +#ifndef NO_WOLFSSL_CLIENT + if (ssl->options.side == WOLFSSL_CLIENT_END) + ret = wolfSSL_connect(ssl); +#endif +#ifndef NO_WOLFSSL_SERVER + if (ssl->options.side == WOLFSSL_SERVER_END) + ret = wolfSSL_accept(ssl); +#endif + + /* do callbacks */ + if (toCb) { + if (oldTimerOn) { + gettimeofday(&endTime, 0); + SubtractTimes(endTime, startTime, totalTime); + /* adjust old timer for elapsed time */ + if (CmpTimes(totalTime, oldTimeout.it_value, <)) + SubtractTimes(oldTimeout.it_value, totalTime, + oldTimeout.it_value); + else { + /* reset value to interval, may be off */ + oldTimeout.it_value.tv_sec = oldTimeout.it_interval.tv_sec; + oldTimeout.it_value.tv_usec =oldTimeout.it_interval.tv_usec; + } + /* keep iter the same whether there or not */ + } + /* restore old handler */ + if (sigaction(SIGALRM, &oact, 0) < 0) + ret = SIGACT_ERROR; /* more pressing error, stomp */ + else + /* use old settings which may turn off (expired or not there) */ + if (setitimer(ITIMER_REAL, &oldTimeout, 0) < 0) + ret = SETITIMER_ERROR; + + /* if we had a timeout call callback */ + if (ssl->timeoutInfo.timeoutName[0]) { + ssl->timeoutInfo.timeoutValue.tv_sec = timeout.tv_sec; + ssl->timeoutInfo.timeoutValue.tv_usec = timeout.tv_usec; + (toCb)(&ssl->timeoutInfo); + } + /* clean up */ + FreeTimeoutInfo(&ssl->timeoutInfo, ssl->heap); + ssl->toInfoOn = 0; + } + if (hsCb) { + FinishHandShakeInfo(&ssl->handShakeInfo); + (hsCb)(&ssl->handShakeInfo); + ssl->hsInfoOn = 0; + } + return ret; + } + + +#ifndef NO_WOLFSSL_CLIENT + + int wolfSSL_connect_ex(WOLFSSL* ssl, HandShakeCallBack hsCb, + TimeoutCallBack toCb, Timeval timeout) + { + WOLFSSL_ENTER("wolfSSL_connect_ex"); + return wolfSSL_ex_wrapper(ssl, hsCb, toCb, timeout); + } + +#endif + + +#ifndef NO_WOLFSSL_SERVER + + int wolfSSL_accept_ex(WOLFSSL* ssl, HandShakeCallBack hsCb, + TimeoutCallBack toCb,Timeval timeout) + { + WOLFSSL_ENTER("wolfSSL_accept_ex"); + return wolfSSL_ex_wrapper(ssl, hsCb, toCb, timeout); + } + +#endif + +#endif /* WOLFSSL_CALLBACKS */ + + +#ifndef NO_PSK + + void wolfSSL_CTX_set_psk_client_callback(WOLFSSL_CTX* ctx, + wc_psk_client_callback cb) + { + WOLFSSL_ENTER("SSL_CTX_set_psk_client_callback"); + + if (ctx == NULL) + return; + + ctx->havePSK = 1; + ctx->client_psk_cb = cb; + } + + + void wolfSSL_set_psk_client_callback(WOLFSSL* ssl,wc_psk_client_callback cb) + { + byte haveRSA = 1; + int keySz = 0; + + WOLFSSL_ENTER("SSL_set_psk_client_callback"); + + if (ssl == NULL) + return; + + ssl->options.havePSK = 1; + ssl->options.client_psk_cb = cb; + + #ifdef NO_RSA + haveRSA = 0; + #endif + #ifndef NO_CERTS + keySz = ssl->buffers.keySz; + #endif + InitSuites(ssl->suites, ssl->version, keySz, haveRSA, TRUE, + ssl->options.haveDH, ssl->options.haveNTRU, + ssl->options.haveECDSAsig, ssl->options.haveECC, + ssl->options.haveStaticECC, ssl->options.side); + } + + + void wolfSSL_CTX_set_psk_server_callback(WOLFSSL_CTX* ctx, + wc_psk_server_callback cb) + { + WOLFSSL_ENTER("SSL_CTX_set_psk_server_callback"); + if (ctx == NULL) + return; + ctx->havePSK = 1; + ctx->server_psk_cb = cb; + } + + + void wolfSSL_set_psk_server_callback(WOLFSSL* ssl,wc_psk_server_callback cb) + { + byte haveRSA = 1; + int keySz = 0; + + WOLFSSL_ENTER("SSL_set_psk_server_callback"); + if (ssl == NULL) + return; + + ssl->options.havePSK = 1; + ssl->options.server_psk_cb = cb; + + #ifdef NO_RSA + haveRSA = 0; + #endif + #ifndef NO_CERTS + keySz = ssl->buffers.keySz; + #endif + InitSuites(ssl->suites, ssl->version, keySz, haveRSA, TRUE, + ssl->options.haveDH, ssl->options.haveNTRU, + ssl->options.haveECDSAsig, ssl->options.haveECC, + ssl->options.haveStaticECC, ssl->options.side); + } + + + const char* wolfSSL_get_psk_identity_hint(const WOLFSSL* ssl) + { + WOLFSSL_ENTER("SSL_get_psk_identity_hint"); + + if (ssl == NULL || ssl->arrays == NULL) + return NULL; + + return ssl->arrays->server_hint; + } + + + const char* wolfSSL_get_psk_identity(const WOLFSSL* ssl) + { + WOLFSSL_ENTER("SSL_get_psk_identity"); + + if (ssl == NULL || ssl->arrays == NULL) + return NULL; + + return ssl->arrays->client_identity; + } + + + int wolfSSL_CTX_use_psk_identity_hint(WOLFSSL_CTX* ctx, const char* hint) + { + WOLFSSL_ENTER("SSL_CTX_use_psk_identity_hint"); + if (hint == 0) + ctx->server_hint[0] = '\0'; + else { + XSTRNCPY(ctx->server_hint, hint, sizeof(ctx->server_hint)); + ctx->server_hint[MAX_PSK_ID_LEN] = '\0'; /* null term */ + } + return WOLFSSL_SUCCESS; + } + + + int wolfSSL_use_psk_identity_hint(WOLFSSL* ssl, const char* hint) + { + WOLFSSL_ENTER("SSL_use_psk_identity_hint"); + + if (ssl == NULL || ssl->arrays == NULL) + return WOLFSSL_FAILURE; + + if (hint == 0) + ssl->arrays->server_hint[0] = 0; + else { + XSTRNCPY(ssl->arrays->server_hint, hint, + sizeof(ssl->arrays->server_hint)-1); + ssl->arrays->server_hint[sizeof(ssl->arrays->server_hint)-1] = '\0'; + } + return WOLFSSL_SUCCESS; + } + +#endif /* NO_PSK */ + + +#ifdef HAVE_ANON + + int wolfSSL_CTX_allow_anon_cipher(WOLFSSL_CTX* ctx) + { + WOLFSSL_ENTER("wolfSSL_CTX_allow_anon_cipher"); + + if (ctx == NULL) + return WOLFSSL_FAILURE; + + ctx->haveAnon = 1; + + return WOLFSSL_SUCCESS; + } + +#endif /* HAVE_ANON */ + + +#ifndef NO_CERTS +/* used to be defined on NO_FILESYSTEM only, but are generally useful */ + + /* wolfSSL extension allows DER files to be loaded from buffers as well */ + int wolfSSL_CTX_load_verify_buffer(WOLFSSL_CTX* ctx, + const unsigned char* in, + long sz, int format) + { + WOLFSSL_ENTER("wolfSSL_CTX_load_verify_buffer"); + if (format == WOLFSSL_FILETYPE_PEM) + return ProcessChainBuffer(ctx, in, sz, format, CA_TYPE, NULL); + else + return ProcessBuffer(ctx, in, sz, format, CA_TYPE, NULL,NULL,0); + } + + + int wolfSSL_CTX_load_verify_chain_buffer_format(WOLFSSL_CTX* ctx, + const unsigned char* in, + long sz, int format) + { + WOLFSSL_ENTER("wolfSSL_CTX_load_verify_chain_buffer_format"); + if (format == WOLFSSL_FILETYPE_PEM) + return ProcessChainBuffer(ctx, in, sz, format, CA_TYPE, NULL); + else + return ProcessBuffer(ctx, in, sz, format, CA_TYPE, NULL,NULL,1); + } + + +#ifdef WOLFSSL_TRUST_PEER_CERT + int wolfSSL_CTX_trust_peer_buffer(WOLFSSL_CTX* ctx, + const unsigned char* in, + long sz, int format) + { + WOLFSSL_ENTER("wolfSSL_CTX_trust_peer_buffer"); + + /* sanity check on arguments */ + if (sz < 0 || in == NULL || ctx == NULL) { + return BAD_FUNC_ARG; + } + + if (format == WOLFSSL_FILETYPE_PEM) + return ProcessChainBuffer(ctx, in, sz, format, + TRUSTED_PEER_TYPE, NULL); + else + return ProcessBuffer(ctx, in, sz, format, TRUSTED_PEER_TYPE, + NULL,NULL,0); + } +#endif /* WOLFSSL_TRUST_PEER_CERT */ + + + int wolfSSL_CTX_use_certificate_buffer(WOLFSSL_CTX* ctx, + const unsigned char* in, long sz, int format) + { + WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_buffer"); + return ProcessBuffer(ctx, in, sz, format, CERT_TYPE, NULL, NULL, 0); + } + + + int wolfSSL_CTX_use_PrivateKey_buffer(WOLFSSL_CTX* ctx, + const unsigned char* in, long sz, int format) + { + WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey_buffer"); + return ProcessBuffer(ctx, in, sz, format, PRIVATEKEY_TYPE, NULL,NULL,0); + } + +#ifdef HAVE_PKCS11 + int wolfSSL_CTX_use_PrivateKey_id(WOLFSSL_CTX* ctx, const unsigned char* id, + long sz, int devId, long keySz) + { + int ret = WOLFSSL_FAILURE; + + FreeDer(&ctx->privateKey); + if (AllocDer(&ctx->privateKey, (word32)sz, PRIVATEKEY_TYPE, + ctx->heap) == 0) { + XMEMCPY(ctx->privateKey->buffer, id, sz); + ctx->privateKeyId = 1; + ctx->privateKeySz = (word32)keySz; + if (devId != INVALID_DEVID) + ctx->privateKeyDevId = devId; + else + ctx->privateKeyDevId = ctx->devId; + + ret = WOLFSSL_SUCCESS; + } + + return ret; + } +#endif + + int wolfSSL_CTX_use_certificate_chain_buffer_format(WOLFSSL_CTX* ctx, + const unsigned char* in, long sz, int format) + { + WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_chain_buffer_format"); + return ProcessBuffer(ctx, in, sz, format, CERT_TYPE, NULL, NULL, 1); + } + + int wolfSSL_CTX_use_certificate_chain_buffer(WOLFSSL_CTX* ctx, + const unsigned char* in, long sz) + { + return wolfSSL_CTX_use_certificate_chain_buffer_format(ctx, in, sz, + WOLFSSL_FILETYPE_PEM); + } + + +#ifndef NO_DH + + /* server wrapper for ctx or ssl Diffie-Hellman parameters */ + static int wolfSSL_SetTmpDH_buffer_wrapper(WOLFSSL_CTX* ctx, WOLFSSL* ssl, + const unsigned char* buf, + long sz, int format) + { + DerBuffer* der = NULL; + int ret = 0; + word32 pSz = MAX_DH_SIZE; + word32 gSz = MAX_DH_SIZE; + #ifdef WOLFSSL_SMALL_STACK + byte* p = NULL; + byte* g = NULL; + #else + byte p[MAX_DH_SIZE]; + byte g[MAX_DH_SIZE]; + #endif + + if (ctx == NULL || buf == NULL) + return BAD_FUNC_ARG; + + ret = AllocDer(&der, 0, DH_PARAM_TYPE, ctx->heap); + if (ret != 0) { + return ret; + } + der->buffer = (byte*)buf; + der->length = (word32)sz; + + #ifdef WOLFSSL_SMALL_STACK + p = (byte*)XMALLOC(pSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + g = (byte*)XMALLOC(gSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + + if (p == NULL || g == NULL) { + XFREE(p, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + XFREE(g, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + return MEMORY_E; + } + #endif + + if (format != WOLFSSL_FILETYPE_ASN1 && format != WOLFSSL_FILETYPE_PEM) + ret = WOLFSSL_BAD_FILETYPE; + else { + if (format == WOLFSSL_FILETYPE_PEM) { +#ifdef WOLFSSL_PEM_TO_DER + FreeDer(&der); + ret = PemToDer(buf, sz, DH_PARAM_TYPE, &der, ctx->heap, + NULL, NULL); + #ifdef WOLFSSL_WPAS + #ifndef NO_DSA + if (ret < 0) { + ret = PemToDer(buf, sz, DSA_PARAM_TYPE, &der, ctx->heap, + NULL, NULL); + } + #endif + #endif /* WOLFSSL_WPAS */ +#else + ret = NOT_COMPILED_IN; +#endif /* WOLFSSL_PEM_TO_DER */ + } + + if (ret == 0) { + if (wc_DhParamsLoad(der->buffer, der->length, p, &pSz, g, &gSz) < 0) + ret = WOLFSSL_BAD_FILETYPE; + else if (ssl) + ret = wolfSSL_SetTmpDH(ssl, p, pSz, g, gSz); + else + ret = wolfSSL_CTX_SetTmpDH(ctx, p, pSz, g, gSz); + } + } + + FreeDer(&der); + + #ifdef WOLFSSL_SMALL_STACK + XFREE(p, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + XFREE(g, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + #endif + + return ret; + } + + + /* server Diffie-Hellman parameters, WOLFSSL_SUCCESS on ok */ + int wolfSSL_SetTmpDH_buffer(WOLFSSL* ssl, const unsigned char* buf, long sz, + int format) + { + if (ssl == NULL) + return BAD_FUNC_ARG; + + return wolfSSL_SetTmpDH_buffer_wrapper(ssl->ctx, ssl, buf, sz, format); + } + + + /* server ctx Diffie-Hellman parameters, WOLFSSL_SUCCESS on ok */ + int wolfSSL_CTX_SetTmpDH_buffer(WOLFSSL_CTX* ctx, const unsigned char* buf, + long sz, int format) + { + return wolfSSL_SetTmpDH_buffer_wrapper(ctx, NULL, buf, sz, format); + } + +#endif /* NO_DH */ + + + int wolfSSL_use_certificate_buffer(WOLFSSL* ssl, + const unsigned char* in, long sz, int format) + { + WOLFSSL_ENTER("wolfSSL_use_certificate_buffer"); + return ProcessBuffer(ssl->ctx, in, sz, format,CERT_TYPE,ssl,NULL,0); + } + + + int wolfSSL_use_PrivateKey_buffer(WOLFSSL* ssl, + const unsigned char* in, long sz, int format) + { + WOLFSSL_ENTER("wolfSSL_use_PrivateKey_buffer"); + return ProcessBuffer(ssl->ctx, in, sz, format, PRIVATEKEY_TYPE, + ssl, NULL, 0); + } + +#ifdef HAVE_PKCS11 + int wolfSSL_use_PrivateKey_id(WOLFSSL* ssl, const unsigned char* id, + long sz, int devId, long keySz) + { + int ret = WOLFSSL_FAILURE; + + if (ssl->buffers.weOwnKey) + FreeDer(&ssl->buffers.key); + if (AllocDer(&ssl->buffers.key, (word32)sz, PRIVATEKEY_TYPE, + ssl->heap) == 0) { + XMEMCPY(ssl->buffers.key->buffer, id, sz); + ssl->buffers.weOwnKey = 1; + ssl->buffers.keyId = 1; + ssl->buffers.keySz = (word32)keySz; + if (devId != INVALID_DEVID) + ssl->buffers.keyDevId = devId; + else + ssl->buffers.keyDevId = ssl->devId; + + ret = WOLFSSL_SUCCESS; + } + + return ret; + } +#endif + + int wolfSSL_use_certificate_chain_buffer_format(WOLFSSL* ssl, + const unsigned char* in, long sz, int format) + { + WOLFSSL_ENTER("wolfSSL_use_certificate_chain_buffer_format"); + return ProcessBuffer(ssl->ctx, in, sz, format, CERT_TYPE, + ssl, NULL, 1); + } + + int wolfSSL_use_certificate_chain_buffer(WOLFSSL* ssl, + const unsigned char* in, long sz) + { + return wolfSSL_use_certificate_chain_buffer_format(ssl, in, sz, + WOLFSSL_FILETYPE_PEM); + } + + + /* unload any certs or keys that SSL owns, leave CTX as is + WOLFSSL_SUCCESS on ok */ + int wolfSSL_UnloadCertsKeys(WOLFSSL* ssl) + { + if (ssl == NULL) { + WOLFSSL_MSG("Null function arg"); + return BAD_FUNC_ARG; + } + + if (ssl->buffers.weOwnCert && !ssl->keepCert) { + WOLFSSL_MSG("Unloading cert"); + FreeDer(&ssl->buffers.certificate); + #ifdef KEEP_OUR_CERT + FreeX509(ssl->ourCert); + if (ssl->ourCert) { + XFREE(ssl->ourCert, ssl->heap, DYNAMIC_TYPE_X509); + ssl->ourCert = NULL; + } + #endif + ssl->buffers.weOwnCert = 0; + } + + if (ssl->buffers.weOwnCertChain) { + WOLFSSL_MSG("Unloading cert chain"); + FreeDer(&ssl->buffers.certChain); + ssl->buffers.weOwnCertChain = 0; + } + + if (ssl->buffers.weOwnKey) { + WOLFSSL_MSG("Unloading key"); + FreeDer(&ssl->buffers.key); + ssl->buffers.weOwnKey = 0; + } + + return WOLFSSL_SUCCESS; + } + + + int wolfSSL_CTX_UnloadCAs(WOLFSSL_CTX* ctx) + { + WOLFSSL_ENTER("wolfSSL_CTX_UnloadCAs"); + + if (ctx == NULL) + return BAD_FUNC_ARG; + + return wolfSSL_CertManagerUnloadCAs(ctx->cm); + } + + +#ifdef WOLFSSL_TRUST_PEER_CERT + int wolfSSL_CTX_Unload_trust_peers(WOLFSSL_CTX* ctx) + { + WOLFSSL_ENTER("wolfSSL_CTX_Unload_trust_peers"); + + if (ctx == NULL) + return BAD_FUNC_ARG; + + return wolfSSL_CertManagerUnload_trust_peers(ctx->cm); + } +#endif /* WOLFSSL_TRUST_PEER_CERT */ +/* old NO_FILESYSTEM end */ +#endif /* !NO_CERTS */ + + +#ifdef OPENSSL_EXTRA + + int wolfSSL_add_all_algorithms(void) + { + WOLFSSL_ENTER("wolfSSL_add_all_algorithms"); + if (wolfSSL_Init() == WOLFSSL_SUCCESS) + return WOLFSSL_SUCCESS; + else + return WOLFSSL_FATAL_ERROR; + } + + int wolfSSL_OpenSSL_add_all_algorithms_noconf(void) + { + WOLFSSL_ENTER("wolfSSL_OpenSSL_add_all_algorithms_noconf"); + + if (wolfSSL_add_all_algorithms() == WOLFSSL_FATAL_ERROR) + return WOLFSSL_FATAL_ERROR; + + return WOLFSSL_SUCCESS; + } + + /* returns previous set cache size which stays constant */ + long wolfSSL_CTX_sess_set_cache_size(WOLFSSL_CTX* ctx, long sz) + { + /* cache size fixed at compile time in wolfSSL */ + (void)ctx; + (void)sz; + WOLFSSL_MSG("session cache is set at compile time"); + #ifndef NO_SESSION_CACHE + return SESSIONS_PER_ROW * SESSION_ROWS; + #else + return 0; + #endif + } + +#endif + +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA) + void wolfSSL_CTX_set_quiet_shutdown(WOLFSSL_CTX* ctx, int mode) + { + WOLFSSL_ENTER("wolfSSL_CTX_set_quiet_shutdown"); + if (mode) + ctx->quietShutdown = 1; + } + + + void wolfSSL_set_quiet_shutdown(WOLFSSL* ssl, int mode) + { + WOLFSSL_ENTER("wolfSSL_CTX_set_quiet_shutdown"); + if (mode) + ssl->options.quietShutdown = 1; + } +#endif + +#ifdef OPENSSL_EXTRA + void wolfSSL_set_bio(WOLFSSL* ssl, WOLFSSL_BIO* rd, WOLFSSL_BIO* wr) + { + WOLFSSL_ENTER("wolfSSL_set_bio"); + + if (ssl == NULL) { + WOLFSSL_MSG("Bad argument, ssl was NULL"); + return; + } + + /* if WOLFSSL_BIO is socket type then set WOLFSSL socket to use */ + if (rd != NULL && rd->type == WOLFSSL_BIO_SOCKET) { + wolfSSL_set_rfd(ssl, rd->fd); + } + if (wr != NULL && wr->type == WOLFSSL_BIO_SOCKET) { + wolfSSL_set_wfd(ssl, wr->fd); + } + + /* free any existing WOLFSSL_BIOs in use */ + if (ssl->biord != NULL) { + if (ssl->biord != ssl->biowr) { + if (ssl->biowr != NULL) { + wolfSSL_BIO_free(ssl->biowr); + ssl->biowr = NULL; + } + } + wolfSSL_BIO_free(ssl->biord); + ssl->biord = NULL; + } + + + ssl->biord = rd; + ssl->biowr = wr; + + /* set SSL to use BIO callbacks instead */ + if (((ssl->cbioFlag & WOLFSSL_CBIO_RECV) == 0) && + (rd != NULL && rd->type != WOLFSSL_BIO_SOCKET)) { + ssl->CBIORecv = BioReceive; + } + if (((ssl->cbioFlag & WOLFSSL_CBIO_SEND) == 0) && + (wr != NULL && wr->type != WOLFSSL_BIO_SOCKET)) { + ssl->CBIOSend = BioSend; + } + } +#endif + +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA) || defined(HAVE_WEBSERVER) + void wolfSSL_CTX_set_client_CA_list(WOLFSSL_CTX* ctx, + WOLF_STACK_OF(WOLFSSL_X509_NAME)* names) + { + WOLFSSL_ENTER("wolfSSL_SSL_CTX_set_client_CA_list"); + #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA) + if (ctx != NULL) + ctx->ca_names = names; + #else + (void)ctx; + (void)names; + #endif + } +#endif + +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA) + WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_SSL_CTX_get_client_CA_list( + const WOLFSSL_CTX *s) + { + WOLFSSL_ENTER("wolfSSL_SSL_CTX_get_client_CA_list"); + + if (s == NULL) + return NULL; + + return s->ca_names; + } +#endif + +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + #if !defined(NO_RSA) && !defined(NO_CERTS) + WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_load_client_CA_file(const char* fname) + { + /* The webserver build is using this to load a CA into the server + * for client authentication as an option. Have this return NULL in + * that case. If OPENSSL_EXTRA is enabled, go ahead and include + * the function. */ + #ifdef OPENSSL_EXTRA + WOLFSSL_STACK *list = NULL; + WOLFSSL_STACK *node; + WOLFSSL_BIO* bio; + WOLFSSL_X509 *cert = NULL; + WOLFSSL_X509_NAME *subjectName = NULL; + + WOLFSSL_ENTER("wolfSSL_load_client_CA_file"); + + bio = wolfSSL_BIO_new_file(fname, "r"); + if (bio == NULL) + return NULL; + + /* Read each certificate in the chain out of the file. */ + while (wolfSSL_PEM_read_bio_X509(bio, &cert, NULL, NULL) != NULL) { + subjectName = wolfSSL_X509_get_subject_name(cert); + if (subjectName == NULL) + break; + + node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL, + DYNAMIC_TYPE_OPENSSL); + if (node == NULL) + break; + + /* Need a persistent copy of the subject name. */ + node->data.name = (WOLFSSL_X509_NAME*)XMALLOC( + sizeof(WOLFSSL_X509_NAME), NULL, DYNAMIC_TYPE_OPENSSL); + if (node->data.name == NULL) { + XFREE(node, NULL, DYNAMIC_TYPE_OPENSSL); + break; + } + XMEMCPY(node->data.name, subjectName, sizeof(WOLFSSL_X509_NAME)); + /* Clear pointers so freeing certificate doesn't free memory. */ + XMEMSET(subjectName, 0, sizeof(WOLFSSL_X509_NAME)); + + /* Put node on the front of the list. */ + node->num = (list == NULL) ? 1 : list->num + 1; + node->next = list; + list = node; + + wolfSSL_X509_free(cert); + cert = NULL; + } + + wolfSSL_X509_free(cert); + wolfSSL_BIO_free(bio); + return list; + #else + (void)fname; + return NULL; + #endif + } + #endif +#endif + +#ifdef OPENSSL_EXTRA + #if !defined(NO_RSA) && !defined(NO_CERTS) + int wolfSSL_CTX_add_client_CA(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509) + { + WOLFSSL_STACK *node = NULL; + WOLFSSL_X509_NAME *subjectName = NULL; + + WOLFSSL_ENTER("wolfSSL_CTX_add_client_CA"); + + if (ctx == NULL || x509 == NULL){ + WOLFSSL_MSG("Bad argument"); + return SSL_FAILURE; + } + + subjectName = wolfSSL_X509_get_subject_name(x509); + if (subjectName == NULL){ + WOLFSSL_MSG("invalid x509 data"); + return SSL_FAILURE; + } + + /* Alloc stack struct */ + node = (WOLF_STACK_OF(WOLFSSL_X509_NAME)*)XMALLOC( + sizeof(WOLF_STACK_OF(WOLFSSL_X509_NAME)), + NULL, DYNAMIC_TYPE_OPENSSL); + if (node == NULL){ + WOLFSSL_MSG("memory allocation error"); + return SSL_FAILURE; + } + XMEMSET(node, 0, sizeof(WOLF_STACK_OF(WOLFSSL_X509_NAME))); + + /* Alloc and copy WOLFSSL_X509_NAME */ + node->data.name = (WOLFSSL_X509_NAME*)XMALLOC( + sizeof(WOLFSSL_X509_NAME), + NULL, DYNAMIC_TYPE_OPENSSL); + if (node->data.name == NULL) { + XFREE(node, NULL, DYNAMIC_TYPE_OPENSSL); + WOLFSSL_MSG("memory allocation error"); + return SSL_FAILURE; + } + XMEMCPY(node->data.name, subjectName, sizeof(WOLFSSL_X509_NAME)); + XMEMSET(subjectName, 0, sizeof(WOLFSSL_X509_NAME)); + + /* push new node onto head of stack */ + node->num = (ctx->ca_names == NULL) ? 1 : ctx->ca_names->num + 1; + node->next = ctx->ca_names; + ctx->ca_names = node; + return SSL_SUCCESS; + } + #endif + + #ifndef NO_WOLFSSL_STUB + int wolfSSL_CTX_set_default_verify_paths(WOLFSSL_CTX* ctx) + { + /* TODO:, not needed in goahead */ + (void)ctx; + WOLFSSL_STUB("SSL_CTX_set_default_verify_paths"); + return SSL_NOT_IMPLEMENTED; + } + #endif + + #if defined(WOLFCRYPT_HAVE_SRP) && !defined(NO_SHA256) \ + && !defined(WC_NO_RNG) + static const byte srp_N[] = { + 0xEE, 0xAF, 0x0A, 0xB9, 0xAD, 0xB3, 0x8D, 0xD6, 0x9C, 0x33, 0xF8, + 0x0A, 0xFA, 0x8F, 0xC5, 0xE8, 0x60, 0x72, 0x61, 0x87, 0x75, 0xFF, + 0x3C, 0x0B, 0x9E, 0xA2, 0x31, 0x4C, 0x9C, 0x25, 0x65, 0x76, 0xD6, + 0x74, 0xDF, 0x74, 0x96, 0xEA, 0x81, 0xD3, 0x38, 0x3B, 0x48, 0x13, + 0xD6, 0x92, 0xC6, 0xE0, 0xE0, 0xD5, 0xD8, 0xE2, 0x50, 0xB9, 0x8B, + 0xE4, 0x8E, 0x49, 0x5C, 0x1D, 0x60, 0x89, 0xDA, 0xD1, 0x5D, 0xC7, + 0xD7, 0xB4, 0x61, 0x54, 0xD6, 0xB6, 0xCE, 0x8E, 0xF4, 0xAD, 0x69, + 0xB1, 0x5D, 0x49, 0x82, 0x55, 0x9B, 0x29, 0x7B, 0xCF, 0x18, 0x85, + 0xC5, 0x29, 0xF5, 0x66, 0x66, 0x0E, 0x57, 0xEC, 0x68, 0xED, 0xBC, + 0x3C, 0x05, 0x72, 0x6C, 0xC0, 0x2F, 0xD4, 0xCB, 0xF4, 0x97, 0x6E, + 0xAA, 0x9A, 0xFD, 0x51, 0x38, 0xFE, 0x83, 0x76, 0x43, 0x5B, 0x9F, + 0xC6, 0x1D, 0x2F, 0xC0, 0xEB, 0x06, 0xE3 + }; + static const byte srp_g[] = { + 0x02 + }; + + int wolfSSL_CTX_set_srp_username(WOLFSSL_CTX* ctx, char* username) + { + int r = 0; + SrpSide srp_side = SRP_CLIENT_SIDE; + WC_RNG rng; + byte salt[SRP_SALT_SIZE]; + + WOLFSSL_ENTER("wolfSSL_CTX_set_srp_username"); + if (ctx == NULL || ctx->srp == NULL || username==NULL) + return SSL_FAILURE; + + if (ctx->method->side == WOLFSSL_SERVER_END){ + srp_side = SRP_SERVER_SIDE; + } else if (ctx->method->side == WOLFSSL_CLIENT_END){ + srp_side = SRP_CLIENT_SIDE; + } else { + WOLFSSL_MSG("Init CTX failed"); + return SSL_FAILURE; + } + + if (wc_SrpInit(ctx->srp, SRP_TYPE_SHA256, srp_side) < 0){ + WOLFSSL_MSG("Init CTX failed"); + XFREE(ctx->srp, ctx->heap, DYNAMIC_TYPE_SRP); + wolfSSL_CTX_free(ctx); + return SSL_FAILURE; + } + r = wc_SrpSetUsername(ctx->srp, (const byte*)username, + (word32)XSTRLEN(username)); + if (r < 0) { + WOLFSSL_MSG("fail to set srp username."); + return SSL_FAILURE; + } + + /* if wolfSSL_CTX_set_srp_password has already been called, */ + /* execute wc_SrpSetPassword here */ + if (ctx->srp_password != NULL){ + if (wc_InitRng(&rng) < 0){ + WOLFSSL_MSG("wc_InitRng failed"); + return SSL_FAILURE; + } + XMEMSET(salt, 0, sizeof(salt)/sizeof(salt[0])); + if (wc_RNG_GenerateBlock(&rng, salt, + sizeof(salt)/sizeof(salt[0])) < 0){ + WOLFSSL_MSG("wc_RNG_GenerateBlock failed"); + wc_FreeRng(&rng); + return SSL_FAILURE; + } + if (wc_SrpSetParams(ctx->srp, srp_N, sizeof(srp_N)/sizeof(srp_N[0]), + srp_g, sizeof(srp_g)/sizeof(srp_g[0]), + salt, sizeof(salt)/sizeof(salt[0])) < 0){ + WOLFSSL_MSG("wc_SrpSetParam failed"); + wc_FreeRng(&rng); + return SSL_FAILURE; + } + r = wc_SrpSetPassword(ctx->srp, + (const byte*)ctx->srp_password, + (word32)XSTRLEN((char *)ctx->srp_password)); + if (r < 0) { + WOLFSSL_MSG("fail to set srp password."); + return SSL_FAILURE; + } + wc_FreeRng(&rng); + XFREE(ctx->srp_password, ctx->heap, DYNAMIC_TYPE_SRP); + ctx->srp_password = NULL; + } + + return SSL_SUCCESS; + } + + int wolfSSL_CTX_set_srp_password(WOLFSSL_CTX* ctx, char* password) + { + int r; + WC_RNG rng; + byte salt[SRP_SALT_SIZE]; + + WOLFSSL_ENTER("wolfSSL_CTX_set_srp_password"); + if (ctx == NULL || ctx->srp == NULL || password == NULL) + return SSL_FAILURE; + + if (ctx->srp->user != NULL){ + if (wc_InitRng(&rng) < 0){ + WOLFSSL_MSG("wc_InitRng failed"); + return SSL_FAILURE; + } + XMEMSET(salt, 0, sizeof(salt)/sizeof(salt[0])); + if (wc_RNG_GenerateBlock(&rng, salt, + sizeof(salt)/sizeof(salt[0])) < 0){ + WOLFSSL_MSG("wc_RNG_GenerateBlock failed"); + wc_FreeRng(&rng); + return SSL_FAILURE; + } + if (wc_SrpSetParams(ctx->srp, srp_N, sizeof(srp_N)/sizeof(srp_N[0]), + srp_g, sizeof(srp_g)/sizeof(srp_g[0]), + salt, sizeof(salt)/sizeof(salt[0])) < 0){ + WOLFSSL_MSG("wc_SrpSetParam failed"); + wc_FreeRng(&rng); + return SSL_FAILURE; + } + r = wc_SrpSetPassword(ctx->srp, (const byte*)password, + (word32)XSTRLEN(password)); + if (r < 0) { + WOLFSSL_MSG("wc_SrpSetPassword failed."); + wc_FreeRng(&rng); + return SSL_FAILURE; + } + if (ctx->srp_password != NULL){ + XFREE(ctx->srp_password,NULL, + DYNAMIC_TYPE_SRP); + ctx->srp_password = NULL; + } + wc_FreeRng(&rng); + } else { + /* save password for wolfSSL_set_srp_username */ + if (ctx->srp_password != NULL) + XFREE(ctx->srp_password,ctx->heap, DYNAMIC_TYPE_SRP); + + ctx->srp_password = (byte*)XMALLOC(XSTRLEN(password) + 1, ctx->heap, + DYNAMIC_TYPE_SRP); + if (ctx->srp_password == NULL){ + WOLFSSL_MSG("memory allocation error"); + return SSL_FAILURE; + } + XMEMCPY(ctx->srp_password, password, XSTRLEN(password) + 1); + } + return SSL_SUCCESS; + } + #endif /* WOLFCRYPT_HAVE_SRP && !NO_SHA256 && !WC_NO_RNG */ + + /* keyblock size in bytes or -1 */ + int wolfSSL_get_keyblock_size(WOLFSSL* ssl) + { + if (ssl == NULL) + return WOLFSSL_FATAL_ERROR; + + return 2 * (ssl->specs.key_size + ssl->specs.iv_size + + ssl->specs.hash_size); + } + + + /* store keys returns WOLFSSL_SUCCESS or -1 on error */ + int wolfSSL_get_keys(WOLFSSL* ssl, unsigned char** ms, unsigned int* msLen, + unsigned char** sr, unsigned int* srLen, + unsigned char** cr, unsigned int* crLen) + { + if (ssl == NULL || ssl->arrays == NULL) + return WOLFSSL_FATAL_ERROR; + + *ms = ssl->arrays->masterSecret; + *sr = ssl->arrays->serverRandom; + *cr = ssl->arrays->clientRandom; + + *msLen = SECRET_LEN; + *srLen = RAN_LEN; + *crLen = RAN_LEN; + + return WOLFSSL_SUCCESS; + } + +#endif /* OPENSSL_EXTRA */ + +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA) + void wolfSSL_set_accept_state(WOLFSSL* ssl) + { + WOLFSSL_ENTER("wolfSSL_set_accept_state"); + if (ssl->options.side == WOLFSSL_CLIENT_END) { + #ifdef HAVE_ECC + ecc_key key; + word32 idx = 0; + + if (ssl->options.haveStaticECC && ssl->buffers.key != NULL) { + if (wc_ecc_init(&key) >= 0) { + if (wc_EccPrivateKeyDecode(ssl->buffers.key->buffer, &idx, &key, + ssl->buffers.key->length) != 0) { + ssl->options.haveECDSAsig = 0; + ssl->options.haveECC = 0; + ssl->options.haveStaticECC = 0; + } + wc_ecc_free(&key); + } + } + #endif + + #ifndef NO_DH + if (!ssl->options.haveDH && ssl->ctx->haveDH) { + ssl->buffers.serverDH_P = ssl->ctx->serverDH_P; + ssl->buffers.serverDH_G = ssl->ctx->serverDH_G; + ssl->options.haveDH = 1; + } + #endif + } + + if (InitSSL_Side(ssl, WOLFSSL_SERVER_END) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Error initializing server side"); + } + } + +#endif /* OPENSSL_EXTRA || WOLFSSL_EXTRA */ + + /* return true if connection established */ + int wolfSSL_is_init_finished(WOLFSSL* ssl) + { + if (ssl == NULL) + return 0; + + if (ssl->options.handShakeState == HANDSHAKE_DONE) + return 1; + + return 0; + } + +#ifdef OPENSSL_EXTRA + + void wolfSSL_CTX_set_tmp_rsa_callback(WOLFSSL_CTX* ctx, + WOLFSSL_RSA*(*f)(WOLFSSL*, int, int)) + { + /* wolfSSL verifies all these internally */ + (void)ctx; + (void)f; + } + + + void wolfSSL_set_shutdown(WOLFSSL* ssl, int opt) + { + WOLFSSL_ENTER("wolfSSL_set_shutdown"); + if(ssl==NULL) { + WOLFSSL_MSG("Shutdown not set. ssl is null"); + return; + } + + ssl->options.sentNotify = (opt&WOLFSSL_SENT_SHUTDOWN) > 0; + ssl->options.closeNotify = (opt&WOLFSSL_RECEIVED_SHUTDOWN) > 0; + } + + + long wolfSSL_CTX_get_options(WOLFSSL_CTX* ctx) + { + WOLFSSL_ENTER("wolfSSL_CTX_get_options"); + WOLFSSL_MSG("wolfSSL options are set through API calls and macros"); + if(ctx == NULL) + return BAD_FUNC_ARG; + return ctx->mask; + } + +#endif + +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + + static long wolf_set_options(long old_op, long op); + long wolfSSL_CTX_set_options(WOLFSSL_CTX* ctx, long opt) + { + WOLFSSL_ENTER("SSL_CTX_set_options"); + + if (ctx == NULL) + return BAD_FUNC_ARG; + + ctx->mask = wolf_set_options(ctx->mask, opt); + + return ctx->mask; + } + +#endif + +#ifdef OPENSSL_EXTRA + + long wolfSSL_CTX_clear_options(WOLFSSL_CTX* ctx, long opt) + { + WOLFSSL_ENTER("SSL_CTX_clear_options"); + if(ctx == NULL) + return BAD_FUNC_ARG; + ctx->mask &= ~opt; + return ctx->mask; + } + + int wolfSSL_set_rfd(WOLFSSL* ssl, int rfd) + { + WOLFSSL_ENTER("SSL_set_rfd"); + ssl->rfd = rfd; /* not used directly to allow IO callbacks */ + + ssl->IOCB_ReadCtx = &ssl->rfd; + + return WOLFSSL_SUCCESS; + } + + + int wolfSSL_set_wfd(WOLFSSL* ssl, int wfd) + { + WOLFSSL_ENTER("SSL_set_wfd"); + ssl->wfd = wfd; /* not used directly to allow IO callbacks */ + + ssl->IOCB_WriteCtx = &ssl->wfd; + + return WOLFSSL_SUCCESS; + } + + + + +#ifndef NO_CERTS + WOLFSSL_X509_STORE* wolfSSL_CTX_get_cert_store(WOLFSSL_CTX* ctx) + { + if (ctx == NULL) { + return NULL; + } + + return &ctx->x509_store; + } + + + void wolfSSL_CTX_set_cert_store(WOLFSSL_CTX* ctx, WOLFSSL_X509_STORE* str) + { + if (ctx == NULL || str == NULL) { + return; + } + + /* free cert manager if have one */ + if (ctx->cm != NULL) { + wolfSSL_CertManagerFree(ctx->cm); + } + ctx->cm = str->cm; + ctx->x509_store.cache = str->cache; + ctx->x509_store_pt = str; /* take ownership of store and free it + with CTX free */ + } + + + WOLFSSL_X509* wolfSSL_X509_STORE_CTX_get_current_cert( + WOLFSSL_X509_STORE_CTX* ctx) + { + WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get_current_cert"); + if (ctx) + return ctx->current_cert; + return NULL; + } + + + int wolfSSL_X509_STORE_CTX_get_error(WOLFSSL_X509_STORE_CTX* ctx) + { + WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get_error"); + if (ctx != NULL) + return ctx->error; + return 0; + } + + + int wolfSSL_X509_STORE_CTX_get_error_depth(WOLFSSL_X509_STORE_CTX* ctx) + { + WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get_error_depth"); + if(ctx) + return ctx->error_depth; + return WOLFSSL_FATAL_ERROR; + } + + void wolfSSL_X509_STORE_CTX_set_verify_cb(WOLFSSL_X509_STORE_CTX *ctx, + WOLFSSL_X509_STORE_CTX_verify_cb verify_cb) + { + WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_set_verify_cb"); + if(ctx == NULL) + return; + ctx->verify_cb = verify_cb; + } +#endif /* !NO_CERTS */ + + WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_buffer(void) + { + static WOLFSSL_BIO_METHOD meth; + + WOLFSSL_ENTER("BIO_f_buffer"); + meth.type = WOLFSSL_BIO_BUFFER; + + return &meth; + } + + #ifndef NO_WOLFSSL_STUB + long wolfSSL_BIO_set_write_buffer_size(WOLFSSL_BIO* bio, long size) + { + /* wolfSSL has internal buffer, compatibility only */ + WOLFSSL_ENTER("BIO_set_write_buffer_size"); + WOLFSSL_STUB("BIO_set_write_buffer_size"); + (void)bio; + return size; + } + #endif + + WOLFSSL_BIO_METHOD* wolfSSL_BIO_s_bio(void) + { + static WOLFSSL_BIO_METHOD bio_meth; + + WOLFSSL_ENTER("wolfSSL_BIO_f_bio"); + bio_meth.type = WOLFSSL_BIO_BIO; + + return &bio_meth; + } + + +#ifndef NO_FILESYSTEM + WOLFSSL_BIO_METHOD* wolfSSL_BIO_s_file(void) + { + static WOLFSSL_BIO_METHOD file_meth; + + WOLFSSL_ENTER("wolfSSL_BIO_f_file"); + file_meth.type = WOLFSSL_BIO_FILE; + + return &file_meth; + } +#endif + + + WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_ssl(void) + { + static WOLFSSL_BIO_METHOD meth; + + WOLFSSL_ENTER("BIO_f_ssl"); + meth.type = WOLFSSL_BIO_SSL; + + return &meth; + } + + + WOLFSSL_BIO_METHOD *wolfSSL_BIO_s_socket(void) + { + static WOLFSSL_BIO_METHOD meth; + + WOLFSSL_ENTER("BIO_s_socket"); + meth.type = WOLFSSL_BIO_SOCKET; + + return &meth; + } + + + WOLFSSL_BIO* wolfSSL_BIO_new_socket(int sfd, int closeF) + { + WOLFSSL_BIO* bio = wolfSSL_BIO_new(wolfSSL_BIO_s_socket()); + + WOLFSSL_ENTER("BIO_new_socket"); + if (bio) { + bio->type = WOLFSSL_BIO_SOCKET; + bio->close = (byte)closeF; + bio->fd = sfd; + } + return bio; + } + + + int wolfSSL_BIO_eof(WOLFSSL_BIO* b) + { + WOLFSSL_ENTER("BIO_eof"); + if (b->eof) + return 1; + + return 0; + } + + + long wolfSSL_BIO_set_ssl(WOLFSSL_BIO* b, WOLFSSL* ssl, int closeF) + { + WOLFSSL_ENTER("wolfSSL_BIO_set_ssl"); + + if (b != NULL) { + b->ssl = ssl; + b->close = (byte)closeF; + /* add to ssl for bio free if SSL_free called before/instead of free_all? */ + } + + return 0; + } + + + long wolfSSL_BIO_set_fd(WOLFSSL_BIO* b, int fd, int closeF) + { + WOLFSSL_ENTER("wolfSSL_BIO_set_fd"); + + if (b != NULL) { + b->fd = fd; + b->close = (byte)closeF; + } + + return WOLFSSL_SUCCESS; + } + + + WOLFSSL_BIO* wolfSSL_BIO_new(WOLFSSL_BIO_METHOD* method) + { + WOLFSSL_BIO* bio = (WOLFSSL_BIO*) XMALLOC(sizeof(WOLFSSL_BIO), 0, + DYNAMIC_TYPE_OPENSSL); + WOLFSSL_ENTER("wolfSSL_BIO_new"); + if (bio) { + XMEMSET(bio, 0, sizeof(WOLFSSL_BIO)); + bio->type = method->type; + bio->close = BIO_CLOSE; /* default to close things */ + if (method->type != WOLFSSL_BIO_FILE && + method->type != WOLFSSL_BIO_SOCKET) { + bio->mem_buf =(WOLFSSL_BUF_MEM*)XMALLOC(sizeof(WOLFSSL_BUF_MEM), + 0, DYNAMIC_TYPE_OPENSSL); + if (bio->mem_buf == NULL) { + WOLFSSL_MSG("Memory error"); + wolfSSL_BIO_free(bio); + return NULL; + } + bio->mem_buf->data = (char*)bio->mem; + } + } + return bio; + } + + + int wolfSSL_BIO_get_mem_data(WOLFSSL_BIO* bio, void* p) + { + WOLFSSL_ENTER("wolfSSL_BIO_get_mem_data"); + + if (bio == NULL || p == NULL) + return WOLFSSL_FATAL_ERROR; + + *(byte **)p = bio->mem; + + return bio->memLen; + } + + + WOLFSSL_BIO* wolfSSL_BIO_new_mem_buf(void* buf, int len) + { + WOLFSSL_BIO* bio = NULL; + + if (buf == NULL || len < 0) { + return bio; + } + + bio = wolfSSL_BIO_new(wolfSSL_BIO_s_mem()); + if (bio == NULL) { + return bio; + } + + bio->memLen = bio->wrSz = len; + bio->mem = (byte*)XMALLOC(len, 0, DYNAMIC_TYPE_OPENSSL); + if (bio->mem == NULL) { + wolfSSL_BIO_free(bio); + return NULL; + } + if (bio->mem_buf != NULL) { + bio->mem_buf->data = (char*)bio->mem; + bio->mem_buf->length = bio->memLen; + } + + XMEMCPY(bio->mem, buf, len); + + return bio; + } + + /* + * Note : If the flag BIO_NOCLOSE is set then freeing memory buffers is up + * to the application. + */ + int wolfSSL_BIO_free(WOLFSSL_BIO* bio) + { + /* unchain?, doesn't matter in goahead since from free all */ + WOLFSSL_ENTER("wolfSSL_BIO_free"); + if (bio) { + /* remove from pair by setting the paired bios pair to NULL */ + if (bio->pair != NULL) { + bio->pair->pair = NULL; + } + + if (bio->close) { + if (bio->ssl) + wolfSSL_free(bio->ssl); + #ifdef CloseSocket + if (bio->fd) + CloseSocket(bio->fd); + #endif + } + + #ifndef NO_FILESYSTEM + if (bio->type == WOLFSSL_BIO_FILE && bio->close == BIO_CLOSE) { + if (bio->file) { + XFCLOSE(bio->file); + } + } + #endif + + if (bio->close != BIO_NOCLOSE) { + if (bio->mem != NULL) { + if (bio->mem_buf != NULL) { + if (bio->mem_buf->data != (char*)bio->mem) { + XFREE(bio->mem, bio->heap, DYNAMIC_TYPE_OPENSSL); + bio->mem = NULL; + } + } + else { + XFREE(bio->mem, bio->heap, DYNAMIC_TYPE_OPENSSL); + bio->mem = NULL; + } + } + if (bio->mem_buf != NULL) { + wolfSSL_BUF_MEM_free(bio->mem_buf); + bio->mem_buf = NULL; + } + } + + XFREE(bio, 0, DYNAMIC_TYPE_OPENSSL); + } + return 0; + } + + + int wolfSSL_BIO_free_all(WOLFSSL_BIO* bio) + { + WOLFSSL_ENTER("BIO_free_all"); + while (bio) { + WOLFSSL_BIO* next = bio->next; + wolfSSL_BIO_free(bio); + bio = next; + } + return 0; + } + + + WOLFSSL_BIO* wolfSSL_BIO_push(WOLFSSL_BIO* top, WOLFSSL_BIO* append) + { + WOLFSSL_ENTER("BIO_push"); + top->next = append; + append->prev = top; + + return top; + } + + + int wolfSSL_BIO_flush(WOLFSSL_BIO* bio) + { + /* for wolfSSL no flushing needed */ + WOLFSSL_ENTER("BIO_flush"); + (void)bio; + return 1; + } +#endif /* OPENSSL_EXTRA */ + +#ifdef WOLFSSL_ENCRYPTED_KEYS + + void wolfSSL_CTX_set_default_passwd_cb_userdata(WOLFSSL_CTX* ctx, + void* userdata) + { + WOLFSSL_ENTER("SSL_CTX_set_default_passwd_cb_userdata"); + if (ctx) + ctx->passwd_userdata = userdata; + } + + + void wolfSSL_CTX_set_default_passwd_cb(WOLFSSL_CTX* ctx,pem_password_cb* cb) + { + WOLFSSL_ENTER("SSL_CTX_set_default_passwd_cb"); + if (ctx) + ctx->passwd_cb = cb; + } + + pem_password_cb* wolfSSL_CTX_get_default_passwd_cb(WOLFSSL_CTX *ctx) + { + if (ctx == NULL || ctx->passwd_cb == NULL) { + return NULL; + } + + return ctx->passwd_cb; + } + + + void* wolfSSL_CTX_get_default_passwd_cb_userdata(WOLFSSL_CTX *ctx) + { + if (ctx == NULL) { + return NULL; + } + + return ctx->passwd_userdata; + } + +#if !defined(NO_PWDBASED) && (defined(OPENSSL_EXTRA) || \ + defined(OPENSSL_EXTRA_X509_SMALL) || defined(HAVE_WEBSERVER)) + + int wolfSSL_EVP_BytesToKey(const WOLFSSL_EVP_CIPHER* type, + const WOLFSSL_EVP_MD* md, const byte* salt, + const byte* data, int sz, int count, byte* key, byte* iv) + { + int ret; + int hashType = WC_HASH_TYPE_NONE; + #ifdef WOLFSSL_SMALL_STACK + EncryptedInfo* info = NULL; + #else + EncryptedInfo info[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL, + DYNAMIC_TYPE_ENCRYPTEDINFO); + if (info == NULL) { + WOLFSSL_MSG("malloc failed"); + return WOLFSSL_FAILURE; + } + #endif + + XMEMSET(info, 0, sizeof(EncryptedInfo)); + + ret = wc_EncryptedInfoGet(info, type); + if (ret < 0) + goto end; + + if (data == NULL) { + ret = info->keySz; + goto end; + } + + ret = wolfSSL_EVP_get_hashinfo(md, &hashType, NULL); + if (ret == WOLFSSL_FAILURE) + goto end; + + ret = wc_PBKDF1_ex(key, info->keySz, iv, info->ivSz, data, sz, salt, + EVP_SALT_SIZE, count, hashType, NULL); + if (ret == 0) + ret = info->keySz; + + end: + #ifdef WOLFSSL_SMALL_STACK + XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO); + #endif + if (ret < 0) + return 0; /* failure - for compatibility */ + + return ret; + } + +#endif /* !NO_PWDBASED && (OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL || HAVE_WEBSERVER) */ +#endif /* WOLFSSL_ENCRYPTED_KEYS */ + + +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + int wolfSSL_num_locks(void) + { + return 0; + } + + void wolfSSL_set_locking_callback(void (*f)(int, int, const char*, int)) + { + WOLFSSL_ENTER("wolfSSL_set_locking_callback"); + + if (wc_SetMutexCb(f) != 0) { + WOLFSSL_MSG("Error when setting mutex call back"); + } + } + + + typedef unsigned long (idCb)(void); + static idCb* inner_idCb = NULL; + + unsigned long wolfSSL_thread_id(void) + { + if (inner_idCb != NULL) { + return inner_idCb(); + } + else { + return 0; + } + } + + + void wolfSSL_set_id_callback(unsigned long (*f)(void)) + { + inner_idCb = f; + } + + unsigned long wolfSSL_ERR_get_error(void) + { + WOLFSSL_ENTER("wolfSSL_ERR_get_error"); + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + { + unsigned long ret = wolfSSL_ERR_peek_error_line_data(NULL, NULL, + NULL, NULL); + wc_RemoveErrorNode(-1); + return ret; + } +#elif (defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE)) + { + int ret = wc_PullErrorNode(NULL, NULL, NULL); + + if (ret < 0) { + if (ret == BAD_STATE_E) return 0; /* no errors in queue */ + WOLFSSL_MSG("Error with pulling error node!"); + WOLFSSL_LEAVE("wolfSSL_ERR_get_error", ret); + ret = 0 - ret; /* return absolute value of error */ + + /* panic and try to clear out nodes */ + wc_ClearErrorNodes(); + } + + return (unsigned long)ret; + } +#else + return (unsigned long)(0 - NOT_COMPILED_IN); +#endif + } + +#endif /* OPENSSL_EXTRA || HAVE_WEBSERVER */ + + +#ifdef OPENSSL_EXTRA + +#if !defined(NO_WOLFSSL_SERVER) +size_t wolfSSL_get_server_random(const WOLFSSL *ssl, unsigned char *out, + size_t outSz) +{ + size_t size; + + /* return max size of buffer */ + if (outSz == 0) { + return RAN_LEN; + } + + if (ssl == NULL || out == NULL) { + return 0; + } + + if (ssl->options.saveArrays == 0 || ssl->arrays == NULL) { + WOLFSSL_MSG("Arrays struct not saved after handshake"); + return 0; + } + + if (outSz > RAN_LEN) { + size = RAN_LEN; + } + else { + size = outSz; + } + + XMEMCPY(out, ssl->arrays->serverRandom, size); + return size; +} +#endif /* !defined(NO_WOLFSSL_SERVER) */ + + +#if !defined(NO_WOLFSSL_CLIENT) +/* Return the amount of random bytes copied over or error case. + * ssl : ssl struct after handshake + * out : buffer to hold random bytes + * outSz : either 0 (return max buffer sz) or size of out buffer + * + * NOTE: wolfSSL_KeepArrays(ssl) must be called to retain handshake information. + */ +size_t wolfSSL_get_client_random(const WOLFSSL* ssl, unsigned char* out, + size_t outSz) +{ + size_t size; + + /* return max size of buffer */ + if (outSz == 0) { + return RAN_LEN; + } + + if (ssl == NULL || out == NULL) { + return 0; + } + + if (ssl->options.saveArrays == 0 || ssl->arrays == NULL) { + WOLFSSL_MSG("Arrays struct not saved after handshake"); + return 0; + } + + if (outSz > RAN_LEN) { + size = RAN_LEN; + } + else { + size = outSz; + } + + XMEMCPY(out, ssl->arrays->clientRandom, size); + return size; +} +#endif /* !NO_WOLFSSL_CLIENT */ + + + unsigned long wolfSSLeay(void) + { + return SSLEAY_VERSION_NUMBER; + } + + + const char* wolfSSLeay_version(int type) + { + static const char* version = "SSLeay wolfSSL compatibility"; + (void)type; + return version; + } + + +#ifndef NO_MD5 + int wolfSSL_MD5_Init(WOLFSSL_MD5_CTX* md5) + { + int ret; + typedef char md5_test[sizeof(MD5_CTX) >= sizeof(wc_Md5) ? 1 : -1]; + (void)sizeof(md5_test); + + WOLFSSL_ENTER("MD5_Init"); + ret = wc_InitMd5((wc_Md5*)md5); + + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + + return 0; + } + + + int wolfSSL_MD5_Update(WOLFSSL_MD5_CTX* md5, const void* input, + unsigned long sz) + { + int ret; + + WOLFSSL_ENTER("wolfSSL_MD5_Update"); + ret = wc_Md5Update((wc_Md5*)md5, (const byte*)input, (word32)sz); + + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + + return 0; + } + + + int wolfSSL_MD5_Final(byte* input, WOLFSSL_MD5_CTX* md5) + { + int ret; + + WOLFSSL_ENTER("MD5_Final"); + ret = wc_Md5Final((wc_Md5*)md5, input); + + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + + return 0; + } +#endif /* !NO_MD5 */ + + +#ifndef NO_SHA + int wolfSSL_SHA_Init(WOLFSSL_SHA_CTX* sha) + { + int ret; + + typedef char sha_test[sizeof(SHA_CTX) >= sizeof(wc_Sha) ? 1 : -1]; + (void)sizeof(sha_test); + + WOLFSSL_ENTER("SHA_Init"); + ret = wc_InitSha((wc_Sha*)sha); + + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + + return 0; + } + + + int wolfSSL_SHA_Update(WOLFSSL_SHA_CTX* sha, const void* input, + unsigned long sz) + { + int ret; + + WOLFSSL_ENTER("SHA_Update"); + ret = wc_ShaUpdate((wc_Sha*)sha, (const byte*)input, (word32)sz); + + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + + return 0; + } + + + int wolfSSL_SHA_Final(byte* input, WOLFSSL_SHA_CTX* sha) + { + int ret; + + WOLFSSL_ENTER("SHA_Final"); + ret = wc_ShaFinal((wc_Sha*)sha, input); + + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + + return 0; + } + + + int wolfSSL_SHA1_Init(WOLFSSL_SHA_CTX* sha) + { + WOLFSSL_ENTER("SHA1_Init"); + return SHA_Init(sha); + } + + + int wolfSSL_SHA1_Update(WOLFSSL_SHA_CTX* sha, const void* input, + unsigned long sz) + { + WOLFSSL_ENTER("SHA1_Update"); + return SHA_Update(sha, input, sz); + } + + + int wolfSSL_SHA1_Final(byte* input, WOLFSSL_SHA_CTX* sha) + { + WOLFSSL_ENTER("SHA1_Final"); + return SHA_Final(input, sha); + } +#endif /* !NO_SHA */ + +#ifdef WOLFSSL_SHA224 + + int wolfSSL_SHA224_Init(WOLFSSL_SHA224_CTX* sha) + { + int ret; + + typedef char sha_test[sizeof(SHA224_CTX) >= sizeof(wc_Sha224) ? 1 : -1]; + (void)sizeof(sha_test); + + WOLFSSL_ENTER("SHA224_Init"); + ret = wc_InitSha224((wc_Sha224*)sha); + + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + + return 0; + } + + + int wolfSSL_SHA224_Update(WOLFSSL_SHA224_CTX* sha, const void* input, + unsigned long sz) + { + int ret; + + WOLFSSL_ENTER("SHA224_Update"); + ret = wc_Sha224Update((wc_Sha224*)sha, (const byte*)input, (word32)sz); + + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + + return 0; + } + + + int wolfSSL_SHA224_Final(byte* input, WOLFSSL_SHA224_CTX* sha) + { + int ret; + + WOLFSSL_ENTER("SHA224_Final"); + ret = wc_Sha224Final((wc_Sha224*)sha, input); + + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + + return 0; + } + +#endif /* WOLFSSL_SHA224 */ + + + int wolfSSL_SHA256_Init(WOLFSSL_SHA256_CTX* sha256) + { + int ret; + + typedef char sha_test[sizeof(SHA256_CTX) >= sizeof(wc_Sha256) ? 1 : -1]; + (void)sizeof(sha_test); + + WOLFSSL_ENTER("SHA256_Init"); + ret = wc_InitSha256((wc_Sha256*)sha256); + + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + + return 0; + } + + + int wolfSSL_SHA256_Update(WOLFSSL_SHA256_CTX* sha, const void* input, + unsigned long sz) + { + int ret; + + WOLFSSL_ENTER("SHA256_Update"); + ret = wc_Sha256Update((wc_Sha256*)sha, (const byte*)input, (word32)sz); + + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + + return 0; + } + + + int wolfSSL_SHA256_Final(byte* input, WOLFSSL_SHA256_CTX* sha) + { + int ret; + + WOLFSSL_ENTER("SHA256_Final"); + ret = wc_Sha256Final((wc_Sha256*)sha, input); + + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + + return 0; + } + + +#ifdef WOLFSSL_SHA384 + + int wolfSSL_SHA384_Init(WOLFSSL_SHA384_CTX* sha) + { + int ret; + + typedef char sha_test[sizeof(SHA384_CTX) >= sizeof(wc_Sha384) ? 1 : -1]; + (void)sizeof(sha_test); + + WOLFSSL_ENTER("SHA384_Init"); + ret = wc_InitSha384((wc_Sha384*)sha); + + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + + return 0; + } + + + int wolfSSL_SHA384_Update(WOLFSSL_SHA384_CTX* sha, const void* input, + unsigned long sz) + { + int ret; + + WOLFSSL_ENTER("SHA384_Update"); + ret = wc_Sha384Update((wc_Sha384*)sha, (const byte*)input, (word32)sz); + + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + + return 0; + } + + + int wolfSSL_SHA384_Final(byte* input, WOLFSSL_SHA384_CTX* sha) + { + int ret; + + WOLFSSL_ENTER("SHA384_Final"); + ret = wc_Sha384Final((wc_Sha384*)sha, input); + + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + + return 0; + } + +#endif /* WOLFSSL_SHA384 */ + + +#ifdef WOLFSSL_SHA512 + + int wolfSSL_SHA512_Init(WOLFSSL_SHA512_CTX* sha) + { + int ret; + + typedef char sha_test[sizeof(SHA512_CTX) >= sizeof(wc_Sha512) ? 1 : -1]; + (void)sizeof(sha_test); + + WOLFSSL_ENTER("SHA512_Init"); + ret = wc_InitSha512((wc_Sha512*)sha); + + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + + return 0; + } + + + int wolfSSL_SHA512_Update(WOLFSSL_SHA512_CTX* sha, const void* input, + unsigned long sz) + { + int ret; + + WOLFSSL_ENTER("SHA512_Update"); + ret = wc_Sha512Update((wc_Sha512*)sha, (const byte*)input, (word32)sz); + + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + + return 0; + } + + + int wolfSSL_SHA512_Final(byte* input, WOLFSSL_SHA512_CTX* sha) + { + int ret; + + WOLFSSL_ENTER("SHA512_Final"); + ret = wc_Sha512Final((wc_Sha512*)sha, input); + + /* return 1 on success, 0 otherwise */ + if (ret == 0) + return 1; + + return 0; + } + +#endif /* WOLFSSL_SHA512 */ + + static const struct s_ent { + const unsigned char macType; + const char *name; + } md_tbl[] = { + #ifndef NO_MD4 + {WC_HASH_TYPE_MD4, "MD4"}, + #endif /* NO_MD4 */ + + #ifndef NO_MD5 + {WC_HASH_TYPE_MD5, "MD5"}, + #endif /* NO_MD5 */ + + #ifndef NO_SHA + {WC_HASH_TYPE_SHA, "SHA"}, + #endif /* NO_SHA */ + + #ifdef WOLFSSL_SHA224 + {WC_HASH_TYPE_SHA224, "SHA224"}, + #endif /* WOLFSSL_SHA224 */ + #ifndef NO_SHA256 + {WC_HASH_TYPE_SHA256, "SHA256"}, + #endif + + #ifdef WOLFSSL_SHA384 + {WC_HASH_TYPE_SHA384, "SHA384"}, + #endif /* WOLFSSL_SHA384 */ + #ifdef WOLFSSL_SHA512 + {WC_HASH_TYPE_SHA512, "SHA512"}, + #endif /* WOLFSSL_SHA512 */ + {0, NULL} + }; + +const WOLFSSL_EVP_MD *wolfSSL_EVP_get_digestbyname(const char *name) +{ + static const struct alias { + const char *name; + const char *alias; + } alias_tbl[] = + { + {"MD4", "ssl3-md4"}, + {"MD5", "ssl3-md5"}, + {"SHA", "ssl3-sha1"}, + {"SHA", "SHA1"}, + { NULL, NULL} + }; + + const struct alias *al; + const struct s_ent *ent; + + for (al = alias_tbl; al->name != NULL; al++) + if(XSTRNCMP(name, al->alias, XSTRLEN(al->alias)+1) == 0) { + name = al->name; + break; + } + + for (ent = md_tbl; ent->name != NULL; ent++) + if(XSTRNCMP(name, ent->name, XSTRLEN(ent->name)+1) == 0) { + return (EVP_MD *)ent->name; + } + return NULL; +} + +static WOLFSSL_EVP_MD *wolfSSL_EVP_get_md(const unsigned char type) +{ + const struct s_ent *ent ; + WOLFSSL_ENTER("EVP_get_md"); + for( ent = md_tbl; ent->name != NULL; ent++){ + if(type == ent->macType) { + return (WOLFSSL_EVP_MD *)ent->name; + } + } + return (WOLFSSL_EVP_MD *)""; +} + +int wolfSSL_EVP_MD_type(const WOLFSSL_EVP_MD *md) +{ + const struct s_ent *ent ; + WOLFSSL_ENTER("EVP_MD_type"); + for( ent = md_tbl; ent->name != NULL; ent++){ + if(XSTRNCMP((const char *)md, ent->name, XSTRLEN(ent->name)+1) == 0) { + return ent->macType; + } + } + return 0; +} + + +#ifndef NO_MD4 + + /* return a pointer to MD4 EVP type */ + const WOLFSSL_EVP_MD* wolfSSL_EVP_md4(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_md4"); + return EVP_get_digestbyname("MD4"); + } + +#endif /* !NO_MD4 */ + + +#ifndef NO_MD5 + + const WOLFSSL_EVP_MD* wolfSSL_EVP_md5(void) + { + WOLFSSL_ENTER("EVP_md5"); + return EVP_get_digestbyname("MD5"); + } + +#endif /* !NO_MD5 */ + + +#ifndef NO_SHA + const WOLFSSL_EVP_MD* wolfSSL_EVP_sha1(void) + { + WOLFSSL_ENTER("EVP_sha1"); + return EVP_get_digestbyname("SHA"); + } +#endif /* NO_SHA */ + +#ifdef WOLFSSL_SHA224 + + const WOLFSSL_EVP_MD* wolfSSL_EVP_sha224(void) + { + WOLFSSL_ENTER("EVP_sha224"); + return EVP_get_digestbyname("SHA224"); + } + +#endif /* WOLFSSL_SHA224 */ + + + const WOLFSSL_EVP_MD* wolfSSL_EVP_sha256(void) + { + WOLFSSL_ENTER("EVP_sha256"); + return EVP_get_digestbyname("SHA256"); + } + +#ifdef WOLFSSL_SHA384 + + const WOLFSSL_EVP_MD* wolfSSL_EVP_sha384(void) + { + WOLFSSL_ENTER("EVP_sha384"); + return EVP_get_digestbyname("SHA384"); + } + +#endif /* WOLFSSL_SHA384 */ + +#ifdef WOLFSSL_SHA512 + + const WOLFSSL_EVP_MD* wolfSSL_EVP_sha512(void) + { + WOLFSSL_ENTER("EVP_sha512"); + return EVP_get_digestbyname("SHA512"); + } + +#endif /* WOLFSSL_SHA512 */ + + + WOLFSSL_EVP_MD_CTX *wolfSSL_EVP_MD_CTX_new(void) + { + WOLFSSL_EVP_MD_CTX* ctx; + WOLFSSL_ENTER("EVP_MD_CTX_new"); + ctx = (WOLFSSL_EVP_MD_CTX*)XMALLOC(sizeof *ctx, NULL, + DYNAMIC_TYPE_OPENSSL); + if (ctx){ + wolfSSL_EVP_MD_CTX_init(ctx); + } + return ctx; + } + + WOLFSSL_API void wolfSSL_EVP_MD_CTX_free(WOLFSSL_EVP_MD_CTX *ctx) + { + if (ctx) { + WOLFSSL_ENTER("EVP_MD_CTX_free"); + wolfSSL_EVP_MD_CTX_cleanup(ctx); + XFREE(ctx, NULL, DYNAMIC_TYPE_OPENSSL); + } + } + + + /* returns the type of message digest used by the ctx */ + int wolfSSL_EVP_MD_CTX_type(const WOLFSSL_EVP_MD_CTX *ctx) { + WOLFSSL_ENTER("EVP_MD_CTX_type"); + return ctx->macType; + } + + + /* returns WOLFSSL_SUCCESS on success */ + int wolfSSL_EVP_MD_CTX_copy(WOLFSSL_EVP_MD_CTX *out, const WOLFSSL_EVP_MD_CTX *in) + { + return wolfSSL_EVP_MD_CTX_copy_ex(out, in); + } + + /* returns digest size */ + int wolfSSL_EVP_MD_CTX_size(const WOLFSSL_EVP_MD_CTX *ctx) { + return(wolfSSL_EVP_MD_size(wolfSSL_EVP_MD_CTX_md(ctx))); + } + /* returns block size */ + int wolfSSL_EVP_MD_CTX_block_size(const WOLFSSL_EVP_MD_CTX *ctx) { + return(wolfSSL_EVP_MD_block_size(wolfSSL_EVP_MD_CTX_md(ctx))); + } + + /* Deep copy of EVP_MD hasher + * return WOLFSSL_SUCCESS on success */ + static int wolfSSL_EVP_MD_Copy_Hasher(WOLFSSL_EVP_MD_CTX* des, + const WOLFSSL_EVP_MD_CTX* src) + { + if (src->macType == (NID_hmac & 0xFF)) { + wolfSSL_HmacCopy(&des->hash.hmac, (Hmac*)&src->hash.hmac); + } + else { + switch (src->macType) { + #ifndef NO_MD5 + case WC_HASH_TYPE_MD5: + wc_Md5Copy((wc_Md5*)&src->hash.digest, + (wc_Md5*)&des->hash.digest); + break; + #endif /* !NO_MD5 */ + + #ifndef NO_SHA + case WC_HASH_TYPE_SHA: + wc_ShaCopy((wc_Sha*)&src->hash.digest, + (wc_Sha*)&des->hash.digest); + break; + #endif /* !NO_SHA */ + + #ifdef WOLFSSL_SHA224 + case WC_HASH_TYPE_SHA224: + wc_Sha224Copy((wc_Sha224*)&src->hash.digest, + (wc_Sha224*)&des->hash.digest); + break; + #endif /* WOLFSSL_SHA224 */ + + #ifndef NO_SHA256 + case WC_HASH_TYPE_SHA256: + wc_Sha256Copy((wc_Sha256*)&src->hash.digest, + (wc_Sha256*)&des->hash.digest); + break; + #endif /* !NO_SHA256 */ + + #ifdef WOLFSSL_SHA384 + case WC_HASH_TYPE_SHA384: + wc_Sha384Copy((wc_Sha384*)&src->hash.digest, + (wc_Sha384*)&des->hash.digest); + break; + #endif /* WOLFSSL_SHA384 */ + #ifdef WOLFSSL_SHA512 + case WC_HASH_TYPE_SHA512: + wc_Sha512Copy((wc_Sha512*)&src->hash.digest, + (wc_Sha512*)&des->hash.digest); + break; + #endif /* WOLFSSL_SHA512 */ + + default: + return WOLFSSL_FAILURE; + } + } + return WOLFSSL_SUCCESS; + } + + + /* copies structure in to the structure out + * + * returns WOLFSSL_SUCCESS on success */ + int wolfSSL_EVP_MD_CTX_copy_ex(WOLFSSL_EVP_MD_CTX *out, const WOLFSSL_EVP_MD_CTX *in) + { + if ((out == NULL) || (in == NULL)) return WOLFSSL_FAILURE; + WOLFSSL_ENTER("EVP_CIPHER_MD_CTX_copy_ex"); + XMEMCPY(out, in, sizeof(WOLFSSL_EVP_MD_CTX)); + if (in->pctx != NULL) { + out->pctx = wolfSSL_EVP_PKEY_CTX_new(in->pctx->pkey, NULL); + if (out->pctx == NULL) + return WOLFSSL_FAILURE; + } + return wolfSSL_EVP_MD_Copy_Hasher(out, (WOLFSSL_EVP_MD_CTX*)in); + } + + void wolfSSL_EVP_MD_CTX_init(WOLFSSL_EVP_MD_CTX* ctx) + { + WOLFSSL_ENTER("EVP_CIPHER_MD_CTX_init"); + XMEMSET(ctx, 0, sizeof(WOLFSSL_EVP_MD_CTX)); + } + + const WOLFSSL_EVP_MD *wolfSSL_EVP_MD_CTX_md(const WOLFSSL_EVP_MD_CTX *ctx) + { + if (ctx == NULL) + return NULL; + WOLFSSL_ENTER("EVP_MD_CTX_md"); + return (const WOLFSSL_EVP_MD *)wolfSSL_EVP_get_md(ctx->macType); + } + + #ifndef NO_AES + + #ifdef HAVE_AES_CBC + #ifdef WOLFSSL_AES_128 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_cbc(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_128_cbc"); + if (EVP_AES_128_CBC == NULL) + wolfSSL_EVP_init(); + return EVP_AES_128_CBC; + } + #endif /* WOLFSSL_AES_128 */ + + + #ifdef WOLFSSL_AES_192 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_cbc(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_192_cbc"); + if (EVP_AES_192_CBC == NULL) + wolfSSL_EVP_init(); + return EVP_AES_192_CBC; + } + #endif /* WOLFSSL_AES_192 */ + + + #ifdef WOLFSSL_AES_256 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_cbc(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_256_cbc"); + if (EVP_AES_256_CBC == NULL) + wolfSSL_EVP_init(); + return EVP_AES_256_CBC; + } + #endif /* WOLFSSL_AES_256 */ + #endif /* HAVE_AES_CBC */ + + + #ifdef WOLFSSL_AES_128 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_ctr(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_128_ctr"); + if (EVP_AES_128_CTR == NULL) + wolfSSL_EVP_init(); + return EVP_AES_128_CTR; + } + #endif /* WOLFSSL_AES_2128 */ + + + #ifdef WOLFSSL_AES_192 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_ctr(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_192_ctr"); + if (EVP_AES_192_CTR == NULL) + wolfSSL_EVP_init(); + return EVP_AES_192_CTR; + } + #endif /* WOLFSSL_AES_192 */ + + + #ifdef WOLFSSL_AES_256 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_ctr(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_256_ctr"); + if (EVP_AES_256_CTR == NULL) + wolfSSL_EVP_init(); + return EVP_AES_256_CTR; + } + #endif /* WOLFSSL_AES_256 */ + + #ifdef WOLFSSL_AES_128 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_128_ecb(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_128_ecb"); + if (EVP_AES_128_ECB == NULL) + wolfSSL_EVP_init(); + return EVP_AES_128_ECB; + } + #endif /* WOLFSSL_AES_128 */ + + + #ifdef WOLFSSL_AES_192 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_192_ecb(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_192_ecb"); + if (EVP_AES_192_ECB == NULL) + wolfSSL_EVP_init(); + return EVP_AES_192_ECB; + } + #endif /* WOLFSSL_AES_192*/ + + + #ifdef WOLFSSL_AES_256 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_aes_256_ecb(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_aes_256_ecb"); + if (EVP_AES_256_ECB == NULL) + wolfSSL_EVP_init(); + return EVP_AES_256_ECB; + } + #endif /* WOLFSSL_AES_256 */ + #endif /* NO_AES */ + +#ifndef NO_DES3 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_des_cbc(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_des_cbc"); + if (EVP_DES_CBC == NULL) + wolfSSL_EVP_init(); + return EVP_DES_CBC; + } +#ifdef WOLFSSL_DES_ECB + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_des_ecb(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_des_ecb"); + if (EVP_DES_ECB == NULL) + wolfSSL_EVP_init(); + return EVP_DES_ECB; + } +#endif + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_des_ede3_cbc(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_des_ede3_cbc"); + if (EVP_DES_EDE3_CBC == NULL) + wolfSSL_EVP_init(); + return EVP_DES_EDE3_CBC; + } +#ifdef WOLFSSL_DES_ECB + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_des_ede3_ecb(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_des_ede3_ecb"); + if (EVP_DES_EDE3_ECB == NULL) + wolfSSL_EVP_init(); + return EVP_DES_EDE3_ECB; + } +#endif +#endif /* NO_DES3 */ + +#ifndef NO_RC4 + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_rc4(void) + { + static const char* type = "ARC4"; + WOLFSSL_ENTER("wolfSSL_EVP_rc4"); + return type; + } +#endif + +#ifdef HAVE_IDEA + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_idea_cbc(void) + { + WOLFSSL_ENTER("wolfSSL_EVP_idea_cbc"); + if (EVP_IDEA_CBC == NULL) + wolfSSL_EVP_init(); + return EVP_IDEA_CBC; + } +#endif + const WOLFSSL_EVP_CIPHER* wolfSSL_EVP_enc_null(void) + { + static const char* type = "NULL"; + WOLFSSL_ENTER("wolfSSL_EVP_enc_null"); + return type; + } + + + int wolfSSL_EVP_MD_CTX_cleanup(WOLFSSL_EVP_MD_CTX* ctx) + { + WOLFSSL_ENTER("EVP_MD_CTX_cleanup"); + if (ctx->pctx != NULL) + wolfSSL_EVP_PKEY_CTX_free(ctx->pctx); + + if (ctx->macType == (NID_hmac & 0xFF)) { + wc_HmacFree(&ctx->hash.hmac); + } + else { + switch (ctx->macType) { + #ifndef NO_MD5 + case WC_HASH_TYPE_MD5: + wc_Md5Free((wc_Md5*)&ctx->hash.digest); + break; + #endif /* !NO_MD5 */ + + #ifndef NO_SHA + case WC_HASH_TYPE_SHA: + wc_ShaFree((wc_Sha*)&ctx->hash.digest); + break; + #endif /* !NO_SHA */ + + #ifdef WOLFSSL_SHA224 + case WC_HASH_TYPE_SHA224: + wc_Sha224Free((wc_Sha224*)&ctx->hash.digest); + break; + #endif /* WOLFSSL_SHA224 */ + + #ifndef NO_SHA256 + case WC_HASH_TYPE_SHA256: + wc_Sha256Free((wc_Sha256*)&ctx->hash.digest); + break; + #endif /* !NO_SHA256 */ + + #ifdef WOLFSSL_SHA384 + case WC_HASH_TYPE_SHA384: + wc_Sha384Free((wc_Sha384*)&ctx->hash.digest); + break; + #endif /* WOLFSSL_SHA384 */ + #ifdef WOLFSSL_SHA512 + case WC_HASH_TYPE_SHA512: + wc_Sha512Free((wc_Sha512*)&ctx->hash.digest); + break; + #endif /* WOLFSSL_SHA512 */ + + default: + return WOLFSSL_FAILURE; + } + } + ForceZero(ctx, sizeof(*ctx)); + ctx->macType = 0xFF; + return 1; + } + + + + void wolfSSL_EVP_CIPHER_CTX_init(WOLFSSL_EVP_CIPHER_CTX* ctx) + { + WOLFSSL_ENTER("EVP_CIPHER_CTX_init"); + if (ctx) { + ctx->cipherType = WOLFSSL_EVP_CIPH_TYPE_INIT; /* not yet initialized */ + ctx->keyLen = 0; + ctx->enc = 1; /* start in encrypt mode */ + } + } + + + /* WOLFSSL_SUCCESS on ok */ + int wolfSSL_EVP_CIPHER_CTX_cleanup(WOLFSSL_EVP_CIPHER_CTX* ctx) + { + WOLFSSL_ENTER("EVP_CIPHER_CTX_cleanup"); + if (ctx) { + ctx->cipherType = WOLFSSL_EVP_CIPH_TYPE_INIT; /* not yet initialized */ + ctx->keyLen = 0; + } + + return WOLFSSL_SUCCESS; + } + +#ifndef NO_AES + static int AesSetKey_ex(Aes* aes, const byte* key, word32 len, + const byte* iv, int dir) + { + int ret; + /* wc_AesSetKey clear aes.reg if iv == NULL. + Keep IV for openSSL compatibility */ + if(iv == NULL) + XMEMCPY((byte *)aes->tmp, (byte *)aes->reg, AES_BLOCK_SIZE); + ret = wc_AesSetKey(aes, key, len, iv, dir); + if(iv == NULL) + XMEMCPY((byte *)aes->reg, (byte *)aes->tmp, AES_BLOCK_SIZE); + return ret; + } +#endif + + /* return WOLFSSL_SUCCESS on ok, 0 on failure to match API compatibility */ + int wolfSSL_EVP_CipherInit(WOLFSSL_EVP_CIPHER_CTX* ctx, + const WOLFSSL_EVP_CIPHER* type, const byte* key, + const byte* iv, int enc) + { + int ret = 0; + (void)key; + (void)iv; + (void)enc; + + WOLFSSL_ENTER("wolfSSL_EVP_CipherInit"); + if (ctx == NULL) { + WOLFSSL_MSG("no ctx"); + return 0; /* failure */ + } + + if (type == NULL && ctx->cipherType == WOLFSSL_EVP_CIPH_TYPE_INIT) { + WOLFSSL_MSG("no type set"); + return 0; /* failure */ + } + if (ctx->cipherType == WOLFSSL_EVP_CIPH_TYPE_INIT){ + /* only first EVP_CipherInit invoke. ctx->cipherType is set below */ + XMEMSET(&ctx->cipher, 0, sizeof(ctx->cipher)); + ctx->bufUsed = 0; + ctx->lastUsed = 0; + ctx->flags = 0; + } + +#ifndef NO_AES + #ifdef HAVE_AES_CBC + #ifdef WOLFSSL_AES_128 + if (ctx->cipherType == AES_128_CBC_TYPE || + (type && XSTRNCMP(type, EVP_AES_128_CBC, EVP_AES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_128_CBC"); + ctx->cipherType = AES_128_CBC_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_CBC_MODE; + ctx->keyLen = 16; + ctx->block_size = AES_BLOCK_SIZE; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv, + ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION); + if (ret != 0) + return ret; + } + if (iv && key == NULL) { + ret = wc_AesSetIV(&ctx->cipher.aes, iv); + if (ret != 0) + return ret; + } + } + #endif /* WOLFSSL_AES_128 */ + #ifdef WOLFSSL_AES_192 + if (ctx->cipherType == AES_192_CBC_TYPE || + (type && XSTRNCMP(type, EVP_AES_192_CBC, EVP_AES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_192_CBC"); + ctx->cipherType = AES_192_CBC_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_CBC_MODE; + ctx->keyLen = 24; + ctx->block_size = AES_BLOCK_SIZE; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv, + ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION); + if (ret != 0) + return ret; + } + if (iv && key == NULL) { + ret = wc_AesSetIV(&ctx->cipher.aes, iv); + if (ret != 0) + return ret; + } + } + #endif /* WOLFSSL_AES_192 */ + #ifdef WOLFSSL_AES_256 + if (ctx->cipherType == AES_256_CBC_TYPE || + (type && XSTRNCMP(type, EVP_AES_256_CBC, EVP_AES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_256_CBC"); + ctx->cipherType = AES_256_CBC_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_CBC_MODE; + ctx->keyLen = 32; + ctx->block_size = AES_BLOCK_SIZE; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv, + ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION); + if (ret != 0){ + WOLFSSL_MSG("AesSetKey() failed"); + return ret; + } + } + if (iv && key == NULL) { + ret = wc_AesSetIV(&ctx->cipher.aes, iv); + if (ret != 0){ + WOLFSSL_MSG("wc_AesSetIV() failed"); + return ret; + } + } + } + #endif /* WOLFSSL_AES_256 */ + #endif /* HAVE_AES_CBC */ +#ifdef WOLFSSL_AES_COUNTER + #ifdef WOLFSSL_AES_128 + if (ctx->cipherType == AES_128_CTR_TYPE || + (type && XSTRNCMP(type, EVP_AES_128_CTR, EVP_AES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_128_CTR"); + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->cipherType = AES_128_CTR_TYPE; + ctx->flags |= WOLFSSL_EVP_CIPH_CTR_MODE; + ctx->keyLen = 16; + ctx->block_size = AES_BLOCK_SIZE; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv, + AES_ENCRYPTION); + if (ret != 0) + return ret; + } + if (iv && key == NULL) { + ret = wc_AesSetIV(&ctx->cipher.aes, iv); + if (ret != 0) + return ret; + } + } + #endif /* WOLFSSL_AES_128 */ + #ifdef WOLFSSL_AES_192 + if (ctx->cipherType == AES_192_CTR_TYPE || + (type && XSTRNCMP(type, EVP_AES_192_CTR, EVP_AES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_192_CTR"); + ctx->cipherType = AES_192_CTR_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_CTR_MODE; + ctx->keyLen = 24; + ctx->block_size = AES_BLOCK_SIZE; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv, + AES_ENCRYPTION); + if (ret != 0) + return ret; + } + if (iv && key == NULL) { + ret = wc_AesSetIV(&ctx->cipher.aes, iv); + if (ret != 0) + return ret; + } + } + #endif /* WOLFSSL_AES_192 */ + #ifdef WOLFSSL_AES_256 + if (ctx->cipherType == AES_256_CTR_TYPE || + (type && XSTRNCMP(type, EVP_AES_256_CTR, EVP_AES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_256_CTR"); + ctx->cipherType = AES_256_CTR_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_CTR_MODE; + ctx->keyLen = 32; + ctx->block_size = AES_BLOCK_SIZE; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, iv, + AES_ENCRYPTION); + if (ret != 0) + return ret; + } + if (iv && key == NULL) { + ret = wc_AesSetIV(&ctx->cipher.aes, iv); + if (ret != 0) + return ret; + } + } + #endif /* WOLFSSL_AES_256 */ +#endif /* WOLFSSL_AES_COUNTER */ + #ifdef WOLFSSL_AES_128 + if (ctx->cipherType == AES_128_ECB_TYPE || + (type && XSTRNCMP(type, EVP_AES_128_ECB, EVP_AES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_128_ECB"); + ctx->cipherType = AES_128_ECB_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_ECB_MODE; + ctx->keyLen = 16; + ctx->block_size = AES_BLOCK_SIZE; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, NULL, + ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION); + } + if (ret != 0) + return ret; + } + #endif /* WOLFSSL_AES_128 */ + #ifdef WOLFSSL_AES_192 + if (ctx->cipherType == AES_192_ECB_TYPE || + (type && XSTRNCMP(type, EVP_AES_192_ECB, EVP_AES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_192_ECB"); + ctx->cipherType = AES_192_ECB_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_ECB_MODE; + ctx->keyLen = 24; + ctx->block_size = AES_BLOCK_SIZE; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, NULL, + ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION); + } + if (ret != 0) + return ret; + } + #endif /* WOLFSSL_AES_192 */ + #ifdef WOLFSSL_AES_256 + if (ctx->cipherType == AES_256_ECB_TYPE || + (type && XSTRNCMP(type, EVP_AES_256_ECB, EVP_AES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_AES_256_ECB"); + ctx->cipherType = AES_256_ECB_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_ECB_MODE; + ctx->keyLen = 32; + ctx->block_size = AES_BLOCK_SIZE; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = AesSetKey_ex(&ctx->cipher.aes, key, ctx->keyLen, NULL, + ctx->enc ? AES_ENCRYPTION : AES_DECRYPTION); + } + if (ret != 0) + return ret; + } + #endif /* WOLFSSL_AES_256 */ +#endif /* NO_AES */ + +#ifndef NO_DES3 + if (ctx->cipherType == DES_CBC_TYPE || + (type && XSTRNCMP(type, EVP_DES_CBC, EVP_DES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_DES_CBC"); + ctx->cipherType = DES_CBC_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_CBC_MODE; + ctx->keyLen = 8; + ctx->block_size = DES_BLOCK_SIZE; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = wc_Des_SetKey(&ctx->cipher.des, key, iv, + ctx->enc ? DES_ENCRYPTION : DES_DECRYPTION); + if (ret != 0) + return ret; + } + + if (iv && key == NULL) + wc_Des_SetIV(&ctx->cipher.des, iv); + } +#ifdef WOLFSSL_DES_ECB + else if (ctx->cipherType == DES_ECB_TYPE || + (type && XSTRNCMP(type, EVP_DES_ECB, EVP_DES_SIZE) == 0)) { + WOLFSSL_MSG("EVP_DES_ECB"); + ctx->cipherType = DES_ECB_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_ECB_MODE; + ctx->keyLen = 8; + ctx->block_size = DES_BLOCK_SIZE; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + WOLFSSL_MSG("Des_SetKey"); + ret = wc_Des_SetKey(&ctx->cipher.des, key, NULL, + ctx->enc ? DES_ENCRYPTION : DES_DECRYPTION); + if (ret != 0) + return ret; + } + } +#endif + else if (ctx->cipherType == DES_EDE3_CBC_TYPE || + (type && + XSTRNCMP(type, EVP_DES_EDE3_CBC, EVP_DES_EDE3_SIZE) == 0)) { + WOLFSSL_MSG("EVP_DES_EDE3_CBC"); + ctx->cipherType = DES_EDE3_CBC_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_CBC_MODE; + ctx->keyLen = 24; + ctx->block_size = DES_BLOCK_SIZE; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = wc_Des3_SetKey(&ctx->cipher.des3, key, iv, + ctx->enc ? DES_ENCRYPTION : DES_DECRYPTION); + if (ret != 0) + return ret; + } + + if (iv && key == NULL) { + ret = wc_Des3_SetIV(&ctx->cipher.des3, iv); + if (ret != 0) + return ret; + } + } + else if (ctx->cipherType == DES_EDE3_ECB_TYPE || + (type && + XSTRNCMP(type, EVP_DES_EDE3_ECB, EVP_DES_EDE3_SIZE) == 0)) { + WOLFSSL_MSG("EVP_DES_EDE3_ECB"); + ctx->cipherType = DES_EDE3_ECB_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_ECB_MODE; + ctx->keyLen = 24; + ctx->block_size = DES_BLOCK_SIZE; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = wc_Des3_SetKey(&ctx->cipher.des3, key, NULL, + ctx->enc ? DES_ENCRYPTION : DES_DECRYPTION); + if (ret != 0) + return ret; + } + } +#endif /* NO_DES3 */ +#ifndef NO_RC4 + if (ctx->cipherType == ARC4_TYPE || (type && + XSTRNCMP(type, "ARC4", 4) == 0)) { + WOLFSSL_MSG("ARC4"); + ctx->cipherType = ARC4_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_STREAM_CIPHER; + ctx->block_size = 1; + if (ctx->keyLen == 0) /* user may have already set */ + ctx->keyLen = 16; /* default to 128 */ + if (key) + wc_Arc4SetKey(&ctx->cipher.arc4, key, ctx->keyLen); + } +#endif /* NO_RC4 */ +#ifdef HAVE_IDEA + if (ctx->cipherType == IDEA_CBC_TYPE || + (type && XSTRNCMP(type, EVP_IDEA_CBC, EVP_IDEA_SIZE) == 0)) { + WOLFSSL_MSG("EVP_IDEA_CBC"); + ctx->cipherType = IDEA_CBC_TYPE; + ctx->flags &= ~WOLFSSL_EVP_CIPH_MODE; + ctx->flags |= WOLFSSL_EVP_CIPH_CBC_MODE; + ctx->keyLen = IDEA_KEY_SIZE; + ctx->block_size = 8; + if (enc == 0 || enc == 1) + ctx->enc = enc ? 1 : 0; + if (key) { + ret = wc_IdeaSetKey(&ctx->cipher.idea, key, (word16)ctx->keyLen, + iv, ctx->enc ? IDEA_ENCRYPTION : + IDEA_DECRYPTION); + if (ret != 0) + return ret; + } + + if (iv && key == NULL) + wc_IdeaSetIV(&ctx->cipher.idea, iv); + } +#endif /* HAVE_IDEA */ + if (ctx->cipherType == NULL_CIPHER_TYPE || (type && + XSTRNCMP(type, "NULL", 4) == 0)) { + WOLFSSL_MSG("NULL cipher"); + ctx->cipherType = NULL_CIPHER_TYPE; + ctx->keyLen = 0; + ctx->block_size = 16; + } + (void)ret; /* remove warning. If execution reaches this point, ret=0 */ + return WOLFSSL_SUCCESS; + } + + + /* WOLFSSL_SUCCESS on ok */ + int wolfSSL_EVP_CIPHER_CTX_key_length(WOLFSSL_EVP_CIPHER_CTX* ctx) + { + WOLFSSL_ENTER("wolfSSL_EVP_CIPHER_CTX_key_length"); + if (ctx) + return ctx->keyLen; + + return 0; /* failure */ + } + + + /* WOLFSSL_SUCCESS on ok */ + int wolfSSL_EVP_CIPHER_CTX_set_key_length(WOLFSSL_EVP_CIPHER_CTX* ctx, + int keylen) + { + WOLFSSL_ENTER("wolfSSL_EVP_CIPHER_CTX_set_key_length"); + if (ctx) + ctx->keyLen = keylen; + else + return 0; /* failure */ + + return WOLFSSL_SUCCESS; + } + + + /* WOLFSSL_SUCCESS on ok */ + int wolfSSL_EVP_Cipher(WOLFSSL_EVP_CIPHER_CTX* ctx, byte* dst, byte* src, + word32 len) + { + int ret = 0; + WOLFSSL_ENTER("wolfSSL_EVP_Cipher"); + + if (ctx == NULL || dst == NULL || src == NULL) { + WOLFSSL_MSG("Bad function argument"); + return 0; /* failure */ + } + + if (ctx->cipherType == 0xff) { + WOLFSSL_MSG("no init"); + return 0; /* failure */ + } + + switch (ctx->cipherType) { + +#ifndef NO_AES +#ifdef HAVE_AES_CBC + case AES_128_CBC_TYPE : + case AES_192_CBC_TYPE : + case AES_256_CBC_TYPE : + WOLFSSL_MSG("AES CBC"); + if (ctx->enc) + ret = wc_AesCbcEncrypt(&ctx->cipher.aes, dst, src, len); + else + ret = wc_AesCbcDecrypt(&ctx->cipher.aes, dst, src, len); + break; +#endif /* HAVE_AES_CBC */ +#ifdef HAVE_AES_ECB + case AES_128_ECB_TYPE : + case AES_192_ECB_TYPE : + case AES_256_ECB_TYPE : + WOLFSSL_MSG("AES ECB"); + if (ctx->enc) + ret = wc_AesEcbEncrypt(&ctx->cipher.aes, dst, src, len); + else + ret = wc_AesEcbDecrypt(&ctx->cipher.aes, dst, src, len); + break; +#endif +#ifdef WOLFSSL_AES_COUNTER + case AES_128_CTR_TYPE : + case AES_192_CTR_TYPE : + case AES_256_CTR_TYPE : + WOLFSSL_MSG("AES CTR"); + ret = wc_AesCtrEncrypt(&ctx->cipher.aes, dst, src, len); + break; +#endif /* WOLFSSL_AES_COUNTER */ +#endif /* NO_AES */ + +#ifndef NO_DES3 + case DES_CBC_TYPE : + if (ctx->enc) + wc_Des_CbcEncrypt(&ctx->cipher.des, dst, src, len); + else + wc_Des_CbcDecrypt(&ctx->cipher.des, dst, src, len); + break; + case DES_EDE3_CBC_TYPE : + if (ctx->enc) + ret = wc_Des3_CbcEncrypt(&ctx->cipher.des3, dst, src, len); + else + ret = wc_Des3_CbcDecrypt(&ctx->cipher.des3, dst, src, len); + break; +#ifdef WOLFSSL_DES_ECB + case DES_ECB_TYPE : + ret = wc_Des_EcbEncrypt(&ctx->cipher.des, dst, src, len); + break; + case DES_EDE3_ECB_TYPE : + ret = wc_Des3_EcbEncrypt(&ctx->cipher.des3, dst, src, len); + break; +#endif +#endif /* !NO_DES3 */ + +#ifndef NO_RC4 + case ARC4_TYPE : + wc_Arc4Process(&ctx->cipher.arc4, dst, src, len); + break; +#endif + +#ifdef HAVE_IDEA + case IDEA_CBC_TYPE : + if (ctx->enc) + wc_IdeaCbcEncrypt(&ctx->cipher.idea, dst, src, len); + else + wc_IdeaCbcDecrypt(&ctx->cipher.idea, dst, src, len); + break; +#endif + case NULL_CIPHER_TYPE : + XMEMCPY(dst, src, len); + break; + + default: { + WOLFSSL_MSG("bad type"); + return 0; /* failure */ + } + } + + if (ret != 0) { + WOLFSSL_MSG("wolfSSL_EVP_Cipher failure"); + return 0; /* failure */ + } + + WOLFSSL_MSG("wolfSSL_EVP_Cipher success"); + return WOLFSSL_SUCCESS; /* success */ + } + +#define WOLFSSL_EVP_INCLUDED +#include "wolfcrypt/src/evp.c" + + + /* store for external read of iv, WOLFSSL_SUCCESS on success */ + int wolfSSL_StoreExternalIV(WOLFSSL_EVP_CIPHER_CTX* ctx) + { + WOLFSSL_ENTER("wolfSSL_StoreExternalIV"); + + if (ctx == NULL) { + WOLFSSL_MSG("Bad function argument"); + return WOLFSSL_FATAL_ERROR; + } + + switch (ctx->cipherType) { + +#ifndef NO_AES + case AES_128_CBC_TYPE : + case AES_192_CBC_TYPE : + case AES_256_CBC_TYPE : + WOLFSSL_MSG("AES CBC"); + XMEMCPY(ctx->iv, &ctx->cipher.aes.reg, AES_BLOCK_SIZE); + break; + +#ifdef WOLFSSL_AES_COUNTER + case AES_128_CTR_TYPE : + case AES_192_CTR_TYPE : + case AES_256_CTR_TYPE : + WOLFSSL_MSG("AES CTR"); + XMEMCPY(ctx->iv, &ctx->cipher.aes.reg, AES_BLOCK_SIZE); + break; +#endif /* WOLFSSL_AES_COUNTER */ + +#endif /* NO_AES */ + +#ifndef NO_DES3 + case DES_CBC_TYPE : + WOLFSSL_MSG("DES CBC"); + XMEMCPY(ctx->iv, &ctx->cipher.des.reg, DES_BLOCK_SIZE); + break; + + case DES_EDE3_CBC_TYPE : + WOLFSSL_MSG("DES EDE3 CBC"); + XMEMCPY(ctx->iv, &ctx->cipher.des3.reg, DES_BLOCK_SIZE); + break; +#endif + +#ifdef HAVE_IDEA + case IDEA_CBC_TYPE : + WOLFSSL_MSG("IDEA CBC"); + XMEMCPY(ctx->iv, &ctx->cipher.idea.reg, IDEA_BLOCK_SIZE); + break; +#endif + case ARC4_TYPE : + WOLFSSL_MSG("ARC4"); + break; + + case NULL_CIPHER_TYPE : + WOLFSSL_MSG("NULL"); + break; + + default: { + WOLFSSL_MSG("bad type"); + return WOLFSSL_FATAL_ERROR; + } + } + return WOLFSSL_SUCCESS; + } + + + /* set internal IV from external, WOLFSSL_SUCCESS on success */ + int wolfSSL_SetInternalIV(WOLFSSL_EVP_CIPHER_CTX* ctx) + { + + WOLFSSL_ENTER("wolfSSL_SetInternalIV"); + + if (ctx == NULL) { + WOLFSSL_MSG("Bad function argument"); + return WOLFSSL_FATAL_ERROR; + } + + switch (ctx->cipherType) { + +#ifndef NO_AES + case AES_128_CBC_TYPE : + case AES_192_CBC_TYPE : + case AES_256_CBC_TYPE : + WOLFSSL_MSG("AES CBC"); + XMEMCPY(&ctx->cipher.aes.reg, ctx->iv, AES_BLOCK_SIZE); + break; + +#ifdef WOLFSSL_AES_COUNTER + case AES_128_CTR_TYPE : + case AES_192_CTR_TYPE : + case AES_256_CTR_TYPE : + WOLFSSL_MSG("AES CTR"); + XMEMCPY(&ctx->cipher.aes.reg, ctx->iv, AES_BLOCK_SIZE); + break; +#endif + +#endif /* NO_AES */ + +#ifndef NO_DES3 + case DES_CBC_TYPE : + WOLFSSL_MSG("DES CBC"); + XMEMCPY(&ctx->cipher.des.reg, ctx->iv, DES_BLOCK_SIZE); + break; + + case DES_EDE3_CBC_TYPE : + WOLFSSL_MSG("DES EDE3 CBC"); + XMEMCPY(&ctx->cipher.des3.reg, ctx->iv, DES_BLOCK_SIZE); + break; +#endif + +#ifdef HAVE_IDEA + case IDEA_CBC_TYPE : + WOLFSSL_MSG("IDEA CBC"); + XMEMCPY(&ctx->cipher.idea.reg, ctx->iv, IDEA_BLOCK_SIZE); + break; +#endif + case ARC4_TYPE : + WOLFSSL_MSG("ARC4"); + break; + + case NULL_CIPHER_TYPE : + WOLFSSL_MSG("NULL"); + break; + + default: { + WOLFSSL_MSG("bad type"); + return WOLFSSL_FATAL_ERROR; + } + } + return WOLFSSL_SUCCESS; + } + + + /* WOLFSSL_SUCCESS on ok */ + int wolfSSL_EVP_DigestInit(WOLFSSL_EVP_MD_CTX* ctx, + const WOLFSSL_EVP_MD* type) + { + int ret = WOLFSSL_SUCCESS; + + WOLFSSL_ENTER("EVP_DigestInit"); + + if (ctx == NULL || type == NULL) { + return BAD_FUNC_ARG; + } + + + #ifdef WOLFSSL_ASYNC_CRYPT + /* compile-time validation of ASYNC_CTX_SIZE */ + typedef char async_test[WC_ASYNC_DEV_SIZE >= sizeof(WC_ASYNC_DEV) ? + 1 : -1]; + (void)sizeof(async_test); + #endif + + if (XSTRNCMP(type, "SHA256", 6) == 0) { + ctx->macType = WC_HASH_TYPE_SHA256; + ret = wolfSSL_SHA256_Init(&(ctx->hash.digest.sha256)); + } + #ifdef WOLFSSL_SHA224 + else if (XSTRNCMP(type, "SHA224", 6) == 0) { + ctx->macType = WC_HASH_TYPE_SHA224; + ret = wolfSSL_SHA224_Init(&(ctx->hash.digest.sha224)); + } + #endif + #ifdef WOLFSSL_SHA384 + else if (XSTRNCMP(type, "SHA384", 6) == 0) { + ctx->macType = WC_HASH_TYPE_SHA384; + ret = wolfSSL_SHA384_Init(&(ctx->hash.digest.sha384)); + } + #endif + #ifdef WOLFSSL_SHA512 + else if (XSTRNCMP(type, "SHA512", 6) == 0) { + ctx->macType = WC_HASH_TYPE_SHA512; + ret = wolfSSL_SHA512_Init(&(ctx->hash.digest.sha512)); + } + #endif + #ifndef NO_MD4 + else if (XSTRNCMP(type, "MD4", 3) == 0) { + ctx->macType = WC_HASH_TYPE_MD4; + wolfSSL_MD4_Init(&(ctx->hash.digest.md4)); + } + #endif + #ifndef NO_MD5 + else if (XSTRNCMP(type, "MD5", 3) == 0) { + ctx->macType = WC_HASH_TYPE_MD5; + ret = wolfSSL_MD5_Init(&(ctx->hash.digest.md5)); + } + #endif + #ifndef NO_SHA + /* has to be last since would pick or 224, 256, 384, or 512 too */ + else if (XSTRNCMP(type, "SHA", 3) == 0) { + ctx->macType = WC_HASH_TYPE_SHA; + ret = wolfSSL_SHA_Init(&(ctx->hash.digest.sha)); + } + #endif /* NO_SHA */ + else { + ctx->macType = WC_HASH_TYPE_NONE; + return BAD_FUNC_ARG; + } + + return ret; + } + + + /* WOLFSSL_SUCCESS on ok, WOLFSSL_FAILURE on failure */ + int wolfSSL_EVP_DigestUpdate(WOLFSSL_EVP_MD_CTX* ctx, const void* data, + size_t sz) + { + WOLFSSL_ENTER("EVP_DigestUpdate"); + + switch (ctx->macType) { +#ifndef NO_MD4 + case WC_HASH_TYPE_MD4: + wolfSSL_MD4_Update((MD4_CTX*)&ctx->hash, data, + (unsigned long)sz); + break; +#endif +#ifndef NO_MD5 + case WC_HASH_TYPE_MD5: + wolfSSL_MD5_Update((MD5_CTX*)&ctx->hash, data, + (unsigned long)sz); + break; +#endif +#ifndef NO_SHA + case WC_HASH_TYPE_SHA: + wolfSSL_SHA_Update((SHA_CTX*)&ctx->hash, data, + (unsigned long)sz); + break; +#endif +#ifdef WOLFSSL_SHA224 + case WC_HASH_TYPE_SHA224: + wolfSSL_SHA224_Update((SHA224_CTX*)&ctx->hash, data, + (unsigned long)sz); + break; +#endif +#ifndef NO_SHA256 + case WC_HASH_TYPE_SHA256: + wolfSSL_SHA256_Update((SHA256_CTX*)&ctx->hash, data, + (unsigned long)sz); + break; +#endif /* !NO_SHA256 */ +#ifdef WOLFSSL_SHA384 + case WC_HASH_TYPE_SHA384: + wolfSSL_SHA384_Update((SHA384_CTX*)&ctx->hash, data, + (unsigned long)sz); + break; +#endif +#ifdef WOLFSSL_SHA512 + case WC_HASH_TYPE_SHA512: + wolfSSL_SHA512_Update((SHA512_CTX*)&ctx->hash, data, + (unsigned long)sz); + break; +#endif /* WOLFSSL_SHA512 */ + default: + return WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; + } + + + /* WOLFSSL_SUCCESS on ok */ + int wolfSSL_EVP_DigestFinal(WOLFSSL_EVP_MD_CTX* ctx, unsigned char* md, + unsigned int* s) + { + WOLFSSL_ENTER("EVP_DigestFinal"); + switch (ctx->macType) { +#ifndef NO_MD4 + case WC_HASH_TYPE_MD4: + wolfSSL_MD4_Final(md, (MD4_CTX*)&ctx->hash); + if (s) *s = MD4_DIGEST_SIZE; + break; +#endif +#ifndef NO_MD5 + case WC_HASH_TYPE_MD5: + wolfSSL_MD5_Final(md, (MD5_CTX*)&ctx->hash); + if (s) *s = WC_MD5_DIGEST_SIZE; + break; +#endif +#ifndef NO_SHA + case WC_HASH_TYPE_SHA: + wolfSSL_SHA_Final(md, (SHA_CTX*)&ctx->hash); + if (s) *s = WC_SHA_DIGEST_SIZE; + break; +#endif +#ifdef WOLFSSL_SHA224 + case WC_HASH_TYPE_SHA224: + wolfSSL_SHA224_Final(md, (SHA224_CTX*)&ctx->hash); + if (s) *s = WC_SHA224_DIGEST_SIZE; + break; +#endif +#ifndef NO_SHA256 + case WC_HASH_TYPE_SHA256: + wolfSSL_SHA256_Final(md, (SHA256_CTX*)&ctx->hash); + if (s) *s = WC_SHA256_DIGEST_SIZE; + break; +#endif /* !NO_SHA256 */ +#ifdef WOLFSSL_SHA384 + case WC_HASH_TYPE_SHA384: + wolfSSL_SHA384_Final(md, (SHA384_CTX*)&ctx->hash); + if (s) *s = WC_SHA384_DIGEST_SIZE; + break; +#endif +#ifdef WOLFSSL_SHA512 + case WC_HASH_TYPE_SHA512: + wolfSSL_SHA512_Final(md, (SHA512_CTX*)&ctx->hash); + if (s) *s = WC_SHA512_DIGEST_SIZE; + break; +#endif /* WOLFSSL_SHA512 */ + default: + return WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; + } + + + /* WOLFSSL_SUCCESS on ok */ + int wolfSSL_EVP_DigestFinal_ex(WOLFSSL_EVP_MD_CTX* ctx, unsigned char* md, + unsigned int* s) + { + WOLFSSL_ENTER("EVP_DigestFinal_ex"); + return EVP_DigestFinal(ctx, md, s); + } + + + unsigned char* wolfSSL_HMAC(const WOLFSSL_EVP_MD* evp_md, const void* key, + int key_len, const unsigned char* d, int n, + unsigned char* md, unsigned int* md_len) + { + int type; + int mdlen; + unsigned char* ret = NULL; +#ifdef WOLFSSL_SMALL_STACK + Hmac* hmac = NULL; +#else + Hmac hmac[1]; +#endif + void* heap = NULL; + + WOLFSSL_ENTER("wolfSSL_HMAC"); + if (!md) { + WOLFSSL_MSG("Static buffer not supported, pass in md buffer"); + return NULL; /* no static buffer support */ + } + +#ifndef NO_MD5 + if (XSTRNCMP(evp_md, "MD5", 3) == 0) { + type = WC_MD5; + mdlen = WC_MD5_DIGEST_SIZE; + } else +#endif +#ifdef WOLFSSL_SHA224 + if (XSTRNCMP(evp_md, "SHA224", 6) == 0) { + type = WC_SHA224; + mdlen = WC_SHA224_DIGEST_SIZE; + } else +#endif +#ifndef NO_SHA256 + if (XSTRNCMP(evp_md, "SHA256", 6) == 0) { + type = WC_SHA256; + mdlen = WC_SHA256_DIGEST_SIZE; + } else +#endif +#ifdef WOLFSSL_SHA384 + if (XSTRNCMP(evp_md, "SHA384", 6) == 0) { + type = WC_SHA384; + mdlen = WC_SHA384_DIGEST_SIZE; + } else +#endif +#ifdef WOLFSSL_SHA512 + if (XSTRNCMP(evp_md, "SHA512", 6) == 0) { + type = WC_SHA512; + mdlen = WC_SHA512_DIGEST_SIZE; + } else +#endif +#ifndef NO_SHA + if (XSTRNCMP(evp_md, "SHA", 3) == 0) { + type = WC_SHA; + mdlen = WC_SHA_DIGEST_SIZE; + } else +#endif + { + return NULL; + } + + #ifdef WOLFSSL_SMALL_STACK + hmac = (Hmac*)XMALLOC(sizeof(Hmac), heap, DYNAMIC_TYPE_HMAC); + if (hmac == NULL) + return NULL; + #endif + + if (wc_HmacInit(hmac, heap, INVALID_DEVID) == 0) { + if (wc_HmacSetKey(hmac, type, (const byte*)key, key_len) == 0) { + if (wc_HmacUpdate(hmac, d, n) == 0) { + if (wc_HmacFinal(hmac, md) == 0) { + if (md_len) + *md_len = mdlen; + ret = md; + } + } + } + wc_HmacFree(hmac); + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(hmac, heap, DYNAMIC_TYPE_HMAC); + #endif + + (void)evp_md; + return ret; + } + + void wolfSSL_ERR_clear_error(void) + { + WOLFSSL_ENTER("wolfSSL_ERR_clear_error"); + +#if defined(DEBUG_WOLFSSL) || defined(WOLFSSL_NGINX) + wc_ClearErrorNodes(); +#endif + } + + + /* frees all nodes in the current threads error queue + * + * id thread id. ERR_remove_state is depreciated and id is ignored. The + * current threads queue will be free'd. + */ + void wolfSSL_ERR_remove_state(unsigned long id) + { + WOLFSSL_ENTER("wolfSSL_ERR_remove_state"); + (void)id; + if (wc_ERR_remove_state() != 0) { + WOLFSSL_MSG("Error with removing the state"); + } + } + + + int wolfSSL_RAND_status(void) + { + return WOLFSSL_SUCCESS; /* wolfCrypt provides enough seed internally */ + } + + + #ifndef NO_WOLFSSL_STUB + void wolfSSL_RAND_add(const void* add, int len, double entropy) + { + (void)add; + (void)len; + (void)entropy; + WOLFSSL_STUB("RAND_add"); + /* wolfSSL seeds/adds internally, use explicit RNG if you want + to take control */ + } + #endif + +#ifndef NO_DES3 + /* 0 on ok */ + int wolfSSL_DES_key_sched(WOLFSSL_const_DES_cblock* key, + WOLFSSL_DES_key_schedule* schedule) + { + WOLFSSL_ENTER("wolfSSL_DES_key_sched"); + + if (key == NULL || schedule == NULL) { + WOLFSSL_MSG("Null argument passed in"); + } + else { + XMEMCPY(schedule, key, sizeof(WOLFSSL_const_DES_cblock)); + } + + return 0; + } + + + /* intended to behave similar to Kerberos mit_des_cbc_cksum + * return the last 4 bytes of cipher text */ + WOLFSSL_DES_LONG wolfSSL_DES_cbc_cksum(const unsigned char* in, + WOLFSSL_DES_cblock* out, long length, WOLFSSL_DES_key_schedule* sc, + WOLFSSL_const_DES_cblock* iv) + { + WOLFSSL_DES_LONG ret; + unsigned char* tmp; + unsigned char* data = (unsigned char*)in; + long dataSz = length; + byte dynamicFlag = 0; /* when padding the buffer created needs free'd */ + + WOLFSSL_ENTER("wolfSSL_DES_cbc_cksum"); + + if (in == NULL || out == NULL || sc == NULL || iv == NULL) { + WOLFSSL_MSG("Bad argument passed in"); + return 0; + } + + /* if input length is not a multiple of DES_BLOCK_SIZE pad with 0s */ + if (dataSz % DES_BLOCK_SIZE) { + dataSz += DES_BLOCK_SIZE - (dataSz % DES_BLOCK_SIZE); + data = (unsigned char*)XMALLOC(dataSz, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (data == NULL) { + WOLFSSL_MSG("Issue creating temporary buffer"); + return 0; + } + dynamicFlag = 1; /* set to free buffer at end */ + XMEMCPY(data, in, length); + XMEMSET(data + length, 0, dataSz - length); /* padding */ + } + + tmp = (unsigned char*)XMALLOC(dataSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) { + WOLFSSL_MSG("Issue creating temporary buffer"); + if (dynamicFlag == 1) { + XFREE(data, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + return 0; + } + + wolfSSL_DES_cbc_encrypt(data, tmp, dataSz, sc, + (WOLFSSL_DES_cblock*)iv, 1); + XMEMCPY((unsigned char*)out, tmp + (dataSz - DES_BLOCK_SIZE), + DES_BLOCK_SIZE); + + ret = (((*((unsigned char*)out + 4) & 0xFF) << 24)| + ((*((unsigned char*)out + 5) & 0xFF) << 16)| + ((*((unsigned char*)out + 6) & 0xFF) << 8) | + (*((unsigned char*)out + 7) & 0xFF)); + + XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (dynamicFlag == 1) { + XFREE(data, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + + return ret; + } + + + void wolfSSL_DES_cbc_encrypt(const unsigned char* input, + unsigned char* output, long length, + WOLFSSL_DES_key_schedule* schedule, + WOLFSSL_DES_cblock* ivec, int enc) + { + Des myDes; + byte lastblock[DES_BLOCK_SIZE]; + int lb_sz; + long blk; + + WOLFSSL_ENTER("DES_cbc_encrypt"); + + /* OpenSSL compat, no ret */ + wc_Des_SetKey(&myDes, (const byte*)schedule, (const byte*)ivec, !enc); + lb_sz = length%DES_BLOCK_SIZE; + blk = length/DES_BLOCK_SIZE; + + if (enc){ + wc_Des_CbcEncrypt(&myDes, output, input, (word32)blk*DES_BLOCK_SIZE); + if(lb_sz){ + XMEMSET(lastblock, 0, DES_BLOCK_SIZE); + XMEMCPY(lastblock, input+length-lb_sz, lb_sz); + wc_Des_CbcEncrypt(&myDes, output+blk*DES_BLOCK_SIZE, + lastblock, (word32)DES_BLOCK_SIZE); + } + } + else { + wc_Des_CbcDecrypt(&myDes, output, input, (word32)blk*DES_BLOCK_SIZE); + if(lb_sz){ + wc_Des_CbcDecrypt(&myDes, lastblock, input+length-lb_sz, (word32)DES_BLOCK_SIZE); + XMEMCPY(output+length-lb_sz, lastblock, lb_sz); + } + } + } + + + /* WOLFSSL_DES_key_schedule is a unsigned char array of size 8 */ + void wolfSSL_DES_ede3_cbc_encrypt(const unsigned char* input, + unsigned char* output, long sz, + WOLFSSL_DES_key_schedule* ks1, + WOLFSSL_DES_key_schedule* ks2, + WOLFSSL_DES_key_schedule* ks3, + WOLFSSL_DES_cblock* ivec, int enc) + { + Des3 des; + byte key[24];/* EDE uses 24 size key */ + byte lastblock[DES_BLOCK_SIZE]; + int lb_sz; + long blk; + + WOLFSSL_ENTER("wolfSSL_DES_ede3_cbc_encrypt"); + + XMEMSET(key, 0, sizeof(key)); + XMEMCPY(key, *ks1, DES_BLOCK_SIZE); + XMEMCPY(&key[DES_BLOCK_SIZE], *ks2, DES_BLOCK_SIZE); + XMEMCPY(&key[DES_BLOCK_SIZE * 2], *ks3, DES_BLOCK_SIZE); + lb_sz = sz%DES_BLOCK_SIZE; + blk = sz/DES_BLOCK_SIZE; + + /* OpenSSL compat, no ret */ + (void)wc_Des3Init(&des, NULL, INVALID_DEVID); + + if (enc) { + wc_Des3_SetKey(&des, key, (const byte*)ivec, DES_ENCRYPTION); + wc_Des3_CbcEncrypt(&des, output, input, (word32)blk*DES_BLOCK_SIZE); + if(lb_sz){ + XMEMSET(lastblock, 0, DES_BLOCK_SIZE); + XMEMCPY(lastblock, input+sz-lb_sz, lb_sz); + wc_Des3_CbcEncrypt(&des, output+blk*DES_BLOCK_SIZE, + lastblock, (word32)DES_BLOCK_SIZE); + } + } + else { + wc_Des3_SetKey(&des, key, (const byte*)ivec, DES_DECRYPTION); + wc_Des3_CbcDecrypt(&des, output, input, (word32)blk*DES_BLOCK_SIZE); + if(lb_sz){ + wc_Des3_CbcDecrypt(&des, lastblock, input+sz-lb_sz, (word32)DES_BLOCK_SIZE); + XMEMCPY(output+sz-lb_sz, lastblock, lb_sz); + } + } + wc_Des3Free(&des); + } + + + /* correctly sets ivec for next call */ + void wolfSSL_DES_ncbc_encrypt(const unsigned char* input, + unsigned char* output, long length, + WOLFSSL_DES_key_schedule* schedule, WOLFSSL_DES_cblock* ivec, + int enc) + { + Des myDes; + byte lastblock[DES_BLOCK_SIZE]; + int lb_sz; + long idx = length; + long blk; + + WOLFSSL_ENTER("DES_ncbc_encrypt"); + + /* OpenSSL compat, no ret */ + wc_Des_SetKey(&myDes, (const byte*)schedule, (const byte*)ivec, !enc); + lb_sz = length%DES_BLOCK_SIZE; + blk = length/DES_BLOCK_SIZE; + idx -= sizeof(DES_cblock); + if (lb_sz) { + idx += DES_BLOCK_SIZE - lb_sz; + } + if (enc){ + wc_Des_CbcEncrypt(&myDes, output, input, + (word32)blk * DES_BLOCK_SIZE); + if (lb_sz){ + XMEMSET(lastblock, 0, DES_BLOCK_SIZE); + XMEMCPY(lastblock, input+length-lb_sz, lb_sz); + wc_Des_CbcEncrypt(&myDes, output + blk * DES_BLOCK_SIZE, + lastblock, (word32)DES_BLOCK_SIZE); + } + XMEMCPY(ivec, output + idx, sizeof(DES_cblock)); + } else { + WOLFSSL_DES_cblock tmp; + XMEMCPY(tmp, input + idx, sizeof(DES_cblock)); + wc_Des_CbcDecrypt(&myDes, output, input, + (word32)blk * DES_BLOCK_SIZE); + if (lb_sz){ + wc_Des_CbcDecrypt(&myDes, lastblock, input + length - lb_sz, + (word32)DES_BLOCK_SIZE); + XMEMCPY(output+length-lb_sz, lastblock, lb_sz); + } + XMEMCPY(ivec, tmp, sizeof(WOLFSSL_DES_cblock)); + } + + } + +#endif /* NO_DES3 */ + + + void wolfSSL_ERR_free_strings(void) + { + /* handled internally */ + } + + + void wolfSSL_EVP_cleanup(void) + { + /* nothing to do here */ + } + + + void wolfSSL_cleanup_all_ex_data(void) + { + /* nothing to do here */ + } + + int wolfSSL_clear(WOLFSSL* ssl) + { + if (ssl == NULL) { + return WOLFSSL_FAILURE; + } + + ssl->options.isClosed = 0; + ssl->options.connReset = 0; + ssl->options.sentNotify = 0; + ssl->options.sendVerify = 0; + ssl->options.serverState = NULL_STATE; + ssl->options.clientState = NULL_STATE; + ssl->options.connectState = CONNECT_BEGIN; + ssl->options.acceptState = ACCEPT_BEGIN; + ssl->options.handShakeState = NULL_STATE; + ssl->options.handShakeDone = 0; + /* ssl->options.processReply = doProcessInit; */ + + ssl->keys.encryptionOn = 0; + XMEMSET(&ssl->msgsReceived, 0, sizeof(ssl->msgsReceived)); + + if (ssl->hsHashes != NULL) { +#ifndef NO_OLD_TLS +#ifndef NO_MD5 + if (wc_InitMd5_ex(&ssl->hsHashes->hashMd5, ssl->heap, + ssl->devId) != 0) { + return WOLFSSL_FAILURE; + } + #if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + wc_Md5SetFlags(&ssl->hsHashes->hashMd5, WC_HASH_FLAG_WILLCOPY); + #endif +#endif +#ifndef NO_SHA + if (wc_InitSha_ex(&ssl->hsHashes->hashSha, ssl->heap, + ssl->devId) != 0) { + return WOLFSSL_FAILURE; + } + #if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + wc_ShaSetFlags(&ssl->hsHashes->hashSha, WC_HASH_FLAG_WILLCOPY); + #endif +#endif +#endif +#ifndef NO_SHA256 + if (wc_InitSha256_ex(&ssl->hsHashes->hashSha256, ssl->heap, + ssl->devId) != 0) { + return WOLFSSL_FAILURE; + } + #if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + wc_Sha256SetFlags(&ssl->hsHashes->hashSha256, WC_HASH_FLAG_WILLCOPY); + #endif +#endif +#ifdef WOLFSSL_SHA384 + if (wc_InitSha384_ex(&ssl->hsHashes->hashSha384, ssl->heap, + ssl->devId) != 0) { + return WOLFSSL_FAILURE; + } + #if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + wc_Sha384SetFlags(&ssl->hsHashes->hashSha384, WC_HASH_FLAG_WILLCOPY); + #endif +#endif +#ifdef WOLFSSL_SHA512 + if (wc_InitSha512_ex(&ssl->hsHashes->hashSha512, ssl->heap, + ssl->devId) != 0) { + return WOLFSSL_FAILURE; + } + #if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + wc_Sha512SetFlags(&ssl->hsHashes->hashSha512, WC_HASH_FLAG_WILLCOPY); + #endif +#endif + } +#ifdef SESSION_CERTS + ssl->session.chain.count = 0; +#endif +#ifdef KEEP_PEER_CERT + FreeX509(&ssl->peerCert); + InitX509(&ssl->peerCert, 0, ssl->heap); +#endif + + return WOLFSSL_SUCCESS; + } + + long wolfSSL_SSL_SESSION_set_timeout(WOLFSSL_SESSION* ses, long t) + { + word32 tmptime; + if (!ses || t < 0) + return BAD_FUNC_ARG; + + tmptime = t & 0xFFFFFFFF; + + ses->timeout = tmptime; + + return WOLFSSL_SUCCESS; + } + +#endif + +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + long wolfSSL_CTX_set_mode(WOLFSSL_CTX* ctx, long mode) + { + /* WOLFSSL_MODE_ACCEPT_MOVING_WRITE_BUFFER is wolfSSL default mode */ + + WOLFSSL_ENTER("SSL_CTX_set_mode"); + if (mode == SSL_MODE_ENABLE_PARTIAL_WRITE) + ctx->partialWrite = 1; + + return mode; + } +#endif + +#ifdef OPENSSL_EXTRA + + #ifndef NO_WOLFSSL_STUB + long wolfSSL_SSL_get_mode(WOLFSSL* ssl) + { + /* TODO: */ + (void)ssl; + WOLFSSL_STUB("SSL_get_mode"); + return 0; + } + #endif + + #ifndef NO_WOLFSSL_STUB + long wolfSSL_CTX_get_mode(WOLFSSL_CTX* ctx) + { + /* TODO: */ + (void)ctx; + WOLFSSL_STUB("SSL_CTX_get_mode"); + return 0; + } + #endif + + #ifndef NO_WOLFSSL_STUB + void wolfSSL_CTX_set_default_read_ahead(WOLFSSL_CTX* ctx, int m) + { + /* TODO: maybe? */ + (void)ctx; + (void)m; + WOLFSSL_STUB("SSL_CTX_set_default_read_ahead"); + } + #endif + + + /* Storing app session context id, this value is inherited by WOLFSSL + * objects created from WOLFSSL_CTX. Any session that is imported with a + * different session context id will be rejected. + * + * ctx structure to set context in + * sid_ctx value of context to set + * sid_ctx_len length of sid_ctx buffer + * + * Returns SSL_SUCCESS in success case and SSL_FAILURE when failing + */ + int wolfSSL_CTX_set_session_id_context(WOLFSSL_CTX* ctx, + const unsigned char* sid_ctx, + unsigned int sid_ctx_len) + { + WOLFSSL_ENTER("SSL_CTX_set_session_id_context"); + + /* No application specific context needed for wolfSSL */ + if (sid_ctx_len > ID_LEN || ctx == NULL || sid_ctx == NULL) { + return SSL_FAILURE; + } + XMEMCPY(ctx->sessionCtx, sid_ctx, sid_ctx_len); + ctx->sessionCtxSz = (byte)sid_ctx_len; + + return SSL_SUCCESS; + } + + + + /* Storing app session context id. Any session that is imported with a + * different session context id will be rejected. + * + * ssl structure to set context in + * id value of context to set + * len length of sid_ctx buffer + * + * Returns SSL_SUCCESS in success case and SSL_FAILURE when failing + */ + int wolfSSL_set_session_id_context(WOLFSSL* ssl, const unsigned char* id, + unsigned int len) + { + WOLFSSL_STUB("wolfSSL_set_session_id_context"); + + if (len > ID_LEN || ssl == NULL || id == NULL) { + return SSL_FAILURE; + } + XMEMCPY(ssl->sessionCtx, id, len); + ssl->sessionCtxSz = (byte)len; + + return SSL_SUCCESS; + } + + + long wolfSSL_CTX_sess_get_cache_size(WOLFSSL_CTX* ctx) + { + (void)ctx; + #ifndef NO_SESSION_CACHE + return SESSIONS_PER_ROW * SESSION_ROWS; + #else + return 0; + #endif + } + + + /* returns the unsigned error value and increments the pointer into the + * error queue. + * + * file pointer to file name + * line gets set to line number of error when not NULL + */ + unsigned long wolfSSL_ERR_get_error_line(const char** file, int* line) + { + #ifdef DEBUG_WOLFSSL + int ret = wc_PullErrorNode(file, NULL, line); + if (ret < 0) { + if (ret == BAD_STATE_E) return 0; /* no errors in queue */ + WOLFSSL_MSG("Issue getting error node"); + WOLFSSL_LEAVE("wolfSSL_ERR_get_error_line", ret); + ret = 0 - ret; /* return absolute value of error */ + + /* panic and try to clear out nodes */ + wc_ClearErrorNodes(); + } + return (unsigned long)ret; + #else + (void)file; + (void)line; + + return 0; + #endif + } + + +#ifdef DEBUG_WOLFSSL + static const char WOLFSSL_SYS_ACCEPT_T[] = "accept"; + static const char WOLFSSL_SYS_BIND_T[] = "bind"; + static const char WOLFSSL_SYS_CONNECT_T[] = "connect"; + static const char WOLFSSL_SYS_FOPEN_T[] = "fopen"; + static const char WOLFSSL_SYS_FREAD_T[] = "fread"; + static const char WOLFSSL_SYS_GETADDRINFO_T[] = "getaddrinfo"; + static const char WOLFSSL_SYS_GETSOCKOPT_T[] = "getsockopt"; + static const char WOLFSSL_SYS_GETSOCKNAME_T[] = "getsockname"; + static const char WOLFSSL_SYS_GETHOSTBYNAME_T[] = "gethostbyname"; + static const char WOLFSSL_SYS_GETNAMEINFO_T[] = "getnameinfo"; + static const char WOLFSSL_SYS_GETSERVBYNAME_T[] = "getservbyname"; + static const char WOLFSSL_SYS_IOCTLSOCKET_T[] = "ioctlsocket"; + static const char WOLFSSL_SYS_LISTEN_T[] = "listen"; + static const char WOLFSSL_SYS_OPENDIR_T[] = "opendir"; + static const char WOLFSSL_SYS_SETSOCKOPT_T[] = "setsockopt"; + static const char WOLFSSL_SYS_SOCKET_T[] = "socket"; + + /* switch with int mapped to function name for compatibility */ + static const char* wolfSSL_ERR_sys_func(int fun) + { + switch (fun) { + case WOLFSSL_SYS_ACCEPT: return WOLFSSL_SYS_ACCEPT_T; + case WOLFSSL_SYS_BIND: return WOLFSSL_SYS_BIND_T; + case WOLFSSL_SYS_CONNECT: return WOLFSSL_SYS_CONNECT_T; + case WOLFSSL_SYS_FOPEN: return WOLFSSL_SYS_FOPEN_T; + case WOLFSSL_SYS_FREAD: return WOLFSSL_SYS_FREAD_T; + case WOLFSSL_SYS_GETADDRINFO: return WOLFSSL_SYS_GETADDRINFO_T; + case WOLFSSL_SYS_GETSOCKOPT: return WOLFSSL_SYS_GETSOCKOPT_T; + case WOLFSSL_SYS_GETSOCKNAME: return WOLFSSL_SYS_GETSOCKNAME_T; + case WOLFSSL_SYS_GETHOSTBYNAME: return WOLFSSL_SYS_GETHOSTBYNAME_T; + case WOLFSSL_SYS_GETNAMEINFO: return WOLFSSL_SYS_GETNAMEINFO_T; + case WOLFSSL_SYS_GETSERVBYNAME: return WOLFSSL_SYS_GETSERVBYNAME_T; + case WOLFSSL_SYS_IOCTLSOCKET: return WOLFSSL_SYS_IOCTLSOCKET_T; + case WOLFSSL_SYS_LISTEN: return WOLFSSL_SYS_LISTEN_T; + case WOLFSSL_SYS_OPENDIR: return WOLFSSL_SYS_OPENDIR_T; + case WOLFSSL_SYS_SETSOCKOPT: return WOLFSSL_SYS_SETSOCKOPT_T; + case WOLFSSL_SYS_SOCKET: return WOLFSSL_SYS_SOCKET_T; + default: + return "NULL"; + } + } +#endif /* DEBUG_WOLFSSL */ + + + /* @TODO when having an error queue this needs to push to the queue */ + void wolfSSL_ERR_put_error(int lib, int fun, int err, const char* file, + int line) + { + WOLFSSL_ENTER("wolfSSL_ERR_put_error"); + + #ifndef DEBUG_WOLFSSL + (void)fun; + (void)err; + (void)file; + (void)line; + WOLFSSL_MSG("Not compiled in debug mode"); + #else + WOLFSSL_ERROR_LINE(err, wolfSSL_ERR_sys_func(fun), (unsigned int)line, + file, NULL); + #endif + (void)lib; + } + + + /* Similar to wolfSSL_ERR_get_error_line but takes in a flags argument for + * more flexibility. + * + * file output pointer to file where error happened + * line output to line number of error + * data output data. Is a string if ERR_TXT_STRING flag is used + * flags bit flag to adjust data output + * + * Returns the error value or 0 if no errors are in the queue + */ + unsigned long wolfSSL_ERR_get_error_line_data(const char** file, int* line, + const char** data, int *flags) + { + int ret; + + WOLFSSL_STUB("wolfSSL_ERR_get_error_line_data"); + + if (flags != NULL) { + if ((*flags & ERR_TXT_STRING) == ERR_TXT_STRING) { + ret = wc_PullErrorNode(file, data, line); + if (ret < 0) { + if (ret == BAD_STATE_E) return 0; /* no errors in queue */ + WOLFSSL_MSG("Error with pulling error node!"); + WOLFSSL_LEAVE("wolfSSL_ERR_get_error_line_data", ret); + ret = 0 - ret; /* return absolute value of error */ + + /* panic and try to clear out nodes */ + wc_ClearErrorNodes(); + } + + return (unsigned long)ret; + } + } + + ret = wc_PullErrorNode(file, NULL, line); + if (ret < 0) { + if (ret == BAD_STATE_E) return 0; /* no errors in queue */ + WOLFSSL_MSG("Error with pulling error node!"); + WOLFSSL_LEAVE("wolfSSL_ERR_get_error_line_data", ret); + ret = 0 - ret; /* return absolute value of error */ + + /* panic and try to clear out nodes */ + wc_ClearErrorNodes(); + } + + return (unsigned long)ret; + } + +#endif /* OPENSSL_EXTRA */ + + +#if (defined(KEEP_PEER_CERT) && defined(SESSION_CERTS)) || \ + (defined(OPENSSL_ALL) && defined(HAVE_PKCS7)) + /* Decode the X509 DER encoded certificate into a WOLFSSL_X509 object. + * + * x509 WOLFSSL_X509 object to decode into. + * in X509 DER data. + * len Length of the X509 DER data. + * returns the new certificate on success, otherwise NULL. + */ + static int DecodeToX509(WOLFSSL_X509* x509, const byte* in, int len) + { + int ret; + #ifdef WOLFSSL_SMALL_STACK + DecodedCert* cert = NULL; + #else + DecodedCert cert[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, + DYNAMIC_TYPE_DCERT); + if (cert == NULL) + return MEMORY_E; + #endif + + /* Create a DecodedCert object and copy fields into WOLFSSL_X509 object. + */ + InitDecodedCert(cert, (byte*)in, len, NULL); + if ((ret = ParseCertRelative(cert, CERT_TYPE, 0, NULL)) == 0) { + InitX509(x509, 0, NULL); + ret = CopyDecodedToX509(x509, cert); + FreeDecodedCert(cert); + } + #ifdef WOLFSSL_SMALL_STACK + XFREE(cert, NULL, DYNAMIC_TYPE_DCERT); + #endif + + return ret; + } +#endif /* (KEEP_PEER_CERT && SESSION_CERTS) || (OPENSSL_ALL && HAVE_PKCS7) */ + + +#ifdef KEEP_PEER_CERT + WOLFSSL_X509* wolfSSL_get_peer_certificate(WOLFSSL* ssl) + { + WOLFSSL_ENTER("SSL_get_peer_certificate"); + if (ssl == NULL) + return NULL; + + if (ssl->peerCert.issuer.sz) + return &ssl->peerCert; +#ifdef SESSION_CERTS + else if (ssl->session.chain.count > 0) { + if (DecodeToX509(&ssl->peerCert, ssl->session.chain.certs[0].buffer, + ssl->session.chain.certs[0].length) == 0) { + return &ssl->peerCert; + } + } +#endif + return 0; + } + +#endif /* KEEP_PEER_CERT */ + + +#ifndef NO_CERTS +#if defined(KEEP_PEER_CERT) || defined(SESSION_CERTS) || \ + defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + +/* user externally called free X509, if dynamic go ahead with free, otherwise + * don't */ +static void ExternalFreeX509(WOLFSSL_X509* x509) +{ + WOLFSSL_ENTER("ExternalFreeX509"); + if (x509) { + if (x509->dynamicMemory) { + FreeX509(x509); + XFREE(x509, x509->heap, DYNAMIC_TYPE_X509); + } else { + WOLFSSL_MSG("free called on non dynamic object, not freeing"); + } + } +} + +/* Frees an external WOLFSSL_X509 structure */ +void wolfSSL_X509_free(WOLFSSL_X509* x509) +{ + WOLFSSL_ENTER("wolfSSL_FreeX509"); + ExternalFreeX509(x509); +} + + +/* copy name into in buffer, at most sz bytes, if buffer is null will + malloc buffer, call responsible for freeing */ +char* wolfSSL_X509_NAME_oneline(WOLFSSL_X509_NAME* name, char* in, int sz) +{ + int copySz; + + if (name == NULL) { + WOLFSSL_MSG("WOLFSSL_X509_NAME pointer was NULL"); + return NULL; + } + + copySz = min(sz, name->sz); + + WOLFSSL_ENTER("wolfSSL_X509_NAME_oneline"); + if (!name->sz) return in; + + if (!in) { + #ifdef WOLFSSL_STATIC_MEMORY + WOLFSSL_MSG("Using static memory -- please pass in a buffer"); + return NULL; + #else + in = (char*)XMALLOC(name->sz, NULL, DYNAMIC_TYPE_OPENSSL); + if (!in ) return in; + copySz = name->sz; + #endif + } + + if (copySz <= 0) + return in; + + XMEMCPY(in, name->name, copySz - 1); + in[copySz - 1] = 0; + + return in; +} + + +/* Wraps wolfSSL_X509_d2i + * + * returns a WOLFSSL_X509 structure pointer on success and NULL on fail + */ +WOLFSSL_X509* wolfSSL_d2i_X509(WOLFSSL_X509** x509, const unsigned char** in, + int len) +{ + return wolfSSL_X509_d2i(x509, *in, len); +} + + +WOLFSSL_X509* wolfSSL_X509_d2i(WOLFSSL_X509** x509, const byte* in, int len) +{ + WOLFSSL_X509 *newX509 = NULL; + + WOLFSSL_ENTER("wolfSSL_X509_d2i"); + + if (in != NULL && len != 0) { + #ifdef WOLFSSL_SMALL_STACK + DecodedCert* cert = NULL; + #else + DecodedCert cert[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, + DYNAMIC_TYPE_DCERT); + if (cert == NULL) + return NULL; + #endif + + InitDecodedCert(cert, (byte*)in, len, NULL); + if (ParseCertRelative(cert, CERT_TYPE, 0, NULL) == 0) { + newX509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), NULL, + DYNAMIC_TYPE_X509); + if (newX509 != NULL) { + InitX509(newX509, 1, NULL); + if (CopyDecodedToX509(newX509, cert) != 0) { + wolfSSL_X509_free(newX509); + newX509 = NULL; + } + } + } + FreeDecodedCert(cert); + #ifdef WOLFSSL_SMALL_STACK + XFREE(cert, NULL, DYNAMIC_TYPE_DCERT); + #endif + } + + if (x509 != NULL) + *x509 = newX509; + + return newX509; +} +#endif /* KEEP_PEER_CERT || SESSION_CERTS || OPENSSL_EXTRA || + OPENSSL_EXTRA_X509_SMALL */ + + + +#if defined(OPENSSL_ALL) || defined(KEEP_OUR_CERT) || defined(KEEP_PEER_CERT) || \ + defined(SESSION_CERTS) + /* return the next, if any, altname from the peer cert */ + char* wolfSSL_X509_get_next_altname(WOLFSSL_X509* cert) + { + char* ret = NULL; + WOLFSSL_ENTER("wolfSSL_X509_get_next_altname"); + + /* don't have any to work with */ + if (cert == NULL || cert->altNames == NULL) + return NULL; + + /* already went through them */ + if (cert->altNamesNext == NULL) + return NULL; + + ret = cert->altNamesNext->name; + cert->altNamesNext = cert->altNamesNext->next; + + return ret; + } + + int wolfSSL_X509_get_isCA(WOLFSSL_X509* x509) + { + int isCA = 0; + + WOLFSSL_ENTER("wolfSSL_X509_get_isCA"); + + if (x509 != NULL) + isCA = x509->isCa; + + WOLFSSL_LEAVE("wolfSSL_X509_get_isCA", isCA); + + return isCA; + } + + int wolfSSL_X509_get_signature(WOLFSSL_X509* x509, + unsigned char* buf, int* bufSz) + { + WOLFSSL_ENTER("wolfSSL_X509_get_signature"); + if (x509 == NULL || bufSz == NULL || (*bufSz < (int)x509->sig.length && + buf != NULL)) + return WOLFSSL_FATAL_ERROR; + + if (buf != NULL) + XMEMCPY(buf, x509->sig.buffer, x509->sig.length); + *bufSz = x509->sig.length; + + return WOLFSSL_SUCCESS; + } + + + /* Getter function that copies over the DER public key buffer to "buf" and + * sets the size in bufSz. If "buf" is NULL then just bufSz is set to needed + * buffer size. "bufSz" passed in should initially be set by the user to be + * the size of "buf". This gets checked to make sure the buffer is large + * enough to hold the public key. + * + * Note: this is the X.509 form of key with "header" info. + * return WOLFSSL_SUCCESS on success + */ + int wolfSSL_X509_get_pubkey_buffer(WOLFSSL_X509* x509, + unsigned char* buf, int* bufSz) + { + #ifdef WOLFSSL_SMALL_STACK + DecodedCert* cert; + #else + DecodedCert cert[1]; + #endif + word32 idx; + const byte* der; + int length = 0; + int ret, derSz = 0; + int badDate = 0; + const byte* pubKeyX509 = NULL; + int pubKeyX509Sz = 0; + + WOLFSSL_ENTER("wolfSSL_X509_get_pubkey_buffer"); + if (x509 == NULL || bufSz == NULL) { + WOLFSSL_LEAVE("wolfSSL_X509_get_pubkey_buffer", BAD_FUNC_ARG); + return WOLFSSL_FATAL_ERROR; + } + + + #ifdef WOLFSSL_SMALL_STACK + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), + x509->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (cert == NULL) { + WOLFSSL_LEAVE("wolfSSL_X509_get_pubkey_buffer", MEMORY_E); + return WOLFSSL_FATAL_ERROR; + } + #endif + + der = wolfSSL_X509_get_der(x509, &derSz); + InitDecodedCert(cert, der, derSz, NULL); + ret = wc_GetPubX509(cert, 0, &badDate); + if (ret >= 0) { + idx = cert->srcIdx; + pubKeyX509 = cert->source + cert->srcIdx; + ret = GetSequence(cert->source, &cert->srcIdx, &length, + cert->maxIdx); + pubKeyX509Sz = length + (cert->srcIdx - idx); + } + + FreeDecodedCert(cert); + #ifdef WOLFSSL_SMALL_STACK + XFREE(cert, x509->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + if (ret < 0) { + WOLFSSL_LEAVE("wolfSSL_X509_get_pubkey_buffer", ret); + return WOLFSSL_FATAL_ERROR; + } + + if (buf != NULL) { + if (pubKeyX509Sz > *bufSz) { + WOLFSSL_LEAVE("wolfSSL_X509_get_pubkey_buffer", BUFFER_E); + return WOLFSSL_FATAL_ERROR; + } + XMEMCPY(buf, pubKeyX509, pubKeyX509Sz); + } + *bufSz = pubKeyX509Sz; + + return WOLFSSL_SUCCESS; + } + + + /* Getter function for the public key OID value + * return public key OID stored in WOLFSSL_X509 structure */ + int wolfSSL_X509_get_pubkey_type(WOLFSSL_X509* x509) + { + if (x509 == NULL) + return WOLFSSL_FAILURE; + return x509->pubKeyOID; + } + + + /* write X509 serial number in unsigned binary to buffer + buffer needs to be at least EXTERNAL_SERIAL_SIZE (32) for all cases + return WOLFSSL_SUCCESS on success */ + int wolfSSL_X509_get_serial_number(WOLFSSL_X509* x509, + byte* in, int* inOutSz) + { + WOLFSSL_ENTER("wolfSSL_X509_get_serial_number"); + if (x509 == NULL || in == NULL || + inOutSz == NULL || *inOutSz < x509->serialSz) + return BAD_FUNC_ARG; + + XMEMCPY(in, x509->serial, x509->serialSz); + *inOutSz = x509->serialSz; + + return WOLFSSL_SUCCESS; + } + + + const byte* wolfSSL_X509_get_der(WOLFSSL_X509* x509, int* outSz) + { + WOLFSSL_ENTER("wolfSSL_X509_get_der"); + + if (x509 == NULL || x509->derCert == NULL || outSz == NULL) + return NULL; + + *outSz = (int)x509->derCert->length; + return x509->derCert->buffer; + } + + + /* get the buffer to be signed (tbs) from the WOLFSSL_X509 certificate + * + * outSz : gets set to the size of the buffer + * returns a pointer to the internal buffer at the location of TBS on + * on success and NULL on failure. + */ + const unsigned char* wolfSSL_X509_get_tbs(WOLFSSL_X509* x509, int* outSz) + { + int sz = 0, len; + unsigned int idx = 0, tmpIdx; + const unsigned char* der = NULL; + const unsigned char* tbs = NULL; + + if (x509 == NULL || outSz == NULL) { + return NULL; + } + + der = wolfSSL_X509_get_der(x509, &sz); + if (der == NULL) { + return NULL; + } + + if (GetSequence(der, &idx, &len, sz) < 0) { + return NULL; + } + tbs = der + idx; + tmpIdx = idx; + if (GetSequence(der, &idx, &len, sz) < 0) { + return NULL; + } + *outSz = len + (idx - tmpIdx); + return tbs; + } + + int wolfSSL_X509_version(WOLFSSL_X509* x509) + { + WOLFSSL_ENTER("wolfSSL_X509_version"); + + if (x509 == NULL) + return 0; + + return x509->version; + } + + + const byte* wolfSSL_X509_notBefore(WOLFSSL_X509* x509) + { + WOLFSSL_ENTER("wolfSSL_X509_notBefore"); + + if (x509 == NULL) + return NULL; + + return x509->notBefore; + } + + + const byte* wolfSSL_X509_notAfter(WOLFSSL_X509* x509) + { + WOLFSSL_ENTER("wolfSSL_X509_notAfter"); + + if (x509 == NULL) + return NULL; + + return x509->notAfter; + } + + +#ifdef WOLFSSL_SEP + +/* copy oid into in buffer, at most *inOutSz bytes, if buffer is null will + malloc buffer, call responsible for freeing. Actual size returned in + *inOutSz. Requires inOutSz be non-null */ +byte* wolfSSL_X509_get_device_type(WOLFSSL_X509* x509, byte* in, int *inOutSz) +{ + int copySz; + + WOLFSSL_ENTER("wolfSSL_X509_get_dev_type"); + if (inOutSz == NULL) return NULL; + if (!x509->deviceTypeSz) return in; + + copySz = min(*inOutSz, x509->deviceTypeSz); + + if (!in) { + #ifdef WOLFSSL_STATIC_MEMORY + WOLFSSL_MSG("Using static memory -- please pass in a buffer"); + return NULL; + #else + in = (byte*)XMALLOC(x509->deviceTypeSz, 0, DYNAMIC_TYPE_OPENSSL); + if (!in) return in; + copySz = x509->deviceTypeSz; + #endif + } + + XMEMCPY(in, x509->deviceType, copySz); + *inOutSz = copySz; + + return in; +} + + +byte* wolfSSL_X509_get_hw_type(WOLFSSL_X509* x509, byte* in, int* inOutSz) +{ + int copySz; + + WOLFSSL_ENTER("wolfSSL_X509_get_hw_type"); + if (inOutSz == NULL) return NULL; + if (!x509->hwTypeSz) return in; + + copySz = min(*inOutSz, x509->hwTypeSz); + + if (!in) { + #ifdef WOLFSSL_STATIC_MEMORY + WOLFSSL_MSG("Using static memory -- please pass in a buffer"); + return NULL; + #else + in = (byte*)XMALLOC(x509->hwTypeSz, 0, DYNAMIC_TYPE_OPENSSL); + if (!in) return in; + copySz = x509->hwTypeSz; + #endif + } + + XMEMCPY(in, x509->hwType, copySz); + *inOutSz = copySz; + + return in; +} + + +byte* wolfSSL_X509_get_hw_serial_number(WOLFSSL_X509* x509,byte* in, + int* inOutSz) +{ + int copySz; + + WOLFSSL_ENTER("wolfSSL_X509_get_hw_serial_number"); + if (inOutSz == NULL) return NULL; + if (!x509->hwTypeSz) return in; + + copySz = min(*inOutSz, x509->hwSerialNumSz); + + if (!in) { + #ifdef WOLFSSL_STATIC_MEMORY + WOLFSSL_MSG("Using static memory -- please pass in a buffer"); + return NULL; + #else + in = (byte*)XMALLOC(x509->hwSerialNumSz, 0, DYNAMIC_TYPE_OPENSSL); + if (!in) return in; + copySz = x509->hwSerialNumSz; + #endif + } + + XMEMCPY(in, x509->hwSerialNum, copySz); + *inOutSz = copySz; + + return in; +} + +#endif /* WOLFSSL_SEP */ + +/* require OPENSSL_EXTRA since wolfSSL_X509_free is wrapped by OPENSSL_EXTRA */ +#if !defined(NO_CERTS) && defined(OPENSSL_EXTRA) +/* return 1 on success 0 on fail */ +int wolfSSL_sk_X509_push(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk, WOLFSSL_X509* x509) +{ + WOLFSSL_STACK* node; + + if (sk == NULL || x509 == NULL) { + return WOLFSSL_FAILURE; + } + + /* no previous values in stack */ + if (sk->data.x509 == NULL) { + sk->data.x509 = x509; + sk->num += 1; + return WOLFSSL_SUCCESS; + } + + /* stack already has value(s) create a new node and add more */ + node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL, + DYNAMIC_TYPE_X509); + if (node == NULL) { + WOLFSSL_MSG("Memory error"); + return WOLFSSL_FAILURE; + } + XMEMSET(node, 0, sizeof(WOLFSSL_STACK)); + + /* push new x509 onto head of stack */ + node->data.x509 = sk->data.x509; + node->next = sk->next; + sk->next = node; + sk->data.x509 = x509; + sk->num += 1; + + return WOLFSSL_SUCCESS; +} + + +WOLFSSL_X509* wolfSSL_sk_X509_pop(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk) { + WOLFSSL_STACK* node; + WOLFSSL_X509* x509; + + if (sk == NULL) { + return NULL; + } + + node = sk->next; + x509 = sk->data.x509; + + if (node != NULL) { /* update sk and remove node from stack */ + sk->data.x509 = node->data.x509; + sk->next = node->next; + XFREE(node, NULL, DYNAMIC_TYPE_X509); + } + else { /* last x509 in stack */ + sk->data.x509 = NULL; + } + + if (sk->num > 0) { + sk->num -= 1; + } + + return x509; +} + + +/* Getter function for WOLFSSL_X509_NAME pointer + * + * sk is the stack to retrieve pointer from + * i is the index value in stack + * + * returns a pointer to a WOLFSSL_X509_NAME structure on success and NULL on + * fail + */ +void* wolfSSL_sk_X509_NAME_value(const STACK_OF(WOLFSSL_X509_NAME)* sk, int i) +{ + WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_value"); + + for (; sk != NULL && i > 0; i--) + sk = sk->next; + + if (i != 0 || sk == NULL) + return NULL; + return sk->data.name; +} + + +/* Getter function for WOLFSSL_X509 pointer + * + * sk is the stack to retrieve pointer from + * i is the index value in stack + * + * returns a pointer to a WOLFSSL_X509 structure on success and NULL on + * fail + */ +void* wolfSSL_sk_X509_value(STACK_OF(WOLFSSL_X509)* sk, int i) +{ + WOLFSSL_ENTER("wolfSSL_sk_X509_value"); + + for (; sk != NULL && i > 0; i--) + sk = sk->next; + + if (i != 0 || sk == NULL) + return NULL; + return sk->data.x509; +} + + +/* Free's all nodes in X509 stack. This is different then wolfSSL_sk_X509_free + * in that it allows for choosing the function to use when freeing an X509s. + * + * sk stack to free nodes in + * f X509 free function + */ +void wolfSSL_sk_X509_pop_free(STACK_OF(WOLFSSL_X509)* sk, void f (WOLFSSL_X509*)){ + WOLFSSL_STACK* node; + + WOLFSSL_ENTER("wolfSSL_sk_X509_pop_free"); + + if (sk == NULL) { + return; + } + + /* parse through stack freeing each node */ + node = sk->next; + while (sk->num > 1) { + WOLFSSL_STACK* tmp = node; + node = node->next; + + f(tmp->data.x509); + XFREE(tmp, NULL, DYNAMIC_TYPE_X509); + sk->num -= 1; + } + + /* free head of stack */ + if (sk->num == 1) { + f(sk->data.x509); + } + XFREE(sk, NULL, DYNAMIC_TYPE_X509); +} + + +/* free structure for x509 stack */ +void wolfSSL_sk_X509_free(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk) { + WOLFSSL_STACK* node; + + if (sk == NULL) { + return; + } + + /* parse through stack freeing each node */ + node = sk->next; + while (sk->num > 1) { + WOLFSSL_STACK* tmp = node; + node = node->next; + + wolfSSL_X509_free(tmp->data.x509); + tmp->data.x509 = NULL; + XFREE(tmp, NULL, DYNAMIC_TYPE_X509); + sk->num -= 1; + } + + /* free head of stack */ + if (sk->num == 1) { + wolfSSL_X509_free(sk->data.x509); + sk->data.x509 = NULL; + } + XFREE(sk, NULL, DYNAMIC_TYPE_X509); +} + +#endif /* NO_CERTS && OPENSSL_EXTRA */ + +#ifdef OPENSSL_EXTRA + +/* Returns the general name at index i from the stack + * + * sk stack to get general name from + * i index to get + * + * return a pointer to the internal node of the stack + */ +WOLFSSL_ASN1_OBJECT* wolfSSL_sk_GENERAL_NAME_value(WOLFSSL_STACK* sk, int i) +{ + WOLFSSL_STACK* cur; + int j; + + WOLFSSL_ENTER("wolfSSL_sk_GENERAL_NAME_value"); + + if (i < 0 || sk == NULL) { + return NULL; + } + + cur = sk; + for (j = 0; j < i && cur != NULL; j++) { + cur = cur->next; + } + + if (cur == NULL) { + return NULL; + } + + return cur->data.obj; +} + + +/* Gets the number of nodes in the stack + * + * sk stack to get the number of nodes from + * + * returns the number of nodes, -1 if no nodes + */ +int wolfSSL_sk_GENERAL_NAME_num(WOLFSSL_STACK* sk) +{ + WOLFSSL_ENTER("wolfSSL_sk_GENERAL_NAME_num"); + + if (sk == NULL) { + return -1; + } + + return (int)sk->num; +} + +/* Frees all nodes in a GENERAL NAME stack + * + * sk stack of nodes to free + * f free function to use, not called with wolfSSL + */ +void wolfSSL_sk_GENERAL_NAME_pop_free(WOLFSSL_STACK* sk, + void f (WOLFSSL_ASN1_OBJECT*)) +{ + WOLFSSL_STACK* node; + + WOLFSSL_ENTER("wolfSSL_sk_GENERAL_NAME_pop_free"); + + (void)f; + if (sk == NULL) { + return; + } + + /* parse through stack freeing each node */ + node = sk->next; + while (sk->num > 1) { + WOLFSSL_STACK* tmp = node; + node = node->next; + + wolfSSL_ASN1_OBJECT_free(tmp->data.obj); + XFREE(tmp, NULL, DYNAMIC_TYPE_ASN1); + sk->num -= 1; + } + + /* free head of stack */ + if (sk->num == 1) { + wolfSSL_ASN1_OBJECT_free(sk->data.obj); + } + XFREE(sk, NULL, DYNAMIC_TYPE_ASN1); + + +} +#endif /* OPENSSL_EXTRA */ + +#ifndef NO_FILESYSTEM + +#ifndef NO_STDIO_FILESYSTEM + +WOLFSSL_X509* wolfSSL_X509_d2i_fp(WOLFSSL_X509** x509, XFILE file) +{ + WOLFSSL_X509* newX509 = NULL; + + WOLFSSL_ENTER("wolfSSL_X509_d2i_fp"); + + if (file != XBADFILE) { + byte* fileBuffer = NULL; + long sz = 0; + + if(XFSEEK(file, 0, XSEEK_END) != 0) + return NULL; + sz = XFTELL(file); + XREWIND(file); + + if (sz < 0) { + WOLFSSL_MSG("Bad tell on FILE"); + return NULL; + } + + fileBuffer = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE); + if (fileBuffer != NULL) { + int ret = (int)XFREAD(fileBuffer, 1, sz, file); + if (ret == sz) { + newX509 = wolfSSL_X509_d2i(NULL, fileBuffer, (int)sz); + } + XFREE(fileBuffer, NULL, DYNAMIC_TYPE_FILE); + } + } + + if (x509 != NULL) + *x509 = newX509; + + return newX509; +} + +#endif /* NO_STDIO_FILESYSTEM */ + +WOLFSSL_X509* wolfSSL_X509_load_certificate_file(const char* fname, int format) +{ +#ifdef WOLFSSL_SMALL_STACK + byte staticBuffer[1]; /* force heap usage */ +#else + byte staticBuffer[FILE_BUFFER_SIZE]; +#endif + byte* fileBuffer = staticBuffer; + int dynamic = 0; + int ret; + long sz = 0; + XFILE file; + + WOLFSSL_X509* x509 = NULL; + + /* Check the inputs */ + if ((fname == NULL) || + (format != WOLFSSL_FILETYPE_ASN1 && format != WOLFSSL_FILETYPE_PEM)) + return NULL; + + file = XFOPEN(fname, "rb"); + if (file == XBADFILE) + return NULL; + + if(XFSEEK(file, 0, XSEEK_END) != 0){ + XFCLOSE(file); + return NULL; + } + sz = XFTELL(file); + XREWIND(file); + + if (sz > (long)sizeof(staticBuffer)) { + fileBuffer = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE); + if (fileBuffer == NULL) { + XFCLOSE(file); + return NULL; + } + dynamic = 1; + } + else if (sz < 0) { + XFCLOSE(file); + return NULL; + } + + ret = (int)XFREAD(fileBuffer, 1, sz, file); + if (ret != sz) { + XFCLOSE(file); + if (dynamic) + XFREE(fileBuffer, NULL, DYNAMIC_TYPE_FILE); + return NULL; + } + + XFCLOSE(file); + + x509 = wolfSSL_X509_load_certificate_buffer(fileBuffer, (int)sz, format); + + if (dynamic) + XFREE(fileBuffer, NULL, DYNAMIC_TYPE_FILE); + + return x509; +} + +#endif /* NO_FILESYSTEM */ + + +WOLFSSL_X509* wolfSSL_X509_load_certificate_buffer( + const unsigned char* buf, int sz, int format) +{ + int ret; + WOLFSSL_X509* x509 = NULL; + DerBuffer* der = NULL; + + WOLFSSL_ENTER("wolfSSL_X509_load_certificate_ex"); + + if (format == WOLFSSL_FILETYPE_PEM) { + #ifdef WOLFSSL_PEM_TO_DER + if (PemToDer(buf, sz, CERT_TYPE, &der, NULL, NULL, NULL) != 0) { + FreeDer(&der); + } + #else + ret = NOT_COMPILED_IN; + #endif + } + else { + ret = AllocDer(&der, (word32)sz, CERT_TYPE, NULL); + if (ret == 0) { + XMEMCPY(der->buffer, buf, sz); + } + } + + /* At this point we want `der` to have the certificate in DER format */ + /* ready to be decoded. */ + if (der != NULL && der->buffer != NULL) { + #ifdef WOLFSSL_SMALL_STACK + DecodedCert* cert = NULL; + #else + DecodedCert cert[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, + DYNAMIC_TYPE_DCERT); + if (cert != NULL) + #endif + { + InitDecodedCert(cert, der->buffer, der->length, NULL); + if (ParseCertRelative(cert, CERT_TYPE, 0, NULL) == 0) { + x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), NULL, + DYNAMIC_TYPE_X509); + if (x509 != NULL) { + InitX509(x509, 1, NULL); + if (CopyDecodedToX509(x509, cert) != 0) { + wolfSSL_X509_free(x509); + x509 = NULL; + } + } + } + + FreeDecodedCert(cert); + #ifdef WOLFSSL_SMALL_STACK + XFREE(cert, NULL, DYNAMIC_TYPE_DCERT); + #endif + } + + FreeDer(&der); + } + + return x509; +} + +#endif /* KEEP_PEER_CERT || SESSION_CERTS */ + +/* OPENSSL_EXTRA is needed for wolfSSL_X509_d21 function + KEEP_OUR_CERT is to insure ability for returning ssl certificate */ +#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \ + defined(KEEP_OUR_CERT) +WOLFSSL_X509* wolfSSL_get_certificate(WOLFSSL* ssl) +{ + if (ssl == NULL) { + return NULL; + } + + if (ssl->buffers.weOwnCert) { + if (ssl->ourCert == NULL) { + if (ssl->buffers.certificate == NULL) { + WOLFSSL_MSG("Certificate buffer not set!"); + return NULL; + } + #ifndef WOLFSSL_X509_STORE_CERTS + ssl->ourCert = wolfSSL_X509_d2i(NULL, + ssl->buffers.certificate->buffer, + ssl->buffers.certificate->length); + #endif + } + return ssl->ourCert; + } + else { /* if cert not owned get parent ctx cert or return null */ + if (ssl->ctx) { + if (ssl->ctx->ourCert == NULL) { + if (ssl->ctx->certificate == NULL) { + WOLFSSL_MSG("Ctx Certificate buffer not set!"); + return NULL; + } + #ifndef WOLFSSL_X509_STORE_CERTS + ssl->ctx->ourCert = wolfSSL_X509_d2i(NULL, + ssl->ctx->certificate->buffer, + ssl->ctx->certificate->length); + #endif + ssl->ctx->ownOurCert = 1; + } + return ssl->ctx->ourCert; + } + } + + return NULL; +} +#endif /* OPENSSL_EXTRA && KEEP_OUR_CERT */ +#endif /* NO_CERTS */ + + +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) +#ifndef NO_ASN +void wolfSSL_ASN1_OBJECT_free(WOLFSSL_ASN1_OBJECT* obj) +{ + if (obj == NULL) { + return; + } + + if ((obj->obj != NULL) && ((obj->dynamic & WOLFSSL_ASN1_DYNAMIC_DATA) != 0)) { + WOLFSSL_MSG("Freeing ASN1 data"); + XFREE((void*)obj->obj, obj->heap, DYNAMIC_TYPE_ASN1); + obj->obj = NULL; + + } + if ((obj->dynamic & WOLFSSL_ASN1_DYNAMIC) != 0) { + WOLFSSL_MSG("Freeing ASN1 OBJECT"); + XFREE(obj, NULL, DYNAMIC_TYPE_ASN1); + } +} +#endif /* NO_ASN */ +#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ + +#ifdef OPENSSL_EXTRA +#ifndef NO_ASN +WOLFSSL_ASN1_OBJECT* wolfSSL_ASN1_OBJECT_new(void) +{ + WOLFSSL_ASN1_OBJECT* obj; + + obj = (WOLFSSL_ASN1_OBJECT*)XMALLOC(sizeof(WOLFSSL_ASN1_OBJECT), NULL, + DYNAMIC_TYPE_ASN1); + if (obj == NULL) { + return NULL; + } + + XMEMSET(obj, 0, sizeof(WOLFSSL_ASN1_OBJECT)); + obj->d.ia5 = &(obj->d.ia5_internal); + obj->dynamic |= WOLFSSL_ASN1_DYNAMIC; + return obj; +} +#endif /* NO_ASN */ + + +/* return 1 on success 0 on fail */ +int wolfSSL_sk_ASN1_OBJECT_push(WOLF_STACK_OF(WOLFSSL_ASN1_OBJEXT)* sk, + WOLFSSL_ASN1_OBJECT* obj) +{ + WOLFSSL_STACK* node; + + if (sk == NULL || obj == NULL) { + return WOLFSSL_FAILURE; + } + + /* no previous values in stack */ + if (sk->data.obj == NULL) { + sk->data.obj = obj; + sk->num += 1; + return WOLFSSL_SUCCESS; + } + + /* stack already has value(s) create a new node and add more */ + node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL, + DYNAMIC_TYPE_ASN1); + if (node == NULL) { + WOLFSSL_MSG("Memory error"); + return WOLFSSL_FAILURE; + } + XMEMSET(node, 0, sizeof(WOLFSSL_STACK)); + + /* push new obj onto head of stack */ + node->data.obj = sk->data.obj; + node->next = sk->next; + sk->next = node; + sk->data.obj = obj; + sk->num += 1; + + return WOLFSSL_SUCCESS; +} + + +WOLFSSL_ASN1_OBJECT* wolfSSL_sk_ASN1_OBJECT_pop( + WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk) +{ + WOLFSSL_STACK* node; + WOLFSSL_ASN1_OBJECT* obj; + + if (sk == NULL) { + return NULL; + } + + node = sk->next; + obj = sk->data.obj; + + if (node != NULL) { /* update sk and remove node from stack */ + sk->data.obj = node->data.obj; + sk->next = node->next; + XFREE(node, NULL, DYNAMIC_TYPE_ASN1); + } + else { /* last obj in stack */ + sk->data.obj = NULL; + } + + if (sk->num > 0) { + sk->num -= 1; + } + + return obj; +} + + +#ifndef NO_ASN +/* free structure for x509 stack */ +void wolfSSL_sk_ASN1_OBJECT_free(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk) +{ + WOLFSSL_STACK* node; + + if (sk == NULL) { + return; + } + + /* parse through stack freeing each node */ + node = sk->next; + while (sk->num > 1) { + WOLFSSL_STACK* tmp = node; + node = node->next; + + wolfSSL_ASN1_OBJECT_free(tmp->data.obj); + XFREE(tmp, NULL, DYNAMIC_TYPE_ASN1); + sk->num -= 1; + } + + /* free head of stack */ + if (sk->num == 1) { + wolfSSL_ASN1_OBJECT_free(sk->data.obj); + } + XFREE(sk, NULL, DYNAMIC_TYPE_ASN1); +} + +int wolfSSL_ASN1_STRING_to_UTF8(unsigned char **out, WOLFSSL_ASN1_STRING *in) +{ + /* + ASN1_STRING_to_UTF8() converts the string in to UTF8 format, + the converted data is allocated in a buffer in *out. + The length of out is returned or a negative error code. + The buffer *out should be free using OPENSSL_free(). + */ + (void)out; + (void)in; + WOLFSSL_STUB("ASN1_STRING_to_UTF8"); + return -1; +} +#endif /* NO_ASN */ + +void wolfSSL_set_connect_state(WOLFSSL* ssl) +{ + if (ssl == NULL) { + WOLFSSL_MSG("WOLFSSL struct pointer passed in was null"); + return; + } + + #ifndef NO_DH + /* client creates its own DH parameters on handshake */ + if (ssl->buffers.serverDH_P.buffer && ssl->buffers.weOwnDH) { + XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, + DYNAMIC_TYPE_PUBLIC_KEY); + } + ssl->buffers.serverDH_P.buffer = NULL; + if (ssl->buffers.serverDH_G.buffer && ssl->buffers.weOwnDH) { + XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, + DYNAMIC_TYPE_PUBLIC_KEY); + } + ssl->buffers.serverDH_G.buffer = NULL; + #endif + + if (InitSSL_Side(ssl, WOLFSSL_CLIENT_END) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Error initializing client side"); + } +} +#endif /* OPENSSL_EXTRA */ + + +int wolfSSL_get_shutdown(const WOLFSSL* ssl) +{ + int isShutdown = 0; + + WOLFSSL_ENTER("wolfSSL_get_shutdown"); + + if (ssl) { + /* in OpenSSL, WOLFSSL_SENT_SHUTDOWN = 1, when closeNotifySent * + * WOLFSSL_RECEIVED_SHUTDOWN = 2, from close notify or fatal err */ + isShutdown = ((ssl->options.closeNotify||ssl->options.connReset) << 1) + | (ssl->options.sentNotify); + } + return isShutdown; +} + + +int wolfSSL_session_reused(WOLFSSL* ssl) +{ + int resuming = 0; + if (ssl) + resuming = ssl->options.resuming; + return resuming; +} + +#if defined(OPENSSL_EXTRA) || defined(HAVE_EXT_CACHE) +void wolfSSL_SESSION_free(WOLFSSL_SESSION* session) +{ + if (session == NULL) + return; + +#ifdef HAVE_EXT_CACHE + if (session->isAlloced) { + #ifdef HAVE_SESSION_TICKET + if (session->isDynamic) + XFREE(session->ticket, NULL, DYNAMIC_TYPE_SESSION_TICK); + #endif + XFREE(session, NULL, DYNAMIC_TYPE_OPENSSL); + } +#else + /* No need to free since cache is static */ + (void)session; +#endif +} +#endif + +const char* wolfSSL_get_version(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("SSL_get_version"); + if (ssl->version.major == SSLv3_MAJOR) { + switch (ssl->version.minor) { + #ifndef NO_OLD_TLS + #ifdef WOLFSSL_ALLOW_SSLV3 + case SSLv3_MINOR : + return "SSLv3"; + #endif + #ifdef WOLFSSL_ALLOW_TLSV10 + case TLSv1_MINOR : + return "TLSv1"; + #endif + case TLSv1_1_MINOR : + return "TLSv1.1"; + #endif + case TLSv1_2_MINOR : + return "TLSv1.2"; + #ifdef WOLFSSL_TLS13 + case TLSv1_3_MINOR : + #ifdef WOLFSSL_TLS13_DRAFT + #ifdef WOLFSSL_TLS13_DRAFT_18 + return "TLSv1.3 (Draft 18)"; + #elif defined(WOLFSSL_TLS13_DRAFT_22) + return "TLSv1.3 (Draft 22)"; + #elif defined(WOLFSSL_TLS13_DRAFT_23) + return "TLSv1.3 (Draft 23)"; + #elif defined(WOLFSSL_TLS13_DRAFT_26) + return "TLSv1.3 (Draft 26)"; + #else + return "TLSv1.3 (Draft 28)"; + #endif + #else + return "TLSv1.3"; + #endif + #endif + default: + return "unknown"; + } + } +#ifdef WOLFSSL_DTLS + else if (ssl->version.major == DTLS_MAJOR) { + switch (ssl->version.minor) { + case DTLS_MINOR : + return "DTLS"; + case DTLSv1_2_MINOR : + return "DTLSv1.2"; + default: + return "unknown"; + } + } +#endif /* WOLFSSL_DTLS */ + return "unknown"; +} + + +/* current library version */ +const char* wolfSSL_lib_version(void) +{ + return LIBWOLFSSL_VERSION_STRING; +} + + +/* current library version in hex */ +word32 wolfSSL_lib_version_hex(void) +{ + return LIBWOLFSSL_VERSION_HEX; +} + + +int wolfSSL_get_current_cipher_suite(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("SSL_get_current_cipher_suite"); + if (ssl) + return (ssl->options.cipherSuite0 << 8) | ssl->options.cipherSuite; + return 0; +} + +WOLFSSL_CIPHER* wolfSSL_get_current_cipher(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("SSL_get_current_cipher"); + if (ssl) + return &ssl->cipher; + else + return NULL; +} + + +const char* wolfSSL_CIPHER_get_name(const WOLFSSL_CIPHER* cipher) +{ + WOLFSSL_ENTER("SSL_CIPHER_get_name"); + + if (cipher == NULL || cipher->ssl == NULL) { + return NULL; + } + + #if !defined(WOLFSSL_CIPHER_INTERNALNAME) && !defined(NO_ERROR_STRINGS) + return wolfSSL_get_cipher_name_iana(cipher->ssl); + #else + return wolfSSL_get_cipher_name_internal(cipher->ssl); + #endif +} + +const char* wolfSSL_SESSION_CIPHER_get_name(WOLFSSL_SESSION* session) +{ + if (session == NULL) { + return NULL; + } + +#ifdef SESSION_CERTS + #if !defined(WOLFSSL_CIPHER_INTERNALNAME) && !defined(NO_ERROR_STRINGS) + return GetCipherNameIana(session->cipherSuite0, session->cipherSuite); + #else + return GetCipherNameInternal(session->cipherSuite0, session->cipherSuite); + #endif +#else + return NULL; +#endif +} + +const char* wolfSSL_get_cipher(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_get_cipher"); + return wolfSSL_CIPHER_get_name(wolfSSL_get_current_cipher(ssl)); +} + +/* gets cipher name in the format DHE-RSA-... rather then TLS_DHE... */ +const char* wolfSSL_get_cipher_name(WOLFSSL* ssl) +{ + /* get access to cipher_name_idx in internal.c */ + return wolfSSL_get_cipher_name_internal(ssl); +} + +const char* wolfSSL_get_cipher_name_from_suite(const byte cipherSuite0, + const byte cipherSuite) +{ + return GetCipherNameInternal(cipherSuite0, cipherSuite); +} + + +#if defined(HAVE_ECC) || !defined(NO_DH) +#ifdef HAVE_FFDHE +static const char* wolfssl_ffdhe_name(word16 group) +{ + const char* str = NULL; + switch (group) { + case WOLFSSL_FFDHE_2048: + str = "FFDHE_2048"; + break; + case WOLFSSL_FFDHE_3072: + str = "FFDHE_3072"; + break; + case WOLFSSL_FFDHE_4096: + str = "FFDHE_4096"; + break; + case WOLFSSL_FFDHE_6144: + str = "FFDHE_6144"; + break; + case WOLFSSL_FFDHE_8192: + str = "FFDHE_8192"; + break; + } + return str; +} +#endif +/* Return the name of the curve used for key exchange as a printable string. + * + * ssl The SSL/TLS object. + * returns NULL if ECDH was not used, otherwise the name as a string. + */ +const char* wolfSSL_get_curve_name(WOLFSSL* ssl) +{ + const char* cName = NULL; + + if (ssl == NULL) + return NULL; + +#ifdef HAVE_FFDHE + if (ssl->namedGroup != 0) { + cName = wolfssl_ffdhe_name(ssl->namedGroup); + } +#endif + +#ifdef HAVE_CURVE25519 + if (ssl->ecdhCurveOID == ECC_X25519_OID && cName == NULL) { + cName = "X25519"; + } +#endif + +#ifdef HAVE_ECC + if (ssl->ecdhCurveOID != 0 && cName == NULL) { + cName = wc_ecc_get_name(wc_ecc_get_oid(ssl->ecdhCurveOID, NULL, + NULL)); + } +#endif + + return cName; +} +#endif + + +#if defined(OPENSSL_EXTRA_X509_SMALL) || defined(KEEP_PEER_CERT) || \ + defined(SESSION_CERTS) +/* Smaller subset of X509 compatibility functions. Avoid increasing the size of + * this subset and its memory usage */ + +#if !defined(NO_CERTS) +/* returns a pointer to a new WOLFSSL_X509 structure on success and NULL on + * fail + */ +WOLFSSL_X509* wolfSSL_X509_new(void) +{ + WOLFSSL_X509* x509; + + x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), NULL, + DYNAMIC_TYPE_X509); + if (x509 != NULL) { + InitX509(x509, 1, NULL); + } + + return x509; +} + +WOLFSSL_X509_NAME* wolfSSL_X509_get_subject_name(WOLFSSL_X509* cert) +{ + WOLFSSL_ENTER("wolfSSL_X509_get_subject_name"); + if (cert && cert->subject.sz != 0) + return &cert->subject; + return NULL; +} + + + +WOLFSSL_X509_NAME* wolfSSL_X509_get_issuer_name(WOLFSSL_X509* cert) +{ + WOLFSSL_ENTER("X509_get_issuer_name"); + if (cert && cert->issuer.sz != 0) + return &cert->issuer; + return NULL; +} + + +int wolfSSL_X509_get_signature_type(WOLFSSL_X509* x509) +{ + int type = 0; + + WOLFSSL_ENTER("wolfSSL_X509_get_signature_type"); + + if (x509 != NULL) + type = x509->sigOID; + + return type; +} + +#if defined(OPENSSL_EXTRA_X509_SMALL) +#ifdef HAVE_ECC + static int SetECKeyExternal(WOLFSSL_EC_KEY* eckey); +#endif + +/* Used to get a string from the WOLFSSL_X509_NAME structure that + * corresponds with the NID value passed in. + * + * name structure to get string from + * nid NID value to search for + * buf [out] buffer to hold results. If NULL then the buffer size minus the + * null char is returned. + * len size of "buf" passed in + * + * returns the length of string found, not including the NULL terminator. + * It's possible the function could return a negative value in the + * case that len is less than or equal to 0. A negative value is + * considered an error case. + */ +int wolfSSL_X509_NAME_get_text_by_NID(WOLFSSL_X509_NAME* name, + int nid, char* buf, int len) +{ + char *text = NULL; + int textSz = 0; + + WOLFSSL_ENTER("wolfSSL_X509_NAME_get_text_by_NID"); + + switch (nid) { + case ASN_COMMON_NAME: + text = name->fullName.fullName + name->fullName.cnIdx; + textSz = name->fullName.cnLen; + break; + case ASN_SUR_NAME: + text = name->fullName.fullName + name->fullName.snIdx; + textSz = name->fullName.snLen; + break; + case ASN_SERIAL_NUMBER: + text = name->fullName.fullName + name->fullName.serialIdx; + textSz = name->fullName.serialLen; + break; + case ASN_COUNTRY_NAME: + text = name->fullName.fullName + name->fullName.cIdx; + textSz = name->fullName.cLen; + break; + case ASN_LOCALITY_NAME: + text = name->fullName.fullName + name->fullName.lIdx; + textSz = name->fullName.lLen; + break; + case ASN_STATE_NAME: + text = name->fullName.fullName + name->fullName.stIdx; + textSz = name->fullName.stLen; + break; + case ASN_ORG_NAME: + text = name->fullName.fullName + name->fullName.oIdx; + textSz = name->fullName.oLen; + break; + case ASN_ORGUNIT_NAME: + text = name->fullName.fullName + name->fullName.ouIdx; + textSz = name->fullName.ouLen; + break; + case ASN_DOMAIN_COMPONENT: + text = name->fullName.fullName + name->fullName.dcIdx[0]; + textSz = name->fullName.dcLen[0]; + break; + #ifdef WOLFSSL_CERT_EXT + case ASN_BUS_CAT: + text = name->fullName.fullName + name->fullName.bcIdx; + textSz = name->fullName.bcLen; + break; + #endif + default: + WOLFSSL_MSG("Entry type not found"); + return SSL_FATAL_ERROR; + } + + /* if buf is NULL return size of buffer needed (minus null char) */ + if (buf == NULL) { + return textSz; + } + + if (buf != NULL && text != NULL) { + textSz = min(textSz + 1, len); /* + 1 to account for null char */ + if (textSz > 0) { + XMEMCPY(buf, text, textSz - 1); + buf[textSz - 1] = '\0'; + } + } + + WOLFSSL_LEAVE("wolfSSL_X509_NAME_get_text_by_NID", textSz); + return (textSz - 1); /* do not include null character in size */ +} + + +/* Creates a new WOLFSSL_EVP_PKEY structure that has the public key from x509 + * + * returns a pointer to the created WOLFSSL_EVP_PKEY on success and NULL on fail + */ +WOLFSSL_EVP_PKEY* wolfSSL_X509_get_pubkey(WOLFSSL_X509* x509) +{ + WOLFSSL_EVP_PKEY* key = NULL; + WOLFSSL_ENTER("X509_get_pubkey"); + if (x509 != NULL) { + key = (WOLFSSL_EVP_PKEY*)XMALLOC( + sizeof(WOLFSSL_EVP_PKEY), x509->heap, + DYNAMIC_TYPE_PUBLIC_KEY); + if (key != NULL) { + XMEMSET(key, 0, sizeof(WOLFSSL_EVP_PKEY)); + if (x509->pubKeyOID == RSAk) { + key->type = EVP_PKEY_RSA; + } + else { + key->type = EVP_PKEY_EC; + } + key->save_type = 0; + key->pkey.ptr = (char*)XMALLOC( + x509->pubKey.length, x509->heap, + DYNAMIC_TYPE_PUBLIC_KEY); + if (key->pkey.ptr == NULL) { + XFREE(key, x509->heap, DYNAMIC_TYPE_PUBLIC_KEY); + return NULL; + } + XMEMCPY(key->pkey.ptr, x509->pubKey.buffer, x509->pubKey.length); + key->pkey_sz = x509->pubKey.length; + + #ifdef HAVE_ECC + key->pkey_curve = (int)x509->pkCurveOID; + #endif /* HAVE_ECC */ + + /* decode RSA key */ + #ifndef NO_RSA + if (key->type == EVP_PKEY_RSA) { + key->ownRsa = 1; + key->rsa = wolfSSL_RSA_new(); + if (key->rsa == NULL) { + XFREE(key, x509->heap, DYNAMIC_TYPE_PUBLIC_KEY); + return NULL; + } + + if (wolfSSL_RSA_LoadDer_ex(key->rsa, + (const unsigned char*)key->pkey.ptr, key->pkey_sz, + WOLFSSL_RSA_LOAD_PUBLIC) != SSL_SUCCESS) { + wolfSSL_RSA_free(key->rsa); + key->rsa = NULL; + XFREE(key, x509->heap, DYNAMIC_TYPE_PUBLIC_KEY); + return NULL; + } + } + #endif /* NO_RSA */ + + /* decode ECC key */ + #ifdef HAVE_ECC + if (key->type == EVP_PKEY_EC) { + word32 idx = 0; + + key->ownEcc = 1; + key->ecc = wolfSSL_EC_KEY_new(); + if (key->ecc == NULL || key->ecc->internal == NULL) { + XFREE(key, x509->heap, DYNAMIC_TYPE_PUBLIC_KEY); + return NULL; + } + + /* not using wolfSSL_EC_KEY_LoadDer because public key in x509 + * is in the format of x963 (no sequence at start of buffer) */ + if (wc_EccPublicKeyDecode((const unsigned char*)key->pkey.ptr, + &idx, (ecc_key*)key->ecc->internal, key->pkey_sz) < 0) { + WOLFSSL_MSG("wc_EccPublicKeyDecode failed"); + wolfSSL_EC_KEY_free(key->ecc); + key->ecc = NULL; + XFREE(key, x509->heap, DYNAMIC_TYPE_PUBLIC_KEY); + return NULL; + } + + if (SetECKeyExternal(key->ecc) != SSL_SUCCESS) { + WOLFSSL_MSG("SetECKeyExternal failed"); + wolfSSL_EC_KEY_free(key->ecc); + key->ecc = NULL; + XFREE(key, x509->heap, DYNAMIC_TYPE_PUBLIC_KEY); + return NULL; + } + + key->ecc->inSet = 1; + } + #endif /* HAVE_ECC */ + } + } + return key; +} +#endif /* OPENSSL_EXTRA_X509_SMALL */ +#endif /* !NO_CERTS */ + +/* End of smaller subset of X509 compatibility functions. Avoid increasing the + * size of this subset and its memory usage */ +#endif /* OPENSSL_EXTRA_X509_SMALL */ + +#if defined(OPENSSL_EXTRA) +#if !defined(NO_CERTS) + int wolfSSL_X509_ext_isSet_by_NID(WOLFSSL_X509* x509, int nid) + { + int isSet = 0; + + WOLFSSL_ENTER("wolfSSL_X509_ext_isSet_by_NID"); + + if (x509 != NULL) { + switch (nid) { + case BASIC_CA_OID: isSet = x509->basicConstSet; break; + case ALT_NAMES_OID: isSet = x509->subjAltNameSet; break; + case AUTH_KEY_OID: isSet = x509->authKeyIdSet; break; + case SUBJ_KEY_OID: isSet = x509->subjKeyIdSet; break; + case KEY_USAGE_OID: isSet = x509->keyUsageSet; break; + case CRL_DIST_OID: isSet = x509->CRLdistSet; break; + #ifdef WOLFSSL_SEP + case CERT_POLICY_OID: isSet = x509->certPolicySet; break; + #endif /* WOLFSSL_SEP */ + } + } + + WOLFSSL_LEAVE("wolfSSL_X509_ext_isSet_by_NID", isSet); + + return isSet; + } + + + int wolfSSL_X509_ext_get_critical_by_NID(WOLFSSL_X509* x509, int nid) + { + int crit = 0; + + WOLFSSL_ENTER("wolfSSL_X509_ext_get_critical_by_NID"); + + if (x509 != NULL) { + switch (nid) { + case BASIC_CA_OID: crit = x509->basicConstCrit; break; + case ALT_NAMES_OID: crit = x509->subjAltNameCrit; break; + case AUTH_KEY_OID: crit = x509->authKeyIdCrit; break; + case SUBJ_KEY_OID: crit = x509->subjKeyIdCrit; break; + case KEY_USAGE_OID: crit = x509->keyUsageCrit; break; + case CRL_DIST_OID: crit= x509->CRLdistCrit; break; + #ifdef WOLFSSL_SEP + case CERT_POLICY_OID: crit = x509->certPolicyCrit; break; + #endif /* WOLFSSL_SEP */ + } + } + + WOLFSSL_LEAVE("wolfSSL_X509_ext_get_critical_by_NID", crit); + + return crit; + } + + + int wolfSSL_X509_get_isSet_pathLength(WOLFSSL_X509* x509) + { + int isSet = 0; + + WOLFSSL_ENTER("wolfSSL_X509_get_isSet_pathLength"); + + if (x509 != NULL) + isSet = x509->basicConstPlSet; + + WOLFSSL_LEAVE("wolfSSL_X509_get_isSet_pathLength", isSet); + + return isSet; + } + + + word32 wolfSSL_X509_get_pathLength(WOLFSSL_X509* x509) + { + word32 pathLength = 0; + + WOLFSSL_ENTER("wolfSSL_X509_get_pathLength"); + + if (x509 != NULL) + pathLength = x509->pathLength; + + WOLFSSL_LEAVE("wolfSSL_X509_get_pathLength", pathLength); + + return pathLength; + } + + + unsigned int wolfSSL_X509_get_keyUsage(WOLFSSL_X509* x509) + { + word16 usage = 0; + + WOLFSSL_ENTER("wolfSSL_X509_get_keyUsage"); + + if (x509 != NULL) + usage = x509->keyUsage; + + WOLFSSL_LEAVE("wolfSSL_X509_get_keyUsage", usage); + + return usage; + } + + + byte* wolfSSL_X509_get_authorityKeyID(WOLFSSL_X509* x509, + byte* dst, int* dstLen) + { + byte *id = NULL; + int copySz = 0; + + WOLFSSL_ENTER("wolfSSL_X509_get_authorityKeyID"); + + if (x509 != NULL) { + if (x509->authKeyIdSet) { + copySz = min(dstLen != NULL ? *dstLen : 0, + (int)x509->authKeyIdSz); + id = x509->authKeyId; + } + + if (dst != NULL && dstLen != NULL && id != NULL && copySz > 0) { + XMEMCPY(dst, id, copySz); + id = dst; + *dstLen = copySz; + } + } + + WOLFSSL_LEAVE("wolfSSL_X509_get_authorityKeyID", copySz); + + return id; + } + + + byte* wolfSSL_X509_get_subjectKeyID(WOLFSSL_X509* x509, + byte* dst, int* dstLen) + { + byte *id = NULL; + int copySz = 0; + + WOLFSSL_ENTER("wolfSSL_X509_get_subjectKeyID"); + + if (x509 != NULL) { + if (x509->subjKeyIdSet) { + copySz = min(dstLen != NULL ? *dstLen : 0, + (int)x509->subjKeyIdSz); + id = x509->subjKeyId; + } + + if (dst != NULL && dstLen != NULL && id != NULL && copySz > 0) { + XMEMCPY(dst, id, copySz); + id = dst; + *dstLen = copySz; + } + } + + WOLFSSL_LEAVE("wolfSSL_X509_get_subjectKeyID", copySz); + + return id; + } + + + int wolfSSL_X509_NAME_entry_count(WOLFSSL_X509_NAME* name) + { + int count = 0; + + WOLFSSL_ENTER("wolfSSL_X509_NAME_entry_count"); + + if (name != NULL) + count = name->fullName.entryCount; + + WOLFSSL_LEAVE("wolfSSL_X509_NAME_entry_count", count); + return count; + } + + + + int wolfSSL_X509_NAME_get_index_by_NID(WOLFSSL_X509_NAME* name, + int nid, int pos) + { + int value = nid, i; + + WOLFSSL_ENTER("wolfSSL_X509_NAME_get_index_by_NID"); + + if (name == NULL || pos >= DN_NAMES_MAX + DOMAIN_COMPONENT_MAX) { + return BAD_FUNC_ARG; + } + + if (value == NID_emailAddress) { + value = ASN_EMAIL_NAME; + } + + i = pos + 1; /* start search after index passed in */ + if (i < 0) { + i = 0; + } + + for (;i < name->fullName.locSz && + i < DN_NAMES_MAX + DOMAIN_COMPONENT_MAX; i++) { + if (name->fullName.loc[i] == value) { + return i; + } + } + return WOLFSSL_FATAL_ERROR; + } + + + WOLFSSL_ASN1_STRING* wolfSSL_X509_NAME_ENTRY_get_data( + WOLFSSL_X509_NAME_ENTRY* in) + { + WOLFSSL_ENTER("wolfSSL_X509_NAME_ENTRY_get_data"); + if (in == NULL) + return NULL; + + return in->value; + } + + + /* Creates a new WOLFSSL_ASN1_STRING structure. + * + * returns a pointer to the new structure created on success or NULL if fail + */ + WOLFSSL_ASN1_STRING* wolfSSL_ASN1_STRING_new(void) + { + WOLFSSL_ASN1_STRING* asn1; + + WOLFSSL_ENTER("wolfSSL_ASN1_STRING_new"); + + asn1 = (WOLFSSL_ASN1_STRING*)XMALLOC(sizeof(WOLFSSL_ASN1_STRING), NULL, + DYNAMIC_TYPE_OPENSSL); + if (asn1 != NULL) { + XMEMSET(asn1, 0, sizeof(WOLFSSL_ASN1_STRING)); + } + + return asn1; /* no check for null because error case is returning null*/ + } + + + /* used to free a WOLFSSL_ASN1_STRING structure */ + void wolfSSL_ASN1_STRING_free(WOLFSSL_ASN1_STRING* asn1) + { + WOLFSSL_ENTER("wolfSSL_ASN1_STRING_free"); + + if (asn1 != NULL) { + if (asn1->length > 0 && asn1->data != NULL && asn1->isDynamic) { + XFREE(asn1->data, NULL, DYNAMIC_TYPE_OPENSSL); + } + XFREE(asn1, NULL, DYNAMIC_TYPE_OPENSSL); + } + } + + + /* Creates a new WOLFSSL_ASN1_STRING structure given the input type. + * + * type is the type of set when WOLFSSL_ASN1_STRING is created + * + * returns a pointer to the new structure created on success or NULL if fail + */ + WOLFSSL_ASN1_STRING* wolfSSL_ASN1_STRING_type_new(int type) + { + WOLFSSL_ASN1_STRING* asn1; + + WOLFSSL_ENTER("wolfSSL_ASN1_STRING_type_new"); + + asn1 = wolfSSL_ASN1_STRING_new(); + if (asn1 == NULL) { + return NULL; + } + asn1->type = type; + + return asn1; + } + + + /* if dataSz is negative then use XSTRLEN to find length of data + * return WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure */ + int wolfSSL_ASN1_STRING_set(WOLFSSL_ASN1_STRING* asn1, const void* data, + int dataSz) + { + int sz; + + WOLFSSL_ENTER("wolfSSL_ASN1_STRING_set"); + + if (data == NULL || asn1 == NULL) { + return WOLFSSL_FAILURE; + } + + if (dataSz < 0) { + sz = (int)XSTRLEN((const char*)data) + 1; /* +1 for null */ + } + else { + sz = dataSz; + } + + if (sz < 0) { + return WOLFSSL_FAILURE; + } + + /* free any existing data before copying */ + if (asn1->data != NULL && asn1->isDynamic) { + XFREE(asn1->data, NULL, DYNAMIC_TYPE_OPENSSL); + } + + if (sz > CTC_NAME_SIZE) { + /* create new data buffer and copy over */ + asn1->data = (char*)XMALLOC(sz, NULL, DYNAMIC_TYPE_OPENSSL); + if (asn1->data == NULL) { + return WOLFSSL_FAILURE; + } + asn1->isDynamic = 1; + } + else { + XMEMSET(asn1->strData, 0, CTC_NAME_SIZE); + asn1->data = asn1->strData; + } + XMEMCPY(asn1->data, data, sz); + asn1->length = sz; + + return WOLFSSL_SUCCESS; + } + + + unsigned char* wolfSSL_ASN1_STRING_data(WOLFSSL_ASN1_STRING* asn) + { + WOLFSSL_ENTER("wolfSSL_ASN1_STRING_data"); + + if (asn) { + return (unsigned char*)asn->data; + } + else { + return NULL; + } + } + + + int wolfSSL_ASN1_STRING_length(WOLFSSL_ASN1_STRING* asn) + { + WOLFSSL_ENTER("wolfSSL_ASN1_STRING_length"); + + if (asn) { + return asn->length; + } + else { + return 0; + } + } + + +#ifdef XSNPRINTF /* a snprintf function needs to be available */ + /* Writes the human readable form of x509 to bio. + * + * bio WOLFSSL_BIO to write to. + * x509 Certificate to write. + * + * returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure + */ + int wolfSSL_X509_print(WOLFSSL_BIO* bio, WOLFSSL_X509* x509) + { + WOLFSSL_ENTER("wolfSSL_X509_print"); + + if (bio == NULL || x509 == NULL) { + return WOLFSSL_FAILURE; + } + + if (wolfSSL_BIO_write(bio, "Certificate:\n", + (int)XSTRLEN("Certificate:\n")) <= 0) { + return WOLFSSL_FAILURE; + } + + if (wolfSSL_BIO_write(bio, " Data:\n", + (int)XSTRLEN(" Data:\n")) <= 0) { + return WOLFSSL_FAILURE; + } + + /* print version of cert */ + { + int version; + char tmp[17]; + + if ((version = wolfSSL_X509_version(x509)) <= 0) { + WOLFSSL_MSG("Error getting X509 version"); + return WOLFSSL_FAILURE; + } + if (wolfSSL_BIO_write(bio, " Version: ", + (int)XSTRLEN(" Version: ")) <= 0) { + return WOLFSSL_FAILURE; + } + XSNPRINTF(tmp, sizeof(tmp), "%d\n", version); + if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) { + return WOLFSSL_FAILURE; + } + } + + /* print serial number out */ + { + unsigned char serial[32]; + int sz = sizeof(serial); + + XMEMSET(serial, 0, sz); + if (wolfSSL_X509_get_serial_number(x509, serial, &sz) + != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Error getting x509 serial number"); + return WOLFSSL_FAILURE; + } + if (wolfSSL_BIO_write(bio, " Serial Number: ", + (int)XSTRLEN(" Serial Number: ")) <= 0) { + return WOLFSSL_FAILURE; + } + + /* if serial can fit into byte than print on the same line */ + if (sz <= (int)sizeof(byte)) { + char tmp[17]; + XSNPRINTF(tmp, sizeof(tmp), "%d (0x%x)\n", serial[0],serial[0]); + if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) { + return WOLFSSL_FAILURE; + } + } + else { + int i; + char tmp[100]; + int tmpSz = 100; + char val[5]; + int valSz = 5; + + /* serial is larger than int size so print off hex values */ + if (wolfSSL_BIO_write(bio, "\n ", + (int)XSTRLEN("\n ")) <= 0) { + return WOLFSSL_FAILURE; + } + tmp[0] = '\0'; + for (i = 0; i < sz - 1 && (3 * i) < tmpSz - valSz; i++) { + XSNPRINTF(val, sizeof(val) - 1, "%02x:", serial[i]); + val[3] = '\0'; /* make sure is null terminated */ + XSTRNCAT(tmp, val, valSz); + } + XSNPRINTF(val, sizeof(val) - 1, "%02x\n", serial[i]); + val[3] = '\0'; /* make sure is null terminated */ + XSTRNCAT(tmp, val, valSz); + if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) { + return WOLFSSL_FAILURE; + } + } + } + + /* print signature algo */ + { + int oid; + char* sig; + + if ((oid = wolfSSL_X509_get_signature_type(x509)) <= 0) { + WOLFSSL_MSG("Error getting x509 signature type"); + return WOLFSSL_FAILURE; + } + if (wolfSSL_BIO_write(bio, " Signature Algorithm: ", + (int)XSTRLEN(" Signature Algorithm: ")) <= 0) { + return WOLFSSL_FAILURE; + } + sig = GetSigName(oid); + if (wolfSSL_BIO_write(bio, sig, (int)XSTRLEN(sig)) <= 0) { + return WOLFSSL_FAILURE; + } + if (wolfSSL_BIO_write(bio, "\n", (int)XSTRLEN("\n")) <= 0) { + return WOLFSSL_FAILURE; + } + } + + /* print issuer */ + { + char* issuer; + #ifdef WOLFSSL_SMALL_STACK + char* buff = NULL; + int issSz = 0; + #else + char buff[256]; + int issSz = 256; + #endif + + issuer = wolfSSL_X509_NAME_oneline( + wolfSSL_X509_get_issuer_name(x509), buff, issSz); + + if (wolfSSL_BIO_write(bio, " Issuer: ", + (int)XSTRLEN(" Issuer: ")) <= 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(issuer, NULL, DYNAMIC_TYPE_OPENSSL); + #endif + return WOLFSSL_FAILURE; + } + if (issuer != NULL) { + if (wolfSSL_BIO_write(bio, issuer, (int)XSTRLEN(issuer)) <= 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(issuer, NULL, DYNAMIC_TYPE_OPENSSL); + #endif + return WOLFSSL_FAILURE; + } + } + #ifdef WOLFSSL_SMALL_STACK + XFREE(issuer, NULL, DYNAMIC_TYPE_OPENSSL); + #endif + if (wolfSSL_BIO_write(bio, "\n", (int)XSTRLEN("\n")) <= 0) { + return WOLFSSL_FAILURE; + } + } + + /* print validity */ + { + char tmp[80]; + + if (wolfSSL_BIO_write(bio, " Validity\n", + (int)XSTRLEN(" Validity\n")) <= 0) { + return WOLFSSL_FAILURE; + } + if (wolfSSL_BIO_write(bio, " Not Before: ", + (int)XSTRLEN(" Not Before: ")) <= 0) { + return WOLFSSL_FAILURE; + } + if (GetTimeString(x509->notBefore + 2, ASN_UTC_TIME, + tmp, sizeof(tmp)) != WOLFSSL_SUCCESS) { + if (GetTimeString(x509->notBefore + 2, ASN_GENERALIZED_TIME, + tmp, sizeof(tmp)) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Error getting not before date"); + return WOLFSSL_FAILURE; + } + } + tmp[sizeof(tmp) - 1] = '\0'; /* make sure null terminated */ + if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) { + return WOLFSSL_FAILURE; + } + if (wolfSSL_BIO_write(bio, "\n Not After : ", + (int)XSTRLEN("\n Not After : ")) <= 0) { + return WOLFSSL_FAILURE; + } + if (GetTimeString(x509->notAfter + 2,ASN_UTC_TIME, + tmp, sizeof(tmp)) != WOLFSSL_SUCCESS) { + if (GetTimeString(x509->notAfter + 2,ASN_GENERALIZED_TIME, + tmp, sizeof(tmp)) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Error getting not before date"); + return WOLFSSL_FAILURE; + } + } + tmp[sizeof(tmp) - 1] = '\0'; /* make sure null terminated */ + if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) { + return WOLFSSL_FAILURE; + } + } + + /* print subject */ + { + char* subject; + #ifdef WOLFSSL_SMALL_STACK + char* buff = NULL; + int subSz = 0; + #else + char buff[256]; + int subSz = 256; + #endif + + subject = wolfSSL_X509_NAME_oneline( + wolfSSL_X509_get_subject_name(x509), buff, subSz); + + if (wolfSSL_BIO_write(bio, "\n Subject: ", + (int)XSTRLEN("\n Subject: ")) <= 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(subject, NULL, DYNAMIC_TYPE_OPENSSL); + #endif + return WOLFSSL_FAILURE; + } + if (subject != NULL) { + if (wolfSSL_BIO_write(bio, subject, (int)XSTRLEN(subject)) <= 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(subject, NULL, DYNAMIC_TYPE_OPENSSL); + #endif + return WOLFSSL_FAILURE; + } + } + #ifdef WOLFSSL_SMALL_STACK + XFREE(subject, NULL, DYNAMIC_TYPE_OPENSSL); + #endif + } + + /* get and print public key */ + if (wolfSSL_BIO_write(bio, "\n Subject Public Key Info:\n", + (int)XSTRLEN("\n Subject Public Key Info:\n")) <= 0) { + return WOLFSSL_FAILURE; + } + { + char tmp[100]; + + switch (x509->pubKeyOID) { + #ifndef NO_RSA + case RSAk: + if (wolfSSL_BIO_write(bio, + " Public Key Algorithm: RSA\n", + (int)XSTRLEN(" Public Key Algorithm: RSA\n")) <= 0) { + return WOLFSSL_FAILURE; + } + #ifdef HAVE_USER_RSA + if (wolfSSL_BIO_write(bio, + " Build without user RSA to print key\n", + (int)XSTRLEN(" Build without user RSA to print key\n")) + <= 0) { + return WOLFSSL_FAILURE; + } + #else + { + RsaKey rsa; + word32 idx = 0; + int sz; + byte lbit = 0; + int rawLen; + unsigned char* rawKey; + + if (wc_InitRsaKey(&rsa, NULL) != 0) { + WOLFSSL_MSG("wc_InitRsaKey failure"); + return WOLFSSL_FAILURE; + } + if (wc_RsaPublicKeyDecode(x509->pubKey.buffer, + &idx, &rsa, x509->pubKey.length) != 0) { + WOLFSSL_MSG("Error decoding RSA key"); + wc_FreeRsaKey(&rsa); + return WOLFSSL_FAILURE; + } + if ((sz = wc_RsaEncryptSize(&rsa)) < 0) { + WOLFSSL_MSG("Error getting RSA key size"); + wc_FreeRsaKey(&rsa); + return WOLFSSL_FAILURE; + } + XSNPRINTF(tmp, sizeof(tmp) - 1, "%s%s: (%d bit)\n%s\n", + " ", "Public-Key", 8 * sz, + " Modulus:"); + tmp[sizeof(tmp) - 1] = '\0'; + if (wolfSSL_BIO_write(bio, tmp, + (int)XSTRLEN(tmp)) <= 0) { + wc_FreeRsaKey(&rsa); + return WOLFSSL_FAILURE; + } + + /* print out modulus */ + XSNPRINTF(tmp, sizeof(tmp) - 1," "); + tmp[sizeof(tmp) - 1] = '\0'; + if (mp_leading_bit(&rsa.n)) { + lbit = 1; + XSTRNCAT(tmp, "00", 3); + } + + rawLen = mp_unsigned_bin_size(&rsa.n); + rawKey = (unsigned char*)XMALLOC(rawLen, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (rawKey == NULL) { + WOLFSSL_MSG("Memory error"); + wc_FreeRsaKey(&rsa); + return WOLFSSL_FAILURE; + } + mp_to_unsigned_bin(&rsa.n, rawKey); + for (idx = 0; idx < (word32)rawLen; idx++) { + char val[5]; + int valSz = 5; + + if ((idx == 0) && !lbit) { + XSNPRINTF(val, valSz - 1, "%02x", rawKey[idx]); + } + else if ((idx != 0) && (((idx + lbit) % 15) == 0)) { + tmp[sizeof(tmp) - 1] = '\0'; + if (wolfSSL_BIO_write(bio, tmp, + (int)XSTRLEN(tmp)) <= 0) { + XFREE(rawKey, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + wc_FreeRsaKey(&rsa); + return WOLFSSL_FAILURE; + } + XSNPRINTF(tmp, sizeof(tmp) - 1, + ":\n "); + XSNPRINTF(val, valSz - 1, "%02x", rawKey[idx]); + } + else { + XSNPRINTF(val, valSz - 1, ":%02x", rawKey[idx]); + } + XSTRNCAT(tmp, val, valSz); + } + XFREE(rawKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + /* print out remaining modulus values */ + if ((idx > 0) && (((idx - 1 + lbit) % 15) != 0)) { + tmp[sizeof(tmp) - 1] = '\0'; + if (wolfSSL_BIO_write(bio, tmp, + (int)XSTRLEN(tmp)) <= 0) { + return WOLFSSL_FAILURE; + } + } + + /* print out exponent values */ + rawLen = mp_unsigned_bin_size(&rsa.e); + if (rawLen < 0) { + WOLFSSL_MSG("Error getting exponent size"); + wc_FreeRsaKey(&rsa); + return WOLFSSL_FAILURE; + } + + if ((word32)rawLen < sizeof(word32)) { + rawLen = sizeof(word32); + } + rawKey = (unsigned char*)XMALLOC(rawLen, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (rawKey == NULL) { + WOLFSSL_MSG("Memory error"); + wc_FreeRsaKey(&rsa); + return WOLFSSL_FAILURE; + } + XMEMSET(rawKey, 0, rawLen); + mp_to_unsigned_bin(&rsa.e, rawKey); + if ((word32)rawLen <= sizeof(word32)) { + idx = *(word32*)rawKey; + } + XSNPRINTF(tmp, sizeof(tmp) - 1, + "\n Exponent: %d\n", idx); + if (wolfSSL_BIO_write(bio, tmp, + (int)XSTRLEN(tmp)) <= 0) { + XFREE(rawKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); + wc_FreeRsaKey(&rsa); + return WOLFSSL_FAILURE; + } + XFREE(rawKey, NULL, DYNAMIC_TYPE_TMP_BUFFER); + wc_FreeRsaKey(&rsa); + } + #endif /* HAVE_USER_RSA */ + break; + #endif /* NO_RSA */ + + #ifdef HAVE_ECC + case ECDSAk: + { + word32 i; + ecc_key ecc; + + if (wolfSSL_BIO_write(bio, + " Public Key Algorithm: EC\n", + (int)XSTRLEN(" Public Key Algorithm: EC\n")) <= 0) { + return WOLFSSL_FAILURE; + } + if (wc_ecc_init_ex(&ecc, x509->heap, INVALID_DEVID) + != 0) { + return WOLFSSL_FAILURE; + } + + i = 0; + if (wc_EccPublicKeyDecode(x509->pubKey.buffer, &i, + &ecc, x509->pubKey.length) != 0) { + wc_ecc_free(&ecc); + return WOLFSSL_FAILURE; + } + XSNPRINTF(tmp, sizeof(tmp) - 1, "%s%s: (%d bit)\n%s\n", + " ", "Public-Key", + 8 * wc_ecc_size(&ecc), + " pub:"); + tmp[sizeof(tmp) - 1] = '\0'; + if (wolfSSL_BIO_write(bio, tmp, + (int)XSTRLEN(tmp)) <= 0) { + wc_ecc_free(&ecc); + return WOLFSSL_FAILURE; + } + XSNPRINTF(tmp, sizeof(tmp) - 1," "); + { + word32 derSz; + byte* der; + + derSz = wc_ecc_size(&ecc) * WOLFSSL_BIT_SIZE; + der = (byte*)XMALLOC(derSz, x509->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (der == NULL) { + wc_ecc_free(&ecc); + return WOLFSSL_FAILURE; + } + + if (wc_ecc_export_x963(&ecc, der, &derSz) != 0) { + wc_ecc_free(&ecc); + XFREE(der, x509->heap, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; + } + for (i = 0; i < derSz; i++) { + char val[5]; + int valSz = 5; + + if (i == 0) { + XSNPRINTF(val, valSz - 1, "%02x", der[i]); + } + else if ((i % 15) == 0) { + tmp[sizeof(tmp) - 1] = '\0'; + if (wolfSSL_BIO_write(bio, tmp, + (int)XSTRLEN(tmp)) <= 0) { + wc_ecc_free(&ecc); + XFREE(der, x509->heap, + DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; + } + XSNPRINTF(tmp, sizeof(tmp) - 1, + ":\n "); + XSNPRINTF(val, valSz - 1, "%02x", der[i]); + } + else { + XSNPRINTF(val, valSz - 1, ":%02x", der[i]); + } + XSTRNCAT(tmp, val, valSz); + } + + /* print out remaining modulus values */ + if ((i > 0) && (((i - 1) % 15) != 0)) { + tmp[sizeof(tmp) - 1] = '\0'; + if (wolfSSL_BIO_write(bio, tmp, + (int)XSTRLEN(tmp)) <= 0) { + wc_ecc_free(&ecc); + XFREE(der, x509->heap, + DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; + } + } + + XFREE(der, x509->heap, DYNAMIC_TYPE_TMP_BUFFER); + } + XSNPRINTF(tmp, sizeof(tmp) - 1, "\n%s%s: %s\n", + " ", "ASN1 OID", + ecc.dp->name); + if (wolfSSL_BIO_write(bio, tmp, + (int)XSTRLEN(tmp)) <= 0) { + wc_ecc_free(&ecc); + return WOLFSSL_FAILURE; + } + wc_ecc_free(&ecc); + } + break; + #endif /* HAVE_ECC */ + default: + WOLFSSL_MSG("Unknown key type"); + return WOLFSSL_FAILURE; + } + } + + /* print out extensions */ + if (wolfSSL_BIO_write(bio, " X509v3 extensions:\n", + (int)XSTRLEN(" X509v3 extensions:\n")) <= 0) { + return WOLFSSL_FAILURE; + } + + /* print subject key id */ + if (x509->subjKeyIdSet && x509->subjKeyId != NULL && + x509->subjKeyIdSz > 0) { + char tmp[100]; + word32 i; + char val[5]; + int valSz = 5; + + + if (wolfSSL_BIO_write(bio, + " X509v3 Subject Key Identifier:\n", + (int)XSTRLEN(" X509v3 Subject Key Identifier:\n")) + <= 0) { + return WOLFSSL_FAILURE; + } + + XSNPRINTF(tmp, sizeof(tmp) - 1, " "); + for (i = 0; i < sizeof(tmp) && i < (x509->subjKeyIdSz - 1); i++) { + XSNPRINTF(val, valSz - 1, "%02X:", x509->subjKeyId[i]); + XSTRNCAT(tmp, val, valSz); + } + XSNPRINTF(val, valSz - 1, "%02X\n", x509->subjKeyId[i]); + XSTRNCAT(tmp, val, valSz); + if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) { + return WOLFSSL_FAILURE; + } + } + + /* printf out authority key id */ + if (x509->authKeyIdSet && x509->authKeyId != NULL && + x509->authKeyIdSz > 0) { + char tmp[100]; + word32 i; + char val[5]; + int valSz = 5; + + if (wolfSSL_BIO_write(bio, + " X509v3 Authority Key Identifier:\n", + (int)XSTRLEN(" X509v3 Authority Key Identifier:\n")) + <= 0) { + return WOLFSSL_FAILURE; + } + + XSNPRINTF(tmp, sizeof(tmp) - 1, " keyid"); + for (i = 0; i < x509->authKeyIdSz; i++) { + /* check if buffer is almost full */ + if (XSTRLEN(tmp) >= sizeof(tmp) - valSz) { + if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) { + return WOLFSSL_FAILURE; + } + tmp[0] = '\0'; + } + XSNPRINTF(val, valSz - 1, ":%02X", x509->authKeyId[i]); + XSTRNCAT(tmp, val, valSz); + } + if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) { + return WOLFSSL_FAILURE; + } + + /* print issuer */ + { + char* issuer; + #ifdef WOLFSSL_SMALL_STACK + char* buff = NULL; + int issSz = 0; + #else + char buff[256]; + int issSz = 256; + #endif + + issuer = wolfSSL_X509_NAME_oneline( + wolfSSL_X509_get_issuer_name(x509), buff, issSz); + + if (wolfSSL_BIO_write(bio, "\n DirName:", + (int)XSTRLEN("\n DirName:")) <= 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(issuer, NULL, DYNAMIC_TYPE_OPENSSL); + #endif + return WOLFSSL_FAILURE; + } + if (issuer != NULL) { + if (wolfSSL_BIO_write(bio, issuer, (int)XSTRLEN(issuer)) <= 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(issuer, NULL, DYNAMIC_TYPE_OPENSSL); + #endif + return WOLFSSL_FAILURE; + } + } + #ifdef WOLFSSL_SMALL_STACK + XFREE(issuer, NULL, DYNAMIC_TYPE_OPENSSL); + #endif + if (wolfSSL_BIO_write(bio, "\n", (int)XSTRLEN("\n")) <= 0) { + return WOLFSSL_FAILURE; + } + } + } + + /* print basic constraint */ + if (x509->basicConstSet) { + char tmp[100]; + + if (wolfSSL_BIO_write(bio, + "\n X509v3 Basic Constraints:\n", + (int)XSTRLEN("\n X509v3 Basic Constraints:\n")) + <= 0) { + return WOLFSSL_FAILURE; + } + XSNPRINTF(tmp, sizeof(tmp), + " CA:%s\n", + (x509->isCa)? "TRUE": "FALSE"); + if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) { + return WOLFSSL_FAILURE; + } + } + + /* print out signature */ + { + unsigned char* sig; + int sigSz; + int i; + char tmp[100]; + int sigOid = wolfSSL_X509_get_signature_type(x509); + + if (wolfSSL_BIO_write(bio, + " Signature Algorithm: ", + (int)XSTRLEN(" Signature Algorithm: ")) <= 0) { + return WOLFSSL_FAILURE; + } + XSNPRINTF(tmp, sizeof(tmp) - 1,"%s\n", GetSigName(sigOid)); + tmp[sizeof(tmp) - 1] = '\0'; + if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) <= 0) { + return WOLFSSL_FAILURE; + } + + sigSz = (int)x509->sig.length; + if (sigSz <= 0) { + /* if sigSz invalid return here to avoid overhead of malloc */ + return WOLFSSL_FAILURE; + } + + sig = (unsigned char*)XMALLOC(sigSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (sig == NULL) { + return WOLFSSL_FAILURE; + } + + if (wolfSSL_X509_get_signature(x509, sig, &sigSz) <= 0) { + XFREE(sig, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; + } + XSNPRINTF(tmp, sizeof(tmp) - 1," "); + tmp[sizeof(tmp) - 1] = '\0'; + for (i = 0; i < sigSz; i++) { + char val[5]; + int valSz = 5; + + if (i == 0) { + XSNPRINTF(val, valSz - 1, "%02x", sig[i]); + } + else if (((i % 18) == 0)) { + tmp[sizeof(tmp) - 1] = '\0'; + if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) + <= 0) { + XFREE(sig, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; + } + XSNPRINTF(tmp, sizeof(tmp) - 1, + ":\n "); + XSNPRINTF(val, valSz - 1, "%02x", sig[i]); + } + else { + XSNPRINTF(val, valSz - 1, ":%02x", sig[i]); + } + XSTRNCAT(tmp, val, valSz); + } + XFREE(sig, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + /* print out remaining sig values */ + if ((i > 0) && (((i - 1) % 18) != 0)) { + tmp[sizeof(tmp) - 1] = '\0'; + if (wolfSSL_BIO_write(bio, tmp, (int)XSTRLEN(tmp)) + <= 0) { + return WOLFSSL_FAILURE; + } + } + } + + /* done with print out */ + if (wolfSSL_BIO_write(bio, "\n\0", (int)XSTRLEN("\n\0")) <= 0) { + return WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; + } +#endif /* XSNPRINTF */ + +#endif /* NO_CERTS */ + +char* wolfSSL_CIPHER_description(const WOLFSSL_CIPHER* cipher, char* in, + int len) +{ + char *ret = in; + const char *keaStr, *authStr, *encStr, *macStr; + size_t strLen; + + if (cipher == NULL || in == NULL) + return NULL; + + switch (cipher->ssl->specs.kea) { + case no_kea: + keaStr = "None"; + break; +#ifndef NO_RSA + case rsa_kea: + keaStr = "RSA"; + break; +#endif +#ifndef NO_DH + case diffie_hellman_kea: + keaStr = "DHE"; + break; +#endif + case fortezza_kea: + keaStr = "FZ"; + break; +#ifndef NO_PSK + case psk_kea: + keaStr = "PSK"; + break; + #ifndef NO_DH + case dhe_psk_kea: + keaStr = "DHEPSK"; + break; + #endif + #ifdef HAVE_ECC + case ecdhe_psk_kea: + keaStr = "ECDHEPSK"; + break; + #endif +#endif +#ifdef HAVE_NTRU + case ntru_kea: + keaStr = "NTRU"; + break; +#endif +#ifdef HAVE_ECC + case ecc_diffie_hellman_kea: + keaStr = "ECDHE"; + break; + case ecc_static_diffie_hellman_kea: + keaStr = "ECDH"; + break; +#endif + default: + keaStr = "unknown"; + break; + } + + switch (cipher->ssl->specs.sig_algo) { + case anonymous_sa_algo: + authStr = "None"; + break; +#ifndef NO_RSA + case rsa_sa_algo: + authStr = "RSA"; + break; +#endif +#ifndef NO_DSA + case dsa_sa_algo: + authStr = "DSA"; + break; +#endif +#ifdef HAVE_ECC + case ecc_dsa_sa_algo: + authStr = "ECDSA"; + break; +#endif + default: + authStr = "unknown"; + break; + } + + switch (cipher->ssl->specs.bulk_cipher_algorithm) { + case wolfssl_cipher_null: + encStr = "None"; + break; +#ifndef NO_RC4 + case wolfssl_rc4: + encStr = "RC4(128)"; + break; +#endif +#ifndef NO_DES3 + case wolfssl_triple_des: + encStr = "3DES(168)"; + break; +#endif +#ifdef HAVE_IDEA + case wolfssl_idea: + encStr = "IDEA(128)"; + break; +#endif +#ifndef NO_AES + case wolfssl_aes: + if (cipher->ssl->specs.key_size == 128) + encStr = "AES(128)"; + else if (cipher->ssl->specs.key_size == 256) + encStr = "AES(256)"; + else + encStr = "AES(?)"; + break; + #ifdef HAVE_AESGCM + case wolfssl_aes_gcm: + if (cipher->ssl->specs.key_size == 128) + encStr = "AESGCM(128)"; + else if (cipher->ssl->specs.key_size == 256) + encStr = "AESGCM(256)"; + else + encStr = "AESGCM(?)"; + break; + #endif + #ifdef HAVE_AESCCM + case wolfssl_aes_ccm: + if (cipher->ssl->specs.key_size == 128) + encStr = "AESCCM(128)"; + else if (cipher->ssl->specs.key_size == 256) + encStr = "AESCCM(256)"; + else + encStr = "AESCCM(?)"; + break; + #endif +#endif +#ifdef HAVE_CHACHA + case wolfssl_chacha: + encStr = "CHACHA20/POLY1305(256)"; + break; +#endif +#ifdef HAVE_CAMELLIA + case wolfssl_camellia: + if (cipher->ssl->specs.key_size == 128) + encStr = "Camellia(128)"; + else if (cipher->ssl->specs.key_size == 256) + encStr = "Camellia(256)"; + else + encStr = "Camellia(?)"; + break; +#endif +#if defined(HAVE_HC128) && !defined(NO_HC128) + case wolfssl_hc128: + encStr = "HC128(128)"; + break; +#endif +#if defined(HAVE_RABBIT) && !defined(NO_RABBIT) + case wolfssl_rabbit: + encStr = "RABBIT(128)"; + break; +#endif + default: + encStr = "unknown"; + break; + } + + switch (cipher->ssl->specs.mac_algorithm) { + case no_mac: + macStr = "None"; + break; +#ifndef NO_MD5 + case md5_mac: + macStr = "MD5"; + break; +#endif +#ifndef NO_SHA + case sha_mac: + macStr = "SHA1"; + break; +#endif +#ifdef HAVE_SHA224 + case sha224_mac: + macStr = "SHA224"; + break; +#endif +#ifndef NO_SHA256 + case sha256_mac: + macStr = "SHA256"; + break; +#endif +#ifdef HAVE_SHA384 + case sha384_mac: + macStr = "SHA384"; + break; +#endif +#ifdef HAVE_SHA512 + case sha512_mac: + macStr = "SHA512"; + break; +#endif +#ifdef HAVE_BLAKE2 + case blake2b_mac: + macStr = "BLAKE2b"; + break; +#endif + default: + macStr = "unknown"; + break; + } + + /* Build up the string by copying onto the end. */ + XSTRNCPY(in, wolfSSL_CIPHER_get_name(cipher), len); + in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen; + + XSTRNCPY(in, " ", len); + in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen; + XSTRNCPY(in, wolfSSL_get_version(cipher->ssl), len); + in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen; + + XSTRNCPY(in, " Kx=", len); + in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen; + XSTRNCPY(in, keaStr, len); + in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen; + + XSTRNCPY(in, " Au=", len); + in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen; + XSTRNCPY(in, authStr, len); + in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen; + + XSTRNCPY(in, " Enc=", len); + in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen; + XSTRNCPY(in, encStr, len); + in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen; + + XSTRNCPY(in, " Mac=", len); + in[len-1] = '\0'; strLen = XSTRLEN(in); len -= (int)strLen; in += strLen; + XSTRNCPY(in, macStr, len); + in[len-1] = '\0'; + + return ret; +} + + +#ifndef NO_SESSION_CACHE + +WOLFSSL_SESSION* wolfSSL_get1_session(WOLFSSL* ssl) +{ + if (ssl == NULL) { + return NULL; + } + + /* sessions are stored statically, no need for reference count */ + return wolfSSL_get_session(ssl); +} + +#endif /* NO_SESSION_CACHE */ + + + +/* was do nothing */ +/* +void OPENSSL_free(void* buf) +{ + (void)buf; +} +*/ + +#ifndef NO_WOLFSSL_STUB +int wolfSSL_OCSP_parse_url(char* url, char** host, char** port, char** path, + int* ssl) +{ + (void)url; + (void)host; + (void)port; + (void)path; + (void)ssl; + WOLFSSL_STUB("OCSP_parse_url"); + return 0; +} +#endif + +#ifndef NO_MD4 + +void wolfSSL_MD4_Init(WOLFSSL_MD4_CTX* md4) +{ + /* make sure we have a big enough buffer */ + typedef char ok[sizeof(md4->buffer) >= sizeof(Md4) ? 1 : -1]; + (void) sizeof(ok); + + WOLFSSL_ENTER("MD4_Init"); + wc_InitMd4((Md4*)md4); +} + + +void wolfSSL_MD4_Update(WOLFSSL_MD4_CTX* md4, const void* data, + unsigned long len) +{ + WOLFSSL_ENTER("MD4_Update"); + wc_Md4Update((Md4*)md4, (const byte*)data, (word32)len); +} + + +void wolfSSL_MD4_Final(unsigned char* digest, WOLFSSL_MD4_CTX* md4) +{ + WOLFSSL_ENTER("MD4_Final"); + wc_Md4Final((Md4*)md4, digest); +} + +#endif /* NO_MD4 */ + + +/* Removes a WOLFSSL_BIO struct from the WOLFSSL_BIO linked list. + * + * bio is the WOLFSSL_BIO struct in the list and removed. + * + * The return WOLFSSL_BIO struct is the next WOLFSSL_BIO in the list or NULL if + * there is none. + */ +WOLFSSL_BIO* wolfSSL_BIO_pop(WOLFSSL_BIO* bio) +{ + if (bio == NULL) { + WOLFSSL_MSG("Bad argument passed in"); + return NULL; + } + + if (bio->prev != NULL) { + bio->prev->next = bio->next; + } + + if (bio->next != NULL) { + bio->next->prev = bio->prev; + } + + return bio->next; +} + + +int wolfSSL_BIO_pending(WOLFSSL_BIO* bio) +{ + return (int)wolfSSL_BIO_ctrl_pending(bio); +} + + + +WOLFSSL_BIO_METHOD* wolfSSL_BIO_s_mem(void) +{ + static WOLFSSL_BIO_METHOD meth; + + WOLFSSL_ENTER("BIO_s_mem"); + meth.type = WOLFSSL_BIO_MEMORY; + + return &meth; +} + + +WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_base64(void) +{ + static WOLFSSL_BIO_METHOD meth; + + WOLFSSL_ENTER("wolfSSL_BIO_f_base64"); + meth.type = WOLFSSL_BIO_BASE64; + + return &meth; +} + + +/* Set the flag for the bio. + * + * bio the structure to set the flag in + * flags the flag to use + */ +void wolfSSL_BIO_set_flags(WOLFSSL_BIO* bio, int flags) +{ + WOLFSSL_ENTER("wolfSSL_BIO_set_flags"); + + if (bio != NULL) { + bio->flags |= flags; + } +} + + +#ifndef NO_WOLFSSL_STUB +void wolfSSL_RAND_screen(void) +{ + WOLFSSL_STUB("RAND_screen"); +} +#endif + + + +int wolfSSL_RAND_load_file(const char* fname, long len) +{ + (void)fname; + /* wolfCrypt provides enough entropy internally or will report error */ + if (len == -1) + return 1024; + else + return (int)len; +} + + +#ifndef NO_WOLFSSL_STUB +WOLFSSL_COMP_METHOD* wolfSSL_COMP_zlib(void) +{ + WOLFSSL_STUB("COMP_zlib"); + return 0; +} +#endif + +#ifndef NO_WOLFSSL_STUB +WOLFSSL_COMP_METHOD* wolfSSL_COMP_rle(void) +{ + WOLFSSL_STUB("COMP_rle"); + return 0; +} +#endif + +#ifndef NO_WOLFSSL_STUB +int wolfSSL_COMP_add_compression_method(int method, void* data) +{ + (void)method; + (void)data; + WOLFSSL_STUB("COMP_add_compression_method"); + return 0; +} +#endif + +#ifndef NO_WOLFSSL_STUB +void wolfSSL_set_dynlock_create_callback(WOLFSSL_dynlock_value* (*f)( + const char*, int)) +{ + WOLFSSL_STUB("CRYPTO_set_dynlock_create_callback"); + (void)f; +} +#endif + +#ifndef NO_WOLFSSL_STUB +void wolfSSL_set_dynlock_lock_callback( + void (*f)(int, WOLFSSL_dynlock_value*, const char*, int)) +{ + WOLFSSL_STUB("CRYPTO_set_set_dynlock_lock_callback"); + (void)f; +} +#endif + +#ifndef NO_WOLFSSL_STUB +void wolfSSL_set_dynlock_destroy_callback( + void (*f)(WOLFSSL_dynlock_value*, const char*, int)) +{ + WOLFSSL_STUB("CRYPTO_set_set_dynlock_destroy_callback"); + (void)f; +} +#endif + + +const char* wolfSSL_X509_verify_cert_error_string(long err) +{ + return wolfSSL_ERR_reason_error_string(err); +} + + +#ifndef NO_WOLFSSL_STUB +int wolfSSL_X509_LOOKUP_add_dir(WOLFSSL_X509_LOOKUP* lookup, const char* dir, + long len) +{ + (void)lookup; + (void)dir; + (void)len; + WOLFSSL_STUB("X509_LOOKUP_add_dir"); + return 0; +} +#endif + +int wolfSSL_X509_LOOKUP_load_file(WOLFSSL_X509_LOOKUP* lookup, + const char* file, long type) +{ +#if !defined(NO_FILESYSTEM) && \ + (defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM)) + int ret = WOLFSSL_FAILURE; + XFILE fp; + long sz; + byte* pem = NULL; + byte* curr = NULL; + byte* prev = NULL; + WOLFSSL_X509* x509; + const char* header = NULL; + const char* footer = NULL; + + if (type != X509_FILETYPE_PEM) + return BAD_FUNC_ARG; + + fp = XFOPEN(file, "r"); + if (fp == XBADFILE) + return BAD_FUNC_ARG; + + if(XFSEEK(fp, 0, XSEEK_END) != 0) { + XFCLOSE(fp); + return WOLFSSL_BAD_FILE; + } + sz = XFTELL(fp); + XREWIND(fp); + + if (sz <= 0) + goto end; + + pem = (byte*)XMALLOC(sz, 0, DYNAMIC_TYPE_PEM); + if (pem == NULL) { + ret = MEMORY_ERROR; + goto end; + } + + /* Read in file which may be CRLs or certificates. */ + if (XFREAD(pem, (size_t)sz, 1, fp) != 1) + goto end; + + prev = curr = pem; + do { + /* get PEM header and footer based on type */ + if (wc_PemGetHeaderFooter(CRL_TYPE, &header, &footer) == 0 && + XSTRNSTR((char*)curr, header, (unsigned int)sz) != NULL) { +#ifdef HAVE_CRL + WOLFSSL_CERT_MANAGER* cm = lookup->store->cm; + + if (cm->crl == NULL) { + if (wolfSSL_CertManagerEnableCRL(cm, 0) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Enable CRL failed"); + goto end; + } + } + + ret = BufferLoadCRL(cm->crl, curr, sz, WOLFSSL_FILETYPE_PEM, 1); + if (ret != WOLFSSL_SUCCESS) + goto end; +#endif + curr = (byte*)XSTRNSTR((char*)curr, footer, (unsigned int)sz); + } + else if (wc_PemGetHeaderFooter(CERT_TYPE, &header, &footer) == 0 && + XSTRNSTR((char*)curr, header, (unsigned int)sz) != NULL) { + x509 = wolfSSL_X509_load_certificate_buffer(curr, (int)sz, + WOLFSSL_FILETYPE_PEM); + if (x509 == NULL) + goto end; + ret = wolfSSL_X509_STORE_add_cert(lookup->store, x509); + wolfSSL_X509_free(x509); + if (ret != WOLFSSL_SUCCESS) + goto end; + curr = (byte*)XSTRNSTR((char*)curr, footer, (unsigned int)sz); + } + else + goto end; + + if (curr == NULL) + goto end; + + curr++; + sz -= (long)(curr - prev); + prev = curr; + } + while (ret == WOLFSSL_SUCCESS); + +end: + if (pem != NULL) + XFREE(pem, 0, DYNAMIC_TYPE_PEM); + XFCLOSE(fp); + return ret; +#else + (void)lookup; + (void)file; + (void)type; + return WOLFSSL_FAILURE; +#endif +} + +WOLFSSL_X509_LOOKUP_METHOD* wolfSSL_X509_LOOKUP_hash_dir(void) +{ + /* Method implementation in functions. */ + static WOLFSSL_X509_LOOKUP_METHOD meth = { 1 }; + return &meth; +} + +WOLFSSL_X509_LOOKUP_METHOD* wolfSSL_X509_LOOKUP_file(void) +{ + /* Method implementation in functions. */ + static WOLFSSL_X509_LOOKUP_METHOD meth = { 0 }; + return &meth; +} + + +WOLFSSL_X509_LOOKUP* wolfSSL_X509_STORE_add_lookup(WOLFSSL_X509_STORE* store, + WOLFSSL_X509_LOOKUP_METHOD* m) +{ + if (store == NULL) + return NULL; + + /* Method is a dummy value and is not needed. */ + (void)m; + /* Make sure the lookup has a back reference to the store. */ + store->lookup.store = store; + return &store->lookup; +} + + +#ifndef NO_CERTS +/* Converts the X509 to DER format and outputs it into bio. + * + * bio is the structure to hold output DER + * x509 certificate to create DER from + * + * returns WOLFSSL_SUCCESS on success + */ +int wolfSSL_i2d_X509_bio(WOLFSSL_BIO* bio, WOLFSSL_X509* x509) +{ + WOLFSSL_ENTER("wolfSSL_i2d_X509_bio"); + + if (bio == NULL || x509 == NULL) { + return WOLFSSL_FAILURE; + } + + if (x509->derCert != NULL) { + word32 len = x509->derCert->length; + byte* der = x509->derCert->buffer; + + if (wolfSSL_BIO_write(bio, der, len) == (int)len) { + return SSL_SUCCESS; + } + } + + return WOLFSSL_FAILURE; +} + + +/* Converts an internal structure to a DER buffer + * + * x509 structure to get DER buffer from + * out buffer to hold result. If NULL then *out is NULL then a new buffer is + * created. + * + * returns the size of the DER result on success + */ +int wolfSSL_i2d_X509(WOLFSSL_X509* x509, unsigned char** out) +{ + const unsigned char* der; + int derSz = 0; + + if (x509 == NULL || out == NULL) { + return BAD_FUNC_ARG; + } + + der = wolfSSL_X509_get_der(x509, &derSz); + if (der == NULL) { + return MEMORY_E; + } + + if (*out == NULL) { + *out = (unsigned char*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_OPENSSL); + if (*out == NULL) { + return MEMORY_E; + } + } + + XMEMCPY(*out, der, derSz); + + return derSz; +} + + +/* Converts the DER from bio and creates a WOLFSSL_X509 structure from it. + * + * bio is the structure holding DER + * x509 certificate to create from DER. Can be NULL + * + * returns pointer to WOLFSSL_X509 structure on success and NULL on fail + */ +WOLFSSL_X509* wolfSSL_d2i_X509_bio(WOLFSSL_BIO* bio, WOLFSSL_X509** x509) +{ + WOLFSSL_X509* localX509 = NULL; + unsigned char* mem = NULL; + int ret; + word32 size; + + WOLFSSL_ENTER("wolfSSL_d2i_X509_bio"); + + if (bio == NULL) { + WOLFSSL_MSG("Bad Function Argument bio is NULL"); + return NULL; + } + + ret = wolfSSL_BIO_get_mem_data(bio, &mem); + if (mem == NULL || ret <= 0) { + WOLFSSL_MSG("Failed to get data from bio struct"); + return NULL; + } + size = ret; + + localX509 = wolfSSL_X509_d2i(NULL, mem, size); + if (localX509 == NULL) { + return NULL; + } + + if (x509 != NULL) { + *x509 = localX509; + } + + return localX509; +} + + +#if !defined(NO_ASN) && !defined(NO_PWDBASED) +WC_PKCS12* wolfSSL_d2i_PKCS12_bio(WOLFSSL_BIO* bio, WC_PKCS12** pkcs12) +{ + WC_PKCS12* localPkcs12 = NULL; + unsigned char* mem = NULL; + int ret; + word32 size; + + WOLFSSL_ENTER("wolfSSL_d2i_PKCS12_bio"); + + if (bio == NULL) { + WOLFSSL_MSG("Bad Function Argument bio is NULL"); + return NULL; + } + + localPkcs12 = wc_PKCS12_new(); + if (localPkcs12 == NULL) { + WOLFSSL_MSG("Memory error"); + return NULL; + } + + if (pkcs12 != NULL) { + *pkcs12 = localPkcs12; + } + + ret = wolfSSL_BIO_get_mem_data(bio, &mem); + if (mem == NULL || ret <= 0) { + WOLFSSL_MSG("Failed to get data from bio struct"); + wc_PKCS12_free(localPkcs12); + if (pkcs12 != NULL) { + *pkcs12 = NULL; + } + return NULL; + } + size = ret; + + ret = wc_d2i_PKCS12(mem, size, localPkcs12); + if (ret < 0) { + WOLFSSL_MSG("Failed to get PKCS12 sequence"); + wc_PKCS12_free(localPkcs12); + if (pkcs12 != NULL) { + *pkcs12 = NULL; + } + return NULL; + } + + return localPkcs12; +} + + +/* helper function to get DER buffer from WOLFSSL_EVP_PKEY */ +static int wolfSSL_i2d_PrivateKey(WOLFSSL_EVP_PKEY* key, unsigned char** der) +{ + *der = (unsigned char*)key->pkey.ptr; + + return key->pkey_sz; +} + + + +/* Creates a new WC_PKCS12 structure + * + * pass password to use + * name friendlyName to use + * pkey private key to go into PKCS12 bundle + * cert certificate to go into PKCS12 bundle + * ca extra certificates that can be added to bundle. Can be NULL + * keyNID type of encryption to use on the key (-1 means no encryption) + * certNID type of encryption to use on the certificate + * itt number of iterations with encryption + * macItt number of iterations with mac creation + * keyType flag for signature and/or encryption key + * + * returns a pointer to a new WC_PKCS12 structure on success and NULL on fail + */ +WC_PKCS12* wolfSSL_PKCS12_create(char* pass, char* name, + WOLFSSL_EVP_PKEY* pkey, WOLFSSL_X509* cert, + WOLF_STACK_OF(WOLFSSL_X509)* ca, + int keyNID, int certNID, int itt, int macItt, int keyType) +{ + WC_PKCS12* pkcs12; + WC_DerCertList* list = NULL; + word32 passSz; + byte* keyDer; + word32 keyDerSz; + byte* certDer; + int certDerSz; + + int ret; + + WOLFSSL_ENTER("wolfSSL_PKCS12_create()"); + + if (pass == NULL || pkey == NULL || cert == NULL) { + WOLFSSL_LEAVE("wolfSSL_PKCS12_create()", BAD_FUNC_ARG); + return NULL; + } + passSz = (word32)XSTRLEN(pass); + + if ((ret = wolfSSL_i2d_PrivateKey(pkey, &keyDer)) < 0) { + WOLFSSL_LEAVE("wolfSSL_PKCS12_create", ret); + return NULL; + } + keyDerSz = ret; + + certDer = (byte*)wolfSSL_X509_get_der(cert, &certDerSz); + if (certDer == NULL) { + return NULL; + } + + if (ca != NULL) { + WC_DerCertList* cur; + unsigned long numCerts = ca->num; + byte* curDer; + int curDerSz = 0; + WOLFSSL_STACK* sk = ca; + + while (numCerts > 0 && sk != NULL) { + cur = (WC_DerCertList*)XMALLOC(sizeof(WC_DerCertList), NULL, + DYNAMIC_TYPE_PKCS); + if (cur == NULL) { + wc_FreeCertList(list, NULL); + return NULL; + } + + curDer = (byte*)wolfSSL_X509_get_der(sk->data.x509, &curDerSz); + if (curDer == NULL || curDerSz < 0) { + XFREE(cur, NULL, DYNAMIC_TYPE_PKCS); + wc_FreeCertList(list, NULL); + return NULL; + } + + cur->buffer = (byte*)XMALLOC(curDerSz, NULL, DYNAMIC_TYPE_PKCS); + if (cur->buffer == NULL) { + XFREE(cur, NULL, DYNAMIC_TYPE_PKCS); + wc_FreeCertList(list, NULL); + return NULL; + } + XMEMCPY(cur->buffer, curDer, curDerSz); + cur->bufferSz = curDerSz; + cur->next = list; + list = cur; + + sk = sk->next; + numCerts--; + } + } + + pkcs12 = wc_PKCS12_create(pass, passSz, name, keyDer, keyDerSz, + certDer, certDerSz, list, keyNID, certNID, itt, macItt, + keyType, NULL); + + if (ca != NULL) { + wc_FreeCertList(list, NULL); + } + + return pkcs12; +} + + +/* return WOLFSSL_SUCCESS on success, WOLFSSL_FAILURE on failure */ +int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, + WOLFSSL_EVP_PKEY** pkey, WOLFSSL_X509** cert, WOLF_STACK_OF(WOLFSSL_X509)** ca) +{ + DecodedCert DeCert; + void* heap = NULL; + int ret; + byte* certData = NULL; + word32 certDataSz; + byte* pk = NULL; + word32 pkSz; + WC_DerCertList* certList = NULL; + + WOLFSSL_ENTER("wolfSSL_PKCS12_parse"); + + /* make sure we init return args */ + if (pkey) *pkey = NULL; + if (cert) *cert = NULL; + if (ca) *ca = NULL; + + if (pkcs12 == NULL || psw == NULL || pkey == NULL || cert == NULL) { + WOLFSSL_MSG("Bad argument value"); + return WOLFSSL_FAILURE; + } + + heap = wc_PKCS12_GetHeap(pkcs12); + + if (ca == NULL) { + ret = wc_PKCS12_parse(pkcs12, psw, &pk, &pkSz, &certData, &certDataSz, + NULL); + } + else { + ret = wc_PKCS12_parse(pkcs12, psw, &pk, &pkSz, &certData, &certDataSz, + &certList); + } + if (ret < 0) { + WOLFSSL_LEAVE("wolfSSL_PKCS12_parse", ret); + return WOLFSSL_FAILURE; + } + + /* Decode cert and place in X509 stack struct */ + if (certList != NULL) { + WC_DerCertList* current = certList; + + *ca = (WOLF_STACK_OF(WOLFSSL_X509)*)XMALLOC(sizeof(WOLF_STACK_OF(WOLFSSL_X509)), + heap, DYNAMIC_TYPE_X509); + if (*ca == NULL) { + if (pk != NULL) { + XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY); + } + if (certData != NULL) { + XFREE(*cert, heap, DYNAMIC_TYPE_PKCS); *cert = NULL; + } + /* Free up WC_DerCertList and move on */ + while (current != NULL) { + WC_DerCertList* next = current->next; + + XFREE(current->buffer, heap, DYNAMIC_TYPE_PKCS); + XFREE(current, heap, DYNAMIC_TYPE_PKCS); + current = next; + } + return WOLFSSL_FAILURE; + } + XMEMSET(*ca, 0, sizeof(WOLF_STACK_OF(WOLFSSL_X509))); + + /* add list of DER certs as X509's to stack */ + while (current != NULL) { + WC_DerCertList* toFree = current; + WOLFSSL_X509* x509; + + x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), heap, + DYNAMIC_TYPE_X509); + InitX509(x509, 1, heap); + InitDecodedCert(&DeCert, current->buffer, current->bufferSz, heap); + if (ParseCertRelative(&DeCert, CERT_TYPE, NO_VERIFY, NULL) != 0) { + WOLFSSL_MSG("Issue with parsing certificate"); + FreeDecodedCert(&DeCert); + wolfSSL_X509_free(x509); + } + else { + if ((ret = CopyDecodedToX509(x509, &DeCert)) != 0) { + WOLFSSL_MSG("Failed to copy decoded cert"); + FreeDecodedCert(&DeCert); + wolfSSL_X509_free(x509); + wolfSSL_sk_X509_free(*ca); *ca = NULL; + if (pk != NULL) { + XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY); + } + if (certData != NULL) { + XFREE(certData, heap, DYNAMIC_TYPE_PKCS); + } + /* Free up WC_DerCertList */ + while (current != NULL) { + WC_DerCertList* next = current->next; + + XFREE(current->buffer, heap, DYNAMIC_TYPE_PKCS); + XFREE(current, heap, DYNAMIC_TYPE_PKCS); + current = next; + } + return WOLFSSL_FAILURE; + } + FreeDecodedCert(&DeCert); + + if (wolfSSL_sk_X509_push(*ca, x509) != 1) { + WOLFSSL_MSG("Failed to push x509 onto stack"); + wolfSSL_X509_free(x509); + wolfSSL_sk_X509_free(*ca); *ca = NULL; + if (pk != NULL) { + XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY); + } + if (certData != NULL) { + XFREE(certData, heap, DYNAMIC_TYPE_PKCS); + } + + /* Free up WC_DerCertList */ + while (current != NULL) { + WC_DerCertList* next = current->next; + + XFREE(current->buffer, heap, DYNAMIC_TYPE_PKCS); + XFREE(current, heap, DYNAMIC_TYPE_PKCS); + current = next; + } + return WOLFSSL_FAILURE; + } + } + current = current->next; + XFREE(toFree->buffer, heap, DYNAMIC_TYPE_PKCS); + XFREE(toFree, heap, DYNAMIC_TYPE_PKCS); + } + } + + + /* Decode cert and place in X509 struct */ + if (certData != NULL) { + *cert = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), heap, + DYNAMIC_TYPE_X509); + if (*cert == NULL) { + if (pk != NULL) { + XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY); + } + if (ca != NULL) { + wolfSSL_sk_X509_free(*ca); *ca = NULL; + } + XFREE(certData, heap, DYNAMIC_TYPE_PKCS); + return WOLFSSL_FAILURE; + } + InitX509(*cert, 1, heap); + InitDecodedCert(&DeCert, certData, certDataSz, heap); + if (ParseCertRelative(&DeCert, CERT_TYPE, NO_VERIFY, NULL) != 0) { + WOLFSSL_MSG("Issue with parsing certificate"); + } + if ((ret = CopyDecodedToX509(*cert, &DeCert)) != 0) { + WOLFSSL_MSG("Failed to copy decoded cert"); + FreeDecodedCert(&DeCert); + if (pk != NULL) { + XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY); + } + if (ca != NULL) { + wolfSSL_sk_X509_free(*ca); *ca = NULL; + } + wolfSSL_X509_free(*cert); *cert = NULL; + return WOLFSSL_FAILURE; + } + FreeDecodedCert(&DeCert); + XFREE(certData, heap, DYNAMIC_TYPE_PKCS); + } + + + /* get key type */ + ret = BAD_STATE_E; + if (pk != NULL) { /* decode key if present */ + *pkey = wolfSSL_PKEY_new_ex(heap); + if (*pkey == NULL) { + wolfSSL_X509_free(*cert); *cert = NULL; + if (ca != NULL) { + wolfSSL_sk_X509_free(*ca); *ca = NULL; + } + XFREE(pk, heap, DYNAMIC_TYPE_PUBLIC_KEY); + return WOLFSSL_FAILURE; + } + #ifndef NO_RSA + { + word32 keyIdx = 0; + RsaKey key; + + if (wc_InitRsaKey(&key, heap) != 0) { + ret = BAD_STATE_E; + } + else { + if ((ret = wc_RsaPrivateKeyDecode(pk, &keyIdx, &key, pkSz)) + == 0) { + (*pkey)->type = EVP_PKEY_RSA; + (*pkey)->rsa = wolfSSL_RSA_new(); + (*pkey)->ownRsa = 1; /* we own RSA */ + if ((*pkey)->rsa == NULL) { + WOLFSSL_MSG("issue creating EVP RSA key"); + wolfSSL_X509_free(*cert); *cert = NULL; + if (ca != NULL) { + wolfSSL_sk_X509_free(*ca); *ca = NULL; + } + wolfSSL_EVP_PKEY_free(*pkey); *pkey = NULL; + XFREE(pk, heap, DYNAMIC_TYPE_PKCS); + return WOLFSSL_FAILURE; + } + if ((ret = wolfSSL_RSA_LoadDer_ex((*pkey)->rsa, pk, pkSz, + WOLFSSL_RSA_LOAD_PRIVATE)) != SSL_SUCCESS) { + WOLFSSL_MSG("issue loading RSA key"); + wolfSSL_X509_free(*cert); *cert = NULL; + if (ca != NULL) { + wolfSSL_sk_X509_free(*ca); *ca = NULL; + } + wolfSSL_EVP_PKEY_free(*pkey); *pkey = NULL; + XFREE(pk, heap, DYNAMIC_TYPE_PKCS); + return WOLFSSL_FAILURE; + } + + WOLFSSL_MSG("Found PKCS12 RSA key"); + ret = 0; /* set in success state for upcoming ECC check */ + } + wc_FreeRsaKey(&key); + } + } + #endif /* NO_RSA */ + + #ifdef HAVE_ECC + { + word32 keyIdx = 0; + ecc_key key; + + if (ret != 0) { /* if is in fail state check if ECC key */ + if (wc_ecc_init(&key) != 0) { + wolfSSL_X509_free(*cert); *cert = NULL; + if (ca != NULL) { + wolfSSL_sk_X509_free(*ca); *ca = NULL; + } + wolfSSL_EVP_PKEY_free(*pkey); *pkey = NULL; + XFREE(pk, heap, DYNAMIC_TYPE_PKCS); + return WOLFSSL_FAILURE; + } + + if ((ret = wc_EccPrivateKeyDecode(pk, &keyIdx, &key, pkSz)) + != 0) { + wolfSSL_X509_free(*cert); *cert = NULL; + if (ca != NULL) { + wolfSSL_sk_X509_free(*ca); *ca = NULL; + } + wolfSSL_EVP_PKEY_free(*pkey); *pkey = NULL; + XFREE(pk, heap, DYNAMIC_TYPE_PKCS); + WOLFSSL_MSG("Bad PKCS12 key format"); + return WOLFSSL_FAILURE; + } + (*pkey)->type = EVP_PKEY_EC; + (*pkey)->pkey_curve = key.dp->oidSum; + wc_ecc_free(&key); + WOLFSSL_MSG("Found PKCS12 ECC key"); + } + } + #else + if (ret != 0) { /* if is in fail state and no ECC then fail */ + wolfSSL_X509_free(*cert); *cert = NULL; + if (ca != NULL) { + wolfSSL_sk_X509_free(*ca); *ca = NULL; + } + wolfSSL_EVP_PKEY_free(*pkey); *pkey = NULL; + XFREE(pk, heap, DYNAMIC_TYPE_PKCS); + WOLFSSL_MSG("Bad PKCS12 key format"); + return WOLFSSL_FAILURE; + } + #endif /* HAVE_ECC */ + + (*pkey)->save_type = 0; + (*pkey)->pkey_sz = pkSz; + (*pkey)->pkey.ptr = (char*)pk; + } + + (void)ret; + (void)ca; + + return WOLFSSL_SUCCESS; +} +#endif /* !defined(NO_ASN) && !defined(NO_PWDBASED) */ + + +/* no-op function. Was initially used for adding encryption algorithms available + * for PKCS12 */ +void wolfSSL_PKCS12_PBE_add(void) +{ + WOLFSSL_ENTER("wolfSSL_PKCS12_PBE_add"); +} + + + +WOLFSSL_STACK* wolfSSL_X509_STORE_CTX_get_chain(WOLFSSL_X509_STORE_CTX* ctx) +{ + WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get_chain"); + + if (ctx == NULL) { + return NULL; + } + +#ifdef SESSION_CERTS + /* if chain is null but sesChain is available then populate stack */ + if (ctx->chain == NULL && ctx->sesChain != NULL) { + int i; + WOLFSSL_X509_CHAIN* c = ctx->sesChain; + WOLFSSL_STACK* sk = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), + NULL, DYNAMIC_TYPE_X509); + + if (sk == NULL) { + return NULL; + } + + XMEMSET(sk, 0, sizeof(WOLFSSL_STACK)); + ctx->chain = sk; + + for (i = 0; i < c->count && i < MAX_CHAIN_DEPTH; i++) { + WOLFSSL_X509* x509 = wolfSSL_get_chain_X509(c, i); + + if (x509 == NULL) { + WOLFSSL_MSG("Unable to get x509 from chain"); + wolfSSL_sk_X509_free(sk); + return NULL; + } + + if (wolfSSL_sk_X509_push(sk, x509) != SSL_SUCCESS) { + WOLFSSL_MSG("Unable to load x509 into stack"); + wolfSSL_sk_X509_free(sk); + wolfSSL_X509_free(x509); + return NULL; + } + } + +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA) + /* add CA used to verify top of chain to the list */ + if (c->count > 0) { + WOLFSSL_X509* x509 = wolfSSL_get_chain_X509(c, c->count - 1); + if (x509 != NULL) { + WOLFSSL_X509* issuer = NULL; + if (wolfSSL_X509_STORE_CTX_get1_issuer(&issuer, ctx, x509) + == WOLFSSL_SUCCESS) { + /* check that the certificate being looked up is not self + * signed and that a issuer was found */ + if (issuer != NULL && wolfSSL_X509_NAME_cmp(&x509->issuer, + &x509->subject) != 0) { + if (wolfSSL_sk_X509_push(sk, issuer) != SSL_SUCCESS) { + WOLFSSL_MSG("Unable to load CA x509 into stack"); + wolfSSL_sk_X509_free(sk); + wolfSSL_X509_free(issuer); + return NULL; + } + } + else { + WOLFSSL_MSG("Certificate is self signed"); + if (issuer != NULL) + wolfSSL_X509_free(issuer); + } + } + else { + WOLFSSL_MSG("Could not find CA for certificate"); + } + } + } +#endif + + } +#endif /* SESSION_CERTS */ + + return ctx->chain; +} + + +int wolfSSL_X509_STORE_add_cert(WOLFSSL_X509_STORE* store, WOLFSSL_X509* x509) +{ + int result = WOLFSSL_FATAL_ERROR; + + WOLFSSL_ENTER("wolfSSL_X509_STORE_add_cert"); + if (store != NULL && store->cm != NULL && x509 != NULL + && x509->derCert != NULL) { + DerBuffer* derCert = NULL; + + result = AllocDer(&derCert, x509->derCert->length, + x509->derCert->type, NULL); + if (result == 0) { + /* AddCA() frees the buffer. */ + XMEMCPY(derCert->buffer, + x509->derCert->buffer, x509->derCert->length); + result = AddCA(store->cm, &derCert, WOLFSSL_USER_CA, 1); + } + } + + WOLFSSL_LEAVE("wolfSSL_X509_STORE_add_cert", result); + + if (result != WOLFSSL_SUCCESS) { + result = WOLFSSL_FATAL_ERROR; + } + + return result; +} + +WOLFSSL_X509_STORE* wolfSSL_X509_STORE_new(void) +{ + WOLFSSL_X509_STORE* store = NULL; + + if((store = (WOLFSSL_X509_STORE*)XMALLOC(sizeof(WOLFSSL_X509_STORE), NULL, + DYNAMIC_TYPE_X509_STORE)) == NULL) + goto err_exit; + + XMEMSET(store, 0, sizeof(WOLFSSL_X509_STORE)); + store->isDynamic = 1; + + if((store->cm = wolfSSL_CertManagerNew()) == NULL) + goto err_exit; + +#ifdef HAVE_CRL + store->crl = NULL; + if((store->crl = (WOLFSSL_X509_CRL *)XMALLOC(sizeof(WOLFSSL_X509_CRL), + NULL, DYNAMIC_TYPE_TMP_BUFFER)) == NULL) + goto err_exit; + if(InitCRL(store->crl, NULL) < 0) + goto err_exit; +#endif + + return store; + +err_exit: + if(store == NULL) + return NULL; + if(store->cm != NULL) + wolfSSL_CertManagerFree(store->cm); +#ifdef HAVE_CRL + if(store->crl != NULL) + wolfSSL_X509_CRL_free(store->crl); +#endif + wolfSSL_X509_STORE_free(store); + + return NULL; +} + + +void wolfSSL_X509_STORE_free(WOLFSSL_X509_STORE* store) +{ + if (store != NULL && store->isDynamic) { + if (store->cm != NULL) + wolfSSL_CertManagerFree(store->cm); +#ifdef HAVE_CRL + if (store->crl != NULL) + wolfSSL_X509_CRL_free(store->crl); +#endif + XFREE(store, NULL, DYNAMIC_TYPE_X509_STORE); + } +} + + +int wolfSSL_X509_STORE_set_flags(WOLFSSL_X509_STORE* store, unsigned long flag) +{ + int ret = WOLFSSL_SUCCESS; + + WOLFSSL_ENTER("wolfSSL_X509_STORE_set_flags"); + + if (store == NULL) + return WOLFSSL_FAILURE; + + if ((flag & WOLFSSL_CRL_CHECKALL) || (flag & WOLFSSL_CRL_CHECK)) { + ret = wolfSSL_CertManagerEnableCRL(store->cm, (int)flag); + } + + (void)store; + (void)flag; + + return ret; +} + + +int wolfSSL_X509_STORE_set_default_paths(WOLFSSL_X509_STORE* store) +{ + (void)store; + return WOLFSSL_SUCCESS; +} + +#ifndef NO_WOLFSSL_STUB +int wolfSSL_X509_STORE_get_by_subject(WOLFSSL_X509_STORE_CTX* ctx, int idx, + WOLFSSL_X509_NAME* name, WOLFSSL_X509_OBJECT* obj) +{ + (void)ctx; + (void)idx; + (void)name; + (void)obj; + WOLFSSL_STUB("X509_STORE_get_by_subject"); + return 0; +} +#endif + +WOLFSSL_X509_STORE_CTX* wolfSSL_X509_STORE_CTX_new(void) +{ + WOLFSSL_X509_STORE_CTX* ctx = (WOLFSSL_X509_STORE_CTX*)XMALLOC( + sizeof(WOLFSSL_X509_STORE_CTX), NULL, + DYNAMIC_TYPE_X509_CTX); + if (ctx != NULL) { + ctx->param = NULL; + wolfSSL_X509_STORE_CTX_init(ctx, NULL, NULL, NULL); + } + + return ctx; +} + + +int wolfSSL_X509_STORE_CTX_init(WOLFSSL_X509_STORE_CTX* ctx, + WOLFSSL_X509_STORE* store, WOLFSSL_X509* x509, WOLF_STACK_OF(WOLFSSL_X509)* sk) +{ + (void)sk; + WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_init"); + if (ctx != NULL) { + ctx->store = store; + #ifndef WOLFSSL_X509_STORE_CERTS + ctx->current_cert = x509; + #else + if(x509 != NULL){ + ctx->current_cert = wolfSSL_X509_d2i(NULL, x509->derCert->buffer,x509->derCert->length); + if(ctx->current_cert == NULL) + return WOLFSSL_FATAL_ERROR; + } else + ctx->current_cert = NULL; + #endif + + ctx->chain = sk; + ctx->domain = NULL; +#ifdef HAVE_EX_DATA + ctx->ex_data = NULL; +#endif + ctx->userCtx = NULL; + ctx->error = 0; + ctx->error_depth = 0; + ctx->discardSessionCerts = 0; +#ifdef OPENSSL_EXTRA + if (ctx->param == NULL) { + ctx->param = (WOLFSSL_X509_VERIFY_PARAM*)XMALLOC( + sizeof(WOLFSSL_X509_VERIFY_PARAM), + NULL,DYNAMIC_TYPE_OPENSSL); + if (ctx->param == NULL){ + WOLFSSL_MSG("wolfSSL_X509_STORE_CTX_init failed"); + return SSL_FATAL_ERROR; + } + } +#endif + return SSL_SUCCESS; + } + return WOLFSSL_FATAL_ERROR; +} + + +void wolfSSL_X509_STORE_CTX_free(WOLFSSL_X509_STORE_CTX* ctx) +{ + if (ctx != NULL) { + if (ctx->store != NULL) + wolfSSL_X509_STORE_free(ctx->store); + #ifndef WOLFSSL_KEEP_STORE_CERTS + if (ctx->current_cert != NULL) + wolfSSL_FreeX509(ctx->current_cert); + #endif +#ifdef OPENSSL_EXTRA + if (ctx->param != NULL){ + XFREE(ctx->param,NULL,DYNAMIC_TYPE_OPENSSL); + } +#endif + XFREE(ctx, NULL, DYNAMIC_TYPE_X509_CTX); + } +} + + +void wolfSSL_X509_STORE_CTX_cleanup(WOLFSSL_X509_STORE_CTX* ctx) +{ + (void)ctx; + /* Do nothing */ +} + + +int wolfSSL_X509_verify_cert(WOLFSSL_X509_STORE_CTX* ctx) +{ + if (ctx != NULL && ctx->store != NULL && ctx->store->cm != NULL + && ctx->current_cert != NULL && ctx->current_cert->derCert != NULL) { + return wolfSSL_CertManagerVerifyBuffer(ctx->store->cm, + ctx->current_cert->derCert->buffer, + ctx->current_cert->derCert->length, + WOLFSSL_FILETYPE_ASN1); + } + return WOLFSSL_FATAL_ERROR; +} + + +/* Use the public key to verify the signature. Note: this only verifies + * the certificate signature. + * returns WOLFSSL_SUCCESS on successful signature verification */ +int wolfSSL_X509_verify(WOLFSSL_X509* x509, WOLFSSL_EVP_PKEY* pkey) +{ + int ret; + const byte* der; + int derSz = 0; + int type; + + if (x509 == NULL || pkey == NULL) { + return WOLFSSL_FATAL_ERROR; + } + + der = wolfSSL_X509_get_der(x509, &derSz); + if (der == NULL) { + WOLFSSL_MSG("Error getting WOLFSSL_X509 DER"); + return WOLFSSL_FATAL_ERROR; + } + + switch (pkey->type) { + case EVP_PKEY_RSA: + type = RSAk; + break; + + case EVP_PKEY_EC: + type = ECDSAk; + break; + + case EVP_PKEY_DSA: + type = DSAk; + break; + + default: + WOLFSSL_MSG("Unknown pkey key type"); + return WOLFSSL_FATAL_ERROR; + } + + ret = CheckCertSignaturePubKey(der, derSz, x509->heap, + (unsigned char*)pkey->pkey.ptr, pkey->pkey_sz, type); + if (ret == 0) { + return WOLFSSL_SUCCESS; + } + return WOLFSSL_FAILURE; +} +#endif /* NO_CERTS */ + +#if !defined(NO_FILESYSTEM) +static void *wolfSSL_d2i_X509_fp_ex(XFILE file, void **x509, int type) +{ + void *newx509 = NULL; + byte *fileBuffer = NULL; + + if (file != XBADFILE) + { + long sz = 0; + + if(XFSEEK(file, 0, XSEEK_END) != 0) + return NULL; + sz = XFTELL(file); + XREWIND(file); + + if (sz < 0) + { + WOLFSSL_MSG("Bad tell on FILE"); + return NULL; + } + + fileBuffer = (byte *)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE); + if (fileBuffer != NULL) + { + if((long)XFREAD(fileBuffer, 1, sz, file) != sz) + { + WOLFSSL_MSG("File read failed"); + goto err_exit; + } + if(type == CERT_TYPE) + newx509 = (void *)wolfSSL_X509_d2i(NULL, fileBuffer, (int)sz); + #ifdef HAVE_CRL + else if(type == CRL_TYPE) + newx509 = (void *)wolfSSL_d2i_X509_CRL(NULL, fileBuffer, (int)sz); + #endif + #if !defined(NO_ASN) && !defined(NO_PWDBASED) + else if(type == PKCS12_TYPE){ + if((newx509 = wc_PKCS12_new()) == NULL) + goto err_exit; + if(wc_d2i_PKCS12(fileBuffer, (int)sz, (WC_PKCS12*)newx509) < 0) + goto err_exit; + } + #endif + else goto err_exit; + if(newx509 == NULL) + { + WOLFSSL_MSG("X509 failed"); + goto err_exit; + } + } + } + if (x509 != NULL) + *x509 = newx509; + + goto _exit; + +err_exit: + #if !defined(NO_ASN) && !defined(NO_PWDBASED) + if((newx509 != NULL) && (type == PKCS12_TYPE)) { + wc_PKCS12_free((WC_PKCS12*)newx509); + } + #endif +_exit: + if(fileBuffer != NULL) + XFREE(fileBuffer, NULL, DYNAMIC_TYPE_FILE); + return newx509; +} + +WOLFSSL_X509_PKCS12 *wolfSSL_d2i_PKCS12_fp(XFILE fp, WOLFSSL_X509_PKCS12 **pkcs12) +{ + WOLFSSL_ENTER("wolfSSL_d2i_PKCS12_fp"); + return (WOLFSSL_X509_PKCS12 *)wolfSSL_d2i_X509_fp_ex(fp, (void **)pkcs12, PKCS12_TYPE); +} + +WOLFSSL_X509 *wolfSSL_d2i_X509_fp(XFILE fp, WOLFSSL_X509 **x509) +{ + WOLFSSL_ENTER("wolfSSL_d2i_X509_fp"); + return (WOLFSSL_X509 *)wolfSSL_d2i_X509_fp_ex(fp, (void **)x509, CERT_TYPE); +} +#endif /* !NO_FILESYSTEM */ + + +#ifdef HAVE_CRL +#ifndef NO_FILESYSTEM +WOLFSSL_X509_CRL *wolfSSL_d2i_X509_CRL_fp(XFILE fp, WOLFSSL_X509_CRL **crl) +{ + WOLFSSL_ENTER("wolfSSL_d2i_X509_CRL_fp"); + return (WOLFSSL_X509_CRL *)wolfSSL_d2i_X509_fp_ex(fp, (void **)crl, CRL_TYPE); +} +#endif /* !NO_FILESYSTEM */ + + +WOLFSSL_X509_CRL* wolfSSL_d2i_X509_CRL(WOLFSSL_X509_CRL** crl, + const unsigned char* in, int len) +{ + WOLFSSL_X509_CRL *newcrl = NULL; + int ret = WOLFSSL_SUCCESS; + + WOLFSSL_ENTER("wolfSSL_d2i_X509_CRL"); + + if (in == NULL) { + WOLFSSL_MSG("Bad argument value"); + } else { + newcrl = (WOLFSSL_X509_CRL*)XMALLOC(sizeof(WOLFSSL_X509_CRL), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (newcrl == NULL){ + WOLFSSL_MSG("New CRL allocation failed"); + } else { + ret = InitCRL(newcrl, NULL); + if (ret < 0) { + WOLFSSL_MSG("Init tmp CRL failed"); + } else { + ret = BufferLoadCRL(newcrl, in, len, WOLFSSL_FILETYPE_ASN1, 1); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Buffer Load CRL failed"); + } else { + if (crl) { + *crl = newcrl; + } + } + } + } + } + + if((ret != WOLFSSL_SUCCESS) && (newcrl != NULL)) { + wolfSSL_X509_CRL_free(newcrl); + newcrl = NULL; + } + + return newcrl; +} + +void wolfSSL_X509_CRL_free(WOLFSSL_X509_CRL *crl) +{ + WOLFSSL_ENTER("wolfSSL_X509_CRL_free"); + + FreeCRL(crl, 1); + return; +} +#endif /* HAVE_CRL */ + +#ifndef NO_WOLFSSL_STUB +WOLFSSL_ASN1_TIME* wolfSSL_X509_CRL_get_lastUpdate(WOLFSSL_X509_CRL* crl) +{ + (void)crl; + WOLFSSL_STUB("X509_CRL_get_lastUpdate"); + return 0; +} +#endif +#ifndef NO_WOLFSSL_STUB +WOLFSSL_ASN1_TIME* wolfSSL_X509_CRL_get_nextUpdate(WOLFSSL_X509_CRL* crl) +{ + (void)crl; + WOLFSSL_STUB("X509_CRL_get_nextUpdate"); + return 0; +} +#endif + + +#ifndef NO_WOLFSSL_STUB +int wolfSSL_X509_CRL_verify(WOLFSSL_X509_CRL* crl, WOLFSSL_EVP_PKEY* key) +{ + (void)crl; + (void)key; + WOLFSSL_STUB("X509_CRL_verify"); + return 0; +} +#endif +#endif /* OPENSSL_EXTRA */ + +#if defined(OPENSSL_EXTRA_X509_SMALL) +/* Subset of OPENSSL_EXTRA for PKEY operations PKEY free is needed by the + * subset of X509 API */ + +WOLFSSL_EVP_PKEY* wolfSSL_PKEY_new(void){ + return wolfSSL_PKEY_new_ex(NULL); +} + + +WOLFSSL_EVP_PKEY* wolfSSL_PKEY_new_ex(void* heap) +{ + WOLFSSL_EVP_PKEY* pkey; + int ret; + WOLFSSL_ENTER("wolfSSL_PKEY_new"); + pkey = (WOLFSSL_EVP_PKEY*)XMALLOC(sizeof(WOLFSSL_EVP_PKEY), heap, + DYNAMIC_TYPE_PUBLIC_KEY); + if (pkey != NULL) { + XMEMSET(pkey, 0, sizeof(WOLFSSL_EVP_PKEY)); + pkey->heap = heap; + pkey->type = WOLFSSL_EVP_PKEY_DEFAULT; +#ifndef HAVE_FIPS + ret = wc_InitRng_ex(&pkey->rng, heap, INVALID_DEVID); +#else + ret = wc_InitRng(&pkey->rng); +#endif + if (ret != 0){ + wolfSSL_EVP_PKEY_free(pkey); + WOLFSSL_MSG("memory failure"); + return NULL; + } + } + else { + WOLFSSL_MSG("memory failure"); + } + + return pkey; +} + + +void wolfSSL_EVP_PKEY_free(WOLFSSL_EVP_PKEY* key) +{ + WOLFSSL_ENTER("wolfSSL_EVP_PKEY_free"); + if (key != NULL) { + wc_FreeRng(&key->rng); + + if (key->pkey.ptr != NULL) { + XFREE(key->pkey.ptr, key->heap, DYNAMIC_TYPE_PUBLIC_KEY); + key->pkey.ptr = NULL; + } + switch(key->type) + { + #ifndef NO_RSA + case EVP_PKEY_RSA: + if (key->rsa != NULL && key->ownRsa == 1) { + wolfSSL_RSA_free(key->rsa); + key->rsa = NULL; + } + break; + #endif /* NO_RSA */ + + #ifdef HAVE_ECC + case EVP_PKEY_EC: + if (key->ecc != NULL && key->ownEcc == 1) { + wolfSSL_EC_KEY_free(key->ecc); + key->ecc = NULL; + } + break; + #endif /* HAVE_ECC */ + + default: + break; + } + XFREE(key, key->heap, DYNAMIC_TYPE_PUBLIC_KEY); + } +} +#endif /* OPENSSL_EXTRA_X509_SMALL */ + + +#ifdef OPENSSL_EXTRA + +void wolfSSL_X509_STORE_CTX_set_time(WOLFSSL_X509_STORE_CTX* ctx, + unsigned long flags, + time_t t) +{ + (void)flags; + + if (ctx == NULL || ctx->param == NULL) + return; + + ctx->param->check_time = t; + ctx->param->flags |= WOLFSSL_USE_CHECK_TIME; +} + +#ifndef NO_WOLFSSL_STUB +void wolfSSL_X509_OBJECT_free_contents(WOLFSSL_X509_OBJECT* obj) +{ + (void)obj; + WOLFSSL_STUB("X509_OBJECT_free_contents"); +} +#endif + +#ifndef NO_WOLFSSL_STUB +int wolfSSL_X509_cmp_current_time(const WOLFSSL_ASN1_TIME* asnTime) +{ + (void)asnTime; + WOLFSSL_STUB("X509_cmp_current_time"); + return 0; +} +#endif + +#ifndef NO_WOLFSSL_STUB +int wolfSSL_sk_X509_REVOKED_num(WOLFSSL_X509_REVOKED* revoked) +{ + (void)revoked; + WOLFSSL_STUB("sk_X509_REVOKED_num"); + return 0; +} +#endif + +#ifndef NO_WOLFSSL_STUB +WOLFSSL_X509_REVOKED* wolfSSL_X509_CRL_get_REVOKED(WOLFSSL_X509_CRL* crl) +{ + (void)crl; + WOLFSSL_STUB("X509_CRL_get_REVOKED"); + return 0; +} +#endif + +#ifndef NO_WOLFSSL_STUB +WOLFSSL_X509_REVOKED* wolfSSL_sk_X509_REVOKED_value( + WOLFSSL_X509_REVOKED* revoked, int value) +{ + (void)revoked; + (void)value; + WOLFSSL_STUB("sk_X509_REVOKED_value"); + return 0; +} +#endif + +/* Used to create a new WOLFSSL_ASN1_INTEGER structure. + * returns a pointer to new structure on success and NULL on failure + */ +WOLFSSL_ASN1_INTEGER* wolfSSL_ASN1_INTEGER_new(void) +{ + WOLFSSL_ASN1_INTEGER* a; + + a = (WOLFSSL_ASN1_INTEGER*)XMALLOC(sizeof(WOLFSSL_ASN1_INTEGER), NULL, + DYNAMIC_TYPE_OPENSSL); + if (a == NULL) { + return NULL; + } + + XMEMSET(a, 0, sizeof(WOLFSSL_ASN1_INTEGER)); + a->data = a->intData; + a->dataMax = WOLFSSL_ASN1_INTEGER_MAX; + return a; +} + + +/* free's internal elements of WOLFSSL_ASN1_INTEGER and free's "in" itself */ +void wolfSSL_ASN1_INTEGER_free(WOLFSSL_ASN1_INTEGER* in) +{ + if (in != NULL) { + if (in->isDynamic) { + XFREE(in->data, NULL, DYNAMIC_TYPE_OPENSSL); + } + XFREE(in, NULL, DYNAMIC_TYPE_OPENSSL); + } +} + + +WOLFSSL_ASN1_INTEGER* wolfSSL_X509_get_serialNumber(WOLFSSL_X509* x509) +{ + WOLFSSL_ASN1_INTEGER* a; + int i = 0; + + WOLFSSL_ENTER("wolfSSL_X509_get_serialNumber"); + + a = wolfSSL_ASN1_INTEGER_new(); + if (a == NULL) + return NULL; + + /* Make sure there is space for the data, ASN.1 type and length. */ + if (x509->serialSz > (WOLFSSL_ASN1_INTEGER_MAX - 2)) { + /* dynamically create data buffer, +2 for type and length */ + a->data = (unsigned char*)XMALLOC(x509->serialSz + 2, NULL, + DYNAMIC_TYPE_OPENSSL); + if (a->data == NULL) { + wolfSSL_ASN1_INTEGER_free(a); + return NULL; + } + a->dataMax = x509->serialSz + 2; + a->isDynamic = 1; + } + + a->data[i++] = ASN_INTEGER; + i += SetLength(x509->serialSz, a->data + i); + XMEMCPY(&a->data[i], x509->serial, x509->serialSz); + + return a; +} + +#endif /* OPENSSL_EXTRA */ + +#if defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(WOLFSSL_NGINX) || \ + defined(WOLFSSL_HAPROXY) || defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) +int wolfSSL_ASN1_TIME_print(WOLFSSL_BIO* bio, const WOLFSSL_ASN1_TIME* asnTime) +{ + char buf[MAX_TIME_STRING_SZ]; + int ret = WOLFSSL_SUCCESS; + + WOLFSSL_ENTER("wolfSSL_ASN1_TIME_print"); + + if (bio == NULL || asnTime == NULL) { + WOLFSSL_MSG("NULL function argument"); + return WOLFSSL_FAILURE; + } + + if (wolfSSL_ASN1_TIME_to_string((WOLFSSL_ASN1_TIME*)asnTime, buf, + sizeof(buf)) == NULL) { + XMEMSET(buf, 0, MAX_TIME_STRING_SZ); + XMEMCPY(buf, "Bad time value", 14); + ret = WOLFSSL_FAILURE; + } + + if (wolfSSL_BIO_write(bio, buf, (int)XSTRLEN(buf)) <= 0) { + WOLFSSL_MSG("Unable to write to bio"); + return WOLFSSL_FAILURE; + } + + return ret; +} + + +char* wolfSSL_ASN1_TIME_to_string(WOLFSSL_ASN1_TIME* t, char* buf, int len) +{ + int format; + int dateLen; + byte* date = (byte*)t; + + WOLFSSL_ENTER("wolfSSL_ASN1_TIME_to_string"); + + if (t == NULL || buf == NULL || len < 5) { + WOLFSSL_MSG("Bad argument"); + return NULL; + } + + format = *date; date++; + dateLen = *date; date++; + if (dateLen > len) { + WOLFSSL_MSG("Length of date is longer then buffer"); + return NULL; + } + + if (!GetTimeString(date, format, buf, len)) { + return NULL; + } + + return buf; +} +#endif /* WOLFSSL_MYSQL_COMPATIBLE || WOLFSSL_NGINX || WOLFSSL_HAPROXY || + OPENSSL_EXTRA*/ + + +#ifdef OPENSSL_EXTRA + +#if !defined(NO_ASN_TIME) && !defined(USER_TIME) && \ + !defined(TIME_OVERRIDES) && !defined(NO_FILESYSTEM) + +WOLFSSL_ASN1_TIME* wolfSSL_ASN1_TIME_adj(WOLFSSL_ASN1_TIME *s, time_t t, + int offset_day, long offset_sec) +{ + const time_t sec_per_day = 24*60*60; + struct tm* ts = NULL; + struct tm* tmpTime = NULL; + time_t t_adj = 0; + time_t offset_day_sec = 0; + +#if defined(NEED_TMP_TIME) + struct tm tmpTimeStorage; + tmpTime = &tmpTimeStorage; +#else + (void)tmpTime; +#endif + + WOLFSSL_ENTER("wolfSSL_ASN1_TIME_adj"); + + if (s == NULL){ + s = (WOLFSSL_ASN1_TIME*)XMALLOC(sizeof(WOLFSSL_ASN1_TIME), NULL, + DYNAMIC_TYPE_OPENSSL); + if (s == NULL){ + return NULL; + } + } + + /* compute GMT time with offset */ + offset_day_sec = offset_day * sec_per_day; + t_adj = t + offset_day_sec + offset_sec; + ts = (struct tm *)XGMTIME(&t_adj, tmpTime); + if (ts == NULL){ + WOLFSSL_MSG("failed to get time data."); + XFREE(s, NULL, DYNAMIC_TYPE_OPENSSL); + return NULL; + } + + /* create ASN1 time notation */ + /* UTC Time */ + if (ts->tm_year >= 50 && ts->tm_year < 150){ + char utc_str[ASN_UTC_TIME_SIZE]; + int utc_year = 0,utc_mon,utc_day,utc_hour,utc_min,utc_sec; + byte *data_ptr = NULL; + + if (ts->tm_year >= 50 && ts->tm_year < 100){ + utc_year = ts->tm_year; + } else if (ts->tm_year >= 100 && ts->tm_year < 150){ + utc_year = ts->tm_year - 100; + } + utc_mon = ts->tm_mon + 1; + utc_day = ts->tm_mday; + utc_hour = ts->tm_hour; + utc_min = ts->tm_min; + utc_sec = ts->tm_sec; + XSNPRINTF((char *)utc_str, ASN_UTC_TIME_SIZE, + "%02d%02d%02d%02d%02d%02dZ", + utc_year, utc_mon, utc_day, utc_hour, utc_min, utc_sec); + data_ptr = s->data; + *data_ptr = (byte) ASN_UTC_TIME; data_ptr++; + *data_ptr = (byte) ASN_UTC_TIME_SIZE; data_ptr++; + XMEMCPY(data_ptr,(byte *)utc_str, ASN_UTC_TIME_SIZE); + /* GeneralizedTime */ + } else { + char gt_str[ASN_GENERALIZED_TIME_MAX]; + int gt_year,gt_mon,gt_day,gt_hour,gt_min,gt_sec; + byte *data_ptr = NULL; + + gt_year = ts->tm_year + 1900; + gt_mon = ts->tm_mon + 1; + gt_day = ts->tm_mday; + gt_hour = ts->tm_hour; + gt_min = ts->tm_min; + gt_sec = ts->tm_sec; + XSNPRINTF((char *)gt_str, ASN_GENERALIZED_TIME_MAX, + "%4d%02d%02d%02d%02d%02dZ", + gt_year, gt_mon, gt_day, gt_hour, gt_min,gt_sec); + data_ptr = s->data; + *data_ptr = (byte) ASN_GENERALIZED_TIME; data_ptr++; + *data_ptr = (byte) ASN_GENERALIZED_TIME_SIZE; data_ptr++; + XMEMCPY(data_ptr,(byte *)gt_str, ASN_GENERALIZED_TIME_SIZE); + } + + return s; +} +#endif /* !NO_ASN_TIME && !USER_TIME && !TIME_OVERRIDES && !NO_FILESYSTEM */ + +#ifndef NO_WOLFSSL_STUB +int wolfSSL_ASN1_INTEGER_cmp(const WOLFSSL_ASN1_INTEGER* a, + const WOLFSSL_ASN1_INTEGER* b) +{ + (void)a; + (void)b; + WOLFSSL_STUB("ASN1_INTEGER_cmp"); + return 0; +} +#endif + +#ifndef NO_WOLFSSL_STUB +long wolfSSL_ASN1_INTEGER_get(const WOLFSSL_ASN1_INTEGER* i) +{ + (void)i; + WOLFSSL_STUB("ASN1_INTEGER_get"); + return 0; +} +#endif + + +void* wolfSSL_X509_STORE_CTX_get_ex_data(WOLFSSL_X509_STORE_CTX* ctx, int idx) +{ + WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_get_ex_data"); +#if defined(HAVE_EX_DATA) || defined(FORTRESS) + if (ctx != NULL && idx == 0) + return ctx->ex_data; +#else + (void)ctx; + (void)idx; +#endif + return 0; +} + + +/* Gets an index to store SSL structure at. + * + * Returns positive index on success and negative values on failure + */ +int wolfSSL_get_ex_data_X509_STORE_CTX_idx(void) +{ + WOLFSSL_ENTER("wolfSSL_get_ex_data_X509_STORE_CTX_idx"); + + /* store SSL at index 0 */ + return 0; +} + + +/* Set an error stat in the X509 STORE CTX + * + */ +void wolfSSL_X509_STORE_CTX_set_error(WOLFSSL_X509_STORE_CTX* ctx, int er) +{ + WOLFSSL_ENTER("wolfSSL_X509_STORE_CTX_set_error"); + + if (ctx != NULL) { + ctx->error = er; + } +} + + +/* Sets a function callback that will send information about the state of all + * WOLFSSL objects that have been created by the WOLFSSL_CTX structure passed + * in. + * + * ctx WOLFSSL_CTX structure to set callback function in + * f callback function to use + */ +void wolfSSL_CTX_set_info_callback(WOLFSSL_CTX* ctx, + void (*f)(const WOLFSSL* ssl, int type, int val)) +{ + WOLFSSL_ENTER("wolfSSL_CTX_set_info_callback"); + if (ctx == NULL) { + WOLFSSL_MSG("Bad function argument"); + } + else { + ctx->CBIS = f; + } +} + + +unsigned long wolfSSL_ERR_peek_error(void) +{ + WOLFSSL_ENTER("wolfSSL_ERR_peek_error"); + + return wolfSSL_ERR_peek_error_line_data(NULL, NULL, NULL, NULL); +} + + +/* This function is to find global error values that are the same through out + * all library version. With wolfSSL having only one set of error codes the + * return value is pretty straight forward. The only thing needed is all wolfSSL + * error values are typically negative. + * + * Returns the error reason + */ +int wolfSSL_ERR_GET_REASON(unsigned long err) +{ + int ret = (int)err; + + WOLFSSL_ENTER("wolfSSL_ERR_GET_REASON"); + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + /* Nginx looks for this error to know to stop parsing certificates. */ + if (err == ((ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE)) + return PEM_R_NO_START_LINE; +#endif + + /* check if error value is in range of wolfSSL errors */ + ret = 0 - ret; /* setting as negative value */ + /* wolfCrypt range is less than MAX (-100) + wolfSSL range is MIN (-300) and lower */ + if (ret < MAX_CODE_E) { + return ret; + } + else { + WOLFSSL_MSG("Not in range of typical error values"); + ret = (int)err; + } + + return ret; +} + + +/* returns a string that describes the alert + * + * alertID the alert value to look up + */ +const char* wolfSSL_alert_type_string_long(int alertID) +{ + WOLFSSL_ENTER("wolfSSL_aalert_type_string_long"); + + switch (alertID) { + case close_notify: + { + static const char close_notify_str[] = + "close_notify"; + return close_notify_str; + } + + case unexpected_message: + { + static const char unexpected_message_str[] = + "unexpected_message"; + return unexpected_message_str; + } + + case bad_record_mac: + { + static const char bad_record_mac_str[] = + "bad_record_mac"; + return bad_record_mac_str; + } + + case record_overflow: + { + static const char record_overflow_str[] = + "record_overflow"; + return record_overflow_str; + } + + case decompression_failure: + { + static const char decompression_failure_str[] = + "decompression_failure"; + return decompression_failure_str; + } + + case handshake_failure: + { + static const char handshake_failure_str[] = + "handshake_failure"; + return handshake_failure_str; + } + + case no_certificate: + { + static const char no_certificate_str[] = + "no_certificate"; + return no_certificate_str; + } + + case bad_certificate: + { + static const char bad_certificate_str[] = + "bad_certificate"; + return bad_certificate_str; + } + + case unsupported_certificate: + { + static const char unsupported_certificate_str[] = + "unsupported_certificate"; + return unsupported_certificate_str; + } + + case certificate_revoked: + { + static const char certificate_revoked_str[] = + "certificate_revoked"; + return certificate_revoked_str; + } + + case certificate_expired: + { + static const char certificate_expired_str[] = + "certificate_expired"; + return certificate_expired_str; + } + + case certificate_unknown: + { + static const char certificate_unknown_str[] = + "certificate_unknown"; + return certificate_unknown_str; + } + + case illegal_parameter: + { + static const char illegal_parameter_str[] = + "illegal_parameter"; + return illegal_parameter_str; + } + + case unknown_ca: + { + static const char unknown_ca_str[] = + "unknown_ca"; + return unknown_ca_str; + } + + case decode_error: + { + static const char decode_error_str[] = + "decode_error"; + return decode_error_str; + } + + case decrypt_error: + { + static const char decrypt_error_str[] = + "decrypt_error"; + return decrypt_error_str; + } + + #ifdef WOLFSSL_MYSQL_COMPATIBLE + /* catch name conflict for enum protocol with MYSQL build */ + case wc_protocol_version: + { + static const char wc_protocol_version_str[] = + "wc_protocol_version"; + return wc_protocol_version_str; + } + + #else + case protocol_version: + { + static const char protocol_version_str[] = + "protocol_version"; + return protocol_version_str; + } + + #endif + case no_renegotiation: + { + static const char no_renegotiation_str[] = + "no_renegotiation"; + return no_renegotiation_str; + } + + case unrecognized_name: + { + static const char unrecognized_name_str[] = + "unrecognized_name"; + return unrecognized_name_str; + } + + case bad_certificate_status_response: + { + static const char bad_certificate_status_response_str[] = + "bad_certificate_status_response"; + return bad_certificate_status_response_str; + } + + case no_application_protocol: + { + static const char no_application_protocol_str[] = + "no_application_protocol"; + return no_application_protocol_str; + } + + default: + WOLFSSL_MSG("Unknown Alert"); + return NULL; + } +} + + +const char* wolfSSL_alert_desc_string_long(int alertID) +{ + WOLFSSL_ENTER("wolfSSL_alert_desc_string_long"); + return wolfSSL_alert_type_string_long(alertID); +} + + +/* Gets the current state of the WOLFSSL structure + * + * ssl WOLFSSL structure to get state of + * + * Returns a human readable string of the WOLFSSL structure state + */ +const char* wolfSSL_state_string_long(const WOLFSSL* ssl) +{ + + static const char* OUTPUT_STR[14][6][3] = { + { + {"SSLv3 Initialization","SSLv3 Initialization","SSLv3 Initialization"}, + {"TLSv1 Initialization","TLSv2 Initialization","TLSv2 Initialization"}, + {"TLSv1_1 Initialization","TLSv1_1 Initialization","TLSv1_1 Initialization"}, + {"TLSv1_2 Initialization","TLSv1_2 Initialization","TLSv1_2 Initialization"}, + {"DTLSv1 Initialization","DTLSv1 Initialization","DTLSv1 Initialization"}, + {"DTLSv1_2 Initialization","DTLSv1_2 Initialization","DTLSv1_2 Initialization"}, + }, + { + {"SSLv3 read Server Hello Verify Request", + "SSLv3 write Server Hello Verify Request", + "SSLv3 Server Hello Verify Request"}, + {"TLSv1 read Server Hello Verify Request", + "TLSv1 write Server Hello Verify Request", + "TLSv1 Server Hello Verify Request"}, + {"TLSv1_1 read Server Hello Verify Request", + "TLSv1_1 write Server Hello Verify Request", + "TLSv1_1 Server Hello Verify Request"}, + {"TLSv1_2 read Server Hello Verify Request", + "TLSv1_2 write Server Hello Verify Request", + "TLSv1_2 Server Hello Verify Request"}, + {"DTLSv1 read Server Hello Verify Request", + "DTLSv1 write Server Hello Verify Request", + "DTLSv1 Server Hello Verify Request"}, + {"DTLSv1_2 read Server Hello Verify Request", + "DTLSv1_2 write Server Hello Verify Request", + "DTLSv1_2 Server Hello Verify Request"}, + }, + { + {"SSLv3 read Server Hello", + "SSLv3 write Server Hello", + "SSLv3 Server Hello"}, + {"TLSv1 read Server Hello", + "TLSv1 write Server Hello", + "TLSv1 Server Hello"}, + {"TLSv1_1 read Server Hello", + "TLSv1_1 write Server Hello", + "TLSv1_1 Server Hello"}, + {"TLSv1_2 read Server Hello", + "TLSv1_2 write Server Hello", + "TLSv1_2 Server Hello"}, + {"DTLSv1 read Server Hello", + "DTLSv1 write Server Hello", + "DTLSv1 Server Hello"}, + {"DTLSv1_2 read Server Hello" + "DTLSv1_2 write Server Hello", + "DTLSv1_2 Server Hello", + }, + }, + { + {"SSLv3 read Server Session Ticket", + "SSLv3 write Server Session Ticket", + "SSLv3 Server Session Ticket"}, + {"TLSv1 read Server Session Ticket", + "TLSv1 write Server Session Ticket", + "TLSv1 Server Session Ticket"}, + {"TLSv1_1 read Server Session Ticket", + "TLSv1_1 write Server Session Ticket", + "TLSv1_1 Server Session Ticket"}, + {"TLSv1_2 read Server Session Ticket", + "TLSv1_2 write Server Session Ticket", + "TLSv1_2 Server Session Ticket"}, + {"DTLSv1 read Server Session Ticket", + "DTLSv1 write Server Session Ticket", + "DTLSv1 Server Session Ticket"}, + {"DTLSv1_2 read Server Session Ticket", + "DTLSv1_2 write Server Session Ticket", + "DTLSv1_2 Server Session Ticket"}, + }, + { + {"SSLv3 read Server Cert", + "SSLv3 write Server Cert", + "SSLv3 Server Cert"}, + {"TLSv1 read Server Cert", + "TLSv1 write Server Cert", + "TLSv1 Server Cert"}, + {"TLSv1_1 read Server Cert", + "TLSv1_1 write Server Cert", + "TLSv1_1 Server Cert"}, + {"TLSv1_2 read Server Cert", + "TLSv1_2 write Server Cert", + "TLSv1_2 Server Cert"}, + {"DTLSv1 read Server Cert", + "DTLSv1 write Server Cert", + "DTLSv1 Server Cert"}, + {"DTLSv1_2 read Server Cert", + "DTLSv1_2 write Server Cert", + "DTLSv1_2 Server Cert"}, + }, + { + {"SSLv3 read Server Key Exchange", + "SSLv3 write Server Key Exchange", + "SSLv3 Server Key Exchange"}, + {"TLSv1 read Server Key Exchange", + "TLSv1 write Server Key Exchange", + "TLSv1 Server Key Exchange"}, + {"TLSv1_1 read Server Key Exchange", + "TLSv1_1 write Server Key Exchange", + "TLSv1_1 Server Key Exchange"}, + {"TLSv1_2 read Server Key Exchange", + "TLSv1_2 write Server Key Exchange", + "TLSv1_2 Server Key Exchange"}, + {"DTLSv1 read Server Key Exchange", + "DTLSv1 write Server Key Exchange", + "DTLSv1 Server Key Exchange"}, + {"DTLSv1_2 read Server Key Exchange", + "DTLSv1_2 write Server Key Exchange", + "DTLSv1_2 Server Key Exchange"}, + }, + { + {"SSLv3 read Server Hello Done", + "SSLv3 write Server Hello Done", + "SSLv3 Server Hello Done"}, + {"TLSv1 read Server Hello Done", + "TLSv1 write Server Hello Done", + "TLSv1 Server Hello Done"}, + {"TLSv1_1 read Server Hello Done", + "TLSv1_1 write Server Hello Done", + "TLSv1_1 Server Hello Done"}, + {"TLSv1_2 read Server Hello Done", + "TLSv1_2 write Server Hello Done", + "TLSv1_2 Server Hello Done"}, + {"DTLSv1 read Server Hello Done", + "DTLSv1 write Server Hello Done", + "DTLSv1 Server Hello Done"}, + {"DTLSv1_2 read Server Hello Done", + "DTLSv1_2 write Server Hello Done", + "DTLSv1_2 Server Hello Done"}, + }, + { + {"SSLv3 read Server Change CipherSpec", + "SSLv3 write Server Change CipherSpec", + "SSLv3 Server Change CipherSpec"}, + {"TLSv1 read Server Change CipherSpec", + "TLSv1 write Server Change CipherSpec", + "TLSv1 Server Change CipherSpec"}, + {"TLSv1_1 read Server Change CipherSpec", + "TLSv1_1 write Server Change CipherSpec", + "TLSv1_1 Server Change CipherSpec"}, + {"TLSv1_2 read Server Change CipherSpec", + "TLSv1_2 write Server Change CipherSpec", + "TLSv1_2 Server Change CipherSpec"}, + {"DTLSv1 read Server Change CipherSpec", + "DTLSv1 write Server Change CipherSpec", + "DTLSv1 Server Change CipherSpec"}, + {"DTLSv1_2 read Server Change CipherSpec", + "DTLSv1_2 write Server Change CipherSpec", + "DTLSv1_2 Server Change CipherSpec"}, + }, + { + {"SSLv3 read Server Finished", + "SSLv3 write Server Finished", + "SSLv3 Server Finished"}, + {"TLSv1 read Server Finished", + "TLSv1 write Server Finished", + "TLSv1 Server Finished"}, + {"TLSv1_1 read Server Finished", + "TLSv1_1 write Server Finished", + "TLSv1_1 Server Finished"}, + {"TLSv1_2 read Server Finished", + "TLSv1_2 write Server Finished", + "TLSv1_2 Server Finished"}, + {"DTLSv1 read Server Finished", + "DTLSv1 write Server Finished", + "DTLSv1 Server Finished"}, + {"DTLSv1_2 read Server Finished", + "DTLSv1_2 write Server Finished", + "DTLSv1_2 Server Finished"}, + }, + { + {"SSLv3 read Client Hello", + "SSLv3 write Client Hello", + "SSLv3 Client Hello"}, + {"TLSv1 read Client Hello", + "TLSv1 write Client Hello", + "TLSv1 Client Hello"}, + {"TLSv1_1 read Client Hello", + "TLSv1_1 write Client Hello", + "TLSv1_1 Client Hello"}, + {"TLSv1_2 read Client Hello", + "TLSv1_2 write Client Hello", + "TLSv1_2 Client Hello"}, + {"DTLSv1 read Client Hello", + "DTLSv1 write Client Hello", + "DTLSv1 Client Hello"}, + {"DTLSv1_2 read Client Hello", + "DTLSv1_2 write Client Hello", + "DTLSv1_2 Client Hello"}, + }, + { + {"SSLv3 read Client Key Exchange", + "SSLv3 write Client Key Exchange", + "SSLv3 Client Key Exchange"}, + {"TLSv1 read Client Key Exchange", + "TLSv1 write Client Key Exchange", + "TLSv1 Client Key Exchange"}, + {"TLSv1_1 read Client Key Exchange", + "TLSv1_1 write Client Key Exchange", + "TLSv1_1 Client Key Exchange"}, + {"TLSv1_2 read Client Key Exchange", + "TLSv1_2 write Client Key Exchange", + "TLSv1_2 Client Key Exchange"}, + {"DTLSv1 read Client Key Exchange", + "DTLSv1 write Client Key Exchange", + "DTLSv1 Client Key Exchange"}, + {"DTLSv1_2 read Client Key Exchange", + "DTLSv1_2 write Client Key Exchange", + "DTLSv1_2 Client Key Exchange"}, + }, + { + {"SSLv3 read Client Change CipherSpec", + "SSLv3 write Client Change CipherSpec", + "SSLv3 Client Change CipherSpec"}, + {"TLSv1 read Client Change CipherSpec", + "TLSv1 write Client Change CipherSpec", + "TLSv1 Client Change CipherSpec"}, + {"TLSv1_1 read Client Change CipherSpec", + "TLSv1_1 write Client Change CipherSpec", + "TLSv1_1 Client Change CipherSpec"}, + {"TLSv1_2 read Client Change CipherSpec", + "TLSv1_2 write Client Change CipherSpec", + "TLSv1_2 Client Change CipherSpec"}, + {"DTLSv1 read Client Change CipherSpec", + "DTLSv1 write Client Change CipherSpec", + "DTLSv1 Client Change CipherSpec"}, + {"DTLSv1_2 read Client Change CipherSpec", + "DTLSv1_2 write Client Change CipherSpec", + "DTLSv1_2 Client Change CipherSpec"}, + }, + { + {"SSLv3 read Client Finished", + "SSLv3 write Client Finished", + "SSLv3 Client Finished"}, + {"TLSv1 read Client Finished", + "TLSv1 write Client Finished", + "TLSv1 Client Finished"}, + {"TLSv1_1 read Client Finished", + "TLSv1_1 write Client Finished", + "TLSv1_1 Client Finished"}, + {"TLSv1_2 read Client Finished", + "TLSv1_2 write Client Finished", + "TLSv1_2 Client Finished"}, + {"DTLSv1 read Client Finished", + "DTLSv1 write Client Finished", + "DTLSv1 Client Finished"}, + {"DTLSv1_2 read Client Finished", + "DTLSv1_2 write Client Finished", + "DTLSv1_2 Client Finished"}, + }, + { + {"SSLv3 Handshake Done", + "SSLv3 Handshake Done", + "SSLv3 Handshake Done"}, + {"TLSv1 Handshake Done", + "TLSv1 Handshake Done", + "TLSv1 Handshake Done"}, + {"TLSv1_1 Handshake Done", + "TLSv1_1 Handshake Done", + "TLSv1_1 Handshake Done"}, + {"TLSv1_2 Handshake Done", + "TLSv1_2 Handshake Done", + "TLSv1_2 Handshake Done"}, + {"DTLSv1 Handshake Done", + "DTLSv1 Handshake Done", + "DTLSv1 Handshake Done"}, + {"DTLSv1_2 Handshake Done" + "DTLSv1_2 Handshake Done" + "DTLSv1_2 Handshake Done"} + } + }; + enum ProtocolVer { + SSL_V3 = 0, + TLS_V1, + TLS_V1_1, + TLS_V1_2, + DTLS_V1, + DTLS_V1_2, + UNKNOWN = 100 + }; + + enum IOMode { + SS_READ = 0, + SS_WRITE, + SS_NEITHER + }; + + enum SslState { + ss_null_state = 0, + ss_server_helloverify, + ss_server_hello, + ss_sessionticket, + ss_server_cert, + ss_server_keyexchange, + ss_server_hellodone, + ss_server_changecipherspec, + ss_server_finished, + ss_client_hello, + ss_client_keyexchange, + ss_client_changecipherspec, + ss_client_finished, + ss_handshake_done + }; + + int protocol = 0; + int cbmode = 0; + int state = 0; + + WOLFSSL_ENTER("wolfSSL_state_string_long"); + if (ssl == NULL) { + WOLFSSL_MSG("Null argument passed in"); + return NULL; + } + + /* Get state of callback */ + if (ssl->cbmode == SSL_CB_MODE_WRITE){ + cbmode = SS_WRITE; + } else if (ssl->cbmode == SSL_CB_MODE_READ){ + cbmode = SS_READ; + } else { + cbmode = SS_NEITHER; + } + + /* Get protocol version */ + switch (ssl->version.major){ + case SSLv3_MAJOR: + switch (ssl->version.minor){ + case TLSv1_MINOR: + protocol = TLS_V1; + break; + case TLSv1_1_MINOR: + protocol = TLS_V1_1; + break; + case TLSv1_2_MINOR: + protocol = TLS_V1_2; + break; + case SSLv3_MINOR: + protocol = SSL_V3; + break; + default: + protocol = UNKNOWN; + } + break; + case DTLS_MAJOR: + switch (ssl->version.minor){ + case DTLS_MINOR: + protocol = DTLS_V1; + break; + case DTLSv1_2_MINOR: + protocol = DTLS_V1_2; + break; + default: + protocol = UNKNOWN; + } + break; + default: + protocol = UNKNOWN; + } + + /* accept process */ + if (ssl->cbmode == SSL_CB_MODE_READ){ + state = ssl->cbtype; + switch (state) { + case hello_verify_request: + state = ss_server_helloverify; + break; + case session_ticket: + state = ss_sessionticket; + break; + case server_hello: + state = ss_server_hello; + break; + case server_hello_done: + state = ss_server_hellodone; + break; + case certificate: + state = ss_server_cert; + break; + case server_key_exchange: + state = ss_server_keyexchange; + break; + case client_hello: + state = ss_client_hello; + break; + case client_key_exchange: + state = ss_client_keyexchange; + break; + case finished: + if (ssl->options.side == WOLFSSL_SERVER_END) + state = ss_client_finished; + else if (ssl->options.side == WOLFSSL_CLIENT_END) + state = ss_server_finished; + else { + WOLFSSL_MSG("Unknown State"); + state = ss_null_state; + } + break; + default: + WOLFSSL_MSG("Unknown State"); + state = ss_null_state; + } + } else { + /* Send process */ + if (ssl->options.side == WOLFSSL_SERVER_END) + state = ssl->options.serverState; + else + state = ssl->options.clientState; + + switch(state){ + case SERVER_HELLOVERIFYREQUEST_COMPLETE: + state = ss_server_helloverify; + break; + case SERVER_HELLO_COMPLETE: + state = ss_server_hello; + break; + case SERVER_CERT_COMPLETE: + state = ss_server_cert; + break; + case SERVER_KEYEXCHANGE_COMPLETE: + state = ss_server_keyexchange; + break; + case SERVER_HELLODONE_COMPLETE: + state = ss_server_hellodone; + break; + case SERVER_CHANGECIPHERSPEC_COMPLETE: + state = ss_server_changecipherspec; + break; + case SERVER_FINISHED_COMPLETE: + state = ss_server_finished; + break; + case CLIENT_HELLO_COMPLETE: + state = ss_client_hello; + break; + case CLIENT_KEYEXCHANGE_COMPLETE: + state = ss_client_keyexchange; + break; + case CLIENT_CHANGECIPHERSPEC_COMPLETE: + state = ss_client_changecipherspec; + break; + case CLIENT_FINISHED_COMPLETE: + state = ss_client_finished; + break; + case HANDSHAKE_DONE: + state = ss_handshake_done; + break; + default: + WOLFSSL_MSG("Unknown State"); + state = ss_null_state; + } + } + + if (protocol == UNKNOWN) + return NULL; + else + return OUTPUT_STR[state][protocol][cbmode]; +} + +#ifndef NO_WOLFSSL_STUB +int wolfSSL_PEM_def_callback(char* name, int num, int w, void* key) +{ + (void)name; + (void)num; + (void)w; + (void)key; + WOLFSSL_STUB("PEM_def_callback"); + return 0; +} +#endif + +#endif + +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) +static long wolf_set_options(long old_op, long op) +{ + /* if SSL_OP_ALL then turn all bug workarounds on */ + if ((op & SSL_OP_ALL) == SSL_OP_ALL) { + WOLFSSL_MSG("\tSSL_OP_ALL"); + + op |= SSL_OP_MICROSOFT_SESS_ID_BUG; + op |= SSL_OP_NETSCAPE_CHALLENGE_BUG; + op |= SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG; + op |= SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG; + op |= SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER; + op |= SSL_OP_MSIE_SSLV2_RSA_PADDING; + op |= SSL_OP_SSLEAY_080_CLIENT_DH_BUG; + op |= SSL_OP_TLS_D5_BUG; + op |= SSL_OP_TLS_BLOCK_PADDING_BUG; + op |= SSL_OP_TLS_ROLLBACK_BUG; + op |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; + } + + /* by default cookie exchange is on with DTLS */ + if ((op & SSL_OP_COOKIE_EXCHANGE) == SSL_OP_COOKIE_EXCHANGE) { + WOLFSSL_MSG("\tSSL_OP_COOKIE_EXCHANGE : on by default"); + } + + if ((op & WOLFSSL_OP_NO_SSLv2) == WOLFSSL_OP_NO_SSLv2) { + WOLFSSL_MSG("\tWOLFSSL_OP_NO_SSLv2 : wolfSSL does not support SSLv2"); + } + + if ((op & SSL_OP_NO_TLSv1_3) == SSL_OP_NO_TLSv1_3) { + WOLFSSL_MSG("\tSSL_OP_NO_TLSv1_3"); + } + + if ((op & SSL_OP_NO_TLSv1_2) == SSL_OP_NO_TLSv1_2) { + WOLFSSL_MSG("\tSSL_OP_NO_TLSv1_2"); + } + + if ((op & SSL_OP_NO_TLSv1_1) == SSL_OP_NO_TLSv1_1) { + WOLFSSL_MSG("\tSSL_OP_NO_TLSv1_1"); + } + + if ((op & SSL_OP_NO_TLSv1) == SSL_OP_NO_TLSv1) { + WOLFSSL_MSG("\tSSL_OP_NO_TLSv1"); + } + + if ((op & SSL_OP_NO_SSLv3) == SSL_OP_NO_SSLv3) { + WOLFSSL_MSG("\tSSL_OP_NO_SSLv3"); + } + + if ((op & SSL_OP_NO_COMPRESSION) == SSL_OP_NO_COMPRESSION) { + #ifdef HAVE_LIBZ + WOLFSSL_MSG("SSL_OP_NO_COMPRESSION"); + #else + WOLFSSL_MSG("SSL_OP_NO_COMPRESSION: compression not compiled in"); + #endif + } + + return old_op | op; +} +#endif + +#ifdef OPENSSL_EXTRA +long wolfSSL_set_options(WOLFSSL* ssl, long op) +{ + word16 haveRSA = 1; + word16 havePSK = 0; + int keySz = 0; + + WOLFSSL_ENTER("wolfSSL_set_options"); + + if (ssl == NULL) { + return 0; + } + + ssl->options.mask = wolf_set_options(ssl->options.mask, op); + + if ((ssl->options.mask & SSL_OP_NO_TLSv1_3) == SSL_OP_NO_TLSv1_3) { + if (ssl->version.minor == TLSv1_3_MINOR) + ssl->version.minor = TLSv1_2_MINOR; + } + + if ((ssl->options.mask & SSL_OP_NO_TLSv1_2) == SSL_OP_NO_TLSv1_2) { + if (ssl->version.minor == TLSv1_2_MINOR) + ssl->version.minor = TLSv1_1_MINOR; + } + + if ((ssl->options.mask & SSL_OP_NO_TLSv1_1) == SSL_OP_NO_TLSv1_1) { + if (ssl->version.minor == TLSv1_1_MINOR) + ssl->version.minor = TLSv1_MINOR; + } + + if ((ssl->options.mask & SSL_OP_NO_TLSv1) == SSL_OP_NO_TLSv1) { + if (ssl->version.minor == TLSv1_MINOR) + ssl->version.minor = SSLv3_MINOR; + } + + if ((ssl->options.mask & SSL_OP_NO_COMPRESSION) == SSL_OP_NO_COMPRESSION) { + #ifdef HAVE_LIBZ + ssl->options.usingCompression = 0; + #endif + } + + /* in the case of a version change the cipher suites should be reset */ +#ifndef NO_PSK + havePSK = ssl->options.havePSK; +#endif +#ifdef NO_RSA + haveRSA = 0; +#endif +#ifndef NO_CERTS + keySz = ssl->buffers.keySz; +#endif + + InitSuites(ssl->suites, ssl->version, keySz, haveRSA, havePSK, + ssl->options.haveDH, ssl->options.haveNTRU, + ssl->options.haveECDSAsig, ssl->options.haveECC, + ssl->options.haveStaticECC, ssl->options.side); + + return ssl->options.mask; +} + + +long wolfSSL_get_options(const WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_get_options"); + if(ssl == NULL) + return WOLFSSL_FAILURE; + return ssl->options.mask; +} + +long wolfSSL_clear_options(WOLFSSL* ssl, long opt) +{ + WOLFSSL_ENTER("SSL_clear_options"); + if(ssl == NULL) + return WOLFSSL_FAILURE; + ssl->options.mask &= ~opt; + return ssl->options.mask; +} + +/*** TBD ***/ +#ifndef NO_WOLFSSL_STUB +WOLFSSL_API long wolfSSL_clear_num_renegotiations(WOLFSSL *s) +{ + (void)s; + WOLFSSL_STUB("SSL_clear_num_renegotiations"); + return 0; +} +#endif + +/*** TBD ***/ +#ifndef NO_WOLFSSL_STUB +WOLFSSL_API long wolfSSL_total_renegotiations(WOLFSSL *s) +{ + (void)s; + WOLFSSL_STUB("SSL_total_renegotiations"); + return 0; +} +#endif + +#ifndef NO_DH +long wolfSSL_set_tmp_dh(WOLFSSL *ssl, WOLFSSL_DH *dh) +{ + int pSz, gSz; + byte *p, *g; + int ret = 0; + + WOLFSSL_ENTER("wolfSSL_set_tmp_dh"); + + if (!ssl || !dh) + return BAD_FUNC_ARG; + + /* Get needed size for p and g */ + pSz = wolfSSL_BN_bn2bin(dh->p, NULL); + gSz = wolfSSL_BN_bn2bin(dh->g, NULL); + + if (pSz <= 0 || gSz <= 0) + return WOLFSSL_FATAL_ERROR; + + p = (byte*)XMALLOC(pSz, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + if (!p) + return MEMORY_E; + + g = (byte*)XMALLOC(gSz, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + if (!g) { + XFREE(p, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + return MEMORY_E; + } + + pSz = wolfSSL_BN_bn2bin(dh->p, p); + gSz = wolfSSL_BN_bn2bin(dh->g, g); + + if (pSz >= 0 && gSz >= 0) /* Conversion successful */ + ret = wolfSSL_SetTmpDH(ssl, p, pSz, g, gSz); + + XFREE(p, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + XFREE(g, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + + return pSz > 0 && gSz > 0 ? ret : WOLFSSL_FATAL_ERROR; +} +#endif /* !NO_DH */ + + +#ifdef HAVE_PK_CALLBACKS +long wolfSSL_set_tlsext_debug_arg(WOLFSSL* ssl, void *arg) +{ + if (ssl == NULL) { + return WOLFSSL_FAILURE; + } + + ssl->loggingCtx = arg; + return WOLFSSL_SUCCESS; +} +#endif /* HAVE_PK_CALLBACKS */ + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_HAPROXY) +const unsigned char *SSL_SESSION_get0_id_context(const SSL_SESSION *sess, unsigned int *sid_ctx_length) +{ + const byte *c = wolfSSL_SESSION_get_id((SSL_SESSION *)sess, sid_ctx_length); + return c; +} +#endif + +/*** TBD ***/ +#ifndef NO_WOLFSSL_STUB +WOLFSSL_API int wolfSSL_sk_SSL_COMP_zero(WOLFSSL_STACK* st) +{ + (void)st; + WOLFSSL_STUB("wolfSSL_sk_SSL_COMP_zero"); + /* wolfSSL_set_options(ssl, SSL_OP_NO_COMPRESSION); */ + return WOLFSSL_FAILURE; +} +#endif + +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST +long wolfSSL_set_tlsext_status_type(WOLFSSL *s, int type) +{ + WOLFSSL_ENTER("wolfSSL_set_tlsext_status_type"); + + if (s == NULL){ + return BAD_FUNC_ARG; + } + + if (type == TLSEXT_STATUSTYPE_ocsp){ + int r = 0; + r = TLSX_UseCertificateStatusRequest(&s->extensions, type, 0, s, + s->heap, s->devId); + return (long)r; + } else { + WOLFSSL_MSG( + "SSL_set_tlsext_status_type only supports TLSEXT_STATUSTYPE_ocsp type."); + return SSL_FAILURE; + } + +} +#endif /* HAVE_CERTIFICATE_STATUS_REQUEST */ + +#ifndef NO_WOLFSSL_STUB +WOLFSSL_API long wolfSSL_get_tlsext_status_exts(WOLFSSL *s, void *arg) +{ + (void)s; + (void)arg; + WOLFSSL_STUB("wolfSSL_get_tlsext_status_exts"); + return WOLFSSL_FAILURE; +} +#endif + +/*** TBD ***/ +#ifndef NO_WOLFSSL_STUB +WOLFSSL_API long wolfSSL_set_tlsext_status_exts(WOLFSSL *s, void *arg) +{ + (void)s; + (void)arg; + WOLFSSL_STUB("wolfSSL_set_tlsext_status_exts"); + return WOLFSSL_FAILURE; +} +#endif + +/*** TBD ***/ +#ifndef NO_WOLFSSL_STUB +WOLFSSL_API long wolfSSL_get_tlsext_status_ids(WOLFSSL *s, void *arg) +{ + (void)s; + (void)arg; + WOLFSSL_STUB("wolfSSL_get_tlsext_status_ids"); + return WOLFSSL_FAILURE; +} +#endif + +/*** TBD ***/ +#ifndef NO_WOLFSSL_STUB +WOLFSSL_API long wolfSSL_set_tlsext_status_ids(WOLFSSL *s, void *arg) +{ + (void)s; + (void)arg; + WOLFSSL_STUB("wolfSSL_set_tlsext_status_ids"); + return WOLFSSL_FAILURE; +} +#endif + +/*** TBD ***/ +#ifndef NO_WOLFSSL_STUB +WOLFSSL_API int SSL_SESSION_set1_id(WOLFSSL_SESSION *s, const unsigned char *sid, unsigned int sid_len) +{ + (void)s; + (void)sid; + (void)sid_len; + WOLFSSL_STUB("SSL_SESSION_set1_id"); + return WOLFSSL_FAILURE; +} +#endif + +#ifndef NO_WOLFSSL_STUB +/*** TBD ***/ +WOLFSSL_API int SSL_SESSION_set1_id_context(WOLFSSL_SESSION *s, const unsigned char *sid_ctx, unsigned int sid_ctx_len) +{ + (void)s; + (void)sid_ctx; + (void)sid_ctx_len; + WOLFSSL_STUB("SSL_SESSION_set1_id_context"); + return WOLFSSL_FAILURE; +} +#endif + +#ifndef NO_WOLFSSL_STUB +/*** TBD ***/ +WOLFSSL_API void *X509_get0_tbs_sigalg(const WOLFSSL_X509 *x) +{ + (void)x; + WOLFSSL_STUB("X509_get0_tbs_sigalg"); + return NULL; +} +#endif + +#ifndef NO_WOLFSSL_STUB +/*** TBD ***/ +WOLFSSL_API void X509_ALGOR_get0(WOLFSSL_ASN1_OBJECT **paobj, int *pptype, const void **ppval, const void *algor) +{ + (void)paobj; + (void)pptype; + (void)ppval; + (void)algor; + WOLFSSL_STUB("X509_ALGOR_get0"); +} +#endif + +#ifndef NO_WOLFSSL_STUB +/*** TBD ***/ +WOLFSSL_API void *X509_get_X509_PUBKEY(void * x) +{ + (void)x; + WOLFSSL_STUB("X509_get_X509_PUBKEY"); + return NULL; +} +#endif + +#ifndef NO_WOLFSSL_STUB +/*** TBD ***/ +WOLFSSL_API int X509_PUBKEY_get0_param(WOLFSSL_ASN1_OBJECT **ppkalg, const unsigned char **pk, int *ppklen, void **pa, WOLFSSL_EVP_PKEY *pub) +{ + (void)ppkalg; + (void)pk; + (void)ppklen; + (void)pa; + (void)pub; + WOLFSSL_STUB("X509_PUBKEY_get0_param"); + return WOLFSSL_FAILURE; +} +#endif + +#ifndef NO_WOLFSSL_STUB +/*** TBD ***/ +WOLFSSL_API WOLFSSL_EVP_PKEY *wolfSSL_get_privatekey(const WOLFSSL *ssl) +{ + (void)ssl; + WOLFSSL_STUB("SSL_get_privatekey"); + return NULL; +} +#endif + +#ifndef NO_WOLFSSL_STUB +/*** TBD ***/ +WOLFSSL_API int i2t_ASN1_OBJECT(char *buf, int buf_len, WOLFSSL_ASN1_OBJECT *a) +{ + (void)buf; + (void)buf_len; + (void)a; + WOLFSSL_STUB("i2t_ASN1_OBJECT"); + return -1; +} +#endif + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_HAPROXY) +#ifndef NO_WOLFSSL_STUB +/*** TBD ***/ +WOLFSSL_API size_t SSL_get_finished(const WOLFSSL *s, void *buf, size_t count) +{ + (void)s; + (void)buf; + (void)count; + WOLFSSL_STUB("SSL_get_finished"); + return WOLFSSL_FAILURE; +} +#endif + +#ifndef NO_WOLFSSL_STUB +/*** TBD ***/ +WOLFSSL_API size_t SSL_get_peer_finished(const WOLFSSL *s, void *buf, size_t count) +{ + (void)s; + (void)buf; + (void)count; + WOLFSSL_STUB("SSL_get_peer_finished"); + return WOLFSSL_FAILURE; +} +#endif +#endif /* WOLFSSL_HAPROXY */ + +#ifndef NO_WOLFSSL_STUB +/*** TBD ***/ +WOLFSSL_API void SSL_CTX_set_tmp_dh_callback(WOLFSSL_CTX *ctx, WOLFSSL_DH *(*dh) (WOLFSSL *ssl, int is_export, int keylength)) +{ + (void)ctx; + (void)dh; + WOLFSSL_STUB("SSL_CTX_set_tmp_dh_callback"); +} +#endif + +#ifndef NO_WOLFSSL_STUB +/*** TBD ***/ +WOLFSSL_API WOLF_STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void) +{ + WOLFSSL_STUB("SSL_COMP_get_compression_methods"); + return NULL; +} +#endif + +#ifndef NO_WOLFSSL_STUB +/*** TBD ***/ +WOLFSSL_API int wolfSSL_sk_SSL_CIPHER_num(const void * p) +{ + (void)p; + WOLFSSL_STUB("wolfSSL_sk_SSL_CIPHER_num"); + return -1; +} +#endif + +#if !defined(NO_FILESYSTEM) +#ifndef NO_WOLFSSL_STUB +/*** TBD ***/ +WOLFSSL_API WOLFSSL_EVP_PKEY *wolfSSL_PEM_read_PrivateKey(XFILE fp, WOLFSSL_EVP_PKEY **x, pem_password_cb *cb, void *u) +{ + (void)fp; + (void)x; + (void)cb; + (void)u; + WOLFSSL_STUB("PEM_read_PrivateKey"); + return NULL; +} +#endif +#endif + +#ifndef NO_WOLFSSL_STUB +/*** TBD ***/ +WOLFSSL_API int X509_STORE_load_locations(WOLFSSL_X509_STORE *ctx, const char *file, const char *dir) +{ + (void)ctx; + (void)file; + (void)dir; + WOLFSSL_STUB("X509_STORE_load_locations"); + return WOLFSSL_FAILURE; +} +#endif + +#ifndef NO_WOLFSSL_STUB +/*** TBD ***/ +WOLFSSL_API WOLFSSL_CIPHER* wolfSSL_sk_SSL_CIPHER_value(void *ciphers, int idx) +{ + (void)ciphers; + (void)idx; + WOLFSSL_STUB("wolfSSL_sk_SSL_CIPHER_value"); + return NULL; +} +#endif + +WOLFSSL_API void ERR_load_SSL_strings(void) +{ + +} + +#ifdef HAVE_OCSP +WOLFSSL_API long wolfSSL_get_tlsext_status_ocsp_resp(WOLFSSL *s, unsigned char **resp) +{ + if (s == NULL || resp == NULL) + return 0; + + *resp = s->ocspResp; + return s->ocspRespSz; +} + +WOLFSSL_API long wolfSSL_set_tlsext_status_ocsp_resp(WOLFSSL *s, unsigned char *resp, int len) +{ + if (s == NULL) + return WOLFSSL_FAILURE; + + s->ocspResp = resp; + s->ocspRespSz = len; + + return WOLFSSL_SUCCESS; +} +#endif /* HAVE_OCSP */ + +#endif /* OPENSSL_EXTRA */ + +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) +long wolfSSL_get_verify_result(const WOLFSSL *ssl) +{ + if (ssl == NULL) { + return WOLFSSL_FAILURE; + } + + return ssl->peerVerifyRet; +} +#endif + +#ifdef OPENSSL_EXTRA + +#ifndef NO_WOLFSSL_STUB +/* shows the number of accepts attempted by CTX in it's lifetime */ +long wolfSSL_CTX_sess_accept(WOLFSSL_CTX* ctx) +{ + WOLFSSL_STUB("wolfSSL_CTX_sess_accept"); + (void)ctx; + return 0; +} +#endif + +#ifndef NO_WOLFSSL_STUB +/* shows the number of connects attempted CTX in it's lifetime */ +long wolfSSL_CTX_sess_connect(WOLFSSL_CTX* ctx) +{ + WOLFSSL_STUB("wolfSSL_CTX_sess_connect"); + (void)ctx; + return 0; +} +#endif + + +#ifndef NO_WOLFSSL_STUB +/* shows the number of accepts completed by CTX in it's lifetime */ +long wolfSSL_CTX_sess_accept_good(WOLFSSL_CTX* ctx) +{ + WOLFSSL_STUB("wolfSSL_CTX_sess_accept_good"); + (void)ctx; + return 0; +} +#endif + + +#ifndef NO_WOLFSSL_STUB +/* shows the number of connects completed by CTX in it's lifetime */ +long wolfSSL_CTX_sess_connect_good(WOLFSSL_CTX* ctx) +{ + WOLFSSL_STUB("wolfSSL_CTX_sess_connect_good"); + (void)ctx; + return 0; +} +#endif + + +#ifndef NO_WOLFSSL_STUB +/* shows the number of renegotiation accepts attempted by CTX */ +long wolfSSL_CTX_sess_accept_renegotiate(WOLFSSL_CTX* ctx) +{ + WOLFSSL_STUB("wolfSSL_CTX_sess_accept_renegotiate"); + (void)ctx; + return 0; +} +#endif + + +#ifndef NO_WOLFSSL_STUB +/* shows the number of renegotiation accepts attempted by CTX */ +long wolfSSL_CTX_sess_connect_renegotiate(WOLFSSL_CTX* ctx) +{ + WOLFSSL_STUB("wolfSSL_CTX_sess_connect_renegotiate"); + (void)ctx; + return 0; +} +#endif + + +#ifndef NO_WOLFSSL_STUB +long wolfSSL_CTX_sess_hits(WOLFSSL_CTX* ctx) +{ + WOLFSSL_STUB("wolfSSL_CTX_sess_hits"); + (void)ctx; + return 0; +} +#endif + + +#ifndef NO_WOLFSSL_STUB +long wolfSSL_CTX_sess_cb_hits(WOLFSSL_CTX* ctx) +{ + WOLFSSL_STUB("wolfSSL_CTX_sess_cb_hits"); + (void)ctx; + return 0; +} +#endif + + +#ifndef NO_WOLFSSL_STUB +long wolfSSL_CTX_sess_cache_full(WOLFSSL_CTX* ctx) +{ + WOLFSSL_STUB("wolfSSL_CTX_sess_cache_full"); + (void)ctx; + return 0; +} +#endif + + +#ifndef NO_WOLFSSL_STUB +long wolfSSL_CTX_sess_misses(WOLFSSL_CTX* ctx) +{ + WOLFSSL_STUB("wolfSSL_CTX_sess_misses"); + (void)ctx; + return 0; +} +#endif + + +#ifndef NO_WOLFSSL_STUB +long wolfSSL_CTX_sess_timeouts(WOLFSSL_CTX* ctx) +{ + WOLFSSL_STUB("wolfSSL_CTX_sess_timeouts"); + (void)ctx; + return 0; +} +#endif + + +/* Return the total number of sessions */ +long wolfSSL_CTX_sess_number(WOLFSSL_CTX* ctx) +{ + word32 total = 0; + + WOLFSSL_ENTER("wolfSSL_CTX_sess_number"); + (void)ctx; + +#ifdef WOLFSSL_SESSION_STATS + if (wolfSSL_get_session_stats(NULL, &total, NULL, NULL) != SSL_SUCCESS) { + WOLFSSL_MSG("Error getting session stats"); + } +#else + WOLFSSL_MSG("Please use macro WOLFSSL_SESSION_STATS for session stats"); +#endif + + return (long)total; +} + + +#ifndef NO_CERTS +long wolfSSL_CTX_add_extra_chain_cert(WOLFSSL_CTX* ctx, WOLFSSL_X509* x509) +{ + byte* chain = NULL; + long chainSz = 0; + int derSz; + const byte* der; + int ret; + int idx = 0; + DerBuffer *derBuffer = NULL; + + WOLFSSL_ENTER("wolfSSL_CTX_add_extra_chain_cert"); + + if (ctx == NULL || x509 == NULL) { + WOLFSSL_MSG("Bad Argument"); + return WOLFSSL_FAILURE; + } + + der = wolfSSL_X509_get_der(x509, &derSz); + if (der == NULL || derSz <= 0) { + WOLFSSL_MSG("Error getting X509 DER"); + return WOLFSSL_FAILURE; + } + + if (ctx->certificate == NULL) { + /* Process buffer makes first certificate the leaf. */ + ret = ProcessBuffer(ctx, der, derSz, WOLFSSL_FILETYPE_ASN1, CERT_TYPE, + NULL, NULL, 1); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_LEAVE("wolfSSL_CTX_add_extra_chain_cert", ret); + return WOLFSSL_FAILURE; + } + } + else { + /* TODO: Do this elsewhere. */ + ret = AllocDer(&derBuffer, derSz, CERT_TYPE, ctx->heap); + if (ret != 0) { + WOLFSSL_MSG("Memory Error"); + return WOLFSSL_FAILURE; + } + XMEMCPY(derBuffer->buffer, der, derSz); + ret = AddCA(ctx->cm, &derBuffer, WOLFSSL_USER_CA, !ctx->verifyNone); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_LEAVE("wolfSSL_CTX_add_extra_chain_cert", ret); + return WOLFSSL_FAILURE; + } + + /* adding cert to existing chain */ + if (ctx->certChain != NULL && ctx->certChain->length > 0) { + chainSz += ctx->certChain->length; + } + chainSz += OPAQUE24_LEN + derSz; + + chain = (byte*)XMALLOC(chainSz, ctx->heap, DYNAMIC_TYPE_DER); + if (chain == NULL) { + WOLFSSL_MSG("Memory Error"); + return WOLFSSL_FAILURE; + } + + if (ctx->certChain != NULL && ctx->certChain->length > 0) { + XMEMCPY(chain, ctx->certChain->buffer, ctx->certChain->length); + idx = ctx->certChain->length; + } + c32to24(derSz, chain + idx); + idx += OPAQUE24_LEN, + XMEMCPY(chain + idx, der, derSz); + idx += derSz; +#ifdef WOLFSSL_TLS13 + ctx->certChainCnt++; +#endif + + FreeDer(&ctx->certChain); + ret = AllocDer(&ctx->certChain, idx, CERT_TYPE, ctx->heap); + if (ret == 0) { + XMEMCPY(ctx->certChain->buffer, chain, idx); + } + } + + /* on success WOLFSSL_X509 memory is responsibility of ctx */ + wolfSSL_X509_free(x509); + if (chain != NULL) + XFREE(chain, ctx->heap, DYNAMIC_TYPE_DER); + + return WOLFSSL_SUCCESS; +} + + +long wolfSSL_CTX_set_tlsext_status_arg(WOLFSSL_CTX* ctx, void* arg) +{ + if (ctx == NULL || ctx->cm == NULL) { + return WOLFSSL_FAILURE; + } + + ctx->cm->ocspIOCtx = arg; + return WOLFSSL_SUCCESS; +} + +#endif /* NO_CERTS */ + + +/* Get the session cache mode for CTX + * + * ctx WOLFSSL_CTX struct to get cache mode from + * + * Returns a bit mask that has the session cache mode */ +WOLFSSL_API long wolfSSL_CTX_get_session_cache_mode(WOLFSSL_CTX* ctx) +{ + long m = 0; + + WOLFSSL_ENTER("SSL_CTX_set_session_cache_mode"); + + if (ctx == NULL) { + return m; + } + + if (ctx->sessionCacheOff != 1) { + m |= SSL_SESS_CACHE_SERVER; + } + + if (ctx->sessionCacheFlushOff == 1) { + m |= SSL_SESS_CACHE_NO_AUTO_CLEAR; + } + +#ifdef HAVE_EXT_CACHE + if (ctx->internalCacheOff == 1) { + m |= SSL_SESS_CACHE_NO_INTERNAL_STORE; + } +#endif + + return m; +} + + +int wolfSSL_CTX_get_read_ahead(WOLFSSL_CTX* ctx) +{ + if (ctx == NULL) { + return WOLFSSL_FAILURE; + } + + return ctx->readAhead; +} + + +int wolfSSL_CTX_set_read_ahead(WOLFSSL_CTX* ctx, int v) +{ + if (ctx == NULL) { + return WOLFSSL_FAILURE; + } + + ctx->readAhead = (byte)v; + + return WOLFSSL_SUCCESS; +} + + +long wolfSSL_CTX_set_tlsext_opaque_prf_input_callback_arg(WOLFSSL_CTX* ctx, + void* arg) +{ + if (ctx == NULL) { + return WOLFSSL_FAILURE; + } + + ctx->userPRFArg = arg; + return WOLFSSL_SUCCESS; +} + + +#ifndef NO_DES3 +/* 0 on success */ +int wolfSSL_DES_set_key(WOLFSSL_const_DES_cblock* myDes, + WOLFSSL_DES_key_schedule* key) +{ +#ifdef WOLFSSL_CHECK_DESKEY + return wolfSSL_DES_set_key_checked(myDes, key); +#else + wolfSSL_DES_set_key_unchecked(myDes, key); + return 0; +#endif +} + + + +/* return true in fail case (1) */ +static int DES_check(word32 mask, word32 mask2, unsigned char* key) +{ + word32 value[2]; + + /* sanity check on length made in wolfSSL_DES_set_key_checked */ + value[0] = mask; + value[1] = mask2; + return (XMEMCMP(value, key, sizeof(value)) == 0)? 1: 0; +} + + +/* check that the key is odd parity and is not a weak key + * returns -1 if parity is wrong, -2 if weak/null key and 0 on success */ +int wolfSSL_DES_set_key_checked(WOLFSSL_const_DES_cblock* myDes, + WOLFSSL_DES_key_schedule* key) +{ + if (myDes == NULL || key == NULL) { + WOLFSSL_MSG("Bad argument passed to wolfSSL_DES_set_key_checked"); + return -2; + } + else { + word32 i; + word32 sz = sizeof(WOLFSSL_DES_key_schedule); + + /* sanity check before call to DES_check */ + if (sz != (sizeof(word32) * 2)) { + WOLFSSL_MSG("Unexpected WOLFSSL_DES_key_schedule size"); + return -2; + } + + /* check odd parity */ + for (i = 0; i < sz; i++) { + unsigned char c = *((unsigned char*)myDes + i); + if (((c & 0x01) ^ + ((c >> 1) & 0x01) ^ + ((c >> 2) & 0x01) ^ + ((c >> 3) & 0x01) ^ + ((c >> 4) & 0x01) ^ + ((c >> 5) & 0x01) ^ + ((c >> 6) & 0x01) ^ + ((c >> 7) & 0x01)) != 1) { + WOLFSSL_MSG("Odd parity test fail"); + return -1; + } + } + + if (wolfSSL_DES_is_weak_key(myDes) == 1) { + WOLFSSL_MSG("Weak key found"); + return -2; + } + + /* passed tests, now copy over key */ + XMEMCPY(key, myDes, sizeof(WOLFSSL_const_DES_cblock)); + + return 0; + } +} + + +/* check is not weak. Weak key list from Nist "Recommendation for the Triple + * Data Encryption Algorithm (TDEA) Block Cipher" + * + * returns 1 if is weak 0 if not + */ +int wolfSSL_DES_is_weak_key(WOLFSSL_const_DES_cblock* key) +{ + word32 mask, mask2; + + WOLFSSL_ENTER("wolfSSL_DES_is_weak_key"); + + if (key == NULL) { + WOLFSSL_MSG("NULL key passed in"); + return 1; + } + + mask = 0x01010101; mask2 = 0x01010101; + if (DES_check(mask, mask2, *key)) { + WOLFSSL_MSG("Weak key found"); + return 1; + } + + mask = 0xFEFEFEFE; mask2 = 0xFEFEFEFE; + if (DES_check(mask, mask2, *key)) { + WOLFSSL_MSG("Weak key found"); + return 1; + } + + mask = 0xE0E0E0E0; mask2 = 0xF1F1F1F1; + if (DES_check(mask, mask2, *key)) { + WOLFSSL_MSG("Weak key found"); + return 1; + } + + mask = 0x1F1F1F1F; mask2 = 0x0E0E0E0E; + if (DES_check(mask, mask2, *key)) { + WOLFSSL_MSG("Weak key found"); + return 1; + } + + /* semi-weak *key check (list from same Nist paper) */ + mask = 0x011F011F; mask2 = 0x010E010E; + if (DES_check(mask, mask2, *key) || + DES_check(ByteReverseWord32(mask), ByteReverseWord32(mask2), *key)) { + WOLFSSL_MSG("Weak key found"); + return 1; + } + + mask = 0x01E001E0; mask2 = 0x01F101F1; + if (DES_check(mask, mask2, *key) || + DES_check(ByteReverseWord32(mask), ByteReverseWord32(mask2), *key)) { + WOLFSSL_MSG("Weak key found"); + return 1; + } + + mask = 0x01FE01FE; mask2 = 0x01FE01FE; + if (DES_check(mask, mask2, *key) || + DES_check(ByteReverseWord32(mask), ByteReverseWord32(mask2), *key)) { + WOLFSSL_MSG("Weak key found"); + return 1; + } + + mask = 0x1FE01FE0; mask2 = 0x0EF10EF1; + if (DES_check(mask, mask2, *key) || + DES_check(ByteReverseWord32(mask), ByteReverseWord32(mask2), *key)) { + WOLFSSL_MSG("Weak key found"); + return 1; + } + + mask = 0x1FFE1FFE; mask2 = 0x0EFE0EFE; + if (DES_check(mask, mask2, *key) || + DES_check(ByteReverseWord32(mask), ByteReverseWord32(mask2), *key)) { + WOLFSSL_MSG("Weak key found"); + return 1; + } + + return 0; +} + + +void wolfSSL_DES_set_key_unchecked(WOLFSSL_const_DES_cblock* myDes, + WOLFSSL_DES_key_schedule* key) +{ + if (myDes != NULL && key != NULL) { + XMEMCPY(key, myDes, sizeof(WOLFSSL_const_DES_cblock)); + } +} + + +/* Sets the parity of the DES key for use */ +void wolfSSL_DES_set_odd_parity(WOLFSSL_DES_cblock* myDes) +{ + word32 i; + word32 sz = sizeof(WOLFSSL_DES_cblock); + + WOLFSSL_ENTER("wolfSSL_DES_set_odd_parity"); + + for (i = 0; i < sz; i++) { + unsigned char c = *((unsigned char*)myDes + i); + if (( + ((c >> 1) & 0x01) ^ + ((c >> 2) & 0x01) ^ + ((c >> 3) & 0x01) ^ + ((c >> 4) & 0x01) ^ + ((c >> 5) & 0x01) ^ + ((c >> 6) & 0x01) ^ + ((c >> 7) & 0x01)) != 1) { + WOLFSSL_MSG("Setting odd parity bit"); + *((unsigned char*)myDes + i) = *((unsigned char*)myDes + i) | 0x01; + } + } +} + + +#ifdef WOLFSSL_DES_ECB +/* Encrypt or decrypt input message desa with key and get output in desb. + * if enc is DES_ENCRYPT,input message is encrypted or + * if enc is DES_DECRYPT,input message is decrypted. + * */ +void wolfSSL_DES_ecb_encrypt(WOLFSSL_DES_cblock* desa, + WOLFSSL_DES_cblock* desb, WOLFSSL_DES_key_schedule* key, int enc) +{ + Des myDes; + + WOLFSSL_ENTER("wolfSSL_DES_ecb_encrypt"); + + if (desa == NULL || key == NULL || desb == NULL || + (enc != DES_ENCRYPT && enc != DES_DECRYPT)) { + WOLFSSL_MSG("Bad argument passed to wolfSSL_DES_ecb_encrypt"); + } else { + if (wc_Des_SetKey(&myDes, (const byte*) key, + (const byte*) NULL, !enc) != 0) { + WOLFSSL_MSG("wc_Des_SetKey return error."); + return; + } + if (enc){ + if (wc_Des_EcbEncrypt(&myDes, (byte*) desb, (const byte*) desa, + sizeof(WOLFSSL_DES_cblock)) != 0){ + WOLFSSL_MSG("wc_Des_EcbEncrypt return error."); + } + } else { + if (wc_Des_EcbDecrypt(&myDes, (byte*) desb, (const byte*) desa, + sizeof(WOLFSSL_DES_cblock)) != 0){ + WOLFSSL_MSG("wc_Des_EcbDecrpyt return error."); + } + } + } +} +#endif + +#endif /* NO_DES3 */ + +#ifndef NO_RC4 +/* Set the key state for Arc4 structure. + * + * key Arc4 structure to use + * len length of data buffer + * data initial state to set Arc4 structure + */ +void wolfSSL_RC4_set_key(WOLFSSL_RC4_KEY* key, int len, + const unsigned char* data) +{ + typedef char rc4_test[sizeof(WOLFSSL_RC4_KEY) >= sizeof(Arc4) ? 1 : -1]; + (void)sizeof(rc4_test); + + WOLFSSL_ENTER("wolfSSL_RC4_set_key"); + + if (key == NULL || len < 0) { + WOLFSSL_MSG("bad argument passed in"); + return; + } + + XMEMSET(key, 0, sizeof(WOLFSSL_RC4_KEY)); + wc_Arc4SetKey((Arc4*)key, data, (word32)len); +} + + +/* Encrypt/decrypt with Arc4 structure. + * + * len length of buffer to encrypt/decrypt (in/out) + * in buffer to encrypt/decrypt + * out results of encryption/decryption + */ +void wolfSSL_RC4(WOLFSSL_RC4_KEY* key, size_t len, + const unsigned char* in, unsigned char* out) +{ + WOLFSSL_ENTER("wolfSSL_RC4"); + + if (key == NULL || in == NULL || out == NULL) { + WOLFSSL_MSG("Bad argument passed in"); + return; + } + + wc_Arc4Process((Arc4*)key, out, in, (word32)len); +} +#endif /* NO_RC4 */ + +#ifndef NO_AES + +#ifdef WOLFSSL_AES_DIRECT +/* AES encrypt direct, it is expected to be blocks of AES_BLOCK_SIZE for input. + * + * input Data to encrypt + * output Encrypted data after done + * key AES key to use for encryption + */ +void wolfSSL_AES_encrypt(const unsigned char* input, unsigned char* output, + AES_KEY *key) +{ + WOLFSSL_ENTER("wolfSSL_AES_encrypt"); + + if (input == NULL || output == NULL || key == NULL) { + WOLFSSL_MSG("Null argument passed in"); + return; + } + + wc_AesEncryptDirect((Aes*)key, output, input); +} + + +/* AES decrypt direct, it is expected to be blocks of AES_BLOCK_SIZE for input. + * + * input Data to decrypt + * output Decrypted data after done + * key AES key to use for encryption + */ +void wolfSSL_AES_decrypt(const unsigned char* input, unsigned char* output, + AES_KEY *key) +{ + WOLFSSL_ENTER("wolfSSL_AES_decrypt"); + + if (input == NULL || output == NULL || key == NULL) { + WOLFSSL_MSG("Null argument passed in"); + return; + } + + wc_AesDecryptDirect((Aes*)key, output, input); +} +#endif /* WOLFSSL_AES_DIRECT */ + +/* Setup of an AES key to use for encryption. + * + * key key in bytes to use for encryption + * bits size of key in bits + * aes AES structure to initialize + */ +int wolfSSL_AES_set_encrypt_key(const unsigned char *key, const int bits, + AES_KEY *aes) +{ + typedef char aes_test[sizeof(AES_KEY) >= sizeof(Aes) ? 1 : -1]; + (void)sizeof(aes_test); + + WOLFSSL_ENTER("wolfSSL_AES_set_encrypt_key"); + + if (key == NULL || aes == NULL) { + WOLFSSL_MSG("Null argument passed in"); + return -1; + } + + XMEMSET(aes, 0, sizeof(AES_KEY)); + if (wc_AesSetKey((Aes*)aes, key, ((bits)/8), NULL, AES_ENCRYPTION) != 0) { + WOLFSSL_MSG("Error in setting AES key"); + return -1; + } + return 0; +} + + +/* Setup of an AES key to use for decryption. + * + * key key in bytes to use for decryption + * bits size of key in bits + * aes AES structure to initialize + */ +int wolfSSL_AES_set_decrypt_key(const unsigned char *key, const int bits, + AES_KEY *aes) +{ + typedef char aes_test[sizeof(AES_KEY) >= sizeof(Aes) ? 1 : -1]; + (void)sizeof(aes_test); + + WOLFSSL_ENTER("wolfSSL_AES_set_decrypt_key"); + + if (key == NULL || aes == NULL) { + WOLFSSL_MSG("Null argument passed in"); + return -1; + } + + XMEMSET(aes, 0, sizeof(AES_KEY)); + if (wc_AesSetKey((Aes*)aes, key, ((bits)/8), NULL, AES_DECRYPTION) != 0) { + WOLFSSL_MSG("Error in setting AES key"); + return -1; + } + return 0; +} + + +#ifdef HAVE_AES_ECB +/* Encrypt/decrypt a 16 byte block of data using the key passed in. + * + * in buffer to encrypt/decrypt + * out buffer to hold result of encryption/decryption + * key AES structure to use with encryption/decryption + * enc AES_ENCRPT for encryption and AES_DECRYPT for decryption + */ +void wolfSSL_AES_ecb_encrypt(const unsigned char *in, unsigned char* out, + AES_KEY *key, const int enc) +{ + Aes* aes; + + WOLFSSL_ENTER("wolfSSL_AES_ecb_encrypt"); + + if (key == NULL || in == NULL || out == NULL) { + WOLFSSL_MSG("Error, Null argument passed in"); + return; + } + + aes = (Aes*)key; + if (enc == AES_ENCRYPT) { + if (wc_AesEcbEncrypt(aes, out, in, AES_BLOCK_SIZE) != 0) { + WOLFSSL_MSG("Error with AES CBC encrypt"); + } + } + else { + #ifdef HAVE_AES_DECRYPT + if (wc_AesEcbDecrypt(aes, out, in, AES_BLOCK_SIZE) != 0) { + WOLFSSL_MSG("Error with AES CBC decrypt"); + } + #else + WOLFSSL_MSG("AES decryption not compiled in"); + #endif + } +} +#endif /* HAVE_AES_ECB */ + +#ifdef HAVE_AES_CBC +/* Encrypt data using key and iv passed in. iv gets updated to most recent iv + * state after encryption/decryption. + * + * in buffer to encrypt/decrypt + * out buffer to hold result of encryption/decryption + * len length of input buffer + * key AES structure to use with encryption/decryption + * iv iv to use with operation + * enc AES_ENCRPT for encryption and AES_DECRYPT for decryption + */ +void wolfSSL_AES_cbc_encrypt(const unsigned char *in, unsigned char* out, + size_t len, AES_KEY *key, unsigned char* iv, const int enc) +{ + Aes* aes; + + WOLFSSL_ENTER("wolfSSL_AES_cbc_encrypt"); + + if (key == NULL || in == NULL || out == NULL || iv == NULL || len == 0) { + WOLFSSL_MSG("Error, Null argument passed in"); + return; + } + + aes = (Aes*)key; + if (wc_AesSetIV(aes, (const byte*)iv) != 0) { + WOLFSSL_MSG("Error with setting iv"); + return; + } + + if (enc == AES_ENCRYPT) { + if (wc_AesCbcEncrypt(aes, out, in, (word32)len) != 0) { + WOLFSSL_MSG("Error with AES CBC encrypt"); + } + } + else { + if (wc_AesCbcDecrypt(aes, out, in, (word32)len) != 0) { + WOLFSSL_MSG("Error with AES CBC decrypt"); + } + } + + /* to be compatible copy iv to iv buffer after completing operation */ + XMEMCPY(iv, (byte*)(aes->reg), AES_BLOCK_SIZE); +} +#endif /* HAVE_AES_CBC */ + + +/* Encrypt data using CFB mode with key and iv passed in. iv gets updated to + * most recent iv state after encryption/decryption. + * + * in buffer to encrypt/decrypt + * out buffer to hold result of encryption/decryption + * len length of input buffer + * key AES structure to use with encryption/decryption + * iv iv to use with operation + * num contains the amount of block used + * enc AES_ENCRPT for encryption and AES_DECRYPT for decryption + */ +void wolfSSL_AES_cfb128_encrypt(const unsigned char *in, unsigned char* out, + size_t len, AES_KEY *key, unsigned char* iv, int* num, + const int enc) +{ +#ifndef WOLFSSL_AES_CFB + WOLFSSL_MSG("CFB mode not enabled please use macro WOLFSSL_AES_CFB"); + (void)in; + (void)out; + (void)len; + (void)key; + (void)iv; + (void)num; + (void)enc; + + return; +#else + Aes* aes; + + WOLFSSL_ENTER("wolfSSL_AES_cbc_encrypt"); + if (key == NULL || in == NULL || out == NULL || iv == NULL) { + WOLFSSL_MSG("Error, Null argument passed in"); + return; + } + + aes = (Aes*)key; + if (wc_AesSetIV(aes, (const byte*)iv) != 0) { + WOLFSSL_MSG("Error with setting iv"); + return; + } + + if (enc == AES_ENCRYPT) { + if (wc_AesCfbEncrypt(aes, out, in, (word32)len) != 0) { + WOLFSSL_MSG("Error with AES CBC encrypt"); + } + } + else { + if (wc_AesCfbDecrypt(aes, out, in, (word32)len) != 0) { + WOLFSSL_MSG("Error with AES CBC decrypt"); + } + } + + /* to be compatible copy iv to iv buffer after completing operation */ + XMEMCPY(iv, (byte*)(aes->reg), AES_BLOCK_SIZE); + + /* store number of left over bytes to num */ + *num = (aes->left)? AES_BLOCK_SIZE - aes->left : 0; +#endif /* WOLFSSL_AES_CFB */ +} +#endif /* NO_AES */ + +#ifndef NO_WOLFSSL_STUB +int wolfSSL_BIO_printf(WOLFSSL_BIO* bio, const char* format, ...) +{ + (void)bio; + (void)format; + WOLFSSL_STUB("BIO_printf"); + return 0; +} +#endif + +#ifndef NO_WOLFSSL_STUB +int wolfSSL_ASN1_UTCTIME_print(WOLFSSL_BIO* bio, const WOLFSSL_ASN1_UTCTIME* a) +{ + (void)bio; + (void)a; + WOLFSSL_STUB("ASN1_UTCTIME_print"); + return 0; +} +#endif + +/* Return the month as a string. + * + * n The number of the month as a two characters (1 based). + * returns the month as a string. + */ +static WC_INLINE const char* MonthStr(const char* n) +{ + static const char monthStr[12][4] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + return monthStr[(n[0] - '0') * 10 + (n[1] - '0') - 1]; +} + +int wolfSSL_ASN1_GENERALIZEDTIME_print(WOLFSSL_BIO* bio, + const WOLFSSL_ASN1_GENERALIZEDTIME* asnTime) +{ + const char* p = (const char *)(asnTime->data + 2); + WOLFSSL_ENTER("wolfSSL_ASN1_GENERALIZEDTIME_print"); + + if (bio == NULL || asnTime == NULL) + return BAD_FUNC_ARG; + + /* GetTimeString not always available. */ + wolfSSL_BIO_write(bio, MonthStr(p + 4), 3); + wolfSSL_BIO_write(bio, " ", 1); + /* Day */ + wolfSSL_BIO_write(bio, p + 6, 2); + wolfSSL_BIO_write(bio, " ", 1); + /* Hour */ + wolfSSL_BIO_write(bio, p + 8, 2); + wolfSSL_BIO_write(bio, ":", 1); + /* Min */ + wolfSSL_BIO_write(bio, p + 10, 2); + wolfSSL_BIO_write(bio, ":", 1); + /* Secs */ + wolfSSL_BIO_write(bio, p + 12, 2); + wolfSSL_BIO_write(bio, " ", 1); + wolfSSL_BIO_write(bio, p, 4); + + return 0; +} + +void wolfSSL_ASN1_GENERALIZEDTIME_free(WOLFSSL_ASN1_TIME* asn1Time) +{ + WOLFSSL_ENTER("wolfSSL_ASN1_GENERALIZEDTIME_free"); + if (asn1Time == NULL) + return; + XMEMSET(asn1Time->data, 0, sizeof(asn1Time->data)); +} + +int wolfSSL_sk_num(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk) +{ + if (sk == NULL) + return 0; + return (int)sk->num; +} + +void* wolfSSL_sk_value(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk, int i) +{ + for (; sk != NULL && i > 0; i--) + sk = sk->next; + if (sk == NULL) + return NULL; + return (void*)sk->data.obj; +} + +#endif /* OPENSSL_EXTRA */ + +#if defined(OPENSSL_EXTRA) || defined(HAVE_EXT_CACHE) +/* stunnel 4.28 needs */ +void wolfSSL_CTX_sess_set_get_cb(WOLFSSL_CTX* ctx, + WOLFSSL_SESSION*(*f)(WOLFSSL*, unsigned char*, int, int*)) +{ + if (ctx == NULL) + return; + +#ifdef HAVE_EXT_CACHE + ctx->get_sess_cb = f; +#else + (void)f; +#endif +} + +void wolfSSL_CTX_sess_set_new_cb(WOLFSSL_CTX* ctx, + int (*f)(WOLFSSL*, WOLFSSL_SESSION*)) +{ + if (ctx == NULL) + return; + +#ifdef HAVE_EXT_CACHE + ctx->new_sess_cb = f; +#else + (void)f; +#endif +} + +void wolfSSL_CTX_sess_set_remove_cb(WOLFSSL_CTX* ctx, void (*f)(WOLFSSL_CTX*, + WOLFSSL_SESSION*)) +{ + if (ctx == NULL) + return; + +#ifdef HAVE_EXT_CACHE + ctx->rem_sess_cb = f; +#else + (void)f; +#endif +} +#endif /* OPENSSL_EXTRA || HAVE_EXT_CACHE */ + +#ifdef OPENSSL_EXTRA + +/* + * + * Note: It is expected that the importing and exporting function have been + * built with the same settings. For example if session tickets was + * enabled with the wolfSSL library exporting a session then it is + * expected to be turned on with the wolfSSL library importing the session. + */ +int wolfSSL_i2d_SSL_SESSION(WOLFSSL_SESSION* sess, unsigned char** p) +{ + int size = 0; +#ifdef HAVE_EXT_CACHE + int idx = 0; +#ifdef SESSION_CERTS + int i; +#endif + unsigned char *data; + + if (sess == NULL) { + return BAD_FUNC_ARG; + } + + /* bornOn | timeout | sessionID len | sessionID | masterSecret | haveEMS */ + size += OPAQUE32_LEN + OPAQUE32_LEN + OPAQUE8_LEN + sess->sessionIDSz + + SECRET_LEN + OPAQUE8_LEN; +#ifdef SESSION_CERTS + /* Peer chain */ + size += OPAQUE8_LEN; + for (i = 0; i < sess->chain.count; i++) + size += OPAQUE16_LEN + sess->chain.certs[i].length; + /* Protocol version */ + size += OPAQUE16_LEN; +#endif +#if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) + /* cipher suite */ + size += OPAQUE16_LEN + OPAQUE16_LEN; +#endif +#ifndef NO_CLIENT_CACHE + /* ServerID len | ServerID */ + size += OPAQUE16_LEN + sess->idLen; +#endif +#ifdef HAVE_SESSION_TICKET + /* ticket len | ticket */ + size += OPAQUE16_LEN + sess->ticketLen; +#endif +#ifdef OPENSSL_EXTRA + /* session context ID len | session context ID */ + size += OPAQUE8_LEN + sess->sessionCtxSz; +#endif + + if (p != NULL) { + if (*p == NULL) + *p = (unsigned char*)XMALLOC(size, NULL, DYNAMIC_TYPE_OPENSSL); + if (*p == NULL) + return 0; + data = *p; + + c32toa(sess->bornOn, data + idx); idx += OPAQUE32_LEN; + c32toa(sess->timeout, data + idx); idx += OPAQUE32_LEN; + data[idx++] = sess->sessionIDSz; + XMEMCPY(data + idx, sess->sessionID, sess->sessionIDSz); + idx += sess->sessionIDSz; + XMEMCPY(data + idx, sess->masterSecret, SECRET_LEN); idx += SECRET_LEN; + data[idx++] = (byte)sess->haveEMS; +#ifdef SESSION_CERTS + data[idx++] = (byte)sess->chain.count; + for (i = 0; i < sess->chain.count; i++) { + c16toa((word16)sess->chain.certs[i].length, data + idx); + idx += OPAQUE16_LEN; + XMEMCPY(data + idx, sess->chain.certs[i].buffer, + sess->chain.certs[i].length); + idx += sess->chain.certs[i].length; + } + data[idx++] = sess->version.major; + data[idx++] = sess->version.minor; +#endif +#if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) + data[idx++] = sess->cipherSuite0; + data[idx++] = sess->cipherSuite; +#endif +#ifndef NO_CLIENT_CACHE + c16toa(sess->idLen, data + idx); idx += OPAQUE16_LEN; + XMEMCPY(data + idx, sess->serverID, sess->idLen); + idx += sess->idLen; +#endif +#ifdef HAVE_SESSION_TICKET + c16toa(sess->ticketLen, data + idx); idx += OPAQUE16_LEN; + XMEMCPY(data + idx, sess->ticket, sess->ticketLen); + idx += sess->ticketLen; +#endif +#ifdef OPENSSL_EXTRA + data[idx++] = sess->sessionCtxSz; + XMEMCPY(data + idx, sess->sessionCtx, sess->sessionCtxSz); + idx += sess->sessionCtxSz; +#endif + } +#endif + + (void)sess; + (void)p; +#ifdef HAVE_EXT_CACHE + (void)idx; +#endif + + return size; +} + + +/* TODO: no function to free new session. + * + * Note: It is expected that the importing and exporting function have been + * built with the same settings. For example if session tickets was + * enabled with the wolfSSL library exporting a session then it is + * expected to be turned on with the wolfSSL library importing the session. + */ +WOLFSSL_SESSION* wolfSSL_d2i_SSL_SESSION(WOLFSSL_SESSION** sess, + const unsigned char** p, long i) +{ + WOLFSSL_SESSION* s = NULL; + int ret = 0; +#if defined(HAVE_EXT_CACHE) + int idx; + byte* data; +#ifdef SESSION_CERTS + int j; + word16 length; +#endif +#endif + + (void)p; + (void)i; + (void)ret; + + if (sess != NULL) + s = *sess; + +#ifdef HAVE_EXT_CACHE + if (p == NULL || *p == NULL) + return NULL; + + if (s == NULL) { + s = (WOLFSSL_SESSION*)XMALLOC(sizeof(WOLFSSL_SESSION), NULL, + DYNAMIC_TYPE_OPENSSL); + if (s == NULL) + return NULL; + XMEMSET(s, 0, sizeof(WOLFSSL_SESSION)); + s->isAlloced = 1; +#ifdef HAVE_SESSION_TICKET + s->isDynamic = 0; +#endif + } + + idx = 0; + data = (byte*)*p; + + /* bornOn | timeout | sessionID len */ + if (i < OPAQUE32_LEN + OPAQUE32_LEN + OPAQUE8_LEN) { + ret = BUFFER_ERROR; + goto end; + } + ato32(data + idx, &s->bornOn); idx += OPAQUE32_LEN; + ato32(data + idx, &s->timeout); idx += OPAQUE32_LEN; + s->sessionIDSz = data[idx++]; + + /* sessionID | secret | haveEMS */ + if (i - idx < s->sessionIDSz + SECRET_LEN + OPAQUE8_LEN) { + ret = BUFFER_ERROR; + goto end; + } + XMEMCPY(s->sessionID, data + idx, s->sessionIDSz); + idx += s->sessionIDSz; + XMEMCPY(s->masterSecret, data + idx, SECRET_LEN); idx += SECRET_LEN; + s->haveEMS = data[idx++]; + +#ifdef SESSION_CERTS + /* Certificate chain */ + if (i - idx == 0) { + ret = BUFFER_ERROR; + goto end; + } + s->chain.count = data[idx++]; + for (j = 0; j < s->chain.count; j++) { + if (i - idx < OPAQUE16_LEN) { + ret = BUFFER_ERROR; + goto end; + } + ato16(data + idx, &length); idx += OPAQUE16_LEN; + s->chain.certs[j].length = length; + if (i - idx < length) { + ret = BUFFER_ERROR; + goto end; + } + XMEMCPY(s->chain.certs[j].buffer, data + idx, length); + idx += length; + } + + /* Protocol Version | Cipher suite */ + if (i - idx < OPAQUE16_LEN + OPAQUE16_LEN) { + ret = BUFFER_ERROR; + goto end; + } + s->version.major = data[idx++]; + s->version.minor = data[idx++]; +#endif +#if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) + s->cipherSuite0 = data[idx++]; + s->cipherSuite = data[idx++]; +#endif +#ifndef NO_CLIENT_CACHE + /* ServerID len */ + if (i - idx < OPAQUE16_LEN) { + ret = BUFFER_ERROR; + goto end; + } + ato16(data + idx, &s->idLen); idx += OPAQUE16_LEN; + + /* ServerID */ + if (i - idx < s->idLen) { + ret = BUFFER_ERROR; + goto end; + } + XMEMCPY(s->serverID, data + idx, s->idLen); idx += s->idLen; +#endif +#ifdef HAVE_SESSION_TICKET + /* ticket len */ + if (i - idx < OPAQUE16_LEN) { + ret = BUFFER_ERROR; + goto end; + } + ato16(data + idx, &s->ticketLen); idx += OPAQUE16_LEN; + + /* Dispose of ol dynamic ticket and ensure space for new ticket. */ + if (s->isDynamic) + XFREE(s->ticket, NULL, DYNAMIC_TYPE_SESSION_TICK); + if (s->ticketLen <= SESSION_TICKET_LEN) + s->ticket = s->staticTicket; + else { + s->ticket = (byte*)XMALLOC(s->ticketLen, NULL, + DYNAMIC_TYPE_SESSION_TICK); + if (s->ticket == NULL) { + ret = MEMORY_ERROR; + goto end; + } + s->isDynamic = 1; + } + + /* ticket */ + if (i - idx < s->ticketLen) { + ret = BUFFER_ERROR; + goto end; + } + XMEMCPY(s->ticket, data + idx, s->ticketLen); idx += s->ticketLen; +#endif +#ifdef OPENSSL_EXTRA + /* byte for length of session context ID */ + if (i - idx < OPAQUE8_LEN) { + ret = BUFFER_ERROR; + goto end; + } + s->sessionCtxSz = data[idx++]; + + /* app session context ID */ + if (i - idx < s->sessionCtxSz) { + ret = BUFFER_ERROR; + goto end; + } + XMEMCPY(s->sessionCtx, data + idx, s->sessionCtxSz); idx += s->sessionCtxSz; +#endif + (void)idx; + + if (sess != NULL) + *sess = s; + + *p += idx; + +end: + if (ret != 0 && (sess == NULL || *sess != s)) + wolfSSL_SESSION_free(s); +#endif + return s; +} + + +long wolfSSL_SESSION_get_timeout(const WOLFSSL_SESSION* sess) +{ + long timeout = 0; + WOLFSSL_ENTER("wolfSSL_SESSION_get_timeout"); + if (sess) + timeout = sess->timeout; + return timeout; +} + + +long wolfSSL_SESSION_get_time(const WOLFSSL_SESSION* sess) +{ + long bornOn = 0; + WOLFSSL_ENTER("wolfSSL_SESSION_get_time"); + if (sess) + bornOn = sess->bornOn; + return bornOn; +} + + +#endif /* OPENSSL_EXTRA */ + + +#ifdef KEEP_PEER_CERT +char* wolfSSL_X509_get_subjectCN(WOLFSSL_X509* x509) +{ + if (x509 == NULL) + return NULL; + + return x509->subjectCN; +} +#endif /* KEEP_PEER_CERT */ + +#ifdef OPENSSL_EXTRA + +#if defined(FORTRESS) && !defined(NO_FILESYSTEM) +int wolfSSL_cmp_peer_cert_to_file(WOLFSSL* ssl, const char *fname) +{ + int ret = WOLFSSL_FATAL_ERROR; + + WOLFSSL_ENTER("wolfSSL_cmp_peer_cert_to_file"); + if (ssl != NULL && fname != NULL) + { + #ifdef WOLFSSL_SMALL_STACK + byte staticBuffer[1]; /* force heap usage */ + #else + byte staticBuffer[FILE_BUFFER_SIZE]; + #endif + byte* myBuffer = staticBuffer; + int dynamic = 0; + XFILE file = XBADFILE; + size_t sz = 0; + WOLFSSL_CTX* ctx = ssl->ctx; + WOLFSSL_X509* peer_cert = &ssl->peerCert; + DerBuffer* fileDer = NULL; + + file = XFOPEN(fname, "rb"); + if (file == XBADFILE) + return WOLFSSL_BAD_FILE; + + if(XFSEEK(file, 0, XSEEK_END) != 0) { + XFCLOSE(file); + return WOLFSSL_BAD_FILE; + } + sz = XFTELL(file); + XREWIND(file); + + if (sz > (long)sizeof(staticBuffer)) { + WOLFSSL_MSG("Getting dynamic buffer"); + myBuffer = (byte*)XMALLOC(sz, ctx->heap, DYNAMIC_TYPE_FILE); + dynamic = 1; + } + + + if ((myBuffer != NULL) && + (sz > 0) && + (XFREAD(myBuffer, 1, sz, file) == sz) && + (PemToDer(myBuffer, (long)sz, CERT_TYPE, + &fileDer, ctx->heap, NULL, NULL) == 0) && + (fileDer->length != 0) && + (fileDer->length == peer_cert->derCert->length) && + (XMEMCMP(peer_cert->derCert->buffer, fileDer->buffer, + fileDer->length) == 0)) + { + ret = 0; + } + + FreeDer(&fileDer); + + if (dynamic) + XFREE(myBuffer, ctx->heap, DYNAMIC_TYPE_FILE); + + XFCLOSE(file); + } + + return ret; +} +#endif +#endif /* OPENSSL_EXTRA */ + +#if defined(OPENSSL_EXTRA) || \ + (defined(OPENSSL_EXTRA_X509_SMALL) && !defined(NO_RSA)) +static WC_RNG globalRNG; +static int initGlobalRNG = 0; +#endif + +#ifdef OPENSSL_EXTRA + +/* Not thread safe! Can be called multiple times. + * Checks if the global RNG has been created. If not then one is created. + * + * Returns SSL_SUCCESS when no error is encountered. + */ +static int wolfSSL_RAND_Init(void) +{ + if (initGlobalRNG == 0) { + if (wc_InitRng(&globalRNG) < 0) { + WOLFSSL_MSG("wolfSSL Init Global RNG failed"); + return 0; + } + initGlobalRNG = 1; + } + + return SSL_SUCCESS; +} + + +/* SSL_SUCCESS on ok */ +int wolfSSL_RAND_seed(const void* seed, int len) +{ + + WOLFSSL_MSG("wolfSSL_RAND_seed"); + + (void)seed; + (void)len; + + return wolfSSL_RAND_Init(); +} + + +/* Returns the path for reading seed data from. + * Uses the env variable $RANDFILE first if set, if not then used $HOME/.rnd + * + * Note uses stdlib by default unless XGETENV macro is overwritten + * + * fname buffer to hold path + * len length of fname buffer + * + * Returns a pointer to fname on success and NULL on failure + */ +const char* wolfSSL_RAND_file_name(char* fname, unsigned long len) +{ +#ifndef NO_FILESYSTEM + char* rt; + char ap[] = "/.rnd"; + + WOLFSSL_ENTER("wolfSSL_RAND_file_name"); + + if (fname == NULL) { + return NULL; + } + + XMEMSET(fname, 0, len); + /* if access to stdlib.h */ + if ((rt = XGETENV("RANDFILE")) != NULL) { + if (len > XSTRLEN(rt)) { + XMEMCPY(fname, rt, XSTRLEN(rt)); + } + else { + WOLFSSL_MSG("RANDFILE too large for buffer"); + rt = NULL; + } + } + + /* $RANDFILE was not set or is too large, check $HOME */ + if (rt == NULL) { + WOLFSSL_MSG("Environment variable RANDFILE not set"); + if ((rt = XGETENV("HOME")) == NULL) { + WOLFSSL_MSG("Environment variable HOME not set"); + return NULL; + } + + if (len > XSTRLEN(rt) + XSTRLEN(ap)) { + fname[0] = '\0'; + XSTRNCAT(fname, rt, len); + XSTRNCAT(fname, ap, len - XSTRLEN(rt)); + return fname; + } + else { + WOLFSSL_MSG("HOME too large for buffer"); + return NULL; + } + } + + return fname; +#else + /* no filesystem defined */ + WOLFSSL_ENTER("wolfSSL_RAND_file_name"); + WOLFSSL_MSG("No filesystem feature enabled, not compiled in"); + (void)fname; + (void)len; + return NULL; +#endif +} + + +/* Writes 1024 bytes from the RNG to the given file name. + * + * fname name of file to write to + * + * Returns the number of bytes written + */ +int wolfSSL_RAND_write_file(const char* fname) +{ + int bytes = 0; + + WOLFSSL_ENTER("RAND_write_file"); + + if (fname == NULL) { + return SSL_FAILURE; + } + +#ifndef NO_FILESYSTEM + { + #ifndef WOLFSSL_SMALL_STACK + unsigned char buf[1024]; + #else + unsigned char* buf = (unsigned char *)XMALLOC(1024, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (buf == NULL) { + WOLFSSL_MSG("malloc failed"); + return SSL_FAILURE; + } + #endif + bytes = 1024; /* default size of buf */ + + if (initGlobalRNG == 0 && wolfSSL_RAND_Init() != SSL_SUCCESS) { + WOLFSSL_MSG("No RNG to use"); + #ifdef WOLFSSL_SMALL_STACK + XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return 0; + } + + if (wc_RNG_GenerateBlock(&globalRNG, buf, bytes) != 0) { + WOLFSSL_MSG("Error generating random buffer"); + bytes = 0; + } + else { + XFILE f; + + f = XFOPEN(fname, "wb"); + if (f == XBADFILE) { + WOLFSSL_MSG("Error opening the file"); + bytes = 0; + } + else { + XFWRITE(buf, 1, bytes, f); + XFCLOSE(f); + } + } + ForceZero(buf, bytes); + #ifdef WOLFSSL_SMALL_STACK + XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + } +#endif + + return bytes; +} + +#ifndef FREERTOS_TCP + +/* These constant values are protocol values made by egd */ +#if defined(USE_WOLFSSL_IO) && !defined(USE_WINDOWS_API) + #define WOLFSSL_EGD_NBLOCK 0x01 + #include +#endif + +/* This collects entropy from the path nm and seeds the global PRNG with it. + * Makes a call to wolfSSL_RAND_Init which is not thread safe. + * + * nm is the file path to the egd server + * + * Returns the number of bytes read. + */ +int wolfSSL_RAND_egd(const char* nm) +{ +#if defined(USE_WOLFSSL_IO) && !defined(USE_WINDOWS_API) && !defined(HAVE_FIPS) && \ + defined(HAVE_HASHDRBG) + struct sockaddr_un rem; + int fd; + int ret = WOLFSSL_SUCCESS; + word32 bytes = 0; + word32 idx = 0; +#ifndef WOLFSSL_SMALL_STACK + unsigned char buf[256]; +#else + unsigned char* buf; + buf = (unsigned char*)XMALLOC(256, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (buf == NULL) { + WOLFSSL_MSG("Not enough memory"); + return WOLFSSL_FATAL_ERROR; + } +#endif + + if (nm == NULL) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return WOLFSSL_FATAL_ERROR; + } + + fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd < 0) { + WOLFSSL_MSG("Error creating socket"); + #ifdef WOLFSSL_SMALL_STACK + XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return WOLFSSL_FATAL_ERROR; + } + if (ret == WOLFSSL_SUCCESS) { + rem.sun_family = AF_UNIX; + XSTRNCPY(rem.sun_path, nm, sizeof(rem.sun_path)); + rem.sun_path[sizeof(rem.sun_path)-1] = '\0'; + } + + /* connect to egd server */ + if (ret == WOLFSSL_SUCCESS) { + if (connect(fd, (struct sockaddr*)&rem, sizeof(struct sockaddr_un)) + == -1) { + WOLFSSL_MSG("error connecting to egd server"); + ret = WOLFSSL_FATAL_ERROR; + } + } + + while (ret == WOLFSSL_SUCCESS && bytes < 255 && idx + 2 < 256) { + if (ret == WOLFSSL_SUCCESS) { + buf[idx] = WOLFSSL_EGD_NBLOCK; + buf[idx + 1] = 255 - bytes; /* request 255 bytes from server */ + ret = (int)write(fd, buf + idx, 2); + if (ret <= 0 || ret != 2) { + if (errno == EAGAIN) { + ret = WOLFSSL_SUCCESS; + continue; + } + WOLFSSL_MSG("error requesting entropy from egd server"); + ret = WOLFSSL_FATAL_ERROR; + break; + } + } + + /* attempting to read */ + buf[idx] = 0; + ret = (int)read(fd, buf + idx, 256 - bytes); + if (ret == 0) { + WOLFSSL_MSG("error reading entropy from egd server"); + ret = WOLFSSL_FATAL_ERROR; + break; + } + if (ret > 0 && buf[idx] > 0) { + bytes += buf[idx]; /* egd stores amount sent in first byte */ + if (bytes + idx > 255 || buf[idx] > ret) { + WOLFSSL_MSG("Buffer error"); + ret = WOLFSSL_FATAL_ERROR; + break; + } + XMEMMOVE(buf + idx, buf + idx + 1, buf[idx]); + idx = bytes; + ret = WOLFSSL_SUCCESS; + if (bytes >= 255) { + break; + } + } + else { + if (errno == EAGAIN || errno == EINTR) { + WOLFSSL_MSG("EGD would read"); + ret = WOLFSSL_SUCCESS; /* try again */ + } + else if (buf[idx] == 0) { + /* if egd returned 0 then there is no more entropy to be had. + Do not try more reads. */ + ret = WOLFSSL_SUCCESS; + break; + } + else { + WOLFSSL_MSG("Error with read"); + ret = WOLFSSL_FATAL_ERROR; + } + } + } + + if (bytes > 0 && ret == WOLFSSL_SUCCESS) { + wolfSSL_RAND_Init(); /* call to check global RNG is created */ + if (wc_RNG_DRBG_Reseed(&globalRNG, (const byte*) buf, bytes) + != 0) { + WOLFSSL_MSG("Error with reseeding DRBG structure"); + ret = WOLFSSL_FATAL_ERROR; + } + #ifdef SHOW_SECRETS + { /* print out entropy found */ + word32 i; + printf("EGD Entropy = "); + for (i = 0; i < bytes; i++) { + printf("%02X", buf[i]); + } + printf("\n"); + } + #endif + } + + ForceZero(buf, bytes); + #ifdef WOLFSSL_SMALL_STACK + XFREE(buf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + close(fd); + + if (ret == WOLFSSL_SUCCESS) { + return bytes; + } + else { + return ret; + } +#else + WOLFSSL_MSG("Type of socket needed is not available"); + WOLFSSL_MSG("\tor using mode where DRBG API is not available"); + (void)nm; + + return WOLFSSL_FATAL_ERROR; +#endif /* USE_WOLFSSL_IO && !USE_WINDOWS_API && !HAVE_FIPS && HAVE_HASHDRBG */ +} + +#endif /* !FREERTOS_TCP */ + +void wolfSSL_RAND_Cleanup(void) +{ + WOLFSSL_ENTER("wolfSSL_RAND_Cleanup()"); + + if (initGlobalRNG != 0) { + wc_FreeRng(&globalRNG); + initGlobalRNG = 0; + } +} + + +int wolfSSL_RAND_pseudo_bytes(unsigned char* buf, int num) +{ + return wolfSSL_RAND_bytes(buf, num); +} + + +/* SSL_SUCCESS on ok */ +int wolfSSL_RAND_bytes(unsigned char* buf, int num) +{ + int ret = 0; + int initTmpRng = 0; + WC_RNG* rng = NULL; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG* tmpRNG = NULL; +#else + WC_RNG tmpRNG[1]; +#endif + + WOLFSSL_ENTER("wolfSSL_RAND_bytes"); + +#ifdef WOLFSSL_SMALL_STACK + tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); + if (tmpRNG == NULL) + return ret; +#endif + + if (initGlobalRNG) + rng = &globalRNG; + else if(wc_InitRng(tmpRNG) == 0) { + rng = tmpRNG; + initTmpRng = 1; + } + + if (rng) { + if (wc_RNG_GenerateBlock(rng, buf, num) != 0) + WOLFSSL_MSG("Bad wc_RNG_GenerateBlock"); + else + ret = WOLFSSL_SUCCESS; + } + + if (initTmpRng) + wc_FreeRng(tmpRNG); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); +#endif + + return ret; +} + + +int wolfSSL_RAND_poll(void) +{ + byte entropy[16]; + int ret = 0; + word32 entropy_sz = 16; + + WOLFSSL_ENTER("wolfSSL_RAND_poll"); + if (initGlobalRNG == 0){ + WOLFSSL_MSG("Global RNG no Init"); + return WOLFSSL_FAILURE; + } + ret = wc_GenerateSeed(&globalRNG.seed, entropy, entropy_sz); + if (ret != 0){ + WOLFSSL_MSG("Bad wc_RNG_GenerateBlock"); + ret = WOLFSSL_FAILURE; + }else + ret = WOLFSSL_SUCCESS; + + return ret; +} + +WOLFSSL_BN_CTX* wolfSSL_BN_CTX_new(void) +{ + static int ctx; /* wolfcrypt doesn't now need ctx */ + + WOLFSSL_MSG("wolfSSL_BN_CTX_new"); + return (WOLFSSL_BN_CTX*)&ctx; + +} + +void wolfSSL_BN_CTX_init(WOLFSSL_BN_CTX* ctx) +{ + (void)ctx; + WOLFSSL_MSG("wolfSSL_BN_CTX_init"); +} + + +void wolfSSL_BN_CTX_free(WOLFSSL_BN_CTX* ctx) +{ + (void)ctx; + WOLFSSL_MSG("wolfSSL_BN_CTX_free"); + /* do free since static ctx that does nothing */ +} +#endif /* OPENSSL_EXTRA */ + + +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) +static void InitwolfSSL_BigNum(WOLFSSL_BIGNUM* bn) +{ + if (bn) { + XMEMSET(bn, 0, sizeof(WOLFSSL_BIGNUM)); + bn->neg = 0; + bn->internal = NULL; + } +} + +WOLFSSL_BIGNUM* wolfSSL_BN_new(void) +{ + WOLFSSL_BIGNUM* external; + mp_int* mpi; + + WOLFSSL_MSG("wolfSSL_BN_new"); + +#if !defined(USE_FAST_MATH) || defined(HAVE_WOLF_BIGINT) + mpi = (mp_int*) XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_BIGINT); + if (mpi == NULL) { + WOLFSSL_MSG("wolfSSL_BN_new malloc mpi failure"); + return NULL; + } +#endif + + external = (WOLFSSL_BIGNUM*) XMALLOC(sizeof(WOLFSSL_BIGNUM), NULL, + DYNAMIC_TYPE_BIGINT); + if (external == NULL) { + WOLFSSL_MSG("wolfSSL_BN_new malloc WOLFSSL_BIGNUM failure"); +#if !defined(USE_FAST_MATH) || defined(HAVE_WOLF_BIGINT) + XFREE(mpi, NULL, DYNAMIC_TYPE_BIGINT); +#endif + return NULL; + } + +#if defined(USE_FAST_MATH) && !defined(HAVE_WOLF_BIGINT) + mpi = &external->fp; +#endif + + InitwolfSSL_BigNum(external); + if (mp_init(mpi) != MP_OKAY) { + wolfSSL_BN_free(external); + return NULL; + } + external->internal = mpi; + + return external; +} + +#if defined(USE_FAST_MATH) && !defined(HAVE_WOLF_BIGINT) +/* This function works without BN_free only with TFM */ +void wolfSSL_BN_init(WOLFSSL_BIGNUM* bn) +{ + if(bn == NULL)return; + WOLFSSL_MSG("wolfSSL_BN_init"); + InitwolfSSL_BigNum(bn); + if (mp_init(&bn->fp) != MP_OKAY) + return; + bn->internal = (void *)&bn->fp; +} +#endif + +void wolfSSL_BN_free(WOLFSSL_BIGNUM* bn) +{ + WOLFSSL_MSG("wolfSSL_BN_free"); + if (bn) { + if (bn->internal) { + mp_int* bni = (mp_int*)bn->internal; + mp_forcezero(bni); + mp_free(bni); +#if !defined(USE_FAST_MATH) || defined(HAVE_WOLF_BIGINT) + XFREE(bn->internal, NULL, DYNAMIC_TYPE_BIGINT); +#endif + bn->internal = NULL; + } + XFREE(bn, NULL, DYNAMIC_TYPE_BIGINT); + bn = NULL; + } +} +#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ + +#ifdef OPENSSL_EXTRA + +void wolfSSL_BN_clear_free(WOLFSSL_BIGNUM* bn) +{ + WOLFSSL_MSG("wolfSSL_BN_clear_free"); + + wolfSSL_BN_free(bn); +} + + +/* WOLFSSL_SUCCESS on ok */ +int wolfSSL_BN_sub(WOLFSSL_BIGNUM* r, const WOLFSSL_BIGNUM* a, + const WOLFSSL_BIGNUM* b) +{ + WOLFSSL_MSG("wolfSSL_BN_sub"); + + if (r == NULL || a == NULL || b == NULL) + return 0; + + if (mp_sub((mp_int*)a->internal,(mp_int*)b->internal, + (mp_int*)r->internal) == MP_OKAY) + return WOLFSSL_SUCCESS; + + WOLFSSL_MSG("wolfSSL_BN_sub mp_sub failed"); + return 0; +} + +/* WOLFSSL_SUCCESS on ok */ +int wolfSSL_BN_mod(WOLFSSL_BIGNUM* r, const WOLFSSL_BIGNUM* a, + const WOLFSSL_BIGNUM* b, const WOLFSSL_BN_CTX* c) +{ + (void)c; + WOLFSSL_MSG("wolfSSL_BN_mod"); + + if (r == NULL || a == NULL || b == NULL) + return 0; + + if (mp_mod((mp_int*)a->internal,(mp_int*)b->internal, + (mp_int*)r->internal) == MP_OKAY) + return WOLFSSL_SUCCESS; + + WOLFSSL_MSG("wolfSSL_BN_mod mp_mod failed"); + return 0; +} + + +/* r = (a^p) % m */ +int wolfSSL_BN_mod_exp(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *a, + const WOLFSSL_BIGNUM *p, const WOLFSSL_BIGNUM *m, WOLFSSL_BN_CTX *ctx) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_BN_mod_exp"); + + (void) ctx; + if (r == NULL || a == NULL || p == NULL || m == NULL) { + WOLFSSL_MSG("Bad Argument"); + return WOLFSSL_FAILURE; + } + + if ((ret = mp_exptmod((mp_int*)a->internal,(mp_int*)p->internal, + (mp_int*)m->internal, (mp_int*)r->internal)) == MP_OKAY) { + return WOLFSSL_SUCCESS; + } + + WOLFSSL_LEAVE("wolfSSL_BN_mod_exp", ret); + (void)ret; + + return WOLFSSL_FAILURE; +} + +/* r = (a * p) % m */ +int wolfSSL_BN_mod_mul(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *a, + const WOLFSSL_BIGNUM *p, const WOLFSSL_BIGNUM *m, WOLFSSL_BN_CTX *ctx) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_BN_mod_mul"); + + (void) ctx; + if (r == NULL || a == NULL || p == NULL || m == NULL) { + WOLFSSL_MSG("Bad Argument"); + return SSL_FAILURE; + } + + if ((ret = mp_mulmod((mp_int*)a->internal,(mp_int*)p->internal, + (mp_int*)m->internal, (mp_int*)r->internal)) == MP_OKAY) { + return SSL_SUCCESS; + } + + WOLFSSL_LEAVE("wolfSSL_BN_mod_mul", ret); + (void)ret; + + return SSL_FAILURE; +} + +const WOLFSSL_BIGNUM* wolfSSL_BN_value_one(void) +{ + static WOLFSSL_BIGNUM* bn_one = NULL; + + WOLFSSL_MSG("wolfSSL_BN_value_one"); + + if (bn_one == NULL) { + bn_one = wolfSSL_BN_new(); + if (bn_one) { + if (mp_set_int((mp_int*)bn_one->internal, 1) != MP_OKAY) { + /* handle error by freeing BN and returning NULL */ + wolfSSL_BN_free(bn_one); + bn_one = NULL; + } + } + } + + return bn_one; +} + +/* return compliant with OpenSSL + * size of BIGNUM in bytes, 0 if error */ +int wolfSSL_BN_num_bytes(const WOLFSSL_BIGNUM* bn) +{ + WOLFSSL_ENTER("wolfSSL_BN_num_bytes"); + + if (bn == NULL || bn->internal == NULL) + return WOLFSSL_FAILURE; + + return mp_unsigned_bin_size((mp_int*)bn->internal); +} + +/* return compliant with OpenSSL + * size of BIGNUM in bits, 0 if error */ +int wolfSSL_BN_num_bits(const WOLFSSL_BIGNUM* bn) +{ + WOLFSSL_ENTER("wolfSSL_BN_num_bits"); + + if (bn == NULL || bn->internal == NULL) + return WOLFSSL_FAILURE; + + return mp_count_bits((mp_int*)bn->internal); +} + +/* return compliant with OpenSSL + * 1 if BIGNUM is zero, 0 else */ +int wolfSSL_BN_is_zero(const WOLFSSL_BIGNUM* bn) +{ + WOLFSSL_MSG("wolfSSL_BN_is_zero"); + + if (bn == NULL || bn->internal == NULL) + return WOLFSSL_FAILURE; + + if (mp_iszero((mp_int*)bn->internal) == MP_YES) + return WOLFSSL_SUCCESS; + + return WOLFSSL_FAILURE; +} + +/* return compliant with OpenSSL + * 1 if BIGNUM is one, 0 else */ +int wolfSSL_BN_is_one(const WOLFSSL_BIGNUM* bn) +{ + WOLFSSL_MSG("wolfSSL_BN_is_one"); + + if (bn == NULL || bn->internal == NULL) + return WOLFSSL_FAILURE; + + if (mp_cmp_d((mp_int*)bn->internal, 1) == MP_EQ) + return WOLFSSL_SUCCESS; + + return WOLFSSL_FAILURE; +} + +/* return compliant with OpenSSL + * 1 if BIGNUM is odd, 0 else */ +int wolfSSL_BN_is_odd(const WOLFSSL_BIGNUM* bn) +{ + WOLFSSL_MSG("wolfSSL_BN_is_odd"); + + if (bn == NULL || bn->internal == NULL) + return WOLFSSL_FAILURE; + + if (mp_isodd((mp_int*)bn->internal) == MP_YES) + return WOLFSSL_SUCCESS; + + return WOLFSSL_FAILURE; +} + +/* return compliant with OpenSSL + * -1 if a < b, 0 if a == b and 1 if a > b + */ +int wolfSSL_BN_cmp(const WOLFSSL_BIGNUM* a, const WOLFSSL_BIGNUM* b) +{ + int ret; + + WOLFSSL_MSG("wolfSSL_BN_cmp"); + + if (a == NULL || a->internal == NULL || b == NULL || b->internal == NULL) + return WOLFSSL_FATAL_ERROR; + + ret = mp_cmp((mp_int*)a->internal, (mp_int*)b->internal); + + return (ret == MP_EQ ? 0 : (ret == MP_GT ? 1 : -1)); +} + +/* return compliant with OpenSSL + * length of BIGNUM in bytes, -1 if error */ +int wolfSSL_BN_bn2bin(const WOLFSSL_BIGNUM* bn, unsigned char* r) +{ + WOLFSSL_MSG("wolfSSL_BN_bn2bin"); + + if (bn == NULL || bn->internal == NULL) { + WOLFSSL_MSG("NULL bn error"); + return WOLFSSL_FATAL_ERROR; + } + + if (r == NULL) + return mp_unsigned_bin_size((mp_int*)bn->internal); + + if (mp_to_unsigned_bin((mp_int*)bn->internal, r) != MP_OKAY) { + WOLFSSL_MSG("mp_to_unsigned_bin error"); + return WOLFSSL_FATAL_ERROR; + } + + return mp_unsigned_bin_size((mp_int*)bn->internal); +} + + +WOLFSSL_BIGNUM* wolfSSL_BN_bin2bn(const unsigned char* str, int len, + WOLFSSL_BIGNUM* ret) +{ + int weOwn = 0; + + WOLFSSL_MSG("wolfSSL_BN_bin2bn"); + + /* if ret is null create a BN */ + if (ret == NULL) { + ret = wolfSSL_BN_new(); + weOwn = 1; + if (ret == NULL) + return NULL; + } + + /* check ret and ret->internal then read in value */ + if (ret && ret->internal) { + if (mp_read_unsigned_bin((mp_int*)ret->internal, str, len) != 0) { + WOLFSSL_MSG("mp_read_unsigned_bin failure"); + if (weOwn) + wolfSSL_BN_free(ret); + return NULL; + } + } + + return ret; +} + +/* return compliant with OpenSSL + * 1 if success, 0 if error */ +#ifndef NO_WOLFSSL_STUB +int wolfSSL_mask_bits(WOLFSSL_BIGNUM* bn, int n) +{ + (void)bn; + (void)n; + WOLFSSL_ENTER("wolfSSL_BN_mask_bits"); + WOLFSSL_STUB("BN_mask_bits"); + return SSL_FAILURE; +} +#endif + + +/* WOLFSSL_SUCCESS on ok */ +int wolfSSL_BN_rand(WOLFSSL_BIGNUM* bn, int bits, int top, int bottom) +{ + int ret = 0; + int len = bits / 8; + int initTmpRng = 0; + WC_RNG* rng = NULL; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG* tmpRNG = NULL; + byte* buff = NULL; +#else + WC_RNG tmpRNG[1]; + byte buff[1024]; +#endif + + (void)top; + (void)bottom; + WOLFSSL_MSG("wolfSSL_BN_rand"); + + if (bits % 8) + len++; + +#ifdef WOLFSSL_SMALL_STACK + buff = (byte*)XMALLOC(1024, NULL, DYNAMIC_TYPE_TMP_BUFFER); + tmpRNG = (WC_RNG*) XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); + if (buff == NULL || tmpRNG == NULL) { + XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); + return ret; + } +#endif + + if (bn == NULL || bn->internal == NULL) + WOLFSSL_MSG("Bad function arguments"); + else if (wc_InitRng(tmpRNG) == 0) { + rng = tmpRNG; + initTmpRng = 1; + } + else if (initGlobalRNG) + rng = &globalRNG; + + if (rng) { + if (wc_RNG_GenerateBlock(rng, buff, len) != 0) + WOLFSSL_MSG("Bad wc_RNG_GenerateBlock"); + else { + buff[0] |= 0x80 | 0x40; + buff[len-1] |= 0x01; + + if (mp_read_unsigned_bin((mp_int*)bn->internal,buff,len) != MP_OKAY) + WOLFSSL_MSG("mp read bin failed"); + else + ret = WOLFSSL_SUCCESS; + } + } + + if (initTmpRng) + wc_FreeRng(tmpRNG); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); +#endif + + return ret; +} + + +/* WOLFSSL_SUCCESS on ok + * code is same as wolfSSL_BN_rand except for how top and bottom is handled. + * top -1 then leave most sig bit alone + * top 0 then most sig is set to 1 + * top is 1 then first two most sig bits are 1 + * + * bottom is hot then odd number */ +int wolfSSL_BN_pseudo_rand(WOLFSSL_BIGNUM* bn, int bits, int top, int bottom) +{ + int ret = 0; + int len = bits / 8; + int initTmpRng = 0; + WC_RNG* rng = NULL; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG* tmpRNG = NULL; + byte* buff = NULL; +#else + WC_RNG tmpRNG[1]; + byte buff[1024]; +#endif + + WOLFSSL_MSG("wolfSSL_BN_rand"); + + if (bits % 8) + len++; + +#ifdef WOLFSSL_SMALL_STACK + buff = (byte*)XMALLOC(1024, NULL, DYNAMIC_TYPE_TMP_BUFFER); + tmpRNG = (WC_RNG*) XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (buff == NULL || tmpRNG == NULL) { + XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } +#endif + + if (bn == NULL || bn->internal == NULL) + WOLFSSL_MSG("Bad function arguments"); + else if (wc_InitRng(tmpRNG) == 0) { + rng = tmpRNG; + initTmpRng = 1; + } + else if (initGlobalRNG) + rng = &globalRNG; + + if (rng) { + if (wc_RNG_GenerateBlock(rng, buff, len) != 0) + WOLFSSL_MSG("Bad wc_RNG_GenerateBlock"); + else { + switch (top) { + case -1: + break; + + case 0: + buff[0] |= 0x80; + break; + + case 1: + buff[0] |= 0x80 | 0x40; + break; + } + + if (bottom == 1) { + buff[len-1] |= 0x01; + } + + if (mp_read_unsigned_bin((mp_int*)bn->internal,buff,len) != MP_OKAY) + WOLFSSL_MSG("mp read bin failed"); + else + ret = WOLFSSL_SUCCESS; + } + } + + if (initTmpRng) + wc_FreeRng(tmpRNG); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(buff, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +/* return code compliant with OpenSSL : + * 1 if bit set, 0 else + */ +int wolfSSL_BN_is_bit_set(const WOLFSSL_BIGNUM* bn, int n) +{ + if (bn == NULL || bn->internal == NULL) { + WOLFSSL_MSG("bn NULL error"); + return WOLFSSL_FAILURE; + } + + if (n > DIGIT_BIT) { + WOLFSSL_MSG("input bit count too large"); + return WOLFSSL_FAILURE; + } + + return mp_is_bit_set((mp_int*)bn->internal, (mp_digit)n); +} + +/* return code compliant with OpenSSL : + * 1 if success, 0 else + */ +int wolfSSL_BN_set_bit(WOLFSSL_BIGNUM* bn, int n) +{ + if (bn == NULL || bn->internal == NULL) { + WOLFSSL_MSG("bn NULL error"); + return WOLFSSL_FAILURE; + } + + if (mp_set_bit((mp_int*)bn->internal, n) != MP_OKAY) { + WOLFSSL_MSG("mp_set_int error"); + return WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; +} + + +/* WOLFSSL_SUCCESS on ok */ +/* Note on use: this function expects str to be an even length. It is + * converting pairs of bytes into 8-bit values. As an example, the RSA + * public exponent is commonly 0x010001. To get it to convert, you need + * to pass in the string "010001", it will fail if you use "10001". This + * is an affect of how Base16_Decode() works. + */ +int wolfSSL_BN_hex2bn(WOLFSSL_BIGNUM** bn, const char* str) +{ + int ret = 0; + word32 decSz = 1024; +#ifdef WOLFSSL_SMALL_STACK + byte* decoded = NULL; +#else + byte decoded[1024]; +#endif + int weOwn = 0; + + WOLFSSL_MSG("wolfSSL_BN_hex2bn"); + +#ifdef WOLFSSL_SMALL_STACK + decoded = (byte*)XMALLOC(decSz, NULL, DYNAMIC_TYPE_DER); + if (decoded == NULL) + return ret; +#endif + + if (str == NULL || str[0] == '\0') + WOLFSSL_MSG("Bad function argument"); + else if (Base16_Decode((byte*)str, (int)XSTRLEN(str), decoded, &decSz) < 0) + WOLFSSL_MSG("Bad Base16_Decode error"); + else if (bn == NULL) + ret = decSz; + else { + if (*bn == NULL) { + *bn = wolfSSL_BN_new(); + if (*bn != NULL) { + weOwn = 1; + } + } + + if (*bn == NULL) + WOLFSSL_MSG("BN new failed"); + else if (wolfSSL_BN_bin2bn(decoded, decSz, *bn) == NULL) { + WOLFSSL_MSG("Bad bin2bn error"); + if (weOwn == 1) { + wolfSSL_BN_free(*bn); /* Free new BN */ + } + } + else + ret = WOLFSSL_SUCCESS; + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(decoded, NULL, DYNAMIC_TYPE_DER); +#endif + + return ret; +} + + +WOLFSSL_BIGNUM* wolfSSL_BN_dup(const WOLFSSL_BIGNUM* bn) +{ + WOLFSSL_BIGNUM* ret; + + WOLFSSL_MSG("wolfSSL_BN_dup"); + + if (bn == NULL || bn->internal == NULL) { + WOLFSSL_MSG("bn NULL error"); + return NULL; + } + + ret = wolfSSL_BN_new(); + if (ret == NULL) { + WOLFSSL_MSG("bn new error"); + return NULL; + } + + if (mp_copy((mp_int*)bn->internal, (mp_int*)ret->internal) != MP_OKAY) { + WOLFSSL_MSG("mp_copy error"); + wolfSSL_BN_free(ret); + return NULL; + } + + ret->neg = bn->neg; + + return ret; +} + + +WOLFSSL_BIGNUM* wolfSSL_BN_copy(WOLFSSL_BIGNUM* r, const WOLFSSL_BIGNUM* bn) +{ + WOLFSSL_MSG("wolfSSL_BN_copy"); + + if (r == NULL || bn == NULL) { + WOLFSSL_MSG("r or bn NULL error"); + return NULL; + } + + if (mp_copy((mp_int*)bn->internal, (mp_int*)r->internal) != MP_OKAY) { + WOLFSSL_MSG("mp_copy error"); + return NULL; + } + + r->neg = bn->neg; + + return r; +} + +/* return code compliant with OpenSSL : + * 1 if success, 0 else + */ +int wolfSSL_BN_set_word(WOLFSSL_BIGNUM* bn, WOLFSSL_BN_ULONG w) +{ + WOLFSSL_MSG("wolfSSL_BN_set_word"); + + if (bn == NULL) { + WOLFSSL_MSG("bn NULL error"); + return WOLFSSL_FAILURE; + } + + if (mp_set_int((mp_int*)bn->internal, w) != MP_OKAY) { + WOLFSSL_MSG("mp_init_set_int error"); + return WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; +} + + +/* Returns the big number as an unsigned long if possible. + * + * bn big number structure to get value from + * + * Returns value or 0xFFFFFFFFL if bigger than unsigned long. + */ +unsigned long wolfSSL_BN_get_word(const WOLFSSL_BIGNUM* bn) +{ + mp_int* mp; + + WOLFSSL_MSG("wolfSSL_BN_get_word"); + + if (bn == NULL) { + WOLFSSL_MSG("Invalid argument"); + return 0; + } + + if (wolfSSL_BN_num_bytes(bn) > (int)sizeof(unsigned long)) { + WOLFSSL_MSG("bignum is larger than unsigned long"); + return 0xFFFFFFFFL; + } + mp = (mp_int*)bn->internal; + + return (unsigned long)(mp->dp[0]); +} + +/* return code compliant with OpenSSL : + * number length in decimal if success, 0 if error + */ +#ifndef NO_WOLFSSL_STUB +int wolfSSL_BN_dec2bn(WOLFSSL_BIGNUM** bn, const char* str) +{ + (void)bn; + (void)str; + + WOLFSSL_MSG("wolfSSL_BN_dec2bn"); + WOLFSSL_STUB("BN_dec2bn"); + return SSL_FAILURE; +} +#endif + +#if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) +char *wolfSSL_BN_bn2dec(const WOLFSSL_BIGNUM *bn) +{ + int len = 0; + char *buf; + + WOLFSSL_MSG("wolfSSL_BN_bn2dec"); + + if (bn == NULL || bn->internal == NULL) { + WOLFSSL_MSG("bn NULL error"); + return NULL; + } + + if (mp_radix_size((mp_int*)bn->internal, MP_RADIX_DEC, &len) != MP_OKAY) { + WOLFSSL_MSG("mp_radix_size failure"); + return NULL; + } + + buf = (char*) XMALLOC(len, NULL, DYNAMIC_TYPE_OPENSSL); + if (buf == NULL) { + WOLFSSL_MSG("BN_bn2dec malloc buffer failure"); + return NULL; + } + + if (mp_todecimal((mp_int*)bn->internal, buf) != MP_OKAY) { + XFREE(buf, NULL, DYNAMIC_TYPE_ECC); + return NULL; + } + + return buf; +} +#else +char* wolfSSL_BN_bn2dec(const WOLFSSL_BIGNUM* bn) +{ + (void)bn; + + WOLFSSL_MSG("wolfSSL_BN_bn2dec"); + + return NULL; +} +#endif /* defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) */ + +/* return code compliant with OpenSSL : + * 1 if success, 0 else + */ +int wolfSSL_BN_lshift(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *bn, int n) +{ + WOLFSSL_MSG("wolfSSL_BN_lshift"); + + if (r == NULL || r->internal == NULL || bn == NULL || bn->internal == NULL){ + WOLFSSL_MSG("bn NULL error"); + return WOLFSSL_FAILURE; + } + + if (mp_mul_2d((mp_int*)bn->internal, n, (mp_int*)r->internal) != MP_OKAY) { + WOLFSSL_MSG("mp_mul_2d error"); + return WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; +} + +/* return code compliant with OpenSSL : + * 1 if success, 0 else + */ +int wolfSSL_BN_rshift(WOLFSSL_BIGNUM *r, const WOLFSSL_BIGNUM *bn, int n) +{ + WOLFSSL_MSG("wolfSSL_BN_rshift"); + + if (r == NULL || r->internal == NULL || bn == NULL || bn->internal == NULL){ + WOLFSSL_MSG("bn NULL error"); + return WOLFSSL_FAILURE; + } + + if (mp_div_2d((mp_int*)bn->internal, n, + (mp_int*)r->internal, NULL) != MP_OKAY) { + WOLFSSL_MSG("mp_mul_2d error"); + return WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; +} + +/* return code compliant with OpenSSL : + * 1 if success, 0 else + */ +int wolfSSL_BN_add_word(WOLFSSL_BIGNUM *bn, WOLFSSL_BN_ULONG w) +{ + WOLFSSL_MSG("wolfSSL_BN_add_word"); + + if (bn == NULL || bn->internal == NULL) { + WOLFSSL_MSG("bn NULL error"); + return WOLFSSL_FAILURE; + } + + if (mp_add_d((mp_int*)bn->internal, w, (mp_int*)bn->internal) != MP_OKAY) { + WOLFSSL_MSG("mp_add_d error"); + return WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; +} + +/* return code compliant with OpenSSL : + * 1 if success, 0 else + */ +int wolfSSL_BN_add(WOLFSSL_BIGNUM *r, WOLFSSL_BIGNUM *a, WOLFSSL_BIGNUM *b) +{ + WOLFSSL_MSG("wolfSSL_BN_add"); + + if (r == NULL || r->internal == NULL || a == NULL || a->internal == NULL || + b == NULL || b->internal == NULL) { + WOLFSSL_MSG("bn NULL error"); + return WOLFSSL_FAILURE; + } + + if (mp_add((mp_int*)a->internal, (mp_int*)b->internal, + (mp_int*)r->internal) != MP_OKAY) { + WOLFSSL_MSG("mp_add_d error"); + return WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; +} + +#ifdef WOLFSSL_KEY_GEN + +/* return code compliant with OpenSSL : + * 1 if prime, 0 if not, -1 if error + */ +int wolfSSL_BN_is_prime_ex(const WOLFSSL_BIGNUM *bn, int nbchecks, + WOLFSSL_BN_CTX *ctx, WOLFSSL_BN_GENCB *cb) +{ + WC_RNG* rng = NULL; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG* tmpRNG = NULL; +#else + WC_RNG tmpRNG[1]; +#endif + int initTmpRng = 0; + int res = MP_NO; + + (void)ctx; + (void)cb; + + WOLFSSL_MSG("wolfSSL_BN_is_prime_ex"); + + if (bn == NULL || bn->internal == NULL) { + WOLFSSL_MSG("bn NULL error"); + return WOLFSSL_FATAL_ERROR; + } + +#ifdef WOLFSSL_SMALL_STACK + tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); + if (tmpRNG == NULL) + return WOLFSSL_FAILURE; +#endif + if (wc_InitRng(tmpRNG) == 0) { + rng = tmpRNG; + initTmpRng = 1; + } + else { + WOLFSSL_MSG("Bad RNG Init, trying global"); + if (initGlobalRNG == 0) { + WOLFSSL_MSG("Global RNG no Init"); + } + else + rng = &globalRNG; + } + + if (rng) { + if (mp_prime_is_prime_ex((mp_int*)bn->internal, + nbchecks, &res, rng) != MP_OKAY) { + WOLFSSL_MSG("mp_prime_is_prime_ex error"); + res = MP_NO; + } + } + + if (initTmpRng) + wc_FreeRng(tmpRNG); +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); +#endif + + if (res != MP_YES) { + WOLFSSL_MSG("mp_prime_is_prime_ex not prime"); + return WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; +} + +/* return code compliant with OpenSSL : + * (bn mod w) if success, -1 if error + */ +WOLFSSL_BN_ULONG wolfSSL_BN_mod_word(const WOLFSSL_BIGNUM *bn, + WOLFSSL_BN_ULONG w) +{ + WOLFSSL_BN_ULONG ret = 0; + + WOLFSSL_MSG("wolfSSL_BN_mod_word"); + + if (bn == NULL || bn->internal == NULL) { + WOLFSSL_MSG("bn NULL error"); + return (WOLFSSL_BN_ULONG)WOLFSSL_FATAL_ERROR; + } + + if (mp_mod_d((mp_int*)bn->internal, w, &ret) != MP_OKAY) { + WOLFSSL_MSG("mp_add_d error"); + return (WOLFSSL_BN_ULONG)WOLFSSL_FATAL_ERROR; + } + + return ret; +} +#endif /* #ifdef WOLFSSL_KEY_GEN */ + +char *wolfSSL_BN_bn2hex(const WOLFSSL_BIGNUM *bn) +{ + int len = 0; + char *buf; + + WOLFSSL_ENTER("wolfSSL_BN_bn2hex"); + + if (bn == NULL || bn->internal == NULL) { + WOLFSSL_MSG("bn NULL error"); + return NULL; + } + + if (mp_radix_size((mp_int*)bn->internal, MP_RADIX_HEX, &len) != MP_OKAY) { + WOLFSSL_MSG("mp_radix_size failure"); + return NULL; + } + len += 1; /* add one for null terminator */ + + buf = (char*)XMALLOC(len, NULL, DYNAMIC_TYPE_OPENSSL); + if (buf == NULL) { + WOLFSSL_MSG("BN_bn2hex malloc buffer failure"); + return NULL; + } + + if (mp_tohex((mp_int*)bn->internal, buf) != MP_OKAY) { + XFREE(buf, NULL, DYNAMIC_TYPE_OPENSSL); + return NULL; + } + + return buf; +} + +#ifndef NO_FILESYSTEM +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_BN_print_fp(XFILE fp, const WOLFSSL_BIGNUM *bn) +{ + char *buf; + + WOLFSSL_ENTER("wolfSSL_BN_print_fp"); + + if (fp == XBADFILE || bn == NULL || bn->internal == NULL) { + WOLFSSL_MSG("bn NULL error"); + return WOLFSSL_FAILURE; + } + + buf = wolfSSL_BN_bn2hex(bn); + if (buf == NULL) { + WOLFSSL_MSG("wolfSSL_BN_bn2hex failure"); + return WOLFSSL_FAILURE; + } + + fprintf(fp, "%s", buf); + XFREE(buf, NULL, DYNAMIC_TYPE_OPENSSL); + + return WOLFSSL_SUCCESS; +} +#endif /* !NO_FILESYSTEM */ + + +WOLFSSL_BIGNUM *wolfSSL_BN_CTX_get(WOLFSSL_BN_CTX *ctx) +{ + /* ctx is not used, return new Bignum */ + (void)ctx; + + WOLFSSL_ENTER("wolfSSL_BN_CTX_get"); + + return wolfSSL_BN_new(); +} + +#ifndef NO_WOLFSSL_STUB +void wolfSSL_BN_CTX_start(WOLFSSL_BN_CTX *ctx) +{ + (void)ctx; + + WOLFSSL_ENTER("wolfSSL_BN_CTX_start"); + WOLFSSL_STUB("BN_CTX_start"); + WOLFSSL_MSG("wolfSSL_BN_CTX_start TBD"); +} +#endif + + +WOLFSSL_BIGNUM *wolfSSL_BN_mod_inverse(WOLFSSL_BIGNUM *r, + WOLFSSL_BIGNUM *a, + const WOLFSSL_BIGNUM *n, + WOLFSSL_BN_CTX *ctx) +{ + int dynamic = 0; + + /* ctx is not used */ + (void)ctx; + + WOLFSSL_ENTER("wolfSSL_BN_mod_inverse"); + + /* check parameter */ + if (r == NULL) { + r = wolfSSL_BN_new(); + if (r == NULL){ + WOLFSSL_MSG("WolfSSL_BN_new() failed"); + return NULL; + } + dynamic = 1; + } + + if (a == NULL) { + WOLFSSL_MSG("a NULL error"); + if (dynamic == 1) { + wolfSSL_BN_free(r); + } + return NULL; + } + + if (n == NULL) { + WOLFSSL_MSG("n NULL error"); + if (dynamic == 1) { + wolfSSL_BN_free(r); + } + return NULL; + } + + /* Compute inverse of a modulo n and return r */ + if (mp_invmod((mp_int *)a->internal,(mp_int *)n->internal, + (mp_int*)r->internal) == MP_VAL){ + WOLFSSL_MSG("mp_invmod() error"); + if (dynamic == 1) { + wolfSSL_BN_free(r); + } + return NULL; + } + + return r; +} + +#ifndef NO_DH + +static void InitwolfSSL_DH(WOLFSSL_DH* dh) +{ + if (dh) { + dh->p = NULL; + dh->g = NULL; + dh->q = NULL; + dh->pub_key = NULL; + dh->priv_key = NULL; + dh->internal = NULL; + dh->inSet = 0; + dh->exSet = 0; + } +} + + +WOLFSSL_DH* wolfSSL_DH_new(void) +{ + WOLFSSL_DH* external; + DhKey* key; + + WOLFSSL_MSG("wolfSSL_DH_new"); + + key = (DhKey*) XMALLOC(sizeof(DhKey), NULL, DYNAMIC_TYPE_DH); + if (key == NULL) { + WOLFSSL_MSG("wolfSSL_DH_new malloc DhKey failure"); + return NULL; + } + + external = (WOLFSSL_DH*) XMALLOC(sizeof(WOLFSSL_DH), NULL, + DYNAMIC_TYPE_DH); + if (external == NULL) { + WOLFSSL_MSG("wolfSSL_DH_new malloc WOLFSSL_DH failure"); + XFREE(key, NULL, DYNAMIC_TYPE_DH); + return NULL; + } + + InitwolfSSL_DH(external); + if (wc_InitDhKey(key) != 0) { + WOLFSSL_MSG("wolfSSL_DH_new InitDhKey failure"); + XFREE(key, NULL, DYNAMIC_TYPE_DH); + XFREE(external, NULL, DYNAMIC_TYPE_DH); + return NULL; + } + external->internal = key; + + return external; +} + + +void wolfSSL_DH_free(WOLFSSL_DH* dh) +{ + WOLFSSL_MSG("wolfSSL_DH_free"); + + if (dh) { + if (dh->internal) { + wc_FreeDhKey((DhKey*)dh->internal); + XFREE(dh->internal, NULL, DYNAMIC_TYPE_DH); + dh->internal = NULL; + } + wolfSSL_BN_free(dh->priv_key); + wolfSSL_BN_free(dh->pub_key); + wolfSSL_BN_free(dh->g); + wolfSSL_BN_free(dh->p); + wolfSSL_BN_free(dh->q); + InitwolfSSL_DH(dh); /* set back to NULLs for safety */ + + XFREE(dh, NULL, DYNAMIC_TYPE_DH); + } +} + + +static int SetDhInternal(WOLFSSL_DH* dh) +{ + int ret = WOLFSSL_FATAL_ERROR; + int pSz = 1024; + int gSz = 1024; +#ifdef WOLFSSL_SMALL_STACK + unsigned char* p = NULL; + unsigned char* g = NULL; +#else + unsigned char p[1024]; + unsigned char g[1024]; +#endif + + WOLFSSL_ENTER("SetDhInternal"); + + if (dh == NULL || dh->p == NULL || dh->g == NULL) + WOLFSSL_MSG("Bad function arguments"); + else if (wolfSSL_BN_bn2bin(dh->p, NULL) > pSz) + WOLFSSL_MSG("Bad p internal size"); + else if (wolfSSL_BN_bn2bin(dh->g, NULL) > gSz) + WOLFSSL_MSG("Bad g internal size"); + else { + #ifdef WOLFSSL_SMALL_STACK + p = (unsigned char*)XMALLOC(pSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + g = (unsigned char*)XMALLOC(gSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + + if (p == NULL || g == NULL) { + XFREE(p, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + XFREE(g, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + return ret; + } + #endif + + pSz = wolfSSL_BN_bn2bin(dh->p, p); + gSz = wolfSSL_BN_bn2bin(dh->g, g); + + if (pSz <= 0 || gSz <= 0) + WOLFSSL_MSG("Bad BN2bin set"); + else if (wc_DhSetKey((DhKey*)dh->internal, p, pSz, g, gSz) < 0) + WOLFSSL_MSG("Bad DH SetKey"); + else { + dh->inSet = 1; + ret = WOLFSSL_SUCCESS; + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(p, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + XFREE(g, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + #endif + } + + + return ret; +} + +/* return code compliant with OpenSSL : + * DH prime size in bytes if success, 0 if error + */ +int wolfSSL_DH_size(WOLFSSL_DH* dh) +{ + WOLFSSL_MSG("wolfSSL_DH_size"); + + if (dh == NULL) + return WOLFSSL_FATAL_ERROR; + + return wolfSSL_BN_num_bytes(dh->p); +} + + +/* This sets a big number with the 1536-bit prime from RFC 3526. + * + * bn if not NULL then the big number structure is used. If NULL then a new + * big number structure is created. + * + * Returns a WOLFSSL_BIGNUM structure on success and NULL with failure. + */ +WOLFSSL_BIGNUM* wolfSSL_DH_1536_prime(WOLFSSL_BIGNUM* bn) +{ + const char prm[] = { + "FFFFFFFFFFFFFFFFC90FDAA22168C234" + "C4C6628B80DC1CD129024E088A67CC74" + "020BBEA63B139B22514A08798E3404DD" + "EF9519B3CD3A431B302B0A6DF25F1437" + "4FE1356D6D51C245E485B576625E7EC6" + "F44C42E9A637ED6B0BFF5CB6F406B7ED" + "EE386BFB5A899FA5AE9F24117C4B1FE6" + "49286651ECE45B3DC2007CB8A163BF05" + "98DA48361C55D39A69163FA8FD24CF5F" + "83655D23DCA3AD961C62F356208552BB" + "9ED529077096966D670C354E4ABC9804" + "F1746C08CA237327FFFFFFFFFFFFFFFF" + }; + + WOLFSSL_ENTER("wolfSSL_DH_1536_prime"); + + if (wolfSSL_BN_hex2bn(&bn, prm) != SSL_SUCCESS) { + WOLFSSL_MSG("Error converting DH 1536 prime to big number"); + return NULL; + } + + return bn; +} + + +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_DH_generate_key(WOLFSSL_DH* dh) +{ + int ret = WOLFSSL_FAILURE; + word32 pubSz = 0; + word32 privSz = 0; + int initTmpRng = 0; + WC_RNG* rng = NULL; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG* tmpRNG = NULL; +#else + WC_RNG tmpRNG[1]; +#endif + unsigned char* pub = NULL; + unsigned char* priv = NULL; + + WOLFSSL_MSG("wolfSSL_DH_generate_key"); + +#ifdef WOLFSSL_SMALL_STACK + tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); + + if (tmpRNG == NULL) { + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); + return ret; + } +#endif + + if (dh == NULL || dh->p == NULL || dh->g == NULL) + WOLFSSL_MSG("Bad function arguments"); + else if (dh->inSet == 0 && SetDhInternal(dh) != WOLFSSL_SUCCESS) + WOLFSSL_MSG("Bad DH set internal"); + else if (wc_InitRng(tmpRNG) == 0) { + rng = tmpRNG; + initTmpRng = 1; + } + else { + WOLFSSL_MSG("Bad RNG Init, trying global"); + if (initGlobalRNG == 0) + WOLFSSL_MSG("Global RNG no Init"); + else + rng = &globalRNG; + } + + if (rng) { + pubSz = privSz = wolfSSL_BN_num_bytes(dh->p); + pub = (unsigned char*)XMALLOC(pubSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + priv = (unsigned char*)XMALLOC(privSz, NULL, DYNAMIC_TYPE_PRIVATE_KEY); + if (pub == NULL || priv == NULL) { + WOLFSSL_MSG("Unable to malloc memory"); + } + else if (wc_DhGenerateKeyPair((DhKey*)dh->internal, rng, priv, &privSz, + pub, &pubSz) < 0) + WOLFSSL_MSG("Bad wc_DhGenerateKeyPair"); + else { + if (dh->pub_key) + wolfSSL_BN_free(dh->pub_key); + + dh->pub_key = wolfSSL_BN_new(); + if (dh->pub_key == NULL) { + WOLFSSL_MSG("Bad DH new pub"); + } + if (dh->priv_key) + wolfSSL_BN_free(dh->priv_key); + + dh->priv_key = wolfSSL_BN_new(); + + if (dh->priv_key == NULL) { + WOLFSSL_MSG("Bad DH new priv"); + } + + if (dh->pub_key && dh->priv_key) { + if (wolfSSL_BN_bin2bn(pub, pubSz, dh->pub_key) == NULL) + WOLFSSL_MSG("Bad DH bn2bin error pub"); + else if (wolfSSL_BN_bin2bn(priv, privSz, dh->priv_key) == NULL) + WOLFSSL_MSG("Bad DH bn2bin error priv"); + else + ret = WOLFSSL_SUCCESS; + } + } + } + + if (initTmpRng) + wc_FreeRng(tmpRNG); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); +#endif + XFREE(pub, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + XFREE(priv, NULL, DYNAMIC_TYPE_PRIVATE_KEY); + + return ret; +} + + +/* return code compliant with OpenSSL : + * size of shared secret if success, -1 if error + */ +int wolfSSL_DH_compute_key(unsigned char* key, WOLFSSL_BIGNUM* otherPub, + WOLFSSL_DH* dh) +{ + int ret = WOLFSSL_FATAL_ERROR; + word32 keySz = 0; + word32 pubSz = 1024; + word32 privSz = 1024; +#ifdef WOLFSSL_SMALL_STACK + unsigned char* pub = NULL; + unsigned char* priv = NULL; +#else + unsigned char pub [1024]; + unsigned char priv[1024]; +#endif + + WOLFSSL_MSG("wolfSSL_DH_compute_key"); + +#ifdef WOLFSSL_SMALL_STACK + pub = (unsigned char*)XMALLOC(pubSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + if (pub == NULL) + return ret; + + priv = (unsigned char*)XMALLOC(privSz, NULL, DYNAMIC_TYPE_PRIVATE_KEY); + if (priv == NULL) { + XFREE(pub, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + return ret; + } +#endif + + if (dh == NULL || dh->priv_key == NULL || otherPub == NULL) + WOLFSSL_MSG("Bad function arguments"); + else if ((keySz = (word32)DH_size(dh)) == 0) + WOLFSSL_MSG("Bad DH_size"); + else if (wolfSSL_BN_bn2bin(dh->priv_key, NULL) > (int)privSz) + WOLFSSL_MSG("Bad priv internal size"); + else if (wolfSSL_BN_bn2bin(otherPub, NULL) > (int)pubSz) + WOLFSSL_MSG("Bad otherPub size"); + else { + privSz = wolfSSL_BN_bn2bin(dh->priv_key, priv); + pubSz = wolfSSL_BN_bn2bin(otherPub, pub); + if (dh->inSet == 0 && SetDhInternal(dh) != SSL_SUCCESS){ + WOLFSSL_MSG("Bad DH set internal"); + } + if (privSz <= 0 || pubSz <= 0) + WOLFSSL_MSG("Bad BN2bin set"); + else if (wc_DhAgree((DhKey*)dh->internal, key, &keySz, + priv, privSz, pub, pubSz) < 0) + WOLFSSL_MSG("wc_DhAgree failed"); + else + ret = (int)keySz; + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(pub, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + XFREE(priv, NULL, DYNAMIC_TYPE_PRIVATE_KEY); +#endif + + return ret; +} +#endif /* NO_DH */ + + +#ifndef NO_DSA +static void InitwolfSSL_DSA(WOLFSSL_DSA* dsa) +{ + if (dsa) { + dsa->p = NULL; + dsa->q = NULL; + dsa->g = NULL; + dsa->pub_key = NULL; + dsa->priv_key = NULL; + dsa->internal = NULL; + dsa->inSet = 0; + dsa->exSet = 0; + } +} + + +WOLFSSL_DSA* wolfSSL_DSA_new(void) +{ + WOLFSSL_DSA* external; + DsaKey* key; + + WOLFSSL_MSG("wolfSSL_DSA_new"); + + key = (DsaKey*) XMALLOC(sizeof(DsaKey), NULL, DYNAMIC_TYPE_DSA); + if (key == NULL) { + WOLFSSL_MSG("wolfSSL_DSA_new malloc DsaKey failure"); + return NULL; + } + + external = (WOLFSSL_DSA*) XMALLOC(sizeof(WOLFSSL_DSA), NULL, + DYNAMIC_TYPE_DSA); + if (external == NULL) { + WOLFSSL_MSG("wolfSSL_DSA_new malloc WOLFSSL_DSA failure"); + XFREE(key, NULL, DYNAMIC_TYPE_DSA); + return NULL; + } + + InitwolfSSL_DSA(external); + if (wc_InitDsaKey(key) != 0) { + WOLFSSL_MSG("wolfSSL_DSA_new InitDsaKey failure"); + XFREE(key, NULL, DYNAMIC_TYPE_DSA); + wolfSSL_DSA_free(external); + return NULL; + } + external->internal = key; + + return external; +} + + +void wolfSSL_DSA_free(WOLFSSL_DSA* dsa) +{ + WOLFSSL_MSG("wolfSSL_DSA_free"); + + if (dsa) { + if (dsa->internal) { + FreeDsaKey((DsaKey*)dsa->internal); + XFREE(dsa->internal, NULL, DYNAMIC_TYPE_DSA); + dsa->internal = NULL; + } + wolfSSL_BN_free(dsa->priv_key); + wolfSSL_BN_free(dsa->pub_key); + wolfSSL_BN_free(dsa->g); + wolfSSL_BN_free(dsa->q); + wolfSSL_BN_free(dsa->p); + InitwolfSSL_DSA(dsa); /* set back to NULLs for safety */ + + XFREE(dsa, NULL, DYNAMIC_TYPE_DSA); + dsa = NULL; + } +} + +#endif /* NO_DSA */ + +#endif /* OPENSSL_EXTRA */ +#if !defined(NO_RSA) && defined(OPENSSL_EXTRA_X509_SMALL) +static void InitwolfSSL_Rsa(WOLFSSL_RSA* rsa) +{ + if (rsa) { + XMEMSET(rsa, 0, sizeof(WOLFSSL_RSA)); + } +} + +void wolfSSL_RSA_free(WOLFSSL_RSA* rsa) +{ + WOLFSSL_ENTER("wolfSSL_RSA_free"); + + if (rsa) { + if (rsa->internal) { +#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && \ + !defined(HAVE_FAST_RSA) && defined(WC_RSA_BLINDING) + WC_RNG* rng; + + /* check if RNG is owned before freeing it */ + if (rsa->ownRng) { + rng = ((RsaKey*)rsa->internal)->rng; + if (rng != NULL && rng != &globalRNG) { + wc_FreeRng(rng); + XFREE(rng, NULL, DYNAMIC_TYPE_RNG); + } + } +#endif /* WC_RSA_BLINDING */ + wc_FreeRsaKey((RsaKey*)rsa->internal); + XFREE(rsa->internal, NULL, DYNAMIC_TYPE_RSA); + rsa->internal = NULL; + } + wolfSSL_BN_free(rsa->iqmp); + wolfSSL_BN_free(rsa->dmq1); + wolfSSL_BN_free(rsa->dmp1); + wolfSSL_BN_free(rsa->q); + wolfSSL_BN_free(rsa->p); + wolfSSL_BN_free(rsa->d); + wolfSSL_BN_free(rsa->e); + wolfSSL_BN_free(rsa->n); + + #ifdef WC_RSA_BLINDING + if (wc_FreeRng(rsa->rng) != 0) { + WOLFSSL_MSG("Issue freeing rng"); + } + XFREE(rsa->rng, NULL, DYNAMIC_TYPE_RNG); + #endif + + InitwolfSSL_Rsa(rsa); /* set back to NULLs for safety */ + + XFREE(rsa, NULL, DYNAMIC_TYPE_RSA); + rsa = NULL; + } +} + +WOLFSSL_RSA* wolfSSL_RSA_new(void) +{ + WOLFSSL_RSA* external; + RsaKey* key; + + WOLFSSL_ENTER("wolfSSL_RSA_new"); + + key = (RsaKey*) XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_RSA); + if (key == NULL) { + WOLFSSL_MSG("wolfSSL_RSA_new malloc RsaKey failure"); + return NULL; + } + + external = (WOLFSSL_RSA*) XMALLOC(sizeof(WOLFSSL_RSA), NULL, + DYNAMIC_TYPE_RSA); + if (external == NULL) { + WOLFSSL_MSG("wolfSSL_RSA_new malloc WOLFSSL_RSA failure"); + XFREE(key, NULL, DYNAMIC_TYPE_RSA); + return NULL; + } + + InitwolfSSL_Rsa(external); + if (wc_InitRsaKey(key, NULL) != 0) { + WOLFSSL_MSG("InitRsaKey WOLFSSL_RSA failure"); + XFREE(external, NULL, DYNAMIC_TYPE_RSA); + XFREE(key, NULL, DYNAMIC_TYPE_RSA); + return NULL; + } + +#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && \ + !defined(HAVE_FAST_RSA) && defined(WC_RSA_BLINDING) + { + WC_RNG* rng = NULL; + + rng = (WC_RNG*) XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); + if (rng != NULL && wc_InitRng(rng) != 0) { + WOLFSSL_MSG("InitRng failure, attempting to use global RNG"); + XFREE(rng, NULL, DYNAMIC_TYPE_RNG); + rng = NULL; + } + + external->ownRng = 1; + if (rng == NULL && initGlobalRNG) { + external->ownRng = 0; + rng = &globalRNG; + } + + if (rng == NULL) { + WOLFSSL_MSG("wolfSSL_RSA_new no WC_RNG for blinding"); + XFREE(external, NULL, DYNAMIC_TYPE_RSA); + XFREE(key, NULL, DYNAMIC_TYPE_RSA); + return NULL; + } + + wc_RsaSetRNG(key, rng); + } +#endif /* WC_RSA_BLINDING */ + + external->internal = key; + external->inSet = 0; + return external; +} +#endif /* !NO_RSA && OPENSSL_EXTRA_X509_SMALL */ + +/* these defines are to make sure the functions SetIndividualExternal is not + * declared and then not used. */ +#if !defined(NO_ASN) || !defined(NO_DSA) || defined(HAVE_ECC) || \ + (!defined(NO_RSA) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA)) + +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) +/* when calling SetIndividualExternal, mpi should be cleared by caller if no + * longer used. ie mp_free(mpi). This is to free data when fastmath is + * disabled since a copy of mpi is made by this function and placed into bn. + */ +static int SetIndividualExternal(WOLFSSL_BIGNUM** bn, mp_int* mpi) +{ + byte dynamic = 0; + + WOLFSSL_MSG("Entering SetIndividualExternal"); + + if (mpi == NULL || bn == NULL) { + WOLFSSL_MSG("mpi NULL error"); + return WOLFSSL_FATAL_ERROR; + } + + if (*bn == NULL) { + *bn = wolfSSL_BN_new(); + if (*bn == NULL) { + WOLFSSL_MSG("SetIndividualExternal alloc failed"); + return WOLFSSL_FATAL_ERROR; + } + dynamic = 1; + } + + if (mp_copy(mpi, (mp_int*)((*bn)->internal)) != MP_OKAY) { + WOLFSSL_MSG("mp_copy error"); + if (dynamic == 1) { + wolfSSL_BN_free(*bn); + } + return WOLFSSL_FATAL_ERROR; + } + + return WOLFSSL_SUCCESS; +} +#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ + +#ifdef OPENSSL_EXTRA /* only without X509_SMALL */ +/* when calling SetIndividualInternal, mpi should be cleared by caller if no + * longer used. ie mp_free(mpi). This is to free data when fastmath is + * disabled since a copy of mpi is made by this function and placed into bn. + */ +static int SetIndividualInternal(WOLFSSL_BIGNUM* bn, mp_int* mpi) +{ + WOLFSSL_MSG("Entering SetIndividualInternal"); + + if (bn == NULL || bn->internal == NULL) { + WOLFSSL_MSG("bn NULL error"); + return WOLFSSL_FATAL_ERROR; + } + + if (mpi == NULL || (mp_init(mpi) != MP_OKAY)) { + WOLFSSL_MSG("mpi NULL error"); + return WOLFSSL_FATAL_ERROR; + } + + if (mp_copy((mp_int*)bn->internal, mpi) != MP_OKAY) { + WOLFSSL_MSG("mp_copy error"); + return WOLFSSL_FATAL_ERROR; + } + + return WOLFSSL_SUCCESS; +} + +#ifndef NO_ASN +WOLFSSL_BIGNUM *wolfSSL_ASN1_INTEGER_to_BN(const WOLFSSL_ASN1_INTEGER *ai, + WOLFSSL_BIGNUM *bn) +{ + mp_int mpi; + word32 idx = 0; + int ret; + + WOLFSSL_ENTER("wolfSSL_ASN1_INTEGER_to_BN"); + + if (ai == NULL) { + return NULL; + } + + if ((ret = GetInt(&mpi, ai->data, &idx, ai->dataMax)) != 0) { + /* expecting ASN1 format for INTEGER */ + WOLFSSL_LEAVE("wolfSSL_ASN1_INTEGER_to_BN", ret); + return NULL; + } + + /* mp_clear needs called because mpi is copied and causes memory leak with + * --disable-fastmath */ + ret = SetIndividualExternal(&bn, &mpi); + mp_clear(&mpi); + + if (ret != WOLFSSL_SUCCESS) { + return NULL; + } + return bn; +} +#endif /* !NO_ASN */ + +#if !defined(NO_DSA) && !defined(NO_DH) +WOLFSSL_DH *wolfSSL_DSA_dup_DH(const WOLFSSL_DSA *dsa) +{ + WOLFSSL_DH* dh; + DhKey* key; + + WOLFSSL_ENTER("wolfSSL_DSA_dup_DH"); + + if (dsa == NULL) { + return NULL; + } + + dh = wolfSSL_DH_new(); + if (dh == NULL) { + return NULL; + } + key = (DhKey*)dh->internal; + + if (dsa->p != NULL && + SetIndividualInternal(((WOLFSSL_DSA*)dsa)->p, &key->p) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("rsa p key error"); + wolfSSL_DH_free(dh); + return NULL; + } + if (dsa->g != NULL && + SetIndividualInternal(((WOLFSSL_DSA*)dsa)->g, &key->g) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("rsa g key error"); + wolfSSL_DH_free(dh); + return NULL; + } + + if (SetIndividualExternal(&dh->p, &key->p) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("dsa p key error"); + wolfSSL_DH_free(dh); + return NULL; + } + if (SetIndividualExternal(&dh->g, &key->g) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("dsa g key error"); + wolfSSL_DH_free(dh); + return NULL; + } + + return dh; +} +#endif /* !defined(NO_DSA) && !defined(NO_DH) */ + +#endif /* OPENSSL_EXTRA */ +#endif /* !NO_RSA && !NO_DSA */ + +#ifdef OPENSSL_EXTRA + +#ifndef NO_DSA +/* wolfSSL -> OpenSSL */ +static int SetDsaExternal(WOLFSSL_DSA* dsa) +{ + DsaKey* key; + WOLFSSL_MSG("Entering SetDsaExternal"); + + if (dsa == NULL || dsa->internal == NULL) { + WOLFSSL_MSG("dsa key NULL error"); + return WOLFSSL_FATAL_ERROR; + } + + key = (DsaKey*)dsa->internal; + + if (SetIndividualExternal(&dsa->p, &key->p) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("dsa p key error"); + return WOLFSSL_FATAL_ERROR; + } + + if (SetIndividualExternal(&dsa->q, &key->q) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("dsa q key error"); + return WOLFSSL_FATAL_ERROR; + } + + if (SetIndividualExternal(&dsa->g, &key->g) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("dsa g key error"); + return WOLFSSL_FATAL_ERROR; + } + + if (SetIndividualExternal(&dsa->pub_key, &key->y) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("dsa y key error"); + return WOLFSSL_FATAL_ERROR; + } + + if (SetIndividualExternal(&dsa->priv_key, &key->x) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("dsa x key error"); + return WOLFSSL_FATAL_ERROR; + } + + dsa->exSet = 1; + + return WOLFSSL_SUCCESS; +} + +/* Openssl -> WolfSSL */ +static int SetDsaInternal(WOLFSSL_DSA* dsa) +{ + DsaKey* key; + WOLFSSL_MSG("Entering SetDsaInternal"); + + if (dsa == NULL || dsa->internal == NULL) { + WOLFSSL_MSG("dsa key NULL error"); + return WOLFSSL_FATAL_ERROR; + } + + key = (DsaKey*)dsa->internal; + + if (dsa->p != NULL && + SetIndividualInternal(dsa->p, &key->p) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("rsa p key error"); + return WOLFSSL_FATAL_ERROR; + } + + if (dsa->q != NULL && + SetIndividualInternal(dsa->q, &key->q) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("rsa q key error"); + return WOLFSSL_FATAL_ERROR; + } + + if (dsa->g != NULL && + SetIndividualInternal(dsa->g, &key->g) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("rsa g key error"); + return WOLFSSL_FATAL_ERROR; + } + + if (dsa->pub_key != NULL) { + if (SetIndividualInternal(dsa->pub_key, &key->y) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("rsa pub_key error"); + return WOLFSSL_FATAL_ERROR; + } + + /* public key */ + key->type = DSA_PUBLIC; + } + + if (dsa->priv_key != NULL) { + if (SetIndividualInternal(dsa->priv_key, &key->x) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("rsa priv_key error"); + return WOLFSSL_FATAL_ERROR; + } + + /* private key */ + key->type = DSA_PRIVATE; + } + + dsa->inSet = 1; + + return WOLFSSL_SUCCESS; +} +#endif /* NO_DSA */ +#endif /* OPENSSL_EXTRA */ + +#if !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA) && \ + !defined(NO_RSA) && (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) +/* WolfSSL -> OpenSSL */ +static int SetRsaExternal(WOLFSSL_RSA* rsa) +{ + RsaKey* key; + WOLFSSL_MSG("Entering SetRsaExternal"); + + if (rsa == NULL || rsa->internal == NULL) { + WOLFSSL_MSG("rsa key NULL error"); + return WOLFSSL_FATAL_ERROR; + } + + key = (RsaKey*)rsa->internal; + + if (SetIndividualExternal(&rsa->n, &key->n) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("rsa n key error"); + return WOLFSSL_FATAL_ERROR; + } + + if (SetIndividualExternal(&rsa->e, &key->e) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("rsa e key error"); + return WOLFSSL_FATAL_ERROR; + } + + if (key->type == RSA_PRIVATE) { + if (SetIndividualExternal(&rsa->d, &key->d) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("rsa d key error"); + return WOLFSSL_FATAL_ERROR; + } + + if (SetIndividualExternal(&rsa->p, &key->p) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("rsa p key error"); + return WOLFSSL_FATAL_ERROR; + } + + if (SetIndividualExternal(&rsa->q, &key->q) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("rsa q key error"); + return WOLFSSL_FATAL_ERROR; + } + + #ifndef RSA_LOW_MEM + if (SetIndividualExternal(&rsa->dmp1, &key->dP) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("rsa dP key error"); + return WOLFSSL_FATAL_ERROR; + } + + if (SetIndividualExternal(&rsa->dmq1, &key->dQ) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("rsa dQ key error"); + return WOLFSSL_FATAL_ERROR; + } + + if (SetIndividualExternal(&rsa->iqmp, &key->u) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("rsa u key error"); + return WOLFSSL_FATAL_ERROR; + } + #endif /* !RSA_LOW_MEM */ + } + rsa->exSet = 1; + + return WOLFSSL_SUCCESS; +} +#endif + +#ifdef OPENSSL_EXTRA +#if !defined(NO_RSA) +#if !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA) +/* Openssl -> WolfSSL */ +static int SetRsaInternal(WOLFSSL_RSA* rsa) +{ + RsaKey* key; + WOLFSSL_MSG("Entering SetRsaInternal"); + + if (rsa == NULL || rsa->internal == NULL) { + WOLFSSL_MSG("rsa key NULL error"); + return WOLFSSL_FATAL_ERROR; + } + + key = (RsaKey*)rsa->internal; + + if (SetIndividualInternal(rsa->n, &key->n) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("rsa n key error"); + return WOLFSSL_FATAL_ERROR; + } + + if (SetIndividualInternal(rsa->e, &key->e) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("rsa e key error"); + return WOLFSSL_FATAL_ERROR; + } + + /* public key */ + key->type = RSA_PUBLIC; + + if (rsa->d != NULL) { + if (SetIndividualInternal(rsa->d, &key->d) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("rsa d key error"); + return WOLFSSL_FATAL_ERROR; + } + + /* private key */ + key->type = RSA_PRIVATE; + } + + if (rsa->p != NULL && + SetIndividualInternal(rsa->p, &key->p) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("rsa p key error"); + return WOLFSSL_FATAL_ERROR; + } + + if (rsa->q != NULL && + SetIndividualInternal(rsa->q, &key->q) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("rsa q key error"); + return WOLFSSL_FATAL_ERROR; + } + +#ifndef RSA_LOW_MEM + if (rsa->dmp1 != NULL && + SetIndividualInternal(rsa->dmp1, &key->dP) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("rsa dP key error"); + return WOLFSSL_FATAL_ERROR; + } + + if (rsa->dmq1 != NULL && + SetIndividualInternal(rsa->dmq1, &key->dQ) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("rsa dQ key error"); + return WOLFSSL_FATAL_ERROR; + } + + if (rsa->iqmp != NULL && + SetIndividualInternal(rsa->iqmp, &key->u) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("rsa u key error"); + return WOLFSSL_FATAL_ERROR; + } +#endif /* !RSA_LOW_MEM */ + + rsa->inSet = 1; + + return WOLFSSL_SUCCESS; +} + + +/* SSL_SUCCESS on ok */ +#ifndef NO_WOLFSSL_STUB +int wolfSSL_RSA_blinding_on(WOLFSSL_RSA* rsa, WOLFSSL_BN_CTX* bn) +{ + (void)rsa; + (void)bn; + WOLFSSL_STUB("RSA_blinding_on"); + WOLFSSL_MSG("wolfSSL_RSA_blinding_on"); + + return WOLFSSL_SUCCESS; /* on by default */ +} +#endif + +/* return compliant with OpenSSL + * size of encrypted data if success , -1 if error + */ +int wolfSSL_RSA_public_encrypt(int len, const unsigned char* fr, + unsigned char* to, WOLFSSL_RSA* rsa, int padding) +{ + int initTmpRng = 0; + WC_RNG *rng = NULL; + int outLen; + int ret = 0; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG* tmpRNG = NULL; +#else + WC_RNG tmpRNG[1]; +#endif +#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA) + int mgf = WC_MGF1NONE; + enum wc_HashType hash = WC_HASH_TYPE_NONE; +#endif + + WOLFSSL_MSG("wolfSSL_RSA_public_encrypt"); + + /* Check and remap the padding to internal values, if needed. */ +#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA) + if (padding == RSA_PKCS1_PADDING) + padding = WC_RSA_PKCSV15_PAD; + else if (padding == RSA_PKCS1_OAEP_PADDING) { + padding = WC_RSA_OAEP_PAD; + hash = WC_HASH_TYPE_SHA; + mgf = WC_MGF1SHA1; + } +#else + if (padding == RSA_PKCS1_PADDING) + ; +#endif + else { + WOLFSSL_MSG("wolfSSL_RSA_public_encrypt unsupported padding"); + return 0; + } + + if (rsa->inSet == 0) + { + if (SetRsaInternal(rsa) != SSL_SUCCESS) { + WOLFSSL_MSG("SetRsaInternal failed"); + return 0; + } + } + + outLen = wolfSSL_RSA_size(rsa); + +#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && \ + !defined(HAVE_FAST_RSA) && defined(WC_RSA_BLINDING) + rng = ((RsaKey*)rsa->internal)->rng; +#endif + if (rng == NULL) { +#ifdef WOLFSSL_SMALL_STACK + tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (tmpRNG == NULL) + return 0; +#endif + + if (wc_InitRng(tmpRNG) == 0) { + rng = tmpRNG; + initTmpRng = 1; + } + else { + WOLFSSL_MSG("Bad RNG Init, trying global"); + if (initGlobalRNG == 0) + WOLFSSL_MSG("Global RNG no Init"); + else + rng = &globalRNG; + } + } + + if (outLen == 0) { + WOLFSSL_MSG("Bad RSA size"); + } + + if (rng) { +#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA) + ret = wc_RsaPublicEncrypt_ex(fr, len, to, outLen, + (RsaKey*)rsa->internal, rng, padding, + hash, mgf, NULL, 0); +#else + ret = wc_RsaPublicEncrypt(fr, len, to, outLen, + (RsaKey*)rsa->internal, rng); +#endif + if (ret <= 0) { + WOLFSSL_MSG("Bad Rsa Encrypt"); + } + if (len <= 0) { + WOLFSSL_MSG("Bad Rsa Encrypt"); + } + } + + if (initTmpRng) + wc_FreeRng(tmpRNG); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + if (ret >= 0) + WOLFSSL_MSG("wolfSSL_RSA_public_encrypt success"); + else { + WOLFSSL_MSG("wolfSSL_RSA_public_encrypt failed"); + ret = WOLFSSL_FATAL_ERROR; /* return -1 on error case */ + } + return ret; +} + +/* return compliant with OpenSSL + * size of plain recovered data if success , -1 if error + */ +int wolfSSL_RSA_private_decrypt(int len, const unsigned char* fr, + unsigned char* to, WOLFSSL_RSA* rsa, int padding) +{ + int outLen; + int ret = 0; + #if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA) + int mgf = WC_MGF1NONE; + enum wc_HashType hash = WC_HASH_TYPE_NONE; + #endif + + WOLFSSL_MSG("wolfSSL_RSA_private_decrypt"); + +#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA) + if (padding == RSA_PKCS1_PADDING) + padding = WC_RSA_PKCSV15_PAD; + else if (padding == RSA_PKCS1_OAEP_PADDING) { + padding = WC_RSA_OAEP_PAD; + hash = WC_HASH_TYPE_SHA; + mgf = WC_MGF1SHA1; + } +#else + if (padding == RSA_PKCS1_PADDING) + ; +#endif + else { + WOLFSSL_MSG("wolfSSL_RSA_private_decrypt unsupported padding"); + return 0; + } + + if (rsa->inSet == 0) + { + if (SetRsaInternal(rsa) != SSL_SUCCESS) { + WOLFSSL_MSG("SetRsaInternal failed"); + return 0; + } + } + + outLen = wolfSSL_RSA_size(rsa); + if (outLen == 0) { + WOLFSSL_MSG("Bad RSA size"); + } + + /* size of 'to' buffer must be size of RSA key */ +#if !defined(HAVE_FIPS) && !defined(HAVE_USER_RSA) && !defined(HAVE_FAST_RSA) + ret = wc_RsaPrivateDecrypt_ex(fr, len, to, outLen, + (RsaKey*)rsa->internal, padding, + hash, mgf, NULL, 0); +#else + ret = wc_RsaPrivateDecrypt(fr, len, to, outLen, + (RsaKey*)rsa->internal); +#endif + + if (len <= 0) { + WOLFSSL_MSG("Bad Rsa Decrypt"); + } + + if (ret > 0) + WOLFSSL_MSG("wolfSSL_RSA_private_decrypt success"); + else { + WOLFSSL_MSG("wolfSSL_RSA_private_decrypt failed"); + ret = WOLFSSL_FATAL_ERROR; + } + return ret; +} + + +/* RSA private encrypt calls wc_RsaSSL_Sign. Similar function set up as RSA + * public decrypt. + * + * len Length of input buffer + * in Input buffer to sign + * out Output buffer (expected to be greater than or equal to RSA key size) + * rsa Key to use for encryption + * padding Type of RSA padding to use. + */ +int wolfSSL_RSA_private_encrypt(int len, unsigned char* in, + unsigned char* out, WOLFSSL_RSA* rsa, int padding) +{ + int sz = 0; + WC_RNG* rng = NULL; + RsaKey* key; + + WOLFSSL_MSG("wolfSSL_RSA_private_encrypt"); + + if (len < 0 || rsa == NULL || rsa->internal == NULL || in == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return 0; + } + + if (padding != RSA_PKCS1_PADDING) { + WOLFSSL_MSG("wolfSSL_RSA_private_encrypt unsupported padding"); + return 0; + } + + if (rsa->inSet == 0) + { + WOLFSSL_MSG("Setting internal RSA structure"); + + if (SetRsaInternal(rsa) != SSL_SUCCESS) { + WOLFSSL_MSG("SetRsaInternal failed"); + return 0; + } + } + + key = (RsaKey*)rsa->internal; + #if defined(WC_RSA_BLINDING) && !defined(HAVE_USER_RSA) + rng = key->rng; + #else +#ifndef HAVE_FIPS + if (wc_InitRng_ex(rng, key->heap, INVALID_DEVID) != 0) { +#else + if (wc_InitRng(rng) != 0) { +#endif + WOLFSSL_MSG("Error with random number"); + return SSL_FATAL_ERROR; + } + #endif + + /* size of output buffer must be size of RSA key */ + sz = wc_RsaSSL_Sign(in, (word32)len, out, wolfSSL_RSA_size(rsa), key, rng); + #if !defined(WC_RSA_BLINDING) || defined(HAVE_USER_RSA) + if (wc_FreeRng(rng) != 0) { + WOLFSSL_MSG("Error freeing random number generator"); + return SSL_FATAL_ERROR; + } + #endif + if (sz <= 0) { + WOLFSSL_LEAVE("wolfSSL_RSA_private_encrypt", sz); + return 0; + } + + return sz; +} +#endif /* HAVE_USER_RSA */ + +/* return compliant with OpenSSL + * RSA modulus size in bytes, -1 if error + */ +int wolfSSL_RSA_size(const WOLFSSL_RSA* rsa) +{ + WOLFSSL_ENTER("wolfSSL_RSA_size"); + + if (rsa == NULL) + return WOLFSSL_FATAL_ERROR; + if (rsa->inSet == 0) + { + if (SetRsaInternal((WOLFSSL_RSA*)rsa) != SSL_SUCCESS) { + WOLFSSL_MSG("SetRsaInternal failed"); + return 0; + } + } + return wc_RsaEncryptSize((RsaKey*)rsa->internal); +} + + +/* Generates a RSA key of length len + * + * len length of RSA key i.e. 2048 + * e e to use when generating RSA key + * f callback function for generation details + * data user callback argument + * + * Note: Because of wc_MakeRsaKey an RSA key size generated can be slightly + * rounded down. For example generating a key of size 2999 with e = + * 65537 will make a key of size 374 instead of 375. + * Returns a new RSA key on success and NULL on failure + */ +WOLFSSL_RSA* wolfSSL_RSA_generate_key(int len, unsigned long e, + void(*f)(int, int, void*), void* data) +{ + WOLFSSL_RSA* rsa = NULL; + WOLFSSL_BIGNUM* bn = NULL; + + WOLFSSL_ENTER("wolfSSL_RSA_generate_key"); + + (void)f; + (void)data; + + if (len < 0) { + WOLFSSL_MSG("Bad argument: length was less than 0"); + return NULL; + } + + bn = wolfSSL_BN_new(); + if (bn == NULL) { + WOLFSSL_MSG("Error creating big number"); + return NULL; + } + + if (wolfSSL_BN_set_word(bn, (WOLFSSL_BN_ULONG)e) != SSL_SUCCESS) { + WOLFSSL_MSG("Error using e value"); + wolfSSL_BN_free(bn); + return NULL; + } + + rsa = wolfSSL_RSA_new(); + if (rsa == NULL) { + WOLFSSL_MSG("memory error"); + } + else { + if (wolfSSL_RSA_generate_key_ex(rsa, len, bn, NULL) != SSL_SUCCESS){ + wolfSSL_RSA_free(rsa); + rsa = NULL; + } + } + wolfSSL_BN_free(bn); + + return rsa; +} + + +/* return compliant with OpenSSL + * 1 if success, 0 if error + */ +int wolfSSL_RSA_generate_key_ex(WOLFSSL_RSA* rsa, int bits, WOLFSSL_BIGNUM* bn, + void* cb) +{ + int ret = WOLFSSL_FAILURE; + + (void)cb; + (void)bn; + (void)bits; + + WOLFSSL_ENTER("wolfSSL_RSA_generate_key_ex"); + + if (rsa == NULL || rsa->internal == NULL) { + /* bit size checked during make key call */ + WOLFSSL_MSG("bad arguments"); + return WOLFSSL_FAILURE; + } + +#ifdef WOLFSSL_KEY_GEN + { + #ifdef WOLFSSL_SMALL_STACK + WC_RNG* rng = NULL; + #else + WC_RNG rng[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + rng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); + if (rng == NULL) + return WOLFSSL_FAILURE; + #endif + + if (wc_InitRng(rng) < 0) + WOLFSSL_MSG("RNG init failed"); + else if (wc_MakeRsaKey((RsaKey*)rsa->internal, bits, + wolfSSL_BN_get_word(bn), rng) != MP_OKAY) + WOLFSSL_MSG("wc_MakeRsaKey failed"); + else if (SetRsaExternal(rsa) != WOLFSSL_SUCCESS) + WOLFSSL_MSG("SetRsaExternal failed"); + else { + rsa->inSet = 1; + ret = WOLFSSL_SUCCESS; + } + + wc_FreeRng(rng); + #ifdef WOLFSSL_SMALL_STACK + XFREE(rng, NULL, DYNAMIC_TYPE_RNG); + #endif + } +#else + WOLFSSL_MSG("No Key Gen built in"); +#endif + return ret; +} +#endif /* NO_RSA */ + +#ifndef NO_DSA +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_DSA_generate_key(WOLFSSL_DSA* dsa) +{ + int ret = WOLFSSL_FAILURE; + + WOLFSSL_ENTER("wolfSSL_DSA_generate_key"); + + if (dsa == NULL || dsa->internal == NULL) { + WOLFSSL_MSG("Bad arguments"); + return WOLFSSL_FAILURE; + } + + if (dsa->inSet == 0) { + WOLFSSL_MSG("No DSA internal set, do it"); + + if (SetDsaInternal(dsa) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetDsaInternal failed"); + return ret; + } + } + +#ifdef WOLFSSL_KEY_GEN + { + int initTmpRng = 0; + WC_RNG *rng = NULL; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG *tmpRNG = NULL; +#else + WC_RNG tmpRNG[1]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); + if (tmpRNG == NULL) + return WOLFSSL_FATAL_ERROR; +#endif + if (wc_InitRng(tmpRNG) == 0) { + rng = tmpRNG; + initTmpRng = 1; + } + else { + WOLFSSL_MSG("Bad RNG Init, trying global"); + if (initGlobalRNG == 0) + WOLFSSL_MSG("Global RNG no Init"); + else + rng = &globalRNG; + } + + if (rng) { + if (wc_MakeDsaKey(rng, (DsaKey*)dsa->internal) != MP_OKAY) + WOLFSSL_MSG("wc_MakeDsaKey failed"); + else if (SetDsaExternal(dsa) != WOLFSSL_SUCCESS) + WOLFSSL_MSG("SetDsaExternal failed"); + else + ret = WOLFSSL_SUCCESS; + } + + if (initTmpRng) + wc_FreeRng(tmpRNG); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); +#endif + } +#else /* WOLFSSL_KEY_GEN */ + WOLFSSL_MSG("No Key Gen built in"); +#endif + return ret; +} + + +/* Returns a pointer to a new WOLFSSL_DSA structure on success and NULL on fail + */ +WOLFSSL_DSA* wolfSSL_DSA_generate_parameters(int bits, unsigned char* seed, + int seedLen, int* counterRet, unsigned long* hRet, + WOLFSSL_BN_CB cb, void* CBArg) +{ + WOLFSSL_DSA* dsa; + + WOLFSSL_ENTER("wolfSSL_DSA_generate_parameters()"); + + (void)cb; + (void)CBArg; + dsa = wolfSSL_DSA_new(); + if (dsa == NULL) { + return NULL; + } + + if (wolfSSL_DSA_generate_parameters_ex(dsa, bits, seed, seedLen, + counterRet, hRet, NULL) != SSL_SUCCESS) { + wolfSSL_DSA_free(dsa); + return NULL; + } + + return dsa; +} + + +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_DSA_generate_parameters_ex(WOLFSSL_DSA* dsa, int bits, + unsigned char* seed, int seedLen, + int* counterRet, + unsigned long* hRet, void* cb) +{ + int ret = WOLFSSL_FAILURE; + + (void)bits; + (void)seed; + (void)seedLen; + (void)counterRet; + (void)hRet; + (void)cb; + + WOLFSSL_ENTER("wolfSSL_DSA_generate_parameters_ex"); + + if (dsa == NULL || dsa->internal == NULL) { + WOLFSSL_MSG("Bad arguments"); + return WOLFSSL_FAILURE; + } + +#ifdef WOLFSSL_KEY_GEN + { + int initTmpRng = 0; + WC_RNG *rng = NULL; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG *tmpRNG = NULL; +#else + WC_RNG tmpRNG[1]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); + if (tmpRNG == NULL) + return WOLFSSL_FATAL_ERROR; +#endif + if (wc_InitRng(tmpRNG) == 0) { + rng = tmpRNG; + initTmpRng = 1; + } + else { + WOLFSSL_MSG("Bad RNG Init, trying global"); + if (initGlobalRNG == 0) + WOLFSSL_MSG("Global RNG no Init"); + else + rng = &globalRNG; + } + + if (rng) { + if (wc_MakeDsaParameters(rng, bits, + (DsaKey*)dsa->internal) != MP_OKAY) + WOLFSSL_MSG("wc_MakeDsaParameters failed"); + else if (SetDsaExternal(dsa) != WOLFSSL_SUCCESS) + WOLFSSL_MSG("SetDsaExternal failed"); + else + ret = WOLFSSL_SUCCESS; + } + + if (initTmpRng) + wc_FreeRng(tmpRNG); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); +#endif + } +#else /* WOLFSSL_KEY_GEN */ + WOLFSSL_MSG("No Key Gen built in"); +#endif + + return ret; +} + +/* return WOLFSSL_SUCCESS on success, < 0 otherwise */ +int wolfSSL_DSA_do_sign(const unsigned char* d, unsigned char* sigRet, + WOLFSSL_DSA* dsa) +{ + int ret = WOLFSSL_FATAL_ERROR; + int initTmpRng = 0; + WC_RNG* rng = NULL; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG* tmpRNG = NULL; +#else + WC_RNG tmpRNG[1]; +#endif + + WOLFSSL_ENTER("wolfSSL_DSA_do_sign"); + + if (d == NULL || sigRet == NULL || dsa == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return ret; + } + + if (dsa->inSet == 0) + { + WOLFSSL_MSG("No DSA internal set, do it"); + + if (SetDsaInternal(dsa) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetDsaInternal failed"); + return ret; + } + } + +#ifdef WOLFSSL_SMALL_STACK + tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); + if (tmpRNG == NULL) + return WOLFSSL_FATAL_ERROR; +#endif + + if (wc_InitRng(tmpRNG) == 0) { + rng = tmpRNG; + initTmpRng = 1; + } + else { + WOLFSSL_MSG("Bad RNG Init, trying global"); + if (initGlobalRNG == 0) + WOLFSSL_MSG("Global RNG no Init"); + else + rng = &globalRNG; + } + + if (rng) { + if (DsaSign(d, sigRet, (DsaKey*)dsa->internal, rng) < 0) + WOLFSSL_MSG("DsaSign failed"); + else + ret = WOLFSSL_SUCCESS; + } + + if (initTmpRng) + wc_FreeRng(tmpRNG); +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); +#endif + + return ret; +} + + +int wolfSSL_DSA_do_verify(const unsigned char* d, unsigned char* sig, + WOLFSSL_DSA* dsa, int *dsacheck) +{ + int ret = WOLFSSL_FATAL_ERROR; + + WOLFSSL_ENTER("wolfSSL_DSA_do_verify"); + + if (d == NULL || sig == NULL || dsa == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return WOLFSSL_FATAL_ERROR; + } + if (dsa->inSet == 0) + { + WOLFSSL_MSG("No DSA internal set, do it"); + + if (SetDsaInternal(dsa) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetDsaInternal failed"); + return WOLFSSL_FATAL_ERROR; + } + } + + ret = DsaVerify(d, sig, (DsaKey*)dsa->internal, dsacheck); + if (ret != 0 || *dsacheck != 1) { + WOLFSSL_MSG("DsaVerify failed"); + return ret; + } + + return WOLFSSL_SUCCESS; +} +#endif /* NO_DSA */ + + +#if !defined(NO_RSA) && !defined(HAVE_USER_RSA) + +#ifdef DEBUG_SIGN +static void show(const char *title, const unsigned char *out, unsigned int outlen) +{ + const unsigned char *pt; + printf("%s[%d] = \n", title, (int)outlen); + outlen = outlen>100?100:outlen; + for (pt = out; pt < out + outlen; + printf("%c", ((*pt)&0x6f)>='A'?((*pt)&0x6f):'.'), pt++); + printf("\n"); +} +#else +#define show(a,b,c) +#endif + +/* return SSL_SUCCES on ok, 0 otherwise */ +int wolfSSL_RSA_sign(int type, const unsigned char* m, + unsigned int mLen, unsigned char* sigRet, + unsigned int* sigLen, WOLFSSL_RSA* rsa) +{ + return wolfSSL_RSA_sign_ex(type, m, mLen, sigRet, sigLen, rsa, 1); +} + +int wolfSSL_RSA_sign_ex(int type, const unsigned char* m, + unsigned int mLen, unsigned char* sigRet, + unsigned int* sigLen, WOLFSSL_RSA* rsa, int flag) +{ + word32 outLen; + word32 signSz; + int initTmpRng = 0; + WC_RNG* rng = NULL; + int ret = 0; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG* tmpRNG = NULL; + byte* encodedSig = NULL; +#else + WC_RNG tmpRNG[1]; + byte encodedSig[MAX_ENCODED_SIG_SZ]; +#endif + + WOLFSSL_ENTER("wolfSSL_RSA_sign"); + + if (m == NULL || sigRet == NULL || sigLen == NULL || rsa == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return 0; + } + show("Message to Sign", m, mLen); + + switch (type) { + #ifdef WOLFSSL_MD2 + case NID_md2: type = MD2h; break; + #endif + #ifndef NO_MD5 + case NID_md5: type = MD5h; break; + #endif + #ifndef NO_SHA + case NID_sha1: type = SHAh; break; + #endif + #ifndef NO_SHA256 + case NID_sha256: type = SHA256h; break; + #endif + #ifdef WOLFSSL_SHA384 + case NID_sha384: type = SHA384h; break; + #endif + #ifdef WOLFSSL_SHA512 + case NID_sha512: type = SHA512h; break; + #endif + default: + WOLFSSL_MSG("This NID (md type) not configured or not implemented"); + return 0; + } + + if (rsa->inSet == 0) + { + WOLFSSL_MSG("No RSA internal set, do it"); + + if (SetRsaInternal(rsa) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetRsaInternal failed"); + return 0; + } + } + + outLen = (word32)wolfSSL_BN_num_bytes(rsa->n); + +#ifdef WOLFSSL_SMALL_STACK + tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); + if (tmpRNG == NULL) + return 0; + + encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, NULL, + DYNAMIC_TYPE_SIGNATURE); + if (encodedSig == NULL) { + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); + return 0; + } +#endif + + if (outLen == 0) + WOLFSSL_MSG("Bad RSA size"); + else if (wc_InitRng(tmpRNG) == 0) { + rng = tmpRNG; + initTmpRng = 1; + } + else { + WOLFSSL_MSG("Bad RNG Init, trying global"); + + if (initGlobalRNG == 0) + WOLFSSL_MSG("Global RNG no Init"); + else + rng = &globalRNG; + } + + if (rng) { + + signSz = wc_EncodeSignature(encodedSig, m, mLen, type); + if (signSz == 0) { + WOLFSSL_MSG("Bad Encode Signature"); + } + else { + show("Encoded Message", encodedSig, signSz); + if (flag != 0) { + ret = wc_RsaSSL_Sign(encodedSig, signSz, sigRet, outLen, + (RsaKey*)rsa->internal, rng); + if (ret <= 0) { + WOLFSSL_MSG("Bad Rsa Sign"); + ret = 0; + } + else { + *sigLen = (unsigned int)ret; + ret = SSL_SUCCESS; + show("Signature", sigRet, *sigLen); + } + } else { + ret = SSL_SUCCESS; + XMEMCPY(sigRet, encodedSig, signSz); + *sigLen = signSz; + } + } + + } + + if (initTmpRng) + wc_FreeRng(tmpRNG); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); + XFREE(encodedSig, NULL, DYNAMIC_TYPE_SIGNATURE); +#endif + + if (ret == WOLFSSL_SUCCESS) + WOLFSSL_MSG("wolfSSL_RSA_sign success"); + else { + WOLFSSL_MSG("wolfSSL_RSA_sign failed"); + } + return ret; +} + + +/* returns WOLFSSL_SUCCESS on successful verify and WOLFSSL_FAILURE on fail */ +int wolfSSL_RSA_verify(int type, const unsigned char* m, + unsigned int mLen, const unsigned char* sig, + unsigned int sigLen, WOLFSSL_RSA* rsa) +{ + int ret; + unsigned char *sigRet ; + unsigned char *sigDec ; + unsigned int len; + + WOLFSSL_ENTER("wolfSSL_RSA_verify"); + if ((m == NULL) || (sig == NULL)) { + WOLFSSL_MSG("Bad function arguments"); + return WOLFSSL_FAILURE; + } + + sigRet = (unsigned char *)XMALLOC(sigLen, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (sigRet == NULL) { + WOLFSSL_MSG("Memory failure"); + return WOLFSSL_FAILURE; + } + sigDec = (unsigned char *)XMALLOC(sigLen, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (sigDec == NULL) { + WOLFSSL_MSG("Memory failure"); + XFREE(sigRet, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; + } + /* get non-encrypted signature to be compared with decrypted signature */ + ret = wolfSSL_RSA_sign_ex(type, m, mLen, sigRet, &len, rsa, 0); + if (ret <= 0) { + WOLFSSL_MSG("Message Digest Error"); + XFREE(sigRet, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(sigDec, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; + } + show("Encoded Message", sigRet, len); + /* decrypt signature */ + ret = wc_RsaSSL_Verify(sig, sigLen, (unsigned char *)sigDec, sigLen, + (RsaKey*)rsa->internal); + if (ret <= 0) { + WOLFSSL_MSG("RSA Decrypt error"); + XFREE(sigRet, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(sigDec, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; + } + show("Decrypted Signature", sigDec, ret); + + if ((int)len == ret && XMEMCMP(sigRet, sigDec, ret) == 0) { + WOLFSSL_MSG("wolfSSL_RSA_verify success"); + XFREE(sigRet, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(sigDec, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_SUCCESS; + } + else { + WOLFSSL_MSG("wolfSSL_RSA_verify failed"); + XFREE(sigRet, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(sigDec, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; + } +} + +int wolfSSL_RSA_public_decrypt(int flen, const unsigned char* from, + unsigned char* to, WOLFSSL_RSA* rsa, int padding) +{ + int tlen = 0; + + WOLFSSL_ENTER("wolfSSL_RSA_public_decrypt"); + + if (rsa == NULL || rsa->internal == NULL || from == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return 0; + } + + if (padding != RSA_PKCS1_PADDING) { + WOLFSSL_MSG("wolfSSL_RSA_public_decrypt unsupported padding"); + return 0; + } + + if (rsa->inSet == 0) + { + WOLFSSL_MSG("No RSA internal set, do it"); + + if (SetRsaInternal(rsa) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetRsaInternal failed"); + return 0; + } + } + + /* size of 'to' buffer must be size of RSA key */ + tlen = wc_RsaSSL_Verify(from, flen, to, wolfSSL_RSA_size(rsa), + (RsaKey*)rsa->internal); + if (tlen <= 0) + WOLFSSL_MSG("wolfSSL_RSA_public_decrypt failed"); + else { + WOLFSSL_MSG("wolfSSL_RSA_public_decrypt success"); + } + return tlen; +} + + +/* generate p-1 and q-1, WOLFSSL_SUCCESS on ok */ +int wolfSSL_RSA_GenAdd(WOLFSSL_RSA* rsa) +{ + int err; + mp_int tmp; + + WOLFSSL_MSG("wolfSSL_RsaGenAdd"); + + if (rsa == NULL || rsa->p == NULL || rsa->q == NULL || rsa->d == NULL || + rsa->dmp1 == NULL || rsa->dmq1 == NULL) { + WOLFSSL_MSG("rsa no init error"); + return WOLFSSL_FATAL_ERROR; + } + + if (mp_init(&tmp) != MP_OKAY) { + WOLFSSL_MSG("mp_init error"); + return WOLFSSL_FATAL_ERROR; + } + + err = mp_sub_d((mp_int*)rsa->p->internal, 1, &tmp); + if (err != MP_OKAY) { + WOLFSSL_MSG("mp_sub_d error"); + } + else + err = mp_mod((mp_int*)rsa->d->internal, &tmp, + (mp_int*)rsa->dmp1->internal); + + if (err != MP_OKAY) { + WOLFSSL_MSG("mp_mod error"); + } + else + err = mp_sub_d((mp_int*)rsa->q->internal, 1, &tmp); + if (err != MP_OKAY) { + WOLFSSL_MSG("mp_sub_d error"); + } + else + err = mp_mod((mp_int*)rsa->d->internal, &tmp, + (mp_int*)rsa->dmq1->internal); + + mp_clear(&tmp); + + if (err == MP_OKAY) + return WOLFSSL_SUCCESS; + else + return WOLFSSL_FATAL_ERROR; +} +#endif /* NO_RSA */ + +int wolfSSL_HMAC_CTX_Init(WOLFSSL_HMAC_CTX* ctx) +{ + WOLFSSL_MSG("wolfSSL_HMAC_CTX_Init"); + + if (ctx != NULL) { + /* wc_HmacSetKey sets up ctx->hmac */ + XMEMSET(ctx, 0, sizeof(WOLFSSL_HMAC_CTX)); + } + + return WOLFSSL_SUCCESS; +} + + +int wolfSSL_HMAC_Init_ex(WOLFSSL_HMAC_CTX* ctx, const void* key, + int keylen, const EVP_MD* type, WOLFSSL_ENGINE* e) +{ + WOLFSSL_ENTER("wolfSSL_HMAC_Init_ex"); + + /* WOLFSSL_ENGINE not used, call wolfSSL_HMAC_Init */ + (void)e; + return wolfSSL_HMAC_Init(ctx, key, keylen, type); +} + + +/* helper function for Deep copy of internal wolfSSL hmac structure + * returns WOLFSSL_SUCCESS on success */ +int wolfSSL_HmacCopy(Hmac* des, Hmac* src) +{ + void* heap = NULL; + +#ifndef HAVE_FIPS + heap = src->heap; +#endif + if (wc_HmacInit(des, heap, 0) != 0) { + return WOLFSSL_FAILURE; + } + + /* requires that hash structures have no dynamic parts to them */ + switch (src->macType) { + #ifndef NO_MD5 + case WC_MD5: + wc_Md5Copy(&src->hash.md5, &des->hash.md5); + break; + #endif /* !NO_MD5 */ + + #ifndef NO_SHA + case WC_SHA: + wc_ShaCopy(&src->hash.sha, &des->hash.sha); + break; + #endif /* !NO_SHA */ + + #ifdef WOLFSSL_SHA224 + case WC_SHA224: + wc_Sha224Copy(&src->hash.sha224, &des->hash.sha224); + break; + #endif /* WOLFSSL_SHA224 */ + + #ifndef NO_SHA256 + case WC_SHA256: + wc_Sha256Copy(&src->hash.sha256, &des->hash.sha256); + break; + #endif /* !NO_SHA256 */ + + #ifdef WOLFSSL_SHA384 + case WC_SHA384: + wc_Sha384Copy(&src->hash.sha384, &des->hash.sha384); + break; + #endif /* WOLFSSL_SHA384 */ + #ifdef WOLFSSL_SHA512 + case WC_SHA512: + wc_Sha512Copy(&src->hash.sha512, &des->hash.sha512); + break; + #endif /* WOLFSSL_SHA512 */ + + default: + return WOLFSSL_FAILURE; + } + + XMEMCPY((byte*)des->ipad, (byte*)src->ipad, WC_HMAC_BLOCK_SIZE); + XMEMCPY((byte*)des->opad, (byte*)src->opad, WC_HMAC_BLOCK_SIZE); + XMEMCPY((byte*)des->innerHash, (byte*)src->innerHash, WC_MAX_DIGEST_SIZE); +#ifndef HAVE_FIPS + des->heap = heap; +#endif + des->macType = src->macType; + des->innerHashKeyed = src->innerHashKeyed; + +#ifdef WOLFSSL_ASYNC_CRYPT + XMEMCPY(&des->asyncDev, &src->asyncDev, sizeof(WC_ASYNC_DEV)); + des->keyLen = src->keyLen; + #ifdef HAVE_CAVIUM + des->data = (byte*)XMALLOC(src->dataLen, des->heap, + DYNAMIC_TYPE_HMAC); + if (des->data == NULL) { + return BUFFER_E; + } + XMEMCPY(des->data, src->data, src->dataLen); + des->dataLen = src->dataLen; + #endif /* HAVE_CAVIUM */ +#endif /* WOLFSSL_ASYNC_CRYPT */ + return WOLFSSL_SUCCESS; +} + + +/* Deep copy of information from src to des structure + * + * des destination to copy information to + * src structure to get information from + * + * Returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on error + */ +int wolfSSL_HMAC_CTX_copy(WOLFSSL_HMAC_CTX* des, WOLFSSL_HMAC_CTX* src) +{ + WOLFSSL_ENTER("wolfSSL_HMAC_CTX_copy"); + + if (des == NULL || src == NULL) { + return WOLFSSL_FAILURE; + } + + des->type = src->type; + XMEMCPY((byte *)&des->save_ipad, (byte *)&src->hmac.ipad, + WC_HMAC_BLOCK_SIZE); + XMEMCPY((byte *)&des->save_opad, (byte *)&src->hmac.opad, + WC_HMAC_BLOCK_SIZE); + + return wolfSSL_HmacCopy(&des->hmac, &src->hmac); +} + + +#if defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) + +static int _HMAC_Init(Hmac* hmac, int type, void* heap) +{ + int ret = 0; + + switch (type) { + #ifndef NO_MD5 + case WC_MD5: + ret = wc_InitMd5(&hmac->hash.md5); + break; + #endif /* !NO_MD5 */ + + #ifndef NO_SHA + case WC_SHA: + ret = wc_InitSha(&hmac->hash.sha); + break; + #endif /* !NO_SHA */ + + #ifdef WOLFSSL_SHA224 + case WC_SHA224: + ret = wc_InitSha224(&hmac->hash.sha224); + break; + #endif /* WOLFSSL_SHA224 */ + + #ifndef NO_SHA256 + case WC_SHA256: + ret = wc_InitSha256(&hmac->hash.sha256); + break; + #endif /* !NO_SHA256 */ + + #ifdef WOLFSSL_SHA384 + case WC_SHA384: + ret = wc_InitSha384(&hmac->hash.sha384); + break; + #endif /* WOLFSSL_SHA384 */ + #ifdef WOLFSSL_SHA512 + case WC_SHA512: + ret = wc_InitSha512(&hmac->hash.sha512); + break; + #endif /* WOLFSSL_SHA512 */ + + #ifdef HAVE_BLAKE2 + case BLAKE2B_ID: + ret = wc_InitBlake2b(&hmac->hash.blake2b, BLAKE2B_256); + break; + #endif /* HAVE_BLAKE2 */ + + #ifdef WOLFSSL_SHA3 + case WC_SHA3_224: + ret = wc_InitSha3_224(&hmac->hash.sha3, heap, INVALID_DEVID); + break; + case WC_SHA3_256: + ret = wc_InitSha3_256(&hmac->hash.sha3, heap, INVALID_DEVID); + break; + case WC_SHA3_384: + ret = wc_InitSha3_384(&hmac->hash.sha3, heap, INVALID_DEVID); + break; + case WC_SHA3_512: + ret = wc_InitSha3_512(&hmac->hash.sha3, heap, INVALID_DEVID); + break; + #endif + + default: + ret = BAD_FUNC_ARG; + break; + } + + (void)heap; + + return ret; +} + +#else + #define _HMAC_Init _InitHmac +#endif + + +int wolfSSL_HMAC_Init(WOLFSSL_HMAC_CTX* ctx, const void* key, int keylen, + const EVP_MD* type) +{ + int hmac_error = 0; + void* heap = NULL; + + WOLFSSL_MSG("wolfSSL_HMAC_Init"); + + if (ctx == NULL) { + WOLFSSL_MSG("no ctx on init"); + return WOLFSSL_FAILURE; + } + +#ifndef HAVE_FIPS + heap = ctx->hmac.heap; +#endif + + if (type) { + WOLFSSL_MSG("init has type"); + +#ifndef NO_MD5 + if (XSTRNCMP(type, "MD5", 3) == 0) { + WOLFSSL_MSG("md5 hmac"); + ctx->type = WC_MD5; + } + else +#endif +#ifdef WOLFSSL_SHA224 + if (XSTRNCMP(type, "SHA224", 6) == 0) { + WOLFSSL_MSG("sha224 hmac"); + ctx->type = WC_SHA224; + } + else +#endif +#ifndef NO_SHA256 + if (XSTRNCMP(type, "SHA256", 6) == 0) { + WOLFSSL_MSG("sha256 hmac"); + ctx->type = WC_SHA256; + } + else +#endif +#ifdef WOLFSSL_SHA384 + if (XSTRNCMP(type, "SHA384", 6) == 0) { + WOLFSSL_MSG("sha384 hmac"); + ctx->type = WC_SHA384; + } + else +#endif +#ifdef WOLFSSL_SHA512 + if (XSTRNCMP(type, "SHA512", 6) == 0) { + WOLFSSL_MSG("sha512 hmac"); + ctx->type = WC_SHA512; + } + else +#endif + +#ifndef NO_SHA + /* has to be last since would pick or 256, 384, or 512 too */ + if (XSTRNCMP(type, "SHA", 3) == 0) { + WOLFSSL_MSG("sha hmac"); + ctx->type = WC_SHA; + } + else +#endif + { + WOLFSSL_MSG("bad init type"); + return WOLFSSL_FAILURE; + } + } + + if (key && keylen) { + WOLFSSL_MSG("keying hmac"); + + if (wc_HmacInit(&ctx->hmac, NULL, INVALID_DEVID) == 0) { + hmac_error = wc_HmacSetKey(&ctx->hmac, ctx->type, (const byte*)key, + (word32)keylen); + if (hmac_error < 0){ + wc_HmacFree(&ctx->hmac); + return WOLFSSL_FAILURE; + } + XMEMCPY((byte *)&ctx->save_ipad, (byte *)&ctx->hmac.ipad, + WC_HMAC_BLOCK_SIZE); + XMEMCPY((byte *)&ctx->save_opad, (byte *)&ctx->hmac.opad, + WC_HMAC_BLOCK_SIZE); + } + /* OpenSSL compat, no error */ + } else if(ctx->type >= 0) { /* MD5 == 0 */ + WOLFSSL_MSG("recover hmac"); + wc_HmacFree(&ctx->hmac); + if (wc_HmacInit(&ctx->hmac, NULL, INVALID_DEVID) == 0) { + ctx->hmac.macType = (byte)ctx->type; + ctx->hmac.innerHashKeyed = 0; + XMEMCPY((byte *)&ctx->hmac.ipad, (byte *)&ctx->save_ipad, + WC_HMAC_BLOCK_SIZE); + XMEMCPY((byte *)&ctx->hmac.opad, (byte *)&ctx->save_opad, + WC_HMAC_BLOCK_SIZE); + if ((hmac_error = _HMAC_Init(&ctx->hmac, ctx->hmac.macType, heap)) + !=0) { + return hmac_error; + } + } + } + + (void)hmac_error; + + return WOLFSSL_SUCCESS; +} + + +int wolfSSL_HMAC_Update(WOLFSSL_HMAC_CTX* ctx, const unsigned char* data, + int len) +{ + int hmac_error = 0; + + WOLFSSL_MSG("wolfSSL_HMAC_Update"); + + if (ctx == NULL) { + WOLFSSL_MSG("no ctx"); + return WOLFSSL_FAILURE; + } + + if (data) { + WOLFSSL_MSG("updating hmac"); + hmac_error = wc_HmacUpdate(&ctx->hmac, data, (word32)len); + if (hmac_error < 0){ + WOLFSSL_MSG("hmac update error"); + return WOLFSSL_FAILURE; + } + } + + return WOLFSSL_SUCCESS; +} + + +int wolfSSL_HMAC_Final(WOLFSSL_HMAC_CTX* ctx, unsigned char* hash, + unsigned int* len) +{ + int hmac_error; + + WOLFSSL_MSG("wolfSSL_HMAC_Final"); + + /* "len" parameter is optional. */ + if (ctx == NULL || hash == NULL) { + WOLFSSL_MSG("invalid parameter"); + return WOLFSSL_FAILURE; + } + + WOLFSSL_MSG("final hmac"); + hmac_error = wc_HmacFinal(&ctx->hmac, hash); + if (hmac_error < 0){ + WOLFSSL_MSG("final hmac error"); + return WOLFSSL_FAILURE; + } + + if (len) { + WOLFSSL_MSG("setting output len"); + switch (ctx->type) { + #ifndef NO_MD5 + case WC_MD5: + *len = WC_MD5_DIGEST_SIZE; + break; + #endif + + #ifndef NO_SHA + case WC_SHA: + *len = WC_SHA_DIGEST_SIZE; + break; + #endif + + #ifdef WOLFSSL_SHA224 + case WC_SHA224: + *len = WC_SHA224_DIGEST_SIZE; + break; + #endif + + #ifndef NO_SHA256 + case WC_SHA256: + *len = WC_SHA256_DIGEST_SIZE; + break; + #endif + + #ifdef WOLFSSL_SHA384 + case WC_SHA384: + *len = WC_SHA384_DIGEST_SIZE; + break; + #endif + + #ifdef WOLFSSL_SHA512 + case WC_SHA512: + *len = WC_SHA512_DIGEST_SIZE; + break; + #endif + + default: + WOLFSSL_MSG("bad hmac type"); + return WOLFSSL_FAILURE; + } + } + + return WOLFSSL_SUCCESS; +} + + +int wolfSSL_HMAC_cleanup(WOLFSSL_HMAC_CTX* ctx) +{ + WOLFSSL_MSG("wolfSSL_HMAC_cleanup"); + + if (ctx) + wc_HmacFree(&ctx->hmac); + + return SSL_SUCCESS; +} + + +const WOLFSSL_EVP_MD* wolfSSL_EVP_get_digestbynid(int id) +{ + WOLFSSL_MSG("wolfSSL_get_digestbynid"); + + switch(id) { +#ifndef NO_MD5 + case NID_md5: + return wolfSSL_EVP_md5(); +#endif +#ifndef NO_SHA + case NID_sha1: + return wolfSSL_EVP_sha1(); +#endif + default: + WOLFSSL_MSG("Bad digest id value"); + } + + return NULL; +} + + +#ifndef NO_RSA +WOLFSSL_RSA* wolfSSL_EVP_PKEY_get1_RSA(WOLFSSL_EVP_PKEY* key) +{ + WOLFSSL_RSA* local; + + WOLFSSL_MSG("wolfSSL_EVP_PKEY_get1_RSA"); + + if (key == NULL) { + return NULL; + } + + local = wolfSSL_RSA_new(); + if (local == NULL) { + WOLFSSL_MSG("Error creating a new WOLFSSL_RSA structure"); + return NULL; + } + + if (key->type == EVP_PKEY_RSA) { + if (wolfSSL_RSA_LoadDer(local, (const unsigned char*)key->pkey.ptr, + key->pkey_sz) != SSL_SUCCESS) { + /* now try public key */ + if (wolfSSL_RSA_LoadDer_ex(local, + (const unsigned char*)key->pkey.ptr, key->pkey_sz, + WOLFSSL_RSA_LOAD_PUBLIC) != SSL_SUCCESS) { + wolfSSL_RSA_free(local); + local = NULL; + } + } + } + else { + WOLFSSL_MSG("WOLFSSL_EVP_PKEY does not hold an RSA key"); + wolfSSL_RSA_free(local); + local = NULL; + } + return local; +} + + +/* with set1 functions the pkey struct does not own the RSA structure + * + * returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure + */ +int wolfSSL_EVP_PKEY_set1_RSA(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_RSA *key) +{ + if((pkey == NULL) || (key ==NULL))return WOLFSSL_FAILURE; + WOLFSSL_ENTER("wolfSSL_EVP_PKEY_set1_RSA"); + if (pkey->rsa != NULL && pkey->ownRsa == 1) { + wolfSSL_RSA_free(pkey->rsa); + } + pkey->rsa = key; + pkey->ownRsa = 0; /* pkey does not own RSA */ + pkey->type = EVP_PKEY_RSA; +#ifdef WC_RSA_BLINDING + if (key->ownRng == 0) { + if (wc_RsaSetRNG((RsaKey*)(pkey->rsa->internal), &(pkey->rng)) != 0) { + WOLFSSL_MSG("Error setting RSA rng"); + return SSL_FAILURE; + } + } +#endif + return WOLFSSL_SUCCESS; +} +#endif /* NO_RSA */ + +#ifndef NO_WOLFSSL_STUB +WOLFSSL_DSA* wolfSSL_EVP_PKEY_get1_DSA(WOLFSSL_EVP_PKEY* key) +{ + (void)key; + WOLFSSL_MSG("wolfSSL_EVP_PKEY_get1_DSA not implemented"); + WOLFSSL_STUB("EVP_PKEY_get1_DSA"); + return NULL; +} +#endif + +#ifndef NO_WOLFSSL_STUB +WOLFSSL_EC_KEY* wolfSSL_EVP_PKEY_get1_EC_KEY(WOLFSSL_EVP_PKEY* key) +{ + (void)key; + WOLFSSL_STUB("EVP_PKEY_get1_EC_KEY"); + WOLFSSL_MSG("wolfSSL_EVP_PKEY_get1_EC_KEY not implemented"); + + return NULL; +} +#endif + +void* wolfSSL_EVP_X_STATE(const WOLFSSL_EVP_CIPHER_CTX* ctx) +{ + WOLFSSL_MSG("wolfSSL_EVP_X_STATE"); + + if (ctx) { + switch (ctx->cipherType) { + case ARC4_TYPE: + WOLFSSL_MSG("returning arc4 state"); + return (void*)&ctx->cipher.arc4.x; + + default: + WOLFSSL_MSG("bad x state type"); + return 0; + } + } + + return NULL; +} + + +int wolfSSL_EVP_X_STATE_LEN(const WOLFSSL_EVP_CIPHER_CTX* ctx) +{ + WOLFSSL_MSG("wolfSSL_EVP_X_STATE_LEN"); + + if (ctx) { + switch (ctx->cipherType) { + case ARC4_TYPE: + WOLFSSL_MSG("returning arc4 state size"); + return sizeof(Arc4); + + default: + WOLFSSL_MSG("bad x state type"); + return 0; + } + } + + return 0; +} + + +#ifndef NO_DES3 + +void wolfSSL_3des_iv(WOLFSSL_EVP_CIPHER_CTX* ctx, int doset, + unsigned char* iv, int len) +{ + (void)len; + + WOLFSSL_MSG("wolfSSL_3des_iv"); + + if (ctx == NULL || iv == NULL) { + WOLFSSL_MSG("Bad function argument"); + return; + } + + if (doset) + wc_Des3_SetIV(&ctx->cipher.des3, iv); /* OpenSSL compat, no ret */ + else + XMEMCPY(iv, &ctx->cipher.des3.reg, DES_BLOCK_SIZE); +} + +#endif /* NO_DES3 */ + + +#ifndef NO_AES + +void wolfSSL_aes_ctr_iv(WOLFSSL_EVP_CIPHER_CTX* ctx, int doset, + unsigned char* iv, int len) +{ + (void)len; + + WOLFSSL_MSG("wolfSSL_aes_ctr_iv"); + + if (ctx == NULL || iv == NULL) { + WOLFSSL_MSG("Bad function argument"); + return; + } + + if (doset) + (void)wc_AesSetIV(&ctx->cipher.aes, iv); /* OpenSSL compat, no ret */ + else + XMEMCPY(iv, &ctx->cipher.aes.reg, AES_BLOCK_SIZE); +} + +#endif /* NO_AES */ + +#ifndef NO_WOLFSSL_STUB +const WOLFSSL_EVP_MD* wolfSSL_EVP_ripemd160(void) +{ + WOLFSSL_MSG("wolfSSL_ripemd160"); + WOLFSSL_STUB("EVP_ripemd160"); + return NULL; +} +#endif + + +int wolfSSL_EVP_MD_block_size(const WOLFSSL_EVP_MD* type) +{ + WOLFSSL_MSG("wolfSSL_EVP_MD_block_size"); + + if (type == NULL) { + WOLFSSL_MSG("No md type arg"); + return BAD_FUNC_ARG; + } + + if (XSTRNCMP(type, "SHA256", 6) == 0) { + return WC_SHA256_BLOCK_SIZE; + } +#ifndef NO_MD5 + else if (XSTRNCMP(type, "MD5", 3) == 0) { + return WC_MD5_BLOCK_SIZE; + } +#endif +#ifdef WOLFSSL_SHA224 + else if (XSTRNCMP(type, "SHA224", 6) == 0) { + return WC_SHA224_BLOCK_SIZE; + } +#endif +#ifdef WOLFSSL_SHA384 + else if (XSTRNCMP(type, "SHA384", 6) == 0) { + return WC_SHA384_BLOCK_SIZE; + } +#endif +#ifdef WOLFSSL_SHA512 + else if (XSTRNCMP(type, "SHA512", 6) == 0) { + return WC_SHA512_BLOCK_SIZE; + } +#endif +#ifndef NO_SHA + /* has to be last since would pick or 256, 384, or 512 too */ + else if (XSTRNCMP(type, "SHA", 3) == 0) { + return WC_SHA_BLOCK_SIZE; + } +#endif + + return BAD_FUNC_ARG; +} + +int wolfSSL_EVP_MD_size(const WOLFSSL_EVP_MD* type) +{ + WOLFSSL_MSG("wolfSSL_EVP_MD_size"); + + if (type == NULL) { + WOLFSSL_MSG("No md type arg"); + return BAD_FUNC_ARG; + } + + if (XSTRNCMP(type, "SHA256", 6) == 0) { + return WC_SHA256_DIGEST_SIZE; + } +#ifndef NO_MD5 + else if (XSTRNCMP(type, "MD5", 3) == 0) { + return WC_MD5_DIGEST_SIZE; + } +#endif +#ifdef WOLFSSL_SHA224 + else if (XSTRNCMP(type, "SHA224", 6) == 0) { + return WC_SHA224_DIGEST_SIZE; + } +#endif +#ifdef WOLFSSL_SHA384 + else if (XSTRNCMP(type, "SHA384", 6) == 0) { + return WC_SHA384_DIGEST_SIZE; + } +#endif +#ifdef WOLFSSL_SHA512 + else if (XSTRNCMP(type, "SHA512", 6) == 0) { + return WC_SHA512_DIGEST_SIZE; + } +#endif +#ifndef NO_SHA + /* has to be last since would pick or 256, 384, or 512 too */ + else if (XSTRNCMP(type, "SHA", 3) == 0) { + return WC_SHA_DIGEST_SIZE; + } +#endif + + return BAD_FUNC_ARG; +} + + +int wolfSSL_EVP_CIPHER_CTX_iv_length(const WOLFSSL_EVP_CIPHER_CTX* ctx) +{ + WOLFSSL_MSG("wolfSSL_EVP_CIPHER_CTX_iv_length"); + + switch (ctx->cipherType) { + +#ifdef HAVE_AES_CBC + case AES_128_CBC_TYPE : + case AES_192_CBC_TYPE : + case AES_256_CBC_TYPE : + WOLFSSL_MSG("AES CBC"); + return AES_BLOCK_SIZE; +#endif +#ifdef WOLFSSL_AES_COUNTER + case AES_128_CTR_TYPE : + case AES_192_CTR_TYPE : + case AES_256_CTR_TYPE : + WOLFSSL_MSG("AES CTR"); + return AES_BLOCK_SIZE; +#endif +#ifndef NO_DES3 + case DES_CBC_TYPE : + WOLFSSL_MSG("DES CBC"); + return DES_BLOCK_SIZE; + + case DES_EDE3_CBC_TYPE : + WOLFSSL_MSG("DES EDE3 CBC"); + return DES_BLOCK_SIZE; +#endif +#ifdef HAVE_IDEA + case IDEA_CBC_TYPE : + WOLFSSL_MSG("IDEA CBC"); + return IDEA_BLOCK_SIZE; +#endif +#ifndef NO_RC4 + case ARC4_TYPE : + WOLFSSL_MSG("ARC4"); + return 0; +#endif + + case NULL_CIPHER_TYPE : + WOLFSSL_MSG("NULL"); + return 0; + + default: { + WOLFSSL_MSG("bad type"); + } + } + return 0; +} + +int wolfSSL_EVP_CIPHER_iv_length(const WOLFSSL_EVP_CIPHER* cipher) +{ + const char *name = (const char *)cipher; + WOLFSSL_MSG("wolfSSL_EVP_CIPHER_iv_length"); + +#ifndef NO_AES +#ifdef HAVE_AES_CBC + #ifdef WOLFSSL_AES_128 + if (XSTRNCMP(name, EVP_AES_128_CBC, XSTRLEN(EVP_AES_128_CBC)) == 0) + return AES_BLOCK_SIZE; + #endif + #ifdef WOLFSSL_AES_192 + if (XSTRNCMP(name, EVP_AES_192_CBC, XSTRLEN(EVP_AES_192_CBC)) == 0) + return AES_BLOCK_SIZE; + #endif + #ifdef WOLFSSL_AES_256 + if (XSTRNCMP(name, EVP_AES_256_CBC, XSTRLEN(EVP_AES_256_CBC)) == 0) + return AES_BLOCK_SIZE; + #endif +#endif /* HAVE_AES_CBC */ +#ifdef WOLFSSL_AES_COUNTER + #ifdef WOLFSSL_AES_128 + if (XSTRNCMP(name, EVP_AES_128_CTR, XSTRLEN(EVP_AES_128_CTR)) == 0) + return AES_BLOCK_SIZE; + #endif + #ifdef WOLFSSL_AES_192 + if (XSTRNCMP(name, EVP_AES_192_CTR, XSTRLEN(EVP_AES_192_CTR)) == 0) + return AES_BLOCK_SIZE; + #endif + #ifdef WOLFSSL_AES_256 + if (XSTRNCMP(name, EVP_AES_256_CTR, XSTRLEN(EVP_AES_256_CTR)) == 0) + return AES_BLOCK_SIZE; + #endif +#endif +#endif + +#ifndef NO_DES3 + if ((XSTRNCMP(name, EVP_DES_CBC, XSTRLEN(EVP_DES_CBC)) == 0) || + (XSTRNCMP(name, EVP_DES_EDE3_CBC, XSTRLEN(EVP_DES_EDE3_CBC)) == 0)) { + return DES_BLOCK_SIZE; + } +#endif + +#ifdef HAVE_IDEA + if (XSTRNCMP(name, EVP_IDEA_CBC, XSTRLEN(EVP_IDEA_CBC)) == 0) + return IDEA_BLOCK_SIZE; +#endif + + (void)name; + + return 0; +} + +/* Free the dynamically allocated data. + * + * p Pointer to dynamically allocated memory. + */ +void wolfSSL_OPENSSL_free(void* p) +{ + WOLFSSL_MSG("wolfSSL_OPENSSL_free"); + + XFREE(p, NULL, DYNAMIC_TYPE_OPENSSL); +} + +void *wolfSSL_OPENSSL_malloc(size_t a) +{ + return XMALLOC(a, NULL, DYNAMIC_TYPE_OPENSSL); +} + +#if defined(WOLFSSL_KEY_GEN) && defined(WOLFSSL_PEM_TO_DER) + +static int EncryptDerKey(byte *der, int *derSz, const EVP_CIPHER* cipher, + unsigned char* passwd, int passwdSz, byte **cipherInfo) +{ + int ret, paddingSz; + word32 idx, cipherInfoSz; +#ifdef WOLFSSL_SMALL_STACK + EncryptedInfo* info = NULL; +#else + EncryptedInfo info[1]; +#endif + + WOLFSSL_ENTER("EncryptDerKey"); + + if (der == NULL || derSz == NULL || cipher == NULL || + passwd == NULL || cipherInfo == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_SMALL_STACK + info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL, + DYNAMIC_TYPE_ENCRYPTEDINFO); + if (info == NULL) { + WOLFSSL_MSG("malloc failed"); + return WOLFSSL_FAILURE; + } +#endif + + XMEMSET(info, 0, sizeof(EncryptedInfo)); + + /* set the cipher name on info */ + XSTRNCPY(info->name, cipher, NAME_SZ-1); + info->name[NAME_SZ-1] = '\0'; /* null term */ + + ret = wc_EncryptedInfoGet(info, info->name); + if (ret != 0) { + WOLFSSL_MSG("unsupported cipher"); + #ifdef WOLFSSL_SMALL_STACK + XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO); + #endif + return WOLFSSL_FAILURE; + } + + /* Generate a random salt */ + if (wolfSSL_RAND_bytes(info->iv, info->ivSz) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("generate iv failed"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO); +#endif + return WOLFSSL_FAILURE; + } + + /* add the padding before encryption */ + paddingSz = ((*derSz)/info->ivSz + 1) * info->ivSz - (*derSz); + if (paddingSz == 0) + paddingSz = info->ivSz; + XMEMSET(der+(*derSz), (byte)paddingSz, paddingSz); + (*derSz) += paddingSz; + + /* encrypt buffer */ + if (wc_BufferKeyEncrypt(info, der, *derSz, passwd, passwdSz, WC_MD5) != 0) { + WOLFSSL_MSG("encrypt key failed"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO); +#endif + return WOLFSSL_FAILURE; + } + + /* create cipher info : 'cipher_name,Salt(hex)' */ + cipherInfoSz = (word32)(2*info->ivSz + XSTRLEN(info->name) + 2); + *cipherInfo = (byte*)XMALLOC(cipherInfoSz, NULL, + DYNAMIC_TYPE_STRING); + if (*cipherInfo == NULL) { + WOLFSSL_MSG("malloc failed"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO); +#endif + return WOLFSSL_FAILURE; + } + XSTRNCPY((char*)*cipherInfo, info->name, cipherInfoSz); + XSTRNCAT((char*)*cipherInfo, ",", 2); + + idx = (word32)XSTRLEN((char*)*cipherInfo); + cipherInfoSz -= idx; + ret = Base16_Encode(info->iv, info->ivSz, *cipherInfo+idx, &cipherInfoSz); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO); +#endif + if (ret != 0) { + WOLFSSL_MSG("Base16_Encode failed"); + XFREE(*cipherInfo, NULL, DYNAMIC_TYPE_STRING); + return WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; +} +#endif /* WOLFSSL_KEY_GEN || WOLFSSL_PEM_TO_DER */ + +#if defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN) + +#ifndef NO_RSA +/* Takes a WOLFSSL_RSA key and writes it out to a WOLFSSL_BIO + * + * bio the WOLFSSL_BIO to write to + * key the WOLFSSL_RSA key to write out + * cipher cipher used + * passwd password string if used + * len length of password string + * cb password callback to use + * arg null terminated string for passphrase + */ +int wolfSSL_PEM_write_bio_RSAPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_RSA* key, + const WOLFSSL_EVP_CIPHER* cipher, + unsigned char* passwd, int len, + pem_password_cb* cb, void* arg) +{ + int ret; + WOLFSSL_EVP_PKEY* pkey; + + WOLFSSL_ENTER("wolfSSL_PEM_write_bio_RSAPrivateKey"); + + + pkey = wolfSSL_PKEY_new_ex(bio->heap); + if (pkey == NULL) { + WOLFSSL_MSG("wolfSSL_PKEY_new_ex failed"); + return SSL_FAILURE; + } + + pkey->type = EVP_PKEY_RSA; + pkey->rsa = key; + pkey->ownRsa = 0; +#ifdef WOLFSSL_KEY_GEN + /* similar to how wolfSSL_PEM_write_mem_RSAPrivateKey finds DER of key */ + { + int derMax; + int derSz; + byte* derBuf; + + /* 5 > size of n, d, p, q, d%(p-1), d(q-1), 1/q%p, e + ASN.1 additional + * informations + */ + derMax = 5 * wolfSSL_RSA_size(key) + AES_BLOCK_SIZE; + + derBuf = (byte*)XMALLOC(derMax, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (derBuf == NULL) { + WOLFSSL_MSG("malloc failed"); + wolfSSL_EVP_PKEY_free(pkey); + return SSL_FAILURE; + } + + /* Key to DER */ + derSz = wc_RsaKeyToDer((RsaKey*)key->internal, derBuf, derMax); + if (derSz < 0) { + WOLFSSL_MSG("wc_RsaKeyToDer failed"); + XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + wolfSSL_EVP_PKEY_free(pkey); + return SSL_FAILURE; + } + + pkey->pkey.ptr = (char*)XMALLOC(derSz, bio->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (pkey->pkey.ptr == NULL) { + WOLFSSL_MSG("key malloc failed"); + XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + wolfSSL_EVP_PKEY_free(pkey); + return SSL_FAILURE; + } + pkey->pkey_sz = derSz; + XMEMCPY(pkey->pkey.ptr, derBuf, derSz); + XFREE(derBuf, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + + ret = wolfSSL_PEM_write_bio_PrivateKey(bio, pkey, cipher, passwd, len, + cb, arg); + + wolfSSL_EVP_PKEY_free(pkey); + + return ret; +} + +#endif /* NO_RSA */ + + +int wolfSSL_PEM_write_bio_PrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EVP_PKEY* key, + const WOLFSSL_EVP_CIPHER* cipher, + unsigned char* passwd, int len, + pem_password_cb* cb, void* arg) +{ + byte* keyDer; + int pemSz; + int type; + int ret; + byte* tmp; + + (void)cipher; + (void)passwd; + (void)len; + (void)cb; + (void)arg; + + WOLFSSL_ENTER("wolfSSL_PEM_write_bio_PrivateKey"); + + if (bio == NULL || key == NULL) { + return WOLFSSL_FAILURE; + } + + keyDer = (byte*)key->pkey.ptr; + + switch (key->type) { +#ifndef NO_RSA + case EVP_PKEY_RSA: + type = PRIVATEKEY_TYPE; + break; +#endif + +#ifndef NO_DSA + case EVP_PKEY_DSA: + type = DSA_PRIVATEKEY_TYPE; + break; +#endif + + case EVP_PKEY_EC: + type = ECC_PRIVATEKEY_TYPE; + break; + + default: + WOLFSSL_MSG("Unknown Key type!"); + type = PRIVATEKEY_TYPE; + } + + pemSz = wc_DerToPem(keyDer, key->pkey_sz, NULL, 0, type); + if (pemSz < 0) { + WOLFSSL_LEAVE("wolfSSL_PEM_write_bio_PrivateKey", pemSz); + return WOLFSSL_FAILURE; + } + tmp = (byte*)XMALLOC(pemSz, bio->heap, DYNAMIC_TYPE_OPENSSL); + if (tmp == NULL) { + return MEMORY_E; + } + + ret = wc_DerToPemEx(keyDer, key->pkey_sz, tmp, pemSz, + NULL, type); + if (ret < 0) { + WOLFSSL_LEAVE("wolfSSL_PEM_write_bio_PrivateKey", ret); + XFREE(tmp, bio->heap, DYNAMIC_TYPE_OPENSSL); + return SSL_FAILURE; + } + + ret = wolfSSL_BIO_write(bio, tmp, pemSz); + XFREE(tmp, bio->heap, DYNAMIC_TYPE_OPENSSL); + if (ret != pemSz) { + WOLFSSL_MSG("Unable to write full PEM to BIO"); + return SSL_FAILURE; + } + + return SSL_SUCCESS; +} +#endif /* defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN) */ + +#if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) && !defined(HAVE_USER_RSA) && \ + (defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM)) + +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_PEM_write_mem_RSAPrivateKey(RSA* rsa, const EVP_CIPHER* cipher, + unsigned char* passwd, int passwdSz, + unsigned char **pem, int *plen) +{ + byte *derBuf, *tmp, *cipherInfo = NULL; + int der_max_len = 0, derSz = 0; + const int type = PRIVATEKEY_TYPE; + const char* header = NULL; + const char* footer = NULL; + + WOLFSSL_ENTER("wolfSSL_PEM_write_mem_RSAPrivateKey"); + + if (pem == NULL || plen == NULL || rsa == NULL || rsa->internal == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return WOLFSSL_FAILURE; + } + + if (wc_PemGetHeaderFooter(type, &header, &footer) != 0) + return WOLFSSL_FAILURE; + + if (rsa->inSet == 0) { + WOLFSSL_MSG("No RSA internal set, do it"); + + if (SetRsaInternal(rsa) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetRsaInternal failed"); + return WOLFSSL_FAILURE; + } + } + + /* 5 > size of n, d, p, q, d%(p-1), d(q-1), 1/q%p, e + ASN.1 additional + * informations + */ + der_max_len = 5 * wolfSSL_RSA_size(rsa) + AES_BLOCK_SIZE; + + derBuf = (byte*)XMALLOC(der_max_len, NULL, DYNAMIC_TYPE_DER); + if (derBuf == NULL) { + WOLFSSL_MSG("malloc failed"); + return WOLFSSL_FAILURE; + } + + /* Key to DER */ + derSz = wc_RsaKeyToDer((RsaKey*)rsa->internal, derBuf, der_max_len); + if (derSz < 0) { + WOLFSSL_MSG("wc_RsaKeyToDer failed"); + XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); + return WOLFSSL_FAILURE; + } + + /* encrypt DER buffer if required */ + if (passwd != NULL && passwdSz > 0 && cipher != NULL) { + int ret; + + ret = EncryptDerKey(derBuf, &derSz, cipher, + passwd, passwdSz, &cipherInfo); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("EncryptDerKey failed"); + XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); + return ret; + } + + /* tmp buffer with a max size */ + *plen = (derSz * 2) + (int)XSTRLEN(header) + 1 + + (int)XSTRLEN(footer) + 1 + HEADER_ENCRYPTED_KEY_SIZE; + } + else { + /* tmp buffer with a max size */ + *plen = (derSz * 2) + (int)XSTRLEN(header) + 1 + + (int)XSTRLEN(footer) + 1; + } + + tmp = (byte*)XMALLOC(*plen, NULL, DYNAMIC_TYPE_PEM); + if (tmp == NULL) { + WOLFSSL_MSG("malloc failed"); + XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); + if (cipherInfo != NULL) + XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING); + return WOLFSSL_FAILURE; + } + + /* DER to PEM */ + *plen = wc_DerToPemEx(derBuf, derSz, tmp, *plen, cipherInfo, type); + if (*plen <= 0) { + WOLFSSL_MSG("wc_DerToPemEx failed"); + XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); + XFREE(tmp, NULL, DYNAMIC_TYPE_PEM); + if (cipherInfo != NULL) + XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING); + return WOLFSSL_FAILURE; + } + XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); + if (cipherInfo != NULL) + XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING); + + *pem = (byte*)XMALLOC((*plen)+1, NULL, DYNAMIC_TYPE_KEY); + if (*pem == NULL) { + WOLFSSL_MSG("malloc failed"); + XFREE(tmp, NULL, DYNAMIC_TYPE_PEM); + return WOLFSSL_FAILURE; + } + XMEMSET(*pem, 0, (*plen)+1); + + if (XMEMCPY(*pem, tmp, *plen) == NULL) { + WOLFSSL_MSG("XMEMCPY failed"); + XFREE(pem, NULL, DYNAMIC_TYPE_KEY); + XFREE(tmp, NULL, DYNAMIC_TYPE_PEM); + return WOLFSSL_FAILURE; + } + XFREE(tmp, NULL, DYNAMIC_TYPE_PEM); + + return WOLFSSL_SUCCESS; +} + + +#ifndef NO_FILESYSTEM +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_PEM_write_RSAPrivateKey(XFILE fp, WOLFSSL_RSA *rsa, + const EVP_CIPHER *enc, + unsigned char *kstr, int klen, + pem_password_cb *cb, void *u) +{ + byte *pem; + int plen, ret; + + (void)cb; + (void)u; + + WOLFSSL_MSG("wolfSSL_PEM_write_RSAPrivateKey"); + + if (fp == XBADFILE || rsa == NULL || rsa->internal == NULL) + { + WOLFSSL_MSG("Bad function arguments"); + return WOLFSSL_FAILURE; + } + + ret = wolfSSL_PEM_write_mem_RSAPrivateKey(rsa, enc, kstr, klen, &pem, &plen); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_PEM_write_mem_RSAPrivateKey failed"); + return WOLFSSL_FAILURE; + } + + ret = (int)XFWRITE(pem, plen, 1, fp); + if (ret != 1) { + WOLFSSL_MSG("RSA private key file write failed"); + return WOLFSSL_FAILURE; + } + + XFREE(pem, NULL, DYNAMIC_TYPE_KEY); + return WOLFSSL_SUCCESS; +} +#endif /* NO_FILESYSTEM */ +#endif /* WOLFSSL_KEY_GEN && !NO_RSA && !HAVE_USER_RSA && WOLFSSL_PEM_TO_DER */ + + +#ifdef HAVE_ECC + +#ifdef ALT_ECC_SIZE +static int SetIndividualInternalEcc(WOLFSSL_BIGNUM* bn, mp_int* mpi) +{ + WOLFSSL_MSG("Entering SetIndividualInternal"); + + if (bn == NULL || bn->internal == NULL) { + WOLFSSL_MSG("bn NULL error"); + return WOLFSSL_FATAL_ERROR; + } + + if (mpi == NULL) { + WOLFSSL_MSG("mpi NULL error"); + return WOLFSSL_FATAL_ERROR; + } + + if (mp_copy((mp_int*)bn->internal, mpi) != MP_OKAY) { + WOLFSSL_MSG("mp_copy error"); + return WOLFSSL_FATAL_ERROR; + } + + return WOLFSSL_SUCCESS; +} +#endif /* ALT_ECC_SIZE */ + +/* EC_POINT Openssl -> WolfSSL */ +static int SetECPointInternal(WOLFSSL_EC_POINT *p) +{ + ecc_point* point; + WOLFSSL_ENTER("SetECPointInternal"); + + if (p == NULL || p->internal == NULL) { + WOLFSSL_MSG("ECPoint NULL error"); + return WOLFSSL_FATAL_ERROR; + } + + point = (ecc_point*)p->internal; + +#ifndef ALT_ECC_SIZE + if (p->X != NULL && SetIndividualInternal(p->X, point->x) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("ecc point X error"); + return WOLFSSL_FATAL_ERROR; + } + + if (p->Y != NULL && SetIndividualInternal(p->Y, point->y) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("ecc point Y error"); + return WOLFSSL_FATAL_ERROR; + } + + if (p->Z != NULL && SetIndividualInternal(p->Z, point->z) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("ecc point Z error"); + return WOLFSSL_FATAL_ERROR; + } +#else + if (p->X != NULL && SetIndividualInternalEcc(p->X, point->x) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("ecc point X error"); + return WOLFSSL_FATAL_ERROR; + } + + if (p->Y != NULL && SetIndividualInternalEcc(p->Y, point->y) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("ecc point Y error"); + return WOLFSSL_FATAL_ERROR; + } + + if (p->Z != NULL && SetIndividualInternalEcc(p->Z, point->z) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("ecc point Z error"); + return WOLFSSL_FATAL_ERROR; + } +#endif + + p->inSet = 1; + + return WOLFSSL_SUCCESS; +} +#endif /* HAVE_ECC */ +#endif /* OPENSSL_EXTRA */ + +#if defined(HAVE_ECC) && defined(OPENSSL_EXTRA_X509_SMALL) + +/* EC_POINT WolfSSL -> OpenSSL */ +static int SetECPointExternal(WOLFSSL_EC_POINT *p) +{ + ecc_point* point; + + WOLFSSL_ENTER("SetECPointExternal"); + + if (p == NULL || p->internal == NULL) { + WOLFSSL_MSG("ECPoint NULL error"); + return WOLFSSL_FATAL_ERROR; + } + + point = (ecc_point*)p->internal; + + if (SetIndividualExternal(&p->X, point->x) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("ecc point X error"); + return WOLFSSL_FATAL_ERROR; + } + + if (SetIndividualExternal(&p->Y, point->y) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("ecc point Y error"); + return WOLFSSL_FATAL_ERROR; + } + + if (SetIndividualExternal(&p->Z, point->z) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("ecc point Z error"); + return WOLFSSL_FATAL_ERROR; + } + + p->exSet = 1; + + return WOLFSSL_SUCCESS; +} + + +/* EC_KEY wolfSSL -> OpenSSL */ +static int SetECKeyExternal(WOLFSSL_EC_KEY* eckey) +{ + ecc_key* key; + + WOLFSSL_ENTER("SetECKeyExternal"); + + if (eckey == NULL || eckey->internal == NULL) { + WOLFSSL_MSG("ec key NULL error"); + return WOLFSSL_FATAL_ERROR; + } + + key = (ecc_key*)eckey->internal; + + /* set group (OID, nid and idx) */ + eckey->group->curve_oid = ecc_sets[key->idx].oidSum; + eckey->group->curve_nid = ecc_sets[key->idx].id; + eckey->group->curve_idx = key->idx; + + if (eckey->pub_key->internal != NULL) { + /* set the internal public key */ + if (wc_ecc_copy_point(&key->pubkey, + (ecc_point*)eckey->pub_key->internal) != MP_OKAY) { + WOLFSSL_MSG("SetECKeyExternal ecc_copy_point failed"); + return WOLFSSL_FATAL_ERROR; + } + + /* set the external pubkey (point) */ + if (SetECPointExternal(eckey->pub_key) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetECKeyExternal SetECPointExternal failed"); + return WOLFSSL_FATAL_ERROR; + } + } + + /* set the external privkey */ + if (key->type == ECC_PRIVATEKEY) { + if (SetIndividualExternal(&eckey->priv_key, &key->k) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("ec priv key error"); + return WOLFSSL_FATAL_ERROR; + } + } + + eckey->exSet = 1; + + return WOLFSSL_SUCCESS; +} +#endif /* HAVE_ECC && OPENSSL_EXTRA_X509_SMALL */ + +#ifdef OPENSSL_EXTRA +#ifdef HAVE_ECC +/* EC_KEY Openssl -> WolfSSL */ +static int SetECKeyInternal(WOLFSSL_EC_KEY* eckey) +{ + ecc_key* key; + + WOLFSSL_ENTER("SetECKeyInternal"); + + if (eckey == NULL || eckey->internal == NULL) { + WOLFSSL_MSG("ec key NULL error"); + return WOLFSSL_FATAL_ERROR; + } + + key = (ecc_key*)eckey->internal; + + /* validate group */ + if ((eckey->group->curve_idx < 0) || + (wc_ecc_is_valid_idx(eckey->group->curve_idx) == 0)) { + WOLFSSL_MSG("invalid curve idx"); + return WOLFSSL_FATAL_ERROR; + } + + /* set group (idx of curve and corresponding domain parameters) */ + key->idx = eckey->group->curve_idx; + key->dp = &ecc_sets[key->idx]; + + /* set pubkey (point) */ + if (eckey->pub_key != NULL) { + if (SetECPointInternal(eckey->pub_key) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("ec key pub error"); + return WOLFSSL_FATAL_ERROR; + } + + /* public key */ + key->type = ECC_PUBLICKEY; + } + + /* set privkey */ + if (eckey->priv_key != NULL) { + if (SetIndividualInternal(eckey->priv_key, &key->k) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("ec key priv error"); + return WOLFSSL_FATAL_ERROR; + } + + /* private key */ + key->type = ECC_PRIVATEKEY; + } + + eckey->inSet = 1; + + return WOLFSSL_SUCCESS; +} + +WOLFSSL_EC_POINT *wolfSSL_EC_KEY_get0_public_key(const WOLFSSL_EC_KEY *key) +{ + WOLFSSL_ENTER("wolfSSL_EC_KEY_get0_public_key"); + + if (key == NULL) { + WOLFSSL_MSG("wolfSSL_EC_KEY_get0_group Bad arguments"); + return NULL; + } + + return key->pub_key; +} + +const WOLFSSL_EC_GROUP *wolfSSL_EC_KEY_get0_group(const WOLFSSL_EC_KEY *key) +{ + WOLFSSL_ENTER("wolfSSL_EC_KEY_get0_group"); + + if (key == NULL) { + WOLFSSL_MSG("wolfSSL_EC_KEY_get0_group Bad arguments"); + return NULL; + } + + return key->group; +} + + +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_EC_KEY_set_private_key(WOLFSSL_EC_KEY *key, + const WOLFSSL_BIGNUM *priv_key) +{ + WOLFSSL_ENTER("wolfSSL_EC_KEY_set_private_key"); + + if (key == NULL || priv_key == NULL) { + WOLFSSL_MSG("Bad arguments"); + return WOLFSSL_FAILURE; + } + + /* free key if previously set */ + if (key->priv_key != NULL) + wolfSSL_BN_free(key->priv_key); + + key->priv_key = wolfSSL_BN_dup(priv_key); + if (key->priv_key == NULL) { + WOLFSSL_MSG("key ecc priv key NULL"); + return WOLFSSL_FAILURE; + } + + if (SetECKeyInternal(key) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetECKeyInternal failed"); + wolfSSL_BN_free(key->priv_key); + return WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; +} + + +WOLFSSL_BIGNUM *wolfSSL_EC_KEY_get0_private_key(const WOLFSSL_EC_KEY *key) +{ + WOLFSSL_ENTER("wolfSSL_EC_KEY_get0_private_key"); + + if (key == NULL) { + WOLFSSL_MSG("wolfSSL_EC_KEY_get0_private_key Bad arguments"); + return NULL; + } + + return key->priv_key; +} + +WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new_by_curve_name(int nid) +{ + WOLFSSL_EC_KEY *key; + int x; + + WOLFSSL_ENTER("wolfSSL_EC_KEY_new_by_curve_name"); + + key = wolfSSL_EC_KEY_new(); + if (key == NULL) { + WOLFSSL_MSG("wolfSSL_EC_KEY_new failure"); + return NULL; + } + + /* set the nid of the curve */ + key->group->curve_nid = nid; + + /* search and set the corresponding internal curve idx */ + for (x = 0; ecc_sets[x].size != 0; x++) + if (ecc_sets[x].id == key->group->curve_nid) { + key->group->curve_idx = x; + key->group->curve_oid = ecc_sets[x].oidSum; + break; + } + + return key; +} + +#endif /* HAVE_ECC */ +#endif /* OPENSSL_EXTRA */ + +#if defined(HAVE_ECC) && (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) +static void InitwolfSSL_ECKey(WOLFSSL_EC_KEY* key) +{ + if (key) { + key->group = NULL; + key->pub_key = NULL; + key->priv_key = NULL; + key->internal = NULL; + key->inSet = 0; + key->exSet = 0; + } +} + +WOLFSSL_EC_KEY *wolfSSL_EC_KEY_new(void) +{ + WOLFSSL_EC_KEY *external; + ecc_key* key; + + WOLFSSL_ENTER("wolfSSL_EC_KEY_new"); + + external = (WOLFSSL_EC_KEY*)XMALLOC(sizeof(WOLFSSL_EC_KEY), NULL, + DYNAMIC_TYPE_ECC); + if (external == NULL) { + WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc WOLFSSL_EC_KEY failure"); + return NULL; + } + XMEMSET(external, 0, sizeof(WOLFSSL_EC_KEY)); + + InitwolfSSL_ECKey(external); + + external->internal = (ecc_key*)XMALLOC(sizeof(ecc_key), NULL, + DYNAMIC_TYPE_ECC); + if (external->internal == NULL) { + WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc ecc key failure"); + wolfSSL_EC_KEY_free(external); + return NULL; + } + XMEMSET(external->internal, 0, sizeof(ecc_key)); + + if (wc_ecc_init((ecc_key*)external->internal) != 0) { + WOLFSSL_MSG("wolfSSL_EC_KEY_new init ecc key failure"); + wolfSSL_EC_KEY_free(external); + return NULL; + } + + /* public key */ + external->pub_key = (WOLFSSL_EC_POINT*)XMALLOC(sizeof(WOLFSSL_EC_POINT), + NULL, DYNAMIC_TYPE_ECC); + if (external->pub_key == NULL) { + WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc WOLFSSL_EC_POINT failure"); + wolfSSL_EC_KEY_free(external); + return NULL; + } + XMEMSET(external->pub_key, 0, sizeof(WOLFSSL_EC_POINT)); + + key = (ecc_key*)external->internal; + external->pub_key->internal = wc_ecc_new_point(); + if (wc_ecc_copy_point((ecc_point*)&key->pubkey, + (ecc_point*)external->pub_key->internal) != MP_OKAY) { + WOLFSSL_MSG("wc_ecc_copy_point failure"); + wolfSSL_EC_KEY_free(external); + return NULL; + } + + /* curve group */ + external->group = (WOLFSSL_EC_GROUP*)XMALLOC(sizeof(WOLFSSL_EC_GROUP), NULL, + DYNAMIC_TYPE_ECC); + if (external->group == NULL) { + WOLFSSL_MSG("wolfSSL_EC_KEY_new malloc WOLFSSL_EC_GROUP failure"); + wolfSSL_EC_KEY_free(external); + return NULL; + } + XMEMSET(external->group, 0, sizeof(WOLFSSL_EC_GROUP)); + + /* private key */ + external->priv_key = wolfSSL_BN_new(); + if (external->priv_key == NULL) { + WOLFSSL_MSG("wolfSSL_BN_new failure"); + wolfSSL_EC_KEY_free(external); + return NULL; + } + + return external; +} + +void wolfSSL_EC_KEY_free(WOLFSSL_EC_KEY *key) +{ + WOLFSSL_ENTER("wolfSSL_EC_KEY_free"); + + if (key != NULL) { + if (key->internal != NULL) { + wc_ecc_free((ecc_key*)key->internal); + XFREE(key->internal, NULL, DYNAMIC_TYPE_ECC); + } + wolfSSL_BN_free(key->priv_key); + wolfSSL_EC_POINT_free(key->pub_key); + wolfSSL_EC_GROUP_free(key->group); + InitwolfSSL_ECKey(key); /* set back to NULLs for safety */ + + XFREE(key, NULL, DYNAMIC_TYPE_ECC); + key = NULL; + } +} +#endif /* HAVE_ECC && (OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL) */ + +#ifdef OPENSSL_EXTRA +#ifdef HAVE_ECC + +#ifndef NO_WOLFSSL_STUB +int wolfSSL_EC_KEY_set_group(WOLFSSL_EC_KEY *key, WOLFSSL_EC_GROUP *group) +{ + (void)key; + (void)group; + + WOLFSSL_ENTER("wolfSSL_EC_KEY_set_group"); + WOLFSSL_STUB("EC_KEY_set_group"); + + return -1; +} +#endif + +int wolfSSL_EC_KEY_generate_key(WOLFSSL_EC_KEY *key) +{ + int initTmpRng = 0; + WC_RNG* rng = NULL; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG* tmpRNG = NULL; +#else + WC_RNG tmpRNG[1]; +#endif + + WOLFSSL_ENTER("wolfSSL_EC_KEY_generate_key"); + + if (key == NULL || key->internal == NULL || + key->group == NULL || key->group->curve_idx < 0) { + WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key Bad arguments"); + return 0; + } + +#ifdef WOLFSSL_SMALL_STACK + tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); + if (tmpRNG == NULL) + return 0; +#endif + + if (wc_InitRng(tmpRNG) == 0) { + rng = tmpRNG; + initTmpRng = 1; + } + else { + WOLFSSL_MSG("Bad RNG Init, trying global"); + if (initGlobalRNG == 0) + WOLFSSL_MSG("Global RNG no Init"); + else + rng = &globalRNG; + } + + if (rng == NULL) { + WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key failed to set RNG"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); +#endif + return 0; + } + + if (wc_ecc_make_key_ex(rng, 0, (ecc_key*)key->internal, + key->group->curve_nid) != MP_OKAY) { + WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key wc_ecc_make_key failed"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); +#endif + return 0; + } + + if (initTmpRng) + wc_FreeRng(tmpRNG); +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); +#endif + + if (SetECKeyExternal(key) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_EC_KEY_generate_key SetECKeyExternal failed"); + return 0; + } + + return 1; +} + +#ifndef NO_WOLFSSL_STUB +void wolfSSL_EC_KEY_set_asn1_flag(WOLFSSL_EC_KEY *key, int asn1_flag) +{ + (void)key; + (void)asn1_flag; + + WOLFSSL_ENTER("wolfSSL_EC_KEY_set_asn1_flag"); + WOLFSSL_STUB("EC_KEY_set_asn1_flag"); +} +#endif + +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_EC_KEY_set_public_key(WOLFSSL_EC_KEY *key, + const WOLFSSL_EC_POINT *pub) +{ + ecc_point *pub_p, *key_p; + + WOLFSSL_ENTER("wolfSSL_EC_KEY_set_public_key"); + + if (key == NULL || key->internal == NULL || + pub == NULL || pub->internal == NULL) { + WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order Bad arguments"); + return WOLFSSL_FAILURE; + } + + if (key->inSet == 0) { + if (SetECKeyInternal(key) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetECKeyInternal failed"); + return WOLFSSL_FAILURE; + } + } + + if (pub->inSet == 0) { + if (SetECPointInternal((WOLFSSL_EC_POINT *)pub) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetECPointInternal failed"); + return WOLFSSL_FAILURE; + } + } + + pub_p = (ecc_point*)pub->internal; + key_p = (ecc_point*)key->pub_key->internal; + + /* create new point if required */ + if (key_p == NULL) + key_p = wc_ecc_new_point(); + + if (key_p == NULL) { + WOLFSSL_MSG("key ecc point NULL"); + return WOLFSSL_FAILURE; + } + + if (wc_ecc_copy_point(pub_p, key_p) != MP_OKAY) { + WOLFSSL_MSG("ecc_copy_point failure"); + return WOLFSSL_FAILURE; + } + + if (SetECKeyExternal(key) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetECKeyInternal failed"); + return WOLFSSL_FAILURE; + } + + wolfSSL_EC_POINT_dump("pub", pub); + wolfSSL_EC_POINT_dump("key->pub_key", key->pub_key); + + return WOLFSSL_SUCCESS; +} +/* End EC_KEY */ + + +#ifndef HAVE_SELFTEST +/* ECC point compression types were not included in selftest ecc.h */ + +char* wolfSSL_EC_POINT_point2hex(const WOLFSSL_EC_GROUP* group, + const WOLFSSL_EC_POINT* point, int form, + WOLFSSL_BN_CTX* ctx) +{ + static const char* hexDigit = "0123456789ABCDEF"; + char* hex = NULL; + int id; + int i, sz, len; + + (void)ctx; + + if (group == NULL || point == NULL) + return NULL; + + id = wc_ecc_get_curve_id(group->curve_idx); + + if ((sz = wc_ecc_get_curve_size_from_id(id)) < 0) + return NULL; + + len = sz + 1; + if (form == POINT_CONVERSION_UNCOMPRESSED) + len += sz; + + hex = (char*)XMALLOC(2 * len + 1, NULL, DYNAMIC_TYPE_ECC); + if (hex == NULL) + return NULL; + XMEMSET(hex, 0, 2 * len + 1); + + /* Put in x-ordinate after format byte. */ + i = sz - mp_unsigned_bin_size((mp_int*)point->X->internal) + 1; + if (mp_to_unsigned_bin((mp_int*)point->X->internal, (byte*)(hex + i)) < 0) { + XFREE(hex, NULL, DYNAMIC_TYPE_ECC); + return NULL; + } + + if (form == POINT_CONVERSION_COMPRESSED) { + hex[0] = mp_isodd((mp_int*)point->Y->internal) ? ECC_POINT_COMP_ODD : + ECC_POINT_COMP_EVEN; + } + else { + hex[0] = ECC_POINT_UNCOMP; + /* Put in y-ordinate after x-ordinate */ + i = 1 + 2 * sz - mp_unsigned_bin_size((mp_int*)point->Y->internal); + if (mp_to_unsigned_bin((mp_int*)point->Y->internal, + (byte*)(hex + i)) < 0) { + XFREE(hex, NULL, DYNAMIC_TYPE_ECC); + return NULL; + } + } + + for (i = len-1; i >= 0; i--) { + byte b = hex[i]; + hex[i * 2 + 1] = hexDigit[b & 0xf]; + hex[i * 2 ] = hexDigit[b >> 4]; + } + + return hex; +} + +#endif /* HAVE_SELFTEST */ + +void wolfSSL_EC_POINT_dump(const char *msg, const WOLFSSL_EC_POINT *p) +{ +#if defined(DEBUG_WOLFSSL) + char *num; + + WOLFSSL_ENTER("wolfSSL_EC_POINT_dump"); + + if (p == NULL) { + printf("%s = NULL", msg); + return; + } + + printf("%s:\n\tinSet=%d, exSet=%d\n", msg, p->inSet, p->exSet); + num = wolfSSL_BN_bn2hex(p->X); + printf("\tX = %s\n", num); + XFREE(num, NULL, DYNAMIC_TYPE_ECC); + num = wolfSSL_BN_bn2hex(p->Y); + printf("\tY = %s\n", num); + XFREE(num, NULL, DYNAMIC_TYPE_ECC); + num = wolfSSL_BN_bn2hex(p->Z); + printf("\tZ = %s\n", num); + XFREE(num, NULL, DYNAMIC_TYPE_ECC); +#else + (void)msg; + (void)p; +#endif +} + +/* Start EC_GROUP */ + +/* return code compliant with OpenSSL : + * 0 if equal, 1 if not and -1 in case of error + */ +int wolfSSL_EC_GROUP_cmp(const WOLFSSL_EC_GROUP *a, const WOLFSSL_EC_GROUP *b, + WOLFSSL_BN_CTX *ctx) +{ + (void)ctx; + + WOLFSSL_ENTER("wolfSSL_EC_GROUP_cmp"); + + if (a == NULL || b == NULL) { + WOLFSSL_MSG("wolfSSL_EC_GROUP_cmp Bad arguments"); + return WOLFSSL_FATAL_ERROR; + } + + /* ok */ + if ((a->curve_idx == b->curve_idx) && (a->curve_nid == b->curve_nid)) + return 0; + + /* ko */ + return 1; +} + +#endif /* HAVE_ECC */ +#endif /* OPENSSL_EXTRA */ + +#if defined(HAVE_ECC) && (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) +void wolfSSL_EC_GROUP_free(WOLFSSL_EC_GROUP *group) +{ + WOLFSSL_ENTER("wolfSSL_EC_GROUP_free"); + + XFREE(group, NULL, DYNAMIC_TYPE_ECC); + group = NULL; +} +#endif + +#ifdef OPENSSL_EXTRA +#ifdef HAVE_ECC +#ifndef NO_WOLFSSL_STUB +void wolfSSL_EC_GROUP_set_asn1_flag(WOLFSSL_EC_GROUP *group, int flag) +{ + (void)group; + (void)flag; + + WOLFSSL_ENTER("wolfSSL_EC_GROUP_set_asn1_flag"); + WOLFSSL_STUB("EC_GROUP_set_asn1_flag"); +} +#endif + +WOLFSSL_EC_GROUP *wolfSSL_EC_GROUP_new_by_curve_name(int nid) +{ + WOLFSSL_EC_GROUP *g; + int x; + + WOLFSSL_ENTER("wolfSSL_EC_GROUP_new_by_curve_name"); + + /* curve group */ + g = (WOLFSSL_EC_GROUP*) XMALLOC(sizeof(WOLFSSL_EC_GROUP), NULL, + DYNAMIC_TYPE_ECC); + if (g == NULL) { + WOLFSSL_MSG("wolfSSL_EC_GROUP_new_by_curve_name malloc failure"); + return NULL; + } + XMEMSET(g, 0, sizeof(WOLFSSL_EC_GROUP)); + + /* set the nid of the curve */ + g->curve_nid = nid; + + /* search and set the corresponding internal curve idx */ + for (x = 0; ecc_sets[x].size != 0; x++) + if (ecc_sets[x].id == g->curve_nid) { + g->curve_idx = x; + g->curve_oid = ecc_sets[x].oidSum; + break; + } + + return g; +} + +/* return code compliant with OpenSSL : + * the curve nid if success, 0 if error + */ +int wolfSSL_EC_GROUP_get_curve_name(const WOLFSSL_EC_GROUP *group) +{ + WOLFSSL_ENTER("wolfSSL_EC_GROUP_get_curve_name"); + + if (group == NULL) { + WOLFSSL_MSG("wolfSSL_EC_GROUP_get_curve_name Bad arguments"); + return WOLFSSL_FAILURE; + } + + return group->curve_nid; +} + +/* return code compliant with OpenSSL : + * the degree of the curve if success, 0 if error + */ +int wolfSSL_EC_GROUP_get_degree(const WOLFSSL_EC_GROUP *group) +{ + WOLFSSL_ENTER("wolfSSL_EC_GROUP_get_degree"); + + if (group == NULL || group->curve_idx < 0) { + WOLFSSL_MSG("wolfSSL_EC_GROUP_get_degree Bad arguments"); + return WOLFSSL_FAILURE; + } + + switch(group->curve_nid) { + case NID_secp112r1: + case NID_secp112r2: + return 112; + case NID_secp128r1: + case NID_secp128r2: + return 128; + case NID_secp160k1: + case NID_secp160r1: + case NID_secp160r2: + case NID_brainpoolP160r1: + return 160; + case NID_secp192k1: + case NID_brainpoolP192r1: + case NID_X9_62_prime192v1: + return 192; + case NID_secp224k1: + case NID_secp224r1: + case NID_brainpoolP224r1: + return 224; + case NID_secp256k1: + case NID_brainpoolP256r1: + case NID_X9_62_prime256v1: + return 256; + case NID_brainpoolP320r1: + return 320; + case NID_secp384r1: + case NID_brainpoolP384r1: + return 384; + case NID_secp521r1: + case NID_brainpoolP512r1: + return 521; + default: + return WOLFSSL_FAILURE; + } +} + +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_EC_GROUP_get_order(const WOLFSSL_EC_GROUP *group, + WOLFSSL_BIGNUM *order, WOLFSSL_BN_CTX *ctx) +{ + (void)ctx; + + if (group == NULL || order == NULL || order->internal == NULL) { + WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order NULL error"); + return WOLFSSL_FAILURE; + } + + if (mp_init((mp_int*)order->internal) != MP_OKAY) { + WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order mp_init failure"); + return WOLFSSL_FAILURE; + } + + if (mp_read_radix((mp_int*)order->internal, + ecc_sets[group->curve_idx].order, MP_RADIX_HEX) != MP_OKAY) { + WOLFSSL_MSG("wolfSSL_EC_GROUP_get_order mp_read order failure"); + mp_clear((mp_int*)order->internal); + return WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; +} +/* End EC_GROUP */ + +/* Start EC_POINT */ + +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_ECPoint_i2d(const WOLFSSL_EC_GROUP *group, + const WOLFSSL_EC_POINT *p, + unsigned char *out, unsigned int *len) +{ + int err; + + WOLFSSL_ENTER("wolfSSL_ECPoint_i2d"); + + if (group == NULL || p == NULL || len == NULL) { + WOLFSSL_MSG("wolfSSL_ECPoint_i2d NULL error"); + return WOLFSSL_FAILURE; + } + + if (p->inSet == 0) { + WOLFSSL_MSG("No ECPoint internal set, do it"); + + if (SetECPointInternal((WOLFSSL_EC_POINT *)p) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetECPointInternal SetECPointInternal failed"); + return WOLFSSL_FAILURE; + } + } + + if (out != NULL) { + wolfSSL_EC_POINT_dump("i2d p", p); + } + + err = wc_ecc_export_point_der(group->curve_idx, (ecc_point*)p->internal, + out, len); + if (err != MP_OKAY && !(out == NULL && err == LENGTH_ONLY_E)) { + WOLFSSL_MSG("wolfSSL_ECPoint_i2d wc_ecc_export_point_der failed"); + return WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; +} + +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_ECPoint_d2i(unsigned char *in, unsigned int len, + const WOLFSSL_EC_GROUP *group, WOLFSSL_EC_POINT *p) +{ + WOLFSSL_ENTER("wolfSSL_ECPoint_d2i"); + + if (group == NULL || p == NULL || p->internal == NULL || in == NULL) { + WOLFSSL_MSG("wolfSSL_ECPoint_d2i NULL error"); + return WOLFSSL_FAILURE; + } + + if (wc_ecc_import_point_der(in, len, group->curve_idx, + (ecc_point*)p->internal) != MP_OKAY) { + WOLFSSL_MSG("wc_ecc_import_point_der failed"); + return WOLFSSL_FAILURE; + } + + if (p->exSet == 0) { + WOLFSSL_MSG("No ECPoint external set, do it"); + + if (SetECPointExternal(p) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetECPointExternal failed"); + return WOLFSSL_FAILURE; + } + } + + wolfSSL_EC_POINT_dump("d2i p", p); + + return WOLFSSL_SUCCESS; +} + +WOLFSSL_EC_POINT *wolfSSL_EC_POINT_new(const WOLFSSL_EC_GROUP *group) +{ + WOLFSSL_EC_POINT *p; + + WOLFSSL_ENTER("wolfSSL_EC_POINT_new"); + + if (group == NULL) { + WOLFSSL_MSG("wolfSSL_EC_POINT_new NULL error"); + return NULL; + } + + p = (WOLFSSL_EC_POINT *)XMALLOC(sizeof(WOLFSSL_EC_POINT), NULL, + DYNAMIC_TYPE_ECC); + if (p == NULL) { + WOLFSSL_MSG("wolfSSL_EC_POINT_new malloc ecc point failure"); + return NULL; + } + XMEMSET(p, 0, sizeof(WOLFSSL_EC_POINT)); + + p->internal = wc_ecc_new_point(); + if (p->internal == NULL) { + WOLFSSL_MSG("ecc_new_point failure"); + XFREE(p, NULL, DYNAMIC_TYPE_ECC); + return NULL; + } + + return p; +} + +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_EC_POINT_get_affine_coordinates_GFp(const WOLFSSL_EC_GROUP *group, + const WOLFSSL_EC_POINT *point, + WOLFSSL_BIGNUM *x, + WOLFSSL_BIGNUM *y, + WOLFSSL_BN_CTX *ctx) +{ + (void)ctx; + + WOLFSSL_ENTER("wolfSSL_EC_POINT_get_affine_coordinates_GFp"); + + if (group == NULL || point == NULL || point->internal == NULL || + x == NULL || y == NULL) { + WOLFSSL_MSG("wolfSSL_EC_POINT_get_affine_coordinates_GFp NULL error"); + return WOLFSSL_FAILURE; + } + + if (point->inSet == 0) { + WOLFSSL_MSG("No ECPoint internal set, do it"); + + if (SetECPointInternal((WOLFSSL_EC_POINT *)point) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetECPointInternal failed"); + return WOLFSSL_FAILURE; + } + } + + BN_copy(x, point->X); + BN_copy(y, point->Y); + + return WOLFSSL_SUCCESS; +} + +#ifndef WOLFSSL_ATECC508A +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_EC_POINT_mul(const WOLFSSL_EC_GROUP *group, WOLFSSL_EC_POINT *r, + const WOLFSSL_BIGNUM *n, const WOLFSSL_EC_POINT *q, + const WOLFSSL_BIGNUM *m, WOLFSSL_BN_CTX *ctx) +{ + mp_int a, prime; + int ret; + + (void)ctx; + (void)n; + + WOLFSSL_ENTER("wolfSSL_EC_POINT_mul"); + + if (group == NULL || r == NULL || r->internal == NULL || + q == NULL || q->internal == NULL || m == NULL) { + WOLFSSL_MSG("wolfSSL_EC_POINT_mul NULL error"); + return WOLFSSL_FAILURE; + } + + if (q->inSet == 0) { + WOLFSSL_MSG("No ECPoint internal set, do it"); + + if (SetECPointInternal((WOLFSSL_EC_POINT *)q) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetECPointInternal q failed"); + return WOLFSSL_FAILURE; + } + } + + /* read the curve prime and a */ + if (mp_init_multi(&prime, &a, NULL, NULL, NULL, NULL) != MP_OKAY) { + return WOLFSSL_FAILURE; + } + + ret = mp_read_radix(&prime, ecc_sets[group->curve_idx].prime, MP_RADIX_HEX); + if (ret == MP_OKAY) { + ret = mp_read_radix(&a, ecc_sets[group->curve_idx].Af, MP_RADIX_HEX); + } + + /* r = q * m % prime */ + if (ret == MP_OKAY) { + ret = wc_ecc_mulmod((mp_int*)m->internal, (ecc_point*)q->internal, + (ecc_point*)r->internal, &a, &prime, 1); + } + + mp_clear(&a); + mp_clear(&prime); + + if (ret == MP_OKAY) { + r->inSet = 1; /* mark internal set */ + + /* set the external value for the computed point */ + ret = SetECPointExternal(r); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetECPointInternal r failed"); + } + } + else { + ret = WOLFSSL_FAILURE; + } + + return ret; +} +#endif + +void wolfSSL_EC_POINT_clear_free(WOLFSSL_EC_POINT *p) +{ + WOLFSSL_ENTER("wolfSSL_EC_POINT_clear_free"); + + wolfSSL_EC_POINT_free(p); +} + +/* return code compliant with OpenSSL : + * 0 if equal, 1 if not and -1 in case of error + */ +int wolfSSL_EC_POINT_cmp(const WOLFSSL_EC_GROUP *group, + const WOLFSSL_EC_POINT *a, const WOLFSSL_EC_POINT *b, + WOLFSSL_BN_CTX *ctx) +{ + int ret; + + (void)ctx; + + WOLFSSL_ENTER("wolfSSL_EC_POINT_cmp"); + + if (group == NULL || a == NULL || a->internal == NULL || b == NULL || + b->internal == NULL) { + WOLFSSL_MSG("wolfSSL_EC_POINT_cmp Bad arguments"); + return WOLFSSL_FATAL_ERROR; + } + + ret = wc_ecc_cmp_point((ecc_point*)a->internal, (ecc_point*)b->internal); + if (ret == MP_EQ) + return 0; + else if (ret == MP_LT || ret == MP_GT) + return 1; + + return WOLFSSL_FATAL_ERROR; +} +#endif /* HAVE_ECC */ +#endif /* OPENSSL_EXTRA */ + +#if defined(HAVE_ECC) && (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) +void wolfSSL_EC_POINT_free(WOLFSSL_EC_POINT *p) +{ + WOLFSSL_ENTER("wolfSSL_EC_POINT_free"); + + if (p != NULL) { + if (p->internal != NULL) { + wc_ecc_del_point((ecc_point*)p->internal); + p->internal = NULL; + } + + wolfSSL_BN_free(p->X); + wolfSSL_BN_free(p->Y); + wolfSSL_BN_free(p->Z); + p->X = NULL; + p->Y = NULL; + p->Z = NULL; + p->inSet = p->exSet = 0; + + XFREE(p, NULL, DYNAMIC_TYPE_ECC); + p = NULL; + } +} +#endif + +#ifdef OPENSSL_EXTRA +#ifdef HAVE_ECC +/* return code compliant with OpenSSL : + * 1 if point at infinity, 0 else + */ +int wolfSSL_EC_POINT_is_at_infinity(const WOLFSSL_EC_GROUP *group, + const WOLFSSL_EC_POINT *point) +{ + int ret; + + WOLFSSL_ENTER("wolfSSL_EC_POINT_is_at_infinity"); + + if (group == NULL || point == NULL || point->internal == NULL) { + WOLFSSL_MSG("wolfSSL_EC_POINT_is_at_infinity NULL error"); + return WOLFSSL_FAILURE; + } + if (point->inSet == 0) { + WOLFSSL_MSG("No ECPoint internal set, do it"); + + if (SetECPointInternal((WOLFSSL_EC_POINT *)point) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetECPointInternal failed"); + return WOLFSSL_FAILURE; + } + } + + ret = wc_ecc_point_is_at_infinity((ecc_point*)point->internal); + if (ret <= 0) { + WOLFSSL_MSG("ecc_point_is_at_infinity failure"); + return WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; +} + +/* End EC_POINT */ + +/* Start ECDSA_SIG */ +void wolfSSL_ECDSA_SIG_free(WOLFSSL_ECDSA_SIG *sig) +{ + WOLFSSL_ENTER("wolfSSL_ECDSA_SIG_free"); + + if (sig) { + wolfSSL_BN_free(sig->r); + wolfSSL_BN_free(sig->s); + + XFREE(sig, NULL, DYNAMIC_TYPE_ECC); + } +} + +WOLFSSL_ECDSA_SIG *wolfSSL_ECDSA_SIG_new(void) +{ + WOLFSSL_ECDSA_SIG *sig; + + WOLFSSL_ENTER("wolfSSL_ECDSA_SIG_new"); + + sig = (WOLFSSL_ECDSA_SIG*) XMALLOC(sizeof(WOLFSSL_ECDSA_SIG), NULL, + DYNAMIC_TYPE_ECC); + if (sig == NULL) { + WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new malloc ECDSA signature failure"); + return NULL; + } + + sig->s = NULL; + sig->r = wolfSSL_BN_new(); + if (sig->r == NULL) { + WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new malloc ECDSA r failure"); + wolfSSL_ECDSA_SIG_free(sig); + return NULL; + } + + sig->s = wolfSSL_BN_new(); + if (sig->s == NULL) { + WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new malloc ECDSA s failure"); + wolfSSL_ECDSA_SIG_free(sig); + return NULL; + } + + return sig; +} + +/* return signature structure on success, NULL otherwise */ +WOLFSSL_ECDSA_SIG *wolfSSL_ECDSA_do_sign(const unsigned char *d, int dlen, + WOLFSSL_EC_KEY *key) +{ + WOLFSSL_ECDSA_SIG *sig = NULL; + int initTmpRng = 0; + WC_RNG* rng = NULL; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG* tmpRNG = NULL; +#else + WC_RNG tmpRNG[1]; +#endif + + WOLFSSL_ENTER("wolfSSL_ECDSA_do_sign"); + + if (d == NULL || key == NULL || key->internal == NULL) { + WOLFSSL_MSG("wolfSSL_ECDSA_do_sign Bad arguments"); + return NULL; + } + + /* set internal key if not done */ + if (key->inSet == 0) + { + WOLFSSL_MSG("wolfSSL_ECDSA_do_sign No EC key internal set, do it"); + + if (SetECKeyInternal(key) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_ECDSA_do_sign SetECKeyInternal failed"); + return NULL; + } + } + +#ifdef WOLFSSL_SMALL_STACK + tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); + if (tmpRNG == NULL) + return NULL; +#endif + + if (wc_InitRng(tmpRNG) == 0) { + rng = tmpRNG; + initTmpRng = 1; + } + else { + WOLFSSL_MSG("wolfSSL_ECDSA_do_sign Bad RNG Init, trying global"); + if (initGlobalRNG == 0) + WOLFSSL_MSG("wolfSSL_ECDSA_do_sign Global RNG no Init"); + else + rng = &globalRNG; + } + + if (rng) { + mp_int sig_r, sig_s; + + if (mp_init_multi(&sig_r, &sig_s, NULL, NULL, NULL, NULL) == MP_OKAY) { + if (wc_ecc_sign_hash_ex(d, dlen, rng, (ecc_key*)key->internal, + &sig_r, &sig_s) != MP_OKAY) { + WOLFSSL_MSG("wc_ecc_sign_hash_ex failed"); + } + else { + /* put signature blob in ECDSA structure */ + sig = wolfSSL_ECDSA_SIG_new(); + if (sig == NULL) + WOLFSSL_MSG("wolfSSL_ECDSA_SIG_new failed"); + else if (SetIndividualExternal(&(sig->r), &sig_r)!=WOLFSSL_SUCCESS){ + WOLFSSL_MSG("ecdsa r key error"); + wolfSSL_ECDSA_SIG_free(sig); + sig = NULL; + } + else if (SetIndividualExternal(&(sig->s), &sig_s)!=WOLFSSL_SUCCESS){ + WOLFSSL_MSG("ecdsa s key error"); + wolfSSL_ECDSA_SIG_free(sig); + sig = NULL; + } + + } + mp_free(&sig_r); + mp_free(&sig_s); + } + } + + if (initTmpRng) + wc_FreeRng(tmpRNG); +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); +#endif + + return sig; +} + +/* return code compliant with OpenSSL : + * 1 for a valid signature, 0 for an invalid signature and -1 on error + */ +int wolfSSL_ECDSA_do_verify(const unsigned char *d, int dlen, + const WOLFSSL_ECDSA_SIG *sig, WOLFSSL_EC_KEY *key) +{ + int check_sign = 0; + + WOLFSSL_ENTER("wolfSSL_ECDSA_do_verify"); + + if (d == NULL || sig == NULL || key == NULL || key->internal == NULL) { + WOLFSSL_MSG("wolfSSL_ECDSA_do_verify Bad arguments"); + return WOLFSSL_FATAL_ERROR; + } + + /* set internal key if not done */ + if (key->inSet == 0) + { + WOLFSSL_MSG("No EC key internal set, do it"); + + if (SetECKeyInternal(key) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetECKeyInternal failed"); + return WOLFSSL_FATAL_ERROR; + } + } + + if (wc_ecc_verify_hash_ex((mp_int*)sig->r->internal, + (mp_int*)sig->s->internal, d, dlen, &check_sign, + (ecc_key *)key->internal) != MP_OKAY) { + WOLFSSL_MSG("wc_ecc_verify_hash failed"); + return WOLFSSL_FATAL_ERROR; + } + else if (check_sign == 0) { + WOLFSSL_MSG("wc_ecc_verify_hash incorrect signature detected"); + return WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; +} + +WOLFSSL_ECDSA_SIG *wolfSSL_d2i_ECDSA_SIG(WOLFSSL_ECDSA_SIG **sig, + const unsigned char **pp, long len) +{ + WOLFSSL_ECDSA_SIG *s = NULL; + + if (pp == NULL) + return NULL; + + if (sig != NULL) + s = *sig; + if (s == NULL) { + s = wolfSSL_ECDSA_SIG_new(); + if (s == NULL) + return NULL; + } + + /* DecodeECC_DSA_Sig calls mp_init, so free these */ + mp_free((mp_int*)s->r->internal); + mp_free((mp_int*)s->s->internal); + + if (DecodeECC_DSA_Sig(*pp, (word32)len, (mp_int*)s->r->internal, + (mp_int*)s->s->internal) != MP_OKAY) { + if (sig == NULL || *sig == NULL) + wolfSSL_ECDSA_SIG_free(s); + return NULL; + } + + *pp += len; + if (sig != NULL) + *sig = s; + return s; +} + +int wolfSSL_i2d_ECDSA_SIG(const WOLFSSL_ECDSA_SIG *sig, unsigned char **pp) +{ + word32 len; + + if (sig == NULL) + return 0; + + /* ASN.1: SEQ + INT + INT + * ASN.1 Integer must be a positive value - prepend zero if number has + * top bit set. + */ + len = 2 + mp_leading_bit((mp_int*)sig->r->internal) + + mp_unsigned_bin_size((mp_int*)sig->r->internal) + + 2 + mp_leading_bit((mp_int*)sig->s->internal) + + mp_unsigned_bin_size((mp_int*)sig->s->internal); + /* Two bytes required for length if ASN.1 SEQ data greater than 127 bytes + * and less than 256 bytes. + */ + len = 1 + ((len > 127) ? 2 : 1) + len; + if (pp != NULL && *pp != NULL) { + if (StoreECC_DSA_Sig(*pp, &len, (mp_int*)sig->r->internal, + (mp_int*)sig->s->internal) != MP_OKAY) { + len = 0; + } + else + *pp += len; + } + + return (int)len; +} +/* End ECDSA_SIG */ + +/* Start ECDH */ +/* return code compliant with OpenSSL : + * length of computed key if success, -1 if error + */ +int wolfSSL_ECDH_compute_key(void *out, size_t outlen, + const WOLFSSL_EC_POINT *pub_key, + WOLFSSL_EC_KEY *ecdh, + void *(*KDF) (const void *in, size_t inlen, + void *out, size_t *outlen)) +{ + word32 len; + (void)KDF; + + (void)KDF; + + WOLFSSL_ENTER("wolfSSL_ECDH_compute_key"); + + if (out == NULL || pub_key == NULL || pub_key->internal == NULL || + ecdh == NULL || ecdh->internal == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return WOLFSSL_FATAL_ERROR; + } + + /* set internal key if not done */ + if (ecdh->inSet == 0) + { + WOLFSSL_MSG("No EC key internal set, do it"); + + if (SetECKeyInternal(ecdh) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetECKeyInternal failed"); + return WOLFSSL_FATAL_ERROR; + } + } + + len = (word32)outlen; + + if (wc_ecc_shared_secret_ssh((ecc_key*)ecdh->internal, + (ecc_point*)pub_key->internal, + (byte *)out, &len) != MP_OKAY) { + WOLFSSL_MSG("wc_ecc_shared_secret failed"); + return WOLFSSL_FATAL_ERROR; + } + + return len; +} +/* End ECDH */ + +#if !defined(NO_FILESYSTEM) +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +#ifndef NO_WOLFSSL_STUB +int wolfSSL_PEM_write_EC_PUBKEY(XFILE fp, WOLFSSL_EC_KEY *x) +{ + (void)fp; + (void)x; + WOLFSSL_STUB("PEM_write_EC_PUBKEY"); + WOLFSSL_MSG("wolfSSL_PEM_write_EC_PUBKEY not implemented"); + + return WOLFSSL_FAILURE; +} +#endif + +#endif /* NO_FILESYSTEM */ + +#if defined(WOLFSSL_KEY_GEN) + +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +#ifndef NO_WOLFSSL_STUB +int wolfSSL_PEM_write_bio_ECPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_EC_KEY* ecc, + const EVP_CIPHER* cipher, + unsigned char* passwd, int len, + pem_password_cb* cb, void* arg) +{ + (void)bio; + (void)ecc; + (void)cipher; + (void)passwd; + (void)len; + (void)cb; + (void)arg; + WOLFSSL_STUB("PEM_write_bio_ECPrivateKey"); + WOLFSSL_MSG("wolfSSL_PEM_write_bio_ECPrivateKey not implemented"); + + return WOLFSSL_FAILURE; +} +#endif + +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_PEM_write_mem_ECPrivateKey(WOLFSSL_EC_KEY* ecc, + const EVP_CIPHER* cipher, + unsigned char* passwd, int passwdSz, + unsigned char **pem, int *plen) +{ +#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM) + byte *derBuf, *tmp, *cipherInfo = NULL; + int der_max_len = 0, derSz = 0; + const int type = ECC_PRIVATEKEY_TYPE; + const char* header = NULL; + const char* footer = NULL; + + WOLFSSL_MSG("wolfSSL_PEM_write_mem_ECPrivateKey"); + + if (pem == NULL || plen == NULL || ecc == NULL || ecc->internal == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return WOLFSSL_FAILURE; + } + + if (wc_PemGetHeaderFooter(type, &header, &footer) != 0) + return WOLFSSL_FAILURE; + + if (ecc->inSet == 0) { + WOLFSSL_MSG("No ECC internal set, do it"); + + if (SetECKeyInternal(ecc) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetDsaInternal failed"); + return WOLFSSL_FAILURE; + } + } + + /* 4 > size of pub, priv + ASN.1 additional informations + */ + der_max_len = 4 * wc_ecc_size((ecc_key*)ecc->internal) + AES_BLOCK_SIZE; + + derBuf = (byte*)XMALLOC(der_max_len, NULL, DYNAMIC_TYPE_DER); + if (derBuf == NULL) { + WOLFSSL_MSG("malloc failed"); + return WOLFSSL_FAILURE; + } + + /* Key to DER */ + derSz = wc_EccKeyToDer((ecc_key*)ecc->internal, derBuf, der_max_len); + if (derSz < 0) { + WOLFSSL_MSG("wc_DsaKeyToDer failed"); + XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); + return WOLFSSL_FAILURE; + } + + /* encrypt DER buffer if required */ + if (passwd != NULL && passwdSz > 0 && cipher != NULL) { + int ret; + + ret = EncryptDerKey(derBuf, &derSz, cipher, + passwd, passwdSz, &cipherInfo); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("EncryptDerKey failed"); + XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); + return ret; + } + + /* tmp buffer with a max size */ + *plen = (derSz * 2) + (int)XSTRLEN(header) + 1 + + (int)XSTRLEN(footer) + 1 + HEADER_ENCRYPTED_KEY_SIZE; + } + else { /* tmp buffer with a max size */ + *plen = (derSz * 2) + (int)XSTRLEN(header) + 1 + + (int)XSTRLEN(footer) + 1; + } + + tmp = (byte*)XMALLOC(*plen, NULL, DYNAMIC_TYPE_PEM); + if (tmp == NULL) { + WOLFSSL_MSG("malloc failed"); + XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); + if (cipherInfo != NULL) + XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING); + return WOLFSSL_FAILURE; + } + + /* DER to PEM */ + *plen = wc_DerToPemEx(derBuf, derSz, tmp, *plen, cipherInfo, type); + if (*plen <= 0) { + WOLFSSL_MSG("wc_DerToPemEx failed"); + XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); + XFREE(tmp, NULL, DYNAMIC_TYPE_PEM); + if (cipherInfo != NULL) + XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING); + return WOLFSSL_FAILURE; + } + XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); + if (cipherInfo != NULL) + XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING); + + *pem = (byte*)XMALLOC((*plen)+1, NULL, DYNAMIC_TYPE_KEY); + if (*pem == NULL) { + WOLFSSL_MSG("malloc failed"); + XFREE(tmp, NULL, DYNAMIC_TYPE_PEM); + return WOLFSSL_FAILURE; + } + XMEMSET(*pem, 0, (*plen)+1); + + if (XMEMCPY(*pem, tmp, *plen) == NULL) { + WOLFSSL_MSG("XMEMCPY failed"); + XFREE(pem, NULL, DYNAMIC_TYPE_KEY); + XFREE(tmp, NULL, DYNAMIC_TYPE_PEM); + return WOLFSSL_FAILURE; + } + XFREE(tmp, NULL, DYNAMIC_TYPE_PEM); + + return WOLFSSL_SUCCESS; +#else + (void)ecc; + (void)cipher; + (void)passwd; + (void)passwdSz; + (void)pem; + (void)plen; + return WOLFSSL_FAILURE; +#endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */ +} + +#ifndef NO_FILESYSTEM +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_PEM_write_ECPrivateKey(XFILE fp, WOLFSSL_EC_KEY *ecc, + const EVP_CIPHER *enc, + unsigned char *kstr, int klen, + pem_password_cb *cb, void *u) +{ + byte *pem; + int plen, ret; + + (void)cb; + (void)u; + + WOLFSSL_MSG("wolfSSL_PEM_write_ECPrivateKey"); + + if (fp == XBADFILE || ecc == NULL || ecc->internal == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return WOLFSSL_FAILURE; + } + + ret = wolfSSL_PEM_write_mem_ECPrivateKey(ecc, enc, kstr, klen, &pem, &plen); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_PEM_write_mem_ECPrivateKey failed"); + return WOLFSSL_FAILURE; + } + + ret = (int)XFWRITE(pem, plen, 1, fp); + if (ret != 1) { + WOLFSSL_MSG("ECC private key file write failed"); + return WOLFSSL_FAILURE; + } + + XFREE(pem, NULL, DYNAMIC_TYPE_KEY); + return WOLFSSL_SUCCESS; +} + +#endif /* NO_FILESYSTEM */ +#endif /* defined(WOLFSSL_KEY_GEN) */ + +#endif /* HAVE_ECC */ + + +#ifndef NO_DSA + +#if defined(WOLFSSL_KEY_GEN) + +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_PEM_write_bio_DSAPrivateKey(WOLFSSL_BIO* bio, WOLFSSL_DSA* dsa, + const EVP_CIPHER* cipher, + unsigned char* passwd, int len, + pem_password_cb* cb, void* arg) +{ + (void)bio; + (void)dsa; + (void)cipher; + (void)passwd; + (void)len; + (void)cb; + (void)arg; + + WOLFSSL_MSG("wolfSSL_PEM_write_bio_DSAPrivateKey not implemented"); + + return WOLFSSL_FAILURE; +} + +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_PEM_write_mem_DSAPrivateKey(WOLFSSL_DSA* dsa, + const EVP_CIPHER* cipher, + unsigned char* passwd, int passwdSz, + unsigned char **pem, int *plen) +{ +#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM) + byte *derBuf, *tmp, *cipherInfo = NULL; + int der_max_len = 0, derSz = 0; + const int type = DSA_PRIVATEKEY_TYPE; + const char* header = NULL; + const char* footer = NULL; + + WOLFSSL_MSG("wolfSSL_PEM_write_mem_DSAPrivateKey"); + + if (pem == NULL || plen == NULL || dsa == NULL || dsa->internal == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return WOLFSSL_FAILURE; + } + + if (wc_PemGetHeaderFooter(type, &header, &footer) != 0) + return WOLFSSL_FAILURE; + + if (dsa->inSet == 0) { + WOLFSSL_MSG("No DSA internal set, do it"); + + if (SetDsaInternal(dsa) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetDsaInternal failed"); + return WOLFSSL_FAILURE; + } + } + + /* 4 > size of pub, priv, p, q, g + ASN.1 additional informations + */ + der_max_len = 4 * wolfSSL_BN_num_bytes(dsa->g) + AES_BLOCK_SIZE; + + derBuf = (byte*)XMALLOC(der_max_len, NULL, DYNAMIC_TYPE_DER); + if (derBuf == NULL) { + WOLFSSL_MSG("malloc failed"); + return WOLFSSL_FAILURE; + } + + /* Key to DER */ + derSz = wc_DsaKeyToDer((DsaKey*)dsa->internal, derBuf, der_max_len); + if (derSz < 0) { + WOLFSSL_MSG("wc_DsaKeyToDer failed"); + XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); + return WOLFSSL_FAILURE; + } + + /* encrypt DER buffer if required */ + if (passwd != NULL && passwdSz > 0 && cipher != NULL) { + int ret; + + ret = EncryptDerKey(derBuf, &derSz, cipher, + passwd, passwdSz, &cipherInfo); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("EncryptDerKey failed"); + XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); + return ret; + } + + /* tmp buffer with a max size */ + *plen = (derSz * 2) + (int)XSTRLEN(header) + 1 + + (int)XSTRLEN(footer) + 1 + HEADER_ENCRYPTED_KEY_SIZE; + } + else { /* tmp buffer with a max size */ + *plen = (derSz * 2) + (int)XSTRLEN(header) + 1 + + (int)XSTRLEN(footer) + 1; + } + + tmp = (byte*)XMALLOC(*plen, NULL, DYNAMIC_TYPE_PEM); + if (tmp == NULL) { + WOLFSSL_MSG("malloc failed"); + XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); + if (cipherInfo != NULL) + XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING); + return WOLFSSL_FAILURE; + } + + /* DER to PEM */ + *plen = wc_DerToPemEx(derBuf, derSz, tmp, *plen, cipherInfo, type); + if (*plen <= 0) { + WOLFSSL_MSG("wc_DerToPemEx failed"); + XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); + XFREE(tmp, NULL, DYNAMIC_TYPE_PEM); + if (cipherInfo != NULL) + XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING); + return WOLFSSL_FAILURE; + } + XFREE(derBuf, NULL, DYNAMIC_TYPE_DER); + if (cipherInfo != NULL) + XFREE(cipherInfo, NULL, DYNAMIC_TYPE_STRING); + + *pem = (byte*)XMALLOC((*plen)+1, NULL, DYNAMIC_TYPE_KEY); + if (*pem == NULL) { + WOLFSSL_MSG("malloc failed"); + XFREE(tmp, NULL, DYNAMIC_TYPE_PEM); + return WOLFSSL_FAILURE; + } + XMEMSET(*pem, 0, (*plen)+1); + + if (XMEMCPY(*pem, tmp, *plen) == NULL) { + WOLFSSL_MSG("XMEMCPY failed"); + XFREE(pem, NULL, DYNAMIC_TYPE_KEY); + XFREE(tmp, NULL, DYNAMIC_TYPE_PEM); + return WOLFSSL_FAILURE; + } + XFREE(tmp, NULL, DYNAMIC_TYPE_PEM); + + return WOLFSSL_SUCCESS; +#else + (void)dsa; + (void)cipher; + (void)passwd; + (void)passwdSz; + (void)pem; + (void)plen; + return WOLFSSL_FAILURE; +#endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */ +} + +#ifndef NO_FILESYSTEM +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +int wolfSSL_PEM_write_DSAPrivateKey(XFILE fp, WOLFSSL_DSA *dsa, + const EVP_CIPHER *enc, + unsigned char *kstr, int klen, + pem_password_cb *cb, void *u) +{ + byte *pem; + int plen, ret; + + (void)cb; + (void)u; + + WOLFSSL_MSG("wolfSSL_PEM_write_DSAPrivateKey"); + + if (fp == XBADFILE || dsa == NULL || dsa->internal == NULL) { + WOLFSSL_MSG("Bad function arguments"); + return WOLFSSL_FAILURE; + } + + ret = wolfSSL_PEM_write_mem_DSAPrivateKey(dsa, enc, kstr, klen, &pem, &plen); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_PEM_write_mem_DSAPrivateKey failed"); + return WOLFSSL_FAILURE; + } + + ret = (int)XFWRITE(pem, plen, 1, fp); + if (ret != 1) { + WOLFSSL_MSG("DSA private key file write failed"); + return WOLFSSL_FAILURE; + } + + XFREE(pem, NULL, DYNAMIC_TYPE_KEY); + return WOLFSSL_SUCCESS; +} + +#endif /* NO_FILESYSTEM */ +#endif /* defined(WOLFSSL_KEY_GEN) */ + +#ifndef NO_FILESYSTEM +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +#ifndef NO_WOLFSSL_STUB +int wolfSSL_PEM_write_DSA_PUBKEY(XFILE fp, WOLFSSL_DSA *x) +{ + (void)fp; + (void)x; + WOLFSSL_STUB("PEM_write_DSA_PUBKEY"); + WOLFSSL_MSG("wolfSSL_PEM_write_DSA_PUBKEY not implemented"); + + return WOLFSSL_FAILURE; +} +#endif +#endif /* NO_FILESYSTEM */ + +#endif /* #ifndef NO_DSA */ + +static int pem_read_bio_key(WOLFSSL_BIO* bio, pem_password_cb* cb, void* pass, + int keyType, int* eccFlag, DerBuffer** der) +{ +#ifdef WOLFSSL_SMALL_STACK + EncryptedInfo* info = NULL; +#else + EncryptedInfo info[1]; +#endif /* WOLFSSL_SMALL_STACK */ + pem_password_cb* localCb = cb; + + char* mem = NULL; + int memSz = 0; + int ret; + + if ((ret = wolfSSL_BIO_pending(bio)) > 0) { + memSz = ret; + mem = (char*)XMALLOC(memSz, bio->heap, DYNAMIC_TYPE_OPENSSL); + if (mem == NULL) { + WOLFSSL_MSG("Memory error"); + ret = MEMORY_E; + } + if (ret >= 0) { + if ((ret = wolfSSL_BIO_read(bio, mem, memSz)) <= 0) { + XFREE(mem, bio->heap, DYNAMIC_TYPE_OPENSSL); + mem = NULL; + ret = MEMORY_E; + } + } + } + else if (bio->type == WOLFSSL_BIO_FILE) { + int sz = 100; /* read from file by 100 byte chunks */ + int idx = 0; + char* tmp = (char*)XMALLOC(sz, bio->heap, DYNAMIC_TYPE_OPENSSL); + + memSz = 0; + if (tmp == NULL) { + WOLFSSL_MSG("Memory error"); + ret = MEMORY_E; + } + + while (ret >= 0 && (sz = wolfSSL_BIO_read(bio, tmp, sz)) > 0) { + char* newMem; + if (memSz + sz < 0) { + /* sanity check */ + break; + } + newMem = (char*)XREALLOC(mem, memSz + sz, bio->heap, + DYNAMIC_TYPE_OPENSSL); + if (newMem == NULL) { + WOLFSSL_MSG("Memory error"); + XFREE(mem, bio->heap, DYNAMIC_TYPE_OPENSSL); + mem = NULL; + XFREE(tmp, bio->heap, DYNAMIC_TYPE_OPENSSL); + tmp = NULL; + ret = MEMORY_E; + break; + } + mem = newMem; + XMEMCPY(mem + idx, tmp, sz); + memSz += sz; + idx += sz; + sz = 100; /* read another 100 byte chunk from file */ + } + XFREE(tmp, bio->heap, DYNAMIC_TYPE_OPENSSL); + tmp = NULL; + if (memSz <= 0) { + WOLFSSL_MSG("No data to read from bio"); + if (mem != NULL) { + XFREE(mem, bio->heap, DYNAMIC_TYPE_OPENSSL); + mem = NULL; + } + ret = BUFFER_E; + } + } + else { + WOLFSSL_MSG("No data to read from bio"); + ret = NOT_COMPILED_IN; + } + +#ifdef WOLFSSL_SMALL_STACK + if (ret >= 0) { + info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (info == NULL) { + WOLFSSL_MSG("Error getting memory for EncryptedInfo structure"); + XFREE(mem, bio->heap, DYNAMIC_TYPE_OPENSSL); + mem = NULL; + ret = MEMORY_E; + } + } +#endif + + if (ret >= 0) { + XMEMSET(info, 0, sizeof(EncryptedInfo)); + info->passwd_cb = localCb; + info->passwd_userdata = pass; + ret = PemToDer((const unsigned char*)mem, memSz, keyType, der, + NULL, info, eccFlag); + + if (ret < 0) { + WOLFSSL_MSG("Bad Pem To Der"); + } + else { + /* write left over data back to bio */ + if ((memSz - (int)info->consumed) > 0 && + bio->type != WOLFSSL_BIO_FILE) { + if (wolfSSL_BIO_write(bio, mem + (int)info->consumed, + memSz - (int)info->consumed) <= 0) { + WOLFSSL_MSG("Unable to advance bio read pointer"); + } + } + } + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(info, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(mem, bio->heap, DYNAMIC_TYPE_OPENSSL); + + return ret; +} + +WOLFSSL_EVP_PKEY* wolfSSL_PEM_read_bio_PrivateKey(WOLFSSL_BIO* bio, + WOLFSSL_EVP_PKEY** key, + pem_password_cb* cb, + void* pass) +{ + WOLFSSL_EVP_PKEY* pkey = NULL; + DerBuffer* der = NULL; + int eccFlag = 0; + + WOLFSSL_ENTER("wolfSSL_PEM_read_bio_PrivateKey"); + + if (bio == NULL) + return pkey; + + if (pem_read_bio_key(bio, cb, pass, PRIVATEKEY_TYPE, &eccFlag, &der) >= 0) { + int type; + const unsigned char* ptr = der->buffer; + + if (eccFlag) + type = EVP_PKEY_EC; + else + type = EVP_PKEY_RSA; + + /* handle case where reuse is attempted */ + if (key != NULL && *key != NULL) + pkey = *key; + + wolfSSL_d2i_PrivateKey(type, &pkey, &ptr, der->length); + if (pkey == NULL) { + WOLFSSL_MSG("Error loading DER buffer into WOLFSSL_EVP_PKEY"); + } + } + + FreeDer(&der); + + if (key != NULL && pkey != NULL) + *key = pkey; + + WOLFSSL_LEAVE("wolfSSL_PEM_read_bio_PrivateKey", 0); + + return pkey; +} + +WOLFSSL_EVP_PKEY *wolfSSL_PEM_read_bio_PUBKEY(WOLFSSL_BIO* bio, + WOLFSSL_EVP_PKEY **key, + pem_password_cb *cb, void *pass) +{ + WOLFSSL_EVP_PKEY* pkey = NULL; + DerBuffer* der = NULL; + int eccFlag = 0; + + WOLFSSL_ENTER("wolfSSL_PEM_read_bio_PUBKEY"); + + if (bio == NULL) + return pkey; + + if (pem_read_bio_key(bio, cb, pass, PUBLICKEY_TYPE, &eccFlag, &der) >= 0) { + unsigned char* ptr = der->buffer; + + /* handle case where reuse is attempted */ + if (key != NULL && *key != NULL) + pkey = *key; + + pkey = wolfSSL_d2i_PUBKEY(&pkey, &ptr, der->length); + if (pkey == NULL) { + WOLFSSL_MSG("Error loading DER buffer into WOLFSSL_EVP_PKEY"); + } + } + + FreeDer(&der); + + if (key != NULL && pkey != NULL) + *key = pkey; + + WOLFSSL_LEAVE("wolfSSL_PEM_read_bio_PrivateKey", 0); + + return pkey; +} + + +#ifndef NO_RSA +/* Uses the same format of input as wolfSSL_PEM_read_bio_PrivateKey but expects + * the results to be an RSA key. + * + * bio structure to read RSA private key from + * rsa if not null is then set to the result + * cb password callback for reading PEM + * pass password string + * + * returns a pointer to a new WOLFSSL_RSA structure on success and NULL on fail + */ +WOLFSSL_RSA* wolfSSL_PEM_read_bio_RSAPrivateKey(WOLFSSL_BIO* bio, + WOLFSSL_RSA** rsa, pem_password_cb* cb, void* pass) +{ + WOLFSSL_EVP_PKEY* pkey; + WOLFSSL_RSA* local; + + pkey = wolfSSL_PEM_read_bio_PrivateKey(bio, NULL, cb, pass); + if (pkey == NULL) { + return NULL; + } + + /* Since the WOLFSSL_RSA structure is being taken from WOLFSSL_EVP_PEKY the + * flag indicating that the WOLFSSL_RSA structure is owned should be FALSE + * to avoid having it free'd */ + pkey->ownRsa = 0; + local = pkey->rsa; + if (rsa != NULL) { + *rsa = local; + } + + wolfSSL_EVP_PKEY_free(pkey); + return local; +} +#endif /* !NO_RSA */ + + +/* return of pkey->type which will be EVP_PKEY_RSA for example. + * + * type type of EVP_PKEY + * + * returns type or if type is not found then NID_undef + */ +int wolfSSL_EVP_PKEY_type(int type) +{ + WOLFSSL_MSG("wolfSSL_EVP_PKEY_type"); + + switch (type) { + #ifdef OPENSSL_EXTRA + case EVP_PKEY_RSA: + return EVP_PKEY_RSA; + case EVP_PKEY_DSA: + return EVP_PKEY_DSA; + case EVP_PKEY_EC: + return EVP_PKEY_EC; + #endif + default: + return NID_undef; + } +} + + +int wolfSSL_EVP_PKEY_id(const EVP_PKEY *pkey) +{ + if (pkey != NULL) + return pkey->type; + return 0; +} + + +int wolfSSL_EVP_PKEY_base_id(const EVP_PKEY *pkey) +{ + if (pkey == NULL) + return NID_undef; + return wolfSSL_EVP_PKEY_type(pkey->type); +} + + +#if !defined(NO_FILESYSTEM) +WOLFSSL_EVP_PKEY *wolfSSL_PEM_read_PUBKEY(XFILE fp, EVP_PKEY **x, + pem_password_cb *cb, void *u) +{ + (void)fp; + (void)x; + (void)cb; + (void)u; + + WOLFSSL_MSG("wolfSSL_PEM_read_PUBKEY not implemented"); + + return NULL; +} +#endif /* NO_FILESYSTEM */ + +#ifndef NO_RSA + +#if !defined(NO_FILESYSTEM) +#ifndef NO_WOLFSSL_STUB +WOLFSSL_RSA *wolfSSL_PEM_read_RSAPublicKey(XFILE fp, WOLFSSL_RSA **x, + pem_password_cb *cb, void *u) +{ + (void)fp; + (void)x; + (void)cb; + (void)u; + WOLFSSL_STUB("PEM_read_RSAPublicKey"); + WOLFSSL_MSG("wolfSSL_PEM_read_RSAPublicKey not implemented"); + + return NULL; +} +#endif +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +#ifndef NO_WOLFSSL_STUB +int wolfSSL_PEM_write_RSAPublicKey(XFILE fp, WOLFSSL_RSA *x) +{ + (void)fp; + (void)x; + WOLFSSL_STUB("PEM_write_RSAPublicKey"); + WOLFSSL_MSG("wolfSSL_PEM_write_RSAPublicKey not implemented"); + + return WOLFSSL_FAILURE; +} +#endif + +/* return code compliant with OpenSSL : + * 1 if success, 0 if error + */ +#ifndef NO_WOLFSSL_STUB +int wolfSSL_PEM_write_RSA_PUBKEY(XFILE fp, WOLFSSL_RSA *x) +{ + (void)fp; + (void)x; + WOLFSSL_STUB("PEM_write_RSA_PUBKEY"); + WOLFSSL_MSG("wolfSSL_PEM_write_RSA_PUBKEY not implemented"); + + return WOLFSSL_FAILURE; +} +#endif + +#endif /* NO_FILESYSTEM */ + +WOLFSSL_RSA *wolfSSL_d2i_RSAPublicKey(WOLFSSL_RSA **r, const unsigned char **pp, + long len) +{ + WOLFSSL_RSA *rsa = NULL; + + WOLFSSL_ENTER("d2i_RSAPublicKey"); + + if (pp == NULL) { + WOLFSSL_MSG("Bad argument"); + return NULL; + } + if ((rsa = wolfSSL_RSA_new()) == NULL) { + WOLFSSL_MSG("RSA_new failed"); + return NULL; + } + + if (wolfSSL_RSA_LoadDer_ex(rsa, *pp, (int)len, WOLFSSL_RSA_LOAD_PUBLIC) + != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("RSA_LoadDer failed"); + wolfSSL_RSA_free(rsa); + rsa = NULL; + } + if (r != NULL) + *r = rsa; + + return rsa; +} + +/* Converts an RSA private key from DER format to an RSA structure. +Returns pointer to the RSA structure on success and NULL if error. */ +WOLFSSL_RSA *wolfSSL_d2i_RSAPrivateKey(WOLFSSL_RSA **r, + const unsigned char **derBuf, long derSz) +{ + WOLFSSL_RSA *rsa = NULL; + + WOLFSSL_ENTER("wolfSSL_d2i_RSAPrivateKey"); + + /* check for bad functions arguments */ + if (derBuf == NULL) { + WOLFSSL_MSG("Bad argument"); + return NULL; + } + if ((rsa = wolfSSL_RSA_new()) == NULL) { + WOLFSSL_MSG("RSA_new failed"); + return NULL; + } + + if (wolfSSL_RSA_LoadDer_ex(rsa, *derBuf, (int)derSz, + WOLFSSL_RSA_LOAD_PRIVATE) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("RSA_LoadDer failed"); + wolfSSL_RSA_free(rsa); + rsa = NULL; + } + if (r != NULL) + *r = rsa; + + return rsa; +} + +#if !defined(HAVE_FAST_RSA) +/* Converts an internal RSA structure to DER format. + * If "pp" is null then buffer size only is returned. + * If "*pp" is null then a created buffer is set in *pp and the caller is + * responsible for free'ing it. + * Returns size of DER on success and WOLFSSL_FAILURE if error + */ +int wolfSSL_i2d_RSAPrivateKey(WOLFSSL_RSA *rsa, unsigned char **pp) +{ +#if defined(WOLFSSL_KEY_GEN) + byte* der = NULL; + int derMax; + int ret; + int i; + + WOLFSSL_ENTER("wolfSSL_i2d_RSAPrivateKey"); + + /* check for bad functions arguments */ + if (rsa == NULL) { + WOLFSSL_MSG("Bad Function Arguments"); + return BAD_FUNC_ARG; + } + + if (rsa->inSet == 0) { + if ((ret = SetRsaInternal(rsa)) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetRsaInternal() Failed"); + return ret; + } + } + + /* 5 > size of n, d, p, q, d%(p-1), d(q-1), 1/q%p, e + ASN.1 additional + * informations + */ + derMax = 5 * wolfSSL_RSA_size(rsa) + AES_BLOCK_SIZE; + + der = (byte*)XMALLOC(derMax, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (der == NULL) { + WOLFSSL_MSG("Malloc failed"); + return WOLFSSL_FAILURE; + } + + /* RSA key to DER */ + if ((ret = wc_RsaKeyToDer((RsaKey *)rsa->internal, der, derMax)) < 0) { + WOLFSSL_MSG("wc_RsaKeyToDer() failed"); + XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER); + der = NULL; + return ret; + } + + if (pp != NULL) { + if (*pp == NULL) { + /* create buffer and return it */ + *pp = (unsigned char*)XMALLOC(ret, NULL, DYNAMIC_TYPE_OPENSSL); + if (*pp == NULL) { + return WOLFSSL_FATAL_ERROR; + } + XMEMCPY(*pp, der, ret); + } + else { + /* ret is the size of the DER buffer */ + for (i = 0; i < ret; i++) { + *(*pp + i) = *(der + i); + } + *pp += ret; + } + } + XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return ret; /* returns size of DER if successful */ +#else + (void)rsa; + (void)pp; + WOLFSSL_MSG("Error, WOLFSSL_KEY_GEN not defined"); + return WOLFSSL_FAILURE; +#endif /* WOLFSSL_KEY_GEN */ +} + + +int wolfSSL_i2d_RSAPublicKey(WOLFSSL_RSA *rsa, const unsigned char **pp) +{ + byte *der; + int derLen; + int ret; + + WOLFSSL_ENTER("i2d_RSAPublicKey"); + if (rsa == NULL) + return WOLFSSL_FATAL_ERROR; + + if (rsa->inSet == 0) { + if ((ret = SetRsaInternal(rsa)) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetRsaInternal Failed"); + return ret; + } + } + if ((derLen = RsaPublicKeyDerSize((RsaKey *)rsa->internal, 1)) < 0) + return WOLFSSL_FATAL_ERROR; + der = (byte*)XMALLOC(derLen, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (der == NULL) { + return WOLFSSL_FATAL_ERROR; + } + if ((ret = wc_RsaKeyToPublicDer((RsaKey *)rsa->internal, der, derLen)) < 0){ + WOLFSSL_MSG("RsaKeyToPublicDer failed"); + if(der != NULL) + XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + if ((pp != NULL) && (ret >= 0)) + *pp = der; + else + XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return ret; +} +#endif /* #if !defined(HAVE_FAST_RSA) */ + +#endif /* !NO_RSA */ +#endif /* OPENSSL_EXTRA */ + +#if !defined(NO_RSA) && (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) +/* return WOLFSSL_SUCCESS if success, WOLFSSL_FATAL_ERROR if error */ +int wolfSSL_RSA_LoadDer(WOLFSSL_RSA* rsa, const unsigned char* derBuf, int derSz) +{ + return wolfSSL_RSA_LoadDer_ex(rsa, derBuf, derSz, WOLFSSL_RSA_LOAD_PRIVATE); +} + + +int wolfSSL_RSA_LoadDer_ex(WOLFSSL_RSA* rsa, const unsigned char* derBuf, + int derSz, int opt) +{ + + word32 idx = 0; + int ret; + + WOLFSSL_ENTER("wolfSSL_RSA_LoadDer"); + + if (rsa == NULL || rsa->internal == NULL || derBuf == NULL || derSz <= 0) { + WOLFSSL_MSG("Bad function arguments"); + return WOLFSSL_FATAL_ERROR; + } + + if (opt == WOLFSSL_RSA_LOAD_PRIVATE) { + ret = wc_RsaPrivateKeyDecode(derBuf, &idx, (RsaKey*)rsa->internal, derSz); + } + else { + ret = wc_RsaPublicKeyDecode(derBuf, &idx, (RsaKey*)rsa->internal, derSz); + } + + if (ret < 0) { + if (opt == WOLFSSL_RSA_LOAD_PRIVATE) { + WOLFSSL_MSG("RsaPrivateKeyDecode failed"); + } + else { + WOLFSSL_MSG("RsaPublicKeyDecode failed"); + } + return SSL_FATAL_ERROR; + } + + if (SetRsaExternal(rsa) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetRsaExternal failed"); + return WOLFSSL_FATAL_ERROR; + } + + rsa->inSet = 1; + + return WOLFSSL_SUCCESS; +} +#endif /* NO_RSA */ + +#ifdef OPENSSL_EXTRA +#ifndef NO_DSA +/* return WOLFSSL_SUCCESS if success, WOLFSSL_FATAL_ERROR if error */ +int wolfSSL_DSA_LoadDer(WOLFSSL_DSA* dsa, const unsigned char* derBuf, int derSz) +{ + word32 idx = 0; + int ret; + + WOLFSSL_ENTER("wolfSSL_DSA_LoadDer"); + + if (dsa == NULL || dsa->internal == NULL || derBuf == NULL || derSz <= 0) { + WOLFSSL_MSG("Bad function arguments"); + return WOLFSSL_FATAL_ERROR; + } + + ret = DsaPrivateKeyDecode(derBuf, &idx, (DsaKey*)dsa->internal, derSz); + if (ret < 0) { + WOLFSSL_MSG("DsaPrivateKeyDecode failed"); + return WOLFSSL_FATAL_ERROR; + } + + if (SetDsaExternal(dsa) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetDsaExternal failed"); + return WOLFSSL_FATAL_ERROR; + } + + dsa->inSet = 1; + + return WOLFSSL_SUCCESS; +} +#endif /* NO_DSA */ + +#ifdef HAVE_ECC +/* return WOLFSSL_SUCCESS if success, WOLFSSL_FATAL_ERROR if error */ +int wolfSSL_EC_KEY_LoadDer(WOLFSSL_EC_KEY* key, const unsigned char* derBuf, + int derSz) +{ + return wolfSSL_EC_KEY_LoadDer_ex(key, derBuf, derSz, + WOLFSSL_EC_KEY_LOAD_PRIVATE); +} + +int wolfSSL_EC_KEY_LoadDer_ex(WOLFSSL_EC_KEY* key, const unsigned char* derBuf, + int derSz, int opt) +{ + word32 idx = 0; + int ret; + + WOLFSSL_ENTER("wolfSSL_EC_KEY_LoadDer"); + + if (key == NULL || key->internal == NULL || derBuf == NULL || derSz <= 0) { + WOLFSSL_MSG("Bad function arguments"); + return WOLFSSL_FATAL_ERROR; + } + + if (opt == WOLFSSL_EC_KEY_LOAD_PRIVATE) { + ret = wc_EccPrivateKeyDecode(derBuf, &idx, (ecc_key*)key->internal, + derSz); + } + else { + ret = wc_EccPublicKeyDecode(derBuf, &idx, (ecc_key*)key->internal, + derSz); + } + if (ret < 0) { + if (opt == WOLFSSL_EC_KEY_LOAD_PRIVATE) { + WOLFSSL_MSG("wc_EccPrivateKeyDecode failed"); + } + else { + WOLFSSL_MSG("wc_EccPublicKeyDecode failed"); + } + return WOLFSSL_FATAL_ERROR; + } + + if (SetECKeyExternal(key) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("SetECKeyExternal failed"); + return WOLFSSL_FATAL_ERROR; + } + + key->inSet = 1; + + return WOLFSSL_SUCCESS; +} +#endif /* HAVE_ECC */ + + +#endif /* OPENSSL_EXTRA */ + + +#ifdef WOLFSSL_ALT_CERT_CHAINS +int wolfSSL_is_peer_alt_cert_chain(const WOLFSSL* ssl) +{ + int isUsing = 0; + if (ssl) + isUsing = ssl->options.usingAltCertChain; + return isUsing; +} +#endif /* WOLFSSL_ALT_CERT_CHAINS */ + + +#ifdef SESSION_CERTS + +#ifdef WOLFSSL_ALT_CERT_CHAINS +/* Get peer's alternate certificate chain */ +WOLFSSL_X509_CHAIN* wolfSSL_get_peer_alt_chain(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_get_peer_alt_chain"); + if (ssl) + return &ssl->session.altChain; + + return 0; +} +#endif /* WOLFSSL_ALT_CERT_CHAINS */ + + +/* Get peer's certificate chain */ +WOLFSSL_X509_CHAIN* wolfSSL_get_peer_chain(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_get_peer_chain"); + if (ssl) + return &ssl->session.chain; + + return 0; +} + + +/* Get peer's certificate chain total count */ +int wolfSSL_get_chain_count(WOLFSSL_X509_CHAIN* chain) +{ + WOLFSSL_ENTER("wolfSSL_get_chain_count"); + if (chain) + return chain->count; + + return 0; +} + + +/* Get peer's ASN.1 DER certificate at index (idx) length in bytes */ +int wolfSSL_get_chain_length(WOLFSSL_X509_CHAIN* chain, int idx) +{ + WOLFSSL_ENTER("wolfSSL_get_chain_length"); + if (chain) + return chain->certs[idx].length; + + return 0; +} + + +/* Get peer's ASN.1 DER certificate at index (idx) */ +byte* wolfSSL_get_chain_cert(WOLFSSL_X509_CHAIN* chain, int idx) +{ + WOLFSSL_ENTER("wolfSSL_get_chain_cert"); + if (chain) + return chain->certs[idx].buffer; + + return 0; +} + + +/* Get peer's wolfSSL X509 certificate at index (idx) */ +WOLFSSL_X509* wolfSSL_get_chain_X509(WOLFSSL_X509_CHAIN* chain, int idx) +{ + int ret; + WOLFSSL_X509* x509 = NULL; +#ifdef WOLFSSL_SMALL_STACK + DecodedCert* cert = NULL; +#else + DecodedCert cert[1]; +#endif + + WOLFSSL_ENTER("wolfSSL_get_chain_X509"); + if (chain != NULL) { + #ifdef WOLFSSL_SMALL_STACK + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, + DYNAMIC_TYPE_DCERT); + if (cert != NULL) + #endif + { + InitDecodedCert(cert, chain->certs[idx].buffer, + chain->certs[idx].length, NULL); + + if ((ret = ParseCertRelative(cert, CERT_TYPE, 0, NULL)) != 0) { + WOLFSSL_MSG("Failed to parse cert"); + } + else { + x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), NULL, + DYNAMIC_TYPE_X509); + if (x509 == NULL) { + WOLFSSL_MSG("Failed alloc X509"); + } + else { + InitX509(x509, 1, NULL); + + if ((ret = CopyDecodedToX509(x509, cert)) != 0) { + WOLFSSL_MSG("Failed to copy decoded"); + wolfSSL_X509_free(x509); + x509 = NULL; + } + } + } + + FreeDecodedCert(cert); + #ifdef WOLFSSL_SMALL_STACK + XFREE(cert, NULL, DYNAMIC_TYPE_DCERT); + #endif + } + } + (void)ret; + + return x509; +} + + +/* Get peer's PEM certificate at index (idx), output to buffer if inLen big + enough else return error (-1). If buffer is NULL only calculate + outLen. Output length is in *outLen WOLFSSL_SUCCESS on ok */ +int wolfSSL_get_chain_cert_pem(WOLFSSL_X509_CHAIN* chain, int idx, + unsigned char* buf, int inLen, int* outLen) +{ +#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM) + const char* header = NULL; + const char* footer = NULL; + int headerLen; + int footerLen; + int i; + int err; + word32 szNeeded = 0; + + WOLFSSL_ENTER("wolfSSL_get_chain_cert_pem"); + if (!chain || !outLen || idx < 0 || idx >= wolfSSL_get_chain_count(chain)) + return BAD_FUNC_ARG; + + err = wc_PemGetHeaderFooter(CERT_TYPE, &header, &footer); + if (err != 0) + return err; + + headerLen = (int)XSTRLEN(header); + footerLen = (int)XSTRLEN(footer); + + /* Null output buffer return size needed in outLen */ + if(!buf) { + if(Base64_Encode(chain->certs[idx].buffer, chain->certs[idx].length, + NULL, &szNeeded) != LENGTH_ONLY_E) + return WOLFSSL_FAILURE; + *outLen = szNeeded + headerLen + footerLen; + return LENGTH_ONLY_E; + } + + /* don't even try if inLen too short */ + if (inLen < headerLen + footerLen + chain->certs[idx].length) + return BAD_FUNC_ARG; + + /* header */ + if (XMEMCPY(buf, header, headerLen) == NULL) + return WOLFSSL_FATAL_ERROR; + + i = headerLen; + + /* body */ + *outLen = inLen; /* input to Base64_Encode */ + if ( (err = Base64_Encode(chain->certs[idx].buffer, + chain->certs[idx].length, buf + i, (word32*)outLen)) < 0) + return err; + i += *outLen; + + /* footer */ + if ( (i + footerLen) > inLen) + return BAD_FUNC_ARG; + if (XMEMCPY(buf + i, footer, footerLen) == NULL) + return WOLFSSL_FATAL_ERROR; + *outLen += headerLen + footerLen; + + return WOLFSSL_SUCCESS; +#else + (void)chain; + (void)idx; + (void)buf; + (void)inLen; + (void)outLen; + return WOLFSSL_FAILURE; +#endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */ +} + + +/* get session ID */ +const byte* wolfSSL_get_sessionID(const WOLFSSL_SESSION* session) +{ + WOLFSSL_ENTER("wolfSSL_get_sessionID"); + if (session) + return session->sessionID; + + return NULL; +} + + +#endif /* SESSION_CERTS */ + +#ifdef HAVE_FUZZER +void wolfSSL_SetFuzzerCb(WOLFSSL* ssl, CallbackFuzzer cbf, void* fCtx) +{ + if (ssl) { + ssl->fuzzerCb = cbf; + ssl->fuzzerCtx = fCtx; + } +} +#endif + +#ifndef NO_CERTS +#ifdef HAVE_PK_CALLBACKS + +#ifdef HAVE_ECC +void wolfSSL_CTX_SetEccKeyGenCb(WOLFSSL_CTX* ctx, CallbackEccKeyGen cb) +{ + if (ctx) + ctx->EccKeyGenCb = cb; +} +void wolfSSL_SetEccKeyGenCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->EccKeyGenCtx = ctx; +} +void* wolfSSL_GetEccKeyGenCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->EccKeyGenCtx; + + return NULL; +} + +void wolfSSL_CTX_SetEccSignCb(WOLFSSL_CTX* ctx, CallbackEccSign cb) +{ + if (ctx) + ctx->EccSignCb = cb; +} +void wolfSSL_SetEccSignCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->EccSignCtx = ctx; +} +void* wolfSSL_GetEccSignCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->EccSignCtx; + + return NULL; +} + +void wolfSSL_CTX_SetEccVerifyCb(WOLFSSL_CTX* ctx, CallbackEccVerify cb) +{ + if (ctx) + ctx->EccVerifyCb = cb; +} +void wolfSSL_SetEccVerifyCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->EccVerifyCtx = ctx; +} +void* wolfSSL_GetEccVerifyCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->EccVerifyCtx; + + return NULL; +} + +void wolfSSL_CTX_SetEccSharedSecretCb(WOLFSSL_CTX* ctx, CallbackEccSharedSecret cb) +{ + if (ctx) + ctx->EccSharedSecretCb = cb; +} +void wolfSSL_SetEccSharedSecretCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->EccSharedSecretCtx = ctx; +} +void* wolfSSL_GetEccSharedSecretCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->EccSharedSecretCtx; + + return NULL; +} +#endif /* HAVE_ECC */ + +#ifdef HAVE_ED25519 +void wolfSSL_CTX_SetEd25519SignCb(WOLFSSL_CTX* ctx, CallbackEd25519Sign cb) +{ + if (ctx) + ctx->Ed25519SignCb = cb; +} +void wolfSSL_SetEd25519SignCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->Ed25519SignCtx = ctx; +} +void* wolfSSL_GetEd25519SignCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->Ed25519SignCtx; + + return NULL; +} + +void wolfSSL_CTX_SetEd25519VerifyCb(WOLFSSL_CTX* ctx, CallbackEd25519Verify cb) +{ + if (ctx) + ctx->Ed25519VerifyCb = cb; +} +void wolfSSL_SetEd25519VerifyCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->Ed25519VerifyCtx = ctx; +} +void* wolfSSL_GetEd25519VerifyCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->Ed25519VerifyCtx; + + return NULL; +} +#endif /* HAVE_ED25519 */ + +#ifdef HAVE_CURVE25519 +void wolfSSL_CTX_SetX25519KeyGenCb(WOLFSSL_CTX* ctx, + CallbackX25519KeyGen cb) +{ + if (ctx) + ctx->X25519KeyGenCb = cb; +} +void wolfSSL_SetX25519KeyGenCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->X25519KeyGenCtx = ctx; +} +void* wolfSSL_GetX25519KeyGenCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->X25519KeyGenCtx; + + return NULL; +} + +void wolfSSL_CTX_SetX25519SharedSecretCb(WOLFSSL_CTX* ctx, + CallbackX25519SharedSecret cb) +{ + if (ctx) + ctx->X25519SharedSecretCb = cb; +} +void wolfSSL_SetX25519SharedSecretCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->X25519SharedSecretCtx = ctx; +} +void* wolfSSL_GetX25519SharedSecretCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->X25519SharedSecretCtx; + + return NULL; +} +#endif /* HAVE_CURVE25519 */ + +#ifndef NO_RSA +void wolfSSL_CTX_SetRsaSignCb(WOLFSSL_CTX* ctx, CallbackRsaSign cb) +{ + if (ctx) + ctx->RsaSignCb = cb; +} +void wolfSSL_CTX_SetRsaSignCheckCb(WOLFSSL_CTX* ctx, CallbackRsaVerify cb) +{ + if (ctx) + ctx->RsaSignCheckCb = cb; +} +void wolfSSL_SetRsaSignCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->RsaSignCtx = ctx; +} +void* wolfSSL_GetRsaSignCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->RsaSignCtx; + + return NULL; +} + + +void wolfSSL_CTX_SetRsaVerifyCb(WOLFSSL_CTX* ctx, CallbackRsaVerify cb) +{ + if (ctx) + ctx->RsaVerifyCb = cb; +} +void wolfSSL_SetRsaVerifyCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->RsaVerifyCtx = ctx; +} +void* wolfSSL_GetRsaVerifyCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->RsaVerifyCtx; + + return NULL; +} + +#ifdef WC_RSA_PSS +void wolfSSL_CTX_SetRsaPssSignCb(WOLFSSL_CTX* ctx, CallbackRsaPssSign cb) +{ + if (ctx) + ctx->RsaPssSignCb = cb; +} +void wolfSSL_CTX_SetRsaPssSignCheckCb(WOLFSSL_CTX* ctx, CallbackRsaPssVerify cb) +{ + if (ctx) + ctx->RsaPssSignCheckCb = cb; +} +void wolfSSL_SetRsaPssSignCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->RsaPssSignCtx = ctx; +} +void* wolfSSL_GetRsaPssSignCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->RsaPssSignCtx; + + return NULL; +} + +void wolfSSL_CTX_SetRsaPssVerifyCb(WOLFSSL_CTX* ctx, CallbackRsaPssVerify cb) +{ + if (ctx) + ctx->RsaPssVerifyCb = cb; +} +void wolfSSL_SetRsaPssVerifyCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->RsaPssVerifyCtx = ctx; +} +void* wolfSSL_GetRsaPssVerifyCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->RsaPssVerifyCtx; + + return NULL; +} +#endif /* WC_RSA_PSS */ + +void wolfSSL_CTX_SetRsaEncCb(WOLFSSL_CTX* ctx, CallbackRsaEnc cb) +{ + if (ctx) + ctx->RsaEncCb = cb; +} +void wolfSSL_SetRsaEncCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->RsaEncCtx = ctx; +} +void* wolfSSL_GetRsaEncCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->RsaEncCtx; + + return NULL; +} + +void wolfSSL_CTX_SetRsaDecCb(WOLFSSL_CTX* ctx, CallbackRsaDec cb) +{ + if (ctx) + ctx->RsaDecCb = cb; +} +void wolfSSL_SetRsaDecCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->RsaDecCtx = ctx; +} +void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->RsaDecCtx; + + return NULL; +} +#endif /* NO_RSA */ + +#endif /* HAVE_PK_CALLBACKS */ +#endif /* NO_CERTS */ + +#if defined(HAVE_PK_CALLBACKS) && !defined(NO_DH) +void wolfSSL_CTX_SetDhAgreeCb(WOLFSSL_CTX* ctx, CallbackDhAgree cb) +{ + if (ctx) + ctx->DhAgreeCb = cb; +} +void wolfSSL_SetDhAgreeCtx(WOLFSSL* ssl, void *ctx) +{ + if (ssl) + ssl->DhAgreeCtx = ctx; +} +void* wolfSSL_GetDhAgreeCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->DhAgreeCtx; + + return NULL; +} +#endif /* HAVE_PK_CALLBACKS && !NO_DH */ + + +#ifdef WOLFSSL_HAVE_WOLFSCEP + /* Used by autoconf to see if wolfSCEP is available */ + void wolfSSL_wolfSCEP(void) {} +#endif + + +#ifdef WOLFSSL_HAVE_CERT_SERVICE + /* Used by autoconf to see if cert service is available */ + void wolfSSL_cert_service(void) {} +#endif + + +#ifdef OPENSSL_EXTRA /*Lighttp compatibility*/ + + #ifndef NO_CERTS + void wolfSSL_X509_NAME_free(WOLFSSL_X509_NAME *name){ + WOLFSSL_ENTER("wolfSSL_X509_NAME_free"); + FreeX509Name(name, NULL); + XFREE(name, NULL, DYNAMIC_TYPE_X509); + } + + + /* Malloc's a new WOLFSSL_X509_NAME structure + * + * returns NULL on failure, otherwise returns a new structure. + */ + WOLFSSL_X509_NAME* wolfSSL_X509_NAME_new(void) + { + WOLFSSL_X509_NAME* name; + + WOLFSSL_ENTER("wolfSSL_X509_NAME_new"); + + name = (WOLFSSL_X509_NAME*)XMALLOC(sizeof(WOLFSSL_X509_NAME), NULL, + DYNAMIC_TYPE_X509); + if (name != NULL) { + InitX509Name(name, 1); + } + return name; + } + + +#if defined(WOLFSSL_CERT_GEN) + /* helper function for CopyX509NameToCertName() + * + * returns WOLFSSL_SUCCESS on success + */ + static int CopyX509NameEntry(char* out, int mx, char* in, int inLen) + { + if (inLen > mx) { + WOLFSSL_MSG("Name too long"); + XMEMCPY(out, in, mx); + } + else { + XMEMCPY(out, in, inLen); + out[inLen] = '\0'; + } + + /* make sure is null terminated */ + out[mx-1] = '\0'; + + return WOLFSSL_SUCCESS; + } + + + /* Helper function to copy cert name from a WOLFSSL_X509_NAME structure to + * a CertName structure. + * + * returns WOLFSSL_SUCCESS on success and a negative error value on failure + */ + static int CopyX509NameToCertName(WOLFSSL_X509_NAME* n, CertName* cName) + { + DecodedName* dn = NULL; + + if (n == NULL || cName == NULL) { + return BAD_FUNC_ARG; + } + + dn = &(n->fullName); + + /* initialize cert name */ + cName->country[0] = '\0'; + cName->countryEnc = CTC_PRINTABLE; + cName->state[0] = '\0'; + cName->stateEnc = CTC_UTF8; + cName->locality[0] = '\0'; + cName->localityEnc = CTC_UTF8; + cName->sur[0] = '\0'; + cName->surEnc = CTC_UTF8; + cName->org[0] = '\0'; + cName->orgEnc = CTC_UTF8; + cName->unit[0] = '\0'; + cName->unitEnc = CTC_UTF8; + cName->commonName[0] = '\0'; + cName->commonNameEnc = CTC_UTF8; + cName->serialDev[0] = '\0'; + cName->serialDevEnc = CTC_PRINTABLE; + #ifdef WOLFSSL_CERT_EXT + cName->busCat[0] = '\0'; + cName->busCatEnc = CTC_UTF8; + cName->serialDev[0] = '\0'; + cName->serialDevEnc = CTC_PRINTABLE; + cName->joiC[0] = '\0'; + cName->joiCEnc = CTC_PRINTABLE; + cName->joiSt[0] = '\0'; + cName->joiStEnc = CTC_PRINTABLE; + #endif + cName->email[0] = '\0'; + + + /* ASN_COUNTRY_NAME */ + WOLFSSL_MSG("Copy Country Name"); + if (CopyX509NameEntry(cName->country, CTC_NAME_SIZE, dn->fullName + dn->cIdx, + dn->cLen) != SSL_SUCCESS) { + return BUFFER_E; + } + + /* ASN_ORGUNIT_NAME */ + WOLFSSL_MSG("Copy Org Unit Name"); + if (CopyX509NameEntry(cName->unit, CTC_NAME_SIZE, dn->fullName + dn->ouIdx, + dn->ouLen) != SSL_SUCCESS) { + return BUFFER_E; + } + + /* ASN_ORG_NAME */ + WOLFSSL_MSG("Copy Org Name"); + if (CopyX509NameEntry(cName->org, CTC_NAME_SIZE, dn->fullName + dn->oIdx, + dn->oLen) != SSL_SUCCESS) { + return BUFFER_E; + } + + /* ASN_STATE_NAME */ + WOLFSSL_MSG("Copy State Name"); + if (CopyX509NameEntry(cName->state, CTC_NAME_SIZE, dn->fullName + dn->stIdx, + dn->stLen) != SSL_SUCCESS) { + return BUFFER_E; + } + + /* ASN_LOCALITY_NAME */ + WOLFSSL_MSG("Copy Locality Name"); + if (CopyX509NameEntry(cName->locality, CTC_NAME_SIZE, + dn->fullName + dn->lIdx, dn->lLen) + != SSL_SUCCESS) { + return BUFFER_E; + } + + /* ASN_SUR_NAME */ + WOLFSSL_MSG("Copy Sur Name"); + if (CopyX509NameEntry(cName->sur, CTC_NAME_SIZE, dn->fullName + dn->snIdx, + dn->snLen) != SSL_SUCCESS) { + return BUFFER_E; + } + + /* ASN_COMMON_NAME */ + WOLFSSL_MSG("Copy Common Name"); + if (CopyX509NameEntry(cName->commonName, CTC_NAME_SIZE, + dn->fullName + dn->cnIdx, dn->cnLen) + != SSL_SUCCESS) { + return BUFFER_E; + } + + /* ASN_SERIAL_NUMBER */ + WOLFSSL_MSG("Copy Serial Number of Device"); + if (CopyX509NameEntry(cName->serialDev, CTC_NAME_SIZE, + dn->fullName + dn->serialIdx, dn->serialLen) + != SSL_SUCCESS) { + return BUFFER_E; + } + + #ifdef WOLFSSL_CERT_EXT + /* ASN_BUS_CAT */ + WOLFSSL_MSG("Copy Business Category"); + if (CopyX509NameEntry(cName->busCat, CTC_NAME_SIZE, + dn->fullName + dn->bcIdx, dn->bcLen) + != SSL_SUCCESS) { + return BUFFER_E; + } + + /* JoI Country */ + WOLFSSL_MSG("Copy Jurisdiction of Incorporation Country"); + if (CopyX509NameEntry(cName->joiC, CTC_NAME_SIZE, + dn->fullName + dn->jcIdx, dn->jcLen) + != SSL_SUCCESS) { + return BUFFER_E; + } + + /* JoI State */ + WOLFSSL_MSG("Copy Jurisdiction of Incorporation State"); + if (CopyX509NameEntry(cName->joiSt, CTC_NAME_SIZE, + dn->fullName + dn->jsIdx, dn->jsLen) + != SSL_SUCCESS) { + return BUFFER_E; + } + #endif + + WOLFSSL_MSG("Copy Email"); + if (CopyX509NameEntry(cName->email, CTC_NAME_SIZE, + dn->fullName + dn->emailIdx, dn->emailLen) + != SSL_SUCCESS) { + return BUFFER_E; + } + + return WOLFSSL_SUCCESS; + } + + + /* Converts the x509 name structure into DER format. + * + * out pointer to either a pre setup buffer or a pointer to null for + * creating a dynamic buffer. In the case that a pre-existing buffer is + * used out will be incremented the size of the DER buffer on success. + * + * returns the size of the buffer on success, or negative value with failure + */ + int wolfSSL_i2d_X509_NAME(WOLFSSL_X509_NAME* name, unsigned char** out) + { + CertName cName; + unsigned char buf[256]; /* ASN_MAX_NAME */ + int sz; + + if (out == NULL || name == NULL) { + return BAD_FUNC_ARG; + } + XMEMSET(&cName, 0, sizeof(CertName)); + + if (CopyX509NameToCertName(name, &cName) != SSL_SUCCESS) { + WOLFSSL_MSG("Error converting x509 name to internal CertName"); + return SSL_FATAL_ERROR; + } + + sz = SetName(buf, sizeof(buf), &cName); + if (sz < 0) { + return sz; + } + + /* using buffer passed in */ + if (*out != NULL) { + XMEMCPY(*out, buf, sz); + *out += sz; + } + else { + *out = (unsigned char*)XMALLOC(sz, NULL, DYNAMIC_TYPE_OPENSSL); + if (*out == NULL) { + return MEMORY_E; + } + XMEMCPY(*out, buf, sz); + } + + return sz; + } +#endif /* WOLFSSL_CERT_GEN */ + + + /* Compares the two X509 names. If the size of x is larger then y then a + * positive value is returned if x is smaller a negative value is returned. + * In the case that the sizes are equal a the value of memcmp between the + * two names is returned. + * + * x First name for comparison + * y Second name to compare with x + */ + int wolfSSL_X509_NAME_cmp(const WOLFSSL_X509_NAME* x, + const WOLFSSL_X509_NAME* y) + { + WOLFSSL_STUB("wolfSSL_X509_NAME_cmp"); + + if (x == NULL || y == NULL) { + WOLFSSL_MSG("Bad argument passed in"); + return -2; + } + + if ((x->sz - y->sz) != 0) { + return x->sz - y->sz; + } + else { + return XMEMCMP(x->name, y->name, x->sz); /* y sz is the same */ + } + } + + + WOLFSSL_X509 *wolfSSL_PEM_read_bio_X509(WOLFSSL_BIO *bp, WOLFSSL_X509 **x, + pem_password_cb *cb, void *u) + { + WOLFSSL_X509* x509 = NULL; +#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM) + unsigned char* pem = NULL; + int pemSz; + long i = 0, l; + const char* footer = NULL; + + WOLFSSL_ENTER("wolfSSL_PEM_read_bio_X509"); + + if (bp == NULL) { + WOLFSSL_LEAVE("wolfSSL_PEM_read_bio_X509", BAD_FUNC_ARG); + return NULL; + } + + if (bp->type == WOLFSSL_BIO_MEMORY) { + l = (long)wolfSSL_BIO_ctrl_pending(bp); + if (l <= 0) { + WOLFSSL_MSG("No pending data in WOLFSSL_BIO"); + return NULL; + } + } + else if (bp->type == WOLFSSL_BIO_FILE) { +#ifndef NO_FILESYSTEM + /* Read in next certificate from file but no more. */ + i = XFTELL(bp->file); + if (i < 0) + return NULL; + if (XFSEEK(bp->file, 0, XSEEK_END) != 0) + return NULL; + l = XFTELL(bp->file); + if (l < 0) + return NULL; + if (XFSEEK(bp->file, i, SEEK_SET) != 0) + return NULL; + + /* check calculated length */ + if (l - i < 0) + return NULL; + + l -= i; +#else + WOLFSSL_MSG("Unable to read file with NO_FILESYSTEM defined"); + return NULL; +#endif /* !NO_FILESYSTEM */ + } + else + return NULL; + + pem = (unsigned char*)XMALLOC(l, 0, DYNAMIC_TYPE_PEM); + if (pem == NULL) + return NULL; + + i = 0; + if (wc_PemGetHeaderFooter(CERT_TYPE, NULL, &footer) != 0) { + XFREE(pem, 0, DYNAMIC_TYPE_PEM); + return NULL; + } + + /* TODO: Inefficient + * reading in one byte at a time until see "END CERTIFICATE" + */ + while ((l = wolfSSL_BIO_read(bp, (char *)&pem[i], 1)) == 1) { + i++; + if (i > 26 && XMEMCMP((char *)&pem[i-26], footer, 25) == 0) { + if (pem[i-1] == '\r') { + /* found \r , Windows line ending is \r\n so try to read one + * more byte for \n, ignoring return value */ + (void)wolfSSL_BIO_read(bp, (char *)&pem[i++], 1); + } + break; + } + } + #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) + if (l == 0) + WOLFSSL_ERROR(ASN_NO_PEM_HEADER); + #endif + pemSz = (int)i; + x509 = wolfSSL_X509_load_certificate_buffer(pem, pemSz, + WOLFSSL_FILETYPE_PEM); + + if (x != NULL) { + *x = x509; + } + + XFREE(pem, NULL, DYNAMIC_TYPE_PEM); + +#endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */ + (void)bp; + (void)x; + (void)cb; + (void)u; + + return x509; + } + +#if !defined(NO_FILESYSTEM) + static void* wolfSSL_PEM_read_X509_ex(XFILE fp, void **x, + pem_password_cb *cb, void *u, int type) + { + unsigned char* pem = NULL; + int pemSz; + long i = 0, l; + void *newx509; + + WOLFSSL_ENTER("wolfSSL_PEM_read_X509"); + + if (fp == XBADFILE) { + WOLFSSL_LEAVE("wolfSSL_PEM_read_X509", BAD_FUNC_ARG); + return NULL; + } + /* Read cert from file */ + i = XFTELL(fp); + if (i < 0) { + WOLFSSL_LEAVE("wolfSSL_PEM_read_X509", BAD_FUNC_ARG); + return NULL; + } + + if (XFSEEK(fp, 0, XSEEK_END) != 0) + return NULL; + l = XFTELL(fp); + if (l < 0) + return NULL; + if (XFSEEK(fp, i, SEEK_SET) != 0) + return NULL; + pemSz = (int)(l - i); + /* check calculated length */ + if (pemSz < 0) + return NULL; + if((pem = (unsigned char*)XMALLOC(pemSz, 0, DYNAMIC_TYPE_PEM)) == NULL) + return NULL; + + if((int)XFREAD((char *)pem, 1, pemSz, fp) != pemSz) + goto err_exit; + + switch(type){ + case CERT_TYPE: + newx509 = (void *)wolfSSL_X509_load_certificate_buffer(pem, pemSz, + WOLFSSL_FILETYPE_PEM); + break; + #ifdef HAVE_CRL + case CRL_TYPE: + { + int derSz; + DerBuffer* der = NULL; + if((PemToDer(pem, pemSz, CRL_TYPE, &der, NULL, NULL, NULL)) < 0) + goto err_exit; + derSz = der->length; + if((newx509 = (void *)wolfSSL_d2i_X509_CRL( + (WOLFSSL_X509_CRL **)x, (const unsigned char *)der->buffer, derSz)) == NULL) + goto err_exit; + FreeDer(&der); + break; + } + #endif + + default: + goto err_exit; + } + if (x != NULL) { + *x = newx509; + } + XFREE(pem, 0, DYNAMIC_TYPE_PEM); + return newx509; + + err_exit: + if(pem != NULL) + XFREE(pem, 0, DYNAMIC_TYPE_PEM); + return NULL; + + (void)cb; + (void)u; + + } + + WOLFSSL_API WOLFSSL_X509* wolfSSL_PEM_read_X509(XFILE fp, WOLFSSL_X509 **x, + pem_password_cb *cb, void *u) + { + return (WOLFSSL_X509* )wolfSSL_PEM_read_X509_ex(fp, (void **)x, cb, u, CERT_TYPE); + } + +#if defined(HAVE_CRL) + WOLFSSL_API WOLFSSL_X509_CRL* wolfSSL_PEM_read_X509_CRL(XFILE fp, WOLFSSL_X509_CRL **crl, + pem_password_cb *cb, void *u) + { + return (WOLFSSL_X509_CRL* )wolfSSL_PEM_read_X509_ex(fp, (void **)crl, cb, u, CRL_TYPE); + } +#endif + + int wolfSSL_PEM_write_X509(XFILE fp, WOLFSSL_X509* x) + { + int ret; + WOLFSSL_BIO* bio; + + if (x == NULL) + return 0; + + bio = wolfSSL_BIO_new(wolfSSL_BIO_s_file()); + if (bio == NULL) + return 0; + + if (wolfSSL_BIO_set_fp(bio, fp, BIO_NOCLOSE) != WOLFSSL_SUCCESS) { + wolfSSL_BIO_free(bio); + bio = NULL; + } + + ret = wolfSSL_PEM_write_bio_X509(bio, x); + + if (bio != NULL) + wolfSSL_BIO_free(bio); + + return ret; + } +#endif /* !NO_FILESYSTEM */ + + #define PEM_BEGIN "-----BEGIN " + #define PEM_BEGIN_SZ 11 + #define PEM_END "-----END " + #define PEM_END_SZ 9 + #define PEM_HDR_FIN "-----" + #define PEM_HDR_FIN_SZ 5 + #define PEM_HDR_FIN_EOL "-----\n" + #define PEM_HDR_FIN_EOL_SZ 6 + + int wolfSSL_PEM_read_bio(WOLFSSL_BIO* bio, char **name, char **header, + unsigned char **data, long *len) + { + int ret = WOLFSSL_SUCCESS; + char pem[256]; + int pemLen; + char* p; + char* nameStr = NULL; + int nameLen = 0; + char* headerStr = NULL; + int headerLen; + int headerFound = 0; + unsigned char* der = NULL; + word32 derLen = 0; + + if (bio == NULL || name == NULL || header == NULL || data == NULL || + len == NULL) { + return WOLFSSL_FAILURE; + } + + /* Find header line. */ + pem[sizeof(pem) - 1] = '\0'; + while ((pemLen = wolfSSL_BIO_gets(bio, pem, sizeof(pem) - 1)) > 0) { + if (XSTRNCMP(pem, PEM_BEGIN, PEM_BEGIN_SZ) == 0) + break; + } + if (pemLen <= 0) + ret = WOLFSSL_FAILURE; + /* Have a header line. */ + if (ret == WOLFSSL_SUCCESS) { + while (pem[pemLen - 1] == '\r' || pem[pemLen - 1] == '\n') + pemLen--; + pem[pemLen] = '\0'; + if (XSTRNCMP(pem + pemLen - PEM_HDR_FIN_SZ, PEM_HDR_FIN, + PEM_HDR_FIN_SZ) != 0) { + ret = WOLFSSL_FAILURE; + } + } + + /* Get out name. */ + if (ret == WOLFSSL_SUCCESS) { + nameLen = pemLen - PEM_BEGIN_SZ - PEM_HDR_FIN_SZ; + nameStr = (char*)XMALLOC(nameLen + 1, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (nameStr == NULL) + ret = WOLFSSL_FAILURE; + } + if (ret == WOLFSSL_SUCCESS) { + XSTRNCPY(nameStr, pem + PEM_BEGIN_SZ, nameLen); + nameStr[nameLen] = '\0'; + } + + /* Get header of PEM - encryption header. */ + if (ret == WOLFSSL_SUCCESS) { + headerLen = 0; + while ((pemLen = wolfSSL_BIO_gets(bio, pem, sizeof(pem) - 1)) > 0) { + while (pemLen > 0 && (pem[pemLen - 1] == '\r' || + pem[pemLen - 1] == '\n')) { + pemLen--; + } + pem[pemLen++] = '\n'; + pem[pemLen] = '\0'; + + /* Header separator is a blank line. */ + if (pem[0] == '\n') { + headerFound = 1; + break; + } + + /* Didn't find a blank line - no header. */ + if (XSTRNCMP(pem, PEM_END, PEM_END_SZ) == 0) { + der = (unsigned char*)headerStr; + derLen = headerLen; + /* Empty header - empty string. */ + headerStr = (char*)XMALLOC(1, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (headerStr == NULL) + ret = WOLFSSL_FAILURE; + else + headerStr[0] = '\0'; + break; + } + + p = (char*)XREALLOC(headerStr, headerLen + pemLen + 1, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (p == NULL) { + ret = WOLFSSL_FAILURE; + break; + } + + headerStr = p; + XMEMCPY(headerStr + headerLen, pem, pemLen + 1); + headerLen += pemLen; + } + if (pemLen <= 0) + ret = WOLFSSL_FAILURE; + } + + /* Get body of PEM - if there was a header */ + if (ret == WOLFSSL_SUCCESS && headerFound) { + derLen = 0; + while ((pemLen = wolfSSL_BIO_gets(bio, pem, sizeof(pem) - 1)) > 0) { + while (pemLen > 0 && (pem[pemLen - 1] == '\r' || + pem[pemLen - 1] == '\n')) { + pemLen--; + } + pem[pemLen++] = '\n'; + pem[pemLen] = '\0'; + + if (XSTRNCMP(pem, PEM_END, PEM_END_SZ) == 0) + break; + + p = (char*)XREALLOC(der, derLen + pemLen + 1, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (p == NULL) { + ret = WOLFSSL_FAILURE; + break; + } + + der = (unsigned char*)p; + XMEMCPY(der + derLen, pem, pemLen + 1); + derLen += pemLen; + } + if (pemLen <= 0) + ret = WOLFSSL_FAILURE; + } + + /* Check trailer. */ + if (ret == WOLFSSL_SUCCESS) { + if (XSTRNCMP(pem + PEM_END_SZ, nameStr, nameLen) != 0) + ret = WOLFSSL_FAILURE; + } + if (ret == WOLFSSL_SUCCESS) { + if (XSTRNCMP(pem + PEM_END_SZ + nameLen, PEM_HDR_FIN_EOL, + PEM_HDR_FIN_EOL_SZ) != 0) { + ret = WOLFSSL_FAILURE; + } + } + + /* Base64 decode body. */ + if (ret == WOLFSSL_SUCCESS) { + if (Base64_Decode(der, derLen, der, &derLen) != 0) + ret = WOLFSSL_FAILURE; + } + + if (ret == WOLFSSL_SUCCESS) { + *name = nameStr; + *header = headerStr; + *data = der; + *len = derLen; + nameStr = NULL; + headerStr = NULL; + der = NULL; + } + + if (nameStr != NULL) + XFREE(nameStr, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (headerStr != NULL) + XFREE(headerStr, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (der != NULL) + XFREE(der, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return ret; + } + + int wolfSSL_PEM_write_bio(WOLFSSL_BIO* bio, const char *name, + const char *header, const unsigned char *data, + long len) + { + int err = 0; + int outSz = 0; + int nameLen; + int headerLen; + byte* pem = NULL; + word32 pemLen; + word32 derLen = (word32)len; + + if (bio == NULL || name == NULL || header == NULL || data == NULL) + return 0; + + nameLen = (int)XSTRLEN(name); + headerLen = (int)XSTRLEN(header); + + pemLen = (derLen + 2) / 3 * 4; + pemLen += (pemLen + 63) / 64; + + pem = (byte*)XMALLOC(pemLen, NULL, DYNAMIC_TYPE_TMP_BUFFER); + err = pem == NULL; + if (!err) + err = Base64_Encode(data, derLen, pem, &pemLen) != 0; + + if (!err) { + err = wolfSSL_BIO_write(bio, PEM_BEGIN, PEM_BEGIN_SZ) != + (int)PEM_BEGIN_SZ; + } + if (!err) + err = wolfSSL_BIO_write(bio, name, nameLen) != nameLen; + if (!err) { + err = wolfSSL_BIO_write(bio, PEM_HDR_FIN_EOL, PEM_HDR_FIN_EOL_SZ) != + (int)PEM_HDR_FIN_EOL_SZ; + } + if (!err && headerLen > 0) { + err = wolfSSL_BIO_write(bio, header, headerLen) != headerLen; + /* Blank line after a header and before body. */ + if (!err) + err = wolfSSL_BIO_write(bio, "\n", 1) != 1; + headerLen++; + } + if (!err) + err = wolfSSL_BIO_write(bio, pem, pemLen) != (int)pemLen; + if (!err) + err = wolfSSL_BIO_write(bio, PEM_END, PEM_END_SZ) != + (int)PEM_END_SZ; + if (!err) + err = wolfSSL_BIO_write(bio, name, nameLen) != nameLen; + if (!err) { + err = wolfSSL_BIO_write(bio, PEM_HDR_FIN_EOL, PEM_HDR_FIN_EOL_SZ) != + (int)PEM_HDR_FIN_EOL_SZ; + } + + if (!err) { + outSz = PEM_BEGIN_SZ + nameLen + PEM_HDR_FIN_EOL_SZ + headerLen + + pemLen + PEM_END_SZ + nameLen + PEM_HDR_FIN_EOL_SZ; + } + + if (pem != NULL) + XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return outSz; + } + +#if !defined(NO_FILESYSTEM) + int wolfSSL_PEM_read(XFILE fp, char **name, char **header, + unsigned char **data, long *len) + { + int ret; + WOLFSSL_BIO* bio; + + if (name == NULL || header == NULL || data == NULL || len == NULL) + return WOLFSSL_FAILURE; + + bio = wolfSSL_BIO_new(wolfSSL_BIO_s_file()); + if (bio == NULL) + return 0; + + if (wolfSSL_BIO_set_fp(bio, fp, BIO_NOCLOSE) != WOLFSSL_SUCCESS) { + wolfSSL_BIO_free(bio); + bio = NULL; + } + + ret = wolfSSL_PEM_read_bio(bio, name, header, data, len); + + if (bio != NULL) + wolfSSL_BIO_free(bio); + + return ret; + } + + int wolfSSL_PEM_write(XFILE fp, const char *name, const char *header, + const unsigned char *data, long len) + { + int ret; + WOLFSSL_BIO* bio; + + if (name == NULL || header == NULL || data == NULL) + return 0; + + bio = wolfSSL_BIO_new(wolfSSL_BIO_s_file()); + if (bio == NULL) + return 0; + + if (wolfSSL_BIO_set_fp(bio, fp, BIO_NOCLOSE) != WOLFSSL_SUCCESS) { + wolfSSL_BIO_free(bio); + bio = NULL; + } + + ret = wolfSSL_PEM_write_bio(bio, name, header, data, len); + + if (bio != NULL) + wolfSSL_BIO_free(bio); + + return ret; + } +#endif + + int wolfSSL_PEM_get_EVP_CIPHER_INFO(char* header, EncryptedInfo* cipher) + { + if (header == NULL || cipher == NULL) + return WOLFSSL_FAILURE; + + XMEMSET(cipher, 0, sizeof(*cipher)); + + if (wc_EncryptedInfoParse(cipher, &header, XSTRLEN(header)) != 0) + return WOLFSSL_FAILURE; + + return WOLFSSL_SUCCESS; + } + + int wolfSSL_PEM_do_header(EncryptedInfo* cipher, unsigned char* data, + long* len, pem_password_cb* callback, void* ctx) + { + int ret = WOLFSSL_SUCCESS; + char password[NAME_SZ]; + int passwordSz; + + if (cipher == NULL || data == NULL || len == NULL || callback == NULL) + return WOLFSSL_FAILURE; + + passwordSz = callback(password, sizeof(password), PEM_PASS_READ, ctx); + if (passwordSz < 0) + ret = WOLFSSL_FAILURE; + + if (ret == WOLFSSL_SUCCESS) { + if (wc_BufferKeyDecrypt(cipher, data, (word32)*len, (byte*)password, + passwordSz, WC_MD5) != 0) { + ret = WOLFSSL_FAILURE; + } + } + + if (passwordSz > 0) + XMEMSET(password, 0, passwordSz); + + return ret; + } + + /* + * bp : bio to read X509 from + * x : x509 to write to + * cb : password call back for reading PEM + * u : password + * _AUX is for working with a trusted X509 certificate + */ + WOLFSSL_X509 *wolfSSL_PEM_read_bio_X509_AUX(WOLFSSL_BIO *bp, + WOLFSSL_X509 **x, pem_password_cb *cb, void *u) { + WOLFSSL_ENTER("wolfSSL_PEM_read_bio_X509"); + + /* AUX info is; trusted/rejected uses, friendly name, private key id, + * and potentially a stack of "other" info. wolfSSL does not store + * friendly name or private key id yet in WOLFSSL_X509 for human + * readability and does not support extra trusted/rejected uses for + * root CA. */ + return wolfSSL_PEM_read_bio_X509(bp, x, cb, u); + } + + void wolfSSL_X509_NAME_ENTRY_free(WOLFSSL_X509_NAME_ENTRY* ne) + { + if (ne != NULL) { + if (ne->value != NULL && ne->value != &(ne->data)) { + wolfSSL_ASN1_STRING_free(ne->value); + } + XFREE(ne, NULL, DYNAMIC_TYPE_NAME_ENTRY); + } + } + + + WOLFSSL_X509_NAME_ENTRY* wolfSSL_X509_NAME_ENTRY_new(void) + { + WOLFSSL_X509_NAME_ENTRY* ne = NULL; + + ne = (WOLFSSL_X509_NAME_ENTRY*)XMALLOC(sizeof(WOLFSSL_X509_NAME_ENTRY), + NULL, DYNAMIC_TYPE_NAME_ENTRY); + if (ne != NULL) { + XMEMSET(ne, 0, sizeof(WOLFSSL_X509_NAME_ENTRY)); + ne->value = &(ne->data); + } + + return ne; + } + + + WOLFSSL_X509_NAME_ENTRY* wolfSSL_X509_NAME_ENTRY_create_by_NID( + WOLFSSL_X509_NAME_ENTRY** out, int nid, int type, + unsigned char* data, int dataSz) + { + WOLFSSL_X509_NAME_ENTRY* ne = NULL; + + WOLFSSL_ENTER("wolfSSL_X509_NAME_ENTRY_create_by_NID()"); + + ne = wolfSSL_X509_NAME_ENTRY_new(); + if (ne == NULL) { + return NULL; + } + + ne->nid = nid; + ne->value = wolfSSL_ASN1_STRING_type_new(type); + wolfSSL_ASN1_STRING_set(ne->value, (const void*)data, dataSz); + ne->set = 1; + + if (out != NULL) { + *out = ne; + } + + return ne; + } + + static int RebuildFullNameAdd(DecodedName* dName, char* data) + { + int totalLen = 0; + int i; + char* fullName; + int idx; + + if (dName->cnLen != 0) + totalLen += dName->cnLen + 4; + if (dName->snLen != 0) + totalLen += dName->snLen + 4; + if (dName->cLen != 0) + totalLen += dName->cLen + 3; + if (dName->lLen != 0) + totalLen += dName->lLen + 3; + if (dName->stLen != 0) + totalLen += dName->stLen + 4; + if (dName->oLen != 0) + totalLen += dName->oLen + 3; + if (dName->ouLen != 0) + totalLen += dName->ouLen + 4; + if (dName->emailLen != 0) + totalLen += dName->emailLen + 14; + if (dName->uidLen != 0) + totalLen += dName->uidLen + 5; + if (dName->serialLen != 0) + totalLen += dName->serialLen + 14; + if (dName->dcNum != 0) { + for (i = 0; i < dName->dcNum; i++) + totalLen += dName->dcLen[i] + 4; + } + + fullName = (char*)XMALLOC(totalLen + 1, NULL, DYNAMIC_TYPE_X509); + if (fullName == NULL) + return MEMORY_E; + + idx = 0; + dName->entryCount = 0; + if (dName->cnLen != 0) { + dName->entryCount++; + XMEMCPY(fullName + idx, WOLFSSL_COMMON_NAME, 4); + idx += 4; + if (dName->cnIdx == -1) + XMEMCPY(fullName + idx, data, dName->cnLen); + else { + XMEMCPY(fullName + idx, dName->fullName + dName->cnIdx, + dName->cnLen); + } + dName->cnIdx = idx; + idx += dName->cnLen; + } + if (dName->snLen != 0) { + dName->entryCount++; + XMEMCPY(fullName + idx, WOLFSSL_SUR_NAME, 4); + idx += 4; + if (dName->snIdx == -1) + XMEMCPY(fullName + idx, data, dName->snLen); + else { + XMEMCPY(fullName + idx, dName->fullName + dName->snIdx, + dName->snLen); + } + dName->snIdx = idx; + idx += dName->snLen; + } + if (dName->cLen != 0) { + dName->entryCount++; + XMEMCPY(fullName + idx, WOLFSSL_COUNTRY_NAME, 3); + idx += 3; + if (dName->cIdx == -1) + XMEMCPY(fullName + idx, data, dName->cLen); + else { + XMEMCPY(fullName + idx, dName->fullName + dName->cIdx, + dName->cLen); + } + dName->cIdx = idx; + idx += dName->cLen; + } + if (dName->lLen != 0) { + dName->entryCount++; + XMEMCPY(fullName + idx, WOLFSSL_LOCALITY_NAME, 3); + idx += 3; + if (dName->lIdx == -1) + XMEMCPY(fullName + idx, data, dName->lLen); + else { + XMEMCPY(fullName + idx, dName->fullName + dName->lIdx, + dName->lLen); + } + dName->lIdx = idx; + idx += dName->lLen; + } + if (dName->stLen != 0) { + dName->entryCount++; + XMEMCPY(fullName + idx, WOLFSSL_STATE_NAME, 4); + idx += 4; + if (dName->stIdx == -1) + XMEMCPY(fullName + idx, data, dName->stLen); + else { + XMEMCPY(fullName + idx, dName->fullName + dName->stIdx, + dName->stLen); + } + dName->stIdx = idx; + idx += dName->stLen; + } + if (dName->oLen != 0) { + dName->entryCount++; + XMEMCPY(fullName + idx, WOLFSSL_ORG_NAME, 3); + idx += 3; + if (dName->oIdx == -1) + XMEMCPY(fullName + idx, data, dName->oLen); + else { + XMEMCPY(fullName + idx, dName->fullName + dName->oIdx, + dName->oLen); + } + dName->oIdx = idx; + idx += dName->oLen; + } + if (dName->ouLen != 0) { + dName->entryCount++; + XMEMCPY(fullName + idx, WOLFSSL_ORGUNIT_NAME, 4); + idx += 4; + if (dName->ouIdx == -1) + XMEMCPY(fullName + idx, data, dName->ouLen); + else { + XMEMCPY(fullName + idx, dName->fullName + dName->ouIdx, + dName->ouLen); + } + dName->ouIdx = idx; + idx += dName->ouLen; + } + if (dName->emailLen != 0) { + dName->entryCount++; + XMEMCPY(fullName + idx, "/emailAddress=", 14); + idx += 14; + if (dName->emailIdx == -1) + XMEMCPY(fullName + idx, data, dName->emailLen); + else { + XMEMCPY(fullName + idx, dName->fullName + dName->emailIdx, + dName->emailLen); + } + dName->emailIdx = idx; + idx += dName->emailLen; + } + if (dName->dcNum != 0) { + for (i = 0; i < dName->dcNum; i++) { + dName->entryCount++; + XMEMCPY(fullName + idx, WOLFSSL_DOMAIN_COMPONENT, 4); + idx += 4; + XMEMCPY(fullName + idx, dName->fullName + dName->dcIdx[i], + dName->dcLen[i]); + dName->dcIdx[i] = idx; + idx += dName->dcLen[i]; + } + } + if (dName->uidLen != 0) { + dName->entryCount++; + XMEMCPY(fullName + idx, "/UID=", 5); + idx += 5; + if (dName->uidIdx == -1) + XMEMCPY(fullName + idx, data, dName->uidLen); + else { + XMEMCPY(fullName + idx, dName->fullName + dName->uidIdx, + dName->uidLen); + } + dName->uidIdx = idx; + idx += dName->uidLen; + } + if (dName->serialLen != 0) { + dName->entryCount++; + XMEMCPY(fullName + idx, WOLFSSL_SERIAL_NUMBER, 14); + idx += 14; + if (dName->serialIdx == -1) + XMEMCPY(fullName + idx, data, dName->serialLen); + else { + XMEMCPY(fullName + idx, dName->fullName + dName->serialIdx, + dName->serialLen); + } + dName->serialIdx = idx; + idx += dName->serialLen; + } + + if (dName->fullName != NULL) + XFREE(dName->fullName, NULL, DYNAMIC_TYPE_X509); + dName->fullName = fullName; + dName->fullNameLen = idx; + + return 0; + } + + /* Copies entry into name. With it being copied freeing entry becomes the + * callers responsibility. + * returns 1 for success and 0 for error */ + int wolfSSL_X509_NAME_add_entry(WOLFSSL_X509_NAME* name, + WOLFSSL_X509_NAME_ENTRY* entry, int idx, int set) + { + int i; + int fullName = 1; + + WOLFSSL_ENTER("wolfSSL_X509_NAME_add_entry()"); + + switch (entry->nid) { + case ASN_COMMON_NAME: + name->fullName.cnIdx = -1; + name->fullName.cnLen = entry->value->length; + name->fullName.cnNid = entry->nid; + break; + case ASN_SUR_NAME: + name->fullName.snIdx = -1; + name->fullName.snLen = entry->value->length; + name->fullName.snNid = entry->nid; + break; + case ASN_SERIAL_NUMBER: + name->fullName.serialIdx = -1; + name->fullName.serialLen = entry->value->length; + name->fullName.serialNid = entry->nid; + break; + case ASN_COUNTRY_NAME: + name->fullName.cIdx = -1; + name->fullName.cLen = entry->value->length; + name->fullName.cNid = entry->nid; + break; + case ASN_LOCALITY_NAME: + name->fullName.lIdx = -1; + name->fullName.lLen = entry->value->length; + name->fullName.lNid = entry->nid; + break; + case ASN_STATE_NAME: + name->fullName.stIdx = -1; + name->fullName.stLen = entry->value->length; + name->fullName.stNid = entry->nid; + break; + case ASN_ORG_NAME: + name->fullName.oIdx = -1; + name->fullName.oLen = entry->value->length; + name->fullName.oNid = entry->nid; + break; + case ASN_ORGUNIT_NAME: + name->fullName.ouIdx = -1; + name->fullName.ouLen = entry->value->length; + name->fullName.ouNid = entry->nid; + break; + case NID_emailAddress: + name->fullName.emailIdx = -1; + name->fullName.emailLen = entry->value->length; + name->fullName.emailNid = entry->nid; + break; + case ASN_USER_ID: + name->fullName.uidIdx = -1; + name->fullName.uidLen = entry->value->length; + name->fullName.uidNid = entry->nid; + break; + case ASN_DOMAIN_COMPONENT: + name->fullName.dcIdx[0] = -1; + name->fullName.dcLen[0] = entry->value->length; + break; + default: + fullName = 0; + break; + } + + if (fullName) { + int nid = entry->nid; + + if (nid == NID_emailAddress) { + nid = (int)ASN_EMAIL_NAME; + } + + if (idx >= DN_NAMES_MAX + DOMAIN_COMPONENT_MAX) { + return WOLFSSL_FAILURE; + } + + if (idx >= 0) { + name->fullName.loc[idx] = nid; + if (idx == name->fullName.locSz) { + name->fullName.locSz += 1; + } + } + + /* place at end */ + if (idx < 0 && name->fullName.locSz + 1 + < DN_NAMES_MAX + DOMAIN_COMPONENT_MAX) { + name->fullName.loc[name->fullName.locSz] = nid; + name->fullName.locSz += 1; + } + + if (RebuildFullNameAdd(&name->fullName, entry->value->data) != 0) + return WOLFSSL_FAILURE; + } + else { + for (i = 0; i < MAX_NAME_ENTRIES; i++) { + if (name->extra[i].set != 1) { /* not set so overwrited */ + WOLFSSL_X509_NAME_ENTRY* current = &(name->extra[i]); + WOLFSSL_ASN1_STRING* str; + + WOLFSSL_MSG("Found place for name entry"); + + XMEMCPY(current, entry, sizeof(WOLFSSL_X509_NAME_ENTRY)); + str = entry->value; + XMEMCPY(&(current->data), str, sizeof(WOLFSSL_ASN1_STRING)); + current->value = &(current->data); + current->data.data = (char*)XMALLOC(str->length, + name->x509->heap, DYNAMIC_TYPE_OPENSSL); + + if (current->data.data == NULL) { + return SSL_FAILURE; + } + XMEMCPY(current->data.data, str->data, str->length); + + /* make sure is null terminated */ + current->data.data[str->length - 1] = '\0'; + + current->set = 1; /* make sure now listed as set */ + break; + } + } + + if (i == MAX_NAME_ENTRIES) { + WOLFSSL_MSG("No spot found for name entry"); + return SSL_FAILURE; + } + } + + (void)idx; + (void)set; + return SSL_SUCCESS; + } + + typedef struct WOLFSSL_ObjectInfo { + int nid; + int id; + word32 type; + const char* sName; + } WOLFSSL_ObjectInfo; + + static WOLFSSL_ObjectInfo wolfssl_object_info[] = { + /* oidHashType */ + #ifdef WOLFSSL_MD2 + { NID_md2, MD2h, oidHashType, "md2" }, + #endif + #ifdef WOLFSSL_MD5 + { NID_md5, MD5h, oidHashType, "md5" }, + #endif + #ifndef NO_SHA + { NID_sha1, SHAh, oidHashType, "sha" }, + #endif + #ifdef WOLFSSL_SHA224 + { NID_sha224, SHA224h, oidHashType, "sha224" }, + #endif + #ifndef NO_SHA256 + { NID_sha256, SHA256h, oidHashType, "sha256" }, + #endif + #ifdef WOLFSSL_SHA384 + { NID_sha384, SHA384h, oidHashType, "sha384" }, + #endif + #ifdef WOLFSSL_SHA512 + { NID_sha512, SHA512h, oidHashType, "sha512" }, + #endif + + /* oidSigType */ + #ifndef NO_DSA + #ifndef NO_SHA + { CTC_SHAwDSA, CTC_SHAwDSA, oidSigType, "shaWithDSA" }, + #endif + #endif /* NO_DSA */ + #ifndef NO_RSA + #ifdef WOLFSSL_MD2 + { CTC_MD2wRSA, CTC_MD2wRSA, oidSigType, "md2WithRSA" }, + #endif + #ifndef NO_MD5 + { CTC_MD5wRSA, CTC_MD5wRSA, oidSigType, "md5WithRSA" }, + #endif + #ifndef NO_SHA + { CTC_SHAwRSA, CTC_SHAwRSA, oidSigType, "shaWithRSA" }, + #endif + #ifdef WOLFSSL_SHA224 + { CTC_SHA224wRSA, CTC_SHA224wRSA, oidSigType, "sha224WithRSA" }, + #endif + #ifndef NO_SHA256 + { CTC_SHA256wRSA, CTC_SHA256wRSA, oidSigType, "sha256WithRSA" }, + #endif + #ifdef WOLFSSL_SHA384 + { CTC_SHA384wRSA, CTC_SHA384wRSA, oidSigType, "sha384WithRSA" }, + #endif + #ifdef WOLFSSL_SHA512 + { CTC_SHA512wRSA, CTC_SHA512wRSA, oidSigType, "sha512WithRSA" }, + #endif + #endif /* NO_RSA */ + #ifdef HAVE_ECC + #ifndef NO_SHA + { CTC_SHAwECDSA, CTC_SHAwECDSA, oidSigType, "shaWithECDSA" }, + #endif + #ifdef WOLFSSL_SHA224 + { CTC_SHA224wECDSA, CTC_SHA224wECDSA, oidSigType, "sha224WithECDSA" }, + #endif + #ifndef NO_SHA256 + { CTC_SHA256wECDSA, CTC_SHA256wECDSA, oidSigType, "sha256WithECDSA" }, + #endif + #ifdef WOLFSSL_SHA384 + { CTC_SHA384wECDSA, CTC_SHA384wECDSA, oidSigType, "sha384WithECDSA" }, + #endif + #ifdef WOLFSSL_SHA512 + { CTC_SHA512wECDSA, CTC_SHA512wECDSA, oidSigType, "sha512WithECDSA" }, + #endif + #endif /* HAVE_ECC */ + + /* oidKeyType */ + #ifndef NO_DSA + { DSAk, DSAk, oidKeyType, "DSA key" }, + #endif /* NO_DSA */ + #ifndef NO_RSA + { RSAk, RSAk, oidKeyType, "RSA key" }, + #endif /* NO_RSA */ + #ifdef HAVE_NTRU + { NTRUk, NTRUk, oidKeyType, "NTRU key" }, + #endif /* HAVE_NTRU */ + #ifdef HAVE_ECC + { ECDSAk, ECDSAk, oidKeyType, "ECDSA key" }, + #endif /* HAVE_ECC */ + + /* oidBlkType */ + #ifdef WOLFSSL_AES_128 + { AES128CBCb, AES128CBCb, oidBlkType, "AES-128-CBC" }, + #endif + #ifdef WOLFSSL_AES_192 + { AES192CBCb, AES192CBCb, oidBlkType, "AES-192-CBC" }, + #endif + #ifdef WOLFSSL_AES_256 + { AES256CBCb, AES256CBCb, oidBlkType, "AES-256-CBC" }, + #endif + #ifndef NO_DES3 + { NID_des, DESb, oidBlkType, "DES-CBC" }, + { NID_des3, DES3b, oidBlkType, "DES3-CBC" }, + #endif /* !NO_DES3 */ + + /* oidOcspType */ + #ifdef HAVE_OCSP + { NID_id_pkix_OCSP_basic, OCSP_BASIC_OID, oidOcspType, "OCSP_basic" }, + { OCSP_NONCE_OID, OCSP_NONCE_OID, oidOcspType, "OCSP_nonce" }, + #endif /* HAVE_OCSP */ + + #ifndef NO_CERTS + /* oidCertExtType */ + { BASIC_CA_OID, BASIC_CA_OID, oidCertExtType, "X509 basic ca" }, + { ALT_NAMES_OID, ALT_NAMES_OID, oidCertExtType, "X509 alt names" }, + { CRL_DIST_OID, CRL_DIST_OID, oidCertExtType, "X509 crl" }, + { AUTH_INFO_OID, AUTH_INFO_OID, oidCertExtType, "X509 auth info" }, + { AUTH_KEY_OID, AUTH_KEY_OID, oidCertExtType, "X509 auth key" }, + { SUBJ_KEY_OID, SUBJ_KEY_OID, oidCertExtType, "X509 subject key" }, + { KEY_USAGE_OID, KEY_USAGE_OID, oidCertExtType, "X509 key usage" }, + { INHIBIT_ANY_OID, INHIBIT_ANY_OID, oidCertExtType, + "X509 inhibit any" }, + { NID_key_usage, KEY_USAGE_OID, oidCertExtType, + "X509 key usage" }, + { NID_name_constraints, NAME_CONS_OID, oidCertExtType, + "X509 name constraints" }, + { NID_certificate_policies, CERT_POLICY_OID, oidCertExtType, + "X509 certificate policies" }, + + /* oidCertAuthInfoType */ + { AIA_OCSP_OID, AIA_OCSP_OID, oidCertAuthInfoType, "Cert Auth OCSP" }, + { AIA_CA_ISSUER_OID, AIA_CA_ISSUER_OID, oidCertAuthInfoType, + "Cert Auth CA Issuer" }, + + /* oidCertPolicyType */ + { NID_any_policy, CP_ANY_OID, oidCertPolicyType, "Cert any policy" }, + + /* oidCertAltNameType */ + { NID_hw_name_oid, HW_NAME_OID, oidCertAltNameType, "Hardware name" }, + + /* oidCertKeyUseType */ + { NID_anyExtendedKeyUsage, EKU_ANY_OID, oidCertKeyUseType, + "Cert any extended key" }, + { EKU_SERVER_AUTH_OID, EKU_SERVER_AUTH_OID, oidCertKeyUseType, + "Cert server auth key" }, + { EKU_CLIENT_AUTH_OID, EKU_CLIENT_AUTH_OID, oidCertKeyUseType, + "Cert client auth key" }, + { EKU_OCSP_SIGN_OID, EKU_OCSP_SIGN_OID, oidCertKeyUseType, + "Cert OCSP sign key" }, + + /* oidCertNameType */ + { NID_commonName, NID_commonName, oidCertNameType, "commonName" }, + { NID_surname, NID_surname, oidCertNameType, "surname" }, + { NID_serialNumber, NID_serialNumber, oidCertNameType, "serialNumber" }, + { NID_countryName, NID_countryName, oidCertNameType, "countryName" }, + { NID_localityName, NID_localityName, oidCertNameType, "localityName" }, + { NID_stateOrProvinceName, NID_stateOrProvinceName, oidCertNameType, + "stateOrProvinceName" }, + { NID_organizationName, NID_organizationName, oidCertNameType, + "organizationName" }, + { NID_organizationalUnitName, NID_organizationalUnitName, + oidCertNameType, "organizationalUnitName" }, + { NID_emailAddress, NID_emailAddress, oidCertNameType, "emailAddress" }, + #endif + + #ifndef NO_PWDBASED + /* oidKdfType */ + { PBKDF2_OID, PBKDF2_OID, oidKdfType, "PBKDFv2" }, + + /* oidPBEType */ + { PBE_SHA1_RC4_128, PBE_SHA1_RC4_128, oidPBEType, + "PBE shaWithRC4-128" }, + { PBE_SHA1_DES, PBE_SHA1_DES, oidPBEType, "PBE shaWithDES" }, + { PBE_SHA1_DES3, PBE_SHA1_DES3, oidPBEType, "PBE shaWithDES3" }, + #endif + + /* oidKeyWrapType */ + #ifdef WOLFSSL_AES_128 + { AES128_WRAP, AES128_WRAP, oidKeyWrapType, "AES-128 wrap" }, + #endif + #ifdef WOLFSSL_AES_192 + { AES192_WRAP, AES192_WRAP, oidKeyWrapType, "AES-192 wrap" }, + #endif + #ifdef WOLFSSL_AES_256 + { AES256_WRAP, AES256_WRAP, oidKeyWrapType, "AES-256 wrap" }, + #endif + + #ifndef NO_PKCS7 + #ifndef NO_DH + /* oidCmsKeyAgreeType */ + #ifndef NO_SHA + { dhSinglePass_stdDH_sha1kdf_scheme, dhSinglePass_stdDH_sha1kdf_scheme, + oidCmsKeyAgreeType, "DH-SHA kdf" }, + #endif + #ifdef WOLFSSL_SHA224 + { dhSinglePass_stdDH_sha224kdf_scheme, + dhSinglePass_stdDH_sha224kdf_scheme, oidCmsKeyAgreeType, + "DH-SHA224 kdf" }, + #endif + #ifndef NO_SHA256 + { dhSinglePass_stdDH_sha256kdf_scheme, + dhSinglePass_stdDH_sha256kdf_scheme, oidCmsKeyAgreeType, + "DH-SHA256 kdf" }, + #endif + #ifdef WOLFSSL_SHA384 + { dhSinglePass_stdDH_sha384kdf_scheme, + dhSinglePass_stdDH_sha384kdf_scheme, oidCmsKeyAgreeType, + "DH-SHA384 kdf" }, + #endif + #ifdef WOLFSSL_SHA512 + { dhSinglePass_stdDH_sha512kdf_scheme, + dhSinglePass_stdDH_sha512kdf_scheme, oidCmsKeyAgreeType, + "DH-SHA512 kdf" }, + #endif + #endif + #endif + }; + + #define WOLFSSL_OBJECT_INFO_SZ \ + (sizeof(wolfssl_object_info) / sizeof(*wolfssl_object_info)) + + int wolfSSL_X509_NAME_add_entry_by_txt(WOLFSSL_X509_NAME *name, + const char *field, int type, + const unsigned char *bytes, int len, + int loc, int set) + { + int ret; + int i; + WOLFSSL_X509_NAME_ENTRY* entry; + size_t fieldSz; + + (void)type; + + if (name == NULL || field == NULL) + return WOLFSSL_FAILURE; + + fieldSz = XSTRLEN(field); + for (i = 0; i < (int)WOLFSSL_OBJECT_INFO_SZ; i++) { + if (XSTRNCMP(field, wolfssl_object_info[i].sName, fieldSz) == 0) + break; + } + + if (i == WOLFSSL_OBJECT_INFO_SZ) + return WOLFSSL_FAILURE; + + entry = wolfSSL_X509_NAME_ENTRY_create_by_NID(NULL, + wolfssl_object_info[i].nid, type, (unsigned char*)bytes, len); + if (entry == NULL) + return WOLFSSL_FAILURE; + + ret = wolfSSL_X509_NAME_add_entry(name, entry, loc, set); + wolfSSL_X509_NAME_ENTRY_free(entry); + return ret; + } + #endif /* ifndef NO_CERTS */ + + + /* NID variables are dependent on compatibility header files currently + * + * returns a pointer to a new WOLFSSL_ASN1_OBJECT struct on success and NULL + * on fail + */ + + WOLFSSL_ASN1_OBJECT* wolfSSL_OBJ_nid2obj(int id) + { + return wolfSSL_OBJ_nid2obj_ex(id, NULL); + } + + + WOLFSSL_LOCAL WOLFSSL_ASN1_OBJECT* wolfSSL_OBJ_nid2obj_ex(int id, + WOLFSSL_ASN1_OBJECT* arg_obj) + { + word32 oidSz = 0; + const byte* oid; + word32 type = 0; + WOLFSSL_ASN1_OBJECT* obj = arg_obj; + byte objBuf[MAX_OID_SZ + MAX_LENGTH_SZ + 1]; /* +1 for object tag */ + word32 objSz = 0; + const char* sName = NULL; + int i; + + WOLFSSL_ENTER("wolfSSL_OBJ_nid2obj()"); + + for (i = 0; i < (int)WOLFSSL_OBJECT_INFO_SZ; i++) { + if (wolfssl_object_info[i].nid == id) { + id = wolfssl_object_info[i].id; + sName = wolfssl_object_info[i].sName; + type = wolfssl_object_info[i].type; + break; + } + } + if (i == (int)WOLFSSL_OBJECT_INFO_SZ) { + WOLFSSL_MSG("NID not in table"); + return NULL; + } + + #ifdef HAVE_ECC + if (type == 0 && wc_ecc_get_oid(id, &oid, &oidSz) > 0) { + type = oidCurveType; + } + #endif /* HAVE_ECC */ + + if (sName != NULL) { + if (XSTRLEN(sName) > WOLFSSL_MAX_SNAME - 1) { + WOLFSSL_MSG("Attempted short name is too large"); + return NULL; + } + } + + oid = OidFromId(id, type, &oidSz); + + /* set object ID to buffer */ + if (obj == NULL){ + obj = wolfSSL_ASN1_OBJECT_new(); + if (obj == NULL) { + WOLFSSL_MSG("Issue creating WOLFSSL_ASN1_OBJECT struct"); + return NULL; + } + obj->dynamic |= WOLFSSL_ASN1_DYNAMIC; + } else { + obj->dynamic &= ~WOLFSSL_ASN1_DYNAMIC; + } + obj->type = id; + obj->grp = type; + + obj->sName[0] = '\0'; + if (sName != NULL) { + XMEMCPY(obj->sName, (char*)sName, XSTRLEN((char*)sName)); + } + + objBuf[0] = ASN_OBJECT_ID; objSz++; + objSz += SetLength(oidSz, objBuf + 1); + XMEMCPY(objBuf + objSz, oid, oidSz); + objSz += oidSz; + obj->objSz = objSz; + if(((obj->dynamic & WOLFSSL_ASN1_DYNAMIC_DATA) != 0) || + (((obj->dynamic & WOLFSSL_ASN1_DYNAMIC_DATA) == 0) && + (obj->obj == NULL))) { + obj->obj = (byte*)XREALLOC((byte*)obj->obj, obj->objSz, NULL, + DYNAMIC_TYPE_ASN1); + if (obj->obj == NULL) { + wolfSSL_ASN1_OBJECT_free(obj); + return NULL; + } + obj->dynamic |= WOLFSSL_ASN1_DYNAMIC_DATA ; + } else { + obj->dynamic &= ~WOLFSSL_ASN1_DYNAMIC_DATA ; + } + XMEMCPY((byte*)obj->obj, objBuf, obj->objSz); + + (void)type; + + return obj; + } + + + /* if no_name is one than use numerical form otherwise can be short name. + * + * returns the buffer size on success + */ + int wolfSSL_OBJ_obj2txt(char *buf, int bufLen, WOLFSSL_ASN1_OBJECT *a, int no_name) + { + int bufSz; + + WOLFSSL_ENTER("wolfSSL_OBJ_obj2txt()"); + + if (buf == NULL || bufLen <= 1 || a == NULL) { + WOLFSSL_MSG("Bad input argument"); + return WOLFSSL_FAILURE; + } + + if (no_name == 1) { + int length; + word32 idx = 0; + + if (a->obj[idx++] != ASN_OBJECT_ID) { + WOLFSSL_MSG("Bad ASN1 Object"); + return WOLFSSL_FAILURE; + } + + if (GetLength((const byte*)a->obj, &idx, &length, + a->objSz) < 0 || length < 0) { + return ASN_PARSE_E; + } + + if (bufLen < MAX_OID_STRING_SZ) { + bufSz = bufLen - 1; + } + else { + bufSz = MAX_OID_STRING_SZ; + } + + if ((bufSz = DecodePolicyOID(buf, (word32)bufSz, a->obj + idx, + (word32)length)) <= 0) { + WOLFSSL_MSG("Error decoding OID"); + return WOLFSSL_FAILURE; + } + + } + else { /* return short name */ + if (XSTRLEN(a->sName) + 1 < (word32)bufLen - 1) { + bufSz = (int)XSTRLEN(a->sName); + } + else { + bufSz = bufLen - 1; + } + XMEMCPY(buf, a->sName, bufSz); + } + + buf[bufSz] = '\0'; + return bufSz; + } + +#if defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY) || \ + defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(HAVE_STUNNEL) || \ + defined(WOLFSSL_NGINX) || defined(HAVE_POCO_LIB) || \ + defined(WOLFSSL_HAPROXY) + +#ifndef NO_SHA + /* One shot SHA1 hash of message. + * + * d message to hash + * n size of d buffer + * md buffer to hold digest. Should be SHA_DIGEST_SIZE. + * + * Note: if md is null then a static buffer of SHA_DIGEST_SIZE is used. + * When the static buffer is used this function is not thread safe. + * + * Returns a pointer to the message digest on success and NULL on failure. + */ + unsigned char *wolfSSL_SHA1(const unsigned char *d, size_t n, + unsigned char *md) + { + static byte dig[WC_SHA_DIGEST_SIZE]; + wc_Sha sha; + + WOLFSSL_ENTER("wolfSSL_SHA1"); + + if (wc_InitSha_ex(&sha, NULL, 0) != 0) { + WOLFSSL_MSG("SHA1 Init failed"); + return NULL; + } + + if (wc_ShaUpdate(&sha, (const byte*)d, (word32)n) != 0) { + WOLFSSL_MSG("SHA1 Update failed"); + return NULL; + } + + if (wc_ShaFinal(&sha, dig) != 0) { + WOLFSSL_MSG("SHA1 Final failed"); + return NULL; + } + + wc_ShaFree(&sha); + + if (md != NULL) { + XMEMCPY(md, dig, WC_SHA_DIGEST_SIZE); + return md; + } + else { + return (unsigned char*)dig; + } + } +#endif /* ! NO_SHA */ + +#ifndef NO_SHA256 + /* One shot SHA256 hash of message. + * + * d message to hash + * n size of d buffer + * md buffer to hold digest. Should be WC_SHA256_DIGEST_SIZE. + * + * Note: if md is null then a static buffer of WC_SHA256_DIGEST_SIZE is used. + * When the static buffer is used this function is not thread safe. + * + * Returns a pointer to the message digest on success and NULL on failure. + */ + unsigned char *wolfSSL_SHA256(const unsigned char *d, size_t n, + unsigned char *md) + { + static byte dig[WC_SHA256_DIGEST_SIZE]; + wc_Sha256 sha; + + WOLFSSL_ENTER("wolfSSL_SHA256"); + + if (wc_InitSha256_ex(&sha, NULL, 0) != 0) { + WOLFSSL_MSG("SHA256 Init failed"); + return NULL; + } + + if (wc_Sha256Update(&sha, (const byte*)d, (word32)n) != 0) { + WOLFSSL_MSG("SHA256 Update failed"); + return NULL; + } + + if (wc_Sha256Final(&sha, dig) != 0) { + WOLFSSL_MSG("SHA256 Final failed"); + return NULL; + } + + wc_Sha256Free(&sha); + + if (md != NULL) { + XMEMCPY(md, dig, WC_SHA256_DIGEST_SIZE); + return md; + } + else { + return (unsigned char*)dig; + } + } +#endif /* ! NO_SHA256 */ + +#ifdef WOLFSSL_SHA384 + /* One shot SHA384 hash of message. + * + * d message to hash + * n size of d buffer + * md buffer to hold digest. Should be WC_SHA256_DIGEST_SIZE. + * + * Note: if md is null then a static buffer of WC_SHA256_DIGEST_SIZE is used. + * When the static buffer is used this function is not thread safe. + * + * Returns a pointer to the message digest on success and NULL on failure. + */ + unsigned char *wolfSSL_SHA384(const unsigned char *d, size_t n, + unsigned char *md) + { + static byte dig[WC_SHA384_DIGEST_SIZE]; + wc_Sha384 sha; + + WOLFSSL_ENTER("wolfSSL_SHA384"); + + if (wc_InitSha384_ex(&sha, NULL, 0) != 0) { + WOLFSSL_MSG("SHA384 Init failed"); + return NULL; + } + + if (wc_Sha384Update(&sha, (const byte*)d, (word32)n) != 0) { + WOLFSSL_MSG("SHA384 Update failed"); + return NULL; + } + + if (wc_Sha384Final(&sha, dig) != 0) { + WOLFSSL_MSG("SHA384 Final failed"); + return NULL; + } + + wc_Sha384Free(&sha); + + if (md != NULL) { + XMEMCPY(md, dig, WC_SHA384_DIGEST_SIZE); + return md; + } + else { + return (unsigned char*)dig; + } + } +#endif /* WOLFSSL_SHA384 */ + + +#if defined(WOLFSSL_SHA512) + /* One shot SHA512 hash of message. + * + * d message to hash + * n size of d buffer + * md buffer to hold digest. Should be WC_SHA256_DIGEST_SIZE. + * + * Note: if md is null then a static buffer of WC_SHA256_DIGEST_SIZE is used. + * When the static buffer is used this function is not thread safe. + * + * Returns a pointer to the message digest on success and NULL on failure. + */ + unsigned char *wolfSSL_SHA512(const unsigned char *d, size_t n, + unsigned char *md) + { + static byte dig[WC_SHA512_DIGEST_SIZE]; + wc_Sha512 sha; + + WOLFSSL_ENTER("wolfSSL_SHA512"); + + if (wc_InitSha512_ex(&sha, NULL, 0) != 0) { + WOLFSSL_MSG("SHA512 Init failed"); + return NULL; + } + + if (wc_Sha512Update(&sha, (const byte*)d, (word32)n) != 0) { + WOLFSSL_MSG("SHA512 Update failed"); + return NULL; + } + + if (wc_Sha512Final(&sha, dig) != 0) { + WOLFSSL_MSG("SHA512 Final failed"); + return NULL; + } + + wc_Sha512Free(&sha); + + if (md != NULL) { + XMEMCPY(md, dig, WC_SHA512_DIGEST_SIZE); + return md; + } + else { + return (unsigned char*)dig; + } + } +#endif /* defined(WOLFSSL_SHA512) */ + + char wolfSSL_CTX_use_certificate(WOLFSSL_CTX *ctx, WOLFSSL_X509 *x) + { + int ret; + + WOLFSSL_ENTER("wolfSSL_CTX_use_certificate"); + + FreeDer(&ctx->certificate); /* Make sure previous is free'd */ + ret = AllocDer(&ctx->certificate, x->derCert->length, CERT_TYPE, + ctx->heap); + if (ret != 0) + return 0; + + XMEMCPY(ctx->certificate->buffer, x->derCert->buffer, + x->derCert->length); +#ifdef KEEP_OUR_CERT + if (ctx->ourCert != NULL && ctx->ownOurCert) { + FreeX509(ctx->ourCert); + XFREE(ctx->ourCert, ctx->heap, DYNAMIC_TYPE_X509); + } + #ifndef WOLFSSL_X509_STORE_CERTS + ctx->ourCert = x; + #else + ctx->ourCert = wolfSSL_X509_d2i(NULL, x->derCert->buffer,x->derCert->length); + if(ctx->ourCert == NULL){ + return 0; + } + #endif + + ctx->ownOurCert = 0; +#endif + + /* Update the available options with public keys. */ + switch (x->pubKeyOID) { + case RSAk: + ctx->haveRSA = 1; + break; + #ifdef HAVE_ED25519 + case ED25519k: + #endif + case ECDSAk: + ctx->haveECC = 1; + #if defined(HAVE_ECC) || defined(HAVE_ED25519) + ctx->pkCurveOID = x->pkCurveOID; + #endif + break; + } + + return WOLFSSL_SUCCESS; + } + + #ifndef NO_WOLFSSL_STUB + int wolfSSL_BIO_read_filename(WOLFSSL_BIO *b, const char *name) { + #ifndef NO_FILESYSTEM + XFILE fp; + + WOLFSSL_ENTER("wolfSSL_BIO_new_file"); + + if ((wolfSSL_BIO_get_fp(b, &fp) == WOLFSSL_SUCCESS) && (fp != XBADFILE)) + { + XFCLOSE(fp); + } + + fp = XFOPEN(name, "r"); + if (fp == XBADFILE) + return WOLFSSL_BAD_FILE; + + if (wolfSSL_BIO_set_fp(b, fp, BIO_CLOSE) != WOLFSSL_SUCCESS) { + XFCLOSE(fp); + return WOLFSSL_BAD_FILE; + } + + /* file is closed when bio is free'd */ + return WOLFSSL_SUCCESS; + #else + (void)name; + (void)b; + return WOLFSSL_NOT_IMPLEMENTED; + #endif + } + #endif + +#ifdef HAVE_ECC + const char * wolfSSL_OBJ_nid2sn(int n) { + int i; + WOLFSSL_ENTER("wolfSSL_OBJ_nid2sn"); + + /* find based on NID and return name */ + for (i = 0; i < ecc_sets[i].size; i++) { + if (n == ecc_sets[i].id) { + return ecc_sets[i].name; + } + } + return NULL; + } + +#endif /* HAVE_ECC */ +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + int wolfSSL_OBJ_sn2nid(const char *sn) { + + WOLFSSL_ENTER("wolfSSL_OBJ_sn2nid"); + return wc_OBJ_sn2nid(sn); + } +#endif + + static int oid2nid(word32 oid, int grp) + { + /* get OID type */ + switch (grp) { + /* oidHashType */ + case oidHashType: + switch (oid) { + #ifdef WOLFSSL_MD2 + case MD2h: + return NID_md2; + #endif + #ifndef NO_MD5 + case MD5h: + return NID_md5; + #endif + #ifndef NO_SHA + case SHAh: + return NID_sha1; + #endif + case SHA224h: + return NID_sha224; + #ifndef NO_SHA256 + case SHA256h: + return NID_sha256; + #endif + #ifdef WOLFSSL_SHA384 + case SHA384h: + return NID_sha384; + #endif + #ifdef WOLFSSL_SHA512 + case SHA512h: + return NID_sha512; + #endif + } + break; + + /* oidSigType */ + case oidSigType: + switch (oid) { + #ifndef NO_DSA + case CTC_SHAwDSA: + return CTC_SHAwDSA; + #endif /* NO_DSA */ + #ifndef NO_RSA + case CTC_MD2wRSA: + return CTC_MD2wRSA; + case CTC_MD5wRSA: + return CTC_MD5wRSA; + case CTC_SHAwRSA: + return CTC_SHAwRSA; + case CTC_SHA224wRSA: + return CTC_SHA224wRSA; + case CTC_SHA256wRSA: + return CTC_SHA256wRSA; + case CTC_SHA384wRSA: + return CTC_SHA384wRSA; + case CTC_SHA512wRSA: + return CTC_SHA512wRSA; + #endif /* NO_RSA */ + #ifdef HAVE_ECC + case CTC_SHAwECDSA: + return CTC_SHAwECDSA; + case CTC_SHA224wECDSA: + return CTC_SHA224wECDSA; + case CTC_SHA256wECDSA: + return CTC_SHA256wECDSA; + case CTC_SHA384wECDSA: + return CTC_SHA384wECDSA; + case CTC_SHA512wECDSA: + return CTC_SHA512wECDSA; + #endif /* HAVE_ECC */ + } + break; + + /* oidKeyType */ + case oidKeyType: + switch (oid) { + #ifndef NO_DSA + case DSAk: + return DSAk; + #endif /* NO_DSA */ + #ifndef NO_RSA + case RSAk: + return RSAk; + #endif /* NO_RSA */ + #ifdef HAVE_NTRU + case NTRUk: + return NTRUk; + #endif /* HAVE_NTRU */ + #ifdef HAVE_ECC + case ECDSAk: + return ECDSAk; + #endif /* HAVE_ECC */ + } + break; + + /* oidBlkType */ + case oidBlkType: + switch (oid) { + #ifdef WOLFSSL_AES_128 + case AES128CBCb: + return AES128CBCb; + #endif + #ifdef WOLFSSL_AES_192 + case AES192CBCb: + return AES192CBCb; + #endif + #ifdef WOLFSSL_AES_256 + case AES256CBCb: + return AES256CBCb; + #endif + #ifndef NO_DES3 + case DESb: + return NID_des; + case DES3b: + return NID_des3; + #endif + } + break; + + #ifdef HAVE_OCSP + case oidOcspType: + switch (oid) { + case OCSP_BASIC_OID: + return NID_id_pkix_OCSP_basic; + case OCSP_NONCE_OID: + return OCSP_NONCE_OID; + } + break; + #endif /* HAVE_OCSP */ + + /* oidCertExtType */ + case oidCertExtType: + switch (oid) { + case BASIC_CA_OID: + return BASIC_CA_OID; + case ALT_NAMES_OID: + return ALT_NAMES_OID; + case CRL_DIST_OID: + return CRL_DIST_OID; + case AUTH_INFO_OID: + return AUTH_INFO_OID; + case AUTH_KEY_OID: + return AUTH_KEY_OID; + case SUBJ_KEY_OID: + return SUBJ_KEY_OID; + case INHIBIT_ANY_OID: + return INHIBIT_ANY_OID; + case KEY_USAGE_OID: + return NID_key_usage; + case NAME_CONS_OID: + return NID_name_constraints; + case CERT_POLICY_OID: + return NID_certificate_policies; + } + break; + + /* oidCertAuthInfoType */ + case oidCertAuthInfoType: + switch (oid) { + case AIA_OCSP_OID: + return AIA_OCSP_OID; + case AIA_CA_ISSUER_OID: + return AIA_CA_ISSUER_OID; + } + break; + + /* oidCertPolicyType */ + case oidCertPolicyType: + switch (oid) { + case CP_ANY_OID: + return NID_any_policy; + } + break; + + /* oidCertAltNameType */ + case oidCertAltNameType: + switch (oid) { + case HW_NAME_OID: + return NID_hw_name_oid; + } + break; + + /* oidCertKeyUseType */ + case oidCertKeyUseType: + switch (oid) { + case EKU_ANY_OID: + return NID_anyExtendedKeyUsage; + case EKU_SERVER_AUTH_OID: + return EKU_SERVER_AUTH_OID; + case EKU_CLIENT_AUTH_OID: + return EKU_CLIENT_AUTH_OID; + case EKU_OCSP_SIGN_OID: + return EKU_OCSP_SIGN_OID; + } + break; + + /* oidKdfType */ + case oidKdfType: + switch (oid) { + case PBKDF2_OID: + return PBKDF2_OID; + } + break; + + /* oidPBEType */ + case oidPBEType: + switch (oid) { + case PBE_SHA1_RC4_128: + return PBE_SHA1_RC4_128; + case PBE_SHA1_DES: + return PBE_SHA1_DES; + case PBE_SHA1_DES3: + return PBE_SHA1_DES3; + } + break; + + /* oidKeyWrapType */ + case oidKeyWrapType: + switch (oid) { + #ifdef WOLFSSL_AES_128 + case AES128_WRAP: + return AES128_WRAP; + #endif + #ifdef WOLFSSL_AES_192 + case AES192_WRAP: + return AES192_WRAP; + #endif + #ifdef WOLFSSL_AES_256 + case AES256_WRAP: + return AES256_WRAP; + #endif + } + break; + + /* oidCmsKeyAgreeType */ + case oidCmsKeyAgreeType: + switch (oid) { + #ifndef NO_SHA + case dhSinglePass_stdDH_sha1kdf_scheme: + return dhSinglePass_stdDH_sha1kdf_scheme; + #endif + #ifdef WOLFSSL_SHA224 + case dhSinglePass_stdDH_sha224kdf_scheme: + return dhSinglePass_stdDH_sha224kdf_scheme; + #endif + #ifndef NO_SHA256 + case dhSinglePass_stdDH_sha256kdf_scheme: + return dhSinglePass_stdDH_sha256kdf_scheme; + #endif + #ifdef WOLFSSL_SHA384 + case dhSinglePass_stdDH_sha384kdf_scheme: + return dhSinglePass_stdDH_sha384kdf_scheme; + #endif + #ifdef WOLFSSL_SHA512 + case dhSinglePass_stdDH_sha512kdf_scheme: + return dhSinglePass_stdDH_sha512kdf_scheme; + #endif + } + break; + + default: + WOLFSSL_MSG("NID not in table"); + return -1; + } + + return -1; + } + + /* Gets the NID value that corresponds with the ASN1 object. + * + * o ASN1 object to get NID of + * + * Return NID on success and a negative value on failure + */ + int wolfSSL_OBJ_obj2nid(const WOLFSSL_ASN1_OBJECT *o) + { + word32 oid = 0; + word32 idx = 0; + + WOLFSSL_ENTER("wolfSSL_OBJ_obj2nid"); + + if (o == NULL) { + return -1; + } + if (o->nid > 0) + return o->nid; + if (GetObjectId(o->obj, &idx, &oid, o->grp, o->objSz) < 0) { + WOLFSSL_MSG("Issue getting OID of object"); + return -1; + } + + return oid2nid(oid, o->grp); + } + +#ifndef NO_WOLFSSL_STUB + char * wolfSSL_OBJ_nid2ln(int n) + { + (void)n; + WOLFSSL_ENTER("wolfSSL_OBJ_nid2ln"); + WOLFSSL_STUB("OBJ_nid2ln"); + + return NULL; + } +#endif + +#ifdef WOLFSSL_CERT_EXT + /* Gets the NID value that is related to the OID string passed in. Example + * string would be "2.5.29.14" for subject key ID. + * + * @TODO does not handle short names yet + * + * returns NID value on success and NID_undef on error + */ + int wolfSSL_OBJ_txt2nid(const char* s) + { + int ret; + unsigned int outSz = MAX_OID_SZ; + unsigned char out[MAX_OID_SZ]; + + WOLFSSL_ENTER("OBJ_txt2nid"); + + if (s == NULL) { + return NID_undef; + } + + ret = EncodePolicyOID(out, &outSz, s, NULL); + if (ret == 0) { + unsigned int i, sum = 0; + + /* sum OID */ + for (i = 0; i < outSz; i++) { + sum += out[i]; + } + + /* get the group that the OID's sum is in + * @TODO possible conflict with multiples */ + for (i = 0; i < WOLFSSL_OBJECT_INFO_SZ; i++) { + if (wolfssl_object_info[i].id == (int)sum) { + return wolfssl_object_info[i].nid; + } + } + } + return NID_undef; + } +#endif /* WOLFSSL_CERT_EXT */ + + + /* compatibility function. It's intended use is to remove OID's from an + * internal table that have been added with OBJ_create. wolfSSL manages it's + * own interenal OID values and does not currently support OBJ_create. */ + void wolfSSL_OBJ_cleanup(void) + { + WOLFSSL_ENTER("wolfSSL_OBJ_cleanup()"); + } + + + #ifndef NO_WOLFSSL_STUB + void wolfSSL_set_verify_depth(WOLFSSL *ssl, int depth) { + WOLFSSL_ENTER("wolfSSL_set_verify_depth"); +#ifndef OPENSSL_EXTRA + (void)ssl; + (void)depth; + WOLFSSL_STUB("wolfSSL_set_verify_depth"); +#else + ssl->options.verifyDepth = (byte)depth; +#endif + } + #endif + + + WOLFSSL_ASN1_OBJECT * wolfSSL_X509_NAME_ENTRY_get_object(WOLFSSL_X509_NAME_ENTRY *ne) { + WOLFSSL_ENTER("wolfSSL_X509_NAME_ENTRY_get_object"); + if (ne == NULL) return NULL; + if (wolfSSL_OBJ_nid2obj_ex(ne->nid, &ne->object) != NULL) { + ne->object.nid = ne->nid; + return &ne->object; + } + return NULL; + } + + + /* looks up the DN given the location "loc". "loc" is the number indicating + * the order that the DN was parsed as, 0 is first DN parsed. + * + * returns the setup WOLFSSL_X509_NAME pointer on success and NULL on fail + */ + static WOLFSSL_X509_NAME *wolfSSL_nameByLoc( WOLFSSL_X509_NAME *name, int loc) + { + char* pt = NULL; + int sz = 0; + + switch (name->fullName.loc[loc]) + { + case ASN_COMMON_NAME: + sz = name->fullName.cnLen; + pt = &name->fullName.fullName[name->fullName.cnIdx], + name->cnEntry.nid = name->fullName.cnNid; + break; + case ASN_COUNTRY_NAME: + sz = name->fullName.cLen; + pt = &name->fullName.fullName[name->fullName.cIdx], + name->cnEntry.nid = name->fullName.cNid; + break; + case ASN_LOCALITY_NAME: + sz = name->fullName.lLen; + pt = &name->fullName.fullName[name->fullName.lIdx]; + name->cnEntry.nid = name->fullName.lNid; + break; + case ASN_STATE_NAME: + sz = name->fullName.stLen; + pt = &name->fullName.fullName[name->fullName.stIdx]; + name->cnEntry.nid = name->fullName.stNid; + break; + case ASN_ORG_NAME: + sz = name->fullName.oLen; + pt = &name->fullName.fullName[name->fullName.oIdx]; + name->cnEntry.nid = name->fullName.oNid; + break; + case ASN_ORGUNIT_NAME: + sz = name->fullName.ouLen; + pt = &name->fullName.fullName[name->fullName.ouIdx]; + name->cnEntry.nid = name->fullName.ouNid; + break; + case ASN_EMAIL_NAME: + sz = name->fullName.emailLen; + pt = &name->fullName.fullName[name->fullName.emailIdx]; + name->cnEntry.nid = name->fullName.emailNid; + break; + case ASN_SUR_NAME: + sz = name->fullName.snLen; + pt = &name->fullName.fullName[name->fullName.snIdx]; + name->cnEntry.nid = name->fullName.snNid; + break; + case ASN_USER_ID: + sz = name->fullName.uidLen; + pt = &name->fullName.fullName[name->fullName.uidIdx]; + name->cnEntry.nid = name->fullName.uidNid; + break; + case ASN_SERIAL_NUMBER: + sz = name->fullName.serialLen; + pt = &name->fullName.fullName[name->fullName.serialIdx]; + name->cnEntry.nid = name->fullName.serialNid; + break; +#ifdef WOLFSSL_CERT_EXT + case ASN_BUS_CAT: + sz = name->fullName.bcLen; + pt = &name->fullName.fullName[name->fullName.bcIdx]; + break; +#endif + + case ASN_DOMAIN_COMPONENT: + /* get index of DC i.e. first or second or ... case */ + { + int idx = 0, i; + for (i = 0; i < loc; i++) { + if (name->fullName.loc[i] == ASN_DOMAIN_COMPONENT) { + idx++; + } + } + + /* check that index is not larger than max buffer size or larger + * than the number of domain components parsed */ + if (idx >= DOMAIN_COMPONENT_MAX || idx > name->fullName.dcNum) { + WOLFSSL_MSG("Index was larger then domain buffer"); + return NULL; + } + pt = &name->fullName.fullName[name->fullName.dcIdx[idx]], + sz = name->fullName.dcLen[idx]; + name->cnEntry.nid = ASN_DOMAIN_COMPONENT; + name->cnEntry.data.type = CTC_UTF8; + } + break; + + default: + return NULL; + } + + /* -1 to leave room for trailing terminator 0 */ + if (sz == 0 || sz >= CTC_NAME_SIZE - 1) + return NULL; + if (wolfSSL_ASN1_STRING_set(name->cnEntry.value, pt, sz) != + WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Error setting local ASN1 string data"); + return NULL; + } + name->cnEntry.value->type = CTC_UTF8; + name->cnEntry.set = 1; + return name; + } + + + WOLFSSL_X509_NAME_ENTRY *wolfSSL_X509_NAME_get_entry( + WOLFSSL_X509_NAME *name, int loc) + { + WOLFSSL_ENTER("wolfSSL_X509_NAME_get_entry"); + + if (name == NULL) { + return NULL; + } + + if (loc < 0) { + WOLFSSL_MSG("Bad argument"); + return NULL; + } + + if (loc <= DN_NAMES_MAX + name->fullName.dcNum) { + if (wolfSSL_nameByLoc(name, loc) != NULL) + return &name->cnEntry; + } else if (loc == name->fullName.cnIdx && name->x509 != NULL) { + /* get CN shortcut from x509 since it has null terminator */ + name->cnEntry.data.data = name->x509->subjectCN; + name->cnEntry.data.length = name->fullName.cnLen; + name->cnEntry.data.type = CTC_UTF8; + name->cnEntry.nid = ASN_COMMON_NAME; + name->cnEntry.set = 1; + return &name->cnEntry; + } + WOLFSSL_MSG("loc passed in is not in range of parsed DN's"); + + return NULL; + } + + #ifndef NO_WOLFSSL_STUB + void wolfSSL_sk_X509_NAME_pop_free(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk, void f (WOLFSSL_X509_NAME*)){ + (void) sk; + (void) f; + WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_pop_free"); + WOLFSSL_STUB("sk_X509_NAME_pop_free"); + } + #endif + #ifndef NO_WOLFSSL_STUB + int wolfSSL_X509_check_private_key(WOLFSSL_X509 *x509, WOLFSSL_EVP_PKEY *key){ + (void) x509; + (void) key; + WOLFSSL_ENTER("wolfSSL_X509_check_private_key"); + WOLFSSL_STUB("X509_check_private_key"); + + return WOLFSSL_SUCCESS; + } + + WOLF_STACK_OF(WOLFSSL_X509_NAME) *wolfSSL_dup_CA_list( WOLF_STACK_OF(WOLFSSL_X509_NAME) *sk ){ + (void) sk; + WOLFSSL_ENTER("wolfSSL_dup_CA_list"); + WOLFSSL_STUB("SSL_dup_CA_list"); + + return NULL; + } + #endif + +#endif /* OPENSSL_ALL || HAVE_LIGHTY || WOLFSSL_MYSQL_COMPATIBLE || HAVE_STUNNEL || WOLFSSL_NGINX || HAVE_POCO_LIB || WOLFSSL_HAPROXY */ +#endif /* OPENSSL_EXTRA */ + +#ifdef OPENSSL_EXTRA + +/* wolfSSL uses negative values for error states. This function returns an + * unsigned type so the value returned is the absolute value of the error. + */ +unsigned long wolfSSL_ERR_peek_last_error_line(const char **file, int *line) +{ + WOLFSSL_ENTER("wolfSSL_ERR_peek_last_error"); + + (void)line; + (void)file; +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(DEBUG_WOLFSSL) || defined(WOLFSSL_HAPROXY) + { + int ret; + + if ((ret = wc_PeekErrorNode(-1, file, NULL, line)) < 0) { + WOLFSSL_MSG("Issue peeking at error node in queue"); + return 0; + } + #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) + if (ret == -ASN_NO_PEM_HEADER) + return (ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE; + #endif + return (unsigned long)ret; + } +#else + return (unsigned long)(0 - NOT_COMPILED_IN); +#endif +} + + +#ifndef NO_CERTS +int wolfSSL_CTX_use_PrivateKey(WOLFSSL_CTX *ctx, WOLFSSL_EVP_PKEY *pkey) +{ + WOLFSSL_ENTER("wolfSSL_CTX_use_PrivateKey"); + + if (ctx == NULL || pkey == NULL) { + return WOLFSSL_FAILURE; + } + + if (pkey->pkey.ptr != NULL) { + /* ptr for WOLFSSL_EVP_PKEY struct is expected to be DER format */ + return wolfSSL_CTX_use_PrivateKey_buffer(ctx, + (const unsigned char*)pkey->pkey.ptr, + pkey->pkey_sz, SSL_FILETYPE_ASN1); + } + + WOLFSSL_MSG("wolfSSL private key not set"); + return BAD_FUNC_ARG; +} +#endif /* !NO_CERTS */ + + +void* wolfSSL_CTX_get_ex_data(const WOLFSSL_CTX* ctx, int idx) +{ + WOLFSSL_ENTER("wolfSSL_CTX_get_ex_data"); + #ifdef HAVE_EX_DATA + if(ctx != NULL && idx < MAX_EX_DATA && idx >= 0) { + return ctx->ex_data[idx]; + } + #else + (void)ctx; + (void)idx; + #endif + return NULL; +} + +int wolfSSL_CTX_get_ex_new_index(long idx, void* arg, void* a, void* b, + void* c) +{ + static int ctx_idx = 0; + + WOLFSSL_ENTER("wolfSSL_CTX_get_ex_new_index"); + (void)idx; + (void)arg; + (void)a; + (void)b; + (void)c; + + return ctx_idx++; +} + + +/* Return the index that can be used for the WOLFSSL structure to store + * application data. + * + */ +int wolfSSL_get_ex_new_index(long argValue, void* arg, + WOLFSSL_CRYPTO_EX_new* cb1, WOLFSSL_CRYPTO_EX_dup* cb2, + WOLFSSL_CRYPTO_EX_free* cb3) +{ + static int ssl_idx = 0; + + WOLFSSL_ENTER("wolfSSL_get_ex_new_index"); + + (void)argValue; + (void)arg; + (void)cb1; + (void)cb2; + (void)cb3; + + return ssl_idx++; +} + + +int wolfSSL_CTX_set_ex_data(WOLFSSL_CTX* ctx, int idx, void* data) +{ + WOLFSSL_ENTER("wolfSSL_CTX_set_ex_data"); + #ifdef HAVE_EX_DATA + if (ctx != NULL && idx < MAX_EX_DATA) + { + ctx->ex_data[idx] = data; + return WOLFSSL_SUCCESS; + } + #else + (void)ctx; + (void)idx; + (void)data; + #endif + return WOLFSSL_FAILURE; +} + + +/* Returns char* to app data stored in ex[0]. + * + * ssl WOLFSSL structure to get app data from + */ +void* wolfSSL_get_app_data(const WOLFSSL *ssl) +{ + /* checkout exdata stuff... */ + WOLFSSL_ENTER("wolfSSL_get_app_data"); + + return wolfSSL_get_ex_data(ssl, 0); +} + + +/* Set ex array 0 to have app data + * + * ssl WOLFSSL struct to set app data in + * arg data to be stored + * + * Returns SSL_SUCCESS on success and SSL_FAILURE on failure + */ +int wolfSSL_set_app_data(WOLFSSL *ssl, void* arg) { + WOLFSSL_ENTER("wolfSSL_set_app_data"); + + return wolfSSL_set_ex_data(ssl, 0, arg); +} + + +int wolfSSL_set_ex_data(WOLFSSL* ssl, int idx, void* data) +{ + WOLFSSL_ENTER("wolfSSL_set_ex_data"); +#if defined(HAVE_EX_DATA) || defined(FORTRESS) + if (ssl != NULL && idx < MAX_EX_DATA) + { + ssl->ex_data[idx] = data; + return WOLFSSL_SUCCESS; + } +#else + WOLFSSL_MSG("HAVE_EX_DATA macro is not defined"); + (void)ssl; + (void)idx; + (void)data; +#endif + return WOLFSSL_FAILURE; +} + + + +void* wolfSSL_get_ex_data(const WOLFSSL* ssl, int idx) +{ + WOLFSSL_ENTER("wolfSSL_get_ex_data"); +#if defined(HAVE_EX_DATA) || defined(FORTRESS) + if (ssl != NULL && idx < MAX_EX_DATA && idx >= 0) + return ssl->ex_data[idx]; +#else + WOLFSSL_MSG("HAVE_EX_DATA macro is not defined"); + (void)ssl; + (void)idx; +#endif + return 0; +} + +#ifndef NO_DSA +WOLFSSL_DSA *wolfSSL_PEM_read_bio_DSAparams(WOLFSSL_BIO *bp, WOLFSSL_DSA **x, + pem_password_cb *cb, void *u) +{ + WOLFSSL_DSA* dsa; + DsaKey* key; + int length; + unsigned char* buf; + word32 bufSz; + int ret; + word32 idx = 0; + DerBuffer* pDer; + + WOLFSSL_ENTER("wolfSSL_PEM_read_bio_DSAparams"); + + ret = wolfSSL_BIO_get_mem_data(bp, &buf); + if (ret <= 0) { + WOLFSSL_LEAVE("wolfSSL_PEM_read_bio_DSAparams", ret); + return NULL; + } + + bufSz = (word32)ret; + + if (cb != NULL || u != NULL) { + /* + * cb is for a call back when encountering encrypted PEM files + * if cb == NULL and u != NULL then u = null terminated password string + */ + WOLFSSL_MSG("Not yet supporting call back or password for encrypted PEM"); + } + + if ((ret = PemToDer(buf, (long)bufSz, DSA_PARAM_TYPE, &pDer, NULL, NULL, + NULL)) < 0 ) { + WOLFSSL_MSG("Issue converting from PEM to DER"); + return NULL; + } + + if ((ret = GetSequence(pDer->buffer, &idx, &length, pDer->length)) < 0) { + WOLFSSL_LEAVE("wolfSSL_PEM_read_bio_DSAparams", ret); + FreeDer(&pDer); + return NULL; + } + + dsa = wolfSSL_DSA_new(); + if (dsa == NULL) { + FreeDer(&pDer); + WOLFSSL_MSG("Error creating DSA struct"); + return NULL; + } + + key = (DsaKey*)dsa->internal; + if (key == NULL) { + FreeDer(&pDer); + wolfSSL_DSA_free(dsa); + WOLFSSL_MSG("Error finding DSA key struct"); + return NULL; + } + + if (GetInt(&key->p, pDer->buffer, &idx, pDer->length) < 0 || + GetInt(&key->q, pDer->buffer, &idx, pDer->length) < 0 || + GetInt(&key->g, pDer->buffer, &idx, pDer->length) < 0 ) { + WOLFSSL_MSG("dsa key error"); + FreeDer(&pDer); + wolfSSL_DSA_free(dsa); + return NULL; + } + + if (SetIndividualExternal(&dsa->p, &key->p) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("dsa p key error"); + FreeDer(&pDer); + wolfSSL_DSA_free(dsa); + return NULL; + } + + if (SetIndividualExternal(&dsa->q, &key->q) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("dsa q key error"); + FreeDer(&pDer); + wolfSSL_DSA_free(dsa); + return NULL; + } + + if (SetIndividualExternal(&dsa->g, &key->g) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("dsa g key error"); + FreeDer(&pDer); + wolfSSL_DSA_free(dsa); + return NULL; + } + + if (x != NULL) { + *x = dsa; + } + + FreeDer(&pDer); + return dsa; +} +#endif /* NO_DSA */ + +#define WOLFSSL_BIO_INCLUDED +#include "src/bio.c" + +/* Begin functions for openssl/buffer.h */ +WOLFSSL_BUF_MEM* wolfSSL_BUF_MEM_new(void) +{ + WOLFSSL_BUF_MEM* buf; + buf = (WOLFSSL_BUF_MEM*)XMALLOC(sizeof(WOLFSSL_BUF_MEM), NULL, + DYNAMIC_TYPE_OPENSSL); + if (buf) { + XMEMSET(buf, 0, sizeof(WOLFSSL_BUF_MEM)); + } + return buf; +} + + +/* returns length of buffer on success */ +int wolfSSL_BUF_MEM_grow(WOLFSSL_BUF_MEM* buf, size_t len) +{ + int len_int = (int)len; + int mx; + + /* verify provided arguments */ + if (buf == NULL || len_int < 0) { + return 0; /* BAD_FUNC_ARG; */ + } + + /* check to see if fits in existing length */ + if (buf->length > len) { + buf->length = len; + return len_int; + } + + /* check to see if fits in max buffer */ + if (buf->max >= len) { + if (buf->data != NULL) { + XMEMSET(&buf->data[buf->length], 0, len - buf->length); + } + buf->length = len; + return len_int; + } + + /* expand size, to handle growth */ + mx = (len_int + 3) / 3 * 4; + + /* use realloc */ + buf->data = (char*)XREALLOC(buf->data, mx, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (buf->data == NULL) { + return 0; /* ERR_R_MALLOC_FAILURE; */ + } + + buf->max = mx; + XMEMSET(&buf->data[buf->length], 0, len - buf->length); + buf->length = len; + + return len_int; +} + +void wolfSSL_BUF_MEM_free(WOLFSSL_BUF_MEM* buf) +{ + if (buf) { + if (buf->data) { + XFREE(buf->data, NULL, DYNAMIC_TYPE_TMP_BUFFER); + buf->data = NULL; + } + buf->max = 0; + buf->length = 0; + XFREE(buf, NULL, DYNAMIC_TYPE_OPENSSL); + } +} +/* End Functions for openssl/buffer.h */ + +#endif /* OPENSSL_EXTRA */ + + +#if defined(HAVE_LIGHTY) || defined(HAVE_STUNNEL) \ + || defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(OPENSSL_EXTRA) + +WOLFSSL_BIO *wolfSSL_BIO_new_file(const char *filename, const char *mode) +{ +#ifndef NO_FILESYSTEM + WOLFSSL_BIO* bio; + XFILE fp; + + WOLFSSL_ENTER("wolfSSL_BIO_new_file"); + + fp = XFOPEN(filename, mode); + if (fp == XBADFILE) + return NULL; + + bio = wolfSSL_BIO_new(wolfSSL_BIO_s_file()); + if (bio == NULL) { + XFCLOSE(fp); + return bio; + } + + if (wolfSSL_BIO_set_fp(bio, fp, BIO_CLOSE) != WOLFSSL_SUCCESS) { + XFCLOSE(fp); + wolfSSL_BIO_free(bio); + bio = NULL; + } + + /* file is closed when BIO is free'd */ + return bio; +#else + (void)filename; + (void)mode; + return NULL; +#endif /* NO_FILESYSTEM */ +} + + +#ifndef NO_DH +WOLFSSL_DH *wolfSSL_PEM_read_bio_DHparams(WOLFSSL_BIO *bio, WOLFSSL_DH **x, + pem_password_cb *cb, void *u) +{ +#ifndef NO_FILESYSTEM + WOLFSSL_DH* localDh = NULL; + unsigned char* mem = NULL; + word32 size; + long sz; + int ret; + DerBuffer *der = NULL; + byte* p = NULL; + byte* g = NULL; + word32 pSz = MAX_DH_SIZE; + word32 gSz = MAX_DH_SIZE; + int memAlloced = 0; + + WOLFSSL_ENTER("wolfSSL_PEM_read_bio_DHparams"); + (void)cb; + (void)u; + + if (bio == NULL) { + WOLFSSL_MSG("Bad Function Argument bio is NULL"); + return NULL; + } + + if (bio->type == WOLFSSL_BIO_MEMORY) { + /* Use the buffer directly. */ + ret = wolfSSL_BIO_get_mem_data(bio, &mem); + if (mem == NULL || ret <= 0) { + WOLFSSL_MSG("Failed to get data from bio struct"); + goto end; + } + size = ret; + } + else if (bio->type == WOLFSSL_BIO_FILE) { + /* Read whole file into a new buffer. */ + if(XFSEEK(bio->file, 0, SEEK_END) != 0) + goto end; + sz = XFTELL(bio->file); + if(XFSEEK(bio->file, 0, SEEK_SET) != 0) + goto end; + if (sz <= 0L) + goto end; + mem = (unsigned char*)XMALLOC(sz, NULL, DYNAMIC_TYPE_PEM); + if (mem == NULL) + goto end; + memAlloced = 1; + + if (wolfSSL_BIO_read(bio, (char *)mem, (int)sz) <= 0) + goto end; + size = (word32)sz; + } + else { + WOLFSSL_MSG("BIO type not supported for reading DH parameters"); + goto end; + } + + ret = PemToDer(mem, size, DH_PARAM_TYPE, &der, NULL, NULL, NULL); + if (ret != 0) + goto end; + + /* Use the object passed in, otherwise allocate a new object */ + if (x != NULL) + localDh = *x; + if (localDh == NULL) { + localDh = wolfSSL_DH_new(); + if (localDh == NULL) + goto end; + } + + /* Load data in manually */ + p = (byte*)XMALLOC(pSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + g = (byte*)XMALLOC(gSz, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + if (p == NULL || g == NULL) + goto end; + + /* Extract the p and g as data from the DER encoded DH parameters. */ + ret = wc_DhParamsLoad(der->buffer, der->length, p, &pSz, g, &gSz); + if (ret != 0) { + if (x != NULL && localDh != *x) + XFREE(localDh, NULL, DYNAMIC_TYPE_OPENSSL); + localDh = NULL; + goto end; + } + + if (x != NULL) + *x = localDh; + + /* Put p and g in as big numbers. */ + if (localDh->p != NULL) { + wolfSSL_BN_free(localDh->p); + localDh->p = NULL; + } + if (localDh->g != NULL) { + wolfSSL_BN_free(localDh->g); + localDh->g = NULL; + } + localDh->p = wolfSSL_BN_bin2bn(p, pSz, NULL); + localDh->g = wolfSSL_BN_bin2bn(g, gSz, NULL); + if (localDh->p == NULL || localDh->g == NULL) { + if (x != NULL && localDh != *x) + wolfSSL_DH_free(localDh); + localDh = NULL; + } + + if (localDh != NULL && localDh->inSet == 0) { + if (SetDhInternal(localDh) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Unable to set internal DH structure"); + wolfSSL_DH_free(localDh); + localDh = NULL; + } + } + +end: + if (memAlloced) XFREE(mem, NULL, DYNAMIC_TYPE_PEM); + if (der != NULL) FreeDer(&der); + XFREE(p, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + XFREE(g, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + return localDh; +#else + (void)bio; + (void)x; + (void)cb; + (void)u; + return NULL; +#endif +} + +#ifndef NO_FILESYSTEM +/* Convert DH key parameters to DER format, write to output (outSz) + * If output is NULL then max expected size is set to outSz and LENGTH_ONLY_E is + * returned. + * + * Note : static function due to redefinition complications with DhKey and FIPS + * version 2 build. + * + * return bytes written on success */ +static int wc_DhParamsToDer(DhKey* key, byte* out, word32* outSz) +{ + word32 sz = 0, idx = 0; + int pSz = 0, gSz = 0, ret; + byte scratch[MAX_LENGTH_SZ]; + + if (key == NULL || outSz == NULL) { + return BAD_FUNC_ARG; + } + + pSz = mp_unsigned_bin_size(&key->p); + if (pSz < 0) { + return pSz; + } + if (mp_leading_bit(&key->p)) { + pSz++; + } + + gSz = mp_unsigned_bin_size(&key->g); + if (gSz < 0) { + return gSz; + } + if (mp_leading_bit(&key->g)) { + gSz++; + } + + sz = ASN_TAG_SZ; /* Integer */ + sz += SetLength(pSz, scratch); + sz += ASN_TAG_SZ; /* Integer */ + sz += SetLength(gSz, scratch); + sz += gSz + pSz; + + if (out == NULL) { + byte seqScratch[MAX_SEQ_SZ]; + + *outSz = sz + SetSequence(sz, seqScratch); + return LENGTH_ONLY_E; + } + + if (*outSz < MAX_SEQ_SZ || *outSz < sz) { + return BUFFER_E; + } + + idx += SetSequence(sz, out); + if (*outSz < idx + sz) { + return BUFFER_E; + } + + out[idx++] = ASN_INTEGER; + idx += SetLength(pSz, out + idx); + if (mp_leading_bit(&key->p)) { + out[idx++] = 0x00; + pSz -= 1; /* subtract 1 from size to account for leading 0 */ + } + ret = mp_to_unsigned_bin(&key->p, out + idx); + if (ret != MP_OKAY) { + return BUFFER_E; + } + idx += pSz; + + out[idx++] = ASN_INTEGER; + idx += SetLength(gSz, out + idx); + if (mp_leading_bit(&key->g)) { + out[idx++] = 0x00; + gSz -= 1; /* subtract 1 from size to account for leading 0 */ + } + ret = mp_to_unsigned_bin(&key->g, out + idx); + if (ret != MP_OKAY) { + return BUFFER_E; + } + idx += gSz; + return idx; +} + + +/* Writes the DH parameters in PEM format from "dh" out to the file pointer + * passed in. + * + * returns WOLFSSL_SUCCESS on success + */ +int wolfSSL_PEM_write_DHparams(XFILE fp, WOLFSSL_DH* dh) +{ + int ret; + word32 derSz = 0, pemSz = 0; + byte *der, *pem; + DhKey* key; + + WOLFSSL_ENTER("wolfSSL_PEM_write_DHparams"); + + if (dh == NULL) { + WOLFSSL_LEAVE("wolfSSL_PEM_write_DHparams", BAD_FUNC_ARG); + return WOLFSSL_FAILURE; + } + + if (dh->inSet == 0) { + if (SetDhInternal(dh) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Unable to set internal DH structure"); + return WOLFSSL_FAILURE; + } + } + key = (DhKey*)dh->internal; + ret = wc_DhParamsToDer(key, NULL, &derSz); + if (ret != LENGTH_ONLY_E) { + WOLFSSL_MSG("Failed to get size of DH params"); + WOLFSSL_LEAVE("wolfSSL_PEM_write_DHparams", ret); + return WOLFSSL_FAILURE; + } + + der = (byte*)XMALLOC(derSz, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (der == NULL) { + WOLFSSL_LEAVE("wolfSSL_PEM_write_DHparams", MEMORY_E); + return WOLFSSL_FAILURE; + } + ret = wc_DhParamsToDer(key, der, &derSz); + if (ret <= 0) { + WOLFSSL_MSG("Failed to export DH params"); + WOLFSSL_LEAVE("wolfSSL_PEM_write_DHparams", ret); + XFREE(der, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; + } + + /* convert to PEM */ + ret = wc_DerToPem(der, derSz, NULL, 0, DH_PARAM_TYPE); + if (ret < 0) { + WOLFSSL_MSG("Failed to convert DH params to PEM"); + WOLFSSL_LEAVE("wolfSSL_PEM_write_DHparams", ret); + XFREE(der, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + pemSz = (word32)ret; + + pem = (byte*)XMALLOC(pemSz, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (pem == NULL) { + WOLFSSL_LEAVE("wolfSSL_PEM_write_DHparams", MEMORY_E); + XFREE(der, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + ret = wc_DerToPem(der, derSz, pem, pemSz, DH_PARAM_TYPE); + XFREE(der, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (ret < 0) { + WOLFSSL_MSG("Failed to convert DH params to PEM"); + WOLFSSL_LEAVE("wolfSSL_PEM_write_DHparams", ret); + XFREE(pem, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + + ret = (int)XFWRITE(pem, 1, pemSz, fp); + XFREE(pem, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (ret <= 0) { + WOLFSSL_MSG("Failed to write to file"); + WOLFSSL_LEAVE("wolfSSL_PEM_write_DHparams", ret); + return WOLFSSL_FAILURE; + } + + WOLFSSL_LEAVE("wolfSSL_PEM_write_DHparams", WOLFSSL_SUCCESS); + return WOLFSSL_SUCCESS; +} +#endif /* !NO_FILESYSTEM */ +#endif + +#ifdef WOLFSSL_CERT_GEN + +#ifdef WOLFSSL_CERT_REQ +/* writes the x509 from x to the WOLFSSL_BIO bp + * + * returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on fail + */ +int wolfSSL_PEM_write_bio_X509_REQ(WOLFSSL_BIO *bp, WOLFSSL_X509 *x) +{ + byte* pem; + int pemSz = 0; + const unsigned char* der; + int derSz; + int ret; + + WOLFSSL_ENTER("wolfSSL_PEM_write_bio_X509_REQ()"); + + if (x == NULL || bp == NULL) { + return WOLFSSL_FAILURE; + } + + der = wolfSSL_X509_get_der(x, &derSz); + if (der == NULL) { + return WOLFSSL_FAILURE; + } + + /* get PEM size */ + pemSz = wc_DerToPemEx(der, derSz, NULL, 0, NULL, CERTREQ_TYPE); + if (pemSz < 0) { + return WOLFSSL_FAILURE; + } + + /* create PEM buffer and convert from DER */ + pem = (byte*)XMALLOC(pemSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (pem == NULL) { + return WOLFSSL_FAILURE; + } + if (wc_DerToPemEx(der, derSz, pem, pemSz, NULL, CERTREQ_TYPE) < 0) { + XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; + } + + /* write the PEM to BIO */ + ret = wolfSSL_BIO_write(bp, pem, pemSz); + XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + if (ret <= 0) return WOLFSSL_FAILURE; + return WOLFSSL_SUCCESS; +} +#endif /* WOLFSSL_CERT_REQ */ + + +/* writes the x509 from x to the WOLFSSL_BIO bp + * + * returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on fail + */ +int wolfSSL_PEM_write_bio_X509_AUX(WOLFSSL_BIO *bp, WOLFSSL_X509 *x) +{ + byte* pem; + int pemSz = 0; + const unsigned char* der; + int derSz; + int ret; + + WOLFSSL_ENTER("wolfSSL_PEM_write_bio_X509_AUX()"); + + if (bp == NULL || x == NULL) { + WOLFSSL_MSG("NULL argument passed in"); + return WOLFSSL_FAILURE; + } + + der = wolfSSL_X509_get_der(x, &derSz); + if (der == NULL) { + return WOLFSSL_FAILURE; + } + + /* get PEM size */ + pemSz = wc_DerToPemEx(der, derSz, NULL, 0, NULL, CERT_TYPE); + if (pemSz < 0) { + return WOLFSSL_FAILURE; + } + + /* create PEM buffer and convert from DER */ + pem = (byte*)XMALLOC(pemSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (pem == NULL) { + return WOLFSSL_FAILURE; + } + if (wc_DerToPemEx(der, derSz, pem, pemSz, NULL, CERT_TYPE) < 0) { + XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; + } + + /* write the PEM to BIO */ + ret = wolfSSL_BIO_write(bp, pem, pemSz); + XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + if (ret <= 0) return WOLFSSL_FAILURE; + return WOLFSSL_SUCCESS; +} +#endif /* WOLFSSL_CERT_GEN */ + +int wolfSSL_PEM_write_bio_X509(WOLFSSL_BIO *bio, WOLFSSL_X509 *cert) +{ + byte* pem; + int pemSz = 0; + const unsigned char* der; + int derSz; + int ret; + + WOLFSSL_ENTER("wolfSSL_PEM_write_bio_X509_AUX()"); + + if (bio == NULL || cert == NULL) { + WOLFSSL_MSG("NULL argument passed in"); + return WOLFSSL_FAILURE; + } + + der = wolfSSL_X509_get_der(cert, &derSz); + if (der == NULL) { + return WOLFSSL_FAILURE; + } + + /* get PEM size */ + pemSz = wc_DerToPemEx(der, derSz, NULL, 0, NULL, CERT_TYPE); + if (pemSz < 0) { + return WOLFSSL_FAILURE; + } + + /* create PEM buffer and convert from DER */ + pem = (byte*)XMALLOC(pemSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (pem == NULL) { + return WOLFSSL_FAILURE; + } + if (wc_DerToPemEx(der, derSz, pem, pemSz, NULL, CERT_TYPE) < 0) { + XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; + } + + /* write the PEM to BIO */ + ret = wolfSSL_BIO_write(bio, pem, pemSz); + XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + if (ret <= 0) return WOLFSSL_FAILURE; + return WOLFSSL_SUCCESS; +} + + +#if defined(OPENSSL_EXTRA) && !defined(NO_DH) +/* Intialize ctx->dh with dh's params. Return WOLFSSL_SUCCESS on ok */ +long wolfSSL_CTX_set_tmp_dh(WOLFSSL_CTX* ctx, WOLFSSL_DH* dh) +{ + int pSz, gSz; + byte *p, *g; + int ret=0; + + WOLFSSL_ENTER("wolfSSL_CTX_set_tmp_dh"); + + if(!ctx || !dh) + return BAD_FUNC_ARG; + + /* Get needed size for p and g */ + pSz = wolfSSL_BN_bn2bin(dh->p, NULL); + gSz = wolfSSL_BN_bn2bin(dh->g, NULL); + + if(pSz <= 0 || gSz <= 0) + return WOLFSSL_FATAL_ERROR; + + p = (byte*)XMALLOC(pSz, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); + if(!p) + return MEMORY_E; + + g = (byte*)XMALLOC(gSz, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); + if(!g) { + XFREE(p, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); + return MEMORY_E; + } + + pSz = wolfSSL_BN_bn2bin(dh->p, p); + gSz = wolfSSL_BN_bn2bin(dh->g, g); + + if(pSz >= 0 && gSz >= 0) /* Conversion successful */ + ret = wolfSSL_CTX_SetTmpDH(ctx, p, pSz, g, gSz); + + XFREE(p, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); + XFREE(g, ctx->heap, DYNAMIC_TYPE_PUBLIC_KEY); + + return pSz > 0 && gSz > 0 ? ret : WOLFSSL_FATAL_ERROR; +} +#endif /* OPENSSL_EXTRA && !NO_DH */ + + +/* returns the enum value associated with handshake state + * + * ssl the WOLFSSL structure to get state of + */ +int wolfSSL_get_state(const WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_get_state"); + + if (ssl == NULL) { + WOLFSSL_MSG("Null argument passed in"); + return SSL_FAILURE; + } + + return ssl->options.handShakeState; +} +#endif /* HAVE_LIGHTY || HAVE_STUNNEL || WOLFSSL_MYSQL_COMPATIBLE */ + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO) + +/* Returns the verifyCallback from the ssl structure if successful. +Returns NULL otherwise. */ +VerifyCallback wolfSSL_get_verify_callback(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_get_verify_callback()"); + if (ssl) { + return ssl->verifyCallback; + } + return NULL; +} + +/* Creates a new bio pair. +Returns WOLFSSL_SUCCESS if no error, WOLFSSL_FAILURE otherwise.*/ +int wolfSSL_BIO_new_bio_pair(WOLFSSL_BIO **bio1_p, size_t writebuf1, + WOLFSSL_BIO **bio2_p, size_t writebuf2) +{ + WOLFSSL_BIO *bio1 = NULL, *bio2 = NULL; + int ret = 1; + + WOLFSSL_ENTER("wolfSSL_BIO_new_bio_pair()"); + + if (bio1_p == NULL || bio2_p == NULL) { + WOLFSSL_MSG("Bad Function Argument"); + return BAD_FUNC_ARG; + } + + /* set up the new bio structures and write buf sizes */ + if ((bio1 = wolfSSL_BIO_new(wolfSSL_BIO_s_bio())) == NULL) { + WOLFSSL_MSG("Bio allocation failed"); + ret = WOLFSSL_FAILURE; + } + if (ret) { + if ((bio2 = wolfSSL_BIO_new(wolfSSL_BIO_s_bio())) == NULL) { + WOLFSSL_MSG("Bio allocation failed"); + ret = WOLFSSL_FAILURE; + } + } + if (ret && writebuf1) { + if (!(ret = wolfSSL_BIO_set_write_buf_size(bio1, writebuf1))) { + WOLFSSL_MSG("wolfSSL_BIO_set_write_buf() failure"); + } + } + if (ret && writebuf2) { + if (!(ret = wolfSSL_BIO_set_write_buf_size(bio2, writebuf2))) { + WOLFSSL_MSG("wolfSSL_BIO_set_write_buf() failure"); + } + } + + if (ret) { + if ((ret = wolfSSL_BIO_make_bio_pair(bio1, bio2))) { + *bio1_p = bio1; + *bio2_p = bio2; + } + } + if (!ret) { + wolfSSL_BIO_free(bio1); + bio1 = NULL; + wolfSSL_BIO_free(bio2); + bio2 = NULL; + } + return ret; +} + + +#if !defined(NO_RSA) +/* Converts an rsa key from a bio buffer into an internal rsa structure. +Returns a pointer to the new WOLFSSL_RSA structure. */ +WOLFSSL_RSA* wolfSSL_d2i_RSAPrivateKey_bio(WOLFSSL_BIO *bio, WOLFSSL_RSA **out) +{ + const unsigned char* bioMem = NULL; + int bioMemSz = 0; + WOLFSSL_RSA* key = NULL; + unsigned char maxKeyBuf[4096]; + unsigned char* bufPtr = NULL; + unsigned char* extraBioMem = NULL; + int extraBioMemSz = 0; + int derLength = 0; + int j = 0, i = 0; + + WOLFSSL_ENTER("wolfSSL_d2i_RSAPrivateKey_bio()"); + + if (bio == NULL) { + WOLFSSL_MSG("Bad Function Argument"); + return NULL; + } + (void)out; + + bioMemSz = wolfSSL_BIO_pending(bio); + if (bioMemSz <= 0) { + WOLFSSL_MSG("wolfSSL_BIO_pending() failure"); + return NULL; + } + + bioMem = (unsigned char*)XMALLOC(bioMemSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (bioMem == NULL) { + WOLFSSL_MSG("Malloc failure"); + return NULL; + } + + bufPtr = maxKeyBuf; + if (wolfSSL_BIO_read(bio, (unsigned char*)bioMem, (int)bioMemSz) == bioMemSz) { + const byte* bioMemPt = bioMem; /* leave bioMem pointer unaltered */ + if ((key = wolfSSL_d2i_RSAPrivateKey(NULL, &bioMemPt, bioMemSz)) == NULL) { + XFREE((unsigned char*)bioMem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + return NULL; + } + + /* This function is used to get the total length of the rsa key. */ + derLength = wolfSSL_i2d_RSAPrivateKey(key, &bufPtr); + + /* Write extra data back into bio object if necessary. */ + extraBioMemSz = (bioMemSz - derLength); + if (extraBioMemSz > 0) { + extraBioMem = (unsigned char *)XMALLOC(extraBioMemSz, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (extraBioMem == NULL) { + WOLFSSL_MSG("Malloc failure"); + XFREE((unsigned char*)extraBioMem, bio->heap, + DYNAMIC_TYPE_TMP_BUFFER); + XFREE((unsigned char*)bioMem, bio->heap, + DYNAMIC_TYPE_TMP_BUFFER); + return NULL; + } + + for (i = derLength; i < bioMemSz; i++) { + *(extraBioMem + j) = *(bioMem + i); + j++; + } + + wolfSSL_BIO_write(bio, extraBioMem, extraBioMemSz); + if (wolfSSL_BIO_pending(bio) <= 0) { + WOLFSSL_MSG("Failed to write memory to bio"); + XFREE((unsigned char*)extraBioMem, bio->heap, + DYNAMIC_TYPE_TMP_BUFFER); + XFREE((unsigned char*)bioMem, bio->heap, + DYNAMIC_TYPE_TMP_BUFFER); + return NULL; + } + XFREE((unsigned char*)extraBioMem, bio->heap, + DYNAMIC_TYPE_TMP_BUFFER); + } + + if (out != NULL && key != NULL) { + *out = key; + } + } + XFREE((unsigned char*)bioMem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + return key; +} +#endif + + +/* Adds the ASN1 certificate to the user ctx. +Returns WOLFSSL_SUCCESS if no error, returns WOLFSSL_FAILURE otherwise.*/ +int wolfSSL_CTX_use_certificate_ASN1(WOLFSSL_CTX *ctx, int derSz, + const unsigned char *der) +{ + WOLFSSL_ENTER("wolfSSL_CTX_use_certificate_ASN1()"); + if (der != NULL && ctx != NULL) { + if (wolfSSL_CTX_use_certificate_buffer(ctx, der, derSz, + WOLFSSL_FILETYPE_ASN1) == WOLFSSL_SUCCESS) { + return WOLFSSL_SUCCESS; + } + + } + return WOLFSSL_FAILURE; +} + + +#if !defined(NO_RSA) && !defined(HAVE_FAST_RSA) +/* Adds the rsa private key to the user ctx. +Returns WOLFSSL_SUCCESS if no error, returns WOLFSSL_FAILURE otherwise.*/ +int wolfSSL_CTX_use_RSAPrivateKey(WOLFSSL_CTX* ctx, WOLFSSL_RSA* rsa) +{ + int ret; + int derSize; + unsigned char maxDerBuf[4096]; + unsigned char* key = NULL; + + WOLFSSL_ENTER("wolfSSL_CTX_use_RSAPrivateKey()"); + + if (ctx == NULL || rsa == NULL) { + WOLFSSL_MSG("one or more inputs were NULL"); + return BAD_FUNC_ARG; + } + key = maxDerBuf; + /* convert RSA struct to der encoded buffer and get the size */ + if ((derSize = wolfSSL_i2d_RSAPrivateKey(rsa, &key)) <= 0) { + WOLFSSL_MSG("wolfSSL_i2d_RSAPrivateKey() failure"); + return WOLFSSL_FAILURE; + } + ret = wolfSSL_CTX_use_PrivateKey_buffer(ctx, (const unsigned char*)maxDerBuf, + derSize, SSL_FILETYPE_ASN1); + if (ret != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("wolfSSL_CTX_USE_PrivateKey_buffer() failure"); + return WOLFSSL_FAILURE; + } + return ret; +} +#endif /* NO_RSA && !HAVE_FAST_RSA */ + + +/* Converts EVP_PKEY data from a bio buffer to a WOLFSSL_EVP_PKEY structure. +Returns pointer to private EVP_PKEY struct upon success, NULL if there +is a failure.*/ +WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey_bio(WOLFSSL_BIO* bio, + WOLFSSL_EVP_PKEY** out) +{ + unsigned char* mem = NULL; + int memSz = 0; + WOLFSSL_EVP_PKEY* key = NULL; + int i = 0, j = 0; + unsigned char* extraBioMem = NULL; + int extraBioMemSz = 0; + int derLength = 0; + + WOLFSSL_ENTER("wolfSSL_d2i_PrivateKey_bio()"); + + if (bio == NULL) { + return NULL; + } + (void)out; + + memSz = wolfSSL_BIO_pending(bio); + if (memSz <= 0) { + WOLFSSL_MSG("wolfSSL_BIO_pending() failure"); + return NULL; + } + + mem = (unsigned char*)XMALLOC(memSz, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (mem == NULL) { + WOLFSSL_MSG("Malloc failure"); + return NULL; + } + + if (wolfSSL_BIO_read(bio, (unsigned char*)mem, memSz) == memSz) { + /* Determines key type and returns the new private EVP_PKEY object */ + if ((key = wolfSSL_d2i_PrivateKey_EVP(NULL, &mem, (long)memSz)) == NULL) { + WOLFSSL_MSG("wolfSSL_d2i_PrivateKey_EVP() failure"); + XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + return NULL; + } + + /* Write extra data back into bio object if necessary. */ + derLength = key->pkey_sz; + extraBioMemSz = (memSz - derLength); + if (extraBioMemSz > 0) { + extraBioMem = (unsigned char *)XMALLOC(extraBioMemSz, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (extraBioMem == NULL) { + WOLFSSL_MSG("Malloc failure"); + XFREE((unsigned char*)extraBioMem, bio->heap, + DYNAMIC_TYPE_TMP_BUFFER); + XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + return NULL; + } + + for (i = derLength; i < memSz; i++) { + *(extraBioMem + j) = *(mem + i); + j++; + } + + wolfSSL_BIO_write(bio, extraBioMem, extraBioMemSz); + if (wolfSSL_BIO_pending(bio) <= 0) { + WOLFSSL_MSG("Failed to write memory to bio"); + XFREE((unsigned char*)extraBioMem, bio->heap, + DYNAMIC_TYPE_TMP_BUFFER); + XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + return NULL; + } + XFREE((unsigned char*)extraBioMem, bio->heap, + DYNAMIC_TYPE_TMP_BUFFER); + } + + if (out != NULL && key != NULL) { + *out = key; + } + } + XFREE(mem, bio->heap, DYNAMIC_TYPE_TMP_BUFFER); + return key; +} + + +/* Converts a DER encoded private key to a WOLFSSL_EVP_PKEY structure. + * returns a pointer to a new WOLFSSL_EVP_PKEY structure on success and NULL + * on fail */ +WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey_EVP(WOLFSSL_EVP_PKEY** out, + unsigned char** in, long inSz) +{ + WOLFSSL_EVP_PKEY* pkey = NULL; + const unsigned char* mem; + long memSz = inSz; + + WOLFSSL_ENTER("wolfSSL_d2i_PrivateKey_EVP()"); + + if (in == NULL || *in == NULL || inSz < 0) { + WOLFSSL_MSG("Bad argument"); + return NULL; + } + mem = *in; + + #if !defined(NO_RSA) + { + RsaKey rsa; + word32 keyIdx = 0; + + /* test if RSA key */ + if (wc_InitRsaKey(&rsa, NULL) == 0 && + wc_RsaPrivateKeyDecode(mem, &keyIdx, &rsa, (word32)memSz) == 0) { + wc_FreeRsaKey(&rsa); + pkey = wolfSSL_PKEY_new(); + if (pkey != NULL) { + pkey->pkey_sz = keyIdx; + pkey->pkey.ptr = (char*)XMALLOC(memSz, NULL, + DYNAMIC_TYPE_PRIVATE_KEY); + if (pkey->pkey.ptr == NULL) { + wolfSSL_EVP_PKEY_free(pkey); + return NULL; + } + XMEMCPY(pkey->pkey.ptr, mem, keyIdx); + pkey->type = EVP_PKEY_RSA; + if (out != NULL) { + *out = pkey; + } + + pkey->ownRsa = 1; + pkey->rsa = wolfSSL_RSA_new(); + if (pkey->rsa == NULL) { + wolfSSL_EVP_PKEY_free(pkey); + return NULL; + } + + if (wolfSSL_RSA_LoadDer_ex(pkey->rsa, + (const unsigned char*)pkey->pkey.ptr, + pkey->pkey_sz, WOLFSSL_RSA_LOAD_PRIVATE) != 1) { + wolfSSL_EVP_PKEY_free(pkey); + return NULL; + } + + return pkey; + } + } + wc_FreeRsaKey(&rsa); + } + #endif /* NO_RSA */ + + #ifdef HAVE_ECC + { + word32 keyIdx = 0; + ecc_key ecc; + + /* test if ecc key */ + if (wc_ecc_init(&ecc) == 0 && + wc_EccPrivateKeyDecode(mem, &keyIdx, &ecc, (word32)memSz) == 0) { + wc_ecc_free(&ecc); + pkey = wolfSSL_PKEY_new(); + if (pkey != NULL) { + pkey->pkey_sz = keyIdx; + pkey->pkey.ptr = (char*)XMALLOC(keyIdx, NULL, + DYNAMIC_TYPE_PRIVATE_KEY); + if (pkey->pkey.ptr == NULL) { + wolfSSL_EVP_PKEY_free(pkey); + return NULL; + } + XMEMCPY(pkey->pkey.ptr, mem, keyIdx); + pkey->type = EVP_PKEY_EC; + if (out != NULL) { + *out = pkey; + } + return pkey; + } + } + wc_ecc_free(&ecc); + } + #endif /* HAVE_ECC */ + return pkey; +} +#endif /* OPENSSL_ALL || WOLFSSL_ASIO */ + + +/* stunnel compatibility functions*/ +#if defined(OPENSSL_ALL) || (defined(OPENSSL_EXTRA) && (defined(HAVE_STUNNEL) || \ + defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY) || \ + defined(WOLFSSL_HAPROXY))) +void wolfSSL_ERR_remove_thread_state(void* pid) +{ + (void) pid; + return; +} + +#ifndef NO_FILESYSTEM +/***TBD ***/ +void wolfSSL_print_all_errors_fp(XFILE fp) +{ + (void)fp; +} +#endif + +int wolfSSL_SESSION_set_ex_data(WOLFSSL_SESSION* session, int idx, void* data) +{ + WOLFSSL_ENTER("wolfSSL_SESSION_set_ex_data"); +#ifdef HAVE_EX_DATA + if(session != NULL && idx < MAX_EX_DATA) { + session->ex_data[idx] = data; + return WOLFSSL_SUCCESS; + } +#else + (void)session; + (void)idx; + (void)data; +#endif + return WOLFSSL_FAILURE; +} + + +int wolfSSL_SESSION_get_ex_new_index(long idx, void* data, void* cb1, + void* cb2, CRYPTO_free_func* cb3) +{ + WOLFSSL_ENTER("wolfSSL_SESSION_get_ex_new_index"); + (void)idx; + (void)cb1; + (void)cb2; + (void)cb3; + if (XSTRNCMP((const char*)data, "redirect index", 14) == 0) { + return 0; + } + else if (XSTRNCMP((const char*)data, "addr index", 10) == 0) { + return 1; + } + return WOLFSSL_FAILURE; +} + + +void* wolfSSL_SESSION_get_ex_data(const WOLFSSL_SESSION* session, int idx) +{ + WOLFSSL_ENTER("wolfSSL_SESSION_get_ex_data"); +#ifdef HAVE_EX_DATA + if (session != NULL && idx < MAX_EX_DATA && idx >= 0) + return session->ex_data[idx]; +#else + (void)session; + (void)idx; +#endif + return NULL; +} + +#ifndef NO_WOLFSSL_STUB +int wolfSSL_CRYPTO_set_mem_ex_functions(void *(*m) (size_t, const char *, int), + void *(*r) (void *, size_t, const char *, + int), void (*f) (void *)) +{ + (void) m; + (void) r; + (void) f; + WOLFSSL_ENTER("wolfSSL_CRYPTO_set_mem_ex_functions"); + WOLFSSL_STUB("CRYPTO_set_mem_ex_functions"); + + return WOLFSSL_FAILURE; +} +#endif + + +void wolfSSL_CRYPTO_cleanup_all_ex_data(void){ + WOLFSSL_ENTER("CRYPTO_cleanup_all_ex_data"); +} + + +#ifndef NO_WOLFSSL_STUB +WOLFSSL_DH *wolfSSL_DH_generate_parameters(int prime_len, int generator, + void (*callback) (int, int, void *), void *cb_arg) +{ + (void)prime_len; + (void)generator; + (void)callback; + (void)cb_arg; + WOLFSSL_ENTER("wolfSSL_DH_generate_parameters"); + WOLFSSL_STUB("DH_generate_parameters"); + + return NULL; +} +#endif + +#ifndef NO_WOLFSSL_STUB +int wolfSSL_DH_generate_parameters_ex(WOLFSSL_DH* dh, int prime_len, int generator, + void (*callback) (int, int, void *)) +{ + (void)prime_len; + (void)generator; + (void)callback; + (void)dh; + WOLFSSL_ENTER("wolfSSL_DH_generate_parameters_ex"); + WOLFSSL_STUB("DH_generate_parameters_ex"); + + return -1; +} +#endif + +void wolfSSL_ERR_load_crypto_strings(void) +{ + WOLFSSL_ENTER("wolfSSL_ERR_load_crypto_strings"); + /* Do nothing */ + return; +} + +#ifndef NO_WOLFSSL_STUB +int wolfSSL_FIPS_mode(void) +{ + WOLFSSL_ENTER("wolfSSL_FIPS_mode"); + WOLFSSL_STUB("FIPS_mode"); + + return WOLFSSL_FAILURE; +} +#endif + +#ifndef NO_WOLFSSL_STUB +int wolfSSL_FIPS_mode_set(int r) +{ + (void)r; + WOLFSSL_ENTER("wolfSSL_FIPS_mode_set"); + WOLFSSL_STUB("FIPS_mode_set"); + + return WOLFSSL_FAILURE; +} +#endif + +#ifndef NO_WOLFSSL_STUB +int wolfSSL_RAND_set_rand_method(const void *meth) +{ + (void) meth; + WOLFSSL_ENTER("wolfSSL_RAND_set_rand_method"); + WOLFSSL_STUB("RAND_set_rand_method"); + + /* if implemented RAND_bytes and RAND_pseudo_bytes need updated + * those two functions will call the respective functions from meth */ + return SSL_FAILURE; +} +#endif + +int wolfSSL_CIPHER_get_bits(const WOLFSSL_CIPHER *c, int *alg_bits) +{ + int ret = WOLFSSL_FAILURE; + WOLFSSL_ENTER("wolfSSL_CIPHER_get_bits"); + if(c != NULL && c->ssl != NULL) { + ret = 8 * c->ssl->specs.key_size; + if(alg_bits != NULL) { + *alg_bits = ret; + } + } + return ret; +} + +int wolfSSL_sk_X509_NAME_num(const WOLF_STACK_OF(WOLFSSL_X509_NAME) *s) +{ + WOLFSSL_ENTER("wolfSSL_sk_X509_NAME_num"); + + if (s == NULL) + return -1; + return (int)s->num; +} + +int wolfSSL_sk_X509_num(const WOLF_STACK_OF(WOLFSSL_X509) *s) +{ + WOLFSSL_ENTER("wolfSSL_sk_X509_num"); + + if (s == NULL) + return -1; + return (int)s->num; +} + +int wolfSSL_X509_NAME_print_ex(WOLFSSL_BIO* bio, WOLFSSL_X509_NAME* name, + int indent, unsigned long flags) +{ + int i; + (void)flags; + WOLFSSL_ENTER("wolfSSL_X509_NAME_print_ex"); + + for (i = 0; i < indent; i++) { + if (wolfSSL_BIO_write(bio, " ", 1) != 1) + return WOLFSSL_FAILURE; + } + + if (flags == XN_FLAG_RFC2253) { + if (wolfSSL_BIO_write(bio, name->name + 1, name->sz - 2) + != name->sz - 2) + return WOLFSSL_FAILURE; + } + else if (wolfSSL_BIO_write(bio, name->name, name->sz) != name->sz) + return WOLFSSL_FAILURE; + + return WOLFSSL_SUCCESS; +} + +#ifndef NO_WOLFSSL_STUB +WOLFSSL_ASN1_BIT_STRING* wolfSSL_X509_get0_pubkey_bitstr(const WOLFSSL_X509* x) +{ + (void)x; + WOLFSSL_ENTER("wolfSSL_X509_get0_pubkey_bitstr"); + WOLFSSL_STUB("X509_get0_pubkey_bitstr"); + + return NULL; +} +#endif + +#ifndef NO_WOLFSSL_STUB +int wolfSSL_CTX_add_session(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* session) +{ + (void)ctx; + (void)session; + WOLFSSL_ENTER("wolfSSL_CTX_add_session"); + WOLFSSL_STUB("SSL_CTX_add_session"); + + return WOLFSSL_SUCCESS; +} +#endif + + +int wolfSSL_version(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_version"); + if (ssl->version.major == SSLv3_MAJOR) { + switch (ssl->version.minor) { + case SSLv3_MINOR : + return SSL3_VERSION; + case TLSv1_MINOR : + case TLSv1_1_MINOR : + case TLSv1_2_MINOR : + case TLSv1_3_MINOR : + return TLS1_VERSION; + default: + return WOLFSSL_FAILURE; + } + } + else if (ssl->version.major == DTLS_MAJOR) { + switch (ssl->version.minor) { + case DTLS_MINOR : + case DTLSv1_2_MINOR : + return DTLS1_VERSION; + default: + return WOLFSSL_FAILURE; + } + } + return WOLFSSL_FAILURE; +} + + +int wolfSSL_X509_NAME_get_sz(WOLFSSL_X509_NAME* name) +{ + WOLFSSL_ENTER("wolfSSL_X509_NAME_get_sz"); + if(!name) + return -1; + return name->sz; +} + +#ifdef HAVE_SNI +int wolfSSL_set_tlsext_host_name(WOLFSSL* ssl, const char* host_name) +{ + int ret; + WOLFSSL_ENTER("wolfSSL_set_tlsext_host_name"); + ret = wolfSSL_UseSNI(ssl, WOLFSSL_SNI_HOST_NAME, + host_name, (word16)XSTRLEN(host_name)); + WOLFSSL_LEAVE("wolfSSL_set_tlsext_host_name", ret); + return ret; +} + + +#ifndef NO_WOLFSSL_SERVER +const char * wolfSSL_get_servername(WOLFSSL* ssl, byte type) +{ + void * serverName = NULL; + if (ssl == NULL) + return NULL; + TLSX_SNI_GetRequest(ssl->extensions, type, &serverName); + return (const char *)serverName; +} +#endif /* NO_WOLFSSL_SERVER */ +#endif /* HAVE_SNI */ + +WOLFSSL_CTX* wolfSSL_set_SSL_CTX(WOLFSSL* ssl, WOLFSSL_CTX* ctx) +{ + if (ssl && ctx && SetSSL_CTX(ssl, ctx, 0) == WOLFSSL_SUCCESS) + return ssl->ctx; + return NULL; +} + + +VerifyCallback wolfSSL_CTX_get_verify_callback(WOLFSSL_CTX* ctx) +{ + WOLFSSL_ENTER("wolfSSL_CTX_get_verify_callback"); + if(ctx) + return ctx->verifyCallback; + return NULL; +} + + +void wolfSSL_CTX_set_servername_callback(WOLFSSL_CTX* ctx, CallbackSniRecv cb) +{ + WOLFSSL_ENTER("wolfSSL_CTX_set_servername_callback"); + if (ctx) + ctx->sniRecvCb = cb; +} + +int wolfSSL_CTX_set_tlsext_servername_callback(WOLFSSL_CTX* ctx, + CallbackSniRecv cb) +{ + WOLFSSL_ENTER("wolfSSL_CTX_set_tlsext_servername_callback"); + if (ctx) { + ctx->sniRecvCb = cb; + return 1; + } + return 0; +} + +void wolfSSL_CTX_set_servername_arg(WOLFSSL_CTX* ctx, void* arg) +{ + WOLFSSL_ENTER("wolfSSL_CTX_set_servername_arg"); + if (ctx) + ctx->sniRecvCbArg = arg; +} + +void wolfSSL_ERR_load_BIO_strings(void) { + WOLFSSL_ENTER("ERR_load_BIO_strings"); + /* do nothing */ +} + +#ifndef NO_WOLFSSL_STUB +void wolfSSL_THREADID_set_callback(void(*threadid_func)(void*)) +{ + WOLFSSL_ENTER("wolfSSL_THREADID_set_callback"); + WOLFSSL_STUB("CRYPTO_THREADID_set_callback"); + (void)threadid_func; + return; +} +#endif + +#ifndef NO_WOLFSSL_STUB +void wolfSSL_THREADID_set_numeric(void* id, unsigned long val) +{ + WOLFSSL_ENTER("wolfSSL_THREADID_set_numeric"); + WOLFSSL_STUB("CRYPTO_THREADID_set_numeric"); + (void)id; + (void)val; + return; +} +#endif + + +#ifndef NO_WOLFSSL_STUB +WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_X509_STORE_get1_certs(WOLFSSL_X509_STORE_CTX* ctx, + WOLFSSL_X509_NAME* name) +{ + WOLFSSL_ENTER("wolfSSL_X509_STORE_get1_certs"); + WOLFSSL_STUB("X509_STORE_get1_certs"); + (void)ctx; + (void)name; + return NULL; +} +#endif + +#endif /* OPENSSL_ALL || (OPENSSL_EXTRA && (HAVE_STUNNEL || WOLFSSL_NGINX || HAVE_LIGHTY)) */ + + +#if defined(OPENSSL_EXTRA) +unsigned long wolfSSL_ERR_peek_last_error(void) +{ + WOLFSSL_ENTER("wolfSSL_ERR_peek_last_error"); + +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_NGINX) + { + int ret; + + if ((ret = wc_PeekErrorNode(-1, NULL, NULL, NULL)) < 0) { + WOLFSSL_MSG("Issue peeking at error node in queue"); + return 0; + } + if (ret == -ASN_NO_PEM_HEADER) + return (ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE; + return (unsigned long)ret; + } +#else + return (unsigned long)(0 - NOT_COMPILED_IN); +#endif +} + +#endif /* OPENSSL_EXTRA */ + +WOLFSSL_CTX* wolfSSL_get_SSL_CTX(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_get_SSL_CTX"); + return ssl->ctx; +} + +#if defined(OPENSSL_ALL) || \ + defined(OPENSSL_EXTRA) || defined(HAVE_STUNNEL) || \ + defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + +const byte* wolfSSL_SESSION_get_id(WOLFSSL_SESSION* sess, unsigned int* idLen) +{ + WOLFSSL_ENTER("wolfSSL_SESSION_get_id"); + if(!sess || !idLen) { + WOLFSSL_MSG("Bad func args. Please provide idLen"); + return NULL; + } + *idLen = sess->sessionIDSz; + return sess->sessionID; +} +#endif + +#if defined(OPENSSL_ALL) || (defined(OPENSSL_EXTRA) && defined(HAVE_STUNNEL)) \ + || defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(WOLFSSL_NGINX) + +int wolfSSL_CTX_get_verify_mode(WOLFSSL_CTX* ctx) +{ + int mode = 0; + WOLFSSL_ENTER("wolfSSL_CTX_get_verify_mode"); + + if(!ctx) + return WOLFSSL_FATAL_ERROR; + + if (ctx->verifyPeer) + mode |= WOLFSSL_VERIFY_PEER; + else if (ctx->verifyNone) + mode |= WOLFSSL_VERIFY_NONE; + + if (ctx->failNoCert) + mode |= WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT; + + if (ctx->failNoCertxPSK) + mode |= WOLFSSL_VERIFY_FAIL_EXCEPT_PSK; + + WOLFSSL_LEAVE("wolfSSL_CTX_get_verify_mode", mode); + return mode; +} +#endif + +#if defined(OPENSSL_EXTRA) && defined(HAVE_CURVE25519) +/* return 1 if success, 0 if error + * output keys are little endian format + */ +int wolfSSL_EC25519_generate_key(unsigned char *priv, unsigned int *privSz, + unsigned char *pub, unsigned int *pubSz) +{ +#ifndef WOLFSSL_KEY_GEN + WOLFSSL_MSG("No Key Gen built in"); + (void) priv; + (void) privSz; + (void) pub; + (void) pubSz; + return WOLFSSL_FAILURE; +#else /* WOLFSSL_KEY_GEN */ + int ret = WOLFSSL_FAILURE; + int initTmpRng = 0; + WC_RNG *rng = NULL; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG *tmpRNG = NULL; +#else + WC_RNG tmpRNG[1]; +#endif + + WOLFSSL_ENTER("wolfSSL_EC25519_generate_key"); + + if (priv == NULL || privSz == NULL || *privSz < CURVE25519_KEYSIZE || + pub == NULL || pubSz == NULL || *pubSz < CURVE25519_KEYSIZE) { + WOLFSSL_MSG("Bad arguments"); + return WOLFSSL_FAILURE; + } + +#ifdef WOLFSSL_SMALL_STACK + tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); + if (tmpRNG == NULL) + return WOLFSSL_FAILURE; +#endif + if (wc_InitRng(tmpRNG) == 0) { + rng = tmpRNG; + initTmpRng = 1; + } + else { + WOLFSSL_MSG("Bad RNG Init, trying global"); + if (initGlobalRNG == 0) + WOLFSSL_MSG("Global RNG no Init"); + else + rng = &globalRNG; + } + + if (rng) { + curve25519_key key; + + if (wc_curve25519_init(&key) != MP_OKAY) + WOLFSSL_MSG("wc_curve25519_init failed"); + else if (wc_curve25519_make_key(rng, CURVE25519_KEYSIZE, &key)!=MP_OKAY) + WOLFSSL_MSG("wc_curve25519_make_key failed"); + /* export key pair */ + else if (wc_curve25519_export_key_raw_ex(&key, priv, privSz, pub, + pubSz, EC25519_LITTLE_ENDIAN) + != MP_OKAY) + WOLFSSL_MSG("wc_curve25519_export_key_raw_ex failed"); + else + ret = WOLFSSL_SUCCESS; + + wc_curve25519_free(&key); + } + + if (initTmpRng) + wc_FreeRng(tmpRNG); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); +#endif + + return ret; +#endif /* WOLFSSL_KEY_GEN */ +} + +/* return 1 if success, 0 if error + * input and output keys are little endian format + */ +int wolfSSL_EC25519_shared_key(unsigned char *shared, unsigned int *sharedSz, + const unsigned char *priv, unsigned int privSz, + const unsigned char *pub, unsigned int pubSz) +{ +#ifndef WOLFSSL_KEY_GEN + WOLFSSL_MSG("No Key Gen built in"); + (void) shared; + (void) sharedSz; + (void) priv; + (void) privSz; + (void) pub; + (void) pubSz; + return WOLFSSL_FAILURE; +#else /* WOLFSSL_KEY_GEN */ + int ret = WOLFSSL_FAILURE; + curve25519_key privkey, pubkey; + + WOLFSSL_ENTER("wolfSSL_EC25519_shared_key"); + + if (shared == NULL || sharedSz == NULL || *sharedSz < CURVE25519_KEYSIZE || + priv == NULL || privSz < CURVE25519_KEYSIZE || + pub == NULL || pubSz < CURVE25519_KEYSIZE) { + WOLFSSL_MSG("Bad arguments"); + return WOLFSSL_FAILURE; + } + + /* import private key */ + if (wc_curve25519_init(&privkey) != MP_OKAY) { + WOLFSSL_MSG("wc_curve25519_init privkey failed"); + return ret; + } + if (wc_curve25519_import_private_ex(priv, privSz, &privkey, + EC25519_LITTLE_ENDIAN) != MP_OKAY) { + WOLFSSL_MSG("wc_curve25519_import_private_ex failed"); + wc_curve25519_free(&privkey); + return ret; + } + + /* import public key */ + if (wc_curve25519_init(&pubkey) != MP_OKAY) { + WOLFSSL_MSG("wc_curve25519_init pubkey failed"); + wc_curve25519_free(&privkey); + return ret; + } + if (wc_curve25519_import_public_ex(pub, pubSz, &pubkey, + EC25519_LITTLE_ENDIAN) != MP_OKAY) { + WOLFSSL_MSG("wc_curve25519_import_public_ex failed"); + wc_curve25519_free(&privkey); + wc_curve25519_free(&pubkey); + return ret; + } + + if (wc_curve25519_shared_secret_ex(&privkey, &pubkey, + shared, sharedSz, + EC25519_LITTLE_ENDIAN) != MP_OKAY) + WOLFSSL_MSG("wc_curve25519_shared_secret_ex failed"); + else + ret = WOLFSSL_SUCCESS; + + wc_curve25519_free(&privkey); + wc_curve25519_free(&pubkey); + + return ret; +#endif /* WOLFSSL_KEY_GEN */ +} +#endif /* OPENSSL_EXTRA && HAVE_CURVE25519 */ + +#if defined(OPENSSL_EXTRA) && defined(HAVE_ED25519) +/* return 1 if success, 0 if error + * output keys are little endian format + */ +int wolfSSL_ED25519_generate_key(unsigned char *priv, unsigned int *privSz, + unsigned char *pub, unsigned int *pubSz) +{ +#ifndef WOLFSSL_KEY_GEN + WOLFSSL_MSG("No Key Gen built in"); + (void) priv; + (void) privSz; + (void) pub; + (void) pubSz; + return WOLFSSL_FAILURE; +#else /* WOLFSSL_KEY_GEN */ + int ret = WOLFSSL_FAILURE; + int initTmpRng = 0; + WC_RNG *rng = NULL; +#ifdef WOLFSSL_SMALL_STACK + WC_RNG *tmpRNG = NULL; +#else + WC_RNG tmpRNG[1]; +#endif + + WOLFSSL_ENTER("wolfSSL_ED25519_generate_key"); + + if (priv == NULL || privSz == NULL || *privSz < ED25519_PRV_KEY_SIZE || + pub == NULL || pubSz == NULL || *pubSz < ED25519_PUB_KEY_SIZE) { + WOLFSSL_MSG("Bad arguments"); + return WOLFSSL_FAILURE; + } + +#ifdef WOLFSSL_SMALL_STACK + tmpRNG = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, DYNAMIC_TYPE_RNG); + if (tmpRNG == NULL) + return WOLFSSL_FATAL_ERROR; +#endif + if (wc_InitRng(tmpRNG) == 0) { + rng = tmpRNG; + initTmpRng = 1; + } + else { + WOLFSSL_MSG("Bad RNG Init, trying global"); + if (initGlobalRNG == 0) + WOLFSSL_MSG("Global RNG no Init"); + else + rng = &globalRNG; + } + + if (rng) { + ed25519_key key; + + if (wc_ed25519_init(&key) != MP_OKAY) + WOLFSSL_MSG("wc_ed25519_init failed"); + else if (wc_ed25519_make_key(rng, ED25519_KEY_SIZE, &key)!=MP_OKAY) + WOLFSSL_MSG("wc_ed25519_make_key failed"); + /* export private key */ + else if (wc_ed25519_export_key(&key, priv, privSz, pub, pubSz)!=MP_OKAY) + WOLFSSL_MSG("wc_ed25519_export_key failed"); + else + ret = WOLFSSL_SUCCESS; + + wc_ed25519_free(&key); + } + + if (initTmpRng) + wc_FreeRng(tmpRNG); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpRNG, NULL, DYNAMIC_TYPE_RNG); +#endif + + return ret; +#endif /* WOLFSSL_KEY_GEN */ +} + +/* return 1 if success, 0 if error + * input and output keys are little endian format + * priv is a buffer containing private and public part of key + */ +int wolfSSL_ED25519_sign(const unsigned char *msg, unsigned int msgSz, + const unsigned char *priv, unsigned int privSz, + unsigned char *sig, unsigned int *sigSz) +{ +#ifndef WOLFSSL_KEY_GEN + WOLFSSL_MSG("No Key Gen built in"); + (void) msg; + (void) msgSz; + (void) priv; + (void) privSz; + (void) sig; + (void) sigSz; + return WOLFSSL_FAILURE; +#else /* WOLFSSL_KEY_GEN */ + ed25519_key key; + int ret = WOLFSSL_FAILURE; + + WOLFSSL_ENTER("wolfSSL_ED25519_sign"); + + if (priv == NULL || privSz != ED25519_PRV_KEY_SIZE || + msg == NULL || sig == NULL || *sigSz < ED25519_SIG_SIZE) { + WOLFSSL_MSG("Bad arguments"); + return WOLFSSL_FAILURE; + } + + /* import key */ + if (wc_ed25519_init(&key) != MP_OKAY) { + WOLFSSL_MSG("wc_curve25519_init failed"); + return ret; + } + if (wc_ed25519_import_private_key(priv, privSz/2, + priv+(privSz/2), ED25519_PUB_KEY_SIZE, + &key) != MP_OKAY){ + WOLFSSL_MSG("wc_ed25519_import_private failed"); + wc_ed25519_free(&key); + return ret; + } + + if (wc_ed25519_sign_msg(msg, msgSz, sig, sigSz, &key) != MP_OKAY) + WOLFSSL_MSG("wc_curve25519_shared_secret_ex failed"); + else + ret = WOLFSSL_SUCCESS; + + wc_ed25519_free(&key); + + return ret; +#endif /* WOLFSSL_KEY_GEN */ +} + +/* return 1 if success, 0 if error + * input and output keys are little endian format + * pub is a buffer containing public part of key + */ +int wolfSSL_ED25519_verify(const unsigned char *msg, unsigned int msgSz, + const unsigned char *pub, unsigned int pubSz, + const unsigned char *sig, unsigned int sigSz) +{ +#ifndef WOLFSSL_KEY_GEN + WOLFSSL_MSG("No Key Gen built in"); + (void) msg; + (void) msgSz; + (void) pub; + (void) pubSz; + (void) sig; + (void) sigSz; + return WOLFSSL_FAILURE; +#else /* WOLFSSL_KEY_GEN */ + ed25519_key key; + int ret = WOLFSSL_FAILURE, check = 0; + + WOLFSSL_ENTER("wolfSSL_ED25519_verify"); + + if (pub == NULL || pubSz != ED25519_PUB_KEY_SIZE || + msg == NULL || sig == NULL || sigSz != ED25519_SIG_SIZE) { + WOLFSSL_MSG("Bad arguments"); + return WOLFSSL_FAILURE; + } + + /* import key */ + if (wc_ed25519_init(&key) != MP_OKAY) { + WOLFSSL_MSG("wc_curve25519_init failed"); + return ret; + } + if (wc_ed25519_import_public(pub, pubSz, &key) != MP_OKAY){ + WOLFSSL_MSG("wc_ed25519_import_public failed"); + wc_ed25519_free(&key); + return ret; + } + + if ((ret = wc_ed25519_verify_msg((byte*)sig, sigSz, msg, msgSz, + &check, &key)) != MP_OKAY) { + WOLFSSL_MSG("wc_ed25519_verify_msg failed"); + } + else if (!check) + WOLFSSL_MSG("wc_ed25519_verify_msg failed (signature invalid)"); + else + ret = WOLFSSL_SUCCESS; + + wc_ed25519_free(&key); + + return ret; +#endif /* WOLFSSL_KEY_GEN */ +} + +#endif /* OPENSSL_EXTRA && HAVE_ED25519 */ + +#ifdef WOLFSSL_JNI + +int wolfSSL_set_jobject(WOLFSSL* ssl, void* objPtr) +{ + WOLFSSL_ENTER("wolfSSL_set_jobject"); + if (ssl != NULL) + { + ssl->jObjectRef = objPtr; + return WOLFSSL_SUCCESS; + } + return WOLFSSL_FAILURE; +} + +void* wolfSSL_get_jobject(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_get_jobject"); + if (ssl != NULL) + return ssl->jObjectRef; + return NULL; +} + +#endif /* WOLFSSL_JNI */ + + +#ifdef WOLFSSL_ASYNC_CRYPT +int wolfSSL_CTX_AsyncPoll(WOLFSSL_CTX* ctx, WOLF_EVENT** events, int maxEvents, + WOLF_EVENT_FLAG flags, int* eventCount) +{ + if (ctx == NULL) { + return BAD_FUNC_ARG; + } + + return wolfAsync_EventQueuePoll(&ctx->event_queue, NULL, + events, maxEvents, flags, eventCount); +} + +int wolfSSL_AsyncPoll(WOLFSSL* ssl, WOLF_EVENT_FLAG flags) +{ + int ret, eventCount = 0; + WOLF_EVENT* events[1]; + + if (ssl == NULL) { + return BAD_FUNC_ARG; + } + + ret = wolfAsync_EventQueuePoll(&ssl->ctx->event_queue, ssl, + events, sizeof(events)/sizeof(events), flags, &eventCount); + if (ret == 0) { + ret = eventCount; + } + + return ret; +} + +#endif /* WOLFSSL_ASYNC_CRYPT */ + +#ifdef OPENSSL_EXTRA +unsigned long wolfSSL_ERR_peek_error_line_data(const char **file, int *line, + const char **data, int *flags) +{ + WOLFSSL_ENTER("wolfSSL_ERR_peek_error_line_data"); + + (void)line; + (void)file; + + /* No data or flags stored - error display only in Nginx. */ + if (data != NULL) { + *data = ""; + } + if (flags != NULL) { + *flags = 0; + } + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || \ + defined(WOLFSSL_HAPROXY) || defined(WOLFSSL_MYSQL_COMPATIBLE) + { + int ret = 0; + + while (1) { + if ((ret = wc_PeekErrorNode(-1, file, NULL, line)) < 0) { + WOLFSSL_MSG("Issue peeking at error node in queue"); + return 0; + } + ret = -ret; + + if (ret == ASN_NO_PEM_HEADER) + return (ERR_LIB_PEM << 24) | PEM_R_NO_START_LINE; + if (ret != WANT_READ && ret != WANT_WRITE && + ret != ZERO_RETURN && ret != WOLFSSL_ERROR_ZERO_RETURN && + ret != SOCKET_PEER_CLOSED_E && ret != SOCKET_ERROR_E) + break; + + wc_RemoveErrorNode(-1); + } + + return (unsigned long)ret; + } +#else + return (unsigned long)(0 - NOT_COMPILED_IN); +#endif +} +#endif + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + +#ifndef NO_WOLFSSL_STUB +WOLF_STACK_OF(WOLFSSL_CIPHER) *wolfSSL_get_ciphers_compat(const WOLFSSL *ssl) +{ + (void)ssl; + WOLFSSL_STUB("wolfSSL_get_ciphers_compat"); + return NULL; +} +#endif + +#ifndef NO_WOLFSSL_STUB +void wolfSSL_OPENSSL_config(char *config_name) +{ + (void)config_name; + WOLFSSL_STUB("OPENSSL_config"); +} +#endif +#endif + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) \ + || defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY) +int wolfSSL_X509_get_ex_new_index(int idx, void *arg, void *a, void *b, void *c) +{ + static int x509_idx = 0; + + WOLFSSL_ENTER("wolfSSL_X509_get_ex_new_index"); + (void)idx; + (void)arg; + (void)a; + (void)b; + (void)c; + + return x509_idx++; +} + +void *wolfSSL_X509_get_ex_data(X509 *x509, int idx) +{ + WOLFSSL_ENTER("wolfSSL_X509_get_ex_data"); + #ifdef HAVE_EX_DATA + if (x509 != NULL && idx < MAX_EX_DATA && idx >= 0) { + return x509->ex_data[idx]; + } + #else + (void)x509; + (void)idx; + #endif + return NULL; +} +int wolfSSL_X509_set_ex_data(X509 *x509, int idx, void *data) +{ + WOLFSSL_ENTER("wolfSSL_X509_set_ex_data"); + #ifdef HAVE_EX_DATA + if (x509 != NULL && idx < MAX_EX_DATA) + { + x509->ex_data[idx] = data; + return WOLFSSL_SUCCESS; + } + #else + (void)x509; + (void)idx; + (void)data; + #endif + return WOLFSSL_FAILURE; +} +int wolfSSL_X509_NAME_digest(const WOLFSSL_X509_NAME *name, + const WOLFSSL_EVP_MD *type, unsigned char *md, unsigned int *len) +{ + WOLFSSL_ENTER("wolfSSL_X509_NAME_digest"); + + if (name == NULL || type == NULL) + return WOLFSSL_FAILURE; + +#ifndef NO_FILESYSTEM + return wolfSSL_EVP_Digest((unsigned char*)name->fullName.fullName, + name->fullName.fullNameLen, md, len, type, NULL); +#else + (void)md; + (void)len; + return NOT_COMPILED_IN; +#endif +} + +long wolfSSL_SSL_CTX_get_timeout(const WOLFSSL_CTX *ctx) +{ + WOLFSSL_ENTER("wolfSSL_SSL_CTX_get_timeout"); + + if (ctx == NULL) + return 0; + + return ctx->timeout; +} + + +/* returns the time in seconds of the current timeout */ +long wolfSSL_get_timeout(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_get_timeout"); + + if (ssl == NULL) + return 0; + return ssl->timeout; +} + +#ifdef HAVE_ECC +int wolfSSL_SSL_CTX_set_tmp_ecdh(WOLFSSL_CTX *ctx, WOLFSSL_EC_KEY *ecdh) +{ + WOLFSSL_ENTER("wolfSSL_SSL_CTX_set_tmp_ecdh"); + + if (ctx == NULL || ecdh == NULL) + return BAD_FUNC_ARG; + + ctx->ecdhCurveOID = ecdh->group->curve_oid; + + return WOLFSSL_SUCCESS; +} +#endif + +/* Assumes that the session passed in is from the cache. */ +int wolfSSL_SSL_CTX_remove_session(WOLFSSL_CTX *ctx, WOLFSSL_SESSION *s) +{ + WOLFSSL_ENTER("wolfSSL_SSL_CTX_remove_session"); + + if (ctx == NULL || s == NULL) + return BAD_FUNC_ARG; + +#ifdef HAVE_EXT_CACHE + if (!ctx->internalCacheOff) +#endif + { + /* Don't remove session just timeout session. */ + s->timeout = 0; + } + +#ifdef HAVE_EXT_CACHE + if (ctx->rem_sess_cb != NULL) + ctx->rem_sess_cb(ctx, s); +#endif + + return 0; +} + +BIO *wolfSSL_SSL_get_rbio(const WOLFSSL *s) +{ + WOLFSSL_ENTER("wolfSSL_SSL_get_rbio"); + /* Nginx sets the buffer size if the read BIO is different to write BIO. + * The setting buffer size doesn't do anything so return NULL for both. + */ + if (s == NULL) + return NULL; + + return s->biord; +} +BIO *wolfSSL_SSL_get_wbio(const WOLFSSL *s) +{ + WOLFSSL_ENTER("wolfSSL_SSL_get_wbio"); + (void)s; + /* Nginx sets the buffer size if the read BIO is different to write BIO. + * The setting buffer size doesn't do anything so return NULL for both. + */ + if (s == NULL) + return NULL; + + return s->biowr; +} + +int wolfSSL_SSL_do_handshake(WOLFSSL *s) +{ + WOLFSSL_ENTER("wolfSSL_SSL_do_handshake"); + + if (s == NULL) + return WOLFSSL_FAILURE; + + if (s->options.side == WOLFSSL_CLIENT_END) { + #ifndef NO_WOLFSSL_CLIENT + return wolfSSL_connect(s); + #else + WOLFSSL_MSG("Client not compiled in"); + return WOLFSSL_FAILURE; + #endif + } + +#ifndef NO_WOLFSSL_SERVER + return wolfSSL_accept(s); +#else + WOLFSSL_MSG("Server not compiled in"); + return WOLFSSL_FAILURE; +#endif +} + +int wolfSSL_SSL_in_init(WOLFSSL *s) +{ + WOLFSSL_ENTER("wolfSSL_SSL_in_init"); + + if (s == NULL) + return WOLFSSL_FAILURE; + + if (s->options.side == WOLFSSL_CLIENT_END) + return s->options.connectState < SECOND_REPLY_DONE; + return s->options.acceptState < ACCEPT_THIRD_REPLY_DONE; +} + +#ifndef NO_SESSION_CACHE + +WOLFSSL_SESSION *wolfSSL_SSL_get0_session(const WOLFSSL *ssl) +{ + WOLFSSL_SESSION *session; + + WOLFSSL_ENTER("wolfSSL_SSL_get0_session"); + + if (ssl == NULL) { + return NULL; + } + + session = wolfSSL_get_session((WOLFSSL*)ssl); + +#ifdef HAVE_EXT_CACHE + ((WOLFSSL*)ssl)->extSession = session; +#endif + + return session; +} + +#endif /* NO_SESSION_CACHE */ + +int wolfSSL_X509_check_host(X509 *x, const char *chk, size_t chklen, + unsigned int flags, char **peername) +{ + int ret; + DecodedCert dCert; + + WOLFSSL_ENTER("wolfSSL_X509_check_host"); + + /* flags and peername not needed for Nginx. */ + (void)flags; + (void)peername; + + if (flags == WOLFSSL_NO_WILDCARDS) { + WOLFSSL_MSG("X509_CHECK_FLAG_NO_WILDCARDS not yet implemented"); + return WOLFSSL_FAILURE; + } + + InitDecodedCert(&dCert, x->derCert->buffer, x->derCert->length, NULL); + ret = ParseCertRelative(&dCert, CERT_TYPE, 0, NULL); + if (ret != 0) + return WOLFSSL_FAILURE; + + ret = CheckHostName(&dCert, (char *)chk, chklen); + FreeDecodedCert(&dCert); + if (ret != 0) + return WOLFSSL_FAILURE; + return WOLFSSL_SUCCESS; +} + +int wolfSSL_i2a_ASN1_INTEGER(BIO *bp, const WOLFSSL_ASN1_INTEGER *a) +{ + static char num[16] = { '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; + int i; + word32 j; + word32 len = 0; + + WOLFSSL_ENTER("wolfSSL_i2a_ASN1_INTEGER"); + + if (bp == NULL || a == NULL) + return WOLFSSL_FAILURE; + + /* Skip ASN.1 INTEGER (type) byte. */ + i = 1; + /* When indefinite length, can't determine length with data available. */ + if (a->data[i] == 0x80) + return 0; + /* One length byte if less than 0x80. */ + if (a->data[i] < 0x80) + len = a->data[i++]; + /* Multiple length byte if greater than 0x80. */ + else if (a->data[i] > 0x80) { + switch (a->data[i++] - 0x80) { + case 4: + len |= a->data[i++] << 24; + FALL_THROUGH; + case 3: + len |= a->data[i++] << 16; + FALL_THROUGH; + case 2: + len |= a->data[i++] << 8; + FALL_THROUGH; + case 1: + len |= a->data[i++]; + break; + default: + /* Not supporting greater than 4 bytes of length. */ + return 0; + } + } + + /* Zero length integer is the value zero. */ + if (len == 0) { + wolfSSL_BIO_write(bp, "00", 2); + return 2; + } + + /* Don't do negative - just write out every byte. */ + for (j = 0; j < len; i++,j++) { + wolfSSL_BIO_write(bp, &num[a->data[i] >> 4], 1); + wolfSSL_BIO_write(bp, &num[a->data[i] & 0xf], 1); + } + + /* Two nibbles written for each byte. */ + return len * 2; +} + + +#if defined(HAVE_SESSION_TICKET) && !defined(NO_WOLFSSL_SERVER) +/* Expected return values from implementations of OpenSSL ticket key callback. + */ +#define TICKET_KEY_CB_RET_FAILURE -1 +#define TICKET_KEY_CB_RET_NOT_FOUND 0 +#define TICKET_KEY_CB_RET_OK 1 +#define TICKET_KEY_CB_RET_RENEW 2 + +/* The ticket key callback as used in OpenSSL is stored here. */ +static int (*ticketKeyCb)(WOLFSSL *ssl, unsigned char *name, unsigned char *iv, + WOLFSSL_EVP_CIPHER_CTX *ectx, WOLFSSL_HMAC_CTX *hctx, int enc) = NULL; + +/* Implementation of session ticket encryption/decryption using OpenSSL + * callback to initialize the cipher and HMAC. + * + * ssl The SSL/TLS object. + * keyName The key name - used to identify the key to be used. + * iv The IV to use. + * mac The MAC of the encrypted data. + * enc Encrypt ticket. + * encTicket The ticket data. + * encTicketLen The length of the ticket data. + * encLen The encrypted/decrypted ticket length - output length. + * ctx Ignored. Application specific data. + * returns WOLFSSL_TICKET_RET_OK to indicate success, + * WOLFSSL_TICKET_RET_CREATE if a new ticket is required and + * WOLFSSL_TICKET_RET_FATAL on error. + */ +static int wolfSSL_TicketKeyCb(WOLFSSL* ssl, + unsigned char keyName[WOLFSSL_TICKET_NAME_SZ], + unsigned char iv[WOLFSSL_TICKET_IV_SZ], + unsigned char mac[WOLFSSL_TICKET_MAC_SZ], + int enc, unsigned char* encTicket, + int encTicketLen, int* encLen, void* ctx) +{ + byte digest[WC_MAX_DIGEST_SIZE]; + WOLFSSL_EVP_CIPHER_CTX evpCtx; + WOLFSSL_HMAC_CTX hmacCtx; + unsigned int mdSz = 0; + int len = 0; + int ret = WOLFSSL_TICKET_RET_FATAL; + int res; + + (void)ctx; + + if (ticketKeyCb == NULL) + return WOLFSSL_TICKET_RET_FATAL; + + wolfSSL_EVP_CIPHER_CTX_init(&evpCtx); + /* Initialize the cipher and HMAC. */ + res = ticketKeyCb(ssl, keyName, iv, &evpCtx, &hmacCtx, enc); + if (res != TICKET_KEY_CB_RET_OK && res != TICKET_KEY_CB_RET_RENEW) + return WOLFSSL_TICKET_RET_FATAL; + + if (enc) + { + /* Encrypt in place. */ + if (!wolfSSL_EVP_CipherUpdate(&evpCtx, encTicket, &len, + encTicket, encTicketLen)) + goto end; + encTicketLen = len; + if (!wolfSSL_EVP_EncryptFinal(&evpCtx, &encTicket[encTicketLen], &len)) + goto end; + /* Total length of encrypted data. */ + encTicketLen += len; + *encLen = encTicketLen; + + /* HMAC the encrypted data into the parameter 'mac'. */ + if (!wolfSSL_HMAC_Update(&hmacCtx, encTicket, encTicketLen)) + goto end; +#ifdef WOLFSSL_SHA512 + /* Check for SHA512, which would overrun the mac buffer */ + if (hmacCtx.hmac.macType == WC_SHA512) + goto end; +#endif + if (!wolfSSL_HMAC_Final(&hmacCtx, mac, &mdSz)) + goto end; + } + else + { + /* HMAC the encrypted data and compare it to the passed in data. */ + if (!wolfSSL_HMAC_Update(&hmacCtx, encTicket, encTicketLen)) + goto end; + if (!wolfSSL_HMAC_Final(&hmacCtx, digest, &mdSz)) + goto end; + if (XMEMCMP(mac, digest, mdSz) != 0) + goto end; + + /* Decrypt the ticket data in place. */ + if (!wolfSSL_EVP_CipherUpdate(&evpCtx, encTicket, &len, + encTicket, encTicketLen)) + goto end; + encTicketLen = len; + if (!wolfSSL_EVP_DecryptFinal(&evpCtx, &encTicket[encTicketLen], &len)) + goto end; + /* Total length of decrypted data. */ + *encLen = encTicketLen + len; + } + + ret = (res == TICKET_KEY_CB_RET_RENEW) ? WOLFSSL_TICKET_RET_CREATE : + WOLFSSL_TICKET_RET_OK; +end: + return ret; +} + +/* Set the callback to use when encrypting/decrypting tickets. + * + * ctx The SSL/TLS context object. + * cb The OpenSSL session ticket callback. + * returns WOLFSSL_SUCCESS to indicate success. + */ +int wolfSSL_CTX_set_tlsext_ticket_key_cb(WOLFSSL_CTX *ctx, int (*cb)( + WOLFSSL *ssl, unsigned char *name, unsigned char *iv, + WOLFSSL_EVP_CIPHER_CTX *ectx, WOLFSSL_HMAC_CTX *hctx, int enc)) +{ + /* Store callback in a global. */ + ticketKeyCb = cb; + /* Set the ticket encryption callback to be a wrapper around OpenSSL + * callback. + */ + ctx->ticketEncCb = wolfSSL_TicketKeyCb; + + return WOLFSSL_SUCCESS; +} +#endif /* HAVE_SESSION_TICKET */ + +#endif /* OPENSSL_ALL || WOLFSSL_NGINX || WOLFSSL_HAPROXY || + OPENSSL_EXTRA || HAVE_LIGHTY */ + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) +#ifdef HAVE_OCSP +/* Not an OpenSSL API. */ +int wolfSSL_get_ocsp_response(WOLFSSL* ssl, byte** response) +{ + *response = ssl->ocspResp; + return ssl->ocspRespSz; +} + +/* Not an OpenSSL API. */ +char* wolfSSL_get_ocsp_url(WOLFSSL* ssl) +{ + return ssl->url; +} + +/* Not an OpenSSL API. */ +int wolfSSL_set_ocsp_url(WOLFSSL* ssl, char* url) +{ + if (ssl == NULL) + return WOLFSSL_FAILURE; + + ssl->url = url; + return WOLFSSL_SUCCESS; +} +#endif /* OCSP */ +#endif /* OPENSSL_ALL / WOLFSSL_NGINX / WOLFSSL_HAPROXY */ + +#if defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \ + defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) +int wolfSSL_CTX_get_extra_chain_certs(WOLFSSL_CTX* ctx, WOLF_STACK_OF(X509)** chain) +{ + word32 idx; + word32 length; + WOLFSSL_STACK* node; + WOLFSSL_STACK* last = NULL; + + if (ctx == NULL || chain == NULL) { + chain = NULL; + return WOLFSSL_FAILURE; + } + if (ctx->x509Chain != NULL) { + *chain = ctx->x509Chain; + return WOLFSSL_SUCCESS; + } + + /* If there are no chains then success! */ + *chain = NULL; + if (ctx->certChain == NULL || ctx->certChain->length == 0) { + return WOLFSSL_SUCCESS; + } + + /* Create a new stack of WOLFSSL_X509 object from chain buffer. */ + for (idx = 0; idx < ctx->certChain->length; ) { + node = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL, + DYNAMIC_TYPE_OPENSSL); + if (node == NULL) + return WOLFSSL_FAILURE; + node->next = NULL; + + /* 3 byte length | X509 DER data */ + ato24(ctx->certChain->buffer + idx, &length); + idx += 3; + + /* Create a new X509 from DER encoded data. */ + node->data.x509 = wolfSSL_X509_d2i(NULL, ctx->certChain->buffer + idx, + length); + if (node->data.x509 == NULL) { + XFREE(node, NULL, DYNAMIC_TYPE_OPENSSL); + /* Return as much of the chain as we created. */ + ctx->x509Chain = *chain; + return WOLFSSL_FAILURE; + } + idx += length; + + /* Add object to the end of the stack. */ + if (last == NULL) { + node->num = 1; + *chain = node; + } + else { + (*chain)->num++; + last->next = node; + } + + last = node; + } + + ctx->x509Chain = *chain; + + return WOLFSSL_SUCCESS; +} + +int wolfSSL_CTX_set_tlsext_status_cb(WOLFSSL_CTX* ctx, + int(*cb)(WOLFSSL*, void*)) +{ + if (ctx == NULL || ctx->cm == NULL) + return WOLFSSL_FAILURE; + +#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + /* Ensure stapling is on for callback to be used. */ + wolfSSL_CTX_EnableOCSPStapling(ctx); + + if (ctx->cm->ocsp_stapling == NULL) + return WOLFSSL_FAILURE; + + ctx->cm->ocsp_stapling->statusCb = cb; +#else + (void)cb; +#endif + + return WOLFSSL_SUCCESS; +} + +int wolfSSL_X509_STORE_CTX_get1_issuer(WOLFSSL_X509 **issuer, + WOLFSSL_X509_STORE_CTX *ctx, WOLFSSL_X509 *x) +{ + WOLFSSL_STACK* node; + Signer* ca = NULL; +#ifdef WOLFSSL_SMALL_STACK + DecodedCert* cert = NULL; +#else + DecodedCert cert[1]; +#endif + + if (issuer == NULL || ctx == NULL || x == NULL) + return WOLFSSL_FATAL_ERROR; + + if (ctx->chain != NULL) { + for (node = ctx->chain; node != NULL; node = node->next) { + if (wolfSSL_X509_check_issued(node->data.x509, x) == X509_V_OK) { + *issuer = x; + return WOLFSSL_SUCCESS; + } + } + } + + +#ifdef WOLFSSL_SMALL_STACK + cert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, DYNAMIC_TYPE_DCERT); + if (cert == NULL) + return WOLFSSL_FAILURE; +#endif + + /* Use existing CA retrieval APIs that use DecodedCert. */ + InitDecodedCert(cert, x->derCert->buffer, x->derCert->length, NULL); + if (ParseCertRelative(cert, CERT_TYPE, 0, NULL) == 0) { + #ifndef NO_SKID + if (cert->extAuthKeyIdSet) + ca = GetCA(ctx->store->cm, cert->extAuthKeyId); + if (ca == NULL) + ca = GetCAByName(ctx->store->cm, cert->issuerHash); + #else /* NO_SKID */ + ca = GetCA(ctx->store->cm, cert->issuerHash); + #endif /* NO SKID */ + } + FreeDecodedCert(cert); +#ifdef WOLFSSL_SMALL_STACK + XFREE(cert, NULL, DYNAMIC_TYPE_DCERT); +#endif + + if (ca == NULL) + return WOLFSSL_FAILURE; + + *issuer = (WOLFSSL_X509 *)XMALLOC(sizeof(WOLFSSL_X509), 0, + DYNAMIC_TYPE_OPENSSL); + if (*issuer == NULL) + return WOLFSSL_FAILURE; + + /* Create an empty certificate as CA doesn't have a certificate. */ + XMEMSET(*issuer, 0, sizeof(WOLFSSL_X509)); + (*issuer)->dynamicMemory = 1; +#ifdef WOLFSSL_SIGNER_DER_CERT + if (AllocDer(&(*issuer)->derCert, ca->derCert->length, ca->derCert->type, + NULL) == 0) { + XMEMCPY((*issuer)->derCert->buffer, ca->derCert->buffer, + ca->derCert->length); + } + else { + XFREE(*issuer, 0, DYNAMIC_TYPE_OPENSSL); + return WOLFSSL_FAILURE; + } +#endif + + /* Result is ignored when passed to wolfSSL_OCSP_cert_to_id(). */ + + return WOLFSSL_SUCCESS; +} + +void wolfSSL_X509_email_free(WOLF_STACK_OF(WOLFSSL_STRING) *sk) +{ + WOLFSSL_STACK *curr; + + while (sk != NULL) { + curr = sk; + sk = sk->next; + + XFREE(curr, NULL, DYNAMIC_TYPE_OPENSSL); + } +} + +WOLF_STACK_OF(WOLFSSL_STRING) *wolfSSL_X509_get1_ocsp(WOLFSSL_X509 *x) +{ + WOLFSSL_STACK* list = NULL; + char* url; + + if (x->authInfoSz == 0) + return NULL; + + list = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK) + x->authInfoSz + 1, + NULL, DYNAMIC_TYPE_OPENSSL); + if (list == NULL) + return NULL; + + url = (char*)list; + url += sizeof(WOLFSSL_STACK); + XMEMCPY(url, x->authInfo, x->authInfoSz); + url[x->authInfoSz] = '\0'; + + list->data.string = url; + list->next = NULL; + + return list; +} + +int wolfSSL_X509_check_issued(WOLFSSL_X509 *issuer, WOLFSSL_X509 *subject) +{ + WOLFSSL_X509_NAME *issuerName = wolfSSL_X509_get_issuer_name(subject); + WOLFSSL_X509_NAME *subjectName = wolfSSL_X509_get_subject_name(issuer); + + if (issuerName == NULL || subjectName == NULL) + return X509_V_ERR_SUBJECT_ISSUER_MISMATCH; + + /* Literal matching of encoded names and key ids. */ + if (issuerName->sz != subjectName->sz || + XMEMCMP(issuerName->name, subjectName->name, subjectName->sz) != 0) { + return X509_V_ERR_SUBJECT_ISSUER_MISMATCH; + } + + if (subject->authKeyId != NULL && issuer->subjKeyId != NULL) { + if (subject->authKeyIdSz != issuer->subjKeyIdSz || + XMEMCMP(subject->authKeyId, issuer->subjKeyId, + issuer->subjKeyIdSz) != 0) { + return X509_V_ERR_SUBJECT_ISSUER_MISMATCH; + } + } + + return X509_V_OK; +} + +WOLFSSL_X509* wolfSSL_X509_dup(WOLFSSL_X509 *x) +{ + return wolfSSL_X509_d2i(NULL, x->derCert->buffer, x->derCert->length); +} + +char* wolfSSL_sk_WOLFSSL_STRING_value(WOLF_STACK_OF(WOLFSSL_STRING)* strings, + int idx) +{ + for (; idx > 0 && strings != NULL; idx--) + strings = strings->next; + if (strings == NULL) + return NULL; + return strings->data.string; +} +#endif /* WOLFSSL_NGINX || WOLFSSL_HAPROXY || OPENSSL_EXTRA || OPENSSL_ALL */ + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) +#ifdef HAVE_ALPN +void wolfSSL_get0_alpn_selected(const WOLFSSL *ssl, const unsigned char **data, + unsigned int *len) +{ + word16 nameLen; + + if (ssl != NULL && data != NULL && len != NULL) { + TLSX_ALPN_GetRequest(ssl->extensions, (void **)data, &nameLen); + *len = nameLen; + } +} + +int wolfSSL_select_next_proto(unsigned char **out, unsigned char *outLen, + const unsigned char *in, unsigned int inLen, + const unsigned char *clientNames, + unsigned int clientLen) +{ + unsigned int i, j; + byte lenIn, lenClient; + + if (out == NULL || outLen == NULL || in == NULL || clientNames == NULL) + return OPENSSL_NPN_UNSUPPORTED; + + for (i = 0; i < inLen; i += lenIn) { + lenIn = in[i++]; + for (j = 0; j < clientLen; j += lenClient) { + lenClient = clientNames[j++]; + + if (lenIn != lenClient) + continue; + + if (XMEMCMP(in + i, clientNames + j, lenIn) == 0) { + *out = (unsigned char *)(in + i); + *outLen = lenIn; + return OPENSSL_NPN_NEGOTIATED; + } + } + } + + *out = (unsigned char *)clientNames + 1; + *outLen = clientNames[0]; + return OPENSSL_NPN_NO_OVERLAP; +} + +void wolfSSL_CTX_set_alpn_select_cb(WOLFSSL_CTX *ctx, + int (*cb) (WOLFSSL *ssl, + const unsigned char **out, + unsigned char *outlen, + const unsigned char *in, + unsigned int inlen, + void *arg), void *arg) +{ + if (ctx != NULL) { + ctx->alpnSelect = cb; + ctx->alpnSelectArg = arg; + } +} + +void wolfSSL_CTX_set_next_protos_advertised_cb(WOLFSSL_CTX *s, + int (*cb) (WOLFSSL *ssl, + const unsigned char + **out, + unsigned int *outlen, + void *arg), void *arg) +{ + (void)s; + (void)cb; + (void)arg; + WOLFSSL_STUB("wolfSSL_CTX_set_next_protos_advertised_cb"); +} + +void wolfSSL_CTX_set_next_proto_select_cb(WOLFSSL_CTX *s, + int (*cb) (WOLFSSL *ssl, + unsigned char **out, + unsigned char *outlen, + const unsigned char *in, + unsigned int inlen, + void *arg), void *arg) +{ + (void)s; + (void)cb; + (void)arg; + WOLFSSL_STUB("wolfSSL_CTX_set_next_proto_select_cb"); +} + +void wolfSSL_get0_next_proto_negotiated(const WOLFSSL *s, const unsigned char **data, + unsigned *len) +{ + (void)s; + (void)data; + (void)len; + WOLFSSL_STUB("wolfSSL_get0_next_proto_negotiated"); +} +#endif /* HAVE_ALPN */ + +#endif /* WOLFSSL_NGINX / WOLFSSL_HAPROXY */ + +#if defined(OPENSSL_EXTRA) && defined(HAVE_ECC) +WOLFSSL_API int wolfSSL_CTX_set1_curves_list(WOLFSSL_CTX* ctx, char* names) +{ + int idx, start = 0, len; + int curve; + char name[MAX_CURVE_NAME_SZ]; + + /* Disable all curves so that only the ones the user wants are enabled. */ + ctx->disabledCurves = (word32)-1; + for (idx = 1; names[idx-1] != '\0'; idx++) { + if (names[idx] != ':' && names[idx] != '\0') + continue; + + len = idx - 1 - start; + if (len > MAX_CURVE_NAME_SZ - 1) + return WOLFSSL_FAILURE; + + XMEMCPY(name, names + start, len); + name[len] = 0; + + if ((XSTRNCMP(name, "prime256v1", len) == 0) || + (XSTRNCMP(name, "secp256r1", len) == 0) || + (XSTRNCMP(name, "P-256", len) == 0)) { + curve = WOLFSSL_ECC_SECP256R1; + } + else if ((XSTRNCMP(name, "secp384r1", len) == 0) || + (XSTRNCMP(name, "P-384", len) == 0)) { + curve = WOLFSSL_ECC_SECP384R1; + } + else if ((XSTRNCMP(name, "secp521r1", len) == 0) || + (XSTRNCMP(name, "P-521", len) == 0)) { + curve = WOLFSSL_ECC_SECP521R1; + } + else if (XSTRNCMP(name, "X25519", len) == 0) + curve = WOLFSSL_ECC_X25519; + else if ((curve = wc_ecc_get_curve_id_from_name(name)) < 0) + return WOLFSSL_FAILURE; + + /* Switch the bit to off and therefore is enabled. */ + ctx->disabledCurves &= ~(1 << curve); + start = idx + 1; + } + + return WOLFSSL_SUCCESS; +} +#endif + +#ifdef OPENSSL_EXTRA +#ifndef NO_WOLFSSL_STUB +int wolfSSL_CTX_set_msg_callback(WOLFSSL_CTX *ctx, SSL_Msg_Cb cb) +{ + WOLFSSL_STUB("SSL_CTX_set_msg_callback"); + (void)ctx; + (void)cb; + return WOLFSSL_FAILURE; +} +#endif + + +/* Sets a callback for when sending and receiving protocol messages. + * + * ssl WOLFSSL structure to set callback in + * cb callback to use + * + * return SSL_SUCCESS on success and SSL_FAILURE with error case + */ +int wolfSSL_set_msg_callback(WOLFSSL *ssl, SSL_Msg_Cb cb) +{ + WOLFSSL_ENTER("wolfSSL_set_msg_callback"); + + if (ssl == NULL) { + return SSL_FAILURE; + } + + if (cb != NULL) { + ssl->toInfoOn = 1; + } + + ssl->protoMsgCb = cb; + return SSL_SUCCESS; +} +#ifndef NO_WOLFSSL_STUB +int wolfSSL_CTX_set_msg_callback_arg(WOLFSSL_CTX *ctx, void* arg) +{ + WOLFSSL_STUB("SSL_CTX_set_msg_callback_arg"); + (void)ctx; + (void)arg; + return WOLFSSL_FAILURE; +} +#endif + +int wolfSSL_set_msg_callback_arg(WOLFSSL *ssl, void* arg) +{ + WOLFSSL_ENTER("wolfSSL_set_msg_callback_arg"); + if (ssl == NULL) + return WOLFSSL_FAILURE; + + ssl->protoMsgCtx = arg; + return WOLFSSL_SUCCESS; +} + +void *wolfSSL_OPENSSL_memdup(const void *data, size_t siz, const char* file, int line) +{ + void *ret; + (void)file; + (void)line; + + if (data == NULL || siz >= INT_MAX) + return NULL; + + ret = OPENSSL_malloc(siz); + if (ret == NULL) { + return NULL; + } + return XMEMCPY(ret, data, siz); +} + +int wolfSSL_CTX_set_alpn_protos(WOLFSSL_CTX *ctx, const unsigned char *p, + unsigned int p_len) +{ + WOLFSSL_ENTER("wolfSSL_CTX_set_alpn_protos"); + if(ctx == NULL) + return BAD_FUNC_ARG; + if((void *)ctx->alpn_cli_protos != NULL) + wolfSSL_OPENSSL_free((void *)ctx->alpn_cli_protos); + ctx->alpn_cli_protos = + (const unsigned char *)wolfSSL_OPENSSL_memdup(p, p_len, NULL, 0); + if (ctx->alpn_cli_protos == NULL) { + return SSL_FAILURE; + } + ctx->alpn_cli_protos_len = p_len; + + return SSL_SUCCESS; +} + +#endif + +#endif /* WOLFCRYPT_ONLY */ + +#if defined(OPENSSL_EXTRA) +int wolfSSL_X509_check_ca(WOLFSSL_X509 *x509) +{ + WOLFSSL_ENTER("X509_check_ca"); + + if (x509 == NULL) + return WOLFSSL_FAILURE; + if (x509->isCa) + return 1; + if (x509->extKeyUsageCrit) + return 4; + + return 0; +} + + +const char *wolfSSL_ASN1_tag2str(int tag) +{ + static const char *const tag_label[31] = { + "EOC", "BOOLEAN", "INTEGER", "BIT STRING", "OCTET STRING", "NULL", + "OBJECT", "OBJECT DESCRIPTOR", "EXTERNAL", "REAL", "ENUMERATED", + "", "UTF8STRING", "", "", "", + "SEQUENCE", "SET", "NUMERICSTRING", "PRINTABLESTRING", "T61STRING", + "VIDEOTEXTSTRING", "IA5STRING", "UTCTIME", "GENERALIZEDTIME", + "GRAPHICSTRING", "VISIBLESTRING", "GENERALSTRING", "UNIVERSALSTRING", + "", "BMPSTRING" + }; + + if ((tag == V_ASN1_NEG_INTEGER) || (tag == V_ASN1_NEG_ENUMERATED)) + tag &= ~0x100; + if (tag < 0 || tag > 30) + return "(unknown)"; + return tag_label[tag]; +} + +static int check_esc_char(char c, char *esc) +{ + char *ptr = NULL; + + ptr = esc; + while(*ptr != 0){ + if (c == *ptr) + return 1; + ptr++; + } + return 0; +} + +int wolfSSL_ASN1_STRING_print_ex(WOLFSSL_BIO *out, WOLFSSL_ASN1_STRING *str, + unsigned long flags) +{ + size_t str_len = 0, type_len = 0; + unsigned char *typebuf = NULL; + const char *hash="#"; + + WOLFSSL_ENTER("wolfSSL_ASN1_STRING_PRINT_ex"); + if (out == NULL || str == NULL) + return WOLFSSL_FAILURE; + + /* add ASN1 type tag */ + if (flags & ASN1_STRFLGS_SHOW_TYPE){ + const char *tag = wolfSSL_ASN1_tag2str(str->type); + /* colon len + tag len + null*/ + type_len = XSTRLEN(tag) + 2; + typebuf = (unsigned char *)XMALLOC(type_len , NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (typebuf == NULL){ + WOLFSSL_MSG("memory alloc failed."); + return WOLFSSL_FAILURE; + } + XMEMSET(typebuf, 0, type_len); + XSNPRINTF((char*)typebuf, (size_t)type_len , "%s:", tag); + type_len--; + } + + /* dump hex */ + if (flags & ASN1_STRFLGS_DUMP_ALL){ + static const char hex_char[] = { '0', '1', '2', '3', '4', '5', '6', + '7','8', '9', 'A', 'B', 'C', 'D', + 'E', 'F' }; + char hex_tmp[4]; + char *str_ptr, *str_end; + + if (type_len > 0){ + if (wolfSSL_BIO_write(out, typebuf, (int)type_len) != (int)type_len){ + XFREE(typebuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; + } + str_len += type_len; + } + if (wolfSSL_BIO_write(out, hash, 1) != 1){ + goto err_exit; + } + str_len++; + if (flags & ASN1_STRFLGS_DUMP_DER){ + hex_tmp[0] = hex_char[str->type >> 4]; + hex_tmp[1] = hex_char[str->type & 0xf]; + hex_tmp[2] = hex_char[str->length >> 4]; + hex_tmp[3] = hex_char[str->length & 0xf]; + if (wolfSSL_BIO_write(out, hex_tmp, 4) != 4){ + goto err_exit; + } + str_len += 4; + XMEMSET(hex_tmp, 0, 4); + } + + str_ptr = str->data; + str_end = str->data + str->length; + while (str_ptr < str_end){ + hex_tmp[0] = hex_char[*str_ptr >> 4]; + hex_tmp[1] = hex_char[*str_ptr & 0xf]; + if (wolfSSL_BIO_write(out, hex_tmp, 2) != 2){ + goto err_exit; + } + str_ptr++; + str_len += 2; + } + if (type_len > 0) + XFREE(typebuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return (int)str_len; + } + + if (type_len > 0){ + if (wolfSSL_BIO_write(out, typebuf, (int)type_len) != (int)type_len){ + XFREE(typebuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; + } + str_len += type_len; + } + + if (flags & ASN1_STRFLGS_ESC_2253){ + char esc_ch[] = "+;<>\\"; + char* esc_ptr = NULL; + + esc_ptr = str->data; + while (*esc_ptr != 0){ + if (check_esc_char(*esc_ptr, esc_ch)){ + if (wolfSSL_BIO_write(out,"\\", 1) != 1) + goto err_exit; + str_len++; + } + if (wolfSSL_BIO_write(out, esc_ptr, 1) != 1) + goto err_exit; + str_len++; + esc_ptr++; + } + if (type_len > 0) + XFREE(typebuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return (int)str_len; + } + + if (wolfSSL_BIO_write(out, str->data, str->length) != str->length){ + goto err_exit; + } + str_len += str->length; + if (type_len > 0) + XFREE(typebuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return (int)str_len; + +err_exit: + if (type_len > 0) + XFREE(typebuf, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return WOLFSSL_FAILURE; +} + +#ifndef NO_ASN_TIME +int wolfSSL_ASN1_TIME_get_length(WOLFSSL_ASN1_TIME *t) +{ + WOLFSSL_ENTER("wolfSSL_ASN1_TIME_get_length"); + if (t == NULL) + return WOLFSSL_FAILURE; + + return (int)t->data[1]; +} + +unsigned char* wolfSSL_ASN1_TIME_get_data(WOLFSSL_ASN1_TIME *t) +{ + unsigned char *dptr = NULL; + + WOLFSSL_ENTER("wolfSSL_ASN1_TIME_get_data"); + if (t == NULL) + return NULL; + + dptr = t->data + 2; + return dptr; +} + +WOLFSSL_ASN1_TIME *wolfSSL_ASN1_TIME_to_generalizedtime(WOLFSSL_ASN1_TIME *t, + WOLFSSL_ASN1_TIME **out) +{ + unsigned char time_type = 0; + WOLFSSL_ASN1_TIME *ret = NULL; + unsigned char *data_ptr = NULL; + + WOLFSSL_ENTER("wolfSSL_ASN1_TIME_to_generalizedtime"); + if (t == NULL) { + WOLFSSL_MSG("Invalid ASN_TIME value"); + } else { + time_type = t->data[0]; + if (time_type != ASN_UTC_TIME && time_type != ASN_GENERALIZED_TIME){ + WOLFSSL_MSG("Invalid ASN_TIME type."); + } else { + if (out == NULL || *out == NULL) { + ret = (WOLFSSL_ASN1_TIME*)XMALLOC(sizeof(WOLFSSL_ASN1_TIME), + NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (ret == NULL){ + WOLFSSL_MSG("memory alloc failed."); + } + else { + XMEMSET(ret, 0, sizeof(WOLFSSL_ASN1_TIME)); + } + } else { + ret = *out; + } + } + } + + if (ret != NULL) { + if (time_type == ASN_GENERALIZED_TIME){ + XMEMCPY(ret->data, t->data, ASN_GENERALIZED_TIME_SIZE); + } else { + /* (time_type == ASN_UTC_TIME) */ + ret->data[0] = ASN_GENERALIZED_TIME; + ret->data[1] = ASN_GENERALIZED_TIME_SIZE; + data_ptr = ret->data + 2; + if (t->data[2] >= '5') { + XSNPRINTF((char*)data_ptr, ASN_UTC_TIME_SIZE + 2, + "19%s", t->data + 2); + } else { + XSNPRINTF((char*)data_ptr, ASN_UTC_TIME_SIZE + 2, + "20%s", t->data + 2); + } + } + } + + return ret; +} +#endif /* !NO_ASN_TIME */ + + +#ifndef NO_ASN +int wolfSSL_i2c_ASN1_INTEGER(WOLFSSL_ASN1_INTEGER *a, unsigned char **pp) +{ + unsigned char *pptr = NULL; + char pad = 0 ; + unsigned char pad_val = 0; + int ret_size = 0; + unsigned char data1 = 0; + unsigned char neg = 0; + int i = 0; + + WOLFSSL_ENTER("wolfSSL_i2c_ASN1_INTEGER"); + if (a == NULL) + return WOLFSSL_FAILURE; + + ret_size = a->intData[1]; + if (ret_size == 0) + ret_size = 1; + else{ + ret_size = (int)a->intData[1]; + neg = a->negative; + data1 = a->intData[2]; + if (ret_size == 1 && data1 == 0) + neg = 0; + /* 0x80 or greater positive number in first byte */ + if (!neg && (data1 > 127)){ + pad = 1; + pad_val = 0; + } else if (neg){ + /* negative number */ + if (data1 > 128){ + pad = 1; + pad_val = 0xff; + } else if (data1 == 128){ + for (i = 3; i < a->intData[1] + 2; i++){ + if (a->intData[i]){ + pad = 1; + pad_val = 0xff; + break; + } + } + } + } + ret_size += (int)pad; + } + if (pp == NULL) + return ret_size; + + pptr = *pp; + if (pad) + *(pptr++) = pad_val; + if (a->intData[1] == 0) + *(pptr++) = 0; + else if (!neg){ + /* positive number */ + for (i=0; i < a->intData[1]; i++){ + *pptr = a->intData[i+2]; + pptr++; + } + } else { + /* negative number */ + int str_len = 0; + + /* 0 padding from end of buffer */ + str_len = (int)a->intData[1]; + pptr += a->intData[1] - 1; + while (!a->intData[str_len + 2] && str_len > 1){ + *(pptr--) = 0; + str_len--; + } + /* 2's complement next octet */ + *(pptr--) = ((a->intData[str_len + 1]) ^ 0xff) + 1; + str_len--; + /* Complement any octets left */ + while (str_len > 0){ + *(pptr--) = a->intData[str_len + 1] ^ 0xff; + str_len--; + } + } + *pp += ret_size; + return ret_size; +} +#endif /* !NO_ASN */ + +#ifndef NO_CERTS +int wolfSSL_X509_CA_num(WOLFSSL_X509_STORE* store) +{ + int i = 0; + int cnt_ret = 0; + Signer **table; + + WOLFSSL_ENTER("wolfSSL_X509_CA_num"); + if (store == NULL || store->cm == NULL){ + WOLFSSL_MSG("invalid parameter"); + return WOLFSSL_FAILURE; + } + + table = store->cm->caTable; + if (table){ + if (wc_LockMutex(&store->cm->caLock) == 0){ + for (i = 0; i < CA_TABLE_SIZE; i++) { + Signer* signer = table[i]; + while (signer) { + Signer* next = signer->next; + cnt_ret++; + signer = next; + } + } + wc_UnLockMutex(&store->cm->caLock); + } + } + + return cnt_ret; +} +#endif /* !NO_CERTS */ + +long wolfSSL_X509_get_version(const WOLFSSL_X509 *x509) +{ + int version = 0; + + WOLFSSL_ENTER("wolfSSL_X509_get_version"); + + if (x509 == NULL){ + WOLFSSL_MSG("invalid parameter"); + return 0L; + } + version = x509->version; + if (version != 0) + return (long)version - 1L; + + return 0L; +} + +int wolfSSL_X509_get_signature_nid(const WOLFSSL_X509 *x) +{ + if (x == NULL) + return 0; + + return oid2nid(x->sigOID, oidSigType); +} +#endif /* OPENSSL_EXTRA */ + +#if defined(OPENSSL_ALL) + +#ifndef NO_RSA +int wolfSSL_EVP_PKEY_assign_RSA(EVP_PKEY* pkey, WOLFSSL_RSA* key) +{ + if (pkey == NULL || key == NULL) + return WOLFSSL_FAILURE; + + pkey->type = EVP_PKEY_RSA; + pkey->rsa = key; + pkey->ownRsa = 1; + + return WOLFSSL_SUCCESS; +} +#endif + +int wolfSSL_EVP_PKEY_assign_EC_KEY(EVP_PKEY* pkey, WOLFSSL_EC_KEY* key) +{ + if (pkey == NULL || key == NULL) + return WOLFSSL_FAILURE; + + pkey->type = EVP_PKEY_EC; + pkey->ecc = key; + pkey->ownEcc = 1; + + return WOLFSSL_SUCCESS; +} +#endif + +#if defined(OPENSSL_ALL) && defined(HAVE_PKCS7) +PKCS7* wolfSSL_PKCS7_new(void) +{ + WOLFSSL_PKCS7* pkcs7; + int ret = 0; + + pkcs7 = (WOLFSSL_PKCS7*)XMALLOC(sizeof(*pkcs7), NULL, DYNAMIC_TYPE_PKCS7); + if (pkcs7 != NULL) { + XMEMSET(pkcs7, 0, sizeof(*pkcs7)); + ret = wc_PKCS7_Init(&pkcs7->pkcs7, NULL, INVALID_DEVID); + } + + if (ret != 0 && pkcs7 != NULL) + XFREE(pkcs7, NULL, DYNAMIC_TYPE_PKCS7); + + return (PKCS7*)pkcs7; +} + +void wolfSSL_PKCS7_free(PKCS7* pkcs7) +{ + WOLFSSL_PKCS7* p7 = (WOLFSSL_PKCS7*)pkcs7; + + if (p7 != NULL) { + if (p7->data != NULL) + XFREE(p7->data, NULL, DYNAMIC_TYPE_PKCS7); + wc_PKCS7_Free(&p7->pkcs7); + XFREE(p7, NULL, DYNAMIC_TYPE_PKCS7); + } +} + +PKCS7* wolfSSL_d2i_PKCS7(PKCS7** p7, const unsigned char** in, int len) +{ + WOLFSSL_PKCS7* pkcs7 = NULL; + word32 idx = 0; + + if (in == NULL) + return NULL; + + if ((pkcs7 = (WOLFSSL_PKCS7*)wolfSSL_PKCS7_new()) == NULL) + return NULL; + + if (GetSequence(*in, &idx, &pkcs7->len, len) < 0) { + wolfSSL_PKCS7_free((PKCS7*)pkcs7); + return NULL; + } + pkcs7->len += idx; + + pkcs7->data = (byte*)XMALLOC(pkcs7->len, NULL, DYNAMIC_TYPE_PKCS7); + if (pkcs7->data == NULL) { + wolfSSL_PKCS7_free((PKCS7*)pkcs7); + return NULL; + } + XMEMCPY(pkcs7->data, *in, pkcs7->len); + *in += pkcs7->len; + + if (p7 != NULL) + *p7 = (PKCS7*)pkcs7; + return (PKCS7*)pkcs7; +} + +PKCS7* wolfSSL_d2i_PKCS7_bio(WOLFSSL_BIO* bio, PKCS7** p7) +{ + WOLFSSL_PKCS7* pkcs7; + + if (bio == NULL) + return NULL; + + if ((pkcs7 = (WOLFSSL_PKCS7*)wolfSSL_PKCS7_new()) == NULL) + return NULL; + + pkcs7->len = wolfSSL_BIO_pending(bio); + pkcs7->data = (byte*)XMALLOC(pkcs7->len, NULL, DYNAMIC_TYPE_PKCS7); + if (pkcs7->data == NULL) { + wolfSSL_PKCS7_free((PKCS7*)pkcs7); + return NULL; + } + + if (wolfSSL_BIO_read(bio, pkcs7->data, pkcs7->len) != pkcs7->len) { + wolfSSL_PKCS7_free((PKCS7*)pkcs7); + return NULL; + } + + if (p7 != NULL) + *p7 = (PKCS7*)pkcs7; + return (PKCS7*)pkcs7; +} + +int wolfSSL_PKCS7_verify(PKCS7* pkcs7, WOLFSSL_STACK* certs, + WOLFSSL_X509_STORE* store, WOLFSSL_BIO* in, + WOLFSSL_BIO* out, int flags) +{ + int ret = 0; + unsigned char* mem = NULL; + int memSz = 0; + WOLFSSL_PKCS7* p7 = (WOLFSSL_PKCS7*)pkcs7; + + if (pkcs7 == NULL) + return WOLFSSL_FAILURE; + + if (in != NULL) { + if ((memSz = wolfSSL_BIO_get_mem_data(in, &mem)) < 0) + return WOLFSSL_FAILURE; + + p7->pkcs7.content = mem; + p7->pkcs7.contentSz = memSz; + } + + /* certs is the list of certificates to find the cert with issuer/serial. */ + (void)certs; + /* store is the certificate store to use to verify signer certificate + * associated with the signers. + */ + (void)store; + + ret = wc_PKCS7_VerifySignedData_ex(&p7->pkcs7, NULL, 0, p7->data, p7->len, + NULL, 0); + if (ret != 0) + return WOLFSSL_FAILURE; + + if ((flags & PKCS7_NOVERIFY) != PKCS7_NOVERIFY) { + /* All signer certificates are verified. */ + return WOLFSSL_FAILURE; + } + + if (out != NULL) + wolfSSL_BIO_write(out, p7->pkcs7.content, p7->pkcs7.contentSz); + + return WOLFSSL_SUCCESS; +} + +WOLFSSL_STACK* wolfSSL_PKCS7_get0_signers(PKCS7* pkcs7, WOLFSSL_STACK* certs, + int flags) +{ + WOLFSSL_STACK* signers = NULL; + WOLFSSL_PKCS7* p7 = (WOLFSSL_PKCS7*)pkcs7; + + if (p7 == NULL) + return NULL; + /* Only PKCS#7 messages with a single cert that is the verifying certificate + * is supported. + */ + if ((flags | PKCS7_NOINTERN) == PKCS7_NOINTERN) + return NULL; + + signers = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL, + DYNAMIC_TYPE_X509); + if (signers == NULL) + return NULL; + + signers->num = 1; + signers->data.x509 = (WOLFSSL_X509*)XMALLOC(sizeof(WOLFSSL_X509), NULL, + DYNAMIC_TYPE_X509); + if (signers->data.x509 == NULL) { + XFREE(signers, NULL, DYNAMIC_TYPE_X509); + return NULL; + } + + if (DecodeToX509(signers->data.x509, p7->pkcs7.singleCert, + p7->pkcs7.singleCertSz) != 0) { + XFREE(signers->data.x509, NULL, DYNAMIC_TYPE_X509); + XFREE(signers, NULL, DYNAMIC_TYPE_X509); + return NULL; + } + + (void)certs; + + return signers; +} +#endif + +#ifdef OPENSSL_ALL +WOLFSSL_STACK* wolfSSL_sk_X509_new(void) +{ + WOLFSSL_STACK* s = (WOLFSSL_STACK*)XMALLOC(sizeof(WOLFSSL_STACK), NULL, + DYNAMIC_TYPE_X509); + if (s != NULL) + XMEMSET(s, 0, sizeof(*s)); + + return s; +} +#endif + +#ifdef OPENSSL_ALL +int wolfSSL_PEM_write_bio_PKCS8PrivateKey(WOLFSSL_BIO* bio, + WOLFSSL_EVP_PKEY* pkey, + const WOLFSSL_EVP_CIPHER* enc, + char* passwd, int passwdSz, + pem_password_cb* cb, void* ctx) +{ + int ret = 0; + char password[NAME_SZ]; + byte* key = NULL; + word32 keySz; + byte* pem = NULL; + int pemSz; + int type = PKCS8_PRIVATEKEY_TYPE; + int algId; + const byte* curveOid; + word32 oidSz; + int encAlgId; + + if (bio == NULL || pkey == NULL) + return -1; + + keySz = pkey->pkey_sz + 128; + key = (byte*)XMALLOC(keySz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (key == NULL) + ret = MEMORY_E; + + if (ret == 0 && enc != NULL && passwd == NULL) { + passwdSz = cb(password, sizeof(password), 1, ctx); + if (passwdSz < 0) + ret = WOLFSSL_FAILURE; + passwd = password; + } + + if (ret == 0 && enc != NULL) { + WC_RNG rng; + ret = wc_InitRng(&rng); + if (ret == 0) { + #ifndef NO_DES3 + if (enc == EVP_DES_CBC) + encAlgId = DESb; + else if (enc == EVP_DES_EDE3_CBC) + encAlgId = DES3b; + else + #endif + #if !defined(NO_AES) && defined(HAVE_AES_CBC) + #ifdef WOLFSSL_AES_256 + if (enc == EVP_AES_256_CBC) + encAlgId = AES256CBCb; + else + #endif + #endif + ret = -1; + if (ret == 0) { + ret = TraditionalEnc((byte*)pkey->pkey.ptr, pkey->pkey_sz, key, + &keySz, passwd, passwdSz, PKCS5, PBES2, + encAlgId, NULL, 0, WC_PKCS12_ITT_DEFAULT, + &rng, NULL); + if (ret > 0) { + keySz = ret; + ret = 0; + } + } + wc_FreeRng(&rng); + } + type = PKCS8_ENC_PRIVATEKEY_TYPE; + } + if (ret == 0 && enc == NULL) { + type = PKCS8_PRIVATEKEY_TYPE; + if (pkey->type == EVP_PKEY_EC) { + algId = ECDSAk; + ret = wc_ecc_get_oid(pkey->ecc->group->curve_oid, &curveOid, + &oidSz); + } + else { + algId = RSAk; + curveOid = NULL; + oidSz = 0; + } + + if (ret >= 0) { + ret = wc_CreatePKCS8Key(key, &keySz, (byte*)pkey->pkey.ptr, + pkey->pkey_sz, algId, curveOid, oidSz); + keySz = ret; + } + } + + if (password == passwd) + XMEMSET(password, 0, passwdSz); + + if (ret >= 0) { + pemSz = 2 * keySz + 2 * 64; + pem = (byte*)XMALLOC(pemSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (pem == NULL) + ret = MEMORY_E; + } + + if (ret >= 0) + ret = wc_DerToPemEx(key, keySz, pem, pemSz, NULL, type); + + if (key != NULL) + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + if (ret >= 0) { + if (wolfSSL_BIO_write(bio, pem, ret) != ret) + ret = -1; + } + + if (pem != NULL) + XFREE(pem, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return ret < 0 ? 0 : ret; + +} + +static int bio_get_data(WOLFSSL_BIO* bio, byte** data) +{ + int ret = 0; + byte* mem = NULL; +#ifndef NO_FILESYSTEM + long memSz; + XFILE file; + long curr; +#endif + + if ((ret = wolfSSL_BIO_pending(bio)) > 0) { + } +#ifndef NO_FILESYSTEM + else if (bio->type == WOLFSSL_BIO_FILE) { + if (wolfSSL_BIO_get_fp(bio, &file) != WOLFSSL_SUCCESS) + ret = BAD_FUNC_ARG; + if (ret == 0) { + curr = XFTELL(file); + if (curr < 0) { + ret = WOLFSSL_BAD_FILE; + } + if (XFSEEK(file, 0, XSEEK_END) != 0) + ret = WOLFSSL_BAD_FILE; + } + if (ret == 0) { + memSz = XFTELL(file) - curr; + ret = (int)memSz; + if (XFSEEK(file, curr, SEEK_SET) != 0) + ret = WOLFSSL_BAD_FILE; + } + } +#endif + + if (ret > 0) { + mem = (byte*)XMALLOC(ret, bio->heap, DYNAMIC_TYPE_OPENSSL); + if (mem == NULL) { + WOLFSSL_MSG("Memory error"); + ret = MEMORY_E; + } + if (ret >= 0) { + if ((ret = wolfSSL_BIO_read(bio, mem, ret)) <= 0) { + XFREE(mem, bio->heap, DYNAMIC_TYPE_OPENSSL); + ret = MEMORY_E; + mem = NULL; + } + } + } + + *data = mem; + + return ret; +} + +/* DER data is PKCS#8 encrypted. */ +WOLFSSL_EVP_PKEY* wolfSSL_d2i_PKCS8PrivateKey_bio(WOLFSSL_BIO* bio, + WOLFSSL_EVP_PKEY** pkey, + pem_password_cb* cb, + void* ctx) +{ + int ret; + byte* der; + int len; + byte* p; + char password[NAME_SZ]; + int passwordSz; + word32 algId; + WOLFSSL_EVP_PKEY* key; + + if ((len = bio_get_data(bio, &der)) < 0) + return NULL; + + if (cb != NULL) { + passwordSz = cb(password, sizeof(password), PEM_PASS_READ, ctx); + if (passwordSz < 0) { + XFREE(der, bio->heap, DYNAMIC_TYPE_OPENSSL); + return NULL; + } + + ret = ToTraditionalEnc(der, len, password, passwordSz, &algId); + if (ret < 0) { + XFREE(der, bio->heap, DYNAMIC_TYPE_OPENSSL); + return NULL; + } + + XMEMSET(password, 0, passwordSz); + } + + p = der; + key = wolfSSL_d2i_PrivateKey_EVP(pkey, &p, len); + XFREE(der, bio->heap, DYNAMIC_TYPE_OPENSSL); + return key; +} + +/* Detect which type of key it is before decoding. */ +WOLFSSL_EVP_PKEY* wolfSSL_d2i_AutoPrivateKey(WOLFSSL_EVP_PKEY** pkey, + const unsigned char** pp, + long length) +{ + int ret; + WOLFSSL_EVP_PKEY* key = NULL; + const byte* der = *pp; + word32 idx = 0; + int len = 0; + word32 end = 0; + int cnt = 0; + int type; + word32 algId; + word32 keyLen = (word32)length; + + /* Take off PKCS#8 wrapper if found. */ + if ((len = ToTraditionalInline_ex(der, &idx, keyLen, &algId)) >= 0) { + der += idx; + keyLen = len; + } + idx = 0; + len = 0; + + /* Use the number of elements in the outer sequence to determine key type. + */ + ret = GetSequence(der, &idx, &len, keyLen); + if (ret >= 0) { + end = idx + len; + while (ret >= 0 && idx < end) { + /* Skip type */ + idx++; + /* Get length and skip over - keeping count */ + len = 0; + ret = GetLength(der, &idx, &len, keyLen); + if (ret >= 0) { + if (idx + len > end) + ret = ASN_PARSE_E; + else { + idx += len; + cnt++; + } + } + } + } + + if (ret >= 0) { + /* ECC includes version, private[, curve][, public key] */ + if (cnt >= 2 && cnt <= 4) + type = EVP_PKEY_EC; + else + type = EVP_PKEY_RSA; + + key = wolfSSL_d2i_PrivateKey(type, pkey, &der, keyLen); + *pp = der; + } + + return key; +} +#endif + +#if defined(OPENSSL_ALL) && !defined(NO_CERTS) && defined(WOLFSSL_CERT_GEN) && \ + defined(WOLFSSL_CERT_REQ) +int wolfSSL_i2d_X509_REQ(WOLFSSL_X509* req, unsigned char** out) +{ + const unsigned char* der; + int derSz = 0; + + if (req == NULL || out == NULL) { + return BAD_FUNC_ARG; + } + + der = wolfSSL_X509_get_der(req, &derSz); + if (der == NULL) { + return MEMORY_E; + } + + if (*out == NULL) { + *out = (unsigned char*)XMALLOC(derSz, NULL, DYNAMIC_TYPE_OPENSSL); + if (*out == NULL) { + return MEMORY_E; + } + } + + XMEMCPY(*out, der, derSz); + + return derSz; +} + +int wolfSSL_X509_set_subject_name(WOLFSSL_X509 *cert, WOLFSSL_X509_NAME *name) +{ + int i; + WOLFSSL_X509_NAME_ENTRY* ne; + + if (cert == NULL || name == NULL) + return WOLFSSL_FAILURE; + + FreeX509Name(&cert->subject, cert->heap); + InitX509Name(&cert->subject, 0); + if (name->dynamicName) { + cert->subject.name = (char*)XMALLOC(name->sz, cert->heap, + DYNAMIC_TYPE_SUBJECT_CN); + if (cert->subject.name == NULL) + return WOLFSSL_FAILURE; + } + XMEMCPY(cert->subject.name, name->name, name->sz); + cert->subject.sz = name->sz; + + for (i = 0; i < 10; i++) { + ne = wolfSSL_X509_NAME_get_entry(name, i); + if (ne != NULL) + wolfSSL_X509_NAME_add_entry(&cert->subject, ne, i, 1); + } + cert->subject.x509 = cert; + + return WOLFSSL_SUCCESS; +} + +int wolfSSL_X509_set_pubkey(WOLFSSL_X509 *cert, WOLFSSL_EVP_PKEY *pkey) +{ + byte* p; + + if (cert == NULL || pkey == NULL) + return WOLFSSL_FAILURE; + + if (pkey->type == EVP_PKEY_RSA) + cert->pubKeyOID = RSAk; + else if (pkey->type == EVP_PKEY_EC) + cert->pubKeyOID = ECDSAk; + else + return WOLFSSL_FAILURE; + + p = (byte*)XMALLOC(pkey->pkey_sz, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY); + if (p == NULL) + return WOLFSSL_FAILURE; + + if (cert->pubKey.buffer != NULL) + XFREE(cert->pubKey.buffer, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY); + cert->pubKey.buffer = p; + XMEMCPY(cert->pubKey.buffer, pkey->pkey.ptr, pkey->pkey_sz); + cert->pubKey.length = pkey->pkey_sz; + + return WOLFSSL_SUCCESS; +} + + +WOLFSSL_X509* wolfSSL_X509_REQ_new(void) +{ + return wolfSSL_X509_new(); +} + +void wolfSSL_X509_REQ_free(WOLFSSL_X509* req) +{ + wolfSSL_X509_free(req); +} + + +static int ReqCertFromX509(Cert* cert, WOLFSSL_X509* req) +{ + int ret; + + ret = CopyX509NameToCertName(&req->subject, &cert->subject); + if (ret == WOLFSSL_SUCCESS) { + cert->version = req->version; + cert->isCA = req->isCa; + if (req->subjKeyIdSz != 0) { + XMEMCPY(cert->skid, req->subjKeyId, req->subjKeyIdSz); + cert->skidSz = req->subjKeyIdSz; + } + if (req->keyUsageSet) + cert->keyUsage = req->keyUsage; + /* Extended Key Usage not supported. */ + } + + return ret; +} + +int wolfSSL_X509_REQ_sign(WOLFSSL_X509 *req, WOLFSSL_EVP_PKEY *pkey, + const WOLFSSL_EVP_MD *md) +{ + int ret; + Cert cert; + byte der[2048]; + int derSz = sizeof(der); + void* key = NULL; + int type = -1; + int sigType; + int hashType; +#ifndef NO_RSA + RsaKey rsa; +#endif +#ifdef HAVE_ECC + ecc_key ecc; +#endif + WC_RNG rng; + word32 idx = 0; + + if (req == NULL || pkey == NULL || md == NULL) + return WOLFSSL_FAILURE; + + /* Create a Cert that has the certificate request fields. */ + if (wc_InitCert(&cert) != 0) + return WOLFSSL_FAILURE; + if (ReqCertFromX509(&cert, req) != WOLFSSL_SUCCESS) + return WOLFSSL_FAILURE; + + /* Convert key type and hash algorithm to a signature algorithm */ + if (wolfSSL_EVP_get_hashinfo(md, &hashType, NULL) == WOLFSSL_FAILURE) + return WOLFSSL_FAILURE; + + if (pkey->type == EVP_PKEY_RSA) { + switch (hashType) { + case WC_HASH_TYPE_SHA: + sigType = CTC_SHAwRSA; + break; + case WC_HASH_TYPE_SHA224: + sigType = CTC_SHA224wRSA; + break; + case WC_HASH_TYPE_SHA256: + sigType = CTC_SHA256wRSA; + break; + case WC_HASH_TYPE_SHA384: + sigType = CTC_SHA384wRSA; + break; + case WC_HASH_TYPE_SHA512: + sigType = CTC_SHA512wRSA; + break; + default: + return WOLFSSL_FAILURE; + } + } + else if (pkey->type == EVP_PKEY_EC) { + switch (hashType) { + case WC_HASH_TYPE_SHA: + sigType = CTC_SHAwECDSA; + break; + case WC_HASH_TYPE_SHA224: + sigType = CTC_SHA224wECDSA; + break; + case WC_HASH_TYPE_SHA256: + sigType = CTC_SHA256wECDSA; + break; + case WC_HASH_TYPE_SHA384: + sigType = CTC_SHA384wECDSA; + break; + case WC_HASH_TYPE_SHA512: + sigType = CTC_SHA512wECDSA; + break; + default: + return WOLFSSL_FAILURE; + } + } + else + return WOLFSSL_FAILURE; + + /* Create a public key object from requests public key. */ +#ifndef NO_RSA + if (req->pubKeyOID == RSAk) { + type = RSA_TYPE; + ret = wc_InitRsaKey(&rsa, req->heap); + if (ret != 0) + return WOLFSSL_FAILURE; + ret = wc_RsaPublicKeyDecode(req->pubKey.buffer, &idx, &rsa, + req->pubKey.length); + if (ret != 0) { + wc_FreeRsaKey(&rsa); + return WOLFSSL_FAILURE; + } + key = (void*)&rsa; + } +#endif +#ifdef HAVE_ECC + if (req->pubKeyOID == ECDSAk) { + type = ECC_TYPE; + ret = wc_ecc_init(&ecc); + if (ret != 0) + return WOLFSSL_FAILURE; + ret = wc_EccPublicKeyDecode(req->pubKey.buffer, &idx, &ecc, + req->pubKey.length); + if (ret != 0) { + wc_ecc_free(&ecc); + return WOLFSSL_FAILURE; + } + key = (void*)&ecc; + } +#endif + if (key == NULL) + return WOLFSSL_FAILURE; + + /* Make the body of the certificate request. */ + ret = wc_MakeCertReq_ex(&cert, der, derSz, type, key); + if (ret < 0) + return WOLFSSL_FAILURE; + + /* Dispose of the public key object. */ +#ifndef NO_RSA + if (req->pubKeyOID == RSAk) + wc_FreeRsaKey(&rsa); +#endif +#ifdef HAVE_ECC + if (req->pubKeyOID == ECDSAk) + wc_ecc_free(&ecc); +#endif + + idx = 0; + /* Get the private key object and type from pkey. */ +#ifndef NO_RSA + if (pkey->type == EVP_PKEY_RSA) { + type = RSA_TYPE; + key = pkey->rsa->internal; + } +#endif +#ifdef HAVE_ECC + if (pkey->type == EVP_PKEY_EC) { + type = ECC_TYPE; + key = pkey->ecc->internal; + } +#endif + + /* Sign the certificate request body. */ + ret = wc_InitRng(&rng); + if (ret != 0) + return WOLFSSL_FAILURE; + ret = wc_SignCert_ex(cert.bodySz, sigType, der, sizeof(der), type, key, + &rng); + wc_FreeRng(&rng); + if (ret < 0) + return WOLFSSL_FAILURE; + + /* Put in the new certificate request encoding into the request object. */ + FreeDer(&req->derCert); + if (AllocDer(&req->derCert, ret, CERTREQ_TYPE, NULL) != 0) + return WOLFSSL_FAILURE; + XMEMCPY(req->derCert->buffer, der, ret); + req->derCert->length = ret; + + return WOLFSSL_SUCCESS; +} + +int wolfSSL_X509_REQ_set_subject_name(WOLFSSL_X509 *req, + WOLFSSL_X509_NAME *name) +{ + return wolfSSL_X509_set_subject_name(req, name); +} + +int wolfSSL_X509_REQ_set_pubkey(WOLFSSL_X509 *req, WOLFSSL_EVP_PKEY *pkey) +{ + return wolfSSL_X509_set_pubkey(req, pkey); +} +#endif + diff --git a/beken_os/beken378/func/wolfssl/src/tls.c b/beken_os/beken378/func/wolfssl/src/tls.c new file mode 100755 index 0000000..955fe98 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/src/tls.c @@ -0,0 +1,11220 @@ +/* tls.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifndef WOLFCRYPT_ONLY + +#include +#include +#include +#include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#ifdef HAVE_CURVE25519 + #include +#endif + +#ifdef HAVE_NTRU + #include "libntruencrypt/ntru_crypto.h" + #include +#endif + +#ifdef HAVE_QSH + static int TLSX_AddQSHKey(QSHKey** list, QSHKey* key); + static byte* TLSX_QSHKeyFind_Pub(QSHKey* qsh, word16* pubLen, word16 name); +#if defined(HAVE_NTRU) + static int TLSX_CreateNtruKey(WOLFSSL* ssl, int type); +#endif +#endif /* HAVE_QSH */ + +#if (!defined(NO_WOLFSSL_SERVER) && defined(WOLFSSL_TLS13) && \ + !defined(WOLFSSL_NO_SERVER_GROUPS_EXT)) || \ + (defined(WOLFSSL_TLS13) && defined(HAVE_SUPPORTED_CURVES)) +static int TLSX_KeyShare_IsSupported(int namedGroup); +#endif + +#if ((!defined(NO_WOLFSSL_SERVER) && defined(WOLFSSL_TLS13) && \ + !defined(WOLFSSL_NO_SERVER_GROUPS_EXT)) || \ + (defined(WOLFSSL_TLS13) && !defined(HAVE_ECC) && \ + !defined(HAVE_CURVE25519) && defined(HAVE_SUPPORTED_CURVES)) || \ + ((defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \ + defined(HAVE_SUPPORTED_CURVES))) && \ + defined(HAVE_TLS_EXTENSIONS) +static int TLSX_PopulateSupportedGroups(WOLFSSL* ssl, TLSX** extensions); +#endif + + +#ifndef NO_TLS + +/* Digest enable checks */ +#ifdef NO_OLD_TLS /* TLS 1.2 only */ + #if defined(NO_SHA256) && !defined(WOLFSSL_SHA384) && \ + !defined(WOLFSSL_SHA512) + #error Must have SHA256, SHA384 or SHA512 enabled for TLS 1.2 + #endif +#else /* TLS 1.1 or older */ + #if defined(NO_MD5) && defined(NO_SHA) + #error Must have SHA1 and MD5 enabled for old TLS + #endif +#endif + +#ifdef WOLFSSL_TLS13 + #if !defined(NO_DH) && \ + !defined(HAVE_FFDHE_2048) && !defined(HAVE_FFDHE_3072) && \ + !defined(HAVE_FFDHE_4096) && !defined(HAVE_FFDHE_6144) && \ + !defined(HAVE_FFDHE_8192) + #error Please configure your TLS 1.3 DH key size using either: HAVE_FFDHE_2048, HAVE_FFDHE_3072, HAVE_FFDHE_4096, HAVE_FFDHE_6144 or HAVE_FFDHE_8192 + #endif + #if !defined(NO_RSA) && !defined(WC_RSA_PSS) + #error The build option WC_RSA_PSS is required for TLS 1.3 with RSA + #endif + #ifndef HAVE_TLS_EXTENSIONS + #ifndef _MSC_VER + #error "The build option HAVE_TLS_EXTENSIONS is required for TLS 1.3" + #else + #pragma message("Error: The build option HAVE_TLS_EXTENSIONS is required for TLS 1.3") + #endif + #endif +#endif + +/* Warn if secrets logging is enabled */ +#if defined(SHOW_SECRETS) || defined(WOLFSSL_SSLKEYLOGFILE) + #ifndef _MSC_VER + #warning The SHOW_SECRETS and WOLFSSL_SSLKEYLOGFILE options should only be used for debugging and never in a production environment + #else + #pragma message("Warning: The SHOW_SECRETS and WOLFSSL_SSLKEYLOGFILE options should only be used for debugging and never in a production environment") + #endif +#endif + +/* Optional Pre-Master-Secret logging for Wireshark */ +#if !defined(NO_FILESYSTEM) && defined(WOLFSSL_SSLKEYLOGFILE) +#ifndef WOLFSSL_SSLKEYLOGFILE_OUTPUT + #define WOLFSSL_SSLKEYLOGFILE_OUTPUT "sslkeylog.log" +#endif +#endif + +#ifndef WOLFSSL_NO_TLS12 + +#ifdef WOLFSSL_SHA384 + #define HSHASH_SZ WC_SHA384_DIGEST_SIZE +#else + #define HSHASH_SZ FINISHED_SZ +#endif + + +int BuildTlsHandshakeHash(WOLFSSL* ssl, byte* hash, word32* hashLen) +{ + int ret = 0; + word32 hashSz = FINISHED_SZ; + + if (ssl == NULL || hash == NULL || hashLen == NULL || *hashLen < HSHASH_SZ) + return BAD_FUNC_ARG; + + /* for constant timing perform these even if error */ +#ifndef NO_OLD_TLS + ret |= wc_Md5GetHash(&ssl->hsHashes->hashMd5, hash); + ret |= wc_ShaGetHash(&ssl->hsHashes->hashSha, &hash[WC_MD5_DIGEST_SIZE]); +#endif + + if (IsAtLeastTLSv1_2(ssl)) { +#ifndef NO_SHA256 + if (ssl->specs.mac_algorithm <= sha256_mac || + ssl->specs.mac_algorithm == blake2b_mac) { + ret |= wc_Sha256GetHash(&ssl->hsHashes->hashSha256, hash); + hashSz = WC_SHA256_DIGEST_SIZE; + } +#endif +#ifdef WOLFSSL_SHA384 + if (ssl->specs.mac_algorithm == sha384_mac) { + ret |= wc_Sha384GetHash(&ssl->hsHashes->hashSha384, hash); + hashSz = WC_SHA384_DIGEST_SIZE; + } +#endif + } + + *hashLen = hashSz; + + if (ret != 0) + ret = BUILD_MSG_ERROR; + + return ret; +} + + +int BuildTlsFinished(WOLFSSL* ssl, Hashes* hashes, const byte* sender) +{ + int ret; + const byte* side; + word32 hashSz = HSHASH_SZ; +#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH) + DECLARE_VAR(handshake_hash, byte, HSHASH_SZ, ssl->heap); + if (handshake_hash == NULL) + return MEMORY_E; +#else + byte handshake_hash[HSHASH_SZ]; +#endif + + ret = BuildTlsHandshakeHash(ssl, handshake_hash, &hashSz); + if (ret == 0) { + if (XSTRNCMP((const char*)sender, (const char*)client, SIZEOF_SENDER) == 0) + side = tls_client; + else + side = tls_server; + +#ifdef WOLFSSL_HAVE_PRF + ret = wc_PRF_TLS((byte*)hashes, TLS_FINISHED_SZ, ssl->arrays->masterSecret, + SECRET_LEN, side, FINISHED_LABEL_SZ, handshake_hash, hashSz, + IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm, + ssl->heap, ssl->devId); +#else + /* Pseudo random function must be enabled in the configuration. */ + ret = PRF_MISSING; + WOLFSSL_MSG("Pseudo-random function is not enabled"); + + (void)side; + (void)hashes; +#endif + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH) + FREE_VAR(handshake_hash, ssl->heap); +#endif + + return ret; +} + +#endif /* !WOLFSSL_NO_TLS12 */ + +#ifndef NO_OLD_TLS + +#ifdef WOLFSSL_ALLOW_TLSV10 +ProtocolVersion MakeTLSv1(void) +{ + ProtocolVersion pv; + pv.major = SSLv3_MAJOR; + pv.minor = TLSv1_MINOR; + + return pv; +} +#endif /* WOLFSSL_ALLOW_TLSV10 */ + + +ProtocolVersion MakeTLSv1_1(void) +{ + ProtocolVersion pv; + pv.major = SSLv3_MAJOR; + pv.minor = TLSv1_1_MINOR; + + return pv; +} + +#endif /* !NO_OLD_TLS */ + + +#ifndef WOLFSSL_NO_TLS12 + +ProtocolVersion MakeTLSv1_2(void) +{ + ProtocolVersion pv; + pv.major = SSLv3_MAJOR; + pv.minor = TLSv1_2_MINOR; + + return pv; +} + +#endif /* !WOLFSSL_NO_TLS12 */ + +#ifdef WOLFSSL_TLS13 +/* The TLS v1.3 protocol version. + * + * returns the protocol version data for TLS v1.3. + */ +ProtocolVersion MakeTLSv1_3(void) +{ + ProtocolVersion pv; + pv.major = SSLv3_MAJOR; + pv.minor = TLSv1_3_MINOR; + + return pv; +} +#endif + +#ifndef WOLFSSL_NO_TLS12 + +#ifdef HAVE_EXTENDED_MASTER +static const byte ext_master_label[EXT_MASTER_LABEL_SZ + 1] = + "extended master secret"; +#endif +static const byte master_label[MASTER_LABEL_SZ + 1] = "master secret"; +static const byte key_label [KEY_LABEL_SZ + 1] = "key expansion"; + +static int _DeriveTlsKeys(byte* key_dig, word32 key_dig_len, + const byte* ms, word32 msLen, + const byte* sr, const byte* cr, + int tls1_2, int hash_type, + void* heap, int devId) +{ + int ret; +#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH) + DECLARE_VAR(seed, byte, SEED_LEN, heap); + if (seed == NULL) + return MEMORY_E; +#else + byte seed[SEED_LEN]; +#endif + + XMEMCPY(seed, sr, RAN_LEN); + XMEMCPY(seed + RAN_LEN, cr, RAN_LEN); + +#ifdef WOLFSSL_HAVE_PRF + ret = wc_PRF_TLS(key_dig, key_dig_len, ms, msLen, key_label, KEY_LABEL_SZ, + seed, SEED_LEN, tls1_2, hash_type, heap, devId); +#else + /* Pseudo random function must be enabled in the configuration. */ + ret = PRF_MISSING; + WOLFSSL_MSG("Pseudo-random function is not enabled"); + + (void)key_dig; + (void)key_dig_len; + (void)ms; + (void)msLen; + (void)tls1_2; + (void)hash_type; + (void)heap; + (void)devId; + (void)key_label; + (void)master_label; +#ifdef HAVE_EXTENDED_MASTER + (void)ext_master_label; +#endif +#endif + +#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH) + FREE_VAR(seed, heap); +#endif + + return ret; +} + +/* External facing wrapper so user can call as well, 0 on success */ +int wolfSSL_DeriveTlsKeys(byte* key_dig, word32 key_dig_len, + const byte* ms, word32 msLen, + const byte* sr, const byte* cr, + int tls1_2, int hash_type) +{ + return _DeriveTlsKeys(key_dig, key_dig_len, ms, msLen, sr, cr, tls1_2, + hash_type, NULL, INVALID_DEVID); +} + + +int DeriveTlsKeys(WOLFSSL* ssl) +{ + int ret; + int key_dig_len = 2 * ssl->specs.hash_size + + 2 * ssl->specs.key_size + + 2 * ssl->specs.iv_size; +#ifdef WOLFSSL_SMALL_STACK + byte* key_dig; +#else + byte key_dig[MAX_PRF_DIG]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + key_dig = (byte*)XMALLOC(MAX_PRF_DIG, ssl->heap, DYNAMIC_TYPE_DIGEST); + if (key_dig == NULL) { + return MEMORY_E; + } +#endif + + ret = _DeriveTlsKeys(key_dig, key_dig_len, + ssl->arrays->masterSecret, SECRET_LEN, + ssl->arrays->serverRandom, ssl->arrays->clientRandom, + IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm, + ssl->heap, ssl->devId); + if (ret == 0) + ret = StoreKeys(ssl, key_dig, PROVISION_CLIENT_SERVER); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(key_dig, ssl->heap, DYNAMIC_TYPE_DIGEST); +#endif + + return ret; +} + +static int _MakeTlsMasterSecret(byte* ms, word32 msLen, + const byte* pms, word32 pmsLen, + const byte* cr, const byte* sr, + int tls1_2, int hash_type, + void* heap, int devId) +{ + int ret; +#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH) + DECLARE_VAR(seed, byte, SEED_LEN, heap); + if (seed == NULL) + return MEMORY_E; +#else + byte seed[SEED_LEN]; +#endif + + XMEMCPY(seed, cr, RAN_LEN); + XMEMCPY(seed + RAN_LEN, sr, RAN_LEN); + +#ifdef WOLFSSL_HAVE_PRF + ret = wc_PRF_TLS(ms, msLen, pms, pmsLen, master_label, MASTER_LABEL_SZ, + seed, SEED_LEN, tls1_2, hash_type, heap, devId); +#else + /* Pseudo random function must be enabled in the configuration. */ + ret = PRF_MISSING; + WOLFSSL_MSG("Pseudo-random function is not enabled"); + + (void)ms; + (void)msLen; + (void)pms; + (void)pmsLen; + (void)tls1_2; + (void)hash_type; + (void)heap; + (void)devId; +#endif + +#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH) + FREE_VAR(seed, heap); +#endif + + return ret; +} + +/* External facing wrapper so user can call as well, 0 on success */ +int wolfSSL_MakeTlsMasterSecret(byte* ms, word32 msLen, + const byte* pms, word32 pmsLen, + const byte* cr, const byte* sr, + int tls1_2, int hash_type) +{ + return _MakeTlsMasterSecret(ms, msLen, pms, pmsLen, cr, sr, tls1_2, + hash_type, NULL, INVALID_DEVID); +} + + +#ifdef HAVE_EXTENDED_MASTER + +static int _MakeTlsExtendedMasterSecret(byte* ms, word32 msLen, + const byte* pms, word32 pmsLen, + const byte* sHash, word32 sHashLen, + int tls1_2, int hash_type, + void* heap, int devId) +{ + int ret; + +#ifdef WOLFSSL_HAVE_PRF + ret = wc_PRF_TLS(ms, msLen, pms, pmsLen, ext_master_label, EXT_MASTER_LABEL_SZ, + sHash, sHashLen, tls1_2, hash_type, heap, devId); +#else + /* Pseudo random function must be enabled in the configuration. */ + ret = PRF_MISSING; + WOLFSSL_MSG("Pseudo-random function is not enabled"); + + (void)ms; + (void)msLen; + (void)pms; + (void)pmsLen; + (void)sHash; + (void)sHashLen; + (void)tls1_2; + (void)hash_type; + (void)heap; + (void)devId; +#endif + return ret; +} + +/* External facing wrapper so user can call as well, 0 on success */ +int wolfSSL_MakeTlsExtendedMasterSecret(byte* ms, word32 msLen, + const byte* pms, word32 pmsLen, + const byte* sHash, word32 sHashLen, + int tls1_2, int hash_type) +{ + return _MakeTlsExtendedMasterSecret(ms, msLen, pms, pmsLen, sHash, sHashLen, + tls1_2, hash_type, NULL, INVALID_DEVID); +} + +#endif /* HAVE_EXTENDED_MASTER */ + + +int MakeTlsMasterSecret(WOLFSSL* ssl) +{ + int ret; + +#ifdef HAVE_EXTENDED_MASTER + if (ssl->options.haveEMS) { + word32 hashSz = HSHASH_SZ; + #ifdef WOLFSSL_SMALL_STACK + byte* handshake_hash = (byte*)XMALLOC(HSHASH_SZ, ssl->heap, + DYNAMIC_TYPE_DIGEST); + if (handshake_hash == NULL) + return MEMORY_E; + #else + byte handshake_hash[HSHASH_SZ]; + #endif + + ret = BuildTlsHandshakeHash(ssl, handshake_hash, &hashSz); + if (ret == 0) { + ret = _MakeTlsExtendedMasterSecret( + ssl->arrays->masterSecret, SECRET_LEN, + ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz, + handshake_hash, hashSz, + IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm, + ssl->heap, ssl->devId); + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(handshake_hash, ssl->heap, DYNAMIC_TYPE_DIGEST); + #endif + } + else +#endif /* HAVE_EXTENDED_MASTER */ + { + ret = _MakeTlsMasterSecret(ssl->arrays->masterSecret, SECRET_LEN, + ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz, + ssl->arrays->clientRandom, ssl->arrays->serverRandom, + IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm, + ssl->heap, ssl->devId); + } + if (ret == 0) { + #ifdef SHOW_SECRETS + /* Wireshark Pre-Master-Secret Format: + * CLIENT_RANDOM + */ + const char* CLIENT_RANDOM_LABEL = "CLIENT_RANDOM"; + int i, pmsPos = 0; + char pmsBuf[13 + 1 + 64 + 1 + 96 + 1 + 1]; + + XSNPRINTF(&pmsBuf[pmsPos], sizeof(pmsBuf) - pmsPos, "%s ", + CLIENT_RANDOM_LABEL); + pmsPos += XSTRLEN(CLIENT_RANDOM_LABEL) + 1; + for (i = 0; i < RAN_LEN; i++) { + XSNPRINTF(&pmsBuf[pmsPos], sizeof(pmsBuf) - pmsPos, "%02x", + ssl->arrays->clientRandom[i]); + pmsPos += 2; + } + XSNPRINTF(&pmsBuf[pmsPos], sizeof(pmsBuf) - pmsPos, " "); + pmsPos += 1; + for (i = 0; i < SECRET_LEN; i++) { + XSNPRINTF(&pmsBuf[pmsPos], sizeof(pmsBuf) - pmsPos, "%02x", + ssl->arrays->masterSecret[i]); + pmsPos += 2; + } + XSNPRINTF(&pmsBuf[pmsPos], sizeof(pmsBuf) - pmsPos, "\n"); + pmsPos += 1; + + /* print master secret */ + puts(pmsBuf); + + #if !defined(NO_FILESYSTEM) && defined(WOLFSSL_SSLKEYLOGFILE) + { + FILE* f = XFOPEN(WOLFSSL_SSLKEYLOGFILE_OUTPUT, "a"); + if (f != XBADFILE) { + XFWRITE(pmsBuf, 1, pmsPos, f); + XFCLOSE(f); + } + } + #endif + #endif /* SHOW_SECRETS */ + + ret = DeriveTlsKeys(ssl); + } + + return ret; +} + + +/* Used by EAP-TLS and EAP-TTLS to derive keying material from + * the master_secret. */ +int wolfSSL_make_eap_keys(WOLFSSL* ssl, void* msk, unsigned int len, + const char* label) +{ + int ret; +#ifdef WOLFSSL_SMALL_STACK + byte* seed; +#else + byte seed[SEED_LEN]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + seed = (byte*)XMALLOC(SEED_LEN, ssl->heap, DYNAMIC_TYPE_SEED); + if (seed == NULL) + return MEMORY_E; +#endif + + /* + * As per RFC-5281, the order of the client and server randoms is reversed + * from that used by the TLS protocol to derive keys. + */ + XMEMCPY(seed, ssl->arrays->clientRandom, RAN_LEN); + XMEMCPY(seed + RAN_LEN, ssl->arrays->serverRandom, RAN_LEN); + +#ifdef WOLFSSL_HAVE_PRF + ret = wc_PRF_TLS((byte*)msk, len, ssl->arrays->masterSecret, SECRET_LEN, + (const byte *)label, (word32)XSTRLEN(label), seed, SEED_LEN, + IsAtLeastTLSv1_2(ssl), ssl->specs.mac_algorithm, + ssl->heap, ssl->devId); +#else + /* Pseudo random function must be enabled in the configuration. */ + ret = PRF_MISSING; + WOLFSSL_MSG("Pseudo-random function is not enabled"); + + (void)msk; + (void)len; + (void)label; +#endif + +#ifdef WOLFSSL_SMALL_STACK + XFREE(seed, ssl->heap, DYNAMIC_TYPE_SEED); +#endif + + return ret; +} + + +static WC_INLINE void GetSEQIncrement(WOLFSSL* ssl, int verify, word32 seq[2]) +{ + if (verify) { + seq[0] = ssl->keys.peer_sequence_number_hi; + seq[1] = ssl->keys.peer_sequence_number_lo++; + if (seq[1] > ssl->keys.peer_sequence_number_lo) { + /* handle rollover */ + ssl->keys.peer_sequence_number_hi++; + } + } + else { + seq[0] = ssl->keys.sequence_number_hi; + seq[1] = ssl->keys.sequence_number_lo++; + if (seq[1] > ssl->keys.sequence_number_lo) { + /* handle rollover */ + ssl->keys.sequence_number_hi++; + } + } +} + + +#ifdef WOLFSSL_DTLS +static WC_INLINE void DtlsGetSEQ(WOLFSSL* ssl, int order, word32 seq[2]) +{ + if (order == PREV_ORDER) { + /* Previous epoch case */ + seq[0] = ((ssl->keys.dtls_epoch - 1) << 16) | + (ssl->keys.dtls_prev_sequence_number_hi & 0xFFFF); + seq[1] = ssl->keys.dtls_prev_sequence_number_lo; + } + else if (order == PEER_ORDER) { + seq[0] = (ssl->keys.curEpoch << 16) | + (ssl->keys.curSeq_hi & 0xFFFF); + seq[1] = ssl->keys.curSeq_lo; /* explicit from peer */ + } + else { + seq[0] = (ssl->keys.dtls_epoch << 16) | + (ssl->keys.dtls_sequence_number_hi & 0xFFFF); + seq[1] = ssl->keys.dtls_sequence_number_lo; + } +} +#endif /* WOLFSSL_DTLS */ + + +static WC_INLINE void WriteSEQ(WOLFSSL* ssl, int verifyOrder, byte* out) +{ + word32 seq[2] = {0, 0}; + + if (!ssl->options.dtls) { + GetSEQIncrement(ssl, verifyOrder, seq); + } + else { +#ifdef WOLFSSL_DTLS + DtlsGetSEQ(ssl, verifyOrder, seq); +#endif + } + + c32toa(seq[0], out); + c32toa(seq[1], out + OPAQUE32_LEN); +} + + +/*** end copy ***/ + + +/* return HMAC digest type in wolfSSL format */ +int wolfSSL_GetHmacType(WOLFSSL* ssl) +{ + if (ssl == NULL) + return BAD_FUNC_ARG; + + switch (ssl->specs.mac_algorithm) { + #ifndef NO_MD5 + case md5_mac: + { + return WC_MD5; + } + #endif + #ifndef NO_SHA256 + case sha256_mac: + { + return WC_SHA256; + } + #endif + #ifdef WOLFSSL_SHA384 + case sha384_mac: + { + return WC_SHA384; + } + + #endif + #ifndef NO_SHA + case sha_mac: + { + return WC_SHA; + } + #endif + #ifdef HAVE_BLAKE2 + case blake2b_mac: + { + return BLAKE2B_ID; + } + #endif + default: + { + return WOLFSSL_FATAL_ERROR; + } + } +} + + +int wolfSSL_SetTlsHmacInner(WOLFSSL* ssl, byte* inner, word32 sz, int content, + int verify) +{ + if (ssl == NULL || inner == NULL) + return BAD_FUNC_ARG; + + XMEMSET(inner, 0, WOLFSSL_TLS_HMAC_INNER_SZ); + + WriteSEQ(ssl, verify, inner); + inner[SEQ_SZ] = (byte)content; + inner[SEQ_SZ + ENUM_LEN] = ssl->version.major; + inner[SEQ_SZ + ENUM_LEN + ENUM_LEN] = ssl->version.minor; + c16toa((word16)sz, inner + SEQ_SZ + ENUM_LEN + VERSION_SZ); + + return 0; +} + + +#ifndef WOLFSSL_AEAD_ONLY +#if !defined(WOLFSSL_NO_HASH_RAW) && !defined(HAVE_FIPS) && \ + !defined(HAVE_SELFTEST) + +/* Update the hash in the HMAC. + * + * hmac HMAC object. + * data Data to be hashed. + * sz Size of data to hash. + * returns 0 on success, otherwise failure. + */ +static int Hmac_HashUpdate(Hmac* hmac, const byte* data, word32 sz) +{ + int ret = BAD_FUNC_ARG; + + switch (hmac->macType) { + #ifndef NO_SHA + case WC_SHA: + ret = wc_ShaUpdate(&hmac->hash.sha, data, sz); + break; + #endif /* !NO_SHA */ + + #ifndef NO_SHA256 + case WC_SHA256: + ret = wc_Sha256Update(&hmac->hash.sha256, data, sz); + break; + #endif /* !NO_SHA256 */ + + #ifdef WOLFSSL_SHA384 + case WC_SHA384: + ret = wc_Sha384Update(&hmac->hash.sha384, data, sz); + break; + #endif /* WOLFSSL_SHA384 */ + + #ifdef WOLFSSL_SHA512 + case WC_SHA512: + ret = wc_Sha512Update(&hmac->hash.sha512, data, sz); + break; + #endif /* WOLFSSL_SHA512 */ + } + + return ret; +} + +/* Finalize the hash but don't put the EOC, padding or length in. + * + * hmac HMAC object. + * hash Hash result. + * returns 0 on success, otherwise failure. + */ +static int Hmac_HashFinalRaw(Hmac* hmac, unsigned char* hash) +{ + int ret = BAD_FUNC_ARG; + + switch (hmac->macType) { + #ifndef NO_SHA + case WC_SHA: + ret = wc_ShaFinalRaw(&hmac->hash.sha, hash); + break; + #endif /* !NO_SHA */ + + #ifndef NO_SHA256 + case WC_SHA256: + ret = wc_Sha256FinalRaw(&hmac->hash.sha256, hash); + break; + #endif /* !NO_SHA256 */ + + #ifdef WOLFSSL_SHA384 + case WC_SHA384: + ret = wc_Sha384FinalRaw(&hmac->hash.sha384, hash); + break; + #endif /* WOLFSSL_SHA384 */ + + #ifdef WOLFSSL_SHA512 + case WC_SHA512: + ret = wc_Sha512FinalRaw(&hmac->hash.sha512, hash); + break; + #endif /* WOLFSSL_SHA512 */ + } + + return ret; +} + +/* Finalize the HMAC by performing outer hash. + * + * hmac HMAC object. + * mac MAC result. + * returns 0 on success, otherwise failure. + */ +static int Hmac_OuterHash(Hmac* hmac, unsigned char* mac) +{ + int ret = BAD_FUNC_ARG; + wc_HashAlg hash; + enum wc_HashType hashType = (enum wc_HashType)hmac->macType; + int digestSz = wc_HashGetDigestSize(hashType); + int blockSz = wc_HashGetBlockSize(hashType); + + if ((digestSz >= 0) && (blockSz >= 0)) { + ret = wc_HashInit(&hash, hashType); + } + if (ret == 0) { + ret = wc_HashUpdate(&hash, hashType, (byte*)hmac->opad, + blockSz); + if (ret == 0) + ret = wc_HashUpdate(&hash, hashType, (byte*)hmac->innerHash, + digestSz); + if (ret == 0) + ret = wc_HashFinal(&hash, hashType, mac); + wc_HashFree(&hash, hashType); + } + + return ret; +} + +/* Calculate the HMAC of the header + message data. + * Constant time implementation using wc_Sha*FinalRaw(). + * + * hmac HMAC object. + * digest MAC result. + * in Message data. + * sz Size of the message data. + * header Constructed record header with length of handshake data. + * returns 0 on success, otherwise failure. + */ +static int Hmac_UpdateFinal_CT(Hmac* hmac, byte* digest, const byte* in, + word32 sz, byte* header) +{ + byte lenBytes[8]; + int i, j, k; + int blockBits, blockMask; + int lastBlockLen, macLen, extraLen, eocIndex; + int blocks, safeBlocks, lenBlock, eocBlock; + int maxLen; + int blockSz, padSz; + int ret; + word32 realLen; + byte extraBlock; + + switch (hmac->macType) { + #ifndef NO_SHA + case WC_SHA: + blockSz = WC_SHA_BLOCK_SIZE; + blockBits = 6; + macLen = WC_SHA_DIGEST_SIZE; + padSz = WC_SHA_BLOCK_SIZE - WC_SHA_PAD_SIZE + 1; + break; + #endif /* !NO_SHA */ + + #ifndef NO_SHA256 + case WC_SHA256: + blockSz = WC_SHA256_BLOCK_SIZE; + blockBits = 6; + macLen = WC_SHA256_DIGEST_SIZE; + padSz = WC_SHA256_BLOCK_SIZE - WC_SHA256_PAD_SIZE + 1; + break; + #endif /* !NO_SHA256 */ + + #ifdef WOLFSSL_SHA384 + case WC_SHA384: + blockSz = WC_SHA384_BLOCK_SIZE; + blockBits = 7; + macLen = WC_SHA384_DIGEST_SIZE; + padSz = WC_SHA384_BLOCK_SIZE - WC_SHA384_PAD_SIZE + 1; + break; + #endif /* WOLFSSL_SHA384 */ + + #ifdef WOLFSSL_SHA512 + case WC_SHA512: + blockSz = WC_SHA512_BLOCK_SIZE; + blockBits = 7; + macLen = WC_SHA512_DIGEST_SIZE; + padSz = WC_SHA512_BLOCK_SIZE - WC_SHA512_PAD_SIZE + 1; + break; + #endif /* WOLFSSL_SHA512 */ + + default: + return BAD_FUNC_ARG; + } + blockMask = blockSz - 1; + + /* Size of data to HMAC if padding length byte is zero. */ + maxLen = WOLFSSL_TLS_HMAC_INNER_SZ + sz - 1 - macLen; + /* Complete data (including padding) has block for EOC and/or length. */ + extraBlock = ctSetLTE((maxLen + padSz) & blockMask, padSz); + /* Total number of blocks for data including padding. */ + blocks = ((maxLen + blockSz - 1) >> blockBits) + extraBlock; + /* Up to last 6 blocks can be hashed safely. */ + safeBlocks = blocks - 6; + + /* Length of message data. */ + realLen = maxLen - in[sz - 1]; + /* Number of message bytes in last block. */ + lastBlockLen = realLen & blockMask; + /* Number of padding bytes in last block. */ + extraLen = ((blockSz * 2 - padSz - lastBlockLen) & blockMask) + 1; + /* Number of blocks to create for hash. */ + lenBlock = (realLen + extraLen) >> blockBits; + /* Block containing EOC byte. */ + eocBlock = realLen >> blockBits; + /* Index of EOC byte in block. */ + eocIndex = realLen & blockMask; + + /* Add length of hmac's ipad to total length. */ + realLen += blockSz; + /* Length as bits - 8 bytes bigendian. */ + c32toa(realLen >> ((sizeof(word32) * 8) - 3), lenBytes); + c32toa(realLen << 3, lenBytes + sizeof(word32)); + + ret = Hmac_HashUpdate(hmac, (unsigned char*)hmac->ipad, blockSz); + if (ret != 0) + return ret; + + XMEMSET(hmac->innerHash, 0, macLen); + + if (safeBlocks > 0) { + ret = Hmac_HashUpdate(hmac, header, WOLFSSL_TLS_HMAC_INNER_SZ); + if (ret != 0) + return ret; + ret = Hmac_HashUpdate(hmac, in, safeBlocks * blockSz - + WOLFSSL_TLS_HMAC_INNER_SZ); + if (ret != 0) + return ret; + } + else + safeBlocks = 0; + + XMEMSET(digest, 0, macLen); + k = safeBlocks * blockSz; + for (i = safeBlocks; i < blocks; i++) { + unsigned char hashBlock[WC_MAX_BLOCK_SIZE]; + unsigned char isEocBlock = ctMaskEq(i, eocBlock); + unsigned char isOutBlock = ctMaskEq(i, lenBlock); + + for (j = 0; j < blockSz; j++, k++) { + unsigned char atEoc = ctMaskEq(j, eocIndex) & isEocBlock; + unsigned char pastEoc = ctMaskGT(j, eocIndex) & isEocBlock; + unsigned char b = 0; + + if (k < WOLFSSL_TLS_HMAC_INNER_SZ) + b = header[k]; + else if (k < maxLen) + b = in[k - WOLFSSL_TLS_HMAC_INNER_SZ]; + + b = ctMaskSel(atEoc, 0x80, b); + b &= (unsigned char)~(word32)pastEoc; + b &= ((unsigned char)~(word32)isOutBlock) | isEocBlock; + + if (j >= blockSz - 8) { + b = ctMaskSel(isOutBlock, lenBytes[j - (blockSz - 8)], b); + } + + hashBlock[j] = b; + } + + ret = Hmac_HashUpdate(hmac, hashBlock, blockSz); + if (ret != 0) + return ret; + ret = Hmac_HashFinalRaw(hmac, hashBlock); + if (ret != 0) + return ret; + for (j = 0; j < macLen; j++) + ((unsigned char*)hmac->innerHash)[j] |= hashBlock[j] & isOutBlock; + } + + ret = Hmac_OuterHash(hmac, digest); + + return ret; +} + +#endif + +#if defined(WOLFSSL_NO_HASH_RAW) || defined(HAVE_FIPS) || \ + defined(HAVE_SELFTEST) || defined(HAVE_BLAKE2) + +/* Calculate the HMAC of the header + message data. + * Constant time implementation using normal hashing operations. + * Update-Final need to be constant time. + * + * hmac HMAC object. + * digest MAC result. + * in Message data. + * sz Size of the message data. + * header Constructed record header with length of handshake data. + * returns 0 on success, otherwise failure. + */ +static int Hmac_UpdateFinal(Hmac* hmac, byte* digest, const byte* in, + word32 sz, byte* header) +{ + byte dummy[WC_MAX_BLOCK_SIZE] = {0}; + int ret; + word32 msgSz, blockSz, macSz, padSz, maxSz, realSz; + word32 currSz, offset = 0; + int msgBlocks, blocks, blockBits; + int i; + + switch (hmac->macType) { + #ifndef NO_SHA + case WC_SHA: + blockSz = WC_SHA_BLOCK_SIZE; + blockBits = 6; + macSz = WC_SHA_DIGEST_SIZE; + padSz = WC_SHA_BLOCK_SIZE - WC_SHA_PAD_SIZE + 1; + break; + #endif /* !NO_SHA */ + + #ifndef NO_SHA256 + case WC_SHA256: + blockSz = WC_SHA256_BLOCK_SIZE; + blockBits = 6; + macSz = WC_SHA256_DIGEST_SIZE; + padSz = WC_SHA256_BLOCK_SIZE - WC_SHA256_PAD_SIZE + 1; + break; + #endif /* !NO_SHA256 */ + + #ifdef WOLFSSL_SHA384 + case WC_SHA384: + blockSz = WC_SHA384_BLOCK_SIZE; + blockBits = 7; + macSz = WC_SHA384_DIGEST_SIZE; + padSz = WC_SHA384_BLOCK_SIZE - WC_SHA384_PAD_SIZE + 1; + break; + #endif /* WOLFSSL_SHA384 */ + + #ifdef WOLFSSL_SHA512 + case WC_SHA512: + blockSz = WC_SHA512_BLOCK_SIZE; + blockBits = 7; + macSz = WC_SHA512_DIGEST_SIZE; + padSz = WC_SHA512_BLOCK_SIZE - WC_SHA512_PAD_SIZE + 1; + break; + #endif /* WOLFSSL_SHA512 */ + + #ifdef HAVE_BLAKE2 + case WC_HASH_TYPE_BLAKE2B: + blockSz = BLAKE2B_BLOCKBYTES; + blockBits = 7; + macSz = BLAKE2B_256; + padSz = 0; + break; + #endif /* HAVE_BLAK2 */ + + default: + return BAD_FUNC_ARG; + } + + msgSz = sz - (1 + in[sz - 1] + macSz); + /* Make negative result 0 */ + msgSz &= ~(0 - (msgSz >> 31)); + realSz = WOLFSSL_TLS_HMAC_INNER_SZ + msgSz; + maxSz = WOLFSSL_TLS_HMAC_INNER_SZ + (sz - 1) - macSz; + + /* Calculate #blocks processed in HMAC for max and real data. */ + blocks = maxSz >> blockBits; + blocks += ((maxSz + padSz) % blockSz) < padSz; + msgBlocks = realSz >> blockBits; + /* #Extra blocks to process. */ + blocks -= msgBlocks + (((realSz + padSz) % blockSz) < padSz); + /* Calculate whole blocks. */ + msgBlocks--; + + ret = wc_HmacUpdate(hmac, header, WOLFSSL_TLS_HMAC_INNER_SZ); + if (ret == 0) { + /* Fill the rest of the block with any available data. */ + currSz = ctMaskLT(msgSz, blockSz) & msgSz; + currSz |= ctMaskGTE(msgSz, blockSz) & blockSz; + currSz -= WOLFSSL_TLS_HMAC_INNER_SZ; + currSz &= ~(0 - (currSz >> 31)); + ret = wc_HmacUpdate(hmac, in, currSz); + offset = currSz; + } + if (ret == 0) { + /* Do the hash operations on a block basis. */ + for (i = 0; i < msgBlocks; i++, offset += blockSz) { + ret = wc_HmacUpdate(hmac, in + offset, blockSz); + if (ret != 0) + break; + } + } + if (ret == 0) + ret = wc_HmacUpdate(hmac, in + offset, msgSz - offset); + if (ret == 0) + ret = wc_HmacFinal(hmac, digest); + if (ret == 0) { + /* Do the dummy hash operations. Do at least one. */ + for (i = 0; i < blocks + 1; i++) { + ret = wc_HmacUpdate(hmac, dummy, blockSz); + if (ret != 0) + break; + } + } + + return ret; +} + +#endif + +int TLS_hmac(WOLFSSL* ssl, byte* digest, const byte* in, word32 sz, int padSz, + int content, int verify) +{ + Hmac hmac; + byte myInner[WOLFSSL_TLS_HMAC_INNER_SZ]; + int ret = 0; + + if (ssl == NULL) + return BAD_FUNC_ARG; + +#ifdef HAVE_FUZZER + /* Fuzz "in" buffer with sz to be used in HMAC algorithm */ + if (ssl->fuzzerCb) { + if (verify && padSz >= 0) { + ssl->fuzzerCb(ssl, in, sz + ssl->specs.hash_size + padSz + 1, + FUZZ_HMAC, ssl->fuzzerCtx); + } + else { + ssl->fuzzerCb(ssl, in, sz, FUZZ_HMAC, ssl->fuzzerCtx); + } + } +#endif + + wolfSSL_SetTlsHmacInner(ssl, myInner, sz, content, verify); + + ret = wc_HmacInit(&hmac, ssl->heap, ssl->devId); + if (ret != 0) + return ret; + + ret = wc_HmacSetKey(&hmac, wolfSSL_GetHmacType(ssl), + wolfSSL_GetMacSecret(ssl, verify), + ssl->specs.hash_size); + if (ret == 0) { + /* Constant time verification required. */ + if (verify && padSz >= 0) { +#if !defined(WOLFSSL_NO_HASH_RAW) && !defined(HAVE_FIPS) && \ + !defined(HAVE_SELFTEST) + #ifdef HAVE_BLAKE2 + if (wolfSSL_GetHmacType(ssl) == WC_HASH_TYPE_BLAKE2B) { + ret = Hmac_UpdateFinal(&hmac, digest, in, sz + + ssl->specs.hash_size + padSz + 1, + myInner); + } + else + #endif + { + ret = Hmac_UpdateFinal_CT(&hmac, digest, in, sz + + ssl->specs.hash_size + padSz + 1, + myInner); + } +#else + ret = Hmac_UpdateFinal(&hmac, digest, in, sz + + ssl->specs.hash_size + padSz + 1, + myInner); +#endif + } + else { + ret = wc_HmacUpdate(&hmac, myInner, sizeof(myInner)); + if (ret == 0) + ret = wc_HmacUpdate(&hmac, in, sz); /* content */ + if (ret == 0) + ret = wc_HmacFinal(&hmac, digest); + } + } + + wc_HmacFree(&hmac); + + return ret; +} +#endif /* WOLFSSL_AEAD_ONLY */ + +#endif /* !WOLFSSL_NO_TLS12 */ + +#ifdef HAVE_TLS_EXTENSIONS + +/** + * The TLSX semaphore is used to calculate the size of the extensions to be sent + * from one peer to another. + */ + +/** Supports up to 64 flags. Increase as needed. */ +#define SEMAPHORE_SIZE 8 + +/** + * Converts the extension type (id) to an index in the semaphore. + * + * Oficial reference for TLS extension types: + * http://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xml + * + * Motivation: + * Previously, we used the extension type itself as the index of that + * extension in the semaphore as the extension types were declared + * sequentially, but maintain a semaphore as big as the number of available + * extensions is no longer an option since the release of renegotiation_info. + * + * How to update: + * Assign extension types that extrapolate the number of available semaphores + * to the first available index going backwards in the semaphore array. + * When adding a new extension type that don't extrapolate the number of + * available semaphores, check for a possible collision with with a + * 'remapped' extension type. + */ +static WC_INLINE word16 TLSX_ToSemaphore(word16 type) +{ + switch (type) { + + case TLSX_RENEGOTIATION_INFO: /* 0xFF01 */ + return 63; + + default: + if (type > 62) { + /* This message SHOULD only happens during the adding of + new TLS extensions in which its IANA number overflows + the current semaphore's range, or if its number already + is assigned to be used by another extension. + Use this check value for the new extension and decrement + the check value by one. */ + WOLFSSL_MSG("### TLSX semaphore colision or overflow detected!"); + } + } + + return type; +} + +/** Checks if a specific light (tls extension) is not set in the semaphore. */ +#define IS_OFF(semaphore, light) \ + (!(((semaphore)[(light) / 8] & (byte) (0x01 << ((light) % 8))))) + +/** Turn on a specific light (tls extension) in the semaphore. */ +/* the semaphore marks the extensions already written to the message */ +#define TURN_ON(semaphore, light) \ + ((semaphore)[(light) / 8] |= (byte) (0x01 << ((light) % 8))) + +/** Turn off a specific light (tls extension) in the semaphore. */ +#define TURN_OFF(semaphore, light) \ + ((semaphore)[(light) / 8] &= (byte) ~(0x01 << ((light) % 8))) + +/** Creates a new extension. */ +static TLSX* TLSX_New(TLSX_Type type, void* data, void* heap) +{ + TLSX* extension = (TLSX*)XMALLOC(sizeof(TLSX), heap, DYNAMIC_TYPE_TLSX); + + (void)heap; + + if (extension) { + extension->type = type; + extension->data = data; + extension->resp = 0; + extension->next = NULL; + } + + return extension; +} + +/** + * Creates a new extension and pushes it to the provided list. + * Checks for duplicate extensions, keeps the newest. + */ +static int TLSX_Push(TLSX** list, TLSX_Type type, void* data, void* heap) +{ + TLSX* extension = TLSX_New(type, data, heap); + + if (extension == NULL) + return MEMORY_E; + + /* pushes the new extension on the list. */ + extension->next = *list; + *list = extension; + + /* remove duplicate extensions, there should be only one of each type. */ + do { + if (extension->next && extension->next->type == type) { + TLSX *next = extension->next; + + extension->next = next->next; + next->next = NULL; + + TLSX_FreeAll(next, heap); + + /* there is no way to occur more than + * two extensions of the same type. + */ + break; + } + } while ((extension = extension->next)); + + return 0; +} + +#ifndef NO_WOLFSSL_CLIENT + +int TLSX_CheckUnsupportedExtension(WOLFSSL* ssl, TLSX_Type type); + +int TLSX_CheckUnsupportedExtension(WOLFSSL* ssl, TLSX_Type type) +{ + TLSX *extension = TLSX_Find(ssl->extensions, type); + + if (!extension) + extension = TLSX_Find(ssl->ctx->extensions, type); + + return extension == NULL; +} + +int TLSX_HandleUnsupportedExtension(WOLFSSL* ssl); + +int TLSX_HandleUnsupportedExtension(WOLFSSL* ssl) +{ + SendAlert(ssl, alert_fatal, unsupported_extension); + return UNSUPPORTED_EXTENSION; +} + +#else + +#define TLSX_CheckUnsupportedExtension(ssl, type) 0 +#define TLSX_HandleUnsupportedExtension(ssl) 0 + +#endif + +/** Mark an extension to be sent back to the client. */ +void TLSX_SetResponse(WOLFSSL* ssl, TLSX_Type type); + +void TLSX_SetResponse(WOLFSSL* ssl, TLSX_Type type) +{ + TLSX *extension = TLSX_Find(ssl->extensions, type); + + if (extension) + extension->resp = 1; +} + +/******************************************************************************/ +/* Application-Layer Protocol Negotiation */ +/******************************************************************************/ + +#ifdef HAVE_ALPN +/** Creates a new ALPN object, providing protocol name to use. */ +static ALPN* TLSX_ALPN_New(char *protocol_name, word16 protocol_nameSz, + void* heap) +{ + ALPN *alpn; + + WOLFSSL_ENTER("TLSX_ALPN_New"); + + if (protocol_name == NULL || + protocol_nameSz > WOLFSSL_MAX_ALPN_PROTO_NAME_LEN) { + WOLFSSL_MSG("Invalid arguments"); + return NULL; + } + + alpn = (ALPN*)XMALLOC(sizeof(ALPN), heap, DYNAMIC_TYPE_TLSX); + if (alpn == NULL) { + WOLFSSL_MSG("Memory failure"); + return NULL; + } + + alpn->next = NULL; + alpn->negotiated = 0; + alpn->options = 0; + + alpn->protocol_name = (char*)XMALLOC(protocol_nameSz + 1, + heap, DYNAMIC_TYPE_TLSX); + if (alpn->protocol_name == NULL) { + WOLFSSL_MSG("Memory failure"); + XFREE(alpn, heap, DYNAMIC_TYPE_TLSX); + return NULL; + } + + XMEMCPY(alpn->protocol_name, protocol_name, protocol_nameSz); + alpn->protocol_name[protocol_nameSz] = 0; + + return alpn; +} + +/** Releases an ALPN object. */ +static void TLSX_ALPN_Free(ALPN *alpn, void* heap) +{ + (void)heap; + + if (alpn == NULL) + return; + + XFREE(alpn->protocol_name, heap, DYNAMIC_TYPE_TLSX); + XFREE(alpn, heap, DYNAMIC_TYPE_TLSX); +} + +/** Releases all ALPN objects in the provided list. */ +static void TLSX_ALPN_FreeAll(ALPN *list, void* heap) +{ + ALPN* alpn; + + while ((alpn = list)) { + list = alpn->next; + TLSX_ALPN_Free(alpn, heap); + } +} + +/** Tells the buffered size of the ALPN objects in a list. */ +static word16 TLSX_ALPN_GetSize(ALPN *list) +{ + ALPN* alpn; + word16 length = OPAQUE16_LEN; /* list length */ + + while ((alpn = list)) { + list = alpn->next; + + length++; /* protocol name length is on one byte */ + length += (word16)XSTRLEN(alpn->protocol_name); + } + + return length; +} + +/** Writes the ALPN objects of a list in a buffer. */ +static word16 TLSX_ALPN_Write(ALPN *list, byte *output) +{ + ALPN* alpn; + word16 length = 0; + word16 offset = OPAQUE16_LEN; /* list length offset */ + + while ((alpn = list)) { + list = alpn->next; + + length = (word16)XSTRLEN(alpn->protocol_name); + + /* protocol name length */ + output[offset++] = (byte)length; + + /* protocol name value */ + XMEMCPY(output + offset, alpn->protocol_name, length); + + offset += length; + } + + /* writing list length */ + c16toa(offset - OPAQUE16_LEN, output); + + return offset; +} + +/** Finds a protocol name in the provided ALPN list */ +static ALPN* TLSX_ALPN_Find(ALPN *list, char *protocol_name, word16 size) +{ + ALPN *alpn; + + if (list == NULL || protocol_name == NULL) + return NULL; + + alpn = list; + while (alpn != NULL && ( + (word16)XSTRLEN(alpn->protocol_name) != size || + XSTRNCMP(alpn->protocol_name, protocol_name, size))) + alpn = alpn->next; + + return alpn; +} + +/** Set the ALPN matching client and server requirements */ +static int TLSX_SetALPN(TLSX** extensions, const void* data, word16 size, + void* heap) +{ + ALPN *alpn; + int ret; + + if (extensions == NULL || data == NULL) + return BAD_FUNC_ARG; + + alpn = TLSX_ALPN_New((char *)data, size, heap); + if (alpn == NULL) { + WOLFSSL_MSG("Memory failure"); + return MEMORY_E; + } + + alpn->negotiated = 1; + + ret = TLSX_Push(extensions, TLSX_APPLICATION_LAYER_PROTOCOL, (void*)alpn, + heap); + if (ret != 0) { + TLSX_ALPN_Free(alpn, heap); + return ret; + } + + return WOLFSSL_SUCCESS; +} + +/** Parses a buffer of ALPN extensions and set the first one matching + * client and server requirements */ +static int TLSX_ALPN_ParseAndSet(WOLFSSL *ssl, byte *input, word16 length, + byte isRequest) +{ + word16 size = 0, offset = 0, idx = 0; + int r = BUFFER_ERROR; + byte match = 0; + TLSX *extension; + ALPN *alpn = NULL, *list; + + if (OPAQUE16_LEN > length) + return BUFFER_ERROR; + + ato16(input, &size); + offset += OPAQUE16_LEN; + + if (size == 0) + return BUFFER_ERROR; + + extension = TLSX_Find(ssl->extensions, TLSX_APPLICATION_LAYER_PROTOCOL); + if (extension == NULL) + extension = TLSX_Find(ssl->ctx->extensions, + TLSX_APPLICATION_LAYER_PROTOCOL); + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + if (ssl->alpnSelect != NULL) { + const byte* out; + unsigned char outLen; + + if (ssl->alpnSelect(ssl, &out, &outLen, input + offset, size, + ssl->alpnSelectArg) == 0) { + WOLFSSL_MSG("ALPN protocol match"); + if (TLSX_UseALPN(&ssl->extensions, (char*)out, outLen, 0, ssl->heap) + == WOLFSSL_SUCCESS) { + if (extension == NULL) { + extension = TLSX_Find(ssl->extensions, + TLSX_APPLICATION_LAYER_PROTOCOL); + } + } + } + } +#endif + + if (extension == NULL || extension->data == NULL) { + return isRequest ? 0 + : TLSX_HandleUnsupportedExtension(ssl); + } + + /* validating alpn list length */ + if (length != OPAQUE16_LEN + size) + return BUFFER_ERROR; + + list = (ALPN*)extension->data; + + /* keep the list sent by client */ + if (isRequest) { + if (ssl->alpn_client_list != NULL) + XFREE(ssl->alpn_client_list, ssl->heap, DYNAMIC_TYPE_ALPN); + + ssl->alpn_client_list = (char *)XMALLOC(size, ssl->heap, + DYNAMIC_TYPE_ALPN); + if (ssl->alpn_client_list == NULL) + return MEMORY_ERROR; + } + + for (size = 0; offset < length; offset += size) { + + size = input[offset++]; + if (offset + size > length || size == 0) + return BUFFER_ERROR; + + if (isRequest) { + XMEMCPY(ssl->alpn_client_list+idx, (char*)input + offset, size); + idx += size; + ssl->alpn_client_list[idx++] = ','; + } + + if (!match) { + alpn = TLSX_ALPN_Find(list, (char*)input + offset, size); + if (alpn != NULL) { + WOLFSSL_MSG("ALPN protocol match"); + match = 1; + + /* skip reading other values if not required */ + if (!isRequest) + break; + } + } + } + + if (isRequest) + ssl->alpn_client_list[idx-1] = 0; + + if (!match) { + WOLFSSL_MSG("No ALPN protocol match"); + + /* do nothing if no protocol match between client and server and option + is set to continue (like OpenSSL) */ + if (list->options & WOLFSSL_ALPN_CONTINUE_ON_MISMATCH) { + WOLFSSL_MSG("Continue on mismatch"); + return 0; + } + + SendAlert(ssl, alert_fatal, no_application_protocol); + return UNKNOWN_ALPN_PROTOCOL_NAME_E; + } + + /* set the matching negotiated protocol */ + r = TLSX_SetALPN(&ssl->extensions, + alpn->protocol_name, + (word16)XSTRLEN(alpn->protocol_name), + ssl->heap); + if (r != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("TLSX_UseALPN failed"); + return BUFFER_ERROR; + } + + /* reply to ALPN extension sent from client */ + if (isRequest) { +#ifndef NO_WOLFSSL_SERVER + TLSX_SetResponse(ssl, TLSX_APPLICATION_LAYER_PROTOCOL); +#endif + } + + return 0; +} + +/** Add a protocol name to the list of accepted usable ones */ +int TLSX_UseALPN(TLSX** extensions, const void* data, word16 size, byte options, + void* heap) +{ + ALPN *alpn; + TLSX *extension; + int ret; + + if (extensions == NULL || data == NULL) + return BAD_FUNC_ARG; + + alpn = TLSX_ALPN_New((char *)data, size, heap); + if (alpn == NULL) { + WOLFSSL_MSG("Memory failure"); + return MEMORY_E; + } + + /* Set Options of ALPN */ + alpn->options = options; + + extension = TLSX_Find(*extensions, TLSX_APPLICATION_LAYER_PROTOCOL); + if (extension == NULL) { + ret = TLSX_Push(extensions, TLSX_APPLICATION_LAYER_PROTOCOL, + (void*)alpn, heap); + if (ret != 0) { + TLSX_ALPN_Free(alpn, heap); + return ret; + } + } + else { + /* push new ALPN object to extension data. */ + alpn->next = (ALPN*)extension->data; + extension->data = (void*)alpn; + } + + return WOLFSSL_SUCCESS; +} + +/** Get the protocol name set by the server */ +int TLSX_ALPN_GetRequest(TLSX* extensions, void** data, word16 *dataSz) +{ + TLSX *extension; + ALPN *alpn; + + if (extensions == NULL || data == NULL || dataSz == NULL) + return BAD_FUNC_ARG; + + extension = TLSX_Find(extensions, TLSX_APPLICATION_LAYER_PROTOCOL); + if (extension == NULL) { + WOLFSSL_MSG("TLS extension not found"); + return WOLFSSL_ALPN_NOT_FOUND; + } + + alpn = (ALPN *)extension->data; + if (alpn == NULL) { + WOLFSSL_MSG("ALPN extension not found"); + *data = NULL; + *dataSz = 0; + return WOLFSSL_FATAL_ERROR; + } + + if (alpn->negotiated != 1) { + + /* consider as an error */ + if (alpn->options & WOLFSSL_ALPN_FAILED_ON_MISMATCH) { + WOLFSSL_MSG("No protocol match with peer -> Failed"); + return WOLFSSL_FATAL_ERROR; + } + + /* continue without negotiated protocol */ + WOLFSSL_MSG("No protocol match with peer -> Continue"); + return WOLFSSL_ALPN_NOT_FOUND; + } + + if (alpn->next != NULL) { + WOLFSSL_MSG("Only one protocol name must be accepted"); + return WOLFSSL_FATAL_ERROR; + } + + *data = alpn->protocol_name; + *dataSz = (word16)XSTRLEN((char*)*data); + + return WOLFSSL_SUCCESS; +} + +#define ALPN_FREE_ALL TLSX_ALPN_FreeAll +#define ALPN_GET_SIZE TLSX_ALPN_GetSize +#define ALPN_WRITE TLSX_ALPN_Write +#define ALPN_PARSE TLSX_ALPN_ParseAndSet + +#else /* HAVE_ALPN */ + +#define ALPN_FREE_ALL(list, heap) +#define ALPN_GET_SIZE(list) 0 +#define ALPN_WRITE(a, b) 0 +#define ALPN_PARSE(a, b, c, d) 0 + +#endif /* HAVE_ALPN */ + +/******************************************************************************/ +/* Server Name Indication */ +/******************************************************************************/ + +#ifdef HAVE_SNI + +/** Creates a new SNI object. */ +static SNI* TLSX_SNI_New(byte type, const void* data, word16 size, void* heap) +{ + SNI* sni = (SNI*)XMALLOC(sizeof(SNI), heap, DYNAMIC_TYPE_TLSX); + + if (sni) { + sni->type = type; + sni->next = NULL; + + #ifndef NO_WOLFSSL_SERVER + sni->options = 0; + sni->status = WOLFSSL_SNI_NO_MATCH; + #endif + + switch (sni->type) { + case WOLFSSL_SNI_HOST_NAME: + sni->data.host_name = (char*)XMALLOC(size + 1, heap, + DYNAMIC_TYPE_TLSX); + if (sni->data.host_name) { + XSTRNCPY(sni->data.host_name, (const char*)data, size); + sni->data.host_name[size] = '\0'; + } else { + XFREE(sni, heap, DYNAMIC_TYPE_TLSX); + sni = NULL; + } + break; + + default: /* invalid type */ + XFREE(sni, heap, DYNAMIC_TYPE_TLSX); + sni = NULL; + } + } + + return sni; +} + +/** Releases a SNI object. */ +static void TLSX_SNI_Free(SNI* sni, void* heap) +{ + if (sni) { + switch (sni->type) { + case WOLFSSL_SNI_HOST_NAME: + XFREE(sni->data.host_name, heap, DYNAMIC_TYPE_TLSX); + break; + } + + XFREE(sni, heap, DYNAMIC_TYPE_TLSX); + } + (void)heap; +} + +/** Releases all SNI objects in the provided list. */ +static void TLSX_SNI_FreeAll(SNI* list, void* heap) +{ + SNI* sni; + + while ((sni = list)) { + list = sni->next; + TLSX_SNI_Free(sni, heap); + } +} + +/** Tells the buffered size of the SNI objects in a list. */ +static word16 TLSX_SNI_GetSize(SNI* list) +{ + SNI* sni; + word16 length = OPAQUE16_LEN; /* list length */ + + while ((sni = list)) { + list = sni->next; + + length += ENUM_LEN + OPAQUE16_LEN; /* sni type + sni length */ + + switch (sni->type) { + case WOLFSSL_SNI_HOST_NAME: + length += (word16)XSTRLEN((char*)sni->data.host_name); + break; + } + } + + return length; +} + +/** Writes the SNI objects of a list in a buffer. */ +static word16 TLSX_SNI_Write(SNI* list, byte* output) +{ + SNI* sni; + word16 length = 0; + word16 offset = OPAQUE16_LEN; /* list length offset */ + + while ((sni = list)) { + list = sni->next; + + output[offset++] = sni->type; /* sni type */ + + switch (sni->type) { + case WOLFSSL_SNI_HOST_NAME: + length = (word16)XSTRLEN((char*)sni->data.host_name); + + c16toa(length, output + offset); /* sni length */ + offset += OPAQUE16_LEN; + + XMEMCPY(output + offset, sni->data.host_name, length); + + offset += length; + break; + } + } + + c16toa(offset - OPAQUE16_LEN, output); /* writing list length */ + + return offset; +} + +/** Finds a SNI object in the provided list. */ +static SNI* TLSX_SNI_Find(SNI *list, byte type) +{ + SNI* sni = list; + + while (sni && sni->type != type) + sni = sni->next; + + return sni; +} + +/** Sets the status of a SNI object. */ +static void TLSX_SNI_SetStatus(TLSX* extensions, byte type, byte status) +{ + TLSX* extension = TLSX_Find(extensions, TLSX_SERVER_NAME); + SNI* sni = TLSX_SNI_Find(extension ? (SNI*)extension->data : NULL, type); + + if (sni) + sni->status = status; +} + +/** Gets the status of a SNI object. */ +byte TLSX_SNI_Status(TLSX* extensions, byte type) +{ + TLSX* extension = TLSX_Find(extensions, TLSX_SERVER_NAME); + SNI* sni = TLSX_SNI_Find(extension ? (SNI*)extension->data : NULL, type); + + if (sni) + return sni->status; + + return 0; +} + +/** Parses a buffer of SNI extensions. */ +static int TLSX_SNI_Parse(WOLFSSL* ssl, byte* input, word16 length, + byte isRequest) +{ +#ifndef NO_WOLFSSL_SERVER + word16 size = 0; + word16 offset = 0; + int cacheOnly = 0; + SNI *sni = NULL; + byte type; + int matchStat; + byte matched; +#endif + + TLSX *extension = TLSX_Find(ssl->extensions, TLSX_SERVER_NAME); + + if (!extension) + extension = TLSX_Find(ssl->ctx->extensions, TLSX_SERVER_NAME); + + if (!isRequest) { + #ifndef NO_WOLFSSL_CLIENT + if (!extension || !extension->data) + return TLSX_HandleUnsupportedExtension(ssl); + + if (length > 0) + return BUFFER_ERROR; /* SNI response MUST be empty. */ + + /* This call enables wolfSSL_SNI_GetRequest() to be called in the + * client side to fetch the used SNI. It will only work if the SNI + * was set at the SSL object level. Right now we only support one + * name type, WOLFSSL_SNI_HOST_NAME, but in the future, the + * inclusion of other name types will turn this method inaccurate, + * as the extension response doesn't contains information of which + * name was accepted. + */ + TLSX_SNI_SetStatus(ssl->extensions, WOLFSSL_SNI_HOST_NAME, + WOLFSSL_SNI_REAL_MATCH); + + return 0; + #endif + } + +#ifndef NO_WOLFSSL_SERVER + if (!extension || !extension->data) { + #if defined(WOLFSSL_ALWAYS_KEEP_SNI) && !defined(NO_WOLFSSL_SERVER) + /* This will keep SNI even though TLSX_UseSNI has not been called. + * Enable it so that the received sni is available to functions + * that use a custom callback when SNI is received. + */ + + cacheOnly = 1; + WOLFSSL_MSG("Forcing SSL object to store SNI parameter"); + #else + /* Skipping, SNI not enabled at server side. */ + return 0; + #endif + } + + if (OPAQUE16_LEN > length) + return BUFFER_ERROR; + + ato16(input, &size); + offset += OPAQUE16_LEN; + + /* validating sni list length */ + if (length != OPAQUE16_LEN + size || size == 0) + return BUFFER_ERROR; + + /* SNI was badly specified and only one type is now recognized and allowed. + * Only one SNI value per type (RFC6066), so, no loop. */ + type = input[offset++]; + if (type != WOLFSSL_SNI_HOST_NAME) + return BUFFER_ERROR; + + if (offset + OPAQUE16_LEN > length) + return BUFFER_ERROR; + ato16(input + offset, &size); + offset += OPAQUE16_LEN; + + if (offset + size != length || size == 0) + return BUFFER_ERROR; + + if (!cacheOnly && !(sni = TLSX_SNI_Find((SNI*)extension->data, type))) + return 0; /* not using this type of SNI. */ + +#ifdef WOLFSSL_TLS13 + /* Don't process the second ClientHello SNI extension if there + * was problems with the first. + */ + if (!cacheOnly && sni->status != 0) + return 0; +#endif + matched = cacheOnly || (XSTRLEN(sni->data.host_name) == size && + XSTRNCMP(sni->data.host_name, (const char*)input + offset, size) == 0); + + if (matched || sni->options & WOLFSSL_SNI_ANSWER_ON_MISMATCH) { + int r = TLSX_UseSNI(&ssl->extensions, type, input + offset, size, + ssl->heap); + if (r != WOLFSSL_SUCCESS) + return r; /* throws error. */ + + if (cacheOnly) { + WOLFSSL_MSG("Forcing storage of SNI, Fake match"); + matchStat = WOLFSSL_SNI_FORCE_KEEP; + } + else if (matched) { + WOLFSSL_MSG("SNI did match!"); + matchStat = WOLFSSL_SNI_REAL_MATCH; + } + else { + WOLFSSL_MSG("fake SNI match from ANSWER_ON_MISMATCH"); + matchStat = WOLFSSL_SNI_FAKE_MATCH; + } + + TLSX_SNI_SetStatus(ssl->extensions, type, (byte)matchStat); + + if(!cacheOnly) + TLSX_SetResponse(ssl, TLSX_SERVER_NAME); + } + else if (!(sni->options & WOLFSSL_SNI_CONTINUE_ON_MISMATCH)) { + SendAlert(ssl, alert_fatal, unrecognized_name); + + return UNKNOWN_SNI_HOST_NAME_E; + } +#else + (void)input; +#endif + + return 0; +} + +static int TLSX_SNI_VerifyParse(WOLFSSL* ssl, byte isRequest) +{ + (void)ssl; + + if (isRequest) { + #ifndef NO_WOLFSSL_SERVER + TLSX* ctx_ext = TLSX_Find(ssl->ctx->extensions, TLSX_SERVER_NAME); + TLSX* ssl_ext = TLSX_Find(ssl->extensions, TLSX_SERVER_NAME); + SNI* ctx_sni = ctx_ext ? (SNI*)ctx_ext->data : NULL; + SNI* ssl_sni = ssl_ext ? (SNI*)ssl_ext->data : NULL; + SNI* sni = NULL; + + for (; ctx_sni; ctx_sni = ctx_sni->next) { + if (ctx_sni->options & WOLFSSL_SNI_ABORT_ON_ABSENCE) { + sni = TLSX_SNI_Find(ssl_sni, ctx_sni->type); + + if (sni) { + if (sni->status != WOLFSSL_SNI_NO_MATCH) + continue; + + /* if ssl level overrides ctx level, it is ok. */ + if ((sni->options & WOLFSSL_SNI_ABORT_ON_ABSENCE) == 0) + continue; + } + + SendAlert(ssl, alert_fatal, handshake_failure); + return SNI_ABSENT_ERROR; + } + } + + for (; ssl_sni; ssl_sni = ssl_sni->next) { + if (ssl_sni->options & WOLFSSL_SNI_ABORT_ON_ABSENCE) { + if (ssl_sni->status != WOLFSSL_SNI_NO_MATCH) + continue; + + SendAlert(ssl, alert_fatal, handshake_failure); + return SNI_ABSENT_ERROR; + } + } + #endif /* NO_WOLFSSL_SERVER */ + } + + return 0; +} + +int TLSX_UseSNI(TLSX** extensions, byte type, const void* data, word16 size, + void* heap) +{ + TLSX* extension; + SNI* sni = NULL; + + if (extensions == NULL || data == NULL) + return BAD_FUNC_ARG; + + if ((sni = TLSX_SNI_New(type, data, size, heap)) == NULL) + return MEMORY_E; + + extension = TLSX_Find(*extensions, TLSX_SERVER_NAME); + if (!extension) { + int ret = TLSX_Push(extensions, TLSX_SERVER_NAME, (void*)sni, heap); + + if (ret != 0) { + TLSX_SNI_Free(sni, heap); + return ret; + } + } + else { + /* push new SNI object to extension data. */ + sni->next = (SNI*)extension->data; + extension->data = (void*)sni; + + /* remove duplicate SNI, there should be only one of each type. */ + do { + if (sni->next && sni->next->type == type) { + SNI* next = sni->next; + + sni->next = next->next; + TLSX_SNI_Free(next, heap); + + /* there is no way to occur more than + * two SNIs of the same type. + */ + break; + } + } while ((sni = sni->next)); + } + + return WOLFSSL_SUCCESS; +} + +#ifndef NO_WOLFSSL_SERVER + +/** Tells the SNI requested by the client. */ +word16 TLSX_SNI_GetRequest(TLSX* extensions, byte type, void** data) +{ + TLSX* extension = TLSX_Find(extensions, TLSX_SERVER_NAME); + SNI* sni = TLSX_SNI_Find(extension ? (SNI*)extension->data : NULL, type); + + if (sni && sni->status != WOLFSSL_SNI_NO_MATCH) { + switch (sni->type) { + case WOLFSSL_SNI_HOST_NAME: + if (data) { + *data = sni->data.host_name; + return (word16)XSTRLEN((char*)*data); + } + } + } + + return 0; +} + +/** Sets the options for a SNI object. */ +void TLSX_SNI_SetOptions(TLSX* extensions, byte type, byte options) +{ + TLSX* extension = TLSX_Find(extensions, TLSX_SERVER_NAME); + SNI* sni = TLSX_SNI_Find(extension ? (SNI*)extension->data : NULL, type); + + if (sni) + sni->options = options; +} + +/** Retrieves a SNI request from a client hello buffer. */ +int TLSX_SNI_GetFromBuffer(const byte* clientHello, word32 helloSz, + byte type, byte* sni, word32* inOutSz) +{ + word32 offset = 0; + word32 len32 = 0; + word16 len16 = 0; + + if (helloSz < RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + CLIENT_HELLO_FIRST) + return INCOMPLETE_DATA; + + /* TLS record header */ + if ((enum ContentType) clientHello[offset++] != handshake) { + + /* checking for SSLv2.0 client hello according to: */ + /* http://tools.ietf.org/html/rfc4346#appendix-E.1 */ + if ((enum HandShakeType) clientHello[++offset] == client_hello) { + offset += ENUM_LEN + VERSION_SZ; /* skip version */ + + ato16(clientHello + offset, &len16); + offset += OPAQUE16_LEN; + + if (len16 % 3) /* cipher_spec_length must be multiple of 3 */ + return BUFFER_ERROR; + + ato16(clientHello + offset, &len16); + /* Returning SNI_UNSUPPORTED do not increment offset here */ + + if (len16 != 0) /* session_id_length must be 0 */ + return BUFFER_ERROR; + + return SNI_UNSUPPORTED; + } + + return BUFFER_ERROR; + } + + if (clientHello[offset++] != SSLv3_MAJOR) + return BUFFER_ERROR; + + if (clientHello[offset++] < TLSv1_MINOR) + return SNI_UNSUPPORTED; + + ato16(clientHello + offset, &len16); + offset += OPAQUE16_LEN; + + if (offset + len16 > helloSz) + return INCOMPLETE_DATA; + + /* Handshake header */ + if ((enum HandShakeType) clientHello[offset] != client_hello) + return BUFFER_ERROR; + + c24to32(clientHello + offset + 1, &len32); + offset += HANDSHAKE_HEADER_SZ; + + if (offset + len32 > helloSz) + return BUFFER_ERROR; + + /* client hello */ + offset += VERSION_SZ + RAN_LEN; /* version, random */ + + if (helloSz < offset + clientHello[offset]) + return BUFFER_ERROR; + + offset += ENUM_LEN + clientHello[offset]; /* skip session id */ + + /* cypher suites */ + if (helloSz < offset + OPAQUE16_LEN) + return BUFFER_ERROR; + + ato16(clientHello + offset, &len16); + offset += OPAQUE16_LEN; + + if (helloSz < offset + len16) + return BUFFER_ERROR; + + offset += len16; /* skip cypher suites */ + + /* compression methods */ + if (helloSz < offset + 1) + return BUFFER_ERROR; + + if (helloSz < offset + clientHello[offset]) + return BUFFER_ERROR; + + offset += ENUM_LEN + clientHello[offset]; /* skip compression methods */ + + /* extensions */ + if (helloSz < offset + OPAQUE16_LEN) + return 0; /* no extensions in client hello. */ + + ato16(clientHello + offset, &len16); + offset += OPAQUE16_LEN; + + if (helloSz < offset + len16) + return BUFFER_ERROR; + + while (len16 >= OPAQUE16_LEN + OPAQUE16_LEN) { + word16 extType; + word16 extLen; + + ato16(clientHello + offset, &extType); + offset += OPAQUE16_LEN; + + ato16(clientHello + offset, &extLen); + offset += OPAQUE16_LEN; + + if (helloSz < offset + extLen) + return BUFFER_ERROR; + + if (extType != TLSX_SERVER_NAME) { + offset += extLen; /* skip extension */ + } else { + word16 listLen; + + ato16(clientHello + offset, &listLen); + offset += OPAQUE16_LEN; + + if (helloSz < offset + listLen) + return BUFFER_ERROR; + + while (listLen > ENUM_LEN + OPAQUE16_LEN) { + byte sniType = clientHello[offset++]; + word16 sniLen; + + ato16(clientHello + offset, &sniLen); + offset += OPAQUE16_LEN; + + if (helloSz < offset + sniLen) + return BUFFER_ERROR; + + if (sniType != type) { + offset += sniLen; + listLen -= min(ENUM_LEN + OPAQUE16_LEN + sniLen, listLen); + continue; + } + + *inOutSz = min(sniLen, *inOutSz); + XMEMCPY(sni, clientHello + offset, *inOutSz); + + return WOLFSSL_SUCCESS; + } + } + + len16 -= min(2 * OPAQUE16_LEN + extLen, len16); + } + + return len16 ? BUFFER_ERROR : 0; +} + +#endif + +#define SNI_FREE_ALL TLSX_SNI_FreeAll +#define SNI_GET_SIZE TLSX_SNI_GetSize +#define SNI_WRITE TLSX_SNI_Write +#define SNI_PARSE TLSX_SNI_Parse +#define SNI_VERIFY_PARSE TLSX_SNI_VerifyParse + +#else + +#define SNI_FREE_ALL(list, heap) +#define SNI_GET_SIZE(list) 0 +#define SNI_WRITE(a, b) 0 +#define SNI_PARSE(a, b, c, d) 0 +#define SNI_VERIFY_PARSE(a, b) 0 + +#endif /* HAVE_SNI */ + +/******************************************************************************/ +/* Trusted CA Key Indication */ +/******************************************************************************/ + +#ifdef HAVE_TRUSTED_CA + +/** Creates a new TCA object. */ +static TCA* TLSX_TCA_New(byte type, const byte* id, word16 idSz, void* heap) +{ + TCA* tca = (TCA*)XMALLOC(sizeof(TCA), heap, DYNAMIC_TYPE_TLSX); + + if (tca) { + XMEMSET(tca, 0, sizeof(TCA)); + tca->type = type; + + switch (type) { + case WOLFSSL_TRUSTED_CA_PRE_AGREED: + break; + + #ifndef NO_SHA + case WOLFSSL_TRUSTED_CA_KEY_SHA1: + case WOLFSSL_TRUSTED_CA_CERT_SHA1: + if (idSz == SHA_DIGEST_SIZE && + (tca->id = + (byte*)XMALLOC(idSz, heap, DYNAMIC_TYPE_TLSX))) { + XMEMCPY(tca->id, id, idSz); + tca->idSz = idSz; + } + else { + XFREE(tca, heap, DYNAMIC_TYPE_TLSX); + tca = NULL; + } + break; + #endif + + case WOLFSSL_TRUSTED_CA_X509_NAME: + if (idSz > 0 && + (tca->id = + (byte*)XMALLOC(idSz, heap, DYNAMIC_TYPE_TLSX))) { + XMEMCPY(tca->id, id, idSz); + tca->idSz = idSz; + } + else { + XFREE(tca, heap, DYNAMIC_TYPE_TLSX); + tca = NULL; + } + break; + + default: /* invalid type */ + XFREE(tca, heap, DYNAMIC_TYPE_TLSX); + tca = NULL; + } + } + + return tca; +} + +/** Releases a TCA object. */ +static void TLSX_TCA_Free(TCA* tca, void* heap) +{ + (void)heap; + + if (tca) { + if (tca->id) + XFREE(tca->id, heap, DYNAMIC_TYPE_TLSX); + XFREE(tca, heap, DYNAMIC_TYPE_TLSX); + } +} + +/** Releases all TCA objects in the provided list. */ +static void TLSX_TCA_FreeAll(TCA* list, void* heap) +{ + TCA* tca; + + while ((tca = list)) { + list = tca->next; + TLSX_TCA_Free(tca, heap); + } +} + +/** Tells the buffered size of the TCA objects in a list. */ +static word16 TLSX_TCA_GetSize(TCA* list) +{ + TCA* tca; + word16 length = OPAQUE16_LEN; /* list length */ + + while ((tca = list)) { + list = tca->next; + + length += ENUM_LEN; /* tca type */ + + switch (tca->type) { + case WOLFSSL_TRUSTED_CA_PRE_AGREED: + break; + case WOLFSSL_TRUSTED_CA_KEY_SHA1: + case WOLFSSL_TRUSTED_CA_CERT_SHA1: + length += tca->idSz; + break; + case WOLFSSL_TRUSTED_CA_X509_NAME: + length += OPAQUE16_LEN + tca->idSz; + break; + } + } + + return length; +} + +/** Writes the TCA objects of a list in a buffer. */ +static word16 TLSX_TCA_Write(TCA* list, byte* output) +{ + TCA* tca; + word16 offset = OPAQUE16_LEN; /* list length offset */ + + while ((tca = list)) { + list = tca->next; + + output[offset++] = tca->type; /* tca type */ + + switch (tca->type) { + case WOLFSSL_TRUSTED_CA_PRE_AGREED: + break; + #ifndef NO_SHA + case WOLFSSL_TRUSTED_CA_KEY_SHA1: + case WOLFSSL_TRUSTED_CA_CERT_SHA1: + if (tca->id != NULL) { + XMEMCPY(output + offset, tca->id, tca->idSz); + offset += tca->idSz; + } + else { + /* ID missing. Set to an empty string. */ + c16toa(0, output + offset); + offset += OPAQUE16_LEN; + } + break; + #endif + case WOLFSSL_TRUSTED_CA_X509_NAME: + if (tca->id != NULL) { + c16toa(tca->idSz, output + offset); /* tca length */ + offset += OPAQUE16_LEN; + XMEMCPY(output + offset, tca->id, tca->idSz); + offset += tca->idSz; + } + else { + /* ID missing. Set to an empty string. */ + c16toa(0, output + offset); + offset += OPAQUE16_LEN; + } + break; + default: + /* ID unknown. Set to an empty string. */ + c16toa(0, output + offset); + offset += OPAQUE16_LEN; + } + } + + c16toa(offset - OPAQUE16_LEN, output); /* writing list length */ + + return offset; +} + +static TCA* TLSX_TCA_Find(TCA *list, byte type, const byte* id, word16 idSz) +{ + TCA* tca = list; + + while (tca && tca->type != type && type != WOLFSSL_TRUSTED_CA_PRE_AGREED && + idSz != tca->idSz && !XMEMCMP(id, tca->id, idSz)) + tca = tca->next; + + return tca; +} + +/** Parses a buffer of TCA extensions. */ +static int TLSX_TCA_Parse(WOLFSSL* ssl, const byte* input, word16 length, + byte isRequest) +{ +#ifndef NO_WOLFSSL_SERVER + word16 size = 0; + word16 offset = 0; +#endif + + TLSX *extension = TLSX_Find(ssl->extensions, TLSX_TRUSTED_CA_KEYS); + + if (!extension) + extension = TLSX_Find(ssl->ctx->extensions, TLSX_TRUSTED_CA_KEYS); + + if (!isRequest) { + #ifndef NO_WOLFSSL_CLIENT + if (!extension || !extension->data) + return TLSX_HandleUnsupportedExtension(ssl); + + if (length > 0) + return BUFFER_ERROR; /* TCA response MUST be empty. */ + + /* Set the flag that we're good for keys */ + TLSX_SetResponse(ssl, TLSX_TRUSTED_CA_KEYS); + + return 0; + #endif + } + +#ifndef NO_WOLFSSL_SERVER + if (!extension || !extension->data) { + /* Skipping, TCA not enabled at server side. */ + return 0; + } + + if (OPAQUE16_LEN > length) + return BUFFER_ERROR; + + ato16(input, &size); + offset += OPAQUE16_LEN; + + /* validating tca list length */ + if (length != OPAQUE16_LEN + size) + return BUFFER_ERROR; + + for (size = 0; offset < length; offset += size) { + TCA *tca = NULL; + byte type; + const byte* id = NULL; + word16 idSz = 0; + + if (offset + ENUM_LEN > length) + return BUFFER_ERROR; + + type = input[offset++]; + + switch (type) { + case WOLFSSL_TRUSTED_CA_PRE_AGREED: + break; + #ifndef NO_SHA + case WOLFSSL_TRUSTED_CA_KEY_SHA1: + case WOLFSSL_TRUSTED_CA_CERT_SHA1: + if (offset + SHA_DIGEST_SIZE > length) + return BUFFER_ERROR; + idSz = SHA_DIGEST_SIZE; + id = input + offset; + offset += idSz; + break; + #endif + case WOLFSSL_TRUSTED_CA_X509_NAME: + if (offset + OPAQUE16_LEN > length) + return BUFFER_ERROR; + ato16(input + offset, &idSz); + offset += OPAQUE16_LEN; + if (offset + idSz > length) + return BUFFER_ERROR; + id = input + offset; + offset += idSz; + break; + default: + return TCA_INVALID_ID_TYPE; + } + + /* Find the type/ID in the TCA list. */ + tca = TLSX_TCA_Find((TCA*)extension->data, type, id, idSz); + if (tca != NULL) { + /* Found it. Set the response flag and break out of the loop. */ + TLSX_SetResponse(ssl, TLSX_TRUSTED_CA_KEYS); + break; + } + } +#else + (void)input; +#endif + + return 0; +} + +/* Checks to see if the server sent a response for the TCA. */ +static int TLSX_TCA_VerifyParse(WOLFSSL* ssl, byte isRequest) +{ + (void)ssl; + + if (!isRequest) { + #ifndef NO_WOLFSSL_CLIENT + TLSX* extension = TLSX_Find(ssl->extensions, TLSX_TRUSTED_CA_KEYS); + + if (extension && !extension->resp) { + SendAlert(ssl, alert_fatal, handshake_failure); + return TCA_ABSENT_ERROR; + } + #endif /* NO_WOLFSSL_CLIENT */ + } + + return 0; +} + +int TLSX_UseTrustedCA(TLSX** extensions, byte type, + const byte* id, word16 idSz, void* heap) +{ + TLSX* extension; + TCA* tca = NULL; + + if (extensions == NULL) + return BAD_FUNC_ARG; + + if ((tca = TLSX_TCA_New(type, id, idSz, heap)) == NULL) + return MEMORY_E; + + extension = TLSX_Find(*extensions, TLSX_TRUSTED_CA_KEYS); + if (!extension) { + int ret = TLSX_Push(extensions, TLSX_TRUSTED_CA_KEYS, (void*)tca, heap); + + if (ret != 0) { + TLSX_TCA_Free(tca, heap); + return ret; + } + } + else { + /* push new TCA object to extension data. */ + tca->next = (TCA*)extension->data; + extension->data = (void*)tca; + } + + return WOLFSSL_SUCCESS; +} + +#define TCA_FREE_ALL TLSX_TCA_FreeAll +#define TCA_GET_SIZE TLSX_TCA_GetSize +#define TCA_WRITE TLSX_TCA_Write +#define TCA_PARSE TLSX_TCA_Parse +#define TCA_VERIFY_PARSE TLSX_TCA_VerifyParse + +#else /* HAVE_TRUSTED_CA */ + +#define TCA_FREE_ALL(list, heap) +#define TCA_GET_SIZE(list) 0 +#define TCA_WRITE(a, b) 0 +#define TCA_PARSE(a, b, c, d) 0 +#define TCA_VERIFY_PARSE(a, b) 0 + +#endif /* HAVE_TRUSTED_CA */ + +/******************************************************************************/ +/* Max Fragment Length Negotiation */ +/******************************************************************************/ + +#ifdef HAVE_MAX_FRAGMENT + +static word16 TLSX_MFL_Write(byte* data, byte* output) +{ + output[0] = data[0]; + + return ENUM_LEN; +} + +static int TLSX_MFL_Parse(WOLFSSL* ssl, byte* input, word16 length, + byte isRequest) +{ + if (length != ENUM_LEN) + return BUFFER_ERROR; + +#ifdef WOLFSSL_OLD_UNSUPPORTED_EXTENSION + (void) isRequest; +#else + if (!isRequest) + if (TLSX_CheckUnsupportedExtension(ssl, TLSX_MAX_FRAGMENT_LENGTH)) + return TLSX_HandleUnsupportedExtension(ssl); +#endif + + switch (*input) { + case WOLFSSL_MFL_2_8 : ssl->max_fragment = 256; break; + case WOLFSSL_MFL_2_9 : ssl->max_fragment = 512; break; + case WOLFSSL_MFL_2_10: ssl->max_fragment = 1024; break; + case WOLFSSL_MFL_2_11: ssl->max_fragment = 2048; break; + case WOLFSSL_MFL_2_12: ssl->max_fragment = 4096; break; + case WOLFSSL_MFL_2_13: ssl->max_fragment = 8192; break; + + default: + SendAlert(ssl, alert_fatal, illegal_parameter); + + return UNKNOWN_MAX_FRAG_LEN_E; + } + +#ifndef NO_WOLFSSL_SERVER + if (isRequest) { + int ret = TLSX_UseMaxFragment(&ssl->extensions, *input, ssl->heap); + + if (ret != WOLFSSL_SUCCESS) + return ret; /* throw error */ + + TLSX_SetResponse(ssl, TLSX_MAX_FRAGMENT_LENGTH); + } +#endif + + return 0; +} + +int TLSX_UseMaxFragment(TLSX** extensions, byte mfl, void* heap) +{ + byte* data = NULL; + int ret = 0; + + if (extensions == NULL || mfl < WOLFSSL_MFL_MIN || mfl > WOLFSSL_MFL_MAX) + return BAD_FUNC_ARG; + + data = (byte*)XMALLOC(ENUM_LEN, heap, DYNAMIC_TYPE_TLSX); + if (data == NULL) + return MEMORY_E; + + data[0] = mfl; + + ret = TLSX_Push(extensions, TLSX_MAX_FRAGMENT_LENGTH, data, heap); + if (ret != 0) { + XFREE(data, heap, DYNAMIC_TYPE_TLSX); + return ret; + } + + return WOLFSSL_SUCCESS; +} + + +#define MFL_FREE_ALL(data, heap) XFREE(data, (heap), DYNAMIC_TYPE_TLSX) +#define MFL_GET_SIZE(data) ENUM_LEN +#define MFL_WRITE TLSX_MFL_Write +#define MFL_PARSE TLSX_MFL_Parse + +#else + +#define MFL_FREE_ALL(a, b) +#define MFL_GET_SIZE(a) 0 +#define MFL_WRITE(a, b) 0 +#define MFL_PARSE(a, b, c, d) 0 + +#endif /* HAVE_MAX_FRAGMENT */ + +/******************************************************************************/ +/* Truncated HMAC */ +/******************************************************************************/ + +#ifdef HAVE_TRUNCATED_HMAC + +static int TLSX_THM_Parse(WOLFSSL* ssl, byte* input, word16 length, + byte isRequest) +{ + if (length != 0 || input == NULL) + return BUFFER_ERROR; + + if (!isRequest) { + #ifndef WOLFSSL_OLD_UNSUPPORTED_EXTENSION + if (TLSX_CheckUnsupportedExtension(ssl, TLSX_TRUNCATED_HMAC)) + return TLSX_HandleUnsupportedExtension(ssl); + #endif + } + else { + #ifndef NO_WOLFSSL_SERVER + int ret = TLSX_UseTruncatedHMAC(&ssl->extensions, ssl->heap); + + if (ret != WOLFSSL_SUCCESS) + return ret; /* throw error */ + + TLSX_SetResponse(ssl, TLSX_TRUNCATED_HMAC); + #endif + } + + ssl->truncated_hmac = 1; + + return 0; +} + +int TLSX_UseTruncatedHMAC(TLSX** extensions, void* heap) +{ + int ret = 0; + + if (extensions == NULL) + return BAD_FUNC_ARG; + + ret = TLSX_Push(extensions, TLSX_TRUNCATED_HMAC, NULL, heap); + if (ret != 0) + return ret; + + return WOLFSSL_SUCCESS; +} + +#define THM_PARSE TLSX_THM_Parse + +#else + +#define THM_PARSE(a, b, c, d) 0 + +#endif /* HAVE_TRUNCATED_HMAC */ + +/******************************************************************************/ +/* Certificate Status Request */ +/******************************************************************************/ + +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST + +static void TLSX_CSR_Free(CertificateStatusRequest* csr, void* heap) +{ + switch (csr->status_type) { + case WOLFSSL_CSR_OCSP: + FreeOcspRequest(&csr->request.ocsp); + break; + } + + XFREE(csr, heap, DYNAMIC_TYPE_TLSX); + (void)heap; +} + +static word16 TLSX_CSR_GetSize(CertificateStatusRequest* csr, byte isRequest) +{ + word16 size = 0; + + /* shut up compiler warnings */ + (void) csr; (void) isRequest; + +#ifndef NO_WOLFSSL_CLIENT + if (isRequest) { + switch (csr->status_type) { + case WOLFSSL_CSR_OCSP: + size += ENUM_LEN + 2 * OPAQUE16_LEN; + + if (csr->request.ocsp.nonceSz) + size += OCSP_NONCE_EXT_SZ; + break; + } + } +#endif +#if defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_SERVER) + if (!isRequest && csr->ssl->options.tls1_3) + return OPAQUE8_LEN + OPAQUE24_LEN + csr->response.length; +#endif + + return size; +} + +static word16 TLSX_CSR_Write(CertificateStatusRequest* csr, byte* output, + byte isRequest) +{ + /* shut up compiler warnings */ + (void) csr; (void) output; (void) isRequest; + +#ifndef NO_WOLFSSL_CLIENT + if (isRequest) { + word16 offset = 0; + word16 length = 0; + + /* type */ + output[offset++] = csr->status_type; + + switch (csr->status_type) { + case WOLFSSL_CSR_OCSP: + /* responder id list */ + c16toa(0, output + offset); + offset += OPAQUE16_LEN; + + /* request extensions */ + if (csr->request.ocsp.nonceSz) + length = (word16)EncodeOcspRequestExtensions( + &csr->request.ocsp, + output + offset + OPAQUE16_LEN, + OCSP_NONCE_EXT_SZ); + + c16toa(length, output + offset); + offset += OPAQUE16_LEN + length; + + break; + } + + return offset; + } +#endif +#if defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_SERVER) + if (!isRequest && csr->ssl->options.tls1_3) { + word16 offset = 0; + output[offset++] = csr->status_type; + c32to24(csr->response.length, output + offset); + offset += OPAQUE24_LEN; + XMEMCPY(output + offset, csr->response.buffer, csr->response.length); + offset += csr->response.length; + return offset; + } +#endif + + return 0; +} + +static int TLSX_CSR_Parse(WOLFSSL* ssl, byte* input, word16 length, + byte isRequest) +{ + int ret; + + /* shut up compiler warnings */ + (void) ssl; (void) input; + + if (!isRequest) { +#ifndef NO_WOLFSSL_CLIENT + TLSX* extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST); + CertificateStatusRequest* csr = extension ? + (CertificateStatusRequest*)extension->data : NULL; + + if (!csr) { + /* look at context level */ + extension = TLSX_Find(ssl->ctx->extensions, TLSX_STATUS_REQUEST); + csr = extension ? (CertificateStatusRequest*)extension->data : NULL; + + if (!csr) /* unexpected extension */ + return TLSX_HandleUnsupportedExtension(ssl); + + /* enable extension at ssl level */ + ret = TLSX_UseCertificateStatusRequest(&ssl->extensions, + csr->status_type, csr->options, ssl, + ssl->heap, ssl->devId); + if (ret != WOLFSSL_SUCCESS) + return ret; + + switch (csr->status_type) { + case WOLFSSL_CSR_OCSP: + /* propagate nonce */ + if (csr->request.ocsp.nonceSz) { + OcspRequest* request = + (OcspRequest*)TLSX_CSR_GetRequest(ssl->extensions); + + if (request) { + XMEMCPY(request->nonce, csr->request.ocsp.nonce, + csr->request.ocsp.nonceSz); + request->nonceSz = csr->request.ocsp.nonceSz; + } + } + break; + } + } + + ssl->status_request = 1; + + #ifdef WOLFSSL_TLS13 + if (ssl->options.tls1_3) { + word32 resp_length; + word32 offset = 0; + + /* Get the new extension potentially created above. */ + extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST); + csr = extension ? (CertificateStatusRequest*)extension->data : NULL; + if (csr == NULL) + return MEMORY_ERROR; + + ret = 0; + if (OPAQUE8_LEN + OPAQUE24_LEN > length) + ret = BUFFER_ERROR; + if (ret == 0 && input[offset++] != WOLFSSL_CSR_OCSP) + ret = BAD_CERTIFICATE_STATUS_ERROR; + if (ret == 0) { + c24to32(input + offset, &resp_length); + offset += OPAQUE24_LEN; + if (offset + resp_length != length) + ret = BUFFER_ERROR; + } + if (ret == 0) { + csr->response.buffer = input + offset; + csr->response.length = resp_length; + } + + return ret; + } + else + #endif + { + /* extension_data MUST be empty. */ + return length ? BUFFER_ERROR : 0; + } +#endif + } + else { +#ifndef NO_WOLFSSL_SERVER + byte status_type; + word16 offset = 0; + word16 size = 0; + + if (length < ENUM_LEN) + return BUFFER_ERROR; + + status_type = input[offset++]; + + switch (status_type) { + case WOLFSSL_CSR_OCSP: { + + /* skip responder_id_list */ + if (length - offset < OPAQUE16_LEN) + return BUFFER_ERROR; + + ato16(input + offset, &size); + offset += OPAQUE16_LEN + size; + + /* skip request_extensions */ + if (length - offset < OPAQUE16_LEN) + return BUFFER_ERROR; + + ato16(input + offset, &size); + offset += OPAQUE16_LEN + size; + + if (offset > length) + return BUFFER_ERROR; + + /* is able to send OCSP response? */ + if (ssl->ctx->cm == NULL || !ssl->ctx->cm->ocspStaplingEnabled) + return 0; + } + break; + + /* unknown status type */ + default: + return 0; + } + + /* if using status_request and already sending it, skip this one */ + #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + if (ssl->status_request_v2) + return 0; + #endif + + /* accept the first good status_type and return */ + ret = TLSX_UseCertificateStatusRequest(&ssl->extensions, status_type, + 0, ssl, ssl->heap, ssl->devId); + if (ret != WOLFSSL_SUCCESS) + return ret; /* throw error */ + + #if defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_SERVER) + if (ssl->options.tls1_3) { + OcspRequest* request; + TLSX* extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST); + CertificateStatusRequest* csr = extension ? + (CertificateStatusRequest*)extension->data : NULL; + if (csr == NULL) + return MEMORY_ERROR; + + request = &csr->request.ocsp; + ret = CreateOcspResponse(ssl, &request, &csr->response); + if (ret != 0) + return ret; + if (csr->response.buffer) + TLSX_SetResponse(ssl, TLSX_STATUS_REQUEST); + } + else + #endif + TLSX_SetResponse(ssl, TLSX_STATUS_REQUEST); + ssl->status_request = status_type; +#endif + } + + return 0; +} + +int TLSX_CSR_InitRequest(TLSX* extensions, DecodedCert* cert, void* heap) +{ + TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST); + CertificateStatusRequest* csr = extension ? + (CertificateStatusRequest*)extension->data : NULL; + int ret = 0; + + if (csr) { + switch (csr->status_type) { + case WOLFSSL_CSR_OCSP: { + byte nonce[MAX_OCSP_NONCE_SZ]; + int nonceSz = csr->request.ocsp.nonceSz; + + /* preserve nonce */ + XMEMCPY(nonce, csr->request.ocsp.nonce, nonceSz); + + if ((ret = InitOcspRequest(&csr->request.ocsp, cert, 0, heap)) + != 0) + return ret; + + /* restore nonce */ + XMEMCPY(csr->request.ocsp.nonce, nonce, nonceSz); + csr->request.ocsp.nonceSz = nonceSz; + } + break; + } + } + + return ret; +} + +void* TLSX_CSR_GetRequest(TLSX* extensions) +{ + TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST); + CertificateStatusRequest* csr = extension ? + (CertificateStatusRequest*)extension->data : NULL; + + if (csr) { + switch (csr->status_type) { + case WOLFSSL_CSR_OCSP: + return &csr->request.ocsp; + break; + } + } + + return NULL; +} + +int TLSX_CSR_ForceRequest(WOLFSSL* ssl) +{ + TLSX* extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST); + CertificateStatusRequest* csr = extension ? + (CertificateStatusRequest*)extension->data : NULL; + + if (csr) { + switch (csr->status_type) { + case WOLFSSL_CSR_OCSP: + if (ssl->ctx->cm->ocspEnabled) { + csr->request.ocsp.ssl = ssl; + return CheckOcspRequest(ssl->ctx->cm->ocsp, + &csr->request.ocsp, NULL); + } + else + return OCSP_LOOKUP_FAIL; + } + } + + return 0; +} + +int TLSX_UseCertificateStatusRequest(TLSX** extensions, byte status_type, + byte options, WOLFSSL* ssl, void* heap, + int devId) +{ + CertificateStatusRequest* csr = NULL; + int ret = 0; + + if (!extensions || status_type != WOLFSSL_CSR_OCSP) + return BAD_FUNC_ARG; + + csr = (CertificateStatusRequest*) + XMALLOC(sizeof(CertificateStatusRequest), heap, DYNAMIC_TYPE_TLSX); + if (!csr) + return MEMORY_E; + + ForceZero(csr, sizeof(CertificateStatusRequest)); + + csr->status_type = status_type; + csr->options = options; + csr->ssl = ssl; + + switch (csr->status_type) { + case WOLFSSL_CSR_OCSP: + if (options & WOLFSSL_CSR_OCSP_USE_NONCE) { + WC_RNG rng; + + #ifndef HAVE_FIPS + ret = wc_InitRng_ex(&rng, heap, devId); + #else + ret = wc_InitRng(&rng); + (void)devId; + #endif + if (ret == 0) { + if (wc_RNG_GenerateBlock(&rng, csr->request.ocsp.nonce, + MAX_OCSP_NONCE_SZ) == 0) + csr->request.ocsp.nonceSz = MAX_OCSP_NONCE_SZ; + + wc_FreeRng(&rng); + } + } + break; + } + + if ((ret = TLSX_Push(extensions, TLSX_STATUS_REQUEST, csr, heap)) != 0) { + XFREE(csr, heap, DYNAMIC_TYPE_TLSX); + return ret; + } + + return WOLFSSL_SUCCESS; +} + +#define CSR_FREE_ALL TLSX_CSR_Free +#define CSR_GET_SIZE TLSX_CSR_GetSize +#define CSR_WRITE TLSX_CSR_Write +#define CSR_PARSE TLSX_CSR_Parse + +#else + +#define CSR_FREE_ALL(data, heap) +#define CSR_GET_SIZE(a, b) 0 +#define CSR_WRITE(a, b, c) 0 +#define CSR_PARSE(a, b, c, d) 0 + +#endif /* HAVE_CERTIFICATE_STATUS_REQUEST */ + +/******************************************************************************/ +/* Certificate Status Request v2 */ +/******************************************************************************/ + +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + +static void TLSX_CSR2_FreeAll(CertificateStatusRequestItemV2* csr2, void* heap) +{ + CertificateStatusRequestItemV2* next; + + for (; csr2; csr2 = next) { + next = csr2->next; + + switch (csr2->status_type) { + case WOLFSSL_CSR2_OCSP: + case WOLFSSL_CSR2_OCSP_MULTI: + while(csr2->requests--) + FreeOcspRequest(&csr2->request.ocsp[csr2->requests]); + break; + } + + XFREE(csr2, heap, DYNAMIC_TYPE_TLSX); + } + (void)heap; +} + +static word16 TLSX_CSR2_GetSize(CertificateStatusRequestItemV2* csr2, + byte isRequest) +{ + word16 size = 0; + + /* shut up compiler warnings */ + (void) csr2; (void) isRequest; + +#ifndef NO_WOLFSSL_CLIENT + if (isRequest) { + CertificateStatusRequestItemV2* next; + + for (size = OPAQUE16_LEN; csr2; csr2 = next) { + next = csr2->next; + + switch (csr2->status_type) { + case WOLFSSL_CSR2_OCSP: + case WOLFSSL_CSR2_OCSP_MULTI: + size += ENUM_LEN + 3 * OPAQUE16_LEN; + + if (csr2->request.ocsp[0].nonceSz) + size += OCSP_NONCE_EXT_SZ; + break; + } + } + } +#endif + + return size; +} + +static word16 TLSX_CSR2_Write(CertificateStatusRequestItemV2* csr2, + byte* output, byte isRequest) +{ + /* shut up compiler warnings */ + (void) csr2; (void) output; (void) isRequest; + +#ifndef NO_WOLFSSL_CLIENT + if (isRequest) { + word16 offset; + word16 length; + + for (offset = OPAQUE16_LEN; csr2 != NULL; csr2 = csr2->next) { + /* status_type */ + output[offset++] = csr2->status_type; + + /* request */ + switch (csr2->status_type) { + case WOLFSSL_CSR2_OCSP: + case WOLFSSL_CSR2_OCSP_MULTI: + /* request_length */ + length = 2 * OPAQUE16_LEN; + + if (csr2->request.ocsp[0].nonceSz) + length += OCSP_NONCE_EXT_SZ; + + c16toa(length, output + offset); + offset += OPAQUE16_LEN; + + /* responder id list */ + c16toa(0, output + offset); + offset += OPAQUE16_LEN; + + /* request extensions */ + length = 0; + + if (csr2->request.ocsp[0].nonceSz) + length = (word16)EncodeOcspRequestExtensions( + &csr2->request.ocsp[0], + output + offset + OPAQUE16_LEN, + OCSP_NONCE_EXT_SZ); + + c16toa(length, output + offset); + offset += OPAQUE16_LEN + length; + break; + } + } + + /* list size */ + c16toa(offset - OPAQUE16_LEN, output); + + return offset; + } +#endif + + return 0; +} + +static int TLSX_CSR2_Parse(WOLFSSL* ssl, byte* input, word16 length, + byte isRequest) +{ + int ret; + + /* shut up compiler warnings */ + (void) ssl; (void) input; + + if (!isRequest) { +#ifndef NO_WOLFSSL_CLIENT + TLSX* extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST_V2); + CertificateStatusRequestItemV2* csr2 = extension ? + (CertificateStatusRequestItemV2*)extension->data : NULL; + + if (!csr2) { + /* look at context level */ + extension = TLSX_Find(ssl->ctx->extensions, TLSX_STATUS_REQUEST_V2); + csr2 = extension ? + (CertificateStatusRequestItemV2*)extension->data : NULL; + + if (!csr2) /* unexpected extension */ + return TLSX_HandleUnsupportedExtension(ssl); + + /* enable extension at ssl level */ + for (; csr2; csr2 = csr2->next) { + ret = TLSX_UseCertificateStatusRequestV2(&ssl->extensions, + csr2->status_type, csr2->options, ssl->heap, + ssl->devId); + if (ret != WOLFSSL_SUCCESS) + return ret; + + switch (csr2->status_type) { + case WOLFSSL_CSR2_OCSP: + /* followed by */ + case WOLFSSL_CSR2_OCSP_MULTI: + /* propagate nonce */ + if (csr2->request.ocsp[0].nonceSz) { + OcspRequest* request = + (OcspRequest*)TLSX_CSR2_GetRequest(ssl->extensions, + csr2->status_type, 0); + + if (request) { + XMEMCPY(request->nonce, + csr2->request.ocsp[0].nonce, + csr2->request.ocsp[0].nonceSz); + + request->nonceSz = + csr2->request.ocsp[0].nonceSz; + } + } + break; + } + } + } + + ssl->status_request_v2 = 1; + + return length ? BUFFER_ERROR : 0; /* extension_data MUST be empty. */ +#endif + } + else { +#ifndef NO_WOLFSSL_SERVER + byte status_type; + word16 request_length; + word16 offset = 0; + word16 size = 0; + + /* list size */ + if (offset + OPAQUE16_LEN >= length) { + return BUFFER_E; + } + + ato16(input + offset, &request_length); + offset += OPAQUE16_LEN; + + if (length - OPAQUE16_LEN != request_length) + return BUFFER_ERROR; + + while (length > offset) { + if (length - offset < ENUM_LEN + OPAQUE16_LEN) + return BUFFER_ERROR; + + status_type = input[offset++]; + + ato16(input + offset, &request_length); + offset += OPAQUE16_LEN; + + if (length - offset < request_length) + return BUFFER_ERROR; + + switch (status_type) { + case WOLFSSL_CSR2_OCSP: + case WOLFSSL_CSR2_OCSP_MULTI: + /* skip responder_id_list */ + if (length - offset < OPAQUE16_LEN) + return BUFFER_ERROR; + + ato16(input + offset, &size); + offset += OPAQUE16_LEN + size; + + /* skip request_extensions */ + if (length - offset < OPAQUE16_LEN) + return BUFFER_ERROR; + + ato16(input + offset, &size); + offset += OPAQUE16_LEN + size; + + if (offset > length) + return BUFFER_ERROR; + + /* is able to send OCSP response? */ + if (ssl->ctx->cm == NULL + || !ssl->ctx->cm->ocspStaplingEnabled) + continue; + break; + + default: + /* unknown status type, skipping! */ + offset += request_length; + continue; + } + + /* if using status_request and already sending it, skip this one */ + #ifdef HAVE_CERTIFICATE_STATUS_REQUEST + if (ssl->status_request) + return 0; + #endif + + /* accept the first good status_type and return */ + ret = TLSX_UseCertificateStatusRequestV2(&ssl->extensions, + status_type, 0, ssl->heap, ssl->devId); + if (ret != WOLFSSL_SUCCESS) + return ret; /* throw error */ + + TLSX_SetResponse(ssl, TLSX_STATUS_REQUEST_V2); + ssl->status_request_v2 = status_type; + + return 0; + } +#endif + } + + return 0; +} + +int TLSX_CSR2_InitRequests(TLSX* extensions, DecodedCert* cert, byte isPeer, + void* heap) +{ + TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST_V2); + CertificateStatusRequestItemV2* csr2 = extension ? + (CertificateStatusRequestItemV2*)extension->data : NULL; + int ret = 0; + + for (; csr2; csr2 = csr2->next) { + switch (csr2->status_type) { + case WOLFSSL_CSR2_OCSP: + if (!isPeer || csr2->requests != 0) + break; + + FALL_THROUGH; /* followed by */ + + case WOLFSSL_CSR2_OCSP_MULTI: { + if (csr2->requests < 1 + MAX_CHAIN_DEPTH) { + byte nonce[MAX_OCSP_NONCE_SZ]; + int nonceSz = csr2->request.ocsp[0].nonceSz; + + /* preserve nonce, replicating nonce of ocsp[0] */ + XMEMCPY(nonce, csr2->request.ocsp[0].nonce, nonceSz); + + if ((ret = InitOcspRequest( + &csr2->request.ocsp[csr2->requests], cert, + 0, heap)) != 0) + return ret; + + /* restore nonce */ + XMEMCPY(csr2->request.ocsp[csr2->requests].nonce, + nonce, nonceSz); + csr2->request.ocsp[csr2->requests].nonceSz = nonceSz; + csr2->requests++; + } + } + break; + } + } + + (void)cert; + return ret; +} + +void* TLSX_CSR2_GetRequest(TLSX* extensions, byte status_type, byte idx) +{ + TLSX* extension = TLSX_Find(extensions, TLSX_STATUS_REQUEST_V2); + CertificateStatusRequestItemV2* csr2 = extension ? + (CertificateStatusRequestItemV2*)extension->data : NULL; + + for (; csr2; csr2 = csr2->next) { + if (csr2->status_type == status_type) { + switch (csr2->status_type) { + case WOLFSSL_CSR2_OCSP: + /* followed by */ + + case WOLFSSL_CSR2_OCSP_MULTI: + /* requests are initialized in the reverse order */ + return idx < csr2->requests + ? &csr2->request.ocsp[csr2->requests - idx - 1] + : NULL; + break; + } + } + } + + return NULL; +} + +int TLSX_CSR2_ForceRequest(WOLFSSL* ssl) +{ + TLSX* extension = TLSX_Find(ssl->extensions, TLSX_STATUS_REQUEST_V2); + CertificateStatusRequestItemV2* csr2 = extension ? + (CertificateStatusRequestItemV2*)extension->data : NULL; + + /* forces only the first one */ + if (csr2) { + switch (csr2->status_type) { + case WOLFSSL_CSR2_OCSP: + /* followed by */ + + case WOLFSSL_CSR2_OCSP_MULTI: + if (ssl->ctx->cm->ocspEnabled) { + csr2->request.ocsp[0].ssl = ssl; + return CheckOcspRequest(ssl->ctx->cm->ocsp, + &csr2->request.ocsp[0], NULL); + } + else + return OCSP_LOOKUP_FAIL; + } + } + + return 0; +} + +int TLSX_UseCertificateStatusRequestV2(TLSX** extensions, byte status_type, + byte options, void* heap, int devId) +{ + TLSX* extension = NULL; + CertificateStatusRequestItemV2* csr2 = NULL; + int ret = 0; + + if (!extensions) + return BAD_FUNC_ARG; + + if (status_type != WOLFSSL_CSR2_OCSP + && status_type != WOLFSSL_CSR2_OCSP_MULTI) + return BAD_FUNC_ARG; + + csr2 = (CertificateStatusRequestItemV2*) + XMALLOC(sizeof(CertificateStatusRequestItemV2), heap, DYNAMIC_TYPE_TLSX); + if (!csr2) + return MEMORY_E; + + ForceZero(csr2, sizeof(CertificateStatusRequestItemV2)); + + csr2->status_type = status_type; + csr2->options = options; + csr2->next = NULL; + + switch (csr2->status_type) { + case WOLFSSL_CSR2_OCSP: + case WOLFSSL_CSR2_OCSP_MULTI: + if (options & WOLFSSL_CSR2_OCSP_USE_NONCE) { + WC_RNG rng; + + #ifndef HAVE_FIPS + ret = wc_InitRng_ex(&rng, heap, devId); + #else + ret = wc_InitRng(&rng); + (void)devId; + #endif + if (ret == 0) { + if (wc_RNG_GenerateBlock(&rng, csr2->request.ocsp[0].nonce, + MAX_OCSP_NONCE_SZ) == 0) + csr2->request.ocsp[0].nonceSz = MAX_OCSP_NONCE_SZ; + + wc_FreeRng(&rng); + } + } + break; + } + + /* append new item */ + if ((extension = TLSX_Find(*extensions, TLSX_STATUS_REQUEST_V2))) { + CertificateStatusRequestItemV2* last = + (CertificateStatusRequestItemV2*)extension->data; + + for (; last->next; last = last->next); + + last->next = csr2; + } + else if ((ret = TLSX_Push(extensions, TLSX_STATUS_REQUEST_V2, csr2,heap))) { + XFREE(csr2, heap, DYNAMIC_TYPE_TLSX); + return ret; + } + + return WOLFSSL_SUCCESS; +} + +#define CSR2_FREE_ALL TLSX_CSR2_FreeAll +#define CSR2_GET_SIZE TLSX_CSR2_GetSize +#define CSR2_WRITE TLSX_CSR2_Write +#define CSR2_PARSE TLSX_CSR2_Parse + +#else + +#define CSR2_FREE_ALL(data, heap) +#define CSR2_GET_SIZE(a, b) 0 +#define CSR2_WRITE(a, b, c) 0 +#define CSR2_PARSE(a, b, c, d) 0 + +#endif /* HAVE_CERTIFICATE_STATUS_REQUEST_V2 */ + +/******************************************************************************/ +/* Supported Elliptic Curves */ +/******************************************************************************/ + +#ifdef HAVE_SUPPORTED_CURVES + +#if !defined(HAVE_ECC) && !defined(HAVE_CURVE25519) && !defined(HAVE_FFDHE) +#error Elliptic Curves Extension requires Elliptic Curve Cryptography. \ + Use --enable-ecc in the configure script or define HAVE_ECC. \ + Alternatively use FFDHE for DH ciperhsuites. +#endif + +static int TLSX_SupportedCurve_New(SupportedCurve** curve, word16 name, + void* heap) +{ + if (curve == NULL) + return BAD_FUNC_ARG; + + (void)heap; + + *curve = (SupportedCurve*)XMALLOC(sizeof(SupportedCurve), heap, + DYNAMIC_TYPE_TLSX); + if (*curve == NULL) + return MEMORY_E; + + (*curve)->name = name; + (*curve)->next = NULL; + + return 0; +} + +static int TLSX_PointFormat_New(PointFormat** point, byte format, void* heap) +{ + if (point == NULL) + return BAD_FUNC_ARG; + + (void)heap; + + *point = (PointFormat*)XMALLOC(sizeof(PointFormat), heap, + DYNAMIC_TYPE_TLSX); + if (*point == NULL) + return MEMORY_E; + + (*point)->format = format; + (*point)->next = NULL; + + return 0; +} + +static void TLSX_SupportedCurve_FreeAll(SupportedCurve* list, void* heap) +{ + SupportedCurve* curve; + + while ((curve = list)) { + list = curve->next; + XFREE(curve, heap, DYNAMIC_TYPE_TLSX); + } + (void)heap; +} + +static void TLSX_PointFormat_FreeAll(PointFormat* list, void* heap) +{ + PointFormat* point; + + while ((point = list)) { + list = point->next; + XFREE(point, heap, DYNAMIC_TYPE_TLSX); + } + (void)heap; +} + +static int TLSX_SupportedCurve_Append(SupportedCurve* list, word16 name, + void* heap) +{ + int ret = BAD_FUNC_ARG; + + while (list) { + if (list->name == name) { + ret = 0; /* curve alreay in use */ + break; + } + + if (list->next == NULL) { + ret = TLSX_SupportedCurve_New(&list->next, name, heap); + break; + } + + list = list->next; + } + + return ret; +} + +static int TLSX_PointFormat_Append(PointFormat* list, byte format, void* heap) +{ + int ret = BAD_FUNC_ARG; + + while (list) { + if (list->format == format) { + ret = 0; /* format already in use */ + break; + } + + if (list->next == NULL) { + ret = TLSX_PointFormat_New(&list->next, format, heap); + break; + } + + list = list->next; + } + + return ret; +} + +#if defined(WOLFSSL_TLS13) || !defined(NO_WOLFSSL_CLIENT) + +static void TLSX_SupportedCurve_ValidateRequest(WOLFSSL* ssl, byte* semaphore) +{ + word16 i; + + for (i = 0; i < ssl->suites->suiteSz; i+= 2) { + if (ssl->suites->suites[i] == TLS13_BYTE) + return; + if (ssl->suites->suites[i] == ECC_BYTE || + ssl->suites->suites[i] == CHACHA_BYTE) { + #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) + return; + #endif + } + else { + #ifdef HAVE_FFDHE + return; + #endif + } + } + + /* turns semaphore on to avoid sending this extension. */ + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_GROUPS)); +} + +static void TLSX_PointFormat_ValidateRequest(WOLFSSL* ssl, byte* semaphore) +{ + word16 i; + + for (i = 0; i < ssl->suites->suiteSz; i+= 2) { + if (ssl->suites->suites[i] == TLS13_BYTE) + return; + if (ssl->suites->suites[i] == ECC_BYTE || + ssl->suites->suites[i] == CHACHA_BYTE) { + #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) + return; + #endif + } + else { + #ifdef HAVE_FFDHE + return; + #endif + } + } + + /* turns semaphore on to avoid sending this extension. */ + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_EC_POINT_FORMATS)); +} + +#endif + +#ifndef NO_WOLFSSL_SERVER + +static void TLSX_PointFormat_ValidateResponse(WOLFSSL* ssl, byte* semaphore) +{ +#if defined(HAVE_FFDHE) || defined(HAVE_ECC) || defined(HAVE_CURVE25519) + (void)semaphore; +#endif + + if (ssl->options.cipherSuite0 == TLS13_BYTE) + return; + if (ssl->options.cipherSuite0 == ECC_BYTE || + ssl->options.cipherSuite0 == CHACHA_BYTE) { +#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) + return; +#endif + } + else { +#ifdef HAVE_FFDHE + return; +#endif + } + +#if !defined(HAVE_FFDHE) || (!defined(HAVE_ECC) && !defined(HAVE_CURVE25519)) + /* turns semaphore on to avoid sending this extension. */ + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_EC_POINT_FORMATS)); +#endif +} + +#endif +#ifndef NO_WOLFSSL_CLIENT + +static word16 TLSX_SupportedCurve_GetSize(SupportedCurve* list) +{ + SupportedCurve* curve; + word16 length = OPAQUE16_LEN; /* list length */ + + while ((curve = list)) { + list = curve->next; + length += OPAQUE16_LEN; /* curve length */ + } + + return length; +} + +#endif + +static word16 TLSX_PointFormat_GetSize(PointFormat* list) +{ + PointFormat* point; + word16 length = ENUM_LEN; /* list length */ + + while ((point = list)) { + list = point->next; + length += ENUM_LEN; /* format length */ + } + + return length; +} + +#ifndef NO_WOLFSSL_CLIENT + +static word16 TLSX_SupportedCurve_Write(SupportedCurve* list, byte* output) +{ + word16 offset = OPAQUE16_LEN; + + while (list) { + c16toa(list->name, output + offset); + offset += OPAQUE16_LEN; + list = list->next; + } + + c16toa(offset - OPAQUE16_LEN, output); /* writing list length */ + + return offset; +} + +#endif + +static word16 TLSX_PointFormat_Write(PointFormat* list, byte* output) +{ + word16 offset = ENUM_LEN; + + while (list) { + output[offset++] = list->format; + list = list->next; + } + + output[0] = (byte)(offset - ENUM_LEN); + + return offset; +} + +#if !defined(NO_WOLFSSL_SERVER) || (defined(WOLFSSL_TLS13) && \ + !defined(WOLFSSL_NO_SERVER_GROUPS_EXT)) + +static int TLSX_SupportedCurve_Parse(WOLFSSL* ssl, byte* input, word16 length, + byte isRequest) +{ + word16 offset; + word16 name; + int ret; + + if(!isRequest && !IsAtLeastTLSv1_3(ssl->version)) { +#ifdef WOLFSSL_ALLOW_SERVER_SC_EXT + return 0; +#else + return BUFFER_ERROR; /* servers doesn't send this extension. */ +#endif + } + + if (OPAQUE16_LEN > length || length % OPAQUE16_LEN) + return BUFFER_ERROR; + + ato16(input, &offset); + + /* validating curve list length */ + if (length != OPAQUE16_LEN + offset) + return BUFFER_ERROR; + + offset = OPAQUE16_LEN; + if (offset == length) + return 0; + +#if defined(WOLFSSL_TLS13) && !defined(WOLFSSL_NO_SERVER_GROUPS_EXT) + if (!isRequest) { + TLSX* extension; + SupportedCurve* curve; + + extension = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS); + if (extension != NULL) { + /* Replace client list with server list of supported groups. */ + curve = (SupportedCurve*)extension->data; + extension->data = NULL; + TLSX_SupportedCurve_FreeAll(curve, ssl->heap); + + ato16(input + offset, &name); + offset += OPAQUE16_LEN; + + ret = TLSX_SupportedCurve_New(&curve, name, ssl->heap); + if (ret != 0) + return ret; /* throw error */ + extension->data = (void*)curve; + } + } +#endif + + for (; offset < length; offset += OPAQUE16_LEN) { + ato16(input + offset, &name); + + ret = TLSX_UseSupportedCurve(&ssl->extensions, name, ssl->heap); + if (ret != WOLFSSL_SUCCESS) + return ret; /* throw error */ + } + + return 0; +} + +#endif + +#if !defined(NO_WOLFSSL_SERVER) + +#if defined(WOLFSSL_TLS13) && !defined(WOLFSSL_NO_SERVER_GROUPS_EXT) + +/* Checks the priority of the groups on the server and set the supported groups + * response if there is a group not advertised by the client that is preferred. + * + * ssl SSL/TLS object. + * returns 0 on success, otherwise an error. + */ +int TLSX_SupportedCurve_CheckPriority(WOLFSSL* ssl) +{ + int ret; + TLSX* extension; + TLSX* priority = NULL; + TLSX* ext = NULL; + word16 name; + SupportedCurve* curve; + + extension = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS); + /* May be doing PSK with no key exchange. */ + if (extension == NULL) + return 0; + + if ((ret = TLSX_PopulateSupportedGroups(ssl, &priority)) != WOLFSSL_SUCCESS) + return ret; + + ext = TLSX_Find(priority, TLSX_SUPPORTED_GROUPS); + curve = (SupportedCurve*)ext->data; + name = curve->name; + + curve = (SupportedCurve*)extension->data; + while (curve != NULL) { + if (curve->name == name) + break; + curve = curve->next; + } + + if (curve == NULL) { + /* Couldn't find the preferred group in client list. */ + extension->resp = 1; + + /* Send server list back and free client list. */ + curve = (SupportedCurve*)extension->data; + extension->data = ext->data; + ext->data = curve; + } + + TLSX_FreeAll(priority, ssl->heap); + + return 0; +} + +#endif + +#if defined(HAVE_FFDHE) && !defined(WOLFSSL_NO_TLS12) +/* Set the highest priority common FFDHE group on the server as compared to + * client extensions. + * + * ssl SSL/TLS object. + * returns 0 on success, otherwise an error. + */ +int TLSX_SupportedFFDHE_Set(WOLFSSL* ssl) +{ + int ret = 0; + TLSX* extension; + TLSX* priority = NULL; + TLSX* ext = NULL; + SupportedCurve* serverGroup; + SupportedCurve* clientGroup; + SupportedCurve* group; + const DhParams* params; + int found = 0; + + extension = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS); + /* May be doing PSK with no key exchange. */ + if (extension == NULL) + return 0; + clientGroup = (SupportedCurve*)extension->data; + for (group = clientGroup; group != NULL; group = group->next) { + if (group->name >= MIN_FFHDE_GROUP && group->name <= MAX_FFHDE_GROUP) { + found = 1; + break; + } + } + if (!found) + return 0; + + if (ssl->buffers.serverDH_P.buffer && ssl->buffers.weOwnDH) { + XFREE(ssl->buffers.serverDH_P.buffer, ssl->heap, + DYNAMIC_TYPE_PUBLIC_KEY); + } + if (ssl->buffers.serverDH_G.buffer && ssl->buffers.weOwnDH) { + XFREE(ssl->buffers.serverDH_G.buffer, ssl->heap, + DYNAMIC_TYPE_PUBLIC_KEY); + } + ssl->buffers.serverDH_P.buffer = NULL; + ssl->buffers.serverDH_G.buffer = NULL; + ssl->buffers.weOwnDH = 0; + ssl->options.haveDH = 0; + + + if ((ret = TLSX_PopulateSupportedGroups(ssl, &priority)) != WOLFSSL_SUCCESS) + return ret; + ret = 0; + + ext = TLSX_Find(priority, TLSX_SUPPORTED_GROUPS); + serverGroup = (SupportedCurve*)ext->data; + + for (; serverGroup != NULL; serverGroup = serverGroup->next) { + if ((serverGroup->name & NAMED_DH_MASK) != NAMED_DH_MASK) + continue; + + for (group = clientGroup; group != NULL; group = group->next) { + if (serverGroup->name != group->name) + continue; + + switch (serverGroup->name) { + #ifdef HAVE_FFDHE_2048 + case WOLFSSL_FFDHE_2048: + params = wc_Dh_ffdhe2048_Get(); + break; + #endif + #ifdef HAVE_FFDHE_3072 + case WOLFSSL_FFDHE_3072: + params = wc_Dh_ffdhe3072_Get(); + break; + #endif + #ifdef HAVE_FFDHE_4096 + case WOLFSSL_FFDHE_4096: + params = wc_Dh_ffdhe4096_Get(); + break; + #endif + #ifdef HAVE_FFDHE_6144 + case WOLFSSL_FFDHE_6144: + params = wc_Dh_ffdhe6144_Get(); + break; + #endif + #ifdef HAVE_FFDHE_8192 + case WOLFSSL_FFDHE_8192: + params = wc_Dh_ffdhe8192_Get(); + break; + #endif + default: + return BAD_FUNC_ARG; + } + if (params->p_len >= ssl->options.minDhKeySz && + params->p_len <= ssl->options.maxDhKeySz) { + break; + } + } + + if (group != NULL && serverGroup->name == group->name) + break; + } + + if (serverGroup) { + ssl->buffers.serverDH_P.buffer = (unsigned char *)params->p; + ssl->buffers.serverDH_P.length = params->p_len; + ssl->buffers.serverDH_G.buffer = (unsigned char *)params->g; + ssl->buffers.serverDH_G.length = params->g_len; + ssl->namedGroup = serverGroup->name; + #if !defined(WOLFSSL_OLD_PRIME_CHECK) && \ + !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) + ssl->options.dhDoKeyTest = 0; + #endif + ssl->options.haveDH = 1; + } + + TLSX_FreeAll(priority, ssl->heap); + + return ret; +} +#endif /* HAVE_FFDHE && !WOLFSSL_NO_TLS12 */ + +#endif /* !NO_WOLFSSL_SERVER */ + +#if defined(WOLFSSL_TLS13) && !defined(WOLFSSL_NO_SERVER_GROUPS_EXT) +/* Return the preferred group. + * + * ssl SSL/TLS object. + * checkSupported Whether to check for the first supported group. + * returns BAD_FUNC_ARG if no group found, otherwise the group. + */ +int TLSX_SupportedCurve_Preferred(WOLFSSL* ssl, int checkSupported) +{ + TLSX* extension; + SupportedCurve* curve; + + extension = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS); + if (extension == NULL) + return BAD_FUNC_ARG; + + curve = (SupportedCurve*)extension->data; + while (curve != NULL) { + if (!checkSupported || TLSX_KeyShare_IsSupported(curve->name)) + return curve->name; + curve = curve->next; + } + + return BAD_FUNC_ARG; +} + +#endif + +#ifndef NO_WOLFSSL_SERVER + +static int TLSX_PointFormat_Parse(WOLFSSL* ssl, byte* input, word16 length, + byte isRequest) +{ + int ret; + + /* validating formats list length */ + if (ENUM_LEN > length || length != (word16)ENUM_LEN + input[0]) + return BUFFER_ERROR; + + if (isRequest) { + /* adding uncompressed point format to response */ + ret = TLSX_UsePointFormat(&ssl->extensions, WOLFSSL_EC_PF_UNCOMPRESSED, + ssl->heap); + if (ret != WOLFSSL_SUCCESS) + return ret; /* throw error */ + + TLSX_SetResponse(ssl, TLSX_EC_POINT_FORMATS); + } + + return 0; +} + +#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) +int TLSX_ValidateSupportedCurves(WOLFSSL* ssl, byte first, byte second) { + TLSX* extension = NULL; + SupportedCurve* curve = NULL; + word32 oid = 0; + word32 pkOid = 0; + word32 defOid = 0; + word32 defSz = 80; /* Maximum known curve size is 66. */ + word32 nextOid = 0; + word32 nextSz = 80; /* Maximum known curve size is 66. */ + word32 currOid = ssl->ecdhCurveOID; + int ephmSuite = 0; + word16 octets = 0; /* according to 'ecc_set_type ecc_sets[];' */ + int sig = 0; /* validate signature */ + int key = 0; /* validate key */ + + (void)oid; + + if (first == ECC_BYTE || first == CHACHA_BYTE) + extension = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS); + if (!extension) + return 1; /* no suite restriction */ + + for (curve = (SupportedCurve*)extension->data; + curve && !(sig && key); + curve = curve->next) { + + #ifdef OPENSSL_EXTRA + if (ssl->ctx->disabledCurves & (1 << curve->name)) + continue; + #endif + + /* find supported curve */ + switch (curve->name) { +#ifdef HAVE_ECC + #if defined(HAVE_ECC160) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP160R1: + pkOid = oid = ECC_SECP160R1_OID; + octets = 20; + break; + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_SECPR2 + case WOLFSSL_ECC_SECP160R2: + pkOid = oid = ECC_SECP160R2_OID; + octets = 20; + break; + #endif /* HAVE_ECC_SECPR2 */ + #ifdef HAVE_ECC_KOBLITZ + case WOLFSSL_ECC_SECP160K1: + pkOid = oid = ECC_SECP160K1_OID; + octets = 20; + break; + #endif /* HAVE_ECC_KOBLITZ */ + #endif + #if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP192R1: + pkOid = oid = ECC_SECP192R1_OID; + octets = 24; + break; + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_KOBLITZ + case WOLFSSL_ECC_SECP192K1: + pkOid = oid = ECC_SECP192K1_OID; + octets = 24; + break; + #endif /* HAVE_ECC_KOBLITZ */ + #endif + #if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP224R1: + pkOid = oid = ECC_SECP224R1_OID; + octets = 28; + break; + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_KOBLITZ + case WOLFSSL_ECC_SECP224K1: + pkOid = oid = ECC_SECP224K1_OID; + octets = 28; + break; + #endif /* HAVE_ECC_KOBLITZ */ + #endif + #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP256R1: + pkOid = oid = ECC_SECP256R1_OID; + octets = 32; + break; + #endif /* !NO_ECC_SECP */ + #endif /* !NO_ECC256 || HAVE_ALL_CURVES */ +#endif + #ifdef HAVE_CURVE25519 + case WOLFSSL_ECC_X25519: + oid = ECC_X25519_OID; + #ifdef HAVE_ED25519 + pkOid = ECC_ED25519_OID; + #else + pkOid = ECC_X25519_OID; + #endif + octets = 32; + break; + #endif /* HAVE_CURVE25519 */ +#ifdef HAVE_ECC + #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) + #ifdef HAVE_ECC_KOBLITZ + case WOLFSSL_ECC_SECP256K1: + pkOid = oid = ECC_SECP256K1_OID; + octets = 32; + break; + #endif /* HAVE_ECC_KOBLITZ */ + #ifdef HAVE_ECC_BRAINPOOL + case WOLFSSL_ECC_BRAINPOOLP256R1: + pkOid = oid = ECC_BRAINPOOLP256R1_OID; + octets = 32; + break; + #endif /* HAVE_ECC_BRAINPOOL */ + #endif + #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP384R1: + pkOid = oid = ECC_SECP384R1_OID; + octets = 48; + break; + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_BRAINPOOL + case WOLFSSL_ECC_BRAINPOOLP384R1: + pkOid = oid = ECC_BRAINPOOLP384R1_OID; + octets = 48; + break; + #endif /* HAVE_ECC_BRAINPOOL */ + #endif + #if defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES) + #ifdef HAVE_ECC_BRAINPOOL + case WOLFSSL_ECC_BRAINPOOLP512R1: + pkOid = oid = ECC_BRAINPOOLP512R1_OID; + octets = 64; + break; + #endif /* HAVE_ECC_BRAINPOOL */ + #endif + #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP521R1: + pkOid = oid = ECC_SECP521R1_OID; + octets = 66; + break; + #endif /* !NO_ECC_SECP */ + #endif +#endif + default: continue; /* unsupported curve */ + } + + #ifdef HAVE_ECC + /* Set default Oid */ + if (defOid == 0 && ssl->eccTempKeySz <= octets && defSz > octets) { + defOid = oid; + defSz = octets; + } + + /* The eccTempKeySz is the preferred ephemeral key size */ + if (currOid == 0 && ssl->eccTempKeySz == octets) + currOid = oid; + if ((nextOid == 0 || nextSz > octets) && ssl->eccTempKeySz <= octets) { + nextOid = oid; + nextSz = octets; + } + #else + if (defOid == 0 && defSz > octets) { + defOid = oid; + defSz = octets; + } + + if (currOid == 0) + currOid = oid; + if (nextOid == 0 || nextSz > octets) { + nextOid = oid; + nextSz = octets; + } + #endif + + if (first == ECC_BYTE) { + switch (second) { + /* ECDHE_ECDSA */ + case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: + case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: + case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: + case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: + case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: + case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: + case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: + case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: + case TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8: + case TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8: + sig |= ssl->pkCurveOID == pkOid; + key |= ssl->ecdhCurveOID == oid; + ephmSuite = 1; + break; + +#ifdef WOLFSSL_STATIC_DH + /* ECDH_ECDSA */ + case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: + case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: + case TLS_ECDH_ECDSA_WITH_RC4_128_SHA: + case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA: + case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256: + case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384: + case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256: + case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384: + if (oid == ECC_X25519_OID && defOid == oid) { + defOid = 0; + defSz = 80; + } + sig |= ssl->pkCurveOID == pkOid; + key |= ssl->pkCurveOID == oid; + break; +#endif /* WOLFSSL_STATIC_DH */ +#ifndef NO_RSA + /* ECDHE_RSA */ + case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: + case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: + case TLS_ECDHE_RSA_WITH_RC4_128_SHA: + case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: + case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: + case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: + case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: + case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: + sig = 1; + key |= ssl->ecdhCurveOID == oid; + ephmSuite = 1; + break; + +#ifdef WOLFSSL_STATIC_DH + /* ECDH_RSA */ + case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: + case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: + case TLS_ECDH_RSA_WITH_RC4_128_SHA: + case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA: + case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256: + case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384: + case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256: + case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384: + if (oid == ECC_X25519_OID && defOid == oid) { + defOid = 0; + defSz = 80; + } + sig = 1; + key |= ssl->pkCurveOID == pkOid; + break; +#endif /* WOLFSSL_STATIC_DH */ +#endif + default: + if (oid == ECC_X25519_OID && defOid == oid) { + defOid = 0; + defSz = 80; + } + if (oid != ECC_X25519_OID) + sig = 1; + key = 1; + break; + } + } + + /* ChaCha20-Poly1305 ECC cipher suites */ + if (first == CHACHA_BYTE) { + switch (second) { + /* ECDHE_ECDSA */ + case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 : + case TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256 : + sig |= ssl->pkCurveOID == pkOid; + key |= ssl->ecdhCurveOID == oid; + ephmSuite = 1; + break; +#ifndef NO_RSA + /* ECDHE_RSA */ + case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 : + case TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 : + sig = 1; + key |= ssl->ecdhCurveOID == oid; + ephmSuite = 1; + break; +#endif + default: + sig = 1; + key = 1; + break; + } + } + } + + /* Choose the default if it is at the required strength. */ +#ifdef HAVE_ECC + if (ssl->ecdhCurveOID == 0 && defSz == ssl->eccTempKeySz) +#else + if (ssl->ecdhCurveOID == 0) +#endif + { + key = 1; + ssl->ecdhCurveOID = defOid; + } + /* Choose any curve at the required strength. */ + if (ssl->ecdhCurveOID == 0) { + key = 1; + ssl->ecdhCurveOID = currOid; + } + /* Choose the default if it is at the next highest strength. */ + if (ssl->ecdhCurveOID == 0 && defSz == nextSz) + ssl->ecdhCurveOID = defOid; + /* Choose any curve at the next highest strength. */ + if (ssl->ecdhCurveOID == 0) + ssl->ecdhCurveOID = nextOid; + /* No curve and ephemeral ECC suite requires a matching curve. */ + if (ssl->ecdhCurveOID == 0 && ephmSuite) + key = 0; + + return sig && key; +} +#endif + +#endif /* NO_WOLFSSL_SERVER */ + +int TLSX_UseSupportedCurve(TLSX** extensions, word16 name, void* heap) +{ + TLSX* extension = NULL; + SupportedCurve* curve = NULL; + int ret; + + if (extensions == NULL) + return BAD_FUNC_ARG; + + extension = TLSX_Find(*extensions, TLSX_SUPPORTED_GROUPS); + + if (!extension) { + ret = TLSX_SupportedCurve_New(&curve, name, heap); + if (ret != 0) + return ret; + + ret = TLSX_Push(extensions, TLSX_SUPPORTED_GROUPS, curve, heap); + if (ret != 0) { + XFREE(curve, heap, DYNAMIC_TYPE_TLSX); + return ret; + } + } + else { + ret = TLSX_SupportedCurve_Append((SupportedCurve*)extension->data, name, + heap); + if (ret != 0) + return ret; + } + + return WOLFSSL_SUCCESS; +} + +int TLSX_UsePointFormat(TLSX** extensions, byte format, void* heap) +{ + TLSX* extension = NULL; + PointFormat* point = NULL; + int ret = 0; + + if (extensions == NULL) + return BAD_FUNC_ARG; + + extension = TLSX_Find(*extensions, TLSX_EC_POINT_FORMATS); + + if (!extension) { + ret = TLSX_PointFormat_New(&point, format, heap); + if (ret != 0) + return ret; + + ret = TLSX_Push(extensions, TLSX_EC_POINT_FORMATS, point, heap); + if (ret != 0) { + XFREE(point, heap, DYNAMIC_TYPE_TLSX); + return ret; + } + } + else { + ret = TLSX_PointFormat_Append((PointFormat*)extension->data, format, + heap); + if (ret != 0) + return ret; + } + + return WOLFSSL_SUCCESS; +} + +#define EC_FREE_ALL TLSX_SupportedCurve_FreeAll +#define EC_VALIDATE_REQUEST TLSX_SupportedCurve_ValidateRequest + +#ifndef NO_WOLFSSL_CLIENT +#define EC_GET_SIZE TLSX_SupportedCurve_GetSize +#define EC_WRITE TLSX_SupportedCurve_Write +#else +#define EC_GET_SIZE(list) 0 +#define EC_WRITE(a, b) 0 +#endif + +#if !defined(NO_WOLFSSL_SERVER) || (defined(WOLFSSL_TLS13) && \ + !defined(WOLFSSL_NO_SERVER_GROUPS_EXT)) +#define EC_PARSE TLSX_SupportedCurve_Parse +#else +#define EC_PARSE(a, b, c, d) 0 +#endif + +#define PF_FREE_ALL TLSX_PointFormat_FreeAll +#define PF_VALIDATE_REQUEST TLSX_PointFormat_ValidateRequest +#define PF_VALIDATE_RESPONSE TLSX_PointFormat_ValidateResponse + +#define PF_GET_SIZE TLSX_PointFormat_GetSize +#define PF_WRITE TLSX_PointFormat_Write + +#ifndef NO_WOLFSSL_SERVER +#define PF_PARSE TLSX_PointFormat_Parse +#else +#define PF_PARSE(a, b, c, d) 0 +#endif + +#else + +#define EC_FREE_ALL(list, heap) +#define EC_GET_SIZE(list) 0 +#define EC_WRITE(a, b) 0 +#define EC_PARSE(a, b, c, d) 0 +#define EC_VALIDATE_REQUEST(a, b) + +#define PF_FREE_ALL(list, heap) +#define PF_GET_SIZE(list) 0 +#define PF_WRITE(a, b) 0 +#define PF_PARSE(a, b, c, d) 0 +#define PF_VALIDATE_REQUEST(a, b) +#define PF_VALIDATE_RESPONSE(a, b) + +#endif /* HAVE_SUPPORTED_CURVES */ + +/******************************************************************************/ +/* Renegotiation Indication */ +/******************************************************************************/ + +#if defined(HAVE_SECURE_RENEGOTIATION) \ + || defined(HAVE_SERVER_RENEGOTIATION_INFO) + +static byte TLSX_SecureRenegotiation_GetSize(SecureRenegotiation* data, + int isRequest) +{ + byte length = OPAQUE8_LEN; /* empty info length */ + + /* data will be NULL for HAVE_SERVER_RENEGOTIATION_INFO only */ + if (data && data->enabled && data->verifySet) { + /* client sends client_verify_data only */ + length += TLS_FINISHED_SZ; + + /* server also sends server_verify_data */ + if (!isRequest) + length += TLS_FINISHED_SZ; + } + + return length; +} + +static word16 TLSX_SecureRenegotiation_Write(SecureRenegotiation* data, + byte* output, int isRequest) +{ + word16 offset = OPAQUE8_LEN; /* RenegotiationInfo length */ + if (data && data->enabled && data->verifySet) { + /* client sends client_verify_data only */ + XMEMCPY(output + offset, data->client_verify_data, TLS_FINISHED_SZ); + offset += TLS_FINISHED_SZ; + + /* server also sends server_verify_data */ + if (!isRequest) { + XMEMCPY(output + offset, data->server_verify_data, TLS_FINISHED_SZ); + offset += TLS_FINISHED_SZ; + } + } + + output[0] = (byte)(offset - 1); /* info length - self */ + + return offset; +} + +static int TLSX_SecureRenegotiation_Parse(WOLFSSL* ssl, byte* input, + word16 length, byte isRequest) +{ + int ret = SECURE_RENEGOTIATION_E; + + if (length >= OPAQUE8_LEN) { + if (isRequest) { + #ifndef NO_WOLFSSL_SERVER + if (ssl->secure_renegotiation == NULL) { + ret = wolfSSL_UseSecureRenegotiation(ssl); + if (ret == WOLFSSL_SUCCESS) + ret = 0; + } + if (ret != 0 && ret != SECURE_RENEGOTIATION_E) { + } + else if (!ssl->secure_renegotiation->enabled) { + if (*input == 0) { + input++; /* get past size */ + + ssl->secure_renegotiation->enabled = 1; + TLSX_SetResponse(ssl, TLSX_RENEGOTIATION_INFO); + ret = 0; + } + else { + /* already in error state */ + WOLFSSL_MSG("SCR client verify data present"); + } + } + else if (*input == TLS_FINISHED_SZ) { + input++; /* get past size */ + + /* validate client verify data */ + if (XMEMCMP(input, + ssl->secure_renegotiation->client_verify_data, + TLS_FINISHED_SZ) == 0) { + WOLFSSL_MSG("SCR client verify data match"); + TLSX_SetResponse(ssl, TLSX_RENEGOTIATION_INFO); + ret = 0; /* verified */ + } else { + /* already in error state */ + WOLFSSL_MSG("SCR client verify data Failure"); + } + } + #endif + } + else { + #ifndef NO_WOLFSSL_CLIENT + if (!ssl->secure_renegotiation->enabled) { + if (*input == 0) { + ssl->secure_renegotiation->enabled = 1; + ret = 0; + } + } + else if (*input == 2 * TLS_FINISHED_SZ && + length == 2 * TLS_FINISHED_SZ + OPAQUE8_LEN) { + input++; /* get past size */ + + /* validate client and server verify data */ + if (XMEMCMP(input, + ssl->secure_renegotiation->client_verify_data, + TLS_FINISHED_SZ) == 0 && + XMEMCMP(input + TLS_FINISHED_SZ, + ssl->secure_renegotiation->server_verify_data, + TLS_FINISHED_SZ) == 0) { + WOLFSSL_MSG("SCR client and server verify data match"); + ret = 0; /* verified */ + } else { + /* already in error state */ + WOLFSSL_MSG("SCR client and server verify data Failure"); + } + } + #endif + } + } + + if (ret != 0) { + SendAlert(ssl, alert_fatal, handshake_failure); + } + + return ret; +} + +int TLSX_UseSecureRenegotiation(TLSX** extensions, void* heap) +{ + int ret = 0; + SecureRenegotiation* data = NULL; + + data = (SecureRenegotiation*)XMALLOC(sizeof(SecureRenegotiation), heap, + DYNAMIC_TYPE_TLSX); + if (data == NULL) + return MEMORY_E; + + XMEMSET(data, 0, sizeof(SecureRenegotiation)); + + ret = TLSX_Push(extensions, TLSX_RENEGOTIATION_INFO, data, heap); + if (ret != 0) { + XFREE(data, heap, DYNAMIC_TYPE_TLSX); + return ret; + } + + return WOLFSSL_SUCCESS; +} + +#ifdef HAVE_SERVER_RENEGOTIATION_INFO + +int TLSX_AddEmptyRenegotiationInfo(TLSX** extensions, void* heap) +{ + int ret; + + /* send empty renegotiation_info extension */ + TLSX* ext = TLSX_Find(*extensions, TLSX_RENEGOTIATION_INFO); + if (ext == NULL) { + ret = TLSX_UseSecureRenegotiation(extensions, heap); + if (ret != WOLFSSL_SUCCESS) + return ret; + + ext = TLSX_Find(*extensions, TLSX_RENEGOTIATION_INFO); + } + if (ext) + ext->resp = 1; + + return WOLFSSL_SUCCESS; +} + +#endif /* HAVE_SERVER_RENEGOTIATION_INFO */ + + +#define SCR_FREE_ALL(data, heap) XFREE(data, (heap), DYNAMIC_TYPE_TLSX) +#define SCR_GET_SIZE TLSX_SecureRenegotiation_GetSize +#define SCR_WRITE TLSX_SecureRenegotiation_Write +#define SCR_PARSE TLSX_SecureRenegotiation_Parse + +#else + +#define SCR_FREE_ALL(a, heap) +#define SCR_GET_SIZE(a, b) 0 +#define SCR_WRITE(a, b, c) 0 +#define SCR_PARSE(a, b, c, d) 0 + +#endif /* HAVE_SECURE_RENEGOTIATION */ + +/******************************************************************************/ +/* Session Tickets */ +/******************************************************************************/ + +#ifdef HAVE_SESSION_TICKET + +#if defined(WOLFSSL_TLS13) || !defined(NO_WOLFSSL_CLIENT) +static void TLSX_SessionTicket_ValidateRequest(WOLFSSL* ssl) +{ + TLSX* extension = TLSX_Find(ssl->extensions, TLSX_SESSION_TICKET); + SessionTicket* ticket = extension ? + (SessionTicket*)extension->data : NULL; + + if (ticket) { + /* TODO validate ticket timeout here! */ + if (ticket->lifetime == 0xfffffff) { + /* send empty ticket on timeout */ + TLSX_UseSessionTicket(&ssl->extensions, NULL, ssl->heap); + } + } +} +#endif /* WLFSSL_TLS13 || !NO_WOLFSSL_CLIENT */ + + +static word16 TLSX_SessionTicket_GetSize(SessionTicket* ticket, int isRequest) +{ + (void)isRequest; + return ticket ? ticket->size : 0; +} + +static word16 TLSX_SessionTicket_Write(SessionTicket* ticket, byte* output, + int isRequest) +{ + word16 offset = 0; /* empty ticket */ + + if (isRequest && ticket) { + XMEMCPY(output + offset, ticket->data, ticket->size); + offset += ticket->size; + } + + return offset; +} + + +static int TLSX_SessionTicket_Parse(WOLFSSL* ssl, byte* input, word16 length, + byte isRequest) +{ + int ret = 0; + + (void) input; /* avoid unused parameter if NO_WOLFSSL_SERVER defined */ + + if (!isRequest) { + if (TLSX_CheckUnsupportedExtension(ssl, TLSX_SESSION_TICKET)) + return TLSX_HandleUnsupportedExtension(ssl); + + if (length != 0) + return BUFFER_ERROR; + +#ifndef NO_WOLFSSL_CLIENT + ssl->expect_session_ticket = 1; +#endif + } +#ifndef NO_WOLFSSL_SERVER + else { + /* server side */ + if (ssl->ctx->ticketEncCb == NULL) { + WOLFSSL_MSG("Client sent session ticket, server has no callback"); + return 0; + } + + if (length == 0) { + /* blank ticket */ + ret = TLSX_UseSessionTicket(&ssl->extensions, NULL, ssl->heap); + if (ret == WOLFSSL_SUCCESS) { + ret = 0; + TLSX_SetResponse(ssl, TLSX_SESSION_TICKET); /* send blank ticket */ + ssl->options.createTicket = 1; /* will send ticket msg */ + ssl->options.useTicket = 1; + ssl->options.resuming = 0; /* no standard resumption */ + ssl->arrays->sessionIDSz = 0; /* no echo on blank ticket */ + } + } else { + /* got actual ticket from client */ + ret = DoClientTicket(ssl, input, length); + if (ret == WOLFSSL_TICKET_RET_OK) { /* use ticket to resume */ + WOLFSSL_MSG("Using exisitng client ticket"); + ssl->options.useTicket = 1; + ssl->options.resuming = 1; + } else if (ret == WOLFSSL_TICKET_RET_CREATE) { + WOLFSSL_MSG("Using existing client ticket, creating new one"); + ret = TLSX_UseSessionTicket(&ssl->extensions, NULL, ssl->heap); + if (ret == WOLFSSL_SUCCESS) { + ret = 0; + TLSX_SetResponse(ssl, TLSX_SESSION_TICKET); + /* send blank ticket */ + ssl->options.createTicket = 1; /* will send ticket msg */ + ssl->options.useTicket = 1; + ssl->options.resuming = 1; + } + } else if (ret == WOLFSSL_TICKET_RET_REJECT) { + WOLFSSL_MSG("Process client ticket rejected, not using"); + ssl->options.rejectTicket = 1; + ret = 0; /* not fatal */ + } else if (ret == WOLFSSL_TICKET_RET_FATAL || ret < 0) { + WOLFSSL_MSG("Process client ticket fatal error, not using"); + } + } + } +#endif /* NO_WOLFSSL_SERVER */ + + return ret; +} + +WOLFSSL_LOCAL SessionTicket* TLSX_SessionTicket_Create(word32 lifetime, + byte* data, word16 size, void* heap) +{ + SessionTicket* ticket = (SessionTicket*)XMALLOC(sizeof(SessionTicket), + heap, DYNAMIC_TYPE_TLSX); + if (ticket) { + ticket->data = (byte*)XMALLOC(size, heap, DYNAMIC_TYPE_TLSX); + if (ticket->data == NULL) { + XFREE(ticket, heap, DYNAMIC_TYPE_TLSX); + return NULL; + } + + XMEMCPY(ticket->data, data, size); + ticket->size = size; + ticket->lifetime = lifetime; + } + + return ticket; +} +WOLFSSL_LOCAL void TLSX_SessionTicket_Free(SessionTicket* ticket, void* heap) +{ + if (ticket) { + XFREE(ticket->data, heap, DYNAMIC_TYPE_TLSX); + XFREE(ticket, heap, DYNAMIC_TYPE_TLSX); + } + + (void)heap; +} + +int TLSX_UseSessionTicket(TLSX** extensions, SessionTicket* ticket, void* heap) +{ + int ret = 0; + + if (extensions == NULL) + return BAD_FUNC_ARG; + + /* If the ticket is NULL, the client will request a new ticket from the + server. Otherwise, the client will use it in the next client hello. */ + if ((ret = TLSX_Push(extensions, TLSX_SESSION_TICKET, (void*)ticket, heap)) + != 0) + return ret; + + return WOLFSSL_SUCCESS; +} + +#define WOLF_STK_VALIDATE_REQUEST TLSX_SessionTicket_ValidateRequest +#define WOLF_STK_GET_SIZE TLSX_SessionTicket_GetSize +#define WOLF_STK_WRITE TLSX_SessionTicket_Write +#define WOLF_STK_PARSE TLSX_SessionTicket_Parse +#define WOLF_STK_FREE(stk, heap) TLSX_SessionTicket_Free((SessionTicket*)stk,(heap)) + +#else + +#define WOLF_STK_FREE(a, b) +#define WOLF_STK_VALIDATE_REQUEST(a) +#define WOLF_STK_GET_SIZE(a, b) 0 +#define WOLF_STK_WRITE(a, b, c) 0 +#define WOLF_STK_PARSE(a, b, c, d) 0 + +#endif /* HAVE_SESSION_TICKET */ + +/******************************************************************************/ +/* Quantum-Safe-Hybrid */ +/******************************************************************************/ + +#ifdef HAVE_QSH +#if defined(HAVE_NTRU) +static WC_RNG* gRng; +static wolfSSL_Mutex* gRngMutex; +#endif + +static void TLSX_QSH_FreeAll(QSHScheme* list, void* heap) +{ + QSHScheme* current; + + while ((current = list)) { + list = current->next; + XFREE(current, heap, DYNAMIC_TYPE_TLSX); + } + + (void)heap; +} + +static int TLSX_QSH_Append(QSHScheme** list, word16 name, byte* pub, + word16 pubLen) +{ + QSHScheme* temp; + + if (list == NULL) + return BAD_FUNC_ARG; + + if ((temp = (QSHScheme*)XMALLOC(sizeof(QSHScheme), NULL, + DYNAMIC_TYPE_TLSX)) == NULL) + return MEMORY_E; + + temp->name = name; + temp->PK = pub; + temp->PKLen = pubLen; + temp->next = *list; + + *list = temp; + + return 0; +} + + +/* request for server's public key : 02 indicates 0-2 requested */ +static byte TLSX_QSH_SerPKReq(byte* output, byte isRequest) +{ + if (isRequest) { + /* only request one public key from the server */ + output[0] = 0x01; + + return OPAQUE8_LEN; + } + else { + return 0; + } +} + +#ifndef NO_WOLFSSL_CLIENT + +/* check for TLS_QSH suite */ +static void TLSX_QSH_ValidateRequest(WOLFSSL* ssl, byte* semaphore) +{ + int i; + + for (i = 0; i < ssl->suites->suiteSz; i+= 2) + if (ssl->suites->suites[i] == QSH_BYTE) + return; + + /* No QSH suite found */ + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_QUANTUM_SAFE_HYBRID)); +} + + +/* return the size of the QSH hello extension + list the list of QSHScheme structs containing id and key + isRequest if 1 then is being sent to the server + */ +word16 TLSX_QSH_GetSize(QSHScheme* list, byte isRequest) +{ + QSHScheme* temp = list; + word16 length = 0; + + /* account for size of scheme list and public key list */ + if (isRequest) + length = OPAQUE16_LEN; + length += OPAQUE24_LEN; + + /* for each non null element in list add size */ + while ((temp)) { + /* add public key info Scheme | Key Length | Key */ + length += OPAQUE16_LEN; + length += OPAQUE16_LEN; + length += temp->PKLen; + + /* if client add name size for scheme list + advance to next QSHScheme struct in list */ + if (isRequest) + length += OPAQUE16_LEN; + temp = temp->next; + } + + /* add length for request server public keys */ + if (isRequest) + length += OPAQUE8_LEN; + + return length; +} + + +/* write out a list of QSHScheme IDs */ +static word16 TLSX_QSH_Write(QSHScheme* list, byte* output) +{ + QSHScheme* current = list; + word16 length = 0; + + length += OPAQUE16_LEN; + + while (current) { + c16toa(current->name, output + length); + length += OPAQUE16_LEN; + current = (QSHScheme*)current->next; + } + + c16toa(length - OPAQUE16_LEN, output); /* writing list length */ + + return length; +} + + +/* write public key list in extension */ +static word16 TLSX_QSHPK_WriteR(QSHScheme* format, byte* output) +{ + word32 offset = 0; + word16 public_len = 0; + + if (!format) + return offset; + + /* write scheme ID */ + c16toa(format->name, output + offset); + offset += OPAQUE16_LEN; + + /* write public key matching scheme */ + public_len = format->PKLen; + c16toa(public_len, output + offset); + offset += OPAQUE16_LEN; + if (format->PK) { + XMEMCPY(output+offset, format->PK, public_len); + } + + return public_len + offset; +} + +word16 TLSX_QSHPK_Write(QSHScheme* list, byte* output) +{ + QSHScheme* current = list; + word32 length = 0; + word24 toWire; + + length += OPAQUE24_LEN; + + while (current) { + length += TLSX_QSHPK_WriteR(current, output + length); + current = (QSHScheme*)current->next; + } + /* length of public keys sent */ + c32to24(length - OPAQUE24_LEN, toWire); + output[0] = toWire[0]; + output[1] = toWire[1]; + output[2] = toWire[2]; + + return length; +} + +#endif /* NO_WOLFSSL_CLIENT */ +#ifndef NO_WOLFSSL_SERVER + +static void TLSX_QSHAgreement(TLSX** extensions, void* heap) +{ + TLSX* extension = TLSX_Find(*extensions, TLSX_QUANTUM_SAFE_HYBRID); + QSHScheme* format = NULL; + QSHScheme* del = NULL; + QSHScheme* prev = NULL; + + if (extension == NULL) + return; + + format = (QSHScheme*)extension->data; + while (format) { + if (format->PKLen == 0) { + /* case of head */ + if (format == extension->data) { + extension->data = format->next; + } + if (prev) + prev->next = format->next; + del = format; + format = format->next; + XFREE(del, heap, DYNAMIC_TYPE_TMP_BUFFER); + del = NULL; + } else { + prev = format; + format = format->next; + } + } + + (void)heap; +} + + +/* Parse in hello extension + input the byte stream to process + length length of total extension found + isRequest set to 1 if being sent to the server + */ +static int TLSX_QSH_Parse(WOLFSSL* ssl, byte* input, word16 length, + byte isRequest) +{ + byte numKeys = 0; + word16 offset = 0; + word16 schemSz = 0; + word16 offset_len = 0; + word32 offset_pk = 0; + word16 name = 0; + word16 PKLen = 0; + byte* PK = NULL; + int r; + + + if (OPAQUE16_LEN > length) + return BUFFER_ERROR; + + if (isRequest) { + ato16(input, &schemSz); + + /* list of public keys available for QSH schemes */ + offset_len = schemSz + OPAQUE16_LEN; + } + + offset_pk = ((input[offset_len] << 16) & 0xFF00000) | + (((input[offset_len + 1]) << 8) & 0xFF00) | + (input[offset_len + 2] & 0xFF); + offset_len += OPAQUE24_LEN; + + /* check buffer size */ + if (offset_pk > length) + return BUFFER_ERROR; + + /* set maximum number of keys the client will accept */ + if (!isRequest) + numKeys = (ssl->maxRequest < 1)? 1 : ssl->maxRequest; + + /* hello extension read list of scheme ids */ + if (isRequest) { + + /* read in request for public keys */ + ssl->minRequest = (input[length -1] >> 4) & 0xFF; + ssl->maxRequest = input[length -1] & 0x0F; + + /* choose the min between min requested by client and 1 */ + numKeys = (ssl->minRequest > 1) ? ssl->minRequest : 1; + + if (ssl->minRequest > ssl->maxRequest) + return BAD_FUNC_ARG; + + offset += OPAQUE16_LEN; + schemSz += offset; + + /* check buffer size */ + if (schemSz > length) + return BUFFER_ERROR; + + while ((offset < schemSz) && numKeys) { + /* Scheme ID list */ + ato16(input + offset, &name); + offset += OPAQUE16_LEN; + + /* validate we have scheme id */ + if (ssl->user_set_QSHSchemes && + !TLSX_ValidateQSHScheme(&ssl->extensions, name)) { + continue; + } + + /* server create keys on demand */ + if ((r = TLSX_CreateNtruKey(ssl, name)) != 0) { + WOLFSSL_MSG("Error creating ntru keys"); + return r; + } + + /* peer sent an agreed upon scheme */ + r = TLSX_UseQSHScheme(&ssl->extensions, name, NULL, 0, ssl->heap); + + if (r != WOLFSSL_SUCCESS) return r; /* throw error */ + + numKeys--; + } + + /* choose the min between min requested by client and 1 */ + numKeys = (ssl->minRequest > 1) ? ssl->minRequest : 1; + } + + /* QSHPK struct */ + offset_pk += offset_len; + while ((offset_len < offset_pk) && numKeys) { + QSHKey * temp; + + if ((temp = (QSHKey*)XMALLOC(sizeof(QSHKey), ssl->heap, + DYNAMIC_TYPE_TLSX)) == NULL) + return MEMORY_E; + + /* initialize */ + temp->next = NULL; + temp->pub.buffer = NULL; + temp->pub.length = 0; + temp->pri.buffer = NULL; + temp->pri.length = 0; + + /* scheme id */ + ato16(input + offset_len, &(temp->name)); + offset_len += OPAQUE16_LEN; + + /* public key length */ + ato16(input + offset_len, &PKLen); + temp->pub.length = PKLen; + offset_len += OPAQUE16_LEN; + + + if (isRequest) { + /* validate we have scheme id */ + if (ssl->user_set_QSHSchemes && + (!TLSX_ValidateQSHScheme(&ssl->extensions, temp->name))) { + offset_len += PKLen; + XFREE(temp, ssl->heap, DYNAMIC_TYPE_TLSX); + continue; + } + } + + /* read in public key */ + if (PKLen > 0) { + temp->pub.buffer = (byte*)XMALLOC(temp->pub.length, + ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + XMEMCPY(temp->pub.buffer, input + offset_len, temp->pub.length); + offset_len += PKLen; + } + else { + PK = NULL; + } + + /* use own key when adding to extensions list for sending reply */ + PKLen = 0; + PK = TLSX_QSHKeyFind_Pub(ssl->QSH_Key, &PKLen, temp->name); + r = TLSX_UseQSHScheme(&ssl->extensions, temp->name, PK, PKLen, + ssl->heap); + + /* store peers key */ + ssl->peerQSHKeyPresent = 1; + if (TLSX_AddQSHKey(&ssl->peerQSHKey, temp) != 0) + return MEMORY_E; + + if (temp->pub.length == 0) { + XFREE(temp, ssl->heap, DYNAMIC_TYPE_TLSX); + } + + if (r != WOLFSSL_SUCCESS) {return r;} /* throw error */ + + numKeys--; + } + + /* reply to a QSH extension sent from client */ + if (isRequest) { + TLSX_SetResponse(ssl, TLSX_QUANTUM_SAFE_HYBRID); + /* only use schemes we have key generated for -- free the rest */ + TLSX_QSHAgreement(&ssl->extensions, ssl->heap); + } + + return 0; +} + + +/* Used for parsing in QSHCipher structs on Key Exchange */ +int TLSX_QSHCipher_Parse(WOLFSSL* ssl, const byte* input, word16 length, + byte isServer) +{ + QSHKey* key; + word16 Max_Secret_Len = 48; + word16 offset = 0; + word16 offset_len = 0; + word32 offset_pk = 0; + word16 name = 0; + word16 secretLen = 0; + byte* secret = NULL; + word16 buffLen = 0; + byte buff[145]; /* size enough for 3 secrets */ + buffer* buf; + + /* pointer to location where secret should be stored */ + if (isServer) { + buf = ssl->QSH_secret->CliSi; + } + else { + buf = ssl->QSH_secret->SerSi; + } + + offset_pk = ((input[offset_len] << 16) & 0xFF0000) | + (((input[offset_len + 1]) << 8) & 0xFF00) | + (input[offset_len + 2] & 0xFF); + offset_len += OPAQUE24_LEN; + + /* validating extension list length -- check if trying to read over edge + of buffer */ + if (length < (offset_pk + OPAQUE24_LEN)) { + return BUFFER_ERROR; + } + + /* QSHCipherList struct */ + offset_pk += offset_len; + while (offset_len < offset_pk) { + + /* scheme id */ + ato16(input + offset_len, &name); + offset_len += OPAQUE16_LEN; + + /* public key length */ + ato16(input + offset_len, &secretLen); + offset_len += OPAQUE16_LEN; + + /* read in public key */ + if (secretLen > 0) { + secret = (byte*)(input + offset_len); + offset_len += secretLen; + } + else { + secret = NULL; + } + + /* no secret sent */ + if (secret == NULL) + continue; + + /* find corresponding key */ + key = ssl->QSH_Key; + while (key) { + if (key->name == name) + break; + else + key = (QSHKey*)key->next; + } + + /* if we do not have the key than there was a big issue negotiation */ + if (key == NULL) { + WOLFSSL_MSG("key was null for decryption!!!\n"); + return MEMORY_E; + } + + /* Decrypt sent secret */ + buffLen = Max_Secret_Len; + QSH_Decrypt(key, secret, secretLen, buff + offset, &buffLen); + offset += buffLen; + } + + /* allocate memory for buffer */ + buf->length = offset; + buf->buffer = (byte*)XMALLOC(offset, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (buf->buffer == NULL) + return MEMORY_E; + + /* store secrets */ + XMEMCPY(buf->buffer, buff, offset); + ForceZero(buff, offset); + + return offset_len; +} + + +/* return 1 on success */ +int TLSX_ValidateQSHScheme(TLSX** extensions, word16 theirs) { + TLSX* extension = TLSX_Find(*extensions, TLSX_QUANTUM_SAFE_HYBRID); + QSHScheme* format = NULL; + + /* if no extension is sent then do not use QSH */ + if (!extension) { + WOLFSSL_MSG("No QSH Extension"); + return 0; + } + + for (format = (QSHScheme*)extension->data; format; format = format->next) { + if (format->name == theirs) { + WOLFSSL_MSG("Found Matching QSH Scheme"); + return 1; /* have QSH */ + } + } + + return 0; +} +#endif /* NO_WOLFSSL_SERVER */ + +/* test if the QSH Scheme is implemented + return 1 if yes 0 if no */ +static int TLSX_HaveQSHScheme(word16 name) +{ + switch(name) { + #ifdef HAVE_NTRU + case WOLFSSL_NTRU_EESS439: + case WOLFSSL_NTRU_EESS593: + case WOLFSSL_NTRU_EESS743: + return 1; + #endif + case WOLFSSL_LWE_XXX: + case WOLFSSL_HFE_XXX: + return 0; /* not supported yet */ + + default: + return 0; + } +} + + +/* Add a QSHScheme struct to list of usable ones */ +int TLSX_UseQSHScheme(TLSX** extensions, word16 name, byte* pKey, word16 pkeySz, + void* heap) +{ + TLSX* extension = TLSX_Find(*extensions, TLSX_QUANTUM_SAFE_HYBRID); + QSHScheme* format = NULL; + int ret = 0; + + /* sanity check */ + if (extensions == NULL || (pKey == NULL && pkeySz != 0)) + return BAD_FUNC_ARG; + + /* if scheme is implemented than add */ + if (TLSX_HaveQSHScheme(name)) { + if ((ret = TLSX_QSH_Append(&format, name, pKey, pkeySz)) != 0) + return ret; + + if (!extension) { + if ((ret = TLSX_Push(extensions, TLSX_QUANTUM_SAFE_HYBRID, format, + heap)) != 0) { + XFREE(format, 0, DYNAMIC_TYPE_TLSX); + return ret; + } + } + else { + /* push new QSH object to extension data. */ + format->next = (QSHScheme*)extension->data; + extension->data = (void*)format; + + /* look for another format of the same name to remove (replacement) */ + do { + if (format->next && (format->next->name == name)) { + QSHScheme* next = format->next; + + format->next = next->next; + XFREE(next, 0, DYNAMIC_TYPE_TLSX); + + break; + } + } while ((format = format->next)); + } + } + return WOLFSSL_SUCCESS; +} + +#define QSH_FREE_ALL TLSX_QSH_FreeAll +#define QSH_VALIDATE_REQUEST TLSX_QSH_ValidateRequest + +#ifndef NO_WOLFSSL_CLIENT +#define QSH_GET_SIZE TLSX_QSH_GetSize +#define QSH_WRITE TLSX_QSH_Write +#else +#define QSH_GET_SIZE(list) 0 +#define QSH_WRITE(a, b) 0 +#endif + +#ifndef NO_WOLFSSL_SERVER +#define QSH_PARSE TLSX_QSH_Parse +#else +#define QSH_PARSE(a, b, c, d) 0 +#endif + +#define QSHPK_WRITE TLSX_QSHPK_Write +#define QSH_SERREQ TLSX_QSH_SerPKReq +#else + +#define QSH_FREE_ALL(list, heap) +#define QSH_GET_SIZE(list, a) 0 +#define QSH_WRITE(a, b) 0 +#define QSH_PARSE(a, b, c, d) 0 +#define QSHPK_WRITE(a, b) 0 +#define QSH_SERREQ(a, b) 0 +#define QSH_VALIDATE_REQUEST(a, b) + +#endif /* HAVE_QSH */ + +/******************************************************************************/ +/* Supported Versions */ +/******************************************************************************/ + +#ifdef WOLFSSL_TLS13 +/* Return the size of the SupportedVersions extension's data. + * + * data The SSL/TLS object. + * msgType The type of the message this extension is being written into. + * returns the length of data that will be in the extension. + */ +static int TLSX_SupportedVersions_GetSize(void* data, byte msgType, word16* pSz) +{ + WOLFSSL* ssl = (WOLFSSL*)data; + + if (msgType == client_hello) { + /* TLS v1.2 and TLS v1.3 */ + int cnt = 0; + + #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + if ((ssl->options.mask & SSL_OP_NO_TLSv1_3) == 0) + #endif + cnt++; + + if (ssl->options.downgrade) { +#ifndef WOLFSSL_NO_TLS12 + #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + if ((ssl->options.mask & SSL_OP_NO_TLSv1_2) == 0) + #endif + cnt++; +#endif + +#ifndef NO_OLD_TLS + #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + if ((ssl->options.mask & SSL_OP_NO_TLSv1_1) == 0) + #endif + cnt++; + #ifdef WOLFSSL_ALLOW_TLSV10 + #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + if ((ssl->options.mask & SSL_OP_NO_TLSv1) == 0) + #endif + cnt++; + #endif +#endif + } + + *pSz += (word16)(OPAQUE8_LEN + cnt * OPAQUE16_LEN); + } +#ifndef WOLFSSL_TLS13_DRAFT_18 + else if (msgType == server_hello || msgType == hello_retry_request) + *pSz += OPAQUE16_LEN; +#endif + else + return SANITY_MSG_E; + + return 0; +} + +/* Writes the SupportedVersions extension into the buffer. + * + * data The SSL/TLS object. + * output The buffer to write the extension into. + * msgType The type of the message this extension is being written into. + * returns the length of data that was written. + */ +static int TLSX_SupportedVersions_Write(void* data, byte* output, + byte msgType, word16* pSz) +{ + WOLFSSL* ssl = (WOLFSSL*)data; + byte major; + byte* cnt; + + if (msgType == client_hello) { + major = ssl->ctx->method->version.major; + + + cnt = output++; + *cnt = 0; + #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + if ((ssl->options.mask & SSL_OP_NO_TLSv1_3) == 0) + #endif + { + *cnt += OPAQUE16_LEN; +#ifdef WOLFSSL_TLS13_DRAFT + /* The TLS draft major number. */ + *(output++) = TLS_DRAFT_MAJOR; + /* Version of draft supported. */ + *(output++) = TLS_DRAFT_MINOR; +#else + *(output++) = major; + *(output++) = (byte)TLSv1_3_MINOR; +#endif + } + if (ssl->options.downgrade) { +#ifndef WOLFSSL_NO_TLS12 + #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + if ((ssl->options.mask & SSL_OP_NO_TLSv1_2) == 0) + #endif + { + *cnt += OPAQUE16_LEN; + *(output++) = major; + *(output++) = (byte)TLSv1_2_MINOR; + } +#endif + +#ifndef NO_OLD_TLS + #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + if ((ssl->options.mask & SSL_OP_NO_TLSv1_1) == 0) + #endif + { + *cnt += OPAQUE16_LEN; + *(output++) = major; + *(output++) = (byte)TLSv1_1_MINOR; + } + #ifdef WOLFSSL_ALLOW_TLSV10 + #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + if ((ssl->options.mask & SSL_OP_NO_TLSv1) == 0) + #endif + { + *cnt += OPAQUE16_LEN; + *(output++) = major; + *(output++) = (byte)TLSv1_MINOR; + } + #endif +#endif + } + + *pSz += (word16)(OPAQUE8_LEN + *cnt); + } +#ifndef WOLFSSL_TLS13_DRAFT_18 + else if (msgType == server_hello || msgType == hello_retry_request) { + #ifdef WOLFSSL_TLS13_DRAFT + if (ssl->version.major == SSLv3_MAJOR && + ssl->version.minor == TLSv1_3_MINOR) { + output[0] = TLS_DRAFT_MAJOR; + output[1] = TLS_DRAFT_MINOR; + } + else + #endif + { + output[0] = ssl->version.major; + output[1] = ssl->version.minor; + } + + *pSz += OPAQUE16_LEN; + } +#endif + else + return SANITY_MSG_E; + + return 0; +} + +/* Parse the SupportedVersions extension. + * + * ssl The SSL/TLS object. + * input The buffer with the extension data. + * length The length of the extension data. + * msgType The type of the message this extension is being parsed from. + * returns 0 on success, otherwise failure. + */ +static int TLSX_SupportedVersions_Parse(WOLFSSL* ssl, byte* input, + word16 length, byte msgType) +{ + ProtocolVersion pv = ssl->ctx->method->version; + int i; + int len; + byte major, minor; + int newMinor = 0; + int set = 0; + + if (msgType == client_hello) { + /* Must contain a length and at least one version. */ + if (length < OPAQUE8_LEN + OPAQUE16_LEN || (length & 1) != 1) + return BUFFER_ERROR; + + len = *input; + + /* Protocol version array must fill rest of data. */ + if (length != (word16)OPAQUE8_LEN + len) + return BUFFER_ERROR; + + input++; + + /* Find first match. */ + for (i = 0; i < len; i += OPAQUE16_LEN) { + major = input[i]; + minor = input[i + OPAQUE8_LEN]; + +#ifdef WOLFSSL_TLS13_DRAFT + if (major == TLS_DRAFT_MAJOR && minor == TLS_DRAFT_MINOR) { + major = SSLv3_MAJOR; + minor = TLSv1_3_MINOR; + } +#else + if (major == TLS_DRAFT_MAJOR) + continue; +#endif + + if (major != pv.major) + continue; + + /* No upgrade allowed. */ + if (minor > ssl->version.minor) + continue; + /* Check downgrade. */ + if (minor < ssl->version.minor) { + if (!ssl->options.downgrade) + continue; + + if (minor < ssl->options.minDowngrade) + continue; + + if (newMinor == 0 && minor > ssl->options.oldMinor) { + /* Downgrade the version. */ + ssl->version.minor = minor; + } + } + + if (minor >= TLSv1_3_MINOR) { + if (!ssl->options.tls1_3) { + ssl->options.tls1_3 = 1; + TLSX_Push(&ssl->extensions, TLSX_SUPPORTED_VERSIONS, ssl, + ssl->heap); +#ifndef WOLFSSL_TLS13_DRAFT_18 + TLSX_SetResponse(ssl, TLSX_SUPPORTED_VERSIONS); +#endif + } + if (minor > newMinor) { + ssl->version.minor = minor; + newMinor = minor; + } + } + else if (minor > ssl->options.oldMinor) + ssl->options.oldMinor = minor; + + set = 1; + } + if (!set) { + #ifdef WOLFSSL_MYSQL_COMPATIBLE + SendAlert(ssl, alert_fatal, wc_protocol_version); + #else + SendAlert(ssl, alert_fatal, protocol_version); + #endif + return VERSION_ERROR; + } + } +#ifndef WOLFSSL_TLS13_DRAFT_18 + else if (msgType == server_hello || msgType == hello_retry_request) { + /* Must contain one version. */ + if (length != OPAQUE16_LEN) + return BUFFER_ERROR; + + major = input[0]; + minor = input[OPAQUE8_LEN]; + + #ifdef WOLFSSL_TLS13_DRAFT + if (major == TLS_DRAFT_MAJOR && minor == TLS_DRAFT_MINOR) { + major = SSLv3_MAJOR; + minor = TLSv1_3_MINOR; + } + #endif + + if (major != pv.major) + return VERSION_ERROR; + + /* Can't downgrade with this extension below TLS v1.3. */ + if (minor < TLSv1_3_MINOR) + return VERSION_ERROR; + + /* Version is TLS v1.2 to handle downgrading from TLS v1.3+. */ + if (ssl->options.downgrade && ssl->version.minor == TLSv1_2_MINOR) { + /* Set minor version back to TLS v1.3+ */ + ssl->version.minor = ssl->ctx->method->version.minor; + } + + /* No upgrade allowed. */ + if (ssl->version.minor < minor) + return VERSION_ERROR; + + /* Check downgrade. */ + if (ssl->version.minor > minor) { + if (!ssl->options.downgrade) + return VERSION_ERROR; + + if (minor < ssl->options.minDowngrade) + return VERSION_ERROR; + + /* Downgrade the version. */ + ssl->version.minor = minor; + } + } +#endif + else + return SANITY_MSG_E; + + return 0; +} + +/* Sets a new SupportedVersions extension into the extension list. + * + * extensions The list of extensions. + * data The extensions specific data. + * heap The heap used for allocation. + * returns 0 on success, otherwise failure. + */ +static int TLSX_SetSupportedVersions(TLSX** extensions, const void* data, + void* heap) +{ + if (extensions == NULL || data == NULL) + return BAD_FUNC_ARG; + + return TLSX_Push(extensions, TLSX_SUPPORTED_VERSIONS, (void *)data, heap); +} + +#define SV_GET_SIZE TLSX_SupportedVersions_GetSize +#define SV_WRITE TLSX_SupportedVersions_Write +#define SV_PARSE TLSX_SupportedVersions_Parse + +#else + +#define SV_GET_SIZE(a, b, c) 0 +#define SV_WRITE(a, b, c, d) 0 +#define SV_PARSE(a, b, c, d) 0 + +#endif /* WOLFSSL_TLS13 */ + +#if defined(WOLFSSL_TLS13) + +/******************************************************************************/ +/* Cookie */ +/******************************************************************************/ + +/* Free the cookie data. + * + * cookie Cookie data. + * heap The heap used for allocation. + */ +static void TLSX_Cookie_FreeAll(Cookie* cookie, void* heap) +{ + (void)heap; + + if (cookie != NULL) + XFREE(cookie, heap, DYNAMIC_TYPE_TLSX); +} + +/* Get the size of the encoded Cookie extension. + * In messages: ClientHello and HelloRetryRequest. + * + * cookie The cookie to write. + * msgType The type of the message this extension is being written into. + * returns the number of bytes of the encoded Cookie extension. + */ +static int TLSX_Cookie_GetSize(Cookie* cookie, byte msgType, word16* pSz) +{ + if (msgType == client_hello || msgType == hello_retry_request) + *pSz += OPAQUE16_LEN + cookie->len; + else + return SANITY_MSG_E; + return 0; +} + +/* Writes the Cookie extension into the output buffer. + * Assumes that the the output buffer is big enough to hold data. + * In messages: ClientHello and HelloRetryRequest. + * + * cookie The cookie to write. + * output The buffer to write into. + * msgType The type of the message this extension is being written into. + * returns the number of bytes written into the buffer. + */ +static int TLSX_Cookie_Write(Cookie* cookie, byte* output, byte msgType, + word16* pSz) +{ + if (msgType == client_hello || msgType == hello_retry_request) { + c16toa(cookie->len, output); + output += OPAQUE16_LEN; + XMEMCPY(output, &cookie->data, cookie->len); + *pSz += OPAQUE16_LEN + cookie->len; + } + else + return SANITY_MSG_E; + return 0; +} + +/* Parse the Cookie extension. + * In messages: ClientHello and HelloRetryRequest. + * + * ssl The SSL/TLS object. + * input The extension data. + * length The length of the extension data. + * msgType The type of the message this extension is being parsed from. + * returns 0 on success and other values indicate failure. + */ +static int TLSX_Cookie_Parse(WOLFSSL* ssl, byte* input, word16 length, + byte msgType) +{ + word16 len; + word16 idx = 0; + TLSX* extension; + Cookie* cookie; + + if (msgType != client_hello && msgType != hello_retry_request) + return SANITY_MSG_E; + + /* Message contains length and Cookie which must be at least one byte + * in length. + */ + if (length < OPAQUE16_LEN + 1) + return BUFFER_E; + ato16(input + idx, &len); + idx += OPAQUE16_LEN; + if (length - idx != len) + return BUFFER_E; + + if (msgType == hello_retry_request) + return TLSX_Cookie_Use(ssl, input + idx, len, NULL, 0, 0); + + /* client_hello */ + extension = TLSX_Find(ssl->extensions, TLSX_COOKIE); + if (extension == NULL) + return HRR_COOKIE_ERROR; + + cookie = (Cookie*)extension->data; + if (cookie->len != len || XMEMCMP(&cookie->data, input + idx, len) != 0) + return HRR_COOKIE_ERROR; + + /* Request seen. */ + extension->resp = 0; + + return 0; +} + +/* Use the data to create a new Cookie object in the extensions. + * + * ssl SSL/TLS object. + * data Cookie data. + * len Length of cookie data in bytes. + * mac MAC data. + * macSz Length of MAC data in bytes. + * resp Indicates the extension will go into a response (HelloRetryRequest). + * returns 0 on success and other values indicate failure. + */ +int TLSX_Cookie_Use(WOLFSSL* ssl, byte* data, word16 len, byte* mac, + byte macSz, int resp) +{ + int ret = 0; + TLSX* extension; + Cookie* cookie; + + /* Find the cookie extension if it exists. */ + extension = TLSX_Find(ssl->extensions, TLSX_COOKIE); + if (extension == NULL) { + /* Push new cookie extension. */ + ret = TLSX_Push(&ssl->extensions, TLSX_COOKIE, NULL, ssl->heap); + if (ret != 0) + return ret; + + extension = TLSX_Find(ssl->extensions, TLSX_COOKIE); + if (extension == NULL) + return MEMORY_E; + } + + /* The Cookie structure has one byte for cookie data already. */ + cookie = (Cookie*)XMALLOC(sizeof(Cookie) + len + macSz - 1, ssl->heap, + DYNAMIC_TYPE_TLSX); + if (cookie == NULL) + return MEMORY_E; + + cookie->len = len + macSz; + XMEMCPY(&cookie->data, data, len); + if (mac != NULL) + XMEMCPY(&cookie->data + len, mac, macSz); + + extension->data = (void*)cookie; + extension->resp = (byte)resp; + + return 0; +} + +#define CKE_FREE_ALL TLSX_Cookie_FreeAll +#define CKE_GET_SIZE TLSX_Cookie_GetSize +#define CKE_WRITE TLSX_Cookie_Write +#define CKE_PARSE TLSX_Cookie_Parse + +#else + +#define CKE_FREE_ALL(a, b) 0 +#define CKE_GET_SIZE(a, b, c) 0 +#define CKE_WRITE(a, b, c, d) 0 +#define CKE_PARSE(a, b, c, d) 0 + +#endif +#if !defined(WOLFSSL_NO_SIGALG) +/******************************************************************************/ +/* Signature Algorithms */ +/******************************************************************************/ + +/* Return the size of the SignatureAlgorithms extension's data. + * + * data Unused + * returns the length of data that will be in the extension. + */ + +static word16 TLSX_SignatureAlgorithms_GetSize(void* data) +{ + WOLFSSL* ssl = (WOLFSSL*)data; + + return OPAQUE16_LEN + ssl->suites->hashSigAlgoSz; +} + +/* Creates a bit string of supported hash algorithms with RSA PSS. + * The bit string is used when determining which signature algorithm to use + * when creating the CertificateVerify message. + * Note: Valid data has an even length as each signature algorithm is two bytes. + * + * ssl The SSL/TLS object. + * input The buffer with the list of supported signature algorithms. + * length The length of the list in bytes. + * returns 0 on success, BUFFER_ERROR when the length is not even. + */ +static int TLSX_SignatureAlgorithms_MapPss(WOLFSSL *ssl, byte* input, + word16 length) +{ + word16 i; + + if ((length & 1) == 1) + return BUFFER_ERROR; + + ssl->pssAlgo = 0; + for (i = 0; i < length; i += 2) { + if (input[i] == rsa_pss_sa_algo && input[i + 1] <= sha512_mac) + ssl->pssAlgo |= 1 << input[i + 1]; + #ifdef WOLFSSL_TLS13 + if (input[i] == rsa_pss_sa_algo && input[i + 1] >= pss_sha256 && + input[i + 1] <= pss_sha512) { + ssl->pssAlgo |= 1 << input[i + 1]; + } + #endif + } + + return 0; +} + +/* Writes the SignatureAlgorithms extension into the buffer. + * + * data Unused + * output The buffer to write the extension into. + * returns the length of data that was written. + */ +static word16 TLSX_SignatureAlgorithms_Write(void* data, byte* output) +{ + WOLFSSL* ssl = (WOLFSSL*)data; + + c16toa(ssl->suites->hashSigAlgoSz, output); + XMEMCPY(output + OPAQUE16_LEN, ssl->suites->hashSigAlgo, + ssl->suites->hashSigAlgoSz); + + TLSX_SignatureAlgorithms_MapPss(ssl, output + OPAQUE16_LEN, + ssl->suites->hashSigAlgoSz); + + return OPAQUE16_LEN + ssl->suites->hashSigAlgoSz; +} + +/* Parse the SignatureAlgorithms extension. + * + * ssl The SSL/TLS object. + * input The buffer with the extension data. + * length The length of the extension data. + * returns 0 on success, otherwise failure. + */ +static int TLSX_SignatureAlgorithms_Parse(WOLFSSL *ssl, byte* input, + word16 length, byte isRequest, Suites* suites) +{ + word16 len; + + if (!isRequest) + return BUFFER_ERROR; + + /* Must contain a length and at least algorithm. */ + if (length < OPAQUE16_LEN + OPAQUE16_LEN || (length & 1) != 0) + return BUFFER_ERROR; + + ato16(input, &len); + input += OPAQUE16_LEN; + + /* Algorithm array must fill rest of data. */ + if (length != OPAQUE16_LEN + len) + return BUFFER_ERROR; + + /* truncate hashSigAlgo list if too long */ + suites->hashSigAlgoSz = len; + if (suites->hashSigAlgoSz > WOLFSSL_MAX_SIGALGO) { + WOLFSSL_MSG("TLSX SigAlgo list exceeds max, truncating"); + suites->hashSigAlgoSz = WOLFSSL_MAX_SIGALGO; + } + XMEMCPY(suites->hashSigAlgo, input, suites->hashSigAlgoSz); + + return TLSX_SignatureAlgorithms_MapPss(ssl, input, len); +} + +/* Sets a new SignatureAlgorithms extension into the extension list. + * + * extensions The list of extensions. + * data The extensions specific data. + * heap The heap used for allocation. + * returns 0 on success, otherwise failure. + */ +static int TLSX_SetSignatureAlgorithms(TLSX** extensions, const void* data, + void* heap) +{ + if (extensions == NULL) + return BAD_FUNC_ARG; + + return TLSX_Push(extensions, TLSX_SIGNATURE_ALGORITHMS, (void *)data, heap); +} + +#define SA_GET_SIZE TLSX_SignatureAlgorithms_GetSize +#define SA_WRITE TLSX_SignatureAlgorithms_Write +#define SA_PARSE TLSX_SignatureAlgorithms_Parse +#endif +/******************************************************************************/ +/* Signature Algorithms Certificate */ +/******************************************************************************/ + +#ifdef WOLFSSL_TLS13 +#if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22) +/* Return the size of the SignatureAlgorithms extension's data. + * + * data Unused + * returns the length of data that will be in the extension. + */ +static word16 TLSX_SignatureAlgorithmsCert_GetSize(void* data) +{ + WOLFSSL* ssl = (WOLFSSL*)data; + + return OPAQUE16_LEN + ssl->certHashSigAlgoSz; +} + +/* Writes the SignatureAlgorithmsCert extension into the buffer. + * + * data Unused + * output The buffer to write the extension into. + * returns the length of data that was written. + */ +static word16 TLSX_SignatureAlgorithmsCert_Write(void* data, byte* output) +{ + WOLFSSL* ssl = (WOLFSSL*)data; + + c16toa(ssl->certHashSigAlgoSz, output); + XMEMCPY(output + OPAQUE16_LEN, ssl->certHashSigAlgo, + ssl->certHashSigAlgoSz); + + return OPAQUE16_LEN + ssl->certHashSigAlgoSz; +} + +/* Parse the SignatureAlgorithmsCert extension. + * + * ssl The SSL/TLS object. + * input The buffer with the extension data. + * length The length of the extension data. + * returns 0 on success, otherwise failure. + */ +static int TLSX_SignatureAlgorithmsCert_Parse(WOLFSSL *ssl, byte* input, + word16 length, byte isRequest) +{ + word16 len; + + if (!isRequest) + return BUFFER_ERROR; + + /* Must contain a length and at least algorithm. */ + if (length < OPAQUE16_LEN + OPAQUE16_LEN || (length & 1) != 0) + return BUFFER_ERROR; + + ato16(input, &len); + input += OPAQUE16_LEN; + + /* Algorithm array must fill rest of data. */ + if (length != OPAQUE16_LEN + len) + return BUFFER_ERROR; + + /* truncate hashSigAlgo list if too long */ + ssl->certHashSigAlgoSz = len; + if (ssl->certHashSigAlgoSz > WOLFSSL_MAX_SIGALGO) { + WOLFSSL_MSG("TLSX SigAlgo list exceeds max, truncating"); + ssl->certHashSigAlgoSz = WOLFSSL_MAX_SIGALGO; + } + XMEMCPY(ssl->certHashSigAlgo, input, ssl->certHashSigAlgoSz); + + return 0; +} + +/* Sets a new SignatureAlgorithmsCert extension into the extension list. + * + * extensions The list of extensions. + * data The extensions specific data. + * heap The heap used for allocation. + * returns 0 on success, otherwise failure. + */ +static int TLSX_SetSignatureAlgorithmsCert(TLSX** extensions, const void* data, + void* heap) +{ + if (extensions == NULL) + return BAD_FUNC_ARG; + + return TLSX_Push(extensions, TLSX_SIGNATURE_ALGORITHMS_CERT, (void *)data, + heap); +} + +#define SAC_GET_SIZE TLSX_SignatureAlgorithmsCert_GetSize +#define SAC_WRITE TLSX_SignatureAlgorithmsCert_Write +#define SAC_PARSE TLSX_SignatureAlgorithmsCert_Parse +#endif /* !WOLFSSL_TLS13_DRAFT_18 && !WOLFSSL_TLS13_DRAFT_22 */ +#endif /* WOLFSSL_TLS13 */ + + +/******************************************************************************/ +/* Key Share */ +/******************************************************************************/ + +#ifdef WOLFSSL_TLS13 +/* Create a key share entry using named Diffie-Hellman parameters group. + * Generates a key pair. + * + * ssl The SSL/TLS object. + * kse The key share entry object. + * returns 0 on success, otherwise failure. + */ +static int TLSX_KeyShare_GenDhKey(WOLFSSL *ssl, KeyShareEntry* kse) +{ + int ret; +#ifndef NO_DH + byte* keyData; + void* key = NULL; + word32 keySz; + word32 dataSz; + const DhParams* params; +#ifdef WOLFSSL_SMALL_STACK + DhKey* dhKey = NULL; +#else + DhKey dhKey[1]; +#endif + + /* TODO: [TLS13] The key size should come from wolfcrypt. */ + /* Pick the parameters from the named group. */ + switch (kse->group) { + #ifdef HAVE_FFDHE_2048 + case WOLFSSL_FFDHE_2048: + params = wc_Dh_ffdhe2048_Get(); + keySz = 29; + break; + #endif + #ifdef HAVE_FFDHE_3072 + case WOLFSSL_FFDHE_3072: + params = wc_Dh_ffdhe3072_Get(); + keySz = 34; + break; + #endif + #ifdef HAVE_FFDHE_4096 + case WOLFSSL_FFDHE_4096: + params = wc_Dh_ffdhe4096_Get(); + keySz = 39; + break; + #endif + #ifdef HAVE_FFDHE_6144 + case WOLFSSL_FFDHE_6144: + params = wc_Dh_ffdhe6144_Get(); + keySz = 46; + break; + #endif + #ifdef HAVE_FFDHE_8192 + case WOLFSSL_FFDHE_8192: + params = wc_Dh_ffdhe8192_Get(); + keySz = 52; + break; + #endif + default: + return BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + dhKey = (DhKey*)XMALLOC(sizeof(DhKey), ssl->heap, DYNAMIC_TYPE_DH); + if (dhKey == NULL) + return MEMORY_E; +#endif + + ret = wc_InitDhKey_ex(dhKey, ssl->heap, ssl->devId); + if (ret != 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(dhKey, ssl->heap, DYNAMIC_TYPE_DH); + #endif + return ret; + } + + /* Allocate space for the public key. */ + dataSz = params->p_len; + keyData = (byte*)XMALLOC(dataSz, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + if (keyData == NULL) { + ret = MEMORY_E; + goto end; + } + /* Allocate space for the private key. */ + key = (byte*)XMALLOC(keySz, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + if (key == NULL) { + ret = MEMORY_E; + goto end; + } + + /* Set key */ + ret = wc_DhSetKey(dhKey, + (byte*)params->p, params->p_len, + (byte*)params->g, params->g_len); + if (ret != 0) + goto end; + + /* Generate a new key pair. */ + ret = wc_DhGenerateKeyPair(dhKey, ssl->rng, (byte*)key, &keySz, keyData, + &dataSz); +#ifdef WOLFSSL_ASYNC_CRYPT + /* TODO: Make this function non-blocking */ + if (ret == WC_PENDING_E) { + ret = wc_AsyncWait(ret, &dhKey->asyncDev, WC_ASYNC_FLAG_NONE); + } +#endif + if (ret != 0) + goto end; + + if (params->p_len != dataSz) { + /* Pad the front of the key data with zeros. */ + XMEMMOVE(keyData + params->p_len - dataSz, keyData, dataSz); + XMEMSET(keyData, 0, params->p_len - dataSz); + } + + kse->pubKey = keyData; + kse->pubKeyLen = params->p_len; + kse->key = key; + kse->keyLen = keySz; + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Public DH Key"); + WOLFSSL_BUFFER(keyData, params->p_len); +#endif + +end: + + wc_FreeDhKey(dhKey); +#ifdef WOLFSSL_SMALL_STACK + XFREE(dhKey, ssl->heap, DYNAMIC_TYPE_DH); +#endif + + if (ret != 0) { + /* Data owned by key share entry otherwise. */ + if (keyData != NULL) + XFREE(keyData, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + if (key != NULL) + XFREE(key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + } +#else + (void)ssl; + (void)kse; + + ret = NOT_COMPILED_IN; +#endif + + return ret; +} + +/* Create a key share entry using X25519 parameters group. + * Generates a key pair. + * + * ssl The SSL/TLS object. + * kse The key share entry object. + * returns 0 on success, otherwise failure. + */ +static int TLSX_KeyShare_GenX25519Key(WOLFSSL *ssl, KeyShareEntry* kse) +{ + int ret; +#ifdef HAVE_CURVE25519 + byte* keyData = NULL; + word32 dataSize = CURVE25519_KEYSIZE; + curve25519_key* key; + + /* Allocate an ECC key to hold private key. */ + key = (curve25519_key*)XMALLOC(sizeof(curve25519_key), + ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + if (key == NULL) { + WOLFSSL_MSG("EccTempKey Memory error"); + return MEMORY_E; + } + + /* Make an ECC key. */ + ret = wc_curve25519_init(key); + if (ret != 0) + goto end; + ret = wc_curve25519_make_key(ssl->rng, CURVE25519_KEYSIZE, key); + if (ret != 0) + goto end; + + /* Allocate space for the public key. */ + keyData = (byte*)XMALLOC(CURVE25519_KEYSIZE, ssl->heap, + DYNAMIC_TYPE_PUBLIC_KEY); + if (keyData == NULL) { + WOLFSSL_MSG("Key data Memory error"); + ret = MEMORY_E; + goto end; + } + + /* Export public key. */ + if (wc_curve25519_export_public_ex(key, keyData, &dataSize, + EC25519_LITTLE_ENDIAN) != 0) { + ret = ECC_EXPORT_ERROR; + goto end; + } + + kse->pubKey = keyData; + kse->pubKeyLen = CURVE25519_KEYSIZE; + kse->key = key; + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Public Curve25519 Key"); + WOLFSSL_BUFFER(keyData, dataSize); +#endif + +end: + if (ret != 0) { + /* Data owned by key share entry otherwise. */ + if (keyData != NULL) + XFREE(keyData, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + wc_curve25519_free(key); + XFREE(key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + } +#else + (void)ssl; + (void)kse; + + ret = NOT_COMPILED_IN; +#endif /* HAVE_CURVE25519 */ + + return ret; +} + +/* Create a key share entry using named elliptic curve parameters group. + * Generates a key pair. + * + * ssl The SSL/TLS object. + * kse The key share entry object. + * returns 0 on success, otherwise failure. + */ +static int TLSX_KeyShare_GenEccKey(WOLFSSL *ssl, KeyShareEntry* kse) +{ + int ret; +#ifdef HAVE_ECC + byte* keyData = NULL; + word32 dataSize; + byte* keyPtr = NULL; + word32 keySize; + ecc_key* eccKey; + word16 curveId; + + /* TODO: [TLS13] The key sizes should come from wolfcrypt. */ + /* Translate named group to a curve id. */ + switch (kse->group) { + #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP256R1: + curveId = ECC_SECP256R1; + keySize = 32; + dataSize = keySize * 2 + 1; + break; + #endif /* !NO_ECC_SECP */ + #endif + #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP384R1: + curveId = ECC_SECP384R1; + keySize = 48; + dataSize = keySize * 2 + 1; + break; + #endif /* !NO_ECC_SECP */ + #endif + #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP521R1: + curveId = ECC_SECP521R1; + keySize = 66; + dataSize = keySize * 2 + 1; + break; + #endif /* !NO_ECC_SECP */ + #endif + #ifdef HAVE_X448 + case WOLFSSL_ECC_X448: + curveId = ECC_X448; + dataSize = keySize = 56; + break; + #endif + default: + return BAD_FUNC_ARG; + } + + /* Allocate an ECC key to hold private key. */ + keyPtr = (byte*)XMALLOC(sizeof(ecc_key), ssl->heap, + DYNAMIC_TYPE_PRIVATE_KEY); + if (keyPtr == NULL) { + WOLFSSL_MSG("EccTempKey Memory error"); + return MEMORY_E; + } + eccKey = (ecc_key*)keyPtr; + + /* Make an ECC key. */ + ret = wc_ecc_init_ex(eccKey, ssl->heap, ssl->devId); + if (ret != 0) + goto end; + ret = wc_ecc_make_key_ex(ssl->rng, keySize, eccKey, curveId); +#ifdef WOLFSSL_ASYNC_CRYPT + /* TODO: Make this function non-blocking */ + if (ret == WC_PENDING_E) { + ret = wc_AsyncWait(ret, &eccKey->asyncDev, WC_ASYNC_FLAG_NONE); + } +#endif + if (ret != 0) + goto end; + + /* Allocate space for the public key. */ + keyData = (byte*)XMALLOC(dataSize, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + if (keyData == NULL) { + WOLFSSL_MSG("Key data Memory error"); + ret = MEMORY_E; + goto end; + } + + /* Export public key. */ + if (wc_ecc_export_x963(eccKey, keyData, &dataSize) != 0) { + ret = ECC_EXPORT_ERROR; + goto end; + } + + kse->pubKey = keyData; + kse->pubKeyLen = dataSize; + kse->key = keyPtr; + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Public ECC Key"); + WOLFSSL_BUFFER(keyData, dataSize); +#endif + +end: + if (ret != 0) { + /* Data owned by key share entry otherwise. */ + if (keyPtr != NULL) + XFREE(keyPtr, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + if (keyData != NULL) + XFREE(keyData, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + } +#else + (void)ssl; + (void)kse; + + ret = NOT_COMPILED_IN; +#endif /* HAVE_ECC */ + + return ret; +} + +/* Generate a secret/key using the key share entry. + * + * ssl The SSL/TLS object. + * kse The key share entry holding peer data. + */ +static int TLSX_KeyShare_GenKey(WOLFSSL *ssl, KeyShareEntry *kse) +{ + /* Named FFHE groups have a bit set to identify them. */ + if ((kse->group & NAMED_DH_MASK) == NAMED_DH_MASK) + return TLSX_KeyShare_GenDhKey(ssl, kse); + if (kse->group == WOLFSSL_ECC_X25519) + return TLSX_KeyShare_GenX25519Key(ssl, kse); + return TLSX_KeyShare_GenEccKey(ssl, kse); +} + +/* Free the key share dynamic data. + * + * list The linked list of key share entry objects. + * heap The heap used for allocation. + */ +static void TLSX_KeyShare_FreeAll(KeyShareEntry* list, void* heap) +{ + KeyShareEntry* current; + + while ((current = list) != NULL) { + list = current->next; + if ((current->group & NAMED_DH_MASK) == 0) { + if (current->group == WOLFSSL_ECC_X25519) { +#ifdef HAVE_CURVE25519 + wc_curve25519_free((curve25519_key*)current->key); +#endif + } + else { +#ifdef HAVE_ECC + wc_ecc_free((ecc_key*)(current->key)); +#endif + } + } + if (current->key != NULL) + XFREE(current->key, heap, DYNAMIC_TYPE_PRIVATE_KEY); + XFREE(current->pubKey, heap, DYNAMIC_TYPE_PUBLIC_KEY); + XFREE(current->ke, heap, DYNAMIC_TYPE_PUBLIC_KEY); + XFREE(current, heap, DYNAMIC_TYPE_TLSX); + } + + (void)heap; +} + +/* Get the size of the encoded key share extension. + * + * list The linked list of key share extensions. + * msgType The type of the message this extension is being written into. + * returns the number of bytes of the encoded key share extension. + */ +static word16 TLSX_KeyShare_GetSize(KeyShareEntry* list, byte msgType) +{ + word16 len = 0; + byte isRequest = (msgType == client_hello); + KeyShareEntry* current; + + /* The named group the server wants to use. */ + if (msgType == hello_retry_request) + return OPAQUE16_LEN; + + /* List of key exchange groups. */ + if (isRequest) + len += OPAQUE16_LEN; + while ((current = list) != NULL) { + list = current->next; + + if (!isRequest && current->key == NULL) + continue; + + len += KE_GROUP_LEN + OPAQUE16_LEN + current->pubKeyLen; + } + + return len; +} + +/* Writes the key share extension into the output buffer. + * Assumes that the the output buffer is big enough to hold data. + * + * list The linked list of key share entries. + * output The buffer to write into. + * msgType The type of the message this extension is being written into. + * returns the number of bytes written into the buffer. + */ +static word16 TLSX_KeyShare_Write(KeyShareEntry* list, byte* output, + byte msgType) +{ + word16 i = 0; + byte isRequest = (msgType == client_hello); + KeyShareEntry* current; + + if (msgType == hello_retry_request) { + c16toa(list->group, output); + return OPAQUE16_LEN; + } + + /* ClientHello has a list but ServerHello is only the chosen. */ + if (isRequest) + i += OPAQUE16_LEN; + + /* Write out all in the list. */ + while ((current = list) != NULL) { + list = current->next; + + if (!isRequest && current->key == NULL) + continue; + + c16toa(current->group, &output[i]); + i += KE_GROUP_LEN; + c16toa((word16)(current->pubKeyLen), &output[i]); + i += OPAQUE16_LEN; + XMEMCPY(&output[i], current->pubKey, current->pubKeyLen); + i += (word16)current->pubKeyLen; + } + /* Write the length of the list if required. */ + if (isRequest) + c16toa(i - OPAQUE16_LEN, output); + + return i; +} + +/* Process the DH key share extension on the client side. + * + * ssl The SSL/TLS object. + * keyShareEntry The key share entry object to use to calculate shared secret. + * returns 0 on success and other values indicate failure. + */ +static int TLSX_KeyShare_ProcessDh(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) +{ +#ifndef NO_DH + int ret; + const DhParams* params; +#ifdef WOLFSSL_SMALL_STACK + DhKey* dhKey = NULL; +#else + DhKey dhKey[1]; +#endif + + switch (keyShareEntry->group) { + #ifdef HAVE_FFDHE_2048 + case WOLFSSL_FFDHE_2048: + params = wc_Dh_ffdhe2048_Get(); + break; + #endif + #ifdef HAVE_FFDHE_3072 + case WOLFSSL_FFDHE_3072: + params = wc_Dh_ffdhe3072_Get(); + break; + #endif + #ifdef HAVE_FFDHE_4096 + case WOLFSSL_FFDHE_4096: + params = wc_Dh_ffdhe4096_Get(); + break; + #endif + #ifdef HAVE_FFDHE_6144 + case WOLFSSL_FFDHE_6144: + params = wc_Dh_ffdhe6144_Get(); + break; + #endif + #ifdef HAVE_FFDHE_8192 + case WOLFSSL_FFDHE_8192: + params = wc_Dh_ffdhe8192_Get(); + break; + #endif + default: + return PEER_KEY_ERROR; + } + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Peer DH Key"); + WOLFSSL_BUFFER(keyShareEntry->ke, keyShareEntry->keLen); +#endif + +#ifdef WOLFSSL_SMALL_STACK + dhKey = (DhKey*)XMALLOC(sizeof(DhKey), ssl->heap, DYNAMIC_TYPE_DH); + if (dhKey == NULL) + return MEMORY_E; +#endif + + ret = wc_InitDhKey_ex(dhKey, ssl->heap, ssl->devId); + if (ret != 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(dhKey, ssl->heap, DYNAMIC_TYPE_DH); + #endif + return ret; + } + + /* Set key */ + ret = wc_DhSetKey(dhKey, (byte*)params->p, params->p_len, (byte*)params->g, + params->g_len); + if (ret != 0) { + wc_FreeDhKey(dhKey); + #ifdef WOLFSSL_SMALL_STACK + XFREE(dhKey, ssl->heap, DYNAMIC_TYPE_DH); + #endif + return ret; + } + + ret = wc_DhCheckPubKey(dhKey, keyShareEntry->ke, keyShareEntry->keLen); + if (ret != 0) { + wc_FreeDhKey(dhKey); + #ifdef WOLFSSL_SMALL_STACK + XFREE(dhKey, ssl->heap, DYNAMIC_TYPE_DH); + #endif + return PEER_KEY_ERROR; + } + + /* Derive secret from private key and peer's public key. */ + ret = wc_DhAgree(dhKey, + ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz, + (const byte*)keyShareEntry->key, keyShareEntry->keyLen, + keyShareEntry->ke, keyShareEntry->keLen); +#ifdef WOLFSSL_ASYNC_CRYPT + /* TODO: Make this function non-blocking */ + if (ret == WC_PENDING_E) { + ret = wc_AsyncWait(ret, &dhKey->asyncDev, WC_ASYNC_FLAG_NONE); + } +#endif + /* RFC 8446 Section 7.4.1: + * ... left-padded with zeros up to the size of the prime. ... + */ + if (params->p_len > ssl->arrays->preMasterSz) { + word32 diff = params->p_len - ssl->arrays->preMasterSz; + XMEMMOVE(ssl->arrays->preMasterSecret + diff, + ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz); + XMEMSET(ssl->arrays->preMasterSecret, 0, diff); + ssl->arrays->preMasterSz = params->p_len; + } + + ssl->options.dhKeySz = params->p_len; + + wc_FreeDhKey(dhKey); +#ifdef WOLFSSL_SMALL_STACK + XFREE(dhKey, ssl->heap, DYNAMIC_TYPE_DH); +#endif + if (keyShareEntry->key != NULL) { + XFREE(keyShareEntry->key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + keyShareEntry->key = NULL; + } + XFREE(keyShareEntry->pubKey, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + keyShareEntry->pubKey = NULL; + XFREE(keyShareEntry->ke, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + keyShareEntry->ke = NULL; + + return ret; +#else + (void)ssl; + (void)keyShareEntry; + return PEER_KEY_ERROR; +#endif +} + +/* Process the X25519 key share extension on the client side. + * + * ssl The SSL/TLS object. + * keyShareEntry The key share entry object to use to calculate shared secret. + * returns 0 on success and other values indicate failure. + */ +static int TLSX_KeyShare_ProcessX25519(WOLFSSL* ssl, + KeyShareEntry* keyShareEntry) +{ + int ret; + +#ifdef HAVE_CURVE25519 + curve25519_key* key = (curve25519_key*)keyShareEntry->key; + curve25519_key* peerX25519Key; + +#ifdef HAVE_ECC + if (ssl->peerEccKey != NULL) { + wc_ecc_free(ssl->peerEccKey); + ssl->peerEccKey = NULL; + } +#endif + + peerX25519Key = (curve25519_key*)XMALLOC(sizeof(curve25519_key), ssl->heap, + DYNAMIC_TYPE_TLSX); + if (peerX25519Key == NULL) { + WOLFSSL_MSG("PeerEccKey Memory error"); + return MEMORY_ERROR; + } + ret = wc_curve25519_init(peerX25519Key); + if (ret != 0) { + XFREE(peerX25519Key, ssl->heap, DYNAMIC_TYPE_TLSX); + return ret; + } +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Peer Curve25519 Key"); + WOLFSSL_BUFFER(keyShareEntry->ke, keyShareEntry->keLen); +#endif + + /* Point is validated by import function. */ + if (wc_curve25519_import_public_ex(keyShareEntry->ke, keyShareEntry->keLen, + peerX25519Key, + EC25519_LITTLE_ENDIAN) != 0) { + ret = ECC_PEERKEY_ERROR; + } + + if (ret == 0) { + ssl->ecdhCurveOID = ECC_X25519_OID; + + ret = wc_curve25519_shared_secret_ex(key, peerX25519Key, + ssl->arrays->preMasterSecret, + &ssl->arrays->preMasterSz, + EC25519_LITTLE_ENDIAN); + } + + wc_curve25519_free(peerX25519Key); + XFREE(peerX25519Key, ssl->heap, DYNAMIC_TYPE_TLSX); + wc_curve25519_free((curve25519_key*)keyShareEntry->key); + if (keyShareEntry->key != NULL) { + XFREE(keyShareEntry->key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + keyShareEntry->key = NULL; + } +#else + (void)ssl; + (void)keyShareEntry; + + ret = PEER_KEY_ERROR; +#endif /* HAVE_CURVE25519 */ + + return ret; +} + +/* Process the ECC key share extension on the client side. + * + * ssl The SSL/TLS object. + * keyShareEntry The key share entry object to use to calculate shared secret. + * returns 0 on success and other values indicate failure. + */ +static int TLSX_KeyShare_ProcessEcc(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) +{ + int ret; + +#ifdef HAVE_ECC + int curveId; + ecc_key* keyShareKey = (ecc_key*)keyShareEntry->key; + + if (ssl->peerEccKey != NULL) + wc_ecc_free(ssl->peerEccKey); + + ssl->peerEccKey = (ecc_key*)XMALLOC(sizeof(ecc_key), ssl->heap, + DYNAMIC_TYPE_ECC); + if (ssl->peerEccKey == NULL) { + WOLFSSL_MSG("PeerEccKey Memory error"); + return MEMORY_ERROR; + } + ret = wc_ecc_init_ex(ssl->peerEccKey, ssl->heap, ssl->devId); + if (ret != 0) + return ret; + + /* find supported curve */ + switch (keyShareEntry->group) { + #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP256R1: + curveId = ECC_SECP256R1; + break; + #endif /* !NO_ECC_SECP */ + #endif + #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP384R1: + curveId = ECC_SECP384R1; + break; + #endif /* !NO_ECC_SECP */ + #endif + #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP521R1: + curveId = ECC_SECP521R1; + break; + #endif /* !NO_ECC_SECP */ + #endif + #ifdef HAVE_X448 + case WOLFSSL_ECC_X448: + curveId = ECC_X448; + break; + #endif + default: + /* unsupported curve */ + return ECC_PEERKEY_ERROR; + } + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Peer ECC Key"); + WOLFSSL_BUFFER(keyShareEntry->ke, keyShareEntry->keLen); +#endif + + /* Point is validated by import function. */ + if (wc_ecc_import_x963_ex(keyShareEntry->ke, keyShareEntry->keLen, + ssl->peerEccKey, curveId) != 0) { + return ECC_PEERKEY_ERROR; + } + ssl->ecdhCurveOID = ssl->peerEccKey->dp->oidSum; + + do { + #if defined(WOLFSSL_ASYNC_CRYPT) + ret = wc_AsyncWait(ret, &keyShareKey->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) + ret = wc_ecc_shared_secret(keyShareKey, ssl->peerEccKey, + ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz); + } while (ret == WC_PENDING_E); + +#if 0 + /* TODO: Switch to support async here and use: */ + ret = EccSharedSecret(ssl, keyShareEntry->key, ssl->peerEccKey, + keyShareEntry->ke, &keyShareEntry->keLen, + ssl->arrays->preMasterSecret, &ssl->arrays->preMasterSz, + ssl->options.side + ); +#endif + + wc_ecc_free(ssl->peerEccKey); + XFREE(ssl->peerEccKey, ssl->heap, DYNAMIC_TYPE_ECC); + ssl->peerEccKey = NULL; + wc_ecc_free((ecc_key*)(keyShareEntry->key)); + if (keyShareEntry->key != NULL) { + XFREE(keyShareEntry->key, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY); + keyShareEntry->key = NULL; + } + +#else + (void)ssl; + (void)keyShareEntry; + + ret = PEER_KEY_ERROR; +#endif /* HAVE_ECC */ + + return ret; +} + +/* Process the key share extension on the client side. + * + * ssl The SSL/TLS object. + * keyShareEntry The key share entry object to use to calculate shared secret. + * returns 0 on success and other values indicate failure. + */ +static int TLSX_KeyShare_Process(WOLFSSL* ssl, KeyShareEntry* keyShareEntry) +{ + int ret; + +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + ssl->session.namedGroup = (byte)keyShareEntry->group; +#endif + /* Use Key Share Data from server. */ + if (keyShareEntry->group & NAMED_DH_MASK) + ret = TLSX_KeyShare_ProcessDh(ssl, keyShareEntry); + else if (keyShareEntry->group == WOLFSSL_ECC_X25519) + ret = TLSX_KeyShare_ProcessX25519(ssl, keyShareEntry); + else + ret = TLSX_KeyShare_ProcessEcc(ssl, keyShareEntry); + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("KE Secret"); + WOLFSSL_BUFFER(ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz); +#endif + + return ret; +} + +/* Parse an entry of the KeyShare extension. + * + * ssl The SSL/TLS object. + * input The extension data. + * length The length of the extension data. + * kse The new key share entry object. + * returns a positive number to indicate amount of data parsed and a negative + * number on error. + */ +static int TLSX_KeyShareEntry_Parse(WOLFSSL* ssl, byte* input, word16 length, + KeyShareEntry **kse) +{ + int ret; + word16 group; + word16 keLen; + int offset = 0; + byte* ke; + + if (length < OPAQUE16_LEN + OPAQUE16_LEN) + return BUFFER_ERROR; + /* Named group */ + ato16(&input[offset], &group); + offset += OPAQUE16_LEN; + /* Key exchange data - public key. */ + ato16(&input[offset], &keLen); + offset += OPAQUE16_LEN; + if (keLen == 0) + return INVALID_PARAMETER; + if (keLen > length - offset) + return BUFFER_ERROR; + + /* Store a copy in the key share object. */ + ke = (byte*)XMALLOC(keLen, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + if (ke == NULL) + return MEMORY_E; + XMEMCPY(ke, &input[offset], keLen); + + /* Populate a key share object in the extension. */ + ret = TLSX_KeyShare_Use(ssl, group, keLen, ke, kse); + if (ret != 0) { + XFREE(ke, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + return ret; + } + + /* Total length of the parsed data. */ + return offset + keLen; +} + +/* Searches the groups sent for the specified named group. + * + * ssl SSL/TLS object. + * name Group name to match. + * returns 1 when the extension has the group name and 0 otherwise. + */ +static int TLSX_KeyShare_Find(WOLFSSL* ssl, word16 group) +{ + TLSX* extension; + KeyShareEntry* list; + + extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); + if (extension == NULL) { + extension = TLSX_Find(ssl->ctx->extensions, TLSX_KEY_SHARE); + if (extension == NULL) + return 0; + } + + list = (KeyShareEntry*)extension->data; + while (list != NULL) { + if (list->group == group) + return 1; + list = list->next; + } + + return 0; +} + + +/* Searches the supported groups extension for the specified named group. + * + * ssl The SSL/TLS object. + * name The group name to match. + * returns 1 when the extension has the group name and 0 otherwise. + */ +static int TLSX_SupportedGroups_Find(WOLFSSL* ssl, word16 name) +{ +#ifdef HAVE_SUPPORTED_CURVES + TLSX* extension; + SupportedCurve* curve = NULL; + + if ((extension = TLSX_Find(ssl->extensions, + TLSX_SUPPORTED_GROUPS)) == NULL) { + if ((extension = TLSX_Find(ssl->ctx->extensions, + TLSX_SUPPORTED_GROUPS)) == NULL) { + return 0; + } + } + + for (curve = (SupportedCurve*)extension->data; curve; curve = curve->next) { + if (curve->name == name) + return 1; + } +#endif + + (void)ssl; + (void)name; + + return 0; +} + + +/* Parse the KeyShare extension. + * Different formats in different messages. + * + * ssl The SSL/TLS object. + * input The extension data. + * length The length of the extension data. + * msgType The type of the message this extension is being parsed from. + * returns 0 on success and other values indicate failure. + */ +static int TLSX_KeyShare_Parse(WOLFSSL* ssl, byte* input, word16 length, + byte msgType) +{ + int ret; + KeyShareEntry *keyShareEntry = NULL; + word16 group; + + if (msgType == client_hello) { + int offset = 0; + word16 len; + TLSX* extension; + + /* Add a KeyShare extension if it doesn't exist. */ + extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); + if (extension == NULL) { + /* Push new KeyShare extension. */ + ret = TLSX_Push(&ssl->extensions, TLSX_KEY_SHARE, NULL, ssl->heap); + if (ret != 0) + return ret; + } + + if (length < OPAQUE16_LEN) + return BUFFER_ERROR; + + /* ClientHello contains zero or more key share entries. */ + ato16(input, &len); + if (len != length - OPAQUE16_LEN) + return BUFFER_ERROR; + offset += OPAQUE16_LEN; + + while (offset < (int)length) { + ret = TLSX_KeyShareEntry_Parse(ssl, &input[offset], length - offset, + &keyShareEntry); + if (ret < 0) + return ret; + + offset += ret; + } + + ret = 0; + } + else if (msgType == server_hello) { + int len; + + if (length < OPAQUE16_LEN) + return BUFFER_ERROR; + + /* The data is the named group the server wants to use. */ + ato16(input, &group); + + /* Check the selected group was supported by ClientHello extensions. */ + if (!TLSX_SupportedGroups_Find(ssl, group)) + return BAD_KEY_SHARE_DATA; + + /* Check if the group was sent. */ + if (!TLSX_KeyShare_Find(ssl, group)) + return BAD_KEY_SHARE_DATA; + + /* ServerHello contains one key share entry. */ + len = TLSX_KeyShareEntry_Parse(ssl, input, length, &keyShareEntry); + if (len != (int)length) + return BUFFER_ERROR; + + /* Not in list sent if there isn't a private key. */ + if (keyShareEntry == NULL || keyShareEntry->key == NULL) + return BAD_KEY_SHARE_DATA; + + /* Process the entry to calculate the secret. */ + ret = TLSX_KeyShare_Process(ssl, keyShareEntry); + if (ret == 0) + ssl->session.namedGroup = ssl->namedGroup = group; + } + else if (msgType == hello_retry_request) { + if (length != OPAQUE16_LEN) + return BUFFER_ERROR; + + /* The data is the named group the server wants to use. */ + ato16(input, &group); + + /* Check the selected group was supported by ClientHello extensions. */ + if (!TLSX_SupportedGroups_Find(ssl, group)) + return BAD_KEY_SHARE_DATA; + + /* Check if the group was sent. */ + if (TLSX_KeyShare_Find(ssl, group)) + return BAD_KEY_SHARE_DATA; + + /* Clear out unusable key shares. */ + ret = TLSX_KeyShare_Empty(ssl); + if (ret != 0) + return ret; + + /* Try to use the server's group. */ + ret = TLSX_KeyShare_Use(ssl, group, 0, NULL, NULL); + } + else { + /* Not a message type that is allowed to have this extension. */ + return SANITY_MSG_E; + } + + return ret; +} + +/* Create a new key share entry and put it into the list. + * + * list The linked list of key share entries. + * group The named group. + * heap The memory to allocate with. + * keyShareEntry The new key share entry object. + * returns 0 on success and other values indicate failure. + */ +static int TLSX_KeyShare_New(KeyShareEntry** list, int group, void *heap, + KeyShareEntry** keyShareEntry) +{ + KeyShareEntry* kse; + + kse = (KeyShareEntry*)XMALLOC(sizeof(KeyShareEntry), heap, + DYNAMIC_TYPE_TLSX); + if (kse == NULL) + return MEMORY_E; + + XMEMSET(kse, 0, sizeof(*kse)); + kse->group = (word16)group; + + /* Add it to the back and maintain the links. */ + while (*list != NULL) + list = &((*list)->next); + *list = kse; + *keyShareEntry = kse; + + (void)heap; + + return 0; +} + +/* Use the data to create a new key share object in the extensions. + * + * ssl The SSL/TLS object. + * group The named group. + * len The length of the public key data. + * data The public key data. + * kse The new key share entry object. + * returns 0 on success and other values indicate failure. + */ +int TLSX_KeyShare_Use(WOLFSSL* ssl, word16 group, word16 len, byte* data, + KeyShareEntry **kse) +{ + int ret = 0; + TLSX* extension; + KeyShareEntry* keyShareEntry = NULL; + + /* Find the KeyShare extension if it exists. */ + extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); + if (extension == NULL) { + /* Push new KeyShare extension. */ + ret = TLSX_Push(&ssl->extensions, TLSX_KEY_SHARE, NULL, ssl->heap); + if (ret != 0) + return ret; + + extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); + if (extension == NULL) + return MEMORY_E; + } + extension->resp = 0; + + /* Try to find the key share entry with this group. */ + keyShareEntry = (KeyShareEntry*)extension->data; + while (keyShareEntry != NULL) { + if (keyShareEntry->group == group) + break; + keyShareEntry = keyShareEntry->next; + } + + /* Create a new key share entry if not found. */ + if (keyShareEntry == NULL) { + ret = TLSX_KeyShare_New((KeyShareEntry**)&extension->data, group, + ssl->heap, &keyShareEntry); + if (ret != 0) + return ret; + } + + if (data != NULL) { + if (keyShareEntry->ke != NULL) { + XFREE(keyShareEntry->ke, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY); + } + keyShareEntry->ke = data; + keyShareEntry->keLen = len; + } + else { + /* Generate a key pair. */ + ret = TLSX_KeyShare_GenKey(ssl, keyShareEntry); + if (ret != 0) + return ret; + } + + if (kse != NULL) + *kse = keyShareEntry; + + return 0; +} + +/* Set an empty Key Share extension. + * + * ssl The SSL/TLS object. + * returns 0 on success and other values indicate failure. + */ +int TLSX_KeyShare_Empty(WOLFSSL* ssl) +{ + int ret = 0; + TLSX* extension; + + /* Find the KeyShare extension if it exists. */ + extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); + if (extension == NULL) { + /* Push new KeyShare extension. */ + ret = TLSX_Push(&ssl->extensions, TLSX_KEY_SHARE, NULL, ssl->heap); + } + else if (extension->data != NULL) { + TLSX_KeyShare_FreeAll((KeyShareEntry*)extension->data, ssl->heap); + extension->data = NULL; + } + + return ret; +} + +/* Returns whether this group is supported. + * + * namedGroup The named group to check. + * returns 1 when supported or 0 otherwise. + */ +static int TLSX_KeyShare_IsSupported(int namedGroup) +{ + switch (namedGroup) { + #ifdef HAVE_FFDHE_2048 + case WOLFSSL_FFDHE_2048: + break; + #endif + #ifdef HAVE_FFDHE_3072 + case WOLFSSL_FFDHE_3072: + break; + #endif + #ifdef HAVE_FFDHE_4096 + case WOLFSSL_FFDHE_4096: + break; + #endif + #ifdef HAVE_FFDHE_6144 + case WOLFSSL_FFDHE_6144: + break; + #endif + #ifdef HAVE_FFDHE_8192 + case WOLFSSL_FFDHE_8192: + break; + #endif + #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP256R1: + break; + #endif /* !NO_ECC_SECP */ + #endif + #ifdef HAVE_CURVE25519 + case WOLFSSL_ECC_X25519: + break; + #endif + #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP384R1: + break; + #endif /* !NO_ECC_SECP */ + #endif + #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + case WOLFSSL_ECC_SECP521R1: + break; + #endif /* !NO_ECC_SECP */ + #endif + #ifdef HAVE_X448 + case WOLFSSL_ECC_X448: + break; + #endif + default: + return 0; + } + + return 1; +} + +/* Examines the application specified group ranking and returns the rank of the + * group. + * If no group ranking set then all groups are rank 0 (highest). + * + * ssl The SSL/TLS object. + * group The group to check ranking for. + * returns ranking from 0 to MAX_GROUP_COUNT-1 or -1 when group not in list. + */ +static int TLSX_KeyShare_GroupRank(WOLFSSL* ssl, int group) +{ + byte i; + + if (ssl->numGroups == 0) { +#if defined(HAVE_ECC) && defined(HAVE_SUPPORTED_CURVES) + #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + ssl->group[ssl->numGroups++] = WOLFSSL_ECC_SECP256R1; + #endif + #endif +#endif + #ifndef HAVE_FIPS + #if defined(HAVE_CURVE25519) + ssl->group[ssl->numGroups++] = WOLFSSL_ECC_X25519; + #endif + #endif +#if defined(HAVE_ECC) && defined(HAVE_SUPPORTED_CURVES) + #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + ssl->group[ssl->numGroups++] = WOLFSSL_ECC_SECP384R1; + #endif + #endif + #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + ssl->group[ssl->numGroups++] = WOLFSSL_ECC_SECP521R1; + #endif + #endif +#endif + /* Add FFDHE supported groups. */ + #ifdef HAVE_FFDHE_2048 + ssl->group[ssl->numGroups++] = WOLFSSL_FFDHE_2048; + #endif + #ifdef HAVE_FFDHE_3072 + ssl->group[ssl->numGroups++] = WOLFSSL_FFDHE_3072; + #endif + #ifdef HAVE_FFDHE_4096 + ssl->group[ssl->numGroups++] = WOLFSSL_FFDHE_4096; + #endif + #ifdef HAVE_FFDHE_6144 + ssl->group[ssl->numGroups++] = WOLFSSL_FFDHE_6144; + #endif + #ifdef HAVE_FFDHE_8192 + ssl->group[ssl->numGroups++] = WOLFSSL_FFDHE_8192; + #endif + } + + for (i = 0; i < ssl->numGroups; i++) + if (ssl->group[i] == (word16)group) + return i; + + return -1; +} + +/* Set a key share that is supported by the client into extensions. + * + * ssl The SSL/TLS object. + * returns BAD_KEY_SHARE_DATA if no supported group has a key share, + * 0 if a supported group has a key share and other values indicate an error. + */ +static int TLSX_KeyShare_SetSupported(WOLFSSL* ssl) +{ + int ret; +#ifdef HAVE_SUPPORTED_CURVES + TLSX* extension; + SupportedCurve* curve = NULL; + SupportedCurve* preferredCurve = NULL; + int preferredRank = WOLFSSL_MAX_GROUP_COUNT; + int rank; + + extension = TLSX_Find(ssl->extensions, TLSX_SUPPORTED_GROUPS); + if (extension != NULL) + curve = (SupportedCurve*)extension->data; + /* Use server's preference order. */ + for (; curve != NULL; curve = curve->next) { + if (!TLSX_KeyShare_IsSupported(curve->name)) + continue; + + rank = TLSX_KeyShare_GroupRank(ssl, curve->name); + if (rank == -1) + continue; + if (rank < preferredRank) { + preferredCurve = curve; + preferredRank = rank; + } + } + curve = preferredCurve; + + if (curve == NULL) + return BAD_KEY_SHARE_DATA; + + /* Delete the old key share data list. */ + extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); + if (extension != NULL) { + TLSX_KeyShare_FreeAll((KeyShareEntry*)extension->data, ssl->heap); + extension->data = NULL; + } + + /* Add in the chosen group. */ + ret = TLSX_KeyShare_Use(ssl, curve->name, 0, NULL, NULL); + if (ret != 0) + return ret; + + /* Set extension to be in reponse. */ + extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); + extension->resp = 1; +#else + + (void)ssl; + ret = NOT_COMPILED_IN; +#endif + + return ret; +} + +/* Ensure there is a key pair that can be used for key exchange. + * + * ssl The SSL/TLS object. + * returns 0 on success and other values indicate failure. + */ +int TLSX_KeyShare_Establish(WOLFSSL *ssl) +{ + int ret; + TLSX* extension; + KeyShareEntry* clientKSE = NULL; + KeyShareEntry* serverKSE; + KeyShareEntry* list = NULL; + KeyShareEntry* preferredKSE = NULL; + int preferredRank = WOLFSSL_MAX_GROUP_COUNT; + int rank; + + /* Find the KeyShare extension if it exists. */ + extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); + if (extension != NULL) + list = (KeyShareEntry*)extension->data; + + if (extension && extension->resp == 1) + return 0; + + /* Use server's preference order. */ + for (clientKSE = list; clientKSE != NULL; clientKSE = clientKSE->next) { + if (clientKSE->ke == NULL) + continue; + + /* Check consistency now - extensions in any order. */ + if (!TLSX_SupportedGroups_Find(ssl, clientKSE->group)) + return BAD_KEY_SHARE_DATA; + + #ifdef OPENSSL_EXTRA + if ((clientKSE->group & NAMED_DH_MASK) == 0) { + /* Check if server supports group. */ + if (ssl->ctx->disabledCurves & (1 << clientKSE->group)) + continue; + } + #endif + if (!TLSX_KeyShare_IsSupported(clientKSE->group)) + continue; + + rank = TLSX_KeyShare_GroupRank(ssl, clientKSE->group); + if (rank == -1) + continue; + if (rank < preferredRank) { + preferredKSE = clientKSE; + preferredRank = rank; + } + } + clientKSE = preferredKSE; + + /* No supported group found - send HelloRetryRequest. */ + if (clientKSE == NULL) { + ret = TLSX_KeyShare_SetSupported(ssl); + /* Return KEY_SHARE_ERROR to indicate HelloRetryRequest required. */ + if (ret == 0) + return KEY_SHARE_ERROR; + return ret; + } + + list = NULL; + /* Generate a new key pair. */ + ret = TLSX_KeyShare_New(&list, clientKSE->group, ssl->heap, &serverKSE); + if (ret != 0) + return ret; + + if (clientKSE->key == NULL) { + ret = TLSX_KeyShare_GenKey(ssl, serverKSE); + if (ret != 0) + return ret; + } + else { + serverKSE->key = clientKSE->key; + serverKSE->keyLen = clientKSE->keyLen; + serverKSE->pubKey = clientKSE->pubKey; + serverKSE->pubKeyLen = clientKSE->pubKeyLen; + clientKSE->key = NULL; + clientKSE->pubKey = NULL; + } + serverKSE->ke = clientKSE->ke; + serverKSE->keLen = clientKSE->keLen; + clientKSE->ke = NULL; + clientKSE->keLen = 0; + + TLSX_KeyShare_FreeAll((KeyShareEntry*)extension->data, ssl->heap); + extension->data = (void *)serverKSE; + + extension->resp = 1; + + return 0; +} + +/* Derive the shared secret of the key exchange. + * + * ssl The SSL/TLS object. + * returns 0 on success and other values indicate failure. + */ +int TLSX_KeyShare_DeriveSecret(WOLFSSL *ssl) +{ + int ret; + TLSX* extension; + KeyShareEntry* list = NULL; + + /* Find the KeyShare extension if it exists. */ + extension = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); + if (extension != NULL) + list = (KeyShareEntry*)extension->data; + + if (list == NULL) + return KEY_SHARE_ERROR; + + /* Calculate secret. */ + ret = TLSX_KeyShare_Process(ssl, list); + if (ret != 0) + return ret; + + return ret; +} + +#define KS_FREE_ALL TLSX_KeyShare_FreeAll +#define KS_GET_SIZE TLSX_KeyShare_GetSize +#define KS_WRITE TLSX_KeyShare_Write +#define KS_PARSE TLSX_KeyShare_Parse + +#else + +#define KS_FREE_ALL(a, b) +#define KS_GET_SIZE(a, b) 0 +#define KS_WRITE(a, b, c) 0 +#define KS_PARSE(a, b, c, d) 0 + +#endif /* WOLFSSL_TLS13 */ + +/******************************************************************************/ +/* Pre-Shared Key */ +/******************************************************************************/ + +#if defined(WOLFSSL_TLS13) && (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)) +/* Free the pre-shared key dynamic data. + * + * list The linked list of key share entry objects. + * heap The heap used for allocation. + */ +static void TLSX_PreSharedKey_FreeAll(PreSharedKey* list, void* heap) +{ + PreSharedKey* current; + + while ((current = list) != NULL) { + list = current->next; + XFREE(current->identity, heap, DYNAMIC_TYPE_TLSX); + XFREE(current, heap, DYNAMIC_TYPE_TLSX); + } + + (void)heap; +} + +/* Get the size of the encoded pre shared key extension. + * + * list The linked list of pre-shared key extensions. + * msgType The type of the message this extension is being written into. + * returns the number of bytes of the encoded pre-shared key extension or + * SANITY_MSG_E to indicate invalid message type. + */ +static int TLSX_PreSharedKey_GetSize(PreSharedKey* list, byte msgType, + word16* pSz) +{ + if (msgType == client_hello) { + /* Length of identities + Length of binders. */ + word16 len = OPAQUE16_LEN + OPAQUE16_LEN; + while (list != NULL) { + /* Each entry has: identity, ticket age and binder. */ + len += OPAQUE16_LEN + list->identityLen + OPAQUE32_LEN + + OPAQUE8_LEN + list->binderLen; + list = list->next; + } + *pSz += len; + return 0; + } + + if (msgType == server_hello) { + *pSz += OPAQUE16_LEN; + return 0; + } + + return SANITY_MSG_E; +} + +/* The number of bytes to be written for the binders. + * + * list The linked list of pre-shared key extensions. + * msgType The type of the message this extension is being written into. + * returns the number of bytes of the encoded pre-shared key extension or + * SANITY_MSG_E to indicate invalid message type. + */ +int TLSX_PreSharedKey_GetSizeBinders(PreSharedKey* list, byte msgType, + word16* pSz) +{ + word16 len; + + if (msgType != client_hello) + return SANITY_MSG_E; + + /* Length of all binders. */ + len = OPAQUE16_LEN; + while (list != NULL) { + len += OPAQUE8_LEN + list->binderLen; + list = list->next; + } + + *pSz = len; + return 0; +} + +/* Writes the pre-shared key extension into the output buffer - binders only. + * Assumes that the the output buffer is big enough to hold data. + * + * list The linked list of key share entries. + * output The buffer to write into. + * msgType The type of the message this extension is being written into. + * returns the number of bytes written into the buffer. + */ +int TLSX_PreSharedKey_WriteBinders(PreSharedKey* list, byte* output, + byte msgType, word16* pSz) +{ + PreSharedKey* current = list; + word16 idx = 0; + word16 lenIdx; + word16 len; + + if (msgType != client_hello) + return SANITY_MSG_E; + + /* Skip length of all binders. */ + lenIdx = idx; + idx += OPAQUE16_LEN; + while (current != NULL) { + /* Binder data length. */ + output[idx++] = current->binderLen; + /* Binder data. */ + XMEMCPY(output + idx, current->binder, current->binderLen); + idx += current->binderLen; + + current = current->next; + } + /* Length of the binders. */ + len = idx - lenIdx - OPAQUE16_LEN; + c16toa(len, output + lenIdx); + + *pSz = idx; + return 0; +} + + +/* Writes the pre-shared key extension into the output buffer. + * Assumes that the the output buffer is big enough to hold data. + * + * list The linked list of key share entries. + * output The buffer to write into. + * msgType The type of the message this extension is being written into. + * returns the number of bytes written into the buffer. + */ +static int TLSX_PreSharedKey_Write(PreSharedKey* list, byte* output, + byte msgType, word16* pSz) +{ + if (msgType == client_hello) { + PreSharedKey* current = list; + word16 idx = 0; + word16 lenIdx; + word16 len; + int ret; + + /* Write identites only. Binders after HMACing over this. */ + lenIdx = idx; + idx += OPAQUE16_LEN; + while (current != NULL) { + /* Identity length */ + c16toa(current->identityLen, output + idx); + idx += OPAQUE16_LEN; + /* Identity data */ + XMEMCPY(output + idx, current->identity, current->identityLen); + idx += current->identityLen; + + /* Obfuscated ticket age. */ + c32toa(current->ticketAge, output + idx); + idx += OPAQUE32_LEN; + + current = current->next; + } + /* Length of the identites. */ + len = idx - lenIdx - OPAQUE16_LEN; + c16toa(len, output + lenIdx); + + /* Don't include binders here. + * The binders are based on the hash of all the ClientHello data up to + * and include the identities written above. + */ + ret = TLSX_PreSharedKey_GetSizeBinders(list, msgType, &len); + if (ret < 0) + return ret; + *pSz += idx + len; + } + else if (msgType == server_hello) { + word16 i; + + /* Find the index of the chosen identity. */ + for (i=0; list != NULL && !list->chosen; i++) + list = list->next; + if (list == NULL) + return BUILD_MSG_ERROR; + + /* The index of the identity chosen by the server from the list supplied + * by the client. + */ + c16toa(i, output); + *pSz += OPAQUE16_LEN; + } + else + return SANITY_MSG_E; + + return 0; +} + +/* Parse the pre-shared key extension. + * Different formats in different messages. + * + * ssl The SSL/TLS object. + * input The extension data. + * length The length of the extension data. + * msgType The type of the message this extension is being parsed from. + * returns 0 on success and other values indicate failure. + */ +static int TLSX_PreSharedKey_Parse(WOLFSSL* ssl, byte* input, word16 length, + byte msgType) +{ + TLSX* extension; + PreSharedKey* list; + + if (msgType == client_hello) { + int ret; + word16 len; + word16 idx = 0; + + TLSX_Remove(&ssl->extensions, TLSX_PRE_SHARED_KEY, ssl->heap); + + /* Length of identities and of binders. */ + if (length - idx < OPAQUE16_LEN + OPAQUE16_LEN) + return BUFFER_E; + + /* Length of identities. */ + ato16(input + idx, &len); + idx += OPAQUE16_LEN; + if (len < MIN_PSK_ID_LEN || length - idx < len) + return BUFFER_E; + + /* Create a pre-shared key object for each identity. */ + while (len > 0) { + byte* identity; + word16 identityLen; + word32 age; + + if (len < OPAQUE16_LEN) + return BUFFER_E; + + /* Length of identity. */ + ato16(input + idx, &identityLen); + idx += OPAQUE16_LEN; + if (len < OPAQUE16_LEN + identityLen + OPAQUE32_LEN || + identityLen > MAX_PSK_ID_LEN) + return BUFFER_E; + /* Cache identity pointer. */ + identity = input + idx; + idx += identityLen; + /* Ticket age. */ + ato32(input + idx, &age); + idx += OPAQUE32_LEN; + + ret = TLSX_PreSharedKey_Use(ssl, identity, identityLen, age, no_mac, + 0, 0, 1, NULL); + if (ret != 0) + return ret; + + /* Done with this identity. */ + len -= OPAQUE16_LEN + identityLen + OPAQUE32_LEN; + } + + /* Find the list of identities sent to server. */ + extension = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY); + if (extension == NULL) + return PSK_KEY_ERROR; + list = (PreSharedKey*)extension->data; + + /* Length of binders. */ + ato16(input + idx, &len); + idx += OPAQUE16_LEN; + if (len < MIN_PSK_BINDERS_LEN || length - idx < len) + return BUFFER_E; + + /* Set binder for each identity. */ + while (list != NULL && len > 0) { + /* Length of binder */ + list->binderLen = input[idx++]; + if (list->binderLen < WC_SHA256_DIGEST_SIZE || + list->binderLen > WC_MAX_DIGEST_SIZE) + return BUFFER_E; + if (len < OPAQUE8_LEN + list->binderLen) + return BUFFER_E; + + /* Copy binder into static buffer. */ + XMEMCPY(list->binder, input + idx, list->binderLen); + idx += list->binderLen; + + /* Done with binder entry. */ + len -= OPAQUE8_LEN + list->binderLen; + + /* Next identity. */ + list = list->next; + } + if (list != NULL || len != 0) + return BUFFER_E; + + return 0; + } + + if (msgType == server_hello) { + word16 idx; + + /* Index of identity chosen by server. */ + if (length != OPAQUE16_LEN) + return BUFFER_E; + ato16(input, &idx); + + #ifdef WOLFSSL_EARLY_DATA + ssl->options.pskIdIndex = idx + 1; + #endif + + /* Find the list of identities sent to server. */ + extension = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY); + if (extension == NULL) + return PSK_KEY_ERROR; + list = (PreSharedKey*)extension->data; + + /* Mark the identity as chosen. */ + for (; list != NULL && idx > 0; idx--) + list = list->next; + if (list == NULL) + return PSK_KEY_ERROR; + list->chosen = 1; + + #ifdef HAVE_SESSION_TICKET + if (list->resumption) { + /* Check that the session's details are the same as the server's. */ + if (ssl->options.cipherSuite0 != ssl->session.cipherSuite0 || + ssl->options.cipherSuite != ssl->session.cipherSuite || + ssl->session.version.major != ssl->ctx->method->version.major || + ssl->session.version.minor != ssl->ctx->method->version.minor) { + return PSK_KEY_ERROR; + } + } + #endif + + return 0; + } + + return SANITY_MSG_E; +} + +/* Create a new pre-shared key and put it into the list. + * + * list The linked list of pre-shared key. + * identity The identity. + * len The length of the identity data. + * heap The memory to allocate with. + * preSharedKey The new pre-shared key object. + * returns 0 on success and other values indicate failure. + */ +static int TLSX_PreSharedKey_New(PreSharedKey** list, byte* identity, + word16 len, void *heap, + PreSharedKey** preSharedKey) +{ + PreSharedKey* psk; + + psk = (PreSharedKey*)XMALLOC(sizeof(PreSharedKey), heap, DYNAMIC_TYPE_TLSX); + if (psk == NULL) + return MEMORY_E; + XMEMSET(psk, 0, sizeof(*psk)); + + /* Make a copy of the identity data. */ + psk->identity = (byte*)XMALLOC(len, heap, DYNAMIC_TYPE_TLSX); + if (psk->identity == NULL) { + XFREE(psk, heap, DYNAMIC_TYPE_TLSX); + return MEMORY_E; + } + XMEMCPY(psk->identity, identity, len); + psk->identityLen = len; + + /* Add it to the end and maintain the links. */ + while (*list != NULL) + list = &((*list)->next); + *list = psk; + *preSharedKey = psk; + + return 0; +} + +static WC_INLINE byte GetHmacLength(int hmac) +{ + switch (hmac) { + #ifndef NO_SHA256 + case sha256_mac: + return WC_SHA256_DIGEST_SIZE; + #endif + #ifdef WOLFSSL_SHA384 + case sha384_mac: + return WC_SHA384_DIGEST_SIZE; + #endif + #ifdef WOLFSSL_SHA512 + case sha512_mac: + return WC_SHA512_DIGEST_SIZE; + #endif + } + return 0; +} + +/* Use the data to create a new pre-shared key object in the extensions. + * + * ssl The SSL/TLS object. + * identity The identity. + * len The length of the identity data. + * age The age of the identity. + * hmac The HMAC algorithm. + * ciphersuite0 The first byte of the ciphersuite to use. + * ciphersuite The second byte of the ciphersuite to use. + * resumption The PSK is for resumption of a session. + * preSharedKey The new pre-shared key object. + * returns 0 on success and other values indicate failure. + */ +int TLSX_PreSharedKey_Use(WOLFSSL* ssl, byte* identity, word16 len, word32 age, + byte hmac, byte cipherSuite0, + byte cipherSuite, byte resumption, + PreSharedKey **preSharedKey) +{ + int ret = 0; + TLSX* extension; + PreSharedKey* psk = NULL; + + /* Find the pre-shared key extension if it exists. */ + extension = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY); + if (extension == NULL) { + /* Push new pre-shared key extension. */ + ret = TLSX_Push(&ssl->extensions, TLSX_PRE_SHARED_KEY, NULL, ssl->heap); + if (ret != 0) + return ret; + + extension = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY); + if (extension == NULL) + return MEMORY_E; + } + + /* Try to find the pre-shared key with this identity. */ + psk = (PreSharedKey*)extension->data; + while (psk != NULL) { + if ((psk->identityLen == len) && + (XMEMCMP(psk->identity, identity, len) == 0)) { + break; + } + psk = psk->next; + } + + /* Create a new pre-shared key object if not found. */ + if (psk == NULL) { + ret = TLSX_PreSharedKey_New((PreSharedKey**)&extension->data, identity, + len, ssl->heap, &psk); + if (ret != 0) + return ret; + } + + /* Update/set age and HMAC algorithm. */ + psk->ticketAge = age; + psk->hmac = hmac; + psk->cipherSuite0 = cipherSuite0; + psk->cipherSuite = cipherSuite; + psk->resumption = resumption; + psk->binderLen = GetHmacLength(psk->hmac); + + if (preSharedKey != NULL) + *preSharedKey = psk; + + return 0; +} + +#define PSK_FREE_ALL TLSX_PreSharedKey_FreeAll +#define PSK_GET_SIZE TLSX_PreSharedKey_GetSize +#define PSK_WRITE TLSX_PreSharedKey_Write +#define PSK_PARSE TLSX_PreSharedKey_Parse + +#else + +#define PSK_FREE_ALL(a, b) +#define PSK_GET_SIZE(a, b, c) 0 +#define PSK_WRITE(a, b, c, d) 0 +#define PSK_PARSE(a, b, c, d) 0 + +#endif + +/******************************************************************************/ +/* PSK Key Exchange Modes */ +/******************************************************************************/ + +#if defined(WOLFSSL_TLS13) && (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)) +/* Get the size of the encoded PSK KE modes extension. + * Only in ClientHello. + * + * modes The PSK KE mode bit string. + * msgType The type of the message this extension is being written into. + * returns the number of bytes of the encoded PSK KE mode extension. + */ +static int TLSX_PskKeModes_GetSize(byte modes, byte msgType, word16* pSz) +{ + if (msgType == client_hello) { + /* Format: Len | Modes* */ + word16 len = OPAQUE8_LEN; + /* Check whether each possible mode is to be written. */ + if (modes & (1 << PSK_KE)) + len += OPAQUE8_LEN; + if (modes & (1 << PSK_DHE_KE)) + len += OPAQUE8_LEN; + *pSz += len; + return 0; + } + + return SANITY_MSG_E; +} + +/* Writes the PSK KE modes extension into the output buffer. + * Assumes that the the output buffer is big enough to hold data. + * Only in ClientHello. + * + * modes The PSK KE mode bit string. + * output The buffer to write into. + * msgType The type of the message this extension is being written into. + * returns the number of bytes written into the buffer. + */ +static int TLSX_PskKeModes_Write(byte modes, byte* output, byte msgType, + word16* pSz) +{ + if (msgType == client_hello) { + /* Format: Len | Modes* */ + int idx = OPAQUE8_LEN; + + /* Write out each possible mode. */ + if (modes & (1 << PSK_KE)) + output[idx++] = PSK_KE; + if (modes & (1 << PSK_DHE_KE)) + output[idx++] = PSK_DHE_KE; + /* Write out length of mode list. */ + output[0] = idx - OPAQUE8_LEN; + + *pSz += idx; + return 0; + } + + return SANITY_MSG_E; +} + +/* Parse the PSK KE modes extension. + * Only in ClientHello. + * + * ssl The SSL/TLS object. + * input The extension data. + * length The length of the extension data. + * msgType The type of the message this extension is being parsed from. + * returns 0 on success and other values indicate failure. + */ +static int TLSX_PskKeModes_Parse(WOLFSSL* ssl, byte* input, word16 length, + byte msgType) +{ + int ret; + + if (msgType == client_hello) { + /* Format: Len | Modes* */ + int idx = 0; + word16 len; + byte modes = 0; + + /* Ensure length byte exists. */ + if (length < OPAQUE8_LEN) + return BUFFER_E; + + /* Get length of mode list and ensure that is the only data. */ + len = input[0]; + if (length - OPAQUE8_LEN != len) + return BUFFER_E; + + idx = OPAQUE8_LEN; + /* Set a bit for each recognized modes. */ + while (len > 0) { + /* Ignore unrecognized modes. */ + if (input[idx] <= PSK_DHE_KE) + modes |= 1 << input[idx]; + idx++; + len--; + } + + ret = TLSX_PskKeModes_Use(ssl, modes); + if (ret != 0) + return ret; + + return 0; + } + + return SANITY_MSG_E; +} + +/* Use the data to create a new PSK Key Exchange Modes object in the extensions. + * + * ssl The SSL/TLS object. + * modes The PSK key exchange modes. + * returns 0 on success and other values indicate failure. + */ +int TLSX_PskKeModes_Use(WOLFSSL* ssl, byte modes) +{ + int ret = 0; + TLSX* extension; + + /* Find the PSK key exchange modes extension if it exists. */ + extension = TLSX_Find(ssl->extensions, TLSX_PSK_KEY_EXCHANGE_MODES); + if (extension == NULL) { + /* Push new PSK key exchange modes extension. */ + ret = TLSX_Push(&ssl->extensions, TLSX_PSK_KEY_EXCHANGE_MODES, NULL, + ssl->heap); + if (ret != 0) + return ret; + + extension = TLSX_Find(ssl->extensions, TLSX_PSK_KEY_EXCHANGE_MODES); + if (extension == NULL) + return MEMORY_E; + } + + extension->val = modes; + + return 0; +} + +#define PKM_GET_SIZE TLSX_PskKeModes_GetSize +#define PKM_WRITE TLSX_PskKeModes_Write +#define PKM_PARSE TLSX_PskKeModes_Parse + +#else + +#define PKM_GET_SIZE(a, b, c) 0 +#define PKM_WRITE(a, b, c, d) 0 +#define PKM_PARSE(a, b, c, d) 0 + +#endif + +/******************************************************************************/ +/* Post-Handshake Authentication */ +/******************************************************************************/ + +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) +/* Get the size of the encoded Post-Handshake Authentication extension. + * Only in ClientHello. + * + * msgType The type of the message this extension is being written into. + * returns the number of bytes of the encoded Post-Handshake Authentication + * extension. + */ +static int TLSX_PostHandAuth_GetSize(byte msgType, word16* pSz) +{ + if (msgType == client_hello) { + *pSz += 0; + return 0; + } + + return SANITY_MSG_E; +} + +/* Writes the Post-Handshake Authentication extension into the output buffer. + * Assumes that the the output buffer is big enough to hold data. + * Only in ClientHello. + * + * output The buffer to write into. + * msgType The type of the message this extension is being written into. + * returns the number of bytes written into the buffer. + */ +static int TLSX_PostHandAuth_Write(byte* output, byte msgType, word16* pSz) +{ + (void)output; + + if (msgType == client_hello) { + *pSz += 0; + return 0; + } + + return SANITY_MSG_E; +} + +/* Parse the Post-Handshake Authentication extension. + * Only in ClientHello. + * + * ssl The SSL/TLS object. + * input The extension data. + * length The length of the extension data. + * msgType The type of the message this extension is being parsed from. + * returns 0 on success and other values indicate failure. + */ +static int TLSX_PostHandAuth_Parse(WOLFSSL* ssl, byte* input, word16 length, + byte msgType) +{ + (void)input; + + if (msgType == client_hello) { + /* Ensure extension is empty. */ + if (length != 0) + return BUFFER_E; + + ssl->options.postHandshakeAuth = 1; + return 0; + } + + return SANITY_MSG_E; +} + +/* Create a new Post-handshake authentication object in the extensions. + * + * ssl The SSL/TLS object. + * returns 0 on success and other values indicate failure. + */ +static int TLSX_PostHandAuth_Use(WOLFSSL* ssl) +{ + int ret = 0; + TLSX* extension; + + /* Find the PSK key exchange modes extension if it exists. */ + extension = TLSX_Find(ssl->extensions, TLSX_POST_HANDSHAKE_AUTH); + if (extension == NULL) { + /* Push new Post-handshake Authentication extension. */ + ret = TLSX_Push(&ssl->extensions, TLSX_POST_HANDSHAKE_AUTH, NULL, + ssl->heap); + if (ret != 0) + return ret; + } + + return 0; +} + +#define PHA_GET_SIZE TLSX_PostHandAuth_GetSize +#define PHA_WRITE TLSX_PostHandAuth_Write +#define PHA_PARSE TLSX_PostHandAuth_Parse + +#else + +#define PHA_GET_SIZE(a, b) 0 +#define PHA_WRITE(a, b, c) 0 +#define PHA_PARSE(a, b, c, d) 0 + +#endif + +/******************************************************************************/ +/* Early Data Indication */ +/******************************************************************************/ + +#ifdef WOLFSSL_EARLY_DATA +/* Get the size of the encoded Early Data Indication extension. + * In messages: ClientHello, EncryptedExtensions and NewSessionTicket. + * + * msgType The type of the message this extension is being written into. + * returns the number of bytes of the encoded Early Data Indication extension. + */ +static int TLSX_EarlyData_GetSize(byte msgType, word16* pSz) +{ + int ret = 0; + + if (msgType == client_hello || msgType == encrypted_extensions) + *pSz += 0; + else if (msgType == session_ticket) + *pSz += OPAQUE32_LEN; + else + ret = SANITY_MSG_E; + + return ret; +} + +/* Writes the Early Data Indicator extension into the output buffer. + * Assumes that the the output buffer is big enough to hold data. + * In messages: ClientHello, EncryptedExtensions and NewSessionTicket. + * + * max The maximum early data size. + * output The buffer to write into. + * msgType The type of the message this extension is being written into. + * returns the number of bytes written into the buffer. + */ +static int TLSX_EarlyData_Write(word32 max, byte* output, byte msgType, + word16* pSz) +{ + if (msgType == client_hello || msgType == encrypted_extensions) + return 0; + else if (msgType == session_ticket) { + c32toa(max, output); + *pSz += OPAQUE32_LEN; + return 0; + } + + return SANITY_MSG_E; +} + +/* Parse the Early Data Indicator extension. + * In messages: ClientHello, EncryptedExtensions and NewSessionTicket. + * + * ssl The SSL/TLS object. + * input The extension data. + * length The length of the extension data. + * msgType The type of the message this extension is being parsed from. + * returns 0 on success and other values indicate failure. + */ +static int TLSX_EarlyData_Parse(WOLFSSL* ssl, byte* input, word16 length, + byte msgType) +{ + if (msgType == client_hello) { + if (length != 0) + return BUFFER_E; + + return TLSX_EarlyData_Use(ssl, 0); + } + if (msgType == encrypted_extensions) { + if (length != 0) + return BUFFER_E; + + /* Ensure the index of PSK identity chosen by server is 0. + * Index is plus one to handle 'not set' value of 0. + */ + if (ssl->options.pskIdIndex != 1) + return PSK_KEY_ERROR; + + return TLSX_EarlyData_Use(ssl, 1); + } + if (msgType == session_ticket) { + word32 max; + + if (length != OPAQUE32_LEN) + return BUFFER_E; + ato32(input, &max); + + ssl->session.maxEarlyDataSz = max; + return 0; + } + + return SANITY_MSG_E; +} + +/* Use the data to create a new Early Data object in the extensions. + * + * ssl The SSL/TLS object. + * max The maximum early data size. + * returns 0 on success and other values indicate failure. + */ +int TLSX_EarlyData_Use(WOLFSSL* ssl, word32 max) +{ + int ret = 0; + TLSX* extension; + + /* Find the early data extension if it exists. */ + extension = TLSX_Find(ssl->extensions, TLSX_EARLY_DATA); + if (extension == NULL) { + /* Push new early data extension. */ + ret = TLSX_Push(&ssl->extensions, TLSX_EARLY_DATA, NULL, ssl->heap); + if (ret != 0) + return ret; + + extension = TLSX_Find(ssl->extensions, TLSX_EARLY_DATA); + if (extension == NULL) + return MEMORY_E; + } + + extension->resp = 1; + extension->val = max; + + return 0; +} + +#define EDI_GET_SIZE TLSX_EarlyData_GetSize +#define EDI_WRITE TLSX_EarlyData_Write +#define EDI_PARSE TLSX_EarlyData_Parse + +#else + +#define EDI_GET_SIZE(a, b) 0 +#define EDI_WRITE(a, b, c, d) 0 +#define EDI_PARSE(a, b, c, d) 0 + +#endif + +/******************************************************************************/ +/* TLS Extensions Framework */ +/******************************************************************************/ + +/** Finds an extension in the provided list. */ +TLSX* TLSX_Find(TLSX* list, TLSX_Type type) +{ + TLSX* extension = list; + + while (extension && extension->type != type) + extension = extension->next; + + return extension; +} + +/** Remove an extension. */ +void TLSX_Remove(TLSX** list, TLSX_Type type, void* heap) +{ + TLSX* extension = *list; + TLSX** next = list; + + while (extension && extension->type != type) { + next = &extension->next; + extension = extension->next; + } + + if (extension) { + *next = extension->next; + extension->next = NULL; + TLSX_FreeAll(extension, heap); + } +} + +/** Releases all extensions in the provided list. */ +void TLSX_FreeAll(TLSX* list, void* heap) +{ + TLSX* extension; + + while ((extension = list)) { + list = extension->next; + + switch (extension->type) { + + case TLSX_SERVER_NAME: + SNI_FREE_ALL((SNI*)extension->data, heap); + break; + + case TLSX_TRUSTED_CA_KEYS: + TCA_FREE_ALL((TCA*)extension->data, heap); + break; + + case TLSX_MAX_FRAGMENT_LENGTH: + MFL_FREE_ALL(extension->data, heap); + break; + + case TLSX_TRUNCATED_HMAC: + /* Nothing to do. */ + break; + + case TLSX_SUPPORTED_GROUPS: + EC_FREE_ALL((SupportedCurve*)extension->data, heap); + break; + + case TLSX_EC_POINT_FORMATS: + PF_FREE_ALL((PointFormat*)extension->data, heap); + break; + + case TLSX_STATUS_REQUEST: + CSR_FREE_ALL((CertificateStatusRequest*)extension->data, heap); + break; + + case TLSX_STATUS_REQUEST_V2: + CSR2_FREE_ALL((CertificateStatusRequestItemV2*)extension->data, + heap); + break; + + case TLSX_RENEGOTIATION_INFO: + SCR_FREE_ALL(extension->data, heap); + break; + + case TLSX_SESSION_TICKET: + WOLF_STK_FREE(extension->data, heap); + break; + + case TLSX_QUANTUM_SAFE_HYBRID: + QSH_FREE_ALL((QSHScheme*)extension->data, heap); + break; + + case TLSX_APPLICATION_LAYER_PROTOCOL: + ALPN_FREE_ALL((ALPN*)extension->data, heap); + break; +#if !defined(WOLFSSL_NO_SIGALG) + case TLSX_SIGNATURE_ALGORITHMS: + break; +#endif +#ifdef WOLFSSL_TLS13 + case TLSX_SUPPORTED_VERSIONS: + break; + + case TLSX_COOKIE: + CKE_FREE_ALL((Cookie*)extension->data, heap); + break; + + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + case TLSX_PRE_SHARED_KEY: + PSK_FREE_ALL((PreSharedKey*)extension->data, heap); + break; + + case TLSX_PSK_KEY_EXCHANGE_MODES: + break; + #endif + + #ifdef WOLFSSL_EARLY_DATA + case TLSX_EARLY_DATA: + break; + #endif + + #ifdef WOLFSSL_POST_HANDSHAKE_AUTH + case TLSX_POST_HANDSHAKE_AUTH: + break; + #endif + + #if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22) + case TLSX_SIGNATURE_ALGORITHMS_CERT: + break; + #endif + + case TLSX_KEY_SHARE: + KS_FREE_ALL((KeyShareEntry*)extension->data, heap); + break; +#endif + } + + XFREE(extension, heap, DYNAMIC_TYPE_TLSX); + } + + (void)heap; +} + +/** Checks if the tls extensions are supported based on the protocol version. */ +int TLSX_SupportExtensions(WOLFSSL* ssl) { + return ssl && (IsTLS(ssl) || ssl->version.major == DTLS_MAJOR); +} + +/** Tells the buffered size of the extensions in a list. */ +static int TLSX_GetSize(TLSX* list, byte* semaphore, byte msgType, + word16* pLength) +{ + int ret = 0; + TLSX* extension; + word16 length = 0; + byte isRequest = (msgType == client_hello || + msgType == certificate_request); + + while ((extension = list)) { + list = extension->next; + + /* only extensions marked as response are sent back to the client. */ + if (!isRequest && !extension->resp) + continue; /* skip! */ + + /* ssl level extensions are expected to override ctx level ones. */ + if (!IS_OFF(semaphore, TLSX_ToSemaphore(extension->type))) + continue; /* skip! */ + + /* extension type + extension data length. */ + length += HELLO_EXT_TYPE_SZ + OPAQUE16_LEN; + + + switch (extension->type) { + + case TLSX_SERVER_NAME: + /* SNI only sends the name on the request. */ + if (isRequest) + length += SNI_GET_SIZE((SNI*)extension->data); + break; + + case TLSX_TRUSTED_CA_KEYS: + /* TCA only sends the list on the request. */ + if (isRequest) + length += TCA_GET_SIZE((TCA*)extension->data); + break; + + case TLSX_MAX_FRAGMENT_LENGTH: + length += MFL_GET_SIZE(extension->data); + break; + + case TLSX_TRUNCATED_HMAC: + /* always empty. */ + break; + + case TLSX_SUPPORTED_GROUPS: + length += EC_GET_SIZE((SupportedCurve*)extension->data); + break; + + case TLSX_EC_POINT_FORMATS: + length += PF_GET_SIZE((PointFormat*)extension->data); + break; + + case TLSX_STATUS_REQUEST: + length += CSR_GET_SIZE( + (CertificateStatusRequest*)extension->data, isRequest); + break; + + case TLSX_STATUS_REQUEST_V2: + length += CSR2_GET_SIZE( + (CertificateStatusRequestItemV2*)extension->data, + isRequest); + break; + + case TLSX_RENEGOTIATION_INFO: + length += SCR_GET_SIZE((SecureRenegotiation*)extension->data, + isRequest); + break; + + case TLSX_SESSION_TICKET: + length += WOLF_STK_GET_SIZE((SessionTicket*)extension->data, + isRequest); + break; + + case TLSX_QUANTUM_SAFE_HYBRID: + length += QSH_GET_SIZE((QSHScheme*)extension->data, isRequest); + break; + + case TLSX_APPLICATION_LAYER_PROTOCOL: + length += ALPN_GET_SIZE((ALPN*)extension->data); + break; +#if !defined(WOLFSSL_NO_SIGALG) + case TLSX_SIGNATURE_ALGORITHMS: + length += SA_GET_SIZE(extension->data); + break; +#endif +#ifdef WOLFSSL_TLS13 + case TLSX_SUPPORTED_VERSIONS: + ret = SV_GET_SIZE(extension->data, msgType, &length); + break; + + case TLSX_COOKIE: + ret = CKE_GET_SIZE((Cookie*)extension->data, msgType, &length); + break; + + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + case TLSX_PRE_SHARED_KEY: + ret = PSK_GET_SIZE((PreSharedKey*)extension->data, msgType, + &length); + break; + + case TLSX_PSK_KEY_EXCHANGE_MODES: + ret = PKM_GET_SIZE(extension->val, msgType, &length); + break; + #endif + + #ifdef WOLFSSL_EARLY_DATA + case TLSX_EARLY_DATA: + ret = EDI_GET_SIZE(msgType, &length); + break; + #endif + + #ifdef WOLFSSL_POST_HANDSHAKE_AUTH + case TLSX_POST_HANDSHAKE_AUTH: + ret = PHA_GET_SIZE(msgType, &length); + break; + #endif + + #if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22) + case TLSX_SIGNATURE_ALGORITHMS_CERT: + length += SAC_GET_SIZE(extension->data); + break; + #endif + + case TLSX_KEY_SHARE: + length += KS_GET_SIZE((KeyShareEntry*)extension->data, msgType); + break; +#endif + } + + /* marks the extension as processed so ctx level */ + /* extensions don't overlap with ssl level ones. */ + TURN_ON(semaphore, TLSX_ToSemaphore(extension->type)); + } + + *pLength += length; + + return ret; +} + +/** Writes the extensions of a list in a buffer. */ +static int TLSX_Write(TLSX* list, byte* output, byte* semaphore, + byte msgType, word16* pOffset) +{ + int ret = 0; + TLSX* extension; + word16 offset = 0; + word16 length_offset = 0; + byte isRequest = (msgType == client_hello || + msgType == certificate_request); + + while ((extension = list)) { + list = extension->next; + + /* only extensions marked as response are written in a response. */ + if (!isRequest && !extension->resp) + continue; /* skip! */ + + /* ssl level extensions are expected to override ctx level ones. */ + if (!IS_OFF(semaphore, TLSX_ToSemaphore(extension->type))) + continue; /* skip! */ + + /* writes extension type. */ + c16toa(extension->type, output + offset); + offset += HELLO_EXT_TYPE_SZ + OPAQUE16_LEN; + length_offset = offset; + + /* extension data should be written internally. */ + switch (extension->type) { + case TLSX_SERVER_NAME: + if (isRequest) { + WOLFSSL_MSG("SNI extension to write"); + offset += SNI_WRITE((SNI*)extension->data, output + offset); + } + break; + + case TLSX_TRUSTED_CA_KEYS: + WOLFSSL_MSG("Trusted CA Indication extension to write"); + if (isRequest) { + offset += TCA_WRITE((TCA*)extension->data, output + offset); + } + break; + + case TLSX_MAX_FRAGMENT_LENGTH: + WOLFSSL_MSG("Max Fragment Length extension to write"); + offset += MFL_WRITE((byte*)extension->data, output + offset); + break; + + case TLSX_TRUNCATED_HMAC: + WOLFSSL_MSG("Truncated HMAC extension to write"); + /* always empty. */ + break; + + case TLSX_SUPPORTED_GROUPS: + WOLFSSL_MSG("Supported Groups extension to write"); + offset += EC_WRITE((SupportedCurve*)extension->data, + output + offset); + break; + + case TLSX_EC_POINT_FORMATS: + WOLFSSL_MSG("Point Formats extension to write"); + offset += PF_WRITE((PointFormat*)extension->data, + output + offset); + break; + + case TLSX_STATUS_REQUEST: + WOLFSSL_MSG("Certificate Status Request extension to write"); + offset += CSR_WRITE((CertificateStatusRequest*)extension->data, + output + offset, isRequest); + break; + + case TLSX_STATUS_REQUEST_V2: + WOLFSSL_MSG("Certificate Status Request v2 extension to write"); + offset += CSR2_WRITE( + (CertificateStatusRequestItemV2*)extension->data, + output + offset, isRequest); + break; + + case TLSX_RENEGOTIATION_INFO: + WOLFSSL_MSG("Secure Renegotiation extension to write"); + offset += SCR_WRITE((SecureRenegotiation*)extension->data, + output + offset, isRequest); + break; + + case TLSX_SESSION_TICKET: + WOLFSSL_MSG("Session Ticket extension to write"); + offset += WOLF_STK_WRITE((SessionTicket*)extension->data, + output + offset, isRequest); + break; + + case TLSX_QUANTUM_SAFE_HYBRID: + WOLFSSL_MSG("Quantum-Safe-Hybrid extension to write"); + if (isRequest) { + offset += QSH_WRITE((QSHScheme*)extension->data, output + offset); + } + offset += QSHPK_WRITE((QSHScheme*)extension->data, output + offset); + offset += QSH_SERREQ(output + offset, isRequest); + break; + + case TLSX_APPLICATION_LAYER_PROTOCOL: + WOLFSSL_MSG("ALPN extension to write"); + offset += ALPN_WRITE((ALPN*)extension->data, output + offset); + break; +#if !defined(WOLFSSL_NO_SIGALG) + case TLSX_SIGNATURE_ALGORITHMS: + WOLFSSL_MSG("Signature Algorithms extension to write"); + offset += SA_WRITE(extension->data, output + offset); + break; +#endif +#ifdef WOLFSSL_TLS13 + case TLSX_SUPPORTED_VERSIONS: + WOLFSSL_MSG("Supported Versions extension to write"); + ret = SV_WRITE(extension->data, output + offset, msgType, &offset); + break; + + case TLSX_COOKIE: + WOLFSSL_MSG("Cookie extension to write"); + ret = CKE_WRITE((Cookie*)extension->data, output + offset, + msgType, &offset); + break; + + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + case TLSX_PRE_SHARED_KEY: + WOLFSSL_MSG("Pre-Shared Key extension to write"); + ret = PSK_WRITE((PreSharedKey*)extension->data, output + offset, + msgType, &offset); + break; + + case TLSX_PSK_KEY_EXCHANGE_MODES: + WOLFSSL_MSG("PSK Key Exchange Modes extension to write"); + ret = PKM_WRITE(extension->val, output + offset, msgType, + &offset); + break; + #endif + + #ifdef WOLFSSL_EARLY_DATA + case TLSX_EARLY_DATA: + WOLFSSL_MSG("Early Data extension to write"); + ret = EDI_WRITE(extension->val, output + offset, msgType, + &offset); + break; + #endif + + #ifdef WOLFSSL_POST_HANDSHAKE_AUTH + case TLSX_POST_HANDSHAKE_AUTH: + WOLFSSL_MSG("Post-Handshake Authentication extension to write"); + ret = PHA_WRITE(output + offset, msgType, &offset); + break; + #endif + + #if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22) + case TLSX_SIGNATURE_ALGORITHMS_CERT: + WOLFSSL_MSG("Signature Algorithms extension to write"); + offset += SAC_WRITE(extension->data, output + offset); + break; + #endif + + case TLSX_KEY_SHARE: + WOLFSSL_MSG("Key Share extension to write"); + offset += KS_WRITE((KeyShareEntry*)extension->data, + output + offset, msgType); + break; +#endif + } + + /* writes extension data length. */ + c16toa(offset - length_offset, output + length_offset - OPAQUE16_LEN); + + /* marks the extension as processed so ctx level */ + /* extensions don't overlap with ssl level ones. */ + TURN_ON(semaphore, TLSX_ToSemaphore(extension->type)); + } + + *pOffset += offset; + + return ret; +} + + +#if defined(HAVE_NTRU) && defined(HAVE_QSH) + +static word32 GetEntropy(unsigned char* out, word32 num_bytes) +{ + int ret = 0; + + if (gRng == NULL) { + if ((gRng = (WC_RNG*)XMALLOC(sizeof(WC_RNG), NULL, + DYNAMIC_TYPE_TLSX)) == NULL) + return DRBG_OUT_OF_MEMORY; + wc_InitRng(gRng); + } + + if (gRngMutex == NULL) { + if ((gRngMutex = (wolfSSL_Mutex*)XMALLOC(sizeof(wolfSSL_Mutex), NULL, + DYNAMIC_TYPE_TLSX)) == NULL) + return DRBG_OUT_OF_MEMORY; + wc_InitMutex(gRngMutex); + } + + ret |= wc_LockMutex(gRngMutex); + ret |= wc_RNG_GenerateBlock(gRng, out, num_bytes); + ret |= wc_UnLockMutex(gRngMutex); + + if (ret != 0) + return DRBG_ENTROPY_FAIL; + + return DRBG_OK; +} +#endif + + +#ifdef HAVE_QSH +static int TLSX_CreateQSHKey(WOLFSSL* ssl, int type) +{ + int ret; + + (void)ssl; + + switch (type) { +#ifdef HAVE_NTRU + case WOLFSSL_NTRU_EESS439: + case WOLFSSL_NTRU_EESS593: + case WOLFSSL_NTRU_EESS743: + ret = TLSX_CreateNtruKey(ssl, type); + break; +#endif + default: + WOLFSSL_MSG("Unknown type for creating NTRU key"); + return -1; + } + + return ret; +} + + +static int TLSX_AddQSHKey(QSHKey** list, QSHKey* key) +{ + QSHKey* current; + + if (key == NULL) + return BAD_FUNC_ARG; + + /* if no public key stored in key then do not add */ + if (key->pub.length == 0 || key->pub.buffer == NULL) + return 0; + + /* first element to be added to the list */ + current = *list; + if (current == NULL) { + *list = key; + return 0; + } + + while (current->next) { + /* can only have one of the key in the list */ + if (current->name == key->name) + return -1; + current = (QSHKey*)current->next; + } + + current->next = (struct QSHKey*)key; + + return 0; +} + + +#if defined(HAVE_NTRU) +int TLSX_CreateNtruKey(WOLFSSL* ssl, int type) +{ + int ret = -1; + int ntruType; + + /* variable declarations for NTRU*/ + QSHKey* temp = NULL; + byte public_key[1027]; + word16 public_key_len = sizeof(public_key); + byte private_key[1120]; + word16 private_key_len = sizeof(private_key); + DRBG_HANDLE drbg; + + if (ssl == NULL) + return BAD_FUNC_ARG; + + switch (type) { + case WOLFSSL_NTRU_EESS439: + ntruType = NTRU_EES439EP1; + break; + case WOLFSSL_NTRU_EESS593: + ntruType = NTRU_EES593EP1; + break; + case WOLFSSL_NTRU_EESS743: + ntruType = NTRU_EES743EP1; + break; + default: + WOLFSSL_MSG("Unknown type for creating NTRU key"); + return -1; + } + ret = ntru_crypto_drbg_external_instantiate(GetEntropy, &drbg); + if (ret != DRBG_OK) { + WOLFSSL_MSG("NTRU drbg instantiate failed\n"); + return ret; + } + + if ((ret = ntru_crypto_ntru_encrypt_keygen(drbg, ntruType, + &public_key_len, NULL, &private_key_len, NULL)) != NTRU_OK) + return ret; + + if ((ret = ntru_crypto_ntru_encrypt_keygen(drbg, ntruType, + &public_key_len, public_key, &private_key_len, private_key)) != NTRU_OK) + return ret; + + ret = ntru_crypto_drbg_uninstantiate(drbg); + if (ret != NTRU_OK) { + WOLFSSL_MSG("NTRU drbg uninstantiate failed\n"); + return ret; + } + + if ((temp = (QSHKey*)XMALLOC(sizeof(QSHKey), ssl->heap, + DYNAMIC_TYPE_TLSX)) == NULL) + return MEMORY_E; + temp->name = type; + temp->pub.length = public_key_len; + temp->pub.buffer = (byte*)XMALLOC(public_key_len, ssl->heap, + DYNAMIC_TYPE_PUBLIC_KEY); + XMEMCPY(temp->pub.buffer, public_key, public_key_len); + temp->pri.length = private_key_len; + temp->pri.buffer = (byte*)XMALLOC(private_key_len, ssl->heap, + DYNAMIC_TYPE_ARRAYS); + XMEMCPY(temp->pri.buffer, private_key, private_key_len); + temp->next = NULL; + + TLSX_AddQSHKey(&ssl->QSH_Key, temp); + + (void)ssl; + (void)type; + + return ret; +} +#endif + + +/* + Used to find a public key from the list of keys + pubLen length of array + name input the name of the scheme looking for ie WOLFSSL_NTRU_ESSXXX + + returns a pointer to public key byte* or NULL if not found + */ +static byte* TLSX_QSHKeyFind_Pub(QSHKey* qsh, word16* pubLen, word16 name) +{ + QSHKey* current = qsh; + + if (qsh == NULL || pubLen == NULL) + return NULL; + + *pubLen = 0; + + while(current) { + if (current->name == name) { + *pubLen = current->pub.length; + return current->pub.buffer; + } + current = (QSHKey*)current->next; + } + + return NULL; +} +#endif /* HAVE_QSH */ + +#if (!defined(NO_WOLFSSL_SERVER) && defined(WOLFSSL_TLS13) && \ + !defined(WOLFSSL_NO_SERVER_GROUPS_EXT)) || \ + (defined(WOLFSSL_TLS13) && !defined(HAVE_ECC) && \ + !defined(HAVE_CURVE25519) && defined(HAVE_SUPPORTED_CURVES)) || \ + ((defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \ + defined(HAVE_SUPPORTED_CURVES)) + +/* Populates the default supported groups / curves */ +static int TLSX_PopulateSupportedGroups(WOLFSSL* ssl, TLSX** extensions) +{ + int ret = WOLFSSL_SUCCESS; +#ifdef WOLFSSL_TLS13 + int i; + +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + if (ssl->options.resuming && ssl->session.namedGroup != 0) { + return TLSX_UseSupportedCurve(extensions, ssl->session.namedGroup, + ssl->heap); + } +#endif + + if (ssl->numGroups != 0) { + for (i = 0; i < ssl->numGroups; i++) { + ret = TLSX_UseSupportedCurve(extensions, ssl->group[i], ssl->heap); + if (ret != WOLFSSL_SUCCESS) + return ret; + } + return WOLFSSL_SUCCESS; + } +#endif /* WOLFSSL_TLS13 */ + +#if defined(HAVE_ECC) && defined(HAVE_SUPPORTED_CURVES) + /* list in order by strength, since not all servers choose by strength */ + #if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_SECP521R1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #endif + #if defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES) + #ifdef HAVE_ECC_BRAINPOOL + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_BRAINPOOLP512R1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #endif + #if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_SECP384R1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #ifdef HAVE_ECC_BRAINPOOL + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_BRAINPOOLP384R1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #endif + #if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_SECP256R1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #ifdef HAVE_ECC_KOBLITZ + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_SECP256K1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #ifdef HAVE_ECC_BRAINPOOL + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_BRAINPOOLP256R1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #endif +#endif /* HAVE_ECC && HAVE_SUPPORTED_CURVES */ + + #ifndef HAVE_FIPS + #if defined(HAVE_CURVE25519) + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_X25519, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #endif /* HAVE_FIPS */ + +#if defined(HAVE_ECC) && defined(HAVE_SUPPORTED_CURVES) + #if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_SECP224R1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #ifdef HAVE_ECC_KOBLITZ + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_SECP224K1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #endif + + #ifndef HAVE_FIPS + #if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_SECP192R1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #ifdef HAVE_ECC_KOBLITZ + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_SECP192K1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #endif + #if defined(HAVE_ECC160) || defined(HAVE_ALL_CURVES) + #ifndef NO_ECC_SECP + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_SECP160R1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #ifdef HAVE_ECC_SECPR2 + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_SECP160R2, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #ifdef HAVE_ECC_KOBLITZ + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_ECC_SECP160K1, ssl->heap); + if (ret != WOLFSSL_SUCCESS) return ret; + #endif + #endif + #endif /* HAVE_FIPS */ +#endif /* HAVE_ECC && HAVE_SUPPORTED_CURVES */ + + /* Add FFDHE supported groups. */ + #ifdef HAVE_FFDHE_8192 + if (8192/8 >= ssl->options.minDhKeySz && + 8192/8 <= ssl->options.maxDhKeySz) { + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_FFDHE_8192, ssl->heap); + if (ret != WOLFSSL_SUCCESS) + return ret; + } + #endif + #ifdef HAVE_FFDHE_6144 + if (6144/8 >= ssl->options.minDhKeySz && + 6144/8 <= ssl->options.maxDhKeySz) { + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_FFDHE_6144, ssl->heap); + if (ret != WOLFSSL_SUCCESS) + return ret; + } + #endif + #ifdef HAVE_FFDHE_4096 + if (4096/8 >= ssl->options.minDhKeySz && + 4096/8 <= ssl->options.maxDhKeySz) { + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_FFDHE_4096, ssl->heap); + if (ret != WOLFSSL_SUCCESS) + return ret; + } + #endif + #ifdef HAVE_FFDHE_3072 + if (3072/8 >= ssl->options.minDhKeySz && + 3072/8 <= ssl->options.maxDhKeySz) { + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_FFDHE_3072, ssl->heap); + if (ret != WOLFSSL_SUCCESS) + return ret; + } + #endif + #ifdef HAVE_FFDHE_2048 + if (2048/8 >= ssl->options.minDhKeySz && + 2048/8 <= ssl->options.maxDhKeySz) { + ret = TLSX_UseSupportedCurve(extensions, + WOLFSSL_FFDHE_2048, ssl->heap); + if (ret != WOLFSSL_SUCCESS) + return ret; + } + #endif + + (void)ssl; + (void)extensions; + + return ret; +} + +#endif + +int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isServer) +{ + int ret = 0; + byte* public_key = NULL; + word16 public_key_len = 0; +#if defined(WOLFSSL_TLS13) && (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)) + int usingPSK = 0; +#endif +#ifdef HAVE_QSH + TLSX* extension; + QSHScheme* qsh; + QSHScheme* next; + + /* add supported QSHSchemes */ + WOLFSSL_MSG("Adding supported QSH Schemes"); +#endif + + /* server will add extension depending on whats parsed from client */ + if (!isServer) { +#ifdef HAVE_QSH + /* test if user has set a specific scheme already */ + if (!ssl->user_set_QSHSchemes) { + if (ssl->sendQSHKeys && ssl->QSH_Key == NULL) { + if ((ret = TLSX_CreateQSHKey(ssl, WOLFSSL_NTRU_EESS743)) != 0) { + WOLFSSL_MSG("Error creating ntru keys"); + return ret; + } + if ((ret = TLSX_CreateQSHKey(ssl, WOLFSSL_NTRU_EESS593)) != 0) { + WOLFSSL_MSG("Error creating ntru keys"); + return ret; + } + if ((ret = TLSX_CreateQSHKey(ssl, WOLFSSL_NTRU_EESS439)) != 0) { + WOLFSSL_MSG("Error creating ntru keys"); + return ret; + } + + /* add NTRU 256 */ + public_key = TLSX_QSHKeyFind_Pub(ssl->QSH_Key, + &public_key_len, WOLFSSL_NTRU_EESS743); + } + if (TLSX_UseQSHScheme(&ssl->extensions, WOLFSSL_NTRU_EESS743, + public_key, public_key_len, ssl->heap) + != WOLFSSL_SUCCESS) + ret = -1; + + /* add NTRU 196 */ + if (ssl->sendQSHKeys) { + public_key = TLSX_QSHKeyFind_Pub(ssl->QSH_Key, + &public_key_len, WOLFSSL_NTRU_EESS593); + } + if (TLSX_UseQSHScheme(&ssl->extensions, WOLFSSL_NTRU_EESS593, + public_key, public_key_len, ssl->heap) + != WOLFSSL_SUCCESS) + ret = -1; + + /* add NTRU 128 */ + if (ssl->sendQSHKeys) { + public_key = TLSX_QSHKeyFind_Pub(ssl->QSH_Key, + &public_key_len, WOLFSSL_NTRU_EESS439); + } + if (TLSX_UseQSHScheme(&ssl->extensions, WOLFSSL_NTRU_EESS439, + public_key, public_key_len, ssl->heap) + != WOLFSSL_SUCCESS) + ret = -1; + } + else if (ssl->sendQSHKeys && ssl->QSH_Key == NULL) { + /* for each scheme make a client key */ + extension = TLSX_Find(ssl->extensions, TLSX_QUANTUM_SAFE_HYBRID); + if (extension) { + qsh = (QSHScheme*)extension->data; + + while (qsh) { + if ((ret = TLSX_CreateQSHKey(ssl, qsh->name)) != 0) + return ret; + + /* get next now because qsh could be freed */ + next = qsh->next; + + /* find the public key created and add to extension*/ + public_key = TLSX_QSHKeyFind_Pub(ssl->QSH_Key, + &public_key_len, qsh->name); + if (TLSX_UseQSHScheme(&ssl->extensions, qsh->name, + public_key, public_key_len, + ssl->heap) != WOLFSSL_SUCCESS) + ret = -1; + qsh = next; + } + } + } +#endif + +#if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && \ + defined(HAVE_SUPPORTED_CURVES) + if (!ssl->options.userCurves && !ssl->ctx->userCurves) { + if (TLSX_Find(ssl->ctx->extensions, + TLSX_SUPPORTED_GROUPS) == NULL) { + ret = TLSX_PopulateSupportedGroups(ssl, &ssl->extensions); + if (ret != WOLFSSL_SUCCESS) + return ret; + } + } + if ((!IsAtLeastTLSv1_3(ssl->version) || ssl->options.downgrade) && + TLSX_Find(ssl->ctx->extensions, TLSX_EC_POINT_FORMATS) == NULL && + TLSX_Find(ssl->extensions, TLSX_EC_POINT_FORMATS) == NULL) { + ret = TLSX_UsePointFormat(&ssl->extensions, + WOLFSSL_EC_PF_UNCOMPRESSED, ssl->heap); + if (ret != WOLFSSL_SUCCESS) + return ret; + } +#endif /* (HAVE_ECC || HAVE_CURVE25519) && HAVE_SUPPORTED_CURVES */ + } /* is not server */ + +#if !defined(WOLFSSL_NO_SIGALG) + WOLFSSL_MSG("Adding signature algorithms extension"); + if ((ret = TLSX_SetSignatureAlgorithms(&ssl->extensions, ssl, ssl->heap)) + != 0) { + return ret; + } +#else + ret = 0; +#endif + #ifdef WOLFSSL_TLS13 + if (!isServer && IsAtLeastTLSv1_3(ssl->version)) { + /* Add mandatory TLS v1.3 extension: supported version */ + WOLFSSL_MSG("Adding supported versions extension"); + if ((ret = TLSX_SetSupportedVersions(&ssl->extensions, ssl, + ssl->heap)) != 0) { + return ret; + } + + #if !defined(HAVE_ECC) && !defined(HAVE_CURVE25519) && \ + defined(HAVE_SUPPORTED_CURVES) + if (TLSX_Find(ssl->ctx->extensions, TLSX_SUPPORTED_GROUPS) == NULL) { + /* Put in DH groups for TLS 1.3 only. */ + ret = TLSX_PopulateSupportedGroups(ssl, &ssl->extensions); + if (ret != WOLFSSL_SUCCESS) + return ret; + ret = 0; + } + #endif /* !HAVE_ECC && !HAVE_CURVE25519 && HAVE_SUPPORTED_CURVES */ + + #if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22) + if (ssl->certHashSigAlgoSz > 0) { + WOLFSSL_MSG("Adding signature algorithms cert extension"); + if ((ret = TLSX_SetSignatureAlgorithmsCert(&ssl->extensions, + ssl, ssl->heap)) != 0) { + return ret; + } + } + #endif /* !WOLFSSL_TLS13_DRAFT_18 && !WOLFSSL_TLS13_DRAFT_22 */ + + if (TLSX_Find(ssl->extensions, TLSX_KEY_SHARE) == NULL) { + word16 namedGroup; + + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + if (ssl->options.resuming && ssl->session.namedGroup != 0) + namedGroup = ssl->session.namedGroup; + else + #endif + { + #if defined(HAVE_ECC) && (!defined(NO_ECC256) || \ + defined(HAVE_ALL_CURVES)) && !defined(NO_ECC_SECP) + namedGroup = WOLFSSL_ECC_SECP256R1; + #elif defined(HAVE_CURVE25519) + namedGroup = WOLFSSL_ECC_X25519; + #elif defined(HAVE_ECC) && (!defined(NO_ECC384) || \ + defined(HAVE_ALL_CURVES)) && !defined(NO_ECC_SECP) + namedGroup = WOLFSSL_ECC_SECP384R1; + #elif defined(HAVE_ECC) && (!defined(NO_ECC521) || \ + defined(HAVE_ALL_CURVES)) && !defined(NO_ECC_SECP) + namedGroup = WOLFSSL_ECC_SECP521R1; + #elif defined(HAVE_FFDHE_2048) + namedGroup = WOLFSSL_FFDHE_2048; + #elif defined(HAVE_FFDHE_3072) + namedGroup = WOLFSSL_FFDHE_3072; + #elif defined(HAVE_FFDHE_4096) + namedGroup = WOLFSSL_FFDHE_4096; + #elif defined(HAVE_FFDHE_6144) + namedGroup = WOLFSSL_FFDHE_6144; + #elif defined(HAVE_FFDHE_8192) + namedGroup = WOLFSSL_FFDHE_8192; + #else + return KEY_SHARE_ERROR; + #endif + } + ret = TLSX_KeyShare_Use(ssl, namedGroup, 0, NULL, NULL); + if (ret != 0) + return ret; + } + + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + TLSX_Remove(&ssl->extensions, TLSX_PRE_SHARED_KEY, ssl->heap); + #endif + #if defined(HAVE_SESSION_TICKET) + if (ssl->options.resuming && ssl->session.ticketLen > 0) { + WOLFSSL_SESSION* sess = &ssl->session; + word32 milli; + + if (sess->ticketLen > MAX_PSK_ID_LEN) { + WOLFSSL_MSG("Session ticket length for PSK ext is too large"); + return BUFFER_ERROR; + } + + /* Determine the MAC algorithm for the cipher suite used. */ + ssl->options.cipherSuite0 = sess->cipherSuite0; + ssl->options.cipherSuite = sess->cipherSuite; + ret = SetCipherSpecs(ssl); + if (ret != 0) + return ret; + milli = TimeNowInMilliseconds() - sess->ticketSeen + + sess->ticketAdd; + /* Pre-shared key is mandatory extension for resumption. */ + ret = TLSX_PreSharedKey_Use(ssl, sess->ticket, sess->ticketLen, + milli, ssl->specs.mac_algorithm, + ssl->options.cipherSuite0, + ssl->options.cipherSuite, 1, + NULL); + if (ret != 0) + return ret; + + usingPSK = 1; + } + #endif + #ifndef NO_PSK + if (ssl->options.client_psk_cb != NULL || + ssl->options.client_psk_tls13_cb != NULL) { + /* Default ciphersuite. */ + byte cipherSuite0 = TLS13_BYTE; + byte cipherSuite = WOLFSSL_DEF_PSK_CIPHER; + const char* cipherName = NULL; + + if (ssl->options.client_psk_tls13_cb != NULL) { + ssl->arrays->psk_keySz = ssl->options.client_psk_tls13_cb( + ssl, ssl->arrays->server_hint, + ssl->arrays->client_identity, MAX_PSK_ID_LEN, + ssl->arrays->psk_key, MAX_PSK_KEY_LEN, &cipherName); + if (GetCipherSuiteFromName(cipherName, &cipherSuite0, + &cipherSuite) != 0) { + return PSK_KEY_ERROR; + } + } + else { + ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl, + ssl->arrays->server_hint, ssl->arrays->client_identity, + MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN); + } + if (ssl->arrays->psk_keySz == 0 || + ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) { + return PSK_KEY_ERROR; + } + ssl->arrays->client_identity[MAX_PSK_ID_LEN] = '\0'; + /* TODO: Callback should be able to change ciphersuite. */ + ssl->options.cipherSuite0 = cipherSuite0; + ssl->options.cipherSuite = cipherSuite; + ret = SetCipherSpecs(ssl); + if (ret != 0) + return ret; + + ret = TLSX_PreSharedKey_Use(ssl, + (byte*)ssl->arrays->client_identity, + (word16)XSTRLEN(ssl->arrays->client_identity), + 0, ssl->specs.mac_algorithm, + cipherSuite0, cipherSuite, 0, + NULL); + if (ret != 0) + return ret; + + usingPSK = 1; + } + #endif + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + if (usingPSK) { + byte modes; + + /* Pre-shared key modes: mandatory extension for resumption. */ + modes = 1 << PSK_KE; + #if !defined(NO_DH) || defined(HAVE_ECC) || defined(HAVE_CURVE25519) + if (!ssl->options.noPskDheKe) + modes |= 1 << PSK_DHE_KE; + #endif + ret = TLSX_PskKeModes_Use(ssl, modes); + if (ret != 0) + return ret; + } + #endif + #if defined(WOLFSSL_POST_HANDSHAKE_AUTH) + if (!isServer && ssl->options.postHandshakeAuth) { + ret = TLSX_PostHandAuth_Use(ssl); + if (ret != 0) + return ret; + } + #endif + } + + #endif + + (void)isServer; + (void)public_key; + (void)public_key_len; + (void)ssl; + + return ret; +} + + +#if defined(WOLFSSL_TLS13) || !defined(NO_WOLFSSL_CLIENT) + +/** Tells the buffered size of extensions to be sent into the client hello. */ +int TLSX_GetRequestSize(WOLFSSL* ssl, byte msgType, word16* pLength) +{ + int ret = 0; + word16 length = 0; + byte semaphore[SEMAPHORE_SIZE] = {0}; + + if (!TLSX_SupportExtensions(ssl)) + return 0; + if (msgType == client_hello) { + EC_VALIDATE_REQUEST(ssl, semaphore); + PF_VALIDATE_REQUEST(ssl, semaphore); + QSH_VALIDATE_REQUEST(ssl, semaphore); + WOLF_STK_VALIDATE_REQUEST(ssl); +#if !defined(WOLFSSL_NO_SIGALG) + if (ssl->suites->hashSigAlgoSz == 0) + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS)); +#endif +#if defined(WOLFSSL_TLS13) + if (!IsAtLeastTLSv1_2(ssl)) + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS)); + if (!IsAtLeastTLSv1_3(ssl->version)) { + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY)); + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PSK_KEY_EXCHANGE_MODES)); + #endif + #ifdef WOLFSSL_EARLY_DATA + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_EARLY_DATA)); + #endif + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_COOKIE)); + #ifdef WOLFSSL_POST_HANDSHAKE_AUTH + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_POST_HANDSHAKE_AUTH)); + #endif + } + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + if (IsAtLeastTLSv1_3(ssl->version) && ssl->options.noPskDheKe) { + #if !defined(NO_PSK) + if (ssl->options.havePSK) + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); + #endif + #if defined(HAVE_SESSION_TICKET) + if (ssl->options.resuming) + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); + #endif + } + #endif +#endif + #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + if (!ssl->ctx->cm->ocspStaplingEnabled) { + /* mark already sent, so it won't send it */ + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST)); + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST_V2)); + } + #endif + } + +#ifdef WOLFSSL_TLS13 + #ifndef NO_CERTS + else if (msgType == certificate_request) { + XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); +#if !defined(WOLFSSL_NO_SIGALG) + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS)); +#endif + /* TODO: TLSX_SIGNED_CERTIFICATE_TIMESTAMP, + * TLSX_CERTIFICATE_AUTHORITIES, OID_FILTERS + * TLSX_STATUS_REQUEST + */ + } + #endif +#endif + if (ssl->extensions) { + ret = TLSX_GetSize(ssl->extensions, semaphore, msgType, &length); + if (ret != 0) + return ret; + } + if (ssl->ctx && ssl->ctx->extensions) { + ret = TLSX_GetSize(ssl->ctx->extensions, semaphore, msgType, &length); + if (ret != 0) + return ret; + } + +#ifdef HAVE_EXTENDED_MASTER + if (msgType == client_hello && ssl->options.haveEMS && + (!IsAtLeastTLSv1_3(ssl->version) || ssl->options.downgrade)) { + length += HELLO_EXT_SZ; + } +#endif + + if (length) + length += OPAQUE16_LEN; /* for total length storage. */ + + *pLength += length; + + return ret; +} + +/** Writes the extensions to be sent into the client hello. */ +int TLSX_WriteRequest(WOLFSSL* ssl, byte* output, byte msgType, word16* pOffset) +{ + int ret = 0; + word16 offset = 0; + byte semaphore[SEMAPHORE_SIZE] = {0}; + + if (!TLSX_SupportExtensions(ssl) || output == NULL) + return 0; + + offset += OPAQUE16_LEN; /* extensions length */ + + if (msgType == client_hello) { + EC_VALIDATE_REQUEST(ssl, semaphore); + PF_VALIDATE_REQUEST(ssl, semaphore); + WOLF_STK_VALIDATE_REQUEST(ssl); + QSH_VALIDATE_REQUEST(ssl, semaphore); +#if !defined(WOLFSSL_NO_SIGALG) + if (ssl->suites->hashSigAlgoSz == 0) + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS)); +#endif +#ifdef WOLFSSL_TLS13 + if (!IsAtLeastTLSv1_2(ssl)) + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS)); + if (!IsAtLeastTLSv1_3(ssl->version)) { + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PSK_KEY_EXCHANGE_MODES)); + #endif + #ifdef WOLFSSL_EARLY_DATA + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_EARLY_DATA)); + #endif + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_COOKIE)); + #ifdef WOLFSSL_POST_HANDSHAKE_AUTH + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_POST_HANDSHAKE_AUTH)); + #endif + } + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + if (IsAtLeastTLSv1_3(ssl->version) && ssl->options.noPskDheKe) { + #if !defined(NO_PSK) + if (ssl->options.havePSK) + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); + #endif + #if defined(HAVE_SESSION_TICKET) + if (ssl->options.resuming) + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); + #endif + } + #endif + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + /* Must write Pre-shared Key extension at the end in TLS v1.3. + * Must not write out Pre-shared Key extension in earlier versions of + * protocol. + */ + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY)); + #endif +#endif + #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + /* mark already sent, so it won't send it */ + if (!ssl->ctx->cm->ocspStaplingEnabled) { + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST)); + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST_V2)); + } + #endif + } +#ifdef WOLFSSL_TLS13 + #ifndef NO_CERTS + else if (msgType == certificate_request) { + XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); +#if !defined(WOLFSSL_NO_SIGALG) + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_SIGNATURE_ALGORITHMS)); +#endif + /* TODO: TLSX_SIGNED_CERTIFICATE_TIMESTAMP, + * TLSX_CERTIFICATE_AUTHORITIES, TLSX_OID_FILTERS + * TLSX_STATUS_REQUEST + */ + } + #endif +#endif + if (ssl->extensions) { + ret = TLSX_Write(ssl->extensions, output + offset, semaphore, + msgType, &offset); + if (ret != 0) + return ret; + } + if (ssl->ctx && ssl->ctx->extensions) { + ret = TLSX_Write(ssl->ctx->extensions, output + offset, semaphore, + msgType, &offset); + if (ret != 0) + return ret; + } + +#ifdef HAVE_EXTENDED_MASTER + if (msgType == client_hello && ssl->options.haveEMS && + (!IsAtLeastTLSv1_3(ssl->version) || ssl->options.downgrade)) { + WOLFSSL_MSG("EMS extension to write"); + c16toa(HELLO_EXT_EXTMS, output + offset); + offset += HELLO_EXT_TYPE_SZ; + c16toa(0, output + offset); + offset += HELLO_EXT_SZ_SZ; + } +#endif + +#ifdef WOLFSSL_TLS13 + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + if (msgType == client_hello && IsAtLeastTLSv1_3(ssl->version)) { + /* Write out what we can of Pre-shared key extension. */ + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY)); + ret = TLSX_Write(ssl->extensions, output + offset, semaphore, + client_hello, &offset); + if (ret != 0) + return ret; + } + #endif +#endif + + if (offset > OPAQUE16_LEN || msgType != client_hello) + c16toa(offset - OPAQUE16_LEN, output); /* extensions length */ + + *pOffset += offset; + + return ret; +} + +#endif /* WOLFSSL_TLS13 || !NO_WOLFSSL_CLIENT */ + +#if defined(WOLFSSL_TLS13) || !defined(NO_WOLFSSL_SERVER) + +/** Tells the buffered size of extensions to be sent into the server hello. */ +int TLSX_GetResponseSize(WOLFSSL* ssl, byte msgType, word16* pLength) +{ + int ret = 0; + word16 length = 0; + byte semaphore[SEMAPHORE_SIZE] = {0}; + + switch (msgType) { +#ifndef NO_WOLFSSL_SERVER + case server_hello: + PF_VALIDATE_RESPONSE(ssl, semaphore); + #ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version)) { + XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); + #ifndef WOLFSSL_TLS13_DRAFT_18 + TURN_OFF(semaphore, + TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS)); + #endif + if (!ssl->options.noPskDheKe) + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY)); + #endif + } + else { + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY)); + #endif + } + #endif + break; + + #ifdef WOLFSSL_TLS13 + case hello_retry_request: + XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); + #ifndef WOLFSSL_TLS13_DRAFT_18 + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS)); + #endif + if (!ssl->options.noPskDheKe) + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_COOKIE)); + break; + #endif + + #ifdef WOLFSSL_TLS13 + case encrypted_extensions: + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_EC_POINT_FORMATS)); + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS)); + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SESSION_TICKET)); + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY)); + #endif + #ifdef HAVE_CERTIFICATE_STATUS_REQUEST + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST)); + #endif + #if defined(HAVE_SECURE_RENEGOTIATION) + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_RENEGOTIATION_INFO)); + #endif + break; + + #ifdef WOLFSSL_EARLY_DATA + case session_ticket: + if (ssl->options.tls1_3) { + XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_EARLY_DATA)); + } + break; + #endif + #endif +#endif + +#ifdef WOLFSSL_TLS13 + #ifndef NO_CERTS + case certificate: + XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST)); + /* TODO: TLSX_SIGNED_CERTIFICATE_TIMESTAMP, + * TLSX_SERVER_CERTIFICATE_TYPE + */ + break; + #endif +#endif + } + + #ifdef HAVE_QSH + /* change response if not using TLS_QSH */ + if (!ssl->options.haveQSH) { + TLSX* ext = TLSX_Find(ssl->extensions, TLSX_QUANTUM_SAFE_HYBRID); + if (ext) + ext->resp = 0; + } + #endif + +#ifdef HAVE_EXTENDED_MASTER + if (ssl->options.haveEMS && msgType == server_hello && + !IsAtLeastTLSv1_3(ssl->version)) { + length += HELLO_EXT_SZ; + } +#endif + + if (TLSX_SupportExtensions(ssl)) { + ret = TLSX_GetSize(ssl->extensions, semaphore, msgType, &length); + if (ret != 0) + return ret; + } + + /* All the response data is set at the ssl object only, so no ctx here. */ + + if (length || msgType != server_hello) + length += OPAQUE16_LEN; /* for total length storage. */ + + *pLength += length; + + return ret; +} + +/** Writes the server hello extensions into a buffer. */ +int TLSX_WriteResponse(WOLFSSL *ssl, byte* output, byte msgType, word16* pOffset) +{ + int ret = 0; + word16 offset = 0; + + if (TLSX_SupportExtensions(ssl) && output) { + byte semaphore[SEMAPHORE_SIZE] = {0}; + + switch (msgType) { +#ifndef NO_WOLFSSL_SERVER + case server_hello: + PF_VALIDATE_RESPONSE(ssl, semaphore); + #ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version)) { + XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); + #ifndef WOLFSSL_TLS13_DRAFT_18 + TURN_OFF(semaphore, + TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS)); + #endif + if (!ssl->options.noPskDheKe) + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY)); + #endif + } + else { + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY)); + #endif + } + #endif + break; + + #ifdef WOLFSSL_TLS13 + case hello_retry_request: + XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); + #ifndef WOLFSSL_TLS13_DRAFT_18 + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS)); + #endif + if (!ssl->options.noPskDheKe) + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); + /* Cookie is written below as last extension. */ + break; + #endif + + #ifdef WOLFSSL_TLS13 + case encrypted_extensions: + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_EC_POINT_FORMATS)); + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SUPPORTED_VERSIONS)); + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_SESSION_TICKET)); + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_KEY_SHARE)); + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_PRE_SHARED_KEY)); + #endif + #ifdef HAVE_CERTIFICATE_STATUS_REQUEST + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST)); + #endif + #if defined(HAVE_SECURE_RENEGOTIATION) + TURN_ON(semaphore, TLSX_ToSemaphore(TLSX_RENEGOTIATION_INFO)); + #endif + break; + + #ifdef WOLFSSL_EARLY_DATA + case session_ticket: + if (ssl->options.tls1_3) { + XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_EARLY_DATA)); + } + break; + #endif + #endif +#endif + + #ifdef WOLFSSL_TLS13 + #ifndef NO_CERTS + case certificate: + XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_STATUS_REQUEST)); + /* TODO: TLSX_SIGNED_CERTIFICATE_TIMESTAMP, + * TLSX_SERVER_CERTIFICATE_TYPE + */ + break; + #endif + #endif + } + + offset += OPAQUE16_LEN; /* extensions length */ + + ret = TLSX_Write(ssl->extensions, output + offset, semaphore, + msgType, &offset); + if (ret != 0) + return ret; + +#ifdef WOLFSSL_TLS13 + if (msgType == hello_retry_request) { + XMEMSET(semaphore, 0xff, SEMAPHORE_SIZE); + TURN_OFF(semaphore, TLSX_ToSemaphore(TLSX_COOKIE)); + ret = TLSX_Write(ssl->extensions, output + offset, semaphore, + msgType, &offset); + if (ret != 0) + return ret; + } +#endif + +#ifdef HAVE_EXTENDED_MASTER + if (ssl->options.haveEMS && msgType == server_hello && + !IsAtLeastTLSv1_3(ssl->version)) { + WOLFSSL_MSG("EMS extension to write"); + c16toa(HELLO_EXT_EXTMS, output + offset); + offset += HELLO_EXT_TYPE_SZ; + c16toa(0, output + offset); + offset += HELLO_EXT_SZ_SZ; + } +#endif + + if (offset > OPAQUE16_LEN || msgType != server_hello) + c16toa(offset - OPAQUE16_LEN, output); /* extensions length */ + } + + if (pOffset) + *pOffset += offset; + + return ret; +} + +#endif /* WOLFSSL_TLS13 || !NO_WOLFSSL_SERVER */ + +#ifdef WOLFSSL_TLS13 +int TLSX_ParseVersion(WOLFSSL* ssl, byte* input, word16 length, byte msgType, + int* found) +{ + int ret = 0; + int offset = 0; + + *found = 0; + while (offset < (int)length) { + word16 type; + word16 size; + + if (offset + (2 * OPAQUE16_LEN) > length) { + ret = BUFFER_ERROR; + break; + } + + ato16(input + offset, &type); + offset += HELLO_EXT_TYPE_SZ; + + ato16(input + offset, &size); + offset += OPAQUE16_LEN; + + if (offset + size > length) { + ret = BUFFER_ERROR; + break; + } + + if (type == TLSX_SUPPORTED_VERSIONS) { + *found = 1; + + WOLFSSL_MSG("Supported Versions extension received"); + + ret = SV_PARSE(ssl, input + offset, size, msgType); + break; + } + + offset += size; + } + + return ret; +} +#endif + +/** Parses a buffer of TLS extensions. */ +int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, byte msgType, + Suites *suites) +{ + int ret = 0; + word16 offset = 0; + byte isRequest = (msgType == client_hello || + msgType == certificate_request); + +#ifdef HAVE_EXTENDED_MASTER + byte pendingEMS = 0; +#endif +#if defined(WOLFSSL_TLS13) && (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)) + int pskDone = 0; +#endif + + if (!ssl || !input || (isRequest && !suites)) + return BAD_FUNC_ARG; + + while (ret == 0 && offset < length) { + word16 type; + word16 size; + +#if defined(WOLFSSL_TLS13) && (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)) + if (msgType == client_hello && pskDone) + return PSK_KEY_ERROR; +#endif + + if (length - offset < HELLO_EXT_TYPE_SZ + OPAQUE16_LEN) + return BUFFER_ERROR; + + ato16(input + offset, &type); + offset += HELLO_EXT_TYPE_SZ; + + ato16(input + offset, &size); + offset += OPAQUE16_LEN; + + if (offset + size > length) + return BUFFER_ERROR; + + switch (type) { + case TLSX_SERVER_NAME: + WOLFSSL_MSG("SNI extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif + +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello && + msgType != server_hello && + msgType != encrypted_extensions) { + return EXT_NOT_ALLOWED; + } + else if (!IsAtLeastTLSv1_3(ssl->version) && + msgType == encrypted_extensions) { + return EXT_NOT_ALLOWED; + } +#endif + ret = SNI_PARSE(ssl, input + offset, size, isRequest); + break; + + case TLSX_TRUSTED_CA_KEYS: + WOLFSSL_MSG("Trusted CA extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif + +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello && + msgType != encrypted_extensions) { + return EXT_NOT_ALLOWED; + } +#endif + ret = TCA_PARSE(ssl, input + offset, size, isRequest); + break; + + case TLSX_MAX_FRAGMENT_LENGTH: + WOLFSSL_MSG("Max Fragment Length extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif + +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello && + msgType != encrypted_extensions) { + return EXT_NOT_ALLOWED; + } + else if (!IsAtLeastTLSv1_3(ssl->version) && + msgType == encrypted_extensions) { + return EXT_NOT_ALLOWED; + } +#endif + ret = MFL_PARSE(ssl, input + offset, size, isRequest); + break; + + case TLSX_TRUNCATED_HMAC: + WOLFSSL_MSG("Truncated HMAC extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif + +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version)) + break; +#endif + ret = THM_PARSE(ssl, input + offset, size, isRequest); + break; + + case TLSX_SUPPORTED_GROUPS: + WOLFSSL_MSG("Supported Groups extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif + +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello && + msgType != server_hello && + msgType != encrypted_extensions) { + return EXT_NOT_ALLOWED; + } + else if (!IsAtLeastTLSv1_3(ssl->version) && + msgType == encrypted_extensions) { + return EXT_NOT_ALLOWED; + } +#endif + ret = EC_PARSE(ssl, input + offset, size, isRequest); + break; + + case TLSX_EC_POINT_FORMATS: + WOLFSSL_MSG("Point Formats extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif + +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version)) + break; +#endif + ret = PF_PARSE(ssl, input + offset, size, isRequest); + break; + + case TLSX_STATUS_REQUEST: + WOLFSSL_MSG("Certificate Status Request extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif + + #ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello && + msgType != certificate_request && + msgType != certificate) { + break; + } + #endif + ret = CSR_PARSE(ssl, input + offset, size, isRequest); + break; + + case TLSX_STATUS_REQUEST_V2: + WOLFSSL_MSG("Certificate Status Request v2 extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif + +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello && + msgType != certificate_request && + msgType != certificate) { + return EXT_NOT_ALLOWED; + } +#endif + ret = CSR2_PARSE(ssl, input + offset, size, isRequest); + break; + +#ifdef HAVE_EXTENDED_MASTER + case HELLO_EXT_EXTMS: + WOLFSSL_MSG("Extended Master Secret extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif + +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version)) + break; +#endif + if (size != 0) + return BUFFER_ERROR; + +#ifndef NO_WOLFSSL_SERVER + if (isRequest) + ssl->options.haveEMS = 1; +#endif + pendingEMS = 1; + break; +#endif + + case TLSX_RENEGOTIATION_INFO: + WOLFSSL_MSG("Secure Renegotiation extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif + +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version)) + break; +#endif + ret = SCR_PARSE(ssl, input + offset, size, isRequest); + break; + + case TLSX_SESSION_TICKET: + WOLFSSL_MSG("Session Ticket extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif + +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello) { + return EXT_NOT_ALLOWED; + } +#endif + ret = WOLF_STK_PARSE(ssl, input + offset, size, isRequest); + break; + + case TLSX_QUANTUM_SAFE_HYBRID: + WOLFSSL_MSG("Quantum-Safe-Hybrid extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif + +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version)) + break; +#endif + ret = QSH_PARSE(ssl, input + offset, size, isRequest); + break; + + case TLSX_APPLICATION_LAYER_PROTOCOL: + WOLFSSL_MSG("ALPN extension received"); + + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif + +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello && + msgType != server_hello && + msgType != encrypted_extensions) { + return EXT_NOT_ALLOWED; + } + else if (!IsAtLeastTLSv1_3(ssl->version) && + msgType == encrypted_extensions) { + return EXT_NOT_ALLOWED; + } +#endif + ret = ALPN_PARSE(ssl, input + offset, size, isRequest); + break; +#if !defined(WOLFSSL_NO_SIGALG) + case TLSX_SIGNATURE_ALGORITHMS: + WOLFSSL_MSG("Signature Algorithms extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif + + if (!IsAtLeastTLSv1_2(ssl)) + break; +#ifdef WOLFSSL_TLS13 + if (IsAtLeastTLSv1_3(ssl->version) && + msgType != client_hello && + msgType != certificate_request) { + return EXT_NOT_ALLOWED; + } +#endif + ret = SA_PARSE(ssl, input + offset, size, isRequest, suites); + break; +#endif +#ifdef WOLFSSL_TLS13 + case TLSX_SUPPORTED_VERSIONS: + WOLFSSL_MSG("Skipping Supported Versions - already processed"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif + + break; + + case TLSX_COOKIE: + WOLFSSL_MSG("Cookie extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif + + if (!IsAtLeastTLSv1_3(ssl->version)) + break; + + if (msgType != client_hello && + msgType != hello_retry_request) { + return EXT_NOT_ALLOWED; + } + + ret = CKE_PARSE(ssl, input + offset, size, msgType); + break; + + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + case TLSX_PRE_SHARED_KEY: + WOLFSSL_MSG("Pre-Shared Key extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif + + if (!IsAtLeastTLSv1_3(ssl->version)) + break; + + if (msgType != client_hello && msgType != server_hello) + return EXT_NOT_ALLOWED; + + ret = PSK_PARSE(ssl, input + offset, size, msgType); + pskDone = 1; + break; + + case TLSX_PSK_KEY_EXCHANGE_MODES: + WOLFSSL_MSG("PSK Key Exchange Modes extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif + + if (!IsAtLeastTLSv1_3(ssl->version)) + break; + + if (msgType != client_hello) + return EXT_NOT_ALLOWED; + + ret = PKM_PARSE(ssl, input + offset, size, msgType); + break; + #endif + + #ifdef WOLFSSL_EARLY_DATA + case TLSX_EARLY_DATA: + WOLFSSL_MSG("Early Data extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif + + if (!IsAtLeastTLSv1_3(ssl->version)) + break; + + if (msgType != client_hello && msgType != session_ticket && + msgType != encrypted_extensions) { + return EXT_NOT_ALLOWED; + } + if (!IsAtLeastTLSv1_3(ssl->version) && + (msgType == session_ticket || + msgType == encrypted_extensions)) { + return EXT_NOT_ALLOWED; + } + ret = EDI_PARSE(ssl, input + offset, size, msgType); + break; + #endif + + #ifdef WOLFSSL_POST_HANDSHAKE_AUTH + case TLSX_POST_HANDSHAKE_AUTH: + WOLFSSL_MSG("Post Handshake Authentication extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif + + if (!IsAtLeastTLSv1_3(ssl->version)) + break; + + if (msgType != client_hello) + return EXT_NOT_ALLOWED; + + ret = PHA_PARSE(ssl, input + offset, size, msgType); + break; + #endif + + #if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22) + case TLSX_SIGNATURE_ALGORITHMS_CERT: + WOLFSSL_MSG("Signature Algorithms extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif + + if (!IsAtLeastTLSv1_3(ssl->version)) + break; + + if (msgType != client_hello && + msgType != certificate_request) { + return EXT_NOT_ALLOWED; + } + if (!IsAtLeastTLSv1_3(ssl->version) && + msgType == certificate_request) { + return EXT_NOT_ALLOWED; + } + + ret = SAC_PARSE(ssl, input + offset, size, isRequest); + break; + #endif + + case TLSX_KEY_SHARE: + WOLFSSL_MSG("Key Share extension received"); + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_BUFFER(input + offset, size); + #endif + + if (!IsAtLeastTLSv1_3(ssl->version)) + break; + + if (msgType != client_hello && msgType != server_hello && + msgType != hello_retry_request) { + return EXT_NOT_ALLOWED; + } + ret = KS_PARSE(ssl, input + offset, size, msgType); + break; +#endif + } + + /* offset should be updated here! */ + offset += size; + } + +#ifdef HAVE_EXTENDED_MASTER + if (!isRequest && ssl->options.haveEMS && !pendingEMS) + ssl->options.haveEMS = 0; +#endif + + if (ret == 0) + ret = SNI_VERIFY_PARSE(ssl, isRequest); + if (ret == 0) + ret = TCA_VERIFY_PARSE(ssl, isRequest); + + return ret; +} + +/* undefining semaphore macros */ +#undef IS_OFF +#undef TURN_ON +#undef SEMAPHORE_SIZE + +#endif /* HAVE_TLS_EXTENSIONS */ + +#ifndef NO_WOLFSSL_CLIENT + +#ifndef NO_OLD_TLS + #ifdef WOLFSSL_ALLOW_TLSV10 + WOLFSSL_METHOD* wolfTLSv1_client_method(void) + { + return wolfTLSv1_client_method_ex(NULL); + } + WOLFSSL_METHOD* wolfTLSv1_client_method_ex(void* heap) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + heap, DYNAMIC_TYPE_METHOD); + (void)heap; + WOLFSSL_ENTER("TLSv1_client_method_ex"); + if (method) + InitSSL_Method(method, MakeTLSv1()); + return method; + } + #endif /* WOLFSSL_ALLOW_TLSV10 */ + + WOLFSSL_METHOD* wolfTLSv1_1_client_method(void) + { + return wolfTLSv1_1_client_method_ex(NULL); + } + WOLFSSL_METHOD* wolfTLSv1_1_client_method_ex(void* heap) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + heap, DYNAMIC_TYPE_METHOD); + (void)heap; + WOLFSSL_ENTER("TLSv1_1_client_method_ex"); + if (method) + InitSSL_Method(method, MakeTLSv1_1()); + return method; + } +#endif /* !NO_OLD_TLS */ + +#ifndef WOLFSSL_NO_TLS12 + WOLFSSL_METHOD* wolfTLSv1_2_client_method(void) + { + return wolfTLSv1_2_client_method_ex(NULL); + } + WOLFSSL_METHOD* wolfTLSv1_2_client_method_ex(void* heap) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + heap, DYNAMIC_TYPE_METHOD); + (void)heap; + WOLFSSL_ENTER("TLSv1_2_client_method_ex"); + if (method) + InitSSL_Method(method, MakeTLSv1_2()); + return method; + } +#endif /* WOLFSSL_NO_TLS12 */ + +#ifdef WOLFSSL_TLS13 + /* The TLS v1.3 client method data. + * + * returns the method data for a TLS v1.3 client. + */ + WOLFSSL_METHOD* wolfTLSv1_3_client_method(void) + { + return wolfTLSv1_3_client_method_ex(NULL); + } + + /* The TLS v1.3 client method data. + * + * heap The heap used for allocation. + * returns the method data for a TLS v1.3 client. + */ + WOLFSSL_METHOD* wolfTLSv1_3_client_method_ex(void* heap) + { + WOLFSSL_METHOD* method = (WOLFSSL_METHOD*) + XMALLOC(sizeof(WOLFSSL_METHOD), heap, + DYNAMIC_TYPE_METHOD); + (void)heap; + WOLFSSL_ENTER("TLSv1_3_client_method_ex"); + if (method) + InitSSL_Method(method, MakeTLSv1_3()); + return method; + } +#endif /* WOLFSSL_TLS13 */ + +#ifdef WOLFSSL_DTLS + + WOLFSSL_METHOD* wolfDTLS_client_method(void) + { + return wolfDTLS_client_method_ex(NULL); + } + WOLFSSL_METHOD* wolfDTLS_client_method_ex(void* heap) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + heap, DYNAMIC_TYPE_METHOD); + (void)heap; + WOLFSSL_ENTER("DTLS_client_method_ex"); + if (method) { + #if !defined(WOLFSSL_NO_TLS12) + InitSSL_Method(method, MakeDTLSv1_2()); + #elif !defined(NO_OLD_TLS) + InitSSL_Method(method, MakeDTLSv1()); + #else + #error No DTLS version enabled! + #endif + + method->downgrade = 1; + method->side = WOLFSSL_CLIENT_END; + } + return method; + } + + #ifndef NO_OLD_TLS + WOLFSSL_METHOD* wolfDTLSv1_client_method(void) + { + return wolfDTLSv1_client_method_ex(NULL); + } + WOLFSSL_METHOD* wolfDTLSv1_client_method_ex(void* heap) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + heap, DYNAMIC_TYPE_METHOD); + (void)heap; + WOLFSSL_ENTER("DTLSv1_client_method_ex"); + if (method) + InitSSL_Method(method, MakeDTLSv1()); + return method; + } + #endif /* NO_OLD_TLS */ + + #ifndef WOLFSSL_NO_TLS12 + WOLFSSL_METHOD* wolfDTLSv1_2_client_method(void) + { + return wolfDTLSv1_2_client_method_ex(NULL); + } + WOLFSSL_METHOD* wolfDTLSv1_2_client_method_ex(void* heap) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + heap, DYNAMIC_TYPE_METHOD); + (void)heap; + WOLFSSL_ENTER("DTLSv1_2_client_method_ex"); + if (method) + InitSSL_Method(method, MakeDTLSv1_2()); + (void)heap; + return method; + } + #endif /* !WOLFSSL_NO_TLS12 */ +#endif /* WOLFSSL_DTLS */ + +#endif /* NO_WOLFSSL_CLIENT */ + + +/* EITHER SIDE METHODS */ +#if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EITHER_SIDE) + #ifndef NO_OLD_TLS + #ifdef WOLFSSL_ALLOW_TLSV10 + /* Gets a WOLFSL_METHOD type that is not set as client or server + * + * Returns a pointer to a WOLFSSL_METHOD struct + */ + WOLFSSL_METHOD* wolfTLSv1_method(void) + { + return wolfTLSv1_method_ex(NULL); + } + WOLFSSL_METHOD* wolfTLSv1_method_ex(void* heap) + { + WOLFSSL_METHOD* m; + WOLFSSL_ENTER("TLSv1_method"); + #ifndef NO_WOLFSSL_CLIENT + m = wolfTLSv1_client_method_ex(heap); + #else + m = wolfTLSv1_server_method_ex(heap); + #endif + if (m != NULL) { + m->side = WOLFSSL_NEITHER_END; + } + + return m; + } + #endif /* WOLFSSL_ALLOW_TLSV10 */ + + /* Gets a WOLFSL_METHOD type that is not set as client or server + * + * Returns a pointer to a WOLFSSL_METHOD struct + */ + WOLFSSL_METHOD* wolfTLSv1_1_method(void) + { + return wolfTLSv1_1_method_ex(NULL); + } + WOLFSSL_METHOD* wolfTLSv1_1_method_ex(void* heap) + { + WOLFSSL_METHOD* m; + WOLFSSL_ENTER("TLSv1_1_method"); + #ifndef NO_WOLFSSL_CLIENT + m = wolfTLSv1_1_client_method_ex(heap); + #else + m = wolfTLSv1_1_server_method_ex(heap); + #endif + if (m != NULL) { + m->side = WOLFSSL_NEITHER_END; + } + return m; + } + #endif /* !NO_OLD_TLS */ + + #ifndef WOLFSSL_NO_TLS12 + /* Gets a WOLFSL_METHOD type that is not set as client or server + * + * Returns a pointer to a WOLFSSL_METHOD struct + */ + WOLFSSL_METHOD* wolfTLSv1_2_method(void) + { + return wolfTLSv1_2_method_ex(NULL); + } + WOLFSSL_METHOD* wolfTLSv1_2_method_ex(void* heap) + { + WOLFSSL_METHOD* m; + WOLFSSL_ENTER("TLSv1_2_method"); + #ifndef NO_WOLFSSL_CLIENT + m = wolfTLSv1_2_client_method_ex(heap); + #else + m = wolfTLSv1_2_server_method_ex(heap); + #endif + if (m != NULL) { + m->side = WOLFSSL_NEITHER_END; + } + return m; + } + #endif /* !WOLFSSL_NO_TLS12 */ + + #ifdef WOLFSSL_TLS13 + /* Gets a WOLFSL_METHOD type that is not set as client or server + * + * Returns a pointer to a WOLFSSL_METHOD struct + */ + WOLFSSL_METHOD* wolfTLSv1_3_method(void) + { + return wolfTLSv1_3_method_ex(NULL); + } + WOLFSSL_METHOD* wolfTLSv1_3_method_ex(void* heap) + { + WOLFSSL_METHOD* m; + WOLFSSL_ENTER("TLSv1_3_method"); + #ifndef NO_WOLFSSL_CLIENT + m = wolfTLSv1_3_client_method_ex(heap); + #else + m = wolfTLSv1_3_server_method_ex(heap); + #endif + if (m != NULL) { + m->side = WOLFSSL_NEITHER_END; + } + return m; + } + #endif /* WOLFSSL_TLS13 */ + +#ifdef WOLFSSL_DTLS + WOLFSSL_METHOD* wolfDTLS_method(void) + { + return wolfDTLS_method_ex(NULL); + } + WOLFSSL_METHOD* wolfDTLS_method_ex(void* heap) + { + WOLFSSL_METHOD* m; + WOLFSSL_ENTER("DTLS_method_ex"); + #ifndef NO_WOLFSSL_CLIENT + m = wolfDTLS_client_method_ex(heap); + #else + m = wolfDTLS_server_method_ex(heap); + #endif + if (m != NULL) { + m->side = WOLFSSL_NEITHER_END; + } + return m; + } + + #ifndef NO_OLD_TLS + WOLFSSL_METHOD* wolfDTLSv1_method(void) + { + return wolfDTLSv1_method_ex(NULL); + } + WOLFSSL_METHOD* wolfDTLSv1_method_ex(void* heap) + { + WOLFSSL_METHOD* m; + WOLFSSL_ENTER("DTLSv1_method_ex"); + #ifndef NO_WOLFSSL_CLIENT + m = wolfDTLSv1_client_method_ex(heap); + #else + m = wolfDTLSv1_server_method_ex(heap); + #endif + if (m != NULL) { + m->side = WOLFSSL_NEITHER_END; + } + return m; + } + #endif /* !NO_OLD_TLS */ + #ifndef WOLFSSL_NO_TLS12 + WOLFSSL_METHOD* wolfDTLSv1_2_method(void) + { + return wolfDTLSv1_2_method_ex(NULL); + } + WOLFSSL_METHOD* wolfDTLSv1_2_method_ex(void* heap) + { + WOLFSSL_METHOD* m; + WOLFSSL_ENTER("DTLSv1_2_method"); + #ifndef NO_WOLFSSL_CLIENT + m = wolfDTLSv1_2_client_method_ex(heap); + #else + m = wolfDTLSv1_2_server_method_ex(heap); + #endif + if (m != NULL) { + m->side = WOLFSSL_NEITHER_END; + } + return m; + } + #endif /* !WOLFSSL_NO_TLS12 */ +#endif /* WOLFSSL_DTLS */ +#endif /* OPENSSL_EXTRA || WOLFSSL_EITHER_SIDE */ + + +#ifndef NO_WOLFSSL_SERVER + +#ifndef NO_OLD_TLS + #ifdef WOLFSSL_ALLOW_TLSV10 + WOLFSSL_METHOD* wolfTLSv1_server_method(void) + { + return wolfTLSv1_server_method_ex(NULL); + } + WOLFSSL_METHOD* wolfTLSv1_server_method_ex(void* heap) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + heap, DYNAMIC_TYPE_METHOD); + (void)heap; + WOLFSSL_ENTER("TLSv1_server_method_ex"); + if (method) { + InitSSL_Method(method, MakeTLSv1()); + method->side = WOLFSSL_SERVER_END; + } + return method; + } + #endif /* WOLFSSL_ALLOW_TLSV10 */ + + WOLFSSL_METHOD* wolfTLSv1_1_server_method(void) + { + return wolfTLSv1_1_server_method_ex(NULL); + } + WOLFSSL_METHOD* wolfTLSv1_1_server_method_ex(void* heap) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + heap, DYNAMIC_TYPE_METHOD); + (void)heap; + WOLFSSL_ENTER("TLSv1_1_server_method_ex"); + if (method) { + InitSSL_Method(method, MakeTLSv1_1()); + method->side = WOLFSSL_SERVER_END; + } + return method; + } +#endif /* !NO_OLD_TLS */ + + +#ifndef WOLFSSL_NO_TLS12 + WOLFSSL_METHOD* wolfTLSv1_2_server_method(void) + { + return wolfTLSv1_2_server_method_ex(NULL); + } + WOLFSSL_METHOD* wolfTLSv1_2_server_method_ex(void* heap) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + heap, DYNAMIC_TYPE_METHOD); + (void)heap; + WOLFSSL_ENTER("TLSv1_2_server_method_ex"); + if (method) { + InitSSL_Method(method, MakeTLSv1_2()); + method->side = WOLFSSL_SERVER_END; + } + return method; + } +#endif /* !WOLFSSL_NO_TLS12 */ + +#ifdef WOLFSSL_TLS13 + /* The TLS v1.3 server method data. + * + * returns the method data for a TLS v1.3 server. + */ + WOLFSSL_METHOD* wolfTLSv1_3_server_method(void) + { + return wolfTLSv1_3_server_method_ex(NULL); + } + + /* The TLS v1.3 server method data. + * + * heap The heap used for allocation. + * returns the method data for a TLS v1.3 server. + */ + WOLFSSL_METHOD* wolfTLSv1_3_server_method_ex(void* heap) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + heap, DYNAMIC_TYPE_METHOD); + (void)heap; + WOLFSSL_ENTER("TLSv1_3_server_method_ex"); + if (method) { + InitSSL_Method(method, MakeTLSv1_3()); + method->side = WOLFSSL_SERVER_END; + } + return method; + } +#endif /* WOLFSSL_TLS13 */ + +#ifdef WOLFSSL_DTLS + WOLFSSL_METHOD* wolfDTLS_server_method(void) + { + return wolfDTLS_server_method_ex(NULL); + } + WOLFSSL_METHOD* wolfDTLS_server_method_ex(void* heap) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + heap, DYNAMIC_TYPE_METHOD); + (void)heap; + WOLFSSL_ENTER("DTLS_server_method_ex"); + if (method) { + #if !defined(WOLFSSL_NO_TLS12) + InitSSL_Method(method, MakeDTLSv1_2()); + #elif !defined(NO_OLD_TLS) + InitSSL_Method(method, MakeDTLSv1()); + #else + #error No DTLS version enabled! + #endif + + method->downgrade = 1; + method->side = WOLFSSL_SERVER_END; + } + return method; + } + + #ifndef NO_OLD_TLS + WOLFSSL_METHOD* wolfDTLSv1_server_method(void) + { + return wolfDTLSv1_server_method_ex(NULL); + } + WOLFSSL_METHOD* wolfDTLSv1_server_method_ex(void* heap) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + heap, DYNAMIC_TYPE_METHOD); + (void)heap; + WOLFSSL_ENTER("DTLSv1_server_method_ex"); + if (method) { + InitSSL_Method(method, MakeDTLSv1()); + method->side = WOLFSSL_SERVER_END; + } + return method; + } + #endif /* !NO_OLD_TLS */ + + #ifndef WOLFSSL_NO_TLS12 + WOLFSSL_METHOD* wolfDTLSv1_2_server_method(void) + { + return wolfDTLSv1_2_server_method_ex(NULL); + } + WOLFSSL_METHOD* wolfDTLSv1_2_server_method_ex(void* heap) + { + WOLFSSL_METHOD* method = + (WOLFSSL_METHOD*) XMALLOC(sizeof(WOLFSSL_METHOD), + heap, DYNAMIC_TYPE_METHOD); + WOLFSSL_ENTER("DTLSv1_2_server_method_ex"); + (void)heap; + if (method) { + InitSSL_Method(method, MakeDTLSv1_2()); + method->side = WOLFSSL_SERVER_END; + } + (void)heap; + return method; + } + #endif /* !WOLFSSL_NO_TLS12 */ +#endif /* WOLFSSL_DTLS */ + +#endif /* NO_WOLFSSL_SERVER */ + +#endif /* NO_TLS */ +#endif /* WOLFCRYPT_ONLY */ diff --git a/beken_os/beken378/func/wolfssl/src/tls13.c b/beken_os/beken378/func/wolfssl/src/tls13.c new file mode 100755 index 0000000..fbe3faf --- /dev/null +++ b/beken_os/beken378/func/wolfssl/src/tls13.c @@ -0,0 +1,8719 @@ +/* tls13.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +/* + * BUILD_GCM + * Enables AES-GCM ciphersuites. + * HAVE_AESCCM + * Enables AES-CCM ciphersuites. + * HAVE_SESSION_TICKET + * Enables session tickets - required for TLS 1.3 resumption. + * NO_PSK + * Do not enable Pre-Shared Keys. + * TLS13_SUPPORTS_EXPORTERS + * Guard to compile out any code for exporter keys. + * Feature not supported yet. + * WOLFSSL_ASYNC_CRYPT + * Enables the use of asynchronous cryptographic operations. + * This is available for ciphers and certificates. + * HAVE_CHACHA && HAVE_POLY1305 + * Enables use of CHACHA20-POLY1305 ciphersuites. + * WOLFSSL_DEBUG_TLS + * Writes out details of TLS 1.3 protocol including handshake message buffers + * and key generation input and output. + * WOLFSSL_EARLY_DATA + * Allow 0-RTT Handshake using Early Data extensions and handshake message + * WOLFSSL_EARLY_DATA_GROUP + * Group EarlyData message with ClientHello when sending + * WOLFSSL_NO_SERVER_GROUPS_EXT + * Do not send the server's groups in an extension when the server's top + * preference is not in client's list. + * WOLFSSL_POST_HANDSHAKE_AUTH + * Allow TLS v1.3 code to perform post-handshake authentication of the + * client. + * WOLFSSL_SEND_HRR_COOKIE + * Send a cookie in hello_retry_request message to enable stateless tracking + * of ClientHello replies. + * WOLFSSL_TLS13 + * Enable TLS 1.3 protocol implementation. + * WOLFSSL_TLS13_DRAFT_18 + * Conform with Draft 18 of the TLS v1.3 specification. + * WOLFSSL_TLS13_DRAFT_22 + * Conform with Draft 22 of the TLS v1.3 specification. + * WOLFSSL_TLS13_DRAFT_23 + * Conform with Draft 23 of the TLS v1.3 specification. + * WOLFSSL_TLS13_MIDDLEBOX_COMPAT + * Enable middlebox compatibility in the TLS 1.3 handshake. + * This includes sending ChangeCipherSpec before encrypted messages and + * including a session id. + * WOLFSSL_TLS13_SHA512 + * Allow generation of SHA-512 digests in handshake - no ciphersuite + * requires SHA-512 at this time. + * WOLFSSL_TLS13_TICKET_BEFORE_FINISHED + * Allow a NewSessionTicket message to be sent by server before Client's + * Finished message. + * See TLS v1.3 specification, Section 4.6.1, Paragraph 4 (Note). + */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifdef WOLFSSL_TLS13 +#ifdef HAVE_SESSION_TICKET + #include +#endif + +#ifndef WOLFCRYPT_ONLY + +#ifdef HAVE_ERRNO_H + #include +#endif + +#include +#include +#include +#include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#ifdef HAVE_NTRU + #include "libntruencrypt/ntru_crypto.h" +#endif + +#if defined(DEBUG_WOLFSSL) || defined(WOLFSSL_DEBUG) || \ + defined(CHACHA_AEAD_TEST) || defined(WOLFSSL_SESSION_EXPORT_DEBUG) + #if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) + #if MQX_USE_IO_OLD + #include + #else + #include + #endif + #else + #include + #endif +#endif + +#ifdef __sun + #include +#endif + +#ifndef TRUE + #define TRUE 1 +#endif +#ifndef FALSE + #define FALSE 0 +#endif + +#ifndef HAVE_HKDF + #error The build option HAVE_HKDF is required for TLS 1.3 +#endif + +#ifndef HAVE_TLS_EXTENSIONS + #ifndef _MSC_VER + #error "The build option HAVE_TLS_EXTENSIONS is required for TLS 1.3" + #else + #pragma message("error: The build option HAVE_TLS_EXTENSIONS is required for TLS 1.3") + #endif +#endif + + +/* Set ret to error value and jump to label. + * + * err The error value to set. + * eLabel The label to jump to. + */ +#define ERROR_OUT(err, eLabel) { ret = (err); goto eLabel; } + + +/* Extract data using HMAC, salt and input. + * RFC 5869 - HMAC-based Extract-and-Expand Key Derivation Function (HKDF) + * + * prk The generated pseudorandom key. + * salt The salt. + * saltLen The length of the salt. + * ikm The input keying material. + * ikmLen The length of the input keying material. + * mac The type of digest to use. + * returns 0 on success, otherwise failure. + */ +static int Tls13_HKDF_Extract(byte* prk, const byte* salt, int saltLen, + byte* ikm, int ikmLen, int mac) +{ + int ret; + int hash = 0; + int len = 0; + + switch (mac) { + #ifndef NO_SHA256 + case sha256_mac: + hash = WC_SHA256; + len = WC_SHA256_DIGEST_SIZE; + break; + #endif + + #ifdef WOLFSSL_SHA384 + case sha384_mac: + hash = WC_SHA384; + len = WC_SHA384_DIGEST_SIZE; + break; + #endif + + #ifdef WOLFSSL_TLS13_SHA512 + case sha512_mac: + hash = WC_SHA512; + len = WC_SHA512_DIGEST_SIZE; + break; + #endif + } + + /* When length is 0 then use zeroed data of digest length. */ + if (ikmLen == 0) { + ikmLen = len; + XMEMSET(ikm, 0, len); + } + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG(" Salt"); + WOLFSSL_BUFFER(salt, saltLen); + WOLFSSL_MSG(" IKM"); + WOLFSSL_BUFFER(ikm, ikmLen); +#endif + + ret = wc_HKDF_Extract(hash, salt, saltLen, ikm, ikmLen, prk); + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG(" PRK"); + WOLFSSL_BUFFER(prk, len); +#endif + + return ret; +} + +/* Expand data using HMAC, salt and label and info. + * TLS v1.3 defines this function. + * + * okm The generated pseudorandom key - output key material. + * okmLen The length of generated pseudorandom key - output key material. + * prk The salt - pseudo-random key. + * prkLen The length of the salt - pseudo-random key. + * protocol The TLS protocol label. + * protocolLen The length of the TLS protocol label. + * info The information to expand. + * infoLen The length of the information. + * digest The type of digest to use. + * returns 0 on success, otherwise failure. + */ +static int HKDF_Expand_Label(byte* okm, word32 okmLen, + const byte* prk, word32 prkLen, + const byte* protocol, word32 protocolLen, + const byte* label, word32 labelLen, + const byte* info, word32 infoLen, + int digest) +{ + int ret = 0; + int idx = 0; + byte data[MAX_HKDF_LABEL_SZ]; + + /* Output length. */ + data[idx++] = (byte)(okmLen >> 8); + data[idx++] = (byte)okmLen; + /* Length of protocol | label. */ + data[idx++] = (byte)(protocolLen + labelLen); + /* Protocol */ + XMEMCPY(&data[idx], protocol, protocolLen); + idx += protocolLen; + /* Label */ + XMEMCPY(&data[idx], label, labelLen); + idx += labelLen; + /* Length of hash of messages */ + data[idx++] = (byte)infoLen; + /* Hash of messages */ + XMEMCPY(&data[idx], info, infoLen); + idx += infoLen; + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG(" PRK"); + WOLFSSL_BUFFER(prk, prkLen); + WOLFSSL_MSG(" Info"); + WOLFSSL_BUFFER(data, idx); +#endif + + ret = wc_HKDF_Expand(digest, prk, prkLen, data, idx, okm, okmLen); + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG(" OKM"); + WOLFSSL_BUFFER(okm, okmLen); +#endif + + ForceZero(data, idx); + + return ret; +} + +#ifdef WOLFSSL_TLS13_DRAFT_18 +/* Size of the TLS v1.3 label use when deriving keys. */ +#define TLS13_PROTOCOL_LABEL_SZ 9 +/* The protocol label for TLS v1.3. */ +static const byte tls13ProtocolLabel[TLS13_PROTOCOL_LABEL_SZ + 1] = "TLS 1.3, "; +#else +/* Size of the TLS v1.3 label use when deriving keys. */ +#define TLS13_PROTOCOL_LABEL_SZ 6 +/* The protocol label for TLS v1.3. */ +static const byte tls13ProtocolLabel[TLS13_PROTOCOL_LABEL_SZ + 1] = "tls13 "; +#endif + +#if !defined(WOLFSSL_TLS13_DRAFT_18) || defined(HAVE_SESSION_TICKET) || \ + !defined(NO_PSK) +/* Derive a key from a message. + * + * ssl The SSL/TLS object. + * output The buffer to hold the derived key. + * outputLen The length of the derived key. + * secret The secret used to derive the key (HMAC secret). + * label The label used to distinguish the context. + * labelLen The length of the label. + * msg The message data to derive key from. + * msgLen The length of the message data to derive key from. + * hashAlgo The hash algorithm to use in the HMAC. + * returns 0 on success, otherwise failure. + */ +static int DeriveKeyMsg(WOLFSSL* ssl, byte* output, int outputLen, + const byte* secret, const byte* label, word32 labelLen, + byte* msg, int msgLen, int hashAlgo) +{ + byte hash[WC_MAX_DIGEST_SIZE]; + Digest digest; + word32 hashSz = 0; + const byte* protocol; + word32 protocolLen; + int digestAlg = -1; + int ret = BAD_FUNC_ARG; + + switch (hashAlgo) { +#ifndef NO_WOLFSSL_SHA256 + case sha256_mac: + ret = wc_InitSha256_ex(&digest.sha256, ssl->heap, INVALID_DEVID); + if (ret == 0) { + ret = wc_Sha256Update(&digest.sha256, msg, msgLen); + if (ret == 0) + ret = wc_Sha256Final(&digest.sha256, hash); + wc_Sha256Free(&digest.sha256); + } + hashSz = WC_SHA256_DIGEST_SIZE; + digestAlg = WC_SHA256; + break; +#endif +#ifdef WOLFSSL_SHA384 + case sha384_mac: + ret = wc_InitSha384_ex(&digest.sha384, ssl->heap, INVALID_DEVID); + if (ret == 0) { + ret = wc_Sha384Update(&digest.sha384, msg, msgLen); + if (ret == 0) + ret = wc_Sha384Final(&digest.sha384, hash); + wc_Sha384Free(&digest.sha384); + } + hashSz = WC_SHA384_DIGEST_SIZE; + digestAlg = WC_SHA384; + break; +#endif +#ifdef WOLFSSL_TLS13_SHA512 + case sha512_mac: + ret = wc_InitSha512_ex(&digest.sha512, ssl->heap, INVALID_DEVID); + if (ret == 0) { + ret = wc_Sha512Update(&digest.sha512, msg, msgLen); + if (ret == 0) + ret = wc_Sha512Final(&digest.sha512, hash); + wc_Sha512Free(&digest.sha512); + } + hashSz = WC_SHA512_DIGEST_SIZE; + digestAlg = WC_SHA512; + break; +#endif + default: + digestAlg = -1; + break; + } + + if (digestAlg < 0) + return HASH_TYPE_E; + + if (ret != 0) + return ret; + + switch (ssl->version.minor) { + case TLSv1_3_MINOR: + protocol = tls13ProtocolLabel; + protocolLen = TLS13_PROTOCOL_LABEL_SZ; + break; + + default: + return VERSION_ERROR; + } + if (outputLen == -1) + outputLen = hashSz; + + return HKDF_Expand_Label(output, outputLen, secret, hashSz, + protocol, protocolLen, label, labelLen, + hash, hashSz, digestAlg); +} +#endif + +/* Derive a key. + * + * ssl The SSL/TLS object. + * output The buffer to hold the derived key. + * outputLen The length of the derived key. + * secret The secret used to derive the key (HMAC secret). + * label The label used to distinguish the context. + * labelLen The length of the label. + * hashAlgo The hash algorithm to use in the HMAC. + * includeMsgs Whether to include a hash of the handshake messages so far. + * returns 0 on success, otherwise failure. + */ +static int DeriveKey(WOLFSSL* ssl, byte* output, int outputLen, + const byte* secret, const byte* label, word32 labelLen, + int hashAlgo, int includeMsgs) +{ + int ret = 0; + byte hash[WC_MAX_DIGEST_SIZE]; + word32 hashSz = 0; + word32 hashOutSz = 0; + const byte* protocol; + word32 protocolLen; + int digestAlg = 0; + + switch (hashAlgo) { + #ifndef NO_SHA256 + case sha256_mac: + hashSz = WC_SHA256_DIGEST_SIZE; + digestAlg = WC_SHA256; + if (includeMsgs) + ret = wc_Sha256GetHash(&ssl->hsHashes->hashSha256, hash); + break; + #endif + + #ifdef WOLFSSL_SHA384 + case sha384_mac: + hashSz = WC_SHA384_DIGEST_SIZE; + digestAlg = WC_SHA384; + if (includeMsgs) + ret = wc_Sha384GetHash(&ssl->hsHashes->hashSha384, hash); + break; + #endif + + #ifdef WOLFSSL_TLS13_SHA512 + case sha512_mac: + hashSz = WC_SHA512_DIGEST_SIZE; + digestAlg = WC_SHA512; + if (includeMsgs) + ret = wc_Sha512GetHash(&ssl->hsHashes->hashSha512, hash); + break; + #endif + } + if (ret != 0) + return ret; + + /* Only one protocol version defined at this time. */ + protocol = tls13ProtocolLabel; + protocolLen = TLS13_PROTOCOL_LABEL_SZ; + + if (outputLen == -1) + outputLen = hashSz; + if (includeMsgs) + hashOutSz = hashSz; + + return HKDF_Expand_Label(output, outputLen, secret, hashSz, + protocol, protocolLen, label, labelLen, + hash, hashOutSz, digestAlg); +} + + +#ifndef NO_PSK +#ifdef WOLFSSL_TLS13_DRAFT_18 +/* The length of the binder key label. */ +#define BINDER_KEY_LABEL_SZ 23 +/* The binder key label. */ +static const byte binderKeyLabel[BINDER_KEY_LABEL_SZ + 1] = + "external psk binder key"; +#else +/* The length of the binder key label. */ +#define BINDER_KEY_LABEL_SZ 10 +/* The binder key label. */ +static const byte binderKeyLabel[BINDER_KEY_LABEL_SZ + 1] = + "ext binder"; +#endif +/* Derive the binder key. + * + * ssl The SSL/TLS object. + * key The derived key. + * returns 0 on success, otherwise failure. + */ +static int DeriveBinderKey(WOLFSSL* ssl, byte* key) +{ + WOLFSSL_MSG("Derive Binder Key"); + return DeriveKeyMsg(ssl, key, -1, ssl->arrays->secret, + binderKeyLabel, BINDER_KEY_LABEL_SZ, + NULL, 0, ssl->specs.mac_algorithm); +} +#endif /* !NO_PSK */ + +#ifdef HAVE_SESSION_TICKET +#ifdef WOLFSSL_TLS13_DRAFT_18 +/* The length of the binder key resume label. */ +#define BINDER_KEY_RESUME_LABEL_SZ 25 +/* The binder key resume label. */ +static const byte binderKeyResumeLabel[BINDER_KEY_RESUME_LABEL_SZ + 1] = + "resumption psk binder key"; +#else +/* The length of the binder key resume label. */ +#define BINDER_KEY_RESUME_LABEL_SZ 10 +/* The binder key resume label. */ +static const byte binderKeyResumeLabel[BINDER_KEY_RESUME_LABEL_SZ + 1] = + "res binder"; +#endif +/* Derive the binder resumption key. + * + * ssl The SSL/TLS object. + * key The derived key. + * returns 0 on success, otherwise failure. + */ +static int DeriveBinderKeyResume(WOLFSSL* ssl, byte* key) +{ + WOLFSSL_MSG("Derive Binder Key - Resumption"); + return DeriveKeyMsg(ssl, key, -1, ssl->arrays->secret, + binderKeyResumeLabel, BINDER_KEY_RESUME_LABEL_SZ, + NULL, 0, ssl->specs.mac_algorithm); +} +#endif /* HAVE_SESSION_TICKET */ + +#ifdef WOLFSSL_EARLY_DATA +#ifdef WOLFSSL_TLS13_DRAFT_18 +/* The length of the early traffic label. */ +#define EARLY_TRAFFIC_LABEL_SZ 27 +/* The early traffic label. */ +static const byte earlyTrafficLabel[EARLY_TRAFFIC_LABEL_SZ + 1] = + "client early traffic secret"; +#else +/* The length of the early traffic label. */ +#define EARLY_TRAFFIC_LABEL_SZ 11 +/* The early traffic label. */ +static const byte earlyTrafficLabel[EARLY_TRAFFIC_LABEL_SZ + 1] = + "c e traffic"; +#endif +/* Derive the early traffic key. + * + * ssl The SSL/TLS object. + * key The derived key. + * returns 0 on success, otherwise failure. + */ +static int DeriveEarlyTrafficSecret(WOLFSSL* ssl, byte* key) +{ + WOLFSSL_MSG("Derive Early Traffic Secret"); + return DeriveKey(ssl, key, -1, ssl->arrays->secret, + earlyTrafficLabel, EARLY_TRAFFIC_LABEL_SZ, + ssl->specs.mac_algorithm, 1); +} + +#ifdef TLS13_SUPPORTS_EXPORTERS +#ifdef WOLFSSL_TLS13_DRAFT_18 +/* The length of the early exporter label. */ +#define EARLY_EXPORTER_LABEL_SZ 28 +/* The early exporter label. */ +static const byte earlyExporterLabel[EARLY_EXPORTER_LABEL_SZ + 1] = + "early exporter master secret"; +#else +/* The length of the early exporter label. */ +#define EARLY_EXPORTER_LABEL_SZ 12 +/* The early exporter label. */ +static const byte earlyExporterLabel[EARLY_EXPORTER_LABEL_SZ + 1] = + "e exp master"; +#endif +/* Derive the early exporter key. + * + * ssl The SSL/TLS object. + * key The derived key. + * returns 0 on success, otherwise failure. + */ +static int DeriveEarlyExporterSecret(WOLFSSL* ssl, byte* key) +{ + WOLFSSL_MSG("Derive Early Exporter Secret"); + return DeriveKey(ssl, key, -1, ssl->arrays->secret, + earlyExporterLabel, EARLY_EXPORTER_LABEL_SZ, + ssl->specs.mac_algorithm, 1); +} +#endif +#endif + +#ifdef WOLFSSL_TLS13_DRAFT_18 +/* The length of the client handshake label. */ +#define CLIENT_HANDSHAKE_LABEL_SZ 31 +/* The client handshake label. */ +static const byte clientHandshakeLabel[CLIENT_HANDSHAKE_LABEL_SZ + 1] = + "client handshake traffic secret"; +#else +/* The length of the client handshake label. */ +#define CLIENT_HANDSHAKE_LABEL_SZ 12 +/* The client handshake label. */ +static const byte clientHandshakeLabel[CLIENT_HANDSHAKE_LABEL_SZ + 1] = + "c hs traffic"; +#endif +/* Derive the client handshake key. + * + * ssl The SSL/TLS object. + * key The derived key. + * returns 0 on success, otherwise failure. + */ +static int DeriveClientHandshakeSecret(WOLFSSL* ssl, byte* key) +{ + WOLFSSL_MSG("Derive Client Handshake Secret"); + return DeriveKey(ssl, key, -1, ssl->arrays->preMasterSecret, + clientHandshakeLabel, CLIENT_HANDSHAKE_LABEL_SZ, + ssl->specs.mac_algorithm, 1); +} + +#ifdef WOLFSSL_TLS13_DRAFT_18 +/* The length of the server handshake label. */ +#define SERVER_HANDSHAKE_LABEL_SZ 31 +/* The server handshake label. */ +static const byte serverHandshakeLabel[SERVER_HANDSHAKE_LABEL_SZ + 1] = + "server handshake traffic secret"; +#else +/* The length of the server handshake label. */ +#define SERVER_HANDSHAKE_LABEL_SZ 12 +/* The server handshake label. */ +static const byte serverHandshakeLabel[SERVER_HANDSHAKE_LABEL_SZ + 1] = + "s hs traffic"; +#endif +/* Derive the server handshake key. + * + * ssl The SSL/TLS object. + * key The derived key. + * returns 0 on success, otherwise failure. + */ +static int DeriveServerHandshakeSecret(WOLFSSL* ssl, byte* key) +{ + WOLFSSL_MSG("Derive Server Handshake Secret"); + return DeriveKey(ssl, key, -1, ssl->arrays->preMasterSecret, + serverHandshakeLabel, SERVER_HANDSHAKE_LABEL_SZ, + ssl->specs.mac_algorithm, 1); +} + +#ifdef WOLFSSL_TLS13_DRAFT_18 +/* The length of the client application traffic label. */ +#define CLIENT_APP_LABEL_SZ 33 +/* The client application traffic label. */ +static const byte clientAppLabel[CLIENT_APP_LABEL_SZ + 1] = + "client application traffic secret"; +#else +/* The length of the client application traffic label. */ +#define CLIENT_APP_LABEL_SZ 12 +/* The client application traffic label. */ +static const byte clientAppLabel[CLIENT_APP_LABEL_SZ + 1] = + "c ap traffic"; +#endif +/* Derive the client application traffic key. + * + * ssl The SSL/TLS object. + * key The derived key. + * returns 0 on success, otherwise failure. + */ +static int DeriveClientTrafficSecret(WOLFSSL* ssl, byte* key) +{ + WOLFSSL_MSG("Derive Client Traffic Secret"); + return DeriveKey(ssl, key, -1, ssl->arrays->masterSecret, + clientAppLabel, CLIENT_APP_LABEL_SZ, + ssl->specs.mac_algorithm, 1); +} + +#ifdef WOLFSSL_TLS13_DRAFT_18 +/* The length of the server application traffic label. */ +#define SERVER_APP_LABEL_SZ 33 +/* The server application traffic label. */ +static const byte serverAppLabel[SERVER_APP_LABEL_SZ + 1] = + "server application traffic secret"; +#else +/* The length of the server application traffic label. */ +#define SERVER_APP_LABEL_SZ 12 +/* The server application traffic label. */ +static const byte serverAppLabel[SERVER_APP_LABEL_SZ + 1] = + "s ap traffic"; +#endif +/* Derive the server application traffic key. + * + * ssl The SSL/TLS object. + * key The derived key. + * returns 0 on success, otherwise failure. + */ +static int DeriveServerTrafficSecret(WOLFSSL* ssl, byte* key) +{ + WOLFSSL_MSG("Derive Server Traffic Secret"); + return DeriveKey(ssl, key, -1, ssl->arrays->masterSecret, + serverAppLabel, SERVER_APP_LABEL_SZ, + ssl->specs.mac_algorithm, 1); +} + +#ifdef TLS13_SUPPORTS_EXPORTERS +#ifdef WOLFSSL_TLS13_DRAFT_18 +/* The length of the exporter master secret label. */ +#define EXPORTER_MASTER_LABEL_SZ 22 +/* The exporter master secret label. */ +static const byte exporterMasterLabel[EXPORTER_MASTER_LABEL_SZ + 1] = + "exporter master secret"; +#else +/* The length of the exporter master secret label. */ +#define EXPORTER_MASTER_LABEL_SZ 10 +/* The exporter master secret label. */ +static const byte exporterMasterLabel[EXPORTER_MASTER_LABEL_SZ + 1] = + "exp master"; +#endif +/* Derive the exporter secret. + * + * ssl The SSL/TLS object. + * key The derived key. + * returns 0 on success, otherwise failure. + */ +static int DeriveExporterSecret(WOLFSSL* ssl, byte* key) +{ + WOLFSSL_MSG("Derive Exporter Secret"); + return DeriveKey(ssl, key, -1, ssl->arrays->masterSecret, + exporterMasterLabel, EXPORTER_MASTER_LABEL_SZ, + ssl->specs.mac_algorithm, 1); +} +#endif + +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) +#ifdef WOLFSSL_TLS13_DRAFT_18 +/* The length of the resumption master secret label. */ +#define RESUME_MASTER_LABEL_SZ 24 +/* The resumption master secret label. */ +static const byte resumeMasterLabel[RESUME_MASTER_LABEL_SZ + 1] = + "resumption master secret"; +#else +/* The length of the resumption master secret label. */ +#define RESUME_MASTER_LABEL_SZ 10 +/* The resumption master secret label. */ +static const byte resumeMasterLabel[RESUME_MASTER_LABEL_SZ + 1] = + "res master"; +#endif +/* Derive the resumption secret. + * + * ssl The SSL/TLS object. + * key The derived key. + * returns 0 on success, otherwise failure. + */ +static int DeriveResumptionSecret(WOLFSSL* ssl, byte* key) +{ + WOLFSSL_MSG("Derive Resumption Secret"); + return DeriveKey(ssl, key, -1, ssl->arrays->masterSecret, + resumeMasterLabel, RESUME_MASTER_LABEL_SZ, + ssl->specs.mac_algorithm, 1); +} +#endif + +/* Length of the finished label. */ +#define FINISHED_LABEL_SZ 8 +/* Finished label for generating finished key. */ +static const byte finishedLabel[FINISHED_LABEL_SZ+1] = "finished"; +/* Derive the finished secret. + * + * ssl The SSL/TLS object. + * key The key to use with the HMAC. + * secret The derived secret. + * returns 0 on success, otherwise failure. + */ +static int DeriveFinishedSecret(WOLFSSL* ssl, byte* key, byte* secret) +{ + WOLFSSL_MSG("Derive Finished Secret"); + return DeriveKey(ssl, secret, -1, key, finishedLabel, FINISHED_LABEL_SZ, + ssl->specs.mac_algorithm, 0); +} + +#ifdef WOLFSSL_TLS13_DRAFT_18 +/* The length of the application traffic label. */ +#define APP_TRAFFIC_LABEL_SZ 26 +/* The application traffic label. */ +static const byte appTrafficLabel[APP_TRAFFIC_LABEL_SZ + 1] = + "application traffic secret"; +#else +/* The length of the application traffic label. */ +#define APP_TRAFFIC_LABEL_SZ 11 +/* The application traffic label. */ +static const byte appTrafficLabel[APP_TRAFFIC_LABEL_SZ + 1] = + "traffic upd"; +#endif +/* Update the traffic secret. + * + * ssl The SSL/TLS object. + * secret The previous secret and derived secret. + * returns 0 on success, otherwise failure. + */ +static int DeriveTrafficSecret(WOLFSSL* ssl, byte* secret) +{ + WOLFSSL_MSG("Derive New Application Traffic Secret"); + return DeriveKey(ssl, secret, -1, secret, + appTrafficLabel, APP_TRAFFIC_LABEL_SZ, + ssl->specs.mac_algorithm, 0); +} + +/* Derive the early secret using HKDF Extract. + * + * ssl The SSL/TLS object. + */ +static int DeriveEarlySecret(WOLFSSL* ssl) +{ + WOLFSSL_MSG("Derive Early Secret"); +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + return Tls13_HKDF_Extract(ssl->arrays->secret, NULL, 0, + ssl->arrays->psk_key, ssl->arrays->psk_keySz, + ssl->specs.mac_algorithm); +#else + return Tls13_HKDF_Extract(ssl->arrays->secret, NULL, 0, + ssl->arrays->masterSecret, 0, ssl->specs.mac_algorithm); +#endif +} + +#ifndef WOLFSSL_TLS13_DRAFT_18 +/* The length of the derived label. */ +#define DERIVED_LABEL_SZ 7 +/* The derived label. */ +static const byte derivedLabel[DERIVED_LABEL_SZ + 1] = + "derived"; +#endif +/* Derive the handshake secret using HKDF Extract. + * + * ssl The SSL/TLS object. + */ +static int DeriveHandshakeSecret(WOLFSSL* ssl) +{ +#ifdef WOLFSSL_TLS13_DRAFT_18 + WOLFSSL_MSG("Derive Handshake Secret"); + return Tls13_HKDF_Extract(ssl->arrays->preMasterSecret, + ssl->arrays->secret, ssl->specs.hash_size, + ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz, + ssl->specs.mac_algorithm); +#else + byte key[WC_MAX_DIGEST_SIZE]; + int ret; + + WOLFSSL_MSG("Derive Handshake Secret"); + + ret = DeriveKeyMsg(ssl, key, -1, ssl->arrays->secret, + derivedLabel, DERIVED_LABEL_SZ, + NULL, 0, ssl->specs.mac_algorithm); + if (ret != 0) + return ret; + + return Tls13_HKDF_Extract(ssl->arrays->preMasterSecret, + key, ssl->specs.hash_size, + ssl->arrays->preMasterSecret, ssl->arrays->preMasterSz, + ssl->specs.mac_algorithm); +#endif +} + +/* Derive the master secret using HKDF Extract. + * + * ssl The SSL/TLS object. + */ +static int DeriveMasterSecret(WOLFSSL* ssl) +{ +#ifdef WOLFSSL_TLS13_DRAFT_18 + WOLFSSL_MSG("Derive Master Secret"); + return Tls13_HKDF_Extract(ssl->arrays->masterSecret, + ssl->arrays->preMasterSecret, ssl->specs.hash_size, + ssl->arrays->masterSecret, 0, ssl->specs.mac_algorithm); +#else + byte key[WC_MAX_DIGEST_SIZE]; + int ret; + + WOLFSSL_MSG("Derive Master Secret"); + + ret = DeriveKeyMsg(ssl, key, -1, ssl->arrays->preMasterSecret, + derivedLabel, DERIVED_LABEL_SZ, + NULL, 0, ssl->specs.mac_algorithm); + if (ret != 0) + return ret; + + return Tls13_HKDF_Extract(ssl->arrays->masterSecret, + key, ssl->specs.hash_size, + ssl->arrays->masterSecret, 0, ssl->specs.mac_algorithm); +#endif +} + +#ifndef WOLFSSL_TLS13_DRAFT_18 +#if defined(HAVE_SESSION_TICKET) +/* Length of the resumption label. */ +#define RESUMPTION_LABEL_SZ 10 +/* Resumption label for generating PSK associated with the ticket. */ +static const byte resumptionLabel[RESUMPTION_LABEL_SZ+1] = "resumption"; +/* Derive the PSK associated with the ticket. + * + * ssl The SSL/TLS object. + * nonce The nonce to derive with. + * nonceLen The length of the nonce to derive with. + * secret The derived secret. + * returns 0 on success, otherwise failure. + */ +static int DeriveResumptionPSK(WOLFSSL* ssl, byte* nonce, byte nonceLen, + byte* secret) +{ + int digestAlg; + /* Only one protocol version defined at this time. */ + const byte* protocol = tls13ProtocolLabel; + word32 protocolLen = TLS13_PROTOCOL_LABEL_SZ; + + WOLFSSL_MSG("Derive Resumption PSK"); + + switch (ssl->specs.mac_algorithm) { + #ifndef NO_SHA256 + case sha256_mac: + digestAlg = WC_SHA256; + break; + #endif + + #ifdef WOLFSSL_SHA384 + case sha384_mac: + digestAlg = WC_SHA384; + break; + #endif + + #ifdef WOLFSSL_TLS13_SHA512 + case sha512_mac: + digestAlg = WC_SHA512; + break; + #endif + + default: + return BAD_FUNC_ARG; + } + + return HKDF_Expand_Label(secret, ssl->specs.hash_size, + ssl->session.masterSecret, ssl->specs.hash_size, + protocol, protocolLen, resumptionLabel, + RESUMPTION_LABEL_SZ, nonce, nonceLen, digestAlg); +} +#endif /* HAVE_SESSION_TICKET */ +#endif /* WOLFSSL_TLS13_DRAFT_18 */ + + +/* Calculate the HMAC of message data to this point. + * + * ssl The SSL/TLS object. + * key The HMAC key. + * hash The hash result - verify data. + * returns length of verify data generated. + */ +static int BuildTls13HandshakeHmac(WOLFSSL* ssl, byte* key, byte* hash, + word32* pHashSz) +{ + Hmac verifyHmac; + int hashType = WC_SHA256; + int hashSz = WC_SHA256_DIGEST_SIZE; + int ret = BAD_FUNC_ARG; + + /* Get the hash of the previous handshake messages. */ + switch (ssl->specs.mac_algorithm) { + #ifndef NO_SHA256 + case sha256_mac: + hashType = WC_SHA256; + hashSz = WC_SHA256_DIGEST_SIZE; + ret = wc_Sha256GetHash(&ssl->hsHashes->hashSha256, hash); + break; + #endif /* !NO_SHA256 */ + #ifdef WOLFSSL_SHA384 + case sha384_mac: + hashType = WC_SHA384; + hashSz = WC_SHA384_DIGEST_SIZE; + ret = wc_Sha384GetHash(&ssl->hsHashes->hashSha384, hash); + break; + #endif /* WOLFSSL_SHA384 */ + #ifdef WOLFSSL_TLS13_SHA512 + case sha512_mac: + hashType = WC_SHA512; + hashSz = WC_SHA512_DIGEST_SIZE; + ret = wc_Sha512GetHash(&ssl->hsHashes->hashSha512, hash); + break; + #endif /* WOLFSSL_TLS13_SHA512 */ + } + if (ret != 0) + return ret; + + /* Calculate the verify data. */ + ret = wc_HmacInit(&verifyHmac, ssl->heap, ssl->devId); + if (ret == 0) { + ret = wc_HmacSetKey(&verifyHmac, hashType, key, ssl->specs.hash_size); + if (ret == 0) + ret = wc_HmacUpdate(&verifyHmac, hash, hashSz); + if (ret == 0) + ret = wc_HmacFinal(&verifyHmac, hash); + wc_HmacFree(&verifyHmac); + } + + if (pHashSz) + *pHashSz = hashSz; + + return ret; +} + +/* The length of the label to use when deriving keys. */ +#define WRITE_KEY_LABEL_SZ 3 +/* The length of the label to use when deriving IVs. */ +#define WRITE_IV_LABEL_SZ 2 +/* The label to use when deriving keys. */ +static const byte writeKeyLabel[WRITE_KEY_LABEL_SZ+1] = "key"; +/* The label to use when deriving IVs. */ +static const byte writeIVLabel[WRITE_IV_LABEL_SZ+1] = "iv"; + +/* Derive the keys and IVs for TLS v1.3. + * + * ssl The SSL/TLS object. + * sercret early_data_key when deriving the key and IV for encrypting early + * data application data and end_of_early_data messages. + * handshake_key when deriving keys and IVs for encrypting handshake + * messages. + * traffic_key when deriving first keys and IVs for encrypting + * traffic messages. + * update_traffic_key when deriving next keys and IVs for encrypting + * traffic messages. + * side ENCRYPT_SIDE_ONLY when only encryption secret needs to be derived. + * DECRYPT_SIDE_ONLY when only decryption secret needs to be derived. + * ENCRYPT_AND_DECRYPT_SIDE when both secret needs to be derived. + * store 1 indicates to derive the keys and IVs from derived secret and + * store ready for provisioning. + * returns 0 on success, otherwise failure. + */ +static int DeriveTls13Keys(WOLFSSL* ssl, int secret, int side, int store) +{ + int ret = BAD_FUNC_ARG; /* Assume failure */ + int i = 0; +#ifdef WOLFSSL_SMALL_STACK + byte* key_dig; +#else + byte key_dig[MAX_PRF_DIG]; +#endif + int provision; + +#ifdef WOLFSSL_SMALL_STACK + key_dig = (byte*)XMALLOC(MAX_PRF_DIG, ssl->heap, DYNAMIC_TYPE_DIGEST); + if (key_dig == NULL) + return MEMORY_E; +#endif + + if (side == ENCRYPT_AND_DECRYPT_SIDE) { + provision = PROVISION_CLIENT_SERVER; + } + else { + provision = ((ssl->options.side != WOLFSSL_CLIENT_END) ^ + (side == ENCRYPT_SIDE_ONLY)) ? PROVISION_CLIENT : + PROVISION_SERVER; + } + + /* Derive the appropriate secret to use in the HKDF. */ + switch (secret) { +#ifdef WOLFSSL_EARLY_DATA + case early_data_key: + ret = DeriveEarlyTrafficSecret(ssl, ssl->clientSecret); + if (ret != 0) + goto end; + break; +#endif + + case handshake_key: + if (provision & PROVISION_CLIENT) { + ret = DeriveClientHandshakeSecret(ssl, + ssl->clientSecret); + if (ret != 0) + goto end; + } + if (provision & PROVISION_SERVER) { + ret = DeriveServerHandshakeSecret(ssl, + ssl->serverSecret); + if (ret != 0) + goto end; + } + break; + + case traffic_key: + if (provision & PROVISION_CLIENT) { + ret = DeriveClientTrafficSecret(ssl, ssl->clientSecret); + if (ret != 0) + goto end; + } + if (provision & PROVISION_SERVER) { + ret = DeriveServerTrafficSecret(ssl, ssl->serverSecret); + if (ret != 0) + goto end; + } + break; + + case update_traffic_key: + if (provision & PROVISION_CLIENT) { + ret = DeriveTrafficSecret(ssl, ssl->clientSecret); + if (ret != 0) + goto end; + } + if (provision & PROVISION_SERVER) { + ret = DeriveTrafficSecret(ssl, ssl->serverSecret); + if (ret != 0) + goto end; + } + break; + } + + if (!store) + goto end; + + /* Key data = client key | server key | client IV | server IV */ + + if (provision & PROVISION_CLIENT) { + /* Derive the client key. */ + WOLFSSL_MSG("Derive Client Key"); + ret = DeriveKey(ssl, &key_dig[i], ssl->specs.key_size, + ssl->clientSecret, writeKeyLabel, + WRITE_KEY_LABEL_SZ, ssl->specs.mac_algorithm, 0); + if (ret != 0) + goto end; + i += ssl->specs.key_size; + } + + if (provision & PROVISION_SERVER) { + /* Derive the server key. */ + WOLFSSL_MSG("Derive Server Key"); + ret = DeriveKey(ssl, &key_dig[i], ssl->specs.key_size, + ssl->serverSecret, writeKeyLabel, + WRITE_KEY_LABEL_SZ, ssl->specs.mac_algorithm, 0); + if (ret != 0) + goto end; + i += ssl->specs.key_size; + } + + if (provision & PROVISION_CLIENT) { + /* Derive the client IV. */ + WOLFSSL_MSG("Derive Client IV"); + ret = DeriveKey(ssl, &key_dig[i], ssl->specs.iv_size, + ssl->clientSecret, writeIVLabel, + WRITE_IV_LABEL_SZ, ssl->specs.mac_algorithm, 0); + if (ret != 0) + goto end; + i += ssl->specs.iv_size; + } + + if (provision & PROVISION_SERVER) { + /* Derive the server IV. */ + WOLFSSL_MSG("Derive Server IV"); + ret = DeriveKey(ssl, &key_dig[i], ssl->specs.iv_size, + ssl->serverSecret, writeIVLabel, + WRITE_IV_LABEL_SZ, ssl->specs.mac_algorithm, 0); + if (ret != 0) + goto end; + } + + /* Store keys and IVs but don't activate them. */ + ret = StoreKeys(ssl, key_dig, provision); + +end: +#ifdef WOLFSSL_SMALL_STACK + XFREE(key_dig, ssl->heap, DYNAMIC_TYPE_DIGEST); +#endif + + return ret; +} + +#ifdef HAVE_SESSION_TICKET +#if defined(USER_TICKS) +#if 0 + word32 TimeNowInMilliseconds(void) + { + /* + write your own clock tick function if don't want gettimeofday() + needs millisecond accuracy but doesn't have to correlated to EPOCH + */ + } +#endif + +#elif defined(TIME_OVERRIDES) + #ifndef HAVE_TIME_T_TYPE + typedef long time_t; + #endif + extern time_t XTIME(time_t * timer); + + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + return (word32) XTIME(0) * 1000; + } + +#elif defined(XTIME_MS) + word32 TimeNowInMilliseconds(void) + { + return (word32)XTIME_MS(0); + } + +#elif defined(USE_WINDOWS_API) + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + static int init = 0; + static LARGE_INTEGER freq; + LARGE_INTEGER count; + + if (!init) { + QueryPerformanceFrequency(&freq); + init = 1; + } + + QueryPerformanceCounter(&count); + + return (word32)(count.QuadPart / (freq.QuadPart / 1000)); + } + +#elif defined(HAVE_RTP_SYS) + #include "rtptime.h" + + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + return (word32)rtp_get_system_sec() * 1000; + } +#elif defined(WOLFSSL_DEOS) + word32 TimeNowInMilliseconds(void) + { + const uint32_t systemTickTimeInHz = 1000000 / systemTickInMicroseconds(); + uint32_t *systemTickPtr = systemTickPointer(); + + return (word32) (*systemTickPtr/systemTickTimeInHz) * 1000; + } +#elif defined(MICRIUM) + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + OS_TICK ticks = 0; + OS_ERR err; + + ticks = OSTimeGet(&err); + + return (word32) (ticks / OSCfg_TickRate_Hz) * 1000; + } +#elif defined(MICROCHIP_TCPIP_V5) + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + return (word32) (TickGet() / (TICKS_PER_SECOND / 1000)); + } +#elif defined(MICROCHIP_TCPIP) + #if defined(MICROCHIP_MPLAB_HARMONY) + #include + + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + return (word32)(SYS_TMR_TickCountGet() / + (SYS_TMR_TickCounterFrequencyGet() / 1000)); + } + #else + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + return (word32)(SYS_TICK_Get() / (SYS_TICK_TicksPerSecondGet() / 1000)); + } + + #endif + +#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + TIME_STRUCT mqxTime; + + _time_get_elapsed(&mqxTime); + + return (word32) mqxTime.SECONDS * 1000; + } +#elif defined(FREESCALE_FREE_RTOS) || defined(FREESCALE_KSDK_FREERTOS) + #include "include/task.h" + + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + return (unsigned int)(((float)xTaskGetTickCount()) / + (configTICK_RATE_HZ / 1000)); + } +#elif defined(FREESCALE_KSDK_BM) + #include "lwip/sys.h" /* lwIP */ + + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + return sys_now(); + } +#elif defined(WOLFSSL_TIRTOS) + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + return (word32) Seconds_get() * 1000; + } +#elif defined(WOLFSSL_UTASKER) + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + return (word32)(uTaskerSystemTick / (TICK_RESOLUTION / 1000)); + } +#else + /* The time in milliseconds. + * Used for tickets to represent difference between when first seen and when + * sending. + * + * returns the time in milliseconds as a 32-bit value. + */ + word32 TimeNowInMilliseconds(void) + { + struct timeval now; + + if (gettimeofday(&now, 0) < 0) + return GETTIME_ERROR; + /* Convert to milliseconds number. */ + return (word32)(now.tv_sec * 1000 + now.tv_usec / 1000); + } +#endif +#endif /* HAVE_SESSION_TICKET || !NO_PSK */ + + +#if !defined(NO_WOLFSSL_SERVER) && (defined(HAVE_SESSION_TICKET) || \ + !defined(NO_PSK)) +/* Add input to all handshake hashes. + * + * ssl The SSL/TLS object. + * input The data to hash. + * sz The size of the data to hash. + * returns 0 on success, otherwise failure. + */ +static int HashInputRaw(WOLFSSL* ssl, const byte* input, int sz) +{ + int ret = BAD_FUNC_ARG; + +#ifndef NO_SHA256 + ret = wc_Sha256Update(&ssl->hsHashes->hashSha256, input, sz); + if (ret != 0) + return ret; +#endif +#ifdef WOLFSSL_SHA384 + ret = wc_Sha384Update(&ssl->hsHashes->hashSha384, input, sz); + if (ret != 0) + return ret; +#endif +#ifdef WOLFSSL_TLS13_SHA512 + ret = wc_Sha512Update(&ssl->hsHashes->hashSha512, input, sz); + if (ret != 0) + return ret; +#endif + + return ret; +} +#endif + +/* Extract the handshake header information. + * + * ssl The SSL/TLS object. + * input The buffer holding the message data. + * inOutIdx On entry, the index into the buffer of the handshake data. + * On exit, the start of the handshake data. + * type Type of handshake message. + * size The length of the handshake message data. + * totalSz The total size of data in the buffer. + * returns BUFFER_E if there is not enough input data and 0 on success. + */ +static int GetHandshakeHeader(WOLFSSL* ssl, const byte* input, word32* inOutIdx, + byte* type, word32* size, word32 totalSz) +{ + const byte* ptr = input + *inOutIdx; + (void)ssl; + + *inOutIdx += HANDSHAKE_HEADER_SZ; + if (*inOutIdx > totalSz) + return BUFFER_E; + + *type = ptr[0]; + c24to32(&ptr[1], size); + + return 0; +} + +/* Add record layer header to message. + * + * output The buffer to write the record layer header into. + * length The length of the record data. + * type The type of record message. + * ssl The SSL/TLS object. + */ +static void AddTls13RecordHeader(byte* output, word32 length, byte type, + WOLFSSL* ssl) +{ + RecordLayerHeader* rl; + + rl = (RecordLayerHeader*)output; + rl->type = type; + rl->pvMajor = ssl->version.major; +#ifdef WOLFSSL_TLS13_DRAFT_18 + rl->pvMinor = TLSv1_MINOR; +#else + /* NOTE: May be TLSv1_MINOR when sending first ClientHello. */ + rl->pvMinor = TLSv1_2_MINOR; +#endif + c16toa((word16)length, rl->length); +} + +/* Add handshake header to message. + * + * output The buffer to write the handshake header into. + * length The length of the handshake data. + * fragOffset The offset of the fragment data. (DTLS) + * fragLength The length of the fragment data. (DTLS) + * type The type of handshake message. + * ssl The SSL/TLS object. (DTLS) + */ +static void AddTls13HandShakeHeader(byte* output, word32 length, + word32 fragOffset, word32 fragLength, + byte type, WOLFSSL* ssl) +{ + HandShakeHeader* hs; + (void)fragOffset; + (void)fragLength; + (void)ssl; + + /* handshake header */ + hs = (HandShakeHeader*)output; + hs->type = type; + c32to24(length, hs->length); +} + + +/* Add both record layer and handshake header to message. + * + * output The buffer to write the headers into. + * length The length of the handshake data. + * type The type of record layer message. + * ssl The SSL/TLS object. (DTLS) + */ +static void AddTls13Headers(byte* output, word32 length, byte type, + WOLFSSL* ssl) +{ + word32 lengthAdj = HANDSHAKE_HEADER_SZ; + word32 outputAdj = RECORD_HEADER_SZ; + + AddTls13RecordHeader(output, length + lengthAdj, handshake, ssl); + AddTls13HandShakeHeader(output + outputAdj, length, 0, length, type, ssl); +} + + +#ifndef NO_CERTS +/* Add both record layer and fragement handshake header to message. + * + * output The buffer to write the headers into. + * fragOffset The offset of the fragment data. (DTLS) + * fragLength The length of the fragment data. (DTLS) + * length The length of the handshake data. + * type The type of record layer message. + * ssl The SSL/TLS object. (DTLS) + */ +static void AddTls13FragHeaders(byte* output, word32 fragSz, word32 fragOffset, + word32 length, byte type, WOLFSSL* ssl) +{ + word32 lengthAdj = HANDSHAKE_HEADER_SZ; + word32 outputAdj = RECORD_HEADER_SZ; + (void)fragSz; + + AddTls13RecordHeader(output, fragSz + lengthAdj, handshake, ssl); + AddTls13HandShakeHeader(output + outputAdj, length, fragOffset, fragSz, + type, ssl); +} +#endif /* NO_CERTS */ + +/* Write the sequence number into the buffer. + * No DTLS v1.3 support. + * + * ssl The SSL/TLS object. + * verifyOrder Which set of sequence numbers to use. + * out The buffer to write into. + */ +static WC_INLINE void WriteSEQ(WOLFSSL* ssl, int verifyOrder, byte* out) +{ + word32 seq[2] = {0, 0}; + + if (verifyOrder) { + seq[0] = ssl->keys.peer_sequence_number_hi; + seq[1] = ssl->keys.peer_sequence_number_lo++; + /* handle rollover */ + if (seq[1] > ssl->keys.peer_sequence_number_lo) + ssl->keys.peer_sequence_number_hi++; + } + else { + seq[0] = ssl->keys.sequence_number_hi; + seq[1] = ssl->keys.sequence_number_lo++; + /* handle rollover */ + if (seq[1] > ssl->keys.sequence_number_lo) + ssl->keys.sequence_number_hi++; + } + + c32toa(seq[0], out); + c32toa(seq[1], out + OPAQUE32_LEN); +} + +/* Build the nonce for TLS v1.3 encryption and decryption. + * + * ssl The SSL/TLS object. + * nonce The nonce data to use when encrypting or decrypting. + * iv The derived IV. + * order The side on which the message is to be or was sent. + */ +static WC_INLINE void BuildTls13Nonce(WOLFSSL* ssl, byte* nonce, const byte* iv, + int order) +{ + int i; + + /* The nonce is the IV with the sequence XORed into the last bytes. */ + WriteSEQ(ssl, order, nonce + AEAD_NONCE_SZ - SEQ_SZ); + for (i = 0; i < AEAD_NONCE_SZ - SEQ_SZ; i++) + nonce[i] = iv[i]; + for (; i < AEAD_NONCE_SZ; i++) + nonce[i] ^= iv[i]; +} + +#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) +/* Encrypt with ChaCha20 and create authenication tag with Poly1305. + * + * ssl The SSL/TLS object. + * output The buffer to write encrypted data and authentication tag into. + * May be the same pointer as input. + * input The data to encrypt. + * sz The number of bytes to encrypt. + * nonce The nonce to use with ChaCha20. + * aad The additional authentication data. + * aadSz The size of the addition authentication data. + * tag The authentication tag buffer. + * returns 0 on success, otherwise failure. + */ +static int ChaCha20Poly1305_Encrypt(WOLFSSL* ssl, byte* output, + const byte* input, word16 sz, byte* nonce, + const byte* aad, word16 aadSz, byte* tag) +{ + int ret = 0; + byte poly[CHACHA20_256_KEY_SIZE]; + + /* Poly1305 key is 256 bits of zero encrypted with ChaCha20. */ + XMEMSET(poly, 0, sizeof(poly)); + + /* Set the nonce for ChaCha and get Poly1305 key. */ + ret = wc_Chacha_SetIV(ssl->encrypt.chacha, nonce, 0); + if (ret != 0) + return ret; + /* Create Poly1305 key using ChaCha20 keystream. */ + ret = wc_Chacha_Process(ssl->encrypt.chacha, poly, poly, sizeof(poly)); + if (ret != 0) + return ret; + /* Encrypt the plain text. */ + ret = wc_Chacha_Process(ssl->encrypt.chacha, output, input, sz); + if (ret != 0) { + ForceZero(poly, sizeof(poly)); + return ret; + } + + /* Set key for Poly1305. */ + ret = wc_Poly1305SetKey(ssl->auth.poly1305, poly, sizeof(poly)); + ForceZero(poly, sizeof(poly)); /* done with poly1305 key, clear it */ + if (ret != 0) + return ret; + /* Add authentication code of encrypted data to end. */ + ret = wc_Poly1305_MAC(ssl->auth.poly1305, (byte*)aad, aadSz, output, sz, + tag, POLY1305_AUTH_SZ); + + return ret; +} +#endif + +/* Encrypt data for TLS v1.3. + * + * ssl The SSL/TLS object. + * output The buffer to write encrypted data and authentication tag into. + * May be the same pointer as input. + * input The record header and data to encrypt. + * sz The number of bytes to encrypt. + * aad The additional authentication data. + * aadSz The size of the addition authentication data. + * asyncOkay If non-zero can return WC_PENDING_E, otherwise blocks on crypto + * returns 0 on success, otherwise failure. + */ +static int EncryptTls13(WOLFSSL* ssl, byte* output, const byte* input, + word16 sz, const byte* aad, word16 aadSz, int asyncOkay) +{ + int ret = 0; + word16 dataSz = sz - ssl->specs.aead_mac_size; + word16 macSz = ssl->specs.aead_mac_size; + word32 nonceSz = 0; +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV* asyncDev = NULL; + word32 event_flags = WC_ASYNC_FLAG_CALL_AGAIN; +#endif + + WOLFSSL_ENTER("EncryptTls13"); + + (void)output; + (void)input; + (void)sz; + (void)dataSz; + (void)macSz; + (void)asyncOkay; + (void)nonceSz; + +#ifdef WOLFSSL_ASYNC_CRYPT + if (ssl->error == WC_PENDING_E) { + ssl->error = 0; /* clear async */ + } +#endif + + switch (ssl->encrypt.state) { + case CIPHER_STATE_BEGIN: + { + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Data to encrypt"); + WOLFSSL_BUFFER(input, dataSz); +#if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22) && \ + !defined(WOLFSSL_TLS13_DRAFT_23) + WOLFSSL_MSG("Additional Authentication Data"); + WOLFSSL_BUFFER(aad, aadSz); +#endif + #endif + + if (ssl->encrypt.nonce == NULL) + ssl->encrypt.nonce = (byte*)XMALLOC(AEAD_NONCE_SZ, + ssl->heap, DYNAMIC_TYPE_AES_BUFFER); + if (ssl->encrypt.nonce == NULL) + return MEMORY_E; + + BuildTls13Nonce(ssl, ssl->encrypt.nonce, ssl->keys.aead_enc_imp_IV, + CUR_ORDER); + + /* Advance state and proceed */ + ssl->encrypt.state = CIPHER_STATE_DO; + } + FALL_THROUGH; + + case CIPHER_STATE_DO: + { + switch (ssl->specs.bulk_cipher_algorithm) { + #ifdef BUILD_AESGCM + case wolfssl_aes_gcm: + #ifdef WOLFSSL_ASYNC_CRYPT + /* initialize event */ + asyncDev = &ssl->encrypt.aes->asyncDev; + ret = wolfSSL_AsyncInit(ssl, asyncDev, event_flags); + if (ret != 0) + break; + #endif + + nonceSz = AESGCM_NONCE_SZ; + #if ((defined(HAVE_FIPS) || defined(HAVE_SELFTEST)) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))) + ret = wc_AesGcmEncrypt(ssl->encrypt.aes, output, input, + dataSz, ssl->encrypt.nonce, nonceSz, + output + dataSz, macSz, aad, aadSz); + #else + ret = wc_AesGcmSetExtIV(ssl->encrypt.aes, + ssl->encrypt.nonce, nonceSz); + if (ret == 0) { + ret = wc_AesGcmEncrypt_ex(ssl->encrypt.aes, output, + input, dataSz, ssl->encrypt.nonce, nonceSz, + output + dataSz, macSz, aad, aadSz); + } + #endif + break; + #endif + + #ifdef HAVE_AESCCM + case wolfssl_aes_ccm: + #ifdef WOLFSSL_ASYNC_CRYPT + /* initialize event */ + asyncDev = &ssl->encrypt.aes->asyncDev; + ret = wolfSSL_AsyncInit(ssl, asyncDev, event_flags); + if (ret != 0) + break; + #endif + + nonceSz = AESCCM_NONCE_SZ; + #if ((defined(HAVE_FIPS) || defined(HAVE_SELFTEST)) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))) + ret = wc_AesCcmEncrypt(ssl->encrypt.aes, output, input, + dataSz, ssl->encrypt.nonce, nonceSz, + output + dataSz, macSz, aad, aadSz); + #else + ret = wc_AesCcmSetNonce(ssl->encrypt.aes, + ssl->encrypt.nonce, nonceSz); + if (ret == 0) { + ret = wc_AesCcmEncrypt_ex(ssl->encrypt.aes, output, + input, dataSz, ssl->encrypt.nonce, nonceSz, + output + dataSz, macSz, aad, aadSz); + } + #endif + break; + #endif + + #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) + case wolfssl_chacha: + ret = ChaCha20Poly1305_Encrypt(ssl, output, input, dataSz, + ssl->encrypt.nonce, aad, aadSz, output + dataSz); + break; + #endif + + default: + WOLFSSL_MSG("wolfSSL Encrypt programming error"); + return ENCRYPT_ERROR; + } + + /* Advance state */ + ssl->encrypt.state = CIPHER_STATE_END; + + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + /* if async is not okay, then block */ + if (!asyncOkay) { + ret = wc_AsyncWait(ret, asyncDev, event_flags); + } + else { + /* If pending, then leave and return will resume below */ + return wolfSSL_AsyncPush(ssl, asyncDev); + } + } + #endif + } + FALL_THROUGH; + + case CIPHER_STATE_END: + { + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Nonce"); + WOLFSSL_BUFFER(ssl->encrypt.nonce, ssl->specs.iv_size); + WOLFSSL_MSG("Encrypted data"); + WOLFSSL_BUFFER(output, dataSz); + WOLFSSL_MSG("Authentication Tag"); + WOLFSSL_BUFFER(output + dataSz, macSz); + #endif + + ForceZero(ssl->encrypt.nonce, AEAD_NONCE_SZ); + + break; + } + } + + /* Reset state */ + ssl->encrypt.state = CIPHER_STATE_BEGIN; + + return ret; +} + +#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) +/* Decrypt with ChaCha20 and check authenication tag with Poly1305. + * + * ssl The SSL/TLS object. + * output The buffer to write decrypted data into. + * May be the same pointer as input. + * input The data to decrypt. + * sz The number of bytes to decrypt. + * nonce The nonce to use with ChaCha20. + * aad The additional authentication data. + * aadSz The size of the addition authentication data. + * tagIn The authentication tag data from packet. + * returns 0 on success, otherwise failure. + */ +static int ChaCha20Poly1305_Decrypt(WOLFSSL* ssl, byte* output, + const byte* input, word16 sz, byte* nonce, + const byte* aad, word16 aadSz, + const byte* tagIn) +{ + int ret; + byte tag[POLY1305_AUTH_SZ]; + byte poly[CHACHA20_256_KEY_SIZE]; /* generated key for mac */ + + /* Poly1305 key is 256 bits of zero encrypted with ChaCha20. */ + XMEMSET(poly, 0, sizeof(poly)); + + /* Set nonce and get Poly1305 key. */ + ret = wc_Chacha_SetIV(ssl->decrypt.chacha, nonce, 0); + if (ret != 0) + return ret; + /* Use ChaCha20 keystream to get Poly1305 key for tag. */ + ret = wc_Chacha_Process(ssl->decrypt.chacha, poly, poly, sizeof(poly)); + if (ret != 0) + return ret; + + /* Set key for Poly1305. */ + ret = wc_Poly1305SetKey(ssl->auth.poly1305, poly, sizeof(poly)); + ForceZero(poly, sizeof(poly)); /* done with poly1305 key, clear it */ + if (ret != 0) + return ret; + /* Generate authentication tag for encrypted data. */ + if ((ret = wc_Poly1305_MAC(ssl->auth.poly1305, (byte*)aad, aadSz, + (byte*)input, sz, tag, sizeof(tag))) != 0) { + return ret; + } + + /* Check tag sent along with packet. */ + if (ConstantCompare(tagIn, tag, POLY1305_AUTH_SZ) != 0) { + WOLFSSL_MSG("MAC did not match"); + return VERIFY_MAC_ERROR; + } + + /* If the tag was good decrypt message. */ + ret = wc_Chacha_Process(ssl->decrypt.chacha, output, input, sz); + + return ret; +} +#endif + +/* Decrypt data for TLS v1.3. + * + * ssl The SSL/TLS object. + * output The buffer to write decrypted data into. + * May be the same pointer as input. + * input The data to decrypt and authentication tag. + * sz The length of the encrypted data plus authentication tag. + * aad The additional authentication data. + * aadSz The size of the addition authentication data. + * returns 0 on success, otherwise failure. + */ +int DecryptTls13(WOLFSSL* ssl, byte* output, const byte* input, word16 sz, + const byte* aad, word16 aadSz) +{ + int ret = 0; + word16 dataSz = sz - ssl->specs.aead_mac_size; + word16 macSz = ssl->specs.aead_mac_size; + word32 nonceSz = 0; + + WOLFSSL_ENTER("DecryptTls13"); + +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfSSL_AsyncPop(ssl, &ssl->decrypt.state); + if (ret != WC_NOT_PENDING_E) { + /* check for still pending */ + if (ret == WC_PENDING_E) + return ret; + + ssl->error = 0; /* clear async */ + + /* let failures through so CIPHER_STATE_END logic is run */ + } + else +#endif + { + /* Reset state */ + ret = 0; + ssl->decrypt.state = CIPHER_STATE_BEGIN; + } + + (void)output; + (void)input; + (void)sz; + (void)dataSz; + (void)macSz; + (void)nonceSz; + + switch (ssl->decrypt.state) { + case CIPHER_STATE_BEGIN: + { + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Data to decrypt"); + WOLFSSL_BUFFER(input, dataSz); +#if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22) && \ + !defined(WOLFSSL_TLS13_DRAFT_23) + WOLFSSL_MSG("Additional Authentication Data"); + WOLFSSL_BUFFER(aad, aadSz); +#endif + WOLFSSL_MSG("Authentication tag"); + WOLFSSL_BUFFER(input + dataSz, macSz); + #endif + + if (ssl->decrypt.nonce == NULL) + ssl->decrypt.nonce = (byte*)XMALLOC(AEAD_NONCE_SZ, + ssl->heap, DYNAMIC_TYPE_AES_BUFFER); + if (ssl->decrypt.nonce == NULL) + return MEMORY_E; + + BuildTls13Nonce(ssl, ssl->decrypt.nonce, ssl->keys.aead_dec_imp_IV, + PEER_ORDER); + + /* Advance state and proceed */ + ssl->decrypt.state = CIPHER_STATE_DO; + } + FALL_THROUGH; + + case CIPHER_STATE_DO: + { + switch (ssl->specs.bulk_cipher_algorithm) { + #ifdef BUILD_AESGCM + case wolfssl_aes_gcm: + #ifdef WOLFSSL_ASYNC_CRYPT + /* initialize event */ + ret = wolfSSL_AsyncInit(ssl, &ssl->decrypt.aes->asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + if (ret != 0) + break; + #endif + + nonceSz = AESGCM_NONCE_SZ; + ret = wc_AesGcmDecrypt(ssl->decrypt.aes, output, input, + dataSz, ssl->decrypt.nonce, nonceSz, + input + dataSz, macSz, aad, aadSz); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, + &ssl->decrypt.aes->asyncDev); + } + #endif + break; + #endif + + #ifdef HAVE_AESCCM + case wolfssl_aes_ccm: + #ifdef WOLFSSL_ASYNC_CRYPT + /* initialize event */ + ret = wolfSSL_AsyncInit(ssl, &ssl->decrypt.aes->asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + if (ret != 0) + break; + #endif + + nonceSz = AESCCM_NONCE_SZ; + ret = wc_AesCcmDecrypt(ssl->decrypt.aes, output, input, + dataSz, ssl->decrypt.nonce, nonceSz, + input + dataSz, macSz, aad, aadSz); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wolfSSL_AsyncPush(ssl, + &ssl->decrypt.aes->asyncDev); + } + #endif + break; + #endif + + #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) + case wolfssl_chacha: + ret = ChaCha20Poly1305_Decrypt(ssl, output, input, dataSz, + ssl->decrypt.nonce, aad, aadSz, input + dataSz); + break; + #endif + + default: + WOLFSSL_MSG("wolfSSL Decrypt programming error"); + return DECRYPT_ERROR; + } + + /* Advance state */ + ssl->decrypt.state = CIPHER_STATE_END; + + #ifdef WOLFSSL_ASYNC_CRYPT + /* If pending, leave now */ + if (ret == WC_PENDING_E) { + return ret; + } + #endif + } + FALL_THROUGH; + + case CIPHER_STATE_END: + { + #ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Nonce"); + WOLFSSL_BUFFER(ssl->decrypt.nonce, ssl->specs.iv_size); + WOLFSSL_MSG("Decrypted data"); + WOLFSSL_BUFFER(output, dataSz); + #endif + + ForceZero(ssl->decrypt.nonce, AEAD_NONCE_SZ); + + break; + } + } + +#ifndef WOLFSSL_EARLY_DATA + if (ret < 0) { + SendAlert(ssl, alert_fatal, bad_record_mac); + ret = VERIFY_MAC_ERROR; + } +#endif + + return ret; +} + +/* Persistable BuildTls13Message arguments */ +typedef struct BuildMsg13Args { + word32 sz; + word32 idx; + word32 headerSz; + word16 size; +} BuildMsg13Args; + +static void FreeBuildMsg13Args(WOLFSSL* ssl, void* pArgs) +{ + BuildMsg13Args* args = (BuildMsg13Args*)pArgs; + + (void)ssl; + (void)args; + + /* no allocations in BuildTls13Message */ +} + +/* Build SSL Message, encrypted. + * TLS v1.3 encryption is AEAD only. + * + * ssl The SSL/TLS object. + * output The buffer to write record message to. + * outSz Size of the buffer being written into. + * input The record data to encrypt (excluding record header). + * inSz The size of the record data. + * type The recorder header content type. + * hashOutput Whether to hash the unencrypted record data. + * sizeOnly Only want the size of the record message. + * asyncOkay If non-zero can return WC_PENDING_E, otherwise blocks on crypto + * returns the size of the encrypted record message or negative value on error. + */ +int BuildTls13Message(WOLFSSL* ssl, byte* output, int outSz, const byte* input, + int inSz, int type, int hashOutput, int sizeOnly, int asyncOkay) +{ + int ret = 0; + BuildMsg13Args* args; + BuildMsg13Args lcl_args; +#ifdef WOLFSSL_ASYNC_CRYPT + args = (BuildMsg13Args*)ssl->async.args; + typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1]; + (void)sizeof(args_test); +#endif + + WOLFSSL_ENTER("BuildTls13Message"); + + ret = WC_NOT_PENDING_E; +#ifdef WOLFSSL_ASYNC_CRYPT + if (asyncOkay) { + ret = wolfSSL_AsyncPop(ssl, &ssl->options.buildMsgState); + if (ret != WC_NOT_PENDING_E) { + /* Check for error */ + if (ret < 0) + goto exit_buildmsg; + } + } + else +#endif + { + args = &lcl_args; + } + + /* Reset state */ + if (ret == WC_NOT_PENDING_E) { + ret = 0; + ssl->options.buildMsgState = BUILD_MSG_BEGIN; + XMEMSET(args, 0, sizeof(BuildMsg13Args)); + + args->sz = RECORD_HEADER_SZ + inSz; + args->idx = RECORD_HEADER_SZ; + args->headerSz = RECORD_HEADER_SZ; + #ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = FreeBuildMsg13Args; + #endif + } + + switch (ssl->options.buildMsgState) { + case BUILD_MSG_BEGIN: + { + /* catch mistaken sizeOnly parameter */ + if (sizeOnly) { + if (output || input) { + WOLFSSL_MSG("BuildTls13Message with sizeOnly " + "doesn't need input or output"); + return BAD_FUNC_ARG; + } + } + else if (output == NULL || input == NULL) { + return BAD_FUNC_ARG; + } + + /* Record layer content type at the end of record data. */ + args->sz++; + /* Authentication data at the end. */ + args->sz += ssl->specs.aead_mac_size; + + if (sizeOnly) + return args->sz; + + if (args->sz > (word32)outSz) { + WOLFSSL_MSG("Oops, want to write past output buffer size"); + return BUFFER_E; + } + + /* Record data length. */ + args->size = (word16)(args->sz - args->headerSz); + /* Write/update the record header with the new size. + * Always have the content type as application data for encrypted + * messages in TLS v1.3. + */ + AddTls13RecordHeader(output, args->size, application_data, ssl); + + /* TLS v1.3 can do in place encryption. */ + if (input != output + args->idx) + XMEMCPY(output + args->idx, input, inSz); + args->idx += inSz; + + ssl->options.buildMsgState = BUILD_MSG_HASH; + } + FALL_THROUGH; + + case BUILD_MSG_HASH: + { + if (hashOutput) { + ret = HashOutput(ssl, output, args->headerSz + inSz, 0); + if (ret != 0) + goto exit_buildmsg; + } + + /* The real record content type goes at the end of the data. */ + output[args->idx++] = (byte)type; + + ssl->options.buildMsgState = BUILD_MSG_ENCRYPT; + } + FALL_THROUGH; + + case BUILD_MSG_ENCRYPT: + { + #ifdef ATOMIC_USER + if (ssl->ctx->MacEncryptCb) { + /* User Record Layer Callback handling */ + byte* mac = output + args->idx; + output += args->headerSz; + + ret = ssl->ctx->MacEncryptCb(ssl, mac, output, inSz, type, 0, + output, output, args->size, ssl->MacEncryptCtx); + } + else + #endif + { +#if defined(WOLFSSL_TLS13_DRAFT_18) || defined(WOLFSSL_TLS13_DRAFT_22) || \ + defined(WOLFSSL_TLS13_DRAFT_23) + output += args->headerSz; + ret = EncryptTls13(ssl, output, output, args->size, NULL, 0, + asyncOkay); +#else + const byte* aad = output; + output += args->headerSz; + ret = EncryptTls13(ssl, output, output, args->size, aad, + RECORD_HEADER_SZ, asyncOkay); +#endif + } + break; + } + } + +exit_buildmsg: + + WOLFSSL_LEAVE("BuildTls13Message", ret); + +#ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + return ret; + } +#endif + + /* make sure build message state is reset */ + ssl->options.buildMsgState = BUILD_MSG_BEGIN; + + /* return sz on success */ + if (ret == 0) + ret = args->sz; + + /* Final cleanup */ + FreeBuildMsg13Args(ssl, args); +#ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = NULL; +#endif + + return ret; +} + +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) +/* Find the cipher suite in the suites set in the SSL. + * + * ssl SSL/TLS object. + * suite Cipher suite to look for. + * returns 1 when suite is found in SSL/TLS object's list and 0 otherwise. + */ +static int FindSuiteSSL(WOLFSSL* ssl, byte* suite) +{ + word16 i; + + for (i = 0; i < ssl->suites->suiteSz; i += 2) { + if (ssl->suites->suites[i+0] == suite[0] && + ssl->suites->suites[i+1] == suite[1]) { + return 1; + } + } + + return 0; +} +#endif + +#ifndef WOLFSSL_TLS13_DRAFT_18 +#if defined(WOLFSSL_SEND_HRR_COOKIE) && !defined(NO_WOLFSSL_SERVER) +/* Create Cookie extension using the hash of the first ClientHello. + * + * ssl SSL/TLS object. + * hash The hash data. + * hashSz The size of the hash data in bytes. + * returns 0 on success, otherwise failure. + */ +static int CreateCookie(WOLFSSL* ssl, byte* hash, byte hashSz) +{ + int ret; + byte mac[WC_MAX_DIGEST_SIZE]; + Hmac cookieHmac; + byte cookieType; + byte macSz; + +#if !defined(NO_SHA) && defined(NO_SHA256) + cookieType = SHA; + macSz = WC_SHA_DIGEST_SIZE; +#endif /* NO_SHA */ +#ifndef NO_SHA256 + cookieType = WC_SHA256; + macSz = WC_SHA256_DIGEST_SIZE; +#endif /* NO_SHA256 */ + + ret = wc_HmacSetKey(&cookieHmac, cookieType, + ssl->buffers.tls13CookieSecret.buffer, + ssl->buffers.tls13CookieSecret.length); + if (ret != 0) + return ret; + if ((ret = wc_HmacUpdate(&cookieHmac, hash, hashSz)) != 0) + return ret; + if ((ret = wc_HmacFinal(&cookieHmac, mac)) != 0) + return ret; + + /* The cookie data is the hash and the integrity check. */ + return TLSX_Cookie_Use(ssl, hash, hashSz, mac, macSz, 1); +} +#endif + +/* Restart the handshake hash with a hash of the previous messages. + * + * ssl The SSL/TLS object. + * returns 0 on success, otherwise failure. + */ +static int RestartHandshakeHash(WOLFSSL* ssl) +{ + int ret; + Hashes hashes; + byte header[HANDSHAKE_HEADER_SZ]; + byte* hash = NULL; + byte hashSz = 0; + + ret = BuildCertHashes(ssl, &hashes); + if (ret != 0) + return ret; + switch (ssl->specs.mac_algorithm) { + #ifndef NO_SHA256 + case sha256_mac: + hash = hashes.sha256; + break; + #endif + #ifdef WOLFSSL_SHA384 + case sha384_mac: + hash = hashes.sha384; + break; + #endif + #ifdef WOLFSSL_TLS13_SHA512 + case sha512_mac: + hash = hashes.sha512; + break; + #endif + } + hashSz = ssl->specs.hash_size; + + /* check hash */ + if (hash == NULL && hashSz > 0) + return BAD_FUNC_ARG; + + AddTls13HandShakeHeader(header, hashSz, 0, 0, message_hash, ssl); + + WOLFSSL_MSG("Restart Hash"); + WOLFSSL_BUFFER(hash, hashSz); + +#if defined(WOLFSSL_SEND_HRR_COOKIE) && !defined(NO_WOLFSSL_SERVER) + if (ssl->options.sendCookie) { + byte cookie[OPAQUE8_LEN + WC_MAX_DIGEST_SIZE + OPAQUE16_LEN * 2]; + TLSX* ext; + word32 idx = 0; + + /* Cookie Data = Hash Len | Hash | CS | KeyShare Group */ + cookie[idx++] = hashSz; + if (hash) + XMEMCPY(cookie + idx, hash, hashSz); + idx += hashSz; + cookie[idx++] = ssl->options.cipherSuite0; + cookie[idx++] = ssl->options.cipherSuite; + if ((ext = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE)) != NULL) { + KeyShareEntry* kse = (KeyShareEntry*)ext->data; + c16toa(kse->group, cookie + idx); + idx += OPAQUE16_LEN; + } + return CreateCookie(ssl, cookie, idx); + } +#endif + + ret = InitHandshakeHashes(ssl); + if (ret != 0) + return ret; + ret = HashOutputRaw(ssl, header, sizeof(header)); + if (ret != 0) + return ret; + return HashOutputRaw(ssl, hash, hashSz); +} + +/* The value in the random field of a ServerHello to indicate + * HelloRetryRequest. + */ +static byte helloRetryRequestRandom[] = { + 0xCF, 0x21, 0xAD, 0x74, 0xE5, 0x9A, 0x61, 0x11, + 0xBE, 0x1D, 0x8C, 0x02, 0x1E, 0x65, 0xB8, 0x91, + 0xC2, 0xA2, 0x11, 0x16, 0x7A, 0xBB, 0x8C, 0x5E, + 0x07, 0x9E, 0x09, 0xE2, 0xC8, 0xA8, 0x33, 0x9C +}; +#endif /* WOLFSSL_TLS13_DRAFT_18 */ + +#ifndef NO_WOLFSSL_CLIENT +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) +/* Setup pre-shared key based on the details in the extension data. + * + * ssl SSL/TLS object. + * psk Pre-shared key extension data. + * returns 0 on success, PSK_KEY_ERROR when the client PSK callback fails and + * other negative value on failure. + */ +static int SetupPskKey(WOLFSSL* ssl, PreSharedKey* psk) +{ + int ret; + byte suite[2]; + + if (psk == NULL) + return BAD_FUNC_ARG; + + suite[0] = psk->cipherSuite0; + suite[1] = psk->cipherSuite; + if (!FindSuiteSSL(ssl, suite)) + return PSK_KEY_ERROR; + + ssl->options.cipherSuite0 = psk->cipherSuite0; + ssl->options.cipherSuite = psk->cipherSuite; + if ((ret = SetCipherSpecs(ssl)) != 0) + return ret; + +#ifdef HAVE_SESSION_TICKET + if (psk->resumption) { + #ifdef WOLFSSL_EARLY_DATA + if (ssl->session.maxEarlyDataSz == 0) + ssl->earlyData = no_early_data; + #endif + /* Resumption PSK is master secret. */ + ssl->arrays->psk_keySz = ssl->specs.hash_size; +#ifdef WOLFSSL_TLS13_DRAFT_18 + XMEMCPY(ssl->arrays->psk_key, ssl->session.masterSecret, + ssl->arrays->psk_keySz); +#else + if ((ret = DeriveResumptionPSK(ssl, ssl->session.ticketNonce.data, + ssl->session.ticketNonce.len, ssl->arrays->psk_key)) != 0) { + return ret; + } +#endif + } +#endif +#ifndef NO_PSK + if (!psk->resumption) { + #ifndef WOLFSSL_PSK_ONE_ID + const char* cipherName = NULL; + byte cipherSuite0 = TLS13_BYTE, cipherSuite = WOLFSSL_DEF_PSK_CIPHER; + + /* Get the pre-shared key. */ + if (ssl->options.client_psk_tls13_cb != NULL) { + ssl->arrays->psk_keySz = ssl->options.client_psk_tls13_cb(ssl, + (char *)psk->identity, ssl->arrays->client_identity, + MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN, + &cipherName); + if (GetCipherSuiteFromName(cipherName, &cipherSuite0, + &cipherSuite) != 0) { + return PSK_KEY_ERROR; + } + } + else { + ssl->arrays->psk_keySz = ssl->options.client_psk_cb(ssl, + (char *)psk->identity, ssl->arrays->client_identity, + MAX_PSK_ID_LEN, ssl->arrays->psk_key, MAX_PSK_KEY_LEN); + } + if (ssl->arrays->psk_keySz == 0 || + ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) { + return PSK_KEY_ERROR; + } + + if (psk->cipherSuite0 != cipherSuite0 || + psk->cipherSuite != cipherSuite) { + return PSK_KEY_ERROR; + } + #else + /* PSK information loaded during setting of default TLS extensions. */ + #endif + } +#endif + + if (ssl->options.noPskDheKe) + ssl->arrays->preMasterSz = 0; + + /* Derive the early secret using the PSK. */ + return DeriveEarlySecret(ssl); +} + +/* Derive and write the binders into the ClientHello in space left when + * writing the Pre-Shared Key extension. + * + * ssl The SSL/TLS object. + * output The buffer containing the ClientHello. + * idx The index at the end of the completed ClientHello. + * returns 0 on success and otherwise failure. + */ +static int WritePSKBinders(WOLFSSL* ssl, byte* output, word32 idx) +{ + int ret; + TLSX* ext; + PreSharedKey* current; + byte binderKey[WC_MAX_DIGEST_SIZE]; + word16 len; + + WOLFSSL_ENTER("WritePSKBinders"); + + ext = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY); + if (ext == NULL) + return SANITY_MSG_E; + + /* Get the size of the binders to determine where to write binders. */ + ret = TLSX_PreSharedKey_GetSizeBinders((PreSharedKey*)ext->data, + client_hello, &len); + if (ret < 0) + return ret; + idx -= len; + + /* Hash truncated ClientHello - up to binders. */ + ret = HashOutput(ssl, output, idx, 0); + if (ret != 0) + return ret; + + current = (PreSharedKey*)ext->data; + /* Calculate the binder for each identity based on previous handshake data. + */ + while (current != NULL) { + if ((ret = SetupPskKey(ssl, current)) != 0) + return ret; + + #ifdef HAVE_SESSION_TICKET + if (current->resumption) + ret = DeriveBinderKeyResume(ssl, binderKey); + #endif + #ifndef NO_PSK + if (!current->resumption) + ret = DeriveBinderKey(ssl, binderKey); + #endif + if (ret != 0) + return ret; + + /* Derive the Finished message secret. */ + ret = DeriveFinishedSecret(ssl, binderKey, + ssl->keys.client_write_MAC_secret); + if (ret != 0) + return ret; + + /* Build the HMAC of the handshake message data = binder. */ + ret = BuildTls13HandshakeHmac(ssl, ssl->keys.client_write_MAC_secret, + current->binder, ¤t->binderLen); + if (ret != 0) + return ret; + + current = current->next; + } + + /* Data entered into extension, now write to message. */ + ret = TLSX_PreSharedKey_WriteBinders((PreSharedKey*)ext->data, output + idx, + client_hello, &len); + if (ret < 0) + return ret; + + /* Hash binders to complete the hash of the ClientHello. */ + ret = HashOutputRaw(ssl, output + idx, len); + if (ret < 0) + return ret; + + #ifdef WOLFSSL_EARLY_DATA + if (ssl->earlyData != no_early_data) { + if ((ret = SetupPskKey(ssl, (PreSharedKey*)ext->data)) != 0) + return ret; + + /* Derive early data encryption key. */ + ret = DeriveTls13Keys(ssl, early_data_key, ENCRYPT_SIDE_ONLY, 1); + if (ret != 0) + return ret; + if ((ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY)) != 0) + return ret; + } + #endif + + WOLFSSL_LEAVE("WritePSKBinders", ret); + + return ret; +} +#endif + +/* handle generation of TLS 1.3 client_hello (1) */ +/* Send a ClientHello message to the server. + * Include the information required to start a handshake with servers using + * protocol versions less than TLS v1.3. + * Only a client will send this message. + * + * ssl The SSL/TLS object. + * returns 0 on success and otherwise failure. + */ +int SendTls13ClientHello(WOLFSSL* ssl) +{ + byte* output; + word16 length; + word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + int sendSz; + int ret; + + WOLFSSL_START(WC_FUNC_CLIENT_HELLO_SEND); + WOLFSSL_ENTER("SendTls13ClientHello"); + +#ifdef HAVE_SESSION_TICKET + if (ssl->options.resuming && + (ssl->session.version.major != ssl->version.major || + ssl->session.version.minor != ssl->version.minor)) { + #ifndef WOLFSSL_NO_TLS12 + if (ssl->session.version.major == ssl->version.major && + ssl->session.version.minor < ssl->version.minor) { + /* Cannot resume with a different protocol version. */ + ssl->options.resuming = 0; + ssl->version.major = ssl->session.version.major; + ssl->version.minor = ssl->session.version.minor; + return SendClientHello(ssl); + } + else + #endif + return VERSION_ERROR; + } +#endif + + if (ssl->suites == NULL) { + WOLFSSL_MSG("Bad suites pointer in SendTls13ClientHello"); + return SUITES_ERROR; + } + + /* Version | Random | Session Id | Cipher Suites | Compression */ + length = VERSION_SZ + RAN_LEN + ENUM_LEN + ssl->suites->suiteSz + + SUITE_LEN + COMP_LEN + ENUM_LEN; +#ifndef WOLFSSL_TLS13_DRAFT_18 + #if defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT) + length += ID_LEN; + #else + if (ssl->session.sessionIDSz > 0) + length += ssl->session.sessionIDSz; + #endif +#endif + + /* Auto populate extensions supported unless user defined. */ + if ((ret = TLSX_PopulateExtensions(ssl, 0)) != 0) + return ret; +#ifdef WOLFSSL_EARLY_DATA + #ifndef NO_PSK + if (!ssl->options.resuming && + ssl->options.client_psk_tls13_cb == NULL && + ssl->options.client_psk_cb == NULL) + #else + if (!ssl->options.resuming) + #endif + ssl->earlyData = no_early_data; + if (ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST_COMPLETE) + ssl->earlyData = no_early_data; + if (ssl->earlyData == no_early_data) + TLSX_Remove(&ssl->extensions, TLSX_EARLY_DATA, ssl->heap); + if (ssl->earlyData != no_early_data && + (ret = TLSX_EarlyData_Use(ssl, 0)) < 0) { + return ret; + } +#endif + /* Include length of TLS extensions. */ + ret = TLSX_GetRequestSize(ssl, client_hello, &length); + if (ret != 0) + return ret; + + /* Total message size. */ + sendSz = length + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ; + + /* Check buffers are big enough and grow if needed. */ + if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) + return ret; + + /* Get position in output buffer to write new message to. */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + /* Put the record and handshake headers on. */ + AddTls13Headers(output, length, client_hello, ssl); + + /* Protocol version - negotiation now in extension: supported_versions. */ + output[idx++] = SSLv3_MAJOR; + output[idx++] = TLSv1_2_MINOR; + /* Keep for downgrade. */ + ssl->chVersion = ssl->version; + + /* Client Random */ + if (ssl->options.connectState == CONNECT_BEGIN) { + ret = wc_RNG_GenerateBlock(ssl->rng, output + idx, RAN_LEN); + if (ret != 0) + return ret; + + /* Store random for possible second ClientHello. */ + XMEMCPY(ssl->arrays->clientRandom, output + idx, RAN_LEN); + } + else + XMEMCPY(output + idx, ssl->arrays->clientRandom, RAN_LEN); + idx += RAN_LEN; + +#ifdef WOLFSSL_TLS13_DRAFT_18 + /* TLS v1.3 does not use session id - 0 length. */ + output[idx++] = 0; +#else + if (ssl->session.sessionIDSz > 0) { + /* Session resumption for old versions of protocol. */ + output[idx++] = ID_LEN; + XMEMCPY(output + idx, ssl->session.sessionID, ssl->session.sessionIDSz); + idx += ID_LEN; + } + else { + #ifdef WOLFSSL_TLS13_MIDDLEBOX_COMPAT + output[idx++] = ID_LEN; + XMEMCPY(output + idx, ssl->arrays->clientRandom, ID_LEN); + idx += ID_LEN; + #else + /* TLS v1.3 does not use session id - 0 length. */ + output[idx++] = 0; + #endif /* WOLFSSL_TLS13_MIDDLEBOX_COMPAT */ + } +#endif /* WOLFSSL_TLS13_DRAFT_18 */ + + /* Cipher suites */ + c16toa(ssl->suites->suiteSz, output + idx); + idx += OPAQUE16_LEN; + XMEMCPY(output + idx, &ssl->suites->suites, ssl->suites->suiteSz); + idx += ssl->suites->suiteSz; + + /* Compression not supported in TLS v1.3. */ + output[idx++] = COMP_LEN; + output[idx++] = NO_COMPRESSION; + + /* Write out extensions for a request. */ + length = 0; + ret = TLSX_WriteRequest(ssl, output + idx, client_hello, &length); + if (ret != 0) + return ret; + idx += length; + +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + /* Resumption has a specific set of extensions and binder is calculated + * for each identity. + */ + if (TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY)) + ret = WritePSKBinders(ssl, output, idx); + else +#endif + ret = HashOutput(ssl, output, idx, 0); + if (ret != 0) + return ret; + + ssl->options.clientState = CLIENT_HELLO_COMPLETE; + +#ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName(ssl, "ClientHello"); + if (ssl->toInfoOn) { + AddPacketInfo(ssl, "ClientHello", handshake, output, sendSz, + WRITE_PROTO, ssl->heap); + } +#endif + + ssl->buffers.outputBuffer.length += sendSz; + +#ifdef WOLFSSL_EARLY_DATA_GROUP + if (ssl->earlyData == no_early_data) +#endif + ret = SendBuffered(ssl); + + + WOLFSSL_LEAVE("SendTls13ClientHello", ret); + WOLFSSL_END(WC_FUNC_CLIENT_HELLO_SEND); + + return ret; +} + +#ifdef WOLFSSL_TLS13_DRAFT_18 +/* handle rocessing of TLS 1.3 hello_retry_request (6) */ +/* Parse and handle a HelloRetryRequest message. + * Only a client will receive this message. + * + * ssl The SSL/TLS object. + * input The message buffer. + * inOutIdx On entry, the index into the message buffer of + * HelloRetryRequest. + * On exit, the index of byte after the HelloRetryRequest message. + * totalSz The length of the current handshake message. + * returns 0 on success and otherwise failure. + */ +static int DoTls13HelloRetryRequest(WOLFSSL* ssl, const byte* input, + word32* inOutIdx, word32 totalSz) +{ + int ret; + word32 begin = *inOutIdx; + word32 i = begin; + word16 totalExtSz; + ProtocolVersion pv; + + WOLFSSL_ENTER("DoTls13HelloRetryRequest"); + +#ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName(ssl, "HelloRetryRequest"); + if (ssl->toInfoOn) AddLateName("HelloRetryRequest", &ssl->timeoutInfo); +#endif + + /* Version info and length field of extension data. */ + if (totalSz < i - begin + OPAQUE16_LEN + OPAQUE16_LEN + OPAQUE16_LEN) + return BUFFER_ERROR; + + /* Protocol version. */ + XMEMCPY(&pv, input + i, OPAQUE16_LEN); + i += OPAQUE16_LEN; + ret = CheckVersion(ssl, pv); + if (ret != 0) + return ret; + + /* Length of extension data. */ + ato16(&input[i], &totalExtSz); + i += OPAQUE16_LEN; + if (totalExtSz == 0) { + WOLFSSL_MSG("HelloRetryRequest must contain extensions"); + return MISSING_HANDSHAKE_DATA; + } + + /* Extension data. */ + if (i - begin + totalExtSz > totalSz) + return BUFFER_ERROR; + if ((ret = TLSX_Parse(ssl, (byte *)(input + i), totalExtSz, + hello_retry_request, NULL)) != 0) + return ret; + /* The KeyShare extension parsing fails when not valid. */ + + /* Move index to byte after message. */ + *inOutIdx = i + totalExtSz; + + ssl->options.tls1_3 = 1; + ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST_COMPLETE; + + WOLFSSL_LEAVE("DoTls13HelloRetryRequest", ret); + + return ret; +} +#endif + + +/* handle processing of TLS 1.3 server_hello (2) and hello_retry_request (6) */ +/* Handle the ServerHello message from the server. + * Only a client will receive this message. + * + * ssl The SSL/TLS object. + * input The message buffer. + * inOutIdx On entry, the index into the message buffer of ServerHello. + * On exit, the index of byte after the ServerHello message. + * helloSz The length of the current handshake message. + * returns 0 on success and otherwise failure. + */ +int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, + word32 helloSz, byte* extMsgType) +{ + ProtocolVersion pv; + word32 i = *inOutIdx; + word32 begin = i; + int ret; +#ifndef WOLFSSL_TLS13_DRAFT_18 + byte sessIdSz; + const byte* sessId; + byte b; + int foundVersion; +#endif + word16 totalExtSz; +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + TLSX* ext; + PreSharedKey* psk = NULL; +#endif + + WOLFSSL_START(WC_FUNC_SERVER_HELLO_DO); + WOLFSSL_ENTER("DoTls13ServerHello"); + +#ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName(ssl, "ServerHello"); + if (ssl->toInfoOn) AddLateName("ServerHello", &ssl->timeoutInfo); +#endif + + /* Protocol version length check. */ + if (OPAQUE16_LEN > helloSz) + return BUFFER_ERROR; + + /* Protocol version */ + XMEMCPY(&pv, input + i, OPAQUE16_LEN); + i += OPAQUE16_LEN; +#ifdef WOLFSSL_TLS13_DRAFT_18 + ret = CheckVersion(ssl, pv); + if (ret != 0) + return ret; + if (!IsAtLeastTLSv1_3(pv) && pv.major != TLS_DRAFT_MAJOR) { +#ifndef WOLFSSL_NO_TLS12 + if (ssl->options.downgrade) { + ssl->version = pv; + return DoServerHello(ssl, input, inOutIdx, helloSz); + } +#endif + + WOLFSSL_MSG("Client using higher version, fatal error"); + return VERSION_ERROR; + } +#else +#ifndef WOLFSSL_NO_TLS12 + if (pv.major == ssl->version.major && pv.minor < TLSv1_2_MINOR && + ssl->options.downgrade) { + /* Force client hello version 1.2 to work for static RSA. */ + ssl->chVersion.minor = TLSv1_2_MINOR; + ssl->version.minor = TLSv1_2_MINOR; + return DoServerHello(ssl, input, inOutIdx, helloSz); + } +#endif + if (pv.major != ssl->version.major || pv.minor != TLSv1_2_MINOR) + return VERSION_ERROR; +#endif + +#ifdef WOLFSSL_TLS13_DRAFT_18 + /* Random length check */ + if ((i - begin) + RAN_LEN > helloSz) + return BUFFER_ERROR; +#else + /* Random and session id length check */ + if ((i - begin) + RAN_LEN + ENUM_LEN > helloSz) + return BUFFER_ERROR; + + if (XMEMCMP(input + i, helloRetryRequestRandom, RAN_LEN) == 0) + *extMsgType = hello_retry_request; +#endif + + /* Server random - keep for debugging. */ + XMEMCPY(ssl->arrays->serverRandom, input + i, RAN_LEN); + i += RAN_LEN; + +#ifndef WOLFSSL_TLS13_DRAFT_18 + /* Session id */ + sessIdSz = input[i++]; + if ((i - begin) + sessIdSz > helloSz) + return BUFFER_ERROR; + sessId = input + i; + i += sessIdSz; +#endif /* WOLFSSL_TLS13_DRAFT_18 */ + ssl->options.haveSessionId = 1; + +#ifdef WOLFSSL_TLS13_DRAFT_18 + /* Ciphersuite check */ + if ((i - begin) + OPAQUE16_LEN + OPAQUE16_LEN > helloSz) + return BUFFER_ERROR; +#else + /* Ciphersuite and compression check */ + if ((i - begin) + OPAQUE16_LEN + OPAQUE8_LEN > helloSz) + return BUFFER_ERROR; +#endif + + /* Set the cipher suite from the message. */ + ssl->options.cipherSuite0 = input[i++]; + ssl->options.cipherSuite = input[i++]; + +#ifndef WOLFSSL_TLS13_DRAFT_18 + /* Compression */ + b = input[i++]; + if (b != 0) { + WOLFSSL_MSG("Must be no compression types in list"); + return INVALID_PARAMETER; + } +#endif + +#ifndef WOLFSSL_TLS13_DRAFT_18 + if ((i - begin) + OPAQUE16_LEN > helloSz) { + if (!ssl->options.downgrade) + return BUFFER_ERROR; +#ifndef WOLFSSL_NO_TLS12 + ssl->version.minor = TLSv1_2_MINOR; +#endif + ssl->options.haveEMS = 0; + } + if ((i - begin) < helloSz) +#endif + { + /* Get extension length and length check. */ + if ((i - begin) + OPAQUE16_LEN > helloSz) + return BUFFER_ERROR; + ato16(&input[i], &totalExtSz); + i += OPAQUE16_LEN; + if ((i - begin) + totalExtSz > helloSz) + return BUFFER_ERROR; + +#ifndef WOLFSSL_TLS13_DRAFT_18 + /* Need to negotiate version first. */ + if ((ret = TLSX_ParseVersion(ssl, (byte*)input + i, totalExtSz, + *extMsgType, &foundVersion))) { + return ret; + } + if (!foundVersion) { + if (!ssl->options.downgrade) { + WOLFSSL_MSG("Server trying to downgrade to version less than " + "TLS v1.3"); + return VERSION_ERROR; + } + + if (pv.minor < ssl->options.minDowngrade) + return VERSION_ERROR; + ssl->version.minor = pv.minor; + } +#endif + + /* Parse and handle extensions. */ + ret = TLSX_Parse(ssl, (byte *) input + i, totalExtSz, *extMsgType, + NULL); + if (ret != 0) + return ret; + + i += totalExtSz; + } + *inOutIdx = i; + + ssl->options.serverState = SERVER_HELLO_COMPLETE; + +#ifdef HAVE_SECRET_CALLBACK + if (ssl->sessionSecretCb != NULL) { + int secretSz = SECRET_LEN; + ret = ssl->sessionSecretCb(ssl, ssl->session.masterSecret, + &secretSz, ssl->sessionSecretCtx); + if (ret != 0 || secretSz != SECRET_LEN) + return SESSION_SECRET_CB_E; + } +#endif /* HAVE_SECRET_CALLBACK */ + +#ifndef WOLFSSL_TLS13_DRAFT_18 + /* Version only negotiated in extensions for TLS v1.3. + * Only now do we know how to deal with session id. + */ + if (!IsAtLeastTLSv1_3(ssl->version)) { +#ifndef WOLFSSL_NO_TLS12 + ssl->arrays->sessionIDSz = sessIdSz; + + if (ssl->arrays->sessionIDSz > ID_LEN) { + WOLFSSL_MSG("Invalid session ID size"); + ssl->arrays->sessionIDSz = 0; + return BUFFER_ERROR; + } + else if (ssl->arrays->sessionIDSz) { + XMEMCPY(ssl->arrays->sessionID, sessId, ssl->arrays->sessionIDSz); + ssl->options.haveSessionId = 1; + } + + /* Force client hello version 1.2 to work for static RSA. */ + ssl->chVersion.minor = TLSv1_2_MINOR; + /* Complete TLS v1.2 processing of ServerHello. */ + ret = CompleteServerHello(ssl); +#else + WOLFSSL_MSG("Client using higher version, fatal error"); + ret = VERSION_ERROR; +#endif + + WOLFSSL_LEAVE("DoTls13ServerHello", ret); + + return ret; + } + + #ifdef WOLFSSL_TLS13_MIDDLEBOX_COMPAT + if (sessIdSz == 0) + return INVALID_PARAMETER; + if (ssl->session.sessionIDSz != 0) { + if (ssl->session.sessionIDSz != sessIdSz || + XMEMCMP(ssl->session.sessionID, sessId, sessIdSz) != 0) { + return INVALID_PARAMETER; + } + } + else if (XMEMCMP(ssl->arrays->clientRandom, sessId, sessIdSz) != 0) + return INVALID_PARAMETER; + #else + if (sessIdSz != ssl->session.sessionIDSz || (sessIdSz > 0 && + XMEMCMP(ssl->session.sessionID, sessId, sessIdSz) != 0)) { + WOLFSSL_MSG("Server sent different session id"); + return INVALID_PARAMETER; + } + #endif /* WOLFSSL_TLS13_MIDDLEBOX_COMPAT */ +#endif + + ret = SetCipherSpecs(ssl); + if (ret != 0) + return ret; + +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) +#ifndef WOLFSSL_TLS13_DRAFT_18 + if (*extMsgType == server_hello) +#endif + { + ext = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY); + if (ext != NULL) + psk = (PreSharedKey*)ext->data; + while (psk != NULL && !psk->chosen) + psk = psk->next; + if (psk == NULL) { + ssl->options.resuming = 0; + ssl->arrays->psk_keySz = 0; + XMEMSET(ssl->arrays->psk_key, 0, MAX_PSK_KEY_LEN); + } + else if ((ret = SetupPskKey(ssl, psk)) != 0) + return ret; + } +#endif + +#ifdef WOLFSSL_TLS13_DRAFT_18 + ssl->keys.encryptionOn = 1; +#else + if (*extMsgType == server_hello) { + ssl->keys.encryptionOn = 1; + ssl->options.serverState = SERVER_HELLO_COMPLETE; + } + else { + ssl->options.tls1_3 = 1; + ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST_COMPLETE; + + ret = RestartHandshakeHash(ssl); + } +#endif + + WOLFSSL_LEAVE("DoTls13ServerHello", ret); + WOLFSSL_END(WC_FUNC_SERVER_HELLO_DO); + + return ret; +} + +/* handle processing TLS 1.3 encrypted_extensions (8) */ +/* Parse and handle an EncryptedExtensions message. + * Only a client will receive this message. + * + * ssl The SSL/TLS object. + * input The message buffer. + * inOutIdx On entry, the index into the message buffer of + * EncryptedExtensions. + * On exit, the index of byte after the EncryptedExtensions + * message. + * totalSz The length of the current handshake message. + * returns 0 on success and otherwise failure. + */ +static int DoTls13EncryptedExtensions(WOLFSSL* ssl, const byte* input, + word32* inOutIdx, word32 totalSz) +{ + int ret; + word32 begin = *inOutIdx; + word32 i = begin; + word16 totalExtSz; + + WOLFSSL_START(WC_FUNC_ENCRYPTED_EXTENSIONS_DO); + WOLFSSL_ENTER("DoTls13EncryptedExtensions"); + +#ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName(ssl, "EncryptedExtensions"); + if (ssl->toInfoOn) AddLateName("EncryptedExtensions", &ssl->timeoutInfo); +#endif + + /* Length field of extension data. */ + if (totalSz < i - begin + OPAQUE16_LEN) + return BUFFER_ERROR; + ato16(&input[i], &totalExtSz); + i += OPAQUE16_LEN; + + /* Extension data. */ + if (i - begin + totalExtSz > totalSz) + return BUFFER_ERROR; + if ((ret = TLSX_Parse(ssl, (byte *)(input + i), totalExtSz, + encrypted_extensions, NULL))) + return ret; + + /* Move index to byte after message. */ + *inOutIdx = i + totalExtSz; + + /* Always encrypted. */ + *inOutIdx += ssl->keys.padSz; + +#ifdef WOLFSSL_EARLY_DATA + if (ssl->earlyData != no_early_data) { + TLSX* ext = TLSX_Find(ssl->extensions, TLSX_EARLY_DATA); + if (ext == NULL || !ext->val) + ssl->earlyData = no_early_data; + } +#endif + +#ifdef WOLFSSL_EARLY_DATA + if (ssl->earlyData == no_early_data) { + ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY); + if (ret != 0) + return ret; + } +#endif + + ssl->options.serverState = SERVER_ENCRYPTED_EXTENSIONS_COMPLETE; + + WOLFSSL_LEAVE("DoTls13EncryptedExtensions", ret); + WOLFSSL_END(WC_FUNC_ENCRYPTED_EXTENSIONS_DO); + + return ret; +} + +/* handle processing TLS v1.3 certificate_request (13) */ +/* Handle a TLS v1.3 CertificateRequest message. + * This message is always encrypted. + * Only a client will receive this message. + * + * ssl The SSL/TLS object. + * input The message buffer. + * inOutIdx On entry, the index into the message buffer of CertificateRequest. + * On exit, the index of byte after the CertificateRequest message. + * size The length of the current handshake message. + * returns 0 on success and otherwise failure. + */ +static int DoTls13CertificateRequest(WOLFSSL* ssl, const byte* input, + word32* inOutIdx, word32 size) +{ + word16 len; + word32 begin = *inOutIdx; + int ret = 0; +#ifndef WOLFSSL_TLS13_DRAFT_18 + Suites peerSuites; +#endif +#ifdef WOLFSSL_POST_HANDSHAKE_AUTH + CertReqCtx* certReqCtx; +#endif + + WOLFSSL_START(WC_FUNC_CERTIFICATE_REQUEST_DO); + WOLFSSL_ENTER("DoTls13CertificateRequest"); + +#ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName(ssl, "CertificateRequest"); + if (ssl->toInfoOn) AddLateName("CertificateRequest", &ssl->timeoutInfo); +#endif + + if ((*inOutIdx - begin) + OPAQUE8_LEN > size) + return BUFFER_ERROR; + + /* Length of the request context. */ + len = input[(*inOutIdx)++]; + if ((*inOutIdx - begin) + len > size) + return BUFFER_ERROR; + if (ssl->options.connectState < FINISHED_DONE && len > 0) + return BUFFER_ERROR; + +#ifdef WOLFSSL_POST_HANDSHAKE_AUTH + /* CertReqCtx has one byte at end for context value. + * Increase size to handle other implementations sending more than one byte. + * That is, allocate extra space, over one byte, to hold the context value. + */ + certReqCtx = (CertReqCtx*)XMALLOC(sizeof(CertReqCtx) + len - 1, ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (certReqCtx == NULL) + return MEMORY_E; + certReqCtx->next = ssl->certReqCtx; + certReqCtx->len = len; + XMEMCPY(&certReqCtx->ctx, input + *inOutIdx, len); + ssl->certReqCtx = certReqCtx; +#endif + *inOutIdx += len; + +#ifdef WOLFSSL_TLS13_DRAFT_18 + /* Signature and hash algorithms. */ + if ((*inOutIdx - begin) + OPAQUE16_LEN > size) + return BUFFER_ERROR; + ato16(input + *inOutIdx, &len); + *inOutIdx += OPAQUE16_LEN; + if ((*inOutIdx - begin) + len > size) + return BUFFER_ERROR; + if (PickHashSigAlgo(ssl, input + *inOutIdx, len) != 0 && + ssl->buffers.certificate && ssl->buffers.certificate->buffer && + ssl->buffers.key && ssl->buffers.key->buffer) { + return INVALID_PARAMETER; + } + *inOutIdx += len; + + /* Length of certificate authority data. */ + if ((*inOutIdx - begin) + OPAQUE16_LEN > size) + return BUFFER_ERROR; + ato16(input + *inOutIdx, &len); + *inOutIdx += OPAQUE16_LEN; + if ((*inOutIdx - begin) + len > size) + return BUFFER_ERROR; + + /* Certificate authorities. */ + while (len) { + word16 dnSz; + + if ((*inOutIdx - begin) + OPAQUE16_LEN > size) + return BUFFER_ERROR; + + ato16(input + *inOutIdx, &dnSz); + *inOutIdx += OPAQUE16_LEN; + + if ((*inOutIdx - begin) + dnSz > size) + return BUFFER_ERROR; + + *inOutIdx += dnSz; + len -= OPAQUE16_LEN + dnSz; + } + + /* Certificate extensions */ + if ((*inOutIdx - begin) + OPAQUE16_LEN > size) + return BUFFER_ERROR; + ato16(input + *inOutIdx, &len); + *inOutIdx += OPAQUE16_LEN; + if ((*inOutIdx - begin) + len > size) + return BUFFER_ERROR; + *inOutIdx += len; +#else + /* TODO: Add support for more extensions: + * signed_certificate_timestamp, certificate_authorities, oid_filters. + */ + /* Certificate extensions */ + if ((*inOutIdx - begin) + OPAQUE16_LEN > size) + return BUFFER_ERROR; + ato16(input + *inOutIdx, &len); + *inOutIdx += OPAQUE16_LEN; + if ((*inOutIdx - begin) + len > size) + return BUFFER_ERROR; + if (len == 0) + return INVALID_PARAMETER; + if ((ret = TLSX_Parse(ssl, (byte *)(input + *inOutIdx), len, + certificate_request, &peerSuites))) { + return ret; + } + *inOutIdx += len; +#endif + + if (ssl->buffers.certificate && ssl->buffers.certificate->buffer && + ssl->buffers.key && ssl->buffers.key->buffer) { +#ifndef WOLFSSL_TLS13_DRAFT_18 + if (PickHashSigAlgo(ssl, peerSuites.hashSigAlgo, + peerSuites.hashSigAlgoSz) != 0) { + return INVALID_PARAMETER; + } +#endif + ssl->options.sendVerify = SEND_CERT; + } + else + ssl->options.sendVerify = SEND_BLANK_CERT; + + /* This message is always encrypted so add encryption padding. */ + *inOutIdx += ssl->keys.padSz; + + WOLFSSL_LEAVE("DoTls13CertificateRequest", ret); + WOLFSSL_END(WC_FUNC_CERTIFICATE_REQUEST_DO); + + return ret; +} + +#endif /* !NO_WOLFSSL_CLIENT */ + +#ifndef NO_WOLFSSL_SERVER +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) +/* Refine list of supported cipher suites to those common to server and client. + * + * ssl SSL/TLS object. + * peerSuites The peer's advertised list of supported cipher suites. + */ +static void RefineSuites(WOLFSSL* ssl, Suites* peerSuites) +{ + byte suites[WOLFSSL_MAX_SUITE_SZ]; + int suiteSz = 0; + word16 i, j; + + XMEMSET(suites, 0, WOLFSSL_MAX_SUITE_SZ); + + for (i = 0; i < ssl->suites->suiteSz; i += 2) { + for (j = 0; j < peerSuites->suiteSz; j += 2) { + if (ssl->suites->suites[i+0] == peerSuites->suites[j+0] && + ssl->suites->suites[i+1] == peerSuites->suites[j+1]) { + suites[suiteSz++] = peerSuites->suites[j+0]; + suites[suiteSz++] = peerSuites->suites[j+1]; + } + } + } + + ssl->suites->suiteSz = suiteSz; + XMEMCPY(ssl->suites->suites, &suites, sizeof(suites)); +} + +/* Handle any Pre-Shared Key (PSK) extension. + * Must do this in ClientHello as it requires a hash of the truncated message. + * Don't know size of binders until Pre-Shared Key extension has been parsed. + * + * ssl The SSL/TLS object. + * input The ClientHello message. + * helloSz The size of the ClientHello message (including binders if present). + * usingPSK Indicates handshake is using Pre-Shared Keys. + * returns 0 on success and otherwise failure. + */ +static int DoPreSharedKeys(WOLFSSL* ssl, const byte* input, word32 helloSz, + int* usingPSK) +{ + int ret; + TLSX* ext; + word16 bindersLen; + PreSharedKey* current; + byte binderKey[WC_MAX_DIGEST_SIZE]; + byte binder[WC_MAX_DIGEST_SIZE]; + word32 binderLen; + word16 modes; + byte suite[2]; +#ifdef WOLFSSL_EARLY_DATA + int pskCnt = 0; + TLSX* extEarlyData; +#endif +#ifndef NO_PSK + const char* cipherName = NULL; + byte cipherSuite0 = TLS13_BYTE; + byte cipherSuite = WOLFSSL_DEF_PSK_CIPHER; +#endif + + WOLFSSL_ENTER("DoPreSharedKeys"); + + ext = TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY); + if (ext == NULL) + return 0; + + /* Extensions pushed on stack/list and PSK must be last. */ + if (ssl->extensions != ext) + return PSK_KEY_ERROR; + + /* Assume we are going to resume with a pre-shared key. */ + ssl->options.resuming = 1; + + /* Find the pre-shared key extension and calculate hash of truncated + * ClientHello for binders. + */ + ret = TLSX_PreSharedKey_GetSizeBinders((PreSharedKey*)ext->data, + client_hello, &bindersLen); + if (ret < 0) + return ret; + + /* Hash data up to binders for deriving binders in PSK extension. */ + ret = HashInput(ssl, input, helloSz - bindersLen); + if (ret != 0) + return ret; + + /* Look through all client's pre-shared keys for a match. */ + current = (PreSharedKey*)ext->data; + while (current != NULL) { + #ifdef WOLFSSL_EARLY_DATA + pskCnt++; + #endif + + #ifndef NO_PSK + if (current->identityLen > MAX_PSK_ID_LEN) { + return BUFFER_ERROR; + } + XMEMCPY(ssl->arrays->client_identity, current->identity, + current->identityLen); + ssl->arrays->client_identity[current->identityLen] = '\0'; + #endif + + #ifdef HAVE_SESSION_TICKET + /* Decode the identity. */ + if ((ret = DoClientTicket(ssl, current->identity, current->identityLen)) + == WOLFSSL_TICKET_RET_OK) { + word32 now; + int diff; + + now = TimeNowInMilliseconds(); + if (now == (word32)GETTIME_ERROR) + return now; + diff = now - ssl->session.ticketSeen; + diff -= current->ticketAge - ssl->session.ticketAdd; + /* Check session and ticket age timeout. + * Allow +/- 1000 milliseconds on ticket age. + */ + if (diff > (int)ssl->timeout * 1000 || diff < -1000 || + diff - MAX_TICKET_AGE_SECS * 1000 > 1000) { + /* Invalid difference, fallback to full handshake. */ + ssl->options.resuming = 0; + break; + } + + /* Check whether resumption is possible based on suites in SSL and + * ciphersuite in ticket. + */ + suite[0] = ssl->session.cipherSuite0; + suite[1] = ssl->session.cipherSuite; + if (!FindSuiteSSL(ssl, suite)) { + current = current->next; + continue; + } + + #ifdef WOLFSSL_EARLY_DATA + ssl->options.maxEarlyDataSz = ssl->session.maxEarlyDataSz; + #endif + /* Use the same cipher suite as before and set up for use. */ + ssl->options.cipherSuite0 = ssl->session.cipherSuite0; + ssl->options.cipherSuite = ssl->session.cipherSuite; + ret = SetCipherSpecs(ssl); + if (ret != 0) + return ret; + + /* Resumption PSK is resumption master secret. */ + ssl->arrays->psk_keySz = ssl->specs.hash_size; + #ifdef WOLFSSL_TLS13_DRAFT_18 + XMEMCPY(ssl->arrays->psk_key, ssl->session.masterSecret, + ssl->arrays->psk_keySz); + #else + if ((ret = DeriveResumptionPSK(ssl, ssl->session.ticketNonce.data, + ssl->session.ticketNonce.len, ssl->arrays->psk_key)) != 0) { + return ret; + } + #endif + + /* Derive the early secret using the PSK. */ + ret = DeriveEarlySecret(ssl); + if (ret != 0) + return ret; + /* Derive the binder key to use to with HMAC. */ + ret = DeriveBinderKeyResume(ssl, binderKey); + if (ret != 0) + return ret; + } + else + #endif + #ifndef NO_PSK + if ((ssl->options.server_psk_tls13_cb != NULL && + (ssl->arrays->psk_keySz = ssl->options.server_psk_tls13_cb(ssl, + ssl->arrays->client_identity, ssl->arrays->psk_key, + MAX_PSK_KEY_LEN, &cipherName)) != 0 && + GetCipherSuiteFromName(cipherName, &cipherSuite0, + &cipherSuite) == 0) || + (ssl->options.server_psk_cb != NULL && + (ssl->arrays->psk_keySz = ssl->options.server_psk_cb(ssl, + ssl->arrays->client_identity, ssl->arrays->psk_key, + MAX_PSK_KEY_LEN)) != 0)) { + if (ssl->arrays->psk_keySz > MAX_PSK_KEY_LEN) + return PSK_KEY_ERROR; + + /* Check whether PSK ciphersuite is in SSL. */ + suite[0] = cipherSuite0; + suite[1] = cipherSuite; + if (!FindSuiteSSL(ssl, suite)) { + current = current->next; + continue; + } + + /* Default to ciphersuite if cb doesn't specify. */ + ssl->options.resuming = 0; + + /* PSK age is always zero. */ + if (current->ticketAge != ssl->session.ticketAdd) + return PSK_KEY_ERROR; + + /* Set PSK ciphersuite into SSL. */ + ssl->options.cipherSuite0 = cipherSuite0; + ssl->options.cipherSuite = cipherSuite; + ret = SetCipherSpecs(ssl); + if (ret != 0) + return ret; + + /* Derive the early secret using the PSK. */ + ret = DeriveEarlySecret(ssl); + if (ret != 0) + return ret; + /* Derive the binder key to use to with HMAC. */ + ret = DeriveBinderKey(ssl, binderKey); + if (ret != 0) + return ret; + } + else + #endif + { + current = current->next; + continue; + } + + ssl->options.sendVerify = 0; + + /* Derive the Finished message secret. */ + ret = DeriveFinishedSecret(ssl, binderKey, + ssl->keys.client_write_MAC_secret); + if (ret != 0) + return ret; + + /* Derive the binder and compare with the one in the extension. */ + ret = BuildTls13HandshakeHmac(ssl, + ssl->keys.client_write_MAC_secret, binder, &binderLen); + if (ret != 0) + return ret; + if (binderLen != current->binderLen || + XMEMCMP(binder, current->binder, binderLen) != 0) { + return BAD_BINDER; + } + + /* This PSK works, no need to try any more. */ + current->chosen = 1; + ext->resp = 1; + break; + } + + if (current == NULL) { +#ifdef WOLFSSL_PSK_ID_PROTECTION + #ifndef NO_CERTS + if (ssl->buffers.certChainCnt != 0) + return 0; + #endif + return BAD_BINDER; +#else + return 0; +#endif + } + + /* Hash the rest of the ClientHello. */ + ret = HashInputRaw(ssl, input + helloSz - bindersLen, bindersLen); + if (ret != 0) + return ret; + +#ifdef WOLFSSL_EARLY_DATA + extEarlyData = TLSX_Find(ssl->extensions, TLSX_EARLY_DATA); + if (extEarlyData != NULL) { + if (ssl->earlyData != no_early_data && current == ext->data) { + extEarlyData->resp = 1; + + /* Derive early data decryption key. */ + ret = DeriveTls13Keys(ssl, early_data_key, DECRYPT_SIDE_ONLY, 1); + if (ret != 0) + return ret; + if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0) + return ret; + + ssl->earlyData = process_early_data; + } + else + extEarlyData->resp = 0; + } +#endif + + /* Get the PSK key exchange modes the client wants to negotiate. */ + ext = TLSX_Find(ssl->extensions, TLSX_PSK_KEY_EXCHANGE_MODES); + if (ext == NULL) + return MISSING_HANDSHAKE_DATA; + modes = ext->val; + + ext = TLSX_Find(ssl->extensions, TLSX_KEY_SHARE); + /* Use (EC)DHE for forward-security if possible. */ + if ((modes & (1 << PSK_DHE_KE)) != 0 && !ssl->options.noPskDheKe && + ext != NULL) { + /* Only use named group used in last session. */ + ssl->namedGroup = ssl->session.namedGroup; + + /* Pick key share and Generate a new key if not present. */ + ret = TLSX_KeyShare_Establish(ssl); + if (ret == KEY_SHARE_ERROR) { + ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST_COMPLETE; + ret = 0; + } + else if (ret < 0) + return ret; + + /* Send new public key to client. */ + ext->resp = 1; + } + else { + if ((modes & (1 << PSK_KE)) == 0) + return PSK_KEY_ERROR; + ssl->options.noPskDheKe = 1; + ssl->arrays->preMasterSz = 0; + } + + *usingPSK = 1; + + WOLFSSL_LEAVE("DoPreSharedKeys", ret); + + return ret; +} +#endif + +#if !defined(WOLFSSL_TLS13_DRAFT_18) && defined(WOLFSSL_SEND_HRR_COOKIE) +/* Check that the Cookie data's integrity. + * + * ssl SSL/TLS object. + * cookie The cookie data - hash and MAC. + * cookieSz The length of the cookie data in bytes. + * returns Length of the hash on success, otherwise failure. + */ +static int CheckCookie(WOLFSSL* ssl, byte* cookie, byte cookieSz) +{ + int ret; + byte mac[WC_MAX_DIGEST_SIZE]; + Hmac cookieHmac; + byte cookieType; + byte macSz; + +#if !defined(NO_SHA) && defined(NO_SHA256) + cookieType = SHA; + macSz = WC_SHA_DIGEST_SIZE; +#endif /* NO_SHA */ +#ifndef NO_SHA256 + cookieType = WC_SHA256; + macSz = WC_SHA256_DIGEST_SIZE; +#endif /* NO_SHA256 */ + + if (cookieSz < ssl->specs.hash_size + macSz) + return HRR_COOKIE_ERROR; + cookieSz -= macSz; + + ret = wc_HmacSetKey(&cookieHmac, cookieType, + ssl->buffers.tls13CookieSecret.buffer, + ssl->buffers.tls13CookieSecret.length); + if (ret != 0) + return ret; + if ((ret = wc_HmacUpdate(&cookieHmac, cookie, cookieSz)) != 0) + return ret; + if ((ret = wc_HmacFinal(&cookieHmac, mac)) != 0) + return ret; + + if (ConstantCompare(cookie + cookieSz, mac, macSz) != 0) + return HRR_COOKIE_ERROR; + return cookieSz; +} + +/* Length of the KeyShare Extension */ +#define HRR_KEY_SHARE_SZ (OPAQUE16_LEN + OPAQUE16_LEN + OPAQUE16_LEN) +/* Length of the Supported Vresions Extension */ +#define HRR_VERSIONS_SZ (OPAQUE16_LEN + OPAQUE16_LEN + OPAQUE16_LEN) +/* Length of the Cookie Extension excluding cookie data */ +#define HRR_COOKIE_HDR_SZ (OPAQUE16_LEN + OPAQUE16_LEN + OPAQUE16_LEN) +#ifdef WOLFSSL_TLS13_DRAFT_18 +/* PV | CipherSuite | Ext Len */ +#define HRR_BODY_SZ (OPAQUE16_LEN + OPAQUE16_LEN + OPAQUE16_LEN) +/* HH | PV | CipherSuite | Ext Len | Key Share | Cookie */ +#define MAX_HRR_SZ (HANDSHAKE_HEADER_SZ + \ + HRR_BODY_SZ + \ + HRR_KEY_SHARE_SZ + \ + HRR_COOKIE_HDR_SZ) +#else +/* PV | Random | Session Id | CipherSuite | Compression | Ext Len */ +#define HRR_BODY_SZ (VERSION_SZ + RAN_LEN + ENUM_LEN + ID_LEN + \ + SUITE_LEN + COMP_LEN + OPAQUE16_LEN) +/* HH | PV | CipherSuite | Ext Len | Key Share | Supported Version | Cookie */ +#define MAX_HRR_SZ (HANDSHAKE_HEADER_SZ + \ + HRR_BODY_SZ + \ + HRR_KEY_SHARE_SZ + \ + HRR_VERSIONS_SZ + \ + HRR_COOKIE_HDR_SZ) +#endif + +/* Restart the handshake hash from the cookie value. + * + * ssl SSL/TLS object. + * cookie Cookie data from client. + * returns 0 on success, otherwise failure. + */ +static int RestartHandshakeHashWithCookie(WOLFSSL* ssl, Cookie* cookie) +{ + byte header[HANDSHAKE_HEADER_SZ]; + byte hrr[MAX_HRR_SZ]; + int hrrIdx; + word32 idx; + byte hashSz; + byte* cookieData; + byte cookieDataSz; + word16 length; + int keyShareExt = 0; + int ret; + + cookieDataSz = ret = CheckCookie(ssl, &cookie->data, cookie->len); + if (ret < 0) + return ret; + hashSz = cookie->data; + cookieData = &cookie->data; + idx = OPAQUE8_LEN; + + /* Restart handshake hash with synthetic message hash. */ + AddTls13HandShakeHeader(header, hashSz, 0, 0, message_hash, ssl); + if ((ret = InitHandshakeHashes(ssl)) != 0) + return ret; + if ((ret = HashOutputRaw(ssl, header, sizeof(header))) != 0) + return ret; + if ((ret = HashOutputRaw(ssl, cookieData + idx, hashSz)) != 0) + return ret; + + /* Reconstruct the HelloRetryMessage for handshake hash. */ +#ifdef WOLFSSL_TLS13_DRAFT_18 + length = HRR_BODY_SZ + HRR_COOKIE_HDR_SZ + cookie->len; +#else + length = HRR_BODY_SZ - ID_LEN + ssl->session.sessionIDSz + + HRR_COOKIE_HDR_SZ + cookie->len; + length += HRR_VERSIONS_SZ; +#endif + if (cookieDataSz > hashSz + OPAQUE16_LEN) { + keyShareExt = 1; + length += HRR_KEY_SHARE_SZ; + } +#ifdef WOLFSSL_TLS13_DRAFT_18 + AddTls13HandShakeHeader(hrr, length, 0, 0, hello_retry_request, ssl); + + idx += hashSz; + hrrIdx = HANDSHAKE_HEADER_SZ; + /* The negotiated protocol version. */ + hrr[hrrIdx++] = TLS_DRAFT_MAJOR; + hrr[hrrIdx++] = TLS_DRAFT_MINOR; + /* Cipher Suite */ + hrr[hrrIdx++] = cookieData[idx++]; + hrr[hrrIdx++] = cookieData[idx++]; + + /* Extensions' length */ + length -= HRR_BODY_SZ; + c16toa(length, hrr + hrrIdx); + hrrIdx += 2; +#else + AddTls13HandShakeHeader(hrr, length, 0, 0, server_hello, ssl); + + idx += hashSz; + hrrIdx = HANDSHAKE_HEADER_SZ; + + /* The negotiated protocol version. */ + hrr[hrrIdx++] = ssl->version.major; + hrr[hrrIdx++] = TLSv1_2_MINOR; + + /* HelloRetryRequest message has fixed value for random. */ + XMEMCPY(hrr + hrrIdx, helloRetryRequestRandom, RAN_LEN); + hrrIdx += RAN_LEN; + + hrr[hrrIdx++] = ssl->session.sessionIDSz; + if (ssl->session.sessionIDSz > 0) { + XMEMCPY(hrr + hrrIdx, ssl->session.sessionID, ssl->session.sessionIDSz); + hrrIdx += ssl->session.sessionIDSz; + } + + /* Cipher Suite */ + hrr[hrrIdx++] = cookieData[idx++]; + hrr[hrrIdx++] = cookieData[idx++]; + + /* Compression not supported in TLS v1.3. */ + hrr[hrrIdx++] = 0; + + /* Extensions' length */ + length -= HRR_BODY_SZ - ID_LEN + ssl->session.sessionIDSz; + c16toa(length, hrr + hrrIdx); + hrrIdx += 2; + +#endif + /* Optional KeyShare Extension */ + if (keyShareExt) { + c16toa(TLSX_KEY_SHARE, hrr + hrrIdx); + hrrIdx += 2; + c16toa(OPAQUE16_LEN, hrr + hrrIdx); + hrrIdx += 2; + hrr[hrrIdx++] = cookieData[idx++]; + hrr[hrrIdx++] = cookieData[idx++]; + } +#ifndef WOLFSSL_TLS13_DRAFT_18 + c16toa(TLSX_SUPPORTED_VERSIONS, hrr + hrrIdx); + hrrIdx += 2; + c16toa(OPAQUE16_LEN, hrr + hrrIdx); + hrrIdx += 2; + #ifdef WOLFSSL_TLS13_DRAFT + hrr[hrrIdx++] = TLS_DRAFT_MAJOR; + hrr[hrrIdx++] = TLS_DRAFT_MINOR; + #else + hrr[hrrIdx++] = ssl->version.major; + hrr[hrrIdx++] = ssl->version.minor; + #endif +#endif + /* Mandatory Cookie Extension */ + c16toa(TLSX_COOKIE, hrr + hrrIdx); + hrrIdx += 2; + c16toa(cookie->len + OPAQUE16_LEN, hrr + hrrIdx); + hrrIdx += 2; + c16toa(cookie->len, hrr + hrrIdx); + hrrIdx += 2; + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Reconstucted HelloRetryRequest"); + WOLFSSL_BUFFER(hrr, hrrIdx); + WOLFSSL_MSG("Cookie"); + WOLFSSL_BUFFER(cookieData, cookie->len); +#endif + + if ((ret = HashOutputRaw(ssl, hrr, hrrIdx)) != 0) + return ret; + return HashOutputRaw(ssl, cookieData, cookie->len); +} +#endif + +/* Do SupportedVersion extension for TLS v1.3+ otherwise it is not. + * + * ssl The SSL/TLS object. + * input The message buffer. + * i The index into the message buffer of ClientHello. + * helloSz The length of the current handshake message. + * returns 0 on success and otherwise failure. + */ +static int DoTls13SupportedVersions(WOLFSSL* ssl, const byte* input, word32 i, + word32 helloSz, int* wantDowngrade) +{ + int ret; + byte b; + word16 suiteSz; + word16 totalExtSz; + int foundVersion = 0; + + /* Client random */ + i += RAN_LEN; + /* Session id - not used in TLS v1.3 */ + b = input[i++]; + if (i + b > helloSz) { + return BUFFER_ERROR; + } + i += b; + /* Cipher suites */ + if (i + OPAQUE16_LEN > helloSz) + return BUFFER_ERROR; + ato16(input + i, &suiteSz); + i += OPAQUE16_LEN; + i += suiteSz; + /* Compression */ + b = input[i++]; + if (i + b > helloSz) + return BUFFER_ERROR; + i += b; + + /* TLS 1.3 must have extensions */ + if (i < helloSz) { + if (i + OPAQUE16_LEN > helloSz) + return BUFFER_ERROR; + ato16(&input[i], &totalExtSz); + i += OPAQUE16_LEN; + if (i + totalExtSz != helloSz) + return BUFFER_ERROR; + + /* Need to negotiate version first. */ + if ((ret = TLSX_ParseVersion(ssl, (byte*)input + i, totalExtSz, + client_hello, &foundVersion))) { + return ret; + } + } + *wantDowngrade = !foundVersion || !IsAtLeastTLSv1_3(ssl->version); + + return 0; +} + +/* Handle a ClientHello handshake message. + * If the protocol version in the message is not TLS v1.3 or higher, use + * DoClientHello() + * Only a server will receive this message. + * + * ssl The SSL/TLS object. + * input The message buffer. + * inOutIdx On entry, the index into the message buffer of ClientHello. + * On exit, the index of byte after the ClientHello message and + * padding. + * helloSz The length of the current handshake message. + * returns 0 on success and otherwise failure. + */ +int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, + word32 helloSz) +{ + int ret = VERSION_ERROR; + byte b; + ProtocolVersion pv; + Suites clSuites; + word32 i = *inOutIdx; + word32 begin = i; + word16 totalExtSz = 0; + int usingPSK = 0; + byte sessIdSz; + int wantDowngrade = 0; + + WOLFSSL_START(WC_FUNC_CLIENT_HELLO_DO); + WOLFSSL_ENTER("DoTls13ClientHello"); + +#ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName(ssl, "ClientHello"); + if (ssl->toInfoOn) AddLateName("ClientHello", &ssl->timeoutInfo); +#endif + + /* protocol version, random and session id length check */ + if ((i - begin) + OPAQUE16_LEN + RAN_LEN + OPAQUE8_LEN > helloSz) + return BUFFER_ERROR; + + /* Protocol version */ + XMEMCPY(&pv, input + i, OPAQUE16_LEN); + ssl->chVersion = pv; /* store */ + i += OPAQUE16_LEN; + if (pv.major < SSLv3_MAJOR) { + WOLFSSL_MSG("Legacy version field contains unsupported value"); + #ifdef WOLFSSL_MYSQL_COMPATIBLE + SendAlert(ssl, alert_fatal, wc_protocol_version); + #else + SendAlert(ssl, alert_fatal, protocol_version); + #endif + return INVALID_PARAMETER; + } + /* Legacy protocol version cannot negotiate TLS 1.3 or higher. */ + if (pv.major > SSLv3_MAJOR || (pv.major == SSLv3_MAJOR && + pv.minor >= TLSv1_3_MINOR)) { + pv.minor = SSLv3_MAJOR; + pv.minor = TLSv1_2_MINOR; + wantDowngrade = 1; + } + /* Legacy version must be [ SSLv3_MAJOR, TLSv1_2_MINOR ] for TLS v1.3 */ + else if (pv.major == SSLv3_MAJOR && pv.minor < TLSv1_2_MINOR) + wantDowngrade = 1; + else { + ret = DoTls13SupportedVersions(ssl, input + begin, i - begin, helloSz, + &wantDowngrade); + if (ret < 0) + return ret; + } + if (wantDowngrade) { +#ifndef WOLFSSL_NO_TLS12 + if (!ssl->options.downgrade) { + WOLFSSL_MSG("Client trying to connect with lesser version than " + "TLS v1.3"); + return VERSION_ERROR; + } + + if (pv.minor < ssl->options.minDowngrade) + return VERSION_ERROR; + ssl->version.minor = pv.minor; + + if ((ret = HashInput(ssl, input + begin, helloSz)) != 0) + return ret; + return DoClientHello(ssl, input, inOutIdx, helloSz); +#else + WOLFSSL_MSG("Client trying to connect with lesser version than " + "TLS v1.3"); + return VERSION_ERROR; +#endif + } + + /* Client random */ + XMEMCPY(ssl->arrays->clientRandom, input + i, RAN_LEN); + i += RAN_LEN; + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("client random"); + WOLFSSL_BUFFER(ssl->arrays->clientRandom, RAN_LEN); +#endif + +#ifdef WOLFSSL_TLS13_DRAFT_18 + /* Session id - empty in TLS v1.3 */ + sessIdSz = input[i++]; + if (sessIdSz > 0 && !ssl->options.downgrade) { + WOLFSSL_MSG("Client sent session id - not supported"); + return BUFFER_ERROR; + } +#else + sessIdSz = input[i++]; + if (sessIdSz != ID_LEN && sessIdSz != 0) + return INVALID_PARAMETER; +#endif + + if (sessIdSz + i > helloSz) { + return BUFFER_ERROR; + } + + ssl->session.sessionIDSz = sessIdSz; + if (sessIdSz == ID_LEN) { + XMEMCPY(ssl->session.sessionID, input + i, sessIdSz); + i += ID_LEN; + } + + /* Cipher suites */ + if ((i - begin) + OPAQUE16_LEN > helloSz) + return BUFFER_ERROR; + ato16(&input[i], &clSuites.suiteSz); + i += OPAQUE16_LEN; + /* suites and compression length check */ + if ((i - begin) + clSuites.suiteSz + OPAQUE8_LEN > helloSz) + return BUFFER_ERROR; + if (clSuites.suiteSz > WOLFSSL_MAX_SUITE_SZ) + return BUFFER_ERROR; + XMEMCPY(clSuites.suites, input + i, clSuites.suiteSz); + i += clSuites.suiteSz; + clSuites.hashSigAlgoSz = 0; + +#ifdef HAVE_SERVER_RENEGOTIATION_INFO + ret = FindSuite(&clSuites, 0, TLS_EMPTY_RENEGOTIATION_INFO_SCSV); + if (ret == SUITES_ERROR) + return BUFFER_ERROR; + if (ret >= 0) { + TLSX* extension; + + /* check for TLS_EMPTY_RENEGOTIATION_INFO_SCSV suite */ + ret = TLSX_AddEmptyRenegotiationInfo(&ssl->extensions, ssl->heap); + if (ret != WOLFSSL_SUCCESS) + return ret; + + extension = TLSX_Find(ssl->extensions, TLSX_RENEGOTIATION_INFO); + if (extension) { + ssl->secure_renegotiation = (SecureRenegotiation*)extension->data; + ssl->secure_renegotiation->enabled = 1; + } + } +#endif /* HAVE_SERVER_RENEGOTIATION_INFO */ + + /* Compression */ + b = input[i++]; + if ((i - begin) + b > helloSz) + return BUFFER_ERROR; + if (b != COMP_LEN) { + WOLFSSL_MSG("Must be one compression type in list"); + return INVALID_PARAMETER; + } + b = input[i++]; + if (b != NO_COMPRESSION) { + WOLFSSL_MSG("Must be no compression type in list"); + return INVALID_PARAMETER; + } + + /* Extensions */ + if ((i - begin) == helloSz) + return BUFFER_ERROR; + if ((i - begin) + OPAQUE16_LEN > helloSz) + return BUFFER_ERROR; + + ato16(&input[i], &totalExtSz); + i += OPAQUE16_LEN; + if ((i - begin) + totalExtSz > helloSz) + return BUFFER_ERROR; + + /* Auto populate extensions supported unless user defined. */ + if ((ret = TLSX_PopulateExtensions(ssl, 1)) != 0) + return ret; + + /* Parse extensions */ + if ((ret = TLSX_Parse(ssl, (byte*)input + i, totalExtSz, client_hello, + &clSuites))) { + return ret; + } + +#if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || \ + defined(WOLFSSL_HAPROXY) + if ((ret = SNI_Callback(ssl)) != 0) + return ret; + ssl->options.side = WOLFSSL_SERVER_END; +#endif /* OPENSSL_ALL || HAVE_STUNNEL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */ + + i += totalExtSz; + *inOutIdx = i; + + ssl->options.sendVerify = SEND_CERT; + + ssl->options.clientState = CLIENT_HELLO_COMPLETE; + ssl->options.haveSessionId = 1; + +#if !defined(WOLFSSL_TLS13_DRAFT_18) && defined(WOLFSSL_SEND_HRR_COOKIE) + if (ssl->options.sendCookie && + ssl->options.serverState == SERVER_HELLO_RETRY_REQUEST_COMPLETE) { + TLSX* ext; + + if ((ext = TLSX_Find(ssl->extensions, TLSX_COOKIE)) == NULL) + return HRR_COOKIE_ERROR; + /* Ensure the cookie came from client and isn't the one in the + * response - HelloRetryRequest. + */ + if (ext->resp == 1) + return HRR_COOKIE_ERROR; + ret = RestartHandshakeHashWithCookie(ssl, (Cookie*)ext->data); + if (ret != 0) + return ret; + } +#endif + +#if (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)) && \ + defined(HAVE_TLS_EXTENSIONS) + if (TLSX_Find(ssl->extensions, TLSX_PRE_SHARED_KEY) != NULL) { + if (ssl->options.downgrade) { + if ((ret = InitHandshakeHashes(ssl)) != 0) + return ret; + } + + /* Refine list for PSK processing. */ + RefineSuites(ssl, &clSuites); + + /* Process the Pre-Shared Key extension if present. */ + ret = DoPreSharedKeys(ssl, input + begin, helloSz, &usingPSK); + if (ret != 0) + return ret; + } + else { +#ifdef WOLFSSL_EARLY_DATA + ssl->earlyData = no_early_data; +#endif + } +#endif + + if (!usingPSK) { + if (TLSX_Find(ssl->extensions, TLSX_KEY_SHARE) == NULL) { + WOLFSSL_MSG("Client did not send a KeyShare extension"); + SendAlert(ssl, alert_fatal, missing_extension); + return INCOMPLETE_DATA; + } + + if ((ret = MatchSuite(ssl, &clSuites)) < 0) { + WOLFSSL_MSG("Unsupported cipher suite, ClientHello"); + return ret; + } + + /* Check that the negotiated ciphersuite matches protocol version. */ + if (ssl->options.cipherSuite0 != TLS13_BYTE) { + WOLFSSL_MSG("Negotiated ciphersuite from lesser version than " + "TLS v1.3"); + return VERSION_ERROR; + } + +#ifdef HAVE_SESSION_TICKET + if (ssl->options.resuming) { + ssl->options.resuming = 0; + XMEMSET(ssl->arrays->psk_key, 0, ssl->specs.hash_size); + /* May or may not have done any hashing. */ + if ((ret = InitHandshakeHashes(ssl)) != 0) + return ret; + } +#endif + + if ((ret = HashInput(ssl, input + begin, helloSz)) != 0) + return ret; + + /* Derive early secret for handshake secret. */ + if ((ret = DeriveEarlySecret(ssl)) != 0) + return ret; + } + + WOLFSSL_LEAVE("DoTls13ClientHello", ret); + WOLFSSL_END(WC_FUNC_CLIENT_HELLO_DO); + + return ret; +} + +#ifdef WOLFSSL_TLS13_DRAFT_18 +/* handle generation of TLS 1.3 hello_retry_request (6) */ +/* Send the HelloRetryRequest message to indicate the negotiated protocol + * version and security parameters the server is willing to use. + * Only a server will send this message. + * + * ssl The SSL/TLS object. + * returns 0 on success, otherwise failure. + */ +int SendTls13HelloRetryRequest(WOLFSSL* ssl) +{ + int ret; + byte* output; + word32 length; + word16 len; + word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + int sendSz; + + WOLFSSL_ENTER("SendTls13HelloRetryRequest"); + + /* Get the length of the extensions that will be written. */ + len = 0; + ret = TLSX_GetResponseSize(ssl, hello_retry_request, &len); + /* There must be extensions sent to indicate what client needs to do. */ + if (ret != 0) + return MISSING_HANDSHAKE_DATA; + + /* Protocol version + Extensions */ + length = OPAQUE16_LEN + len; + sendSz = idx + length; + + /* Check buffers are big enough and grow if needed. */ + if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) + return ret; + + /* Get position in output buffer to write new message to. */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + /* Add record and handshake headers. */ + AddTls13Headers(output, length, hello_retry_request, ssl); + + /* The negotiated protocol version. */ + output[idx++] = TLS_DRAFT_MAJOR; + output[idx++] = TLS_DRAFT_MINOR; + + /* Add TLS extensions. */ + ret = TLSX_WriteResponse(ssl, output + idx, hello_retry_request, NULL); + if (ret != 0) + return ret; + idx += len; + +#ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName(ssl, "HelloRetryRequest"); + if (ssl->toInfoOn) { + AddPacketInfo(ssl, "HelloRetryRequest", handshake, output, sendSz, + WRITE_PROTO, ssl->heap); + } +#endif + if ((ret = HashOutput(ssl, output, idx, 0)) != 0) + return ret; + + ssl->buffers.outputBuffer.length += sendSz; + + if (!ssl->options.groupMessages) + ret = SendBuffered(ssl); + + WOLFSSL_LEAVE("SendTls13HelloRetryRequest", ret); + + return ret; +} +#endif /* WOLFSSL_TLS13_DRAFT_18 */ + +/* Send TLS v1.3 ServerHello message to client. + * Only a server will send this message. + * + * ssl The SSL/TLS object. + * returns 0 on success, otherwise failure. + */ +#ifdef WOLFSSL_TLS13_DRAFT_18 +static +#endif +/* handle generation of TLS 1.3 server_hello (2) */ +int SendTls13ServerHello(WOLFSSL* ssl, byte extMsgType) +{ + int ret; + byte* output; + word16 length; + word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + int sendSz; + + WOLFSSL_START(WC_FUNC_SERVER_HELLO_SEND); + WOLFSSL_ENTER("SendTls13ServerHello"); + +#ifndef WOLFSSL_TLS13_DRAFT_18 + if (extMsgType == hello_retry_request) { + WOLFSSL_MSG("wolfSSL Doing HelloRetryRequest"); + if ((ret = RestartHandshakeHash(ssl)) < 0) + return ret; + } +#endif + +#ifdef WOLFSSL_TLS13_DRAFT_18 + /* Protocol version, server random, cipher suite and extensions. */ + length = VERSION_SZ + RAN_LEN + SUITE_LEN; + ret = TLSX_GetResponseSize(ssl, server_hello, &length); + if (ret != 0) + return ret; +#else + /* Protocol version, server random, session id, cipher suite, compression + * and extensions. + */ + length = VERSION_SZ + RAN_LEN + ENUM_LEN + ssl->session.sessionIDSz + + SUITE_LEN + COMP_LEN; + ret = TLSX_GetResponseSize(ssl, extMsgType, &length); + if (ret != 0) + return ret; +#endif + sendSz = idx + length; + + /* Check buffers are big enough and grow if needed. */ + if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) + return ret; + + /* Get position in output buffer to write new message to. */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + /* Put the record and handshake headers on. */ + AddTls13Headers(output, length, server_hello, ssl); + +#ifdef WOLFSSL_TLS13_DRAFT_18 + /* The negotiated protocol version. */ + output[idx++] = TLS_DRAFT_MAJOR; + output[idx++] = TLS_DRAFT_MINOR; +#else + /* The protocol version must be TLS v1.2 for middleboxes. */ + output[idx++] = ssl->version.major; + output[idx++] = TLSv1_2_MINOR; +#endif + + if (extMsgType == server_hello) { + /* Generate server random. */ + if ((ret = wc_RNG_GenerateBlock(ssl->rng, output + idx, RAN_LEN)) != 0) + return ret; + } +#ifndef WOLFSSL_TLS13_DRAFT_18 + else { + /* HelloRetryRequest message has fixed value for random. */ + XMEMCPY(output + idx, helloRetryRequestRandom, RAN_LEN); + } +#endif + /* Store in SSL for debugging. */ + XMEMCPY(ssl->arrays->serverRandom, output + idx, RAN_LEN); + idx += RAN_LEN; + +#ifdef WOLFSSL_DEBUG_TLS + WOLFSSL_MSG("Server random"); + WOLFSSL_BUFFER(ssl->arrays->serverRandom, RAN_LEN); +#endif + +#ifndef WOLFSSL_TLS13_DRAFT_18 + output[idx++] = ssl->session.sessionIDSz; + if (ssl->session.sessionIDSz > 0) { + XMEMCPY(output + idx, ssl->session.sessionID, ssl->session.sessionIDSz); + idx += ssl->session.sessionIDSz; + } +#endif + + /* Chosen cipher suite */ + output[idx++] = ssl->options.cipherSuite0; + output[idx++] = ssl->options.cipherSuite; + +#ifndef WOLFSSL_TLS13_DRAFT_18 + /* Compression not supported in TLS v1.3. */ + output[idx++] = 0; +#endif + + /* Extensions */ + ret = TLSX_WriteResponse(ssl, output + idx, extMsgType, NULL); + if (ret != 0) + return ret; + + ssl->buffers.outputBuffer.length += sendSz; + + if ((ret = HashOutput(ssl, output, sendSz, 0)) != 0) + return ret; + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName(ssl, "ServerHello"); + if (ssl->toInfoOn) { + AddPacketInfo(ssl, "ServerHello", handshake, output, sendSz, + WRITE_PROTO, ssl->heap); + } + #endif + +#ifdef WOLFSSL_TLS13_DRAFT_18 + ssl->options.serverState = SERVER_HELLO_COMPLETE; +#else + if (extMsgType == server_hello) + ssl->options.serverState = SERVER_HELLO_COMPLETE; +#endif + +#ifdef WOLFSSL_TLS13_DRAFT_18 + if (!ssl->options.groupMessages) +#else + if (!ssl->options.groupMessages || extMsgType != server_hello) +#endif + ret = SendBuffered(ssl); + + WOLFSSL_LEAVE("SendTls13ServerHello", ret); + WOLFSSL_END(WC_FUNC_SERVER_HELLO_SEND); + + return ret; +} + +/* handle generation of TLS 1.3 encrypted_extensions (8) */ +/* Send the rest of the extensions encrypted under the handshake key. + * This message is always encrypted in TLS v1.3. + * Only a server will send this message. + * + * ssl The SSL/TLS object. + * returns 0 on success, otherwise failure. + */ +static int SendTls13EncryptedExtensions(WOLFSSL* ssl) +{ + int ret; + byte* output; + word16 length = 0; + word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + int sendSz; + + WOLFSSL_START(WC_FUNC_ENCRYPTED_EXTENSIONS_SEND); + WOLFSSL_ENTER("SendTls13EncryptedExtensions"); + + ssl->keys.encryptionOn = 1; + +#ifndef WOLFSSL_NO_SERVER_GROUPS_EXT + if ((ret = TLSX_SupportedCurve_CheckPriority(ssl)) != 0) + return ret; +#endif + + /* Derive the handshake secret now that we are at first message to be + * encrypted under the keys. + */ + if ((ret = DeriveHandshakeSecret(ssl)) != 0) + return ret; + if ((ret = DeriveTls13Keys(ssl, handshake_key, + ENCRYPT_AND_DECRYPT_SIDE, 1)) != 0) + return ret; + + /* Setup encrypt/decrypt keys for following messages. */ +#ifdef WOLFSSL_EARLY_DATA + if ((ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY)) != 0) + return ret; + if (ssl->earlyData != process_early_data) { + if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0) + return ret; + } +#else + if ((ret = SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE)) != 0) + return ret; +#endif + + ret = TLSX_GetResponseSize(ssl, encrypted_extensions, &length); + if (ret != 0) + return ret; + + sendSz = idx + length; + /* Encryption always on. */ + sendSz += MAX_MSG_EXTRA; + + /* Check buffers are big enough and grow if needed. */ + ret = CheckAvailableSize(ssl, sendSz); + if (ret != 0) + return ret; + + /* Get position in output buffer to write new message to. */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + /* Put the record and handshake headers on. */ + AddTls13Headers(output, length, encrypted_extensions, ssl); + + ret = TLSX_WriteResponse(ssl, output + idx, encrypted_extensions, NULL); + if (ret != 0) + return ret; + idx += length; + +#ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName(ssl, "EncryptedExtensions"); + if (ssl->toInfoOn) { + AddPacketInfo(ssl, "EncryptedExtensions", handshake, output, + sendSz, WRITE_PROTO, ssl->heap); + } +#endif + + /* This handshake message is always encrypted. */ + sendSz = BuildTls13Message(ssl, output, sendSz, output + RECORD_HEADER_SZ, + idx - RECORD_HEADER_SZ, handshake, 1, 0, 0); + if (sendSz < 0) + return sendSz; + + ssl->buffers.outputBuffer.length += sendSz; + + ssl->options.serverState = SERVER_ENCRYPTED_EXTENSIONS_COMPLETE; + + if (!ssl->options.groupMessages) + ret = SendBuffered(ssl); + + WOLFSSL_LEAVE("SendTls13EncryptedExtensions", ret); + WOLFSSL_END(WC_FUNC_ENCRYPTED_EXTENSIONS_SEND); + + return ret; +} + +#ifndef NO_CERTS +/* handle generation TLS v1.3 certificate_request (13) */ +/* Send the TLS v1.3 CertificateRequest message. + * This message is always encrypted in TLS v1.3. + * Only a server will send this message. + * + * ssl SSL/TLS object. + * reqCtx Request context. + * reqCtxLen Length of context. 0 when sending as part of handshake. + * returns 0 on success, otherwise failure. + */ +static int SendTls13CertificateRequest(WOLFSSL* ssl, byte* reqCtx, + int reqCtxLen) +{ + byte* output; + int ret; + int sendSz; + word32 i; + word16 reqSz; +#ifndef WOLFSSL_TLS13_DRAFT_18 + TLSX* ext; +#endif + + WOLFSSL_START(WC_FUNC_CERTIFICATE_REQUEST_SEND); + WOLFSSL_ENTER("SendTls13CertificateRequest"); + + if (ssl->options.side == WOLFSSL_SERVER_END) + InitSuitesHashSigAlgo(ssl->suites, 1, 1, 0, 1, ssl->buffers.keySz); + +#ifdef WOLFSSL_TLS13_DRAFT_18 + i = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + reqSz = OPAQUE8_LEN + reqCtxLen + REQ_HEADER_SZ + REQ_HEADER_SZ; + reqSz += LENGTH_SZ + ssl->suites->hashSigAlgoSz; + + sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + reqSz; + /* Always encrypted and make room for padding. */ + sendSz += MAX_MSG_EXTRA; + + /* Check buffers are big enough and grow if needed. */ + if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) + return ret; + + /* Get position in output buffer to write new message to. */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + /* Put the record and handshake headers on. */ + AddTls13Headers(output, reqSz, certificate_request, ssl); + + /* Certificate request context. */ + output[i++] = reqCtxLen; + if (reqCtxLen != 0) { + XMEMCPY(output + i, reqCtx, reqCtxLen); + i += reqCtxLen; + } + + /* supported hash/sig */ + c16toa(ssl->suites->hashSigAlgoSz, &output[i]); + i += LENGTH_SZ; + + XMEMCPY(&output[i], ssl->suites->hashSigAlgo, ssl->suites->hashSigAlgoSz); + i += ssl->suites->hashSigAlgoSz; + + /* Certificate authorities not supported yet - empty buffer. */ + c16toa(0, &output[i]); + i += REQ_HEADER_SZ; + + /* Certificate extensions. */ + c16toa(0, &output[i]); /* auth's */ + i += REQ_HEADER_SZ; +#else + ext = TLSX_Find(ssl->extensions, TLSX_SIGNATURE_ALGORITHMS); + if (ext == NULL) + return EXT_MISSING; + ext->resp = 0; + + i = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + reqSz = (word16)(OPAQUE8_LEN + reqCtxLen); + ret = TLSX_GetRequestSize(ssl, certificate_request, &reqSz); + if (ret != 0) + return ret; + + sendSz = i + reqSz; + /* Always encrypted and make room for padding. */ + sendSz += MAX_MSG_EXTRA; + + /* Check buffers are big enough and grow if needed. */ + if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) + return ret; + + /* Get position in output buffer to write new message to. */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + /* Put the record and handshake headers on. */ + AddTls13Headers(output, reqSz, certificate_request, ssl); + + /* Certificate request context. */ + output[i++] = (byte)reqCtxLen; + if (reqCtxLen != 0) { + XMEMCPY(output + i, reqCtx, reqCtxLen); + i += reqCtxLen; + } + + /* Certificate extensions. */ + reqSz = 0; + ret = TLSX_WriteRequest(ssl, output + i, certificate_request, &reqSz); + if (ret != 0) + return ret; + i += reqSz; +#endif + + /* Always encrypted. */ + sendSz = BuildTls13Message(ssl, output, sendSz, output + RECORD_HEADER_SZ, + i - RECORD_HEADER_SZ, handshake, 1, 0, 0); + if (sendSz < 0) + return sendSz; + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName(ssl, "CertificateRequest"); + if (ssl->toInfoOn) { + AddPacketInfo(ssl, "CertificateRequest", handshake, output, + sendSz, WRITE_PROTO, ssl->heap); + } + #endif + + ssl->buffers.outputBuffer.length += sendSz; + if (!ssl->options.groupMessages) + ret = SendBuffered(ssl); + + WOLFSSL_LEAVE("SendTls13CertificateRequest", ret); + WOLFSSL_END(WC_FUNC_CERTIFICATE_REQUEST_SEND); + + return ret; +} +#endif /* NO_CERTS */ +#endif /* NO_WOLFSSL_SERVER */ + +#ifndef NO_CERTS +#if !defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519) +/* Encode the signature algorithm into buffer. + * + * hashalgo The hash algorithm. + * hsType The signature type. + * output The buffer to encode into. + */ +static WC_INLINE void EncodeSigAlg(byte hashAlgo, byte hsType, byte* output) +{ + switch (hsType) { +#ifdef HAVE_ECC + case ecc_dsa_sa_algo: + output[0] = hashAlgo; + output[1] = ecc_dsa_sa_algo; + break; +#endif +#ifdef HAVE_ED25519 + /* ED25519: 0x0807 */ + case ed25519_sa_algo: + output[0] = ED25519_SA_MAJOR; + output[1] = ED25519_SA_MINOR; + (void)hashAlgo; + break; +#endif +#ifndef NO_RSA + /* PSS signatures: 0x080[4-6] */ + case rsa_pss_sa_algo: + output[0] = rsa_pss_sa_algo; + output[1] = hashAlgo; + break; +#endif + /* ED448: 0x0808 */ + } +} + +/* Decode the signature algorithm. + * + * input The encoded signature algorithm. + * hashalgo The hash algorithm. + * hsType The signature type. + * returns INVALID_PARAMETER if not recognized and 0 otherwise. + */ +static WC_INLINE int DecodeTls13SigAlg(byte* input, byte* hashAlgo, + byte* hsType) +{ + int ret = 0; + + switch (input[0]) { + case NEW_SA_MAJOR: + /* PSS signatures: 0x080[4-6] */ + if (input[1] >= sha256_mac && input[1] <= sha512_mac) { + *hsType = input[0]; + *hashAlgo = input[1]; + } + #ifdef HAVE_ED25519 + /* ED25519: 0x0807 */ + else if (input[1] == ED25519_SA_MINOR) { + *hsType = ed25519_sa_algo; + /* Hash performed as part of sign/verify operation. */ + *hashAlgo = sha512_mac; + } + #endif + else + ret = INVALID_PARAMETER; + /* ED448: 0x0808 */ + break; + default: + *hashAlgo = input[0]; + *hsType = input[1]; + break; + } + + return ret; +} + +/* Get the hash of the messages so far. + * + * ssl The SSL/TLS object. + * hash The buffer to write the hash to. + * returns the length of the hash. + */ +static WC_INLINE int GetMsgHash(WOLFSSL* ssl, byte* hash) +{ + int ret = 0; + switch (ssl->specs.mac_algorithm) { + #ifndef NO_SHA256 + case sha256_mac: + ret = wc_Sha256GetHash(&ssl->hsHashes->hashSha256, hash); + if (ret == 0) + ret = WC_SHA256_DIGEST_SIZE; + break; + #endif /* !NO_SHA256 */ + #ifdef WOLFSSL_SHA384 + case sha384_mac: + ret = wc_Sha384GetHash(&ssl->hsHashes->hashSha384, hash); + if (ret == 0) + ret = WC_SHA384_DIGEST_SIZE; + break; + #endif /* WOLFSSL_SHA384 */ + #ifdef WOLFSSL_TLS13_SHA512 + case sha512_mac: + ret = wc_Sha512GetHash(&ssl->hsHashes->hashSha512, hash); + if (ret == 0) + ret = WC_SHA512_DIGEST_SIZE; + break; + #endif /* WOLFSSL_TLS13_SHA512 */ + } + return ret; +} + +/* The length of the certificate verification label - client and server. */ +#define CERT_VFY_LABEL_SZ 34 +/* The server certificate verification label. */ +static const byte serverCertVfyLabel[CERT_VFY_LABEL_SZ] = + "TLS 1.3, server CertificateVerify"; +/* The client certificate verification label. */ +static const byte clientCertVfyLabel[CERT_VFY_LABEL_SZ] = + "TLS 1.3, client CertificateVerify"; + +/* The number of prefix bytes for signature data. */ +#define SIGNING_DATA_PREFIX_SZ 64 +/* The prefix byte in the signature data. */ +#define SIGNING_DATA_PREFIX_BYTE 0x20 +/* Maximum length of the signature data. */ +#define MAX_SIG_DATA_SZ (SIGNING_DATA_PREFIX_SZ + \ + CERT_VFY_LABEL_SZ + \ + WC_MAX_DIGEST_SIZE) + +/* Create the signature data for TLS v1.3 certificate verification. + * + * ssl The SSL/TLS object. + * sigData The signature data. + * sigDataSz The length of the signature data. + * check Indicates this is a check not create. + */ +static int CreateSigData(WOLFSSL* ssl, byte* sigData, word16* sigDataSz, + int check) +{ + word16 idx; + int side = ssl->options.side; + int ret; + + /* Signature Data = Prefix | Label | Handshake Hash */ + XMEMSET(sigData, SIGNING_DATA_PREFIX_BYTE, SIGNING_DATA_PREFIX_SZ); + idx = SIGNING_DATA_PREFIX_SZ; + + if ((side == WOLFSSL_SERVER_END && check) || + (side == WOLFSSL_CLIENT_END && !check)) { + XMEMCPY(&sigData[idx], clientCertVfyLabel, CERT_VFY_LABEL_SZ); + } + if ((side == WOLFSSL_CLIENT_END && check) || + (side == WOLFSSL_SERVER_END && !check)) { + XMEMCPY(&sigData[idx], serverCertVfyLabel, CERT_VFY_LABEL_SZ); + } + idx += CERT_VFY_LABEL_SZ; + + ret = GetMsgHash(ssl, &sigData[idx]); + if (ret < 0) + return ret; + + *sigDataSz = (word16)(idx + ret); + ret = 0; + + return ret; +} + +#ifndef NO_RSA +/* Encode the PKCS #1.5 RSA signature. + * + * sig The buffer to place the encoded signature into. + * sigData The data to be signed. + * sigDataSz The size of the data to be signed. + * hashAlgo The hash algorithm to use when signing. + * returns the length of the encoded signature or negative on error. + */ +static int CreateRSAEncodedSig(byte* sig, byte* sigData, int sigDataSz, + int sigAlgo, int hashAlgo) +{ + Digest digest; + int hashSz = 0; + int ret = BAD_FUNC_ARG; + byte* hash; + + (void)sigAlgo; + + hash = sig; + + /* Digest the signature data. */ + switch (hashAlgo) { +#ifndef NO_WOLFSSL_SHA256 + case sha256_mac: + ret = wc_InitSha256(&digest.sha256); + if (ret == 0) { + ret = wc_Sha256Update(&digest.sha256, sigData, sigDataSz); + if (ret == 0) + ret = wc_Sha256Final(&digest.sha256, hash); + wc_Sha256Free(&digest.sha256); + } + hashSz = WC_SHA256_DIGEST_SIZE; + break; +#endif +#ifdef WOLFSSL_SHA384 + case sha384_mac: + ret = wc_InitSha384(&digest.sha384); + if (ret == 0) { + ret = wc_Sha384Update(&digest.sha384, sigData, sigDataSz); + if (ret == 0) + ret = wc_Sha384Final(&digest.sha384, hash); + wc_Sha384Free(&digest.sha384); + } + hashSz = WC_SHA384_DIGEST_SIZE; + break; +#endif +#ifdef WOLFSSL_SHA512 + case sha512_mac: + ret = wc_InitSha512(&digest.sha512); + if (ret == 0) { + ret = wc_Sha512Update(&digest.sha512, sigData, sigDataSz); + if (ret == 0) + ret = wc_Sha512Final(&digest.sha512, hash); + wc_Sha512Free(&digest.sha512); + } + hashSz = WC_SHA512_DIGEST_SIZE; + break; +#endif + } + + if (ret != 0) + return ret; + + return hashSz; +} +#endif /* !NO_RSA */ + +#ifdef HAVE_ECC +/* Encode the ECC signature. + * + * sigData The data to be signed. + * sigDataSz The size of the data to be signed. + * hashAlgo The hash algorithm to use when signing. + * returns the length of the encoded signature or negative on error. + */ +static int CreateECCEncodedSig(byte* sigData, int sigDataSz, int hashAlgo) +{ + Digest digest; + int hashSz = 0; + int ret = BAD_FUNC_ARG; + + /* Digest the signature data. */ + switch (hashAlgo) { +#ifndef NO_WOLFSSL_SHA256 + case sha256_mac: + ret = wc_InitSha256(&digest.sha256); + if (ret == 0) { + ret = wc_Sha256Update(&digest.sha256, sigData, sigDataSz); + if (ret == 0) + ret = wc_Sha256Final(&digest.sha256, sigData); + wc_Sha256Free(&digest.sha256); + } + hashSz = WC_SHA256_DIGEST_SIZE; + break; +#endif +#ifdef WOLFSSL_SHA384 + case sha384_mac: + ret = wc_InitSha384(&digest.sha384); + if (ret == 0) { + ret = wc_Sha384Update(&digest.sha384, sigData, sigDataSz); + if (ret == 0) + ret = wc_Sha384Final(&digest.sha384, sigData); + wc_Sha384Free(&digest.sha384); + } + hashSz = WC_SHA384_DIGEST_SIZE; + break; +#endif +#ifdef WOLFSSL_SHA512 + case sha512_mac: + ret = wc_InitSha512(&digest.sha512); + if (ret == 0) { + ret = wc_Sha512Update(&digest.sha512, sigData, sigDataSz); + if (ret == 0) + ret = wc_Sha512Final(&digest.sha512, sigData); + wc_Sha512Free(&digest.sha512); + } + hashSz = WC_SHA512_DIGEST_SIZE; + break; +#endif + } + + if (ret != 0) + return ret; + + return hashSz; +} +#endif /* HAVE_ECC */ + +#ifndef NO_RSA +/* Check that the decrypted signature matches the encoded signature + * based on the digest of the signature data. + * + * ssl The SSL/TLS object. + * sigAlgo The signature algorithm used to generate signature. + * hashAlgo The hash algorithm used to generate signature. + * decSig The decrypted signature. + * decSigSz The size of the decrypted signature. + * returns 0 on success, otherwise failure. + */ +static int CheckRSASignature(WOLFSSL* ssl, int sigAlgo, int hashAlgo, + byte* decSig, word32 decSigSz) +{ + int ret = 0; + byte sigData[MAX_SIG_DATA_SZ]; + word16 sigDataSz; + word32 sigSz; + + ret = CreateSigData(ssl, sigData, &sigDataSz, 1); + if (ret != 0) + return ret; + + if (sigAlgo == rsa_pss_sa_algo) { + enum wc_HashType hashType = WC_HASH_TYPE_NONE; + + ret = ConvertHashPss(hashAlgo, &hashType, NULL); + if (ret < 0) + return ret; + + /* PSS signature can be done in-place */ + ret = CreateRSAEncodedSig(sigData, sigData, sigDataSz, + sigAlgo, hashAlgo); + if (ret < 0) + return ret; + sigSz = ret; + + ret = wc_RsaPSS_CheckPadding(sigData, sigSz, decSig, decSigSz, + hashType); + } + + return ret; +} +#endif /* !NO_RSA */ +#endif /* !NO_RSA || HAVE_ECC */ + +/* Get the next certificate from the list for writing into the TLS v1.3 + * Certificate message. + * + * data The certificate list. + * length The length of the certificate data in the list. + * idx The index of the next certificate. + * returns the length of the certificate data. 0 indicates no more certificates + * in the list. + */ +static word32 NextCert(byte* data, word32 length, word32* idx) +{ + word32 len; + + /* Is index at end of list. */ + if (*idx == length) + return 0; + + /* Length of the current ASN.1 encoded certificate. */ + c24to32(data + *idx, &len); + /* Include the length field. */ + len += 3; + + /* Move index to next certificate and return the current certificate's + * length. + */ + *idx += len; + return len; +} + +/* Add certificate data and empty extension to output up to the fragment size. + * + * ssl SSL/TLS object. + * cert The certificate data to write out. + * len The length of the certificate data. + * extSz Length of the extension data with the certificate. + * idx The start of the certificate data to write out. + * fragSz The maximum size of this fragment. + * output The buffer to write to. + * returns the number of bytes written. + */ +static word32 AddCertExt(WOLFSSL* ssl, byte* cert, word32 len, word16 extSz, + word32 idx, word32 fragSz, byte* output) +{ + word32 i = 0; + word32 copySz = min(len - idx, fragSz); + + if (idx < len) { + XMEMCPY(output, cert + idx, copySz); + i = copySz; + if (copySz == fragSz) + return i; + } + copySz = len + extSz - idx - i; + + if (extSz == OPAQUE16_LEN) { + if (copySz <= fragSz) { + /* Empty extension */ + output[i++] = 0; + output[i++] = 0; + } + } + else { + byte* certExts = ssl->buffers.certExts->buffer + idx + i - len; + /* Put out as much of the extensions' data as will fit in fragment. */ + if (copySz > fragSz - i) + copySz = fragSz - i; + XMEMCPY(output + i, certExts, copySz); + i += copySz; + } + + return i; +} + +/* handle generation TLS v1.3 certificate (11) */ +/* Send the certificate for this end and any CAs that help with validation. + * This message is always encrypted in TLS v1.3. + * + * ssl The SSL/TLS object. + * returns 0 on success, otherwise failure. + */ +static int SendTls13Certificate(WOLFSSL* ssl) +{ + int ret = 0; + word32 certSz, certChainSz, headerSz, listSz, payloadSz; + word16 extSz = 0; + word32 length, maxFragment; + word32 len = 0; + word32 idx = 0; + word32 offset = OPAQUE16_LEN; + byte* p = NULL; + byte certReqCtxLen = 0; + byte* certReqCtx = NULL; + + WOLFSSL_START(WC_FUNC_CERTIFICATE_SEND); + WOLFSSL_ENTER("SendTls13Certificate"); + +#ifdef WOLFSSL_POST_HANDSHAKE_AUTH + if (ssl->options.side == WOLFSSL_CLIENT_END && ssl->certReqCtx != NULL) { + certReqCtxLen = ssl->certReqCtx->len; + certReqCtx = &ssl->certReqCtx->ctx; + } +#endif + + if (ssl->options.sendVerify == SEND_BLANK_CERT) { + certSz = 0; + certChainSz = 0; + headerSz = OPAQUE8_LEN + certReqCtxLen + CERT_HEADER_SZ; + length = headerSz; + listSz = 0; + } + else { + if (!ssl->buffers.certificate) { + WOLFSSL_MSG("Send Cert missing certificate buffer"); + return BUFFER_ERROR; + } + /* Certificate Data */ + certSz = ssl->buffers.certificate->length; + /* Cert Req Ctx Len | Cert Req Ctx | Cert List Len | Cert Data Len */ + headerSz = OPAQUE8_LEN + certReqCtxLen + CERT_HEADER_SZ + + CERT_HEADER_SZ; + + ret = TLSX_GetResponseSize(ssl, certificate, &extSz); + if (ret < 0) + return ret; + + /* Create extensions' data if none already present. */ + if (extSz > OPAQUE16_LEN && ssl->buffers.certExts == NULL) { + ret = AllocDer(&ssl->buffers.certExts, extSz, CERT_TYPE, ssl->heap); + if (ret < 0) + return ret; + + extSz = 0; + ret = TLSX_WriteResponse(ssl, ssl->buffers.certExts->buffer, + certificate, &extSz); + if (ret < 0) + return ret; + } + + /* Length of message data with one certificate and extensions. */ + length = headerSz + certSz + extSz; + /* Length of list data with one certificate and extensions. */ + listSz = CERT_HEADER_SZ + certSz + extSz; + + /* Send rest of chain if sending cert (chain has leading size/s). */ + if (certSz > 0 && ssl->buffers.certChainCnt > 0) { + p = ssl->buffers.certChain->buffer; + /* Chain length including extensions. */ + certChainSz = ssl->buffers.certChain->length + + OPAQUE16_LEN * ssl->buffers.certChainCnt; + length += certChainSz; + listSz += certChainSz; + } + else + certChainSz = 0; + } + + payloadSz = length; + + if (ssl->fragOffset != 0) + length -= (ssl->fragOffset + headerSz); + + maxFragment = wolfSSL_GetMaxRecordSize(ssl, MAX_RECORD_SIZE); + + while (length > 0 && ret == 0) { + byte* output = NULL; + word32 fragSz = 0; + word32 i = RECORD_HEADER_SZ; + int sendSz = RECORD_HEADER_SZ; + + if (ssl->fragOffset == 0) { + if (headerSz + certSz + extSz + certChainSz <= + maxFragment - HANDSHAKE_HEADER_SZ) { + fragSz = headerSz + certSz + extSz + certChainSz; + } + else + fragSz = maxFragment - HANDSHAKE_HEADER_SZ; + + sendSz += fragSz + HANDSHAKE_HEADER_SZ; + i += HANDSHAKE_HEADER_SZ; + } + else { + fragSz = min(length, maxFragment); + sendSz += fragSz; + } + + sendSz += MAX_MSG_EXTRA; + + /* Check buffers are big enough and grow if needed. */ + if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) + return ret; + + /* Get position in output buffer to write new message to. */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + if (ssl->fragOffset == 0) { + AddTls13FragHeaders(output, fragSz, 0, payloadSz, certificate, ssl); + + /* Request context. */ + output[i++] = certReqCtxLen; + if (certReqCtxLen > 0) { + XMEMCPY(output + i, certReqCtx, certReqCtxLen); + i += certReqCtxLen; + } + length -= OPAQUE8_LEN + certReqCtxLen; + fragSz -= OPAQUE8_LEN + certReqCtxLen; + /* Certificate list length. */ + c32to24(listSz, output + i); + i += CERT_HEADER_SZ; + length -= CERT_HEADER_SZ; + fragSz -= CERT_HEADER_SZ; + /* Leaf certificate data length. */ + if (certSz > 0) { + c32to24(certSz, output + i); + i += CERT_HEADER_SZ; + length -= CERT_HEADER_SZ; + fragSz -= CERT_HEADER_SZ; + } + } + else + AddTls13RecordHeader(output, fragSz, handshake, ssl); + + if (certSz > 0 && ssl->fragOffset < certSz + extSz) { + /* Put in the leaf certificate with extensions. */ + word32 copySz = AddCertExt(ssl, ssl->buffers.certificate->buffer, + certSz, extSz, ssl->fragOffset, fragSz, output + i); + i += copySz; + ssl->fragOffset += copySz; + length -= copySz; + fragSz -= copySz; + if (ssl->fragOffset == certSz + extSz) + FreeDer(&ssl->buffers.certExts); + } + if (certChainSz > 0 && fragSz > 0) { + /* Put in the CA certificates with empty extensions. */ + while (fragSz > 0) { + word32 l; + + if (offset == len + OPAQUE16_LEN) { + /* Find next CA certificate to write out. */ + offset = 0; + /* Point to the start of current cert in chain buffer. */ + p = ssl->buffers.certChain->buffer + idx; + len = NextCert(ssl->buffers.certChain->buffer, + ssl->buffers.certChain->length, &idx); + if (len == 0) + break; + } + + /* Write out certificate and empty extension. */ + l = AddCertExt(ssl, p, len, OPAQUE16_LEN, offset, fragSz, + output + i); + i += l; + ssl->fragOffset += l; + length -= l; + fragSz -= l; + offset += l; + } + } + + if ((int)i - RECORD_HEADER_SZ < 0) { + WOLFSSL_MSG("Send Cert bad inputSz"); + return BUFFER_E; + } + + /* This message is always encrypted. */ + sendSz = BuildTls13Message(ssl, output, sendSz, + output + RECORD_HEADER_SZ, + i - RECORD_HEADER_SZ, handshake, 1, 0, 0); + if (sendSz < 0) + return sendSz; + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName(ssl, "Certificate"); + if (ssl->toInfoOn) { + AddPacketInfo(ssl, "Certificate", handshake, output, + sendSz, WRITE_PROTO, ssl->heap); + } + #endif + + ssl->buffers.outputBuffer.length += sendSz; + if (!ssl->options.groupMessages) + ret = SendBuffered(ssl); + } + + if (ret != WANT_WRITE) { + /* Clean up the fragment offset. */ + ssl->fragOffset = 0; + if (ssl->options.side == WOLFSSL_SERVER_END) + ssl->options.serverState = SERVER_CERT_COMPLETE; + } + +#ifdef WOLFSSL_POST_HANDSHAKE_AUTH + if (ssl->options.side == WOLFSSL_CLIENT_END && ssl->certReqCtx != NULL) { + CertReqCtx* ctx = ssl->certReqCtx; + ssl->certReqCtx = ssl->certReqCtx->next; + XFREE(ctx, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + + WOLFSSL_LEAVE("SendTls13Certificate", ret); + WOLFSSL_END(WC_FUNC_CERTIFICATE_SEND); + + return ret; +} + +typedef struct Scv13Args { + byte* output; /* not allocated */ + byte* verify; /* not allocated */ + word32 idx; + word32 sigLen; + int sendSz; + word16 length; + + byte sigAlgo; + byte* sigData; + word16 sigDataSz; +} Scv13Args; + +static void FreeScv13Args(WOLFSSL* ssl, void* pArgs) +{ + Scv13Args* args = (Scv13Args*)pArgs; + + (void)ssl; + + if (args->sigData) { + XFREE(args->sigData, ssl->heap, DYNAMIC_TYPE_SIGNATURE); + args->sigData = NULL; + } +} + +/* handle generation TLS v1.3 certificate_verify (15) */ +/* Send the TLS v1.3 CertificateVerify message. + * A hash of all the message so far is used. + * The signed data is: + * 0x20 * 64 | context string | 0x00 | hash of messages + * This message is always encrypted in TLS v1.3. + * + * ssl The SSL/TLS object. + * returns 0 on success, otherwise failure. + */ +static int SendTls13CertificateVerify(WOLFSSL* ssl) +{ + int ret = 0; + buffer* sig = &ssl->buffers.sig; +#ifdef WOLFSSL_ASYNC_CRYPT + Scv13Args* args = (Scv13Args*)ssl->async.args; + typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1]; + (void)sizeof(args_test); +#else + Scv13Args args[1]; +#endif + + WOLFSSL_START(WC_FUNC_CERTIFICATE_VERIFY_SEND); + WOLFSSL_ENTER("SendTls13CertificateVerify"); + +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); + if (ret != WC_NOT_PENDING_E) { + /* Check for error */ + if (ret < 0) + goto exit_scv; + } + else +#endif + { + /* Reset state */ + ret = 0; + ssl->options.asyncState = TLS_ASYNC_BEGIN; + XMEMSET(args, 0, sizeof(Scv13Args)); + #ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = FreeScv13Args; + #endif + } + + switch(ssl->options.asyncState) + { + case TLS_ASYNC_BEGIN: + { + if (ssl->options.sendVerify == SEND_BLANK_CERT) { + return 0; /* sent blank cert, can't verify */ + } + + args->sendSz = MAX_CERT_VERIFY_SZ + MAX_MSG_EXTRA; + /* Always encrypted. */ + args->sendSz += MAX_MSG_EXTRA; + + /* check for available size */ + if ((ret = CheckAvailableSize(ssl, args->sendSz)) != 0) { + goto exit_scv; + } + + /* get output buffer */ + args->output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_BUILD; + } /* case TLS_ASYNC_BEGIN */ + FALL_THROUGH; + + case TLS_ASYNC_BUILD: + { + /* idx is used to track verify pointer offset to output */ + args->idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + args->verify = + &args->output[RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ]; + + if (ssl->buffers.key == NULL) { + #ifdef HAVE_PK_CALLBACKS + if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) + args->length = GetPrivateKeySigSize(ssl); + else + #endif + ERROR_OUT(NO_PRIVATE_KEY, exit_scv); + } + else { + ret = DecodePrivateKey(ssl, &args->length); + if (ret != 0) + goto exit_scv; + } + + if (args->length <= 0) { + ERROR_OUT(NO_PRIVATE_KEY, exit_scv); + } + + /* Add signature algorithm. */ + if (ssl->hsType == DYNAMIC_TYPE_RSA) + args->sigAlgo = rsa_pss_sa_algo; + else if (ssl->hsType == DYNAMIC_TYPE_ECC) + args->sigAlgo = ecc_dsa_sa_algo; + #ifdef HAVE_ED25519 + else if (ssl->hsType == DYNAMIC_TYPE_ED25519) + args->sigAlgo = ed25519_sa_algo; + #endif + EncodeSigAlg(ssl->suites->hashAlgo, args->sigAlgo, args->verify); + + if (ssl->hsType == DYNAMIC_TYPE_RSA) { + int sigLen = MAX_SIG_DATA_SZ; + if (args->length > MAX_SIG_DATA_SZ) + sigLen = args->length; + args->sigData = (byte*)XMALLOC(sigLen, ssl->heap, + DYNAMIC_TYPE_SIGNATURE); + } + else { + args->sigData = (byte*)XMALLOC(MAX_SIG_DATA_SZ, ssl->heap, + DYNAMIC_TYPE_SIGNATURE); + } + if (args->sigData == NULL) { + ERROR_OUT(MEMORY_E, exit_scv); + } + + /* Create the data to be signed. */ + ret = CreateSigData(ssl, args->sigData, &args->sigDataSz, 0); + if (ret != 0) + goto exit_scv; + + #ifndef NO_RSA + if (ssl->hsType == DYNAMIC_TYPE_RSA) { + /* build encoded signature buffer */ + sig->length = WC_MAX_DIGEST_SIZE; + sig->buffer = (byte*)XMALLOC(sig->length, ssl->heap, + DYNAMIC_TYPE_SIGNATURE); + if (sig->buffer == NULL) { + ERROR_OUT(MEMORY_E, exit_scv); + } + + ret = CreateRSAEncodedSig(sig->buffer, args->sigData, + args->sigDataSz, args->sigAlgo, ssl->suites->hashAlgo); + if (ret < 0) + goto exit_scv; + sig->length = ret; + ret = 0; + + /* Maximum size of RSA Signature. */ + args->sigLen = args->length; + } + #endif /* !NO_RSA */ + #ifdef HAVE_ECC + if (ssl->hsType == DYNAMIC_TYPE_ECC) { + sig->length = args->sendSz - args->idx - HASH_SIG_SIZE - + VERIFY_HEADER; + ret = CreateECCEncodedSig(args->sigData, + args->sigDataSz, ssl->suites->hashAlgo); + if (ret < 0) + goto exit_scv; + args->sigDataSz = (word16)ret; + ret = 0; + } + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + if (ssl->hsType == DYNAMIC_TYPE_ED25519) { + ret = Ed25519CheckPubKey(ssl); + if (ret < 0) { + ERROR_OUT(ret, exit_scv); + } + sig->length = ED25519_SIG_SIZE; + } + #endif /* HAVE_ECC */ + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_DO; + } /* case TLS_ASYNC_BUILD */ + FALL_THROUGH; + + case TLS_ASYNC_DO: + { + #ifdef HAVE_ECC + if (ssl->hsType == DYNAMIC_TYPE_ECC) { + + ret = EccSign(ssl, args->sigData, args->sigDataSz, + args->verify + HASH_SIG_SIZE + VERIFY_HEADER, + (word32*)&sig->length, (ecc_key*)ssl->hsKey, + #ifdef HAVE_PK_CALLBACKS + ssl->buffers.key + #else + NULL + #endif + ); + args->length = (word16)sig->length; + } + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + if (ssl->hsType == DYNAMIC_TYPE_ED25519) { + ret = Ed25519Sign(ssl, args->sigData, args->sigDataSz, + args->verify + HASH_SIG_SIZE + VERIFY_HEADER, + (word32*)&sig->length, (ed25519_key*)ssl->hsKey, + #ifdef HAVE_PK_CALLBACKS + ssl->buffers.key + #else + NULL + #endif + ); + args->length = (word16)sig->length; + } + #endif + #ifndef NO_RSA + if (ssl->hsType == DYNAMIC_TYPE_RSA) { + ret = RsaSign(ssl, sig->buffer, (word32)sig->length, + args->verify + HASH_SIG_SIZE + VERIFY_HEADER, &args->sigLen, + args->sigAlgo, ssl->suites->hashAlgo, + (RsaKey*)ssl->hsKey, + ssl->buffers.key + ); + if (ret == 0) { + args->length = (word16)args->sigLen; + + XMEMCPY(args->sigData, + args->verify + HASH_SIG_SIZE + VERIFY_HEADER, + args->sigLen); + } + } + #endif /* !NO_RSA */ + + /* Check for error */ + if (ret != 0) { + goto exit_scv; + } + + /* Add signature length. */ + c16toa(args->length, args->verify + HASH_SIG_SIZE); + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_VERIFY; + } /* case TLS_ASYNC_DO */ + FALL_THROUGH; + + case TLS_ASYNC_VERIFY: + { + #ifndef NO_RSA + if (ssl->hsType == DYNAMIC_TYPE_RSA) { + /* check for signature faults */ + ret = VerifyRsaSign(ssl, args->sigData, args->sigLen, + sig->buffer, (word32)sig->length, args->sigAlgo, + ssl->suites->hashAlgo, (RsaKey*)ssl->hsKey, + ssl->buffers.key + ); + } + #endif /* !NO_RSA */ + + /* Check for error */ + if (ret != 0) { + goto exit_scv; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_FINALIZE; + } /* case TLS_ASYNC_VERIFY */ + FALL_THROUGH; + + case TLS_ASYNC_FINALIZE: + { + /* Put the record and handshake headers on. */ + AddTls13Headers(args->output, args->length + HASH_SIG_SIZE + + VERIFY_HEADER, certificate_verify, ssl); + + args->sendSz = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ + + args->length + HASH_SIG_SIZE + VERIFY_HEADER; + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_END; + } /* case TLS_ASYNC_FINALIZE */ + FALL_THROUGH; + + case TLS_ASYNC_END: + { + /* This message is always encrypted. */ + ret = BuildTls13Message(ssl, args->output, + MAX_CERT_VERIFY_SZ + MAX_MSG_EXTRA, + args->output + RECORD_HEADER_SZ, + args->sendSz - RECORD_HEADER_SZ, handshake, + 1, 0, 0); + + if (ret < 0) { + goto exit_scv; + } + else { + args->sendSz = ret; + ret = 0; + } + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) + AddPacketName(ssl, "CertificateVerify"); + if (ssl->toInfoOn) { + AddPacketInfo(ssl, "CertificateVerify", handshake, + args->output, args->sendSz, WRITE_PROTO, ssl->heap); + } + #endif + + ssl->buffers.outputBuffer.length += args->sendSz; + + if (!ssl->options.groupMessages) + ret = SendBuffered(ssl); + break; + } + default: + ret = INPUT_CASE_ERROR; + } /* switch(ssl->options.asyncState) */ + +exit_scv: + + WOLFSSL_LEAVE("SendTls13CertificateVerify", ret); + WOLFSSL_END(WC_FUNC_CERTIFICATE_VERIFY_SEND); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* Handle async operation */ + if (ret == WC_PENDING_E) { + return ret; + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + /* Final cleanup */ + FreeScv13Args(ssl, args); + FreeKeyExchange(ssl); + + return ret; +} + +/* handle processing TLS v1.3 certificate (11) */ +/* Parse and handle a TLS v1.3 Certificate message. + * + * ssl The SSL/TLS object. + * input The message buffer. + * inOutIdx On entry, the index into the message buffer of Certificate. + * On exit, the index of byte after the Certificate message. + * totalSz The length of the current handshake message. + * returns 0 on success and otherwise failure. + */ +static int DoTls13Certificate(WOLFSSL* ssl, byte* input, word32* inOutIdx, + word32 totalSz) +{ + int ret; + + WOLFSSL_START(WC_FUNC_CERTIFICATE_DO); + WOLFSSL_ENTER("DoTls13Certificate"); + + ret = ProcessPeerCerts(ssl, input, inOutIdx, totalSz); + if (ret == 0) { +#if !defined(NO_WOLFSSL_CLIENT) + if (ssl->options.side == WOLFSSL_CLIENT_END) + ssl->options.serverState = SERVER_CERT_COMPLETE; +#endif +#if !defined(NO_WOLFSSL_SERVER) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) + if (ssl->options.side == WOLFSSL_SERVER_END && + ssl->options.handShakeState == HANDSHAKE_DONE) { + /* reset handshake states */ + ssl->options.serverState = SERVER_FINISHED_COMPLETE; + ssl->options.acceptState = TICKET_SENT; + ssl->options.handShakeState = SERVER_FINISHED_COMPLETE; + } +#endif + } + + WOLFSSL_LEAVE("DoTls13Certificate", ret); + WOLFSSL_END(WC_FUNC_CERTIFICATE_DO); + + return ret; +} + +#if !defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519) + +typedef struct Dcv13Args { + byte* output; /* not allocated */ + word32 sendSz; + word16 sz; + word32 sigSz; + word32 idx; + word32 begin; + byte hashAlgo; + byte sigAlgo; + + byte* sigData; + word16 sigDataSz; +} Dcv13Args; + +static void FreeDcv13Args(WOLFSSL* ssl, void* pArgs) +{ + Dcv13Args* args = (Dcv13Args*)pArgs; + + if (args->sigData != NULL) { + XFREE(args->sigData, ssl->heap, DYNAMIC_TYPE_SIGNATURE); + args->sigData = NULL; + } + + (void)ssl; +} + +/* handle processing TLS v1.3 certificate_verify (15) */ +/* Parse and handle a TLS v1.3 CertificateVerify message. + * + * ssl The SSL/TLS object. + * input The message buffer. + * inOutIdx On entry, the index into the message buffer of + * CertificateVerify. + * On exit, the index of byte after the CertificateVerify message. + * totalSz The length of the current handshake message. + * returns 0 on success and otherwise failure. + */ +static int DoTls13CertificateVerify(WOLFSSL* ssl, byte* input, + word32* inOutIdx, word32 totalSz) +{ + int ret = 0; + buffer* sig = &ssl->buffers.sig; +#ifdef WOLFSSL_ASYNC_CRYPT + Dcv13Args* args = (Dcv13Args*)ssl->async.args; + typedef char args_test[sizeof(ssl->async.args) >= sizeof(*args) ? 1 : -1]; + (void)sizeof(args_test); +#else + Dcv13Args args[1]; +#endif + + WOLFSSL_START(WC_FUNC_CERTIFICATE_VERIFY_DO); + WOLFSSL_ENTER("DoTls13CertificateVerify"); + +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfSSL_AsyncPop(ssl, &ssl->options.asyncState); + if (ret != WC_NOT_PENDING_E) { + /* Check for error */ + if (ret < 0) + goto exit_dcv; + } + else +#endif + { + /* Reset state */ + ret = 0; + ssl->options.asyncState = TLS_ASYNC_BEGIN; + XMEMSET(args, 0, sizeof(Dcv13Args)); + args->hashAlgo = sha_mac; + args->sigAlgo = anonymous_sa_algo; + args->idx = *inOutIdx; + args->begin = *inOutIdx; + #ifdef WOLFSSL_ASYNC_CRYPT + ssl->async.freeArgs = FreeDcv13Args; + #endif + } + + switch(ssl->options.asyncState) + { + case TLS_ASYNC_BEGIN: + { + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName(ssl, "CertificateVerify"); + if (ssl->toInfoOn) AddLateName("CertificateVerify", + &ssl->timeoutInfo); + #endif + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_BUILD; + } /* case TLS_ASYNC_BEGIN */ + FALL_THROUGH; + + case TLS_ASYNC_BUILD: + { + /* Signature algorithm. */ + if ((args->idx - args->begin) + ENUM_LEN + ENUM_LEN > totalSz) { + ERROR_OUT(BUFFER_ERROR, exit_dcv); + } + ret = DecodeTls13SigAlg(input + args->idx, &args->hashAlgo, + &args->sigAlgo); + if (ret < 0) + goto exit_dcv; + args->idx += OPAQUE16_LEN; + + /* Signature length. */ + if ((args->idx - args->begin) + OPAQUE16_LEN > totalSz) { + ERROR_OUT(BUFFER_ERROR, exit_dcv); + } + ato16(input + args->idx, &args->sz); + args->idx += OPAQUE16_LEN; + + /* Signature data. */ + if ((args->idx - args->begin) + args->sz > totalSz || + args->sz > ENCRYPT_LEN) { + ERROR_OUT(BUFFER_ERROR, exit_dcv); + } + + /* Check for public key of required type. */ + #ifdef HAVE_ED25519 + if (args->sigAlgo == ed25519_sa_algo && + !ssl->peerEd25519KeyPresent) { + WOLFSSL_MSG("Oops, peer sent ED25519 key but not in verify"); + } + #endif + #ifdef HAVE_ECC + if (args->sigAlgo == ecc_dsa_sa_algo && + !ssl->peerEccDsaKeyPresent) { + WOLFSSL_MSG("Oops, peer sent ECC key but not in verify"); + } + #endif + #ifndef NO_RSA + if (args->sigAlgo == rsa_sa_algo) { + WOLFSSL_MSG("Oops, peer sent PKCS#1.5 signature"); + ERROR_OUT(INVALID_PARAMETER, exit_dcv); + } + if (args->sigAlgo == rsa_pss_sa_algo && + (ssl->peerRsaKey == NULL || !ssl->peerRsaKeyPresent)) { + WOLFSSL_MSG("Oops, peer sent RSA key but not in verify"); + } + #endif + + sig->buffer = (byte*)XMALLOC(args->sz, ssl->heap, + DYNAMIC_TYPE_SIGNATURE); + if (sig->buffer == NULL) { + ERROR_OUT(MEMORY_E, exit_dcv); + } + sig->length = args->sz; + XMEMCPY(sig->buffer, input + args->idx, args->sz); + + #ifdef HAVE_ECC + if (ssl->peerEccDsaKeyPresent) { + WOLFSSL_MSG("Doing ECC peer cert verify"); + + args->sigData = (byte*)XMALLOC(MAX_SIG_DATA_SZ, ssl->heap, + DYNAMIC_TYPE_SIGNATURE); + if (args->sigData == NULL) { + ERROR_OUT(MEMORY_E, exit_dcv); + } + + ret = CreateSigData(ssl, args->sigData, &args->sigDataSz, 1); + if (ret != 0) + goto exit_dcv; + ret = CreateECCEncodedSig(args->sigData, + args->sigDataSz, args->hashAlgo); + if (ret < 0) + goto exit_dcv; + args->sigDataSz = (word16)ret; + ret = 0; + } + #endif + #ifdef HAVE_ED25519 + if (ssl->peerEd25519KeyPresent) { + WOLFSSL_MSG("Doing ED25519 peer cert verify"); + + args->sigData = (byte*)XMALLOC(MAX_SIG_DATA_SZ, ssl->heap, + DYNAMIC_TYPE_SIGNATURE); + if (args->sigData == NULL) { + ERROR_OUT(MEMORY_E, exit_dcv); + } + + CreateSigData(ssl, args->sigData, &args->sigDataSz, 1); + ret = 0; + } + #endif + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_DO; + } /* case TLS_ASYNC_BUILD */ + FALL_THROUGH; + + case TLS_ASYNC_DO: + { + #ifndef NO_RSA + if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0) { + WOLFSSL_MSG("Doing RSA peer cert verify"); + + ret = RsaVerify(ssl, sig->buffer, (word32)sig->length, &args->output, + args->sigAlgo, args->hashAlgo, ssl->peerRsaKey, + #ifdef HAVE_PK_CALLBACKS + &ssl->buffers.peerRsaKey + #else + NULL + #endif + ); + if (ret >= 0) { + args->sendSz = ret; + ret = 0; + } + } + #endif /* !NO_RSA */ + #ifdef HAVE_ECC + if (ssl->peerEccDsaKeyPresent) { + WOLFSSL_MSG("Doing ECC peer cert verify"); + + ret = EccVerify(ssl, input + args->idx, args->sz, + args->sigData, args->sigDataSz, + ssl->peerEccDsaKey, + #ifdef HAVE_PK_CALLBACKS + &ssl->buffers.peerEccDsaKey + #else + NULL + #endif + ); + + if (ret >= 0) { + FreeKey(ssl, DYNAMIC_TYPE_ECC, (void**)&ssl->peerEccDsaKey); + ssl->peerEccDsaKeyPresent = 0; + } + } + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + if (ssl->peerEd25519KeyPresent) { + WOLFSSL_MSG("Doing ED25519 peer cert verify"); + + ret = Ed25519Verify(ssl, input + args->idx, args->sz, + args->sigData, args->sigDataSz, + ssl->peerEd25519Key, + #ifdef HAVE_PK_CALLBACKS + &ssl->buffers.peerEd25519Key + #else + NULL + #endif + ); + + if (ret >= 0) { + FreeKey(ssl, DYNAMIC_TYPE_ED25519, + (void**)&ssl->peerEd25519Key); + ssl->peerEd25519KeyPresent = 0; + } + } + #endif + + /* Check for error */ + if (ret != 0) { + goto exit_dcv; + } + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_VERIFY; + } /* case TLS_ASYNC_DO */ + FALL_THROUGH; + + case TLS_ASYNC_VERIFY: + { + #ifndef NO_RSA + if (ssl->peerRsaKey != NULL && ssl->peerRsaKeyPresent != 0) { + ret = CheckRSASignature(ssl, args->sigAlgo, args->hashAlgo, + args->output, args->sendSz); + if (ret != 0) + goto exit_dcv; + + FreeKey(ssl, DYNAMIC_TYPE_RSA, (void**)&ssl->peerRsaKey); + ssl->peerRsaKeyPresent = 0; + } + #endif /* !NO_RSA */ + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_FINALIZE; + } /* case TLS_ASYNC_VERIFY */ + FALL_THROUGH; + + case TLS_ASYNC_FINALIZE: + { + ssl->options.havePeerVerify = 1; + + /* Set final index */ + args->idx += args->sz; + *inOutIdx = args->idx; + + /* Encryption is always on: add padding */ + *inOutIdx += ssl->keys.padSz; + + /* Advance state and proceed */ + ssl->options.asyncState = TLS_ASYNC_END; + } /* case TLS_ASYNC_FINALIZE */ + + case TLS_ASYNC_END: + { + break; + } + default: + ret = INPUT_CASE_ERROR; + } /* switch(ssl->options.asyncState) */ + +exit_dcv: + + WOLFSSL_LEAVE("DoTls13CertificateVerify", ret); + WOLFSSL_END(WC_FUNC_CERTIFICATE_VERIFY_DO); + +#ifdef WOLFSSL_ASYNC_CRYPT + /* Handle async operation */ + if (ret == WC_PENDING_E) { + /* Mark message as not received so it can process again */ + ssl->msgsReceived.got_certificate_verify = 0; + + return ret; + } + else +#endif /* WOLFSSL_ASYNC_CRYPT */ + if (ret != 0 && ret != INVALID_PARAMETER) + SendAlert(ssl, alert_fatal, decrypt_error); + + /* Final cleanup */ + FreeDcv13Args(ssl, args); + FreeKeyExchange(ssl); + + return ret; +} +#endif /* !NO_RSA || HAVE_ECC */ + +/* Parse and handle a TLS v1.3 Finished message. + * + * ssl The SSL/TLS object. + * input The message buffer. + * inOutIdx On entry, the index into the message buffer of Finished. + * On exit, the index of byte after the Finished message and padding. + * size Length of message data. + * totalSz Length of remaining data in the message buffer. + * sniff Indicates whether we are sniffing packets. + * returns 0 on success and otherwise failure. + */ +static int DoTls13Finished(WOLFSSL* ssl, const byte* input, word32* inOutIdx, + word32 size, word32 totalSz, int sniff) +{ + int ret; + word32 finishedSz = 0; + byte* secret; + byte mac[WC_MAX_DIGEST_SIZE]; + + WOLFSSL_START(WC_FUNC_FINISHED_DO); + WOLFSSL_ENTER("DoTls13Finished"); + + /* check against totalSz */ + if (*inOutIdx + size + ssl->keys.padSz > totalSz) + return BUFFER_E; + + if (ssl->options.handShakeDone) { + ret = DeriveFinishedSecret(ssl, ssl->clientSecret, + ssl->keys.client_write_MAC_secret); + if (ret != 0) + return ret; + + secret = ssl->keys.client_write_MAC_secret; + } + else if (ssl->options.side == WOLFSSL_CLIENT_END) { + /* All the handshake messages have been received to calculate + * client and server finished keys. + */ + ret = DeriveFinishedSecret(ssl, ssl->clientSecret, + ssl->keys.client_write_MAC_secret); + if (ret != 0) + return ret; + + ret = DeriveFinishedSecret(ssl, ssl->serverSecret, + ssl->keys.server_write_MAC_secret); + if (ret != 0) + return ret; + + secret = ssl->keys.server_write_MAC_secret; + } + else + secret = ssl->keys.client_write_MAC_secret; + + ret = BuildTls13HandshakeHmac(ssl, secret, mac, &finishedSz); + if (ret != 0) + return ret; + if (size != finishedSz) + return BUFFER_ERROR; + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName(ssl, "Finished"); + if (ssl->toInfoOn) AddLateName("Finished", &ssl->timeoutInfo); + #endif + + if (sniff == NO_SNIFF) { + /* Actually check verify data. */ + if (XMEMCMP(input + *inOutIdx, mac, size) != 0){ + WOLFSSL_MSG("Verify finished error on hashes"); + SendAlert(ssl, alert_fatal, decrypt_error); + return VERIFY_FINISHED_ERROR; + } + } + + /* Force input exhaustion at ProcessReply by consuming padSz. */ + *inOutIdx += size + ssl->keys.padSz; + + if (ssl->options.side == WOLFSSL_SERVER_END && + !ssl->options.handShakeDone) { +#ifdef WOLFSSL_EARLY_DATA + if (ssl->earlyData != no_early_data) { + if ((ret = DeriveTls13Keys(ssl, no_key, DECRYPT_SIDE_ONLY, 1)) != 0) + return ret; + } +#endif + /* Setup keys for application data messages from client. */ + if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0) + return ret; + } + +#ifndef NO_WOLFSSL_CLIENT + if (ssl->options.side == WOLFSSL_CLIENT_END) + ssl->options.serverState = SERVER_FINISHED_COMPLETE; +#endif +#ifndef NO_WOLFSSL_SERVER + if (ssl->options.side == WOLFSSL_SERVER_END) { + ssl->options.clientState = CLIENT_FINISHED_COMPLETE; + ssl->options.handShakeState = HANDSHAKE_DONE; + ssl->options.handShakeDone = 1; + } +#endif + + WOLFSSL_LEAVE("DoTls13Finished", 0); + WOLFSSL_END(WC_FUNC_FINISHED_DO); + + return 0; +} +#endif /* NO_CERTS */ + +/* Send the TLS v1.3 Finished message. + * + * ssl The SSL/TLS object. + * returns 0 on success, otherwise failure. + */ +static int SendTls13Finished(WOLFSSL* ssl) +{ + int sendSz; + int finishedSz = ssl->specs.hash_size; + byte* input; + byte* output; + int ret; + int headerSz = HANDSHAKE_HEADER_SZ; + int outputSz; + byte* secret; + + WOLFSSL_START(WC_FUNC_FINISHED_SEND); + WOLFSSL_ENTER("SendTls13Finished"); + + outputSz = WC_MAX_DIGEST_SIZE + DTLS_HANDSHAKE_HEADER_SZ + MAX_MSG_EXTRA; + /* Check buffers are big enough and grow if needed. */ + if ((ret = CheckAvailableSize(ssl, outputSz)) != 0) + return ret; + + /* get output buffer */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + input = output + RECORD_HEADER_SZ; + + AddTls13HandShakeHeader(input, finishedSz, 0, finishedSz, finished, ssl); + + /* make finished hashes */ + if (ssl->options.handShakeDone) { + ret = DeriveFinishedSecret(ssl, ssl->clientSecret, + ssl->keys.client_write_MAC_secret); + if (ret != 0) + return ret; + + secret = ssl->keys.client_write_MAC_secret; + } + else if (ssl->options.side == WOLFSSL_CLIENT_END) + secret = ssl->keys.client_write_MAC_secret; + else { + /* All the handshake messages have been done to calculate client and + * server finished keys. + */ + ret = DeriveFinishedSecret(ssl, ssl->clientSecret, + ssl->keys.client_write_MAC_secret); + if (ret != 0) + return ret; + + ret = DeriveFinishedSecret(ssl, ssl->serverSecret, + ssl->keys.server_write_MAC_secret); + if (ret != 0) + return ret; + + secret = ssl->keys.server_write_MAC_secret; + } + ret = BuildTls13HandshakeHmac(ssl, secret, &input[headerSz], NULL); + if (ret != 0) + return ret; + + /* This message is always encrypted. */ + sendSz = BuildTls13Message(ssl, output, outputSz, input, + headerSz + finishedSz, handshake, 1, 0, 0); + if (sendSz < 0) + return BUILD_MSG_ERROR; + +#ifndef NO_SESSION_CACHE + if (!ssl->options.resuming && (ssl->options.side == WOLFSSL_SERVER_END || + (ssl->options.side == WOLFSSL_SERVER_END && ssl->arrays != NULL))) { + AddSession(ssl); /* just try */ + } +#endif + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName(ssl, "Finished"); + if (ssl->toInfoOn) { + AddPacketInfo(ssl, "Finished", handshake, output, sendSz, + WRITE_PROTO, ssl->heap); + } + #endif + + ssl->buffers.outputBuffer.length += sendSz; + + if (ssl->options.side == WOLFSSL_SERVER_END) { + /* Can send application data now. */ + if ((ret = DeriveMasterSecret(ssl)) != 0) + return ret; +#ifdef WOLFSSL_EARLY_DATA + if ((ret = DeriveTls13Keys(ssl, traffic_key, ENCRYPT_SIDE_ONLY, 1)) + != 0) { + return ret; + } + if ((ret = DeriveTls13Keys(ssl, traffic_key, DECRYPT_SIDE_ONLY, + ssl->earlyData == no_early_data)) != 0) { + return ret; + } +#else + if ((ret = DeriveTls13Keys(ssl, traffic_key, ENCRYPT_AND_DECRYPT_SIDE, + 1)) != 0) { + return ret; + } +#endif + if ((ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY)) != 0) + return ret; + } + + if (ssl->options.side == WOLFSSL_CLIENT_END && + !ssl->options.handShakeDone) { +#ifdef WOLFSSL_EARLY_DATA + if (ssl->earlyData != no_early_data) { + if ((ret = DeriveTls13Keys(ssl, no_key, ENCRYPT_AND_DECRYPT_SIDE, + 1)) != 0) { + return ret; + } + } +#endif + /* Setup keys for application data messages. */ + if ((ret = SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE)) != 0) + return ret; + +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + ret = DeriveResumptionSecret(ssl, ssl->session.masterSecret); + if (ret != 0) + return ret; +#endif + } + +#ifndef NO_WOLFSSL_CLIENT + if (ssl->options.side == WOLFSSL_CLIENT_END) { + ssl->options.clientState = CLIENT_FINISHED_COMPLETE; + ssl->options.handShakeState = HANDSHAKE_DONE; + ssl->options.handShakeDone = 1; + } +#endif +#ifndef NO_WOLFSSL_SERVER + if (ssl->options.side == WOLFSSL_SERVER_END) { + ssl->options.serverState = SERVER_FINISHED_COMPLETE; + } +#endif + + if ((ret = SendBuffered(ssl)) != 0) + return ret; + + WOLFSSL_LEAVE("SendTls13Finished", ret); + WOLFSSL_END(WC_FUNC_FINISHED_SEND); + + return ret; +} + +/* handle generation TLS v1.3 key_update (24) */ +/* Send the TLS v1.3 KeyUpdate message. + * + * ssl The SSL/TLS object. + * returns 0 on success, otherwise failure. + */ +static int SendTls13KeyUpdate(WOLFSSL* ssl) +{ + int sendSz; + byte* input; + byte* output; + int ret; + int headerSz = HANDSHAKE_HEADER_SZ; + int outputSz; + word32 i = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + + WOLFSSL_START(WC_FUNC_KEY_UPDATE_SEND); + WOLFSSL_ENTER("SendTls13KeyUpdate"); + + outputSz = OPAQUE8_LEN + MAX_MSG_EXTRA; + /* Check buffers are big enough and grow if needed. */ + if ((ret = CheckAvailableSize(ssl, outputSz)) != 0) + return ret; + + /* get output buffer */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + input = output + RECORD_HEADER_SZ; + + AddTls13Headers(output, OPAQUE8_LEN, key_update, ssl); + + /* If: + * 1. I haven't sent a KeyUpdate requesting a response and + * 2. This isn't responding to peer KeyUpdate requiring a response then, + * I want a response. + */ + ssl->keys.updateResponseReq = output[i++] = + !ssl->keys.updateResponseReq && !ssl->keys.keyUpdateRespond; + /* Sent response, no longer need to respond. */ + ssl->keys.keyUpdateRespond = 0; + + /* This message is always encrypted. */ + sendSz = BuildTls13Message(ssl, output, outputSz, input, + headerSz + OPAQUE8_LEN, handshake, 0, 0, 0); + if (sendSz < 0) + return BUILD_MSG_ERROR; + + #ifdef WOLFSSL_CALLBACKS + if (ssl->hsInfoOn) AddPacketName(ssl, "KeyUpdate"); + if (ssl->toInfoOn) { + AddPacketInfo(ssl, "KeyUpdate", handshake, output, sendSz, + WRITE_PROTO, ssl->heap); + } + #endif + + ssl->buffers.outputBuffer.length += sendSz; + + ret = SendBuffered(ssl); + if (ret != 0 && ret != WANT_WRITE) + return ret; + + /* Future traffic uses new encryption keys. */ + if ((ret = DeriveTls13Keys(ssl, update_traffic_key, ENCRYPT_SIDE_ONLY, 1)) + != 0) + return ret; + if ((ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY)) != 0) + return ret; + + WOLFSSL_LEAVE("SendTls13KeyUpdate", ret); + WOLFSSL_END(WC_FUNC_KEY_UPDATE_SEND); + + return ret; +} + +/* handle processing TLS v1.3 key_update (24) */ +/* Parse and handle a TLS v1.3 KeyUpdate message. + * + * ssl The SSL/TLS object. + * input The message buffer. + * inOutIdx On entry, the index into the message buffer of Finished. + * On exit, the index of byte after the Finished message and padding. + * totalSz The length of the current handshake message. + * returns 0 on success and otherwise failure. + */ +static int DoTls13KeyUpdate(WOLFSSL* ssl, const byte* input, word32* inOutIdx, + word32 totalSz) +{ + int ret; + word32 i = *inOutIdx; + + WOLFSSL_START(WC_FUNC_KEY_UPDATE_DO); + WOLFSSL_ENTER("DoTls13KeyUpdate"); + + /* check against totalSz */ + if (OPAQUE8_LEN != totalSz) + return BUFFER_E; + + switch (input[i]) { + case update_not_requested: + /* This message in response to any outstanding request. */ + ssl->keys.keyUpdateRespond = 0; + ssl->keys.updateResponseReq = 0; + break; + case update_requested: + /* New key update requiring a response. */ + ssl->keys.keyUpdateRespond = 1; + break; + default: + return INVALID_PARAMETER; + } + + /* Move index to byte after message. */ + *inOutIdx += totalSz; + /* Always encrypted. */ + *inOutIdx += ssl->keys.padSz; + + /* Future traffic uses new decryption keys. */ + if ((ret = DeriveTls13Keys(ssl, update_traffic_key, DECRYPT_SIDE_ONLY, 1)) + != 0) { + return ret; + } + if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0) + return ret; + + if (ssl->keys.keyUpdateRespond) + return SendTls13KeyUpdate(ssl); + + WOLFSSL_LEAVE("DoTls13KeyUpdate", ret); + WOLFSSL_END(WC_FUNC_KEY_UPDATE_DO); + + return 0; +} + +#ifdef WOLFSSL_EARLY_DATA +#ifndef NO_WOLFSSL_CLIENT +/* Send the TLS v1.3 EndOfEarlyData message to indicate that there will be no + * more early application data. + * The encryption key now changes to the pre-calculated handshake key. + * + * ssl The SSL/TLS object. + * returns 0 on success and otherwise failure. + */ +static int SendTls13EndOfEarlyData(WOLFSSL* ssl) +{ + byte* output; + int ret; + int sendSz; + word32 length; + word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + + WOLFSSL_START(WC_FUNC_END_OF_EARLY_DATA_SEND); + WOLFSSL_ENTER("SendTls13EndOfEarlyData"); + + length = 0; + sendSz = idx + length + MAX_MSG_EXTRA; + + /* Check buffers are big enough and grow if needed. */ + if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) + return ret; + + /* Get position in output buffer to write new message to. */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + /* Put the record and handshake headers on. */ + AddTls13Headers(output, length, end_of_early_data, ssl); + + /* This message is always encrypted. */ + sendSz = BuildTls13Message(ssl, output, sendSz, output + RECORD_HEADER_SZ, + idx - RECORD_HEADER_SZ, handshake, 1, 0, 0); + if (sendSz < 0) + return sendSz; + + ssl->buffers.outputBuffer.length += sendSz; + + if ((ret = SetKeysSide(ssl, ENCRYPT_SIDE_ONLY)) != 0) + return ret; + + if (!ssl->options.groupMessages) + ret = SendBuffered(ssl); + + WOLFSSL_LEAVE("SendTls13EndOfEarlyData", ret); + WOLFSSL_END(WC_FUNC_END_OF_EARLY_DATA_SEND); + + return ret; +} +#endif /* !NO_WOLFSSL_CLIENT */ + +#ifndef NO_WOLFSSL_SERVER +/* handle processing of TLS 1.3 end_of_early_data (5) */ +/* Parse the TLS v1.3 EndOfEarlyData message that indicates that there will be + * no more early application data. + * The decryption key now changes to the pre-calculated handshake key. + * + * ssl The SSL/TLS object. + * returns 0 on success and otherwise failure. + */ +static int DoTls13EndOfEarlyData(WOLFSSL* ssl, const byte* input, + word32* inOutIdx, word32 size) +{ + int ret; + word32 begin = *inOutIdx; + + (void)input; + + WOLFSSL_START(WC_FUNC_END_OF_EARLY_DATA_DO); + WOLFSSL_ENTER("DoTls13EndOfEarlyData"); + + if ((*inOutIdx - begin) != size) + return BUFFER_ERROR; + + if (ssl->earlyData == no_early_data) { + WOLFSSL_MSG("EndOfEarlyData received unexpectedly"); + SendAlert(ssl, alert_fatal, unexpected_message); + return OUT_OF_ORDER_E; + } + + ssl->earlyData = done_early_data; + + /* Always encrypted. */ + *inOutIdx += ssl->keys.padSz; + + ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY); + + WOLFSSL_LEAVE("DoTls13EndOfEarlyData", ret); + WOLFSSL_END(WC_FUNC_END_OF_EARLY_DATA_DO); + + return ret; +} +#endif /* !NO_WOLFSSL_SERVER */ +#endif /* WOLFSSL_EARLY_DATA */ + +#ifndef NO_WOLFSSL_CLIENT +/* Handle a New Session Ticket handshake message. + * Message contains the information required to perform resumption. + * + * ssl The SSL/TLS object. + * input The message buffer. + * inOutIdx On entry, the index into the message buffer of Finished. + * On exit, the index of byte after the Finished message and padding. + * size The length of the current handshake message. + * returns 0 on success, otherwise failure. + */ +static int DoTls13NewSessionTicket(WOLFSSL* ssl, const byte* input, + word32* inOutIdx, word32 size) +{ +#ifdef HAVE_SESSION_TICKET + int ret; + word32 begin = *inOutIdx; + word32 lifetime; + word32 ageAdd; + word16 length; + word32 now; +#ifndef WOLFSSL_TLS13_DRAFT_18 + const byte* nonce; + byte nonceLength; +#endif + + WOLFSSL_START(WC_FUNC_NEW_SESSION_TICKET_DO); + WOLFSSL_ENTER("DoTls13NewSessionTicket"); + + /* Lifetime hint. */ + if ((*inOutIdx - begin) + SESSION_HINT_SZ > size) + return BUFFER_ERROR; + ato32(input + *inOutIdx, &lifetime); + *inOutIdx += SESSION_HINT_SZ; + if (lifetime > MAX_LIFETIME) + return SERVER_HINT_ERROR; + + /* Age add. */ + if ((*inOutIdx - begin) + SESSION_ADD_SZ > size) + return BUFFER_ERROR; + ato32(input + *inOutIdx, &ageAdd); + *inOutIdx += SESSION_ADD_SZ; + +#ifndef WOLFSSL_TLS13_DRAFT_18 + /* Ticket nonce. */ + if ((*inOutIdx - begin) + 1 > size) + return BUFFER_ERROR; + nonceLength = input[*inOutIdx]; + if (nonceLength > MAX_TICKET_NONCE_SZ) { + WOLFSSL_MSG("Nonce length not supported"); + return INVALID_PARAMETER; + } + *inOutIdx += 1; + if ((*inOutIdx - begin) + nonceLength > size) + return BUFFER_ERROR; + nonce = input + *inOutIdx; + *inOutIdx += nonceLength; +#endif + + /* Ticket length. */ + if ((*inOutIdx - begin) + LENGTH_SZ > size) + return BUFFER_ERROR; + ato16(input + *inOutIdx, &length); + *inOutIdx += LENGTH_SZ; + if ((*inOutIdx - begin) + length > size) + return BUFFER_ERROR; + + if ((ret = SetTicket(ssl, input + *inOutIdx, length)) != 0) + return ret; + *inOutIdx += length; + + now = TimeNowInMilliseconds(); + if (now == (word32)GETTIME_ERROR) + return now; + /* Copy in ticket data (server identity). */ + ssl->timeout = lifetime; + ssl->session.timeout = lifetime; + ssl->session.cipherSuite0 = ssl->options.cipherSuite0; + ssl->session.cipherSuite = ssl->options.cipherSuite; + ssl->session.ticketSeen = now; + ssl->session.ticketAdd = ageAdd; + #ifdef WOLFSSL_EARLY_DATA + ssl->session.maxEarlyDataSz = ssl->options.maxEarlyDataSz; + #endif +#ifndef WOLFSSL_TLS13_DRAFT_18 + ssl->session.ticketNonce.len = nonceLength; + if (nonceLength > 0) + XMEMCPY(&ssl->session.ticketNonce.data, nonce, nonceLength); +#endif + ssl->session.namedGroup = ssl->namedGroup; + + if ((*inOutIdx - begin) + EXTS_SZ > size) + return BUFFER_ERROR; + ato16(input + *inOutIdx, &length); + *inOutIdx += EXTS_SZ; + if ((*inOutIdx - begin) + length != size) + return BUFFER_ERROR; + #ifdef WOLFSSL_EARLY_DATA + ret = TLSX_Parse(ssl, (byte *)input + (*inOutIdx), length, session_ticket, + NULL); + if (ret != 0) + return ret; + #endif + *inOutIdx += length; + + #ifndef NO_SESSION_CACHE + AddSession(ssl); + #endif + + /* Always encrypted. */ + *inOutIdx += ssl->keys.padSz; + + ssl->expect_session_ticket = 0; +#else + (void)ssl; + (void)input; + + WOLFSSL_ENTER("DoTls13NewSessionTicket"); + + *inOutIdx += size + ssl->keys.padSz; +#endif /* HAVE_SESSION_TICKET */ + + WOLFSSL_LEAVE("DoTls13NewSessionTicket", 0); + WOLFSSL_END(WC_FUNC_NEW_SESSION_TICKET_DO); + + return 0; +} +#endif /* NO_WOLFSSL_CLIENT */ + +#ifndef NO_WOLFSSL_SERVER + #ifdef HAVE_SESSION_TICKET + +#ifdef WOLFSSL_TLS13_TICKET_BEFORE_FINISHED +/* Offset of the MAC size in the finished message. */ +#define FINISHED_MSG_SIZE_OFFSET 3 + +/* Calculate the resumption secret which includes the unseen client finished + * message. + * + * ssl The SSL/TLS object. + * returns 0 on success, otherwise failure. + */ +static int ExpectedResumptionSecret(WOLFSSL* ssl) +{ + int ret; + word32 finishedSz = 0; + byte mac[WC_MAX_DIGEST_SIZE]; + Digest digest; + static byte header[] = { 0x14, 0x00, 0x00, 0x00 }; + + /* Copy the running hash so we can restore it after. */ + switch (ssl->specs.mac_algorithm) { + #ifndef NO_SHA256 + case sha256_mac: + ret = wc_Sha256Copy(&ssl->hsHashes->hashSha256, &digest.sha256); + if (ret != 0) + return ret; + break; + #endif + #ifdef WOLFSSL_SHA384 + case sha384_mac: + ret = wc_Sha384Copy(&ssl->hsHashes->hashSha384, &digest.sha384); + if (ret != 0) + return ret; + break; + #endif + #ifdef WOLFSSL_TLS13_SHA512 + case sha512_mac: + ret = wc_Sha512Copy(&ssl->hsHashes->hashSha512, &digest.sha512); + if (ret != 0) + return ret; + break; + #endif + } + + /* Generate the Client's Finished message and hash it. */ + ret = BuildTls13HandshakeHmac(ssl, ssl->keys.client_write_MAC_secret, mac, + &finishedSz); + if (ret != 0) + return ret; + header[FINISHED_MSG_SIZE_OFFSET] = finishedSz; +#ifdef WOLFSSL_EARLY_DATA + if (ssl->earlyData != no_early_data) { + static byte endOfEarlyData[] = { 0x05, 0x00, 0x00, 0x00 }; + ret = HashInputRaw(ssl, endOfEarlyData, sizeof(endOfEarlyData)); + if (ret != 0) + return ret; + } +#endif + if ((ret = HashInputRaw(ssl, header, sizeof(header))) != 0) + return ret; + if ((ret = HashInputRaw(ssl, mac, finishedSz)) != 0) + return ret; + + if ((ret = DeriveResumptionSecret(ssl, ssl->session.masterSecret)) != 0) + return ret; + + /* Restore the hash inline with currently seen messages. */ + switch (ssl->specs.mac_algorithm) { + #ifndef NO_SHA256 + case sha256_mac: + ret = wc_Sha256Copy(&digest.sha256, &ssl->hsHashes->hashSha256); + if (ret != 0) + return ret; + break; + #endif + #ifdef WOLFSSL_SHA384 + case sha384_mac: + ret = wc_Sha384Copy(&digest.sha384, &ssl->hsHashes->hashSha384); + if (ret != 0) + return ret; + break; + #endif + #ifdef WOLFSSL_TLS13_SHA512 + case sha512_mac: + ret = wc_Sha512Copy(&digest.sha512, &ssl->hsHashes->hashSha384); + if (ret != 0) + return ret; + break; + #endif + } + + return ret; +} +#endif + +/* Send New Session Ticket handshake message. + * Message contains the information required to perform resumption. + * + * ssl The SSL/TLS object. + * returns 0 on success, otherwise failure. + */ +static int SendTls13NewSessionTicket(WOLFSSL* ssl) +{ + byte* output; + int ret; + int sendSz; + word16 extSz; + word32 length; + word32 idx = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + + WOLFSSL_START(WC_FUNC_NEW_SESSION_TICKET_SEND); + WOLFSSL_ENTER("SendTls13NewSessionTicket"); + +#ifdef WOLFSSL_TLS13_TICKET_BEFORE_FINISHED + if (!ssl->msgsReceived.got_finished) { + if ((ret = ExpectedResumptionSecret(ssl)) != 0) + return ret; + } +#endif + +#ifndef WOLFSSL_TLS13_DRAFT_18 + /* Start ticket nonce at 0 and go up to 255. */ + if (ssl->session.ticketNonce.len == 0) { + ssl->session.ticketNonce.len = DEF_TICKET_NONCE_SZ; + ssl->session.ticketNonce.data[0] = 0; + } + else + ssl->session.ticketNonce.data[0]++; +#endif + + if (!ssl->options.noTicketTls13) { + if ((ret = CreateTicket(ssl)) != 0) + return ret; + } + +#ifdef WOLFSSL_EARLY_DATA + ssl->session.maxEarlyDataSz = ssl->options.maxEarlyDataSz; + if (ssl->session.maxEarlyDataSz > 0) + TLSX_EarlyData_Use(ssl, ssl->session.maxEarlyDataSz); + extSz = 0; + ret = TLSX_GetResponseSize(ssl, session_ticket, &extSz); + if (ret != 0) + return ret; +#else + extSz = EXTS_SZ; +#endif + + /* Lifetime | Age Add | Ticket | Extensions */ + length = SESSION_HINT_SZ + SESSION_ADD_SZ + LENGTH_SZ + + ssl->session.ticketLen + extSz; +#ifndef WOLFSSL_TLS13_DRAFT_18 + /* Nonce */ + length += TICKET_NONCE_LEN_SZ + DEF_TICKET_NONCE_SZ; +#endif + sendSz = idx + length + MAX_MSG_EXTRA; + + /* Check buffers are big enough and grow if needed. */ + if ((ret = CheckAvailableSize(ssl, sendSz)) != 0) + return ret; + + /* Get position in output buffer to write new message to. */ + output = ssl->buffers.outputBuffer.buffer + + ssl->buffers.outputBuffer.length; + + /* Put the record and handshake headers on. */ + AddTls13Headers(output, length, session_ticket, ssl); + + /* Lifetime hint */ + c32toa(ssl->ctx->ticketHint, output + idx); + idx += SESSION_HINT_SZ; + /* Age add - obfuscator */ + c32toa(ssl->session.ticketAdd, output + idx); + idx += SESSION_ADD_SZ; + +#ifndef WOLFSSL_TLS13_DRAFT_18 + output[idx++] = ssl->session.ticketNonce.len; + output[idx++] = ssl->session.ticketNonce.data[0]; +#endif + + /* length */ + c16toa(ssl->session.ticketLen, output + idx); + idx += LENGTH_SZ; + /* ticket */ + XMEMCPY(output + idx, ssl->session.ticket, ssl->session.ticketLen); + idx += ssl->session.ticketLen; + +#ifdef WOLFSSL_EARLY_DATA + extSz = 0; + ret = TLSX_WriteResponse(ssl, output + idx, session_ticket, &extSz); + if (ret != 0) + return ret; + idx += extSz; +#else + /* No extension support - empty extensions. */ + c16toa(0, output + idx); + idx += EXTS_SZ; +#endif + + ssl->options.haveSessionId = 1; + +#ifndef NO_SESSION_CACHE + AddSession(ssl); +#endif + + /* This message is always encrypted. */ + sendSz = BuildTls13Message(ssl, output, sendSz, output + RECORD_HEADER_SZ, + idx - RECORD_HEADER_SZ, handshake, 0, 0, 0); + if (sendSz < 0) + return sendSz; + + ssl->buffers.outputBuffer.length += sendSz; + + if (!ssl->options.groupMessages) + ret = SendBuffered(ssl); + + WOLFSSL_LEAVE("SendTls13NewSessionTicket", 0); + WOLFSSL_END(WC_FUNC_NEW_SESSION_TICKET_SEND); + + return ret; +} + #endif /* HAVE_SESSION_TICKET */ +#endif /* NO_WOLFSSL_SERVER */ + +/* Make sure no duplicates, no fast forward, or other problems + * + * ssl The SSL/TLS object. + * type Type of handshake message received. + * returns 0 on success, otherwise failure. + */ +static int SanityCheckTls13MsgReceived(WOLFSSL* ssl, byte type) +{ + /* verify not a duplicate, mark received, check state */ + switch (type) { + +#ifndef NO_WOLFSSL_SERVER + case client_hello: + #ifndef NO_WOLFSSL_CLIENT + if (ssl->options.side == WOLFSSL_CLIENT_END) { + WOLFSSL_MSG("ClientHello received by client"); + return OUT_OF_ORDER_E; + } + #endif + if (ssl->options.clientState >= CLIENT_HELLO_COMPLETE) { + WOLFSSL_MSG("ClientHello received out of order"); + return OUT_OF_ORDER_E; + } + if (ssl->msgsReceived.got_client_hello == 2) { + WOLFSSL_MSG("Too many ClientHello received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_client_hello++; + + break; +#endif + +#ifndef NO_WOLFSSL_CLIENT + case server_hello: + #ifndef NO_WOLFSSL_SERVER + if (ssl->options.side == WOLFSSL_SERVER_END) { + WOLFSSL_MSG("ServerHello received by server"); + return OUT_OF_ORDER_E; + } + #endif + #ifdef WOLFSSL_TLS13_DRAFT_18 + if (ssl->msgsReceived.got_server_hello) { + WOLFSSL_MSG("Duplicate ServerHello received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_server_hello = 1; + #else + if (ssl->msgsReceived.got_server_hello == 2) { + WOLFSSL_MSG("Duplicate ServerHello received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_server_hello++; + #endif + + break; +#endif + +#ifndef NO_WOLFSSL_CLIENT + case session_ticket: + #ifndef NO_WOLFSSL_SERVER + if (ssl->options.side == WOLFSSL_SERVER_END) { + WOLFSSL_MSG("NewSessionTicket received by server"); + return OUT_OF_ORDER_E; + } + #endif + if (ssl->options.clientState < CLIENT_FINISHED_COMPLETE) { + WOLFSSL_MSG("NewSessionTicket received out of order"); + return OUT_OF_ORDER_E; + } + ssl->msgsReceived.got_session_ticket = 1; + + break; +#endif + +#ifndef NO_WOLFSSL_SERVER + #ifdef WOLFSSL_EARLY_DATA + case end_of_early_data: + #ifndef NO_WOLFSSL_CLIENT + if (ssl->options.side == WOLFSSL_CLIENT_END) { + WOLFSSL_MSG("EndOfEarlyData received by client"); + return OUT_OF_ORDER_E; + } + #endif + if (ssl->options.serverState < SERVER_FINISHED_COMPLETE) { + WOLFSSL_MSG("EndOfEarlyData received out of order"); + return OUT_OF_ORDER_E; + } + if (ssl->options.clientState >= CLIENT_FINISHED_COMPLETE) { + WOLFSSL_MSG("EndOfEarlyData received out of order"); + return OUT_OF_ORDER_E; + } + if (ssl->msgsReceived.got_end_of_early_data == 1) { + WOLFSSL_MSG("Too many EndOfEarlyData received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_end_of_early_data++; + + break; + #endif +#endif + +#ifdef WOLFSSL_TLS13_DRAFT_18 + #ifndef NO_WOLFSSL_CLIENT + case hello_retry_request: + #ifndef NO_WOLFSSL_SERVER + if (ssl->options.side == WOLFSSL_SERVER_END) { + WOLFSSL_MSG("HelloRetryRequest received by server"); + return OUT_OF_ORDER_E; + } + #endif + if (ssl->options.clientState > CLIENT_FINISHED_COMPLETE) { + WOLFSSL_MSG("HelloRetryRequest received out of order"); + return OUT_OF_ORDER_E; + } + if (ssl->msgsReceived.got_hello_retry_request) { + WOLFSSL_MSG("Duplicate HelloRetryRequest received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_hello_retry_request = 1; + + break; + #endif +#endif + +#ifndef NO_WOLFSSL_CLIENT + case encrypted_extensions: + #ifndef NO_WOLFSSL_SERVER + if (ssl->options.side == WOLFSSL_SERVER_END) { + WOLFSSL_MSG("EncryptedExtensions received by server"); + return OUT_OF_ORDER_E; + } + #endif + if (ssl->options.serverState != SERVER_HELLO_COMPLETE) { + WOLFSSL_MSG("EncryptedExtensions received out of order"); + return OUT_OF_ORDER_E; + } + if (ssl->msgsReceived.got_encrypted_extensions) { + WOLFSSL_MSG("Duplicate EncryptedExtensions received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_encrypted_extensions = 1; + + break; +#endif + + case certificate: + #ifndef NO_WOLFSSL_CLIENT + if (ssl->options.side == WOLFSSL_CLIENT_END && + ssl->options.serverState != + SERVER_ENCRYPTED_EXTENSIONS_COMPLETE) { + WOLFSSL_MSG("Certificate received out of order - Client"); + return OUT_OF_ORDER_E; + } + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + /* Server's authenticating with PSK must not send this. */ + if (ssl->options.side == WOLFSSL_CLIENT_END && + ssl->options.serverState == SERVER_CERT_COMPLETE && + ssl->arrays->psk_keySz != 0) { + WOLFSSL_MSG("Certificate received while using PSK"); + return SANITY_MSG_E; + } + #endif + #endif + #ifndef NO_WOLFSSL_SERVER + if (ssl->options.side == WOLFSSL_SERVER_END && + ssl->options.serverState < SERVER_FINISHED_COMPLETE) { + WOLFSSL_MSG("Certificate received out of order - Server"); + return OUT_OF_ORDER_E; + } + #endif + if (ssl->msgsReceived.got_certificate) { + WOLFSSL_MSG("Duplicate Certificate received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_certificate = 1; + + break; + +#ifndef NO_WOLFSSL_CLIENT + case certificate_request: + #ifndef NO_WOLFSSL_SERVER + if (ssl->options.side == WOLFSSL_SERVER_END) { + WOLFSSL_MSG("CertificateRequest received by server"); + return OUT_OF_ORDER_E; + } + #endif + #ifndef WOLFSSL_POST_HANDSHAKE_AUTH + if (ssl->options.serverState != + SERVER_ENCRYPTED_EXTENSIONS_COMPLETE) { + WOLFSSL_MSG("CertificateRequest received out of order"); + return OUT_OF_ORDER_E; + } + #else + if (ssl->options.serverState != + SERVER_ENCRYPTED_EXTENSIONS_COMPLETE && + (ssl->options.serverState != SERVER_FINISHED_COMPLETE || + ssl->options.clientState != CLIENT_FINISHED_COMPLETE)) { + WOLFSSL_MSG("CertificateRequest received out of order"); + return OUT_OF_ORDER_E; + } + #endif + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + /* Server's authenticating with PSK must not send this. */ + if (ssl->options.serverState == + SERVER_ENCRYPTED_EXTENSIONS_COMPLETE && + ssl->arrays->psk_keySz != 0) { + WOLFSSL_MSG("CertificateRequset received while using PSK"); + return SANITY_MSG_E; + } + #endif + #ifndef WOLFSSL_POST_HANDSHAKE_AUTH + if (ssl->msgsReceived.got_certificate_request) { + WOLFSSL_MSG("Duplicate CertificateRequest received"); + return DUPLICATE_MSG_E; + } + #endif + ssl->msgsReceived.got_certificate_request = 1; + + break; +#endif + + case certificate_verify: + #ifndef NO_WOLFSSL_CLIENT + if (ssl->options.side == WOLFSSL_CLIENT_END) { + if (ssl->options.serverState != SERVER_CERT_COMPLETE) { + WOLFSSL_MSG("No Cert before CertVerify"); + return OUT_OF_ORDER_E; + } + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + /* Server's authenticating with PSK must not send this. */ + if (ssl->options.serverState == SERVER_CERT_COMPLETE && + ssl->arrays->psk_keySz != 0) { + WOLFSSL_MSG("CertificateVerify received while using PSK"); + return SANITY_MSG_E; + } + #endif + } + #endif + #ifndef NO_WOLFSSL_SERVER + if (ssl->options.side == WOLFSSL_SERVER_END) { + if (ssl->options.serverState < SERVER_FINISHED_COMPLETE) { + WOLFSSL_MSG("CertificateVerify received out of order"); + return OUT_OF_ORDER_E; + } + if (ssl->options.clientState < CLIENT_HELLO_COMPLETE) { + WOLFSSL_MSG("CertificateVerify before ClientHello done"); + return OUT_OF_ORDER_E; + } + if (!ssl->msgsReceived.got_certificate) { + WOLFSSL_MSG("No Cert before CertificateVerify"); + return OUT_OF_ORDER_E; + } + } + #endif + if (ssl->msgsReceived.got_certificate_verify) { + WOLFSSL_MSG("Duplicate CertificateVerify received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_certificate_verify = 1; + + break; + + case finished: + #ifndef NO_WOLFSSL_CLIENT + if (ssl->options.side == WOLFSSL_CLIENT_END) { + if (ssl->options.clientState < CLIENT_HELLO_COMPLETE) { + WOLFSSL_MSG("Finished received out of order"); + return OUT_OF_ORDER_E; + } + if (ssl->options.serverState < + SERVER_ENCRYPTED_EXTENSIONS_COMPLETE) { + WOLFSSL_MSG("Finished received out of order"); + return OUT_OF_ORDER_E; + } + } + #endif + #ifndef NO_WOLFSSL_SERVER + if (ssl->options.side == WOLFSSL_SERVER_END) { + if (ssl->options.serverState < SERVER_FINISHED_COMPLETE) { + WOLFSSL_MSG("Finished received out of order"); + return OUT_OF_ORDER_E; + } + if (ssl->options.clientState < CLIENT_HELLO_COMPLETE) { + WOLFSSL_MSG("Finished received out of order"); + return OUT_OF_ORDER_E; + } + #ifdef WOLFSSL_EARLY_DATA + if (ssl->earlyData == process_early_data) { + return OUT_OF_ORDER_E; + } + #endif + } + #endif + if (ssl->msgsReceived.got_finished) { + WOLFSSL_MSG("Duplicate Finished received"); + return DUPLICATE_MSG_E; + } + ssl->msgsReceived.got_finished = 1; + + break; + + case key_update: + if (!ssl->msgsReceived.got_finished) { + WOLFSSL_MSG("No KeyUpdate before Finished"); + return OUT_OF_ORDER_E; + } + break; + + default: + WOLFSSL_MSG("Unknown message type"); + return SANITY_MSG_E; + } + + return 0; +} + +/* Handle a type of handshake message that has been received. + * + * ssl The SSL/TLS object. + * input The message buffer. + * inOutIdx On entry, the index into the buffer of the current message. + * On exit, the index into the buffer of the next message. + * size The length of the current handshake message. + * totalSz Length of remaining data in the message buffer. + * returns 0 on success and otherwise failure. + */ +int DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input, word32* inOutIdx, + byte type, word32 size, word32 totalSz) +{ + int ret = 0; + word32 inIdx = *inOutIdx; + + (void)totalSz; + + WOLFSSL_ENTER("DoTls13HandShakeMsgType"); + + /* make sure we can read the message */ + if (*inOutIdx + size > totalSz) + return INCOMPLETE_DATA; + + /* sanity check msg received */ + if ((ret = SanityCheckTls13MsgReceived(ssl, type)) != 0) { + WOLFSSL_MSG("Sanity Check on handshake message type received failed"); + SendAlert(ssl, alert_fatal, unexpected_message); + return ret; + } + +#ifdef WOLFSSL_CALLBACKS + /* add name later, add on record and handshake header part back on */ + if (ssl->toInfoOn) { + int add = RECORD_HEADER_SZ + HANDSHAKE_HEADER_SZ; + AddPacketInfo(ssl, 0, handshake, input + *inOutIdx - add, + size + add, READ_PROTO, ssl->heap); + AddLateRecordHeader(&ssl->curRL, &ssl->timeoutInfo); + } +#endif + + if (ssl->options.handShakeState == HANDSHAKE_DONE && + type != session_ticket && type != certificate_request && + type != certificate && type != key_update) { + WOLFSSL_MSG("HandShake message after handshake complete"); + SendAlert(ssl, alert_fatal, unexpected_message); + return OUT_OF_ORDER_E; + } + + if (ssl->options.side == WOLFSSL_CLIENT_END && + ssl->options.serverState == NULL_STATE && + type != server_hello && type != hello_retry_request) { + WOLFSSL_MSG("First server message not server hello"); + SendAlert(ssl, alert_fatal, unexpected_message); + return OUT_OF_ORDER_E; + } + + if (ssl->options.side == WOLFSSL_SERVER_END && + ssl->options.clientState == NULL_STATE && type != client_hello) { + WOLFSSL_MSG("First client message not client hello"); + SendAlert(ssl, alert_fatal, unexpected_message); + return OUT_OF_ORDER_E; + } + + /* above checks handshake state */ + switch (type) { +#ifndef NO_WOLFSSL_CLIENT + /* Messages only received by client. */ + #ifdef WOLFSSL_TLS13_DRAFT_18 + case hello_retry_request: + WOLFSSL_MSG("processing hello retry request"); + ret = DoTls13HelloRetryRequest(ssl, input, inOutIdx, size); + break; + #endif + + case server_hello: + WOLFSSL_MSG("processing server hello"); + ret = DoTls13ServerHello(ssl, input, inOutIdx, size, &type); + #if !defined(WOLFSSL_NO_CLIENT_AUTH) && defined(HAVE_ED25519) && \ + !defined(NO_ED25519_CLIENT_AUTH) + if (ssl->options.resuming || !IsAtLeastTLSv1_2(ssl) || + IsAtLeastTLSv1_3(ssl->version)) { + ssl->options.cacheMessages = 0; + if (ssl->hsHashes->messages != NULL) { + XFREE(ssl->hsHashes->messages, ssl->heap, DYNAMIC_TYPE_HASHES); + ssl->hsHashes->messages = NULL; + } + } + #endif + break; + + case encrypted_extensions: + WOLFSSL_MSG("processing encrypted extensions"); + ret = DoTls13EncryptedExtensions(ssl, input, inOutIdx, size); + break; + + #ifndef NO_CERTS + case certificate_request: + WOLFSSL_MSG("processing certificate request"); + ret = DoTls13CertificateRequest(ssl, input, inOutIdx, size); + break; + #endif + + case session_ticket: + WOLFSSL_MSG("processing new session ticket"); + ret = DoTls13NewSessionTicket(ssl, input, inOutIdx, size); + break; +#endif /* !NO_WOLFSSL_CLIENT */ + +#ifndef NO_WOLFSSL_SERVER + /* Messages only received by server. */ + case client_hello: + WOLFSSL_MSG("processing client hello"); + ret = DoTls13ClientHello(ssl, input, inOutIdx, size); + break; + + #ifdef WOLFSSL_EARLY_DATA + case end_of_early_data: + WOLFSSL_MSG("processing end of early data"); + ret = DoTls13EndOfEarlyData(ssl, input, inOutIdx, size); + break; + #endif +#endif /* !NO_WOLFSSL_SERVER */ + + /* Messages received by both client and server. */ +#ifndef NO_CERTS + case certificate: + WOLFSSL_MSG("processing certificate"); + ret = DoTls13Certificate(ssl, input, inOutIdx, size); + break; +#endif + +#if !defined(NO_RSA) || defined(HAVE_ECC) || defined(HAVE_ED25519) + case certificate_verify: + WOLFSSL_MSG("processing certificate verify"); + ret = DoTls13CertificateVerify(ssl, input, inOutIdx, size); + break; +#endif /* !NO_RSA || HAVE_ECC */ + + case finished: + WOLFSSL_MSG("processing finished"); + ret = DoTls13Finished(ssl, input, inOutIdx, size, totalSz, NO_SNIFF); + break; + + case key_update: + WOLFSSL_MSG("processing finished"); + ret = DoTls13KeyUpdate(ssl, input, inOutIdx, size); + break; + + default: + WOLFSSL_MSG("Unknown handshake message type"); + ret = UNKNOWN_HANDSHAKE_TYPE; + break; + } + + /* reset error */ + if (ret == 0 && ssl->error == WC_PENDING_E) + ssl->error = 0; + + if (ret == 0 && type != client_hello && type != session_ticket && + type != key_update) { + ret = HashInput(ssl, input + inIdx, size); + } + if (ret == 0 && ssl->buffers.inputBuffer.dynamicFlag) { + ShrinkInputBuffer(ssl, NO_FORCED_FREE); + } + + if (ret == BUFFER_ERROR || ret == MISSING_HANDSHAKE_DATA) + SendAlert(ssl, alert_fatal, decode_error); + else if (ret == EXT_NOT_ALLOWED || ret == PEER_KEY_ERROR || + ret == ECC_PEERKEY_ERROR || ret == BAD_KEY_SHARE_DATA || + ret == PSK_KEY_ERROR || ret == INVALID_PARAMETER) { + SendAlert(ssl, alert_fatal, illegal_parameter); + } + + if (ssl->options.tls1_3) { + /* Need to hash input message before deriving secrets. */ + #ifndef NO_WOLFSSL_CLIENT + if (ssl->options.side == WOLFSSL_CLIENT_END) { + if (type == server_hello) { + if ((ret = DeriveEarlySecret(ssl)) != 0) + return ret; + if ((ret = DeriveHandshakeSecret(ssl)) != 0) + return ret; + + if ((ret = DeriveTls13Keys(ssl, handshake_key, + ENCRYPT_AND_DECRYPT_SIDE, 1)) != 0) { + return ret; + } + #ifdef WOLFSSL_EARLY_DATA + if ((ret = SetKeysSide(ssl, DECRYPT_SIDE_ONLY)) != 0) + return ret; + #else + if ((ret = SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE)) != 0) + return ret; + #endif + } + + if (type == finished) { + if ((ret = DeriveMasterSecret(ssl)) != 0) + return ret; + #ifdef WOLFSSL_EARLY_DATA + if ((ret = DeriveTls13Keys(ssl, traffic_key, + ENCRYPT_AND_DECRYPT_SIDE, + ssl->earlyData == no_early_data)) != 0) { + return ret; + } + #else + if ((ret = DeriveTls13Keys(ssl, traffic_key, + ENCRYPT_AND_DECRYPT_SIDE, 1)) != 0) { + return ret; + } + #endif + } + #ifdef WOLFSSL_POST_HANDSHAKE_AUTH + if (type == certificate_request && + ssl->options.handShakeState == HANDSHAKE_DONE) { + /* reset handshake states */ + ssl->options.clientState = CLIENT_HELLO_COMPLETE; + ssl->options.connectState = FIRST_REPLY_DONE; + ssl->options.handShakeState = CLIENT_HELLO_COMPLETE; + + if (wolfSSL_connect_TLSv13(ssl) != SSL_SUCCESS) + ret = POST_HAND_AUTH_ERROR; + } + #endif + } + #endif /* NO_WOLFSSL_CLIENT */ + +#ifndef NO_WOLFSSL_SERVER + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + if (ssl->options.side == WOLFSSL_SERVER_END && type == finished) { + ret = DeriveResumptionSecret(ssl, ssl->session.masterSecret); + if (ret != 0) + return ret; + } + #endif +#endif /* NO_WOLFSSL_SERVER */ + } + +#ifdef WOLFSSL_ASYNC_CRYPT + /* if async, offset index so this msg will be processed again */ + if (ret == WC_PENDING_E && *inOutIdx > 0) { + *inOutIdx -= HANDSHAKE_HEADER_SZ; + } +#endif + + WOLFSSL_LEAVE("DoTls13HandShakeMsgType()", ret); + return ret; +} + + +/* Handle a handshake message that has been received. + * + * ssl The SSL/TLS object. + * input The message buffer. + * inOutIdx On entry, the index into the buffer of the current message. + * On exit, the index into the buffer of the next message. + * totalSz Length of remaining data in the message buffer. + * returns 0 on success and otherwise failure. + */ +int DoTls13HandShakeMsg(WOLFSSL* ssl, byte* input, word32* inOutIdx, + word32 totalSz) +{ + int ret = 0; + word32 inputLength; + + WOLFSSL_ENTER("DoTls13HandShakeMsg()"); + + if (ssl->arrays == NULL) { + byte type; + word32 size; + + if (GetHandshakeHeader(ssl, input, inOutIdx, &type, &size, + totalSz) != 0) { + SendAlert(ssl, alert_fatal, unexpected_message); + return PARSE_ERROR; + } + + return DoTls13HandShakeMsgType(ssl, input, inOutIdx, type, size, + totalSz); + } + + inputLength = ssl->buffers.inputBuffer.length - *inOutIdx - ssl->keys.padSz; + + /* If there is a pending fragmented handshake message, + * pending message size will be non-zero. */ + if (ssl->arrays->pendingMsgSz == 0) { + byte type; + word32 size; + + if (GetHandshakeHeader(ssl,input, inOutIdx, &type, &size, totalSz) != 0) + return PARSE_ERROR; + + /* Cap the maximum size of a handshake message to something reasonable. + * By default is the maximum size of a certificate message assuming + * nine 2048-bit RSA certificates in the chain. */ + if (size > MAX_HANDSHAKE_SZ) { + WOLFSSL_MSG("Handshake message too large"); + return HANDSHAKE_SIZE_ERROR; + } + + /* size is the size of the certificate message payload */ + if (inputLength - HANDSHAKE_HEADER_SZ < size) { + ssl->arrays->pendingMsgType = type; + ssl->arrays->pendingMsgSz = size + HANDSHAKE_HEADER_SZ; + ssl->arrays->pendingMsg = (byte*)XMALLOC(size + HANDSHAKE_HEADER_SZ, + ssl->heap, + DYNAMIC_TYPE_ARRAYS); + if (ssl->arrays->pendingMsg == NULL) + return MEMORY_E; + XMEMCPY(ssl->arrays->pendingMsg, + input + *inOutIdx - HANDSHAKE_HEADER_SZ, + inputLength); + ssl->arrays->pendingMsgOffset = inputLength; + *inOutIdx += inputLength + ssl->keys.padSz - HANDSHAKE_HEADER_SZ; + return 0; + } + + ret = DoTls13HandShakeMsgType(ssl, input, inOutIdx, type, size, + totalSz); + } + else { + if (inputLength + ssl->arrays->pendingMsgOffset > + ssl->arrays->pendingMsgSz) { + inputLength = ssl->arrays->pendingMsgSz - + ssl->arrays->pendingMsgOffset; + } + XMEMCPY(ssl->arrays->pendingMsg + ssl->arrays->pendingMsgOffset, + input + *inOutIdx, inputLength); + ssl->arrays->pendingMsgOffset += inputLength; + *inOutIdx += inputLength + ssl->keys.padSz; + + if (ssl->arrays->pendingMsgOffset == ssl->arrays->pendingMsgSz) + { + word32 idx = 0; + ret = DoTls13HandShakeMsgType(ssl, + ssl->arrays->pendingMsg + HANDSHAKE_HEADER_SZ, + &idx, ssl->arrays->pendingMsgType, + ssl->arrays->pendingMsgSz - HANDSHAKE_HEADER_SZ, + ssl->arrays->pendingMsgSz); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + /* setup to process fragment again */ + ssl->arrays->pendingMsgOffset -= inputLength; + *inOutIdx -= inputLength + ssl->keys.padSz; + } + else + #endif + { + XFREE(ssl->arrays->pendingMsg, ssl->heap, DYNAMIC_TYPE_ARRAYS); + ssl->arrays->pendingMsg = NULL; + ssl->arrays->pendingMsgSz = 0; + } + } + } + + WOLFSSL_LEAVE("DoTls13HandShakeMsg()", ret); + return ret; +} + +#ifndef NO_WOLFSSL_CLIENT + +/* The client connecting to the server. + * The protocol version is expecting to be TLS v1.3. + * If the server downgrades, and older versions of the protocol are compiled + * in, the client will fallback to wolfSSL_connect(). + * Please see note at top of README if you get an error from connect. + * + * ssl The SSL/TLS object. + * returns WOLFSSL_SUCCESS on successful handshake, WOLFSSL_FATAL_ERROR when + * unrecoverable error occurs and 0 otherwise. + * For more error information use wolfSSL_get_error(). + */ +int wolfSSL_connect_TLSv13(WOLFSSL* ssl) +{ + WOLFSSL_ENTER("wolfSSL_connect_TLSv13()"); + + #ifdef HAVE_ERRNO_H + errno = 0; + #endif + + if (ssl->options.side != WOLFSSL_CLIENT_END) { + WOLFSSL_ERROR(ssl->error = SIDE_ERROR); + return WOLFSSL_FATAL_ERROR; + } + + if (ssl->buffers.outputBuffer.length > 0) { + if ((ssl->error = SendBuffered(ssl)) == 0) { + /* fragOffset is non-zero when sending fragments. On the last + * fragment, fragOffset is zero again, and the state can be + * advanced. */ + if (ssl->fragOffset == 0) { + ssl->options.connectState++; + WOLFSSL_MSG("connect state: " + "Advanced from last buffered fragment send"); + } + else { + WOLFSSL_MSG("connect state: " + "Not advanced, more fragments to send"); + } + } + else { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } + + switch (ssl->options.connectState) { + + case CONNECT_BEGIN: + /* Always send client hello first. */ + if ((ssl->error = SendTls13ClientHello(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + + ssl->options.connectState = CLIENT_HELLO_SENT; + WOLFSSL_MSG("connect state: CLIENT_HELLO_SENT"); + #ifdef WOLFSSL_EARLY_DATA + if (ssl->earlyData != no_early_data) { + #if !defined(WOLFSSL_TLS13_DRAFT_18) && \ + defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT) + if ((ssl->error = SendChangeCipher(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + ssl->options.sentChangeCipher = 1; + #endif + ssl->options.handShakeState = CLIENT_HELLO_COMPLETE; + return WOLFSSL_SUCCESS; + } + #endif + FALL_THROUGH; + + case CLIENT_HELLO_SENT: + /* Get the response/s from the server. */ + while (ssl->options.serverState < + SERVER_HELLO_RETRY_REQUEST_COMPLETE) { + if ((ssl->error = ProcessReply(ssl)) < 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } + + ssl->options.connectState = HELLO_AGAIN; + WOLFSSL_MSG("connect state: HELLO_AGAIN"); + FALL_THROUGH; + + case HELLO_AGAIN: + if (ssl->options.certOnly) + return WOLFSSL_SUCCESS; + + if (!ssl->options.tls1_3) { + #ifndef WOLFSSL_NO_TLS12 + if (ssl->options.downgrade) + return wolfSSL_connect(ssl); + #endif + + WOLFSSL_MSG("Client using higher version, fatal error"); + return VERSION_ERROR; + } + + if (ssl->options.serverState == + SERVER_HELLO_RETRY_REQUEST_COMPLETE) { + #if !defined(WOLFSSL_TLS13_DRAFT_18) && \ + defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT) + if (!ssl->options.sentChangeCipher) { + if ((ssl->error = SendChangeCipher(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + ssl->options.sentChangeCipher = 1; + } + #endif + /* Try again with different security parameters. */ + if ((ssl->error = SendTls13ClientHello(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } + + ssl->options.connectState = HELLO_AGAIN_REPLY; + WOLFSSL_MSG("connect state: HELLO_AGAIN_REPLY"); + FALL_THROUGH; + + case HELLO_AGAIN_REPLY: + /* Get the response/s from the server. */ + while (ssl->options.serverState < SERVER_FINISHED_COMPLETE) { + if ((ssl->error = ProcessReply(ssl)) < 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } + + ssl->options.connectState = FIRST_REPLY_DONE; + WOLFSSL_MSG("connect state: FIRST_REPLY_DONE"); + FALL_THROUGH; + + case FIRST_REPLY_DONE: + #ifdef WOLFSSL_EARLY_DATA + if (ssl->earlyData != no_early_data) { + if ((ssl->error = SendTls13EndOfEarlyData(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + WOLFSSL_MSG("sent: end_of_early_data"); + } + #endif + + ssl->options.connectState = FIRST_REPLY_FIRST; + WOLFSSL_MSG("connect state: FIRST_REPLY_FIRST"); + FALL_THROUGH; + + case FIRST_REPLY_FIRST: + #if !defined(WOLFSSL_TLS13_DRAFT_18) && \ + defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT) + if (!ssl->options.sentChangeCipher) { + if ((ssl->error = SendChangeCipher(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + ssl->options.sentChangeCipher = 1; + } + #endif + + ssl->options.connectState = FIRST_REPLY_SECOND; + WOLFSSL_MSG("connect state: FIRST_REPLY_SECOND"); + FALL_THROUGH; + + case FIRST_REPLY_SECOND: + #ifndef NO_CERTS + if (!ssl->options.resuming && ssl->options.sendVerify) { + ssl->error = SendTls13Certificate(ssl); + if (ssl->error != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + WOLFSSL_MSG("sent: certificate"); + } + #endif + + ssl->options.connectState = FIRST_REPLY_THIRD; + WOLFSSL_MSG("connect state: FIRST_REPLY_THIRD"); + FALL_THROUGH; + + case FIRST_REPLY_THIRD: + #ifndef NO_CERTS + if (!ssl->options.resuming && ssl->options.sendVerify) { + ssl->error = SendTls13CertificateVerify(ssl); + if (ssl->error != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + WOLFSSL_MSG("sent: certificate verify"); + } + #endif + + ssl->options.connectState = FIRST_REPLY_FOURTH; + WOLFSSL_MSG("connect state: FIRST_REPLY_FOURTH"); + FALL_THROUGH; + + case FIRST_REPLY_FOURTH: + if ((ssl->error = SendTls13Finished(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + WOLFSSL_MSG("sent: finished"); + + ssl->options.connectState = FINISHED_DONE; + WOLFSSL_MSG("connect state: FINISHED_DONE"); + FALL_THROUGH; + + case FINISHED_DONE: + #ifndef NO_HANDSHAKE_DONE_CB + if (ssl->hsDoneCb != NULL) { + int cbret = ssl->hsDoneCb(ssl, ssl->hsDoneCtx); + if (cbret < 0) { + ssl->error = cbret; + WOLFSSL_MSG("HandShake Done Cb don't continue error"); + return WOLFSSL_FATAL_ERROR; + } + } + #endif /* NO_HANDSHAKE_DONE_CB */ + + if (!ssl->options.keepResources) { + FreeHandshakeResources(ssl); + } + + WOLFSSL_LEAVE("wolfSSL_connect_TLSv13()", WOLFSSL_SUCCESS); + return WOLFSSL_SUCCESS; + + default: + WOLFSSL_MSG("Unknown connect state ERROR"); + return WOLFSSL_FATAL_ERROR; /* unknown connect state */ + } +} +#endif + +#if defined(WOLFSSL_SEND_HRR_COOKIE) +/* Send a cookie with the HelloRetryRequest to avoid storing state. + * + * ssl SSL/TLS object. + * secret Secret to use when generating integrity check for cookie. + * A value of NULL indicates to generate a new random secret. + * secretSz Size of secret data in bytes. + * Use a value of 0 to indicate use of default size. + * returns BAD_FUNC_ARG when ssl is NULL or not using TLS v1.3, SIDE_ERROR when + * called on a client; WOLFSSL_SUCCESS on success and otherwise failure. + */ +int wolfSSL_send_hrr_cookie(WOLFSSL* ssl, const unsigned char* secret, + unsigned int secretSz) +{ + int ret; + + if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version)) + return BAD_FUNC_ARG; + #ifndef NO_WOLFSSL_SERVER + if (ssl->options.side == WOLFSSL_CLIENT_END) + return SIDE_ERROR; + + if (secretSz == 0) { + #if !defined(NO_SHA) && defined(NO_SHA256) + secretSz = WC_SHA_DIGEST_SIZE; + #endif /* NO_SHA */ + #ifndef NO_SHA256 + secretSz = WC_SHA256_DIGEST_SIZE; + #endif /* NO_SHA256 */ + } + + if (secretSz != ssl->buffers.tls13CookieSecret.length) { + byte* newSecret; + + if (ssl->buffers.tls13CookieSecret.buffer != NULL) { + ForceZero(ssl->buffers.tls13CookieSecret.buffer, + ssl->buffers.tls13CookieSecret.length); + XFREE(ssl->buffers.tls13CookieSecret.buffer, + ssl->heap, DYNAMIC_TYPE_COOKIE_PWD); + } + + newSecret = (byte*)XMALLOC(secretSz, ssl->heap, + DYNAMIC_TYPE_COOKIE_PWD); + if (newSecret == NULL) { + ssl->buffers.tls13CookieSecret.buffer = NULL; + ssl->buffers.tls13CookieSecret.length = 0; + WOLFSSL_MSG("couldn't allocate new cookie secret"); + return MEMORY_ERROR; + } + ssl->buffers.tls13CookieSecret.buffer = newSecret; + ssl->buffers.tls13CookieSecret.length = secretSz; + } + + /* If the supplied secret is NULL, randomly generate a new secret. */ + if (secret == NULL) { + ret = wc_RNG_GenerateBlock(ssl->rng, + ssl->buffers.tls13CookieSecret.buffer, secretSz); + if (ret < 0) + return ret; + } + else + XMEMCPY(ssl->buffers.tls13CookieSecret.buffer, secret, secretSz); + + ssl->options.sendCookie = 1; + + ret = WOLFSSL_SUCCESS; +#else + (void)secret; + (void)secretSz; + + ret = SIDE_ERROR; +#endif + + return ret; +} +#endif + +/* Create a key share entry from group. + * Generates a key pair. + * + * ssl The SSL/TLS object. + * group The named group. + * returns 0 on success, otherwise failure. + */ +int wolfSSL_UseKeyShare(WOLFSSL* ssl, word16 group) +{ + int ret; + + if (ssl == NULL) + return BAD_FUNC_ARG; + + ret = TLSX_KeyShare_Use(ssl, group, 0, NULL, NULL); + if (ret != 0) + return ret; + + return WOLFSSL_SUCCESS; +} + +/* Send no key share entries - use HelloRetryRequest to negotiate shared group. + * + * ssl The SSL/TLS object. + * returns 0 on success, otherwise failure. + */ +int wolfSSL_NoKeyShares(WOLFSSL* ssl) +{ + int ret; + + if (ssl == NULL) + return BAD_FUNC_ARG; + if (ssl->options.side == WOLFSSL_SERVER_END) + return SIDE_ERROR; + + ret = TLSX_KeyShare_Empty(ssl); + if (ret != 0) + return ret; + + return WOLFSSL_SUCCESS; +} + +/* Do not send a ticket after TLS v1.3 handshake for resumption. + * + * ctx The SSL/TLS CTX object. + * returns BAD_FUNC_ARG when ctx is NULL and 0 on success. + */ +int wolfSSL_CTX_no_ticket_TLSv13(WOLFSSL_CTX* ctx) +{ + if (ctx == NULL || !IsAtLeastTLSv1_3(ctx->method->version)) + return BAD_FUNC_ARG; + if (ctx->method->side == WOLFSSL_CLIENT_END) + return SIDE_ERROR; + +#ifdef HAVE_SESSION_TICKET + ctx->noTicketTls13 = 1; +#endif + + return 0; +} + +/* Do not send a ticket after TLS v1.3 handshake for resumption. + * + * ssl The SSL/TLS object. + * returns BAD_FUNC_ARG when ssl is NULL, not using TLS v1.3, or called on + * a client and 0 on success. + */ +int wolfSSL_no_ticket_TLSv13(WOLFSSL* ssl) +{ + if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version)) + return BAD_FUNC_ARG; + if (ssl->options.side == WOLFSSL_CLIENT_END) + return SIDE_ERROR; + +#ifdef HAVE_SESSION_TICKET + ssl->options.noTicketTls13 = 1; +#endif + + return 0; +} + +/* Disallow (EC)DHE key exchange when using pre-shared keys. + * + * ctx The SSL/TLS CTX object. + * returns BAD_FUNC_ARG when ctx is NULL and 0 on success. + */ +int wolfSSL_CTX_no_dhe_psk(WOLFSSL_CTX* ctx) +{ + if (ctx == NULL || !IsAtLeastTLSv1_3(ctx->method->version)) + return BAD_FUNC_ARG; + + ctx->noPskDheKe = 1; + + return 0; +} + +/* Disallow (EC)DHE key exchange when using pre-shared keys. + * + * ssl The SSL/TLS object. + * returns BAD_FUNC_ARG when ssl is NULL, or not using TLS v1.3 and 0 on + * success. + */ +int wolfSSL_no_dhe_psk(WOLFSSL* ssl) +{ + if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version)) + return BAD_FUNC_ARG; + + ssl->options.noPskDheKe = 1; + + return 0; +} + +/* Update the keys for encryption and decryption. + * If using non-blocking I/O and WOLFSSL_ERROR_WANT_WRITE is returned then + * calling wolfSSL_write() will have the message sent when ready. + * + * ssl The SSL/TLS object. + * returns BAD_FUNC_ARG when ssl is NULL, or not using TLS v1.3, + * WOLFSSL_ERROR_WANT_WRITE when non-blocking I/O is not ready to write, + * WOLFSSL_SUCCESS on success and otherwise failure. + */ +int wolfSSL_update_keys(WOLFSSL* ssl) +{ + int ret; + + if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version)) + return BAD_FUNC_ARG; + + ret = SendTls13KeyUpdate(ssl); + if (ret == WANT_WRITE) + ret = WOLFSSL_ERROR_WANT_WRITE; + else if (ret == 0) + ret = WOLFSSL_SUCCESS; + return ret; +} + +#if !defined(NO_CERTS) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) +/* Allow post-handshake authentication in TLS v1.3 connections. + * + * ctx The SSL/TLS CTX object. + * returns BAD_FUNC_ARG when ctx is NULL, SIDE_ERROR when not a client and + * 0 on success. + */ +int wolfSSL_CTX_allow_post_handshake_auth(WOLFSSL_CTX* ctx) +{ + if (ctx == NULL || !IsAtLeastTLSv1_3(ctx->method->version)) + return BAD_FUNC_ARG; + if (ctx->method->side == WOLFSSL_SERVER_END) + return SIDE_ERROR; + + ctx->postHandshakeAuth = 1; + + return 0; +} + +/* Allow post-handshake authentication in TLS v1.3 connection. + * + * ssl The SSL/TLS object. + * returns BAD_FUNC_ARG when ssl is NULL, or not using TLS v1.3, + * SIDE_ERROR when not a client and 0 on success. + */ +int wolfSSL_allow_post_handshake_auth(WOLFSSL* ssl) +{ + if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version)) + return BAD_FUNC_ARG; + if (ssl->options.side == WOLFSSL_SERVER_END) + return SIDE_ERROR; + + ssl->options.postHandshakeAuth = 1; + + return 0; +} + +/* Request a certificate of the client. + * Can be called any time after handshake completion. + * A maximum of 256 requests can be sent on a connection. + * + * ssl SSL/TLS object. + */ +int wolfSSL_request_certificate(WOLFSSL* ssl) +{ + int ret; +#ifndef NO_WOLFSSL_SERVER + CertReqCtx* certReqCtx; +#endif + + if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version)) + return BAD_FUNC_ARG; +#ifndef NO_WOLFSSL_SERVER + if (ssl->options.side == WOLFSSL_CLIENT_END) + return SIDE_ERROR; + if (ssl->options.handShakeState != HANDSHAKE_DONE) + return NOT_READY_ERROR; + if (!ssl->options.postHandshakeAuth) + return POST_HAND_AUTH_ERROR; + + certReqCtx = (CertReqCtx*)XMALLOC(sizeof(CertReqCtx), ssl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (certReqCtx == NULL) + return MEMORY_E; + XMEMSET(certReqCtx, 0, sizeof(CertReqCtx)); + certReqCtx->next = ssl->certReqCtx; + certReqCtx->len = 1; + if (certReqCtx->next != NULL) + certReqCtx->ctx = certReqCtx->next->ctx + 1; + ssl->certReqCtx = certReqCtx; + + ssl->msgsReceived.got_certificate = 0; + ssl->msgsReceived.got_certificate_verify = 0; + ssl->msgsReceived.got_finished = 0; + + ret = SendTls13CertificateRequest(ssl, &certReqCtx->ctx, certReqCtx->len); + if (ret == WANT_WRITE) + ret = WOLFSSL_ERROR_WANT_WRITE; + else if (ret == 0) + ret = WOLFSSL_SUCCESS; +#else + ret = SIDE_ERROR; +#endif + + return ret; +} +#endif /* !NO_CERTS && WOLFSSL_POST_HANDSHAKE_AUTH */ + +#if !defined(WOLFSSL_NO_SERVER_GROUPS_EXT) +/* Get the preferred key exchange group. + * + * ssl The SSL/TLS object. + * returns BAD_FUNC_ARG when ssl is NULL or not using TLS v1.3, + * SIDE_ERROR when not a client, NOT_READY_ERROR when handshake not complete + * and group number on success. + */ +int wolfSSL_preferred_group(WOLFSSL* ssl) +{ + if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version)) + return BAD_FUNC_ARG; +#ifndef NO_WOLFSSL_CLIENT + if (ssl->options.side == WOLFSSL_SERVER_END) + return SIDE_ERROR; + if (ssl->options.handShakeState != HANDSHAKE_DONE) + return NOT_READY_ERROR; + + /* Return supported groups only. */ + return TLSX_SupportedCurve_Preferred(ssl, 1); +#else + return SIDE_ERROR; +#endif +} +#endif + +/* Sets the key exchange groups in rank order on a context. + * + * ctx SSL/TLS context object. + * groups Array of groups. + * count Number of groups in array. + * returns BAD_FUNC_ARG when ctx or groups is NULL, not using TLS v1.3 or + * count is greater than WOLFSSL_MAX_GROUP_COUNT and WOLFSSL_SUCCESS on success. + */ +int wolfSSL_CTX_set_groups(WOLFSSL_CTX* ctx, int* groups, int count) +{ + int i; + + if (ctx == NULL || groups == NULL || count > WOLFSSL_MAX_GROUP_COUNT) + return BAD_FUNC_ARG; + if (!IsAtLeastTLSv1_3(ctx->method->version)) + return BAD_FUNC_ARG; + + for (i = 0; i < count; i++) + ctx->group[i] = (word16)groups[i]; + ctx->numGroups = (byte)count; + + return WOLFSSL_SUCCESS; +} + +/* Sets the key exchange groups in rank order. + * + * ssl SSL/TLS object. + * groups Array of groups. + * count Number of groups in array. + * returns BAD_FUNC_ARG when ssl or groups is NULL, not using TLS v1.3 or + * count is greater than WOLFSSL_MAX_GROUP_COUNT and WOLFSSL_SUCCESS on success. + */ +int wolfSSL_set_groups(WOLFSSL* ssl, int* groups, int count) +{ + int i; + + if (ssl == NULL || groups == NULL || count > WOLFSSL_MAX_GROUP_COUNT) + return BAD_FUNC_ARG; + if (!IsAtLeastTLSv1_3(ssl->version)) + return BAD_FUNC_ARG; + + for (i = 0; i < count; i++) + ssl->group[i] = (word16)groups[i]; + ssl->numGroups = (byte)count; + + return WOLFSSL_SUCCESS; +} + +#ifndef NO_PSK +void wolfSSL_CTX_set_psk_client_tls13_callback(WOLFSSL_CTX* ctx, + wc_psk_client_tls13_callback cb) +{ + WOLFSSL_ENTER("SSL_CTX_set_psk_client_tls13_callback"); + + if (ctx == NULL) + return; + + ctx->havePSK = 1; + ctx->client_psk_tls13_cb = cb; +} + + +void wolfSSL_set_psk_client_tls13_callback(WOLFSSL* ssl, + wc_psk_client_tls13_callback cb) +{ + byte haveRSA = 1; + int keySz = 0; + + WOLFSSL_ENTER("SSL_set_psk_client_tls13_callback"); + + if (ssl == NULL) + return; + + ssl->options.havePSK = 1; + ssl->options.client_psk_tls13_cb = cb; + + #ifdef NO_RSA + haveRSA = 0; + #endif + #ifndef NO_CERTS + keySz = ssl->buffers.keySz; + #endif + InitSuites(ssl->suites, ssl->version, keySz, haveRSA, TRUE, + ssl->options.haveDH, ssl->options.haveNTRU, + ssl->options.haveECDSAsig, ssl->options.haveECC, + ssl->options.haveStaticECC, ssl->options.side); +} + + +void wolfSSL_CTX_set_psk_server_tls13_callback(WOLFSSL_CTX* ctx, + wc_psk_server_tls13_callback cb) +{ + WOLFSSL_ENTER("SSL_CTX_set_psk_server_tls13_callback"); + if (ctx == NULL) + return; + ctx->havePSK = 1; + ctx->server_psk_tls13_cb = cb; +} + + +void wolfSSL_set_psk_server_tls13_callback(WOLFSSL* ssl, + wc_psk_server_tls13_callback cb) +{ + byte haveRSA = 1; + int keySz = 0; + + WOLFSSL_ENTER("SSL_set_psk_server_tls13_callback"); + if (ssl == NULL) + return; + + ssl->options.havePSK = 1; + ssl->options.server_psk_tls13_cb = cb; + + #ifdef NO_RSA + haveRSA = 0; + #endif + #ifndef NO_CERTS + keySz = ssl->buffers.keySz; + #endif + InitSuites(ssl->suites, ssl->version, keySz, haveRSA, TRUE, + ssl->options.haveDH, ssl->options.haveNTRU, + ssl->options.haveECDSAsig, ssl->options.haveECC, + ssl->options.haveStaticECC, ssl->options.side); +} +#endif + + +#ifndef NO_WOLFSSL_SERVER +/* The server accepting a connection from a client. + * The protocol version is expecting to be TLS v1.3. + * If the client downgrades, and older versions of the protocol are compiled + * in, the server will fallback to wolfSSL_accept(). + * Please see note at top of README if you get an error from accept. + * + * ssl The SSL/TLS object. + * returns WOLFSSL_SUCCESS on successful handshake, WOLFSSL_FATAL_ERROR when + * unrecoverable error occurs and 0 otherwise. + * For more error information use wolfSSL_get_error(). + */ +int wolfSSL_accept_TLSv13(WOLFSSL* ssl) +{ + word16 havePSK = 0; + WOLFSSL_ENTER("SSL_accept_TLSv13()"); + +#ifdef HAVE_ERRNO_H + errno = 0; +#endif + +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + havePSK = ssl->options.havePSK; +#endif + (void)havePSK; + + if (ssl->options.side != WOLFSSL_SERVER_END) { + WOLFSSL_ERROR(ssl->error = SIDE_ERROR); + return WOLFSSL_FATAL_ERROR; + } + +#ifndef NO_CERTS + /* allow no private key if using PK callbacks and CB is set */ + if (!havePSK) { + if (!ssl->buffers.certificate || + !ssl->buffers.certificate->buffer) { + + WOLFSSL_MSG("accept error: server cert required"); + WOLFSSL_ERROR(ssl->error = NO_PRIVATE_KEY); + return WOLFSSL_FATAL_ERROR; + } + + #ifdef HAVE_PK_CALLBACKS + if (wolfSSL_CTX_IsPrivatePkSet(ssl->ctx)) { + WOLFSSL_MSG("Using PK for server private key"); + } + else + #endif + if (!ssl->buffers.key || !ssl->buffers.key->buffer) { + WOLFSSL_MSG("accept error: server key required"); + WOLFSSL_ERROR(ssl->error = NO_PRIVATE_KEY); + return WOLFSSL_FATAL_ERROR; + } + } +#endif + + if (ssl->buffers.outputBuffer.length > 0) { + if ((ssl->error = SendBuffered(ssl)) == 0) { + /* fragOffset is non-zero when sending fragments. On the last + * fragment, fragOffset is zero again, and the state can be + * advanced. */ + if (ssl->fragOffset == 0) { + ssl->options.acceptState++; + WOLFSSL_MSG("accept state: " + "Advanced from last buffered fragment send"); + } + else { + WOLFSSL_MSG("accept state: " + "Not advanced, more fragments to send"); + } + } + else { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } + + switch (ssl->options.acceptState) { + + case TLS13_ACCEPT_BEGIN : + /* get client_hello */ + while (ssl->options.clientState < CLIENT_HELLO_COMPLETE) { + if ((ssl->error = ProcessReply(ssl)) < 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } + + ssl->options.acceptState = TLS13_ACCEPT_CLIENT_HELLO_DONE; + WOLFSSL_MSG("accept state ACCEPT_CLIENT_HELLO_DONE"); + if (!IsAtLeastTLSv1_3(ssl->version)) + return wolfSSL_accept(ssl); + FALL_THROUGH; + + case TLS13_ACCEPT_CLIENT_HELLO_DONE : +#ifdef WOLFSSL_TLS13_DRAFT_18 + if (ssl->options.serverState == + SERVER_HELLO_RETRY_REQUEST_COMPLETE) { + if ((ssl->error = SendTls13HelloRetryRequest(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } + + ssl->options.acceptState = TLS13_ACCEPT_FIRST_REPLY_DONE; + WOLFSSL_MSG("accept state ACCEPT_FIRST_REPLY_DONE"); + FALL_THROUGH; + + case TLS13_ACCEPT_HELLO_RETRY_REQUEST_DONE : +#else + if (ssl->options.serverState == + SERVER_HELLO_RETRY_REQUEST_COMPLETE) { + if ((ssl->error = SendTls13ServerHello(ssl, + hello_retry_request)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } + + ssl->options.acceptState = TLS13_ACCEPT_HELLO_RETRY_REQUEST_DONE; + WOLFSSL_MSG("accept state ACCEPT_HELLO_RETRY_REQUEST_DONE"); + FALL_THROUGH; + + case TLS13_ACCEPT_HELLO_RETRY_REQUEST_DONE : + #ifdef WOLFSSL_TLS13_MIDDLEBOX_COMPAT + if (ssl->options.serverState == + SERVER_HELLO_RETRY_REQUEST_COMPLETE) { + if ((ssl->error = SendChangeCipher(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + ssl->options.sentChangeCipher = 1; + ssl->options.serverState = SERVER_HELLO_RETRY_REQUEST_COMPLETE; + } + #endif + ssl->options.acceptState = TLS13_ACCEPT_FIRST_REPLY_DONE; + WOLFSSL_MSG("accept state ACCEPT_FIRST_REPLY_DONE"); + FALL_THROUGH; +#endif + + case TLS13_ACCEPT_FIRST_REPLY_DONE : + if (ssl->options.serverState == + SERVER_HELLO_RETRY_REQUEST_COMPLETE) { + ssl->options.clientState = CLIENT_HELLO_RETRY; + while (ssl->options.clientState < CLIENT_HELLO_COMPLETE) { + if ((ssl->error = ProcessReply(ssl)) < 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } + } + + ssl->options.acceptState = TLS13_ACCEPT_SECOND_REPLY_DONE; + WOLFSSL_MSG("accept state ACCEPT_SECOND_REPLY_DONE"); + FALL_THROUGH; + + case TLS13_ACCEPT_SECOND_REPLY_DONE : + if ((ssl->error = SendTls13ServerHello(ssl, server_hello)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + ssl->options.acceptState = TLS13_SERVER_HELLO_SENT; + WOLFSSL_MSG("accept state SERVER_HELLO_SENT"); + FALL_THROUGH; + + case TLS13_SERVER_HELLO_SENT : + #if !defined(WOLFSSL_TLS13_DRAFT_18) && \ + defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT) + if (!ssl->options.sentChangeCipher) { + if ((ssl->error = SendChangeCipher(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + ssl->options.sentChangeCipher = 1; + } + #endif + + ssl->options.acceptState = TLS13_ACCEPT_THIRD_REPLY_DONE; + WOLFSSL_MSG("accept state ACCEPT_THIRD_REPLY_DONE"); + FALL_THROUGH; + + case TLS13_ACCEPT_THIRD_REPLY_DONE : + if (!ssl->options.noPskDheKe) { + ssl->error = TLSX_KeyShare_DeriveSecret(ssl); + if (ssl->error != 0) + return WOLFSSL_FATAL_ERROR; + } + + if ((ssl->error = SendTls13EncryptedExtensions(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + ssl->options.acceptState = TLS13_SERVER_EXTENSIONS_SENT; + WOLFSSL_MSG("accept state SERVER_EXTENSIONS_SENT"); + FALL_THROUGH; + + case TLS13_SERVER_EXTENSIONS_SENT : +#ifndef NO_CERTS + if (!ssl->options.resuming) { + if (ssl->options.verifyPeer) { + ssl->error = SendTls13CertificateRequest(ssl, NULL, 0); + if (ssl->error != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } + } +#endif + ssl->options.acceptState = TLS13_CERT_REQ_SENT; + WOLFSSL_MSG("accept state CERT_REQ_SENT"); + FALL_THROUGH; + + case TLS13_CERT_REQ_SENT : +#ifndef NO_CERTS + if (!ssl->options.resuming && ssl->options.sendVerify) { + if ((ssl->error = SendTls13Certificate(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } +#endif + ssl->options.acceptState = TLS13_CERT_SENT; + WOLFSSL_MSG("accept state CERT_SENT"); + FALL_THROUGH; + + case TLS13_CERT_SENT : +#ifndef NO_CERTS + if (!ssl->options.resuming && ssl->options.sendVerify) { + if ((ssl->error = SendTls13CertificateVerify(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } +#endif + ssl->options.acceptState = TLS13_CERT_VERIFY_SENT; + WOLFSSL_MSG("accept state CERT_VERIFY_SENT"); + FALL_THROUGH; + + case TLS13_CERT_VERIFY_SENT : + if ((ssl->error = SendTls13Finished(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + + ssl->options.acceptState = TLS13_ACCEPT_FINISHED_SENT; + WOLFSSL_MSG("accept state ACCEPT_FINISHED_SENT"); +#ifdef WOLFSSL_EARLY_DATA + if (ssl->earlyData != no_early_data) { + ssl->options.handShakeState = SERVER_FINISHED_COMPLETE; + return WOLFSSL_SUCCESS; + } +#endif + FALL_THROUGH; + + case TLS13_ACCEPT_FINISHED_SENT : +#ifdef HAVE_SESSION_TICKET + #ifdef WOLFSSL_TLS13_TICKET_BEFORE_FINISHED + if (!ssl->options.verifyPeer && !ssl->options.noTicketTls13 && + ssl->ctx->ticketEncCb != NULL) { + if ((ssl->error = SendTls13NewSessionTicket(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } + #endif +#endif /* HAVE_SESSION_TICKET */ + ssl->options.acceptState = TLS13_PRE_TICKET_SENT; + WOLFSSL_MSG("accept state TICKET_SENT"); + FALL_THROUGH; + + case TLS13_PRE_TICKET_SENT : + while (ssl->options.clientState < CLIENT_FINISHED_COMPLETE) + if ( (ssl->error = ProcessReply(ssl)) < 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + + ssl->options.acceptState = TLS13_ACCEPT_FINISHED_DONE; + WOLFSSL_MSG("accept state ACCEPT_FINISHED_DONE"); + FALL_THROUGH; + + case TLS13_ACCEPT_FINISHED_DONE : +#ifdef HAVE_SESSION_TICKET + #ifdef WOLFSSL_TLS13_TICKET_BEFORE_FINISHED + if (!ssl->options.verifyPeer) { + } + else + #endif + if (!ssl->options.noTicketTls13 && ssl->ctx->ticketEncCb != NULL) { + if ((ssl->error = SendTls13NewSessionTicket(ssl)) != 0) { + WOLFSSL_ERROR(ssl->error); + return WOLFSSL_FATAL_ERROR; + } + } +#endif /* HAVE_SESSION_TICKET */ + ssl->options.acceptState = TLS13_TICKET_SENT; + WOLFSSL_MSG("accept state TICKET_SENT"); + FALL_THROUGH; + + case TLS13_TICKET_SENT : +#ifndef NO_HANDSHAKE_DONE_CB + if (ssl->hsDoneCb) { + int cbret = ssl->hsDoneCb(ssl, ssl->hsDoneCtx); + if (cbret < 0) { + ssl->error = cbret; + WOLFSSL_MSG("HandShake Done Cb don't continue error"); + return WOLFSSL_FATAL_ERROR; + } + } +#endif /* NO_HANDSHAKE_DONE_CB */ + + if (!ssl->options.keepResources) { + FreeHandshakeResources(ssl); + } + + WOLFSSL_LEAVE("SSL_accept()", WOLFSSL_SUCCESS); + return WOLFSSL_SUCCESS; + + default : + WOLFSSL_MSG("Unknown accept state ERROR"); + return WOLFSSL_FATAL_ERROR; + } +} +#endif + +#ifdef WOLFSSL_EARLY_DATA +/* Sets the maximum amount of early data that can be seen by server when using + * session tickets for resumption. + * A value of zero indicates no early data is to be sent by client using session + * tickets. + * + * ctx The SSL/TLS CTX object. + * sz Maximum size of the early data. + * returns BAD_FUNC_ARG when ctx is NULL, SIDE_ERROR when not a server and + * 0 on success. + */ +int wolfSSL_CTX_set_max_early_data(WOLFSSL_CTX* ctx, unsigned int sz) +{ + if (ctx == NULL || !IsAtLeastTLSv1_3(ctx->method->version)) + return BAD_FUNC_ARG; + if (ctx->method->side == WOLFSSL_CLIENT_END) + return SIDE_ERROR; + + ctx->maxEarlyDataSz = sz; + + return 0; +} + +/* Sets the maximum amount of early data that can be seen by server when using + * session tickets for resumption. + * A value of zero indicates no early data is to be sent by client using session + * tickets. + * + * ssl The SSL/TLS object. + * sz Maximum size of the early data. + * returns BAD_FUNC_ARG when ssl is NULL, or not using TLS v1.3, + * SIDE_ERROR when not a server and 0 on success. + */ +int wolfSSL_set_max_early_data(WOLFSSL* ssl, unsigned int sz) +{ + if (ssl == NULL || !IsAtLeastTLSv1_3(ssl->version)) + return BAD_FUNC_ARG; + if (ssl->options.side == WOLFSSL_CLIENT_END) + return SIDE_ERROR; + + ssl->options.maxEarlyDataSz = sz; + + return 0; +} + +/* Write early data to the server. + * + * ssl The SSL/TLS object. + * data Early data to write + * sz The size of the eary data in bytes. + * outSz The number of early data bytes written. + * returns BAD_FUNC_ARG when: ssl, data or outSz is NULL; sz is negative; + * or not using TLS v1.3. SIDE ERROR when not a server. Otherwise the number of + * early data bytes written. + */ +int wolfSSL_write_early_data(WOLFSSL* ssl, const void* data, int sz, int* outSz) +{ + int ret = 0; + + WOLFSSL_ENTER("SSL_write_early_data()"); + + if (ssl == NULL || data == NULL || sz < 0 || outSz == NULL) + return BAD_FUNC_ARG; + if (!IsAtLeastTLSv1_3(ssl->version)) + return BAD_FUNC_ARG; + +#ifndef NO_WOLFSSL_CLIENT + if (ssl->options.side == WOLFSSL_SERVER_END) + return SIDE_ERROR; + + if (ssl->options.handShakeState == NULL_STATE) { + ssl->earlyData = expecting_early_data; + ret = wolfSSL_connect_TLSv13(ssl); + if (ret != WOLFSSL_SUCCESS) + return WOLFSSL_FATAL_ERROR; + } + if (ssl->options.handShakeState == CLIENT_HELLO_COMPLETE) { + ret = SendData(ssl, data, sz); + if (ret > 0) + *outSz = ret; + } +#else + return SIDE_ERROR; +#endif + + WOLFSSL_LEAVE("SSL_write_early_data()", ret); + + if (ret < 0) + ret = WOLFSSL_FATAL_ERROR; + return ret; +} + +/* Read the any early data from the client. + * + * ssl The SSL/TLS object. + * data Buffer to put the early data into. + * sz The size of the buffer in bytes. + * outSz The number of early data bytes read. + * returns BAD_FUNC_ARG when: ssl, data or outSz is NULL; sz is negative; + * or not using TLS v1.3. SIDE ERROR when not a server. Otherwise the number of + * early data bytes read. + */ +int wolfSSL_read_early_data(WOLFSSL* ssl, void* data, int sz, int* outSz) +{ + int ret = 0; + + WOLFSSL_ENTER("wolfSSL_read_early_data()"); + + + if (ssl == NULL || data == NULL || sz < 0 || outSz == NULL) + return BAD_FUNC_ARG; + if (!IsAtLeastTLSv1_3(ssl->version)) + return BAD_FUNC_ARG; + +#ifndef NO_WOLFSSL_SERVER + if (ssl->options.side == WOLFSSL_CLIENT_END) + return SIDE_ERROR; + + if (ssl->options.handShakeState == NULL_STATE) { + ssl->earlyData = expecting_early_data; + ret = wolfSSL_accept_TLSv13(ssl); + if (ret <= 0) + return WOLFSSL_FATAL_ERROR; + } + if (ssl->options.handShakeState == SERVER_FINISHED_COMPLETE) { + ret = ReceiveData(ssl, (byte*)data, sz, FALSE); + if (ret > 0) + *outSz = ret; + if (ssl->error == ZERO_RETURN) + ssl->error = WOLFSSL_ERROR_NONE; + } + else + ret = 0; +#else + return SIDE_ERROR; +#endif + + WOLFSSL_LEAVE("wolfSSL_read_early_data()", ret); + + if (ret < 0) + ret = WOLFSSL_FATAL_ERROR; + return ret; +} +#endif + +#undef ERROR_OUT + +#endif /* !WOLFCRYPT_ONLY */ + +#endif /* WOLFSSL_TLS13 */ diff --git a/beken_os/beken378/func/wolfssl/src/wolfio.c b/beken_os/beken378/func/wolfssl/src/wolfio.c new file mode 100755 index 0000000..647ea38 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/src/wolfio.c @@ -0,0 +1,2228 @@ +/* wolfio.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifndef WOLFCRYPT_ONLY + +#ifdef _WIN32_WCE + /* On WinCE winsock2.h must be included before windows.h for socket stuff */ + #include +#endif + +#include +#include +#include + +#if defined(HAVE_HTTP_CLIENT) + #include /* atoi(), strtol() */ +#endif + +/* +Possible IO enable options: + * WOLFSSL_USER_IO: Disables default Embed* callbacks and default: off + allows user to define their own using + wolfSSL_CTX_SetIORecv and wolfSSL_CTX_SetIOSend + * USE_WOLFSSL_IO: Enables the wolfSSL IO functions default: off + * HAVE_HTTP_CLIENT: Enables HTTP client API's default: off + (unless HAVE_OCSP or HAVE_CRL_IO defined) + * HAVE_IO_TIMEOUT: Enables support for connect timeout default: off + */ + + +/* if user writes own I/O callbacks they can define WOLFSSL_USER_IO to remove + automatic setting of default I/O functions EmbedSend() and EmbedReceive() + but they'll still need SetCallback xxx() at end of file +*/ + +#if defined(USE_WOLFSSL_IO) || defined(HAVE_HTTP_CLIENT) + +/* Translates return codes returned from + * send() and recv() if need be. + */ +static WC_INLINE int TranslateReturnCode(int old, int sd) +{ + (void)sd; + +#if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) + if (old == 0) { + errno = SOCKET_EWOULDBLOCK; + return -1; /* convert to BSD style wouldblock as error */ + } + + if (old < 0) { + errno = RTCS_geterror(sd); + if (errno == RTCSERR_TCP_CONN_CLOSING) + return 0; /* convert to BSD style closing */ + if (errno == RTCSERR_TCP_CONN_RLSD) + errno = SOCKET_ECONNRESET; + if (errno == RTCSERR_TCP_TIMED_OUT) + errno = SOCKET_EAGAIN; + } +#endif + + return old; +} + +static WC_INLINE int wolfSSL_LastError(void) +{ +#ifdef USE_WINDOWS_API + return WSAGetLastError(); +#elif defined(EBSNET) + return xn_getlasterror(); +#else + return errno; +#endif +} + +#endif /* USE_WOLFSSL_IO || HAVE_HTTP_CLIENT */ + + +#ifdef OPENSSL_EXTRA +/* Use the WOLFSSL read BIO for receiving data. This is set by the function + * wolfSSL_set_bio and can also be set by wolfSSL_CTX_SetIORecv. + * + * ssl WOLFSSL struct passed in that has this function set as the receive + * callback. + * buf buffer to fill with data read + * sz size of buf buffer + * ctx a user set context + * + * returns the amount of data read or want read. See WOLFSSL_CBIO_ERR_* values. + */ +int BioReceive(WOLFSSL* ssl, char* buf, int sz, void* ctx) +{ + int recvd = WOLFSSL_CBIO_ERR_GENERAL; + + WOLFSSL_ENTER("BioReceive"); + + if (ssl->biord == NULL) { + WOLFSSL_MSG("WOLFSSL biord not set"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + + switch (ssl->biord->type) { + case WOLFSSL_BIO_MEMORY: + case WOLFSSL_BIO_BIO: + if (wolfSSL_BIO_ctrl_pending(ssl->biord) == 0) { + return WOLFSSL_CBIO_ERR_WANT_READ; + } + recvd = wolfSSL_BIO_read(ssl->biord, buf, sz); + if (recvd <= 0) { + return WOLFSSL_CBIO_ERR_GENERAL; + } + break; + + default: + WOLFSSL_MSG("This BIO type is unknown / unsupported"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + + (void)ctx; + return recvd; +} + + +/* Use the WOLFSSL write BIO for sending data. This is set by the function + * wolfSSL_set_bio and can also be set by wolfSSL_CTX_SetIOSend. + * + * ssl WOLFSSL struct passed in that has this function set as the send callback. + * buf buffer with data to write out + * sz size of buf buffer + * ctx a user set context + * + * returns the amount of data sent or want send. See WOLFSSL_CBIO_ERR_* values. + */ +int BioSend(WOLFSSL* ssl, char *buf, int sz, void *ctx) +{ + int sent = WOLFSSL_CBIO_ERR_GENERAL; + + if (ssl->biowr == NULL) { + WOLFSSL_MSG("WOLFSSL biowr not set\n"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + + switch (ssl->biowr->type) { + case WOLFSSL_BIO_MEMORY: + case WOLFSSL_BIO_BIO: + sent = wolfSSL_BIO_write(ssl->biowr, buf, sz); + if (sent < 0) { + return WOLFSSL_CBIO_ERR_GENERAL; + } + break; + + default: + WOLFSSL_MSG("This BIO type is unknown / unsupported"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + (void)ctx; + + return sent; +} +#endif + + +#ifdef USE_WOLFSSL_IO + +/* The receive embedded callback + * return : nb bytes read, or error + */ +int EmbedReceive(WOLFSSL *ssl, char *buf, int sz, void *ctx) +{ + int sd = *(int*)ctx; + int recvd; + + recvd = wolfIO_Recv(sd, buf, sz, ssl->rflags); + if (recvd < 0) { + int err = wolfSSL_LastError(); + WOLFSSL_MSG("Embed Receive error"); + + if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { + WOLFSSL_MSG("\tWould block"); + return WOLFSSL_CBIO_ERR_WANT_READ; + } + else if (err == SOCKET_ECONNRESET) { + WOLFSSL_MSG("\tConnection reset"); + return WOLFSSL_CBIO_ERR_CONN_RST; + } + else if (err == SOCKET_EINTR) { + WOLFSSL_MSG("\tSocket interrupted"); + return WOLFSSL_CBIO_ERR_ISR; + } + else if (err == SOCKET_ECONNABORTED) { + WOLFSSL_MSG("\tConnection aborted"); + return WOLFSSL_CBIO_ERR_CONN_CLOSE; + } + else { + WOLFSSL_MSG("\tGeneral error"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + } + else if (recvd == 0) { + WOLFSSL_MSG("Embed receive connection closed"); + return WOLFSSL_CBIO_ERR_CONN_CLOSE; + } + + return recvd; +} + +/* The send embedded callback + * return : nb bytes sent, or error + */ +int EmbedSend(WOLFSSL* ssl, char *buf, int sz, void *ctx) +{ + int sd = *(int*)ctx; + int sent; + +#ifdef WOLFSSL_MAX_SEND_SZ + if (sz > WOLFSSL_MAX_SEND_SZ) + sz = WOLFSSL_MAX_SEND_SZ; +#endif + + sent = wolfIO_Send(sd, buf, sz, ssl->wflags); + if (sent < 0) { + int err = wolfSSL_LastError(); + WOLFSSL_MSG("Embed Send error"); + + if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { + WOLFSSL_MSG("\tWould Block"); + return WOLFSSL_CBIO_ERR_WANT_WRITE; + } + else if (err == SOCKET_ECONNRESET) { + WOLFSSL_MSG("\tConnection reset"); + return WOLFSSL_CBIO_ERR_CONN_RST; + } + else if (err == SOCKET_EINTR) { + WOLFSSL_MSG("\tSocket interrupted"); + return WOLFSSL_CBIO_ERR_ISR; + } + else if (err == SOCKET_EPIPE) { + WOLFSSL_MSG("\tSocket EPIPE"); + return WOLFSSL_CBIO_ERR_CONN_CLOSE; + } + else { + WOLFSSL_MSG("\tGeneral error"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + } + + return sent; +} + + +#ifdef WOLFSSL_DTLS + +#include + +#define SENDTO_FUNCTION sendto +#define RECVFROM_FUNCTION recvfrom + + +/* The receive embedded callback + * return : nb bytes read, or error + */ +int EmbedReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx) +{ + WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx; + int recvd; + int err; + int sd = dtlsCtx->rfd; + int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl); + SOCKADDR_S peer; + XSOCKLENT peerSz = sizeof(peer); + + WOLFSSL_ENTER("EmbedReceiveFrom()"); + + if (ssl->options.handShakeDone) + dtls_timeout = 0; + + if (!wolfSSL_get_using_nonblock(ssl)) { + #ifdef USE_WINDOWS_API + DWORD timeout = dtls_timeout * 1000; + #else + struct timeval timeout; + XMEMSET(&timeout, 0, sizeof(timeout)); + timeout.tv_sec = dtls_timeout; + #endif + if (setsockopt(sd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, + sizeof(timeout)) != 0) { + WOLFSSL_MSG("setsockopt rcvtimeo failed"); + } + } + + recvd = (int)RECVFROM_FUNCTION(sd, buf, sz, ssl->rflags, + (SOCKADDR*)&peer, &peerSz); + + recvd = TranslateReturnCode(recvd, sd); + + if (recvd < 0) { + err = wolfSSL_LastError(); + WOLFSSL_MSG("Embed Receive From error"); + + if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { + if (wolfSSL_dtls_get_using_nonblock(ssl)) { + WOLFSSL_MSG("\tWould block"); + return WOLFSSL_CBIO_ERR_WANT_READ; + } + else { + WOLFSSL_MSG("\tSocket timeout"); + return WOLFSSL_CBIO_ERR_TIMEOUT; + } + } + else if (err == SOCKET_ECONNRESET) { + WOLFSSL_MSG("\tConnection reset"); + return WOLFSSL_CBIO_ERR_CONN_RST; + } + else if (err == SOCKET_EINTR) { + WOLFSSL_MSG("\tSocket interrupted"); + return WOLFSSL_CBIO_ERR_ISR; + } + else if (err == SOCKET_ECONNREFUSED) { + WOLFSSL_MSG("\tConnection refused"); + return WOLFSSL_CBIO_ERR_WANT_READ; + } + else { + WOLFSSL_MSG("\tGeneral error"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + } + else { + if (dtlsCtx->peer.sz > 0 + && peerSz != (XSOCKLENT)dtlsCtx->peer.sz + && XMEMCMP(&peer, dtlsCtx->peer.sa, peerSz) != 0) { + WOLFSSL_MSG(" Ignored packet from invalid peer"); + return WOLFSSL_CBIO_ERR_WANT_READ; + } + } + + return recvd; +} + + +/* The send embedded callback + * return : nb bytes sent, or error + */ +int EmbedSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx) +{ + WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx; + int sd = dtlsCtx->wfd; + int sent; + int len = sz; + int err; + + WOLFSSL_ENTER("EmbedSendTo()"); + + sent = (int)SENDTO_FUNCTION(sd, &buf[sz - len], len, ssl->wflags, + (const SOCKADDR*)dtlsCtx->peer.sa, + dtlsCtx->peer.sz); + + sent = TranslateReturnCode(sent, sd); + + if (sent < 0) { + err = wolfSSL_LastError(); + WOLFSSL_MSG("Embed Send To error"); + + if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { + WOLFSSL_MSG("\tWould Block"); + return WOLFSSL_CBIO_ERR_WANT_WRITE; + } + else if (err == SOCKET_ECONNRESET) { + WOLFSSL_MSG("\tConnection reset"); + return WOLFSSL_CBIO_ERR_CONN_RST; + } + else if (err == SOCKET_EINTR) { + WOLFSSL_MSG("\tSocket interrupted"); + return WOLFSSL_CBIO_ERR_ISR; + } + else if (err == SOCKET_EPIPE) { + WOLFSSL_MSG("\tSocket EPIPE"); + return WOLFSSL_CBIO_ERR_CONN_CLOSE; + } + else { + WOLFSSL_MSG("\tGeneral error"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + } + + return sent; +} + + +#ifdef WOLFSSL_MULTICAST + +/* The alternate receive embedded callback for Multicast + * return : nb bytes read, or error + */ +int EmbedReceiveFromMcast(WOLFSSL *ssl, char *buf, int sz, void *ctx) +{ + WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx; + int recvd; + int err; + int sd = dtlsCtx->rfd; + + WOLFSSL_ENTER("EmbedReceiveFromMcast()"); + + recvd = (int)RECVFROM_FUNCTION(sd, buf, sz, ssl->rflags, NULL, NULL); + + recvd = TranslateReturnCode(recvd, sd); + + if (recvd < 0) { + err = wolfSSL_LastError(); + WOLFSSL_MSG("Embed Receive From error"); + + if (err == SOCKET_EWOULDBLOCK || err == SOCKET_EAGAIN) { + if (wolfSSL_dtls_get_using_nonblock(ssl)) { + WOLFSSL_MSG("\tWould block"); + return WOLFSSL_CBIO_ERR_WANT_READ; + } + else { + WOLFSSL_MSG("\tSocket timeout"); + return WOLFSSL_CBIO_ERR_TIMEOUT; + } + } + else if (err == SOCKET_ECONNRESET) { + WOLFSSL_MSG("\tConnection reset"); + return WOLFSSL_CBIO_ERR_CONN_RST; + } + else if (err == SOCKET_EINTR) { + WOLFSSL_MSG("\tSocket interrupted"); + return WOLFSSL_CBIO_ERR_ISR; + } + else if (err == SOCKET_ECONNREFUSED) { + WOLFSSL_MSG("\tConnection refused"); + return WOLFSSL_CBIO_ERR_WANT_READ; + } + else { + WOLFSSL_MSG("\tGeneral error"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + } + + return recvd; +} +#endif /* WOLFSSL_MULTICAST */ + + +/* The DTLS Generate Cookie callback + * return : number of bytes copied into buf, or error + */ +int EmbedGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx) +{ + int sd = ssl->wfd; + SOCKADDR_S peer; + XSOCKLENT peerSz = sizeof(peer); + byte digest[WC_SHA256_DIGEST_SIZE]; + int ret = 0; + + (void)ctx; + + XMEMSET(&peer, 0, sizeof(peer)); + if (getpeername(sd, (SOCKADDR*)&peer, &peerSz) != 0) { + WOLFSSL_MSG("getpeername failed in EmbedGenerateCookie"); + return GEN_COOKIE_E; + } + + ret = wc_Sha256Hash((byte*)&peer, peerSz, digest); + if (ret != 0) + return ret; + + if (sz > WC_SHA256_DIGEST_SIZE) + sz = WC_SHA256_DIGEST_SIZE; + XMEMCPY(buf, digest, sz); + + return sz; +} + +#ifdef WOLFSSL_SESSION_EXPORT + + /* get the peer information in human readable form (ip, port, family) + * default function assumes BSD sockets + * can be overridden with wolfSSL_CTX_SetIOGetPeer + */ + int EmbedGetPeer(WOLFSSL* ssl, char* ip, int* ipSz, + unsigned short* port, int* fam) + { + SOCKADDR_S peer; + word32 peerSz; + int ret; + + if (ssl == NULL || ip == NULL || ipSz == NULL || + port == NULL || fam == NULL) { + return BAD_FUNC_ARG; + } + + /* get peer information stored in ssl struct */ + peerSz = sizeof(SOCKADDR_S); + if ((ret = wolfSSL_dtls_get_peer(ssl, (void*)&peer, &peerSz)) + != WOLFSSL_SUCCESS) { + return ret; + } + + /* extract family, ip, and port */ + *fam = ((SOCKADDR_S*)&peer)->ss_family; + switch (*fam) { + case WOLFSSL_IP4: + if (XINET_NTOP(*fam, &(((SOCKADDR_IN*)&peer)->sin_addr), + ip, *ipSz) == NULL) { + WOLFSSL_MSG("XINET_NTOP error"); + return SOCKET_ERROR_E; + } + *port = XNTOHS(((SOCKADDR_IN*)&peer)->sin_port); + break; + + case WOLFSSL_IP6: + #ifdef WOLFSSL_IPV6 + if (XINET_NTOP(*fam, &(((SOCKADDR_IN6*)&peer)->sin6_addr), + ip, *ipSz) == NULL) { + WOLFSSL_MSG("XINET_NTOP error"); + return SOCKET_ERROR_E; + } + *port = XNTOHS(((SOCKADDR_IN6*)&peer)->sin6_port); + #endif /* WOLFSSL_IPV6 */ + break; + + default: + WOLFSSL_MSG("Unknown family type"); + return SOCKET_ERROR_E; + } + ip[*ipSz - 1] = '\0'; /* make sure has terminator */ + *ipSz = (word16)XSTRLEN(ip); + + return WOLFSSL_SUCCESS; + } + + /* set the peer information in human readable form (ip, port, family) + * default function assumes BSD sockets + * can be overridden with wolfSSL_CTX_SetIOSetPeer + */ + int EmbedSetPeer(WOLFSSL* ssl, char* ip, int ipSz, + unsigned short port, int fam) + { + int ret; + SOCKADDR_S addr; + + /* sanity checks on arguments */ + if (ssl == NULL || ip == NULL || ipSz < 0 || ipSz > DTLS_EXPORT_IP) { + return BAD_FUNC_ARG; + } + + addr.ss_family = fam; + switch (addr.ss_family) { + case WOLFSSL_IP4: + if (XINET_PTON(addr.ss_family, ip, + &(((SOCKADDR_IN*)&addr)->sin_addr)) <= 0) { + WOLFSSL_MSG("XINET_PTON error"); + return SOCKET_ERROR_E; + } + ((SOCKADDR_IN*)&addr)->sin_port = XHTONS(port); + + /* peer sa is free'd in SSL_ResourceFree */ + if ((ret = wolfSSL_dtls_set_peer(ssl, (SOCKADDR_IN*)&addr, + sizeof(SOCKADDR_IN)))!= WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Import DTLS peer info error"); + return ret; + } + break; + + case WOLFSSL_IP6: + #ifdef WOLFSSL_IPV6 + if (XINET_PTON(addr.ss_family, ip, + &(((SOCKADDR_IN6*)&addr)->sin6_addr)) <= 0) { + WOLFSSL_MSG("XINET_PTON error"); + return SOCKET_ERROR_E; + } + ((SOCKADDR_IN6*)&addr)->sin6_port = XHTONS(port); + + /* peer sa is free'd in SSL_ResourceFree */ + if ((ret = wolfSSL_dtls_set_peer(ssl, (SOCKADDR_IN6*)&addr, + sizeof(SOCKADDR_IN6)))!= WOLFSSL_SUCCESS) { + WOLFSSL_MSG("Import DTLS peer info error"); + return ret; + } + #endif /* WOLFSSL_IPV6 */ + break; + + default: + WOLFSSL_MSG("Unknown address family"); + return BUFFER_E; + } + + return WOLFSSL_SUCCESS; + } +#endif /* WOLFSSL_SESSION_EXPORT */ +#endif /* WOLFSSL_DTLS */ + + +int wolfIO_Recv(SOCKET_T sd, char *buf, int sz, int rdFlags) +{ + int recvd; + + recvd = (int)RECV_FUNCTION(sd, buf, sz, rdFlags); + recvd = TranslateReturnCode(recvd, sd); + + return recvd; +} + +int wolfIO_Send(SOCKET_T sd, char *buf, int sz, int wrFlags) +{ + int sent; + + sent = (int)SEND_FUNCTION(sd, buf, sz, wrFlags); + sent = TranslateReturnCode(sent, sd); + + return sent; +} + +#endif /* USE_WOLFSSL_IO */ + + +#ifdef HAVE_HTTP_CLIENT + +#ifndef HAVE_IO_TIMEOUT + #define io_timeout_sec 0 +#else + + #ifndef DEFAULT_TIMEOUT_SEC + #define DEFAULT_TIMEOUT_SEC 0 /* no timeout */ + #endif + + static int io_timeout_sec = DEFAULT_TIMEOUT_SEC; + + void wolfIO_SetTimeout(int to_sec) + { + io_timeout_sec = to_sec; + } + + int wolfIO_SetBlockingMode(SOCKET_T sockfd, int non_blocking) + { + int ret = 0; + + #ifdef USE_WINDOWS_API + unsigned long blocking = non_blocking; + ret = ioctlsocket(sockfd, FIONBIO, &blocking); + if (ret == SOCKET_ERROR) + ret = -1; + #else + ret = fcntl(sockfd, F_GETFL, 0); + if (ret >= 0) { + if (non_blocking) + ret |= O_NONBLOCK; + else + ret &= ~O_NONBLOCK; + ret = fcntl(sockfd, F_SETFL, ret); + } + #endif + if (ret < 0) { + WOLFSSL_MSG("wolfIO_SetBlockingMode failed"); + } + + return ret; + } + + int wolfIO_Select(SOCKET_T sockfd, int to_sec) + { + fd_set rfds, wfds; + int nfds = 0; + struct timeval timeout = { (to_sec > 0) ? to_sec : 0, 0}; + int ret; + + #ifndef USE_WINDOWS_API + nfds = (int)sockfd + 1; + #endif + + FD_ZERO(&rfds); + FD_SET(sockfd, &rfds); + wfds = rfds; + + ret = select(nfds, &rfds, &wfds, NULL, &timeout); + if (ret == 0) { + #ifdef DEBUG_HTTP + printf("Timeout: %d\n", ret); + #endif + return HTTP_TIMEOUT; + } + else if (ret > 0) { + if (FD_ISSET(sockfd, &wfds)) { + if (!FD_ISSET(sockfd, &rfds)) { + return 0; + } + } + } + return SOCKET_ERROR_E; + } +#endif /* HAVE_IO_TIMEOUT */ + +static int wolfIO_Word16ToString(char* d, word16 number) +{ + int i = 0; + word16 order = 10000; + word16 digit; + + if (d == NULL) + return i; + + if (number == 0) + d[i++] = '0'; + else { + while (order) { + digit = number / order; + if (i > 0 || digit != 0) + d[i++] = (char)digit + '0'; + if (digit != 0) + number %= digit * order; + + order = (order > 1) ? order / 10 : 0; + } + } + d[i] = 0; /* null terminate */ + + return i; +} + +int wolfIO_TcpConnect(SOCKET_T* sockfd, const char* ip, word16 port, int to_sec) +{ +#ifdef HAVE_SOCKADDR + int ret = 0; + SOCKADDR_S addr; + int sockaddr_len = sizeof(SOCKADDR_IN); +#ifdef HAVE_GETADDRINFO + ADDRINFO hints; + ADDRINFO* answer = NULL; + char strPort[6]; +#else + HOSTENT* entry; + SOCKADDR_IN *sin; +#endif + + XMEMSET(&addr, 0, sizeof(addr)); + +#ifdef WOLFIO_DEBUG + printf("TCP Connect: %s:%d\n", ip, port); +#endif + +#ifdef HAVE_GETADDRINFO + XMEMSET(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + if (wolfIO_Word16ToString(strPort, port) == 0) { + WOLFSSL_MSG("invalid port number for responder"); + return -1; + } + + if (getaddrinfo(ip, strPort, &hints, &answer) < 0 || answer == NULL) { + WOLFSSL_MSG("no addr info for responder"); + return -1; + } + + sockaddr_len = answer->ai_addrlen; + XMEMCPY(&addr, answer->ai_addr, sockaddr_len); + freeaddrinfo(answer); +#else + entry = gethostbyname(ip); + sin = (SOCKADDR_IN *)&addr; + + if (entry) { + sin->sin_family = AF_INET; + sin->sin_port = XHTONS(port); + XMEMCPY(&sin->sin_addr.s_addr, entry->h_addr_list[0], entry->h_length); + } + else { + WOLFSSL_MSG("no addr info for responder"); + return -1; + } +#endif + + *sockfd = (SOCKET_T)socket(addr.ss_family, SOCK_STREAM, 0); + +#ifdef USE_WINDOWS_API + if (*sockfd == INVALID_SOCKET) { + WOLFSSL_MSG("bad socket fd, out of fds?"); + return -1; + } +#else + if (*sockfd < 0) { + WOLFSSL_MSG("bad socket fd, out of fds?"); + return -1; + } +#endif + +#ifdef HAVE_IO_TIMEOUT + /* if timeout value provided then set socket non-blocking */ + if (to_sec > 0) { + wolfIO_SetBlockingMode(*sockfd, 1); + } +#else + (void)to_sec; +#endif + + ret = connect(*sockfd, (SOCKADDR *)&addr, sockaddr_len); +#ifdef HAVE_IO_TIMEOUT + if (ret != 0) { + if ((errno == EINPROGRESS) && (to_sec > 0)) { + /* wait for connect to complete */ + ret = wolfIO_Select(*sockfd, to_sec); + + /* restore blocking mode */ + wolfIO_SetBlockingMode(*sockfd, 0); + } + } +#endif + if (ret != 0) { + WOLFSSL_MSG("Responder tcp connect failed"); + return -1; + } + return ret; +#else + (void)sockfd; + (void)ip; + (void)port; + (void)to_sec; + return -1; +#endif /* HAVE_SOCKADDR */ +} + +#ifndef HTTP_SCRATCH_BUFFER_SIZE + #define HTTP_SCRATCH_BUFFER_SIZE 512 +#endif +#ifndef MAX_URL_ITEM_SIZE + #define MAX_URL_ITEM_SIZE 80 +#endif + +int wolfIO_DecodeUrl(const char* url, int urlSz, char* outName, char* outPath, + word16* outPort) +{ + int result = -1; + + if (url == NULL || urlSz == 0) { + if (outName) + *outName = 0; + if (outPath) + *outPath = 0; + if (outPort) + *outPort = 0; + } + else { + int i, cur; + + /* need to break the url down into scheme, address, and port */ + /* "http://example.com:8080/" */ + /* "http://[::1]:443/" */ + if (XSTRNCMP(url, "http://", 7) == 0) { + cur = 7; + } else cur = 0; + + i = 0; + if (url[cur] == '[') { + cur++; + /* copy until ']' */ + while ( cur < urlSz && url[cur] != 0 && url[cur] != ']' ) { + if (outName) + outName[i] = url[cur]; + i++; cur++; + } + cur++; /* skip ']' */ + } + else { + while ( cur < urlSz && url[cur] != 0 && url[cur] != ':' && + url[cur] != '/') { + if (outName) + outName[i] = url[cur]; + i++; cur++; + } + } + if (outName) + outName[i] = 0; + /* Need to pick out the path after the domain name */ + + if (cur < urlSz && url[cur] == ':') { + char port[6]; + int j; + word32 bigPort = 0; + i = 0; + cur++; + while (cur < urlSz && url[cur] != 0 && url[cur] != '/' && + i < 6) { + port[i++] = url[cur++]; + } + + for (j = 0; j < i; j++) { + if (port[j] < '0' || port[j] > '9') return -1; + bigPort = (bigPort * 10) + (port[j] - '0'); + } + if (outPort) + *outPort = (word16)bigPort; + } + else if (outPort) + *outPort = 80; + + + if (cur < urlSz && url[cur] == '/') { + i = 0; + while (cur < urlSz && url[cur] != 0 && i < MAX_URL_ITEM_SIZE) { + if (outPath) + outPath[i] = url[cur]; + i++; cur++; + } + if (outPath) + outPath[i] = 0; + } + else if (outPath) { + outPath[0] = '/'; + outPath[1] = 0; + } + + result = 0; + } + + return result; +} + +static int wolfIO_HttpProcessResponseBuf(int sfd, byte **recvBuf, int* recvBufSz, + int chunkSz, char* start, int len, int dynType, void* heap) +{ + byte* newRecvBuf = NULL; + int newRecvSz = *recvBufSz + chunkSz; + int pos = 0; + + WOLFSSL_MSG("Processing HTTP response"); +#ifdef WOLFIO_DEBUG + printf("HTTP Chunk %d->%d\n", *recvBufSz, chunkSz); +#endif + + newRecvBuf = (byte*)XMALLOC(newRecvSz, heap, dynType); + if (newRecvBuf == NULL) { + WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf malloc failed"); + return MEMORY_E; + } + + /* if buffer already exists, then we are growing it */ + if (*recvBuf) { + XMEMCPY(&newRecvBuf[pos], *recvBuf, *recvBufSz); + XFREE(*recvBuf, heap, dynType); + pos += *recvBufSz; + *recvBuf = NULL; + } + + /* copy the remainder of the httpBuf into the respBuf */ + if (len != 0) { + XMEMCPY(&newRecvBuf[pos], start, len); + pos += len; + } + + /* receive the remainder of chunk */ + while (len < chunkSz) { + int rxSz = wolfIO_Recv(sfd, (char*)&newRecvBuf[pos], chunkSz-len, 0); + if (rxSz > 0) { + len += rxSz; + pos += rxSz; + } + else { + WOLFSSL_MSG("wolfIO_HttpProcessResponseBuf recv failed"); + XFREE(newRecvBuf, heap, dynType); + return -1; + } + } + + *recvBuf = newRecvBuf; + *recvBufSz = newRecvSz; + + return 0; +} + +int wolfIO_HttpProcessResponse(int sfd, const char** appStrList, + byte** respBuf, byte* httpBuf, int httpBufSz, int dynType, void* heap) +{ + int result = 0; + int len = 0; + char *start, *end; + int respBufSz = 0; + int isChunked = 0, chunkSz = 0; + enum phr_state { phr_init, phr_http_start, phr_have_length, phr_have_type, + phr_wait_end, phr_get_chunk_len, phr_get_chunk_data, + phr_http_end + } state = phr_init; + + *respBuf = NULL; + start = end = NULL; + do { + if (state == phr_get_chunk_data) { + /* get chunk of data */ + result = wolfIO_HttpProcessResponseBuf(sfd, respBuf, &respBufSz, + chunkSz, start, len, dynType, heap); + + state = (result != 0) ? phr_http_end : phr_get_chunk_len; + end = NULL; + len = 0; + } + + /* read data if no \r\n or first time */ + if (end == NULL) { + result = wolfIO_Recv(sfd, (char*)httpBuf+len, httpBufSz-len-1, 0); + if (result > 0) { + len += result; + start = (char*)httpBuf; + start[len] = 0; + } + else { + WOLFSSL_MSG("wolfIO_HttpProcessResponse recv http from peer failed"); + return -1; + } + } + end = XSTRSTR(start, "\r\n"); /* locate end */ + + /* handle incomplete rx */ + if (end == NULL) { + if (len != 0) + XMEMMOVE(httpBuf, start, len); + start = end = NULL; + } + /* when start is "\r\n" */ + else if (end == start) { + /* if waiting for end or need chunk len */ + if (state == phr_wait_end || state == phr_get_chunk_len) { + state = (isChunked) ? phr_get_chunk_len : phr_http_end; + len -= 2; start += 2; /* skip \r\n */ + } + else { + WOLFSSL_MSG("wolfIO_HttpProcessResponse header ended early"); + return -1; + } + } + else { + *end = 0; /* null terminate */ + len -= (int)(end - start) + 2; + /* adjust len to remove the first line including the /r/n */ + + #ifdef WOLFIO_DEBUG + printf("HTTP Resp: %s\n", start); + #endif + + switch (state) { + case phr_init: + if (XSTRNCASECMP(start, "HTTP/1", 6) == 0) { + start += 9; + if (XSTRNCASECMP(start, "200 OK", 6) != 0) { + WOLFSSL_MSG("wolfIO_HttpProcessResponse not OK"); + return -1; + } + state = phr_http_start; + } + break; + case phr_http_start: + case phr_have_length: + case phr_have_type: + if (XSTRNCASECMP(start, "Content-Type:", 13) == 0) { + int i; + + start += 13; + while (*start == ' ' && *start != '\0') start++; + + /* try and match against appStrList */ + i = 0; + while (appStrList[i] != NULL) { + if (XSTRNCASECMP(start, appStrList[i], + XSTRLEN(appStrList[i])) == 0) { + break; + } + i++; + } + if (appStrList[i] == NULL) { + WOLFSSL_MSG("wolfIO_HttpProcessResponse appstr mismatch"); + return -1; + } + state = (state == phr_http_start) ? phr_have_type : phr_wait_end; + } + else if (XSTRNCASECMP(start, "Content-Length:", 15) == 0) { + start += 15; + while (*start == ' ' && *start != '\0') start++; + chunkSz = atoi(start); + state = (state == phr_http_start) ? phr_have_length : phr_wait_end; + } + else if (XSTRNCASECMP(start, "Transfer-Encoding:", 18) == 0) { + start += 18; + while (*start == ' ' && *start != '\0') start++; + if (XSTRNCASECMP(start, "chunked", 7) == 0) { + isChunked = 1; + state = (state == phr_http_start) ? phr_have_length : phr_wait_end; + } + } + break; + case phr_get_chunk_len: + chunkSz = (int)strtol(start, NULL, 16); /* hex format */ + state = (chunkSz == 0) ? phr_http_end : phr_get_chunk_data; + break; + case phr_get_chunk_data: + /* processing for chunk data done above, since \r\n isn't required */ + case phr_wait_end: + case phr_http_end: + /* do nothing */ + break; + } /* switch (state) */ + + /* skip to end plus \r\n */ + start = end + 2; + } + } while (state != phr_http_end); + + if (!isChunked) { + result = wolfIO_HttpProcessResponseBuf(sfd, respBuf, &respBufSz, chunkSz, + start, len, dynType, heap); + } + + if (result >= 0) { + result = respBufSz; + } + else { + WOLFSSL_ERROR(result); + } + + return result; +} +int wolfIO_HttpBuildRequest(const char *reqType, const char *domainName, + const char *path, int pathLen, int reqSz, const char *contentType, + byte *buf, int bufSize) +{ + return wolfIO_HttpBuildRequest_ex(reqType, domainName, path, pathLen, reqSz, contentType, "", buf, bufSize); +} + + int wolfIO_HttpBuildRequest_ex(const char *reqType, const char *domainName, + const char *path, int pathLen, int reqSz, const char *contentType, + const char *exHdrs, byte *buf, int bufSize) + { + word32 reqTypeLen, domainNameLen, reqSzStrLen, contentTypeLen, exHdrsLen, maxLen; + char reqSzStr[6]; + char* req = (char*)buf; + const char* blankStr = " "; + const char* http11Str = " HTTP/1.1"; + const char* hostStr = "\r\nHost: "; + const char* contentLenStr = "\r\nContent-Length: "; + const char* contentTypeStr = "\r\nContent-Type: "; + const char* singleCrLfStr = "\r\n"; + const char* doubleCrLfStr = "\r\n\r\n"; + word32 blankStrLen, http11StrLen, hostStrLen, contentLenStrLen, + contentTypeStrLen, singleCrLfStrLen, doubleCrLfStrLen; + + reqTypeLen = (word32)XSTRLEN(reqType); + domainNameLen = (word32)XSTRLEN(domainName); + reqSzStrLen = wolfIO_Word16ToString(reqSzStr, (word16)reqSz); + contentTypeLen = (word32)XSTRLEN(contentType); + + blankStrLen = (word32)XSTRLEN(blankStr); + http11StrLen = (word32)XSTRLEN(http11Str); + hostStrLen = (word32)XSTRLEN(hostStr); + contentLenStrLen = (word32)XSTRLEN(contentLenStr); + contentTypeStrLen = (word32)XSTRLEN(contentTypeStr); + + if(exHdrs){ + singleCrLfStrLen = (word32)XSTRLEN(singleCrLfStr); + exHdrsLen = (word32)XSTRLEN(exHdrs); + } else { + singleCrLfStrLen = 0; + exHdrsLen = 0; + } + + doubleCrLfStrLen = (word32)XSTRLEN(doubleCrLfStr); + + /* determine max length and check it */ + maxLen = + reqTypeLen + + blankStrLen + + pathLen + + http11StrLen + + hostStrLen + + domainNameLen + + contentLenStrLen + + reqSzStrLen + + contentTypeStrLen + + contentTypeLen + + singleCrLfStrLen + + exHdrsLen + + doubleCrLfStrLen + + 1 /* null term */; + if (maxLen > (word32)bufSize) + return 0; + + XSTRNCPY((char*)buf, reqType, bufSize); + buf += reqTypeLen; bufSize -= reqTypeLen; + XSTRNCPY((char*)buf, blankStr, bufSize); + buf += blankStrLen; bufSize -= blankStrLen; + XSTRNCPY((char*)buf, path, bufSize); + buf += pathLen; bufSize -= pathLen; + XSTRNCPY((char*)buf, http11Str, bufSize); + buf += http11StrLen; bufSize -= http11StrLen; + if (domainNameLen > 0) { + XSTRNCPY((char*)buf, hostStr, bufSize); + buf += hostStrLen; bufSize -= hostStrLen; + XSTRNCPY((char*)buf, domainName, bufSize); + buf += domainNameLen; bufSize -= domainNameLen; + } + if (reqSz > 0 && reqSzStrLen > 0) { + XSTRNCPY((char*)buf, contentLenStr, bufSize); + buf += contentLenStrLen; bufSize -= contentLenStrLen; + XSTRNCPY((char*)buf, reqSzStr, bufSize); + buf += reqSzStrLen; bufSize -= reqSzStrLen; + } + if (contentTypeLen > 0) { + XSTRNCPY((char*)buf, contentTypeStr, bufSize); + buf += contentTypeStrLen; bufSize -= contentTypeStrLen; + XSTRNCPY((char*)buf, contentType, bufSize); + buf += contentTypeLen; bufSize -= contentTypeLen; + } + if (exHdrsLen > 0) + { + XSTRNCPY((char *)buf, singleCrLfStr, bufSize); + buf += singleCrLfStrLen; + bufSize -= singleCrLfStrLen; + XSTRNCPY((char *)buf, exHdrs, bufSize); + buf += exHdrsLen; + bufSize -= exHdrsLen; + } + XSTRNCPY((char*)buf, doubleCrLfStr, bufSize); + buf += doubleCrLfStrLen; + +#ifdef WOLFIO_DEBUG + printf("HTTP %s: %s", reqType, req); +#endif + + /* calculate actual length based on original and new pointer */ + return (int)((char*)buf - req); +} + + +#ifdef HAVE_OCSP + +int wolfIO_HttpBuildRequestOcsp(const char* domainName, const char* path, + int ocspReqSz, byte* buf, int bufSize) +{ + const char *cacheCtl = "Cache-Control: no-cache"; + return wolfIO_HttpBuildRequest_ex("POST", domainName, path, (int)XSTRLEN(path), + ocspReqSz, "application/ocsp-request", cacheCtl, buf, bufSize); +} + +/* return: >0 OCSP Response Size + * -1 error */ +int wolfIO_HttpProcessResponseOcsp(int sfd, byte** respBuf, + byte* httpBuf, int httpBufSz, void* heap) +{ + const char* appStrList[] = { + "application/ocsp-response", + NULL + }; + + return wolfIO_HttpProcessResponse(sfd, appStrList, + respBuf, httpBuf, httpBufSz, DYNAMIC_TYPE_OCSP, heap); +} + +/* in default wolfSSL callback ctx is the heap pointer */ +int EmbedOcspLookup(void* ctx, const char* url, int urlSz, + byte* ocspReqBuf, int ocspReqSz, byte** ocspRespBuf) +{ + SOCKET_T sfd = 0; + word16 port; + int ret = -1; +#ifdef WOLFSSL_SMALL_STACK + char* path; + char* domainName; +#else + char path[MAX_URL_ITEM_SIZE]; + char domainName[MAX_URL_ITEM_SIZE]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + path = (char*)XMALLOC(MAX_URL_ITEM_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (path == NULL) + return MEMORY_E; + + domainName = (char*)XMALLOC(MAX_URL_ITEM_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (domainName == NULL) { + XFREE(path, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#endif + + if (ocspReqBuf == NULL || ocspReqSz == 0) { + WOLFSSL_MSG("OCSP request is required for lookup"); + } + else if (ocspRespBuf == NULL) { + WOLFSSL_MSG("Cannot save OCSP response"); + } + else if (wolfIO_DecodeUrl(url, urlSz, domainName, path, &port) < 0) { + WOLFSSL_MSG("Unable to decode OCSP URL"); + } + else { + /* Note, the library uses the EmbedOcspRespFree() callback to + * free this buffer. */ + int httpBufSz = HTTP_SCRATCH_BUFFER_SIZE; + byte* httpBuf = (byte*)XMALLOC(httpBufSz, ctx, DYNAMIC_TYPE_OCSP); + + if (httpBuf == NULL) { + WOLFSSL_MSG("Unable to create OCSP response buffer"); + } + else { + httpBufSz = wolfIO_HttpBuildRequestOcsp(domainName, path, ocspReqSz, + httpBuf, httpBufSz); + + ret = wolfIO_TcpConnect(&sfd, domainName, port, io_timeout_sec); + if ((ret != 0) || ((int)sfd < 0)) { + WOLFSSL_MSG("OCSP Responder connection failed"); + } + else if (wolfIO_Send(sfd, (char*)httpBuf, httpBufSz, 0) != + httpBufSz) { + WOLFSSL_MSG("OCSP http request failed"); + } + else if (wolfIO_Send(sfd, (char*)ocspReqBuf, ocspReqSz, 0) != + ocspReqSz) { + WOLFSSL_MSG("OCSP ocsp request failed"); + } + else { + ret = wolfIO_HttpProcessResponseOcsp(sfd, ocspRespBuf, httpBuf, + HTTP_SCRATCH_BUFFER_SIZE, ctx); + } + + CloseSocket(sfd); + XFREE(httpBuf, ctx, DYNAMIC_TYPE_OCSP); + } + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(path, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(domainName, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +/* in default callback ctx is heap hint */ +void EmbedOcspRespFree(void* ctx, byte *resp) +{ + if (resp) + XFREE(resp, ctx, DYNAMIC_TYPE_OCSP); + + (void)ctx; +} +#endif /* HAVE_OCSP */ + + +#if defined(HAVE_CRL) && defined(HAVE_CRL_IO) + +int wolfIO_HttpBuildRequestCrl(const char* url, int urlSz, + const char* domainName, byte* buf, int bufSize) +{ + const char *cacheCtl = "Cache-Control: no-cache"; + return wolfIO_HttpBuildRequest_ex("GET", domainName, url, urlSz, 0, "", + cacheCtl, buf, bufSize); +} + +int wolfIO_HttpProcessResponseCrl(WOLFSSL_CRL* crl, int sfd, byte* httpBuf, + int httpBufSz) +{ + int result; + byte *respBuf = NULL; + + const char* appStrList[] = { + "application/pkix-crl", + "application/x-pkcs7-crl", + NULL + }; + + result = wolfIO_HttpProcessResponse(sfd, appStrList, + &respBuf, httpBuf, httpBufSz, DYNAMIC_TYPE_CRL, crl->heap); + if (result >= 0) { + result = BufferLoadCRL(crl, respBuf, result, WOLFSSL_FILETYPE_ASN1, 0); + } + XFREE(respBuf, crl->heap, DYNAMIC_TYPE_CRL); + + return result; +} + +int EmbedCrlLookup(WOLFSSL_CRL* crl, const char* url, int urlSz) +{ + SOCKET_T sfd = 0; + word16 port; + int ret = -1; +#ifdef WOLFSSL_SMALL_STACK + char* domainName; +#else + char domainName[MAX_URL_ITEM_SIZE]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + domainName = (char*)XMALLOC(MAX_URL_ITEM_SIZE, crl->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (domainName == NULL) { + return MEMORY_E; + } +#endif + + if (wolfIO_DecodeUrl(url, urlSz, domainName, NULL, &port) < 0) { + WOLFSSL_MSG("Unable to decode CRL URL"); + } + else { + int httpBufSz = HTTP_SCRATCH_BUFFER_SIZE; + byte* httpBuf = (byte*)XMALLOC(httpBufSz, crl->heap, + DYNAMIC_TYPE_CRL); + if (httpBuf == NULL) { + WOLFSSL_MSG("Unable to create CRL response buffer"); + } + else { + httpBufSz = wolfIO_HttpBuildRequestCrl(url, urlSz, domainName, + httpBuf, httpBufSz); + + ret = wolfIO_TcpConnect(&sfd, domainName, port, io_timeout_sec); + if ((ret != 0) || (sfd < 0)) { + WOLFSSL_MSG("CRL connection failed"); + } + else if (wolfIO_Send(sfd, (char*)httpBuf, httpBufSz, 0) + != httpBufSz) { + WOLFSSL_MSG("CRL http get failed"); + } + else { + ret = wolfIO_HttpProcessResponseCrl(crl, sfd, httpBuf, + HTTP_SCRATCH_BUFFER_SIZE); + } + + CloseSocket(sfd); + XFREE(httpBuf, crl->heap, DYNAMIC_TYPE_CRL); + } + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(domainName, crl->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} +#endif /* HAVE_CRL && HAVE_CRL_IO */ + +#endif /* HAVE_HTTP_CLIENT */ + + + +WOLFSSL_API void wolfSSL_CTX_SetIORecv(WOLFSSL_CTX *ctx, CallbackIORecv CBIORecv) +{ + if (ctx != NULL) { + ctx->CBIORecv = CBIORecv; + #ifdef OPENSSL_EXTRA + ctx->cbioFlag |= WOLFSSL_CBIO_RECV; + #endif + } +} + + +WOLFSSL_API void wolfSSL_CTX_SetIOSend(WOLFSSL_CTX *ctx, CallbackIOSend CBIOSend) +{ + if (ctx != NULL) { + ctx->CBIOSend = CBIOSend; + #ifdef OPENSSL_EXTRA + ctx->cbioFlag |= WOLFSSL_CBIO_SEND; + #endif + } +} + + +/* sets the IO callback to use for receives at WOLFSSL level */ +WOLFSSL_API void wolfSSL_SSLSetIORecv(WOLFSSL *ssl, CallbackIORecv CBIORecv) +{ + if (ssl != NULL) { + ssl->CBIORecv = CBIORecv; + #ifdef OPENSSL_EXTRA + ssl->cbioFlag |= WOLFSSL_CBIO_RECV; + #endif + } +} + + +/* sets the IO callback to use for sends at WOLFSSL level */ +WOLFSSL_API void wolfSSL_SSLSetIOSend(WOLFSSL *ssl, CallbackIOSend CBIOSend) +{ + if (ssl != NULL) { + ssl->CBIOSend = CBIOSend; + #ifdef OPENSSL_EXTRA + ssl->cbioFlag |= WOLFSSL_CBIO_SEND; + #endif + } +} + + +WOLFSSL_API void wolfSSL_SetIOReadCtx(WOLFSSL* ssl, void *rctx) +{ + ssl->IOCB_ReadCtx = rctx; +} + + +WOLFSSL_API void wolfSSL_SetIOWriteCtx(WOLFSSL* ssl, void *wctx) +{ + ssl->IOCB_WriteCtx = wctx; +} + + +WOLFSSL_API void* wolfSSL_GetIOReadCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->IOCB_ReadCtx; + + return NULL; +} + + +WOLFSSL_API void* wolfSSL_GetIOWriteCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->IOCB_WriteCtx; + + return NULL; +} + + +WOLFSSL_API void wolfSSL_SetIOReadFlags(WOLFSSL* ssl, int flags) +{ + ssl->rflags = flags; +} + + +WOLFSSL_API void wolfSSL_SetIOWriteFlags(WOLFSSL* ssl, int flags) +{ + ssl->wflags = flags; +} + + +#ifdef WOLFSSL_DTLS + +WOLFSSL_API void wolfSSL_CTX_SetGenCookie(WOLFSSL_CTX* ctx, CallbackGenCookie cb) +{ + ctx->CBIOCookie = cb; +} + + +WOLFSSL_API void wolfSSL_SetCookieCtx(WOLFSSL* ssl, void *ctx) +{ + ssl->IOCB_CookieCtx = ctx; +} + + +WOLFSSL_API void* wolfSSL_GetCookieCtx(WOLFSSL* ssl) +{ + if (ssl) + return ssl->IOCB_CookieCtx; + + return NULL; +} + +#ifdef WOLFSSL_SESSION_EXPORT + +WOLFSSL_API void wolfSSL_CTX_SetIOGetPeer(WOLFSSL_CTX* ctx, CallbackGetPeer cb) +{ + ctx->CBGetPeer = cb; +} + + +WOLFSSL_API void wolfSSL_CTX_SetIOSetPeer(WOLFSSL_CTX* ctx, CallbackSetPeer cb) +{ + ctx->CBSetPeer = cb; +} + +#endif /* WOLFSSL_SESSION_EXPORT */ +#endif /* WOLFSSL_DTLS */ + + +#ifdef HAVE_NETX + +/* The NetX receive callback + * return : bytes read, or error + */ +int NetX_Receive(WOLFSSL *ssl, char *buf, int sz, void *ctx) +{ + NetX_Ctx* nxCtx = (NetX_Ctx*)ctx; + ULONG left; + ULONG total; + ULONG copied = 0; + UINT status; + + (void)ssl; + + if (nxCtx == NULL || nxCtx->nxSocket == NULL) { + WOLFSSL_MSG("NetX Recv NULL parameters"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + + if (nxCtx->nxPacket == NULL) { + status = nx_tcp_socket_receive(nxCtx->nxSocket, &nxCtx->nxPacket, + nxCtx->nxWait); + if (status != NX_SUCCESS) { + WOLFSSL_MSG("NetX Recv receive error"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + } + + if (nxCtx->nxPacket) { + status = nx_packet_length_get(nxCtx->nxPacket, &total); + if (status != NX_SUCCESS) { + WOLFSSL_MSG("NetX Recv length get error"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + + left = total - nxCtx->nxOffset; + status = nx_packet_data_extract_offset(nxCtx->nxPacket, nxCtx->nxOffset, + buf, sz, &copied); + if (status != NX_SUCCESS) { + WOLFSSL_MSG("NetX Recv data extract offset error"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + + nxCtx->nxOffset += copied; + + if (copied == left) { + WOLFSSL_MSG("NetX Recv Drained packet"); + nx_packet_release(nxCtx->nxPacket); + nxCtx->nxPacket = NULL; + nxCtx->nxOffset = 0; + } + } + + return copied; +} + + +/* The NetX send callback + * return : bytes sent, or error + */ +int NetX_Send(WOLFSSL* ssl, char *buf, int sz, void *ctx) +{ + NetX_Ctx* nxCtx = (NetX_Ctx*)ctx; + NX_PACKET* packet; + NX_PACKET_POOL* pool; /* shorthand */ + UINT status; + + (void)ssl; + + if (nxCtx == NULL || nxCtx->nxSocket == NULL) { + WOLFSSL_MSG("NetX Send NULL parameters"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + + pool = nxCtx->nxSocket->nx_tcp_socket_ip_ptr->nx_ip_default_packet_pool; + status = nx_packet_allocate(pool, &packet, NX_TCP_PACKET, + nxCtx->nxWait); + if (status != NX_SUCCESS) { + WOLFSSL_MSG("NetX Send packet alloc error"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + + status = nx_packet_data_append(packet, buf, sz, pool, nxCtx->nxWait); + if (status != NX_SUCCESS) { + nx_packet_release(packet); + WOLFSSL_MSG("NetX Send data append error"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + + status = nx_tcp_socket_send(nxCtx->nxSocket, packet, nxCtx->nxWait); + if (status != NX_SUCCESS) { + nx_packet_release(packet); + WOLFSSL_MSG("NetX Send socket send error"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + + return sz; +} + + +/* like set_fd, but for default NetX context */ +void wolfSSL_SetIO_NetX(WOLFSSL* ssl, NX_TCP_SOCKET* nxSocket, ULONG waitOption) +{ + if (ssl) { + ssl->nxCtx.nxSocket = nxSocket; + ssl->nxCtx.nxWait = waitOption; + } +} + +#endif /* HAVE_NETX */ + + +#ifdef MICRIUM + +/* Micrium uTCP/IP port, using the NetSock API + * TCP and UDP are currently supported with the callbacks below. + * + * WOLFSSL_SESSION_EXPORT is not yet supported, would need EmbedGetPeer() + * and EmbedSetPeer() callbacks implemented. + * + * HAVE_CRL is not yet supported, would need an EmbedCrlLookup() + * callback implemented. + * + * HAVE_OCSP is not yet supported, would need an EmbedOCSPLookup() + * callback implemented. + */ + +/* The Micrium uTCP/IP send callback + * return : bytes sent, or error + */ +int MicriumSend(WOLFSSL* ssl, char* buf, int sz, void* ctx) +{ + NET_SOCK_ID sd = *(int*)ctx; + NET_SOCK_RTN_CODE ret; + NET_ERR err; + + ret = NetSock_TxData(sd, buf, sz, ssl->wflags, &err); + if (ret < 0) { + WOLFSSL_MSG("Embed Send error"); + + if (err == NET_ERR_TX) { + WOLFSSL_MSG("\tWould block"); + return WOLFSSL_CBIO_ERR_WANT_WRITE; + + } else { + WOLFSSL_MSG("\tGeneral error"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + } + + return ret; +} + +/* The Micrium uTCP/IP receive callback + * return : nb bytes read, or error + */ +int MicriumReceive(WOLFSSL *ssl, char *buf, int sz, void *ctx) +{ + NET_SOCK_ID sd = *(int*)ctx; + NET_SOCK_RTN_CODE ret; + NET_ERR err; + +#ifdef WOLFSSL_DTLS + { + int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl); + if (wolfSSL_dtls(ssl) + && !wolfSSL_dtls_get_using_nonblock(ssl) + && dtls_timeout != 0) { + /* needs timeout in milliseconds */ + NetSock_CfgTimeoutRxQ_Set(sd, dtls_timeout * 1000, &err); + if (err != NET_SOCK_ERR_NONE) { + WOLFSSL_MSG("NetSock_CfgTimeoutRxQ_Set failed"); + } + } + } +#endif + + ret = NetSock_RxData(sd, buf, sz, ssl->rflags, &err); + if (ret < 0) { + WOLFSSL_MSG("Embed Receive error"); + + if (err == NET_ERR_RX || err == NET_SOCK_ERR_RX_Q_EMPTY || + err == NET_ERR_FAULT_LOCK_ACQUIRE) { + if (!wolfSSL_dtls(ssl) || wolfSSL_dtls_get_using_nonblock(ssl)) { + WOLFSSL_MSG("\tWould block"); + return WOLFSSL_CBIO_ERR_WANT_READ; + } + else { + WOLFSSL_MSG("\tSocket timeout"); + return WOLFSSL_CBIO_ERR_TIMEOUT; + } + + } else if (err == NET_SOCK_ERR_CLOSED) { + WOLFSSL_MSG("Embed receive connection closed"); + return WOLFSSL_CBIO_ERR_CONN_CLOSE; + + } else { + WOLFSSL_MSG("\tGeneral error"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + } + + return ret; +} + +/* The Micrium uTCP/IP receivefrom callback + * return : nb bytes read, or error + */ +int MicriumReceiveFrom(WOLFSSL *ssl, char *buf, int sz, void *ctx) +{ + WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx; + NET_SOCK_ID sd = dtlsCtx->rfd; + NET_SOCK_ADDR peer; + NET_SOCK_ADDR_LEN peerSz = sizeof(peer); + NET_SOCK_RTN_CODE ret; + NET_ERR err; + int dtls_timeout = wolfSSL_dtls_get_current_timeout(ssl); + + WOLFSSL_ENTER("MicriumReceiveFrom()"); + + if (ssl->options.handShakeDone) + dtls_timeout = 0; + + if (!wolfSSL_dtls_get_using_nonblock(ssl)) { + /* needs timeout in milliseconds */ + NetSock_CfgTimeoutRxQ_Set(sd, dtls_timeout * 1000, &err); + if (err != NET_SOCK_ERR_NONE) { + WOLFSSL_MSG("NetSock_CfgTimeoutRxQ_Set failed"); + } + } + + ret = NetSock_RxDataFrom(sd, buf, sz, ssl->rflags, &peer, &peerSz, + 0, 0, 0, &err); + if (ret < 0) { + WOLFSSL_MSG("Embed Receive From error"); + + if (err == NET_ERR_RX || err == NET_SOCK_ERR_RX_Q_EMPTY || + err == NET_ERR_FAULT_LOCK_ACQUIRE) { + if (wolfSSL_dtls_get_using_nonblock(ssl)) { + WOLFSSL_MSG("\tWould block"); + return WOLFSSL_CBIO_ERR_WANT_READ; + } + else { + WOLFSSL_MSG("\tSocket timeout"); + return WOLFSSL_CBIO_ERR_TIMEOUT; + } + } else { + WOLFSSL_MSG("\tGeneral error"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + } + else { + if (dtlsCtx->peer.sz > 0 + && peerSz != (NET_SOCK_ADDR_LEN)dtlsCtx->peer.sz + && XMEMCMP(&peer, dtlsCtx->peer.sa, peerSz) != 0) { + WOLFSSL_MSG("\tIgnored packet from invalid peer"); + return WOLFSSL_CBIO_ERR_WANT_READ; + } + } + + return ret; +} + +/* The Micrium uTCP/IP sendto callback + * return : nb bytes sent, or error + */ +int MicriumSendTo(WOLFSSL* ssl, char *buf, int sz, void *ctx) +{ + WOLFSSL_DTLS_CTX* dtlsCtx = (WOLFSSL_DTLS_CTX*)ctx; + NET_SOCK_ID sd = dtlsCtx->wfd; + NET_SOCK_RTN_CODE ret; + int len = sz; + NET_ERR err; + + WOLFSSL_ENTER("MicriumSendTo()"); + + ret = NetSock_TxDataTo(sd, &buf[sz - len], len, ssl->wflags, + (NET_SOCK_ADDR*)dtlsCtx->peer.sa, + (NET_SOCK_ADDR_LEN)dtlsCtx->peer.sz, + &err); + if (err < 0) { + WOLFSSL_MSG("Embed Send To error"); + + if (err == NET_ERR_TX) { + WOLFSSL_MSG("\tWould block"); + return WOLFSSL_CBIO_ERR_WANT_WRITE; + + } else { + WOLFSSL_MSG("\tGeneral error"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + } + + return ret; +} + +/* Micrium DTLS Generate Cookie callback + * return : number of bytes copied into buf, or error + */ +int MicriumGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx) +{ + NET_SOCK_ADDR peer; + NET_SOCK_ADDR_LEN peerSz = sizeof(peer); + byte digest[WC_SHA_DIGEST_SIZE]; + int ret = 0; + + (void)ctx; + + XMEMSET(&peer, 0, sizeof(peer)); + if (wolfSSL_dtls_get_peer(ssl, (void*)&peer, + (unsigned int*)&peerSz) != WOLFSSL_SUCCESS) { + WOLFSSL_MSG("getpeername failed in MicriumGenerateCookie"); + return GEN_COOKIE_E; + } + + ret = wc_ShaHash((byte*)&peer, peerSz, digest); + if (ret != 0) + return ret; + + if (sz > WC_SHA_DIGEST_SIZE) + sz = WC_SHA_DIGEST_SIZE; + XMEMCPY(buf, digest, sz); + + return sz; +} + +#endif /* MICRIUM */ + +#if defined(WOLFSSL_APACHE_MYNEWT) && !defined(WOLFSSL_LWIP) + +#include +#include +#include + +#define MB_NAME "wolfssl_mb" + +typedef struct Mynewt_Ctx { + struct mn_socket *mnSocket; /* send/recv socket handler */ + struct mn_sockaddr_in mnSockAddrIn; /* socket address */ + struct os_mbuf *mnPacket; /* incoming packet handle + for short reads */ + int reading; /* reading flag */ + + /* private */ + void *mnMemBuffer; /* memory buffer for mempool */ + struct os_mempool mnMempool; /* mempool */ + struct os_mbuf_pool mnMbufpool; /* mbuf pool */ +} Mynewt_Ctx; + +void mynewt_ctx_clear(void *ctx) { + Mynewt_Ctx *mynewt_ctx = (Mynewt_Ctx*)ctx; + if(!mynewt_ctx) return; + + if(mynewt_ctx->mnPacket) { + os_mbuf_free_chain(mynewt_ctx->mnPacket); + mynewt_ctx->mnPacket = NULL; + } + os_mempool_clear(&mynewt_ctx->mnMempool); + XFREE(mynewt_ctx->mnMemBuffer, 0, 0); + XFREE(mynewt_ctx, 0, 0); +} + +/* return Mynewt_Ctx instance */ +void* mynewt_ctx_new() { + int rc = 0; + Mynewt_Ctx *mynewt_ctx = NULL; + int mem_buf_count = MYNEWT_VAL(WOLFSSL_MNSOCK_MEM_BUF_COUNT); + int mem_buf_size = MYNEWT_VAL(WOLFSSL_MNSOCK_MEM_BUF_SIZE); + int mempool_bytes = OS_MEMPOOL_BYTES(mem_buf_count, mem_buf_size); + + mynewt_ctx = (Mynewt_Ctx *)XMALLOC(sizeof(struct Mynewt_Ctx), + NULL, DYNAMIC_TYPE_TMP_BUFFER); + if(!mynewt_ctx) return NULL; + + XMEMSET(mynewt_ctx, 0, sizeof(Mynewt_Ctx)); + mynewt_ctx->mnMemBuffer = XMALLOC(mempool_bytes, 0, 0); + if(!mynewt_ctx->mnMemBuffer) { + mynewt_ctx_clear((void*)mynewt_ctx); + return NULL; + } + + rc = os_mempool_init(&mynewt_ctx->mnMempool, + mem_buf_count, mem_buf_size, + mynewt_ctx->mnMemBuffer, MB_NAME); + if(rc != 0) { + mynewt_ctx_clear((void*)mynewt_ctx); + return NULL; + } + rc = os_mbuf_pool_init(&mynewt_ctx->mnMbufpool, &mynewt_ctx->mnMempool, + mem_buf_count, mem_buf_size); + if(rc != 0) { + mynewt_ctx_clear((void*)mynewt_ctx); + return NULL; + } + + return mynewt_ctx; +} + +static void mynewt_sock_writable(void *arg, int err); +static void mynewt_sock_readable(void *arg, int err); +static const union mn_socket_cb mynewt_sock_cbs = { + .socket.writable = mynewt_sock_writable, + .socket.readable = mynewt_sock_readable, +}; +static void mynewt_sock_writable(void *arg, int err) +{ + /* do nothing */ +} +static void mynewt_sock_readable(void *arg, int err) +{ + Mynewt_Ctx *mynewt_ctx = (Mynewt_Ctx *)arg; + if (err && mynewt_ctx->reading) { + mynewt_ctx->reading = 0; + } +} + +/* The Mynewt receive callback + * return : bytes read, or error + */ +int Mynewt_Receive(WOLFSSL *ssl, char *buf, int sz, void *ctx) +{ + Mynewt_Ctx *mynewt_ctx = (Mynewt_Ctx*)ctx; + int rc = 0; + struct mn_sockaddr_in from; + struct os_mbuf *m; + int read_sz = 0; + uint16_t total; + + if (mynewt_ctx == NULL || mynewt_ctx->mnSocket == NULL) { + WOLFSSL_MSG("Mynewt Recv NULL parameters"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + + if(mynewt_ctx->mnPacket == NULL) { + mynewt_ctx->mnPacket = os_mbuf_get_pkthdr(&mynewt_ctx->mnMbufpool, 0); + if(mynewt_ctx->mnPacket == NULL) { + return MEMORY_E; + } + + mynewt_ctx->reading = 1; + while(mynewt_ctx->reading && rc == 0) { + rc = mn_recvfrom(mynewt_ctx->mnSocket, &m, (struct mn_sockaddr *) &from); + if(rc == MN_ECONNABORTED) { + rc = 0; + mynewt_ctx->reading = 0; + break; + } + if (!(rc == 0 || rc == MN_EAGAIN)) { + WOLFSSL_MSG("Mynewt Recv receive error"); + mynewt_ctx->reading = 0; + break; + } + if(rc == 0) { + int len = OS_MBUF_PKTLEN(m); + if(len == 0) { + break; + } + rc = os_mbuf_appendfrom(mynewt_ctx->mnPacket, m, 0, len); + if(rc != 0) { + WOLFSSL_MSG("Mynewt Recv os_mbuf_appendfrom error"); + break; + } + os_mbuf_free_chain(m); + m = NULL; + } else if(rc == MN_EAGAIN) { + /* continue to until reading all of packet data. */ + rc = 0; + break; + } + } + if(rc != 0) { + mynewt_ctx->reading = 0; + os_mbuf_free_chain(mynewt_ctx->mnPacket); + mynewt_ctx->mnPacket = NULL; + return rc; + } + } + + if(mynewt_ctx->mnPacket) { + total = OS_MBUF_PKTLEN(mynewt_ctx->mnPacket); + read_sz = (total >= sz)? sz : total; + + os_mbuf_copydata(mynewt_ctx->mnPacket, 0, read_sz, (void*)buf); + os_mbuf_adj(mynewt_ctx->mnPacket, read_sz); + + if (read_sz == total) { + WOLFSSL_MSG("Mynewt Recv Drained packet"); + os_mbuf_free_chain(mynewt_ctx->mnPacket); + mynewt_ctx->mnPacket = NULL; + } + } + + return read_sz; +} + +/* The Mynewt send callback + * return : bytes sent, or error + */ +int Mynewt_Send(WOLFSSL* ssl, char *buf, int sz, void *ctx) +{ + Mynewt_Ctx *mynewt_ctx = (Mynewt_Ctx*)ctx; + int rc = 0; + struct os_mbuf *m = NULL; + int write_sz = 0; + m = os_msys_get_pkthdr(sz, 0); + if (!m) { + WOLFSSL_MSG("Mynewt Send os_msys_get_pkthdr error"); + return WOLFSSL_CBIO_ERR_GENERAL; + } + rc = os_mbuf_copyinto(m, 0, buf, sz); + if (rc != 0) { + WOLFSSL_MSG("Mynewt Send os_mbuf_copyinto error"); + os_mbuf_free_chain(m); + return rc; + } + rc = mn_sendto(mynewt_ctx->mnSocket, m, (struct mn_sockaddr *)&mynewt_ctx->mnSockAddrIn); + if(rc != 0) { + WOLFSSL_MSG("Mynewt Send mn_sendto error"); + os_mbuf_free_chain(m); + return rc; + } + write_sz = sz; + return write_sz; +} + +/* like set_fd, but for default NetX context */ +void wolfSSL_SetIO_Mynewt(WOLFSSL* ssl, struct mn_socket* mnSocket, struct mn_sockaddr_in* mnSockAddrIn) +{ + if (ssl && ssl->mnCtx) { + Mynewt_Ctx *mynewt_ctx = (Mynewt_Ctx *)ssl->mnCtx; + mynewt_ctx->mnSocket = mnSocket; + memcpy(&mynewt_ctx->mnSockAddrIn, mnSockAddrIn, sizeof(struct mn_sockaddr_in)); + mn_socket_set_cbs(mynewt_ctx->mnSocket, mnSocket, &mynewt_sock_cbs); + } +} + +#endif /* defined(WOLFSSL_APACHE_MYNEWT) && !defined(WOLFSSL_LWIP) */ + +#ifdef WOLFSSL_UIP +#include +#include + +/* uIP TCP/IP port, using the native tcp/udp socket api. + * TCP and UDP are currently supported with the callbacks below. + * + */ +/* The uIP tcp send callback + * return : bytes sent, or error + */ +int uIPSend(WOLFSSL* ssl, char* buf, int sz, void* _ctx) +{ + uip_wolfssl_ctx *ctx = (struct uip_wolfssl_ctx *)_ctx; + int ret; + unsigned int max_sendlen; + int total_written = 0; + (void)ssl; + do { + unsigned int bytes_left = sz - total_written; + max_sendlen = tcp_socket_max_sendlen(&ctx->conn.tcp); + if (bytes_left > max_sendlen) { + printf("Send limited by buffer\r\n"); + bytes_left = max_sendlen; + } + if (bytes_left == 0) { + printf("Buffer full!\r\n"); + break; + } + ret = tcp_socket_send(&ctx->conn.tcp, (unsigned char *)buf + total_written, bytes_left); + if (ret <= 0) + break; + total_written += ret; + } while(total_written < sz); + return total_written; +} + +int uIPSendTo(WOLFSSL* ssl, char* buf, int sz, void* _ctx) +{ + uip_wolfssl_ctx *ctx = (struct uip_wolfssl_ctx *)_ctx; + int ret = 0; + (void)ssl; + ret = udp_socket_sendto(&ctx->conn.udp, (unsigned char *)buf, sz, &ctx->peer_addr, ctx->peer_port ); + if (ret <= 0) + return 0; + return ret; +} + +/* The uIP uTCP/IP receive callback + * return : nb bytes read, or error + */ +int uIPReceive(WOLFSSL *ssl, char *buf, int sz, void *_ctx) +{ + uip_wolfssl_ctx *ctx = (uip_wolfssl_ctx *)_ctx; + if (!ctx || !ctx->ssl_rx_databuf) + return -1; + (void)ssl; + if (ctx->ssl_rb_len > 0) { + if (sz > ctx->ssl_rb_len - ctx->ssl_rb_off) + sz = ctx->ssl_rb_len - ctx->ssl_rb_off; + XMEMCPY(buf, ctx->ssl_rx_databuf + ctx->ssl_rb_off, sz); + ctx->ssl_rb_off += sz; + if (ctx->ssl_rb_off >= ctx->ssl_rb_len) { + ctx->ssl_rb_len = 0; + ctx->ssl_rb_off = 0; + } + return sz; + } else { + return WOLFSSL_CBIO_ERR_WANT_READ; + } +} + +/* uIP DTLS Generate Cookie callback + * return : number of bytes copied into buf, or error + */ +int uIPGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *_ctx) +{ + uip_wolfssl_ctx *ctx = (uip_wolfssl_ctx *)ctx; + byte token[32]; + byte digest[WC_SHA_DIGEST_SIZE]; + int ret = 0; + XMEMSET(token, 0, sizeof(token)); + XMEMCPY(token, &ctx->peer_addr, sizeof(uip_ipaddr_t)); + XMEMCPY(token + sizeof(uip_ipaddr_t), &ctx->peer_port, sizeof(word16)); + ret = wc_ShaHash(token, sizeof(uip_ipaddr_t) + sizeof(word16), digest); + if (ret != 0) + return ret; + if (sz > WC_SHA_DIGEST_SIZE) + sz = WC_SHA_DIGEST_SIZE; + XMEMCPY(buf, digest, sz); + return sz; +} + +#endif /* WOLFSSL_UIP */ + +#endif /* WOLFCRYPT_ONLY */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/aes.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/aes.c new file mode 100755 index 0000000..adbe1b1 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/aes.c @@ -0,0 +1,7574 @@ +/* aes.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include +#include + +#if !defined(NO_AES) + +/* Tip: Locate the software cipher modes by searching for "Software AES" */ + +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + + /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ + #define FIPS_NO_WRAPPERS + + #ifdef USE_WINDOWS_API + #pragma code_seg(".fipsA$g") + #pragma const_seg(".fipsB$g") + #endif +#endif + +#include +#include + +#ifdef WOLF_CRYPTO_CB + #include +#endif + + +/* fips wrapper calls, user can call direct */ +#if defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) + + int wc_AesSetKey(Aes* aes, const byte* key, word32 len, const byte* iv, + int dir) + { + if (aes == NULL || !( (len == 16) || (len == 24) || (len == 32)) ) { + return BAD_FUNC_ARG; + } + + return AesSetKey_fips(aes, key, len, iv, dir); + } + int wc_AesSetIV(Aes* aes, const byte* iv) + { + if (aes == NULL) { + return BAD_FUNC_ARG; + } + + return AesSetIV_fips(aes, iv); + } + #ifdef HAVE_AES_CBC + int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + if (aes == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + + return AesCbcEncrypt_fips(aes, out, in, sz); + } + #ifdef HAVE_AES_DECRYPT + int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + if (aes == NULL || out == NULL || in == NULL + || sz % AES_BLOCK_SIZE != 0) { + return BAD_FUNC_ARG; + } + + return AesCbcDecrypt_fips(aes, out, in, sz); + } + #endif /* HAVE_AES_DECRYPT */ + #endif /* HAVE_AES_CBC */ + + /* AES-CTR */ + #ifdef WOLFSSL_AES_COUNTER + int wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + if (aes == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + + return AesCtrEncrypt(aes, out, in, sz); + } + #endif + + /* AES-DIRECT */ + #if defined(WOLFSSL_AES_DIRECT) + void wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in) + { + AesEncryptDirect(aes, out, in); + } + + #ifdef HAVE_AES_DECRYPT + void wc_AesDecryptDirect(Aes* aes, byte* out, const byte* in) + { + AesDecryptDirect(aes, out, in); + } + #endif /* HAVE_AES_DECRYPT */ + + int wc_AesSetKeyDirect(Aes* aes, const byte* key, word32 len, + const byte* iv, int dir) + { + return AesSetKeyDirect(aes, key, len, iv, dir); + } + #endif /* WOLFSSL_AES_DIRECT */ + + /* AES-GCM */ + #ifdef HAVE_AESGCM + int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len) + { + if (aes == NULL || !( (len == 16) || (len == 24) || (len == 32)) ) { + return BAD_FUNC_ARG; + } + + return AesGcmSetKey_fips(aes, key, len); + } + int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, + const byte* iv, word32 ivSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) + { + if (aes == NULL || authTagSz > AES_BLOCK_SIZE + || authTagSz < WOLFSSL_MIN_AUTH_TAG_SZ || + ivSz > AES_BLOCK_SIZE) { + return BAD_FUNC_ARG; + } + + return AesGcmEncrypt_fips(aes, out, in, sz, iv, ivSz, authTag, + authTagSz, authIn, authInSz); + } + + #ifdef HAVE_AES_DECRYPT + int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, + const byte* iv, word32 ivSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) + { + if (aes == NULL || out == NULL || in == NULL || iv == NULL + || authTag == NULL || authTagSz > AES_BLOCK_SIZE || + ivSz > AES_BLOCK_SIZE) { + return BAD_FUNC_ARG; + } + + return AesGcmDecrypt_fips(aes, out, in, sz, iv, ivSz, authTag, + authTagSz, authIn, authInSz); + } + #endif /* HAVE_AES_DECRYPT */ + + int wc_GmacSetKey(Gmac* gmac, const byte* key, word32 len) + { + if (gmac == NULL || key == NULL || !((len == 16) || + (len == 24) || (len == 32)) ) { + return BAD_FUNC_ARG; + } + + return GmacSetKey(gmac, key, len); + } + int wc_GmacUpdate(Gmac* gmac, const byte* iv, word32 ivSz, + const byte* authIn, word32 authInSz, + byte* authTag, word32 authTagSz) + { + if (gmac == NULL || authTagSz > AES_BLOCK_SIZE || + authTagSz < WOLFSSL_MIN_AUTH_TAG_SZ) { + return BAD_FUNC_ARG; + } + + return GmacUpdate(gmac, iv, ivSz, authIn, authInSz, + authTag, authTagSz); + } + #endif /* HAVE_AESGCM */ + + /* AES-CCM */ + #if defined(HAVE_AESCCM) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + int wc_AesCcmSetKey(Aes* aes, const byte* key, word32 keySz) + { + return AesCcmSetKey(aes, key, keySz); + } + int wc_AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz, + const byte* nonce, word32 nonceSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) + { + /* sanity check on arguments */ + if (aes == NULL || out == NULL || in == NULL || nonce == NULL + || authTag == NULL || nonceSz < 7 || nonceSz > 13) + return BAD_FUNC_ARG; + + AesCcmEncrypt(aes, out, in, inSz, nonce, nonceSz, authTag, + authTagSz, authIn, authInSz); + return 0; + } + + #ifdef HAVE_AES_DECRYPT + int wc_AesCcmDecrypt(Aes* aes, byte* out, + const byte* in, word32 inSz, + const byte* nonce, word32 nonceSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) + { + + if (aes == NULL || out == NULL || in == NULL || nonce == NULL + || authTag == NULL || nonceSz < 7 || nonceSz > 13) { + return BAD_FUNC_ARG; + } + + return AesCcmDecrypt(aes, out, in, inSz, nonce, nonceSz, + authTag, authTagSz, authIn, authInSz); + } + #endif /* HAVE_AES_DECRYPT */ + #endif /* HAVE_AESCCM && HAVE_FIPS_VERSION 2 */ + + int wc_AesInit(Aes* aes, void* h, int i) + { + if (aes == NULL) + return BAD_FUNC_ARG; + + (void)h; + (void)i; + + /* FIPS doesn't support: + return AesInit(aes, h, i); */ + return 0; + } + void wc_AesFree(Aes* aes) + { + (void)aes; + /* FIPS doesn't support: + AesFree(aes); */ + } + +#else /* else build without fips, or for FIPS v2 */ + + +#if defined(WOLFSSL_TI_CRYPT) + #include +#else + +#include + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#if !defined(WOLFSSL_ARMASM) + +#ifdef WOLFSSL_IMX6_CAAM_BLOB + /* case of possibly not using hardware acceleration for AES but using key + blobs */ + #include +#endif + +#ifdef DEBUG_AESNI + #include +#endif + +#ifdef _MSC_VER + /* 4127 warning constant while(1) */ + #pragma warning(disable: 4127) +#endif + + +/* Define AES implementation includes and functions */ +#if defined(STM32_CRYPTO) + /* STM32F2/F4/F7/L4 hardware AES support for ECB, CBC, CTR and GCM modes */ + +#if defined(WOLFSSL_AES_DIRECT) || defined(HAVE_AESGCM) || defined(HAVE_AESCCM) + + static int wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock) + { + int ret = 0; + #ifdef WOLFSSL_STM32_CUBEMX + CRYP_HandleTypeDef hcryp; + #else + CRYP_InitTypeDef cryptInit; + CRYP_KeyInitTypeDef keyInit; + #endif + + #ifdef WOLFSSL_STM32_CUBEMX + ret = wc_Stm32_Aes_Init(aes, &hcryp); + if (ret != 0) + return ret; + + #ifdef STM32_CRYPTO_AES_ONLY + hcryp.Init.OperatingMode = CRYP_ALGOMODE_ENCRYPT; + hcryp.Init.ChainingMode = CRYP_CHAINMODE_AES_ECB; + hcryp.Init.KeyWriteFlag = CRYP_KEY_WRITE_ENABLE; + #endif + HAL_CRYP_Init(&hcryp); + + #ifdef STM32_CRYPTO_AES_ONLY + ret = HAL_CRYPEx_AES(&hcryp, (uint8_t*)inBlock, AES_BLOCK_SIZE, + outBlock, STM32_HAL_TIMEOUT); + #else + ret = HAL_CRYP_AESECB_Encrypt(&hcryp, (uint8_t*)inBlock, AES_BLOCK_SIZE, + outBlock, STM32_HAL_TIMEOUT); + #endif + if (ret != HAL_OK) { + ret = WC_TIMEOUT_E; + } + HAL_CRYP_DeInit(&hcryp); + + #else /* STD_PERI_LIB */ + ret = wc_Stm32_Aes_Init(aes, &cryptInit, &keyInit); + if (ret != 0) + return ret; + + /* reset registers to their default values */ + CRYP_DeInit(); + + /* setup key */ + CRYP_KeyInit(&keyInit); + + /* set direction and mode */ + cryptInit.CRYP_AlgoDir = CRYP_AlgoDir_Encrypt; + cryptInit.CRYP_AlgoMode = CRYP_AlgoMode_AES_ECB; + CRYP_Init(&cryptInit); + + /* enable crypto processor */ + CRYP_Cmd(ENABLE); + + /* flush IN/OUT FIFOs */ + CRYP_FIFOFlush(); + + CRYP_DataIn(*(uint32_t*)&inBlock[0]); + CRYP_DataIn(*(uint32_t*)&inBlock[4]); + CRYP_DataIn(*(uint32_t*)&inBlock[8]); + CRYP_DataIn(*(uint32_t*)&inBlock[12]); + + /* wait until the complete message has been processed */ + while (CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {} + + *(uint32_t*)&outBlock[0] = CRYP_DataOut(); + *(uint32_t*)&outBlock[4] = CRYP_DataOut(); + *(uint32_t*)&outBlock[8] = CRYP_DataOut(); + *(uint32_t*)&outBlock[12] = CRYP_DataOut(); + + /* disable crypto processor */ + CRYP_Cmd(DISABLE); + #endif /* WOLFSSL_STM32_CUBEMX */ + return ret; + } +#endif /* WOLFSSL_AES_DIRECT || HAVE_AESGCM || HAVE_AESCCM */ + +#ifdef HAVE_AES_DECRYPT + #if defined(WOLFSSL_AES_DIRECT) || defined(HAVE_AESCCM) + static int wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) + { + int ret = 0; + #ifdef WOLFSSL_STM32_CUBEMX + CRYP_HandleTypeDef hcryp; + #else + CRYP_InitTypeDef cryptInit; + CRYP_KeyInitTypeDef keyInit; + #endif + + #ifdef WOLFSSL_STM32_CUBEMX + ret = wc_Stm32_Aes_Init(aes, &hcryp); + if (ret != 0) + return ret; + + #ifdef STM32_CRYPTO_AES_ONLY + hcryp.Init.OperatingMode = CRYP_ALGOMODE_DECRYPT; + hcryp.Init.ChainingMode = CRYP_CHAINMODE_AES_ECB; + hcryp.Init.KeyWriteFlag = CRYP_KEY_WRITE_ENABLE; + #endif + HAL_CRYP_Init(&hcryp); + + #ifdef STM32_CRYPTO_AES_ONLY + ret = HAL_CRYPEx_AES(&hcryp, (uint8_t*)inBlock, AES_BLOCK_SIZE, + outBlock, STM32_HAL_TIMEOUT); + #else + ret = HAL_CRYP_AESECB_Decrypt(&hcryp, (uint8_t*)inBlock, AES_BLOCK_SIZE, + outBlock, STM32_HAL_TIMEOUT); + #endif + if (ret != HAL_OK) { + ret = WC_TIMEOUT_E; + } + HAL_CRYP_DeInit(&hcryp); + + #else /* STD_PERI_LIB */ + ret = wc_Stm32_Aes_Init(aes, &cryptInit, &keyInit); + if (ret != 0) + return ret; + + /* reset registers to their default values */ + CRYP_DeInit(); + + /* set direction and key */ + CRYP_KeyInit(&keyInit); + cryptInit.CRYP_AlgoDir = CRYP_AlgoDir_Decrypt; + cryptInit.CRYP_AlgoMode = CRYP_AlgoMode_AES_Key; + CRYP_Init(&cryptInit); + + /* enable crypto processor */ + CRYP_Cmd(ENABLE); + + /* wait until decrypt key has been initialized */ + while (CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {} + + /* set direction and mode */ + cryptInit.CRYP_AlgoDir = CRYP_AlgoDir_Decrypt; + cryptInit.CRYP_AlgoMode = CRYP_AlgoMode_AES_ECB; + CRYP_Init(&cryptInit); + + /* enable crypto processor */ + CRYP_Cmd(ENABLE); + + /* flush IN/OUT FIFOs */ + CRYP_FIFOFlush(); + + CRYP_DataIn(*(uint32_t*)&inBlock[0]); + CRYP_DataIn(*(uint32_t*)&inBlock[4]); + CRYP_DataIn(*(uint32_t*)&inBlock[8]); + CRYP_DataIn(*(uint32_t*)&inBlock[12]); + + /* wait until the complete message has been processed */ + while (CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {} + + *(uint32_t*)&outBlock[0] = CRYP_DataOut(); + *(uint32_t*)&outBlock[4] = CRYP_DataOut(); + *(uint32_t*)&outBlock[8] = CRYP_DataOut(); + *(uint32_t*)&outBlock[12] = CRYP_DataOut(); + + /* disable crypto processor */ + CRYP_Cmd(DISABLE); + #endif /* WOLFSSL_STM32_CUBEMX */ + return ret; + } + #endif /* WOLFSSL_AES_DIRECT || HAVE_AESCCM */ +#endif /* HAVE_AES_DECRYPT */ + +#elif defined(HAVE_COLDFIRE_SEC) + /* Freescale Coldfire SEC support for CBC mode. + * NOTE: no support for AES-CTR/GCM/CCM/Direct */ + #include + #include "sec.h" + #include "mcf5475_sec.h" + #include "mcf5475_siu.h" +#elif defined(FREESCALE_LTC) + #include "fsl_ltc.h" + #if defined(FREESCALE_LTC_AES_GCM) + #undef NEED_AES_TABLES + #undef GCM_TABLE + #else + /* if LTC doesn't have GCM, use software with LTC AES ECB mode */ + static int wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock) + { + wc_AesEncryptDirect(aes, outBlock, inBlock); + return 0; + } + static int wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) + { + wc_AesDecryptDirect(aes, outBlock, inBlock); + return 0; + } + #endif +#elif defined(FREESCALE_MMCAU) + /* Freescale mmCAU hardware AES support for Direct, CBC, CCM, GCM modes + * through the CAU/mmCAU library. Documentation located in + * ColdFire/ColdFire+ CAU and Kinetis mmCAU Software Library User + * Guide (See note in README). */ + #ifdef FREESCALE_MMCAU_CLASSIC + /* MMCAU 1.4 library used with non-KSDK / classic MQX builds */ + #include "cau_api.h" + #else + #include "fsl_mmcau.h" + #endif + + static int wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock) + { + int ret; + + #ifdef FREESCALE_MMCAU_CLASSIC + if ((wolfssl_word)outBlock % WOLFSSL_MMCAU_ALIGNMENT) { + WOLFSSL_MSG("Bad cau_aes_encrypt alignment"); + return BAD_ALIGN_E; + } + #endif + + ret = wolfSSL_CryptHwMutexLock(); + if(ret == 0) { + #ifdef FREESCALE_MMCAU_CLASSIC + cau_aes_encrypt(inBlock, (byte*)aes->key, aes->rounds, outBlock); + #else + MMCAU_AES_EncryptEcb(inBlock, (byte*)aes->key, aes->rounds, + outBlock); + #endif + wolfSSL_CryptHwMutexUnLock(); + } + return ret; + } + #ifdef HAVE_AES_DECRYPT + static int wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) + { + int ret; + + #ifdef FREESCALE_MMCAU_CLASSIC + if ((wolfssl_word)outBlock % WOLFSSL_MMCAU_ALIGNMENT) { + WOLFSSL_MSG("Bad cau_aes_decrypt alignment"); + return BAD_ALIGN_E; + } + #endif + + ret = wolfSSL_CryptHwMutexLock(); + if(ret == 0) { + #ifdef FREESCALE_MMCAU_CLASSIC + cau_aes_decrypt(inBlock, (byte*)aes->key, aes->rounds, outBlock); + #else + MMCAU_AES_DecryptEcb(inBlock, (byte*)aes->key, aes->rounds, + outBlock); + #endif + wolfSSL_CryptHwMutexUnLock(); + } + return ret; + } + #endif /* HAVE_AES_DECRYPT */ + +#elif defined(WOLFSSL_PIC32MZ_CRYPT) + + #include + + #if defined(HAVE_AESGCM) || defined(WOLFSSL_AES_DIRECT) + static int wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock) + { + return wc_Pic32AesCrypt(aes->key, aes->keylen, NULL, 0, + outBlock, inBlock, AES_BLOCK_SIZE, + PIC32_ENCRYPTION, PIC32_ALGO_AES, PIC32_CRYPTOALGO_RECB); + } + #endif + + #if defined(HAVE_AES_DECRYPT) && defined(WOLFSSL_AES_DIRECT) + static int wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) + { + return wc_Pic32AesCrypt(aes->key, aes->keylen, NULL, 0, + outBlock, inBlock, AES_BLOCK_SIZE, + PIC32_DECRYPTION, PIC32_ALGO_AES, PIC32_CRYPTOALGO_RECB); + } + #endif + +#elif defined(WOLFSSL_NRF51_AES) + /* Use built-in AES hardware - AES 128 ECB Encrypt Only */ + #include "wolfssl/wolfcrypt/port/nrf51.h" + + static int wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock) + { + return nrf51_aes_encrypt(inBlock, (byte*)aes->key, aes->rounds, outBlock); + } + + #ifdef HAVE_AES_DECRYPT + #error nRF51 AES Hardware does not support decrypt + #endif /* HAVE_AES_DECRYPT */ + +#elif defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_AES) + + #include "wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h" + + #if defined(HAVE_AESGCM) || defined(WOLFSSL_AES_DIRECT) + static int wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock) + { + return wc_esp32AesEncrypt(aes, inBlock, outBlock); + } + #endif + + #if defined(HAVE_AES_DECRYPT) && defined(WOLFSSL_AES_DIRECT) + static int wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) + { + return wc_esp32AesDecrypt(aes, inBlock, outBlock); + } + #endif + +#elif defined(WOLFSSL_AESNI) + + #define NEED_AES_TABLES + + /* Each platform needs to query info type 1 from cpuid to see if aesni is + * supported. Also, let's setup a macro for proper linkage w/o ABI conflicts + */ + + #ifndef AESNI_ALIGN + #define AESNI_ALIGN 16 + #endif + + #ifdef _MSC_VER + #define XASM_LINK(f) + #elif defined(__APPLE__) + #define XASM_LINK(f) asm("_" f) + #else + #define XASM_LINK(f) asm(f) + #endif /* _MSC_VER */ + + static int checkAESNI = 0; + static int haveAESNI = 0; + static word32 intel_flags = 0; + + static int Check_CPU_support_AES(void) + { + intel_flags = cpuid_get_flags(); + + return IS_INTEL_AESNI(intel_flags) != 0; + } + + + /* tell C compiler these are asm functions in case any mix up of ABI underscore + prefix between clang/gcc/llvm etc */ + #ifdef HAVE_AES_CBC + void AES_CBC_encrypt(const unsigned char* in, unsigned char* out, + unsigned char* ivec, unsigned long length, + const unsigned char* KS, int nr) + XASM_LINK("AES_CBC_encrypt"); + + #ifdef HAVE_AES_DECRYPT + #if defined(WOLFSSL_AESNI_BY4) + void AES_CBC_decrypt_by4(const unsigned char* in, unsigned char* out, + unsigned char* ivec, unsigned long length, + const unsigned char* KS, int nr) + XASM_LINK("AES_CBC_decrypt_by4"); + #elif defined(WOLFSSL_AESNI_BY6) + void AES_CBC_decrypt_by6(const unsigned char* in, unsigned char* out, + unsigned char* ivec, unsigned long length, + const unsigned char* KS, int nr) + XASM_LINK("AES_CBC_decrypt_by6"); + #else /* WOLFSSL_AESNI_BYx */ + void AES_CBC_decrypt_by8(const unsigned char* in, unsigned char* out, + unsigned char* ivec, unsigned long length, + const unsigned char* KS, int nr) + XASM_LINK("AES_CBC_decrypt_by8"); + #endif /* WOLFSSL_AESNI_BYx */ + #endif /* HAVE_AES_DECRYPT */ + #endif /* HAVE_AES_CBC */ + + void AES_ECB_encrypt(const unsigned char* in, unsigned char* out, + unsigned long length, const unsigned char* KS, int nr) + XASM_LINK("AES_ECB_encrypt"); + + #ifdef HAVE_AES_DECRYPT + void AES_ECB_decrypt(const unsigned char* in, unsigned char* out, + unsigned long length, const unsigned char* KS, int nr) + XASM_LINK("AES_ECB_decrypt"); + #endif + + void AES_128_Key_Expansion(const unsigned char* userkey, + unsigned char* key_schedule) + XASM_LINK("AES_128_Key_Expansion"); + + void AES_192_Key_Expansion(const unsigned char* userkey, + unsigned char* key_schedule) + XASM_LINK("AES_192_Key_Expansion"); + + void AES_256_Key_Expansion(const unsigned char* userkey, + unsigned char* key_schedule) + XASM_LINK("AES_256_Key_Expansion"); + + + static int AES_set_encrypt_key(const unsigned char *userKey, const int bits, + Aes* aes) + { + int ret; + + if (!userKey || !aes) + return BAD_FUNC_ARG; + + switch (bits) { + case 128: + AES_128_Key_Expansion (userKey,(byte*)aes->key); aes->rounds = 10; + return 0; + case 192: + AES_192_Key_Expansion (userKey,(byte*)aes->key); aes->rounds = 12; + return 0; + case 256: + AES_256_Key_Expansion (userKey,(byte*)aes->key); aes->rounds = 14; + return 0; + default: + ret = BAD_FUNC_ARG; + } + + return ret; + } + + #ifdef HAVE_AES_DECRYPT + static int AES_set_decrypt_key(const unsigned char* userKey, + const int bits, Aes* aes) + { + int nr; + Aes temp_key; + __m128i *Key_Schedule = (__m128i*)aes->key; + __m128i *Temp_Key_Schedule = (__m128i*)temp_key.key; + + if (!userKey || !aes) + return BAD_FUNC_ARG; + + if (AES_set_encrypt_key(userKey,bits,&temp_key) == BAD_FUNC_ARG) + return BAD_FUNC_ARG; + + nr = temp_key.rounds; + aes->rounds = nr; + + Key_Schedule[nr] = Temp_Key_Schedule[0]; + Key_Schedule[nr-1] = _mm_aesimc_si128(Temp_Key_Schedule[1]); + Key_Schedule[nr-2] = _mm_aesimc_si128(Temp_Key_Schedule[2]); + Key_Schedule[nr-3] = _mm_aesimc_si128(Temp_Key_Schedule[3]); + Key_Schedule[nr-4] = _mm_aesimc_si128(Temp_Key_Schedule[4]); + Key_Schedule[nr-5] = _mm_aesimc_si128(Temp_Key_Schedule[5]); + Key_Schedule[nr-6] = _mm_aesimc_si128(Temp_Key_Schedule[6]); + Key_Schedule[nr-7] = _mm_aesimc_si128(Temp_Key_Schedule[7]); + Key_Schedule[nr-8] = _mm_aesimc_si128(Temp_Key_Schedule[8]); + Key_Schedule[nr-9] = _mm_aesimc_si128(Temp_Key_Schedule[9]); + + if (nr>10) { + Key_Schedule[nr-10] = _mm_aesimc_si128(Temp_Key_Schedule[10]); + Key_Schedule[nr-11] = _mm_aesimc_si128(Temp_Key_Schedule[11]); + } + + if (nr>12) { + Key_Schedule[nr-12] = _mm_aesimc_si128(Temp_Key_Schedule[12]); + Key_Schedule[nr-13] = _mm_aesimc_si128(Temp_Key_Schedule[13]); + } + + Key_Schedule[0] = Temp_Key_Schedule[nr]; + + return 0; + } + #endif /* HAVE_AES_DECRYPT */ + +#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES) + static int wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock) + { + wc_AesEncryptDirect(aes, outBlock, inBlock); + return 0; + } + +#elif defined(WOLFSSL_AFALG) +#elif defined(WOLFSSL_DEVCRYPTO_AES) + /* if all AES is enabled with devcrypto then tables are not needed */ + +#else + + /* using wolfCrypt software implementation */ + #define NEED_AES_TABLES +#endif + + + +#ifdef NEED_AES_TABLES + +static const word32 rcon[] = { + 0x01000000, 0x02000000, 0x04000000, 0x08000000, + 0x10000000, 0x20000000, 0x40000000, 0x80000000, + 0x1B000000, 0x36000000, + /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */ +}; + +static const word32 Te[4][256] = { +{ + 0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU, + 0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U, + 0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU, + 0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU, + 0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U, + 0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU, + 0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU, + 0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU, + 0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU, + 0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU, + 0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U, + 0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU, + 0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU, + 0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U, + 0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU, + 0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU, + 0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU, + 0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU, + 0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU, + 0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U, + 0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU, + 0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU, + 0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU, + 0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU, + 0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U, + 0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U, + 0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U, + 0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U, + 0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU, + 0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U, + 0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U, + 0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU, + 0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU, + 0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U, + 0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U, + 0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U, + 0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU, + 0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U, + 0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU, + 0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U, + 0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU, + 0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U, + 0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U, + 0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU, + 0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U, + 0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U, + 0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U, + 0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U, + 0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U, + 0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U, + 0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U, + 0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U, + 0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU, + 0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U, + 0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U, + 0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U, + 0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U, + 0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U, + 0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U, + 0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU, + 0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U, + 0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U, + 0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U, + 0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU, +}, +{ + 0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU, + 0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U, + 0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU, + 0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U, + 0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU, + 0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U, + 0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU, + 0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U, + 0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U, + 0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU, + 0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U, + 0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U, + 0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U, + 0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU, + 0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U, + 0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U, + 0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU, + 0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U, + 0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U, + 0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U, + 0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU, + 0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU, + 0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U, + 0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU, + 0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU, + 0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U, + 0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU, + 0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U, + 0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU, + 0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U, + 0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U, + 0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U, + 0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU, + 0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U, + 0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU, + 0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U, + 0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU, + 0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U, + 0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U, + 0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU, + 0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU, + 0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU, + 0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U, + 0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U, + 0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU, + 0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U, + 0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU, + 0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U, + 0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU, + 0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U, + 0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU, + 0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU, + 0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U, + 0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU, + 0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U, + 0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU, + 0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U, + 0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U, + 0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U, + 0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU, + 0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU, + 0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U, + 0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU, + 0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U, +}, +{ + 0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU, + 0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U, + 0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU, + 0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U, + 0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU, + 0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U, + 0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU, + 0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U, + 0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U, + 0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU, + 0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U, + 0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U, + 0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U, + 0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU, + 0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U, + 0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U, + 0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU, + 0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U, + 0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U, + 0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U, + 0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU, + 0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU, + 0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U, + 0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU, + 0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU, + 0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U, + 0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU, + 0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U, + 0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU, + 0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U, + 0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U, + 0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U, + 0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU, + 0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U, + 0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU, + 0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U, + 0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU, + 0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U, + 0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U, + 0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU, + 0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU, + 0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU, + 0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U, + 0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U, + 0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU, + 0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U, + 0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU, + 0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U, + 0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU, + 0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U, + 0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU, + 0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU, + 0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U, + 0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU, + 0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U, + 0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU, + 0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U, + 0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U, + 0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U, + 0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU, + 0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU, + 0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U, + 0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU, + 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U, +}, +{ + 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U, + 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U, + 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U, + 0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU, + 0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU, + 0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU, + 0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U, + 0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU, + 0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU, + 0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U, + 0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U, + 0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU, + 0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU, + 0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU, + 0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU, + 0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU, + 0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U, + 0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU, + 0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU, + 0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U, + 0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U, + 0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U, + 0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U, + 0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U, + 0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU, + 0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U, + 0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU, + 0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU, + 0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U, + 0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U, + 0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U, + 0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU, + 0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U, + 0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU, + 0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU, + 0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U, + 0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U, + 0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU, + 0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U, + 0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU, + 0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U, + 0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U, + 0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U, + 0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U, + 0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU, + 0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U, + 0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU, + 0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U, + 0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU, + 0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U, + 0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU, + 0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU, + 0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU, + 0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU, + 0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U, + 0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U, + 0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U, + 0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U, + 0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U, + 0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U, + 0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU, + 0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U, + 0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU, + 0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU, +} +}; + +#ifdef HAVE_AES_DECRYPT +static const word32 Td[4][256] = { +{ + 0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U, + 0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U, + 0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U, + 0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU, + 0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U, + 0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U, + 0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU, + 0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U, + 0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU, + 0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U, + 0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U, + 0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U, + 0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U, + 0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU, + 0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U, + 0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU, + 0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U, + 0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU, + 0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U, + 0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U, + 0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U, + 0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU, + 0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U, + 0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU, + 0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U, + 0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU, + 0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U, + 0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU, + 0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU, + 0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U, + 0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU, + 0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U, + 0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU, + 0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U, + 0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U, + 0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U, + 0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU, + 0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U, + 0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U, + 0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU, + 0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U, + 0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U, + 0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U, + 0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U, + 0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U, + 0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU, + 0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U, + 0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U, + 0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U, + 0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U, + 0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U, + 0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU, + 0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU, + 0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU, + 0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU, + 0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U, + 0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U, + 0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU, + 0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU, + 0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U, + 0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU, + 0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U, + 0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U, + 0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U, +}, +{ + 0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU, + 0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U, + 0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU, + 0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U, + 0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U, + 0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U, + 0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U, + 0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U, + 0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U, + 0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU, + 0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU, + 0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU, + 0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U, + 0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU, + 0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U, + 0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U, + 0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U, + 0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU, + 0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU, + 0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U, + 0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU, + 0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U, + 0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU, + 0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU, + 0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U, + 0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U, + 0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U, + 0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU, + 0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U, + 0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU, + 0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U, + 0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U, + 0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U, + 0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU, + 0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U, + 0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U, + 0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U, + 0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U, + 0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U, + 0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U, + 0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU, + 0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU, + 0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U, + 0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU, + 0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U, + 0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU, + 0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU, + 0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U, + 0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU, + 0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U, + 0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U, + 0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U, + 0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U, + 0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U, + 0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U, + 0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U, + 0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU, + 0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U, + 0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U, + 0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU, + 0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U, + 0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U, + 0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U, + 0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U, +}, +{ + 0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U, + 0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U, + 0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U, + 0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U, + 0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU, + 0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U, + 0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U, + 0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U, + 0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U, + 0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU, + 0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U, + 0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U, + 0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU, + 0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U, + 0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U, + 0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U, + 0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U, + 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U, + 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U, + 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU, + + 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U, + 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U, + 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U, + 0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U, + 0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U, + 0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU, + 0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU, + 0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U, + 0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU, + 0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U, + 0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU, + 0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU, + 0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU, + 0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU, + 0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U, + 0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U, + 0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U, + 0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U, + 0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U, + 0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U, + 0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U, + 0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU, + 0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU, + 0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U, + 0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U, + 0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU, + 0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU, + 0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U, + 0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U, + 0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U, + 0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U, + 0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U, + 0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U, + 0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U, + 0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU, + 0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U, + 0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U, + 0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U, + 0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U, + 0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U, + 0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U, + 0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU, + 0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U, + 0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U, +}, +{ + 0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU, + 0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU, + 0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U, + 0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U, + 0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU, + 0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU, + 0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U, + 0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU, + 0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U, + 0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU, + 0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U, + 0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U, + 0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U, + 0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U, + 0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U, + 0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU, + 0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU, + 0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U, + 0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U, + 0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU, + 0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU, + 0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U, + 0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U, + 0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U, + 0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U, + 0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU, + 0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U, + 0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U, + 0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU, + 0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU, + 0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U, + 0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U, + 0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U, + 0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU, + 0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U, + 0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U, + 0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U, + 0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U, + 0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U, + 0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U, + 0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U, + 0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU, + 0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U, + 0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U, + 0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU, + 0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU, + 0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U, + 0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU, + 0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U, + 0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U, + 0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U, + 0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U, + 0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U, + 0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U, + 0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU, + 0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU, + 0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU, + 0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU, + 0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U, + 0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U, + 0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U, + 0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU, + 0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U, + 0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U, +} +}; + + +#if defined(HAVE_AES_CBC) || defined(WOLFSSL_AES_DIRECT) +static const byte Td4[256] = +{ + 0x52U, 0x09U, 0x6aU, 0xd5U, 0x30U, 0x36U, 0xa5U, 0x38U, + 0xbfU, 0x40U, 0xa3U, 0x9eU, 0x81U, 0xf3U, 0xd7U, 0xfbU, + 0x7cU, 0xe3U, 0x39U, 0x82U, 0x9bU, 0x2fU, 0xffU, 0x87U, + 0x34U, 0x8eU, 0x43U, 0x44U, 0xc4U, 0xdeU, 0xe9U, 0xcbU, + 0x54U, 0x7bU, 0x94U, 0x32U, 0xa6U, 0xc2U, 0x23U, 0x3dU, + 0xeeU, 0x4cU, 0x95U, 0x0bU, 0x42U, 0xfaU, 0xc3U, 0x4eU, + 0x08U, 0x2eU, 0xa1U, 0x66U, 0x28U, 0xd9U, 0x24U, 0xb2U, + 0x76U, 0x5bU, 0xa2U, 0x49U, 0x6dU, 0x8bU, 0xd1U, 0x25U, + 0x72U, 0xf8U, 0xf6U, 0x64U, 0x86U, 0x68U, 0x98U, 0x16U, + 0xd4U, 0xa4U, 0x5cU, 0xccU, 0x5dU, 0x65U, 0xb6U, 0x92U, + 0x6cU, 0x70U, 0x48U, 0x50U, 0xfdU, 0xedU, 0xb9U, 0xdaU, + 0x5eU, 0x15U, 0x46U, 0x57U, 0xa7U, 0x8dU, 0x9dU, 0x84U, + 0x90U, 0xd8U, 0xabU, 0x00U, 0x8cU, 0xbcU, 0xd3U, 0x0aU, + 0xf7U, 0xe4U, 0x58U, 0x05U, 0xb8U, 0xb3U, 0x45U, 0x06U, + 0xd0U, 0x2cU, 0x1eU, 0x8fU, 0xcaU, 0x3fU, 0x0fU, 0x02U, + 0xc1U, 0xafU, 0xbdU, 0x03U, 0x01U, 0x13U, 0x8aU, 0x6bU, + 0x3aU, 0x91U, 0x11U, 0x41U, 0x4fU, 0x67U, 0xdcU, 0xeaU, + 0x97U, 0xf2U, 0xcfU, 0xceU, 0xf0U, 0xb4U, 0xe6U, 0x73U, + 0x96U, 0xacU, 0x74U, 0x22U, 0xe7U, 0xadU, 0x35U, 0x85U, + 0xe2U, 0xf9U, 0x37U, 0xe8U, 0x1cU, 0x75U, 0xdfU, 0x6eU, + 0x47U, 0xf1U, 0x1aU, 0x71U, 0x1dU, 0x29U, 0xc5U, 0x89U, + 0x6fU, 0xb7U, 0x62U, 0x0eU, 0xaaU, 0x18U, 0xbeU, 0x1bU, + 0xfcU, 0x56U, 0x3eU, 0x4bU, 0xc6U, 0xd2U, 0x79U, 0x20U, + 0x9aU, 0xdbU, 0xc0U, 0xfeU, 0x78U, 0xcdU, 0x5aU, 0xf4U, + 0x1fU, 0xddU, 0xa8U, 0x33U, 0x88U, 0x07U, 0xc7U, 0x31U, + 0xb1U, 0x12U, 0x10U, 0x59U, 0x27U, 0x80U, 0xecU, 0x5fU, + 0x60U, 0x51U, 0x7fU, 0xa9U, 0x19U, 0xb5U, 0x4aU, 0x0dU, + 0x2dU, 0xe5U, 0x7aU, 0x9fU, 0x93U, 0xc9U, 0x9cU, 0xefU, + 0xa0U, 0xe0U, 0x3bU, 0x4dU, 0xaeU, 0x2aU, 0xf5U, 0xb0U, + 0xc8U, 0xebU, 0xbbU, 0x3cU, 0x83U, 0x53U, 0x99U, 0x61U, + 0x17U, 0x2bU, 0x04U, 0x7eU, 0xbaU, 0x77U, 0xd6U, 0x26U, + 0xe1U, 0x69U, 0x14U, 0x63U, 0x55U, 0x21U, 0x0cU, 0x7dU, +}; +#endif /* HAVE_AES_CBC || WOLFSSL_AES_DIRECT */ +#endif /* HAVE_AES_DECRYPT */ + +#define GETBYTE(x, y) (word32)((byte)((x) >> (8 * (y)))) + + + +#if defined(HAVE_AES_CBC) || defined(WOLFSSL_AES_DIRECT) || defined(HAVE_AESGCM) + +#ifndef WC_CACHE_LINE_SZ + #if defined(__x86_64__) || defined(_M_X64) || \ + (defined(__ILP32__) && (__ILP32__ >= 1)) + #define WC_CACHE_LINE_SZ 64 + #else + /* default cache line size */ + #define WC_CACHE_LINE_SZ 32 + #endif +#endif + + +/* load 4 Te Tables into cache by cache line stride */ +static WC_INLINE word32 PreFetchTe(void) +{ + word32 x = 0; + int i,j; + + for (i = 0; i < 4; i++) { + /* 256 elements, each one is 4 bytes */ + for (j = 0; j < 256; j += WC_CACHE_LINE_SZ/4) { + x &= Te[i][j]; + } + } + return x; +} + +/* Software AES - ECB Encrypt */ +static void wc_AesEncrypt(Aes* aes, const byte* inBlock, byte* outBlock) +{ + word32 s0, s1, s2, s3; + word32 t0, t1, t2, t3; + word32 r = aes->rounds >> 1; + const word32* rk = aes->key; + + if (r > 7 || r == 0) { + WOLFSSL_MSG("AesEncrypt encountered improper key, set it up"); + return; /* stop instead of seg-faulting, set up your keys! */ + } + +#ifdef WOLFSSL_AESNI + if (haveAESNI && aes->use_aesni) { + #ifdef DEBUG_AESNI + printf("about to aes encrypt\n"); + printf("in = %p\n", inBlock); + printf("out = %p\n", outBlock); + printf("aes->key = %p\n", aes->key); + printf("aes->rounds = %d\n", aes->rounds); + printf("sz = %d\n", AES_BLOCK_SIZE); + #endif + + /* check alignment, decrypt doesn't need alignment */ + if ((wolfssl_word)inBlock % AESNI_ALIGN) { + #ifndef NO_WOLFSSL_ALLOC_ALIGN + byte* tmp = (byte*)XMALLOC(AES_BLOCK_SIZE + AESNI_ALIGN, aes->heap, + DYNAMIC_TYPE_TMP_BUFFER); + byte* tmp_align; + if (tmp == NULL) return; + + tmp_align = tmp + (AESNI_ALIGN - ((size_t)tmp % AESNI_ALIGN)); + + XMEMCPY(tmp_align, inBlock, AES_BLOCK_SIZE); + AES_ECB_encrypt(tmp_align, tmp_align, AES_BLOCK_SIZE, (byte*)aes->key, + aes->rounds); + XMEMCPY(outBlock, tmp_align, AES_BLOCK_SIZE); + XFREE(tmp, aes->heap, DYNAMIC_TYPE_TMP_BUFFER); + return; + #else + WOLFSSL_MSG("AES-ECB encrypt with bad alignment"); + return; + #endif + } + + AES_ECB_encrypt(inBlock, outBlock, AES_BLOCK_SIZE, (byte*)aes->key, + aes->rounds); + + return; + } + else { + #ifdef DEBUG_AESNI + printf("Skipping AES-NI\n"); + #endif + } +#endif + + /* + * map byte array block to cipher state + * and add initial round key: + */ + XMEMCPY(&s0, inBlock, sizeof(s0)); + XMEMCPY(&s1, inBlock + sizeof(s0), sizeof(s1)); + XMEMCPY(&s2, inBlock + 2 * sizeof(s0), sizeof(s2)); + XMEMCPY(&s3, inBlock + 3 * sizeof(s0), sizeof(s3)); + +#ifdef LITTLE_ENDIAN_ORDER + s0 = ByteReverseWord32(s0); + s1 = ByteReverseWord32(s1); + s2 = ByteReverseWord32(s2); + s3 = ByteReverseWord32(s3); +#endif + + s0 ^= rk[0]; + s1 ^= rk[1]; + s2 ^= rk[2]; + s3 ^= rk[3]; + + s0 |= PreFetchTe(); + + /* + * Nr - 1 full rounds: + */ + + for (;;) { + t0 = + Te[0][GETBYTE(s0, 3)] ^ + Te[1][GETBYTE(s1, 2)] ^ + Te[2][GETBYTE(s2, 1)] ^ + Te[3][GETBYTE(s3, 0)] ^ + rk[4]; + t1 = + Te[0][GETBYTE(s1, 3)] ^ + Te[1][GETBYTE(s2, 2)] ^ + Te[2][GETBYTE(s3, 1)] ^ + Te[3][GETBYTE(s0, 0)] ^ + rk[5]; + t2 = + Te[0][GETBYTE(s2, 3)] ^ + Te[1][GETBYTE(s3, 2)] ^ + Te[2][GETBYTE(s0, 1)] ^ + Te[3][GETBYTE(s1, 0)] ^ + rk[6]; + t3 = + Te[0][GETBYTE(s3, 3)] ^ + Te[1][GETBYTE(s0, 2)] ^ + Te[2][GETBYTE(s1, 1)] ^ + Te[3][GETBYTE(s2, 0)] ^ + rk[7]; + + rk += 8; + if (--r == 0) { + break; + } + + s0 = + Te[0][GETBYTE(t0, 3)] ^ + Te[1][GETBYTE(t1, 2)] ^ + Te[2][GETBYTE(t2, 1)] ^ + Te[3][GETBYTE(t3, 0)] ^ + rk[0]; + s1 = + Te[0][GETBYTE(t1, 3)] ^ + Te[1][GETBYTE(t2, 2)] ^ + Te[2][GETBYTE(t3, 1)] ^ + Te[3][GETBYTE(t0, 0)] ^ + rk[1]; + s2 = + Te[0][GETBYTE(t2, 3)] ^ + Te[1][GETBYTE(t3, 2)] ^ + Te[2][GETBYTE(t0, 1)] ^ + Te[3][GETBYTE(t1, 0)] ^ + rk[2]; + s3 = + Te[0][GETBYTE(t3, 3)] ^ + Te[1][GETBYTE(t0, 2)] ^ + Te[2][GETBYTE(t1, 1)] ^ + Te[3][GETBYTE(t2, 0)] ^ + rk[3]; + } + + /* + * apply last round and + * map cipher state to byte array block: + */ + + s0 = + (Te[2][GETBYTE(t0, 3)] & 0xff000000) ^ + (Te[3][GETBYTE(t1, 2)] & 0x00ff0000) ^ + (Te[0][GETBYTE(t2, 1)] & 0x0000ff00) ^ + (Te[1][GETBYTE(t3, 0)] & 0x000000ff) ^ + rk[0]; + s1 = + (Te[2][GETBYTE(t1, 3)] & 0xff000000) ^ + (Te[3][GETBYTE(t2, 2)] & 0x00ff0000) ^ + (Te[0][GETBYTE(t3, 1)] & 0x0000ff00) ^ + (Te[1][GETBYTE(t0, 0)] & 0x000000ff) ^ + rk[1]; + s2 = + (Te[2][GETBYTE(t2, 3)] & 0xff000000) ^ + (Te[3][GETBYTE(t3, 2)] & 0x00ff0000) ^ + (Te[0][GETBYTE(t0, 1)] & 0x0000ff00) ^ + (Te[1][GETBYTE(t1, 0)] & 0x000000ff) ^ + rk[2]; + s3 = + (Te[2][GETBYTE(t3, 3)] & 0xff000000) ^ + (Te[3][GETBYTE(t0, 2)] & 0x00ff0000) ^ + (Te[0][GETBYTE(t1, 1)] & 0x0000ff00) ^ + (Te[1][GETBYTE(t2, 0)] & 0x000000ff) ^ + rk[3]; + + /* write out */ +#ifdef LITTLE_ENDIAN_ORDER + s0 = ByteReverseWord32(s0); + s1 = ByteReverseWord32(s1); + s2 = ByteReverseWord32(s2); + s3 = ByteReverseWord32(s3); +#endif + + XMEMCPY(outBlock, &s0, sizeof(s0)); + XMEMCPY(outBlock + sizeof(s0), &s1, sizeof(s1)); + XMEMCPY(outBlock + 2 * sizeof(s0), &s2, sizeof(s2)); + XMEMCPY(outBlock + 3 * sizeof(s0), &s3, sizeof(s3)); + +} +#endif /* HAVE_AES_CBC || WOLFSSL_AES_DIRECT || HAVE_AESGCM */ + +#if defined(HAVE_AES_DECRYPT) +#if (defined(HAVE_AES_CBC) || defined(WOLFSSL_AES_DIRECT)) && \ + !defined(WOLFSSL_DEVCRYPTO_CBC) + +/* load 4 Td Tables into cache by cache line stride */ +static WC_INLINE word32 PreFetchTd(void) +{ + word32 x = 0; + int i,j; + + for (i = 0; i < 4; i++) { + /* 256 elements, each one is 4 bytes */ + for (j = 0; j < 256; j += WC_CACHE_LINE_SZ/4) { + x &= Td[i][j]; + } + } + return x; +} + +/* load Td Table4 into cache by cache line stride */ +static WC_INLINE word32 PreFetchTd4(void) +{ + word32 x = 0; + int i; + + for (i = 0; i < 256; i += WC_CACHE_LINE_SZ) { + x &= (word32)Td4[i]; + } + return x; +} + +/* Software AES - ECB Decrypt */ +static void wc_AesDecrypt(Aes* aes, const byte* inBlock, byte* outBlock) +{ + word32 s0, s1, s2, s3; + word32 t0, t1, t2, t3; + word32 r = aes->rounds >> 1; + + const word32* rk = aes->key; + if (r > 7 || r == 0) { + WOLFSSL_MSG("AesDecrypt encountered improper key, set it up"); + return; /* stop instead of seg-faulting, set up your keys! */ + } +#ifdef WOLFSSL_AESNI + if (haveAESNI && aes->use_aesni) { + #ifdef DEBUG_AESNI + printf("about to aes decrypt\n"); + printf("in = %p\n", inBlock); + printf("out = %p\n", outBlock); + printf("aes->key = %p\n", aes->key); + printf("aes->rounds = %d\n", aes->rounds); + printf("sz = %d\n", AES_BLOCK_SIZE); + #endif + + /* if input and output same will overwrite input iv */ + if ((const byte*)aes->tmp != inBlock) + XMEMCPY(aes->tmp, inBlock, AES_BLOCK_SIZE); + AES_ECB_decrypt(inBlock, outBlock, AES_BLOCK_SIZE, (byte*)aes->key, + aes->rounds); + return; + } + else { + #ifdef DEBUG_AESNI + printf("Skipping AES-NI\n"); + #endif + } +#endif /* WOLFSSL_AESNI */ + + /* + * map byte array block to cipher state + * and add initial round key: + */ + XMEMCPY(&s0, inBlock, sizeof(s0)); + XMEMCPY(&s1, inBlock + sizeof(s0), sizeof(s1)); + XMEMCPY(&s2, inBlock + 2 * sizeof(s0), sizeof(s2)); + XMEMCPY(&s3, inBlock + 3 * sizeof(s0), sizeof(s3)); + +#ifdef LITTLE_ENDIAN_ORDER + s0 = ByteReverseWord32(s0); + s1 = ByteReverseWord32(s1); + s2 = ByteReverseWord32(s2); + s3 = ByteReverseWord32(s3); +#endif + + s0 ^= rk[0]; + s1 ^= rk[1]; + s2 ^= rk[2]; + s3 ^= rk[3]; + + s0 |= PreFetchTd(); + + /* + * Nr - 1 full rounds: + */ + + for (;;) { + t0 = + Td[0][GETBYTE(s0, 3)] ^ + Td[1][GETBYTE(s3, 2)] ^ + Td[2][GETBYTE(s2, 1)] ^ + Td[3][GETBYTE(s1, 0)] ^ + rk[4]; + t1 = + Td[0][GETBYTE(s1, 3)] ^ + Td[1][GETBYTE(s0, 2)] ^ + Td[2][GETBYTE(s3, 1)] ^ + Td[3][GETBYTE(s2, 0)] ^ + rk[5]; + t2 = + Td[0][GETBYTE(s2, 3)] ^ + Td[1][GETBYTE(s1, 2)] ^ + Td[2][GETBYTE(s0, 1)] ^ + Td[3][GETBYTE(s3, 0)] ^ + rk[6]; + t3 = + Td[0][GETBYTE(s3, 3)] ^ + Td[1][GETBYTE(s2, 2)] ^ + Td[2][GETBYTE(s1, 1)] ^ + Td[3][GETBYTE(s0, 0)] ^ + rk[7]; + + rk += 8; + if (--r == 0) { + break; + } + + s0 = + Td[0][GETBYTE(t0, 3)] ^ + Td[1][GETBYTE(t3, 2)] ^ + Td[2][GETBYTE(t2, 1)] ^ + Td[3][GETBYTE(t1, 0)] ^ + rk[0]; + s1 = + Td[0][GETBYTE(t1, 3)] ^ + Td[1][GETBYTE(t0, 2)] ^ + Td[2][GETBYTE(t3, 1)] ^ + Td[3][GETBYTE(t2, 0)] ^ + rk[1]; + s2 = + Td[0][GETBYTE(t2, 3)] ^ + Td[1][GETBYTE(t1, 2)] ^ + Td[2][GETBYTE(t0, 1)] ^ + Td[3][GETBYTE(t3, 0)] ^ + rk[2]; + s3 = + Td[0][GETBYTE(t3, 3)] ^ + Td[1][GETBYTE(t2, 2)] ^ + Td[2][GETBYTE(t1, 1)] ^ + Td[3][GETBYTE(t0, 0)] ^ + rk[3]; + } + /* + * apply last round and + * map cipher state to byte array block: + */ + + t0 |= PreFetchTd4(); + + s0 = + ((word32)Td4[GETBYTE(t0, 3)] << 24) ^ + ((word32)Td4[GETBYTE(t3, 2)] << 16) ^ + ((word32)Td4[GETBYTE(t2, 1)] << 8) ^ + ((word32)Td4[GETBYTE(t1, 0)]) ^ + rk[0]; + s1 = + ((word32)Td4[GETBYTE(t1, 3)] << 24) ^ + ((word32)Td4[GETBYTE(t0, 2)] << 16) ^ + ((word32)Td4[GETBYTE(t3, 1)] << 8) ^ + ((word32)Td4[GETBYTE(t2, 0)]) ^ + rk[1]; + s2 = + ((word32)Td4[GETBYTE(t2, 3)] << 24) ^ + ((word32)Td4[GETBYTE(t1, 2)] << 16) ^ + ((word32)Td4[GETBYTE(t0, 1)] << 8) ^ + ((word32)Td4[GETBYTE(t3, 0)]) ^ + rk[2]; + s3 = + ((word32)Td4[GETBYTE(t3, 3)] << 24) ^ + ((word32)Td4[GETBYTE(t2, 2)] << 16) ^ + ((word32)Td4[GETBYTE(t1, 1)] << 8) ^ + ((word32)Td4[GETBYTE(t0, 0)]) ^ + rk[3]; + + /* write out */ +#ifdef LITTLE_ENDIAN_ORDER + s0 = ByteReverseWord32(s0); + s1 = ByteReverseWord32(s1); + s2 = ByteReverseWord32(s2); + s3 = ByteReverseWord32(s3); +#endif + + XMEMCPY(outBlock, &s0, sizeof(s0)); + XMEMCPY(outBlock + sizeof(s0), &s1, sizeof(s1)); + XMEMCPY(outBlock + 2 * sizeof(s0), &s2, sizeof(s2)); + XMEMCPY(outBlock + 3 * sizeof(s0), &s3, sizeof(s3)); +} +#endif /* HAVE_AES_CBC || WOLFSSL_AES_DIRECT */ +#endif /* HAVE_AES_DECRYPT */ + +#endif /* NEED_AES_TABLES */ + + + +/* wc_AesSetKey */ +#if defined(STM32_CRYPTO) + + int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, + const byte* iv, int dir) + { + word32 *rk = aes->key; + + (void)dir; + + if (keylen != 16 && + #ifdef WOLFSSL_AES_192 + keylen != 24 && + #endif + keylen != 32) { + return BAD_FUNC_ARG; + } + + aes->keylen = keylen; + aes->rounds = keylen/4 + 6; + XMEMCPY(rk, userKey, keylen); + #ifndef WOLFSSL_STM32_CUBEMX + ByteReverseWords(rk, rk, keylen); + #endif + #if defined(WOLFSSL_AES_CFB) || defined(WOLFSSL_AES_COUNTER) + aes->left = 0; + #endif + + return wc_AesSetIV(aes, iv); + } + #if defined(WOLFSSL_AES_DIRECT) + int wc_AesSetKeyDirect(Aes* aes, const byte* userKey, word32 keylen, + const byte* iv, int dir) + { + return wc_AesSetKey(aes, userKey, keylen, iv, dir); + } + #endif + +#elif defined(HAVE_COLDFIRE_SEC) + #if defined (HAVE_THREADX) + #include "memory_pools.h" + extern TX_BYTE_POOL mp_ncached; /* Non Cached memory pool */ + #endif + + #define AES_BUFFER_SIZE (AES_BLOCK_SIZE * 64) + static unsigned char *AESBuffIn = NULL; + static unsigned char *AESBuffOut = NULL; + static byte *secReg; + static byte *secKey; + static volatile SECdescriptorType *secDesc; + + static wolfSSL_Mutex Mutex_AesSEC; + + #define SEC_DESC_AES_CBC_ENCRYPT 0x60300010 + #define SEC_DESC_AES_CBC_DECRYPT 0x60200010 + + extern volatile unsigned char __MBAR[]; + + int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, + const byte* iv, int dir) + { + if (AESBuffIn == NULL) { + #if defined (HAVE_THREADX) + int s1, s2, s3, s4, s5; + s5 = tx_byte_allocate(&mp_ncached,(void *)&secDesc, + sizeof(SECdescriptorType), TX_NO_WAIT); + s1 = tx_byte_allocate(&mp_ncached, (void *)&AESBuffIn, + AES_BUFFER_SIZE, TX_NO_WAIT); + s2 = tx_byte_allocate(&mp_ncached, (void *)&AESBuffOut, + AES_BUFFER_SIZE, TX_NO_WAIT); + s3 = tx_byte_allocate(&mp_ncached, (void *)&secKey, + AES_BLOCK_SIZE*2, TX_NO_WAIT); + s4 = tx_byte_allocate(&mp_ncached, (void *)&secReg, + AES_BLOCK_SIZE, TX_NO_WAIT); + + if (s1 || s2 || s3 || s4 || s5) + return BAD_FUNC_ARG; + #else + #warning "Allocate non-Cache buffers" + #endif + + wc_InitMutex(&Mutex_AesSEC); + } + + if (!((keylen == 16) || (keylen == 24) || (keylen == 32))) + return BAD_FUNC_ARG; + + if (aes == NULL) + return BAD_FUNC_ARG; + + aes->keylen = keylen; + aes->rounds = keylen/4 + 6; + XMEMCPY(aes->key, userKey, keylen); + + if (iv) + XMEMCPY(aes->reg, iv, AES_BLOCK_SIZE); + + #if defined(WOLFSSL_AES_CFB) || defined(WOLFSSL_AES_COUNTER) + aes->left = 0; + #endif + + return 0; + } +#elif defined(FREESCALE_LTC) + int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, const byte* iv, + int dir) + { + if (aes == NULL || !((keylen == 16) || (keylen == 24) || (keylen == 32))) + return BAD_FUNC_ARG; + + aes->rounds = keylen/4 + 6; + XMEMCPY(aes->key, userKey, keylen); + + #if defined(WOLFSSL_AES_CFB) || defined(WOLFSSL_AES_COUNTER) + aes->left = 0; + #endif + + return wc_AesSetIV(aes, iv); + } + + int wc_AesSetKeyDirect(Aes* aes, const byte* userKey, word32 keylen, + const byte* iv, int dir) + { + return wc_AesSetKey(aes, userKey, keylen, iv, dir); + } +#elif defined(FREESCALE_MMCAU) + int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, + const byte* iv, int dir) + { + int ret; + byte *rk = (byte*)aes->key; + + (void)dir; + + if (!((keylen == 16) || (keylen == 24) || (keylen == 32))) + return BAD_FUNC_ARG; + + if (rk == NULL) + return BAD_FUNC_ARG; + + #if defined(WOLFSSL_AES_CFB) || defined(WOLFSSL_AES_COUNTER) + aes->left = 0; + #endif + + aes->rounds = keylen/4 + 6; + + ret = wolfSSL_CryptHwMutexLock(); + if(ret == 0) { + #ifdef FREESCALE_MMCAU_CLASSIC + cau_aes_set_key(userKey, keylen*8, rk); + #else + MMCAU_AES_SetKey(userKey, keylen, rk); + #endif + wolfSSL_CryptHwMutexUnLock(); + + ret = wc_AesSetIV(aes, iv); + } + + return ret; + } + + int wc_AesSetKeyDirect(Aes* aes, const byte* userKey, word32 keylen, + const byte* iv, int dir) + { + return wc_AesSetKey(aes, userKey, keylen, iv, dir); + } + +#elif defined(WOLFSSL_NRF51_AES) + int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, + const byte* iv, int dir) + { + int ret; + + (void)dir; + (void)iv; + + if (keylen != 16) + return BAD_FUNC_ARG; + + aes->keylen = keylen; + aes->rounds = keylen/4 + 6; + ret = nrf51_aes_set_key(userKey); + + #if defined(WOLFSSL_AES_CFB) || defined(WOLFSSL_AES_COUNTER) + aes->left = 0; + #endif + + return ret; + } + + int wc_AesSetKeyDirect(Aes* aes, const byte* userKey, word32 keylen, + const byte* iv, int dir) + { + return wc_AesSetKey(aes, userKey, keylen, iv, dir); + } +#elif defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_AES) + + int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, + const byte* iv, int dir) + { + (void)dir; + (void)iv; + + if ( aes == NULL || (keylen != 16 && keylen != 24 && keylen != 32)) { + return BAD_FUNC_ARG; + } + + aes->keylen = keylen; + aes->rounds = keylen/4 + 6; + + XMEMCPY(aes->key, userKey, keylen); + + return wc_AesSetIV(aes, iv); + } + + int wc_AesSetKeyDirect(Aes* aes, const byte* userKey, word32 keylen, + const byte* iv, int dir) + { + return wc_AesSetKey(aes, userKey, keylen, iv, dir); + } +#elif defined(WOLFSSL_CRYPTOCELL) && defined(WOLFSSL_CRYPTOCELL_AES) + + int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, const byte* iv, + int dir) + { + SaSiError_t ret = SASI_OK; + SaSiAesIv_t iv_aes; + + if (aes == NULL || + (keylen != AES_128_KEY_SIZE && + keylen != AES_192_KEY_SIZE && + keylen != AES_256_KEY_SIZE)) { + return BAD_FUNC_ARG; + } + #if defined(AES_MAX_KEY_SIZE) + if (keylen > (AES_MAX_KEY_SIZE/8)) { + return BAD_FUNC_ARG; + } + #endif + if (dir != AES_ENCRYPTION && + dir != AES_DECRYPTION) { + return BAD_FUNC_ARG; + } + + if (dir == AES_ENCRYPTION) { + aes->ctx.mode = SASI_AES_ENCRYPT; + SaSi_AesInit(&aes->ctx.user_ctx, + SASI_AES_ENCRYPT, + SASI_AES_MODE_CBC, + SASI_AES_PADDING_NONE); + } + else { + aes->ctx.mode = SASI_AES_DECRYPT; + SaSi_AesInit(&aes->ctx.user_ctx, + SASI_AES_DECRYPT, + SASI_AES_MODE_CBC, + SASI_AES_PADDING_NONE); + } + + aes->keylen = keylen; + aes->rounds = keylen/4 + 6; + XMEMCPY(aes->key, userKey, keylen); + + aes->ctx.key.pKey = (uint8_t*)aes->key; + aes->ctx.key.keySize= keylen; + + ret = SaSi_AesSetKey(&aes->ctx.user_ctx, + SASI_AES_USER_KEY, + &aes->ctx.key, + sizeof(aes->ctx.key)); + if (ret != SASI_OK) { + return BAD_FUNC_ARG; + } + + ret = wc_AesSetIV(aes, iv); + + if (iv) + XMEMCPY(iv_aes, iv, AES_BLOCK_SIZE); + else + XMEMSET(iv_aes, 0, AES_BLOCK_SIZE); + + + ret = SaSi_AesSetIv(&aes->ctx.user_ctx, iv_aes); + if (ret != SASI_OK) { + return ret; + } + return ret; + } + #if defined(WOLFSSL_AES_DIRECT) + int wc_AesSetKeyDirect(Aes* aes, const byte* userKey, word32 keylen, + const byte* iv, int dir) + { + return wc_AesSetKey(aes, userKey, keylen, iv, dir); + } + #endif + +#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES) + /* implemented in wolfcrypt/src/port/caam/caam_aes.c */ + +#elif defined(WOLFSSL_AFALG) + /* implemented in wolfcrypt/src/port/af_alg/afalg_aes.c */ + +#elif defined(WOLFSSL_DEVCRYPTO_AES) + /* implemented in wolfcrypt/src/port/devcrypto/devcrypto_aes.c */ + +#else + + /* Software AES - SetKey */ + static int wc_AesSetKeyLocal(Aes* aes, const byte* userKey, word32 keylen, + const byte* iv, int dir) + { + word32 *rk = aes->key; + #ifdef NEED_AES_TABLES + word32 temp; + unsigned int i = 0; + #endif + + #ifdef WOLFSSL_AESNI + aes->use_aesni = 0; + #endif /* WOLFSSL_AESNI */ + #if defined(WOLFSSL_AES_CFB) || defined(WOLFSSL_AES_COUNTER) + aes->left = 0; + #endif + + aes->keylen = keylen; + aes->rounds = (keylen/4) + 6; + + XMEMCPY(rk, userKey, keylen); + #if defined(LITTLE_ENDIAN_ORDER) && !defined(WOLFSSL_PIC32MZ_CRYPT) && \ + (!defined(WOLFSSL_ESP32WROOM32_CRYPT) || \ + defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_AES)) + ByteReverseWords(rk, rk, keylen); + #endif + +#ifdef NEED_AES_TABLES + + switch (keylen) { + #if defined(AES_MAX_KEY_SIZE) && AES_MAX_KEY_SIZE >= 128 && \ + defined(WOLFSSL_AES_128) + case 16: + while (1) + { + temp = rk[3]; + rk[4] = rk[0] ^ + (Te[2][GETBYTE(temp, 2)] & 0xff000000) ^ + (Te[3][GETBYTE(temp, 1)] & 0x00ff0000) ^ + (Te[0][GETBYTE(temp, 0)] & 0x0000ff00) ^ + (Te[1][GETBYTE(temp, 3)] & 0x000000ff) ^ + rcon[i]; + rk[5] = rk[1] ^ rk[4]; + rk[6] = rk[2] ^ rk[5]; + rk[7] = rk[3] ^ rk[6]; + if (++i == 10) + break; + rk += 4; + } + break; + #endif /* 128 */ + + #if defined(AES_MAX_KEY_SIZE) && AES_MAX_KEY_SIZE >= 192 && \ + defined(WOLFSSL_AES_192) + case 24: + /* for (;;) here triggers a bug in VC60 SP4 w/ Pro Pack */ + while (1) + { + temp = rk[ 5]; + rk[ 6] = rk[ 0] ^ + (Te[2][GETBYTE(temp, 2)] & 0xff000000) ^ + (Te[3][GETBYTE(temp, 1)] & 0x00ff0000) ^ + (Te[0][GETBYTE(temp, 0)] & 0x0000ff00) ^ + (Te[1][GETBYTE(temp, 3)] & 0x000000ff) ^ + rcon[i]; + rk[ 7] = rk[ 1] ^ rk[ 6]; + rk[ 8] = rk[ 2] ^ rk[ 7]; + rk[ 9] = rk[ 3] ^ rk[ 8]; + if (++i == 8) + break; + rk[10] = rk[ 4] ^ rk[ 9]; + rk[11] = rk[ 5] ^ rk[10]; + rk += 6; + } + break; + #endif /* 192 */ + + #if defined(AES_MAX_KEY_SIZE) && AES_MAX_KEY_SIZE >= 256 && \ + defined(WOLFSSL_AES_256) + case 32: + while (1) + { + temp = rk[ 7]; + rk[ 8] = rk[ 0] ^ + (Te[2][GETBYTE(temp, 2)] & 0xff000000) ^ + (Te[3][GETBYTE(temp, 1)] & 0x00ff0000) ^ + (Te[0][GETBYTE(temp, 0)] & 0x0000ff00) ^ + (Te[1][GETBYTE(temp, 3)] & 0x000000ff) ^ + rcon[i]; + rk[ 9] = rk[ 1] ^ rk[ 8]; + rk[10] = rk[ 2] ^ rk[ 9]; + rk[11] = rk[ 3] ^ rk[10]; + if (++i == 7) + break; + temp = rk[11]; + rk[12] = rk[ 4] ^ + (Te[2][GETBYTE(temp, 3)] & 0xff000000) ^ + (Te[3][GETBYTE(temp, 2)] & 0x00ff0000) ^ + (Te[0][GETBYTE(temp, 1)] & 0x0000ff00) ^ + (Te[1][GETBYTE(temp, 0)] & 0x000000ff); + rk[13] = rk[ 5] ^ rk[12]; + rk[14] = rk[ 6] ^ rk[13]; + rk[15] = rk[ 7] ^ rk[14]; + + rk += 8; + } + break; + #endif /* 256 */ + + default: + return BAD_FUNC_ARG; + } /* switch */ + + #ifdef HAVE_AES_DECRYPT + if (dir == AES_DECRYPTION) { + unsigned int j; + rk = aes->key; + + /* invert the order of the round keys: */ + for (i = 0, j = 4* aes->rounds; i < j; i += 4, j -= 4) { + temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp; + temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp; + temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp; + temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp; + } + /* apply the inverse MixColumn transform to all round keys but the + first and the last: */ + for (i = 1; i < aes->rounds; i++) { + rk += 4; + rk[0] = + Td[0][Te[1][GETBYTE(rk[0], 3)] & 0xff] ^ + Td[1][Te[1][GETBYTE(rk[0], 2)] & 0xff] ^ + Td[2][Te[1][GETBYTE(rk[0], 1)] & 0xff] ^ + Td[3][Te[1][GETBYTE(rk[0], 0)] & 0xff]; + rk[1] = + Td[0][Te[1][GETBYTE(rk[1], 3)] & 0xff] ^ + Td[1][Te[1][GETBYTE(rk[1], 2)] & 0xff] ^ + Td[2][Te[1][GETBYTE(rk[1], 1)] & 0xff] ^ + Td[3][Te[1][GETBYTE(rk[1], 0)] & 0xff]; + rk[2] = + Td[0][Te[1][GETBYTE(rk[2], 3)] & 0xff] ^ + Td[1][Te[1][GETBYTE(rk[2], 2)] & 0xff] ^ + Td[2][Te[1][GETBYTE(rk[2], 1)] & 0xff] ^ + Td[3][Te[1][GETBYTE(rk[2], 0)] & 0xff]; + rk[3] = + Td[0][Te[1][GETBYTE(rk[3], 3)] & 0xff] ^ + Td[1][Te[1][GETBYTE(rk[3], 2)] & 0xff] ^ + Td[2][Te[1][GETBYTE(rk[3], 1)] & 0xff] ^ + Td[3][Te[1][GETBYTE(rk[3], 0)] & 0xff]; + } + } + #else + (void)dir; + #endif /* HAVE_AES_DECRYPT */ +#endif /* NEED_AES_TABLES */ + + return wc_AesSetIV(aes, iv); + } + + int wc_AesSetKey(Aes* aes, const byte* userKey, word32 keylen, + const byte* iv, int dir) + { + int ret; + #if defined(AES_MAX_KEY_SIZE) + const word32 max_key_len = (AES_MAX_KEY_SIZE / 8); + #endif + + #ifdef WOLFSSL_IMX6_CAAM_BLOB + byte local[32]; + word32 localSz = 32; + + if (keylen == (16 + WC_CAAM_BLOB_SZ) || + keylen == (24 + WC_CAAM_BLOB_SZ) || + keylen == (32 + WC_CAAM_BLOB_SZ)) { + if (wc_caamOpenBlob((byte*)userKey, keylen, local, &localSz) != 0) { + return BAD_FUNC_ARG; + } + + /* set local values */ + userKey = local; + keylen = localSz; + } + #endif + if (aes == NULL || + !((keylen == 16) || (keylen == 24) || (keylen == 32))) { + return BAD_FUNC_ARG; + } + + #if defined(AES_MAX_KEY_SIZE) + /* Check key length */ + if (keylen > max_key_len) { + return BAD_FUNC_ARG; + } + #endif + aes->keylen = keylen; + aes->rounds = keylen/4 + 6; + + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES) + if (aes->asyncDev.marker == WOLFSSL_ASYNC_MARKER_AES) { + XMEMCPY(aes->asyncKey, userKey, keylen); + if (iv) + XMEMCPY(aes->asyncIv, iv, AES_BLOCK_SIZE); + } + #endif /* WOLFSSL_ASYNC_CRYPT */ + #ifdef WOLF_CRYPTO_CB + if (aes->devId != INVALID_DEVID) { + XMEMCPY(aes->devKey, userKey, keylen); + } + #endif + + #ifdef WOLFSSL_AESNI + if (checkAESNI == 0) { + haveAESNI = Check_CPU_support_AES(); + checkAESNI = 1; + } + if (haveAESNI) { + #if defined(WOLFSSL_AES_COUNTER) || defined(WOLFSSL_AES_CFB) + aes->left = 0; + #endif /* WOLFSSL_AES_COUNTER */ + aes->use_aesni = 1; + if (iv) + XMEMCPY(aes->reg, iv, AES_BLOCK_SIZE); + if (dir == AES_ENCRYPTION) + return AES_set_encrypt_key(userKey, keylen * 8, aes); + #ifdef HAVE_AES_DECRYPT + else + return AES_set_decrypt_key(userKey, keylen * 8, aes); + #endif + } + #endif /* WOLFSSL_AESNI */ + + ret = wc_AesSetKeyLocal(aes, userKey, keylen, iv, dir); + + #if defined(WOLFSSL_DEVCRYPTO) && \ + (defined(WOLFSSL_DEVCRYPTO_AES) || defined(WOLFSSL_DEVCRYPTO_CBC)) + aes->ctx.cfd = -1; + XMEMCPY(aes->devKey, userKey, keylen); + #endif + #ifdef WOLFSSL_IMX6_CAAM_BLOB + ForceZero(local, sizeof(local)); + #endif + return ret; + } + + #if defined(WOLFSSL_AES_DIRECT) || defined(WOLFSSL_AES_COUNTER) + /* AES-CTR and AES-DIRECT need to use this for key setup, no aesni yet */ + int wc_AesSetKeyDirect(Aes* aes, const byte* userKey, word32 keylen, + const byte* iv, int dir) + { + int ret; + + #ifdef WOLFSSL_IMX6_CAAM_BLOB + byte local[32]; + word32 localSz = 32; + + if (keylen == (16 + WC_CAAM_BLOB_SZ) || + keylen == (24 + WC_CAAM_BLOB_SZ) || + keylen == (32 + WC_CAAM_BLOB_SZ)) { + if (wc_caamOpenBlob((byte*)userKey, keylen, local, &localSz) + != 0) { + return BAD_FUNC_ARG; + } + + /* set local values */ + userKey = local; + keylen = localSz; + } + #endif + ret = wc_AesSetKeyLocal(aes, userKey, keylen, iv, dir); + + #ifdef WOLFSSL_IMX6_CAAM_BLOB + ForceZero(local, sizeof(local)); + #endif + + return ret; + } + #endif /* WOLFSSL_AES_DIRECT || WOLFSSL_AES_COUNTER */ +#endif /* wc_AesSetKey block */ + + +/* wc_AesSetIV is shared between software and hardware */ +int wc_AesSetIV(Aes* aes, const byte* iv) +{ + if (aes == NULL) + return BAD_FUNC_ARG; + + if (iv) + XMEMCPY(aes->reg, iv, AES_BLOCK_SIZE); + else + XMEMSET(aes->reg, 0, AES_BLOCK_SIZE); + + return 0; +} + +/* AES-DIRECT */ +#if defined(WOLFSSL_AES_DIRECT) + #if defined(HAVE_COLDFIRE_SEC) + #error "Coldfire SEC doesn't yet support AES direct" + + #elif defined(FREESCALE_LTC) + /* Allow direct access to one block encrypt */ + void wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in) + { + byte *key; + uint32_t keySize; + + key = (byte*)aes->key; + wc_AesGetKeySize(aes, &keySize); + + LTC_AES_EncryptEcb(LTC_BASE, in, out, AES_BLOCK_SIZE, + key, keySize); + } + + /* Allow direct access to one block decrypt */ + void wc_AesDecryptDirect(Aes* aes, byte* out, const byte* in) + { + byte *key; + uint32_t keySize; + + key = (byte*)aes->key; + wc_AesGetKeySize(aes, &keySize); + + LTC_AES_DecryptEcb(LTC_BASE, in, out, AES_BLOCK_SIZE, + key, keySize, kLTC_EncryptKey); + } + + #elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES) + /* implemented in wolfcrypt/src/port/caam/caam_aes.c */ + + #elif defined(WOLFSSL_AFALG) + /* implemented in wolfcrypt/src/port/af_alg/afalg_aes.c */ + + #elif defined(WOLFSSL_DEVCRYPTO_AES) + /* implemented in wolfcrypt/src/port/devcrypt/devcrypto_aes.c */ + + #else + /* Allow direct access to one block encrypt */ + void wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in) + { + wc_AesEncrypt(aes, in, out); + } + #ifdef HAVE_AES_DECRYPT + /* Allow direct access to one block decrypt */ + void wc_AesDecryptDirect(Aes* aes, byte* out, const byte* in) + { + wc_AesDecrypt(aes, in, out); + } + #endif /* HAVE_AES_DECRYPT */ + #endif /* AES direct block */ +#endif /* WOLFSSL_AES_DIRECT */ + + +/* AES-CBC */ +#ifdef HAVE_AES_CBC +#if defined(STM32_CRYPTO) + +#ifdef WOLFSSL_STM32_CUBEMX + int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + int ret = 0; + word32 blocks = (sz / AES_BLOCK_SIZE); + CRYP_HandleTypeDef hcryp; + + ret = wc_Stm32_Aes_Init(aes, &hcryp); + if (ret != 0) + return ret; + + #ifdef STM32_CRYPTO_AES_ONLY + hcryp.Init.OperatingMode = CRYP_ALGOMODE_ENCRYPT; + hcryp.Init.ChainingMode = CRYP_CHAINMODE_AES_CBC; + hcryp.Init.KeyWriteFlag = CRYP_KEY_WRITE_ENABLE; + #endif + hcryp.Init.pInitVect = (uint8_t*)aes->reg; + HAL_CRYP_Init(&hcryp); + + while (blocks--) { + #ifdef STM32_CRYPTO_AES_ONLY + ret = HAL_CRYPEx_AES(&hcryp, (uint8_t*)in, AES_BLOCK_SIZE, + out, STM32_HAL_TIMEOUT); + #else + ret = HAL_CRYP_AESCBC_Encrypt(&hcryp, (uint8_t*)in, AES_BLOCK_SIZE, + out, STM32_HAL_TIMEOUT); + #endif + if (ret != HAL_OK) { + ret = WC_TIMEOUT_E; + break; + } + + /* store iv for next call */ + XMEMCPY(aes->reg, out + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + + sz -= AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + } + + HAL_CRYP_DeInit(&hcryp); + + return ret; + } + #ifdef HAVE_AES_DECRYPT + int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + int ret = 0; + word32 blocks = (sz / AES_BLOCK_SIZE); + CRYP_HandleTypeDef hcryp; + + ret = wc_Stm32_Aes_Init(aes, &hcryp); + if (ret != 0) + return ret; + + /* if input and output same will overwrite input iv */ + XMEMCPY(aes->tmp, in + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + + #ifdef STM32_CRYPTO_AES_ONLY + hcryp.Init.OperatingMode = CRYP_ALGOMODE_KEYDERIVATION_DECRYPT; + hcryp.Init.ChainingMode = CRYP_CHAINMODE_AES_CBC; + hcryp.Init.KeyWriteFlag = CRYP_KEY_WRITE_ENABLE; + #endif + + hcryp.Init.pInitVect = (uint8_t*)aes->reg; + HAL_CRYP_Init(&hcryp); + + while (blocks--) { + #ifdef STM32_CRYPTO_AES_ONLY + ret = HAL_CRYPEx_AES(&hcryp, (uint8_t*)in, AES_BLOCK_SIZE, + out, STM32_HAL_TIMEOUT); + #else + ret = HAL_CRYP_AESCBC_Decrypt(&hcryp, (uint8_t*)in, AES_BLOCK_SIZE, + out, STM32_HAL_TIMEOUT); + #endif + if (ret != HAL_OK) { + ret = WC_TIMEOUT_E; + break; + } + + /* store iv for next call */ + XMEMCPY(aes->reg, aes->tmp, AES_BLOCK_SIZE); + + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + } + + HAL_CRYP_DeInit(&hcryp); + + return ret; + } + #endif /* HAVE_AES_DECRYPT */ + +#else /* STD_PERI_LIB */ + int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + int ret; + word32 *iv; + word32 blocks = (sz / AES_BLOCK_SIZE); + CRYP_InitTypeDef cryptInit; + CRYP_KeyInitTypeDef keyInit; + CRYP_IVInitTypeDef ivInit; + + ret = wc_Stm32_Aes_Init(aes, &cryptInit, &keyInit); + if (ret != 0) + return ret; + + /* reset registers to their default values */ + CRYP_DeInit(); + + /* set key */ + CRYP_KeyInit(&keyInit); + + /* set iv */ + iv = aes->reg; + CRYP_IVStructInit(&ivInit); + ByteReverseWords(iv, iv, AES_BLOCK_SIZE); + ivInit.CRYP_IV0Left = iv[0]; + ivInit.CRYP_IV0Right = iv[1]; + ivInit.CRYP_IV1Left = iv[2]; + ivInit.CRYP_IV1Right = iv[3]; + CRYP_IVInit(&ivInit); + + /* set direction and mode */ + cryptInit.CRYP_AlgoDir = CRYP_AlgoDir_Encrypt; + cryptInit.CRYP_AlgoMode = CRYP_AlgoMode_AES_CBC; + CRYP_Init(&cryptInit); + + /* enable crypto processor */ + CRYP_Cmd(ENABLE); + + while (blocks--) { + /* flush IN/OUT FIFOs */ + CRYP_FIFOFlush(); + + CRYP_DataIn(*(uint32_t*)&in[0]); + CRYP_DataIn(*(uint32_t*)&in[4]); + CRYP_DataIn(*(uint32_t*)&in[8]); + CRYP_DataIn(*(uint32_t*)&in[12]); + + /* wait until the complete message has been processed */ + while (CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {} + + *(uint32_t*)&out[0] = CRYP_DataOut(); + *(uint32_t*)&out[4] = CRYP_DataOut(); + *(uint32_t*)&out[8] = CRYP_DataOut(); + *(uint32_t*)&out[12] = CRYP_DataOut(); + + /* store iv for next call */ + XMEMCPY(aes->reg, out + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + + sz -= AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + } + + /* disable crypto processor */ + CRYP_Cmd(DISABLE); + + return ret; + } + + #ifdef HAVE_AES_DECRYPT + int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + int ret; + word32 *iv; + word32 blocks = (sz / AES_BLOCK_SIZE); + CRYP_InitTypeDef cryptInit; + CRYP_KeyInitTypeDef keyInit; + CRYP_IVInitTypeDef ivInit; + + ret = wc_Stm32_Aes_Init(aes, &cryptInit, &keyInit); + if (ret != 0) + return ret; + + /* if input and output same will overwrite input iv */ + XMEMCPY(aes->tmp, in + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + + /* reset registers to their default values */ + CRYP_DeInit(); + + /* set direction and key */ + CRYP_KeyInit(&keyInit); + cryptInit.CRYP_AlgoDir = CRYP_AlgoDir_Decrypt; + cryptInit.CRYP_AlgoMode = CRYP_AlgoMode_AES_Key; + CRYP_Init(&cryptInit); + + /* enable crypto processor */ + CRYP_Cmd(ENABLE); + + /* wait until key has been prepared */ + while (CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {} + + /* set direction and mode */ + cryptInit.CRYP_AlgoDir = CRYP_AlgoDir_Decrypt; + cryptInit.CRYP_AlgoMode = CRYP_AlgoMode_AES_CBC; + CRYP_Init(&cryptInit); + + /* set iv */ + iv = aes->reg; + CRYP_IVStructInit(&ivInit); + ByteReverseWords(iv, iv, AES_BLOCK_SIZE); + ivInit.CRYP_IV0Left = iv[0]; + ivInit.CRYP_IV0Right = iv[1]; + ivInit.CRYP_IV1Left = iv[2]; + ivInit.CRYP_IV1Right = iv[3]; + CRYP_IVInit(&ivInit); + + /* enable crypto processor */ + CRYP_Cmd(ENABLE); + + while (blocks--) { + /* flush IN/OUT FIFOs */ + CRYP_FIFOFlush(); + + CRYP_DataIn(*(uint32_t*)&in[0]); + CRYP_DataIn(*(uint32_t*)&in[4]); + CRYP_DataIn(*(uint32_t*)&in[8]); + CRYP_DataIn(*(uint32_t*)&in[12]); + + /* wait until the complete message has been processed */ + while (CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {} + + *(uint32_t*)&out[0] = CRYP_DataOut(); + *(uint32_t*)&out[4] = CRYP_DataOut(); + *(uint32_t*)&out[8] = CRYP_DataOut(); + *(uint32_t*)&out[12] = CRYP_DataOut(); + + /* store iv for next call */ + XMEMCPY(aes->reg, aes->tmp, AES_BLOCK_SIZE); + + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + } + + /* disable crypto processor */ + CRYP_Cmd(DISABLE); + + return ret; + } + #endif /* HAVE_AES_DECRYPT */ +#endif /* WOLFSSL_STM32_CUBEMX */ + +#elif defined(HAVE_COLDFIRE_SEC) + static int wc_AesCbcCrypt(Aes* aes, byte* po, const byte* pi, word32 sz, + word32 descHeader) + { + #ifdef DEBUG_WOLFSSL + int i; int stat1, stat2; int ret; + #endif + + int size; + volatile int v; + + if ((pi == NULL) || (po == NULL)) + return BAD_FUNC_ARG; /*wrong pointer*/ + + wc_LockMutex(&Mutex_AesSEC); + + /* Set descriptor for SEC */ + secDesc->length1 = 0x0; + secDesc->pointer1 = NULL; + + secDesc->length2 = AES_BLOCK_SIZE; + secDesc->pointer2 = (byte *)secReg; /* Initial Vector */ + + switch(aes->rounds) { + case 10: secDesc->length3 = 16; break; + case 12: secDesc->length3 = 24; break; + case 14: secDesc->length3 = 32; break; + } + XMEMCPY(secKey, aes->key, secDesc->length3); + + secDesc->pointer3 = (byte *)secKey; + secDesc->pointer4 = AESBuffIn; + secDesc->pointer5 = AESBuffOut; + secDesc->length6 = 0x0; + secDesc->pointer6 = NULL; + secDesc->length7 = 0x0; + secDesc->pointer7 = NULL; + secDesc->nextDescriptorPtr = NULL; + + while (sz) { + secDesc->header = descHeader; + XMEMCPY(secReg, aes->reg, AES_BLOCK_SIZE); + if ((sz % AES_BUFFER_SIZE) == sz) { + size = sz; + sz = 0; + } else { + size = AES_BUFFER_SIZE; + sz -= AES_BUFFER_SIZE; + } + secDesc->length4 = size; + secDesc->length5 = size; + + XMEMCPY(AESBuffIn, pi, size); + if(descHeader == SEC_DESC_AES_CBC_DECRYPT) { + XMEMCPY((void*)aes->tmp, (void*)&(pi[size-AES_BLOCK_SIZE]), + AES_BLOCK_SIZE); + } + + /* Point SEC to the location of the descriptor */ + MCF_SEC_FR0 = (uint32)secDesc; + /* Initialize SEC and wait for encryption to complete */ + MCF_SEC_CCCR0 = 0x0000001a; + /* poll SISR to determine when channel is complete */ + v=0; + + while ((secDesc->header>> 24) != 0xff) v++; + + #ifdef DEBUG_WOLFSSL + ret = MCF_SEC_SISRH; + stat1 = MCF_SEC_AESSR; + stat2 = MCF_SEC_AESISR; + if (ret & 0xe0000000) { + db_printf("Aes_Cbc(i=%d):ISRH=%08x, AESSR=%08x, " + "AESISR=%08x\n", i, ret, stat1, stat2); + } + #endif + + XMEMCPY(po, AESBuffOut, size); + + if (descHeader == SEC_DESC_AES_CBC_ENCRYPT) { + XMEMCPY((void*)aes->reg, (void*)&(po[size-AES_BLOCK_SIZE]), + AES_BLOCK_SIZE); + } else { + XMEMCPY((void*)aes->reg, (void*)aes->tmp, AES_BLOCK_SIZE); + } + + pi += size; + po += size; + } + + wc_UnLockMutex(&Mutex_AesSEC); + return 0; + } + + int wc_AesCbcEncrypt(Aes* aes, byte* po, const byte* pi, word32 sz) + { + return (wc_AesCbcCrypt(aes, po, pi, sz, SEC_DESC_AES_CBC_ENCRYPT)); + } + + #ifdef HAVE_AES_DECRYPT + int wc_AesCbcDecrypt(Aes* aes, byte* po, const byte* pi, word32 sz) + { + return (wc_AesCbcCrypt(aes, po, pi, sz, SEC_DESC_AES_CBC_DECRYPT)); + } + #endif /* HAVE_AES_DECRYPT */ + +#elif defined(FREESCALE_LTC) + int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + uint32_t keySize; + status_t status; + byte *iv, *enc_key; + word32 blocks = (sz / AES_BLOCK_SIZE); + + iv = (byte*)aes->reg; + enc_key = (byte*)aes->key; + + status = wc_AesGetKeySize(aes, &keySize); + if (status != 0) { + return status; + } + + status = LTC_AES_EncryptCbc(LTC_BASE, in, out, blocks * AES_BLOCK_SIZE, + iv, enc_key, keySize); + + /* store iv for next call */ + if (status == kStatus_Success) { + XMEMCPY(iv, out + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + } + + return (status == kStatus_Success) ? 0 : -1; + } + + #ifdef HAVE_AES_DECRYPT + int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + uint32_t keySize; + status_t status; + byte* iv, *dec_key; + word32 blocks = (sz / AES_BLOCK_SIZE); + byte temp_block[AES_BLOCK_SIZE]; + + iv = (byte*)aes->reg; + dec_key = (byte*)aes->key; + + status = wc_AesGetKeySize(aes, &keySize); + if (status != 0) { + return status; + } + + /* get IV for next call */ + XMEMCPY(temp_block, in + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + + status = LTC_AES_DecryptCbc(LTC_BASE, in, out, blocks * AES_BLOCK_SIZE, + iv, dec_key, keySize, kLTC_EncryptKey); + + /* store IV for next call */ + if (status == kStatus_Success) { + XMEMCPY(iv, temp_block, AES_BLOCK_SIZE); + } + + return (status == kStatus_Success) ? 0 : -1; + } + #endif /* HAVE_AES_DECRYPT */ + +#elif defined(FREESCALE_MMCAU) + int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + int i; + int offset = 0; + word32 blocks = (sz / AES_BLOCK_SIZE); + byte *iv; + byte temp_block[AES_BLOCK_SIZE]; + + iv = (byte*)aes->reg; + + while (blocks--) { + XMEMCPY(temp_block, in + offset, AES_BLOCK_SIZE); + + /* XOR block with IV for CBC */ + for (i = 0; i < AES_BLOCK_SIZE; i++) + temp_block[i] ^= iv[i]; + + wc_AesEncrypt(aes, temp_block, out + offset); + + offset += AES_BLOCK_SIZE; + + /* store IV for next block */ + XMEMCPY(iv, out + offset - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + } + + return 0; + } + #ifdef HAVE_AES_DECRYPT + int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + int i; + int offset = 0; + word32 blocks = (sz / AES_BLOCK_SIZE); + byte* iv; + byte temp_block[AES_BLOCK_SIZE]; + + iv = (byte*)aes->reg; + + while (blocks--) { + XMEMCPY(temp_block, in + offset, AES_BLOCK_SIZE); + + wc_AesDecrypt(aes, in + offset, out + offset); + + /* XOR block with IV for CBC */ + for (i = 0; i < AES_BLOCK_SIZE; i++) + (out + offset)[i] ^= iv[i]; + + /* store IV for next block */ + XMEMCPY(iv, temp_block, AES_BLOCK_SIZE); + + offset += AES_BLOCK_SIZE; + } + + return 0; + } + #endif /* HAVE_AES_DECRYPT */ + +#elif defined(WOLFSSL_PIC32MZ_CRYPT) + + int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + int ret; + + /* hardware fails on input that is not a multiple of AES block size */ + if (sz % AES_BLOCK_SIZE != 0) { + return BAD_FUNC_ARG; + } + + ret = wc_Pic32AesCrypt( + aes->key, aes->keylen, aes->reg, AES_BLOCK_SIZE, + out, in, sz, PIC32_ENCRYPTION, + PIC32_ALGO_AES, PIC32_CRYPTOALGO_RCBC); + + /* store iv for next call */ + if (ret == 0) { + XMEMCPY(aes->reg, out + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + } + + return ret; + } + #ifdef HAVE_AES_DECRYPT + int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + int ret; + byte scratch[AES_BLOCK_SIZE]; + + /* hardware fails on input that is not a multiple of AES block size */ + if (sz % AES_BLOCK_SIZE != 0) { + return BAD_FUNC_ARG; + } + XMEMCPY(scratch, in + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + + ret = wc_Pic32AesCrypt( + aes->key, aes->keylen, aes->reg, AES_BLOCK_SIZE, + out, in, sz, PIC32_DECRYPTION, + PIC32_ALGO_AES, PIC32_CRYPTOALGO_RCBC); + + /* store iv for next call */ + if (ret == 0) { + XMEMCPY((byte*)aes->reg, scratch, AES_BLOCK_SIZE); + } + + return ret; + } + #endif /* HAVE_AES_DECRYPT */ +#elif defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_AES) + + int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + return wc_esp32AesCbcEncrypt(aes, out, in, sz); + } + int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + return wc_esp32AesCbcDecrypt(aes, out, in, sz); + } +#elif defined(WOLFSSL_CRYPTOCELL) && defined(WOLFSSL_CRYPTOCELL_AES) + int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + return SaSi_AesBlock(&aes->ctx.user_ctx, (uint8_t* )in, sz, out); + } + int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + return SaSi_AesBlock(&aes->ctx.user_ctx, (uint8_t* )in, sz, out); + } +#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES) + /* implemented in wolfcrypt/src/port/caam/caam_aes.c */ + +#elif defined(WOLFSSL_AFALG) + /* implemented in wolfcrypt/src/port/af_alg/afalg_aes.c */ + +#elif defined(WOLFSSL_DEVCRYPTO_CBC) + /* implemented in wolfcrypt/src/port/devcrypt/devcrypto_aes.c */ + +#else + + /* Software AES - CBC Encrypt */ + int wc_AesCbcEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + word32 blocks = (sz / AES_BLOCK_SIZE); + + if (aes == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + + #ifdef WOLF_CRYPTO_CB + if (aes->devId != INVALID_DEVID) { + int ret = wc_CryptoCb_AesCbcEncrypt(aes, out, in, sz); + if (ret != CRYPTOCB_UNAVAILABLE) + return ret; + /* fall-through when unavailable */ + } + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES) + /* if async and byte count above threshold */ + if (aes->asyncDev.marker == WOLFSSL_ASYNC_MARKER_AES && + sz >= WC_ASYNC_THRESH_AES_CBC) { + #if defined(HAVE_CAVIUM) + return NitroxAesCbcEncrypt(aes, out, in, sz); + #elif defined(HAVE_INTEL_QA) + return IntelQaSymAesCbcEncrypt(&aes->asyncDev, out, in, sz, + (const byte*)aes->asyncKey, aes->keylen, + (const byte*)aes->asyncIv, AES_BLOCK_SIZE); + #else /* WOLFSSL_ASYNC_CRYPT_TEST */ + if (wc_AsyncTestInit(&aes->asyncDev, ASYNC_TEST_AES_CBC_ENCRYPT)) { + WC_ASYNC_TEST* testDev = &aes->asyncDev.test; + testDev->aes.aes = aes; + testDev->aes.out = out; + testDev->aes.in = in; + testDev->aes.sz = sz; + return WC_PENDING_E; + } + #endif + } + #endif /* WOLFSSL_ASYNC_CRYPT */ + + #ifdef WOLFSSL_AESNI + if (haveAESNI) { + #ifdef DEBUG_AESNI + printf("about to aes cbc encrypt\n"); + printf("in = %p\n", in); + printf("out = %p\n", out); + printf("aes->key = %p\n", aes->key); + printf("aes->reg = %p\n", aes->reg); + printf("aes->rounds = %d\n", aes->rounds); + printf("sz = %d\n", sz); + #endif + + /* check alignment, decrypt doesn't need alignment */ + if ((wolfssl_word)in % AESNI_ALIGN) { + #ifndef NO_WOLFSSL_ALLOC_ALIGN + byte* tmp = (byte*)XMALLOC(sz + AES_BLOCK_SIZE + AESNI_ALIGN, + aes->heap, DYNAMIC_TYPE_TMP_BUFFER); + byte* tmp_align; + if (tmp == NULL) return MEMORY_E; + + tmp_align = tmp + (AESNI_ALIGN - ((size_t)tmp % AESNI_ALIGN)); + XMEMCPY(tmp_align, in, sz); + AES_CBC_encrypt(tmp_align, tmp_align, (byte*)aes->reg, sz, + (byte*)aes->key, aes->rounds); + /* store iv for next call */ + XMEMCPY(aes->reg, tmp_align + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + + XMEMCPY(out, tmp_align, sz); + XFREE(tmp, aes->heap, DYNAMIC_TYPE_TMP_BUFFER); + return 0; + #else + WOLFSSL_MSG("AES-CBC encrypt with bad alignment"); + return BAD_ALIGN_E; + #endif + } + + AES_CBC_encrypt(in, out, (byte*)aes->reg, sz, (byte*)aes->key, + aes->rounds); + /* store iv for next call */ + XMEMCPY(aes->reg, out + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + + return 0; + } + #endif + + while (blocks--) { + xorbuf((byte*)aes->reg, in, AES_BLOCK_SIZE); + wc_AesEncrypt(aes, (byte*)aes->reg, (byte*)aes->reg); + XMEMCPY(out, aes->reg, AES_BLOCK_SIZE); + + out += AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; + } + + return 0; + } + + #ifdef HAVE_AES_DECRYPT + /* Software AES - CBC Decrypt */ + int wc_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + word32 blocks; + + if (aes == NULL || out == NULL || in == NULL + || sz % AES_BLOCK_SIZE != 0) { + return BAD_FUNC_ARG; + } + + #ifdef WOLF_CRYPTO_CB + if (aes->devId != INVALID_DEVID) { + int ret = wc_CryptoCb_AesCbcDecrypt(aes, out, in, sz); + if (ret != CRYPTOCB_UNAVAILABLE) + return ret; + /* fall-through when unavailable */ + } + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES) + /* if async and byte count above threshold */ + if (aes->asyncDev.marker == WOLFSSL_ASYNC_MARKER_AES && + sz >= WC_ASYNC_THRESH_AES_CBC) { + #if defined(HAVE_CAVIUM) + return NitroxAesCbcDecrypt(aes, out, in, sz); + #elif defined(HAVE_INTEL_QA) + return IntelQaSymAesCbcDecrypt(&aes->asyncDev, out, in, sz, + (const byte*)aes->asyncKey, aes->keylen, + (const byte*)aes->asyncIv, AES_BLOCK_SIZE); + #else /* WOLFSSL_ASYNC_CRYPT_TEST */ + if (wc_AsyncTestInit(&aes->asyncDev, ASYNC_TEST_AES_CBC_DECRYPT)) { + WC_ASYNC_TEST* testDev = &aes->asyncDev.test; + testDev->aes.aes = aes; + testDev->aes.out = out; + testDev->aes.in = in; + testDev->aes.sz = sz; + return WC_PENDING_E; + } + #endif + } + #endif + + #ifdef WOLFSSL_AESNI + if (haveAESNI) { + #ifdef DEBUG_AESNI + printf("about to aes cbc decrypt\n"); + printf("in = %p\n", in); + printf("out = %p\n", out); + printf("aes->key = %p\n", aes->key); + printf("aes->reg = %p\n", aes->reg); + printf("aes->rounds = %d\n", aes->rounds); + printf("sz = %d\n", sz); + #endif + + /* if input and output same will overwrite input iv */ + XMEMCPY(aes->tmp, in + sz - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + #if defined(WOLFSSL_AESNI_BY4) + AES_CBC_decrypt_by4(in, out, (byte*)aes->reg, sz, (byte*)aes->key, + aes->rounds); + #elif defined(WOLFSSL_AESNI_BY6) + AES_CBC_decrypt_by6(in, out, (byte*)aes->reg, sz, (byte*)aes->key, + aes->rounds); + #else /* WOLFSSL_AESNI_BYx */ + AES_CBC_decrypt_by8(in, out, (byte*)aes->reg, sz, (byte*)aes->key, + aes->rounds); + #endif /* WOLFSSL_AESNI_BYx */ + /* store iv for next call */ + XMEMCPY(aes->reg, aes->tmp, AES_BLOCK_SIZE); + return 0; + } + #endif + + blocks = sz / AES_BLOCK_SIZE; + while (blocks--) { + XMEMCPY(aes->tmp, in, AES_BLOCK_SIZE); + wc_AesDecrypt(aes, (byte*)aes->tmp, out); + xorbuf(out, (byte*)aes->reg, AES_BLOCK_SIZE); + XMEMCPY(aes->reg, aes->tmp, AES_BLOCK_SIZE); + + out += AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; + } + + return 0; + } + #endif + +#endif /* AES-CBC block */ +#endif /* HAVE_AES_CBC */ + +/* AES-CTR */ +#if defined(WOLFSSL_AES_COUNTER) + + #ifdef STM32_CRYPTO + #define NEED_AES_CTR_SOFT + #define XTRANSFORM_AESCTRBLOCK wc_AesCtrEncryptBlock + + int wc_AesCtrEncryptBlock(Aes* aes, byte* out, const byte* in) + { + int ret = 0; + #ifdef WOLFSSL_STM32_CUBEMX + CRYP_HandleTypeDef hcryp; + #else + word32 *iv; + CRYP_InitTypeDef cryptInit; + CRYP_KeyInitTypeDef keyInit; + CRYP_IVInitTypeDef ivInit; + #endif + + #ifdef WOLFSSL_STM32_CUBEMX + ret = wc_Stm32_Aes_Init(aes, &hcryp); + if (ret != 0) + return ret; + + #ifdef STM32_CRYPTO_AES_ONLY + hcryp.Init.OperatingMode = CRYP_ALGOMODE_ENCRYPT; + hcryp.Init.ChainingMode = CRYP_CHAINMODE_AES_CTR; + hcryp.Init.KeyWriteFlag = CRYP_KEY_WRITE_ENABLE; + #endif + hcryp.Init.pInitVect = (uint8_t*)aes->reg; + HAL_CRYP_Init(&hcryp); + + #ifdef STM32_CRYPTO_AES_ONLY + ret = HAL_CRYPEx_AES(&hcryp, (byte*)in, AES_BLOCK_SIZE, + out, STM32_HAL_TIMEOUT); + #else + ret = HAL_CRYP_AESCTR_Encrypt(&hcryp, (byte*)in, AES_BLOCK_SIZE, + out, STM32_HAL_TIMEOUT); + #endif + if (ret != HAL_OK) { + ret = WC_TIMEOUT_E; + } + HAL_CRYP_DeInit(&hcryp); + + #else /* STD_PERI_LIB */ + ret = wc_Stm32_Aes_Init(aes, &cryptInit, &keyInit); + if (ret != 0) + return ret; + + /* reset registers to their default values */ + CRYP_DeInit(); + + /* set key */ + CRYP_KeyInit(&keyInit); + + /* set iv */ + iv = aes->reg; + CRYP_IVStructInit(&ivInit); + ivInit.CRYP_IV0Left = ByteReverseWord32(iv[0]); + ivInit.CRYP_IV0Right = ByteReverseWord32(iv[1]); + ivInit.CRYP_IV1Left = ByteReverseWord32(iv[2]); + ivInit.CRYP_IV1Right = ByteReverseWord32(iv[3]); + CRYP_IVInit(&ivInit); + + /* set direction and mode */ + cryptInit.CRYP_AlgoDir = CRYP_AlgoDir_Encrypt; + cryptInit.CRYP_AlgoMode = CRYP_AlgoMode_AES_CTR; + CRYP_Init(&cryptInit); + + /* enable crypto processor */ + CRYP_Cmd(ENABLE); + + /* flush IN/OUT FIFOs */ + CRYP_FIFOFlush(); + + CRYP_DataIn(*(uint32_t*)&in[0]); + CRYP_DataIn(*(uint32_t*)&in[4]); + CRYP_DataIn(*(uint32_t*)&in[8]); + CRYP_DataIn(*(uint32_t*)&in[12]); + + /* wait until the complete message has been processed */ + while (CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {} + + *(uint32_t*)&out[0] = CRYP_DataOut(); + *(uint32_t*)&out[4] = CRYP_DataOut(); + *(uint32_t*)&out[8] = CRYP_DataOut(); + *(uint32_t*)&out[12] = CRYP_DataOut(); + + /* disable crypto processor */ + CRYP_Cmd(DISABLE); + + #endif /* WOLFSSL_STM32_CUBEMX */ + return ret; + } + + + #elif defined(WOLFSSL_PIC32MZ_CRYPT) + + #define NEED_AES_CTR_SOFT + #define XTRANSFORM_AESCTRBLOCK wc_AesCtrEncryptBlock + + int wc_AesCtrEncryptBlock(Aes* aes, byte* out, const byte* in) + { + word32 tmpIv[AES_BLOCK_SIZE / sizeof(word32)]; + XMEMCPY(tmpIv, aes->reg, AES_BLOCK_SIZE); + return wc_Pic32AesCrypt( + aes->key, aes->keylen, tmpIv, AES_BLOCK_SIZE, + out, in, AES_BLOCK_SIZE, + PIC32_ENCRYPTION, PIC32_ALGO_AES, PIC32_CRYPTOALGO_RCTR); + } + + #elif defined(HAVE_COLDFIRE_SEC) + #error "Coldfire SEC doesn't currently support AES-CTR mode" + + #elif defined(FREESCALE_LTC) + int wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + uint32_t keySize; + byte *iv, *enc_key; + byte* tmp; + + if (aes == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + + /* consume any unused bytes left in aes->tmp */ + tmp = (byte*)aes->tmp + AES_BLOCK_SIZE - aes->left; + while (aes->left && sz) { + *(out++) = *(in++) ^ *(tmp++); + aes->left--; + sz--; + } + + if (sz) { + iv = (byte*)aes->reg; + enc_key = (byte*)aes->key; + + wc_AesGetKeySize(aes, &keySize); + + LTC_AES_CryptCtr(LTC_BASE, in, out, sz, + iv, enc_key, keySize, (byte*)aes->tmp, + (uint32_t*)&aes->left); + } + + return 0; + } + + #elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES) + /* implemented in wolfcrypt/src/port/caam/caam_aes.c */ + + #elif defined(WOLFSSL_AFALG) + /* implemented in wolfcrypt/src/port/af_alg/afalg_aes.c */ + + #elif defined(WOLFSSL_DEVCRYPTO_AES) + /* implemented in wolfcrypt/src/port/devcrypt/devcrypto_aes.c */ + + #else + + /* Use software based AES counter */ + #define NEED_AES_CTR_SOFT + #endif + + #ifdef NEED_AES_CTR_SOFT + /* Increment AES counter */ + static WC_INLINE void IncrementAesCounter(byte* inOutCtr) + { + /* in network byte order so start at end and work back */ + int i; + for (i = AES_BLOCK_SIZE - 1; i >= 0; i--) { + if (++inOutCtr[i]) /* we're done unless we overflow */ + return; + } + } + + /* Software AES - CTR Encrypt */ + int wc_AesCtrEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) + { + byte* tmp; + byte scratch[AES_BLOCK_SIZE]; + + if (aes == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + + /* consume any unused bytes left in aes->tmp */ + tmp = (byte*)aes->tmp + AES_BLOCK_SIZE - aes->left; + while (aes->left && sz) { + *(out++) = *(in++) ^ *(tmp++); + aes->left--; + sz--; + } + + /* do as many block size ops as possible */ + while (sz >= AES_BLOCK_SIZE) { + #ifdef XTRANSFORM_AESCTRBLOCK + XTRANSFORM_AESCTRBLOCK(aes, out, in); + #else + wc_AesEncrypt(aes, (byte*)aes->reg, scratch); + xorbuf(scratch, in, AES_BLOCK_SIZE); + XMEMCPY(out, scratch, AES_BLOCK_SIZE); + #endif + IncrementAesCounter((byte*)aes->reg); + + out += AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; + sz -= AES_BLOCK_SIZE; + aes->left = 0; + } + ForceZero(scratch, AES_BLOCK_SIZE); + + /* handle non block size remaining and store unused byte count in left */ + if (sz) { + wc_AesEncrypt(aes, (byte*)aes->reg, (byte*)aes->tmp); + IncrementAesCounter((byte*)aes->reg); + + aes->left = AES_BLOCK_SIZE; + tmp = (byte*)aes->tmp; + + while (sz--) { + *(out++) = *(in++) ^ *(tmp++); + aes->left--; + } + } + + return 0; + } + + #endif /* NEED_AES_CTR_SOFT */ + +#endif /* WOLFSSL_AES_COUNTER */ +#endif /* !WOLFSSL_ARMASM */ + + +/* + * The IV for AES GCM and CCM, stored in struct Aes's member reg, is comprised + * of two parts in order: + * 1. The fixed field which may be 0 or 4 bytes long. In TLS, this is set + * to the implicit IV. + * 2. The explicit IV is generated by wolfCrypt. It needs to be managed + * by wolfCrypt to ensure the IV is unique for each call to encrypt. + * The IV may be a 96-bit random value, or the 32-bit fixed value and a + * 64-bit set of 0 or random data. The final 32-bits of reg is used as a + * block counter during the encryption. + */ + +#if (defined(HAVE_AESGCM) && !defined(WC_NO_RNG)) || defined(HAVE_AESCCM) +static WC_INLINE void IncCtr(byte* ctr, word32 ctrSz) +{ + int i; + for (i = ctrSz-1; i >= 0; i--) { + if (++ctr[i]) + break; + } +} +#endif /* HAVE_AESGCM || HAVE_AESCCM */ + + +#ifdef HAVE_AESGCM + +#if defined(HAVE_COLDFIRE_SEC) + #error "Coldfire SEC doesn't currently support AES-GCM mode" + +#elif defined(WOLFSSL_NRF51_AES) + #error "nRF51 doesn't currently support AES-GCM mode" + +#endif + +#ifdef WOLFSSL_ARMASM + /* implementation is located in wolfcrypt/src/port/arm/armv8-aes.c */ + +#elif defined(WOLFSSL_AFALG) + /* implemented in wolfcrypt/src/port/afalg/afalg_aes.c */ + +#elif defined(WOLFSSL_DEVCRYPTO_AES) + /* implemented in wolfcrypt/src/port/devcrypt/devcrypto_aes.c */ + +#else /* software + AESNI implementation */ + +#if !defined(FREESCALE_LTC_AES_GCM) +static WC_INLINE void IncrementGcmCounter(byte* inOutCtr) +{ + int i; + + /* in network byte order so start at end and work back */ + for (i = AES_BLOCK_SIZE - 1; i >= AES_BLOCK_SIZE - CTR_SZ; i--) { + if (++inOutCtr[i]) /* we're done unless we overflow */ + return; + } +} +#ifdef STM32_CRYPTO_AES_GCM +static WC_INLINE void DecrementGcmCounter(byte* inOutCtr) +{ + int i; + + /* in network byte order so start at end and work back */ + for (i = AES_BLOCK_SIZE - 1; i >= AES_BLOCK_SIZE - CTR_SZ; i--) { + if (--inOutCtr[i] != 0xFF) /* we're done unless we underflow */ + return; + } +} +#endif /* STM32_CRYPTO_AES_GCM */ +#endif /* !FREESCALE_LTC_AES_GCM */ + +#if defined(GCM_SMALL) || defined(GCM_TABLE) + +static WC_INLINE void FlattenSzInBits(byte* buf, word32 sz) +{ + /* Multiply the sz by 8 */ + word32 szHi = (sz >> (8*sizeof(sz) - 3)); + sz <<= 3; + + /* copy over the words of the sz into the destination buffer */ + buf[0] = (szHi >> 24) & 0xff; + buf[1] = (szHi >> 16) & 0xff; + buf[2] = (szHi >> 8) & 0xff; + buf[3] = szHi & 0xff; + buf[4] = (sz >> 24) & 0xff; + buf[5] = (sz >> 16) & 0xff; + buf[6] = (sz >> 8) & 0xff; + buf[7] = sz & 0xff; +} + + +static WC_INLINE void RIGHTSHIFTX(byte* x) +{ + int i; + int carryOut = 0; + int carryIn = 0; + int borrow = x[15] & 0x01; + + for (i = 0; i < AES_BLOCK_SIZE; i++) { + carryOut = x[i] & 0x01; + x[i] = (x[i] >> 1) | (carryIn ? 0x80 : 0); + carryIn = carryOut; + } + if (borrow) x[0] ^= 0xE1; +} + +#endif /* defined(GCM_SMALL) || defined(GCM_TABLE) */ + + +#ifdef GCM_TABLE + +static void GenerateM0(Aes* aes) +{ + int i, j; + byte (*m)[AES_BLOCK_SIZE] = aes->M0; + + XMEMCPY(m[128], aes->H, AES_BLOCK_SIZE); + + for (i = 64; i > 0; i /= 2) { + XMEMCPY(m[i], m[i*2], AES_BLOCK_SIZE); + RIGHTSHIFTX(m[i]); + } + + for (i = 2; i < 256; i *= 2) { + for (j = 1; j < i; j++) { + XMEMCPY(m[i+j], m[i], AES_BLOCK_SIZE); + xorbuf(m[i+j], m[j], AES_BLOCK_SIZE); + } + } + + XMEMSET(m[0], 0, AES_BLOCK_SIZE); +} + +#endif /* GCM_TABLE */ + +/* Software AES - GCM SetKey */ +int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len) +{ + int ret; + byte iv[AES_BLOCK_SIZE]; + + #ifdef WOLFSSL_IMX6_CAAM_BLOB + byte local[32]; + word32 localSz = 32; + + if (len == (16 + WC_CAAM_BLOB_SZ) || + len == (24 + WC_CAAM_BLOB_SZ) || + len == (32 + WC_CAAM_BLOB_SZ)) { + if (wc_caamOpenBlob((byte*)key, len, local, &localSz) != 0) { + return BAD_FUNC_ARG; + } + + /* set local values */ + key = local; + len = localSz; + } + #endif + + if (!((len == 16) || (len == 24) || (len == 32))) + return BAD_FUNC_ARG; + + XMEMSET(iv, 0, AES_BLOCK_SIZE); + ret = wc_AesSetKey(aes, key, len, iv, AES_ENCRYPTION); + + #ifdef WOLFSSL_AESNI + /* AES-NI code generates its own H value. */ + if (haveAESNI) + return ret; + #endif /* WOLFSSL_AESNI */ + +#if !defined(FREESCALE_LTC_AES_GCM) + if (ret == 0) { + wc_AesEncrypt(aes, iv, aes->H); + #ifdef GCM_TABLE + GenerateM0(aes); + #endif /* GCM_TABLE */ + } +#endif /* FREESCALE_LTC_AES_GCM */ + +#if defined(WOLFSSL_XILINX_CRYPT) + wc_AesGcmSetKey_ex(aes, key, len, XSECURE_CSU_AES_KEY_SRC_KUP); +#elif defined(WOLFSSL_AFALG_XILINX_AES) + wc_AesGcmSetKey_ex(aes, key, len, 0); +#endif + +#ifdef WOLFSSL_IMX6_CAAM_BLOB + ForceZero(local, sizeof(local)); +#endif + + return ret; +} + + +#ifdef WOLFSSL_AESNI + +#if defined(USE_INTEL_SPEEDUP) + #define HAVE_INTEL_AVX1 + #define HAVE_INTEL_AVX2 +#endif /* USE_INTEL_SPEEDUP */ + +#ifndef _MSC_VER + +void AES_GCM_encrypt(const unsigned char *in, unsigned char *out, + const unsigned char* addt, const unsigned char* ivec, + unsigned char *tag, unsigned int nbytes, + unsigned int abytes, unsigned int ibytes, + unsigned int tbytes, const unsigned char* key, int nr) + XASM_LINK("AES_GCM_encrypt"); +#ifdef HAVE_INTEL_AVX1 +void AES_GCM_encrypt_avx1(const unsigned char *in, unsigned char *out, + const unsigned char* addt, const unsigned char* ivec, + unsigned char *tag, unsigned int nbytes, + unsigned int abytes, unsigned int ibytes, + unsigned int tbytes, const unsigned char* key, + int nr) + XASM_LINK("AES_GCM_encrypt_avx1"); +#ifdef HAVE_INTEL_AVX2 +void AES_GCM_encrypt_avx2(const unsigned char *in, unsigned char *out, + const unsigned char* addt, const unsigned char* ivec, + unsigned char *tag, unsigned int nbytes, + unsigned int abytes, unsigned int ibytes, + unsigned int tbytes, const unsigned char* key, + int nr) + XASM_LINK("AES_GCM_encrypt_avx2"); +#endif /* HAVE_INTEL_AVX2 */ +#endif /* HAVE_INTEL_AVX1 */ + +#ifdef HAVE_AES_DECRYPT +void AES_GCM_decrypt(const unsigned char *in, unsigned char *out, + const unsigned char* addt, const unsigned char* ivec, + const unsigned char *tag, int nbytes, int abytes, + int ibytes, int tbytes, const unsigned char* key, int nr, + int* res) + XASM_LINK("AES_GCM_decrypt"); +#ifdef HAVE_INTEL_AVX1 +void AES_GCM_decrypt_avx1(const unsigned char *in, unsigned char *out, + const unsigned char* addt, const unsigned char* ivec, + const unsigned char *tag, int nbytes, int abytes, + int ibytes, int tbytes, const unsigned char* key, + int nr, int* res) + XASM_LINK("AES_GCM_decrypt_avx1"); +#ifdef HAVE_INTEL_AVX2 +void AES_GCM_decrypt_avx2(const unsigned char *in, unsigned char *out, + const unsigned char* addt, const unsigned char* ivec, + const unsigned char *tag, int nbytes, int abytes, + int ibytes, int tbytes, const unsigned char* key, + int nr, int* res) + XASM_LINK("AES_GCM_decrypt_avx2"); +#endif /* HAVE_INTEL_AVX2 */ +#endif /* HAVE_INTEL_AVX1 */ +#endif /* HAVE_AES_DECRYPT */ + +#else /* _MSC_VER */ + +#define S(w,z) ((char)((unsigned long long)(w) >> (8*(7-(z))) & 0xFF)) +#define M128_INIT(x,y) { S((x),7), S((x),6), S((x),5), S((x),4), \ + S((x),3), S((x),2), S((x),1), S((x),0), \ + S((y),7), S((y),6), S((y),5), S((y),4), \ + S((y),3), S((y),2), S((y),1), S((y),0) } + +static const __m128i MOD2_128 = + M128_INIT(0x1, (long long int)0xc200000000000000UL); + + +/* See Intel® Carry-Less Multiplication Instruction + * and its Usage for Computing the GCM Mode White Paper + * by Shay Gueron, Intel Mobility Group, Israel Development Center; + * and Michael E. Kounavis, Intel Labs, Circuits and Systems Research */ + + +/* Figure 9. AES-GCM – Encrypt With Single Block Ghash at a Time */ + +static const __m128i ONE = M128_INIT(0x0, 0x1); +#ifndef AES_GCM_AESNI_NO_UNROLL +static const __m128i TWO = M128_INIT(0x0, 0x2); +static const __m128i THREE = M128_INIT(0x0, 0x3); +static const __m128i FOUR = M128_INIT(0x0, 0x4); +static const __m128i FIVE = M128_INIT(0x0, 0x5); +static const __m128i SIX = M128_INIT(0x0, 0x6); +static const __m128i SEVEN = M128_INIT(0x0, 0x7); +static const __m128i EIGHT = M128_INIT(0x0, 0x8); +#endif +static const __m128i BSWAP_EPI64 = + M128_INIT(0x0001020304050607, 0x08090a0b0c0d0e0f); +static const __m128i BSWAP_MASK = + M128_INIT(0x08090a0b0c0d0e0f, 0x0001020304050607); + + +/* The following are for MSC based builds which do not allow + * inline assembly. Intrinsic functions are used instead. */ + +#define aes_gcm_calc_iv_12(KEY, ivec, nr, H, Y, T) \ +do \ +{ \ + word32 iv12[4]; \ + iv12[0] = *(word32*)&ivec[0]; \ + iv12[1] = *(word32*)&ivec[4]; \ + iv12[2] = *(word32*)&ivec[8]; \ + iv12[3] = 0x01000000; \ + Y = _mm_loadu_si128((__m128i*)iv12); \ + \ + /* (Compute E[ZERO, KS] and E[Y0, KS] together */ \ + tmp1 = _mm_load_si128(&KEY[0]); \ + tmp2 = _mm_xor_si128(Y, KEY[0]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[1]); \ + tmp2 = _mm_aesenc_si128(tmp2, KEY[1]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[2]); \ + tmp2 = _mm_aesenc_si128(tmp2, KEY[2]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[3]); \ + tmp2 = _mm_aesenc_si128(tmp2, KEY[3]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[4]); \ + tmp2 = _mm_aesenc_si128(tmp2, KEY[4]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[5]); \ + tmp2 = _mm_aesenc_si128(tmp2, KEY[5]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[6]); \ + tmp2 = _mm_aesenc_si128(tmp2, KEY[6]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[7]); \ + tmp2 = _mm_aesenc_si128(tmp2, KEY[7]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[8]); \ + tmp2 = _mm_aesenc_si128(tmp2, KEY[8]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[9]); \ + tmp2 = _mm_aesenc_si128(tmp2, KEY[9]); \ + lastKey = KEY[10]; \ + if (nr > 10) { \ + tmp1 = _mm_aesenc_si128(tmp1, lastKey); \ + tmp2 = _mm_aesenc_si128(tmp2, lastKey); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[11]); \ + tmp2 = _mm_aesenc_si128(tmp2, KEY[11]); \ + lastKey = KEY[12]; \ + if (nr > 12) { \ + tmp1 = _mm_aesenc_si128(tmp1, lastKey); \ + tmp2 = _mm_aesenc_si128(tmp2, lastKey); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[13]); \ + tmp2 = _mm_aesenc_si128(tmp2, KEY[13]); \ + lastKey = KEY[14]; \ + } \ + } \ + H = _mm_aesenclast_si128(tmp1, lastKey); \ + T = _mm_aesenclast_si128(tmp2, lastKey); \ + H = _mm_shuffle_epi8(H, BSWAP_MASK); \ +} \ +while (0) + +#define aes_gcm_calc_iv(KEY, ivec, ibytes, nr, H, Y, T) \ +do \ +{ \ + if (ibytes % 16) { \ + i = ibytes / 16; \ + for (j=0; j < (int)(ibytes%16); j++) \ + ((unsigned char*)&last_block)[j] = ivec[i*16+j]; \ + } \ + tmp1 = _mm_load_si128(&KEY[0]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[1]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[2]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[3]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[4]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[5]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[6]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[7]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[8]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[9]); \ + lastKey = KEY[10]; \ + if (nr > 10) { \ + tmp1 = _mm_aesenc_si128(tmp1, lastKey); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[11]); \ + lastKey = KEY[12]; \ + if (nr > 12) { \ + tmp1 = _mm_aesenc_si128(tmp1, lastKey); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[13]); \ + lastKey = KEY[14]; \ + } \ + } \ + H = _mm_aesenclast_si128(tmp1, lastKey); \ + H = _mm_shuffle_epi8(H, BSWAP_MASK); \ + Y = _mm_setzero_si128(); \ + for (i=0; i < (int)(ibytes/16); i++) { \ + tmp1 = _mm_loadu_si128(&((__m128i*)ivec)[i]); \ + tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK); \ + Y = _mm_xor_si128(Y, tmp1); \ + Y = gfmul_sw(Y, H); \ + } \ + if (ibytes % 16) { \ + tmp1 = last_block; \ + tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK); \ + Y = _mm_xor_si128(Y, tmp1); \ + Y = gfmul_sw(Y, H); \ + } \ + tmp1 = _mm_insert_epi64(tmp1, ibytes*8, 0); \ + tmp1 = _mm_insert_epi64(tmp1, 0, 1); \ + Y = _mm_xor_si128(Y, tmp1); \ + Y = gfmul_sw(Y, H); \ + Y = _mm_shuffle_epi8(Y, BSWAP_MASK); /* Compute E(K, Y0) */ \ + tmp1 = _mm_xor_si128(Y, KEY[0]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[1]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[2]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[3]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[4]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[5]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[6]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[7]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[8]); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[9]); \ + lastKey = KEY[10]; \ + if (nr > 10) { \ + tmp1 = _mm_aesenc_si128(tmp1, lastKey); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[11]); \ + lastKey = KEY[12]; \ + if (nr > 12) { \ + tmp1 = _mm_aesenc_si128(tmp1, lastKey); \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[13]); \ + lastKey = KEY[14]; \ + } \ + } \ + T = _mm_aesenclast_si128(tmp1, lastKey); \ +} \ +while (0) + +#define AES_ENC_8(j) \ + tmp1 = _mm_aesenc_si128(tmp1, KEY[j]); \ + tmp2 = _mm_aesenc_si128(tmp2, KEY[j]); \ + tmp3 = _mm_aesenc_si128(tmp3, KEY[j]); \ + tmp4 = _mm_aesenc_si128(tmp4, KEY[j]); \ + tmp5 = _mm_aesenc_si128(tmp5, KEY[j]); \ + tmp6 = _mm_aesenc_si128(tmp6, KEY[j]); \ + tmp7 = _mm_aesenc_si128(tmp7, KEY[j]); \ + tmp8 = _mm_aesenc_si128(tmp8, KEY[j]); + +#define AES_ENC_LAST_8() \ + tmp1 =_mm_aesenclast_si128(tmp1, lastKey); \ + tmp2 =_mm_aesenclast_si128(tmp2, lastKey); \ + tmp1 = _mm_xor_si128(tmp1, _mm_loadu_si128(&((__m128i*)in)[i*8+0])); \ + tmp2 = _mm_xor_si128(tmp2, _mm_loadu_si128(&((__m128i*)in)[i*8+1])); \ + _mm_storeu_si128(&((__m128i*)out)[i*8+0], tmp1); \ + _mm_storeu_si128(&((__m128i*)out)[i*8+1], tmp2); \ + tmp3 =_mm_aesenclast_si128(tmp3, lastKey); \ + tmp4 =_mm_aesenclast_si128(tmp4, lastKey); \ + tmp3 = _mm_xor_si128(tmp3, _mm_loadu_si128(&((__m128i*)in)[i*8+2])); \ + tmp4 = _mm_xor_si128(tmp4, _mm_loadu_si128(&((__m128i*)in)[i*8+3])); \ + _mm_storeu_si128(&((__m128i*)out)[i*8+2], tmp3); \ + _mm_storeu_si128(&((__m128i*)out)[i*8+3], tmp4); \ + tmp5 =_mm_aesenclast_si128(tmp5, lastKey); \ + tmp6 =_mm_aesenclast_si128(tmp6, lastKey); \ + tmp5 = _mm_xor_si128(tmp5, _mm_loadu_si128(&((__m128i*)in)[i*8+4])); \ + tmp6 = _mm_xor_si128(tmp6, _mm_loadu_si128(&((__m128i*)in)[i*8+5])); \ + _mm_storeu_si128(&((__m128i*)out)[i*8+4], tmp5); \ + _mm_storeu_si128(&((__m128i*)out)[i*8+5], tmp6); \ + tmp7 =_mm_aesenclast_si128(tmp7, lastKey); \ + tmp8 =_mm_aesenclast_si128(tmp8, lastKey); \ + tmp7 = _mm_xor_si128(tmp7, _mm_loadu_si128(&((__m128i*)in)[i*8+6])); \ + tmp8 = _mm_xor_si128(tmp8, _mm_loadu_si128(&((__m128i*)in)[i*8+7])); \ + _mm_storeu_si128(&((__m128i*)out)[i*8+6], tmp7); \ + _mm_storeu_si128(&((__m128i*)out)[i*8+7], tmp8); + + +static __m128i gfmul_sw(__m128i a, __m128i b) +{ + __m128i r, t1, t2, t3, t4, t5, t6, t7; + t2 = _mm_shuffle_epi32(b, 78); + t3 = _mm_shuffle_epi32(a, 78); + t2 = _mm_xor_si128(t2, b); + t3 = _mm_xor_si128(t3, a); + t4 = _mm_clmulepi64_si128(b, a, 0x11); + t1 = _mm_clmulepi64_si128(b, a, 0x00); + t2 = _mm_clmulepi64_si128(t2, t3, 0x00); + t2 = _mm_xor_si128(t2, t1); + t2 = _mm_xor_si128(t2, t4); + t3 = _mm_slli_si128(t2, 8); + t2 = _mm_srli_si128(t2, 8); + t1 = _mm_xor_si128(t1, t3); + t4 = _mm_xor_si128(t4, t2); + + t5 = _mm_srli_epi32(t1, 31); + t6 = _mm_srli_epi32(t4, 31); + t1 = _mm_slli_epi32(t1, 1); + t4 = _mm_slli_epi32(t4, 1); + t7 = _mm_srli_si128(t5, 12); + t5 = _mm_slli_si128(t5, 4); + t6 = _mm_slli_si128(t6, 4); + t4 = _mm_or_si128(t4, t7); + t1 = _mm_or_si128(t1, t5); + t4 = _mm_or_si128(t4, t6); + + t5 = _mm_slli_epi32(t1, 31); + t6 = _mm_slli_epi32(t1, 30); + t7 = _mm_slli_epi32(t1, 25); + t5 = _mm_xor_si128(t5, t6); + t5 = _mm_xor_si128(t5, t7); + + t6 = _mm_srli_si128(t5, 4); + t5 = _mm_slli_si128(t5, 12); + t1 = _mm_xor_si128(t1, t5); + t7 = _mm_srli_epi32(t1, 1); + t3 = _mm_srli_epi32(t1, 2); + t2 = _mm_srli_epi32(t1, 7); + + t7 = _mm_xor_si128(t7, t3); + t7 = _mm_xor_si128(t7, t2); + t7 = _mm_xor_si128(t7, t6); + t7 = _mm_xor_si128(t7, t1); + r = _mm_xor_si128(t4, t7); + + return r; +} + +static void gfmul_only(__m128i a, __m128i b, __m128i* r0, __m128i* r1) +{ + __m128i t1, t2, t3, t4; + + /* 128 x 128 Carryless Multiply */ + t2 = _mm_shuffle_epi32(b, 78); + t3 = _mm_shuffle_epi32(a, 78); + t2 = _mm_xor_si128(t2, b); + t3 = _mm_xor_si128(t3, a); + t4 = _mm_clmulepi64_si128(b, a, 0x11); + t1 = _mm_clmulepi64_si128(b, a, 0x00); + t2 = _mm_clmulepi64_si128(t2, t3, 0x00); + t2 = _mm_xor_si128(t2, t1); + t2 = _mm_xor_si128(t2, t4); + t3 = _mm_slli_si128(t2, 8); + t2 = _mm_srli_si128(t2, 8); + t1 = _mm_xor_si128(t1, t3); + t4 = _mm_xor_si128(t4, t2); + *r0 = _mm_xor_si128(t1, *r0); + *r1 = _mm_xor_si128(t4, *r1); +} + +static __m128i gfmul_shl1(__m128i a) +{ + __m128i t1 = a, t2; + t2 = _mm_srli_epi64(t1, 63); + t1 = _mm_slli_epi64(t1, 1); + t2 = _mm_slli_si128(t2, 8); + t1 = _mm_or_si128(t1, t2); + /* if (a[1] >> 63) t1 = _mm_xor_si128(t1, MOD2_128); */ + a = _mm_shuffle_epi32(a, 0xff); + a = _mm_srai_epi32(a, 31); + a = _mm_and_si128(a, MOD2_128); + t1 = _mm_xor_si128(t1, a); + return t1; +} + +static __m128i ghash_red(__m128i r0, __m128i r1) +{ + __m128i t2, t3; + __m128i t5, t6, t7; + + t5 = _mm_slli_epi32(r0, 31); + t6 = _mm_slli_epi32(r0, 30); + t7 = _mm_slli_epi32(r0, 25); + t5 = _mm_xor_si128(t5, t6); + t5 = _mm_xor_si128(t5, t7); + + t6 = _mm_srli_si128(t5, 4); + t5 = _mm_slli_si128(t5, 12); + r0 = _mm_xor_si128(r0, t5); + t7 = _mm_srli_epi32(r0, 1); + t3 = _mm_srli_epi32(r0, 2); + t2 = _mm_srli_epi32(r0, 7); + + t7 = _mm_xor_si128(t7, t3); + t7 = _mm_xor_si128(t7, t2); + t7 = _mm_xor_si128(t7, t6); + t7 = _mm_xor_si128(t7, r0); + return _mm_xor_si128(r1, t7); +} + +static __m128i gfmul_shifted(__m128i a, __m128i b) +{ + __m128i t0 = _mm_setzero_si128(), t1 = _mm_setzero_si128(); + gfmul_only(a, b, &t0, &t1); + return ghash_red(t0, t1); +} + +#ifndef AES_GCM_AESNI_NO_UNROLL +static __m128i gfmul8(__m128i a1, __m128i a2, __m128i a3, __m128i a4, + __m128i a5, __m128i a6, __m128i a7, __m128i a8, + __m128i b1, __m128i b2, __m128i b3, __m128i b4, + __m128i b5, __m128i b6, __m128i b7, __m128i b8) +{ + __m128i t0 = _mm_setzero_si128(), t1 = _mm_setzero_si128(); + gfmul_only(a1, b8, &t0, &t1); + gfmul_only(a2, b7, &t0, &t1); + gfmul_only(a3, b6, &t0, &t1); + gfmul_only(a4, b5, &t0, &t1); + gfmul_only(a5, b4, &t0, &t1); + gfmul_only(a6, b3, &t0, &t1); + gfmul_only(a7, b2, &t0, &t1); + gfmul_only(a8, b1, &t0, &t1); + return ghash_red(t0, t1); +} +#endif + + +static void AES_GCM_encrypt(const unsigned char *in, + unsigned char *out, + const unsigned char* addt, + const unsigned char* ivec, + unsigned char *tag, unsigned int nbytes, + unsigned int abytes, unsigned int ibytes, + unsigned int tbytes, + const unsigned char* key, int nr) +{ + int i, j ,k; + __m128i ctr1; + __m128i H, Y, T; + __m128i X = _mm_setzero_si128(); + __m128i *KEY = (__m128i*)key, lastKey; + __m128i last_block = _mm_setzero_si128(); + __m128i tmp1, tmp2; +#ifndef AES_GCM_AESNI_NO_UNROLL + __m128i HT[8]; + __m128i r0, r1; + __m128i XV; + __m128i tmp3, tmp4, tmp5, tmp6, tmp7, tmp8; +#endif + + if (ibytes == GCM_NONCE_MID_SZ) + aes_gcm_calc_iv_12(KEY, ivec, nr, H, Y, T); + else + aes_gcm_calc_iv(KEY, ivec, ibytes, nr, H, Y, T); + + for (i=0; i < (int)(abytes/16); i++) { + tmp1 = _mm_loadu_si128(&((__m128i*)addt)[i]); + tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK); + X = _mm_xor_si128(X, tmp1); + X = gfmul_sw(X, H); + } + if (abytes%16) { + last_block = _mm_setzero_si128(); + for (j=0; j < (int)(abytes%16); j++) + ((unsigned char*)&last_block)[j] = addt[i*16+j]; + tmp1 = last_block; + tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK); + X = _mm_xor_si128(X, tmp1); + X = gfmul_sw(X, H); + } + tmp1 = _mm_shuffle_epi8(Y, BSWAP_EPI64); + ctr1 = _mm_add_epi32(tmp1, ONE); + H = gfmul_shl1(H); + +#ifndef AES_GCM_AESNI_NO_UNROLL + i = 0; + if (nbytes >= 16*8) { + HT[0] = H; + HT[1] = gfmul_shifted(H, H); + HT[2] = gfmul_shifted(H, HT[1]); + HT[3] = gfmul_shifted(HT[1], HT[1]); + HT[4] = gfmul_shifted(HT[1], HT[2]); + HT[5] = gfmul_shifted(HT[2], HT[2]); + HT[6] = gfmul_shifted(HT[2], HT[3]); + HT[7] = gfmul_shifted(HT[3], HT[3]); + + tmp1 = _mm_shuffle_epi8(ctr1, BSWAP_EPI64); + tmp2 = _mm_add_epi32(ctr1, ONE); + tmp2 = _mm_shuffle_epi8(tmp2, BSWAP_EPI64); + tmp3 = _mm_add_epi32(ctr1, TWO); + tmp3 = _mm_shuffle_epi8(tmp3, BSWAP_EPI64); + tmp4 = _mm_add_epi32(ctr1, THREE); + tmp4 = _mm_shuffle_epi8(tmp4, BSWAP_EPI64); + tmp5 = _mm_add_epi32(ctr1, FOUR); + tmp5 = _mm_shuffle_epi8(tmp5, BSWAP_EPI64); + tmp6 = _mm_add_epi32(ctr1, FIVE); + tmp6 = _mm_shuffle_epi8(tmp6, BSWAP_EPI64); + tmp7 = _mm_add_epi32(ctr1, SIX); + tmp7 = _mm_shuffle_epi8(tmp7, BSWAP_EPI64); + tmp8 = _mm_add_epi32(ctr1, SEVEN); + tmp8 = _mm_shuffle_epi8(tmp8, BSWAP_EPI64); + ctr1 = _mm_add_epi32(ctr1, EIGHT); + tmp1 =_mm_xor_si128(tmp1, KEY[0]); + tmp2 =_mm_xor_si128(tmp2, KEY[0]); + tmp3 =_mm_xor_si128(tmp3, KEY[0]); + tmp4 =_mm_xor_si128(tmp4, KEY[0]); + tmp5 =_mm_xor_si128(tmp5, KEY[0]); + tmp6 =_mm_xor_si128(tmp6, KEY[0]); + tmp7 =_mm_xor_si128(tmp7, KEY[0]); + tmp8 =_mm_xor_si128(tmp8, KEY[0]); + AES_ENC_8(1); + AES_ENC_8(2); + AES_ENC_8(3); + AES_ENC_8(4); + AES_ENC_8(5); + AES_ENC_8(6); + AES_ENC_8(7); + AES_ENC_8(8); + AES_ENC_8(9); + lastKey = KEY[10]; + if (nr > 10) { + AES_ENC_8(10); + AES_ENC_8(11); + lastKey = KEY[12]; + if (nr > 12) { + AES_ENC_8(12); + AES_ENC_8(13); + lastKey = KEY[14]; + } + } + AES_ENC_LAST_8(); + + for (i=1; i < (int)(nbytes/16/8); i++) { + r0 = _mm_setzero_si128(); + r1 = _mm_setzero_si128(); + tmp1 = _mm_shuffle_epi8(ctr1, BSWAP_EPI64); + tmp2 = _mm_add_epi32(ctr1, ONE); + tmp2 = _mm_shuffle_epi8(tmp2, BSWAP_EPI64); + tmp3 = _mm_add_epi32(ctr1, TWO); + tmp3 = _mm_shuffle_epi8(tmp3, BSWAP_EPI64); + tmp4 = _mm_add_epi32(ctr1, THREE); + tmp4 = _mm_shuffle_epi8(tmp4, BSWAP_EPI64); + tmp5 = _mm_add_epi32(ctr1, FOUR); + tmp5 = _mm_shuffle_epi8(tmp5, BSWAP_EPI64); + tmp6 = _mm_add_epi32(ctr1, FIVE); + tmp6 = _mm_shuffle_epi8(tmp6, BSWAP_EPI64); + tmp7 = _mm_add_epi32(ctr1, SIX); + tmp7 = _mm_shuffle_epi8(tmp7, BSWAP_EPI64); + tmp8 = _mm_add_epi32(ctr1, SEVEN); + tmp8 = _mm_shuffle_epi8(tmp8, BSWAP_EPI64); + ctr1 = _mm_add_epi32(ctr1, EIGHT); + tmp1 =_mm_xor_si128(tmp1, KEY[0]); + tmp2 =_mm_xor_si128(tmp2, KEY[0]); + tmp3 =_mm_xor_si128(tmp3, KEY[0]); + tmp4 =_mm_xor_si128(tmp4, KEY[0]); + tmp5 =_mm_xor_si128(tmp5, KEY[0]); + tmp6 =_mm_xor_si128(tmp6, KEY[0]); + tmp7 =_mm_xor_si128(tmp7, KEY[0]); + tmp8 =_mm_xor_si128(tmp8, KEY[0]); + /* 128 x 128 Carryless Multiply */ + XV = _mm_loadu_si128(&((__m128i*)out)[(i-1)*8+0]); + XV = _mm_shuffle_epi8(XV, BSWAP_MASK); + XV = _mm_xor_si128(XV, X); + gfmul_only(XV, HT[7], &r0, &r1); + tmp1 = _mm_aesenc_si128(tmp1, KEY[1]); + tmp2 = _mm_aesenc_si128(tmp2, KEY[1]); + tmp3 = _mm_aesenc_si128(tmp3, KEY[1]); + tmp4 = _mm_aesenc_si128(tmp4, KEY[1]); + tmp5 = _mm_aesenc_si128(tmp5, KEY[1]); + tmp6 = _mm_aesenc_si128(tmp6, KEY[1]); + tmp7 = _mm_aesenc_si128(tmp7, KEY[1]); + tmp8 = _mm_aesenc_si128(tmp8, KEY[1]); + /* 128 x 128 Carryless Multiply */ + XV = _mm_loadu_si128(&((__m128i*)out)[(i-1)*8+1]); + XV = _mm_shuffle_epi8(XV, BSWAP_MASK); + gfmul_only(XV, HT[6], &r0, &r1); + tmp1 = _mm_aesenc_si128(tmp1, KEY[2]); + tmp2 = _mm_aesenc_si128(tmp2, KEY[2]); + tmp3 = _mm_aesenc_si128(tmp3, KEY[2]); + tmp4 = _mm_aesenc_si128(tmp4, KEY[2]); + tmp5 = _mm_aesenc_si128(tmp5, KEY[2]); + tmp6 = _mm_aesenc_si128(tmp6, KEY[2]); + tmp7 = _mm_aesenc_si128(tmp7, KEY[2]); + tmp8 = _mm_aesenc_si128(tmp8, KEY[2]); + /* 128 x 128 Carryless Multiply */ + XV = _mm_loadu_si128(&((__m128i*)out)[(i-1)*8+2]); + XV = _mm_shuffle_epi8(XV, BSWAP_MASK); + gfmul_only(XV, HT[5], &r0, &r1); + tmp1 = _mm_aesenc_si128(tmp1, KEY[3]); + tmp2 = _mm_aesenc_si128(tmp2, KEY[3]); + tmp3 = _mm_aesenc_si128(tmp3, KEY[3]); + tmp4 = _mm_aesenc_si128(tmp4, KEY[3]); + tmp5 = _mm_aesenc_si128(tmp5, KEY[3]); + tmp6 = _mm_aesenc_si128(tmp6, KEY[3]); + tmp7 = _mm_aesenc_si128(tmp7, KEY[3]); + tmp8 = _mm_aesenc_si128(tmp8, KEY[3]); + /* 128 x 128 Carryless Multiply */ + XV = _mm_loadu_si128(&((__m128i*)out)[(i-1)*8+3]); + XV = _mm_shuffle_epi8(XV, BSWAP_MASK); + gfmul_only(XV, HT[4], &r0, &r1); + tmp1 = _mm_aesenc_si128(tmp1, KEY[4]); + tmp2 = _mm_aesenc_si128(tmp2, KEY[4]); + tmp3 = _mm_aesenc_si128(tmp3, KEY[4]); + tmp4 = _mm_aesenc_si128(tmp4, KEY[4]); + tmp5 = _mm_aesenc_si128(tmp5, KEY[4]); + tmp6 = _mm_aesenc_si128(tmp6, KEY[4]); + tmp7 = _mm_aesenc_si128(tmp7, KEY[4]); + tmp8 = _mm_aesenc_si128(tmp8, KEY[4]); + /* 128 x 128 Carryless Multiply */ + XV = _mm_loadu_si128(&((__m128i*)out)[(i-1)*8+4]); + XV = _mm_shuffle_epi8(XV, BSWAP_MASK); + gfmul_only(XV, HT[3], &r0, &r1); + tmp1 = _mm_aesenc_si128(tmp1, KEY[5]); + tmp2 = _mm_aesenc_si128(tmp2, KEY[5]); + tmp3 = _mm_aesenc_si128(tmp3, KEY[5]); + tmp4 = _mm_aesenc_si128(tmp4, KEY[5]); + tmp5 = _mm_aesenc_si128(tmp5, KEY[5]); + tmp6 = _mm_aesenc_si128(tmp6, KEY[5]); + tmp7 = _mm_aesenc_si128(tmp7, KEY[5]); + tmp8 = _mm_aesenc_si128(tmp8, KEY[5]); + /* 128 x 128 Carryless Multiply */ + XV = _mm_loadu_si128(&((__m128i*)out)[(i-1)*8+5]); + XV = _mm_shuffle_epi8(XV, BSWAP_MASK); + gfmul_only(XV, HT[2], &r0, &r1); + tmp1 = _mm_aesenc_si128(tmp1, KEY[6]); + tmp2 = _mm_aesenc_si128(tmp2, KEY[6]); + tmp3 = _mm_aesenc_si128(tmp3, KEY[6]); + tmp4 = _mm_aesenc_si128(tmp4, KEY[6]); + tmp5 = _mm_aesenc_si128(tmp5, KEY[6]); + tmp6 = _mm_aesenc_si128(tmp6, KEY[6]); + tmp7 = _mm_aesenc_si128(tmp7, KEY[6]); + tmp8 = _mm_aesenc_si128(tmp8, KEY[6]); + /* 128 x 128 Carryless Multiply */ + XV = _mm_loadu_si128(&((__m128i*)out)[(i-1)*8+6]); + XV = _mm_shuffle_epi8(XV, BSWAP_MASK); + gfmul_only(XV, HT[1], &r0, &r1); + tmp1 = _mm_aesenc_si128(tmp1, KEY[7]); + tmp2 = _mm_aesenc_si128(tmp2, KEY[7]); + tmp3 = _mm_aesenc_si128(tmp3, KEY[7]); + tmp4 = _mm_aesenc_si128(tmp4, KEY[7]); + tmp5 = _mm_aesenc_si128(tmp5, KEY[7]); + tmp6 = _mm_aesenc_si128(tmp6, KEY[7]); + tmp7 = _mm_aesenc_si128(tmp7, KEY[7]); + tmp8 = _mm_aesenc_si128(tmp8, KEY[7]); + /* 128 x 128 Carryless Multiply */ + XV = _mm_loadu_si128(&((__m128i*)out)[(i-1)*8+7]); + XV = _mm_shuffle_epi8(XV, BSWAP_MASK); + gfmul_only(XV, HT[0], &r0, &r1); + tmp1 = _mm_aesenc_si128(tmp1, KEY[8]); + tmp2 = _mm_aesenc_si128(tmp2, KEY[8]); + tmp3 = _mm_aesenc_si128(tmp3, KEY[8]); + tmp4 = _mm_aesenc_si128(tmp4, KEY[8]); + tmp5 = _mm_aesenc_si128(tmp5, KEY[8]); + tmp6 = _mm_aesenc_si128(tmp6, KEY[8]); + tmp7 = _mm_aesenc_si128(tmp7, KEY[8]); + tmp8 = _mm_aesenc_si128(tmp8, KEY[8]); + /* Reduction */ + X = ghash_red(r0, r1); + tmp1 = _mm_aesenc_si128(tmp1, KEY[9]); + tmp2 = _mm_aesenc_si128(tmp2, KEY[9]); + tmp3 = _mm_aesenc_si128(tmp3, KEY[9]); + tmp4 = _mm_aesenc_si128(tmp4, KEY[9]); + tmp5 = _mm_aesenc_si128(tmp5, KEY[9]); + tmp6 = _mm_aesenc_si128(tmp6, KEY[9]); + tmp7 = _mm_aesenc_si128(tmp7, KEY[9]); + tmp8 = _mm_aesenc_si128(tmp8, KEY[9]); + lastKey = KEY[10]; + if (nr > 10) { + tmp1 = _mm_aesenc_si128(tmp1, KEY[10]); + tmp2 = _mm_aesenc_si128(tmp2, KEY[10]); + tmp3 = _mm_aesenc_si128(tmp3, KEY[10]); + tmp4 = _mm_aesenc_si128(tmp4, KEY[10]); + tmp5 = _mm_aesenc_si128(tmp5, KEY[10]); + tmp6 = _mm_aesenc_si128(tmp6, KEY[10]); + tmp7 = _mm_aesenc_si128(tmp7, KEY[10]); + tmp8 = _mm_aesenc_si128(tmp8, KEY[10]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[11]); + tmp2 = _mm_aesenc_si128(tmp2, KEY[11]); + tmp3 = _mm_aesenc_si128(tmp3, KEY[11]); + tmp4 = _mm_aesenc_si128(tmp4, KEY[11]); + tmp5 = _mm_aesenc_si128(tmp5, KEY[11]); + tmp6 = _mm_aesenc_si128(tmp6, KEY[11]); + tmp7 = _mm_aesenc_si128(tmp7, KEY[11]); + tmp8 = _mm_aesenc_si128(tmp8, KEY[11]); + lastKey = KEY[12]; + if (nr > 12) { + tmp1 = _mm_aesenc_si128(tmp1, KEY[12]); + tmp2 = _mm_aesenc_si128(tmp2, KEY[12]); + tmp3 = _mm_aesenc_si128(tmp3, KEY[12]); + tmp4 = _mm_aesenc_si128(tmp4, KEY[12]); + tmp5 = _mm_aesenc_si128(tmp5, KEY[12]); + tmp6 = _mm_aesenc_si128(tmp6, KEY[12]); + tmp7 = _mm_aesenc_si128(tmp7, KEY[12]); + tmp8 = _mm_aesenc_si128(tmp8, KEY[12]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[13]); + tmp2 = _mm_aesenc_si128(tmp2, KEY[13]); + tmp3 = _mm_aesenc_si128(tmp3, KEY[13]); + tmp4 = _mm_aesenc_si128(tmp4, KEY[13]); + tmp5 = _mm_aesenc_si128(tmp5, KEY[13]); + tmp6 = _mm_aesenc_si128(tmp6, KEY[13]); + tmp7 = _mm_aesenc_si128(tmp7, KEY[13]); + tmp8 = _mm_aesenc_si128(tmp8, KEY[13]); + lastKey = KEY[14]; + } + } + AES_ENC_LAST_8(); + } + + tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK); + tmp2 = _mm_shuffle_epi8(tmp2, BSWAP_MASK); + tmp3 = _mm_shuffle_epi8(tmp3, BSWAP_MASK); + tmp4 = _mm_shuffle_epi8(tmp4, BSWAP_MASK); + tmp5 = _mm_shuffle_epi8(tmp5, BSWAP_MASK); + tmp6 = _mm_shuffle_epi8(tmp6, BSWAP_MASK); + tmp7 = _mm_shuffle_epi8(tmp7, BSWAP_MASK); + tmp8 = _mm_shuffle_epi8(tmp8, BSWAP_MASK); + tmp1 = _mm_xor_si128(X, tmp1); + X = gfmul8(tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, + HT[0], HT[1], HT[2], HT[3], HT[4], HT[5], HT[6], HT[7]); + } + for (k = i*8; k < (int)(nbytes/16); k++) { + tmp1 = _mm_shuffle_epi8(ctr1, BSWAP_EPI64); + ctr1 = _mm_add_epi32(ctr1, ONE); + tmp1 = _mm_xor_si128(tmp1, KEY[0]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[1]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[2]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[3]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[4]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[5]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[6]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[7]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[8]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[9]); + lastKey = KEY[10]; + if (nr > 10) { + tmp1 = _mm_aesenc_si128(tmp1, lastKey); + tmp1 = _mm_aesenc_si128(tmp1, KEY[11]); + lastKey = KEY[12]; + if (nr > 12) { + tmp1 = _mm_aesenc_si128(tmp1, lastKey); + tmp1 = _mm_aesenc_si128(tmp1, KEY[13]); + lastKey = KEY[14]; + } + } + tmp1 = _mm_aesenclast_si128(tmp1, lastKey); + tmp1 = _mm_xor_si128(tmp1, _mm_loadu_si128(&((__m128i*)in)[k])); + _mm_storeu_si128(&((__m128i*)out)[k], tmp1); + tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK); + X =_mm_xor_si128(X, tmp1); + X = gfmul_shifted(X, H); + } +#else /* AES_GCM_AESNI_NO_UNROLL */ + for (k = 0; k < (int)(nbytes/16) && k < 1; k++) { + tmp1 = _mm_shuffle_epi8(ctr1, BSWAP_EPI64); + ctr1 = _mm_add_epi32(ctr1, ONE); + tmp1 = _mm_xor_si128(tmp1, KEY[0]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[1]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[2]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[3]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[4]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[5]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[6]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[7]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[8]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[9]); + lastKey = KEY[10]; + if (nr > 10) { + tmp1 = _mm_aesenc_si128(tmp1, lastKey); + tmp1 = _mm_aesenc_si128(tmp1, KEY[11]); + lastKey = KEY[12]; + if (nr > 12) { + tmp1 = _mm_aesenc_si128(tmp1, lastKey); + tmp1 = _mm_aesenc_si128(tmp1, KEY[13]); + lastKey = KEY[14]; + } + } + tmp1 = _mm_aesenclast_si128(tmp1, lastKey); + tmp1 = _mm_xor_si128(tmp1, _mm_loadu_si128(&((__m128i*)in)[k])); + _mm_storeu_si128(&((__m128i*)out)[k], tmp1); + tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK); + X =_mm_xor_si128(X, tmp1); + } + for (; k < (int)(nbytes/16); k++) { + tmp1 = _mm_shuffle_epi8(ctr1, BSWAP_EPI64); + ctr1 = _mm_add_epi32(ctr1, ONE); + tmp1 = _mm_xor_si128(tmp1, KEY[0]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[1]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[2]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[3]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[4]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[5]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[6]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[7]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[8]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[9]); + X = gfmul_shifted(X, H); + lastKey = KEY[10]; + if (nr > 10) { + tmp1 = _mm_aesenc_si128(tmp1, lastKey); + tmp1 = _mm_aesenc_si128(tmp1, KEY[11]); + lastKey = KEY[12]; + if (nr > 12) { + tmp1 = _mm_aesenc_si128(tmp1, lastKey); + tmp1 = _mm_aesenc_si128(tmp1, KEY[13]); + lastKey = KEY[14]; + } + } + tmp1 = _mm_aesenclast_si128(tmp1, lastKey); + tmp1 = _mm_xor_si128(tmp1, _mm_loadu_si128(&((__m128i*)in)[k])); + _mm_storeu_si128(&((__m128i*)out)[k], tmp1); + tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK); + X =_mm_xor_si128(X, tmp1); + } + if (k > 0) { + X = gfmul_shifted(X, H); + } +#endif /* AES_GCM_AESNI_NO_UNROLL */ + + /* If one partial block remains */ + if (nbytes % 16) { + tmp1 = _mm_shuffle_epi8(ctr1, BSWAP_EPI64); + tmp1 = _mm_xor_si128(tmp1, KEY[0]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[1]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[2]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[3]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[4]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[5]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[6]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[7]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[8]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[9]); + lastKey = KEY[10]; + if (nr > 10) { + tmp1 = _mm_aesenc_si128(tmp1, lastKey); + tmp1 = _mm_aesenc_si128(tmp1, KEY[11]); + lastKey = KEY[12]; + if (nr > 12) { + tmp1 = _mm_aesenc_si128(tmp1, lastKey); + tmp1 = _mm_aesenc_si128(tmp1, KEY[13]); + lastKey = KEY[14]; + } + } + tmp1 = _mm_aesenclast_si128(tmp1, lastKey); + last_block = tmp1; + for (j=0; j < (int)(nbytes%16); j++) + ((unsigned char*)&last_block)[j] = in[k*16+j]; + tmp1 = _mm_xor_si128(tmp1, last_block); + last_block = tmp1; + for (j=0; j < (int)(nbytes%16); j++) + out[k*16+j] = ((unsigned char*)&last_block)[j]; + tmp1 = last_block; + tmp1 = _mm_shuffle_epi8(tmp1, BSWAP_MASK); + X =_mm_xor_si128(X, tmp1); + X = gfmul_shifted(X, H); + } + tmp1 = _mm_insert_epi64(tmp1, nbytes*8, 0); + tmp1 = _mm_insert_epi64(tmp1, abytes*8, 1); + X = _mm_xor_si128(X, tmp1); + X = gfmul_shifted(X, H); + X = _mm_shuffle_epi8(X, BSWAP_MASK); + T = _mm_xor_si128(X, T); + /*_mm_storeu_si128((__m128i*)tag, T);*/ + XMEMCPY(tag, &T, tbytes); +} + +#ifdef HAVE_AES_DECRYPT + +static void AES_GCM_decrypt(const unsigned char *in, + unsigned char *out, + const unsigned char* addt, + const unsigned char* ivec, + const unsigned char *tag, int nbytes, int abytes, + int ibytes, word32 tbytes, const unsigned char* key, + int nr, int* res) +{ + int i, j ,k; + __m128i H, Y, T; + __m128i *KEY = (__m128i*)key, lastKey; + __m128i ctr1; + __m128i last_block = _mm_setzero_si128(); + __m128i X = _mm_setzero_si128(); + __m128i tmp1, tmp2, XV; +#ifndef AES_GCM_AESNI_NO_UNROLL + __m128i HT[8]; + __m128i r0, r1; + __m128i tmp3, tmp4, tmp5, tmp6, tmp7, tmp8; +#endif /* AES_GCM_AESNI_NO_UNROLL */ + + if (ibytes == GCM_NONCE_MID_SZ) + aes_gcm_calc_iv_12(KEY, ivec, nr, H, Y, T); + else + aes_gcm_calc_iv(KEY, ivec, ibytes, nr, H, Y, T); + + for (i=0; i 10) { + tmp1 = _mm_aesenc_si128(tmp1, KEY[10]); + tmp2 = _mm_aesenc_si128(tmp2, KEY[10]); + tmp3 = _mm_aesenc_si128(tmp3, KEY[10]); + tmp4 = _mm_aesenc_si128(tmp4, KEY[10]); + tmp5 = _mm_aesenc_si128(tmp5, KEY[10]); + tmp6 = _mm_aesenc_si128(tmp6, KEY[10]); + tmp7 = _mm_aesenc_si128(tmp7, KEY[10]); + tmp8 = _mm_aesenc_si128(tmp8, KEY[10]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[11]); + tmp2 = _mm_aesenc_si128(tmp2, KEY[11]); + tmp3 = _mm_aesenc_si128(tmp3, KEY[11]); + tmp4 = _mm_aesenc_si128(tmp4, KEY[11]); + tmp5 = _mm_aesenc_si128(tmp5, KEY[11]); + tmp6 = _mm_aesenc_si128(tmp6, KEY[11]); + tmp7 = _mm_aesenc_si128(tmp7, KEY[11]); + tmp8 = _mm_aesenc_si128(tmp8, KEY[11]); + lastKey = KEY[12]; + if (nr > 12) { + tmp1 = _mm_aesenc_si128(tmp1, KEY[12]); + tmp2 = _mm_aesenc_si128(tmp2, KEY[12]); + tmp3 = _mm_aesenc_si128(tmp3, KEY[12]); + tmp4 = _mm_aesenc_si128(tmp4, KEY[12]); + tmp5 = _mm_aesenc_si128(tmp5, KEY[12]); + tmp6 = _mm_aesenc_si128(tmp6, KEY[12]); + tmp7 = _mm_aesenc_si128(tmp7, KEY[12]); + tmp8 = _mm_aesenc_si128(tmp8, KEY[12]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[13]); + tmp2 = _mm_aesenc_si128(tmp2, KEY[13]); + tmp3 = _mm_aesenc_si128(tmp3, KEY[13]); + tmp4 = _mm_aesenc_si128(tmp4, KEY[13]); + tmp5 = _mm_aesenc_si128(tmp5, KEY[13]); + tmp6 = _mm_aesenc_si128(tmp6, KEY[13]); + tmp7 = _mm_aesenc_si128(tmp7, KEY[13]); + tmp8 = _mm_aesenc_si128(tmp8, KEY[13]); + lastKey = KEY[14]; + } + } + AES_ENC_LAST_8(); + } + } + +#endif /* AES_GCM_AESNI_NO_UNROLL */ + + for (k = i*8; k < nbytes/16; k++) { + tmp1 = _mm_shuffle_epi8(ctr1, BSWAP_EPI64); + ctr1 = _mm_add_epi32(ctr1, ONE); + tmp1 = _mm_xor_si128(tmp1, KEY[0]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[1]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[2]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[3]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[4]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[5]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[6]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[7]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[8]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[9]); + /* 128 x 128 Carryless Multiply */ + XV = _mm_loadu_si128(&((__m128i*)in)[k]); + XV = _mm_shuffle_epi8(XV, BSWAP_MASK); + XV = _mm_xor_si128(XV, X); + X = gfmul_shifted(XV, H); + lastKey = KEY[10]; + if (nr > 10) { + tmp1 = _mm_aesenc_si128(tmp1, lastKey); + tmp1 = _mm_aesenc_si128(tmp1, KEY[11]); + lastKey = KEY[12]; + if (nr > 12) { + tmp1 = _mm_aesenc_si128(tmp1, lastKey); + tmp1 = _mm_aesenc_si128(tmp1, KEY[13]); + lastKey = KEY[14]; + } + } + tmp1 = _mm_aesenclast_si128(tmp1, lastKey); + tmp2 = _mm_loadu_si128(&((__m128i*)in)[k]); + tmp1 = _mm_xor_si128(tmp1, tmp2); + _mm_storeu_si128(&((__m128i*)out)[k], tmp1); + } + + /* If one partial block remains */ + if (nbytes % 16) { + tmp1 = _mm_shuffle_epi8(ctr1, BSWAP_EPI64); + tmp1 = _mm_xor_si128(tmp1, KEY[0]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[1]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[2]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[3]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[4]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[5]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[6]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[7]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[8]); + tmp1 = _mm_aesenc_si128(tmp1, KEY[9]); + lastKey = KEY[10]; + if (nr > 10) { + tmp1 = _mm_aesenc_si128(tmp1, lastKey); + tmp1 = _mm_aesenc_si128(tmp1, KEY[11]); + lastKey = KEY[12]; + if (nr > 12) { + tmp1 = _mm_aesenc_si128(tmp1, lastKey); + tmp1 = _mm_aesenc_si128(tmp1, KEY[13]); + lastKey = KEY[14]; + } + } + tmp1 = _mm_aesenclast_si128(tmp1, lastKey); + last_block = _mm_setzero_si128(); + for (j=0; j < nbytes%16; j++) + ((unsigned char*)&last_block)[j] = in[k*16+j]; + XV = last_block; + tmp1 = _mm_xor_si128(tmp1, last_block); + last_block = tmp1; + for (j=0; j < nbytes%16; j++) + out[k*16+j] = ((unsigned char*)&last_block)[j]; + XV = _mm_shuffle_epi8(XV, BSWAP_MASK); + XV = _mm_xor_si128(XV, X); + X = gfmul_shifted(XV, H); + } + + tmp1 = _mm_insert_epi64(tmp1, nbytes*8, 0); + tmp1 = _mm_insert_epi64(tmp1, abytes*8, 1); + /* 128 x 128 Carryless Multiply */ + X = _mm_xor_si128(X, tmp1); + X = gfmul_shifted(X, H); + X = _mm_shuffle_epi8(X, BSWAP_MASK); + T = _mm_xor_si128(X, T); + +/* if (0xffff != + _mm_movemask_epi8(_mm_cmpeq_epi8(T, _mm_loadu_si128((__m128i*)tag)))) */ + if (XMEMCMP(tag, &T, tbytes) != 0) + *res = 0; /* in case the authentication failed */ + else + *res = 1; /* when successful returns 1 */ +} + +#endif /* HAVE_AES_DECRYPT */ +#endif /* _MSC_VER */ +#endif /* WOLFSSL_AESNI */ + + +#if defined(GCM_SMALL) +static void GMULT(byte* X, byte* Y) +{ + byte Z[AES_BLOCK_SIZE]; + byte V[AES_BLOCK_SIZE]; + int i, j; + + XMEMSET(Z, 0, AES_BLOCK_SIZE); + XMEMCPY(V, X, AES_BLOCK_SIZE); + for (i = 0; i < AES_BLOCK_SIZE; i++) + { + byte y = Y[i]; + for (j = 0; j < 8; j++) + { + if (y & 0x80) { + xorbuf(Z, V, AES_BLOCK_SIZE); + } + + RIGHTSHIFTX(V); + y = y << 1; + } + } + XMEMCPY(X, Z, AES_BLOCK_SIZE); +} + + +void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c, + word32 cSz, byte* s, word32 sSz) +{ + byte x[AES_BLOCK_SIZE]; + byte scratch[AES_BLOCK_SIZE]; + word32 blocks, partial; + byte* h = aes->H; + + XMEMSET(x, 0, AES_BLOCK_SIZE); + + /* Hash in A, the Additional Authentication Data */ + if (aSz != 0 && a != NULL) { + blocks = aSz / AES_BLOCK_SIZE; + partial = aSz % AES_BLOCK_SIZE; + while (blocks--) { + xorbuf(x, a, AES_BLOCK_SIZE); + GMULT(x, h); + a += AES_BLOCK_SIZE; + } + if (partial != 0) { + XMEMSET(scratch, 0, AES_BLOCK_SIZE); + XMEMCPY(scratch, a, partial); + xorbuf(x, scratch, AES_BLOCK_SIZE); + GMULT(x, h); + } + } + + /* Hash in C, the Ciphertext */ + if (cSz != 0 && c != NULL) { + blocks = cSz / AES_BLOCK_SIZE; + partial = cSz % AES_BLOCK_SIZE; + while (blocks--) { + xorbuf(x, c, AES_BLOCK_SIZE); + GMULT(x, h); + c += AES_BLOCK_SIZE; + } + if (partial != 0) { + XMEMSET(scratch, 0, AES_BLOCK_SIZE); + XMEMCPY(scratch, c, partial); + xorbuf(x, scratch, AES_BLOCK_SIZE); + GMULT(x, h); + } + } + + /* Hash in the lengths of A and C in bits */ + FlattenSzInBits(&scratch[0], aSz); + FlattenSzInBits(&scratch[8], cSz); + xorbuf(x, scratch, AES_BLOCK_SIZE); + GMULT(x, h); + + /* Copy the result into s. */ + XMEMCPY(s, x, sSz); +} + +/* end GCM_SMALL */ +#elif defined(GCM_TABLE) + +static const byte R[256][2] = { + {0x00, 0x00}, {0x01, 0xc2}, {0x03, 0x84}, {0x02, 0x46}, + {0x07, 0x08}, {0x06, 0xca}, {0x04, 0x8c}, {0x05, 0x4e}, + {0x0e, 0x10}, {0x0f, 0xd2}, {0x0d, 0x94}, {0x0c, 0x56}, + {0x09, 0x18}, {0x08, 0xda}, {0x0a, 0x9c}, {0x0b, 0x5e}, + {0x1c, 0x20}, {0x1d, 0xe2}, {0x1f, 0xa4}, {0x1e, 0x66}, + {0x1b, 0x28}, {0x1a, 0xea}, {0x18, 0xac}, {0x19, 0x6e}, + {0x12, 0x30}, {0x13, 0xf2}, {0x11, 0xb4}, {0x10, 0x76}, + {0x15, 0x38}, {0x14, 0xfa}, {0x16, 0xbc}, {0x17, 0x7e}, + {0x38, 0x40}, {0x39, 0x82}, {0x3b, 0xc4}, {0x3a, 0x06}, + {0x3f, 0x48}, {0x3e, 0x8a}, {0x3c, 0xcc}, {0x3d, 0x0e}, + {0x36, 0x50}, {0x37, 0x92}, {0x35, 0xd4}, {0x34, 0x16}, + {0x31, 0x58}, {0x30, 0x9a}, {0x32, 0xdc}, {0x33, 0x1e}, + {0x24, 0x60}, {0x25, 0xa2}, {0x27, 0xe4}, {0x26, 0x26}, + {0x23, 0x68}, {0x22, 0xaa}, {0x20, 0xec}, {0x21, 0x2e}, + {0x2a, 0x70}, {0x2b, 0xb2}, {0x29, 0xf4}, {0x28, 0x36}, + {0x2d, 0x78}, {0x2c, 0xba}, {0x2e, 0xfc}, {0x2f, 0x3e}, + {0x70, 0x80}, {0x71, 0x42}, {0x73, 0x04}, {0x72, 0xc6}, + {0x77, 0x88}, {0x76, 0x4a}, {0x74, 0x0c}, {0x75, 0xce}, + {0x7e, 0x90}, {0x7f, 0x52}, {0x7d, 0x14}, {0x7c, 0xd6}, + {0x79, 0x98}, {0x78, 0x5a}, {0x7a, 0x1c}, {0x7b, 0xde}, + {0x6c, 0xa0}, {0x6d, 0x62}, {0x6f, 0x24}, {0x6e, 0xe6}, + {0x6b, 0xa8}, {0x6a, 0x6a}, {0x68, 0x2c}, {0x69, 0xee}, + {0x62, 0xb0}, {0x63, 0x72}, {0x61, 0x34}, {0x60, 0xf6}, + {0x65, 0xb8}, {0x64, 0x7a}, {0x66, 0x3c}, {0x67, 0xfe}, + {0x48, 0xc0}, {0x49, 0x02}, {0x4b, 0x44}, {0x4a, 0x86}, + {0x4f, 0xc8}, {0x4e, 0x0a}, {0x4c, 0x4c}, {0x4d, 0x8e}, + {0x46, 0xd0}, {0x47, 0x12}, {0x45, 0x54}, {0x44, 0x96}, + {0x41, 0xd8}, {0x40, 0x1a}, {0x42, 0x5c}, {0x43, 0x9e}, + {0x54, 0xe0}, {0x55, 0x22}, {0x57, 0x64}, {0x56, 0xa6}, + {0x53, 0xe8}, {0x52, 0x2a}, {0x50, 0x6c}, {0x51, 0xae}, + {0x5a, 0xf0}, {0x5b, 0x32}, {0x59, 0x74}, {0x58, 0xb6}, + {0x5d, 0xf8}, {0x5c, 0x3a}, {0x5e, 0x7c}, {0x5f, 0xbe}, + {0xe1, 0x00}, {0xe0, 0xc2}, {0xe2, 0x84}, {0xe3, 0x46}, + {0xe6, 0x08}, {0xe7, 0xca}, {0xe5, 0x8c}, {0xe4, 0x4e}, + {0xef, 0x10}, {0xee, 0xd2}, {0xec, 0x94}, {0xed, 0x56}, + {0xe8, 0x18}, {0xe9, 0xda}, {0xeb, 0x9c}, {0xea, 0x5e}, + {0xfd, 0x20}, {0xfc, 0xe2}, {0xfe, 0xa4}, {0xff, 0x66}, + {0xfa, 0x28}, {0xfb, 0xea}, {0xf9, 0xac}, {0xf8, 0x6e}, + {0xf3, 0x30}, {0xf2, 0xf2}, {0xf0, 0xb4}, {0xf1, 0x76}, + {0xf4, 0x38}, {0xf5, 0xfa}, {0xf7, 0xbc}, {0xf6, 0x7e}, + {0xd9, 0x40}, {0xd8, 0x82}, {0xda, 0xc4}, {0xdb, 0x06}, + {0xde, 0x48}, {0xdf, 0x8a}, {0xdd, 0xcc}, {0xdc, 0x0e}, + {0xd7, 0x50}, {0xd6, 0x92}, {0xd4, 0xd4}, {0xd5, 0x16}, + {0xd0, 0x58}, {0xd1, 0x9a}, {0xd3, 0xdc}, {0xd2, 0x1e}, + {0xc5, 0x60}, {0xc4, 0xa2}, {0xc6, 0xe4}, {0xc7, 0x26}, + {0xc2, 0x68}, {0xc3, 0xaa}, {0xc1, 0xec}, {0xc0, 0x2e}, + {0xcb, 0x70}, {0xca, 0xb2}, {0xc8, 0xf4}, {0xc9, 0x36}, + {0xcc, 0x78}, {0xcd, 0xba}, {0xcf, 0xfc}, {0xce, 0x3e}, + {0x91, 0x80}, {0x90, 0x42}, {0x92, 0x04}, {0x93, 0xc6}, + {0x96, 0x88}, {0x97, 0x4a}, {0x95, 0x0c}, {0x94, 0xce}, + {0x9f, 0x90}, {0x9e, 0x52}, {0x9c, 0x14}, {0x9d, 0xd6}, + {0x98, 0x98}, {0x99, 0x5a}, {0x9b, 0x1c}, {0x9a, 0xde}, + {0x8d, 0xa0}, {0x8c, 0x62}, {0x8e, 0x24}, {0x8f, 0xe6}, + {0x8a, 0xa8}, {0x8b, 0x6a}, {0x89, 0x2c}, {0x88, 0xee}, + {0x83, 0xb0}, {0x82, 0x72}, {0x80, 0x34}, {0x81, 0xf6}, + {0x84, 0xb8}, {0x85, 0x7a}, {0x87, 0x3c}, {0x86, 0xfe}, + {0xa9, 0xc0}, {0xa8, 0x02}, {0xaa, 0x44}, {0xab, 0x86}, + {0xae, 0xc8}, {0xaf, 0x0a}, {0xad, 0x4c}, {0xac, 0x8e}, + {0xa7, 0xd0}, {0xa6, 0x12}, {0xa4, 0x54}, {0xa5, 0x96}, + {0xa0, 0xd8}, {0xa1, 0x1a}, {0xa3, 0x5c}, {0xa2, 0x9e}, + {0xb5, 0xe0}, {0xb4, 0x22}, {0xb6, 0x64}, {0xb7, 0xa6}, + {0xb2, 0xe8}, {0xb3, 0x2a}, {0xb1, 0x6c}, {0xb0, 0xae}, + {0xbb, 0xf0}, {0xba, 0x32}, {0xb8, 0x74}, {0xb9, 0xb6}, + {0xbc, 0xf8}, {0xbd, 0x3a}, {0xbf, 0x7c}, {0xbe, 0xbe} }; + + +static void GMULT(byte *x, byte m[256][AES_BLOCK_SIZE]) +{ + int i, j; + byte Z[AES_BLOCK_SIZE]; + byte a; + + XMEMSET(Z, 0, sizeof(Z)); + + for (i = 15; i > 0; i--) { + xorbuf(Z, m[x[i]], AES_BLOCK_SIZE); + a = Z[15]; + + for (j = 15; j > 0; j--) { + Z[j] = Z[j-1]; + } + + Z[0] = R[a][0]; + Z[1] ^= R[a][1]; + } + xorbuf(Z, m[x[0]], AES_BLOCK_SIZE); + + XMEMCPY(x, Z, AES_BLOCK_SIZE); +} + + +void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c, + word32 cSz, byte* s, word32 sSz) +{ + byte x[AES_BLOCK_SIZE]; + byte scratch[AES_BLOCK_SIZE]; + word32 blocks, partial; + + XMEMSET(x, 0, AES_BLOCK_SIZE); + + /* Hash in A, the Additional Authentication Data */ + if (aSz != 0 && a != NULL) { + blocks = aSz / AES_BLOCK_SIZE; + partial = aSz % AES_BLOCK_SIZE; + while (blocks--) { + xorbuf(x, a, AES_BLOCK_SIZE); + GMULT(x, aes->M0); + a += AES_BLOCK_SIZE; + } + if (partial != 0) { + XMEMSET(scratch, 0, AES_BLOCK_SIZE); + XMEMCPY(scratch, a, partial); + xorbuf(x, scratch, AES_BLOCK_SIZE); + GMULT(x, aes->M0); + } + } + + /* Hash in C, the Ciphertext */ + if (cSz != 0 && c != NULL) { + blocks = cSz / AES_BLOCK_SIZE; + partial = cSz % AES_BLOCK_SIZE; + while (blocks--) { + xorbuf(x, c, AES_BLOCK_SIZE); + GMULT(x, aes->M0); + c += AES_BLOCK_SIZE; + } + if (partial != 0) { + XMEMSET(scratch, 0, AES_BLOCK_SIZE); + XMEMCPY(scratch, c, partial); + xorbuf(x, scratch, AES_BLOCK_SIZE); + GMULT(x, aes->M0); + } + } + + /* Hash in the lengths of A and C in bits */ + FlattenSzInBits(&scratch[0], aSz); + FlattenSzInBits(&scratch[8], cSz); + xorbuf(x, scratch, AES_BLOCK_SIZE); + GMULT(x, aes->M0); + + /* Copy the result into s. */ + XMEMCPY(s, x, sSz); +} + +/* end GCM_TABLE */ +#elif defined(WORD64_AVAILABLE) && !defined(GCM_WORD32) + +#if !defined(FREESCALE_LTC_AES_GCM) +static void GMULT(word64* X, word64* Y) +{ + word64 Z[2] = {0,0}; + word64 V[2]; + int i, j; + V[0] = X[0]; V[1] = X[1]; + + for (i = 0; i < 2; i++) + { + word64 y = Y[i]; + for (j = 0; j < 64; j++) + { + if (y & 0x8000000000000000ULL) { + Z[0] ^= V[0]; + Z[1] ^= V[1]; + } + + if (V[1] & 0x0000000000000001) { + V[1] >>= 1; + V[1] |= ((V[0] & 0x0000000000000001) ? + 0x8000000000000000ULL : 0); + V[0] >>= 1; + V[0] ^= 0xE100000000000000ULL; + } + else { + V[1] >>= 1; + V[1] |= ((V[0] & 0x0000000000000001) ? + 0x8000000000000000ULL : 0); + V[0] >>= 1; + } + y <<= 1; + } + } + X[0] = Z[0]; + X[1] = Z[1]; +} + + +void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c, + word32 cSz, byte* s, word32 sSz) +{ + word64 x[2] = {0,0}; + word32 blocks, partial; + word64 bigH[2]; + + XMEMCPY(bigH, aes->H, AES_BLOCK_SIZE); + #ifdef LITTLE_ENDIAN_ORDER + ByteReverseWords64(bigH, bigH, AES_BLOCK_SIZE); + #endif + + /* Hash in A, the Additional Authentication Data */ + if (aSz != 0 && a != NULL) { + word64 bigA[2]; + blocks = aSz / AES_BLOCK_SIZE; + partial = aSz % AES_BLOCK_SIZE; + while (blocks--) { + XMEMCPY(bigA, a, AES_BLOCK_SIZE); + #ifdef LITTLE_ENDIAN_ORDER + ByteReverseWords64(bigA, bigA, AES_BLOCK_SIZE); + #endif + x[0] ^= bigA[0]; + x[1] ^= bigA[1]; + GMULT(x, bigH); + a += AES_BLOCK_SIZE; + } + if (partial != 0) { + XMEMSET(bigA, 0, AES_BLOCK_SIZE); + XMEMCPY(bigA, a, partial); + #ifdef LITTLE_ENDIAN_ORDER + ByteReverseWords64(bigA, bigA, AES_BLOCK_SIZE); + #endif + x[0] ^= bigA[0]; + x[1] ^= bigA[1]; + GMULT(x, bigH); + } + } + + /* Hash in C, the Ciphertext */ + if (cSz != 0 && c != NULL) { + word64 bigC[2]; + blocks = cSz / AES_BLOCK_SIZE; + partial = cSz % AES_BLOCK_SIZE; + while (blocks--) { + XMEMCPY(bigC, c, AES_BLOCK_SIZE); + #ifdef LITTLE_ENDIAN_ORDER + ByteReverseWords64(bigC, bigC, AES_BLOCK_SIZE); + #endif + x[0] ^= bigC[0]; + x[1] ^= bigC[1]; + GMULT(x, bigH); + c += AES_BLOCK_SIZE; + } + if (partial != 0) { + XMEMSET(bigC, 0, AES_BLOCK_SIZE); + XMEMCPY(bigC, c, partial); + #ifdef LITTLE_ENDIAN_ORDER + ByteReverseWords64(bigC, bigC, AES_BLOCK_SIZE); + #endif + x[0] ^= bigC[0]; + x[1] ^= bigC[1]; + GMULT(x, bigH); + } + } + + /* Hash in the lengths in bits of A and C */ + { + word64 len[2]; + len[0] = aSz; len[1] = cSz; + + /* Lengths are in bytes. Convert to bits. */ + len[0] *= 8; + len[1] *= 8; + + x[0] ^= len[0]; + x[1] ^= len[1]; + GMULT(x, bigH); + } + #ifdef LITTLE_ENDIAN_ORDER + ByteReverseWords64(x, x, AES_BLOCK_SIZE); + #endif + XMEMCPY(s, x, sSz); +} +#endif /* !FREESCALE_LTC_AES_GCM */ + +/* end defined(WORD64_AVAILABLE) && !defined(GCM_WORD32) */ +#else /* GCM_WORD32 */ + +static void GMULT(word32* X, word32* Y) +{ + word32 Z[4] = {0,0,0,0}; + word32 V[4]; + int i, j; + + V[0] = X[0]; V[1] = X[1]; V[2] = X[2]; V[3] = X[3]; + + for (i = 0; i < 4; i++) + { + word32 y = Y[i]; + for (j = 0; j < 32; j++) + { + if (y & 0x80000000) { + Z[0] ^= V[0]; + Z[1] ^= V[1]; + Z[2] ^= V[2]; + Z[3] ^= V[3]; + } + + if (V[3] & 0x00000001) { + V[3] >>= 1; + V[3] |= ((V[2] & 0x00000001) ? 0x80000000 : 0); + V[2] >>= 1; + V[2] |= ((V[1] & 0x00000001) ? 0x80000000 : 0); + V[1] >>= 1; + V[1] |= ((V[0] & 0x00000001) ? 0x80000000 : 0); + V[0] >>= 1; + V[0] ^= 0xE1000000; + } else { + V[3] >>= 1; + V[3] |= ((V[2] & 0x00000001) ? 0x80000000 : 0); + V[2] >>= 1; + V[2] |= ((V[1] & 0x00000001) ? 0x80000000 : 0); + V[1] >>= 1; + V[1] |= ((V[0] & 0x00000001) ? 0x80000000 : 0); + V[0] >>= 1; + } + y <<= 1; + } + } + X[0] = Z[0]; + X[1] = Z[1]; + X[2] = Z[2]; + X[3] = Z[3]; +} + + +void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c, + word32 cSz, byte* s, word32 sSz) +{ + word32 x[4] = {0,0,0,0}; + word32 blocks, partial; + word32 bigH[4]; + + XMEMCPY(bigH, aes->H, AES_BLOCK_SIZE); + #ifdef LITTLE_ENDIAN_ORDER + ByteReverseWords(bigH, bigH, AES_BLOCK_SIZE); + #endif + + /* Hash in A, the Additional Authentication Data */ + if (aSz != 0 && a != NULL) { + word32 bigA[4]; + blocks = aSz / AES_BLOCK_SIZE; + partial = aSz % AES_BLOCK_SIZE; + while (blocks--) { + XMEMCPY(bigA, a, AES_BLOCK_SIZE); + #ifdef LITTLE_ENDIAN_ORDER + ByteReverseWords(bigA, bigA, AES_BLOCK_SIZE); + #endif + x[0] ^= bigA[0]; + x[1] ^= bigA[1]; + x[2] ^= bigA[2]; + x[3] ^= bigA[3]; + GMULT(x, bigH); + a += AES_BLOCK_SIZE; + } + if (partial != 0) { + XMEMSET(bigA, 0, AES_BLOCK_SIZE); + XMEMCPY(bigA, a, partial); + #ifdef LITTLE_ENDIAN_ORDER + ByteReverseWords(bigA, bigA, AES_BLOCK_SIZE); + #endif + x[0] ^= bigA[0]; + x[1] ^= bigA[1]; + x[2] ^= bigA[2]; + x[3] ^= bigA[3]; + GMULT(x, bigH); + } + } + + /* Hash in C, the Ciphertext */ + if (cSz != 0 && c != NULL) { + word32 bigC[4]; + blocks = cSz / AES_BLOCK_SIZE; + partial = cSz % AES_BLOCK_SIZE; + while (blocks--) { + XMEMCPY(bigC, c, AES_BLOCK_SIZE); + #ifdef LITTLE_ENDIAN_ORDER + ByteReverseWords(bigC, bigC, AES_BLOCK_SIZE); + #endif + x[0] ^= bigC[0]; + x[1] ^= bigC[1]; + x[2] ^= bigC[2]; + x[3] ^= bigC[3]; + GMULT(x, bigH); + c += AES_BLOCK_SIZE; + } + if (partial != 0) { + XMEMSET(bigC, 0, AES_BLOCK_SIZE); + XMEMCPY(bigC, c, partial); + #ifdef LITTLE_ENDIAN_ORDER + ByteReverseWords(bigC, bigC, AES_BLOCK_SIZE); + #endif + x[0] ^= bigC[0]; + x[1] ^= bigC[1]; + x[2] ^= bigC[2]; + x[3] ^= bigC[3]; + GMULT(x, bigH); + } + } + + /* Hash in the lengths in bits of A and C */ + { + word32 len[4]; + + /* Lengths are in bytes. Convert to bits. */ + len[0] = (aSz >> (8*sizeof(aSz) - 3)); + len[1] = aSz << 3; + len[2] = (cSz >> (8*sizeof(cSz) - 3)); + len[3] = cSz << 3; + + x[0] ^= len[0]; + x[1] ^= len[1]; + x[2] ^= len[2]; + x[3] ^= len[3]; + GMULT(x, bigH); + } + #ifdef LITTLE_ENDIAN_ORDER + ByteReverseWords(x, x, AES_BLOCK_SIZE); + #endif + XMEMCPY(s, x, sSz); +} + +#endif /* end GCM_WORD32 */ + + +#if !defined(WOLFSSL_XILINX_CRYPT) && !defined(WOLFSSL_AFALG_XILINX_AES) +#ifdef FREESCALE_LTC_AES_GCM +int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, + const byte* iv, word32 ivSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) +{ + status_t status; + word32 keySize; + + /* argument checks */ + if (aes == NULL || authTagSz > AES_BLOCK_SIZE) { + return BAD_FUNC_ARG; + } + + if (authTagSz < WOLFSSL_MIN_AUTH_TAG_SZ) { + WOLFSSL_MSG("GcmEncrypt authTagSz too small error"); + return BAD_FUNC_ARG; + } + + status = wc_AesGetKeySize(aes, &keySize); + if (status) + return status; + + status = LTC_AES_EncryptTagGcm(LTC_BASE, in, out, sz, iv, ivSz, + authIn, authInSz, (byte*)aes->key, keySize, authTag, authTagSz); + + return (status == kStatus_Success) ? 0 : AES_GCM_AUTH_E; +} + +#else + +#ifdef STM32_CRYPTO_AES_GCM + +/* this function supports inline encrypt */ +static int wc_AesGcmEncrypt_STM32(Aes* aes, byte* out, const byte* in, word32 sz, + const byte* iv, word32 ivSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) +{ + int ret; +#ifdef WOLFSSL_STM32_CUBEMX + CRYP_HandleTypeDef hcryp; +#else + word32 keyCopy[AES_256_KEY_SIZE/sizeof(word32)]; +#endif + word32 keySize; + int status = HAL_OK; + word32 blocks = sz / AES_BLOCK_SIZE; + word32 partial = sz % AES_BLOCK_SIZE; + byte tag[AES_BLOCK_SIZE]; + byte partialBlock[AES_BLOCK_SIZE]; + byte ctr[AES_BLOCK_SIZE]; + byte* authInPadded = NULL; + int authPadSz; + + ret = wc_AesGetKeySize(aes, &keySize); + if (ret != 0) + return ret; + +#ifdef WOLFSSL_STM32_CUBEMX + ret = wc_Stm32_Aes_Init(aes, &hcryp); + if (ret != 0) + return ret; +#endif + + XMEMSET(ctr, 0, AES_BLOCK_SIZE); + if (ivSz == GCM_NONCE_MID_SZ) { + XMEMCPY(ctr, iv, ivSz); + ctr[AES_BLOCK_SIZE - 1] = 1; + } + else { + GHASH(aes, NULL, 0, iv, ivSz, ctr, AES_BLOCK_SIZE); + } + /* Hardware requires counter + 1 */ + IncrementGcmCounter(ctr); + + if (authInSz == 0 || (authInSz % AES_BLOCK_SIZE) != 0) { + /* Need to pad the AAD to a full block with zeros. */ + authPadSz = ((authInSz / AES_BLOCK_SIZE) + 1) * AES_BLOCK_SIZE; + authInPadded = (byte*)XMALLOC(authPadSz, aes->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (authInPadded == NULL) { + return MEMORY_E; + } + XMEMSET(authInPadded, 0, authPadSz); + XMEMCPY(authInPadded, authIn, authInSz); + } else { + authPadSz = authInSz; + authInPadded = (byte*)authIn; + } + +#ifdef WOLFSSL_STM32_CUBEMX + hcryp.Init.pInitVect = (uint8_t*)ctr; + hcryp.Init.Header = authInPadded; + hcryp.Init.HeaderSize = authInSz; + +#ifdef STM32_CRYPTO_AES_ONLY + /* Set the CRYP parameters */ + hcryp.Init.ChainingMode = CRYP_CHAINMODE_AES_GCM_GMAC; + hcryp.Init.OperatingMode = CRYP_ALGOMODE_ENCRYPT; + hcryp.Init.GCMCMACPhase = CRYP_INIT_PHASE; + HAL_CRYP_Init(&hcryp); + + /* GCM init phase */ + status = HAL_CRYPEx_AES_Auth(&hcryp, NULL, 0, NULL, STM32_HAL_TIMEOUT); + if (status == HAL_OK) { + /* GCM header phase */ + hcryp.Init.GCMCMACPhase = CRYP_HEADER_PHASE; + status = HAL_CRYPEx_AES_Auth(&hcryp, NULL, 0, NULL, STM32_HAL_TIMEOUT); + } + if (status == HAL_OK) { + /* GCM payload phase - blocks */ + hcryp.Init.GCMCMACPhase = CRYP_PAYLOAD_PHASE; + if (blocks) { + status = HAL_CRYPEx_AES_Auth(&hcryp, (byte*)in, + (blocks * AES_BLOCK_SIZE), out, STM32_HAL_TIMEOUT); + } + } + if (status == HAL_OK && partial != 0) { + /* GCM payload phase - partial remainder */ + XMEMSET(partialBlock, 0, sizeof(partialBlock)); + XMEMCPY(partialBlock, in + (blocks * AES_BLOCK_SIZE), partial); + status = HAL_CRYPEx_AES_Auth(&hcryp, partialBlock, partial, + partialBlock, STM32_HAL_TIMEOUT); + XMEMCPY(out + (blocks * AES_BLOCK_SIZE), partialBlock, partial); + } + if (status == HAL_OK) { + /* GCM final phase */ + hcryp.Init.GCMCMACPhase = CRYP_FINAL_PHASE; + status = HAL_CRYPEx_AES_Auth(&hcryp, NULL, sz, tag, STM32_HAL_TIMEOUT); + } +#else + HAL_CRYP_Init(&hcryp); + if (blocks) { + /* GCM payload phase - blocks */ + status = HAL_CRYPEx_AESGCM_Encrypt(&hcryp, (byte*)in, + (blocks * AES_BLOCK_SIZE), out, STM32_HAL_TIMEOUT); + } + if (status == HAL_OK && partial != 0) { + /* GCM payload phase - partial remainder */ + XMEMSET(partialBlock, 0, sizeof(partialBlock)); + XMEMCPY(partialBlock, in + (blocks * AES_BLOCK_SIZE), partial); + status = HAL_CRYPEx_AESGCM_Encrypt(&hcryp, partialBlock, partial, + partialBlock, STM32_HAL_TIMEOUT); + XMEMCPY(out + (blocks * AES_BLOCK_SIZE), partialBlock, partial); + } + if (status == HAL_OK) { + /* Compute the authTag */ + status = HAL_CRYPEx_AESGCM_Finish(&hcryp, sz, tag, STM32_HAL_TIMEOUT); + } +#endif + + if (status != HAL_OK) + ret = AES_GCM_AUTH_E; + HAL_CRYP_DeInit(&hcryp); + +#else /* STD_PERI_LIB */ + ByteReverseWords(keyCopy, (word32*)aes->key, keySize); + status = CRYP_AES_GCM(MODE_ENCRYPT, (uint8_t*)ctr, + (uint8_t*)keyCopy, keySize * 8, + (uint8_t*)in, sz, + (uint8_t*)authInPadded, authInSz, + (uint8_t*)out, tag); + if (status != SUCCESS) + ret = AES_GCM_AUTH_E; +#endif /* WOLFSSL_STM32_CUBEMX */ + + if (ret == 0) { + /* return authTag */ + if (authTag) { + /* STM32 GCM won't compute Auth correctly for partial or + when IV != 12, so use software here */ + if (partial != 0 || ivSz != GCM_NONCE_MID_SZ) { + DecrementGcmCounter(ctr); /* hardware requires +1, so subtract it */ + GHASH(aes, authIn, authInSz, out, sz, authTag, authTagSz); + wc_AesEncrypt(aes, ctr, tag); + xorbuf(authTag, tag, authTagSz); + } + else { + XMEMCPY(authTag, tag, authTagSz); + } + } + } + + /* Free memory if not a multiple of AES_BLOCK_SZ */ + if (authInPadded != authIn) { + XFREE(authInPadded, aes->heap, DYNAMIC_TYPE_TMP_BUFFER); + } + + return ret; +} + +#endif /* STM32_CRYPTO_AES_GCM */ + +#ifdef WOLFSSL_AESNI +int AES_GCM_encrypt_C(Aes* aes, byte* out, const byte* in, word32 sz, + const byte* iv, word32 ivSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz); +#else +static +#endif +int AES_GCM_encrypt_C(Aes* aes, byte* out, const byte* in, word32 sz, + const byte* iv, word32 ivSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) +{ + int ret = 0; + word32 blocks = sz / AES_BLOCK_SIZE; + word32 partial = sz % AES_BLOCK_SIZE; + const byte* p = in; + byte* c = out; + byte counter[AES_BLOCK_SIZE]; + byte initialCounter[AES_BLOCK_SIZE]; + byte *ctr; + byte scratch[AES_BLOCK_SIZE]; + + ctr = counter; + XMEMSET(initialCounter, 0, AES_BLOCK_SIZE); + if (ivSz == GCM_NONCE_MID_SZ) { + XMEMCPY(initialCounter, iv, ivSz); + initialCounter[AES_BLOCK_SIZE - 1] = 1; + } + else { + GHASH(aes, NULL, 0, iv, ivSz, initialCounter, AES_BLOCK_SIZE); + } + XMEMCPY(ctr, initialCounter, AES_BLOCK_SIZE); + +#ifdef WOLFSSL_PIC32MZ_CRYPT + if (blocks) { + /* use initial IV for HW, but don't use it below */ + XMEMCPY(aes->reg, ctr, AES_BLOCK_SIZE); + + ret = wc_Pic32AesCrypt( + aes->key, aes->keylen, aes->reg, AES_BLOCK_SIZE, + out, in, (blocks * AES_BLOCK_SIZE), + PIC32_ENCRYPTION, PIC32_ALGO_AES, PIC32_CRYPTOALGO_AES_GCM); + if (ret != 0) + return ret; + } + /* process remainder using partial handling */ +#endif + +#if defined(HAVE_AES_ECB) && !defined(WOLFSSL_PIC32MZ_CRYPT) + /* some hardware acceleration can gain performance from doing AES encryption + * of the whole buffer at once */ + if (c != p) { /* can not handle inline encryption */ + while (blocks--) { + IncrementGcmCounter(ctr); + XMEMCPY(c, ctr, AES_BLOCK_SIZE); + c += AES_BLOCK_SIZE; + } + + /* reset number of blocks and then do encryption */ + blocks = sz / AES_BLOCK_SIZE; + wc_AesEcbEncrypt(aes, out, out, AES_BLOCK_SIZE * blocks); + xorbuf(out, p, AES_BLOCK_SIZE * blocks); + p += AES_BLOCK_SIZE * blocks; + } + else +#endif /* HAVE_AES_ECB && !WOLFSSL_PIC32MZ_CRYPT */ + + while (blocks--) { + IncrementGcmCounter(ctr); + #if !defined(WOLFSSL_PIC32MZ_CRYPT) + wc_AesEncrypt(aes, ctr, scratch); + xorbuf(scratch, p, AES_BLOCK_SIZE); + XMEMCPY(c, scratch, AES_BLOCK_SIZE); + #endif + p += AES_BLOCK_SIZE; + c += AES_BLOCK_SIZE; + } + + if (partial != 0) { + IncrementGcmCounter(ctr); + wc_AesEncrypt(aes, ctr, scratch); + xorbuf(scratch, p, partial); + XMEMCPY(c, scratch, partial); + } + + if (authTag) { + GHASH(aes, authIn, authInSz, out, sz, authTag, authTagSz); + wc_AesEncrypt(aes, initialCounter, scratch); + xorbuf(authTag, scratch, authTagSz); + } + + return ret; +} + +/* Software AES - GCM Encrypt */ +int wc_AesGcmEncrypt(Aes* aes, byte* out, const byte* in, word32 sz, + const byte* iv, word32 ivSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) +{ + /* argument checks */ + if (aes == NULL || authTagSz > AES_BLOCK_SIZE) { + return BAD_FUNC_ARG; + } + + if (authTagSz < WOLFSSL_MIN_AUTH_TAG_SZ) { + WOLFSSL_MSG("GcmEncrypt authTagSz too small error"); + return BAD_FUNC_ARG; + } + +#ifdef WOLF_CRYPTO_CB + if (aes->devId != INVALID_DEVID) { + int ret = wc_CryptoCb_AesGcmEncrypt(aes, out, in, sz, iv, ivSz, + authTag, authTagSz, authIn, authInSz); + if (ret != CRYPTOCB_UNAVAILABLE) + return ret; + /* fall-through when unavailable */ + } +#endif + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES) + /* if async and byte count above threshold */ + /* only 12-byte IV is supported in HW */ + if (aes->asyncDev.marker == WOLFSSL_ASYNC_MARKER_AES && + sz >= WC_ASYNC_THRESH_AES_GCM && ivSz == GCM_NONCE_MID_SZ) { + #if defined(HAVE_CAVIUM) + #ifdef HAVE_CAVIUM_V + if (authInSz == 20) { /* Nitrox V GCM is only working with 20 byte AAD */ + return NitroxAesGcmEncrypt(aes, out, in, sz, + (const byte*)aes->asyncKey, aes->keylen, iv, ivSz, + authTag, authTagSz, authIn, authInSz); + } + #endif + #elif defined(HAVE_INTEL_QA) + return IntelQaSymAesGcmEncrypt(&aes->asyncDev, out, in, sz, + (const byte*)aes->asyncKey, aes->keylen, iv, ivSz, + authTag, authTagSz, authIn, authInSz); + #else /* WOLFSSL_ASYNC_CRYPT_TEST */ + if (wc_AsyncTestInit(&aes->asyncDev, ASYNC_TEST_AES_GCM_ENCRYPT)) { + WC_ASYNC_TEST* testDev = &aes->asyncDev.test; + testDev->aes.aes = aes; + testDev->aes.out = out; + testDev->aes.in = in; + testDev->aes.sz = sz; + testDev->aes.iv = iv; + testDev->aes.ivSz = ivSz; + testDev->aes.authTag = authTag; + testDev->aes.authTagSz = authTagSz; + testDev->aes.authIn = authIn; + testDev->aes.authInSz = authInSz; + return WC_PENDING_E; + } + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + +#ifdef STM32_CRYPTO_AES_GCM + /* The STM standard peripheral library API's doesn't support partial blocks */ + #ifdef STD_PERI_LIB + if (partial == 0) + #endif + { + return wc_AesGcmEncrypt_STM32( + aes, out, in, sz, iv, ivSz, + authTag, authTagSz, authIn, authInSz); + } +#endif /* STM32_CRYPTO_AES_GCM */ + +#ifdef WOLFSSL_AESNI + #ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_AVX2(intel_flags)) { + AES_GCM_encrypt_avx2(in, out, authIn, iv, authTag, sz, authInSz, ivSz, + authTagSz, (const byte*)aes->key, aes->rounds); + return 0; + } + else + #endif + #ifdef HAVE_INTEL_AVX1 + if (IS_INTEL_AVX1(intel_flags)) { + AES_GCM_encrypt_avx1(in, out, authIn, iv, authTag, sz, authInSz, ivSz, + authTagSz, (const byte*)aes->key, aes->rounds); + return 0; + } + else + #endif + if (haveAESNI) { + AES_GCM_encrypt(in, out, authIn, iv, authTag, sz, authInSz, ivSz, + authTagSz, (const byte*)aes->key, aes->rounds); + return 0; + } + else +#endif + { + return AES_GCM_encrypt_C(aes, out, in, sz, iv, ivSz, authTag, authTagSz, + authIn, authInSz); + } +} +#endif + + + +/* AES GCM Decrypt */ +#if defined(HAVE_AES_DECRYPT) || defined(HAVE_AESGCM_DECRYPT) +#ifdef FREESCALE_LTC_AES_GCM +int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, + const byte* iv, word32 ivSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) +{ + int ret; + word32 keySize; + status_t status; + + /* argument checks */ + /* If the sz is non-zero, both in and out must be set. If sz is 0, + * in and out are don't cares, as this is is the GMAC case. */ + if (aes == NULL || iv == NULL || (sz != 0 && (in == NULL || out == NULL)) || + authTag == NULL || authTagSz > AES_BLOCK_SIZE || authTagSz == 0) { + + return BAD_FUNC_ARG; + } + + ret = wc_AesGetKeySize(aes, &keySize); + if (ret != 0) { + return ret; + } + + status = LTC_AES_DecryptTagGcm(LTC_BASE, in, out, sz, iv, ivSz, + authIn, authInSz, (byte*)aes->key, keySize, authTag, authTagSz); + + return (status == kStatus_Success) ? 0 : AES_GCM_AUTH_E; +} + +#else + +#ifdef STM32_CRYPTO_AES_GCM +/* this function supports inline decrypt */ +static int wc_AesGcmDecrypt_STM32(Aes* aes, byte* out, + const byte* in, word32 sz, + const byte* iv, word32 ivSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) +{ + int ret; +#ifdef WOLFSSL_STM32_CUBEMX + CRYP_HandleTypeDef hcryp; +#else + word32 keyCopy[AES_256_KEY_SIZE/sizeof(word32)]; +#endif + word32 keySize; + int status = HAL_OK; + word32 blocks = sz / AES_BLOCK_SIZE; + word32 partial = sz % AES_BLOCK_SIZE; + byte tag[AES_BLOCK_SIZE]; + byte partialBlock[AES_BLOCK_SIZE]; + byte ctr[AES_BLOCK_SIZE]; + byte* authInPadded = NULL; + int authPadSz; + + ret = wc_AesGetKeySize(aes, &keySize); + if (ret != 0) + return ret; + +#ifdef WOLFSSL_STM32_CUBEMX + ret = wc_Stm32_Aes_Init(aes, &hcryp); + if (ret != 0) + return ret; +#endif + + XMEMSET(ctr, 0, AES_BLOCK_SIZE); + if (ivSz == GCM_NONCE_MID_SZ) { + XMEMCPY(ctr, iv, ivSz); + ctr[AES_BLOCK_SIZE - 1] = 1; + } + else { + GHASH(aes, NULL, 0, iv, ivSz, ctr, AES_BLOCK_SIZE); + } + /* Hardware requires counter + 1 */ + IncrementGcmCounter(ctr); + + if (authInSz == 0 || (authInSz % AES_BLOCK_SIZE) != 0) { + /* Need to pad the AAD to a full block with zeros. */ + authPadSz = ((authInSz / AES_BLOCK_SIZE) + 1) * AES_BLOCK_SIZE; + authInPadded = (byte*)XMALLOC(authPadSz, aes->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (authInPadded == NULL) { + return MEMORY_E; + } + XMEMSET(authInPadded, 0, authPadSz); + XMEMCPY(authInPadded, authIn, authInSz); + } else { + authPadSz = authInSz; + authInPadded = (byte*)authIn; + } + +#ifdef WOLFSSL_STM32_CUBEMX + hcryp.Init.pInitVect = (uint8_t*)ctr; + hcryp.Init.Header = authInPadded; + hcryp.Init.HeaderSize = authInSz; + +#ifdef STM32_CRYPTO_AES_ONLY + /* Set the CRYP parameters */ + hcryp.Init.ChainingMode = CRYP_CHAINMODE_AES_GCM_GMAC; + hcryp.Init.OperatingMode = CRYP_ALGOMODE_DECRYPT; + hcryp.Init.GCMCMACPhase = CRYP_INIT_PHASE; + HAL_CRYP_Init(&hcryp); + + /* GCM init phase */ + status = HAL_CRYPEx_AES_Auth(&hcryp, NULL, 0, NULL, STM32_HAL_TIMEOUT); + if (status == HAL_OK) { + /* GCM header phase */ + hcryp.Init.GCMCMACPhase = CRYP_HEADER_PHASE; + status = HAL_CRYPEx_AES_Auth(&hcryp, NULL, 0, NULL, STM32_HAL_TIMEOUT); + } + if (status == HAL_OK) { + /* GCM payload phase - blocks */ + hcryp.Init.GCMCMACPhase = CRYP_PAYLOAD_PHASE; + if (blocks) { + status = HAL_CRYPEx_AES_Auth(&hcryp, (byte*)in, + (blocks * AES_BLOCK_SIZE), out, STM32_HAL_TIMEOUT); + } + } + if (status == HAL_OK && partial != 0) { + /* GCM payload phase - partial remainder */ + XMEMSET(partialBlock, 0, sizeof(partialBlock)); + XMEMCPY(partialBlock, in + (blocks * AES_BLOCK_SIZE), partial); + status = HAL_CRYPEx_AES_Auth(&hcryp, partialBlock, partial, + partialBlock, STM32_HAL_TIMEOUT); + XMEMCPY(out + (blocks * AES_BLOCK_SIZE), partialBlock, partial); + } + if (status == HAL_OK) { + /* GCM final phase */ + hcryp.Init.GCMCMACPhase = CRYP_FINAL_PHASE; + status = HAL_CRYPEx_AES_Auth(&hcryp, NULL, sz, tag, STM32_HAL_TIMEOUT); + } +#else + HAL_CRYP_Init(&hcryp); + if (blocks) { + /* GCM payload phase - blocks */ + status = HAL_CRYPEx_AESGCM_Decrypt(&hcryp, (byte*)in, + (blocks * AES_BLOCK_SIZE), out, STM32_HAL_TIMEOUT); + } + if (status == HAL_OK && partial != 0) { + /* GCM payload phase - partial remainder */ + XMEMSET(partialBlock, 0, sizeof(partialBlock)); + XMEMCPY(partialBlock, in + (blocks * AES_BLOCK_SIZE), partial); + status = HAL_CRYPEx_AESGCM_Decrypt(&hcryp, partialBlock, partial, + partialBlock, STM32_HAL_TIMEOUT); + XMEMCPY(out + (blocks * AES_BLOCK_SIZE), partialBlock, partial); + } + if (status == HAL_OK) { + /* Compute the authTag */ + status = HAL_CRYPEx_AESGCM_Finish(&hcryp, sz, tag, STM32_HAL_TIMEOUT); + } +#endif + + if (status != HAL_OK) + ret = AES_GCM_AUTH_E; + + HAL_CRYP_DeInit(&hcryp); + +#else /* STD_PERI_LIB */ + ByteReverseWords(keyCopy, (word32*)aes->key, aes->keylen); + + /* Input size and auth size need to be the actual sizes, even though + * they are not block aligned, because this length (in bits) is used + * in the final GHASH. */ + status = CRYP_AES_GCM(MODE_DECRYPT, (uint8_t*)ctr, + (uint8_t*)keyCopy, keySize * 8, + (uint8_t*)in, sz, + (uint8_t*)authInPadded, authInSz, + (uint8_t*)out, tag); + if (status != SUCCESS) + ret = AES_GCM_AUTH_E; +#endif /* WOLFSSL_STM32_CUBEMX */ + + /* STM32 GCM hardware only supports IV of 12 bytes, so use software for auth */ + if (ivSz != GCM_NONCE_MID_SZ) { + DecrementGcmCounter(ctr); /* hardware requires +1, so subtract it */ + GHASH(aes, authIn, authInSz, in, sz, tag, sizeof(tag)); + wc_AesEncrypt(aes, ctr, partialBlock); + xorbuf(tag, partialBlock, sizeof(tag)); + } + + if (ConstantCompare(authTag, tag, authTagSz) != 0) { + ret = AES_GCM_AUTH_E; + } + + /* Free memory if not a multiple of AES_BLOCK_SZ */ + if (authInPadded != authIn) { + XFREE(authInPadded, aes->heap, DYNAMIC_TYPE_TMP_BUFFER); + } + + return ret; +} + +#endif /* STM32_CRYPTO_AES_GCM */ + +#ifdef WOLFSSL_AESNI +int AES_GCM_decrypt_C(Aes* aes, byte* out, const byte* in, word32 sz, + const byte* iv, word32 ivSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz); +#else +static +#endif +int AES_GCM_decrypt_C(Aes* aes, byte* out, const byte* in, word32 sz, + const byte* iv, word32 ivSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) +{ + int ret = 0; + word32 blocks = sz / AES_BLOCK_SIZE; + word32 partial = sz % AES_BLOCK_SIZE; + const byte* c = in; + byte* p = out; + byte counter[AES_BLOCK_SIZE]; + byte initialCounter[AES_BLOCK_SIZE]; + byte *ctr; + byte scratch[AES_BLOCK_SIZE]; + byte Tprime[AES_BLOCK_SIZE]; + byte EKY0[AES_BLOCK_SIZE]; + + ctr = counter; + XMEMSET(initialCounter, 0, AES_BLOCK_SIZE); + if (ivSz == GCM_NONCE_MID_SZ) { + XMEMCPY(initialCounter, iv, ivSz); + initialCounter[AES_BLOCK_SIZE - 1] = 1; + } + else { + GHASH(aes, NULL, 0, iv, ivSz, initialCounter, AES_BLOCK_SIZE); + } + XMEMCPY(ctr, initialCounter, AES_BLOCK_SIZE); + + /* Calc the authTag again using the received auth data and the cipher text */ + GHASH(aes, authIn, authInSz, in, sz, Tprime, sizeof(Tprime)); + wc_AesEncrypt(aes, ctr, EKY0); + xorbuf(Tprime, EKY0, sizeof(Tprime)); + + if (ConstantCompare(authTag, Tprime, authTagSz) != 0) { + return AES_GCM_AUTH_E; + } + +#if defined(WOLFSSL_PIC32MZ_CRYPT) + if (blocks) { + /* use initial IV for HW, but don't use it below */ + XMEMCPY(aes->reg, ctr, AES_BLOCK_SIZE); + + ret = wc_Pic32AesCrypt( + aes->key, aes->keylen, aes->reg, AES_BLOCK_SIZE, + out, in, (blocks * AES_BLOCK_SIZE), + PIC32_DECRYPTION, PIC32_ALGO_AES, PIC32_CRYPTOALGO_AES_GCM); + if (ret != 0) + return ret; + } + /* process remainder using partial handling */ +#endif + +#if defined(HAVE_AES_ECB) && !defined(WOLFSSL_PIC32MZ_CRYPT) + /* some hardware acceleration can gain performance from doing AES encryption + * of the whole buffer at once */ + if (c != p) { /* can not handle inline decryption */ + while (blocks--) { + IncrementGcmCounter(ctr); + XMEMCPY(p, ctr, AES_BLOCK_SIZE); + p += AES_BLOCK_SIZE; + } + + /* reset number of blocks and then do encryption */ + blocks = sz / AES_BLOCK_SIZE; + wc_AesEcbEncrypt(aes, out, out, AES_BLOCK_SIZE * blocks); + xorbuf(out, c, AES_BLOCK_SIZE * blocks); + c += AES_BLOCK_SIZE * blocks; + } + else +#endif /* HAVE_AES_ECB && !PIC32MZ */ + while (blocks--) { + IncrementGcmCounter(ctr); + #if !defined(WOLFSSL_PIC32MZ_CRYPT) + wc_AesEncrypt(aes, ctr, scratch); + xorbuf(scratch, c, AES_BLOCK_SIZE); + XMEMCPY(p, scratch, AES_BLOCK_SIZE); + #endif + p += AES_BLOCK_SIZE; + c += AES_BLOCK_SIZE; + } + + if (partial != 0) { + IncrementGcmCounter(ctr); + wc_AesEncrypt(aes, ctr, scratch); + xorbuf(scratch, c, partial); + XMEMCPY(p, scratch, partial); + } + + return ret; +} + +/* Software AES - GCM Decrypt */ +int wc_AesGcmDecrypt(Aes* aes, byte* out, const byte* in, word32 sz, + const byte* iv, word32 ivSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) +{ +#ifdef WOLFSSL_AESNI + int res = AES_GCM_AUTH_E; +#endif + + /* argument checks */ + /* If the sz is non-zero, both in and out must be set. If sz is 0, + * in and out are don't cares, as this is is the GMAC case. */ + if (aes == NULL || iv == NULL || (sz != 0 && (in == NULL || out == NULL)) || + authTag == NULL || authTagSz > AES_BLOCK_SIZE || authTagSz == 0) { + + return BAD_FUNC_ARG; + } + +#ifdef WOLF_CRYPTO_CB + if (aes->devId != INVALID_DEVID) { + int ret = wc_CryptoCb_AesGcmDecrypt(aes, out, in, sz, iv, ivSz, + authTag, authTagSz, authIn, authInSz); + if (ret != CRYPTOCB_UNAVAILABLE) + return ret; + /* fall-through when unavailable */ + } +#endif + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES) + /* if async and byte count above threshold */ + /* only 12-byte IV is supported in HW */ + if (aes->asyncDev.marker == WOLFSSL_ASYNC_MARKER_AES && + sz >= WC_ASYNC_THRESH_AES_GCM && ivSz == GCM_NONCE_MID_SZ) { + #if defined(HAVE_CAVIUM) + #ifdef HAVE_CAVIUM_V + if (authInSz == 20) { /* Nitrox V GCM is only working with 20 byte AAD */ + return NitroxAesGcmDecrypt(aes, out, in, sz, + (const byte*)aes->asyncKey, aes->keylen, iv, ivSz, + authTag, authTagSz, authIn, authInSz); + } + #endif + #elif defined(HAVE_INTEL_QA) + return IntelQaSymAesGcmDecrypt(&aes->asyncDev, out, in, sz, + (const byte*)aes->asyncKey, aes->keylen, iv, ivSz, + authTag, authTagSz, authIn, authInSz); + #else /* WOLFSSL_ASYNC_CRYPT_TEST */ + if (wc_AsyncTestInit(&aes->asyncDev, ASYNC_TEST_AES_GCM_DECRYPT)) { + WC_ASYNC_TEST* testDev = &aes->asyncDev.test; + testDev->aes.aes = aes; + testDev->aes.out = out; + testDev->aes.in = in; + testDev->aes.sz = sz; + testDev->aes.iv = iv; + testDev->aes.ivSz = ivSz; + testDev->aes.authTag = (byte*)authTag; + testDev->aes.authTagSz = authTagSz; + testDev->aes.authIn = authIn; + testDev->aes.authInSz = authInSz; + return WC_PENDING_E; + } + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + +#ifdef STM32_CRYPTO_AES_GCM + /* The STM standard peripheral library API's doesn't support partial blocks */ + #ifdef STD_PERI_LIB + if (partial == 0) + #endif + { + return wc_AesGcmDecrypt_STM32( + aes, out, in, sz, iv, ivSz, + authTag, authTagSz, authIn, authInSz); + } +#endif /* STM32_CRYPTO_AES_GCM */ + +#ifdef WOLFSSL_AESNI + #ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_AVX2(intel_flags)) { + AES_GCM_decrypt_avx2(in, out, authIn, iv, authTag, sz, authInSz, ivSz, + authTagSz, (byte*)aes->key, aes->rounds, &res); + if (res == 0) + return AES_GCM_AUTH_E; + return 0; + } + else + #endif + #ifdef HAVE_INTEL_AVX1 + if (IS_INTEL_AVX1(intel_flags)) { + AES_GCM_decrypt_avx1(in, out, authIn, iv, authTag, sz, authInSz, ivSz, + authTagSz, (byte*)aes->key, aes->rounds, &res); + if (res == 0) + return AES_GCM_AUTH_E; + return 0; + } + else + #endif + if (haveAESNI) { + AES_GCM_decrypt(in, out, authIn, iv, authTag, sz, authInSz, ivSz, + authTagSz, (byte*)aes->key, aes->rounds, &res); + if (res == 0) + return AES_GCM_AUTH_E; + return 0; + } + else +#endif + { + return AES_GCM_decrypt_C(aes, out, in, sz, iv, ivSz, authTag, authTagSz, + authIn, authInSz); + } +} +#endif +#endif /* HAVE_AES_DECRYPT || HAVE_AESGCM_DECRYPT */ +#endif /* WOLFSSL_XILINX_CRYPT */ +#endif /* end of block for AESGCM implementation selection */ + + +/* Common to all, abstract functions that build off of lower level AESGCM + * functions */ +#ifndef WC_NO_RNG + +int wc_AesGcmSetExtIV(Aes* aes, const byte* iv, word32 ivSz) +{ + int ret = 0; + + if (aes == NULL || iv == NULL || + (ivSz != GCM_NONCE_MIN_SZ && ivSz != GCM_NONCE_MID_SZ && + ivSz != GCM_NONCE_MAX_SZ)) { + + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + XMEMCPY((byte*)aes->reg, iv, ivSz); + + /* If the IV is 96, allow for a 2^64 invocation counter. + * For any other size for the nonce, limit the invocation + * counter to 32-bits. (SP 800-38D 8.3) */ + aes->invokeCtr[0] = 0; + aes->invokeCtr[1] = (ivSz == GCM_NONCE_MID_SZ) ? 0 : 0xFFFFFFFF; + aes->nonceSz = ivSz; + } + + return ret; +} + + +int wc_AesGcmSetIV(Aes* aes, word32 ivSz, + const byte* ivFixed, word32 ivFixedSz, + WC_RNG* rng) +{ + int ret = 0; + + if (aes == NULL || rng == NULL || + (ivSz != GCM_NONCE_MIN_SZ && ivSz != GCM_NONCE_MID_SZ && + ivSz != GCM_NONCE_MAX_SZ) || + (ivFixed == NULL && ivFixedSz != 0) || + (ivFixed != NULL && ivFixedSz != AES_IV_FIXED_SZ)) { + + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + byte* iv = (byte*)aes->reg; + + if (ivFixedSz) + XMEMCPY(iv, ivFixed, ivFixedSz); + + ret = wc_RNG_GenerateBlock(rng, iv + ivFixedSz, ivSz - ivFixedSz); + } + + if (ret == 0) { + /* If the IV is 96, allow for a 2^64 invocation counter. + * For any other size for the nonce, limit the invocation + * counter to 32-bits. (SP 800-38D 8.3) */ + aes->invokeCtr[0] = 0; + aes->invokeCtr[1] = (ivSz == GCM_NONCE_MID_SZ) ? 0 : 0xFFFFFFFF; + aes->nonceSz = ivSz; + } + + return ret; +} + + +int wc_AesGcmEncrypt_ex(Aes* aes, byte* out, const byte* in, word32 sz, + byte* ivOut, word32 ivOutSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) +{ + int ret = 0; + + if (aes == NULL || (sz != 0 && (in == NULL || out == NULL)) || + ivOut == NULL || ivOutSz != aes->nonceSz || + (authIn == NULL && authInSz != 0)) { + + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + aes->invokeCtr[0]++; + if (aes->invokeCtr[0] == 0) { + aes->invokeCtr[1]++; + if (aes->invokeCtr[1] == 0) + ret = AES_GCM_OVERFLOW_E; + } + } + + if (ret == 0) { + XMEMCPY(ivOut, aes->reg, ivOutSz); + ret = wc_AesGcmEncrypt(aes, out, in, sz, + (byte*)aes->reg, ivOutSz, + authTag, authTagSz, + authIn, authInSz); + if (ret == 0) + IncCtr((byte*)aes->reg, ivOutSz); + } + + return ret; +} + +int wc_Gmac(const byte* key, word32 keySz, byte* iv, word32 ivSz, + const byte* authIn, word32 authInSz, + byte* authTag, word32 authTagSz, WC_RNG* rng) +{ + Aes aes; + int ret; + + if (key == NULL || iv == NULL || (authIn == NULL && authInSz != 0) || + authTag == NULL || authTagSz == 0 || rng == NULL) { + + return BAD_FUNC_ARG; + } + + ret = wc_AesInit(&aes, NULL, INVALID_DEVID); + if (ret == 0) { + ret = wc_AesGcmSetKey(&aes, key, keySz); + if (ret == 0) + ret = wc_AesGcmSetIV(&aes, ivSz, NULL, 0, rng); + if (ret == 0) + ret = wc_AesGcmEncrypt_ex(&aes, NULL, NULL, 0, iv, ivSz, + authTag, authTagSz, authIn, authInSz); + wc_AesFree(&aes); + } + ForceZero(&aes, sizeof(aes)); + + return ret; +} + +int wc_GmacVerify(const byte* key, word32 keySz, + const byte* iv, word32 ivSz, + const byte* authIn, word32 authInSz, + const byte* authTag, word32 authTagSz) +{ + int ret; +#ifndef NO_AES_DECRYPT + Aes aes; + + if (key == NULL || iv == NULL || (authIn == NULL && authInSz != 0) || + authTag == NULL || authTagSz == 0 || authTagSz > AES_BLOCK_SIZE) { + + return BAD_FUNC_ARG; + } + + ret = wc_AesInit(&aes, NULL, INVALID_DEVID); + if (ret == 0) { + ret = wc_AesGcmSetKey(&aes, key, keySz); + if (ret == 0) + ret = wc_AesGcmDecrypt(&aes, NULL, NULL, 0, iv, ivSz, + authTag, authTagSz, authIn, authInSz); + wc_AesFree(&aes); + } + ForceZero(&aes, sizeof(aes)); +#else + (void)key; + (void)keySz; + (void)iv; + (void)ivSz; + (void)authIn; + (void)authInSz; + (void)authTag; + (void)authTagSz; + ret = NOT_COMPILED_IN; +#endif + return ret; +} + +#endif /* WC_NO_RNG */ + + +WOLFSSL_API int wc_GmacSetKey(Gmac* gmac, const byte* key, word32 len) +{ + if (gmac == NULL || key == NULL) { + return BAD_FUNC_ARG; + } + return wc_AesGcmSetKey(&gmac->aes, key, len); +} + + +WOLFSSL_API int wc_GmacUpdate(Gmac* gmac, const byte* iv, word32 ivSz, + const byte* authIn, word32 authInSz, + byte* authTag, word32 authTagSz) +{ + return wc_AesGcmEncrypt(&gmac->aes, NULL, NULL, 0, iv, ivSz, + authTag, authTagSz, authIn, authInSz); +} + +#endif /* HAVE_AESGCM */ + + +#ifdef HAVE_AESCCM + +int wc_AesCcmSetKey(Aes* aes, const byte* key, word32 keySz) +{ + if (!((keySz == 16) || (keySz == 24) || (keySz == 32))) + return BAD_FUNC_ARG; + + return wc_AesSetKey(aes, key, keySz, NULL, AES_ENCRYPTION); +} + +#ifdef WOLFSSL_ARMASM + /* implementation located in wolfcrypt/src/port/arm/armv8-aes.c */ + +#elif defined(HAVE_COLDFIRE_SEC) + #error "Coldfire SEC doesn't currently support AES-CCM mode" + +#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES) + /* implemented in wolfcrypt/src/port/caam_aes.c */ + +#elif defined(FREESCALE_LTC) + +/* return 0 on success */ +int wc_AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz, + const byte* nonce, word32 nonceSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) +{ + byte *key; + uint32_t keySize; + status_t status; + + /* sanity check on arguments */ + if (aes == NULL || out == NULL || in == NULL || nonce == NULL + || authTag == NULL || nonceSz < 7 || nonceSz > 13) + return BAD_FUNC_ARG; + + key = (byte*)aes->key; + + status = wc_AesGetKeySize(aes, &keySize); + if (status != 0) { + return status; + } + + status = LTC_AES_EncryptTagCcm(LTC_BASE, in, out, inSz, + nonce, nonceSz, authIn, authInSz, key, keySize, authTag, authTagSz); + + return (kStatus_Success == status) ? 0 : BAD_FUNC_ARG; +} + +#ifdef HAVE_AES_DECRYPT +int wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz, + const byte* nonce, word32 nonceSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) +{ + byte *key; + uint32_t keySize; + status_t status; + + /* sanity check on arguments */ + if (aes == NULL || out == NULL || in == NULL || nonce == NULL + || authTag == NULL || nonceSz < 7 || nonceSz > 13) + return BAD_FUNC_ARG; + + key = (byte*)aes->key; + + status = wc_AesGetKeySize(aes, &keySize); + if (status != 0) { + return status; + } + + status = LTC_AES_DecryptTagCcm(LTC_BASE, in, out, inSz, + nonce, nonceSz, authIn, authInSz, key, keySize, authTag, authTagSz); + + if (status == kStatus_Success) { + return 0; + } + else { + XMEMSET(out, 0, inSz); + return AES_CCM_AUTH_E; + } +} +#endif /* HAVE_AES_DECRYPT */ + +#else + +/* Software CCM */ +static void roll_x(Aes* aes, const byte* in, word32 inSz, byte* out) +{ + /* process the bulk of the data */ + while (inSz >= AES_BLOCK_SIZE) { + xorbuf(out, in, AES_BLOCK_SIZE); + in += AES_BLOCK_SIZE; + inSz -= AES_BLOCK_SIZE; + + wc_AesEncrypt(aes, out, out); + } + + /* process remainder of the data */ + if (inSz > 0) { + xorbuf(out, in, inSz); + wc_AesEncrypt(aes, out, out); + } +} + +static void roll_auth(Aes* aes, const byte* in, word32 inSz, byte* out) +{ + word32 authLenSz; + word32 remainder; + + /* encode the length in */ + if (inSz <= 0xFEFF) { + authLenSz = 2; + out[0] ^= ((inSz & 0xFF00) >> 8); + out[1] ^= (inSz & 0x00FF); + } + else if (inSz <= 0xFFFFFFFF) { + authLenSz = 6; + out[0] ^= 0xFF; out[1] ^= 0xFE; + out[2] ^= ((inSz & 0xFF000000) >> 24); + out[3] ^= ((inSz & 0x00FF0000) >> 16); + out[4] ^= ((inSz & 0x0000FF00) >> 8); + out[5] ^= (inSz & 0x000000FF); + } + /* Note, the protocol handles auth data up to 2^64, but we are + * using 32-bit sizes right now, so the bigger data isn't handled + * else if (inSz <= 0xFFFFFFFFFFFFFFFF) {} */ + else + return; + + /* start fill out the rest of the first block */ + remainder = AES_BLOCK_SIZE - authLenSz; + if (inSz >= remainder) { + /* plenty of bulk data to fill the remainder of this block */ + xorbuf(out + authLenSz, in, remainder); + inSz -= remainder; + in += remainder; + } + else { + /* not enough bulk data, copy what is available, and pad zero */ + xorbuf(out + authLenSz, in, inSz); + inSz = 0; + } + wc_AesEncrypt(aes, out, out); + + if (inSz > 0) + roll_x(aes, in, inSz, out); +} + + +static WC_INLINE void AesCcmCtrInc(byte* B, word32 lenSz) +{ + word32 i; + + for (i = 0; i < lenSz; i++) { + if (++B[AES_BLOCK_SIZE - 1 - i] != 0) return; + } +} + +/* Software AES - CCM Encrypt */ +/* return 0 on success */ +int wc_AesCcmEncrypt(Aes* aes, byte* out, const byte* in, word32 inSz, + const byte* nonce, word32 nonceSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) +{ + byte A[AES_BLOCK_SIZE]; + byte B[AES_BLOCK_SIZE]; + byte lenSz; + word32 i; + byte mask = 0xFF; + const word32 wordSz = (word32)sizeof(word32); + + /* sanity check on arguments */ + if (aes == NULL || out == NULL || in == NULL || nonce == NULL + || authTag == NULL || nonceSz < 7 || nonceSz > 13 || + authTagSz > AES_BLOCK_SIZE) + return BAD_FUNC_ARG; + + XMEMCPY(B+1, nonce, nonceSz); + lenSz = AES_BLOCK_SIZE - 1 - (byte)nonceSz; + B[0] = (authInSz > 0 ? 64 : 0) + + (8 * (((byte)authTagSz - 2) / 2)) + + (lenSz - 1); + for (i = 0; i < lenSz; i++) { + if (mask && i >= wordSz) + mask = 0x00; + B[AES_BLOCK_SIZE - 1 - i] = (inSz >> ((8 * i) & mask)) & mask; + } + + wc_AesEncrypt(aes, B, A); + + if (authInSz > 0) + roll_auth(aes, authIn, authInSz, A); + if (inSz > 0) + roll_x(aes, in, inSz, A); + XMEMCPY(authTag, A, authTagSz); + + B[0] = lenSz - 1; + for (i = 0; i < lenSz; i++) + B[AES_BLOCK_SIZE - 1 - i] = 0; + wc_AesEncrypt(aes, B, A); + xorbuf(authTag, A, authTagSz); + + B[15] = 1; + while (inSz >= AES_BLOCK_SIZE) { + wc_AesEncrypt(aes, B, A); + xorbuf(A, in, AES_BLOCK_SIZE); + XMEMCPY(out, A, AES_BLOCK_SIZE); + + AesCcmCtrInc(B, lenSz); + inSz -= AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + } + if (inSz > 0) { + wc_AesEncrypt(aes, B, A); + xorbuf(A, in, inSz); + XMEMCPY(out, A, inSz); + } + + ForceZero(A, AES_BLOCK_SIZE); + ForceZero(B, AES_BLOCK_SIZE); + + return 0; +} + +#ifdef HAVE_AES_DECRYPT +/* Software AES - CCM Decrypt */ +int wc_AesCcmDecrypt(Aes* aes, byte* out, const byte* in, word32 inSz, + const byte* nonce, word32 nonceSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) +{ + byte A[AES_BLOCK_SIZE]; + byte B[AES_BLOCK_SIZE]; + byte* o; + byte lenSz; + word32 i, oSz; + int result = 0; + byte mask = 0xFF; + const word32 wordSz = (word32)sizeof(word32); + + /* sanity check on arguments */ + if (aes == NULL || out == NULL || in == NULL || nonce == NULL + || authTag == NULL || nonceSz < 7 || nonceSz > 13 || + authTagSz > AES_BLOCK_SIZE) + return BAD_FUNC_ARG; + + o = out; + oSz = inSz; + XMEMCPY(B+1, nonce, nonceSz); + lenSz = AES_BLOCK_SIZE - 1 - (byte)nonceSz; + + B[0] = lenSz - 1; + for (i = 0; i < lenSz; i++) + B[AES_BLOCK_SIZE - 1 - i] = 0; + B[15] = 1; + + while (oSz >= AES_BLOCK_SIZE) { + wc_AesEncrypt(aes, B, A); + xorbuf(A, in, AES_BLOCK_SIZE); + XMEMCPY(o, A, AES_BLOCK_SIZE); + + AesCcmCtrInc(B, lenSz); + oSz -= AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; + o += AES_BLOCK_SIZE; + } + if (inSz > 0) { + wc_AesEncrypt(aes, B, A); + xorbuf(A, in, oSz); + XMEMCPY(o, A, oSz); + } + + for (i = 0; i < lenSz; i++) + B[AES_BLOCK_SIZE - 1 - i] = 0; + wc_AesEncrypt(aes, B, A); + + o = out; + oSz = inSz; + + B[0] = (authInSz > 0 ? 64 : 0) + + (8 * (((byte)authTagSz - 2) / 2)) + + (lenSz - 1); + for (i = 0; i < lenSz; i++) { + if (mask && i >= wordSz) + mask = 0x00; + B[AES_BLOCK_SIZE - 1 - i] = (inSz >> ((8 * i) & mask)) & mask; + } + + wc_AesEncrypt(aes, B, A); + + if (authInSz > 0) + roll_auth(aes, authIn, authInSz, A); + if (inSz > 0) + roll_x(aes, o, oSz, A); + + B[0] = lenSz - 1; + for (i = 0; i < lenSz; i++) + B[AES_BLOCK_SIZE - 1 - i] = 0; + wc_AesEncrypt(aes, B, B); + xorbuf(A, B, authTagSz); + + if (ConstantCompare(A, authTag, authTagSz) != 0) { + /* If the authTag check fails, don't keep the decrypted data. + * Unfortunately, you need the decrypted data to calculate the + * check value. */ + XMEMSET(out, 0, inSz); + result = AES_CCM_AUTH_E; + } + + ForceZero(A, AES_BLOCK_SIZE); + ForceZero(B, AES_BLOCK_SIZE); + o = NULL; + + return result; +} + +#endif /* HAVE_AES_DECRYPT */ +#endif /* software CCM */ + +/* abstract functions that call lower level AESCCM functions */ +#ifndef WC_NO_RNG + +int wc_AesCcmSetNonce(Aes* aes, const byte* nonce, word32 nonceSz) +{ + int ret = 0; + + if (aes == NULL || nonce == NULL || + nonceSz < CCM_NONCE_MIN_SZ || nonceSz > CCM_NONCE_MAX_SZ) { + + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + XMEMCPY(aes->reg, nonce, nonceSz); + aes->nonceSz = nonceSz; + + /* Invocation counter should be 2^61 */ + aes->invokeCtr[0] = 0; + aes->invokeCtr[1] = 0xE0000000; + } + + return ret; +} + + +int wc_AesCcmEncrypt_ex(Aes* aes, byte* out, const byte* in, word32 sz, + byte* ivOut, word32 ivOutSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) +{ + int ret = 0; + + if (aes == NULL || out == NULL || + (in == NULL && sz != 0) || + ivOut == NULL || + (authIn == NULL && authInSz != 0) || + (ivOutSz != aes->nonceSz)) { + + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + aes->invokeCtr[0]++; + if (aes->invokeCtr[0] == 0) { + aes->invokeCtr[1]++; + if (aes->invokeCtr[1] == 0) + ret = AES_CCM_OVERFLOW_E; + } + } + + if (ret == 0) { + ret = wc_AesCcmEncrypt(aes, out, in, sz, + (byte*)aes->reg, aes->nonceSz, + authTag, authTagSz, + authIn, authInSz); + if (ret == 0) { + XMEMCPY(ivOut, aes->reg, aes->nonceSz); + IncCtr((byte*)aes->reg, aes->nonceSz); + } + } + + return ret; +} + +#endif /* WC_NO_RNG */ + +#endif /* HAVE_AESCCM */ + + +/* Initialize Aes for use with async hardware */ +int wc_AesInit(Aes* aes, void* heap, int devId) +{ + int ret = 0; + + if (aes == NULL) + return BAD_FUNC_ARG; + + aes->heap = heap; + +#ifdef WOLF_CRYPTO_CB + aes->devId = devId; + aes->devCtx = NULL; +#else + (void)devId; +#endif +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES) + ret = wolfAsync_DevCtxInit(&aes->asyncDev, WOLFSSL_ASYNC_MARKER_AES, + aes->heap, devId); +#endif /* WOLFSSL_ASYNC_CRYPT */ + +#ifdef WOLFSSL_AFALG + aes->alFd = -1; + aes->rdFd = -1; +#endif +#if defined(WOLFSSL_DEVCRYPTO) && \ + (defined(WOLFSSL_DEVCRYPTO_AES) || defined(WOLFSSL_DEVCRYPTO_CBC)) + aes->ctx.cfd = -1; +#endif +#if defined(WOLFSSL_CRYPTOCELL) && defined(WOLFSSL_CRYPTOCELL_AES) + XMEMSET(&aes->ctx, 0, sizeof(aes->ctx)); +#endif + return ret; +} + +#ifdef HAVE_PKCS11 +int wc_AesInit_Id(Aes* aes, unsigned char* id, int len, void* heap, int devId) +{ + int ret = 0; + + if (aes == NULL) + ret = BAD_FUNC_ARG; + if (ret == 0 && (len < 0 || len > AES_MAX_ID_LEN)) + ret = BUFFER_E; + + if (ret == 0) + ret = wc_AesInit(aes, heap, devId); + if (ret == 0) { + XMEMCPY(aes->id, id, len); + aes->idLen = len; + } + + return ret; +} +#endif + +/* Free Aes from use with async hardware */ +void wc_AesFree(Aes* aes) +{ + if (aes == NULL) + return; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES) + wolfAsync_DevCtxFree(&aes->asyncDev, WOLFSSL_ASYNC_MARKER_AES); +#endif /* WOLFSSL_ASYNC_CRYPT */ +#if defined(WOLFSSL_AFALG) || defined(WOLFSSL_AFALG_XILINX_AES) + if (aes->rdFd > 0) { /* negative is error case */ + close(aes->rdFd); + } + if (aes->alFd > 0) { + close(aes->alFd); + } +#endif /* WOLFSSL_AFALG */ +#if defined(WOLFSSL_DEVCRYPTO) && \ + (defined(WOLFSSL_DEVCRYPTO_AES) || defined(WOLFSSL_DEVCRYPTO_CBC)) + wc_DevCryptoFree(&aes->ctx); +#endif +#if defined(WOLF_CRYPTO_CB) || (defined(WOLFSSL_DEVCRYPTO) && \ + (defined(WOLFSSL_DEVCRYPTO_AES) || defined(WOLFSSL_DEVCRYPTO_CBC))) + ForceZero((byte*)aes->devKey, AES_MAX_KEY_SIZE/WOLFSSL_BIT_SIZE); +#endif +} + + +int wc_AesGetKeySize(Aes* aes, word32* keySize) +{ + int ret = 0; + + if (aes == NULL || keySize == NULL) { + return BAD_FUNC_ARG; + } +#if defined(WOLFSSL_CRYPTOCELL) && defined(WOLFSSL_CRYPTOCELL_AES) + *keySize = aes->ctx.key.keySize; + return ret; +#endif + switch (aes->rounds) { +#ifdef WOLFSSL_AES_128 + case 10: + *keySize = 16; + break; +#endif +#ifdef WOLFSSL_AES_192 + case 12: + *keySize = 24; + break; +#endif +#ifdef WOLFSSL_AES_256 + case 14: + *keySize = 32; + break; +#endif + default: + *keySize = 0; + ret = BAD_FUNC_ARG; + } + + return ret; +} + +#endif /* !WOLFSSL_TI_CRYPT */ + +#ifdef HAVE_AES_ECB +#if defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_AES) + /* implemented in wolfcrypt/src/port/caam/caam_aes.c */ + +#elif defined(WOLFSSL_AFALG) + /* implemented in wolfcrypt/src/port/af_alg/afalg_aes.c */ + +#elif defined(WOLFSSL_DEVCRYPTO_AES) + /* implemented in wolfcrypt/src/port/devcrypt/devcrypto_aes.c */ + +#else + +/* Software AES - ECB */ +int wc_AesEcbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + word32 blocks = sz / AES_BLOCK_SIZE; + + if ((in == NULL) || (out == NULL) || (aes == NULL)) + return BAD_FUNC_ARG; + while (blocks>0) { + wc_AesEncryptDirect(aes, out, in); + out += AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; + sz -= AES_BLOCK_SIZE; + blocks--; + } + return 0; +} + + +int wc_AesEcbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + word32 blocks = sz / AES_BLOCK_SIZE; + + if ((in == NULL) || (out == NULL) || (aes == NULL)) + return BAD_FUNC_ARG; + while (blocks>0) { + wc_AesDecryptDirect(aes, out, in); + out += AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; + sz -= AES_BLOCK_SIZE; + blocks--; + } + return 0; +} +#endif +#endif /* HAVE_AES_ECB */ + +#ifdef WOLFSSL_AES_CFB +/* CFB 128 + * + * aes structure holding key to use for encryption + * out buffer to hold result of encryption (must be at least as large as input + * buffer) + * in buffer to encrypt + * sz size of input buffer + * + * returns 0 on success and negative error values on failure + */ +/* Software AES - CFB Encrypt */ +int wc_AesCfbEncrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + byte* tmp = NULL; + byte* reg = NULL; + + WOLFSSL_ENTER("wc_AesCfbEncrypt"); + + if (aes == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + + if (aes->left && sz) { + reg = (byte*)aes->reg + AES_BLOCK_SIZE - aes->left; + } + + /* consume any unused bytes left in aes->tmp */ + tmp = (byte*)aes->tmp + AES_BLOCK_SIZE - aes->left; + while (aes->left && sz) { + *(out++) = *(reg++) = *(in++) ^ *(tmp++); + aes->left--; + sz--; + } + + while (sz >= AES_BLOCK_SIZE) { + wc_AesEncryptDirect(aes, out, (byte*)aes->reg); + xorbuf(out, in, AES_BLOCK_SIZE); + XMEMCPY(aes->reg, out, AES_BLOCK_SIZE); + out += AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; + sz -= AES_BLOCK_SIZE; + aes->left = 0; + } + + /* encrypt left over data */ + if (sz) { + wc_AesEncryptDirect(aes, (byte*)aes->tmp, (byte*)aes->reg); + aes->left = AES_BLOCK_SIZE; + tmp = (byte*)aes->tmp; + reg = (byte*)aes->reg; + + while (sz--) { + *(out++) = *(reg++) = *(in++) ^ *(tmp++); + aes->left--; + } + } + + return 0; +} + + +#ifdef HAVE_AES_DECRYPT +/* CFB 128 + * + * aes structure holding key to use for decryption + * out buffer to hold result of decryption (must be at least as large as input + * buffer) + * in buffer to decrypt + * sz size of input buffer + * + * returns 0 on success and negative error values on failure + */ +/* Software AES - CFB Decrypt */ +int wc_AesCfbDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) +{ + byte* tmp; + + WOLFSSL_ENTER("wc_AesCfbDecrypt"); + + if (aes == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + + /* check if more input needs copied over to aes->reg */ + if (aes->left && sz) { + int size = min(aes->left, sz); + XMEMCPY((byte*)aes->reg + AES_BLOCK_SIZE - aes->left, in, size); + } + + /* consume any unused bytes left in aes->tmp */ + tmp = (byte*)aes->tmp + AES_BLOCK_SIZE - aes->left; + while (aes->left && sz) { + *(out++) = *(in++) ^ *(tmp++); + aes->left--; + sz--; + } + + while (sz > AES_BLOCK_SIZE) { + wc_AesEncryptDirect(aes, out, (byte*)aes->reg); + xorbuf(out, in, AES_BLOCK_SIZE); + XMEMCPY(aes->reg, in, AES_BLOCK_SIZE); + out += AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; + sz -= AES_BLOCK_SIZE; + aes->left = 0; + } + + /* decrypt left over data */ + if (sz) { + wc_AesEncryptDirect(aes, (byte*)aes->tmp, (byte*)aes->reg); + XMEMCPY(aes->reg, in, sz); + aes->left = AES_BLOCK_SIZE; + tmp = (byte*)aes->tmp; + + while (sz--) { + *(out++) = *(in++) ^ *(tmp++); + aes->left--; + } + } + + return 0; +} +#endif /* HAVE_AES_DECRYPT */ +#endif /* WOLFSSL_AES_CFB */ + + +#ifdef HAVE_AES_KEYWRAP + +/* Initialize key wrap counter with value */ +static WC_INLINE void InitKeyWrapCounter(byte* inOutCtr, word32 value) +{ + int i; + word32 bytes; + + bytes = sizeof(word32); + for (i = 0; i < (int)sizeof(word32); i++) { + inOutCtr[i+sizeof(word32)] = (value >> ((bytes - 1) * 8)) & 0xFF; + bytes--; + } +} + +/* Increment key wrap counter */ +static WC_INLINE void IncrementKeyWrapCounter(byte* inOutCtr) +{ + int i; + + /* in network byte order so start at end and work back */ + for (i = KEYWRAP_BLOCK_SIZE - 1; i >= 0; i--) { + if (++inOutCtr[i]) /* we're done unless we overflow */ + return; + } +} + +/* Decrement key wrap counter */ +static WC_INLINE void DecrementKeyWrapCounter(byte* inOutCtr) +{ + int i; + + for (i = KEYWRAP_BLOCK_SIZE - 1; i >= 0; i--) { + if (--inOutCtr[i] != 0xFF) /* we're done unless we underflow */ + return; + } +} + +/* perform AES key wrap (RFC3394), return out sz on success, negative on err */ +int wc_AesKeyWrap(const byte* key, word32 keySz, const byte* in, word32 inSz, + byte* out, word32 outSz, const byte* iv) +{ + Aes aes; + byte* r; + word32 i; + int ret, j; + + byte t[KEYWRAP_BLOCK_SIZE]; + byte tmp[AES_BLOCK_SIZE]; + + /* n must be at least 2, output size is n + 8 bytes */ + if (key == NULL || in == NULL || inSz < 2 || + out == NULL || outSz < (inSz + KEYWRAP_BLOCK_SIZE)) + return BAD_FUNC_ARG; + + /* input must be multiple of 64-bits */ + if (inSz % KEYWRAP_BLOCK_SIZE != 0) + return BAD_FUNC_ARG; + + /* user IV is optional */ + if (iv == NULL) { + XMEMSET(tmp, 0xA6, KEYWRAP_BLOCK_SIZE); + } else { + XMEMCPY(tmp, iv, KEYWRAP_BLOCK_SIZE); + } + + r = out + 8; + XMEMCPY(r, in, inSz); + XMEMSET(t, 0, sizeof(t)); + + ret = wc_AesInit(&aes, NULL, INVALID_DEVID); + if (ret != 0) + return ret; + + ret = wc_AesSetKey(&aes, key, keySz, NULL, AES_ENCRYPTION); + if (ret != 0) + return ret; + + for (j = 0; j <= 5; j++) { + for (i = 1; i <= inSz / KEYWRAP_BLOCK_SIZE; i++) { + + /* load R[i] */ + XMEMCPY(tmp + KEYWRAP_BLOCK_SIZE, r, KEYWRAP_BLOCK_SIZE); + + wc_AesEncryptDirect(&aes, tmp, tmp); + + /* calculate new A */ + IncrementKeyWrapCounter(t); + xorbuf(tmp, t, KEYWRAP_BLOCK_SIZE); + + /* save R[i] */ + XMEMCPY(r, tmp + KEYWRAP_BLOCK_SIZE, KEYWRAP_BLOCK_SIZE); + r += KEYWRAP_BLOCK_SIZE; + } + r = out + KEYWRAP_BLOCK_SIZE; + } + + /* C[0] = A */ + XMEMCPY(out, tmp, KEYWRAP_BLOCK_SIZE); + + wc_AesFree(&aes); + + return inSz + KEYWRAP_BLOCK_SIZE; +} + +int wc_AesKeyUnWrap(const byte* key, word32 keySz, const byte* in, word32 inSz, + byte* out, word32 outSz, const byte* iv) +{ + Aes aes; + byte* r; + word32 i, n; + int ret, j; + + byte t[KEYWRAP_BLOCK_SIZE]; + byte tmp[AES_BLOCK_SIZE]; + + const byte* expIv; + const byte defaultIV[] = { + 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6, 0xA6 + }; + + (void)iv; + + if (key == NULL || in == NULL || inSz < 3 || + out == NULL || outSz < (inSz - KEYWRAP_BLOCK_SIZE)) + return BAD_FUNC_ARG; + + /* input must be multiple of 64-bits */ + if (inSz % KEYWRAP_BLOCK_SIZE != 0) + return BAD_FUNC_ARG; + + /* user IV optional */ + if (iv != NULL) { + expIv = iv; + } else { + expIv = defaultIV; + } + + /* A = C[0], R[i] = C[i] */ + XMEMCPY(tmp, in, KEYWRAP_BLOCK_SIZE); + XMEMCPY(out, in + KEYWRAP_BLOCK_SIZE, inSz - KEYWRAP_BLOCK_SIZE); + XMEMSET(t, 0, sizeof(t)); + + ret = wc_AesInit(&aes, NULL, INVALID_DEVID); + if (ret != 0) + return ret; + + ret = wc_AesSetKey(&aes, key, keySz, NULL, AES_DECRYPTION); + if (ret != 0) + return ret; + + /* initialize counter to 6n */ + n = (inSz - 1) / KEYWRAP_BLOCK_SIZE; + InitKeyWrapCounter(t, 6 * n); + + for (j = 5; j >= 0; j--) { + for (i = n; i >= 1; i--) { + + /* calculate A */ + xorbuf(tmp, t, KEYWRAP_BLOCK_SIZE); + DecrementKeyWrapCounter(t); + + /* load R[i], starting at end of R */ + r = out + ((i - 1) * KEYWRAP_BLOCK_SIZE); + XMEMCPY(tmp + KEYWRAP_BLOCK_SIZE, r, KEYWRAP_BLOCK_SIZE); + wc_AesDecryptDirect(&aes, tmp, tmp); + + /* save R[i] */ + XMEMCPY(r, tmp + KEYWRAP_BLOCK_SIZE, KEYWRAP_BLOCK_SIZE); + } + } + + wc_AesFree(&aes); + + /* verify IV */ + if (XMEMCMP(tmp, expIv, KEYWRAP_BLOCK_SIZE) != 0) + return BAD_KEYWRAP_IV_E; + + return inSz - KEYWRAP_BLOCK_SIZE; +} + +#endif /* HAVE_AES_KEYWRAP */ + +#ifdef WOLFSSL_AES_XTS + +/* Galios Field to use */ +#define GF_XTS 0x87 + +/* This is to help with setting keys to correct encrypt or decrypt type. + * + * tweak AES key for tweak in XTS + * aes AES key for encrypt/decrypt process + * key buffer holding aes key | tweak key + * len length of key buffer in bytes. Should be twice that of key size. i.e. + * 32 for a 16 byte key. + * dir direction, either AES_ENCRYPTION or AES_DECRYPTION + * heap heap hint to use for memory. Can be NULL + * devId id to use with async crypto. Can be 0 + * + * Note: is up to user to call wc_AesFree on tweak and aes key when done. + * + * return 0 on success + */ +int wc_AesXtsSetKey(XtsAes* aes, const byte* key, word32 len, int dir, + void* heap, int devId) +{ + word32 keySz; + int ret = 0; + + if (aes == NULL || key == NULL) { + return BAD_FUNC_ARG; + } + + if ((ret = wc_AesInit(&aes->tweak, heap, devId)) != 0) { + return ret; + } + if ((ret = wc_AesInit(&aes->aes, heap, devId)) != 0) { + return ret; + } + + keySz = len/2; + if (keySz != 16 && keySz != 32) { + WOLFSSL_MSG("Unsupported key size"); + return WC_KEY_SIZE_E; + } + + if ((ret = wc_AesSetKey(&aes->aes, key, keySz, NULL, dir)) == 0) { + ret = wc_AesSetKey(&aes->tweak, key + keySz, keySz, NULL, + AES_ENCRYPTION); + if (ret != 0) { + wc_AesFree(&aes->aes); + } + } + + return ret; +} + + +/* This is used to free up resources used by Aes structs + * + * aes AES keys to free + * + * return 0 on success + */ +int wc_AesXtsFree(XtsAes* aes) +{ + if (aes != NULL) { + wc_AesFree(&aes->aes); + wc_AesFree(&aes->tweak); + } + + return 0; +} + + +/* Same process as wc_AesXtsEncrypt but uses a word64 type as the tweak value + * instead of a byte array. This just converts the word64 to a byte array and + * calls wc_AesXtsEncrypt. + * + * aes AES keys to use for block encrypt/decrypt + * out output buffer to hold cipher text + * in input plain text buffer to encrypt + * sz size of both out and in buffers + * sector value to use for tweak + * + * returns 0 on success + */ +int wc_AesXtsEncryptSector(XtsAes* aes, byte* out, const byte* in, + word32 sz, word64 sector) +{ + byte* pt; + byte i[AES_BLOCK_SIZE]; + + XMEMSET(i, 0, AES_BLOCK_SIZE); +#ifdef BIG_ENDIAN_ORDER + sector = ByteReverseWord64(sector); +#endif + pt = (byte*)§or; + XMEMCPY(i, pt, sizeof(word64)); + + return wc_AesXtsEncrypt(aes, out, in, sz, (const byte*)i, AES_BLOCK_SIZE); +} + + +/* Same process as wc_AesXtsDecrypt but uses a word64 type as the tweak value + * instead of a byte array. This just converts the word64 to a byte array. + * + * aes AES keys to use for block encrypt/decrypt + * out output buffer to hold plain text + * in input cipher text buffer to encrypt + * sz size of both out and in buffers + * sector value to use for tweak + * + * returns 0 on success + */ +int wc_AesXtsDecryptSector(XtsAes* aes, byte* out, const byte* in, word32 sz, + word64 sector) +{ + byte* pt; + byte i[AES_BLOCK_SIZE]; + + XMEMSET(i, 0, AES_BLOCK_SIZE); +#ifdef BIG_ENDIAN_ORDER + sector = ByteReverseWord64(sector); +#endif + pt = (byte*)§or; + XMEMCPY(i, pt, sizeof(word64)); + + return wc_AesXtsDecrypt(aes, out, in, sz, (const byte*)i, AES_BLOCK_SIZE); +} + +#ifdef HAVE_AES_ECB +/* helper function for encrypting / decrypting full buffer at once */ +static int _AesXtsHelper(Aes* aes, byte* out, const byte* in, word32 sz, int dir) +{ + word32 outSz = sz; + word32 totalSz = (sz / AES_BLOCK_SIZE) * AES_BLOCK_SIZE; /* total bytes */ + byte* pt = out; + + outSz -= AES_BLOCK_SIZE; + + while (outSz > 0) { + word32 j; + byte carry = 0; + + /* multiply by shift left and propagate carry */ + for (j = 0; j < AES_BLOCK_SIZE && outSz > 0; j++, outSz--) { + byte tmpC; + + tmpC = (pt[j] >> 7) & 0x01; + pt[j+AES_BLOCK_SIZE] = ((pt[j] << 1) + carry) & 0xFF; + carry = tmpC; + } + if (carry) { + pt[AES_BLOCK_SIZE] ^= GF_XTS; + } + + pt += AES_BLOCK_SIZE; + } + + xorbuf(out, in, totalSz); + if (dir == AES_ENCRYPTION) { + return wc_AesEcbEncrypt(aes, out, out, totalSz); + } + else { + return wc_AesEcbDecrypt(aes, out, out, totalSz); + } +} +#endif /* HAVE_AES_ECB */ + + +/* AES with XTS mode. (XTS) XEX encryption with Tweak and cipher text Stealing. + * + * xaes AES keys to use for block encrypt/decrypt + * out output buffer to hold cipher text + * in input plain text buffer to encrypt + * sz size of both out and in buffers + * i value to use for tweak + * iSz size of i buffer, should always be AES_BLOCK_SIZE but having this input + * adds a sanity check on how the user calls the function. + * + * returns 0 on success + */ +/* Software AES - XTS Encrypt */ +int wc_AesXtsEncrypt(XtsAes* xaes, byte* out, const byte* in, word32 sz, + const byte* i, word32 iSz) +{ + int ret = 0; + word32 blocks = (sz / AES_BLOCK_SIZE); + Aes *aes, *tweak; + + if (xaes == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + + aes = &xaes->aes; + tweak = &xaes->tweak; + + if (iSz < AES_BLOCK_SIZE) { + return BAD_FUNC_ARG; + } + + if (blocks > 0) { + byte tmp[AES_BLOCK_SIZE]; + + XMEMSET(tmp, 0, AES_BLOCK_SIZE); /* set to 0's in case of improper AES + * key setup passed to encrypt direct*/ + + wc_AesEncryptDirect(tweak, tmp, i); + + #ifdef HAVE_AES_ECB + /* encrypt all of buffer at once when possible */ + if (in != out) { /* can not handle inline */ + XMEMCPY(out, tmp, AES_BLOCK_SIZE); + if ((ret = _AesXtsHelper(aes, out, in, sz, AES_ENCRYPTION)) != 0) { + return ret; + } + } + #endif + + while (blocks > 0) { + word32 j; + byte carry = 0; + byte buf[AES_BLOCK_SIZE]; + + #ifdef HAVE_AES_ECB + if (in == out) { /* check for if inline */ + #endif + XMEMCPY(buf, in, AES_BLOCK_SIZE); + xorbuf(buf, tmp, AES_BLOCK_SIZE); + wc_AesEncryptDirect(aes, out, buf); + #ifdef HAVE_AES_ECB + } + #endif + xorbuf(out, tmp, AES_BLOCK_SIZE); + + /* multiply by shift left and propagate carry */ + for (j = 0; j < AES_BLOCK_SIZE; j++) { + byte tmpC; + + tmpC = (tmp[j] >> 7) & 0x01; + tmp[j] = ((tmp[j] << 1) + carry) & 0xFF; + carry = tmpC; + } + if (carry) { + tmp[0] ^= GF_XTS; + } + + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + sz -= AES_BLOCK_SIZE; + blocks--; + } + + /* stealing operation of XTS to handle left overs */ + if (sz > 0) { + byte buf[AES_BLOCK_SIZE]; + + XMEMCPY(buf, out - AES_BLOCK_SIZE, AES_BLOCK_SIZE); + if (sz >= AES_BLOCK_SIZE) { /* extra sanity check before copy */ + return BUFFER_E; + } + XMEMCPY(out, buf, sz); + XMEMCPY(buf, in, sz); + + xorbuf(buf, tmp, AES_BLOCK_SIZE); + wc_AesEncryptDirect(aes, out - AES_BLOCK_SIZE, buf); + xorbuf(out - AES_BLOCK_SIZE, tmp, AES_BLOCK_SIZE); + } + } + else { + WOLFSSL_MSG("Plain text input too small for encryption"); + return BAD_FUNC_ARG; + } + + return ret; +} + + +/* Same process as encryption but Aes key is AES_DECRYPTION type. + * + * xaes AES keys to use for block encrypt/decrypt + * out output buffer to hold plain text + * in input cipher text buffer to decrypt + * sz size of both out and in buffers + * i value to use for tweak + * iSz size of i buffer, should always be AES_BLOCK_SIZE but having this input + * adds a sanity check on how the user calls the function. + * + * returns 0 on success + */ +/* Software AES - XTS Decrypt */ +int wc_AesXtsDecrypt(XtsAes* xaes, byte* out, const byte* in, word32 sz, + const byte* i, word32 iSz) +{ + int ret = 0; + word32 blocks = (sz / AES_BLOCK_SIZE); + Aes *aes, *tweak; + + if (xaes == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + + aes = &xaes->aes; + tweak = &xaes->tweak; + + if (iSz < AES_BLOCK_SIZE) { + return BAD_FUNC_ARG; + } + + if (blocks > 0) { + word32 j; + byte carry = 0; + byte tmp[AES_BLOCK_SIZE]; + byte stl = (sz % AES_BLOCK_SIZE); + + XMEMSET(tmp, 0, AES_BLOCK_SIZE); /* set to 0's in case of improper AES + * key setup passed to decrypt direct*/ + + wc_AesEncryptDirect(tweak, tmp, i); + + /* if Stealing then break out of loop one block early to handle special + * case */ + if (stl > 0) { + blocks--; + } + + #ifdef HAVE_AES_ECB + /* decrypt all of buffer at once when possible */ + if (in != out) { /* can not handle inline */ + XMEMCPY(out, tmp, AES_BLOCK_SIZE); + if ((ret = _AesXtsHelper(aes, out, in, sz, AES_DECRYPTION)) != 0) { + return ret; + } + } + #endif + + while (blocks > 0) { + byte buf[AES_BLOCK_SIZE]; + + #ifdef HAVE_AES_ECB + if (in == out) { /* check for if inline */ + #endif + XMEMCPY(buf, in, AES_BLOCK_SIZE); + xorbuf(buf, tmp, AES_BLOCK_SIZE); + wc_AesDecryptDirect(aes, out, buf); + #ifdef HAVE_AES_ECB + } + #endif + xorbuf(out, tmp, AES_BLOCK_SIZE); + + /* multiply by shift left and propagate carry */ + for (j = 0; j < AES_BLOCK_SIZE; j++) { + byte tmpC; + + tmpC = (tmp[j] >> 7) & 0x01; + tmp[j] = ((tmp[j] << 1) + carry) & 0xFF; + carry = tmpC; + } + if (carry) { + tmp[0] ^= GF_XTS; + } + carry = 0; + + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + sz -= AES_BLOCK_SIZE; + blocks--; + } + + /* stealing operation of XTS to handle left overs */ + if (sz > 0) { + byte buf[AES_BLOCK_SIZE]; + byte tmp2[AES_BLOCK_SIZE]; + + /* multiply by shift left and propagate carry */ + for (j = 0; j < AES_BLOCK_SIZE; j++) { + byte tmpC; + + tmpC = (tmp[j] >> 7) & 0x01; + tmp2[j] = ((tmp[j] << 1) + carry) & 0xFF; + carry = tmpC; + } + if (carry) { + tmp2[0] ^= GF_XTS; + } + + XMEMCPY(buf, in, AES_BLOCK_SIZE); + xorbuf(buf, tmp2, AES_BLOCK_SIZE); + wc_AesDecryptDirect(aes, out, buf); + xorbuf(out, tmp2, AES_BLOCK_SIZE); + + /* tmp2 holds partial | last */ + XMEMCPY(tmp2, out, AES_BLOCK_SIZE); + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; + sz -= AES_BLOCK_SIZE; + + /* Make buffer with end of cipher text | last */ + XMEMCPY(buf, tmp2, AES_BLOCK_SIZE); + if (sz >= AES_BLOCK_SIZE) { /* extra sanity check before copy */ + return BUFFER_E; + } + XMEMCPY(buf, in, sz); + XMEMCPY(out, tmp2, sz); + + xorbuf(buf, tmp, AES_BLOCK_SIZE); + wc_AesDecryptDirect(aes, tmp2, buf); + xorbuf(tmp2, tmp, AES_BLOCK_SIZE); + XMEMCPY(out - AES_BLOCK_SIZE, tmp2, AES_BLOCK_SIZE); + } + } + else { + WOLFSSL_MSG("Plain text input too small for encryption"); + return BAD_FUNC_ARG; + } + + return ret; +} + +#endif /* WOLFSSL_AES_XTS */ + +#endif /* HAVE_FIPS */ +#endif /* !NO_AES */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/aes_asm.S b/beken_os/beken378/func/wolfssl/wolfcrypt/src/aes_asm.S new file mode 100755 index 0000000..1ddae68 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/aes_asm.S @@ -0,0 +1,1338 @@ +/* aes_asm.S + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +/* This file is in at&t asm syntax, see .asm for intel syntax */ + +/* See Intel® Advanced Encryption Standard (AES) Instructions Set White Paper + * by Intel Mobility Group, Israel Development Center, Israel Shay Gueron + */ + + +/* +AES_CBC_encrypt (const unsigned char *in, + unsigned char *out, + unsigned char ivec[16], + unsigned long length, + const unsigned char *KS, + int nr) +*/ +#ifndef __APPLE__ +.globl AES_CBC_encrypt +AES_CBC_encrypt: +#else +.globl _AES_CBC_encrypt +_AES_CBC_encrypt: +#endif +# parameter 1: %rdi +# parameter 2: %rsi +# parameter 3: %rdx +# parameter 4: %rcx +# parameter 5: %r8 +# parameter 6: %r9d +movq %rcx, %r10 +shrq $4, %rcx +shlq $60, %r10 +je NO_PARTS +addq $1, %rcx +NO_PARTS: +subq $16, %rsi +movdqa (%rdx), %xmm1 +LOOP: +pxor (%rdi), %xmm1 +pxor (%r8), %xmm1 +addq $16,%rsi +addq $16,%rdi +cmpl $12, %r9d +aesenc 16(%r8),%xmm1 +aesenc 32(%r8),%xmm1 +aesenc 48(%r8),%xmm1 +aesenc 64(%r8),%xmm1 +aesenc 80(%r8),%xmm1 +aesenc 96(%r8),%xmm1 +aesenc 112(%r8),%xmm1 +aesenc 128(%r8),%xmm1 +aesenc 144(%r8),%xmm1 +movdqa 160(%r8),%xmm2 +jb LAST +cmpl $14, %r9d + +aesenc 160(%r8),%xmm1 +aesenc 176(%r8),%xmm1 +movdqa 192(%r8),%xmm2 +jb LAST +aesenc 192(%r8),%xmm1 +aesenc 208(%r8),%xmm1 +movdqa 224(%r8),%xmm2 +LAST: +decq %rcx +aesenclast %xmm2,%xmm1 +movdqu %xmm1,(%rsi) +jne LOOP +ret + + +#if defined(WOLFSSL_AESNI_BY4) + +/* +AES_CBC_decrypt_by4 (const unsigned char *in, + unsigned char *out, + unsigned char ivec[16], + unsigned long length, + const unsigned char *KS, + int nr) +*/ +#ifndef __APPLE__ +.globl AES_CBC_decrypt_by4 +AES_CBC_decrypt_by4: +#else +.globl _AES_CBC_decrypt_by4 +_AES_CBC_decrypt_by4: +#endif +# parameter 1: %rdi +# parameter 2: %rsi +# parameter 3: %rdx +# parameter 4: %rcx +# parameter 5: %r8 +# parameter 6: %r9d + + movq %rcx, %r10 + shrq $4, %rcx + shlq $60, %r10 + je DNO_PARTS_4 + addq $1, %rcx +DNO_PARTS_4: + movq %rcx, %r10 + shlq $62, %r10 + shrq $62, %r10 + shrq $2, %rcx + movdqu (%rdx),%xmm5 + je DREMAINDER_4 + subq $64, %rsi +DLOOP_4: + movdqu (%rdi), %xmm1 + movdqu 16(%rdi), %xmm2 + movdqu 32(%rdi), %xmm3 + movdqu 48(%rdi), %xmm4 + movdqa %xmm1, %xmm6 + movdqa %xmm2, %xmm7 + movdqa %xmm3, %xmm8 + movdqa %xmm4, %xmm15 + movdqa (%r8), %xmm9 + movdqa 16(%r8), %xmm10 + movdqa 32(%r8), %xmm11 + movdqa 48(%r8), %xmm12 + pxor %xmm9, %xmm1 + pxor %xmm9, %xmm2 + pxor %xmm9, %xmm3 + pxor %xmm9, %xmm4 + aesdec %xmm10, %xmm1 + aesdec %xmm10, %xmm2 + aesdec %xmm10, %xmm3 + aesdec %xmm10, %xmm4 + aesdec %xmm11, %xmm1 + aesdec %xmm11, %xmm2 + aesdec %xmm11, %xmm3 + aesdec %xmm11, %xmm4 + aesdec %xmm12, %xmm1 + aesdec %xmm12, %xmm2 + aesdec %xmm12, %xmm3 + aesdec %xmm12, %xmm4 + movdqa 64(%r8), %xmm9 + movdqa 80(%r8), %xmm10 + movdqa 96(%r8), %xmm11 + movdqa 112(%r8), %xmm12 + aesdec %xmm9, %xmm1 + aesdec %xmm9, %xmm2 + aesdec %xmm9, %xmm3 + aesdec %xmm9, %xmm4 + aesdec %xmm10, %xmm1 + aesdec %xmm10, %xmm2 + aesdec %xmm10, %xmm3 + aesdec %xmm10, %xmm4 + aesdec %xmm11, %xmm1 + aesdec %xmm11, %xmm2 + aesdec %xmm11, %xmm3 + aesdec %xmm11, %xmm4 + aesdec %xmm12, %xmm1 + aesdec %xmm12, %xmm2 + aesdec %xmm12, %xmm3 + aesdec %xmm12, %xmm4 + movdqa 128(%r8), %xmm9 + movdqa 144(%r8), %xmm10 + movdqa 160(%r8), %xmm11 + cmpl $12, %r9d + aesdec %xmm9, %xmm1 + aesdec %xmm9, %xmm2 + aesdec %xmm9, %xmm3 + aesdec %xmm9, %xmm4 + aesdec %xmm10, %xmm1 + aesdec %xmm10, %xmm2 + aesdec %xmm10, %xmm3 + aesdec %xmm10, %xmm4 + jb DLAST_4 + movdqa 160(%r8), %xmm9 + movdqa 176(%r8), %xmm10 + movdqa 192(%r8), %xmm11 + cmpl $14, %r9d + aesdec %xmm9, %xmm1 + aesdec %xmm9, %xmm2 + aesdec %xmm9, %xmm3 + aesdec %xmm9, %xmm4 + aesdec %xmm10, %xmm1 + aesdec %xmm10, %xmm2 + aesdec %xmm10, %xmm3 + aesdec %xmm10, %xmm4 + jb DLAST_4 + movdqa 192(%r8), %xmm9 + movdqa 208(%r8), %xmm10 + movdqa 224(%r8), %xmm11 + aesdec %xmm9, %xmm1 + aesdec %xmm9, %xmm2 + aesdec %xmm9, %xmm3 + aesdec %xmm9, %xmm4 + aesdec %xmm10, %xmm1 + aesdec %xmm10, %xmm2 + aesdec %xmm10, %xmm3 + aesdec %xmm10, %xmm4 +DLAST_4: + addq $64, %rdi + addq $64, %rsi + decq %rcx + aesdeclast %xmm11, %xmm1 + aesdeclast %xmm11, %xmm2 + aesdeclast %xmm11, %xmm3 + aesdeclast %xmm11, %xmm4 + pxor %xmm5, %xmm1 + pxor %xmm6, %xmm2 + pxor %xmm7, %xmm3 + pxor %xmm8, %xmm4 + movdqu %xmm1, (%rsi) + movdqu %xmm2, 16(%rsi) + movdqu %xmm3, 32(%rsi) + movdqu %xmm4, 48(%rsi) + movdqa %xmm15,%xmm5 + jne DLOOP_4 + addq $64, %rsi +DREMAINDER_4: + cmpq $0, %r10 + je DEND_4 +DLOOP_4_2: + movdqu (%rdi), %xmm1 + movdqa %xmm1, %xmm15 + addq $16, %rdi + pxor (%r8), %xmm1 + movdqu 160(%r8), %xmm2 + cmpl $12, %r9d + aesdec 16(%r8), %xmm1 + aesdec 32(%r8), %xmm1 + aesdec 48(%r8), %xmm1 + aesdec 64(%r8), %xmm1 + aesdec 80(%r8), %xmm1 + aesdec 96(%r8), %xmm1 + aesdec 112(%r8), %xmm1 + aesdec 128(%r8), %xmm1 + aesdec 144(%r8), %xmm1 + jb DLAST_4_2 + movdqu 192(%r8), %xmm2 + cmpl $14, %r9d + aesdec 160(%r8), %xmm1 + aesdec 176(%r8), %xmm1 + jb DLAST_4_2 + movdqu 224(%r8), %xmm2 + aesdec 192(%r8), %xmm1 + aesdec 208(%r8), %xmm1 +DLAST_4_2: + aesdeclast %xmm2, %xmm1 + pxor %xmm5, %xmm1 + movdqa %xmm15, %xmm5 + movdqu %xmm1, (%rsi) + addq $16, %rsi + decq %r10 + jne DLOOP_4_2 +DEND_4: + ret + +#elif defined(WOLFSSL_AESNI_BY6) + +/* +AES_CBC_decrypt_by6 (const unsigned char *in, + unsigned char *out, + unsigned char ivec[16], + unsigned long length, + const unsigned char *KS, + int nr) +*/ +#ifndef __APPLE__ +.globl AES_CBC_decrypt_by6 +AES_CBC_decrypt_by6: +#else +.globl _AES_CBC_decrypt_by6 +_AES_CBC_decrypt_by6: +#endif +# parameter 1: %rdi - in +# parameter 2: %rsi - out +# parameter 3: %rdx - ivec +# parameter 4: %rcx - length +# parameter 5: %r8 - KS +# parameter 6: %r9d - nr + + movq %rcx, %r10 + shrq $4, %rcx + shlq $60, %r10 + je DNO_PARTS_6 + addq $1, %rcx +DNO_PARTS_6: + movq %rax, %r12 + movq %rdx, %r13 + movq %rbx, %r14 + movq $0, %rdx + movq %rcx, %rax + movq $6, %rbx + div %rbx + movq %rax, %rcx + movq %rdx, %r10 + movq %r12, %rax + movq %r13, %rdx + movq %r14, %rbx + cmpq $0, %rcx + movdqu (%rdx), %xmm7 + je DREMAINDER_6 + subq $96, %rsi +DLOOP_6: + movdqu (%rdi), %xmm1 + movdqu 16(%rdi), %xmm2 + movdqu 32(%rdi), %xmm3 + movdqu 48(%rdi), %xmm4 + movdqu 64(%rdi), %xmm5 + movdqu 80(%rdi), %xmm6 + movdqa (%r8), %xmm8 + movdqa 16(%r8), %xmm9 + movdqa 32(%r8), %xmm10 + movdqa 48(%r8), %xmm11 + pxor %xmm8, %xmm1 + pxor %xmm8, %xmm2 + pxor %xmm8, %xmm3 + pxor %xmm8, %xmm4 + pxor %xmm8, %xmm5 + pxor %xmm8, %xmm6 + aesdec %xmm9, %xmm1 + aesdec %xmm9, %xmm2 + aesdec %xmm9, %xmm3 + aesdec %xmm9, %xmm4 + aesdec %xmm9, %xmm5 + aesdec %xmm9, %xmm6 + aesdec %xmm10, %xmm1 + aesdec %xmm10, %xmm2 + aesdec %xmm10, %xmm3 + aesdec %xmm10, %xmm4 + aesdec %xmm10, %xmm5 + aesdec %xmm10, %xmm6 + aesdec %xmm11, %xmm1 + aesdec %xmm11, %xmm2 + aesdec %xmm11, %xmm3 + aesdec %xmm11, %xmm4 + aesdec %xmm11, %xmm5 + aesdec %xmm11, %xmm6 + movdqa 64(%r8), %xmm8 + movdqa 80(%r8), %xmm9 + movdqa 96(%r8), %xmm10 + movdqa 112(%r8), %xmm11 + aesdec %xmm8, %xmm1 + aesdec %xmm8, %xmm2 + aesdec %xmm8, %xmm3 + aesdec %xmm8, %xmm4 + aesdec %xmm8, %xmm5 + aesdec %xmm8, %xmm6 + aesdec %xmm9, %xmm1 + aesdec %xmm9, %xmm2 + aesdec %xmm9, %xmm3 + aesdec %xmm9, %xmm4 + aesdec %xmm9, %xmm5 + aesdec %xmm9, %xmm6 + aesdec %xmm10, %xmm1 + aesdec %xmm10, %xmm2 + aesdec %xmm10, %xmm3 + aesdec %xmm10, %xmm4 + aesdec %xmm10, %xmm5 + aesdec %xmm10, %xmm6 + aesdec %xmm11, %xmm1 + aesdec %xmm11, %xmm2 + aesdec %xmm11, %xmm3 + aesdec %xmm11, %xmm4 + aesdec %xmm11, %xmm5 + aesdec %xmm11, %xmm6 + movdqa 128(%r8), %xmm8 + movdqa 144(%r8), %xmm9 + movdqa 160(%r8), %xmm10 + cmpl $12, %r9d + aesdec %xmm8, %xmm1 + aesdec %xmm8, %xmm2 + aesdec %xmm8, %xmm3 + aesdec %xmm8, %xmm4 + aesdec %xmm8, %xmm5 + aesdec %xmm8, %xmm6 + aesdec %xmm9, %xmm1 + aesdec %xmm9, %xmm2 + aesdec %xmm9, %xmm3 + aesdec %xmm9, %xmm4 + aesdec %xmm9, %xmm5 + aesdec %xmm9, %xmm6 + jb DLAST_6 + movdqa 160(%r8), %xmm8 + movdqa 176(%r8), %xmm9 + movdqa 192(%r8), %xmm10 + cmpl $14, %r9d + aesdec %xmm8, %xmm1 + aesdec %xmm8, %xmm2 + aesdec %xmm8, %xmm3 + aesdec %xmm8, %xmm4 + aesdec %xmm8, %xmm5 + aesdec %xmm8, %xmm6 + aesdec %xmm9, %xmm1 + aesdec %xmm9, %xmm2 + aesdec %xmm9, %xmm3 + aesdec %xmm9, %xmm4 + aesdec %xmm9, %xmm5 + aesdec %xmm9, %xmm6 + jb DLAST_6 + movdqa 192(%r8), %xmm8 + movdqa 208(%r8), %xmm9 + movdqa 224(%r8), %xmm10 + aesdec %xmm8, %xmm1 + aesdec %xmm8, %xmm2 + aesdec %xmm8, %xmm3 + aesdec %xmm8, %xmm4 + aesdec %xmm8, %xmm5 + aesdec %xmm8, %xmm6 + aesdec %xmm9, %xmm1 + aesdec %xmm9, %xmm2 + aesdec %xmm9, %xmm3 + aesdec %xmm9, %xmm4 + aesdec %xmm9, %xmm5 + aesdec %xmm9, %xmm6 +DLAST_6: + addq $96, %rsi + aesdeclast %xmm10, %xmm1 + aesdeclast %xmm10, %xmm2 + aesdeclast %xmm10, %xmm3 + aesdeclast %xmm10, %xmm4 + aesdeclast %xmm10, %xmm5 + aesdeclast %xmm10, %xmm6 + movdqu (%rdi), %xmm8 + movdqu 16(%rdi), %xmm9 + movdqu 32(%rdi), %xmm10 + movdqu 48(%rdi), %xmm11 + movdqu 64(%rdi), %xmm12 + movdqu 80(%rdi), %xmm13 + pxor %xmm7, %xmm1 + pxor %xmm8, %xmm2 + pxor %xmm9, %xmm3 + pxor %xmm10, %xmm4 + pxor %xmm11, %xmm5 + pxor %xmm12, %xmm6 + movdqu %xmm13, %xmm7 + movdqu %xmm1, (%rsi) + movdqu %xmm2, 16(%rsi) + movdqu %xmm3, 32(%rsi) + movdqu %xmm4, 48(%rsi) + movdqu %xmm5, 64(%rsi) + movdqu %xmm6, 80(%rsi) + addq $96, %rdi + decq %rcx + jne DLOOP_6 + addq $96, %rsi +DREMAINDER_6: + cmpq $0, %r10 + je DEND_6 +DLOOP_6_2: + movdqu (%rdi), %xmm1 + movdqa %xmm1, %xmm10 + addq $16, %rdi + pxor (%r8), %xmm1 + movdqu 160(%r8), %xmm2 + cmpl $12, %r9d + aesdec 16(%r8), %xmm1 + aesdec 32(%r8), %xmm1 + aesdec 48(%r8), %xmm1 + aesdec 64(%r8), %xmm1 + aesdec 80(%r8), %xmm1 + aesdec 96(%r8), %xmm1 + aesdec 112(%r8), %xmm1 + aesdec 128(%r8), %xmm1 + aesdec 144(%r8), %xmm1 + jb DLAST_6_2 + movdqu 192(%r8), %xmm2 + cmpl $14, %r9d + aesdec 160(%r8), %xmm1 + aesdec 176(%r8), %xmm1 + jb DLAST_6_2 + movdqu 224(%r8), %xmm2 + aesdec 192(%r8), %xmm1 + aesdec 208(%r8), %xmm1 +DLAST_6_2: + aesdeclast %xmm2, %xmm1 + pxor %xmm7, %xmm1 + movdqa %xmm10, %xmm7 + movdqu %xmm1, (%rsi) + addq $16, %rsi + decq %r10 + jne DLOOP_6_2 +DEND_6: + ret + +#else /* WOLFSSL_AESNI_BYx */ + +/* +AES_CBC_decrypt_by8 (const unsigned char *in, + unsigned char *out, + unsigned char ivec[16], + unsigned long length, + const unsigned char *KS, + int nr) +*/ +#ifndef __APPLE__ +.globl AES_CBC_decrypt_by8 +AES_CBC_decrypt_by8: +#else +.globl _AES_CBC_decrypt_by8 +_AES_CBC_decrypt_by8: +#endif +# parameter 1: %rdi - in +# parameter 2: %rsi - out +# parameter 3: %rdx - ivec +# parameter 4: %rcx - length +# parameter 5: %r8 - KS +# parameter 6: %r9d - nr + + movq %rcx, %r10 + shrq $4, %rcx + shlq $60, %r10 + je DNO_PARTS_8 + addq $1, %rcx +DNO_PARTS_8: + movq %rcx, %r10 + shlq $61, %r10 + shrq $61, %r10 + shrq $3, %rcx + movdqu (%rdx), %xmm9 + je DREMAINDER_8 + subq $128, %rsi +DLOOP_8: + movdqu (%rdi), %xmm1 + movdqu 16(%rdi), %xmm2 + movdqu 32(%rdi), %xmm3 + movdqu 48(%rdi), %xmm4 + movdqu 64(%rdi), %xmm5 + movdqu 80(%rdi), %xmm6 + movdqu 96(%rdi), %xmm7 + movdqu 112(%rdi), %xmm8 + movdqa (%r8), %xmm10 + movdqa 16(%r8), %xmm11 + movdqa 32(%r8), %xmm12 + movdqa 48(%r8), %xmm13 + pxor %xmm10, %xmm1 + pxor %xmm10, %xmm2 + pxor %xmm10, %xmm3 + pxor %xmm10, %xmm4 + pxor %xmm10, %xmm5 + pxor %xmm10, %xmm6 + pxor %xmm10, %xmm7 + pxor %xmm10, %xmm8 + aesdec %xmm11, %xmm1 + aesdec %xmm11, %xmm2 + aesdec %xmm11, %xmm3 + aesdec %xmm11, %xmm4 + aesdec %xmm11, %xmm5 + aesdec %xmm11, %xmm6 + aesdec %xmm11, %xmm7 + aesdec %xmm11, %xmm8 + aesdec %xmm12, %xmm1 + aesdec %xmm12, %xmm2 + aesdec %xmm12, %xmm3 + aesdec %xmm12, %xmm4 + aesdec %xmm12, %xmm5 + aesdec %xmm12, %xmm6 + aesdec %xmm12, %xmm7 + aesdec %xmm12, %xmm8 + aesdec %xmm13, %xmm1 + aesdec %xmm13, %xmm2 + aesdec %xmm13, %xmm3 + aesdec %xmm13, %xmm4 + aesdec %xmm13, %xmm5 + aesdec %xmm13, %xmm6 + aesdec %xmm13, %xmm7 + aesdec %xmm13, %xmm8 + movdqa 64(%r8), %xmm10 + movdqa 80(%r8), %xmm11 + movdqa 96(%r8), %xmm12 + movdqa 112(%r8), %xmm13 + aesdec %xmm10, %xmm1 + aesdec %xmm10, %xmm2 + aesdec %xmm10, %xmm3 + aesdec %xmm10, %xmm4 + aesdec %xmm10, %xmm5 + aesdec %xmm10, %xmm6 + aesdec %xmm10, %xmm7 + aesdec %xmm10, %xmm8 + aesdec %xmm11, %xmm1 + aesdec %xmm11, %xmm2 + aesdec %xmm11, %xmm3 + aesdec %xmm11, %xmm4 + aesdec %xmm11, %xmm5 + aesdec %xmm11, %xmm6 + aesdec %xmm11, %xmm7 + aesdec %xmm11, %xmm8 + aesdec %xmm12, %xmm1 + aesdec %xmm12, %xmm2 + aesdec %xmm12, %xmm3 + aesdec %xmm12, %xmm4 + aesdec %xmm12, %xmm5 + aesdec %xmm12, %xmm6 + aesdec %xmm12, %xmm7 + aesdec %xmm12, %xmm8 + aesdec %xmm13, %xmm1 + aesdec %xmm13, %xmm2 + aesdec %xmm13, %xmm3 + aesdec %xmm13, %xmm4 + aesdec %xmm13, %xmm5 + aesdec %xmm13, %xmm6 + aesdec %xmm13, %xmm7 + aesdec %xmm13, %xmm8 + movdqa 128(%r8), %xmm10 + movdqa 144(%r8), %xmm11 + movdqa 160(%r8), %xmm12 + cmpl $12, %r9d + aesdec %xmm10, %xmm1 + aesdec %xmm10, %xmm2 + aesdec %xmm10, %xmm3 + aesdec %xmm10, %xmm4 + aesdec %xmm10, %xmm5 + aesdec %xmm10, %xmm6 + aesdec %xmm10, %xmm7 + aesdec %xmm10, %xmm8 + aesdec %xmm11, %xmm1 + aesdec %xmm11, %xmm2 + aesdec %xmm11, %xmm3 + aesdec %xmm11, %xmm4 + aesdec %xmm11, %xmm5 + aesdec %xmm11, %xmm6 + aesdec %xmm11, %xmm7 + aesdec %xmm11, %xmm8 + jb DLAST_8 + movdqa 160(%r8), %xmm10 + movdqa 176(%r8), %xmm11 + movdqa 192(%r8), %xmm12 + cmpl $14, %r9d + aesdec %xmm10, %xmm1 + aesdec %xmm10, %xmm2 + aesdec %xmm10, %xmm3 + aesdec %xmm10, %xmm4 + aesdec %xmm10, %xmm5 + aesdec %xmm10, %xmm6 + aesdec %xmm10, %xmm7 + aesdec %xmm10, %xmm8 + aesdec %xmm11, %xmm1 + aesdec %xmm11, %xmm2 + aesdec %xmm11, %xmm3 + aesdec %xmm11, %xmm4 + aesdec %xmm11, %xmm5 + aesdec %xmm11, %xmm6 + aesdec %xmm11, %xmm7 + aesdec %xmm11, %xmm8 + jb DLAST_8 + movdqa 192(%r8), %xmm10 + movdqa 208(%r8), %xmm11 + movdqa 224(%r8), %xmm12 + aesdec %xmm10, %xmm1 + aesdec %xmm10, %xmm2 + aesdec %xmm10, %xmm3 + aesdec %xmm10, %xmm4 + aesdec %xmm10, %xmm5 + aesdec %xmm10, %xmm6 + aesdec %xmm10, %xmm7 + aesdec %xmm10, %xmm8 + aesdec %xmm11, %xmm1 + aesdec %xmm11, %xmm2 + aesdec %xmm11, %xmm3 + aesdec %xmm11, %xmm4 + aesdec %xmm11, %xmm5 + aesdec %xmm11, %xmm6 + aesdec %xmm11, %xmm7 + aesdec %xmm11, %xmm8 +DLAST_8: + addq $128, %rsi + aesdeclast %xmm12, %xmm1 + aesdeclast %xmm12, %xmm2 + aesdeclast %xmm12, %xmm3 + aesdeclast %xmm12, %xmm4 + aesdeclast %xmm12, %xmm5 + aesdeclast %xmm12, %xmm6 + aesdeclast %xmm12, %xmm7 + aesdeclast %xmm12, %xmm8 + movdqu (%rdi), %xmm10 + movdqu 16(%rdi), %xmm11 + movdqu 32(%rdi), %xmm12 + movdqu 48(%rdi), %xmm13 + pxor %xmm9, %xmm1 + pxor %xmm10, %xmm2 + pxor %xmm11, %xmm3 + pxor %xmm12, %xmm4 + pxor %xmm13, %xmm5 + movdqu 64(%rdi), %xmm10 + movdqu 80(%rdi), %xmm11 + movdqu 96(%rdi), %xmm12 + movdqu 112(%rdi), %xmm9 + pxor %xmm10, %xmm6 + pxor %xmm11, %xmm7 + pxor %xmm12, %xmm8 + movdqu %xmm1, (%rsi) + movdqu %xmm2, 16(%rsi) + movdqu %xmm3, 32(%rsi) + movdqu %xmm4, 48(%rsi) + movdqu %xmm5, 64(%rsi) + movdqu %xmm6, 80(%rsi) + movdqu %xmm7, 96(%rsi) + movdqu %xmm8, 112(%rsi) + addq $128, %rdi + decq %rcx + jne DLOOP_8 + addq $128, %rsi +DREMAINDER_8: + cmpq $0, %r10 + je DEND_8 +DLOOP_8_2: + movdqu (%rdi), %xmm1 + movdqa %xmm1, %xmm10 + addq $16, %rdi + pxor (%r8), %xmm1 + movdqu 160(%r8), %xmm2 + cmpl $12, %r9d + aesdec 16(%r8), %xmm1 + aesdec 32(%r8), %xmm1 + aesdec 48(%r8), %xmm1 + aesdec 64(%r8), %xmm1 + aesdec 80(%r8), %xmm1 + aesdec 96(%r8), %xmm1 + aesdec 112(%r8), %xmm1 + aesdec 128(%r8), %xmm1 + aesdec 144(%r8), %xmm1 + jb DLAST_8_2 + movdqu 192(%r8), %xmm2 + cmpl $14, %r9d + aesdec 160(%r8), %xmm1 + aesdec 176(%r8), %xmm1 + jb DLAST_8_2 + movdqu 224(%r8), %xmm2 + aesdec 192(%r8), %xmm1 + aesdec 208(%r8), %xmm1 +DLAST_8_2: + aesdeclast %xmm2, %xmm1 + pxor %xmm9, %xmm1 + movdqa %xmm10, %xmm9 + movdqu %xmm1, (%rsi) + addq $16, %rsi + decq %r10 + jne DLOOP_8_2 +DEND_8: + ret + +#endif /* WOLFSSL_AESNI_BYx */ + + +/* +AES_ECB_encrypt (const unsigned char *in, + unsigned char *out, + unsigned long length, + const unsigned char *KS, + int nr) +*/ +#ifndef __APPLE__ +.globl AES_ECB_encrypt +AES_ECB_encrypt: +#else +.globl _AES_ECB_encrypt +_AES_ECB_encrypt: +#endif +# parameter 1: %rdi +# parameter 2: %rsi +# parameter 3: %rdx +# parameter 4: %rcx +# parameter 5: %r8d + movq %rdx, %r10 + shrq $4, %rdx + shlq $60, %r10 + je EECB_NO_PARTS_4 + addq $1, %rdx +EECB_NO_PARTS_4: + movq %rdx, %r10 + shlq $62, %r10 + shrq $62, %r10 + shrq $2, %rdx + je EECB_REMAINDER_4 + subq $64, %rsi +EECB_LOOP_4: + movdqu (%rdi), %xmm1 + movdqu 16(%rdi), %xmm2 + movdqu 32(%rdi), %xmm3 + movdqu 48(%rdi), %xmm4 + movdqa (%rcx), %xmm9 + movdqa 16(%rcx), %xmm10 + movdqa 32(%rcx), %xmm11 + movdqa 48(%rcx), %xmm12 + pxor %xmm9, %xmm1 + pxor %xmm9, %xmm2 + pxor %xmm9, %xmm3 + pxor %xmm9, %xmm4 + aesenc %xmm10, %xmm1 + aesenc %xmm10, %xmm2 + aesenc %xmm10, %xmm3 + aesenc %xmm10, %xmm4 + aesenc %xmm11, %xmm1 + aesenc %xmm11, %xmm2 + aesenc %xmm11, %xmm3 + aesenc %xmm11, %xmm4 + aesenc %xmm12, %xmm1 + aesenc %xmm12, %xmm2 + aesenc %xmm12, %xmm3 + aesenc %xmm12, %xmm4 + movdqa 64(%rcx), %xmm9 + movdqa 80(%rcx), %xmm10 + movdqa 96(%rcx), %xmm11 + movdqa 112(%rcx), %xmm12 + aesenc %xmm9, %xmm1 + aesenc %xmm9, %xmm2 + aesenc %xmm9, %xmm3 + aesenc %xmm9, %xmm4 + aesenc %xmm10, %xmm1 + aesenc %xmm10, %xmm2 + aesenc %xmm10, %xmm3 + aesenc %xmm10, %xmm4 + aesenc %xmm11, %xmm1 + aesenc %xmm11, %xmm2 + aesenc %xmm11, %xmm3 + aesenc %xmm11, %xmm4 + aesenc %xmm12, %xmm1 + aesenc %xmm12, %xmm2 + aesenc %xmm12, %xmm3 + aesenc %xmm12, %xmm4 + movdqa 128(%rcx), %xmm9 + movdqa 144(%rcx), %xmm10 + movdqa 160(%rcx), %xmm11 + cmpl $12, %r8d + aesenc %xmm9, %xmm1 + aesenc %xmm9, %xmm2 + aesenc %xmm9, %xmm3 + aesenc %xmm9, %xmm4 + aesenc %xmm10, %xmm1 + aesenc %xmm10, %xmm2 + aesenc %xmm10, %xmm3 + aesenc %xmm10, %xmm4 + jb EECB_LAST_4 + movdqa 160(%rcx), %xmm9 + movdqa 176(%rcx), %xmm10 + movdqa 192(%rcx), %xmm11 + cmpl $14, %r8d + aesenc %xmm9, %xmm1 + aesenc %xmm9, %xmm2 + aesenc %xmm9, %xmm3 + aesenc %xmm9, %xmm4 + aesenc %xmm10, %xmm1 + aesenc %xmm10, %xmm2 + aesenc %xmm10, %xmm3 + aesenc %xmm10, %xmm4 + jb EECB_LAST_4 + movdqa 192(%rcx), %xmm9 + movdqa 208(%rcx), %xmm10 + movdqa 224(%rcx), %xmm11 + aesenc %xmm9, %xmm1 + aesenc %xmm9, %xmm2 + aesenc %xmm9, %xmm3 + aesenc %xmm9, %xmm4 + aesenc %xmm10, %xmm1 + aesenc %xmm10, %xmm2 + aesenc %xmm10, %xmm3 + aesenc %xmm10, %xmm4 +EECB_LAST_4: + addq $64, %rdi + addq $64, %rsi + decq %rdx + aesenclast %xmm11, %xmm1 + aesenclast %xmm11, %xmm2 + aesenclast %xmm11, %xmm3 + aesenclast %xmm11, %xmm4 + movdqu %xmm1, (%rsi) + movdqu %xmm2, 16(%rsi) + movdqu %xmm3, 32(%rsi) + movdqu %xmm4, 48(%rsi) + jne EECB_LOOP_4 + addq $64, %rsi +EECB_REMAINDER_4: + cmpq $0, %r10 + je EECB_END_4 +EECB_LOOP_4_2: + movdqu (%rdi), %xmm1 + addq $16, %rdi + pxor (%rcx), %xmm1 + movdqu 160(%rcx), %xmm2 + aesenc 16(%rcx), %xmm1 + aesenc 32(%rcx), %xmm1 + aesenc 48(%rcx), %xmm1 + aesenc 64(%rcx), %xmm1 + aesenc 80(%rcx), %xmm1 + aesenc 96(%rcx), %xmm1 + aesenc 112(%rcx), %xmm1 + aesenc 128(%rcx), %xmm1 + aesenc 144(%rcx), %xmm1 + cmpl $12, %r8d + jb EECB_LAST_4_2 + movdqu 192(%rcx), %xmm2 + aesenc 160(%rcx), %xmm1 + aesenc 176(%rcx), %xmm1 + cmpl $14, %r8d + jb EECB_LAST_4_2 + movdqu 224(%rcx), %xmm2 + aesenc 192(%rcx), %xmm1 + aesenc 208(%rcx), %xmm1 +EECB_LAST_4_2: + aesenclast %xmm2, %xmm1 + movdqu %xmm1, (%rsi) + addq $16, %rsi + decq %r10 + jne EECB_LOOP_4_2 +EECB_END_4: + ret + + +/* +AES_ECB_decrypt (const unsigned char *in, + unsigned char *out, + unsigned long length, + const unsigned char *KS, + int nr) +*/ +#ifndef __APPLE__ +.globl AES_ECB_decrypt +AES_ECB_decrypt: +#else +.globl _AES_ECB_decrypt +_AES_ECB_decrypt: +#endif +# parameter 1: %rdi +# parameter 2: %rsi +# parameter 3: %rdx +# parameter 4: %rcx +# parameter 5: %r8d + + movq %rdx, %r10 + shrq $4, %rdx + shlq $60, %r10 + je DECB_NO_PARTS_4 + addq $1, %rdx +DECB_NO_PARTS_4: + movq %rdx, %r10 + shlq $62, %r10 + shrq $62, %r10 + shrq $2, %rdx + je DECB_REMAINDER_4 + subq $64, %rsi +DECB_LOOP_4: + movdqu (%rdi), %xmm1 + movdqu 16(%rdi), %xmm2 + movdqu 32(%rdi), %xmm3 + movdqu 48(%rdi), %xmm4 + movdqa (%rcx), %xmm9 + movdqa 16(%rcx), %xmm10 + movdqa 32(%rcx), %xmm11 + movdqa 48(%rcx), %xmm12 + pxor %xmm9, %xmm1 + pxor %xmm9, %xmm2 + pxor %xmm9, %xmm3 + pxor %xmm9, %xmm4 + aesdec %xmm10, %xmm1 + aesdec %xmm10, %xmm2 + aesdec %xmm10, %xmm3 + aesdec %xmm10, %xmm4 + aesdec %xmm11, %xmm1 + aesdec %xmm11, %xmm2 + aesdec %xmm11, %xmm3 + aesdec %xmm11, %xmm4 + aesdec %xmm12, %xmm1 + aesdec %xmm12, %xmm2 + aesdec %xmm12, %xmm3 + aesdec %xmm12, %xmm4 + movdqa 64(%rcx), %xmm9 + movdqa 80(%rcx), %xmm10 + movdqa 96(%rcx), %xmm11 + movdqa 112(%rcx), %xmm12 + aesdec %xmm9, %xmm1 + aesdec %xmm9, %xmm2 + aesdec %xmm9, %xmm3 + aesdec %xmm9, %xmm4 + aesdec %xmm10, %xmm1 + aesdec %xmm10, %xmm2 + aesdec %xmm10, %xmm3 + aesdec %xmm10, %xmm4 + aesdec %xmm11, %xmm1 + aesdec %xmm11, %xmm2 + aesdec %xmm11, %xmm3 + aesdec %xmm11, %xmm4 + aesdec %xmm12, %xmm1 + aesdec %xmm12, %xmm2 + aesdec %xmm12, %xmm3 + aesdec %xmm12, %xmm4 + movdqa 128(%rcx), %xmm9 + movdqa 144(%rcx), %xmm10 + movdqa 160(%rcx), %xmm11 + cmpl $12, %r8d + aesdec %xmm9, %xmm1 + aesdec %xmm9, %xmm2 + aesdec %xmm9, %xmm3 + aesdec %xmm9, %xmm4 + aesdec %xmm10, %xmm1 + aesdec %xmm10, %xmm2 + aesdec %xmm10, %xmm3 + aesdec %xmm10, %xmm4 + jb DECB_LAST_4 + movdqa 160(%rcx), %xmm9 + movdqa 176(%rcx), %xmm10 + movdqa 192(%rcx), %xmm11 + cmpl $14, %r8d + aesdec %xmm9, %xmm1 + aesdec %xmm9, %xmm2 + aesdec %xmm9, %xmm3 + aesdec %xmm9, %xmm4 + aesdec %xmm10, %xmm1 + aesdec %xmm10, %xmm2 + aesdec %xmm10, %xmm3 + aesdec %xmm10, %xmm4 + jb DECB_LAST_4 + movdqa 192(%rcx), %xmm9 + movdqa 208(%rcx), %xmm10 + movdqa 224(%rcx), %xmm11 + aesdec %xmm9, %xmm1 + aesdec %xmm9, %xmm2 + aesdec %xmm9, %xmm3 + aesdec %xmm9, %xmm4 + aesdec %xmm10, %xmm1 + aesdec %xmm10, %xmm2 + aesdec %xmm10, %xmm3 + aesdec %xmm10, %xmm4 +DECB_LAST_4: + addq $64, %rdi + addq $64, %rsi + decq %rdx + aesdeclast %xmm11, %xmm1 + aesdeclast %xmm11, %xmm2 + aesdeclast %xmm11, %xmm3 + aesdeclast %xmm11, %xmm4 + movdqu %xmm1, (%rsi) + movdqu %xmm2, 16(%rsi) + movdqu %xmm3, 32(%rsi) + movdqu %xmm4, 48(%rsi) + jne DECB_LOOP_4 + addq $64, %rsi +DECB_REMAINDER_4: + cmpq $0, %r10 + je DECB_END_4 +DECB_LOOP_4_2: + movdqu (%rdi), %xmm1 + addq $16, %rdi + pxor (%rcx), %xmm1 + movdqu 160(%rcx), %xmm2 + cmpl $12, %r8d + aesdec 16(%rcx), %xmm1 + aesdec 32(%rcx), %xmm1 + aesdec 48(%rcx), %xmm1 + aesdec 64(%rcx), %xmm1 + aesdec 80(%rcx), %xmm1 + aesdec 96(%rcx), %xmm1 + aesdec 112(%rcx), %xmm1 + aesdec 128(%rcx), %xmm1 + aesdec 144(%rcx), %xmm1 + jb DECB_LAST_4_2 + cmpl $14, %r8d + movdqu 192(%rcx), %xmm2 + aesdec 160(%rcx), %xmm1 + aesdec 176(%rcx), %xmm1 + jb DECB_LAST_4_2 + movdqu 224(%rcx), %xmm2 + aesdec 192(%rcx), %xmm1 + aesdec 208(%rcx), %xmm1 +DECB_LAST_4_2: + aesdeclast %xmm2, %xmm1 + movdqu %xmm1, (%rsi) + addq $16, %rsi + decq %r10 + jne DECB_LOOP_4_2 +DECB_END_4: + ret + + + + +/* +void AES_128_Key_Expansion(const unsigned char* userkey, + unsigned char* key_schedule); +*/ +.align 16,0x90 +#ifndef __APPLE__ +.globl AES_128_Key_Expansion +AES_128_Key_Expansion: +#else +.globl _AES_128_Key_Expansion +_AES_128_Key_Expansion: +#endif +# parameter 1: %rdi +# parameter 2: %rsi +movl $10, 240(%rsi) + +movdqu (%rdi), %xmm1 +movdqa %xmm1, (%rsi) + + +ASSISTS: +aeskeygenassist $1, %xmm1, %xmm2 +call PREPARE_ROUNDKEY_128 +movdqa %xmm1, 16(%rsi) +aeskeygenassist $2, %xmm1, %xmm2 +call PREPARE_ROUNDKEY_128 +movdqa %xmm1, 32(%rsi) +aeskeygenassist $4, %xmm1, %xmm2 +call PREPARE_ROUNDKEY_128 +movdqa %xmm1, 48(%rsi) +aeskeygenassist $8, %xmm1, %xmm2 +call PREPARE_ROUNDKEY_128 +movdqa %xmm1, 64(%rsi) +aeskeygenassist $16, %xmm1, %xmm2 +call PREPARE_ROUNDKEY_128 +movdqa %xmm1, 80(%rsi) +aeskeygenassist $32, %xmm1, %xmm2 +call PREPARE_ROUNDKEY_128 +movdqa %xmm1, 96(%rsi) +aeskeygenassist $64, %xmm1, %xmm2 +call PREPARE_ROUNDKEY_128 +movdqa %xmm1, 112(%rsi) +aeskeygenassist $0x80, %xmm1, %xmm2 +call PREPARE_ROUNDKEY_128 +movdqa %xmm1, 128(%rsi) +aeskeygenassist $0x1b, %xmm1, %xmm2 +call PREPARE_ROUNDKEY_128 +movdqa %xmm1, 144(%rsi) +aeskeygenassist $0x36, %xmm1, %xmm2 +call PREPARE_ROUNDKEY_128 +movdqa %xmm1, 160(%rsi) +ret + +PREPARE_ROUNDKEY_128: +pshufd $255, %xmm2, %xmm2 +movdqa %xmm1, %xmm3 +pslldq $4, %xmm3 +pxor %xmm3, %xmm1 +pslldq $4, %xmm3 +pxor %xmm3, %xmm1 +pslldq $4, %xmm3 +pxor %xmm3, %xmm1 +pxor %xmm2, %xmm1 +ret + + +/* +void AES_192_Key_Expansion (const unsigned char *userkey, + unsigned char *key) +*/ +#ifndef __APPLE__ +.globl AES_192_Key_Expansion +AES_192_Key_Expansion: +#else +.globl _AES_192_Key_Expansion +_AES_192_Key_Expansion: +#endif +# parameter 1: %rdi +# parameter 2: %rsi + +movdqu (%rdi), %xmm1 +movq 16(%rdi), %xmm3 +movdqa %xmm1, (%rsi) +movdqa %xmm3, %xmm5 + +aeskeygenassist $0x1, %xmm3, %xmm2 +call PREPARE_ROUNDKEY_192 +shufpd $0, %xmm1, %xmm5 +movdqa %xmm5, 16(%rsi) +movdqa %xmm1, %xmm6 +shufpd $1, %xmm3, %xmm6 +movdqa %xmm6, 32(%rsi) + +aeskeygenassist $0x2, %xmm3, %xmm2 +call PREPARE_ROUNDKEY_192 +movdqa %xmm1, 48(%rsi) +movdqa %xmm3, %xmm5 + +aeskeygenassist $0x4, %xmm3, %xmm2 +call PREPARE_ROUNDKEY_192 +shufpd $0, %xmm1, %xmm5 +movdqa %xmm5, 64(%rsi) +movdqa %xmm1, %xmm6 +shufpd $1, %xmm3, %xmm6 +movdqa %xmm6, 80(%rsi) + +aeskeygenassist $0x8, %xmm3, %xmm2 +call PREPARE_ROUNDKEY_192 +movdqa %xmm1, 96(%rsi) +movdqa %xmm3, %xmm5 + +aeskeygenassist $0x10, %xmm3, %xmm2 +call PREPARE_ROUNDKEY_192 +shufpd $0, %xmm1, %xmm5 +movdqa %xmm5, 112(%rsi) +movdqa %xmm1, %xmm6 +shufpd $1, %xmm3, %xmm6 +movdqa %xmm6, 128(%rsi) + +aeskeygenassist $0x20, %xmm3, %xmm2 +call PREPARE_ROUNDKEY_192 +movdqa %xmm1, 144(%rsi) +movdqa %xmm3, %xmm5 + +aeskeygenassist $0x40, %xmm3, %xmm2 +call PREPARE_ROUNDKEY_192 +shufpd $0, %xmm1, %xmm5 +movdqa %xmm5, 160(%rsi) +movdqa %xmm1, %xmm6 +shufpd $1, %xmm3, %xmm6 +movdqa %xmm6, 176(%rsi) + +aeskeygenassist $0x80, %xmm3, %xmm2 +call PREPARE_ROUNDKEY_192 +movdqa %xmm1, 192(%rsi) +movdqa %xmm3, 208(%rsi) +ret + +PREPARE_ROUNDKEY_192: +pshufd $0x55, %xmm2, %xmm2 +movdqu %xmm1, %xmm4 +pslldq $4, %xmm4 +pxor %xmm4, %xmm1 + +pslldq $4, %xmm4 +pxor %xmm4, %xmm1 +pslldq $4, %xmm4 +pxor %xmm4, %xmm1 +pxor %xmm2, %xmm1 +pshufd $0xff, %xmm1, %xmm2 +movdqu %xmm3, %xmm4 +pslldq $4, %xmm4 +pxor %xmm4, %xmm3 +pxor %xmm2, %xmm3 +ret + + +/* +void AES_256_Key_Expansion (const unsigned char *userkey, + unsigned char *key) +*/ +#ifndef __APPLE__ +.globl AES_256_Key_Expansion +AES_256_Key_Expansion: +#else +.globl _AES_256_Key_Expansion +_AES_256_Key_Expansion: +#endif +# parameter 1: %rdi +# parameter 2: %rsi + +movdqu (%rdi), %xmm1 +movdqu 16(%rdi), %xmm3 +movdqa %xmm1, (%rsi) +movdqa %xmm3, 16(%rsi) + +aeskeygenassist $0x1, %xmm3, %xmm2 +call MAKE_RK256_a +movdqa %xmm1, 32(%rsi) +aeskeygenassist $0x0, %xmm1, %xmm2 +call MAKE_RK256_b +movdqa %xmm3, 48(%rsi) +aeskeygenassist $0x2, %xmm3, %xmm2 +call MAKE_RK256_a +movdqa %xmm1, 64(%rsi) +aeskeygenassist $0x0, %xmm1, %xmm2 +call MAKE_RK256_b +movdqa %xmm3, 80(%rsi) +aeskeygenassist $0x4, %xmm3, %xmm2 +call MAKE_RK256_a +movdqa %xmm1, 96(%rsi) +aeskeygenassist $0x0, %xmm1, %xmm2 +call MAKE_RK256_b +movdqa %xmm3, 112(%rsi) +aeskeygenassist $0x8, %xmm3, %xmm2 +call MAKE_RK256_a +movdqa %xmm1, 128(%rsi) +aeskeygenassist $0x0, %xmm1, %xmm2 +call MAKE_RK256_b +movdqa %xmm3, 144(%rsi) +aeskeygenassist $0x10, %xmm3, %xmm2 +call MAKE_RK256_a +movdqa %xmm1, 160(%rsi) +aeskeygenassist $0x0, %xmm1, %xmm2 +call MAKE_RK256_b +movdqa %xmm3, 176(%rsi) +aeskeygenassist $0x20, %xmm3, %xmm2 +call MAKE_RK256_a +movdqa %xmm1, 192(%rsi) + +aeskeygenassist $0x0, %xmm1, %xmm2 +call MAKE_RK256_b +movdqa %xmm3, 208(%rsi) +aeskeygenassist $0x40, %xmm3, %xmm2 +call MAKE_RK256_a +movdqa %xmm1, 224(%rsi) + +ret + +MAKE_RK256_a: +pshufd $0xff, %xmm2, %xmm2 +movdqa %xmm1, %xmm4 +pslldq $4, %xmm4 +pxor %xmm4, %xmm1 +pslldq $4, %xmm4 +pxor %xmm4, %xmm1 +pslldq $4, %xmm4 +pxor %xmm4, %xmm1 +pxor %xmm2, %xmm1 +ret + +MAKE_RK256_b: +pshufd $0xaa, %xmm2, %xmm2 +movdqa %xmm3, %xmm4 +pslldq $4, %xmm4 +pxor %xmm4, %xmm3 +pslldq $4, %xmm4 +pxor %xmm4, %xmm3 +pslldq $4, %xmm4 +pxor %xmm4, %xmm3 +pxor %xmm2, %xmm3 +ret + +#if defined(__linux__) && defined(__ELF__) + .section .note.GNU-stack,"",%progbits +#endif diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/aes_gcm_asm.S b/beken_os/beken378/func/wolfssl/wolfcrypt/src/aes_gcm_asm.S new file mode 100755 index 0000000..0924cde --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/aes_gcm_asm.S @@ -0,0 +1,8733 @@ +/* aes_gcm_asm + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#ifndef HAVE_INTEL_AVX1 +#define HAVE_INTEL_AVX1 +#endif /* HAVE_INTEL_AVX1 */ +#ifndef HAVE_INTEL_AVX2 +#define HAVE_INTEL_AVX2 +#endif /* HAVE_INTEL_AVX2 */ + +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_aes_gcm_one: +.quad 0x0, 0x1 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_aes_gcm_two: +.quad 0x0, 0x2 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_aes_gcm_three: +.quad 0x0, 0x3 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_aes_gcm_four: +.quad 0x0, 0x4 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_aes_gcm_five: +.quad 0x0, 0x5 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_aes_gcm_six: +.quad 0x0, 0x6 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_aes_gcm_seven: +.quad 0x0, 0x7 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_aes_gcm_eight: +.quad 0x0, 0x8 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_aes_gcm_bswap_epi64: +.quad 0x1020304050607, 0x8090a0b0c0d0e0f +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_aes_gcm_bswap_mask: +.quad 0x8090a0b0c0d0e0f, 0x1020304050607 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_aes_gcm_mod2_128: +.quad 0x1, 0xc200000000000000 +#ifndef __APPLE__ +.text +.globl AES_GCM_encrypt +.type AES_GCM_encrypt,@function +.align 4 +AES_GCM_encrypt: +#else +.section __TEXT,__text +.globl _AES_GCM_encrypt +.p2align 2 +_AES_GCM_encrypt: +#endif /* __APPLE__ */ + pushq %r13 + pushq %r12 + pushq %rbx + pushq %r14 + pushq %r15 + movq %rdx, %r12 + movq %rcx, %rax + movl 48(%rsp), %r11d + movl 56(%rsp), %ebx + movl 64(%rsp), %r14d + movq 72(%rsp), %r15 + movl 80(%rsp), %r10d + subq $0xa0, %rsp + pxor %xmm4, %xmm4 + pxor %xmm6, %xmm6 + cmpl $12, %ebx + movl %ebx, %edx + jne L_AES_GCM_encrypt_iv_not_12 + # # Calculate values when IV is 12 bytes + # Set counter based on IV + movl $0x1000000, %ecx + pinsrq $0x00, (%rax), %xmm4 + pinsrd $2, 8(%rax), %xmm4 + pinsrd $3, %ecx, %xmm4 + # H = Encrypt X(=0) and T = Encrypt counter + movdqa %xmm4, %xmm1 + movdqa (%r15), %xmm5 + pxor %xmm5, %xmm1 + movdqa 16(%r15), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 32(%r15), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 48(%r15), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 64(%r15), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 80(%r15), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 96(%r15), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 112(%r15), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 128(%r15), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 144(%r15), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + cmpl $11, %r10d + movdqa 160(%r15), %xmm7 + jl L_AES_GCM_encrypt_calc_iv_12_last + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 176(%r15), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + cmpl $13, %r10d + movdqa 192(%r15), %xmm7 + jl L_AES_GCM_encrypt_calc_iv_12_last + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 208(%r15), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 224(%r15), %xmm7 +L_AES_GCM_encrypt_calc_iv_12_last: + aesenclast %xmm7, %xmm5 + aesenclast %xmm7, %xmm1 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm5 + movdqa %xmm1, 144(%rsp) + jmp L_AES_GCM_encrypt_iv_done +L_AES_GCM_encrypt_iv_not_12: + # Calculate values when IV is not 12 bytes + # H = Encrypt X(=0) + movdqa (%r15), %xmm5 + aesenc 16(%r15), %xmm5 + aesenc 32(%r15), %xmm5 + aesenc 48(%r15), %xmm5 + aesenc 64(%r15), %xmm5 + aesenc 80(%r15), %xmm5 + aesenc 96(%r15), %xmm5 + aesenc 112(%r15), %xmm5 + aesenc 128(%r15), %xmm5 + aesenc 144(%r15), %xmm5 + cmpl $11, %r10d + movdqa 160(%r15), %xmm9 + jl L_AES_GCM_encrypt_calc_iv_1_aesenc_avx_last + aesenc %xmm9, %xmm5 + aesenc 176(%r15), %xmm5 + cmpl $13, %r10d + movdqa 192(%r15), %xmm9 + jl L_AES_GCM_encrypt_calc_iv_1_aesenc_avx_last + aesenc %xmm9, %xmm5 + aesenc 208(%r15), %xmm5 + movdqa 224(%r15), %xmm9 +L_AES_GCM_encrypt_calc_iv_1_aesenc_avx_last: + aesenclast %xmm9, %xmm5 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm5 + # Calc counter + # Initialization vector + cmpl $0x00, %edx + movq $0x00, %rcx + je L_AES_GCM_encrypt_calc_iv_done + cmpl $16, %edx + jl L_AES_GCM_encrypt_calc_iv_lt16 + andl $0xfffffff0, %edx +L_AES_GCM_encrypt_calc_iv_16_loop: + movdqu (%rax,%rcx,1), %xmm8 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm8 + pxor %xmm8, %xmm4 + pshufd $0x4e, %xmm4, %xmm1 + pshufd $0x4e, %xmm5, %xmm2 + movdqa %xmm5, %xmm3 + movdqa %xmm5, %xmm0 + pclmulqdq $0x11, %xmm4, %xmm3 + pclmulqdq $0x00, %xmm4, %xmm0 + pxor %xmm4, %xmm1 + pxor %xmm5, %xmm2 + pclmulqdq $0x00, %xmm2, %xmm1 + pxor %xmm0, %xmm1 + pxor %xmm3, %xmm1 + movdqa %xmm1, %xmm2 + movdqa %xmm0, %xmm7 + movdqa %xmm3, %xmm4 + pslldq $8, %xmm2 + psrldq $8, %xmm1 + pxor %xmm2, %xmm7 + pxor %xmm1, %xmm4 + movdqa %xmm7, %xmm0 + movdqa %xmm4, %xmm1 + psrld $31, %xmm0 + psrld $31, %xmm1 + pslld $0x01, %xmm7 + pslld $0x01, %xmm4 + movdqa %xmm0, %xmm2 + pslldq $4, %xmm0 + psrldq $12, %xmm2 + pslldq $4, %xmm1 + por %xmm2, %xmm4 + por %xmm0, %xmm7 + por %xmm1, %xmm4 + movdqa %xmm7, %xmm0 + movdqa %xmm7, %xmm1 + movdqa %xmm7, %xmm2 + pslld $31, %xmm0 + pslld $30, %xmm1 + pslld $25, %xmm2 + pxor %xmm1, %xmm0 + pxor %xmm2, %xmm0 + movdqa %xmm0, %xmm1 + psrldq $4, %xmm1 + pslldq $12, %xmm0 + pxor %xmm0, %xmm7 + movdqa %xmm7, %xmm2 + movdqa %xmm7, %xmm3 + movdqa %xmm7, %xmm0 + psrld $0x01, %xmm2 + psrld $2, %xmm3 + psrld $7, %xmm0 + pxor %xmm3, %xmm2 + pxor %xmm0, %xmm2 + pxor %xmm1, %xmm2 + pxor %xmm7, %xmm2 + pxor %xmm2, %xmm4 + addl $16, %ecx + cmpl %edx, %ecx + jl L_AES_GCM_encrypt_calc_iv_16_loop + movl %ebx, %edx + cmpl %edx, %ecx + je L_AES_GCM_encrypt_calc_iv_done +L_AES_GCM_encrypt_calc_iv_lt16: + subq $16, %rsp + pxor %xmm8, %xmm8 + xorl %ebx, %ebx + movdqa %xmm8, (%rsp) +L_AES_GCM_encrypt_calc_iv_loop: + movzbl (%rax,%rcx,1), %r13d + movb %r13b, (%rsp,%rbx,1) + incl %ecx + incl %ebx + cmpl %edx, %ecx + jl L_AES_GCM_encrypt_calc_iv_loop + movdqa (%rsp), %xmm8 + addq $16, %rsp + pshufb L_aes_gcm_bswap_mask(%rip), %xmm8 + pxor %xmm8, %xmm4 + pshufd $0x4e, %xmm4, %xmm1 + pshufd $0x4e, %xmm5, %xmm2 + movdqa %xmm5, %xmm3 + movdqa %xmm5, %xmm0 + pclmulqdq $0x11, %xmm4, %xmm3 + pclmulqdq $0x00, %xmm4, %xmm0 + pxor %xmm4, %xmm1 + pxor %xmm5, %xmm2 + pclmulqdq $0x00, %xmm2, %xmm1 + pxor %xmm0, %xmm1 + pxor %xmm3, %xmm1 + movdqa %xmm1, %xmm2 + movdqa %xmm0, %xmm7 + movdqa %xmm3, %xmm4 + pslldq $8, %xmm2 + psrldq $8, %xmm1 + pxor %xmm2, %xmm7 + pxor %xmm1, %xmm4 + movdqa %xmm7, %xmm0 + movdqa %xmm4, %xmm1 + psrld $31, %xmm0 + psrld $31, %xmm1 + pslld $0x01, %xmm7 + pslld $0x01, %xmm4 + movdqa %xmm0, %xmm2 + pslldq $4, %xmm0 + psrldq $12, %xmm2 + pslldq $4, %xmm1 + por %xmm2, %xmm4 + por %xmm0, %xmm7 + por %xmm1, %xmm4 + movdqa %xmm7, %xmm0 + movdqa %xmm7, %xmm1 + movdqa %xmm7, %xmm2 + pslld $31, %xmm0 + pslld $30, %xmm1 + pslld $25, %xmm2 + pxor %xmm1, %xmm0 + pxor %xmm2, %xmm0 + movdqa %xmm0, %xmm1 + psrldq $4, %xmm1 + pslldq $12, %xmm0 + pxor %xmm0, %xmm7 + movdqa %xmm7, %xmm2 + movdqa %xmm7, %xmm3 + movdqa %xmm7, %xmm0 + psrld $0x01, %xmm2 + psrld $2, %xmm3 + psrld $7, %xmm0 + pxor %xmm3, %xmm2 + pxor %xmm0, %xmm2 + pxor %xmm1, %xmm2 + pxor %xmm7, %xmm2 + pxor %xmm2, %xmm4 +L_AES_GCM_encrypt_calc_iv_done: + # T = Encrypt counter + pxor %xmm0, %xmm0 + shll $3, %edx + pinsrq $0x00, %rdx, %xmm0 + pxor %xmm0, %xmm4 + pshufd $0x4e, %xmm4, %xmm1 + pshufd $0x4e, %xmm5, %xmm2 + movdqa %xmm5, %xmm3 + movdqa %xmm5, %xmm0 + pclmulqdq $0x11, %xmm4, %xmm3 + pclmulqdq $0x00, %xmm4, %xmm0 + pxor %xmm4, %xmm1 + pxor %xmm5, %xmm2 + pclmulqdq $0x00, %xmm2, %xmm1 + pxor %xmm0, %xmm1 + pxor %xmm3, %xmm1 + movdqa %xmm1, %xmm2 + movdqa %xmm0, %xmm7 + movdqa %xmm3, %xmm4 + pslldq $8, %xmm2 + psrldq $8, %xmm1 + pxor %xmm2, %xmm7 + pxor %xmm1, %xmm4 + movdqa %xmm7, %xmm0 + movdqa %xmm4, %xmm1 + psrld $31, %xmm0 + psrld $31, %xmm1 + pslld $0x01, %xmm7 + pslld $0x01, %xmm4 + movdqa %xmm0, %xmm2 + pslldq $4, %xmm0 + psrldq $12, %xmm2 + pslldq $4, %xmm1 + por %xmm2, %xmm4 + por %xmm0, %xmm7 + por %xmm1, %xmm4 + movdqa %xmm7, %xmm0 + movdqa %xmm7, %xmm1 + movdqa %xmm7, %xmm2 + pslld $31, %xmm0 + pslld $30, %xmm1 + pslld $25, %xmm2 + pxor %xmm1, %xmm0 + pxor %xmm2, %xmm0 + movdqa %xmm0, %xmm1 + psrldq $4, %xmm1 + pslldq $12, %xmm0 + pxor %xmm0, %xmm7 + movdqa %xmm7, %xmm2 + movdqa %xmm7, %xmm3 + movdqa %xmm7, %xmm0 + psrld $0x01, %xmm2 + psrld $2, %xmm3 + psrld $7, %xmm0 + pxor %xmm3, %xmm2 + pxor %xmm0, %xmm2 + pxor %xmm1, %xmm2 + pxor %xmm7, %xmm2 + pxor %xmm2, %xmm4 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm4 + # Encrypt counter + movdqa (%r15), %xmm8 + pxor %xmm4, %xmm8 + aesenc 16(%r15), %xmm8 + aesenc 32(%r15), %xmm8 + aesenc 48(%r15), %xmm8 + aesenc 64(%r15), %xmm8 + aesenc 80(%r15), %xmm8 + aesenc 96(%r15), %xmm8 + aesenc 112(%r15), %xmm8 + aesenc 128(%r15), %xmm8 + aesenc 144(%r15), %xmm8 + cmpl $11, %r10d + movdqa 160(%r15), %xmm9 + jl L_AES_GCM_encrypt_calc_iv_2_aesenc_avx_last + aesenc %xmm9, %xmm8 + aesenc 176(%r15), %xmm8 + cmpl $13, %r10d + movdqa 192(%r15), %xmm9 + jl L_AES_GCM_encrypt_calc_iv_2_aesenc_avx_last + aesenc %xmm9, %xmm8 + aesenc 208(%r15), %xmm8 + movdqa 224(%r15), %xmm9 +L_AES_GCM_encrypt_calc_iv_2_aesenc_avx_last: + aesenclast %xmm9, %xmm8 + movdqa %xmm8, 144(%rsp) +L_AES_GCM_encrypt_iv_done: + # Additional authentication data + movl %r11d, %edx + cmpl $0x00, %edx + je L_AES_GCM_encrypt_calc_aad_done + xorl %ecx, %ecx + cmpl $16, %edx + jl L_AES_GCM_encrypt_calc_aad_lt16 + andl $0xfffffff0, %edx +L_AES_GCM_encrypt_calc_aad_16_loop: + movdqu (%r12,%rcx,1), %xmm8 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm8 + pxor %xmm8, %xmm6 + pshufd $0x4e, %xmm6, %xmm1 + pshufd $0x4e, %xmm5, %xmm2 + movdqa %xmm5, %xmm3 + movdqa %xmm5, %xmm0 + pclmulqdq $0x11, %xmm6, %xmm3 + pclmulqdq $0x00, %xmm6, %xmm0 + pxor %xmm6, %xmm1 + pxor %xmm5, %xmm2 + pclmulqdq $0x00, %xmm2, %xmm1 + pxor %xmm0, %xmm1 + pxor %xmm3, %xmm1 + movdqa %xmm1, %xmm2 + movdqa %xmm0, %xmm7 + movdqa %xmm3, %xmm6 + pslldq $8, %xmm2 + psrldq $8, %xmm1 + pxor %xmm2, %xmm7 + pxor %xmm1, %xmm6 + movdqa %xmm7, %xmm0 + movdqa %xmm6, %xmm1 + psrld $31, %xmm0 + psrld $31, %xmm1 + pslld $0x01, %xmm7 + pslld $0x01, %xmm6 + movdqa %xmm0, %xmm2 + pslldq $4, %xmm0 + psrldq $12, %xmm2 + pslldq $4, %xmm1 + por %xmm2, %xmm6 + por %xmm0, %xmm7 + por %xmm1, %xmm6 + movdqa %xmm7, %xmm0 + movdqa %xmm7, %xmm1 + movdqa %xmm7, %xmm2 + pslld $31, %xmm0 + pslld $30, %xmm1 + pslld $25, %xmm2 + pxor %xmm1, %xmm0 + pxor %xmm2, %xmm0 + movdqa %xmm0, %xmm1 + psrldq $4, %xmm1 + pslldq $12, %xmm0 + pxor %xmm0, %xmm7 + movdqa %xmm7, %xmm2 + movdqa %xmm7, %xmm3 + movdqa %xmm7, %xmm0 + psrld $0x01, %xmm2 + psrld $2, %xmm3 + psrld $7, %xmm0 + pxor %xmm3, %xmm2 + pxor %xmm0, %xmm2 + pxor %xmm1, %xmm2 + pxor %xmm7, %xmm2 + pxor %xmm2, %xmm6 + addl $16, %ecx + cmpl %edx, %ecx + jl L_AES_GCM_encrypt_calc_aad_16_loop + movl %r11d, %edx + cmpl %edx, %ecx + je L_AES_GCM_encrypt_calc_aad_done +L_AES_GCM_encrypt_calc_aad_lt16: + subq $16, %rsp + pxor %xmm8, %xmm8 + xorl %ebx, %ebx + movdqa %xmm8, (%rsp) +L_AES_GCM_encrypt_calc_aad_loop: + movzbl (%r12,%rcx,1), %r13d + movb %r13b, (%rsp,%rbx,1) + incl %ecx + incl %ebx + cmpl %edx, %ecx + jl L_AES_GCM_encrypt_calc_aad_loop + movdqa (%rsp), %xmm8 + addq $16, %rsp + pshufb L_aes_gcm_bswap_mask(%rip), %xmm8 + pxor %xmm8, %xmm6 + pshufd $0x4e, %xmm6, %xmm1 + pshufd $0x4e, %xmm5, %xmm2 + movdqa %xmm5, %xmm3 + movdqa %xmm5, %xmm0 + pclmulqdq $0x11, %xmm6, %xmm3 + pclmulqdq $0x00, %xmm6, %xmm0 + pxor %xmm6, %xmm1 + pxor %xmm5, %xmm2 + pclmulqdq $0x00, %xmm2, %xmm1 + pxor %xmm0, %xmm1 + pxor %xmm3, %xmm1 + movdqa %xmm1, %xmm2 + movdqa %xmm0, %xmm7 + movdqa %xmm3, %xmm6 + pslldq $8, %xmm2 + psrldq $8, %xmm1 + pxor %xmm2, %xmm7 + pxor %xmm1, %xmm6 + movdqa %xmm7, %xmm0 + movdqa %xmm6, %xmm1 + psrld $31, %xmm0 + psrld $31, %xmm1 + pslld $0x01, %xmm7 + pslld $0x01, %xmm6 + movdqa %xmm0, %xmm2 + pslldq $4, %xmm0 + psrldq $12, %xmm2 + pslldq $4, %xmm1 + por %xmm2, %xmm6 + por %xmm0, %xmm7 + por %xmm1, %xmm6 + movdqa %xmm7, %xmm0 + movdqa %xmm7, %xmm1 + movdqa %xmm7, %xmm2 + pslld $31, %xmm0 + pslld $30, %xmm1 + pslld $25, %xmm2 + pxor %xmm1, %xmm0 + pxor %xmm2, %xmm0 + movdqa %xmm0, %xmm1 + psrldq $4, %xmm1 + pslldq $12, %xmm0 + pxor %xmm0, %xmm7 + movdqa %xmm7, %xmm2 + movdqa %xmm7, %xmm3 + movdqa %xmm7, %xmm0 + psrld $0x01, %xmm2 + psrld $2, %xmm3 + psrld $7, %xmm0 + pxor %xmm3, %xmm2 + pxor %xmm0, %xmm2 + pxor %xmm1, %xmm2 + pxor %xmm7, %xmm2 + pxor %xmm2, %xmm6 +L_AES_GCM_encrypt_calc_aad_done: + # Calculate counter and H + pshufb L_aes_gcm_bswap_epi64(%rip), %xmm4 + movdqa %xmm5, %xmm9 + paddd L_aes_gcm_one(%rip), %xmm4 + movdqa %xmm5, %xmm8 + movdqa %xmm4, 128(%rsp) + psrlq $63, %xmm9 + psllq $0x01, %xmm8 + pslldq $8, %xmm9 + por %xmm9, %xmm8 + pshufd $0xff, %xmm5, %xmm5 + psrad $31, %xmm5 + pand L_aes_gcm_mod2_128(%rip), %xmm5 + pxor %xmm8, %xmm5 + xorq %rbx, %rbx + cmpl $0x80, %r9d + movl %r9d, %r13d + jl L_AES_GCM_encrypt_done_128 + andl $0xffffff80, %r13d + movdqa %xmm6, %xmm2 + # H ^ 1 + movdqa %xmm5, (%rsp) + # H ^ 2 + pshufd $0x4e, %xmm5, %xmm9 + pshufd $0x4e, %xmm5, %xmm10 + movdqa %xmm5, %xmm11 + movdqa %xmm5, %xmm8 + pclmulqdq $0x11, %xmm5, %xmm11 + pclmulqdq $0x00, %xmm5, %xmm8 + pxor %xmm5, %xmm9 + pxor %xmm5, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm0 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm0 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm0 + movdqa %xmm0, 16(%rsp) + # H ^ 3 + pshufd $0x4e, %xmm5, %xmm9 + pshufd $0x4e, %xmm0, %xmm10 + movdqa %xmm0, %xmm11 + movdqa %xmm0, %xmm8 + pclmulqdq $0x11, %xmm5, %xmm11 + pclmulqdq $0x00, %xmm5, %xmm8 + pxor %xmm5, %xmm9 + pxor %xmm0, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm1 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm1 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm1 + movdqa %xmm1, 32(%rsp) + # H ^ 4 + pshufd $0x4e, %xmm0, %xmm9 + pshufd $0x4e, %xmm0, %xmm10 + movdqa %xmm0, %xmm11 + movdqa %xmm0, %xmm8 + pclmulqdq $0x11, %xmm0, %xmm11 + pclmulqdq $0x00, %xmm0, %xmm8 + pxor %xmm0, %xmm9 + pxor %xmm0, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm3 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm3 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm3 + movdqa %xmm3, 48(%rsp) + # H ^ 5 + pshufd $0x4e, %xmm0, %xmm9 + pshufd $0x4e, %xmm1, %xmm10 + movdqa %xmm1, %xmm11 + movdqa %xmm1, %xmm8 + pclmulqdq $0x11, %xmm0, %xmm11 + pclmulqdq $0x00, %xmm0, %xmm8 + pxor %xmm0, %xmm9 + pxor %xmm1, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm7 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm7 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm7 + movdqa %xmm7, 64(%rsp) + # H ^ 6 + pshufd $0x4e, %xmm1, %xmm9 + pshufd $0x4e, %xmm1, %xmm10 + movdqa %xmm1, %xmm11 + movdqa %xmm1, %xmm8 + pclmulqdq $0x11, %xmm1, %xmm11 + pclmulqdq $0x00, %xmm1, %xmm8 + pxor %xmm1, %xmm9 + pxor %xmm1, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm7 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm7 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm7 + movdqa %xmm7, 80(%rsp) + # H ^ 7 + pshufd $0x4e, %xmm1, %xmm9 + pshufd $0x4e, %xmm3, %xmm10 + movdqa %xmm3, %xmm11 + movdqa %xmm3, %xmm8 + pclmulqdq $0x11, %xmm1, %xmm11 + pclmulqdq $0x00, %xmm1, %xmm8 + pxor %xmm1, %xmm9 + pxor %xmm3, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm7 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm7 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm7 + movdqa %xmm7, 96(%rsp) + # H ^ 8 + pshufd $0x4e, %xmm3, %xmm9 + pshufd $0x4e, %xmm3, %xmm10 + movdqa %xmm3, %xmm11 + movdqa %xmm3, %xmm8 + pclmulqdq $0x11, %xmm3, %xmm11 + pclmulqdq $0x00, %xmm3, %xmm8 + pxor %xmm3, %xmm9 + pxor %xmm3, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm7 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm7 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm7 + movdqa %xmm7, 112(%rsp) + # First 128 bytes of input + movdqa 128(%rsp), %xmm8 + movdqa L_aes_gcm_bswap_epi64(%rip), %xmm1 + movdqa %xmm8, %xmm0 + pshufb %xmm1, %xmm8 + movdqa %xmm0, %xmm9 + paddd L_aes_gcm_one(%rip), %xmm9 + pshufb %xmm1, %xmm9 + movdqa %xmm0, %xmm10 + paddd L_aes_gcm_two(%rip), %xmm10 + pshufb %xmm1, %xmm10 + movdqa %xmm0, %xmm11 + paddd L_aes_gcm_three(%rip), %xmm11 + pshufb %xmm1, %xmm11 + movdqa %xmm0, %xmm12 + paddd L_aes_gcm_four(%rip), %xmm12 + pshufb %xmm1, %xmm12 + movdqa %xmm0, %xmm13 + paddd L_aes_gcm_five(%rip), %xmm13 + pshufb %xmm1, %xmm13 + movdqa %xmm0, %xmm14 + paddd L_aes_gcm_six(%rip), %xmm14 + pshufb %xmm1, %xmm14 + movdqa %xmm0, %xmm15 + paddd L_aes_gcm_seven(%rip), %xmm15 + pshufb %xmm1, %xmm15 + paddd L_aes_gcm_eight(%rip), %xmm0 + movdqa (%r15), %xmm7 + movdqa %xmm0, 128(%rsp) + pxor %xmm7, %xmm8 + pxor %xmm7, %xmm9 + pxor %xmm7, %xmm10 + pxor %xmm7, %xmm11 + pxor %xmm7, %xmm12 + pxor %xmm7, %xmm13 + pxor %xmm7, %xmm14 + pxor %xmm7, %xmm15 + movdqa 16(%r15), %xmm7 + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + movdqa 32(%r15), %xmm7 + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + movdqa 48(%r15), %xmm7 + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + movdqa 64(%r15), %xmm7 + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + movdqa 80(%r15), %xmm7 + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + movdqa 96(%r15), %xmm7 + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + movdqa 112(%r15), %xmm7 + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + movdqa 128(%r15), %xmm7 + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + movdqa 144(%r15), %xmm7 + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + cmpl $11, %r10d + movdqa 160(%r15), %xmm7 + jl L_AES_GCM_encrypt_enc_done + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + movdqa 176(%r15), %xmm7 + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + cmpl $13, %r10d + movdqa 192(%r15), %xmm7 + jl L_AES_GCM_encrypt_enc_done + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + movdqa 208(%r15), %xmm7 + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + movdqa 224(%r15), %xmm7 +L_AES_GCM_encrypt_enc_done: + aesenclast %xmm7, %xmm8 + aesenclast %xmm7, %xmm9 + movdqu (%rdi), %xmm0 + movdqu 16(%rdi), %xmm1 + pxor %xmm0, %xmm8 + pxor %xmm1, %xmm9 + movdqu %xmm8, (%rsi) + movdqu %xmm9, 16(%rsi) + aesenclast %xmm7, %xmm10 + aesenclast %xmm7, %xmm11 + movdqu 32(%rdi), %xmm0 + movdqu 48(%rdi), %xmm1 + pxor %xmm0, %xmm10 + pxor %xmm1, %xmm11 + movdqu %xmm10, 32(%rsi) + movdqu %xmm11, 48(%rsi) + aesenclast %xmm7, %xmm12 + aesenclast %xmm7, %xmm13 + movdqu 64(%rdi), %xmm0 + movdqu 80(%rdi), %xmm1 + pxor %xmm0, %xmm12 + pxor %xmm1, %xmm13 + movdqu %xmm12, 64(%rsi) + movdqu %xmm13, 80(%rsi) + aesenclast %xmm7, %xmm14 + aesenclast %xmm7, %xmm15 + movdqu 96(%rdi), %xmm0 + movdqu 112(%rdi), %xmm1 + pxor %xmm0, %xmm14 + pxor %xmm1, %xmm15 + movdqu %xmm14, 96(%rsi) + movdqu %xmm15, 112(%rsi) + cmpl $0x80, %r13d + movl $0x80, %ebx + jle L_AES_GCM_encrypt_end_128 + # More 128 bytes of input +L_AES_GCM_encrypt_ghash_128: + leaq (%rdi,%rbx,1), %rcx + leaq (%rsi,%rbx,1), %rdx + movdqa 128(%rsp), %xmm8 + movdqa L_aes_gcm_bswap_epi64(%rip), %xmm1 + movdqa %xmm8, %xmm0 + pshufb %xmm1, %xmm8 + movdqa %xmm0, %xmm9 + paddd L_aes_gcm_one(%rip), %xmm9 + pshufb %xmm1, %xmm9 + movdqa %xmm0, %xmm10 + paddd L_aes_gcm_two(%rip), %xmm10 + pshufb %xmm1, %xmm10 + movdqa %xmm0, %xmm11 + paddd L_aes_gcm_three(%rip), %xmm11 + pshufb %xmm1, %xmm11 + movdqa %xmm0, %xmm12 + paddd L_aes_gcm_four(%rip), %xmm12 + pshufb %xmm1, %xmm12 + movdqa %xmm0, %xmm13 + paddd L_aes_gcm_five(%rip), %xmm13 + pshufb %xmm1, %xmm13 + movdqa %xmm0, %xmm14 + paddd L_aes_gcm_six(%rip), %xmm14 + pshufb %xmm1, %xmm14 + movdqa %xmm0, %xmm15 + paddd L_aes_gcm_seven(%rip), %xmm15 + pshufb %xmm1, %xmm15 + paddd L_aes_gcm_eight(%rip), %xmm0 + movdqa (%r15), %xmm7 + movdqa %xmm0, 128(%rsp) + pxor %xmm7, %xmm8 + pxor %xmm7, %xmm9 + pxor %xmm7, %xmm10 + pxor %xmm7, %xmm11 + pxor %xmm7, %xmm12 + pxor %xmm7, %xmm13 + pxor %xmm7, %xmm14 + pxor %xmm7, %xmm15 + movdqa 112(%rsp), %xmm7 + movdqu -128(%rdx), %xmm0 + aesenc 16(%r15), %xmm8 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm0 + pxor %xmm2, %xmm0 + pshufd $0x4e, %xmm7, %xmm1 + pshufd $0x4e, %xmm0, %xmm5 + pxor %xmm7, %xmm1 + pxor %xmm0, %xmm5 + movdqa %xmm0, %xmm3 + pclmulqdq $0x11, %xmm7, %xmm3 + aesenc 16(%r15), %xmm9 + aesenc 16(%r15), %xmm10 + movdqa %xmm0, %xmm2 + pclmulqdq $0x00, %xmm7, %xmm2 + aesenc 16(%r15), %xmm11 + aesenc 16(%r15), %xmm12 + pclmulqdq $0x00, %xmm5, %xmm1 + aesenc 16(%r15), %xmm13 + aesenc 16(%r15), %xmm14 + aesenc 16(%r15), %xmm15 + pxor %xmm2, %xmm1 + pxor %xmm3, %xmm1 + movdqa 96(%rsp), %xmm7 + movdqu -112(%rdx), %xmm0 + pshufd $0x4e, %xmm7, %xmm4 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm0 + aesenc 32(%r15), %xmm8 + pxor %xmm7, %xmm4 + pshufd $0x4e, %xmm0, %xmm5 + pxor %xmm0, %xmm5 + movdqa %xmm0, %xmm6 + pclmulqdq $0x11, %xmm7, %xmm6 + aesenc 32(%r15), %xmm9 + aesenc 32(%r15), %xmm10 + pclmulqdq $0x00, %xmm0, %xmm7 + aesenc 32(%r15), %xmm11 + aesenc 32(%r15), %xmm12 + pclmulqdq $0x00, %xmm5, %xmm4 + aesenc 32(%r15), %xmm13 + aesenc 32(%r15), %xmm14 + aesenc 32(%r15), %xmm15 + pxor %xmm7, %xmm1 + pxor %xmm7, %xmm2 + pxor %xmm6, %xmm1 + pxor %xmm6, %xmm3 + pxor %xmm4, %xmm1 + movdqa 80(%rsp), %xmm7 + movdqu -96(%rdx), %xmm0 + pshufd $0x4e, %xmm7, %xmm4 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm0 + aesenc 48(%r15), %xmm8 + pxor %xmm7, %xmm4 + pshufd $0x4e, %xmm0, %xmm5 + pxor %xmm0, %xmm5 + movdqa %xmm0, %xmm6 + pclmulqdq $0x11, %xmm7, %xmm6 + aesenc 48(%r15), %xmm9 + aesenc 48(%r15), %xmm10 + pclmulqdq $0x00, %xmm0, %xmm7 + aesenc 48(%r15), %xmm11 + aesenc 48(%r15), %xmm12 + pclmulqdq $0x00, %xmm5, %xmm4 + aesenc 48(%r15), %xmm13 + aesenc 48(%r15), %xmm14 + aesenc 48(%r15), %xmm15 + pxor %xmm7, %xmm1 + pxor %xmm7, %xmm2 + pxor %xmm6, %xmm1 + pxor %xmm6, %xmm3 + pxor %xmm4, %xmm1 + movdqa 64(%rsp), %xmm7 + movdqu -80(%rdx), %xmm0 + pshufd $0x4e, %xmm7, %xmm4 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm0 + aesenc 64(%r15), %xmm8 + pxor %xmm7, %xmm4 + pshufd $0x4e, %xmm0, %xmm5 + pxor %xmm0, %xmm5 + movdqa %xmm0, %xmm6 + pclmulqdq $0x11, %xmm7, %xmm6 + aesenc 64(%r15), %xmm9 + aesenc 64(%r15), %xmm10 + pclmulqdq $0x00, %xmm0, %xmm7 + aesenc 64(%r15), %xmm11 + aesenc 64(%r15), %xmm12 + pclmulqdq $0x00, %xmm5, %xmm4 + aesenc 64(%r15), %xmm13 + aesenc 64(%r15), %xmm14 + aesenc 64(%r15), %xmm15 + pxor %xmm7, %xmm1 + pxor %xmm7, %xmm2 + pxor %xmm6, %xmm1 + pxor %xmm6, %xmm3 + pxor %xmm4, %xmm1 + movdqa 48(%rsp), %xmm7 + movdqu -64(%rdx), %xmm0 + pshufd $0x4e, %xmm7, %xmm4 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm0 + aesenc 80(%r15), %xmm8 + pxor %xmm7, %xmm4 + pshufd $0x4e, %xmm0, %xmm5 + pxor %xmm0, %xmm5 + movdqa %xmm0, %xmm6 + pclmulqdq $0x11, %xmm7, %xmm6 + aesenc 80(%r15), %xmm9 + aesenc 80(%r15), %xmm10 + pclmulqdq $0x00, %xmm0, %xmm7 + aesenc 80(%r15), %xmm11 + aesenc 80(%r15), %xmm12 + pclmulqdq $0x00, %xmm5, %xmm4 + aesenc 80(%r15), %xmm13 + aesenc 80(%r15), %xmm14 + aesenc 80(%r15), %xmm15 + pxor %xmm7, %xmm1 + pxor %xmm7, %xmm2 + pxor %xmm6, %xmm1 + pxor %xmm6, %xmm3 + pxor %xmm4, %xmm1 + movdqa 32(%rsp), %xmm7 + movdqu -48(%rdx), %xmm0 + pshufd $0x4e, %xmm7, %xmm4 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm0 + aesenc 96(%r15), %xmm8 + pxor %xmm7, %xmm4 + pshufd $0x4e, %xmm0, %xmm5 + pxor %xmm0, %xmm5 + movdqa %xmm0, %xmm6 + pclmulqdq $0x11, %xmm7, %xmm6 + aesenc 96(%r15), %xmm9 + aesenc 96(%r15), %xmm10 + pclmulqdq $0x00, %xmm0, %xmm7 + aesenc 96(%r15), %xmm11 + aesenc 96(%r15), %xmm12 + pclmulqdq $0x00, %xmm5, %xmm4 + aesenc 96(%r15), %xmm13 + aesenc 96(%r15), %xmm14 + aesenc 96(%r15), %xmm15 + pxor %xmm7, %xmm1 + pxor %xmm7, %xmm2 + pxor %xmm6, %xmm1 + pxor %xmm6, %xmm3 + pxor %xmm4, %xmm1 + movdqa 16(%rsp), %xmm7 + movdqu -32(%rdx), %xmm0 + pshufd $0x4e, %xmm7, %xmm4 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm0 + aesenc 112(%r15), %xmm8 + pxor %xmm7, %xmm4 + pshufd $0x4e, %xmm0, %xmm5 + pxor %xmm0, %xmm5 + movdqa %xmm0, %xmm6 + pclmulqdq $0x11, %xmm7, %xmm6 + aesenc 112(%r15), %xmm9 + aesenc 112(%r15), %xmm10 + pclmulqdq $0x00, %xmm0, %xmm7 + aesenc 112(%r15), %xmm11 + aesenc 112(%r15), %xmm12 + pclmulqdq $0x00, %xmm5, %xmm4 + aesenc 112(%r15), %xmm13 + aesenc 112(%r15), %xmm14 + aesenc 112(%r15), %xmm15 + pxor %xmm7, %xmm1 + pxor %xmm7, %xmm2 + pxor %xmm6, %xmm1 + pxor %xmm6, %xmm3 + pxor %xmm4, %xmm1 + movdqa (%rsp), %xmm7 + movdqu -16(%rdx), %xmm0 + pshufd $0x4e, %xmm7, %xmm4 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm0 + aesenc 128(%r15), %xmm8 + pxor %xmm7, %xmm4 + pshufd $0x4e, %xmm0, %xmm5 + pxor %xmm0, %xmm5 + movdqa %xmm0, %xmm6 + pclmulqdq $0x11, %xmm7, %xmm6 + aesenc 128(%r15), %xmm9 + aesenc 128(%r15), %xmm10 + pclmulqdq $0x00, %xmm0, %xmm7 + aesenc 128(%r15), %xmm11 + aesenc 128(%r15), %xmm12 + pclmulqdq $0x00, %xmm5, %xmm4 + aesenc 128(%r15), %xmm13 + aesenc 128(%r15), %xmm14 + aesenc 128(%r15), %xmm15 + pxor %xmm7, %xmm1 + pxor %xmm7, %xmm2 + pxor %xmm6, %xmm1 + pxor %xmm6, %xmm3 + pxor %xmm4, %xmm1 + movdqa %xmm1, %xmm5 + psrldq $8, %xmm1 + pslldq $8, %xmm5 + aesenc 144(%r15), %xmm8 + pxor %xmm5, %xmm2 + pxor %xmm1, %xmm3 + movdqa %xmm2, %xmm7 + movdqa %xmm2, %xmm4 + movdqa %xmm2, %xmm5 + aesenc 144(%r15), %xmm9 + pslld $31, %xmm7 + pslld $30, %xmm4 + pslld $25, %xmm5 + aesenc 144(%r15), %xmm10 + pxor %xmm4, %xmm7 + pxor %xmm5, %xmm7 + aesenc 144(%r15), %xmm11 + movdqa %xmm7, %xmm4 + pslldq $12, %xmm7 + psrldq $4, %xmm4 + aesenc 144(%r15), %xmm12 + pxor %xmm7, %xmm2 + movdqa %xmm2, %xmm5 + movdqa %xmm2, %xmm1 + movdqa %xmm2, %xmm0 + aesenc 144(%r15), %xmm13 + psrld $0x01, %xmm5 + psrld $2, %xmm1 + psrld $7, %xmm0 + aesenc 144(%r15), %xmm14 + pxor %xmm1, %xmm5 + pxor %xmm0, %xmm5 + aesenc 144(%r15), %xmm15 + pxor %xmm4, %xmm5 + pxor %xmm5, %xmm2 + pxor %xmm3, %xmm2 + cmpl $11, %r10d + movdqa 160(%r15), %xmm7 + jl L_AES_GCM_encrypt_aesenc_128_ghash_avx_done + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + movdqa 176(%r15), %xmm7 + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + cmpl $13, %r10d + movdqa 192(%r15), %xmm7 + jl L_AES_GCM_encrypt_aesenc_128_ghash_avx_done + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + movdqa 208(%r15), %xmm7 + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + movdqa 224(%r15), %xmm7 +L_AES_GCM_encrypt_aesenc_128_ghash_avx_done: + aesenclast %xmm7, %xmm8 + aesenclast %xmm7, %xmm9 + movdqu (%rcx), %xmm0 + movdqu 16(%rcx), %xmm1 + pxor %xmm0, %xmm8 + pxor %xmm1, %xmm9 + movdqu %xmm8, (%rdx) + movdqu %xmm9, 16(%rdx) + aesenclast %xmm7, %xmm10 + aesenclast %xmm7, %xmm11 + movdqu 32(%rcx), %xmm0 + movdqu 48(%rcx), %xmm1 + pxor %xmm0, %xmm10 + pxor %xmm1, %xmm11 + movdqu %xmm10, 32(%rdx) + movdqu %xmm11, 48(%rdx) + aesenclast %xmm7, %xmm12 + aesenclast %xmm7, %xmm13 + movdqu 64(%rcx), %xmm0 + movdqu 80(%rcx), %xmm1 + pxor %xmm0, %xmm12 + pxor %xmm1, %xmm13 + movdqu %xmm12, 64(%rdx) + movdqu %xmm13, 80(%rdx) + aesenclast %xmm7, %xmm14 + aesenclast %xmm7, %xmm15 + movdqu 96(%rcx), %xmm0 + movdqu 112(%rcx), %xmm1 + pxor %xmm0, %xmm14 + pxor %xmm1, %xmm15 + movdqu %xmm14, 96(%rdx) + movdqu %xmm15, 112(%rdx) + addl $0x80, %ebx + cmpl %r13d, %ebx + jl L_AES_GCM_encrypt_ghash_128 +L_AES_GCM_encrypt_end_128: + movdqa L_aes_gcm_bswap_mask(%rip), %xmm4 + pshufb %xmm4, %xmm8 + pshufb %xmm4, %xmm9 + pshufb %xmm4, %xmm10 + pshufb %xmm4, %xmm11 + pxor %xmm2, %xmm8 + pshufb %xmm4, %xmm12 + pshufb %xmm4, %xmm13 + pshufb %xmm4, %xmm14 + pshufb %xmm4, %xmm15 + movdqa 112(%rsp), %xmm7 + pshufd $0x4e, %xmm8, %xmm1 + pshufd $0x4e, %xmm7, %xmm2 + movdqa %xmm7, %xmm3 + movdqa %xmm7, %xmm0 + pclmulqdq $0x11, %xmm8, %xmm3 + pclmulqdq $0x00, %xmm8, %xmm0 + pxor %xmm8, %xmm1 + pxor %xmm7, %xmm2 + pclmulqdq $0x00, %xmm2, %xmm1 + pxor %xmm0, %xmm1 + pxor %xmm3, %xmm1 + movdqa %xmm1, %xmm2 + movdqa %xmm0, %xmm4 + movdqa %xmm3, %xmm6 + pslldq $8, %xmm2 + psrldq $8, %xmm1 + pxor %xmm2, %xmm4 + pxor %xmm1, %xmm6 + movdqa 96(%rsp), %xmm7 + pshufd $0x4e, %xmm9, %xmm1 + pshufd $0x4e, %xmm7, %xmm2 + movdqa %xmm7, %xmm3 + movdqa %xmm7, %xmm0 + pclmulqdq $0x11, %xmm9, %xmm3 + pclmulqdq $0x00, %xmm9, %xmm0 + pxor %xmm9, %xmm1 + pxor %xmm7, %xmm2 + pclmulqdq $0x00, %xmm2, %xmm1 + pxor %xmm0, %xmm1 + pxor %xmm3, %xmm1 + movdqa %xmm1, %xmm2 + pxor %xmm0, %xmm4 + pxor %xmm3, %xmm6 + pslldq $8, %xmm2 + psrldq $8, %xmm1 + pxor %xmm2, %xmm4 + pxor %xmm1, %xmm6 + movdqa 80(%rsp), %xmm7 + pshufd $0x4e, %xmm10, %xmm1 + pshufd $0x4e, %xmm7, %xmm2 + movdqa %xmm7, %xmm3 + movdqa %xmm7, %xmm0 + pclmulqdq $0x11, %xmm10, %xmm3 + pclmulqdq $0x00, %xmm10, %xmm0 + pxor %xmm10, %xmm1 + pxor %xmm7, %xmm2 + pclmulqdq $0x00, %xmm2, %xmm1 + pxor %xmm0, %xmm1 + pxor %xmm3, %xmm1 + movdqa %xmm1, %xmm2 + pxor %xmm0, %xmm4 + pxor %xmm3, %xmm6 + pslldq $8, %xmm2 + psrldq $8, %xmm1 + pxor %xmm2, %xmm4 + pxor %xmm1, %xmm6 + movdqa 64(%rsp), %xmm7 + pshufd $0x4e, %xmm11, %xmm1 + pshufd $0x4e, %xmm7, %xmm2 + movdqa %xmm7, %xmm3 + movdqa %xmm7, %xmm0 + pclmulqdq $0x11, %xmm11, %xmm3 + pclmulqdq $0x00, %xmm11, %xmm0 + pxor %xmm11, %xmm1 + pxor %xmm7, %xmm2 + pclmulqdq $0x00, %xmm2, %xmm1 + pxor %xmm0, %xmm1 + pxor %xmm3, %xmm1 + movdqa %xmm1, %xmm2 + pxor %xmm0, %xmm4 + pxor %xmm3, %xmm6 + pslldq $8, %xmm2 + psrldq $8, %xmm1 + pxor %xmm2, %xmm4 + pxor %xmm1, %xmm6 + movdqa 48(%rsp), %xmm7 + pshufd $0x4e, %xmm12, %xmm1 + pshufd $0x4e, %xmm7, %xmm2 + movdqa %xmm7, %xmm3 + movdqa %xmm7, %xmm0 + pclmulqdq $0x11, %xmm12, %xmm3 + pclmulqdq $0x00, %xmm12, %xmm0 + pxor %xmm12, %xmm1 + pxor %xmm7, %xmm2 + pclmulqdq $0x00, %xmm2, %xmm1 + pxor %xmm0, %xmm1 + pxor %xmm3, %xmm1 + movdqa %xmm1, %xmm2 + pxor %xmm0, %xmm4 + pxor %xmm3, %xmm6 + pslldq $8, %xmm2 + psrldq $8, %xmm1 + pxor %xmm2, %xmm4 + pxor %xmm1, %xmm6 + movdqa 32(%rsp), %xmm7 + pshufd $0x4e, %xmm13, %xmm1 + pshufd $0x4e, %xmm7, %xmm2 + movdqa %xmm7, %xmm3 + movdqa %xmm7, %xmm0 + pclmulqdq $0x11, %xmm13, %xmm3 + pclmulqdq $0x00, %xmm13, %xmm0 + pxor %xmm13, %xmm1 + pxor %xmm7, %xmm2 + pclmulqdq $0x00, %xmm2, %xmm1 + pxor %xmm0, %xmm1 + pxor %xmm3, %xmm1 + movdqa %xmm1, %xmm2 + pxor %xmm0, %xmm4 + pxor %xmm3, %xmm6 + pslldq $8, %xmm2 + psrldq $8, %xmm1 + pxor %xmm2, %xmm4 + pxor %xmm1, %xmm6 + movdqa 16(%rsp), %xmm7 + pshufd $0x4e, %xmm14, %xmm1 + pshufd $0x4e, %xmm7, %xmm2 + movdqa %xmm7, %xmm3 + movdqa %xmm7, %xmm0 + pclmulqdq $0x11, %xmm14, %xmm3 + pclmulqdq $0x00, %xmm14, %xmm0 + pxor %xmm14, %xmm1 + pxor %xmm7, %xmm2 + pclmulqdq $0x00, %xmm2, %xmm1 + pxor %xmm0, %xmm1 + pxor %xmm3, %xmm1 + movdqa %xmm1, %xmm2 + pxor %xmm0, %xmm4 + pxor %xmm3, %xmm6 + pslldq $8, %xmm2 + psrldq $8, %xmm1 + pxor %xmm2, %xmm4 + pxor %xmm1, %xmm6 + movdqa (%rsp), %xmm7 + pshufd $0x4e, %xmm15, %xmm1 + pshufd $0x4e, %xmm7, %xmm2 + movdqa %xmm7, %xmm3 + movdqa %xmm7, %xmm0 + pclmulqdq $0x11, %xmm15, %xmm3 + pclmulqdq $0x00, %xmm15, %xmm0 + pxor %xmm15, %xmm1 + pxor %xmm7, %xmm2 + pclmulqdq $0x00, %xmm2, %xmm1 + pxor %xmm0, %xmm1 + pxor %xmm3, %xmm1 + movdqa %xmm1, %xmm2 + pxor %xmm0, %xmm4 + pxor %xmm3, %xmm6 + pslldq $8, %xmm2 + psrldq $8, %xmm1 + pxor %xmm2, %xmm4 + pxor %xmm1, %xmm6 + movdqa %xmm4, %xmm0 + movdqa %xmm4, %xmm1 + movdqa %xmm4, %xmm2 + pslld $31, %xmm0 + pslld $30, %xmm1 + pslld $25, %xmm2 + pxor %xmm1, %xmm0 + pxor %xmm2, %xmm0 + movdqa %xmm0, %xmm1 + psrldq $4, %xmm1 + pslldq $12, %xmm0 + pxor %xmm0, %xmm4 + movdqa %xmm4, %xmm2 + movdqa %xmm4, %xmm3 + movdqa %xmm4, %xmm0 + psrld $0x01, %xmm2 + psrld $2, %xmm3 + psrld $7, %xmm0 + pxor %xmm3, %xmm2 + pxor %xmm0, %xmm2 + pxor %xmm1, %xmm2 + pxor %xmm4, %xmm2 + pxor %xmm2, %xmm6 + movdqa (%rsp), %xmm5 +L_AES_GCM_encrypt_done_128: + movl %r9d, %edx + cmpl %edx, %ebx + jge L_AES_GCM_encrypt_done_enc + movl %r9d, %r13d + andl $0xfffffff0, %r13d + cmpl %r13d, %ebx + jge L_AES_GCM_encrypt_last_block_done + leaq (%rdi,%rbx,1), %rcx + leaq (%rsi,%rbx,1), %rdx + movdqa 128(%rsp), %xmm8 + movdqa %xmm8, %xmm9 + pshufb L_aes_gcm_bswap_epi64(%rip), %xmm8 + paddd L_aes_gcm_one(%rip), %xmm9 + pxor (%r15), %xmm8 + movdqa %xmm9, 128(%rsp) + aesenc 16(%r15), %xmm8 + aesenc 32(%r15), %xmm8 + aesenc 48(%r15), %xmm8 + aesenc 64(%r15), %xmm8 + aesenc 80(%r15), %xmm8 + aesenc 96(%r15), %xmm8 + aesenc 112(%r15), %xmm8 + aesenc 128(%r15), %xmm8 + aesenc 144(%r15), %xmm8 + cmpl $11, %r10d + movdqa 160(%r15), %xmm9 + jl L_AES_GCM_encrypt_aesenc_block_aesenc_avx_last + aesenc %xmm9, %xmm8 + aesenc 176(%r15), %xmm8 + cmpl $13, %r10d + movdqa 192(%r15), %xmm9 + jl L_AES_GCM_encrypt_aesenc_block_aesenc_avx_last + aesenc %xmm9, %xmm8 + aesenc 208(%r15), %xmm8 + movdqa 224(%r15), %xmm9 +L_AES_GCM_encrypt_aesenc_block_aesenc_avx_last: + aesenclast %xmm9, %xmm8 + movdqu (%rcx), %xmm9 + pxor %xmm9, %xmm8 + movdqu %xmm8, (%rdx) + pshufb L_aes_gcm_bswap_mask(%rip), %xmm8 + pxor %xmm8, %xmm6 + addl $16, %ebx + cmpl %r13d, %ebx + jge L_AES_GCM_encrypt_last_block_ghash +L_AES_GCM_encrypt_last_block_start: + leaq (%rdi,%rbx,1), %rcx + leaq (%rsi,%rbx,1), %rdx + movdqa 128(%rsp), %xmm8 + movdqa %xmm8, %xmm9 + pshufb L_aes_gcm_bswap_epi64(%rip), %xmm8 + paddd L_aes_gcm_one(%rip), %xmm9 + pxor (%r15), %xmm8 + movdqa %xmm9, 128(%rsp) + movdqa %xmm6, %xmm10 + pclmulqdq $16, %xmm5, %xmm10 + aesenc 16(%r15), %xmm8 + aesenc 32(%r15), %xmm8 + movdqa %xmm6, %xmm11 + pclmulqdq $0x01, %xmm5, %xmm11 + aesenc 48(%r15), %xmm8 + aesenc 64(%r15), %xmm8 + movdqa %xmm6, %xmm12 + pclmulqdq $0x00, %xmm5, %xmm12 + aesenc 80(%r15), %xmm8 + movdqa %xmm6, %xmm1 + pclmulqdq $0x11, %xmm5, %xmm1 + aesenc 96(%r15), %xmm8 + pxor %xmm11, %xmm10 + movdqa %xmm10, %xmm2 + psrldq $8, %xmm10 + pslldq $8, %xmm2 + aesenc 112(%r15), %xmm8 + movdqa %xmm1, %xmm3 + pxor %xmm12, %xmm2 + pxor %xmm10, %xmm3 + movdqa L_aes_gcm_mod2_128(%rip), %xmm0 + movdqa %xmm2, %xmm11 + pclmulqdq $16, %xmm0, %xmm11 + aesenc 128(%r15), %xmm8 + pshufd $0x4e, %xmm2, %xmm10 + pxor %xmm11, %xmm10 + movdqa %xmm10, %xmm11 + pclmulqdq $16, %xmm0, %xmm11 + aesenc 144(%r15), %xmm8 + pshufd $0x4e, %xmm10, %xmm6 + pxor %xmm11, %xmm6 + pxor %xmm3, %xmm6 + cmpl $11, %r10d + movdqa 160(%r15), %xmm9 + jl L_AES_GCM_encrypt_aesenc_gfmul_last + aesenc %xmm9, %xmm8 + aesenc 176(%r15), %xmm8 + cmpl $13, %r10d + movdqa 192(%r15), %xmm9 + jl L_AES_GCM_encrypt_aesenc_gfmul_last + aesenc %xmm9, %xmm8 + aesenc 208(%r15), %xmm8 + movdqa 224(%r15), %xmm9 +L_AES_GCM_encrypt_aesenc_gfmul_last: + aesenclast %xmm9, %xmm8 + movdqu (%rcx), %xmm9 + pxor %xmm9, %xmm8 + movdqu %xmm8, (%rdx) + pshufb L_aes_gcm_bswap_mask(%rip), %xmm8 + pxor %xmm8, %xmm6 + addl $16, %ebx + cmpl %r13d, %ebx + jl L_AES_GCM_encrypt_last_block_start +L_AES_GCM_encrypt_last_block_ghash: + pshufd $0x4e, %xmm5, %xmm9 + pshufd $0x4e, %xmm6, %xmm10 + movdqa %xmm6, %xmm11 + movdqa %xmm6, %xmm8 + pclmulqdq $0x11, %xmm5, %xmm11 + pclmulqdq $0x00, %xmm5, %xmm8 + pxor %xmm5, %xmm9 + pxor %xmm6, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm6 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm6 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm6 +L_AES_GCM_encrypt_last_block_done: + movl %r9d, %ecx + movl %ecx, %edx + andl $15, %ecx + jz L_AES_GCM_encrypt_aesenc_last15_enc_avx_done + movdqa 128(%rsp), %xmm4 + pshufb L_aes_gcm_bswap_epi64(%rip), %xmm4 + pxor (%r15), %xmm4 + aesenc 16(%r15), %xmm4 + aesenc 32(%r15), %xmm4 + aesenc 48(%r15), %xmm4 + aesenc 64(%r15), %xmm4 + aesenc 80(%r15), %xmm4 + aesenc 96(%r15), %xmm4 + aesenc 112(%r15), %xmm4 + aesenc 128(%r15), %xmm4 + aesenc 144(%r15), %xmm4 + cmpl $11, %r10d + movdqa 160(%r15), %xmm9 + jl L_AES_GCM_encrypt_aesenc_last15_enc_avx_aesenc_avx_last + aesenc %xmm9, %xmm4 + aesenc 176(%r15), %xmm4 + cmpl $13, %r10d + movdqa 192(%r15), %xmm9 + jl L_AES_GCM_encrypt_aesenc_last15_enc_avx_aesenc_avx_last + aesenc %xmm9, %xmm4 + aesenc 208(%r15), %xmm4 + movdqa 224(%r15), %xmm9 +L_AES_GCM_encrypt_aesenc_last15_enc_avx_aesenc_avx_last: + aesenclast %xmm9, %xmm4 + subq $16, %rsp + xorl %ecx, %ecx + movdqa %xmm4, (%rsp) +L_AES_GCM_encrypt_aesenc_last15_enc_avx_loop: + movzbl (%rdi,%rbx,1), %r13d + xorb (%rsp,%rcx,1), %r13b + movb %r13b, (%rsi,%rbx,1) + movb %r13b, (%rsp,%rcx,1) + incl %ebx + incl %ecx + cmpl %edx, %ebx + jl L_AES_GCM_encrypt_aesenc_last15_enc_avx_loop + xorq %r13, %r13 + cmpl $16, %ecx + je L_AES_GCM_encrypt_aesenc_last15_enc_avx_finish_enc +L_AES_GCM_encrypt_aesenc_last15_enc_avx_byte_loop: + movb %r13b, (%rsp,%rcx,1) + incl %ecx + cmpl $16, %ecx + jl L_AES_GCM_encrypt_aesenc_last15_enc_avx_byte_loop +L_AES_GCM_encrypt_aesenc_last15_enc_avx_finish_enc: + movdqa (%rsp), %xmm4 + addq $16, %rsp + pshufb L_aes_gcm_bswap_mask(%rip), %xmm4 + pxor %xmm4, %xmm6 + pshufd $0x4e, %xmm5, %xmm9 + pshufd $0x4e, %xmm6, %xmm10 + movdqa %xmm6, %xmm11 + movdqa %xmm6, %xmm8 + pclmulqdq $0x11, %xmm5, %xmm11 + pclmulqdq $0x00, %xmm5, %xmm8 + pxor %xmm5, %xmm9 + pxor %xmm6, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm6 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm6 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm6 +L_AES_GCM_encrypt_aesenc_last15_enc_avx_done: +L_AES_GCM_encrypt_done_enc: + movl %r9d, %edx + movl %r11d, %ecx + shlq $3, %rdx + shlq $3, %rcx + pinsrq $0x00, %rdx, %xmm0 + pinsrq $0x01, %rcx, %xmm0 + pxor %xmm0, %xmm6 + pshufd $0x4e, %xmm5, %xmm9 + pshufd $0x4e, %xmm6, %xmm10 + movdqa %xmm6, %xmm11 + movdqa %xmm6, %xmm8 + pclmulqdq $0x11, %xmm5, %xmm11 + pclmulqdq $0x00, %xmm5, %xmm8 + pxor %xmm5, %xmm9 + pxor %xmm6, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm6 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm6 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm6 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm6 + movdqa 144(%rsp), %xmm0 + pxor %xmm6, %xmm0 + cmpl $16, %r14d + je L_AES_GCM_encrypt_store_tag_16 + xorq %rcx, %rcx + movdqa %xmm0, (%rsp) +L_AES_GCM_encrypt_store_tag_loop: + movzbl (%rsp,%rcx,1), %r13d + movb %r13b, (%r8,%rcx,1) + incl %ecx + cmpl %r14d, %ecx + jne L_AES_GCM_encrypt_store_tag_loop + jmp L_AES_GCM_encrypt_store_tag_done +L_AES_GCM_encrypt_store_tag_16: + movdqu %xmm0, (%r8) +L_AES_GCM_encrypt_store_tag_done: + addq $0xa0, %rsp + popq %r15 + popq %r14 + popq %rbx + popq %r12 + popq %r13 + repz retq +#ifndef __APPLE__ +.size AES_GCM_encrypt,.-AES_GCM_encrypt +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl AES_GCM_decrypt +.type AES_GCM_decrypt,@function +.align 4 +AES_GCM_decrypt: +#else +.section __TEXT,__text +.globl _AES_GCM_decrypt +.p2align 2 +_AES_GCM_decrypt: +#endif /* __APPLE__ */ + pushq %r13 + pushq %r12 + pushq %rbx + pushq %r14 + pushq %r15 + pushq %rbp + movq %rdx, %r12 + movq %rcx, %rax + movl 56(%rsp), %r11d + movl 64(%rsp), %ebx + movl 72(%rsp), %r14d + movq 80(%rsp), %r15 + movl 88(%rsp), %r10d + movq 96(%rsp), %rbp + subq $0xa8, %rsp + pxor %xmm4, %xmm4 + pxor %xmm6, %xmm6 + cmpl $12, %ebx + movl %ebx, %edx + jne L_AES_GCM_decrypt_iv_not_12 + # # Calculate values when IV is 12 bytes + # Set counter based on IV + movl $0x1000000, %ecx + pinsrq $0x00, (%rax), %xmm4 + pinsrd $2, 8(%rax), %xmm4 + pinsrd $3, %ecx, %xmm4 + # H = Encrypt X(=0) and T = Encrypt counter + movdqa %xmm4, %xmm1 + movdqa (%r15), %xmm5 + pxor %xmm5, %xmm1 + movdqa 16(%r15), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 32(%r15), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 48(%r15), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 64(%r15), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 80(%r15), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 96(%r15), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 112(%r15), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 128(%r15), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 144(%r15), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + cmpl $11, %r10d + movdqa 160(%r15), %xmm7 + jl L_AES_GCM_decrypt_calc_iv_12_last + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 176(%r15), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + cmpl $13, %r10d + movdqa 192(%r15), %xmm7 + jl L_AES_GCM_decrypt_calc_iv_12_last + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 208(%r15), %xmm7 + aesenc %xmm7, %xmm5 + aesenc %xmm7, %xmm1 + movdqa 224(%r15), %xmm7 +L_AES_GCM_decrypt_calc_iv_12_last: + aesenclast %xmm7, %xmm5 + aesenclast %xmm7, %xmm1 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm5 + movdqa %xmm1, 144(%rsp) + jmp L_AES_GCM_decrypt_iv_done +L_AES_GCM_decrypt_iv_not_12: + # Calculate values when IV is not 12 bytes + # H = Encrypt X(=0) + movdqa (%r15), %xmm5 + aesenc 16(%r15), %xmm5 + aesenc 32(%r15), %xmm5 + aesenc 48(%r15), %xmm5 + aesenc 64(%r15), %xmm5 + aesenc 80(%r15), %xmm5 + aesenc 96(%r15), %xmm5 + aesenc 112(%r15), %xmm5 + aesenc 128(%r15), %xmm5 + aesenc 144(%r15), %xmm5 + cmpl $11, %r10d + movdqa 160(%r15), %xmm9 + jl L_AES_GCM_decrypt_calc_iv_1_aesenc_avx_last + aesenc %xmm9, %xmm5 + aesenc 176(%r15), %xmm5 + cmpl $13, %r10d + movdqa 192(%r15), %xmm9 + jl L_AES_GCM_decrypt_calc_iv_1_aesenc_avx_last + aesenc %xmm9, %xmm5 + aesenc 208(%r15), %xmm5 + movdqa 224(%r15), %xmm9 +L_AES_GCM_decrypt_calc_iv_1_aesenc_avx_last: + aesenclast %xmm9, %xmm5 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm5 + # Calc counter + # Initialization vector + cmpl $0x00, %edx + movq $0x00, %rcx + je L_AES_GCM_decrypt_calc_iv_done + cmpl $16, %edx + jl L_AES_GCM_decrypt_calc_iv_lt16 + andl $0xfffffff0, %edx +L_AES_GCM_decrypt_calc_iv_16_loop: + movdqu (%rax,%rcx,1), %xmm8 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm8 + pxor %xmm8, %xmm4 + pshufd $0x4e, %xmm4, %xmm1 + pshufd $0x4e, %xmm5, %xmm2 + movdqa %xmm5, %xmm3 + movdqa %xmm5, %xmm0 + pclmulqdq $0x11, %xmm4, %xmm3 + pclmulqdq $0x00, %xmm4, %xmm0 + pxor %xmm4, %xmm1 + pxor %xmm5, %xmm2 + pclmulqdq $0x00, %xmm2, %xmm1 + pxor %xmm0, %xmm1 + pxor %xmm3, %xmm1 + movdqa %xmm1, %xmm2 + movdqa %xmm0, %xmm7 + movdqa %xmm3, %xmm4 + pslldq $8, %xmm2 + psrldq $8, %xmm1 + pxor %xmm2, %xmm7 + pxor %xmm1, %xmm4 + movdqa %xmm7, %xmm0 + movdqa %xmm4, %xmm1 + psrld $31, %xmm0 + psrld $31, %xmm1 + pslld $0x01, %xmm7 + pslld $0x01, %xmm4 + movdqa %xmm0, %xmm2 + pslldq $4, %xmm0 + psrldq $12, %xmm2 + pslldq $4, %xmm1 + por %xmm2, %xmm4 + por %xmm0, %xmm7 + por %xmm1, %xmm4 + movdqa %xmm7, %xmm0 + movdqa %xmm7, %xmm1 + movdqa %xmm7, %xmm2 + pslld $31, %xmm0 + pslld $30, %xmm1 + pslld $25, %xmm2 + pxor %xmm1, %xmm0 + pxor %xmm2, %xmm0 + movdqa %xmm0, %xmm1 + psrldq $4, %xmm1 + pslldq $12, %xmm0 + pxor %xmm0, %xmm7 + movdqa %xmm7, %xmm2 + movdqa %xmm7, %xmm3 + movdqa %xmm7, %xmm0 + psrld $0x01, %xmm2 + psrld $2, %xmm3 + psrld $7, %xmm0 + pxor %xmm3, %xmm2 + pxor %xmm0, %xmm2 + pxor %xmm1, %xmm2 + pxor %xmm7, %xmm2 + pxor %xmm2, %xmm4 + addl $16, %ecx + cmpl %edx, %ecx + jl L_AES_GCM_decrypt_calc_iv_16_loop + movl %ebx, %edx + cmpl %edx, %ecx + je L_AES_GCM_decrypt_calc_iv_done +L_AES_GCM_decrypt_calc_iv_lt16: + subq $16, %rsp + pxor %xmm8, %xmm8 + xorl %ebx, %ebx + movdqa %xmm8, (%rsp) +L_AES_GCM_decrypt_calc_iv_loop: + movzbl (%rax,%rcx,1), %r13d + movb %r13b, (%rsp,%rbx,1) + incl %ecx + incl %ebx + cmpl %edx, %ecx + jl L_AES_GCM_decrypt_calc_iv_loop + movdqa (%rsp), %xmm8 + addq $16, %rsp + pshufb L_aes_gcm_bswap_mask(%rip), %xmm8 + pxor %xmm8, %xmm4 + pshufd $0x4e, %xmm4, %xmm1 + pshufd $0x4e, %xmm5, %xmm2 + movdqa %xmm5, %xmm3 + movdqa %xmm5, %xmm0 + pclmulqdq $0x11, %xmm4, %xmm3 + pclmulqdq $0x00, %xmm4, %xmm0 + pxor %xmm4, %xmm1 + pxor %xmm5, %xmm2 + pclmulqdq $0x00, %xmm2, %xmm1 + pxor %xmm0, %xmm1 + pxor %xmm3, %xmm1 + movdqa %xmm1, %xmm2 + movdqa %xmm0, %xmm7 + movdqa %xmm3, %xmm4 + pslldq $8, %xmm2 + psrldq $8, %xmm1 + pxor %xmm2, %xmm7 + pxor %xmm1, %xmm4 + movdqa %xmm7, %xmm0 + movdqa %xmm4, %xmm1 + psrld $31, %xmm0 + psrld $31, %xmm1 + pslld $0x01, %xmm7 + pslld $0x01, %xmm4 + movdqa %xmm0, %xmm2 + pslldq $4, %xmm0 + psrldq $12, %xmm2 + pslldq $4, %xmm1 + por %xmm2, %xmm4 + por %xmm0, %xmm7 + por %xmm1, %xmm4 + movdqa %xmm7, %xmm0 + movdqa %xmm7, %xmm1 + movdqa %xmm7, %xmm2 + pslld $31, %xmm0 + pslld $30, %xmm1 + pslld $25, %xmm2 + pxor %xmm1, %xmm0 + pxor %xmm2, %xmm0 + movdqa %xmm0, %xmm1 + psrldq $4, %xmm1 + pslldq $12, %xmm0 + pxor %xmm0, %xmm7 + movdqa %xmm7, %xmm2 + movdqa %xmm7, %xmm3 + movdqa %xmm7, %xmm0 + psrld $0x01, %xmm2 + psrld $2, %xmm3 + psrld $7, %xmm0 + pxor %xmm3, %xmm2 + pxor %xmm0, %xmm2 + pxor %xmm1, %xmm2 + pxor %xmm7, %xmm2 + pxor %xmm2, %xmm4 +L_AES_GCM_decrypt_calc_iv_done: + # T = Encrypt counter + pxor %xmm0, %xmm0 + shll $3, %edx + pinsrq $0x00, %rdx, %xmm0 + pxor %xmm0, %xmm4 + pshufd $0x4e, %xmm4, %xmm1 + pshufd $0x4e, %xmm5, %xmm2 + movdqa %xmm5, %xmm3 + movdqa %xmm5, %xmm0 + pclmulqdq $0x11, %xmm4, %xmm3 + pclmulqdq $0x00, %xmm4, %xmm0 + pxor %xmm4, %xmm1 + pxor %xmm5, %xmm2 + pclmulqdq $0x00, %xmm2, %xmm1 + pxor %xmm0, %xmm1 + pxor %xmm3, %xmm1 + movdqa %xmm1, %xmm2 + movdqa %xmm0, %xmm7 + movdqa %xmm3, %xmm4 + pslldq $8, %xmm2 + psrldq $8, %xmm1 + pxor %xmm2, %xmm7 + pxor %xmm1, %xmm4 + movdqa %xmm7, %xmm0 + movdqa %xmm4, %xmm1 + psrld $31, %xmm0 + psrld $31, %xmm1 + pslld $0x01, %xmm7 + pslld $0x01, %xmm4 + movdqa %xmm0, %xmm2 + pslldq $4, %xmm0 + psrldq $12, %xmm2 + pslldq $4, %xmm1 + por %xmm2, %xmm4 + por %xmm0, %xmm7 + por %xmm1, %xmm4 + movdqa %xmm7, %xmm0 + movdqa %xmm7, %xmm1 + movdqa %xmm7, %xmm2 + pslld $31, %xmm0 + pslld $30, %xmm1 + pslld $25, %xmm2 + pxor %xmm1, %xmm0 + pxor %xmm2, %xmm0 + movdqa %xmm0, %xmm1 + psrldq $4, %xmm1 + pslldq $12, %xmm0 + pxor %xmm0, %xmm7 + movdqa %xmm7, %xmm2 + movdqa %xmm7, %xmm3 + movdqa %xmm7, %xmm0 + psrld $0x01, %xmm2 + psrld $2, %xmm3 + psrld $7, %xmm0 + pxor %xmm3, %xmm2 + pxor %xmm0, %xmm2 + pxor %xmm1, %xmm2 + pxor %xmm7, %xmm2 + pxor %xmm2, %xmm4 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm4 + # Encrypt counter + movdqa (%r15), %xmm8 + pxor %xmm4, %xmm8 + aesenc 16(%r15), %xmm8 + aesenc 32(%r15), %xmm8 + aesenc 48(%r15), %xmm8 + aesenc 64(%r15), %xmm8 + aesenc 80(%r15), %xmm8 + aesenc 96(%r15), %xmm8 + aesenc 112(%r15), %xmm8 + aesenc 128(%r15), %xmm8 + aesenc 144(%r15), %xmm8 + cmpl $11, %r10d + movdqa 160(%r15), %xmm9 + jl L_AES_GCM_decrypt_calc_iv_2_aesenc_avx_last + aesenc %xmm9, %xmm8 + aesenc 176(%r15), %xmm8 + cmpl $13, %r10d + movdqa 192(%r15), %xmm9 + jl L_AES_GCM_decrypt_calc_iv_2_aesenc_avx_last + aesenc %xmm9, %xmm8 + aesenc 208(%r15), %xmm8 + movdqa 224(%r15), %xmm9 +L_AES_GCM_decrypt_calc_iv_2_aesenc_avx_last: + aesenclast %xmm9, %xmm8 + movdqa %xmm8, 144(%rsp) +L_AES_GCM_decrypt_iv_done: + # Additional authentication data + movl %r11d, %edx + cmpl $0x00, %edx + je L_AES_GCM_decrypt_calc_aad_done + xorl %ecx, %ecx + cmpl $16, %edx + jl L_AES_GCM_decrypt_calc_aad_lt16 + andl $0xfffffff0, %edx +L_AES_GCM_decrypt_calc_aad_16_loop: + movdqu (%r12,%rcx,1), %xmm8 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm8 + pxor %xmm8, %xmm6 + pshufd $0x4e, %xmm6, %xmm1 + pshufd $0x4e, %xmm5, %xmm2 + movdqa %xmm5, %xmm3 + movdqa %xmm5, %xmm0 + pclmulqdq $0x11, %xmm6, %xmm3 + pclmulqdq $0x00, %xmm6, %xmm0 + pxor %xmm6, %xmm1 + pxor %xmm5, %xmm2 + pclmulqdq $0x00, %xmm2, %xmm1 + pxor %xmm0, %xmm1 + pxor %xmm3, %xmm1 + movdqa %xmm1, %xmm2 + movdqa %xmm0, %xmm7 + movdqa %xmm3, %xmm6 + pslldq $8, %xmm2 + psrldq $8, %xmm1 + pxor %xmm2, %xmm7 + pxor %xmm1, %xmm6 + movdqa %xmm7, %xmm0 + movdqa %xmm6, %xmm1 + psrld $31, %xmm0 + psrld $31, %xmm1 + pslld $0x01, %xmm7 + pslld $0x01, %xmm6 + movdqa %xmm0, %xmm2 + pslldq $4, %xmm0 + psrldq $12, %xmm2 + pslldq $4, %xmm1 + por %xmm2, %xmm6 + por %xmm0, %xmm7 + por %xmm1, %xmm6 + movdqa %xmm7, %xmm0 + movdqa %xmm7, %xmm1 + movdqa %xmm7, %xmm2 + pslld $31, %xmm0 + pslld $30, %xmm1 + pslld $25, %xmm2 + pxor %xmm1, %xmm0 + pxor %xmm2, %xmm0 + movdqa %xmm0, %xmm1 + psrldq $4, %xmm1 + pslldq $12, %xmm0 + pxor %xmm0, %xmm7 + movdqa %xmm7, %xmm2 + movdqa %xmm7, %xmm3 + movdqa %xmm7, %xmm0 + psrld $0x01, %xmm2 + psrld $2, %xmm3 + psrld $7, %xmm0 + pxor %xmm3, %xmm2 + pxor %xmm0, %xmm2 + pxor %xmm1, %xmm2 + pxor %xmm7, %xmm2 + pxor %xmm2, %xmm6 + addl $16, %ecx + cmpl %edx, %ecx + jl L_AES_GCM_decrypt_calc_aad_16_loop + movl %r11d, %edx + cmpl %edx, %ecx + je L_AES_GCM_decrypt_calc_aad_done +L_AES_GCM_decrypt_calc_aad_lt16: + subq $16, %rsp + pxor %xmm8, %xmm8 + xorl %ebx, %ebx + movdqa %xmm8, (%rsp) +L_AES_GCM_decrypt_calc_aad_loop: + movzbl (%r12,%rcx,1), %r13d + movb %r13b, (%rsp,%rbx,1) + incl %ecx + incl %ebx + cmpl %edx, %ecx + jl L_AES_GCM_decrypt_calc_aad_loop + movdqa (%rsp), %xmm8 + addq $16, %rsp + pshufb L_aes_gcm_bswap_mask(%rip), %xmm8 + pxor %xmm8, %xmm6 + pshufd $0x4e, %xmm6, %xmm1 + pshufd $0x4e, %xmm5, %xmm2 + movdqa %xmm5, %xmm3 + movdqa %xmm5, %xmm0 + pclmulqdq $0x11, %xmm6, %xmm3 + pclmulqdq $0x00, %xmm6, %xmm0 + pxor %xmm6, %xmm1 + pxor %xmm5, %xmm2 + pclmulqdq $0x00, %xmm2, %xmm1 + pxor %xmm0, %xmm1 + pxor %xmm3, %xmm1 + movdqa %xmm1, %xmm2 + movdqa %xmm0, %xmm7 + movdqa %xmm3, %xmm6 + pslldq $8, %xmm2 + psrldq $8, %xmm1 + pxor %xmm2, %xmm7 + pxor %xmm1, %xmm6 + movdqa %xmm7, %xmm0 + movdqa %xmm6, %xmm1 + psrld $31, %xmm0 + psrld $31, %xmm1 + pslld $0x01, %xmm7 + pslld $0x01, %xmm6 + movdqa %xmm0, %xmm2 + pslldq $4, %xmm0 + psrldq $12, %xmm2 + pslldq $4, %xmm1 + por %xmm2, %xmm6 + por %xmm0, %xmm7 + por %xmm1, %xmm6 + movdqa %xmm7, %xmm0 + movdqa %xmm7, %xmm1 + movdqa %xmm7, %xmm2 + pslld $31, %xmm0 + pslld $30, %xmm1 + pslld $25, %xmm2 + pxor %xmm1, %xmm0 + pxor %xmm2, %xmm0 + movdqa %xmm0, %xmm1 + psrldq $4, %xmm1 + pslldq $12, %xmm0 + pxor %xmm0, %xmm7 + movdqa %xmm7, %xmm2 + movdqa %xmm7, %xmm3 + movdqa %xmm7, %xmm0 + psrld $0x01, %xmm2 + psrld $2, %xmm3 + psrld $7, %xmm0 + pxor %xmm3, %xmm2 + pxor %xmm0, %xmm2 + pxor %xmm1, %xmm2 + pxor %xmm7, %xmm2 + pxor %xmm2, %xmm6 +L_AES_GCM_decrypt_calc_aad_done: + # Calculate counter and H + pshufb L_aes_gcm_bswap_epi64(%rip), %xmm4 + movdqa %xmm5, %xmm9 + paddd L_aes_gcm_one(%rip), %xmm4 + movdqa %xmm5, %xmm8 + movdqa %xmm4, 128(%rsp) + psrlq $63, %xmm9 + psllq $0x01, %xmm8 + pslldq $8, %xmm9 + por %xmm9, %xmm8 + pshufd $0xff, %xmm5, %xmm5 + psrad $31, %xmm5 + pand L_aes_gcm_mod2_128(%rip), %xmm5 + pxor %xmm8, %xmm5 + xorl %ebx, %ebx + cmpl $0x80, %r9d + movl %r9d, %r13d + jl L_AES_GCM_decrypt_done_128 + andl $0xffffff80, %r13d + movdqa %xmm6, %xmm2 + # H ^ 1 + movdqa %xmm5, (%rsp) + # H ^ 2 + pshufd $0x4e, %xmm5, %xmm9 + pshufd $0x4e, %xmm5, %xmm10 + movdqa %xmm5, %xmm11 + movdqa %xmm5, %xmm8 + pclmulqdq $0x11, %xmm5, %xmm11 + pclmulqdq $0x00, %xmm5, %xmm8 + pxor %xmm5, %xmm9 + pxor %xmm5, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm0 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm0 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm0 + movdqa %xmm0, 16(%rsp) + # H ^ 3 + pshufd $0x4e, %xmm5, %xmm9 + pshufd $0x4e, %xmm0, %xmm10 + movdqa %xmm0, %xmm11 + movdqa %xmm0, %xmm8 + pclmulqdq $0x11, %xmm5, %xmm11 + pclmulqdq $0x00, %xmm5, %xmm8 + pxor %xmm5, %xmm9 + pxor %xmm0, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm1 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm1 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm1 + movdqa %xmm1, 32(%rsp) + # H ^ 4 + pshufd $0x4e, %xmm0, %xmm9 + pshufd $0x4e, %xmm0, %xmm10 + movdqa %xmm0, %xmm11 + movdqa %xmm0, %xmm8 + pclmulqdq $0x11, %xmm0, %xmm11 + pclmulqdq $0x00, %xmm0, %xmm8 + pxor %xmm0, %xmm9 + pxor %xmm0, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm3 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm3 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm3 + movdqa %xmm3, 48(%rsp) + # H ^ 5 + pshufd $0x4e, %xmm0, %xmm9 + pshufd $0x4e, %xmm1, %xmm10 + movdqa %xmm1, %xmm11 + movdqa %xmm1, %xmm8 + pclmulqdq $0x11, %xmm0, %xmm11 + pclmulqdq $0x00, %xmm0, %xmm8 + pxor %xmm0, %xmm9 + pxor %xmm1, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm7 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm7 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm7 + movdqa %xmm7, 64(%rsp) + # H ^ 6 + pshufd $0x4e, %xmm1, %xmm9 + pshufd $0x4e, %xmm1, %xmm10 + movdqa %xmm1, %xmm11 + movdqa %xmm1, %xmm8 + pclmulqdq $0x11, %xmm1, %xmm11 + pclmulqdq $0x00, %xmm1, %xmm8 + pxor %xmm1, %xmm9 + pxor %xmm1, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm7 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm7 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm7 + movdqa %xmm7, 80(%rsp) + # H ^ 7 + pshufd $0x4e, %xmm1, %xmm9 + pshufd $0x4e, %xmm3, %xmm10 + movdqa %xmm3, %xmm11 + movdqa %xmm3, %xmm8 + pclmulqdq $0x11, %xmm1, %xmm11 + pclmulqdq $0x00, %xmm1, %xmm8 + pxor %xmm1, %xmm9 + pxor %xmm3, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm7 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm7 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm7 + movdqa %xmm7, 96(%rsp) + # H ^ 8 + pshufd $0x4e, %xmm3, %xmm9 + pshufd $0x4e, %xmm3, %xmm10 + movdqa %xmm3, %xmm11 + movdqa %xmm3, %xmm8 + pclmulqdq $0x11, %xmm3, %xmm11 + pclmulqdq $0x00, %xmm3, %xmm8 + pxor %xmm3, %xmm9 + pxor %xmm3, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm7 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm7 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm7 + movdqa %xmm7, 112(%rsp) +L_AES_GCM_decrypt_ghash_128: + leaq (%rdi,%rbx,1), %rcx + leaq (%rsi,%rbx,1), %rdx + movdqa 128(%rsp), %xmm8 + movdqa L_aes_gcm_bswap_epi64(%rip), %xmm1 + movdqa %xmm8, %xmm0 + pshufb %xmm1, %xmm8 + movdqa %xmm0, %xmm9 + paddd L_aes_gcm_one(%rip), %xmm9 + pshufb %xmm1, %xmm9 + movdqa %xmm0, %xmm10 + paddd L_aes_gcm_two(%rip), %xmm10 + pshufb %xmm1, %xmm10 + movdqa %xmm0, %xmm11 + paddd L_aes_gcm_three(%rip), %xmm11 + pshufb %xmm1, %xmm11 + movdqa %xmm0, %xmm12 + paddd L_aes_gcm_four(%rip), %xmm12 + pshufb %xmm1, %xmm12 + movdqa %xmm0, %xmm13 + paddd L_aes_gcm_five(%rip), %xmm13 + pshufb %xmm1, %xmm13 + movdqa %xmm0, %xmm14 + paddd L_aes_gcm_six(%rip), %xmm14 + pshufb %xmm1, %xmm14 + movdqa %xmm0, %xmm15 + paddd L_aes_gcm_seven(%rip), %xmm15 + pshufb %xmm1, %xmm15 + paddd L_aes_gcm_eight(%rip), %xmm0 + movdqa (%r15), %xmm7 + movdqa %xmm0, 128(%rsp) + pxor %xmm7, %xmm8 + pxor %xmm7, %xmm9 + pxor %xmm7, %xmm10 + pxor %xmm7, %xmm11 + pxor %xmm7, %xmm12 + pxor %xmm7, %xmm13 + pxor %xmm7, %xmm14 + pxor %xmm7, %xmm15 + movdqa 112(%rsp), %xmm7 + movdqu (%rcx), %xmm0 + aesenc 16(%r15), %xmm8 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm0 + pxor %xmm2, %xmm0 + pshufd $0x4e, %xmm7, %xmm1 + pshufd $0x4e, %xmm0, %xmm5 + pxor %xmm7, %xmm1 + pxor %xmm0, %xmm5 + movdqa %xmm0, %xmm3 + pclmulqdq $0x11, %xmm7, %xmm3 + aesenc 16(%r15), %xmm9 + aesenc 16(%r15), %xmm10 + movdqa %xmm0, %xmm2 + pclmulqdq $0x00, %xmm7, %xmm2 + aesenc 16(%r15), %xmm11 + aesenc 16(%r15), %xmm12 + pclmulqdq $0x00, %xmm5, %xmm1 + aesenc 16(%r15), %xmm13 + aesenc 16(%r15), %xmm14 + aesenc 16(%r15), %xmm15 + pxor %xmm2, %xmm1 + pxor %xmm3, %xmm1 + movdqa 96(%rsp), %xmm7 + movdqu 16(%rcx), %xmm0 + pshufd $0x4e, %xmm7, %xmm4 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm0 + aesenc 32(%r15), %xmm8 + pxor %xmm7, %xmm4 + pshufd $0x4e, %xmm0, %xmm5 + pxor %xmm0, %xmm5 + movdqa %xmm0, %xmm6 + pclmulqdq $0x11, %xmm7, %xmm6 + aesenc 32(%r15), %xmm9 + aesenc 32(%r15), %xmm10 + pclmulqdq $0x00, %xmm0, %xmm7 + aesenc 32(%r15), %xmm11 + aesenc 32(%r15), %xmm12 + pclmulqdq $0x00, %xmm5, %xmm4 + aesenc 32(%r15), %xmm13 + aesenc 32(%r15), %xmm14 + aesenc 32(%r15), %xmm15 + pxor %xmm7, %xmm1 + pxor %xmm7, %xmm2 + pxor %xmm6, %xmm1 + pxor %xmm6, %xmm3 + pxor %xmm4, %xmm1 + movdqa 80(%rsp), %xmm7 + movdqu 32(%rcx), %xmm0 + pshufd $0x4e, %xmm7, %xmm4 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm0 + aesenc 48(%r15), %xmm8 + pxor %xmm7, %xmm4 + pshufd $0x4e, %xmm0, %xmm5 + pxor %xmm0, %xmm5 + movdqa %xmm0, %xmm6 + pclmulqdq $0x11, %xmm7, %xmm6 + aesenc 48(%r15), %xmm9 + aesenc 48(%r15), %xmm10 + pclmulqdq $0x00, %xmm0, %xmm7 + aesenc 48(%r15), %xmm11 + aesenc 48(%r15), %xmm12 + pclmulqdq $0x00, %xmm5, %xmm4 + aesenc 48(%r15), %xmm13 + aesenc 48(%r15), %xmm14 + aesenc 48(%r15), %xmm15 + pxor %xmm7, %xmm1 + pxor %xmm7, %xmm2 + pxor %xmm6, %xmm1 + pxor %xmm6, %xmm3 + pxor %xmm4, %xmm1 + movdqa 64(%rsp), %xmm7 + movdqu 48(%rcx), %xmm0 + pshufd $0x4e, %xmm7, %xmm4 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm0 + aesenc 64(%r15), %xmm8 + pxor %xmm7, %xmm4 + pshufd $0x4e, %xmm0, %xmm5 + pxor %xmm0, %xmm5 + movdqa %xmm0, %xmm6 + pclmulqdq $0x11, %xmm7, %xmm6 + aesenc 64(%r15), %xmm9 + aesenc 64(%r15), %xmm10 + pclmulqdq $0x00, %xmm0, %xmm7 + aesenc 64(%r15), %xmm11 + aesenc 64(%r15), %xmm12 + pclmulqdq $0x00, %xmm5, %xmm4 + aesenc 64(%r15), %xmm13 + aesenc 64(%r15), %xmm14 + aesenc 64(%r15), %xmm15 + pxor %xmm7, %xmm1 + pxor %xmm7, %xmm2 + pxor %xmm6, %xmm1 + pxor %xmm6, %xmm3 + pxor %xmm4, %xmm1 + movdqa 48(%rsp), %xmm7 + movdqu 64(%rcx), %xmm0 + pshufd $0x4e, %xmm7, %xmm4 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm0 + aesenc 80(%r15), %xmm8 + pxor %xmm7, %xmm4 + pshufd $0x4e, %xmm0, %xmm5 + pxor %xmm0, %xmm5 + movdqa %xmm0, %xmm6 + pclmulqdq $0x11, %xmm7, %xmm6 + aesenc 80(%r15), %xmm9 + aesenc 80(%r15), %xmm10 + pclmulqdq $0x00, %xmm0, %xmm7 + aesenc 80(%r15), %xmm11 + aesenc 80(%r15), %xmm12 + pclmulqdq $0x00, %xmm5, %xmm4 + aesenc 80(%r15), %xmm13 + aesenc 80(%r15), %xmm14 + aesenc 80(%r15), %xmm15 + pxor %xmm7, %xmm1 + pxor %xmm7, %xmm2 + pxor %xmm6, %xmm1 + pxor %xmm6, %xmm3 + pxor %xmm4, %xmm1 + movdqa 32(%rsp), %xmm7 + movdqu 80(%rcx), %xmm0 + pshufd $0x4e, %xmm7, %xmm4 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm0 + aesenc 96(%r15), %xmm8 + pxor %xmm7, %xmm4 + pshufd $0x4e, %xmm0, %xmm5 + pxor %xmm0, %xmm5 + movdqa %xmm0, %xmm6 + pclmulqdq $0x11, %xmm7, %xmm6 + aesenc 96(%r15), %xmm9 + aesenc 96(%r15), %xmm10 + pclmulqdq $0x00, %xmm0, %xmm7 + aesenc 96(%r15), %xmm11 + aesenc 96(%r15), %xmm12 + pclmulqdq $0x00, %xmm5, %xmm4 + aesenc 96(%r15), %xmm13 + aesenc 96(%r15), %xmm14 + aesenc 96(%r15), %xmm15 + pxor %xmm7, %xmm1 + pxor %xmm7, %xmm2 + pxor %xmm6, %xmm1 + pxor %xmm6, %xmm3 + pxor %xmm4, %xmm1 + movdqa 16(%rsp), %xmm7 + movdqu 96(%rcx), %xmm0 + pshufd $0x4e, %xmm7, %xmm4 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm0 + aesenc 112(%r15), %xmm8 + pxor %xmm7, %xmm4 + pshufd $0x4e, %xmm0, %xmm5 + pxor %xmm0, %xmm5 + movdqa %xmm0, %xmm6 + pclmulqdq $0x11, %xmm7, %xmm6 + aesenc 112(%r15), %xmm9 + aesenc 112(%r15), %xmm10 + pclmulqdq $0x00, %xmm0, %xmm7 + aesenc 112(%r15), %xmm11 + aesenc 112(%r15), %xmm12 + pclmulqdq $0x00, %xmm5, %xmm4 + aesenc 112(%r15), %xmm13 + aesenc 112(%r15), %xmm14 + aesenc 112(%r15), %xmm15 + pxor %xmm7, %xmm1 + pxor %xmm7, %xmm2 + pxor %xmm6, %xmm1 + pxor %xmm6, %xmm3 + pxor %xmm4, %xmm1 + movdqa (%rsp), %xmm7 + movdqu 112(%rcx), %xmm0 + pshufd $0x4e, %xmm7, %xmm4 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm0 + aesenc 128(%r15), %xmm8 + pxor %xmm7, %xmm4 + pshufd $0x4e, %xmm0, %xmm5 + pxor %xmm0, %xmm5 + movdqa %xmm0, %xmm6 + pclmulqdq $0x11, %xmm7, %xmm6 + aesenc 128(%r15), %xmm9 + aesenc 128(%r15), %xmm10 + pclmulqdq $0x00, %xmm0, %xmm7 + aesenc 128(%r15), %xmm11 + aesenc 128(%r15), %xmm12 + pclmulqdq $0x00, %xmm5, %xmm4 + aesenc 128(%r15), %xmm13 + aesenc 128(%r15), %xmm14 + aesenc 128(%r15), %xmm15 + pxor %xmm7, %xmm1 + pxor %xmm7, %xmm2 + pxor %xmm6, %xmm1 + pxor %xmm6, %xmm3 + pxor %xmm4, %xmm1 + movdqa %xmm1, %xmm5 + psrldq $8, %xmm1 + pslldq $8, %xmm5 + aesenc 144(%r15), %xmm8 + pxor %xmm5, %xmm2 + pxor %xmm1, %xmm3 + movdqa %xmm2, %xmm7 + movdqa %xmm2, %xmm4 + movdqa %xmm2, %xmm5 + aesenc 144(%r15), %xmm9 + pslld $31, %xmm7 + pslld $30, %xmm4 + pslld $25, %xmm5 + aesenc 144(%r15), %xmm10 + pxor %xmm4, %xmm7 + pxor %xmm5, %xmm7 + aesenc 144(%r15), %xmm11 + movdqa %xmm7, %xmm4 + pslldq $12, %xmm7 + psrldq $4, %xmm4 + aesenc 144(%r15), %xmm12 + pxor %xmm7, %xmm2 + movdqa %xmm2, %xmm5 + movdqa %xmm2, %xmm1 + movdqa %xmm2, %xmm0 + aesenc 144(%r15), %xmm13 + psrld $0x01, %xmm5 + psrld $2, %xmm1 + psrld $7, %xmm0 + aesenc 144(%r15), %xmm14 + pxor %xmm1, %xmm5 + pxor %xmm0, %xmm5 + aesenc 144(%r15), %xmm15 + pxor %xmm4, %xmm5 + pxor %xmm5, %xmm2 + pxor %xmm3, %xmm2 + cmpl $11, %r10d + movdqa 160(%r15), %xmm7 + jl L_AES_GCM_decrypt_aesenc_128_ghash_avx_done + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + movdqa 176(%r15), %xmm7 + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + cmpl $13, %r10d + movdqa 192(%r15), %xmm7 + jl L_AES_GCM_decrypt_aesenc_128_ghash_avx_done + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + movdqa 208(%r15), %xmm7 + aesenc %xmm7, %xmm8 + aesenc %xmm7, %xmm9 + aesenc %xmm7, %xmm10 + aesenc %xmm7, %xmm11 + aesenc %xmm7, %xmm12 + aesenc %xmm7, %xmm13 + aesenc %xmm7, %xmm14 + aesenc %xmm7, %xmm15 + movdqa 224(%r15), %xmm7 +L_AES_GCM_decrypt_aesenc_128_ghash_avx_done: + aesenclast %xmm7, %xmm8 + aesenclast %xmm7, %xmm9 + movdqu (%rcx), %xmm0 + movdqu 16(%rcx), %xmm1 + pxor %xmm0, %xmm8 + pxor %xmm1, %xmm9 + movdqu %xmm8, (%rdx) + movdqu %xmm9, 16(%rdx) + aesenclast %xmm7, %xmm10 + aesenclast %xmm7, %xmm11 + movdqu 32(%rcx), %xmm0 + movdqu 48(%rcx), %xmm1 + pxor %xmm0, %xmm10 + pxor %xmm1, %xmm11 + movdqu %xmm10, 32(%rdx) + movdqu %xmm11, 48(%rdx) + aesenclast %xmm7, %xmm12 + aesenclast %xmm7, %xmm13 + movdqu 64(%rcx), %xmm0 + movdqu 80(%rcx), %xmm1 + pxor %xmm0, %xmm12 + pxor %xmm1, %xmm13 + movdqu %xmm12, 64(%rdx) + movdqu %xmm13, 80(%rdx) + aesenclast %xmm7, %xmm14 + aesenclast %xmm7, %xmm15 + movdqu 96(%rcx), %xmm0 + movdqu 112(%rcx), %xmm1 + pxor %xmm0, %xmm14 + pxor %xmm1, %xmm15 + movdqu %xmm14, 96(%rdx) + movdqu %xmm15, 112(%rdx) + addl $0x80, %ebx + cmpl %r13d, %ebx + jl L_AES_GCM_decrypt_ghash_128 + movdqa %xmm2, %xmm6 + movdqa (%rsp), %xmm5 +L_AES_GCM_decrypt_done_128: + movl %r9d, %edx + cmpl %edx, %ebx + jge L_AES_GCM_decrypt_done_dec + movl %r9d, %r13d + andl $0xfffffff0, %r13d + cmpl %r13d, %ebx + jge L_AES_GCM_decrypt_last_block_done +L_AES_GCM_decrypt_last_block_start: + leaq (%rdi,%rbx,1), %rcx + leaq (%rsi,%rbx,1), %rdx + movdqu (%rcx), %xmm1 + movdqa %xmm5, %xmm0 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm1 + pxor %xmm6, %xmm1 + movdqa 128(%rsp), %xmm8 + movdqa %xmm8, %xmm9 + pshufb L_aes_gcm_bswap_epi64(%rip), %xmm8 + paddd L_aes_gcm_one(%rip), %xmm9 + pxor (%r15), %xmm8 + movdqa %xmm9, 128(%rsp) + movdqa %xmm1, %xmm10 + pclmulqdq $16, %xmm0, %xmm10 + aesenc 16(%r15), %xmm8 + aesenc 32(%r15), %xmm8 + movdqa %xmm1, %xmm11 + pclmulqdq $0x01, %xmm0, %xmm11 + aesenc 48(%r15), %xmm8 + aesenc 64(%r15), %xmm8 + movdqa %xmm1, %xmm12 + pclmulqdq $0x00, %xmm0, %xmm12 + aesenc 80(%r15), %xmm8 + movdqa %xmm1, %xmm1 + pclmulqdq $0x11, %xmm0, %xmm1 + aesenc 96(%r15), %xmm8 + pxor %xmm11, %xmm10 + movdqa %xmm10, %xmm2 + psrldq $8, %xmm10 + pslldq $8, %xmm2 + aesenc 112(%r15), %xmm8 + movdqa %xmm1, %xmm3 + pxor %xmm12, %xmm2 + pxor %xmm10, %xmm3 + movdqa L_aes_gcm_mod2_128(%rip), %xmm0 + movdqa %xmm2, %xmm11 + pclmulqdq $16, %xmm0, %xmm11 + aesenc 128(%r15), %xmm8 + pshufd $0x4e, %xmm2, %xmm10 + pxor %xmm11, %xmm10 + movdqa %xmm10, %xmm11 + pclmulqdq $16, %xmm0, %xmm11 + aesenc 144(%r15), %xmm8 + pshufd $0x4e, %xmm10, %xmm6 + pxor %xmm11, %xmm6 + pxor %xmm3, %xmm6 + cmpl $11, %r10d + movdqa 160(%r15), %xmm9 + jl L_AES_GCM_decrypt_aesenc_gfmul_last + aesenc %xmm9, %xmm8 + aesenc 176(%r15), %xmm8 + cmpl $13, %r10d + movdqa 192(%r15), %xmm9 + jl L_AES_GCM_decrypt_aesenc_gfmul_last + aesenc %xmm9, %xmm8 + aesenc 208(%r15), %xmm8 + movdqa 224(%r15), %xmm9 +L_AES_GCM_decrypt_aesenc_gfmul_last: + aesenclast %xmm9, %xmm8 + movdqu (%rcx), %xmm9 + pxor %xmm9, %xmm8 + movdqu %xmm8, (%rdx) + addl $16, %ebx + cmpl %r13d, %ebx + jl L_AES_GCM_decrypt_last_block_start +L_AES_GCM_decrypt_last_block_done: + movl %r9d, %ecx + movl %ecx, %edx + andl $15, %ecx + jz L_AES_GCM_decrypt_aesenc_last15_dec_avx_done + movdqa 128(%rsp), %xmm4 + pshufb L_aes_gcm_bswap_epi64(%rip), %xmm4 + pxor (%r15), %xmm4 + aesenc 16(%r15), %xmm4 + aesenc 32(%r15), %xmm4 + aesenc 48(%r15), %xmm4 + aesenc 64(%r15), %xmm4 + aesenc 80(%r15), %xmm4 + aesenc 96(%r15), %xmm4 + aesenc 112(%r15), %xmm4 + aesenc 128(%r15), %xmm4 + aesenc 144(%r15), %xmm4 + cmpl $11, %r10d + movdqa 160(%r15), %xmm9 + jl L_AES_GCM_decrypt_aesenc_last15_dec_avx_aesenc_avx_last + aesenc %xmm9, %xmm4 + aesenc 176(%r15), %xmm4 + cmpl $13, %r10d + movdqa 192(%r15), %xmm9 + jl L_AES_GCM_decrypt_aesenc_last15_dec_avx_aesenc_avx_last + aesenc %xmm9, %xmm4 + aesenc 208(%r15), %xmm4 + movdqa 224(%r15), %xmm9 +L_AES_GCM_decrypt_aesenc_last15_dec_avx_aesenc_avx_last: + aesenclast %xmm9, %xmm4 + subq $32, %rsp + xorl %ecx, %ecx + movdqa %xmm4, (%rsp) + pxor %xmm0, %xmm0 + movdqa %xmm0, 16(%rsp) +L_AES_GCM_decrypt_aesenc_last15_dec_avx_loop: + movzbl (%rdi,%rbx,1), %r13d + movb %r13b, 16(%rsp,%rcx,1) + xorb (%rsp,%rcx,1), %r13b + movb %r13b, (%rsi,%rbx,1) + incl %ebx + incl %ecx + cmpl %edx, %ebx + jl L_AES_GCM_decrypt_aesenc_last15_dec_avx_loop + movdqa 16(%rsp), %xmm4 + addq $32, %rsp + pshufb L_aes_gcm_bswap_mask(%rip), %xmm4 + pxor %xmm4, %xmm6 + pshufd $0x4e, %xmm5, %xmm9 + pshufd $0x4e, %xmm6, %xmm10 + movdqa %xmm6, %xmm11 + movdqa %xmm6, %xmm8 + pclmulqdq $0x11, %xmm5, %xmm11 + pclmulqdq $0x00, %xmm5, %xmm8 + pxor %xmm5, %xmm9 + pxor %xmm6, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm6 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm6 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm6 +L_AES_GCM_decrypt_aesenc_last15_dec_avx_done: +L_AES_GCM_decrypt_done_dec: + movl %r9d, %edx + movl %r11d, %ecx + shlq $3, %rdx + shlq $3, %rcx + pinsrq $0x00, %rdx, %xmm0 + pinsrq $0x01, %rcx, %xmm0 + pxor %xmm0, %xmm6 + pshufd $0x4e, %xmm5, %xmm9 + pshufd $0x4e, %xmm6, %xmm10 + movdqa %xmm6, %xmm11 + movdqa %xmm6, %xmm8 + pclmulqdq $0x11, %xmm5, %xmm11 + pclmulqdq $0x00, %xmm5, %xmm8 + pxor %xmm5, %xmm9 + pxor %xmm6, %xmm10 + pclmulqdq $0x00, %xmm10, %xmm9 + pxor %xmm8, %xmm9 + pxor %xmm11, %xmm9 + movdqa %xmm9, %xmm10 + movdqa %xmm11, %xmm6 + pslldq $8, %xmm10 + psrldq $8, %xmm9 + pxor %xmm10, %xmm8 + pxor %xmm9, %xmm6 + movdqa %xmm8, %xmm12 + movdqa %xmm8, %xmm13 + movdqa %xmm8, %xmm14 + pslld $31, %xmm12 + pslld $30, %xmm13 + pslld $25, %xmm14 + pxor %xmm13, %xmm12 + pxor %xmm14, %xmm12 + movdqa %xmm12, %xmm13 + psrldq $4, %xmm13 + pslldq $12, %xmm12 + pxor %xmm12, %xmm8 + movdqa %xmm8, %xmm14 + movdqa %xmm8, %xmm10 + movdqa %xmm8, %xmm9 + psrld $0x01, %xmm14 + psrld $2, %xmm10 + psrld $7, %xmm9 + pxor %xmm10, %xmm14 + pxor %xmm9, %xmm14 + pxor %xmm13, %xmm14 + pxor %xmm8, %xmm14 + pxor %xmm14, %xmm6 + pshufb L_aes_gcm_bswap_mask(%rip), %xmm6 + movdqa 144(%rsp), %xmm0 + pxor %xmm6, %xmm0 + cmpl $16, %r14d + je L_AES_GCM_decrypt_cmp_tag_16 + subq $16, %rsp + xorq %rcx, %rcx + xorq %rbx, %rbx + movdqa %xmm0, (%rsp) +L_AES_GCM_decrypt_cmp_tag_loop: + movzbl (%rsp,%rcx,1), %r13d + xorb (%r8,%rcx,1), %r13b + orb %r13b, %bl + incl %ecx + cmpl %r14d, %ecx + jne L_AES_GCM_decrypt_cmp_tag_loop + cmpb $0x00, %bl + sete %bl + addq $16, %rsp + xorq %rcx, %rcx + jmp L_AES_GCM_decrypt_cmp_tag_done +L_AES_GCM_decrypt_cmp_tag_16: + movdqu (%r8), %xmm1 + pcmpeqb %xmm1, %xmm0 + pmovmskb %xmm0, %rdx + # %%edx == 0xFFFF then return 1 else => return 0 + xorl %ebx, %ebx + cmpl $0xffff, %edx + sete %bl +L_AES_GCM_decrypt_cmp_tag_done: + movl %ebx, (%rbp) + addq $0xa8, %rsp + popq %rbp + popq %r15 + popq %r14 + popq %rbx + popq %r12 + popq %r13 + repz retq +#ifndef __APPLE__ +.size AES_GCM_decrypt,.-AES_GCM_decrypt +#endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX1 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx1_aes_gcm_one: +.quad 0x0, 0x1 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx1_aes_gcm_two: +.quad 0x0, 0x2 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx1_aes_gcm_three: +.quad 0x0, 0x3 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx1_aes_gcm_four: +.quad 0x0, 0x4 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx1_aes_gcm_five: +.quad 0x0, 0x5 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx1_aes_gcm_six: +.quad 0x0, 0x6 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx1_aes_gcm_seven: +.quad 0x0, 0x7 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx1_aes_gcm_eight: +.quad 0x0, 0x8 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx1_aes_gcm_bswap_epi64: +.quad 0x1020304050607, 0x8090a0b0c0d0e0f +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx1_aes_gcm_bswap_mask: +.quad 0x8090a0b0c0d0e0f, 0x1020304050607 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx1_aes_gcm_mod2_128: +.quad 0x1, 0xc200000000000000 +#ifndef __APPLE__ +.text +.globl AES_GCM_encrypt_avx1 +.type AES_GCM_encrypt_avx1,@function +.align 4 +AES_GCM_encrypt_avx1: +#else +.section __TEXT,__text +.globl _AES_GCM_encrypt_avx1 +.p2align 2 +_AES_GCM_encrypt_avx1: +#endif /* __APPLE__ */ + pushq %r13 + pushq %r12 + pushq %rbx + pushq %r14 + pushq %r15 + movq %rdx, %r12 + movq %rcx, %rax + movl 48(%rsp), %r11d + movl 56(%rsp), %ebx + movl 64(%rsp), %r14d + movq 72(%rsp), %r15 + movl 80(%rsp), %r10d + subq $0xa0, %rsp + vpxor %xmm4, %xmm4, %xmm4 + vpxor %xmm6, %xmm6, %xmm6 + movl %ebx, %edx + cmpl $12, %edx + jne L_AES_GCM_encrypt_avx1_iv_not_12 + # # Calculate values when IV is 12 bytes + # Set counter based on IV + movl $0x1000000, %ecx + vpinsrq $0x00, (%rax), %xmm4, %xmm4 + vpinsrd $2, 8(%rax), %xmm4, %xmm4 + vpinsrd $3, %ecx, %xmm4, %xmm4 + # H = Encrypt X(=0) and T = Encrypt counter + vmovdqa (%r15), %xmm5 + vpxor %xmm5, %xmm4, %xmm1 + vmovdqa 16(%r15), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 32(%r15), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 48(%r15), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 64(%r15), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 80(%r15), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 96(%r15), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 112(%r15), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 128(%r15), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 144(%r15), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + cmpl $11, %r10d + vmovdqa 160(%r15), %xmm7 + jl L_AES_GCM_encrypt_avx1_calc_iv_12_last + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 176(%r15), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + cmpl $13, %r10d + vmovdqa 192(%r15), %xmm7 + jl L_AES_GCM_encrypt_avx1_calc_iv_12_last + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 208(%r15), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 224(%r15), %xmm7 +L_AES_GCM_encrypt_avx1_calc_iv_12_last: + vaesenclast %xmm7, %xmm5, %xmm5 + vaesenclast %xmm7, %xmm1, %xmm1 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm5, %xmm5 + vmovdqa %xmm1, 144(%rsp) + jmp L_AES_GCM_encrypt_avx1_iv_done +L_AES_GCM_encrypt_avx1_iv_not_12: + # Calculate values when IV is not 12 bytes + # H = Encrypt X(=0) + vmovdqa (%r15), %xmm5 + vaesenc 16(%r15), %xmm5, %xmm5 + vaesenc 32(%r15), %xmm5, %xmm5 + vaesenc 48(%r15), %xmm5, %xmm5 + vaesenc 64(%r15), %xmm5, %xmm5 + vaesenc 80(%r15), %xmm5, %xmm5 + vaesenc 96(%r15), %xmm5, %xmm5 + vaesenc 112(%r15), %xmm5, %xmm5 + vaesenc 128(%r15), %xmm5, %xmm5 + vaesenc 144(%r15), %xmm5, %xmm5 + cmpl $11, %r10d + vmovdqa 160(%r15), %xmm9 + jl L_AES_GCM_encrypt_avx1_calc_iv_1_aesenc_avx_last + vaesenc %xmm9, %xmm5, %xmm5 + vaesenc 176(%r15), %xmm5, %xmm5 + cmpl $13, %r10d + vmovdqa 192(%r15), %xmm9 + jl L_AES_GCM_encrypt_avx1_calc_iv_1_aesenc_avx_last + vaesenc %xmm9, %xmm5, %xmm5 + vaesenc 208(%r15), %xmm5, %xmm5 + vmovdqa 224(%r15), %xmm9 +L_AES_GCM_encrypt_avx1_calc_iv_1_aesenc_avx_last: + vaesenclast %xmm9, %xmm5, %xmm5 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm5, %xmm5 + # Calc counter + # Initialization vector + cmpl $0x00, %edx + movq $0x00, %rcx + je L_AES_GCM_encrypt_avx1_calc_iv_done + cmpl $16, %edx + jl L_AES_GCM_encrypt_avx1_calc_iv_lt16 + andl $0xfffffff0, %edx +L_AES_GCM_encrypt_avx1_calc_iv_16_loop: + vmovdqu (%rax,%rcx,1), %xmm8 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm8, %xmm8 + vpxor %xmm8, %xmm4, %xmm4 + # ghash_gfmul_avx + vpshufd $0x4e, %xmm4, %xmm1 + vpshufd $0x4e, %xmm5, %xmm2 + vpclmulqdq $0x11, %xmm4, %xmm5, %xmm3 + vpclmulqdq $0x00, %xmm4, %xmm5, %xmm0 + vpxor %xmm4, %xmm1, %xmm1 + vpxor %xmm5, %xmm2, %xmm2 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vmovdqa %xmm0, %xmm7 + vmovdqa %xmm3, %xmm4 + vpslldq $8, %xmm1, %xmm2 + vpsrldq $8, %xmm1, %xmm1 + vpxor %xmm2, %xmm7, %xmm7 + vpxor %xmm1, %xmm4, %xmm4 + vpsrld $31, %xmm7, %xmm0 + vpsrld $31, %xmm4, %xmm1 + vpslld $0x01, %xmm7, %xmm7 + vpslld $0x01, %xmm4, %xmm4 + vpsrldq $12, %xmm0, %xmm2 + vpslldq $4, %xmm0, %xmm0 + vpslldq $4, %xmm1, %xmm1 + vpor %xmm2, %xmm4, %xmm4 + vpor %xmm0, %xmm7, %xmm7 + vpor %xmm1, %xmm4, %xmm4 + vpslld $31, %xmm7, %xmm0 + vpslld $30, %xmm7, %xmm1 + vpslld $25, %xmm7, %xmm2 + vpxor %xmm1, %xmm0, %xmm0 + vpxor %xmm2, %xmm0, %xmm0 + vmovdqa %xmm0, %xmm1 + vpsrldq $4, %xmm1, %xmm1 + vpslldq $12, %xmm0, %xmm0 + vpxor %xmm0, %xmm7, %xmm7 + vpsrld $0x01, %xmm7, %xmm2 + vpsrld $2, %xmm7, %xmm3 + vpsrld $7, %xmm7, %xmm0 + vpxor %xmm3, %xmm2, %xmm2 + vpxor %xmm0, %xmm2, %xmm2 + vpxor %xmm1, %xmm2, %xmm2 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm2, %xmm4, %xmm4 + addl $16, %ecx + cmpl %edx, %ecx + jl L_AES_GCM_encrypt_avx1_calc_iv_16_loop + movl %ebx, %edx + cmpl %edx, %ecx + je L_AES_GCM_encrypt_avx1_calc_iv_done +L_AES_GCM_encrypt_avx1_calc_iv_lt16: + subq $16, %rsp + vpxor %xmm8, %xmm8, %xmm8 + xorl %ebx, %ebx + vmovdqa %xmm8, (%rsp) +L_AES_GCM_encrypt_avx1_calc_iv_loop: + movzbl (%rax,%rcx,1), %r13d + movb %r13b, (%rsp,%rbx,1) + incl %ecx + incl %ebx + cmpl %edx, %ecx + jl L_AES_GCM_encrypt_avx1_calc_iv_loop + vmovdqa (%rsp), %xmm8 + addq $16, %rsp + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm8, %xmm8 + vpxor %xmm8, %xmm4, %xmm4 + # ghash_gfmul_avx + vpshufd $0x4e, %xmm4, %xmm1 + vpshufd $0x4e, %xmm5, %xmm2 + vpclmulqdq $0x11, %xmm4, %xmm5, %xmm3 + vpclmulqdq $0x00, %xmm4, %xmm5, %xmm0 + vpxor %xmm4, %xmm1, %xmm1 + vpxor %xmm5, %xmm2, %xmm2 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vmovdqa %xmm0, %xmm7 + vmovdqa %xmm3, %xmm4 + vpslldq $8, %xmm1, %xmm2 + vpsrldq $8, %xmm1, %xmm1 + vpxor %xmm2, %xmm7, %xmm7 + vpxor %xmm1, %xmm4, %xmm4 + vpsrld $31, %xmm7, %xmm0 + vpsrld $31, %xmm4, %xmm1 + vpslld $0x01, %xmm7, %xmm7 + vpslld $0x01, %xmm4, %xmm4 + vpsrldq $12, %xmm0, %xmm2 + vpslldq $4, %xmm0, %xmm0 + vpslldq $4, %xmm1, %xmm1 + vpor %xmm2, %xmm4, %xmm4 + vpor %xmm0, %xmm7, %xmm7 + vpor %xmm1, %xmm4, %xmm4 + vpslld $31, %xmm7, %xmm0 + vpslld $30, %xmm7, %xmm1 + vpslld $25, %xmm7, %xmm2 + vpxor %xmm1, %xmm0, %xmm0 + vpxor %xmm2, %xmm0, %xmm0 + vmovdqa %xmm0, %xmm1 + vpsrldq $4, %xmm1, %xmm1 + vpslldq $12, %xmm0, %xmm0 + vpxor %xmm0, %xmm7, %xmm7 + vpsrld $0x01, %xmm7, %xmm2 + vpsrld $2, %xmm7, %xmm3 + vpsrld $7, %xmm7, %xmm0 + vpxor %xmm3, %xmm2, %xmm2 + vpxor %xmm0, %xmm2, %xmm2 + vpxor %xmm1, %xmm2, %xmm2 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm2, %xmm4, %xmm4 +L_AES_GCM_encrypt_avx1_calc_iv_done: + # T = Encrypt counter + vpxor %xmm0, %xmm0, %xmm0 + shll $3, %edx + vpinsrq $0x00, %rdx, %xmm0, %xmm0 + vpxor %xmm0, %xmm4, %xmm4 + # ghash_gfmul_avx + vpshufd $0x4e, %xmm4, %xmm1 + vpshufd $0x4e, %xmm5, %xmm2 + vpclmulqdq $0x11, %xmm4, %xmm5, %xmm3 + vpclmulqdq $0x00, %xmm4, %xmm5, %xmm0 + vpxor %xmm4, %xmm1, %xmm1 + vpxor %xmm5, %xmm2, %xmm2 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vmovdqa %xmm0, %xmm7 + vmovdqa %xmm3, %xmm4 + vpslldq $8, %xmm1, %xmm2 + vpsrldq $8, %xmm1, %xmm1 + vpxor %xmm2, %xmm7, %xmm7 + vpxor %xmm1, %xmm4, %xmm4 + vpsrld $31, %xmm7, %xmm0 + vpsrld $31, %xmm4, %xmm1 + vpslld $0x01, %xmm7, %xmm7 + vpslld $0x01, %xmm4, %xmm4 + vpsrldq $12, %xmm0, %xmm2 + vpslldq $4, %xmm0, %xmm0 + vpslldq $4, %xmm1, %xmm1 + vpor %xmm2, %xmm4, %xmm4 + vpor %xmm0, %xmm7, %xmm7 + vpor %xmm1, %xmm4, %xmm4 + vpslld $31, %xmm7, %xmm0 + vpslld $30, %xmm7, %xmm1 + vpslld $25, %xmm7, %xmm2 + vpxor %xmm1, %xmm0, %xmm0 + vpxor %xmm2, %xmm0, %xmm0 + vmovdqa %xmm0, %xmm1 + vpsrldq $4, %xmm1, %xmm1 + vpslldq $12, %xmm0, %xmm0 + vpxor %xmm0, %xmm7, %xmm7 + vpsrld $0x01, %xmm7, %xmm2 + vpsrld $2, %xmm7, %xmm3 + vpsrld $7, %xmm7, %xmm0 + vpxor %xmm3, %xmm2, %xmm2 + vpxor %xmm0, %xmm2, %xmm2 + vpxor %xmm1, %xmm2, %xmm2 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm2, %xmm4, %xmm4 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm4, %xmm4 + # Encrypt counter + vmovdqa (%r15), %xmm8 + vpxor %xmm4, %xmm8, %xmm8 + vaesenc 16(%r15), %xmm8, %xmm8 + vaesenc 32(%r15), %xmm8, %xmm8 + vaesenc 48(%r15), %xmm8, %xmm8 + vaesenc 64(%r15), %xmm8, %xmm8 + vaesenc 80(%r15), %xmm8, %xmm8 + vaesenc 96(%r15), %xmm8, %xmm8 + vaesenc 112(%r15), %xmm8, %xmm8 + vaesenc 128(%r15), %xmm8, %xmm8 + vaesenc 144(%r15), %xmm8, %xmm8 + cmpl $11, %r10d + vmovdqa 160(%r15), %xmm9 + jl L_AES_GCM_encrypt_avx1_calc_iv_2_aesenc_avx_last + vaesenc %xmm9, %xmm8, %xmm8 + vaesenc 176(%r15), %xmm8, %xmm8 + cmpl $13, %r10d + vmovdqa 192(%r15), %xmm9 + jl L_AES_GCM_encrypt_avx1_calc_iv_2_aesenc_avx_last + vaesenc %xmm9, %xmm8, %xmm8 + vaesenc 208(%r15), %xmm8, %xmm8 + vmovdqa 224(%r15), %xmm9 +L_AES_GCM_encrypt_avx1_calc_iv_2_aesenc_avx_last: + vaesenclast %xmm9, %xmm8, %xmm8 + vmovdqa %xmm8, 144(%rsp) +L_AES_GCM_encrypt_avx1_iv_done: + # Additional authentication data + movl %r11d, %edx + cmpl $0x00, %edx + je L_AES_GCM_encrypt_avx1_calc_aad_done + xorl %ecx, %ecx + cmpl $16, %edx + jl L_AES_GCM_encrypt_avx1_calc_aad_lt16 + andl $0xfffffff0, %edx +L_AES_GCM_encrypt_avx1_calc_aad_16_loop: + vmovdqu (%r12,%rcx,1), %xmm8 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm8, %xmm8 + vpxor %xmm8, %xmm6, %xmm6 + # ghash_gfmul_avx + vpshufd $0x4e, %xmm6, %xmm1 + vpshufd $0x4e, %xmm5, %xmm2 + vpclmulqdq $0x11, %xmm6, %xmm5, %xmm3 + vpclmulqdq $0x00, %xmm6, %xmm5, %xmm0 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm5, %xmm2, %xmm2 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vmovdqa %xmm0, %xmm7 + vmovdqa %xmm3, %xmm6 + vpslldq $8, %xmm1, %xmm2 + vpsrldq $8, %xmm1, %xmm1 + vpxor %xmm2, %xmm7, %xmm7 + vpxor %xmm1, %xmm6, %xmm6 + vpsrld $31, %xmm7, %xmm0 + vpsrld $31, %xmm6, %xmm1 + vpslld $0x01, %xmm7, %xmm7 + vpslld $0x01, %xmm6, %xmm6 + vpsrldq $12, %xmm0, %xmm2 + vpslldq $4, %xmm0, %xmm0 + vpslldq $4, %xmm1, %xmm1 + vpor %xmm2, %xmm6, %xmm6 + vpor %xmm0, %xmm7, %xmm7 + vpor %xmm1, %xmm6, %xmm6 + vpslld $31, %xmm7, %xmm0 + vpslld $30, %xmm7, %xmm1 + vpslld $25, %xmm7, %xmm2 + vpxor %xmm1, %xmm0, %xmm0 + vpxor %xmm2, %xmm0, %xmm0 + vmovdqa %xmm0, %xmm1 + vpsrldq $4, %xmm1, %xmm1 + vpslldq $12, %xmm0, %xmm0 + vpxor %xmm0, %xmm7, %xmm7 + vpsrld $0x01, %xmm7, %xmm2 + vpsrld $2, %xmm7, %xmm3 + vpsrld $7, %xmm7, %xmm0 + vpxor %xmm3, %xmm2, %xmm2 + vpxor %xmm0, %xmm2, %xmm2 + vpxor %xmm1, %xmm2, %xmm2 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm2, %xmm6, %xmm6 + addl $16, %ecx + cmpl %edx, %ecx + jl L_AES_GCM_encrypt_avx1_calc_aad_16_loop + movl %r11d, %edx + cmpl %edx, %ecx + je L_AES_GCM_encrypt_avx1_calc_aad_done +L_AES_GCM_encrypt_avx1_calc_aad_lt16: + subq $16, %rsp + vpxor %xmm8, %xmm8, %xmm8 + xorl %ebx, %ebx + vmovdqa %xmm8, (%rsp) +L_AES_GCM_encrypt_avx1_calc_aad_loop: + movzbl (%r12,%rcx,1), %r13d + movb %r13b, (%rsp,%rbx,1) + incl %ecx + incl %ebx + cmpl %edx, %ecx + jl L_AES_GCM_encrypt_avx1_calc_aad_loop + vmovdqa (%rsp), %xmm8 + addq $16, %rsp + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm8, %xmm8 + vpxor %xmm8, %xmm6, %xmm6 + # ghash_gfmul_avx + vpshufd $0x4e, %xmm6, %xmm1 + vpshufd $0x4e, %xmm5, %xmm2 + vpclmulqdq $0x11, %xmm6, %xmm5, %xmm3 + vpclmulqdq $0x00, %xmm6, %xmm5, %xmm0 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm5, %xmm2, %xmm2 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vmovdqa %xmm0, %xmm7 + vmovdqa %xmm3, %xmm6 + vpslldq $8, %xmm1, %xmm2 + vpsrldq $8, %xmm1, %xmm1 + vpxor %xmm2, %xmm7, %xmm7 + vpxor %xmm1, %xmm6, %xmm6 + vpsrld $31, %xmm7, %xmm0 + vpsrld $31, %xmm6, %xmm1 + vpslld $0x01, %xmm7, %xmm7 + vpslld $0x01, %xmm6, %xmm6 + vpsrldq $12, %xmm0, %xmm2 + vpslldq $4, %xmm0, %xmm0 + vpslldq $4, %xmm1, %xmm1 + vpor %xmm2, %xmm6, %xmm6 + vpor %xmm0, %xmm7, %xmm7 + vpor %xmm1, %xmm6, %xmm6 + vpslld $31, %xmm7, %xmm0 + vpslld $30, %xmm7, %xmm1 + vpslld $25, %xmm7, %xmm2 + vpxor %xmm1, %xmm0, %xmm0 + vpxor %xmm2, %xmm0, %xmm0 + vmovdqa %xmm0, %xmm1 + vpsrldq $4, %xmm1, %xmm1 + vpslldq $12, %xmm0, %xmm0 + vpxor %xmm0, %xmm7, %xmm7 + vpsrld $0x01, %xmm7, %xmm2 + vpsrld $2, %xmm7, %xmm3 + vpsrld $7, %xmm7, %xmm0 + vpxor %xmm3, %xmm2, %xmm2 + vpxor %xmm0, %xmm2, %xmm2 + vpxor %xmm1, %xmm2, %xmm2 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm2, %xmm6, %xmm6 +L_AES_GCM_encrypt_avx1_calc_aad_done: + # Calculate counter and H + vpsrlq $63, %xmm5, %xmm9 + vpsllq $0x01, %xmm5, %xmm8 + vpslldq $8, %xmm9, %xmm9 + vpor %xmm9, %xmm8, %xmm8 + vpshufd $0xff, %xmm5, %xmm5 + vpsrad $31, %xmm5, %xmm5 + vpshufb L_avx1_aes_gcm_bswap_epi64(%rip), %xmm4, %xmm4 + vpand L_avx1_aes_gcm_mod2_128(%rip), %xmm5, %xmm5 + vpaddd L_avx1_aes_gcm_one(%rip), %xmm4, %xmm4 + vpxor %xmm8, %xmm5, %xmm5 + vmovdqa %xmm4, 128(%rsp) + xorl %ebx, %ebx + cmpl $0x80, %r9d + movl %r9d, %r13d + jl L_AES_GCM_encrypt_avx1_done_128 + andl $0xffffff80, %r13d + vmovdqa %xmm6, %xmm2 + # H ^ 1 + vmovdqa %xmm5, (%rsp) + # H ^ 2 + vpclmulqdq $0x00, %xmm5, %xmm5, %xmm8 + vpclmulqdq $0x11, %xmm5, %xmm5, %xmm0 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm0, %xmm0 + vmovdqa %xmm0, 16(%rsp) + # H ^ 3 + # ghash_gfmul_red_avx + vpshufd $0x4e, %xmm5, %xmm9 + vpshufd $0x4e, %xmm0, %xmm10 + vpclmulqdq $0x11, %xmm5, %xmm0, %xmm11 + vpclmulqdq $0x00, %xmm5, %xmm0, %xmm8 + vpxor %xmm5, %xmm9, %xmm9 + vpxor %xmm0, %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm10, %xmm9, %xmm9 + vpxor %xmm8, %xmm9, %xmm9 + vpxor %xmm11, %xmm9, %xmm9 + vpslldq $8, %xmm9, %xmm10 + vpsrldq $8, %xmm9, %xmm9 + vpxor %xmm10, %xmm8, %xmm8 + vpxor %xmm9, %xmm11, %xmm1 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm1, %xmm1 + vmovdqa %xmm1, 32(%rsp) + # H ^ 4 + vpclmulqdq $0x00, %xmm0, %xmm0, %xmm8 + vpclmulqdq $0x11, %xmm0, %xmm0, %xmm3 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm3, %xmm3 + vmovdqa %xmm3, 48(%rsp) + # H ^ 5 + # ghash_gfmul_red_avx + vpshufd $0x4e, %xmm0, %xmm9 + vpshufd $0x4e, %xmm1, %xmm10 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm11 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm8 + vpxor %xmm0, %xmm9, %xmm9 + vpxor %xmm1, %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm10, %xmm9, %xmm9 + vpxor %xmm8, %xmm9, %xmm9 + vpxor %xmm11, %xmm9, %xmm9 + vpslldq $8, %xmm9, %xmm10 + vpsrldq $8, %xmm9, %xmm9 + vpxor %xmm10, %xmm8, %xmm8 + vpxor %xmm9, %xmm11, %xmm7 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm7, %xmm7 + vmovdqa %xmm7, 64(%rsp) + # H ^ 6 + vpclmulqdq $0x00, %xmm1, %xmm1, %xmm8 + vpclmulqdq $0x11, %xmm1, %xmm1, %xmm7 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm7, %xmm7 + vmovdqa %xmm7, 80(%rsp) + # H ^ 7 + # ghash_gfmul_red_avx + vpshufd $0x4e, %xmm1, %xmm9 + vpshufd $0x4e, %xmm3, %xmm10 + vpclmulqdq $0x11, %xmm1, %xmm3, %xmm11 + vpclmulqdq $0x00, %xmm1, %xmm3, %xmm8 + vpxor %xmm1, %xmm9, %xmm9 + vpxor %xmm3, %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm10, %xmm9, %xmm9 + vpxor %xmm8, %xmm9, %xmm9 + vpxor %xmm11, %xmm9, %xmm9 + vpslldq $8, %xmm9, %xmm10 + vpsrldq $8, %xmm9, %xmm9 + vpxor %xmm10, %xmm8, %xmm8 + vpxor %xmm9, %xmm11, %xmm7 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm7, %xmm7 + vmovdqa %xmm7, 96(%rsp) + # H ^ 8 + vpclmulqdq $0x00, %xmm3, %xmm3, %xmm8 + vpclmulqdq $0x11, %xmm3, %xmm3, %xmm7 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm7, %xmm7 + vmovdqa %xmm7, 112(%rsp) + # First 128 bytes of input + vmovdqa 128(%rsp), %xmm0 + vmovdqa L_avx1_aes_gcm_bswap_epi64(%rip), %xmm1 + vpshufb %xmm1, %xmm0, %xmm8 + vpaddd L_avx1_aes_gcm_one(%rip), %xmm0, %xmm9 + vpshufb %xmm1, %xmm9, %xmm9 + vpaddd L_avx1_aes_gcm_two(%rip), %xmm0, %xmm10 + vpshufb %xmm1, %xmm10, %xmm10 + vpaddd L_avx1_aes_gcm_three(%rip), %xmm0, %xmm11 + vpshufb %xmm1, %xmm11, %xmm11 + vpaddd L_avx1_aes_gcm_four(%rip), %xmm0, %xmm12 + vpshufb %xmm1, %xmm12, %xmm12 + vpaddd L_avx1_aes_gcm_five(%rip), %xmm0, %xmm13 + vpshufb %xmm1, %xmm13, %xmm13 + vpaddd L_avx1_aes_gcm_six(%rip), %xmm0, %xmm14 + vpshufb %xmm1, %xmm14, %xmm14 + vpaddd L_avx1_aes_gcm_seven(%rip), %xmm0, %xmm15 + vpshufb %xmm1, %xmm15, %xmm15 + vpaddd L_avx1_aes_gcm_eight(%rip), %xmm0, %xmm0 + vmovdqa (%r15), %xmm7 + vmovdqa %xmm0, 128(%rsp) + vpxor %xmm7, %xmm8, %xmm8 + vpxor %xmm7, %xmm9, %xmm9 + vpxor %xmm7, %xmm10, %xmm10 + vpxor %xmm7, %xmm11, %xmm11 + vpxor %xmm7, %xmm12, %xmm12 + vpxor %xmm7, %xmm13, %xmm13 + vpxor %xmm7, %xmm14, %xmm14 + vpxor %xmm7, %xmm15, %xmm15 + vmovdqa 16(%r15), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 32(%r15), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 48(%r15), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 64(%r15), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 80(%r15), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 96(%r15), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 112(%r15), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 128(%r15), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 144(%r15), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + cmpl $11, %r10d + vmovdqa 160(%r15), %xmm7 + jl L_AES_GCM_encrypt_avx1_aesenc_128_enc_done + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 176(%r15), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + cmpl $13, %r10d + vmovdqa 192(%r15), %xmm7 + jl L_AES_GCM_encrypt_avx1_aesenc_128_enc_done + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 208(%r15), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 224(%r15), %xmm7 +L_AES_GCM_encrypt_avx1_aesenc_128_enc_done: + vaesenclast %xmm7, %xmm8, %xmm8 + vaesenclast %xmm7, %xmm9, %xmm9 + vmovdqu (%rdi), %xmm0 + vmovdqu 16(%rdi), %xmm1 + vpxor %xmm0, %xmm8, %xmm8 + vpxor %xmm1, %xmm9, %xmm9 + vmovdqu %xmm8, (%rsi) + vmovdqu %xmm9, 16(%rsi) + vaesenclast %xmm7, %xmm10, %xmm10 + vaesenclast %xmm7, %xmm11, %xmm11 + vmovdqu 32(%rdi), %xmm0 + vmovdqu 48(%rdi), %xmm1 + vpxor %xmm0, %xmm10, %xmm10 + vpxor %xmm1, %xmm11, %xmm11 + vmovdqu %xmm10, 32(%rsi) + vmovdqu %xmm11, 48(%rsi) + vaesenclast %xmm7, %xmm12, %xmm12 + vaesenclast %xmm7, %xmm13, %xmm13 + vmovdqu 64(%rdi), %xmm0 + vmovdqu 80(%rdi), %xmm1 + vpxor %xmm0, %xmm12, %xmm12 + vpxor %xmm1, %xmm13, %xmm13 + vmovdqu %xmm12, 64(%rsi) + vmovdqu %xmm13, 80(%rsi) + vaesenclast %xmm7, %xmm14, %xmm14 + vaesenclast %xmm7, %xmm15, %xmm15 + vmovdqu 96(%rdi), %xmm0 + vmovdqu 112(%rdi), %xmm1 + vpxor %xmm0, %xmm14, %xmm14 + vpxor %xmm1, %xmm15, %xmm15 + vmovdqu %xmm14, 96(%rsi) + vmovdqu %xmm15, 112(%rsi) + cmpl $0x80, %r13d + movl $0x80, %ebx + jle L_AES_GCM_encrypt_avx1_end_128 + # More 128 bytes of input +L_AES_GCM_encrypt_avx1_ghash_128: + leaq (%rdi,%rbx,1), %rcx + leaq (%rsi,%rbx,1), %rdx + vmovdqa 128(%rsp), %xmm0 + vmovdqa L_avx1_aes_gcm_bswap_epi64(%rip), %xmm1 + vpshufb %xmm1, %xmm0, %xmm8 + vpaddd L_avx1_aes_gcm_one(%rip), %xmm0, %xmm9 + vpshufb %xmm1, %xmm9, %xmm9 + vpaddd L_avx1_aes_gcm_two(%rip), %xmm0, %xmm10 + vpshufb %xmm1, %xmm10, %xmm10 + vpaddd L_avx1_aes_gcm_three(%rip), %xmm0, %xmm11 + vpshufb %xmm1, %xmm11, %xmm11 + vpaddd L_avx1_aes_gcm_four(%rip), %xmm0, %xmm12 + vpshufb %xmm1, %xmm12, %xmm12 + vpaddd L_avx1_aes_gcm_five(%rip), %xmm0, %xmm13 + vpshufb %xmm1, %xmm13, %xmm13 + vpaddd L_avx1_aes_gcm_six(%rip), %xmm0, %xmm14 + vpshufb %xmm1, %xmm14, %xmm14 + vpaddd L_avx1_aes_gcm_seven(%rip), %xmm0, %xmm15 + vpshufb %xmm1, %xmm15, %xmm15 + vpaddd L_avx1_aes_gcm_eight(%rip), %xmm0, %xmm0 + vmovdqa (%r15), %xmm7 + vmovdqa %xmm0, 128(%rsp) + vpxor %xmm7, %xmm8, %xmm8 + vpxor %xmm7, %xmm9, %xmm9 + vpxor %xmm7, %xmm10, %xmm10 + vpxor %xmm7, %xmm11, %xmm11 + vpxor %xmm7, %xmm12, %xmm12 + vpxor %xmm7, %xmm13, %xmm13 + vpxor %xmm7, %xmm14, %xmm14 + vpxor %xmm7, %xmm15, %xmm15 + vmovdqa 112(%rsp), %xmm7 + vmovdqu -128(%rdx), %xmm0 + vaesenc 16(%r15), %xmm8, %xmm8 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vpxor %xmm2, %xmm0, %xmm0 + vpshufd $0x4e, %xmm7, %xmm1 + vpshufd $0x4e, %xmm0, %xmm5 + vpxor %xmm7, %xmm1, %xmm1 + vpxor %xmm0, %xmm5, %xmm5 + vpclmulqdq $0x11, %xmm7, %xmm0, %xmm3 + vaesenc 16(%r15), %xmm9, %xmm9 + vaesenc 16(%r15), %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm7, %xmm0, %xmm2 + vaesenc 16(%r15), %xmm11, %xmm11 + vaesenc 16(%r15), %xmm12, %xmm12 + vpclmulqdq $0x00, %xmm5, %xmm1, %xmm1 + vaesenc 16(%r15), %xmm13, %xmm13 + vaesenc 16(%r15), %xmm14, %xmm14 + vaesenc 16(%r15), %xmm15, %xmm15 + vpxor %xmm2, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vmovdqa 96(%rsp), %xmm7 + vmovdqu -112(%rdx), %xmm0 + vpshufd $0x4e, %xmm7, %xmm4 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vaesenc 32(%r15), %xmm8, %xmm8 + vpxor %xmm7, %xmm4, %xmm4 + vpshufd $0x4e, %xmm0, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + vpclmulqdq $0x11, %xmm7, %xmm0, %xmm6 + vaesenc 32(%r15), %xmm9, %xmm9 + vaesenc 32(%r15), %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm7, %xmm0, %xmm7 + vaesenc 32(%r15), %xmm11, %xmm11 + vaesenc 32(%r15), %xmm12, %xmm12 + vpclmulqdq $0x00, %xmm5, %xmm4, %xmm4 + vaesenc 32(%r15), %xmm13, %xmm13 + vaesenc 32(%r15), %xmm14, %xmm14 + vaesenc 32(%r15), %xmm15, %xmm15 + vpxor %xmm7, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm6, %xmm3, %xmm3 + vpxor %xmm4, %xmm1, %xmm1 + vmovdqa 80(%rsp), %xmm7 + vmovdqu -96(%rdx), %xmm0 + vpshufd $0x4e, %xmm7, %xmm4 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vaesenc 48(%r15), %xmm8, %xmm8 + vpxor %xmm7, %xmm4, %xmm4 + vpshufd $0x4e, %xmm0, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + vpclmulqdq $0x11, %xmm7, %xmm0, %xmm6 + vaesenc 48(%r15), %xmm9, %xmm9 + vaesenc 48(%r15), %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm7, %xmm0, %xmm7 + vaesenc 48(%r15), %xmm11, %xmm11 + vaesenc 48(%r15), %xmm12, %xmm12 + vpclmulqdq $0x00, %xmm5, %xmm4, %xmm4 + vaesenc 48(%r15), %xmm13, %xmm13 + vaesenc 48(%r15), %xmm14, %xmm14 + vaesenc 48(%r15), %xmm15, %xmm15 + vpxor %xmm7, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm6, %xmm3, %xmm3 + vpxor %xmm4, %xmm1, %xmm1 + vmovdqa 64(%rsp), %xmm7 + vmovdqu -80(%rdx), %xmm0 + vpshufd $0x4e, %xmm7, %xmm4 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vaesenc 64(%r15), %xmm8, %xmm8 + vpxor %xmm7, %xmm4, %xmm4 + vpshufd $0x4e, %xmm0, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + vpclmulqdq $0x11, %xmm7, %xmm0, %xmm6 + vaesenc 64(%r15), %xmm9, %xmm9 + vaesenc 64(%r15), %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm7, %xmm0, %xmm7 + vaesenc 64(%r15), %xmm11, %xmm11 + vaesenc 64(%r15), %xmm12, %xmm12 + vpclmulqdq $0x00, %xmm5, %xmm4, %xmm4 + vaesenc 64(%r15), %xmm13, %xmm13 + vaesenc 64(%r15), %xmm14, %xmm14 + vaesenc 64(%r15), %xmm15, %xmm15 + vpxor %xmm7, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm6, %xmm3, %xmm3 + vpxor %xmm4, %xmm1, %xmm1 + vmovdqa 48(%rsp), %xmm7 + vmovdqu -64(%rdx), %xmm0 + vpshufd $0x4e, %xmm7, %xmm4 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vaesenc 80(%r15), %xmm8, %xmm8 + vpxor %xmm7, %xmm4, %xmm4 + vpshufd $0x4e, %xmm0, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + vpclmulqdq $0x11, %xmm7, %xmm0, %xmm6 + vaesenc 80(%r15), %xmm9, %xmm9 + vaesenc 80(%r15), %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm7, %xmm0, %xmm7 + vaesenc 80(%r15), %xmm11, %xmm11 + vaesenc 80(%r15), %xmm12, %xmm12 + vpclmulqdq $0x00, %xmm5, %xmm4, %xmm4 + vaesenc 80(%r15), %xmm13, %xmm13 + vaesenc 80(%r15), %xmm14, %xmm14 + vaesenc 80(%r15), %xmm15, %xmm15 + vpxor %xmm7, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm6, %xmm3, %xmm3 + vpxor %xmm4, %xmm1, %xmm1 + vmovdqa 32(%rsp), %xmm7 + vmovdqu -48(%rdx), %xmm0 + vpshufd $0x4e, %xmm7, %xmm4 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vaesenc 96(%r15), %xmm8, %xmm8 + vpxor %xmm7, %xmm4, %xmm4 + vpshufd $0x4e, %xmm0, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + vpclmulqdq $0x11, %xmm7, %xmm0, %xmm6 + vaesenc 96(%r15), %xmm9, %xmm9 + vaesenc 96(%r15), %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm7, %xmm0, %xmm7 + vaesenc 96(%r15), %xmm11, %xmm11 + vaesenc 96(%r15), %xmm12, %xmm12 + vpclmulqdq $0x00, %xmm5, %xmm4, %xmm4 + vaesenc 96(%r15), %xmm13, %xmm13 + vaesenc 96(%r15), %xmm14, %xmm14 + vaesenc 96(%r15), %xmm15, %xmm15 + vpxor %xmm7, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm6, %xmm3, %xmm3 + vpxor %xmm4, %xmm1, %xmm1 + vmovdqa 16(%rsp), %xmm7 + vmovdqu -32(%rdx), %xmm0 + vpshufd $0x4e, %xmm7, %xmm4 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vaesenc 112(%r15), %xmm8, %xmm8 + vpxor %xmm7, %xmm4, %xmm4 + vpshufd $0x4e, %xmm0, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + vpclmulqdq $0x11, %xmm7, %xmm0, %xmm6 + vaesenc 112(%r15), %xmm9, %xmm9 + vaesenc 112(%r15), %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm7, %xmm0, %xmm7 + vaesenc 112(%r15), %xmm11, %xmm11 + vaesenc 112(%r15), %xmm12, %xmm12 + vpclmulqdq $0x00, %xmm5, %xmm4, %xmm4 + vaesenc 112(%r15), %xmm13, %xmm13 + vaesenc 112(%r15), %xmm14, %xmm14 + vaesenc 112(%r15), %xmm15, %xmm15 + vpxor %xmm7, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm6, %xmm3, %xmm3 + vpxor %xmm4, %xmm1, %xmm1 + vmovdqa (%rsp), %xmm7 + vmovdqu -16(%rdx), %xmm0 + vpshufd $0x4e, %xmm7, %xmm4 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vaesenc 128(%r15), %xmm8, %xmm8 + vpxor %xmm7, %xmm4, %xmm4 + vpshufd $0x4e, %xmm0, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + vpclmulqdq $0x11, %xmm7, %xmm0, %xmm6 + vaesenc 128(%r15), %xmm9, %xmm9 + vaesenc 128(%r15), %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm7, %xmm0, %xmm7 + vaesenc 128(%r15), %xmm11, %xmm11 + vaesenc 128(%r15), %xmm12, %xmm12 + vpclmulqdq $0x00, %xmm5, %xmm4, %xmm4 + vaesenc 128(%r15), %xmm13, %xmm13 + vaesenc 128(%r15), %xmm14, %xmm14 + vaesenc 128(%r15), %xmm15, %xmm15 + vpxor %xmm7, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm6, %xmm3, %xmm3 + vpxor %xmm4, %xmm1, %xmm1 + vpslldq $8, %xmm1, %xmm5 + vpsrldq $8, %xmm1, %xmm1 + vaesenc 144(%r15), %xmm8, %xmm8 + vpxor %xmm5, %xmm2, %xmm2 + vpxor %xmm1, %xmm3, %xmm3 + vaesenc 144(%r15), %xmm9, %xmm9 + vpslld $31, %xmm2, %xmm7 + vpslld $30, %xmm2, %xmm4 + vpslld $25, %xmm2, %xmm5 + vaesenc 144(%r15), %xmm10, %xmm10 + vpxor %xmm4, %xmm7, %xmm7 + vpxor %xmm5, %xmm7, %xmm7 + vaesenc 144(%r15), %xmm11, %xmm11 + vpsrldq $4, %xmm7, %xmm4 + vpslldq $12, %xmm7, %xmm7 + vaesenc 144(%r15), %xmm12, %xmm12 + vpxor %xmm7, %xmm2, %xmm2 + vpsrld $0x01, %xmm2, %xmm5 + vaesenc 144(%r15), %xmm13, %xmm13 + vpsrld $2, %xmm2, %xmm1 + vpsrld $7, %xmm2, %xmm0 + vaesenc 144(%r15), %xmm14, %xmm14 + vpxor %xmm1, %xmm5, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + vaesenc 144(%r15), %xmm15, %xmm15 + vpxor %xmm4, %xmm5, %xmm5 + vpxor %xmm5, %xmm2, %xmm2 + vpxor %xmm3, %xmm2, %xmm2 + cmpl $11, %r10d + vmovdqa 160(%r15), %xmm7 + jl L_AES_GCM_encrypt_avx1_aesenc_128_ghash_avx_done + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 176(%r15), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + cmpl $13, %r10d + vmovdqa 192(%r15), %xmm7 + jl L_AES_GCM_encrypt_avx1_aesenc_128_ghash_avx_done + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 208(%r15), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 224(%r15), %xmm7 +L_AES_GCM_encrypt_avx1_aesenc_128_ghash_avx_done: + vaesenclast %xmm7, %xmm8, %xmm8 + vaesenclast %xmm7, %xmm9, %xmm9 + vmovdqu (%rcx), %xmm0 + vmovdqu 16(%rcx), %xmm1 + vpxor %xmm0, %xmm8, %xmm8 + vpxor %xmm1, %xmm9, %xmm9 + vmovdqu %xmm8, (%rdx) + vmovdqu %xmm9, 16(%rdx) + vaesenclast %xmm7, %xmm10, %xmm10 + vaesenclast %xmm7, %xmm11, %xmm11 + vmovdqu 32(%rcx), %xmm0 + vmovdqu 48(%rcx), %xmm1 + vpxor %xmm0, %xmm10, %xmm10 + vpxor %xmm1, %xmm11, %xmm11 + vmovdqu %xmm10, 32(%rdx) + vmovdqu %xmm11, 48(%rdx) + vaesenclast %xmm7, %xmm12, %xmm12 + vaesenclast %xmm7, %xmm13, %xmm13 + vmovdqu 64(%rcx), %xmm0 + vmovdqu 80(%rcx), %xmm1 + vpxor %xmm0, %xmm12, %xmm12 + vpxor %xmm1, %xmm13, %xmm13 + vmovdqu %xmm12, 64(%rdx) + vmovdqu %xmm13, 80(%rdx) + vaesenclast %xmm7, %xmm14, %xmm14 + vaesenclast %xmm7, %xmm15, %xmm15 + vmovdqu 96(%rcx), %xmm0 + vmovdqu 112(%rcx), %xmm1 + vpxor %xmm0, %xmm14, %xmm14 + vpxor %xmm1, %xmm15, %xmm15 + vmovdqu %xmm14, 96(%rdx) + vmovdqu %xmm15, 112(%rdx) + addl $0x80, %ebx + cmpl %r13d, %ebx + jl L_AES_GCM_encrypt_avx1_ghash_128 +L_AES_GCM_encrypt_avx1_end_128: + vmovdqa L_avx1_aes_gcm_bswap_mask(%rip), %xmm4 + vpshufb %xmm4, %xmm8, %xmm8 + vpshufb %xmm4, %xmm9, %xmm9 + vpshufb %xmm4, %xmm10, %xmm10 + vpshufb %xmm4, %xmm11, %xmm11 + vpxor %xmm2, %xmm8, %xmm8 + vpshufb %xmm4, %xmm12, %xmm12 + vpshufb %xmm4, %xmm13, %xmm13 + vpshufb %xmm4, %xmm14, %xmm14 + vpshufb %xmm4, %xmm15, %xmm15 + vmovdqa (%rsp), %xmm7 + vmovdqa 16(%rsp), %xmm5 + # ghash_gfmul_avx + vpshufd $0x4e, %xmm15, %xmm1 + vpshufd $0x4e, %xmm7, %xmm2 + vpclmulqdq $0x11, %xmm15, %xmm7, %xmm3 + vpclmulqdq $0x00, %xmm15, %xmm7, %xmm0 + vpxor %xmm15, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vmovdqa %xmm0, %xmm4 + vmovdqa %xmm3, %xmm6 + vpslldq $8, %xmm1, %xmm2 + vpsrldq $8, %xmm1, %xmm1 + vpxor %xmm2, %xmm4, %xmm4 + vpxor %xmm1, %xmm6, %xmm6 + # ghash_gfmul_xor_avx + vpshufd $0x4e, %xmm14, %xmm1 + vpshufd $0x4e, %xmm5, %xmm2 + vpclmulqdq $0x11, %xmm14, %xmm5, %xmm3 + vpclmulqdq $0x00, %xmm14, %xmm5, %xmm0 + vpxor %xmm14, %xmm1, %xmm1 + vpxor %xmm5, %xmm2, %xmm2 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vpxor %xmm0, %xmm4, %xmm4 + vpxor %xmm3, %xmm6, %xmm6 + vpslldq $8, %xmm1, %xmm2 + vpsrldq $8, %xmm1, %xmm1 + vpxor %xmm2, %xmm4, %xmm4 + vpxor %xmm1, %xmm6, %xmm6 + vmovdqa 32(%rsp), %xmm7 + vmovdqa 48(%rsp), %xmm5 + # ghash_gfmul_xor_avx + vpshufd $0x4e, %xmm13, %xmm1 + vpshufd $0x4e, %xmm7, %xmm2 + vpclmulqdq $0x11, %xmm13, %xmm7, %xmm3 + vpclmulqdq $0x00, %xmm13, %xmm7, %xmm0 + vpxor %xmm13, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vpxor %xmm0, %xmm4, %xmm4 + vpxor %xmm3, %xmm6, %xmm6 + vpslldq $8, %xmm1, %xmm2 + vpsrldq $8, %xmm1, %xmm1 + vpxor %xmm2, %xmm4, %xmm4 + vpxor %xmm1, %xmm6, %xmm6 + # ghash_gfmul_xor_avx + vpshufd $0x4e, %xmm12, %xmm1 + vpshufd $0x4e, %xmm5, %xmm2 + vpclmulqdq $0x11, %xmm12, %xmm5, %xmm3 + vpclmulqdq $0x00, %xmm12, %xmm5, %xmm0 + vpxor %xmm12, %xmm1, %xmm1 + vpxor %xmm5, %xmm2, %xmm2 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vpxor %xmm0, %xmm4, %xmm4 + vpxor %xmm3, %xmm6, %xmm6 + vpslldq $8, %xmm1, %xmm2 + vpsrldq $8, %xmm1, %xmm1 + vpxor %xmm2, %xmm4, %xmm4 + vpxor %xmm1, %xmm6, %xmm6 + vmovdqa 64(%rsp), %xmm7 + vmovdqa 80(%rsp), %xmm5 + # ghash_gfmul_xor_avx + vpshufd $0x4e, %xmm11, %xmm1 + vpshufd $0x4e, %xmm7, %xmm2 + vpclmulqdq $0x11, %xmm11, %xmm7, %xmm3 + vpclmulqdq $0x00, %xmm11, %xmm7, %xmm0 + vpxor %xmm11, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vpxor %xmm0, %xmm4, %xmm4 + vpxor %xmm3, %xmm6, %xmm6 + vpslldq $8, %xmm1, %xmm2 + vpsrldq $8, %xmm1, %xmm1 + vpxor %xmm2, %xmm4, %xmm4 + vpxor %xmm1, %xmm6, %xmm6 + # ghash_gfmul_xor_avx + vpshufd $0x4e, %xmm10, %xmm1 + vpshufd $0x4e, %xmm5, %xmm2 + vpclmulqdq $0x11, %xmm10, %xmm5, %xmm3 + vpclmulqdq $0x00, %xmm10, %xmm5, %xmm0 + vpxor %xmm10, %xmm1, %xmm1 + vpxor %xmm5, %xmm2, %xmm2 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vpxor %xmm0, %xmm4, %xmm4 + vpxor %xmm3, %xmm6, %xmm6 + vpslldq $8, %xmm1, %xmm2 + vpsrldq $8, %xmm1, %xmm1 + vpxor %xmm2, %xmm4, %xmm4 + vpxor %xmm1, %xmm6, %xmm6 + vmovdqa 96(%rsp), %xmm7 + vmovdqa 112(%rsp), %xmm5 + # ghash_gfmul_xor_avx + vpshufd $0x4e, %xmm9, %xmm1 + vpshufd $0x4e, %xmm7, %xmm2 + vpclmulqdq $0x11, %xmm9, %xmm7, %xmm3 + vpclmulqdq $0x00, %xmm9, %xmm7, %xmm0 + vpxor %xmm9, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vpxor %xmm0, %xmm4, %xmm4 + vpxor %xmm3, %xmm6, %xmm6 + vpslldq $8, %xmm1, %xmm2 + vpsrldq $8, %xmm1, %xmm1 + vpxor %xmm2, %xmm4, %xmm4 + vpxor %xmm1, %xmm6, %xmm6 + # ghash_gfmul_xor_avx + vpshufd $0x4e, %xmm8, %xmm1 + vpshufd $0x4e, %xmm5, %xmm2 + vpclmulqdq $0x11, %xmm8, %xmm5, %xmm3 + vpclmulqdq $0x00, %xmm8, %xmm5, %xmm0 + vpxor %xmm8, %xmm1, %xmm1 + vpxor %xmm5, %xmm2, %xmm2 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vpxor %xmm0, %xmm4, %xmm4 + vpxor %xmm3, %xmm6, %xmm6 + vpslldq $8, %xmm1, %xmm2 + vpsrldq $8, %xmm1, %xmm1 + vpxor %xmm2, %xmm4, %xmm4 + vpxor %xmm1, %xmm6, %xmm6 + vpslld $31, %xmm4, %xmm0 + vpslld $30, %xmm4, %xmm1 + vpslld $25, %xmm4, %xmm2 + vpxor %xmm1, %xmm0, %xmm0 + vpxor %xmm2, %xmm0, %xmm0 + vmovdqa %xmm0, %xmm1 + vpsrldq $4, %xmm1, %xmm1 + vpslldq $12, %xmm0, %xmm0 + vpxor %xmm0, %xmm4, %xmm4 + vpsrld $0x01, %xmm4, %xmm2 + vpsrld $2, %xmm4, %xmm3 + vpsrld $7, %xmm4, %xmm0 + vpxor %xmm3, %xmm2, %xmm2 + vpxor %xmm0, %xmm2, %xmm2 + vpxor %xmm1, %xmm2, %xmm2 + vpxor %xmm4, %xmm2, %xmm2 + vpxor %xmm2, %xmm6, %xmm6 + vmovdqa (%rsp), %xmm5 +L_AES_GCM_encrypt_avx1_done_128: + movl %r9d, %edx + cmpl %edx, %ebx + jge L_AES_GCM_encrypt_avx1_done_enc + movl %r9d, %r13d + andl $0xfffffff0, %r13d + cmpl %r13d, %ebx + jge L_AES_GCM_encrypt_avx1_last_block_done + vmovdqa 128(%rsp), %xmm9 + vpshufb L_avx1_aes_gcm_bswap_epi64(%rip), %xmm9, %xmm8 + vpaddd L_avx1_aes_gcm_one(%rip), %xmm9, %xmm9 + vmovdqa %xmm9, 128(%rsp) + vpxor (%r15), %xmm8, %xmm8 + vaesenc 16(%r15), %xmm8, %xmm8 + vaesenc 32(%r15), %xmm8, %xmm8 + vaesenc 48(%r15), %xmm8, %xmm8 + vaesenc 64(%r15), %xmm8, %xmm8 + vaesenc 80(%r15), %xmm8, %xmm8 + vaesenc 96(%r15), %xmm8, %xmm8 + vaesenc 112(%r15), %xmm8, %xmm8 + vaesenc 128(%r15), %xmm8, %xmm8 + vaesenc 144(%r15), %xmm8, %xmm8 + cmpl $11, %r10d + vmovdqa 160(%r15), %xmm9 + jl L_AES_GCM_encrypt_avx1_aesenc_block_last + vaesenc %xmm9, %xmm8, %xmm8 + vaesenc 176(%r15), %xmm8, %xmm8 + cmpl $13, %r10d + vmovdqa 192(%r15), %xmm9 + jl L_AES_GCM_encrypt_avx1_aesenc_block_last + vaesenc %xmm9, %xmm8, %xmm8 + vaesenc 208(%r15), %xmm8, %xmm8 + vmovdqa 224(%r15), %xmm9 +L_AES_GCM_encrypt_avx1_aesenc_block_last: + vaesenclast %xmm9, %xmm8, %xmm8 + vmovdqu (%rdi,%rbx,1), %xmm9 + vpxor %xmm9, %xmm8, %xmm8 + vmovdqu %xmm8, (%rsi,%rbx,1) + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm8, %xmm8 + vpxor %xmm8, %xmm6, %xmm6 + addl $16, %ebx + cmpl %r13d, %ebx + jge L_AES_GCM_encrypt_avx1_last_block_ghash +L_AES_GCM_encrypt_avx1_last_block_start: + vmovdqu (%rdi,%rbx,1), %xmm13 + vmovdqa 128(%rsp), %xmm9 + vpshufb L_avx1_aes_gcm_bswap_epi64(%rip), %xmm9, %xmm8 + vpaddd L_avx1_aes_gcm_one(%rip), %xmm9, %xmm9 + vmovdqa %xmm9, 128(%rsp) + vpxor (%r15), %xmm8, %xmm8 + vpclmulqdq $16, %xmm5, %xmm6, %xmm10 + vaesenc 16(%r15), %xmm8, %xmm8 + vaesenc 32(%r15), %xmm8, %xmm8 + vpclmulqdq $0x01, %xmm5, %xmm6, %xmm11 + vaesenc 48(%r15), %xmm8, %xmm8 + vaesenc 64(%r15), %xmm8, %xmm8 + vpclmulqdq $0x00, %xmm5, %xmm6, %xmm12 + vaesenc 80(%r15), %xmm8, %xmm8 + vpclmulqdq $0x11, %xmm5, %xmm6, %xmm1 + vaesenc 96(%r15), %xmm8, %xmm8 + vpxor %xmm11, %xmm10, %xmm10 + vpslldq $8, %xmm10, %xmm2 + vpsrldq $8, %xmm10, %xmm10 + vaesenc 112(%r15), %xmm8, %xmm8 + vpxor %xmm12, %xmm2, %xmm2 + vpxor %xmm10, %xmm1, %xmm3 + vmovdqa L_avx1_aes_gcm_mod2_128(%rip), %xmm0 + vpclmulqdq $16, %xmm0, %xmm2, %xmm11 + vaesenc 128(%r15), %xmm8, %xmm8 + vpshufd $0x4e, %xmm2, %xmm10 + vpxor %xmm11, %xmm10, %xmm10 + vpclmulqdq $16, %xmm0, %xmm10, %xmm11 + vaesenc 144(%r15), %xmm8, %xmm8 + vpshufd $0x4e, %xmm10, %xmm10 + vpxor %xmm11, %xmm10, %xmm10 + vpxor %xmm3, %xmm10, %xmm6 + cmpl $11, %r10d + vmovdqa 160(%r15), %xmm9 + jl L_AES_GCM_encrypt_avx1_aesenc_gfmul_last + vaesenc %xmm9, %xmm8, %xmm8 + vaesenc 176(%r15), %xmm8, %xmm8 + cmpl $13, %r10d + vmovdqa 192(%r15), %xmm9 + jl L_AES_GCM_encrypt_avx1_aesenc_gfmul_last + vaesenc %xmm9, %xmm8, %xmm8 + vaesenc 208(%r15), %xmm8, %xmm8 + vmovdqa 224(%r15), %xmm9 +L_AES_GCM_encrypt_avx1_aesenc_gfmul_last: + vaesenclast %xmm9, %xmm8, %xmm8 + vmovdqa %xmm13, %xmm0 + vpxor %xmm0, %xmm8, %xmm8 + vmovdqu %xmm8, (%rsi,%rbx,1) + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm8, %xmm8 + addl $16, %ebx + vpxor %xmm8, %xmm6, %xmm6 + cmpl %r13d, %ebx + jl L_AES_GCM_encrypt_avx1_last_block_start +L_AES_GCM_encrypt_avx1_last_block_ghash: + # ghash_gfmul_red_avx + vpshufd $0x4e, %xmm5, %xmm9 + vpshufd $0x4e, %xmm6, %xmm10 + vpclmulqdq $0x11, %xmm5, %xmm6, %xmm11 + vpclmulqdq $0x00, %xmm5, %xmm6, %xmm8 + vpxor %xmm5, %xmm9, %xmm9 + vpxor %xmm6, %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm10, %xmm9, %xmm9 + vpxor %xmm8, %xmm9, %xmm9 + vpxor %xmm11, %xmm9, %xmm9 + vpslldq $8, %xmm9, %xmm10 + vpsrldq $8, %xmm9, %xmm9 + vpxor %xmm10, %xmm8, %xmm8 + vpxor %xmm9, %xmm11, %xmm6 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm6, %xmm6 +L_AES_GCM_encrypt_avx1_last_block_done: + movl %r9d, %ecx + movl %ecx, %edx + andl $15, %ecx + jz L_AES_GCM_encrypt_avx1_aesenc_last15_enc_avx_done + vmovdqa 128(%rsp), %xmm4 + vpshufb L_avx1_aes_gcm_bswap_epi64(%rip), %xmm4, %xmm4 + vpxor (%r15), %xmm4, %xmm4 + vaesenc 16(%r15), %xmm4, %xmm4 + vaesenc 32(%r15), %xmm4, %xmm4 + vaesenc 48(%r15), %xmm4, %xmm4 + vaesenc 64(%r15), %xmm4, %xmm4 + vaesenc 80(%r15), %xmm4, %xmm4 + vaesenc 96(%r15), %xmm4, %xmm4 + vaesenc 112(%r15), %xmm4, %xmm4 + vaesenc 128(%r15), %xmm4, %xmm4 + vaesenc 144(%r15), %xmm4, %xmm4 + cmpl $11, %r10d + vmovdqa 160(%r15), %xmm9 + jl L_AES_GCM_encrypt_avx1_aesenc_last15_enc_avx_aesenc_avx_last + vaesenc %xmm9, %xmm4, %xmm4 + vaesenc 176(%r15), %xmm4, %xmm4 + cmpl $13, %r10d + vmovdqa 192(%r15), %xmm9 + jl L_AES_GCM_encrypt_avx1_aesenc_last15_enc_avx_aesenc_avx_last + vaesenc %xmm9, %xmm4, %xmm4 + vaesenc 208(%r15), %xmm4, %xmm4 + vmovdqa 224(%r15), %xmm9 +L_AES_GCM_encrypt_avx1_aesenc_last15_enc_avx_aesenc_avx_last: + vaesenclast %xmm9, %xmm4, %xmm4 + subq $16, %rsp + xorl %ecx, %ecx + vmovdqa %xmm4, (%rsp) +L_AES_GCM_encrypt_avx1_aesenc_last15_enc_avx_loop: + movzbl (%rdi,%rbx,1), %r13d + xorb (%rsp,%rcx,1), %r13b + movb %r13b, (%rsi,%rbx,1) + movb %r13b, (%rsp,%rcx,1) + incl %ebx + incl %ecx + cmpl %edx, %ebx + jl L_AES_GCM_encrypt_avx1_aesenc_last15_enc_avx_loop + xorq %r13, %r13 + cmpl $16, %ecx + je L_AES_GCM_encrypt_avx1_aesenc_last15_enc_avx_finish_enc +L_AES_GCM_encrypt_avx1_aesenc_last15_enc_avx_byte_loop: + movb %r13b, (%rsp,%rcx,1) + incl %ecx + cmpl $16, %ecx + jl L_AES_GCM_encrypt_avx1_aesenc_last15_enc_avx_byte_loop +L_AES_GCM_encrypt_avx1_aesenc_last15_enc_avx_finish_enc: + vmovdqa (%rsp), %xmm4 + addq $16, %rsp + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm4, %xmm4 + vpxor %xmm4, %xmm6, %xmm6 + # ghash_gfmul_red_avx + vpshufd $0x4e, %xmm5, %xmm9 + vpshufd $0x4e, %xmm6, %xmm10 + vpclmulqdq $0x11, %xmm5, %xmm6, %xmm11 + vpclmulqdq $0x00, %xmm5, %xmm6, %xmm8 + vpxor %xmm5, %xmm9, %xmm9 + vpxor %xmm6, %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm10, %xmm9, %xmm9 + vpxor %xmm8, %xmm9, %xmm9 + vpxor %xmm11, %xmm9, %xmm9 + vpslldq $8, %xmm9, %xmm10 + vpsrldq $8, %xmm9, %xmm9 + vpxor %xmm10, %xmm8, %xmm8 + vpxor %xmm9, %xmm11, %xmm6 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm6, %xmm6 +L_AES_GCM_encrypt_avx1_aesenc_last15_enc_avx_done: +L_AES_GCM_encrypt_avx1_done_enc: + movl %r9d, %edx + movl %r11d, %ecx + shlq $3, %rdx + shlq $3, %rcx + vpinsrq $0x00, %rdx, %xmm0, %xmm0 + vpinsrq $0x01, %rcx, %xmm0, %xmm0 + vpxor %xmm0, %xmm6, %xmm6 + # ghash_gfmul_red_avx + vpshufd $0x4e, %xmm5, %xmm9 + vpshufd $0x4e, %xmm6, %xmm10 + vpclmulqdq $0x11, %xmm5, %xmm6, %xmm11 + vpclmulqdq $0x00, %xmm5, %xmm6, %xmm8 + vpxor %xmm5, %xmm9, %xmm9 + vpxor %xmm6, %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm10, %xmm9, %xmm9 + vpxor %xmm8, %xmm9, %xmm9 + vpxor %xmm11, %xmm9, %xmm9 + vpslldq $8, %xmm9, %xmm10 + vpsrldq $8, %xmm9, %xmm9 + vpxor %xmm10, %xmm8, %xmm8 + vpxor %xmm9, %xmm11, %xmm6 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm6, %xmm6 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm6, %xmm6 + vpxor 144(%rsp), %xmm6, %xmm0 + cmpl $16, %r14d + je L_AES_GCM_encrypt_avx1_store_tag_16 + xorq %rcx, %rcx + vmovdqa %xmm0, (%rsp) +L_AES_GCM_encrypt_avx1_store_tag_loop: + movzbl (%rsp,%rcx,1), %r13d + movb %r13b, (%r8,%rcx,1) + incl %ecx + cmpl %r14d, %ecx + jne L_AES_GCM_encrypt_avx1_store_tag_loop + jmp L_AES_GCM_encrypt_avx1_store_tag_done +L_AES_GCM_encrypt_avx1_store_tag_16: + vmovdqu %xmm0, (%r8) +L_AES_GCM_encrypt_avx1_store_tag_done: + vzeroupper + addq $0xa0, %rsp + popq %r15 + popq %r14 + popq %rbx + popq %r12 + popq %r13 + repz retq +#ifndef __APPLE__ +.size AES_GCM_encrypt_avx1,.-AES_GCM_encrypt_avx1 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl AES_GCM_decrypt_avx1 +.type AES_GCM_decrypt_avx1,@function +.align 4 +AES_GCM_decrypt_avx1: +#else +.section __TEXT,__text +.globl _AES_GCM_decrypt_avx1 +.p2align 2 +_AES_GCM_decrypt_avx1: +#endif /* __APPLE__ */ + pushq %r13 + pushq %r12 + pushq %rbx + pushq %r14 + pushq %r15 + pushq %rbp + movq %rdx, %r12 + movq %rcx, %rax + movl 56(%rsp), %r11d + movl 64(%rsp), %ebx + movl 72(%rsp), %r14d + movq 80(%rsp), %r15 + movl 88(%rsp), %r10d + movq 96(%rsp), %rbp + subq $0xa8, %rsp + vpxor %xmm4, %xmm4, %xmm4 + vpxor %xmm6, %xmm6, %xmm6 + cmpl $12, %ebx + movl %ebx, %edx + jne L_AES_GCM_decrypt_avx1_iv_not_12 + # # Calculate values when IV is 12 bytes + # Set counter based on IV + movl $0x1000000, %ecx + vpinsrq $0x00, (%rax), %xmm4, %xmm4 + vpinsrd $2, 8(%rax), %xmm4, %xmm4 + vpinsrd $3, %ecx, %xmm4, %xmm4 + # H = Encrypt X(=0) and T = Encrypt counter + vmovdqa (%r15), %xmm5 + vpxor %xmm5, %xmm4, %xmm1 + vmovdqa 16(%r15), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 32(%r15), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 48(%r15), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 64(%r15), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 80(%r15), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 96(%r15), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 112(%r15), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 128(%r15), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 144(%r15), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + cmpl $11, %r10d + vmovdqa 160(%r15), %xmm7 + jl L_AES_GCM_decrypt_avx1_calc_iv_12_last + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 176(%r15), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + cmpl $13, %r10d + vmovdqa 192(%r15), %xmm7 + jl L_AES_GCM_decrypt_avx1_calc_iv_12_last + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 208(%r15), %xmm7 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm1, %xmm1 + vmovdqa 224(%r15), %xmm7 +L_AES_GCM_decrypt_avx1_calc_iv_12_last: + vaesenclast %xmm7, %xmm5, %xmm5 + vaesenclast %xmm7, %xmm1, %xmm1 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm5, %xmm5 + vmovdqa %xmm1, 144(%rsp) + jmp L_AES_GCM_decrypt_avx1_iv_done +L_AES_GCM_decrypt_avx1_iv_not_12: + # Calculate values when IV is not 12 bytes + # H = Encrypt X(=0) + vmovdqa (%r15), %xmm5 + vaesenc 16(%r15), %xmm5, %xmm5 + vaesenc 32(%r15), %xmm5, %xmm5 + vaesenc 48(%r15), %xmm5, %xmm5 + vaesenc 64(%r15), %xmm5, %xmm5 + vaesenc 80(%r15), %xmm5, %xmm5 + vaesenc 96(%r15), %xmm5, %xmm5 + vaesenc 112(%r15), %xmm5, %xmm5 + vaesenc 128(%r15), %xmm5, %xmm5 + vaesenc 144(%r15), %xmm5, %xmm5 + cmpl $11, %r10d + vmovdqa 160(%r15), %xmm9 + jl L_AES_GCM_decrypt_avx1_calc_iv_1_aesenc_avx_last + vaesenc %xmm9, %xmm5, %xmm5 + vaesenc 176(%r15), %xmm5, %xmm5 + cmpl $13, %r10d + vmovdqa 192(%r15), %xmm9 + jl L_AES_GCM_decrypt_avx1_calc_iv_1_aesenc_avx_last + vaesenc %xmm9, %xmm5, %xmm5 + vaesenc 208(%r15), %xmm5, %xmm5 + vmovdqa 224(%r15), %xmm9 +L_AES_GCM_decrypt_avx1_calc_iv_1_aesenc_avx_last: + vaesenclast %xmm9, %xmm5, %xmm5 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm5, %xmm5 + # Calc counter + # Initialization vector + cmpl $0x00, %edx + movq $0x00, %rcx + je L_AES_GCM_decrypt_avx1_calc_iv_done + cmpl $16, %edx + jl L_AES_GCM_decrypt_avx1_calc_iv_lt16 + andl $0xfffffff0, %edx +L_AES_GCM_decrypt_avx1_calc_iv_16_loop: + vmovdqu (%rax,%rcx,1), %xmm8 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm8, %xmm8 + vpxor %xmm8, %xmm4, %xmm4 + # ghash_gfmul_avx + vpshufd $0x4e, %xmm4, %xmm1 + vpshufd $0x4e, %xmm5, %xmm2 + vpclmulqdq $0x11, %xmm4, %xmm5, %xmm3 + vpclmulqdq $0x00, %xmm4, %xmm5, %xmm0 + vpxor %xmm4, %xmm1, %xmm1 + vpxor %xmm5, %xmm2, %xmm2 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vmovdqa %xmm0, %xmm7 + vmovdqa %xmm3, %xmm4 + vpslldq $8, %xmm1, %xmm2 + vpsrldq $8, %xmm1, %xmm1 + vpxor %xmm2, %xmm7, %xmm7 + vpxor %xmm1, %xmm4, %xmm4 + vpsrld $31, %xmm7, %xmm0 + vpsrld $31, %xmm4, %xmm1 + vpslld $0x01, %xmm7, %xmm7 + vpslld $0x01, %xmm4, %xmm4 + vpsrldq $12, %xmm0, %xmm2 + vpslldq $4, %xmm0, %xmm0 + vpslldq $4, %xmm1, %xmm1 + vpor %xmm2, %xmm4, %xmm4 + vpor %xmm0, %xmm7, %xmm7 + vpor %xmm1, %xmm4, %xmm4 + vpslld $31, %xmm7, %xmm0 + vpslld $30, %xmm7, %xmm1 + vpslld $25, %xmm7, %xmm2 + vpxor %xmm1, %xmm0, %xmm0 + vpxor %xmm2, %xmm0, %xmm0 + vmovdqa %xmm0, %xmm1 + vpsrldq $4, %xmm1, %xmm1 + vpslldq $12, %xmm0, %xmm0 + vpxor %xmm0, %xmm7, %xmm7 + vpsrld $0x01, %xmm7, %xmm2 + vpsrld $2, %xmm7, %xmm3 + vpsrld $7, %xmm7, %xmm0 + vpxor %xmm3, %xmm2, %xmm2 + vpxor %xmm0, %xmm2, %xmm2 + vpxor %xmm1, %xmm2, %xmm2 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm2, %xmm4, %xmm4 + addl $16, %ecx + cmpl %edx, %ecx + jl L_AES_GCM_decrypt_avx1_calc_iv_16_loop + movl %ebx, %edx + cmpl %edx, %ecx + je L_AES_GCM_decrypt_avx1_calc_iv_done +L_AES_GCM_decrypt_avx1_calc_iv_lt16: + subq $16, %rsp + vpxor %xmm8, %xmm8, %xmm8 + xorl %ebx, %ebx + vmovdqa %xmm8, (%rsp) +L_AES_GCM_decrypt_avx1_calc_iv_loop: + movzbl (%rax,%rcx,1), %r13d + movb %r13b, (%rsp,%rbx,1) + incl %ecx + incl %ebx + cmpl %edx, %ecx + jl L_AES_GCM_decrypt_avx1_calc_iv_loop + vmovdqa (%rsp), %xmm8 + addq $16, %rsp + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm8, %xmm8 + vpxor %xmm8, %xmm4, %xmm4 + # ghash_gfmul_avx + vpshufd $0x4e, %xmm4, %xmm1 + vpshufd $0x4e, %xmm5, %xmm2 + vpclmulqdq $0x11, %xmm4, %xmm5, %xmm3 + vpclmulqdq $0x00, %xmm4, %xmm5, %xmm0 + vpxor %xmm4, %xmm1, %xmm1 + vpxor %xmm5, %xmm2, %xmm2 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vmovdqa %xmm0, %xmm7 + vmovdqa %xmm3, %xmm4 + vpslldq $8, %xmm1, %xmm2 + vpsrldq $8, %xmm1, %xmm1 + vpxor %xmm2, %xmm7, %xmm7 + vpxor %xmm1, %xmm4, %xmm4 + vpsrld $31, %xmm7, %xmm0 + vpsrld $31, %xmm4, %xmm1 + vpslld $0x01, %xmm7, %xmm7 + vpslld $0x01, %xmm4, %xmm4 + vpsrldq $12, %xmm0, %xmm2 + vpslldq $4, %xmm0, %xmm0 + vpslldq $4, %xmm1, %xmm1 + vpor %xmm2, %xmm4, %xmm4 + vpor %xmm0, %xmm7, %xmm7 + vpor %xmm1, %xmm4, %xmm4 + vpslld $31, %xmm7, %xmm0 + vpslld $30, %xmm7, %xmm1 + vpslld $25, %xmm7, %xmm2 + vpxor %xmm1, %xmm0, %xmm0 + vpxor %xmm2, %xmm0, %xmm0 + vmovdqa %xmm0, %xmm1 + vpsrldq $4, %xmm1, %xmm1 + vpslldq $12, %xmm0, %xmm0 + vpxor %xmm0, %xmm7, %xmm7 + vpsrld $0x01, %xmm7, %xmm2 + vpsrld $2, %xmm7, %xmm3 + vpsrld $7, %xmm7, %xmm0 + vpxor %xmm3, %xmm2, %xmm2 + vpxor %xmm0, %xmm2, %xmm2 + vpxor %xmm1, %xmm2, %xmm2 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm2, %xmm4, %xmm4 +L_AES_GCM_decrypt_avx1_calc_iv_done: + # T = Encrypt counter + vpxor %xmm0, %xmm0, %xmm0 + shll $3, %edx + vpinsrq $0x00, %rdx, %xmm0, %xmm0 + vpxor %xmm0, %xmm4, %xmm4 + # ghash_gfmul_avx + vpshufd $0x4e, %xmm4, %xmm1 + vpshufd $0x4e, %xmm5, %xmm2 + vpclmulqdq $0x11, %xmm4, %xmm5, %xmm3 + vpclmulqdq $0x00, %xmm4, %xmm5, %xmm0 + vpxor %xmm4, %xmm1, %xmm1 + vpxor %xmm5, %xmm2, %xmm2 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vmovdqa %xmm0, %xmm7 + vmovdqa %xmm3, %xmm4 + vpslldq $8, %xmm1, %xmm2 + vpsrldq $8, %xmm1, %xmm1 + vpxor %xmm2, %xmm7, %xmm7 + vpxor %xmm1, %xmm4, %xmm4 + vpsrld $31, %xmm7, %xmm0 + vpsrld $31, %xmm4, %xmm1 + vpslld $0x01, %xmm7, %xmm7 + vpslld $0x01, %xmm4, %xmm4 + vpsrldq $12, %xmm0, %xmm2 + vpslldq $4, %xmm0, %xmm0 + vpslldq $4, %xmm1, %xmm1 + vpor %xmm2, %xmm4, %xmm4 + vpor %xmm0, %xmm7, %xmm7 + vpor %xmm1, %xmm4, %xmm4 + vpslld $31, %xmm7, %xmm0 + vpslld $30, %xmm7, %xmm1 + vpslld $25, %xmm7, %xmm2 + vpxor %xmm1, %xmm0, %xmm0 + vpxor %xmm2, %xmm0, %xmm0 + vmovdqa %xmm0, %xmm1 + vpsrldq $4, %xmm1, %xmm1 + vpslldq $12, %xmm0, %xmm0 + vpxor %xmm0, %xmm7, %xmm7 + vpsrld $0x01, %xmm7, %xmm2 + vpsrld $2, %xmm7, %xmm3 + vpsrld $7, %xmm7, %xmm0 + vpxor %xmm3, %xmm2, %xmm2 + vpxor %xmm0, %xmm2, %xmm2 + vpxor %xmm1, %xmm2, %xmm2 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm2, %xmm4, %xmm4 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm4, %xmm4 + # Encrypt counter + vmovdqa (%r15), %xmm8 + vpxor %xmm4, %xmm8, %xmm8 + vaesenc 16(%r15), %xmm8, %xmm8 + vaesenc 32(%r15), %xmm8, %xmm8 + vaesenc 48(%r15), %xmm8, %xmm8 + vaesenc 64(%r15), %xmm8, %xmm8 + vaesenc 80(%r15), %xmm8, %xmm8 + vaesenc 96(%r15), %xmm8, %xmm8 + vaesenc 112(%r15), %xmm8, %xmm8 + vaesenc 128(%r15), %xmm8, %xmm8 + vaesenc 144(%r15), %xmm8, %xmm8 + cmpl $11, %r10d + vmovdqa 160(%r15), %xmm9 + jl L_AES_GCM_decrypt_avx1_calc_iv_2_aesenc_avx_last + vaesenc %xmm9, %xmm8, %xmm8 + vaesenc 176(%r15), %xmm8, %xmm8 + cmpl $13, %r10d + vmovdqa 192(%r15), %xmm9 + jl L_AES_GCM_decrypt_avx1_calc_iv_2_aesenc_avx_last + vaesenc %xmm9, %xmm8, %xmm8 + vaesenc 208(%r15), %xmm8, %xmm8 + vmovdqa 224(%r15), %xmm9 +L_AES_GCM_decrypt_avx1_calc_iv_2_aesenc_avx_last: + vaesenclast %xmm9, %xmm8, %xmm8 + vmovdqa %xmm8, 144(%rsp) +L_AES_GCM_decrypt_avx1_iv_done: + # Additional authentication data + movl %r11d, %edx + cmpl $0x00, %edx + je L_AES_GCM_decrypt_avx1_calc_aad_done + xorl %ecx, %ecx + cmpl $16, %edx + jl L_AES_GCM_decrypt_avx1_calc_aad_lt16 + andl $0xfffffff0, %edx +L_AES_GCM_decrypt_avx1_calc_aad_16_loop: + vmovdqu (%r12,%rcx,1), %xmm8 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm8, %xmm8 + vpxor %xmm8, %xmm6, %xmm6 + # ghash_gfmul_avx + vpshufd $0x4e, %xmm6, %xmm1 + vpshufd $0x4e, %xmm5, %xmm2 + vpclmulqdq $0x11, %xmm6, %xmm5, %xmm3 + vpclmulqdq $0x00, %xmm6, %xmm5, %xmm0 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm5, %xmm2, %xmm2 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vmovdqa %xmm0, %xmm7 + vmovdqa %xmm3, %xmm6 + vpslldq $8, %xmm1, %xmm2 + vpsrldq $8, %xmm1, %xmm1 + vpxor %xmm2, %xmm7, %xmm7 + vpxor %xmm1, %xmm6, %xmm6 + vpsrld $31, %xmm7, %xmm0 + vpsrld $31, %xmm6, %xmm1 + vpslld $0x01, %xmm7, %xmm7 + vpslld $0x01, %xmm6, %xmm6 + vpsrldq $12, %xmm0, %xmm2 + vpslldq $4, %xmm0, %xmm0 + vpslldq $4, %xmm1, %xmm1 + vpor %xmm2, %xmm6, %xmm6 + vpor %xmm0, %xmm7, %xmm7 + vpor %xmm1, %xmm6, %xmm6 + vpslld $31, %xmm7, %xmm0 + vpslld $30, %xmm7, %xmm1 + vpslld $25, %xmm7, %xmm2 + vpxor %xmm1, %xmm0, %xmm0 + vpxor %xmm2, %xmm0, %xmm0 + vmovdqa %xmm0, %xmm1 + vpsrldq $4, %xmm1, %xmm1 + vpslldq $12, %xmm0, %xmm0 + vpxor %xmm0, %xmm7, %xmm7 + vpsrld $0x01, %xmm7, %xmm2 + vpsrld $2, %xmm7, %xmm3 + vpsrld $7, %xmm7, %xmm0 + vpxor %xmm3, %xmm2, %xmm2 + vpxor %xmm0, %xmm2, %xmm2 + vpxor %xmm1, %xmm2, %xmm2 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm2, %xmm6, %xmm6 + addl $16, %ecx + cmpl %edx, %ecx + jl L_AES_GCM_decrypt_avx1_calc_aad_16_loop + movl %r11d, %edx + cmpl %edx, %ecx + je L_AES_GCM_decrypt_avx1_calc_aad_done +L_AES_GCM_decrypt_avx1_calc_aad_lt16: + subq $16, %rsp + vpxor %xmm8, %xmm8, %xmm8 + xorl %ebx, %ebx + vmovdqa %xmm8, (%rsp) +L_AES_GCM_decrypt_avx1_calc_aad_loop: + movzbl (%r12,%rcx,1), %r13d + movb %r13b, (%rsp,%rbx,1) + incl %ecx + incl %ebx + cmpl %edx, %ecx + jl L_AES_GCM_decrypt_avx1_calc_aad_loop + vmovdqa (%rsp), %xmm8 + addq $16, %rsp + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm8, %xmm8 + vpxor %xmm8, %xmm6, %xmm6 + # ghash_gfmul_avx + vpshufd $0x4e, %xmm6, %xmm1 + vpshufd $0x4e, %xmm5, %xmm2 + vpclmulqdq $0x11, %xmm6, %xmm5, %xmm3 + vpclmulqdq $0x00, %xmm6, %xmm5, %xmm0 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm5, %xmm2, %xmm2 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vmovdqa %xmm0, %xmm7 + vmovdqa %xmm3, %xmm6 + vpslldq $8, %xmm1, %xmm2 + vpsrldq $8, %xmm1, %xmm1 + vpxor %xmm2, %xmm7, %xmm7 + vpxor %xmm1, %xmm6, %xmm6 + vpsrld $31, %xmm7, %xmm0 + vpsrld $31, %xmm6, %xmm1 + vpslld $0x01, %xmm7, %xmm7 + vpslld $0x01, %xmm6, %xmm6 + vpsrldq $12, %xmm0, %xmm2 + vpslldq $4, %xmm0, %xmm0 + vpslldq $4, %xmm1, %xmm1 + vpor %xmm2, %xmm6, %xmm6 + vpor %xmm0, %xmm7, %xmm7 + vpor %xmm1, %xmm6, %xmm6 + vpslld $31, %xmm7, %xmm0 + vpslld $30, %xmm7, %xmm1 + vpslld $25, %xmm7, %xmm2 + vpxor %xmm1, %xmm0, %xmm0 + vpxor %xmm2, %xmm0, %xmm0 + vmovdqa %xmm0, %xmm1 + vpsrldq $4, %xmm1, %xmm1 + vpslldq $12, %xmm0, %xmm0 + vpxor %xmm0, %xmm7, %xmm7 + vpsrld $0x01, %xmm7, %xmm2 + vpsrld $2, %xmm7, %xmm3 + vpsrld $7, %xmm7, %xmm0 + vpxor %xmm3, %xmm2, %xmm2 + vpxor %xmm0, %xmm2, %xmm2 + vpxor %xmm1, %xmm2, %xmm2 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm2, %xmm6, %xmm6 +L_AES_GCM_decrypt_avx1_calc_aad_done: + # Calculate counter and H + vpsrlq $63, %xmm5, %xmm9 + vpsllq $0x01, %xmm5, %xmm8 + vpslldq $8, %xmm9, %xmm9 + vpor %xmm9, %xmm8, %xmm8 + vpshufd $0xff, %xmm5, %xmm5 + vpsrad $31, %xmm5, %xmm5 + vpshufb L_avx1_aes_gcm_bswap_epi64(%rip), %xmm4, %xmm4 + vpand L_avx1_aes_gcm_mod2_128(%rip), %xmm5, %xmm5 + vpaddd L_avx1_aes_gcm_one(%rip), %xmm4, %xmm4 + vpxor %xmm8, %xmm5, %xmm5 + vmovdqa %xmm4, 128(%rsp) + xorl %ebx, %ebx + cmpl $0x80, %r9d + movl %r9d, %r13d + jl L_AES_GCM_decrypt_avx1_done_128 + andl $0xffffff80, %r13d + vmovdqa %xmm6, %xmm2 + # H ^ 1 + vmovdqa %xmm5, (%rsp) + # H ^ 2 + vpclmulqdq $0x00, %xmm5, %xmm5, %xmm8 + vpclmulqdq $0x11, %xmm5, %xmm5, %xmm0 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm0, %xmm0 + vmovdqa %xmm0, 16(%rsp) + # H ^ 3 + # ghash_gfmul_red_avx + vpshufd $0x4e, %xmm5, %xmm9 + vpshufd $0x4e, %xmm0, %xmm10 + vpclmulqdq $0x11, %xmm5, %xmm0, %xmm11 + vpclmulqdq $0x00, %xmm5, %xmm0, %xmm8 + vpxor %xmm5, %xmm9, %xmm9 + vpxor %xmm0, %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm10, %xmm9, %xmm9 + vpxor %xmm8, %xmm9, %xmm9 + vpxor %xmm11, %xmm9, %xmm9 + vpslldq $8, %xmm9, %xmm10 + vpsrldq $8, %xmm9, %xmm9 + vpxor %xmm10, %xmm8, %xmm8 + vpxor %xmm9, %xmm11, %xmm1 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm1, %xmm1 + vmovdqa %xmm1, 32(%rsp) + # H ^ 4 + vpclmulqdq $0x00, %xmm0, %xmm0, %xmm8 + vpclmulqdq $0x11, %xmm0, %xmm0, %xmm3 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm3, %xmm3 + vmovdqa %xmm3, 48(%rsp) + # H ^ 5 + # ghash_gfmul_red_avx + vpshufd $0x4e, %xmm0, %xmm9 + vpshufd $0x4e, %xmm1, %xmm10 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm11 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm8 + vpxor %xmm0, %xmm9, %xmm9 + vpxor %xmm1, %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm10, %xmm9, %xmm9 + vpxor %xmm8, %xmm9, %xmm9 + vpxor %xmm11, %xmm9, %xmm9 + vpslldq $8, %xmm9, %xmm10 + vpsrldq $8, %xmm9, %xmm9 + vpxor %xmm10, %xmm8, %xmm8 + vpxor %xmm9, %xmm11, %xmm7 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm7, %xmm7 + vmovdqa %xmm7, 64(%rsp) + # H ^ 6 + vpclmulqdq $0x00, %xmm1, %xmm1, %xmm8 + vpclmulqdq $0x11, %xmm1, %xmm1, %xmm7 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm7, %xmm7 + vmovdqa %xmm7, 80(%rsp) + # H ^ 7 + # ghash_gfmul_red_avx + vpshufd $0x4e, %xmm1, %xmm9 + vpshufd $0x4e, %xmm3, %xmm10 + vpclmulqdq $0x11, %xmm1, %xmm3, %xmm11 + vpclmulqdq $0x00, %xmm1, %xmm3, %xmm8 + vpxor %xmm1, %xmm9, %xmm9 + vpxor %xmm3, %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm10, %xmm9, %xmm9 + vpxor %xmm8, %xmm9, %xmm9 + vpxor %xmm11, %xmm9, %xmm9 + vpslldq $8, %xmm9, %xmm10 + vpsrldq $8, %xmm9, %xmm9 + vpxor %xmm10, %xmm8, %xmm8 + vpxor %xmm9, %xmm11, %xmm7 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm7, %xmm7 + vmovdqa %xmm7, 96(%rsp) + # H ^ 8 + vpclmulqdq $0x00, %xmm3, %xmm3, %xmm8 + vpclmulqdq $0x11, %xmm3, %xmm3, %xmm7 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm7, %xmm7 + vmovdqa %xmm7, 112(%rsp) +L_AES_GCM_decrypt_avx1_ghash_128: + leaq (%rdi,%rbx,1), %rcx + leaq (%rsi,%rbx,1), %rdx + vmovdqa 128(%rsp), %xmm0 + vmovdqa L_avx1_aes_gcm_bswap_epi64(%rip), %xmm1 + vpshufb %xmm1, %xmm0, %xmm8 + vpaddd L_avx1_aes_gcm_one(%rip), %xmm0, %xmm9 + vpshufb %xmm1, %xmm9, %xmm9 + vpaddd L_avx1_aes_gcm_two(%rip), %xmm0, %xmm10 + vpshufb %xmm1, %xmm10, %xmm10 + vpaddd L_avx1_aes_gcm_three(%rip), %xmm0, %xmm11 + vpshufb %xmm1, %xmm11, %xmm11 + vpaddd L_avx1_aes_gcm_four(%rip), %xmm0, %xmm12 + vpshufb %xmm1, %xmm12, %xmm12 + vpaddd L_avx1_aes_gcm_five(%rip), %xmm0, %xmm13 + vpshufb %xmm1, %xmm13, %xmm13 + vpaddd L_avx1_aes_gcm_six(%rip), %xmm0, %xmm14 + vpshufb %xmm1, %xmm14, %xmm14 + vpaddd L_avx1_aes_gcm_seven(%rip), %xmm0, %xmm15 + vpshufb %xmm1, %xmm15, %xmm15 + vpaddd L_avx1_aes_gcm_eight(%rip), %xmm0, %xmm0 + vmovdqa (%r15), %xmm7 + vmovdqa %xmm0, 128(%rsp) + vpxor %xmm7, %xmm8, %xmm8 + vpxor %xmm7, %xmm9, %xmm9 + vpxor %xmm7, %xmm10, %xmm10 + vpxor %xmm7, %xmm11, %xmm11 + vpxor %xmm7, %xmm12, %xmm12 + vpxor %xmm7, %xmm13, %xmm13 + vpxor %xmm7, %xmm14, %xmm14 + vpxor %xmm7, %xmm15, %xmm15 + vmovdqa 112(%rsp), %xmm7 + vmovdqu (%rcx), %xmm0 + vaesenc 16(%r15), %xmm8, %xmm8 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vpxor %xmm2, %xmm0, %xmm0 + vpshufd $0x4e, %xmm7, %xmm1 + vpshufd $0x4e, %xmm0, %xmm5 + vpxor %xmm7, %xmm1, %xmm1 + vpxor %xmm0, %xmm5, %xmm5 + vpclmulqdq $0x11, %xmm7, %xmm0, %xmm3 + vaesenc 16(%r15), %xmm9, %xmm9 + vaesenc 16(%r15), %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm7, %xmm0, %xmm2 + vaesenc 16(%r15), %xmm11, %xmm11 + vaesenc 16(%r15), %xmm12, %xmm12 + vpclmulqdq $0x00, %xmm5, %xmm1, %xmm1 + vaesenc 16(%r15), %xmm13, %xmm13 + vaesenc 16(%r15), %xmm14, %xmm14 + vaesenc 16(%r15), %xmm15, %xmm15 + vpxor %xmm2, %xmm1, %xmm1 + vpxor %xmm3, %xmm1, %xmm1 + vmovdqa 96(%rsp), %xmm7 + vmovdqu 16(%rcx), %xmm0 + vpshufd $0x4e, %xmm7, %xmm4 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vaesenc 32(%r15), %xmm8, %xmm8 + vpxor %xmm7, %xmm4, %xmm4 + vpshufd $0x4e, %xmm0, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + vpclmulqdq $0x11, %xmm7, %xmm0, %xmm6 + vaesenc 32(%r15), %xmm9, %xmm9 + vaesenc 32(%r15), %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm7, %xmm0, %xmm7 + vaesenc 32(%r15), %xmm11, %xmm11 + vaesenc 32(%r15), %xmm12, %xmm12 + vpclmulqdq $0x00, %xmm5, %xmm4, %xmm4 + vaesenc 32(%r15), %xmm13, %xmm13 + vaesenc 32(%r15), %xmm14, %xmm14 + vaesenc 32(%r15), %xmm15, %xmm15 + vpxor %xmm7, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm6, %xmm3, %xmm3 + vpxor %xmm4, %xmm1, %xmm1 + vmovdqa 80(%rsp), %xmm7 + vmovdqu 32(%rcx), %xmm0 + vpshufd $0x4e, %xmm7, %xmm4 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vaesenc 48(%r15), %xmm8, %xmm8 + vpxor %xmm7, %xmm4, %xmm4 + vpshufd $0x4e, %xmm0, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + vpclmulqdq $0x11, %xmm7, %xmm0, %xmm6 + vaesenc 48(%r15), %xmm9, %xmm9 + vaesenc 48(%r15), %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm7, %xmm0, %xmm7 + vaesenc 48(%r15), %xmm11, %xmm11 + vaesenc 48(%r15), %xmm12, %xmm12 + vpclmulqdq $0x00, %xmm5, %xmm4, %xmm4 + vaesenc 48(%r15), %xmm13, %xmm13 + vaesenc 48(%r15), %xmm14, %xmm14 + vaesenc 48(%r15), %xmm15, %xmm15 + vpxor %xmm7, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm6, %xmm3, %xmm3 + vpxor %xmm4, %xmm1, %xmm1 + vmovdqa 64(%rsp), %xmm7 + vmovdqu 48(%rcx), %xmm0 + vpshufd $0x4e, %xmm7, %xmm4 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vaesenc 64(%r15), %xmm8, %xmm8 + vpxor %xmm7, %xmm4, %xmm4 + vpshufd $0x4e, %xmm0, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + vpclmulqdq $0x11, %xmm7, %xmm0, %xmm6 + vaesenc 64(%r15), %xmm9, %xmm9 + vaesenc 64(%r15), %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm7, %xmm0, %xmm7 + vaesenc 64(%r15), %xmm11, %xmm11 + vaesenc 64(%r15), %xmm12, %xmm12 + vpclmulqdq $0x00, %xmm5, %xmm4, %xmm4 + vaesenc 64(%r15), %xmm13, %xmm13 + vaesenc 64(%r15), %xmm14, %xmm14 + vaesenc 64(%r15), %xmm15, %xmm15 + vpxor %xmm7, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm6, %xmm3, %xmm3 + vpxor %xmm4, %xmm1, %xmm1 + vmovdqa 48(%rsp), %xmm7 + vmovdqu 64(%rcx), %xmm0 + vpshufd $0x4e, %xmm7, %xmm4 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vaesenc 80(%r15), %xmm8, %xmm8 + vpxor %xmm7, %xmm4, %xmm4 + vpshufd $0x4e, %xmm0, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + vpclmulqdq $0x11, %xmm7, %xmm0, %xmm6 + vaesenc 80(%r15), %xmm9, %xmm9 + vaesenc 80(%r15), %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm7, %xmm0, %xmm7 + vaesenc 80(%r15), %xmm11, %xmm11 + vaesenc 80(%r15), %xmm12, %xmm12 + vpclmulqdq $0x00, %xmm5, %xmm4, %xmm4 + vaesenc 80(%r15), %xmm13, %xmm13 + vaesenc 80(%r15), %xmm14, %xmm14 + vaesenc 80(%r15), %xmm15, %xmm15 + vpxor %xmm7, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm6, %xmm3, %xmm3 + vpxor %xmm4, %xmm1, %xmm1 + vmovdqa 32(%rsp), %xmm7 + vmovdqu 80(%rcx), %xmm0 + vpshufd $0x4e, %xmm7, %xmm4 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vaesenc 96(%r15), %xmm8, %xmm8 + vpxor %xmm7, %xmm4, %xmm4 + vpshufd $0x4e, %xmm0, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + vpclmulqdq $0x11, %xmm7, %xmm0, %xmm6 + vaesenc 96(%r15), %xmm9, %xmm9 + vaesenc 96(%r15), %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm7, %xmm0, %xmm7 + vaesenc 96(%r15), %xmm11, %xmm11 + vaesenc 96(%r15), %xmm12, %xmm12 + vpclmulqdq $0x00, %xmm5, %xmm4, %xmm4 + vaesenc 96(%r15), %xmm13, %xmm13 + vaesenc 96(%r15), %xmm14, %xmm14 + vaesenc 96(%r15), %xmm15, %xmm15 + vpxor %xmm7, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm6, %xmm3, %xmm3 + vpxor %xmm4, %xmm1, %xmm1 + vmovdqa 16(%rsp), %xmm7 + vmovdqu 96(%rcx), %xmm0 + vpshufd $0x4e, %xmm7, %xmm4 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vaesenc 112(%r15), %xmm8, %xmm8 + vpxor %xmm7, %xmm4, %xmm4 + vpshufd $0x4e, %xmm0, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + vpclmulqdq $0x11, %xmm7, %xmm0, %xmm6 + vaesenc 112(%r15), %xmm9, %xmm9 + vaesenc 112(%r15), %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm7, %xmm0, %xmm7 + vaesenc 112(%r15), %xmm11, %xmm11 + vaesenc 112(%r15), %xmm12, %xmm12 + vpclmulqdq $0x00, %xmm5, %xmm4, %xmm4 + vaesenc 112(%r15), %xmm13, %xmm13 + vaesenc 112(%r15), %xmm14, %xmm14 + vaesenc 112(%r15), %xmm15, %xmm15 + vpxor %xmm7, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm6, %xmm3, %xmm3 + vpxor %xmm4, %xmm1, %xmm1 + vmovdqa (%rsp), %xmm7 + vmovdqu 112(%rcx), %xmm0 + vpshufd $0x4e, %xmm7, %xmm4 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vaesenc 128(%r15), %xmm8, %xmm8 + vpxor %xmm7, %xmm4, %xmm4 + vpshufd $0x4e, %xmm0, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + vpclmulqdq $0x11, %xmm7, %xmm0, %xmm6 + vaesenc 128(%r15), %xmm9, %xmm9 + vaesenc 128(%r15), %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm7, %xmm0, %xmm7 + vaesenc 128(%r15), %xmm11, %xmm11 + vaesenc 128(%r15), %xmm12, %xmm12 + vpclmulqdq $0x00, %xmm5, %xmm4, %xmm4 + vaesenc 128(%r15), %xmm13, %xmm13 + vaesenc 128(%r15), %xmm14, %xmm14 + vaesenc 128(%r15), %xmm15, %xmm15 + vpxor %xmm7, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm6, %xmm3, %xmm3 + vpxor %xmm4, %xmm1, %xmm1 + vpslldq $8, %xmm1, %xmm5 + vpsrldq $8, %xmm1, %xmm1 + vaesenc 144(%r15), %xmm8, %xmm8 + vpxor %xmm5, %xmm2, %xmm2 + vpxor %xmm1, %xmm3, %xmm3 + vaesenc 144(%r15), %xmm9, %xmm9 + vpslld $31, %xmm2, %xmm7 + vpslld $30, %xmm2, %xmm4 + vpslld $25, %xmm2, %xmm5 + vaesenc 144(%r15), %xmm10, %xmm10 + vpxor %xmm4, %xmm7, %xmm7 + vpxor %xmm5, %xmm7, %xmm7 + vaesenc 144(%r15), %xmm11, %xmm11 + vpsrldq $4, %xmm7, %xmm4 + vpslldq $12, %xmm7, %xmm7 + vaesenc 144(%r15), %xmm12, %xmm12 + vpxor %xmm7, %xmm2, %xmm2 + vpsrld $0x01, %xmm2, %xmm5 + vaesenc 144(%r15), %xmm13, %xmm13 + vpsrld $2, %xmm2, %xmm1 + vpsrld $7, %xmm2, %xmm0 + vaesenc 144(%r15), %xmm14, %xmm14 + vpxor %xmm1, %xmm5, %xmm5 + vpxor %xmm0, %xmm5, %xmm5 + vaesenc 144(%r15), %xmm15, %xmm15 + vpxor %xmm4, %xmm5, %xmm5 + vpxor %xmm5, %xmm2, %xmm2 + vpxor %xmm3, %xmm2, %xmm2 + cmpl $11, %r10d + vmovdqa 160(%r15), %xmm7 + jl L_AES_GCM_decrypt_avx1_aesenc_128_ghash_avx_done + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 176(%r15), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + cmpl $13, %r10d + vmovdqa 192(%r15), %xmm7 + jl L_AES_GCM_decrypt_avx1_aesenc_128_ghash_avx_done + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 208(%r15), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 224(%r15), %xmm7 +L_AES_GCM_decrypt_avx1_aesenc_128_ghash_avx_done: + vaesenclast %xmm7, %xmm8, %xmm8 + vaesenclast %xmm7, %xmm9, %xmm9 + vmovdqu (%rcx), %xmm0 + vmovdqu 16(%rcx), %xmm1 + vpxor %xmm0, %xmm8, %xmm8 + vpxor %xmm1, %xmm9, %xmm9 + vmovdqu %xmm8, (%rdx) + vmovdqu %xmm9, 16(%rdx) + vaesenclast %xmm7, %xmm10, %xmm10 + vaesenclast %xmm7, %xmm11, %xmm11 + vmovdqu 32(%rcx), %xmm0 + vmovdqu 48(%rcx), %xmm1 + vpxor %xmm0, %xmm10, %xmm10 + vpxor %xmm1, %xmm11, %xmm11 + vmovdqu %xmm10, 32(%rdx) + vmovdqu %xmm11, 48(%rdx) + vaesenclast %xmm7, %xmm12, %xmm12 + vaesenclast %xmm7, %xmm13, %xmm13 + vmovdqu 64(%rcx), %xmm0 + vmovdqu 80(%rcx), %xmm1 + vpxor %xmm0, %xmm12, %xmm12 + vpxor %xmm1, %xmm13, %xmm13 + vmovdqu %xmm12, 64(%rdx) + vmovdqu %xmm13, 80(%rdx) + vaesenclast %xmm7, %xmm14, %xmm14 + vaesenclast %xmm7, %xmm15, %xmm15 + vmovdqu 96(%rcx), %xmm0 + vmovdqu 112(%rcx), %xmm1 + vpxor %xmm0, %xmm14, %xmm14 + vpxor %xmm1, %xmm15, %xmm15 + vmovdqu %xmm14, 96(%rdx) + vmovdqu %xmm15, 112(%rdx) + addl $0x80, %ebx + cmpl %r13d, %ebx + jl L_AES_GCM_decrypt_avx1_ghash_128 + vmovdqa %xmm2, %xmm6 + vmovdqa (%rsp), %xmm5 +L_AES_GCM_decrypt_avx1_done_128: + movl %r9d, %edx + cmpl %edx, %ebx + jge L_AES_GCM_decrypt_avx1_done_dec + movl %r9d, %r13d + andl $0xfffffff0, %r13d + cmpl %r13d, %ebx + jge L_AES_GCM_decrypt_avx1_last_block_done +L_AES_GCM_decrypt_avx1_last_block_start: + vmovdqu (%rdi,%rbx,1), %xmm13 + vmovdqa %xmm5, %xmm0 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm13, %xmm1 + vpxor %xmm6, %xmm1, %xmm1 + vmovdqa 128(%rsp), %xmm9 + vpshufb L_avx1_aes_gcm_bswap_epi64(%rip), %xmm9, %xmm8 + vpaddd L_avx1_aes_gcm_one(%rip), %xmm9, %xmm9 + vmovdqa %xmm9, 128(%rsp) + vpxor (%r15), %xmm8, %xmm8 + vpclmulqdq $16, %xmm0, %xmm1, %xmm10 + vaesenc 16(%r15), %xmm8, %xmm8 + vaesenc 32(%r15), %xmm8, %xmm8 + vpclmulqdq $0x01, %xmm0, %xmm1, %xmm11 + vaesenc 48(%r15), %xmm8, %xmm8 + vaesenc 64(%r15), %xmm8, %xmm8 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm12 + vaesenc 80(%r15), %xmm8, %xmm8 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm1 + vaesenc 96(%r15), %xmm8, %xmm8 + vpxor %xmm11, %xmm10, %xmm10 + vpslldq $8, %xmm10, %xmm2 + vpsrldq $8, %xmm10, %xmm10 + vaesenc 112(%r15), %xmm8, %xmm8 + vpxor %xmm12, %xmm2, %xmm2 + vpxor %xmm10, %xmm1, %xmm3 + vmovdqa L_avx1_aes_gcm_mod2_128(%rip), %xmm0 + vpclmulqdq $16, %xmm0, %xmm2, %xmm11 + vaesenc 128(%r15), %xmm8, %xmm8 + vpshufd $0x4e, %xmm2, %xmm10 + vpxor %xmm11, %xmm10, %xmm10 + vpclmulqdq $16, %xmm0, %xmm10, %xmm11 + vaesenc 144(%r15), %xmm8, %xmm8 + vpshufd $0x4e, %xmm10, %xmm10 + vpxor %xmm11, %xmm10, %xmm10 + vpxor %xmm3, %xmm10, %xmm6 + cmpl $11, %r10d + vmovdqa 160(%r15), %xmm9 + jl L_AES_GCM_decrypt_avx1_aesenc_gfmul_last + vaesenc %xmm9, %xmm8, %xmm8 + vaesenc 176(%r15), %xmm8, %xmm8 + cmpl $13, %r10d + vmovdqa 192(%r15), %xmm9 + jl L_AES_GCM_decrypt_avx1_aesenc_gfmul_last + vaesenc %xmm9, %xmm8, %xmm8 + vaesenc 208(%r15), %xmm8, %xmm8 + vmovdqa 224(%r15), %xmm9 +L_AES_GCM_decrypt_avx1_aesenc_gfmul_last: + vaesenclast %xmm9, %xmm8, %xmm8 + vmovdqa %xmm13, %xmm0 + vpxor %xmm0, %xmm8, %xmm8 + vmovdqu %xmm8, (%rsi,%rbx,1) + addl $16, %ebx + cmpl %r13d, %ebx + jl L_AES_GCM_decrypt_avx1_last_block_start +L_AES_GCM_decrypt_avx1_last_block_done: + movl %r9d, %ecx + movl %ecx, %edx + andl $15, %ecx + jz L_AES_GCM_decrypt_avx1_aesenc_last15_dec_avx_done + vmovdqa 128(%rsp), %xmm4 + vpshufb L_avx1_aes_gcm_bswap_epi64(%rip), %xmm4, %xmm4 + vpxor (%r15), %xmm4, %xmm4 + vaesenc 16(%r15), %xmm4, %xmm4 + vaesenc 32(%r15), %xmm4, %xmm4 + vaesenc 48(%r15), %xmm4, %xmm4 + vaesenc 64(%r15), %xmm4, %xmm4 + vaesenc 80(%r15), %xmm4, %xmm4 + vaesenc 96(%r15), %xmm4, %xmm4 + vaesenc 112(%r15), %xmm4, %xmm4 + vaesenc 128(%r15), %xmm4, %xmm4 + vaesenc 144(%r15), %xmm4, %xmm4 + cmpl $11, %r10d + vmovdqa 160(%r15), %xmm9 + jl L_AES_GCM_decrypt_avx1_aesenc_last15_dec_avx_aesenc_avx_last + vaesenc %xmm9, %xmm4, %xmm4 + vaesenc 176(%r15), %xmm4, %xmm4 + cmpl $13, %r10d + vmovdqa 192(%r15), %xmm9 + jl L_AES_GCM_decrypt_avx1_aesenc_last15_dec_avx_aesenc_avx_last + vaesenc %xmm9, %xmm4, %xmm4 + vaesenc 208(%r15), %xmm4, %xmm4 + vmovdqa 224(%r15), %xmm9 +L_AES_GCM_decrypt_avx1_aesenc_last15_dec_avx_aesenc_avx_last: + vaesenclast %xmm9, %xmm4, %xmm4 + subq $32, %rsp + xorl %ecx, %ecx + vmovdqa %xmm4, (%rsp) + vpxor %xmm0, %xmm0, %xmm0 + vmovdqa %xmm0, 16(%rsp) +L_AES_GCM_decrypt_avx1_aesenc_last15_dec_avx_loop: + movzbl (%rdi,%rbx,1), %r13d + movb %r13b, 16(%rsp,%rcx,1) + xorb (%rsp,%rcx,1), %r13b + movb %r13b, (%rsi,%rbx,1) + incl %ebx + incl %ecx + cmpl %edx, %ebx + jl L_AES_GCM_decrypt_avx1_aesenc_last15_dec_avx_loop + vmovdqa 16(%rsp), %xmm4 + addq $32, %rsp + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm4, %xmm4 + vpxor %xmm4, %xmm6, %xmm6 + # ghash_gfmul_red_avx + vpshufd $0x4e, %xmm5, %xmm9 + vpshufd $0x4e, %xmm6, %xmm10 + vpclmulqdq $0x11, %xmm5, %xmm6, %xmm11 + vpclmulqdq $0x00, %xmm5, %xmm6, %xmm8 + vpxor %xmm5, %xmm9, %xmm9 + vpxor %xmm6, %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm10, %xmm9, %xmm9 + vpxor %xmm8, %xmm9, %xmm9 + vpxor %xmm11, %xmm9, %xmm9 + vpslldq $8, %xmm9, %xmm10 + vpsrldq $8, %xmm9, %xmm9 + vpxor %xmm10, %xmm8, %xmm8 + vpxor %xmm9, %xmm11, %xmm6 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm6, %xmm6 +L_AES_GCM_decrypt_avx1_aesenc_last15_dec_avx_done: +L_AES_GCM_decrypt_avx1_done_dec: + movl %r9d, %edx + movl %r11d, %ecx + shlq $3, %rdx + shlq $3, %rcx + vpinsrq $0x00, %rdx, %xmm0, %xmm0 + vpinsrq $0x01, %rcx, %xmm0, %xmm0 + vpxor %xmm0, %xmm6, %xmm6 + # ghash_gfmul_red_avx + vpshufd $0x4e, %xmm5, %xmm9 + vpshufd $0x4e, %xmm6, %xmm10 + vpclmulqdq $0x11, %xmm5, %xmm6, %xmm11 + vpclmulqdq $0x00, %xmm5, %xmm6, %xmm8 + vpxor %xmm5, %xmm9, %xmm9 + vpxor %xmm6, %xmm10, %xmm10 + vpclmulqdq $0x00, %xmm10, %xmm9, %xmm9 + vpxor %xmm8, %xmm9, %xmm9 + vpxor %xmm11, %xmm9, %xmm9 + vpslldq $8, %xmm9, %xmm10 + vpsrldq $8, %xmm9, %xmm9 + vpxor %xmm10, %xmm8, %xmm8 + vpxor %xmm9, %xmm11, %xmm6 + vpslld $31, %xmm8, %xmm12 + vpslld $30, %xmm8, %xmm13 + vpslld $25, %xmm8, %xmm14 + vpxor %xmm13, %xmm12, %xmm12 + vpxor %xmm14, %xmm12, %xmm12 + vpsrldq $4, %xmm12, %xmm13 + vpslldq $12, %xmm12, %xmm12 + vpxor %xmm12, %xmm8, %xmm8 + vpsrld $0x01, %xmm8, %xmm14 + vpsrld $2, %xmm8, %xmm10 + vpsrld $7, %xmm8, %xmm9 + vpxor %xmm10, %xmm14, %xmm14 + vpxor %xmm9, %xmm14, %xmm14 + vpxor %xmm13, %xmm14, %xmm14 + vpxor %xmm8, %xmm14, %xmm14 + vpxor %xmm14, %xmm6, %xmm6 + vpshufb L_avx1_aes_gcm_bswap_mask(%rip), %xmm6, %xmm6 + vpxor 144(%rsp), %xmm6, %xmm0 + cmpl $16, %r14d + je L_AES_GCM_decrypt_avx1_cmp_tag_16 + subq $16, %rsp + xorq %rcx, %rcx + xorq %rbx, %rbx + vmovdqa %xmm0, (%rsp) +L_AES_GCM_decrypt_avx1_cmp_tag_loop: + movzbl (%rsp,%rcx,1), %r13d + xorb (%r8,%rcx,1), %r13b + orb %r13b, %bl + incl %ecx + cmpl %r14d, %ecx + jne L_AES_GCM_decrypt_avx1_cmp_tag_loop + cmpb $0x00, %bl + sete %bl + addq $16, %rsp + xorq %rcx, %rcx + jmp L_AES_GCM_decrypt_avx1_cmp_tag_done +L_AES_GCM_decrypt_avx1_cmp_tag_16: + vmovdqu (%r8), %xmm1 + vpcmpeqb %xmm1, %xmm0, %xmm0 + vpmovmskb %xmm0, %rdx + # %%edx == 0xFFFF then return 1 else => return 0 + xorl %ebx, %ebx + cmpl $0xffff, %edx + sete %bl +L_AES_GCM_decrypt_avx1_cmp_tag_done: + movl %ebx, (%rbp) + vzeroupper + addq $0xa8, %rsp + popq %rbp + popq %r15 + popq %r14 + popq %rbx + popq %r12 + popq %r13 + repz retq +#ifndef __APPLE__ +.size AES_GCM_decrypt_avx1,.-AES_GCM_decrypt_avx1 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX1 */ +#ifdef HAVE_INTEL_AVX2 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx2_aes_gcm_one: +.quad 0x0, 0x1 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx2_aes_gcm_two: +.quad 0x0, 0x2 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx2_aes_gcm_three: +.quad 0x0, 0x3 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx2_aes_gcm_four: +.quad 0x0, 0x4 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx2_aes_gcm_five: +.quad 0x0, 0x5 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx2_aes_gcm_six: +.quad 0x0, 0x6 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx2_aes_gcm_seven: +.quad 0x0, 0x7 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx2_aes_gcm_eight: +.quad 0x0, 0x8 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx2_aes_gcm_bswap_one: +.quad 0x0, 0x100000000000000 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx2_aes_gcm_bswap_epi64: +.quad 0x1020304050607, 0x8090a0b0c0d0e0f +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx2_aes_gcm_bswap_mask: +.quad 0x8090a0b0c0d0e0f, 0x1020304050607 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx2_aes_gcm_mod2_128: +.quad 0x1, 0xc200000000000000 +#ifndef __APPLE__ +.text +.globl AES_GCM_encrypt_avx2 +.type AES_GCM_encrypt_avx2,@function +.align 4 +AES_GCM_encrypt_avx2: +#else +.section __TEXT,__text +.globl _AES_GCM_encrypt_avx2 +.p2align 2 +_AES_GCM_encrypt_avx2: +#endif /* __APPLE__ */ + pushq %r13 + pushq %r12 + pushq %r15 + pushq %rbx + pushq %r14 + movq %rdx, %r12 + movq %rcx, %rax + movq %r8, %r15 + movq %rsi, %r8 + movl %r9d, %r10d + movl 48(%rsp), %r11d + movl 56(%rsp), %ebx + movl 64(%rsp), %r14d + movq 72(%rsp), %rsi + movl 80(%rsp), %r9d + subq $0xa0, %rsp + vpxor %xmm4, %xmm4, %xmm4 + vpxor %xmm6, %xmm6, %xmm6 + movl %ebx, %edx + cmpl $12, %edx + je L_AES_GCM_encrypt_avx2_iv_12 + # Calculate values when IV is not 12 bytes + # H = Encrypt X(=0) + vmovdqa (%rsi), %xmm5 + vaesenc 16(%rsi), %xmm5, %xmm5 + vaesenc 32(%rsi), %xmm5, %xmm5 + vaesenc 48(%rsi), %xmm5, %xmm5 + vaesenc 64(%rsi), %xmm5, %xmm5 + vaesenc 80(%rsi), %xmm5, %xmm5 + vaesenc 96(%rsi), %xmm5, %xmm5 + vaesenc 112(%rsi), %xmm5, %xmm5 + vaesenc 128(%rsi), %xmm5, %xmm5 + vaesenc 144(%rsi), %xmm5, %xmm5 + cmpl $11, %r9d + vmovdqa 160(%rsi), %xmm0 + jl L_AES_GCM_encrypt_avx2_calc_iv_1_aesenc_avx_last + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc 176(%rsi), %xmm5, %xmm5 + cmpl $13, %r9d + vmovdqa 192(%rsi), %xmm0 + jl L_AES_GCM_encrypt_avx2_calc_iv_1_aesenc_avx_last + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc 208(%rsi), %xmm5, %xmm5 + vmovdqa 224(%rsi), %xmm0 +L_AES_GCM_encrypt_avx2_calc_iv_1_aesenc_avx_last: + vaesenclast %xmm0, %xmm5, %xmm5 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm5, %xmm5 + # Calc counter + # Initialization vector + cmpl $0x00, %edx + movq $0x00, %rcx + je L_AES_GCM_encrypt_avx2_calc_iv_done + cmpl $16, %edx + jl L_AES_GCM_encrypt_avx2_calc_iv_lt16 + andl $0xfffffff0, %edx +L_AES_GCM_encrypt_avx2_calc_iv_16_loop: + vmovdqu (%rax,%rcx,1), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vpxor %xmm0, %xmm4, %xmm4 + # ghash_gfmul_avx + vpclmulqdq $16, %xmm4, %xmm5, %xmm2 + vpclmulqdq $0x01, %xmm4, %xmm5, %xmm1 + vpclmulqdq $0x00, %xmm4, %xmm5, %xmm0 + vpclmulqdq $0x11, %xmm4, %xmm5, %xmm3 + vpxor %xmm1, %xmm2, %xmm2 + vpslldq $8, %xmm2, %xmm1 + vpsrldq $8, %xmm2, %xmm2 + vpxor %xmm1, %xmm0, %xmm7 + vpxor %xmm2, %xmm3, %xmm4 + # ghash_mid + vpsrld $31, %xmm7, %xmm0 + vpsrld $31, %xmm4, %xmm1 + vpslld $0x01, %xmm7, %xmm7 + vpslld $0x01, %xmm4, %xmm4 + vpsrldq $12, %xmm0, %xmm2 + vpslldq $4, %xmm0, %xmm0 + vpslldq $4, %xmm1, %xmm1 + vpor %xmm2, %xmm4, %xmm4 + vpor %xmm0, %xmm7, %xmm7 + vpor %xmm1, %xmm4, %xmm4 + # ghash_red + vmovdqa L_avx2_aes_gcm_mod2_128(%rip), %xmm2 + vpclmulqdq $16, %xmm2, %xmm7, %xmm0 + vpshufd $0x4e, %xmm7, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpclmulqdq $16, %xmm2, %xmm1, %xmm0 + vpshufd $0x4e, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm1, %xmm4, %xmm4 + addl $16, %ecx + cmpl %edx, %ecx + jl L_AES_GCM_encrypt_avx2_calc_iv_16_loop + movl %ebx, %edx + cmpl %edx, %ecx + je L_AES_GCM_encrypt_avx2_calc_iv_done +L_AES_GCM_encrypt_avx2_calc_iv_lt16: + vpxor %xmm0, %xmm0, %xmm0 + xorl %ebx, %ebx + vmovdqa %xmm0, (%rsp) +L_AES_GCM_encrypt_avx2_calc_iv_loop: + movzbl (%rax,%rcx,1), %r13d + movb %r13b, (%rsp,%rbx,1) + incl %ecx + incl %ebx + cmpl %edx, %ecx + jl L_AES_GCM_encrypt_avx2_calc_iv_loop + vmovdqa (%rsp), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vpxor %xmm0, %xmm4, %xmm4 + # ghash_gfmul_avx + vpclmulqdq $16, %xmm4, %xmm5, %xmm2 + vpclmulqdq $0x01, %xmm4, %xmm5, %xmm1 + vpclmulqdq $0x00, %xmm4, %xmm5, %xmm0 + vpclmulqdq $0x11, %xmm4, %xmm5, %xmm3 + vpxor %xmm1, %xmm2, %xmm2 + vpslldq $8, %xmm2, %xmm1 + vpsrldq $8, %xmm2, %xmm2 + vpxor %xmm1, %xmm0, %xmm7 + vpxor %xmm2, %xmm3, %xmm4 + # ghash_mid + vpsrld $31, %xmm7, %xmm0 + vpsrld $31, %xmm4, %xmm1 + vpslld $0x01, %xmm7, %xmm7 + vpslld $0x01, %xmm4, %xmm4 + vpsrldq $12, %xmm0, %xmm2 + vpslldq $4, %xmm0, %xmm0 + vpslldq $4, %xmm1, %xmm1 + vpor %xmm2, %xmm4, %xmm4 + vpor %xmm0, %xmm7, %xmm7 + vpor %xmm1, %xmm4, %xmm4 + # ghash_red + vmovdqa L_avx2_aes_gcm_mod2_128(%rip), %xmm2 + vpclmulqdq $16, %xmm2, %xmm7, %xmm0 + vpshufd $0x4e, %xmm7, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpclmulqdq $16, %xmm2, %xmm1, %xmm0 + vpshufd $0x4e, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm1, %xmm4, %xmm4 +L_AES_GCM_encrypt_avx2_calc_iv_done: + # T = Encrypt counter + vpxor %xmm0, %xmm0, %xmm0 + shll $3, %edx + vpinsrq $0x00, %rdx, %xmm0, %xmm0 + vpxor %xmm0, %xmm4, %xmm4 + # ghash_gfmul_avx + vpclmulqdq $16, %xmm4, %xmm5, %xmm2 + vpclmulqdq $0x01, %xmm4, %xmm5, %xmm1 + vpclmulqdq $0x00, %xmm4, %xmm5, %xmm0 + vpclmulqdq $0x11, %xmm4, %xmm5, %xmm3 + vpxor %xmm1, %xmm2, %xmm2 + vpslldq $8, %xmm2, %xmm1 + vpsrldq $8, %xmm2, %xmm2 + vpxor %xmm1, %xmm0, %xmm7 + vpxor %xmm2, %xmm3, %xmm4 + # ghash_mid + vpsrld $31, %xmm7, %xmm0 + vpsrld $31, %xmm4, %xmm1 + vpslld $0x01, %xmm7, %xmm7 + vpslld $0x01, %xmm4, %xmm4 + vpsrldq $12, %xmm0, %xmm2 + vpslldq $4, %xmm0, %xmm0 + vpslldq $4, %xmm1, %xmm1 + vpor %xmm2, %xmm4, %xmm4 + vpor %xmm0, %xmm7, %xmm7 + vpor %xmm1, %xmm4, %xmm4 + # ghash_red + vmovdqa L_avx2_aes_gcm_mod2_128(%rip), %xmm2 + vpclmulqdq $16, %xmm2, %xmm7, %xmm0 + vpshufd $0x4e, %xmm7, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpclmulqdq $16, %xmm2, %xmm1, %xmm0 + vpshufd $0x4e, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm1, %xmm4, %xmm4 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm4, %xmm4 + # Encrypt counter + vmovdqa (%rsi), %xmm15 + vpxor %xmm4, %xmm15, %xmm15 + vaesenc 16(%rsi), %xmm15, %xmm15 + vaesenc 32(%rsi), %xmm15, %xmm15 + vaesenc 48(%rsi), %xmm15, %xmm15 + vaesenc 64(%rsi), %xmm15, %xmm15 + vaesenc 80(%rsi), %xmm15, %xmm15 + vaesenc 96(%rsi), %xmm15, %xmm15 + vaesenc 112(%rsi), %xmm15, %xmm15 + vaesenc 128(%rsi), %xmm15, %xmm15 + vaesenc 144(%rsi), %xmm15, %xmm15 + cmpl $11, %r9d + vmovdqa 160(%rsi), %xmm0 + jl L_AES_GCM_encrypt_avx2_calc_iv_2_aesenc_avx_last + vaesenc %xmm0, %xmm15, %xmm15 + vaesenc 176(%rsi), %xmm15, %xmm15 + cmpl $13, %r9d + vmovdqa 192(%rsi), %xmm0 + jl L_AES_GCM_encrypt_avx2_calc_iv_2_aesenc_avx_last + vaesenc %xmm0, %xmm15, %xmm15 + vaesenc 208(%rsi), %xmm15, %xmm15 + vmovdqa 224(%rsi), %xmm0 +L_AES_GCM_encrypt_avx2_calc_iv_2_aesenc_avx_last: + vaesenclast %xmm0, %xmm15, %xmm15 + jmp L_AES_GCM_encrypt_avx2_iv_done +L_AES_GCM_encrypt_avx2_iv_12: + # # Calculate values when IV is 12 bytes + # Set counter based on IV + vmovdqa L_avx2_aes_gcm_bswap_one(%rip), %xmm4 + vmovdqa (%rsi), %xmm5 + vpblendd $7, (%rax), %xmm4, %xmm4 + # H = Encrypt X(=0) and T = Encrypt counter + vmovdqa 16(%rsi), %xmm7 + vpxor %xmm5, %xmm4, %xmm15 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 32(%rsi), %xmm0 + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm15, %xmm15 + vmovdqa 48(%rsi), %xmm0 + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm15, %xmm15 + vmovdqa 64(%rsi), %xmm0 + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm15, %xmm15 + vmovdqa 80(%rsi), %xmm0 + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm15, %xmm15 + vmovdqa 96(%rsi), %xmm0 + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm15, %xmm15 + vmovdqa 112(%rsi), %xmm0 + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm15, %xmm15 + vmovdqa 128(%rsi), %xmm0 + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm15, %xmm15 + vmovdqa 144(%rsi), %xmm0 + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm15, %xmm15 + cmpl $11, %r9d + vmovdqa 160(%rsi), %xmm0 + jl L_AES_GCM_encrypt_avx2_calc_iv_12_last + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm15, %xmm15 + vmovdqa 176(%rsi), %xmm0 + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm15, %xmm15 + cmpl $13, %r9d + vmovdqa 192(%rsi), %xmm0 + jl L_AES_GCM_encrypt_avx2_calc_iv_12_last + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm15, %xmm15 + vmovdqa 208(%rsi), %xmm0 + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm15, %xmm15 + vmovdqa 224(%rsi), %xmm0 +L_AES_GCM_encrypt_avx2_calc_iv_12_last: + vaesenclast %xmm0, %xmm5, %xmm5 + vaesenclast %xmm0, %xmm15, %xmm15 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm5, %xmm5 +L_AES_GCM_encrypt_avx2_iv_done: + # Additional authentication data + movl %r11d, %edx + cmpl $0x00, %edx + je L_AES_GCM_encrypt_avx2_calc_aad_done + xorl %ecx, %ecx + cmpl $16, %edx + jl L_AES_GCM_encrypt_avx2_calc_aad_lt16 + andl $0xfffffff0, %edx +L_AES_GCM_encrypt_avx2_calc_aad_16_loop: + vmovdqu (%r12,%rcx,1), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vpxor %xmm0, %xmm6, %xmm6 + # ghash_gfmul_avx + vpclmulqdq $16, %xmm6, %xmm5, %xmm2 + vpclmulqdq $0x01, %xmm6, %xmm5, %xmm1 + vpclmulqdq $0x00, %xmm6, %xmm5, %xmm0 + vpclmulqdq $0x11, %xmm6, %xmm5, %xmm3 + vpxor %xmm1, %xmm2, %xmm2 + vpslldq $8, %xmm2, %xmm1 + vpsrldq $8, %xmm2, %xmm2 + vpxor %xmm1, %xmm0, %xmm7 + vpxor %xmm2, %xmm3, %xmm6 + # ghash_mid + vpsrld $31, %xmm7, %xmm0 + vpsrld $31, %xmm6, %xmm1 + vpslld $0x01, %xmm7, %xmm7 + vpslld $0x01, %xmm6, %xmm6 + vpsrldq $12, %xmm0, %xmm2 + vpslldq $4, %xmm0, %xmm0 + vpslldq $4, %xmm1, %xmm1 + vpor %xmm2, %xmm6, %xmm6 + vpor %xmm0, %xmm7, %xmm7 + vpor %xmm1, %xmm6, %xmm6 + # ghash_red + vmovdqa L_avx2_aes_gcm_mod2_128(%rip), %xmm2 + vpclmulqdq $16, %xmm2, %xmm7, %xmm0 + vpshufd $0x4e, %xmm7, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpclmulqdq $16, %xmm2, %xmm1, %xmm0 + vpshufd $0x4e, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm1, %xmm6, %xmm6 + addl $16, %ecx + cmpl %edx, %ecx + jl L_AES_GCM_encrypt_avx2_calc_aad_16_loop + movl %r11d, %edx + cmpl %edx, %ecx + je L_AES_GCM_encrypt_avx2_calc_aad_done +L_AES_GCM_encrypt_avx2_calc_aad_lt16: + vpxor %xmm0, %xmm0, %xmm0 + xorl %ebx, %ebx + vmovdqa %xmm0, (%rsp) +L_AES_GCM_encrypt_avx2_calc_aad_loop: + movzbl (%r12,%rcx,1), %r13d + movb %r13b, (%rsp,%rbx,1) + incl %ecx + incl %ebx + cmpl %edx, %ecx + jl L_AES_GCM_encrypt_avx2_calc_aad_loop + vmovdqa (%rsp), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vpxor %xmm0, %xmm6, %xmm6 + # ghash_gfmul_avx + vpclmulqdq $16, %xmm6, %xmm5, %xmm2 + vpclmulqdq $0x01, %xmm6, %xmm5, %xmm1 + vpclmulqdq $0x00, %xmm6, %xmm5, %xmm0 + vpclmulqdq $0x11, %xmm6, %xmm5, %xmm3 + vpxor %xmm1, %xmm2, %xmm2 + vpslldq $8, %xmm2, %xmm1 + vpsrldq $8, %xmm2, %xmm2 + vpxor %xmm1, %xmm0, %xmm7 + vpxor %xmm2, %xmm3, %xmm6 + # ghash_mid + vpsrld $31, %xmm7, %xmm0 + vpsrld $31, %xmm6, %xmm1 + vpslld $0x01, %xmm7, %xmm7 + vpslld $0x01, %xmm6, %xmm6 + vpsrldq $12, %xmm0, %xmm2 + vpslldq $4, %xmm0, %xmm0 + vpslldq $4, %xmm1, %xmm1 + vpor %xmm2, %xmm6, %xmm6 + vpor %xmm0, %xmm7, %xmm7 + vpor %xmm1, %xmm6, %xmm6 + # ghash_red + vmovdqa L_avx2_aes_gcm_mod2_128(%rip), %xmm2 + vpclmulqdq $16, %xmm2, %xmm7, %xmm0 + vpshufd $0x4e, %xmm7, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpclmulqdq $16, %xmm2, %xmm1, %xmm0 + vpshufd $0x4e, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm1, %xmm6, %xmm6 +L_AES_GCM_encrypt_avx2_calc_aad_done: + # Calculate counter and H + vpsrlq $63, %xmm5, %xmm1 + vpsllq $0x01, %xmm5, %xmm0 + vpslldq $8, %xmm1, %xmm1 + vpor %xmm1, %xmm0, %xmm0 + vpshufd $0xff, %xmm5, %xmm5 + vpsrad $31, %xmm5, %xmm5 + vpshufb L_avx2_aes_gcm_bswap_epi64(%rip), %xmm4, %xmm4 + vpand L_avx2_aes_gcm_mod2_128(%rip), %xmm5, %xmm5 + vpaddd L_avx2_aes_gcm_one(%rip), %xmm4, %xmm4 + vpxor %xmm0, %xmm5, %xmm5 + xorl %ebx, %ebx + cmpl $0x80, %r10d + movl %r10d, %r13d + jl L_AES_GCM_encrypt_avx2_done_128 + andl $0xffffff80, %r13d + vmovdqa %xmm4, 128(%rsp) + vmovdqa %xmm15, 144(%rsp) + vmovdqa L_avx2_aes_gcm_mod2_128(%rip), %xmm3 + # H ^ 1 and H ^ 2 + vpclmulqdq $0x00, %xmm5, %xmm5, %xmm9 + vpclmulqdq $0x11, %xmm5, %xmm5, %xmm10 + vpclmulqdq $16, %xmm3, %xmm9, %xmm8 + vpshufd $0x4e, %xmm9, %xmm9 + vpxor %xmm8, %xmm9, %xmm9 + vpclmulqdq $16, %xmm3, %xmm9, %xmm8 + vpshufd $0x4e, %xmm9, %xmm9 + vpxor %xmm8, %xmm9, %xmm9 + vpxor %xmm9, %xmm10, %xmm0 + vmovdqa %xmm5, (%rsp) + vmovdqa %xmm0, 16(%rsp) + # H ^ 3 and H ^ 4 + vpclmulqdq $16, %xmm5, %xmm0, %xmm11 + vpclmulqdq $0x01, %xmm5, %xmm0, %xmm10 + vpclmulqdq $0x00, %xmm5, %xmm0, %xmm9 + vpclmulqdq $0x11, %xmm5, %xmm0, %xmm12 + vpclmulqdq $0x00, %xmm0, %xmm0, %xmm13 + vpclmulqdq $0x11, %xmm0, %xmm0, %xmm14 + vpxor %xmm10, %xmm11, %xmm11 + vpslldq $8, %xmm11, %xmm10 + vpsrldq $8, %xmm11, %xmm11 + vpxor %xmm9, %xmm10, %xmm10 + vpclmulqdq $16, %xmm3, %xmm13, %xmm8 + vpclmulqdq $16, %xmm3, %xmm10, %xmm9 + vpshufd $0x4e, %xmm10, %xmm10 + vpshufd $0x4e, %xmm13, %xmm13 + vpxor %xmm9, %xmm10, %xmm10 + vpxor %xmm8, %xmm13, %xmm13 + vpclmulqdq $16, %xmm3, %xmm10, %xmm9 + vpclmulqdq $16, %xmm3, %xmm13, %xmm8 + vpshufd $0x4e, %xmm10, %xmm10 + vpshufd $0x4e, %xmm13, %xmm13 + vpxor %xmm11, %xmm12, %xmm12 + vpxor %xmm8, %xmm13, %xmm13 + vpxor %xmm12, %xmm10, %xmm10 + vpxor %xmm14, %xmm13, %xmm2 + vpxor %xmm9, %xmm10, %xmm1 + vmovdqa %xmm1, 32(%rsp) + vmovdqa %xmm2, 48(%rsp) + # H ^ 5 and H ^ 6 + vpclmulqdq $16, %xmm0, %xmm1, %xmm11 + vpclmulqdq $0x01, %xmm0, %xmm1, %xmm10 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm9 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm12 + vpclmulqdq $0x00, %xmm1, %xmm1, %xmm13 + vpclmulqdq $0x11, %xmm1, %xmm1, %xmm14 + vpxor %xmm10, %xmm11, %xmm11 + vpslldq $8, %xmm11, %xmm10 + vpsrldq $8, %xmm11, %xmm11 + vpxor %xmm9, %xmm10, %xmm10 + vpclmulqdq $16, %xmm3, %xmm13, %xmm8 + vpclmulqdq $16, %xmm3, %xmm10, %xmm9 + vpshufd $0x4e, %xmm10, %xmm10 + vpshufd $0x4e, %xmm13, %xmm13 + vpxor %xmm9, %xmm10, %xmm10 + vpxor %xmm8, %xmm13, %xmm13 + vpclmulqdq $16, %xmm3, %xmm10, %xmm9 + vpclmulqdq $16, %xmm3, %xmm13, %xmm8 + vpshufd $0x4e, %xmm10, %xmm10 + vpshufd $0x4e, %xmm13, %xmm13 + vpxor %xmm11, %xmm12, %xmm12 + vpxor %xmm8, %xmm13, %xmm13 + vpxor %xmm12, %xmm10, %xmm10 + vpxor %xmm14, %xmm13, %xmm0 + vpxor %xmm9, %xmm10, %xmm7 + vmovdqa %xmm7, 64(%rsp) + vmovdqa %xmm0, 80(%rsp) + # H ^ 7 and H ^ 8 + vpclmulqdq $16, %xmm1, %xmm2, %xmm11 + vpclmulqdq $0x01, %xmm1, %xmm2, %xmm10 + vpclmulqdq $0x00, %xmm1, %xmm2, %xmm9 + vpclmulqdq $0x11, %xmm1, %xmm2, %xmm12 + vpclmulqdq $0x00, %xmm2, %xmm2, %xmm13 + vpclmulqdq $0x11, %xmm2, %xmm2, %xmm14 + vpxor %xmm10, %xmm11, %xmm11 + vpslldq $8, %xmm11, %xmm10 + vpsrldq $8, %xmm11, %xmm11 + vpxor %xmm9, %xmm10, %xmm10 + vpclmulqdq $16, %xmm3, %xmm13, %xmm8 + vpclmulqdq $16, %xmm3, %xmm10, %xmm9 + vpshufd $0x4e, %xmm10, %xmm10 + vpshufd $0x4e, %xmm13, %xmm13 + vpxor %xmm9, %xmm10, %xmm10 + vpxor %xmm8, %xmm13, %xmm13 + vpclmulqdq $16, %xmm3, %xmm10, %xmm9 + vpclmulqdq $16, %xmm3, %xmm13, %xmm8 + vpshufd $0x4e, %xmm10, %xmm10 + vpshufd $0x4e, %xmm13, %xmm13 + vpxor %xmm11, %xmm12, %xmm12 + vpxor %xmm8, %xmm13, %xmm13 + vpxor %xmm12, %xmm10, %xmm10 + vpxor %xmm14, %xmm13, %xmm0 + vpxor %xmm9, %xmm10, %xmm7 + vmovdqa %xmm7, 96(%rsp) + vmovdqa %xmm0, 112(%rsp) + # First 128 bytes of input + # aesenc_128 + # aesenc_ctr + vmovdqa 128(%rsp), %xmm0 + vmovdqa L_avx2_aes_gcm_bswap_epi64(%rip), %xmm1 + vpaddd L_avx2_aes_gcm_one(%rip), %xmm0, %xmm9 + vpshufb %xmm1, %xmm0, %xmm8 + vpaddd L_avx2_aes_gcm_two(%rip), %xmm0, %xmm10 + vpshufb %xmm1, %xmm9, %xmm9 + vpaddd L_avx2_aes_gcm_three(%rip), %xmm0, %xmm11 + vpshufb %xmm1, %xmm10, %xmm10 + vpaddd L_avx2_aes_gcm_four(%rip), %xmm0, %xmm12 + vpshufb %xmm1, %xmm11, %xmm11 + vpaddd L_avx2_aes_gcm_five(%rip), %xmm0, %xmm13 + vpshufb %xmm1, %xmm12, %xmm12 + vpaddd L_avx2_aes_gcm_six(%rip), %xmm0, %xmm14 + vpshufb %xmm1, %xmm13, %xmm13 + vpaddd L_avx2_aes_gcm_seven(%rip), %xmm0, %xmm15 + vpshufb %xmm1, %xmm14, %xmm14 + vpaddd L_avx2_aes_gcm_eight(%rip), %xmm0, %xmm0 + vpshufb %xmm1, %xmm15, %xmm15 + # aesenc_xor + vmovdqa (%rsi), %xmm7 + vmovdqa %xmm0, 128(%rsp) + vpxor %xmm7, %xmm8, %xmm8 + vpxor %xmm7, %xmm9, %xmm9 + vpxor %xmm7, %xmm10, %xmm10 + vpxor %xmm7, %xmm11, %xmm11 + vpxor %xmm7, %xmm12, %xmm12 + vpxor %xmm7, %xmm13, %xmm13 + vpxor %xmm7, %xmm14, %xmm14 + vpxor %xmm7, %xmm15, %xmm15 + vmovdqa 16(%rsi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 32(%rsi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 48(%rsi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 64(%rsi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 80(%rsi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 96(%rsi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 112(%rsi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 128(%rsi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 144(%rsi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + cmpl $11, %r9d + vmovdqa 160(%rsi), %xmm7 + jl L_AES_GCM_encrypt_avx2_aesenc_128_enc_done + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 176(%rsi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + cmpl $13, %r9d + vmovdqa 192(%rsi), %xmm7 + jl L_AES_GCM_encrypt_avx2_aesenc_128_enc_done + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 208(%rsi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 224(%rsi), %xmm7 +L_AES_GCM_encrypt_avx2_aesenc_128_enc_done: + # aesenc_last + vaesenclast %xmm7, %xmm8, %xmm8 + vaesenclast %xmm7, %xmm9, %xmm9 + vaesenclast %xmm7, %xmm10, %xmm10 + vaesenclast %xmm7, %xmm11, %xmm11 + vmovdqu (%rdi), %xmm0 + vmovdqu 16(%rdi), %xmm1 + vmovdqu 32(%rdi), %xmm2 + vmovdqu 48(%rdi), %xmm3 + vpxor %xmm0, %xmm8, %xmm8 + vpxor %xmm1, %xmm9, %xmm9 + vpxor %xmm2, %xmm10, %xmm10 + vpxor %xmm3, %xmm11, %xmm11 + vmovdqu %xmm8, (%r8) + vmovdqu %xmm9, 16(%r8) + vmovdqu %xmm10, 32(%r8) + vmovdqu %xmm11, 48(%r8) + vaesenclast %xmm7, %xmm12, %xmm12 + vaesenclast %xmm7, %xmm13, %xmm13 + vaesenclast %xmm7, %xmm14, %xmm14 + vaesenclast %xmm7, %xmm15, %xmm15 + vmovdqu 64(%rdi), %xmm0 + vmovdqu 80(%rdi), %xmm1 + vmovdqu 96(%rdi), %xmm2 + vmovdqu 112(%rdi), %xmm3 + vpxor %xmm0, %xmm12, %xmm12 + vpxor %xmm1, %xmm13, %xmm13 + vpxor %xmm2, %xmm14, %xmm14 + vpxor %xmm3, %xmm15, %xmm15 + vmovdqu %xmm12, 64(%r8) + vmovdqu %xmm13, 80(%r8) + vmovdqu %xmm14, 96(%r8) + vmovdqu %xmm15, 112(%r8) + cmpl $0x80, %r13d + movl $0x80, %ebx + jle L_AES_GCM_encrypt_avx2_end_128 + # More 128 bytes of input +L_AES_GCM_encrypt_avx2_ghash_128: + # aesenc_128_ghash + leaq (%rdi,%rbx,1), %rcx + leaq (%r8,%rbx,1), %rdx + # aesenc_ctr + vmovdqa 128(%rsp), %xmm0 + vmovdqa L_avx2_aes_gcm_bswap_epi64(%rip), %xmm1 + vpaddd L_avx2_aes_gcm_one(%rip), %xmm0, %xmm9 + vpshufb %xmm1, %xmm0, %xmm8 + vpaddd L_avx2_aes_gcm_two(%rip), %xmm0, %xmm10 + vpshufb %xmm1, %xmm9, %xmm9 + vpaddd L_avx2_aes_gcm_three(%rip), %xmm0, %xmm11 + vpshufb %xmm1, %xmm10, %xmm10 + vpaddd L_avx2_aes_gcm_four(%rip), %xmm0, %xmm12 + vpshufb %xmm1, %xmm11, %xmm11 + vpaddd L_avx2_aes_gcm_five(%rip), %xmm0, %xmm13 + vpshufb %xmm1, %xmm12, %xmm12 + vpaddd L_avx2_aes_gcm_six(%rip), %xmm0, %xmm14 + vpshufb %xmm1, %xmm13, %xmm13 + vpaddd L_avx2_aes_gcm_seven(%rip), %xmm0, %xmm15 + vpshufb %xmm1, %xmm14, %xmm14 + vpaddd L_avx2_aes_gcm_eight(%rip), %xmm0, %xmm0 + vpshufb %xmm1, %xmm15, %xmm15 + # aesenc_xor + vmovdqa (%rsi), %xmm7 + vmovdqa %xmm0, 128(%rsp) + vpxor %xmm7, %xmm8, %xmm8 + vpxor %xmm7, %xmm9, %xmm9 + vpxor %xmm7, %xmm10, %xmm10 + vpxor %xmm7, %xmm11, %xmm11 + vpxor %xmm7, %xmm12, %xmm12 + vpxor %xmm7, %xmm13, %xmm13 + vpxor %xmm7, %xmm14, %xmm14 + vpxor %xmm7, %xmm15, %xmm15 + # aesenc_pclmul_1 + vmovdqu -128(%rdx), %xmm1 + vmovdqu 16(%rsi), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm1, %xmm1 + vmovdqa 112(%rsp), %xmm2 + vpxor %xmm6, %xmm1, %xmm1 + vpclmulqdq $16, %xmm2, %xmm1, %xmm5 + vpclmulqdq $0x01, %xmm2, %xmm1, %xmm3 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm6 + vpclmulqdq $0x11, %xmm2, %xmm1, %xmm7 + vaesenc %xmm0, %xmm8, %xmm8 + vaesenc %xmm0, %xmm9, %xmm9 + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc %xmm0, %xmm12, %xmm12 + vaesenc %xmm0, %xmm13, %xmm13 + vaesenc %xmm0, %xmm14, %xmm14 + vaesenc %xmm0, %xmm15, %xmm15 + # aesenc_pclmul_2 + vmovdqu -112(%rdx), %xmm1 + vmovdqa 96(%rsp), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm1, %xmm1 + vpxor %xmm3, %xmm5, %xmm5 + vpclmulqdq $16, %xmm0, %xmm1, %xmm2 + vpclmulqdq $0x01, %xmm0, %xmm1, %xmm3 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm4 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm1 + vmovdqu 32(%rsi), %xmm0 + vpxor %xmm1, %xmm7, %xmm7 + vaesenc %xmm0, %xmm8, %xmm8 + vaesenc %xmm0, %xmm9, %xmm9 + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc %xmm0, %xmm12, %xmm12 + vaesenc %xmm0, %xmm13, %xmm13 + vaesenc %xmm0, %xmm14, %xmm14 + vaesenc %xmm0, %xmm15, %xmm15 + # aesenc_pclmul_n + vmovdqu -96(%rdx), %xmm1 + vmovdqa 80(%rsp), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm1, %xmm1 + vpxor %xmm2, %xmm5, %xmm5 + vpclmulqdq $16, %xmm0, %xmm1, %xmm2 + vpxor %xmm3, %xmm5, %xmm5 + vpclmulqdq $0x01, %xmm0, %xmm1, %xmm3 + vpxor %xmm4, %xmm6, %xmm6 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm4 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm1 + vmovdqu 48(%rsi), %xmm0 + vpxor %xmm1, %xmm7, %xmm7 + vaesenc %xmm0, %xmm8, %xmm8 + vaesenc %xmm0, %xmm9, %xmm9 + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc %xmm0, %xmm12, %xmm12 + vaesenc %xmm0, %xmm13, %xmm13 + vaesenc %xmm0, %xmm14, %xmm14 + vaesenc %xmm0, %xmm15, %xmm15 + # aesenc_pclmul_n + vmovdqu -80(%rdx), %xmm1 + vmovdqa 64(%rsp), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm1, %xmm1 + vpxor %xmm2, %xmm5, %xmm5 + vpclmulqdq $16, %xmm0, %xmm1, %xmm2 + vpxor %xmm3, %xmm5, %xmm5 + vpclmulqdq $0x01, %xmm0, %xmm1, %xmm3 + vpxor %xmm4, %xmm6, %xmm6 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm4 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm1 + vmovdqu 64(%rsi), %xmm0 + vpxor %xmm1, %xmm7, %xmm7 + vaesenc %xmm0, %xmm8, %xmm8 + vaesenc %xmm0, %xmm9, %xmm9 + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc %xmm0, %xmm12, %xmm12 + vaesenc %xmm0, %xmm13, %xmm13 + vaesenc %xmm0, %xmm14, %xmm14 + vaesenc %xmm0, %xmm15, %xmm15 + # aesenc_pclmul_n + vmovdqu -64(%rdx), %xmm1 + vmovdqa 48(%rsp), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm1, %xmm1 + vpxor %xmm2, %xmm5, %xmm5 + vpclmulqdq $16, %xmm0, %xmm1, %xmm2 + vpxor %xmm3, %xmm5, %xmm5 + vpclmulqdq $0x01, %xmm0, %xmm1, %xmm3 + vpxor %xmm4, %xmm6, %xmm6 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm4 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm1 + vmovdqu 80(%rsi), %xmm0 + vpxor %xmm1, %xmm7, %xmm7 + vaesenc %xmm0, %xmm8, %xmm8 + vaesenc %xmm0, %xmm9, %xmm9 + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc %xmm0, %xmm12, %xmm12 + vaesenc %xmm0, %xmm13, %xmm13 + vaesenc %xmm0, %xmm14, %xmm14 + vaesenc %xmm0, %xmm15, %xmm15 + # aesenc_pclmul_n + vmovdqu -48(%rdx), %xmm1 + vmovdqa 32(%rsp), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm1, %xmm1 + vpxor %xmm2, %xmm5, %xmm5 + vpclmulqdq $16, %xmm0, %xmm1, %xmm2 + vpxor %xmm3, %xmm5, %xmm5 + vpclmulqdq $0x01, %xmm0, %xmm1, %xmm3 + vpxor %xmm4, %xmm6, %xmm6 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm4 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm1 + vmovdqu 96(%rsi), %xmm0 + vpxor %xmm1, %xmm7, %xmm7 + vaesenc %xmm0, %xmm8, %xmm8 + vaesenc %xmm0, %xmm9, %xmm9 + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc %xmm0, %xmm12, %xmm12 + vaesenc %xmm0, %xmm13, %xmm13 + vaesenc %xmm0, %xmm14, %xmm14 + vaesenc %xmm0, %xmm15, %xmm15 + # aesenc_pclmul_n + vmovdqu -32(%rdx), %xmm1 + vmovdqa 16(%rsp), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm1, %xmm1 + vpxor %xmm2, %xmm5, %xmm5 + vpclmulqdq $16, %xmm0, %xmm1, %xmm2 + vpxor %xmm3, %xmm5, %xmm5 + vpclmulqdq $0x01, %xmm0, %xmm1, %xmm3 + vpxor %xmm4, %xmm6, %xmm6 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm4 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm1 + vmovdqu 112(%rsi), %xmm0 + vpxor %xmm1, %xmm7, %xmm7 + vaesenc %xmm0, %xmm8, %xmm8 + vaesenc %xmm0, %xmm9, %xmm9 + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc %xmm0, %xmm12, %xmm12 + vaesenc %xmm0, %xmm13, %xmm13 + vaesenc %xmm0, %xmm14, %xmm14 + vaesenc %xmm0, %xmm15, %xmm15 + # aesenc_pclmul_n + vmovdqu -16(%rdx), %xmm1 + vmovdqa (%rsp), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm1, %xmm1 + vpxor %xmm2, %xmm5, %xmm5 + vpclmulqdq $16, %xmm0, %xmm1, %xmm2 + vpxor %xmm3, %xmm5, %xmm5 + vpclmulqdq $0x01, %xmm0, %xmm1, %xmm3 + vpxor %xmm4, %xmm6, %xmm6 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm4 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm1 + vmovdqu 128(%rsi), %xmm0 + vpxor %xmm1, %xmm7, %xmm7 + vaesenc %xmm0, %xmm8, %xmm8 + vaesenc %xmm0, %xmm9, %xmm9 + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc %xmm0, %xmm12, %xmm12 + vaesenc %xmm0, %xmm13, %xmm13 + vaesenc %xmm0, %xmm14, %xmm14 + vaesenc %xmm0, %xmm15, %xmm15 + # aesenc_pclmul_l + vpxor %xmm2, %xmm5, %xmm5 + vpxor %xmm4, %xmm6, %xmm6 + vpxor %xmm3, %xmm5, %xmm5 + vpslldq $8, %xmm5, %xmm1 + vpsrldq $8, %xmm5, %xmm5 + vmovdqa 144(%rsi), %xmm4 + vmovdqa L_avx2_aes_gcm_mod2_128(%rip), %xmm0 + vaesenc %xmm4, %xmm8, %xmm8 + vpxor %xmm1, %xmm6, %xmm6 + vpxor %xmm5, %xmm7, %xmm7 + vpclmulqdq $16, %xmm0, %xmm6, %xmm3 + vaesenc %xmm4, %xmm9, %xmm9 + vaesenc %xmm4, %xmm10, %xmm10 + vaesenc %xmm4, %xmm11, %xmm11 + vpshufd $0x4e, %xmm6, %xmm6 + vpxor %xmm3, %xmm6, %xmm6 + vpclmulqdq $16, %xmm0, %xmm6, %xmm3 + vaesenc %xmm4, %xmm12, %xmm12 + vaesenc %xmm4, %xmm13, %xmm13 + vaesenc %xmm4, %xmm14, %xmm14 + vpshufd $0x4e, %xmm6, %xmm6 + vpxor %xmm3, %xmm6, %xmm6 + vpxor %xmm7, %xmm6, %xmm6 + vaesenc %xmm4, %xmm15, %xmm15 + cmpl $11, %r9d + vmovdqa 160(%rsi), %xmm7 + jl L_AES_GCM_encrypt_avx2_aesenc_128_ghash_avx_done + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 176(%rsi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + cmpl $13, %r9d + vmovdqa 192(%rsi), %xmm7 + jl L_AES_GCM_encrypt_avx2_aesenc_128_ghash_avx_done + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 208(%rsi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 224(%rsi), %xmm7 +L_AES_GCM_encrypt_avx2_aesenc_128_ghash_avx_done: + # aesenc_last + vaesenclast %xmm7, %xmm8, %xmm8 + vaesenclast %xmm7, %xmm9, %xmm9 + vaesenclast %xmm7, %xmm10, %xmm10 + vaesenclast %xmm7, %xmm11, %xmm11 + vmovdqu (%rcx), %xmm0 + vmovdqu 16(%rcx), %xmm1 + vmovdqu 32(%rcx), %xmm2 + vmovdqu 48(%rcx), %xmm3 + vpxor %xmm0, %xmm8, %xmm8 + vpxor %xmm1, %xmm9, %xmm9 + vpxor %xmm2, %xmm10, %xmm10 + vpxor %xmm3, %xmm11, %xmm11 + vmovdqu %xmm8, (%rdx) + vmovdqu %xmm9, 16(%rdx) + vmovdqu %xmm10, 32(%rdx) + vmovdqu %xmm11, 48(%rdx) + vaesenclast %xmm7, %xmm12, %xmm12 + vaesenclast %xmm7, %xmm13, %xmm13 + vaesenclast %xmm7, %xmm14, %xmm14 + vaesenclast %xmm7, %xmm15, %xmm15 + vmovdqu 64(%rcx), %xmm0 + vmovdqu 80(%rcx), %xmm1 + vmovdqu 96(%rcx), %xmm2 + vmovdqu 112(%rcx), %xmm3 + vpxor %xmm0, %xmm12, %xmm12 + vpxor %xmm1, %xmm13, %xmm13 + vpxor %xmm2, %xmm14, %xmm14 + vpxor %xmm3, %xmm15, %xmm15 + vmovdqu %xmm12, 64(%rdx) + vmovdqu %xmm13, 80(%rdx) + vmovdqu %xmm14, 96(%rdx) + vmovdqu %xmm15, 112(%rdx) + # aesenc_128_ghash - end + addl $0x80, %ebx + cmpl %r13d, %ebx + jl L_AES_GCM_encrypt_avx2_ghash_128 +L_AES_GCM_encrypt_avx2_end_128: + vmovdqa L_avx2_aes_gcm_bswap_mask(%rip), %xmm4 + vpshufb %xmm4, %xmm8, %xmm8 + vpshufb %xmm4, %xmm9, %xmm9 + vpshufb %xmm4, %xmm10, %xmm10 + vpshufb %xmm4, %xmm11, %xmm11 + vpshufb %xmm4, %xmm12, %xmm12 + vpshufb %xmm4, %xmm13, %xmm13 + vpshufb %xmm4, %xmm14, %xmm14 + vpshufb %xmm4, %xmm15, %xmm15 + vpxor %xmm6, %xmm8, %xmm8 + vmovdqu (%rsp), %xmm7 + vpclmulqdq $16, %xmm15, %xmm7, %xmm5 + vpclmulqdq $0x01, %xmm15, %xmm7, %xmm1 + vpclmulqdq $0x00, %xmm15, %xmm7, %xmm4 + vpclmulqdq $0x11, %xmm15, %xmm7, %xmm6 + vpxor %xmm1, %xmm5, %xmm5 + vmovdqu 16(%rsp), %xmm7 + vpclmulqdq $16, %xmm14, %xmm7, %xmm2 + vpclmulqdq $0x01, %xmm14, %xmm7, %xmm1 + vpclmulqdq $0x00, %xmm14, %xmm7, %xmm0 + vpclmulqdq $0x11, %xmm14, %xmm7, %xmm3 + vpxor %xmm1, %xmm2, %xmm2 + vpxor %xmm3, %xmm6, %xmm6 + vpxor %xmm2, %xmm5, %xmm5 + vpxor %xmm0, %xmm4, %xmm4 + vmovdqu 32(%rsp), %xmm15 + vmovdqu 48(%rsp), %xmm7 + vpclmulqdq $16, %xmm13, %xmm15, %xmm2 + vpclmulqdq $0x01, %xmm13, %xmm15, %xmm1 + vpclmulqdq $0x00, %xmm13, %xmm15, %xmm0 + vpclmulqdq $0x11, %xmm13, %xmm15, %xmm3 + vpxor %xmm1, %xmm2, %xmm2 + vpxor %xmm3, %xmm6, %xmm6 + vpxor %xmm2, %xmm5, %xmm5 + vpxor %xmm0, %xmm4, %xmm4 + vpclmulqdq $16, %xmm12, %xmm7, %xmm2 + vpclmulqdq $0x01, %xmm12, %xmm7, %xmm1 + vpclmulqdq $0x00, %xmm12, %xmm7, %xmm0 + vpclmulqdq $0x11, %xmm12, %xmm7, %xmm3 + vpxor %xmm1, %xmm2, %xmm2 + vpxor %xmm3, %xmm6, %xmm6 + vpxor %xmm2, %xmm5, %xmm5 + vpxor %xmm0, %xmm4, %xmm4 + vmovdqu 64(%rsp), %xmm15 + vmovdqu 80(%rsp), %xmm7 + vpclmulqdq $16, %xmm11, %xmm15, %xmm2 + vpclmulqdq $0x01, %xmm11, %xmm15, %xmm1 + vpclmulqdq $0x00, %xmm11, %xmm15, %xmm0 + vpclmulqdq $0x11, %xmm11, %xmm15, %xmm3 + vpxor %xmm1, %xmm2, %xmm2 + vpxor %xmm3, %xmm6, %xmm6 + vpxor %xmm2, %xmm5, %xmm5 + vpxor %xmm0, %xmm4, %xmm4 + vpclmulqdq $16, %xmm10, %xmm7, %xmm2 + vpclmulqdq $0x01, %xmm10, %xmm7, %xmm1 + vpclmulqdq $0x00, %xmm10, %xmm7, %xmm0 + vpclmulqdq $0x11, %xmm10, %xmm7, %xmm3 + vpxor %xmm1, %xmm2, %xmm2 + vpxor %xmm3, %xmm6, %xmm6 + vpxor %xmm2, %xmm5, %xmm5 + vpxor %xmm0, %xmm4, %xmm4 + vmovdqu 96(%rsp), %xmm15 + vmovdqu 112(%rsp), %xmm7 + vpclmulqdq $16, %xmm9, %xmm15, %xmm2 + vpclmulqdq $0x01, %xmm9, %xmm15, %xmm1 + vpclmulqdq $0x00, %xmm9, %xmm15, %xmm0 + vpclmulqdq $0x11, %xmm9, %xmm15, %xmm3 + vpxor %xmm1, %xmm2, %xmm2 + vpxor %xmm3, %xmm6, %xmm6 + vpxor %xmm2, %xmm5, %xmm5 + vpxor %xmm0, %xmm4, %xmm4 + vpclmulqdq $16, %xmm8, %xmm7, %xmm2 + vpclmulqdq $0x01, %xmm8, %xmm7, %xmm1 + vpclmulqdq $0x00, %xmm8, %xmm7, %xmm0 + vpclmulqdq $0x11, %xmm8, %xmm7, %xmm3 + vpxor %xmm1, %xmm2, %xmm2 + vpxor %xmm3, %xmm6, %xmm6 + vpxor %xmm2, %xmm5, %xmm5 + vpxor %xmm0, %xmm4, %xmm4 + vpslldq $8, %xmm5, %xmm7 + vpsrldq $8, %xmm5, %xmm5 + vpxor %xmm7, %xmm4, %xmm4 + vpxor %xmm5, %xmm6, %xmm6 + # ghash_red + vmovdqa L_avx2_aes_gcm_mod2_128(%rip), %xmm2 + vpclmulqdq $16, %xmm2, %xmm4, %xmm0 + vpshufd $0x4e, %xmm4, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpclmulqdq $16, %xmm2, %xmm1, %xmm0 + vpshufd $0x4e, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm1, %xmm6, %xmm6 + vmovdqa (%rsp), %xmm5 + vmovdqu 128(%rsp), %xmm4 + vmovdqu 144(%rsp), %xmm15 +L_AES_GCM_encrypt_avx2_done_128: + cmpl %r10d, %ebx + je L_AES_GCM_encrypt_avx2_done_enc + movl %r10d, %r13d + andl $0xfffffff0, %r13d + cmpl %r13d, %ebx + jge L_AES_GCM_encrypt_avx2_last_block_done + # aesenc_block + vmovdqa %xmm4, %xmm1 + vpshufb L_avx2_aes_gcm_bswap_epi64(%rip), %xmm1, %xmm0 + vpaddd L_avx2_aes_gcm_one(%rip), %xmm1, %xmm1 + vpxor (%rsi), %xmm0, %xmm0 + vmovdqa 16(%rsi), %xmm2 + vaesenc %xmm2, %xmm0, %xmm0 + vmovdqa 32(%rsi), %xmm2 + vaesenc %xmm2, %xmm0, %xmm0 + vmovdqa 48(%rsi), %xmm2 + vaesenc %xmm2, %xmm0, %xmm0 + vmovdqa 64(%rsi), %xmm2 + vaesenc %xmm2, %xmm0, %xmm0 + vmovdqa 80(%rsi), %xmm2 + vaesenc %xmm2, %xmm0, %xmm0 + vmovdqa 96(%rsi), %xmm2 + vaesenc %xmm2, %xmm0, %xmm0 + vmovdqa 112(%rsi), %xmm2 + vaesenc %xmm2, %xmm0, %xmm0 + vmovdqa 128(%rsi), %xmm2 + vaesenc %xmm2, %xmm0, %xmm0 + vmovdqa 144(%rsi), %xmm2 + vaesenc %xmm2, %xmm0, %xmm0 + vmovdqa %xmm1, %xmm4 + cmpl $11, %r9d + vmovdqa 160(%rsi), %xmm1 + jl L_AES_GCM_encrypt_avx2_aesenc_block_last + vaesenc %xmm1, %xmm0, %xmm0 + vmovdqa 176(%rsi), %xmm2 + vaesenc %xmm2, %xmm0, %xmm0 + cmpl $13, %r9d + vmovdqa 192(%rsi), %xmm1 + jl L_AES_GCM_encrypt_avx2_aesenc_block_last + vaesenc %xmm1, %xmm0, %xmm0 + vmovdqa 208(%rsi), %xmm2 + vaesenc %xmm2, %xmm0, %xmm0 + vmovdqa 224(%rsi), %xmm1 +L_AES_GCM_encrypt_avx2_aesenc_block_last: + vaesenclast %xmm1, %xmm0, %xmm0 + vmovdqu (%rdi,%rbx,1), %xmm1 + vpxor %xmm1, %xmm0, %xmm0 + vmovdqu %xmm0, (%r8,%rbx,1) + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vpxor %xmm0, %xmm6, %xmm6 + addl $16, %ebx + cmpl %r13d, %ebx + jge L_AES_GCM_encrypt_avx2_last_block_ghash +L_AES_GCM_encrypt_avx2_last_block_start: + vmovdqu (%rdi,%rbx,1), %xmm12 + vpshufb L_avx2_aes_gcm_bswap_epi64(%rip), %xmm4, %xmm11 + vpaddd L_avx2_aes_gcm_one(%rip), %xmm4, %xmm4 + # aesenc_gfmul_sb + vpclmulqdq $0x01, %xmm5, %xmm6, %xmm2 + vpclmulqdq $16, %xmm5, %xmm6, %xmm3 + vpclmulqdq $0x00, %xmm5, %xmm6, %xmm1 + vpclmulqdq $0x11, %xmm5, %xmm6, %xmm8 + vpxor (%rsi), %xmm11, %xmm11 + vaesenc 16(%rsi), %xmm11, %xmm11 + vpxor %xmm2, %xmm3, %xmm3 + vpslldq $8, %xmm3, %xmm2 + vpsrldq $8, %xmm3, %xmm3 + vaesenc 32(%rsi), %xmm11, %xmm11 + vpxor %xmm1, %xmm2, %xmm2 + vpclmulqdq $16, L_avx2_aes_gcm_mod2_128(%rip), %xmm2, %xmm1 + vaesenc 48(%rsi), %xmm11, %xmm11 + vaesenc 64(%rsi), %xmm11, %xmm11 + vaesenc 80(%rsi), %xmm11, %xmm11 + vpshufd $0x4e, %xmm2, %xmm2 + vpxor %xmm1, %xmm2, %xmm2 + vpclmulqdq $16, L_avx2_aes_gcm_mod2_128(%rip), %xmm2, %xmm1 + vaesenc 96(%rsi), %xmm11, %xmm11 + vaesenc 112(%rsi), %xmm11, %xmm11 + vaesenc 128(%rsi), %xmm11, %xmm11 + vpshufd $0x4e, %xmm2, %xmm2 + vaesenc 144(%rsi), %xmm11, %xmm11 + vpxor %xmm3, %xmm8, %xmm8 + vpxor %xmm8, %xmm2, %xmm2 + vmovdqa 160(%rsi), %xmm0 + cmpl $11, %r9d + jl L_AES_GCM_encrypt_avx2_aesenc_gfmul_sb_last + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc 176(%rsi), %xmm11, %xmm11 + vmovdqa 192(%rsi), %xmm0 + cmpl $13, %r9d + jl L_AES_GCM_encrypt_avx2_aesenc_gfmul_sb_last + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc 208(%rsi), %xmm11, %xmm11 + vmovdqa 224(%rsi), %xmm0 +L_AES_GCM_encrypt_avx2_aesenc_gfmul_sb_last: + vaesenclast %xmm0, %xmm11, %xmm11 + vpxor %xmm1, %xmm2, %xmm6 + vpxor %xmm12, %xmm11, %xmm11 + vmovdqu %xmm11, (%r8,%rbx,1) + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm11, %xmm11 + vpxor %xmm11, %xmm6, %xmm6 + addl $16, %ebx + cmpl %r13d, %ebx + jl L_AES_GCM_encrypt_avx2_last_block_start +L_AES_GCM_encrypt_avx2_last_block_ghash: + # ghash_gfmul_red + vpclmulqdq $16, %xmm5, %xmm6, %xmm10 + vpclmulqdq $0x01, %xmm5, %xmm6, %xmm9 + vpclmulqdq $0x00, %xmm5, %xmm6, %xmm8 + vpxor %xmm9, %xmm10, %xmm10 + vpslldq $8, %xmm10, %xmm9 + vpsrldq $8, %xmm10, %xmm10 + vpxor %xmm8, %xmm9, %xmm9 + vpclmulqdq $0x11, %xmm5, %xmm6, %xmm6 + vpclmulqdq $16, L_avx2_aes_gcm_mod2_128(%rip), %xmm9, %xmm8 + vpshufd $0x4e, %xmm9, %xmm9 + vpxor %xmm8, %xmm9, %xmm9 + vpclmulqdq $16, L_avx2_aes_gcm_mod2_128(%rip), %xmm9, %xmm8 + vpshufd $0x4e, %xmm9, %xmm9 + vpxor %xmm10, %xmm6, %xmm6 + vpxor %xmm9, %xmm6, %xmm6 + vpxor %xmm8, %xmm6, %xmm6 +L_AES_GCM_encrypt_avx2_last_block_done: + movl %r10d, %ecx + movl %r10d, %edx + andl $15, %ecx + jz L_AES_GCM_encrypt_avx2_done_enc + # aesenc_last15_enc + vpshufb L_avx2_aes_gcm_bswap_epi64(%rip), %xmm4, %xmm4 + vpxor (%rsi), %xmm4, %xmm4 + vaesenc 16(%rsi), %xmm4, %xmm4 + vaesenc 32(%rsi), %xmm4, %xmm4 + vaesenc 48(%rsi), %xmm4, %xmm4 + vaesenc 64(%rsi), %xmm4, %xmm4 + vaesenc 80(%rsi), %xmm4, %xmm4 + vaesenc 96(%rsi), %xmm4, %xmm4 + vaesenc 112(%rsi), %xmm4, %xmm4 + vaesenc 128(%rsi), %xmm4, %xmm4 + vaesenc 144(%rsi), %xmm4, %xmm4 + cmpl $11, %r9d + vmovdqa 160(%rsi), %xmm0 + jl L_AES_GCM_encrypt_avx2_aesenc_last15_enc_avx_aesenc_avx_last + vaesenc %xmm0, %xmm4, %xmm4 + vaesenc 176(%rsi), %xmm4, %xmm4 + cmpl $13, %r9d + vmovdqa 192(%rsi), %xmm0 + jl L_AES_GCM_encrypt_avx2_aesenc_last15_enc_avx_aesenc_avx_last + vaesenc %xmm0, %xmm4, %xmm4 + vaesenc 208(%rsi), %xmm4, %xmm4 + vmovdqa 224(%rsi), %xmm0 +L_AES_GCM_encrypt_avx2_aesenc_last15_enc_avx_aesenc_avx_last: + vaesenclast %xmm0, %xmm4, %xmm4 + xorl %ecx, %ecx + vpxor %xmm0, %xmm0, %xmm0 + vmovdqa %xmm4, (%rsp) + vmovdqa %xmm0, 16(%rsp) +L_AES_GCM_encrypt_avx2_aesenc_last15_enc_avx_loop: + movzbl (%rdi,%rbx,1), %r13d + xorb (%rsp,%rcx,1), %r13b + movb %r13b, 16(%rsp,%rcx,1) + movb %r13b, (%r8,%rbx,1) + incl %ebx + incl %ecx + cmpl %edx, %ebx + jl L_AES_GCM_encrypt_avx2_aesenc_last15_enc_avx_loop +L_AES_GCM_encrypt_avx2_aesenc_last15_enc_avx_finish_enc: + vmovdqa 16(%rsp), %xmm4 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm4, %xmm4 + vpxor %xmm4, %xmm6, %xmm6 + # ghash_gfmul_red + vpclmulqdq $16, %xmm5, %xmm6, %xmm2 + vpclmulqdq $0x01, %xmm5, %xmm6, %xmm1 + vpclmulqdq $0x00, %xmm5, %xmm6, %xmm0 + vpxor %xmm1, %xmm2, %xmm2 + vpslldq $8, %xmm2, %xmm1 + vpsrldq $8, %xmm2, %xmm2 + vpxor %xmm0, %xmm1, %xmm1 + vpclmulqdq $0x11, %xmm5, %xmm6, %xmm6 + vpclmulqdq $16, L_avx2_aes_gcm_mod2_128(%rip), %xmm1, %xmm0 + vpshufd $0x4e, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpclmulqdq $16, L_avx2_aes_gcm_mod2_128(%rip), %xmm1, %xmm0 + vpshufd $0x4e, %xmm1, %xmm1 + vpxor %xmm2, %xmm6, %xmm6 + vpxor %xmm1, %xmm6, %xmm6 + vpxor %xmm0, %xmm6, %xmm6 +L_AES_GCM_encrypt_avx2_done_enc: + # calc_tag + shlq $3, %r10 + vpinsrq $0x00, %r10, %xmm0, %xmm0 + shlq $3, %r11 + vpinsrq $0x01, %r11, %xmm1, %xmm1 + vpblendd $12, %xmm1, %xmm0, %xmm0 + vpxor %xmm6, %xmm0, %xmm0 + # ghash_gfmul_red + vpclmulqdq $16, %xmm5, %xmm0, %xmm4 + vpclmulqdq $0x01, %xmm5, %xmm0, %xmm3 + vpclmulqdq $0x00, %xmm5, %xmm0, %xmm2 + vpxor %xmm3, %xmm4, %xmm4 + vpslldq $8, %xmm4, %xmm3 + vpsrldq $8, %xmm4, %xmm4 + vpxor %xmm2, %xmm3, %xmm3 + vpclmulqdq $0x11, %xmm5, %xmm0, %xmm0 + vpclmulqdq $16, L_avx2_aes_gcm_mod2_128(%rip), %xmm3, %xmm2 + vpshufd $0x4e, %xmm3, %xmm3 + vpxor %xmm2, %xmm3, %xmm3 + vpclmulqdq $16, L_avx2_aes_gcm_mod2_128(%rip), %xmm3, %xmm2 + vpshufd $0x4e, %xmm3, %xmm3 + vpxor %xmm4, %xmm0, %xmm0 + vpxor %xmm3, %xmm0, %xmm0 + vpxor %xmm2, %xmm0, %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vpxor %xmm15, %xmm0, %xmm0 + # store_tag + cmpl $16, %r14d + je L_AES_GCM_encrypt_avx2_store_tag_16 + xorq %rcx, %rcx + vmovdqa %xmm0, (%rsp) +L_AES_GCM_encrypt_avx2_store_tag_loop: + movzbl (%rsp,%rcx,1), %r13d + movb %r13b, (%r15,%rcx,1) + incl %ecx + cmpl %r14d, %ecx + jne L_AES_GCM_encrypt_avx2_store_tag_loop + jmp L_AES_GCM_encrypt_avx2_store_tag_done +L_AES_GCM_encrypt_avx2_store_tag_16: + vmovdqu %xmm0, (%r15) +L_AES_GCM_encrypt_avx2_store_tag_done: + vzeroupper + addq $0xa0, %rsp + popq %r14 + popq %rbx + popq %r15 + popq %r12 + popq %r13 + repz retq +#ifndef __APPLE__ +.size AES_GCM_encrypt_avx2,.-AES_GCM_encrypt_avx2 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl AES_GCM_decrypt_avx2 +.type AES_GCM_decrypt_avx2,@function +.align 4 +AES_GCM_decrypt_avx2: +#else +.section __TEXT,__text +.globl _AES_GCM_decrypt_avx2 +.p2align 2 +_AES_GCM_decrypt_avx2: +#endif /* __APPLE__ */ + pushq %r13 + pushq %r12 + pushq %r14 + pushq %rbx + pushq %r15 + pushq %rbp + movq %rdx, %r12 + movq %rcx, %rax + movq %r8, %r14 + movq %rsi, %r8 + movl %r9d, %r10d + movl 56(%rsp), %r11d + movl 64(%rsp), %ebx + movl 72(%rsp), %r15d + movq 80(%rsp), %rsi + movl 88(%rsp), %r9d + movq 96(%rsp), %rbp + subq $0xa8, %rsp + vpxor %xmm4, %xmm4, %xmm4 + vpxor %xmm6, %xmm6, %xmm6 + movl %ebx, %edx + cmpl $12, %edx + je L_AES_GCM_decrypt_avx2_iv_12 + # Calculate values when IV is not 12 bytes + # H = Encrypt X(=0) + vmovdqa (%rsi), %xmm5 + vaesenc 16(%rsi), %xmm5, %xmm5 + vaesenc 32(%rsi), %xmm5, %xmm5 + vaesenc 48(%rsi), %xmm5, %xmm5 + vaesenc 64(%rsi), %xmm5, %xmm5 + vaesenc 80(%rsi), %xmm5, %xmm5 + vaesenc 96(%rsi), %xmm5, %xmm5 + vaesenc 112(%rsi), %xmm5, %xmm5 + vaesenc 128(%rsi), %xmm5, %xmm5 + vaesenc 144(%rsi), %xmm5, %xmm5 + cmpl $11, %r9d + vmovdqa 160(%rsi), %xmm0 + jl L_AES_GCM_decrypt_avx2_calc_iv_1_aesenc_avx_last + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc 176(%rsi), %xmm5, %xmm5 + cmpl $13, %r9d + vmovdqa 192(%rsi), %xmm0 + jl L_AES_GCM_decrypt_avx2_calc_iv_1_aesenc_avx_last + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc 208(%rsi), %xmm5, %xmm5 + vmovdqa 224(%rsi), %xmm0 +L_AES_GCM_decrypt_avx2_calc_iv_1_aesenc_avx_last: + vaesenclast %xmm0, %xmm5, %xmm5 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm5, %xmm5 + # Calc counter + # Initialization vector + cmpl $0x00, %edx + movq $0x00, %rcx + je L_AES_GCM_decrypt_avx2_calc_iv_done + cmpl $16, %edx + jl L_AES_GCM_decrypt_avx2_calc_iv_lt16 + andl $0xfffffff0, %edx +L_AES_GCM_decrypt_avx2_calc_iv_16_loop: + vmovdqu (%rax,%rcx,1), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vpxor %xmm0, %xmm4, %xmm4 + # ghash_gfmul_avx + vpclmulqdq $16, %xmm4, %xmm5, %xmm2 + vpclmulqdq $0x01, %xmm4, %xmm5, %xmm1 + vpclmulqdq $0x00, %xmm4, %xmm5, %xmm0 + vpclmulqdq $0x11, %xmm4, %xmm5, %xmm3 + vpxor %xmm1, %xmm2, %xmm2 + vpslldq $8, %xmm2, %xmm1 + vpsrldq $8, %xmm2, %xmm2 + vpxor %xmm1, %xmm0, %xmm7 + vpxor %xmm2, %xmm3, %xmm4 + # ghash_mid + vpsrld $31, %xmm7, %xmm0 + vpsrld $31, %xmm4, %xmm1 + vpslld $0x01, %xmm7, %xmm7 + vpslld $0x01, %xmm4, %xmm4 + vpsrldq $12, %xmm0, %xmm2 + vpslldq $4, %xmm0, %xmm0 + vpslldq $4, %xmm1, %xmm1 + vpor %xmm2, %xmm4, %xmm4 + vpor %xmm0, %xmm7, %xmm7 + vpor %xmm1, %xmm4, %xmm4 + # ghash_red + vmovdqa L_avx2_aes_gcm_mod2_128(%rip), %xmm2 + vpclmulqdq $16, %xmm2, %xmm7, %xmm0 + vpshufd $0x4e, %xmm7, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpclmulqdq $16, %xmm2, %xmm1, %xmm0 + vpshufd $0x4e, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm1, %xmm4, %xmm4 + addl $16, %ecx + cmpl %edx, %ecx + jl L_AES_GCM_decrypt_avx2_calc_iv_16_loop + movl %ebx, %edx + cmpl %edx, %ecx + je L_AES_GCM_decrypt_avx2_calc_iv_done +L_AES_GCM_decrypt_avx2_calc_iv_lt16: + vpxor %xmm0, %xmm0, %xmm0 + xorl %ebx, %ebx + vmovdqa %xmm0, (%rsp) +L_AES_GCM_decrypt_avx2_calc_iv_loop: + movzbl (%rax,%rcx,1), %r13d + movb %r13b, (%rsp,%rbx,1) + incl %ecx + incl %ebx + cmpl %edx, %ecx + jl L_AES_GCM_decrypt_avx2_calc_iv_loop + vmovdqa (%rsp), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vpxor %xmm0, %xmm4, %xmm4 + # ghash_gfmul_avx + vpclmulqdq $16, %xmm4, %xmm5, %xmm2 + vpclmulqdq $0x01, %xmm4, %xmm5, %xmm1 + vpclmulqdq $0x00, %xmm4, %xmm5, %xmm0 + vpclmulqdq $0x11, %xmm4, %xmm5, %xmm3 + vpxor %xmm1, %xmm2, %xmm2 + vpslldq $8, %xmm2, %xmm1 + vpsrldq $8, %xmm2, %xmm2 + vpxor %xmm1, %xmm0, %xmm7 + vpxor %xmm2, %xmm3, %xmm4 + # ghash_mid + vpsrld $31, %xmm7, %xmm0 + vpsrld $31, %xmm4, %xmm1 + vpslld $0x01, %xmm7, %xmm7 + vpslld $0x01, %xmm4, %xmm4 + vpsrldq $12, %xmm0, %xmm2 + vpslldq $4, %xmm0, %xmm0 + vpslldq $4, %xmm1, %xmm1 + vpor %xmm2, %xmm4, %xmm4 + vpor %xmm0, %xmm7, %xmm7 + vpor %xmm1, %xmm4, %xmm4 + # ghash_red + vmovdqa L_avx2_aes_gcm_mod2_128(%rip), %xmm2 + vpclmulqdq $16, %xmm2, %xmm7, %xmm0 + vpshufd $0x4e, %xmm7, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpclmulqdq $16, %xmm2, %xmm1, %xmm0 + vpshufd $0x4e, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm1, %xmm4, %xmm4 +L_AES_GCM_decrypt_avx2_calc_iv_done: + # T = Encrypt counter + vpxor %xmm0, %xmm0, %xmm0 + shll $3, %edx + vpinsrq $0x00, %rdx, %xmm0, %xmm0 + vpxor %xmm0, %xmm4, %xmm4 + # ghash_gfmul_avx + vpclmulqdq $16, %xmm4, %xmm5, %xmm2 + vpclmulqdq $0x01, %xmm4, %xmm5, %xmm1 + vpclmulqdq $0x00, %xmm4, %xmm5, %xmm0 + vpclmulqdq $0x11, %xmm4, %xmm5, %xmm3 + vpxor %xmm1, %xmm2, %xmm2 + vpslldq $8, %xmm2, %xmm1 + vpsrldq $8, %xmm2, %xmm2 + vpxor %xmm1, %xmm0, %xmm7 + vpxor %xmm2, %xmm3, %xmm4 + # ghash_mid + vpsrld $31, %xmm7, %xmm0 + vpsrld $31, %xmm4, %xmm1 + vpslld $0x01, %xmm7, %xmm7 + vpslld $0x01, %xmm4, %xmm4 + vpsrldq $12, %xmm0, %xmm2 + vpslldq $4, %xmm0, %xmm0 + vpslldq $4, %xmm1, %xmm1 + vpor %xmm2, %xmm4, %xmm4 + vpor %xmm0, %xmm7, %xmm7 + vpor %xmm1, %xmm4, %xmm4 + # ghash_red + vmovdqa L_avx2_aes_gcm_mod2_128(%rip), %xmm2 + vpclmulqdq $16, %xmm2, %xmm7, %xmm0 + vpshufd $0x4e, %xmm7, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpclmulqdq $16, %xmm2, %xmm1, %xmm0 + vpshufd $0x4e, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm1, %xmm4, %xmm4 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm4, %xmm4 + # Encrypt counter + vmovdqa (%rsi), %xmm15 + vpxor %xmm4, %xmm15, %xmm15 + vaesenc 16(%rsi), %xmm15, %xmm15 + vaesenc 32(%rsi), %xmm15, %xmm15 + vaesenc 48(%rsi), %xmm15, %xmm15 + vaesenc 64(%rsi), %xmm15, %xmm15 + vaesenc 80(%rsi), %xmm15, %xmm15 + vaesenc 96(%rsi), %xmm15, %xmm15 + vaesenc 112(%rsi), %xmm15, %xmm15 + vaesenc 128(%rsi), %xmm15, %xmm15 + vaesenc 144(%rsi), %xmm15, %xmm15 + cmpl $11, %r9d + vmovdqa 160(%rsi), %xmm0 + jl L_AES_GCM_decrypt_avx2_calc_iv_2_aesenc_avx_last + vaesenc %xmm0, %xmm15, %xmm15 + vaesenc 176(%rsi), %xmm15, %xmm15 + cmpl $13, %r9d + vmovdqa 192(%rsi), %xmm0 + jl L_AES_GCM_decrypt_avx2_calc_iv_2_aesenc_avx_last + vaesenc %xmm0, %xmm15, %xmm15 + vaesenc 208(%rsi), %xmm15, %xmm15 + vmovdqa 224(%rsi), %xmm0 +L_AES_GCM_decrypt_avx2_calc_iv_2_aesenc_avx_last: + vaesenclast %xmm0, %xmm15, %xmm15 + jmp L_AES_GCM_decrypt_avx2_iv_done +L_AES_GCM_decrypt_avx2_iv_12: + # # Calculate values when IV is 12 bytes + # Set counter based on IV + vmovdqa L_avx2_aes_gcm_bswap_one(%rip), %xmm4 + vmovdqa (%rsi), %xmm5 + vpblendd $7, (%rax), %xmm4, %xmm4 + # H = Encrypt X(=0) and T = Encrypt counter + vmovdqa 16(%rsi), %xmm7 + vpxor %xmm5, %xmm4, %xmm15 + vaesenc %xmm7, %xmm5, %xmm5 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 32(%rsi), %xmm0 + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm15, %xmm15 + vmovdqa 48(%rsi), %xmm0 + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm15, %xmm15 + vmovdqa 64(%rsi), %xmm0 + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm15, %xmm15 + vmovdqa 80(%rsi), %xmm0 + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm15, %xmm15 + vmovdqa 96(%rsi), %xmm0 + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm15, %xmm15 + vmovdqa 112(%rsi), %xmm0 + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm15, %xmm15 + vmovdqa 128(%rsi), %xmm0 + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm15, %xmm15 + vmovdqa 144(%rsi), %xmm0 + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm15, %xmm15 + cmpl $11, %r9d + vmovdqa 160(%rsi), %xmm0 + jl L_AES_GCM_decrypt_avx2_calc_iv_12_last + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm15, %xmm15 + vmovdqa 176(%rsi), %xmm0 + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm15, %xmm15 + cmpl $13, %r9d + vmovdqa 192(%rsi), %xmm0 + jl L_AES_GCM_decrypt_avx2_calc_iv_12_last + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm15, %xmm15 + vmovdqa 208(%rsi), %xmm0 + vaesenc %xmm0, %xmm5, %xmm5 + vaesenc %xmm0, %xmm15, %xmm15 + vmovdqa 224(%rsi), %xmm0 +L_AES_GCM_decrypt_avx2_calc_iv_12_last: + vaesenclast %xmm0, %xmm5, %xmm5 + vaesenclast %xmm0, %xmm15, %xmm15 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm5, %xmm5 +L_AES_GCM_decrypt_avx2_iv_done: + # Additional authentication data + movl %r11d, %edx + cmpl $0x00, %edx + je L_AES_GCM_decrypt_avx2_calc_aad_done + xorl %ecx, %ecx + cmpl $16, %edx + jl L_AES_GCM_decrypt_avx2_calc_aad_lt16 + andl $0xfffffff0, %edx +L_AES_GCM_decrypt_avx2_calc_aad_16_loop: + vmovdqu (%r12,%rcx,1), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vpxor %xmm0, %xmm6, %xmm6 + # ghash_gfmul_avx + vpclmulqdq $16, %xmm6, %xmm5, %xmm2 + vpclmulqdq $0x01, %xmm6, %xmm5, %xmm1 + vpclmulqdq $0x00, %xmm6, %xmm5, %xmm0 + vpclmulqdq $0x11, %xmm6, %xmm5, %xmm3 + vpxor %xmm1, %xmm2, %xmm2 + vpslldq $8, %xmm2, %xmm1 + vpsrldq $8, %xmm2, %xmm2 + vpxor %xmm1, %xmm0, %xmm7 + vpxor %xmm2, %xmm3, %xmm6 + # ghash_mid + vpsrld $31, %xmm7, %xmm0 + vpsrld $31, %xmm6, %xmm1 + vpslld $0x01, %xmm7, %xmm7 + vpslld $0x01, %xmm6, %xmm6 + vpsrldq $12, %xmm0, %xmm2 + vpslldq $4, %xmm0, %xmm0 + vpslldq $4, %xmm1, %xmm1 + vpor %xmm2, %xmm6, %xmm6 + vpor %xmm0, %xmm7, %xmm7 + vpor %xmm1, %xmm6, %xmm6 + # ghash_red + vmovdqa L_avx2_aes_gcm_mod2_128(%rip), %xmm2 + vpclmulqdq $16, %xmm2, %xmm7, %xmm0 + vpshufd $0x4e, %xmm7, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpclmulqdq $16, %xmm2, %xmm1, %xmm0 + vpshufd $0x4e, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm1, %xmm6, %xmm6 + addl $16, %ecx + cmpl %edx, %ecx + jl L_AES_GCM_decrypt_avx2_calc_aad_16_loop + movl %r11d, %edx + cmpl %edx, %ecx + je L_AES_GCM_decrypt_avx2_calc_aad_done +L_AES_GCM_decrypt_avx2_calc_aad_lt16: + vpxor %xmm0, %xmm0, %xmm0 + xorl %ebx, %ebx + vmovdqa %xmm0, (%rsp) +L_AES_GCM_decrypt_avx2_calc_aad_loop: + movzbl (%r12,%rcx,1), %r13d + movb %r13b, (%rsp,%rbx,1) + incl %ecx + incl %ebx + cmpl %edx, %ecx + jl L_AES_GCM_decrypt_avx2_calc_aad_loop + vmovdqa (%rsp), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vpxor %xmm0, %xmm6, %xmm6 + # ghash_gfmul_avx + vpclmulqdq $16, %xmm6, %xmm5, %xmm2 + vpclmulqdq $0x01, %xmm6, %xmm5, %xmm1 + vpclmulqdq $0x00, %xmm6, %xmm5, %xmm0 + vpclmulqdq $0x11, %xmm6, %xmm5, %xmm3 + vpxor %xmm1, %xmm2, %xmm2 + vpslldq $8, %xmm2, %xmm1 + vpsrldq $8, %xmm2, %xmm2 + vpxor %xmm1, %xmm0, %xmm7 + vpxor %xmm2, %xmm3, %xmm6 + # ghash_mid + vpsrld $31, %xmm7, %xmm0 + vpsrld $31, %xmm6, %xmm1 + vpslld $0x01, %xmm7, %xmm7 + vpslld $0x01, %xmm6, %xmm6 + vpsrldq $12, %xmm0, %xmm2 + vpslldq $4, %xmm0, %xmm0 + vpslldq $4, %xmm1, %xmm1 + vpor %xmm2, %xmm6, %xmm6 + vpor %xmm0, %xmm7, %xmm7 + vpor %xmm1, %xmm6, %xmm6 + # ghash_red + vmovdqa L_avx2_aes_gcm_mod2_128(%rip), %xmm2 + vpclmulqdq $16, %xmm2, %xmm7, %xmm0 + vpshufd $0x4e, %xmm7, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpclmulqdq $16, %xmm2, %xmm1, %xmm0 + vpshufd $0x4e, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpxor %xmm1, %xmm6, %xmm6 +L_AES_GCM_decrypt_avx2_calc_aad_done: + # Calculate counter and H + vpsrlq $63, %xmm5, %xmm1 + vpsllq $0x01, %xmm5, %xmm0 + vpslldq $8, %xmm1, %xmm1 + vpor %xmm1, %xmm0, %xmm0 + vpshufd $0xff, %xmm5, %xmm5 + vpsrad $31, %xmm5, %xmm5 + vpshufb L_avx2_aes_gcm_bswap_epi64(%rip), %xmm4, %xmm4 + vpand L_avx2_aes_gcm_mod2_128(%rip), %xmm5, %xmm5 + vpaddd L_avx2_aes_gcm_one(%rip), %xmm4, %xmm4 + vpxor %xmm0, %xmm5, %xmm5 + xorl %ebx, %ebx + cmpl $0x80, %r10d + movl %r10d, %r13d + jl L_AES_GCM_decrypt_avx2_done_128 + andl $0xffffff80, %r13d + vmovdqa %xmm4, 128(%rsp) + vmovdqa %xmm15, 144(%rsp) + vmovdqa L_avx2_aes_gcm_mod2_128(%rip), %xmm3 + # H ^ 1 and H ^ 2 + vpclmulqdq $0x00, %xmm5, %xmm5, %xmm9 + vpclmulqdq $0x11, %xmm5, %xmm5, %xmm10 + vpclmulqdq $16, %xmm3, %xmm9, %xmm8 + vpshufd $0x4e, %xmm9, %xmm9 + vpxor %xmm8, %xmm9, %xmm9 + vpclmulqdq $16, %xmm3, %xmm9, %xmm8 + vpshufd $0x4e, %xmm9, %xmm9 + vpxor %xmm8, %xmm9, %xmm9 + vpxor %xmm9, %xmm10, %xmm0 + vmovdqa %xmm5, (%rsp) + vmovdqa %xmm0, 16(%rsp) + # H ^ 3 and H ^ 4 + vpclmulqdq $16, %xmm5, %xmm0, %xmm11 + vpclmulqdq $0x01, %xmm5, %xmm0, %xmm10 + vpclmulqdq $0x00, %xmm5, %xmm0, %xmm9 + vpclmulqdq $0x11, %xmm5, %xmm0, %xmm12 + vpclmulqdq $0x00, %xmm0, %xmm0, %xmm13 + vpclmulqdq $0x11, %xmm0, %xmm0, %xmm14 + vpxor %xmm10, %xmm11, %xmm11 + vpslldq $8, %xmm11, %xmm10 + vpsrldq $8, %xmm11, %xmm11 + vpxor %xmm9, %xmm10, %xmm10 + vpclmulqdq $16, %xmm3, %xmm13, %xmm8 + vpclmulqdq $16, %xmm3, %xmm10, %xmm9 + vpshufd $0x4e, %xmm10, %xmm10 + vpshufd $0x4e, %xmm13, %xmm13 + vpxor %xmm9, %xmm10, %xmm10 + vpxor %xmm8, %xmm13, %xmm13 + vpclmulqdq $16, %xmm3, %xmm10, %xmm9 + vpclmulqdq $16, %xmm3, %xmm13, %xmm8 + vpshufd $0x4e, %xmm10, %xmm10 + vpshufd $0x4e, %xmm13, %xmm13 + vpxor %xmm11, %xmm12, %xmm12 + vpxor %xmm8, %xmm13, %xmm13 + vpxor %xmm12, %xmm10, %xmm10 + vpxor %xmm14, %xmm13, %xmm2 + vpxor %xmm9, %xmm10, %xmm1 + vmovdqa %xmm1, 32(%rsp) + vmovdqa %xmm2, 48(%rsp) + # H ^ 5 and H ^ 6 + vpclmulqdq $16, %xmm0, %xmm1, %xmm11 + vpclmulqdq $0x01, %xmm0, %xmm1, %xmm10 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm9 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm12 + vpclmulqdq $0x00, %xmm1, %xmm1, %xmm13 + vpclmulqdq $0x11, %xmm1, %xmm1, %xmm14 + vpxor %xmm10, %xmm11, %xmm11 + vpslldq $8, %xmm11, %xmm10 + vpsrldq $8, %xmm11, %xmm11 + vpxor %xmm9, %xmm10, %xmm10 + vpclmulqdq $16, %xmm3, %xmm13, %xmm8 + vpclmulqdq $16, %xmm3, %xmm10, %xmm9 + vpshufd $0x4e, %xmm10, %xmm10 + vpshufd $0x4e, %xmm13, %xmm13 + vpxor %xmm9, %xmm10, %xmm10 + vpxor %xmm8, %xmm13, %xmm13 + vpclmulqdq $16, %xmm3, %xmm10, %xmm9 + vpclmulqdq $16, %xmm3, %xmm13, %xmm8 + vpshufd $0x4e, %xmm10, %xmm10 + vpshufd $0x4e, %xmm13, %xmm13 + vpxor %xmm11, %xmm12, %xmm12 + vpxor %xmm8, %xmm13, %xmm13 + vpxor %xmm12, %xmm10, %xmm10 + vpxor %xmm14, %xmm13, %xmm0 + vpxor %xmm9, %xmm10, %xmm7 + vmovdqa %xmm7, 64(%rsp) + vmovdqa %xmm0, 80(%rsp) + # H ^ 7 and H ^ 8 + vpclmulqdq $16, %xmm1, %xmm2, %xmm11 + vpclmulqdq $0x01, %xmm1, %xmm2, %xmm10 + vpclmulqdq $0x00, %xmm1, %xmm2, %xmm9 + vpclmulqdq $0x11, %xmm1, %xmm2, %xmm12 + vpclmulqdq $0x00, %xmm2, %xmm2, %xmm13 + vpclmulqdq $0x11, %xmm2, %xmm2, %xmm14 + vpxor %xmm10, %xmm11, %xmm11 + vpslldq $8, %xmm11, %xmm10 + vpsrldq $8, %xmm11, %xmm11 + vpxor %xmm9, %xmm10, %xmm10 + vpclmulqdq $16, %xmm3, %xmm13, %xmm8 + vpclmulqdq $16, %xmm3, %xmm10, %xmm9 + vpshufd $0x4e, %xmm10, %xmm10 + vpshufd $0x4e, %xmm13, %xmm13 + vpxor %xmm9, %xmm10, %xmm10 + vpxor %xmm8, %xmm13, %xmm13 + vpclmulqdq $16, %xmm3, %xmm10, %xmm9 + vpclmulqdq $16, %xmm3, %xmm13, %xmm8 + vpshufd $0x4e, %xmm10, %xmm10 + vpshufd $0x4e, %xmm13, %xmm13 + vpxor %xmm11, %xmm12, %xmm12 + vpxor %xmm8, %xmm13, %xmm13 + vpxor %xmm12, %xmm10, %xmm10 + vpxor %xmm14, %xmm13, %xmm0 + vpxor %xmm9, %xmm10, %xmm7 + vmovdqa %xmm7, 96(%rsp) + vmovdqa %xmm0, 112(%rsp) +L_AES_GCM_decrypt_avx2_ghash_128: + # aesenc_128_ghash + leaq (%rdi,%rbx,1), %rcx + leaq (%r8,%rbx,1), %rdx + # aesenc_ctr + vmovdqa 128(%rsp), %xmm0 + vmovdqa L_avx2_aes_gcm_bswap_epi64(%rip), %xmm1 + vpaddd L_avx2_aes_gcm_one(%rip), %xmm0, %xmm9 + vpshufb %xmm1, %xmm0, %xmm8 + vpaddd L_avx2_aes_gcm_two(%rip), %xmm0, %xmm10 + vpshufb %xmm1, %xmm9, %xmm9 + vpaddd L_avx2_aes_gcm_three(%rip), %xmm0, %xmm11 + vpshufb %xmm1, %xmm10, %xmm10 + vpaddd L_avx2_aes_gcm_four(%rip), %xmm0, %xmm12 + vpshufb %xmm1, %xmm11, %xmm11 + vpaddd L_avx2_aes_gcm_five(%rip), %xmm0, %xmm13 + vpshufb %xmm1, %xmm12, %xmm12 + vpaddd L_avx2_aes_gcm_six(%rip), %xmm0, %xmm14 + vpshufb %xmm1, %xmm13, %xmm13 + vpaddd L_avx2_aes_gcm_seven(%rip), %xmm0, %xmm15 + vpshufb %xmm1, %xmm14, %xmm14 + vpaddd L_avx2_aes_gcm_eight(%rip), %xmm0, %xmm0 + vpshufb %xmm1, %xmm15, %xmm15 + # aesenc_xor + vmovdqa (%rsi), %xmm7 + vmovdqa %xmm0, 128(%rsp) + vpxor %xmm7, %xmm8, %xmm8 + vpxor %xmm7, %xmm9, %xmm9 + vpxor %xmm7, %xmm10, %xmm10 + vpxor %xmm7, %xmm11, %xmm11 + vpxor %xmm7, %xmm12, %xmm12 + vpxor %xmm7, %xmm13, %xmm13 + vpxor %xmm7, %xmm14, %xmm14 + vpxor %xmm7, %xmm15, %xmm15 + # aesenc_pclmul_1 + vmovdqu (%rcx), %xmm1 + vmovdqu 16(%rsi), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm1, %xmm1 + vmovdqa 112(%rsp), %xmm2 + vpxor %xmm6, %xmm1, %xmm1 + vpclmulqdq $16, %xmm2, %xmm1, %xmm5 + vpclmulqdq $0x01, %xmm2, %xmm1, %xmm3 + vpclmulqdq $0x00, %xmm2, %xmm1, %xmm6 + vpclmulqdq $0x11, %xmm2, %xmm1, %xmm7 + vaesenc %xmm0, %xmm8, %xmm8 + vaesenc %xmm0, %xmm9, %xmm9 + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc %xmm0, %xmm12, %xmm12 + vaesenc %xmm0, %xmm13, %xmm13 + vaesenc %xmm0, %xmm14, %xmm14 + vaesenc %xmm0, %xmm15, %xmm15 + # aesenc_pclmul_2 + vmovdqu 16(%rcx), %xmm1 + vmovdqa 96(%rsp), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm1, %xmm1 + vpxor %xmm3, %xmm5, %xmm5 + vpclmulqdq $16, %xmm0, %xmm1, %xmm2 + vpclmulqdq $0x01, %xmm0, %xmm1, %xmm3 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm4 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm1 + vmovdqu 32(%rsi), %xmm0 + vpxor %xmm1, %xmm7, %xmm7 + vaesenc %xmm0, %xmm8, %xmm8 + vaesenc %xmm0, %xmm9, %xmm9 + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc %xmm0, %xmm12, %xmm12 + vaesenc %xmm0, %xmm13, %xmm13 + vaesenc %xmm0, %xmm14, %xmm14 + vaesenc %xmm0, %xmm15, %xmm15 + # aesenc_pclmul_n + vmovdqu 32(%rcx), %xmm1 + vmovdqa 80(%rsp), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm1, %xmm1 + vpxor %xmm2, %xmm5, %xmm5 + vpclmulqdq $16, %xmm0, %xmm1, %xmm2 + vpxor %xmm3, %xmm5, %xmm5 + vpclmulqdq $0x01, %xmm0, %xmm1, %xmm3 + vpxor %xmm4, %xmm6, %xmm6 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm4 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm1 + vmovdqu 48(%rsi), %xmm0 + vpxor %xmm1, %xmm7, %xmm7 + vaesenc %xmm0, %xmm8, %xmm8 + vaesenc %xmm0, %xmm9, %xmm9 + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc %xmm0, %xmm12, %xmm12 + vaesenc %xmm0, %xmm13, %xmm13 + vaesenc %xmm0, %xmm14, %xmm14 + vaesenc %xmm0, %xmm15, %xmm15 + # aesenc_pclmul_n + vmovdqu 48(%rcx), %xmm1 + vmovdqa 64(%rsp), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm1, %xmm1 + vpxor %xmm2, %xmm5, %xmm5 + vpclmulqdq $16, %xmm0, %xmm1, %xmm2 + vpxor %xmm3, %xmm5, %xmm5 + vpclmulqdq $0x01, %xmm0, %xmm1, %xmm3 + vpxor %xmm4, %xmm6, %xmm6 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm4 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm1 + vmovdqu 64(%rsi), %xmm0 + vpxor %xmm1, %xmm7, %xmm7 + vaesenc %xmm0, %xmm8, %xmm8 + vaesenc %xmm0, %xmm9, %xmm9 + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc %xmm0, %xmm12, %xmm12 + vaesenc %xmm0, %xmm13, %xmm13 + vaesenc %xmm0, %xmm14, %xmm14 + vaesenc %xmm0, %xmm15, %xmm15 + # aesenc_pclmul_n + vmovdqu 64(%rcx), %xmm1 + vmovdqa 48(%rsp), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm1, %xmm1 + vpxor %xmm2, %xmm5, %xmm5 + vpclmulqdq $16, %xmm0, %xmm1, %xmm2 + vpxor %xmm3, %xmm5, %xmm5 + vpclmulqdq $0x01, %xmm0, %xmm1, %xmm3 + vpxor %xmm4, %xmm6, %xmm6 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm4 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm1 + vmovdqu 80(%rsi), %xmm0 + vpxor %xmm1, %xmm7, %xmm7 + vaesenc %xmm0, %xmm8, %xmm8 + vaesenc %xmm0, %xmm9, %xmm9 + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc %xmm0, %xmm12, %xmm12 + vaesenc %xmm0, %xmm13, %xmm13 + vaesenc %xmm0, %xmm14, %xmm14 + vaesenc %xmm0, %xmm15, %xmm15 + # aesenc_pclmul_n + vmovdqu 80(%rcx), %xmm1 + vmovdqa 32(%rsp), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm1, %xmm1 + vpxor %xmm2, %xmm5, %xmm5 + vpclmulqdq $16, %xmm0, %xmm1, %xmm2 + vpxor %xmm3, %xmm5, %xmm5 + vpclmulqdq $0x01, %xmm0, %xmm1, %xmm3 + vpxor %xmm4, %xmm6, %xmm6 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm4 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm1 + vmovdqu 96(%rsi), %xmm0 + vpxor %xmm1, %xmm7, %xmm7 + vaesenc %xmm0, %xmm8, %xmm8 + vaesenc %xmm0, %xmm9, %xmm9 + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc %xmm0, %xmm12, %xmm12 + vaesenc %xmm0, %xmm13, %xmm13 + vaesenc %xmm0, %xmm14, %xmm14 + vaesenc %xmm0, %xmm15, %xmm15 + # aesenc_pclmul_n + vmovdqu 96(%rcx), %xmm1 + vmovdqa 16(%rsp), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm1, %xmm1 + vpxor %xmm2, %xmm5, %xmm5 + vpclmulqdq $16, %xmm0, %xmm1, %xmm2 + vpxor %xmm3, %xmm5, %xmm5 + vpclmulqdq $0x01, %xmm0, %xmm1, %xmm3 + vpxor %xmm4, %xmm6, %xmm6 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm4 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm1 + vmovdqu 112(%rsi), %xmm0 + vpxor %xmm1, %xmm7, %xmm7 + vaesenc %xmm0, %xmm8, %xmm8 + vaesenc %xmm0, %xmm9, %xmm9 + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc %xmm0, %xmm12, %xmm12 + vaesenc %xmm0, %xmm13, %xmm13 + vaesenc %xmm0, %xmm14, %xmm14 + vaesenc %xmm0, %xmm15, %xmm15 + # aesenc_pclmul_n + vmovdqu 112(%rcx), %xmm1 + vmovdqa (%rsp), %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm1, %xmm1 + vpxor %xmm2, %xmm5, %xmm5 + vpclmulqdq $16, %xmm0, %xmm1, %xmm2 + vpxor %xmm3, %xmm5, %xmm5 + vpclmulqdq $0x01, %xmm0, %xmm1, %xmm3 + vpxor %xmm4, %xmm6, %xmm6 + vpclmulqdq $0x00, %xmm0, %xmm1, %xmm4 + vpclmulqdq $0x11, %xmm0, %xmm1, %xmm1 + vmovdqu 128(%rsi), %xmm0 + vpxor %xmm1, %xmm7, %xmm7 + vaesenc %xmm0, %xmm8, %xmm8 + vaesenc %xmm0, %xmm9, %xmm9 + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc %xmm0, %xmm11, %xmm11 + vaesenc %xmm0, %xmm12, %xmm12 + vaesenc %xmm0, %xmm13, %xmm13 + vaesenc %xmm0, %xmm14, %xmm14 + vaesenc %xmm0, %xmm15, %xmm15 + # aesenc_pclmul_l + vpxor %xmm2, %xmm5, %xmm5 + vpxor %xmm4, %xmm6, %xmm6 + vpxor %xmm3, %xmm5, %xmm5 + vpslldq $8, %xmm5, %xmm1 + vpsrldq $8, %xmm5, %xmm5 + vmovdqa 144(%rsi), %xmm4 + vmovdqa L_avx2_aes_gcm_mod2_128(%rip), %xmm0 + vaesenc %xmm4, %xmm8, %xmm8 + vpxor %xmm1, %xmm6, %xmm6 + vpxor %xmm5, %xmm7, %xmm7 + vpclmulqdq $16, %xmm0, %xmm6, %xmm3 + vaesenc %xmm4, %xmm9, %xmm9 + vaesenc %xmm4, %xmm10, %xmm10 + vaesenc %xmm4, %xmm11, %xmm11 + vpshufd $0x4e, %xmm6, %xmm6 + vpxor %xmm3, %xmm6, %xmm6 + vpclmulqdq $16, %xmm0, %xmm6, %xmm3 + vaesenc %xmm4, %xmm12, %xmm12 + vaesenc %xmm4, %xmm13, %xmm13 + vaesenc %xmm4, %xmm14, %xmm14 + vpshufd $0x4e, %xmm6, %xmm6 + vpxor %xmm3, %xmm6, %xmm6 + vpxor %xmm7, %xmm6, %xmm6 + vaesenc %xmm4, %xmm15, %xmm15 + cmpl $11, %r9d + vmovdqa 160(%rsi), %xmm7 + jl L_AES_GCM_decrypt_avx2_aesenc_128_ghash_avx_done + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 176(%rsi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + cmpl $13, %r9d + vmovdqa 192(%rsi), %xmm7 + jl L_AES_GCM_decrypt_avx2_aesenc_128_ghash_avx_done + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 208(%rsi), %xmm7 + vaesenc %xmm7, %xmm8, %xmm8 + vaesenc %xmm7, %xmm9, %xmm9 + vaesenc %xmm7, %xmm10, %xmm10 + vaesenc %xmm7, %xmm11, %xmm11 + vaesenc %xmm7, %xmm12, %xmm12 + vaesenc %xmm7, %xmm13, %xmm13 + vaesenc %xmm7, %xmm14, %xmm14 + vaesenc %xmm7, %xmm15, %xmm15 + vmovdqa 224(%rsi), %xmm7 +L_AES_GCM_decrypt_avx2_aesenc_128_ghash_avx_done: + # aesenc_last + vaesenclast %xmm7, %xmm8, %xmm8 + vaesenclast %xmm7, %xmm9, %xmm9 + vaesenclast %xmm7, %xmm10, %xmm10 + vaesenclast %xmm7, %xmm11, %xmm11 + vmovdqu (%rcx), %xmm0 + vmovdqu 16(%rcx), %xmm1 + vmovdqu 32(%rcx), %xmm2 + vmovdqu 48(%rcx), %xmm3 + vpxor %xmm0, %xmm8, %xmm8 + vpxor %xmm1, %xmm9, %xmm9 + vpxor %xmm2, %xmm10, %xmm10 + vpxor %xmm3, %xmm11, %xmm11 + vmovdqu %xmm8, (%rdx) + vmovdqu %xmm9, 16(%rdx) + vmovdqu %xmm10, 32(%rdx) + vmovdqu %xmm11, 48(%rdx) + vaesenclast %xmm7, %xmm12, %xmm12 + vaesenclast %xmm7, %xmm13, %xmm13 + vaesenclast %xmm7, %xmm14, %xmm14 + vaesenclast %xmm7, %xmm15, %xmm15 + vmovdqu 64(%rcx), %xmm0 + vmovdqu 80(%rcx), %xmm1 + vmovdqu 96(%rcx), %xmm2 + vmovdqu 112(%rcx), %xmm3 + vpxor %xmm0, %xmm12, %xmm12 + vpxor %xmm1, %xmm13, %xmm13 + vpxor %xmm2, %xmm14, %xmm14 + vpxor %xmm3, %xmm15, %xmm15 + vmovdqu %xmm12, 64(%rdx) + vmovdqu %xmm13, 80(%rdx) + vmovdqu %xmm14, 96(%rdx) + vmovdqu %xmm15, 112(%rdx) + # aesenc_128_ghash - end + addl $0x80, %ebx + cmpl %r13d, %ebx + jl L_AES_GCM_decrypt_avx2_ghash_128 + vmovdqa (%rsp), %xmm5 + vmovdqa 128(%rsp), %xmm4 + vmovdqa 144(%rsp), %xmm15 +L_AES_GCM_decrypt_avx2_done_128: + cmpl %r10d, %ebx + jge L_AES_GCM_decrypt_avx2_done_dec + movl %r10d, %r13d + andl $0xfffffff0, %r13d + cmpl %r13d, %ebx + jge L_AES_GCM_decrypt_avx2_last_block_done +L_AES_GCM_decrypt_avx2_last_block_start: + vmovdqu (%rdi,%rbx,1), %xmm11 + vpshufb L_avx2_aes_gcm_bswap_epi64(%rip), %xmm4, %xmm10 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm11, %xmm12 + vpaddd L_avx2_aes_gcm_one(%rip), %xmm4, %xmm4 + vpxor %xmm6, %xmm12, %xmm12 + # aesenc_gfmul_sb + vpclmulqdq $0x01, %xmm5, %xmm12, %xmm2 + vpclmulqdq $16, %xmm5, %xmm12, %xmm3 + vpclmulqdq $0x00, %xmm5, %xmm12, %xmm1 + vpclmulqdq $0x11, %xmm5, %xmm12, %xmm8 + vpxor (%rsi), %xmm10, %xmm10 + vaesenc 16(%rsi), %xmm10, %xmm10 + vpxor %xmm2, %xmm3, %xmm3 + vpslldq $8, %xmm3, %xmm2 + vpsrldq $8, %xmm3, %xmm3 + vaesenc 32(%rsi), %xmm10, %xmm10 + vpxor %xmm1, %xmm2, %xmm2 + vpclmulqdq $16, L_avx2_aes_gcm_mod2_128(%rip), %xmm2, %xmm1 + vaesenc 48(%rsi), %xmm10, %xmm10 + vaesenc 64(%rsi), %xmm10, %xmm10 + vaesenc 80(%rsi), %xmm10, %xmm10 + vpshufd $0x4e, %xmm2, %xmm2 + vpxor %xmm1, %xmm2, %xmm2 + vpclmulqdq $16, L_avx2_aes_gcm_mod2_128(%rip), %xmm2, %xmm1 + vaesenc 96(%rsi), %xmm10, %xmm10 + vaesenc 112(%rsi), %xmm10, %xmm10 + vaesenc 128(%rsi), %xmm10, %xmm10 + vpshufd $0x4e, %xmm2, %xmm2 + vaesenc 144(%rsi), %xmm10, %xmm10 + vpxor %xmm3, %xmm8, %xmm8 + vpxor %xmm8, %xmm2, %xmm2 + vmovdqa 160(%rsi), %xmm0 + cmpl $11, %r9d + jl L_AES_GCM_decrypt_avx2_aesenc_gfmul_sb_last + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc 176(%rsi), %xmm10, %xmm10 + vmovdqa 192(%rsi), %xmm0 + cmpl $13, %r9d + jl L_AES_GCM_decrypt_avx2_aesenc_gfmul_sb_last + vaesenc %xmm0, %xmm10, %xmm10 + vaesenc 208(%rsi), %xmm10, %xmm10 + vmovdqa 224(%rsi), %xmm0 +L_AES_GCM_decrypt_avx2_aesenc_gfmul_sb_last: + vaesenclast %xmm0, %xmm10, %xmm10 + vpxor %xmm1, %xmm2, %xmm6 + vpxor %xmm11, %xmm10, %xmm10 + vmovdqu %xmm10, (%r8,%rbx,1) + addl $16, %ebx + cmpl %r13d, %ebx + jl L_AES_GCM_decrypt_avx2_last_block_start +L_AES_GCM_decrypt_avx2_last_block_done: + movl %r10d, %ecx + movl %r10d, %edx + andl $15, %ecx + jz L_AES_GCM_decrypt_avx2_done_dec + # aesenc_last15_dec + vpshufb L_avx2_aes_gcm_bswap_epi64(%rip), %xmm4, %xmm4 + vpxor (%rsi), %xmm4, %xmm4 + vaesenc 16(%rsi), %xmm4, %xmm4 + vaesenc 32(%rsi), %xmm4, %xmm4 + vaesenc 48(%rsi), %xmm4, %xmm4 + vaesenc 64(%rsi), %xmm4, %xmm4 + vaesenc 80(%rsi), %xmm4, %xmm4 + vaesenc 96(%rsi), %xmm4, %xmm4 + vaesenc 112(%rsi), %xmm4, %xmm4 + vaesenc 128(%rsi), %xmm4, %xmm4 + vaesenc 144(%rsi), %xmm4, %xmm4 + cmpl $11, %r9d + vmovdqa 160(%rsi), %xmm1 + jl L_AES_GCM_decrypt_avx2_aesenc_last15_dec_avx_aesenc_avx_last + vaesenc %xmm1, %xmm4, %xmm4 + vaesenc 176(%rsi), %xmm4, %xmm4 + cmpl $13, %r9d + vmovdqa 192(%rsi), %xmm1 + jl L_AES_GCM_decrypt_avx2_aesenc_last15_dec_avx_aesenc_avx_last + vaesenc %xmm1, %xmm4, %xmm4 + vaesenc 208(%rsi), %xmm4, %xmm4 + vmovdqa 224(%rsi), %xmm1 +L_AES_GCM_decrypt_avx2_aesenc_last15_dec_avx_aesenc_avx_last: + vaesenclast %xmm1, %xmm4, %xmm4 + xorl %ecx, %ecx + vpxor %xmm0, %xmm0, %xmm0 + vmovdqa %xmm4, (%rsp) + vmovdqa %xmm0, 16(%rsp) +L_AES_GCM_decrypt_avx2_aesenc_last15_dec_avx_loop: + movzbl (%rdi,%rbx,1), %r13d + movb %r13b, 16(%rsp,%rcx,1) + xorb (%rsp,%rcx,1), %r13b + movb %r13b, (%r8,%rbx,1) + incl %ebx + incl %ecx + cmpl %edx, %ebx + jl L_AES_GCM_decrypt_avx2_aesenc_last15_dec_avx_loop + vmovdqa 16(%rsp), %xmm4 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm4, %xmm4 + vpxor %xmm4, %xmm6, %xmm6 + # ghash_gfmul_red + vpclmulqdq $16, %xmm5, %xmm6, %xmm2 + vpclmulqdq $0x01, %xmm5, %xmm6, %xmm1 + vpclmulqdq $0x00, %xmm5, %xmm6, %xmm0 + vpxor %xmm1, %xmm2, %xmm2 + vpslldq $8, %xmm2, %xmm1 + vpsrldq $8, %xmm2, %xmm2 + vpxor %xmm0, %xmm1, %xmm1 + vpclmulqdq $0x11, %xmm5, %xmm6, %xmm6 + vpclmulqdq $16, L_avx2_aes_gcm_mod2_128(%rip), %xmm1, %xmm0 + vpshufd $0x4e, %xmm1, %xmm1 + vpxor %xmm0, %xmm1, %xmm1 + vpclmulqdq $16, L_avx2_aes_gcm_mod2_128(%rip), %xmm1, %xmm0 + vpshufd $0x4e, %xmm1, %xmm1 + vpxor %xmm2, %xmm6, %xmm6 + vpxor %xmm1, %xmm6, %xmm6 + vpxor %xmm0, %xmm6, %xmm6 +L_AES_GCM_decrypt_avx2_done_dec: + # calc_tag + shlq $3, %r10 + vpinsrq $0x00, %r10, %xmm0, %xmm0 + shlq $3, %r11 + vpinsrq $0x01, %r11, %xmm1, %xmm1 + vpblendd $12, %xmm1, %xmm0, %xmm0 + vpxor %xmm6, %xmm0, %xmm0 + # ghash_gfmul_red + vpclmulqdq $16, %xmm5, %xmm0, %xmm4 + vpclmulqdq $0x01, %xmm5, %xmm0, %xmm3 + vpclmulqdq $0x00, %xmm5, %xmm0, %xmm2 + vpxor %xmm3, %xmm4, %xmm4 + vpslldq $8, %xmm4, %xmm3 + vpsrldq $8, %xmm4, %xmm4 + vpxor %xmm2, %xmm3, %xmm3 + vpclmulqdq $0x11, %xmm5, %xmm0, %xmm0 + vpclmulqdq $16, L_avx2_aes_gcm_mod2_128(%rip), %xmm3, %xmm2 + vpshufd $0x4e, %xmm3, %xmm3 + vpxor %xmm2, %xmm3, %xmm3 + vpclmulqdq $16, L_avx2_aes_gcm_mod2_128(%rip), %xmm3, %xmm2 + vpshufd $0x4e, %xmm3, %xmm3 + vpxor %xmm4, %xmm0, %xmm0 + vpxor %xmm3, %xmm0, %xmm0 + vpxor %xmm2, %xmm0, %xmm0 + vpshufb L_avx2_aes_gcm_bswap_mask(%rip), %xmm0, %xmm0 + vpxor %xmm15, %xmm0, %xmm0 + # cmp_tag + cmpl $16, %r15d + je L_AES_GCM_decrypt_avx2_cmp_tag_16 + xorq %rdx, %rdx + xorq %rax, %rax + vmovdqa %xmm0, (%rsp) +L_AES_GCM_decrypt_avx2_cmp_tag_loop: + movzbl (%rsp,%rdx,1), %r13d + xorb (%r14,%rdx,1), %r13b + orb %r13b, %al + incl %edx + cmpl %r15d, %edx + jne L_AES_GCM_decrypt_avx2_cmp_tag_loop + cmpb $0x00, %al + sete %al + jmp L_AES_GCM_decrypt_avx2_cmp_tag_done +L_AES_GCM_decrypt_avx2_cmp_tag_16: + vmovdqu (%r14), %xmm1 + vpcmpeqb %xmm1, %xmm0, %xmm0 + vpmovmskb %xmm0, %rdx + # %%edx == 0xFFFF then return 1 else => return 0 + xorl %eax, %eax + cmpl $0xffff, %edx + sete %al +L_AES_GCM_decrypt_avx2_cmp_tag_done: + movl %eax, (%rbp) + vzeroupper + addq $0xa8, %rsp + popq %rbp + popq %r15 + popq %rbx + popq %r14 + popq %r12 + popq %r13 + repz retq +#ifndef __APPLE__ +.size AES_GCM_decrypt_avx2,.-AES_GCM_decrypt_avx2 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/arc4.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/arc4.c new file mode 100755 index 0000000..ac849a9 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/arc4.c @@ -0,0 +1,149 @@ +/* arc4.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifndef NO_RC4 + +#include +#include + + +int wc_Arc4SetKey(Arc4* arc4, const byte* key, word32 length) +{ + int ret = 0; + word32 i; + word32 keyIndex = 0, stateIndex = 0; + + if (arc4 == NULL || key == NULL) { + return BAD_FUNC_ARG; + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ARC4) && \ + defined(HAVE_CAVIUM) && !defined(HAVE_CAVIUM_V) + if (arc4->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ARC4) { + return NitroxArc4SetKey(arc4, key, length); + } +#endif + + arc4->x = 1; + arc4->y = 0; + + for (i = 0; i < ARC4_STATE_SIZE; i++) + arc4->state[i] = (byte)i; + + for (i = 0; i < ARC4_STATE_SIZE; i++) { + word32 a = arc4->state[i]; + stateIndex += key[keyIndex] + a; + stateIndex &= 0xFF; + arc4->state[i] = arc4->state[stateIndex]; + arc4->state[stateIndex] = (byte)a; + + if (++keyIndex >= length) + keyIndex = 0; + } + + return ret; +} + + +static WC_INLINE byte MakeByte(word32* x, word32* y, byte* s) +{ + word32 a = s[*x], b; + *y = (*y+a) & 0xff; + + b = s[*y]; + s[*x] = (byte)b; + s[*y] = (byte)a; + *x = (*x+1) & 0xff; + + return s[(a+b) & 0xff]; +} + + +int wc_Arc4Process(Arc4* arc4, byte* out, const byte* in, word32 length) +{ + int ret = 0; + word32 x; + word32 y; + + if (arc4 == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ARC4) && \ + defined(HAVE_CAVIUM) && !defined(HAVE_CAVIUM_V) + if (arc4->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ARC4) { + return NitroxArc4Process(arc4, out, in, length); + } +#endif + + x = arc4->x; + y = arc4->y; + + while(length--) + *out++ = *in++ ^ MakeByte(&x, &y, arc4->state); + + arc4->x = (byte)x; + arc4->y = (byte)y; + + return ret; +} + +/* Initialize Arc4 for use with async device */ +int wc_Arc4Init(Arc4* arc4, void* heap, int devId) +{ + int ret = 0; + + if (arc4 == NULL) + return BAD_FUNC_ARG; + + arc4->heap = heap; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ARC4) + ret = wolfAsync_DevCtxInit(&arc4->asyncDev, WOLFSSL_ASYNC_MARKER_ARC4, + arc4->heap, devId); +#else + (void)devId; +#endif /* WOLFSSL_ASYNC_CRYPT */ + + return ret; +} + + +/* Free Arc4 from use with async device */ +void wc_Arc4Free(Arc4* arc4) +{ + if (arc4 == NULL) + return; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ARC4) + wolfAsync_DevCtxFree(&arc4->asyncDev, WOLFSSL_ASYNC_MARKER_ARC4); +#endif /* WOLFSSL_ASYNC_CRYPT */ +} + +#endif /* NO_RC4 */ + diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/asm.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/asm.c new file mode 100755 index 0000000..4e51c82 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/asm.c @@ -0,0 +1,1783 @@ +/* asm.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +/* + * Based on public domain TomsFastMath 0.10 by Tom St Denis, tomstdenis@iahu.ca, + * http://math.libtomcrypt.com + */ + + +/******************************************************************/ +/* fp_montgomery_reduce.c asm or generic */ + + +/* Each platform needs to query info type 1 from cpuid to see if aesni is + * supported. Also, let's setup a macro for proper linkage w/o ABI conflicts + */ + +#if defined(HAVE_INTEL_MULX) +#ifndef _MSC_VER + #define cpuid(reg, leaf, sub)\ + __asm__ __volatile__ ("cpuid":\ + "=a" (reg[0]), "=b" (reg[1]), "=c" (reg[2]), "=d" (reg[3]) :\ + "a" (leaf), "c"(sub)); + + #define XASM_LINK(f) asm(f) +#else + + #include + #define cpuid(a,b,c) __cpuidex((int*)a,b,c) + + #define XASM_LINK(f) + +#endif /* _MSC_VER */ + +#define EAX 0 +#define EBX 1 +#define ECX 2 +#define EDX 3 + +#define CPUID_AVX1 0x1 +#define CPUID_AVX2 0x2 +#define CPUID_RDRAND 0x4 +#define CPUID_RDSEED 0x8 +#define CPUID_BMI2 0x10 /* MULX, RORX */ +#define CPUID_ADX 0x20 /* ADCX, ADOX */ + +#define IS_INTEL_AVX1 (cpuid_flags&CPUID_AVX1) +#define IS_INTEL_AVX2 (cpuid_flags&CPUID_AVX2) +#define IS_INTEL_BMI2 (cpuid_flags&CPUID_BMI2) +#define IS_INTEL_ADX (cpuid_flags&CPUID_ADX) +#define IS_INTEL_RDRAND (cpuid_flags&CPUID_RDRAND) +#define IS_INTEL_RDSEED (cpuid_flags&CPUID_RDSEED) +#define SET_FLAGS + +static word32 cpuid_check = 0 ; +static word32 cpuid_flags = 0 ; + +static word32 cpuid_flag(word32 leaf, word32 sub, word32 num, word32 bit) { + int got_intel_cpu = 0; + int got_amd_cpu = 0; + unsigned int reg[5]; + + reg[4] = '\0' ; + cpuid(reg, 0, 0); + + /* check for intel cpu */ + if( memcmp((char *)&(reg[EBX]), "Genu", 4) == 0 && + memcmp((char *)&(reg[EDX]), "ineI", 4) == 0 && + memcmp((char *)&(reg[ECX]), "ntel", 4) == 0) { + got_intel_cpu = 1; + } + + /* check for AMD cpu */ + if( memcmp((char *)&(reg[EBX]), "Auth", 4) == 0 && + memcmp((char *)&(reg[EDX]), "enti", 4) == 0 && + memcmp((char *)&(reg[ECX]), "cAMD", 4) == 0) { + got_amd_cpu = 1; + } + if (got_intel_cpu || got_amd_cpu) { + cpuid(reg, leaf, sub); + return((reg[num]>>bit)&0x1) ; + } + return 0 ; +} + +WC_INLINE static int set_cpuid_flags(void) { + if(cpuid_check == 0) { + if(cpuid_flag(7, 0, EBX, 8)){ cpuid_flags |= CPUID_BMI2 ; } + if(cpuid_flag(7, 0, EBX,19)){ cpuid_flags |= CPUID_ADX ; } + cpuid_check = 1 ; + return 0 ; + } + return 1 ; +} + +#define RETURN return +#define IF_HAVE_INTEL_MULX(func, ret) \ + if(cpuid_check==0)set_cpuid_flags() ; \ + if(IS_INTEL_BMI2 && IS_INTEL_ADX){ func; ret ; } + +#else + #define IF_HAVE_INTEL_MULX(func, ret) +#endif + +#if defined(TFM_X86) && !defined(TFM_SSE2) +/* x86-32 code */ + +#define MONT_START +#define MONT_FINI +#define LOOP_END +#define LOOP_START \ + mu = c[x] * mp + +#define INNERMUL \ +__asm__( \ + "movl %5,%%eax \n\t" \ + "mull %4 \n\t" \ + "addl %1,%%eax \n\t" \ + "adcl $0,%%edx \n\t" \ + "addl %%eax,%0 \n\t" \ + "adcl $0,%%edx \n\t" \ + "movl %%edx,%1 \n\t" \ +:"=g"(_c[LO]), "=r"(cy) \ +:"0"(_c[LO]), "1"(cy), "r"(mu), "r"(*tmpm++) \ +: "%eax", "%edx", "cc") + +#define PROPCARRY \ +__asm__( \ + "addl %1,%0 \n\t" \ + "setb %%al \n\t" \ + "movzbl %%al,%1 \n\t" \ +:"=g"(_c[LO]), "=r"(cy) \ +:"0"(_c[LO]), "1"(cy) \ +: "%eax", "cc") + +/******************************************************************/ +#elif defined(TFM_X86_64) +/* x86-64 code */ + +#define MONT_START +#define MONT_FINI +#define LOOP_END +#define LOOP_START \ + mu = c[x] * mp + +#define INNERMUL \ +__asm__( \ + "movq %5,%%rax \n\t" \ + "mulq %4 \n\t" \ + "addq %1,%%rax \n\t" \ + "adcq $0,%%rdx \n\t" \ + "addq %%rax,%0 \n\t" \ + "adcq $0,%%rdx \n\t" \ + "movq %%rdx,%1 \n\t" \ +:"=g"(_c[LO]), "=r"(cy) \ +:"0"(_c[LO]), "1"(cy), "r"(mu), "r"(*tmpm++) \ +: "%rax", "%rdx", "cc") + +#if defined(HAVE_INTEL_MULX) +#define MULX_INNERMUL8(x,y,z,cy) \ + __asm__ volatile ( \ + "movq %[yn], %%rdx\n\t" \ + "xorq %%rcx, %%rcx\n\t" \ + "movq 0(%[c]), %%r8\n\t" \ + "movq 8(%[c]), %%r9\n\t" \ + "movq 16(%[c]), %%r10\n\t" \ + "movq 24(%[c]), %%r11\n\t" \ + "movq 32(%[c]), %%r12\n\t" \ + "movq 40(%[c]), %%r13\n\t" \ + "movq 48(%[c]), %%r14\n\t" \ + "movq 56(%[c]), %%r15\n\t" \ + \ + "mulx 0(%[xp]), %%rax, %%rcx\n\t" \ + "adcxq %[cy], %%r8\n\t" \ + "adoxq %%rax, %%r8\n\t" \ + "mulx 8(%[xp]), %%rax, %[cy]\n\t" \ + "adcxq %%rcx, %%r9\n\t" \ + "adoxq %%rax, %%r9\n\t" \ + "mulx 16(%[xp]), %%rax, %%rcx\n\t" \ + "adcxq %[cy], %%r10\n\t" \ + "adoxq %%rax, %%r10\n\t" \ + "mulx 24(%[xp]), %%rax, %[cy]\n\t" \ + "adcxq %%rcx, %%r11\n\t" \ + "adoxq %%rax, %%r11\n\t" \ + "mulx 32(%[xp]), %%rax, %%rcx\n\t" \ + "adcxq %[cy], %%r12\n\t" \ + "adoxq %%rax, %%r12\n\t" \ + "mulx 40(%[xp]), %%rax, %[cy]\n\t" \ + "adcxq %%rcx, %%r13\n\t" \ + "adoxq %%rax, %%r13\n\t" \ + "mulx 48(%[xp]), %%rax, %%rcx\n\t" \ + "adcxq %[cy], %%r14\n\t" \ + "adoxq %%rax, %%r14\n\t" \ + "adcxq %%rcx, %%r15\n\t" \ + "mulx 56(%[xp]), %%rax, %[cy]\n\t" \ + "movq $0, %%rdx\n\t" \ + "adoxq %%rdx, %%rax\n\t" \ + "adcxq %%rdx, %[cy]\n\t" \ + "adoxq %%rdx, %[cy]\n\t" \ + "addq %%rax, %%r15\n\t" \ + "adcq $0, %[cy]\n\t" \ + \ + "movq %%r8, 0(%[c])\n\t" \ + "movq %%r9, 8(%[c])\n\t" \ + "movq %%r10, 16(%[c])\n\t" \ + "movq %%r11, 24(%[c])\n\t" \ + "movq %%r12, 32(%[c])\n\t" \ + "movq %%r13, 40(%[c])\n\t" \ + "movq %%r14, 48(%[c])\n\t" \ + "movq %%r15, 56(%[c])\n\t" \ + : [cy] "+r" (cy) \ + : [xp] "r" (x), [c] "r" (c_mulx), [yn] "rm" (y) \ + :"%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", \ + "%rdx", "%rax", "%rcx" \ + ) + +#define INNERMUL8_MULX \ +{\ + MULX_INNERMUL8(tmpm, mu, _c, cy);\ +} +#endif + +#define INNERMUL8 \ + __asm__( \ + "movq 0(%5),%%rax \n\t" \ + "movq 0(%2),%%r10 \n\t" \ + "movq 0x8(%5),%%r11 \n\t" \ + "mulq %4 \n\t" \ + "addq %%r10,%%rax \n\t" \ + "adcq $0,%%rdx \n\t" \ + "movq 0x8(%2),%%r10 \n\t" \ + "addq %3,%%rax \n\t" \ + "adcq $0,%%rdx \n\t" \ + "movq %%rax,0(%0) \n\t" \ + "movq %%rdx,%1 \n\t" \ + \ + "movq %%r11,%%rax \n\t" \ + "movq 0x10(%5),%%r11 \n\t" \ + "mulq %4 \n\t" \ + "addq %%r10,%%rax \n\t" \ + "adcq $0,%%rdx \n\t" \ + "movq 0x10(%2),%%r10 \n\t" \ + "addq %3,%%rax \n\t" \ + "adcq $0,%%rdx \n\t" \ + "movq %%rax,0x8(%0) \n\t" \ + "movq %%rdx,%1 \n\t" \ + \ + "movq %%r11,%%rax \n\t" \ + "movq 0x18(%5),%%r11 \n\t" \ + "mulq %4 \n\t" \ + "addq %%r10,%%rax \n\t" \ + "adcq $0,%%rdx \n\t" \ + "movq 0x18(%2),%%r10 \n\t" \ + "addq %3,%%rax \n\t" \ + "adcq $0,%%rdx \n\t" \ + "movq %%rax,0x10(%0) \n\t" \ + "movq %%rdx,%1 \n\t" \ + \ + "movq %%r11,%%rax \n\t" \ + "movq 0x20(%5),%%r11 \n\t" \ + "mulq %4 \n\t" \ + "addq %%r10,%%rax \n\t" \ + "adcq $0,%%rdx \n\t" \ + "movq 0x20(%2),%%r10 \n\t" \ + "addq %3,%%rax \n\t" \ + "adcq $0,%%rdx \n\t" \ + "movq %%rax,0x18(%0) \n\t" \ + "movq %%rdx,%1 \n\t" \ + \ + "movq %%r11,%%rax \n\t" \ + "movq 0x28(%5),%%r11 \n\t" \ + "mulq %4 \n\t" \ + "addq %%r10,%%rax \n\t" \ + "adcq $0,%%rdx \n\t" \ + "movq 0x28(%2),%%r10 \n\t" \ + "addq %3,%%rax \n\t" \ + "adcq $0,%%rdx \n\t" \ + "movq %%rax,0x20(%0) \n\t" \ + "movq %%rdx,%1 \n\t" \ + \ + "movq %%r11,%%rax \n\t" \ + "movq 0x30(%5),%%r11 \n\t" \ + "mulq %4 \n\t" \ + "addq %%r10,%%rax \n\t" \ + "adcq $0,%%rdx \n\t" \ + "movq 0x30(%2),%%r10 \n\t" \ + "addq %3,%%rax \n\t" \ + "adcq $0,%%rdx \n\t" \ + "movq %%rax,0x28(%0) \n\t" \ + "movq %%rdx,%1 \n\t" \ + \ + "movq %%r11,%%rax \n\t" \ + "movq 0x38(%5),%%r11 \n\t" \ + "mulq %4 \n\t" \ + "addq %%r10,%%rax \n\t" \ + "adcq $0,%%rdx \n\t" \ + "movq 0x38(%2),%%r10 \n\t" \ + "addq %3,%%rax \n\t" \ + "adcq $0,%%rdx \n\t" \ + "movq %%rax,0x30(%0) \n\t" \ + "movq %%rdx,%1 \n\t" \ + \ + "movq %%r11,%%rax \n\t" \ + "mulq %4 \n\t" \ + "addq %%r10,%%rax \n\t" \ + "adcq $0,%%rdx \n\t" \ + "addq %3,%%rax \n\t" \ + "adcq $0,%%rdx \n\t" \ + "movq %%rax,0x38(%0) \n\t" \ + "movq %%rdx,%1 \n\t" \ + \ +:"=r"(_c), "=r"(cy) \ +: "0"(_c), "1"(cy), "g"(mu), "r"(tmpm)\ +: "%rax", "%rdx", "%r10", "%r11", "cc") + +#define PROPCARRY \ +__asm__( \ + "addq %1,%0 \n\t" \ + "setb %%al \n\t" \ + "movzbq %%al,%1 \n\t" \ +:"=g"(_c[LO]), "=r"(cy) \ +:"0"(_c[LO]), "1"(cy) \ +: "%rax", "cc") + +/******************************************************************/ +#elif defined(TFM_SSE2) +/* SSE2 code (assumes 32-bit fp_digits) */ +/* XMM register assignments: + * xmm0 *tmpm++, then Mu * (*tmpm++) + * xmm1 c[x], then Mu + * xmm2 mp + * xmm3 cy + * xmm4 _c[LO] + */ + +#define MONT_START \ + __asm__("movd %0,%%mm2"::"g"(mp)) + +#define MONT_FINI \ + __asm__("emms") + +#define LOOP_START \ +__asm__( \ +"movd %0,%%mm1 \n\t" \ +"pxor %%mm3,%%mm3 \n\t" \ +"pmuludq %%mm2,%%mm1 \n\t" \ +:: "g"(c[x])) + +/* pmuludq on mmx registers does a 32x32->64 multiply. */ +#define INNERMUL \ +__asm__( \ + "movd %1,%%mm4 \n\t" \ + "movd %2,%%mm0 \n\t" \ + "paddq %%mm4,%%mm3 \n\t" \ + "pmuludq %%mm1,%%mm0 \n\t" \ + "paddq %%mm0,%%mm3 \n\t" \ + "movd %%mm3,%0 \n\t" \ + "psrlq $32, %%mm3 \n\t" \ +:"=g"(_c[LO]) : "0"(_c[LO]), "g"(*tmpm++) ); + +#define INNERMUL8 \ +__asm__( \ + "movd 0(%1),%%mm4 \n\t" \ + "movd 0(%2),%%mm0 \n\t" \ + "paddq %%mm4,%%mm3 \n\t" \ + "pmuludq %%mm1,%%mm0 \n\t" \ + "movd 4(%2),%%mm5 \n\t" \ + "paddq %%mm0,%%mm3 \n\t" \ + "movd 4(%1),%%mm6 \n\t" \ + "movd %%mm3,0(%0) \n\t" \ + "psrlq $32, %%mm3 \n\t" \ +\ + "paddq %%mm6,%%mm3 \n\t" \ + "pmuludq %%mm1,%%mm5 \n\t" \ + "movd 8(%2),%%mm6 \n\t" \ + "paddq %%mm5,%%mm3 \n\t" \ + "movd 8(%1),%%mm7 \n\t" \ + "movd %%mm3,4(%0) \n\t" \ + "psrlq $32, %%mm3 \n\t" \ +\ + "paddq %%mm7,%%mm3 \n\t" \ + "pmuludq %%mm1,%%mm6 \n\t" \ + "movd 12(%2),%%mm7 \n\t" \ + "paddq %%mm6,%%mm3 \n\t" \ + "movd 12(%1),%%mm5 \n\t" \ + "movd %%mm3,8(%0) \n\t" \ + "psrlq $32, %%mm3 \n\t" \ +\ + "paddq %%mm5,%%mm3 \n\t" \ + "pmuludq %%mm1,%%mm7 \n\t" \ + "movd 16(%2),%%mm5 \n\t" \ + "paddq %%mm7,%%mm3 \n\t" \ + "movd 16(%1),%%mm6 \n\t" \ + "movd %%mm3,12(%0) \n\t" \ + "psrlq $32, %%mm3 \n\t" \ +\ + "paddq %%mm6,%%mm3 \n\t" \ + "pmuludq %%mm1,%%mm5 \n\t" \ + "movd 20(%2),%%mm6 \n\t" \ + "paddq %%mm5,%%mm3 \n\t" \ + "movd 20(%1),%%mm7 \n\t" \ + "movd %%mm3,16(%0) \n\t" \ + "psrlq $32, %%mm3 \n\t" \ +\ + "paddq %%mm7,%%mm3 \n\t" \ + "pmuludq %%mm1,%%mm6 \n\t" \ + "movd 24(%2),%%mm7 \n\t" \ + "paddq %%mm6,%%mm3 \n\t" \ + "movd 24(%1),%%mm5 \n\t" \ + "movd %%mm3,20(%0) \n\t" \ + "psrlq $32, %%mm3 \n\t" \ +\ + "paddq %%mm5,%%mm3 \n\t" \ + "pmuludq %%mm1,%%mm7 \n\t" \ + "movd 28(%2),%%mm5 \n\t" \ + "paddq %%mm7,%%mm3 \n\t" \ + "movd 28(%1),%%mm6 \n\t" \ + "movd %%mm3,24(%0) \n\t" \ + "psrlq $32, %%mm3 \n\t" \ +\ + "paddq %%mm6,%%mm3 \n\t" \ + "pmuludq %%mm1,%%mm5 \n\t" \ + "paddq %%mm5,%%mm3 \n\t" \ + "movd %%mm3,28(%0) \n\t" \ + "psrlq $32, %%mm3 \n\t" \ +:"=r"(_c) : "0"(_c), "r"(tmpm) ); + +/* TAO switched tmpm from "g" to "r" after gcc tried to index the indexed stack + pointer */ + +#define LOOP_END \ +__asm__( "movd %%mm3,%0 \n" :"=r"(cy)) + +#define PROPCARRY \ +__asm__( \ + "addl %1,%0 \n\t" \ + "setb %%al \n\t" \ + "movzbl %%al,%1 \n\t" \ +:"=g"(_c[LO]), "=r"(cy) \ +:"0"(_c[LO]), "1"(cy) \ +: "%eax", "cc") + +/******************************************************************/ +#elif defined(TFM_ARM) + /* ARMv4 code */ + +#define MONT_START +#define MONT_FINI +#define LOOP_END +#define LOOP_START \ + mu = c[x] * mp + + +#ifdef __thumb__ + +#define INNERMUL \ +__asm__( \ + " LDR r0,%1 \n\t" \ + " ADDS r0,r0,%0 \n\t" \ + " ITE CS \n\t" \ + " MOVCS %0,#1 \n\t" \ + " MOVCC %0,#0 \n\t" \ + " UMLAL r0,%0,%3,%4 \n\t" \ + " STR r0,%1 \n\t" \ +:"=r"(cy),"=m"(_c[0]):"0"(cy),"r"(mu),"r"(*tmpm++),"m"(_c[0]):"r0","cc"); + +#define PROPCARRY \ +__asm__( \ + " LDR r0,%1 \n\t" \ + " ADDS r0,r0,%0 \n\t" \ + " STR r0,%1 \n\t" \ + " ITE CS \n\t" \ + " MOVCS %0,#1 \n\t" \ + " MOVCC %0,#0 \n\t" \ +:"=r"(cy),"=m"(_c[0]):"0"(cy),"m"(_c[0]):"r0","cc"); + + +/* TAO thumb mode uses ite (if then else) to detect carry directly + * fixed unmatched constraint warning by changing 1 to m */ + +#else /* __thumb__ */ + +#define INNERMUL \ +__asm__( \ + " LDR r0,%1 \n\t" \ + " ADDS r0,r0,%0 \n\t" \ + " MOVCS %0,#1 \n\t" \ + " MOVCC %0,#0 \n\t" \ + " UMLAL r0,%0,%3,%4 \n\t" \ + " STR r0,%1 \n\t" \ +:"=r"(cy),"=m"(_c[0]):"0"(cy),"r"(mu),"r"(*tmpm++),"1"(_c[0]):"r0","cc"); + +#define PROPCARRY \ +__asm__( \ + " LDR r0,%1 \n\t" \ + " ADDS r0,r0,%0 \n\t" \ + " STR r0,%1 \n\t" \ + " MOVCS %0,#1 \n\t" \ + " MOVCC %0,#0 \n\t" \ +:"=r"(cy),"=m"(_c[0]):"0"(cy),"1"(_c[0]):"r0","cc"); + +#endif /* __thumb__ */ + +#elif defined(TFM_PPC32) + +/* PPC32 */ +#define MONT_START +#define MONT_FINI +#define LOOP_END +#define LOOP_START \ + mu = c[x] * mp + +#define INNERMUL \ +__asm__( \ + " mullw 16,%3,%4 \n\t" \ + " mulhwu 17,%3,%4 \n\t" \ + " addc 16,16,%2 \n\t" \ + " addze 17,17 \n\t" \ + " addc %1,16,%5 \n\t" \ + " addze %0,17 \n\t" \ +:"=r"(cy),"=r"(_c[0]):"0"(cy),"r"(mu),"r"(tmpm[0]),"1"(_c[0]):"16", "17", "cc"); ++tmpm; + +#define PROPCARRY \ +__asm__( \ + " addc %1,%3,%2 \n\t" \ + " xor %0,%2,%2 \n\t" \ + " addze %0,%2 \n\t" \ +:"=r"(cy),"=r"(_c[0]):"0"(cy),"1"(_c[0]):"cc"); + +#elif defined(TFM_PPC64) + +/* PPC64 */ +#define MONT_START +#define MONT_FINI +#define LOOP_END +#define LOOP_START \ + mu = c[x] * mp + +#define INNERMUL \ +__asm__( \ + " mulld r16,%3,%4 \n\t" \ + " mulhdu r17,%3,%4 \n\t" \ + " addc r16,16,%0 \n\t" \ + " addze r17,r17 \n\t" \ + " ldx r18,0,%1 \n\t" \ + " addc r16,r16,r18 \n\t" \ + " addze %0,r17 \n\t" \ + " sdx r16,0,%1 \n\t" \ +:"=r"(cy),"=m"(_c[0]):"0"(cy),"r"(mu),"r"(tmpm[0]),"1"(_c[0]):"r16", "r17", "r18","cc"); ++tmpm; + +#define PROPCARRY \ +__asm__( \ + " ldx r16,0,%1 \n\t" \ + " addc r16,r16,%0 \n\t" \ + " sdx r16,0,%1 \n\t" \ + " xor %0,%0,%0 \n\t" \ + " addze %0,%0 \n\t" \ +:"=r"(cy),"=m"(_c[0]):"0"(cy),"1"(_c[0]):"r16","cc"); + +/******************************************************************/ + +#elif defined(TFM_AVR32) + +/* AVR32 */ +#define MONT_START +#define MONT_FINI +#define LOOP_END +#define LOOP_START \ + mu = c[x] * mp + +#define INNERMUL \ +__asm__( \ + " ld.w r2,%1 \n\t" \ + " add r2,%0 \n\t" \ + " eor r3,r3 \n\t" \ + " acr r3 \n\t" \ + " macu.d r2,%3,%4 \n\t" \ + " st.w %1,r2 \n\t" \ + " mov %0,r3 \n\t" \ +:"=r"(cy),"=r"(_c):"0"(cy),"r"(mu),"r"(*tmpm++),"1"(_c):"r2","r3"); + +#define PROPCARRY \ +__asm__( \ + " ld.w r2,%1 \n\t" \ + " add r2,%0 \n\t" \ + " st.w %1,r2 \n\t" \ + " eor %0,%0 \n\t" \ + " acr %0 \n\t" \ +:"=r"(cy),"=r"(&_c[0]):"0"(cy),"1"(&_c[0]):"r2","cc"); + +/******************************************************************/ +#elif defined(TFM_MIPS) + +/* MIPS */ +#define MONT_START +#define MONT_FINI +#define LOOP_END +#define LOOP_START \ + mu = c[x] * mp + +#define INNERMUL \ +__asm__( \ + " multu %3,%4 \n\t" \ + " mflo $12 \n\t" \ + " mfhi $13 \n\t" \ + " addu $12,$12,%0 \n\t" \ + " sltu $10,$12,%0 \n\t" \ + " addu $13,$13,$10 \n\t" \ + " lw $10,%1 \n\t" \ + " addu $12,$12,$10 \n\t" \ + " sltu $10,$12,$10 \n\t" \ + " addu %0,$13,$10 \n\t" \ + " sw $12,%1 \n\t" \ +:"+r"(cy),"+m"(_c[0]):""(cy),"r"(mu),"r"(tmpm[0]),""(_c[0]):"$10","$12","$13"); ++tmpm; + +#define PROPCARRY \ +__asm__( \ + " lw $10,%1 \n\t" \ + " addu $10,$10,%0 \n\t" \ + " sw $10,%1 \n\t" \ + " sltu %0,$10,%0 \n\t" \ +:"+r"(cy),"+m"(_c[0]):""(cy),""(_c[0]):"$10"); + +/******************************************************************/ +#else + +/* ISO C code */ +#define MONT_START +#define MONT_FINI +#define LOOP_END +#define LOOP_START \ + mu = c[x] * mp + +#define INNERMUL \ + do { fp_word t; \ + t = ((fp_word)_c[0] + (fp_word)cy) + \ + (((fp_word)mu) * ((fp_word)*tmpm++)); \ + _c[0] = (fp_digit)t; \ + cy = (fp_digit)(t >> DIGIT_BIT); \ + } while (0) + +#define PROPCARRY \ + do { fp_digit t = _c[0] += cy; cy = (t < cy); } while (0) + +#endif +/******************************************************************/ + + +#define LO 0 +/* end fp_montogomery_reduce.c asm */ + + +/* start fp_sqr_comba.c asm */ +#if defined(TFM_X86) + +/* x86-32 optimized */ + +#define COMBA_START + +#define CLEAR_CARRY \ + c0 = c1 = c2 = 0; + +#define COMBA_STORE(x) \ + x = c0; + +#define COMBA_STORE2(x) \ + x = c1; + +#define CARRY_FORWARD \ + do { c0 = c1; c1 = c2; c2 = 0; } while (0); + +#define COMBA_FINI + +#define SQRADD(i, j) \ +__asm__( \ + "movl %6,%%eax \n\t" \ + "mull %%eax \n\t" \ + "addl %%eax,%0 \n\t" \ + "adcl %%edx,%1 \n\t" \ + "adcl $0,%2 \n\t" \ + :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i) :"%eax","%edx","cc"); + +#define SQRADD2(i, j) \ +__asm__( \ + "movl %6,%%eax \n\t" \ + "mull %7 \n\t" \ + "addl %%eax,%0 \n\t" \ + "adcl %%edx,%1 \n\t" \ + "adcl $0,%2 \n\t" \ + "addl %%eax,%0 \n\t" \ + "adcl %%edx,%1 \n\t" \ + "adcl $0,%2 \n\t" \ + :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i), "m"(j) :"%eax","%edx", "cc"); + +#define SQRADDSC(i, j) \ +__asm__( \ + "movl %3,%%eax \n\t" \ + "mull %4 \n\t" \ + "movl %%eax,%0 \n\t" \ + "movl %%edx,%1 \n\t" \ + "xorl %2,%2 \n\t" \ + :"=r"(sc0), "=r"(sc1), "=r"(sc2): "g"(i), "g"(j) :"%eax","%edx","cc"); + +#define SQRADDAC(i, j) \ +__asm__( \ + "movl %6,%%eax \n\t" \ + "mull %7 \n\t" \ + "addl %%eax,%0 \n\t" \ + "adcl %%edx,%1 \n\t" \ + "adcl $0,%2 \n\t" \ + :"=r"(sc0), "=r"(sc1), "=r"(sc2): "0"(sc0), "1"(sc1), "2"(sc2), "g"(i), "g"(j) :"%eax","%edx","cc"); + +#define SQRADDDB \ +__asm__( \ + "addl %6,%0 \n\t" \ + "adcl %7,%1 \n\t" \ + "adcl %8,%2 \n\t" \ + "addl %6,%0 \n\t" \ + "adcl %7,%1 \n\t" \ + "adcl %8,%2 \n\t" \ + :"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(sc0), "r"(sc1), "r"(sc2) : "cc"); + +#elif defined(TFM_X86_64) +/* x86-64 optimized */ + +#define COMBA_START + +#define CLEAR_CARRY \ + c0 = c1 = c2 = 0; + +#define COMBA_STORE(x) \ + x = c0; + +#define COMBA_STORE2(x) \ + x = c1; + +#define CARRY_FORWARD \ + do { c0 = c1; c1 = c2; c2 = 0; } while (0); + +#define COMBA_FINI + +#define SQRADD(i, j) \ +__asm__( \ + "movq %6,%%rax \n\t" \ + "mulq %%rax \n\t" \ + "addq %%rax,%0 \n\t" \ + "adcq %%rdx,%1 \n\t" \ + "adcq $0,%2 \n\t" \ + :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "x"(i) :"%rax","%rdx","cc"); + +#define SQRADD2(i, j) \ +__asm__( \ + "movq %6,%%rax \n\t" \ + "mulq %7 \n\t" \ + "addq %%rax,%0 \n\t" \ + "adcq %%rdx,%1 \n\t" \ + "adcq $0,%2 \n\t" \ + "addq %%rax,%0 \n\t" \ + "adcq %%rdx,%1 \n\t" \ + "adcq $0,%2 \n\t" \ + :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "g"(i), "g"(j) :"%rax","%rdx","cc"); + +#define SQRADDSC(i, j) \ +__asm__( \ + "movq %3,%%rax \n\t" \ + "mulq %4 \n\t" \ + "movq %%rax,%0 \n\t" \ + "movq %%rdx,%1 \n\t" \ + "xorq %2,%2 \n\t" \ + :"=r"(sc0), "=r"(sc1), "=r"(sc2): "g"(i), "g"(j) :"%rax","%rdx","cc"); + +#define SQRADDAC(i, j) \ +__asm__( \ + "movq %6,%%rax \n\t" \ + "mulq %7 \n\t" \ + "addq %%rax,%0 \n\t" \ + "adcq %%rdx,%1 \n\t" \ + "adcq $0,%2 \n\t" \ + :"=r"(sc0), "=r"(sc1), "=r"(sc2): "0"(sc0), "1"(sc1), "2"(sc2), "g"(i), "g"(j) :"%rax","%rdx","cc"); + +#define SQRADDDB \ +__asm__( \ + "addq %6,%0 \n\t" \ + "adcq %7,%1 \n\t" \ + "adcq %8,%2 \n\t" \ + "addq %6,%0 \n\t" \ + "adcq %7,%1 \n\t" \ + "adcq %8,%2 \n\t" \ + :"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(sc0), "r"(sc1), "r"(sc2) : "cc"); + +#elif defined(TFM_SSE2) + +/* SSE2 Optimized */ +#define COMBA_START + +#define CLEAR_CARRY \ + c0 = c1 = c2 = 0; + +#define COMBA_STORE(x) \ + x = c0; + +#define COMBA_STORE2(x) \ + x = c1; + +#define CARRY_FORWARD \ + do { c0 = c1; c1 = c2; c2 = 0; } while (0); + +#define COMBA_FINI \ + __asm__("emms"); + +#define SQRADD(i, j) \ +__asm__( \ + "movd %6,%%mm0 \n\t" \ + "pmuludq %%mm0,%%mm0\n\t" \ + "movd %%mm0,%%eax \n\t" \ + "psrlq $32,%%mm0 \n\t" \ + "addl %%eax,%0 \n\t" \ + "movd %%mm0,%%eax \n\t" \ + "adcl %%eax,%1 \n\t" \ + "adcl $0,%2 \n\t" \ + :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i) :"%eax","cc"); + +#define SQRADD2(i, j) \ +__asm__( \ + "movd %6,%%mm0 \n\t" \ + "movd %7,%%mm1 \n\t" \ + "pmuludq %%mm1,%%mm0\n\t" \ + "movd %%mm0,%%eax \n\t" \ + "psrlq $32,%%mm0 \n\t" \ + "movd %%mm0,%%edx \n\t" \ + "addl %%eax,%0 \n\t" \ + "adcl %%edx,%1 \n\t" \ + "adcl $0,%2 \n\t" \ + "addl %%eax,%0 \n\t" \ + "adcl %%edx,%1 \n\t" \ + "adcl $0,%2 \n\t" \ + :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i), "m"(j) :"%eax","%edx","cc"); + +#define SQRADDSC(i, j) \ +__asm__( \ + "movd %3,%%mm0 \n\t" \ + "movd %4,%%mm1 \n\t" \ + "pmuludq %%mm1,%%mm0\n\t" \ + "movd %%mm0,%0 \n\t" \ + "psrlq $32,%%mm0 \n\t" \ + "movd %%mm0,%1 \n\t" \ + "xorl %2,%2 \n\t" \ + :"=r"(sc0), "=r"(sc1), "=r"(sc2): "m"(i), "m"(j)); + +/* TAO removed sc0,1,2 as input to remove warning so %6,%7 become %3,%4 */ + +#define SQRADDAC(i, j) \ +__asm__( \ + "movd %6,%%mm0 \n\t" \ + "movd %7,%%mm1 \n\t" \ + "pmuludq %%mm1,%%mm0\n\t" \ + "movd %%mm0,%%eax \n\t" \ + "psrlq $32,%%mm0 \n\t" \ + "movd %%mm0,%%edx \n\t" \ + "addl %%eax,%0 \n\t" \ + "adcl %%edx,%1 \n\t" \ + "adcl $0,%2 \n\t" \ + :"=r"(sc0), "=r"(sc1), "=r"(sc2): "0"(sc0), "1"(sc1), "2"(sc2), "m"(i), "m"(j) :"%eax","%edx","cc"); + +#define SQRADDDB \ +__asm__( \ + "addl %6,%0 \n\t" \ + "adcl %7,%1 \n\t" \ + "adcl %8,%2 \n\t" \ + "addl %6,%0 \n\t" \ + "adcl %7,%1 \n\t" \ + "adcl %8,%2 \n\t" \ + :"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(sc0), "r"(sc1), "r"(sc2) : "cc"); + +#elif defined(TFM_ARM) + +/* ARM code */ + +#define COMBA_START + +#define CLEAR_CARRY \ + c0 = c1 = c2 = 0; + +#define COMBA_STORE(x) \ + x = c0; + +#define COMBA_STORE2(x) \ + x = c1; + +#define CARRY_FORWARD \ + do { c0 = c1; c1 = c2; c2 = 0; } while (0); + +#define COMBA_FINI + +/* multiplies point i and j, updates carry "c1" and digit c2 */ +#define SQRADD(i, j) \ +__asm__( \ +" UMULL r0,r1,%6,%6 \n\t" \ +" ADDS %0,%0,r0 \n\t" \ +" ADCS %1,%1,r1 \n\t" \ +" ADC %2,%2,#0 \n\t" \ +:"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(i) : "r0", "r1", "cc"); + +/* for squaring some of the terms are doubled... */ +#define SQRADD2(i, j) \ +__asm__( \ +" UMULL r0,r1,%6,%7 \n\t" \ +" ADDS %0,%0,r0 \n\t" \ +" ADCS %1,%1,r1 \n\t" \ +" ADC %2,%2,#0 \n\t" \ +" ADDS %0,%0,r0 \n\t" \ +" ADCS %1,%1,r1 \n\t" \ +" ADC %2,%2,#0 \n\t" \ +:"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j) : "r0", "r1", "cc"); + +#define SQRADDSC(i, j) \ +__asm__( \ +" UMULL %0,%1,%3,%4 \n\t" \ +" SUB %2,%2,%2 \n\t" \ +:"=r"(sc0), "=r"(sc1), "=r"(sc2) : "r"(i), "r"(j) : "cc"); + +/* TAO removed sc0,1,2 as input to remove warning so %6,%7 become %3,%4 */ + +#define SQRADDAC(i, j) \ +__asm__( \ +" UMULL r0,r1,%6,%7 \n\t" \ +" ADDS %0,%0,r0 \n\t" \ +" ADCS %1,%1,r1 \n\t" \ +" ADC %2,%2,#0 \n\t" \ +:"=r"(sc0), "=r"(sc1), "=r"(sc2) : "0"(sc0), "1"(sc1), "2"(sc2), "r"(i), "r"(j) : "r0", "r1", "cc"); + +#define SQRADDDB \ +__asm__( \ +" ADDS %0,%0,%3 \n\t" \ +" ADCS %1,%1,%4 \n\t" \ +" ADC %2,%2,%5 \n\t" \ +" ADDS %0,%0,%3 \n\t" \ +" ADCS %1,%1,%4 \n\t" \ +" ADC %2,%2,%5 \n\t" \ +:"=r"(c0), "=r"(c1), "=r"(c2) : "r"(sc0), "r"(sc1), "r"(sc2), "0"(c0), "1"(c1), "2"(c2) : "cc"); + +#elif defined(TFM_PPC32) + +/* PPC32 */ + +#define COMBA_START + +#define CLEAR_CARRY \ + c0 = c1 = c2 = 0; + +#define COMBA_STORE(x) \ + x = c0; + +#define COMBA_STORE2(x) \ + x = c1; + +#define CARRY_FORWARD \ + do { c0 = c1; c1 = c2; c2 = 0; } while (0); + +#define COMBA_FINI + +/* multiplies point i and j, updates carry "c1" and digit c2 */ +#define SQRADD(i, j) \ +__asm__( \ + " mullw 16,%6,%6 \n\t" \ + " addc %0,%0,16 \n\t" \ + " mulhwu 16,%6,%6 \n\t" \ + " adde %1,%1,16 \n\t" \ + " addze %2,%2 \n\t" \ +:"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i):"16","cc"); + +/* for squaring some of the terms are doubled... */ +#define SQRADD2(i, j) \ +__asm__( \ + " mullw 16,%6,%7 \n\t" \ + " mulhwu 17,%6,%7 \n\t" \ + " addc %0,%0,16 \n\t" \ + " adde %1,%1,17 \n\t" \ + " addze %2,%2 \n\t" \ + " addc %0,%0,16 \n\t" \ + " adde %1,%1,17 \n\t" \ + " addze %2,%2 \n\t" \ +:"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j):"16", "17","cc"); + +#define SQRADDSC(i, j) \ +__asm__( \ + " mullw %0,%6,%7 \n\t" \ + " mulhwu %1,%6,%7 \n\t" \ + " xor %2,%2,%2 \n\t" \ +:"=r"(sc0), "=r"(sc1), "=r"(sc2):"0"(sc0), "1"(sc1), "2"(sc2), "r"(i),"r"(j) : "cc"); + +#define SQRADDAC(i, j) \ +__asm__( \ + " mullw 16,%6,%7 \n\t" \ + " addc %0,%0,16 \n\t" \ + " mulhwu 16,%6,%7 \n\t" \ + " adde %1,%1,16 \n\t" \ + " addze %2,%2 \n\t" \ +:"=r"(sc0), "=r"(sc1), "=r"(sc2):"0"(sc0), "1"(sc1), "2"(sc2), "r"(i), "r"(j):"16", "cc"); + +#define SQRADDDB \ +__asm__( \ + " addc %0,%0,%3 \n\t" \ + " adde %1,%1,%4 \n\t" \ + " adde %2,%2,%5 \n\t" \ + " addc %0,%0,%3 \n\t" \ + " adde %1,%1,%4 \n\t" \ + " adde %2,%2,%5 \n\t" \ +:"=r"(c0), "=r"(c1), "=r"(c2) : "r"(sc0), "r"(sc1), "r"(sc2), "0"(c0), "1"(c1), "2"(c2) : "cc"); + +#elif defined(TFM_PPC64) +/* PPC64 */ + +#define COMBA_START + +#define CLEAR_CARRY \ + c0 = c1 = c2 = 0; + +#define COMBA_STORE(x) \ + x = c0; + +#define COMBA_STORE2(x) \ + x = c1; + +#define CARRY_FORWARD \ + do { c0 = c1; c1 = c2; c2 = 0; } while (0); + +#define COMBA_FINI + +/* multiplies point i and j, updates carry "c1" and digit c2 */ +#define SQRADD(i, j) \ +__asm__( \ + " mulld r16,%6,%6 \n\t" \ + " addc %0,%0,r16 \n\t" \ + " mulhdu r16,%6,%6 \n\t" \ + " adde %1,%1,r16 \n\t" \ + " addze %2,%2 \n\t" \ +:"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i):"r16","cc"); + +/* for squaring some of the terms are doubled... */ +#define SQRADD2(i, j) \ +__asm__( \ + " mulld r16,%6,%7 \n\t" \ + " mulhdu r17,%6,%7 \n\t" \ + " addc %0,%0,r16 \n\t" \ + " adde %1,%1,r17 \n\t" \ + " addze %2,%2 \n\t" \ + " addc %0,%0,r16 \n\t" \ + " adde %1,%1,r17 \n\t" \ + " addze %2,%2 \n\t" \ +:"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j):"r16", "r17","cc"); + +#define SQRADDSC(i, j) \ +__asm__( \ + " mulld %0,%6,%7 \n\t" \ + " mulhdu %1,%6,%7 \n\t" \ + " xor %2,%2,%2 \n\t" \ +:"=r"(sc0), "=r"(sc1), "=r"(sc2):"0"(sc0), "1"(sc1), "2"(sc2), "r"(i),"r"(j) : "cc"); + +#define SQRADDAC(i, j) \ +__asm__( \ + " mulld r16,%6,%7 \n\t" \ + " addc %0,%0,r16 \n\t" \ + " mulhdu r16,%6,%7 \n\t" \ + " adde %1,%1,r16 \n\t" \ + " addze %2,%2 \n\t" \ +:"=r"(sc0), "=r"(sc1), "=r"(sc2):"0"(sc0), "1"(sc1), "2"(sc2), "r"(i), "r"(j):"r16", "cc"); + +#define SQRADDDB \ +__asm__( \ + " addc %0,%0,%3 \n\t" \ + " adde %1,%1,%4 \n\t" \ + " adde %2,%2,%5 \n\t" \ + " addc %0,%0,%3 \n\t" \ + " adde %1,%1,%4 \n\t" \ + " adde %2,%2,%5 \n\t" \ +:"=r"(c0), "=r"(c1), "=r"(c2) : "r"(sc0), "r"(sc1), "r"(sc2), "0"(c0), "1"(c1), "2"(c2) : "cc"); + + +#elif defined(TFM_AVR32) + +/* AVR32 */ + +#define COMBA_START + +#define CLEAR_CARRY \ + c0 = c1 = c2 = 0; + +#define COMBA_STORE(x) \ + x = c0; + +#define COMBA_STORE2(x) \ + x = c1; + +#define CARRY_FORWARD \ + do { c0 = c1; c1 = c2; c2 = 0; } while (0); + +#define COMBA_FINI + +/* multiplies point i and j, updates carry "c1" and digit c2 */ +#define SQRADD(i, j) \ +__asm__( \ + " mulu.d r2,%6,%6 \n\t" \ + " add %0,%0,r2 \n\t" \ + " adc %1,%1,r3 \n\t" \ + " acr %2 \n\t" \ +:"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i):"r2","r3"); + +/* for squaring some of the terms are doubled... */ +#define SQRADD2(i, j) \ +__asm__( \ + " mulu.d r2,%6,%7 \n\t" \ + " add %0,%0,r2 \n\t" \ + " adc %1,%1,r3 \n\t" \ + " acr %2, \n\t" \ + " add %0,%0,r2 \n\t" \ + " adc %1,%1,r3 \n\t" \ + " acr %2, \n\t" \ +:"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j):"r2", "r3"); + +#define SQRADDSC(i, j) \ +__asm__( \ + " mulu.d r2,%6,%7 \n\t" \ + " mov %0,r2 \n\t" \ + " mov %1,r3 \n\t" \ + " eor %2,%2 \n\t" \ +:"=r"(sc0), "=r"(sc1), "=r"(sc2):"0"(sc0), "1"(sc1), "2"(sc2), "r"(i),"r"(j) : "r2", "r3"); + +#define SQRADDAC(i, j) \ +__asm__( \ + " mulu.d r2,%6,%7 \n\t" \ + " add %0,%0,r2 \n\t" \ + " adc %1,%1,r3 \n\t" \ + " acr %2 \n\t" \ +:"=r"(sc0), "=r"(sc1), "=r"(sc2):"0"(sc0), "1"(sc1), "2"(sc2), "r"(i), "r"(j):"r2", "r3"); + +#define SQRADDDB \ +__asm__( \ + " add %0,%0,%3 \n\t" \ + " adc %1,%1,%4 \n\t" \ + " adc %2,%2,%5 \n\t" \ + " add %0,%0,%3 \n\t" \ + " adc %1,%1,%4 \n\t" \ + " adc %2,%2,%5 \n\t" \ +:"=r"(c0), "=r"(c1), "=r"(c2) : "r"(sc0), "r"(sc1), "r"(sc2), "0"(c0), "1"(c1), "2"(c2) : "cc"); + +#elif defined(TFM_MIPS) + +/* MIPS */ +#define COMBA_START + +#define CLEAR_CARRY \ + c0 = c1 = c2 = 0; + +#define COMBA_STORE(x) \ + x = c0; + +#define COMBA_STORE2(x) \ + x = c1; + +#define CARRY_FORWARD \ + do { c0 = c1; c1 = c2; c2 = 0; } while (0); + +#define COMBA_FINI + +/* multiplies point i and j, updates carry "c1" and digit c2 */ +#define SQRADD(i, j) \ +__asm__( \ + " multu %6,%6 \n\t" \ + " mflo $12 \n\t" \ + " mfhi $13 \n\t" \ + " addu %0,%0,$12 \n\t" \ + " sltu $12,%0,$12 \n\t" \ + " addu %1,%1,$13 \n\t" \ + " sltu $13,%1,$13 \n\t" \ + " addu %1,%1,$12 \n\t" \ + " sltu $12,%1,$12 \n\t" \ + " addu %2,%2,$13 \n\t" \ + " addu %2,%2,$12 \n\t" \ +:"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i):"$12","$13"); + +/* for squaring some of the terms are doubled... */ +#define SQRADD2(i, j) \ +__asm__( \ + " multu %6,%7 \n\t" \ + " mflo $12 \n\t" \ + " mfhi $13 \n\t" \ + \ + " addu %0,%0,$12 \n\t" \ + " sltu $14,%0,$12 \n\t" \ + " addu %1,%1,$13 \n\t" \ + " sltu $15,%1,$13 \n\t" \ + " addu %1,%1,$14 \n\t" \ + " sltu $14,%1,$14 \n\t" \ + " addu %2,%2,$15 \n\t" \ + " addu %2,%2,$14 \n\t" \ + \ + " addu %0,%0,$12 \n\t" \ + " sltu $14,%0,$12 \n\t" \ + " addu %1,%1,$13 \n\t" \ + " sltu $15,%1,$13 \n\t" \ + " addu %1,%1,$14 \n\t" \ + " sltu $14,%1,$14 \n\t" \ + " addu %2,%2,$15 \n\t" \ + " addu %2,%2,$14 \n\t" \ +:"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j):"$12", "$13", "$14", "$15"); + +#define SQRADDSC(i, j) \ +__asm__( \ + " multu %6,%7 \n\t" \ + " mflo %0 \n\t" \ + " mfhi %1 \n\t" \ + " xor %2,%2,%2 \n\t" \ +:"=r"(sc0), "=r"(sc1), "=r"(sc2):"0"(sc0), "1"(sc1), "2"(sc2), "r"(i),"r"(j) : "cc"); + +#define SQRADDAC(i, j) \ +__asm__( \ + " multu %6,%7 \n\t" \ + " mflo $12 \n\t" \ + " mfhi $13 \n\t" \ + " addu %0,%0,$12 \n\t" \ + " sltu $12,%0,$12 \n\t" \ + " addu %1,%1,$13 \n\t" \ + " sltu $13,%1,$13 \n\t" \ + " addu %1,%1,$12 \n\t" \ + " sltu $12,%1,$12 \n\t" \ + " addu %2,%2,$13 \n\t" \ + " addu %2,%2,$12 \n\t" \ +:"=r"(sc0), "=r"(sc1), "=r"(sc2):"0"(sc0), "1"(sc1), "2"(sc2), "r"(i), "r"(j):"$12", "$13", "$14"); + +#define SQRADDDB \ +__asm__( \ + " addu %0,%0,%3 \n\t" \ + " sltu $10,%0,%3 \n\t" \ + " addu %1,%1,$10 \n\t" \ + " sltu $10,%1,$10 \n\t" \ + " addu %1,%1,%4 \n\t" \ + " sltu $11,%1,%4 \n\t" \ + " addu %2,%2,$10 \n\t" \ + " addu %2,%2,$11 \n\t" \ + " addu %2,%2,%5 \n\t" \ + \ + " addu %0,%0,%3 \n\t" \ + " sltu $10,%0,%3 \n\t" \ + " addu %1,%1,$10 \n\t" \ + " sltu $10,%1,$10 \n\t" \ + " addu %1,%1,%4 \n\t" \ + " sltu $11,%1,%4 \n\t" \ + " addu %2,%2,$10 \n\t" \ + " addu %2,%2,$11 \n\t" \ + " addu %2,%2,%5 \n\t" \ +:"=r"(c0), "=r"(c1), "=r"(c2) : "r"(sc0), "r"(sc1), "r"(sc2), "0"(c0), "1"(c1), "2"(c2) : "$10", "$11"); + +#else + +#define TFM_ISO + +/* ISO C portable code */ + +#define COMBA_START + +#define CLEAR_CARRY \ + c0 = c1 = c2 = 0; + +#define COMBA_STORE(x) \ + x = c0; + +#define COMBA_STORE2(x) \ + x = c1; + +#define CARRY_FORWARD \ + do { c0 = c1; c1 = c2; c2 = 0; } while (0); + +#define COMBA_FINI + +/* multiplies point i and j, updates carry "c1" and digit c2 */ +#define SQRADD(i, j) \ + do { fp_word t; \ + t = c0 + ((fp_word)i) * ((fp_word)j); c0 = (fp_digit)t; \ + t = c1 + (t >> DIGIT_BIT); c1 = (fp_digit)t; \ + c2 +=(fp_digit) (t >> DIGIT_BIT); \ + } while (0); + + +/* for squaring some of the terms are doubled... */ +#define SQRADD2(i, j) \ + do { fp_word t; \ + t = ((fp_word)i) * ((fp_word)j); \ + tt = (fp_word)c0 + t; c0 = (fp_digit)tt; \ + tt = (fp_word)c1 + (tt >> DIGIT_BIT); c1 = (fp_digit)tt; \ + c2 +=(fp_digit)(tt >> DIGIT_BIT); \ + tt = (fp_word)c0 + t; c0 = (fp_digit)tt; \ + tt = (fp_word)c1 + (tt >> DIGIT_BIT); c1 = (fp_digit)tt; \ + c2 +=(fp_digit)(tt >> DIGIT_BIT); \ + } while (0); + +#define SQRADDSC(i, j) \ + do { fp_word t; \ + t = ((fp_word)i) * ((fp_word)j); \ + sc0 = (fp_digit)t; sc1 = (t >> DIGIT_BIT); sc2 = 0; \ + } while (0); + +#define SQRADDAC(i, j) \ + do { fp_word t; \ + t = sc0 + ((fp_word)i) * ((fp_word)j); sc0 = (fp_digit)t; \ + t = sc1 + (t >> DIGIT_BIT); sc1 = (fp_digit)t; \ + sc2 += (fp_digit)(t >> DIGIT_BIT); \ + } while (0); + +#define SQRADDDB \ + do { fp_word t; \ + t = ((fp_word)sc0) + ((fp_word)sc0) + c0; c0 = (fp_digit)t; \ + t = ((fp_word)sc1) + ((fp_word)sc1) + c1 + (t >> DIGIT_BIT); \ + c1 = (fp_digit)t; \ + c2 = c2 + (fp_digit)(((fp_word)sc2) + ((fp_word)sc2) + (t >> DIGIT_BIT)); \ + } while (0); + +#endif + +#ifdef TFM_SMALL_SET + #include "fp_sqr_comba_small_set.i" +#endif + +#if defined(TFM_SQR3) && FP_SIZE >= 6 + #include "fp_sqr_comba_3.i" +#endif +#if defined(TFM_SQR4) && FP_SIZE >= 8 + #include "fp_sqr_comba_4.i" +#endif +#if defined(TFM_SQR6) && FP_SIZE >= 12 + #include "fp_sqr_comba_6.i" +#endif +#if defined(TFM_SQR7) && FP_SIZE >= 14 + #include "fp_sqr_comba_7.i" +#endif +#if defined(TFM_SQR8) && FP_SIZE >= 16 + #include "fp_sqr_comba_8.i" +#endif +#if defined(TFM_SQR9) && FP_SIZE >= 18 + #include "fp_sqr_comba_9.i" +#endif +#if defined(TFM_SQR12) && FP_SIZE >= 24 + #include "fp_sqr_comba_12.i" +#endif +#if defined(TFM_SQR17) && FP_SIZE >= 34 + #include "fp_sqr_comba_17.i" +#endif +#if defined(TFM_SQR20) && FP_SIZE >= 40 + #include "fp_sqr_comba_20.i" +#endif +#if defined(TFM_SQR24) && FP_SIZE >= 48 + #include "fp_sqr_comba_24.i" +#endif +#if defined(TFM_SQR28) && FP_SIZE >= 56 + #include "fp_sqr_comba_28.i" +#endif +#if defined(TFM_SQR32) && FP_SIZE >= 64 + #include "fp_sqr_comba_32.i" +#endif +#if defined(TFM_SQR48) && FP_SIZE >= 96 + #include "fp_sqr_comba_48.i" +#endif +#if defined(TFM_SQR64) && FP_SIZE >= 128 + #include "fp_sqr_comba_64.i" +#endif +/* end fp_sqr_comba.c asm */ + +/* start fp_mul_comba.c asm */ +/* these are the combas. Worship them. */ +#if defined(TFM_X86) +/* Generic x86 optimized code */ + +/* anything you need at the start */ +#define COMBA_START + +/* clear the chaining variables */ +#define COMBA_CLEAR \ + c0 = c1 = c2 = 0; + +/* forward the carry to the next digit */ +#define COMBA_FORWARD \ + do { c0 = c1; c1 = c2; c2 = 0; } while (0); + +/* store the first sum */ +#define COMBA_STORE(x) \ + x = c0; + +/* store the second sum [carry] */ +#define COMBA_STORE2(x) \ + x = c1; + +/* anything you need at the end */ +#define COMBA_FINI + +/* this should multiply i and j */ +#define MULADD(i, j) \ +__asm__( \ + "movl %6,%%eax \n\t" \ + "mull %7 \n\t" \ + "addl %%eax,%0 \n\t" \ + "adcl %%edx,%1 \n\t" \ + "adcl $0,%2 \n\t" \ + :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i), "m"(j) :"%eax","%edx","cc"); + +#elif defined(TFM_X86_64) +/* x86-64 optimized */ + +/* anything you need at the start */ +#define COMBA_START + +/* clear the chaining variables */ +#define COMBA_CLEAR \ + c0 = c1 = c2 = 0; + +/* forward the carry to the next digit */ +#define COMBA_FORWARD \ + do { c0 = c1; c1 = c2; c2 = 0; } while (0); + +/* store the first sum */ +#define COMBA_STORE(x) \ + x = c0; + +/* store the second sum [carry] */ +#define COMBA_STORE2(x) \ + x = c1; + +/* anything you need at the end */ +#define COMBA_FINI + +/* this should multiply i and j */ +#define MULADD(i, j) \ +__asm__ ( \ + "movq %6,%%rax \n\t" \ + "mulq %7 \n\t" \ + "addq %%rax,%0 \n\t" \ + "adcq %%rdx,%1 \n\t" \ + "adcq $0,%2 \n\t" \ + :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "g"(i), "g"(j) :"%rax","%rdx","cc"); + + +#if defined(HAVE_INTEL_MULX) +#define MULADD_BODY(a,b,c) \ + __asm__ volatile( \ + "movq %[a0],%%rdx\n\t" \ + "xorq %%rcx, %%rcx\n\t" \ + "movq 0(%[cp]),%%r8\n\t" \ + "movq 8(%[cp]),%%r9\n\t" \ + "movq 16(%[cp]),%%r10\n\t" \ + "movq 24(%[cp]),%%r11\n\t" \ + "movq 32(%[cp]),%%r12\n\t" \ + "movq 40(%[cp]),%%r13\n\t" \ + \ + "mulx (%[bp]),%%rax, %%rbx\n\t" \ + "adoxq %%rax, %%r8\n\t" \ + "mulx 8(%[bp]),%%rax, %%rcx\n\t" \ + "adcxq %%rbx, %%r9\n\t" \ + "adoxq %%rax, %%r9\n\t" \ + "mulx 16(%[bp]),%%rax, %%rbx\n\t" \ + "adcxq %%rcx, %%r10\n\t" \ + "adoxq %%rax, %%r10\n\t" \ + "mulx 24(%[bp]),%%rax, %%rcx\n\t" \ + "adcxq %%rbx, %%r11\n\t" \ + "adoxq %%rax, %%r11\n\t" \ + "adcxq %%rcx, %%r12\n\t" \ + "mov $0, %%rdx\n\t" \ + "adox %%rdx, %%r12\n\t" \ + "adcx %%rdx, %%r13\n\t" \ + \ + "movq %%r8, 0(%[cp])\n\t" \ + "movq %%r9, 8(%[cp])\n\t" \ + "movq %%r10, 16(%[cp])\n\t" \ + "movq %%r11, 24(%[cp])\n\t" \ + "movq %%r12, 32(%[cp])\n\t" \ + "movq %%r13, 40(%[cp])\n\t" \ + : \ + : [a0] "r" (a->dp[ix]), [bp] "r" (&(b->dp[iy])), \ + [cp] "r" (&(c->dp[iz])) \ + : "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", \ + "%rdx", "%rax", "%rcx", "%rbx" \ + ) + +#define TFM_INTEL_MUL_COMBA(a, b, c) \ + for (iz=0; izdp[iz] = 0; \ + for (ix=0; ixused; ix++) { \ + for (iy=0; iyused; iy+=4) { \ + iz = ix + iy; \ + MULADD_BODY(a, b, c); \ + } \ + } +#endif + +#elif defined(TFM_SSE2) +/* use SSE2 optimizations */ + +/* anything you need at the start */ +#define COMBA_START + +/* clear the chaining variables */ +#define COMBA_CLEAR \ + c0 = c1 = c2 = 0; + +/* forward the carry to the next digit */ +#define COMBA_FORWARD \ + do { c0 = c1; c1 = c2; c2 = 0; } while (0); + +/* store the first sum */ +#define COMBA_STORE(x) \ + x = c0; + +/* store the second sum [carry] */ +#define COMBA_STORE2(x) \ + x = c1; + +/* anything you need at the end */ +#define COMBA_FINI \ + __asm__("emms"); + +/* this should multiply i and j */ +#define MULADD(i, j) \ +__asm__( \ + "movd %6,%%mm0 \n\t" \ + "movd %7,%%mm1 \n\t" \ + "pmuludq %%mm1,%%mm0\n\t" \ + "movd %%mm0,%%eax \n\t" \ + "psrlq $32,%%mm0 \n\t" \ + "addl %%eax,%0 \n\t" \ + "movd %%mm0,%%eax \n\t" \ + "adcl %%eax,%1 \n\t" \ + "adcl $0,%2 \n\t" \ + :"=r"(c0), "=r"(c1), "=r"(c2): "0"(c0), "1"(c1), "2"(c2), "m"(i), "m"(j) :"%eax","cc"); + +#elif defined(TFM_ARM) +/* ARM code */ + +#define COMBA_START + +#define COMBA_CLEAR \ + c0 = c1 = c2 = 0; + +#define COMBA_FORWARD \ + do { c0 = c1; c1 = c2; c2 = 0; } while (0); + +#define COMBA_STORE(x) \ + x = c0; + +#define COMBA_STORE2(x) \ + x = c1; + +#define COMBA_FINI + +#define MULADD(i, j) \ +__asm__( \ +" UMULL r0,r1,%6,%7 \n\t" \ +" ADDS %0,%0,r0 \n\t" \ +" ADCS %1,%1,r1 \n\t" \ +" ADC %2,%2,#0 \n\t" \ +:"=r"(c0), "=r"(c1), "=r"(c2) : "0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j) : "r0", "r1", "cc"); + +#elif defined(TFM_PPC32) +/* For 32-bit PPC */ + +#define COMBA_START + +#define COMBA_CLEAR \ + c0 = c1 = c2 = 0; + +#define COMBA_FORWARD \ + do { c0 = c1; c1 = c2; c2 = 0; } while (0); + +#define COMBA_STORE(x) \ + x = c0; + +#define COMBA_STORE2(x) \ + x = c1; + +#define COMBA_FINI + +/* untested: will mulhwu change the flags? Docs say no */ +#define MULADD(i, j) \ +__asm__( \ + " mullw 16,%6,%7 \n\t" \ + " addc %0,%0,16 \n\t" \ + " mulhwu 16,%6,%7 \n\t" \ + " adde %1,%1,16 \n\t" \ + " addze %2,%2 \n\t" \ +:"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j):"16"); + +#elif defined(TFM_PPC64) +/* For 64-bit PPC */ + +#define COMBA_START + +#define COMBA_CLEAR \ + c0 = c1 = c2 = 0; + +#define COMBA_FORWARD \ + do { c0 = c1; c1 = c2; c2 = 0; } while (0); + +#define COMBA_STORE(x) \ + x = c0; + +#define COMBA_STORE2(x) \ + x = c1; + +#define COMBA_FINI + +/* untested: will mulhdu change the flags? Docs say no */ +#define MULADD(i, j) \ +____asm__( \ + " mulld r16,%6,%7 \n\t" \ + " addc %0,%0,16 \n\t" \ + " mulhdu r16,%6,%7 \n\t" \ + " adde %1,%1,16 \n\t" \ + " addze %2,%2 \n\t" \ +:"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j):"r16"); + +#elif defined(TFM_AVR32) + +/* ISO C code */ + +#define COMBA_START + +#define COMBA_CLEAR \ + c0 = c1 = c2 = 0; + +#define COMBA_FORWARD \ + do { c0 = c1; c1 = c2; c2 = 0; } while (0); + +#define COMBA_STORE(x) \ + x = c0; + +#define COMBA_STORE2(x) \ + x = c1; + +#define COMBA_FINI + +#define MULADD(i, j) \ +____asm__( \ + " mulu.d r2,%6,%7 \n\t"\ + " add %0,r2 \n\t"\ + " adc %1,%1,r3 \n\t"\ + " acr %2 \n\t"\ +:"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j):"r2","r3"); + +#elif defined(TFM_MIPS) + +/* MIPS */ +#define COMBA_START + +#define COMBA_CLEAR \ + c0 = c1 = c2 = 0; + +#define COMBA_FORWARD \ + do { c0 = c1; c1 = c2; c2 = 0; } while (0); + +#define COMBA_STORE(x) \ + x = c0; + +#define COMBA_STORE2(x) \ + x = c1; + +#define COMBA_FINI + +#define MULADD(i, j) \ +__asm__( \ + " multu %6,%7 \n\t" \ + " mflo $12 \n\t" \ + " mfhi $13 \n\t" \ + " addu %0,%0,$12 \n\t" \ + " sltu $12,%0,$12 \n\t" \ + " addu %1,%1,$13 \n\t" \ + " sltu $13,%1,$13 \n\t" \ + " addu %1,%1,$12 \n\t" \ + " sltu $12,%1,$12 \n\t" \ + " addu %2,%2,$13 \n\t" \ + " addu %2,%2,$12 \n\t" \ +:"=r"(c0), "=r"(c1), "=r"(c2):"0"(c0), "1"(c1), "2"(c2), "r"(i), "r"(j):"$12","$13"); + +#else +/* ISO C code */ + +#define COMBA_START + +#define COMBA_CLEAR \ + c0 = c1 = c2 = 0; + +#define COMBA_FORWARD \ + do { c0 = c1; c1 = c2; c2 = 0; } while (0); + +#define COMBA_STORE(x) \ + x = c0; + +#define COMBA_STORE2(x) \ + x = c1; + +#define COMBA_FINI + +#define MULADD(i, j) \ + do { fp_word t; \ + t = (fp_word)c0 + ((fp_word)i) * ((fp_word)j); \ + c0 = (fp_digit)t; \ + t = (fp_word)c1 + (t >> DIGIT_BIT); \ + c1 = (fp_digit)t; \ + c2 += (fp_digit)(t >> DIGIT_BIT); \ + } while (0); + +#endif + + +#ifdef TFM_SMALL_SET + #include "fp_mul_comba_small_set.i" +#endif + +#if defined(TFM_MUL3) && FP_SIZE >= 6 + #include "fp_mul_comba_3.i" +#endif +#if defined(TFM_MUL4) && FP_SIZE >= 8 + #include "fp_mul_comba_4.i" +#endif +#if defined(TFM_MUL6) && FP_SIZE >= 12 + #include "fp_mul_comba_6.i" +#endif +#if defined(TFM_MUL7) && FP_SIZE >= 14 + #include "fp_mul_comba_7.i" +#endif +#if defined(TFM_MUL8) && FP_SIZE >= 16 + #include "fp_mul_comba_8.i" +#endif +#if defined(TFM_MUL9) && FP_SIZE >= 18 + #include "fp_mul_comba_9.i" +#endif +#if defined(TFM_MUL12) && FP_SIZE >= 24 + #include "fp_mul_comba_12.i" +#endif +#if defined(TFM_MUL17) && FP_SIZE >= 34 + #include "fp_mul_comba_17.i" +#endif +#if defined(TFM_MUL20) && FP_SIZE >= 40 + #include "fp_mul_comba_20.i" +#endif +#if defined(TFM_MUL24) && FP_SIZE >= 48 + #include "fp_mul_comba_24.i" +#endif +#if defined(TFM_MUL28) && FP_SIZE >= 56 + #include "fp_mul_comba_28.i" +#endif +#if defined(TFM_MUL32) && FP_SIZE >= 64 + #include "fp_mul_comba_32.i" +#endif +#if defined(TFM_MUL48) && FP_SIZE >= 96 + #include "fp_mul_comba_48.i" +#endif +#if defined(TFM_MUL64) && FP_SIZE >= 128 + #include "fp_mul_comba_64.i" +#endif + +/* end fp_mul_comba.c asm */ + diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/asn.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/asn.c new file mode 100755 index 0000000..e621c07 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/asn.c @@ -0,0 +1,15394 @@ +/* asn.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +/* +ASN Options: + * NO_ASN_TIME: Disables time parts of the ASN code for systems without an RTC + or wishing to save space. + * IGNORE_NAME_CONSTRAINTS: Skip ASN name checks. + * ASN_DUMP_OID: Allows dump of OID information for debugging. + * RSA_DECODE_EXTRA: Decodes extra information in RSA public key. + * WOLFSSL_CERT_GEN: Cert generation. Saves extra certificate info in GetName. + * WOLFSSL_NO_ASN_STRICT: Disable strict RFC compliance checks to + restore 3.13.0 behavior. + * WOLFSSL_NO_OCSP_OPTIONAL_CERTS: Skip optional OCSP certs (responder issuer + must still be trusted) + * WOLFSSL_NO_TRUSTED_CERTS_VERIFY: Workaround for situation where entire cert + chain is not loaded. This only matches on subject and public key and + does not perform a PKI validation, so it is not a secure solution. + Only enabled for OCSP. + * WOLFSSL_NO_OCSP_ISSUER_CHECK: Can be defined for backwards compatibility to + disable checking of OCSP subject hash with issuer hash. + * WOLFSSL_SMALL_CERT_VERIFY: Verify the certificate signature without using + DecodedCert. Doubles up on some code but allows smaller dynamic memory + usage. + * WOLFSSL_NO_OCSP_DATE_CHECK: Disable date checks for OCSP responses. This + may be required when the system's real-time clock is not very accurate. + It is recommended to enforce the nonce check instead if possible. + * WOLFSSL_FORCE_OCSP_NONCE_CHECK: Require nonces to be available in OCSP + responses. The nonces are optional and may not be supported by all + responders. If it can be ensured that the used responder sends nonces this + option may improve security. +*/ + +#ifndef NO_ASN + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#ifndef NO_PWDBASED + #include +#endif +#ifndef NO_RC4 + #include +#endif + +#ifdef HAVE_NTRU + #include "libntruencrypt/ntru_crypto.h" +#endif + +#if defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384) + #include +#endif + +#ifndef NO_SHA256 + #include +#endif + +#ifdef HAVE_ECC + #include +#endif + +#ifdef HAVE_ED25519 + #include +#endif + +#ifndef NO_RSA + #include +#if defined(WOLFSSL_XILINX_CRYPT) || defined(WOLFSSL_CRYPTOCELL) +extern int wc_InitRsaHw(RsaKey* key); +#endif +#endif + +#ifdef WOLF_CRYPTO_CB + #include +#endif + +#ifdef WOLFSSL_DEBUG_ENCODING + #if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) + #if MQX_USE_IO_OLD + #include + #else + #include + #endif + #else + #include + #endif +#endif + + +#ifdef _MSC_VER + /* 4996 warning to use MS extensions e.g., strcpy_s instead of XSTRNCPY */ + #pragma warning(disable: 4996) +#endif + +#define ERROR_OUT(err, eLabel) { ret = (err); goto eLabel; } + +#ifdef HAVE_SELFTEST + #ifndef WOLFSSL_AES_KEY_SIZE_ENUM + enum Asn_Misc { + AES_IV_SIZE = 16, + AES_128_KEY_SIZE = 16, + AES_192_KEY_SIZE = 24, + AES_256_KEY_SIZE = 32 + }; + #endif +#endif + +WOLFSSL_LOCAL int GetLength(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx) +{ + return GetLength_ex(input, inOutIdx, len, maxIdx, 1); +} + + +/* give option to check length value found against index. 1 to check 0 to not */ +WOLFSSL_LOCAL int GetLength_ex(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx, int check) +{ + int length = 0; + word32 idx = *inOutIdx; + byte b; + + *len = 0; /* default length */ + + if ((idx + 1) > maxIdx) { /* for first read */ + WOLFSSL_MSG("GetLength bad index on input"); + return BUFFER_E; + } + + b = input[idx++]; + if (b >= ASN_LONG_LENGTH) { + word32 bytes = b & 0x7F; + + if ((idx + bytes) > maxIdx) { /* for reading bytes */ + WOLFSSL_MSG("GetLength bad long length"); + return BUFFER_E; + } + + while (bytes--) { + b = input[idx++]; + length = (length << 8) | b; + } + } + else + length = b; + + if (check && (idx + length) > maxIdx) { /* for user of length */ + WOLFSSL_MSG("GetLength value exceeds buffer length"); + return BUFFER_E; + } + + *inOutIdx = idx; + if (length > 0) + *len = length; + + return length; +} + + +static int GetASNHeader_ex(const byte* input, byte tag, word32* inOutIdx, int* len, + word32 maxIdx, int check) +{ + word32 idx = *inOutIdx; + byte b; + int length; + + if ((idx + 1) > maxIdx) + return BUFFER_E; + + b = input[idx++]; + if (b != tag) + return ASN_PARSE_E; + + if (GetLength_ex(input, &idx, &length, maxIdx, check) < 0) + return ASN_PARSE_E; + + *len = length; + *inOutIdx = idx; + return length; +} + + +/* Get the DER/BER encoding of an ASN.1 header. + * + * input Buffer holding DER/BER encoded data. + * tag ASN.1 tag value expected in header. + * inOutIdx Current index into buffer to parse. + * len The number of bytes in the ASN.1 data. + * maxIdx Length of data in buffer. + * returns BUFFER_E when there is not enough data to parse. + * ASN_PARSE_E when the expected tag is not found or length is invalid. + * Otherwise, the number of bytes in the ASN.1 data. + */ +static int GetASNHeader(const byte* input, byte tag, word32* inOutIdx, int* len, + word32 maxIdx) +{ + return GetASNHeader_ex(input, tag, inOutIdx, len, maxIdx, 1); +} + +static int GetHeader(const byte* input, byte* tag, word32* inOutIdx, int* len, + word32 maxIdx, int check) +{ + word32 idx = *inOutIdx; + int length; + + if ((idx + 1) > maxIdx) + return BUFFER_E; + + *tag = input[idx++]; + + if (GetLength_ex(input, &idx, &length, maxIdx, check) < 0) + return ASN_PARSE_E; + + *len = length; + *inOutIdx = idx; + return length; +} + +WOLFSSL_LOCAL int GetSequence(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx) +{ + return GetASNHeader(input, ASN_SEQUENCE | ASN_CONSTRUCTED, inOutIdx, len, + maxIdx); +} + + +WOLFSSL_LOCAL int GetSequence_ex(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx, int check) +{ + return GetASNHeader_ex(input, ASN_SEQUENCE | ASN_CONSTRUCTED, inOutIdx, len, + maxIdx, check); +} + + +WOLFSSL_LOCAL int GetSet(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx) +{ + return GetASNHeader(input, ASN_SET | ASN_CONSTRUCTED, inOutIdx, len, + maxIdx); +} + + +WOLFSSL_LOCAL int GetSet_ex(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx, int check) +{ + return GetASNHeader_ex(input, ASN_SET | ASN_CONSTRUCTED, inOutIdx, len, + maxIdx, check); +} + +/* Get the DER/BER encoded ASN.1 NULL element. + * Ensure that the all fields are as expected and move index past the element. + * + * input Buffer holding DER/BER encoded data. + * inOutIdx Current index into buffer to parse. + * maxIdx Length of data in buffer. + * returns BUFFER_E when there is not enough data to parse. + * ASN_TAG_NULL_E when the NULL tag is not found. + * ASN_EXPECT_0_E when the length is not zero. + * Otherwise, 0 to indicate success. + */ +static int GetASNNull(const byte* input, word32* inOutIdx, word32 maxIdx) +{ + word32 idx = *inOutIdx; + byte b; + + if ((idx + 2) > maxIdx) + return BUFFER_E; + + b = input[idx++]; + if (b != ASN_TAG_NULL) + return ASN_TAG_NULL_E; + + if (input[idx++] != 0) + return ASN_EXPECT_0_E; + + *inOutIdx = idx; + return 0; +} + +/* Set the DER/BER encoding of the ASN.1 NULL element. + * + * output Buffer to write into. + * returns the number of bytes added to the buffer. + */ +static int SetASNNull(byte* output) +{ + output[0] = ASN_TAG_NULL; + output[1] = 0; + + return 2; +} + +/* Get the DER/BER encoding of an ASN.1 BOOLEAN. + * + * input Buffer holding DER/BER encoded data. + * inOutIdx Current index into buffer to parse. + * maxIdx Length of data in buffer. + * returns BUFFER_E when there is not enough data to parse. + * ASN_PARSE_E when the BOOLEAN tag is not found or length is not 1. + * Otherwise, 0 to indicate the value was false and 1 to indicate true. + */ +static int GetBoolean(const byte* input, word32* inOutIdx, word32 maxIdx) +{ + word32 idx = *inOutIdx; + byte b; + + if ((idx + 3) > maxIdx) + return BUFFER_E; + + b = input[idx++]; + if (b != ASN_BOOLEAN) + return ASN_PARSE_E; + + if (input[idx++] != 1) + return ASN_PARSE_E; + + b = input[idx++] != 0; + + *inOutIdx = idx; + return b; +} + +#ifdef ASN1_SET_BOOLEAN +/* Set the DER/BER encoding of the ASN.1 NULL element. + * Note: Function not required as yet. + * + * val Boolean value to encode. + * output Buffer to write into. + * returns the number of bytes added to the buffer. + */ +static int SetBoolean(int val, byte* output) +{ + output[0] = ASN_BOOLEAN; + output[1] = 1; + output[2] = val ? -1 : 0; + + return 3; +} +#endif + +/* Get the DER/BER encoding of an ASN.1 OCTET_STRING header. + * + * input Buffer holding DER/BER encoded data. + * inOutIdx Current index into buffer to parse. + * len The number of bytes in the ASN.1 data. + * maxIdx Length of data in buffer. + * returns BUFFER_E when there is not enough data to parse. + * ASN_PARSE_E when the OCTET_STRING tag is not found or length is + * invalid. + * Otherwise, the number of bytes in the ASN.1 data. + */ +static int GetOctetString(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx) +{ + return GetASNHeader(input, ASN_OCTET_STRING, inOutIdx, len, maxIdx); +} + +/* Get the DER/BER encoding of an ASN.1 INTEGER header. + * Removes the leading zero byte when found. + * + * input Buffer holding DER/BER encoded data. + * inOutIdx Current index into buffer to parse. + * len The number of bytes in the ASN.1 data (excluding any leading zero). + * maxIdx Length of data in buffer. + * returns BUFFER_E when there is not enough data to parse. + * ASN_PARSE_E when the INTEGER tag is not found, length is invalid, + * or invalid use of or missing leading zero. + * Otherwise, 0 to indicate success. + */ +static int GetASNInt(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx) +{ + int ret; + + ret = GetASNHeader(input, ASN_INTEGER, inOutIdx, len, maxIdx); + if (ret < 0) + return ret; + + if (*len > 0) { + /* remove leading zero, unless there is only one 0x00 byte */ + if ((input[*inOutIdx] == 0x00) && (*len > 1)) { + (*inOutIdx)++; + (*len)--; + + if (*len > 0 && (input[*inOutIdx] & 0x80) == 0) + return ASN_PARSE_E; + } + } + + return 0; +} + +/* Get the DER/BER encoding of an ASN.1 INTEGER that has a value of no more than + * 7 bits. + * + * input Buffer holding DER/BER encoded data. + * inOutIdx Current index into buffer to parse. + * maxIdx Length of data in buffer. + * returns BUFFER_E when there is not enough data to parse. + * ASN_PARSE_E when the INTEGER tag is not found or length is invalid. + * Otherwise, the 7-bit value. + */ +static int GetInteger7Bit(const byte* input, word32* inOutIdx, word32 maxIdx) +{ + word32 idx = *inOutIdx; + byte b; + + if ((idx + 3) > maxIdx) + return BUFFER_E; + + if (input[idx++] != ASN_INTEGER) + return ASN_PARSE_E; + if (input[idx++] != 1) + return ASN_PARSE_E; + b = input[idx++]; + + *inOutIdx = idx; + return b; +} + + +#if !defined(NO_DSA) && !defined(NO_SHA) +static char sigSha1wDsaName[] = "SHAwDSA"; +#endif /* NO_DSA */ +#ifndef NO_RSA +#ifdef WOLFSSL_MD2 + static char sigMd2wRsaName[] = "MD2wRSA"; +#endif +#ifndef NO_MD5 + static char sigMd5wRsaName[] = "MD5wRSA"; +#endif +#ifndef NO_SHA + static char sigSha1wRsaName[] = "SHAwRSA"; +#endif +#ifdef WOLFSSL_SHA224 + static char sigSha224wRsaName[] = "SHA224wRSA"; +#endif +#ifndef NO_SHA256 + static char sigSha256wRsaName[] = "SHA256wRSA"; +#endif +#ifdef WOLFSSL_SHA384 + static char sigSha384wRsaName[] = "SHA384wRSA"; +#endif +#ifdef WOLFSSL_SHA512 + static char sigSha512wRsaName[] = "SHA512wRSA"; +#endif +#endif /* NO_RSA */ +#ifdef HAVE_ECC +#ifndef NO_SHA + static char sigSha1wEcdsaName[] = "SHAwECDSA"; +#endif +#ifdef WOLFSSL_SHA224 + static char sigSha224wEcdsaName[] = "SHA224wECDSA"; +#endif +#ifndef NO_SHA256 + static char sigSha256wEcdsaName[] = "SHA256wECDSA"; +#endif +#ifdef WOLFSSL_SHA384 + static char sigSha384wEcdsaName[] = "SHA384wECDSA"; +#endif +#ifdef WOLFSSL_SHA512 + static char sigSha512wEcdsaName[] = "SHA512wECDSA"; +#endif +#endif /* HAVE_ECC */ +static char sigUnknownName[] = "Unknown"; + + +/* Get the human readable string for a signature type + * + * oid Oid value for signature + */ +char* GetSigName(int oid) { + switch (oid) { + #if !defined(NO_DSA) && !defined(NO_SHA) + case CTC_SHAwDSA: + return sigSha1wDsaName; + #endif /* NO_DSA && NO_SHA */ + #ifndef NO_RSA + #ifdef WOLFSSL_MD2 + case CTC_MD2wRSA: + return sigMd2wRsaName; + #endif + #ifndef NO_MD5 + case CTC_MD5wRSA: + return sigMd5wRsaName; + #endif + #ifndef NO_SHA + case CTC_SHAwRSA: + return sigSha1wRsaName; + #endif + #ifdef WOLFSSL_SHA224 + case CTC_SHA224wRSA: + return sigSha224wRsaName; + #endif + #ifndef NO_SHA256 + case CTC_SHA256wRSA: + return sigSha256wRsaName; + #endif + #ifdef WOLFSSL_SHA384 + case CTC_SHA384wRSA: + return sigSha384wRsaName; + #endif + #ifdef WOLFSSL_SHA512 + case CTC_SHA512wRSA: + return sigSha512wRsaName; + #endif + #endif /* NO_RSA */ + #ifdef HAVE_ECC + #ifndef NO_SHA + case CTC_SHAwECDSA: + return sigSha1wEcdsaName; + #endif + #ifdef WOLFSSL_SHA224 + case CTC_SHA224wECDSA: + return sigSha224wEcdsaName; + #endif + #ifndef NO_SHA256 + case CTC_SHA256wECDSA: + return sigSha256wEcdsaName; + #endif + #ifdef WOLFSSL_SHA384 + case CTC_SHA384wECDSA: + return sigSha384wEcdsaName; + #endif + #ifdef WOLFSSL_SHA512 + case CTC_SHA512wECDSA: + return sigSha512wEcdsaName; + #endif + #endif /* HAVE_ECC */ + default: + return sigUnknownName; + } +} + + +#if !defined(NO_DSA) || defined(HAVE_ECC) || \ + (!defined(NO_RSA) && \ + (defined(WOLFSSL_CERT_GEN) || \ + ((defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA)) && !defined(HAVE_USER_RSA)))) +/* Set the DER/BER encoding of the ASN.1 INTEGER header. + * + * len Length of data to encode. + * firstByte First byte of data, most significant byte of integer, to encode. + * output Buffer to write into. + * returns the number of bytes added to the buffer. + */ +static int SetASNInt(int len, byte firstByte, byte* output) +{ + word32 idx = 0; + + output[idx++] = ASN_INTEGER; + if (firstByte & 0x80) + len++; + idx += SetLength(len, output + idx); + if (firstByte & 0x80) + output[idx++] = 0x00; + + return idx; +} +#endif + +#if !defined(NO_DSA) || defined(HAVE_ECC) || defined(WOLFSSL_CERT_GEN) || \ + ((defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA)) && !defined(NO_RSA) && !defined(HAVE_USER_RSA)) +/* Set the DER/BER encoding of the ASN.1 INTEGER element with an mp_int. + * The number is assumed to be positive. + * + * n Multi-precision integer to encode. + * maxSz Maximum size of the encoded integer. + * A negative value indicates no check of length requested. + * output Buffer to write into. + * returns BUFFER_E when the data is too long for the buffer. + * MP_TO_E when encoding the integer fails. + * Otherwise, the number of bytes added to the buffer. + */ +static int SetASNIntMP(mp_int* n, int maxSz, byte* output) +{ + int idx = 0; + int leadingBit; + int length; + int err; + + leadingBit = mp_leading_bit(n); + length = mp_unsigned_bin_size(n); + idx = SetASNInt(length, leadingBit ? 0x80 : 0x00, output); + if (maxSz >= 0 && (idx + length) > maxSz) + return BUFFER_E; + + err = mp_to_unsigned_bin(n, output + idx); + if (err != MP_OKAY) + return MP_TO_E; + idx += length; + + return idx; +} +#endif + +#if !defined(NO_RSA) && defined(HAVE_USER_RSA) && defined(WOLFSSL_CERT_GEN) +/* Set the DER/BER encoding of the ASN.1 INTEGER element with an mp_int from + * an RSA key. + * The number is assumed to be positive. + * + * n Multi-precision integer to encode. + * output Buffer to write into. + * returns BUFFER_E when the data is too long for the buffer. + * MP_TO_E when encoding the integer fails. + * Otherwise, the number of bytes added to the buffer. + */ +static int SetASNIntRSA(mp_int* n, byte* output) +{ + int idx = 0; + int leadingBit; + int length; + int err; + + leadingBit = wc_Rsa_leading_bit(n); + length = wc_Rsa_unsigned_bin_size(n); + idx = SetASNInt(length, leadingBit ? 0x80 : 0x00, output); + if ((idx + length) > MAX_RSA_INT_SZ) + return BUFFER_E; + + err = wc_Rsa_to_unsigned_bin(n, output + idx, length); + if (err != MP_OKAY) + return MP_TO_E; + idx += length; + + return idx; +} +#endif /* !NO_RSA && HAVE_USER_RSA && WOLFSSL_CERT_GEN */ + +/* Windows header clash for WinCE using GetVersion */ +WOLFSSL_LOCAL int GetMyVersion(const byte* input, word32* inOutIdx, + int* version, word32 maxIdx) +{ + word32 idx = *inOutIdx; + + if ((idx + MIN_VERSION_SZ) > maxIdx) + return ASN_PARSE_E; + + if (input[idx++] != ASN_INTEGER) + return ASN_PARSE_E; + + if (input[idx++] != 0x01) + return ASN_VERSION_E; + + *version = input[idx++]; + *inOutIdx = idx; + + return *version; +} + + +#ifndef NO_PWDBASED +/* Get small count integer, 32 bits or less */ +int GetShortInt(const byte* input, word32* inOutIdx, int* number, word32 maxIdx) +{ + word32 idx = *inOutIdx; + word32 len; + + *number = 0; + + /* check for type and length bytes */ + if ((idx + 2) > maxIdx) + return BUFFER_E; + + if (input[idx++] != ASN_INTEGER) + return ASN_PARSE_E; + + len = input[idx++]; + if (len > 4) + return ASN_PARSE_E; + + if (len + idx > maxIdx) + return ASN_PARSE_E; + + while (len--) { + *number = *number << 8 | input[idx++]; + } + + *inOutIdx = idx; + + return *number; +} + + +/* Set small integer, 32 bits or less. DER encoding with no leading 0s + * returns total amount written including ASN tag and length byte on success */ +static int SetShortInt(byte* input, word32* inOutIdx, word32 number, + word32 maxIdx) +{ + word32 idx = *inOutIdx; + word32 len = 0; + int i; + byte ar[MAX_LENGTH_SZ]; + + /* check for room for type and length bytes */ + if ((idx + 2) > maxIdx) + return BUFFER_E; + + input[idx++] = ASN_INTEGER; + idx++; /* place holder for length byte */ + if (MAX_LENGTH_SZ + idx > maxIdx) + return ASN_PARSE_E; + + /* find first non zero byte */ + XMEMSET(ar, 0, MAX_LENGTH_SZ); + c32toa(number, ar); + for (i = 0; i < MAX_LENGTH_SZ; i++) { + if (ar[i] != 0) { + break; + } + } + + /* handle case of 0 */ + if (i == MAX_LENGTH_SZ) { + input[idx++] = 0; len++; + } + + for (; i < MAX_LENGTH_SZ && idx < maxIdx; i++) { + input[idx++] = ar[i]; len++; + } + + /* jump back to beginning of input buffer using unaltered inOutIdx value + * and set number of bytes for integer, then update the index value */ + input[*inOutIdx + 1] = (byte)len; + *inOutIdx = idx; + + return len + 2; /* size of integer bytes plus ASN TAG and length byte */ +} +#endif /* !NO_PWDBASED */ + +/* May not have one, not an error */ +static int GetExplicitVersion(const byte* input, word32* inOutIdx, int* version, + word32 maxIdx) +{ + word32 idx = *inOutIdx; + + WOLFSSL_ENTER("GetExplicitVersion"); + + if ((idx + 1) > maxIdx) + return BUFFER_E; + + if (input[idx++] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) { + *inOutIdx = ++idx; /* skip header */ + return GetMyVersion(input, inOutIdx, version, maxIdx); + } + + /* go back as is */ + *version = 0; + + return 0; +} + +int GetInt(mp_int* mpi, const byte* input, word32* inOutIdx, word32 maxIdx) +{ + word32 idx = *inOutIdx; + int ret; + int length; + + ret = GetASNInt(input, &idx, &length, maxIdx); + if (ret != 0) + return ret; + + if (mp_init(mpi) != MP_OKAY) + return MP_INIT_E; + + if (mp_read_unsigned_bin(mpi, (byte*)input + idx, length) != 0) { + mp_clear(mpi); + return ASN_GETINT_E; + } + +#ifdef HAVE_WOLF_BIGINT + if (wc_bigint_from_unsigned_bin(&mpi->raw, input + idx, length) != 0) { + mp_clear(mpi); + return ASN_GETINT_E; + } +#endif /* HAVE_WOLF_BIGINT */ + + *inOutIdx = idx + length; + + return 0; +} + +#if (!defined(WOLFSSL_KEY_GEN) && !defined(OPENSSL_EXTRA) && defined(RSA_LOW_MEM)) \ + || defined(WOLFSSL_RSA_PUBLIC_ONLY) +#if !defined(NO_RSA) && !defined(HAVE_USER_RSA) +static int SkipInt(const byte* input, word32* inOutIdx, word32 maxIdx) +{ + word32 idx = *inOutIdx; + int ret; + int length; + + ret = GetASNInt(input, &idx, &length, maxIdx); + if (ret != 0) + return ret; + + *inOutIdx = idx + length; + + return 0; +} +#endif +#endif + +static int CheckBitString(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx, int zeroBits, byte* unusedBits) +{ + word32 idx = *inOutIdx; + int length; + byte b; + + if ((idx + 1) > maxIdx) + return BUFFER_E; + + if (input[idx++] != ASN_BIT_STRING) + return ASN_BITSTR_E; + + if (GetLength(input, &idx, &length, maxIdx) < 0) + return ASN_PARSE_E; + + /* extra sanity check that length is greater than 0 */ + if (length <= 0) { + WOLFSSL_MSG("Error length was 0 in CheckBitString"); + return BUFFER_E; + } + + if (idx + 1 > maxIdx) { + WOLFSSL_MSG("Attempted buffer read larger than input buffer"); + return BUFFER_E; + } + + b = input[idx]; + if (zeroBits && b != 0x00) + return ASN_EXPECT_0_E; + if (b >= 0x08) + return ASN_PARSE_E; + if (b != 0) { + if ((byte)(input[idx + length - 1] << (8 - b)) != 0) + return ASN_PARSE_E; + } + idx++; + length--; /* length has been checked for greater than 0 */ + + *inOutIdx = idx; + if (len != NULL) + *len = length; + if (unusedBits != NULL) + *unusedBits = b; + + return 0; +} + +/* RSA (with CertGen or KeyGen) OR ECC OR ED25519 (with CertGen or KeyGen) */ +#if (!defined(NO_RSA) && !defined(HAVE_USER_RSA) && \ + (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA))) || \ + (defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT)) || \ + (defined(HAVE_ED25519) && \ + (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA))) + +/* Set the DER/BER encoding of the ASN.1 BIT_STRING header. + * + * len Length of data to encode. + * unusedBits The number of unused bits in the last byte of data. + * That is, the number of least significant zero bits before a one. + * The last byte is the most-significant non-zero byte of a number. + * output Buffer to write into. + * returns the number of bytes added to the buffer. + */ +static word32 SetBitString(word32 len, byte unusedBits, byte* output) +{ + word32 idx = 0; + + output[idx++] = ASN_BIT_STRING; + idx += SetLength(len + 1, output + idx); + output[idx++] = unusedBits; + + return idx; +} +#endif /* !NO_RSA || HAVE_ECC || HAVE_ED25519 */ + +#ifdef ASN_BER_TO_DER +/* Convert a BER encoding with indefinite length items to DER. + * + * ber BER encoded data. + * berSz Length of BER encoded data. + * der Buffer to hold DER encoded version of data. + * NULL indicates only the length is required. + * derSz The size of the buffer to hold the DER encoded data. + * Will be set if der is NULL, otherwise the value is checked as der is + * filled. + * returns ASN_PARSE_E if the BER data is invalid and BAD_FUNC_ARG if ber or + * derSz are NULL. + */ +int wc_BerToDer(const byte* ber, word32 berSz, byte* der, word32* derSz) +{ + int ret; + word32 i, j, k; + int len, l; + int indef; + int depth = 0; + byte type; + word32 cnt, sz; + word32 outSz = 0; + byte lenBytes[4]; + + if (ber == NULL || derSz == NULL) + return BAD_FUNC_ARG; + + sz = 0; + outSz = *derSz; + + for (i = 0, j = 0; i < berSz; ) { + /* Check that there is data for an ASN item to parse. */ + if (i + 2 > berSz) + return ASN_PARSE_E; + + /* End Of Content (EOC) mark end of indefinite length items. + * EOCs are not encoded in DER. + * Keep track of no. indefinite length items that have not been + * terminated in depth. + */ + if (ber[i] == 0 && ber[i+1] == 0) { + if (depth == 0) + break; + if (--depth == 0) + break; + + i += 2; + continue; + } + + /* Indefinite length is encoded as: 0x80 */ + type = ber[i]; + indef = ber[i+1] == ASN_INDEF_LENGTH; + if (indef && (type & 0xC0) == 0 && + ber[i] != (ASN_SEQUENCE | ASN_CONSTRUCTED) && + ber[i] != (ASN_SET | ASN_CONSTRUCTED)) { + /* Indefinite length OCTET STRING or other simple type. + * Put all the data into one entry. + */ + + /* Type no longer constructed. */ + type &= ~ASN_CONSTRUCTED; + if (der != NULL) { + /* Ensure space for type. */ + if (j + 1 >= outSz) + return BUFFER_E; + der[j] = type; + } + i++; j++; + /* Skip indefinite length. */ + i++; + + /* There must be further ASN1 items to combine. */ + if (i + 2 > berSz) + return ASN_PARSE_E; + + /* Calculate length of combined data. */ + len = 0; + k = i; + while (ber[k] != 0x00) { + /* Each ASN item must be the same type as the constructed. */ + if (ber[k] != type) + return ASN_PARSE_E; + k++; + + ret = GetLength(ber, &k, &l, berSz); + if (ret < 0) + return ASN_PARSE_E; + k += l; + len += l; + + /* Must at least have terminating EOC. */ + if (k + 2 > berSz) + return ASN_PARSE_E; + } + /* Ensure a valid EOC ASN item. */ + if (ber[k+1] != 0x00) + return ASN_PARSE_E; + + if (der == NULL) { + /* Add length of ASN item length encoding and data. */ + j += SetLength(len, lenBytes); + j += len; + } + else { + /* Check space for encoded length. */ + if (SetLength(len, lenBytes) > outSz - j) + return BUFFER_E; + /* Encode new length. */ + j += SetLength(len, der + j); + + /* Encode data in single item. */ + k = i; + while (ber[k] != 0x00) { + /* Skip ASN type. */ + k++; + + /* Find length of data in ASN item. */ + ret = GetLength(ber, &k, &l, berSz); + if (ret < 0) + return ASN_PARSE_E; + + /* Ensure space for data and copy in. */ + if (j + l > outSz) + return BUFFER_E; + XMEMCPY(der + j, ber + k, l); + k += l; j += l; + } + } + /* Continue conversion after EOC. */ + i = k + 2; + + continue; + } + + if (der != NULL) { + /* Ensure space for type and at least one byte of length. */ + if (j + 1 >= outSz) + return BUFFER_E; + /* Put in type. */ + der[j] = ber[i]; + } + i++; j++; + + if (indef) { + /* Skip indefinite length. */ + i++; + /* Calculate the size of the data inside constructed. */ + ret = wc_BerToDer(ber + i, berSz - i, NULL, &sz); + if (ret != LENGTH_ONLY_E) + return ret; + + if (der != NULL) { + /* Ensure space for encoded length. */ + if (SetLength(sz, lenBytes) > outSz - j) + return BUFFER_E; + /* Encode real length. */ + j += SetLength(sz, der + j); + } + else { + /* Add size of encoded length. */ + j += SetLength(sz, lenBytes); + } + + /* Another EOC to find. */ + depth++; + } + else { + /* Get the size of the encode length and length value. */ + cnt = i; + ret = GetLength(ber, &cnt, &len, berSz); + if (ret < 0) + return ASN_PARSE_E; + cnt -= i; + + /* Check there is enough data to copy out. */ + if (i + cnt + len > berSz) + return ASN_PARSE_E; + + if (der != NULL) { + /* Ensure space in DER buffer. */ + if (j + cnt + len > outSz) + return BUFFER_E; + /* Copy length and data into DER buffer. */ + XMEMCPY(der + j, ber + i, cnt + len); + } + /* Continue conversion after this ASN item. */ + i += cnt + len; + j += cnt + len; + } + } + + if (depth >= 1) + return ASN_PARSE_E; + + /* Return length if no buffer to write to. */ + if (der == NULL) { + *derSz = j; + return LENGTH_ONLY_E; + } + + return 0; +} +#endif + +#if defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN) + +#if (!defined(NO_RSA) && !defined(HAVE_USER_RSA)) || \ + defined(HAVE_ECC) || defined(HAVE_ED25519) + +#ifdef WOLFSSL_CERT_EXT +/* Set the DER/BER encoding of the ASN.1 BIT_STRING with a 16-bit value. + * + * val 16-bit value to encode. + * output Buffer to write into. + * returns the number of bytes added to the buffer. + */ +static word32 SetBitString16Bit(word16 val, byte* output) +{ + word32 idx; + int len; + byte lastByte; + byte unusedBits = 0; + + if ((val >> 8) != 0) { + len = 2; + lastByte = (byte)(val >> 8); + } + else { + len = 1; + lastByte = (byte)val; + } + + while (((lastByte >> unusedBits) & 0x01) == 0x00) + unusedBits++; + + idx = SetBitString(len, unusedBits, output); + output[idx++] = (byte)val; + if (len > 1) + output[idx++] = (byte)(val >> 8); + + return idx; +} +#endif /* WOLFSSL_CERT_EXT */ +#endif /* !NO_RSA || HAVE_ECC || HAVE_ED25519 */ +#endif /* WOLFSSL_CERT_GEN || WOLFSSL_KEY_GEN */ + + + +/* hashType */ +#ifdef WOLFSSL_MD2 + static const byte hashMd2hOid[] = {42, 134, 72, 134, 247, 13, 2, 2}; +#endif +#ifndef NO_MD5 + static const byte hashMd5hOid[] = {42, 134, 72, 134, 247, 13, 2, 5}; +#endif +#ifndef NO_SHA + static const byte hashSha1hOid[] = {43, 14, 3, 2, 26}; +#endif +#ifdef WOLFSSL_SHA224 + static const byte hashSha224hOid[] = {96, 134, 72, 1, 101, 3, 4, 2, 4}; +#endif +#ifndef NO_SHA256 + static const byte hashSha256hOid[] = {96, 134, 72, 1, 101, 3, 4, 2, 1}; +#endif +#ifdef WOLFSSL_SHA384 + static const byte hashSha384hOid[] = {96, 134, 72, 1, 101, 3, 4, 2, 2}; +#endif +#ifdef WOLFSSL_SHA512 + static const byte hashSha512hOid[] = {96, 134, 72, 1, 101, 3, 4, 2, 3}; +#endif + +/* hmacType */ +#ifndef NO_HMAC + #ifdef WOLFSSL_SHA224 + static const byte hmacSha224Oid[] = {42, 134, 72, 134, 247, 13, 2, 8}; + #endif + #ifndef NO_SHA256 + static const byte hmacSha256Oid[] = {42, 134, 72, 134, 247, 13, 2, 9}; + #endif + #ifdef WOLFSSL_SHA384 + static const byte hmacSha384Oid[] = {42, 134, 72, 134, 247, 13, 2, 10}; + #endif + #ifdef WOLFSSL_SHA512 + static const byte hmacSha512Oid[] = {42, 134, 72, 134, 247, 13, 2, 11}; + #endif +#endif + +/* sigType */ +#if !defined(NO_DSA) && !defined(NO_SHA) + static const byte sigSha1wDsaOid[] = {42, 134, 72, 206, 56, 4, 3}; +#endif /* NO_DSA */ +#ifndef NO_RSA + #ifdef WOLFSSL_MD2 + static const byte sigMd2wRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1, 2}; + #endif + #ifndef NO_MD5 + static const byte sigMd5wRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1, 4}; + #endif + #ifndef NO_SHA + static const byte sigSha1wRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1, 5}; + #endif + #ifdef WOLFSSL_SHA224 + static const byte sigSha224wRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1,14}; + #endif + #ifndef NO_SHA256 + static const byte sigSha256wRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1,11}; + #endif + #ifdef WOLFSSL_SHA384 + static const byte sigSha384wRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1,12}; + #endif + #ifdef WOLFSSL_SHA512 + static const byte sigSha512wRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1,13}; + #endif +#endif /* NO_RSA */ +#ifdef HAVE_ECC + #ifndef NO_SHA + static const byte sigSha1wEcdsaOid[] = {42, 134, 72, 206, 61, 4, 1}; + #endif + #ifdef WOLFSSL_SHA224 + static const byte sigSha224wEcdsaOid[] = {42, 134, 72, 206, 61, 4, 3, 1}; + #endif + #ifndef NO_SHA256 + static const byte sigSha256wEcdsaOid[] = {42, 134, 72, 206, 61, 4, 3, 2}; + #endif + #ifdef WOLFSSL_SHA384 + static const byte sigSha384wEcdsaOid[] = {42, 134, 72, 206, 61, 4, 3, 3}; + #endif + #ifdef WOLFSSL_SHA512 + static const byte sigSha512wEcdsaOid[] = {42, 134, 72, 206, 61, 4, 3, 4}; + #endif +#endif /* HAVE_ECC */ +#ifdef HAVE_ED25519 + static const byte sigEd25519Oid[] = {43, 101, 112}; +#endif /* HAVE_ED25519 */ + +/* keyType */ +#ifndef NO_DSA + static const byte keyDsaOid[] = {42, 134, 72, 206, 56, 4, 1}; +#endif /* NO_DSA */ +#ifndef NO_RSA + static const byte keyRsaOid[] = {42, 134, 72, 134, 247, 13, 1, 1, 1}; +#endif /* NO_RSA */ +#ifdef HAVE_NTRU + static const byte keyNtruOid[] = {43, 6, 1, 4, 1, 193, 22, 1, 1, 1, 1}; +#endif /* HAVE_NTRU */ +#ifdef HAVE_ECC + static const byte keyEcdsaOid[] = {42, 134, 72, 206, 61, 2, 1}; +#endif /* HAVE_ECC */ +#ifdef HAVE_ED25519 + static const byte keyEd25519Oid[] = {43, 101, 112}; +#endif /* HAVE_ED25519 */ + +/* curveType */ +#ifdef HAVE_ECC + /* See "ecc_sets" table in ecc.c */ +#endif /* HAVE_ECC */ + +#ifdef HAVE_AES_CBC +/* blkType */ + #ifdef WOLFSSL_AES_128 + static const byte blkAes128CbcOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 2}; + #endif + #ifdef WOLFSSL_AES_192 + static const byte blkAes192CbcOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 22}; + #endif + #ifdef WOLFSSL_AES_256 + static const byte blkAes256CbcOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 42}; + #endif +#endif /* HAVE_AES_CBC */ +#ifdef HAVE_AESGCM + #ifdef WOLFSSL_AES_128 + static const byte blkAes128GcmOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 6}; + #endif + #ifdef WOLFSSL_AES_192 + static const byte blkAes192GcmOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 26}; + #endif + #ifdef WOLFSSL_AES_256 + static const byte blkAes256GcmOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 46}; + #endif +#endif /* HAVE_AESGCM */ +#ifdef HAVE_AESCCM + #ifdef WOLFSSL_AES_128 + static const byte blkAes128CcmOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 7}; + #endif + #ifdef WOLFSSL_AES_192 + static const byte blkAes192CcmOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 27}; + #endif + #ifdef WOLFSSL_AES_256 + static const byte blkAes256CcmOid[] = {96, 134, 72, 1, 101, 3, 4, 1, 47}; + #endif +#endif /* HAVE_AESCCM */ + +#ifndef NO_DES3 + static const byte blkDesCbcOid[] = {43, 14, 3, 2, 7}; + static const byte blkDes3CbcOid[] = {42, 134, 72, 134, 247, 13, 3, 7}; +#endif + +/* keyWrapType */ +#ifdef WOLFSSL_AES_128 + static const byte wrapAes128Oid[] = {96, 134, 72, 1, 101, 3, 4, 1, 5}; +#endif +#ifdef WOLFSSL_AES_192 + static const byte wrapAes192Oid[] = {96, 134, 72, 1, 101, 3, 4, 1, 25}; +#endif +#ifdef WOLFSSL_AES_256 + static const byte wrapAes256Oid[] = {96, 134, 72, 1, 101, 3, 4, 1, 45}; +#endif +#ifdef HAVE_PKCS7 +/* From RFC 3211 */ +static const byte wrapPwriKekOid[] = {42, 134, 72, 134, 247, 13, 1, 9, 16, 3,9}; +#endif + +/* cmsKeyAgreeType */ +#ifndef NO_SHA + static const byte dhSinglePass_stdDH_sha1kdf_Oid[] = + {43, 129, 5, 16, 134, 72, 63, 0, 2}; +#endif +#ifdef WOLFSSL_SHA224 + static const byte dhSinglePass_stdDH_sha224kdf_Oid[] = {43, 129, 4, 1, 11, 0}; +#endif +#ifndef NO_SHA256 + static const byte dhSinglePass_stdDH_sha256kdf_Oid[] = {43, 129, 4, 1, 11, 1}; +#endif +#ifdef WOLFSSL_SHA384 + static const byte dhSinglePass_stdDH_sha384kdf_Oid[] = {43, 129, 4, 1, 11, 2}; +#endif +#ifdef WOLFSSL_SHA512 + static const byte dhSinglePass_stdDH_sha512kdf_Oid[] = {43, 129, 4, 1, 11, 3}; +#endif + +/* ocspType */ +#ifdef HAVE_OCSP + static const byte ocspBasicOid[] = {43, 6, 1, 5, 5, 7, 48, 1, 1}; + static const byte ocspNonceOid[] = {43, 6, 1, 5, 5, 7, 48, 1, 2}; +#endif /* HAVE_OCSP */ + +/* certExtType */ +static const byte extBasicCaOid[] = {85, 29, 19}; +static const byte extAltNamesOid[] = {85, 29, 17}; +static const byte extCrlDistOid[] = {85, 29, 31}; +static const byte extAuthInfoOid[] = {43, 6, 1, 5, 5, 7, 1, 1}; +static const byte extAuthKeyOid[] = {85, 29, 35}; +static const byte extSubjKeyOid[] = {85, 29, 14}; +static const byte extCertPolicyOid[] = {85, 29, 32}; +static const byte extKeyUsageOid[] = {85, 29, 15}; +static const byte extInhibitAnyOid[] = {85, 29, 54}; +static const byte extExtKeyUsageOid[] = {85, 29, 37}; +#ifndef IGNORE_NAME_CONSTRAINTS + static const byte extNameConsOid[] = {85, 29, 30}; +#endif + +/* certAuthInfoType */ +#ifdef HAVE_OCSP + static const byte extAuthInfoOcspOid[] = {43, 6, 1, 5, 5, 7, 48, 1}; +#endif +static const byte extAuthInfoCaIssuerOid[] = {43, 6, 1, 5, 5, 7, 48, 2}; + +/* certPolicyType */ +static const byte extCertPolicyAnyOid[] = {85, 29, 32, 0}; + +/* certKeyUseType */ +static const byte extAltNamesHwNameOid[] = {43, 6, 1, 5, 5, 7, 8, 4}; + +/* certKeyUseType */ +static const byte extExtKeyUsageAnyOid[] = {85, 29, 37, 0}; +static const byte extExtKeyUsageServerAuthOid[] = {43, 6, 1, 5, 5, 7, 3, 1}; +static const byte extExtKeyUsageClientAuthOid[] = {43, 6, 1, 5, 5, 7, 3, 2}; +static const byte extExtKeyUsageCodeSigningOid[] = {43, 6, 1, 5, 5, 7, 3, 3}; +static const byte extExtKeyUsageEmailProtectOid[] = {43, 6, 1, 5, 5, 7, 3, 4}; +static const byte extExtKeyUsageTimestampOid[] = {43, 6, 1, 5, 5, 7, 3, 8}; +static const byte extExtKeyUsageOcspSignOid[] = {43, 6, 1, 5, 5, 7, 3, 9}; + +/* kdfType */ +static const byte pbkdf2Oid[] = {42, 134, 72, 134, 247, 13, 1, 5, 12}; + +/* PKCS5 */ +#if !defined(NO_DES3) && !defined(NO_SHA) +static const byte pbeSha1Des[] = {42, 134, 72, 134, 247, 13, 1, 5, 10}; +#endif +static const byte pbes2[] = {42, 134, 72, 134, 247, 13, 1, 5, 13}; + +/* PKCS12 */ +#if !defined(NO_RC4) && !defined(NO_SHA) +static const byte pbeSha1RC4128[] = {42, 134, 72, 134, 247, 13, 1, 12, 1, 1}; +#endif +#if !defined(NO_DES3) && !defined(NO_SHA) +static const byte pbeSha1Des3[] = {42, 134, 72, 134, 247, 13, 1, 12, 1, 3}; +#endif + +#ifdef HAVE_LIBZ +/* zlib compression */ +static const byte zlibCompress[] = {42, 134, 72, 134, 247, 13, 1, 9, 16, 3, 8}; +#endif + + +/* returns a pointer to the OID string on success and NULL on fail */ +const byte* OidFromId(word32 id, word32 type, word32* oidSz) +{ + const byte* oid = NULL; + + *oidSz = 0; + + switch (type) { + + case oidHashType: + switch (id) { + #ifdef WOLFSSL_MD2 + case MD2h: + oid = hashMd2hOid; + *oidSz = sizeof(hashMd2hOid); + break; + #endif + #ifndef NO_MD5 + case MD5h: + oid = hashMd5hOid; + *oidSz = sizeof(hashMd5hOid); + break; + #endif + #ifndef NO_SHA + case SHAh: + oid = hashSha1hOid; + *oidSz = sizeof(hashSha1hOid); + break; + #endif + #ifdef WOLFSSL_SHA224 + case SHA224h: + oid = hashSha224hOid; + *oidSz = sizeof(hashSha224hOid); + break; + #endif + #ifndef NO_SHA256 + case SHA256h: + oid = hashSha256hOid; + *oidSz = sizeof(hashSha256hOid); + break; + #endif + #ifdef WOLFSSL_SHA384 + case SHA384h: + oid = hashSha384hOid; + *oidSz = sizeof(hashSha384hOid); + break; + #endif + #ifdef WOLFSSL_SHA512 + case SHA512h: + oid = hashSha512hOid; + *oidSz = sizeof(hashSha512hOid); + break; + #endif + } + break; + + case oidSigType: + switch (id) { + #if !defined(NO_DSA) && !defined(NO_SHA) + case CTC_SHAwDSA: + oid = sigSha1wDsaOid; + *oidSz = sizeof(sigSha1wDsaOid); + break; + #endif /* NO_DSA */ + #ifndef NO_RSA + #ifdef WOLFSSL_MD2 + case CTC_MD2wRSA: + oid = sigMd2wRsaOid; + *oidSz = sizeof(sigMd2wRsaOid); + break; + #endif + #ifndef NO_MD5 + case CTC_MD5wRSA: + oid = sigMd5wRsaOid; + *oidSz = sizeof(sigMd5wRsaOid); + break; + #endif + #ifndef NO_SHA + case CTC_SHAwRSA: + oid = sigSha1wRsaOid; + *oidSz = sizeof(sigSha1wRsaOid); + break; + #endif + #ifdef WOLFSSL_SHA224 + case CTC_SHA224wRSA: + oid = sigSha224wRsaOid; + *oidSz = sizeof(sigSha224wRsaOid); + break; + #endif + #ifndef NO_SHA256 + case CTC_SHA256wRSA: + oid = sigSha256wRsaOid; + *oidSz = sizeof(sigSha256wRsaOid); + break; + #endif + #ifdef WOLFSSL_SHA384 + case CTC_SHA384wRSA: + oid = sigSha384wRsaOid; + *oidSz = sizeof(sigSha384wRsaOid); + break; + #endif + #ifdef WOLFSSL_SHA512 + case CTC_SHA512wRSA: + oid = sigSha512wRsaOid; + *oidSz = sizeof(sigSha512wRsaOid); + break; + #endif /* WOLFSSL_SHA512 */ + #endif /* NO_RSA */ + #ifdef HAVE_ECC + #ifndef NO_SHA + case CTC_SHAwECDSA: + oid = sigSha1wEcdsaOid; + *oidSz = sizeof(sigSha1wEcdsaOid); + break; + #endif + #ifdef WOLFSSL_SHA224 + case CTC_SHA224wECDSA: + oid = sigSha224wEcdsaOid; + *oidSz = sizeof(sigSha224wEcdsaOid); + break; + #endif + #ifndef NO_SHA256 + case CTC_SHA256wECDSA: + oid = sigSha256wEcdsaOid; + *oidSz = sizeof(sigSha256wEcdsaOid); + break; + #endif + #ifdef WOLFSSL_SHA384 + case CTC_SHA384wECDSA: + oid = sigSha384wEcdsaOid; + *oidSz = sizeof(sigSha384wEcdsaOid); + break; + #endif + #ifdef WOLFSSL_SHA512 + case CTC_SHA512wECDSA: + oid = sigSha512wEcdsaOid; + *oidSz = sizeof(sigSha512wEcdsaOid); + break; + #endif + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case CTC_ED25519: + oid = sigEd25519Oid; + *oidSz = sizeof(sigEd25519Oid); + break; + #endif + default: + break; + } + break; + + case oidKeyType: + switch (id) { + #ifndef NO_DSA + case DSAk: + oid = keyDsaOid; + *oidSz = sizeof(keyDsaOid); + break; + #endif /* NO_DSA */ + #ifndef NO_RSA + case RSAk: + oid = keyRsaOid; + *oidSz = sizeof(keyRsaOid); + break; + #endif /* NO_RSA */ + #ifdef HAVE_NTRU + case NTRUk: + oid = keyNtruOid; + *oidSz = sizeof(keyNtruOid); + break; + #endif /* HAVE_NTRU */ + #ifdef HAVE_ECC + case ECDSAk: + oid = keyEcdsaOid; + *oidSz = sizeof(keyEcdsaOid); + break; + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ED25519k: + oid = keyEd25519Oid; + *oidSz = sizeof(keyEd25519Oid); + break; + #endif /* HAVE_ED25519 */ + default: + break; + } + break; + + #ifdef HAVE_ECC + case oidCurveType: + if (wc_ecc_get_oid(id, &oid, oidSz) < 0) { + WOLFSSL_MSG("ECC OID not found"); + } + break; + #endif /* HAVE_ECC */ + + case oidBlkType: + switch (id) { + #ifdef HAVE_AES_CBC + #ifdef WOLFSSL_AES_128 + case AES128CBCb: + oid = blkAes128CbcOid; + *oidSz = sizeof(blkAes128CbcOid); + break; + #endif + #ifdef WOLFSSL_AES_192 + case AES192CBCb: + oid = blkAes192CbcOid; + *oidSz = sizeof(blkAes192CbcOid); + break; + #endif + #ifdef WOLFSSL_AES_256 + case AES256CBCb: + oid = blkAes256CbcOid; + *oidSz = sizeof(blkAes256CbcOid); + break; + #endif + #endif /* HAVE_AES_CBC */ + #ifdef HAVE_AESGCM + #ifdef WOLFSSL_AES_128 + case AES128GCMb: + oid = blkAes128GcmOid; + *oidSz = sizeof(blkAes128GcmOid); + break; + #endif + #ifdef WOLFSSL_AES_192 + case AES192GCMb: + oid = blkAes192GcmOid; + *oidSz = sizeof(blkAes192GcmOid); + break; + #endif + #ifdef WOLFSSL_AES_256 + case AES256GCMb: + oid = blkAes256GcmOid; + *oidSz = sizeof(blkAes256GcmOid); + break; + #endif + #endif /* HAVE_AESGCM */ + #ifdef HAVE_AESCCM + #ifdef WOLFSSL_AES_128 + case AES128CCMb: + oid = blkAes128CcmOid; + *oidSz = sizeof(blkAes128CcmOid); + break; + #endif + #ifdef WOLFSSL_AES_192 + case AES192CCMb: + oid = blkAes192CcmOid; + *oidSz = sizeof(blkAes192CcmOid); + break; + #endif + #ifdef WOLFSSL_AES_256 + case AES256CCMb: + oid = blkAes256CcmOid; + *oidSz = sizeof(blkAes256CcmOid); + break; + #endif + #endif /* HAVE_AESCCM */ + #ifndef NO_DES3 + case DESb: + oid = blkDesCbcOid; + *oidSz = sizeof(blkDesCbcOid); + break; + case DES3b: + oid = blkDes3CbcOid; + *oidSz = sizeof(blkDes3CbcOid); + break; + #endif /* !NO_DES3 */ + } + break; + + #ifdef HAVE_OCSP + case oidOcspType: + switch (id) { + case OCSP_BASIC_OID: + oid = ocspBasicOid; + *oidSz = sizeof(ocspBasicOid); + break; + case OCSP_NONCE_OID: + oid = ocspNonceOid; + *oidSz = sizeof(ocspNonceOid); + break; + } + break; + #endif /* HAVE_OCSP */ + + case oidCertExtType: + switch (id) { + case BASIC_CA_OID: + oid = extBasicCaOid; + *oidSz = sizeof(extBasicCaOid); + break; + case ALT_NAMES_OID: + oid = extAltNamesOid; + *oidSz = sizeof(extAltNamesOid); + break; + case CRL_DIST_OID: + oid = extCrlDistOid; + *oidSz = sizeof(extCrlDistOid); + break; + case AUTH_INFO_OID: + oid = extAuthInfoOid; + *oidSz = sizeof(extAuthInfoOid); + break; + case AUTH_KEY_OID: + oid = extAuthKeyOid; + *oidSz = sizeof(extAuthKeyOid); + break; + case SUBJ_KEY_OID: + oid = extSubjKeyOid; + *oidSz = sizeof(extSubjKeyOid); + break; + case CERT_POLICY_OID: + oid = extCertPolicyOid; + *oidSz = sizeof(extCertPolicyOid); + break; + case KEY_USAGE_OID: + oid = extKeyUsageOid; + *oidSz = sizeof(extKeyUsageOid); + break; + case INHIBIT_ANY_OID: + oid = extInhibitAnyOid; + *oidSz = sizeof(extInhibitAnyOid); + break; + case EXT_KEY_USAGE_OID: + oid = extExtKeyUsageOid; + *oidSz = sizeof(extExtKeyUsageOid); + break; + #ifndef IGNORE_NAME_CONSTRAINTS + case NAME_CONS_OID: + oid = extNameConsOid; + *oidSz = sizeof(extNameConsOid); + break; + #endif + } + break; + + case oidCertAuthInfoType: + switch (id) { + #ifdef HAVE_OCSP + case AIA_OCSP_OID: + oid = extAuthInfoOcspOid; + *oidSz = sizeof(extAuthInfoOcspOid); + break; + #endif + case AIA_CA_ISSUER_OID: + oid = extAuthInfoCaIssuerOid; + *oidSz = sizeof(extAuthInfoCaIssuerOid); + break; + } + break; + + case oidCertPolicyType: + switch (id) { + case CP_ANY_OID: + oid = extCertPolicyAnyOid; + *oidSz = sizeof(extCertPolicyAnyOid); + break; + } + break; + + case oidCertAltNameType: + switch (id) { + case HW_NAME_OID: + oid = extAltNamesHwNameOid; + *oidSz = sizeof(extAltNamesHwNameOid); + break; + } + break; + + case oidCertKeyUseType: + switch (id) { + case EKU_ANY_OID: + oid = extExtKeyUsageAnyOid; + *oidSz = sizeof(extExtKeyUsageAnyOid); + break; + case EKU_SERVER_AUTH_OID: + oid = extExtKeyUsageServerAuthOid; + *oidSz = sizeof(extExtKeyUsageServerAuthOid); + break; + case EKU_CLIENT_AUTH_OID: + oid = extExtKeyUsageClientAuthOid; + *oidSz = sizeof(extExtKeyUsageClientAuthOid); + break; + case EKU_CODESIGNING_OID: + oid = extExtKeyUsageCodeSigningOid; + *oidSz = sizeof(extExtKeyUsageCodeSigningOid); + break; + case EKU_EMAILPROTECT_OID: + oid = extExtKeyUsageEmailProtectOid; + *oidSz = sizeof(extExtKeyUsageEmailProtectOid); + break; + case EKU_TIMESTAMP_OID: + oid = extExtKeyUsageTimestampOid; + *oidSz = sizeof(extExtKeyUsageTimestampOid); + break; + case EKU_OCSP_SIGN_OID: + oid = extExtKeyUsageOcspSignOid; + *oidSz = sizeof(extExtKeyUsageOcspSignOid); + break; + } + break; + + case oidKdfType: + switch (id) { + case PBKDF2_OID: + oid = pbkdf2Oid; + *oidSz = sizeof(pbkdf2Oid); + break; + } + break; + + case oidPBEType: + switch (id) { + #if !defined(NO_SHA) && !defined(NO_RC4) + case PBE_SHA1_RC4_128: + oid = pbeSha1RC4128; + *oidSz = sizeof(pbeSha1RC4128); + break; + #endif + #if !defined(NO_SHA) && !defined(NO_DES3) + case PBE_SHA1_DES: + oid = pbeSha1Des; + *oidSz = sizeof(pbeSha1Des); + break; + + #endif + #if !defined(NO_SHA) && !defined(NO_DES3) + case PBE_SHA1_DES3: + oid = pbeSha1Des3; + *oidSz = sizeof(pbeSha1Des3); + break; + #endif + case PBES2: + oid = pbes2; + *oidSz = sizeof(pbes2); + break; + } + break; + + case oidKeyWrapType: + switch (id) { + #ifdef WOLFSSL_AES_128 + case AES128_WRAP: + oid = wrapAes128Oid; + *oidSz = sizeof(wrapAes128Oid); + break; + #endif + #ifdef WOLFSSL_AES_192 + case AES192_WRAP: + oid = wrapAes192Oid; + *oidSz = sizeof(wrapAes192Oid); + break; + #endif + #ifdef WOLFSSL_AES_256 + case AES256_WRAP: + oid = wrapAes256Oid; + *oidSz = sizeof(wrapAes256Oid); + break; + #endif + #ifdef HAVE_PKCS7 + case PWRI_KEK_WRAP: + oid = wrapPwriKekOid; + *oidSz = sizeof(wrapPwriKekOid); + break; + #endif + } + break; + + case oidCmsKeyAgreeType: + switch (id) { + #ifndef NO_SHA + case dhSinglePass_stdDH_sha1kdf_scheme: + oid = dhSinglePass_stdDH_sha1kdf_Oid; + *oidSz = sizeof(dhSinglePass_stdDH_sha1kdf_Oid); + break; + #endif + #ifdef WOLFSSL_SHA224 + case dhSinglePass_stdDH_sha224kdf_scheme: + oid = dhSinglePass_stdDH_sha224kdf_Oid; + *oidSz = sizeof(dhSinglePass_stdDH_sha224kdf_Oid); + break; + #endif + #ifndef NO_SHA256 + case dhSinglePass_stdDH_sha256kdf_scheme: + oid = dhSinglePass_stdDH_sha256kdf_Oid; + *oidSz = sizeof(dhSinglePass_stdDH_sha256kdf_Oid); + break; + #endif + #ifdef WOLFSSL_SHA384 + case dhSinglePass_stdDH_sha384kdf_scheme: + oid = dhSinglePass_stdDH_sha384kdf_Oid; + *oidSz = sizeof(dhSinglePass_stdDH_sha384kdf_Oid); + break; + #endif + #ifdef WOLFSSL_SHA512 + case dhSinglePass_stdDH_sha512kdf_scheme: + oid = dhSinglePass_stdDH_sha512kdf_Oid; + *oidSz = sizeof(dhSinglePass_stdDH_sha512kdf_Oid); + break; + #endif + } + break; + +#ifndef NO_HMAC + case oidHmacType: + switch (id) { + #ifdef WOLFSSL_SHA224 + case HMAC_SHA224_OID: + oid = hmacSha224Oid; + *oidSz = sizeof(hmacSha224Oid); + break; + #endif + #ifndef NO_SHA256 + case HMAC_SHA256_OID: + oid = hmacSha256Oid; + *oidSz = sizeof(hmacSha256Oid); + break; + #endif + #ifdef WOLFSSL_SHA384 + case HMAC_SHA384_OID: + oid = hmacSha384Oid; + *oidSz = sizeof(hmacSha384Oid); + break; + #endif + #ifdef WOLFSSL_SHA512 + case HMAC_SHA512_OID: + oid = hmacSha512Oid; + *oidSz = sizeof(hmacSha512Oid); + break; + #endif + } + break; +#endif /* !NO_HMAC */ + +#ifdef HAVE_LIBZ + case oidCompressType: + switch (id) { + case ZLIBc: + oid = zlibCompress; + *oidSz = sizeof(zlibCompress); + break; + } + break; +#endif /* HAVE_LIBZ */ + + case oidIgnoreType: + default: + break; + } + + return oid; +} + +#ifdef HAVE_OID_ENCODING +int EncodeObjectId(const word16* in, word32 inSz, byte* out, word32* outSz) +{ + int i, x, len; + word32 d, t; + + /* check args */ + if (in == NULL || outSz == NULL) { + return BAD_FUNC_ARG; + } + + /* compute length of encoded OID */ + d = (in[0] * 40) + in[1]; + len = 0; + for (i = 1; i < (int)inSz; i++) { + x = 0; + t = d; + while (t) { + x++; + t >>= 1; + } + len += (x / 7) + ((x % 7) ? 1 : 0) + (d == 0 ? 1 : 0); + + if (i < (int)inSz - 1) { + d = in[i + 1]; + } + } + + if (out) { + /* verify length */ + if ((int)*outSz < len) { + return BUFFER_E; /* buffer provided is not large enough */ + } + + /* calc first byte */ + d = (in[0] * 40) + in[1]; + + /* encode bytes */ + x = 0; + for (i = 1; i < (int)inSz; i++) { + if (d) { + int y = x, z; + byte mask = 0; + while (d) { + out[x++] = (byte)((d & 0x7F) | mask); + d >>= 7; + mask |= 0x80; /* upper bit is set on all but the last byte */ + } + /* now swap bytes y...x-1 */ + z = x - 1; + while (y < z) { + mask = out[y]; + out[y] = out[z]; + out[z] = mask; + ++y; + --z; + } + } + else { + out[x++] = 0x00; /* zero value */ + } + + /* next word */ + if (i < (int)inSz - 1) { + d = in[i + 1]; + } + } + } + + /* return length */ + *outSz = len; + + return 0; +} +#endif /* HAVE_OID_ENCODING */ + +#ifdef HAVE_OID_DECODING +int DecodeObjectId(const byte* in, word32 inSz, word16* out, word32* outSz) +{ + int x = 0, y = 0; + word32 t = 0; + + /* check args */ + if (in == NULL || outSz == NULL) { + return BAD_FUNC_ARG; + } + + /* decode bytes */ + while (inSz--) { + t = (t << 7) | (in[x] & 0x7F); + if (!(in[x] & 0x80)) { + if (y >= (int)*outSz) { + return BUFFER_E; + } + if (y == 0) { + out[0] = (t / 40); + out[1] = (t % 40); + y = 2; + } + else { + out[y++] = t; + } + t = 0; /* reset tmp */ + } + x++; + } + + /* return length */ + *outSz = y; + + return 0; +} +#endif /* HAVE_OID_DECODING */ + +/* Get the DER/BER encoding of an ASN.1 OBJECT_ID header. + * + * input Buffer holding DER/BER encoded data. + * inOutIdx Current index into buffer to parse. + * len The number of bytes in the ASN.1 data. + * maxIdx Length of data in buffer. + * returns BUFFER_E when there is not enough data to parse. + * ASN_OBJECt_ID_E when the OBJECT_ID tag is not found. + * ASN_PARSE_E when length is invalid. + * Otherwise, 0 to indicate success. + */ +int GetASNObjectId(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx) +{ + word32 idx = *inOutIdx; + byte b; + int length; + + if ((idx + 1) > maxIdx) + return BUFFER_E; + + b = input[idx++]; + if (b != ASN_OBJECT_ID) + return ASN_OBJECT_ID_E; + + if (GetLength(input, &idx, &length, maxIdx) < 0) + return ASN_PARSE_E; + + *len = length; + *inOutIdx = idx; + return 0; +} + +/* Set the DER/BER encoding of the ASN.1 OBJECT_ID header. + * + * len Length of the OBJECT_ID data. + * output Buffer to write into. + * returns the number of bytes added to the buffer. + */ +int SetObjectId(int len, byte* output) +{ + int idx = 0; + + output[idx++] = ASN_OBJECT_ID; + idx += SetLength(len, output + idx); + + return idx; +} + +int GetObjectId(const byte* input, word32* inOutIdx, word32* oid, + word32 oidType, word32 maxIdx) +{ + int ret = 0, length; + word32 idx = *inOutIdx; +#ifndef NO_VERIFY_OID + word32 actualOidSz = 0; + const byte* actualOid; +#endif /* NO_VERIFY_OID */ + + (void)oidType; + WOLFSSL_ENTER("GetObjectId()"); + *oid = 0; + + ret = GetASNObjectId(input, &idx, &length, maxIdx); + if (ret != 0) + return ret; + +#ifndef NO_VERIFY_OID + actualOid = &input[idx]; + if (length > 0) + actualOidSz = (word32)length; +#endif /* NO_VERIFY_OID */ + + while (length--) { + /* odd HC08 compiler behavior here when input[idx++] */ + *oid += (word32)input[idx]; + idx++; + } + /* just sum it up for now */ + + *inOutIdx = idx; + +#ifndef NO_VERIFY_OID + { + const byte* checkOid = NULL; + word32 checkOidSz; + #ifdef ASN_DUMP_OID + word32 i; + #endif + + if (oidType != oidIgnoreType) { + checkOid = OidFromId(*oid, oidType, &checkOidSz); + + #ifdef ASN_DUMP_OID + /* support for dumping OID information */ + printf("OID (Type %d, Sz %d, Sum %d): ", oidType, actualOidSz, *oid); + for (i=0; itype = RSA_PRIVATE; + + if (GetInt(&key->n, input, inOutIdx, inSz) < 0 || + GetInt(&key->e, input, inOutIdx, inSz) < 0 || +#ifndef WOLFSSL_RSA_PUBLIC_ONLY + GetInt(&key->d, input, inOutIdx, inSz) < 0 || + GetInt(&key->p, input, inOutIdx, inSz) < 0 || + GetInt(&key->q, input, inOutIdx, inSz) < 0) +#else + SkipInt(input, inOutIdx, inSz) < 0 || + SkipInt(input, inOutIdx, inSz) < 0 || + SkipInt(input, inOutIdx, inSz) < 0 ) + +#endif + return ASN_RSA_KEY_E; +#if (defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || !defined(RSA_LOW_MEM)) \ + && !defined(WOLFSSL_RSA_PUBLIC_ONLY) + if (GetInt(&key->dP, input, inOutIdx, inSz) < 0 || + GetInt(&key->dQ, input, inOutIdx, inSz) < 0 || + GetInt(&key->u, input, inOutIdx, inSz) < 0 ) return ASN_RSA_KEY_E; +#else + if (SkipInt(input, inOutIdx, inSz) < 0 || + SkipInt(input, inOutIdx, inSz) < 0 || + SkipInt(input, inOutIdx, inSz) < 0 ) return ASN_RSA_KEY_E; +#endif + +#if defined(WOLFSSL_XILINX_CRYPT) || defined(WOLFSSL_CRYPTOCELL) + if (wc_InitRsaHw(key) != 0) { + return BAD_STATE_E; + } +#endif + + return 0; +} +#endif /* HAVE_USER_RSA */ +#endif /* NO_RSA */ + +#ifdef HAVE_PKCS8 + +/* Remove PKCS8 header, place inOutIdx at beginning of traditional, + * return traditional length on success, negative on error */ +int ToTraditionalInline_ex(const byte* input, word32* inOutIdx, word32 sz, + word32* algId) +{ + word32 idx; + int version, length; + int ret; + + if (input == NULL || inOutIdx == NULL) + return BAD_FUNC_ARG; + + idx = *inOutIdx; + + if (GetSequence(input, &idx, &length, sz) < 0) + return ASN_PARSE_E; + + if (GetMyVersion(input, &idx, &version, sz) < 0) + return ASN_PARSE_E; + + if (GetAlgoId(input, &idx, algId, oidKeyType, sz) < 0) + return ASN_PARSE_E; + + if (input[idx] == ASN_OBJECT_ID) { + if (SkipObjectId(input, &idx, sz) < 0) + return ASN_PARSE_E; + } + + ret = GetOctetString(input, &idx, &length, sz); + if (ret < 0) + return ret; + + *inOutIdx = idx; + + return length; +} + +int ToTraditionalInline(const byte* input, word32* inOutIdx, word32 sz) +{ + word32 oid; + + return ToTraditionalInline_ex(input, inOutIdx, sz, &oid); +} + +/* Remove PKCS8 header, move beginning of traditional to beginning of input */ +int ToTraditional_ex(byte* input, word32 sz, word32* algId) +{ + word32 inOutIdx = 0; + int length; + + if (input == NULL) + return BAD_FUNC_ARG; + + length = ToTraditionalInline_ex(input, &inOutIdx, sz, algId); + if (length < 0) + return length; + + XMEMMOVE(input, input + inOutIdx, length); + + return length; +} + +int ToTraditional(byte* input, word32 sz) +{ + word32 oid; + + return ToTraditional_ex(input, sz, &oid); +} + +/* find beginning of traditional key inside PKCS#8 unencrypted buffer + * return traditional length on success, with inOutIdx at beginning of + * traditional + * return negative on failure/error */ +int wc_GetPkcs8TraditionalOffset(byte* input, word32* inOutIdx, word32 sz) +{ + int length; + word32 algId; + + if (input == NULL || inOutIdx == NULL || (*inOutIdx > sz)) + return BAD_FUNC_ARG; + + length = ToTraditionalInline_ex(input, inOutIdx, sz, &algId); + + return length; +} + + +/* PKCS#8 from RFC 5208 + * This function takes in a DER key and converts it to PKCS#8 format. Used + * in creating PKCS#12 shrouded key bags. + * Reverse of ToTraditional + * + * PrivateKeyInfo ::= SEQUENCE { + * version Version, + * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, + * privateKey PrivateKey, + * attributes optional + * } + * Version ::= INTEGER + * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier + * PrivateKey ::= OCTET STRING + * + * out buffer to place result in + * outSz size of out buffer + * key buffer with DER key + * keySz size of key buffer + * algoID algorithm ID i.e. RSAk + * curveOID ECC curve oid if used. Should be NULL for RSA keys. + * oidSz size of curve oid. Is set to 0 if curveOID is NULL. + * + * Returns the size of PKCS#8 placed into out. In error cases returns negative + * values. + */ +int wc_CreatePKCS8Key(byte* out, word32* outSz, byte* key, word32 keySz, + int algoID, const byte* curveOID, word32 oidSz) +{ + word32 keyIdx = 0; + word32 tmpSz = 0; + word32 sz; + + + /* If out is NULL then return the max size needed + * + 2 for ASN_OBJECT_ID and ASN_OCTET_STRING tags */ + if (out == NULL && outSz != NULL) { + *outSz = keySz + MAX_SEQ_SZ + MAX_VERSION_SZ + MAX_ALGO_SZ + + MAX_LENGTH_SZ + MAX_LENGTH_SZ + 2; + + if (curveOID != NULL) + *outSz += oidSz + MAX_LENGTH_SZ + 1; + + WOLFSSL_MSG("Checking size of PKCS8"); + + return LENGTH_ONLY_E; + } + + WOLFSSL_ENTER("wc_CreatePKCS8Key()"); + + if (key == NULL || out == NULL || outSz == NULL) { + return BAD_FUNC_ARG; + } + + /* check the buffer has enough room for largest possible size */ + if (curveOID != NULL) { + if (*outSz < (keySz + MAX_SEQ_SZ + MAX_VERSION_SZ + MAX_ALGO_SZ + + MAX_LENGTH_SZ + MAX_LENGTH_SZ + 3 + oidSz + MAX_LENGTH_SZ)) + return BUFFER_E; + } + else { + oidSz = 0; /* with no curveOID oid size must be 0 */ + if (*outSz < (keySz + MAX_SEQ_SZ + MAX_VERSION_SZ + MAX_ALGO_SZ + + MAX_LENGTH_SZ + MAX_LENGTH_SZ + 2)) + return BUFFER_E; + } + + /* PrivateKeyInfo ::= SEQUENCE */ + keyIdx += MAX_SEQ_SZ; /* save room for sequence */ + + /* version Version + * no header information just INTEGER */ + sz = SetMyVersion(PKCS8v0, out + keyIdx, 0); + tmpSz += sz; keyIdx += sz; + + /* privateKeyAlgorithm PrivateKeyAlgorithmIdentifier */ + sz = 0; /* set sz to 0 and get privateKey oid buffer size needed */ + if (curveOID != NULL && oidSz > 0) { + byte buf[MAX_LENGTH_SZ]; + sz = SetLength(oidSz, buf); + sz += 1; /* plus one for ASN object id */ + } + sz = SetAlgoID(algoID, out + keyIdx, oidKeyType, oidSz + sz); + tmpSz += sz; keyIdx += sz; + + /* privateKey PrivateKey * + * pkcs8 ecc uses slightly different format. Places curve oid in + * buffer */ + if (curveOID != NULL && oidSz > 0) { + sz = SetObjectId(oidSz, out + keyIdx); + keyIdx += sz; tmpSz += sz; + XMEMCPY(out + keyIdx, curveOID, oidSz); + keyIdx += oidSz; tmpSz += oidSz; + } + + sz = SetOctetString(keySz, out + keyIdx); + keyIdx += sz; tmpSz += sz; + XMEMCPY(out + keyIdx, key, keySz); + tmpSz += keySz; + + /* attributes optional + * No attributes currently added */ + + /* rewind and add sequence */ + sz = SetSequence(tmpSz, out); + XMEMMOVE(out + sz, out + MAX_SEQ_SZ, tmpSz); + + return tmpSz + sz; +} + +#endif /* HAVE_PKCS8 */ + +#ifdef HAVE_PKCS12 +/* check that the private key is a pair for the public key in certificate + * return 1 (true) on match + * return 0 or negative value on failure/error + * + * key : buffer holding DER fromat key + * keySz : size of key buffer + * der : a initialized and parsed DecodedCert holding a certificate */ +int wc_CheckPrivateKey(byte* key, word32 keySz, DecodedCert* der) +{ + int ret; + (void)keySz; + + if (key == NULL || der == NULL) { + return BAD_FUNC_ARG; + } + + #if !defined(NO_RSA) && !defined(NO_ASN_CRYPT) + /* test if RSA key */ + if (der->keyOID == RSAk) { + #ifdef WOLFSSL_SMALL_STACK + RsaKey* a = NULL; + RsaKey* b = NULL; + #else + RsaKey a[1], b[1]; + #endif + word32 keyIdx = 0; + + #ifdef WOLFSSL_SMALL_STACK + a = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_RSA); + if (a == NULL) + return MEMORY_E; + b = (RsaKey*)XMALLOC(sizeof(RsaKey), NULL, DYNAMIC_TYPE_RSA); + if (b == NULL) { + XFREE(a, NULL, DYNAMIC_TYPE_RSA); + return MEMORY_E; + } + #endif + + if ((ret = wc_InitRsaKey(a, NULL)) < 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_RSA); + XFREE(a, NULL, DYNAMIC_TYPE_RSA); + #endif + return ret; + } + if ((ret = wc_InitRsaKey(b, NULL)) < 0) { + wc_FreeRsaKey(a); + #ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_RSA); + XFREE(a, NULL, DYNAMIC_TYPE_RSA); + #endif + return ret; + } + if ((ret = wc_RsaPrivateKeyDecode(key, &keyIdx, a, keySz)) == 0) { + WOLFSSL_MSG("Checking RSA key pair"); + keyIdx = 0; /* reset to 0 for parsing public key */ + + if ((ret = wc_RsaPublicKeyDecode(der->publicKey, &keyIdx, b, + der->pubKeySize)) == 0) { + /* limit for user RSA crypto because of RsaKey + * dereference. */ + #if defined(HAVE_USER_RSA) + WOLFSSL_MSG("Cannot verify RSA pair with user RSA"); + ret = 1; /* return first RSA cert as match */ + #else + /* both keys extracted successfully now check n and e + * values are the same. This is dereferencing RsaKey */ + if (mp_cmp(&(a->n), &(b->n)) != MP_EQ || + mp_cmp(&(a->e), &(b->e)) != MP_EQ) { + ret = MP_CMP_E; + } + else + ret = 1; + #endif + } + } + wc_FreeRsaKey(b); + wc_FreeRsaKey(a); + #ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_RSA); + XFREE(a, NULL, DYNAMIC_TYPE_RSA); + #endif + } + else + #endif /* !NO_RSA && !NO_ASN_CRYPT */ + + #if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT) && !defined(NO_ASN_CRYPT) + if (der->keyOID == ECDSAk) { + #ifdef WOLFSSL_SMALL_STACK + ecc_key* key_pair = NULL; + byte* privDer; + #else + ecc_key key_pair[1]; + byte privDer[MAX_ECC_BYTES]; + #endif + word32 privSz = MAX_ECC_BYTES; + word32 keyIdx = 0; + + #ifdef WOLFSSL_SMALL_STACK + key_pair = (ecc_key*)XMALLOC(sizeof(ecc_key), NULL, DYNAMIC_TYPE_ECC); + if (key_pair == NULL) + return MEMORY_E; + privDer = (byte*)XMALLOC(MAX_ECC_BYTES, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (privDer == NULL) { + XFREE(key_pair, NULL, DYNAMIC_TYPE_ECC); + return MEMORY_E; + } + #endif + + if ((ret = wc_ecc_init(key_pair)) < 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(privDer, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key_pair, NULL, DYNAMIC_TYPE_ECC); + #endif + return ret; + } + + if ((ret = wc_EccPrivateKeyDecode(key, &keyIdx, key_pair, + keySz)) == 0) { + WOLFSSL_MSG("Checking ECC key pair"); + + if ((ret = wc_ecc_export_private_only(key_pair, privDer, &privSz)) + == 0) { + wc_ecc_free(key_pair); + ret = wc_ecc_init(key_pair); + if (ret == 0) { + ret = wc_ecc_import_private_key((const byte*)privDer, + privSz, (const byte*)der->publicKey, + der->pubKeySize, key_pair); + } + + /* public and private extracted successfuly now check if is + * a pair and also do sanity checks on key. wc_ecc_check_key + * checks that private * base generator equals pubkey */ + if (ret == 0) { + if ((ret = wc_ecc_check_key(key_pair)) == 0) { + ret = 1; + } + } + ForceZero(privDer, privSz); + } + } + wc_ecc_free(key_pair); + #ifdef WOLFSSL_SMALL_STACK + XFREE(privDer, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key_pair, NULL, DYNAMIC_TYPE_ECC); + #endif + } + else + #endif /* HAVE_ECC && HAVE_ECC_KEY_EXPORT && !NO_ASN_CRYPT */ + + #if defined(HAVE_ED25519) && !defined(NO_ASN_CRYPT) + if (der->keyOID == ED25519k) { + #ifdef WOLFSSL_SMALL_STACK + ed25519_key* key_pair = NULL; + #else + ed25519_key key_pair[1]; + #endif + word32 keyIdx = 0; + + #ifdef WOLFSSL_SMALL_STACK + key_pair = (ed25519_key*)XMALLOC(sizeof(ed25519_key), NULL, + DYNAMIC_TYPE_ED25519); + if (key_pair == NULL) + return MEMORY_E; + #endif + + if ((ret = wc_ed25519_init(key_pair)) < 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(key_pair, NULL, DYNAMIC_TYPE_ED25519); + #endif + return ret; + } + if ((ret = wc_Ed25519PrivateKeyDecode(key, &keyIdx, key_pair, + keySz)) == 0) { + WOLFSSL_MSG("Checking ED25519 key pair"); + keyIdx = 0; + if ((ret = wc_ed25519_import_public(der->publicKey, der->pubKeySize, + key_pair)) == 0) { + /* public and private extracted successfuly no check if is + * a pair and also do sanity checks on key. wc_ecc_check_key + * checks that private * base generator equals pubkey */ + if ((ret = wc_ed25519_check_key(key_pair)) == 0) + ret = 1; + } + } + wc_ed25519_free(key_pair); + #ifdef WOLFSSL_SMALL_STACK + XFREE(key_pair, NULL, DYNAMIC_TYPE_ED25519); + #endif + } + else + #endif /* HAVE_ED25519 && !NO_ASN_CRYPT */ + { + ret = 0; + } + + (void)keySz; + + return ret; +} + +#endif /* HAVE_PKCS12 */ + +#ifndef NO_PWDBASED + +#ifdef HAVE_PKCS8 +/* Check To see if PKCS version algo is supported, set id if it is return 0 + < 0 on error */ +static int CheckAlgo(int first, int second, int* id, int* version, int* blockSz) +{ + *id = ALGO_ID_E; + *version = PKCS5; /* default */ + if (blockSz) *blockSz = 8; /* default */ + + if (first == 1) { + switch (second) { +#if !defined(NO_SHA) + #ifndef NO_RC4 + case PBE_SHA1_RC4_128: + *id = PBE_SHA1_RC4_128; + *version = PKCS12v1; + return 0; + #endif + #ifndef NO_DES3 + case PBE_SHA1_DES3: + *id = PBE_SHA1_DES3; + *version = PKCS12v1; + if (blockSz) *blockSz = DES_BLOCK_SIZE; + return 0; + #endif +#endif /* !NO_SHA */ + default: + return ALGO_ID_E; + } + } + + if (first != PKCS5) + return ASN_INPUT_E; /* VERSION ERROR */ + + if (second == PBES2) { + *version = PKCS5v2; + return 0; + } + + switch (second) { +#ifndef NO_DES3 + #ifndef NO_MD5 + case 3: /* see RFC 2898 for ids */ + *id = PBE_MD5_DES; + if (blockSz) *blockSz = DES_BLOCK_SIZE; + return 0; + #endif + #ifndef NO_SHA + case 10: + *id = PBE_SHA1_DES; + if (blockSz) *blockSz = DES_BLOCK_SIZE; + return 0; + #endif +#endif /* !NO_DES3 */ + default: + return ALGO_ID_E; + + } +} + + +/* Check To see if PKCS v2 algo is supported, set id if it is return 0 + < 0 on error */ +static int CheckAlgoV2(int oid, int* id, int* blockSz) +{ + if (blockSz) *blockSz = 8; /* default */ + (void)id; /* not used if AES and DES3 disabled */ + switch (oid) { +#if !defined(NO_DES3) && !defined(NO_SHA) + case DESb: + *id = PBE_SHA1_DES; + if (blockSz) *blockSz = DES_BLOCK_SIZE; + return 0; + case DES3b: + *id = PBE_SHA1_DES3; + if (blockSz) *blockSz = DES_BLOCK_SIZE; + return 0; +#endif +#ifdef WOLFSSL_AES_256 + case AES256CBCb: + *id = PBE_AES256_CBC; + if (blockSz) *blockSz = AES_BLOCK_SIZE; + return 0; +#endif + default: + return ALGO_ID_E; + + } +} + + +int wc_GetKeyOID(byte* key, word32 keySz, const byte** curveOID, word32* oidSz, + int* algoID, void* heap) +{ + word32 tmpIdx = 0; + + if (key == NULL || algoID == NULL) + return BAD_FUNC_ARG; + + *algoID = 0; + + #if !defined(NO_RSA) && !defined(NO_ASN_CRYPT) + { + RsaKey rsa; + + wc_InitRsaKey(&rsa, heap); + if (wc_RsaPrivateKeyDecode(key, &tmpIdx, &rsa, keySz) == 0) { + *algoID = RSAk; + } + else { + WOLFSSL_MSG("Not RSA DER key"); + } + wc_FreeRsaKey(&rsa); + } + #endif /* !NO_RSA && !NO_ASN_CRYPT */ + #if defined(HAVE_ECC) && !defined(NO_ASN_CRYPT) + if (*algoID == 0) { + ecc_key ecc; + + tmpIdx = 0; + wc_ecc_init_ex(&ecc, heap, INVALID_DEVID); + if (wc_EccPrivateKeyDecode(key, &tmpIdx, &ecc, keySz) == 0) { + *algoID = ECDSAk; + + /* now find oid */ + if (wc_ecc_get_oid(ecc.dp->oidSum, curveOID, oidSz) < 0) { + WOLFSSL_MSG("Error getting ECC curve OID"); + wc_ecc_free(&ecc); + return BAD_FUNC_ARG; + } + } + else { + WOLFSSL_MSG("Not ECC DER key either"); + } + wc_ecc_free(&ecc); + } +#endif /* HAVE_ECC && !NO_ASN_CRYPT */ +#if defined(HAVE_ED25519) && !defined(NO_ASN_CRYPT) + if (*algoID != RSAk && *algoID != ECDSAk) { + ed25519_key ed25519; + + tmpIdx = 0; + if (wc_ed25519_init(&ed25519) == 0) { + if (wc_Ed25519PrivateKeyDecode(key, &tmpIdx, &ed25519, keySz) + == 0) { + *algoID = ED25519k; + } + else { + WOLFSSL_MSG("Not ED25519 DER key"); + } + wc_ed25519_free(&ed25519); + } + else { + WOLFSSL_MSG("GetKeyOID wc_ed25519_init failed"); + } + } +#endif /* HAVE_ED25519 && !NO_ASN_CRYPT */ + + /* if flag is not set then is neither RSA or ECC key that could be + * found */ + if (*algoID == 0) { + WOLFSSL_MSG("Bad key DER or compile options"); + return BAD_FUNC_ARG; + } + + (void)tmpIdx; + (void)curveOID; + (void)oidSz; + (void)keySz; + (void)heap; + + return 1; +} + +#define PKCS8_MIN_BLOCK_SIZE 8 +static int Pkcs8Pad(byte* buf, int sz, int blockSz) +{ + int i, padSz; + + /* calculate pad size */ + padSz = blockSz - (sz & (blockSz - 1)); + + /* pad with padSz value */ + if (buf) { + for (i = 0; i < padSz; i++) { + buf[sz+i] = (byte)(padSz & 0xFF); + } + } + + /* return adjusted length */ + return sz + padSz; +} + +/* + * Used when creating PKCS12 shrouded key bags + * vPKCS is the version of PKCS to use + * vAlgo is the algorithm version to use + * + * if salt is NULL a random number is generated + * + * returns the size of encrypted data on success + */ +int UnTraditionalEnc(byte* key, word32 keySz, byte* out, word32* outSz, + const char* password, int passwordSz, int vPKCS, int vAlgo, + byte* salt, word32 saltSz, int itt, WC_RNG* rng, void* heap) +{ + int algoID = 0; + byte* tmp; + word32 tmpSz = 0; + word32 sz; + word32 seqSz; + word32 inOutIdx = 0; + word32 totalSz = 0; + int version, id; + int ret; + int blockSz = 0; + + const byte* curveOID = NULL; + word32 oidSz = 0; + +#ifdef WOLFSSL_SMALL_STACK + byte* saltTmp = NULL; + byte* cbcIv = NULL; +#else + byte saltTmp[MAX_IV_SIZE]; + byte cbcIv[MAX_IV_SIZE]; +#endif + + WOLFSSL_ENTER("UnTraditionalEnc()"); + + if (saltSz > MAX_SALT_SIZE) + return ASN_PARSE_E; + + + inOutIdx += MAX_SEQ_SZ; /* leave room for size of finished shroud */ + if (CheckAlgo(vPKCS, vAlgo, &id, &version, &blockSz) < 0) { + WOLFSSL_MSG("Bad/Unsupported algorithm ID"); + return ASN_INPUT_E; /* Algo ID error */ + } + + if (out != NULL) { + if (*outSz < inOutIdx + MAX_ALGO_SZ + MAX_SALT_SIZE + MAX_SEQ_SZ + 1 + + MAX_LENGTH_SZ + MAX_SHORT_SZ + 1) + return BUFFER_E; + + if (version == PKCS5v2) { + WOLFSSL_MSG("PKCS5v2 Not supported yet\n"); + return ASN_VERSION_E; + } + + if (salt == NULL || saltSz <= 0) { + saltSz = 8; + #ifdef WOLFSSL_SMALL_STACK + saltTmp = (byte*)XMALLOC(saltSz, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (saltTmp == NULL) + return MEMORY_E; + #endif + salt = saltTmp; + + if ((ret = wc_RNG_GenerateBlock(rng, saltTmp, saltSz)) != 0) { + WOLFSSL_MSG("Error generating random salt"); + #ifdef WOLFSSL_SMALL_STACK + if (saltTmp != NULL) + XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ret; + } + } + + + /* leave room for a sequence (contains salt and iterations int) */ + inOutIdx += MAX_SEQ_SZ; sz = 0; + inOutIdx += MAX_ALGO_SZ; + + /* place salt in buffer */ + out[inOutIdx++] = ASN_OCTET_STRING; sz++; + tmpSz = SetLength(saltSz, out + inOutIdx); + inOutIdx += tmpSz; sz += tmpSz; + XMEMCPY(out + inOutIdx, salt, saltSz); + inOutIdx += saltSz; sz += saltSz; + + /* place iteration count in buffer */ + ret = SetShortInt(out, &inOutIdx, itt, *outSz); + if (ret < 0) { + return ret; + } + sz += (word32)ret; + + /* wind back index and set sequence then clean up buffer */ + inOutIdx -= (sz + MAX_SEQ_SZ); + tmpSz = SetSequence(sz, out + inOutIdx); + XMEMMOVE(out + inOutIdx + tmpSz, out + inOutIdx + MAX_SEQ_SZ, sz); + totalSz += tmpSz + sz; sz += tmpSz; + + /* add in algo ID */ + inOutIdx -= MAX_ALGO_SZ; + tmpSz = SetAlgoID(id, out + inOutIdx, oidPBEType, sz); + XMEMMOVE(out + inOutIdx + tmpSz, out + inOutIdx + MAX_ALGO_SZ, sz); + totalSz += tmpSz; inOutIdx += tmpSz + sz; + + /* octet string containing encrypted key */ + out[inOutIdx++] = ASN_OCTET_STRING; totalSz++; + } + + /* check key type and get OID if ECC */ + if ((ret = wc_GetKeyOID(key, keySz, &curveOID, &oidSz, &algoID, heap))< 0) { + return ret; + } + + /* PKCS#8 wrapping around key */ + if (wc_CreatePKCS8Key(NULL, &tmpSz, key, keySz, algoID, curveOID, oidSz) + != LENGTH_ONLY_E) { + #ifdef WOLFSSL_SMALL_STACK + if (saltTmp != NULL) + XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return MEMORY_E; + } + + /* check if should return max size */ + if (out == NULL) { + /* account for salt size */ + if (salt == NULL || saltSz <= 0) { + tmpSz += MAX_SALT_SIZE; + } + else { + tmpSz += saltSz; + } + + /* plus 3 for tags */ + *outSz = tmpSz + MAX_ALGO_SZ + MAX_LENGTH_SZ +MAX_LENGTH_SZ + MAX_SEQ_SZ + + MAX_LENGTH_SZ + MAX_SEQ_SZ + 3; + return LENGTH_ONLY_E; + } + + /* reserve buffer for crypto and make sure it supports full blocks */ + tmp = (byte*)XMALLOC(tmpSz + (blockSz-1), heap, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) { + #ifdef WOLFSSL_SMALL_STACK + if (saltTmp != NULL) + XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return MEMORY_E; + } + + if ((ret = wc_CreatePKCS8Key(tmp, &tmpSz, key, keySz, algoID, curveOID, + oidSz)) < 0) { + XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + WOLFSSL_MSG("Error wrapping key with PKCS#8"); + #ifdef WOLFSSL_SMALL_STACK + if (saltTmp != NULL) + XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ret; + } + tmpSz = ret; + + /* adjust size to pad */ + tmpSz = Pkcs8Pad(tmp, tmpSz, blockSz); + +#ifdef WOLFSSL_SMALL_STACK + cbcIv = (byte*)XMALLOC(MAX_IV_SIZE, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (cbcIv == NULL) { + if (saltTmp != NULL) + XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(salt, heap, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#endif + + /* encrypt PKCS#8 wrapped key */ + if ((ret = wc_CryptKey(password, passwordSz, salt, saltSz, itt, id, + tmp, tmpSz, version, cbcIv, 1)) < 0) { + XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + WOLFSSL_MSG("Error encrypting key"); + #ifdef WOLFSSL_SMALL_STACK + if (saltTmp != NULL) + XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (cbcIv != NULL) + XFREE(cbcIv, heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ret; /* encryption failure */ + } + totalSz += tmpSz; + +#ifdef WOLFSSL_SMALL_STACK + if (saltTmp != NULL) + XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (cbcIv != NULL) + XFREE(cbcIv, heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + if (*outSz < inOutIdx + tmpSz + MAX_LENGTH_SZ) { + XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + return BUFFER_E; + } + + /* set length of key and copy over encrypted key */ + seqSz = SetLength(tmpSz, out + inOutIdx); + inOutIdx += seqSz; totalSz += seqSz; + XMEMCPY(out + inOutIdx, tmp, tmpSz); + XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + + /* set total size at beginning */ + sz = SetSequence(totalSz, out); + XMEMMOVE(out + sz, out + MAX_SEQ_SZ, totalSz); + + (void)rng; + + return totalSz + sz; +} + +static int GetAlgoV2(int encAlgId, const byte** oid, int *len, int* id, + int *blkSz) +{ + int ret = 0; + + switch (encAlgId) { +#if !defined(NO_DES3) && !defined(NO_SHA) + case DESb: + *len = sizeof(blkDesCbcOid); + *oid = blkDesCbcOid; + *id = PBE_SHA1_DES; + *blkSz = 8; + break; + case DES3b: + *len = sizeof(blkDes3CbcOid); + *oid = blkDes3CbcOid; + *id = PBE_SHA1_DES3; + *blkSz = 8; + break; +#endif +#if defined(WOLFSSL_AES_256) && defined(HAVE_AES_CBC) + case AES256CBCb: + *len = sizeof(blkAes256CbcOid); + *oid = blkAes256CbcOid; + *id = PBE_AES256_CBC; + *blkSz = 16; + break; +#endif + default: + (void)len; + (void)oid; + (void)id; + (void)blkSz; + ret = ALGO_ID_E; + } + + return ret; +} + +/* Converts Encrypted PKCS#8 to 'traditional' (i.e. PKCS#8 removed from + * decrypted key.) + */ +int TraditionalEnc(byte* key, word32 keySz, byte* out, word32* outSz, + const char* password, int passwordSz, int vPKCS, int vAlgo, + int encAlgId, byte* salt, word32 saltSz, int itt, WC_RNG* rng, + void* heap) +{ + int ret = 0; + int version, blockSz, id; + word32 idx = 0, encIdx; +#ifdef WOLFSSL_SMALL_STACK + byte* saltTmp = NULL; +#else + byte saltTmp[MAX_SALT_SIZE]; +#endif + byte cbcIv[MAX_IV_SIZE]; + byte *pkcs8Key = NULL; + word32 pkcs8KeySz = 0, padSz = 0; + int algId = 0; + const byte* curveOid = NULL; + word32 curveOidSz = 0; + const byte* pbeOid = NULL; + word32 pbeOidSz = 0; + const byte* encOid = NULL; + int encOidSz = 0; + word32 pbeLen = 0, kdfLen = 0, encLen = 0; + word32 innerLen = 0, outerLen; + + ret = CheckAlgo(vPKCS, vAlgo, &id, &version, &blockSz); + /* create random salt if one not provided */ + if (ret == 0 && (salt == NULL || saltSz <= 0)) { + saltSz = 8; + #ifdef WOLFSSL_SMALL_STACK + saltTmp = (byte*)XMALLOC(saltSz, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (saltTmp == NULL) + return MEMORY_E; + #endif + salt = saltTmp; + + if ((ret = wc_RNG_GenerateBlock(rng, saltTmp, saltSz)) != 0) { + WOLFSSL_MSG("Error generating random salt"); + #ifdef WOLFSSL_SMALL_STACK + XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ret; + } + } + + if (ret == 0) { + /* check key type and get OID if ECC */ + ret = wc_GetKeyOID(key, keySz, &curveOid, &curveOidSz, &algId, heap); + if (ret == 1) + ret = 0; + } + if (ret == 0) { + ret = wc_CreatePKCS8Key(NULL, &pkcs8KeySz, key, keySz, algId, curveOid, + curveOidSz); + if (ret == LENGTH_ONLY_E) + ret = 0; + } + if (ret == 0) { + pkcs8Key = (byte*)XMALLOC(pkcs8KeySz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (pkcs8Key == NULL) + ret = MEMORY_E; + } + if (ret == 0) { + ret = wc_CreatePKCS8Key(pkcs8Key, &pkcs8KeySz, key, keySz, algId, + curveOid, curveOidSz); + if (ret >= 0) { + pkcs8KeySz = ret; + ret = 0; + } + } + + if (ret == 0 && version == PKCS5v2) + ret = GetAlgoV2(encAlgId, &encOid, &encOidSz, &id, &blockSz); + + if (ret == 0) { + padSz = (blockSz - (pkcs8KeySz & (blockSz - 1))) & (blockSz - 1); + /* inner = OCT salt INT itt */ + innerLen = 2 + saltSz + 2 + (itt < 256 ? 1 : 2); + + if (version != PKCS5v2) { + pbeOid = OidFromId(id, oidPBEType, &pbeOidSz); + /* pbe = OBJ pbse1 SEQ [ inner ] */ + pbeLen = 2 + pbeOidSz + 2 + innerLen; + } + else { + pbeOid = pbes2; + pbeOidSz = sizeof(pbes2); + /* kdf = OBJ pbkdf2 [ SEQ innerLen ] */ + kdfLen = 2 + sizeof(pbkdf2Oid) + 2 + innerLen; + /* enc = OBJ enc_alg OCT iv */ + encLen = 2 + encOidSz + 2 + blockSz; + /* pbe = OBJ pbse2 SEQ [ SEQ [ kdf ] SEQ [ enc ] ] */ + pbeLen = 2 + sizeof(pbes2) + 2 + 2 + kdfLen + 2 + encLen; + + ret = wc_RNG_GenerateBlock(rng, cbcIv, blockSz); + } + } + if (ret == 0) { + /* outer = SEQ [ pbe ] OCT encrypted_PKCS#8_key */ + outerLen = 2 + pbeLen; + outerLen += SetOctetString(pkcs8KeySz + padSz, out); + outerLen += pkcs8KeySz + padSz; + + idx += SetSequence(outerLen, out + idx); + + encIdx = idx + outerLen - pkcs8KeySz - padSz; + /* Put Encrypted content in place. */ + XMEMCPY(out + encIdx, pkcs8Key, pkcs8KeySz); + if (padSz > 0) { + XMEMSET(out + encIdx + pkcs8KeySz, padSz, padSz); + pkcs8KeySz += padSz; + } + ret = wc_CryptKey(password, passwordSz, salt, saltSz, itt, id, + out + encIdx, pkcs8KeySz, version, cbcIv, 1); + } + if (ret == 0) { + if (version != PKCS5v2) { + /* PBE algorithm */ + idx += SetSequence(pbeLen, out + idx); + idx += SetObjectId(pbeOidSz, out + idx); + XMEMCPY(out + idx, pbeOid, pbeOidSz); + idx += pbeOidSz; + } + else { + /* PBES2 algorithm identifier */ + idx += SetSequence(pbeLen, out + idx); + idx += SetObjectId(pbeOidSz, out + idx); + XMEMCPY(out + idx, pbeOid, pbeOidSz); + idx += pbeOidSz; + /* PBES2 Parameters: SEQ [ kdf ] SEQ [ enc ] */ + idx += SetSequence(2 + kdfLen + 2 + encLen, out + idx); + /* KDF Algorithm Identifier */ + idx += SetSequence(kdfLen, out + idx); + idx += SetObjectId(sizeof(pbkdf2Oid), out + idx); + XMEMCPY(out + idx, pbkdf2Oid, sizeof(pbkdf2Oid)); + idx += sizeof(pbkdf2Oid); + } + idx += SetSequence(innerLen, out + idx); + idx += SetOctetString(saltSz, out + idx); + XMEMCPY(out + idx, salt, saltSz); idx += saltSz; + ret = SetShortInt(out, &idx, itt, *outSz); + if (ret > 0) + ret = 0; + } + if (ret == 0) { + if (version == PKCS5v2) { + /* Encryption Algorithm Identifier */ + idx += SetSequence(encLen, out + idx); + idx += SetObjectId(encOidSz, out + idx); + XMEMCPY(out + idx, encOid, encOidSz); + idx += encOidSz; + /* Encryption Algorithm Parameter: CBC IV */ + idx += SetOctetString(blockSz, out + idx); + XMEMCPY(out + idx, cbcIv, blockSz); + idx += blockSz; + } + idx += SetOctetString(pkcs8KeySz, out + idx); + /* Default PRF - no need to write out OID */ + idx += pkcs8KeySz; + + ret = idx; + } + + if (pkcs8Key != NULL) { + ForceZero(pkcs8Key, pkcs8KeySz); + XFREE(pkcs8Key, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +#ifdef WOLFSSL_SMALL_STACK + if (saltTmp != NULL) { + XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif + + (void)rng; + + return ret; +} + +/* Remove Encrypted PKCS8 header, move beginning of traditional to beginning + of input */ +int ToTraditionalEnc(byte* input, word32 sz,const char* password, + int passwordSz, word32* algId) +{ + word32 inOutIdx = 0, seqEnd, oid; + int ret = 0, first, second, length = 0, version, saltSz, id; + int iterations = 0, keySz = 0; +#ifdef WOLFSSL_SMALL_STACK + byte* salt = NULL; + byte* cbcIv = NULL; +#else + byte salt[MAX_SALT_SIZE]; + byte cbcIv[MAX_IV_SIZE]; +#endif + + if (passwordSz < 0) { + WOLFSSL_MSG("Bad password size"); + return BAD_FUNC_ARG; + } + + if (GetSequence(input, &inOutIdx, &length, sz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_tte); + } + + if (GetAlgoId(input, &inOutIdx, &oid, oidIgnoreType, sz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_tte); + } + + first = input[inOutIdx - 2]; /* PKCS version always 2nd to last byte */ + second = input[inOutIdx - 1]; /* version.algo, algo id last byte */ + + if (CheckAlgo(first, second, &id, &version, NULL) < 0) { + ERROR_OUT(ASN_INPUT_E, exit_tte); /* Algo ID error */ + } + + if (version == PKCS5v2) { + if (GetSequence(input, &inOutIdx, &length, sz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_tte); + } + + if (GetAlgoId(input, &inOutIdx, &oid, oidKdfType, sz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_tte); + } + + if (oid != PBKDF2_OID) { + ERROR_OUT(ASN_PARSE_E, exit_tte); + } + } + + if (GetSequence(input, &inOutIdx, &length, sz) <= 0) { + ERROR_OUT(ASN_PARSE_E, exit_tte); + } + /* Find the end of this SEQUENCE so we can check for the OPTIONAL and + * DEFAULT items. */ + seqEnd = inOutIdx + length; + + ret = GetOctetString(input, &inOutIdx, &saltSz, sz); + if (ret < 0) + goto exit_tte; + + if (saltSz > MAX_SALT_SIZE) { + ERROR_OUT(ASN_PARSE_E, exit_tte); + } + +#ifdef WOLFSSL_SMALL_STACK + salt = (byte*)XMALLOC(MAX_SALT_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (salt == NULL) { + ERROR_OUT(MEMORY_E, exit_tte); + } +#endif + + XMEMCPY(salt, &input[inOutIdx], saltSz); + inOutIdx += saltSz; + + if (GetShortInt(input, &inOutIdx, &iterations, sz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_tte); + } + + /* OPTIONAL key length */ + if (seqEnd > inOutIdx && input[inOutIdx] == ASN_INTEGER) { + if (GetShortInt(input, &inOutIdx, &keySz, sz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_tte); + } + } + + /* DEFAULT HMAC is SHA-1 */ + if (seqEnd > inOutIdx) { + if (GetAlgoId(input, &inOutIdx, &oid, oidHmacType, sz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_tte); + } + } + +#ifdef WOLFSSL_SMALL_STACK + cbcIv = (byte*)XMALLOC(MAX_IV_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (cbcIv == NULL) { + ERROR_OUT(MEMORY_E, exit_tte); + } +#endif + + if (version == PKCS5v2) { + /* get encryption algo */ + if (GetAlgoId(input, &inOutIdx, &oid, oidBlkType, sz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_tte); + } + + if (CheckAlgoV2(oid, &id, NULL) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_tte); /* PKCS v2 algo id error */ + } + + ret = GetOctetString(input, &inOutIdx, &length, sz); + if (ret < 0) + goto exit_tte; + + if (length > MAX_IV_SIZE) { + ERROR_OUT(ASN_PARSE_E, exit_tte); + } + + XMEMCPY(cbcIv, &input[inOutIdx], length); + inOutIdx += length; + } + + ret = GetOctetString(input, &inOutIdx, &length, sz); + if (ret < 0) + goto exit_tte; + + ret = wc_CryptKey(password, passwordSz, salt, saltSz, iterations, id, + input + inOutIdx, length, version, cbcIv, 0); + +exit_tte: +#ifdef WOLFSSL_SMALL_STACK + XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + if (ret == 0) { + XMEMMOVE(input, input + inOutIdx, length); + ret = ToTraditional_ex(input, length, algId); + } + + return ret; +} + +#endif /* HAVE_PKCS8 */ + +#ifdef HAVE_PKCS12 + +/* encrypt PKCS 12 content + * + * NOTE: if out is NULL then outSz is set with the total buffer size needed and + * the error value LENGTH_ONLY_E is returned. + * + * input data to encrypt + * inputSz size of input buffer + * out buffer to hold the result + * outSz size of out buffer + * password password if used. Can be NULL for no password + * passwordSz size of password buffer + * vPKCS version of PKCS i.e. PKCS5v2 + * vAlgo algorithm version + * salt buffer holding salt if used. If NULL then a random salt is created + * saltSz size of salt buffer if it is not NULL + * itt number of iterations used + * rng random number generator to use + * heap possible heap hint for mallocs/frees + * + * returns the total size of encrypted content on success. + */ +int EncryptContent(byte* input, word32 inputSz, byte* out, word32* outSz, + const char* password, int passwordSz, int vPKCS, int vAlgo, + byte* salt, word32 saltSz, int itt, WC_RNG* rng, void* heap) +{ + word32 sz; + word32 inOutIdx = 0; + word32 tmpIdx = 0; + word32 totalSz = 0; + word32 seqSz; + int ret; + int version, id, blockSz = 0; +#ifdef WOLFSSL_SMALL_STACK + byte* saltTmp = NULL; + byte* cbcIv = NULL; +#else + byte saltTmp[MAX_SALT_SIZE]; + byte cbcIv[MAX_IV_SIZE]; +#endif + + (void)heap; + + WOLFSSL_ENTER("EncryptContent()"); + + if (CheckAlgo(vPKCS, vAlgo, &id, &version, &blockSz) < 0) + return ASN_INPUT_E; /* Algo ID error */ + + if (version == PKCS5v2) { + WOLFSSL_MSG("PKCS#5 version 2 not supported yet"); + return BAD_FUNC_ARG; + } + + if (saltSz > MAX_SALT_SIZE) + return ASN_PARSE_E; + + if (outSz == NULL) { + return BAD_FUNC_ARG; + } + + if (out == NULL) { + sz = inputSz; + switch (id) { + #if !defined(NO_DES3) && (!defined(NO_MD5) || !defined(NO_SHA)) + case PBE_MD5_DES: + case PBE_SHA1_DES: + case PBE_SHA1_DES3: + /* set to block size of 8 for DES operations. This rounds up + * to the nearest multiple of 8 */ + sz &= 0xfffffff8; + sz += 8; + break; + #endif /* !NO_DES3 && (!NO_MD5 || !NO_SHA) */ + #if !defined(NO_RC4) && !defined(NO_SHA) + case PBE_SHA1_RC4_128: + break; + #endif + case -1: + break; + + default: + return ALGO_ID_E; + } + + if (saltSz <= 0) { + sz += MAX_SALT_SIZE; + } + else { + sz += saltSz; + } + + /* add 2 for tags */ + totalSz = sz + MAX_ALGO_SZ + MAX_SEQ_SZ + MAX_LENGTH_SZ + + MAX_LENGTH_SZ + MAX_LENGTH_SZ + MAX_SHORT_SZ + 2; + + /* adjust size to pad */ + totalSz = Pkcs8Pad(NULL, totalSz, blockSz); + + /* return result */ + *outSz = totalSz; + + return LENGTH_ONLY_E; + } + + if (inOutIdx + MAX_ALGO_SZ + MAX_SEQ_SZ + 1 > *outSz) + return BUFFER_E; + + sz = SetAlgoID(id, out + inOutIdx, oidPBEType, 0); + inOutIdx += sz; totalSz += sz; + tmpIdx = inOutIdx; + tmpIdx += MAX_SEQ_SZ; /* save room for salt and itter sequence */ + out[tmpIdx++] = ASN_OCTET_STRING; + + /* create random salt if one not provided */ + if (salt == NULL || saltSz <= 0) { + saltSz = 8; + #ifdef WOLFSSL_SMALL_STACK + saltTmp = (byte*)XMALLOC(saltSz, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (saltTmp == NULL) + return MEMORY_E; + #endif + salt = saltTmp; + + if ((ret = wc_RNG_GenerateBlock(rng, saltTmp, saltSz)) != 0) { + WOLFSSL_MSG("Error generating random salt"); + #ifdef WOLFSSL_SMALL_STACK + XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ret; + } + } + + if (tmpIdx + MAX_LENGTH_SZ + saltSz + MAX_SHORT_SZ > *outSz) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return BUFFER_E; + } + + sz = SetLength(saltSz, out + tmpIdx); + tmpIdx += sz; + + XMEMCPY(out + tmpIdx, salt, saltSz); + tmpIdx += saltSz; + + /* place iteration setting in buffer */ + ret = SetShortInt(out, &tmpIdx, itt, *outSz); + if (ret < 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ret; + } + + /* rewind and place sequence */ + sz = tmpIdx - inOutIdx - MAX_SEQ_SZ; + seqSz = SetSequence(sz, out + inOutIdx); + XMEMMOVE(out + inOutIdx + seqSz, out + inOutIdx + MAX_SEQ_SZ, sz); + inOutIdx += seqSz; totalSz += seqSz; + inOutIdx += sz; totalSz += sz; + +#ifdef WOLFSSL_SMALL_STACK + cbcIv = (byte*)XMALLOC(MAX_IV_SIZE, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (cbcIv == NULL) { + XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#endif + + if (inOutIdx + 1 + MAX_LENGTH_SZ + inputSz > *outSz) + return BUFFER_E; + + out[inOutIdx++] = ASN_CONTEXT_SPECIFIC | 0; totalSz++; + sz = SetLength(inputSz, out + inOutIdx); + inOutIdx += sz; totalSz += sz; + + /* get pad size and verify buffer room */ + sz = Pkcs8Pad(NULL, inputSz, blockSz); + if (sz + inOutIdx > *outSz) + return BUFFER_E; + + /* copy input to output buffer and pad end */ + XMEMCPY(out + inOutIdx, input, inputSz); + sz = Pkcs8Pad(out + inOutIdx, inputSz, blockSz); + totalSz += sz; + + /* encrypt */ + if ((ret = wc_CryptKey(password, passwordSz, salt, saltSz, itt, id, + out + inOutIdx, sz, version, cbcIv, 1)) < 0) { + + #ifdef WOLFSSL_SMALL_STACK + XFREE(cbcIv, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ret; /* encrypt failure */ + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(cbcIv, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(saltTmp, heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + (void)rng; + + return totalSz; +} + + +/* decrypt PKCS + * + * NOTE: input buffer is overwritten with decrypted data! + * + * input[in/out] data to decrypt and results are written to + * sz size of input buffer + * password password if used. Can be NULL for no password + * passwordSz size of password buffer + * + * returns the total size of decrypted content on success. + */ +int DecryptContent(byte* input, word32 sz,const char* password, int passwordSz) +{ + word32 inOutIdx = 0, seqEnd, oid; + int ret = 0; + int first, second, length = 0, version, saltSz, id; + int iterations = 0, keySz = 0; +#ifdef WOLFSSL_SMALL_STACK + byte* salt = NULL; + byte* cbcIv = NULL; +#else + byte salt[MAX_SALT_SIZE]; + byte cbcIv[MAX_IV_SIZE]; +#endif + + if (GetAlgoId(input, &inOutIdx, &oid, oidIgnoreType, sz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_dc); + } + + first = input[inOutIdx - 2]; /* PKCS version always 2nd to last byte */ + second = input[inOutIdx - 1]; /* version.algo, algo id last byte */ + + if (CheckAlgo(first, second, &id, &version, NULL) < 0) { + ERROR_OUT(ASN_INPUT_E, exit_dc); /* Algo ID error */ + } + + if (version == PKCS5v2) { + if (GetSequence(input, &inOutIdx, &length, sz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_dc); + } + + if (GetAlgoId(input, &inOutIdx, &oid, oidKdfType, sz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_dc); + } + + if (oid != PBKDF2_OID) { + ERROR_OUT(ASN_PARSE_E, exit_dc); + } + } + + if (GetSequence(input, &inOutIdx, &length, sz) <= 0) { + ERROR_OUT(ASN_PARSE_E, exit_dc); + } + /* Find the end of this SEQUENCE so we can check for the OPTIONAL and + * DEFAULT items. */ + seqEnd = inOutIdx + length; + + ret = GetOctetString(input, &inOutIdx, &saltSz, sz); + if (ret < 0) + goto exit_dc; + + if (saltSz > MAX_SALT_SIZE) { + ERROR_OUT(ASN_PARSE_E, exit_dc); + } + +#ifdef WOLFSSL_SMALL_STACK + salt = (byte*)XMALLOC(MAX_SALT_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (salt == NULL) { + ERROR_OUT(MEMORY_E, exit_dc); + } +#endif + + XMEMCPY(salt, &input[inOutIdx], saltSz); + inOutIdx += saltSz; + + if (GetShortInt(input, &inOutIdx, &iterations, sz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_dc); + } + + /* OPTIONAL key length */ + if (seqEnd > inOutIdx && input[inOutIdx] == ASN_INTEGER) { + if (GetShortInt(input, &inOutIdx, &keySz, sz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_dc); + } + } + + /* DEFAULT HMAC is SHA-1 */ + if (seqEnd > inOutIdx) { + if (GetAlgoId(input, &inOutIdx, &oid, oidHmacType, sz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_dc); + } + } + +#ifdef WOLFSSL_SMALL_STACK + cbcIv = (byte*)XMALLOC(MAX_IV_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (cbcIv == NULL) { + ERROR_OUT(MEMORY_E, exit_dc); + } +#endif + + if (version == PKCS5v2) { + /* get encryption algo */ + if (GetAlgoId(input, &inOutIdx, &oid, oidBlkType, sz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_dc); + } + + if (CheckAlgoV2(oid, &id, NULL) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_dc); /* PKCS v2 algo id error */ + } + + ret = GetOctetString(input, &inOutIdx, &length, sz); + if (ret < 0) + goto exit_dc; + + if (length > MAX_IV_SIZE) { + ERROR_OUT(ASN_PARSE_E, exit_dc); + } + + XMEMCPY(cbcIv, &input[inOutIdx], length); + inOutIdx += length; + } + + if (input[inOutIdx++] != (ASN_CONTEXT_SPECIFIC | 0)) { + ERROR_OUT(ASN_PARSE_E, exit_dc); + } + + if (GetLength(input, &inOutIdx, &length, sz) < 0) { + ERROR_OUT(ASN_PARSE_E, exit_dc); + } + + ret = wc_CryptKey(password, passwordSz, salt, saltSz, iterations, id, + input + inOutIdx, length, version, cbcIv, 0); + +exit_dc: + +#ifdef WOLFSSL_SMALL_STACK + XFREE(salt, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(cbcIv, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + if (ret == 0) { + XMEMMOVE(input, input + inOutIdx, length); + ret = length; + } + + return ret; +} +#endif /* HAVE_PKCS12 */ +#endif /* NO_PWDBASED */ + +#ifndef NO_RSA + +#ifndef HAVE_USER_RSA +int wc_RsaPublicKeyDecode_ex(const byte* input, word32* inOutIdx, word32 inSz, + const byte** n, word32* nSz, const byte** e, word32* eSz) +{ + int ret = 0; + int length = 0; +#if defined(OPENSSL_EXTRA) || defined(RSA_DECODE_EXTRA) + byte b; +#endif + + if (input == NULL || inOutIdx == NULL) + return BAD_FUNC_ARG; + + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + return ASN_PARSE_E; + +#if defined(OPENSSL_EXTRA) || defined(RSA_DECODE_EXTRA) + if ((*inOutIdx + 1) > inSz) + return BUFFER_E; + + b = input[*inOutIdx]; + if (b != ASN_INTEGER) { + /* not from decoded cert, will have algo id, skip past */ + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + return ASN_PARSE_E; + + if (SkipObjectId(input, inOutIdx, inSz) < 0) + return ASN_PARSE_E; + + /* Option NULL ASN.1 tag */ + if (*inOutIdx >= inSz) { + return BUFFER_E; + } + if (input[*inOutIdx] == ASN_TAG_NULL) { + ret = GetASNNull(input, inOutIdx, inSz); + if (ret != 0) + return ret; + } + + /* should have bit tag length and seq next */ + ret = CheckBitString(input, inOutIdx, NULL, inSz, 1, NULL); + if (ret != 0) + return ret; + + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + return ASN_PARSE_E; + } +#endif /* OPENSSL_EXTRA */ + + /* Get modulus */ + ret = GetASNInt(input, inOutIdx, &length, inSz); + if (ret < 0) { + return ASN_RSA_KEY_E; + } + if (nSz) + *nSz = length; + if (n) + *n = &input[*inOutIdx]; + *inOutIdx += length; + + /* Get exponent */ + ret = GetASNInt(input, inOutIdx, &length, inSz); + if (ret < 0) { + return ASN_RSA_KEY_E; + } + if (eSz) + *eSz = length; + if (e) + *e = &input[*inOutIdx]; + *inOutIdx += length; + + return ret; +} + +int wc_RsaPublicKeyDecode(const byte* input, word32* inOutIdx, RsaKey* key, + word32 inSz) +{ + int ret; + const byte *n = NULL, *e = NULL; + word32 nSz = 0, eSz = 0; + + if (key == NULL) + return BAD_FUNC_ARG; + + ret = wc_RsaPublicKeyDecode_ex(input, inOutIdx, inSz, &n, &nSz, &e, &eSz); + if (ret == 0) { + ret = wc_RsaPublicKeyDecodeRaw(n, nSz, e, eSz, key); + } + + return ret; +} + +/* import RSA public key elements (n, e) into RsaKey structure (key) */ +int wc_RsaPublicKeyDecodeRaw(const byte* n, word32 nSz, const byte* e, + word32 eSz, RsaKey* key) +{ + if (n == NULL || e == NULL || key == NULL) + return BAD_FUNC_ARG; + + key->type = RSA_PUBLIC; + + if (mp_init(&key->n) != MP_OKAY) + return MP_INIT_E; + + if (mp_read_unsigned_bin(&key->n, n, nSz) != 0) { + mp_clear(&key->n); + return ASN_GETINT_E; + } +#ifdef HAVE_WOLF_BIGINT + if ((int)nSz > 0 && wc_bigint_from_unsigned_bin(&key->n.raw, n, nSz) != 0) { + mp_clear(&key->n); + return ASN_GETINT_E; + } +#endif /* HAVE_WOLF_BIGINT */ + + if (mp_init(&key->e) != MP_OKAY) { + mp_clear(&key->n); + return MP_INIT_E; + } + + if (mp_read_unsigned_bin(&key->e, e, eSz) != 0) { + mp_clear(&key->n); + mp_clear(&key->e); + return ASN_GETINT_E; + } +#ifdef HAVE_WOLF_BIGINT + if ((int)eSz > 0 && wc_bigint_from_unsigned_bin(&key->e.raw, e, eSz) != 0) { + mp_clear(&key->n); + mp_clear(&key->e); + return ASN_GETINT_E; + } +#endif /* HAVE_WOLF_BIGINT */ + +#ifdef WOLFSSL_XILINX_CRYPT + if (wc_InitRsaHw(key) != 0) { + return BAD_STATE_E; + } +#endif + + return 0; +} +#endif /* HAVE_USER_RSA */ +#endif /* !NO_RSA */ + +#ifndef NO_DH + +int wc_DhKeyDecode(const byte* input, word32* inOutIdx, DhKey* key, word32 inSz) +{ + int length; + + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + return ASN_PARSE_E; + + if (GetInt(&key->p, input, inOutIdx, inSz) < 0 || + GetInt(&key->g, input, inOutIdx, inSz) < 0) { + return ASN_DH_KEY_E; + } + + return 0; +} + + +int wc_DhParamsLoad(const byte* input, word32 inSz, byte* p, word32* pInOutSz, + byte* g, word32* gInOutSz) +{ + word32 idx = 0; + int ret; + int length; + + if (GetSequence(input, &idx, &length, inSz) <= 0) + return ASN_PARSE_E; + + ret = GetASNInt(input, &idx, &length, inSz); + if (ret != 0) + return ret; + + if (length <= (int)*pInOutSz) { + XMEMCPY(p, &input[idx], length); + *pInOutSz = length; + } + else { + return BUFFER_E; + } + idx += length; + + ret = GetASNInt(input, &idx, &length, inSz); + if (ret != 0) + return ret; + + if (length <= (int)*gInOutSz) { + XMEMCPY(g, &input[idx], length); + *gInOutSz = length; + } + else { + return BUFFER_E; + } + + return 0; +} +#endif /* NO_DH */ + + +#ifndef NO_DSA + +int DsaPublicKeyDecode(const byte* input, word32* inOutIdx, DsaKey* key, + word32 inSz) +{ + int length; + + if (input == NULL || inOutIdx == NULL || key == NULL) { + return BAD_FUNC_ARG; + } + + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + return ASN_PARSE_E; + + if (GetInt(&key->p, input, inOutIdx, inSz) < 0 || + GetInt(&key->q, input, inOutIdx, inSz) < 0 || + GetInt(&key->g, input, inOutIdx, inSz) < 0 || + GetInt(&key->y, input, inOutIdx, inSz) < 0 ) + return ASN_DH_KEY_E; + + key->type = DSA_PUBLIC; + return 0; +} + + +int DsaPrivateKeyDecode(const byte* input, word32* inOutIdx, DsaKey* key, + word32 inSz) +{ + int length, version; + + /* Sanity checks on input */ + if (input == NULL || inOutIdx == NULL || key == NULL) { + return BAD_FUNC_ARG; + } + + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + return ASN_PARSE_E; + + if (GetMyVersion(input, inOutIdx, &version, inSz) < 0) + return ASN_PARSE_E; + + if (GetInt(&key->p, input, inOutIdx, inSz) < 0 || + GetInt(&key->q, input, inOutIdx, inSz) < 0 || + GetInt(&key->g, input, inOutIdx, inSz) < 0 || + GetInt(&key->y, input, inOutIdx, inSz) < 0 || + GetInt(&key->x, input, inOutIdx, inSz) < 0 ) + return ASN_DH_KEY_E; + + key->type = DSA_PRIVATE; + return 0; +} + +static mp_int* GetDsaInt(DsaKey* key, int idx) +{ + if (idx == 0) + return &key->p; + if (idx == 1) + return &key->q; + if (idx == 2) + return &key->g; + if (idx == 3) + return &key->y; + if (idx == 4) + return &key->x; + + return NULL; +} + +/* Release Tmp DSA resources */ +static WC_INLINE void FreeTmpDsas(byte** tmps, void* heap) +{ + int i; + + for (i = 0; i < DSA_INTS; i++) + XFREE(tmps[i], heap, DYNAMIC_TYPE_DSA); + + (void)heap; +} + +/* Convert DsaKey key to DER format, write to output (inLen), return bytes + written */ +int wc_DsaKeyToDer(DsaKey* key, byte* output, word32 inLen) +{ + word32 seqSz, verSz, rawLen, intTotalLen = 0; + word32 sizes[DSA_INTS]; + int i, j, outLen, ret = 0, mpSz; + + byte seq[MAX_SEQ_SZ]; + byte ver[MAX_VERSION_SZ]; + byte* tmps[DSA_INTS]; + + if (!key || !output) + return BAD_FUNC_ARG; + + if (key->type != DSA_PRIVATE) + return BAD_FUNC_ARG; + + for (i = 0; i < DSA_INTS; i++) + tmps[i] = NULL; + + /* write all big ints from key to DER tmps */ + for (i = 0; i < DSA_INTS; i++) { + mp_int* keyInt = GetDsaInt(key, i); + + rawLen = mp_unsigned_bin_size(keyInt) + 1; + tmps[i] = (byte*)XMALLOC(rawLen + MAX_SEQ_SZ, key->heap, + DYNAMIC_TYPE_DSA); + if (tmps[i] == NULL) { + ret = MEMORY_E; + break; + } + + mpSz = SetASNIntMP(keyInt, -1, tmps[i]); + if (mpSz < 0) { + ret = mpSz; + break; + } + intTotalLen += (sizes[i] = mpSz); + } + + if (ret != 0) { + FreeTmpDsas(tmps, key->heap); + return ret; + } + + /* make headers */ + verSz = SetMyVersion(0, ver, FALSE); + seqSz = SetSequence(verSz + intTotalLen, seq); + + outLen = seqSz + verSz + intTotalLen; + if (outLen > (int)inLen) { + FreeTmpDsas(tmps, key->heap); + return BAD_FUNC_ARG; + } + + /* write to output */ + XMEMCPY(output, seq, seqSz); + j = seqSz; + XMEMCPY(output + j, ver, verSz); + j += verSz; + + for (i = 0; i < DSA_INTS; i++) { + XMEMCPY(output + j, tmps[i], sizes[i]); + j += sizes[i]; + } + FreeTmpDsas(tmps, key->heap); + + return outLen; +} + +#endif /* NO_DSA */ + +void InitDecodedCert(DecodedCert* cert, + const byte* source, word32 inSz, void* heap) +{ + if (cert != NULL) { + XMEMSET(cert, 0, sizeof(DecodedCert)); + + cert->subjectCNEnc = CTC_UTF8; + cert->issuer[0] = '\0'; + cert->subject[0] = '\0'; + cert->source = source; /* don't own */ + cert->maxIdx = inSz; /* can't go over this index */ + cert->heap = heap; + #ifdef WOLFSSL_CERT_GEN + cert->subjectSNEnc = CTC_UTF8; + cert->subjectCEnc = CTC_PRINTABLE; + cert->subjectLEnc = CTC_UTF8; + cert->subjectSTEnc = CTC_UTF8; + cert->subjectOEnc = CTC_UTF8; + cert->subjectOUEnc = CTC_UTF8; + #endif /* WOLFSSL_CERT_GEN */ + + #ifndef NO_CERTS + InitSignatureCtx(&cert->sigCtx, heap, INVALID_DEVID); + #endif + } +} + + +void FreeAltNames(DNS_entry* altNames, void* heap) +{ + (void)heap; + + while (altNames) { + DNS_entry* tmp = altNames->next; + + XFREE(altNames->name, heap, DYNAMIC_TYPE_ALTNAME); + XFREE(altNames, heap, DYNAMIC_TYPE_ALTNAME); + altNames = tmp; + } +} + +#ifndef IGNORE_NAME_CONSTRAINTS + +void FreeNameSubtrees(Base_entry* names, void* heap) +{ + (void)heap; + + while (names) { + Base_entry* tmp = names->next; + + XFREE(names->name, heap, DYNAMIC_TYPE_ALTNAME); + XFREE(names, heap, DYNAMIC_TYPE_ALTNAME); + names = tmp; + } +} + +#endif /* IGNORE_NAME_CONSTRAINTS */ + +void FreeDecodedCert(DecodedCert* cert) +{ + if (cert == NULL) + return; + if (cert->subjectCNStored == 1) + XFREE(cert->subjectCN, cert->heap, DYNAMIC_TYPE_SUBJECT_CN); + if (cert->pubKeyStored == 1) + XFREE((void*)cert->publicKey, cert->heap, DYNAMIC_TYPE_PUBLIC_KEY); + if (cert->weOwnAltNames && cert->altNames) + FreeAltNames(cert->altNames, cert->heap); +#ifndef IGNORE_NAME_CONSTRAINTS + if (cert->altEmailNames) + FreeAltNames(cert->altEmailNames, cert->heap); + if (cert->permittedNames) + FreeNameSubtrees(cert->permittedNames, cert->heap); + if (cert->excludedNames) + FreeNameSubtrees(cert->excludedNames, cert->heap); +#endif /* IGNORE_NAME_CONSTRAINTS */ +#ifdef WOLFSSL_SEP + XFREE(cert->deviceType, cert->heap, DYNAMIC_TYPE_X509_EXT); + XFREE(cert->hwType, cert->heap, DYNAMIC_TYPE_X509_EXT); + XFREE(cert->hwSerialNum, cert->heap, DYNAMIC_TYPE_X509_EXT); +#endif /* WOLFSSL_SEP */ +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + if (cert->issuerName.fullName != NULL) + XFREE(cert->issuerName.fullName, cert->heap, DYNAMIC_TYPE_X509); + if (cert->subjectName.fullName != NULL) + XFREE(cert->subjectName.fullName, cert->heap, DYNAMIC_TYPE_X509); +#endif /* OPENSSL_EXTRA */ +#ifndef NO_CERTS + FreeSignatureCtx(&cert->sigCtx); +#endif +} + +static int GetCertHeader(DecodedCert* cert) +{ + int ret = 0, len; + + if (GetSequence(cert->source, &cert->srcIdx, &len, cert->maxIdx) < 0) + return ASN_PARSE_E; + + cert->certBegin = cert->srcIdx; + + if (GetSequence(cert->source, &cert->srcIdx, &len, cert->maxIdx) < 0) + return ASN_PARSE_E; + cert->sigIndex = len + cert->srcIdx; + + if (GetExplicitVersion(cert->source, &cert->srcIdx, &cert->version, + cert->maxIdx) < 0) + return ASN_PARSE_E; + + if (GetSerialNumber(cert->source, &cert->srcIdx, cert->serial, + &cert->serialSz, cert->maxIdx) < 0) + return ASN_PARSE_E; + + return ret; +} + +#if !defined(NO_RSA) +/* Store Rsa Key, may save later, Dsa could use in future */ +static int StoreRsaKey(DecodedCert* cert, word32 bitStringEnd) +{ + int length; + word32 recvd = cert->srcIdx; + + if (GetSequence(cert->source, &cert->srcIdx, &length, bitStringEnd) < 0) + return ASN_PARSE_E; + + recvd = cert->srcIdx - recvd; + length += recvd; + + while (recvd--) + cert->srcIdx--; + + cert->pubKeySize = length; + cert->publicKey = cert->source + cert->srcIdx; + cert->srcIdx += length; + + return 0; +} +#endif /* !NO_RSA */ + +#ifdef HAVE_ECC + + /* return 0 on success if the ECC curve oid sum is supported */ + static int CheckCurve(word32 oid) + { + int ret = 0; + word32 oidSz = 0; + + ret = wc_ecc_get_oid(oid, NULL, &oidSz); + if (ret < 0 || oidSz <= 0) { + WOLFSSL_MSG("CheckCurve not found"); + ret = ALGO_ID_E; + } + + return ret; + } + +#endif /* HAVE_ECC */ + +static int GetKey(DecodedCert* cert) +{ + int length; +#if defined(HAVE_ECC) || defined(HAVE_NTRU) + int tmpIdx = cert->srcIdx; +#endif + + if (GetSequence(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0) + return ASN_PARSE_E; + + if (GetAlgoId(cert->source, &cert->srcIdx, + &cert->keyOID, oidKeyType, cert->maxIdx) < 0) + return ASN_PARSE_E; + + switch (cert->keyOID) { + #ifndef NO_RSA + case RSAk: + { + int ret; + + ret = CheckBitString(cert->source, &cert->srcIdx, &length, + cert->maxIdx, 1, NULL); + if (ret != 0) + return ret; + + #ifdef HAVE_OCSP + ret = CalcHashId(cert->source + cert->srcIdx, length, + cert->subjectKeyHash); + if (ret != 0) + return ret; + #endif + + return StoreRsaKey(cert, cert->srcIdx + length); + } + + #endif /* NO_RSA */ + #ifdef HAVE_NTRU + case NTRUk: + { + const byte* key = &cert->source[tmpIdx]; + byte* next = (byte*)key; + word16 keyLen; + word32 rc; + word32 remaining = cert->maxIdx - cert->srcIdx; + byte* publicKey; +#ifdef WOLFSSL_SMALL_STACK + byte* keyBlob = NULL; +#else + byte keyBlob[MAX_NTRU_KEY_SZ]; +#endif + rc = ntru_crypto_ntru_encrypt_subjectPublicKeyInfo2PublicKey(key, + &keyLen, NULL, &next, &remaining); + if (rc != NTRU_OK) + return ASN_NTRU_KEY_E; + if (keyLen > MAX_NTRU_KEY_SZ) + return ASN_NTRU_KEY_E; + +#ifdef WOLFSSL_SMALL_STACK + keyBlob = (byte*)XMALLOC(MAX_NTRU_KEY_SZ, cert->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (keyBlob == NULL) + return MEMORY_E; +#endif + + rc = ntru_crypto_ntru_encrypt_subjectPublicKeyInfo2PublicKey(key, + &keyLen, keyBlob, &next, &remaining); + if (rc != NTRU_OK) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(keyBlob, cert->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ASN_NTRU_KEY_E; + } + + if ( (next - key) < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(keyBlob, cert->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ASN_NTRU_KEY_E; + } + + cert->srcIdx = tmpIdx + (int)(next - key); + + publicKey = (byte*)XMALLOC(keyLen, cert->heap, + DYNAMIC_TYPE_PUBLIC_KEY); + if (publicKey == NULL) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(keyBlob, cert->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return MEMORY_E; + } + XMEMCPY(publicKey, keyBlob, keyLen); + cert->publicKey = publicKey; + cert->pubKeyStored = 1; + cert->pubKeySize = keyLen; + +#ifdef WOLFSSL_SMALL_STACK + XFREE(keyBlob, cert->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return 0; + } + #endif /* HAVE_NTRU */ + #ifdef HAVE_ECC + case ECDSAk: + { + int ret; + byte seq[5]; + int pubLen = length + 1 + SetLength(length, seq); + byte* publicKey; + + if (cert->source[cert->srcIdx] != + (ASN_SEQUENCE | ASN_CONSTRUCTED)) { + if (GetObjectId(cert->source, &cert->srcIdx, + &cert->pkCurveOID, oidCurveType, cert->maxIdx) < 0) + return ASN_PARSE_E; + + if (CheckCurve(cert->pkCurveOID) < 0) + return ECC_CURVE_OID_E; + + /* key header */ + ret = CheckBitString(cert->source, &cert->srcIdx, &length, + cert->maxIdx, 1, NULL); + if (ret != 0) + return ret; + #ifdef HAVE_OCSP + ret = CalcHashId(cert->source + cert->srcIdx, length, + cert->subjectKeyHash); + if (ret != 0) + return ret; + #endif + } + + publicKey = (byte*)XMALLOC(pubLen, cert->heap, + DYNAMIC_TYPE_PUBLIC_KEY); + if (publicKey == NULL) + return MEMORY_E; + XMEMCPY(publicKey, &cert->source[tmpIdx], pubLen); + cert->publicKey = publicKey; + cert->pubKeyStored = 1; + cert->pubKeySize = pubLen; + + cert->srcIdx = tmpIdx + pubLen; + + return 0; + } + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ED25519k: + { + byte* publicKey; + int ret; + + cert->pkCurveOID = ED25519k; + + ret = CheckBitString(cert->source, &cert->srcIdx, &length, + cert->maxIdx, 1, NULL); + if (ret != 0) + return ret; + + #ifdef HAVE_OCSP + ret = CalcHashId(cert->source + cert->srcIdx, length, + cert->subjectKeyHash); + if (ret != 0) + return ret; + #endif + + publicKey = (byte*) XMALLOC(length, cert->heap, + DYNAMIC_TYPE_PUBLIC_KEY); + if (publicKey == NULL) + return MEMORY_E; + XMEMCPY(publicKey, &cert->source[cert->srcIdx], length); + cert->publicKey = publicKey; + cert->pubKeyStored = 1; + cert->pubKeySize = length; + + cert->srcIdx += length; + + return 0; + } + #endif /* HAVE_ED25519 */ + default: + return ASN_UNKNOWN_OID_E; + } +} + +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) +WOLFSSL_LOCAL int wc_OBJ_sn2nid(const char *sn) +{ + static const struct { + const char *sn; + int nid; + } sn2nid[] = { + {WOLFSSL_COMMON_NAME, NID_commonName}, + {WOLFSSL_COUNTRY_NAME, NID_countryName}, + {WOLFSSL_LOCALITY_NAME, NID_localityName}, + {WOLFSSL_STATE_NAME, NID_stateOrProvinceName}, + {WOLFSSL_ORG_NAME, NID_organizationName}, + {WOLFSSL_ORGUNIT_NAME, NID_organizationalUnitName}, + {WOLFSSL_EMAIL_ADDR, NID_emailAddress}, + {NULL, -1}}; + + int i; + WOLFSSL_ENTER("OBJ_osn2nid"); + #ifdef HAVE_ECC + /* Nginx uses this OpenSSL string. */ + if (XSTRNCMP(sn, "prime256v1", 10) == 0) + sn = "SECP256R1"; + if (XSTRNCMP(sn, "secp384r1", 10) == 0) + sn = "SECP384R1"; + /* find based on name and return NID */ + for (i = 0; i < ecc_sets[i].size; i++) { + if (XSTRNCMP(sn, ecc_sets[i].name, ECC_MAXNAME) == 0) { + return ecc_sets[i].id; + } + } + #endif + + for(i=0; sn2nid[i].sn != NULL; i++) { + if(XSTRNCMP(sn, sn2nid[i].sn, XSTRLEN(sn2nid[i].sn)) == 0) { + return sn2nid[i].nid; + } + } + + return NID_undef; +} +#endif + +/* Routine for calculating hashId */ +int CalcHashId(const byte* data, word32 len, byte* hash) +{ + int ret = NOT_COMPILED_IN; + +#ifdef WOLF_CRYPTO_CB + /* try to use a registered crypto callback */ + ret = wc_CryptoCb_Sha256Hash(NULL, data, len, hash); + if (ret != CRYPTOCB_UNAVAILABLE) + return ret; + /* fall-through when unavailable */ +#endif + +#if defined(NO_SHA) && !defined(NO_SHA256) + ret = wc_Sha256Hash(data, len, hash); +#elif !defined(NO_SHA) + ret = wc_ShaHash(data, len, hash); +#endif + + return ret; +} + +/* process NAME, either issuer or subject */ +static int GetName(DecodedCert* cert, int nameType) +{ + int length; /* length of all distinguished names */ + int dummy; + int ret; + char* full; + byte* hash; + word32 idx; + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + DecodedName* dName = + (nameType == ISSUER) ? &cert->issuerName : &cert->subjectName; + int dcnum = 0; + #ifdef OPENSSL_EXTRA + int count = 0; + #endif + #endif /* OPENSSL_EXTRA */ + + WOLFSSL_MSG("Getting Cert Name"); + + if (nameType == ISSUER) { + full = cert->issuer; + hash = cert->issuerHash; + } + else { + full = cert->subject; + hash = cert->subjectHash; + } + + if (cert->srcIdx >= cert->maxIdx) { + return BUFFER_E; + } + + if (cert->source[cert->srcIdx] == ASN_OBJECT_ID) { + WOLFSSL_MSG("Trying optional prefix..."); + + if (SkipObjectId(cert->source, &cert->srcIdx, cert->maxIdx) < 0) + return ASN_PARSE_E; + WOLFSSL_MSG("Got optional prefix"); + } + + /* For OCSP, RFC2560 section 4.1.1 states the issuer hash should be + * calculated over the entire DER encoding of the Name field, including + * the tag and length. */ + idx = cert->srcIdx; + if (GetSequence(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0) + return ASN_PARSE_E; + + ret = CalcHashId(&cert->source[idx], length + cert->srcIdx - idx, hash); + if (ret != 0) + return ret; + + length += cert->srcIdx; + idx = 0; + +#if defined(HAVE_PKCS7) || defined(WOLFSSL_CERT_EXT) + /* store pointer to raw issuer */ + if (nameType == ISSUER) { + cert->issuerRaw = &cert->source[cert->srcIdx]; + cert->issuerRawLen = length - cert->srcIdx; + } +#endif +#ifndef IGNORE_NAME_CONSTRAINTS + if (nameType == SUBJECT) { + cert->subjectRaw = &cert->source[cert->srcIdx]; + cert->subjectRawLen = length - cert->srcIdx; + } +#endif + + while (cert->srcIdx < (word32)length) { + byte b = 0; + byte joint[3]; + byte tooBig = FALSE; + int oidSz; + + if (GetSet(cert->source, &cert->srcIdx, &dummy, cert->maxIdx) < 0) { + WOLFSSL_MSG("Cert name lacks set header, trying sequence"); + } + + if (GetSequence(cert->source, &cert->srcIdx, &dummy, cert->maxIdx) <= 0) + return ASN_PARSE_E; + + ret = GetASNObjectId(cert->source, &cert->srcIdx, &oidSz, cert->maxIdx); + if (ret != 0) + return ret; + + /* make sure there is room for joint */ + if ((cert->srcIdx + sizeof(joint)) > cert->maxIdx) + return ASN_PARSE_E; + + XMEMCPY(joint, &cert->source[cert->srcIdx], sizeof(joint)); + + /* v1 name types */ + if (joint[0] == 0x55 && joint[1] == 0x04) { + const char* copy = NULL; + int strLen = 0; + byte id; + + cert->srcIdx += 3; + id = joint[2]; + if (GetHeader(cert->source, &b, &cert->srcIdx, &strLen, + cert->maxIdx, 1) < 0) { + return ASN_PARSE_E; + } + + if ( (strLen + 14) > (int)(ASN_NAME_MAX - idx)) { + /* include biggest pre fix header too 4 = "/serialNumber=" */ + WOLFSSL_MSG("ASN Name too big, skipping"); + tooBig = TRUE; + } + + if (id == ASN_COMMON_NAME) { + if (nameType == SUBJECT) { + cert->subjectCN = (char *)&cert->source[cert->srcIdx]; + cert->subjectCNLen = strLen; + cert->subjectCNEnc = b; + } + + copy = WOLFSSL_COMMON_NAME; + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + dName->cnIdx = cert->srcIdx; + dName->cnLen = strLen; + #endif /* OPENSSL_EXTRA */ + } + else if (id == ASN_SUR_NAME) { + copy = WOLFSSL_SUR_NAME; + #ifdef WOLFSSL_CERT_GEN + if (nameType == SUBJECT) { + cert->subjectSN = (char*)&cert->source[cert->srcIdx]; + cert->subjectSNLen = strLen; + cert->subjectSNEnc = b; + } + #endif /* WOLFSSL_CERT_GEN */ + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + dName->snIdx = cert->srcIdx; + dName->snLen = strLen; + #endif /* OPENSSL_EXTRA */ + } + else if (id == ASN_COUNTRY_NAME) { + copy = WOLFSSL_COUNTRY_NAME; + #ifdef WOLFSSL_CERT_GEN + if (nameType == SUBJECT) { + cert->subjectC = (char*)&cert->source[cert->srcIdx]; + cert->subjectCLen = strLen; + cert->subjectCEnc = b; + } + #endif /* WOLFSSL_CERT_GEN */ + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + dName->cIdx = cert->srcIdx; + dName->cLen = strLen; + #endif /* OPENSSL_EXTRA */ + } + else if (id == ASN_LOCALITY_NAME) { + copy = WOLFSSL_LOCALITY_NAME; + #ifdef WOLFSSL_CERT_GEN + if (nameType == SUBJECT) { + cert->subjectL = (char*)&cert->source[cert->srcIdx]; + cert->subjectLLen = strLen; + cert->subjectLEnc = b; + } + #endif /* WOLFSSL_CERT_GEN */ + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + dName->lIdx = cert->srcIdx; + dName->lLen = strLen; + #endif /* OPENSSL_EXTRA */ + } + else if (id == ASN_STATE_NAME) { + copy = WOLFSSL_STATE_NAME; + #ifdef WOLFSSL_CERT_GEN + if (nameType == SUBJECT) { + cert->subjectST = (char*)&cert->source[cert->srcIdx]; + cert->subjectSTLen = strLen; + cert->subjectSTEnc = b; + } + #endif /* WOLFSSL_CERT_GEN */ + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + dName->stIdx = cert->srcIdx; + dName->stLen = strLen; + #endif /* OPENSSL_EXTRA */ + } + else if (id == ASN_ORG_NAME) { + copy = WOLFSSL_ORG_NAME; + #ifdef WOLFSSL_CERT_GEN + if (nameType == SUBJECT) { + cert->subjectO = (char*)&cert->source[cert->srcIdx]; + cert->subjectOLen = strLen; + cert->subjectOEnc = b; + } + #endif /* WOLFSSL_CERT_GEN */ + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + dName->oIdx = cert->srcIdx; + dName->oLen = strLen; + #endif /* OPENSSL_EXTRA */ + } + else if (id == ASN_ORGUNIT_NAME) { + copy = WOLFSSL_ORGUNIT_NAME; + #ifdef WOLFSSL_CERT_GEN + if (nameType == SUBJECT) { + cert->subjectOU = (char*)&cert->source[cert->srcIdx]; + cert->subjectOULen = strLen; + cert->subjectOUEnc = b; + } + #endif /* WOLFSSL_CERT_GEN */ + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + dName->ouIdx = cert->srcIdx; + dName->ouLen = strLen; + #endif /* OPENSSL_EXTRA */ + } + else if (id == ASN_SERIAL_NUMBER) { + copy = WOLFSSL_SERIAL_NUMBER; + #ifdef WOLFSSL_CERT_GEN + if (nameType == SUBJECT) { + cert->subjectSND = (char*)&cert->source[cert->srcIdx]; + cert->subjectSNDLen = strLen; + cert->subjectSNDEnc = b; + } + #endif /* WOLFSSL_CERT_GEN */ + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + dName->snIdx = cert->srcIdx; + dName->snLen = strLen; + #endif /* OPENSSL_EXTRA */ + } + #ifdef WOLFSSL_CERT_EXT + else if (id == ASN_BUS_CAT) { + copy = WOLFSSL_BUS_CAT; + #ifdef WOLFSSL_CERT_GEN + if (nameType == SUBJECT) { + cert->subjectBC = (char*)&cert->source[cert->srcIdx]; + cert->subjectBCLen = strLen; + cert->subjectBCEnc = b; + } + #endif /* WOLFSSL_CERT_GEN */ + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + dName->bcIdx = cert->srcIdx; + dName->bcLen = strLen; + #endif /* OPENSSL_EXTRA */ + } + #endif /* WOLFSSL_CERT_EXT */ + if (copy && !tooBig) { + XMEMCPY(&full[idx], copy, XSTRLEN(copy)); + idx += (word32)XSTRLEN(copy); + #ifdef WOLFSSL_WPAS + full[idx] = '='; + idx++; + #endif + XMEMCPY(&full[idx], &cert->source[cert->srcIdx], strLen); + idx += strLen; + #if defined(OPENSSL_EXTRA) + /* store order that DN was parsed */ + dName->loc[count++] = id; + #endif + } + + cert->srcIdx += strLen; + } + #ifdef WOLFSSL_CERT_EXT + else if ((0 == XMEMCMP(&cert->source[cert->srcIdx], ASN_JOI_PREFIX, + XSTRLEN(ASN_JOI_PREFIX))) && + ((cert->source[cert->srcIdx + XSTRLEN(ASN_JOI_PREFIX)] == + ASN_JOI_C) || + (cert->source[cert->srcIdx + XSTRLEN(ASN_JOI_PREFIX)] == + ASN_JOI_ST))) + { + int strLen; + byte id; + const char* copy = NULL; + + cert->srcIdx += 10; + id = cert->source[cert->srcIdx++]; + b = cert->source[cert->srcIdx++]; /* encoding */ + + if (GetLength(cert->source, &cert->srcIdx, &strLen, + cert->maxIdx) < 0) + return ASN_PARSE_E; + + if ((strLen + strlen(WOLFSSL_JOI_ST)) > (ASN_NAME_MAX - idx)) { + WOLFSSL_MSG("ASN Name too big, skipping"); + tooBig = TRUE; + } + + /* Check for jurisdiction of incorporation country name */ + if (id == ASN_JOI_C) { + copy = WOLFSSL_JOI_C; + #ifdef WOLFSSL_CERT_GEN + if (nameType == SUBJECT) { + cert->subjectJC = (char*)&cert->source[cert->srcIdx]; + cert->subjectJCLen = strLen; + cert->subjectJCEnc = b; + } + #endif /* WOLFSSL_CERT_GEN */ + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + dName->jcIdx = cert->srcIdx; + dName->jcLen = strLen; + #endif /* OPENSSL_EXTRA */ + } + + /* Check for jurisdiction of incorporation state name */ + else if (id == ASN_JOI_ST) { + copy = WOLFSSL_JOI_ST; + #ifdef WOLFSSL_CERT_GEN + if (nameType == SUBJECT) { + cert->subjectJS = (char*)&cert->source[cert->srcIdx]; + cert->subjectJSLen = strLen; + cert->subjectJSEnc = b; + } + #endif /* WOLFSSL_CERT_GEN */ + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + dName->jsIdx = cert->srcIdx; + dName->jsLen = strLen; + #endif /* OPENSSL_EXTRA */ + } + + if ((copy != NULL) && (tooBig != 1)) { + XMEMCPY(&full[idx], copy, XSTRLEN(copy)); + idx += (word32)XSTRLEN(copy); + #ifdef WOLFSSL_WPAS + full[idx] = '='; + idx++; + #endif + XMEMCPY(&full[idx], &cert->source[cert->srcIdx], strLen); + idx += strLen; + #if defined(OPENSSL_EXTRA) + /* store order that DN was parsed */ + dName->loc[count++] = id; + #endif + } + + cert->srcIdx += strLen; + } + #endif /* WOLFSSL_CERT_EXT */ + else { + /* skip */ + byte email = FALSE; + byte pilot = FALSE; + byte id = 0; + int adv; + + if (joint[0] == 0x2a && joint[1] == 0x86) /* email id hdr */ + email = TRUE; + + if (joint[0] == 0x9 && joint[1] == 0x92) { /* uid id hdr */ + /* last value of OID is the type of pilot attribute */ + id = cert->source[cert->srcIdx + oidSz - 1]; + pilot = TRUE; + } + + cert->srcIdx += oidSz + 1; + + if (GetLength(cert->source, &cert->srcIdx, &adv, cert->maxIdx) < 0) + return ASN_PARSE_E; + + if (adv > (int)(ASN_NAME_MAX - idx)) { + WOLFSSL_MSG("ASN name too big, skipping"); + tooBig = TRUE; + } + + if (email) { + if ( (14 + adv) > (int)(ASN_NAME_MAX - idx)) { + WOLFSSL_MSG("ASN name too big, skipping"); + tooBig = TRUE; + } + if (!tooBig) { + XMEMCPY(&full[idx], "/emailAddress=", 14); + idx += 14; + } + + #ifdef WOLFSSL_CERT_GEN + if (nameType == SUBJECT) { + cert->subjectEmail = (char*)&cert->source[cert->srcIdx]; + cert->subjectEmailLen = adv; + } + #endif /* WOLFSSL_CERT_GEN */ + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + dName->emailIdx = cert->srcIdx; + dName->emailLen = adv; + #endif /* OPENSSL_EXTRA */ + #ifndef IGNORE_NAME_CONSTRAINTS + { + DNS_entry* emailName = NULL; + + emailName = (DNS_entry*)XMALLOC(sizeof(DNS_entry), + cert->heap, DYNAMIC_TYPE_ALTNAME); + if (emailName == NULL) { + WOLFSSL_MSG("\tOut of Memory"); + return MEMORY_E; + } + emailName->type = 0; + emailName->name = (char*)XMALLOC(adv + 1, + cert->heap, DYNAMIC_TYPE_ALTNAME); + if (emailName->name == NULL) { + WOLFSSL_MSG("\tOut of Memory"); + XFREE(emailName, cert->heap, DYNAMIC_TYPE_ALTNAME); + return MEMORY_E; + } + emailName->len = adv; + XMEMCPY(emailName->name, + &cert->source[cert->srcIdx], adv); + emailName->name[adv] = '\0'; + + emailName->next = cert->altEmailNames; + cert->altEmailNames = emailName; + } + #endif /* IGNORE_NAME_CONSTRAINTS */ + if (!tooBig) { + XMEMCPY(&full[idx], &cert->source[cert->srcIdx], adv); + idx += adv; + #if defined(OPENSSL_EXTRA) + /* store order that DN was parsed */ + dName->loc[count++] = ASN_EMAIL_NAME; + #endif + } + } + + if (pilot) { + if ( (5 + adv) > (int)(ASN_NAME_MAX - idx)) { + WOLFSSL_MSG("ASN name too big, skipping"); + tooBig = TRUE; + } + if (!tooBig) { + switch (id) { + case ASN_USER_ID: + XMEMCPY(&full[idx], "/UID=", 5); + idx += 5; + #if defined(OPENSSL_EXTRA) || \ + defined(OPENSSL_EXTRA_X509_SMALL) + dName->uidIdx = cert->srcIdx; + dName->uidLen = adv; + + #ifdef OPENSSL_EXTRA + /* store order that DN was parsed */ + dName->loc[count++] = ASN_USER_ID; + #endif + #endif /* OPENSSL_EXTRA */ + break; + + case ASN_DOMAIN_COMPONENT: + XMEMCPY(&full[idx], "/DC=", 4); + idx += 4; + #if defined(OPENSSL_EXTRA) || \ + defined(OPENSSL_EXTRA_X509_SMALL) + dName->dcIdx[dcnum] = cert->srcIdx; + dName->dcLen[dcnum] = adv; + dName->dcNum = dcnum + 1; + dcnum++; + + #ifdef OPENSSL_EXTRA + /* store order that DN was parsed */ + dName->loc[count++] = ASN_DOMAIN_COMPONENT; + #endif + #endif /* OPENSSL_EXTRA */ + break; + + default: + WOLFSSL_MSG("Unknown pilot attribute type"); + return ASN_PARSE_E; + } + XMEMCPY(&full[idx], &cert->source[cert->srcIdx], adv); + idx += adv; + } + } + + cert->srcIdx += adv; + } + } + full[idx++] = 0; + #if defined(OPENSSL_EXTRA) + /* store order that DN was parsed */ + dName->locSz = count; + #endif + + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + { + int totalLen = 0; + int i = 0; + + if (dName->cnLen != 0) + totalLen += dName->cnLen + 4; + if (dName->snLen != 0) + totalLen += dName->snLen + 4; + if (dName->cLen != 0) + totalLen += dName->cLen + 3; + if (dName->lLen != 0) + totalLen += dName->lLen + 3; + if (dName->stLen != 0) + totalLen += dName->stLen + 4; + if (dName->oLen != 0) + totalLen += dName->oLen + 3; + if (dName->ouLen != 0) + totalLen += dName->ouLen + 4; + if (dName->emailLen != 0) + totalLen += dName->emailLen + 14; + if (dName->uidLen != 0) + totalLen += dName->uidLen + 5; + if (dName->serialLen != 0) + totalLen += dName->serialLen + 14; + if (dName->dcNum != 0){ + for (i = 0;i < dName->dcNum;i++) + totalLen += dName->dcLen[i] + 4; + } + + dName->fullName = (char*)XMALLOC(totalLen + 1, cert->heap, + DYNAMIC_TYPE_X509); + if (dName->fullName != NULL) { + idx = 0; + + if (dName->cnLen != 0) { + dName->entryCount++; + XMEMCPY(&dName->fullName[idx], WOLFSSL_COMMON_NAME, 4); + dName->cnNid = wc_OBJ_sn2nid((const char *)WOLFSSL_COMMON_NAME); + idx += 4; + XMEMCPY(&dName->fullName[idx], + &cert->source[dName->cnIdx], dName->cnLen); + dName->cnIdx = idx; + idx += dName->cnLen; + } + if (dName->snLen != 0) { + dName->entryCount++; + XMEMCPY(&dName->fullName[idx], WOLFSSL_SUR_NAME, 4); + dName->snNid = wc_OBJ_sn2nid((const char *)WOLFSSL_SUR_NAME); + idx += 4; + XMEMCPY(&dName->fullName[idx], + &cert->source[dName->snIdx], dName->snLen); + dName->snIdx = idx; + idx += dName->snLen; + } + if (dName->cLen != 0) { + dName->entryCount++; + XMEMCPY(&dName->fullName[idx], WOLFSSL_COUNTRY_NAME, 3); + dName->cNid = wc_OBJ_sn2nid((const char *)WOLFSSL_COUNTRY_NAME); + idx += 3; + XMEMCPY(&dName->fullName[idx], + &cert->source[dName->cIdx], dName->cLen); + dName->cIdx = idx; + idx += dName->cLen; + } + if (dName->lLen != 0) { + dName->entryCount++; + XMEMCPY(&dName->fullName[idx], WOLFSSL_LOCALITY_NAME, 3); + dName->lNid = wc_OBJ_sn2nid((const char *)WOLFSSL_LOCALITY_NAME); + idx += 3; + XMEMCPY(&dName->fullName[idx], + &cert->source[dName->lIdx], dName->lLen); + dName->lIdx = idx; + idx += dName->lLen; + } + if (dName->stLen != 0) { + dName->entryCount++; + XMEMCPY(&dName->fullName[idx], WOLFSSL_STATE_NAME, 4); + dName->stNid = wc_OBJ_sn2nid((const char *)WOLFSSL_STATE_NAME); + idx += 4; + XMEMCPY(&dName->fullName[idx], + &cert->source[dName->stIdx], dName->stLen); + dName->stIdx = idx; + idx += dName->stLen; + } + if (dName->oLen != 0) { + dName->entryCount++; + XMEMCPY(&dName->fullName[idx], WOLFSSL_ORG_NAME, 3); + dName->oNid = wc_OBJ_sn2nid((const char *)WOLFSSL_ORG_NAME); + idx += 3; + XMEMCPY(&dName->fullName[idx], + &cert->source[dName->oIdx], dName->oLen); + dName->oIdx = idx; + idx += dName->oLen; + } + if (dName->ouLen != 0) { + dName->entryCount++; + XMEMCPY(&dName->fullName[idx], WOLFSSL_ORGUNIT_NAME, 4); + dName->ouNid = wc_OBJ_sn2nid((const char *)WOLFSSL_ORGUNIT_NAME); + idx += 4; + XMEMCPY(&dName->fullName[idx], + &cert->source[dName->ouIdx], dName->ouLen); + dName->ouIdx = idx; + idx += dName->ouLen; + } + if (dName->emailLen != 0) { + dName->entryCount++; + XMEMCPY(&dName->fullName[idx], "/emailAddress=", 14); + dName->emailNid = wc_OBJ_sn2nid((const char *)"/emailAddress="); + idx += 14; + XMEMCPY(&dName->fullName[idx], + &cert->source[dName->emailIdx], dName->emailLen); + dName->emailIdx = idx; + idx += dName->emailLen; + } + for (i = 0;i < dName->dcNum;i++){ + if (dName->dcLen[i] != 0) { + dName->entryCount++; + XMEMCPY(&dName->fullName[idx], WOLFSSL_DOMAIN_COMPONENT, 4); + idx += 4; + XMEMCPY(&dName->fullName[idx], + &cert->source[dName->dcIdx[i]], dName->dcLen[i]); + dName->dcIdx[i] = idx; + idx += dName->dcLen[i]; + } + } + if (dName->uidLen != 0) { + dName->entryCount++; + XMEMCPY(&dName->fullName[idx], "/UID=", 5); + dName->uidNid = wc_OBJ_sn2nid((const char *)"/UID="); + idx += 5; + XMEMCPY(&dName->fullName[idx], + &cert->source[dName->uidIdx], dName->uidLen); + dName->uidIdx = idx; + idx += dName->uidLen; + } + if (dName->serialLen != 0) { + dName->entryCount++; + XMEMCPY(&dName->fullName[idx], WOLFSSL_SERIAL_NUMBER, 14); + dName->serialNid = wc_OBJ_sn2nid((const char *)WOLFSSL_SERIAL_NUMBER); + idx += 14; + XMEMCPY(&dName->fullName[idx], + &cert->source[dName->serialIdx], dName->serialLen); + dName->serialIdx = idx; + idx += dName->serialLen; + } + dName->fullName[idx] = '\0'; + dName->fullNameLen = totalLen; + } + } + #endif /* OPENSSL_EXTRA */ + + return 0; +} + + +#ifndef NO_ASN_TIME + +/* two byte date/time, add to value */ +static WC_INLINE void GetTime(int* value, const byte* date, int* idx) +{ + int i = *idx; + + *value += btoi(date[i++]) * 10; + *value += btoi(date[i++]); + + *idx = i; +} + +int ExtractDate(const unsigned char* date, unsigned char format, + struct tm* certTime, int* idx) +{ + XMEMSET(certTime, 0, sizeof(struct tm)); + + if (format == ASN_UTC_TIME) { + if (btoi(date[0]) >= 5) + certTime->tm_year = 1900; + else + certTime->tm_year = 2000; + } + else { /* format == GENERALIZED_TIME */ + certTime->tm_year += btoi(date[*idx]) * 1000; *idx = *idx + 1; + certTime->tm_year += btoi(date[*idx]) * 100; *idx = *idx + 1; + } + + /* adjust tm_year, tm_mon */ + GetTime((int*)&certTime->tm_year, date, idx); certTime->tm_year -= 1900; + GetTime((int*)&certTime->tm_mon, date, idx); certTime->tm_mon -= 1; + GetTime((int*)&certTime->tm_mday, date, idx); + GetTime((int*)&certTime->tm_hour, date, idx); + GetTime((int*)&certTime->tm_min, date, idx); + GetTime((int*)&certTime->tm_sec, date, idx); + + return 1; +} + + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_MYSQL_COMPATIBLE) || \ + defined(OPENSSL_EXTRA) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) +int GetTimeString(byte* date, int format, char* buf, int len) +{ + struct tm t; + int idx = 0; + + if (!ExtractDate(date, (unsigned char)format, &t, &idx)) { + return 0; + } + + if (date[idx] != 'Z') { + WOLFSSL_MSG("UTCtime, not Zulu") ; + return 0; + } + + /* place month in buffer */ + buf[0] = '\0'; + switch(t.tm_mon) { + case 0: XSTRNCAT(buf, "Jan ", 5); break; + case 1: XSTRNCAT(buf, "Feb ", 5); break; + case 2: XSTRNCAT(buf, "Mar ", 5); break; + case 3: XSTRNCAT(buf, "Apr ", 5); break; + case 4: XSTRNCAT(buf, "May ", 5); break; + case 5: XSTRNCAT(buf, "Jun ", 5); break; + case 6: XSTRNCAT(buf, "Jul ", 5); break; + case 7: XSTRNCAT(buf, "Aug ", 5); break; + case 8: XSTRNCAT(buf, "Sep ", 5); break; + case 9: XSTRNCAT(buf, "Oct ", 5); break; + case 10: XSTRNCAT(buf, "Nov ", 5); break; + case 11: XSTRNCAT(buf, "Dec ", 5); break; + default: + return 0; + + } + idx = 4; /* use idx now for char buffer */ + + XSNPRINTF(buf + idx, len - idx, "%2d %02d:%02d:%02d %d GMT", + t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec, t.tm_year + 1900); + + return 1; +} +#endif /* OPENSSL_ALL || WOLFSSL_MYSQL_COMPATIBLE || WOLFSSL_NGINX || WOLFSSL_HAPROXY */ + + +#if !defined(NO_ASN_TIME) && defined(HAVE_PKCS7) + +/* Set current time string, either UTC or GeneralizedTime. + * (void*) tm should be a pointer to time_t, output is placed in buf. + * + * Return time string length placed in buf on success, negative on error */ +int GetAsnTimeString(void* currTime, byte* buf, word32 len) +{ + struct tm* ts = NULL; + struct tm* tmpTime = NULL; +#if defined(NEED_TMP_TIME) + struct tm tmpTimeStorage; + tmpTime = &tmpTimeStorage; +#else + (void)tmpTime; +#endif + byte* data_ptr = buf; + word32 data_len = 0; + int year, mon, day, hour, mini, sec; + + WOLFSSL_ENTER("SetAsnTimeString"); + + if (buf == NULL || len == 0) + return BAD_FUNC_ARG; + + ts = (struct tm *)XGMTIME((time_t*)currTime, tmpTime); + if (ts == NULL){ + WOLFSSL_MSG("failed to get time data."); + return ASN_TIME_E; + } + + /* Note ASN_UTC_TIME_SIZE and ASN_GENERALIZED_TIME_SIZE include space for + * the null terminator. ASN encoded values leave off the terminator. */ + + if (ts->tm_year >= 50 && ts->tm_year < 150) { + /* UTC Time */ + char utc_str[ASN_UTC_TIME_SIZE]; + data_len = ASN_UTC_TIME_SIZE - 1 + 2; + + if (len < data_len) + return BUFFER_E; + + if (ts->tm_year >= 50 && ts->tm_year < 100) { + year = ts->tm_year; + } else if (ts->tm_year >= 100 && ts->tm_year < 150) { + year = ts->tm_year - 100; + } + else { + WOLFSSL_MSG("unsupported year range"); + return BAD_FUNC_ARG; + } + mon = ts->tm_mon + 1; + day = ts->tm_mday; + hour = ts->tm_hour; + mini = ts->tm_min; + sec = ts->tm_sec; + XSNPRINTF((char *)utc_str, ASN_UTC_TIME_SIZE, + "%02d%02d%02d%02d%02d%02dZ", year, mon, day, hour, mini, sec); + *data_ptr = (byte) ASN_UTC_TIME; data_ptr++; + /* -1 below excludes null terminator */ + *data_ptr = (byte) ASN_UTC_TIME_SIZE - 1; data_ptr++; + XMEMCPY(data_ptr,(byte *)utc_str, ASN_UTC_TIME_SIZE - 1); + + } else { + /* GeneralizedTime */ + char gt_str[ASN_GENERALIZED_TIME_SIZE]; + data_len = ASN_GENERALIZED_TIME_SIZE - 1 + 2; + + if (len < data_len) + return BUFFER_E; + + year = ts->tm_year + 1900; + mon = ts->tm_mon + 1; + day = ts->tm_mday; + hour = ts->tm_hour; + mini = ts->tm_min; + sec = ts->tm_sec; + XSNPRINTF((char *)gt_str, ASN_GENERALIZED_TIME_SIZE, + "%4d%02d%02d%02d%02d%02dZ", year, mon, day, hour, mini, sec); + *data_ptr = (byte) ASN_GENERALIZED_TIME; data_ptr++; + /* -1 below excludes null terminator */ + *data_ptr = (byte) ASN_GENERALIZED_TIME_SIZE - 1; data_ptr++; + XMEMCPY(data_ptr,(byte *)gt_str, ASN_GENERALIZED_TIME_SIZE - 1); + } + + return data_len; +} + +#endif /* !NO_ASN_TIME && HAVE_PKCS7 */ + + +#if defined(USE_WOLF_VALIDDATE) + +/* to the second */ +static int DateGreaterThan(const struct tm* a, const struct tm* b) +{ + if (a->tm_year > b->tm_year) + return 1; + + if (a->tm_year == b->tm_year && a->tm_mon > b->tm_mon) + return 1; + + if (a->tm_year == b->tm_year && a->tm_mon == b->tm_mon && + a->tm_mday > b->tm_mday) + return 1; + + if (a->tm_year == b->tm_year && a->tm_mon == b->tm_mon && + a->tm_mday == b->tm_mday && a->tm_hour > b->tm_hour) + return 1; + + if (a->tm_year == b->tm_year && a->tm_mon == b->tm_mon && + a->tm_mday == b->tm_mday && a->tm_hour == b->tm_hour && + a->tm_min > b->tm_min) + return 1; + + if (a->tm_year == b->tm_year && a->tm_mon == b->tm_mon && + a->tm_mday == b->tm_mday && a->tm_hour == b->tm_hour && + a->tm_min == b->tm_min && a->tm_sec > b->tm_sec) + return 1; + + return 0; /* false */ +} + + +static WC_INLINE int DateLessThan(const struct tm* a, const struct tm* b) +{ + return DateGreaterThan(b,a); +} + +/* like atoi but only use first byte */ +/* Make sure before and after dates are valid */ +int ValidateDate(const byte* date, byte format, int dateType) +{ + time_t ltime; + struct tm certTime; + struct tm* localTime; + struct tm* tmpTime = NULL; + int i = 0; + int timeDiff = 0 ; + int diffHH = 0 ; int diffMM = 0 ; + int diffSign = 0 ; + +#if defined(NEED_TMP_TIME) + struct tm tmpTimeStorage; + tmpTime = &tmpTimeStorage; +#else + (void)tmpTime; +#endif + + ltime = XTIME(0); + +#ifdef WOLFSSL_BEFORE_DATE_CLOCK_SKEW + if (dateType == BEFORE) { + WOLFSSL_MSG("Skewing local time for before date check"); + ltime += WOLFSSL_BEFORE_DATE_CLOCK_SKEW; + } +#endif + +#ifdef WOLFSSL_AFTER_DATE_CLOCK_SKEW + if (dateType == AFTER) { + WOLFSSL_MSG("Skewing local time for after date check"); + ltime -= WOLFSSL_AFTER_DATE_CLOCK_SKEW; + } +#endif + + if (!ExtractDate(date, format, &certTime, &i)) { + WOLFSSL_MSG("Error extracting the date"); + return 0; + } + + if ((date[i] == '+') || (date[i] == '-')) { + WOLFSSL_MSG("Using time differential, not Zulu") ; + diffSign = date[i++] == '+' ? 1 : -1 ; + GetTime(&diffHH, date, &i); + GetTime(&diffMM, date, &i); + timeDiff = diffSign * (diffHH*60 + diffMM) * 60 ; + } else if (date[i] != 'Z') { + WOLFSSL_MSG("UTCtime, neither Zulu or time differential") ; + return 0; + } + + ltime -= (time_t)timeDiff ; + localTime = XGMTIME(<ime, tmpTime); + + if (localTime == NULL) { + WOLFSSL_MSG("XGMTIME failed"); + return 0; + } + + if (dateType == BEFORE) { + if (DateLessThan(localTime, &certTime)) { + WOLFSSL_MSG("Date BEFORE check failed"); + return 0; + } + } + else { /* dateType == AFTER */ + if (DateGreaterThan(localTime, &certTime)) { + WOLFSSL_MSG("Date AFTER check failed"); + return 0; + } + } + + return 1; +} +#endif /* USE_WOLF_VALIDDATE */ + +int wc_GetTime(void* timePtr, word32 timeSize) +{ + time_t* ltime = (time_t*)timePtr; + + if (timePtr == NULL) { + return BAD_FUNC_ARG; + } + + if ((word32)sizeof(time_t) > timeSize) { + return BUFFER_E; + } + + *ltime = XTIME(0); + + return 0; +} + +#endif /* !NO_ASN_TIME */ + + +/* Get date buffer, format and length. Returns 0=success or error */ +static int GetDateInfo(const byte* source, word32* idx, const byte** pDate, + byte* pFormat, int* pLength, word32 maxIdx) +{ + int length; + byte format; + + if (source == NULL || idx == NULL) + return BAD_FUNC_ARG; + + /* get ASN format header */ + if (*idx+1 > maxIdx) + return BUFFER_E; + format = source[*idx]; + *idx += 1; + if (format != ASN_UTC_TIME && format != ASN_GENERALIZED_TIME) + return ASN_TIME_E; + + /* get length */ + if (GetLength(source, idx, &length, maxIdx) < 0) + return ASN_PARSE_E; + if (length > MAX_DATE_SIZE || length < MIN_DATE_SIZE) + return ASN_DATE_SZ_E; + + /* return format, date and length */ + if (pFormat) + *pFormat = format; + if (pDate) + *pDate = &source[*idx]; + if (pLength) + *pLength = length; + + *idx += length; + + return 0; +} + +static int GetDate(DecodedCert* cert, int dateType, int verify) +{ + int ret, length; + const byte *datePtr = NULL; + byte date[MAX_DATE_SIZE]; + byte format; + word32 startIdx = 0; + + if (dateType == BEFORE) + cert->beforeDate = &cert->source[cert->srcIdx]; + else + cert->afterDate = &cert->source[cert->srcIdx]; + startIdx = cert->srcIdx; + + ret = GetDateInfo(cert->source, &cert->srcIdx, &datePtr, &format, + &length, cert->maxIdx); + if (ret < 0) + return ret; + + XMEMSET(date, 0, MAX_DATE_SIZE); + XMEMCPY(date, datePtr, length); + + if (dateType == BEFORE) + cert->beforeDateLen = cert->srcIdx - startIdx; + else + cert->afterDateLen = cert->srcIdx - startIdx; + +#ifndef NO_ASN_TIME + if (verify != NO_VERIFY && !XVALIDATE_DATE(date, format, dateType)) { + if (dateType == BEFORE) + return ASN_BEFORE_DATE_E; + else + return ASN_AFTER_DATE_E; + } +#else + (void)verify; +#endif + + return 0; +} + +static int GetValidity(DecodedCert* cert, int verify) +{ + int length; + int badDate = 0; + + if (GetSequence(cert->source, &cert->srcIdx, &length, cert->maxIdx) < 0) + return ASN_PARSE_E; + + if (GetDate(cert, BEFORE, verify) < 0) + badDate = ASN_BEFORE_DATE_E; /* continue parsing */ + + if (GetDate(cert, AFTER, verify) < 0) + return ASN_AFTER_DATE_E; + + if (badDate != 0) + return badDate; + + return 0; +} + + +int wc_GetDateInfo(const byte* certDate, int certDateSz, const byte** date, + byte* format, int* length) +{ + int ret; + word32 idx = 0; + + ret = GetDateInfo(certDate, &idx, date, format, length, certDateSz); + if (ret < 0) + return ret; + + return 0; +} + +#ifndef NO_ASN_TIME +int wc_GetDateAsCalendarTime(const byte* date, int length, byte format, + struct tm* timearg) +{ + int idx = 0; + (void)length; + if (!ExtractDate(date, format, timearg, &idx)) + return ASN_TIME_E; + return 0; +} + +#if defined(WOLFSSL_CERT_GEN) && defined(WOLFSSL_ALT_NAMES) +int wc_GetCertDates(Cert* cert, struct tm* before, struct tm* after) +{ + int ret = 0; + const byte* date; + byte format; + int length; + + if (cert == NULL) + return BAD_FUNC_ARG; + + if (before && cert->beforeDateSz > 0) { + ret = wc_GetDateInfo(cert->beforeDate, cert->beforeDateSz, &date, + &format, &length); + if (ret == 0) + ret = wc_GetDateAsCalendarTime(date, length, format, before); + } + if (after && cert->afterDateSz > 0) { + ret = wc_GetDateInfo(cert->afterDate, cert->afterDateSz, &date, + &format, &length); + if (ret == 0) + ret = wc_GetDateAsCalendarTime(date, length, format, after); + } + + return ret; +} +#endif /* WOLFSSL_CERT_GEN && WOLFSSL_ALT_NAMES */ +#endif /* !NO_ASN_TIME */ + +/* parses certificate up to point of X.509 public key + * + * if cert date is invalid then badDate gets set to error value, otherwise is 0 + * + * returns a negative value on fail case + */ +int wc_GetPubX509(DecodedCert* cert, int verify, int* badDate) +{ + int ret; + + if (cert == NULL || badDate == NULL) + return BAD_FUNC_ARG; + + *badDate = 0; + if ( (ret = GetCertHeader(cert)) < 0) + return ret; + + WOLFSSL_MSG("Got Cert Header"); + + if ( (ret = GetAlgoId(cert->source, &cert->srcIdx, &cert->signatureOID, + oidSigType, cert->maxIdx)) < 0) + return ret; + + WOLFSSL_MSG("Got Algo ID"); + + if ( (ret = GetName(cert, ISSUER)) < 0) + return ret; + + if ( (ret = GetValidity(cert, verify)) < 0) + *badDate = ret; + + if ( (ret = GetName(cert, SUBJECT)) < 0) + return ret; + + WOLFSSL_MSG("Got Subject Name"); + return ret; +} + +int DecodeToKey(DecodedCert* cert, int verify) +{ + int badDate = 0; + int ret; + + if ( (ret = wc_GetPubX509(cert, verify, &badDate)) < 0) + return ret; + + /* Determine if self signed */ + cert->selfSigned = XMEMCMP(cert->issuerHash, + cert->subjectHash, + KEYID_SIZE) == 0 ? 1 : 0; + + if ( (ret = GetKey(cert)) < 0) + return ret; + + WOLFSSL_MSG("Got Key"); + + if (badDate != 0) + return badDate; + + return ret; +} + +static int GetSignature(DecodedCert* cert) +{ + int length; + int ret; + ret = CheckBitString(cert->source, &cert->srcIdx, &length, cert->maxIdx, 1, + NULL); + if (ret != 0) + return ret; + + cert->sigLength = length; + cert->signature = &cert->source[cert->srcIdx]; + cert->srcIdx += cert->sigLength; + + return 0; +} + +static word32 SetOctetString8Bit(word32 len, byte* output) +{ + output[0] = ASN_OCTET_STRING; + output[1] = (byte)len; + return 2; +} + +static word32 SetDigest(const byte* digest, word32 digSz, byte* output) +{ + word32 idx = SetOctetString8Bit(digSz, output); + XMEMCPY(&output[idx], digest, digSz); + + return idx + digSz; +} + + +static word32 BytePrecision(word32 value) +{ + word32 i; + for (i = sizeof(value); i; --i) + if (value >> ((i - 1) * WOLFSSL_BIT_SIZE)) + break; + + return i; +} + + +WOLFSSL_LOCAL word32 SetLength(word32 length, byte* output) +{ + word32 i = 0, j; + + if (length < ASN_LONG_LENGTH) + output[i++] = (byte)length; + else { + output[i++] = (byte)(BytePrecision(length) | ASN_LONG_LENGTH); + + for (j = BytePrecision(length); j; --j) { + output[i] = (byte)(length >> ((j - 1) * WOLFSSL_BIT_SIZE)); + i++; + } + } + + return i; +} + + +WOLFSSL_LOCAL word32 SetSequence(word32 len, byte* output) +{ + output[0] = ASN_SEQUENCE | ASN_CONSTRUCTED; + return SetLength(len, output + 1) + 1; +} + +WOLFSSL_LOCAL word32 SetOctetString(word32 len, byte* output) +{ + output[0] = ASN_OCTET_STRING; + return SetLength(len, output + 1) + 1; +} + +/* Write a set header to output */ +WOLFSSL_LOCAL word32 SetSet(word32 len, byte* output) +{ + output[0] = ASN_SET | ASN_CONSTRUCTED; + return SetLength(len, output + 1) + 1; +} + +WOLFSSL_LOCAL word32 SetImplicit(byte tag, byte number, word32 len, byte* output) +{ + + output[0] = ((tag == ASN_SEQUENCE || tag == ASN_SET) ? ASN_CONSTRUCTED : 0) + | ASN_CONTEXT_SPECIFIC | number; + return SetLength(len, output + 1) + 1; +} + +WOLFSSL_LOCAL word32 SetExplicit(byte number, word32 len, byte* output) +{ + output[0] = ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | number; + return SetLength(len, output + 1) + 1; +} + + +#if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT) + +static int SetCurve(ecc_key* key, byte* output) +{ +#ifdef HAVE_OID_ENCODING + int ret; +#endif + int idx = 0; + word32 oidSz = 0; + + /* validate key */ + if (key == NULL || key->dp == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef HAVE_OID_ENCODING + ret = EncodeObjectId(key->dp->oid, key->dp->oidSz, NULL, &oidSz); + if (ret != 0) { + return ret; + } +#else + oidSz = key->dp->oidSz; +#endif + + idx += SetObjectId(oidSz, output); + +#ifdef HAVE_OID_ENCODING + ret = EncodeObjectId(key->dp->oid, key->dp->oidSz, output+idx, &oidSz); + if (ret != 0) { + return ret; + } +#else + XMEMCPY(output+idx, key->dp->oid, oidSz); +#endif + idx += oidSz; + + return idx; +} + +#endif /* HAVE_ECC && HAVE_ECC_KEY_EXPORT */ + + +#ifdef HAVE_ECC +static WC_INLINE int IsSigAlgoECDSA(int algoOID) +{ + /* ECDSA sigAlgo must not have ASN1 NULL parameters */ + if (algoOID == CTC_SHAwECDSA || algoOID == CTC_SHA256wECDSA || + algoOID == CTC_SHA384wECDSA || algoOID == CTC_SHA512wECDSA) { + return 1; + } + + return 0; +} +#endif + +WOLFSSL_LOCAL word32 SetAlgoID(int algoOID, byte* output, int type, int curveSz) +{ + word32 tagSz, idSz, seqSz, algoSz = 0; + const byte* algoName = 0; + byte ID_Length[1 + MAX_LENGTH_SZ]; + byte seqArray[MAX_SEQ_SZ + 1]; /* add object_id to end */ + + tagSz = (type == oidHashType || + (type == oidSigType + #ifdef HAVE_ECC + && !IsSigAlgoECDSA(algoOID) + #endif + #ifdef HAVE_ED25519 + && algoOID != ED25519k + #endif + ) || + (type == oidKeyType && algoOID == RSAk)) ? 2 : 0; + + algoName = OidFromId(algoOID, type, &algoSz); + + if (algoName == NULL) { + WOLFSSL_MSG("Unknown Algorithm"); + return 0; + } + + idSz = SetObjectId(algoSz, ID_Length); + seqSz = SetSequence(idSz + algoSz + tagSz + curveSz, seqArray); + + XMEMCPY(output, seqArray, seqSz); + XMEMCPY(output + seqSz, ID_Length, idSz); + XMEMCPY(output + seqSz + idSz, algoName, algoSz); + if (tagSz == 2) + SetASNNull(&output[seqSz + idSz + algoSz]); + + return seqSz + idSz + algoSz + tagSz; + +} + + +word32 wc_EncodeSignature(byte* out, const byte* digest, word32 digSz, + int hashOID) +{ + byte digArray[MAX_ENCODED_DIG_SZ]; + byte algoArray[MAX_ALGO_SZ]; + byte seqArray[MAX_SEQ_SZ]; + word32 encDigSz, algoSz, seqSz; + + encDigSz = SetDigest(digest, digSz, digArray); + algoSz = SetAlgoID(hashOID, algoArray, oidHashType, 0); + seqSz = SetSequence(encDigSz + algoSz, seqArray); + + XMEMCPY(out, seqArray, seqSz); + XMEMCPY(out + seqSz, algoArray, algoSz); + XMEMCPY(out + seqSz + algoSz, digArray, encDigSz); + + return encDigSz + algoSz + seqSz; +} + + +#ifndef NO_CERTS + +int wc_GetCTC_HashOID(int type) +{ + int ret; + enum wc_HashType hType; + + hType = wc_HashTypeConvert(type); + ret = wc_HashGetOID(hType); + if (ret < 0) + ret = 0; /* backwards compatibility */ + + return ret; +} + +void InitSignatureCtx(SignatureCtx* sigCtx, void* heap, int devId) +{ + if (sigCtx) { + XMEMSET(sigCtx, 0, sizeof(SignatureCtx)); + sigCtx->devId = devId; + sigCtx->heap = heap; + } +} + +void FreeSignatureCtx(SignatureCtx* sigCtx) +{ + if (sigCtx == NULL) + return; + + if (sigCtx->digest) { + XFREE(sigCtx->digest, sigCtx->heap, DYNAMIC_TYPE_DIGEST); + sigCtx->digest = NULL; + } +#ifndef NO_RSA + if (sigCtx->plain) { + XFREE(sigCtx->plain, sigCtx->heap, DYNAMIC_TYPE_SIGNATURE); + sigCtx->plain = NULL; + } +#endif +#ifndef NO_ASN_CRYPT + if (sigCtx->key.ptr) { + switch (sigCtx->keyOID) { + #ifndef NO_RSA + case RSAk: + wc_FreeRsaKey(sigCtx->key.rsa); + XFREE(sigCtx->key.ptr, sigCtx->heap, DYNAMIC_TYPE_RSA); + break; + #endif /* !NO_RSA */ + #ifdef HAVE_ECC + case ECDSAk: + wc_ecc_free(sigCtx->key.ecc); + XFREE(sigCtx->key.ecc, sigCtx->heap, DYNAMIC_TYPE_ECC); + break; + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ED25519k: + wc_ed25519_free(sigCtx->key.ed25519); + XFREE(sigCtx->key.ed25519, sigCtx->heap, DYNAMIC_TYPE_ED25519); + break; + #endif /* HAVE_ED25519 */ + default: + break; + } /* switch (keyOID) */ + sigCtx->key.ptr = NULL; + } +#endif + + /* reset state, we are done */ + sigCtx->state = SIG_STATE_BEGIN; +} + +#ifndef NO_ASN_CRYPT +static int HashForSignature(const byte* buf, word32 bufSz, word32 sigOID, + byte* digest, int* typeH, int* digestSz, int verify) +{ + int ret = 0; + + (void)verify; + + switch (sigOID) { + #if defined(WOLFSSL_MD2) + case CTC_MD2wRSA: + if (!verify) { + ret = HASH_TYPE_E; + WOLFSSL_MSG("MD2 not supported for signing"); + } + else if ((ret = wc_Md2Hash(buf, bufSz, digest)) == 0) { + *typeH = MD2h; + *digestSz = MD2_DIGEST_SIZE; + } + break; + #endif + #ifndef NO_MD5 + case CTC_MD5wRSA: + if ((ret = wc_Md5Hash(buf, bufSz, digest)) == 0) { + *typeH = MD5h; + *digestSz = WC_MD5_DIGEST_SIZE; + } + break; + #endif + #ifndef NO_SHA + case CTC_SHAwRSA: + case CTC_SHAwDSA: + case CTC_SHAwECDSA: + if ((ret = wc_ShaHash(buf, bufSz, digest)) == 0) { + *typeH = SHAh; + *digestSz = WC_SHA_DIGEST_SIZE; + } + break; + #endif + #ifdef WOLFSSL_SHA224 + case CTC_SHA224wRSA: + case CTC_SHA224wECDSA: + if ((ret = wc_Sha224Hash(buf, bufSz, digest)) == 0) { + *typeH = SHA224h; + *digestSz = WC_SHA224_DIGEST_SIZE; + } + break; + #endif + #ifndef NO_SHA256 + case CTC_SHA256wRSA: + case CTC_SHA256wECDSA: + if ((ret = wc_Sha256Hash(buf, bufSz, digest)) == 0) { + *typeH = SHA256h; + *digestSz = WC_SHA256_DIGEST_SIZE; + } + break; + #endif + #ifdef WOLFSSL_SHA384 + case CTC_SHA384wRSA: + case CTC_SHA384wECDSA: + if ((ret = wc_Sha384Hash(buf, bufSz, digest)) == 0) { + *typeH = SHA384h; + *digestSz = WC_SHA384_DIGEST_SIZE; + } + break; + #endif + #ifdef WOLFSSL_SHA512 + case CTC_SHA512wRSA: + case CTC_SHA512wECDSA: + if ((ret = wc_Sha512Hash(buf, bufSz, digest)) == 0) { + *typeH = SHA512h; + *digestSz = WC_SHA512_DIGEST_SIZE; + } + break; + #endif + case CTC_ED25519: + /* Hashes done in signing operation. + * Two dependent hashes with prefixes performed. + */ + break; + default: + ret = HASH_TYPE_E; + WOLFSSL_MSG("Hash for Signature has unsupported type"); + } + + return ret; +} +#endif /* !NO_ASN_CRYPT */ + +/* Return codes: 0=Success, Negative (see error-crypt.h), ASN_SIG_CONFIRM_E */ +static int ConfirmSignature(SignatureCtx* sigCtx, + const byte* buf, word32 bufSz, + const byte* key, word32 keySz, word32 keyOID, + const byte* sig, word32 sigSz, word32 sigOID) +{ + int ret = 0; + + if (sigCtx == NULL || buf == NULL || bufSz == 0 || key == NULL || + keySz == 0 || sig == NULL || sigSz == 0) { + return BAD_FUNC_ARG; + } + + (void)key; + (void)keySz; + (void)sig; + (void)sigSz; + + WOLFSSL_ENTER("ConfirmSignature"); + +#ifndef NO_ASN_CRYPT + switch (sigCtx->state) { + case SIG_STATE_BEGIN: + { + sigCtx->keyOID = keyOID; /* must set early for cleanup */ + + sigCtx->digest = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, sigCtx->heap, + DYNAMIC_TYPE_DIGEST); + if (sigCtx->digest == NULL) { + ERROR_OUT(MEMORY_E, exit_cs); + } + + sigCtx->state = SIG_STATE_HASH; + } /* SIG_STATE_BEGIN */ + FALL_THROUGH; + + case SIG_STATE_HASH: + { + ret = HashForSignature(buf, bufSz, sigOID, sigCtx->digest, + &sigCtx->typeH, &sigCtx->digestSz, 1); + if (ret != 0) { + goto exit_cs; + } + + sigCtx->state = SIG_STATE_KEY; + } /* SIG_STATE_HASH */ + FALL_THROUGH; + + case SIG_STATE_KEY: + { + switch (keyOID) { + #ifndef NO_RSA + case RSAk: + { + word32 idx = 0; + + sigCtx->key.rsa = (RsaKey*)XMALLOC(sizeof(RsaKey), + sigCtx->heap, DYNAMIC_TYPE_RSA); + sigCtx->plain = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, + sigCtx->heap, DYNAMIC_TYPE_SIGNATURE); + if (sigCtx->key.rsa == NULL || sigCtx->plain == NULL) { + ERROR_OUT(MEMORY_E, exit_cs); + } + if ((ret = wc_InitRsaKey_ex(sigCtx->key.rsa, sigCtx->heap, + sigCtx->devId)) != 0) { + goto exit_cs; + } + if (sigSz > MAX_ENCODED_SIG_SZ) { + WOLFSSL_MSG("Verify Signature is too big"); + ERROR_OUT(BUFFER_E, exit_cs); + } + if ((ret = wc_RsaPublicKeyDecode(key, &idx, sigCtx->key.rsa, + keySz)) != 0) { + WOLFSSL_MSG("ASN Key decode error RSA"); + goto exit_cs; + } + XMEMCPY(sigCtx->plain, sig, sigSz); + sigCtx->out = NULL; + + #ifdef WOLFSSL_ASYNC_CRYPT + sigCtx->asyncDev = &sigCtx->key.rsa->asyncDev; + #endif + break; + } + #endif /* !NO_RSA */ + #ifdef HAVE_ECC + case ECDSAk: + { + word32 idx = 0; + + sigCtx->verify = 0; + sigCtx->key.ecc = (ecc_key*)XMALLOC(sizeof(ecc_key), + sigCtx->heap, DYNAMIC_TYPE_ECC); + if (sigCtx->key.ecc == NULL) { + ERROR_OUT(MEMORY_E, exit_cs); + } + if ((ret = wc_ecc_init_ex(sigCtx->key.ecc, sigCtx->heap, + sigCtx->devId)) < 0) { + goto exit_cs; + } + ret = wc_EccPublicKeyDecode(key, &idx, sigCtx->key.ecc, + keySz); + if (ret < 0) { + WOLFSSL_MSG("ASN Key import error ECC"); + goto exit_cs; + } + #ifdef WOLFSSL_ASYNC_CRYPT + sigCtx->asyncDev = &sigCtx->key.ecc->asyncDev; + #endif + break; + } + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ED25519k: + { + sigCtx->verify = 0; + sigCtx->key.ed25519 = (ed25519_key*)XMALLOC( + sizeof(ed25519_key), sigCtx->heap, + DYNAMIC_TYPE_ED25519); + if (sigCtx->key.ed25519 == NULL) { + ERROR_OUT(MEMORY_E, exit_cs); + } + if ((ret = wc_ed25519_init(sigCtx->key.ed25519)) < 0) { + goto exit_cs; + } + if ((ret = wc_ed25519_import_public(key, keySz, + sigCtx->key.ed25519)) < 0) { + WOLFSSL_MSG("ASN Key import error ED25519"); + goto exit_cs; + } + #ifdef WOLFSSL_ASYNC_CRYPT + sigCtx->asyncDev = &sigCtx->key.ed25519->asyncDev; + #endif + break; + } + #endif + default: + WOLFSSL_MSG("Verify Key type unknown"); + ret = ASN_UNKNOWN_OID_E; + break; + } /* switch (keyOID) */ + + if (ret != 0) { + goto exit_cs; + } + + sigCtx->state = SIG_STATE_DO; + + #ifdef WOLFSSL_ASYNC_CRYPT + if (sigCtx->devId != INVALID_DEVID && sigCtx->asyncDev && sigCtx->asyncCtx) { + /* make sure event is initialized */ + WOLF_EVENT* event = &sigCtx->asyncDev->event; + ret = wolfAsync_EventInit(event, WOLF_EVENT_TYPE_ASYNC_WOLFSSL, + sigCtx->asyncCtx, WC_ASYNC_FLAG_CALL_AGAIN); + } + #endif + } /* SIG_STATE_KEY */ + FALL_THROUGH; + + case SIG_STATE_DO: + { + switch (keyOID) { + #ifndef NO_RSA + case RSAk: + { + #ifdef HAVE_PK_CALLBACKS + if (sigCtx->pkCbRsa) { + ret = sigCtx->pkCbRsa( + sigCtx->plain, sigSz, &sigCtx->out, + key, keySz, + sigCtx->pkCtxRsa); + } + else + #endif /* HAVE_PK_CALLBACKS */ + { + ret = wc_RsaSSL_VerifyInline(sigCtx->plain, sigSz, + &sigCtx->out, sigCtx->key.rsa); + } + break; + } + #endif /* !NO_RSA */ + #ifdef HAVE_ECC + case ECDSAk: + { + #ifdef HAVE_PK_CALLBACKS + if (sigCtx->pkCbEcc) { + ret = sigCtx->pkCbEcc( + sig, sigSz, + sigCtx->digest, sigCtx->digestSz, + key, keySz, &sigCtx->verify, + sigCtx->pkCtxEcc); + } + else + #endif /* HAVE_PK_CALLBACKS */ + { + ret = wc_ecc_verify_hash(sig, sigSz, sigCtx->digest, + sigCtx->digestSz, &sigCtx->verify, + sigCtx->key.ecc); + } + break; + } + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ED25519k: + { + ret = wc_ed25519_verify_msg(sig, sigSz, buf, bufSz, + &sigCtx->verify, sigCtx->key.ed25519); + break; + } + #endif + default: + break; + } /* switch (keyOID) */ + + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + goto exit_cs; + } + #endif + + if (ret < 0) { + /* treat all RSA errors as ASN_SIG_CONFIRM_E */ + ret = ASN_SIG_CONFIRM_E; + goto exit_cs; + } + + sigCtx->state = SIG_STATE_CHECK; + } /* SIG_STATE_DO */ + FALL_THROUGH; + + case SIG_STATE_CHECK: + { + switch (keyOID) { + #ifndef NO_RSA + case RSAk: + { + int encodedSigSz, verifySz; + #ifdef WOLFSSL_SMALL_STACK + byte* encodedSig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, + sigCtx->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (encodedSig == NULL) { + ERROR_OUT(MEMORY_E, exit_cs); + } + #else + byte encodedSig[MAX_ENCODED_SIG_SZ]; + #endif + + verifySz = ret; + + /* make sure we're right justified */ + encodedSigSz = wc_EncodeSignature(encodedSig, + sigCtx->digest, sigCtx->digestSz, sigCtx->typeH); + if (encodedSigSz == verifySz && sigCtx->out != NULL && + XMEMCMP(sigCtx->out, encodedSig, encodedSigSz) == 0) { + ret = 0; + } + else { + WOLFSSL_MSG("RSA SSL verify match encode error"); + ret = ASN_SIG_CONFIRM_E; + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(encodedSig, sigCtx->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + break; + } + #endif /* NO_RSA */ + #ifdef HAVE_ECC + case ECDSAk: + { + if (sigCtx->verify == 1) { + ret = 0; + } + else { + WOLFSSL_MSG("ECC Verify didn't match"); + ret = ASN_SIG_CONFIRM_E; + } + break; + } + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + case ED25519k: + { + if (sigCtx->verify == 1) { + ret = 0; + } + else { + WOLFSSL_MSG("ED25519 Verify didn't match"); + ret = ASN_SIG_CONFIRM_E; + } + break; + } + #endif /* HAVE_ED25519 */ + default: + break; + } /* switch (keyOID) */ + + break; + } /* SIG_STATE_CHECK */ + } /* switch (sigCtx->state) */ + +exit_cs: + +#endif /* !NO_ASN_CRYPT */ + + (void)keyOID; + (void)sigOID; + + WOLFSSL_LEAVE("ConfirmSignature", ret); + +#ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) + return ret; +#endif + + FreeSignatureCtx(sigCtx); + + return ret; +} + + +#ifndef IGNORE_NAME_CONSTRAINTS + +static int MatchBaseName(int type, const char* name, int nameSz, + const char* base, int baseSz) +{ + if (base == NULL || baseSz <= 0 || name == NULL || nameSz <= 0 || + name[0] == '.' || nameSz < baseSz || + (type != ASN_RFC822_TYPE && type != ASN_DNS_TYPE)) + return 0; + + /* If an email type, handle special cases where the base is only + * a domain, or is an email address itself. */ + if (type == ASN_RFC822_TYPE) { + const char* p = NULL; + int count = 0; + + if (base[0] != '.') { + p = base; + count = 0; + + /* find the '@' in the base */ + while (*p != '@' && count < baseSz) { + count++; + p++; + } + + /* No '@' in base, reset p to NULL */ + if (count >= baseSz) + p = NULL; + } + + if (p == NULL) { + /* Base isn't an email address, it is a domain name, + * wind the name forward one character past its '@'. */ + p = name; + count = 0; + while (*p != '@' && count < baseSz) { + count++; + p++; + } + + if (count < baseSz && *p == '@') { + name = p + 1; + nameSz -= count + 1; + } + } + } + + if ((type == ASN_DNS_TYPE || type == ASN_RFC822_TYPE) && base[0] == '.') { + int szAdjust = nameSz - baseSz; + name += szAdjust; + nameSz -= szAdjust; + } + + while (nameSz > 0) { + if (XTOLOWER((unsigned char)*name++) != + XTOLOWER((unsigned char)*base++)) + return 0; + nameSz--; + } + + return 1; +} + + +static int ConfirmNameConstraints(Signer* signer, DecodedCert* cert) +{ + if (signer == NULL || cert == NULL) + return 0; + + /* Check against the excluded list */ + if (signer->excludedNames) { + Base_entry* base = signer->excludedNames; + + while (base != NULL) { + switch (base->type) { + case ASN_DNS_TYPE: + { + DNS_entry* name = cert->altNames; + while (name != NULL) { + if (MatchBaseName(ASN_DNS_TYPE, + name->name, name->len, + base->name, base->nameSz)) { + return 0; + } + name = name->next; + } + break; + } + case ASN_RFC822_TYPE: + { + DNS_entry* name = cert->altEmailNames; + while (name != NULL) { + if (MatchBaseName(ASN_RFC822_TYPE, + name->name, name->len, + base->name, base->nameSz)) { + return 0; + } + name = name->next; + } + break; + } + case ASN_DIR_TYPE: + { + /* allow permitted dirName smaller than actual subject */ + if (cert->subjectRawLen >= base->nameSz && + XMEMCMP(cert->subjectRaw, base->name, + base->nameSz) == 0) { + return 0; + } + break; + } + }; /* switch */ + base = base->next; + } + } + + /* Check against the permitted list */ + if (signer->permittedNames != NULL) { + int needDns = 0; + int matchDns = 0; + int needEmail = 0; + int matchEmail = 0; + int needDir = 0; + int matchDir = 0; + Base_entry* base = signer->permittedNames; + + while (base != NULL) { + switch (base->type) { + case ASN_DNS_TYPE: + { + DNS_entry* name = cert->altNames; + + if (name != NULL) + needDns = 1; + + while (name != NULL) { + matchDns = MatchBaseName(ASN_DNS_TYPE, + name->name, name->len, + base->name, base->nameSz); + name = name->next; + } + break; + } + case ASN_RFC822_TYPE: + { + DNS_entry* name = cert->altEmailNames; + + if (name != NULL) + needEmail = 1; + + while (name != NULL) { + matchEmail = MatchBaseName(ASN_DNS_TYPE, + name->name, name->len, + base->name, base->nameSz); + name = name->next; + } + break; + } + case ASN_DIR_TYPE: + { + /* allow permitted dirName smaller than actual subject */ + needDir = 1; + if (cert->subjectRaw != NULL && + cert->subjectRawLen >= base->nameSz && + XMEMCMP(cert->subjectRaw, base->name, + base->nameSz) == 0) { + matchDir = 1; + } + break; + } + } /* switch */ + base = base->next; + } + + if ((needDns && !matchDns) || + (needEmail && !matchEmail) || + (needDir && !matchDir)) { + return 0; + } + } + + return 1; +} + +#endif /* IGNORE_NAME_CONSTRAINTS */ + +static int DecodeAltNames(const byte* input, int sz, DecodedCert* cert) +{ + word32 idx = 0; + int length = 0; + + WOLFSSL_ENTER("DecodeAltNames"); + + if (GetSequence(input, &idx, &length, sz) < 0) { + WOLFSSL_MSG("\tBad Sequence"); + return ASN_PARSE_E; + } + + cert->weOwnAltNames = 1; + + while (length > 0) { + byte b = input[idx++]; + + length--; + + /* Save DNS Type names in the altNames list. */ + /* Save Other Type names in the cert's OidMap */ + if (b == (ASN_CONTEXT_SPECIFIC | ASN_DNS_TYPE)) { + DNS_entry* dnsEntry; + int strLen; + word32 lenStartIdx = idx; + + if (GetLength(input, &idx, &strLen, sz) < 0) { + WOLFSSL_MSG("\tfail: str length"); + return ASN_PARSE_E; + } + length -= (idx - lenStartIdx); + + dnsEntry = (DNS_entry*)XMALLOC(sizeof(DNS_entry), cert->heap, + DYNAMIC_TYPE_ALTNAME); + if (dnsEntry == NULL) { + WOLFSSL_MSG("\tOut of Memory"); + return MEMORY_E; + } + + dnsEntry->type = ASN_DNS_TYPE; + dnsEntry->name = (char*)XMALLOC(strLen + 1, cert->heap, + DYNAMIC_TYPE_ALTNAME); + if (dnsEntry->name == NULL) { + WOLFSSL_MSG("\tOut of Memory"); + XFREE(dnsEntry, cert->heap, DYNAMIC_TYPE_ALTNAME); + return MEMORY_E; + } + dnsEntry->len = strLen; + XMEMCPY(dnsEntry->name, &input[idx], strLen); + dnsEntry->name[strLen] = '\0'; + + dnsEntry->next = cert->altNames; + cert->altNames = dnsEntry; + + length -= strLen; + idx += strLen; + } + #ifndef IGNORE_NAME_CONSTRAINTS + else if (b == (ASN_CONTEXT_SPECIFIC | ASN_RFC822_TYPE)) { + DNS_entry* emailEntry; + int strLen; + word32 lenStartIdx = idx; + + if (GetLength(input, &idx, &strLen, sz) < 0) { + WOLFSSL_MSG("\tfail: str length"); + return ASN_PARSE_E; + } + length -= (idx - lenStartIdx); + + emailEntry = (DNS_entry*)XMALLOC(sizeof(DNS_entry), cert->heap, + DYNAMIC_TYPE_ALTNAME); + if (emailEntry == NULL) { + WOLFSSL_MSG("\tOut of Memory"); + return MEMORY_E; + } + + emailEntry->type = ASN_RFC822_TYPE; + emailEntry->name = (char*)XMALLOC(strLen + 1, cert->heap, + DYNAMIC_TYPE_ALTNAME); + if (emailEntry->name == NULL) { + WOLFSSL_MSG("\tOut of Memory"); + XFREE(emailEntry, cert->heap, DYNAMIC_TYPE_ALTNAME); + return MEMORY_E; + } + emailEntry->len = strLen; + XMEMCPY(emailEntry->name, &input[idx], strLen); + emailEntry->name[strLen] = '\0'; + + emailEntry->next = cert->altEmailNames; + cert->altEmailNames = emailEntry; + + length -= strLen; + idx += strLen; + } + else if (b == (ASN_CONTEXT_SPECIFIC | ASN_URI_TYPE)) { + DNS_entry* uriEntry; + int strLen; + word32 lenStartIdx = idx; + + WOLFSSL_MSG("\tPutting URI into list but not using"); + if (GetLength(input, &idx, &strLen, sz) < 0) { + WOLFSSL_MSG("\tfail: str length"); + return ASN_PARSE_E; + } + length -= (idx - lenStartIdx); + + /* check that strLen at index is not past input buffer */ + if (strLen + (int)idx > sz) { + return BUFFER_E; + } + + #ifndef WOLFSSL_NO_ASN_STRICT + /* Verify RFC 5280 Sec 4.2.1.6 rule: + "The name MUST NOT be a relative URI" */ + + { + int i; + + /* skip past scheme (i.e http,ftp,...) finding first ':' char */ + for (i = 0; i < strLen; i++) { + if (input[idx + i] == ':') { + break; + } + if (input[idx + i] == '/') { + i = strLen; /* error, found relative path since '/' was + * encountered before ':'. Returning error + * value in next if statement. */ + } + } + + /* test if no ':' char was found and test that the next two + * chars are // to match the pattern "://" */ + if (i >= strLen - 2 || (input[idx + i + 1] != '/' || + input[idx + i + 2] != '/')) { + WOLFSSL_MSG("\tAlt Name must be absolute URI"); + return ASN_ALT_NAME_E; + } + } + #endif + + uriEntry = (DNS_entry*)XMALLOC(sizeof(DNS_entry), cert->heap, + DYNAMIC_TYPE_ALTNAME); + if (uriEntry == NULL) { + WOLFSSL_MSG("\tOut of Memory"); + return MEMORY_E; + } + + uriEntry->type = ASN_URI_TYPE; + uriEntry->name = (char*)XMALLOC(strLen + 1, cert->heap, + DYNAMIC_TYPE_ALTNAME); + if (uriEntry->name == NULL) { + WOLFSSL_MSG("\tOut of Memory"); + XFREE(uriEntry, cert->heap, DYNAMIC_TYPE_ALTNAME); + return MEMORY_E; + } + uriEntry->len = strLen; + XMEMCPY(uriEntry->name, &input[idx], strLen); + uriEntry->name[strLen] = '\0'; + + uriEntry->next = cert->altNames; + cert->altNames = uriEntry; + + length -= strLen; + idx += strLen; + } +#endif /* IGNORE_NAME_CONSTRAINTS */ +#ifdef WOLFSSL_SEP + else if (b == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | ASN_OTHER_TYPE)) + { + int strLen; + word32 lenStartIdx = idx; + word32 oid = 0; + int ret; + + if (GetLength(input, &idx, &strLen, sz) < 0) { + WOLFSSL_MSG("\tfail: other name length"); + return ASN_PARSE_E; + } + /* Consume the rest of this sequence. */ + length -= (strLen + idx - lenStartIdx); + + if (GetObjectId(input, &idx, &oid, oidCertAltNameType, sz) < 0) { + WOLFSSL_MSG("\tbad OID"); + return ASN_PARSE_E; + } + + if (oid != HW_NAME_OID) { + WOLFSSL_MSG("\tincorrect OID"); + return ASN_PARSE_E; + } + + if (input[idx++] != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) { + WOLFSSL_MSG("\twrong type"); + return ASN_PARSE_E; + } + + if (GetLength(input, &idx, &strLen, sz) < 0) { + WOLFSSL_MSG("\tfail: str len"); + return ASN_PARSE_E; + } + + if (GetSequence(input, &idx, &strLen, sz) < 0) { + WOLFSSL_MSG("\tBad Sequence"); + return ASN_PARSE_E; + } + + ret = GetASNObjectId(input, &idx, &strLen, sz); + if (ret != 0) { + WOLFSSL_MSG("\tbad OID"); + return ret; + } + + cert->hwType = (byte*)XMALLOC(strLen, cert->heap, + DYNAMIC_TYPE_X509_EXT); + if (cert->hwType == NULL) { + WOLFSSL_MSG("\tOut of Memory"); + return MEMORY_E; + } + + XMEMCPY(cert->hwType, &input[idx], strLen); + cert->hwTypeSz = strLen; + idx += strLen; + + ret = GetOctetString(input, &idx, &strLen, sz); + if (ret < 0) + return ret; + + cert->hwSerialNum = (byte*)XMALLOC(strLen + 1, cert->heap, + DYNAMIC_TYPE_X509_EXT); + if (cert->hwSerialNum == NULL) { + WOLFSSL_MSG("\tOut of Memory"); + return MEMORY_E; + } + + XMEMCPY(cert->hwSerialNum, &input[idx], strLen); + cert->hwSerialNum[strLen] = '\0'; + cert->hwSerialNumSz = strLen; + idx += strLen; + } + #endif /* WOLFSSL_SEP */ + else { + int strLen; + word32 lenStartIdx = idx; + + WOLFSSL_MSG("\tUnsupported name type, skipping"); + + if (GetLength(input, &idx, &strLen, sz) < 0) { + WOLFSSL_MSG("\tfail: unsupported name length"); + return ASN_PARSE_E; + } + length -= (strLen + idx - lenStartIdx); + idx += strLen; + } + } + return 0; +} + +static int DecodeBasicCaConstraint(const byte* input, int sz, DecodedCert* cert) +{ + word32 idx = 0; + int length = 0; + int ret; + + WOLFSSL_ENTER("DecodeBasicCaConstraint"); + + if (GetSequence(input, &idx, &length, sz) < 0) { + WOLFSSL_MSG("\tfail: bad SEQUENCE"); + return ASN_PARSE_E; + } + + if (length == 0) + return 0; + + /* If the basic ca constraint is false, this extension may be named, but + * left empty. So, if the length is 0, just return. */ + + ret = GetBoolean(input, &idx, sz); + if (ret < 0) { + WOLFSSL_MSG("\tfail: constraint not valid BOOLEAN"); + return ret; + } + + cert->isCA = (byte)ret; + + /* If there isn't any more data, return. */ + if (idx >= (word32)sz) + return 0; + + ret = GetInteger7Bit(input, &idx, sz); + if (ret < 0) + return ret; + + cert->pathLength = (byte)ret; + cert->pathLengthSet = 1; + + return 0; +} + + +#define CRLDP_FULL_NAME 0 + /* From RFC3280 SS4.2.1.14, Distribution Point Name*/ +#define GENERALNAME_URI 6 + /* From RFC3280 SS4.2.1.7, GeneralName */ + +static int DecodeCrlDist(const byte* input, int sz, DecodedCert* cert) +{ + word32 idx = 0; + int length = 0; + + WOLFSSL_ENTER("DecodeCrlDist"); + + /* Unwrap the list of Distribution Points*/ + if (GetSequence(input, &idx, &length, sz) < 0) + return ASN_PARSE_E; + + /* Unwrap a single Distribution Point */ + if (GetSequence(input, &idx, &length, sz) < 0) + return ASN_PARSE_E; + + /* The Distribution Point has three explicit optional members + * First check for a DistributionPointName + */ + if (input[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) + { + idx++; + if (GetLength(input, &idx, &length, sz) < 0) + return ASN_PARSE_E; + + if (input[idx] == + (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | CRLDP_FULL_NAME)) + { + idx++; + if (GetLength(input, &idx, &length, sz) < 0) + return ASN_PARSE_E; + + if (input[idx] == (ASN_CONTEXT_SPECIFIC | GENERALNAME_URI)) + { + idx++; + if (GetLength(input, &idx, &length, sz) < 0) + return ASN_PARSE_E; + + cert->extCrlInfoSz = length; + cert->extCrlInfo = input + idx; + idx += length; + } + else + /* This isn't a URI, skip it. */ + idx += length; + } + else { + /* This isn't a FULLNAME, skip it. */ + idx += length; + } + } + + /* Check for reasonFlags */ + if (idx < (word32)sz && + input[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) + { + idx++; + if (GetLength(input, &idx, &length, sz) < 0) + return ASN_PARSE_E; + idx += length; + } + + /* Check for cRLIssuer */ + if (idx < (word32)sz && + input[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 2)) + { + idx++; + if (GetLength(input, &idx, &length, sz) < 0) + return ASN_PARSE_E; + idx += length; + } + + if (idx < (word32)sz) + { + WOLFSSL_MSG("\tThere are more CRL Distribution Point records, " + "but we only use the first one."); + } + + return 0; +} + + +static int DecodeAuthInfo(const byte* input, int sz, DecodedCert* cert) +/* + * Read the first of the Authority Information Access records. If there are + * any issues, return without saving the record. + */ +{ + word32 idx = 0; + int length = 0; + byte b; + word32 oid; + + WOLFSSL_ENTER("DecodeAuthInfo"); + + /* Unwrap the list of AIAs */ + if (GetSequence(input, &idx, &length, sz) < 0) + return ASN_PARSE_E; + + while (idx < (word32)sz) { + /* Unwrap a single AIA */ + if (GetSequence(input, &idx, &length, sz) < 0) + return ASN_PARSE_E; + + oid = 0; + if (GetObjectId(input, &idx, &oid, oidCertAuthInfoType, sz) < 0) + return ASN_PARSE_E; + + + /* Only supporting URIs right now. */ + b = input[idx++]; + if (GetLength(input, &idx, &length, sz) < 0) + return ASN_PARSE_E; + + if (b == (ASN_CONTEXT_SPECIFIC | GENERALNAME_URI) && + oid == AIA_OCSP_OID) + { + cert->extAuthInfoSz = length; + cert->extAuthInfo = input + idx; + break; + } + idx += length; + } + + return 0; +} + + +static int DecodeAuthKeyId(const byte* input, int sz, DecodedCert* cert) +{ + word32 idx = 0; + int length = 0, ret = 0; + + WOLFSSL_ENTER("DecodeAuthKeyId"); + + if (GetSequence(input, &idx, &length, sz) < 0) { + WOLFSSL_MSG("\tfail: should be a SEQUENCE\n"); + return ASN_PARSE_E; + } + + if (input[idx++] != (ASN_CONTEXT_SPECIFIC | 0)) { + WOLFSSL_MSG("\tinfo: OPTIONAL item 0, not available\n"); + return 0; + } + + if (GetLength(input, &idx, &length, sz) <= 0) { + WOLFSSL_MSG("\tfail: extension data length"); + return ASN_PARSE_E; + } + +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + cert->extAuthKeyIdSrc = &input[idx]; + cert->extAuthKeyIdSz = length; +#endif /* OPENSSL_EXTRA */ + + if (length == KEYID_SIZE) { + XMEMCPY(cert->extAuthKeyId, input + idx, length); + } + else + ret = CalcHashId(input + idx, length, cert->extAuthKeyId); + + return ret; +} + + +static int DecodeSubjKeyId(const byte* input, int sz, DecodedCert* cert) +{ + word32 idx = 0; + int length = 0, ret = 0; + + WOLFSSL_ENTER("DecodeSubjKeyId"); + + if (sz <= 0) + return ASN_PARSE_E; + + ret = GetOctetString(input, &idx, &length, sz); + if (ret < 0) + return ret; + + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + cert->extSubjKeyIdSrc = &input[idx]; + cert->extSubjKeyIdSz = length; + #endif /* OPENSSL_EXTRA */ + + if (length == KEYID_SIZE) { + XMEMCPY(cert->extSubjKeyId, input + idx, length); + } + else + ret = CalcHashId(input + idx, length, cert->extSubjKeyId); + + return ret; +} + + +static int DecodeKeyUsage(const byte* input, int sz, DecodedCert* cert) +{ + word32 idx = 0; + int length; + int ret; + WOLFSSL_ENTER("DecodeKeyUsage"); + + ret = CheckBitString(input, &idx, &length, sz, 0, NULL); + if (ret != 0) + return ret; + + cert->extKeyUsage = (word16)(input[idx]); + if (length == 2) + cert->extKeyUsage |= (word16)(input[idx+1] << 8); + + return 0; +} + + +static int DecodeExtKeyUsage(const byte* input, int sz, DecodedCert* cert) +{ + word32 idx = 0, oid; + int length, ret; + + WOLFSSL_MSG("DecodeExtKeyUsage"); + + if (GetSequence(input, &idx, &length, sz) < 0) { + WOLFSSL_MSG("\tfail: should be a SEQUENCE"); + return ASN_PARSE_E; + } + +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + cert->extExtKeyUsageSrc = input + idx; + cert->extExtKeyUsageSz = length; +#endif + + while (idx < (word32)sz) { + ret = GetObjectId(input, &idx, &oid, oidCertKeyUseType, sz); + if (ret == ASN_UNKNOWN_OID_E) + continue; + else if (ret < 0) + return ret; + + switch (oid) { + case EKU_ANY_OID: + cert->extExtKeyUsage |= EXTKEYUSE_ANY; + break; + case EKU_SERVER_AUTH_OID: + cert->extExtKeyUsage |= EXTKEYUSE_SERVER_AUTH; + break; + case EKU_CLIENT_AUTH_OID: + cert->extExtKeyUsage |= EXTKEYUSE_CLIENT_AUTH; + break; + case EKU_CODESIGNING_OID: + cert->extExtKeyUsage |= EXTKEYUSE_CODESIGN; + break; + case EKU_EMAILPROTECT_OID: + cert->extExtKeyUsage |= EXTKEYUSE_EMAILPROT; + break; + case EKU_TIMESTAMP_OID: + cert->extExtKeyUsage |= EXTKEYUSE_TIMESTAMP; + break; + case EKU_OCSP_SIGN_OID: + cert->extExtKeyUsage |= EXTKEYUSE_OCSP_SIGN; + break; + } + + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + cert->extExtKeyUsageCount++; + #endif + } + + return 0; +} + + +#ifndef IGNORE_NAME_CONSTRAINTS +#define ASN_TYPE_MASK 0xF +static int DecodeSubtree(const byte* input, int sz, + Base_entry** head, void* heap) +{ + word32 idx = 0; + + (void)heap; + + while (idx < (word32)sz) { + int seqLength, strLength; + word32 nameIdx; + byte b, bType; + + if (GetSequence(input, &idx, &seqLength, sz) < 0) { + WOLFSSL_MSG("\tfail: should be a SEQUENCE"); + return ASN_PARSE_E; + } + nameIdx = idx; + b = input[nameIdx++]; + + if (GetLength(input, &nameIdx, &strLength, sz) <= 0) { + WOLFSSL_MSG("\tinvalid length"); + return ASN_PARSE_E; + } + + /* Get type, LSB 4-bits */ + bType = (b & ASN_TYPE_MASK); + + if (bType == ASN_DNS_TYPE || bType == ASN_RFC822_TYPE || + bType == ASN_DIR_TYPE) { + Base_entry* entry; + + /* if constructed has leading sequence */ + if (b & ASN_CONSTRUCTED) { + if (GetSequence(input, &nameIdx, &strLength, sz) < 0) { + WOLFSSL_MSG("\tfail: constructed be a SEQUENCE"); + return ASN_PARSE_E; + } + } + + entry = (Base_entry*)XMALLOC(sizeof(Base_entry), heap, + DYNAMIC_TYPE_ALTNAME); + if (entry == NULL) { + WOLFSSL_MSG("allocate error"); + return MEMORY_E; + } + + entry->name = (char*)XMALLOC(strLength, heap, DYNAMIC_TYPE_ALTNAME); + if (entry->name == NULL) { + WOLFSSL_MSG("allocate error"); + XFREE(entry, heap, DYNAMIC_TYPE_ALTNAME); + return MEMORY_E; + } + + XMEMCPY(entry->name, &input[nameIdx], strLength); + entry->nameSz = strLength; + entry->type = bType; + + entry->next = *head; + *head = entry; + } + + idx += seqLength; + } + + return 0; +} + + +static int DecodeNameConstraints(const byte* input, int sz, DecodedCert* cert) +{ + word32 idx = 0; + int length = 0; + + WOLFSSL_ENTER("DecodeNameConstraints"); + + if (GetSequence(input, &idx, &length, sz) < 0) { + WOLFSSL_MSG("\tfail: should be a SEQUENCE"); + return ASN_PARSE_E; + } + + while (idx < (word32)sz) { + byte b = input[idx++]; + Base_entry** subtree = NULL; + + if (GetLength(input, &idx, &length, sz) <= 0) { + WOLFSSL_MSG("\tinvalid length"); + return ASN_PARSE_E; + } + + if (b == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0)) + subtree = &cert->permittedNames; + else if (b == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1)) + subtree = &cert->excludedNames; + else { + WOLFSSL_MSG("\tinvalid subtree"); + return ASN_PARSE_E; + } + + DecodeSubtree(input + idx, length, subtree, cert->heap); + + idx += length; + } + + return 0; +} +#endif /* IGNORE_NAME_CONSTRAINTS */ + +#if (defined(WOLFSSL_CERT_EXT) && !defined(WOLFSSL_SEP)) || defined(OPENSSL_EXTRA) + +static int Word32ToString(char* d, word32 number) +{ + int i = 0; + + if (d != NULL) { + word32 order = 1000000000; + word32 digit; + + if (number == 0) { + d[i++] = '0'; + } + else { + while (order) { + digit = number / order; + if (i > 0 || digit != 0) { + d[i++] = (char)digit + '0'; + } + if (digit != 0) + number %= digit * order; + if (order > 1) + order /= 10; + else + order = 0; + } + } + d[i] = 0; + } + + return i; +} + + +/* Decode ITU-T X.690 OID format to a string representation + * return string length */ +int DecodePolicyOID(char *out, word32 outSz, const byte *in, word32 inSz) +{ + word32 val, idx = 0, nb_bytes; + size_t w_bytes = 0; + + if (out == NULL || in == NULL || outSz < 4 || inSz < 2) + return BAD_FUNC_ARG; + + /* first two byte must be interpreted as : 40 * int1 + int2 */ + val = (word16)in[idx++]; + + w_bytes = Word32ToString(out, val / 40); + out[w_bytes++] = '.'; + w_bytes += Word32ToString(out+w_bytes, val % 40); + + while (idx < inSz) { + /* init value */ + val = 0; + nb_bytes = 0; + + /* check that output size is ok */ + if (w_bytes > (outSz - 3)) + return BUFFER_E; + + /* first bit is used to set if value is coded on 1 or multiple bytes */ + while ((in[idx+nb_bytes] & 0x80)) + nb_bytes++; + + if (!nb_bytes) + val = (word32)(in[idx++] & 0x7f); + else { + word32 base = 1, tmp = nb_bytes; + + while (tmp != 0) { + val += (word32)(in[idx+tmp] & 0x7f) * base; + base *= 128; + tmp--; + } + val += (word32)(in[idx++] & 0x7f) * base; + + idx += nb_bytes; + } + + out[w_bytes++] = '.'; + w_bytes += Word32ToString(out+w_bytes, val); + } + + return (int)w_bytes; +} +#endif /* WOLFSSL_CERT_EXT && !WOLFSSL_SEP */ + +#if defined(WOLFSSL_SEP) || defined(WOLFSSL_CERT_EXT) + /* Reference: https://tools.ietf.org/html/rfc5280#section-4.2.1.4 */ + static int DecodeCertPolicy(const byte* input, int sz, DecodedCert* cert) + { + word32 idx = 0; + word32 oldIdx; + int ret; + int total_length = 0, policy_length = 0, length = 0; + #if !defined(WOLFSSL_SEP) && defined(WOLFSSL_CERT_EXT) && \ + !defined(WOLFSSL_DUP_CERTPOL) + int i; + #endif + + WOLFSSL_ENTER("DecodeCertPolicy"); + + if (GetSequence(input, &idx, &total_length, sz) < 0) { + WOLFSSL_MSG("\tGet CertPolicy total seq failed"); + return ASN_PARSE_E; + } + + /* Validate total length */ + if (total_length > (sz - (int)idx)) { + WOLFSSL_MSG("\tCertPolicy length mismatch"); + return ASN_PARSE_E; + } + + /* Unwrap certificatePolicies */ + do { + if (GetSequence(input, &idx, &policy_length, sz) < 0) { + WOLFSSL_MSG("\tGet CertPolicy seq failed"); + return ASN_PARSE_E; + } + + oldIdx = idx; + ret = GetASNObjectId(input, &idx, &length, sz); + if (ret != 0) + return ret; + policy_length -= idx - oldIdx; + + if (length > 0) { + /* Verify length won't overrun buffer */ + if (length > (sz - (int)idx)) { + WOLFSSL_MSG("\tCertPolicy length exceeds input buffer"); + return ASN_PARSE_E; + } + + #if defined(WOLFSSL_SEP) + cert->deviceType = (byte*)XMALLOC(length, cert->heap, + DYNAMIC_TYPE_X509_EXT); + if (cert->deviceType == NULL) { + WOLFSSL_MSG("\tCouldn't alloc memory for deviceType"); + return MEMORY_E; + } + cert->deviceTypeSz = length; + XMEMCPY(cert->deviceType, input + idx, length); + break; + #elif defined(WOLFSSL_CERT_EXT) + /* decode cert policy */ + if (DecodePolicyOID(cert->extCertPolicies[cert->extCertPoliciesNb], MAX_CERTPOL_SZ, + input + idx, length) <= 0) { + WOLFSSL_MSG("\tCouldn't decode CertPolicy"); + return ASN_PARSE_E; + } + #ifndef WOLFSSL_DUP_CERTPOL + /* From RFC 5280 section 4.2.1.3 "A certificate policy OID MUST + * NOT appear more than once in a certificate policies + * extension". This is a sanity check for duplicates. + * extCertPolicies should only have OID values, additional + * qualifiers need to be stored in a seperate array. */ + for (i = 0; i < cert->extCertPoliciesNb; i++) { + if (XMEMCMP(cert->extCertPolicies[i], + cert->extCertPolicies[cert->extCertPoliciesNb], + MAX_CERTPOL_SZ) == 0) { + WOLFSSL_MSG("Duplicate policy OIDs not allowed"); + WOLFSSL_MSG("Use WOLFSSL_DUP_CERTPOL if wanted"); + return CERTPOLICIES_E; + } + } + #endif /* !WOLFSSL_DUP_CERTPOL */ + cert->extCertPoliciesNb++; + #else + WOLFSSL_LEAVE("DecodeCertPolicy : unsupported mode", 0); + return 0; + #endif + } + idx += policy_length; + } while((int)idx < total_length + #if defined(WOLFSSL_CERT_EXT) + && cert->extCertPoliciesNb < MAX_CERTPOL_NB + #endif + ); + + WOLFSSL_LEAVE("DecodeCertPolicy", 0); + return 0; + } +#endif /* WOLFSSL_SEP */ + +/* Macro to check if bit is set, if not sets and return success. + Otherwise returns failure */ +/* Macro required here because bit-field operation */ +#ifndef WOLFSSL_NO_ASN_STRICT + #define VERIFY_AND_SET_OID(bit) \ + if (bit == 0) \ + bit = 1; \ + else \ + return ASN_OBJECT_ID_E; +#else + /* With no strict defined, the verify is skipped */ +#define VERIFY_AND_SET_OID(bit) bit = 1; +#endif + +static int DecodeCertExtensions(DecodedCert* cert) +/* + * Processing the Certificate Extensions. This does not modify the current + * index. It is works starting with the recorded extensions pointer. + */ +{ + int ret = 0; + word32 idx = 0; + int sz = cert->extensionsSz; + const byte* input = cert->extensions; + int length; + word32 oid; + byte critical = 0; + byte criticalFail = 0; + + WOLFSSL_ENTER("DecodeCertExtensions"); + + if (input == NULL || sz == 0) + return BAD_FUNC_ARG; + + if (input[idx++] != ASN_EXTENSIONS) { + WOLFSSL_MSG("\tfail: should be an EXTENSIONS"); + return ASN_PARSE_E; + } + + if (GetLength(input, &idx, &length, sz) < 0) { + WOLFSSL_MSG("\tfail: invalid length"); + return ASN_PARSE_E; + } + + if (GetSequence(input, &idx, &length, sz) < 0) { + WOLFSSL_MSG("\tfail: should be a SEQUENCE (1)"); + return ASN_PARSE_E; + } + + while (idx < (word32)sz) { + if (GetSequence(input, &idx, &length, sz) < 0) { + WOLFSSL_MSG("\tfail: should be a SEQUENCE"); + return ASN_PARSE_E; + } + + oid = 0; + if ((ret = GetObjectId(input, &idx, &oid, oidCertExtType, sz)) < 0) { + WOLFSSL_MSG("\tfail: OBJECT ID"); + return ret; + } + + /* check for critical flag */ + critical = 0; + if (input[idx] == ASN_BOOLEAN) { + ret = GetBoolean(input, &idx, sz); + if (ret < 0) { + WOLFSSL_MSG("\tfail: critical boolean"); + return ret; + } + + critical = (byte)ret; + } + + /* process the extension based on the OID */ + ret = GetOctetString(input, &idx, &length, sz); + if (ret < 0) { + WOLFSSL_MSG("\tfail: bad OCTET STRING"); + return ret; + } + + switch (oid) { + case BASIC_CA_OID: + VERIFY_AND_SET_OID(cert->extBasicConstSet); + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + cert->extBasicConstCrit = critical; + #endif + if (DecodeBasicCaConstraint(&input[idx], length, cert) < 0) + return ASN_PARSE_E; + break; + + case CRL_DIST_OID: + VERIFY_AND_SET_OID(cert->extCRLdistSet); + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + cert->extCRLdistCrit = critical; + #endif + if (DecodeCrlDist(&input[idx], length, cert) < 0) + return ASN_PARSE_E; + break; + + case AUTH_INFO_OID: + VERIFY_AND_SET_OID(cert->extAuthInfoSet); + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + cert->extAuthInfoCrit = critical; + #endif + if (DecodeAuthInfo(&input[idx], length, cert) < 0) + return ASN_PARSE_E; + break; + + case ALT_NAMES_OID: + VERIFY_AND_SET_OID(cert->extSubjAltNameSet); + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + cert->extSubjAltNameCrit = critical; + #endif + ret = DecodeAltNames(&input[idx], length, cert); + if (ret < 0) + return ret; + break; + + case AUTH_KEY_OID: + VERIFY_AND_SET_OID(cert->extAuthKeyIdSet); + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + cert->extAuthKeyIdCrit = critical; + #endif + #ifndef WOLFSSL_ALLOW_CRIT_SKID + /* This check is added due to RFC 5280 section 4.2.1.1 + * stating that conforming CA's must mark this extension + * as non-critical. When parsing extensions check that + * certificate was made in compliance with this. */ + if (critical) { + WOLFSSL_MSG("Critical Auth Key ID is not allowed"); + WOLFSSL_MSG("Use macro WOLFSSL_ALLOW_CRIT_SKID if wanted"); + return ASN_CRIT_EXT_E; + } + #endif + if (DecodeAuthKeyId(&input[idx], length, cert) < 0) + return ASN_PARSE_E; + break; + + case SUBJ_KEY_OID: + VERIFY_AND_SET_OID(cert->extSubjKeyIdSet); + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + cert->extSubjKeyIdCrit = critical; + #endif + #ifndef WOLFSSL_ALLOW_CRIT_SKID + /* This check is added due to RFC 5280 section 4.2.1.2 + * stating that conforming CA's must mark this extension + * as non-critical. When parsing extensions check that + * certificate was made in compliance with this. */ + if (critical) { + WOLFSSL_MSG("Critical Subject Key ID is not allowed"); + WOLFSSL_MSG("Use macro WOLFSSL_ALLOW_CRIT_SKID if wanted"); + return ASN_CRIT_EXT_E; + } + #endif + + if (DecodeSubjKeyId(&input[idx], length, cert) < 0) + return ASN_PARSE_E; + break; + + case CERT_POLICY_OID: + #ifdef WOLFSSL_SEP + VERIFY_AND_SET_OID(cert->extCertPolicySet); + #if defined(OPENSSL_EXTRA) || \ + defined(OPENSSL_EXTRA_X509_SMALL) + cert->extCertPolicyCrit = critical; + #endif + #endif + #if defined(WOLFSSL_SEP) || defined(WOLFSSL_CERT_EXT) + if (DecodeCertPolicy(&input[idx], length, cert) < 0) { + return ASN_PARSE_E; + } + #else + WOLFSSL_MSG("Certificate Policy extension not supported yet."); + #endif + break; + + case KEY_USAGE_OID: + VERIFY_AND_SET_OID(cert->extKeyUsageSet); + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + cert->extKeyUsageCrit = critical; + #endif + if (DecodeKeyUsage(&input[idx], length, cert) < 0) + return ASN_PARSE_E; + break; + + case EXT_KEY_USAGE_OID: + VERIFY_AND_SET_OID(cert->extExtKeyUsageSet); + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + cert->extExtKeyUsageCrit = critical; + #endif + if (DecodeExtKeyUsage(&input[idx], length, cert) < 0) + return ASN_PARSE_E; + break; + + #ifndef IGNORE_NAME_CONSTRAINTS + case NAME_CONS_OID: + #ifndef WOLFSSL_NO_ASN_STRICT + /* Verify RFC 5280 Sec 4.2.1.10 rule: + "The name constraints extension, + which MUST be used only in a CA certificate" */ + if (!cert->isCA) { + WOLFSSL_MSG("Name constraints allowed only for CA certs"); + return ASN_NAME_INVALID_E; + } + #endif + VERIFY_AND_SET_OID(cert->extNameConstraintSet); + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + cert->extNameConstraintCrit = critical; + #endif + if (DecodeNameConstraints(&input[idx], length, cert) < 0) + return ASN_PARSE_E; + break; + #endif /* IGNORE_NAME_CONSTRAINTS */ + + case INHIBIT_ANY_OID: + VERIFY_AND_SET_OID(cert->inhibitAnyOidSet); + WOLFSSL_MSG("Inhibit anyPolicy extension not supported yet."); + break; + + default: + #ifndef WOLFSSL_NO_ASN_STRICT + /* While it is a failure to not support critical extensions, + * still parse the certificate ignoring the unsupported + * extension to allow caller to accept it with the verify + * callback. */ + if (critical) + criticalFail = 1; + #endif + break; + } + idx += length; + } + + return criticalFail ? ASN_CRIT_EXT_E : 0; +} + +int ParseCert(DecodedCert* cert, int type, int verify, void* cm) +{ + int ret; + char* ptr; + + ret = ParseCertRelative(cert, type, verify, cm); + if (ret < 0) + return ret; + + if (cert->subjectCNLen > 0) { + ptr = (char*) XMALLOC(cert->subjectCNLen + 1, cert->heap, + DYNAMIC_TYPE_SUBJECT_CN); + if (ptr == NULL) + return MEMORY_E; + XMEMCPY(ptr, cert->subjectCN, cert->subjectCNLen); + ptr[cert->subjectCNLen] = '\0'; + cert->subjectCN = ptr; + cert->subjectCNStored = 1; + } + + if (cert->keyOID == RSAk && + cert->publicKey != NULL && cert->pubKeySize > 0) { + ptr = (char*) XMALLOC(cert->pubKeySize, cert->heap, + DYNAMIC_TYPE_PUBLIC_KEY); + if (ptr == NULL) + return MEMORY_E; + XMEMCPY(ptr, cert->publicKey, cert->pubKeySize); + cert->publicKey = (byte *)ptr; + cert->pubKeyStored = 1; + } + + return ret; +} + + +/* from SSL proper, for locking can't do find here anymore */ +#ifdef __cplusplus + extern "C" { +#endif + WOLFSSL_LOCAL Signer* GetCA(void* signers, byte* hash); + #ifndef NO_SKID + WOLFSSL_LOCAL Signer* GetCAByName(void* signers, byte* hash); + #endif +#ifdef __cplusplus + } +#endif + + +#if defined(WOLFCRYPT_ONLY) || defined(NO_CERTS) + +/* dummy functions, not using wolfSSL so don't need actual ones */ +Signer* GetCA(void* signers, byte* hash) +{ + (void)hash; + + return (Signer*)signers; +} + +#ifndef NO_SKID +Signer* GetCAByName(void* signers, byte* hash) +{ + (void)hash; + + return (Signer*)signers; +} +#endif /* NO_SKID */ + +#endif /* WOLFCRYPT_ONLY || NO_CERTS */ + +#if defined(WOLFSSL_NO_TRUSTED_CERTS_VERIFY) && !defined(NO_SKID) +static Signer* GetCABySubjectAndPubKey(DecodedCert* cert, void* cm) +{ + Signer* ca = NULL; + if (cert->extSubjKeyIdSet) + ca = GetCA(cm, cert->extSubjKeyId); + if (ca == NULL) + ca = GetCAByName(cm, cert->subjectHash); + if (ca) { + if ((ca->pubKeySize == cert->pubKeySize) && + (XMEMCMP(ca->publicKey, cert->publicKey, ca->pubKeySize) == 0)) { + return ca; + } + } + return NULL; +} +#endif + +#if defined(WOLFSSL_SMALL_CERT_VERIFY) || defined(OPENSSL_EXTRA) +/* Only quick step through the certificate to find fields that are then used + * in certificate signature verification. + * Must use the signature OID from the signed part of the certificate. + * + * This is only for minimizing dynamic memory usage during TLS certificate + * chain processing. + * Doesn't support: + * OCSP Only: alt lookup using subject and pub key w/o sig check + */ +static int CheckCertSignature_ex(const byte* cert, word32 certSz, void* heap, + void* cm, const byte* pubKey, word32 pubKeySz, int pubKeyOID) +{ +#ifndef WOLFSSL_SMALL_STACK + SignatureCtx sigCtx[1]; +#else + SignatureCtx* sigCtx; +#endif + byte hash[KEYID_SIZE]; + Signer* ca = NULL; + word32 idx = 0; + int len; + word32 tbsCertIdx = 0; + word32 sigIndex = 0; + word32 signatureOID; + word32 oid; + word32 issuerIdx = 0; + word32 issuerSz = 0; +#ifndef NO_SKID + int extLen; + word32 extIdx; + word32 extEndIdx; + int extAuthKeyIdSet = 0; +#endif + int ret = 0; + + if (cert == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + sigCtx = XMALLOC(sizeof(*sigCtx), heap, DYNAMIC_TYPE_SIGNATURE); + if (sigCtx == NULL) + return MEMORY_E; +#endif + InitSignatureCtx(sigCtx, heap, INVALID_DEVID); + + /* Certificate SEQUENCE */ + if (GetSequence(cert, &idx, &len, certSz) < 0) + ret = ASN_PARSE_E; + if (ret == 0) { + tbsCertIdx = idx; + + /* TBSCertificate SEQUENCE */ + if (GetSequence(cert, &idx, &len, certSz) < 0) + ret = ASN_PARSE_E; + } + if (ret == 0) { + sigIndex = len + idx; + + if ((idx + 1) > certSz) + ret = BUFFER_E; + } + if (ret == 0) { + /* version - optional */ + if (cert[idx] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) { + idx++; + if (GetLength(cert, &idx, &len, certSz) < 0) + ret = ASN_PARSE_E; + idx += len; + } + } + + if (ret == 0) { + /* serialNumber */ + if (GetASNHeader(cert, ASN_INTEGER, &idx, &len, certSz) < 0) + ret = ASN_PARSE_E; + } + if (ret == 0) { + idx += len; + + /* signature */ + if (GetAlgoId(cert, &idx, &signatureOID, oidSigType, certSz) < 0) + ret = ASN_PARSE_E; + } + + if (ret == 0) { + issuerIdx = idx; + /* issuer */ + if (GetSequence(cert, &idx, &len, certSz) < 0) + ret = ASN_PARSE_E; + } + if (ret == 0) { + issuerSz = len + idx - issuerIdx; + } +#ifndef NO_SKID + if (ret == 0) { + idx += len; + + /* validity */ + if (GetSequence(cert, &idx, &len, certSz) < 0) + ret = ASN_PARSE_E; + } + if (ret == 0) { + idx += len; + + /* subject */ + if (GetSequence(cert, &idx, &len, certSz) < 0) + ret = ASN_PARSE_E; + } + if (ret == 0) { + idx += len; + + /* subjectPublicKeyInfo */ + if (GetSequence(cert, &idx, &len, certSz) < 0) + ret = ASN_PARSE_E; + } + if (ret == 0) { + idx += len; + + if ((idx + 1) > certSz) + ret = BUFFER_E; + } + if (ret == 0) { + /* issuerUniqueID - optional */ + if (cert[idx] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1)) { + idx++; + if (GetLength(cert, &idx, &len, certSz) < 0) + ret = ASN_PARSE_E; + idx += len; + } + } + if (ret == 0) { + if ((idx + 1) > certSz) + ret = BUFFER_E; + } + if (ret == 0) { + /* subjectUniqueID - optional */ + if (cert[idx] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 2)) { + idx++; + if (GetLength(cert, &idx, &len, certSz) < 0) + ret = ASN_PARSE_E; + idx += len; + } + } + + if (ret == 0) { + if ((idx + 1) > certSz) + ret = BUFFER_E; + } + /* extensions - optional */ + if (ret == 0 && cert[idx] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 3)) { + idx++; + if (GetLength(cert, &idx, &extLen, certSz) < 0) + ret = ASN_PARSE_E; + if (ret == 0) { + if (GetSequence(cert, &idx, &extLen, certSz) < 0) + ret = ASN_PARSE_E; + } + if (ret == 0) { + extEndIdx = idx + extLen; + + /* Check each extension for the ones we want. */ + while (ret == 0 && idx < extEndIdx) { + if (GetSequence(cert, &idx, &len, certSz) < 0) + ret = ASN_PARSE_E; + if (ret == 0) { + extIdx = idx; + if (GetObjectId(cert, &extIdx, &oid, oidCertExtType, + certSz) < 0) { + ret = ASN_PARSE_E; + } + } + if (ret == 0) { + if (cert[extIdx] == ASN_BOOLEAN) { + if (GetBoolean(cert, &extIdx, certSz) < 0) + ret = ASN_PARSE_E; + } + } + if (ret == 0) { + if (GetOctetString(cert, &extIdx, &extLen, certSz) < 0) + ret = ASN_PARSE_E; + } + + if (ret == 0) { + switch (oid) { + case AUTH_KEY_OID: + extAuthKeyIdSet = 1; + if (GetSequence(cert, &extIdx, &extLen, certSz) < 0) + ret = ASN_PARSE_E; + + if (ret == 0 && + cert[extIdx++] == (ASN_CONTEXT_SPECIFIC | 0)) { + if (GetLength(cert, &extIdx, &extLen, certSz) <= 0) + ret = ASN_PARSE_E; + if (ret == 0) { + if (extLen == KEYID_SIZE) + XMEMCPY(hash, cert + extIdx, extLen); + else { + ret = CalcHashId(cert + extIdx, extLen, + hash); + } + } + } + break; + + default: + break; + } + } + idx += len; + } + } + } + + if (ret == 0 && pubKey == NULL) { + if (extAuthKeyIdSet) + ca = GetCA(cm, hash); + if (ca == NULL) { + ret = CalcHashId(cert + issuerIdx, issuerSz, hash); + if (ret == 0) + ca = GetCAByName(cm, hash); + } + } +#else + if (ret == 0 && pubKey == NULL) { + ret = CalcHashId(cert + issuerIdx, issuerSz, hash); + if (ret == 0) + ca = GetCA(cm, hash); + } +#endif /* !NO_SKID */ + if (ca == NULL && pubKey == NULL) + ret = ASN_NO_SIGNER_E; + + if (ret == 0) { + idx = sigIndex; + /* signatureAlgorithm */ + if (GetAlgoId(cert, &idx, &oid, oidSigType, certSz) < 0) + ret = ASN_PARSE_E; + } + if (ret == 0) { + if (oid != signatureOID) + ret = ASN_SIG_OID_E; + } + if (ret == 0) { + /* signatureValue */ + if (CheckBitString(cert, &idx, &len, certSz, 1, NULL) < 0) + ret = ASN_PARSE_E; + } + + if (ret == 0) { + if (pubKey != NULL) { + ret = ConfirmSignature(sigCtx, cert + tbsCertIdx, + sigIndex - tbsCertIdx, + pubKey, pubKeySz, pubKeyOID, + cert + idx, len, signatureOID); + } + else { + ret = ConfirmSignature(sigCtx, cert + tbsCertIdx, + sigIndex - tbsCertIdx, + ca->publicKey, ca->pubKeySize, ca->keyOID, + cert + idx, len, signatureOID); + } + if (ret != 0) { + WOLFSSL_MSG("Confirm signature failed"); + } + } + + FreeSignatureCtx(sigCtx); +#ifdef WOLFSSL_SMALL_STACK + if (sigCtx != NULL) + XFREE(sigCtx, heap, DYNAMIC_TYPE_SIGNATURE); +#endif + return ret; +} + +#ifdef OPENSSL_EXTRA +/* Call CheckCertSignature_ex using a public key buffer for verification + */ +int CheckCertSignaturePubKey(const byte* cert, word32 certSz, void* heap, + const byte* pubKey, word32 pubKeySz, int pubKeyOID) +{ + return CheckCertSignature_ex(cert, certSz, heap, NULL, + pubKey, pubKeySz, pubKeyOID); +} +#endif /* OPENSSL_EXTRA */ +#ifdef WOLFSSL_SMALL_CERT_VERIFY +/* Call CheckCertSignature_ex using a certificate manager (cm) + */ +int CheckCertSignature(const byte* cert, word32 certSz, void* heap, void* cm) +{ + return CheckCertSignature_ex(cert, certSz, heap, cm, NULL, 0, 0); +} +#endif /* WOLFSSL_SMALL_CERT_VERIFY */ +#endif /* WOLFSSL_SMALL_CERT_VERIFY || OPENSSL_EXTRA */ + +int ParseCertRelative(DecodedCert* cert, int type, int verify, void* cm) +{ + int ret = 0; + int badDate = 0; + int criticalExt = 0; + word32 confirmOID; + + if (cert == NULL) { + return BAD_FUNC_ARG; + } + + if (cert->sigCtx.state == SIG_STATE_BEGIN) { + if ((ret = DecodeToKey(cert, verify)) < 0) { + if (ret == ASN_BEFORE_DATE_E || ret == ASN_AFTER_DATE_E) + badDate = ret; + else + return ret; + } + + WOLFSSL_MSG("Parsed Past Key"); + + if (cert->srcIdx < cert->sigIndex) { + #ifndef ALLOW_V1_EXTENSIONS + if (cert->version < 2) { + WOLFSSL_MSG("\tv1 and v2 certs not allowed extensions"); + return ASN_VERSION_E; + } + #endif + + /* save extensions */ + cert->extensions = &cert->source[cert->srcIdx]; + cert->extensionsSz = cert->sigIndex - cert->srcIdx; + cert->extensionsIdx = cert->srcIdx; /* for potential later use */ + + if ((ret = DecodeCertExtensions(cert)) < 0) { + if (ret == ASN_CRIT_EXT_E) + criticalExt = ret; + else + return ret; + } + + /* advance past extensions */ + cert->srcIdx = cert->sigIndex; + } + + if ((ret = GetAlgoId(cert->source, &cert->srcIdx, &confirmOID, + oidSigType, cert->maxIdx)) < 0) + return ret; + + if ((ret = GetSignature(cert)) < 0) + return ret; + + if (confirmOID != cert->signatureOID) + return ASN_SIG_OID_E; + + #ifndef NO_SKID + if (cert->extSubjKeyIdSet == 0 && cert->publicKey != NULL && + cert->pubKeySize > 0) { + ret = CalcHashId(cert->publicKey, cert->pubKeySize, + cert->extSubjKeyId); + if (ret != 0) + return ret; + } + #endif /* !NO_SKID */ + + if (verify != NO_VERIFY && type != CA_TYPE && type != TRUSTED_PEER_TYPE) { + cert->ca = NULL; + #ifndef NO_SKID + if (cert->extAuthKeyIdSet) + cert->ca = GetCA(cm, cert->extAuthKeyId); + if (cert->ca == NULL && cert->extSubjKeyIdSet \ + && verify != VERIFY_OCSP) { + cert->ca = GetCA(cm, cert->extSubjKeyId); + } + if (cert->ca == NULL) + cert->ca = GetCAByName(cm, cert->issuerHash); + + /* OCSP Only: alt lookup using subject and pub key w/o sig check */ + #ifdef WOLFSSL_NO_TRUSTED_CERTS_VERIFY + if (cert->ca == NULL && verify == VERIFY_OCSP) { + cert->ca = GetCABySubjectAndPubKey(cert, cm); + if (cert->ca) { + ret = 0; /* success */ + goto exit_pcr; + } + } + #endif /* WOLFSSL_NO_TRUSTED_CERTS_VERIFY */ + #else + cert->ca = GetCA(cm, cert->issuerHash); + #endif /* !NO_SKID */ + + WOLFSSL_MSG("About to verify certificate signature"); + + if (cert->ca) { + /* Check if cert is CA type and signer has path length set */ + if (cert->isCA && cert->ca->pathLengthSet) { + #if defined(WOLFSSL_WPAS) && !defined(WOLFSSL_NO_ASN_STRICT) + /* WPA Supplicant - has test case that expects self-signed + root CA to have path length == 0 */ + if (cert->selfSigned) { + if (cert->ca->pathLength != 0) { + WOLFSSL_MSG("Root CA with path length > 0"); + return ASN_PATHLEN_INV_E; + } + } + #endif + /* Check if signer is root CA (self-signed) */ + if (cert->ca->selfSigned) { + /* Root CA as signer: + * Must have path length > 0 to sign another CA + * If path length == 0 can only sign an end entity + * certificate, not intermediate CA + */ + if (cert->ca->pathLength == 0) { + WOLFSSL_MSG("Root CA with path length == 0"); + return ASN_PATHLEN_INV_E; + } + } + else { + /* Intermediate CA signing Intermediate CA */ + /* Check path lengths are valid between two CA's */ + if (cert->ca->pathLength == 0) { + WOLFSSL_MSG("CA with path length 0 signing a CA"); + return ASN_PATHLEN_INV_E; + } + else if (cert->pathLength >= cert->ca->pathLength) { + WOLFSSL_MSG("CA signing CA with longer path length"); + return ASN_PATHLEN_INV_E; + } + } + } + + #ifdef HAVE_OCSP + /* Need the CA's public key hash for OCSP */ + XMEMCPY(cert->issuerKeyHash, cert->ca->subjectKeyHash, + KEYID_SIZE); + #endif /* HAVE_OCSP */ + } + } + } + + if (verify != NO_VERIFY && type != CA_TYPE && type != TRUSTED_PEER_TYPE) { + if (cert->ca) { + if (verify == VERIFY || verify == VERIFY_OCSP) { + /* try to confirm/verify signature */ + if ((ret = ConfirmSignature(&cert->sigCtx, + cert->source + cert->certBegin, + cert->sigIndex - cert->certBegin, + cert->ca->publicKey, cert->ca->pubKeySize, + cert->ca->keyOID, cert->signature, + cert->sigLength, cert->signatureOID)) != 0) { + if (ret != 0 && ret != WC_PENDING_E) { + WOLFSSL_MSG("Confirm signature failed"); + } + return ret; + } + } + #ifndef IGNORE_NAME_CONSTRAINTS + if (verify == VERIFY || verify == VERIFY_OCSP || + verify == VERIFY_NAME) { + /* check that this cert's name is permitted by the signer's + * name constraints */ + if (!ConfirmNameConstraints(cert->ca, cert)) { + WOLFSSL_MSG("Confirm name constraint failed"); + return ASN_NAME_INVALID_E; + } + } + #endif /* IGNORE_NAME_CONSTRAINTS */ + } + else { + /* no signer */ + WOLFSSL_MSG("No CA signer to verify with"); + return ASN_NO_SIGNER_E; + } + } + +#if defined(WOLFSSL_NO_TRUSTED_CERTS_VERIFY) && !defined(NO_SKID) +exit_pcr: +#endif + + if (badDate != 0) + return badDate; + + if (criticalExt != 0) + return criticalExt; + + return ret; +} + +/* Create and init an new signer */ +Signer* MakeSigner(void* heap) +{ + Signer* signer = (Signer*) XMALLOC(sizeof(Signer), heap, + DYNAMIC_TYPE_SIGNER); + if (signer) { + XMEMSET(signer, 0, sizeof(Signer)); + } + (void)heap; + + return signer; +} + + +/* Free an individual signer */ +void FreeSigner(Signer* signer, void* heap) +{ + XFREE(signer->name, heap, DYNAMIC_TYPE_SUBJECT_CN); + XFREE((void*)signer->publicKey, heap, DYNAMIC_TYPE_PUBLIC_KEY); +#ifndef IGNORE_NAME_CONSTRAINTS + if (signer->permittedNames) + FreeNameSubtrees(signer->permittedNames, heap); + if (signer->excludedNames) + FreeNameSubtrees(signer->excludedNames, heap); +#endif +#ifdef WOLFSSL_SIGNER_DER_CERT + FreeDer(&signer->derCert); +#endif + XFREE(signer, heap, DYNAMIC_TYPE_SIGNER); + + (void)heap; +} + + +/* Free the whole singer table with number of rows */ +void FreeSignerTable(Signer** table, int rows, void* heap) +{ + int i; + + for (i = 0; i < rows; i++) { + Signer* signer = table[i]; + while (signer) { + Signer* next = signer->next; + FreeSigner(signer, heap); + signer = next; + } + table[i] = NULL; + } +} + +#ifdef WOLFSSL_TRUST_PEER_CERT +/* Free an individual trusted peer cert */ +void FreeTrustedPeer(TrustedPeerCert* tp, void* heap) +{ + if (tp == NULL) { + return; + } + + if (tp->name) { + XFREE(tp->name, heap, DYNAMIC_TYPE_SUBJECT_CN); + } + + if (tp->sig) { + XFREE(tp->sig, heap, DYNAMIC_TYPE_SIGNATURE); + } +#ifndef IGNORE_NAME_CONSTRAINTS + if (tp->permittedNames) + FreeNameSubtrees(tp->permittedNames, heap); + if (tp->excludedNames) + FreeNameSubtrees(tp->excludedNames, heap); +#endif + XFREE(tp, heap, DYNAMIC_TYPE_CERT); + + (void)heap; +} + +/* Free the whole Trusted Peer linked list */ +void FreeTrustedPeerTable(TrustedPeerCert** table, int rows, void* heap) +{ + int i; + + for (i = 0; i < rows; i++) { + TrustedPeerCert* tp = table[i]; + while (tp) { + TrustedPeerCert* next = tp->next; + FreeTrustedPeer(tp, heap); + tp = next; + } + table[i] = NULL; + } +} +#endif /* WOLFSSL_TRUST_PEER_CERT */ + +WOLFSSL_LOCAL int SetMyVersion(word32 version, byte* output, int header) +{ + int i = 0; + + if (output == NULL) + return BAD_FUNC_ARG; + + if (header) { + output[i++] = ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED; + output[i++] = 3; + } + output[i++] = ASN_INTEGER; + output[i++] = 0x01; + output[i++] = (byte)version; + + return i; +} + + +WOLFSSL_LOCAL int SetSerialNumber(const byte* sn, word32 snSz, byte* output, + int maxSnSz) +{ + int i = 0; + int snSzInt = (int)snSz; + + if (sn == NULL || output == NULL || snSzInt < 0) + return BAD_FUNC_ARG; + + /* remove leading zeros */ + while (snSzInt > 0 && sn[0] == 0) { + snSzInt--; + sn++; + } + + /* truncate if input is too long */ + if (snSzInt > maxSnSz) + snSzInt = maxSnSz; + + /* encode ASN Integer, with length and value */ + output[i++] = ASN_INTEGER; + + /* handle MSB, to make sure value is positive */ + if (sn[0] & 0x80) { + /* make room for zero pad */ + if (snSzInt > maxSnSz-1) + snSzInt = maxSnSz-1; + + /* add zero pad */ + i += SetLength(snSzInt+1, &output[i]); + output[i++] = 0x00; + XMEMCPY(&output[i], sn, snSzInt); + } + else { + i += SetLength(snSzInt, &output[i]); + XMEMCPY(&output[i], sn, snSzInt); + } + + /* compute final length */ + i += snSzInt; + + return i; +} + +#endif /* !NO_CERTS */ + +WOLFSSL_LOCAL int GetSerialNumber(const byte* input, word32* inOutIdx, + byte* serial, int* serialSz, word32 maxIdx) +{ + int result = 0; + int ret; + + WOLFSSL_ENTER("GetSerialNumber"); + + if (serial == NULL || input == NULL || serialSz == NULL) { + return BAD_FUNC_ARG; + } + + /* First byte is ASN type */ + if ((*inOutIdx+1) > maxIdx) { + WOLFSSL_MSG("Bad idx first"); + return BUFFER_E; + } + + ret = GetASNInt(input, inOutIdx, serialSz, maxIdx); + if (ret != 0) + return ret; + + if (*serialSz > EXTERNAL_SERIAL_SIZE) { + WOLFSSL_MSG("Serial size bad"); + return ASN_PARSE_E; + } + + /* return serial */ + XMEMCPY(serial, &input[*inOutIdx], *serialSz); + *inOutIdx += *serialSz; + + return result; +} + +#ifndef NO_CERTS + +int AllocDer(DerBuffer** pDer, word32 length, int type, void* heap) +{ + int ret = BAD_FUNC_ARG; + if (pDer) { + int dynType = 0; + DerBuffer* der; + + /* Determine dynamic type */ + switch (type) { + case CA_TYPE: dynType = DYNAMIC_TYPE_CA; break; + case CERT_TYPE: dynType = DYNAMIC_TYPE_CERT; break; + case CRL_TYPE: dynType = DYNAMIC_TYPE_CRL; break; + case DSA_TYPE: dynType = DYNAMIC_TYPE_DSA; break; + case ECC_TYPE: dynType = DYNAMIC_TYPE_ECC; break; + case RSA_TYPE: dynType = DYNAMIC_TYPE_RSA; break; + default: dynType = DYNAMIC_TYPE_KEY; break; + } + + /* Setup new buffer */ + *pDer = (DerBuffer*)XMALLOC(sizeof(DerBuffer) + length, heap, dynType); + if (*pDer == NULL) { + return MEMORY_E; + } + XMEMSET(*pDer, 0, sizeof(DerBuffer) + length); + + der = *pDer; + der->type = type; + der->dynType = dynType; /* Cache this for FreeDer */ + der->heap = heap; + der->buffer = (byte*)der + sizeof(DerBuffer); + der->length = length; + ret = 0; /* Success */ + } + return ret; +} + +void FreeDer(DerBuffer** pDer) +{ + if (pDer && *pDer) + { + DerBuffer* der = (DerBuffer*)*pDer; + + /* ForceZero private keys */ + if (der->type == PRIVATEKEY_TYPE) { + ForceZero(der->buffer, der->length); + } + der->buffer = NULL; + der->length = 0; + XFREE(der, der->heap, der->dynType); + + *pDer = NULL; + } +} + +int wc_AllocDer(DerBuffer** pDer, word32 length, int type, void* heap) +{ + return AllocDer(pDer, length, type, heap); +} +void wc_FreeDer(DerBuffer** pDer) +{ + FreeDer(pDer); +} + + +#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM) + +/* Max X509 header length indicates the max length + 2 ('\n', '\0') */ +#define MAX_X509_HEADER_SZ (37 + 2) + +const char* const BEGIN_CERT = "-----BEGIN CERTIFICATE-----"; +const char* const END_CERT = "-----END CERTIFICATE-----"; +#ifdef WOLFSSL_CERT_REQ + const char* const BEGIN_CERT_REQ = "-----BEGIN CERTIFICATE REQUEST-----"; + const char* const END_CERT_REQ = "-----END CERTIFICATE REQUEST-----"; +#endif +#ifndef NO_DH + const char* const BEGIN_DH_PARAM = "-----BEGIN DH PARAMETERS-----"; + const char* const END_DH_PARAM = "-----END DH PARAMETERS-----"; +#endif +#ifndef NO_DSA + const char* const BEGIN_DSA_PARAM = "-----BEGIN DSA PARAMETERS-----"; + const char* const END_DSA_PARAM = "-----END DSA PARAMETERS-----"; +#endif +const char* const BEGIN_X509_CRL = "-----BEGIN X509 CRL-----"; +const char* const END_X509_CRL = "-----END X509 CRL-----"; +const char* const BEGIN_RSA_PRIV = "-----BEGIN RSA PRIVATE KEY-----"; +const char* const END_RSA_PRIV = "-----END RSA PRIVATE KEY-----"; +const char* const BEGIN_PRIV_KEY = "-----BEGIN PRIVATE KEY-----"; +const char* const END_PRIV_KEY = "-----END PRIVATE KEY-----"; +const char* const BEGIN_ENC_PRIV_KEY = "-----BEGIN ENCRYPTED PRIVATE KEY-----"; +const char* const END_ENC_PRIV_KEY = "-----END ENCRYPTED PRIVATE KEY-----"; +#ifdef HAVE_ECC + const char* const BEGIN_EC_PRIV = "-----BEGIN EC PRIVATE KEY-----"; + const char* const END_EC_PRIV = "-----END EC PRIVATE KEY-----"; +#endif +#if defined(HAVE_ECC) || defined(HAVE_ED25519) || !defined(NO_DSA) + const char* const BEGIN_DSA_PRIV = "-----BEGIN DSA PRIVATE KEY-----"; + const char* const END_DSA_PRIV = "-----END DSA PRIVATE KEY-----"; +#endif +const char* const BEGIN_PUB_KEY = "-----BEGIN PUBLIC KEY-----"; +const char* const END_PUB_KEY = "-----END PUBLIC KEY-----"; +#ifdef HAVE_ED25519 + const char* const BEGIN_EDDSA_PRIV = "-----BEGIN EDDSA PRIVATE KEY-----"; + const char* const END_EDDSA_PRIV = "-----END EDDSA PRIVATE KEY-----"; +#endif +#ifdef HAVE_CRL + const char *const BEGIN_CRL = "-----BEGIN X509 CRL-----"; + const char* const END_CRL = "-----END X509 CRL-----"; +#endif + + +static WC_INLINE char* SkipEndOfLineChars(char* line, const char* endOfLine) +{ + /* eat end of line characters */ + while (line < endOfLine && + (line[0] == '\r' || line[0] == '\n')) { + line++; + } + return line; +} + +int wc_PemGetHeaderFooter(int type, const char** header, const char** footer) +{ + int ret = BAD_FUNC_ARG; + + switch (type) { + case CA_TYPE: /* same as below */ + case TRUSTED_PEER_TYPE: + case CERT_TYPE: + if (header) *header = BEGIN_CERT; + if (footer) *footer = END_CERT; + ret = 0; + break; + + case CRL_TYPE: + if (header) *header = BEGIN_X509_CRL; + if (footer) *footer = END_X509_CRL; + ret = 0; + break; + #ifndef NO_DH + case DH_PARAM_TYPE: + if (header) *header = BEGIN_DH_PARAM; + if (footer) *footer = END_DH_PARAM; + ret = 0; + break; + #endif + #ifndef NO_DSA + case DSA_PARAM_TYPE: + if (header) *header = BEGIN_DSA_PARAM; + if (footer) *footer = END_DSA_PARAM; + ret = 0; + break; + #endif + #ifdef WOLFSSL_CERT_REQ + case CERTREQ_TYPE: + if (header) *header = BEGIN_CERT_REQ; + if (footer) *footer = END_CERT_REQ; + ret = 0; + break; + #endif + #ifndef NO_DSA + case DSA_TYPE: + case DSA_PRIVATEKEY_TYPE: + if (header) *header = BEGIN_DSA_PRIV; + if (footer) *footer = END_DSA_PRIV; + ret = 0; + break; + #endif + #ifdef HAVE_ECC + case ECC_TYPE: + case ECC_PRIVATEKEY_TYPE: + if (header) *header = BEGIN_EC_PRIV; + if (footer) *footer = END_EC_PRIV; + ret = 0; + break; + #endif + case RSA_TYPE: + case PRIVATEKEY_TYPE: + if (header) *header = BEGIN_RSA_PRIV; + if (footer) *footer = END_RSA_PRIV; + ret = 0; + break; + #ifdef HAVE_ED25519 + case ED25519_TYPE: + case EDDSA_PRIVATEKEY_TYPE: + if (header) *header = BEGIN_EDDSA_PRIV; + if (footer) *footer = END_EDDSA_PRIV; + ret = 0; + break; + #endif + case PUBLICKEY_TYPE: + case ECC_PUBLICKEY_TYPE: + if (header) *header = BEGIN_PUB_KEY; + if (footer) *footer = END_PUB_KEY; + ret = 0; + break; + case PKCS8_PRIVATEKEY_TYPE: + if (header) *header = BEGIN_PRIV_KEY; + if (footer) *footer = END_PRIV_KEY; + ret = 0; + break; + case PKCS8_ENC_PRIVATEKEY_TYPE: + if (header) *header = BEGIN_ENC_PRIV_KEY; + if (footer) *footer = END_ENC_PRIV_KEY; + ret = 0; + break; + default: + break; + } + return ret; +} + +#ifdef WOLFSSL_ENCRYPTED_KEYS + +static const char* const kProcTypeHeader = "Proc-Type"; +static const char* const kDecInfoHeader = "DEK-Info"; + +#ifdef WOLFSSL_PEM_TO_DER +#ifndef NO_DES3 + static const char* const kEncTypeDes = "DES-CBC"; + static const char* const kEncTypeDes3 = "DES-EDE3-CBC"; +#endif +#if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_128) + static const char* const kEncTypeAesCbc128 = "AES-128-CBC"; +#endif +#if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_192) + static const char* const kEncTypeAesCbc192 = "AES-192-CBC"; +#endif +#if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_256) + static const char* const kEncTypeAesCbc256 = "AES-256-CBC"; +#endif + +int wc_EncryptedInfoGet(EncryptedInfo* info, const char* cipherInfo) +{ + int ret = 0; + + if (info == NULL || cipherInfo == NULL) + return BAD_FUNC_ARG; + + /* determine cipher information */ +#ifndef NO_DES3 + if (XSTRNCMP(cipherInfo, kEncTypeDes, XSTRLEN(kEncTypeDes)) == 0) { + info->cipherType = WC_CIPHER_DES; + info->keySz = DES_KEY_SIZE; + if (info->ivSz == 0) info->ivSz = DES_IV_SIZE; + } + else if (XSTRNCMP(cipherInfo, kEncTypeDes3, XSTRLEN(kEncTypeDes3)) == 0) { + info->cipherType = WC_CIPHER_DES3; + info->keySz = DES3_KEY_SIZE; + if (info->ivSz == 0) info->ivSz = DES_IV_SIZE; + } + else +#endif /* !NO_DES3 */ +#if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_128) + if (XSTRNCMP(cipherInfo, kEncTypeAesCbc128, XSTRLEN(kEncTypeAesCbc128)) == 0) { + info->cipherType = WC_CIPHER_AES_CBC; + info->keySz = AES_128_KEY_SIZE; + if (info->ivSz == 0) info->ivSz = AES_IV_SIZE; + } + else +#endif +#if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_192) + if (XSTRNCMP(cipherInfo, kEncTypeAesCbc192, XSTRLEN(kEncTypeAesCbc192)) == 0) { + info->cipherType = WC_CIPHER_AES_CBC; + info->keySz = AES_192_KEY_SIZE; + if (info->ivSz == 0) info->ivSz = AES_IV_SIZE; + } + else +#endif +#if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(WOLFSSL_AES_256) + if (XSTRNCMP(cipherInfo, kEncTypeAesCbc256, XSTRLEN(kEncTypeAesCbc256)) == 0) { + info->cipherType = WC_CIPHER_AES_CBC; + info->keySz = AES_256_KEY_SIZE; + if (info->ivSz == 0) info->ivSz = AES_IV_SIZE; + } + else +#endif + { + ret = NOT_COMPILED_IN; + } + return ret; +} + +int wc_EncryptedInfoParse(EncryptedInfo* info, char** pBuffer, size_t bufSz) +{ + int err = 0; + char* bufferStart; + char* bufferEnd; + char* line; + word32 lineSz; + char* finish; + word32 finishSz; + char* start = NULL; + word32 startSz; + char* newline = NULL; + + if (info == NULL || pBuffer == NULL || bufSz == 0) + return BAD_FUNC_ARG; + + bufferStart = *pBuffer; + bufferEnd = bufferStart + bufSz; + + /* find encrypted info marker */ + line = XSTRNSTR(bufferStart, kProcTypeHeader, + min((word32)bufSz, PEM_LINE_LEN)); + if (line != NULL) { + if (line >= bufferEnd) { + return BUFFER_E; + } + + lineSz = (word32)(bufferEnd - line); + + /* find DEC-Info marker */ + start = XSTRNSTR(line, kDecInfoHeader, min(lineSz, PEM_LINE_LEN)); + + if (start == NULL) + return BUFFER_E; + + /* skip dec-info and ": " */ + start += XSTRLEN(kDecInfoHeader); + if (start >= bufferEnd) + return BUFFER_E; + + if (start[0] == ':') { + start++; + if (start >= bufferEnd) + return BUFFER_E; + } + if (start[0] == ' ') + start++; + + startSz = (word32)(bufferEnd - start); + finish = XSTRNSTR(start, ",", min(startSz, PEM_LINE_LEN)); + + if ((start != NULL) && (finish != NULL) && (start < finish)) { + if (finish >= bufferEnd) { + return BUFFER_E; + } + + finishSz = (word32)(bufferEnd - finish); + newline = XSTRNSTR(finish, "\r", min(finishSz, PEM_LINE_LEN)); + + /* get cipher name */ + if (NAME_SZ < (finish - start)) /* buffer size of info->name */ + return BUFFER_E; + if (XMEMCPY(info->name, start, finish - start) == NULL) + return BUFFER_E; + info->name[finish - start] = '\0'; /* null term */ + + /* populate info */ + err = wc_EncryptedInfoGet(info, info->name); + if (err != 0) + return err; + + /* get IV */ + if (finishSz < info->ivSz + 1) + return BUFFER_E; + + if (newline == NULL) { + newline = XSTRNSTR(finish, "\n", min(finishSz, + PEM_LINE_LEN)); + } + if ((newline != NULL) && (newline > finish)) { + info->ivSz = (word32)(newline - (finish + 1)); + if (XMEMCPY(info->iv, finish + 1, info->ivSz) == NULL) + return BUFFER_E; + info->set = 1; + } + else + return BUFFER_E; + } + else + return BUFFER_E; + + /* eat end of line characters */ + newline = SkipEndOfLineChars(newline, bufferEnd); + + /* return new headerEnd */ + if (pBuffer) + *pBuffer = newline; + } + + return err; +} +#endif /* WOLFSSL_PEM_TO_DER */ + +#ifdef WOLFSSL_DER_TO_PEM +static int wc_EncryptedInfoAppend(char* dest, int destSz, char* cipherInfo) +{ + if (cipherInfo != NULL) { + int cipherInfoStrLen = (int)XSTRLEN((char*)cipherInfo); + + if (cipherInfoStrLen > HEADER_ENCRYPTED_KEY_SIZE - (9+14+10+3)) + cipherInfoStrLen = HEADER_ENCRYPTED_KEY_SIZE - (9+14+10+3); + + if (destSz - (int)XSTRLEN(dest) >= cipherInfoStrLen + (9+14+8+2+2+1)) { + /* strncat's src length needs to include the NULL */ + XSTRNCAT(dest, kProcTypeHeader, 10); + XSTRNCAT(dest, ": 4,ENCRYPTED\n", 15); + XSTRNCAT(dest, kDecInfoHeader, 9); + XSTRNCAT(dest, ": ", 3); + XSTRNCAT(dest, cipherInfo, destSz - (int)XSTRLEN(dest) - 1); + XSTRNCAT(dest, "\n\n", 4); + } + } + return 0; +} +#endif /* WOLFSSL_DER_TO_PEM */ +#endif /* WOLFSSL_ENCRYPTED_KEYS */ + +#ifdef WOLFSSL_DER_TO_PEM + +/* Used for compatibility API */ +int wc_DerToPem(const byte* der, word32 derSz, + byte* output, word32 outSz, int type) +{ + return wc_DerToPemEx(der, derSz, output, outSz, NULL, type); +} + +/* convert der buffer to pem into output, can't do inplace, der and output + need to be different */ +int wc_DerToPemEx(const byte* der, word32 derSz, byte* output, word32 outSz, + byte *cipher_info, int type) +{ + const char* headerStr = NULL; + const char* footerStr = NULL; +#ifdef WOLFSSL_SMALL_STACK + char* header = NULL; + char* footer = NULL; +#else + char header[MAX_X509_HEADER_SZ + HEADER_ENCRYPTED_KEY_SIZE]; + char footer[MAX_X509_HEADER_SZ]; +#endif + int headerLen = MAX_X509_HEADER_SZ + HEADER_ENCRYPTED_KEY_SIZE; + int footerLen = MAX_X509_HEADER_SZ; + int i; + int err; + int outLen; /* return length or error */ + + (void)cipher_info; + + if (der == output) /* no in place conversion */ + return BAD_FUNC_ARG; + + err = wc_PemGetHeaderFooter(type, &headerStr, &footerStr); + if (err != 0) + return err; + +#ifdef WOLFSSL_SMALL_STACK + header = (char*)XMALLOC(headerLen, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (header == NULL) + return MEMORY_E; + + footer = (char*)XMALLOC(footerLen, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (footer == NULL) { + XFREE(header, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#endif + + /* build header and footer based on type */ + XSTRNCPY(header, headerStr, headerLen - 1); + header[headerLen - 2] = 0; + XSTRNCPY(footer, footerStr, footerLen - 1); + footer[footerLen - 2] = 0; + + /* add new line to end */ + XSTRNCAT(header, "\n", 2); + XSTRNCAT(footer, "\n", 2); + +#ifdef WOLFSSL_ENCRYPTED_KEYS + err = wc_EncryptedInfoAppend(header, headerLen, (char*)cipher_info); + if (err != 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(header, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(footer, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return err; + } +#endif + + headerLen = (int)XSTRLEN(header); + footerLen = (int)XSTRLEN(footer); + + /* if null output and 0 size passed in then return size needed */ + if (!output && outSz == 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(header, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(footer, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + outLen = 0; + if ((err = Base64_Encode(der, derSz, NULL, (word32*)&outLen)) + != LENGTH_ONLY_E) { + return err; + } + return headerLen + footerLen + outLen; + } + + if (!der || !output) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(header, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(footer, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return BAD_FUNC_ARG; + } + + /* don't even try if outSz too short */ + if (outSz < headerLen + footerLen + derSz) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(header, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(footer, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return BAD_FUNC_ARG; + } + + /* header */ + XMEMCPY(output, header, headerLen); + i = headerLen; + +#ifdef WOLFSSL_SMALL_STACK + XFREE(header, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + /* body */ + outLen = outSz - (headerLen + footerLen); /* input to Base64_Encode */ + if ( (err = Base64_Encode(der, derSz, output + i, (word32*)&outLen)) < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(footer, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return err; + } + i += outLen; + + /* footer */ + if ( (i + footerLen) > (int)outSz) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(footer, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return BAD_FUNC_ARG; + } + XMEMCPY(output + i, footer, footerLen); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(footer, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return outLen + headerLen + footerLen; +} + +#endif /* WOLFSSL_DER_TO_PEM */ + +#ifdef WOLFSSL_PEM_TO_DER + +/* Remove PEM header/footer, convert to ASN1, store any encrypted data + info->consumed tracks of PEM bytes consumed in case multiple parts */ +int PemToDer(const unsigned char* buff, long longSz, int type, + DerBuffer** pDer, void* heap, EncryptedInfo* info, int* eccKey) +{ + const char* header = NULL; + const char* footer = NULL; + char* headerEnd; + char* footerEnd; + char* consumedEnd; + char* bufferEnd = (char*)(buff + longSz); + long neededSz; + int ret = 0; + int sz = (int)longSz; + int encrypted_key = 0; + DerBuffer* der; + word32 algId = 0; + + WOLFSSL_ENTER("PemToDer"); + + /* get PEM header and footer based on type */ + ret = wc_PemGetHeaderFooter(type, &header, &footer); + if (ret != 0) + return ret; + + /* map header if not found for type */ + for (;;) { + headerEnd = XSTRNSTR((char*)buff, header, sz); + + if (headerEnd) { + break; + } else + if (type == PRIVATEKEY_TYPE) { + if (header == BEGIN_RSA_PRIV) { + header = BEGIN_PRIV_KEY; footer = END_PRIV_KEY; + } else + if (header == BEGIN_PRIV_KEY) { + header = BEGIN_ENC_PRIV_KEY; footer = END_ENC_PRIV_KEY; + } else + #ifdef HAVE_ECC + if (header == BEGIN_ENC_PRIV_KEY) { + header = BEGIN_EC_PRIV; footer = END_EC_PRIV; + } else + if (header == BEGIN_EC_PRIV) { + header = BEGIN_DSA_PRIV; footer = END_DSA_PRIV; + } else + #endif + #ifdef HAVE_ED25519 + #ifdef HAVE_ECC + if (header == BEGIN_DSA_PRIV) + #else + if (header == BEGIN_ENC_PRIV_KEY) + #endif + { + header = BEGIN_EDDSA_PRIV; footer = END_EDDSA_PRIV; + } else + #endif + { + break; + } + } else +#ifdef HAVE_CRL + if ((type == CRL_TYPE) && (header != BEGIN_CRL)) { + header = BEGIN_CRL; footer = END_CRL; + } else +#endif + { + break; + } + } + + if (!headerEnd) { + WOLFSSL_MSG("Couldn't find PEM header"); + return ASN_NO_PEM_HEADER; + } + + headerEnd += XSTRLEN(header); + + /* eat end of line characters */ + headerEnd = SkipEndOfLineChars(headerEnd, bufferEnd); + + if (type == PRIVATEKEY_TYPE) { + if (eccKey) { + #ifdef HAVE_ECC + *eccKey = (header == BEGIN_EC_PRIV) ? 1 : 0; + #else + *eccKey = 0; + #endif + } + } + +#ifdef WOLFSSL_ENCRYPTED_KEYS + if (info) { + ret = wc_EncryptedInfoParse(info, &headerEnd, bufferEnd - headerEnd); + if (ret < 0) + return ret; + if (info->set) + encrypted_key = 1; + } +#endif /* WOLFSSL_ENCRYPTED_KEYS */ + + /* find footer */ + footerEnd = XSTRNSTR((char*)buff, footer, sz); + if (!footerEnd) { + if (info) + info->consumed = longSz; /* No more certs if no footer */ + return BUFFER_E; + } + + consumedEnd = footerEnd + XSTRLEN(footer); + + if (consumedEnd < bufferEnd) { /* handle no end of line on last line */ + /* eat end of line characters */ + consumedEnd = SkipEndOfLineChars(consumedEnd, bufferEnd); + /* skip possible null term */ + if (consumedEnd < bufferEnd && consumedEnd[0] == '\0') + consumedEnd++; + } + + if (info) + info->consumed = (long)(consumedEnd - (char*)buff); + + /* set up der buffer */ + neededSz = (long)(footerEnd - headerEnd); + if (neededSz > sz || neededSz <= 0) + return BUFFER_E; + + ret = AllocDer(pDer, (word32)neededSz, type, heap); + if (ret < 0) { + return ret; + } + der = *pDer; + + if (Base64_Decode((byte*)headerEnd, (word32)neededSz, + der->buffer, &der->length) < 0) + return BUFFER_E; + + if ((header == BEGIN_PRIV_KEY +#ifdef HAVE_ECC + || header == BEGIN_EC_PRIV +#endif + ) && !encrypted_key) + { + /* pkcs8 key, convert and adjust length */ + if ((ret = ToTraditional_ex(der->buffer, der->length, &algId)) > 0) { + der->length = ret; + } + else { + /* ignore failure here and assume key is not pkcs8 wrapped */ + } + + return 0; + } + +#ifdef WOLFSSL_ENCRYPTED_KEYS + if (encrypted_key || header == BEGIN_ENC_PRIV_KEY) { + int passwordSz = NAME_SZ; + #ifdef WOLFSSL_SMALL_STACK + char* password = NULL; + #else + char password[NAME_SZ]; + #endif + + if (!info || !info->passwd_cb) { + WOLFSSL_MSG("No password callback set"); + return NO_PASSWORD; + } + + #ifdef WOLFSSL_SMALL_STACK + password = (char*)XMALLOC(passwordSz, heap, DYNAMIC_TYPE_STRING); + if (password == NULL) + return MEMORY_E; + #endif + + /* get password */ + ret = info->passwd_cb(password, passwordSz, PEM_PASS_READ, + info->passwd_userdata); + if (ret >= 0) { + passwordSz = ret; + + /* convert and adjust length */ + if (header == BEGIN_ENC_PRIV_KEY) { + #ifndef NO_PWDBASED + ret = ToTraditionalEnc(der->buffer, der->length, + password, passwordSz, &algId); + + if (ret >= 0) { + der->length = ret; + if ((algId == ECDSAk) && (eccKey != NULL)) { + *eccKey = 1; + } + ret = 0; + } + #else + ret = NOT_COMPILED_IN; + #endif + } + /* decrypt the key */ + else { + ret = wc_BufferKeyDecrypt(info, der->buffer, der->length, + (byte*)password, passwordSz, WC_MD5); + } + ForceZero(password, passwordSz); + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(password, heap, DYNAMIC_TYPE_STRING); + #endif + } +#endif /* WOLFSSL_ENCRYPTED_KEYS */ + + return ret; +} + +int wc_PemToDer(const unsigned char* buff, long longSz, int type, + DerBuffer** pDer, void* heap, EncryptedInfo* info, int* eccKey) +{ + return PemToDer(buff, longSz, type, pDer, heap, info, eccKey); +} + + +/* our KeyPemToDer password callback, password in userData */ +static WC_INLINE int OurPasswordCb(char* passwd, int sz, int rw, void* userdata) +{ + (void)rw; + + if (userdata == NULL) + return 0; + + XSTRNCPY(passwd, (char*)userdata, sz); + return min((word32)sz, (word32)XSTRLEN((char*)userdata)); +} + +/* Return bytes written to buff or < 0 for error */ +int wc_KeyPemToDer(const unsigned char* pem, int pemSz, + unsigned char* buff, int buffSz, const char* pass) +{ + int eccKey = 0; + int ret; + DerBuffer* der = NULL; +#ifdef WOLFSSL_SMALL_STACK + EncryptedInfo* info = NULL; +#else + EncryptedInfo info[1]; +#endif + + WOLFSSL_ENTER("wc_KeyPemToDer"); + + if (pem == NULL || buff == NULL || buffSz <= 0) { + WOLFSSL_MSG("Bad pem der args"); + return BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + info = (EncryptedInfo*)XMALLOC(sizeof(EncryptedInfo), NULL, + DYNAMIC_TYPE_ENCRYPTEDINFO); + if (info == NULL) + return MEMORY_E; +#endif + + XMEMSET(info, 0, sizeof(EncryptedInfo)); + info->passwd_cb = OurPasswordCb; + info->passwd_userdata = (void*)pass; + + ret = PemToDer(pem, pemSz, PRIVATEKEY_TYPE, &der, NULL, info, &eccKey); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(info, NULL, DYNAMIC_TYPE_ENCRYPTEDINFO); +#endif + + if (ret < 0 || der == NULL) { + WOLFSSL_MSG("Bad Pem To Der"); + } + else { + if (der->length <= (word32)buffSz) { + XMEMCPY(buff, der->buffer, der->length); + ret = der->length; + } + else { + WOLFSSL_MSG("Bad der length"); + ret = BAD_FUNC_ARG; + } + } + + FreeDer(&der); + return ret; +} + + +/* Return bytes written to buff or < 0 for error */ +int wc_CertPemToDer(const unsigned char* pem, int pemSz, + unsigned char* buff, int buffSz, int type) +{ + int eccKey = 0; + int ret; + DerBuffer* der = NULL; + + WOLFSSL_ENTER("wc_CertPemToDer"); + + if (pem == NULL || buff == NULL || buffSz <= 0) { + WOLFSSL_MSG("Bad pem der args"); + return BAD_FUNC_ARG; + } + + if (type != CERT_TYPE && type != CA_TYPE && type != CERTREQ_TYPE) { + WOLFSSL_MSG("Bad cert type"); + return BAD_FUNC_ARG; + } + + + ret = PemToDer(pem, pemSz, type, &der, NULL, NULL, &eccKey); + if (ret < 0 || der == NULL) { + WOLFSSL_MSG("Bad Pem To Der"); + } + else { + if (der->length <= (word32)buffSz) { + XMEMCPY(buff, der->buffer, der->length); + ret = der->length; + } + else { + WOLFSSL_MSG("Bad der length"); + ret = BAD_FUNC_ARG; + } + } + + FreeDer(&der); + return ret; +} + +#endif /* WOLFSSL_PEM_TO_DER */ +#endif /* WOLFSSL_PEM_TO_DER || WOLFSSL_DER_TO_PEM */ + + +#ifdef WOLFSSL_PEM_TO_DER +#if defined(WOLFSSL_CERT_EXT) || defined(WOLFSSL_PUB_PEM_TO_DER) +/* Return bytes written to buff or < 0 for error */ +int wc_PubKeyPemToDer(const unsigned char* pem, int pemSz, + unsigned char* buff, int buffSz) +{ + int ret; + DerBuffer* der = NULL; + + WOLFSSL_ENTER("wc_PubKeyPemToDer"); + + if (pem == NULL || buff == NULL || buffSz <= 0) { + WOLFSSL_MSG("Bad pem der args"); + return BAD_FUNC_ARG; + } + + ret = PemToDer(pem, pemSz, PUBLICKEY_TYPE, &der, NULL, NULL, NULL); + if (ret < 0 || der == NULL) { + WOLFSSL_MSG("Bad Pem To Der"); + } + else { + if (der->length <= (word32)buffSz) { + XMEMCPY(buff, der->buffer, der->length); + ret = der->length; + } + else { + WOLFSSL_MSG("Bad der length"); + ret = BAD_FUNC_ARG; + } + } + + FreeDer(&der); + return ret; +} +#endif /* WOLFSSL_CERT_EXT || WOLFSSL_PUB_PEM_TO_DER */ +#endif /* WOLFSSL_PEM_TO_DER */ + +#ifndef NO_FILESYSTEM + +#ifdef WOLFSSL_CERT_GEN +/* load pem cert from file into der buffer, return der size or error */ +int wc_PemCertToDer(const char* fileName, unsigned char* derBuf, int derSz) +{ +#ifdef WOLFSSL_SMALL_STACK + byte staticBuffer[1]; /* force XMALLOC */ +#else + byte staticBuffer[FILE_BUFFER_SIZE]; +#endif + byte* fileBuf = staticBuffer; + int dynamic = 0; + int ret = 0; + long sz = 0; + XFILE file; + DerBuffer* converted = NULL; + + WOLFSSL_ENTER("wc_PemCertToDer"); + + if (fileName == NULL) { + ret = BAD_FUNC_ARG; + } + else { + file = XFOPEN(fileName, "rb"); + if (file == XBADFILE) { + ret = BUFFER_E; + } + } + + if (ret == 0) { + if(XFSEEK(file, 0, XSEEK_END) != 0) + ret = BUFFER_E; + sz = XFTELL(file); + XREWIND(file); + + if (sz <= 0) { + ret = BUFFER_E; + } + else if (sz > (long)sizeof(staticBuffer)) { + #ifdef WOLFSSL_STATIC_MEMORY + WOLFSSL_MSG("File was larger then static buffer"); + return MEMORY_E; + #endif + fileBuf = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE); + if (fileBuf == NULL) + ret = MEMORY_E; + else + dynamic = 1; + } + + if (ret == 0) { + if ( (ret = (int)XFREAD(fileBuf, 1, sz, file)) != sz) { + ret = BUFFER_E; + } + #ifdef WOLFSSL_PEM_TO_DER + else { + ret = PemToDer(fileBuf, sz, CA_TYPE, &converted, 0, NULL,NULL); + } + #endif + + if (ret == 0) { + if (converted->length < (word32)derSz) { + XMEMCPY(derBuf, converted->buffer, converted->length); + ret = converted->length; + } + else + ret = BUFFER_E; + } + + FreeDer(&converted); + } + + XFCLOSE(file); + if (dynamic) + XFREE(fileBuf, NULL, DYNAMIC_TYPE_FILE); + } + + return ret; +} +#endif /* WOLFSSL_CERT_GEN */ + +#if defined(WOLFSSL_CERT_EXT) || defined(WOLFSSL_PUB_PEM_TO_DER) +/* load pem public key from file into der buffer, return der size or error */ +int wc_PemPubKeyToDer(const char* fileName, + unsigned char* derBuf, int derSz) +{ +#ifdef WOLFSSL_SMALL_STACK + byte staticBuffer[1]; /* force XMALLOC */ +#else + byte staticBuffer[FILE_BUFFER_SIZE]; +#endif + byte* fileBuf = staticBuffer; + int dynamic = 0; + int ret = 0; + long sz = 0; + XFILE file; + DerBuffer* converted = NULL; + + WOLFSSL_ENTER("wc_PemPubKeyToDer"); + + if (fileName == NULL) { + ret = BAD_FUNC_ARG; + } + else { + file = XFOPEN(fileName, "rb"); + if (file == XBADFILE) { + ret = BUFFER_E; + } + } + + if (ret == 0) { + if(XFSEEK(file, 0, XSEEK_END) != 0) + ret = BUFFER_E; + sz = XFTELL(file); + XREWIND(file); + + if (sz <= 0) { + ret = BUFFER_E; + } + else if (sz > (long)sizeof(staticBuffer)) { + #ifdef WOLFSSL_STATIC_MEMORY + WOLFSSL_MSG("File was larger then static buffer"); + return MEMORY_E; + #endif + fileBuf = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_FILE); + if (fileBuf == NULL) + ret = MEMORY_E; + else + dynamic = 1; + } + if (ret == 0) { + if ( (ret = (int)XFREAD(fileBuf, 1, sz, file)) != sz) { + ret = BUFFER_E; + } + #ifdef WOLFSSL_PEM_TO_DER + else { + ret = PemToDer(fileBuf, sz, PUBLICKEY_TYPE, &converted, + 0, NULL, NULL); + } + #endif + + if (ret == 0) { + if (converted->length < (word32)derSz) { + XMEMCPY(derBuf, converted->buffer, converted->length); + ret = converted->length; + } + else + ret = BUFFER_E; + } + + FreeDer(&converted); + } + + XFCLOSE(file); + if (dynamic) + XFREE(fileBuf, NULL, DYNAMIC_TYPE_FILE); + } + + return ret; +} +#endif /* WOLFSSL_CERT_EXT || WOLFSSL_PUB_PEM_TO_DER */ + +#endif /* !NO_FILESYSTEM */ + + +#if !defined(NO_RSA) && (defined(WOLFSSL_CERT_GEN) || \ + ((defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA)) && !defined(HAVE_USER_RSA))) +/* USER RSA ifdef portions used instead of refactor in consideration for + possible fips build */ +/* Write a public RSA key to output */ +static int SetRsaPublicKey(byte* output, RsaKey* key, + int outLen, int with_header) +{ +#ifdef WOLFSSL_SMALL_STACK + byte* n = NULL; + byte* e = NULL; +#else + byte n[MAX_RSA_INT_SZ]; + byte e[MAX_RSA_E_SZ]; +#endif + byte seq[MAX_SEQ_SZ]; + byte bitString[1 + MAX_LENGTH_SZ + 1]; + int nSz; + int eSz; + int seqSz; + int bitStringSz; + int idx; + + if (output == NULL || key == NULL || outLen < MAX_SEQ_SZ) + return BAD_FUNC_ARG; + + /* n */ +#ifdef WOLFSSL_SMALL_STACK + n = (byte*)XMALLOC(MAX_RSA_INT_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (n == NULL) + return MEMORY_E; +#endif + +#ifdef HAVE_USER_RSA + nSz = SetASNIntRSA(key->n, n); +#else + nSz = SetASNIntMP(&key->n, MAX_RSA_INT_SZ, n); +#endif + if (nSz < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(n, key->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return nSz; + } + + /* e */ +#ifdef WOLFSSL_SMALL_STACK + e = (byte*)XMALLOC(MAX_RSA_E_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (e == NULL) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(n, key->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return MEMORY_E; + } +#endif + +#ifdef HAVE_USER_RSA + eSz = SetASNIntRSA(key->e, e); +#else + eSz = SetASNIntMP(&key->e, MAX_RSA_INT_SZ, e); +#endif + if (eSz < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(n, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(e, key->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return eSz; + } + + seqSz = SetSequence(nSz + eSz, seq); + + /* check output size */ + if ( (seqSz + nSz + eSz) > outLen) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(n, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(e, key->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return BUFFER_E; + } + + /* headers */ + if (with_header) { + int algoSz; +#ifdef WOLFSSL_SMALL_STACK + byte* algo = NULL; + + algo = (byte*)XMALLOC(MAX_ALGO_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (algo == NULL) { + XFREE(n, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(e, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#else + byte algo[MAX_ALGO_SZ]; +#endif + algoSz = SetAlgoID(RSAk, algo, oidKeyType, 0); + bitStringSz = SetBitString(seqSz + nSz + eSz, 0, bitString); + + idx = SetSequence(nSz + eSz + seqSz + bitStringSz + algoSz, output); + + /* check output size */ + if ( (idx + algoSz + bitStringSz + seqSz + nSz + eSz) > outLen) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(n, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(e, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(algo, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + return BUFFER_E; + } + + /* algo */ + XMEMCPY(output + idx, algo, algoSz); + idx += algoSz; + /* bit string */ + XMEMCPY(output + idx, bitString, bitStringSz); + idx += bitStringSz; +#ifdef WOLFSSL_SMALL_STACK + XFREE(algo, key->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + } + else + idx = 0; + + /* seq */ + XMEMCPY(output + idx, seq, seqSz); + idx += seqSz; + /* n */ + XMEMCPY(output + idx, n, nSz); + idx += nSz; + /* e */ + XMEMCPY(output + idx, e, eSz); + idx += eSz; + +#ifdef WOLFSSL_SMALL_STACK + XFREE(n, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(e, key->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return idx; +} + +int RsaPublicKeyDerSize(RsaKey* key, int with_header) +{ + byte* dummy = NULL; + byte seq[MAX_SEQ_SZ]; + byte bitString[1 + MAX_LENGTH_SZ + 1]; + int nSz; + int eSz; + int seqSz; + int bitStringSz; + int idx; + + if (key == NULL) + return BAD_FUNC_ARG; + + /* n */ + dummy = (byte*)XMALLOC(MAX_RSA_INT_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (dummy == NULL) + return MEMORY_E; + +#ifdef HAVE_USER_RSA + nSz = SetASNIntRSA(key->n, dummy); +#else + nSz = SetASNIntMP(&key->n, MAX_RSA_INT_SZ, dummy); +#endif + XFREE(dummy, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (nSz < 0) { + return nSz; + } + + /* e */ + dummy = (byte*)XMALLOC(MAX_RSA_E_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (dummy == NULL) { + XFREE(dummy, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } + +#ifdef HAVE_USER_RSA + eSz = SetASNIntRSA(key->e, dummy); +#else + eSz = SetASNIntMP(&key->e, MAX_RSA_INT_SZ, dummy); +#endif + XFREE(dummy, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (eSz < 0) { + return eSz; + } + + seqSz = SetSequence(nSz + eSz, seq); + + /* headers */ + if (with_header) { + int algoSz; + dummy = (byte*)XMALLOC(MAX_RSA_INT_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (dummy == NULL) + return MEMORY_E; + + algoSz = SetAlgoID(RSAk, dummy, oidKeyType, 0); + bitStringSz = SetBitString(seqSz + nSz + eSz, 0, bitString); + + idx = SetSequence(nSz + eSz + seqSz + bitStringSz + algoSz, dummy); + XFREE(dummy, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + + /* algo */ + idx += algoSz; + /* bit string */ + idx += bitStringSz; + } + else + idx = 0; + + /* seq */ + idx += seqSz; + /* n */ + idx += nSz; + /* e */ + idx += eSz; + + return idx; +} +#endif /* !NO_RSA && (WOLFSSL_CERT_GEN || (WOLFSSL_KEY_GEN && + !HAVE_USER_RSA))) */ + + +#if defined(WOLFSSL_KEY_GEN) && !defined(NO_RSA) && !defined(HAVE_USER_RSA) + +static mp_int* GetRsaInt(RsaKey* key, int idx) +{ + if (idx == 0) + return &key->n; + if (idx == 1) + return &key->e; + if (idx == 2) + return &key->d; + if (idx == 3) + return &key->p; + if (idx == 4) + return &key->q; + if (idx == 5) + return &key->dP; + if (idx == 6) + return &key->dQ; + if (idx == 7) + return &key->u; + + return NULL; +} + + +/* Release Tmp RSA resources */ +static WC_INLINE void FreeTmpRsas(byte** tmps, void* heap) +{ + int i; + + (void)heap; + + for (i = 0; i < RSA_INTS; i++) + XFREE(tmps[i], heap, DYNAMIC_TYPE_RSA); +} + + +/* Convert RsaKey key to DER format, write to output (inLen), return bytes + written */ +int wc_RsaKeyToDer(RsaKey* key, byte* output, word32 inLen) +{ + word32 seqSz, verSz, rawLen, intTotalLen = 0; + word32 sizes[RSA_INTS]; + int i, j, outLen, ret = 0, mpSz; + + byte seq[MAX_SEQ_SZ]; + byte ver[MAX_VERSION_SZ]; + byte* tmps[RSA_INTS]; + + if (!key || !output) + return BAD_FUNC_ARG; + + if (key->type != RSA_PRIVATE) + return BAD_FUNC_ARG; + + for (i = 0; i < RSA_INTS; i++) + tmps[i] = NULL; + + /* write all big ints from key to DER tmps */ + for (i = 0; i < RSA_INTS; i++) { + mp_int* keyInt = GetRsaInt(key, i); + + rawLen = mp_unsigned_bin_size(keyInt) + 1; + tmps[i] = (byte*)XMALLOC(rawLen + MAX_SEQ_SZ, key->heap, + DYNAMIC_TYPE_RSA); + if (tmps[i] == NULL) { + ret = MEMORY_E; + break; + } + + mpSz = SetASNIntMP(keyInt, MAX_RSA_INT_SZ, tmps[i]); + if (mpSz < 0) { + ret = mpSz; + break; + } + intTotalLen += (sizes[i] = mpSz); + } + + if (ret != 0) { + FreeTmpRsas(tmps, key->heap); + return ret; + } + + /* make headers */ + verSz = SetMyVersion(0, ver, FALSE); + seqSz = SetSequence(verSz + intTotalLen, seq); + + outLen = seqSz + verSz + intTotalLen; + if (outLen > (int)inLen) { + FreeTmpRsas(tmps, key->heap); + return BAD_FUNC_ARG; + } + + /* write to output */ + XMEMCPY(output, seq, seqSz); + j = seqSz; + XMEMCPY(output + j, ver, verSz); + j += verSz; + + for (i = 0; i < RSA_INTS; i++) { + XMEMCPY(output + j, tmps[i], sizes[i]); + j += sizes[i]; + } + FreeTmpRsas(tmps, key->heap); + + return outLen; +} +#endif + +#if (defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA)) && !defined(NO_RSA) && !defined(HAVE_USER_RSA) +/* Convert Rsa Public key to DER format, write to output (inLen), return bytes + written */ +int wc_RsaKeyToPublicDer(RsaKey* key, byte* output, word32 inLen) +{ + return SetRsaPublicKey(output, key, inLen, 1); +} + +#endif /* (WOLFSSL_KEY_GEN || OPENSSL_EXTRA) && !NO_RSA && !HAVE_USER_RSA */ + + +#ifdef WOLFSSL_CERT_GEN + +/* Initialize and Set Certificate defaults: + version = 3 (0x2) + serial = 0 + sigType = SHA_WITH_RSA + issuer = blank + daysValid = 500 + selfSigned = 1 (true) use subject as issuer + subject = blank +*/ +int wc_InitCert(Cert* cert) +{ +#ifdef WOLFSSL_MULTI_ATTRIB + int i = 0; +#endif + if (cert == NULL) { + return BAD_FUNC_ARG; + } + + XMEMSET(cert, 0, sizeof(Cert)); + + cert->version = 2; /* version 3 is hex 2 */ +#ifndef NO_SHA + cert->sigType = CTC_SHAwRSA; +#elif !defined(NO_SHA256) + cert->sigType = CTC_SHA256wRSA; +#else + cert->sigType = 0; +#endif + cert->daysValid = 500; + cert->selfSigned = 1; + cert->keyType = RSA_KEY; + + cert->issuer.countryEnc = CTC_PRINTABLE; + cert->issuer.stateEnc = CTC_UTF8; + cert->issuer.localityEnc = CTC_UTF8; + cert->issuer.surEnc = CTC_UTF8; + cert->issuer.orgEnc = CTC_UTF8; + cert->issuer.unitEnc = CTC_UTF8; + cert->issuer.commonNameEnc = CTC_UTF8; + + cert->subject.countryEnc = CTC_PRINTABLE; + cert->subject.stateEnc = CTC_UTF8; + cert->subject.localityEnc = CTC_UTF8; + cert->subject.surEnc = CTC_UTF8; + cert->subject.orgEnc = CTC_UTF8; + cert->subject.unitEnc = CTC_UTF8; + cert->subject.commonNameEnc = CTC_UTF8; + +#ifdef WOLFSSL_MULTI_ATTRIB + for (i = 0; i < CTC_MAX_ATTRIB; i++) { + cert->issuer.name[i].type = CTC_UTF8; + cert->subject.name[i].type = CTC_UTF8; + } +#endif /* WOLFSSL_MULTI_ATTRIB */ + +#ifdef WOLFSSL_HEAP_TEST + cert->heap = (void*)WOLFSSL_HEAP_TEST; +#endif + + return 0; +} + + +/* DER encoded x509 Certificate */ +typedef struct DerCert { + byte size[MAX_LENGTH_SZ]; /* length encoded */ + byte version[MAX_VERSION_SZ]; /* version encoded */ + byte serial[(int)CTC_SERIAL_SIZE + (int)MAX_LENGTH_SZ]; /* serial number encoded */ + byte sigAlgo[MAX_ALGO_SZ]; /* signature algo encoded */ + byte issuer[ASN_NAME_MAX]; /* issuer encoded */ + byte subject[ASN_NAME_MAX]; /* subject encoded */ + byte validity[MAX_DATE_SIZE*2 + MAX_SEQ_SZ*2]; /* before and after dates */ + byte publicKey[MAX_PUBLIC_KEY_SZ]; /* rsa / ntru public key encoded */ + byte ca[MAX_CA_SZ]; /* basic constraint CA true size */ + byte extensions[MAX_EXTENSIONS_SZ]; /* all extensions */ +#ifdef WOLFSSL_CERT_EXT + byte skid[MAX_KID_SZ]; /* Subject Key Identifier extension */ + byte akid[MAX_KID_SZ]; /* Authority Key Identifier extension */ + byte keyUsage[MAX_KEYUSAGE_SZ]; /* Key Usage extension */ + byte extKeyUsage[MAX_EXTKEYUSAGE_SZ]; /* Extended Key Usage extension */ + byte certPolicies[MAX_CERTPOL_NB*MAX_CERTPOL_SZ]; /* Certificate Policies */ +#endif +#ifdef WOLFSSL_CERT_REQ + byte attrib[MAX_ATTRIB_SZ]; /* Cert req attributes encoded */ +#endif +#ifdef WOLFSSL_ALT_NAMES + byte altNames[CTC_MAX_ALT_SIZE]; /* Alternative Names encoded */ +#endif + int sizeSz; /* encoded size length */ + int versionSz; /* encoded version length */ + int serialSz; /* encoded serial length */ + int sigAlgoSz; /* encoded sig alog length */ + int issuerSz; /* encoded issuer length */ + int subjectSz; /* encoded subject length */ + int validitySz; /* encoded validity length */ + int publicKeySz; /* encoded public key length */ + int caSz; /* encoded CA extension length */ +#ifdef WOLFSSL_CERT_EXT + int skidSz; /* encoded SKID extension length */ + int akidSz; /* encoded SKID extension length */ + int keyUsageSz; /* encoded KeyUsage extension length */ + int extKeyUsageSz; /* encoded ExtendedKeyUsage extension length */ + int certPoliciesSz; /* encoded CertPolicies extension length*/ +#endif +#ifdef WOLFSSL_ALT_NAMES + int altNamesSz; /* encoded AltNames extension length */ +#endif + int extensionsSz; /* encoded extensions total length */ + int total; /* total encoded lengths */ +#ifdef WOLFSSL_CERT_REQ + int attribSz; +#endif +} DerCert; + + +#ifdef WOLFSSL_CERT_REQ + +/* Write a set header to output */ +static word32 SetPrintableString(word32 len, byte* output) +{ + output[0] = ASN_PRINTABLE_STRING; + return SetLength(len, output + 1) + 1; +} + +static word32 SetUTF8String(word32 len, byte* output) +{ + output[0] = ASN_UTF8STRING; + return SetLength(len, output + 1) + 1; +} + +#endif /* WOLFSSL_CERT_REQ */ + + +#ifndef WOLFSSL_CERT_GEN_CACHE +/* wc_SetCert_Free is only public when WOLFSSL_CERT_GEN_CACHE is not defined */ +static +#endif +void wc_SetCert_Free(Cert* cert) +{ + if (cert != NULL) { + + if (cert->der != NULL) { + cert->der = NULL; + } + + if (cert->decodedCert) { + FreeDecodedCert((DecodedCert*)cert->decodedCert); + + XFREE(cert->decodedCert, cert->heap, DYNAMIC_TYPE_DCERT); + cert->decodedCert = NULL; + } + } +} + +static int wc_SetCert_LoadDer(Cert* cert, const byte* der, word32 derSz) +{ + int ret; + + if (cert == NULL) { + ret = BAD_FUNC_ARG; + } + else { + /* Allocate DecodedCert struct and Zero */ + cert->decodedCert = (void*)XMALLOC(sizeof(DecodedCert), cert->heap, + DYNAMIC_TYPE_DCERT); + + if (cert->decodedCert == NULL) { + ret = MEMORY_E; + } + else { + XMEMSET(cert->decodedCert, 0, sizeof(DecodedCert)); + + InitDecodedCert((DecodedCert*)cert->decodedCert, der, derSz, + cert->heap); + ret = ParseCertRelative((DecodedCert*)cert->decodedCert, + CERT_TYPE, 0, NULL); + if (ret >= 0) { + cert->der = (byte*)der; + } + else { + wc_SetCert_Free(cert); + } + } + } + + return ret; +} + +#endif /* WOLFSSL_CERT_GEN */ + + +#if defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT) + +/* Write a public ECC key to output */ +static int SetEccPublicKey(byte* output, ecc_key* key, int with_header) +{ + byte bitString[1 + MAX_LENGTH_SZ + 1]; + int algoSz; + int curveSz; + int bitStringSz; + int idx; + word32 pubSz = ECC_BUFSIZE; +#ifdef WOLFSSL_SMALL_STACK + byte* algo = NULL; + byte* curve = NULL; + byte* pub = NULL; +#else + byte algo[MAX_ALGO_SZ]; + byte curve[MAX_ALGO_SZ]; + byte pub[ECC_BUFSIZE]; +#endif + int ret; + +#ifdef WOLFSSL_SMALL_STACK + pub = (byte*)XMALLOC(ECC_BUFSIZE, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (pub == NULL) + return MEMORY_E; +#endif + + ret = wc_ecc_export_x963(key, pub, &pubSz); + if (ret != 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + /* headers */ + if (with_header) { +#ifdef WOLFSSL_SMALL_STACK + curve = (byte*)XMALLOC(MAX_ALGO_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (curve == NULL) { + XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#endif + curveSz = SetCurve(key, curve); + if (curveSz <= 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(curve, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return curveSz; + } + +#ifdef WOLFSSL_SMALL_STACK + algo = (byte*)XMALLOC(MAX_ALGO_SZ, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (algo == NULL) { + XFREE(curve, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#endif + algoSz = SetAlgoID(ECDSAk, algo, oidKeyType, curveSz); + + bitStringSz = SetBitString(pubSz, 0, bitString); + + idx = SetSequence(pubSz + curveSz + bitStringSz + algoSz, output); + /* algo */ + XMEMCPY(output + idx, algo, algoSz); + idx += algoSz; + /* curve */ + XMEMCPY(output + idx, curve, curveSz); + idx += curveSz; + /* bit string */ + XMEMCPY(output + idx, bitString, bitStringSz); + idx += bitStringSz; + } + else + idx = 0; + + /* pub */ + XMEMCPY(output + idx, pub, pubSz); + idx += pubSz; + +#ifdef WOLFSSL_SMALL_STACK + if (with_header) { + XFREE(algo, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(curve, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + } + XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return idx; +} + + +/* returns the size of buffer used, the public ECC key in DER format is stored + in output buffer + with_AlgCurve is a flag for when to include a header that has the Algorithm + and Curve information */ +int wc_EccPublicKeyToDer(ecc_key* key, byte* output, word32 inLen, + int with_AlgCurve) +{ + word32 infoSz = 0; + word32 keySz = 0; + int ret; + + if (output == NULL || key == NULL) { + return BAD_FUNC_ARG; + } + + if (with_AlgCurve) { + /* buffer space for algorithm/curve */ + infoSz += MAX_SEQ_SZ; + infoSz += 2 * MAX_ALGO_SZ; + + /* buffer space for public key sequence */ + infoSz += MAX_SEQ_SZ; + infoSz += TRAILING_ZERO; + } + + if ((ret = wc_ecc_export_x963(key, NULL, &keySz)) != LENGTH_ONLY_E) { + WOLFSSL_MSG("Error in getting ECC public key size"); + return ret; + } + + if (inLen < keySz + infoSz) { + return BUFFER_E; + } + + return SetEccPublicKey(output, key, with_AlgCurve); +} +#endif /* HAVE_ECC && HAVE_ECC_KEY_EXPORT */ + +#if defined(HAVE_ED25519) && (defined(WOLFSSL_CERT_GEN) || \ + defined(WOLFSSL_KEY_GEN)) + +/* Write a public ECC key to output */ +static int SetEd25519PublicKey(byte* output, ed25519_key* key, int with_header) +{ + byte bitString[1 + MAX_LENGTH_SZ + 1]; + int algoSz; + int bitStringSz; + int idx; + word32 pubSz = ED25519_PUB_KEY_SIZE; +#ifdef WOLFSSL_SMALL_STACK + byte* algo = NULL; + byte* pub = NULL; +#else + byte algo[MAX_ALGO_SZ]; + byte pub[ED25519_PUB_KEY_SIZE]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + pub = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (pub == NULL) + return MEMORY_E; +#endif + + idx = wc_ed25519_export_public(key, pub, &pubSz); + if (idx != 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return idx; + } + + /* headers */ + if (with_header) { +#ifdef WOLFSSL_SMALL_STACK + algo = (byte*)XMALLOC(MAX_ALGO_SZ, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (algo == NULL) { + XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#endif + algoSz = SetAlgoID(ED25519k, algo, oidKeyType, 0); + + bitStringSz = SetBitString(pubSz, 0, bitString); + + idx = SetSequence(pubSz + bitStringSz + algoSz, output); + /* algo */ + XMEMCPY(output + idx, algo, algoSz); + idx += algoSz; + /* bit string */ + XMEMCPY(output + idx, bitString, bitStringSz); + idx += bitStringSz; + } + else + idx = 0; + + /* pub */ + XMEMCPY(output + idx, pub, pubSz); + idx += pubSz; + +#ifdef WOLFSSL_SMALL_STACK + if (with_header) { + XFREE(algo, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + XFREE(pub, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return idx; +} + +int wc_Ed25519PublicKeyToDer(ed25519_key* key, byte* output, word32 inLen, + int withAlg) +{ + word32 infoSz = 0; + word32 keySz = 0; + int ret; + + if (output == NULL || key == NULL) { + return BAD_FUNC_ARG; + } + + if (withAlg) { + /* buffer space for algorithm */ + infoSz += MAX_SEQ_SZ; + infoSz += MAX_ALGO_SZ; + + /* buffer space for public key sequence */ + infoSz += MAX_SEQ_SZ; + infoSz += TRAILING_ZERO; + } + + if ((ret = wc_ed25519_export_public(key, output, &keySz)) != BUFFER_E) { + WOLFSSL_MSG("Error in getting ECC public key size"); + return ret; + } + + if (inLen < keySz + infoSz) { + return BUFFER_E; + } + + return SetEd25519PublicKey(output, key, withAlg); +} +#endif /* HAVE_ED25519 && (WOLFSSL_CERT_GEN || WOLFSSL_KEY_GEN) */ + + +#ifdef WOLFSSL_CERT_GEN + +static WC_INLINE byte itob(int number) +{ + return (byte)number + 0x30; +} + + +/* write time to output, format */ +static void SetTime(struct tm* date, byte* output) +{ + int i = 0; + + output[i++] = itob((date->tm_year % 10000) / 1000); + output[i++] = itob((date->tm_year % 1000) / 100); + output[i++] = itob((date->tm_year % 100) / 10); + output[i++] = itob( date->tm_year % 10); + + output[i++] = itob(date->tm_mon / 10); + output[i++] = itob(date->tm_mon % 10); + + output[i++] = itob(date->tm_mday / 10); + output[i++] = itob(date->tm_mday % 10); + + output[i++] = itob(date->tm_hour / 10); + output[i++] = itob(date->tm_hour % 10); + + output[i++] = itob(date->tm_min / 10); + output[i++] = itob(date->tm_min % 10); + + output[i++] = itob(date->tm_sec / 10); + output[i++] = itob(date->tm_sec % 10); + + output[i] = 'Z'; /* Zulu profile */ +} + + +#ifdef WOLFSSL_ALT_NAMES + +/* Copy Dates from cert, return bytes written */ +static int CopyValidity(byte* output, Cert* cert) +{ + int seqSz; + + WOLFSSL_ENTER("CopyValidity"); + + /* headers and output */ + seqSz = SetSequence(cert->beforeDateSz + cert->afterDateSz, output); + XMEMCPY(output + seqSz, cert->beforeDate, cert->beforeDateSz); + XMEMCPY(output + seqSz + cert->beforeDateSz, cert->afterDate, + cert->afterDateSz); + return seqSz + cert->beforeDateSz + cert->afterDateSz; +} + +#endif + + +/* Set Date validity from now until now + daysValid + * return size in bytes written to output, 0 on error */ +static int SetValidity(byte* output, int daysValid) +{ + byte before[MAX_DATE_SIZE]; + byte after[MAX_DATE_SIZE]; + + int beforeSz; + int afterSz; + int seqSz; + + time_t now; + time_t then; + struct tm* tmpTime = NULL; + struct tm* expandedTime; + struct tm localTime; + +#if defined(NEED_TMP_TIME) + /* for use with gmtime_r */ + struct tm tmpTimeStorage; + tmpTime = &tmpTimeStorage; +#else + (void)tmpTime; +#endif + + now = XTIME(0); + + /* before now */ + before[0] = ASN_GENERALIZED_TIME; + beforeSz = SetLength(ASN_GEN_TIME_SZ, before + 1) + 1; /* gen tag */ + + /* subtract 1 day of seconds for more compliance */ + then = now - 86400; + expandedTime = XGMTIME(&then, tmpTime); + if (expandedTime == NULL) { + WOLFSSL_MSG("XGMTIME failed"); + return 0; /* error */ + } + localTime = *expandedTime; + + /* adjust */ + localTime.tm_year += 1900; + localTime.tm_mon += 1; + + SetTime(&localTime, before + beforeSz); + beforeSz += ASN_GEN_TIME_SZ; + + after[0] = ASN_GENERALIZED_TIME; + afterSz = SetLength(ASN_GEN_TIME_SZ, after + 1) + 1; /* gen tag */ + + /* add daysValid of seconds */ + then = now + (daysValid * (time_t)86400); + expandedTime = XGMTIME(&then, tmpTime); + if (expandedTime == NULL) { + WOLFSSL_MSG("XGMTIME failed"); + return 0; /* error */ + } + localTime = *expandedTime; + + /* adjust */ + localTime.tm_year += 1900; + localTime.tm_mon += 1; + + SetTime(&localTime, after + afterSz); + afterSz += ASN_GEN_TIME_SZ; + + /* headers and output */ + seqSz = SetSequence(beforeSz + afterSz, output); + XMEMCPY(output + seqSz, before, beforeSz); + XMEMCPY(output + seqSz + beforeSz, after, afterSz); + + return seqSz + beforeSz + afterSz; +} + + +/* ASN Encoded Name field */ +typedef struct EncodedName { + int nameLen; /* actual string value length */ + int totalLen; /* total encoded length */ + int type; /* type of name */ + int used; /* are we actually using this one */ + byte encoded[CTC_NAME_SIZE * 2]; /* encoding */ +} EncodedName; + + +/* Get Which Name from index */ +static const char* GetOneName(CertName* name, int idx) +{ + switch (idx) { + case 0: + return name->country; + + case 1: + return name->state; + + case 2: + return name->locality; + + case 3: + return name->sur; + + case 4: + return name->org; + + case 5: + return name->unit; + + case 6: + return name->commonName; + + case 7: + return name->serialDev; + +#ifdef WOLFSSL_CERT_EXT + case 8: + return name->busCat; + + case 9: +#else + case 8: +#endif + return name->email; + + default: + return 0; + } +} + + +/* Get Which Name Encoding from index */ +static char GetNameType(CertName* name, int idx) +{ + switch (idx) { + case 0: + return name->countryEnc; + + case 1: + return name->stateEnc; + + case 2: + return name->localityEnc; + + case 3: + return name->surEnc; + + case 4: + return name->orgEnc; + + case 5: + return name->unitEnc; + + case 6: + return name->commonNameEnc; + + case 7: + return name->serialDevEnc; + +#ifdef WOLFSSL_CERT_EXT + case 8: + return name->busCatEnc; + + case 9: +#else + case 8: +#endif + /* FALL THROUGH */ + /* The last index, email name, does not have encoding type. + The empty case here is to keep track of it for future reference. */ + default: + return 0; + } +} + + +/* Get ASN Name from index */ +static byte GetNameId(int idx) +{ + switch (idx) { + case 0: + return ASN_COUNTRY_NAME; + + case 1: + return ASN_STATE_NAME; + + case 2: + return ASN_LOCALITY_NAME; + + case 3: + return ASN_SUR_NAME; + + case 4: + return ASN_ORG_NAME; + + case 5: + return ASN_ORGUNIT_NAME; + + case 6: + return ASN_COMMON_NAME; + + case 7: + return ASN_SERIAL_NUMBER; + +#ifdef WOLFSSL_CERT_EXT + case 8: + return ASN_BUS_CAT; + + case 9: +#else + case 8: +#endif + return ASN_EMAIL_NAME; + + default: + return 0; + } +} + +/* + Extensions ::= SEQUENCE OF Extension + + Extension ::= SEQUENCE { + extnId OBJECT IDENTIFIER, + critical BOOLEAN DEFAULT FALSE, + extnValue OCTET STRING } + */ + +/* encode all extensions, return total bytes written */ +static int SetExtensions(byte* out, word32 outSz, int *IdxInOut, + const byte* ext, int extSz) +{ + if (out == NULL || IdxInOut == NULL || ext == NULL) + return BAD_FUNC_ARG; + + if (outSz < (word32)(*IdxInOut+extSz)) + return BUFFER_E; + + XMEMCPY(&out[*IdxInOut], ext, extSz); /* extensions */ + *IdxInOut += extSz; + + return *IdxInOut; +} + +/* encode extensions header, return total bytes written */ +static int SetExtensionsHeader(byte* out, word32 outSz, int extSz) +{ + byte sequence[MAX_SEQ_SZ]; + byte len[MAX_LENGTH_SZ]; + int seqSz, lenSz, idx = 0; + + if (out == NULL) + return BAD_FUNC_ARG; + + if (outSz < 3) + return BUFFER_E; + + seqSz = SetSequence(extSz, sequence); + + /* encode extensions length provided */ + lenSz = SetLength(extSz+seqSz, len); + + if (outSz < (word32)(lenSz+seqSz+1)) + return BUFFER_E; + + out[idx++] = ASN_EXTENSIONS; /* extensions id */ + XMEMCPY(&out[idx], len, lenSz); /* length */ + idx += lenSz; + + XMEMCPY(&out[idx], sequence, seqSz); /* sequence */ + idx += seqSz; + + return idx; +} + + +/* encode CA basic constraint true, return total bytes written */ +static int SetCa(byte* out, word32 outSz) +{ + static const byte ca[] = { 0x30, 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, + 0x05, 0x30, 0x03, 0x01, 0x01, 0xff }; + + if (out == NULL) + return BAD_FUNC_ARG; + + if (outSz < sizeof(ca)) + return BUFFER_E; + + XMEMCPY(out, ca, sizeof(ca)); + + return (int)sizeof(ca); +} + + +#ifdef WOLFSSL_CERT_EXT +/* encode OID and associated value, return total bytes written */ +static int SetOidValue(byte* out, word32 outSz, const byte *oid, word32 oidSz, + byte *in, word32 inSz) +{ + int idx = 0; + + if (out == NULL || oid == NULL || in == NULL) + return BAD_FUNC_ARG; + + if (outSz < 3) + return BUFFER_E; + + /* sequence, + 1 => byte to put value size */ + idx = SetSequence(inSz + oidSz + 1, out); + + if ((idx + inSz + oidSz + 1) > outSz) + return BUFFER_E; + + XMEMCPY(out+idx, oid, oidSz); + idx += oidSz; + out[idx++] = (byte)inSz; + XMEMCPY(out+idx, in, inSz); + + return (idx+inSz); +} + +/* encode Subject Key Identifier, return total bytes written + * RFC5280 : non-critical */ +static int SetSKID(byte* output, word32 outSz, const byte *input, word32 length) +{ + byte skid_len[1 + MAX_LENGTH_SZ]; + byte skid_enc_len[MAX_LENGTH_SZ]; + int idx = 0, skid_lenSz, skid_enc_lenSz; + static const byte skid_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04 }; + + if (output == NULL || input == NULL) + return BAD_FUNC_ARG; + + /* Octet String header */ + skid_lenSz = SetOctetString(length, skid_len); + + /* length of encoded value */ + skid_enc_lenSz = SetLength(length + skid_lenSz, skid_enc_len); + + if (outSz < 3) + return BUFFER_E; + + idx = SetSequence(length + sizeof(skid_oid) + skid_lenSz + skid_enc_lenSz, + output); + + if ((length + sizeof(skid_oid) + skid_lenSz + skid_enc_lenSz) > outSz) + return BUFFER_E; + + /* put oid */ + XMEMCPY(output+idx, skid_oid, sizeof(skid_oid)); + idx += sizeof(skid_oid); + + /* put encoded len */ + XMEMCPY(output+idx, skid_enc_len, skid_enc_lenSz); + idx += skid_enc_lenSz; + + /* put octet header */ + XMEMCPY(output+idx, skid_len, skid_lenSz); + idx += skid_lenSz; + + /* put value */ + XMEMCPY(output+idx, input, length); + idx += length; + + return idx; +} + +/* encode Authority Key Identifier, return total bytes written + * RFC5280 : non-critical */ +static int SetAKID(byte* output, word32 outSz, + byte *input, word32 length, void* heap) +{ + byte *enc_val; + int ret, enc_valSz; + static const byte akid_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04 }; + static const byte akid_cs[] = { 0x80 }; + + if (output == NULL || input == NULL) + return BAD_FUNC_ARG; + + enc_valSz = length + 3 + sizeof(akid_cs); + enc_val = (byte *)XMALLOC(enc_valSz, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (enc_val == NULL) + return MEMORY_E; + + /* sequence for ContentSpec & value */ + ret = SetOidValue(enc_val, enc_valSz, akid_cs, sizeof(akid_cs), + input, length); + if (ret > 0) { + enc_valSz = ret; + + ret = SetOidValue(output, outSz, akid_oid, sizeof(akid_oid), + enc_val, enc_valSz); + } + + XFREE(enc_val, heap, DYNAMIC_TYPE_TMP_BUFFER); + return ret; +} + +/* encode Key Usage, return total bytes written + * RFC5280 : critical */ +static int SetKeyUsage(byte* output, word32 outSz, word16 input) +{ + byte ku[5]; + int idx; + static const byte keyusage_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x0f, + 0x01, 0x01, 0xff, 0x04}; + if (output == NULL) + return BAD_FUNC_ARG; + + idx = SetBitString16Bit(input, ku); + return SetOidValue(output, outSz, keyusage_oid, sizeof(keyusage_oid), + ku, idx); +} + +static int SetOjectIdValue(byte* output, word32 outSz, int* idx, + const byte* oid, word32 oidSz) +{ + /* verify room */ + if (*idx + 2 + oidSz >= outSz) + return ASN_PARSE_E; + + *idx += SetObjectId(oidSz, &output[*idx]); + XMEMCPY(&output[*idx], oid, oidSz); + *idx += oidSz; + + return 0; +} + +/* encode Extended Key Usage (RFC 5280 4.2.1.12), return total bytes written */ +static int SetExtKeyUsage(Cert* cert, byte* output, word32 outSz, byte input) +{ + int idx = 0, oidListSz = 0, totalSz, ret = 0; + static const byte extkeyusage_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x25 }; + + if (output == NULL) + return BAD_FUNC_ARG; + + /* Skip to OID List */ + totalSz = 2 + sizeof(extkeyusage_oid) + 4; + idx = totalSz; + + /* Build OID List */ + /* If any set, then just use it */ + if (input & EXTKEYUSE_ANY) { + ret |= SetOjectIdValue(output, outSz, &idx, + extExtKeyUsageAnyOid, sizeof(extExtKeyUsageAnyOid)); + } + else { + if (input & EXTKEYUSE_SERVER_AUTH) + ret |= SetOjectIdValue(output, outSz, &idx, + extExtKeyUsageServerAuthOid, sizeof(extExtKeyUsageServerAuthOid)); + if (input & EXTKEYUSE_CLIENT_AUTH) + ret |= SetOjectIdValue(output, outSz, &idx, + extExtKeyUsageClientAuthOid, sizeof(extExtKeyUsageClientAuthOid)); + if (input & EXTKEYUSE_CODESIGN) + ret |= SetOjectIdValue(output, outSz, &idx, + extExtKeyUsageCodeSigningOid, sizeof(extExtKeyUsageCodeSigningOid)); + if (input & EXTKEYUSE_EMAILPROT) + ret |= SetOjectIdValue(output, outSz, &idx, + extExtKeyUsageEmailProtectOid, sizeof(extExtKeyUsageEmailProtectOid)); + if (input & EXTKEYUSE_TIMESTAMP) + ret |= SetOjectIdValue(output, outSz, &idx, + extExtKeyUsageTimestampOid, sizeof(extExtKeyUsageTimestampOid)); + if (input & EXTKEYUSE_OCSP_SIGN) + ret |= SetOjectIdValue(output, outSz, &idx, + extExtKeyUsageOcspSignOid, sizeof(extExtKeyUsageOcspSignOid)); + #ifdef WOLFSSL_EKU_OID + /* iterate through OID values */ + if (input & EXTKEYUSE_USER) { + int i, sz; + for (i = 0; i < CTC_MAX_EKU_NB; i++) { + sz = cert->extKeyUsageOIDSz[i]; + if (sz > 0) { + ret |= SetOjectIdValue(output, outSz, &idx, + cert->extKeyUsageOID[i], sz); + } + } + } + #endif /* WOLFSSL_EKU_OID */ + } + if (ret != 0) + return ASN_PARSE_E; + + /* Calculate Sizes */ + oidListSz = idx - totalSz; + totalSz = idx - 2; /* exclude first seq/len (2) */ + + /* 1. Seq + Total Len (2) */ + idx = SetSequence(totalSz, output); + + /* 2. Object ID (2) */ + XMEMCPY(&output[idx], extkeyusage_oid, sizeof(extkeyusage_oid)); + idx += sizeof(extkeyusage_oid); + + /* 3. Octect String (2) */ + idx += SetOctetString(totalSz - idx, &output[idx]); + + /* 4. Seq + OidListLen (2) */ + idx += SetSequence(oidListSz, &output[idx]); + + /* 5. Oid List (already set in-place above) */ + idx += oidListSz; + + (void)cert; + return idx; +} + +/* Encode OID string representation to ITU-T X.690 format */ +int EncodePolicyOID(byte *out, word32 *outSz, const char *in, void* heap) +{ + word32 val, idx = 0, nb_val; + char *token, *str, *ptr; + word32 len; + + if (out == NULL || outSz == NULL || *outSz < 2 || in == NULL) + return BAD_FUNC_ARG; + + len = (word32)XSTRLEN(in); + + str = (char *)XMALLOC(len+1, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (str == NULL) + return MEMORY_E; + + XSTRNCPY(str, in, len+1); + + nb_val = 0; + + /* parse value, and set corresponding Policy OID value */ + token = XSTRTOK(str, ".", &ptr); + while (token != NULL) + { + val = (word32)atoi(token); + + if (nb_val == 0) { + if (val > 2) { + XFREE(str, heap, DYNAMIC_TYPE_TMP_BUFFER); + return ASN_OBJECT_ID_E; + } + + out[idx] = (byte)(40 * val); + } + else if (nb_val == 1) { + if (val > 127) { + XFREE(str, heap, DYNAMIC_TYPE_TMP_BUFFER); + return ASN_OBJECT_ID_E; + } + + if (idx > *outSz) { + XFREE(str, heap, DYNAMIC_TYPE_TMP_BUFFER); + return BUFFER_E; + } + + out[idx++] += (byte)val; + } + else { + word32 tb = 0, x; + int i = 0; + byte oid[MAX_OID_SZ]; + + while (val >= 128) { + x = val % 128; + val /= 128; + oid[i++] = (byte) (((tb++) ? 0x80 : 0) | x); + } + + if ((idx+(word32)i) > *outSz) { + XFREE(str, heap, DYNAMIC_TYPE_TMP_BUFFER); + return BUFFER_E; + } + + oid[i] = (byte) (((tb++) ? 0x80 : 0) | val); + + /* push value in the right order */ + while (i >= 0) + out[idx++] = oid[i--]; + } + + token = XSTRTOK(NULL, ".", &ptr); + nb_val++; + } + + *outSz = idx; + + XFREE(str, heap, DYNAMIC_TYPE_TMP_BUFFER); + return 0; +} + +/* encode Certificate Policies, return total bytes written + * each input value must be ITU-T X.690 formatted : a.b.c... + * input must be an array of values with a NULL terminated for the latest + * RFC5280 : non-critical */ +static int SetCertificatePolicies(byte *output, + word32 outputSz, + char input[MAX_CERTPOL_NB][MAX_CERTPOL_SZ], + word16 nb_certpol, + void* heap) +{ + byte oid[MAX_OID_SZ], + der_oid[MAX_CERTPOL_NB][MAX_OID_SZ], + out[MAX_CERTPOL_SZ]; + word32 oidSz; + word32 outSz, i = 0, der_oidSz[MAX_CERTPOL_NB]; + int ret; + + static const byte certpol_oid[] = { 0x06, 0x03, 0x55, 0x1d, 0x20, 0x04 }; + static const byte oid_oid[] = { 0x06 }; + + if (output == NULL || input == NULL || nb_certpol > MAX_CERTPOL_NB) + return BAD_FUNC_ARG; + + for (i = 0; i < nb_certpol; i++) { + oidSz = sizeof(oid); + XMEMSET(oid, 0, oidSz); + + ret = EncodePolicyOID(oid, &oidSz, input[i], heap); + if (ret != 0) + return ret; + + /* compute sequence value for the oid */ + ret = SetOidValue(der_oid[i], MAX_OID_SZ, oid_oid, + sizeof(oid_oid), oid, oidSz); + if (ret <= 0) + return ret; + else + der_oidSz[i] = (word32)ret; + } + + /* concatenate oid, keep two byte for sequence/size of the created value */ + for (i = 0, outSz = 2; i < nb_certpol; i++) { + XMEMCPY(out+outSz, der_oid[i], der_oidSz[i]); + outSz += der_oidSz[i]; + } + + /* add sequence */ + ret = SetSequence(outSz-2, out); + if (ret <= 0) + return ret; + + /* add Policy OID to compute final value */ + return SetOidValue(output, outputSz, certpol_oid, sizeof(certpol_oid), + out, outSz); +} +#endif /* WOLFSSL_CERT_EXT */ + +#ifdef WOLFSSL_ALT_NAMES +/* encode Alternative Names, return total bytes written */ +static int SetAltNames(byte *out, word32 outSz, byte *input, word32 length) +{ + if (out == NULL || input == NULL) + return BAD_FUNC_ARG; + + if (outSz < length) + return BUFFER_E; + + /* Alternative Names come from certificate or computed by + * external function, so already encoded. Just copy value */ + XMEMCPY(out, input, length); + return length; +} +#endif /* WOLFSL_ALT_NAMES */ + +/* Encodes one attribute of the name (issuer/subject) + * + * name structure to hold result of encoding + * nameStr value to be encoded + * nameType type of encoding i.e CTC_UTF8 + * type id of attribute i.e ASN_COMMON_NAME + * + * returns length on success + */ +static int wc_EncodeName(EncodedName* name, const char* nameStr, char nameType, + byte type) +{ + word32 idx = 0; + + if (nameStr) { + /* bottom up */ + byte firstLen[1 + MAX_LENGTH_SZ]; + byte secondLen[MAX_LENGTH_SZ]; + byte sequence[MAX_SEQ_SZ]; + byte set[MAX_SET_SZ]; + + int strLen = (int)XSTRLEN(nameStr); + int thisLen = strLen; + int firstSz, secondSz, seqSz, setSz; + + if (strLen == 0) { /* no user data for this item */ + name->used = 0; + return 0; + } + + /* Restrict country code size */ + if (ASN_COUNTRY_NAME == type && strLen != CTC_COUNTRY_SIZE) { + return ASN_COUNTRY_SIZE_E; + } + + secondSz = SetLength(strLen, secondLen); + thisLen += secondSz; + switch (type) { + case ASN_EMAIL_NAME: /* email */ + thisLen += EMAIL_JOINT_LEN; + firstSz = EMAIL_JOINT_LEN; + break; + + case ASN_DOMAIN_COMPONENT: + thisLen += PILOT_JOINT_LEN; + firstSz = PILOT_JOINT_LEN; + break; + + default: + thisLen++; /* str type */ + thisLen += JOINT_LEN; + firstSz = JOINT_LEN + 1; + } + thisLen++; /* id type */ + firstSz = SetObjectId(firstSz, firstLen); + thisLen += firstSz; + + seqSz = SetSequence(thisLen, sequence); + thisLen += seqSz; + setSz = SetSet(thisLen, set); + thisLen += setSz; + + if (thisLen > (int)sizeof(name->encoded)) { + return BUFFER_E; + } + + /* store it */ + idx = 0; + /* set */ + XMEMCPY(name->encoded, set, setSz); + idx += setSz; + /* seq */ + XMEMCPY(name->encoded + idx, sequence, seqSz); + idx += seqSz; + /* asn object id */ + XMEMCPY(name->encoded + idx, firstLen, firstSz); + idx += firstSz; + switch (type) { + case ASN_EMAIL_NAME: + { + const byte EMAIL_OID[] = { 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, + 0x01, 0x09, 0x01, 0x16 }; + /* email joint id */ + XMEMCPY(name->encoded + idx, EMAIL_OID, sizeof(EMAIL_OID)); + idx += (int)sizeof(EMAIL_OID); + } + break; + + case ASN_DOMAIN_COMPONENT: + { + const byte PILOT_OID[] = { 0x09, 0x92, 0x26, 0x89, + 0x93, 0xF2, 0x2C, 0x64, 0x01 + }; + + XMEMCPY(name->encoded + idx, PILOT_OID, + sizeof(PILOT_OID)); + idx += (int)sizeof(PILOT_OID); + /* id type */ + name->encoded[idx++] = type; + /* str type */ + name->encoded[idx++] = nameType; + } + break; + + default: + name->encoded[idx++] = 0x55; + name->encoded[idx++] = 0x04; + /* id type */ + name->encoded[idx++] = type; + /* str type */ + name->encoded[idx++] = nameType; + } + /* second length */ + XMEMCPY(name->encoded + idx, secondLen, secondSz); + idx += secondSz; + /* str value */ + XMEMCPY(name->encoded + idx, nameStr, strLen); + idx += strLen; + + name->type = type; + name->totalLen = idx; + name->used = 1; + } + else + name->used = 0; + + return idx; +} + +/* encode CertName into output, return total bytes written */ +int SetName(byte* output, word32 outputSz, CertName* name) +{ + int totalBytes = 0, i, idx; +#ifdef WOLFSSL_SMALL_STACK + EncodedName* names = NULL; +#else + EncodedName names[NAME_ENTRIES]; +#endif +#ifdef WOLFSSL_MULTI_ATTRIB + EncodedName addNames[CTC_MAX_ATTRIB]; + int j, type; +#endif + + if (output == NULL || name == NULL) + return BAD_FUNC_ARG; + + if (outputSz < 3) + return BUFFER_E; + +#ifdef WOLFSSL_SMALL_STACK + names = (EncodedName*)XMALLOC(sizeof(EncodedName) * NAME_ENTRIES, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (names == NULL) + return MEMORY_E; +#endif + + for (i = 0; i < NAME_ENTRIES; i++) { + int ret; + const char* nameStr = GetOneName(name, i); + + ret = wc_EncodeName(&names[i], nameStr, GetNameType(name, i), + GetNameId(i)); + if (ret < 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return BUFFER_E; + } + totalBytes += ret; + } +#ifdef WOLFSSL_MULTI_ATTRIB + for (i = 0; i < CTC_MAX_ATTRIB; i++) { + if (name->name[i].sz > 0) { + int ret; + ret = wc_EncodeName(&addNames[i], name->name[i].value, + name->name[i].type, name->name[i].id); + if (ret < 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return BUFFER_E; + } + totalBytes += ret; + } + else { + addNames[i].used = 0; + } + } +#endif /* WOLFSSL_MULTI_ATTRIB */ + + /* header */ + idx = SetSequence(totalBytes, output); + totalBytes += idx; + if (totalBytes > ASN_NAME_MAX) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return BUFFER_E; + } + + for (i = 0; i < NAME_ENTRIES; i++) { + #ifdef WOLFSSL_MULTI_ATTRIB + type = GetNameId(i); + + /* list all DC values before OUs */ + if (type == ASN_ORGUNIT_NAME) { + type = ASN_DOMAIN_COMPONENT; + for (j = 0; j < CTC_MAX_ATTRIB; j++) { + if (name->name[j].sz > 0 && type == name->name[j].id) { + if (outputSz < (word32)(idx+addNames[j].totalLen)) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return BUFFER_E; + } + + XMEMCPY(output + idx, addNames[j].encoded, + addNames[j].totalLen); + idx += addNames[j].totalLen; + } + } + type = ASN_ORGUNIT_NAME; + } + + /* write all similar types to the buffer */ + for (j = 0; j < CTC_MAX_ATTRIB; j++) { + if (name->name[j].sz > 0 && type == name->name[j].id) { + if (outputSz < (word32)(idx+addNames[j].totalLen)) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return BUFFER_E; + } + + XMEMCPY(output + idx, addNames[j].encoded, + addNames[j].totalLen); + idx += addNames[j].totalLen; + } + } + #endif /* WOLFSSL_MULTI_ATTRIB */ + + if (names[i].used) { + if (outputSz < (word32)(idx+names[i].totalLen)) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return BUFFER_E; + } + + XMEMCPY(output + idx, names[i].encoded, names[i].totalLen); + idx += names[i].totalLen; + } + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(names, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return totalBytes; +} + +/* encode info from cert into DER encoded format */ +static int EncodeCert(Cert* cert, DerCert* der, RsaKey* rsaKey, ecc_key* eccKey, + WC_RNG* rng, const byte* ntruKey, word16 ntruSz, + ed25519_key* ed25519Key) +{ + int ret; + + if (cert == NULL || der == NULL || rng == NULL) + return BAD_FUNC_ARG; + + /* make sure at least one key type is provided */ + if (rsaKey == NULL && eccKey == NULL && ed25519Key == NULL && ntruKey == NULL) + return PUBLIC_KEY_E; + + /* init */ + XMEMSET(der, 0, sizeof(DerCert)); + + /* version */ + der->versionSz = SetMyVersion(cert->version, der->version, TRUE); + + /* serial number (must be positive) */ + if (cert->serialSz == 0) { + /* generate random serial */ + cert->serialSz = CTC_SERIAL_SIZE; + ret = wc_RNG_GenerateBlock(rng, cert->serial, cert->serialSz); + if (ret != 0) + return ret; + } + der->serialSz = SetSerialNumber(cert->serial, cert->serialSz, der->serial, + CTC_SERIAL_SIZE); + if (der->serialSz < 0) + return der->serialSz; + + /* signature algo */ + der->sigAlgoSz = SetAlgoID(cert->sigType, der->sigAlgo, oidSigType, 0); + if (der->sigAlgoSz <= 0) + return ALGO_ID_E; + + /* public key */ +#ifndef NO_RSA + if (cert->keyType == RSA_KEY) { + if (rsaKey == NULL) + return PUBLIC_KEY_E; + der->publicKeySz = SetRsaPublicKey(der->publicKey, rsaKey, + sizeof(der->publicKey), 1); + } +#endif + +#ifdef HAVE_ECC + if (cert->keyType == ECC_KEY) { + if (eccKey == NULL) + return PUBLIC_KEY_E; + der->publicKeySz = SetEccPublicKey(der->publicKey, eccKey, 1); + } +#endif + +#ifdef HAVE_ED25519 + if (cert->keyType == ED25519_KEY) { + if (ed25519Key == NULL) + return PUBLIC_KEY_E; + der->publicKeySz = SetEd25519PublicKey(der->publicKey, ed25519Key, 1); + } +#endif + +#ifdef HAVE_NTRU + if (cert->keyType == NTRU_KEY) { + word32 rc; + word16 encodedSz; + + if (ntruKey == NULL) + return PUBLIC_KEY_E; + + rc = ntru_crypto_ntru_encrypt_publicKey2SubjectPublicKeyInfo(ntruSz, + ntruKey, &encodedSz, NULL); + if (rc != NTRU_OK) + return PUBLIC_KEY_E; + if (encodedSz > MAX_PUBLIC_KEY_SZ) + return PUBLIC_KEY_E; + + rc = ntru_crypto_ntru_encrypt_publicKey2SubjectPublicKeyInfo(ntruSz, + ntruKey, &encodedSz, der->publicKey); + if (rc != NTRU_OK) + return PUBLIC_KEY_E; + + der->publicKeySz = encodedSz; + } +#else + (void)ntruSz; +#endif /* HAVE_NTRU */ + + if (der->publicKeySz <= 0) + return PUBLIC_KEY_E; + + der->validitySz = 0; +#ifdef WOLFSSL_ALT_NAMES + /* date validity copy ? */ + if (cert->beforeDateSz && cert->afterDateSz) { + der->validitySz = CopyValidity(der->validity, cert); + if (der->validitySz <= 0) + return DATE_E; + } +#endif + + /* date validity */ + if (der->validitySz == 0) { + der->validitySz = SetValidity(der->validity, cert->daysValid); + if (der->validitySz <= 0) + return DATE_E; + } + + /* subject name */ +#ifdef WOLFSSL_CERT_EXT + if (XSTRLEN((const char*)cert->sbjRaw) > 0) { + /* Use the raw subject */ + int idx; + + der->subjectSz = min(sizeof(der->subject), + (word32)XSTRLEN((const char*)cert->sbjRaw)); + /* header */ + idx = SetSequence(der->subjectSz, der->subject); + if (der->subjectSz + idx > (int)sizeof(der->subject)) { + return SUBJECT_E; + } + + XMEMCPY((char*)der->subject + idx, (const char*)cert->sbjRaw, + der->subjectSz); + der->subjectSz += idx; + } + else +#endif + { + /* Use the name structure */ + der->subjectSz = SetName(der->subject, sizeof(der->subject), + &cert->subject); + } + if (der->subjectSz <= 0) + return SUBJECT_E; + + /* issuer name */ +#ifdef WOLFSSL_CERT_EXT + if (XSTRLEN((const char*)cert->issRaw) > 0) { + /* Use the raw issuer */ + int idx; + + der->issuerSz = min(sizeof(der->issuer), + (word32)XSTRLEN((const char*)cert->issRaw)); + /* header */ + idx = SetSequence(der->issuerSz, der->issuer); + if (der->issuerSz + idx > (int)sizeof(der->issuer)) { + return ISSUER_E; + } + + XMEMCPY((char*)der->issuer + idx, (const char*)cert->issRaw, + der->issuerSz); + der->issuerSz += idx; + } + else +#endif + { + /* Use the name structure */ + der->issuerSz = SetName(der->issuer, sizeof(der->issuer), + cert->selfSigned ? &cert->subject : &cert->issuer); + } + if (der->issuerSz <= 0) + return ISSUER_E; + + /* set the extensions */ + der->extensionsSz = 0; + + /* CA */ + if (cert->isCA) { + der->caSz = SetCa(der->ca, sizeof(der->ca)); + if (der->caSz <= 0) + return CA_TRUE_E; + + der->extensionsSz += der->caSz; + } + else + der->caSz = 0; + +#ifdef WOLFSSL_ALT_NAMES + /* Alternative Name */ + if (cert->altNamesSz) { + der->altNamesSz = SetAltNames(der->altNames, sizeof(der->altNames), + cert->altNames, cert->altNamesSz); + if (der->altNamesSz <= 0) + return ALT_NAME_E; + + der->extensionsSz += der->altNamesSz; + } + else + der->altNamesSz = 0; +#endif + +#ifdef WOLFSSL_CERT_EXT + /* SKID */ + if (cert->skidSz) { + /* check the provided SKID size */ + if (cert->skidSz > (int)min(CTC_MAX_SKID_SIZE, sizeof(der->skid))) + return SKID_E; + + /* Note: different skid buffers sizes for der (MAX_KID_SZ) and + cert (CTC_MAX_SKID_SIZE). */ + der->skidSz = SetSKID(der->skid, sizeof(der->skid), + cert->skid, cert->skidSz); + if (der->skidSz <= 0) + return SKID_E; + + der->extensionsSz += der->skidSz; + } + else + der->skidSz = 0; + + /* AKID */ + if (cert->akidSz) { + /* check the provided AKID size */ + if (cert->akidSz > (int)min(CTC_MAX_AKID_SIZE, sizeof(der->akid))) + return AKID_E; + + der->akidSz = SetAKID(der->akid, sizeof(der->akid), + cert->akid, cert->akidSz, cert->heap); + if (der->akidSz <= 0) + return AKID_E; + + der->extensionsSz += der->akidSz; + } + else + der->akidSz = 0; + + /* Key Usage */ + if (cert->keyUsage != 0){ + der->keyUsageSz = SetKeyUsage(der->keyUsage, sizeof(der->keyUsage), + cert->keyUsage); + if (der->keyUsageSz <= 0) + return KEYUSAGE_E; + + der->extensionsSz += der->keyUsageSz; + } + else + der->keyUsageSz = 0; + + /* Extended Key Usage */ + if (cert->extKeyUsage != 0){ + der->extKeyUsageSz = SetExtKeyUsage(cert, der->extKeyUsage, + sizeof(der->extKeyUsage), cert->extKeyUsage); + if (der->extKeyUsageSz <= 0) + return EXTKEYUSAGE_E; + + der->extensionsSz += der->extKeyUsageSz; + } + else + der->extKeyUsageSz = 0; + + /* Certificate Policies */ + if (cert->certPoliciesNb != 0) { + der->certPoliciesSz = SetCertificatePolicies(der->certPolicies, + sizeof(der->certPolicies), + cert->certPolicies, + cert->certPoliciesNb, + cert->heap); + if (der->certPoliciesSz <= 0) + return CERTPOLICIES_E; + + der->extensionsSz += der->certPoliciesSz; + } + else + der->certPoliciesSz = 0; +#endif /* WOLFSSL_CERT_EXT */ + + /* put extensions */ + if (der->extensionsSz > 0) { + + /* put the start of extensions sequence (ID, Size) */ + der->extensionsSz = SetExtensionsHeader(der->extensions, + sizeof(der->extensions), + der->extensionsSz); + if (der->extensionsSz <= 0) + return EXTENSIONS_E; + + /* put CA */ + if (der->caSz) { + ret = SetExtensions(der->extensions, sizeof(der->extensions), + &der->extensionsSz, + der->ca, der->caSz); + if (ret == 0) + return EXTENSIONS_E; + } + +#ifdef WOLFSSL_ALT_NAMES + /* put Alternative Names */ + if (der->altNamesSz) { + ret = SetExtensions(der->extensions, sizeof(der->extensions), + &der->extensionsSz, + der->altNames, der->altNamesSz); + if (ret <= 0) + return EXTENSIONS_E; + } +#endif + +#ifdef WOLFSSL_CERT_EXT + /* put SKID */ + if (der->skidSz) { + ret = SetExtensions(der->extensions, sizeof(der->extensions), + &der->extensionsSz, + der->skid, der->skidSz); + if (ret <= 0) + return EXTENSIONS_E; + } + + /* put AKID */ + if (der->akidSz) { + ret = SetExtensions(der->extensions, sizeof(der->extensions), + &der->extensionsSz, + der->akid, der->akidSz); + if (ret <= 0) + return EXTENSIONS_E; + } + + /* put KeyUsage */ + if (der->keyUsageSz) { + ret = SetExtensions(der->extensions, sizeof(der->extensions), + &der->extensionsSz, + der->keyUsage, der->keyUsageSz); + if (ret <= 0) + return EXTENSIONS_E; + } + + /* put ExtendedKeyUsage */ + if (der->extKeyUsageSz) { + ret = SetExtensions(der->extensions, sizeof(der->extensions), + &der->extensionsSz, + der->extKeyUsage, der->extKeyUsageSz); + if (ret <= 0) + return EXTENSIONS_E; + } + + /* put Certificate Policies */ + if (der->certPoliciesSz) { + ret = SetExtensions(der->extensions, sizeof(der->extensions), + &der->extensionsSz, + der->certPolicies, der->certPoliciesSz); + if (ret <= 0) + return EXTENSIONS_E; + } +#endif /* WOLFSSL_CERT_EXT */ + } + + der->total = der->versionSz + der->serialSz + der->sigAlgoSz + + der->publicKeySz + der->validitySz + der->subjectSz + der->issuerSz + + der->extensionsSz; + + return 0; +} + + +/* write DER encoded cert to buffer, size already checked */ +static int WriteCertBody(DerCert* der, byte* buffer) +{ + int idx; + + /* signed part header */ + idx = SetSequence(der->total, buffer); + /* version */ + XMEMCPY(buffer + idx, der->version, der->versionSz); + idx += der->versionSz; + /* serial */ + XMEMCPY(buffer + idx, der->serial, der->serialSz); + idx += der->serialSz; + /* sig algo */ + XMEMCPY(buffer + idx, der->sigAlgo, der->sigAlgoSz); + idx += der->sigAlgoSz; + /* issuer */ + XMEMCPY(buffer + idx, der->issuer, der->issuerSz); + idx += der->issuerSz; + /* validity */ + XMEMCPY(buffer + idx, der->validity, der->validitySz); + idx += der->validitySz; + /* subject */ + XMEMCPY(buffer + idx, der->subject, der->subjectSz); + idx += der->subjectSz; + /* public key */ + XMEMCPY(buffer + idx, der->publicKey, der->publicKeySz); + idx += der->publicKeySz; + if (der->extensionsSz) { + /* extensions */ + XMEMCPY(buffer + idx, der->extensions, min(der->extensionsSz, + (int)sizeof(der->extensions))); + idx += der->extensionsSz; + } + + return idx; +} + + +/* Make RSA signature from buffer (sz), write to sig (sigSz) */ +static int MakeSignature(CertSignCtx* certSignCtx, const byte* buffer, int sz, + byte* sig, int sigSz, RsaKey* rsaKey, ecc_key* eccKey, + ed25519_key* ed25519Key, WC_RNG* rng, int sigAlgoType, void* heap) +{ + int digestSz = 0, typeH = 0, ret = 0; + + (void)digestSz; + (void)typeH; + (void)buffer; + (void)sz; + (void)sig; + (void)sigSz; + (void)rsaKey; + (void)eccKey; + (void)ed25519Key; + (void)rng; + + switch (certSignCtx->state) { + case CERTSIGN_STATE_BEGIN: + case CERTSIGN_STATE_DIGEST: + + certSignCtx->state = CERTSIGN_STATE_DIGEST; + certSignCtx->digest = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (certSignCtx->digest == NULL) { + ret = MEMORY_E; goto exit_ms; + } + + ret = HashForSignature(buffer, sz, sigAlgoType, certSignCtx->digest, + &typeH, &digestSz, 0); + /* set next state, since WC_PENDING_E rentry for these are not "call again" */ + certSignCtx->state = CERTSIGN_STATE_ENCODE; + if (ret != 0) { + goto exit_ms; + } + FALL_THROUGH; + + case CERTSIGN_STATE_ENCODE: + #ifndef NO_RSA + if (rsaKey) { + certSignCtx->encSig = (byte*)XMALLOC(MAX_DER_DIGEST_SZ, heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (certSignCtx->encSig == NULL) { + ret = MEMORY_E; goto exit_ms; + } + + /* signature */ + certSignCtx->encSigSz = wc_EncodeSignature(certSignCtx->encSig, + certSignCtx->digest, digestSz, typeH); + } + #endif /* !NO_RSA */ + FALL_THROUGH; + + case CERTSIGN_STATE_DO: + certSignCtx->state = CERTSIGN_STATE_DO; + ret = ALGO_ID_E; /* default to error */ + + #ifndef NO_RSA + if (rsaKey) { + /* signature */ + ret = wc_RsaSSL_Sign(certSignCtx->encSig, certSignCtx->encSigSz, + sig, sigSz, rsaKey, rng); + } + #endif /* !NO_RSA */ + + #ifdef HAVE_ECC + if (!rsaKey && eccKey) { + word32 outSz = sigSz; + + ret = wc_ecc_sign_hash(certSignCtx->digest, digestSz, + sig, &outSz, rng, eccKey); + if (ret == 0) + ret = outSz; + } + #endif /* HAVE_ECC */ + + #ifdef HAVE_ED25519 + if (!rsaKey && !eccKey && ed25519Key) { + word32 outSz = sigSz; + + ret = wc_ed25519_sign_msg(buffer, sz, sig, &outSz, ed25519Key); + if (ret == 0) + ret = outSz; + } + #endif /* HAVE_ECC */ + break; + } + +exit_ms: + +#ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + return ret; + } +#endif + +#ifndef NO_RSA + if (rsaKey) { + XFREE(certSignCtx->encSig, heap, DYNAMIC_TYPE_TMP_BUFFER); + } +#endif /* !NO_RSA */ + + XFREE(certSignCtx->digest, heap, DYNAMIC_TYPE_TMP_BUFFER); + certSignCtx->digest = NULL; + + /* reset state */ + certSignCtx->state = CERTSIGN_STATE_BEGIN; + + return ret; +} + + +/* add signature to end of buffer, size of buffer assumed checked, return + new length */ +static int AddSignature(byte* buffer, int bodySz, const byte* sig, int sigSz, + int sigAlgoType) +{ + byte seq[MAX_SEQ_SZ]; + int idx = bodySz, seqSz; + + /* algo */ + idx += SetAlgoID(sigAlgoType, buffer + idx, oidSigType, 0); + /* bit string */ + idx += SetBitString(sigSz, 0, buffer + idx); + /* signature */ + XMEMCPY(buffer + idx, sig, sigSz); + idx += sigSz; + + /* make room for overall header */ + seqSz = SetSequence(idx, seq); + XMEMMOVE(buffer + seqSz, buffer, idx); + XMEMCPY(buffer, seq, seqSz); + + return idx + seqSz; +} + + +/* Make an x509 Certificate v3 any key type from cert input, write to buffer */ +static int MakeAnyCert(Cert* cert, byte* derBuffer, word32 derSz, + RsaKey* rsaKey, ecc_key* eccKey, WC_RNG* rng, + const byte* ntruKey, word16 ntruSz, + ed25519_key* ed25519Key) +{ + int ret; +#ifdef WOLFSSL_SMALL_STACK + DerCert* der; +#else + DerCert der[1]; +#endif + + cert->keyType = eccKey ? ECC_KEY : (rsaKey ? RSA_KEY : + (ed25519Key ? ED25519_KEY : NTRU_KEY)); + +#ifdef WOLFSSL_SMALL_STACK + der = (DerCert*)XMALLOC(sizeof(DerCert), cert->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (der == NULL) + return MEMORY_E; +#endif + + ret = EncodeCert(cert, der, rsaKey, eccKey, rng, ntruKey, ntruSz, + ed25519Key); + if (ret == 0) { + if (der->total + MAX_SEQ_SZ * 2 > (int)derSz) + ret = BUFFER_E; + else + ret = cert->bodySz = WriteCertBody(der, derBuffer); + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(der, cert->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + + +/* Make an x509 Certificate v3 RSA or ECC from cert input, write to buffer */ +int wc_MakeCert_ex(Cert* cert, byte* derBuffer, word32 derSz, int keyType, + void* key, WC_RNG* rng) +{ + RsaKey* rsaKey = NULL; + ecc_key* eccKey = NULL; + ed25519_key* ed25519Key = NULL; + + if (keyType == RSA_TYPE) + rsaKey = (RsaKey*)key; + else if (keyType == ECC_TYPE) + eccKey = (ecc_key*)key; + else if (keyType == ED25519_TYPE) + ed25519Key = (ed25519_key*)key; + + return MakeAnyCert(cert, derBuffer, derSz, rsaKey, eccKey, rng, NULL, 0, + ed25519Key); +} +/* Make an x509 Certificate v3 RSA or ECC from cert input, write to buffer */ +int wc_MakeCert(Cert* cert, byte* derBuffer, word32 derSz, RsaKey* rsaKey, + ecc_key* eccKey, WC_RNG* rng) +{ + return MakeAnyCert(cert, derBuffer, derSz, rsaKey, eccKey, rng, NULL, 0, + NULL); +} + + +#ifdef HAVE_NTRU + +int wc_MakeNtruCert(Cert* cert, byte* derBuffer, word32 derSz, + const byte* ntruKey, word16 keySz, WC_RNG* rng) +{ + return MakeAnyCert(cert, derBuffer, derSz, NULL, NULL, rng, ntruKey, keySz, NULL); +} + +#endif /* HAVE_NTRU */ + + +#ifdef WOLFSSL_CERT_REQ + +static int SetReqAttrib(byte* output, char* pw, int pwPrintableString, + int extSz) +{ + static const byte cpOid[] = + { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x09, 0x07 }; + static const byte erOid[] = + { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x09, 0x0e }; + + int sz = 0; /* overall size */ + int cpSz = 0; /* Challenge Password section size */ + int cpSeqSz = 0; + int cpSetSz = 0; + int cpStrSz = 0; + int pwSz = 0; + int erSz = 0; /* Extension Request section size */ + int erSeqSz = 0; + int erSetSz = 0; + byte cpSeq[MAX_SEQ_SZ]; + byte cpSet[MAX_SET_SZ]; + byte cpStr[MAX_PRSTR_SZ]; + byte erSeq[MAX_SEQ_SZ]; + byte erSet[MAX_SET_SZ]; + + output[0] = 0xa0; + sz++; + + if (pw && pw[0]) { + pwSz = (int)XSTRLEN(pw); + if (pwPrintableString) { + cpStrSz = SetPrintableString(pwSz, cpStr); + } else { + cpStrSz = SetUTF8String(pwSz, cpStr); + } + cpSetSz = SetSet(cpStrSz + pwSz, cpSet); + cpSeqSz = SetSequence(sizeof(cpOid) + cpSetSz + cpStrSz + pwSz, cpSeq); + cpSz = cpSeqSz + sizeof(cpOid) + cpSetSz + cpStrSz + pwSz; + } + + if (extSz) { + erSetSz = SetSet(extSz, erSet); + erSeqSz = SetSequence(erSetSz + sizeof(erOid) + extSz, erSeq); + erSz = extSz + erSetSz + erSeqSz + sizeof(erOid); + } + + /* Put the pieces together. */ + sz += SetLength(cpSz + erSz, &output[sz]); + + if (cpSz) { + XMEMCPY(&output[sz], cpSeq, cpSeqSz); + sz += cpSeqSz; + XMEMCPY(&output[sz], cpOid, sizeof(cpOid)); + sz += sizeof(cpOid); + XMEMCPY(&output[sz], cpSet, cpSetSz); + sz += cpSetSz; + XMEMCPY(&output[sz], cpStr, cpStrSz); + sz += cpStrSz; + XMEMCPY(&output[sz], pw, pwSz); + sz += pwSz; + } + + if (erSz) { + XMEMCPY(&output[sz], erSeq, erSeqSz); + sz += erSeqSz; + XMEMCPY(&output[sz], erOid, sizeof(erOid)); + sz += sizeof(erOid); + XMEMCPY(&output[sz], erSet, erSetSz); + sz += erSetSz; + /* The actual extension data will be tacked onto the output later. */ + } + + return sz; +} + + +/* encode info from cert into DER encoded format */ +static int EncodeCertReq(Cert* cert, DerCert* der, RsaKey* rsaKey, + ecc_key* eccKey, ed25519_key* ed25519Key) +{ + (void)eccKey; + (void)ed25519Key; + + if (cert == NULL || der == NULL) + return BAD_FUNC_ARG; + + if (rsaKey == NULL && eccKey == NULL && ed25519Key == NULL) + return PUBLIC_KEY_E; + + /* init */ + XMEMSET(der, 0, sizeof(DerCert)); + + /* version */ + der->versionSz = SetMyVersion(cert->version, der->version, FALSE); + + /* subject name */ + der->subjectSz = SetName(der->subject, sizeof(der->subject), &cert->subject); + if (der->subjectSz <= 0) + return SUBJECT_E; + + /* public key */ +#ifndef NO_RSA + if (cert->keyType == RSA_KEY) { + if (rsaKey == NULL) + return PUBLIC_KEY_E; + der->publicKeySz = SetRsaPublicKey(der->publicKey, rsaKey, + sizeof(der->publicKey), 1); + } +#endif + +#ifdef HAVE_ECC + if (cert->keyType == ECC_KEY) { + der->publicKeySz = SetEccPublicKey(der->publicKey, eccKey, 1); + } +#endif + +#ifdef HAVE_ED25519 + if (cert->keyType == ED25519_KEY) { + if (ed25519Key == NULL) + return PUBLIC_KEY_E; + der->publicKeySz = SetEd25519PublicKey(der->publicKey, ed25519Key, 1); + } +#endif + + if (der->publicKeySz <= 0) + return PUBLIC_KEY_E; + + /* set the extensions */ + der->extensionsSz = 0; + + /* CA */ + if (cert->isCA) { + der->caSz = SetCa(der->ca, sizeof(der->ca)); + if (der->caSz <= 0) + return CA_TRUE_E; + + der->extensionsSz += der->caSz; + } + else + der->caSz = 0; + +#ifdef WOLFSSL_CERT_EXT + /* SKID */ + if (cert->skidSz) { + /* check the provided SKID size */ + if (cert->skidSz > (int)min(CTC_MAX_SKID_SIZE, sizeof(der->skid))) + return SKID_E; + + der->skidSz = SetSKID(der->skid, sizeof(der->skid), + cert->skid, cert->skidSz); + if (der->skidSz <= 0) + return SKID_E; + + der->extensionsSz += der->skidSz; + } + else + der->skidSz = 0; + + /* Key Usage */ + if (cert->keyUsage != 0){ + der->keyUsageSz = SetKeyUsage(der->keyUsage, sizeof(der->keyUsage), + cert->keyUsage); + if (der->keyUsageSz <= 0) + return KEYUSAGE_E; + + der->extensionsSz += der->keyUsageSz; + } + else + der->keyUsageSz = 0; + + /* Extended Key Usage */ + if (cert->extKeyUsage != 0){ + der->extKeyUsageSz = SetExtKeyUsage(cert, der->extKeyUsage, + sizeof(der->extKeyUsage), cert->extKeyUsage); + if (der->extKeyUsageSz <= 0) + return EXTKEYUSAGE_E; + + der->extensionsSz += der->extKeyUsageSz; + } + else + der->extKeyUsageSz = 0; + +#endif /* WOLFSSL_CERT_EXT */ + + /* put extensions */ + if (der->extensionsSz > 0) { + int ret; + + /* put the start of sequence (ID, Size) */ + der->extensionsSz = SetSequence(der->extensionsSz, der->extensions); + if (der->extensionsSz <= 0) + return EXTENSIONS_E; + + /* put CA */ + if (der->caSz) { + ret = SetExtensions(der->extensions, sizeof(der->extensions), + &der->extensionsSz, + der->ca, der->caSz); + if (ret <= 0) + return EXTENSIONS_E; + } + +#ifdef WOLFSSL_CERT_EXT + /* put SKID */ + if (der->skidSz) { + ret = SetExtensions(der->extensions, sizeof(der->extensions), + &der->extensionsSz, + der->skid, der->skidSz); + if (ret <= 0) + return EXTENSIONS_E; + } + + /* put AKID */ + if (der->akidSz) { + ret = SetExtensions(der->extensions, sizeof(der->extensions), + &der->extensionsSz, + der->akid, der->akidSz); + if (ret <= 0) + return EXTENSIONS_E; + } + + /* put KeyUsage */ + if (der->keyUsageSz) { + ret = SetExtensions(der->extensions, sizeof(der->extensions), + &der->extensionsSz, + der->keyUsage, der->keyUsageSz); + if (ret <= 0) + return EXTENSIONS_E; + } + + /* put ExtendedKeyUsage */ + if (der->extKeyUsageSz) { + ret = SetExtensions(der->extensions, sizeof(der->extensions), + &der->extensionsSz, + der->extKeyUsage, der->extKeyUsageSz); + if (ret <= 0) + return EXTENSIONS_E; + } + +#endif /* WOLFSSL_CERT_EXT */ + } + + der->attribSz = SetReqAttrib(der->attrib, cert->challengePw, + cert->challengePwPrintableString, + der->extensionsSz); + if (der->attribSz <= 0) + return REQ_ATTRIBUTE_E; + + der->total = der->versionSz + der->subjectSz + der->publicKeySz + + der->extensionsSz + der->attribSz; + + return 0; +} + + +/* write DER encoded cert req to buffer, size already checked */ +static int WriteCertReqBody(DerCert* der, byte* buffer) +{ + int idx; + + /* signed part header */ + idx = SetSequence(der->total, buffer); + /* version */ + XMEMCPY(buffer + idx, der->version, der->versionSz); + idx += der->versionSz; + /* subject */ + XMEMCPY(buffer + idx, der->subject, der->subjectSz); + idx += der->subjectSz; + /* public key */ + XMEMCPY(buffer + idx, der->publicKey, der->publicKeySz); + idx += der->publicKeySz; + /* attributes */ + XMEMCPY(buffer + idx, der->attrib, der->attribSz); + idx += der->attribSz; + /* extensions */ + if (der->extensionsSz) { + XMEMCPY(buffer + idx, der->extensions, min(der->extensionsSz, + (int)sizeof(der->extensions))); + idx += der->extensionsSz; + } + + return idx; +} + + +static int MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz, + RsaKey* rsaKey, ecc_key* eccKey, ed25519_key* ed25519Key) +{ + int ret; +#ifdef WOLFSSL_SMALL_STACK + DerCert* der; +#else + DerCert der[1]; +#endif + + cert->keyType = eccKey ? ECC_KEY : (ed25519Key ? ED25519_KEY : RSA_KEY); + +#ifdef WOLFSSL_SMALL_STACK + der = (DerCert*)XMALLOC(sizeof(DerCert), cert->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (der == NULL) + return MEMORY_E; +#endif + + ret = EncodeCertReq(cert, der, rsaKey, eccKey, ed25519Key); + + if (ret == 0) { + if (der->total + MAX_SEQ_SZ * 2 > (int)derSz) + ret = BUFFER_E; + else + ret = cert->bodySz = WriteCertReqBody(der, derBuffer); + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(der, cert->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +int wc_MakeCertReq_ex(Cert* cert, byte* derBuffer, word32 derSz, int keyType, + void* key) +{ + RsaKey* rsaKey = NULL; + ecc_key* eccKey = NULL; + ed25519_key* ed25519Key = NULL; + + if (keyType == RSA_TYPE) + rsaKey = (RsaKey*)key; + else if (keyType == ECC_TYPE) + eccKey = (ecc_key*)key; + else if (keyType == ED25519_TYPE) + ed25519Key = (ed25519_key*)key; + + return MakeCertReq(cert, derBuffer, derSz, rsaKey, eccKey, ed25519Key); +} + +int wc_MakeCertReq(Cert* cert, byte* derBuffer, word32 derSz, + RsaKey* rsaKey, ecc_key* eccKey) +{ + return MakeCertReq(cert, derBuffer, derSz, rsaKey, eccKey, NULL); +} +#endif /* WOLFSSL_CERT_REQ */ + + +static int SignCert(int requestSz, int sType, byte* buffer, word32 buffSz, + RsaKey* rsaKey, ecc_key* eccKey, ed25519_key* ed25519Key, + WC_RNG* rng) +{ + int sigSz = 0; + void* heap = NULL; + CertSignCtx* certSignCtx = NULL; +#ifndef WOLFSSL_ASYNC_CRYPT + CertSignCtx certSignCtx_lcl; + certSignCtx = &certSignCtx_lcl; + XMEMSET(certSignCtx, 0, sizeof(CertSignCtx)); +#endif + + if (requestSz < 0) + return requestSz; + + /* locate ctx */ + if (rsaKey) { + #ifndef NO_RSA + #ifdef WOLFSSL_ASYNC_CRYPT + certSignCtx = &rsaKey->certSignCtx; + #endif + heap = rsaKey->heap; + #else + return NOT_COMPILED_IN; + #endif /* NO_RSA */ + } + else if (eccKey) { + #ifdef HAVE_ECC + #ifdef WOLFSSL_ASYNC_CRYPT + certSignCtx = &eccKey->certSignCtx; + #endif + heap = eccKey->heap; + #else + return NOT_COMPILED_IN; + #endif /* HAVE_ECC */ + } + +#ifdef WOLFSSL_ASYNC_CRYPT + if (certSignCtx == NULL) { + return BAD_FUNC_ARG; + } +#endif + + if (certSignCtx->sig == NULL) { + certSignCtx->sig = (byte*)XMALLOC(MAX_ENCODED_SIG_SZ, heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (certSignCtx->sig == NULL) + return MEMORY_E; + } + + sigSz = MakeSignature(certSignCtx, buffer, requestSz, certSignCtx->sig, + MAX_ENCODED_SIG_SZ, rsaKey, eccKey, ed25519Key, rng, sType, heap); +#ifdef WOLFSSL_ASYNC_CRYPT + if (sigSz == WC_PENDING_E) { + /* Not free'ing certSignCtx->sig here because it could still be in use + * with async operations. */ + return sigSz; + } +#endif + + if (sigSz >= 0) { + if (requestSz + MAX_SEQ_SZ * 2 + sigSz > (int)buffSz) + sigSz = BUFFER_E; + else + sigSz = AddSignature(buffer, requestSz, certSignCtx->sig, sigSz, + sType); + } + + XFREE(certSignCtx->sig, heap, DYNAMIC_TYPE_TMP_BUFFER); + certSignCtx->sig = NULL; + + return sigSz; +} + +int wc_SignCert_ex(int requestSz, int sType, byte* buffer, word32 buffSz, + int keyType, void* key, WC_RNG* rng) +{ + RsaKey* rsaKey = NULL; + ecc_key* eccKey = NULL; + ed25519_key* ed25519Key = NULL; + + if (keyType == RSA_TYPE) + rsaKey = (RsaKey*)key; + else if (keyType == ECC_TYPE) + eccKey = (ecc_key*)key; + else if (keyType == ED25519_TYPE) + ed25519Key = (ed25519_key*)key; + + return SignCert(requestSz, sType, buffer, buffSz, rsaKey, eccKey, + ed25519Key, rng); +} + +int wc_SignCert(int requestSz, int sType, byte* buffer, word32 buffSz, + RsaKey* rsaKey, ecc_key* eccKey, WC_RNG* rng) +{ + return SignCert(requestSz, sType, buffer, buffSz, rsaKey, eccKey, NULL, + rng); +} + +int wc_MakeSelfCert(Cert* cert, byte* buffer, word32 buffSz, + RsaKey* key, WC_RNG* rng) +{ + int ret; + + ret = wc_MakeCert(cert, buffer, buffSz, key, NULL, rng); + if (ret < 0) + return ret; + + return wc_SignCert(cert->bodySz, cert->sigType, + buffer, buffSz, key, NULL, rng); +} + + +#ifdef WOLFSSL_CERT_EXT + +/* Get raw subject from cert, which may contain OIDs not parsed by Decode. + The raw subject pointer will only be valid while "cert" is valid. */ +int wc_GetSubjectRaw(byte **subjectRaw, Cert *cert) +{ + int rc = BAD_FUNC_ARG; + if ((subjectRaw != NULL) && (cert != NULL)) { + *subjectRaw = cert->sbjRaw; + rc = 0; + } + return rc; +} + +/* Set KID from public key */ +static int SetKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey, + byte *ntruKey, word16 ntruKeySz, + ed25519_key* ed25519Key, int kid_type) +{ + byte *buffer; + int bufferSz, ret; + + if (cert == NULL || + (rsakey == NULL && eckey == NULL && ntruKey == NULL && + ed25519Key == NULL) || + (kid_type != SKID_TYPE && kid_type != AKID_TYPE)) + return BAD_FUNC_ARG; + + buffer = (byte *)XMALLOC(MAX_PUBLIC_KEY_SZ, cert->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (buffer == NULL) + return MEMORY_E; + + /* Public Key */ + bufferSz = -1; +#ifndef NO_RSA + /* RSA public key */ + if (rsakey != NULL) + bufferSz = SetRsaPublicKey(buffer, rsakey, MAX_PUBLIC_KEY_SZ, 0); +#endif +#ifdef HAVE_ECC + /* ECC public key */ + if (eckey != NULL) + bufferSz = SetEccPublicKey(buffer, eckey, 0); +#endif +#ifdef HAVE_NTRU + /* NTRU public key */ + if (ntruKey != NULL) { + bufferSz = MAX_PUBLIC_KEY_SZ; + ret = ntru_crypto_ntru_encrypt_publicKey2SubjectPublicKeyInfo( + ntruKeySz, ntruKey, (word16 *)(&bufferSz), buffer); + if (ret != NTRU_OK) + bufferSz = -1; + } +#else + (void)ntruKeySz; +#endif +#ifdef HAVE_ED25519 + /* ED25519 public key */ + if (ed25519Key != NULL) + bufferSz = SetEd25519PublicKey(buffer, ed25519Key, 0); +#endif + + if (bufferSz <= 0) { + XFREE(buffer, cert->heap, DYNAMIC_TYPE_TMP_BUFFER); + return PUBLIC_KEY_E; + } + + /* Compute SKID by hashing public key */ + if (kid_type == SKID_TYPE) { + ret = CalcHashId(buffer, bufferSz, cert->skid); + cert->skidSz = KEYID_SIZE; + } + else if (kid_type == AKID_TYPE) { + ret = CalcHashId(buffer, bufferSz, cert->akid); + cert->akidSz = KEYID_SIZE; + } + else + ret = BAD_FUNC_ARG; + + XFREE(buffer, cert->heap, DYNAMIC_TYPE_TMP_BUFFER); + return ret; +} + +int wc_SetSubjectKeyIdFromPublicKey_ex(Cert *cert, int keyType, void* key) +{ + RsaKey* rsaKey = NULL; + ecc_key* eccKey = NULL; + ed25519_key* ed25519Key = NULL; + + if (keyType == RSA_TYPE) + rsaKey = (RsaKey*)key; + else if (keyType == ECC_TYPE) + eccKey = (ecc_key*)key; + else if (keyType == ED25519_TYPE) + ed25519Key = (ed25519_key*)key; + + return SetKeyIdFromPublicKey(cert, rsaKey, eccKey, NULL, 0, ed25519Key, + SKID_TYPE); +} + +/* Set SKID from RSA or ECC public key */ +int wc_SetSubjectKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey) +{ + return SetKeyIdFromPublicKey(cert, rsakey, eckey, NULL, 0, NULL, SKID_TYPE); +} + +#ifdef HAVE_NTRU +/* Set SKID from NTRU public key */ +int wc_SetSubjectKeyIdFromNtruPublicKey(Cert *cert, + byte *ntruKey, word16 ntruKeySz) +{ + return SetKeyIdFromPublicKey(cert, NULL,NULL,ntruKey, ntruKeySz, NULL, + SKID_TYPE); +} +#endif + +int wc_SetAuthKeyIdFromPublicKey_ex(Cert *cert, int keyType, void* key) +{ + RsaKey* rsaKey = NULL; + ecc_key* eccKey = NULL; + ed25519_key* ed25519Key = NULL; + + if (keyType == RSA_TYPE) + rsaKey = (RsaKey*)key; + else if (keyType == ECC_TYPE) + eccKey = (ecc_key*)key; + else if (keyType == ED25519_TYPE) + ed25519Key = (ed25519_key*)key; + + return SetKeyIdFromPublicKey(cert, rsaKey, eccKey, NULL, 0, ed25519Key, + AKID_TYPE); +} + +/* Set SKID from RSA or ECC public key */ +int wc_SetAuthKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, ecc_key *eckey) +{ + return SetKeyIdFromPublicKey(cert, rsakey, eckey, NULL, 0, NULL, AKID_TYPE); +} + + +#if !defined(NO_FILESYSTEM) && !defined(NO_ASN_CRYPT) + +/* Set SKID from public key file in PEM */ +int wc_SetSubjectKeyId(Cert *cert, const char* file) +{ + int ret, derSz; + byte* der; + word32 idx; + RsaKey *rsakey = NULL; + ecc_key *eckey = NULL; + + if (cert == NULL || file == NULL) + return BAD_FUNC_ARG; + + der = (byte*)XMALLOC(MAX_PUBLIC_KEY_SZ, cert->heap, DYNAMIC_TYPE_CERT); + if (der == NULL) { + WOLFSSL_MSG("wc_SetSubjectKeyId memory Problem"); + return MEMORY_E; + } + derSz = MAX_PUBLIC_KEY_SZ; + + XMEMSET(der, 0, derSz); + derSz = wc_PemPubKeyToDer(file, der, derSz); + if (derSz <= 0) { + XFREE(der, cert->heap, DYNAMIC_TYPE_CERT); + return derSz; + } + + /* Load PubKey in internal structure */ +#ifndef NO_RSA + rsakey = (RsaKey*) XMALLOC(sizeof(RsaKey), cert->heap, DYNAMIC_TYPE_RSA); + if (rsakey == NULL) { + XFREE(der, cert->heap, DYNAMIC_TYPE_CERT); + return MEMORY_E; + } + + if (wc_InitRsaKey(rsakey, cert->heap) != 0) { + WOLFSSL_MSG("wc_InitRsaKey failure"); + XFREE(rsakey, cert->heap, DYNAMIC_TYPE_RSA); + XFREE(der, cert->heap, DYNAMIC_TYPE_CERT); + return MEMORY_E; + } + + idx = 0; + ret = wc_RsaPublicKeyDecode(der, &idx, rsakey, derSz); + if (ret != 0) +#endif + { +#ifndef NO_RSA + WOLFSSL_MSG("wc_RsaPublicKeyDecode failed"); + wc_FreeRsaKey(rsakey); + XFREE(rsakey, cert->heap, DYNAMIC_TYPE_RSA); + rsakey = NULL; +#endif +#ifdef HAVE_ECC + /* Check to load ecc public key */ + eckey = (ecc_key*) XMALLOC(sizeof(ecc_key), cert->heap, + DYNAMIC_TYPE_ECC); + if (eckey == NULL) { + XFREE(der, cert->heap, DYNAMIC_TYPE_CERT); + return MEMORY_E; + } + + if (wc_ecc_init(eckey) != 0) { + WOLFSSL_MSG("wc_ecc_init failure"); + wc_ecc_free(eckey); + XFREE(eckey, cert->heap, DYNAMIC_TYPE_ECC); + XFREE(der, cert->heap, DYNAMIC_TYPE_CERT); + return MEMORY_E; + } + + idx = 0; + ret = wc_EccPublicKeyDecode(der, &idx, eckey, derSz); + if (ret != 0) { + WOLFSSL_MSG("wc_EccPublicKeyDecode failed"); + XFREE(der, cert->heap, DYNAMIC_TYPE_CERT); + wc_ecc_free(eckey); + XFREE(eckey, cert->heap, DYNAMIC_TYPE_ECC); + return PUBLIC_KEY_E; + } +#else + XFREE(der, cert->heap, DYNAMIC_TYPE_CERT); + return PUBLIC_KEY_E; +#endif /* HAVE_ECC */ + } + + XFREE(der, cert->heap, DYNAMIC_TYPE_CERT); + + ret = wc_SetSubjectKeyIdFromPublicKey(cert, rsakey, eckey); + +#ifndef NO_RSA + wc_FreeRsaKey(rsakey); + XFREE(rsakey, cert->heap, DYNAMIC_TYPE_RSA); +#endif +#ifdef HAVE_ECC + wc_ecc_free(eckey); + XFREE(eckey, cert->heap, DYNAMIC_TYPE_ECC); +#endif + return ret; +} + +#endif /* !NO_FILESYSTEM && !NO_ASN_CRYPT */ + +static int SetAuthKeyIdFromDcert(Cert* cert, DecodedCert* decoded) +{ + int ret = 0; + + /* Subject Key Id not found !! */ + if (decoded->extSubjKeyIdSet == 0) { + ret = ASN_NO_SKID; + } + + /* SKID invalid size */ + else if (sizeof(cert->akid) < sizeof(decoded->extSubjKeyId)) { + ret = MEMORY_E; + } + + else { + /* Put the SKID of CA to AKID of certificate */ + XMEMCPY(cert->akid, decoded->extSubjKeyId, KEYID_SIZE); + cert->akidSz = KEYID_SIZE; + } + + return ret; +} + +/* Set AKID from certificate contains in buffer (DER encoded) */ +int wc_SetAuthKeyIdFromCert(Cert *cert, const byte *der, int derSz) +{ + int ret = 0; + + if (cert == NULL) { + ret = BAD_FUNC_ARG; + } + else { + /* Check if decodedCert is cached */ + if (cert->der != der) { + /* Allocate cache for the decoded cert */ + ret = wc_SetCert_LoadDer(cert, der, derSz); + } + + if (ret >= 0) { + ret = SetAuthKeyIdFromDcert(cert, (DecodedCert*)cert->decodedCert); +#ifndef WOLFSSL_CERT_GEN_CACHE + wc_SetCert_Free(cert); +#endif + } + } + + return ret; +} + + +#ifndef NO_FILESYSTEM + +/* Set AKID from certificate file in PEM */ +int wc_SetAuthKeyId(Cert *cert, const char* file) +{ + int ret; + int derSz; + byte* der; + + if (cert == NULL || file == NULL) + return BAD_FUNC_ARG; + + der = (byte*)XMALLOC(EIGHTK_BUF, cert->heap, DYNAMIC_TYPE_CERT); + if (der == NULL) { + WOLFSSL_MSG("wc_SetAuthKeyId OOF Problem"); + return MEMORY_E; + } + + derSz = wc_PemCertToDer(file, der, EIGHTK_BUF); + if (derSz <= 0) + { + XFREE(der, cert->heap, DYNAMIC_TYPE_CERT); + return derSz; + } + + ret = wc_SetAuthKeyIdFromCert(cert, der, derSz); + XFREE(der, cert->heap, DYNAMIC_TYPE_CERT); + + return ret; +} + +#endif /* !NO_FILESYSTEM */ + +/* Set KeyUsage from human readable string */ +int wc_SetKeyUsage(Cert *cert, const char *value) +{ + int ret = 0; + char *token, *str, *ptr; + word32 len; + + if (cert == NULL || value == NULL) + return BAD_FUNC_ARG; + + cert->keyUsage = 0; + + len = (word32)XSTRLEN(value); + str = (char*)XMALLOC(len+1, cert->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (str == NULL) + return MEMORY_E; + + XSTRNCPY(str, value, len+1); + + /* parse value, and set corresponding Key Usage value */ + if ((token = XSTRTOK(str, ",", &ptr)) == NULL) { + XFREE(str, cert->heap, DYNAMIC_TYPE_TMP_BUFFER); + return KEYUSAGE_E; + } + while (token != NULL) + { + len = (word32)XSTRLEN(token); + + if (!XSTRNCASECMP(token, "digitalSignature", len)) + cert->keyUsage |= KEYUSE_DIGITAL_SIG; + else if (!XSTRNCASECMP(token, "nonRepudiation", len) || + !XSTRNCASECMP(token, "contentCommitment", len)) + cert->keyUsage |= KEYUSE_CONTENT_COMMIT; + else if (!XSTRNCASECMP(token, "keyEncipherment", len)) + cert->keyUsage |= KEYUSE_KEY_ENCIPHER; + else if (!XSTRNCASECMP(token, "dataEncipherment", len)) + cert->keyUsage |= KEYUSE_DATA_ENCIPHER; + else if (!XSTRNCASECMP(token, "keyAgreement", len)) + cert->keyUsage |= KEYUSE_KEY_AGREE; + else if (!XSTRNCASECMP(token, "keyCertSign", len)) + cert->keyUsage |= KEYUSE_KEY_CERT_SIGN; + else if (!XSTRNCASECMP(token, "cRLSign", len)) + cert->keyUsage |= KEYUSE_CRL_SIGN; + else if (!XSTRNCASECMP(token, "encipherOnly", len)) + cert->keyUsage |= KEYUSE_ENCIPHER_ONLY; + else if (!XSTRNCASECMP(token, "decipherOnly", len)) + cert->keyUsage |= KEYUSE_DECIPHER_ONLY; + else { + ret = KEYUSAGE_E; + break; + } + + token = XSTRTOK(NULL, ",", &ptr); + } + + XFREE(str, cert->heap, DYNAMIC_TYPE_TMP_BUFFER); + return ret; +} + +/* Set ExtendedKeyUsage from human readable string */ +int wc_SetExtKeyUsage(Cert *cert, const char *value) +{ + int ret = 0; + char *token, *str, *ptr; + word32 len; + + if (cert == NULL || value == NULL) + return BAD_FUNC_ARG; + + cert->extKeyUsage = 0; + + len = (word32)XSTRLEN(value); + str = (char*)XMALLOC(len+1, cert->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (str == NULL) + return MEMORY_E; + + XSTRNCPY(str, value, len+1); + + /* parse value, and set corresponding Key Usage value */ + if ((token = XSTRTOK(str, ",", &ptr)) == NULL) { + XFREE(str, cert->heap, DYNAMIC_TYPE_TMP_BUFFER); + return EXTKEYUSAGE_E; + } + + while (token != NULL) + { + len = (word32)XSTRLEN(token); + + if (!XSTRNCASECMP(token, "any", len)) + cert->extKeyUsage |= EXTKEYUSE_ANY; + else if (!XSTRNCASECMP(token, "serverAuth", len)) + cert->extKeyUsage |= EXTKEYUSE_SERVER_AUTH; + else if (!XSTRNCASECMP(token, "clientAuth", len)) + cert->extKeyUsage |= EXTKEYUSE_CLIENT_AUTH; + else if (!XSTRNCASECMP(token, "codeSigning", len)) + cert->extKeyUsage |= EXTKEYUSE_CODESIGN; + else if (!XSTRNCASECMP(token, "emailProtection", len)) + cert->extKeyUsage |= EXTKEYUSE_EMAILPROT; + else if (!XSTRNCASECMP(token, "timeStamping", len)) + cert->extKeyUsage |= EXTKEYUSE_TIMESTAMP; + else if (!XSTRNCASECMP(token, "OCSPSigning", len)) + cert->extKeyUsage |= EXTKEYUSE_OCSP_SIGN; + else { + ret = EXTKEYUSAGE_E; + break; + } + + token = XSTRTOK(NULL, ",", &ptr); + } + + XFREE(str, cert->heap, DYNAMIC_TYPE_TMP_BUFFER); + return ret; +} + +#ifdef WOLFSSL_EKU_OID +/* + * cert structure to set EKU oid in + * oid the oid in byte representation + * sz size of oid buffer + * idx index of array to place oid + * + * returns 0 on success + */ +int wc_SetExtKeyUsageOID(Cert *cert, const char *in, word32 sz, byte idx, + void* heap) +{ + byte oid[MAX_OID_SZ]; + word32 oidSz = MAX_OID_SZ; + + if (idx >= CTC_MAX_EKU_NB || sz >= CTC_MAX_EKU_OID_SZ) { + WOLFSSL_MSG("Either idx or sz was too large"); + return BAD_FUNC_ARG; + } + + if (EncodePolicyOID(oid, &oidSz, in, heap) != 0) { + return BUFFER_E; + } + + XMEMCPY(cert->extKeyUsageOID[idx], oid, oidSz); + cert->extKeyUsageOIDSz[idx] = oidSz; + cert->extKeyUsage |= EXTKEYUSE_USER; + + return 0; +} +#endif /* WOLFSSL_EKU_OID */ +#endif /* WOLFSSL_CERT_EXT */ + + +#ifdef WOLFSSL_ALT_NAMES + +static int SetAltNamesFromDcert(Cert* cert, DecodedCert* decoded) +{ + int ret = 0; + + if (decoded->extensions) { + byte b; + int length; + word32 maxExtensionsIdx; + + decoded->srcIdx = decoded->extensionsIdx; + b = decoded->source[decoded->srcIdx++]; + + if (b != ASN_EXTENSIONS) { + ret = ASN_PARSE_E; + } + else if (GetLength(decoded->source, &decoded->srcIdx, &length, + decoded->maxIdx) < 0) { + ret = ASN_PARSE_E; + } + else if (GetSequence(decoded->source, &decoded->srcIdx, &length, + decoded->maxIdx) < 0) { + ret = ASN_PARSE_E; + } + else { + maxExtensionsIdx = decoded->srcIdx + length; + + while (decoded->srcIdx < maxExtensionsIdx) { + word32 oid; + word32 startIdx = decoded->srcIdx; + word32 tmpIdx; + + if (GetSequence(decoded->source, &decoded->srcIdx, &length, + decoded->maxIdx) < 0) { + ret = ASN_PARSE_E; + break; + } + + tmpIdx = decoded->srcIdx; + decoded->srcIdx = startIdx; + + if (GetAlgoId(decoded->source, &decoded->srcIdx, &oid, + oidCertExtType, decoded->maxIdx) < 0) { + ret = ASN_PARSE_E; + break; + } + + if (oid == ALT_NAMES_OID) { + cert->altNamesSz = length + (tmpIdx - startIdx); + + if (cert->altNamesSz < (int)sizeof(cert->altNames)) + XMEMCPY(cert->altNames, &decoded->source[startIdx], + cert->altNamesSz); + else { + cert->altNamesSz = 0; + WOLFSSL_MSG("AltNames extensions too big"); + ret = ALT_NAME_E; + break; + } + } + decoded->srcIdx = tmpIdx + length; + } + } + } + + return ret; +} + +#ifndef NO_FILESYSTEM + +/* Set Alt Names from der cert, return 0 on success */ +static int SetAltNamesFromCert(Cert* cert, const byte* der, int derSz) +{ + int ret; +#ifdef WOLFSSL_SMALL_STACK + DecodedCert* decoded; +#else + DecodedCert decoded[1]; +#endif + + if (derSz < 0) + return derSz; + +#ifdef WOLFSSL_SMALL_STACK + decoded = (DecodedCert*)XMALLOC(sizeof(DecodedCert), cert->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (decoded == NULL) + return MEMORY_E; +#endif + + InitDecodedCert(decoded, der, derSz, NULL); + ret = ParseCertRelative(decoded, CA_TYPE, NO_VERIFY, 0); + + if (ret < 0) { + WOLFSSL_MSG("ParseCertRelative error"); + } + else { + ret = SetAltNamesFromDcert(cert, decoded); + } + + FreeDecodedCert(decoded); +#ifdef WOLFSSL_SMALL_STACK + XFREE(decoded, cert->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret < 0 ? ret : 0; +} + +#endif + +static int SetDatesFromDcert(Cert* cert, DecodedCert* decoded) +{ + int ret = 0; + + if (decoded->beforeDate == NULL || decoded->afterDate == NULL) { + WOLFSSL_MSG("Couldn't extract dates"); + ret = -1; + } + else if (decoded->beforeDateLen > MAX_DATE_SIZE || + decoded->afterDateLen > MAX_DATE_SIZE) { + WOLFSSL_MSG("Bad date size"); + ret = -1; + } + else { + XMEMCPY(cert->beforeDate, decoded->beforeDate, decoded->beforeDateLen); + XMEMCPY(cert->afterDate, decoded->afterDate, decoded->afterDateLen); + + cert->beforeDateSz = decoded->beforeDateLen; + cert->afterDateSz = decoded->afterDateLen; + } + + return ret; +} + +#endif /* WOLFSSL_ALT_NAMES */ + +static void SetNameFromDcert(CertName* cn, DecodedCert* decoded) +{ + int sz; + + if (decoded->subjectCN) { + sz = (decoded->subjectCNLen < CTC_NAME_SIZE) ? decoded->subjectCNLen + : CTC_NAME_SIZE - 1; + XSTRNCPY(cn->commonName, decoded->subjectCN, CTC_NAME_SIZE); + cn->commonName[sz] = '\0'; + cn->commonNameEnc = decoded->subjectCNEnc; + } + if (decoded->subjectC) { + sz = (decoded->subjectCLen < CTC_NAME_SIZE) ? decoded->subjectCLen + : CTC_NAME_SIZE - 1; + XSTRNCPY(cn->country, decoded->subjectC, CTC_NAME_SIZE); + cn->country[sz] = '\0'; + cn->countryEnc = decoded->subjectCEnc; + } + if (decoded->subjectST) { + sz = (decoded->subjectSTLen < CTC_NAME_SIZE) ? decoded->subjectSTLen + : CTC_NAME_SIZE - 1; + XSTRNCPY(cn->state, decoded->subjectST, CTC_NAME_SIZE); + cn->state[sz] = '\0'; + cn->stateEnc = decoded->subjectSTEnc; + } + if (decoded->subjectL) { + sz = (decoded->subjectLLen < CTC_NAME_SIZE) ? decoded->subjectLLen + : CTC_NAME_SIZE - 1; + XSTRNCPY(cn->locality, decoded->subjectL, CTC_NAME_SIZE); + cn->locality[sz] = '\0'; + cn->localityEnc = decoded->subjectLEnc; + } + if (decoded->subjectO) { + sz = (decoded->subjectOLen < CTC_NAME_SIZE) ? decoded->subjectOLen + : CTC_NAME_SIZE - 1; + XSTRNCPY(cn->org, decoded->subjectO, CTC_NAME_SIZE); + cn->org[sz] = '\0'; + cn->orgEnc = decoded->subjectOEnc; + } + if (decoded->subjectOU) { + sz = (decoded->subjectOULen < CTC_NAME_SIZE) ? decoded->subjectOULen + : CTC_NAME_SIZE - 1; + XSTRNCPY(cn->unit, decoded->subjectOU, CTC_NAME_SIZE); + cn->unit[sz] = '\0'; + cn->unitEnc = decoded->subjectOUEnc; + } + if (decoded->subjectSN) { + sz = (decoded->subjectSNLen < CTC_NAME_SIZE) ? decoded->subjectSNLen + : CTC_NAME_SIZE - 1; + XSTRNCPY(cn->sur, decoded->subjectSN, CTC_NAME_SIZE); + cn->sur[sz] = '\0'; + cn->surEnc = decoded->subjectSNEnc; + } + if (decoded->subjectSND) { + sz = (decoded->subjectSNDLen < CTC_NAME_SIZE) ? decoded->subjectSNDLen + : CTC_NAME_SIZE - 1; + XSTRNCPY(cn->serialDev, decoded->subjectSND, CTC_NAME_SIZE); + cn->serialDev[sz] = '\0'; + cn->serialDevEnc = decoded->subjectSNDEnc; + } +#ifdef WOLFSSL_CERT_EXT + if (decoded->subjectBC) { + sz = (decoded->subjectBCLen < CTC_NAME_SIZE) ? decoded->subjectBCLen + : CTC_NAME_SIZE - 1; + XSTRNCPY(cn->busCat, decoded->subjectBC, CTC_NAME_SIZE); + cn->busCat[sz] = '\0'; + cn->busCatEnc = decoded->subjectBCEnc; + } + if (decoded->subjectJC) { + sz = (decoded->subjectJCLen < CTC_NAME_SIZE) ? decoded->subjectJCLen + : CTC_NAME_SIZE - 1; + XSTRNCPY(cn->joiC, decoded->subjectJC, CTC_NAME_SIZE); + cn->joiC[sz] = '\0'; + cn->joiCEnc = decoded->subjectJCEnc; + } + if (decoded->subjectJS) { + sz = (decoded->subjectJSLen < CTC_NAME_SIZE) ? decoded->subjectJSLen + : CTC_NAME_SIZE - 1; + XSTRNCPY(cn->joiSt, decoded->subjectJS, CTC_NAME_SIZE); + cn->joiSt[sz] = '\0'; + cn->joiStEnc = decoded->subjectJSEnc; + } +#endif + if (decoded->subjectEmail) { + sz = (decoded->subjectEmailLen < CTC_NAME_SIZE) + ? decoded->subjectEmailLen : CTC_NAME_SIZE - 1; + XSTRNCPY(cn->email, decoded->subjectEmail, CTC_NAME_SIZE); + cn->email[sz] = '\0'; + } +} + +#ifndef NO_FILESYSTEM + +/* Set cn name from der buffer, return 0 on success */ +static int SetNameFromCert(CertName* cn, const byte* der, int derSz) +{ + int ret; +#ifdef WOLFSSL_SMALL_STACK + DecodedCert* decoded; +#else + DecodedCert decoded[1]; +#endif + + if (derSz < 0) + return derSz; + +#ifdef WOLFSSL_SMALL_STACK + decoded = (DecodedCert*)XMALLOC(sizeof(DecodedCert), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (decoded == NULL) + return MEMORY_E; +#endif + + InitDecodedCert(decoded, der, derSz, NULL); + ret = ParseCertRelative(decoded, CA_TYPE, NO_VERIFY, 0); + + if (ret < 0) { + WOLFSSL_MSG("ParseCertRelative error"); + } + else { + SetNameFromDcert(cn, decoded); + } + + FreeDecodedCert(decoded); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(decoded, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret < 0 ? ret : 0; +} + +/* Set cert issuer from issuerFile in PEM */ +int wc_SetIssuer(Cert* cert, const char* issuerFile) +{ + int ret; + int derSz; + byte* der; + + if (cert == NULL) { + return BAD_FUNC_ARG; + } + + der = (byte*)XMALLOC(EIGHTK_BUF, cert->heap, DYNAMIC_TYPE_CERT); + if (der == NULL) { + WOLFSSL_MSG("wc_SetIssuer OOF Problem"); + return MEMORY_E; + } + derSz = wc_PemCertToDer(issuerFile, der, EIGHTK_BUF); + cert->selfSigned = 0; + ret = SetNameFromCert(&cert->issuer, der, derSz); + XFREE(der, cert->heap, DYNAMIC_TYPE_CERT); + + return ret; +} + + +/* Set cert subject from subjectFile in PEM */ +int wc_SetSubject(Cert* cert, const char* subjectFile) +{ + int ret; + int derSz; + byte* der; + + if (cert == NULL) { + return BAD_FUNC_ARG; + } + + der = (byte*)XMALLOC(EIGHTK_BUF, cert->heap, DYNAMIC_TYPE_CERT); + if (der == NULL) { + WOLFSSL_MSG("wc_SetSubject OOF Problem"); + return MEMORY_E; + } + + derSz = wc_PemCertToDer(subjectFile, der, EIGHTK_BUF); + ret = SetNameFromCert(&cert->subject, der, derSz); + XFREE(der, cert->heap, DYNAMIC_TYPE_CERT); + + return ret; +} + +#ifdef WOLFSSL_ALT_NAMES + +/* Set alt names from file in PEM */ +int wc_SetAltNames(Cert* cert, const char* file) +{ + int ret; + int derSz; + byte* der; + + if (cert == NULL) { + return BAD_FUNC_ARG; + } + + der = (byte*)XMALLOC(EIGHTK_BUF, cert->heap, DYNAMIC_TYPE_CERT); + if (der == NULL) { + WOLFSSL_MSG("wc_SetAltNames OOF Problem"); + return MEMORY_E; + } + derSz = wc_PemCertToDer(file, der, EIGHTK_BUF); + ret = SetAltNamesFromCert(cert, der, derSz); + XFREE(der, cert->heap, DYNAMIC_TYPE_CERT); + + return ret; +} + +#endif /* WOLFSSL_ALT_NAMES */ + +#endif /* !NO_FILESYSTEM */ + +/* Set cert issuer from DER buffer */ +int wc_SetIssuerBuffer(Cert* cert, const byte* der, int derSz) +{ + int ret = 0; + + if (cert == NULL) { + ret = BAD_FUNC_ARG; + } + else { + cert->selfSigned = 0; + + /* Check if decodedCert is cached */ + if (cert->der != der) { + /* Allocate cache for the decoded cert */ + ret = wc_SetCert_LoadDer(cert, der, derSz); + } + + if (ret >= 0) { + SetNameFromDcert(&cert->issuer, (DecodedCert*)cert->decodedCert); +#ifndef WOLFSSL_CERT_GEN_CACHE + wc_SetCert_Free(cert); +#endif + } + } + + return ret; +} + +/* Set cert subject from DER buffer */ +int wc_SetSubjectBuffer(Cert* cert, const byte* der, int derSz) +{ + int ret = 0; + + if (cert == NULL) { + ret = BAD_FUNC_ARG; + } + else { + /* Check if decodedCert is cached */ + if (cert->der != der) { + /* Allocate cache for the decoded cert */ + ret = wc_SetCert_LoadDer(cert, der, derSz); + } + + if (ret >= 0) { + SetNameFromDcert(&cert->subject, (DecodedCert*)cert->decodedCert); +#ifndef WOLFSSL_CERT_GEN_CACHE + wc_SetCert_Free(cert); +#endif + } + } + + return ret; +} +#ifdef WOLFSSL_CERT_EXT +/* Set cert raw subject from DER buffer */ +int wc_SetSubjectRaw(Cert* cert, const byte* der, int derSz) +{ + int ret = 0; + + if (cert == NULL) { + ret = BAD_FUNC_ARG; + } + else { + /* Check if decodedCert is cached */ + if (cert->der != der) { + /* Allocate cache for the decoded cert */ + ret = wc_SetCert_LoadDer(cert, der, derSz); + } + + if (ret >= 0) { + if ((((DecodedCert*)cert->decodedCert)->subjectRaw) && + (((DecodedCert*)cert->decodedCert)->subjectRawLen <= + (int)sizeof(CertName))) { + XMEMCPY(cert->sbjRaw, + ((DecodedCert*)cert->decodedCert)->subjectRaw, + ((DecodedCert*)cert->decodedCert)->subjectRawLen); + } +#ifndef WOLFSSL_CERT_GEN_CACHE + wc_SetCert_Free(cert); +#endif + } + } + + return ret; +} + +/* Set cert raw issuer from DER buffer */ +int wc_SetIssuerRaw(Cert* cert, const byte* der, int derSz) +{ + int ret = 0; + + if (cert == NULL) { + ret = BAD_FUNC_ARG; + } + else { + /* Check if decodedCert is cached */ + if (cert->der != der) { + /* Allocate cache for the decoded cert */ + ret = wc_SetCert_LoadDer(cert, der, derSz); + } + + if (ret >= 0) { + if ((((DecodedCert*)cert->decodedCert)->issuerRaw) && + (((DecodedCert*)cert->decodedCert)->issuerRawLen <= + (int)sizeof(CertName))) { + XMEMCPY(cert->issRaw, + ((DecodedCert*)cert->decodedCert)->issuerRaw, + ((DecodedCert*)cert->decodedCert)->issuerRawLen); + } +#ifndef WOLFSSL_CERT_GEN_CACHE + wc_SetCert_Free(cert); +#endif + } + } + return ret; +} +#endif + +#ifdef WOLFSSL_ALT_NAMES + +/* Set cert alt names from DER buffer */ +int wc_SetAltNamesBuffer(Cert* cert, const byte* der, int derSz) +{ + int ret = 0; + + if (cert == NULL) { + ret = BAD_FUNC_ARG; + } + else { + /* Check if decodedCert is cached */ + if (cert->der != der) { + /* Allocate cache for the decoded cert */ + ret = wc_SetCert_LoadDer(cert, der, derSz); + } + + if (ret >= 0) { + ret = SetAltNamesFromDcert(cert, (DecodedCert*)cert->decodedCert); +#ifndef WOLFSSL_CERT_GEN_CACHE + wc_SetCert_Free(cert); +#endif + } + } + + return(ret); +} + +/* Set cert dates from DER buffer */ +int wc_SetDatesBuffer(Cert* cert, const byte* der, int derSz) +{ + int ret = 0; + + if (cert == NULL) { + ret = BAD_FUNC_ARG; + } + else { + /* Check if decodedCert is cached */ + if (cert->der != der) { + /* Allocate cache for the decoded cert */ + ret = wc_SetCert_LoadDer(cert, der, derSz); + } + + if (ret >= 0) { + ret = SetDatesFromDcert(cert, (DecodedCert*)cert->decodedCert); +#ifndef WOLFSSL_CERT_GEN_CACHE + wc_SetCert_Free(cert); +#endif + } + } + + return(ret); +} + +#endif /* WOLFSSL_ALT_NAMES */ + +#endif /* WOLFSSL_CERT_GEN */ + +#endif /* !NO_CERTS */ + +#ifdef HAVE_ECC + +/* Der Encode r & s ints into out, outLen is (in/out) size */ +int StoreECC_DSA_Sig(byte* out, word32* outLen, mp_int* r, mp_int* s) +{ + word32 idx = 0; + int rSz; /* encoding size */ + int sSz; + word32 headerSz = 4; /* 2*ASN_TAG + 2*LEN(ENUM) */ + + /* If the leading bit on the INTEGER is a 1, add a leading zero */ + int rLeadingZero = mp_leading_bit(r); + int sLeadingZero = mp_leading_bit(s); + int rLen = mp_unsigned_bin_size(r); /* big int size */ + int sLen = mp_unsigned_bin_size(s); + + if (*outLen < (rLen + rLeadingZero + sLen + sLeadingZero + + headerSz + 2)) /* SEQ_TAG + LEN(ENUM) */ + return BUFFER_E; + + idx = SetSequence(rLen + rLeadingZero + sLen+sLeadingZero + headerSz, out); + + /* store r */ + rSz = SetASNIntMP(r, -1, &out[idx]); + if (rSz < 0) + return rSz; + idx += rSz; + + /* store s */ + sSz = SetASNIntMP(s, -1, &out[idx]); + if (sSz < 0) + return sSz; + idx += sSz; + + *outLen = idx; + + return 0; +} + + +/* Der Decode ECC-DSA Signature, r & s stored as big ints */ +int DecodeECC_DSA_Sig(const byte* sig, word32 sigLen, mp_int* r, mp_int* s) +{ + word32 idx = 0; + int len = 0; + + if (GetSequence(sig, &idx, &len, sigLen) < 0) { + return ASN_ECC_KEY_E; + } + +#ifndef NO_STRICT_ECDSA_LEN + /* enable strict length checking for signature */ + if (sigLen != idx + (word32)len) { + return ASN_ECC_KEY_E; + } +#else + /* allow extra signature bytes at end */ + if ((word32)len > (sigLen - idx)) { + return ASN_ECC_KEY_E; + } +#endif + + if (GetInt(r, sig, &idx, sigLen) < 0) { + return ASN_ECC_KEY_E; + } + + if (GetInt(s, sig, &idx, sigLen) < 0) { + return ASN_ECC_KEY_E; + } + + return 0; +} + + +int wc_EccPrivateKeyDecode(const byte* input, word32* inOutIdx, ecc_key* key, + word32 inSz) +{ + word32 oidSum; + int version, length; + int privSz, pubSz = 0; + byte b; + int ret = 0; + int curve_id = ECC_CURVE_DEF; +#ifdef WOLFSSL_SMALL_STACK + byte* priv; + byte* pub; +#else + byte priv[ECC_MAXSIZE+1]; + byte pub[2*(ECC_MAXSIZE+1)]; /* public key has two parts plus header */ +#endif + byte* pubData = NULL; + + if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0) + return BAD_FUNC_ARG; + + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + return ASN_PARSE_E; + + if (GetMyVersion(input, inOutIdx, &version, inSz) < 0) + return ASN_PARSE_E; + + if (*inOutIdx >= inSz) + return ASN_PARSE_E; + + b = input[*inOutIdx]; + *inOutIdx += 1; + + /* priv type */ + if (b != 4 && b != 6 && b != 7) + return ASN_PARSE_E; + + if (GetLength(input, inOutIdx, &length, inSz) < 0) + return ASN_PARSE_E; + + if (length > ECC_MAXSIZE) + return BUFFER_E; + +#ifdef WOLFSSL_SMALL_STACK + priv = (byte*)XMALLOC(ECC_MAXSIZE+1, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (priv == NULL) + return MEMORY_E; + + pub = (byte*)XMALLOC(2*(ECC_MAXSIZE+1), key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (pub == NULL) { + XFREE(priv, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#endif + + /* priv key */ + privSz = length; + XMEMCPY(priv, &input[*inOutIdx], privSz); + *inOutIdx += length; + + if (ret == 0 && (*inOutIdx + 1) < inSz) { + /* prefix 0, may have */ + b = input[*inOutIdx]; + if (b == ECC_PREFIX_0) { + *inOutIdx += 1; + + if (GetLength(input, inOutIdx, &length, inSz) <= 0) + ret = ASN_PARSE_E; + else { + ret = GetObjectId(input, inOutIdx, &oidSum, oidIgnoreType, + inSz); + if (ret == 0) { + if ((ret = CheckCurve(oidSum)) < 0) + ret = ECC_CURVE_OID_E; + else { + curve_id = ret; + ret = 0; + } + } + } + } + } + + if (ret == 0 && (*inOutIdx + 1) < inSz) { + /* prefix 1 */ + b = input[*inOutIdx]; + *inOutIdx += 1; + + if (b != ECC_PREFIX_1) { + ret = ASN_ECC_KEY_E; + } + else if (GetLength(input, inOutIdx, &length, inSz) <= 0) { + ret = ASN_PARSE_E; + } + else { + /* key header */ + ret = CheckBitString(input, inOutIdx, &length, inSz, 0, NULL); + if (ret == 0) { + /* pub key */ + pubSz = length; + if (pubSz < 2*(ECC_MAXSIZE+1)) { + XMEMCPY(pub, &input[*inOutIdx], pubSz); + *inOutIdx += length; + pubData = pub; + } + else + ret = BUFFER_E; + } + } + } + + if (ret == 0) { + ret = wc_ecc_import_private_key_ex(priv, privSz, pubData, pubSz, key, + curve_id); + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(priv, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + + +#ifdef WOLFSSL_CUSTOM_CURVES +static void ByteToHex(byte n, char* str) +{ + static const char hexChar[] = { '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' }; + + str[0] = hexChar[n >> 4]; + str[1] = hexChar[n & 0xf]; +} + +/* returns 0 on success */ +static int ASNToHexString(const byte* input, word32* inOutIdx, char** out, + word32 inSz, void* heap, int heapType) +{ + int len; + int i; + char* str; + + if (*inOutIdx >= inSz) { + return BUFFER_E; + } + + if (input[*inOutIdx] == ASN_INTEGER) { + if (GetASNInt(input, inOutIdx, &len, inSz) < 0) + return ASN_PARSE_E; + } + else { + if (GetOctetString(input, inOutIdx, &len, inSz) < 0) + return ASN_PARSE_E; + } + + str = (char*)XMALLOC(len * 2 + 1, heap, heapType); + for (i=0; i= inSz) { + return BUFFER_E; + } + + if (input[*inOutIdx] == (ASN_SEQUENCE | ASN_CONSTRUCTED)) { +#ifdef WOLFSSL_CUSTOM_CURVES + ecc_set_type* curve; + int len; + char* point = NULL; + + ret = 0; + + curve = (ecc_set_type*)XMALLOC(sizeof(*curve), key->heap, + DYNAMIC_TYPE_ECC_BUFFER); + if (curve == NULL) + ret = MEMORY_E; + + if (ret == 0) { + static char customName[] = "Custom"; + XMEMSET(curve, 0, sizeof(*curve)); + #ifndef USE_WINDOWS_API + curve->name = customName; + #else + XMEMCPY((void*)curve->name, customName, sizeof(customName)); + #endif + curve->id = ECC_CURVE_CUSTOM; + + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + ret = ASN_PARSE_E; + } + + if (ret == 0) { + GetInteger7Bit(input, inOutIdx, inSz); + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + ret = ASN_PARSE_E; + } + if (ret == 0) { + SkipObjectId(input, inOutIdx, inSz); + ret = ASNToHexString(input, inOutIdx, (char**)&curve->prime, inSz, + key->heap, DYNAMIC_TYPE_ECC_BUFFER); + } + if (ret == 0) { + curve->size = (int)XSTRLEN(curve->prime) / 2; + + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + ret = ASN_PARSE_E; + } + if (ret == 0) { + ret = ASNToHexString(input, inOutIdx, (char**)&curve->Af, inSz, + key->heap, DYNAMIC_TYPE_ECC_BUFFER); + } + if (ret == 0) { + ret = ASNToHexString(input, inOutIdx, (char**)&curve->Bf, inSz, + key->heap, DYNAMIC_TYPE_ECC_BUFFER); + } + if (ret == 0) { + if (*inOutIdx < inSz && input[*inOutIdx] == ASN_BIT_STRING) { + len = 0; + ret = GetASNHeader(input, ASN_BIT_STRING, inOutIdx, &len, inSz); + *inOutIdx += len; + } + } + if (ret == 0) { + ret = ASNToHexString(input, inOutIdx, (char**)&point, inSz, + key->heap, DYNAMIC_TYPE_ECC_BUFFER); + + /* sanity check that point buffer is not smaller than the expected + * size to hold ( 0 4 || Gx || Gy ) + * where Gx and Gy are each the size of curve->size * 2 */ + if (ret == 0 && (int)XSTRLEN(point) < (curve->size * 4) + 2) { + XFREE(point, key->heap, DYNAMIC_TYPE_ECC_BUFFER); + ret = BUFFER_E; + } + } + if (ret == 0) { + #ifndef USE_WINDOWS_API + curve->Gx = (const char*)XMALLOC(curve->size * 2 + 2, key->heap, + DYNAMIC_TYPE_ECC_BUFFER); + curve->Gy = (const char*)XMALLOC(curve->size * 2 + 2, key->heap, + DYNAMIC_TYPE_ECC_BUFFER); + if (curve->Gx == NULL || curve->Gy == NULL) { + XFREE(point, key->heap, DYNAMIC_TYPE_ECC_BUFFER); + ret = MEMORY_E; + } + #else + if (curve->size * 2 + 2 > MAX_ECC_STRING) { + WOLFSSL_MSG("curve size is too large to fit in buffer"); + ret = BUFFER_E; + } + #endif + } + if (ret == 0) { + XMEMCPY((char*)curve->Gx, point + 2, curve->size * 2); + XMEMCPY((char*)curve->Gy, point + curve->size * 2 + 2, + curve->size * 2); + ((char*)curve->Gx)[curve->size * 2] = '\0'; + ((char*)curve->Gy)[curve->size * 2] = '\0'; + XFREE(point, key->heap, DYNAMIC_TYPE_ECC_BUFFER); + ret = ASNToHexString(input, inOutIdx, (char**)&curve->order, inSz, + key->heap, DYNAMIC_TYPE_ECC_BUFFER); + } + if (ret == 0) { + curve->cofactor = GetInteger7Bit(input, inOutIdx, inSz); + + #ifndef USE_WINDOWS_API + curve->oid = NULL; + #else + XMEMSET((void*)curve->oid, 0, sizeof(curve->oid)); + #endif + curve->oidSz = 0; + curve->oidSum = 0; + + if (wc_ecc_set_custom_curve(key, curve) < 0) { + ret = ASN_PARSE_E; + } + #ifndef USE_WINDOWS_API + key->deallocSet = 1; + #endif + curve = NULL; + } + if (curve != NULL) + wc_ecc_free_curve(curve, key->heap); + + if (ret < 0) + return ret; +#else + return ASN_PARSE_E; +#endif /* WOLFSSL_CUSTOM_CURVES */ + } + else { + /* ecc params information */ + ret = GetObjectId(input, inOutIdx, &oidSum, oidIgnoreType, inSz); + if (ret != 0) + return ret; + + /* get curve id */ + curve_id = wc_ecc_get_oid(oidSum, NULL, 0); + if (curve_id < 0) + return ECC_CURVE_OID_E; + } + + /* key header */ + ret = CheckBitString(input, inOutIdx, &length, inSz, 1, NULL); + if (ret != 0) + return ret; + + /* This is the raw point data compressed or uncompressed. */ + if (wc_ecc_import_x963_ex(input + *inOutIdx, inSz - *inOutIdx, key, + curve_id) != 0) { + return ASN_ECC_KEY_E; + } + + *inOutIdx += length; + + return 0; +} + +#if defined(HAVE_ECC_KEY_EXPORT) && !defined(NO_ASN_CRYPT) +/* build DER formatted ECC key, include optional public key if requested, + * return length on success, negative on error */ +static int wc_BuildEccKeyDer(ecc_key* key, byte* output, word32 inLen, + int pubIn) +{ + byte curve[MAX_ALGO_SZ+2]; + byte ver[MAX_VERSION_SZ]; + byte seq[MAX_SEQ_SZ]; + byte *prv = NULL, *pub = NULL; + int ret, totalSz, curveSz, verSz; + int privHdrSz = ASN_ECC_HEADER_SZ; + int pubHdrSz = ASN_ECC_CONTEXT_SZ + ASN_ECC_HEADER_SZ; + + word32 idx = 0, prvidx = 0, pubidx = 0, curveidx = 0; + word32 seqSz, privSz, pubSz = ECC_BUFSIZE; + + if (key == NULL || output == NULL || inLen == 0) + return BAD_FUNC_ARG; + + /* curve */ + curve[curveidx++] = ECC_PREFIX_0; + curveidx++ /* to put the size after computation */; + curveSz = SetCurve(key, curve+curveidx); + if (curveSz < 0) + return curveSz; + /* set computed size */ + curve[1] = (byte)curveSz; + curveidx += curveSz; + + /* private */ + privSz = key->dp->size; + prv = (byte*)XMALLOC(privSz + privHdrSz + MAX_SEQ_SZ, + key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (prv == NULL) { + return MEMORY_E; + } + prvidx += SetOctetString8Bit(key->dp->size, &prv[prvidx]); + ret = wc_ecc_export_private_only(key, prv + prvidx, &privSz); + if (ret < 0) { + XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + prvidx += privSz; + + /* pubIn */ + if (pubIn) { + ret = wc_ecc_export_x963(key, NULL, &pubSz); + if (ret != LENGTH_ONLY_E) { + XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + + pub = (byte*)XMALLOC(pubSz + pubHdrSz + MAX_SEQ_SZ, + key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (pub == NULL) { + XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } + + pub[pubidx++] = ECC_PREFIX_1; + if (pubSz > 128) /* leading zero + extra size byte */ + pubidx += SetLength(pubSz + ASN_ECC_CONTEXT_SZ + 2, pub+pubidx); + else /* leading zero */ + pubidx += SetLength(pubSz + ASN_ECC_CONTEXT_SZ + 1, pub+pubidx); + + /* SetBitString adds leading zero */ + pubidx += SetBitString(pubSz, 0, pub + pubidx); + ret = wc_ecc_export_x963(key, pub + pubidx, &pubSz); + if (ret != 0) { + XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + pubidx += pubSz; + } + + /* make headers */ + verSz = SetMyVersion(1, ver, FALSE); + seqSz = SetSequence(verSz + prvidx + pubidx + curveidx, seq); + + totalSz = prvidx + pubidx + curveidx + verSz + seqSz; + if (totalSz > (int)inLen) { + XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (pubIn) { + XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + } + return BAD_FUNC_ARG; + } + + /* write out */ + /* seq */ + XMEMCPY(output + idx, seq, seqSz); + idx = seqSz; + + /* ver */ + XMEMCPY(output + idx, ver, verSz); + idx += verSz; + + /* private */ + XMEMCPY(output + idx, prv, prvidx); + idx += prvidx; + XFREE(prv, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + + /* curve */ + XMEMCPY(output + idx, curve, curveidx); + idx += curveidx; + + /* pubIn */ + if (pubIn) { + XMEMCPY(output + idx, pub, pubidx); + /* idx += pubidx; not used after write, if more data remove comment */ + XFREE(pub, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + } + + return totalSz; +} + +/* Write a Private ecc key, including public to DER format, + * length on success else < 0 */ +int wc_EccKeyToDer(ecc_key* key, byte* output, word32 inLen) +{ + return wc_BuildEccKeyDer(key, output, inLen, 1); +} + + +/* Write only private ecc key to DER format, + * length on success else < 0 */ +int wc_EccPrivateKeyToDer(ecc_key* key, byte* output, word32 inLen) +{ + return wc_BuildEccKeyDer(key, output, inLen, 0); +} + +/* Write only private ecc key to unencrypted PKCS#8 format. + * + * If output is NULL, places required PKCS#8 buffer size in outLen and + * returns LENGTH_ONLY_E. + * + * return length on success else < 0 */ +int wc_EccPrivateKeyToPKCS8(ecc_key* key, byte* output, word32* outLen) +{ + int ret, tmpDerSz; + int algoID = 0; + word32 oidSz = 0; + word32 pkcs8Sz = 0; + const byte* curveOID = NULL; + byte* tmpDer = NULL; + + if (key == NULL || outLen == NULL) + return BAD_FUNC_ARG; + + /* set algoID, get curve OID */ + algoID = ECDSAk; + ret = wc_ecc_get_oid(key->dp->oidSum, &curveOID, &oidSz); + if (ret < 0) + return ret; + + /* temp buffer for plain DER key */ + tmpDer = (byte*)XMALLOC(ECC_BUFSIZE, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (tmpDer == NULL) + return MEMORY_E; + + XMEMSET(tmpDer, 0, ECC_BUFSIZE); + + tmpDerSz = wc_BuildEccKeyDer(key, tmpDer, ECC_BUFSIZE, 0); + if (tmpDerSz < 0) { + XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + return tmpDerSz; + } + + /* get pkcs8 expected output size */ + ret = wc_CreatePKCS8Key(NULL, &pkcs8Sz, tmpDer, tmpDerSz, algoID, + curveOID, oidSz); + if (ret != LENGTH_ONLY_E) { + XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + + if (output == NULL) { + XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + *outLen = pkcs8Sz; + return LENGTH_ONLY_E; + + } else if (*outLen < pkcs8Sz) { + XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + WOLFSSL_MSG("Input buffer too small for ECC PKCS#8 key"); + return BUFFER_E; + } + + ret = wc_CreatePKCS8Key(output, &pkcs8Sz, tmpDer, tmpDerSz, + algoID, curveOID, oidSz); + if (ret < 0) { + XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + + XFREE(tmpDer, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + + *outLen = ret; + return ret; +} + +#endif /* HAVE_ECC_KEY_EXPORT && !NO_ASN_CRYPT */ +#endif /* HAVE_ECC */ + + +#ifdef HAVE_ED25519 + +int wc_Ed25519PrivateKeyDecode(const byte* input, word32* inOutIdx, + ed25519_key* key, word32 inSz) +{ + word32 oid; + int ret, version, length, endKeyIdx, privSz, pubSz; + const byte* priv; + const byte* pub; + + if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0) + return BAD_FUNC_ARG; + + if (GetSequence(input, inOutIdx, &length, inSz) >= 0) { + endKeyIdx = *inOutIdx + length; + + if (GetMyVersion(input, inOutIdx, &version, inSz) < 0) + return ASN_PARSE_E; + if (version != 0) { + WOLFSSL_MSG("Unrecognized version of ED25519 private key"); + return ASN_PARSE_E; + } + + if (GetAlgoId(input, inOutIdx, &oid, oidKeyType, inSz) < 0) + return ASN_PARSE_E; + if (oid != ED25519k) + return ASN_PARSE_E; + + if (GetOctetString(input, inOutIdx, &length, inSz) < 0) + return ASN_PARSE_E; + + if (GetOctetString(input, inOutIdx, &privSz, inSz) < 0) + return ASN_PARSE_E; + + priv = input + *inOutIdx; + *inOutIdx += privSz; + } + else { + if (GetOctetString(input, inOutIdx, &privSz, inSz) < 0) + return ASN_PARSE_E; + + priv = input + *inOutIdx; + *inOutIdx += privSz; + endKeyIdx = *inOutIdx; + } + + if (endKeyIdx == (int)*inOutIdx) { + ret = wc_ed25519_import_private_only(priv, privSz, key); + } + else { + if (GetASNHeader(input, ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1, + inOutIdx, &length, inSz) < 0) { + return ASN_PARSE_E; + } + if (GetOctetString(input, inOutIdx, &pubSz, inSz) < 0) + return ASN_PARSE_E; + pub = input + *inOutIdx; + *inOutIdx += pubSz; + + ret = wc_ed25519_import_private_key(priv, privSz, pub, pubSz, key); + } + if (ret == 0 && endKeyIdx != (int)*inOutIdx) + return ASN_PARSE_E; + + return ret; +} + + +int wc_Ed25519PublicKeyDecode(const byte* input, word32* inOutIdx, + ed25519_key* key, word32 inSz) +{ + int length; + int ret; + + if (input == NULL || inOutIdx == NULL || key == NULL || inSz == 0) + return BAD_FUNC_ARG; + + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + return ASN_PARSE_E; + + if (GetSequence(input, inOutIdx, &length, inSz) < 0) + return ASN_PARSE_E; + + ret = SkipObjectId(input, inOutIdx, inSz); + if (ret != 0) + return ret; + + /* key header */ + ret = CheckBitString(input, inOutIdx, NULL, inSz, 1, NULL); + if (ret != 0) + return ret; + + /* This is the raw point data compressed or uncompressed. */ + if (wc_ed25519_import_public(input + *inOutIdx, inSz - *inOutIdx, key) != 0) + return ASN_ECC_KEY_E; + + return 0; +} + + +#ifdef WOLFSSL_KEY_GEN + +/* build DER formatted ED25519 key, + * return length on success, negative on error */ +static int wc_BuildEd25519KeyDer(ed25519_key* key, byte* output, word32 inLen, + int pubOut) +{ + byte algoArray[MAX_ALGO_SZ]; + byte ver[MAX_VERSION_SZ]; + byte seq[MAX_SEQ_SZ]; + int ret; + word32 idx = 0, seqSz, verSz, algoSz, privSz, pubSz = 0; + + if (key == NULL || output == NULL || inLen == 0) + return BAD_FUNC_ARG; + + if (pubOut) + pubSz = 2 + 2 + ED25519_PUB_KEY_SIZE; + privSz = 2 + 2 + ED25519_KEY_SIZE; + algoSz = SetAlgoID(ED25519k, algoArray, oidKeyType, 0); + verSz = SetMyVersion(0, ver, FALSE); + seqSz = SetSequence(verSz + algoSz + privSz + pubSz, seq); + + if (seqSz + verSz + algoSz + privSz + pubSz > inLen) + return BAD_FUNC_ARG; + + /* write out */ + /* seq */ + XMEMCPY(output + idx, seq, seqSz); + idx = seqSz; + /* ver */ + XMEMCPY(output + idx, ver, verSz); + idx += verSz; + /* algo */ + XMEMCPY(output + idx, algoArray, algoSz); + idx += algoSz; + /* privKey */ + idx += SetOctetString(2 + ED25519_KEY_SIZE, output + idx); + idx += SetOctetString(ED25519_KEY_SIZE, output + idx); + ret = wc_ed25519_export_private_only(key, output + idx, &privSz); + if (ret != 0) + return ret; + idx += privSz; + /* pubKey */ + if (pubOut) { + idx += SetExplicit(1, 2 + ED25519_PUB_KEY_SIZE, output + idx); + idx += SetOctetString(ED25519_KEY_SIZE, output + idx); + ret = wc_ed25519_export_public(key, output + idx, &pubSz); + if (ret != 0) + return ret; + idx += pubSz; + } + + return idx; +} + +/* Write a Private ecc key, including public to DER format, + * length on success else < 0 */ +int wc_Ed25519KeyToDer(ed25519_key* key, byte* output, word32 inLen) +{ + return wc_BuildEd25519KeyDer(key, output, inLen, 1); +} + + + +/* Write only private ecc key to DER format, + * length on success else < 0 */ +int wc_Ed25519PrivateKeyToDer(ed25519_key* key, byte* output, word32 inLen) +{ + return wc_BuildEd25519KeyDer(key, output, inLen, 0); +} + +#endif /* WOLFSSL_KEY_GEN */ + +#endif /* HAVE_ED25519 */ + + +#if defined(HAVE_OCSP) || defined(HAVE_CRL) + +/* Get raw Date only, no processing, 0 on success */ +static int GetBasicDate(const byte* source, word32* idx, byte* date, + byte* format, int maxIdx) +{ + int ret, length; + const byte *datePtr = NULL; + + WOLFSSL_ENTER("GetBasicDate"); + + ret = GetDateInfo(source, idx, &datePtr, format, &length, maxIdx); + if (ret < 0) + return ret; + + XMEMCPY(date, datePtr, length); + + return 0; +} + +#endif /* HAVE_OCSP || HAVE_CRL */ + + +#ifdef HAVE_OCSP + +static int GetEnumerated(const byte* input, word32* inOutIdx, int *value) +{ + word32 idx = *inOutIdx; + word32 len; + + WOLFSSL_ENTER("GetEnumerated"); + + *value = 0; + + if (input[idx++] != ASN_ENUMERATED) + return ASN_PARSE_E; + + len = input[idx++]; + if (len > 4) + return ASN_PARSE_E; + + while (len--) { + *value = *value << 8 | input[idx++]; + } + + *inOutIdx = idx; + + return *value; +} + + +static int DecodeSingleResponse(byte* source, + word32* ioIndex, OcspResponse* resp, word32 size) +{ + word32 idx = *ioIndex, prevIndex, oid; + int length, wrapperSz; + CertStatus* cs = resp->status; + int ret; + + WOLFSSL_ENTER("DecodeSingleResponse"); + + /* Outer wrapper of the SEQUENCE OF Single Responses. */ + if (GetSequence(source, &idx, &wrapperSz, size) < 0) + return ASN_PARSE_E; + + prevIndex = idx; + + /* When making a request, we only request one status on one certificate + * at a time. There should only be one SingleResponse */ + + /* Wrapper around the Single Response */ + if (GetSequence(source, &idx, &length, size) < 0) + return ASN_PARSE_E; + + /* Wrapper around the CertID */ + if (GetSequence(source, &idx, &length, size) < 0) + return ASN_PARSE_E; + /* Skip the hash algorithm */ + if (GetAlgoId(source, &idx, &oid, oidIgnoreType, size) < 0) + return ASN_PARSE_E; + /* Save reference to the hash of CN */ + ret = GetOctetString(source, &idx, &length, size); + if (ret < 0) + return ret; + resp->issuerHash = source + idx; + idx += length; + /* Save reference to the hash of the issuer public key */ + ret = GetOctetString(source, &idx, &length, size); + if (ret < 0) + return ret; + resp->issuerKeyHash = source + idx; + idx += length; + + /* Get serial number */ + if (GetSerialNumber(source, &idx, cs->serial, &cs->serialSz, size) < 0) + return ASN_PARSE_E; + + /* CertStatus */ + switch (source[idx++]) + { + case (ASN_CONTEXT_SPECIFIC | CERT_GOOD): + cs->status = CERT_GOOD; + idx++; + break; + case (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | CERT_REVOKED): + cs->status = CERT_REVOKED; + if (GetLength(source, &idx, &length, size) < 0) + return ASN_PARSE_E; + idx += length; + break; + case (ASN_CONTEXT_SPECIFIC | CERT_UNKNOWN): + cs->status = CERT_UNKNOWN; + idx++; + break; + default: + return ASN_PARSE_E; + } + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + cs->thisDateAsn = source + idx; +#endif + if (GetBasicDate(source, &idx, cs->thisDate, + &cs->thisDateFormat, size) < 0) + return ASN_PARSE_E; + +#ifndef NO_ASN_TIME +#ifndef WOLFSSL_NO_OCSP_DATE_CHECK + if (!XVALIDATE_DATE(cs->thisDate, cs->thisDateFormat, BEFORE)) + return ASN_BEFORE_DATE_E; +#endif +#endif + + /* The following items are optional. Only check for them if there is more + * unprocessed data in the singleResponse wrapper. */ + + if (((int)(idx - prevIndex) < wrapperSz) && + (source[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0))) + { + idx++; + if (GetLength(source, &idx, &length, size) < 0) + return ASN_PARSE_E; +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + cs->nextDateAsn = source + idx; +#endif + if (GetBasicDate(source, &idx, cs->nextDate, + &cs->nextDateFormat, size) < 0) + return ASN_PARSE_E; + +#ifndef NO_ASN_TIME +#ifndef WOLFSSL_NO_OCSP_DATE_CHECK + if (!XVALIDATE_DATE(cs->nextDate, cs->nextDateFormat, AFTER)) + return ASN_AFTER_DATE_E; +#endif +#endif + } + if (((int)(idx - prevIndex) < wrapperSz) && + (source[idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1))) + { + idx++; + if (GetLength(source, &idx, &length, size) < 0) + return ASN_PARSE_E; + idx += length; + } + + *ioIndex = idx; + + return 0; +} + +static int DecodeOcspRespExtensions(byte* source, + word32* ioIndex, OcspResponse* resp, word32 sz) +{ + word32 idx = *ioIndex; + int length; + int ext_bound; /* boundary index for the sequence of extensions */ + word32 oid; + int ret; + + WOLFSSL_ENTER("DecodeOcspRespExtensions"); + + if ((idx + 1) > sz) + return BUFFER_E; + + if (source[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) + return ASN_PARSE_E; + + if (GetLength(source, &idx, &length, sz) < 0) + return ASN_PARSE_E; + + if (GetSequence(source, &idx, &length, sz) < 0) + return ASN_PARSE_E; + + ext_bound = idx + length; + + while (idx < (word32)ext_bound) { + if (GetSequence(source, &idx, &length, sz) < 0) { + WOLFSSL_MSG("\tfail: should be a SEQUENCE"); + return ASN_PARSE_E; + } + + oid = 0; + if (GetObjectId(source, &idx, &oid, oidOcspType, sz) < 0) { + WOLFSSL_MSG("\tfail: OBJECT ID"); + return ASN_PARSE_E; + } + + /* check for critical flag */ + if (source[idx] == ASN_BOOLEAN) { + WOLFSSL_MSG("\tfound optional critical flag, moving past"); + ret = GetBoolean(source, &idx, sz); + if (ret < 0) + return ret; + } + + ret = GetOctetString(source, &idx, &length, sz); + if (ret < 0) + return ret; + + if (oid == OCSP_NONCE_OID) { + /* get data inside extra OCTET_STRING */ + ret = GetOctetString(source, &idx, &length, sz); + if (ret < 0) + return ret; + + resp->nonce = source + idx; + resp->nonceSz = length; + } + + idx += length; + } + + *ioIndex = idx; + return 0; +} + + +static int DecodeResponseData(byte* source, + word32* ioIndex, OcspResponse* resp, word32 size) +{ + word32 idx = *ioIndex, prev_idx; + int length; + int version; + word32 responderId = 0; + + WOLFSSL_ENTER("DecodeResponseData"); + + resp->response = source + idx; + prev_idx = idx; + if (GetSequence(source, &idx, &length, size) < 0) + return ASN_PARSE_E; + resp->responseSz = length + idx - prev_idx; + + /* Get version. It is an EXPLICIT[0] DEFAULT(0) value. If this + * item isn't an EXPLICIT[0], then set version to zero and move + * onto the next item. + */ + if (source[idx] == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED)) + { + idx += 2; /* Eat the value and length */ + if (GetMyVersion(source, &idx, &version, size) < 0) + return ASN_PARSE_E; + } else + version = 0; + + responderId = source[idx++]; + if ((responderId == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 1)) || + (responderId == (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 2))) + { + if (GetLength(source, &idx, &length, size) < 0) + return ASN_PARSE_E; + idx += length; + } + else + return ASN_PARSE_E; + + /* save pointer to the producedAt time */ + if (GetBasicDate(source, &idx, resp->producedDate, + &resp->producedDateFormat, size) < 0) + return ASN_PARSE_E; + + if (DecodeSingleResponse(source, &idx, resp, size) < 0) + return ASN_PARSE_E; + + /* + * Check the length of the ResponseData against the current index to + * see if there are extensions, they are optional. + */ + if (idx - prev_idx < resp->responseSz) + if (DecodeOcspRespExtensions(source, &idx, resp, size) < 0) + return ASN_PARSE_E; + + *ioIndex = idx; + return 0; +} + + +#ifndef WOLFSSL_NO_OCSP_OPTIONAL_CERTS + +static int DecodeCerts(byte* source, + word32* ioIndex, OcspResponse* resp, word32 size) +{ + word32 idx = *ioIndex; + + WOLFSSL_ENTER("DecodeCerts"); + + if (source[idx++] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) + { + int length; + + if (GetLength(source, &idx, &length, size) < 0) + return ASN_PARSE_E; + + if (GetSequence(source, &idx, &length, size) < 0) + return ASN_PARSE_E; + + resp->cert = source + idx; + resp->certSz = length; + + idx += length; + } + *ioIndex = idx; + return 0; +} + +#endif /* WOLFSSL_NO_OCSP_OPTIONAL_CERTS */ + + +static int DecodeBasicOcspResponse(byte* source, word32* ioIndex, + OcspResponse* resp, word32 size, void* cm, void* heap, int noVerify) +{ + int length; + word32 idx = *ioIndex; + word32 end_index; + int ret; + int sigLength; + + WOLFSSL_ENTER("DecodeBasicOcspResponse"); + (void)heap; + + if (GetSequence(source, &idx, &length, size) < 0) + return ASN_PARSE_E; + + if (idx + length > size) + return ASN_INPUT_E; + end_index = idx + length; + + if (DecodeResponseData(source, &idx, resp, size) < 0) + return ASN_PARSE_E; + + /* Get the signature algorithm */ + if (GetAlgoId(source, &idx, &resp->sigOID, oidSigType, size) < 0) + return ASN_PARSE_E; + + ret = CheckBitString(source, &idx, &sigLength, size, 1, NULL); + if (ret != 0) + return ret; + + resp->sigSz = sigLength; + resp->sig = source + idx; + idx += sigLength; + + /* + * Check the length of the BasicOcspResponse against the current index to + * see if there are certificates, they are optional. + */ +#ifndef WOLFSSL_NO_OCSP_OPTIONAL_CERTS + if (idx < end_index) + { + DecodedCert cert; + + if (DecodeCerts(source, &idx, resp, size) < 0) + return ASN_PARSE_E; + + InitDecodedCert(&cert, resp->cert, resp->certSz, heap); + + /* Don't verify if we don't have access to Cert Manager. */ + ret = ParseCertRelative(&cert, CERT_TYPE, + noVerify ? NO_VERIFY : VERIFY_OCSP, cm); + if (ret < 0) { + WOLFSSL_MSG("\tOCSP Responder certificate parsing failed"); + FreeDecodedCert(&cert); + return ret; + } + +#ifndef WOLFSSL_NO_OCSP_ISSUER_CHECK + if ((cert.extExtKeyUsage & EXTKEYUSE_OCSP_SIGN) == 0) { + if (XMEMCMP(cert.subjectHash, + resp->issuerHash, KEYID_SIZE) == 0) { + WOLFSSL_MSG("\tOCSP Response signed by issuer"); + } + else { + WOLFSSL_MSG("\tOCSP Responder key usage check failed"); + #ifdef OPENSSL_EXTRA + resp->verifyError = OCSP_BAD_ISSUER; + #else + FreeDecodedCert(&cert); + return BAD_OCSP_RESPONDER; + #endif + } + } +#endif + + /* ConfirmSignature is blocking here */ + ret = ConfirmSignature(&cert.sigCtx, + resp->response, resp->responseSz, + cert.publicKey, cert.pubKeySize, cert.keyOID, + resp->sig, resp->sigSz, resp->sigOID); + FreeDecodedCert(&cert); + + if (ret != 0) { + WOLFSSL_MSG("\tOCSP Confirm signature failed"); + return ASN_OCSP_CONFIRM_E; + } + } + else +#endif /* WOLFSSL_NO_OCSP_OPTIONAL_CERTS */ + { + Signer* ca = NULL; + int sigValid = -1; + + #ifndef NO_SKID + ca = GetCA(cm, resp->issuerKeyHash); + #else + ca = GetCA(cm, resp->issuerHash); + #endif + + if (ca) { + SignatureCtx sigCtx; + InitSignatureCtx(&sigCtx, heap, INVALID_DEVID); + + /* ConfirmSignature is blocking here */ + sigValid = ConfirmSignature(&sigCtx, resp->response, + resp->responseSz, ca->publicKey, ca->pubKeySize, ca->keyOID, + resp->sig, resp->sigSz, resp->sigOID); + } + if (ca == NULL || sigValid != 0) { + WOLFSSL_MSG("\tOCSP Confirm signature failed"); + return ASN_OCSP_CONFIRM_E; + } + + (void)noVerify; + } + + *ioIndex = idx; + return 0; +} + + +void InitOcspResponse(OcspResponse* resp, CertStatus* status, + byte* source, word32 inSz) +{ + WOLFSSL_ENTER("InitOcspResponse"); + + XMEMSET(status, 0, sizeof(CertStatus)); + XMEMSET(resp, 0, sizeof(OcspResponse)); + + resp->responseStatus = -1; + resp->status = status; + resp->source = source; + resp->maxIdx = inSz; +} + + +int OcspResponseDecode(OcspResponse* resp, void* cm, void* heap, int noVerify) +{ + int ret; + int length = 0; + word32 idx = 0; + byte* source = resp->source; + word32 size = resp->maxIdx; + word32 oid; + + WOLFSSL_ENTER("OcspResponseDecode"); + + /* peel the outer SEQUENCE wrapper */ + if (GetSequence(source, &idx, &length, size) < 0) + return ASN_PARSE_E; + + /* First get the responseStatus, an ENUMERATED */ + if (GetEnumerated(source, &idx, &resp->responseStatus) < 0) + return ASN_PARSE_E; + + if (resp->responseStatus != OCSP_SUCCESSFUL) + return 0; + + /* Next is an EXPLICIT record called ResponseBytes, OPTIONAL */ + if (idx >= size) + return ASN_INPUT_E; + if (source[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) + return ASN_PARSE_E; + if (GetLength(source, &idx, &length, size) < 0) + return ASN_PARSE_E; + + /* Get the responseBytes SEQUENCE */ + if (GetSequence(source, &idx, &length, size) < 0) + return ASN_PARSE_E; + + /* Check ObjectID for the resposeBytes */ + if (GetObjectId(source, &idx, &oid, oidOcspType, size) < 0) + return ASN_PARSE_E; + if (oid != OCSP_BASIC_OID) + return ASN_PARSE_E; + ret = GetOctetString(source, &idx, &length, size); + if (ret < 0) + return ret; + + ret = DecodeBasicOcspResponse(source, &idx, resp, size, cm, heap, noVerify); + if (ret < 0) + return ret; + + return 0; +} + + +word32 EncodeOcspRequestExtensions(OcspRequest* req, byte* output, word32 size) +{ + static const byte NonceObjId[] = { 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, + 0x30, 0x01, 0x02 }; + byte seqArray[5][MAX_SEQ_SZ]; + word32 seqSz[5], totalSz = (word32)sizeof(NonceObjId); + + WOLFSSL_ENTER("SetOcspReqExtensions"); + + if (!req || !output || !req->nonceSz) + return 0; + + totalSz += req->nonceSz; + totalSz += seqSz[0] = SetOctetString(req->nonceSz, seqArray[0]); + totalSz += seqSz[1] = SetOctetString(req->nonceSz + seqSz[0], seqArray[1]); + totalSz += seqSz[2] = SetObjectId(sizeof(NonceObjId), seqArray[2]); + totalSz += seqSz[3] = SetSequence(totalSz, seqArray[3]); + totalSz += seqSz[4] = SetSequence(totalSz, seqArray[4]); + + if (totalSz > size) + return 0; + + totalSz = 0; + + XMEMCPY(output + totalSz, seqArray[4], seqSz[4]); + totalSz += seqSz[4]; + + XMEMCPY(output + totalSz, seqArray[3], seqSz[3]); + totalSz += seqSz[3]; + + XMEMCPY(output + totalSz, seqArray[2], seqSz[2]); + totalSz += seqSz[2]; + + XMEMCPY(output + totalSz, NonceObjId, sizeof(NonceObjId)); + totalSz += (word32)sizeof(NonceObjId); + + XMEMCPY(output + totalSz, seqArray[1], seqSz[1]); + totalSz += seqSz[1]; + + XMEMCPY(output + totalSz, seqArray[0], seqSz[0]); + totalSz += seqSz[0]; + + XMEMCPY(output + totalSz, req->nonce, req->nonceSz); + totalSz += req->nonceSz; + + return totalSz; +} + + +int EncodeOcspRequest(OcspRequest* req, byte* output, word32 size) +{ + byte seqArray[5][MAX_SEQ_SZ]; + /* The ASN.1 of the OCSP Request is an onion of sequences */ + byte algoArray[MAX_ALGO_SZ]; + byte issuerArray[MAX_ENCODED_DIG_SZ]; + byte issuerKeyArray[MAX_ENCODED_DIG_SZ]; + byte snArray[MAX_SN_SZ]; + byte extArray[MAX_OCSP_EXT_SZ]; + word32 seqSz[5], algoSz, issuerSz, issuerKeySz, extSz, totalSz; + int i, snSz; + + WOLFSSL_ENTER("EncodeOcspRequest"); + +#ifdef NO_SHA + algoSz = SetAlgoID(SHA256h, algoArray, oidHashType, 0); +#else + algoSz = SetAlgoID(SHAh, algoArray, oidHashType, 0); +#endif + + issuerSz = SetDigest(req->issuerHash, KEYID_SIZE, issuerArray); + issuerKeySz = SetDigest(req->issuerKeyHash, KEYID_SIZE, issuerKeyArray); + snSz = SetSerialNumber(req->serial, req->serialSz, snArray, MAX_SN_SZ); + extSz = 0; + + if (snSz < 0) + return snSz; + + if (req->nonceSz) { + /* TLS Extensions use this function too - put extensions after + * ASN.1: Context Specific [2]. + */ + extSz = EncodeOcspRequestExtensions(req, extArray + 2, + OCSP_NONCE_EXT_SZ); + extSz += SetExplicit(2, extSz, extArray); + } + + totalSz = algoSz + issuerSz + issuerKeySz + snSz; + for (i = 4; i >= 0; i--) { + seqSz[i] = SetSequence(totalSz, seqArray[i]); + totalSz += seqSz[i]; + if (i == 2) totalSz += extSz; + } + + if (output == NULL) + return totalSz; + if (totalSz > size) + return BUFFER_E; + + totalSz = 0; + for (i = 0; i < 5; i++) { + XMEMCPY(output + totalSz, seqArray[i], seqSz[i]); + totalSz += seqSz[i]; + } + + XMEMCPY(output + totalSz, algoArray, algoSz); + totalSz += algoSz; + + XMEMCPY(output + totalSz, issuerArray, issuerSz); + totalSz += issuerSz; + + XMEMCPY(output + totalSz, issuerKeyArray, issuerKeySz); + totalSz += issuerKeySz; + + XMEMCPY(output + totalSz, snArray, snSz); + totalSz += snSz; + + if (extSz != 0) { + XMEMCPY(output + totalSz, extArray, extSz); + totalSz += extSz; + } + + return totalSz; +} + + +int InitOcspRequest(OcspRequest* req, DecodedCert* cert, byte useNonce, + void* heap) +{ + int ret; + + WOLFSSL_ENTER("InitOcspRequest"); + + if (req == NULL) + return BAD_FUNC_ARG; + + ForceZero(req, sizeof(OcspRequest)); + req->heap = heap; + + if (cert) { + XMEMCPY(req->issuerHash, cert->issuerHash, KEYID_SIZE); + XMEMCPY(req->issuerKeyHash, cert->issuerKeyHash, KEYID_SIZE); + + req->serial = (byte*)XMALLOC(cert->serialSz, req->heap, + DYNAMIC_TYPE_OCSP_REQUEST); + if (req->serial == NULL) + return MEMORY_E; + + XMEMCPY(req->serial, cert->serial, cert->serialSz); + req->serialSz = cert->serialSz; + + if (cert->extAuthInfoSz != 0 && cert->extAuthInfo != NULL) { + req->url = (byte*)XMALLOC(cert->extAuthInfoSz + 1, req->heap, + DYNAMIC_TYPE_OCSP_REQUEST); + if (req->url == NULL) { + XFREE(req->serial, req->heap, DYNAMIC_TYPE_OCSP); + return MEMORY_E; + } + + XMEMCPY(req->url, cert->extAuthInfo, cert->extAuthInfoSz); + req->urlSz = cert->extAuthInfoSz; + req->url[req->urlSz] = 0; + } + } + + if (useNonce) { + WC_RNG rng; + + #ifndef HAVE_FIPS + ret = wc_InitRng_ex(&rng, req->heap, INVALID_DEVID); + #else + ret = wc_InitRng(&rng); + #endif + if (ret != 0) { + WOLFSSL_MSG("\tCannot initialize RNG. Skipping the OSCP Nonce."); + } else { + if (wc_RNG_GenerateBlock(&rng, req->nonce, MAX_OCSP_NONCE_SZ) != 0) + WOLFSSL_MSG("\tCannot run RNG. Skipping the OSCP Nonce."); + else + req->nonceSz = MAX_OCSP_NONCE_SZ; + + wc_FreeRng(&rng); + } + } + + return 0; +} + +void FreeOcspRequest(OcspRequest* req) +{ + WOLFSSL_ENTER("FreeOcspRequest"); + + if (req) { + if (req->serial) + XFREE(req->serial, req->heap, DYNAMIC_TYPE_OCSP_REQUEST); + req->serial = NULL; + + if (req->url) + XFREE(req->url, req->heap, DYNAMIC_TYPE_OCSP_REQUEST); + req->url = NULL; + } +} + + +int CompareOcspReqResp(OcspRequest* req, OcspResponse* resp) +{ + int cmp; + + WOLFSSL_ENTER("CompareOcspReqResp"); + + if (req == NULL) + { + WOLFSSL_MSG("\tReq missing"); + return -1; + } + + if (resp == NULL) + { + WOLFSSL_MSG("\tResp missing"); + return 1; + } + + /* Nonces are not critical. The responder may not necessarily add + * the nonce to the response. */ + if (req->nonceSz +#ifndef WOLFSSL_FORCE_OCSP_NONCE_CHECK + && resp->nonceSz != 0 +#endif + ) { + cmp = req->nonceSz - resp->nonceSz; + if (cmp != 0) + { + WOLFSSL_MSG("\tnonceSz mismatch"); + return cmp; + } + + cmp = XMEMCMP(req->nonce, resp->nonce, req->nonceSz); + if (cmp != 0) + { + WOLFSSL_MSG("\tnonce mismatch"); + return cmp; + } + } + + cmp = XMEMCMP(req->issuerHash, resp->issuerHash, KEYID_SIZE); + if (cmp != 0) + { + WOLFSSL_MSG("\tissuerHash mismatch"); + return cmp; + } + + cmp = XMEMCMP(req->issuerKeyHash, resp->issuerKeyHash, KEYID_SIZE); + if (cmp != 0) + { + WOLFSSL_MSG("\tissuerKeyHash mismatch"); + return cmp; + } + + cmp = req->serialSz - resp->status->serialSz; + if (cmp != 0) + { + WOLFSSL_MSG("\tserialSz mismatch"); + return cmp; + } + + cmp = XMEMCMP(req->serial, resp->status->serial, req->serialSz); + if (cmp != 0) + { + WOLFSSL_MSG("\tserial mismatch"); + return cmp; + } + + return 0; +} + +#endif /* HAVE_OCSP */ + + +/* store WC_SHA hash of NAME */ +WOLFSSL_LOCAL int GetNameHash(const byte* source, word32* idx, byte* hash, + int maxIdx) +{ + int length; /* length of all distinguished names */ + int ret; + word32 dummy; + + WOLFSSL_ENTER("GetNameHash"); + + if (source[*idx] == ASN_OBJECT_ID) { + WOLFSSL_MSG("Trying optional prefix..."); + + if (GetLength(source, idx, &length, maxIdx) < 0) + return ASN_PARSE_E; + + *idx += length; + WOLFSSL_MSG("Got optional prefix"); + } + + /* For OCSP, RFC2560 section 4.1.1 states the issuer hash should be + * calculated over the entire DER encoding of the Name field, including + * the tag and length. */ + dummy = *idx; + if (GetSequence(source, idx, &length, maxIdx) < 0) + return ASN_PARSE_E; + + ret = CalcHashId(source + dummy, length + *idx - dummy, hash); + + *idx += length; + + return ret; +} + + +#ifdef HAVE_CRL + +/* initialize decoded CRL */ +void InitDecodedCRL(DecodedCRL* dcrl, void* heap) +{ + WOLFSSL_MSG("InitDecodedCRL"); + + dcrl->certBegin = 0; + dcrl->sigIndex = 0; + dcrl->sigLength = 0; + dcrl->signatureOID = 0; + dcrl->certs = NULL; + dcrl->totalCerts = 0; + dcrl->heap = heap; + #ifdef WOLFSSL_HEAP_TEST + dcrl->heap = (void*)WOLFSSL_HEAP_TEST; + #endif +} + + +/* free decoded CRL resources */ +void FreeDecodedCRL(DecodedCRL* dcrl) +{ + RevokedCert* tmp = dcrl->certs; + + WOLFSSL_MSG("FreeDecodedCRL"); + + while(tmp) { + RevokedCert* next = tmp->next; + XFREE(tmp, dcrl->heap, DYNAMIC_TYPE_REVOKED); + tmp = next; + } +} + + +/* Get Revoked Cert list, 0 on success */ +static int GetRevoked(const byte* buff, word32* idx, DecodedCRL* dcrl, + int maxIdx) +{ + int ret, len; + word32 end; + byte b; + RevokedCert* rc; + + WOLFSSL_ENTER("GetRevoked"); + + if (GetSequence(buff, idx, &len, maxIdx) < 0) + return ASN_PARSE_E; + + end = *idx + len; + + rc = (RevokedCert*)XMALLOC(sizeof(RevokedCert), dcrl->heap, + DYNAMIC_TYPE_REVOKED); + if (rc == NULL) { + WOLFSSL_MSG("Alloc Revoked Cert failed"); + return MEMORY_E; + } + + if (GetSerialNumber(buff, idx, rc->serialNumber, &rc->serialSz, + maxIdx) < 0) { + XFREE(rc, dcrl->heap, DYNAMIC_TYPE_REVOKED); + return ASN_PARSE_E; + } + + /* add to list */ + rc->next = dcrl->certs; + dcrl->certs = rc; + dcrl->totalCerts++; + + /* get date */ + ret = GetDateInfo(buff, idx, NULL, &b, NULL, maxIdx); + if (ret < 0) { + WOLFSSL_MSG("Expecting Date"); + return ret; + } + + if (*idx != end) /* skip extensions */ + *idx = end; + + return 0; +} + + +/* Get CRL Signature, 0 on success */ +static int GetCRL_Signature(const byte* source, word32* idx, DecodedCRL* dcrl, + int maxIdx) +{ + int length; + int ret; + + WOLFSSL_ENTER("GetCRL_Signature"); + + ret = CheckBitString(source, idx, &length, maxIdx, 1, NULL); + if (ret != 0) + return ret; + dcrl->sigLength = length; + + dcrl->signature = (byte*)&source[*idx]; + *idx += dcrl->sigLength; + + return 0; +} + +int VerifyCRL_Signature(SignatureCtx* sigCtx, const byte* toBeSigned, + word32 tbsSz, const byte* signature, word32 sigSz, + word32 signatureOID, Signer *ca, void* heap) +{ + /* try to confirm/verify signature */ +#ifndef IGNORE_KEY_EXTENSIONS + if ((ca->keyUsage & KEYUSE_CRL_SIGN) == 0) { + WOLFSSL_MSG("CA cannot sign CRLs"); + return ASN_CRL_NO_SIGNER_E; + } +#endif /* IGNORE_KEY_EXTENSIONS */ + + InitSignatureCtx(sigCtx, heap, INVALID_DEVID); + if (ConfirmSignature(sigCtx, toBeSigned, tbsSz, ca->publicKey, + ca->pubKeySize, ca->keyOID, signature, sigSz, + signatureOID) != 0) { + WOLFSSL_MSG("CRL Confirm signature failed"); + return ASN_CRL_CONFIRM_E; + } + + return 0; +} + +/* prase crl buffer into decoded state, 0 on success */ +int ParseCRL(DecodedCRL* dcrl, const byte* buff, word32 sz, void* cm) +{ + int version, len, doNextDate = 1; + word32 oid, idx = 0, dateIdx; + Signer* ca = NULL; + SignatureCtx sigCtx; + + WOLFSSL_MSG("ParseCRL"); + + /* raw crl hash */ + /* hash here if needed for optimized comparisons + * wc_Sha sha; + * wc_InitSha(&sha); + * wc_ShaUpdate(&sha, buff, sz); + * wc_ShaFinal(&sha, dcrl->crlHash); */ + + if (GetSequence(buff, &idx, &len, sz) < 0) + return ASN_PARSE_E; + + dcrl->certBegin = idx; + + if (GetSequence(buff, &idx, &len, sz) < 0) + return ASN_PARSE_E; + dcrl->sigIndex = len + idx; + + /* may have version */ + if (buff[idx] == ASN_INTEGER) { + if (GetMyVersion(buff, &idx, &version, sz) < 0) + return ASN_PARSE_E; + } + + if (GetAlgoId(buff, &idx, &oid, oidIgnoreType, sz) < 0) + return ASN_PARSE_E; + + if (GetNameHash(buff, &idx, dcrl->issuerHash, sz) < 0) + return ASN_PARSE_E; + + if (GetBasicDate(buff, &idx, dcrl->lastDate, &dcrl->lastDateFormat, sz) < 0) + return ASN_PARSE_E; + + dateIdx = idx; + + if (GetBasicDate(buff, &idx, dcrl->nextDate, &dcrl->nextDateFormat, sz) < 0) + { +#ifndef WOLFSSL_NO_CRL_NEXT_DATE + (void)dateIdx; + return ASN_PARSE_E; +#else + dcrl->nextDateFormat = ASN_OTHER_TYPE; /* skip flag */ + doNextDate = 0; + idx = dateIdx; +#endif + } + + if (doNextDate) { +#ifndef NO_ASN_TIME + if (!XVALIDATE_DATE(dcrl->nextDate, dcrl->nextDateFormat, AFTER)) { + WOLFSSL_MSG("CRL after date is no longer valid"); + return ASN_AFTER_DATE_E; + } +#endif + } + + if (idx != dcrl->sigIndex && buff[idx] != CRL_EXTENSIONS) { + if (GetSequence(buff, &idx, &len, sz) < 0) + return ASN_PARSE_E; + + len += idx; + + while (idx < (word32)len) { + if (GetRevoked(buff, &idx, dcrl, sz) < 0) + return ASN_PARSE_E; + } + } + + if (idx != dcrl->sigIndex) + idx = dcrl->sigIndex; /* skip extensions */ + + if (GetAlgoId(buff, &idx, &dcrl->signatureOID, oidSigType, sz) < 0) + return ASN_PARSE_E; + + if (GetCRL_Signature(buff, &idx, dcrl, sz) < 0) + return ASN_PARSE_E; + + /* openssl doesn't add skid by default for CRLs cause firefox chokes + we're not assuming it's available yet */ +#if !defined(NO_SKID) && defined(CRL_SKID_READY) + if (dcrl->extAuthKeyIdSet) + ca = GetCA(cm, dcrl->extAuthKeyId); + if (ca == NULL) + ca = GetCAByName(cm, dcrl->issuerHash); +#else + ca = GetCA(cm, dcrl->issuerHash); +#endif /* !NO_SKID && CRL_SKID_READY */ + WOLFSSL_MSG("About to verify CRL signature"); + + if (ca == NULL) { + WOLFSSL_MSG("Did NOT find CRL issuer CA"); + return ASN_CRL_NO_SIGNER_E; + } + + WOLFSSL_MSG("Found CRL issuer CA"); + return VerifyCRL_Signature(&sigCtx, buff + dcrl->certBegin, + dcrl->sigIndex - dcrl->certBegin, dcrl->signature, dcrl->sigLength, + dcrl->signatureOID, ca, dcrl->heap); +} + +#endif /* HAVE_CRL */ + + + +#ifdef WOLFSSL_CERT_PIV + +int wc_ParseCertPIV(wc_CertPIV* piv, const byte* buf, word32 totalSz) +{ + int length = 0; + word32 idx = 0; + + WOLFSSL_ENTER("wc_ParseCertPIV"); + + if (piv == NULL || buf == NULL || totalSz == 0) + return BAD_FUNC_ARG; + + XMEMSET(piv, 0, sizeof(wc_CertPIV)); + + /* Detect Identiv PIV (with 0x0A, 0x0B and 0x0C sections) */ + /* Certificate (0A 82 05FA) */ + if (GetASNHeader(buf, ASN_PIV_CERT, &idx, &length, totalSz) >= 0) { + /* Identiv Type PIV card */ + piv->isIdentiv = 1; + + piv->cert = &buf[idx]; + piv->certSz = length; + idx += length; + + /* Nonce (0B 14) */ + if (GetASNHeader(buf, ASN_PIV_NONCE, &idx, &length, totalSz) >= 0) { + piv->nonce = &buf[idx]; + piv->nonceSz = length; + idx += length; + } + + /* Signed Nonce (0C 82 0100) */ + if (GetASNHeader(buf, ASN_PIV_SIGNED_NONCE, &idx, &length, totalSz) >= 0) { + piv->signedNonce = &buf[idx]; + piv->signedNonceSz = length; + idx += length; + } + + idx = 0; + buf = piv->cert; + totalSz = piv->certSz; + } + + /* Certificate Buffer Total Size (53 82 05F6) */ + if (GetASNHeader(buf, ASN_APPLICATION | ASN_PRINTABLE_STRING, &idx, + &length, totalSz) < 0) { + return ASN_PARSE_E; + } + /* PIV Certificate (70 82 05ED) */ + if (GetASNHeader(buf, ASN_PIV_TAG_CERT, &idx, &length, + totalSz) < 0) { + return ASN_PARSE_E; + } + + /* Capture certificate buffer pointer and length */ + piv->cert = &buf[idx]; + piv->certSz = length; + idx += length; + + /* PIV Certificate Info (71 01 00) */ + if (GetASNHeader(buf, ASN_PIV_TAG_CERT_INFO, &idx, &length, + totalSz) >= 0) { + if (length >= 1) { + piv->compression = (buf[idx] & ASN_PIV_CERT_INFO_COMPRESSED); + piv->isX509 = (buf[idx] & ASN_PIV_CERT_INFO_ISX509); + } + idx += length; + } + + /* PIV Error Detection (FE 00) */ + if (GetASNHeader(buf, ASN_PIV_TAG_ERR_DET, &idx, &length, + totalSz) >= 0) { + piv->certErrDet = &buf[idx]; + piv->certErrDetSz = length; + idx += length; + } + + return 0; +} + +#endif /* WOLFSSL_CERT_PIV */ + + +#undef ERROR_OUT + +#endif /* !NO_ASN */ + +#ifdef WOLFSSL_SEP + + +#endif /* WOLFSSL_SEP */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/blake2b.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/blake2b.c new file mode 100755 index 0000000..59d849b --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/blake2b.c @@ -0,0 +1,453 @@ +/* + BLAKE2 reference source code package - reference C implementations + + Written in 2012 by Samuel Neves + + To the extent possible under law, the author(s) have dedicated all copyright + and related and neighboring rights to this software to the public domain + worldwide. This software is distributed without any warranty. + + You should have received a copy of the CC0 Public Domain Dedication along with + this software. If not, see . +*/ +/* blake2b.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifdef HAVE_BLAKE2 + +#include +#include + + +static const word64 blake2b_IV[8] = +{ + 0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL, + 0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL, + 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL, + 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL +}; + +static const byte blake2b_sigma[12][16] = +{ + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , + { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } , + { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } , + { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } , + { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } , + { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } , + { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } , + { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } , + { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } , + { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } , + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , + { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } +}; + + +static WC_INLINE int blake2b_set_lastnode( blake2b_state *S ) +{ + S->f[1] = ~0ULL; + return 0; +} + +/* Some helper functions, not necessarily useful */ +static WC_INLINE int blake2b_set_lastblock( blake2b_state *S ) +{ + if( S->last_node ) blake2b_set_lastnode( S ); + + S->f[0] = ~0ULL; + return 0; +} + +static WC_INLINE int blake2b_increment_counter( blake2b_state *S, const word64 + inc ) +{ + S->t[0] += inc; + S->t[1] += ( S->t[0] < inc ); + return 0; +} + +static WC_INLINE int blake2b_init0( blake2b_state *S ) +{ + int i; + XMEMSET( S, 0, sizeof( blake2b_state ) ); + + for( i = 0; i < 8; ++i ) S->h[i] = blake2b_IV[i]; + + return 0; +} + +/* init xors IV with input parameter block */ +int blake2b_init_param( blake2b_state *S, const blake2b_param *P ) +{ + word32 i; + byte *p ; + blake2b_init0( S ); + p = ( byte * )( P ); + + /* IV XOR ParamBlock */ + for( i = 0; i < 8; ++i ) + S->h[i] ^= load64( p + sizeof( S->h[i] ) * i ); + + return 0; +} + + + +int blake2b_init( blake2b_state *S, const byte outlen ) +{ + blake2b_param P[1]; + + if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1; + +#ifdef WOLFSSL_BLAKE2B_INIT_EACH_FIELD + P->digest_length = outlen; + P->key_length = 0; + P->fanout = 1; + P->depth = 1; + store32( &P->leaf_length, 0 ); + store64( &P->node_offset, 0 ); + P->node_depth = 0; + P->inner_length = 0; + XMEMSET( P->reserved, 0, sizeof( P->reserved ) ); + XMEMSET( P->salt, 0, sizeof( P->salt ) ); + XMEMSET( P->personal, 0, sizeof( P->personal ) ); +#else + XMEMSET( P, 0, sizeof( *P ) ); + P->digest_length = outlen; + P->fanout = 1; + P->depth = 1; +#endif + return blake2b_init_param( S, P ); +} + + +int blake2b_init_key( blake2b_state *S, const byte outlen, const void *key, + const byte keylen ) +{ + blake2b_param P[1]; + + if ( ( !outlen ) || ( outlen > BLAKE2B_OUTBYTES ) ) return -1; + + if ( !key || !keylen || keylen > BLAKE2B_KEYBYTES ) return -1; + +#ifdef WOLFSSL_BLAKE2B_INIT_EACH_FIELD + P->digest_length = outlen; + P->key_length = keylen; + P->fanout = 1; + P->depth = 1; + store32( &P->leaf_length, 0 ); + store64( &P->node_offset, 0 ); + P->node_depth = 0; + P->inner_length = 0; + XMEMSET( P->reserved, 0, sizeof( P->reserved ) ); + XMEMSET( P->salt, 0, sizeof( P->salt ) ); + XMEMSET( P->personal, 0, sizeof( P->personal ) ); +#else + XMEMSET( P, 0, sizeof( *P ) ); + P->digest_length = outlen; + P->key_length = keylen; + P->fanout = 1; + P->depth = 1; +#endif + + if( blake2b_init_param( S, P ) < 0 ) return -1; + + { +#ifdef WOLFSSL_SMALL_STACK + byte* block; + + block = (byte*)XMALLOC(BLAKE2B_BLOCKBYTES, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + if ( block == NULL ) return -1; +#else + byte block[BLAKE2B_BLOCKBYTES]; +#endif + + XMEMSET( block, 0, BLAKE2B_BLOCKBYTES ); + XMEMCPY( block, key, keylen ); + blake2b_update( S, block, BLAKE2B_BLOCKBYTES ); + secure_zero_memory( block, BLAKE2B_BLOCKBYTES ); /* Burn the key from */ + /* memory */ + +#ifdef WOLFSSL_SMALL_STACK + XFREE(block, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + } + return 0; +} + +static int blake2b_compress( blake2b_state *S, + const byte block[BLAKE2B_BLOCKBYTES] ) +{ + int i; + +#ifdef WOLFSSL_SMALL_STACK + word64* m; + word64* v; + + m = (word64*)XMALLOC(sizeof(word64) * 16, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + if ( m == NULL ) return -1; + + v = (word64*)XMALLOC(sizeof(word64) * 16, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + if ( v == NULL ) + { + XFREE(m, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return -1; + } +#else + word64 m[16]; + word64 v[16]; +#endif + + for( i = 0; i < 16; ++i ) + m[i] = load64( block + i * sizeof( m[i] ) ); + + for( i = 0; i < 8; ++i ) + v[i] = S->h[i]; + + v[ 8] = blake2b_IV[0]; + v[ 9] = blake2b_IV[1]; + v[10] = blake2b_IV[2]; + v[11] = blake2b_IV[3]; + v[12] = S->t[0] ^ blake2b_IV[4]; + v[13] = S->t[1] ^ blake2b_IV[5]; + v[14] = S->f[0] ^ blake2b_IV[6]; + v[15] = S->f[1] ^ blake2b_IV[7]; +#define G(r,i,a,b,c,d) \ + do { \ + a = a + b + m[blake2b_sigma[r][2*i+0]]; \ + d = rotr64(d ^ a, 32); \ + c = c + d; \ + b = rotr64(b ^ c, 24); \ + a = a + b + m[blake2b_sigma[r][2*i+1]]; \ + d = rotr64(d ^ a, 16); \ + c = c + d; \ + b = rotr64(b ^ c, 63); \ + } while(0) +#define ROUND(r) \ + do { \ + G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \ + G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \ + G(r,2,v[ 2],v[ 6],v[10],v[14]); \ + G(r,3,v[ 3],v[ 7],v[11],v[15]); \ + G(r,4,v[ 0],v[ 5],v[10],v[15]); \ + G(r,5,v[ 1],v[ 6],v[11],v[12]); \ + G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \ + G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \ + } while(0) + ROUND( 0 ); + ROUND( 1 ); + ROUND( 2 ); + ROUND( 3 ); + ROUND( 4 ); + ROUND( 5 ); + ROUND( 6 ); + ROUND( 7 ); + ROUND( 8 ); + ROUND( 9 ); + ROUND( 10 ); + ROUND( 11 ); + + for( i = 0; i < 8; ++i ) + S->h[i] = S->h[i] ^ v[i] ^ v[i + 8]; + +#undef G +#undef ROUND + +#ifdef WOLFSSL_SMALL_STACK + XFREE(m, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(v, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return 0; +} + +/* inlen now in bytes */ +int blake2b_update( blake2b_state *S, const byte *in, word64 inlen ) +{ + while( inlen > 0 ) + { + word64 left = S->buflen; + word64 fill = 2 * BLAKE2B_BLOCKBYTES - left; + + if( inlen > fill ) + { + XMEMCPY( S->buf + left, in, (wolfssl_word)fill ); /* Fill buffer */ + S->buflen += fill; + blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES ); + + if ( blake2b_compress( S, S->buf ) < 0 ) return -1; /* Compress */ + + XMEMCPY( S->buf, S->buf + BLAKE2B_BLOCKBYTES, BLAKE2B_BLOCKBYTES ); + /* Shift buffer left */ + S->buflen -= BLAKE2B_BLOCKBYTES; + in += fill; + inlen -= fill; + } + else /* inlen <= fill */ + { + XMEMCPY( S->buf + left, in, (wolfssl_word)inlen ); + S->buflen += inlen; /* Be lazy, do not compress */ + in += inlen; + inlen -= inlen; + } + } + + return 0; +} + +/* Is this correct? */ +int blake2b_final( blake2b_state *S, byte *out, byte outlen ) +{ + byte buffer[BLAKE2B_OUTBYTES]; + int i; + + if( S->buflen > BLAKE2B_BLOCKBYTES ) + { + blake2b_increment_counter( S, BLAKE2B_BLOCKBYTES ); + + if ( blake2b_compress( S, S->buf ) < 0 ) return -1; + + S->buflen -= BLAKE2B_BLOCKBYTES; + XMEMCPY( S->buf, S->buf + BLAKE2B_BLOCKBYTES, (wolfssl_word)S->buflen ); + } + + blake2b_increment_counter( S, S->buflen ); + blake2b_set_lastblock( S ); + XMEMSET( S->buf + S->buflen, 0, (wolfssl_word)(2 * BLAKE2B_BLOCKBYTES - S->buflen) ); + /* Padding */ + if ( blake2b_compress( S, S->buf ) < 0 ) return -1; + + for( i = 0; i < 8; ++i ) /* Output full hash to temp buffer */ + store64( buffer + sizeof( S->h[i] ) * i, S->h[i] ); + + XMEMCPY( out, buffer, outlen ); + return 0; +} + +/* inlen, at least, should be word64. Others can be size_t. */ +int blake2b( byte *out, const void *in, const void *key, const byte outlen, + const word64 inlen, byte keylen ) +{ + blake2b_state S[1]; + + /* Verify parameters */ + if ( NULL == in ) return -1; + + if ( NULL == out ) return -1; + + if( NULL == key ) keylen = 0; + + if( keylen > 0 ) + { + if( blake2b_init_key( S, outlen, key, keylen ) < 0 ) return -1; + } + else + { + if( blake2b_init( S, outlen ) < 0 ) return -1; + } + + if ( blake2b_update( S, ( byte * )in, inlen ) < 0) return -1; + + return blake2b_final( S, out, outlen ); +} + +#if defined(BLAKE2B_SELFTEST) +#include +#include "blake2-kat.h" +int main( int argc, char **argv ) +{ + byte key[BLAKE2B_KEYBYTES]; + byte buf[KAT_LENGTH]; + + for( word32 i = 0; i < BLAKE2B_KEYBYTES; ++i ) + key[i] = ( byte )i; + + for( word32 i = 0; i < KAT_LENGTH; ++i ) + buf[i] = ( byte )i; + + for( word32 i = 0; i < KAT_LENGTH; ++i ) + { + byte hash[BLAKE2B_OUTBYTES]; + if ( blake2b( hash, buf, key, BLAKE2B_OUTBYTES, i, BLAKE2B_KEYBYTES ) < 0 ) + { + puts( "error" ); + return -1; + } + + if( 0 != XMEMCMP( hash, blake2b_keyed_kat[i], BLAKE2B_OUTBYTES ) ) + { + puts( "error" ); + return -1; + } + } + + puts( "ok" ); + return 0; +} +#endif + + +/* wolfCrypt API */ + +/* Init Blake2b digest, track size in case final doesn't want to "remember" */ +int wc_InitBlake2b(Blake2b* b2b, word32 digestSz) +{ + if (b2b == NULL){ + return -1; + } + b2b->digestSz = digestSz; + + return blake2b_init(b2b->S, (byte)digestSz); +} + + +/* Blake2b Update */ +int wc_Blake2bUpdate(Blake2b* b2b, const byte* data, word32 sz) +{ + return blake2b_update(b2b->S, data, sz); +} + + +/* Blake2b Final, if pass in zero size we use init digestSz */ +int wc_Blake2bFinal(Blake2b* b2b, byte* final, word32 requestSz) +{ + word32 sz = requestSz ? requestSz : b2b->digestSz; + + return blake2b_final(b2b->S, final, (byte)sz); +} + + +/* end CTaoCrypt API */ + +#endif /* HAVE_BLAKE2 */ + diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/blake2s.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/blake2s.c new file mode 100755 index 0000000..9ef817c --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/blake2s.c @@ -0,0 +1,447 @@ +/* + BLAKE2 reference source code package - reference C implementations + + Written in 2012 by Samuel Neves + + To the extent possible under law, the author(s) have dedicated all copyright + and related and neighboring rights to this software to the public domain + worldwide. This software is distributed without any warranty. + + You should have received a copy of the CC0 Public Domain Dedication along with + this software. If not, see . +*/ +/* blake2s.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifdef HAVE_BLAKE2S + +#include +#include + + +static const word32 blake2s_IV[8] = +{ + 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, + 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19 +}; + +static const byte blake2s_sigma[10][16] = +{ + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 } , + { 14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3 } , + { 11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4 } , + { 7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8 } , + { 9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13 } , + { 2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9 } , + { 12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11 } , + { 13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10 } , + { 6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5 } , + { 10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13 , 0 } +}; + + +static WC_INLINE int blake2s_set_lastnode( blake2s_state *S ) +{ + S->f[1] = ~0; + return 0; +} + +/* Some helper functions, not necessarily useful */ +static WC_INLINE int blake2s_set_lastblock( blake2s_state *S ) +{ + if( S->last_node ) blake2s_set_lastnode( S ); + + S->f[0] = ~0; + return 0; +} + +static WC_INLINE int blake2s_increment_counter( blake2s_state *S, const word32 + inc ) +{ + S->t[0] += inc; + S->t[1] += ( S->t[0] < inc ); + return 0; +} + +static WC_INLINE int blake2s_init0( blake2s_state *S ) +{ + int i; + XMEMSET( S, 0, sizeof( blake2s_state ) ); + + for( i = 0; i < 8; ++i ) S->h[i] = blake2s_IV[i]; + + return 0; +} + +/* init xors IV with input parameter block */ +int blake2s_init_param( blake2s_state *S, const blake2s_param *P ) +{ + word32 i; + byte *p ; + blake2s_init0( S ); + p = ( byte * )( P ); + + /* IV XOR ParamBlock */ + for( i = 0; i < 8; ++i ) + S->h[i] ^= load32( p + sizeof( S->h[i] ) * i ); + + return 0; +} + + + +int blake2s_init( blake2s_state *S, const byte outlen ) +{ + blake2s_param P[1]; + + if ( ( !outlen ) || ( outlen > BLAKE2S_OUTBYTES ) ) return -1; + +#ifdef WOLFSSL_BLAKE2S_INIT_EACH_FIELD + P->digest_length = outlen; + P->key_length = 0; + P->fanout = 1; + P->depth = 1; + store32( &P->leaf_length, 0 ); + store32( &P->node_offset, 0 ); + P->node_depth = 0; + P->inner_length = 0; + XMEMSET( P->reserved, 0, sizeof( P->reserved ) ); + XMEMSET( P->salt, 0, sizeof( P->salt ) ); + XMEMSET( P->personal, 0, sizeof( P->personal ) ); +#else + XMEMSET( P, 0, sizeof( *P ) ); + P->digest_length = outlen; + P->fanout = 1; + P->depth = 1; +#endif + return blake2s_init_param( S, P ); +} + + +int blake2s_init_key( blake2s_state *S, const byte outlen, const void *key, + const byte keylen ) +{ + blake2s_param P[1]; + + if ( ( !outlen ) || ( outlen > BLAKE2S_OUTBYTES ) ) return -1; + + if ( !key || !keylen || keylen > BLAKE2S_KEYBYTES ) return -1; + +#ifdef WOLFSSL_BLAKE2S_INIT_EACH_FIELD + P->digest_length = outlen; + P->key_length = keylen; + P->fanout = 1; + P->depth = 1; + store32( &P->leaf_length, 0 ); + store64( &P->node_offset, 0 ); + P->node_depth = 0; + P->inner_length = 0; + XMEMSET( P->reserved, 0, sizeof( P->reserved ) ); + XMEMSET( P->salt, 0, sizeof( P->salt ) ); + XMEMSET( P->personal, 0, sizeof( P->personal ) ); +#else + XMEMSET( P, 0, sizeof( *P ) ); + P->digest_length = outlen; + P->key_length = keylen; + P->fanout = 1; + P->depth = 1; +#endif + + if( blake2s_init_param( S, P ) < 0 ) return -1; + + { +#ifdef WOLFSSL_SMALL_STACK + byte* block; + + block = (byte*)XMALLOC(BLAKE2S_BLOCKBYTES, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + if ( block == NULL ) return -1; +#else + byte block[BLAKE2S_BLOCKBYTES]; +#endif + + XMEMSET( block, 0, BLAKE2S_BLOCKBYTES ); + XMEMCPY( block, key, keylen ); + blake2s_update( S, block, BLAKE2S_BLOCKBYTES ); + secure_zero_memory( block, BLAKE2S_BLOCKBYTES ); /* Burn the key from */ + /* memory */ + +#ifdef WOLFSSL_SMALL_STACK + XFREE(block, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + } + return 0; +} + +static int blake2s_compress( blake2s_state *S, + const byte block[BLAKE2S_BLOCKBYTES] ) +{ + int i; + +#ifdef WOLFSSL_SMALL_STACK + word32* m; + word32* v; + + m = (word32*)XMALLOC(sizeof(word32) * 16, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + if ( m == NULL ) return -1; + + v = (word32*)XMALLOC(sizeof(word32) * 16, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + if ( v == NULL ) + { + XFREE(m, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return -1; + } +#else + word32 m[16]; + word32 v[16]; +#endif + + for( i = 0; i < 16; ++i ) + m[i] = load32( block + i * sizeof( m[i] ) ); + + for( i = 0; i < 8; ++i ) + v[i] = S->h[i]; + + v[ 8] = blake2s_IV[0]; + v[ 9] = blake2s_IV[1]; + v[10] = blake2s_IV[2]; + v[11] = blake2s_IV[3]; + v[12] = S->t[0] ^ blake2s_IV[4]; + v[13] = S->t[1] ^ blake2s_IV[5]; + v[14] = S->f[0] ^ blake2s_IV[6]; + v[15] = S->f[1] ^ blake2s_IV[7]; +#define G(r,i,a,b,c,d) \ + do { \ + a = a + b + m[blake2s_sigma[r][2*i+0]]; \ + d = rotr32(d ^ a, 16); \ + c = c + d; \ + b = rotr32(b ^ c, 12); \ + a = a + b + m[blake2s_sigma[r][2*i+1]]; \ + d = rotr32(d ^ a, 8); \ + c = c + d; \ + b = rotr32(b ^ c, 7); \ + } while(0) +#define ROUND(r) \ + do { \ + G(r,0,v[ 0],v[ 4],v[ 8],v[12]); \ + G(r,1,v[ 1],v[ 5],v[ 9],v[13]); \ + G(r,2,v[ 2],v[ 6],v[10],v[14]); \ + G(r,3,v[ 3],v[ 7],v[11],v[15]); \ + G(r,4,v[ 0],v[ 5],v[10],v[15]); \ + G(r,5,v[ 1],v[ 6],v[11],v[12]); \ + G(r,6,v[ 2],v[ 7],v[ 8],v[13]); \ + G(r,7,v[ 3],v[ 4],v[ 9],v[14]); \ + } while(0) + ROUND( 0 ); + ROUND( 1 ); + ROUND( 2 ); + ROUND( 3 ); + ROUND( 4 ); + ROUND( 5 ); + ROUND( 6 ); + ROUND( 7 ); + ROUND( 8 ); + ROUND( 9 ); + + for( i = 0; i < 8; ++i ) + S->h[i] = S->h[i] ^ v[i] ^ v[i + 8]; + +#undef G +#undef ROUND + +#ifdef WOLFSSL_SMALL_STACK + XFREE(m, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(v, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return 0; +} + +/* inlen now in bytes */ +int blake2s_update( blake2s_state *S, const byte *in, word32 inlen ) +{ + while( inlen > 0 ) + { + word32 left = S->buflen; + word32 fill = 2 * BLAKE2S_BLOCKBYTES - left; + + if( inlen > fill ) + { + XMEMCPY( S->buf + left, in, (wolfssl_word)fill ); /* Fill buffer */ + S->buflen += fill; + blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES ); + + if ( blake2s_compress( S, S->buf ) < 0 ) return -1; /* Compress */ + + XMEMCPY( S->buf, S->buf + BLAKE2S_BLOCKBYTES, BLAKE2S_BLOCKBYTES ); + /* Shift buffer left */ + S->buflen -= BLAKE2S_BLOCKBYTES; + in += fill; + inlen -= fill; + } + else /* inlen <= fill */ + { + XMEMCPY( S->buf + left, in, (wolfssl_word)inlen ); + S->buflen += inlen; /* Be lazy, do not compress */ + in += inlen; + inlen -= inlen; + } + } + + return 0; +} + +/* Is this correct? */ +int blake2s_final( blake2s_state *S, byte *out, byte outlen ) +{ + int i; + byte buffer[BLAKE2S_BLOCKBYTES]; + + if( S->buflen > BLAKE2S_BLOCKBYTES ) + { + blake2s_increment_counter( S, BLAKE2S_BLOCKBYTES ); + + if ( blake2s_compress( S, S->buf ) < 0 ) return -1; + + S->buflen -= BLAKE2S_BLOCKBYTES; + XMEMCPY( S->buf, S->buf + BLAKE2S_BLOCKBYTES, (wolfssl_word)S->buflen ); + } + + blake2s_increment_counter( S, S->buflen ); + blake2s_set_lastblock( S ); + XMEMSET( S->buf + S->buflen, 0, (wolfssl_word)(2 * BLAKE2S_BLOCKBYTES - S->buflen) ); + /* Padding */ + if ( blake2s_compress( S, S->buf ) < 0 ) return -1; + + for( i = 0; i < 8; ++i ) /* Output full hash to temp buffer */ + store64( buffer + sizeof( S->h[i] ) * i, S->h[i] ); + + XMEMCPY( out, buffer, outlen ); + return 0; +} + +/* inlen, at least, should be word32. Others can be size_t. */ +int blake2s( byte *out, const void *in, const void *key, const byte outlen, + const word32 inlen, byte keylen ) +{ + blake2s_state S[1]; + + /* Verify parameters */ + if ( NULL == in ) return -1; + + if ( NULL == out ) return -1; + + if( NULL == key ) keylen = 0; + + if( keylen > 0 ) + { + if( blake2s_init_key( S, outlen, key, keylen ) < 0 ) return -1; + } + else + { + if( blake2s_init( S, outlen ) < 0 ) return -1; + } + + if ( blake2s_update( S, ( byte * )in, inlen ) < 0) return -1; + + return blake2s_final( S, out, outlen ); +} + +#if defined(BLAKE2S_SELFTEST) +#include +#include "blake2-kat.h" +int main( int argc, char **argv ) +{ + byte key[BLAKE2S_KEYBYTES]; + byte buf[KAT_LENGTH]; + + for( word32 i = 0; i < BLAKE2S_KEYBYTES; ++i ) + key[i] = ( byte )i; + + for( word32 i = 0; i < KAT_LENGTH; ++i ) + buf[i] = ( byte )i; + + for( word32 i = 0; i < KAT_LENGTH; ++i ) + { + byte hash[BLAKE2S_OUTBYTES]; + if ( blake2s( hash, buf, key, BLAKE2S_OUTBYTES, i, BLAKE2S_KEYBYTES ) < 0 ) + { + puts( "error" ); + return -1; + } + + if( 0 != XMEMCMP( hash, blake2s_keyed_kat[i], BLAKE2S_OUTBYTES ) ) + { + puts( "error" ); + return -1; + } + } + + puts( "ok" ); + return 0; +} +#endif + + +/* wolfCrypt API */ + +/* Init Blake2s digest, track size in case final doesn't want to "remember" */ +int wc_InitBlake2s(Blake2s* b2s, word32 digestSz) +{ + if (b2s == NULL){ + return -1; + } + b2s->digestSz = digestSz; + + return blake2s_init(b2s->S, (byte)digestSz); +} + + +/* Blake2s Update */ +int wc_Blake2sUpdate(Blake2s* b2s, const byte* data, word32 sz) +{ + return blake2s_update(b2s->S, data, sz); +} + + +/* Blake2s Final, if pass in zero size we use init digestSz */ +int wc_Blake2sFinal(Blake2s* b2s, byte* final, word32 requestSz) +{ + word32 sz = requestSz ? requestSz : b2s->digestSz; + + return blake2s_final(b2s->S, final, (byte)sz); +} + + +/* end CTaoCrypt API */ + +#endif /* HAVE_BLAKE2S */ + diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/camellia.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/camellia.c new file mode 100755 index 0000000..96f8bc9 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/camellia.c @@ -0,0 +1,1644 @@ +/* camellia.c ver 1.2.0 + * + * Copyright (c) 2006,2007 + * NTT (Nippon Telegraph and Telephone Corporation) . All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer as + * the first lines of this file unmodified. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY NTT ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL NTT BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* camellia.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +/* + * Algorithm Specification + * http://info.isl.ntt.co.jp/crypt/eng/camellia/specifications.html + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifdef HAVE_CAMELLIA + +#include +#include +#include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +/* u32 must be 32bit word */ +typedef unsigned int u32; +typedef unsigned char u8; + +/* key constants */ + +#define CAMELLIA_SIGMA1L ((u32)0xA09E667FL) +#define CAMELLIA_SIGMA1R ((u32)0x3BCC908BL) +#define CAMELLIA_SIGMA2L ((u32)0xB67AE858L) +#define CAMELLIA_SIGMA2R ((u32)0x4CAA73B2L) +#define CAMELLIA_SIGMA3L ((u32)0xC6EF372FL) +#define CAMELLIA_SIGMA3R ((u32)0xE94F82BEL) +#define CAMELLIA_SIGMA4L ((u32)0x54FF53A5L) +#define CAMELLIA_SIGMA4R ((u32)0xF1D36F1CL) +#define CAMELLIA_SIGMA5L ((u32)0x10E527FAL) +#define CAMELLIA_SIGMA5R ((u32)0xDE682D1DL) +#define CAMELLIA_SIGMA6L ((u32)0xB05688C2L) +#define CAMELLIA_SIGMA6R ((u32)0xB3E6C1FDL) + +/* + * macros + */ + + +#if defined(_MSC_VER) + +# define SWAP(x) (_lrotl(x, 8) & 0x00ff00ff | _lrotr(x, 8) & 0xff00ff00) +# define GETU32(p) SWAP(*((u32 *)(p))) +# define PUTU32(ct, st) {*((u32 *)(ct)) = SWAP((st));} + +#else /* not MS-VC */ + +# define GETU32(pt) \ + (((u32)(pt)[0] << 24) \ + ^ ((u32)(pt)[1] << 16) \ + ^ ((u32)(pt)[2] << 8) \ + ^ ((u32)(pt)[3])) + +# define PUTU32(ct, st) { \ + (ct)[0] = (u8)((st) >> 24); \ + (ct)[1] = (u8)((st) >> 16); \ + (ct)[2] = (u8)((st) >> 8); \ + (ct)[3] = (u8)(st); } + +#endif + +#define CamelliaSubkeyL(INDEX) (subkey[(INDEX)*2]) +#define CamelliaSubkeyR(INDEX) (subkey[(INDEX)*2 + 1]) + +/* rotation right shift 1byte */ +#define CAMELLIA_RR8(x) (((x) >> 8) + ((x) << 24)) +/* rotation left shift 1bit */ +#define CAMELLIA_RL1(x) (((x) << 1) + ((x) >> 31)) +/* rotation left shift 1byte */ +#define CAMELLIA_RL8(x) (((x) << 8) + ((x) >> 24)) + +#define CAMELLIA_ROLDQ(ll, lr, rl, rr, w0, w1, bits) \ + do { \ + w0 = ll; \ + ll = (ll << bits) + (lr >> (32 - bits)); \ + lr = (lr << bits) + (rl >> (32 - bits)); \ + rl = (rl << bits) + (rr >> (32 - bits)); \ + rr = (rr << bits) + (w0 >> (32 - bits)); \ + } while(0) + +#define CAMELLIA_ROLDQo32(ll, lr, rl, rr, w0, w1, bits) \ + do { \ + w0 = ll; \ + w1 = lr; \ + ll = (lr << (bits - 32)) + (rl >> (64 - bits)); \ + lr = (rl << (bits - 32)) + (rr >> (64 - bits)); \ + rl = (rr << (bits - 32)) + (w0 >> (64 - bits)); \ + rr = (w0 << (bits - 32)) + (w1 >> (64 - bits)); \ + } while(0) + +#define CAMELLIA_SP1110(INDEX) (camellia_sp1110[(INDEX)]) +#define CAMELLIA_SP0222(INDEX) (camellia_sp0222[(INDEX)]) +#define CAMELLIA_SP3033(INDEX) (camellia_sp3033[(INDEX)]) +#define CAMELLIA_SP4404(INDEX) (camellia_sp4404[(INDEX)]) + +#define CAMELLIA_F(xl, xr, kl, kr, yl, yr, il, ir, t0, t1) \ + do { \ + il = xl ^ kl; \ + ir = xr ^ kr; \ + t0 = il >> 16; \ + t1 = ir >> 16; \ + yl = CAMELLIA_SP1110(ir & 0xff) \ + ^ CAMELLIA_SP0222((t1 >> 8) & 0xff) \ + ^ CAMELLIA_SP3033(t1 & 0xff) \ + ^ CAMELLIA_SP4404((ir >> 8) & 0xff); \ + yr = CAMELLIA_SP1110((t0 >> 8) & 0xff) \ + ^ CAMELLIA_SP0222(t0 & 0xff) \ + ^ CAMELLIA_SP3033((il >> 8) & 0xff) \ + ^ CAMELLIA_SP4404(il & 0xff); \ + yl ^= yr; \ + yr = CAMELLIA_RR8(yr); \ + yr ^= yl; \ + } while(0) + + +/* + * for speed up + * + */ +#define CAMELLIA_FLS(ll, lr, rl, rr, kll, klr, krl, krr, t0, t1, t2, t3) \ + do { \ + t0 = kll; \ + t0 &= ll; \ + lr ^= CAMELLIA_RL1(t0); \ + t1 = klr; \ + t1 |= lr; \ + ll ^= t1; \ + \ + t2 = krr; \ + t2 |= rr; \ + rl ^= t2; \ + t3 = krl; \ + t3 &= rl; \ + rr ^= CAMELLIA_RL1(t3); \ + } while(0) + +#define CAMELLIA_ROUNDSM(xl, xr, kl, kr, yl, yr, il, ir, t0, t1) \ + do { \ + ir = CAMELLIA_SP1110(xr & 0xff) \ + ^ CAMELLIA_SP0222((xr >> 24) & 0xff) \ + ^ CAMELLIA_SP3033((xr >> 16) & 0xff) \ + ^ CAMELLIA_SP4404((xr >> 8) & 0xff); \ + il = CAMELLIA_SP1110((xl >> 24) & 0xff) \ + ^ CAMELLIA_SP0222((xl >> 16) & 0xff) \ + ^ CAMELLIA_SP3033((xl >> 8) & 0xff) \ + ^ CAMELLIA_SP4404(xl & 0xff); \ + il ^= kl; \ + ir ^= kr; \ + ir ^= il; \ + il = CAMELLIA_RR8(il); \ + il ^= ir; \ + yl ^= ir; \ + yr ^= il; \ + } while(0) + + +static const u32 camellia_sp1110[256] = { + 0x70707000,0x82828200,0x2c2c2c00,0xececec00, + 0xb3b3b300,0x27272700,0xc0c0c000,0xe5e5e500, + 0xe4e4e400,0x85858500,0x57575700,0x35353500, + 0xeaeaea00,0x0c0c0c00,0xaeaeae00,0x41414100, + 0x23232300,0xefefef00,0x6b6b6b00,0x93939300, + 0x45454500,0x19191900,0xa5a5a500,0x21212100, + 0xededed00,0x0e0e0e00,0x4f4f4f00,0x4e4e4e00, + 0x1d1d1d00,0x65656500,0x92929200,0xbdbdbd00, + 0x86868600,0xb8b8b800,0xafafaf00,0x8f8f8f00, + 0x7c7c7c00,0xebebeb00,0x1f1f1f00,0xcecece00, + 0x3e3e3e00,0x30303000,0xdcdcdc00,0x5f5f5f00, + 0x5e5e5e00,0xc5c5c500,0x0b0b0b00,0x1a1a1a00, + 0xa6a6a600,0xe1e1e100,0x39393900,0xcacaca00, + 0xd5d5d500,0x47474700,0x5d5d5d00,0x3d3d3d00, + 0xd9d9d900,0x01010100,0x5a5a5a00,0xd6d6d600, + 0x51515100,0x56565600,0x6c6c6c00,0x4d4d4d00, + 0x8b8b8b00,0x0d0d0d00,0x9a9a9a00,0x66666600, + 0xfbfbfb00,0xcccccc00,0xb0b0b000,0x2d2d2d00, + 0x74747400,0x12121200,0x2b2b2b00,0x20202000, + 0xf0f0f000,0xb1b1b100,0x84848400,0x99999900, + 0xdfdfdf00,0x4c4c4c00,0xcbcbcb00,0xc2c2c200, + 0x34343400,0x7e7e7e00,0x76767600,0x05050500, + 0x6d6d6d00,0xb7b7b700,0xa9a9a900,0x31313100, + 0xd1d1d100,0x17171700,0x04040400,0xd7d7d700, + 0x14141400,0x58585800,0x3a3a3a00,0x61616100, + 0xdedede00,0x1b1b1b00,0x11111100,0x1c1c1c00, + 0x32323200,0x0f0f0f00,0x9c9c9c00,0x16161600, + 0x53535300,0x18181800,0xf2f2f200,0x22222200, + 0xfefefe00,0x44444400,0xcfcfcf00,0xb2b2b200, + 0xc3c3c300,0xb5b5b500,0x7a7a7a00,0x91919100, + 0x24242400,0x08080800,0xe8e8e800,0xa8a8a800, + 0x60606000,0xfcfcfc00,0x69696900,0x50505000, + 0xaaaaaa00,0xd0d0d000,0xa0a0a000,0x7d7d7d00, + 0xa1a1a100,0x89898900,0x62626200,0x97979700, + 0x54545400,0x5b5b5b00,0x1e1e1e00,0x95959500, + 0xe0e0e000,0xffffff00,0x64646400,0xd2d2d200, + 0x10101000,0xc4c4c400,0x00000000,0x48484800, + 0xa3a3a300,0xf7f7f700,0x75757500,0xdbdbdb00, + 0x8a8a8a00,0x03030300,0xe6e6e600,0xdadada00, + 0x09090900,0x3f3f3f00,0xdddddd00,0x94949400, + 0x87878700,0x5c5c5c00,0x83838300,0x02020200, + 0xcdcdcd00,0x4a4a4a00,0x90909000,0x33333300, + 0x73737300,0x67676700,0xf6f6f600,0xf3f3f300, + 0x9d9d9d00,0x7f7f7f00,0xbfbfbf00,0xe2e2e200, + 0x52525200,0x9b9b9b00,0xd8d8d800,0x26262600, + 0xc8c8c800,0x37373700,0xc6c6c600,0x3b3b3b00, + 0x81818100,0x96969600,0x6f6f6f00,0x4b4b4b00, + 0x13131300,0xbebebe00,0x63636300,0x2e2e2e00, + 0xe9e9e900,0x79797900,0xa7a7a700,0x8c8c8c00, + 0x9f9f9f00,0x6e6e6e00,0xbcbcbc00,0x8e8e8e00, + 0x29292900,0xf5f5f500,0xf9f9f900,0xb6b6b600, + 0x2f2f2f00,0xfdfdfd00,0xb4b4b400,0x59595900, + 0x78787800,0x98989800,0x06060600,0x6a6a6a00, + 0xe7e7e700,0x46464600,0x71717100,0xbababa00, + 0xd4d4d400,0x25252500,0xababab00,0x42424200, + 0x88888800,0xa2a2a200,0x8d8d8d00,0xfafafa00, + 0x72727200,0x07070700,0xb9b9b900,0x55555500, + 0xf8f8f800,0xeeeeee00,0xacacac00,0x0a0a0a00, + 0x36363600,0x49494900,0x2a2a2a00,0x68686800, + 0x3c3c3c00,0x38383800,0xf1f1f100,0xa4a4a400, + 0x40404000,0x28282800,0xd3d3d300,0x7b7b7b00, + 0xbbbbbb00,0xc9c9c900,0x43434300,0xc1c1c100, + 0x15151500,0xe3e3e300,0xadadad00,0xf4f4f400, + 0x77777700,0xc7c7c700,0x80808000,0x9e9e9e00, +}; + +static const u32 camellia_sp0222[256] = { + 0x00e0e0e0,0x00050505,0x00585858,0x00d9d9d9, + 0x00676767,0x004e4e4e,0x00818181,0x00cbcbcb, + 0x00c9c9c9,0x000b0b0b,0x00aeaeae,0x006a6a6a, + 0x00d5d5d5,0x00181818,0x005d5d5d,0x00828282, + 0x00464646,0x00dfdfdf,0x00d6d6d6,0x00272727, + 0x008a8a8a,0x00323232,0x004b4b4b,0x00424242, + 0x00dbdbdb,0x001c1c1c,0x009e9e9e,0x009c9c9c, + 0x003a3a3a,0x00cacaca,0x00252525,0x007b7b7b, + 0x000d0d0d,0x00717171,0x005f5f5f,0x001f1f1f, + 0x00f8f8f8,0x00d7d7d7,0x003e3e3e,0x009d9d9d, + 0x007c7c7c,0x00606060,0x00b9b9b9,0x00bebebe, + 0x00bcbcbc,0x008b8b8b,0x00161616,0x00343434, + 0x004d4d4d,0x00c3c3c3,0x00727272,0x00959595, + 0x00ababab,0x008e8e8e,0x00bababa,0x007a7a7a, + 0x00b3b3b3,0x00020202,0x00b4b4b4,0x00adadad, + 0x00a2a2a2,0x00acacac,0x00d8d8d8,0x009a9a9a, + 0x00171717,0x001a1a1a,0x00353535,0x00cccccc, + 0x00f7f7f7,0x00999999,0x00616161,0x005a5a5a, + 0x00e8e8e8,0x00242424,0x00565656,0x00404040, + 0x00e1e1e1,0x00636363,0x00090909,0x00333333, + 0x00bfbfbf,0x00989898,0x00979797,0x00858585, + 0x00686868,0x00fcfcfc,0x00ececec,0x000a0a0a, + 0x00dadada,0x006f6f6f,0x00535353,0x00626262, + 0x00a3a3a3,0x002e2e2e,0x00080808,0x00afafaf, + 0x00282828,0x00b0b0b0,0x00747474,0x00c2c2c2, + 0x00bdbdbd,0x00363636,0x00222222,0x00383838, + 0x00646464,0x001e1e1e,0x00393939,0x002c2c2c, + 0x00a6a6a6,0x00303030,0x00e5e5e5,0x00444444, + 0x00fdfdfd,0x00888888,0x009f9f9f,0x00656565, + 0x00878787,0x006b6b6b,0x00f4f4f4,0x00232323, + 0x00484848,0x00101010,0x00d1d1d1,0x00515151, + 0x00c0c0c0,0x00f9f9f9,0x00d2d2d2,0x00a0a0a0, + 0x00555555,0x00a1a1a1,0x00414141,0x00fafafa, + 0x00434343,0x00131313,0x00c4c4c4,0x002f2f2f, + 0x00a8a8a8,0x00b6b6b6,0x003c3c3c,0x002b2b2b, + 0x00c1c1c1,0x00ffffff,0x00c8c8c8,0x00a5a5a5, + 0x00202020,0x00898989,0x00000000,0x00909090, + 0x00474747,0x00efefef,0x00eaeaea,0x00b7b7b7, + 0x00151515,0x00060606,0x00cdcdcd,0x00b5b5b5, + 0x00121212,0x007e7e7e,0x00bbbbbb,0x00292929, + 0x000f0f0f,0x00b8b8b8,0x00070707,0x00040404, + 0x009b9b9b,0x00949494,0x00212121,0x00666666, + 0x00e6e6e6,0x00cecece,0x00ededed,0x00e7e7e7, + 0x003b3b3b,0x00fefefe,0x007f7f7f,0x00c5c5c5, + 0x00a4a4a4,0x00373737,0x00b1b1b1,0x004c4c4c, + 0x00919191,0x006e6e6e,0x008d8d8d,0x00767676, + 0x00030303,0x002d2d2d,0x00dedede,0x00969696, + 0x00262626,0x007d7d7d,0x00c6c6c6,0x005c5c5c, + 0x00d3d3d3,0x00f2f2f2,0x004f4f4f,0x00191919, + 0x003f3f3f,0x00dcdcdc,0x00797979,0x001d1d1d, + 0x00525252,0x00ebebeb,0x00f3f3f3,0x006d6d6d, + 0x005e5e5e,0x00fbfbfb,0x00696969,0x00b2b2b2, + 0x00f0f0f0,0x00313131,0x000c0c0c,0x00d4d4d4, + 0x00cfcfcf,0x008c8c8c,0x00e2e2e2,0x00757575, + 0x00a9a9a9,0x004a4a4a,0x00575757,0x00848484, + 0x00111111,0x00454545,0x001b1b1b,0x00f5f5f5, + 0x00e4e4e4,0x000e0e0e,0x00737373,0x00aaaaaa, + 0x00f1f1f1,0x00dddddd,0x00595959,0x00141414, + 0x006c6c6c,0x00929292,0x00545454,0x00d0d0d0, + 0x00787878,0x00707070,0x00e3e3e3,0x00494949, + 0x00808080,0x00505050,0x00a7a7a7,0x00f6f6f6, + 0x00777777,0x00939393,0x00868686,0x00838383, + 0x002a2a2a,0x00c7c7c7,0x005b5b5b,0x00e9e9e9, + 0x00eeeeee,0x008f8f8f,0x00010101,0x003d3d3d, +}; + +static const u32 camellia_sp3033[256] = { + 0x38003838,0x41004141,0x16001616,0x76007676, + 0xd900d9d9,0x93009393,0x60006060,0xf200f2f2, + 0x72007272,0xc200c2c2,0xab00abab,0x9a009a9a, + 0x75007575,0x06000606,0x57005757,0xa000a0a0, + 0x91009191,0xf700f7f7,0xb500b5b5,0xc900c9c9, + 0xa200a2a2,0x8c008c8c,0xd200d2d2,0x90009090, + 0xf600f6f6,0x07000707,0xa700a7a7,0x27002727, + 0x8e008e8e,0xb200b2b2,0x49004949,0xde00dede, + 0x43004343,0x5c005c5c,0xd700d7d7,0xc700c7c7, + 0x3e003e3e,0xf500f5f5,0x8f008f8f,0x67006767, + 0x1f001f1f,0x18001818,0x6e006e6e,0xaf00afaf, + 0x2f002f2f,0xe200e2e2,0x85008585,0x0d000d0d, + 0x53005353,0xf000f0f0,0x9c009c9c,0x65006565, + 0xea00eaea,0xa300a3a3,0xae00aeae,0x9e009e9e, + 0xec00ecec,0x80008080,0x2d002d2d,0x6b006b6b, + 0xa800a8a8,0x2b002b2b,0x36003636,0xa600a6a6, + 0xc500c5c5,0x86008686,0x4d004d4d,0x33003333, + 0xfd00fdfd,0x66006666,0x58005858,0x96009696, + 0x3a003a3a,0x09000909,0x95009595,0x10001010, + 0x78007878,0xd800d8d8,0x42004242,0xcc00cccc, + 0xef00efef,0x26002626,0xe500e5e5,0x61006161, + 0x1a001a1a,0x3f003f3f,0x3b003b3b,0x82008282, + 0xb600b6b6,0xdb00dbdb,0xd400d4d4,0x98009898, + 0xe800e8e8,0x8b008b8b,0x02000202,0xeb00ebeb, + 0x0a000a0a,0x2c002c2c,0x1d001d1d,0xb000b0b0, + 0x6f006f6f,0x8d008d8d,0x88008888,0x0e000e0e, + 0x19001919,0x87008787,0x4e004e4e,0x0b000b0b, + 0xa900a9a9,0x0c000c0c,0x79007979,0x11001111, + 0x7f007f7f,0x22002222,0xe700e7e7,0x59005959, + 0xe100e1e1,0xda00dada,0x3d003d3d,0xc800c8c8, + 0x12001212,0x04000404,0x74007474,0x54005454, + 0x30003030,0x7e007e7e,0xb400b4b4,0x28002828, + 0x55005555,0x68006868,0x50005050,0xbe00bebe, + 0xd000d0d0,0xc400c4c4,0x31003131,0xcb00cbcb, + 0x2a002a2a,0xad00adad,0x0f000f0f,0xca00caca, + 0x70007070,0xff00ffff,0x32003232,0x69006969, + 0x08000808,0x62006262,0x00000000,0x24002424, + 0xd100d1d1,0xfb00fbfb,0xba00baba,0xed00eded, + 0x45004545,0x81008181,0x73007373,0x6d006d6d, + 0x84008484,0x9f009f9f,0xee00eeee,0x4a004a4a, + 0xc300c3c3,0x2e002e2e,0xc100c1c1,0x01000101, + 0xe600e6e6,0x25002525,0x48004848,0x99009999, + 0xb900b9b9,0xb300b3b3,0x7b007b7b,0xf900f9f9, + 0xce00cece,0xbf00bfbf,0xdf00dfdf,0x71007171, + 0x29002929,0xcd00cdcd,0x6c006c6c,0x13001313, + 0x64006464,0x9b009b9b,0x63006363,0x9d009d9d, + 0xc000c0c0,0x4b004b4b,0xb700b7b7,0xa500a5a5, + 0x89008989,0x5f005f5f,0xb100b1b1,0x17001717, + 0xf400f4f4,0xbc00bcbc,0xd300d3d3,0x46004646, + 0xcf00cfcf,0x37003737,0x5e005e5e,0x47004747, + 0x94009494,0xfa00fafa,0xfc00fcfc,0x5b005b5b, + 0x97009797,0xfe00fefe,0x5a005a5a,0xac00acac, + 0x3c003c3c,0x4c004c4c,0x03000303,0x35003535, + 0xf300f3f3,0x23002323,0xb800b8b8,0x5d005d5d, + 0x6a006a6a,0x92009292,0xd500d5d5,0x21002121, + 0x44004444,0x51005151,0xc600c6c6,0x7d007d7d, + 0x39003939,0x83008383,0xdc00dcdc,0xaa00aaaa, + 0x7c007c7c,0x77007777,0x56005656,0x05000505, + 0x1b001b1b,0xa400a4a4,0x15001515,0x34003434, + 0x1e001e1e,0x1c001c1c,0xf800f8f8,0x52005252, + 0x20002020,0x14001414,0xe900e9e9,0xbd00bdbd, + 0xdd00dddd,0xe400e4e4,0xa100a1a1,0xe000e0e0, + 0x8a008a8a,0xf100f1f1,0xd600d6d6,0x7a007a7a, + 0xbb00bbbb,0xe300e3e3,0x40004040,0x4f004f4f, +}; + +static const u32 camellia_sp4404[256] = { + 0x70700070,0x2c2c002c,0xb3b300b3,0xc0c000c0, + 0xe4e400e4,0x57570057,0xeaea00ea,0xaeae00ae, + 0x23230023,0x6b6b006b,0x45450045,0xa5a500a5, + 0xeded00ed,0x4f4f004f,0x1d1d001d,0x92920092, + 0x86860086,0xafaf00af,0x7c7c007c,0x1f1f001f, + 0x3e3e003e,0xdcdc00dc,0x5e5e005e,0x0b0b000b, + 0xa6a600a6,0x39390039,0xd5d500d5,0x5d5d005d, + 0xd9d900d9,0x5a5a005a,0x51510051,0x6c6c006c, + 0x8b8b008b,0x9a9a009a,0xfbfb00fb,0xb0b000b0, + 0x74740074,0x2b2b002b,0xf0f000f0,0x84840084, + 0xdfdf00df,0xcbcb00cb,0x34340034,0x76760076, + 0x6d6d006d,0xa9a900a9,0xd1d100d1,0x04040004, + 0x14140014,0x3a3a003a,0xdede00de,0x11110011, + 0x32320032,0x9c9c009c,0x53530053,0xf2f200f2, + 0xfefe00fe,0xcfcf00cf,0xc3c300c3,0x7a7a007a, + 0x24240024,0xe8e800e8,0x60600060,0x69690069, + 0xaaaa00aa,0xa0a000a0,0xa1a100a1,0x62620062, + 0x54540054,0x1e1e001e,0xe0e000e0,0x64640064, + 0x10100010,0x00000000,0xa3a300a3,0x75750075, + 0x8a8a008a,0xe6e600e6,0x09090009,0xdddd00dd, + 0x87870087,0x83830083,0xcdcd00cd,0x90900090, + 0x73730073,0xf6f600f6,0x9d9d009d,0xbfbf00bf, + 0x52520052,0xd8d800d8,0xc8c800c8,0xc6c600c6, + 0x81810081,0x6f6f006f,0x13130013,0x63630063, + 0xe9e900e9,0xa7a700a7,0x9f9f009f,0xbcbc00bc, + 0x29290029,0xf9f900f9,0x2f2f002f,0xb4b400b4, + 0x78780078,0x06060006,0xe7e700e7,0x71710071, + 0xd4d400d4,0xabab00ab,0x88880088,0x8d8d008d, + 0x72720072,0xb9b900b9,0xf8f800f8,0xacac00ac, + 0x36360036,0x2a2a002a,0x3c3c003c,0xf1f100f1, + 0x40400040,0xd3d300d3,0xbbbb00bb,0x43430043, + 0x15150015,0xadad00ad,0x77770077,0x80800080, + 0x82820082,0xecec00ec,0x27270027,0xe5e500e5, + 0x85850085,0x35350035,0x0c0c000c,0x41410041, + 0xefef00ef,0x93930093,0x19190019,0x21210021, + 0x0e0e000e,0x4e4e004e,0x65650065,0xbdbd00bd, + 0xb8b800b8,0x8f8f008f,0xebeb00eb,0xcece00ce, + 0x30300030,0x5f5f005f,0xc5c500c5,0x1a1a001a, + 0xe1e100e1,0xcaca00ca,0x47470047,0x3d3d003d, + 0x01010001,0xd6d600d6,0x56560056,0x4d4d004d, + 0x0d0d000d,0x66660066,0xcccc00cc,0x2d2d002d, + 0x12120012,0x20200020,0xb1b100b1,0x99990099, + 0x4c4c004c,0xc2c200c2,0x7e7e007e,0x05050005, + 0xb7b700b7,0x31310031,0x17170017,0xd7d700d7, + 0x58580058,0x61610061,0x1b1b001b,0x1c1c001c, + 0x0f0f000f,0x16160016,0x18180018,0x22220022, + 0x44440044,0xb2b200b2,0xb5b500b5,0x91910091, + 0x08080008,0xa8a800a8,0xfcfc00fc,0x50500050, + 0xd0d000d0,0x7d7d007d,0x89890089,0x97970097, + 0x5b5b005b,0x95950095,0xffff00ff,0xd2d200d2, + 0xc4c400c4,0x48480048,0xf7f700f7,0xdbdb00db, + 0x03030003,0xdada00da,0x3f3f003f,0x94940094, + 0x5c5c005c,0x02020002,0x4a4a004a,0x33330033, + 0x67670067,0xf3f300f3,0x7f7f007f,0xe2e200e2, + 0x9b9b009b,0x26260026,0x37370037,0x3b3b003b, + 0x96960096,0x4b4b004b,0xbebe00be,0x2e2e002e, + 0x79790079,0x8c8c008c,0x6e6e006e,0x8e8e008e, + 0xf5f500f5,0xb6b600b6,0xfdfd00fd,0x59590059, + 0x98980098,0x6a6a006a,0x46460046,0xbaba00ba, + 0x25250025,0x42420042,0xa2a200a2,0xfafa00fa, + 0x07070007,0x55550055,0xeeee00ee,0x0a0a000a, + 0x49490049,0x68680068,0x38380038,0xa4a400a4, + 0x28280028,0x7b7b007b,0xc9c900c9,0xc1c100c1, + 0xe3e300e3,0xf4f400f4,0xc7c700c7,0x9e9e009e, +}; + + +/** + * Stuff related to the Camellia key schedule + */ +#define subl(x) subL[(x)] +#define subr(x) subR[(x)] + +static int camellia_setup128(const unsigned char *key, u32 *subkey) +{ + u32 kll, klr, krl, krr; + u32 il, ir, t0, t1, w0, w1; + u32 kw4l, kw4r, dw, tl, tr; + +#ifdef WOLFSSL_SMALL_STACK + u32* subL; + u32* subR; + + subL = (u32*) XMALLOC(sizeof(u32) * 26, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (subL == NULL) + return MEMORY_E; + + subR = (u32*) XMALLOC(sizeof(u32) * 26, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (subR == NULL) { + XFREE(subL, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#else + u32 subL[26]; + u32 subR[26]; +#endif + + /** + * k == kll || klr || krl || krr (|| is concatenation) + */ + kll = GETU32(key ); + klr = GETU32(key + 4); + krl = GETU32(key + 8); + krr = GETU32(key + 12); + /** + * generate KL dependent subkeys + */ + subl(0) = kll; subr(0) = klr; + subl(1) = krl; subr(1) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); + subl(4) = kll; subr(4) = klr; + subl(5) = krl; subr(5) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 30); + subl(10) = kll; subr(10) = klr; + subl(11) = krl; subr(11) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); + subl(13) = krl; subr(13) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17); + subl(16) = kll; subr(16) = klr; + subl(17) = krl; subr(17) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17); + subl(18) = kll; subr(18) = klr; + subl(19) = krl; subr(19) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17); + subl(22) = kll; subr(22) = klr; + subl(23) = krl; subr(23) = krr; + + /* generate KA */ + kll = subl(0); klr = subr(0); + krl = subl(1); krr = subr(1); + CAMELLIA_F(kll, klr, + CAMELLIA_SIGMA1L, CAMELLIA_SIGMA1R, + w0, w1, il, ir, t0, t1); + krl ^= w0; krr ^= w1; + CAMELLIA_F(krl, krr, + CAMELLIA_SIGMA2L, CAMELLIA_SIGMA2R, + kll, klr, il, ir, t0, t1); + CAMELLIA_F(kll, klr, + CAMELLIA_SIGMA3L, CAMELLIA_SIGMA3R, + krl, krr, il, ir, t0, t1); + krl ^= w0; krr ^= w1; + CAMELLIA_F(krl, krr, + CAMELLIA_SIGMA4L, CAMELLIA_SIGMA4R, + w0, w1, il, ir, t0, t1); + kll ^= w0; klr ^= w1; + + /* generate KA dependent subkeys */ + subl(2) = kll; subr(2) = klr; + subl(3) = krl; subr(3) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); + subl(6) = kll; subr(6) = klr; + subl(7) = krl; subr(7) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); + subl(8) = kll; subr(8) = klr; + subl(9) = krl; subr(9) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); + subl(12) = kll; subr(12) = klr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); + subl(14) = kll; subr(14) = klr; + subl(15) = krl; subr(15) = krr; + CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 34); + subl(20) = kll; subr(20) = klr; + subl(21) = krl; subr(21) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17); + subl(24) = kll; subr(24) = klr; + subl(25) = krl; subr(25) = krr; + + + /* absorb kw2 to other subkeys */ + subl(3) ^= subl(1); subr(3) ^= subr(1); + subl(5) ^= subl(1); subr(5) ^= subr(1); + subl(7) ^= subl(1); subr(7) ^= subr(1); + subl(1) ^= subr(1) & ~subr(9); + dw = subl(1) & subl(9), subr(1) ^= CAMELLIA_RL1(dw); + subl(11) ^= subl(1); subr(11) ^= subr(1); + subl(13) ^= subl(1); subr(13) ^= subr(1); + subl(15) ^= subl(1); subr(15) ^= subr(1); + subl(1) ^= subr(1) & ~subr(17); + dw = subl(1) & subl(17), subr(1) ^= CAMELLIA_RL1(dw); + subl(19) ^= subl(1); subr(19) ^= subr(1); + subl(21) ^= subl(1); subr(21) ^= subr(1); + subl(23) ^= subl(1); subr(23) ^= subr(1); + subl(24) ^= subl(1); subr(24) ^= subr(1); + + /* absorb kw4 to other subkeys */ + kw4l = subl(25); kw4r = subr(25); + subl(22) ^= kw4l; subr(22) ^= kw4r; + subl(20) ^= kw4l; subr(20) ^= kw4r; + subl(18) ^= kw4l; subr(18) ^= kw4r; + kw4l ^= kw4r & ~subr(16); + dw = kw4l & subl(16), kw4r ^= CAMELLIA_RL1(dw); + subl(14) ^= kw4l; subr(14) ^= kw4r; + subl(12) ^= kw4l; subr(12) ^= kw4r; + subl(10) ^= kw4l; subr(10) ^= kw4r; + kw4l ^= kw4r & ~subr(8); + dw = kw4l & subl(8), kw4r ^= CAMELLIA_RL1(dw); + subl(6) ^= kw4l; subr(6) ^= kw4r; + subl(4) ^= kw4l; subr(4) ^= kw4r; + subl(2) ^= kw4l; subr(2) ^= kw4r; + subl(0) ^= kw4l; subr(0) ^= kw4r; + + /* key XOR is end of F-function */ + CamelliaSubkeyL(0) = subl(0) ^ subl(2); + CamelliaSubkeyR(0) = subr(0) ^ subr(2); + CamelliaSubkeyL(2) = subl(3); + CamelliaSubkeyR(2) = subr(3); + CamelliaSubkeyL(3) = subl(2) ^ subl(4); + CamelliaSubkeyR(3) = subr(2) ^ subr(4); + CamelliaSubkeyL(4) = subl(3) ^ subl(5); + CamelliaSubkeyR(4) = subr(3) ^ subr(5); + CamelliaSubkeyL(5) = subl(4) ^ subl(6); + CamelliaSubkeyR(5) = subr(4) ^ subr(6); + CamelliaSubkeyL(6) = subl(5) ^ subl(7); + CamelliaSubkeyR(6) = subr(5) ^ subr(7); + tl = subl(10) ^ (subr(10) & ~subr(8)); + dw = tl & subl(8), tr = subr(10) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(7) = subl(6) ^ tl; + CamelliaSubkeyR(7) = subr(6) ^ tr; + CamelliaSubkeyL(8) = subl(8); + CamelliaSubkeyR(8) = subr(8); + CamelliaSubkeyL(9) = subl(9); + CamelliaSubkeyR(9) = subr(9); + tl = subl(7) ^ (subr(7) & ~subr(9)); + dw = tl & subl(9), tr = subr(7) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(10) = tl ^ subl(11); + CamelliaSubkeyR(10) = tr ^ subr(11); + CamelliaSubkeyL(11) = subl(10) ^ subl(12); + CamelliaSubkeyR(11) = subr(10) ^ subr(12); + CamelliaSubkeyL(12) = subl(11) ^ subl(13); + CamelliaSubkeyR(12) = subr(11) ^ subr(13); + CamelliaSubkeyL(13) = subl(12) ^ subl(14); + CamelliaSubkeyR(13) = subr(12) ^ subr(14); + CamelliaSubkeyL(14) = subl(13) ^ subl(15); + CamelliaSubkeyR(14) = subr(13) ^ subr(15); + tl = subl(18) ^ (subr(18) & ~subr(16)); + dw = tl & subl(16), tr = subr(18) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(15) = subl(14) ^ tl; + CamelliaSubkeyR(15) = subr(14) ^ tr; + CamelliaSubkeyL(16) = subl(16); + CamelliaSubkeyR(16) = subr(16); + CamelliaSubkeyL(17) = subl(17); + CamelliaSubkeyR(17) = subr(17); + tl = subl(15) ^ (subr(15) & ~subr(17)); + dw = tl & subl(17), tr = subr(15) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(18) = tl ^ subl(19); + CamelliaSubkeyR(18) = tr ^ subr(19); + CamelliaSubkeyL(19) = subl(18) ^ subl(20); + CamelliaSubkeyR(19) = subr(18) ^ subr(20); + CamelliaSubkeyL(20) = subl(19) ^ subl(21); + CamelliaSubkeyR(20) = subr(19) ^ subr(21); + CamelliaSubkeyL(21) = subl(20) ^ subl(22); + CamelliaSubkeyR(21) = subr(20) ^ subr(22); + CamelliaSubkeyL(22) = subl(21) ^ subl(23); + CamelliaSubkeyR(22) = subr(21) ^ subr(23); + CamelliaSubkeyL(23) = subl(22); + CamelliaSubkeyR(23) = subr(22); + CamelliaSubkeyL(24) = subl(24) ^ subl(23); + CamelliaSubkeyR(24) = subr(24) ^ subr(23); + + /* apply the inverse of the last half of P-function */ + dw = CamelliaSubkeyL(2) ^ CamelliaSubkeyR(2), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(2) = CamelliaSubkeyL(2) ^ dw, CamelliaSubkeyL(2) = dw; + dw = CamelliaSubkeyL(3) ^ CamelliaSubkeyR(3), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(3) = CamelliaSubkeyL(3) ^ dw, CamelliaSubkeyL(3) = dw; + dw = CamelliaSubkeyL(4) ^ CamelliaSubkeyR(4), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(4) = CamelliaSubkeyL(4) ^ dw, CamelliaSubkeyL(4) = dw; + dw = CamelliaSubkeyL(5) ^ CamelliaSubkeyR(5), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(5) = CamelliaSubkeyL(5) ^ dw, CamelliaSubkeyL(5) = dw; + dw = CamelliaSubkeyL(6) ^ CamelliaSubkeyR(6), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(6) = CamelliaSubkeyL(6) ^ dw, CamelliaSubkeyL(6) = dw; + dw = CamelliaSubkeyL(7) ^ CamelliaSubkeyR(7), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(7) = CamelliaSubkeyL(7) ^ dw, CamelliaSubkeyL(7) = dw; + dw = CamelliaSubkeyL(10) ^ CamelliaSubkeyR(10), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(10) = CamelliaSubkeyL(10) ^ dw, CamelliaSubkeyL(10) = dw; + dw = CamelliaSubkeyL(11) ^ CamelliaSubkeyR(11), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(11) = CamelliaSubkeyL(11) ^ dw, CamelliaSubkeyL(11) = dw; + dw = CamelliaSubkeyL(12) ^ CamelliaSubkeyR(12), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(12) = CamelliaSubkeyL(12) ^ dw, CamelliaSubkeyL(12) = dw; + dw = CamelliaSubkeyL(13) ^ CamelliaSubkeyR(13), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(13) = CamelliaSubkeyL(13) ^ dw, CamelliaSubkeyL(13) = dw; + dw = CamelliaSubkeyL(14) ^ CamelliaSubkeyR(14), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(14) = CamelliaSubkeyL(14) ^ dw, CamelliaSubkeyL(14) = dw; + dw = CamelliaSubkeyL(15) ^ CamelliaSubkeyR(15), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(15) = CamelliaSubkeyL(15) ^ dw, CamelliaSubkeyL(15) = dw; + dw = CamelliaSubkeyL(18) ^ CamelliaSubkeyR(18), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(18) = CamelliaSubkeyL(18) ^ dw, CamelliaSubkeyL(18) = dw; + dw = CamelliaSubkeyL(19) ^ CamelliaSubkeyR(19), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(19) = CamelliaSubkeyL(19) ^ dw, CamelliaSubkeyL(19) = dw; + dw = CamelliaSubkeyL(20) ^ CamelliaSubkeyR(20), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(20) = CamelliaSubkeyL(20) ^ dw, CamelliaSubkeyL(20) = dw; + dw = CamelliaSubkeyL(21) ^ CamelliaSubkeyR(21), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(21) = CamelliaSubkeyL(21) ^ dw, CamelliaSubkeyL(21) = dw; + dw = CamelliaSubkeyL(22) ^ CamelliaSubkeyR(22), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(22) = CamelliaSubkeyL(22) ^ dw, CamelliaSubkeyL(22) = dw; + dw = CamelliaSubkeyL(23) ^ CamelliaSubkeyR(23), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(23) = CamelliaSubkeyL(23) ^ dw, CamelliaSubkeyL(23) = dw; + +#ifdef WOLFSSL_SMALL_STACK + XFREE(subL, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(subR, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return 0; +} + +static int camellia_setup256(const unsigned char *key, u32 *subkey) +{ + u32 kll,klr,krl,krr; /* left half of key */ + u32 krll,krlr,krrl,krrr; /* right half of key */ + u32 il, ir, t0, t1, w0, w1; /* temporary variables */ + u32 kw4l, kw4r, dw, tl, tr; + +#ifdef WOLFSSL_SMALL_STACK + u32* subL; + u32* subR; + + subL = (u32*) XMALLOC(sizeof(u32) * 34, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (subL == NULL) + return MEMORY_E; + + subR = (u32*) XMALLOC(sizeof(u32) * 34, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (subR == NULL) { + XFREE(subL, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#else + u32 subL[34]; + u32 subR[34]; +#endif + + /** + * key = (kll || klr || krl || krr || krll || krlr || krrl || krrr) + * (|| is concatenation) + */ + + kll = GETU32(key ); + klr = GETU32(key + 4); + krl = GETU32(key + 8); + krr = GETU32(key + 12); + krll = GETU32(key + 16); + krlr = GETU32(key + 20); + krrl = GETU32(key + 24); + krrr = GETU32(key + 28); + + /* generate KL dependent subkeys */ + subl(0) = kll; subr(0) = klr; + subl(1) = krl; subr(1) = krr; + CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 45); + subl(12) = kll; subr(12) = klr; + subl(13) = krl; subr(13) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); + subl(16) = kll; subr(16) = klr; + subl(17) = krl; subr(17) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 17); + subl(22) = kll; subr(22) = klr; + subl(23) = krl; subr(23) = krr; + CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 34); + subl(30) = kll; subr(30) = klr; + subl(31) = krl; subr(31) = krr; + + /* generate KR dependent subkeys */ + CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 15); + subl(4) = krll; subr(4) = krlr; + subl(5) = krrl; subr(5) = krrr; + CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 15); + subl(8) = krll; subr(8) = krlr; + subl(9) = krrl; subr(9) = krrr; + CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30); + subl(18) = krll; subr(18) = krlr; + subl(19) = krrl; subr(19) = krrr; + CAMELLIA_ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 34); + subl(26) = krll; subr(26) = krlr; + subl(27) = krrl; subr(27) = krrr; + CAMELLIA_ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 34); + + /* generate KA */ + kll = subl(0) ^ krll; klr = subr(0) ^ krlr; + krl = subl(1) ^ krrl; krr = subr(1) ^ krrr; + CAMELLIA_F(kll, klr, + CAMELLIA_SIGMA1L, CAMELLIA_SIGMA1R, + w0, w1, il, ir, t0, t1); + krl ^= w0; krr ^= w1; + CAMELLIA_F(krl, krr, + CAMELLIA_SIGMA2L, CAMELLIA_SIGMA2R, + kll, klr, il, ir, t0, t1); + kll ^= krll; klr ^= krlr; + CAMELLIA_F(kll, klr, + CAMELLIA_SIGMA3L, CAMELLIA_SIGMA3R, + krl, krr, il, ir, t0, t1); + krl ^= w0 ^ krrl; krr ^= w1 ^ krrr; + CAMELLIA_F(krl, krr, + CAMELLIA_SIGMA4L, CAMELLIA_SIGMA4R, + w0, w1, il, ir, t0, t1); + kll ^= w0; klr ^= w1; + + /* generate KB */ + krll ^= kll; krlr ^= klr; + krrl ^= krl; krrr ^= krr; + CAMELLIA_F(krll, krlr, + CAMELLIA_SIGMA5L, CAMELLIA_SIGMA5R, + w0, w1, il, ir, t0, t1); + krrl ^= w0; krrr ^= w1; + CAMELLIA_F(krrl, krrr, + CAMELLIA_SIGMA6L, CAMELLIA_SIGMA6R, + w0, w1, il, ir, t0, t1); + krll ^= w0; krlr ^= w1; + + /* generate KA dependent subkeys */ + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 15); + subl(6) = kll; subr(6) = klr; + subl(7) = krl; subr(7) = krr; + CAMELLIA_ROLDQ(kll, klr, krl, krr, w0, w1, 30); + subl(14) = kll; subr(14) = klr; + subl(15) = krl; subr(15) = krr; + subl(24) = klr; subr(24) = krl; + subl(25) = krr; subr(25) = kll; + CAMELLIA_ROLDQo32(kll, klr, krl, krr, w0, w1, 49); + subl(28) = kll; subr(28) = klr; + subl(29) = krl; subr(29) = krr; + + /* generate KB dependent subkeys */ + subl(2) = krll; subr(2) = krlr; + subl(3) = krrl; subr(3) = krrr; + CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30); + subl(10) = krll; subr(10) = krlr; + subl(11) = krrl; subr(11) = krrr; + CAMELLIA_ROLDQ(krll, krlr, krrl, krrr, w0, w1, 30); + subl(20) = krll; subr(20) = krlr; + subl(21) = krrl; subr(21) = krrr; + CAMELLIA_ROLDQo32(krll, krlr, krrl, krrr, w0, w1, 51); + subl(32) = krll; subr(32) = krlr; + subl(33) = krrl; subr(33) = krrr; + + /* absorb kw2 to other subkeys */ + subl(3) ^= subl(1); subr(3) ^= subr(1); + subl(5) ^= subl(1); subr(5) ^= subr(1); + subl(7) ^= subl(1); subr(7) ^= subr(1); + subl(1) ^= subr(1) & ~subr(9); + dw = subl(1) & subl(9), subr(1) ^= CAMELLIA_RL1(dw); + subl(11) ^= subl(1); subr(11) ^= subr(1); + subl(13) ^= subl(1); subr(13) ^= subr(1); + subl(15) ^= subl(1); subr(15) ^= subr(1); + subl(1) ^= subr(1) & ~subr(17); + dw = subl(1) & subl(17), subr(1) ^= CAMELLIA_RL1(dw); + subl(19) ^= subl(1); subr(19) ^= subr(1); + subl(21) ^= subl(1); subr(21) ^= subr(1); + subl(23) ^= subl(1); subr(23) ^= subr(1); + subl(1) ^= subr(1) & ~subr(25); + dw = subl(1) & subl(25), subr(1) ^= CAMELLIA_RL1(dw); + subl(27) ^= subl(1); subr(27) ^= subr(1); + subl(29) ^= subl(1); subr(29) ^= subr(1); + subl(31) ^= subl(1); subr(31) ^= subr(1); + subl(32) ^= subl(1); subr(32) ^= subr(1); + + /* absorb kw4 to other subkeys */ + kw4l = subl(33); kw4r = subr(33); + subl(30) ^= kw4l; subr(30) ^= kw4r; + subl(28) ^= kw4l; subr(28) ^= kw4r; + subl(26) ^= kw4l; subr(26) ^= kw4r; + kw4l ^= kw4r & ~subr(24); + dw = kw4l & subl(24), kw4r ^= CAMELLIA_RL1(dw); + subl(22) ^= kw4l; subr(22) ^= kw4r; + subl(20) ^= kw4l; subr(20) ^= kw4r; + subl(18) ^= kw4l; subr(18) ^= kw4r; + kw4l ^= kw4r & ~subr(16); + dw = kw4l & subl(16), kw4r ^= CAMELLIA_RL1(dw); + subl(14) ^= kw4l; subr(14) ^= kw4r; + subl(12) ^= kw4l; subr(12) ^= kw4r; + subl(10) ^= kw4l; subr(10) ^= kw4r; + kw4l ^= kw4r & ~subr(8); + dw = kw4l & subl(8), kw4r ^= CAMELLIA_RL1(dw); + subl(6) ^= kw4l; subr(6) ^= kw4r; + subl(4) ^= kw4l; subr(4) ^= kw4r; + subl(2) ^= kw4l; subr(2) ^= kw4r; + subl(0) ^= kw4l; subr(0) ^= kw4r; + + /* key XOR is end of F-function */ + CamelliaSubkeyL(0) = subl(0) ^ subl(2); + CamelliaSubkeyR(0) = subr(0) ^ subr(2); + CamelliaSubkeyL(2) = subl(3); + CamelliaSubkeyR(2) = subr(3); + CamelliaSubkeyL(3) = subl(2) ^ subl(4); + CamelliaSubkeyR(3) = subr(2) ^ subr(4); + CamelliaSubkeyL(4) = subl(3) ^ subl(5); + CamelliaSubkeyR(4) = subr(3) ^ subr(5); + CamelliaSubkeyL(5) = subl(4) ^ subl(6); + CamelliaSubkeyR(5) = subr(4) ^ subr(6); + CamelliaSubkeyL(6) = subl(5) ^ subl(7); + CamelliaSubkeyR(6) = subr(5) ^ subr(7); + tl = subl(10) ^ (subr(10) & ~subr(8)); + dw = tl & subl(8), tr = subr(10) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(7) = subl(6) ^ tl; + CamelliaSubkeyR(7) = subr(6) ^ tr; + CamelliaSubkeyL(8) = subl(8); + CamelliaSubkeyR(8) = subr(8); + CamelliaSubkeyL(9) = subl(9); + CamelliaSubkeyR(9) = subr(9); + tl = subl(7) ^ (subr(7) & ~subr(9)); + dw = tl & subl(9), tr = subr(7) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(10) = tl ^ subl(11); + CamelliaSubkeyR(10) = tr ^ subr(11); + CamelliaSubkeyL(11) = subl(10) ^ subl(12); + CamelliaSubkeyR(11) = subr(10) ^ subr(12); + CamelliaSubkeyL(12) = subl(11) ^ subl(13); + CamelliaSubkeyR(12) = subr(11) ^ subr(13); + CamelliaSubkeyL(13) = subl(12) ^ subl(14); + CamelliaSubkeyR(13) = subr(12) ^ subr(14); + CamelliaSubkeyL(14) = subl(13) ^ subl(15); + CamelliaSubkeyR(14) = subr(13) ^ subr(15); + tl = subl(18) ^ (subr(18) & ~subr(16)); + dw = tl & subl(16), tr = subr(18) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(15) = subl(14) ^ tl; + CamelliaSubkeyR(15) = subr(14) ^ tr; + CamelliaSubkeyL(16) = subl(16); + CamelliaSubkeyR(16) = subr(16); + CamelliaSubkeyL(17) = subl(17); + CamelliaSubkeyR(17) = subr(17); + tl = subl(15) ^ (subr(15) & ~subr(17)); + dw = tl & subl(17), tr = subr(15) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(18) = tl ^ subl(19); + CamelliaSubkeyR(18) = tr ^ subr(19); + CamelliaSubkeyL(19) = subl(18) ^ subl(20); + CamelliaSubkeyR(19) = subr(18) ^ subr(20); + CamelliaSubkeyL(20) = subl(19) ^ subl(21); + CamelliaSubkeyR(20) = subr(19) ^ subr(21); + CamelliaSubkeyL(21) = subl(20) ^ subl(22); + CamelliaSubkeyR(21) = subr(20) ^ subr(22); + CamelliaSubkeyL(22) = subl(21) ^ subl(23); + CamelliaSubkeyR(22) = subr(21) ^ subr(23); + tl = subl(26) ^ (subr(26) & ~subr(24)); + dw = tl & subl(24), tr = subr(26) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(23) = subl(22) ^ tl; + CamelliaSubkeyR(23) = subr(22) ^ tr; + CamelliaSubkeyL(24) = subl(24); + CamelliaSubkeyR(24) = subr(24); + CamelliaSubkeyL(25) = subl(25); + CamelliaSubkeyR(25) = subr(25); + tl = subl(23) ^ (subr(23) & ~subr(25)); + dw = tl & subl(25), tr = subr(23) ^ CAMELLIA_RL1(dw); + CamelliaSubkeyL(26) = tl ^ subl(27); + CamelliaSubkeyR(26) = tr ^ subr(27); + CamelliaSubkeyL(27) = subl(26) ^ subl(28); + CamelliaSubkeyR(27) = subr(26) ^ subr(28); + CamelliaSubkeyL(28) = subl(27) ^ subl(29); + CamelliaSubkeyR(28) = subr(27) ^ subr(29); + CamelliaSubkeyL(29) = subl(28) ^ subl(30); + CamelliaSubkeyR(29) = subr(28) ^ subr(30); + CamelliaSubkeyL(30) = subl(29) ^ subl(31); + CamelliaSubkeyR(30) = subr(29) ^ subr(31); + CamelliaSubkeyL(31) = subl(30); + CamelliaSubkeyR(31) = subr(30); + CamelliaSubkeyL(32) = subl(32) ^ subl(31); + CamelliaSubkeyR(32) = subr(32) ^ subr(31); + + /* apply the inverse of the last half of P-function */ + dw = CamelliaSubkeyL(2) ^ CamelliaSubkeyR(2), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(2) = CamelliaSubkeyL(2) ^ dw, CamelliaSubkeyL(2) = dw; + dw = CamelliaSubkeyL(3) ^ CamelliaSubkeyR(3), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(3) = CamelliaSubkeyL(3) ^ dw, CamelliaSubkeyL(3) = dw; + dw = CamelliaSubkeyL(4) ^ CamelliaSubkeyR(4), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(4) = CamelliaSubkeyL(4) ^ dw, CamelliaSubkeyL(4) = dw; + dw = CamelliaSubkeyL(5) ^ CamelliaSubkeyR(5), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(5) = CamelliaSubkeyL(5) ^ dw, CamelliaSubkeyL(5) = dw; + dw = CamelliaSubkeyL(6) ^ CamelliaSubkeyR(6), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(6) = CamelliaSubkeyL(6) ^ dw, CamelliaSubkeyL(6) = dw; + dw = CamelliaSubkeyL(7) ^ CamelliaSubkeyR(7), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(7) = CamelliaSubkeyL(7) ^ dw, CamelliaSubkeyL(7) = dw; + dw = CamelliaSubkeyL(10) ^ CamelliaSubkeyR(10), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(10) = CamelliaSubkeyL(10) ^ dw, CamelliaSubkeyL(10) = dw; + dw = CamelliaSubkeyL(11) ^ CamelliaSubkeyR(11), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(11) = CamelliaSubkeyL(11) ^ dw, CamelliaSubkeyL(11) = dw; + dw = CamelliaSubkeyL(12) ^ CamelliaSubkeyR(12), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(12) = CamelliaSubkeyL(12) ^ dw, CamelliaSubkeyL(12) = dw; + dw = CamelliaSubkeyL(13) ^ CamelliaSubkeyR(13), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(13) = CamelliaSubkeyL(13) ^ dw, CamelliaSubkeyL(13) = dw; + dw = CamelliaSubkeyL(14) ^ CamelliaSubkeyR(14), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(14) = CamelliaSubkeyL(14) ^ dw, CamelliaSubkeyL(14) = dw; + dw = CamelliaSubkeyL(15) ^ CamelliaSubkeyR(15), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(15) = CamelliaSubkeyL(15) ^ dw, CamelliaSubkeyL(15) = dw; + dw = CamelliaSubkeyL(18) ^ CamelliaSubkeyR(18), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(18) = CamelliaSubkeyL(18) ^ dw, CamelliaSubkeyL(18) = dw; + dw = CamelliaSubkeyL(19) ^ CamelliaSubkeyR(19), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(19) = CamelliaSubkeyL(19) ^ dw, CamelliaSubkeyL(19) = dw; + dw = CamelliaSubkeyL(20) ^ CamelliaSubkeyR(20), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(20) = CamelliaSubkeyL(20) ^ dw, CamelliaSubkeyL(20) = dw; + dw = CamelliaSubkeyL(21) ^ CamelliaSubkeyR(21), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(21) = CamelliaSubkeyL(21) ^ dw, CamelliaSubkeyL(21) = dw; + dw = CamelliaSubkeyL(22) ^ CamelliaSubkeyR(22), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(22) = CamelliaSubkeyL(22) ^ dw, CamelliaSubkeyL(22) = dw; + dw = CamelliaSubkeyL(23) ^ CamelliaSubkeyR(23), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(23) = CamelliaSubkeyL(23) ^ dw, CamelliaSubkeyL(23) = dw; + dw = CamelliaSubkeyL(26) ^ CamelliaSubkeyR(26), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(26) = CamelliaSubkeyL(26) ^ dw, CamelliaSubkeyL(26) = dw; + dw = CamelliaSubkeyL(27) ^ CamelliaSubkeyR(27), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(27) = CamelliaSubkeyL(27) ^ dw, CamelliaSubkeyL(27) = dw; + dw = CamelliaSubkeyL(28) ^ CamelliaSubkeyR(28), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(28) = CamelliaSubkeyL(28) ^ dw, CamelliaSubkeyL(28) = dw; + dw = CamelliaSubkeyL(29) ^ CamelliaSubkeyR(29), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(29) = CamelliaSubkeyL(29) ^ dw, CamelliaSubkeyL(29) = dw; + dw = CamelliaSubkeyL(30) ^ CamelliaSubkeyR(30), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(30) = CamelliaSubkeyL(30) ^ dw, CamelliaSubkeyL(30) = dw; + dw = CamelliaSubkeyL(31) ^ CamelliaSubkeyR(31), dw = CAMELLIA_RL8(dw); + CamelliaSubkeyR(31) = CamelliaSubkeyL(31) ^ dw,CamelliaSubkeyL(31) = dw; + +#ifdef WOLFSSL_SMALL_STACK + XFREE(subL, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(subR, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return 0; +} + +static int camellia_setup192(const unsigned char *key, u32 *subkey) +{ + unsigned char kk[32]; + u32 krll, krlr, krrl,krrr; + + XMEMCPY(kk, key, 24); + XMEMCPY((unsigned char *)&krll, key+16,4); + XMEMCPY((unsigned char *)&krlr, key+20,4); + krrl = ~krll; + krrr = ~krlr; + XMEMCPY(kk+24, (unsigned char *)&krrl, 4); + XMEMCPY(kk+28, (unsigned char *)&krrr, 4); + + return camellia_setup256(kk, subkey); +} + + +/** + * Stuff related to camellia encryption/decryption + * + * "io" must be 4byte aligned and big-endian data. + */ +static void camellia_encrypt128(const u32 *subkey, u32 *io) +{ + u32 il, ir, t0, t1; + + /* pre whitening but absorb kw2*/ + io[0] ^= CamelliaSubkeyL(0); + io[1] ^= CamelliaSubkeyR(0); + /* main iteration */ + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(2),CamelliaSubkeyR(2), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(3),CamelliaSubkeyR(3), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(4),CamelliaSubkeyR(4), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(5),CamelliaSubkeyR(5), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(6),CamelliaSubkeyR(6), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(7),CamelliaSubkeyR(7), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(8),CamelliaSubkeyR(8), + CamelliaSubkeyL(9),CamelliaSubkeyR(9), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(10),CamelliaSubkeyR(10), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(11),CamelliaSubkeyR(11), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(12),CamelliaSubkeyR(12), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(13),CamelliaSubkeyR(13), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(14),CamelliaSubkeyR(14), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(15),CamelliaSubkeyR(15), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(16),CamelliaSubkeyR(16), + CamelliaSubkeyL(17),CamelliaSubkeyR(17), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(18),CamelliaSubkeyR(18), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(19),CamelliaSubkeyR(19), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(20),CamelliaSubkeyR(20), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(21),CamelliaSubkeyR(21), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(22),CamelliaSubkeyR(22), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(23),CamelliaSubkeyR(23), + io[0],io[1],il,ir,t0,t1); + + /* post whitening but kw4 */ + io[2] ^= CamelliaSubkeyL(24); + io[3] ^= CamelliaSubkeyR(24); + + t0 = io[0]; + t1 = io[1]; + io[0] = io[2]; + io[1] = io[3]; + io[2] = t0; + io[3] = t1; + + return; +} + +static void camellia_decrypt128(const u32 *subkey, u32 *io) +{ + u32 il,ir,t0,t1; /* temporary variables */ + + /* pre whitening but absorb kw2*/ + io[0] ^= CamelliaSubkeyL(24); + io[1] ^= CamelliaSubkeyR(24); + + /* main iteration */ + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(23),CamelliaSubkeyR(23), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(22),CamelliaSubkeyR(22), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(21),CamelliaSubkeyR(21), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(20),CamelliaSubkeyR(20), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(19),CamelliaSubkeyR(19), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(18),CamelliaSubkeyR(18), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(17),CamelliaSubkeyR(17), + CamelliaSubkeyL(16),CamelliaSubkeyR(16), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(15),CamelliaSubkeyR(15), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(14),CamelliaSubkeyR(14), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(13),CamelliaSubkeyR(13), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(12),CamelliaSubkeyR(12), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(11),CamelliaSubkeyR(11), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(10),CamelliaSubkeyR(10), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(9),CamelliaSubkeyR(9), + CamelliaSubkeyL(8),CamelliaSubkeyR(8), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(7),CamelliaSubkeyR(7), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(6),CamelliaSubkeyR(6), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(5),CamelliaSubkeyR(5), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(4),CamelliaSubkeyR(4), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(3),CamelliaSubkeyR(3), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(2),CamelliaSubkeyR(2), + io[0],io[1],il,ir,t0,t1); + + /* post whitening but kw4 */ + io[2] ^= CamelliaSubkeyL(0); + io[3] ^= CamelliaSubkeyR(0); + + t0 = io[0]; + t1 = io[1]; + io[0] = io[2]; + io[1] = io[3]; + io[2] = t0; + io[3] = t1; + + return; +} + +/** + * stuff for 192 and 256bit encryption/decryption + */ +static void camellia_encrypt256(const u32 *subkey, u32 *io) +{ + u32 il,ir,t0,t1; /* temporary variables */ + + /* pre whitening but absorb kw2*/ + io[0] ^= CamelliaSubkeyL(0); + io[1] ^= CamelliaSubkeyR(0); + + /* main iteration */ + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(2),CamelliaSubkeyR(2), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(3),CamelliaSubkeyR(3), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(4),CamelliaSubkeyR(4), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(5),CamelliaSubkeyR(5), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(6),CamelliaSubkeyR(6), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(7),CamelliaSubkeyR(7), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(8),CamelliaSubkeyR(8), + CamelliaSubkeyL(9),CamelliaSubkeyR(9), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(10),CamelliaSubkeyR(10), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(11),CamelliaSubkeyR(11), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(12),CamelliaSubkeyR(12), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(13),CamelliaSubkeyR(13), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(14),CamelliaSubkeyR(14), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(15),CamelliaSubkeyR(15), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(16),CamelliaSubkeyR(16), + CamelliaSubkeyL(17),CamelliaSubkeyR(17), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(18),CamelliaSubkeyR(18), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(19),CamelliaSubkeyR(19), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(20),CamelliaSubkeyR(20), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(21),CamelliaSubkeyR(21), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(22),CamelliaSubkeyR(22), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(23),CamelliaSubkeyR(23), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(24),CamelliaSubkeyR(24), + CamelliaSubkeyL(25),CamelliaSubkeyR(25), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(26),CamelliaSubkeyR(26), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(27),CamelliaSubkeyR(27), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(28),CamelliaSubkeyR(28), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(29),CamelliaSubkeyR(29), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(30),CamelliaSubkeyR(30), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(31),CamelliaSubkeyR(31), + io[0],io[1],il,ir,t0,t1); + + /* post whitening but kw4 */ + io[2] ^= CamelliaSubkeyL(32); + io[3] ^= CamelliaSubkeyR(32); + + t0 = io[0]; + t1 = io[1]; + io[0] = io[2]; + io[1] = io[3]; + io[2] = t0; + io[3] = t1; + + return; +} + +static void camellia_decrypt256(const u32 *subkey, u32 *io) +{ + u32 il,ir,t0,t1; /* temporary variables */ + + /* pre whitening but absorb kw2*/ + io[0] ^= CamelliaSubkeyL(32); + io[1] ^= CamelliaSubkeyR(32); + + /* main iteration */ + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(31),CamelliaSubkeyR(31), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(30),CamelliaSubkeyR(30), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(29),CamelliaSubkeyR(29), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(28),CamelliaSubkeyR(28), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(27),CamelliaSubkeyR(27), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(26),CamelliaSubkeyR(26), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(25),CamelliaSubkeyR(25), + CamelliaSubkeyL(24),CamelliaSubkeyR(24), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(23),CamelliaSubkeyR(23), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(22),CamelliaSubkeyR(22), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(21),CamelliaSubkeyR(21), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(20),CamelliaSubkeyR(20), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(19),CamelliaSubkeyR(19), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(18),CamelliaSubkeyR(18), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(17),CamelliaSubkeyR(17), + CamelliaSubkeyL(16),CamelliaSubkeyR(16), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(15),CamelliaSubkeyR(15), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(14),CamelliaSubkeyR(14), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(13),CamelliaSubkeyR(13), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(12),CamelliaSubkeyR(12), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(11),CamelliaSubkeyR(11), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(10),CamelliaSubkeyR(10), + io[0],io[1],il,ir,t0,t1); + + CAMELLIA_FLS(io[0],io[1],io[2],io[3], + CamelliaSubkeyL(9),CamelliaSubkeyR(9), + CamelliaSubkeyL(8),CamelliaSubkeyR(8), + t0,t1,il,ir); + + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(7),CamelliaSubkeyR(7), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(6),CamelliaSubkeyR(6), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(5),CamelliaSubkeyR(5), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(4),CamelliaSubkeyR(4), + io[0],io[1],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[0],io[1], + CamelliaSubkeyL(3),CamelliaSubkeyR(3), + io[2],io[3],il,ir,t0,t1); + CAMELLIA_ROUNDSM(io[2],io[3], + CamelliaSubkeyL(2),CamelliaSubkeyR(2), + io[0],io[1],il,ir,t0,t1); + + /* post whitening but kw4 */ + io[2] ^= CamelliaSubkeyL(0); + io[3] ^= CamelliaSubkeyR(0); + + t0 = io[0]; + t1 = io[1]; + io[0] = io[2]; + io[1] = io[3]; + io[2] = t0; + io[3] = t1; + + return; +} + +/*** + * + * API for compatibility + */ + +static void Camellia_EncryptBlock(const int keyBitLength, + const unsigned char *plaintext, + const KEY_TABLE_TYPE keyTable, + unsigned char *ciphertext) +{ + u32 tmp[4]; + + tmp[0] = GETU32(plaintext); + tmp[1] = GETU32(plaintext + 4); + tmp[2] = GETU32(plaintext + 8); + tmp[3] = GETU32(plaintext + 12); + + switch (keyBitLength) { + case 128: + camellia_encrypt128(keyTable, tmp); + break; + case 192: + /* fall through */ + case 256: + camellia_encrypt256(keyTable, tmp); + break; + default: + break; + } + + PUTU32(ciphertext, tmp[0]); + PUTU32(ciphertext + 4, tmp[1]); + PUTU32(ciphertext + 8, tmp[2]); + PUTU32(ciphertext + 12, tmp[3]); +} + +static void Camellia_DecryptBlock(const int keyBitLength, + const unsigned char *ciphertext, + const KEY_TABLE_TYPE keyTable, + unsigned char *plaintext) +{ + u32 tmp[4]; + + tmp[0] = GETU32(ciphertext); + tmp[1] = GETU32(ciphertext + 4); + tmp[2] = GETU32(ciphertext + 8); + tmp[3] = GETU32(ciphertext + 12); + + switch (keyBitLength) { + case 128: + camellia_decrypt128(keyTable, tmp); + break; + case 192: + /* fall through */ + case 256: + camellia_decrypt256(keyTable, tmp); + break; + default: + break; + } + PUTU32(plaintext, tmp[0]); + PUTU32(plaintext + 4, tmp[1]); + PUTU32(plaintext + 8, tmp[2]); + PUTU32(plaintext + 12, tmp[3]); +} + + + +/* wolfCrypt wrappers to the Camellia code */ + +int wc_CamelliaSetKey(Camellia* cam, const byte* key, word32 len, const byte* iv) +{ + int ret = 0; + + if (cam == NULL) return BAD_FUNC_ARG; + + XMEMSET(cam->key, 0, sizeof(KEY_TABLE_TYPE)); + + switch (len) { + case 16: + ret = camellia_setup128(key, cam->key); + break; + case 24: + ret = camellia_setup192(key, cam->key); + break; + case 32: + ret = camellia_setup256(key, cam->key); + break; + default: + return BAD_FUNC_ARG; + } + + if (ret != 0) + return ret; + + cam->keySz = len * 8; + + return wc_CamelliaSetIV(cam, iv); +} + + +int wc_CamelliaSetIV(Camellia* cam, const byte* iv) +{ + if (cam == NULL) + return BAD_FUNC_ARG; + + if (iv) + XMEMCPY(cam->reg, iv, CAMELLIA_BLOCK_SIZE); + else + XMEMSET(cam->reg, 0, CAMELLIA_BLOCK_SIZE); + + return 0; +} + + +int wc_CamelliaEncryptDirect(Camellia* cam, byte* out, const byte* in) +{ + if (cam == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + Camellia_EncryptBlock(cam->keySz, in, cam->key, out); + + return 0; +} + + +int wc_CamelliaDecryptDirect(Camellia* cam, byte* out, const byte* in) +{ + if (cam == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + Camellia_DecryptBlock(cam->keySz, in, cam->key, out); + + return 0; +} + + +int wc_CamelliaCbcEncrypt(Camellia* cam, byte* out, const byte* in, word32 sz) +{ + word32 blocks; + if (cam == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + blocks = sz / CAMELLIA_BLOCK_SIZE; + + while (blocks--) { + xorbuf((byte*)cam->reg, in, CAMELLIA_BLOCK_SIZE); + Camellia_EncryptBlock(cam->keySz, (byte*)cam->reg, + cam->key, (byte*)cam->reg); + XMEMCPY(out, cam->reg, CAMELLIA_BLOCK_SIZE); + + out += CAMELLIA_BLOCK_SIZE; + in += CAMELLIA_BLOCK_SIZE; + } + + return 0; +} + + +int wc_CamelliaCbcDecrypt(Camellia* cam, byte* out, const byte* in, word32 sz) +{ + word32 blocks; + if (cam == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + blocks = sz / CAMELLIA_BLOCK_SIZE; + + while (blocks--) { + XMEMCPY(cam->tmp, in, CAMELLIA_BLOCK_SIZE); + Camellia_DecryptBlock(cam->keySz, (byte*)cam->tmp, cam->key, out); + xorbuf(out, (byte*)cam->reg, CAMELLIA_BLOCK_SIZE); + XMEMCPY(cam->reg, cam->tmp, CAMELLIA_BLOCK_SIZE); + + out += CAMELLIA_BLOCK_SIZE; + in += CAMELLIA_BLOCK_SIZE; + } + + return 0; +} + + +#endif /* HAVE_CAMELLIA */ + diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/chacha.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/chacha.c new file mode 100755 index 0000000..71b8108 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/chacha.c @@ -0,0 +1,323 @@ +/* chacha.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/* + * based from + * chacha-ref.c version 20080118 + * D. J. Bernstein + * Public domain. + */ + + +#ifdef WOLFSSL_ARMASM + /* implementation is located in wolfcrypt/src/port/arm/armv8-chacha.c */ + +#else +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifdef HAVE_CHACHA + +#include +#include +#include +#include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#ifdef CHACHA_AEAD_TEST + #include +#endif + +#ifdef USE_INTEL_CHACHA_SPEEDUP + #include + #include + + #if defined(__GNUC__) && ((__GNUC__ < 4) || \ + (__GNUC__ == 4 && __GNUC_MINOR__ <= 8)) + #undef NO_AVX2_SUPPORT + #define NO_AVX2_SUPPORT + #endif + #if defined(__clang__) && ((__clang_major__ < 3) || \ + (__clang_major__ == 3 && __clang_minor__ <= 5)) + #undef NO_AVX2_SUPPORT + #define NO_AVX2_SUPPORT + #elif defined(__clang__) && defined(NO_AVX2_SUPPORT) + #undef NO_AVX2_SUPPORT + #endif + + #ifndef NO_AVX2_SUPPORT + #define HAVE_INTEL_AVX2 + #endif + + static int cpuidFlagsSet = 0; + static int cpuidFlags = 0; +#endif + +#ifdef BIG_ENDIAN_ORDER + #define LITTLE32(x) ByteReverseWord32(x) +#else + #define LITTLE32(x) (x) +#endif + +/* Number of rounds */ +#define ROUNDS 20 + +#define U32C(v) (v##U) +#define U32V(v) ((word32)(v) & U32C(0xFFFFFFFF)) +#define U8TO32_LITTLE(p) LITTLE32(((word32*)(p))[0]) + +#define ROTATE(v,c) rotlFixed(v, c) +#define XOR(v,w) ((v) ^ (w)) +#define PLUS(v,w) (U32V((v) + (w))) +#define PLUSONE(v) (PLUS((v),1)) + +#define QUARTERROUND(a,b,c,d) \ + x[a] = PLUS(x[a],x[b]); x[d] = ROTATE(XOR(x[d],x[a]),16); \ + x[c] = PLUS(x[c],x[d]); x[b] = ROTATE(XOR(x[b],x[c]),12); \ + x[a] = PLUS(x[a],x[b]); x[d] = ROTATE(XOR(x[d],x[a]), 8); \ + x[c] = PLUS(x[c],x[d]); x[b] = ROTATE(XOR(x[b],x[c]), 7); + + +/** + * Set up iv(nonce). Earlier versions used 64 bits instead of 96, this version + * uses the typical AEAD 96 bit nonce and can do record sizes of 256 GB. + */ +int wc_Chacha_SetIV(ChaCha* ctx, const byte* inIv, word32 counter) +{ + word32 temp[CHACHA_IV_WORDS];/* used for alignment of memory */ + +#ifdef CHACHA_AEAD_TEST + word32 i; + printf("NONCE : "); + for (i = 0; i < CHACHA_IV_BYTES; i++) { + printf("%02x", inIv[i]); + } + printf("\n\n"); +#endif + + if (ctx == NULL) + return BAD_FUNC_ARG; + + XMEMCPY(temp, inIv, CHACHA_IV_BYTES); + + ctx->X[CHACHA_IV_BYTES+0] = counter; /* block counter */ + ctx->X[CHACHA_IV_BYTES+1] = LITTLE32(temp[0]); /* fixed variable from nonce */ + ctx->X[CHACHA_IV_BYTES+2] = LITTLE32(temp[1]); /* counter from nonce */ + ctx->X[CHACHA_IV_BYTES+3] = LITTLE32(temp[2]); /* counter from nonce */ + + return 0; +} + +/* "expand 32-byte k" as unsigned 32 byte */ +static const word32 sigma[4] = {0x61707865, 0x3320646e, 0x79622d32, 0x6b206574}; +/* "expand 16-byte k" as unsigned 16 byte */ +static const word32 tau[4] = {0x61707865, 0x3120646e, 0x79622d36, 0x6b206574}; + +/** + * Key setup. 8 word iv (nonce) + */ +int wc_Chacha_SetKey(ChaCha* ctx, const byte* key, word32 keySz) +{ + const word32* constants; + const byte* k; + +#ifdef XSTREAM_ALIGN + word32 alignKey[8]; +#endif + + if (ctx == NULL) + return BAD_FUNC_ARG; + + if (keySz != (CHACHA_MAX_KEY_SZ/2) && keySz != CHACHA_MAX_KEY_SZ) + return BAD_FUNC_ARG; + +#ifdef XSTREAM_ALIGN + if ((wolfssl_word)key % 4) { + WOLFSSL_MSG("wc_ChachaSetKey unaligned key"); + XMEMCPY(alignKey, key, keySz); + k = (byte*)alignKey; + } + else { + k = key; + } +#else + k = key; +#endif /* XSTREAM_ALIGN */ + +#ifdef CHACHA_AEAD_TEST + word32 i; + printf("ChaCha key used :\n"); + for (i = 0; i < keySz; i++) { + printf("%02x", key[i]); + if ((i + 1) % 8 == 0) + printf("\n"); + } + printf("\n\n"); +#endif + + ctx->X[4] = U8TO32_LITTLE(k + 0); + ctx->X[5] = U8TO32_LITTLE(k + 4); + ctx->X[6] = U8TO32_LITTLE(k + 8); + ctx->X[7] = U8TO32_LITTLE(k + 12); + if (keySz == CHACHA_MAX_KEY_SZ) { + k += 16; + constants = sigma; + } + else { + constants = tau; + } + ctx->X[ 8] = U8TO32_LITTLE(k + 0); + ctx->X[ 9] = U8TO32_LITTLE(k + 4); + ctx->X[10] = U8TO32_LITTLE(k + 8); + ctx->X[11] = U8TO32_LITTLE(k + 12); + ctx->X[ 0] = constants[0]; + ctx->X[ 1] = constants[1]; + ctx->X[ 2] = constants[2]; + ctx->X[ 3] = constants[3]; + + return 0; +} + +/** + * Converts word into bytes with rotations having been done. + */ +static WC_INLINE void wc_Chacha_wordtobyte(word32 output[CHACHA_CHUNK_WORDS], + const word32 input[CHACHA_CHUNK_WORDS]) +{ + word32 x[CHACHA_CHUNK_WORDS]; + word32 i; + + for (i = 0; i < CHACHA_CHUNK_WORDS; i++) { + x[i] = input[i]; + } + + for (i = (ROUNDS); i > 0; i -= 2) { + QUARTERROUND(0, 4, 8, 12) + QUARTERROUND(1, 5, 9, 13) + QUARTERROUND(2, 6, 10, 14) + QUARTERROUND(3, 7, 11, 15) + QUARTERROUND(0, 5, 10, 15) + QUARTERROUND(1, 6, 11, 12) + QUARTERROUND(2, 7, 8, 13) + QUARTERROUND(3, 4, 9, 14) + } + + for (i = 0; i < CHACHA_CHUNK_WORDS; i++) { + x[i] = PLUS(x[i], input[i]); + } + + for (i = 0; i < CHACHA_CHUNK_WORDS; i++) { + output[i] = LITTLE32(x[i]); + } +} + +#ifdef __cplusplus + extern "C" { +#endif + +extern void chacha_encrypt_x64(ChaCha* ctx, const byte* m, byte* c, + word32 bytes); +extern void chacha_encrypt_avx1(ChaCha* ctx, const byte* m, byte* c, + word32 bytes); +extern void chacha_encrypt_avx2(ChaCha* ctx, const byte* m, byte* c, + word32 bytes); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + + +/** + * Encrypt a stream of bytes + */ +static void wc_Chacha_encrypt_bytes(ChaCha* ctx, const byte* m, byte* c, + word32 bytes) +{ + byte* output; + word32 temp[CHACHA_CHUNK_WORDS]; /* used to make sure aligned */ + word32 i; + + output = (byte*)temp; + + for (; bytes > 0;) { + wc_Chacha_wordtobyte(temp, ctx->X); + ctx->X[CHACHA_IV_BYTES] = PLUSONE(ctx->X[CHACHA_IV_BYTES]); + if (bytes <= CHACHA_CHUNK_BYTES) { + for (i = 0; i < bytes; ++i) { + c[i] = m[i] ^ output[i]; + } + return; + } + for (i = 0; i < CHACHA_CHUNK_BYTES; ++i) { + c[i] = m[i] ^ output[i]; + } + bytes -= CHACHA_CHUNK_BYTES; + c += CHACHA_CHUNK_BYTES; + m += CHACHA_CHUNK_BYTES; + } +} + +/** + * API to encrypt/decrypt a message of any size. + */ +int wc_Chacha_Process(ChaCha* ctx, byte* output, const byte* input, + word32 msglen) +{ + if (ctx == NULL) + return BAD_FUNC_ARG; + +#ifdef USE_INTEL_CHACHA_SPEEDUP + if (!cpuidFlagsSet) { + cpuidFlags = cpuid_get_flags(); + cpuidFlagsSet = 1; + } + + #ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_AVX2(cpuidFlags)) { + chacha_encrypt_avx2(ctx, input, output, msglen); + return 0; + } + #endif + if (IS_INTEL_AVX1(cpuidFlags)) { + chacha_encrypt_avx1(ctx, input, output, msglen); + return 0; + } + else { + chacha_encrypt_x64(ctx, input, output, msglen); + return 0; + } +#endif + wc_Chacha_encrypt_bytes(ctx, input, output, msglen); + + return 0; +} + +#endif /* HAVE_CHACHA*/ + +#endif /* WOLFSSL_ARMASM */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/chacha20_poly1305.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/chacha20_poly1305.c new file mode 100755 index 0000000..a30fbf9 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/chacha20_poly1305.c @@ -0,0 +1,251 @@ +/* chacha.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) + +#include +#include +#include +#include +#include + +#ifdef NO_INLINE +#include +#else +#define WOLFSSL_MISC_INCLUDED +#include +#endif + +#ifdef CHACHA_AEAD_TEST +#include +#endif + +#define CHACHA20_POLY1305_AEAD_INITIAL_COUNTER 0 +#define CHACHA20_POLY1305_MAC_PADDING_ALIGNMENT 16 + +static void word32ToLittle64(const word32 inLittle32, byte outLittle64[8]); +static int calculateAuthTag( + const byte inAuthKey[CHACHA20_POLY1305_AEAD_KEYSIZE], + const byte* inAAD, const word32 inAADLen, + const byte *inCiphertext, const word32 inCiphertextLen, + byte outAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE]); + +int wc_ChaCha20Poly1305_Encrypt( + const byte inKey[CHACHA20_POLY1305_AEAD_KEYSIZE], + const byte inIV[CHACHA20_POLY1305_AEAD_IV_SIZE], + const byte* inAAD, const word32 inAADLen, + const byte* inPlaintext, const word32 inPlaintextLen, + byte* outCiphertext, + byte outAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE]) +{ + int err; + byte poly1305Key[CHACHA20_POLY1305_AEAD_KEYSIZE]; + ChaCha chaChaCtx; + + /* Validate function arguments */ + + if (!inKey || !inIV || + !inPlaintext || !inPlaintextLen || + !outCiphertext || + !outAuthTag) + { + return BAD_FUNC_ARG; + } + + XMEMSET(poly1305Key, 0, sizeof(poly1305Key)); + + /* Create the Poly1305 key */ + err = wc_Chacha_SetKey(&chaChaCtx, inKey, CHACHA20_POLY1305_AEAD_KEYSIZE); + if (err != 0) return err; + + err = wc_Chacha_SetIV(&chaChaCtx, inIV, + CHACHA20_POLY1305_AEAD_INITIAL_COUNTER); + if (err != 0) return err; + + err = wc_Chacha_Process(&chaChaCtx, poly1305Key, poly1305Key, + CHACHA20_POLY1305_AEAD_KEYSIZE); + if (err != 0) return err; + + /* Encrypt the plaintext using ChaCha20 */ + err = wc_Chacha_Process(&chaChaCtx, outCiphertext, inPlaintext, + inPlaintextLen); + /* Calculate the Poly1305 auth tag */ + if (err == 0) + err = calculateAuthTag(poly1305Key, + inAAD, inAADLen, + outCiphertext, inPlaintextLen, + outAuthTag); + ForceZero(poly1305Key, sizeof(poly1305Key)); + + return err; +} + + +int wc_ChaCha20Poly1305_Decrypt( + const byte inKey[CHACHA20_POLY1305_AEAD_KEYSIZE], + const byte inIV[CHACHA20_POLY1305_AEAD_IV_SIZE], + const byte* inAAD, const word32 inAADLen, + const byte* inCiphertext, const word32 inCiphertextLen, + const byte inAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE], + byte* outPlaintext) +{ + int err; + byte poly1305Key[CHACHA20_POLY1305_AEAD_KEYSIZE]; + ChaCha chaChaCtx; + byte calculatedAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE]; + + /* Validate function arguments */ + + if (!inKey || !inIV || + !inCiphertext || !inCiphertextLen || + !inAuthTag || + !outPlaintext) + { + return BAD_FUNC_ARG; + } + + XMEMSET(calculatedAuthTag, 0, sizeof(calculatedAuthTag)); + XMEMSET(poly1305Key, 0, sizeof(poly1305Key)); + + /* Create the Poly1305 key */ + err = wc_Chacha_SetKey(&chaChaCtx, inKey, CHACHA20_POLY1305_AEAD_KEYSIZE); + if (err != 0) return err; + + err = wc_Chacha_SetIV(&chaChaCtx, inIV, + CHACHA20_POLY1305_AEAD_INITIAL_COUNTER); + if (err != 0) return err; + + err = wc_Chacha_Process(&chaChaCtx, poly1305Key, poly1305Key, + CHACHA20_POLY1305_AEAD_KEYSIZE); + if (err != 0) return err; + + /* Calculate the Poly1305 auth tag */ + err = calculateAuthTag(poly1305Key, + inAAD, inAADLen, + inCiphertext, inCiphertextLen, + calculatedAuthTag); + + /* Compare the calculated auth tag with the received one */ + if (err == 0 && ConstantCompare(inAuthTag, calculatedAuthTag, + CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE) != 0) + { + err = MAC_CMP_FAILED_E; + } + + /* Decrypt the received ciphertext */ + if (err == 0) + err = wc_Chacha_Process(&chaChaCtx, outPlaintext, inCiphertext, + inCiphertextLen); + ForceZero(poly1305Key, sizeof(poly1305Key)); + + return err; +} + + +static int calculateAuthTag( + const byte inAuthKey[CHACHA20_POLY1305_AEAD_KEYSIZE], + const byte *inAAD, const word32 inAADLen, + const byte *inCiphertext, const word32 inCiphertextLen, + byte outAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE]) +{ + int err; + Poly1305 poly1305Ctx; + byte padding[CHACHA20_POLY1305_MAC_PADDING_ALIGNMENT - 1]; + word32 paddingLen; + byte little64[16]; + + XMEMSET(padding, 0, sizeof(padding)); + + /* Initialize Poly1305 */ + err = wc_Poly1305SetKey(&poly1305Ctx, inAuthKey, + CHACHA20_POLY1305_AEAD_KEYSIZE); + if (err) + return err; + + /* Create the authTag by MAC'ing the following items: */ + /* -- AAD */ + if (inAAD && inAADLen) + { + err = wc_Poly1305Update(&poly1305Ctx, inAAD, inAADLen); + /* -- padding1: pad the AAD to 16 bytes */ + paddingLen = -(int)inAADLen & + (CHACHA20_POLY1305_MAC_PADDING_ALIGNMENT - 1); + if (paddingLen) + err += wc_Poly1305Update(&poly1305Ctx, padding, paddingLen); + + if (err) + return err; + } + + /* -- Ciphertext */ + err = wc_Poly1305Update(&poly1305Ctx, inCiphertext, inCiphertextLen); + if (err) + return err; + + /* -- padding2: pad the ciphertext to 16 bytes */ + paddingLen = -(int)inCiphertextLen & + (CHACHA20_POLY1305_MAC_PADDING_ALIGNMENT - 1); + if (paddingLen) + { + err = wc_Poly1305Update(&poly1305Ctx, padding, paddingLen); + if (err) + return err; + } + + /* -- AAD length as a 64-bit little endian integer */ + word32ToLittle64(inAADLen, little64); + /* -- Ciphertext length as a 64-bit little endian integer */ + word32ToLittle64(inCiphertextLen, little64 + 8); + err = wc_Poly1305Update(&poly1305Ctx, little64, sizeof(little64)); + if (err) + return err; + + /* Finalize the auth tag */ + err = wc_Poly1305Final(&poly1305Ctx, outAuthTag); + + return err; +} + + +static void word32ToLittle64(const word32 inLittle32, byte outLittle64[8]) +{ +#ifndef WOLFSSL_X86_64_BUILD + XMEMSET(outLittle64 + 4, 0, 4); + + outLittle64[0] = (byte)(inLittle32 & 0x000000FF); + outLittle64[1] = (byte)((inLittle32 & 0x0000FF00) >> 8); + outLittle64[2] = (byte)((inLittle32 & 0x00FF0000) >> 16); + outLittle64[3] = (byte)((inLittle32 & 0xFF000000) >> 24); +#else + *(word64*)outLittle64 = inLittle32; +#endif +} + + +#endif /* HAVE_CHACHA && HAVE_POLY1305 */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/chacha_asm.S b/beken_os/beken378/func/wolfssl/wolfcrypt/src/chacha_asm.S new file mode 100755 index 0000000..0a1ee5d --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/chacha_asm.S @@ -0,0 +1,1420 @@ +/* chacha_asm + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#ifndef HAVE_INTEL_AVX1 +#define HAVE_INTEL_AVX1 +#endif /* HAVE_INTEL_AVX1 */ +#ifndef NO_AVX2_SUPPORT +#define HAVE_INTEL_AVX2 +#endif /* NO_AVX2_SUPPORT */ + +#ifndef __APPLE__ +.text +.globl chacha_encrypt_x64 +.type chacha_encrypt_x64,@function +.align 4 +chacha_encrypt_x64: +#else +.section __TEXT,__text +.globl _chacha_encrypt_x64 +.p2align 2 +_chacha_encrypt_x64: +#endif /* __APPLE__ */ + pushq %rbx + pushq %rbp + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + subq $0x40, %rsp + cmpl $0x40, %ecx + jl L_chacha_x64_small +L_chacha_x64_start: + subq $48, %rsp + movq %rdx, 24(%rsp) + movq %rsi, 32(%rsp) + movq %rcx, 40(%rsp) + movq 32(%rdi), %rax + movq 40(%rdi), %rbx + movq %rax, 8(%rsp) + movq %rbx, 16(%rsp) + movl (%rdi), %eax + movl 4(%rdi), %ebx + movl 8(%rdi), %ecx + movl 12(%rdi), %edx + movl 16(%rdi), %r8d + movl 20(%rdi), %r9d + movl 24(%rdi), %r10d + movl 28(%rdi), %r11d + movl 48(%rdi), %r12d + movl 52(%rdi), %r13d + movl 56(%rdi), %r14d + movl 60(%rdi), %r15d + movb $10, (%rsp) + movl 8(%rsp), %esi + movl 12(%rsp), %ebp +L_chacha_x64_block_crypt_start: + addl %r8d, %eax + addl %r9d, %ebx + xorl %eax, %r12d + xorl %ebx, %r13d + roll $16, %r12d + roll $16, %r13d + addl %r12d, %esi + addl %r13d, %ebp + xorl %esi, %r8d + xorl %ebp, %r9d + roll $12, %r8d + roll $12, %r9d + addl %r8d, %eax + addl %r9d, %ebx + xorl %eax, %r12d + xorl %ebx, %r13d + roll $8, %r12d + roll $8, %r13d + addl %r12d, %esi + addl %r13d, %ebp + xorl %esi, %r8d + xorl %ebp, %r9d + roll $7, %r8d + roll $7, %r9d + movl %esi, 8(%rsp) + movl %ebp, 12(%rsp) + movl 16(%rsp), %esi + movl 20(%rsp), %ebp + addl %r10d, %ecx + addl %r11d, %edx + xorl %ecx, %r14d + xorl %edx, %r15d + roll $16, %r14d + roll $16, %r15d + addl %r14d, %esi + addl %r15d, %ebp + xorl %esi, %r10d + xorl %ebp, %r11d + roll $12, %r10d + roll $12, %r11d + addl %r10d, %ecx + addl %r11d, %edx + xorl %ecx, %r14d + xorl %edx, %r15d + roll $8, %r14d + roll $8, %r15d + addl %r14d, %esi + addl %r15d, %ebp + xorl %esi, %r10d + xorl %ebp, %r11d + roll $7, %r10d + roll $7, %r11d + addl %r9d, %eax + addl %r10d, %ebx + xorl %eax, %r15d + xorl %ebx, %r12d + roll $16, %r15d + roll $16, %r12d + addl %r15d, %esi + addl %r12d, %ebp + xorl %esi, %r9d + xorl %ebp, %r10d + roll $12, %r9d + roll $12, %r10d + addl %r9d, %eax + addl %r10d, %ebx + xorl %eax, %r15d + xorl %ebx, %r12d + roll $8, %r15d + roll $8, %r12d + addl %r15d, %esi + addl %r12d, %ebp + xorl %esi, %r9d + xorl %ebp, %r10d + roll $7, %r9d + roll $7, %r10d + movl %esi, 16(%rsp) + movl %ebp, 20(%rsp) + movl 8(%rsp), %esi + movl 12(%rsp), %ebp + addl %r11d, %ecx + addl %r8d, %edx + xorl %ecx, %r13d + xorl %edx, %r14d + roll $16, %r13d + roll $16, %r14d + addl %r13d, %esi + addl %r14d, %ebp + xorl %esi, %r11d + xorl %ebp, %r8d + roll $12, %r11d + roll $12, %r8d + addl %r11d, %ecx + addl %r8d, %edx + xorl %ecx, %r13d + xorl %edx, %r14d + roll $8, %r13d + roll $8, %r14d + addl %r13d, %esi + addl %r14d, %ebp + xorl %esi, %r11d + xorl %ebp, %r8d + roll $7, %r11d + roll $7, %r8d + decb (%rsp) + jnz L_chacha_x64_block_crypt_start + movl %esi, 8(%rsp) + movl %ebp, 12(%rsp) + movq 32(%rsp), %rsi + movq 24(%rsp), %rbp + addl (%rdi), %eax + addl 4(%rdi), %ebx + addl 8(%rdi), %ecx + addl 12(%rdi), %edx + addl 16(%rdi), %r8d + addl 20(%rdi), %r9d + addl 24(%rdi), %r10d + addl 28(%rdi), %r11d + addl 48(%rdi), %r12d + addl 52(%rdi), %r13d + addl 56(%rdi), %r14d + addl 60(%rdi), %r15d + xorl (%rsi), %eax + xorl 4(%rsi), %ebx + xorl 8(%rsi), %ecx + xorl 12(%rsi), %edx + xorl 16(%rsi), %r8d + xorl 20(%rsi), %r9d + xorl 24(%rsi), %r10d + xorl 28(%rsi), %r11d + xorl 48(%rsi), %r12d + xorl 52(%rsi), %r13d + xorl 56(%rsi), %r14d + xorl 60(%rsi), %r15d + movl %eax, (%rbp) + movl %ebx, 4(%rbp) + movl %ecx, 8(%rbp) + movl %edx, 12(%rbp) + movl %r8d, 16(%rbp) + movl %r9d, 20(%rbp) + movl %r10d, 24(%rbp) + movl %r11d, 28(%rbp) + movl %r12d, 48(%rbp) + movl %r13d, 52(%rbp) + movl %r14d, 56(%rbp) + movl %r15d, 60(%rbp) + movl 8(%rsp), %eax + movl 12(%rsp), %ebx + movl 16(%rsp), %ecx + movl 20(%rsp), %edx + addl 32(%rdi), %eax + addl 36(%rdi), %ebx + addl 40(%rdi), %ecx + addl 44(%rdi), %edx + xorl 32(%rsi), %eax + xorl 36(%rsi), %ebx + xorl 40(%rsi), %ecx + xorl 44(%rsi), %edx + movl %eax, 32(%rbp) + movl %ebx, 36(%rbp) + movl %ecx, 40(%rbp) + movl %edx, 44(%rbp) + movq 24(%rsp), %rdx + movq 40(%rsp), %rcx + addl $0x01, 48(%rdi) + addq $48, %rsp + subl $0x40, %ecx + addq $0x40, %rsi + addq $0x40, %rdx + cmpl $0x40, %ecx + jge L_chacha_x64_start +L_chacha_x64_small: + cmpl $0x00, %ecx + je L_chacha_x64_done + subq $48, %rsp + movq %rdx, 24(%rsp) + movq %rsi, 32(%rsp) + movq %rcx, 40(%rsp) + movq 32(%rdi), %rax + movq 40(%rdi), %rbx + movq %rax, 8(%rsp) + movq %rbx, 16(%rsp) + movl (%rdi), %eax + movl 4(%rdi), %ebx + movl 8(%rdi), %ecx + movl 12(%rdi), %edx + movl 16(%rdi), %r8d + movl 20(%rdi), %r9d + movl 24(%rdi), %r10d + movl 28(%rdi), %r11d + movl 48(%rdi), %r12d + movl 52(%rdi), %r13d + movl 56(%rdi), %r14d + movl 60(%rdi), %r15d + movb $10, (%rsp) + movl 8(%rsp), %esi + movl 12(%rsp), %ebp +L_chacha_x64_partial_crypt_start: + addl %r8d, %eax + addl %r9d, %ebx + xorl %eax, %r12d + xorl %ebx, %r13d + roll $16, %r12d + roll $16, %r13d + addl %r12d, %esi + addl %r13d, %ebp + xorl %esi, %r8d + xorl %ebp, %r9d + roll $12, %r8d + roll $12, %r9d + addl %r8d, %eax + addl %r9d, %ebx + xorl %eax, %r12d + xorl %ebx, %r13d + roll $8, %r12d + roll $8, %r13d + addl %r12d, %esi + addl %r13d, %ebp + xorl %esi, %r8d + xorl %ebp, %r9d + roll $7, %r8d + roll $7, %r9d + movl %esi, 8(%rsp) + movl %ebp, 12(%rsp) + movl 16(%rsp), %esi + movl 20(%rsp), %ebp + addl %r10d, %ecx + addl %r11d, %edx + xorl %ecx, %r14d + xorl %edx, %r15d + roll $16, %r14d + roll $16, %r15d + addl %r14d, %esi + addl %r15d, %ebp + xorl %esi, %r10d + xorl %ebp, %r11d + roll $12, %r10d + roll $12, %r11d + addl %r10d, %ecx + addl %r11d, %edx + xorl %ecx, %r14d + xorl %edx, %r15d + roll $8, %r14d + roll $8, %r15d + addl %r14d, %esi + addl %r15d, %ebp + xorl %esi, %r10d + xorl %ebp, %r11d + roll $7, %r10d + roll $7, %r11d + addl %r9d, %eax + addl %r10d, %ebx + xorl %eax, %r15d + xorl %ebx, %r12d + roll $16, %r15d + roll $16, %r12d + addl %r15d, %esi + addl %r12d, %ebp + xorl %esi, %r9d + xorl %ebp, %r10d + roll $12, %r9d + roll $12, %r10d + addl %r9d, %eax + addl %r10d, %ebx + xorl %eax, %r15d + xorl %ebx, %r12d + roll $8, %r15d + roll $8, %r12d + addl %r15d, %esi + addl %r12d, %ebp + xorl %esi, %r9d + xorl %ebp, %r10d + roll $7, %r9d + roll $7, %r10d + movl %esi, 16(%rsp) + movl %ebp, 20(%rsp) + movl 8(%rsp), %esi + movl 12(%rsp), %ebp + addl %r11d, %ecx + addl %r8d, %edx + xorl %ecx, %r13d + xorl %edx, %r14d + roll $16, %r13d + roll $16, %r14d + addl %r13d, %esi + addl %r14d, %ebp + xorl %esi, %r11d + xorl %ebp, %r8d + roll $12, %r11d + roll $12, %r8d + addl %r11d, %ecx + addl %r8d, %edx + xorl %ecx, %r13d + xorl %edx, %r14d + roll $8, %r13d + roll $8, %r14d + addl %r13d, %esi + addl %r14d, %ebp + xorl %esi, %r11d + xorl %ebp, %r8d + roll $7, %r11d + roll $7, %r8d + decb (%rsp) + jnz L_chacha_x64_partial_crypt_start + movl %esi, 8(%rsp) + movl %ebp, 12(%rsp) + movq 32(%rsp), %rsi + addl (%rdi), %eax + addl 4(%rdi), %ebx + addl 8(%rdi), %ecx + addl 12(%rdi), %edx + addl 16(%rdi), %r8d + addl 20(%rdi), %r9d + addl 24(%rdi), %r10d + addl 28(%rdi), %r11d + addl 48(%rdi), %r12d + addl 52(%rdi), %r13d + addl 56(%rdi), %r14d + addl 60(%rdi), %r15d + movl %eax, 48(%rsp) + movl %ebx, 52(%rsp) + movl %ecx, 56(%rsp) + movl %edx, 60(%rsp) + movl %r8d, 64(%rsp) + movl %r9d, 68(%rsp) + movl %r10d, 72(%rsp) + movl %r11d, 76(%rsp) + movl %r12d, 96(%rsp) + movl %r13d, 100(%rsp) + movl %r14d, 104(%rsp) + movl %r15d, 108(%rsp) + movl 8(%rsp), %eax + movl 12(%rsp), %ebx + movl 16(%rsp), %ecx + movl 20(%rsp), %edx + addl 32(%rdi), %eax + addl 36(%rdi), %ebx + addl 40(%rdi), %ecx + addl 44(%rdi), %edx + movl %eax, 80(%rsp) + movl %ebx, 84(%rsp) + movl %ecx, 88(%rsp) + movl %edx, 92(%rsp) + movq 24(%rsp), %rdx + movq 40(%rsp), %rcx + addl $0x01, 48(%rdi) + addq $48, %rsp + movl %ecx, %r8d + xorq %rbx, %rbx + andl $7, %r8d + jz L_chacha_x64_partial_start64 +L_chacha_x64_partial_start8: + movzbl (%rsp,%rbx,1), %eax + xorb (%rsi,%rbx,1), %al + movb %al, (%rdx,%rbx,1) + incl %ebx + cmpl %r8d, %ebx + jne L_chacha_x64_partial_start8 + je L_chacha_x64_partial_end64 +L_chacha_x64_partial_start64: + movq (%rsp,%rbx,1), %rax + xorq (%rsi,%rbx,1), %rax + movq %rax, (%rdx,%rbx,1) + addl $8, %ebx +L_chacha_x64_partial_end64: + cmpl %ecx, %ebx + jne L_chacha_x64_partial_start64 +L_chacha_x64_done: + addq $0x40, %rsp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbp + popq %rbx + repz retq +#ifndef __APPLE__ +.size chacha_encrypt_x64,.-chacha_encrypt_x64 +#endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX1 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_chacha20_avx1_rotl8: +.quad 0x605040702010003, 0xe0d0c0f0a09080b +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_chacha20_avx1_rotl16: +.quad 0x504070601000302, 0xd0c0f0e09080b0a +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_chacha20_avx1_add: +.quad 0x100000000, 0x300000002 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_chacha20_avx1_four: +.quad 0x400000004, 0x400000004 +#ifndef __APPLE__ +.text +.globl chacha_encrypt_avx1 +.type chacha_encrypt_avx1,@function +.align 4 +chacha_encrypt_avx1: +#else +.section __TEXT,__text +.globl _chacha_encrypt_avx1 +.p2align 2 +_chacha_encrypt_avx1: +#endif /* __APPLE__ */ + subq $0x190, %rsp + movq %rsp, %r9 + leaq 256(%rsp), %r10 + andq $-16, %r9 + andq $-16, %r10 + movl %ecx, %eax + shrl $8, %eax + jz L_chacha20_avx1_end128 + vpshufd $0x00, (%rdi), %xmm0 + vpshufd $0x00, 4(%rdi), %xmm1 + vpshufd $0x00, 8(%rdi), %xmm2 + vpshufd $0x00, 12(%rdi), %xmm3 + vpshufd $0x00, 16(%rdi), %xmm4 + vpshufd $0x00, 20(%rdi), %xmm5 + vpshufd $0x00, 24(%rdi), %xmm6 + vpshufd $0x00, 28(%rdi), %xmm7 + vpshufd $0x00, 32(%rdi), %xmm8 + vpshufd $0x00, 36(%rdi), %xmm9 + vpshufd $0x00, 40(%rdi), %xmm10 + vpshufd $0x00, 44(%rdi), %xmm11 + vpshufd $0x00, 48(%rdi), %xmm12 + vpshufd $0x00, 52(%rdi), %xmm13 + vpshufd $0x00, 56(%rdi), %xmm14 + vpshufd $0x00, 60(%rdi), %xmm15 + vpaddd L_chacha20_avx1_add(%rip), %xmm12, %xmm12 + vmovdqa %xmm0, (%r9) + vmovdqa %xmm1, 16(%r9) + vmovdqa %xmm2, 32(%r9) + vmovdqa %xmm3, 48(%r9) + vmovdqa %xmm4, 64(%r9) + vmovdqa %xmm5, 80(%r9) + vmovdqa %xmm6, 96(%r9) + vmovdqa %xmm7, 112(%r9) + vmovdqa %xmm8, 128(%r9) + vmovdqa %xmm9, 144(%r9) + vmovdqa %xmm10, 160(%r9) + vmovdqa %xmm11, 176(%r9) + vmovdqa %xmm12, 192(%r9) + vmovdqa %xmm13, 208(%r9) + vmovdqa %xmm14, 224(%r9) + vmovdqa %xmm15, 240(%r9) +L_chacha20_avx1_start128: + vmovdqa %xmm11, 48(%r10) + movb $10, %r8b +L_chacha20_avx1_loop128: + vpaddd %xmm4, %xmm0, %xmm0 + vpxor %xmm0, %xmm12, %xmm12 + vmovdqa 48(%r10), %xmm11 + vpshufb L_chacha20_avx1_rotl16(%rip), %xmm12, %xmm12 + vpaddd %xmm12, %xmm8, %xmm8 + vpxor %xmm8, %xmm4, %xmm4 + vpaddd %xmm5, %xmm1, %xmm1 + vpxor %xmm1, %xmm13, %xmm13 + vpshufb L_chacha20_avx1_rotl16(%rip), %xmm13, %xmm13 + vpaddd %xmm13, %xmm9, %xmm9 + vpxor %xmm9, %xmm5, %xmm5 + vpaddd %xmm6, %xmm2, %xmm2 + vpxor %xmm2, %xmm14, %xmm14 + vpshufb L_chacha20_avx1_rotl16(%rip), %xmm14, %xmm14 + vpaddd %xmm14, %xmm10, %xmm10 + vpxor %xmm10, %xmm6, %xmm6 + vpaddd %xmm7, %xmm3, %xmm3 + vpxor %xmm3, %xmm15, %xmm15 + vpshufb L_chacha20_avx1_rotl16(%rip), %xmm15, %xmm15 + vpaddd %xmm15, %xmm11, %xmm11 + vpxor %xmm11, %xmm7, %xmm7 + vmovdqa %xmm11, 48(%r10) + vpsrld $20, %xmm4, %xmm11 + vpslld $12, %xmm4, %xmm4 + vpxor %xmm11, %xmm4, %xmm4 + vpsrld $20, %xmm5, %xmm11 + vpslld $12, %xmm5, %xmm5 + vpxor %xmm11, %xmm5, %xmm5 + vpsrld $20, %xmm6, %xmm11 + vpslld $12, %xmm6, %xmm6 + vpxor %xmm11, %xmm6, %xmm6 + vpsrld $20, %xmm7, %xmm11 + vpslld $12, %xmm7, %xmm7 + vpxor %xmm11, %xmm7, %xmm7 + vpaddd %xmm4, %xmm0, %xmm0 + vpxor %xmm0, %xmm12, %xmm12 + vmovdqa 48(%r10), %xmm11 + vpshufb L_chacha20_avx1_rotl8(%rip), %xmm12, %xmm12 + vpaddd %xmm12, %xmm8, %xmm8 + vpxor %xmm8, %xmm4, %xmm4 + vpaddd %xmm5, %xmm1, %xmm1 + vpxor %xmm1, %xmm13, %xmm13 + vpshufb L_chacha20_avx1_rotl8(%rip), %xmm13, %xmm13 + vpaddd %xmm13, %xmm9, %xmm9 + vpxor %xmm9, %xmm5, %xmm5 + vpaddd %xmm6, %xmm2, %xmm2 + vpxor %xmm2, %xmm14, %xmm14 + vpshufb L_chacha20_avx1_rotl8(%rip), %xmm14, %xmm14 + vpaddd %xmm14, %xmm10, %xmm10 + vpxor %xmm10, %xmm6, %xmm6 + vpaddd %xmm7, %xmm3, %xmm3 + vpxor %xmm3, %xmm15, %xmm15 + vpshufb L_chacha20_avx1_rotl8(%rip), %xmm15, %xmm15 + vpaddd %xmm15, %xmm11, %xmm11 + vpxor %xmm11, %xmm7, %xmm7 + vmovdqa %xmm11, 48(%r10) + vpsrld $25, %xmm4, %xmm11 + vpslld $7, %xmm4, %xmm4 + vpxor %xmm11, %xmm4, %xmm4 + vpsrld $25, %xmm5, %xmm11 + vpslld $7, %xmm5, %xmm5 + vpxor %xmm11, %xmm5, %xmm5 + vpsrld $25, %xmm6, %xmm11 + vpslld $7, %xmm6, %xmm6 + vpxor %xmm11, %xmm6, %xmm6 + vpsrld $25, %xmm7, %xmm11 + vpslld $7, %xmm7, %xmm7 + vpxor %xmm11, %xmm7, %xmm7 + vpaddd %xmm5, %xmm0, %xmm0 + vpxor %xmm0, %xmm15, %xmm15 + vmovdqa 48(%r10), %xmm11 + vpshufb L_chacha20_avx1_rotl16(%rip), %xmm15, %xmm15 + vpaddd %xmm15, %xmm10, %xmm10 + vpxor %xmm10, %xmm5, %xmm5 + vpaddd %xmm6, %xmm1, %xmm1 + vpxor %xmm1, %xmm12, %xmm12 + vpshufb L_chacha20_avx1_rotl16(%rip), %xmm12, %xmm12 + vpaddd %xmm12, %xmm11, %xmm11 + vpxor %xmm11, %xmm6, %xmm6 + vpaddd %xmm7, %xmm2, %xmm2 + vpxor %xmm2, %xmm13, %xmm13 + vpshufb L_chacha20_avx1_rotl16(%rip), %xmm13, %xmm13 + vpaddd %xmm13, %xmm8, %xmm8 + vpxor %xmm8, %xmm7, %xmm7 + vpaddd %xmm4, %xmm3, %xmm3 + vpxor %xmm3, %xmm14, %xmm14 + vpshufb L_chacha20_avx1_rotl16(%rip), %xmm14, %xmm14 + vpaddd %xmm14, %xmm9, %xmm9 + vpxor %xmm9, %xmm4, %xmm4 + vmovdqa %xmm11, 48(%r10) + vpsrld $20, %xmm5, %xmm11 + vpslld $12, %xmm5, %xmm5 + vpxor %xmm11, %xmm5, %xmm5 + vpsrld $20, %xmm6, %xmm11 + vpslld $12, %xmm6, %xmm6 + vpxor %xmm11, %xmm6, %xmm6 + vpsrld $20, %xmm7, %xmm11 + vpslld $12, %xmm7, %xmm7 + vpxor %xmm11, %xmm7, %xmm7 + vpsrld $20, %xmm4, %xmm11 + vpslld $12, %xmm4, %xmm4 + vpxor %xmm11, %xmm4, %xmm4 + vpaddd %xmm5, %xmm0, %xmm0 + vpxor %xmm0, %xmm15, %xmm15 + vmovdqa 48(%r10), %xmm11 + vpshufb L_chacha20_avx1_rotl8(%rip), %xmm15, %xmm15 + vpaddd %xmm15, %xmm10, %xmm10 + vpxor %xmm10, %xmm5, %xmm5 + vpaddd %xmm6, %xmm1, %xmm1 + vpxor %xmm1, %xmm12, %xmm12 + vpshufb L_chacha20_avx1_rotl8(%rip), %xmm12, %xmm12 + vpaddd %xmm12, %xmm11, %xmm11 + vpxor %xmm11, %xmm6, %xmm6 + vpaddd %xmm7, %xmm2, %xmm2 + vpxor %xmm2, %xmm13, %xmm13 + vpshufb L_chacha20_avx1_rotl8(%rip), %xmm13, %xmm13 + vpaddd %xmm13, %xmm8, %xmm8 + vpxor %xmm8, %xmm7, %xmm7 + vpaddd %xmm4, %xmm3, %xmm3 + vpxor %xmm3, %xmm14, %xmm14 + vpshufb L_chacha20_avx1_rotl8(%rip), %xmm14, %xmm14 + vpaddd %xmm14, %xmm9, %xmm9 + vpxor %xmm9, %xmm4, %xmm4 + vmovdqa %xmm11, 48(%r10) + vpsrld $25, %xmm5, %xmm11 + vpslld $7, %xmm5, %xmm5 + vpxor %xmm11, %xmm5, %xmm5 + vpsrld $25, %xmm6, %xmm11 + vpslld $7, %xmm6, %xmm6 + vpxor %xmm11, %xmm6, %xmm6 + vpsrld $25, %xmm7, %xmm11 + vpslld $7, %xmm7, %xmm7 + vpxor %xmm11, %xmm7, %xmm7 + vpsrld $25, %xmm4, %xmm11 + vpslld $7, %xmm4, %xmm4 + vpxor %xmm11, %xmm4, %xmm4 + decb %r8b + jnz L_chacha20_avx1_loop128 + vmovdqa 48(%r10), %xmm11 + vpaddd (%r9), %xmm0, %xmm0 + vpaddd 16(%r9), %xmm1, %xmm1 + vpaddd 32(%r9), %xmm2, %xmm2 + vpaddd 48(%r9), %xmm3, %xmm3 + vpaddd 64(%r9), %xmm4, %xmm4 + vpaddd 80(%r9), %xmm5, %xmm5 + vpaddd 96(%r9), %xmm6, %xmm6 + vpaddd 112(%r9), %xmm7, %xmm7 + vpaddd 128(%r9), %xmm8, %xmm8 + vpaddd 144(%r9), %xmm9, %xmm9 + vpaddd 160(%r9), %xmm10, %xmm10 + vpaddd 176(%r9), %xmm11, %xmm11 + vpaddd 192(%r9), %xmm12, %xmm12 + vpaddd 208(%r9), %xmm13, %xmm13 + vpaddd 224(%r9), %xmm14, %xmm14 + vpaddd 240(%r9), %xmm15, %xmm15 + vmovdqa %xmm8, (%r10) + vmovdqa %xmm9, 16(%r10) + vmovdqa %xmm10, 32(%r10) + vmovdqa %xmm11, 48(%r10) + vmovdqa %xmm12, 64(%r10) + vmovdqa %xmm13, 80(%r10) + vmovdqa %xmm14, 96(%r10) + vmovdqa %xmm15, 112(%r10) + vpunpckldq %xmm1, %xmm0, %xmm8 + vpunpckldq %xmm3, %xmm2, %xmm9 + vpunpckhdq %xmm1, %xmm0, %xmm12 + vpunpckhdq %xmm3, %xmm2, %xmm13 + vpunpckldq %xmm5, %xmm4, %xmm10 + vpunpckldq %xmm7, %xmm6, %xmm11 + vpunpckhdq %xmm5, %xmm4, %xmm14 + vpunpckhdq %xmm7, %xmm6, %xmm15 + vpunpcklqdq %xmm9, %xmm8, %xmm0 + vpunpcklqdq %xmm11, %xmm10, %xmm1 + vpunpckhqdq %xmm9, %xmm8, %xmm2 + vpunpckhqdq %xmm11, %xmm10, %xmm3 + vpunpcklqdq %xmm13, %xmm12, %xmm4 + vpunpcklqdq %xmm15, %xmm14, %xmm5 + vpunpckhqdq %xmm13, %xmm12, %xmm6 + vpunpckhqdq %xmm15, %xmm14, %xmm7 + vmovdqu (%rsi), %xmm8 + vmovdqu 16(%rsi), %xmm9 + vmovdqu 64(%rsi), %xmm10 + vmovdqu 80(%rsi), %xmm11 + vmovdqu 128(%rsi), %xmm12 + vmovdqu 144(%rsi), %xmm13 + vmovdqu 192(%rsi), %xmm14 + vmovdqu 208(%rsi), %xmm15 + vpxor %xmm8, %xmm0, %xmm0 + vpxor %xmm9, %xmm1, %xmm1 + vpxor %xmm10, %xmm2, %xmm2 + vpxor %xmm11, %xmm3, %xmm3 + vpxor %xmm12, %xmm4, %xmm4 + vpxor %xmm13, %xmm5, %xmm5 + vpxor %xmm14, %xmm6, %xmm6 + vpxor %xmm15, %xmm7, %xmm7 + vmovdqu %xmm0, (%rdx) + vmovdqu %xmm1, 16(%rdx) + vmovdqu %xmm2, 64(%rdx) + vmovdqu %xmm3, 80(%rdx) + vmovdqu %xmm4, 128(%rdx) + vmovdqu %xmm5, 144(%rdx) + vmovdqu %xmm6, 192(%rdx) + vmovdqu %xmm7, 208(%rdx) + vmovdqa (%r10), %xmm0 + vmovdqa 16(%r10), %xmm1 + vmovdqa 32(%r10), %xmm2 + vmovdqa 48(%r10), %xmm3 + vmovdqa 64(%r10), %xmm4 + vmovdqa 80(%r10), %xmm5 + vmovdqa 96(%r10), %xmm6 + vmovdqa 112(%r10), %xmm7 + vpunpckldq %xmm1, %xmm0, %xmm8 + vpunpckldq %xmm3, %xmm2, %xmm9 + vpunpckhdq %xmm1, %xmm0, %xmm12 + vpunpckhdq %xmm3, %xmm2, %xmm13 + vpunpckldq %xmm5, %xmm4, %xmm10 + vpunpckldq %xmm7, %xmm6, %xmm11 + vpunpckhdq %xmm5, %xmm4, %xmm14 + vpunpckhdq %xmm7, %xmm6, %xmm15 + vpunpcklqdq %xmm9, %xmm8, %xmm0 + vpunpcklqdq %xmm11, %xmm10, %xmm1 + vpunpckhqdq %xmm9, %xmm8, %xmm2 + vpunpckhqdq %xmm11, %xmm10, %xmm3 + vpunpcklqdq %xmm13, %xmm12, %xmm4 + vpunpcklqdq %xmm15, %xmm14, %xmm5 + vpunpckhqdq %xmm13, %xmm12, %xmm6 + vpunpckhqdq %xmm15, %xmm14, %xmm7 + vmovdqu 32(%rsi), %xmm8 + vmovdqu 48(%rsi), %xmm9 + vmovdqu 96(%rsi), %xmm10 + vmovdqu 112(%rsi), %xmm11 + vmovdqu 160(%rsi), %xmm12 + vmovdqu 176(%rsi), %xmm13 + vmovdqu 224(%rsi), %xmm14 + vmovdqu 240(%rsi), %xmm15 + vpxor %xmm8, %xmm0, %xmm0 + vpxor %xmm9, %xmm1, %xmm1 + vpxor %xmm10, %xmm2, %xmm2 + vpxor %xmm11, %xmm3, %xmm3 + vpxor %xmm12, %xmm4, %xmm4 + vpxor %xmm13, %xmm5, %xmm5 + vpxor %xmm14, %xmm6, %xmm6 + vpxor %xmm15, %xmm7, %xmm7 + vmovdqu %xmm0, 32(%rdx) + vmovdqu %xmm1, 48(%rdx) + vmovdqu %xmm2, 96(%rdx) + vmovdqu %xmm3, 112(%rdx) + vmovdqu %xmm4, 160(%rdx) + vmovdqu %xmm5, 176(%rdx) + vmovdqu %xmm6, 224(%rdx) + vmovdqu %xmm7, 240(%rdx) + vmovdqa 192(%r9), %xmm12 + addq $0x100, %rsi + addq $0x100, %rdx + vpaddd L_chacha20_avx1_four(%rip), %xmm12, %xmm12 + subl $0x100, %ecx + vmovdqa %xmm12, 192(%r9) + cmpl $0x100, %ecx + jl L_chacha20_avx1_done128 + vmovdqa (%r9), %xmm0 + vmovdqa 16(%r9), %xmm1 + vmovdqa 32(%r9), %xmm2 + vmovdqa 48(%r9), %xmm3 + vmovdqa 64(%r9), %xmm4 + vmovdqa 80(%r9), %xmm5 + vmovdqa 96(%r9), %xmm6 + vmovdqa 112(%r9), %xmm7 + vmovdqa 128(%r9), %xmm8 + vmovdqa 144(%r9), %xmm9 + vmovdqa 160(%r9), %xmm10 + vmovdqa 176(%r9), %xmm11 + vmovdqa 192(%r9), %xmm12 + vmovdqa 208(%r9), %xmm13 + vmovdqa 224(%r9), %xmm14 + vmovdqa 240(%r9), %xmm15 + jmp L_chacha20_avx1_start128 +L_chacha20_avx1_done128: + shl $2, %eax + addl %eax, 48(%rdi) +L_chacha20_avx1_end128: + cmpl $0x40, %ecx + jl L_chacha20_avx1_block_done +L_chacha20_avx1_block_start: + vmovdqu (%rdi), %xmm0 + vmovdqu 16(%rdi), %xmm1 + vmovdqu 32(%rdi), %xmm2 + vmovdqu 48(%rdi), %xmm3 + vmovdqa %xmm0, %xmm5 + vmovdqa %xmm1, %xmm6 + vmovdqa %xmm2, %xmm7 + vmovdqa %xmm3, %xmm8 + movb $10, %al +L_chacha20_avx1_block_crypt_start: + vpaddd %xmm1, %xmm0, %xmm0 + vpxor %xmm0, %xmm3, %xmm3 + vpshufb L_chacha20_avx1_rotl16(%rip), %xmm3, %xmm3 + vpaddd %xmm3, %xmm2, %xmm2 + vpxor %xmm2, %xmm1, %xmm1 + vpsrld $20, %xmm1, %xmm4 + vpslld $12, %xmm1, %xmm1 + vpxor %xmm4, %xmm1, %xmm1 + vpaddd %xmm1, %xmm0, %xmm0 + vpxor %xmm0, %xmm3, %xmm3 + vpshufb L_chacha20_avx1_rotl8(%rip), %xmm3, %xmm3 + vpaddd %xmm3, %xmm2, %xmm2 + vpxor %xmm2, %xmm1, %xmm1 + vpsrld $25, %xmm1, %xmm4 + vpslld $7, %xmm1, %xmm1 + vpxor %xmm4, %xmm1, %xmm1 + vpshufd $57, %xmm1, %xmm1 + vpshufd $0x4e, %xmm2, %xmm2 + vpshufd $0x93, %xmm3, %xmm3 + vpaddd %xmm1, %xmm0, %xmm0 + vpxor %xmm0, %xmm3, %xmm3 + vpshufb L_chacha20_avx1_rotl16(%rip), %xmm3, %xmm3 + vpaddd %xmm3, %xmm2, %xmm2 + vpxor %xmm2, %xmm1, %xmm1 + vpsrld $20, %xmm1, %xmm4 + vpslld $12, %xmm1, %xmm1 + vpxor %xmm4, %xmm1, %xmm1 + vpaddd %xmm1, %xmm0, %xmm0 + vpxor %xmm0, %xmm3, %xmm3 + vpshufb L_chacha20_avx1_rotl8(%rip), %xmm3, %xmm3 + vpaddd %xmm3, %xmm2, %xmm2 + vpxor %xmm2, %xmm1, %xmm1 + vpsrld $25, %xmm1, %xmm4 + vpslld $7, %xmm1, %xmm1 + vpxor %xmm4, %xmm1, %xmm1 + vpshufd $0x93, %xmm1, %xmm1 + vpshufd $0x4e, %xmm2, %xmm2 + vpshufd $57, %xmm3, %xmm3 + decb %al + jnz L_chacha20_avx1_block_crypt_start + vpaddd %xmm5, %xmm0, %xmm0 + vpaddd %xmm6, %xmm1, %xmm1 + vpaddd %xmm7, %xmm2, %xmm2 + vpaddd %xmm8, %xmm3, %xmm3 + vmovdqu (%rsi), %xmm5 + vmovdqu 16(%rsi), %xmm6 + vmovdqu 32(%rsi), %xmm7 + vmovdqu 48(%rsi), %xmm8 + vpxor %xmm5, %xmm0, %xmm0 + vpxor %xmm6, %xmm1, %xmm1 + vpxor %xmm7, %xmm2, %xmm2 + vpxor %xmm8, %xmm3, %xmm3 + vmovdqu %xmm0, (%rdx) + vmovdqu %xmm1, 16(%rdx) + vmovdqu %xmm2, 32(%rdx) + vmovdqu %xmm3, 48(%rdx) + addl $0x01, 48(%rdi) + subl $0x40, %ecx + addq $0x40, %rsi + addq $0x40, %rdx + cmpl $0x40, %ecx + jge L_chacha20_avx1_block_start +L_chacha20_avx1_block_done: + cmpl $0x00, %ecx + je L_chacha20_avx1_partial_done + vmovdqu (%rdi), %xmm0 + vmovdqu 16(%rdi), %xmm1 + vmovdqu 32(%rdi), %xmm2 + vmovdqu 48(%rdi), %xmm3 + vmovdqa %xmm0, %xmm5 + vmovdqa %xmm1, %xmm6 + vmovdqa %xmm2, %xmm7 + vmovdqa %xmm3, %xmm8 + movb $10, %al +L_chacha20_avx1_partial_crypt_start: + vpaddd %xmm1, %xmm0, %xmm0 + vpxor %xmm0, %xmm3, %xmm3 + vpshufb L_chacha20_avx1_rotl16(%rip), %xmm3, %xmm3 + vpaddd %xmm3, %xmm2, %xmm2 + vpxor %xmm2, %xmm1, %xmm1 + vpsrld $20, %xmm1, %xmm4 + vpslld $12, %xmm1, %xmm1 + vpxor %xmm4, %xmm1, %xmm1 + vpaddd %xmm1, %xmm0, %xmm0 + vpxor %xmm0, %xmm3, %xmm3 + vpshufb L_chacha20_avx1_rotl8(%rip), %xmm3, %xmm3 + vpaddd %xmm3, %xmm2, %xmm2 + vpxor %xmm2, %xmm1, %xmm1 + vpsrld $25, %xmm1, %xmm4 + vpslld $7, %xmm1, %xmm1 + vpxor %xmm4, %xmm1, %xmm1 + vpshufd $57, %xmm1, %xmm1 + vpshufd $0x4e, %xmm2, %xmm2 + vpshufd $0x93, %xmm3, %xmm3 + vpaddd %xmm1, %xmm0, %xmm0 + vpxor %xmm0, %xmm3, %xmm3 + vpshufb L_chacha20_avx1_rotl16(%rip), %xmm3, %xmm3 + vpaddd %xmm3, %xmm2, %xmm2 + vpxor %xmm2, %xmm1, %xmm1 + vpsrld $20, %xmm1, %xmm4 + vpslld $12, %xmm1, %xmm1 + vpxor %xmm4, %xmm1, %xmm1 + vpaddd %xmm1, %xmm0, %xmm0 + vpxor %xmm0, %xmm3, %xmm3 + vpshufb L_chacha20_avx1_rotl8(%rip), %xmm3, %xmm3 + vpaddd %xmm3, %xmm2, %xmm2 + vpxor %xmm2, %xmm1, %xmm1 + vpsrld $25, %xmm1, %xmm4 + vpslld $7, %xmm1, %xmm1 + vpxor %xmm4, %xmm1, %xmm1 + vpshufd $0x93, %xmm1, %xmm1 + vpshufd $0x4e, %xmm2, %xmm2 + vpshufd $57, %xmm3, %xmm3 + decb %al + jnz L_chacha20_avx1_partial_crypt_start + vpaddd %xmm5, %xmm0, %xmm0 + vpaddd %xmm6, %xmm1, %xmm1 + vpaddd %xmm7, %xmm2, %xmm2 + vpaddd %xmm8, %xmm3, %xmm3 + vmovdqu %xmm0, (%r10) + vmovdqu %xmm1, 16(%r10) + vmovdqu %xmm2, 32(%r10) + vmovdqu %xmm3, 48(%r10) + addl $0x01, 48(%rdi) + movl %ecx, %r8d + xorq %r11, %r11 + andl $7, %r8d + jz L_chacha20_avx1_partial_start64 +L_chacha20_avx1_partial_start8: + movzbl (%r10,%r11,1), %eax + xorb (%rsi,%r11,1), %al + movb %al, (%rdx,%r11,1) + incl %r11d + cmpl %r8d, %r11d + jne L_chacha20_avx1_partial_start8 + je L_chacha20_avx1_partial_end64 +L_chacha20_avx1_partial_start64: + movq (%r10,%r11,1), %rax + xorq (%rsi,%r11,1), %rax + movq %rax, (%rdx,%r11,1) + addl $8, %r11d +L_chacha20_avx1_partial_end64: + cmpl %ecx, %r11d + jne L_chacha20_avx1_partial_start64 +L_chacha20_avx1_partial_done: + addq $0x190, %rsp + repz retq +#ifndef __APPLE__ +.size chacha_encrypt_avx1,.-chacha_encrypt_avx1 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX1 */ +#ifdef HAVE_INTEL_AVX2 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 32 +#else +.p2align 5 +#endif /* __APPLE__ */ +L_chacha20_avx2_rotl8: +.quad 0x605040702010003, 0xe0d0c0f0a09080b +.quad 0x605040702010003, 0xe0d0c0f0a09080b +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 32 +#else +.p2align 5 +#endif /* __APPLE__ */ +L_chacha20_avx2_rotl16: +.quad 0x504070601000302, 0xd0c0f0e09080b0a +.quad 0x504070601000302, 0xd0c0f0e09080b0a +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 32 +#else +.p2align 5 +#endif /* __APPLE__ */ +L_chacha20_avx2_add: +.quad 0x100000000, 0x300000002 +.quad 0x500000004, 0x700000006 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 32 +#else +.p2align 5 +#endif /* __APPLE__ */ +L_chacha20_avx2_eight: +.quad 0x800000008, 0x800000008 +.quad 0x800000008, 0x800000008 +#ifndef __APPLE__ +.text +.globl chacha_encrypt_avx2 +.type chacha_encrypt_avx2,@function +.align 4 +chacha_encrypt_avx2: +#else +.section __TEXT,__text +.globl _chacha_encrypt_avx2 +.p2align 2 +_chacha_encrypt_avx2: +#endif /* __APPLE__ */ + subq $0x310, %rsp + movq %rsp, %r9 + leaq 512(%rsp), %r10 + andq $-32, %r9 + andq $-32, %r10 + movl %ecx, %eax + shrl $9, %eax + jz L_chacha20_avx2_end256 + vpbroadcastd (%rdi), %ymm0 + vpbroadcastd 4(%rdi), %ymm1 + vpbroadcastd 8(%rdi), %ymm2 + vpbroadcastd 12(%rdi), %ymm3 + vpbroadcastd 16(%rdi), %ymm4 + vpbroadcastd 20(%rdi), %ymm5 + vpbroadcastd 24(%rdi), %ymm6 + vpbroadcastd 28(%rdi), %ymm7 + vpbroadcastd 32(%rdi), %ymm8 + vpbroadcastd 36(%rdi), %ymm9 + vpbroadcastd 40(%rdi), %ymm10 + vpbroadcastd 44(%rdi), %ymm11 + vpbroadcastd 48(%rdi), %ymm12 + vpbroadcastd 52(%rdi), %ymm13 + vpbroadcastd 56(%rdi), %ymm14 + vpbroadcastd 60(%rdi), %ymm15 + vpaddd L_chacha20_avx2_add(%rip), %ymm12, %ymm12 + vmovdqa %ymm0, (%r9) + vmovdqa %ymm1, 32(%r9) + vmovdqa %ymm2, 64(%r9) + vmovdqa %ymm3, 96(%r9) + vmovdqa %ymm4, 128(%r9) + vmovdqa %ymm5, 160(%r9) + vmovdqa %ymm6, 192(%r9) + vmovdqa %ymm7, 224(%r9) + vmovdqa %ymm8, 256(%r9) + vmovdqa %ymm9, 288(%r9) + vmovdqa %ymm10, 320(%r9) + vmovdqa %ymm11, 352(%r9) + vmovdqa %ymm12, 384(%r9) + vmovdqa %ymm13, 416(%r9) + vmovdqa %ymm14, 448(%r9) + vmovdqa %ymm15, 480(%r9) +L_chacha20_avx2_start256: + movb $10, %r8b + vmovdqa %ymm11, 96(%r10) +L_chacha20_avx2_loop256: + vpaddd %ymm4, %ymm0, %ymm0 + vpxor %ymm0, %ymm12, %ymm12 + vmovdqa 96(%r10), %ymm11 + vpshufb L_chacha20_avx2_rotl16(%rip), %ymm12, %ymm12 + vpaddd %ymm12, %ymm8, %ymm8 + vpxor %ymm8, %ymm4, %ymm4 + vpaddd %ymm5, %ymm1, %ymm1 + vpxor %ymm1, %ymm13, %ymm13 + vpshufb L_chacha20_avx2_rotl16(%rip), %ymm13, %ymm13 + vpaddd %ymm13, %ymm9, %ymm9 + vpxor %ymm9, %ymm5, %ymm5 + vpaddd %ymm6, %ymm2, %ymm2 + vpxor %ymm2, %ymm14, %ymm14 + vpshufb L_chacha20_avx2_rotl16(%rip), %ymm14, %ymm14 + vpaddd %ymm14, %ymm10, %ymm10 + vpxor %ymm10, %ymm6, %ymm6 + vpaddd %ymm7, %ymm3, %ymm3 + vpxor %ymm3, %ymm15, %ymm15 + vpshufb L_chacha20_avx2_rotl16(%rip), %ymm15, %ymm15 + vpaddd %ymm15, %ymm11, %ymm11 + vpxor %ymm11, %ymm7, %ymm7 + vmovdqa %ymm11, 96(%r10) + vpsrld $20, %ymm4, %ymm11 + vpslld $12, %ymm4, %ymm4 + vpxor %ymm11, %ymm4, %ymm4 + vpsrld $20, %ymm5, %ymm11 + vpslld $12, %ymm5, %ymm5 + vpxor %ymm11, %ymm5, %ymm5 + vpsrld $20, %ymm6, %ymm11 + vpslld $12, %ymm6, %ymm6 + vpxor %ymm11, %ymm6, %ymm6 + vpsrld $20, %ymm7, %ymm11 + vpslld $12, %ymm7, %ymm7 + vpxor %ymm11, %ymm7, %ymm7 + vpaddd %ymm4, %ymm0, %ymm0 + vpxor %ymm0, %ymm12, %ymm12 + vmovdqa 96(%r10), %ymm11 + vpshufb L_chacha20_avx2_rotl8(%rip), %ymm12, %ymm12 + vpaddd %ymm12, %ymm8, %ymm8 + vpxor %ymm8, %ymm4, %ymm4 + vpaddd %ymm5, %ymm1, %ymm1 + vpxor %ymm1, %ymm13, %ymm13 + vpshufb L_chacha20_avx2_rotl8(%rip), %ymm13, %ymm13 + vpaddd %ymm13, %ymm9, %ymm9 + vpxor %ymm9, %ymm5, %ymm5 + vpaddd %ymm6, %ymm2, %ymm2 + vpxor %ymm2, %ymm14, %ymm14 + vpshufb L_chacha20_avx2_rotl8(%rip), %ymm14, %ymm14 + vpaddd %ymm14, %ymm10, %ymm10 + vpxor %ymm10, %ymm6, %ymm6 + vpaddd %ymm7, %ymm3, %ymm3 + vpxor %ymm3, %ymm15, %ymm15 + vpshufb L_chacha20_avx2_rotl8(%rip), %ymm15, %ymm15 + vpaddd %ymm15, %ymm11, %ymm11 + vpxor %ymm11, %ymm7, %ymm7 + vmovdqa %ymm11, 96(%r10) + vpsrld $25, %ymm4, %ymm11 + vpslld $7, %ymm4, %ymm4 + vpxor %ymm11, %ymm4, %ymm4 + vpsrld $25, %ymm5, %ymm11 + vpslld $7, %ymm5, %ymm5 + vpxor %ymm11, %ymm5, %ymm5 + vpsrld $25, %ymm6, %ymm11 + vpslld $7, %ymm6, %ymm6 + vpxor %ymm11, %ymm6, %ymm6 + vpsrld $25, %ymm7, %ymm11 + vpslld $7, %ymm7, %ymm7 + vpxor %ymm11, %ymm7, %ymm7 + vpaddd %ymm5, %ymm0, %ymm0 + vpxor %ymm0, %ymm15, %ymm15 + vmovdqa 96(%r10), %ymm11 + vpshufb L_chacha20_avx2_rotl16(%rip), %ymm15, %ymm15 + vpaddd %ymm15, %ymm10, %ymm10 + vpxor %ymm10, %ymm5, %ymm5 + vpaddd %ymm6, %ymm1, %ymm1 + vpxor %ymm1, %ymm12, %ymm12 + vpshufb L_chacha20_avx2_rotl16(%rip), %ymm12, %ymm12 + vpaddd %ymm12, %ymm11, %ymm11 + vpxor %ymm11, %ymm6, %ymm6 + vpaddd %ymm7, %ymm2, %ymm2 + vpxor %ymm2, %ymm13, %ymm13 + vpshufb L_chacha20_avx2_rotl16(%rip), %ymm13, %ymm13 + vpaddd %ymm13, %ymm8, %ymm8 + vpxor %ymm8, %ymm7, %ymm7 + vpaddd %ymm4, %ymm3, %ymm3 + vpxor %ymm3, %ymm14, %ymm14 + vpshufb L_chacha20_avx2_rotl16(%rip), %ymm14, %ymm14 + vpaddd %ymm14, %ymm9, %ymm9 + vpxor %ymm9, %ymm4, %ymm4 + vmovdqa %ymm11, 96(%r10) + vpsrld $20, %ymm5, %ymm11 + vpslld $12, %ymm5, %ymm5 + vpxor %ymm11, %ymm5, %ymm5 + vpsrld $20, %ymm6, %ymm11 + vpslld $12, %ymm6, %ymm6 + vpxor %ymm11, %ymm6, %ymm6 + vpsrld $20, %ymm7, %ymm11 + vpslld $12, %ymm7, %ymm7 + vpxor %ymm11, %ymm7, %ymm7 + vpsrld $20, %ymm4, %ymm11 + vpslld $12, %ymm4, %ymm4 + vpxor %ymm11, %ymm4, %ymm4 + vpaddd %ymm5, %ymm0, %ymm0 + vpxor %ymm0, %ymm15, %ymm15 + vmovdqa 96(%r10), %ymm11 + vpshufb L_chacha20_avx2_rotl8(%rip), %ymm15, %ymm15 + vpaddd %ymm15, %ymm10, %ymm10 + vpxor %ymm10, %ymm5, %ymm5 + vpaddd %ymm6, %ymm1, %ymm1 + vpxor %ymm1, %ymm12, %ymm12 + vpshufb L_chacha20_avx2_rotl8(%rip), %ymm12, %ymm12 + vpaddd %ymm12, %ymm11, %ymm11 + vpxor %ymm11, %ymm6, %ymm6 + vpaddd %ymm7, %ymm2, %ymm2 + vpxor %ymm2, %ymm13, %ymm13 + vpshufb L_chacha20_avx2_rotl8(%rip), %ymm13, %ymm13 + vpaddd %ymm13, %ymm8, %ymm8 + vpxor %ymm8, %ymm7, %ymm7 + vpaddd %ymm4, %ymm3, %ymm3 + vpxor %ymm3, %ymm14, %ymm14 + vpshufb L_chacha20_avx2_rotl8(%rip), %ymm14, %ymm14 + vpaddd %ymm14, %ymm9, %ymm9 + vpxor %ymm9, %ymm4, %ymm4 + vmovdqa %ymm11, 96(%r10) + vpsrld $25, %ymm5, %ymm11 + vpslld $7, %ymm5, %ymm5 + vpxor %ymm11, %ymm5, %ymm5 + vpsrld $25, %ymm6, %ymm11 + vpslld $7, %ymm6, %ymm6 + vpxor %ymm11, %ymm6, %ymm6 + vpsrld $25, %ymm7, %ymm11 + vpslld $7, %ymm7, %ymm7 + vpxor %ymm11, %ymm7, %ymm7 + vpsrld $25, %ymm4, %ymm11 + vpslld $7, %ymm4, %ymm4 + vpxor %ymm11, %ymm4, %ymm4 + decb %r8b + jnz L_chacha20_avx2_loop256 + vmovdqa 96(%r10), %ymm11 + vpaddd (%r9), %ymm0, %ymm0 + vpaddd 32(%r9), %ymm1, %ymm1 + vpaddd 64(%r9), %ymm2, %ymm2 + vpaddd 96(%r9), %ymm3, %ymm3 + vpaddd 128(%r9), %ymm4, %ymm4 + vpaddd 160(%r9), %ymm5, %ymm5 + vpaddd 192(%r9), %ymm6, %ymm6 + vpaddd 224(%r9), %ymm7, %ymm7 + vpaddd 256(%r9), %ymm8, %ymm8 + vpaddd 288(%r9), %ymm9, %ymm9 + vpaddd 320(%r9), %ymm10, %ymm10 + vpaddd 352(%r9), %ymm11, %ymm11 + vpaddd 384(%r9), %ymm12, %ymm12 + vpaddd 416(%r9), %ymm13, %ymm13 + vpaddd 448(%r9), %ymm14, %ymm14 + vpaddd 480(%r9), %ymm15, %ymm15 + vmovdqa %ymm8, (%r10) + vmovdqa %ymm9, 32(%r10) + vmovdqa %ymm10, 64(%r10) + vmovdqa %ymm11, 96(%r10) + vmovdqa %ymm12, 128(%r10) + vmovdqa %ymm13, 160(%r10) + vmovdqa %ymm14, 192(%r10) + vmovdqa %ymm15, 224(%r10) + vpunpckldq %ymm1, %ymm0, %ymm8 + vpunpckldq %ymm3, %ymm2, %ymm9 + vpunpckhdq %ymm1, %ymm0, %ymm12 + vpunpckhdq %ymm3, %ymm2, %ymm13 + vpunpckldq %ymm5, %ymm4, %ymm10 + vpunpckldq %ymm7, %ymm6, %ymm11 + vpunpckhdq %ymm5, %ymm4, %ymm14 + vpunpckhdq %ymm7, %ymm6, %ymm15 + vpunpcklqdq %ymm9, %ymm8, %ymm0 + vpunpcklqdq %ymm11, %ymm10, %ymm1 + vpunpckhqdq %ymm9, %ymm8, %ymm2 + vpunpckhqdq %ymm11, %ymm10, %ymm3 + vpunpcklqdq %ymm13, %ymm12, %ymm4 + vpunpcklqdq %ymm15, %ymm14, %ymm5 + vpunpckhqdq %ymm13, %ymm12, %ymm6 + vpunpckhqdq %ymm15, %ymm14, %ymm7 + vperm2i128 $32, %ymm1, %ymm0, %ymm8 + vperm2i128 $32, %ymm3, %ymm2, %ymm9 + vperm2i128 $49, %ymm1, %ymm0, %ymm12 + vperm2i128 $49, %ymm3, %ymm2, %ymm13 + vperm2i128 $32, %ymm5, %ymm4, %ymm10 + vperm2i128 $32, %ymm7, %ymm6, %ymm11 + vperm2i128 $49, %ymm5, %ymm4, %ymm14 + vperm2i128 $49, %ymm7, %ymm6, %ymm15 + vmovdqu (%rsi), %ymm0 + vmovdqu 64(%rsi), %ymm1 + vmovdqu 128(%rsi), %ymm2 + vmovdqu 192(%rsi), %ymm3 + vmovdqu 256(%rsi), %ymm4 + vmovdqu 320(%rsi), %ymm5 + vmovdqu 384(%rsi), %ymm6 + vmovdqu 448(%rsi), %ymm7 + vpxor %ymm0, %ymm8, %ymm8 + vpxor %ymm1, %ymm9, %ymm9 + vpxor %ymm2, %ymm10, %ymm10 + vpxor %ymm3, %ymm11, %ymm11 + vpxor %ymm4, %ymm12, %ymm12 + vpxor %ymm5, %ymm13, %ymm13 + vpxor %ymm6, %ymm14, %ymm14 + vpxor %ymm7, %ymm15, %ymm15 + vmovdqu %ymm8, (%rdx) + vmovdqu %ymm9, 64(%rdx) + vmovdqu %ymm10, 128(%rdx) + vmovdqu %ymm11, 192(%rdx) + vmovdqu %ymm12, 256(%rdx) + vmovdqu %ymm13, 320(%rdx) + vmovdqu %ymm14, 384(%rdx) + vmovdqu %ymm15, 448(%rdx) + vmovdqa (%r10), %ymm0 + vmovdqa 32(%r10), %ymm1 + vmovdqa 64(%r10), %ymm2 + vmovdqa 96(%r10), %ymm3 + vmovdqa 128(%r10), %ymm4 + vmovdqa 160(%r10), %ymm5 + vmovdqa 192(%r10), %ymm6 + vmovdqa 224(%r10), %ymm7 + vpunpckldq %ymm1, %ymm0, %ymm8 + vpunpckldq %ymm3, %ymm2, %ymm9 + vpunpckhdq %ymm1, %ymm0, %ymm12 + vpunpckhdq %ymm3, %ymm2, %ymm13 + vpunpckldq %ymm5, %ymm4, %ymm10 + vpunpckldq %ymm7, %ymm6, %ymm11 + vpunpckhdq %ymm5, %ymm4, %ymm14 + vpunpckhdq %ymm7, %ymm6, %ymm15 + vpunpcklqdq %ymm9, %ymm8, %ymm0 + vpunpcklqdq %ymm11, %ymm10, %ymm1 + vpunpckhqdq %ymm9, %ymm8, %ymm2 + vpunpckhqdq %ymm11, %ymm10, %ymm3 + vpunpcklqdq %ymm13, %ymm12, %ymm4 + vpunpcklqdq %ymm15, %ymm14, %ymm5 + vpunpckhqdq %ymm13, %ymm12, %ymm6 + vpunpckhqdq %ymm15, %ymm14, %ymm7 + vperm2i128 $32, %ymm1, %ymm0, %ymm8 + vperm2i128 $32, %ymm3, %ymm2, %ymm9 + vperm2i128 $49, %ymm1, %ymm0, %ymm12 + vperm2i128 $49, %ymm3, %ymm2, %ymm13 + vperm2i128 $32, %ymm5, %ymm4, %ymm10 + vperm2i128 $32, %ymm7, %ymm6, %ymm11 + vperm2i128 $49, %ymm5, %ymm4, %ymm14 + vperm2i128 $49, %ymm7, %ymm6, %ymm15 + vmovdqu 32(%rsi), %ymm0 + vmovdqu 96(%rsi), %ymm1 + vmovdqu 160(%rsi), %ymm2 + vmovdqu 224(%rsi), %ymm3 + vmovdqu 288(%rsi), %ymm4 + vmovdqu 352(%rsi), %ymm5 + vmovdqu 416(%rsi), %ymm6 + vmovdqu 480(%rsi), %ymm7 + vpxor %ymm0, %ymm8, %ymm8 + vpxor %ymm1, %ymm9, %ymm9 + vpxor %ymm2, %ymm10, %ymm10 + vpxor %ymm3, %ymm11, %ymm11 + vpxor %ymm4, %ymm12, %ymm12 + vpxor %ymm5, %ymm13, %ymm13 + vpxor %ymm6, %ymm14, %ymm14 + vpxor %ymm7, %ymm15, %ymm15 + vmovdqu %ymm8, 32(%rdx) + vmovdqu %ymm9, 96(%rdx) + vmovdqu %ymm10, 160(%rdx) + vmovdqu %ymm11, 224(%rdx) + vmovdqu %ymm12, 288(%rdx) + vmovdqu %ymm13, 352(%rdx) + vmovdqu %ymm14, 416(%rdx) + vmovdqu %ymm15, 480(%rdx) + vmovdqa 384(%r9), %ymm12 + addq $0x200, %rsi + addq $0x200, %rdx + vpaddd L_chacha20_avx2_eight(%rip), %ymm12, %ymm12 + subl $0x200, %ecx + vmovdqa %ymm12, 384(%r9) + cmpl $0x200, %ecx + jl L_chacha20_avx2_done256 + vmovdqa (%r9), %ymm0 + vmovdqa 32(%r9), %ymm1 + vmovdqa 64(%r9), %ymm2 + vmovdqa 96(%r9), %ymm3 + vmovdqa 128(%r9), %ymm4 + vmovdqa 160(%r9), %ymm5 + vmovdqa 192(%r9), %ymm6 + vmovdqa 224(%r9), %ymm7 + vmovdqa 256(%r9), %ymm8 + vmovdqa 288(%r9), %ymm9 + vmovdqa 320(%r9), %ymm10 + vmovdqa 352(%r9), %ymm11 + vmovdqa 384(%r9), %ymm12 + vmovdqa 416(%r9), %ymm13 + vmovdqa 448(%r9), %ymm14 + vmovdqa 480(%r9), %ymm15 + jmp L_chacha20_avx2_start256 +L_chacha20_avx2_done256: + shl $3, %eax + addl %eax, 48(%rdi) +L_chacha20_avx2_end256: +#ifndef __APPLE__ + callq chacha_encrypt_avx1@plt +#else + callq _chacha_encrypt_avx1 +#endif /* __APPLE__ */ + addq $0x310, %rsp + repz retq +#ifndef __APPLE__ +.size chacha_encrypt_avx2,.-chacha_encrypt_avx2 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/cmac.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/cmac.c new file mode 100755 index 0000000..3fd91a5 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/cmac.c @@ -0,0 +1,215 @@ +/* cmac.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#if defined(WOLFSSL_CMAC) && !defined(NO_AES) && defined(WOLFSSL_AES_DIRECT) + +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + + /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ + #define FIPS_NO_WRAPPERS + + #ifdef USE_WINDOWS_API + #pragma code_seg(".fipsA$n") + #pragma const_seg(".fipsB$n") + #endif +#endif + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#include +#include +#include + + +static void ShiftAndXorRb(byte* out, byte* in) +{ + int i, j, xorRb; + int mask = 0, last = 0; + byte Rb = 0x87; + + xorRb = (in[0] & 0x80) != 0; + + for (i = 1, j = AES_BLOCK_SIZE - 1; i <= AES_BLOCK_SIZE; i++, j--) { + last = (in[j] & 0x80) ? 1 : 0; + out[j] = (byte)((in[j] << 1) | mask); + mask = last; + if (xorRb) { + out[j] ^= Rb; + Rb = 0; + } + } +} + + +int wc_InitCmac(Cmac* cmac, const byte* key, word32 keySz, + int type, void* unused) +{ + int ret; + + (void)unused; + + if (cmac == NULL || key == NULL || keySz == 0 || type != WC_CMAC_AES) + return BAD_FUNC_ARG; + + XMEMSET(cmac, 0, sizeof(Cmac)); + ret = wc_AesSetKey(&cmac->aes, key, keySz, NULL, AES_ENCRYPTION); + if (ret == 0) { + byte l[AES_BLOCK_SIZE]; + + XMEMSET(l, 0, AES_BLOCK_SIZE); + wc_AesEncryptDirect(&cmac->aes, l, l); + ShiftAndXorRb(cmac->k1, l); + ShiftAndXorRb(cmac->k2, cmac->k1); + ForceZero(l, AES_BLOCK_SIZE); + } + return ret; +} + + +int wc_CmacUpdate(Cmac* cmac, const byte* in, word32 inSz) +{ + if ((cmac == NULL) || (in == NULL && inSz != 0)) + return BAD_FUNC_ARG; + + while (inSz != 0) { + word32 add = min(inSz, AES_BLOCK_SIZE - cmac->bufferSz); + XMEMCPY(&cmac->buffer[cmac->bufferSz], in, add); + + cmac->bufferSz += add; + in += add; + inSz -= add; + + if (cmac->bufferSz == AES_BLOCK_SIZE && inSz != 0) { + if (cmac->totalSz != 0) + xorbuf(cmac->buffer, cmac->digest, AES_BLOCK_SIZE); + wc_AesEncryptDirect(&cmac->aes, + cmac->digest, + cmac->buffer); + cmac->totalSz += AES_BLOCK_SIZE; + cmac->bufferSz = 0; + } + } + + return 0; +} + + +int wc_CmacFinal(Cmac* cmac, byte* out, word32* outSz) +{ + const byte* subKey; + + if (cmac == NULL || out == NULL || outSz == NULL) + return BAD_FUNC_ARG; + + if (*outSz < WC_CMAC_TAG_MIN_SZ || *outSz > WC_CMAC_TAG_MAX_SZ) + return BUFFER_E; + + if (cmac->bufferSz == AES_BLOCK_SIZE) { + subKey = cmac->k1; + } + else { + word32 remainder = AES_BLOCK_SIZE - cmac->bufferSz; + + if (remainder == 0) + remainder = AES_BLOCK_SIZE; + + if (remainder > 1) + XMEMSET(cmac->buffer + AES_BLOCK_SIZE - remainder, 0, remainder); + cmac->buffer[AES_BLOCK_SIZE - remainder] = 0x80; + subKey = cmac->k2; + } + xorbuf(cmac->buffer, cmac->digest, AES_BLOCK_SIZE); + xorbuf(cmac->buffer, subKey, AES_BLOCK_SIZE); + wc_AesEncryptDirect(&cmac->aes, cmac->digest, cmac->buffer); + + XMEMCPY(out, cmac->digest, *outSz); + + ForceZero(cmac, sizeof(Cmac)); + + return 0; +} + + +int wc_AesCmacGenerate(byte* out, word32* outSz, + const byte* in, word32 inSz, + const byte* key, word32 keySz) +{ + Cmac cmac; + int ret; + + if (out == NULL || (in == NULL && inSz > 0) || key == NULL || keySz == 0) + return BAD_FUNC_ARG; + + ret = wc_InitCmac(&cmac, key, keySz, WC_CMAC_AES, NULL); + if (ret != 0) + return ret; + + ret = wc_CmacUpdate(&cmac, in, inSz); + if (ret != 0) + return ret; + + ret = wc_CmacFinal(&cmac, out, outSz); + if (ret != 0) + return ret; + + return 0; +} + + +int wc_AesCmacVerify(const byte* check, word32 checkSz, + const byte* in, word32 inSz, + const byte* key, word32 keySz) +{ + byte a[AES_BLOCK_SIZE]; + word32 aSz = sizeof(a); + int result; + int compareRet; + + if (check == NULL || checkSz == 0 || (in == NULL && inSz != 0) || + key == NULL || keySz == 0) + + return BAD_FUNC_ARG; + + XMEMSET(a, 0, aSz); + result = wc_AesCmacGenerate(a, &aSz, in, inSz, key, keySz); + compareRet = ConstantCompare(check, a, min(checkSz, aSz)); + + if (result == 0) + result = compareRet ? 1 : 0; + + return result; +} + + +#endif /* WOLFSSL_CMAC && NO_AES && WOLFSSL_AES_DIRECT */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/coding.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/coding.c new file mode 100755 index 0000000..94a85a2 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/coding.c @@ -0,0 +1,460 @@ +/* coding.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifndef NO_CODING + +#include +#include +#include + + +enum { + BAD = 0xFF, /* invalid encoding */ + PAD = '=', + PEM_LINE_SZ = 64, + BASE64_MIN = 0x2B, + BASE16_MIN = 0x30, +}; + + +static +const byte base64Decode[] = { 62, BAD, BAD, BAD, 63, /* + starts at 0x2B */ + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, + BAD, BAD, BAD, BAD, BAD, BAD, BAD, + 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, + BAD, BAD, BAD, BAD, BAD, BAD, + 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 + }; + + +int Base64_Decode(const byte* in, word32 inLen, byte* out, word32* outLen) +{ + word32 i = 0; + word32 j = 0; + word32 plainSz = inLen - ((inLen + (PEM_LINE_SZ - 1)) / PEM_LINE_SZ ); + const byte maxIdx = (byte)sizeof(base64Decode) + BASE64_MIN - 1; + + plainSz = (plainSz * 3 + 3) / 4; + if (plainSz > *outLen) return BAD_FUNC_ARG; + + while (inLen > 3) { + byte b1, b2, b3; + byte e1 = in[j++]; + byte e2 = in[j++]; + byte e3 = in[j++]; + byte e4 = in[j++]; + + int pad3 = 0; + int pad4 = 0; + + if (e1 == 0) /* end file 0's */ + break; + if (e3 == PAD) + pad3 = 1; + if (e4 == PAD) + pad4 = 1; + + if (e1 < BASE64_MIN || e2 < BASE64_MIN || e3 < BASE64_MIN || e4 < BASE64_MIN) { + WOLFSSL_MSG("Bad Base64 Decode data, too small"); + return ASN_INPUT_E; + } + + if (e1 > maxIdx || e2 > maxIdx || e3 > maxIdx || e4 > maxIdx) { + WOLFSSL_MSG("Bad Base64 Decode data, too big"); + return ASN_INPUT_E; + } + + e1 = base64Decode[e1 - BASE64_MIN]; + e2 = base64Decode[e2 - BASE64_MIN]; + e3 = (e3 == PAD) ? 0 : base64Decode[e3 - BASE64_MIN]; + e4 = (e4 == PAD) ? 0 : base64Decode[e4 - BASE64_MIN]; + + b1 = (byte)((e1 << 2) | (e2 >> 4)); + b2 = (byte)(((e2 & 0xF) << 4) | (e3 >> 2)); + b3 = (byte)(((e3 & 0x3) << 6) | e4); + + out[i++] = b1; + if (!pad3) + out[i++] = b2; + if (!pad4) + out[i++] = b3; + else + break; + + inLen -= 4; + if (inLen && (in[j] == ' ' || in[j] == '\r' || in[j] == '\n')) { + byte endLine = in[j++]; + inLen--; + while (inLen && endLine == ' ') { /* allow trailing whitespace */ + endLine = in[j++]; + inLen--; + } + if (endLine == '\r') { + if (inLen) { + endLine = in[j++]; + inLen--; + } + } + if (endLine != '\n') { + WOLFSSL_MSG("Bad end of line in Base64 Decode"); + return ASN_INPUT_E; + } + } + } + *outLen = i; + + return 0; +} + + +#if defined(WOLFSSL_BASE64_ENCODE) + +static +const byte base64Encode[] = { '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', + '+', '/' + }; + + +/* make sure *i (idx) won't exceed max, store and possibly escape to out, + * raw means use e w/o decode, 0 on success */ +static int CEscape(int escaped, byte e, byte* out, word32* i, word32 max, + int raw, int getSzOnly) +{ + int doEscape = 0; + word32 needed = 1; + word32 idx = *i; + + byte basic; + byte plus = 0; + byte equals = 0; + byte newline = 0; + + if (raw) + basic = e; + else + basic = base64Encode[e]; + + /* check whether to escape. Only escape for EncodeEsc */ + if (escaped == WC_ESC_NL_ENC) { + switch ((char)basic) { + case '+' : + plus = 1; + doEscape = 1; + needed += 2; + break; + case '=' : + equals = 1; + doEscape = 1; + needed += 2; + break; + case '\n' : + newline = 1; + doEscape = 1; + needed += 2; + break; + default: + /* do nothing */ + break; + } + } + + /* check size */ + if ( (idx+needed) > max && !getSzOnly) { + WOLFSSL_MSG("Escape buffer max too small"); + return BUFFER_E; + } + + /* store it */ + if (doEscape == 0) { + if(getSzOnly) + idx++; + else + out[idx++] = basic; + } + else { + if(getSzOnly) + idx+=3; + else { + out[idx++] = '%'; /* start escape */ + + if (plus) { + out[idx++] = '2'; + out[idx++] = 'B'; + } + else if (equals) { + out[idx++] = '3'; + out[idx++] = 'D'; + } + else if (newline) { + out[idx++] = '0'; + out[idx++] = 'A'; + } + } + } + *i = idx; + + return 0; +} + + +/* internal worker, handles both escaped and normal line endings. + If out buffer is NULL, will return sz needed in outLen */ +static int DoBase64_Encode(const byte* in, word32 inLen, byte* out, + word32* outLen, int escaped) +{ + int ret = 0; + word32 i = 0, + j = 0, + n = 0; /* new line counter */ + + int getSzOnly = (out == NULL); + + word32 outSz = (inLen + 3 - 1) / 3 * 4; + word32 addSz = (outSz + PEM_LINE_SZ - 1) / PEM_LINE_SZ; /* new lines */ + + if (escaped == WC_ESC_NL_ENC) + addSz *= 3; /* instead of just \n, we're doing %0A triplet */ + else if (escaped == WC_NO_NL_ENC) + addSz = 0; /* encode without \n */ + + outSz += addSz; + + /* if escaped we can't predetermine size for one pass encoding, but + * make sure we have enough if no escapes are in input + * Also need to ensure outLen valid before dereference */ + if (!outLen || (outSz > *outLen && !getSzOnly)) return BAD_FUNC_ARG; + + while (inLen > 2) { + byte b1 = in[j++]; + byte b2 = in[j++]; + byte b3 = in[j++]; + + /* encoded idx */ + byte e1 = b1 >> 2; + byte e2 = (byte)(((b1 & 0x3) << 4) | (b2 >> 4)); + byte e3 = (byte)(((b2 & 0xF) << 2) | (b3 >> 6)); + byte e4 = b3 & 0x3F; + + /* store */ + ret = CEscape(escaped, e1, out, &i, *outLen, 0, getSzOnly); + if (ret != 0) break; + ret = CEscape(escaped, e2, out, &i, *outLen, 0, getSzOnly); + if (ret != 0) break; + ret = CEscape(escaped, e3, out, &i, *outLen, 0, getSzOnly); + if (ret != 0) break; + ret = CEscape(escaped, e4, out, &i, *outLen, 0, getSzOnly); + if (ret != 0) break; + + inLen -= 3; + + /* Insert newline after PEM_LINE_SZ, unless no \n requested */ + if (escaped != WC_NO_NL_ENC && (++n % (PEM_LINE_SZ/4)) == 0 && inLen) { + ret = CEscape(escaped, '\n', out, &i, *outLen, 1, getSzOnly); + if (ret != 0) break; + } + } + + /* last integral */ + if (inLen && ret == 0) { + int twoBytes = (inLen == 2); + + byte b1 = in[j++]; + byte b2 = (twoBytes) ? in[j++] : 0; + + byte e1 = b1 >> 2; + byte e2 = (byte)(((b1 & 0x3) << 4) | (b2 >> 4)); + byte e3 = (byte)((b2 & 0xF) << 2); + + ret = CEscape(escaped, e1, out, &i, *outLen, 0, getSzOnly); + if (ret == 0) + ret = CEscape(escaped, e2, out, &i, *outLen, 0, getSzOnly); + if (ret == 0) { + /* third */ + if (twoBytes) + ret = CEscape(escaped, e3, out, &i, *outLen, 0, getSzOnly); + else + ret = CEscape(escaped, '=', out, &i, *outLen, 1, getSzOnly); + } + /* fourth always pad */ + if (ret == 0) + ret = CEscape(escaped, '=', out, &i, *outLen, 1, getSzOnly); + } + + if (ret == 0 && escaped != WC_NO_NL_ENC) + ret = CEscape(escaped, '\n', out, &i, *outLen, 1, getSzOnly); + + if (i != outSz && escaped != 1 && ret == 0) + return ASN_INPUT_E; + + *outLen = i; + if(ret == 0) + return getSzOnly ? LENGTH_ONLY_E : 0; + return ret; +} + + +/* Base64 Encode, PEM style, with \n line endings */ +int Base64_Encode(const byte* in, word32 inLen, byte* out, word32* outLen) +{ + return DoBase64_Encode(in, inLen, out, outLen, WC_STD_ENC); +} + + +/* Base64 Encode, with %0A escaped line endings instead of \n */ +int Base64_EncodeEsc(const byte* in, word32 inLen, byte* out, word32* outLen) +{ + return DoBase64_Encode(in, inLen, out, outLen, WC_ESC_NL_ENC); +} + +int Base64_Encode_NoNl(const byte* in, word32 inLen, byte* out, word32* outLen) +{ + return DoBase64_Encode(in, inLen, out, outLen, WC_NO_NL_ENC); +} + +#endif /* WOLFSSL_BASE64_ENCODE */ + + +#ifdef WOLFSSL_BASE16 + +static +const byte hexDecode[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + BAD, BAD, BAD, BAD, BAD, BAD, BAD, + 10, 11, 12, 13, 14, 15, /* upper case A-F */ + BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, + BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, + BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD, + BAD, BAD, /* G - ` */ + 10, 11, 12, 13, 14, 15 /* lower case a-f */ + }; /* A starts at 0x41 not 0x3A */ + +int Base16_Decode(const byte* in, word32 inLen, byte* out, word32* outLen) +{ + word32 inIdx = 0; + word32 outIdx = 0; + + if (in == NULL || out == NULL || outLen == NULL) + return BAD_FUNC_ARG; + + if (inLen == 1 && *outLen && in) { + byte b = in[inIdx++] - BASE16_MIN; /* 0 starts at 0x30 */ + + /* sanity check */ + if (b >= sizeof(hexDecode)/sizeof(hexDecode[0])) + return ASN_INPUT_E; + + b = hexDecode[b]; + + if (b == BAD) + return ASN_INPUT_E; + + out[outIdx++] = b; + + *outLen = outIdx; + return 0; + } + + if (inLen % 2) + return BAD_FUNC_ARG; + + if (*outLen < (inLen / 2)) + return BAD_FUNC_ARG; + + while (inLen) { + byte b = in[inIdx++] - BASE16_MIN; /* 0 starts at 0x30 */ + byte b2 = in[inIdx++] - BASE16_MIN; + + /* sanity checks */ + if (b >= sizeof(hexDecode)/sizeof(hexDecode[0])) + return ASN_INPUT_E; + if (b2 >= sizeof(hexDecode)/sizeof(hexDecode[0])) + return ASN_INPUT_E; + + b = hexDecode[b]; + b2 = hexDecode[b2]; + + if (b == BAD || b2 == BAD) + return ASN_INPUT_E; + + out[outIdx++] = (byte)((b << 4) | b2); + inLen -= 2; + } + + *outLen = outIdx; + return 0; +} + +int Base16_Encode(const byte* in, word32 inLen, byte* out, word32* outLen) +{ + word32 outIdx = 0; + word32 i; + byte hb, lb; + + if (in == NULL || out == NULL || outLen == NULL) + return BAD_FUNC_ARG; + + if (*outLen < (2 * inLen + 1)) + return BAD_FUNC_ARG; + + for (i = 0; i < inLen; i++) { + hb = in[i] >> 4; + lb = in[i] & 0x0f; + + /* ASCII value */ + hb += '0'; + if (hb > '9') + hb += 7; + + /* ASCII value */ + lb += '0'; + if (lb>'9') + lb += 7; + + out[outIdx++] = hb; + out[outIdx++] = lb; + } + + /* force 0 at this end */ + out[outIdx++] = 0; + + *outLen = outIdx; + return 0; +} + +#endif /* WOLFSSL_BASE16 */ + +#endif /* !NO_CODING */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/compress.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/compress.c new file mode 100755 index 0000000..2eb92f4 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/compress.c @@ -0,0 +1,198 @@ +/* compress.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifdef HAVE_LIBZ + + +#include +#include +#include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#include + + +/* alloc user allocs to work with zlib */ +static void* myAlloc(void* opaque, unsigned int item, unsigned int size) +{ + (void)opaque; + return XMALLOC(item * size, opaque, DYNAMIC_TYPE_LIBZ); +} + + +static void myFree(void* opaque, void* memory) +{ + (void)opaque; + XFREE(memory, opaque, DYNAMIC_TYPE_LIBZ); +} + + +#ifdef HAVE_MCAPI + #define DEFLATE_DEFAULT_WINDOWBITS 11 + #define DEFLATE_DEFAULT_MEMLEVEL 1 +#else + #define DEFLATE_DEFAULT_WINDOWBITS 15 + #define DEFLATE_DEFAULT_MEMLEVEL 8 +#endif + + +/* + * out - pointer to destination buffer + * outSz - size of destination buffer + * in - pointer to source buffer to compress + * inSz - size of source to compress + * flags - flags to control how compress operates + * + * return: + * negative - error code + * positive - bytes stored in out buffer + * + * Note, the output buffer still needs to be larger than the input buffer. + * The right chunk of data won't compress at all, and the lookup table will + * add to the size of the output. The libz code says the compressed + * buffer should be srcSz + 0.1% + 12. + */ +int wc_Compress_ex(byte* out, word32 outSz, const byte* in, word32 inSz, + word32 flags, word32 windowBits) +{ + z_stream stream; + int result = 0; + + stream.next_in = (Bytef*)in; + stream.avail_in = (uInt)inSz; +#ifdef MAXSEG_64K + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != inSz) return COMPRESS_INIT_E; +#endif + stream.next_out = out; + stream.avail_out = (uInt)outSz; + if ((uLong)stream.avail_out != outSz) return COMPRESS_INIT_E; + + stream.zalloc = (alloc_func)myAlloc; + stream.zfree = (free_func)myFree; + stream.opaque = (voidpf)0; + + if (deflateInit2(&stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, + DEFLATE_DEFAULT_WINDOWBITS | windowBits, + DEFLATE_DEFAULT_MEMLEVEL, + flags ? Z_FIXED : Z_DEFAULT_STRATEGY) != Z_OK) + return COMPRESS_INIT_E; + + if (deflate(&stream, Z_FINISH) != Z_STREAM_END) { + deflateEnd(&stream); + return COMPRESS_E; + } + + result = (int)stream.total_out; + + if (deflateEnd(&stream) != Z_OK) + result = COMPRESS_E; + + return result; +} + +int wc_Compress(byte* out, word32 outSz, const byte* in, word32 inSz, word32 flags) +{ + return wc_Compress_ex(out, outSz, in, inSz, flags, 0); +} + + +/* windowBits: +* deflateInit() and inflateInit(), as well as deflateInit2() and inflateInit2() + with windowBits in 0..15 all process zlib-wrapped deflate data. + (See RFC 1950 and RFC 1951.) +* deflateInit2() and inflateInit2() with negative windowBits in -1..-15 process + raw deflate data with no header or trailer. +* deflateInit2() and inflateInit2() with windowBits in 16..31, i.e. 16 + added to 0..15, process gzip-wrapped deflate data (RFC 1952). +* inflateInit2() with windowBits in 32..47 (32 added to 0..15) will + automatically detect either a gzip or zlib header (but not raw deflate + data), and decompress accordingly. +*/ +int wc_DeCompress_ex(byte* out, word32 outSz, const byte* in, word32 inSz, + int windowBits) +/* + * out - pointer to destination buffer + * outSz - size of destination buffer + * in - pointer to source buffer to compress + * inSz - size of source to compress + * windowBits - flags to control how decompress operates + * + * return: + * negative - error code + * positive - bytes stored in out buffer + */ +{ + z_stream stream; + int result = 0; + + stream.next_in = (Bytef*)in; + stream.avail_in = (uInt)inSz; + /* Check for source > 64K on 16-bit machine: */ + if ((uLong)stream.avail_in != inSz) return DECOMPRESS_INIT_E; + + stream.next_out = out; + stream.avail_out = (uInt)outSz; + if ((uLong)stream.avail_out != outSz) return DECOMPRESS_INIT_E; + + stream.zalloc = (alloc_func)myAlloc; + stream.zfree = (free_func)myFree; + stream.opaque = (voidpf)0; + + if (inflateInit2(&stream, DEFLATE_DEFAULT_WINDOWBITS | windowBits) != Z_OK) + return DECOMPRESS_INIT_E; + + result = inflate(&stream, Z_FINISH); + if (result != Z_STREAM_END) { + inflateEnd(&stream); + return DECOMPRESS_E; + } + + result = (int)stream.total_out; + + if (inflateEnd(&stream) != Z_OK) + result = DECOMPRESS_E; + + return result; +} + + +int wc_DeCompress(byte* out, word32 outSz, const byte* in, word32 inSz) +{ + return wc_DeCompress_ex(out, outSz, in, inSz, 0); +} + + +#endif /* HAVE_LIBZ */ + diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/cpuid.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/cpuid.c new file mode 100755 index 0000000..2613a1b --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/cpuid.c @@ -0,0 +1,110 @@ +/* cpuid.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#include + +#if (defined(WOLFSSL_X86_64_BUILD) || defined(USE_INTEL_SPEEDUP) || \ + defined(WOLFSSL_AESNI)) && !defined(WOLFSSL_NO_ASM) + /* Each platform needs to query info type 1 from cpuid to see if aesni is + * supported. Also, let's setup a macro for proper linkage w/o ABI conflicts + */ + + #ifndef _MSC_VER + #define cpuid(reg, leaf, sub)\ + __asm__ __volatile__ ("cpuid":\ + "=a" (reg[0]), "=b" (reg[1]), "=c" (reg[2]), "=d" (reg[3]) :\ + "a" (leaf), "c"(sub)); + + #define XASM_LINK(f) asm(f) + #else + #include + + #define cpuid(a,b,c) __cpuidex((int*)a,b,c) + + #define XASM_LINK(f) + #endif /* _MSC_VER */ + + #define EAX 0 + #define EBX 1 + #define ECX 2 + #define EDX 3 + + static word32 cpuid_check = 0; + static word32 cpuid_flags = 0; + + static word32 cpuid_flag(word32 leaf, word32 sub, word32 num, word32 bit) + { + int got_intel_cpu = 0; + int got_amd_cpu = 0; + unsigned int reg[5]; + reg[4] = '\0'; + cpuid(reg, 0, 0); + + /* check for Intel cpu */ + if (XMEMCMP((char *)&(reg[EBX]), "Genu", 4) == 0 && + XMEMCMP((char *)&(reg[EDX]), "ineI", 4) == 0 && + XMEMCMP((char *)&(reg[ECX]), "ntel", 4) == 0) { + got_intel_cpu = 1; + } + + /* check for AMD cpu */ + if (XMEMCMP((char *)&(reg[EBX]), "Auth", 4) == 0 && + XMEMCMP((char *)&(reg[EDX]), "enti", 4) == 0 && + XMEMCMP((char *)&(reg[ECX]), "cAMD", 4) == 0) { + got_amd_cpu = 1; + } + + if (got_intel_cpu || got_amd_cpu) { + cpuid(reg, leaf, sub); + return ((reg[num] >> bit) & 0x1); + } + return 0; + } + + + void cpuid_set_flags(void) + { + if (!cpuid_check) { + if (cpuid_flag(1, 0, ECX, 28)) { cpuid_flags |= CPUID_AVX1 ; } + if (cpuid_flag(7, 0, EBX, 5)) { cpuid_flags |= CPUID_AVX2 ; } + if (cpuid_flag(7, 0, EBX, 8)) { cpuid_flags |= CPUID_BMI2 ; } + if (cpuid_flag(1, 0, ECX, 30)) { cpuid_flags |= CPUID_RDRAND; } + if (cpuid_flag(7, 0, EBX, 18)) { cpuid_flags |= CPUID_RDSEED; } + if (cpuid_flag(1, 0, ECX, 26)) { cpuid_flags |= CPUID_AESNI ; } + if (cpuid_flag(7, 0, EBX, 19)) { cpuid_flags |= CPUID_ADX ; } + cpuid_check = 1; + } + } + + word32 cpuid_get_flags(void) + { + if (!cpuid_check) + cpuid_set_flags(); + return cpuid_flags; + } +#endif diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/cryptocb.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/cryptocb.c new file mode 100755 index 0000000..5e7c8fb --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/cryptocb.c @@ -0,0 +1,648 @@ +/* cryptocb.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/* This framework provides a central place for crypto hardware integration + using the devId scheme. If not supported return `CRYPTOCB_UNAVAILABLE`. */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifdef WOLF_CRYPTO_CB + +#include +#include +#include + + +/* TODO: Consider linked list with mutex */ +#ifndef MAX_CRYPTO_DEVID_CALLBACKS +#define MAX_CRYPTO_DEVID_CALLBACKS 8 +#endif + +typedef struct CryptoCb { + int devId; + CryptoDevCallbackFunc cb; + void* ctx; +} CryptoCb; +static CryptoCb gCryptoDev[MAX_CRYPTO_DEVID_CALLBACKS]; + +static CryptoCb* wc_CryptoCb_FindDevice(int devId) +{ + int i; + for (i=0; idevId = devId; + dev->cb = cb; + dev->ctx = ctx; + + return 0; +} + +void wc_CryptoCb_UnRegisterDevice(int devId) +{ + CryptoCb* dev = wc_CryptoCb_FindDevice(devId); + if (dev) { + XMEMSET(dev, 0, sizeof(*dev)); + dev->devId = INVALID_DEVID; + } +} + +#ifndef NO_RSA +int wc_CryptoCb_Rsa(const byte* in, word32 inLen, byte* out, + word32* outLen, int type, RsaKey* key, WC_RNG* rng) +{ + int ret = CRYPTOCB_UNAVAILABLE; + CryptoCb* dev; + + if (key == NULL) + return ret; + + /* locate registered callback */ + dev = wc_CryptoCb_FindDevice(key->devId); + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_PK; + cryptoInfo.pk.type = WC_PK_TYPE_RSA; + cryptoInfo.pk.rsa.in = in; + cryptoInfo.pk.rsa.inLen = inLen; + cryptoInfo.pk.rsa.out = out; + cryptoInfo.pk.rsa.outLen = outLen; + cryptoInfo.pk.rsa.type = type; + cryptoInfo.pk.rsa.key = key; + cryptoInfo.pk.rsa.rng = rng; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} + +#ifdef WOLFSSL_KEY_GEN +int wc_CryptoCb_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) +{ + int ret = CRYPTOCB_UNAVAILABLE; + CryptoCb* dev; + + if (key == NULL) + return ret; + + /* locate registered callback */ + dev = wc_CryptoCb_FindDevice(key->devId); + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_PK; + cryptoInfo.pk.type = WC_PK_TYPE_RSA_KEYGEN; + cryptoInfo.pk.rsakg.key = key; + cryptoInfo.pk.rsakg.size = size; + cryptoInfo.pk.rsakg.e = e; + cryptoInfo.pk.rsakg.rng = rng; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} +#endif +#endif /* !NO_RSA */ + +#ifdef HAVE_ECC +int wc_CryptoCb_MakeEccKey(WC_RNG* rng, int keySize, ecc_key* key, int curveId) +{ + int ret = CRYPTOCB_UNAVAILABLE; + CryptoCb* dev; + + if (key == NULL) + return ret; + + /* locate registered callback */ + dev = wc_CryptoCb_FindDevice(key->devId); + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_PK; + cryptoInfo.pk.type = WC_PK_TYPE_EC_KEYGEN; + cryptoInfo.pk.eckg.rng = rng; + cryptoInfo.pk.eckg.size = keySize; + cryptoInfo.pk.eckg.key = key; + cryptoInfo.pk.eckg.curveId = curveId; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} + +int wc_CryptoCb_Ecdh(ecc_key* private_key, ecc_key* public_key, + byte* out, word32* outlen) +{ + int ret = CRYPTOCB_UNAVAILABLE; + CryptoCb* dev; + + if (private_key == NULL) + return ret; + + /* locate registered callback */ + dev = wc_CryptoCb_FindDevice(private_key->devId); + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_PK; + cryptoInfo.pk.type = WC_PK_TYPE_ECDH; + cryptoInfo.pk.ecdh.private_key = private_key; + cryptoInfo.pk.ecdh.public_key = public_key; + cryptoInfo.pk.ecdh.out = out; + cryptoInfo.pk.ecdh.outlen = outlen; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} + +int wc_CryptoCb_EccSign(const byte* in, word32 inlen, byte* out, + word32 *outlen, WC_RNG* rng, ecc_key* key) +{ + int ret = CRYPTOCB_UNAVAILABLE; + CryptoCb* dev; + + if (key == NULL) + return ret; + + /* locate registered callback */ + dev = wc_CryptoCb_FindDevice(key->devId); + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_PK; + cryptoInfo.pk.type = WC_PK_TYPE_ECDSA_SIGN; + cryptoInfo.pk.eccsign.in = in; + cryptoInfo.pk.eccsign.inlen = inlen; + cryptoInfo.pk.eccsign.out = out; + cryptoInfo.pk.eccsign.outlen = outlen; + cryptoInfo.pk.eccsign.rng = rng; + cryptoInfo.pk.eccsign.key = key; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} + +int wc_CryptoCb_EccVerify(const byte* sig, word32 siglen, + const byte* hash, word32 hashlen, int* res, ecc_key* key) +{ + int ret = CRYPTOCB_UNAVAILABLE; + CryptoCb* dev; + + if (key == NULL) + return ret; + + /* locate registered callback */ + dev = wc_CryptoCb_FindDevice(key->devId); + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_PK; + cryptoInfo.pk.type = WC_PK_TYPE_ECDSA_VERIFY; + cryptoInfo.pk.eccverify.sig = sig; + cryptoInfo.pk.eccverify.siglen = siglen; + cryptoInfo.pk.eccverify.hash = hash; + cryptoInfo.pk.eccverify.hashlen = hashlen; + cryptoInfo.pk.eccverify.res = res; + cryptoInfo.pk.eccverify.key = key; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} +#endif /* HAVE_ECC */ + +#ifndef NO_AES +#ifdef HAVE_AESGCM +int wc_CryptoCb_AesGcmEncrypt(Aes* aes, byte* out, + const byte* in, word32 sz, + const byte* iv, word32 ivSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) +{ + int ret = CRYPTOCB_UNAVAILABLE; + CryptoCb* dev; + + /* locate registered callback */ + if (aes) { + dev = wc_CryptoCb_FindDevice(aes->devId); + } + else { + /* locate first callback and try using it */ + dev = wc_CryptoCb_FindDeviceByIndex(0); + } + + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_CIPHER; + cryptoInfo.cipher.type = WC_CIPHER_AES_GCM; + cryptoInfo.cipher.enc = 1; + cryptoInfo.cipher.aesgcm_enc.aes = aes; + cryptoInfo.cipher.aesgcm_enc.out = out; + cryptoInfo.cipher.aesgcm_enc.in = in; + cryptoInfo.cipher.aesgcm_enc.sz = sz; + cryptoInfo.cipher.aesgcm_enc.iv = iv; + cryptoInfo.cipher.aesgcm_enc.ivSz = ivSz; + cryptoInfo.cipher.aesgcm_enc.authTag = authTag; + cryptoInfo.cipher.aesgcm_enc.authTagSz = authTagSz; + cryptoInfo.cipher.aesgcm_enc.authIn = authIn; + cryptoInfo.cipher.aesgcm_enc.authInSz = authInSz; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} + +int wc_CryptoCb_AesGcmDecrypt(Aes* aes, byte* out, + const byte* in, word32 sz, + const byte* iv, word32 ivSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz) +{ + int ret = CRYPTOCB_UNAVAILABLE; + CryptoCb* dev; + + /* locate registered callback */ + if (aes) { + dev = wc_CryptoCb_FindDevice(aes->devId); + } + else { + /* locate first callback and try using it */ + dev = wc_CryptoCb_FindDeviceByIndex(0); + } + + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_CIPHER; + cryptoInfo.cipher.type = WC_CIPHER_AES_GCM; + cryptoInfo.cipher.enc = 0; + cryptoInfo.cipher.aesgcm_dec.aes = aes; + cryptoInfo.cipher.aesgcm_dec.out = out; + cryptoInfo.cipher.aesgcm_dec.in = in; + cryptoInfo.cipher.aesgcm_dec.sz = sz; + cryptoInfo.cipher.aesgcm_dec.iv = iv; + cryptoInfo.cipher.aesgcm_dec.ivSz = ivSz; + cryptoInfo.cipher.aesgcm_dec.authTag = authTag; + cryptoInfo.cipher.aesgcm_dec.authTagSz = authTagSz; + cryptoInfo.cipher.aesgcm_dec.authIn = authIn; + cryptoInfo.cipher.aesgcm_dec.authInSz = authInSz; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} +#endif /* HAVE_AESGCM */ + +#ifdef HAVE_AES_CBC +int wc_CryptoCb_AesCbcEncrypt(Aes* aes, byte* out, + const byte* in, word32 sz) +{ + int ret = CRYPTOCB_UNAVAILABLE; + CryptoCb* dev; + + /* locate registered callback */ + if (aes) { + dev = wc_CryptoCb_FindDevice(aes->devId); + } + else { + /* locate first callback and try using it */ + dev = wc_CryptoCb_FindDeviceByIndex(0); + } + + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_CIPHER; + cryptoInfo.cipher.type = WC_CIPHER_AES_CBC; + cryptoInfo.cipher.enc = 1; + cryptoInfo.cipher.aescbc.aes = aes; + cryptoInfo.cipher.aescbc.out = out; + cryptoInfo.cipher.aescbc.in = in; + cryptoInfo.cipher.aescbc.sz = sz; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} + +int wc_CryptoCb_AesCbcDecrypt(Aes* aes, byte* out, + const byte* in, word32 sz) +{ + int ret = CRYPTOCB_UNAVAILABLE; + CryptoCb* dev; + + /* locate registered callback */ + if (aes) { + dev = wc_CryptoCb_FindDevice(aes->devId); + } + else { + /* locate first callback and try using it */ + dev = wc_CryptoCb_FindDeviceByIndex(0); + } + + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_CIPHER; + cryptoInfo.cipher.type = WC_CIPHER_AES_CBC; + cryptoInfo.cipher.enc = 0; + cryptoInfo.cipher.aescbc.aes = aes; + cryptoInfo.cipher.aescbc.out = out; + cryptoInfo.cipher.aescbc.in = in; + cryptoInfo.cipher.aescbc.sz = sz; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} +#endif /* HAVE_AES_CBC */ +#endif /* !NO_AES */ + +#ifndef NO_DES3 +int wc_CryptoCb_Des3Encrypt(Des3* des3, byte* out, + const byte* in, word32 sz) +{ + int ret = CRYPTOCB_UNAVAILABLE; + CryptoCb* dev; + + /* locate registered callback */ + if (des3) { + dev = wc_CryptoCb_FindDevice(des3->devId); + } + else { + /* locate first callback and try using it */ + dev = wc_CryptoCb_FindDeviceByIndex(0); + } + + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_CIPHER; + cryptoInfo.cipher.type = WC_CIPHER_DES3; + cryptoInfo.cipher.enc = 1; + cryptoInfo.cipher.des3.des = des3; + cryptoInfo.cipher.des3.out = out; + cryptoInfo.cipher.des3.in = in; + cryptoInfo.cipher.des3.sz = sz; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} + +int wc_CryptoCb_Des3Decrypt(Des3* des3, byte* out, + const byte* in, word32 sz) +{ + int ret = CRYPTOCB_UNAVAILABLE; + CryptoCb* dev; + + /* locate registered callback */ + if (des3) { + dev = wc_CryptoCb_FindDevice(des3->devId); + } + else { + /* locate first callback and try using it */ + dev = wc_CryptoCb_FindDeviceByIndex(0); + } + + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_CIPHER; + cryptoInfo.cipher.type = WC_CIPHER_DES3; + cryptoInfo.cipher.enc = 0; + cryptoInfo.cipher.des3.des = des3; + cryptoInfo.cipher.des3.out = out; + cryptoInfo.cipher.des3.in = in; + cryptoInfo.cipher.des3.sz = sz; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} +#endif /* !NO_DES3 */ + +#ifndef NO_SHA +int wc_CryptoCb_ShaHash(wc_Sha* sha, const byte* in, + word32 inSz, byte* digest) +{ + int ret = CRYPTOCB_UNAVAILABLE; + CryptoCb* dev; + + /* locate registered callback */ + if (sha) { + dev = wc_CryptoCb_FindDevice(sha->devId); + } + else { + /* locate first callback and try using it */ + dev = wc_CryptoCb_FindDeviceByIndex(0); + } + + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_HASH; + cryptoInfo.hash.type = WC_HASH_TYPE_SHA; + cryptoInfo.hash.sha1 = sha; + cryptoInfo.hash.in = in; + cryptoInfo.hash.inSz = inSz; + cryptoInfo.hash.digest = digest; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} +#endif /* !NO_SHA */ + +#ifndef NO_SHA256 +int wc_CryptoCb_Sha256Hash(wc_Sha256* sha256, const byte* in, + word32 inSz, byte* digest) +{ + int ret = CRYPTOCB_UNAVAILABLE; + CryptoCb* dev; + + /* locate registered callback */ + if (sha256) { + dev = wc_CryptoCb_FindDevice(sha256->devId); + } + else { + /* locate first callback and try using it */ + dev = wc_CryptoCb_FindDeviceByIndex(0); + } + + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_HASH; + cryptoInfo.hash.type = WC_HASH_TYPE_SHA256; + cryptoInfo.hash.sha256 = sha256; + cryptoInfo.hash.in = in; + cryptoInfo.hash.inSz = inSz; + cryptoInfo.hash.digest = digest; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} +#endif /* !NO_SHA256 */ + +#ifndef NO_HMAC +int wc_CryptoCb_Hmac(Hmac* hmac, int macType, const byte* in, word32 inSz, + byte* digest) +{ + int ret = CRYPTOCB_UNAVAILABLE; + CryptoCb* dev; + + if (hmac == NULL) + return ret; + + /* locate registered callback */ + dev = wc_CryptoCb_FindDevice(hmac->devId); + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_HMAC; + cryptoInfo.hmac.macType = macType; + cryptoInfo.hmac.in = in; + cryptoInfo.hmac.inSz = inSz; + cryptoInfo.hmac.digest = digest; + cryptoInfo.hmac.hmac = hmac; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} +#endif /* !NO_HMAC */ + +#ifndef WC_NO_RNG +int wc_CryptoCb_RandomBlock(WC_RNG* rng, byte* out, word32 sz) +{ + int ret = CRYPTOCB_UNAVAILABLE; + CryptoCb* dev; + + /* locate registered callback */ + if (rng) { + dev = wc_CryptoCb_FindDevice(rng->devId); + } + else { + /* locate first callback and try using it */ + dev = wc_CryptoCb_FindDeviceByIndex(0); + } + + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_RNG; + cryptoInfo.rng.rng = rng; + cryptoInfo.rng.out = out; + cryptoInfo.rng.sz = sz; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} + +int wc_CryptoCb_RandomSeed(OS_Seed* os, byte* seed, word32 sz) +{ + int ret = CRYPTOCB_UNAVAILABLE; + CryptoCb* dev; + + /* locate registered callback */ + dev = wc_CryptoCb_FindDevice(os->devId); + if (dev && dev->cb) { + wc_CryptoInfo cryptoInfo; + XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); + cryptoInfo.algo_type = WC_ALGO_TYPE_SEED; + cryptoInfo.seed.os = os; + cryptoInfo.seed.seed = seed; + cryptoInfo.seed.sz = sz; + + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + } + + return wc_CryptoCb_TranslateErrorCode(ret); +} +#endif /* !WC_NO_RNG */ + +#endif /* WOLF_CRYPTO_CB */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/curve25519.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/curve25519.c new file mode 100755 index 0000000..741c55e --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/curve25519.c @@ -0,0 +1,455 @@ +/* curve25519.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + /* Based On Daniel J Bernstein's curve25519 Public Domain ref10 work. */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifdef HAVE_CURVE25519 + +#include +#include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#if defined(FREESCALE_LTC_ECC) + #include +#endif + +const curve25519_set_type curve25519_sets[] = { + { + CURVE25519_KEYSIZE, + "CURVE25519", + } +}; + +int wc_curve25519_make_key(WC_RNG* rng, int keysize, curve25519_key* key) +{ +#ifdef FREESCALE_LTC_ECC + const ECPoint* basepoint = wc_curve25519_GetBasePoint(); +#else + unsigned char basepoint[CURVE25519_KEYSIZE] = {9}; +#endif + int ret; + + if (key == NULL || rng == NULL) + return BAD_FUNC_ARG; + + /* currently only a key size of 32 bytes is used */ + if (keysize != CURVE25519_KEYSIZE) + return ECC_BAD_ARG_E; + +#ifndef FREESCALE_LTC_ECC + fe_init(); +#endif + + /* random number for private key */ + ret = wc_RNG_GenerateBlock(rng, key->k.point, keysize); + if (ret != 0) + return ret; + + /* Clamp the private key */ + key->k.point[0] &= 248; + key->k.point[CURVE25519_KEYSIZE-1] &= 63; /* same &=127 because |=64 after */ + key->k.point[CURVE25519_KEYSIZE-1] |= 64; + + /* compute public key */ + #ifdef FREESCALE_LTC_ECC + ret = wc_curve25519(&key->p, key->k.point, basepoint, kLTC_Weierstrass); /* input basepoint on Weierstrass curve */ + #else + ret = curve25519(key->p.point, key->k.point, basepoint); + #endif + if (ret != 0) { + ForceZero(key->k.point, keysize); + ForceZero(key->p.point, keysize); + return ret; + } + + return ret; +} + +#ifdef HAVE_CURVE25519_SHARED_SECRET + +int wc_curve25519_shared_secret(curve25519_key* private_key, + curve25519_key* public_key, + byte* out, word32* outlen) +{ + return wc_curve25519_shared_secret_ex(private_key, public_key, + out, outlen, EC25519_BIG_ENDIAN); +} + +int wc_curve25519_shared_secret_ex(curve25519_key* private_key, + curve25519_key* public_key, + byte* out, word32* outlen, int endian) +{ + #ifdef FREESCALE_LTC_ECC + ECPoint o = {{0}}; + #else + unsigned char o[CURVE25519_KEYSIZE]; + #endif + int ret = 0; + + /* sanity check */ + if (private_key == NULL || public_key == NULL || + out == NULL || outlen == NULL || *outlen < CURVE25519_KEYSIZE) + return BAD_FUNC_ARG; + + /* avoid implementation fingerprinting */ + if (public_key->p.point[CURVE25519_KEYSIZE-1] > 0x7F) + return ECC_BAD_ARG_E; + + #ifdef FREESCALE_LTC_ECC + ret = wc_curve25519(&o, private_key->k.point, &public_key->p, kLTC_Curve25519 /* input point P on Curve25519 */); + #else + ret = curve25519(o, private_key->k.point, public_key->p.point); + #endif + if (ret != 0) { + #ifdef FREESCALE_LTC_ECC + ForceZero(o.point, CURVE25519_KEYSIZE); + ForceZero(o.pointY, CURVE25519_KEYSIZE); + #else + ForceZero(o, CURVE25519_KEYSIZE); + #endif + return ret; + } + + if (endian == EC25519_BIG_ENDIAN) { + int i; + /* put shared secret key in Big Endian format */ + for (i = 0; i < CURVE25519_KEYSIZE; i++) + #ifdef FREESCALE_LTC_ECC + out[i] = o.point[CURVE25519_KEYSIZE - i -1]; + #else + out[i] = o[CURVE25519_KEYSIZE - i -1]; + #endif + } + else /* put shared secret key in Little Endian format */ + #ifdef FREESCALE_LTC_ECC + XMEMCPY(out, o.point, CURVE25519_KEYSIZE); + #else + XMEMCPY(out, o, CURVE25519_KEYSIZE); + #endif + + *outlen = CURVE25519_KEYSIZE; + + #ifdef FREESCALE_LTC_ECC + ForceZero(o.point, CURVE25519_KEYSIZE); + ForceZero(o.pointY, CURVE25519_KEYSIZE); + #else + ForceZero(o, CURVE25519_KEYSIZE); + #endif + + return ret; +} + +#endif /* HAVE_CURVE25519_SHARED_SECRET */ + +#ifdef HAVE_CURVE25519_KEY_EXPORT + +/* export curve25519 public key (Big endian) + * return 0 on success */ +int wc_curve25519_export_public(curve25519_key* key, byte* out, word32* outLen) +{ + return wc_curve25519_export_public_ex(key, out, outLen, EC25519_BIG_ENDIAN); +} + +/* export curve25519 public key (Big or Little endian) + * return 0 on success */ +int wc_curve25519_export_public_ex(curve25519_key* key, byte* out, + word32* outLen, int endian) +{ + if (key == NULL || out == NULL || outLen == NULL) + return BAD_FUNC_ARG; + + /* check and set outgoing key size */ + if (*outLen < CURVE25519_KEYSIZE) { + *outLen = CURVE25519_KEYSIZE; + return ECC_BAD_ARG_E; + } + *outLen = CURVE25519_KEYSIZE; + + if (endian == EC25519_BIG_ENDIAN) { + int i; + + /* read keys in Big Endian format */ + for (i = 0; i < CURVE25519_KEYSIZE; i++) + out[i] = key->p.point[CURVE25519_KEYSIZE - i - 1]; + } + else + XMEMCPY(out, key->p.point, CURVE25519_KEYSIZE); + + return 0; +} + +#endif /* HAVE_CURVE25519_KEY_EXPORT */ + +#ifdef HAVE_CURVE25519_KEY_IMPORT + +/* import curve25519 public key (Big endian) + * return 0 on success */ +int wc_curve25519_import_public(const byte* in, word32 inLen, + curve25519_key* key) +{ + return wc_curve25519_import_public_ex(in, inLen, key, EC25519_BIG_ENDIAN); +} + +/* import curve25519 public key (Big or Little endian) + * return 0 on success */ +int wc_curve25519_import_public_ex(const byte* in, word32 inLen, + curve25519_key* key, int endian) +{ + /* sanity check */ + if (key == NULL || in == NULL) + return BAD_FUNC_ARG; + + /* check size of incoming keys */ + if (inLen != CURVE25519_KEYSIZE) + return ECC_BAD_ARG_E; + + if (endian == EC25519_BIG_ENDIAN) { + int i; + + /* read keys in Big Endian format */ + for (i = 0; i < CURVE25519_KEYSIZE; i++) + key->p.point[i] = in[CURVE25519_KEYSIZE - i - 1]; + } + else + XMEMCPY(key->p.point, in, inLen); + + key->dp = &curve25519_sets[0]; + + /* LTC needs also Y coordinate - let's compute it */ + #ifdef FREESCALE_LTC_ECC + ltc_pkha_ecc_point_t ltcPoint; + ltcPoint.X = &key->p.point[0]; + ltcPoint.Y = &key->p.pointY[0]; + LTC_PKHA_Curve25519ComputeY(<cPoint); + #endif + + return 0; +} + +#endif /* HAVE_CURVE25519_KEY_IMPORT */ + + +#ifdef HAVE_CURVE25519_KEY_EXPORT + +/* export curve25519 private key only raw (Big endian) + * outLen is in/out size + * return 0 on success */ +int wc_curve25519_export_private_raw(curve25519_key* key, byte* out, + word32* outLen) +{ + return wc_curve25519_export_private_raw_ex(key, out, outLen, + EC25519_BIG_ENDIAN); +} + +/* export curve25519 private key only raw (Big or Little endian) + * outLen is in/out size + * return 0 on success */ +int wc_curve25519_export_private_raw_ex(curve25519_key* key, byte* out, + word32* outLen, int endian) +{ + /* sanity check */ + if (key == NULL || out == NULL || outLen == NULL) + return BAD_FUNC_ARG; + + /* check size of outgoing buffer */ + if (*outLen < CURVE25519_KEYSIZE) { + *outLen = CURVE25519_KEYSIZE; + return ECC_BAD_ARG_E; + } + *outLen = CURVE25519_KEYSIZE; + + if (endian == EC25519_BIG_ENDIAN) { + int i; + + /* put the key in Big Endian format */ + for (i = 0; i < CURVE25519_KEYSIZE; i++) + out[i] = key->k.point[CURVE25519_KEYSIZE - i - 1]; + } + else + XMEMCPY(out, key->k.point, CURVE25519_KEYSIZE); + + return 0; +} + +/* curve25519 key pair export (Big or Little endian) + * return 0 on success */ +int wc_curve25519_export_key_raw(curve25519_key* key, + byte* priv, word32 *privSz, + byte* pub, word32 *pubSz) +{ + return wc_curve25519_export_key_raw_ex(key, priv, privSz, + pub, pubSz, EC25519_BIG_ENDIAN); +} + +/* curve25519 key pair export (Big or Little endian) + * return 0 on success */ +int wc_curve25519_export_key_raw_ex(curve25519_key* key, + byte* priv, word32 *privSz, + byte* pub, word32 *pubSz, + int endian) +{ + int ret; + + /* export private part */ + ret = wc_curve25519_export_private_raw_ex(key, priv, privSz, endian); + if (ret != 0) + return ret; + + /* export public part */ + return wc_curve25519_export_public_ex(key, pub, pubSz, endian); +} + +#endif /* HAVE_CURVE25519_KEY_EXPORT */ + +#ifdef HAVE_CURVE25519_KEY_IMPORT + +/* curve25519 private key import (Big endian) + * Public key to match private key needs to be imported too + * return 0 on success */ +int wc_curve25519_import_private_raw(const byte* priv, word32 privSz, + const byte* pub, word32 pubSz, + curve25519_key* key) +{ + return wc_curve25519_import_private_raw_ex(priv, privSz, pub, pubSz, + key, EC25519_BIG_ENDIAN); +} + +/* curve25519 private key import (Big or Little endian) + * Public key to match private key needs to be imported too + * return 0 on success */ +int wc_curve25519_import_private_raw_ex(const byte* priv, word32 privSz, + const byte* pub, word32 pubSz, + curve25519_key* key, int endian) +{ + int ret; + + /* import private part */ + ret = wc_curve25519_import_private_ex(priv, privSz, key, endian); + if (ret != 0) + return ret; + + /* import public part */ + return wc_curve25519_import_public_ex(pub, pubSz, key, endian); +} + +/* curve25519 private key import only. (Big endian) + * return 0 on success */ +int wc_curve25519_import_private(const byte* priv, word32 privSz, + curve25519_key* key) +{ + return wc_curve25519_import_private_ex(priv, privSz, + key, EC25519_BIG_ENDIAN); +} + +/* curve25519 private key import only. (Big or Little endian) + * return 0 on success */ +int wc_curve25519_import_private_ex(const byte* priv, word32 privSz, + curve25519_key* key, int endian) +{ + /* sanity check */ + if (key == NULL || priv == NULL) + return BAD_FUNC_ARG; + + /* check size of incoming keys */ + if ((int)privSz != CURVE25519_KEYSIZE) + return ECC_BAD_ARG_E; + + if (endian == EC25519_BIG_ENDIAN) { + int i; + + /* read the key in Big Endian format */ + for (i = 0; i < CURVE25519_KEYSIZE; i++) + key->k.point[i] = priv[CURVE25519_KEYSIZE - i - 1]; + } + else + XMEMCPY(key->k.point, priv, CURVE25519_KEYSIZE); + + key->dp = &curve25519_sets[0]; + + /* Clamp the key */ + key->k.point[0] &= 248; + key->k.point[privSz-1] &= 63; /* same &=127 because |=64 after */ + key->k.point[privSz-1] |= 64; + + return 0; +} + +#endif /* HAVE_CURVE25519_KEY_IMPORT */ + + +int wc_curve25519_init(curve25519_key* key) +{ + if (key == NULL) + return BAD_FUNC_ARG; + + XMEMSET(key, 0, sizeof(*key)); + + /* currently the format for curve25519 */ + key->dp = &curve25519_sets[0]; + +#ifndef FREESCALE_LTC_ECC + fe_init(); +#endif + + return 0; +} + + +/* Clean the memory of a key */ +void wc_curve25519_free(curve25519_key* key) +{ + if (key == NULL) + return; + + key->dp = NULL; + ForceZero(key->p.point, sizeof(key->p.point)); + ForceZero(key->k.point, sizeof(key->k.point)); + #ifdef FREESCALE_LTC_ECC + ForceZero(key->p.point, sizeof(key->p.pointY)); + ForceZero(key->k.point, sizeof(key->k.pointY)); + #endif +} + + +/* get key size */ +int wc_curve25519_size(curve25519_key* key) +{ + if (key == NULL) + return 0; + + return key->dp->size; +} + +#endif /*HAVE_CURVE25519*/ + diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/des3.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/des3.c new file mode 100755 index 0000000..fdd18e0 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/des3.c @@ -0,0 +1,1787 @@ +/* des3.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include +#include +#include + + +#ifndef NO_DES3 + +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + + /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ + #define FIPS_NO_WRAPPERS + + #ifdef USE_WINDOWS_API + #pragma code_seg(".fipsA$i") + #pragma const_seg(".fipsB$i") + #endif +#endif + +#include + +#ifdef WOLF_CRYPTO_CB + #include +#endif + +/* fips wrapper calls, user can call direct */ +#if defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) + + int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir) + { + return Des_SetKey(des, key, iv, dir); + } + int wc_Des3_SetKey(Des3* des, const byte* key, const byte* iv, int dir) + { + if (des == NULL || key == NULL || dir < 0) { + return BAD_FUNC_ARG; + } + + return Des3_SetKey_fips(des, key, iv, dir); + } + int wc_Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz) + { + return Des_CbcEncrypt(des, out, in, sz); + } + int wc_Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz) + { + return Des_CbcDecrypt(des, out, in, sz); + } + int wc_Des3_CbcEncrypt(Des3* des, byte* out, const byte* in, word32 sz) + { + if (des == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + return Des3_CbcEncrypt_fips(des, out, in, sz); + } + int wc_Des3_CbcDecrypt(Des3* des, byte* out, const byte* in, word32 sz) + { + if (des == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + return Des3_CbcDecrypt_fips(des, out, in, sz); + } + + #ifdef WOLFSSL_DES_ECB + /* One block, compatibility only */ + int wc_Des_EcbEncrypt(Des* des, byte* out, const byte* in, word32 sz) + { + return Des_EcbEncrypt(des, out, in, sz); + } + int wc_Des3_EcbEncrypt(Des3* des, byte* out, const byte* in, word32 sz) + { + return Des3_EcbEncrypt(des, out, in, sz); + } + #endif /* WOLFSSL_DES_ECB */ + + void wc_Des_SetIV(Des* des, const byte* iv) + { + Des_SetIV(des, iv); + } + int wc_Des3_SetIV(Des3* des, const byte* iv) + { + return Des3_SetIV_fips(des, iv); + } + + int wc_Des3Init(Des3* des3, void* heap, int devId) + { + (void)des3; + (void)heap; + (void)devId; + /* FIPS doesn't support: + return Des3Init(des3, heap, devId); */ + return 0; + } + void wc_Des3Free(Des3* des3) + { + (void)des3; + /* FIPS doesn't support: + Des3Free(des3); */ + } + +#else /* else build without fips, or for FIPS v2 */ + + +#if defined(WOLFSSL_TI_CRYPT) + #include +#else + + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + + +/* Hardware Acceleration */ +#if defined(STM32_CRYPTO) + + /* + * STM32F2/F4 hardware DES/3DES support through the standard + * peripheral library. (See note in README). + */ + + int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir) + { + word32 *dkey = des->key; + + (void)dir; + + XMEMCPY(dkey, key, 8); + #ifndef WOLFSSL_STM32_CUBEMX + ByteReverseWords(dkey, dkey, 8); + #endif + + wc_Des_SetIV(des, iv); + + return 0; + } + + int wc_Des3_SetKey(Des3* des, const byte* key, const byte* iv, int dir) + { + #ifndef WOLFSSL_STM32_CUBEMX + word32 *dkey1 = des->key[0]; + word32 *dkey2 = des->key[1]; + word32 *dkey3 = des->key[2]; + + (void)dir; + + XMEMCPY(dkey1, key, 8); /* set key 1 */ + XMEMCPY(dkey2, key + 8, 8); /* set key 2 */ + XMEMCPY(dkey3, key + 16, 8); /* set key 3 */ + + ByteReverseWords(dkey1, dkey1, 8); + ByteReverseWords(dkey2, dkey2, 8); + ByteReverseWords(dkey3, dkey3, 8); + #else + (void)dir; + XMEMCPY(des->key[0], key, DES3_KEYLEN); /* CUBEMX wants keys in sequential memory */ + #endif + + return wc_Des3_SetIV(des, iv); + } + + static void DesCrypt(Des* des, byte* out, const byte* in, word32 sz, + int dir, int mode) + { + #ifdef WOLFSSL_STM32_CUBEMX + CRYP_HandleTypeDef hcryp; + + XMEMSET(&hcryp, 0, sizeof(CRYP_HandleTypeDef)); + hcryp.Instance = CRYP; + hcryp.Init.KeySize = CRYP_KEYSIZE_128B; + hcryp.Init.DataType = CRYP_DATATYPE_8B; + hcryp.Init.pKey = (uint8_t*)des->key; + hcryp.Init.pInitVect = (uint8_t*)des->reg; + + HAL_CRYP_Init(&hcryp); + + while (sz > 0) + { + /* if input and output same will overwrite input iv */ + XMEMCPY(des->tmp, in + sz - DES_BLOCK_SIZE, DES_BLOCK_SIZE); + + if (mode == DES_CBC) { + if (dir == DES_ENCRYPTION) { + HAL_CRYP_DESCBC_Encrypt(&hcryp, (uint8_t*)in, + DES_BLOCK_SIZE, out, STM32_HAL_TIMEOUT); + } + else { + HAL_CRYP_DESCBC_Decrypt(&hcryp, (uint8_t*)in, + DES_BLOCK_SIZE, out, STM32_HAL_TIMEOUT); + } + } + else { + if (dir == DES_ENCRYPTION) { + HAL_CRYP_DESECB_Encrypt(&hcryp, (uint8_t*)in, + DES_BLOCK_SIZE, out, STM32_HAL_TIMEOUT); + } + else { + HAL_CRYP_DESECB_Decrypt(&hcryp, (uint8_t*)in, + DES_BLOCK_SIZE, out, STM32_HAL_TIMEOUT); + } + } + + /* store iv for next call */ + XMEMCPY(des->reg, des->tmp, DES_BLOCK_SIZE); + + sz -= DES_BLOCK_SIZE; + in += DES_BLOCK_SIZE; + out += DES_BLOCK_SIZE; + } + + HAL_CRYP_DeInit(&hcryp); + #else + word32 *dkey, *iv; + CRYP_InitTypeDef DES_CRYP_InitStructure; + CRYP_KeyInitTypeDef DES_CRYP_KeyInitStructure; + CRYP_IVInitTypeDef DES_CRYP_IVInitStructure; + + dkey = des->key; + iv = des->reg; + + /* crypto structure initialization */ + CRYP_KeyStructInit(&DES_CRYP_KeyInitStructure); + CRYP_StructInit(&DES_CRYP_InitStructure); + CRYP_IVStructInit(&DES_CRYP_IVInitStructure); + + /* reset registers to their default values */ + CRYP_DeInit(); + + /* set direction, mode, and datatype */ + if (dir == DES_ENCRYPTION) { + DES_CRYP_InitStructure.CRYP_AlgoDir = CRYP_AlgoDir_Encrypt; + } else { /* DES_DECRYPTION */ + DES_CRYP_InitStructure.CRYP_AlgoDir = CRYP_AlgoDir_Decrypt; + } + + if (mode == DES_CBC) { + DES_CRYP_InitStructure.CRYP_AlgoMode = CRYP_AlgoMode_DES_CBC; + } else { /* DES_ECB */ + DES_CRYP_InitStructure.CRYP_AlgoMode = CRYP_AlgoMode_DES_ECB; + } + + DES_CRYP_InitStructure.CRYP_DataType = CRYP_DataType_8b; + CRYP_Init(&DES_CRYP_InitStructure); + + /* load key into correct registers */ + DES_CRYP_KeyInitStructure.CRYP_Key1Left = dkey[0]; + DES_CRYP_KeyInitStructure.CRYP_Key1Right = dkey[1]; + CRYP_KeyInit(&DES_CRYP_KeyInitStructure); + + /* set iv */ + ByteReverseWords(iv, iv, DES_BLOCK_SIZE); + DES_CRYP_IVInitStructure.CRYP_IV0Left = iv[0]; + DES_CRYP_IVInitStructure.CRYP_IV0Right = iv[1]; + CRYP_IVInit(&DES_CRYP_IVInitStructure); + + /* enable crypto processor */ + CRYP_Cmd(ENABLE); + + while (sz > 0) + { + /* flush IN/OUT FIFOs */ + CRYP_FIFOFlush(); + + /* if input and output same will overwrite input iv */ + XMEMCPY(des->tmp, in + sz - DES_BLOCK_SIZE, DES_BLOCK_SIZE); + + CRYP_DataIn(*(uint32_t*)&in[0]); + CRYP_DataIn(*(uint32_t*)&in[4]); + + /* wait until the complete message has been processed */ + while(CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {} + + *(uint32_t*)&out[0] = CRYP_DataOut(); + *(uint32_t*)&out[4] = CRYP_DataOut(); + + /* store iv for next call */ + XMEMCPY(des->reg, des->tmp, DES_BLOCK_SIZE); + + sz -= DES_BLOCK_SIZE; + in += DES_BLOCK_SIZE; + out += DES_BLOCK_SIZE; + } + + /* disable crypto processor */ + CRYP_Cmd(DISABLE); + #endif /* WOLFSSL_STM32_CUBEMX */ + } + + int wc_Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz) + { + DesCrypt(des, out, in, sz, DES_ENCRYPTION, DES_CBC); + return 0; + } + + int wc_Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz) + { + DesCrypt(des, out, in, sz, DES_DECRYPTION, DES_CBC); + return 0; + } + + int wc_Des_EcbEncrypt(Des* des, byte* out, const byte* in, word32 sz) + { + DesCrypt(des, out, in, sz, DES_ENCRYPTION, DES_ECB); + return 0; + } + + static void Des3Crypt(Des3* des, byte* out, const byte* in, word32 sz, + int dir) + { + #ifdef WOLFSSL_STM32_CUBEMX + CRYP_HandleTypeDef hcryp; + + XMEMSET(&hcryp, 0, sizeof(CRYP_HandleTypeDef)); + hcryp.Instance = CRYP; + hcryp.Init.KeySize = CRYP_KEYSIZE_128B; + hcryp.Init.DataType = CRYP_DATATYPE_8B; + hcryp.Init.pKey = (uint8_t*)des->key; + hcryp.Init.pInitVect = (uint8_t*)des->reg; + + HAL_CRYP_Init(&hcryp); + + while (sz > 0) + { + if (dir == DES_ENCRYPTION) { + HAL_CRYP_TDESCBC_Encrypt(&hcryp, (byte*)in, + DES_BLOCK_SIZE, out, STM32_HAL_TIMEOUT); + } + else { + HAL_CRYP_TDESCBC_Decrypt(&hcryp, (byte*)in, + DES_BLOCK_SIZE, out, STM32_HAL_TIMEOUT); + } + + /* store iv for next call */ + XMEMCPY(des->reg, out + sz - DES_BLOCK_SIZE, DES_BLOCK_SIZE); + + sz -= DES_BLOCK_SIZE; + in += DES_BLOCK_SIZE; + out += DES_BLOCK_SIZE; + } + + HAL_CRYP_DeInit(&hcryp); + #else + word32 *dkey1, *dkey2, *dkey3, *iv; + CRYP_InitTypeDef DES3_CRYP_InitStructure; + CRYP_KeyInitTypeDef DES3_CRYP_KeyInitStructure; + CRYP_IVInitTypeDef DES3_CRYP_IVInitStructure; + + dkey1 = des->key[0]; + dkey2 = des->key[1]; + dkey3 = des->key[2]; + iv = des->reg; + + /* crypto structure initialization */ + CRYP_KeyStructInit(&DES3_CRYP_KeyInitStructure); + CRYP_StructInit(&DES3_CRYP_InitStructure); + CRYP_IVStructInit(&DES3_CRYP_IVInitStructure); + + /* reset registers to their default values */ + CRYP_DeInit(); + + /* set direction, mode, and datatype */ + if (dir == DES_ENCRYPTION) { + DES3_CRYP_InitStructure.CRYP_AlgoDir = CRYP_AlgoDir_Encrypt; + } else { + DES3_CRYP_InitStructure.CRYP_AlgoDir = CRYP_AlgoDir_Decrypt; + } + + DES3_CRYP_InitStructure.CRYP_AlgoMode = CRYP_AlgoMode_TDES_CBC; + DES3_CRYP_InitStructure.CRYP_DataType = CRYP_DataType_8b; + CRYP_Init(&DES3_CRYP_InitStructure); + + /* load key into correct registers */ + DES3_CRYP_KeyInitStructure.CRYP_Key1Left = dkey1[0]; + DES3_CRYP_KeyInitStructure.CRYP_Key1Right = dkey1[1]; + DES3_CRYP_KeyInitStructure.CRYP_Key2Left = dkey2[0]; + DES3_CRYP_KeyInitStructure.CRYP_Key2Right = dkey2[1]; + DES3_CRYP_KeyInitStructure.CRYP_Key3Left = dkey3[0]; + DES3_CRYP_KeyInitStructure.CRYP_Key3Right = dkey3[1]; + CRYP_KeyInit(&DES3_CRYP_KeyInitStructure); + + /* set iv */ + ByteReverseWords(iv, iv, DES_BLOCK_SIZE); + DES3_CRYP_IVInitStructure.CRYP_IV0Left = iv[0]; + DES3_CRYP_IVInitStructure.CRYP_IV0Right = iv[1]; + CRYP_IVInit(&DES3_CRYP_IVInitStructure); + + /* enable crypto processor */ + CRYP_Cmd(ENABLE); + + while (sz > 0) + { + /* flush IN/OUT FIFOs */ + CRYP_FIFOFlush(); + + CRYP_DataIn(*(uint32_t*)&in[0]); + CRYP_DataIn(*(uint32_t*)&in[4]); + + /* wait until the complete message has been processed */ + while(CRYP_GetFlagStatus(CRYP_FLAG_BUSY) != RESET) {} + + *(uint32_t*)&out[0] = CRYP_DataOut(); + *(uint32_t*)&out[4] = CRYP_DataOut(); + + /* store iv for next call */ + XMEMCPY(des->reg, out + sz - DES_BLOCK_SIZE, DES_BLOCK_SIZE); + + sz -= DES_BLOCK_SIZE; + in += DES_BLOCK_SIZE; + out += DES_BLOCK_SIZE; + } + + /* disable crypto processor */ + CRYP_Cmd(DISABLE); + #endif /* WOLFSSL_STM32_CUBEMX */ + } + + int wc_Des3_CbcEncrypt(Des3* des, byte* out, const byte* in, word32 sz) + { + Des3Crypt(des, out, in, sz, DES_ENCRYPTION); + return 0; + } + + int wc_Des3_CbcDecrypt(Des3* des, byte* out, const byte* in, word32 sz) + { + Des3Crypt(des, out, in, sz, DES_DECRYPTION); + return 0; + } + +#elif defined(HAVE_COLDFIRE_SEC) + + #include + + #include "sec.h" + #include "mcf5475_sec.h" + #include "mcf5475_siu.h" + + #if defined (HAVE_THREADX) + #include "memory_pools.h" + extern TX_BYTE_POOL mp_ncached; /* Non Cached memory pool */ + #endif + + #define DES_BUFFER_SIZE (DES_BLOCK_SIZE * 64) + static unsigned char *desBuffIn = NULL; + static unsigned char *desBuffOut = NULL; + static byte *secIV; + static byte *secKey; + static volatile SECdescriptorType *secDesc; + + static wolfSSL_Mutex Mutex_DesSEC; + + #define SEC_DESC_DES_CBC_ENCRYPT 0x20500010 + #define SEC_DESC_DES_CBC_DECRYPT 0x20400010 + #define SEC_DESC_DES3_CBC_ENCRYPT 0x20700010 + #define SEC_DESC_DES3_CBC_DECRYPT 0x20600010 + + #define DES_IVLEN 8 + #define DES_KEYLEN 8 + #define DES3_IVLEN 8 + #define DES3_KEYLEN 24 + + extern volatile unsigned char __MBAR[]; + + static void wc_Des_Cbc(byte* out, const byte* in, word32 sz, + byte *key, byte *iv, word32 desc) + { + #ifdef DEBUG_WOLFSSL + int ret; int stat1,stat2; + #endif + int size; + volatile int v; + + wc_LockMutex(&Mutex_DesSEC) ; + + secDesc->length1 = 0x0; + secDesc->pointer1 = NULL; + if((desc==SEC_DESC_DES_CBC_ENCRYPT)||(desc==SEC_DESC_DES_CBC_DECRYPT)){ + secDesc->length2 = DES_IVLEN; + secDesc->length3 = DES_KEYLEN; + } else { + secDesc->length2 = DES3_IVLEN; + secDesc->length3 = DES3_KEYLEN; + } + secDesc->pointer2 = secIV; + secDesc->pointer3 = secKey; + secDesc->pointer4 = desBuffIn; + secDesc->pointer5 = desBuffOut; + secDesc->length6 = 0; + secDesc->pointer6 = NULL; + secDesc->length7 = 0x0; + secDesc->pointer7 = NULL; + secDesc->nextDescriptorPtr = NULL; + + while(sz) { + XMEMCPY(secIV, iv, secDesc->length2); + if((sz%DES_BUFFER_SIZE) == sz) { + size = sz; + sz = 0; + } else { + size = DES_BUFFER_SIZE; + sz -= DES_BUFFER_SIZE; + } + + XMEMCPY(desBuffIn, in, size); + XMEMCPY(secKey, key, secDesc->length3); + + secDesc->header = desc; + secDesc->length4 = size; + secDesc->length5 = size; + /* Point SEC to the location of the descriptor */ + MCF_SEC_FR0 = (uint32)secDesc; + /* Initialize SEC and wait for encryption to complete */ + MCF_SEC_CCCR0 = 0x0000001a; + /* poll SISR to determine when channel is complete */ + v=0; + while((secDesc->header>> 24) != 0xff) { + if(v++ > 1000)break; + } + + #ifdef DEBUG_WOLFSSL + ret = MCF_SEC_SISRH; + stat1 = MCF_SEC_DSR; + stat2 = MCF_SEC_DISR; + if(ret & 0xe0000000) { + /* db_printf("Des_Cbc(%x):ISRH=%08x, DSR=%08x, DISR=%08x\n", desc, ret, stat1, stat2); */ + } + #endif + + XMEMCPY(out, desBuffOut, size); + + if ((desc==SEC_DESC_DES3_CBC_ENCRYPT)||(desc==SEC_DESC_DES_CBC_ENCRYPT)) { + XMEMCPY((void*)iv, (void*)&(out[size-secDesc->length2]), secDesc->length2); + } else { + XMEMCPY((void*)iv, (void*)&(in[size-secDesc->length2]), secDesc->length2); + } + + in += size; + out += size; + + } + wc_UnLockMutex(&Mutex_DesSEC) ; + + } + + + int wc_Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz) + { + wc_Des_Cbc(out, in, sz, (byte *)des->key, (byte *)des->reg, SEC_DESC_DES_CBC_ENCRYPT); + return 0; + } + + int wc_Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz) + { + wc_Des_Cbc(out, in, sz, (byte *)des->key, (byte *)des->reg, SEC_DESC_DES_CBC_DECRYPT); + return 0; + } + + int wc_Des3_CbcEncrypt(Des3* des3, byte* out, const byte* in, word32 sz) + { + wc_Des_Cbc(out, in, sz, (byte *)des3->key, (byte *)des3->reg, SEC_DESC_DES3_CBC_ENCRYPT); + return 0; + } + + + int wc_Des3_CbcDecrypt(Des3* des3, byte* out, const byte* in, word32 sz) + { + wc_Des_Cbc(out, in, sz, (byte *)des3->key, (byte *)des3->reg, SEC_DESC_DES3_CBC_DECRYPT); + return 0; + } + + static void setParity(byte *buf, int len) + { + int i, j; + byte v; + int bits; + + for (i=0; i> 1; + buf[i] = v << 1; + bits = 0; + for (j=0; j<7; j++) { + bits += (v&0x1); + v = v >> 1; + } + buf[i] |= (1 - (bits&0x1)); + } + + } + + int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir) + { + if(desBuffIn == NULL) { + #if defined (HAVE_THREADX) + int s1, s2, s3, s4, s5; + s5 = tx_byte_allocate(&mp_ncached,(void *)&secDesc, + sizeof(SECdescriptorType), TX_NO_WAIT); + s1 = tx_byte_allocate(&mp_ncached,(void *)&desBuffIn, DES_BUFFER_SIZE, TX_NO_WAIT); + s2 = tx_byte_allocate(&mp_ncached,(void *)&desBuffOut, DES_BUFFER_SIZE, TX_NO_WAIT); + /* Don't know des or des3 to be used. Allocate larger buffers */ + s3 = tx_byte_allocate(&mp_ncached,(void *)&secKey, DES3_KEYLEN,TX_NO_WAIT); + s4 = tx_byte_allocate(&mp_ncached,(void *)&secIV, DES3_IVLEN, TX_NO_WAIT); + #else + #warning "Allocate non-Cache buffers" + #endif + + InitMutex(&Mutex_DesSEC); + } + + XMEMCPY(des->key, key, DES_KEYLEN); + setParity((byte *)des->key, DES_KEYLEN); + + if (iv) { + XMEMCPY(des->reg, iv, DES_IVLEN); + } else { + XMEMSET(des->reg, 0x0, DES_IVLEN); + } + return 0; + } + + int wc_Des3_SetKey(Des3* des3, const byte* key, const byte* iv, int dir) + { + + if(desBuffIn == NULL) { + #if defined (HAVE_THREADX) + int s1, s2, s3, s4, s5; + s5 = tx_byte_allocate(&mp_ncached,(void *)&secDesc, + sizeof(SECdescriptorType), TX_NO_WAIT); + s1 = tx_byte_allocate(&mp_ncached,(void *)&desBuffIn, DES_BUFFER_SIZE, TX_NO_WAIT); + s2 = tx_byte_allocate(&mp_ncached,(void *)&desBuffOut, DES_BUFFER_SIZE, TX_NO_WAIT); + s3 = tx_byte_allocate(&mp_ncached,(void *)&secKey, DES3_KEYLEN,TX_NO_WAIT); + s4 = tx_byte_allocate(&mp_ncached,(void *)&secIV, DES3_IVLEN, TX_NO_WAIT); + #else + #warning "Allocate non-Cache buffers" + #endif + + InitMutex(&Mutex_DesSEC); + } + + XMEMCPY(des3->key[0], key, DES3_KEYLEN); + setParity((byte *)des3->key[0], DES3_KEYLEN); + + if (iv) { + XMEMCPY(des3->reg, iv, DES3_IVLEN); + } else { + XMEMSET(des3->reg, 0x0, DES3_IVLEN); + } + return 0; + + } +#elif defined(FREESCALE_LTC_DES) + + #include "fsl_ltc.h" + int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir) + { + byte* dkey = (byte*)des->key; + + XMEMCPY(dkey, key, 8); + + wc_Des_SetIV(des, iv); + + return 0; + } + + int wc_Des3_SetKey(Des3* des, const byte* key, const byte* iv, int dir) + { + int ret = 0; + byte* dkey1 = (byte*)des->key[0]; + byte* dkey2 = (byte*)des->key[1]; + byte* dkey3 = (byte*)des->key[2]; + + XMEMCPY(dkey1, key, 8); /* set key 1 */ + XMEMCPY(dkey2, key + 8, 8); /* set key 2 */ + XMEMCPY(dkey3, key + 16, 8); /* set key 3 */ + + ret = wc_Des3_SetIV(des, iv); + if (ret != 0) + return ret; + + return ret; + } + + int wc_Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz) + { + status_t status; + status = LTC_DES_EncryptCbc(LTC_BASE, in, out, sz, (byte*)des->reg, (byte*)des->key); + if (status == kStatus_Success) + return 0; + else + return -1; + } + + int wc_Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz) + { + status_t status; + status = LTC_DES_DecryptCbc(LTC_BASE, in, out, sz, (byte*)des->reg, (byte*)des->key); + if (status == kStatus_Success) + return 0; + else + return -1; + } + + int wc_Des3_CbcEncrypt(Des3* des, byte* out, const byte* in, word32 sz) + { + status_t status; + status = LTC_DES3_EncryptCbc(LTC_BASE, + in, + out, + sz, + (byte*)des->reg, + (byte*)des->key[0], + (byte*)des->key[1], + (byte*)des->key[2]); + if (status == kStatus_Success) + return 0; + else + return -1; + } + + int wc_Des3_CbcDecrypt(Des3* des, byte* out, const byte* in, word32 sz) + { + status_t status; + status = LTC_DES3_DecryptCbc(LTC_BASE, + in, + out, + sz, + (byte*)des->reg, + (byte*)des->key[0], + (byte*)des->key[1], + (byte*)des->key[2]); + if (status == kStatus_Success) + return 0; + else + return -1; + + } + +#elif defined(FREESCALE_MMCAU) + /* + * Freescale mmCAU hardware DES/3DES support through the CAU/mmCAU library. + * Documentation located in ColdFire/ColdFire+ CAU and Kinetis mmCAU + * Software Library User Guide (See note in README). + */ + #ifdef FREESCALE_MMCAU_CLASSIC + #include "cau_api.h" + #else + #include "fsl_mmcau.h" + #endif + + const unsigned char parityLookup[128] = { + 1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0, + 0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1, + 0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1, + 1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0 + }; + + int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir) + { + int i = 0; + byte* dkey = (byte*)des->key; + + XMEMCPY(dkey, key, 8); + + wc_Des_SetIV(des, iv); + + /* fix key parity, if needed */ + for (i = 0; i < 8; i++) { + dkey[i] = ((dkey[i] & 0xFE) | parityLookup[dkey[i] >> 1]); + } + + return 0; + } + + int wc_Des3_SetKey(Des3* des, const byte* key, const byte* iv, int dir) + { + int i = 0, ret = 0; + byte* dkey1 = (byte*)des->key[0]; + byte* dkey2 = (byte*)des->key[1]; + byte* dkey3 = (byte*)des->key[2]; + + XMEMCPY(dkey1, key, 8); /* set key 1 */ + XMEMCPY(dkey2, key + 8, 8); /* set key 2 */ + XMEMCPY(dkey3, key + 16, 8); /* set key 3 */ + + ret = wc_Des3_SetIV(des, iv); + if (ret != 0) + return ret; + + /* fix key parity if needed */ + for (i = 0; i < 8; i++) + dkey1[i] = ((dkey1[i] & 0xFE) | parityLookup[dkey1[i] >> 1]); + + for (i = 0; i < 8; i++) + dkey2[i] = ((dkey2[i] & 0xFE) | parityLookup[dkey2[i] >> 1]); + + for (i = 0; i < 8; i++) + dkey3[i] = ((dkey3[i] & 0xFE) | parityLookup[dkey3[i] >> 1]); + + return ret; + } + + int wc_Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz) + { + int i; + int offset = 0; + int len = sz; + int ret = 0; + byte *iv; + byte temp_block[DES_BLOCK_SIZE]; + + iv = (byte*)des->reg; + + #ifdef FREESCALE_MMCAU_CLASSIC + if ((wolfssl_word)out % WOLFSSL_MMCAU_ALIGNMENT) { + WOLFSSL_MSG("Bad cau_des_encrypt alignment"); + return BAD_ALIGN_E; + } + #endif + + while (len > 0) + { + XMEMCPY(temp_block, in + offset, DES_BLOCK_SIZE); + + /* XOR block with IV for CBC */ + for (i = 0; i < DES_BLOCK_SIZE; i++) + temp_block[i] ^= iv[i]; + + ret = wolfSSL_CryptHwMutexLock(); + if(ret != 0) { + return ret; + } + #ifdef FREESCALE_MMCAU_CLASSIC + cau_des_encrypt(temp_block, (byte*)des->key, out + offset); + #else + MMCAU_DES_EncryptEcb(temp_block, (byte*)des->key, out + offset); + #endif + wolfSSL_CryptHwMutexUnLock(); + + len -= DES_BLOCK_SIZE; + offset += DES_BLOCK_SIZE; + + /* store IV for next block */ + XMEMCPY(iv, out + offset - DES_BLOCK_SIZE, DES_BLOCK_SIZE); + } + + return ret; + } + + int wc_Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz) + { + int i; + int offset = 0; + int len = sz; + int ret = 0; + byte* iv; + byte temp_block[DES_BLOCK_SIZE]; + + iv = (byte*)des->reg; + + #ifdef FREESCALE_MMCAU_CLASSIC + if ((wolfssl_word)out % WOLFSSL_MMCAU_ALIGNMENT) { + WOLFSSL_MSG("Bad cau_des_decrypt alignment"); + return BAD_ALIGN_E; + } + #endif + + while (len > 0) + { + XMEMCPY(temp_block, in + offset, DES_BLOCK_SIZE); + + ret = wolfSSL_CryptHwMutexLock(); + if(ret != 0) { + return ret; + } + + #ifdef FREESCALE_MMCAU_CLASSIC + cau_des_decrypt(in + offset, (byte*)des->key, out + offset); + #else + MMCAU_DES_DecryptEcb(in + offset, (byte*)des->key, out + offset); + #endif + wolfSSL_CryptHwMutexUnLock(); + + /* XOR block with IV for CBC */ + for (i = 0; i < DES_BLOCK_SIZE; i++) + (out + offset)[i] ^= iv[i]; + + /* store IV for next block */ + XMEMCPY(iv, temp_block, DES_BLOCK_SIZE); + + len -= DES_BLOCK_SIZE; + offset += DES_BLOCK_SIZE; + } + + return ret; + } + + int wc_Des3_CbcEncrypt(Des3* des, byte* out, const byte* in, word32 sz) + { + int i; + int offset = 0; + int len = sz; + int ret = 0; + + byte *iv; + byte temp_block[DES_BLOCK_SIZE]; + + iv = (byte*)des->reg; + + #ifdef FREESCALE_MMCAU_CLASSIC + if ((wolfssl_word)out % WOLFSSL_MMCAU_ALIGNMENT) { + WOLFSSL_MSG("Bad 3ede cau_des_encrypt alignment"); + return BAD_ALIGN_E; + } + #endif + + while (len > 0) + { + XMEMCPY(temp_block, in + offset, DES_BLOCK_SIZE); + + /* XOR block with IV for CBC */ + for (i = 0; i < DES_BLOCK_SIZE; i++) + temp_block[i] ^= iv[i]; + + ret = wolfSSL_CryptHwMutexLock(); + if(ret != 0) { + return ret; + } + #ifdef FREESCALE_MMCAU_CLASSIC + cau_des_encrypt(temp_block, (byte*)des->key[0], out + offset); + cau_des_decrypt(out + offset, (byte*)des->key[1], out + offset); + cau_des_encrypt(out + offset, (byte*)des->key[2], out + offset); + #else + MMCAU_DES_EncryptEcb(temp_block , (byte*)des->key[0], out + offset); + MMCAU_DES_DecryptEcb(out + offset, (byte*)des->key[1], out + offset); + MMCAU_DES_EncryptEcb(out + offset, (byte*)des->key[2], out + offset); + #endif + wolfSSL_CryptHwMutexUnLock(); + + len -= DES_BLOCK_SIZE; + offset += DES_BLOCK_SIZE; + + /* store IV for next block */ + XMEMCPY(iv, out + offset - DES_BLOCK_SIZE, DES_BLOCK_SIZE); + } + + return ret; + } + + int wc_Des3_CbcDecrypt(Des3* des, byte* out, const byte* in, word32 sz) + { + int i; + int offset = 0; + int len = sz; + int ret = 0; + + byte* iv; + byte temp_block[DES_BLOCK_SIZE]; + + iv = (byte*)des->reg; + + #ifdef FREESCALE_MMCAU_CLASSIC + if ((wolfssl_word)out % WOLFSSL_MMCAU_ALIGNMENT) { + WOLFSSL_MSG("Bad 3ede cau_des_decrypt alignment"); + return BAD_ALIGN_E; + } + #endif + + while (len > 0) + { + XMEMCPY(temp_block, in + offset, DES_BLOCK_SIZE); + + ret = wolfSSL_CryptHwMutexLock(); + if(ret != 0) { + return ret; + } + #ifdef FREESCALE_MMCAU_CLASSIC + cau_des_decrypt(in + offset, (byte*)des->key[2], out + offset); + cau_des_encrypt(out + offset, (byte*)des->key[1], out + offset); + cau_des_decrypt(out + offset, (byte*)des->key[0], out + offset); + #else + MMCAU_DES_DecryptEcb(in + offset , (byte*)des->key[2], out + offset); + MMCAU_DES_EncryptEcb(out + offset, (byte*)des->key[1], out + offset); + MMCAU_DES_DecryptEcb(out + offset, (byte*)des->key[0], out + offset); + #endif + wolfSSL_CryptHwMutexUnLock(); + + /* XOR block with IV for CBC */ + for (i = 0; i < DES_BLOCK_SIZE; i++) + (out + offset)[i] ^= iv[i]; + + /* store IV for next block */ + XMEMCPY(iv, temp_block, DES_BLOCK_SIZE); + + len -= DES_BLOCK_SIZE; + offset += DES_BLOCK_SIZE; + } + + return ret; + } + + +#elif defined(WOLFSSL_PIC32MZ_CRYPT) + + /* PIC32MZ DES hardware requires size multiple of block size */ + #include + + int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir) + { + if (des == NULL || key == NULL || iv == NULL) + return BAD_FUNC_ARG; + + XMEMCPY(des->key, key, DES_KEYLEN); + XMEMCPY(des->reg, iv, DES_IVLEN); + + return 0; + } + + int wc_Des3_SetKey(Des3* des, const byte* key, const byte* iv, int dir) + { + if (des == NULL || key == NULL || iv == NULL) + return BAD_FUNC_ARG; + + XMEMCPY(des->key[0], key, DES3_KEYLEN); + XMEMCPY(des->reg, iv, DES3_IVLEN); + + return 0; + } + + int wc_Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz) + { + word32 blocks = sz / DES_BLOCK_SIZE; + + if (des == NULL || out == NULL || in == NULL) + return BAD_FUNC_ARG; + + return wc_Pic32DesCrypt(des->key, DES_KEYLEN, des->reg, DES_IVLEN, + out, in, (blocks * DES_BLOCK_SIZE), + PIC32_ENCRYPTION, PIC32_ALGO_DES, PIC32_CRYPTOALGO_CBC); + } + + int wc_Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz) + { + word32 blocks = sz / DES_BLOCK_SIZE; + + if (des == NULL || out == NULL || in == NULL) + return BAD_FUNC_ARG; + + return wc_Pic32DesCrypt(des->key, DES_KEYLEN, des->reg, DES_IVLEN, + out, in, (blocks * DES_BLOCK_SIZE), + PIC32_DECRYPTION, PIC32_ALGO_DES, PIC32_CRYPTOALGO_CBC); + } + + int wc_Des3_CbcEncrypt(Des3* des, byte* out, const byte* in, word32 sz) + { + word32 blocks = sz / DES_BLOCK_SIZE; + + if (des == NULL || out == NULL || in == NULL) + return BAD_FUNC_ARG; + + return wc_Pic32DesCrypt(des->key[0], DES3_KEYLEN, des->reg, DES3_IVLEN, + out, in, (blocks * DES_BLOCK_SIZE), + PIC32_ENCRYPTION, PIC32_ALGO_TDES, PIC32_CRYPTOALGO_TCBC); + } + + int wc_Des3_CbcDecrypt(Des3* des, byte* out, const byte* in, word32 sz) + { + word32 blocks = sz / DES_BLOCK_SIZE; + + if (des == NULL || out == NULL || in == NULL) + return BAD_FUNC_ARG; + + return wc_Pic32DesCrypt(des->key[0], DES3_KEYLEN, des->reg, DES3_IVLEN, + out, in, (blocks * DES_BLOCK_SIZE), + PIC32_DECRYPTION, PIC32_ALGO_TDES, PIC32_CRYPTOALGO_TCBC); + } + + #ifdef WOLFSSL_DES_ECB + int wc_Des_EcbEncrypt(Des* des, byte* out, const byte* in, word32 sz) + { + word32 blocks = sz / DES_BLOCK_SIZE; + + if (des == NULL || out == NULL || in == NULL) + return BAD_FUNC_ARG; + + return wc_Pic32DesCrypt(des->key, DES_KEYLEN, des->reg, DES_IVLEN, + out, in, (blocks * DES_BLOCK_SIZE), + PIC32_ENCRYPTION, PIC32_ALGO_DES, PIC32_CRYPTOALGO_ECB); + } + + int wc_Des3_EcbEncrypt(Des3* des, byte* out, const byte* in, word32 sz) + { + word32 blocks = sz / DES_BLOCK_SIZE; + + if (des == NULL || out == NULL || in == NULL) + return BAD_FUNC_ARG; + + return wc_Pic32DesCrypt(des->key[0], DES3_KEYLEN, des->reg, DES3_IVLEN, + out, in, (blocks * DES_BLOCK_SIZE), + PIC32_ENCRYPTION, PIC32_ALGO_TDES, PIC32_CRYPTOALGO_TECB); + } + #endif /* WOLFSSL_DES_ECB */ + +#else + #define NEED_SOFT_DES + +#endif + + +#ifdef NEED_SOFT_DES + + /* permuted choice table (key) */ + static const byte pc1[] = { + 57, 49, 41, 33, 25, 17, 9, + 1, 58, 50, 42, 34, 26, 18, + 10, 2, 59, 51, 43, 35, 27, + 19, 11, 3, 60, 52, 44, 36, + + 63, 55, 47, 39, 31, 23, 15, + 7, 62, 54, 46, 38, 30, 22, + 14, 6, 61, 53, 45, 37, 29, + 21, 13, 5, 28, 20, 12, 4 + }; + + /* number left rotations of pc1 */ + static const byte totrot[] = { + 1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28 + }; + + /* permuted choice key (table) */ + static const byte pc2[] = { + 14, 17, 11, 24, 1, 5, + 3, 28, 15, 6, 21, 10, + 23, 19, 12, 4, 26, 8, + 16, 7, 27, 20, 13, 2, + 41, 52, 31, 37, 47, 55, + 30, 40, 51, 45, 33, 48, + 44, 49, 39, 56, 34, 53, + 46, 42, 50, 36, 29, 32 + }; + + /* End of DES-defined tables */ + + /* bit 0 is left-most in byte */ + static const int bytebit[] = { + 0200,0100,040,020,010,04,02,01 + }; + + static const word32 Spbox[8][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}, + { 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}, + { 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}, + { 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}, + { 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}, + { 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}, + { 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}, + { 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} + }; + + static WC_INLINE void IPERM(word32* left, word32* right) + { + word32 work; + + *right = rotlFixed(*right, 4U); + work = (*left ^ *right) & 0xf0f0f0f0; + *left ^= work; + + *right = rotrFixed(*right^work, 20U); + work = (*left ^ *right) & 0xffff0000; + *left ^= work; + + *right = rotrFixed(*right^work, 18U); + work = (*left ^ *right) & 0x33333333; + *left ^= work; + + *right = rotrFixed(*right^work, 6U); + work = (*left ^ *right) & 0x00ff00ff; + *left ^= work; + + *right = rotlFixed(*right^work, 9U); + work = (*left ^ *right) & 0xaaaaaaaa; + *left = rotlFixed(*left^work, 1U); + *right ^= work; + } + + static WC_INLINE void FPERM(word32* left, word32* right) + { + word32 work; + + *right = rotrFixed(*right, 1U); + work = (*left ^ *right) & 0xaaaaaaaa; + *right ^= work; + + *left = rotrFixed(*left^work, 9U); + work = (*left ^ *right) & 0x00ff00ff; + *right ^= work; + + *left = rotlFixed(*left^work, 6U); + work = (*left ^ *right) & 0x33333333; + *right ^= work; + + *left = rotlFixed(*left^work, 18U); + work = (*left ^ *right) & 0xffff0000; + *right ^= work; + + *left = rotlFixed(*left^work, 20U); + work = (*left ^ *right) & 0xf0f0f0f0; + *right ^= work; + + *left = rotrFixed(*left^work, 4U); + } + + static int DesSetKey(const byte* key, int dir, word32* out) + { + #define DES_KEY_BUFFER_SIZE (56+56+8) + #ifdef WOLFSSL_SMALL_STACK + byte* buffer = (byte*)XMALLOC(DES_KEY_BUFFER_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + if (buffer == NULL) + return MEMORY_E; + #else + byte buffer[DES_KEY_BUFFER_SIZE]; + #endif + + { + byte* const pc1m = buffer; /* place to modify pc1 into */ + byte* const pcr = pc1m + 56; /* place to rotate pc1 into */ + byte* const ks = pcr + 56; + register int i, j, l; + int m; + + for (j = 0; j < 56; j++) { /* convert pc1 to bits of key */ + l = pc1[j] - 1; /* integer bit location */ + m = l & 07; /* find bit */ + pc1m[j] = (key[l >> 3] & /* find which key byte l is in */ + bytebit[m]) /* and which bit of that byte */ + ? 1 : 0; /* and store 1-bit result */ + } + + for (i = 0; i < 16; i++) { /* key chunk for each iteration */ + XMEMSET(ks, 0, 8); /* Clear key schedule */ + + for (j = 0; j < 56; j++) /* rotate pc1 the right amount */ + pcr[j] = + pc1m[(l = j + totrot[i]) < (j < 28 ? 28 : 56) ? l : l-28]; + + /* rotate left and right halves independently */ + for (j = 0; j < 48; j++) { /* select bits individually */ + if (pcr[pc2[j] - 1]) { /* check bit that goes to ks[j] */ + l= j % 6; /* mask it in if it's there */ + ks[j/6] |= bytebit[l] >> 2; + } + } + + /* Now convert to odd/even interleaved form for use in F */ + out[2*i] = ((word32) ks[0] << 24) + | ((word32) ks[2] << 16) + | ((word32) ks[4] << 8) + | ((word32) ks[6]); + + out[2*i + 1] = ((word32) ks[1] << 24) + | ((word32) ks[3] << 16) + | ((word32) ks[5] << 8) + | ((word32) ks[7]); + } + + /* reverse key schedule order */ + if (dir == DES_DECRYPTION) { + for (i = 0; i < 16; i += 2) { + word32 swap = out[i]; + out[i] = out[DES_KS_SIZE - 2 - i]; + out[DES_KS_SIZE - 2 - i] = swap; + + swap = out[i + 1]; + out[i + 1] = out[DES_KS_SIZE - 1 - i]; + out[DES_KS_SIZE - 1 - i] = swap; + } + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + } + + return 0; + } + + int wc_Des_SetKey(Des* des, const byte* key, const byte* iv, int dir) + { + wc_Des_SetIV(des, iv); + + return DesSetKey(key, dir, des->key); + } + + int wc_Des3_SetKey(Des3* des, const byte* key, const byte* iv, int dir) + { + int ret; + + if (des == NULL || key == NULL || dir < 0) { + return BAD_FUNC_ARG; + } + + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_3DES) + if (des->asyncDev.marker == WOLFSSL_ASYNC_MARKER_3DES) { + /* key_raw holds orignal key copy */ + des->key_raw = key; + des->iv_raw = iv; + + /* continue on to set normal key for smaller DES operations */ + } + #endif /* WOLFSSL_ASYNC_CRYPT */ + + ret = DesSetKey(key + (dir == DES_ENCRYPTION ? 0:16), dir, des->key[0]); + if (ret != 0) + return ret; + + ret = DesSetKey(key + 8, !dir, des->key[1]); + if (ret != 0) + return ret; + + ret = DesSetKey(key + (dir == DES_DECRYPTION ? 0:16), dir, des->key[2]); + if (ret != 0) + return ret; + + return wc_Des3_SetIV(des, iv); + } + + static void DesRawProcessBlock(word32* lIn, word32* rIn, const word32* kptr) + { + word32 l = *lIn, r = *rIn, i; + + for (i=0; i<8; i++) + { + word32 work = rotrFixed(r, 4U) ^ kptr[4*i+0]; + l ^= Spbox[6][(work) & 0x3f] + ^ Spbox[4][(work >> 8) & 0x3f] + ^ Spbox[2][(work >> 16) & 0x3f] + ^ Spbox[0][(work >> 24) & 0x3f]; + work = r ^ kptr[4*i+1]; + l ^= Spbox[7][(work) & 0x3f] + ^ Spbox[5][(work >> 8) & 0x3f] + ^ Spbox[3][(work >> 16) & 0x3f] + ^ Spbox[1][(work >> 24) & 0x3f]; + + work = rotrFixed(l, 4U) ^ kptr[4*i+2]; + r ^= Spbox[6][(work) & 0x3f] + ^ Spbox[4][(work >> 8) & 0x3f] + ^ Spbox[2][(work >> 16) & 0x3f] + ^ Spbox[0][(work >> 24) & 0x3f]; + work = l ^ kptr[4*i+3]; + r ^= Spbox[7][(work) & 0x3f] + ^ Spbox[5][(work >> 8) & 0x3f] + ^ Spbox[3][(work >> 16) & 0x3f] + ^ Spbox[1][(work >> 24) & 0x3f]; + } + + *lIn = l; *rIn = r; + } + + static void DesProcessBlock(Des* des, const byte* in, byte* out) + { + word32 l, r; + + XMEMCPY(&l, in, sizeof(l)); + XMEMCPY(&r, in + sizeof(l), sizeof(r)); + #ifdef LITTLE_ENDIAN_ORDER + l = ByteReverseWord32(l); + r = ByteReverseWord32(r); + #endif + IPERM(&l,&r); + + DesRawProcessBlock(&l, &r, des->key); + + FPERM(&l,&r); + #ifdef LITTLE_ENDIAN_ORDER + l = ByteReverseWord32(l); + r = ByteReverseWord32(r); + #endif + XMEMCPY(out, &r, sizeof(r)); + XMEMCPY(out + sizeof(r), &l, sizeof(l)); + } + + static void Des3ProcessBlock(Des3* des, const byte* in, byte* out) + { + word32 l, r; + + XMEMCPY(&l, in, sizeof(l)); + XMEMCPY(&r, in + sizeof(l), sizeof(r)); + #ifdef LITTLE_ENDIAN_ORDER + l = ByteReverseWord32(l); + r = ByteReverseWord32(r); + #endif + IPERM(&l,&r); + + DesRawProcessBlock(&l, &r, des->key[0]); + DesRawProcessBlock(&r, &l, des->key[1]); + DesRawProcessBlock(&l, &r, des->key[2]); + + FPERM(&l,&r); + #ifdef LITTLE_ENDIAN_ORDER + l = ByteReverseWord32(l); + r = ByteReverseWord32(r); + #endif + XMEMCPY(out, &r, sizeof(r)); + XMEMCPY(out + sizeof(r), &l, sizeof(l)); + } + + int wc_Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz) + { + word32 blocks = sz / DES_BLOCK_SIZE; + + while (blocks--) { + xorbuf((byte*)des->reg, in, DES_BLOCK_SIZE); + DesProcessBlock(des, (byte*)des->reg, (byte*)des->reg); + XMEMCPY(out, des->reg, DES_BLOCK_SIZE); + + out += DES_BLOCK_SIZE; + in += DES_BLOCK_SIZE; + } + return 0; + } + + int wc_Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz) + { + word32 blocks = sz / DES_BLOCK_SIZE; + + while (blocks--) { + XMEMCPY(des->tmp, in, DES_BLOCK_SIZE); + DesProcessBlock(des, (byte*)des->tmp, out); + xorbuf(out, (byte*)des->reg, DES_BLOCK_SIZE); + XMEMCPY(des->reg, des->tmp, DES_BLOCK_SIZE); + + out += DES_BLOCK_SIZE; + in += DES_BLOCK_SIZE; + } + return 0; + } + + int wc_Des3_CbcEncrypt(Des3* des, byte* out, const byte* in, word32 sz) + { + word32 blocks; + + if (des == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + + #ifdef WOLF_CRYPTO_CB + if (des->devId != INVALID_DEVID) { + int ret = wc_CryptoCb_Des3Encrypt(des, out, in, sz); + if (ret != CRYPTOCB_UNAVAILABLE) + return ret; + /* fall-through when unavailable */ + } + #endif + + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_3DES) + if (des->asyncDev.marker == WOLFSSL_ASYNC_MARKER_3DES && + sz >= WC_ASYNC_THRESH_DES3_CBC) { + #if defined(HAVE_CAVIUM) + return NitroxDes3CbcEncrypt(des, out, in, sz); + #elif defined(HAVE_INTEL_QA) + return IntelQaSymDes3CbcEncrypt(&des->asyncDev, out, in, sz, + des->key_raw, DES3_KEYLEN, (byte*)des->iv_raw, DES3_IVLEN); + #else /* WOLFSSL_ASYNC_CRYPT_TEST */ + if (wc_AsyncTestInit(&des->asyncDev, ASYNC_TEST_DES3_CBC_ENCRYPT)) { + WC_ASYNC_TEST* testDev = &des->asyncDev.test; + testDev->des.des = des; + testDev->des.out = out; + testDev->des.in = in; + testDev->des.sz = sz; + return WC_PENDING_E; + } + #endif + } + #endif /* WOLFSSL_ASYNC_CRYPT */ + + blocks = sz / DES_BLOCK_SIZE; + while (blocks--) { + xorbuf((byte*)des->reg, in, DES_BLOCK_SIZE); + Des3ProcessBlock(des, (byte*)des->reg, (byte*)des->reg); + XMEMCPY(out, des->reg, DES_BLOCK_SIZE); + + out += DES_BLOCK_SIZE; + in += DES_BLOCK_SIZE; + } + return 0; + } + + + int wc_Des3_CbcDecrypt(Des3* des, byte* out, const byte* in, word32 sz) + { + word32 blocks; + + if (des == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + + #ifdef WOLF_CRYPTO_CB + if (des->devId != INVALID_DEVID) { + int ret = wc_CryptoCb_Des3Decrypt(des, out, in, sz); + if (ret != CRYPTOCB_UNAVAILABLE) + return ret; + /* fall-through when unavailable */ + } + #endif + + #if defined(WOLFSSL_ASYNC_CRYPT) + if (des->asyncDev.marker == WOLFSSL_ASYNC_MARKER_3DES && + sz >= WC_ASYNC_THRESH_DES3_CBC) { + #if defined(HAVE_CAVIUM) + return NitroxDes3CbcDecrypt(des, out, in, sz); + #elif defined(HAVE_INTEL_QA) + return IntelQaSymDes3CbcDecrypt(&des->asyncDev, out, in, sz, + des->key_raw, DES3_KEYLEN, (byte*)des->iv_raw, DES3_IVLEN); + #else /* WOLFSSL_ASYNC_CRYPT_TEST */ + if (wc_AsyncTestInit(&des->asyncDev, ASYNC_TEST_DES3_CBC_DECRYPT)) { + WC_ASYNC_TEST* testDev = &des->asyncDev.test; + testDev->des.des = des; + testDev->des.out = out; + testDev->des.in = in; + testDev->des.sz = sz; + return WC_PENDING_E; + } + #endif + } + #endif /* WOLFSSL_ASYNC_CRYPT */ + + blocks = sz / DES_BLOCK_SIZE; + while (blocks--) { + XMEMCPY(des->tmp, in, DES_BLOCK_SIZE); + Des3ProcessBlock(des, (byte*)des->tmp, out); + xorbuf(out, (byte*)des->reg, DES_BLOCK_SIZE); + XMEMCPY(des->reg, des->tmp, DES_BLOCK_SIZE); + + out += DES_BLOCK_SIZE; + in += DES_BLOCK_SIZE; + } + return 0; + } + + #ifdef WOLFSSL_DES_ECB + /* One block, compatibility only */ + int wc_Des_EcbEncrypt(Des* des, byte* out, const byte* in, word32 sz) + { + word32 blocks = sz / DES_BLOCK_SIZE; + + if (des == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + + while (blocks--) { + DesProcessBlock(des, in, out); + + out += DES_BLOCK_SIZE; + in += DES_BLOCK_SIZE; + } + return 0; + } + + int wc_Des3_EcbEncrypt(Des3* des, byte* out, const byte* in, word32 sz) + { + word32 blocks = sz / DES_BLOCK_SIZE; + + if (des == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + + while (blocks--) { + Des3ProcessBlock(des, in, out); + + out += DES_BLOCK_SIZE; + in += DES_BLOCK_SIZE; + } + return 0; + } + #endif /* WOLFSSL_DES_ECB */ + +#endif /* NEED_SOFT_DES */ + + +void wc_Des_SetIV(Des* des, const byte* iv) +{ + if (des && iv) + XMEMCPY(des->reg, iv, DES_BLOCK_SIZE); + else if (des) + XMEMSET(des->reg, 0, DES_BLOCK_SIZE); +} + +int wc_Des3_SetIV(Des3* des, const byte* iv) +{ + if (des == NULL) { + return BAD_FUNC_ARG; + } + if (des && iv) + XMEMCPY(des->reg, iv, DES_BLOCK_SIZE); + else if (des) + XMEMSET(des->reg, 0, DES_BLOCK_SIZE); + + return 0; +} + + +/* Initialize Des3 for use with async device */ +int wc_Des3Init(Des3* des3, void* heap, int devId) +{ + int ret = 0; + if (des3 == NULL) + return BAD_FUNC_ARG; + + des3->heap = heap; + +#ifdef WOLF_CRYPTO_CB + des3->devId = devId; + des3->devCtx = NULL; +#else + (void)devId; +#endif + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_3DES) + ret = wolfAsync_DevCtxInit(&des3->asyncDev, WOLFSSL_ASYNC_MARKER_3DES, + des3->heap, devId); +#endif + + return ret; +} + +/* Free Des3 from use with async device */ +void wc_Des3Free(Des3* des3) +{ + if (des3 == NULL) + return; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_3DES) + wolfAsync_DevCtxFree(&des3->asyncDev, WOLFSSL_ASYNC_MARKER_3DES); +#endif /* WOLFSSL_ASYNC_CRYPT */ +} + +#endif /* WOLFSSL_TI_CRYPT */ +#endif /* HAVE_FIPS */ +#endif /* NO_DES3 */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/dh.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/dh.c new file mode 100755 index 0000000..622d2f9 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/dh.c @@ -0,0 +1,2385 @@ +/* dh.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifndef NO_DH + +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + + /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ + #define FIPS_NO_WRAPPERS + + #ifdef USE_WINDOWS_API + #pragma code_seg(".fipsA$m") + #pragma const_seg(".fipsB$m") + #endif +#endif + +#include +#include +#include + +#ifdef WOLFSSL_HAVE_SP_DH +#include +#endif + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + + +/* +Possible DH enable options: + * NO_RSA: Overall control of DH default: on (not defined) + * WOLFSSL_OLD_PRIME_CHECK: Disables the new prime number check. It does not + directly effect this file, but it does speed up DH + removing the testing. It is not recommended to + disable the prime checking. default: off + +*/ + + +#if !defined(USER_MATH_LIB) && !defined(WOLFSSL_DH_CONST) + #include + #define XPOW(x,y) pow((x),(y)) + #define XLOG(x) log((x)) +#else + /* user's own math lib */ +#endif + +#ifdef HAVE_FFDHE_2048 +static const byte dh_ffdhe2048_p[] = { + 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 +}; +static const byte dh_ffdhe2048_g[] = { 0x02 }; +#ifdef HAVE_FFDHE_Q +static const byte dh_ffdhe2048_q[] = { + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xD6, 0xFC, 0x2A, 0x2C, 0x51, 0x5D, 0xA5, 0x4D, + 0x57, 0xEE, 0x2B, 0x10, 0x13, 0x9E, 0x9E, 0x78, + 0xEC, 0x5C, 0xE2, 0xC1, 0xE7, 0x16, 0x9B, 0x4A, + 0xD4, 0xF0, 0x9B, 0x20, 0x8A, 0x32, 0x19, 0xFD, + 0xE6, 0x49, 0xCE, 0xE7, 0x12, 0x4D, 0x9F, 0x7C, + 0xBE, 0x97, 0xF1, 0xB1, 0xB1, 0x86, 0x3A, 0xEC, + 0x7B, 0x40, 0xD9, 0x01, 0x57, 0x62, 0x30, 0xBD, + 0x69, 0xEF, 0x8F, 0x6A, 0xEA, 0xFE, 0xB2, 0xB0, + 0x92, 0x19, 0xFA, 0x8F, 0xAF, 0x83, 0x37, 0x68, + 0x42, 0xB1, 0xB2, 0xAA, 0x9E, 0xF6, 0x8D, 0x79, + 0xDA, 0xAB, 0x89, 0xAF, 0x3F, 0xAB, 0xE4, 0x9A, + 0xCC, 0x27, 0x86, 0x38, 0x70, 0x73, 0x45, 0xBB, + 0xF1, 0x53, 0x44, 0xED, 0x79, 0xF7, 0xF4, 0x39, + 0x0E, 0xF8, 0xAC, 0x50, 0x9B, 0x56, 0xF3, 0x9A, + 0x98, 0x56, 0x65, 0x27, 0xA4, 0x1D, 0x3C, 0xBD, + 0x5E, 0x05, 0x58, 0xC1, 0x59, 0x92, 0x7D, 0xB0, + 0xE8, 0x84, 0x54, 0xA5, 0xD9, 0x64, 0x71, 0xFD, + 0xDC, 0xB5, 0x6D, 0x5B, 0xB0, 0x6B, 0xFA, 0x34, + 0x0E, 0xA7, 0xA1, 0x51, 0xEF, 0x1C, 0xA6, 0xFA, + 0x57, 0x2B, 0x76, 0xF3, 0xB1, 0xB9, 0x5D, 0x8C, + 0x85, 0x83, 0xD3, 0xE4, 0x77, 0x05, 0x36, 0xB8, + 0x4F, 0x01, 0x7E, 0x70, 0xE6, 0xFB, 0xF1, 0x76, + 0x60, 0x1A, 0x02, 0x66, 0x94, 0x1A, 0x17, 0xB0, + 0xC8, 0xB9, 0x7F, 0x4E, 0x74, 0xC2, 0xC1, 0xFF, + 0xC7, 0x27, 0x89, 0x19, 0x77, 0x79, 0x40, 0xC1, + 0xE1, 0xFF, 0x1D, 0x8D, 0xA6, 0x37, 0xD6, 0xB9, + 0x9D, 0xDA, 0xFE, 0x5E, 0x17, 0x61, 0x10, 0x02, + 0xE2, 0xC7, 0x78, 0xC1, 0xBE, 0x8B, 0x41, 0xD9, + 0x63, 0x79, 0xA5, 0x13, 0x60, 0xD9, 0x77, 0xFD, + 0x44, 0x35, 0xA1, 0x1C, 0x30, 0x94, 0x2E, 0x4B, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; +#endif /* HAVE_FFDHE_Q */ + +const DhParams* wc_Dh_ffdhe2048_Get(void) +{ + static const DhParams ffdhe2048 = { + #ifdef HAVE_FFDHE_Q + dh_ffdhe2048_q, sizeof(dh_ffdhe2048_q), + #endif /* HAVE_FFDHE_Q */ + dh_ffdhe2048_p, sizeof(dh_ffdhe2048_p), + dh_ffdhe2048_g, sizeof(dh_ffdhe2048_g) + }; + return &ffdhe2048; +} +#endif + +#ifdef HAVE_FFDHE_3072 +static const byte dh_ffdhe3072_p[] = { + 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 +}; +static const byte dh_ffdhe3072_g[] = { 0x02 }; +#ifdef HAVE_FFDHE_Q +static const byte dh_ffdhe3072_q[] = { + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xD6, 0xFC, 0x2A, 0x2C, 0x51, 0x5D, 0xA5, 0x4D, + 0x57, 0xEE, 0x2B, 0x10, 0x13, 0x9E, 0x9E, 0x78, + 0xEC, 0x5C, 0xE2, 0xC1, 0xE7, 0x16, 0x9B, 0x4A, + 0xD4, 0xF0, 0x9B, 0x20, 0x8A, 0x32, 0x19, 0xFD, + 0xE6, 0x49, 0xCE, 0xE7, 0x12, 0x4D, 0x9F, 0x7C, + 0xBE, 0x97, 0xF1, 0xB1, 0xB1, 0x86, 0x3A, 0xEC, + 0x7B, 0x40, 0xD9, 0x01, 0x57, 0x62, 0x30, 0xBD, + 0x69, 0xEF, 0x8F, 0x6A, 0xEA, 0xFE, 0xB2, 0xB0, + 0x92, 0x19, 0xFA, 0x8F, 0xAF, 0x83, 0x37, 0x68, + 0x42, 0xB1, 0xB2, 0xAA, 0x9E, 0xF6, 0x8D, 0x79, + 0xDA, 0xAB, 0x89, 0xAF, 0x3F, 0xAB, 0xE4, 0x9A, + 0xCC, 0x27, 0x86, 0x38, 0x70, 0x73, 0x45, 0xBB, + 0xF1, 0x53, 0x44, 0xED, 0x79, 0xF7, 0xF4, 0x39, + 0x0E, 0xF8, 0xAC, 0x50, 0x9B, 0x56, 0xF3, 0x9A, + 0x98, 0x56, 0x65, 0x27, 0xA4, 0x1D, 0x3C, 0xBD, + 0x5E, 0x05, 0x58, 0xC1, 0x59, 0x92, 0x7D, 0xB0, + 0xE8, 0x84, 0x54, 0xA5, 0xD9, 0x64, 0x71, 0xFD, + 0xDC, 0xB5, 0x6D, 0x5B, 0xB0, 0x6B, 0xFA, 0x34, + 0x0E, 0xA7, 0xA1, 0x51, 0xEF, 0x1C, 0xA6, 0xFA, + 0x57, 0x2B, 0x76, 0xF3, 0xB1, 0xB9, 0x5D, 0x8C, + 0x85, 0x83, 0xD3, 0xE4, 0x77, 0x05, 0x36, 0xB8, + 0x4F, 0x01, 0x7E, 0x70, 0xE6, 0xFB, 0xF1, 0x76, + 0x60, 0x1A, 0x02, 0x66, 0x94, 0x1A, 0x17, 0xB0, + 0xC8, 0xB9, 0x7F, 0x4E, 0x74, 0xC2, 0xC1, 0xFF, + 0xC7, 0x27, 0x89, 0x19, 0x77, 0x79, 0x40, 0xC1, + 0xE1, 0xFF, 0x1D, 0x8D, 0xA6, 0x37, 0xD6, 0xB9, + 0x9D, 0xDA, 0xFE, 0x5E, 0x17, 0x61, 0x10, 0x02, + 0xE2, 0xC7, 0x78, 0xC1, 0xBE, 0x8B, 0x41, 0xD9, + 0x63, 0x79, 0xA5, 0x13, 0x60, 0xD9, 0x77, 0xFD, + 0x44, 0x35, 0xA1, 0x1C, 0x30, 0x8F, 0xE7, 0xEE, + 0x6F, 0x1A, 0xAD, 0x9D, 0xB2, 0x8C, 0x81, 0xAD, + 0xDE, 0x1A, 0x7A, 0x6F, 0x7C, 0xCE, 0x01, 0x1C, + 0x30, 0xDA, 0x37, 0xE4, 0xEB, 0x73, 0x64, 0x83, + 0xBD, 0x6C, 0x8E, 0x93, 0x48, 0xFB, 0xFB, 0xF7, + 0x2C, 0xC6, 0x58, 0x7D, 0x60, 0xC3, 0x6C, 0x8E, + 0x57, 0x7F, 0x09, 0x84, 0xC2, 0x89, 0xC9, 0x38, + 0x5A, 0x09, 0x86, 0x49, 0xDE, 0x21, 0xBC, 0xA2, + 0x7A, 0x7E, 0xA2, 0x29, 0x71, 0x6B, 0xA6, 0xE9, + 0xB2, 0x79, 0x71, 0x0F, 0x38, 0xFA, 0xA5, 0xFF, + 0xAE, 0x57, 0x41, 0x55, 0xCE, 0x4E, 0xFB, 0x4F, + 0x74, 0x36, 0x95, 0xE2, 0x91, 0x1B, 0x1D, 0x06, + 0xD5, 0xE2, 0x90, 0xCB, 0xCD, 0x86, 0xF5, 0x6D, + 0x0E, 0xDF, 0xCD, 0x21, 0x6A, 0xE2, 0x24, 0x27, + 0x05, 0x5E, 0x68, 0x35, 0xFD, 0x29, 0xEE, 0xF7, + 0x9E, 0x0D, 0x90, 0x77, 0x1F, 0xEA, 0xCE, 0xBE, + 0x12, 0xF2, 0x0E, 0x95, 0xB3, 0x63, 0x17, 0x1B, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; +#endif /* HAVE_FFDHE_Q */ + +const DhParams* wc_Dh_ffdhe3072_Get(void) +{ + static const DhParams ffdhe3072 = { + #ifdef HAVE_FFDHE_Q + dh_ffdhe3072_q, sizeof(dh_ffdhe3072_q), + #endif /* HAVE_FFDHE_Q */ + dh_ffdhe3072_p, sizeof(dh_ffdhe3072_p), + dh_ffdhe3072_g, sizeof(dh_ffdhe3072_g) + }; + return &ffdhe3072; +} +#endif + +#ifdef HAVE_FFDHE_4096 +static const byte dh_ffdhe4096_p[] = { + 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 +}; +static const byte dh_ffdhe4096_g[] = { 0x02 }; +#ifdef HAVE_FFDHE_Q +static const byte dh_ffdhe4096_q[] = { + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xD6, 0xFC, 0x2A, 0x2C, 0x51, 0x5D, 0xA5, 0x4D, + 0x57, 0xEE, 0x2B, 0x10, 0x13, 0x9E, 0x9E, 0x78, + 0xEC, 0x5C, 0xE2, 0xC1, 0xE7, 0x16, 0x9B, 0x4A, + 0xD4, 0xF0, 0x9B, 0x20, 0x8A, 0x32, 0x19, 0xFD, + 0xE6, 0x49, 0xCE, 0xE7, 0x12, 0x4D, 0x9F, 0x7C, + 0xBE, 0x97, 0xF1, 0xB1, 0xB1, 0x86, 0x3A, 0xEC, + 0x7B, 0x40, 0xD9, 0x01, 0x57, 0x62, 0x30, 0xBD, + 0x69, 0xEF, 0x8F, 0x6A, 0xEA, 0xFE, 0xB2, 0xB0, + 0x92, 0x19, 0xFA, 0x8F, 0xAF, 0x83, 0x37, 0x68, + 0x42, 0xB1, 0xB2, 0xAA, 0x9E, 0xF6, 0x8D, 0x79, + 0xDA, 0xAB, 0x89, 0xAF, 0x3F, 0xAB, 0xE4, 0x9A, + 0xCC, 0x27, 0x86, 0x38, 0x70, 0x73, 0x45, 0xBB, + 0xF1, 0x53, 0x44, 0xED, 0x79, 0xF7, 0xF4, 0x39, + 0x0E, 0xF8, 0xAC, 0x50, 0x9B, 0x56, 0xF3, 0x9A, + 0x98, 0x56, 0x65, 0x27, 0xA4, 0x1D, 0x3C, 0xBD, + 0x5E, 0x05, 0x58, 0xC1, 0x59, 0x92, 0x7D, 0xB0, + 0xE8, 0x84, 0x54, 0xA5, 0xD9, 0x64, 0x71, 0xFD, + 0xDC, 0xB5, 0x6D, 0x5B, 0xB0, 0x6B, 0xFA, 0x34, + 0x0E, 0xA7, 0xA1, 0x51, 0xEF, 0x1C, 0xA6, 0xFA, + 0x57, 0x2B, 0x76, 0xF3, 0xB1, 0xB9, 0x5D, 0x8C, + 0x85, 0x83, 0xD3, 0xE4, 0x77, 0x05, 0x36, 0xB8, + 0x4F, 0x01, 0x7E, 0x70, 0xE6, 0xFB, 0xF1, 0x76, + 0x60, 0x1A, 0x02, 0x66, 0x94, 0x1A, 0x17, 0xB0, + 0xC8, 0xB9, 0x7F, 0x4E, 0x74, 0xC2, 0xC1, 0xFF, + 0xC7, 0x27, 0x89, 0x19, 0x77, 0x79, 0x40, 0xC1, + 0xE1, 0xFF, 0x1D, 0x8D, 0xA6, 0x37, 0xD6, 0xB9, + 0x9D, 0xDA, 0xFE, 0x5E, 0x17, 0x61, 0x10, 0x02, + 0xE2, 0xC7, 0x78, 0xC1, 0xBE, 0x8B, 0x41, 0xD9, + 0x63, 0x79, 0xA5, 0x13, 0x60, 0xD9, 0x77, 0xFD, + 0x44, 0x35, 0xA1, 0x1C, 0x30, 0x8F, 0xE7, 0xEE, + 0x6F, 0x1A, 0xAD, 0x9D, 0xB2, 0x8C, 0x81, 0xAD, + 0xDE, 0x1A, 0x7A, 0x6F, 0x7C, 0xCE, 0x01, 0x1C, + 0x30, 0xDA, 0x37, 0xE4, 0xEB, 0x73, 0x64, 0x83, + 0xBD, 0x6C, 0x8E, 0x93, 0x48, 0xFB, 0xFB, 0xF7, + 0x2C, 0xC6, 0x58, 0x7D, 0x60, 0xC3, 0x6C, 0x8E, + 0x57, 0x7F, 0x09, 0x84, 0xC2, 0x89, 0xC9, 0x38, + 0x5A, 0x09, 0x86, 0x49, 0xDE, 0x21, 0xBC, 0xA2, + 0x7A, 0x7E, 0xA2, 0x29, 0x71, 0x6B, 0xA6, 0xE9, + 0xB2, 0x79, 0x71, 0x0F, 0x38, 0xFA, 0xA5, 0xFF, + 0xAE, 0x57, 0x41, 0x55, 0xCE, 0x4E, 0xFB, 0x4F, + 0x74, 0x36, 0x95, 0xE2, 0x91, 0x1B, 0x1D, 0x06, + 0xD5, 0xE2, 0x90, 0xCB, 0xCD, 0x86, 0xF5, 0x6D, + 0x0E, 0xDF, 0xCD, 0x21, 0x6A, 0xE2, 0x24, 0x27, + 0x05, 0x5E, 0x68, 0x35, 0xFD, 0x29, 0xEE, 0xF7, + 0x9E, 0x0D, 0x90, 0x77, 0x1F, 0xEA, 0xCE, 0xBE, + 0x12, 0xF2, 0x0E, 0x95, 0xB3, 0x4F, 0x0F, 0x78, + 0xB7, 0x37, 0xA9, 0x61, 0x8B, 0x26, 0xFA, 0x7D, + 0xBC, 0x98, 0x74, 0xF2, 0x72, 0xC4, 0x2B, 0xDB, + 0x56, 0x3E, 0xAF, 0xA1, 0x6B, 0x4F, 0xB6, 0x8C, + 0x3B, 0xB1, 0xE7, 0x8E, 0xAA, 0x81, 0xA0, 0x02, + 0x43, 0xFA, 0xAD, 0xD2, 0xBF, 0x18, 0xE6, 0x3D, + 0x38, 0x9A, 0xE4, 0x43, 0x77, 0xDA, 0x18, 0xC5, + 0x76, 0xB5, 0x0F, 0x00, 0x96, 0xCF, 0x34, 0x19, + 0x54, 0x83, 0xB0, 0x05, 0x48, 0xC0, 0x98, 0x62, + 0x36, 0xE3, 0xBC, 0x7C, 0xB8, 0xD6, 0x80, 0x1C, + 0x04, 0x94, 0xCC, 0xD1, 0x99, 0xE5, 0xC5, 0xBD, + 0x0D, 0x0E, 0xDC, 0x9E, 0xB8, 0xA0, 0x00, 0x1E, + 0x15, 0x27, 0x67, 0x54, 0xFC, 0xC6, 0x85, 0x66, + 0x05, 0x41, 0x48, 0xE6, 0xE7, 0x64, 0xBE, 0xE7, + 0xC7, 0x64, 0xDA, 0xAD, 0x3F, 0xC4, 0x52, 0x35, + 0xA6, 0xDA, 0xD4, 0x28, 0xFA, 0x20, 0xC1, 0x70, + 0xE3, 0x45, 0x00, 0x3F, 0x2F, 0x32, 0xAF, 0xB5, + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; +#endif /* HAVE_FFDHE_Q */ + +const DhParams* wc_Dh_ffdhe4096_Get(void) +{ + static const DhParams ffdhe4096 = { + #ifdef HAVE_FFDHE_Q + dh_ffdhe4096_q, sizeof(dh_ffdhe4096_q), + #endif /* HAVE_FFDHE_Q */ + dh_ffdhe4096_p, sizeof(dh_ffdhe4096_p), + dh_ffdhe4096_g, sizeof(dh_ffdhe4096_g) + }; + return &ffdhe4096; +} +#endif + +#ifdef HAVE_FFDHE_6144 +static const byte dh_ffdhe6144_p[] = { + 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 +}; +static const byte dh_ffdhe6144_g[] = { 0x02 }; +#ifdef HAVE_FFDHE_Q +static const byte dh_ffdhe6144_q[] = { + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xD6, 0xFC, 0x2A, 0x2C, 0x51, 0x5D, 0xA5, 0x4D, + 0x57, 0xEE, 0x2B, 0x10, 0x13, 0x9E, 0x9E, 0x78, + 0xEC, 0x5C, 0xE2, 0xC1, 0xE7, 0x16, 0x9B, 0x4A, + 0xD4, 0xF0, 0x9B, 0x20, 0x8A, 0x32, 0x19, 0xFD, + 0xE6, 0x49, 0xCE, 0xE7, 0x12, 0x4D, 0x9F, 0x7C, + 0xBE, 0x97, 0xF1, 0xB1, 0xB1, 0x86, 0x3A, 0xEC, + 0x7B, 0x40, 0xD9, 0x01, 0x57, 0x62, 0x30, 0xBD, + 0x69, 0xEF, 0x8F, 0x6A, 0xEA, 0xFE, 0xB2, 0xB0, + 0x92, 0x19, 0xFA, 0x8F, 0xAF, 0x83, 0x37, 0x68, + 0x42, 0xB1, 0xB2, 0xAA, 0x9E, 0xF6, 0x8D, 0x79, + 0xDA, 0xAB, 0x89, 0xAF, 0x3F, 0xAB, 0xE4, 0x9A, + 0xCC, 0x27, 0x86, 0x38, 0x70, 0x73, 0x45, 0xBB, + 0xF1, 0x53, 0x44, 0xED, 0x79, 0xF7, 0xF4, 0x39, + 0x0E, 0xF8, 0xAC, 0x50, 0x9B, 0x56, 0xF3, 0x9A, + 0x98, 0x56, 0x65, 0x27, 0xA4, 0x1D, 0x3C, 0xBD, + 0x5E, 0x05, 0x58, 0xC1, 0x59, 0x92, 0x7D, 0xB0, + 0xE8, 0x84, 0x54, 0xA5, 0xD9, 0x64, 0x71, 0xFD, + 0xDC, 0xB5, 0x6D, 0x5B, 0xB0, 0x6B, 0xFA, 0x34, + 0x0E, 0xA7, 0xA1, 0x51, 0xEF, 0x1C, 0xA6, 0xFA, + 0x57, 0x2B, 0x76, 0xF3, 0xB1, 0xB9, 0x5D, 0x8C, + 0x85, 0x83, 0xD3, 0xE4, 0x77, 0x05, 0x36, 0xB8, + 0x4F, 0x01, 0x7E, 0x70, 0xE6, 0xFB, 0xF1, 0x76, + 0x60, 0x1A, 0x02, 0x66, 0x94, 0x1A, 0x17, 0xB0, + 0xC8, 0xB9, 0x7F, 0x4E, 0x74, 0xC2, 0xC1, 0xFF, + 0xC7, 0x27, 0x89, 0x19, 0x77, 0x79, 0x40, 0xC1, + 0xE1, 0xFF, 0x1D, 0x8D, 0xA6, 0x37, 0xD6, 0xB9, + 0x9D, 0xDA, 0xFE, 0x5E, 0x17, 0x61, 0x10, 0x02, + 0xE2, 0xC7, 0x78, 0xC1, 0xBE, 0x8B, 0x41, 0xD9, + 0x63, 0x79, 0xA5, 0x13, 0x60, 0xD9, 0x77, 0xFD, + 0x44, 0x35, 0xA1, 0x1C, 0x30, 0x8F, 0xE7, 0xEE, + 0x6F, 0x1A, 0xAD, 0x9D, 0xB2, 0x8C, 0x81, 0xAD, + 0xDE, 0x1A, 0x7A, 0x6F, 0x7C, 0xCE, 0x01, 0x1C, + 0x30, 0xDA, 0x37, 0xE4, 0xEB, 0x73, 0x64, 0x83, + 0xBD, 0x6C, 0x8E, 0x93, 0x48, 0xFB, 0xFB, 0xF7, + 0x2C, 0xC6, 0x58, 0x7D, 0x60, 0xC3, 0x6C, 0x8E, + 0x57, 0x7F, 0x09, 0x84, 0xC2, 0x89, 0xC9, 0x38, + 0x5A, 0x09, 0x86, 0x49, 0xDE, 0x21, 0xBC, 0xA2, + 0x7A, 0x7E, 0xA2, 0x29, 0x71, 0x6B, 0xA6, 0xE9, + 0xB2, 0x79, 0x71, 0x0F, 0x38, 0xFA, 0xA5, 0xFF, + 0xAE, 0x57, 0x41, 0x55, 0xCE, 0x4E, 0xFB, 0x4F, + 0x74, 0x36, 0x95, 0xE2, 0x91, 0x1B, 0x1D, 0x06, + 0xD5, 0xE2, 0x90, 0xCB, 0xCD, 0x86, 0xF5, 0x6D, + 0x0E, 0xDF, 0xCD, 0x21, 0x6A, 0xE2, 0x24, 0x27, + 0x05, 0x5E, 0x68, 0x35, 0xFD, 0x29, 0xEE, 0xF7, + 0x9E, 0x0D, 0x90, 0x77, 0x1F, 0xEA, 0xCE, 0xBE, + 0x12, 0xF2, 0x0E, 0x95, 0xB3, 0x4F, 0x0F, 0x78, + 0xB7, 0x37, 0xA9, 0x61, 0x8B, 0x26, 0xFA, 0x7D, + 0xBC, 0x98, 0x74, 0xF2, 0x72, 0xC4, 0x2B, 0xDB, + 0x56, 0x3E, 0xAF, 0xA1, 0x6B, 0x4F, 0xB6, 0x8C, + 0x3B, 0xB1, 0xE7, 0x8E, 0xAA, 0x81, 0xA0, 0x02, + 0x43, 0xFA, 0xAD, 0xD2, 0xBF, 0x18, 0xE6, 0x3D, + 0x38, 0x9A, 0xE4, 0x43, 0x77, 0xDA, 0x18, 0xC5, + 0x76, 0xB5, 0x0F, 0x00, 0x96, 0xCF, 0x34, 0x19, + 0x54, 0x83, 0xB0, 0x05, 0x48, 0xC0, 0x98, 0x62, + 0x36, 0xE3, 0xBC, 0x7C, 0xB8, 0xD6, 0x80, 0x1C, + 0x04, 0x94, 0xCC, 0xD1, 0x99, 0xE5, 0xC5, 0xBD, + 0x0D, 0x0E, 0xDC, 0x9E, 0xB8, 0xA0, 0x00, 0x1E, + 0x15, 0x27, 0x67, 0x54, 0xFC, 0xC6, 0x85, 0x66, + 0x05, 0x41, 0x48, 0xE6, 0xE7, 0x64, 0xBE, 0xE7, + 0xC7, 0x64, 0xDA, 0xAD, 0x3F, 0xC4, 0x52, 0x35, + 0xA6, 0xDA, 0xD4, 0x28, 0xFA, 0x20, 0xC1, 0x70, + 0xE3, 0x45, 0x00, 0x3F, 0x2F, 0x06, 0xEC, 0x81, + 0x05, 0xFE, 0xB2, 0x5B, 0x22, 0x81, 0xB6, 0x3D, + 0x27, 0x33, 0xBE, 0x96, 0x1C, 0x29, 0x95, 0x1D, + 0x11, 0xDD, 0x22, 0x21, 0x65, 0x7A, 0x9F, 0x53, + 0x1D, 0xDA, 0x2A, 0x19, 0x4D, 0xBB, 0x12, 0x64, + 0x48, 0xBD, 0xEE, 0xB2, 0x58, 0xE0, 0x7E, 0xA6, + 0x59, 0xC7, 0x46, 0x19, 0xA6, 0x38, 0x0E, 0x1D, + 0x66, 0xD6, 0x83, 0x2B, 0xFE, 0x67, 0xF6, 0x38, + 0xCD, 0x8F, 0xAE, 0x1F, 0x27, 0x23, 0x02, 0x0F, + 0x9C, 0x40, 0xA3, 0xFD, 0xA6, 0x7E, 0xDA, 0x3B, + 0xD2, 0x92, 0x38, 0xFB, 0xD4, 0xD4, 0xB4, 0x88, + 0x5C, 0x2A, 0x99, 0x17, 0x6D, 0xB1, 0xA0, 0x6C, + 0x50, 0x07, 0x78, 0x49, 0x1A, 0x82, 0x88, 0xF1, + 0x85, 0x5F, 0x60, 0xFF, 0xFC, 0xF1, 0xD1, 0x37, + 0x3F, 0xD9, 0x4F, 0xC6, 0x0C, 0x18, 0x11, 0xE1, + 0xAC, 0x3F, 0x1C, 0x6D, 0x00, 0x3B, 0xEC, 0xDA, + 0x3B, 0x1F, 0x27, 0x25, 0xCA, 0x59, 0x5D, 0xE0, + 0xCA, 0x63, 0x32, 0x8F, 0x3B, 0xE5, 0x7C, 0xC9, + 0x77, 0x55, 0x60, 0x11, 0x95, 0x14, 0x0D, 0xFB, + 0x59, 0xD3, 0x9C, 0xE0, 0x91, 0x30, 0x8B, 0x41, + 0x05, 0x74, 0x6D, 0xAC, 0x23, 0xD3, 0x3E, 0x5F, + 0x7C, 0xE4, 0x84, 0x8D, 0xA3, 0x16, 0xA9, 0xC6, + 0x6B, 0x95, 0x81, 0xBA, 0x35, 0x73, 0xBF, 0xAF, + 0x31, 0x14, 0x96, 0x18, 0x8A, 0xB1, 0x54, 0x23, + 0x28, 0x2E, 0xE4, 0x16, 0xDC, 0x2A, 0x19, 0xC5, + 0x72, 0x4F, 0xA9, 0x1A, 0xE4, 0xAD, 0xC8, 0x8B, + 0xC6, 0x67, 0x96, 0xEA, 0xE5, 0x67, 0x7A, 0x01, + 0xF6, 0x4E, 0x8C, 0x08, 0x63, 0x13, 0x95, 0x82, + 0x2D, 0x9D, 0xB8, 0xFC, 0xEE, 0x35, 0xC0, 0x6B, + 0x1F, 0xEE, 0xA5, 0x47, 0x4D, 0x6D, 0x8F, 0x34, + 0xB1, 0x53, 0x4A, 0x93, 0x6A, 0x18, 0xB0, 0xE0, + 0xD2, 0x0E, 0xAB, 0x86, 0xBC, 0x9C, 0x6D, 0x6A, + 0x52, 0x07, 0x19, 0x4E, 0x68, 0x72, 0x07, 0x32, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; +#endif /* HAVE_FFDHE_Q */ + +const DhParams* wc_Dh_ffdhe6144_Get(void) +{ + static const DhParams ffdhe6144 = { + #ifdef HAVE_FFDHE_Q + dh_ffdhe6144_q, sizeof(dh_ffdhe6144_q), + #endif /* HAVE_FFDHE_Q */ + dh_ffdhe6144_p, sizeof(dh_ffdhe6144_p), + dh_ffdhe6144_g, sizeof(dh_ffdhe6144_g) + }; + return &ffdhe6144; +} +#endif + +#ifdef HAVE_FFDHE_8192 +static const byte dh_ffdhe8192_p[] = { + 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 +}; +static const byte dh_ffdhe8192_g[] = { 0x02 }; +#ifdef HAVE_FFDHE_Q +static const byte dh_ffdhe8192_q[] = { + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xD6, 0xFC, 0x2A, 0x2C, 0x51, 0x5D, 0xA5, 0x4D, + 0x57, 0xEE, 0x2B, 0x10, 0x13, 0x9E, 0x9E, 0x78, + 0xEC, 0x5C, 0xE2, 0xC1, 0xE7, 0x16, 0x9B, 0x4A, + 0xD4, 0xF0, 0x9B, 0x20, 0x8A, 0x32, 0x19, 0xFD, + 0xE6, 0x49, 0xCE, 0xE7, 0x12, 0x4D, 0x9F, 0x7C, + 0xBE, 0x97, 0xF1, 0xB1, 0xB1, 0x86, 0x3A, 0xEC, + 0x7B, 0x40, 0xD9, 0x01, 0x57, 0x62, 0x30, 0xBD, + 0x69, 0xEF, 0x8F, 0x6A, 0xEA, 0xFE, 0xB2, 0xB0, + 0x92, 0x19, 0xFA, 0x8F, 0xAF, 0x83, 0x37, 0x68, + 0x42, 0xB1, 0xB2, 0xAA, 0x9E, 0xF6, 0x8D, 0x79, + 0xDA, 0xAB, 0x89, 0xAF, 0x3F, 0xAB, 0xE4, 0x9A, + 0xCC, 0x27, 0x86, 0x38, 0x70, 0x73, 0x45, 0xBB, + 0xF1, 0x53, 0x44, 0xED, 0x79, 0xF7, 0xF4, 0x39, + 0x0E, 0xF8, 0xAC, 0x50, 0x9B, 0x56, 0xF3, 0x9A, + 0x98, 0x56, 0x65, 0x27, 0xA4, 0x1D, 0x3C, 0xBD, + 0x5E, 0x05, 0x58, 0xC1, 0x59, 0x92, 0x7D, 0xB0, + 0xE8, 0x84, 0x54, 0xA5, 0xD9, 0x64, 0x71, 0xFD, + 0xDC, 0xB5, 0x6D, 0x5B, 0xB0, 0x6B, 0xFA, 0x34, + 0x0E, 0xA7, 0xA1, 0x51, 0xEF, 0x1C, 0xA6, 0xFA, + 0x57, 0x2B, 0x76, 0xF3, 0xB1, 0xB9, 0x5D, 0x8C, + 0x85, 0x83, 0xD3, 0xE4, 0x77, 0x05, 0x36, 0xB8, + 0x4F, 0x01, 0x7E, 0x70, 0xE6, 0xFB, 0xF1, 0x76, + 0x60, 0x1A, 0x02, 0x66, 0x94, 0x1A, 0x17, 0xB0, + 0xC8, 0xB9, 0x7F, 0x4E, 0x74, 0xC2, 0xC1, 0xFF, + 0xC7, 0x27, 0x89, 0x19, 0x77, 0x79, 0x40, 0xC1, + 0xE1, 0xFF, 0x1D, 0x8D, 0xA6, 0x37, 0xD6, 0xB9, + 0x9D, 0xDA, 0xFE, 0x5E, 0x17, 0x61, 0x10, 0x02, + 0xE2, 0xC7, 0x78, 0xC1, 0xBE, 0x8B, 0x41, 0xD9, + 0x63, 0x79, 0xA5, 0x13, 0x60, 0xD9, 0x77, 0xFD, + 0x44, 0x35, 0xA1, 0x1C, 0x30, 0x8F, 0xE7, 0xEE, + 0x6F, 0x1A, 0xAD, 0x9D, 0xB2, 0x8C, 0x81, 0xAD, + 0xDE, 0x1A, 0x7A, 0x6F, 0x7C, 0xCE, 0x01, 0x1C, + 0x30, 0xDA, 0x37, 0xE4, 0xEB, 0x73, 0x64, 0x83, + 0xBD, 0x6C, 0x8E, 0x93, 0x48, 0xFB, 0xFB, 0xF7, + 0x2C, 0xC6, 0x58, 0x7D, 0x60, 0xC3, 0x6C, 0x8E, + 0x57, 0x7F, 0x09, 0x84, 0xC2, 0x89, 0xC9, 0x38, + 0x5A, 0x09, 0x86, 0x49, 0xDE, 0x21, 0xBC, 0xA2, + 0x7A, 0x7E, 0xA2, 0x29, 0x71, 0x6B, 0xA6, 0xE9, + 0xB2, 0x79, 0x71, 0x0F, 0x38, 0xFA, 0xA5, 0xFF, + 0xAE, 0x57, 0x41, 0x55, 0xCE, 0x4E, 0xFB, 0x4F, + 0x74, 0x36, 0x95, 0xE2, 0x91, 0x1B, 0x1D, 0x06, + 0xD5, 0xE2, 0x90, 0xCB, 0xCD, 0x86, 0xF5, 0x6D, + 0x0E, 0xDF, 0xCD, 0x21, 0x6A, 0xE2, 0x24, 0x27, + 0x05, 0x5E, 0x68, 0x35, 0xFD, 0x29, 0xEE, 0xF7, + 0x9E, 0x0D, 0x90, 0x77, 0x1F, 0xEA, 0xCE, 0xBE, + 0x12, 0xF2, 0x0E, 0x95, 0xB3, 0x4F, 0x0F, 0x78, + 0xB7, 0x37, 0xA9, 0x61, 0x8B, 0x26, 0xFA, 0x7D, + 0xBC, 0x98, 0x74, 0xF2, 0x72, 0xC4, 0x2B, 0xDB, + 0x56, 0x3E, 0xAF, 0xA1, 0x6B, 0x4F, 0xB6, 0x8C, + 0x3B, 0xB1, 0xE7, 0x8E, 0xAA, 0x81, 0xA0, 0x02, + 0x43, 0xFA, 0xAD, 0xD2, 0xBF, 0x18, 0xE6, 0x3D, + 0x38, 0x9A, 0xE4, 0x43, 0x77, 0xDA, 0x18, 0xC5, + 0x76, 0xB5, 0x0F, 0x00, 0x96, 0xCF, 0x34, 0x19, + 0x54, 0x83, 0xB0, 0x05, 0x48, 0xC0, 0x98, 0x62, + 0x36, 0xE3, 0xBC, 0x7C, 0xB8, 0xD6, 0x80, 0x1C, + 0x04, 0x94, 0xCC, 0xD1, 0x99, 0xE5, 0xC5, 0xBD, + 0x0D, 0x0E, 0xDC, 0x9E, 0xB8, 0xA0, 0x00, 0x1E, + 0x15, 0x27, 0x67, 0x54, 0xFC, 0xC6, 0x85, 0x66, + 0x05, 0x41, 0x48, 0xE6, 0xE7, 0x64, 0xBE, 0xE7, + 0xC7, 0x64, 0xDA, 0xAD, 0x3F, 0xC4, 0x52, 0x35, + 0xA6, 0xDA, 0xD4, 0x28, 0xFA, 0x20, 0xC1, 0x70, + 0xE3, 0x45, 0x00, 0x3F, 0x2F, 0x06, 0xEC, 0x81, + 0x05, 0xFE, 0xB2, 0x5B, 0x22, 0x81, 0xB6, 0x3D, + 0x27, 0x33, 0xBE, 0x96, 0x1C, 0x29, 0x95, 0x1D, + 0x11, 0xDD, 0x22, 0x21, 0x65, 0x7A, 0x9F, 0x53, + 0x1D, 0xDA, 0x2A, 0x19, 0x4D, 0xBB, 0x12, 0x64, + 0x48, 0xBD, 0xEE, 0xB2, 0x58, 0xE0, 0x7E, 0xA6, + 0x59, 0xC7, 0x46, 0x19, 0xA6, 0x38, 0x0E, 0x1D, + 0x66, 0xD6, 0x83, 0x2B, 0xFE, 0x67, 0xF6, 0x38, + 0xCD, 0x8F, 0xAE, 0x1F, 0x27, 0x23, 0x02, 0x0F, + 0x9C, 0x40, 0xA3, 0xFD, 0xA6, 0x7E, 0xDA, 0x3B, + 0xD2, 0x92, 0x38, 0xFB, 0xD4, 0xD4, 0xB4, 0x88, + 0x5C, 0x2A, 0x99, 0x17, 0x6D, 0xB1, 0xA0, 0x6C, + 0x50, 0x07, 0x78, 0x49, 0x1A, 0x82, 0x88, 0xF1, + 0x85, 0x5F, 0x60, 0xFF, 0xFC, 0xF1, 0xD1, 0x37, + 0x3F, 0xD9, 0x4F, 0xC6, 0x0C, 0x18, 0x11, 0xE1, + 0xAC, 0x3F, 0x1C, 0x6D, 0x00, 0x3B, 0xEC, 0xDA, + 0x3B, 0x1F, 0x27, 0x25, 0xCA, 0x59, 0x5D, 0xE0, + 0xCA, 0x63, 0x32, 0x8F, 0x3B, 0xE5, 0x7C, 0xC9, + 0x77, 0x55, 0x60, 0x11, 0x95, 0x14, 0x0D, 0xFB, + 0x59, 0xD3, 0x9C, 0xE0, 0x91, 0x30, 0x8B, 0x41, + 0x05, 0x74, 0x6D, 0xAC, 0x23, 0xD3, 0x3E, 0x5F, + 0x7C, 0xE4, 0x84, 0x8D, 0xA3, 0x16, 0xA9, 0xC6, + 0x6B, 0x95, 0x81, 0xBA, 0x35, 0x73, 0xBF, 0xAF, + 0x31, 0x14, 0x96, 0x18, 0x8A, 0xB1, 0x54, 0x23, + 0x28, 0x2E, 0xE4, 0x16, 0xDC, 0x2A, 0x19, 0xC5, + 0x72, 0x4F, 0xA9, 0x1A, 0xE4, 0xAD, 0xC8, 0x8B, + 0xC6, 0x67, 0x96, 0xEA, 0xE5, 0x67, 0x7A, 0x01, + 0xF6, 0x4E, 0x8C, 0x08, 0x63, 0x13, 0x95, 0x82, + 0x2D, 0x9D, 0xB8, 0xFC, 0xEE, 0x35, 0xC0, 0x6B, + 0x1F, 0xEE, 0xA5, 0x47, 0x4D, 0x6D, 0x8F, 0x34, + 0xB1, 0x53, 0x4A, 0x93, 0x6A, 0x18, 0xB0, 0xE0, + 0xD2, 0x0E, 0xAB, 0x86, 0xBC, 0x9C, 0x6D, 0x6A, + 0x52, 0x07, 0x19, 0x4E, 0x67, 0xFA, 0x35, 0x55, + 0x1B, 0x56, 0x80, 0x26, 0x7B, 0x00, 0x64, 0x1C, + 0x0F, 0x21, 0x2D, 0x18, 0xEC, 0xA8, 0xD7, 0x32, + 0x7E, 0xD9, 0x1F, 0xE7, 0x64, 0xA8, 0x4E, 0xA1, + 0xB4, 0x3F, 0xF5, 0xB4, 0xF6, 0xE8, 0xE6, 0x2F, + 0x05, 0xC6, 0x61, 0xDE, 0xFB, 0x25, 0x88, 0x77, + 0xC3, 0x5B, 0x18, 0xA1, 0x51, 0xD5, 0xC4, 0x14, + 0xAA, 0xAD, 0x97, 0xBA, 0x3E, 0x49, 0x93, 0x32, + 0xE5, 0x96, 0x07, 0x8E, 0x60, 0x0D, 0xEB, 0x81, + 0x14, 0x9C, 0x44, 0x1C, 0xE9, 0x57, 0x82, 0xF2, + 0x2A, 0x28, 0x25, 0x63, 0xC5, 0xBA, 0xC1, 0x41, + 0x14, 0x23, 0x60, 0x5D, 0x1A, 0xE1, 0xAF, 0xAE, + 0x2C, 0x8B, 0x06, 0x60, 0x23, 0x7E, 0xC1, 0x28, + 0xAA, 0x0F, 0xE3, 0x46, 0x4E, 0x43, 0x58, 0x11, + 0x5D, 0xB8, 0x4C, 0xC3, 0xB5, 0x23, 0x07, 0x3A, + 0x28, 0xD4, 0x54, 0x98, 0x84, 0xB8, 0x1F, 0xF7, + 0x0E, 0x10, 0xBF, 0x36, 0x1C, 0x13, 0x72, 0x96, + 0x28, 0xD5, 0x34, 0x8F, 0x07, 0x21, 0x1E, 0x7E, + 0x4C, 0xF4, 0xF1, 0x8B, 0x28, 0x60, 0x90, 0xBD, + 0xB1, 0x24, 0x0B, 0x66, 0xD6, 0xCD, 0x4A, 0xFC, + 0xEA, 0xDC, 0x00, 0xCA, 0x44, 0x6C, 0xE0, 0x50, + 0x50, 0xFF, 0x18, 0x3A, 0xD2, 0xBB, 0xF1, 0x18, + 0xC1, 0xFC, 0x0E, 0xA5, 0x1F, 0x97, 0xD2, 0x2B, + 0x8F, 0x7E, 0x46, 0x70, 0x5D, 0x45, 0x27, 0xF4, + 0x5B, 0x42, 0xAE, 0xFF, 0x39, 0x58, 0x53, 0x37, + 0x6F, 0x69, 0x7D, 0xD5, 0xFD, 0xF2, 0xC5, 0x18, + 0x7D, 0x7D, 0x5F, 0x0E, 0x2E, 0xB8, 0xD4, 0x3F, + 0x17, 0xBA, 0x0F, 0x7C, 0x60, 0xFF, 0x43, 0x7F, + 0x53, 0x5D, 0xFE, 0xF2, 0x98, 0x33, 0xBF, 0x86, + 0xCB, 0xE8, 0x8E, 0xA4, 0xFB, 0xD4, 0x22, 0x1E, + 0x84, 0x11, 0x72, 0x83, 0x54, 0xFA, 0x30, 0xA7, + 0x00, 0x8F, 0x15, 0x4A, 0x41, 0xC7, 0xFC, 0x46, + 0x6B, 0x46, 0x45, 0xDB, 0xE2, 0xE3, 0x21, 0x26, + 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; +#endif /* HAVE_FFDHE_Q */ + +const DhParams* wc_Dh_ffdhe8192_Get(void) +{ + static const DhParams ffdhe8192 = { + #ifdef HAVE_FFDHE_Q + dh_ffdhe8192_q, sizeof(dh_ffdhe8192_q), + #endif /* HAVE_FFDHE_Q */ + dh_ffdhe8192_p, sizeof(dh_ffdhe8192_p), + dh_ffdhe8192_g, sizeof(dh_ffdhe8192_g) + }; + return &ffdhe8192; +} +#endif + +int wc_InitDhKey_ex(DhKey* key, void* heap, int devId) +{ + int ret = 0; + + if (key == NULL) + return BAD_FUNC_ARG; + + key->heap = heap; /* for XMALLOC/XFREE in future */ + + if (mp_init_multi(&key->p, &key->g, &key->q, NULL, NULL, NULL) != MP_OKAY) + return MEMORY_E; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_DH) + /* handle as async */ + ret = wolfAsync_DevCtxInit(&key->asyncDev, WOLFSSL_ASYNC_MARKER_DH, + key->heap, devId); +#else + (void)devId; +#endif + + return ret; +} + +int wc_InitDhKey(DhKey* key) +{ + return wc_InitDhKey_ex(key, NULL, INVALID_DEVID); +} + + +int wc_FreeDhKey(DhKey* key) +{ + if (key) { + mp_clear(&key->p); + mp_clear(&key->g); + mp_clear(&key->q); + + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_DH) + wolfAsync_DevCtxFree(&key->asyncDev, WOLFSSL_ASYNC_MARKER_DH); + #endif + } + return 0; +} + + +#ifndef WC_NO_RNG +/* if defined to not use floating point values do not compile in */ +#ifndef WOLFSSL_DH_CONST + static word32 DiscreteLogWorkFactor(word32 n) + { + /* assuming discrete log takes about the same time as factoring */ + if (n < 5) + return 0; + else + return (word32)(2.4 * XPOW((double)n, 1.0/3.0) * + XPOW(XLOG((double)n), 2.0/3.0) - 5); + } +#endif /* WOLFSSL_DH_CONST*/ + + +/* if not using fixed points use DiscreteLogWorkFactor function for unsual size + otherwise round up on size needed */ +#ifndef WOLFSSL_DH_CONST + #define WOLFSSL_DH_ROUND(x) +#else + #define WOLFSSL_DH_ROUND(x) \ + do { \ + if (x % 128) { \ + x &= 0xffffff80;\ + x += 128; \ + } \ + } \ + while (0) +#endif + + +#ifndef WOLFSSL_NO_DH186 +/* validate that (L,N) match allowed sizes from SP 800-56A, Section 5.5.1.1. + * modLen - represents L, the size of p in bits + * divLen - represents N, the size of q in bits + * return 0 on success, -1 on error */ +static int CheckDhLN(int modLen, int divLen) +{ + int ret = -1; + + switch (modLen) { + /* FA */ + case 1024: + if (divLen == 160) + ret = 0; + break; + /* FB, FC */ + case 2048: + if (divLen == 224 || divLen == 256) + ret = 0; + break; + default: + break; + } + + return ret; +} + + +/* Create DH private key + * + * Based on NIST FIPS 186-4, + * "B.1.1 Key Pair Generation Using Extra Random Bits" + * + * dh - pointer to initialized DhKey structure, needs to have dh->q + * rng - pointer to initialized WC_RNG structure + * priv - output location for generated private key + * privSz - IN/OUT, size of priv buffer, size of generated private key + * + * return 0 on success, negative on error */ +static int GeneratePrivateDh186(DhKey* key, WC_RNG* rng, byte* priv, + word32* privSz) +{ + byte* cBuf; + int qSz, pSz, cSz, err; +#ifdef WOLFSSL_SMALL_STACK + mp_int* tmpQ = NULL; + mp_int* tmpX = NULL; +#else + mp_int tmpQ[1], tmpX[1]; +#endif + + /* Parameters validated in calling functions. */ + + if (mp_iszero(&key->q) == MP_YES) { + WOLFSSL_MSG("DH q parameter needed for FIPS 186-4 key generation"); + return BAD_FUNC_ARG; + } + + qSz = mp_unsigned_bin_size(&key->q); + pSz = mp_unsigned_bin_size(&key->p); + + /* verify (L,N) pair bit lengths */ + if (CheckDhLN(pSz * WOLFSSL_BIT_SIZE, qSz * WOLFSSL_BIT_SIZE) != 0) { + WOLFSSL_MSG("DH param sizes do not match SP 800-56A requirements"); + return BAD_FUNC_ARG; + } + + /* generate extra 64 bits so that bias from mod function is negligible */ + cSz = qSz + (64 / WOLFSSL_BIT_SIZE); + cBuf = (byte*)XMALLOC(cSz, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (cBuf == NULL) { + return MEMORY_E; + } +#ifdef WOLFSSL_SMALL_STACK + tmpQ = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH); + if (tmpQ == NULL) { + XFREE(cBuf, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } + tmpX = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH); + if (tmpX == NULL) { + XFREE(cBuf, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(tmpQ, key->heap, DYNAMIC_TYPE_DH); + return MEMORY_E; + } +#endif + + + if ((err = mp_init_multi(tmpX, tmpQ, NULL, NULL, NULL, NULL)) + != MP_OKAY) { + XFREE(cBuf, key->heap, DYNAMIC_TYPE_TMP_BUFFER); +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpQ, key->heap, DYNAMIC_TYPE_DH); + XFREE(tmpX, key->heap, DYNAMIC_TYPE_DH); +#endif + return err; + } + + do { + /* generate N+64 bits (c) from RBG into tmpX, making sure positive. + * Hash_DRBG uses SHA-256 which matches maximum + * requested_security_strength of (L,N) */ + err = wc_RNG_GenerateBlock(rng, cBuf, cSz); + if (err == MP_OKAY) + err = mp_read_unsigned_bin(tmpX, cBuf, cSz); + if (err != MP_OKAY) { + mp_clear(tmpX); + mp_clear(tmpQ); + XFREE(cBuf, key->heap, DYNAMIC_TYPE_TMP_BUFFER); +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpQ, key->heap, DYNAMIC_TYPE_DH); + XFREE(tmpX, key->heap, DYNAMIC_TYPE_DH); +#endif + return err; + } + } while (mp_cmp_d(tmpX, 1) != MP_GT); + + ForceZero(cBuf, cSz); + XFREE(cBuf, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + + /* tmpQ = q - 1 */ + if (err == MP_OKAY) + err = mp_copy(&key->q, tmpQ); + + if (err == MP_OKAY) + err = mp_sub_d(tmpQ, 1, tmpQ); + + /* x = c mod (q-1), tmpX holds c */ + if (err == MP_OKAY) + err = mp_mod(tmpX, tmpQ, tmpX); + + /* x = c mod (q-1) + 1 */ + if (err == MP_OKAY) + err = mp_add_d(tmpX, 1, tmpX); + + /* copy tmpX into priv */ + if (err == MP_OKAY) { + pSz = mp_unsigned_bin_size(tmpX); + if (pSz > (int)*privSz) { + WOLFSSL_MSG("DH private key output buffer too small"); + err = BAD_FUNC_ARG; + } else { + *privSz = pSz; + err = mp_to_unsigned_bin(tmpX, priv); + } + } + + mp_forcezero(tmpX); + mp_clear(tmpX); + mp_clear(tmpQ); +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmpQ, key->heap, DYNAMIC_TYPE_DH); + XFREE(tmpX, key->heap, DYNAMIC_TYPE_DH); +#endif + + return err; +} +#endif /* WOLFSSL_NO_DH186 */ +#endif /* !WC_NO_RNG */ + +static int GeneratePrivateDh(DhKey* key, WC_RNG* rng, byte* priv, + word32* privSz) +{ +#ifndef WC_NO_RNG + int ret = 0; + word32 sz = 0; + +#ifndef WOLFSSL_NO_DH186 + if (mp_iszero(&key->q) == MP_NO) { + + /* q param available, use NIST FIPS 186-4, "B.1.1 Key Pair + * Generation Using Extra Random Bits" */ + ret = GeneratePrivateDh186(key, rng, priv, privSz); + + } else +#endif + { + + sz = mp_unsigned_bin_size(&key->p); + + /* Table of predetermined values from the operation + 2 * DiscreteLogWorkFactor(sz * WOLFSSL_BIT_SIZE) / + WOLFSSL_BIT_SIZE + 1 + Sizes in table checked against RFC 3526 + */ + WOLFSSL_DH_ROUND(sz); /* if using fixed points only, then round up */ + switch (sz) { + case 128: sz = 21; break; + case 256: sz = 29; break; + case 384: sz = 34; break; + case 512: sz = 39; break; + case 640: sz = 42; break; + case 768: sz = 46; break; + case 896: sz = 49; break; + case 1024: sz = 52; break; + default: + #ifndef WOLFSSL_DH_CONST + /* if using floating points and size of p is not in table */ + sz = min(sz, 2 * DiscreteLogWorkFactor(sz * WOLFSSL_BIT_SIZE) / + WOLFSSL_BIT_SIZE + 1); + break; + #else + return BAD_FUNC_ARG; + #endif + } + + ret = wc_RNG_GenerateBlock(rng, priv, sz); + + if (ret == 0) { + priv[0] |= 0x0C; + *privSz = sz; + } + } + + return ret; +#else + (void)key; + (void)rng; + (void)priv; + (void)privSz; + return NOT_COMPILED_IN; +#endif /* WC_NO_RNG */ +} + + +static int GeneratePublicDh(DhKey* key, byte* priv, word32 privSz, + byte* pub, word32* pubSz) +{ + int ret = 0; +#ifndef WOLFSSL_SP_MATH +#ifdef WOLFSSL_SMALL_STACK + mp_int* x = NULL; + mp_int* y = NULL; +#else + mp_int x[1]; + mp_int y[1]; +#endif +#endif + +#ifdef WOLFSSL_HAVE_SP_DH +#ifndef WOLFSSL_SP_NO_2048 + if (mp_count_bits(&key->p) == 2048) + return sp_DhExp_2048(&key->g, priv, privSz, &key->p, pub, pubSz); +#endif +#ifndef WOLFSSL_SP_NO_3072 + if (mp_count_bits(&key->p) == 3072) + return sp_DhExp_3072(&key->g, priv, privSz, &key->p, pub, pubSz); +#endif +#endif + +#ifndef WOLFSSL_SP_MATH +#ifdef WOLFSSL_SMALL_STACK + x = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH); + if (x == NULL) + return MEMORY_E; + y = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH); + if (y == NULL) { + XFREE(x, key->heap, DYNAMIC_TYPE_DH); + return MEMORY_E; + } +#endif + if (mp_init_multi(x, y, 0, 0, 0, 0) != MP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(y, key->heap, DYNAMIC_TYPE_DH); + XFREE(x, key->heap, DYNAMIC_TYPE_DH); + #endif + return MP_INIT_E; + } + + if (mp_read_unsigned_bin(x, priv, privSz) != MP_OKAY) + ret = MP_READ_E; + + if (ret == 0 && mp_exptmod(&key->g, x, &key->p, y) != MP_OKAY) + ret = MP_EXPTMOD_E; + + if (ret == 0 && mp_to_unsigned_bin(y, pub) != MP_OKAY) + ret = MP_TO_E; + + if (ret == 0) + *pubSz = mp_unsigned_bin_size(y); + + mp_clear(y); + mp_clear(x); +#ifdef WOLFSSL_SMALL_STACK + XFREE(y, key->heap, DYNAMIC_TYPE_DH); + XFREE(x, key->heap, DYNAMIC_TYPE_DH); +#endif +#else + ret = WC_KEY_SIZE_E; +#endif + + return ret; +} + +static int wc_DhGenerateKeyPair_Sync(DhKey* key, WC_RNG* rng, + byte* priv, word32* privSz, byte* pub, word32* pubSz) +{ + int ret; + + if (key == NULL || rng == NULL || priv == NULL || privSz == NULL || + pub == NULL || pubSz == NULL) { + return BAD_FUNC_ARG; + } + + ret = GeneratePrivateDh(key, rng, priv, privSz); + + return (ret != 0) ? ret : GeneratePublicDh(key, priv, *privSz, pub, pubSz); +} + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_DH) +static int wc_DhGenerateKeyPair_Async(DhKey* key, WC_RNG* rng, + byte* priv, word32* privSz, byte* pub, word32* pubSz) +{ + int ret; + +#if defined(HAVE_INTEL_QA) + word32 pBits; + + /* QAT DH sizes: 768, 1024, 1536, 2048, 3072 and 4096 bits */ + pBits = mp_unsigned_bin_size(&key->p) * 8; + if (pBits == 768 || pBits == 1024 || pBits == 1536 || + pBits == 2048 || pBits == 3072 || pBits == 4096) { + mp_int x; + + ret = mp_init(&x); + if (ret != MP_OKAY) + return ret; + + ret = GeneratePrivateDh(key, rng, priv, privSz); + if (ret == 0) + ret = mp_read_unsigned_bin(&x, priv, *privSz); + if (ret == MP_OKAY) + ret = wc_mp_to_bigint(&x, &x.raw); + if (ret == MP_OKAY) + ret = wc_mp_to_bigint(&key->p, &key->p.raw); + if (ret == MP_OKAY) + ret = wc_mp_to_bigint(&key->g, &key->g.raw); + if (ret == MP_OKAY) + ret = IntelQaDhKeyGen(&key->asyncDev, &key->p.raw, &key->g.raw, + &x.raw, pub, pubSz); + mp_clear(&x); + + return ret; + } + +#elif defined(HAVE_CAVIUM) + /* TODO: Not implemented - use software for now */ + +#else /* WOLFSSL_ASYNC_CRYPT_TEST */ + if (wc_AsyncTestInit(&key->asyncDev, ASYNC_TEST_DH_GEN)) { + WC_ASYNC_TEST* testDev = &key->asyncDev.test; + testDev->dhGen.key = key; + testDev->dhGen.rng = rng; + testDev->dhGen.priv = priv; + testDev->dhGen.privSz = privSz; + testDev->dhGen.pub = pub; + testDev->dhGen.pubSz = pubSz; + return WC_PENDING_E; + } +#endif + + /* otherwise use software DH */ + ret = wc_DhGenerateKeyPair_Sync(key, rng, priv, privSz, pub, pubSz); + + return ret; +} +#endif /* WOLFSSL_ASYNC_CRYPT && WC_ASYNC_ENABLE_DH */ + + +/* Check DH Public Key for invalid numbers, optionally allowing + * the public key to be checked against the large prime (q). + * Check per process in SP 800-56Ar3, section 5.6.2.3.1. + * + * key DH key group parameters. + * pub Public Key. + * pubSz Public Key size. + * prime Large prime (q), optionally NULL to skip check + * primeSz Size of large prime + * + * returns 0 on success or error code + */ +int wc_DhCheckPubKey_ex(DhKey* key, const byte* pub, word32 pubSz, + const byte* prime, word32 primeSz) +{ + int ret = 0; +#ifdef WOLFSSL_SMALL_STACK + mp_int* y = NULL; + mp_int* p = NULL; + mp_int* q = NULL; +#else + mp_int y[1]; + mp_int p[1]; + mp_int q[1]; +#endif + + if (key == NULL || pub == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + y = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH); + if (y == NULL) + return MEMORY_E; + p = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH); + if (p == NULL) { + XFREE(y, key->heap, DYNAMIC_TYPE_DH); + return MEMORY_E; + } + q = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH); + if (q == NULL) { + XFREE(p, key->heap, DYNAMIC_TYPE_DH); + XFREE(y, key->heap, DYNAMIC_TYPE_DH); + return MEMORY_E; + } +#endif + + if (mp_init_multi(y, p, q, NULL, NULL, NULL) != MP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(q, key->heap, DYNAMIC_TYPE_DH); + XFREE(p, key->heap, DYNAMIC_TYPE_DH); + XFREE(y, key->heap, DYNAMIC_TYPE_DH); + #endif + return MP_INIT_E; + } + + if (mp_read_unsigned_bin(y, pub, pubSz) != MP_OKAY) { + ret = MP_READ_E; + } + + if (ret == 0 && prime != NULL) { + if (mp_read_unsigned_bin(q, prime, primeSz) != MP_OKAY) + ret = MP_READ_E; + + } else if (mp_iszero(&key->q) == MP_NO) { + /* use q available in DhKey */ + if (mp_copy(&key->q, q) != MP_OKAY) + ret = MP_INIT_E; + } + + /* SP 800-56Ar3, section 5.6.2.3.1, process step 1 */ + /* pub (y) should not be 0 or 1 */ + if (ret == 0 && mp_cmp_d(y, 2) == MP_LT) { + ret = MP_CMP_E; + } + + /* pub (y) shouldn't be greater than or equal to p - 1 */ + if (ret == 0 && mp_copy(&key->p, p) != MP_OKAY) { + ret = MP_INIT_E; + } + if (ret == 0 && mp_sub_d(p, 2, p) != MP_OKAY) { + ret = MP_SUB_E; + } + if (ret == 0 && mp_cmp(y, p) == MP_GT) { + ret = MP_CMP_E; + } + + if (ret == 0 && (prime != NULL || (mp_iszero(&key->q) == MP_NO) )) { + + /* restore key->p into p */ + if (mp_copy(&key->p, p) != MP_OKAY) + ret = MP_INIT_E; + } + + if (ret == 0 && prime != NULL) { +#ifdef WOLFSSL_HAVE_SP_DH +#ifndef WOLFSSL_SP_NO_2048 + if (mp_count_bits(&key->p) == 2048) { + ret = sp_ModExp_2048(y, q, p, y); + if (ret != 0) + ret = MP_EXPTMOD_E; + } + else +#endif +#ifndef WOLFSSL_SP_NO_3072 + if (mp_count_bits(&key->p) == 3072) { + ret = sp_ModExp_3072(y, q, p, y); + if (ret != 0) + ret = MP_EXPTMOD_E; + } + else +#endif +#endif + + { + /* SP 800-56Ar3, section 5.6.2.3.1, process step 2 */ +#ifndef WOLFSSL_SP_MATH + /* calculate (y^q) mod(p), store back into y */ + if (ret == 0 && mp_exptmod(y, q, p, y) != MP_OKAY) + ret = MP_EXPTMOD_E; +#else + ret = WC_KEY_SIZE_E; +#endif + } + + /* verify above == 1 */ + if (ret == 0 && mp_cmp_d(y, 1) != MP_EQ) + ret = MP_CMP_E; + } + + mp_clear(y); + mp_clear(p); + mp_clear(q); +#ifdef WOLFSSL_SMALL_STACK + XFREE(q, key->heap, DYNAMIC_TYPE_DH); + XFREE(p, key->heap, DYNAMIC_TYPE_DH); + XFREE(y, key->heap, DYNAMIC_TYPE_DH); +#endif + + return ret; +} + + +/* Check DH Public Key for invalid numbers + * + * key DH key group parameters. + * pub Public Key. + * pubSz Public Key size. + * + * returns 0 on success or error code + */ +int wc_DhCheckPubKey(DhKey* key, const byte* pub, word32 pubSz) +{ + return wc_DhCheckPubKey_ex(key, pub, pubSz, NULL, 0); +} + + +/** + * Quick validity check of public key value agaist prime. + * Checks are: + * - Public key not 0 or 1 + * - Public key not equal to prime or prime - 1 + * - Public key not bigger than prime. + * + * prime Big-endian encoding of prime in bytes. + * primeSz Size of prime in bytes. + * pub Big-endian encoding of public key in bytes. + * pubSz Size of public key in bytes. + */ +int wc_DhCheckPubValue(const byte* prime, word32 primeSz, const byte* pub, + word32 pubSz) +{ + int ret = 0; + word32 i; + + for (i = 0; i < pubSz && pub[i] == 0; i++) { + } + pubSz -= i; + pub += i; + + if (pubSz == 0 || (pubSz == 1 && pub[0] == 1)) + ret = MP_VAL; + else if (pubSz == primeSz) { + for (i = 0; i < pubSz-1 && pub[i] == prime[i]; i++) { + } + if (i == pubSz-1 && (pub[i] == prime[i] || pub[i] == prime[i] - 1)) + ret = MP_VAL; + else if (pub[i] > prime[i]) + ret = MP_VAL; + } + else if (pubSz > primeSz) + ret = MP_VAL; + + return ret; +} + + +/* Check DH Private Key for invalid numbers, optionally allowing + * the private key to be checked against the large prime (q). + * Check per process in SP 800-56Ar3, section 5.6.2.1.2. + * + * key DH key group parameters. + * priv Private Key. + * privSz Private Key size. + * prime Large prime (q), optionally NULL to skip check + * primeSz Size of large prime + * + * returns 0 on success or error code + */ +int wc_DhCheckPrivKey_ex(DhKey* key, const byte* priv, word32 privSz, + const byte* prime, word32 primeSz) +{ + int ret = 0; +#ifdef WOLFSSL_SMALL_STACK + mp_int* x = NULL; + mp_int* q = NULL; +#else + mp_int x[1]; + mp_int q[1]; +#endif + + if (key == NULL || priv == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + x = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH); + if (x == NULL) + return MEMORY_E; + q = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH); + if (q == NULL) { + XFREE(x, key->heap, DYNAMIC_TYPE_DH); + return MEMORY_E; + } +#endif + + if (mp_init_multi(x, q, NULL, NULL, NULL, NULL) != MP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(q, key->heap, DYNAMIC_TYPE_DH); + XFREE(x, key->heap, DYNAMIC_TYPE_DH); + #endif + return MP_INIT_E; + } + + if (mp_read_unsigned_bin(x, priv, privSz) != MP_OKAY) { + ret = MP_READ_E; + } + + if (ret == 0) { + if (prime != NULL) { + if (mp_read_unsigned_bin(q, prime, primeSz) != MP_OKAY) + ret = MP_READ_E; + } + else if (mp_iszero(&key->q) == MP_NO) { + /* use q available in DhKey */ + if (mp_copy(&key->q, q) != MP_OKAY) + ret = MP_INIT_E; + } + } + + /* priv (x) should not be 0 */ + if (ret == 0) { + if (mp_cmp_d(x, 0) == MP_EQ) + ret = MP_CMP_E; + } + + if (ret == 0) { + if (mp_iszero(q) == MP_NO) { + /* priv (x) shouldn't be greater than q - 1 */ + if (ret == 0) { + if (mp_copy(&key->q, q) != MP_OKAY) + ret = MP_INIT_E; + } + if (ret == 0) { + if (mp_sub_d(q, 1, q) != MP_OKAY) + ret = MP_SUB_E; + } + if (ret == 0) { + if (mp_cmp(x, q) == MP_GT) + ret = DH_CHECK_PRIV_E; + } + } + } + + mp_clear(x); + mp_clear(q); +#ifdef WOLFSSL_SMALL_STACK + XFREE(q, key->heap, DYNAMIC_TYPE_DH); + XFREE(x, key->heap, DYNAMIC_TYPE_DH); +#endif + + return ret; +} + + +/* Check DH Private Key for invalid numbers + * + * key DH key group parameters. + * priv Private Key. + * privSz Private Key size. + * + * returns 0 on success or error code + */ +int wc_DhCheckPrivKey(DhKey* key, const byte* priv, word32 privSz) +{ + return wc_DhCheckPrivKey_ex(key, priv, privSz, NULL, 0); +} + + +/* Check DH Keys for pair-wise consistency per process in + * SP 800-56Ar3, section 5.6.2.1.4, method (b) for FFC. + * + * key DH key group parameters. + * pub Public Key. + * pubSz Public Key size. + * priv Private Key. + * privSz Private Key size. + * + * returns 0 on success or error code + */ +int wc_DhCheckKeyPair(DhKey* key, const byte* pub, word32 pubSz, + const byte* priv, word32 privSz) +{ +#ifdef WOLFSSL_SMALL_STACK + mp_int* publicKey = NULL; + mp_int* privateKey = NULL; + mp_int* checkKey = NULL; +#else + mp_int publicKey[1]; + mp_int privateKey[1]; + mp_int checkKey[1]; +#endif + int ret = 0; + + if (key == NULL || pub == NULL || priv == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_SMALL_STACK + publicKey = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH); + if (publicKey == NULL) + return MEMORY_E; + privateKey = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH); + if (privateKey == NULL) { + XFREE(publicKey, key->heap, DYNAMIC_TYPE_DH); + return MEMORY_E; + } + checkKey = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH); + if (checkKey == NULL) { + XFREE(privateKey, key->heap, DYNAMIC_TYPE_DH); + XFREE(publicKey, key->heap, DYNAMIC_TYPE_DH); + return MEMORY_E; + } +#endif + + if (mp_init_multi(publicKey, privateKey, checkKey, + NULL, NULL, NULL) != MP_OKAY) { + + #ifdef WOLFSSL_SMALL_STACK + XFREE(privateKey, key->heap, DYNAMIC_TYPE_DH); + XFREE(publicKey, key->heap, DYNAMIC_TYPE_DH); + XFREE(checkKey, key->heap, DYNAMIC_TYPE_DH); + #endif + return MP_INIT_E; + } + + /* Load the private and public keys into big integers. */ + if (mp_read_unsigned_bin(publicKey, pub, pubSz) != MP_OKAY || + mp_read_unsigned_bin(privateKey, priv, privSz) != MP_OKAY) { + + ret = MP_READ_E; + } + + /* Calculate checkKey = g^privateKey mod p */ + if (ret == 0) { +#ifdef WOLFSSL_HAVE_SP_DH +#ifndef WOLFSSL_SP_NO_2048 + if (mp_count_bits(&key->p) == 2048) { + ret = sp_ModExp_2048(&key->g, privateKey, &key->p, checkKey); + if (ret != 0) + ret = MP_EXPTMOD_E; + } + else +#endif +#ifndef WOLFSSL_SP_NO_3072 + if (mp_count_bits(&key->p) == 3072) { + ret = sp_ModExp_3072(&key->g, privateKey, &key->p, checkKey); + if (ret != 0) + ret = MP_EXPTMOD_E; + } + else +#endif +#endif + { +#ifndef WOLFSSL_SP_MATH + if (mp_exptmod(&key->g, privateKey, &key->p, checkKey) != MP_OKAY) + ret = MP_EXPTMOD_E; +#else + ret = WC_KEY_SIZE_E; +#endif + } + } + + /* Compare the calculated public key to the supplied check value. */ + if (ret == 0) { + if (mp_cmp(checkKey, publicKey) != MP_EQ) + ret = MP_CMP_E; + } + + mp_forcezero(privateKey); + mp_clear(privateKey); + mp_clear(publicKey); + mp_clear(checkKey); +#ifdef WOLFSSL_SMALL_STACK + XFREE(checkKey, key->heap, DYNAMIC_TYPE_DH); + XFREE(privateKey, key->heap, DYNAMIC_TYPE_DH); + XFREE(publicKey, key->heap, DYNAMIC_TYPE_DH); +#endif + + return ret; +} + + +int wc_DhGenerateKeyPair(DhKey* key, WC_RNG* rng, + byte* priv, word32* privSz, byte* pub, word32* pubSz) +{ + int ret; + + if (key == NULL || rng == NULL || priv == NULL || privSz == NULL || + pub == NULL || pubSz == NULL) { + return BAD_FUNC_ARG; + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_DH) + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_DH) { + ret = wc_DhGenerateKeyPair_Async(key, rng, priv, privSz, pub, pubSz); + } + else +#endif + { + ret = wc_DhGenerateKeyPair_Sync(key, rng, priv, privSz, pub, pubSz); + } + + return ret; +} + + +static int wc_DhAgree_Sync(DhKey* key, byte* agree, word32* agreeSz, + const byte* priv, word32 privSz, const byte* otherPub, word32 pubSz) +{ + int ret = 0; +#ifdef WOLFSSL_SMALL_STACK + mp_int* y = NULL; +#ifndef WOLFSSL_SP_MATH + mp_int* x = NULL; + mp_int* z = NULL; +#endif +#else + mp_int y[1]; +#ifndef WOLFSSL_SP_MATH + mp_int x[1]; + mp_int z[1]; +#endif +#endif + +#ifdef WOLFSSL_VALIDATE_FFC_IMPORT + if (wc_DhCheckPrivKey(key, priv, privSz) != 0) { + WOLFSSL_MSG("wc_DhAgree wc_DhCheckPrivKey failed"); + return DH_CHECK_PRIV_E; + } + + if (wc_DhCheckPubKey(key, otherPub, pubSz) != 0) { + WOLFSSL_MSG("wc_DhAgree wc_DhCheckPubKey failed"); + return DH_CHECK_PUB_E; + } +#endif + +#ifdef WOLFSSL_SMALL_STACK + y = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH); + if (y == NULL) + return MEMORY_E; +#ifndef WOLFSSL_SP_MATH + x = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH); + if (x == NULL) { + XFREE(y, key->heap, DYNAMIC_TYPE_DH); + return MEMORY_E; + } + z = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_DH); + if (z == NULL) { + XFREE(x, key->heap, DYNAMIC_TYPE_DH); + XFREE(y, key->heap, DYNAMIC_TYPE_DH); + return MEMORY_E; + } +#endif +#endif + +#ifdef WOLFSSL_HAVE_SP_DH +#ifndef WOLFSSL_SP_NO_2048 + if (mp_count_bits(&key->p) == 2048) { + if (mp_init(y) != MP_OKAY) + return MP_INIT_E; + + if (ret == 0 && mp_read_unsigned_bin(y, otherPub, pubSz) != MP_OKAY) + ret = MP_READ_E; + + if (ret == 0) + ret = sp_DhExp_2048(y, priv, privSz, &key->p, agree, agreeSz); + + mp_clear(y); + #ifdef WOLFSSL_SMALL_STACK + #ifndef WOLFSSL_SP_MATH + XFREE(z, key->heap, DYNAMIC_TYPE_DH); + XFREE(x, key->heap, DYNAMIC_TYPE_DH); + #endif + XFREE(y, key->heap, DYNAMIC_TYPE_DH); + #endif + return ret; + } +#endif +#ifndef WOLFSSL_SP_NO_3072 + if (mp_count_bits(&key->p) == 3072) { + if (mp_init(y) != MP_OKAY) + return MP_INIT_E; + + if (ret == 0 && mp_read_unsigned_bin(y, otherPub, pubSz) != MP_OKAY) + ret = MP_READ_E; + + if (ret == 0) + ret = sp_DhExp_3072(y, priv, privSz, &key->p, agree, agreeSz); + + mp_clear(y); + #ifdef WOLFSSL_SMALL_STACK + #ifndef WOLFSSL_SP_MATH + XFREE(z, key->heap, DYNAMIC_TYPE_DH); + XFREE(x, key->heap, DYNAMIC_TYPE_DH); + #endif + XFREE(y, key->heap, DYNAMIC_TYPE_DH); + #endif + return ret; + } +#endif +#endif + +#ifndef WOLFSSL_SP_MATH + if (mp_init_multi(x, y, z, 0, 0, 0) != MP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(z, key->heap, DYNAMIC_TYPE_DH); + XFREE(x, key->heap, DYNAMIC_TYPE_DH); + XFREE(y, key->heap, DYNAMIC_TYPE_DH); + #endif + return MP_INIT_E; + } + + if (mp_read_unsigned_bin(x, priv, privSz) != MP_OKAY) + ret = MP_READ_E; + + if (ret == 0 && mp_read_unsigned_bin(y, otherPub, pubSz) != MP_OKAY) + ret = MP_READ_E; + + if (ret == 0 && mp_exptmod(y, x, &key->p, z) != MP_OKAY) + ret = MP_EXPTMOD_E; + + /* make sure z is not one (SP800-56A, 5.7.1.1) */ + if (ret == 0 && (mp_cmp_d(z, 1) == MP_EQ)) + ret = MP_VAL; + + if (ret == 0 && mp_to_unsigned_bin(z, agree) != MP_OKAY) + ret = MP_TO_E; + + if (ret == 0) + *agreeSz = mp_unsigned_bin_size(z); + + mp_clear(z); + mp_clear(y); + mp_forcezero(x); +#endif + +#ifdef WOLFSSL_SMALL_STACK +#ifndef WOLFSSL_SP_MATH + XFREE(z, key->heap, DYNAMIC_TYPE_DH); + XFREE(x, key->heap, DYNAMIC_TYPE_DH); +#endif + XFREE(y, key->heap, DYNAMIC_TYPE_DH); +#endif + + return ret; +} + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_DH) +static int wc_DhAgree_Async(DhKey* key, byte* agree, word32* agreeSz, + const byte* priv, word32 privSz, const byte* otherPub, word32 pubSz) +{ + int ret; + +#if defined(HAVE_INTEL_QA) + word32 pBits; + + /* QAT DH sizes: 768, 1024, 1536, 2048, 3072 and 4096 bits */ + pBits = mp_unsigned_bin_size(&key->p) * 8; + if (pBits == 768 || pBits == 1024 || pBits == 1536 || + pBits == 2048 || pBits == 3072 || pBits == 4096) { + ret = wc_mp_to_bigint(&key->p, &key->p.raw); + if (ret == MP_OKAY) + ret = IntelQaDhAgree(&key->asyncDev, &key->p.raw, + agree, agreeSz, priv, privSz, otherPub, pubSz); + return ret; + } + +#elif defined(HAVE_CAVIUM) + /* TODO: Not implemented - use software for now */ + +#else /* WOLFSSL_ASYNC_CRYPT_TEST */ + if (wc_AsyncTestInit(&key->asyncDev, ASYNC_TEST_DH_AGREE)) { + WC_ASYNC_TEST* testDev = &key->asyncDev.test; + testDev->dhAgree.key = key; + testDev->dhAgree.agree = agree; + testDev->dhAgree.agreeSz = agreeSz; + testDev->dhAgree.priv = priv; + testDev->dhAgree.privSz = privSz; + testDev->dhAgree.otherPub = otherPub; + testDev->dhAgree.pubSz = pubSz; + return WC_PENDING_E; + } +#endif + + /* otherwise use software DH */ + ret = wc_DhAgree_Sync(key, agree, agreeSz, priv, privSz, otherPub, pubSz); + + return ret; +} +#endif /* WOLFSSL_ASYNC_CRYPT */ + +int wc_DhAgree(DhKey* key, byte* agree, word32* agreeSz, const byte* priv, + word32 privSz, const byte* otherPub, word32 pubSz) +{ + int ret = 0; + + if (key == NULL || agree == NULL || agreeSz == NULL || priv == NULL || + otherPub == NULL) { + return BAD_FUNC_ARG; + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_DH) + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_DH) { + ret = wc_DhAgree_Async(key, agree, agreeSz, priv, privSz, otherPub, pubSz); + } + else +#endif + { + ret = wc_DhAgree_Sync(key, agree, agreeSz, priv, privSz, otherPub, pubSz); + } + + return ret; +} + + +static int _DhSetKey(DhKey* key, const byte* p, word32 pSz, const byte* g, + word32 gSz, const byte* q, word32 qSz, int trusted, + WC_RNG* rng) +{ + int ret = 0; + mp_int* keyP = NULL; + mp_int* keyG = NULL; + mp_int* keyQ = NULL; + + if (key == NULL || p == NULL || g == NULL || pSz == 0 || gSz == 0) { + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + /* may have leading 0 */ + if (p[0] == 0) { + pSz--; p++; + } + + if (g[0] == 0) { + gSz--; g++; + } + + if (q != NULL) { + if (q[0] == 0) { + qSz--; q++; + } + } + + if (mp_init(&key->p) != MP_OKAY) + ret = MP_INIT_E; + } + + if (ret == 0) { + if (mp_read_unsigned_bin(&key->p, p, pSz) != MP_OKAY) + ret = ASN_DH_KEY_E; + else + keyP = &key->p; + } + +#ifndef WOLFSSL_SP_MATH + if (ret == 0 && !trusted) { + int isPrime = 0; + if (rng != NULL) + ret = mp_prime_is_prime_ex(keyP, 8, &isPrime, rng); + else + ret = mp_prime_is_prime(keyP, 8, &isPrime); + + if (ret == 0 && isPrime == 0) + ret = DH_CHECK_PUB_E; + } +#else + (void)trusted; + (void)rng; +#endif + + if (ret == 0 && mp_init(&key->g) != MP_OKAY) + ret = MP_INIT_E; + if (ret == 0) { + if (mp_read_unsigned_bin(&key->g, g, gSz) != MP_OKAY) + ret = ASN_DH_KEY_E; + else + keyG = &key->g; + } + + if (ret == 0 && q != NULL) { + if (mp_init(&key->q) != MP_OKAY) + ret = MP_INIT_E; + } + if (ret == 0 && q != NULL) { + if (mp_read_unsigned_bin(&key->q, q, qSz) != MP_OKAY) + ret = MP_INIT_E; + else + keyQ = &key->q; + } + + if (ret != 0 && key != NULL) { + if (keyQ) + mp_clear(keyQ); + if (keyG) + mp_clear(keyG); + if (keyP) + mp_clear(keyP); + } + + return ret; +} + + +int wc_DhSetCheckKey(DhKey* key, const byte* p, word32 pSz, const byte* g, + word32 gSz, const byte* q, word32 qSz, int trusted, + WC_RNG* rng) +{ + return _DhSetKey(key, p, pSz, g, gSz, q, qSz, trusted, rng); +} + + +int wc_DhSetKey_ex(DhKey* key, const byte* p, word32 pSz, const byte* g, + word32 gSz, const byte* q, word32 qSz) +{ + return _DhSetKey(key, p, pSz, g, gSz, q, qSz, 1, NULL); +} + + +/* not in asn anymore since no actual asn types used */ +int wc_DhSetKey(DhKey* key, const byte* p, word32 pSz, const byte* g, + word32 gSz) +{ + return _DhSetKey(key, p, pSz, g, gSz, NULL, 0, 1, NULL); +} + + +#ifdef WOLFSSL_KEY_GEN + +/* modulus_size in bits */ +int wc_DhGenerateParams(WC_RNG *rng, int modSz, DhKey *dh) +{ + mp_int tmp, tmp2; + int groupSz = 0, bufSz = 0, + primeCheckCount = 0, + primeCheck = MP_NO, + ret = 0; + unsigned char *buf = NULL; + + if (rng == NULL || dh == NULL) + ret = BAD_FUNC_ARG; + + /* set group size in bytes from modulus size + * FIPS 186-4 defines valid values (1024, 160) (2048, 256) (3072, 256) + */ + if (ret == 0) { + switch (modSz) { + case 1024: + groupSz = 20; + break; + case 2048: + case 3072: + groupSz = 32; + break; + default: + ret = BAD_FUNC_ARG; + break; + } + } + + if (ret == 0) { + /* modulus size in bytes */ + modSz /= WOLFSSL_BIT_SIZE; + bufSz = modSz - groupSz; + + /* allocate ram */ + buf = (unsigned char *)XMALLOC(bufSz, + dh->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (buf == NULL) + ret = MEMORY_E; + } + + /* make a random string that will be multplied against q */ + if (ret == 0) + ret = wc_RNG_GenerateBlock(rng, buf, bufSz); + + if (ret == 0) { + /* force magnitude */ + buf[0] |= 0xC0; + /* force even */ + buf[bufSz - 1] &= ~1; + + if (mp_init_multi(&tmp, &tmp2, &dh->p, &dh->q, &dh->g, 0) + != MP_OKAY) { + ret = MP_INIT_E; + } + } + + if (ret == 0) { + if (mp_read_unsigned_bin(&tmp2, buf, bufSz) != MP_OKAY) + ret = MP_READ_E; + } + + /* make our prime q */ + if (ret == 0) { + if (mp_rand_prime(&dh->q, groupSz, rng, NULL) != MP_OKAY) + ret = PRIME_GEN_E; + } + + /* p = random * q */ + if (ret == 0) { + if (mp_mul(&dh->q, &tmp2, &dh->p) != MP_OKAY) + ret = MP_MUL_E; + } + + /* p = random * q + 1, so q is a prime divisor of p-1 */ + if (ret == 0) { + if (mp_add_d(&dh->p, 1, &dh->p) != MP_OKAY) + ret = MP_ADD_E; + } + + /* tmp = 2q */ + if (ret == 0) { + if (mp_add(&dh->q, &dh->q, &tmp) != MP_OKAY) + ret = MP_ADD_E; + } + + /* loop until p is prime */ + if (ret == 0) { + do { + if (mp_prime_is_prime_ex(&dh->p, 8, &primeCheck, rng) != MP_OKAY) + ret = PRIME_GEN_E; + + if (primeCheck != MP_YES) { + /* p += 2q */ + if (mp_add(&tmp, &dh->p, &dh->p) != MP_OKAY) + ret = MP_ADD_E; + else + primeCheckCount++; + } + } while (ret == 0 && primeCheck == MP_NO); + } + + /* tmp2 += (2*loop_check_prime) + * to have p = (q * tmp2) + 1 prime + */ + if ((ret == 0) && (primeCheckCount)) { + if (mp_add_d(&tmp2, 2 * primeCheckCount, &tmp2) != MP_OKAY) + ret = MP_ADD_E; + } + + /* find a value g for which g^tmp2 != 1 */ + if ((ret == 0) && (mp_set(&dh->g, 1) != MP_OKAY)) + ret = MP_ZERO_E; + + if (ret == 0) { + do { + if (mp_add_d(&dh->g, 1, &dh->g) != MP_OKAY) + ret = MP_ADD_E; + else if (mp_exptmod(&dh->g, &tmp2, &dh->p, &tmp) != MP_OKAY) + ret = MP_EXPTMOD_E; + } while (ret == 0 && mp_cmp_d(&tmp, 1) == MP_EQ); + } + + if (ret == 0) { + /* at this point tmp generates a group of order q mod p */ + mp_exch(&tmp, &dh->g); + } + + /* clear the parameters if there was an error */ + if ((ret != 0) && (dh != NULL)) { + mp_clear(&dh->q); + mp_clear(&dh->p); + mp_clear(&dh->g); + } + + if (buf != NULL) { + ForceZero(buf, bufSz); + if (dh != NULL) { + XFREE(buf, dh->heap, DYNAMIC_TYPE_TMP_BUFFER); + } + } + mp_clear(&tmp); + mp_clear(&tmp2); + + return ret; +} + + +/* Export raw DH parameters from DhKey structure + * + * dh - pointer to initialized DhKey structure + * p - output location for DH (p) parameter + * pSz - [IN/OUT] size of output buffer for p, size of p + * q - output location for DH (q) parameter + * qSz - [IN/OUT] size of output buffer for q, size of q + * g - output location for DH (g) parameter + * gSz - [IN/OUT] size of output buffer for g, size of g + * + * If p, q, and g pointers are all passed in as NULL, the function + * will set pSz, qSz, and gSz to the required output buffer sizes for p, + * q, and g. In this case, the function will return LENGTH_ONLY_E. + * + * returns 0 on success, negative upon failure + */ +int wc_DhExportParamsRaw(DhKey* dh, byte* p, word32* pSz, + byte* q, word32* qSz, byte* g, word32* gSz) +{ + int ret = 0; + word32 pLen = 0, qLen = 0, gLen = 0; + + if (dh == NULL || pSz == NULL || qSz == NULL || gSz == NULL) + ret = BAD_FUNC_ARG; + + /* get required output buffer sizes */ + if (ret == 0) { + pLen = mp_unsigned_bin_size(&dh->p); + qLen = mp_unsigned_bin_size(&dh->q); + gLen = mp_unsigned_bin_size(&dh->g); + + /* return buffer sizes and LENGTH_ONLY_E if buffers are NULL */ + if (p == NULL && q == NULL && g == NULL) { + *pSz = pLen; + *qSz = qLen; + *gSz = gLen; + ret = LENGTH_ONLY_E; + } + } + + if (ret == 0) { + if (p == NULL || q == NULL || g == NULL) + ret = BAD_FUNC_ARG; + } + + /* export p */ + if (ret == 0) { + if (*pSz < pLen) { + WOLFSSL_MSG("Output buffer for DH p parameter too small, " + "required size placed into pSz"); + *pSz = pLen; + ret = BUFFER_E; + } + } + + if (ret == 0) { + *pSz = pLen; + if (mp_to_unsigned_bin(&dh->p, p) != MP_OKAY) + ret = MP_TO_E; + } + + /* export q */ + if (ret == 0) { + if (*qSz < qLen) { + WOLFSSL_MSG("Output buffer for DH q parameter too small, " + "required size placed into qSz"); + *qSz = qLen; + ret = BUFFER_E; + } + } + + if (ret == 0) { + *qSz = qLen; + if (mp_to_unsigned_bin(&dh->q, q) != MP_OKAY) + ret = MP_TO_E; + } + + /* export g */ + if (ret == 0) { + if (*gSz < gLen) { + WOLFSSL_MSG("Output buffer for DH g parameter too small, " + "required size placed into gSz"); + *gSz = gLen; + ret = BUFFER_E; + } + } + + if (ret == 0) { + *gSz = gLen; + if (mp_to_unsigned_bin(&dh->g, g) != MP_OKAY) + ret = MP_TO_E; + } + + return ret; +} + +#endif /* WOLFSSL_KEY_GEN */ + +#endif /* NO_DH */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/dsa.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/dsa.c new file mode 100755 index 0000000..6974704 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/dsa.c @@ -0,0 +1,831 @@ +/* dsa.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifndef NO_DSA + +#include +#include +#include +#include +#include +#include + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + + +enum { + DSA_HALF_SIZE = 20, /* r and s size */ + DSA_SIG_SIZE = 40 /* signature size */ +}; + + + +int wc_InitDsaKey(DsaKey* key) +{ + if (key == NULL) + return BAD_FUNC_ARG; + + key->type = -1; /* haven't decided yet */ + key->heap = NULL; + + return mp_init_multi( + /* public alloc parts */ + &key->p, + &key->q, + &key->g, + &key->y, + + /* private alloc parts */ + &key->x, + NULL + ); +} + + +int wc_InitDsaKey_h(DsaKey* key, void* h) +{ + int ret = wc_InitDsaKey(key); + if (ret == 0) + key->heap = h; + + return ret; +} + + +void wc_FreeDsaKey(DsaKey* key) +{ + if (key == NULL) + return; + + if (key->type == DSA_PRIVATE) + mp_forcezero(&key->x); + + mp_clear(&key->x); + mp_clear(&key->y); + mp_clear(&key->g); + mp_clear(&key->q); + mp_clear(&key->p); +} + + +/* validate that (L,N) match allowed sizes from FIPS 186-4, Section 4.2. + * modLen - represents L, the size of p (prime modulus) in bits + * divLen - represents N, the size of q (prime divisor) in bits + * return 0 on success, -1 on error */ +static int CheckDsaLN(int modLen, int divLen) +{ + int ret = -1; + + switch (modLen) { + case 1024: + if (divLen == 160) + ret = 0; + break; + case 2048: + if (divLen == 224 || divLen == 256) + ret = 0; + break; + case 3072: + if (divLen == 256) + ret = 0; + break; + default: + break; + } + + return ret; +} + + +#ifdef WOLFSSL_KEY_GEN + +/* Create DSA key pair (&dsa->x, &dsa->y) + * + * Based on NIST FIPS 186-4, + * "B.1.1 Key Pair Generation Using Extra Random Bits" + * + * rng - pointer to initialized WC_RNG structure + * dsa - pointer to initialized DsaKey structure, will hold generated key + * + * return 0 on success, negative on error */ +int wc_MakeDsaKey(WC_RNG *rng, DsaKey *dsa) +{ + byte* cBuf; + int qSz, pSz, cSz, err; + mp_int tmpQ; + + if (rng == NULL || dsa == NULL) + return BAD_FUNC_ARG; + + qSz = mp_unsigned_bin_size(&dsa->q); + pSz = mp_unsigned_bin_size(&dsa->p); + + /* verify (L,N) pair bit lengths */ + if (CheckDsaLN(pSz * WOLFSSL_BIT_SIZE, qSz * WOLFSSL_BIT_SIZE) != 0) + return BAD_FUNC_ARG; + + /* generate extra 64 bits so that bias from mod function is negligible */ + cSz = qSz + (64 / WOLFSSL_BIT_SIZE); + cBuf = (byte*)XMALLOC(cSz, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (cBuf == NULL) { + return MEMORY_E; + } + + if ((err = mp_init_multi(&dsa->x, &dsa->y, &tmpQ, NULL, NULL, NULL)) + != MP_OKAY) { + XFREE(cBuf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER); + return err; + } + + do { + /* generate N+64 bits (c) from RBG into &dsa->x, making sure positive. + * Hash_DRBG uses SHA-256 which matches maximum + * requested_security_strength of (L,N) */ + err = wc_RNG_GenerateBlock(rng, cBuf, cSz); + if (err != MP_OKAY) { + mp_clear(&dsa->x); + mp_clear(&dsa->y); + mp_clear(&tmpQ); + XFREE(cBuf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER); + return err; + } + + err = mp_read_unsigned_bin(&dsa->x, cBuf, cSz); + if (err != MP_OKAY) { + mp_clear(&dsa->x); + mp_clear(&dsa->y); + mp_clear(&tmpQ); + XFREE(cBuf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER); + return err; + } + } while (mp_cmp_d(&dsa->x, 1) != MP_GT); + + XFREE(cBuf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER); + + /* tmpQ = q - 1 */ + if (err == MP_OKAY) + err = mp_copy(&dsa->q, &tmpQ); + + if (err == MP_OKAY) + err = mp_sub_d(&tmpQ, 1, &tmpQ); + + /* x = c mod (q-1), &dsa->x holds c */ + if (err == MP_OKAY) + err = mp_mod(&dsa->x, &tmpQ, &dsa->x); + + /* x = c mod (q-1) + 1 */ + if (err == MP_OKAY) + err = mp_add_d(&dsa->x, 1, &dsa->x); + + /* public key : y = g^x mod p */ + if (err == MP_OKAY) + err = mp_exptmod(&dsa->g, &dsa->x, &dsa->p, &dsa->y); + + if (err == MP_OKAY) + dsa->type = DSA_PRIVATE; + + if (err != MP_OKAY) { + mp_clear(&dsa->x); + mp_clear(&dsa->y); + } + mp_clear(&tmpQ); + + return err; +} + + +/* modulus_size in bits */ +int wc_MakeDsaParameters(WC_RNG *rng, int modulus_size, DsaKey *dsa) +{ + mp_int tmp, tmp2; + int err, msize, qsize, + loop_check_prime = 0, + check_prime = MP_NO; + unsigned char *buf; + + if (rng == NULL || dsa == NULL) + return BAD_FUNC_ARG; + + /* set group size in bytes from modulus size + * FIPS 186-4 defines valid values (1024, 160) (2048, 256) (3072, 256) + */ + switch (modulus_size) { + case 1024: + qsize = 20; + break; + case 2048: + case 3072: + qsize = 32; + break; + default: + return BAD_FUNC_ARG; + } + + /* modulus size in bytes */ + msize = modulus_size / WOLFSSL_BIT_SIZE; + + /* allocate ram */ + buf = (unsigned char *)XMALLOC(msize - qsize, + dsa->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (buf == NULL) { + return MEMORY_E; + } + + /* make a random string that will be multplied against q */ + err = wc_RNG_GenerateBlock(rng, buf, msize - qsize); + if (err != MP_OKAY) { + XFREE(buf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER); + return err; + } + + /* force magnitude */ + buf[0] |= 0xC0; + + /* force even */ + buf[msize - qsize - 1] &= ~1; + + if (mp_init_multi(&tmp2, &dsa->p, &dsa->q, 0, 0, 0) != MP_OKAY) { + mp_clear(&dsa->q); + XFREE(buf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER); + return MP_INIT_E; + } + + err = mp_read_unsigned_bin(&tmp2, buf, msize - qsize); + if (err != MP_OKAY) { + mp_clear(&dsa->q); + mp_clear(&dsa->p); + mp_clear(&tmp2); + XFREE(buf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER); + return err; + } + XFREE(buf, dsa->heap, DYNAMIC_TYPE_TMP_BUFFER); + + /* make our prime q */ + err = mp_rand_prime(&dsa->q, qsize, rng, NULL); + if (err != MP_OKAY) { + mp_clear(&dsa->q); + mp_clear(&dsa->p); + mp_clear(&tmp2); + return err; + } + + /* p = random * q */ + err = mp_mul(&dsa->q, &tmp2, &dsa->p); + if (err != MP_OKAY) { + mp_clear(&dsa->q); + mp_clear(&dsa->p); + mp_clear(&tmp2); + return err; + } + + /* p = random * q + 1, so q is a prime divisor of p-1 */ + err = mp_add_d(&dsa->p, 1, &dsa->p); + if (err != MP_OKAY) { + mp_clear(&dsa->q); + mp_clear(&dsa->p); + mp_clear(&tmp2); + return err; + } + + if (mp_init(&tmp) != MP_OKAY) { + mp_clear(&dsa->q); + mp_clear(&dsa->p); + mp_clear(&tmp2); + return MP_INIT_E; + } + + /* tmp = 2q */ + err = mp_add(&dsa->q, &dsa->q, &tmp); + if (err != MP_OKAY) { + mp_clear(&dsa->q); + mp_clear(&dsa->p); + mp_clear(&tmp); + mp_clear(&tmp2); + return err; + } + + /* loop until p is prime */ + while (check_prime == MP_NO) { + err = mp_prime_is_prime_ex(&dsa->p, 8, &check_prime, rng); + if (err != MP_OKAY) { + mp_clear(&dsa->q); + mp_clear(&dsa->p); + mp_clear(&tmp); + mp_clear(&tmp2); + return err; + } + + if (check_prime != MP_YES) { + /* p += 2q */ + err = mp_add(&tmp, &dsa->p, &dsa->p); + if (err != MP_OKAY) { + mp_clear(&dsa->q); + mp_clear(&dsa->p); + mp_clear(&tmp); + mp_clear(&tmp2); + return err; + } + + loop_check_prime++; + } + } + + /* tmp2 += (2*loop_check_prime) + * to have p = (q * tmp2) + 1 prime + */ + if (loop_check_prime) { + err = mp_add_d(&tmp2, 2*loop_check_prime, &tmp2); + if (err != MP_OKAY) { + mp_clear(&dsa->q); + mp_clear(&dsa->p); + mp_clear(&tmp); + mp_clear(&tmp2); + return err; + } + } + + if (mp_init(&dsa->g) != MP_OKAY) { + mp_clear(&dsa->q); + mp_clear(&dsa->p); + mp_clear(&tmp); + mp_clear(&tmp2); + return MP_INIT_E; + } + + /* find a value g for which g^tmp2 != 1 */ + if (mp_set(&dsa->g, 1) != MP_OKAY) { + mp_clear(&dsa->q); + mp_clear(&dsa->p); + mp_clear(&tmp); + mp_clear(&tmp2); + return MP_INIT_E; + } + + do { + err = mp_add_d(&dsa->g, 1, &dsa->g); + if (err != MP_OKAY) { + mp_clear(&dsa->q); + mp_clear(&dsa->p); + mp_clear(&dsa->g); + mp_clear(&tmp); + mp_clear(&tmp2); + return err; + } + + err = mp_exptmod(&dsa->g, &tmp2, &dsa->p, &tmp); + if (err != MP_OKAY) { + mp_clear(&dsa->q); + mp_clear(&dsa->p); + mp_clear(&dsa->g); + mp_clear(&tmp); + mp_clear(&tmp2); + return err; + } + + } while (mp_cmp_d(&tmp, 1) == MP_EQ); + + /* at this point tmp generates a group of order q mod p */ + mp_exch(&tmp, &dsa->g); + + mp_clear(&tmp); + mp_clear(&tmp2); + + return MP_OKAY; +} +#endif /* WOLFSSL_KEY_GEN */ + + +static int _DsaImportParamsRaw(DsaKey* dsa, const char* p, const char* q, + const char* g, int trusted, WC_RNG* rng) +{ + int err; + word32 pSz, qSz; + + if (dsa == NULL || p == NULL || q == NULL || g == NULL) + return BAD_FUNC_ARG; + + /* read p */ + err = mp_read_radix(&dsa->p, p, MP_RADIX_HEX); + if (err == MP_OKAY && !trusted) { + int isPrime = 1; + if (rng == NULL) + err = mp_prime_is_prime(&dsa->p, 8, &isPrime); + else + err = mp_prime_is_prime_ex(&dsa->p, 8, &isPrime, rng); + + if (err == MP_OKAY) { + if (!isPrime) + err = DH_CHECK_PUB_E; + } + } + + /* read q */ + if (err == MP_OKAY) + err = mp_read_radix(&dsa->q, q, MP_RADIX_HEX); + + /* read g */ + if (err == MP_OKAY) + err = mp_read_radix(&dsa->g, g, MP_RADIX_HEX); + + /* verify (L,N) pair bit lengths */ + pSz = mp_unsigned_bin_size(&dsa->p); + qSz = mp_unsigned_bin_size(&dsa->q); + + if (CheckDsaLN(pSz * WOLFSSL_BIT_SIZE, qSz * WOLFSSL_BIT_SIZE) != 0) { + WOLFSSL_MSG("Invalid DSA p or q parameter size"); + err = BAD_FUNC_ARG; + } + + if (err != MP_OKAY) { + mp_clear(&dsa->p); + mp_clear(&dsa->q); + mp_clear(&dsa->g); + } + + return err; +} + + +/* Import raw DSA parameters into DsaKey structure for use with wc_MakeDsaKey(), + * input parameters (p,q,g) should be represented as ASCII hex values. + * + * dsa - pointer to initialized DsaKey structure + * p - DSA (p) parameter, ASCII hex string + * pSz - length of p + * q - DSA (q) parameter, ASCII hex string + * qSz - length of q + * g - DSA (g) parameter, ASCII hex string + * gSz - length of g + * + * returns 0 on success, negative upon failure + */ +int wc_DsaImportParamsRaw(DsaKey* dsa, const char* p, const char* q, + const char* g) +{ + return _DsaImportParamsRaw(dsa, p, q, g, 1, NULL); +} + + +/* Import raw DSA parameters into DsaKey structure for use with wc_MakeDsaKey(), + * input parameters (p,q,g) should be represented as ASCII hex values. Check + * that the p value is probably prime. + * + * dsa - pointer to initialized DsaKey structure + * p - DSA (p) parameter, ASCII hex string + * pSz - length of p + * q - DSA (q) parameter, ASCII hex string + * qSz - length of q + * g - DSA (g) parameter, ASCII hex string + * gSz - length of g + * trusted - trust that p is OK + * rng - random number generator for the prime test + * + * returns 0 on success, negative upon failure + */ +int wc_DsaImportParamsRawCheck(DsaKey* dsa, const char* p, const char* q, + const char* g, int trusted, WC_RNG* rng) +{ + return _DsaImportParamsRaw(dsa, p, q, g, trusted, rng); +} + + +/* Export raw DSA parameters from DsaKey structure + * + * dsa - pointer to initialized DsaKey structure + * p - output location for DSA (p) parameter + * pSz - [IN/OUT] size of output buffer for p, size of p + * q - output location for DSA (q) parameter + * qSz - [IN/OUT] size of output buffer for q, size of q + * g - output location for DSA (g) parameter + * gSz - [IN/OUT] size of output buffer for g, size of g + * + * If p, q, and g pointers are all passed in as NULL, the function + * will set pSz, qSz, and gSz to the required output buffer sizes for p, + * q, and g. In this case, the function will return LENGTH_ONLY_E. + * + * returns 0 on success, negative upon failure + */ +int wc_DsaExportParamsRaw(DsaKey* dsa, byte* p, word32* pSz, + byte* q, word32* qSz, byte* g, word32* gSz) +{ + int err; + word32 pLen, qLen, gLen; + + if (dsa == NULL || pSz == NULL || qSz == NULL || gSz == NULL) + return BAD_FUNC_ARG; + + /* get required output buffer sizes */ + pLen = mp_unsigned_bin_size(&dsa->p); + qLen = mp_unsigned_bin_size(&dsa->q); + gLen = mp_unsigned_bin_size(&dsa->g); + + /* return buffer sizes and LENGTH_ONLY_E if buffers are NULL */ + if (p == NULL && q == NULL && g == NULL) { + *pSz = pLen; + *qSz = qLen; + *gSz = gLen; + return LENGTH_ONLY_E; + } + + if (p == NULL || q == NULL || g == NULL) + return BAD_FUNC_ARG; + + /* export p */ + if (*pSz < pLen) { + WOLFSSL_MSG("Output buffer for DSA p parameter too small, " + "required size placed into pSz"); + *pSz = pLen; + return BUFFER_E; + } + *pSz = pLen; + err = mp_to_unsigned_bin(&dsa->p, p); + + /* export q */ + if (err == MP_OKAY) { + if (*qSz < qLen) { + WOLFSSL_MSG("Output buffer for DSA q parameter too small, " + "required size placed into qSz"); + *qSz = qLen; + return BUFFER_E; + } + *qSz = qLen; + err = mp_to_unsigned_bin(&dsa->q, q); + } + + /* export g */ + if (err == MP_OKAY) { + if (*gSz < gLen) { + WOLFSSL_MSG("Output buffer for DSA g parameter too small, " + "required size placed into gSz"); + *gSz = gLen; + return BUFFER_E; + } + *gSz = gLen; + err = mp_to_unsigned_bin(&dsa->g, g); + } + + return err; +} + + +/* Export raw DSA key (x, y) from DsaKey structure + * + * dsa - pointer to initialized DsaKey structure + * x - output location for private key + * xSz - [IN/OUT] size of output buffer for x, size of x + * y - output location for public key + * ySz - [IN/OUT] size of output buffer for y, size of y + * + * If x and y pointers are all passed in as NULL, the function + * will set xSz and ySz to the required output buffer sizes for x + * and y. In this case, the function will return LENGTH_ONLY_E. + * + * returns 0 on success, negative upon failure + */ +int wc_DsaExportKeyRaw(DsaKey* dsa, byte* x, word32* xSz, byte* y, word32* ySz) +{ + int err; + word32 xLen, yLen; + + if (dsa == NULL || xSz == NULL || ySz == NULL) + return BAD_FUNC_ARG; + + /* get required output buffer sizes */ + xLen = mp_unsigned_bin_size(&dsa->x); + yLen = mp_unsigned_bin_size(&dsa->y); + + /* return buffer sizes and LENGTH_ONLY_E if buffers are NULL */ + if (x == NULL && y == NULL) { + *xSz = xLen; + *ySz = yLen; + return LENGTH_ONLY_E; + } + + if (x == NULL || y == NULL) + return BAD_FUNC_ARG; + + /* export x */ + if (*xSz < xLen) { + WOLFSSL_MSG("Output buffer for DSA private key (x) too small, " + "required size placed into xSz"); + *xSz = xLen; + return BUFFER_E; + } + *xSz = xLen; + err = mp_to_unsigned_bin(&dsa->x, x); + + /* export y */ + if (err == MP_OKAY) { + if (*ySz < yLen) { + WOLFSSL_MSG("Output buffer to DSA public key (y) too small, " + "required size placed into ySz"); + *ySz = yLen; + return BUFFER_E; + } + *ySz = yLen; + err = mp_to_unsigned_bin(&dsa->y, y); + } + + return err; +} + + +int wc_DsaSign(const byte* digest, byte* out, DsaKey* key, WC_RNG* rng) +{ + mp_int k, kInv, r, s, H; + int ret, sz; + byte buffer[DSA_HALF_SIZE]; + byte* tmp; /* initial output pointer */ + + if (digest == NULL || out == NULL || key == NULL || rng == NULL) { + return BAD_FUNC_ARG; + } + + tmp = out; + + sz = min((int)sizeof(buffer), mp_unsigned_bin_size(&key->q)); + + if (mp_init_multi(&k, &kInv, &r, &s, &H, 0) != MP_OKAY) + return MP_INIT_E; + + do { + /* generate k */ + ret = wc_RNG_GenerateBlock(rng, buffer, sz); + if (ret != 0) + return ret; + + buffer[0] |= 0x0C; + + if (mp_read_unsigned_bin(&k, buffer, sz) != MP_OKAY) + ret = MP_READ_E; + + /* k is a random numnber and it should be less than q + * if k greater than repeat + */ + } while (mp_cmp(&k, &key->q) != MP_LT); + + if (ret == 0 && mp_cmp_d(&k, 1) != MP_GT) + ret = MP_CMP_E; + + /* inverse k mod q */ + if (ret == 0 && mp_invmod(&k, &key->q, &kInv) != MP_OKAY) + ret = MP_INVMOD_E; + + /* generate r, r = (g exp k mod p) mod q */ + if (ret == 0 && mp_exptmod(&key->g, &k, &key->p, &r) != MP_OKAY) + ret = MP_EXPTMOD_E; + + if (ret == 0 && mp_mod(&r, &key->q, &r) != MP_OKAY) + ret = MP_MOD_E; + + /* generate H from sha digest */ + if (ret == 0 && mp_read_unsigned_bin(&H, digest,WC_SHA_DIGEST_SIZE) != MP_OKAY) + ret = MP_READ_E; + + /* generate s, s = (kInv * (H + x*r)) % q */ + if (ret == 0 && mp_mul(&key->x, &r, &s) != MP_OKAY) + ret = MP_MUL_E; + + if (ret == 0 && mp_add(&s, &H, &s) != MP_OKAY) + ret = MP_ADD_E; + + if (ret == 0 && mp_mulmod(&s, &kInv, &key->q, &s) != MP_OKAY) + ret = MP_MULMOD_E; + + /* detect zero r or s */ + if (ret == 0 && (mp_iszero(&r) == MP_YES || mp_iszero(&s) == MP_YES)) + ret = MP_ZERO_E; + + /* write out */ + if (ret == 0) { + int rSz = mp_unsigned_bin_size(&r); + int sSz = mp_unsigned_bin_size(&s); + + while (rSz++ < DSA_HALF_SIZE) { + *out++ = 0x00; /* pad front with zeros */ + } + + if (mp_to_unsigned_bin(&r, out) != MP_OKAY) + ret = MP_TO_E; + else { + out = tmp + DSA_HALF_SIZE; /* advance to s in output */ + while (sSz++ < DSA_HALF_SIZE) { + *out++ = 0x00; /* pad front with zeros */ + } + ret = mp_to_unsigned_bin(&s, out); + } + } + + mp_clear(&H); + mp_clear(&s); + mp_clear(&r); + mp_clear(&kInv); + mp_clear(&k); + + return ret; +} + + +int wc_DsaVerify(const byte* digest, const byte* sig, DsaKey* key, int* answer) +{ + mp_int w, u1, u2, v, r, s; + int ret = 0; + + if (digest == NULL || sig == NULL || key == NULL || answer == NULL) { + return BAD_FUNC_ARG; + } + + if (mp_init_multi(&w, &u1, &u2, &v, &r, &s) != MP_OKAY) + return MP_INIT_E; + + /* set r and s from signature */ + if (mp_read_unsigned_bin(&r, sig, DSA_HALF_SIZE) != MP_OKAY || + mp_read_unsigned_bin(&s, sig + DSA_HALF_SIZE, DSA_HALF_SIZE) != MP_OKAY) + ret = MP_READ_E; + + /* sanity checks */ + if (ret == 0) { + if (mp_iszero(&r) == MP_YES || mp_iszero(&s) == MP_YES || + mp_cmp(&r, &key->q) != MP_LT || mp_cmp(&s, &key->q) != MP_LT) { + ret = MP_ZERO_E; + } + } + + /* put H into u1 from sha digest */ + if (ret == 0 && mp_read_unsigned_bin(&u1,digest,WC_SHA_DIGEST_SIZE) != MP_OKAY) + ret = MP_READ_E; + + /* w = s invmod q */ + if (ret == 0 && mp_invmod(&s, &key->q, &w) != MP_OKAY) + ret = MP_INVMOD_E; + + /* u1 = (H * w) % q */ + if (ret == 0 && mp_mulmod(&u1, &w, &key->q, &u1) != MP_OKAY) + ret = MP_MULMOD_E; + + /* u2 = (r * w) % q */ + if (ret == 0 && mp_mulmod(&r, &w, &key->q, &u2) != MP_OKAY) + ret = MP_MULMOD_E; + + /* verify v = ((g^u1 * y^u2) mod p) mod q */ + if (ret == 0 && mp_exptmod(&key->g, &u1, &key->p, &u1) != MP_OKAY) + ret = MP_EXPTMOD_E; + + if (ret == 0 && mp_exptmod(&key->y, &u2, &key->p, &u2) != MP_OKAY) + ret = MP_EXPTMOD_E; + + if (ret == 0 && mp_mulmod(&u1, &u2, &key->p, &v) != MP_OKAY) + ret = MP_MULMOD_E; + + if (ret == 0 && mp_mod(&v, &key->q, &v) != MP_OKAY) + ret = MP_MULMOD_E; + + /* do they match */ + if (ret == 0 && mp_cmp(&r, &v) == MP_EQ) + *answer = 1; + else + *answer = 0; + + mp_clear(&s); + mp_clear(&r); + mp_clear(&u1); + mp_clear(&u2); + mp_clear(&w); + mp_clear(&v); + + return ret; +} + + +#endif /* NO_DSA */ + diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/ecc.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/ecc.c new file mode 100755 index 0000000..e204601 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/ecc.c @@ -0,0 +1,10033 @@ +/* ecc.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +/* in case user set HAVE_ECC there */ +#include + +/* public ASN interface */ +#include + +/* +Possible ECC enable options: + * HAVE_ECC: Overall control of ECC default: on + * HAVE_ECC_ENCRYPT: ECC encrypt/decrypt w/AES and HKDF default: off + * HAVE_ECC_SIGN: ECC sign default: on + * HAVE_ECC_VERIFY: ECC verify default: on + * HAVE_ECC_DHE: ECC build shared secret default: on + * HAVE_ECC_CDH: ECC cofactor DH shared secret default: off + * HAVE_ECC_KEY_IMPORT: ECC Key import default: on + * HAVE_ECC_KEY_EXPORT: ECC Key export default: on + * ECC_SHAMIR: Enables Shamir calc method default: on + * HAVE_COMP_KEY: Enables compressed key default: off + * WOLFSSL_VALIDATE_ECC_IMPORT: Validate ECC key on import default: off + * WOLFSSL_VALIDATE_ECC_KEYGEN: Validate ECC key gen default: off + * WOLFSSL_CUSTOM_CURVES: Allow non-standard curves. default: off + * Includes the curve "a" variable in calculation + * ECC_DUMP_OID: Enables dump of OID encoding and sum default: off + * ECC_CACHE_CURVE: Enables cache of curve info to improve perofrmance + default: off + * FP_ECC: ECC Fixed Point Cache default: off + * USE_ECC_B_PARAM: Enable ECC curve B param default: off + (on for HAVE_COMP_KEY) + */ + +/* +ECC Curve Types: + * NO_ECC_SECP Disables SECP curves default: off (not defined) + * HAVE_ECC_SECPR2 Enables SECP R2 curves default: off + * HAVE_ECC_SECPR3 Enables SECP R3 curves default: off + * HAVE_ECC_BRAINPOOL Enables Brainpool curves default: off + * HAVE_ECC_KOBLITZ Enables Koblitz curves default: off + */ + +/* +ECC Curve Sizes: + * ECC_USER_CURVES: Allows custom combination of key sizes below + * HAVE_ALL_CURVES: Enable all key sizes (on unless ECC_USER_CURVES is defined) + * HAVE_ECC112: 112 bit key + * HAVE_ECC128: 128 bit key + * HAVE_ECC160: 160 bit key + * HAVE_ECC192: 192 bit key + * HAVE_ECC224: 224 bit key + * HAVE_ECC239: 239 bit key + * NO_ECC256: Disables 256 bit key (on by default) + * HAVE_ECC320: 320 bit key + * HAVE_ECC384: 384 bit key + * HAVE_ECC512: 512 bit key + * HAVE_ECC521: 521 bit key + */ + + +#ifdef HAVE_ECC + +/* Make sure custom curves is enabled for Brainpool or Koblitz curve types */ +#if (defined(HAVE_ECC_BRAINPOOL) || defined(HAVE_ECC_KOBLITZ)) &&\ + !defined(WOLFSSL_CUSTOM_CURVES) + #error Brainpool and Koblitz curves requires WOLFSSL_CUSTOM_CURVES +#endif + +#if defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ + #define FIPS_NO_WRAPPERS + + #ifdef USE_WINDOWS_API + #pragma code_seg(".fipsA$f") + #pragma const_seg(".fipsB$f") + #endif +#endif + +#include +#include +#include +#include +#include + +#ifdef WOLFSSL_HAVE_SP_ECC +#include +#endif + +#ifdef HAVE_ECC_ENCRYPT + #include + #include +#endif + +#ifdef HAVE_X963_KDF + #include +#endif + +#ifdef WOLF_CRYPTO_CB + #include +#endif + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#if defined(FREESCALE_LTC_ECC) + #include +#endif + +#ifdef WOLFSSL_SP_MATH + #define GEN_MEM_ERR MP_MEM +#elif defined(USE_FAST_MATH) + #define GEN_MEM_ERR FP_MEM +#else + #define GEN_MEM_ERR MP_MEM +#endif + + +/* internal ECC states */ +enum { + ECC_STATE_NONE = 0, + + ECC_STATE_SHARED_SEC_GEN, + ECC_STATE_SHARED_SEC_RES, + + ECC_STATE_SIGN_DO, + ECC_STATE_SIGN_ENCODE, + + ECC_STATE_VERIFY_DECODE, + ECC_STATE_VERIFY_DO, + ECC_STATE_VERIFY_RES, +}; + + +/* map + ptmul -> mulmod +*/ + +/* 256-bit curve on by default whether user curves or not */ +#if defined(HAVE_ECC112) || defined(HAVE_ALL_CURVES) + #define ECC112 +#endif +#if defined(HAVE_ECC128) || defined(HAVE_ALL_CURVES) + #define ECC128 +#endif +#if defined(HAVE_ECC160) || defined(HAVE_ALL_CURVES) + #define ECC160 +#endif +#if defined(HAVE_ECC192) || defined(HAVE_ALL_CURVES) + #define ECC192 +#endif +#if defined(HAVE_ECC224) || defined(HAVE_ALL_CURVES) + #define ECC224 +#endif +#if defined(HAVE_ECC239) || defined(HAVE_ALL_CURVES) + #define ECC239 +#endif +#if !defined(NO_ECC256) || defined(HAVE_ALL_CURVES) + #define ECC256 +#endif +#if defined(HAVE_ECC320) || defined(HAVE_ALL_CURVES) + #define ECC320 +#endif +#if defined(HAVE_ECC384) || defined(HAVE_ALL_CURVES) + #define ECC384 +#endif +#if defined(HAVE_ECC512) || defined(HAVE_ALL_CURVES) + #define ECC512 +#endif +#if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES) + #define ECC521 +#endif + +/* The encoded OID's for ECC curves */ +#ifdef ECC112 + #ifndef NO_ECC_SECP + #ifdef HAVE_OID_ENCODING + #define CODED_SECP112R1 {1,3,132,0,6} + #define CODED_SECP112R1_SZ 5 + #else + #define CODED_SECP112R1 {0x2B,0x81,0x04,0x00,0x06} + #define CODED_SECP112R1_SZ 5 + #endif + #ifndef USE_WINDOWS_API + static const ecc_oid_t ecc_oid_secp112r1[] = CODED_SECP112R1; + #else + #define ecc_oid_secp112r1 CODED_SECP112R1 + #endif + #define ecc_oid_secp112r1_sz CODED_SECP112R1_SZ + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_SECPR2 + #ifdef HAVE_OID_ENCODING + #define CODED_SECP112R2 {1,3,132,0,7} + #define CODED_SECP112R2_SZ 5 + #else + #define CODED_SECP112R2 {0x2B,0x81,0x04,0x00,0x07} + #define CODED_SECP112R2_SZ 5 + #endif + #ifndef USE_WINDOWS_API + static const ecc_oid_t ecc_oid_secp112r2[] = CODED_SECP112R2; + #else + #define ecc_oid_secp112r2 CODED_SECP112R2 + #endif + #define ecc_oid_secp112r2_sz CODED_SECP112R2_SZ + #endif /* HAVE_ECC_SECPR2 */ +#endif /* ECC112 */ +#ifdef ECC128 + #ifndef NO_ECC_SECP + #ifdef HAVE_OID_ENCODING + #define CODED_SECP128R1 {1,3,132,0,28} + #define CODED_SECP128R1_SZ 5 + #else + #define CODED_SECP128R1 {0x2B,0x81,0x04,0x00,0x1C} + #define CODED_SECP128R1_SZ 5 + #endif + #ifndef USE_WINDOWS_API + static const ecc_oid_t ecc_oid_secp128r1[] = CODED_SECP128R1; + #else + #define ecc_oid_secp128r1 CODED_SECP128R1 + #endif + #define ecc_oid_secp128r1_sz CODED_SECP128R1_SZ + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_SECPR2 + #ifdef HAVE_OID_ENCODING + #define CODED_SECP128R2 {1,3,132,0,29} + #define CODED_SECP128R2_SZ 5 + #else + #define CODED_SECP128R2 {0x2B,0x81,0x04,0x00,0x1D} + #define CODED_SECP128R2_SZ 5 + #endif + #ifndef USE_WINDOWS_API + static const ecc_oid_t ecc_oid_secp128r2[] = CODED_SECP128R2; + #else + #define ecc_oid_secp128r2 CODED_SECP128R2 + #endif + #define ecc_oid_secp128r2_sz CODED_SECP128R2_SZ + #endif /* HAVE_ECC_SECPR2 */ +#endif /* ECC128 */ +#ifdef ECC160 + #ifndef NO_ECC_SECP + #ifdef HAVE_OID_ENCODING + #define CODED_SECP160R1 {1,3,132,0,8} + #define CODED_SECP160R1_SZ 5 + #else + #define CODED_SECP160R1 {0x2B,0x81,0x04,0x00,0x08} + #define CODED_SECP160R1_SZ 5 + #endif + #ifndef USE_WINDOWS_API + static const ecc_oid_t ecc_oid_secp160r1[] = CODED_SECP160R1; + #else + #define ecc_oid_secp160r1 CODED_SECP160R1 + #endif + #define ecc_oid_secp160r1_sz CODED_SECP160R1_SZ + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_SECPR2 + #ifdef HAVE_OID_ENCODING + #define CODED_SECP160R2 {1,3,132,0,30} + #define CODED_SECP160R1_SZ 5 + #else + #define CODED_SECP160R2 {0x2B,0x81,0x04,0x00,0x1E} + #define CODED_SECP160R2_SZ 5 + #endif + #ifndef USE_WINDOWS_API + static const ecc_oid_t ecc_oid_secp160r2[] = CODED_SECP160R2; + #else + #define ecc_oid_secp160r2 CODED_SECP160R2 + #endif + #define ecc_oid_secp160r2_sz CODED_SECP160R2_SZ + #endif /* HAVE_ECC_SECPR2 */ + #ifdef HAVE_ECC_KOBLITZ + #ifdef HAVE_OID_ENCODING + #define CODED_SECP160K1 {1,3,132,0,9} + #define CODED_SECP160K1_SZ 5 + #else + #define CODED_SECP160K1 {0x2B,0x81,0x04,0x00,0x09} + #define CODED_SECP160K1_SZ 5 + #endif + #ifndef USE_WINDOWS_API + static const ecc_oid_t ecc_oid_secp160k1[] = CODED_SECP160K1; + #else + #define ecc_oid_secp160k1 CODED_SECP160K1 + #endif + #define ecc_oid_secp160k1_sz CODED_SECP160K1_SZ + #endif /* HAVE_ECC_KOBLITZ */ + #ifdef HAVE_ECC_BRAINPOOL + #ifdef HAVE_OID_ENCODING + #define CODED_BRAINPOOLP160R1 {1,3,36,3,3,2,8,1,1,1} + #define CODED_BRAINPOOLP160R1_SZ 10 + #else + #define CODED_BRAINPOOLP160R1 {0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x01} + #define CODED_BRAINPOOLP160R1_SZ 9 + #endif + #ifndef USE_WINDOWS_API + static const ecc_oid_t ecc_oid_brainpoolp160r1[] = CODED_BRAINPOOLP160R1; + #else + #define ecc_oid_brainpoolp160r1 CODED_BRAINPOOLP160R1 + #endif + #define ecc_oid_brainpoolp160r1_sz CODED_BRAINPOOLP160R1_SZ + #endif /* HAVE_ECC_BRAINPOOL */ +#endif /* ECC160 */ +#ifdef ECC192 + #ifndef NO_ECC_SECP + #ifdef HAVE_OID_ENCODING + #define CODED_SECP192R1 {1,2,840,10045,3,1,1} + #define CODED_SECP192R1_SZ 7 + #else + #define CODED_SECP192R1 {0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x01} + #define CODED_SECP192R1_SZ 8 + #endif + #ifndef USE_WINDOWS_API + static const ecc_oid_t ecc_oid_secp192r1[] = CODED_SECP192R1; + #else + #define ecc_oid_secp192r1 CODED_SECP192R1 + #endif + #define ecc_oid_secp192r1_sz CODED_SECP192R1_SZ + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_SECPR2 + #ifdef HAVE_OID_ENCODING + #define CODED_PRIME192V2 {1,2,840,10045,3,1,2} + #define CODED_PRIME192V2_SZ 7 + #else + #define CODED_PRIME192V2 {0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x02} + #define CODED_PRIME192V2_SZ 8 + #endif + #ifndef USE_WINDOWS_API + static const ecc_oid_t ecc_oid_prime192v2[] = CODED_PRIME192V2; + #else + #define ecc_oid_prime192v2 CODED_PRIME192V2 + #endif + #define ecc_oid_prime192v2_sz CODED_PRIME192V2_SZ + #endif /* HAVE_ECC_SECPR2 */ + #ifdef HAVE_ECC_SECPR3 + #ifdef HAVE_OID_ENCODING + #define CODED_PRIME192V3 {1,2,840,10045,3,1,3} + #define CODED_PRIME192V3_SZ 7 + #else + #define CODED_PRIME192V3 {0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x03} + #define CODED_PRIME192V3_SZ 8 + #endif + #ifndef USE_WINDOWS_API + static const ecc_oid_t ecc_oid_prime192v3[] = CODED_PRIME192V3; + #else + #define ecc_oid_prime192v3 CODED_PRIME192V3 + #endif + #define ecc_oid_prime192v3_sz CODED_PRIME192V3_SZ + #endif /* HAVE_ECC_SECPR3 */ + #ifdef HAVE_ECC_KOBLITZ + #ifdef HAVE_OID_ENCODING + #define CODED_SECP192K1 {1,3,132,0,31} + #define CODED_SECP192K1_SZ 5 + #else + #define CODED_SECP192K1 {0x2B,0x81,0x04,0x00,0x1F} + #define CODED_SECP192K1_SZ 5 + #endif + #ifndef USE_WINDOWS_API + static const ecc_oid_t ecc_oid_secp192k1[] = CODED_SECP192K1; + #else + #define ecc_oid_secp192k1 CODED_SECP192K1 + #endif + #define ecc_oid_secp192k1_sz CODED_SECP192K1_SZ + #endif /* HAVE_ECC_KOBLITZ */ + #ifdef HAVE_ECC_BRAINPOOL + #ifdef HAVE_OID_ENCODING + #define CODED_BRAINPOOLP192R1 {1,3,36,3,3,2,8,1,1,3} + #define CODED_BRAINPOOLP192R1_SZ 10 + #else + #define CODED_BRAINPOOLP192R1 {0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x03} + #define CODED_BRAINPOOLP192R1_SZ 9 + #endif + #ifndef USE_WINDOWS_API + static const ecc_oid_t ecc_oid_brainpoolp192r1[] = CODED_BRAINPOOLP192R1; + #else + #define ecc_oid_brainpoolp192r1 CODED_BRAINPOOLP192R1 + #endif + #define ecc_oid_brainpoolp192r1_sz CODED_BRAINPOOLP192R1_SZ + #endif /* HAVE_ECC_BRAINPOOL */ +#endif /* ECC192 */ +#ifdef ECC224 + #ifndef NO_ECC_SECP + #ifdef HAVE_OID_ENCODING + #define CODED_SECP224R1 {1,3,132,0,33} + #define CODED_SECP224R1_SZ 5 + #else + #define CODED_SECP224R1 {0x2B,0x81,0x04,0x00,0x21} + #define CODED_SECP224R1_SZ 5 + #endif + #ifndef USE_WINDOWS_API + static const ecc_oid_t ecc_oid_secp224r1[] = CODED_SECP224R1; + #else + #define ecc_oid_secp224r1 CODED_SECP224R1 + #endif + #define ecc_oid_secp224r1_sz CODED_SECP224R1_SZ + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_KOBLITZ + #ifdef HAVE_OID_ENCODING + #define CODED_SECP224K1 {1,3,132,0,32} + #define CODED_SECP224K1_SZ 5 + #else + #define CODED_SECP224K1 {0x2B,0x81,0x04,0x00,0x20} + #define CODED_SECP224K1_SZ 5 + #endif + #ifndef USE_WINDOWS_API + static const ecc_oid_t ecc_oid_secp224k1[] = CODED_SECP224K1; + #else + #define ecc_oid_secp224k1 CODED_SECP224K1 + #endif + #define ecc_oid_secp224k1_sz CODED_SECP224K1_SZ + #endif /* HAVE_ECC_KOBLITZ */ + #ifdef HAVE_ECC_BRAINPOOL + #ifdef HAVE_OID_ENCODING + #define CODED_BRAINPOOLP224R1 {1,3,36,3,3,2,8,1,1,5} + #define CODED_BRAINPOOLP224R1_SZ 10 + #else + #define CODED_BRAINPOOLP224R1 {0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x05} + #define CODED_BRAINPOOLP224R1_SZ 9 + #endif + #ifndef USE_WINDOWS_API + static const ecc_oid_t ecc_oid_brainpoolp224r1[] = CODED_BRAINPOOLP224R1; + #else + #define ecc_oid_brainpoolp224r1 CODED_BRAINPOOLP224R1 + #endif + #define ecc_oid_brainpoolp224r1_sz CODED_BRAINPOOLP224R1_SZ + #endif /* HAVE_ECC_BRAINPOOL */ +#endif /* ECC224 */ +#ifdef ECC239 + #ifndef NO_ECC_SECP + #ifdef HAVE_OID_ENCODING + #define CODED_PRIME239V1 {1,2,840,10045,3,1,4} + #define CODED_PRIME239V1_SZ 7 + #else + #define CODED_PRIME239V1 {0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x04} + #define CODED_PRIME239V1_SZ 8 + #endif + #ifndef USE_WINDOWS_API + static const ecc_oid_t ecc_oid_prime239v1[] = CODED_PRIME239V1; + #else + #define ecc_oid_prime239v1 CODED_PRIME239V1 + #endif + #define ecc_oid_prime239v1_sz CODED_PRIME239V1_SZ + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_SECPR2 + #ifdef HAVE_OID_ENCODING + #define CODED_PRIME239V2 {1,2,840,10045,3,1,5} + #define CODED_PRIME239V2_SZ 7 + #else + #define CODED_PRIME239V2 {0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x05} + #define CODED_PRIME239V2_SZ 8 + #endif + #ifndef USE_WINDOWS_API + static const ecc_oid_t ecc_oid_prime239v2[] = CODED_PRIME239V2; + #else + #define ecc_oid_prime239v2 CODED_PRIME239V2 + #endif + #define ecc_oid_prime239v2_sz CODED_PRIME239V2_SZ + #endif /* HAVE_ECC_SECPR2 */ + #ifdef HAVE_ECC_SECPR3 + #ifdef HAVE_OID_ENCODING + #define CODED_PRIME239V3 {1,2,840,10045,3,1,6} + #define CODED_PRIME239V3_SZ 7 + #else + #define CODED_PRIME239V3 {0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x06} + #define CODED_PRIME239V3_SZ 8 + #endif + #ifndef USE_WINDOWS_API + static const ecc_oid_t ecc_oid_prime239v3[] = CODED_PRIME239V3; + #else + #define ecc_oid_prime239v3 CODED_PRIME239V3 + #endif + #define ecc_oid_prime239v3_sz CODED_PRIME239V3_SZ + #endif /* HAVE_ECC_SECPR3 */ +#endif /* ECC239 */ +#ifdef ECC256 + #ifndef NO_ECC_SECP + #ifdef HAVE_OID_ENCODING + #define CODED_SECP256R1 {1,2,840,10045,3,1,7} + #define CODED_SECP256R1_SZ 7 + #else + #define CODED_SECP256R1 {0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x07} + #define CODED_SECP256R1_SZ 8 + #endif + #ifndef USE_WINDOWS_API + static const ecc_oid_t ecc_oid_secp256r1[] = CODED_SECP256R1; + #else + #define ecc_oid_secp256r1 CODED_SECP256R1 + #endif + #define ecc_oid_secp256r1_sz CODED_SECP256R1_SZ + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_KOBLITZ + #ifdef HAVE_OID_ENCODING + #define CODED_SECP256K1 {1,3,132,0,10} + #define CODED_SECP256K1_SZ 5 + #else + #define CODED_SECP256K1 {0x2B,0x81,0x04,0x00,0x0A} + #define CODED_SECP256K1_SZ 5 + #endif + #ifndef USE_WINDOWS_API + static const ecc_oid_t ecc_oid_secp256k1[] = CODED_SECP256K1; + #else + #define ecc_oid_secp256k1 CODED_SECP256K1 + #endif + #define ecc_oid_secp256k1_sz CODED_SECP256K1_SZ + #endif /* HAVE_ECC_KOBLITZ */ + #ifdef HAVE_ECC_BRAINPOOL + #ifdef HAVE_OID_ENCODING + #define CODED_BRAINPOOLP256R1 {1,3,36,3,3,2,8,1,1,7} + #define CODED_BRAINPOOLP256R1_SZ 10 + #else + #define CODED_BRAINPOOLP256R1 {0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x07} + #define CODED_BRAINPOOLP256R1_SZ 9 + #endif + #ifndef USE_WINDOWS_API + static const ecc_oid_t ecc_oid_brainpoolp256r1[] = CODED_BRAINPOOLP256R1; + #else + #define ecc_oid_brainpoolp256r1 CODED_BRAINPOOLP256R1 + #endif + #define ecc_oid_brainpoolp256r1_sz CODED_BRAINPOOLP256R1_SZ + #endif /* HAVE_ECC_BRAINPOOL */ +#endif /* ECC256 */ +#ifdef ECC320 + #ifdef HAVE_ECC_BRAINPOOL + #ifdef HAVE_OID_ENCODING + #define CODED_BRAINPOOLP320R1 {1,3,36,3,3,2,8,1,1,9} + #define CODED_BRAINPOOLP320R1_SZ 10 + #else + #define CODED_BRAINPOOLP320R1 {0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x09} + #define CODED_BRAINPOOLP320R1_SZ 9 + #endif + #ifndef USE_WINDOWS_API + static const ecc_oid_t ecc_oid_brainpoolp320r1[] = CODED_BRAINPOOLP320R1; + #else + #define ecc_oid_brainpoolp320r1 CODED_BRAINPOOLP320R1 + #endif + #define ecc_oid_brainpoolp320r1_sz CODED_BRAINPOOLP320R1_SZ + #endif /* HAVE_ECC_BRAINPOOL */ +#endif /* ECC320 */ +#ifdef ECC384 + #ifndef NO_ECC_SECP + #ifdef HAVE_OID_ENCODING + #define CODED_SECP384R1 {1,3,132,0,34} + #define CODED_SECP384R1_SZ 5 + #else + #define CODED_SECP384R1 {0x2B,0x81,0x04,0x00,0x22} + #define CODED_SECP384R1_SZ 5 + #endif + #ifndef USE_WINDOWS_API + static const ecc_oid_t ecc_oid_secp384r1[] = CODED_SECP384R1; + #define CODED_SECP384R1_OID ecc_oid_secp384r1 + #else + #define ecc_oid_secp384r1 CODED_SECP384R1 + #endif + #define ecc_oid_secp384r1_sz CODED_SECP384R1_SZ + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_BRAINPOOL + #ifdef HAVE_OID_ENCODING + #define CODED_BRAINPOOLP384R1 {1,3,36,3,3,2,8,1,1,11} + #define CODED_BRAINPOOLP384R1_SZ 10 + #else + #define CODED_BRAINPOOLP384R1 {0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x0B} + #define CODED_BRAINPOOLP384R1_SZ 9 + #endif + #ifndef USE_WINDOWS_API + static const ecc_oid_t ecc_oid_brainpoolp384r1[] = CODED_BRAINPOOLP384R1; + #else + #define ecc_oid_brainpoolp384r1 CODED_BRAINPOOLP384R1 + #endif + #define ecc_oid_brainpoolp384r1_sz CODED_BRAINPOOLP384R1_SZ + #endif /* HAVE_ECC_BRAINPOOL */ +#endif /* ECC384 */ +#ifdef ECC512 + #ifdef HAVE_ECC_BRAINPOOL + #ifdef HAVE_OID_ENCODING + #define CODED_BRAINPOOLP512R1 {1,3,36,3,3,2,8,1,1,13} + #define CODED_BRAINPOOLP512R1_SZ 10 + #else + #define CODED_BRAINPOOLP512R1 {0x2B,0x24,0x03,0x03,0x02,0x08,0x01,0x01,0x0D} + #define CODED_BRAINPOOLP512R1_SZ 9 + #endif + #ifndef USE_WINDOWS_API + static const ecc_oid_t ecc_oid_brainpoolp512r1[] = CODED_BRAINPOOLP512R1; + #else + #define ecc_oid_brainpoolp512r1 CODED_BRAINPOOLP512R1 + #endif + #define ecc_oid_brainpoolp512r1_sz CODED_BRAINPOOLP512R1_SZ + #endif /* HAVE_ECC_BRAINPOOL */ +#endif /* ECC512 */ +#ifdef ECC521 + #ifndef NO_ECC_SECP + #ifdef HAVE_OID_ENCODING + #define CODED_SECP521R1 {1,3,132,0,35} + #define CODED_SECP521R1_SZ 5 + #else + #define CODED_SECP521R1 {0x2B,0x81,0x04,0x00,0x23} + #define CODED_SECP521R1_SZ 5 + #endif + #ifndef USE_WINDOWS_API + static const ecc_oid_t ecc_oid_secp521r1[] = CODED_SECP521R1; + #else + #define ecc_oid_secp521r1 CODED_SECP521R1 + #endif + #define ecc_oid_secp521r1_sz CODED_SECP521R1_SZ + #endif /* !NO_ECC_SECP */ +#endif /* ECC521 */ + + +/* This holds the key settings. + ***MUST*** be organized by size from smallest to largest. */ + +const ecc_set_type ecc_sets[] = { +#ifdef ECC112 + #ifndef NO_ECC_SECP + { + 14, /* size/bytes */ + ECC_SECP112R1, /* ID */ + "SECP112R1", /* curve name */ + "DB7C2ABF62E35E668076BEAD208B", /* prime */ + "DB7C2ABF62E35E668076BEAD2088", /* A */ + "659EF8BA043916EEDE8911702B22", /* B */ + "DB7C2ABF62E35E7628DFAC6561C5", /* order */ + "9487239995A5EE76B55F9C2F098", /* Gx */ + "A89CE5AF8724C0A23E0E0FF77500", /* Gy */ + ecc_oid_secp112r1, /* oid/oidSz */ + ecc_oid_secp112r1_sz, + ECC_SECP112R1_OID, /* oid sum */ + 1, /* cofactor */ + }, + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_SECPR2 + { + 14, /* size/bytes */ + ECC_SECP112R2, /* ID */ + "SECP112R2", /* curve name */ + "DB7C2ABF62E35E668076BEAD208B", /* prime */ + "6127C24C05F38A0AAAF65C0EF02C", /* A */ + "51DEF1815DB5ED74FCC34C85D709", /* B */ + "36DF0AAFD8B8D7597CA10520D04B", /* order */ + "4BA30AB5E892B4E1649DD0928643", /* Gx */ + "ADCD46F5882E3747DEF36E956E97", /* Gy */ + ecc_oid_secp112r2, /* oid/oidSz */ + ecc_oid_secp112r2_sz, + ECC_SECP112R2_OID, /* oid sum */ + 4, /* cofactor */ + }, + #endif /* HAVE_ECC_SECPR2 */ +#endif /* ECC112 */ +#ifdef ECC128 + #ifndef NO_ECC_SECP + { + 16, /* size/bytes */ + ECC_SECP128R1, /* ID */ + "SECP128R1", /* curve name */ + "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF", /* prime */ + "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC", /* A */ + "E87579C11079F43DD824993C2CEE5ED3", /* B */ + "FFFFFFFE0000000075A30D1B9038A115", /* order */ + "161FF7528B899B2D0C28607CA52C5B86", /* Gx */ + "CF5AC8395BAFEB13C02DA292DDED7A83", /* Gy */ + ecc_oid_secp128r1, /* oid/oidSz */ + ecc_oid_secp128r1_sz, + ECC_SECP128R1_OID, /* oid sum */ + 1, /* cofactor */ + }, + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_SECPR2 + { + 16, /* size/bytes */ + ECC_SECP128R2, /* ID */ + "SECP128R2", /* curve name */ + "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF", /* prime */ + "D6031998D1B3BBFEBF59CC9BBFF9AEE1", /* A */ + "5EEEFCA380D02919DC2C6558BB6D8A5D", /* B */ + "3FFFFFFF7FFFFFFFBE0024720613B5A3", /* order */ + "7B6AA5D85E572983E6FB32A7CDEBC140", /* Gx */ + "27B6916A894D3AEE7106FE805FC34B44", /* Gy */ + ecc_oid_secp128r2, /* oid/oidSz */ + ecc_oid_secp128r2_sz, + ECC_SECP128R2_OID, /* oid sum */ + 4, /* cofactor */ + }, + #endif /* HAVE_ECC_SECPR2 */ +#endif /* ECC128 */ +#ifdef ECC160 + #ifndef NO_ECC_SECP + { + 20, /* size/bytes */ + ECC_SECP160R1, /* ID */ + "SECP160R1", /* curve name */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF", /* prime */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC", /* A */ + "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45", /* B */ + "100000000000000000001F4C8F927AED3CA752257",/* order */ + "4A96B5688EF573284664698968C38BB913CBFC82", /* Gx */ + "23A628553168947D59DCC912042351377AC5FB32", /* Gy */ + ecc_oid_secp160r1, /* oid/oidSz */ + ecc_oid_secp160r1_sz, + ECC_SECP160R1_OID, /* oid sum */ + 1, /* cofactor */ + }, + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_SECPR2 + { + 20, /* size/bytes */ + ECC_SECP160R2, /* ID */ + "SECP160R2", /* curve name */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73", /* prime */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC70", /* A */ + "B4E134D3FB59EB8BAB57274904664D5AF50388BA", /* B */ + "100000000000000000000351EE786A818F3A1A16B",/* order */ + "52DCB034293A117E1F4FF11B30F7199D3144CE6D", /* Gx */ + "FEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E", /* Gy */ + ecc_oid_secp160r2, /* oid/oidSz */ + ecc_oid_secp160r2_sz, + ECC_SECP160R2_OID, /* oid sum */ + 1, /* cofactor */ + }, + #endif /* HAVE_ECC_SECPR2 */ + #ifdef HAVE_ECC_KOBLITZ + { + 20, /* size/bytes */ + ECC_SECP160K1, /* ID */ + "SECP160K1", /* curve name */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73", /* prime */ + "0000000000000000000000000000000000000000", /* A */ + "0000000000000000000000000000000000000007", /* B */ + "100000000000000000001B8FA16DFAB9ACA16B6B3",/* order */ + "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB", /* Gx */ + "938CF935318FDCED6BC28286531733C3F03C4FEE", /* Gy */ + ecc_oid_secp160k1, /* oid/oidSz */ + ecc_oid_secp160k1_sz, + ECC_SECP160K1_OID, /* oid sum */ + 1, /* cofactor */ + }, + #endif /* HAVE_ECC_KOBLITZ */ + #ifdef HAVE_ECC_BRAINPOOL + { + 20, /* size/bytes */ + ECC_BRAINPOOLP160R1, /* ID */ + "BRAINPOOLP160R1", /* curve name */ + "E95E4A5F737059DC60DFC7AD95B3D8139515620F", /* prime */ + "340E7BE2A280EB74E2BE61BADA745D97E8F7C300", /* A */ + "1E589A8595423412134FAA2DBDEC95C8D8675E58", /* B */ + "E95E4A5F737059DC60DF5991D45029409E60FC09", /* order */ + "BED5AF16EA3F6A4F62938C4631EB5AF7BDBCDBC3", /* Gx */ + "1667CB477A1A8EC338F94741669C976316DA6321", /* Gy */ + ecc_oid_brainpoolp160r1, /* oid/oidSz */ + ecc_oid_brainpoolp160r1_sz, + ECC_BRAINPOOLP160R1_OID, /* oid sum */ + 1, /* cofactor */ + }, + #endif /* HAVE_ECC_BRAINPOOL */ +#endif /* ECC160 */ +#ifdef ECC192 + #ifndef NO_ECC_SECP + { + 24, /* size/bytes */ + ECC_SECP192R1, /* ID */ + "SECP192R1", /* curve name */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", /* prime */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", /* A */ + "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1", /* B */ + "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831", /* order */ + "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012", /* Gx */ + "7192B95FFC8DA78631011ED6B24CDD573F977A11E794811", /* Gy */ + ecc_oid_secp192r1, /* oid/oidSz */ + ecc_oid_secp192r1_sz, + ECC_SECP192R1_OID, /* oid sum */ + 1, /* cofactor */ + }, + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_SECPR2 + { + 24, /* size/bytes */ + ECC_PRIME192V2, /* ID */ + "PRIME192V2", /* curve name */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", /* prime */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", /* A */ + "CC22D6DFB95C6B25E49C0D6364A4E5980C393AA21668D953", /* B */ + "FFFFFFFFFFFFFFFFFFFFFFFE5FB1A724DC80418648D8DD31", /* order */ + "EEA2BAE7E1497842F2DE7769CFE9C989C072AD696F48034A", /* Gx */ + "6574D11D69B6EC7A672BB82A083DF2F2B0847DE970B2DE15", /* Gy */ + ecc_oid_prime192v2, /* oid/oidSz */ + ecc_oid_prime192v2_sz, + ECC_PRIME192V2_OID, /* oid sum */ + 1, /* cofactor */ + }, + #endif /* HAVE_ECC_SECPR2 */ + #ifdef HAVE_ECC_SECPR3 + { + 24, /* size/bytes */ + ECC_PRIME192V3, /* ID */ + "PRIME192V3", /* curve name */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF", /* prime */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC", /* A */ + "22123DC2395A05CAA7423DAECCC94760A7D462256BD56916", /* B */ + "FFFFFFFFFFFFFFFFFFFFFFFF7A62D031C83F4294F640EC13", /* order */ + "7D29778100C65A1DA1783716588DCE2B8B4AEE8E228F1896", /* Gx */ + "38A90F22637337334B49DCB66A6DC8F9978ACA7648A943B0", /* Gy */ + ecc_oid_prime192v3, /* oid/oidSz */ + ecc_oid_prime192v3_sz, + ECC_PRIME192V3_OID, /* oid sum */ + 1, /* cofactor */ + }, + #endif /* HAVE_ECC_SECPR3 */ + #ifdef HAVE_ECC_KOBLITZ + { + 24, /* size/bytes */ + ECC_SECP192K1, /* ID */ + "SECP192K1", /* curve name */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37", /* prime */ + "000000000000000000000000000000000000000000000000", /* A */ + "000000000000000000000000000000000000000000000003", /* B */ + "FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D", /* order */ + "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D", /* Gx */ + "9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D", /* Gy */ + ecc_oid_secp192k1, /* oid/oidSz */ + ecc_oid_secp192k1_sz, + ECC_SECP192K1_OID, /* oid sum */ + 1, /* cofactor */ + }, + #endif /* HAVE_ECC_KOBLITZ */ + #ifdef HAVE_ECC_BRAINPOOL + { + 24, /* size/bytes */ + ECC_BRAINPOOLP192R1, /* ID */ + "BRAINPOOLP192R1", /* curve name */ + "C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297", /* prime */ + "6A91174076B1E0E19C39C031FE8685C1CAE040E5C69A28EF", /* A */ + "469A28EF7C28CCA3DC721D044F4496BCCA7EF4146FBF25C9", /* B */ + "C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1", /* order */ + "C0A0647EAAB6A48753B033C56CB0F0900A2F5C4853375FD6", /* Gx */ + "14B690866ABD5BB88B5F4828C1490002E6773FA2FA299B8F", /* Gy */ + ecc_oid_brainpoolp192r1, /* oid/oidSz */ + ecc_oid_brainpoolp192r1_sz, + ECC_BRAINPOOLP192R1_OID, /* oid sum */ + 1, /* cofactor */ + }, + #endif /* HAVE_ECC_BRAINPOOL */ +#endif /* ECC192 */ +#ifdef ECC224 + #ifndef NO_ECC_SECP + { + 28, /* size/bytes */ + ECC_SECP224R1, /* ID */ + "SECP224R1", /* curve name */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001", /* prime */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE", /* A */ + "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4", /* B */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D", /* order */ + "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21", /* Gx */ + "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34", /* Gy */ + ecc_oid_secp224r1, /* oid/oidSz */ + ecc_oid_secp224r1_sz, + ECC_SECP224R1_OID, /* oid sum */ + 1, /* cofactor */ + }, + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_KOBLITZ + { + 28, /* size/bytes */ + ECC_SECP224K1, /* ID */ + "SECP224K1", /* curve name */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D", /* prime */ + "00000000000000000000000000000000000000000000000000000000", /* A */ + "00000000000000000000000000000000000000000000000000000005", /* B */ + "10000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7",/* order */ + "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C", /* Gx */ + "7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5", /* Gy */ + ecc_oid_secp224k1, /* oid/oidSz */ + ecc_oid_secp224k1_sz, + ECC_SECP224K1_OID, /* oid sum */ + 1, /* cofactor */ + }, + #endif /* HAVE_ECC_KOBLITZ */ + #ifdef HAVE_ECC_BRAINPOOL + { + 28, /* size/bytes */ + ECC_BRAINPOOLP224R1, /* ID */ + "BRAINPOOLP224R1", /* curve name */ + "D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF", /* prime */ + "68A5E62CA9CE6C1C299803A6C1530B514E182AD8B0042A59CAD29F43", /* A */ + "2580F63CCFE44138870713B1A92369E33E2135D266DBB372386C400B", /* B */ + "D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F", /* order */ + "0D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D", /* Gx */ + "58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD", /* Gy */ + ecc_oid_brainpoolp224r1, /* oid/oidSz */ + ecc_oid_brainpoolp224r1_sz, + ECC_BRAINPOOLP224R1_OID, /* oid sum */ + 1, /* cofactor */ + }, + #endif /* HAVE_ECC_BRAINPOOL */ +#endif /* ECC224 */ +#ifdef ECC239 + #ifndef NO_ECC_SECP + { + 30, /* size/bytes */ + ECC_PRIME239V1, /* ID */ + "PRIME239V1", /* curve name */ + "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF", /* prime */ + "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC", /* A */ + "6B016C3BDCF18941D0D654921475CA71A9DB2FB27D1D37796185C2942C0A", /* B */ + "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF9E5E9A9F5D9071FBD1522688909D0B", /* order */ + "0FFA963CDCA8816CCC33B8642BEDF905C3D358573D3F27FBBD3B3CB9AAAF", /* Gx */ + "7DEBE8E4E90A5DAE6E4054CA530BA04654B36818CE226B39FCCB7B02F1AE", /* Gy */ + ecc_oid_prime239v1, /* oid/oidSz */ + ecc_oid_prime239v1_sz, + ECC_PRIME239V1_OID, /* oid sum */ + 1, /* cofactor */ + }, + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_SECPR2 + { + 30, /* size/bytes */ + ECC_PRIME239V2, /* ID */ + "PRIME239V2", /* curve name */ + "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF", /* prime */ + "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC", /* A */ + "617FAB6832576CBBFED50D99F0249C3FEE58B94BA0038C7AE84C8C832F2C", /* B */ + "7FFFFFFFFFFFFFFFFFFFFFFF800000CFA7E8594377D414C03821BC582063", /* order */ + "38AF09D98727705120C921BB5E9E26296A3CDCF2F35757A0EAFD87B830E7", /* Gx */ + "5B0125E4DBEA0EC7206DA0FC01D9B081329FB555DE6EF460237DFF8BE4BA", /* Gy */ + ecc_oid_prime239v2, /* oid/oidSz */ + ecc_oid_prime239v2_sz, + ECC_PRIME239V2_OID, /* oid sum */ + 1, /* cofactor */ + }, + #endif /* HAVE_ECC_SECPR2 */ + #ifdef HAVE_ECC_SECPR3 + { + 30, /* size/bytes */ + ECC_PRIME239V3, /* ID */ + "PRIME239V3", /* curve name */ + "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF", /* prime */ + "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC", /* A */ + "255705FA2A306654B1F4CB03D6A750A30C250102D4988717D9BA15AB6D3E", /* B */ + "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF975DEB41B3A6057C3C432146526551", /* order */ + "6768AE8E18BB92CFCF005C949AA2C6D94853D0E660BBF854B1C9505FE95A", /* Gx */ + "1607E6898F390C06BC1D552BAD226F3B6FCFE48B6E818499AF18E3ED6CF3", /* Gy */ + ecc_oid_prime239v3, /* oid/oidSz */ + ecc_oid_prime239v3_sz, + ECC_PRIME239V3_OID, /* oid sum */ + 1, /* cofactor */ + }, + #endif /* HAVE_ECC_SECPR3 */ +#endif /* ECC239 */ +#ifdef ECC256 + #ifndef NO_ECC_SECP + { + 32, /* size/bytes */ + ECC_SECP256R1, /* ID */ + "SECP256R1", /* curve name */ + "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF", /* prime */ + "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC", /* A */ + "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B", /* B */ + "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551", /* order */ + "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296", /* Gx */ + "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5", /* Gy */ + ecc_oid_secp256r1, /* oid/oidSz */ + ecc_oid_secp256r1_sz, + ECC_SECP256R1_OID, /* oid sum */ + 1, /* cofactor */ + }, + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_KOBLITZ + { + 32, /* size/bytes */ + ECC_SECP256K1, /* ID */ + "SECP256K1", /* curve name */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", /* prime */ + "0000000000000000000000000000000000000000000000000000000000000000", /* A */ + "0000000000000000000000000000000000000000000000000000000000000007", /* B */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", /* order */ + "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", /* Gx */ + "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", /* Gy */ + ecc_oid_secp256k1, /* oid/oidSz */ + ecc_oid_secp256k1_sz, + ECC_SECP256K1_OID, /* oid sum */ + 1, /* cofactor */ + }, + #endif /* HAVE_ECC_KOBLITZ */ + #ifdef HAVE_ECC_BRAINPOOL + { + 32, /* size/bytes */ + ECC_BRAINPOOLP256R1, /* ID */ + "BRAINPOOLP256R1", /* curve name */ + "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377", /* prime */ + "7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9", /* A */ + "26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6", /* B */ + "A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7", /* order */ + "8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262", /* Gx */ + "547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997", /* Gy */ + ecc_oid_brainpoolp256r1, /* oid/oidSz */ + ecc_oid_brainpoolp256r1_sz, + ECC_BRAINPOOLP256R1_OID, /* oid sum */ + 1, /* cofactor */ + }, + #endif /* HAVE_ECC_BRAINPOOL */ +#endif /* ECC256 */ +#ifdef ECC320 + #ifdef HAVE_ECC_BRAINPOOL + { + 40, /* size/bytes */ + ECC_BRAINPOOLP320R1, /* ID */ + "BRAINPOOLP320R1", /* curve name */ + "D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27", /* prime */ + "3EE30B568FBAB0F883CCEBD46D3F3BB8A2A73513F5EB79DA66190EB085FFA9F492F375A97D860EB4", /* A */ + "520883949DFDBC42D3AD198640688A6FE13F41349554B49ACC31DCCD884539816F5EB4AC8FB1F1A6", /* B */ + "D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311", /* order */ + "43BD7E9AFB53D8B85289BCC48EE5BFE6F20137D10A087EB6E7871E2A10A599C710AF8D0D39E20611", /* Gx */ + "14FDD05545EC1CC8AB4093247F77275E0743FFED117182EAA9C77877AAAC6AC7D35245D1692E8EE1", /* Gy */ + ecc_oid_brainpoolp320r1, ecc_oid_brainpoolp320r1_sz, /* oid/oidSz */ + ECC_BRAINPOOLP320R1_OID, /* oid sum */ + 1, /* cofactor */ + }, + #endif /* HAVE_ECC_BRAINPOOL */ +#endif /* ECC320 */ +#ifdef ECC384 + #ifndef NO_ECC_SECP + { + 48, /* size/bytes */ + ECC_SECP384R1, /* ID */ + "SECP384R1", /* curve name */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF", /* prime */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC", /* A */ + "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF", /* B */ + "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973", /* order */ + "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7", /* Gx */ + "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F", /* Gy */ + ecc_oid_secp384r1, ecc_oid_secp384r1_sz, /* oid/oidSz */ + ECC_SECP384R1_OID, /* oid sum */ + 1, /* cofactor */ + }, + #endif /* !NO_ECC_SECP */ + #ifdef HAVE_ECC_BRAINPOOL + { + 48, /* size/bytes */ + ECC_BRAINPOOLP384R1, /* ID */ + "BRAINPOOLP384R1", /* curve name */ + "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53", /* prime */ + "7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA5814A503AD4EB04A8C7DD22CE2826", /* A */ + "04A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DBC9943AB78696FA504C11", /* B */ + "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565", /* order */ + "1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E", /* Gx */ + "8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315", /* Gy */ + ecc_oid_brainpoolp384r1, ecc_oid_brainpoolp384r1_sz, /* oid/oidSz */ + ECC_BRAINPOOLP384R1_OID, /* oid sum */ + 1, /* cofactor */ + }, + #endif /* HAVE_ECC_BRAINPOOL */ +#endif /* ECC384 */ +#ifdef ECC512 + #ifdef HAVE_ECC_BRAINPOOL + { + 64, /* size/bytes */ + ECC_BRAINPOOLP512R1, /* ID */ + "BRAINPOOLP512R1", /* curve name */ + "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3", /* prime */ + "7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA", /* A */ + "3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723", /* B */ + "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069", /* order */ + "81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822", /* Gx */ + "7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892", /* Gy */ + ecc_oid_brainpoolp512r1, ecc_oid_brainpoolp512r1_sz, /* oid/oidSz */ + ECC_BRAINPOOLP512R1_OID, /* oid sum */ + 1, /* cofactor */ + }, + #endif /* HAVE_ECC_BRAINPOOL */ +#endif /* ECC512 */ +#ifdef ECC521 + #ifndef NO_ECC_SECP + { + 66, /* size/bytes */ + ECC_SECP521R1, /* ID */ + "SECP521R1", /* curve name */ + "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", /* prime */ + "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC", /* A */ + "51953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00", /* B */ + "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409", /* order */ + "C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66", /* Gx */ + "11839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650", /* Gy */ + ecc_oid_secp521r1, ecc_oid_secp521r1_sz, /* oid/oidSz */ + ECC_SECP521R1_OID, /* oid sum */ + 1, /* cofactor */ + }, + #endif /* !NO_ECC_SECP */ +#endif /* ECC521 */ +#if defined(WOLFSSL_CUSTOM_CURVES) && defined(ECC_CACHE_CURVE) + /* place holder for custom curve index for cache */ + { + 1, /* non-zero */ + ECC_CURVE_CUSTOM, + #ifndef USE_WINDOWS_API + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + #else + {0},{0},{0},{0},{0},{0},{0},{0}, + #endif + 0, 0, 0 + }, +#endif + { + 0, + ECC_CURVE_INVALID, + #ifndef USE_WINDOWS_API + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, + #else + {0},{0},{0},{0},{0},{0},{0},{0}, + #endif + 0, 0, 0 + } +}; +#define ECC_SET_COUNT (sizeof(ecc_sets)/sizeof(ecc_set_type)) + + +#ifdef HAVE_OID_ENCODING + /* encoded OID cache */ + typedef struct { + word32 oidSz; + byte oid[ECC_MAX_OID_LEN]; + } oid_cache_t; + static oid_cache_t ecc_oid_cache[ECC_SET_COUNT]; +#endif + + +#ifdef HAVE_COMP_KEY +static int wc_ecc_export_x963_compressed(ecc_key*, byte* out, word32* outLen); +#endif + + +#if (defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || !defined(WOLFSSL_SP_MATH)) && \ + !defined(WOLFSSL_ATECC508A) +static int ecc_check_pubkey_order(ecc_key* key, ecc_point* pubkey, mp_int* a, + mp_int* prime, mp_int* order); +#endif + +int mp_jacobi(mp_int* a, mp_int* n, int* c); +int mp_sqrtmod_prime(mp_int* n, mp_int* prime, mp_int* ret); + + +/* Curve Specs */ +typedef struct ecc_curve_spec { + const ecc_set_type* dp; + + mp_int* prime; + mp_int* Af; + #ifdef USE_ECC_B_PARAM + mp_int* Bf; + #endif + mp_int* order; + mp_int* Gx; + mp_int* Gy; + +#ifdef ECC_CACHE_CURVE + mp_int prime_lcl; + mp_int Af_lcl; + #ifdef USE_ECC_B_PARAM + mp_int Bf_lcl; + #endif + mp_int order_lcl; + mp_int Gx_lcl; + mp_int Gy_lcl; +#else + mp_int* spec_ints; + word32 spec_count; + word32 spec_use; +#endif + + byte load_mask; +} ecc_curve_spec; + +enum ecc_curve_load_mask { + ECC_CURVE_FIELD_NONE = 0x00, + ECC_CURVE_FIELD_PRIME = 0x01, + ECC_CURVE_FIELD_AF = 0x02, +#ifdef USE_ECC_B_PARAM + ECC_CURVE_FIELD_BF = 0x04, +#endif + ECC_CURVE_FIELD_ORDER = 0x08, + ECC_CURVE_FIELD_GX = 0x10, + ECC_CURVE_FIELD_GY = 0x20, +#ifdef USE_ECC_B_PARAM + ECC_CURVE_FIELD_ALL = 0x3F, + ECC_CURVE_FIELD_COUNT = 6, +#else + ECC_CURVE_FIELD_ALL = 0x3B, + ECC_CURVE_FIELD_COUNT = 5, +#endif +}; + +#ifdef ECC_CACHE_CURVE + /* cache (mp_int) of the curve parameters */ + static ecc_curve_spec* ecc_curve_spec_cache[ECC_SET_COUNT]; + #ifndef SINGLE_THREADED + static wolfSSL_Mutex ecc_curve_cache_mutex; + #endif + + #define DECLARE_CURVE_SPECS(curve, intcount) ecc_curve_spec* curve = NULL + #define ALLOC_CURVE_SPECS(intcount) + #define FREE_CURVE_SPECS() +#elif defined(WOLFSSL_SMALL_STACK) + #define DECLARE_CURVE_SPECS(curve, intcount) \ + mp_int* spec_ints = NULL; \ + ecc_curve_spec curve_lcl; \ + ecc_curve_spec* curve = &curve_lcl; \ + XMEMSET(curve, 0, sizeof(ecc_curve_spec)); \ + curve->spec_count = intcount + + #define ALLOC_CURVE_SPECS(intcount) \ + spec_ints = (mp_int*)XMALLOC(sizeof(mp_int) * (intcount), NULL, \ + DYNAMIC_TYPE_ECC); \ + if (spec_ints == NULL) \ + return MEMORY_E; \ + curve->spec_ints = spec_ints + #define FREE_CURVE_SPECS() \ + XFREE(spec_ints, NULL, DYNAMIC_TYPE_ECC) +#else + #define DECLARE_CURVE_SPECS(curve, intcount) \ + mp_int spec_ints[(intcount)]; \ + ecc_curve_spec curve_lcl; \ + ecc_curve_spec* curve = &curve_lcl; \ + XMEMSET(curve, 0, sizeof(ecc_curve_spec)); \ + curve->spec_ints = spec_ints; \ + curve->spec_count = intcount + #define ALLOC_CURVE_SPECS(intcount) + #define FREE_CURVE_SPECS() +#endif /* ECC_CACHE_CURVE */ + +static void _wc_ecc_curve_free(ecc_curve_spec* curve) +{ + if (curve == NULL) { + return; + } + + if (curve->load_mask & ECC_CURVE_FIELD_PRIME) + mp_clear(curve->prime); + if (curve->load_mask & ECC_CURVE_FIELD_AF) + mp_clear(curve->Af); +#ifdef USE_ECC_B_PARAM + if (curve->load_mask & ECC_CURVE_FIELD_BF) + mp_clear(curve->Bf); +#endif + if (curve->load_mask & ECC_CURVE_FIELD_ORDER) + mp_clear(curve->order); + if (curve->load_mask & ECC_CURVE_FIELD_GX) + mp_clear(curve->Gx); + if (curve->load_mask & ECC_CURVE_FIELD_GY) + mp_clear(curve->Gy); + + curve->load_mask = 0; +} + +static void wc_ecc_curve_free(ecc_curve_spec* curve) +{ + /* don't free cached curves */ +#ifndef ECC_CACHE_CURVE + _wc_ecc_curve_free(curve); +#endif + (void)curve; +} + +static int wc_ecc_curve_load_item(const char* src, mp_int** dst, + ecc_curve_spec* curve, byte mask) +{ + int err; + +#ifndef ECC_CACHE_CURVE + /* get mp_int from temp */ + if (curve->spec_use >= curve->spec_count) { + WOLFSSL_MSG("Invalid DECLARE_CURVE_SPECS count"); + return ECC_BAD_ARG_E; + } + *dst = &curve->spec_ints[curve->spec_use++]; +#endif + + err = mp_init(*dst); + if (err == MP_OKAY) { + curve->load_mask |= mask; + + err = mp_read_radix(*dst, src, MP_RADIX_HEX); + + #ifdef HAVE_WOLF_BIGINT + if (err == MP_OKAY) + err = wc_mp_to_bigint(*dst, &(*dst)->raw); + #endif + } + return err; +} + +static int wc_ecc_curve_load(const ecc_set_type* dp, ecc_curve_spec** pCurve, + byte load_mask) +{ + int ret = 0, x; + ecc_curve_spec* curve; + byte load_items = 0; /* mask of items to load */ + + if (dp == NULL || pCurve == NULL) + return BAD_FUNC_ARG; + +#ifdef ECC_CACHE_CURVE + x = wc_ecc_get_curve_idx(dp->id); + if (x == ECC_CURVE_INVALID) + return ECC_BAD_ARG_E; + +#if !defined(SINGLE_THREADED) + ret = wc_LockMutex(&ecc_curve_cache_mutex); + if (ret != 0) { + return ret; + } +#endif + + /* make sure cache has been allocated */ + if (ecc_curve_spec_cache[x] == NULL) { + ecc_curve_spec_cache[x] = (ecc_curve_spec*)XMALLOC( + sizeof(ecc_curve_spec), NULL, DYNAMIC_TYPE_ECC); + if (ecc_curve_spec_cache[x] == NULL) { + #if defined(ECC_CACHE_CURVE) && !defined(SINGLE_THREADED) + wc_UnLockMutex(&ecc_curve_cache_mutex); + #endif + return MEMORY_E; + } + XMEMSET(ecc_curve_spec_cache[x], 0, sizeof(ecc_curve_spec)); + } + + /* set curve pointer to cache */ + *pCurve = ecc_curve_spec_cache[x]; + +#endif /* ECC_CACHE_CURVE */ + curve = *pCurve; + + /* make sure the curve is initialized */ + if (curve->dp != dp) { + curve->load_mask = 0; + + #ifdef ECC_CACHE_CURVE + curve->prime = &curve->prime_lcl; + curve->Af = &curve->Af_lcl; + #ifdef USE_ECC_B_PARAM + curve->Bf = &curve->Bf_lcl; + #endif + curve->order = &curve->order_lcl; + curve->Gx = &curve->Gx_lcl; + curve->Gy = &curve->Gy_lcl; + #endif + } + curve->dp = dp; /* set dp info */ + + /* determine items to load */ + load_items = (((byte)~(word32)curve->load_mask) & load_mask); + curve->load_mask |= load_items; + + /* load items */ + x = 0; + if (load_items & ECC_CURVE_FIELD_PRIME) + x += wc_ecc_curve_load_item(dp->prime, &curve->prime, curve, + ECC_CURVE_FIELD_PRIME); + if (load_items & ECC_CURVE_FIELD_AF) + x += wc_ecc_curve_load_item(dp->Af, &curve->Af, curve, + ECC_CURVE_FIELD_AF); +#ifdef USE_ECC_B_PARAM + if (load_items & ECC_CURVE_FIELD_BF) + x += wc_ecc_curve_load_item(dp->Bf, &curve->Bf, curve, + ECC_CURVE_FIELD_BF); +#endif + if (load_items & ECC_CURVE_FIELD_ORDER) + x += wc_ecc_curve_load_item(dp->order, &curve->order, curve, + ECC_CURVE_FIELD_ORDER); + if (load_items & ECC_CURVE_FIELD_GX) + x += wc_ecc_curve_load_item(dp->Gx, &curve->Gx, curve, + ECC_CURVE_FIELD_GX); + if (load_items & ECC_CURVE_FIELD_GY) + x += wc_ecc_curve_load_item(dp->Gy, &curve->Gy, curve, + ECC_CURVE_FIELD_GY); + + /* check for error */ + if (x != 0) { + wc_ecc_curve_free(curve); + ret = MP_READ_E; + } + +#if defined(ECC_CACHE_CURVE) && !defined(SINGLE_THREADED) + wc_UnLockMutex(&ecc_curve_cache_mutex); +#endif + + return ret; +} + +#ifdef ECC_CACHE_CURVE +int wc_ecc_curve_cache_init(void) +{ + int ret = 0; +#if defined(ECC_CACHE_CURVE) && !defined(SINGLE_THREADED) + ret = wc_InitMutex(&ecc_curve_cache_mutex); +#endif + return ret; +} + +void wc_ecc_curve_cache_free(void) +{ + int x; + + /* free all ECC curve caches */ + for (x = 0; x < (int)ECC_SET_COUNT; x++) { + if (ecc_curve_spec_cache[x]) { + _wc_ecc_curve_free(ecc_curve_spec_cache[x]); + XFREE(ecc_curve_spec_cache[x], NULL, DYNAMIC_TYPE_ECC); + ecc_curve_spec_cache[x] = NULL; + } + } + +#if defined(ECC_CACHE_CURVE) && !defined(SINGLE_THREADED) + wc_FreeMutex(&ecc_curve_cache_mutex); +#endif +} +#endif /* ECC_CACHE_CURVE */ + + +/* Retrieve the curve name for the ECC curve id. + * + * curve_id The id of the curve. + * returns the name stored from the curve if available, otherwise NULL. + */ +const char* wc_ecc_get_name(int curve_id) +{ + int curve_idx = wc_ecc_get_curve_idx(curve_id); + if (curve_idx == ECC_CURVE_INVALID) + return NULL; + return ecc_sets[curve_idx].name; +} + +int wc_ecc_set_curve(ecc_key* key, int keysize, int curve_id) +{ + if (keysize <= 0 && curve_id < 0) { + return BAD_FUNC_ARG; + } + + if (keysize > ECC_MAXSIZE) { + return ECC_BAD_ARG_E; + } + + /* handle custom case */ + if (key->idx != ECC_CUSTOM_IDX) { + int x; + + /* default values */ + key->idx = 0; + key->dp = NULL; + + /* find ecc_set based on curve_id or key size */ + for (x = 0; ecc_sets[x].size != 0; x++) { + if (curve_id > ECC_CURVE_DEF) { + if (curve_id == ecc_sets[x].id) + break; + } + else if (keysize <= ecc_sets[x].size) { + break; + } + } + if (ecc_sets[x].size == 0) { + WOLFSSL_MSG("ECC Curve not found"); + return ECC_CURVE_OID_E; + } + + key->idx = x; + key->dp = &ecc_sets[x]; + } + + return 0; +} + + +#ifdef ALT_ECC_SIZE +static void alt_fp_init(mp_int* a) +{ + a->size = FP_SIZE_ECC; + mp_zero(a); +} +#endif /* ALT_ECC_SIZE */ + + +#ifndef WOLFSSL_ATECC508A + +#if !defined(WOLFSSL_SP_MATH) || defined(WOLFSSL_PUBLIC_ECC_ADD_DBL) + +/** + Add two ECC points + P The point to add + Q The point to add + R [out] The destination of the double + a ECC curve parameter a + modulus The modulus of the field the ECC curve is in + mp The "b" value from montgomery_setup() + return MP_OKAY on success +*/ +int ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R, + mp_int* a, mp_int* modulus, mp_digit mp) +{ +#ifndef WOLFSSL_SP_MATH +#ifdef WOLFSSL_SMALL_STACK + mp_int* t1 = NULL; + mp_int* t2 = NULL; +#ifdef ALT_ECC_SIZE + mp_int* rx = NULL; + mp_int* ry = NULL; + mp_int* rz = NULL; +#endif +#else + mp_int t1[1], t2[1]; +#ifdef ALT_ECC_SIZE + mp_int rx[1], ry[1], rz[1]; +#endif +#endif + mp_int *x, *y, *z; + int err; + + if (P == NULL || Q == NULL || R == NULL || modulus == NULL) { + return ECC_BAD_ARG_E; + } + + /* if Q == R then swap P and Q, so we don't require a local x,y,z */ + if (Q == R) { + ecc_point* tPt = P; + P = Q; + Q = tPt; + } + +#ifdef WOLFSSL_SMALL_STACK +#ifdef WOLFSSL_SMALL_STACK_CACHE + if (R->key != NULL) { + t1 = R->key->t1; + t2 = R->key->t2; +#ifdef ALT_ECC_SIZE + rx = R->key->x; + ry = R->key->y; + rz = R->key->z; +#endif + } + else +#endif /* WOLFSSL_SMALL_STACK_CACHE */ + { + t1 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + t2 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + if (t1 == NULL || t2 == NULL) { + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + XFREE(t2, NULL, DYNAMIC_TYPE_ECC); + return MEMORY_E; + } +#ifdef ALT_ECC_SIZE + rx = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + ry = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + rz = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + if (rx == NULL || ry == NULL || rz == NULL) { + XFREE(rz, NULL, DYNAMIC_TYPE_ECC); + XFREE(ry, NULL, DYNAMIC_TYPE_ECC); + XFREE(rx, NULL, DYNAMIC_TYPE_ECC); + XFREE(t2, NULL, DYNAMIC_TYPE_ECC); + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + return MEMORY_E; + } +#endif + } +#endif /* WOLFSSL_SMALL_STACK */ + + if ((err = mp_init_multi(t1, t2, NULL, NULL, NULL, NULL)) != MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + #ifdef WOLFSSL_SMALL_STACK_CACHE + if (R->key == NULL) + #endif + { + #ifdef ALT_ECC_SIZE + XFREE(rz, NULL, DYNAMIC_TYPE_ECC); + XFREE(ry, NULL, DYNAMIC_TYPE_ECC); + XFREE(rx, NULL, DYNAMIC_TYPE_ECC); + #endif + XFREE(t2, NULL, DYNAMIC_TYPE_ECC); + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + } +#endif + return err; + } + + /* should we dbl instead? */ + if (err == MP_OKAY) + err = mp_sub(modulus, Q->y, t1); + if (err == MP_OKAY) { + if ( (mp_cmp(P->x, Q->x) == MP_EQ) && + (get_digit_count(Q->z) && mp_cmp(P->z, Q->z) == MP_EQ) && + (mp_cmp(P->y, Q->y) == MP_EQ || mp_cmp(P->y, t1) == MP_EQ)) { + mp_clear(t1); + mp_clear(t2); + #ifdef WOLFSSL_SMALL_STACK + #ifdef WOLFSSL_SMALL_STACK_CACHE + if (R->key == NULL) + #endif + { + #ifdef ALT_ECC_SIZE + XFREE(rz, NULL, DYNAMIC_TYPE_ECC); + XFREE(ry, NULL, DYNAMIC_TYPE_ECC); + XFREE(rx, NULL, DYNAMIC_TYPE_ECC); + #endif + XFREE(t2, NULL, DYNAMIC_TYPE_ECC); + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + } + #endif + return ecc_projective_dbl_point(P, R, a, modulus, mp); + } + } + + if (err != MP_OKAY) { + goto done; + } + +/* If use ALT_ECC_SIZE we need to use local stack variable since + ecc_point x,y,z is reduced size */ +#ifdef ALT_ECC_SIZE + /* Use local stack variable */ + x = rx; + y = ry; + z = rz; + + if ((err = mp_init_multi(x, y, z, NULL, NULL, NULL)) != MP_OKAY) { + goto done; + } +#else + /* Use destination directly */ + x = R->x; + y = R->y; + z = R->z; +#endif + + if (err == MP_OKAY) + err = mp_copy(P->x, x); + if (err == MP_OKAY) + err = mp_copy(P->y, y); + if (err == MP_OKAY) + err = mp_copy(P->z, z); + + /* if Z is one then these are no-operations */ + if (err == MP_OKAY) { + if (!mp_iszero(Q->z)) { + /* T1 = Z' * Z' */ + err = mp_sqr(Q->z, t1); + if (err == MP_OKAY) + err = mp_montgomery_reduce(t1, modulus, mp); + + /* X = X * T1 */ + if (err == MP_OKAY) + err = mp_mul(t1, x, x); + if (err == MP_OKAY) + err = mp_montgomery_reduce(x, modulus, mp); + + /* T1 = Z' * T1 */ + if (err == MP_OKAY) + err = mp_mul(Q->z, t1, t1); + if (err == MP_OKAY) + err = mp_montgomery_reduce(t1, modulus, mp); + + /* Y = Y * T1 */ + if (err == MP_OKAY) + err = mp_mul(t1, y, y); + if (err == MP_OKAY) + err = mp_montgomery_reduce(y, modulus, mp); + } + } + + /* T1 = Z*Z */ + if (err == MP_OKAY) + err = mp_sqr(z, t1); + if (err == MP_OKAY) + err = mp_montgomery_reduce(t1, modulus, mp); + + /* T2 = X' * T1 */ + if (err == MP_OKAY) + err = mp_mul(Q->x, t1, t2); + if (err == MP_OKAY) + err = mp_montgomery_reduce(t2, modulus, mp); + + /* T1 = Z * T1 */ + if (err == MP_OKAY) + err = mp_mul(z, t1, t1); + if (err == MP_OKAY) + err = mp_montgomery_reduce(t1, modulus, mp); + + /* T1 = Y' * T1 */ + if (err == MP_OKAY) + err = mp_mul(Q->y, t1, t1); + if (err == MP_OKAY) + err = mp_montgomery_reduce(t1, modulus, mp); + + /* Y = Y - T1 */ + if (err == MP_OKAY) + err = mp_sub(y, t1, y); + if (err == MP_OKAY) { + if (mp_isneg(y)) + err = mp_add(y, modulus, y); + } + /* T1 = 2T1 */ + if (err == MP_OKAY) + err = mp_add(t1, t1, t1); + if (err == MP_OKAY) { + if (mp_cmp(t1, modulus) != MP_LT) + err = mp_sub(t1, modulus, t1); + } + /* T1 = Y + T1 */ + if (err == MP_OKAY) + err = mp_add(t1, y, t1); + if (err == MP_OKAY) { + if (mp_cmp(t1, modulus) != MP_LT) + err = mp_sub(t1, modulus, t1); + } + /* X = X - T2 */ + if (err == MP_OKAY) + err = mp_sub(x, t2, x); + if (err == MP_OKAY) { + if (mp_isneg(x)) + err = mp_add(x, modulus, x); + } + /* T2 = 2T2 */ + if (err == MP_OKAY) + err = mp_add(t2, t2, t2); + if (err == MP_OKAY) { + if (mp_cmp(t2, modulus) != MP_LT) + err = mp_sub(t2, modulus, t2); + } + /* T2 = X + T2 */ + if (err == MP_OKAY) + err = mp_add(t2, x, t2); + if (err == MP_OKAY) { + if (mp_cmp(t2, modulus) != MP_LT) + err = mp_sub(t2, modulus, t2); + } + + if (err == MP_OKAY) { + if (!mp_iszero(Q->z)) { + /* Z = Z * Z' */ + err = mp_mul(z, Q->z, z); + if (err == MP_OKAY) + err = mp_montgomery_reduce(z, modulus, mp); + } + } + + /* Z = Z * X */ + if (err == MP_OKAY) + err = mp_mul(z, x, z); + if (err == MP_OKAY) + err = mp_montgomery_reduce(z, modulus, mp); + + /* T1 = T1 * X */ + if (err == MP_OKAY) + err = mp_mul(t1, x, t1); + if (err == MP_OKAY) + err = mp_montgomery_reduce(t1, modulus, mp); + + /* X = X * X */ + if (err == MP_OKAY) + err = mp_sqr(x, x); + if (err == MP_OKAY) + err = mp_montgomery_reduce(x, modulus, mp); + + /* T2 = T2 * x */ + if (err == MP_OKAY) + err = mp_mul(t2, x, t2); + if (err == MP_OKAY) + err = mp_montgomery_reduce(t2, modulus, mp); + + /* T1 = T1 * X */ + if (err == MP_OKAY) + err = mp_mul(t1, x, t1); + if (err == MP_OKAY) + err = mp_montgomery_reduce(t1, modulus, mp); + + /* X = Y*Y */ + if (err == MP_OKAY) + err = mp_sqr(y, x); + if (err == MP_OKAY) + err = mp_montgomery_reduce(x, modulus, mp); + + /* X = X - T2 */ + if (err == MP_OKAY) + err = mp_sub(x, t2, x); + if (err == MP_OKAY) { + if (mp_isneg(x)) + err = mp_add(x, modulus, x); + } + /* T2 = T2 - X */ + if (err == MP_OKAY) + err = mp_sub(t2, x, t2); + if (err == MP_OKAY) { + if (mp_isneg(t2)) + err = mp_add(t2, modulus, t2); + } + /* T2 = T2 - X */ + if (err == MP_OKAY) + err = mp_sub(t2, x, t2); + if (err == MP_OKAY) { + if (mp_isneg(t2)) + err = mp_add(t2, modulus, t2); + } + /* T2 = T2 * Y */ + if (err == MP_OKAY) + err = mp_mul(t2, y, t2); + if (err == MP_OKAY) + err = mp_montgomery_reduce(t2, modulus, mp); + + /* Y = T2 - T1 */ + if (err == MP_OKAY) + err = mp_sub(t2, t1, y); + if (err == MP_OKAY) { + if (mp_isneg(y)) + err = mp_add(y, modulus, y); + } + /* Y = Y/2 */ + if (err == MP_OKAY) { + if (mp_isodd(y) == MP_YES) + err = mp_add(y, modulus, y); + } + if (err == MP_OKAY) + err = mp_div_2(y, y); + +#ifdef ALT_ECC_SIZE + if (err == MP_OKAY) + err = mp_copy(x, R->x); + if (err == MP_OKAY) + err = mp_copy(y, R->y); + if (err == MP_OKAY) + err = mp_copy(z, R->z); +#endif + +done: + + /* clean up */ + mp_clear(t1); + mp_clear(t2); +#ifdef WOLFSSL_SMALL_STACK +#ifdef WOLFSSL_SMALL_STACK_CACHE + if (R->key == NULL) +#endif + { + #ifdef ALT_ECC_SIZE + XFREE(rz, NULL, DYNAMIC_TYPE_ECC); + XFREE(ry, NULL, DYNAMIC_TYPE_ECC); + XFREE(rx, NULL, DYNAMIC_TYPE_ECC); + #endif + XFREE(t2, NULL, DYNAMIC_TYPE_ECC); + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + } +#endif + + return err; +#else + if (P == NULL || Q == NULL || R == NULL || modulus == NULL) { + return ECC_BAD_ARG_E; + } + + (void)a; + (void)mp; + + return sp_ecc_proj_add_point_256(P->x, P->y, P->z, Q->x, Q->y, Q->z, + R->x, R->y, R->z); +#endif +} + +/* ### Point doubling in Jacobian coordinate system ### + * + * let us have a curve: y^2 = x^3 + a*x + b + * in Jacobian coordinates it becomes: y^2 = x^3 + a*x*z^4 + b*z^6 + * + * The doubling of P = (Xp, Yp, Zp) is given by R = (Xr, Yr, Zr) where: + * Xr = M^2 - 2*S + * Yr = M * (S - Xr) - 8*T + * Zr = 2 * Yp * Zp + * + * M = 3 * Xp^2 + a*Zp^4 + * T = Yp^4 + * S = 4 * Xp * Yp^2 + * + * SPECIAL CASE: when a == 3 we can compute M as + * M = 3 * (Xp^2 - Zp^4) = 3 * (Xp + Zp^2) * (Xp - Zp^2) + */ + +/** + Double an ECC point + P The point to double + R [out] The destination of the double + a ECC curve parameter a + modulus The modulus of the field the ECC curve is in + mp The "b" value from montgomery_setup() + return MP_OKAY on success +*/ +int ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mp_int* a, + mp_int* modulus, mp_digit mp) +{ +#ifndef WOLFSSL_SP_MATH +#ifdef WOLFSSL_SMALL_STACK + mp_int* t1 = NULL; + mp_int* t2 = NULL; +#ifdef ALT_ECC_SIZE + mp_int* rx = NULL; + mp_int* ry = NULL; + mp_int* rz = NULL; +#endif +#else + mp_int t1[1], t2[1]; +#ifdef ALT_ECC_SIZE + mp_int rx[1], ry[1], rz[1]; +#endif +#endif + mp_int *x, *y, *z; + int err; + + if (P == NULL || R == NULL || modulus == NULL) + return ECC_BAD_ARG_E; + +#ifdef WOLFSSL_SMALL_STACK +#ifdef WOLFSSL_SMALL_STACK_CACHE + if (R->key != NULL) { + t1 = R->key->t1; + t2 = R->key->t2; + #ifdef ALT_ECC_SIZE + rx = R->key->x; + ry = R->key->y; + rz = R->key->z; + #endif + } + else +#endif /* WOLFSSL_SMALL_STACK_CACHE */ + { + t1 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + t2 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + if (t1 == NULL || t2 == NULL) { + XFREE(t2, NULL, DYNAMIC_TYPE_ECC); + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + return MEMORY_E; + } + #ifdef ALT_ECC_SIZE + rx = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + ry = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + rz = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + if (rx == NULL || ry == NULL || rz == NULL) { + XFREE(rz, NULL, DYNAMIC_TYPE_ECC); + XFREE(ry, NULL, DYNAMIC_TYPE_ECC); + XFREE(rx, NULL, DYNAMIC_TYPE_ECC); + XFREE(t2, NULL, DYNAMIC_TYPE_ECC); + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + return MEMORY_E; + } + #endif + } +#endif + + if ((err = mp_init_multi(t1, t2, NULL, NULL, NULL, NULL)) != MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK +#ifdef WOLFSSL_SMALL_STACK_CACHE + if (R->key == NULL) +#endif + { + #ifdef ALT_ECC_SIZE + XFREE(rz, NULL, DYNAMIC_TYPE_ECC); + XFREE(ry, NULL, DYNAMIC_TYPE_ECC); + XFREE(rx, NULL, DYNAMIC_TYPE_ECC); + #endif + XFREE(t2, NULL, DYNAMIC_TYPE_ECC); + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + } +#endif + return err; + } + +/* If use ALT_ECC_SIZE we need to use local stack variable since + ecc_point x,y,z is reduced size */ +#ifdef ALT_ECC_SIZE + /* Use local stack variable */ + x = rx; + y = ry; + z = rz; + + if ((err = mp_init_multi(x, y, z, NULL, NULL, NULL)) != MP_OKAY) { + mp_clear(t1); + mp_clear(t2); + #ifdef WOLFSSL_SMALL_STACK + #ifdef WOLFSSL_SMALL_STACK_CACHE + if (R->key == NULL) + #endif + { + #ifdef ALT_ECC_SIZE + XFREE(rz, NULL, DYNAMIC_TYPE_ECC); + XFREE(ry, NULL, DYNAMIC_TYPE_ECC); + XFREE(rx, NULL, DYNAMIC_TYPE_ECC); + #endif + XFREE(t2, NULL, DYNAMIC_TYPE_ECC); + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + } + #endif + return err; + } +#else + /* Use destination directly */ + x = R->x; + y = R->y; + z = R->z; +#endif + + if (err == MP_OKAY) + err = mp_copy(P->x, x); + if (err == MP_OKAY) + err = mp_copy(P->y, y); + if (err == MP_OKAY) + err = mp_copy(P->z, z); + + /* T1 = Z * Z */ + if (err == MP_OKAY) + err = mp_sqr(z, t1); + if (err == MP_OKAY) + err = mp_montgomery_reduce(t1, modulus, mp); + + /* Z = Y * Z */ + if (err == MP_OKAY) + err = mp_mul(z, y, z); + if (err == MP_OKAY) + err = mp_montgomery_reduce(z, modulus, mp); + + /* Z = 2Z */ + if (err == MP_OKAY) + err = mp_add(z, z, z); + if (err == MP_OKAY) { + if (mp_cmp(z, modulus) != MP_LT) + err = mp_sub(z, modulus, z); + } + + /* Determine if curve "a" should be used in calc */ +#ifdef WOLFSSL_CUSTOM_CURVES + if (err == MP_OKAY) { + /* Use a and prime to determine if a == 3 */ + err = mp_submod(modulus, a, modulus, t2); + } + if (err == MP_OKAY && mp_cmp_d(t2, 3) != MP_EQ) { + /* use "a" in calc */ + + /* T2 = T1 * T1 */ + if (err == MP_OKAY) + err = mp_sqr(t1, t2); + if (err == MP_OKAY) + err = mp_montgomery_reduce(t2, modulus, mp); + /* T1 = T2 * a */ + if (err == MP_OKAY) + err = mp_mulmod(t2, a, modulus, t1); + /* T2 = X * X */ + if (err == MP_OKAY) + err = mp_sqr(x, t2); + if (err == MP_OKAY) + err = mp_montgomery_reduce(t2, modulus, mp); + /* T1 = T2 + T1 */ + if (err == MP_OKAY) + err = mp_add(t1, t2, t1); + if (err == MP_OKAY) { + if (mp_cmp(t1, modulus) != MP_LT) + err = mp_sub(t1, modulus, t1); + } + /* T1 = T2 + T1 */ + if (err == MP_OKAY) + err = mp_add(t1, t2, t1); + if (err == MP_OKAY) { + if (mp_cmp(t1, modulus) != MP_LT) + err = mp_sub(t1, modulus, t1); + } + /* T1 = T2 + T1 */ + if (err == MP_OKAY) + err = mp_add(t1, t2, t1); + if (err == MP_OKAY) { + if (mp_cmp(t1, modulus) != MP_LT) + err = mp_sub(t1, modulus, t1); + } + } + else +#endif /* WOLFSSL_CUSTOM_CURVES */ + { + /* assumes "a" == 3 */ + (void)a; + + /* T2 = X - T1 */ + if (err == MP_OKAY) + err = mp_sub(x, t1, t2); + if (err == MP_OKAY) { + if (mp_isneg(t2)) + err = mp_add(t2, modulus, t2); + } + /* T1 = X + T1 */ + if (err == MP_OKAY) + err = mp_add(t1, x, t1); + if (err == MP_OKAY) { + if (mp_cmp(t1, modulus) != MP_LT) + err = mp_sub(t1, modulus, t1); + } + /* T2 = T1 * T2 */ + if (err == MP_OKAY) + err = mp_mul(t1, t2, t2); + if (err == MP_OKAY) + err = mp_montgomery_reduce(t2, modulus, mp); + + /* T1 = 2T2 */ + if (err == MP_OKAY) + err = mp_add(t2, t2, t1); + if (err == MP_OKAY) { + if (mp_cmp(t1, modulus) != MP_LT) + err = mp_sub(t1, modulus, t1); + } + /* T1 = T1 + T2 */ + if (err == MP_OKAY) + err = mp_add(t1, t2, t1); + if (err == MP_OKAY) { + if (mp_cmp(t1, modulus) != MP_LT) + err = mp_sub(t1, modulus, t1); + } + } + + /* Y = 2Y */ + if (err == MP_OKAY) + err = mp_add(y, y, y); + if (err == MP_OKAY) { + if (mp_cmp(y, modulus) != MP_LT) + err = mp_sub(y, modulus, y); + } + /* Y = Y * Y */ + if (err == MP_OKAY) + err = mp_sqr(y, y); + if (err == MP_OKAY) + err = mp_montgomery_reduce(y, modulus, mp); + + /* T2 = Y * Y */ + if (err == MP_OKAY) + err = mp_sqr(y, t2); + if (err == MP_OKAY) + err = mp_montgomery_reduce(t2, modulus, mp); + + /* T2 = T2/2 */ + if (err == MP_OKAY) { + if (mp_isodd(t2) == MP_YES) + err = mp_add(t2, modulus, t2); + } + if (err == MP_OKAY) + err = mp_div_2(t2, t2); + + /* Y = Y * X */ + if (err == MP_OKAY) + err = mp_mul(y, x, y); + if (err == MP_OKAY) + err = mp_montgomery_reduce(y, modulus, mp); + + /* X = T1 * T1 */ + if (err == MP_OKAY) + err = mp_sqr(t1, x); + if (err == MP_OKAY) + err = mp_montgomery_reduce(x, modulus, mp); + + /* X = X - Y */ + if (err == MP_OKAY) + err = mp_sub(x, y, x); + if (err == MP_OKAY) { + if (mp_isneg(x)) + err = mp_add(x, modulus, x); + } + /* X = X - Y */ + if (err == MP_OKAY) + err = mp_sub(x, y, x); + if (err == MP_OKAY) { + if (mp_isneg(x)) + err = mp_add(x, modulus, x); + } + + /* Y = Y - X */ + if (err == MP_OKAY) + err = mp_sub(y, x, y); + if (err == MP_OKAY) { + if (mp_isneg(y)) + err = mp_add(y, modulus, y); + } + /* Y = Y * T1 */ + if (err == MP_OKAY) + err = mp_mul(y, t1, y); + if (err == MP_OKAY) + err = mp_montgomery_reduce(y, modulus, mp); + + /* Y = Y - T2 */ + if (err == MP_OKAY) + err = mp_sub(y, t2, y); + if (err == MP_OKAY) { + if (mp_isneg(y)) + err = mp_add(y, modulus, y); + } + +#ifdef ALT_ECC_SIZE + if (err == MP_OKAY) + err = mp_copy(x, R->x); + if (err == MP_OKAY) + err = mp_copy(y, R->y); + if (err == MP_OKAY) + err = mp_copy(z, R->z); +#endif + + /* clean up */ + mp_clear(t1); + mp_clear(t2); + +#ifdef WOLFSSL_SMALL_STACK +#ifdef WOLFSSL_SMALL_STACK_CACHE + if (R->key == NULL) +#endif + { + #ifdef ALT_ECC_SIZE + XFREE(rz, NULL, DYNAMIC_TYPE_ECC); + XFREE(ry, NULL, DYNAMIC_TYPE_ECC); + XFREE(rx, NULL, DYNAMIC_TYPE_ECC); + #endif + XFREE(t2, NULL, DYNAMIC_TYPE_ECC); + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + } +#endif + + return err; +#else + if (P == NULL || R == NULL || modulus == NULL) + return ECC_BAD_ARG_E; + + (void)a; + (void)mp; + + return sp_ecc_proj_dbl_point_256(P->x, P->y, P->z, R->x, R->y, R->z); +#endif +} + + +/** + Map a projective jacbobian point back to affine space + P [in/out] The point to map + modulus The modulus of the field the ECC curve is in + mp The "b" value from montgomery_setup() + return MP_OKAY on success +*/ +int ecc_map(ecc_point* P, mp_int* modulus, mp_digit mp) +{ +#ifndef WOLFSSL_SP_MATH +#ifdef WOLFSSL_SMALL_STACK + mp_int* t1 = NULL; + mp_int* t2 = NULL; +#ifdef ALT_ECC_SIZE + mp_int* rx = NULL; + mp_int* ry = NULL; + mp_int* rz = NULL; +#endif +#else + mp_int t1[1], t2[1]; +#ifdef ALT_ECC_SIZE + mp_int rx[1], ry[1], rz[1]; +#endif +#endif /* WOLFSSL_SMALL_STACK */ + mp_int *x, *y, *z; + int err; + + if (P == NULL || modulus == NULL) + return ECC_BAD_ARG_E; + + /* special case for point at infinity */ + if (mp_cmp_d(P->z, 0) == MP_EQ) { + err = mp_set(P->x, 0); + if (err == MP_OKAY) + err = mp_set(P->y, 0); + if (err == MP_OKAY) + err = mp_set(P->z, 1); + return err; + } + +#ifdef WOLFSSL_SMALL_STACK +#ifdef WOLFSSL_SMALL_STACK_CACHE + if (P->key != NULL) { + t1 = P->key->t1; + t2 = P->key->t2; + #ifdef ALT_ECC_SIZE + rx = P->key->x; + ry = P->key->y; + rz = P->key->z; + #endif + } + else +#endif /* WOLFSSL_SMALL_STACK_CACHE */ + { + t1 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + t2 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + if (t1 == NULL || t2 == NULL) { + XFREE(t2, NULL, DYNAMIC_TYPE_ECC); + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + return MEMORY_E; + } +#ifdef ALT_ECC_SIZE + rx = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + ry = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + rz = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + if (rx == NULL || ry == NULL || rz == NULL) { + XFREE(rz, NULL, DYNAMIC_TYPE_ECC); + XFREE(ry, NULL, DYNAMIC_TYPE_ECC); + XFREE(rx, NULL, DYNAMIC_TYPE_ECC); + XFREE(t2, NULL, DYNAMIC_TYPE_ECC); + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + return MEMORY_E; + } +#endif + } +#endif /* WOLFSSL_SMALL_STACK */ + + if ((err = mp_init_multi(t1, t2, NULL, NULL, NULL, NULL)) != MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK +#ifdef WOLFSSL_SMALL_STACK_CACHE + if (P->key == NULL) +#endif + { + #ifdef ALT_ECC_SIZE + XFREE(rz, NULL, DYNAMIC_TYPE_ECC); + XFREE(ry, NULL, DYNAMIC_TYPE_ECC); + XFREE(rx, NULL, DYNAMIC_TYPE_ECC); + #endif + XFREE(t2, NULL, DYNAMIC_TYPE_ECC); + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + } +#endif + return MEMORY_E; + } + +#ifdef ALT_ECC_SIZE + /* Use local stack variable */ + x = rx; + y = ry; + z = rz; + + if ((err = mp_init_multi(x, y, z, NULL, NULL, NULL)) != MP_OKAY) { + goto done; + } + + if (err == MP_OKAY) + err = mp_copy(P->x, x); + if (err == MP_OKAY) + err = mp_copy(P->y, y); + if (err == MP_OKAY) + err = mp_copy(P->z, z); + + if (err != MP_OKAY) { + goto done; + } +#else + /* Use destination directly */ + x = P->x; + y = P->y; + z = P->z; +#endif + + /* first map z back to normal */ + err = mp_montgomery_reduce(z, modulus, mp); + + /* get 1/z */ + if (err == MP_OKAY) + err = mp_invmod(z, modulus, t1); + + /* get 1/z^2 and 1/z^3 */ + if (err == MP_OKAY) + err = mp_sqr(t1, t2); + if (err == MP_OKAY) + err = mp_mod(t2, modulus, t2); + if (err == MP_OKAY) + err = mp_mul(t1, t2, t1); + if (err == MP_OKAY) + err = mp_mod(t1, modulus, t1); + + /* multiply against x/y */ + if (err == MP_OKAY) + err = mp_mul(x, t2, x); + if (err == MP_OKAY) + err = mp_montgomery_reduce(x, modulus, mp); + if (err == MP_OKAY) + err = mp_mul(y, t1, y); + if (err == MP_OKAY) + err = mp_montgomery_reduce(y, modulus, mp); + + if (err == MP_OKAY) + err = mp_set(z, 1); + +#ifdef ALT_ECC_SIZE + /* return result */ + if (err == MP_OKAY) + err = mp_copy(x, P->x); + if (err == MP_OKAY) + err = mp_copy(y, P->y); + if (err == MP_OKAY) + err = mp_copy(z, P->z); + +done: +#endif + + /* clean up */ + mp_clear(t1); + mp_clear(t2); + +#ifdef WOLFSSL_SMALL_STACK +#ifdef WOLFSSL_SMALL_STACK_CACHE + if (P->key == NULL) +#endif + { + #ifdef ALT_ECC_SIZE + XFREE(rz, NULL, DYNAMIC_TYPE_ECC); + XFREE(ry, NULL, DYNAMIC_TYPE_ECC); + XFREE(rx, NULL, DYNAMIC_TYPE_ECC); + #endif + XFREE(t2, NULL, DYNAMIC_TYPE_ECC); + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + } +#endif + + return err; +#else + if (P == NULL || modulus == NULL) + return ECC_BAD_ARG_E; + + (void)mp; + + return sp_ecc_map_256(P->x, P->y, P->z); +#endif +} + +#endif /* !WOLFSSL_SP_MATH || WOLFSSL_PUBLIC_ECC_ADD_DBL */ + +#if !defined(FREESCALE_LTC_ECC) + +#if !defined(FP_ECC) || !defined(WOLFSSL_SP_MATH) +/** + Perform a point multiplication + k The scalar to multiply by + G The base point + R [out] Destination for kG + a ECC curve parameter a + modulus The modulus of the field the ECC curve is in + map Boolean whether to map back to affine or not + (1==map, 0 == leave in projective) + return MP_OKAY on success +*/ +#ifdef FP_ECC +static int normal_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, + mp_int* a, mp_int* modulus, int map, + void* heap) +#else +int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, + mp_int* a, mp_int* modulus, int map, + void* heap) +#endif +{ +#ifndef WOLFSSL_SP_MATH +#ifndef ECC_TIMING_RESISTANT + /* size of sliding window, don't change this! */ + #define WINSIZE 4 + #define M_POINTS 8 + int first = 1, bitbuf = 0, bitcpy = 0, j; +#else + #define M_POINTS 4 +#endif + + ecc_point *tG, *M[M_POINTS]; + int i, err; +#ifdef WOLFSSL_SMALL_STACK + mp_int* mu = NULL; +#ifdef WOLFSSL_SMALL_STACK_CACHE + ecc_key key; +#endif +#else + mp_int mu[1]; +#endif + mp_digit mp; + mp_digit buf; + int bitcnt = 0, mode = 0, digidx = 0; + + if (k == NULL || G == NULL || R == NULL || modulus == NULL) { + return ECC_BAD_ARG_E; + } + + /* init variables */ + tG = NULL; + XMEMSET(M, 0, sizeof(M)); +#ifdef WOLFSSL_SMALL_STACK + mu = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); + if (mu == NULL) + return MEMORY_E; +#endif +#ifdef WOLFSSL_SMALL_STACK_CACHE + key.t1 = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); + key.t2 = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); +#ifdef ALT_ECC_SIZE + key.x = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); + key.y = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); + key.z = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); +#endif + if (key.t1 == NULL || key.t2 == NULL +#ifdef ALT_ECC_SIZE + || key.x == NULL || key.y == NULL || key.z == NULL +#endif + ) { +#ifdef ALT_ECC_SIZE + XFREE(key.z, heap, DYNAMIC_TYPE_ECC); + XFREE(key.y, heap, DYNAMIC_TYPE_ECC); + XFREE(key.x, heap, DYNAMIC_TYPE_ECC); +#endif + XFREE(key.t2, heap, DYNAMIC_TYPE_ECC); + XFREE(key.t1, heap, DYNAMIC_TYPE_ECC); + XFREE(mu, heap, DYNAMIC_TYPE_ECC); + return MEMORY_E; + } +#endif /* WOLFSSL_SMALL_STACK_CACHE */ + + /* init montgomery reduction */ + if ((err = mp_montgomery_setup(modulus, &mp)) != MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK_CACHE +#ifdef ALT_ECC_SIZE + XFREE(key.z, heap, DYNAMIC_TYPE_ECC); + XFREE(key.y, heap, DYNAMIC_TYPE_ECC); + XFREE(key.x, heap, DYNAMIC_TYPE_ECC); +#endif + XFREE(key.t2, heap, DYNAMIC_TYPE_ECC); + XFREE(key.t1, heap, DYNAMIC_TYPE_ECC); +#endif /* WOLFSSL_SMALL_STACK_CACHE */ +#ifdef WOLFSSL_SMALL_STACK + XFREE(mu, heap, DYNAMIC_TYPE_ECC); +#endif + return err; + } + + if ((err = mp_init(mu)) != MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK_CACHE +#ifdef ALT_ECC_SIZE + XFREE(key.z, heap, DYNAMIC_TYPE_ECC); + XFREE(key.y, heap, DYNAMIC_TYPE_ECC); + XFREE(key.x, heap, DYNAMIC_TYPE_ECC); +#endif + XFREE(key.t2, heap, DYNAMIC_TYPE_ECC); + XFREE(key.t1, heap, DYNAMIC_TYPE_ECC); +#endif /* WOLFSSL_SMALL_STACK_CACHE */ +#ifdef WOLFSSL_SMALL_STACK + XFREE(mu, heap, DYNAMIC_TYPE_ECC); +#endif + return err; + } + if ((err = mp_montgomery_calc_normalization(mu, modulus)) != MP_OKAY) { + mp_clear(mu); +#ifdef WOLFSSL_SMALL_STACK_CACHE +#ifdef ALT_ECC_SIZE + XFREE(key.z, heap, DYNAMIC_TYPE_ECC); + XFREE(key.y, heap, DYNAMIC_TYPE_ECC); + XFREE(key.x, heap, DYNAMIC_TYPE_ECC); +#endif + XFREE(key.t2, heap, DYNAMIC_TYPE_ECC); + XFREE(key.t1, heap, DYNAMIC_TYPE_ECC); +#endif /* WOLFSSL_SMALL_STACK_CACHE */ +#ifdef WOLFSSL_SMALL_STACK + XFREE(mu, heap, DYNAMIC_TYPE_ECC); +#endif + return err; + } + + /* alloc ram for window temps */ + for (i = 0; i < M_POINTS; i++) { + M[i] = wc_ecc_new_point_h(heap); + if (M[i] == NULL) { + mp_clear(mu); + err = MEMORY_E; goto exit; + } +#ifdef WOLFSSL_SMALL_STACK_CACHE + M[i]->key = &key; +#endif + } + + /* make a copy of G in case R==G */ + tG = wc_ecc_new_point_h(heap); + if (tG == NULL) + err = MEMORY_E; + + /* tG = G and convert to montgomery */ + if (err == MP_OKAY) { + if (mp_cmp_d(mu, 1) == MP_EQ) { + err = mp_copy(G->x, tG->x); + if (err == MP_OKAY) + err = mp_copy(G->y, tG->y); + if (err == MP_OKAY) + err = mp_copy(G->z, tG->z); + } else { + err = mp_mulmod(G->x, mu, modulus, tG->x); + if (err == MP_OKAY) + err = mp_mulmod(G->y, mu, modulus, tG->y); + if (err == MP_OKAY) + err = mp_mulmod(G->z, mu, modulus, tG->z); + } + } + + /* done with mu */ + mp_clear(mu); + +#ifdef WOLFSSL_SMALL_STACK_CACHE + R->key = &key; +#endif +#ifndef ECC_TIMING_RESISTANT + + /* calc the M tab, which holds kG for k==8..15 */ + /* M[0] == 8G */ + if (err == MP_OKAY) + err = ecc_projective_dbl_point(tG, M[0], a, modulus, mp); + if (err == MP_OKAY) + err = ecc_projective_dbl_point(M[0], M[0], a, modulus, mp); + if (err == MP_OKAY) + err = ecc_projective_dbl_point(M[0], M[0], a, modulus, mp); + + /* now find (8+k)G for k=1..7 */ + if (err == MP_OKAY) + for (j = 9; j < 16; j++) { + err = ecc_projective_add_point(M[j-9], tG, M[j-M_POINTS], a, + modulus, mp); + if (err != MP_OKAY) break; + } + + /* setup sliding window */ + if (err == MP_OKAY) { + mode = 0; + bitcnt = 1; + buf = 0; + digidx = get_digit_count(k) - 1; + bitcpy = bitbuf = 0; + first = 1; + + /* perform ops */ + for (;;) { + /* grab next digit as required */ + if (--bitcnt == 0) { + if (digidx == -1) { + break; + } + buf = get_digit(k, digidx); + bitcnt = (int) DIGIT_BIT; + --digidx; + } + + /* grab the next msb from the ltiplicand */ + i = (int)(buf >> (DIGIT_BIT - 1)) & 1; + buf <<= 1; + + /* skip leading zero bits */ + if (mode == 0 && i == 0) + continue; + + /* if the bit is zero and mode == 1 then we double */ + if (mode == 1 && i == 0) { + err = ecc_projective_dbl_point(R, R, a, modulus, mp); + if (err != MP_OKAY) break; + continue; + } + + /* else we add it to the window */ + bitbuf |= (i << (WINSIZE - ++bitcpy)); + mode = 2; + + if (bitcpy == WINSIZE) { + /* if this is the first window we do a simple copy */ + if (first == 1) { + /* R = kG [k = first window] */ + err = mp_copy(M[bitbuf-M_POINTS]->x, R->x); + if (err != MP_OKAY) break; + + err = mp_copy(M[bitbuf-M_POINTS]->y, R->y); + if (err != MP_OKAY) break; + + err = mp_copy(M[bitbuf-M_POINTS]->z, R->z); + first = 0; + } else { + /* normal window */ + /* ok window is filled so double as required and add */ + /* double first */ + for (j = 0; j < WINSIZE; j++) { + err = ecc_projective_dbl_point(R, R, a, modulus, mp); + if (err != MP_OKAY) break; + } + if (err != MP_OKAY) break; /* out of first for(;;) */ + + /* then add, bitbuf will be 8..15 [8..2^WINSIZE] guaranteed */ + err = ecc_projective_add_point(R, M[bitbuf-M_POINTS], R, a, + modulus, mp); + } + if (err != MP_OKAY) break; + /* empty window and reset */ + bitcpy = bitbuf = 0; + mode = 1; + } + } + } + + /* if bits remain then double/add */ + if (err == MP_OKAY) { + if (mode == 2 && bitcpy > 0) { + /* double then add */ + for (j = 0; j < bitcpy; j++) { + /* only double if we have had at least one add first */ + if (first == 0) { + err = ecc_projective_dbl_point(R, R, a, modulus, mp); + if (err != MP_OKAY) break; + } + + bitbuf <<= 1; + if ((bitbuf & (1 << WINSIZE)) != 0) { + if (first == 1) { + /* first add, so copy */ + err = mp_copy(tG->x, R->x); + if (err != MP_OKAY) break; + + err = mp_copy(tG->y, R->y); + if (err != MP_OKAY) break; + + err = mp_copy(tG->z, R->z); + if (err != MP_OKAY) break; + first = 0; + } else { + /* then add */ + err = ecc_projective_add_point(R, tG, R, a, modulus, + mp); + if (err != MP_OKAY) break; + } + } + } + } + } + + #undef WINSIZE + +#else /* ECC_TIMING_RESISTANT */ + + /* calc the M tab */ + /* M[0] == G */ + if (err == MP_OKAY) + err = mp_copy(tG->x, M[0]->x); + if (err == MP_OKAY) + err = mp_copy(tG->y, M[0]->y); + if (err == MP_OKAY) + err = mp_copy(tG->z, M[0]->z); + + /* M[1] == 2G */ + if (err == MP_OKAY) + err = ecc_projective_dbl_point(tG, M[1], a, modulus, mp); + + /* setup sliding window */ + mode = 0; + bitcnt = 1; + buf = 0; + digidx = get_digit_count(modulus) - 1; + /* The order MAY be 1 bit longer than the modulus. */ + digidx += (modulus->dp[digidx] >> (DIGIT_BIT-1)); + + /* perform ops */ + if (err == MP_OKAY) { + for (;;) { + /* grab next digit as required */ + if (--bitcnt == 0) { + if (digidx == -1) { + break; + } + buf = get_digit(k, digidx); + bitcnt = (int)DIGIT_BIT; + --digidx; + } + + /* grab the next msb from the multiplicand */ + i = (buf >> (DIGIT_BIT - 1)) & 1; + buf <<= 1; + + if (mode == 0) { + mode = i; + /* timing resistant - dummy operations */ + if (err == MP_OKAY) + err = ecc_projective_add_point(M[1], M[2], M[2], a, modulus, + mp); +#ifdef WC_NO_CACHE_RESISTANT + if (err == MP_OKAY) + err = ecc_projective_dbl_point(M[2], M[3], a, modulus, mp); +#else + /* instead of using M[i] for double, which leaks key bit to cache + * monitor, use M[2] as temp, make sure address calc is constant, + * keep M[0] and M[1] in cache */ + if (err == MP_OKAY) + err = mp_copy((mp_int*) + ( ((wolfssl_word)M[0]->x & wc_off_on_addr[i^1]) + + ((wolfssl_word)M[1]->x & wc_off_on_addr[i])), + M[2]->x); + if (err == MP_OKAY) + err = mp_copy((mp_int*) + ( ((wolfssl_word)M[0]->y & wc_off_on_addr[i^1]) + + ((wolfssl_word)M[1]->y & wc_off_on_addr[i])), + M[2]->y); + if (err == MP_OKAY) + err = mp_copy((mp_int*) + ( ((wolfssl_word)M[0]->z & wc_off_on_addr[i^1]) + + ((wolfssl_word)M[1]->z & wc_off_on_addr[i])), + M[2]->z); + if (err == MP_OKAY) + err = ecc_projective_dbl_point(M[2], M[3], a, modulus, mp); + /* copy M[2] back to M[i] */ + if (err == MP_OKAY) + err = mp_copy(M[2]->x, + (mp_int*) + ( ((wolfssl_word)M[0]->x & wc_off_on_addr[i^1]) + + ((wolfssl_word)M[1]->x & wc_off_on_addr[i])) ); + if (err == MP_OKAY) + err = mp_copy(M[2]->y, + (mp_int*) + ( ((wolfssl_word)M[0]->y & wc_off_on_addr[i^1]) + + ((wolfssl_word)M[1]->y & wc_off_on_addr[i])) ); + if (err == MP_OKAY) + err = mp_copy(M[2]->z, + (mp_int*) + ( ((wolfssl_word)M[0]->z & wc_off_on_addr[i^1]) + + ((wolfssl_word)M[1]->z & wc_off_on_addr[i])) ); +#endif + if (err == MP_OKAY) + continue; + } + + if (err == MP_OKAY) + err = ecc_projective_add_point(M[0], M[1], M[i^1], a, modulus, + mp); +#ifdef WC_NO_CACHE_RESISTANT + if (err == MP_OKAY) + err = ecc_projective_dbl_point(M[i], M[i], a, modulus, mp); +#else + /* instead of using M[i] for double, which leaks key bit to cache + * monitor, use M[2] as temp, make sure address calc is constant, + * keep M[0] and M[1] in cache */ + if (err == MP_OKAY) + err = mp_copy((mp_int*) + ( ((wolfssl_word)M[0]->x & wc_off_on_addr[i^1]) + + ((wolfssl_word)M[1]->x & wc_off_on_addr[i])), + M[2]->x); + if (err == MP_OKAY) + err = mp_copy((mp_int*) + ( ((wolfssl_word)M[0]->y & wc_off_on_addr[i^1]) + + ((wolfssl_word)M[1]->y & wc_off_on_addr[i])), + M[2]->y); + if (err == MP_OKAY) + err = mp_copy((mp_int*) + ( ((wolfssl_word)M[0]->z & wc_off_on_addr[i^1]) + + ((wolfssl_word)M[1]->z & wc_off_on_addr[i])), + M[2]->z); + if (err == MP_OKAY) + err = ecc_projective_dbl_point(M[2], M[2], a, modulus, mp); + /* copy M[2] back to M[i] */ + if (err == MP_OKAY) + err = mp_copy(M[2]->x, + (mp_int*) + ( ((wolfssl_word)M[0]->x & wc_off_on_addr[i^1]) + + ((wolfssl_word)M[1]->x & wc_off_on_addr[i])) ); + if (err == MP_OKAY) + err = mp_copy(M[2]->y, + (mp_int*) + ( ((wolfssl_word)M[0]->y & wc_off_on_addr[i^1]) + + ((wolfssl_word)M[1]->y & wc_off_on_addr[i])) ); + if (err == MP_OKAY) + err = mp_copy(M[2]->z, + (mp_int*) + ( ((wolfssl_word)M[0]->z & wc_off_on_addr[i^1]) + + ((wolfssl_word)M[1]->z & wc_off_on_addr[i])) ); + if (err != MP_OKAY) + break; +#endif /* WC_NO_CACHE_RESISTANT */ + } /* end for */ + } + + /* copy result out */ + if (err == MP_OKAY) + err = mp_copy(M[0]->x, R->x); + if (err == MP_OKAY) + err = mp_copy(M[0]->y, R->y); + if (err == MP_OKAY) + err = mp_copy(M[0]->z, R->z); + +#endif /* ECC_TIMING_RESISTANT */ + + /* map R back from projective space */ + if (err == MP_OKAY && map) + err = ecc_map(R, modulus, mp); + +exit: + + /* done */ + wc_ecc_del_point_h(tG, heap); + for (i = 0; i < M_POINTS; i++) { + wc_ecc_del_point_h(M[i], heap); + } +#ifdef WOLFSSL_SMALL_STACK_CACHE + R->key = NULL; +#ifdef ALT_ECC_SIZE + XFREE(key.z, heap, DYNAMIC_TYPE_ECC); + XFREE(key.y, heap, DYNAMIC_TYPE_ECC); + XFREE(key.x, heap, DYNAMIC_TYPE_ECC); +#endif + XFREE(key.t2, heap, DYNAMIC_TYPE_ECC); + XFREE(key.t1, heap, DYNAMIC_TYPE_ECC); +#endif /* WOLFSSL_SMALL_STACK_CACHE */ +#ifdef WOLFSSL_SMALL_STACK + XFREE(mu, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +#else + if (k == NULL || G == NULL || R == NULL || modulus == NULL) { + return ECC_BAD_ARG_E; + } + + (void)a; + + return sp_ecc_mulmod_256(k, G, R, map, heap); +#endif +} + +#endif /* !FP_ECC || !WOLFSSL_SP_MATH */ + +#endif /* !FREESCALE_LTC_ECC */ + +/** ECC Fixed Point mulmod global + k The multiplicand + G Base point to multiply + R [out] Destination of product + a ECC curve parameter a + modulus The modulus for the curve + map [boolean] If non-zero maps the point back to affine co-ordinates, + otherwise it's left in jacobian-montgomery form + return MP_OKAY if successful +*/ +int wc_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, + mp_int* modulus, int map) +{ + return wc_ecc_mulmod_ex(k, G, R, a, modulus, map, NULL); +} + +#endif /* !WOLFSSL_ATECC508A */ + +/** + * use a heap hint when creating new ecc_point + * return an allocated point on success or NULL on failure + */ +ecc_point* wc_ecc_new_point_h(void* heap) +{ + ecc_point* p; + + (void)heap; + + p = (ecc_point*)XMALLOC(sizeof(ecc_point), heap, DYNAMIC_TYPE_ECC); + if (p == NULL) { + return NULL; + } + XMEMSET(p, 0, sizeof(ecc_point)); + +#ifndef ALT_ECC_SIZE + if (mp_init_multi(p->x, p->y, p->z, NULL, NULL, NULL) != MP_OKAY) { + XFREE(p, heap, DYNAMIC_TYPE_ECC); + return NULL; + } +#else + p->x = (mp_int*)&p->xyz[0]; + p->y = (mp_int*)&p->xyz[1]; + p->z = (mp_int*)&p->xyz[2]; + alt_fp_init(p->x); + alt_fp_init(p->y); + alt_fp_init(p->z); +#endif + + return p; +} + + +/** + Allocate a new ECC point + return A newly allocated point or NULL on error +*/ +ecc_point* wc_ecc_new_point(void) +{ + return wc_ecc_new_point_h(NULL); +} + + +void wc_ecc_del_point_h(ecc_point* p, void* heap) +{ + /* prevents free'ing null arguments */ + if (p != NULL) { + mp_clear(p->x); + mp_clear(p->y); + mp_clear(p->z); + XFREE(p, heap, DYNAMIC_TYPE_ECC); + } + (void)heap; +} + + +/** Free an ECC point from memory + p The point to free +*/ +void wc_ecc_del_point(ecc_point* p) +{ + wc_ecc_del_point_h(p, NULL); +} + + +/** Copy the value of a point to an other one + p The point to copy + r The created point +*/ +int wc_ecc_copy_point(ecc_point* p, ecc_point *r) +{ + int ret; + + /* prevents null arguments */ + if (p == NULL || r == NULL) + return ECC_BAD_ARG_E; + + ret = mp_copy(p->x, r->x); + if (ret != MP_OKAY) + return ret; + ret = mp_copy(p->y, r->y); + if (ret != MP_OKAY) + return ret; + ret = mp_copy(p->z, r->z); + if (ret != MP_OKAY) + return ret; + + return MP_OKAY; +} + +/** Compare the value of a point with an other one + a The point to compare + b The other point to compare + + return MP_EQ if equal, MP_LT/MP_GT if not, < 0 in case of error + */ +int wc_ecc_cmp_point(ecc_point* a, ecc_point *b) +{ + int ret; + + /* prevents null arguments */ + if (a == NULL || b == NULL) + return BAD_FUNC_ARG; + + ret = mp_cmp(a->x, b->x); + if (ret != MP_EQ) + return ret; + ret = mp_cmp(a->y, b->y); + if (ret != MP_EQ) + return ret; + ret = mp_cmp(a->z, b->z); + if (ret != MP_EQ) + return ret; + + return MP_EQ; +} + + +/** Returns whether an ECC idx is valid or not + n The idx number to check + return 1 if valid, 0 if not +*/ +int wc_ecc_is_valid_idx(int n) +{ + int x; + + for (x = 0; ecc_sets[x].size != 0; x++) + ; + /* -1 is a valid index --- indicating that the domain params + were supplied by the user */ + if ((n >= ECC_CUSTOM_IDX) && (n < x)) { + return 1; + } + + return 0; +} + +int wc_ecc_get_curve_idx(int curve_id) +{ + int curve_idx; + for (curve_idx = 0; ecc_sets[curve_idx].size != 0; curve_idx++) { + if (curve_id == ecc_sets[curve_idx].id) + break; + } + if (ecc_sets[curve_idx].size == 0) { + return ECC_CURVE_INVALID; + } + return curve_idx; +} + +int wc_ecc_get_curve_id(int curve_idx) +{ + if (wc_ecc_is_valid_idx(curve_idx)) { + return ecc_sets[curve_idx].id; + } + return ECC_CURVE_INVALID; +} + +/* Returns the curve size that corresponds to a given ecc_curve_id identifier + * + * id curve id, from ecc_curve_id enum in ecc.h + * return curve size, from ecc_sets[] on success, negative on error + */ +int wc_ecc_get_curve_size_from_id(int curve_id) +{ + int curve_idx = wc_ecc_get_curve_idx(curve_id); + if (curve_idx == ECC_CURVE_INVALID) + return ECC_BAD_ARG_E; + return ecc_sets[curve_idx].size; +} + +/* Returns the curve index that corresponds to a given curve name in + * ecc_sets[] of ecc.c + * + * name curve name, from ecc_sets[].name in ecc.c + * return curve index in ecc_sets[] on success, negative on error + */ +int wc_ecc_get_curve_idx_from_name(const char* curveName) +{ + int curve_idx; + word32 len; + + if (curveName == NULL) + return BAD_FUNC_ARG; + + len = (word32)XSTRLEN(curveName); + + for (curve_idx = 0; ecc_sets[curve_idx].size != 0; curve_idx++) { + if (ecc_sets[curve_idx].name && + XSTRNCASECMP(ecc_sets[curve_idx].name, curveName, len) == 0) { + break; + } + } + if (ecc_sets[curve_idx].size == 0) { + WOLFSSL_MSG("ecc_set curve name not found"); + return ECC_CURVE_INVALID; + } + return curve_idx; +} + +/* Returns the curve size that corresponds to a given curve name, + * as listed in ecc_sets[] of ecc.c. + * + * name curve name, from ecc_sets[].name in ecc.c + * return curve size, from ecc_sets[] on success, negative on error + */ +int wc_ecc_get_curve_size_from_name(const char* curveName) +{ + int curve_idx; + + if (curveName == NULL) + return BAD_FUNC_ARG; + + curve_idx = wc_ecc_get_curve_idx_from_name(curveName); + if (curve_idx < 0) + return curve_idx; + + return ecc_sets[curve_idx].size; +} + +/* Returns the curve id that corresponds to a given curve name, + * as listed in ecc_sets[] of ecc.c. + * + * name curve name, from ecc_sets[].name in ecc.c + * return curve id, from ecc_sets[] on success, negative on error + */ +int wc_ecc_get_curve_id_from_name(const char* curveName) +{ + int curve_idx; + + if (curveName == NULL) + return BAD_FUNC_ARG; + + curve_idx = wc_ecc_get_curve_idx_from_name(curveName); + if (curve_idx < 0) + return curve_idx; + + return ecc_sets[curve_idx].id; +} + +/* Compares a curve parameter (hex, from ecc_sets[]) to given input + * parameter for equality. + * encType is WC_TYPE_UNSIGNED_BIN or WC_TYPE_HEX_STR + * Returns MP_EQ on success, negative on error */ +static int wc_ecc_cmp_param(const char* curveParam, + const byte* param, word32 paramSz, int encType) +{ + int err = MP_OKAY; +#ifdef WOLFSSL_SMALL_STACK + mp_int* a = NULL; + mp_int* b = NULL; +#else + mp_int a[1], b[1]; +#endif + + if (param == NULL || curveParam == NULL) + return BAD_FUNC_ARG; + + if (encType == WC_TYPE_HEX_STR) + return XSTRNCMP(curveParam, (char*) param, paramSz); + +#ifdef WOLFSSL_SMALL_STACK + a = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + if (a == NULL) + return MEMORY_E; + b = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + if (b == NULL) { + XFREE(a, NULL, DYNAMIC_TYPE_ECC); + return MEMORY_E; + } +#endif + + if ((err = mp_init_multi(a, b, NULL, NULL, NULL, NULL)) != MP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(a, NULL, DYNAMIC_TYPE_ECC); + XFREE(b, NULL, DYNAMIC_TYPE_ECC); + #endif + return err; + } + + if (err == MP_OKAY) { + err = mp_read_unsigned_bin(a, param, paramSz); + } + if (err == MP_OKAY) + err = mp_read_radix(b, curveParam, MP_RADIX_HEX); + + if (err == MP_OKAY) { + if (mp_cmp(a, b) != MP_EQ) { + err = -1; + } else { + err = MP_EQ; + } + } + + mp_clear(a); + mp_clear(b); +#ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_ECC); + XFREE(a, NULL, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Returns the curve id in ecc_sets[] that corresponds to a given set of + * curve parameters. + * + * fieldSize the field size in bits + * prime prime of the finite field + * primeSz size of prime in octets + * Af first coefficient a of the curve + * AfSz size of Af in octets + * Bf second coefficient b of the curve + * BfSz size of Bf in octets + * order curve order + * orderSz size of curve in octets + * Gx affine x coordinate of base point + * GxSz size of Gx in octets + * Gy affine y coordinate of base point + * GySz size of Gy in octets + * cofactor curve cofactor + * + * return curve id, from ecc_sets[] on success, negative on error + */ +int wc_ecc_get_curve_id_from_params(int fieldSize, + const byte* prime, word32 primeSz, const byte* Af, word32 AfSz, + const byte* Bf, word32 BfSz, const byte* order, word32 orderSz, + const byte* Gx, word32 GxSz, const byte* Gy, word32 GySz, int cofactor) +{ + int idx; + int curveSz; + + if (prime == NULL || Af == NULL || Bf == NULL || order == NULL || + Gx == NULL || Gy == NULL) + return BAD_FUNC_ARG; + + curveSz = (fieldSize + 1) / 8; /* round up */ + + for (idx = 0; ecc_sets[idx].size != 0; idx++) { + if (curveSz == ecc_sets[idx].size) { + if ((wc_ecc_cmp_param(ecc_sets[idx].prime, prime, + primeSz, WC_TYPE_UNSIGNED_BIN) == MP_EQ) && + (wc_ecc_cmp_param(ecc_sets[idx].Af, Af, AfSz, + WC_TYPE_UNSIGNED_BIN) == MP_EQ) && + (wc_ecc_cmp_param(ecc_sets[idx].Bf, Bf, BfSz, + WC_TYPE_UNSIGNED_BIN) == MP_EQ) && + (wc_ecc_cmp_param(ecc_sets[idx].order, order, + orderSz, WC_TYPE_UNSIGNED_BIN) == MP_EQ) && + (wc_ecc_cmp_param(ecc_sets[idx].Gx, Gx, GxSz, + WC_TYPE_UNSIGNED_BIN) == MP_EQ) && + (wc_ecc_cmp_param(ecc_sets[idx].Gy, Gy, GySz, + WC_TYPE_UNSIGNED_BIN) == MP_EQ) && + (cofactor == ecc_sets[idx].cofactor)) { + break; + } + } + } + + if (ecc_sets[idx].size == 0) + return ECC_CURVE_INVALID; + + return ecc_sets[idx].id; +} + +/* Returns the curve id in ecc_sets[] that corresponds + * to a given domain parameters pointer. + * + * dp domain parameters pointer + * + * return curve id, from ecc_sets[] on success, negative on error + */ +int wc_ecc_get_curve_id_from_dp_params(const ecc_set_type* dp) +{ + int idx; + + if (dp == NULL || dp->prime == NULL || dp->Af == NULL || + dp->Bf == NULL || dp->order == NULL || dp->Gx == NULL || dp->Gy == NULL) + return BAD_FUNC_ARG; + + for (idx = 0; ecc_sets[idx].size != 0; idx++) { + if (dp->size == ecc_sets[idx].size) { + if ((wc_ecc_cmp_param(ecc_sets[idx].prime, (const byte*)dp->prime, + (word32)XSTRLEN(dp->prime), WC_TYPE_HEX_STR) == MP_EQ) && + (wc_ecc_cmp_param(ecc_sets[idx].Af, (const byte*)dp->Af, + (word32)XSTRLEN(dp->Af),WC_TYPE_HEX_STR) == MP_EQ) && + (wc_ecc_cmp_param(ecc_sets[idx].Bf, (const byte*)dp->Bf, + (word32)XSTRLEN(dp->Bf),WC_TYPE_HEX_STR) == MP_EQ) && + (wc_ecc_cmp_param(ecc_sets[idx].order, (const byte*)dp->order, + (word32)XSTRLEN(dp->order),WC_TYPE_HEX_STR) == MP_EQ) && + (wc_ecc_cmp_param(ecc_sets[idx].Gx, (const byte*)dp->Gx, + (word32)XSTRLEN(dp->Gx),WC_TYPE_HEX_STR) == MP_EQ) && + (wc_ecc_cmp_param(ecc_sets[idx].Gy, (const byte*)dp->Gy, + (word32)XSTRLEN(dp->Gy),WC_TYPE_HEX_STR) == MP_EQ) && + (dp->cofactor == ecc_sets[idx].cofactor)) { + break; + } + } + } + + if (ecc_sets[idx].size == 0) + return ECC_CURVE_INVALID; + + return ecc_sets[idx].id; +} + +/* Returns the curve id that corresponds to a given OID, + * as listed in ecc_sets[] of ecc.c. + * + * oid OID, from ecc_sets[].name in ecc.c + * len OID len, from ecc_sets[].name in ecc.c + * return curve id, from ecc_sets[] on success, negative on error + */ +int wc_ecc_get_curve_id_from_oid(const byte* oid, word32 len) +{ + int curve_idx; + + if (oid == NULL) + return BAD_FUNC_ARG; + + for (curve_idx = 0; ecc_sets[curve_idx].size != 0; curve_idx++) { + if (ecc_sets[curve_idx].oid && ecc_sets[curve_idx].oidSz == len && + XMEMCMP(ecc_sets[curve_idx].oid, oid, len) == 0) { + break; + } + } + if (ecc_sets[curve_idx].size == 0) { + WOLFSSL_MSG("ecc_set curve name not found"); + return ECC_CURVE_INVALID; + } + + return ecc_sets[curve_idx].id; +} + + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) +static WC_INLINE int wc_ecc_alloc_mpint(ecc_key* key, mp_int** mp) +{ + if (key == NULL || mp == NULL) + return BAD_FUNC_ARG; + if (*mp == NULL) { + *mp = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_BIGINT); + if (*mp == NULL) { + return MEMORY_E; + } + XMEMSET(*mp, 0, sizeof(mp_int)); + } + return 0; +} +static WC_INLINE void wc_ecc_free_mpint(ecc_key* key, mp_int** mp) +{ + if (key && mp && *mp) { + mp_clear(*mp); + XFREE(*mp, key->heap, DYNAMIC_TYPE_BIGINT); + *mp = NULL; + } +} + +static int wc_ecc_alloc_async(ecc_key* key) +{ + int err = wc_ecc_alloc_mpint(key, &key->r); + if (err == 0) + err = wc_ecc_alloc_mpint(key, &key->s); + return err; +} + +static void wc_ecc_free_async(ecc_key* key) +{ + wc_ecc_free_mpint(key, &key->r); + wc_ecc_free_mpint(key, &key->s); +#ifdef HAVE_CAVIUM_V + wc_ecc_free_mpint(key, &key->e); + wc_ecc_free_mpint(key, &key->signK); +#endif /* HAVE_CAVIUM_V */ +} +#endif /* WOLFSSL_ASYNC_CRYPT && WC_ASYNC_ENABLE_ECC */ + + +#ifdef HAVE_ECC_DHE +/** + Create an ECC shared secret between two keys + private_key The private ECC key (heap hint based off of private key) + public_key The public key + out [out] Destination of the shared secret + Conforms to EC-DH from ANSI X9.63 + outlen [in/out] The max size and resulting size of the shared secret + return MP_OKAY if successful +*/ +int wc_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, byte* out, + word32* outlen) +{ + int err; +#if defined(WOLFSSL_CRYPTOCELL) + CRYS_ECDH_TempData_t tempBuff; +#endif + if (private_key == NULL || public_key == NULL || out == NULL || + outlen == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef WOLF_CRYPTO_CB + if (private_key->devId != INVALID_DEVID) { + err = wc_CryptoCb_Ecdh(private_key, public_key, out, outlen); + if (err != CRYPTOCB_UNAVAILABLE) + return err; + /* fall-through when unavailable */ + } +#endif + + /* type valid? */ + if (private_key->type != ECC_PRIVATEKEY && + private_key->type != ECC_PRIVATEKEY_ONLY) { + return ECC_BAD_ARG_E; + } + + /* Verify domain params supplied */ + if (wc_ecc_is_valid_idx(private_key->idx) == 0 || + wc_ecc_is_valid_idx(public_key->idx) == 0) { + return ECC_BAD_ARG_E; + } + + /* Verify curve id matches */ + if (private_key->dp->id != public_key->dp->id) { + return ECC_BAD_ARG_E; + } + +#ifdef WOLFSSL_ATECC508A + /* For SECP256R1 use hardware */ + if (private_key->dp->id == ECC_SECP256R1) { + err = atmel_ecc_create_pms(private_key->slot, public_key->pubkey_raw, out); + *outlen = private_key->dp->size; + } + else { + err = NOT_COMPILED_IN; + } +#elif defined(WOLFSSL_CRYPTOCELL) + + /* generate a secret*/ + err = CRYS_ECDH_SVDP_DH(&public_key->ctx.pubKey, + &private_key->ctx.privKey, + out, + outlen, + &tempBuff); + + if (err != SA_SILIB_RET_OK){ + WOLFSSL_MSG("CRYS_ECDH_SVDP_DH for secret failed"); + return err; + } + +#else + err = wc_ecc_shared_secret_ex(private_key, &public_key->pubkey, out, outlen); +#endif /* WOLFSSL_ATECC508A */ + + return err; +} + + +#if !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_CRYPTOCELL) + +static int wc_ecc_shared_secret_gen_sync(ecc_key* private_key, ecc_point* point, + byte* out, word32* outlen, ecc_curve_spec* curve) +{ + int err; +#ifndef WOLFSSL_SP_MATH + ecc_point* result = NULL; + word32 x = 0; +#endif + mp_int* k = &private_key->k; +#ifdef HAVE_ECC_CDH + mp_int k_lcl; + + /* if cofactor flag has been set */ + if (private_key->flags & WC_ECC_FLAG_COFACTOR) { + mp_digit cofactor = (mp_digit)private_key->dp->cofactor; + /* only perform cofactor calc if not equal to 1 */ + if (cofactor != 1) { + k = &k_lcl; + if (mp_init(k) != MP_OKAY) + return MEMORY_E; + /* multiply cofactor times private key "k" */ + err = mp_mul_d(&private_key->k, cofactor, k); + if (err != MP_OKAY) { + mp_clear(k); + return err; + } + } + } +#endif + +#ifdef WOLFSSL_HAVE_SP_ECC +#ifndef WOLFSSL_SP_NO_256 + if (private_key->idx != ECC_CUSTOM_IDX && + ecc_sets[private_key->idx].id == ECC_SECP256R1) { + err = sp_ecc_secret_gen_256(k, point, out, outlen, private_key->heap); + } + else +#endif +#endif +#ifdef WOLFSSL_SP_MATH + { + err = WC_KEY_SIZE_E; + + (void)curve; + } +#else + { + /* make new point */ + result = wc_ecc_new_point_h(private_key->heap); + if (result == NULL) { +#ifdef HAVE_ECC_CDH + if (k == &k_lcl) + mp_clear(k); +#endif + return MEMORY_E; + } + + err = wc_ecc_mulmod_ex(k, point, result, curve->Af, curve->prime, 1, + private_key->heap); + if (err == MP_OKAY) { + x = mp_unsigned_bin_size(curve->prime); + if (*outlen < x) { + err = BUFFER_E; + } + } + + if (err == MP_OKAY) { + XMEMSET(out, 0, x); + err = mp_to_unsigned_bin(result->x,out + + (x - mp_unsigned_bin_size(result->x))); + } + *outlen = x; + + wc_ecc_del_point_h(result, private_key->heap); + } +#endif +#ifdef HAVE_ECC_CDH + if (k == &k_lcl) + mp_clear(k); +#endif + + return err; +} + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) +static int wc_ecc_shared_secret_gen_async(ecc_key* private_key, + ecc_point* point, byte* out, word32 *outlen, + ecc_curve_spec* curve) +{ + int err; + +#if defined(HAVE_CAVIUM_V) || defined(HAVE_INTEL_QA) +#ifdef HAVE_CAVIUM_V + /* verify the curve is supported by hardware */ + if (NitroxEccIsCurveSupported(private_key)) +#endif + { + word32 keySz = private_key->dp->size; + + /* sync public key x/y */ + err = wc_mp_to_bigint_sz(&private_key->k, &private_key->k.raw, keySz); + if (err == MP_OKAY) + err = wc_mp_to_bigint_sz(point->x, &point->x->raw, keySz); + if (err == MP_OKAY) + err = wc_mp_to_bigint_sz(point->y, &point->y->raw, keySz); + #ifdef HAVE_CAVIUM_V + /* allocate buffer for output */ + if (err == MP_OKAY) + err = wc_ecc_alloc_mpint(private_key, &private_key->e); + if (err == MP_OKAY) + err = wc_bigint_alloc(&private_key->e->raw, + NitroxEccGetSize(private_key)*2); + if (err == MP_OKAY) + err = NitroxEcdh(private_key, + &private_key->k.raw, &point->x->raw, &point->y->raw, + private_key->e->raw.buf, &private_key->e->raw.len, + &curve->prime->raw); + #else + if (err == MP_OKAY) + err = wc_ecc_curve_load(private_key->dp, &curve, ECC_CURVE_FIELD_BF); + if (err == MP_OKAY) + err = IntelQaEcdh(&private_key->asyncDev, + &private_key->k.raw, &point->x->raw, &point->y->raw, + out, outlen, + &curve->Af->raw, &curve->Bf->raw, &curve->prime->raw, + private_key->dp->cofactor); + #endif + return err; + } +#elif defined(WOLFSSL_ASYNC_CRYPT_TEST) + if (wc_AsyncTestInit(&private_key->asyncDev, ASYNC_TEST_ECC_SHARED_SEC)) { + WC_ASYNC_TEST* testDev = &private_key->asyncDev.test; + testDev->eccSharedSec.private_key = private_key; + testDev->eccSharedSec.public_point = point; + testDev->eccSharedSec.out = out; + testDev->eccSharedSec.outLen = outlen; + return WC_PENDING_E; + } +#endif + + /* use sync in other cases */ + err = wc_ecc_shared_secret_gen_sync(private_key, point, out, outlen, curve); + + return err; +} +#endif /* WOLFSSL_ASYNC_CRYPT && WC_ASYNC_ENABLE_ECC */ + +int wc_ecc_shared_secret_gen(ecc_key* private_key, ecc_point* point, + byte* out, word32 *outlen) +{ + int err; + DECLARE_CURVE_SPECS(curve, 2); + + if (private_key == NULL || point == NULL || out == NULL || + outlen == NULL) { + return BAD_FUNC_ARG; + } + + ALLOC_CURVE_SPECS(2); + + /* load curve info */ + err = wc_ecc_curve_load(private_key->dp, &curve, + (ECC_CURVE_FIELD_PRIME | ECC_CURVE_FIELD_AF)); + if (err != MP_OKAY) { + FREE_CURVE_SPECS(); + return err; + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + if (private_key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { + err = wc_ecc_shared_secret_gen_async(private_key, point, + out, outlen, curve); + } + else +#endif + { + err = wc_ecc_shared_secret_gen_sync(private_key, point, + out, outlen, curve); + } + + wc_ecc_curve_free(curve); + FREE_CURVE_SPECS(); + + return err; +} + +/** + Create an ECC shared secret between private key and public point + private_key The private ECC key (heap hint based on private key) + point The point to use (public key) + out [out] Destination of the shared secret + Conforms to EC-DH from ANSI X9.63 + outlen [in/out] The max size and resulting size of the shared secret + return MP_OKAY if successful +*/ +int wc_ecc_shared_secret_ex(ecc_key* private_key, ecc_point* point, + byte* out, word32 *outlen) +{ + int err; + + if (private_key == NULL || point == NULL || out == NULL || + outlen == NULL) { + return BAD_FUNC_ARG; + } + + /* type valid? */ + if (private_key->type != ECC_PRIVATEKEY && + private_key->type != ECC_PRIVATEKEY_ONLY) { + return ECC_BAD_ARG_E; + } + + /* Verify domain params supplied */ + if (wc_ecc_is_valid_idx(private_key->idx) == 0) + return ECC_BAD_ARG_E; + + switch(private_key->state) { + case ECC_STATE_NONE: + case ECC_STATE_SHARED_SEC_GEN: + private_key->state = ECC_STATE_SHARED_SEC_GEN; + + err = wc_ecc_shared_secret_gen(private_key, point, out, outlen); + if (err < 0) { + break; + } + FALL_THROUGH; + + case ECC_STATE_SHARED_SEC_RES: + private_key->state = ECC_STATE_SHARED_SEC_RES; + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + if (private_key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { + #ifdef HAVE_CAVIUM_V + /* verify the curve is supported by hardware */ + if (NitroxEccIsCurveSupported(private_key)) { + /* copy output */ + *outlen = private_key->dp->size; + XMEMCPY(out, private_key->e->raw.buf, *outlen); + } + #endif /* HAVE_CAVIUM_V */ + } + #endif /* WOLFSSL_ASYNC_CRYPT */ + err = 0; + break; + + default: + err = BAD_STATE_E; + } /* switch */ + + /* if async pending then return and skip done cleanup below */ + if (err == WC_PENDING_E) { + private_key->state++; + return err; + } + + /* cleanup */ +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + wc_ecc_free_async(private_key); +#endif + private_key->state = ECC_STATE_NONE; + + return err; +} +#endif /* !WOLFSSL_ATECC508A && !WOLFSSL_CRYPTOCELL */ +#endif /* HAVE_ECC_DHE */ + + +#if !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_CRYPTOCELL) +/* return 1 if point is at infinity, 0 if not, < 0 on error */ +int wc_ecc_point_is_at_infinity(ecc_point* p) +{ + if (p == NULL) + return BAD_FUNC_ARG; + + if (get_digit_count(p->x) == 0 && get_digit_count(p->y) == 0) + return 1; + + return 0; +} + +#ifndef WOLFSSL_SP_MATH +/* generate random and ensure its greater than 0 and less than order */ +static int wc_ecc_gen_k(WC_RNG* rng, int size, mp_int* k, mp_int* order) +{ +#ifndef WC_NO_RNG + int err; +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + DECLARE_VAR(buf, byte, ECC_MAXSIZE_GEN, rng->heap); +#else + byte buf[ECC_MAXSIZE_GEN]; +#endif + + /*generate 8 extra bytes to mitigate bias from the modulo operation below*/ + /*see section A.1.2 in 'Suite B Implementor's Guide to FIPS 186-3 (ECDSA)'*/ + size += 8; + + /* make up random string */ + err = wc_RNG_GenerateBlock(rng, buf, size); + + /* load random buffer data into k */ + if (err == 0) + err = mp_read_unsigned_bin(k, (byte*)buf, size); + + /* the key should be smaller than the order of base point */ + if (err == MP_OKAY) { + if (mp_cmp(k, order) != MP_LT) { + err = mp_mod(k, order, k); + } + } + + /* quick sanity check to make sure we're not dealing with a 0 key */ + if (err == MP_OKAY) { + if (mp_iszero(k) == MP_YES) + err = MP_ZERO_E; + } + + ForceZero(buf, ECC_MAXSIZE); +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + FREE_VAR(buf, rng->heap); +#endif + + return err; +#else + (void)rng; + (void)size; + (void)k; + (void)order; + return NOT_COMPILED_IN; +#endif /* !WC_NO_RNG */ +} +#endif /* WOLFSSL_SP_MATH */ +#endif /* !WOLFSSL_ATECC508A && !WOLFSSL_CRYPTOCELL */ + +static WC_INLINE void wc_ecc_reset(ecc_key* key) +{ + /* make sure required key variables are reset */ + key->state = ECC_STATE_NONE; +} + + +/* create the public ECC key from a private key + * + * key an initialized private key to generate public part from + * curveIn [in]curve for key, can be NULL + * pubOut [out]ecc_point holding the public key, if NULL then public key part + * is cached in key instead. + * + * Note this function is local to the file because of the argument type + * ecc_curve_spec. Having this argument allows for not having to load the + * curve type multiple times when generating a key with wc_ecc_make_key(). + * + * returns MP_OKAY on success + */ +static int wc_ecc_make_pub_ex(ecc_key* key, ecc_curve_spec* curveIn, + ecc_point* pubOut) +{ + int err = MP_OKAY; +#ifndef WOLFSSL_ATECC508A +#ifndef WOLFSSL_SP_MATH + ecc_point* base = NULL; +#endif + ecc_point* pub; + DECLARE_CURVE_SPECS(curve, ECC_CURVE_FIELD_COUNT); +#endif /* !WOLFSSL_ATECC508A */ + + if (key == NULL) { + return BAD_FUNC_ARG; + } + +#ifndef WOLFSSL_ATECC508A + + /* if ecc_point passed in then use it as output for public key point */ + if (pubOut != NULL) { + pub = pubOut; + } + else { + /* caching public key making it a ECC_PRIVATEKEY instead of + ECC_PRIVATEKEY_ONLY */ + pub = &key->pubkey; + key->type = ECC_PRIVATEKEY_ONLY; + } + + /* avoid loading the curve unless it is not passed in */ + if (curveIn != NULL) { + curve = curveIn; + } + else { + ALLOC_CURVE_SPECS(ECC_CURVE_FIELD_COUNT); + + /* load curve info */ + if (err == MP_OKAY) + err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ALL); + } + + if (err == MP_OKAY) { + #ifndef ALT_ECC_SIZE + err = mp_init_multi(pub->x, pub->y, pub->z, NULL, NULL, NULL); + #else + pub->x = (mp_int*)&pub->xyz[0]; + pub->y = (mp_int*)&pub->xyz[1]; + pub->z = (mp_int*)&pub->xyz[2]; + alt_fp_init(pub->x); + alt_fp_init(pub->y); + alt_fp_init(pub->z); + #endif + } + + +#ifdef WOLFSSL_HAVE_SP_ECC +#ifndef WOLFSSL_SP_NO_256 + if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1) { + if (err == MP_OKAY) + err = sp_ecc_mulmod_base_256(&key->k, pub, 1, key->heap); + } + else +#endif +#endif +#ifdef WOLFSSL_SP_MATH + err = WC_KEY_SIZE_E; +#else + { + if (err == MP_OKAY) { + base = wc_ecc_new_point_h(key->heap); + if (base == NULL) + err = MEMORY_E; + } + /* read in the x/y for this key */ + if (err == MP_OKAY) + err = mp_copy(curve->Gx, base->x); + if (err == MP_OKAY) + err = mp_copy(curve->Gy, base->y); + if (err == MP_OKAY) + err = mp_set(base->z, 1); + + /* make the public key */ + if (err == MP_OKAY) { + err = wc_ecc_mulmod_ex(&key->k, base, pub, curve->Af, curve->prime, + 1, key->heap); + if (err == MP_MEM) { + err = MEMORY_E; + } + } + + wc_ecc_del_point_h(base, key->heap); + } +#endif + +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + /* validate the public key, order * pubkey = point at infinity */ + if (err == MP_OKAY) + err = ecc_check_pubkey_order(key, pub, curve->Af, curve->prime, + curve->order); +#endif /* WOLFSSL_VALIDATE_KEYGEN */ + + if (err != MP_OKAY) { + /* clean up if failed */ + #ifndef ALT_ECC_SIZE + mp_clear(pub->x); + mp_clear(pub->y); + mp_clear(pub->z); + #endif + } + + /* free up local curve */ + if (curveIn == NULL) { + wc_ecc_curve_free(curve); + FREE_CURVE_SPECS(); + } + +#else + (void)curveIn; + err = NOT_COMPILED_IN; +#endif /* WOLFSSL_ATECC508A */ + + /* change key state if public part is cached */ + if (key->type == ECC_PRIVATEKEY_ONLY && pubOut == NULL) { + key->type = ECC_PRIVATEKEY; + } + + return err; +} + + +/* create the public ECC key from a private key + * + * key an initialized private key to generate public part from + * pubOut [out]ecc_point holding the public key, if NULL then public key part + * is cached in key instead. + * + * + * returns MP_OKAY on success + */ +int wc_ecc_make_pub(ecc_key* key, ecc_point* pubOut) +{ + WOLFSSL_ENTER("wc_ecc_make_pub"); + + return wc_ecc_make_pub_ex(key, NULL, pubOut); +} + + +int wc_ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, int curve_id) +{ + int err; +#if !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_CRYPTOCELL) +#ifndef WOLFSSL_SP_MATH + DECLARE_CURVE_SPECS(curve, ECC_CURVE_FIELD_COUNT); +#endif +#endif /* !WOLFSSL_ATECC508A */ +#if defined(WOLFSSL_CRYPTOCELL) + const CRYS_ECPKI_Domain_t* pDomain; + CRYS_ECPKI_KG_TempData_t tempBuff; + CRYS_ECPKI_KG_FipsContext_t fipsCtx; + byte ucompressed_key[ECC_MAX_CRYPTO_HW_SIZE*2 + 1]; + word32 raw_size = (word32) (key->dp->size)*2 + 1; +#endif + if (key == NULL || rng == NULL) { + return BAD_FUNC_ARG; + } + + /* make sure required variables are reset */ + wc_ecc_reset(key); + + err = wc_ecc_set_curve(key, keysize, curve_id); + if (err != 0) { + return err; + } + +#ifdef WOLF_CRYPTO_CB + if (key->devId != INVALID_DEVID) { + err = wc_CryptoCb_MakeEccKey(rng, keysize, key, curve_id); + if (err != CRYPTOCB_UNAVAILABLE) + return err; + /* fall-through when unavailable */ + } +#endif + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { + #ifdef HAVE_CAVIUM + /* TODO: Not implemented */ + #elif defined(HAVE_INTEL_QA) + /* TODO: Not implemented */ + #else + if (wc_AsyncTestInit(&key->asyncDev, ASYNC_TEST_ECC_MAKE)) { + WC_ASYNC_TEST* testDev = &key->asyncDev.test; + testDev->eccMake.rng = rng; + testDev->eccMake.key = key; + testDev->eccMake.size = keysize; + testDev->eccMake.curve_id = curve_id; + return WC_PENDING_E; + } + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT && WC_ASYNC_ENABLE_ECC */ + +#ifdef WOLFSSL_ATECC508A + if (key->dp->id == ECC_SECP256R1) { + key->type = ECC_PRIVATEKEY; + key->slot = atmel_ecc_alloc(ATMEL_SLOT_ECDHE); + err = atmel_ecc_create_key(key->slot, key->pubkey_raw); + + /* populate key->pubkey */ + if (err == 0 + #ifdef ALT_ECC_SIZE + && key->pubkey.x + #endif + ) { + err = mp_read_unsigned_bin(key->pubkey.x, key->pubkey_raw, + ECC_MAX_CRYPTO_HW_SIZE); + } + if (err == 0 + #ifdef ALT_ECC_SIZE + && key->pubkey.y + #endif + ) { + err = mp_read_unsigned_bin(key->pubkey.y, + key->pubkey_raw + ECC_MAX_CRYPTO_HW_SIZE, + ECC_MAX_CRYPTO_HW_SIZE); + } + } + else { + err = NOT_COMPILED_IN; + } +#elif defined(WOLFSSL_CRYPTOCELL) + + pDomain = CRYS_ECPKI_GetEcDomain(cc310_mapCurve(curve_id)); + + /* generate first key pair */ + err = CRYS_ECPKI_GenKeyPair(&wc_rndState, + wc_rndGenVectFunc, + pDomain, + &key->ctx.privKey, + &key->ctx.pubKey, + &tempBuff, + &fipsCtx); + + if (err != SA_SILIB_RET_OK){ + WOLFSSL_MSG("CRYS_ECPKI_GenKeyPair for key pair failed"); + return err; + } + key->type = ECC_PRIVATEKEY; + + err = CRYS_ECPKI_ExportPublKey(&key->ctx.pubKey, + CRYS_EC_PointUncompressed, + &ucompressed_key[0], + &raw_size); + + if (err == SA_SILIB_RET_OK && key->pubkey.x && key->pubkey.y) { + err = mp_read_unsigned_bin(key->pubkey.x, + &ucompressed_key[1], key->dp->size); + if (err == MP_OKAY) { + err = mp_read_unsigned_bin(key->pubkey.y, + &ucompressed_key[1+key->dp->size],key->dp->size); + } + } + raw_size = key->dp->size; + if (err == MP_OKAY) { + err = CRYS_ECPKI_ExportPrivKey(&key->ctx.privKey, + ucompressed_key, + &raw_size); + } + + if (err == SA_SILIB_RET_OK) { + err = mp_read_unsigned_bin(&key->k, ucompressed_key, raw_size); + } + +#else + +#ifdef WOLFSSL_HAVE_SP_ECC +#ifndef WOLFSSL_SP_NO_256 + if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1) { + err = sp_ecc_make_key_256(rng, &key->k, &key->pubkey, key->heap); + if (err == MP_OKAY) + key->type = ECC_PRIVATEKEY; + } + else +#endif +#endif /* WOLFSSL_HAVE_SP_ECC */ + + { /* software key gen */ +#ifdef WOLFSSL_SP_MATH + err = WC_KEY_SIZE_E; +#else + ALLOC_CURVE_SPECS(ECC_CURVE_FIELD_COUNT); + + /* setup the key variables */ + err = mp_init(&key->k); + + /* load curve info */ + if (err == MP_OKAY) + err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ALL); + + /* generate k */ + if (err == MP_OKAY) + err = wc_ecc_gen_k(rng, key->dp->size, &key->k, curve->order); + + /* generate public key from k */ + if (err == MP_OKAY) + err = wc_ecc_make_pub_ex(key, curve, NULL); + + if (err == MP_OKAY) + key->type = ECC_PRIVATEKEY; + + /* cleanup these on failure case only */ + if (err != MP_OKAY) { + /* clean up */ + mp_forcezero(&key->k); + } + + /* cleanup allocations */ + wc_ecc_curve_free(curve); + FREE_CURVE_SPECS(); +#endif /* WOLFSSL_SP_MATH */ + } + +#ifdef HAVE_WOLF_BIGINT + if (err == MP_OKAY) + err = wc_mp_to_bigint(&key->k, &key->k.raw); + if (err == MP_OKAY) + err = wc_mp_to_bigint(key->pubkey.x, &key->pubkey.x->raw); + if (err == MP_OKAY) + err = wc_mp_to_bigint(key->pubkey.y, &key->pubkey.y->raw); + if (err == MP_OKAY) + err = wc_mp_to_bigint(key->pubkey.z, &key->pubkey.z->raw); +#endif + +#endif /* WOLFSSL_ATECC508A */ + + return err; +} + +#ifdef ECC_DUMP_OID +/* Optional dump of encoded OID for adding new curves */ +static int mOidDumpDone; +static void wc_ecc_dump_oids(void) +{ + int x; + + if (mOidDumpDone) { + return; + } + + /* find matching OID sum (based on encoded value) */ + for (x = 0; ecc_sets[x].size != 0; x++) { + int i; + byte* oid; + word32 oidSz, sum = 0; + + printf("ECC %s (%d):\n", ecc_sets[x].name, x); + + #ifdef HAVE_OID_ENCODING + byte oidEnc[ECC_MAX_OID_LEN]; + + oid = oidEnc; + oidSz = ECC_MAX_OID_LEN; + + printf("OID: "); + for (i = 0; i < (int)ecc_sets[x].oidSz; i++) { + printf("%d.", ecc_sets[x].oid[i]); + } + printf("\n"); + + EncodeObjectId(ecc_sets[x].oid, ecc_sets[x].oidSz, oidEnc, &oidSz); + #else + oid = (byte*)ecc_sets[x].oid; + oidSz = ecc_sets[x].oidSz; + #endif + + printf("OID Encoded: "); + for (i = 0; i < (int)oidSz; i++) { + printf("0x%02X,", oid[i]); + } + printf("\n"); + + for (i = 0; i < (int)oidSz; i++) { + sum += oid[i]; + } + printf("Sum: %d\n", sum); + + /* validate sum */ + if (ecc_sets[x].oidSum != sum) { + printf(" Sum %d Not Valid!\n", ecc_sets[x].oidSum); + } + } + mOidDumpDone = 1; +} +#endif /* ECC_DUMP_OID */ + +/** + Make a new ECC key + rng An active RNG state + keysize The keysize for the new key (in octets from 20 to 65 bytes) + key [out] Destination of the newly created key + return MP_OKAY if successful, + upon error all allocated memory will be freed + */ +int wc_ecc_make_key(WC_RNG* rng, int keysize, ecc_key* key) +{ + return wc_ecc_make_key_ex(rng, keysize, key, ECC_CURVE_DEF); +} + +/* Setup dynamic pointers if using normal math for proper freeing */ +int wc_ecc_init_ex(ecc_key* key, void* heap, int devId) +{ + int ret = 0; + + if (key == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef ECC_DUMP_OID + wc_ecc_dump_oids(); +#endif + + XMEMSET(key, 0, sizeof(ecc_key)); + key->state = ECC_STATE_NONE; + +#if defined(PLUTON_CRYPTO_ECC) || defined(WOLF_CRYPTO_CB) + key->devId = devId; +#else + (void)devId; +#endif + +#ifdef WOLFSSL_ATECC508A + key->slot = ATECC_INVALID_SLOT; +#else +#ifdef ALT_ECC_SIZE + key->pubkey.x = (mp_int*)&key->pubkey.xyz[0]; + key->pubkey.y = (mp_int*)&key->pubkey.xyz[1]; + key->pubkey.z = (mp_int*)&key->pubkey.xyz[2]; + alt_fp_init(key->pubkey.x); + alt_fp_init(key->pubkey.y); + alt_fp_init(key->pubkey.z); + ret = mp_init(&key->k); +#else + ret = mp_init_multi(&key->k, key->pubkey.x, key->pubkey.y, key->pubkey.z, + NULL, NULL); +#endif /* ALT_ECC_SIZE */ + if (ret != MP_OKAY) { + return MEMORY_E; + } +#endif /* WOLFSSL_ATECC508A */ + +#ifdef WOLFSSL_HEAP_TEST + key->heap = (void*)WOLFSSL_HEAP_TEST; +#else + key->heap = heap; +#endif + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + /* handle as async */ + ret = wolfAsync_DevCtxInit(&key->asyncDev, WOLFSSL_ASYNC_MARKER_ECC, + key->heap, devId); +#endif + + return ret; +} + +int wc_ecc_init(ecc_key* key) +{ + return wc_ecc_init_ex(key, NULL, INVALID_DEVID); +} + +#ifdef HAVE_PKCS11 +int wc_ecc_init_id(ecc_key* key, unsigned char* id, int len, void* heap, + int devId) +{ + int ret = 0; + + if (key == NULL) + ret = BAD_FUNC_ARG; + if (ret == 0 && (len < 0 || len > ECC_MAX_ID_LEN)) + ret = BUFFER_E; + + if (ret == 0) + ret = wc_ecc_init_ex(key, heap, devId); + + if (ret == 0 && id != NULL && len != 0) { + XMEMCPY(key->id, id, len); + key->idLen = len; + } + + return ret; +} +#endif + +int wc_ecc_set_flags(ecc_key* key, word32 flags) +{ + if (key == NULL) { + return BAD_FUNC_ARG; + } + key->flags |= flags; + return 0; +} + + +static int wc_ecc_get_curve_order_bit_count(const ecc_set_type* dp) +{ + int err; + word32 orderBits; + DECLARE_CURVE_SPECS(curve, 1); + + ALLOC_CURVE_SPECS(1); + err = wc_ecc_curve_load(dp, &curve, ECC_CURVE_FIELD_ORDER); + if (err != 0) { + FREE_CURVE_SPECS(); + return err; + } + orderBits = mp_count_bits(curve->order); + + wc_ecc_curve_free(curve); + FREE_CURVE_SPECS(); + return (int)orderBits; +} + +#ifdef HAVE_ECC_SIGN + +#ifndef NO_ASN + +#if defined(WOLFSSL_ATECC508A) || defined(PLUTON_CRYPTO_ECC) || \ + defined(WOLFSSL_CRYPTOCELL) +static int wc_ecc_sign_hash_hw(const byte* in, word32 inlen, + mp_int* r, mp_int* s, byte* out, word32 *outlen, WC_RNG* rng, + ecc_key* key) +{ + int err; +#ifdef PLUTON_CRYPTO_ECC + if (key->devId != INVALID_DEVID) /* use hardware */ +#endif +#if defined(WOLFSSL_CRYPTOCELL) + CRYS_ECDSA_SignUserContext_t sigCtxTemp; + word32 raw_sig_size = *outlen; + word32 msgLenInBytes = inlen; + CRYS_ECPKI_HASH_OpMode_t hash_mode; +#endif + { + word32 keysize = (word32)key->dp->size; + word32 orderBits = wc_ecc_get_curve_order_bit_count(key->dp); + + /* Check args */ + if (keysize > ECC_MAX_CRYPTO_HW_SIZE || *outlen < keysize*2) { + return ECC_BAD_ARG_E; + } + + /* if the input is larger than curve order, we must truncate */ + if ((inlen * WOLFSSL_BIT_SIZE) > orderBits) { + inlen = (orderBits + WOLFSSL_BIT_SIZE - 1) / WOLFSSL_BIT_SIZE; + } + + #if defined(WOLFSSL_ATECC508A) + key->slot = atmel_ecc_alloc(ATMEL_SLOT_DEVICE); + if (key->slot == ATECC_INVALID_SLOT) { + return ECC_BAD_ARG_E; + } + + /* Sign: Result is 32-bytes of R then 32-bytes of S */ + err = atmel_ecc_sign(key->slot, in, out); + if (err != 0) { + return err; + } + #elif defined(PLUTON_CRYPTO_ECC) + { + /* perform ECC sign */ + word32 raw_sig_size = *outlen; + err = Crypto_EccSign(in, inlen, out, &raw_sig_size); + if (err != CRYPTO_RES_SUCCESS || raw_sig_size != keysize*2){ + return BAD_COND_E; + } + } + #elif defined(WOLFSSL_CRYPTOCELL) + + hash_mode = cc310_hashModeECC(msgLenInBytes); + if (hash_mode == CRYS_ECPKI_HASH_OpModeLast) { + hash_mode = cc310_hashModeECC(keysize); + hash_mode = CRYS_ECPKI_HASH_SHA256_mode; + } + + /* truncate if hash is longer than key size */ + if (msgLenInBytes > keysize) { + msgLenInBytes = keysize; + } + + /* create signature from an input buffer using a private key*/ + err = CRYS_ECDSA_Sign(&wc_rndState, + wc_rndGenVectFunc, + &sigCtxTemp, + &key->ctx.privKey, + hash_mode, + (byte*)in, + msgLenInBytes, + out, + &raw_sig_size); + + if (err != SA_SILIB_RET_OK){ + WOLFSSL_MSG("CRYS_ECDSA_Sign failed"); + return err; + } + #endif + + /* Load R and S */ + err = mp_read_unsigned_bin(r, &out[0], keysize); + if (err != MP_OKAY) { + return err; + } + err = mp_read_unsigned_bin(s, &out[keysize], keysize); + if (err != MP_OKAY) { + return err; + } + + /* Check for zeros */ + if (mp_iszero(r) || mp_iszero(s)) { + return MP_ZERO_E; + } + } +#ifdef PLUTON_CRYPTO_ECC + else { + err = wc_ecc_sign_hash_ex(in, inlen, rng, key, r, s); + } +#endif + (void)rng; + + return err; +} +#endif /* WOLFSSL_ATECC508A || PLUTON_CRYPTO_ECC || WOLFSSL_CRYPTOCELL */ + +/** + Sign a message digest + in The message digest to sign + inlen The length of the digest + out [out] The destination for the signature + outlen [in/out] The max size and resulting size of the signature + key A private ECC key + return MP_OKAY if successful + */ +int wc_ecc_sign_hash(const byte* in, word32 inlen, byte* out, word32 *outlen, + WC_RNG* rng, ecc_key* key) +{ + int err; + mp_int *r = NULL, *s = NULL; +#if (!defined(WOLFSSL_ASYNC_CRYPT) || !defined(WC_ASYNC_ENABLE_ECC)) && \ + !defined(WOLFSSL_SMALL_STACK) + mp_int r_lcl, s_lcl; +#endif + + if (in == NULL || out == NULL || outlen == NULL || key == NULL || + rng == NULL) { + return ECC_BAD_ARG_E; + } + +#ifdef WOLF_CRYPTO_CB + if (key->devId != INVALID_DEVID) { + err = wc_CryptoCb_EccSign(in, inlen, out, outlen, rng, key); + if (err != CRYPTOCB_UNAVAILABLE) + return err; + /* fall-through when unavailable */ + } +#endif + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + err = wc_ecc_alloc_async(key); + if (err != 0) + return err; + r = key->r; + s = key->s; +#elif !defined(WOLFSSL_SMALL_STACK) + r = &r_lcl; + s = &s_lcl; +#else + r = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC); + if (r == NULL) + return MEMORY_E; + s = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC); + if (s == NULL) { + XFREE(r, key->heap, DYNAMIC_TYPE_ECC); + return MEMORY_E; + } +#endif /* WOLFSSL_ASYNC_CRYPT && WC_ASYNC_ENABLE_ECC */ + + switch(key->state) { + case ECC_STATE_NONE: + case ECC_STATE_SIGN_DO: + key->state = ECC_STATE_SIGN_DO; + + if ((err = mp_init_multi(r, s, NULL, NULL, NULL, NULL)) != MP_OKAY){ + #if !defined(WOLFSSL_ASYNC_CRYPT) && defined(WOLFSSL_SMALL_STACK) + XFREE(s, key->heap, DYNAMIC_TYPE_ECC); + XFREE(r, key->heap, DYNAMIC_TYPE_ECC); + #endif + break; + } + + /* hardware crypto */ + #if defined(WOLFSSL_ATECC508A) || defined(PLUTON_CRYPTO_ECC) || defined(WOLFSSL_CRYPTOCELL) + err = wc_ecc_sign_hash_hw(in, inlen, r, s, out, outlen, rng, key); + #else + err = wc_ecc_sign_hash_ex(in, inlen, rng, key, r, s); + #endif + if (err < 0) { + #if !defined(WOLFSSL_ASYNC_CRYPT) && defined(WOLFSSL_SMALL_STACK) + XFREE(s, key->heap, DYNAMIC_TYPE_ECC); + XFREE(r, key->heap, DYNAMIC_TYPE_ECC); + #endif + break; + } + + FALL_THROUGH; + + case ECC_STATE_SIGN_ENCODE: + key->state = ECC_STATE_SIGN_ENCODE; + + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { + #ifdef HAVE_CAVIUM_V + /* Nitrox requires r and s in sep buffer, so split it */ + NitroxEccRsSplit(key, &r->raw, &s->raw); + #endif + #ifndef WOLFSSL_ASYNC_CRYPT_TEST + /* only do this if not simulator, since it overwrites result */ + wc_bigint_to_mp(&r->raw, r); + wc_bigint_to_mp(&s->raw, s); + #endif + } + #endif /* WOLFSSL_ASYNC_CRYPT */ + + /* encoded with DSA header */ + err = StoreECC_DSA_Sig(out, outlen, r, s); + + /* done with R/S */ + mp_clear(r); + mp_clear(s); + #if !defined(WOLFSSL_ASYNC_CRYPT) && defined(WOLFSSL_SMALL_STACK) + XFREE(s, key->heap, DYNAMIC_TYPE_ECC); + XFREE(r, key->heap, DYNAMIC_TYPE_ECC); + #endif + break; + + default: + err = BAD_STATE_E; + break; + } + + /* if async pending then return and skip done cleanup below */ + if (err == WC_PENDING_E) { + key->state++; + return err; + } + + /* cleanup */ +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + wc_ecc_free_async(key); +#endif + key->state = ECC_STATE_NONE; + + return err; +} +#endif /* !NO_ASN */ + +#if !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_CRYPTOCELL) +/** + Sign a message digest + in The message digest to sign + inlen The length of the digest + key A private ECC key + r [out] The destination for r component of the signature + s [out] The destination for s component of the signature + return MP_OKAY if successful +*/ +int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, + ecc_key* key, mp_int *r, mp_int *s) +{ + int err; +#ifndef WOLFSSL_SP_MATH + mp_int* e; +#if (!defined(WOLFSSL_ASYNC_CRYPT) || !defined(HAVE_CAVIUM_V)) && \ + !defined(WOLFSSL_SMALL_STACK) + mp_int e_lcl; +#endif + DECLARE_CURVE_SPECS(curve, 1); +#endif /* !WOLFSSL_SP_MATH */ + + if (in == NULL || r == NULL || s == NULL || key == NULL || rng == NULL) + return ECC_BAD_ARG_E; + + /* is this a private key? */ + if (key->type != ECC_PRIVATEKEY && key->type != ECC_PRIVATEKEY_ONLY) { + return ECC_BAD_ARG_E; + } + + /* is the IDX valid ? */ + if (wc_ecc_is_valid_idx(key->idx) != 1) { + return ECC_BAD_ARG_E; + } + +#ifdef WOLFSSL_SP_MATH + if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1) + return sp_ecc_sign_256(in, inlen, rng, &key->k, r, s, key->heap); + else + return WC_KEY_SIZE_E; +#else +#ifdef WOLFSSL_HAVE_SP_ECC + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + if (key->asyncDev.marker != WOLFSSL_ASYNC_MARKER_ECC) + #endif + { +#ifndef WOLFSSL_SP_NO_256 + if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1) + return sp_ecc_sign_256(in, inlen, rng, &key->k, r, s, key->heap); +#endif + } +#endif /* WOLFSSL_HAVE_SP_ECC */ + + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) && \ + defined(WOLFSSL_ASYNC_CRYPT_TEST) + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { + if (wc_AsyncTestInit(&key->asyncDev, ASYNC_TEST_ECC_SIGN)) { + WC_ASYNC_TEST* testDev = &key->asyncDev.test; + testDev->eccSign.in = in; + testDev->eccSign.inSz = inlen; + testDev->eccSign.rng = rng; + testDev->eccSign.key = key; + testDev->eccSign.r = r; + testDev->eccSign.s = s; + return WC_PENDING_E; + } + } +#endif + + ALLOC_CURVE_SPECS(1); + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM_V) + err = wc_ecc_alloc_mpint(key, &key->e); + if (err != 0) { + FREE_CURVE_SPECS(); + return err; + } + e = key->e; +#elif !defined(WOLFSSL_SMALL_STACK) + e = &e_lcl; +#else + e = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC); + if (e == NULL) { + FREE_CURVE_SPECS(); + return MEMORY_E; + } +#endif + + /* get the hash and load it as a bignum into 'e' */ + /* init the bignums */ + if ((err = mp_init(e)) != MP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(e, key->heap, DYNAMIC_TYPE_ECC); + #endif + FREE_CURVE_SPECS(); + return err; + } + + /* load curve info */ + err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ORDER); + + /* load digest into e */ + if (err == MP_OKAY) { + /* we may need to truncate if hash is longer than key size */ + word32 orderBits = mp_count_bits(curve->order); + + /* truncate down to byte size, may be all that's needed */ + if ((WOLFSSL_BIT_SIZE * inlen) > orderBits) + inlen = (orderBits + WOLFSSL_BIT_SIZE - 1) / WOLFSSL_BIT_SIZE; + err = mp_read_unsigned_bin(e, (byte*)in, inlen); + + /* may still need bit truncation too */ + if (err == MP_OKAY && (WOLFSSL_BIT_SIZE * inlen) > orderBits) + mp_rshb(e, WOLFSSL_BIT_SIZE - (orderBits & 0x7)); + } + + /* make up a key and export the public copy */ + if (err == MP_OKAY) { + int loop_check = 0; + #ifdef WOLFSSL_SMALL_STACK + ecc_key* pubkey = NULL; + #else + ecc_key pubkey[1]; + #endif + + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { + #if defined(HAVE_CAVIUM_V) || defined(HAVE_INTEL_QA) + #ifdef HAVE_CAVIUM_V + if (NitroxEccIsCurveSupported(key)) + #endif + { + word32 keySz = key->dp->size; + mp_int* k; + #ifdef HAVE_CAVIUM_V + err = wc_ecc_alloc_mpint(key, &key->signK); + if (err != 0) + return err; + k = key->signK; + #else + mp_int k_lcl; + k = &k_lcl; + #endif + + err = mp_init(k); + + /* make sure r and s are allocated */ + #ifdef HAVE_CAVIUM_V + /* Nitrox V needs single buffer for R and S */ + if (err == MP_OKAY) + err = wc_bigint_alloc(&key->r->raw, NitroxEccGetSize(key)*2); + /* Nitrox V only needs Prime and Order */ + if (err == MP_OKAY) + err = wc_ecc_curve_load(key->dp, &curve, + (ECC_CURVE_FIELD_PRIME | ECC_CURVE_FIELD_ORDER)); + #else + if (err == MP_OKAY) + err = wc_bigint_alloc(&key->r->raw, key->dp->size); + if (err == MP_OKAY) + err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ALL); + #endif + if (err == MP_OKAY) + err = wc_bigint_alloc(&key->s->raw, key->dp->size); + + /* load e and k */ + if (err == MP_OKAY) + err = wc_mp_to_bigint_sz(e, &e->raw, keySz); + if (err == MP_OKAY) + err = wc_mp_to_bigint_sz(&key->k, &key->k.raw, keySz); + if (err == MP_OKAY) + err = wc_ecc_gen_k(rng, key->dp->size, k, curve->order); + if (err == MP_OKAY) + err = wc_mp_to_bigint_sz(k, &k->raw, keySz); + + #ifdef HAVE_CAVIUM_V + if (err == MP_OKAY) + err = NitroxEcdsaSign(key, &e->raw, &key->k.raw, &k->raw, + &r->raw, &s->raw, &curve->prime->raw, &curve->order->raw); + #else + if (err == MP_OKAY) + err = IntelQaEcdsaSign(&key->asyncDev, &e->raw, &key->k.raw, + &k->raw, &r->raw, &s->raw, &curve->Af->raw, &curve->Bf->raw, + &curve->prime->raw, &curve->order->raw, &curve->Gx->raw, + &curve->Gy->raw); + #endif + + #ifndef HAVE_CAVIUM_V + mp_clear(e); + mp_clear(k); + #endif + wc_ecc_curve_free(curve); + FREE_CURVE_SPECS(); + + return err; + } + #endif /* HAVE_CAVIUM_V || HAVE_INTEL_QA */ + } + #endif /* WOLFSSL_ASYNC_CRYPT && WC_ASYNC_ENABLE_ECC */ + + #ifdef WOLFSSL_SMALL_STACK + pubkey = (ecc_key*)XMALLOC(sizeof(ecc_key), key->heap, DYNAMIC_TYPE_ECC); + if (pubkey == NULL) + err = MEMORY_E; + #endif + + /* don't use async for key, since we don't support async return here */ + if (err == MP_OKAY && (err = wc_ecc_init_ex(pubkey, key->heap, + INVALID_DEVID)) == MP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + mp_int* b = NULL; + #else + mp_int b[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + if (err == MP_OKAY) { + b = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, + DYNAMIC_TYPE_ECC); + if (b == NULL) + err = MEMORY_E; + } + #endif + + if (err == MP_OKAY) { + err = mp_init(b); + } + + #ifdef WOLFSSL_CUSTOM_CURVES + /* if custom curve, apply params to pubkey */ + if (err == MP_OKAY && key->idx == ECC_CUSTOM_IDX) { + err = wc_ecc_set_custom_curve(pubkey, key->dp); + } + #endif + + if (err == MP_OKAY) { + /* Generate blinding value - non-zero value. */ + do { + if (++loop_check > 64) { + err = RNG_FAILURE_E; + break; + } + + err = wc_ecc_gen_k(rng, key->dp->size, b, curve->order); + } + while (err == MP_ZERO_E); + loop_check = 0; + } + + for (; err == MP_OKAY;) { + if (++loop_check > 64) { + err = RNG_FAILURE_E; + break; + } + err = wc_ecc_make_key_ex(rng, key->dp->size, pubkey, + key->dp->id); + if (err != MP_OKAY) break; + + /* find r = x1 mod n */ + err = mp_mod(pubkey->pubkey.x, curve->order, r); + if (err != MP_OKAY) break; + + if (mp_iszero(r) == MP_YES) { + #ifndef ALT_ECC_SIZE + mp_clear(pubkey->pubkey.x); + mp_clear(pubkey->pubkey.y); + mp_clear(pubkey->pubkey.z); + #endif + mp_forcezero(&pubkey->k); + } + else { + /* find s = (e + xr)/k + = b.(e/k.b + x.r/k.b) */ + + /* k = k.b */ + err = mp_mulmod(&pubkey->k, b, curve->order, &pubkey->k); + if (err != MP_OKAY) break; + + /* k = 1/k.b */ + err = mp_invmod(&pubkey->k, curve->order, &pubkey->k); + if (err != MP_OKAY) break; + + /* s = x.r */ + err = mp_mulmod(&key->k, r, curve->order, s); + if (err != MP_OKAY) break; + + /* s = x.r/k.b */ + err = mp_mulmod(&pubkey->k, s, curve->order, s); + if (err != MP_OKAY) break; + + /* e = e/k.b */ + err = mp_mulmod(&pubkey->k, e, curve->order, e); + if (err != MP_OKAY) break; + + /* s = e/k.b + x.r/k.b + = (e + x.r)/k.b */ + err = mp_add(e, s, s); + if (err != MP_OKAY) break; + + /* s = b.(e + x.r)/k.b + = (e + x.r)/k */ + err = mp_mulmod(s, b, curve->order, s); + if (err != MP_OKAY) break; + + /* s = (e + xr)/k */ + err = mp_mod(s, curve->order, s); + if (err != MP_OKAY) break; + + if (mp_iszero(s) == MP_NO) + break; + } + } + mp_clear(b); + mp_free(b); + #ifdef WOLFSSL_SMALL_STACK + XFREE(b, key->heap, DYNAMIC_TYPE_ECC); + #endif + wc_ecc_free(pubkey); + #ifdef WOLFSSL_SMALL_STACK + XFREE(pubkey, key->heap, DYNAMIC_TYPE_ECC); + #endif + } + } + + mp_clear(e); + wc_ecc_curve_free(curve); +#ifdef WOLFSSL_SMALL_STACK + XFREE(e, key->heap, DYNAMIC_TYPE_ECC); +#endif + FREE_CURVE_SPECS(); +#endif /* WOLFSSL_SP_MATH */ + + return err; +} +#endif /* WOLFSSL_ATECC508A && WOLFSSL_CRYPTOCELL*/ +#endif /* HAVE_ECC_SIGN */ + +#ifdef WOLFSSL_CUSTOM_CURVES +void wc_ecc_free_curve(const ecc_set_type* curve, void* heap) +{ + if (curve->prime != NULL) + XFREE((void*)curve->prime, heap, DYNAMIC_TYPE_ECC_BUFFER); + if (curve->Af != NULL) + XFREE((void*)curve->Af, heap, DYNAMIC_TYPE_ECC_BUFFER); + if (curve->Bf != NULL) + XFREE((void*)curve->Bf, heap, DYNAMIC_TYPE_ECC_BUFFER); + if (curve->order != NULL) + XFREE((void*)curve->order, heap, DYNAMIC_TYPE_ECC_BUFFER); + if (curve->Gx != NULL) + XFREE((void*)curve->Gx, heap, DYNAMIC_TYPE_ECC_BUFFER); + if (curve->Gy != NULL) + XFREE((void*)curve->Gy, heap, DYNAMIC_TYPE_ECC_BUFFER); + + XFREE((void*)curve, heap, DYNAMIC_TYPE_ECC_BUFFER); + + (void)heap; +} +#endif /* WOLFSSL_CUSTOM_CURVES */ + +/** + Free an ECC key from memory + key The key you wish to free +*/ +int wc_ecc_free(ecc_key* key) +{ + if (key == NULL) { + return 0; + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + #ifdef WC_ASYNC_ENABLE_ECC + wolfAsync_DevCtxFree(&key->asyncDev, WOLFSSL_ASYNC_MARKER_ECC); + #endif + wc_ecc_free_async(key); +#endif + +#ifdef WOLFSSL_ATECC508A + atmel_ecc_free(key->slot); + key->slot = ATECC_INVALID_SLOT; +#else + + mp_clear(key->pubkey.x); + mp_clear(key->pubkey.y); + mp_clear(key->pubkey.z); + + mp_forcezero(&key->k); +#endif /* WOLFSSL_ATECC508A */ + +#ifdef WOLFSSL_CUSTOM_CURVES + if (key->deallocSet && key->dp != NULL) + wc_ecc_free_curve(key->dp, key->heap); +#endif + + return 0; +} + +#if !defined(WOLFSSL_SP_MATH) && !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_CRYPTOCELL) +#ifdef ECC_SHAMIR + +/** Computes kA*A + kB*B = C using Shamir's Trick + A First point to multiply + kA What to multiple A by + B Second point to multiply + kB What to multiple B by + C [out] Destination point (can overlap with A or B) + a ECC curve parameter a + modulus Modulus for curve + return MP_OKAY on success +*/ +#ifdef FP_ECC +static int normal_ecc_mul2add(ecc_point* A, mp_int* kA, + ecc_point* B, mp_int* kB, + ecc_point* C, mp_int* a, mp_int* modulus, + void* heap) +#else +int ecc_mul2add(ecc_point* A, mp_int* kA, + ecc_point* B, mp_int* kB, + ecc_point* C, mp_int* a, mp_int* modulus, + void* heap) +#endif +{ +#ifdef WOLFSSL_SMALL_STACK + ecc_point** precomp = NULL; +#ifdef WOLFSSL_SMALL_STACK_CACHE + ecc_key key; +#endif +#else + ecc_point* precomp[SHAMIR_PRECOMP_SZ]; +#endif + unsigned bitbufA, bitbufB, lenA, lenB, len, nA, nB, nibble; + unsigned char* tA; + unsigned char* tB; + int err = MP_OKAY, first, x, y; + mp_digit mp = 0; + + /* argchks */ + if (A == NULL || kA == NULL || B == NULL || kB == NULL || C == NULL || + modulus == NULL) { + return ECC_BAD_ARG_E; + } + + /* allocate memory */ + tA = (unsigned char*)XMALLOC(ECC_BUFSIZE, heap, DYNAMIC_TYPE_ECC_BUFFER); + if (tA == NULL) { + return GEN_MEM_ERR; + } + tB = (unsigned char*)XMALLOC(ECC_BUFSIZE, heap, DYNAMIC_TYPE_ECC_BUFFER); + if (tB == NULL) { + XFREE(tA, heap, DYNAMIC_TYPE_ECC_BUFFER); + return GEN_MEM_ERR; + } +#ifdef WOLFSSL_SMALL_STACK + precomp = (ecc_point**)XMALLOC(sizeof(ecc_point*) * SHAMIR_PRECOMP_SZ, heap, + DYNAMIC_TYPE_ECC_BUFFER); + if (precomp == NULL) { + XFREE(tB, heap, DYNAMIC_TYPE_ECC_BUFFER); + XFREE(tA, heap, DYNAMIC_TYPE_ECC_BUFFER); + return GEN_MEM_ERR; + } +#endif +#ifdef WOLFSSL_SMALL_STACK_CACHE + key.t1 = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); + key.t2 = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); +#ifdef ALT_ECC_SIZE + key.x = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); + key.y = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); + key.z = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); +#endif + if (key.t1 == NULL || key.t2 == NULL +#ifdef ALT_ECC_SIZE + || key.x == NULL || key.y == NULL || key.z == NULL +#endif + ) { +#ifdef ALT_ECC_SIZE + XFREE(key.z, heap, DYNAMIC_TYPE_ECC); + XFREE(key.y, heap, DYNAMIC_TYPE_ECC); + XFREE(key.x, heap, DYNAMIC_TYPE_ECC); +#endif + XFREE(key.t2, heap, DYNAMIC_TYPE_ECC); + XFREE(key.t1, heap, DYNAMIC_TYPE_ECC); + XFREE(precomp, heap, DYNAMIC_TYPE_ECC_BUFFER); + XFREE(tB, heap, DYNAMIC_TYPE_ECC_BUFFER); + XFREE(tA, heap, DYNAMIC_TYPE_ECC_BUFFER); + return MEMORY_E; + } + C->key = &key; +#endif /* WOLFSSL_SMALL_STACK_CACHE */ + + /* init variables */ + XMEMSET(tA, 0, ECC_BUFSIZE); + XMEMSET(tB, 0, ECC_BUFSIZE); +#ifndef WOLFSSL_SMALL_STACK + XMEMSET(precomp, 0, sizeof(precomp)); +#else + XMEMSET(precomp, 0, sizeof(ecc_point*) * SHAMIR_PRECOMP_SZ); +#endif + + /* get sizes */ + lenA = mp_unsigned_bin_size(kA); + lenB = mp_unsigned_bin_size(kB); + len = MAX(lenA, lenB); + + /* sanity check */ + if ((lenA > ECC_BUFSIZE) || (lenB > ECC_BUFSIZE)) { + err = BAD_FUNC_ARG; + } + + if (err == MP_OKAY) { + /* extract and justify kA */ + err = mp_to_unsigned_bin(kA, (len - lenA) + tA); + + /* extract and justify kB */ + if (err == MP_OKAY) + err = mp_to_unsigned_bin(kB, (len - lenB) + tB); + + /* allocate the table */ + if (err == MP_OKAY) { + for (x = 0; x < SHAMIR_PRECOMP_SZ; x++) { + precomp[x] = wc_ecc_new_point_h(heap); + if (precomp[x] == NULL) { + err = GEN_MEM_ERR; + break; + } + #ifdef WOLFSSL_SMALL_STACK_CACHE + precomp[x]->key = &key; + #endif + } + } + } + + if (err == MP_OKAY) + /* init montgomery reduction */ + err = mp_montgomery_setup(modulus, &mp); + + if (err == MP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + mp_int* mu = NULL; + #else + mp_int mu[1]; + #endif + #ifdef WOLFSSL_SMALL_STACK + mu = (mp_int*)XMALLOC(sizeof(mp_int), heap, DYNAMIC_TYPE_ECC); + if (mu == NULL) + err = MEMORY_E; + #endif + if (err == MP_OKAY) { + err = mp_init(mu); + } + if (err == MP_OKAY) { + err = mp_montgomery_calc_normalization(mu, modulus); + + if (err == MP_OKAY) + /* copy ones ... */ + err = mp_mulmod(A->x, mu, modulus, precomp[1]->x); + + if (err == MP_OKAY) + err = mp_mulmod(A->y, mu, modulus, precomp[1]->y); + if (err == MP_OKAY) + err = mp_mulmod(A->z, mu, modulus, precomp[1]->z); + + if (err == MP_OKAY) + err = mp_mulmod(B->x, mu, modulus, precomp[1<<2]->x); + if (err == MP_OKAY) + err = mp_mulmod(B->y, mu, modulus, precomp[1<<2]->y); + if (err == MP_OKAY) + err = mp_mulmod(B->z, mu, modulus, precomp[1<<2]->z); + + /* done with mu */ + mp_clear(mu); + #ifdef WOLFSSL_SMALL_STACK + XFREE(mu, heap, DYNAMIC_TYPE_ECC); + #endif + } + } + + if (err == MP_OKAY) + /* precomp [i,0](A + B) table */ + err = ecc_projective_dbl_point(precomp[1], precomp[2], a, modulus, mp); + + if (err == MP_OKAY) + err = ecc_projective_add_point(precomp[1], precomp[2], precomp[3], + a, modulus, mp); + if (err == MP_OKAY) + /* precomp [0,i](A + B) table */ + err = ecc_projective_dbl_point(precomp[1<<2], precomp[2<<2], a, modulus, mp); + + if (err == MP_OKAY) + err = ecc_projective_add_point(precomp[1<<2], precomp[2<<2], precomp[3<<2], + a, modulus, mp); + + if (err == MP_OKAY) { + /* precomp [i,j](A + B) table (i != 0, j != 0) */ + for (x = 1; x < 4; x++) { + for (y = 1; y < 4; y++) { + if (err == MP_OKAY) { + err = ecc_projective_add_point(precomp[x], precomp[(y<<2)], + precomp[x+(y<<2)], a, modulus, mp); + } + } + } + } + + if (err == MP_OKAY) { + nibble = 3; + first = 1; + bitbufA = tA[0]; + bitbufB = tB[0]; + + /* for every byte of the multiplicands */ + for (x = 0;; ) { + /* grab a nibble */ + if (++nibble == 4) { + if (x == (int)len) break; + bitbufA = tA[x]; + bitbufB = tB[x]; + nibble = 0; + x++; + } + + /* extract two bits from both, shift/update */ + nA = (bitbufA >> 6) & 0x03; + nB = (bitbufB >> 6) & 0x03; + bitbufA = (bitbufA << 2) & 0xFF; + bitbufB = (bitbufB << 2) & 0xFF; + + /* if both zero, if first, continue */ + if ((nA == 0) && (nB == 0) && (first == 1)) { + continue; + } + + /* double twice, only if this isn't the first */ + if (first == 0) { + /* double twice */ + if (err == MP_OKAY) + err = ecc_projective_dbl_point(C, C, a, modulus, mp); + if (err == MP_OKAY) + err = ecc_projective_dbl_point(C, C, a, modulus, mp); + else + break; + } + + /* if not both zero */ + if ((nA != 0) || (nB != 0)) { + if (first == 1) { + /* if first, copy from table */ + first = 0; + if (err == MP_OKAY) + err = mp_copy(precomp[nA + (nB<<2)]->x, C->x); + + if (err == MP_OKAY) + err = mp_copy(precomp[nA + (nB<<2)]->y, C->y); + + if (err == MP_OKAY) + err = mp_copy(precomp[nA + (nB<<2)]->z, C->z); + else + break; + } else { + /* if not first, add from table */ + if (err == MP_OKAY) + err = ecc_projective_add_point(C, precomp[nA + (nB<<2)], C, + a, modulus, mp); + else + break; + } + } + } + } + + /* reduce to affine */ + if (err == MP_OKAY) + err = ecc_map(C, modulus, mp); + + /* clean up */ + for (x = 0; x < SHAMIR_PRECOMP_SZ; x++) { + wc_ecc_del_point_h(precomp[x], heap); + } + + ForceZero(tA, ECC_BUFSIZE); + ForceZero(tB, ECC_BUFSIZE); +#ifdef WOLFSSL_SMALL_STACK_CACHE +#ifdef ALT_ECC_SIZE + XFREE(key.z, heap, DYNAMIC_TYPE_ECC); + XFREE(key.y, heap, DYNAMIC_TYPE_ECC); + XFREE(key.x, heap, DYNAMIC_TYPE_ECC); +#endif + XFREE(key.t2, heap, DYNAMIC_TYPE_ECC); + XFREE(key.t1, heap, DYNAMIC_TYPE_ECC); + C->key = NULL; +#endif +#ifdef WOLFSSL_SMALL_STACK + XFREE(precomp, heap, DYNAMIC_TYPE_ECC_BUFFER); +#endif + XFREE(tB, heap, DYNAMIC_TYPE_ECC_BUFFER); + XFREE(tA, heap, DYNAMIC_TYPE_ECC_BUFFER); + + return err; +} + +#endif /* ECC_SHAMIR */ +#endif /* !WOLFSSL_SP_MATH && !WOLFSSL_ATECC508A && !WOLFSSL_CRYPTOCEL*/ + + +#ifdef HAVE_ECC_VERIFY +#ifndef NO_ASN +/* verify + * + * w = s^-1 mod n + * u1 = xw + * u2 = rw + * X = u1*G + u2*Q + * v = X_x1 mod n + * accept if v == r + */ + +/** + Verify an ECC signature + sig The signature to verify + siglen The length of the signature (octets) + hash The hash (message digest) that was signed + hashlen The length of the hash (octets) + res Result of signature, 1==valid, 0==invalid + key The corresponding public ECC key + return MP_OKAY if successful (even if the signature is not valid) + */ +int wc_ecc_verify_hash(const byte* sig, word32 siglen, const byte* hash, + word32 hashlen, int* res, ecc_key* key) +{ + int err; + mp_int *r = NULL, *s = NULL; +#if (!defined(WOLFSSL_ASYNC_CRYPT) || !defined(WC_ASYNC_ENABLE_ECC)) && \ + !defined(WOLFSSL_SMALL_STACK) + mp_int r_lcl, s_lcl; +#endif + + if (sig == NULL || hash == NULL || res == NULL || key == NULL) { + return ECC_BAD_ARG_E; + } + +#ifdef WOLF_CRYPTO_CB + if (key->devId != INVALID_DEVID) { + err = wc_CryptoCb_EccVerify(sig, siglen, hash, hashlen, res, key); + if (err != CRYPTOCB_UNAVAILABLE) + return err; + /* fall-through when unavailable */ + } +#endif + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + err = wc_ecc_alloc_async(key); + if (err != 0) + return err; + r = key->r; + s = key->s; +#else + #ifndef WOLFSSL_SMALL_STACK + r = &r_lcl; + s = &s_lcl; + #else + r = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC); + if (r == NULL) + return MEMORY_E; + s = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC); + if (s == NULL) { + XFREE(r, key->heap, DYNAMIC_TYPE_ECC); + return MEMORY_E; + } + #endif + XMEMSET(r, 0, sizeof(mp_int)); + XMEMSET(s, 0, sizeof(mp_int)); +#endif /* WOLFSSL_ASYNC_CRYPT */ + + switch (key->state) { + case ECC_STATE_NONE: + case ECC_STATE_VERIFY_DECODE: + key->state = ECC_STATE_VERIFY_DECODE; + + /* default to invalid signature */ + *res = 0; + + /* Note, DecodeECC_DSA_Sig() calls mp_init() on r and s. + * If either of those don't allocate correctly, none of + * the rest of this function will execute, and everything + * gets cleaned up at the end. */ + /* decode DSA header */ + err = DecodeECC_DSA_Sig(sig, siglen, r, s); + if (err < 0) { + break; + } + FALL_THROUGH; + + case ECC_STATE_VERIFY_DO: + key->state = ECC_STATE_VERIFY_DO; + + err = wc_ecc_verify_hash_ex(r, s, hash, hashlen, res, key); + + #ifndef WOLFSSL_ASYNC_CRYPT + /* done with R/S */ + mp_clear(r); + mp_clear(s); + #ifdef WOLFSSL_SMALL_STACK + XFREE(s, key->heap, DYNAMIC_TYPE_ECC); + XFREE(r, key->heap, DYNAMIC_TYPE_ECC); + r = NULL; + s = NULL; + #endif + #endif + + if (err < 0) { + break; + } + FALL_THROUGH; + + case ECC_STATE_VERIFY_RES: + key->state = ECC_STATE_VERIFY_RES; + err = 0; + break; + + default: + err = BAD_STATE_E; + } + + /* if async pending then return and skip done cleanup below */ + if (err == WC_PENDING_E) { + key->state++; + return err; + } + + /* cleanup */ +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + wc_ecc_free_async(key); +#elif defined(WOLFSSL_SMALL_STACK) + XFREE(s, key->heap, DYNAMIC_TYPE_ECC); + XFREE(r, key->heap, DYNAMIC_TYPE_ECC); + r = NULL; + s = NULL; +#endif + + key->state = ECC_STATE_NONE; + + return err; +} +#endif /* !NO_ASN */ + + +/** + Verify an ECC signature + r The signature R component to verify + s The signature S component to verify + hash The hash (message digest) that was signed + hashlen The length of the hash (octets) + res Result of signature, 1==valid, 0==invalid + key The corresponding public ECC key + return MP_OKAY if successful (even if the signature is not valid) +*/ +int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, + word32 hashlen, int* res, ecc_key* key) +{ + int err; + word32 keySz; +#ifdef WOLFSSL_ATECC508A + byte sigRS[ATECC_KEY_SIZE*2]; +#elif defined(WOLFSSL_CRYPTOCELL) + byte sigRS[ECC_MAX_CRYPTO_HW_SIZE*2]; + CRYS_ECDSA_VerifyUserContext_t sigCtxTemp; + word32 msgLenInBytes = hashlen; + CRYS_ECPKI_HASH_OpMode_t hash_mode; +#elif !defined(WOLFSSL_SP_MATH) + int did_init = 0; + ecc_point *mG = NULL, *mQ = NULL; +#ifdef WOLFSSL_SMALL_STACK + mp_int* v = NULL; + mp_int* w = NULL; + mp_int* u1 = NULL; + mp_int* u2 = NULL; +#if !defined(WOLFSSL_ASYNC_CRYPT) || !defined(HAVE_CAVIUM_V) + mp_int* e_lcl = NULL; +#endif +#else /* WOLFSSL_SMALL_STACK */ + mp_int v[1]; + mp_int w[1]; + mp_int u1[1]; + mp_int u2[1]; +#if !defined(WOLFSSL_ASYNC_CRYPT) || !defined(HAVE_CAVIUM_V) + mp_int e_lcl[1]; +#endif +#endif /* WOLFSSL_SMALL_STACK */ + mp_int* e; + DECLARE_CURVE_SPECS(curve, ECC_CURVE_FIELD_COUNT); +#endif + + if (r == NULL || s == NULL || hash == NULL || res == NULL || key == NULL) + return ECC_BAD_ARG_E; + + /* default to invalid signature */ + *res = 0; + + /* is the IDX valid ? */ + if (wc_ecc_is_valid_idx(key->idx) != 1) { + return ECC_BAD_ARG_E; + } + + keySz = key->dp->size; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) && \ + defined(WOLFSSL_ASYNC_CRYPT_TEST) + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { + if (wc_AsyncTestInit(&key->asyncDev, ASYNC_TEST_ECC_VERIFY)) { + WC_ASYNC_TEST* testDev = &key->asyncDev.test; + testDev->eccVerify.r = r; + testDev->eccVerify.s = s; + testDev->eccVerify.hash = hash; + testDev->eccVerify.hashlen = hashlen; + testDev->eccVerify.stat = res; + testDev->eccVerify.key = key; + return WC_PENDING_E; + } + } +#endif + +#ifdef WOLFSSL_ATECC508A + /* Extract R and S */ + err = mp_to_unsigned_bin(r, &sigRS[0]); + if (err != MP_OKAY) { + return err; + } + err = mp_to_unsigned_bin(s, &sigRS[keySz]); + if (err != MP_OKAY) { + return err; + } + + err = atmel_ecc_verify(hash, sigRS, key->pubkey_raw, res); + if (err != 0) { + return err; + } + (void)hashlen; +#elif defined(WOLFSSL_CRYPTOCELL) + + /* Extract R and S */ + + err = mp_to_unsigned_bin(r, &sigRS[0]); + if (err != MP_OKAY) { + return err; + } + err = mp_to_unsigned_bin(s, &sigRS[keySz]); + if (err != MP_OKAY) { + return err; + } + + hash_mode = cc310_hashModeECC(msgLenInBytes); + if (hash_mode == CRYS_ECPKI_HASH_OpModeLast) { + hash_mode = cc310_hashModeECC(keySz); + hash_mode = CRYS_ECPKI_HASH_SHA256_mode; + } + /* truncate if hash is longer than key size */ + if (msgLenInBytes > keySz) { + msgLenInBytes = keySz; + } + + /* verify the signature using the public key */ + err = CRYS_ECDSA_Verify(&sigCtxTemp, + &key->ctx.pubKey, + hash_mode, + &sigRS[0], + keySz*2, + (byte*)hash, + msgLenInBytes); + + if (err != SA_SILIB_RET_OK) { + WOLFSSL_MSG("CRYS_ECDSA_Verify failed"); + return err; + } + /* valid signature if we get to this point */ + *res = 1; +#else + /* checking if private key with no public part */ + if (key->type == ECC_PRIVATEKEY_ONLY) { + WOLFSSL_MSG("Verify called with private key, generating public part"); + err = wc_ecc_make_pub_ex(key, NULL, NULL); + if (err != MP_OKAY) { + WOLFSSL_MSG("Unable to extract public key"); + return err; + } + } + +#ifdef WOLFSSL_SP_MATH + if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1) { + return sp_ecc_verify_256(hash, hashlen, key->pubkey.x, key->pubkey.y, + key->pubkey.z, r, s, res, key->heap); + } + else + return WC_KEY_SIZE_E; +#else +#ifdef WOLFSSL_HAVE_SP_ECC +#ifndef WOLFSSL_SP_NO_256 + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + if (key->asyncDev.marker != WOLFSSL_ASYNC_MARKER_ECC) + #endif + { + if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1) + return sp_ecc_verify_256(hash, hashlen, key->pubkey.x, key->pubkey.y, + key->pubkey.z,r, s, res, key->heap); + } +#endif /* WOLFSSL_SP_NO_256 */ +#endif /* WOLFSSL_HAVE_SP_ECC */ + + ALLOC_CURVE_SPECS(ECC_CURVE_FIELD_COUNT); + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_CAVIUM_V) + err = wc_ecc_alloc_mpint(key, &key->e); + if (err != 0) { + FREE_CURVE_SPECS(); + return err; + } + e = key->e; +#else +#ifdef WOLFSSL_SMALL_STACK + e_lcl = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC); + if (e_lcl == NULL) { + FREE_CURVE_SPECS(); + return MEMORY_E; + } +#endif + e = e_lcl; +#endif /* WOLFSSL_ASYNC_CRYPT && HAVE_CAVIUM_V */ + + err = mp_init(e); + if (err != MP_OKAY) + return MEMORY_E; + + /* read in the specs for this curve */ + err = wc_ecc_curve_load(key->dp, &curve, ECC_CURVE_FIELD_ALL); + + /* check for zero */ + if (err == MP_OKAY) { + if (mp_iszero(r) == MP_YES || mp_iszero(s) == MP_YES || + mp_cmp(r, curve->order) != MP_LT || + mp_cmp(s, curve->order) != MP_LT) { + err = MP_ZERO_E; + } + } + + /* read hash */ + if (err == MP_OKAY) { + /* we may need to truncate if hash is longer than key size */ + unsigned int orderBits = mp_count_bits(curve->order); + + /* truncate down to byte size, may be all that's needed */ + if ( (WOLFSSL_BIT_SIZE * hashlen) > orderBits) + hashlen = (orderBits + WOLFSSL_BIT_SIZE - 1) / WOLFSSL_BIT_SIZE; + err = mp_read_unsigned_bin(e, hash, hashlen); + + /* may still need bit truncation too */ + if (err == MP_OKAY && (WOLFSSL_BIT_SIZE * hashlen) > orderBits) + mp_rshb(e, WOLFSSL_BIT_SIZE - (orderBits & 0x7)); + } + + /* check for async hardware acceleration */ +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_ECC) { + #if defined(HAVE_CAVIUM_V) || defined(HAVE_INTEL_QA) + #ifdef HAVE_CAVIUM_V + if (NitroxEccIsCurveSupported(key)) + #endif + { + err = wc_mp_to_bigint_sz(e, &e->raw, keySz); + if (err == MP_OKAY) + err = wc_mp_to_bigint_sz(key->pubkey.x, &key->pubkey.x->raw, keySz); + if (err == MP_OKAY) + err = wc_mp_to_bigint_sz(key->pubkey.y, &key->pubkey.y->raw, keySz); + if (err == MP_OKAY) + #ifdef HAVE_CAVIUM_V + err = NitroxEcdsaVerify(key, &e->raw, &key->pubkey.x->raw, + &key->pubkey.y->raw, &r->raw, &s->raw, + &curve->prime->raw, &curve->order->raw, res); + #else + err = IntelQaEcdsaVerify(&key->asyncDev, &e->raw, &key->pubkey.x->raw, + &key->pubkey.y->raw, &r->raw, &s->raw, &curve->Af->raw, + &curve->Bf->raw, &curve->prime->raw, &curve->order->raw, + &curve->Gx->raw, &curve->Gy->raw, res); + #endif + + #ifndef HAVE_CAVIUM_V + mp_clear(e); + #endif + wc_ecc_curve_free(curve); + FREE_CURVE_SPECS(); + + return err; + } + #endif /* HAVE_CAVIUM_V || HAVE_INTEL_QA */ + } +#endif /* WOLFSSL_ASYNC_CRYPT && WC_ASYNC_ENABLE_ECC */ + +#ifdef WOLFSSL_SMALL_STACK + if (err == MP_OKAY) { + v = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC); + if (v == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + w = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC); + if (w == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + u1 = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC); + if (u1 == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + u2 = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC); + if (u2 == NULL) + err = MEMORY_E; + } +#endif + + /* allocate ints */ + if (err == MP_OKAY) { + if ((err = mp_init_multi(v, w, u1, u2, NULL, NULL)) != MP_OKAY) { + err = MEMORY_E; + } + did_init = 1; + } + + /* allocate points */ + if (err == MP_OKAY) { + mG = wc_ecc_new_point_h(key->heap); + mQ = wc_ecc_new_point_h(key->heap); + if (mQ == NULL || mG == NULL) + err = MEMORY_E; + } + + /* w = s^-1 mod n */ + if (err == MP_OKAY) + err = mp_invmod(s, curve->order, w); + + /* u1 = ew */ + if (err == MP_OKAY) + err = mp_mulmod(e, w, curve->order, u1); + + /* u2 = rw */ + if (err == MP_OKAY) + err = mp_mulmod(r, w, curve->order, u2); + + /* find mG and mQ */ + if (err == MP_OKAY) + err = mp_copy(curve->Gx, mG->x); + if (err == MP_OKAY) + err = mp_copy(curve->Gy, mG->y); + if (err == MP_OKAY) + err = mp_set(mG->z, 1); + + if (err == MP_OKAY) + err = mp_copy(key->pubkey.x, mQ->x); + if (err == MP_OKAY) + err = mp_copy(key->pubkey.y, mQ->y); + if (err == MP_OKAY) + err = mp_copy(key->pubkey.z, mQ->z); + +#ifdef FREESCALE_LTC_ECC + /* use PKHA to compute u1*mG + u2*mQ */ + if (err == MP_OKAY) + err = wc_ecc_mulmod_ex(u1, mG, mG, curve->Af, curve->prime, 0, key->heap); + if (err == MP_OKAY) + err = wc_ecc_mulmod_ex(u2, mQ, mQ, curve->Af, curve->prime, 0, key->heap); + if (err == MP_OKAY) + err = wc_ecc_point_add(mG, mQ, mG, curve->prime); +#else +#ifndef ECC_SHAMIR + { + mp_digit mp = 0; + + /* compute u1*mG + u2*mQ = mG */ + if (err == MP_OKAY) { + err = wc_ecc_mulmod_ex(u1, mG, mG, curve->Af, curve->prime, 0, + key->heap); + } + if (err == MP_OKAY) { + err = wc_ecc_mulmod_ex(u2, mQ, mQ, curve->Af, curve->prime, 0, + key->heap); + } + + /* find the montgomery mp */ + if (err == MP_OKAY) + err = mp_montgomery_setup(curve->prime, &mp); + + /* add them */ + if (err == MP_OKAY) + err = ecc_projective_add_point(mQ, mG, mG, curve->Af, + curve->prime, mp); + + /* reduce */ + if (err == MP_OKAY) + err = ecc_map(mG, curve->prime, mp); + } +#else + /* use Shamir's trick to compute u1*mG + u2*mQ using half the doubles */ + if (err == MP_OKAY) { + err = ecc_mul2add(mG, u1, mQ, u2, mG, curve->Af, curve->prime, + key->heap); + } +#endif /* ECC_SHAMIR */ +#endif /* FREESCALE_LTC_ECC */ + /* v = X_x1 mod n */ + if (err == MP_OKAY) + err = mp_mod(mG->x, curve->order, v); + + /* does v == r */ + if (err == MP_OKAY) { + if (mp_cmp(v, r) == MP_EQ) + *res = 1; + } + + /* cleanup */ + wc_ecc_del_point_h(mG, key->heap); + wc_ecc_del_point_h(mQ, key->heap); + + mp_clear(e); + if (did_init) { + mp_clear(v); + mp_clear(w); + mp_clear(u1); + mp_clear(u2); + } +#ifdef WOLFSSL_SMALL_STACK + XFREE(u2, key->heap, DYNAMIC_TYPE_ECC); + XFREE(u1, key->heap, DYNAMIC_TYPE_ECC); + XFREE(w, key->heap, DYNAMIC_TYPE_ECC); + XFREE(v, key->heap, DYNAMIC_TYPE_ECC); +#if !defined(WOLFSSL_ASYNC_CRYPT) || !defined(HAVE_CAVIUM_V) + XFREE(e_lcl, key->heap, DYNAMIC_TYPE_ECC); +#endif +#endif + + wc_ecc_curve_free(curve); + FREE_CURVE_SPECS(); + +#endif /* WOLFSSL_SP_MATH */ +#endif /* WOLFSSL_ATECC508A */ + + (void)keySz; + (void)hashlen; + + return err; +} +#endif /* HAVE_ECC_VERIFY */ + +#ifdef HAVE_ECC_KEY_IMPORT +/* import point from der */ +int wc_ecc_import_point_der(byte* in, word32 inLen, const int curve_idx, + ecc_point* point) +{ + int err = 0; + int compressed = 0; + int keysize; + byte pointType; + + if (in == NULL || point == NULL || (curve_idx < 0) || + (wc_ecc_is_valid_idx(curve_idx) == 0)) + return ECC_BAD_ARG_E; + + /* must be odd */ + if ((inLen & 1) == 0) { + return ECC_BAD_ARG_E; + } + + /* init point */ +#ifdef ALT_ECC_SIZE + point->x = (mp_int*)&point->xyz[0]; + point->y = (mp_int*)&point->xyz[1]; + point->z = (mp_int*)&point->xyz[2]; + alt_fp_init(point->x); + alt_fp_init(point->y); + alt_fp_init(point->z); +#else + err = mp_init_multi(point->x, point->y, point->z, NULL, NULL, NULL); +#endif + if (err != MP_OKAY) + return MEMORY_E; + + /* check for point type (4, 2, or 3) */ + pointType = in[0]; + if (pointType != ECC_POINT_UNCOMP && pointType != ECC_POINT_COMP_EVEN && + pointType != ECC_POINT_COMP_ODD) { + err = ASN_PARSE_E; + } + + if (pointType == ECC_POINT_COMP_EVEN || pointType == ECC_POINT_COMP_ODD) { +#ifdef HAVE_COMP_KEY + compressed = 1; +#else + err = NOT_COMPILED_IN; +#endif + } + + /* adjust to skip first byte */ + inLen -= 1; + in += 1; + + /* calculate key size based on inLen / 2 */ + keysize = inLen>>1; + + /* read data */ + if (err == MP_OKAY) + err = mp_read_unsigned_bin(point->x, (byte*)in, keysize); + +#ifdef HAVE_COMP_KEY + if (err == MP_OKAY && compressed == 1) { /* build y */ +#ifndef WOLFSSL_SP_MATH + int did_init = 0; + mp_int t1, t2; + DECLARE_CURVE_SPECS(curve, 3); + + ALLOC_CURVE_SPECS(3); + + if (mp_init_multi(&t1, &t2, NULL, NULL, NULL, NULL) != MP_OKAY) + err = MEMORY_E; + else + did_init = 1; + + /* load curve info */ + if (err == MP_OKAY) + err = wc_ecc_curve_load(&ecc_sets[curve_idx], &curve, + (ECC_CURVE_FIELD_PRIME | ECC_CURVE_FIELD_AF | + ECC_CURVE_FIELD_BF)); + + /* compute x^3 */ + if (err == MP_OKAY) + err = mp_sqr(point->x, &t1); + if (err == MP_OKAY) + err = mp_mulmod(&t1, point->x, curve->prime, &t1); + + /* compute x^3 + a*x */ + if (err == MP_OKAY) + err = mp_mulmod(curve->Af, point->x, curve->prime, &t2); + if (err == MP_OKAY) + err = mp_add(&t1, &t2, &t1); + + /* compute x^3 + a*x + b */ + if (err == MP_OKAY) + err = mp_add(&t1, curve->Bf, &t1); + + /* compute sqrt(x^3 + a*x + b) */ + if (err == MP_OKAY) + err = mp_sqrtmod_prime(&t1, curve->prime, &t2); + + /* adjust y */ + if (err == MP_OKAY) { + if ((mp_isodd(&t2) == MP_YES && pointType == ECC_POINT_COMP_ODD) || + (mp_isodd(&t2) == MP_NO && pointType == ECC_POINT_COMP_EVEN)) { + err = mp_mod(&t2, curve->prime, point->y); + } + else { + err = mp_submod(curve->prime, &t2, curve->prime, point->y); + } + } + + if (did_init) { + mp_clear(&t2); + mp_clear(&t1); + } + + wc_ecc_curve_free(curve); + FREE_CURVE_SPECS(); +#else + sp_ecc_uncompress_256(point->x, pointType, point->y); +#endif + } +#endif + + if (err == MP_OKAY && compressed == 0) + err = mp_read_unsigned_bin(point->y, (byte*)in + keysize, keysize); + if (err == MP_OKAY) + err = mp_set(point->z, 1); + + if (err != MP_OKAY) { + mp_clear(point->x); + mp_clear(point->y); + mp_clear(point->z); + } + + return err; +} +#endif /* HAVE_ECC_KEY_IMPORT */ + +#ifdef HAVE_ECC_KEY_EXPORT +/* export point to der */ +int wc_ecc_export_point_der(const int curve_idx, ecc_point* point, byte* out, + word32* outLen) +{ + int ret = MP_OKAY; + word32 numlen; +#ifdef WOLFSSL_SMALL_STACK + byte* buf; +#else + byte buf[ECC_BUFSIZE]; +#endif + + if ((curve_idx < 0) || (wc_ecc_is_valid_idx(curve_idx) == 0)) + return ECC_BAD_ARG_E; + + /* return length needed only */ + if (point != NULL && out == NULL && outLen != NULL) { + numlen = ecc_sets[curve_idx].size; + *outLen = 1 + 2*numlen; + return LENGTH_ONLY_E; + } + + if (point == NULL || out == NULL || outLen == NULL) + return ECC_BAD_ARG_E; + + numlen = ecc_sets[curve_idx].size; + + if (*outLen < (1 + 2*numlen)) { + *outLen = 1 + 2*numlen; + return BUFFER_E; + } + + /* store byte point type */ + out[0] = ECC_POINT_UNCOMP; + +#ifdef WOLFSSL_SMALL_STACK + buf = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_ECC_BUFFER); + if (buf == NULL) + return MEMORY_E; +#endif + + /* pad and store x */ + XMEMSET(buf, 0, ECC_BUFSIZE); + ret = mp_to_unsigned_bin(point->x, buf + + (numlen - mp_unsigned_bin_size(point->x))); + if (ret != MP_OKAY) + goto done; + XMEMCPY(out+1, buf, numlen); + + /* pad and store y */ + XMEMSET(buf, 0, ECC_BUFSIZE); + ret = mp_to_unsigned_bin(point->y, buf + + (numlen - mp_unsigned_bin_size(point->y))); + if (ret != MP_OKAY) + goto done; + XMEMCPY(out+1+numlen, buf, numlen); + + *outLen = 1 + 2*numlen; + +done: +#ifdef WOLFSSL_SMALL_STACK + XFREE(buf, NULL, DYNAMIC_TYPE_ECC_BUFFER); +#endif + + return ret; +} + + +/* export public ECC key in ANSI X9.63 format */ +int wc_ecc_export_x963(ecc_key* key, byte* out, word32* outLen) +{ + int ret = MP_OKAY; + word32 numlen; +#ifdef WOLFSSL_SMALL_STACK + byte* buf; +#else + byte buf[ECC_BUFSIZE]; +#endif + word32 pubxlen, pubylen; + + /* return length needed only */ + if (key != NULL && out == NULL && outLen != NULL) { + numlen = key->dp->size; + *outLen = 1 + 2*numlen; + return LENGTH_ONLY_E; + } + + if (key == NULL || out == NULL || outLen == NULL) + return ECC_BAD_ARG_E; + + if (key->type == ECC_PRIVATEKEY_ONLY) + return ECC_PRIVATEONLY_E; + + if (wc_ecc_is_valid_idx(key->idx) == 0) { + return ECC_BAD_ARG_E; + } + numlen = key->dp->size; + + /* verify room in out buffer */ + if (*outLen < (1 + 2*numlen)) { + *outLen = 1 + 2*numlen; + return BUFFER_E; + } + + /* verify public key length is less than key size */ + pubxlen = mp_unsigned_bin_size(key->pubkey.x); + pubylen = mp_unsigned_bin_size(key->pubkey.y); + if ((pubxlen > numlen) || (pubylen > numlen)) { + WOLFSSL_MSG("Public key x/y invalid!"); + return BUFFER_E; + } + + /* store byte point type */ + out[0] = ECC_POINT_UNCOMP; + +#ifdef WOLFSSL_SMALL_STACK + buf = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_ECC_BUFFER); + if (buf == NULL) + return MEMORY_E; +#endif + + /* pad and store x */ + XMEMSET(buf, 0, ECC_BUFSIZE); + ret = mp_to_unsigned_bin(key->pubkey.x, buf + (numlen - pubxlen)); + if (ret != MP_OKAY) + goto done; + XMEMCPY(out+1, buf, numlen); + + /* pad and store y */ + XMEMSET(buf, 0, ECC_BUFSIZE); + ret = mp_to_unsigned_bin(key->pubkey.y, buf + (numlen - pubylen)); + if (ret != MP_OKAY) + goto done; + XMEMCPY(out+1+numlen, buf, numlen); + + *outLen = 1 + 2*numlen; + +done: +#ifdef WOLFSSL_SMALL_STACK + XFREE(buf, NULL, DYNAMIC_TYPE_ECC_BUFFER); +#endif + + return ret; +} + + +/* export public ECC key in ANSI X9.63 format, extended with + * compression option */ +int wc_ecc_export_x963_ex(ecc_key* key, byte* out, word32* outLen, + int compressed) +{ + if (compressed == 0) + return wc_ecc_export_x963(key, out, outLen); +#ifdef HAVE_COMP_KEY + else + return wc_ecc_export_x963_compressed(key, out, outLen); +#else + return NOT_COMPILED_IN; +#endif +} +#endif /* HAVE_ECC_KEY_EXPORT */ + + +#if !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_CRYPTOCELL) + +/* is ecc point on curve described by dp ? */ +int wc_ecc_is_point(ecc_point* ecp, mp_int* a, mp_int* b, mp_int* prime) +{ +#ifndef WOLFSSL_SP_MATH + int err; +#ifdef WOLFSSL_SMALL_STACK + mp_int* t1 = NULL; + mp_int* t2 = NULL; +#else + mp_int t1[1], t2[1]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + t1 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + if (t1 == NULL) + return MEMORY_E; + t2 = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + if (t2 == NULL) { + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + return MEMORY_E; + } +#endif + + if ((err = mp_init_multi(t1, t2, NULL, NULL, NULL, NULL)) != MP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(t2, NULL, DYNAMIC_TYPE_ECC); + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); + #endif + return err; + } + + /* compute y^2 */ + if (err == MP_OKAY) + err = mp_sqr(ecp->y, t1); + + /* compute x^3 */ + if (err == MP_OKAY) + err = mp_sqr(ecp->x, t2); + if (err == MP_OKAY) + err = mp_mod(t2, prime, t2); + if (err == MP_OKAY) + err = mp_mul(ecp->x, t2, t2); + + /* compute y^2 - x^3 */ + if (err == MP_OKAY) + err = mp_sub(t1, t2, t1); + + /* Determine if curve "a" should be used in calc */ +#ifdef WOLFSSL_CUSTOM_CURVES + if (err == MP_OKAY) { + /* Use a and prime to determine if a == 3 */ + err = mp_set(t2, 0); + if (err == MP_OKAY) + err = mp_submod(prime, a, prime, t2); + } + if (err == MP_OKAY && mp_cmp_d(t2, 3) != MP_EQ) { + /* compute y^2 - x^3 + a*x */ + if (err == MP_OKAY) + err = mp_mulmod(t2, ecp->x, prime, t2); + if (err == MP_OKAY) + err = mp_addmod(t1, t2, prime, t1); + } + else +#endif /* WOLFSSL_CUSTOM_CURVES */ + { + /* assumes "a" == 3 */ + (void)a; + + /* compute y^2 - x^3 + 3x */ + if (err == MP_OKAY) + err = mp_add(t1, ecp->x, t1); + if (err == MP_OKAY) + err = mp_add(t1, ecp->x, t1); + if (err == MP_OKAY) + err = mp_add(t1, ecp->x, t1); + if (err == MP_OKAY) + err = mp_mod(t1, prime, t1); + } + + /* adjust range (0, prime) */ + while (err == MP_OKAY && mp_isneg(t1)) { + err = mp_add(t1, prime, t1); + } + while (err == MP_OKAY && mp_cmp(t1, prime) != MP_LT) { + err = mp_sub(t1, prime, t1); + } + + /* compare to b */ + if (err == MP_OKAY) { + if (mp_cmp(t1, b) != MP_EQ) { + err = MP_VAL; + } else { + err = MP_OKAY; + } + } + + mp_clear(t1); + mp_clear(t2); +#ifdef WOLFSSL_SMALL_STACK + XFREE(t2, NULL, DYNAMIC_TYPE_ECC); + XFREE(t1, NULL, DYNAMIC_TYPE_ECC); +#endif + + return err; +#else + (void)a; + (void)b; + (void)prime; + + return sp_ecc_is_point_256(ecp->x, ecp->y); +#endif +} + +#ifndef WOLFSSL_SP_MATH +/* validate privkey * generator == pubkey, 0 on success */ +static int ecc_check_privkey_gen(ecc_key* key, mp_int* a, mp_int* prime) +{ + int err = MP_OKAY; + ecc_point* base = NULL; + ecc_point* res = NULL; + DECLARE_CURVE_SPECS(curve, 2); + + if (key == NULL) + return BAD_FUNC_ARG; + + ALLOC_CURVE_SPECS(2); + + res = wc_ecc_new_point_h(key->heap); + if (res == NULL) + err = MEMORY_E; + +#ifdef WOLFSSL_HAVE_SP_ECC +#ifndef WOLFSSL_SP_NO_256 + if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1) { + if (err == MP_OKAY) + err = sp_ecc_mulmod_base_256(&key->k, res, 1, key->heap); + } + else +#endif +#endif + { + base = wc_ecc_new_point_h(key->heap); + if (base == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + /* load curve info */ + err = wc_ecc_curve_load(key->dp, &curve, + (ECC_CURVE_FIELD_GX | ECC_CURVE_FIELD_GY)); + } + + /* set up base generator */ + if (err == MP_OKAY) + err = mp_copy(curve->Gx, base->x); + if (err == MP_OKAY) + err = mp_copy(curve->Gy, base->y); + if (err == MP_OKAY) + err = mp_set(base->z, 1); + + if (err == MP_OKAY) + err = wc_ecc_mulmod_ex(&key->k, base, res, a, prime, 1, key->heap); + } + + if (err == MP_OKAY) { + /* compare result to public key */ + if (mp_cmp(res->x, key->pubkey.x) != MP_EQ || + mp_cmp(res->y, key->pubkey.y) != MP_EQ || + mp_cmp(res->z, key->pubkey.z) != MP_EQ) { + /* didn't match */ + err = ECC_PRIV_KEY_E; + } + } + + wc_ecc_curve_free(curve); + wc_ecc_del_point_h(res, key->heap); + wc_ecc_del_point_h(base, key->heap); + FREE_CURVE_SPECS(); + + return err; +} +#endif + +#ifdef WOLFSSL_VALIDATE_ECC_IMPORT + +/* check privkey generator helper, creates prime needed */ +static int ecc_check_privkey_gen_helper(ecc_key* key) +{ + int err; +#ifndef WOLFSSL_ATECC508A + DECLARE_CURVE_SPECS(curve, 2); +#endif + + if (key == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_ATECC508A + /* Hardware based private key, so this operation is not supported */ + err = MP_OKAY; /* just report success */ + +#else + ALLOC_CURVE_SPECS(2); + + /* load curve info */ + err = wc_ecc_curve_load(key->dp, &curve, + (ECC_CURVE_FIELD_PRIME | ECC_CURVE_FIELD_AF)); + + if (err == MP_OKAY) + err = ecc_check_privkey_gen(key, curve->Af, curve->prime); + + wc_ecc_curve_free(curve); + FREE_CURVE_SPECS(); + +#endif /* WOLFSSL_ATECC508A */ + + return err; +} + +#endif /* WOLFSSL_VALIDATE_ECC_IMPORT */ + + +#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || !defined(WOLFSSL_SP_MATH) +/* validate order * pubkey = point at infinity, 0 on success */ +static int ecc_check_pubkey_order(ecc_key* key, ecc_point* pubkey, mp_int* a, + mp_int* prime, mp_int* order) +{ + ecc_point* inf = NULL; + int err; + + if (key == NULL) + return BAD_FUNC_ARG; + + inf = wc_ecc_new_point_h(key->heap); + if (inf == NULL) + err = MEMORY_E; + else { +#ifdef WOLFSSL_HAVE_SP_ECC +#ifndef WOLFSSL_SP_NO_256 + if (key->idx != ECC_CUSTOM_IDX && + ecc_sets[key->idx].id == ECC_SECP256R1) { + err = sp_ecc_mulmod_256(order, pubkey, inf, 1, key->heap); + } + else +#endif +#endif +#ifndef WOLFSSL_SP_MATH + err = wc_ecc_mulmod_ex(order, pubkey, inf, a, prime, 1, key->heap); + if (err == MP_OKAY && !wc_ecc_point_is_at_infinity(inf)) + err = ECC_INF_E; +#else + (void)a; + (void)prime; + + err = WC_KEY_SIZE_E; +#endif + } + + wc_ecc_del_point_h(inf, key->heap); + + return err; +} +#endif +#endif /* !WOLFSSL_ATECC508A && !WOLFSSL_CRYPTOCELL*/ + + +/* perform sanity checks on ecc key validity, 0 on success */ +int wc_ecc_check_key(ecc_key* key) +{ + int err; +#ifndef WOLFSSL_SP_MATH +#if !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_CRYPTOCELL) + mp_int* b = NULL; +#ifdef USE_ECC_B_PARAM + DECLARE_CURVE_SPECS(curve, 4); +#else +#ifndef WOLFSSL_SMALL_STACK + mp_int b_lcl; +#endif + DECLARE_CURVE_SPECS(curve, 3); +#endif /* USE_ECC_B_PARAM */ +#endif /* WOLFSSL_ATECC508A */ + + if (key == NULL) + return BAD_FUNC_ARG; + +#if defined(WOLFSSL_ATECC508A) || defined(WOLFSSL_CRYPTOCELL) + + err = 0; /* consider key check success on ATECC508A */ + +#else + #ifdef USE_ECC_B_PARAM + ALLOC_CURVE_SPECS(4); + #else + ALLOC_CURVE_SPECS(3); + #ifndef WOLFSSL_SMALL_STACK + b = &b_lcl; + #else + b = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_ECC); + if (b == NULL) { + FREE_CURVE_SPECS(); + return MEMORY_E; + } + #endif + XMEMSET(b, 0, sizeof(mp_int)); + #endif + + /* SP 800-56Ar3, section 5.6.2.3.3, process step 1 */ + /* pubkey point cannot be at infinity */ + if (wc_ecc_point_is_at_infinity(&key->pubkey)) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(b, key->heap, DYNAMIC_TYPE_ECC); + #endif + FREE_CURVE_SPECS(); + return ECC_INF_E; + } + + /* load curve info */ + err = wc_ecc_curve_load(key->dp, &curve, (ECC_CURVE_FIELD_PRIME | + ECC_CURVE_FIELD_AF | ECC_CURVE_FIELD_ORDER +#ifdef USE_ECC_B_PARAM + | ECC_CURVE_FIELD_BF +#endif + )); + +#ifndef USE_ECC_B_PARAM + /* load curve b parameter */ + if (err == MP_OKAY) + err = mp_init(b); + if (err == MP_OKAY) + err = mp_read_radix(b, key->dp->Bf, MP_RADIX_HEX); +#else + if (err == MP_OKAY) + b = curve->Bf; +#endif + + /* SP 800-56Ar3, section 5.6.2.3.3, process step 2 */ + /* Qx must be in the range [0, p-1] */ + if (err == MP_OKAY) { + if (mp_cmp(key->pubkey.x, curve->prime) != MP_LT) + err = ECC_OUT_OF_RANGE_E; + } + + /* Qy must be in the range [0, p-1] */ + if (err == MP_OKAY) { + if (mp_cmp(key->pubkey.y, curve->prime) != MP_LT) + err = ECC_OUT_OF_RANGE_E; + } + + /* SP 800-56Ar3, section 5.6.2.3.3, process steps 3 */ + /* make sure point is actually on curve */ + if (err == MP_OKAY) + err = wc_ecc_is_point(&key->pubkey, curve->Af, b, curve->prime); + + /* SP 800-56Ar3, section 5.6.2.3.3, process steps 4 */ + /* pubkey * order must be at infinity */ + if (err == MP_OKAY) + err = ecc_check_pubkey_order(key, &key->pubkey, curve->Af, curve->prime, + curve->order); + + /* SP 800-56Ar3, section 5.6.2.1.4, method (b) for ECC */ + /* private * base generator must equal pubkey */ + if (err == MP_OKAY && key->type == ECC_PRIVATEKEY) + err = ecc_check_privkey_gen(key, curve->Af, curve->prime); + + wc_ecc_curve_free(curve); + +#ifndef USE_ECC_B_PARAM + mp_clear(b); + #ifdef WOLFSSL_SMALL_STACK + XFREE(b, key->heap, DYNAMIC_TYPE_ECC); + #endif +#endif + + FREE_CURVE_SPECS(); + +#endif /* WOLFSSL_ATECC508A */ +#else + if (key == NULL) + return BAD_FUNC_ARG; + + /* pubkey point cannot be at infinity */ + if (key->idx != ECC_CUSTOM_IDX && ecc_sets[key->idx].id == ECC_SECP256R1) { + err = sp_ecc_check_key_256(key->pubkey.x, key->pubkey.y, &key->k, + key->heap); + } + else + err = WC_KEY_SIZE_E; +#endif + + return err; +} + +#ifdef HAVE_ECC_KEY_IMPORT +/* import public ECC key in ANSI X9.63 format */ +int wc_ecc_import_x963_ex(const byte* in, word32 inLen, ecc_key* key, + int curve_id) +{ + int err = MP_OKAY; + int compressed = 0; + int keysize = 0; + byte pointType; + + if (in == NULL || key == NULL) + return BAD_FUNC_ARG; + + /* must be odd */ + if ((inLen & 1) == 0) { + return ECC_BAD_ARG_E; + } + + /* make sure required variables are reset */ + wc_ecc_reset(key); + + /* init key */ + #ifdef ALT_ECC_SIZE + key->pubkey.x = (mp_int*)&key->pubkey.xyz[0]; + key->pubkey.y = (mp_int*)&key->pubkey.xyz[1]; + key->pubkey.z = (mp_int*)&key->pubkey.xyz[2]; + alt_fp_init(key->pubkey.x); + alt_fp_init(key->pubkey.y); + alt_fp_init(key->pubkey.z); + err = mp_init(&key->k); + #else + err = mp_init_multi(&key->k, + key->pubkey.x, key->pubkey.y, key->pubkey.z, NULL, NULL); + #endif + if (err != MP_OKAY) + return MEMORY_E; + + /* check for point type (4, 2, or 3) */ + pointType = in[0]; + if (pointType != ECC_POINT_UNCOMP && pointType != ECC_POINT_COMP_EVEN && + pointType != ECC_POINT_COMP_ODD) { + err = ASN_PARSE_E; + } + + if (pointType == ECC_POINT_COMP_EVEN || pointType == ECC_POINT_COMP_ODD) { + #ifdef HAVE_COMP_KEY + compressed = 1; + #else + err = NOT_COMPILED_IN; + #endif + } + + /* adjust to skip first byte */ + inLen -= 1; + in += 1; + +#ifdef WOLFSSL_ATECC508A + /* For SECP256R1 only save raw public key for hardware */ + if (curve_id == ECC_SECP256R1 && !compressed && + inLen <= sizeof(key->pubkey_raw)) { + XMEMCPY(key->pubkey_raw, (byte*)in, inLen); + } +#endif + + if (err == MP_OKAY) { + #ifdef HAVE_COMP_KEY + /* adjust inLen if compressed */ + if (compressed) + inLen = inLen*2 + 1; /* used uncompressed len */ + #endif + + /* determine key size */ + keysize = (inLen>>1); + err = wc_ecc_set_curve(key, keysize, curve_id); + key->type = ECC_PUBLICKEY; + } + + /* read data */ + if (err == MP_OKAY) + err = mp_read_unsigned_bin(key->pubkey.x, (byte*)in, keysize); + +#ifdef HAVE_COMP_KEY + if (err == MP_OKAY && compressed == 1) { /* build y */ +#ifndef WOLFSSL_SP_MATH + mp_int t1, t2; + int did_init = 0; + + DECLARE_CURVE_SPECS(curve, 3); + ALLOC_CURVE_SPECS(3); + + if (mp_init_multi(&t1, &t2, NULL, NULL, NULL, NULL) != MP_OKAY) + err = MEMORY_E; + else + did_init = 1; + + /* load curve info */ + if (err == MP_OKAY) + err = wc_ecc_curve_load(key->dp, &curve, + (ECC_CURVE_FIELD_PRIME | ECC_CURVE_FIELD_AF | + ECC_CURVE_FIELD_BF)); + + /* compute x^3 */ + if (err == MP_OKAY) + err = mp_sqr(key->pubkey.x, &t1); + if (err == MP_OKAY) + err = mp_mulmod(&t1, key->pubkey.x, curve->prime, &t1); + + /* compute x^3 + a*x */ + if (err == MP_OKAY) + err = mp_mulmod(curve->Af, key->pubkey.x, curve->prime, &t2); + if (err == MP_OKAY) + err = mp_add(&t1, &t2, &t1); + + /* compute x^3 + a*x + b */ + if (err == MP_OKAY) + err = mp_add(&t1, curve->Bf, &t1); + + /* compute sqrt(x^3 + a*x + b) */ + if (err == MP_OKAY) + err = mp_sqrtmod_prime(&t1, curve->prime, &t2); + + /* adjust y */ + if (err == MP_OKAY) { + if ((mp_isodd(&t2) == MP_YES && pointType == ECC_POINT_COMP_ODD) || + (mp_isodd(&t2) == MP_NO && pointType == ECC_POINT_COMP_EVEN)) { + err = mp_mod(&t2, curve->prime, &t2); + } + else { + err = mp_submod(curve->prime, &t2, curve->prime, &t2); + } + if (err == MP_OKAY) + err = mp_copy(&t2, key->pubkey.y); + } + + if (did_init) { + mp_clear(&t2); + mp_clear(&t1); + } + + wc_ecc_curve_free(curve); + FREE_CURVE_SPECS(); +#else + sp_ecc_uncompress_256(key->pubkey.x, pointType, key->pubkey.y); +#endif + } +#endif /* HAVE_COMP_KEY */ + + if (err == MP_OKAY && compressed == 0) + err = mp_read_unsigned_bin(key->pubkey.y, (byte*)in + keysize, keysize); + if (err == MP_OKAY) + err = mp_set(key->pubkey.z, 1); + +#ifdef WOLFSSL_VALIDATE_ECC_IMPORT + if (err == MP_OKAY) + err = wc_ecc_check_key(key); +#endif + + if (err != MP_OKAY) { + mp_clear(key->pubkey.x); + mp_clear(key->pubkey.y); + mp_clear(key->pubkey.z); + mp_clear(&key->k); + } + + return err; +} + +int wc_ecc_import_x963(const byte* in, word32 inLen, ecc_key* key) +{ + return wc_ecc_import_x963_ex(in, inLen, key, ECC_CURVE_DEF); +} +#endif /* HAVE_ECC_KEY_IMPORT */ + +#ifdef HAVE_ECC_KEY_EXPORT + +/* export ecc key to component form, d is optional if only exporting public + * encType is WC_TYPE_UNSIGNED_BIN or WC_TYPE_HEX_STR + * return MP_OKAY on success */ +int wc_ecc_export_ex(ecc_key* key, byte* qx, word32* qxLen, + byte* qy, word32* qyLen, byte* d, word32* dLen, int encType) +{ + int err = 0; + word32 keySz; + + if (key == NULL) { + return BAD_FUNC_ARG; + } + + if (wc_ecc_is_valid_idx(key->idx) == 0) { + return ECC_BAD_ARG_E; + } + keySz = key->dp->size; + + /* private key, d */ + if (d != NULL) { + if (dLen == NULL || + (key->type != ECC_PRIVATEKEY && key->type != ECC_PRIVATEKEY_ONLY)) + return BAD_FUNC_ARG; + + #ifdef WOLFSSL_ATECC508A + /* Hardware cannot export private portion */ + return NOT_COMPILED_IN; + #else + err = wc_export_int(&key->k, d, dLen, keySz, encType); + if (err != MP_OKAY) + return err; + #endif + } + + /* public x component */ + if (qx != NULL) { + if (qxLen == NULL || key->type == ECC_PRIVATEKEY_ONLY) + return BAD_FUNC_ARG; + + err = wc_export_int(key->pubkey.x, qx, qxLen, keySz, encType); + if (err != MP_OKAY) + return err; + } + + /* public y component */ + if (qy != NULL) { + if (qyLen == NULL || key->type == ECC_PRIVATEKEY_ONLY) + return BAD_FUNC_ARG; + + err = wc_export_int(key->pubkey.y, qy, qyLen, keySz, encType); + if (err != MP_OKAY) + return err; + } + + return err; +} + + +/* export ecc private key only raw, outLen is in/out size as unsigned bin + return MP_OKAY on success */ +int wc_ecc_export_private_only(ecc_key* key, byte* out, word32* outLen) +{ + if (out == NULL || outLen == NULL) { + return BAD_FUNC_ARG; + } + + return wc_ecc_export_ex(key, NULL, NULL, NULL, NULL, out, outLen, + WC_TYPE_UNSIGNED_BIN); +} + +/* export public key to raw elements including public (Qx,Qy) as unsigned bin + * return MP_OKAY on success, negative on error */ +int wc_ecc_export_public_raw(ecc_key* key, byte* qx, word32* qxLen, + byte* qy, word32* qyLen) +{ + if (qx == NULL || qxLen == NULL || qy == NULL || qyLen == NULL) { + return BAD_FUNC_ARG; + } + + return wc_ecc_export_ex(key, qx, qxLen, qy, qyLen, NULL, NULL, + WC_TYPE_UNSIGNED_BIN); +} + +/* export ecc key to raw elements including public (Qx,Qy) and + * private (d) as unsigned bin + * return MP_OKAY on success, negative on error */ +int wc_ecc_export_private_raw(ecc_key* key, byte* qx, word32* qxLen, + byte* qy, word32* qyLen, byte* d, word32* dLen) +{ + return wc_ecc_export_ex(key, qx, qxLen, qy, qyLen, d, dLen, + WC_TYPE_UNSIGNED_BIN); +} + +#endif /* HAVE_ECC_KEY_EXPORT */ + +#ifndef NO_ASN +#ifdef HAVE_ECC_KEY_IMPORT +/* import private key, public part optional if (pub) passed as NULL */ +int wc_ecc_import_private_key_ex(const byte* priv, word32 privSz, + const byte* pub, word32 pubSz, ecc_key* key, + int curve_id) +{ + int ret; + word32 idx = 0; +#if defined(WOLFSSL_CRYPTOCELL) + const CRYS_ECPKI_Domain_t* pDomain; + CRYS_ECPKI_BUILD_TempData_t tempBuff; +#endif + if (key == NULL || priv == NULL) + return BAD_FUNC_ARG; + + /* public optional, NULL if only importing private */ + if (pub != NULL) { + ret = wc_ecc_import_x963_ex(pub, pubSz, key, curve_id); + if (ret < 0) + ret = wc_EccPublicKeyDecode(pub, &idx, key, pubSz); + key->type = ECC_PRIVATEKEY; + } + else { + /* make sure required variables are reset */ + wc_ecc_reset(key); + + /* set key size */ + ret = wc_ecc_set_curve(key, privSz, curve_id); + key->type = ECC_PRIVATEKEY_ONLY; + } + + if (ret != 0) + return ret; + +#ifdef WOLFSSL_ATECC508A + /* Hardware does not support loading private keys */ + return NOT_COMPILED_IN; +#elif defined(WOLFSSL_CRYPTOCELL) + pDomain = CRYS_ECPKI_GetEcDomain(cc310_mapCurve(curve_id)); + + if (pub != NULL && pub[0] != '\0') { + /* create public key from external key buffer */ + ret = CRYS_ECPKI_BuildPublKeyFullCheck(pDomain, + (byte*)pub, + pubSz, + &key->ctx.pubKey, + &tempBuff); + + if (ret != SA_SILIB_RET_OK){ + WOLFSSL_MSG("CRYS_ECPKI_BuildPublKeyFullCheck failed"); + return ret; + } + } + /* import private key */ + if (priv != NULL && priv[0] != '\0') { + + /* Create private key from external key buffer*/ + ret = CRYS_ECPKI_BuildPrivKey(pDomain, + priv, + privSz, + &key->ctx.privKey); + + if (ret != SA_SILIB_RET_OK) { + WOLFSSL_MSG("CRYS_ECPKI_BuildPrivKey failed"); + return ret; + } + + ret = mp_read_unsigned_bin(&key->k, priv, privSz); + } + +#else + + ret = mp_read_unsigned_bin(&key->k, priv, privSz); +#ifdef HAVE_WOLF_BIGINT + if (ret == 0 && + wc_bigint_from_unsigned_bin(&key->k.raw, priv, privSz) != 0) { + mp_clear(&key->k); + ret = ASN_GETINT_E; + } +#endif /* HAVE_WOLF_BIGINT */ + + +#endif /* WOLFSSL_ATECC508A */ + +#ifdef WOLFSSL_VALIDATE_ECC_IMPORT + if ((pub != NULL) && (ret == MP_OKAY)) + /* public key needed to perform key validation */ + ret = ecc_check_privkey_gen_helper(key); +#endif + + return ret; +} + +/* ecc private key import, public key in ANSI X9.63 format, private raw */ +int wc_ecc_import_private_key(const byte* priv, word32 privSz, const byte* pub, + word32 pubSz, ecc_key* key) +{ + return wc_ecc_import_private_key_ex(priv, privSz, pub, pubSz, key, + ECC_CURVE_DEF); +} +#endif /* HAVE_ECC_KEY_IMPORT */ + +/** + Convert ECC R,S to signature + r R component of signature + s S component of signature + out DER-encoded ECDSA signature + outlen [in/out] output buffer size, output signature size + return MP_OKAY on success +*/ +int wc_ecc_rs_to_sig(const char* r, const char* s, byte* out, word32* outlen) +{ + int err; +#ifdef WOLFSSL_SMALL_STACK + mp_int* rtmp = NULL; + mp_int* stmp = NULL; +#else + mp_int rtmp[1]; + mp_int stmp[1]; +#endif + + if (r == NULL || s == NULL || out == NULL || outlen == NULL) + return ECC_BAD_ARG_E; + +#ifdef WOLFSSL_SMALL_STACK + rtmp = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + if (rtmp == NULL) + return MEMORY_E; + stmp = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + if (stmp == NULL) { + XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC); + return MEMORY_E; + } +#endif + + err = mp_init_multi(rtmp, stmp, NULL, NULL, NULL, NULL); + if (err != MP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(stmp, NULL, DYNAMIC_TYPE_ECC); + XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC); + #endif + return err; + } + + err = mp_read_radix(rtmp, r, MP_RADIX_HEX); + if (err == MP_OKAY) + err = mp_read_radix(stmp, s, MP_RADIX_HEX); + + /* convert mp_ints to ECDSA sig, initializes rtmp and stmp internally */ + if (err == MP_OKAY) + err = StoreECC_DSA_Sig(out, outlen, rtmp, stmp); + + if (err == MP_OKAY) { + if (mp_iszero(rtmp) == MP_YES || mp_iszero(stmp) == MP_YES) + err = MP_ZERO_E; + } + + mp_clear(rtmp); + mp_clear(stmp); +#ifdef WOLFSSL_SMALL_STACK + XFREE(stmp, NULL, DYNAMIC_TYPE_ECC); + XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/** + Convert ECC R,S raw unsigned bin to signature + r R component of signature + rSz R size + s S component of signature + sSz S size + out DER-encoded ECDSA signature + outlen [in/out] output buffer size, output signature size + return MP_OKAY on success +*/ +int wc_ecc_rs_raw_to_sig(const byte* r, word32 rSz, const byte* s, word32 sSz, + byte* out, word32* outlen) +{ + int err; +#ifdef WOLFSSL_SMALL_STACK + mp_int* rtmp = NULL; + mp_int* stmp = NULL; +#else + mp_int rtmp[1]; + mp_int stmp[1]; +#endif + + if (r == NULL || s == NULL || out == NULL || outlen == NULL) + return ECC_BAD_ARG_E; + +#ifdef WOLFSSL_SMALL_STACK + rtmp = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + if (rtmp == NULL) + return MEMORY_E; + stmp = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + if (stmp == NULL) { + XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC); + return MEMORY_E; + } +#endif + + err = mp_init_multi(rtmp, stmp, NULL, NULL, NULL, NULL); + if (err != MP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(stmp, NULL, DYNAMIC_TYPE_ECC); + XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC); + #endif + return err; + } + + err = mp_read_unsigned_bin(rtmp, r, rSz); + if (err == MP_OKAY) + err = mp_read_unsigned_bin(stmp, s, sSz); + + /* convert mp_ints to ECDSA sig, initializes rtmp and stmp internally */ + if (err == MP_OKAY) + err = StoreECC_DSA_Sig(out, outlen, rtmp, stmp); + + if (err == MP_OKAY) { + if (mp_iszero(rtmp) == MP_YES || mp_iszero(stmp) == MP_YES) + err = MP_ZERO_E; + } + + mp_clear(rtmp); + mp_clear(stmp); +#ifdef WOLFSSL_SMALL_STACK + XFREE(stmp, NULL, DYNAMIC_TYPE_ECC); + XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/** + Convert ECC signature to R,S + sig DER-encoded ECDSA signature + sigLen length of signature in octets + r R component of signature + rLen [in/out] output "r" buffer size, output "r" size + s S component of signature + sLen [in/out] output "s" buffer size, output "s" size + return MP_OKAY on success, negative on error +*/ +int wc_ecc_sig_to_rs(const byte* sig, word32 sigLen, byte* r, word32* rLen, + byte* s, word32* sLen) +{ + int err; + int tmp_valid = 0; + word32 x = 0; +#ifdef WOLFSSL_SMALL_STACK + mp_int* rtmp = NULL; + mp_int* stmp = NULL; +#else + mp_int rtmp[1]; + mp_int stmp[1]; +#endif + + if (sig == NULL || r == NULL || rLen == NULL || s == NULL || sLen == NULL) + return ECC_BAD_ARG_E; + +#ifdef WOLFSSL_SMALL_STACK + rtmp = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + if (rtmp == NULL) + return MEMORY_E; + stmp = (mp_int*)XMALLOC(sizeof(mp_int), NULL, DYNAMIC_TYPE_ECC); + if (stmp == NULL) { + XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC); + return MEMORY_E; + } +#endif + + err = DecodeECC_DSA_Sig(sig, sigLen, rtmp, stmp); + + /* rtmp and stmp are initialized */ + if (err == MP_OKAY) { + tmp_valid = 1; + } + + /* extract r */ + if (err == MP_OKAY) { + x = mp_unsigned_bin_size(rtmp); + if (*rLen < x) + err = BUFFER_E; + + if (err == MP_OKAY) { + *rLen = x; + err = mp_to_unsigned_bin(rtmp, r); + } + } + + /* extract s */ + if (err == MP_OKAY) { + x = mp_unsigned_bin_size(stmp); + if (*sLen < x) + err = BUFFER_E; + + if (err == MP_OKAY) { + *sLen = x; + err = mp_to_unsigned_bin(stmp, s); + } + } + + if (tmp_valid) { + mp_clear(rtmp); + mp_clear(stmp); + } +#ifdef WOLFSSL_SMALL_STACK + XFREE(stmp, NULL, DYNAMIC_TYPE_ECC); + XFREE(rtmp, NULL, DYNAMIC_TYPE_ECC); +#endif + + return err; +} +#endif /* !NO_ASN */ + +#ifdef HAVE_ECC_KEY_IMPORT +static int wc_ecc_import_raw_private(ecc_key* key, const char* qx, + const char* qy, const char* d, int curve_id, int encType) +{ + int err = MP_OKAY; +#if defined(WOLFSSL_CRYPTOCELL) + const CRYS_ECPKI_Domain_t* pDomain; + CRYS_ECPKI_BUILD_TempData_t tempBuff; + byte key_raw[ECC_MAX_CRYPTO_HW_SIZE*2 + 1]; + word32 keySz = key->dp->size; +#endif + /* if d is NULL, only import as public key using Qx,Qy */ + if (key == NULL || qx == NULL || qy == NULL) { + return BAD_FUNC_ARG; + } + + /* make sure required variables are reset */ + wc_ecc_reset(key); + + /* set curve type and index */ + err = wc_ecc_set_curve(key, 0, curve_id); + if (err != 0) { + return err; + } + + /* init key */ +#ifdef ALT_ECC_SIZE + key->pubkey.x = (mp_int*)&key->pubkey.xyz[0]; + key->pubkey.y = (mp_int*)&key->pubkey.xyz[1]; + key->pubkey.z = (mp_int*)&key->pubkey.xyz[2]; + alt_fp_init(key->pubkey.x); + alt_fp_init(key->pubkey.y); + alt_fp_init(key->pubkey.z); + err = mp_init(&key->k); +#else + err = mp_init_multi(&key->k, key->pubkey.x, key->pubkey.y, key->pubkey.z, + NULL, NULL); +#endif + if (err != MP_OKAY) + return MEMORY_E; + + /* read Qx */ + if (err == MP_OKAY) { + if (encType == WC_TYPE_HEX_STR) + err = mp_read_radix(key->pubkey.x, qx, MP_RADIX_HEX); + else + err = mp_read_unsigned_bin(key->pubkey.x, (const byte*)qx, + key->dp->size); + } + + /* read Qy */ + if (err == MP_OKAY) { + if (encType == WC_TYPE_HEX_STR) + err = mp_read_radix(key->pubkey.y, qy, MP_RADIX_HEX); + else + err = mp_read_unsigned_bin(key->pubkey.y, (const byte*)qy, + key->dp->size); + + } + + if (err == MP_OKAY) + err = mp_set(key->pubkey.z, 1); + +#ifdef WOLFSSL_ATECC508A + /* For SECP256R1 only save raw public key for hardware */ + if (err == MP_OKAY && curve_id == ECC_SECP256R1) { + word32 keySz = key->dp->size; + err = wc_export_int(key->pubkey.x, key->pubkey_raw, + &keySz, keySz, WC_TYPE_UNSIGNED_BIN); + if (err == MP_OKAY) + err = wc_export_int(key->pubkey.y, &key->pubkey_raw[keySz], + &keySz, keySz, WC_TYPE_UNSIGNED_BIN); + } +#elif defined(WOLFSSL_CRYPTOCELL) + if (err == MP_OKAY) { + key_raw[0] = ECC_POINT_UNCOMP; + keySz = key->dp->size; + err = wc_export_int(key->pubkey.x, &key_raw[1], &keySz, keySz, + WC_TYPE_UNSIGNED_BIN); + if (err == MP_OKAY) + err = wc_export_int(key->pubkey.y, &key_raw[1+keySz], + &keySz, keySz, WC_TYPE_UNSIGNED_BIN); + + + pDomain = CRYS_ECPKI_GetEcDomain(cc310_mapCurve(curve_id)); + + /* create public key from external key buffer */ + err = CRYS_ECPKI_BuildPublKeyFullCheck(pDomain, + key_raw, + keySz*2 + 1, + &key->ctx.pubKey, + &tempBuff); + + if (err != SA_SILIB_RET_OK){ + WOLFSSL_MSG("CRYS_ECPKI_BuildPublKeyFullCheck failed"); + return err; + } + } + +#endif + + /* import private key */ + if (err == MP_OKAY) { + if (d != NULL && d[0] != '\0') { + #ifdef WOLFSSL_ATECC508A + /* Hardware doesn't support loading private key */ + err = NOT_COMPILED_IN; + + #elif defined(WOLFSSL_CRYPTOCELL) + + key->type = ECC_PRIVATEKEY; + + if (encType == WC_TYPE_HEX_STR) + err = mp_read_radix(&key->k, d, MP_RADIX_HEX); + else + err = mp_read_unsigned_bin(&key->k, (const byte*)d, + key->dp->size); + + err = wc_export_int(&key->k, &key_raw[0], &keySz, keySz, + WC_TYPE_UNSIGNED_BIN); + + /* Create private key from external key buffer*/ + err = CRYS_ECPKI_BuildPrivKey(pDomain, + key_raw, + keySz, + &key->ctx.privKey); + + if (err != SA_SILIB_RET_OK){ + WOLFSSL_MSG("CRYS_ECPKI_BuildPrivKey failed"); + return err; + } + + #else + key->type = ECC_PRIVATEKEY; + + if (encType == WC_TYPE_HEX_STR) + err = mp_read_radix(&key->k, d, MP_RADIX_HEX); + else + err = mp_read_unsigned_bin(&key->k, (const byte*)d, + key->dp->size); + #endif /* WOLFSSL_ATECC508A */ + } else { + key->type = ECC_PUBLICKEY; + } + } + +#ifdef WOLFSSL_VALIDATE_ECC_IMPORT + if (err == MP_OKAY) + err = wc_ecc_check_key(key); +#endif + + if (err != MP_OKAY) { + mp_clear(key->pubkey.x); + mp_clear(key->pubkey.y); + mp_clear(key->pubkey.z); + mp_clear(&key->k); + } + + return err; +} + +/** + Import raw ECC key + key The destination ecc_key structure + qx x component of the public key, as ASCII hex string + qy y component of the public key, as ASCII hex string + d private key, as ASCII hex string, optional if importing public + key only + dp Custom ecc_set_type + return MP_OKAY on success +*/ +int wc_ecc_import_raw_ex(ecc_key* key, const char* qx, const char* qy, + const char* d, int curve_id) +{ + return wc_ecc_import_raw_private(key, qx, qy, d, curve_id, + WC_TYPE_HEX_STR); + +} + +/* Import x, y and optional private (d) as unsigned binary */ +int wc_ecc_import_unsigned(ecc_key* key, byte* qx, byte* qy, + byte* d, int curve_id) +{ + return wc_ecc_import_raw_private(key, (const char*)qx, (const char*)qy, + (const char*)d, curve_id, WC_TYPE_UNSIGNED_BIN); +} + +/** + Import raw ECC key + key The destination ecc_key structure + qx x component of the public key, as ASCII hex string + qy y component of the public key, as ASCII hex string + d private key, as ASCII hex string, optional if importing public + key only + curveName ECC curve name, from ecc_sets[] + return MP_OKAY on success +*/ +int wc_ecc_import_raw(ecc_key* key, const char* qx, const char* qy, + const char* d, const char* curveName) +{ + int err, x; + + /* if d is NULL, only import as public key using Qx,Qy */ + if (key == NULL || qx == NULL || qy == NULL || curveName == NULL) { + return BAD_FUNC_ARG; + } + + /* set curve type and index */ + for (x = 0; ecc_sets[x].size != 0; x++) { + if (XSTRNCMP(ecc_sets[x].name, curveName, + XSTRLEN(curveName)) == 0) { + break; + } + } + + if (ecc_sets[x].size == 0) { + WOLFSSL_MSG("ecc_set curve name not found"); + err = ASN_PARSE_E; + } else { + return wc_ecc_import_raw_private(key, qx, qy, d, ecc_sets[x].id, + WC_TYPE_HEX_STR); + } + + return err; +} +#endif /* HAVE_ECC_KEY_IMPORT */ + +/* key size in octets */ +int wc_ecc_size(ecc_key* key) +{ + if (key == NULL) + return 0; + + return key->dp->size; +} + +/* maximum signature size based on key size */ +int wc_ecc_sig_size_calc(int sz) +{ + int maxSigSz = 0; + + /* calculate based on key bits */ + /* maximum possible signature header size is 7 bytes plus 2 bytes padding */ + maxSigSz = (sz * 2) + SIG_HEADER_SZ + ECC_MAX_PAD_SZ; + + /* if total length is less than 128 + SEQ(1)+LEN(1) then subtract 1 */ + if (maxSigSz < (128 + 2)) { + maxSigSz -= 1; + } + + return maxSigSz; +} + +/* maximum signature size based on actual key curve */ +int wc_ecc_sig_size(ecc_key* key) +{ + int maxSigSz; + int orderBits, keySz; + + if (key == NULL || key->dp == NULL) + return 0; + + /* the signature r and s will always be less than order */ + /* if the order MSB (top bit of byte) is set then ASN encoding needs + extra byte for r and s, so add 2 */ + keySz = key->dp->size; + orderBits = wc_ecc_get_curve_order_bit_count(key->dp); + /* maximum possible signature header size is 7 bytes */ + maxSigSz = (keySz * 2) + SIG_HEADER_SZ; + if ((orderBits % 8) == 0) { + /* MSB can be set, so add 2 */ + maxSigSz += ECC_MAX_PAD_SZ; + } + /* if total length is less than 128 + SEQ(1)+LEN(1) then subtract 1 */ + if (maxSigSz < (128 + 2)) { + maxSigSz -= 1; + } + + return maxSigSz; +} + + +#ifdef FP_ECC + +/* fixed point ECC cache */ +/* number of entries in the cache */ +#ifndef FP_ENTRIES + #define FP_ENTRIES 15 +#endif + +/* number of bits in LUT */ +#ifndef FP_LUT + #define FP_LUT 8U +#endif + +#ifdef ECC_SHAMIR + /* Sharmir requires a bigger LUT, TAO */ + #if (FP_LUT > 12) || (FP_LUT < 4) + #error FP_LUT must be between 4 and 12 inclusively + #endif +#else + #if (FP_LUT > 12) || (FP_LUT < 2) + #error FP_LUT must be between 2 and 12 inclusively + #endif +#endif + + +#ifndef WOLFSSL_SP_MATH + +/** Our FP cache */ +typedef struct { + ecc_point* g; /* cached COPY of base point */ + ecc_point* LUT[1U< 6 + { 1, 0, 0 }, { 2, 1, 64 }, { 2, 2, 64 }, { 3, 3, 64 }, { 2, 4, 64 }, { 3, 5, 64 }, { 3, 6, 64 }, { 4, 7, 64 }, + { 2, 8, 64 }, { 3, 9, 64 }, { 3, 10, 64 }, { 4, 11, 64 }, { 3, 12, 64 }, { 4, 13, 64 }, { 4, 14, 64 }, { 5, 15, 64 }, + { 2, 16, 64 }, { 3, 17, 64 }, { 3, 18, 64 }, { 4, 19, 64 }, { 3, 20, 64 }, { 4, 21, 64 }, { 4, 22, 64 }, { 5, 23, 64 }, + { 3, 24, 64 }, { 4, 25, 64 }, { 4, 26, 64 }, { 5, 27, 64 }, { 4, 28, 64 }, { 5, 29, 64 }, { 5, 30, 64 }, { 6, 31, 64 }, + { 2, 32, 64 }, { 3, 33, 64 }, { 3, 34, 64 }, { 4, 35, 64 }, { 3, 36, 64 }, { 4, 37, 64 }, { 4, 38, 64 }, { 5, 39, 64 }, + { 3, 40, 64 }, { 4, 41, 64 }, { 4, 42, 64 }, { 5, 43, 64 }, { 4, 44, 64 }, { 5, 45, 64 }, { 5, 46, 64 }, { 6, 47, 64 }, + { 3, 48, 64 }, { 4, 49, 64 }, { 4, 50, 64 }, { 5, 51, 64 }, { 4, 52, 64 }, { 5, 53, 64 }, { 5, 54, 64 }, { 6, 55, 64 }, + { 4, 56, 64 }, { 5, 57, 64 }, { 5, 58, 64 }, { 6, 59, 64 }, { 5, 60, 64 }, { 6, 61, 64 }, { 6, 62, 64 }, { 7, 63, 64 }, +#if FP_LUT > 7 + { 1, 0, 0 }, { 2, 1, 128 }, { 2, 2, 128 }, { 3, 3, 128 }, { 2, 4, 128 }, { 3, 5, 128 }, { 3, 6, 128 }, { 4, 7, 128 }, + { 2, 8, 128 }, { 3, 9, 128 }, { 3, 10, 128 }, { 4, 11, 128 }, { 3, 12, 128 }, { 4, 13, 128 }, { 4, 14, 128 }, { 5, 15, 128 }, + { 2, 16, 128 }, { 3, 17, 128 }, { 3, 18, 128 }, { 4, 19, 128 }, { 3, 20, 128 }, { 4, 21, 128 }, { 4, 22, 128 }, { 5, 23, 128 }, + { 3, 24, 128 }, { 4, 25, 128 }, { 4, 26, 128 }, { 5, 27, 128 }, { 4, 28, 128 }, { 5, 29, 128 }, { 5, 30, 128 }, { 6, 31, 128 }, + { 2, 32, 128 }, { 3, 33, 128 }, { 3, 34, 128 }, { 4, 35, 128 }, { 3, 36, 128 }, { 4, 37, 128 }, { 4, 38, 128 }, { 5, 39, 128 }, + { 3, 40, 128 }, { 4, 41, 128 }, { 4, 42, 128 }, { 5, 43, 128 }, { 4, 44, 128 }, { 5, 45, 128 }, { 5, 46, 128 }, { 6, 47, 128 }, + { 3, 48, 128 }, { 4, 49, 128 }, { 4, 50, 128 }, { 5, 51, 128 }, { 4, 52, 128 }, { 5, 53, 128 }, { 5, 54, 128 }, { 6, 55, 128 }, + { 4, 56, 128 }, { 5, 57, 128 }, { 5, 58, 128 }, { 6, 59, 128 }, { 5, 60, 128 }, { 6, 61, 128 }, { 6, 62, 128 }, { 7, 63, 128 }, + { 2, 64, 128 }, { 3, 65, 128 }, { 3, 66, 128 }, { 4, 67, 128 }, { 3, 68, 128 }, { 4, 69, 128 }, { 4, 70, 128 }, { 5, 71, 128 }, + { 3, 72, 128 }, { 4, 73, 128 }, { 4, 74, 128 }, { 5, 75, 128 }, { 4, 76, 128 }, { 5, 77, 128 }, { 5, 78, 128 }, { 6, 79, 128 }, + { 3, 80, 128 }, { 4, 81, 128 }, { 4, 82, 128 }, { 5, 83, 128 }, { 4, 84, 128 }, { 5, 85, 128 }, { 5, 86, 128 }, { 6, 87, 128 }, + { 4, 88, 128 }, { 5, 89, 128 }, { 5, 90, 128 }, { 6, 91, 128 }, { 5, 92, 128 }, { 6, 93, 128 }, { 6, 94, 128 }, { 7, 95, 128 }, + { 3, 96, 128 }, { 4, 97, 128 }, { 4, 98, 128 }, { 5, 99, 128 }, { 4, 100, 128 }, { 5, 101, 128 }, { 5, 102, 128 }, { 6, 103, 128 }, + { 4, 104, 128 }, { 5, 105, 128 }, { 5, 106, 128 }, { 6, 107, 128 }, { 5, 108, 128 }, { 6, 109, 128 }, { 6, 110, 128 }, { 7, 111, 128 }, + { 4, 112, 128 }, { 5, 113, 128 }, { 5, 114, 128 }, { 6, 115, 128 }, { 5, 116, 128 }, { 6, 117, 128 }, { 6, 118, 128 }, { 7, 119, 128 }, + { 5, 120, 128 }, { 6, 121, 128 }, { 6, 122, 128 }, { 7, 123, 128 }, { 6, 124, 128 }, { 7, 125, 128 }, { 7, 126, 128 }, { 8, 127, 128 }, +#if FP_LUT > 8 + { 1, 0, 0 }, { 2, 1, 256 }, { 2, 2, 256 }, { 3, 3, 256 }, { 2, 4, 256 }, { 3, 5, 256 }, { 3, 6, 256 }, { 4, 7, 256 }, + { 2, 8, 256 }, { 3, 9, 256 }, { 3, 10, 256 }, { 4, 11, 256 }, { 3, 12, 256 }, { 4, 13, 256 }, { 4, 14, 256 }, { 5, 15, 256 }, + { 2, 16, 256 }, { 3, 17, 256 }, { 3, 18, 256 }, { 4, 19, 256 }, { 3, 20, 256 }, { 4, 21, 256 }, { 4, 22, 256 }, { 5, 23, 256 }, + { 3, 24, 256 }, { 4, 25, 256 }, { 4, 26, 256 }, { 5, 27, 256 }, { 4, 28, 256 }, { 5, 29, 256 }, { 5, 30, 256 }, { 6, 31, 256 }, + { 2, 32, 256 }, { 3, 33, 256 }, { 3, 34, 256 }, { 4, 35, 256 }, { 3, 36, 256 }, { 4, 37, 256 }, { 4, 38, 256 }, { 5, 39, 256 }, + { 3, 40, 256 }, { 4, 41, 256 }, { 4, 42, 256 }, { 5, 43, 256 }, { 4, 44, 256 }, { 5, 45, 256 }, { 5, 46, 256 }, { 6, 47, 256 }, + { 3, 48, 256 }, { 4, 49, 256 }, { 4, 50, 256 }, { 5, 51, 256 }, { 4, 52, 256 }, { 5, 53, 256 }, { 5, 54, 256 }, { 6, 55, 256 }, + { 4, 56, 256 }, { 5, 57, 256 }, { 5, 58, 256 }, { 6, 59, 256 }, { 5, 60, 256 }, { 6, 61, 256 }, { 6, 62, 256 }, { 7, 63, 256 }, + { 2, 64, 256 }, { 3, 65, 256 }, { 3, 66, 256 }, { 4, 67, 256 }, { 3, 68, 256 }, { 4, 69, 256 }, { 4, 70, 256 }, { 5, 71, 256 }, + { 3, 72, 256 }, { 4, 73, 256 }, { 4, 74, 256 }, { 5, 75, 256 }, { 4, 76, 256 }, { 5, 77, 256 }, { 5, 78, 256 }, { 6, 79, 256 }, + { 3, 80, 256 }, { 4, 81, 256 }, { 4, 82, 256 }, { 5, 83, 256 }, { 4, 84, 256 }, { 5, 85, 256 }, { 5, 86, 256 }, { 6, 87, 256 }, + { 4, 88, 256 }, { 5, 89, 256 }, { 5, 90, 256 }, { 6, 91, 256 }, { 5, 92, 256 }, { 6, 93, 256 }, { 6, 94, 256 }, { 7, 95, 256 }, + { 3, 96, 256 }, { 4, 97, 256 }, { 4, 98, 256 }, { 5, 99, 256 }, { 4, 100, 256 }, { 5, 101, 256 }, { 5, 102, 256 }, { 6, 103, 256 }, + { 4, 104, 256 }, { 5, 105, 256 }, { 5, 106, 256 }, { 6, 107, 256 }, { 5, 108, 256 }, { 6, 109, 256 }, { 6, 110, 256 }, { 7, 111, 256 }, + { 4, 112, 256 }, { 5, 113, 256 }, { 5, 114, 256 }, { 6, 115, 256 }, { 5, 116, 256 }, { 6, 117, 256 }, { 6, 118, 256 }, { 7, 119, 256 }, + { 5, 120, 256 }, { 6, 121, 256 }, { 6, 122, 256 }, { 7, 123, 256 }, { 6, 124, 256 }, { 7, 125, 256 }, { 7, 126, 256 }, { 8, 127, 256 }, + { 2, 128, 256 }, { 3, 129, 256 }, { 3, 130, 256 }, { 4, 131, 256 }, { 3, 132, 256 }, { 4, 133, 256 }, { 4, 134, 256 }, { 5, 135, 256 }, + { 3, 136, 256 }, { 4, 137, 256 }, { 4, 138, 256 }, { 5, 139, 256 }, { 4, 140, 256 }, { 5, 141, 256 }, { 5, 142, 256 }, { 6, 143, 256 }, + { 3, 144, 256 }, { 4, 145, 256 }, { 4, 146, 256 }, { 5, 147, 256 }, { 4, 148, 256 }, { 5, 149, 256 }, { 5, 150, 256 }, { 6, 151, 256 }, + { 4, 152, 256 }, { 5, 153, 256 }, { 5, 154, 256 }, { 6, 155, 256 }, { 5, 156, 256 }, { 6, 157, 256 }, { 6, 158, 256 }, { 7, 159, 256 }, + { 3, 160, 256 }, { 4, 161, 256 }, { 4, 162, 256 }, { 5, 163, 256 }, { 4, 164, 256 }, { 5, 165, 256 }, { 5, 166, 256 }, { 6, 167, 256 }, + { 4, 168, 256 }, { 5, 169, 256 }, { 5, 170, 256 }, { 6, 171, 256 }, { 5, 172, 256 }, { 6, 173, 256 }, { 6, 174, 256 }, { 7, 175, 256 }, + { 4, 176, 256 }, { 5, 177, 256 }, { 5, 178, 256 }, { 6, 179, 256 }, { 5, 180, 256 }, { 6, 181, 256 }, { 6, 182, 256 }, { 7, 183, 256 }, + { 5, 184, 256 }, { 6, 185, 256 }, { 6, 186, 256 }, { 7, 187, 256 }, { 6, 188, 256 }, { 7, 189, 256 }, { 7, 190, 256 }, { 8, 191, 256 }, + { 3, 192, 256 }, { 4, 193, 256 }, { 4, 194, 256 }, { 5, 195, 256 }, { 4, 196, 256 }, { 5, 197, 256 }, { 5, 198, 256 }, { 6, 199, 256 }, + { 4, 200, 256 }, { 5, 201, 256 }, { 5, 202, 256 }, { 6, 203, 256 }, { 5, 204, 256 }, { 6, 205, 256 }, { 6, 206, 256 }, { 7, 207, 256 }, + { 4, 208, 256 }, { 5, 209, 256 }, { 5, 210, 256 }, { 6, 211, 256 }, { 5, 212, 256 }, { 6, 213, 256 }, { 6, 214, 256 }, { 7, 215, 256 }, + { 5, 216, 256 }, { 6, 217, 256 }, { 6, 218, 256 }, { 7, 219, 256 }, { 6, 220, 256 }, { 7, 221, 256 }, { 7, 222, 256 }, { 8, 223, 256 }, + { 4, 224, 256 }, { 5, 225, 256 }, { 5, 226, 256 }, { 6, 227, 256 }, { 5, 228, 256 }, { 6, 229, 256 }, { 6, 230, 256 }, { 7, 231, 256 }, + { 5, 232, 256 }, { 6, 233, 256 }, { 6, 234, 256 }, { 7, 235, 256 }, { 6, 236, 256 }, { 7, 237, 256 }, { 7, 238, 256 }, { 8, 239, 256 }, + { 5, 240, 256 }, { 6, 241, 256 }, { 6, 242, 256 }, { 7, 243, 256 }, { 6, 244, 256 }, { 7, 245, 256 }, { 7, 246, 256 }, { 8, 247, 256 }, + { 6, 248, 256 }, { 7, 249, 256 }, { 7, 250, 256 }, { 8, 251, 256 }, { 7, 252, 256 }, { 8, 253, 256 }, { 8, 254, 256 }, { 9, 255, 256 }, +#if FP_LUT > 9 + { 1, 0, 0 }, { 2, 1, 512 }, { 2, 2, 512 }, { 3, 3, 512 }, { 2, 4, 512 }, { 3, 5, 512 }, { 3, 6, 512 }, { 4, 7, 512 }, + { 2, 8, 512 }, { 3, 9, 512 }, { 3, 10, 512 }, { 4, 11, 512 }, { 3, 12, 512 }, { 4, 13, 512 }, { 4, 14, 512 }, { 5, 15, 512 }, + { 2, 16, 512 }, { 3, 17, 512 }, { 3, 18, 512 }, { 4, 19, 512 }, { 3, 20, 512 }, { 4, 21, 512 }, { 4, 22, 512 }, { 5, 23, 512 }, + { 3, 24, 512 }, { 4, 25, 512 }, { 4, 26, 512 }, { 5, 27, 512 }, { 4, 28, 512 }, { 5, 29, 512 }, { 5, 30, 512 }, { 6, 31, 512 }, + { 2, 32, 512 }, { 3, 33, 512 }, { 3, 34, 512 }, { 4, 35, 512 }, { 3, 36, 512 }, { 4, 37, 512 }, { 4, 38, 512 }, { 5, 39, 512 }, + { 3, 40, 512 }, { 4, 41, 512 }, { 4, 42, 512 }, { 5, 43, 512 }, { 4, 44, 512 }, { 5, 45, 512 }, { 5, 46, 512 }, { 6, 47, 512 }, + { 3, 48, 512 }, { 4, 49, 512 }, { 4, 50, 512 }, { 5, 51, 512 }, { 4, 52, 512 }, { 5, 53, 512 }, { 5, 54, 512 }, { 6, 55, 512 }, + { 4, 56, 512 }, { 5, 57, 512 }, { 5, 58, 512 }, { 6, 59, 512 }, { 5, 60, 512 }, { 6, 61, 512 }, { 6, 62, 512 }, { 7, 63, 512 }, + { 2, 64, 512 }, { 3, 65, 512 }, { 3, 66, 512 }, { 4, 67, 512 }, { 3, 68, 512 }, { 4, 69, 512 }, { 4, 70, 512 }, { 5, 71, 512 }, + { 3, 72, 512 }, { 4, 73, 512 }, { 4, 74, 512 }, { 5, 75, 512 }, { 4, 76, 512 }, { 5, 77, 512 }, { 5, 78, 512 }, { 6, 79, 512 }, + { 3, 80, 512 }, { 4, 81, 512 }, { 4, 82, 512 }, { 5, 83, 512 }, { 4, 84, 512 }, { 5, 85, 512 }, { 5, 86, 512 }, { 6, 87, 512 }, + { 4, 88, 512 }, { 5, 89, 512 }, { 5, 90, 512 }, { 6, 91, 512 }, { 5, 92, 512 }, { 6, 93, 512 }, { 6, 94, 512 }, { 7, 95, 512 }, + { 3, 96, 512 }, { 4, 97, 512 }, { 4, 98, 512 }, { 5, 99, 512 }, { 4, 100, 512 }, { 5, 101, 512 }, { 5, 102, 512 }, { 6, 103, 512 }, + { 4, 104, 512 }, { 5, 105, 512 }, { 5, 106, 512 }, { 6, 107, 512 }, { 5, 108, 512 }, { 6, 109, 512 }, { 6, 110, 512 }, { 7, 111, 512 }, + { 4, 112, 512 }, { 5, 113, 512 }, { 5, 114, 512 }, { 6, 115, 512 }, { 5, 116, 512 }, { 6, 117, 512 }, { 6, 118, 512 }, { 7, 119, 512 }, + { 5, 120, 512 }, { 6, 121, 512 }, { 6, 122, 512 }, { 7, 123, 512 }, { 6, 124, 512 }, { 7, 125, 512 }, { 7, 126, 512 }, { 8, 127, 512 }, + { 2, 128, 512 }, { 3, 129, 512 }, { 3, 130, 512 }, { 4, 131, 512 }, { 3, 132, 512 }, { 4, 133, 512 }, { 4, 134, 512 }, { 5, 135, 512 }, + { 3, 136, 512 }, { 4, 137, 512 }, { 4, 138, 512 }, { 5, 139, 512 }, { 4, 140, 512 }, { 5, 141, 512 }, { 5, 142, 512 }, { 6, 143, 512 }, + { 3, 144, 512 }, { 4, 145, 512 }, { 4, 146, 512 }, { 5, 147, 512 }, { 4, 148, 512 }, { 5, 149, 512 }, { 5, 150, 512 }, { 6, 151, 512 }, + { 4, 152, 512 }, { 5, 153, 512 }, { 5, 154, 512 }, { 6, 155, 512 }, { 5, 156, 512 }, { 6, 157, 512 }, { 6, 158, 512 }, { 7, 159, 512 }, + { 3, 160, 512 }, { 4, 161, 512 }, { 4, 162, 512 }, { 5, 163, 512 }, { 4, 164, 512 }, { 5, 165, 512 }, { 5, 166, 512 }, { 6, 167, 512 }, + { 4, 168, 512 }, { 5, 169, 512 }, { 5, 170, 512 }, { 6, 171, 512 }, { 5, 172, 512 }, { 6, 173, 512 }, { 6, 174, 512 }, { 7, 175, 512 }, + { 4, 176, 512 }, { 5, 177, 512 }, { 5, 178, 512 }, { 6, 179, 512 }, { 5, 180, 512 }, { 6, 181, 512 }, { 6, 182, 512 }, { 7, 183, 512 }, + { 5, 184, 512 }, { 6, 185, 512 }, { 6, 186, 512 }, { 7, 187, 512 }, { 6, 188, 512 }, { 7, 189, 512 }, { 7, 190, 512 }, { 8, 191, 512 }, + { 3, 192, 512 }, { 4, 193, 512 }, { 4, 194, 512 }, { 5, 195, 512 }, { 4, 196, 512 }, { 5, 197, 512 }, { 5, 198, 512 }, { 6, 199, 512 }, + { 4, 200, 512 }, { 5, 201, 512 }, { 5, 202, 512 }, { 6, 203, 512 }, { 5, 204, 512 }, { 6, 205, 512 }, { 6, 206, 512 }, { 7, 207, 512 }, + { 4, 208, 512 }, { 5, 209, 512 }, { 5, 210, 512 }, { 6, 211, 512 }, { 5, 212, 512 }, { 6, 213, 512 }, { 6, 214, 512 }, { 7, 215, 512 }, + { 5, 216, 512 }, { 6, 217, 512 }, { 6, 218, 512 }, { 7, 219, 512 }, { 6, 220, 512 }, { 7, 221, 512 }, { 7, 222, 512 }, { 8, 223, 512 }, + { 4, 224, 512 }, { 5, 225, 512 }, { 5, 226, 512 }, { 6, 227, 512 }, { 5, 228, 512 }, { 6, 229, 512 }, { 6, 230, 512 }, { 7, 231, 512 }, + { 5, 232, 512 }, { 6, 233, 512 }, { 6, 234, 512 }, { 7, 235, 512 }, { 6, 236, 512 }, { 7, 237, 512 }, { 7, 238, 512 }, { 8, 239, 512 }, + { 5, 240, 512 }, { 6, 241, 512 }, { 6, 242, 512 }, { 7, 243, 512 }, { 6, 244, 512 }, { 7, 245, 512 }, { 7, 246, 512 }, { 8, 247, 512 }, + { 6, 248, 512 }, { 7, 249, 512 }, { 7, 250, 512 }, { 8, 251, 512 }, { 7, 252, 512 }, { 8, 253, 512 }, { 8, 254, 512 }, { 9, 255, 512 }, + { 2, 256, 512 }, { 3, 257, 512 }, { 3, 258, 512 }, { 4, 259, 512 }, { 3, 260, 512 }, { 4, 261, 512 }, { 4, 262, 512 }, { 5, 263, 512 }, + { 3, 264, 512 }, { 4, 265, 512 }, { 4, 266, 512 }, { 5, 267, 512 }, { 4, 268, 512 }, { 5, 269, 512 }, { 5, 270, 512 }, { 6, 271, 512 }, + { 3, 272, 512 }, { 4, 273, 512 }, { 4, 274, 512 }, { 5, 275, 512 }, { 4, 276, 512 }, { 5, 277, 512 }, { 5, 278, 512 }, { 6, 279, 512 }, + { 4, 280, 512 }, { 5, 281, 512 }, { 5, 282, 512 }, { 6, 283, 512 }, { 5, 284, 512 }, { 6, 285, 512 }, { 6, 286, 512 }, { 7, 287, 512 }, + { 3, 288, 512 }, { 4, 289, 512 }, { 4, 290, 512 }, { 5, 291, 512 }, { 4, 292, 512 }, { 5, 293, 512 }, { 5, 294, 512 }, { 6, 295, 512 }, + { 4, 296, 512 }, { 5, 297, 512 }, { 5, 298, 512 }, { 6, 299, 512 }, { 5, 300, 512 }, { 6, 301, 512 }, { 6, 302, 512 }, { 7, 303, 512 }, + { 4, 304, 512 }, { 5, 305, 512 }, { 5, 306, 512 }, { 6, 307, 512 }, { 5, 308, 512 }, { 6, 309, 512 }, { 6, 310, 512 }, { 7, 311, 512 }, + { 5, 312, 512 }, { 6, 313, 512 }, { 6, 314, 512 }, { 7, 315, 512 }, { 6, 316, 512 }, { 7, 317, 512 }, { 7, 318, 512 }, { 8, 319, 512 }, + { 3, 320, 512 }, { 4, 321, 512 }, { 4, 322, 512 }, { 5, 323, 512 }, { 4, 324, 512 }, { 5, 325, 512 }, { 5, 326, 512 }, { 6, 327, 512 }, + { 4, 328, 512 }, { 5, 329, 512 }, { 5, 330, 512 }, { 6, 331, 512 }, { 5, 332, 512 }, { 6, 333, 512 }, { 6, 334, 512 }, { 7, 335, 512 }, + { 4, 336, 512 }, { 5, 337, 512 }, { 5, 338, 512 }, { 6, 339, 512 }, { 5, 340, 512 }, { 6, 341, 512 }, { 6, 342, 512 }, { 7, 343, 512 }, + { 5, 344, 512 }, { 6, 345, 512 }, { 6, 346, 512 }, { 7, 347, 512 }, { 6, 348, 512 }, { 7, 349, 512 }, { 7, 350, 512 }, { 8, 351, 512 }, + { 4, 352, 512 }, { 5, 353, 512 }, { 5, 354, 512 }, { 6, 355, 512 }, { 5, 356, 512 }, { 6, 357, 512 }, { 6, 358, 512 }, { 7, 359, 512 }, + { 5, 360, 512 }, { 6, 361, 512 }, { 6, 362, 512 }, { 7, 363, 512 }, { 6, 364, 512 }, { 7, 365, 512 }, { 7, 366, 512 }, { 8, 367, 512 }, + { 5, 368, 512 }, { 6, 369, 512 }, { 6, 370, 512 }, { 7, 371, 512 }, { 6, 372, 512 }, { 7, 373, 512 }, { 7, 374, 512 }, { 8, 375, 512 }, + { 6, 376, 512 }, { 7, 377, 512 }, { 7, 378, 512 }, { 8, 379, 512 }, { 7, 380, 512 }, { 8, 381, 512 }, { 8, 382, 512 }, { 9, 383, 512 }, + { 3, 384, 512 }, { 4, 385, 512 }, { 4, 386, 512 }, { 5, 387, 512 }, { 4, 388, 512 }, { 5, 389, 512 }, { 5, 390, 512 }, { 6, 391, 512 }, + { 4, 392, 512 }, { 5, 393, 512 }, { 5, 394, 512 }, { 6, 395, 512 }, { 5, 396, 512 }, { 6, 397, 512 }, { 6, 398, 512 }, { 7, 399, 512 }, + { 4, 400, 512 }, { 5, 401, 512 }, { 5, 402, 512 }, { 6, 403, 512 }, { 5, 404, 512 }, { 6, 405, 512 }, { 6, 406, 512 }, { 7, 407, 512 }, + { 5, 408, 512 }, { 6, 409, 512 }, { 6, 410, 512 }, { 7, 411, 512 }, { 6, 412, 512 }, { 7, 413, 512 }, { 7, 414, 512 }, { 8, 415, 512 }, + { 4, 416, 512 }, { 5, 417, 512 }, { 5, 418, 512 }, { 6, 419, 512 }, { 5, 420, 512 }, { 6, 421, 512 }, { 6, 422, 512 }, { 7, 423, 512 }, + { 5, 424, 512 }, { 6, 425, 512 }, { 6, 426, 512 }, { 7, 427, 512 }, { 6, 428, 512 }, { 7, 429, 512 }, { 7, 430, 512 }, { 8, 431, 512 }, + { 5, 432, 512 }, { 6, 433, 512 }, { 6, 434, 512 }, { 7, 435, 512 }, { 6, 436, 512 }, { 7, 437, 512 }, { 7, 438, 512 }, { 8, 439, 512 }, + { 6, 440, 512 }, { 7, 441, 512 }, { 7, 442, 512 }, { 8, 443, 512 }, { 7, 444, 512 }, { 8, 445, 512 }, { 8, 446, 512 }, { 9, 447, 512 }, + { 4, 448, 512 }, { 5, 449, 512 }, { 5, 450, 512 }, { 6, 451, 512 }, { 5, 452, 512 }, { 6, 453, 512 }, { 6, 454, 512 }, { 7, 455, 512 }, + { 5, 456, 512 }, { 6, 457, 512 }, { 6, 458, 512 }, { 7, 459, 512 }, { 6, 460, 512 }, { 7, 461, 512 }, { 7, 462, 512 }, { 8, 463, 512 }, + { 5, 464, 512 }, { 6, 465, 512 }, { 6, 466, 512 }, { 7, 467, 512 }, { 6, 468, 512 }, { 7, 469, 512 }, { 7, 470, 512 }, { 8, 471, 512 }, + { 6, 472, 512 }, { 7, 473, 512 }, { 7, 474, 512 }, { 8, 475, 512 }, { 7, 476, 512 }, { 8, 477, 512 }, { 8, 478, 512 }, { 9, 479, 512 }, + { 5, 480, 512 }, { 6, 481, 512 }, { 6, 482, 512 }, { 7, 483, 512 }, { 6, 484, 512 }, { 7, 485, 512 }, { 7, 486, 512 }, { 8, 487, 512 }, + { 6, 488, 512 }, { 7, 489, 512 }, { 7, 490, 512 }, { 8, 491, 512 }, { 7, 492, 512 }, { 8, 493, 512 }, { 8, 494, 512 }, { 9, 495, 512 }, + { 6, 496, 512 }, { 7, 497, 512 }, { 7, 498, 512 }, { 8, 499, 512 }, { 7, 500, 512 }, { 8, 501, 512 }, { 8, 502, 512 }, { 9, 503, 512 }, + { 7, 504, 512 }, { 8, 505, 512 }, { 8, 506, 512 }, { 9, 507, 512 }, { 8, 508, 512 }, { 9, 509, 512 }, { 9, 510, 512 }, { 10, 511, 512 }, +#if FP_LUT > 10 + { 1, 0, 0 }, { 2, 1, 1024 }, { 2, 2, 1024 }, { 3, 3, 1024 }, { 2, 4, 1024 }, { 3, 5, 1024 }, { 3, 6, 1024 }, { 4, 7, 1024 }, + { 2, 8, 1024 }, { 3, 9, 1024 }, { 3, 10, 1024 }, { 4, 11, 1024 }, { 3, 12, 1024 }, { 4, 13, 1024 }, { 4, 14, 1024 }, { 5, 15, 1024 }, + { 2, 16, 1024 }, { 3, 17, 1024 }, { 3, 18, 1024 }, { 4, 19, 1024 }, { 3, 20, 1024 }, { 4, 21, 1024 }, { 4, 22, 1024 }, { 5, 23, 1024 }, + { 3, 24, 1024 }, { 4, 25, 1024 }, { 4, 26, 1024 }, { 5, 27, 1024 }, { 4, 28, 1024 }, { 5, 29, 1024 }, { 5, 30, 1024 }, { 6, 31, 1024 }, + { 2, 32, 1024 }, { 3, 33, 1024 }, { 3, 34, 1024 }, { 4, 35, 1024 }, { 3, 36, 1024 }, { 4, 37, 1024 }, { 4, 38, 1024 }, { 5, 39, 1024 }, + { 3, 40, 1024 }, { 4, 41, 1024 }, { 4, 42, 1024 }, { 5, 43, 1024 }, { 4, 44, 1024 }, { 5, 45, 1024 }, { 5, 46, 1024 }, { 6, 47, 1024 }, + { 3, 48, 1024 }, { 4, 49, 1024 }, { 4, 50, 1024 }, { 5, 51, 1024 }, { 4, 52, 1024 }, { 5, 53, 1024 }, { 5, 54, 1024 }, { 6, 55, 1024 }, + { 4, 56, 1024 }, { 5, 57, 1024 }, { 5, 58, 1024 }, { 6, 59, 1024 }, { 5, 60, 1024 }, { 6, 61, 1024 }, { 6, 62, 1024 }, { 7, 63, 1024 }, + { 2, 64, 1024 }, { 3, 65, 1024 }, { 3, 66, 1024 }, { 4, 67, 1024 }, { 3, 68, 1024 }, { 4, 69, 1024 }, { 4, 70, 1024 }, { 5, 71, 1024 }, + { 3, 72, 1024 }, { 4, 73, 1024 }, { 4, 74, 1024 }, { 5, 75, 1024 }, { 4, 76, 1024 }, { 5, 77, 1024 }, { 5, 78, 1024 }, { 6, 79, 1024 }, + { 3, 80, 1024 }, { 4, 81, 1024 }, { 4, 82, 1024 }, { 5, 83, 1024 }, { 4, 84, 1024 }, { 5, 85, 1024 }, { 5, 86, 1024 }, { 6, 87, 1024 }, + { 4, 88, 1024 }, { 5, 89, 1024 }, { 5, 90, 1024 }, { 6, 91, 1024 }, { 5, 92, 1024 }, { 6, 93, 1024 }, { 6, 94, 1024 }, { 7, 95, 1024 }, + { 3, 96, 1024 }, { 4, 97, 1024 }, { 4, 98, 1024 }, { 5, 99, 1024 }, { 4, 100, 1024 }, { 5, 101, 1024 }, { 5, 102, 1024 }, { 6, 103, 1024 }, + { 4, 104, 1024 }, { 5, 105, 1024 }, { 5, 106, 1024 }, { 6, 107, 1024 }, { 5, 108, 1024 }, { 6, 109, 1024 }, { 6, 110, 1024 }, { 7, 111, 1024 }, + { 4, 112, 1024 }, { 5, 113, 1024 }, { 5, 114, 1024 }, { 6, 115, 1024 }, { 5, 116, 1024 }, { 6, 117, 1024 }, { 6, 118, 1024 }, { 7, 119, 1024 }, + { 5, 120, 1024 }, { 6, 121, 1024 }, { 6, 122, 1024 }, { 7, 123, 1024 }, { 6, 124, 1024 }, { 7, 125, 1024 }, { 7, 126, 1024 }, { 8, 127, 1024 }, + { 2, 128, 1024 }, { 3, 129, 1024 }, { 3, 130, 1024 }, { 4, 131, 1024 }, { 3, 132, 1024 }, { 4, 133, 1024 }, { 4, 134, 1024 }, { 5, 135, 1024 }, + { 3, 136, 1024 }, { 4, 137, 1024 }, { 4, 138, 1024 }, { 5, 139, 1024 }, { 4, 140, 1024 }, { 5, 141, 1024 }, { 5, 142, 1024 }, { 6, 143, 1024 }, + { 3, 144, 1024 }, { 4, 145, 1024 }, { 4, 146, 1024 }, { 5, 147, 1024 }, { 4, 148, 1024 }, { 5, 149, 1024 }, { 5, 150, 1024 }, { 6, 151, 1024 }, + { 4, 152, 1024 }, { 5, 153, 1024 }, { 5, 154, 1024 }, { 6, 155, 1024 }, { 5, 156, 1024 }, { 6, 157, 1024 }, { 6, 158, 1024 }, { 7, 159, 1024 }, + { 3, 160, 1024 }, { 4, 161, 1024 }, { 4, 162, 1024 }, { 5, 163, 1024 }, { 4, 164, 1024 }, { 5, 165, 1024 }, { 5, 166, 1024 }, { 6, 167, 1024 }, + { 4, 168, 1024 }, { 5, 169, 1024 }, { 5, 170, 1024 }, { 6, 171, 1024 }, { 5, 172, 1024 }, { 6, 173, 1024 }, { 6, 174, 1024 }, { 7, 175, 1024 }, + { 4, 176, 1024 }, { 5, 177, 1024 }, { 5, 178, 1024 }, { 6, 179, 1024 }, { 5, 180, 1024 }, { 6, 181, 1024 }, { 6, 182, 1024 }, { 7, 183, 1024 }, + { 5, 184, 1024 }, { 6, 185, 1024 }, { 6, 186, 1024 }, { 7, 187, 1024 }, { 6, 188, 1024 }, { 7, 189, 1024 }, { 7, 190, 1024 }, { 8, 191, 1024 }, + { 3, 192, 1024 }, { 4, 193, 1024 }, { 4, 194, 1024 }, { 5, 195, 1024 }, { 4, 196, 1024 }, { 5, 197, 1024 }, { 5, 198, 1024 }, { 6, 199, 1024 }, + { 4, 200, 1024 }, { 5, 201, 1024 }, { 5, 202, 1024 }, { 6, 203, 1024 }, { 5, 204, 1024 }, { 6, 205, 1024 }, { 6, 206, 1024 }, { 7, 207, 1024 }, + { 4, 208, 1024 }, { 5, 209, 1024 }, { 5, 210, 1024 }, { 6, 211, 1024 }, { 5, 212, 1024 }, { 6, 213, 1024 }, { 6, 214, 1024 }, { 7, 215, 1024 }, + { 5, 216, 1024 }, { 6, 217, 1024 }, { 6, 218, 1024 }, { 7, 219, 1024 }, { 6, 220, 1024 }, { 7, 221, 1024 }, { 7, 222, 1024 }, { 8, 223, 1024 }, + { 4, 224, 1024 }, { 5, 225, 1024 }, { 5, 226, 1024 }, { 6, 227, 1024 }, { 5, 228, 1024 }, { 6, 229, 1024 }, { 6, 230, 1024 }, { 7, 231, 1024 }, + { 5, 232, 1024 }, { 6, 233, 1024 }, { 6, 234, 1024 }, { 7, 235, 1024 }, { 6, 236, 1024 }, { 7, 237, 1024 }, { 7, 238, 1024 }, { 8, 239, 1024 }, + { 5, 240, 1024 }, { 6, 241, 1024 }, { 6, 242, 1024 }, { 7, 243, 1024 }, { 6, 244, 1024 }, { 7, 245, 1024 }, { 7, 246, 1024 }, { 8, 247, 1024 }, + { 6, 248, 1024 }, { 7, 249, 1024 }, { 7, 250, 1024 }, { 8, 251, 1024 }, { 7, 252, 1024 }, { 8, 253, 1024 }, { 8, 254, 1024 }, { 9, 255, 1024 }, + { 2, 256, 1024 }, { 3, 257, 1024 }, { 3, 258, 1024 }, { 4, 259, 1024 }, { 3, 260, 1024 }, { 4, 261, 1024 }, { 4, 262, 1024 }, { 5, 263, 1024 }, + { 3, 264, 1024 }, { 4, 265, 1024 }, { 4, 266, 1024 }, { 5, 267, 1024 }, { 4, 268, 1024 }, { 5, 269, 1024 }, { 5, 270, 1024 }, { 6, 271, 1024 }, + { 3, 272, 1024 }, { 4, 273, 1024 }, { 4, 274, 1024 }, { 5, 275, 1024 }, { 4, 276, 1024 }, { 5, 277, 1024 }, { 5, 278, 1024 }, { 6, 279, 1024 }, + { 4, 280, 1024 }, { 5, 281, 1024 }, { 5, 282, 1024 }, { 6, 283, 1024 }, { 5, 284, 1024 }, { 6, 285, 1024 }, { 6, 286, 1024 }, { 7, 287, 1024 }, + { 3, 288, 1024 }, { 4, 289, 1024 }, { 4, 290, 1024 }, { 5, 291, 1024 }, { 4, 292, 1024 }, { 5, 293, 1024 }, { 5, 294, 1024 }, { 6, 295, 1024 }, + { 4, 296, 1024 }, { 5, 297, 1024 }, { 5, 298, 1024 }, { 6, 299, 1024 }, { 5, 300, 1024 }, { 6, 301, 1024 }, { 6, 302, 1024 }, { 7, 303, 1024 }, + { 4, 304, 1024 }, { 5, 305, 1024 }, { 5, 306, 1024 }, { 6, 307, 1024 }, { 5, 308, 1024 }, { 6, 309, 1024 }, { 6, 310, 1024 }, { 7, 311, 1024 }, + { 5, 312, 1024 }, { 6, 313, 1024 }, { 6, 314, 1024 }, { 7, 315, 1024 }, { 6, 316, 1024 }, { 7, 317, 1024 }, { 7, 318, 1024 }, { 8, 319, 1024 }, + { 3, 320, 1024 }, { 4, 321, 1024 }, { 4, 322, 1024 }, { 5, 323, 1024 }, { 4, 324, 1024 }, { 5, 325, 1024 }, { 5, 326, 1024 }, { 6, 327, 1024 }, + { 4, 328, 1024 }, { 5, 329, 1024 }, { 5, 330, 1024 }, { 6, 331, 1024 }, { 5, 332, 1024 }, { 6, 333, 1024 }, { 6, 334, 1024 }, { 7, 335, 1024 }, + { 4, 336, 1024 }, { 5, 337, 1024 }, { 5, 338, 1024 }, { 6, 339, 1024 }, { 5, 340, 1024 }, { 6, 341, 1024 }, { 6, 342, 1024 }, { 7, 343, 1024 }, + { 5, 344, 1024 }, { 6, 345, 1024 }, { 6, 346, 1024 }, { 7, 347, 1024 }, { 6, 348, 1024 }, { 7, 349, 1024 }, { 7, 350, 1024 }, { 8, 351, 1024 }, + { 4, 352, 1024 }, { 5, 353, 1024 }, { 5, 354, 1024 }, { 6, 355, 1024 }, { 5, 356, 1024 }, { 6, 357, 1024 }, { 6, 358, 1024 }, { 7, 359, 1024 }, + { 5, 360, 1024 }, { 6, 361, 1024 }, { 6, 362, 1024 }, { 7, 363, 1024 }, { 6, 364, 1024 }, { 7, 365, 1024 }, { 7, 366, 1024 }, { 8, 367, 1024 }, + { 5, 368, 1024 }, { 6, 369, 1024 }, { 6, 370, 1024 }, { 7, 371, 1024 }, { 6, 372, 1024 }, { 7, 373, 1024 }, { 7, 374, 1024 }, { 8, 375, 1024 }, + { 6, 376, 1024 }, { 7, 377, 1024 }, { 7, 378, 1024 }, { 8, 379, 1024 }, { 7, 380, 1024 }, { 8, 381, 1024 }, { 8, 382, 1024 }, { 9, 383, 1024 }, + { 3, 384, 1024 }, { 4, 385, 1024 }, { 4, 386, 1024 }, { 5, 387, 1024 }, { 4, 388, 1024 }, { 5, 389, 1024 }, { 5, 390, 1024 }, { 6, 391, 1024 }, + { 4, 392, 1024 }, { 5, 393, 1024 }, { 5, 394, 1024 }, { 6, 395, 1024 }, { 5, 396, 1024 }, { 6, 397, 1024 }, { 6, 398, 1024 }, { 7, 399, 1024 }, + { 4, 400, 1024 }, { 5, 401, 1024 }, { 5, 402, 1024 }, { 6, 403, 1024 }, { 5, 404, 1024 }, { 6, 405, 1024 }, { 6, 406, 1024 }, { 7, 407, 1024 }, + { 5, 408, 1024 }, { 6, 409, 1024 }, { 6, 410, 1024 }, { 7, 411, 1024 }, { 6, 412, 1024 }, { 7, 413, 1024 }, { 7, 414, 1024 }, { 8, 415, 1024 }, + { 4, 416, 1024 }, { 5, 417, 1024 }, { 5, 418, 1024 }, { 6, 419, 1024 }, { 5, 420, 1024 }, { 6, 421, 1024 }, { 6, 422, 1024 }, { 7, 423, 1024 }, + { 5, 424, 1024 }, { 6, 425, 1024 }, { 6, 426, 1024 }, { 7, 427, 1024 }, { 6, 428, 1024 }, { 7, 429, 1024 }, { 7, 430, 1024 }, { 8, 431, 1024 }, + { 5, 432, 1024 }, { 6, 433, 1024 }, { 6, 434, 1024 }, { 7, 435, 1024 }, { 6, 436, 1024 }, { 7, 437, 1024 }, { 7, 438, 1024 }, { 8, 439, 1024 }, + { 6, 440, 1024 }, { 7, 441, 1024 }, { 7, 442, 1024 }, { 8, 443, 1024 }, { 7, 444, 1024 }, { 8, 445, 1024 }, { 8, 446, 1024 }, { 9, 447, 1024 }, + { 4, 448, 1024 }, { 5, 449, 1024 }, { 5, 450, 1024 }, { 6, 451, 1024 }, { 5, 452, 1024 }, { 6, 453, 1024 }, { 6, 454, 1024 }, { 7, 455, 1024 }, + { 5, 456, 1024 }, { 6, 457, 1024 }, { 6, 458, 1024 }, { 7, 459, 1024 }, { 6, 460, 1024 }, { 7, 461, 1024 }, { 7, 462, 1024 }, { 8, 463, 1024 }, + { 5, 464, 1024 }, { 6, 465, 1024 }, { 6, 466, 1024 }, { 7, 467, 1024 }, { 6, 468, 1024 }, { 7, 469, 1024 }, { 7, 470, 1024 }, { 8, 471, 1024 }, + { 6, 472, 1024 }, { 7, 473, 1024 }, { 7, 474, 1024 }, { 8, 475, 1024 }, { 7, 476, 1024 }, { 8, 477, 1024 }, { 8, 478, 1024 }, { 9, 479, 1024 }, + { 5, 480, 1024 }, { 6, 481, 1024 }, { 6, 482, 1024 }, { 7, 483, 1024 }, { 6, 484, 1024 }, { 7, 485, 1024 }, { 7, 486, 1024 }, { 8, 487, 1024 }, + { 6, 488, 1024 }, { 7, 489, 1024 }, { 7, 490, 1024 }, { 8, 491, 1024 }, { 7, 492, 1024 }, { 8, 493, 1024 }, { 8, 494, 1024 }, { 9, 495, 1024 }, + { 6, 496, 1024 }, { 7, 497, 1024 }, { 7, 498, 1024 }, { 8, 499, 1024 }, { 7, 500, 1024 }, { 8, 501, 1024 }, { 8, 502, 1024 }, { 9, 503, 1024 }, + { 7, 504, 1024 }, { 8, 505, 1024 }, { 8, 506, 1024 }, { 9, 507, 1024 }, { 8, 508, 1024 }, { 9, 509, 1024 }, { 9, 510, 1024 }, { 10, 511, 1024 }, + { 2, 512, 1024 }, { 3, 513, 1024 }, { 3, 514, 1024 }, { 4, 515, 1024 }, { 3, 516, 1024 }, { 4, 517, 1024 }, { 4, 518, 1024 }, { 5, 519, 1024 }, + { 3, 520, 1024 }, { 4, 521, 1024 }, { 4, 522, 1024 }, { 5, 523, 1024 }, { 4, 524, 1024 }, { 5, 525, 1024 }, { 5, 526, 1024 }, { 6, 527, 1024 }, + { 3, 528, 1024 }, { 4, 529, 1024 }, { 4, 530, 1024 }, { 5, 531, 1024 }, { 4, 532, 1024 }, { 5, 533, 1024 }, { 5, 534, 1024 }, { 6, 535, 1024 }, + { 4, 536, 1024 }, { 5, 537, 1024 }, { 5, 538, 1024 }, { 6, 539, 1024 }, { 5, 540, 1024 }, { 6, 541, 1024 }, { 6, 542, 1024 }, { 7, 543, 1024 }, + { 3, 544, 1024 }, { 4, 545, 1024 }, { 4, 546, 1024 }, { 5, 547, 1024 }, { 4, 548, 1024 }, { 5, 549, 1024 }, { 5, 550, 1024 }, { 6, 551, 1024 }, + { 4, 552, 1024 }, { 5, 553, 1024 }, { 5, 554, 1024 }, { 6, 555, 1024 }, { 5, 556, 1024 }, { 6, 557, 1024 }, { 6, 558, 1024 }, { 7, 559, 1024 }, + { 4, 560, 1024 }, { 5, 561, 1024 }, { 5, 562, 1024 }, { 6, 563, 1024 }, { 5, 564, 1024 }, { 6, 565, 1024 }, { 6, 566, 1024 }, { 7, 567, 1024 }, + { 5, 568, 1024 }, { 6, 569, 1024 }, { 6, 570, 1024 }, { 7, 571, 1024 }, { 6, 572, 1024 }, { 7, 573, 1024 }, { 7, 574, 1024 }, { 8, 575, 1024 }, + { 3, 576, 1024 }, { 4, 577, 1024 }, { 4, 578, 1024 }, { 5, 579, 1024 }, { 4, 580, 1024 }, { 5, 581, 1024 }, { 5, 582, 1024 }, { 6, 583, 1024 }, + { 4, 584, 1024 }, { 5, 585, 1024 }, { 5, 586, 1024 }, { 6, 587, 1024 }, { 5, 588, 1024 }, { 6, 589, 1024 }, { 6, 590, 1024 }, { 7, 591, 1024 }, + { 4, 592, 1024 }, { 5, 593, 1024 }, { 5, 594, 1024 }, { 6, 595, 1024 }, { 5, 596, 1024 }, { 6, 597, 1024 }, { 6, 598, 1024 }, { 7, 599, 1024 }, + { 5, 600, 1024 }, { 6, 601, 1024 }, { 6, 602, 1024 }, { 7, 603, 1024 }, { 6, 604, 1024 }, { 7, 605, 1024 }, { 7, 606, 1024 }, { 8, 607, 1024 }, + { 4, 608, 1024 }, { 5, 609, 1024 }, { 5, 610, 1024 }, { 6, 611, 1024 }, { 5, 612, 1024 }, { 6, 613, 1024 }, { 6, 614, 1024 }, { 7, 615, 1024 }, + { 5, 616, 1024 }, { 6, 617, 1024 }, { 6, 618, 1024 }, { 7, 619, 1024 }, { 6, 620, 1024 }, { 7, 621, 1024 }, { 7, 622, 1024 }, { 8, 623, 1024 }, + { 5, 624, 1024 }, { 6, 625, 1024 }, { 6, 626, 1024 }, { 7, 627, 1024 }, { 6, 628, 1024 }, { 7, 629, 1024 }, { 7, 630, 1024 }, { 8, 631, 1024 }, + { 6, 632, 1024 }, { 7, 633, 1024 }, { 7, 634, 1024 }, { 8, 635, 1024 }, { 7, 636, 1024 }, { 8, 637, 1024 }, { 8, 638, 1024 }, { 9, 639, 1024 }, + { 3, 640, 1024 }, { 4, 641, 1024 }, { 4, 642, 1024 }, { 5, 643, 1024 }, { 4, 644, 1024 }, { 5, 645, 1024 }, { 5, 646, 1024 }, { 6, 647, 1024 }, + { 4, 648, 1024 }, { 5, 649, 1024 }, { 5, 650, 1024 }, { 6, 651, 1024 }, { 5, 652, 1024 }, { 6, 653, 1024 }, { 6, 654, 1024 }, { 7, 655, 1024 }, + { 4, 656, 1024 }, { 5, 657, 1024 }, { 5, 658, 1024 }, { 6, 659, 1024 }, { 5, 660, 1024 }, { 6, 661, 1024 }, { 6, 662, 1024 }, { 7, 663, 1024 }, + { 5, 664, 1024 }, { 6, 665, 1024 }, { 6, 666, 1024 }, { 7, 667, 1024 }, { 6, 668, 1024 }, { 7, 669, 1024 }, { 7, 670, 1024 }, { 8, 671, 1024 }, + { 4, 672, 1024 }, { 5, 673, 1024 }, { 5, 674, 1024 }, { 6, 675, 1024 }, { 5, 676, 1024 }, { 6, 677, 1024 }, { 6, 678, 1024 }, { 7, 679, 1024 }, + { 5, 680, 1024 }, { 6, 681, 1024 }, { 6, 682, 1024 }, { 7, 683, 1024 }, { 6, 684, 1024 }, { 7, 685, 1024 }, { 7, 686, 1024 }, { 8, 687, 1024 }, + { 5, 688, 1024 }, { 6, 689, 1024 }, { 6, 690, 1024 }, { 7, 691, 1024 }, { 6, 692, 1024 }, { 7, 693, 1024 }, { 7, 694, 1024 }, { 8, 695, 1024 }, + { 6, 696, 1024 }, { 7, 697, 1024 }, { 7, 698, 1024 }, { 8, 699, 1024 }, { 7, 700, 1024 }, { 8, 701, 1024 }, { 8, 702, 1024 }, { 9, 703, 1024 }, + { 4, 704, 1024 }, { 5, 705, 1024 }, { 5, 706, 1024 }, { 6, 707, 1024 }, { 5, 708, 1024 }, { 6, 709, 1024 }, { 6, 710, 1024 }, { 7, 711, 1024 }, + { 5, 712, 1024 }, { 6, 713, 1024 }, { 6, 714, 1024 }, { 7, 715, 1024 }, { 6, 716, 1024 }, { 7, 717, 1024 }, { 7, 718, 1024 }, { 8, 719, 1024 }, + { 5, 720, 1024 }, { 6, 721, 1024 }, { 6, 722, 1024 }, { 7, 723, 1024 }, { 6, 724, 1024 }, { 7, 725, 1024 }, { 7, 726, 1024 }, { 8, 727, 1024 }, + { 6, 728, 1024 }, { 7, 729, 1024 }, { 7, 730, 1024 }, { 8, 731, 1024 }, { 7, 732, 1024 }, { 8, 733, 1024 }, { 8, 734, 1024 }, { 9, 735, 1024 }, + { 5, 736, 1024 }, { 6, 737, 1024 }, { 6, 738, 1024 }, { 7, 739, 1024 }, { 6, 740, 1024 }, { 7, 741, 1024 }, { 7, 742, 1024 }, { 8, 743, 1024 }, + { 6, 744, 1024 }, { 7, 745, 1024 }, { 7, 746, 1024 }, { 8, 747, 1024 }, { 7, 748, 1024 }, { 8, 749, 1024 }, { 8, 750, 1024 }, { 9, 751, 1024 }, + { 6, 752, 1024 }, { 7, 753, 1024 }, { 7, 754, 1024 }, { 8, 755, 1024 }, { 7, 756, 1024 }, { 8, 757, 1024 }, { 8, 758, 1024 }, { 9, 759, 1024 }, + { 7, 760, 1024 }, { 8, 761, 1024 }, { 8, 762, 1024 }, { 9, 763, 1024 }, { 8, 764, 1024 }, { 9, 765, 1024 }, { 9, 766, 1024 }, { 10, 767, 1024 }, + { 3, 768, 1024 }, { 4, 769, 1024 }, { 4, 770, 1024 }, { 5, 771, 1024 }, { 4, 772, 1024 }, { 5, 773, 1024 }, { 5, 774, 1024 }, { 6, 775, 1024 }, + { 4, 776, 1024 }, { 5, 777, 1024 }, { 5, 778, 1024 }, { 6, 779, 1024 }, { 5, 780, 1024 }, { 6, 781, 1024 }, { 6, 782, 1024 }, { 7, 783, 1024 }, + { 4, 784, 1024 }, { 5, 785, 1024 }, { 5, 786, 1024 }, { 6, 787, 1024 }, { 5, 788, 1024 }, { 6, 789, 1024 }, { 6, 790, 1024 }, { 7, 791, 1024 }, + { 5, 792, 1024 }, { 6, 793, 1024 }, { 6, 794, 1024 }, { 7, 795, 1024 }, { 6, 796, 1024 }, { 7, 797, 1024 }, { 7, 798, 1024 }, { 8, 799, 1024 }, + { 4, 800, 1024 }, { 5, 801, 1024 }, { 5, 802, 1024 }, { 6, 803, 1024 }, { 5, 804, 1024 }, { 6, 805, 1024 }, { 6, 806, 1024 }, { 7, 807, 1024 }, + { 5, 808, 1024 }, { 6, 809, 1024 }, { 6, 810, 1024 }, { 7, 811, 1024 }, { 6, 812, 1024 }, { 7, 813, 1024 }, { 7, 814, 1024 }, { 8, 815, 1024 }, + { 5, 816, 1024 }, { 6, 817, 1024 }, { 6, 818, 1024 }, { 7, 819, 1024 }, { 6, 820, 1024 }, { 7, 821, 1024 }, { 7, 822, 1024 }, { 8, 823, 1024 }, + { 6, 824, 1024 }, { 7, 825, 1024 }, { 7, 826, 1024 }, { 8, 827, 1024 }, { 7, 828, 1024 }, { 8, 829, 1024 }, { 8, 830, 1024 }, { 9, 831, 1024 }, + { 4, 832, 1024 }, { 5, 833, 1024 }, { 5, 834, 1024 }, { 6, 835, 1024 }, { 5, 836, 1024 }, { 6, 837, 1024 }, { 6, 838, 1024 }, { 7, 839, 1024 }, + { 5, 840, 1024 }, { 6, 841, 1024 }, { 6, 842, 1024 }, { 7, 843, 1024 }, { 6, 844, 1024 }, { 7, 845, 1024 }, { 7, 846, 1024 }, { 8, 847, 1024 }, + { 5, 848, 1024 }, { 6, 849, 1024 }, { 6, 850, 1024 }, { 7, 851, 1024 }, { 6, 852, 1024 }, { 7, 853, 1024 }, { 7, 854, 1024 }, { 8, 855, 1024 }, + { 6, 856, 1024 }, { 7, 857, 1024 }, { 7, 858, 1024 }, { 8, 859, 1024 }, { 7, 860, 1024 }, { 8, 861, 1024 }, { 8, 862, 1024 }, { 9, 863, 1024 }, + { 5, 864, 1024 }, { 6, 865, 1024 }, { 6, 866, 1024 }, { 7, 867, 1024 }, { 6, 868, 1024 }, { 7, 869, 1024 }, { 7, 870, 1024 }, { 8, 871, 1024 }, + { 6, 872, 1024 }, { 7, 873, 1024 }, { 7, 874, 1024 }, { 8, 875, 1024 }, { 7, 876, 1024 }, { 8, 877, 1024 }, { 8, 878, 1024 }, { 9, 879, 1024 }, + { 6, 880, 1024 }, { 7, 881, 1024 }, { 7, 882, 1024 }, { 8, 883, 1024 }, { 7, 884, 1024 }, { 8, 885, 1024 }, { 8, 886, 1024 }, { 9, 887, 1024 }, + { 7, 888, 1024 }, { 8, 889, 1024 }, { 8, 890, 1024 }, { 9, 891, 1024 }, { 8, 892, 1024 }, { 9, 893, 1024 }, { 9, 894, 1024 }, { 10, 895, 1024 }, + { 4, 896, 1024 }, { 5, 897, 1024 }, { 5, 898, 1024 }, { 6, 899, 1024 }, { 5, 900, 1024 }, { 6, 901, 1024 }, { 6, 902, 1024 }, { 7, 903, 1024 }, + { 5, 904, 1024 }, { 6, 905, 1024 }, { 6, 906, 1024 }, { 7, 907, 1024 }, { 6, 908, 1024 }, { 7, 909, 1024 }, { 7, 910, 1024 }, { 8, 911, 1024 }, + { 5, 912, 1024 }, { 6, 913, 1024 }, { 6, 914, 1024 }, { 7, 915, 1024 }, { 6, 916, 1024 }, { 7, 917, 1024 }, { 7, 918, 1024 }, { 8, 919, 1024 }, + { 6, 920, 1024 }, { 7, 921, 1024 }, { 7, 922, 1024 }, { 8, 923, 1024 }, { 7, 924, 1024 }, { 8, 925, 1024 }, { 8, 926, 1024 }, { 9, 927, 1024 }, + { 5, 928, 1024 }, { 6, 929, 1024 }, { 6, 930, 1024 }, { 7, 931, 1024 }, { 6, 932, 1024 }, { 7, 933, 1024 }, { 7, 934, 1024 }, { 8, 935, 1024 }, + { 6, 936, 1024 }, { 7, 937, 1024 }, { 7, 938, 1024 }, { 8, 939, 1024 }, { 7, 940, 1024 }, { 8, 941, 1024 }, { 8, 942, 1024 }, { 9, 943, 1024 }, + { 6, 944, 1024 }, { 7, 945, 1024 }, { 7, 946, 1024 }, { 8, 947, 1024 }, { 7, 948, 1024 }, { 8, 949, 1024 }, { 8, 950, 1024 }, { 9, 951, 1024 }, + { 7, 952, 1024 }, { 8, 953, 1024 }, { 8, 954, 1024 }, { 9, 955, 1024 }, { 8, 956, 1024 }, { 9, 957, 1024 }, { 9, 958, 1024 }, { 10, 959, 1024 }, + { 5, 960, 1024 }, { 6, 961, 1024 }, { 6, 962, 1024 }, { 7, 963, 1024 }, { 6, 964, 1024 }, { 7, 965, 1024 }, { 7, 966, 1024 }, { 8, 967, 1024 }, + { 6, 968, 1024 }, { 7, 969, 1024 }, { 7, 970, 1024 }, { 8, 971, 1024 }, { 7, 972, 1024 }, { 8, 973, 1024 }, { 8, 974, 1024 }, { 9, 975, 1024 }, + { 6, 976, 1024 }, { 7, 977, 1024 }, { 7, 978, 1024 }, { 8, 979, 1024 }, { 7, 980, 1024 }, { 8, 981, 1024 }, { 8, 982, 1024 }, { 9, 983, 1024 }, + { 7, 984, 1024 }, { 8, 985, 1024 }, { 8, 986, 1024 }, { 9, 987, 1024 }, { 8, 988, 1024 }, { 9, 989, 1024 }, { 9, 990, 1024 }, { 10, 991, 1024 }, + { 6, 992, 1024 }, { 7, 993, 1024 }, { 7, 994, 1024 }, { 8, 995, 1024 }, { 7, 996, 1024 }, { 8, 997, 1024 }, { 8, 998, 1024 }, { 9, 999, 1024 }, + { 7, 1000, 1024 }, { 8, 1001, 1024 }, { 8, 1002, 1024 }, { 9, 1003, 1024 }, { 8, 1004, 1024 }, { 9, 1005, 1024 }, { 9, 1006, 1024 }, { 10, 1007, 1024 }, + { 7, 1008, 1024 }, { 8, 1009, 1024 }, { 8, 1010, 1024 }, { 9, 1011, 1024 }, { 8, 1012, 1024 }, { 9, 1013, 1024 }, { 9, 1014, 1024 }, { 10, 1015, 1024 }, + { 8, 1016, 1024 }, { 9, 1017, 1024 }, { 9, 1018, 1024 }, { 10, 1019, 1024 }, { 9, 1020, 1024 }, { 10, 1021, 1024 }, { 10, 1022, 1024 }, { 11, 1023, 1024 }, +#if FP_LUT > 11 + { 1, 0, 0 }, { 2, 1, 2048 }, { 2, 2, 2048 }, { 3, 3, 2048 }, { 2, 4, 2048 }, { 3, 5, 2048 }, { 3, 6, 2048 }, { 4, 7, 2048 }, + { 2, 8, 2048 }, { 3, 9, 2048 }, { 3, 10, 2048 }, { 4, 11, 2048 }, { 3, 12, 2048 }, { 4, 13, 2048 }, { 4, 14, 2048 }, { 5, 15, 2048 }, + { 2, 16, 2048 }, { 3, 17, 2048 }, { 3, 18, 2048 }, { 4, 19, 2048 }, { 3, 20, 2048 }, { 4, 21, 2048 }, { 4, 22, 2048 }, { 5, 23, 2048 }, + { 3, 24, 2048 }, { 4, 25, 2048 }, { 4, 26, 2048 }, { 5, 27, 2048 }, { 4, 28, 2048 }, { 5, 29, 2048 }, { 5, 30, 2048 }, { 6, 31, 2048 }, + { 2, 32, 2048 }, { 3, 33, 2048 }, { 3, 34, 2048 }, { 4, 35, 2048 }, { 3, 36, 2048 }, { 4, 37, 2048 }, { 4, 38, 2048 }, { 5, 39, 2048 }, + { 3, 40, 2048 }, { 4, 41, 2048 }, { 4, 42, 2048 }, { 5, 43, 2048 }, { 4, 44, 2048 }, { 5, 45, 2048 }, { 5, 46, 2048 }, { 6, 47, 2048 }, + { 3, 48, 2048 }, { 4, 49, 2048 }, { 4, 50, 2048 }, { 5, 51, 2048 }, { 4, 52, 2048 }, { 5, 53, 2048 }, { 5, 54, 2048 }, { 6, 55, 2048 }, + { 4, 56, 2048 }, { 5, 57, 2048 }, { 5, 58, 2048 }, { 6, 59, 2048 }, { 5, 60, 2048 }, { 6, 61, 2048 }, { 6, 62, 2048 }, { 7, 63, 2048 }, + { 2, 64, 2048 }, { 3, 65, 2048 }, { 3, 66, 2048 }, { 4, 67, 2048 }, { 3, 68, 2048 }, { 4, 69, 2048 }, { 4, 70, 2048 }, { 5, 71, 2048 }, + { 3, 72, 2048 }, { 4, 73, 2048 }, { 4, 74, 2048 }, { 5, 75, 2048 }, { 4, 76, 2048 }, { 5, 77, 2048 }, { 5, 78, 2048 }, { 6, 79, 2048 }, + { 3, 80, 2048 }, { 4, 81, 2048 }, { 4, 82, 2048 }, { 5, 83, 2048 }, { 4, 84, 2048 }, { 5, 85, 2048 }, { 5, 86, 2048 }, { 6, 87, 2048 }, + { 4, 88, 2048 }, { 5, 89, 2048 }, { 5, 90, 2048 }, { 6, 91, 2048 }, { 5, 92, 2048 }, { 6, 93, 2048 }, { 6, 94, 2048 }, { 7, 95, 2048 }, + { 3, 96, 2048 }, { 4, 97, 2048 }, { 4, 98, 2048 }, { 5, 99, 2048 }, { 4, 100, 2048 }, { 5, 101, 2048 }, { 5, 102, 2048 }, { 6, 103, 2048 }, + { 4, 104, 2048 }, { 5, 105, 2048 }, { 5, 106, 2048 }, { 6, 107, 2048 }, { 5, 108, 2048 }, { 6, 109, 2048 }, { 6, 110, 2048 }, { 7, 111, 2048 }, + { 4, 112, 2048 }, { 5, 113, 2048 }, { 5, 114, 2048 }, { 6, 115, 2048 }, { 5, 116, 2048 }, { 6, 117, 2048 }, { 6, 118, 2048 }, { 7, 119, 2048 }, + { 5, 120, 2048 }, { 6, 121, 2048 }, { 6, 122, 2048 }, { 7, 123, 2048 }, { 6, 124, 2048 }, { 7, 125, 2048 }, { 7, 126, 2048 }, { 8, 127, 2048 }, + { 2, 128, 2048 }, { 3, 129, 2048 }, { 3, 130, 2048 }, { 4, 131, 2048 }, { 3, 132, 2048 }, { 4, 133, 2048 }, { 4, 134, 2048 }, { 5, 135, 2048 }, + { 3, 136, 2048 }, { 4, 137, 2048 }, { 4, 138, 2048 }, { 5, 139, 2048 }, { 4, 140, 2048 }, { 5, 141, 2048 }, { 5, 142, 2048 }, { 6, 143, 2048 }, + { 3, 144, 2048 }, { 4, 145, 2048 }, { 4, 146, 2048 }, { 5, 147, 2048 }, { 4, 148, 2048 }, { 5, 149, 2048 }, { 5, 150, 2048 }, { 6, 151, 2048 }, + { 4, 152, 2048 }, { 5, 153, 2048 }, { 5, 154, 2048 }, { 6, 155, 2048 }, { 5, 156, 2048 }, { 6, 157, 2048 }, { 6, 158, 2048 }, { 7, 159, 2048 }, + { 3, 160, 2048 }, { 4, 161, 2048 }, { 4, 162, 2048 }, { 5, 163, 2048 }, { 4, 164, 2048 }, { 5, 165, 2048 }, { 5, 166, 2048 }, { 6, 167, 2048 }, + { 4, 168, 2048 }, { 5, 169, 2048 }, { 5, 170, 2048 }, { 6, 171, 2048 }, { 5, 172, 2048 }, { 6, 173, 2048 }, { 6, 174, 2048 }, { 7, 175, 2048 }, + { 4, 176, 2048 }, { 5, 177, 2048 }, { 5, 178, 2048 }, { 6, 179, 2048 }, { 5, 180, 2048 }, { 6, 181, 2048 }, { 6, 182, 2048 }, { 7, 183, 2048 }, + { 5, 184, 2048 }, { 6, 185, 2048 }, { 6, 186, 2048 }, { 7, 187, 2048 }, { 6, 188, 2048 }, { 7, 189, 2048 }, { 7, 190, 2048 }, { 8, 191, 2048 }, + { 3, 192, 2048 }, { 4, 193, 2048 }, { 4, 194, 2048 }, { 5, 195, 2048 }, { 4, 196, 2048 }, { 5, 197, 2048 }, { 5, 198, 2048 }, { 6, 199, 2048 }, + { 4, 200, 2048 }, { 5, 201, 2048 }, { 5, 202, 2048 }, { 6, 203, 2048 }, { 5, 204, 2048 }, { 6, 205, 2048 }, { 6, 206, 2048 }, { 7, 207, 2048 }, + { 4, 208, 2048 }, { 5, 209, 2048 }, { 5, 210, 2048 }, { 6, 211, 2048 }, { 5, 212, 2048 }, { 6, 213, 2048 }, { 6, 214, 2048 }, { 7, 215, 2048 }, + { 5, 216, 2048 }, { 6, 217, 2048 }, { 6, 218, 2048 }, { 7, 219, 2048 }, { 6, 220, 2048 }, { 7, 221, 2048 }, { 7, 222, 2048 }, { 8, 223, 2048 }, + { 4, 224, 2048 }, { 5, 225, 2048 }, { 5, 226, 2048 }, { 6, 227, 2048 }, { 5, 228, 2048 }, { 6, 229, 2048 }, { 6, 230, 2048 }, { 7, 231, 2048 }, + { 5, 232, 2048 }, { 6, 233, 2048 }, { 6, 234, 2048 }, { 7, 235, 2048 }, { 6, 236, 2048 }, { 7, 237, 2048 }, { 7, 238, 2048 }, { 8, 239, 2048 }, + { 5, 240, 2048 }, { 6, 241, 2048 }, { 6, 242, 2048 }, { 7, 243, 2048 }, { 6, 244, 2048 }, { 7, 245, 2048 }, { 7, 246, 2048 }, { 8, 247, 2048 }, + { 6, 248, 2048 }, { 7, 249, 2048 }, { 7, 250, 2048 }, { 8, 251, 2048 }, { 7, 252, 2048 }, { 8, 253, 2048 }, { 8, 254, 2048 }, { 9, 255, 2048 }, + { 2, 256, 2048 }, { 3, 257, 2048 }, { 3, 258, 2048 }, { 4, 259, 2048 }, { 3, 260, 2048 }, { 4, 261, 2048 }, { 4, 262, 2048 }, { 5, 263, 2048 }, + { 3, 264, 2048 }, { 4, 265, 2048 }, { 4, 266, 2048 }, { 5, 267, 2048 }, { 4, 268, 2048 }, { 5, 269, 2048 }, { 5, 270, 2048 }, { 6, 271, 2048 }, + { 3, 272, 2048 }, { 4, 273, 2048 }, { 4, 274, 2048 }, { 5, 275, 2048 }, { 4, 276, 2048 }, { 5, 277, 2048 }, { 5, 278, 2048 }, { 6, 279, 2048 }, + { 4, 280, 2048 }, { 5, 281, 2048 }, { 5, 282, 2048 }, { 6, 283, 2048 }, { 5, 284, 2048 }, { 6, 285, 2048 }, { 6, 286, 2048 }, { 7, 287, 2048 }, + { 3, 288, 2048 }, { 4, 289, 2048 }, { 4, 290, 2048 }, { 5, 291, 2048 }, { 4, 292, 2048 }, { 5, 293, 2048 }, { 5, 294, 2048 }, { 6, 295, 2048 }, + { 4, 296, 2048 }, { 5, 297, 2048 }, { 5, 298, 2048 }, { 6, 299, 2048 }, { 5, 300, 2048 }, { 6, 301, 2048 }, { 6, 302, 2048 }, { 7, 303, 2048 }, + { 4, 304, 2048 }, { 5, 305, 2048 }, { 5, 306, 2048 }, { 6, 307, 2048 }, { 5, 308, 2048 }, { 6, 309, 2048 }, { 6, 310, 2048 }, { 7, 311, 2048 }, + { 5, 312, 2048 }, { 6, 313, 2048 }, { 6, 314, 2048 }, { 7, 315, 2048 }, { 6, 316, 2048 }, { 7, 317, 2048 }, { 7, 318, 2048 }, { 8, 319, 2048 }, + { 3, 320, 2048 }, { 4, 321, 2048 }, { 4, 322, 2048 }, { 5, 323, 2048 }, { 4, 324, 2048 }, { 5, 325, 2048 }, { 5, 326, 2048 }, { 6, 327, 2048 }, + { 4, 328, 2048 }, { 5, 329, 2048 }, { 5, 330, 2048 }, { 6, 331, 2048 }, { 5, 332, 2048 }, { 6, 333, 2048 }, { 6, 334, 2048 }, { 7, 335, 2048 }, + { 4, 336, 2048 }, { 5, 337, 2048 }, { 5, 338, 2048 }, { 6, 339, 2048 }, { 5, 340, 2048 }, { 6, 341, 2048 }, { 6, 342, 2048 }, { 7, 343, 2048 }, + { 5, 344, 2048 }, { 6, 345, 2048 }, { 6, 346, 2048 }, { 7, 347, 2048 }, { 6, 348, 2048 }, { 7, 349, 2048 }, { 7, 350, 2048 }, { 8, 351, 2048 }, + { 4, 352, 2048 }, { 5, 353, 2048 }, { 5, 354, 2048 }, { 6, 355, 2048 }, { 5, 356, 2048 }, { 6, 357, 2048 }, { 6, 358, 2048 }, { 7, 359, 2048 }, + { 5, 360, 2048 }, { 6, 361, 2048 }, { 6, 362, 2048 }, { 7, 363, 2048 }, { 6, 364, 2048 }, { 7, 365, 2048 }, { 7, 366, 2048 }, { 8, 367, 2048 }, + { 5, 368, 2048 }, { 6, 369, 2048 }, { 6, 370, 2048 }, { 7, 371, 2048 }, { 6, 372, 2048 }, { 7, 373, 2048 }, { 7, 374, 2048 }, { 8, 375, 2048 }, + { 6, 376, 2048 }, { 7, 377, 2048 }, { 7, 378, 2048 }, { 8, 379, 2048 }, { 7, 380, 2048 }, { 8, 381, 2048 }, { 8, 382, 2048 }, { 9, 383, 2048 }, + { 3, 384, 2048 }, { 4, 385, 2048 }, { 4, 386, 2048 }, { 5, 387, 2048 }, { 4, 388, 2048 }, { 5, 389, 2048 }, { 5, 390, 2048 }, { 6, 391, 2048 }, + { 4, 392, 2048 }, { 5, 393, 2048 }, { 5, 394, 2048 }, { 6, 395, 2048 }, { 5, 396, 2048 }, { 6, 397, 2048 }, { 6, 398, 2048 }, { 7, 399, 2048 }, + { 4, 400, 2048 }, { 5, 401, 2048 }, { 5, 402, 2048 }, { 6, 403, 2048 }, { 5, 404, 2048 }, { 6, 405, 2048 }, { 6, 406, 2048 }, { 7, 407, 2048 }, + { 5, 408, 2048 }, { 6, 409, 2048 }, { 6, 410, 2048 }, { 7, 411, 2048 }, { 6, 412, 2048 }, { 7, 413, 2048 }, { 7, 414, 2048 }, { 8, 415, 2048 }, + { 4, 416, 2048 }, { 5, 417, 2048 }, { 5, 418, 2048 }, { 6, 419, 2048 }, { 5, 420, 2048 }, { 6, 421, 2048 }, { 6, 422, 2048 }, { 7, 423, 2048 }, + { 5, 424, 2048 }, { 6, 425, 2048 }, { 6, 426, 2048 }, { 7, 427, 2048 }, { 6, 428, 2048 }, { 7, 429, 2048 }, { 7, 430, 2048 }, { 8, 431, 2048 }, + { 5, 432, 2048 }, { 6, 433, 2048 }, { 6, 434, 2048 }, { 7, 435, 2048 }, { 6, 436, 2048 }, { 7, 437, 2048 }, { 7, 438, 2048 }, { 8, 439, 2048 }, + { 6, 440, 2048 }, { 7, 441, 2048 }, { 7, 442, 2048 }, { 8, 443, 2048 }, { 7, 444, 2048 }, { 8, 445, 2048 }, { 8, 446, 2048 }, { 9, 447, 2048 }, + { 4, 448, 2048 }, { 5, 449, 2048 }, { 5, 450, 2048 }, { 6, 451, 2048 }, { 5, 452, 2048 }, { 6, 453, 2048 }, { 6, 454, 2048 }, { 7, 455, 2048 }, + { 5, 456, 2048 }, { 6, 457, 2048 }, { 6, 458, 2048 }, { 7, 459, 2048 }, { 6, 460, 2048 }, { 7, 461, 2048 }, { 7, 462, 2048 }, { 8, 463, 2048 }, + { 5, 464, 2048 }, { 6, 465, 2048 }, { 6, 466, 2048 }, { 7, 467, 2048 }, { 6, 468, 2048 }, { 7, 469, 2048 }, { 7, 470, 2048 }, { 8, 471, 2048 }, + { 6, 472, 2048 }, { 7, 473, 2048 }, { 7, 474, 2048 }, { 8, 475, 2048 }, { 7, 476, 2048 }, { 8, 477, 2048 }, { 8, 478, 2048 }, { 9, 479, 2048 }, + { 5, 480, 2048 }, { 6, 481, 2048 }, { 6, 482, 2048 }, { 7, 483, 2048 }, { 6, 484, 2048 }, { 7, 485, 2048 }, { 7, 486, 2048 }, { 8, 487, 2048 }, + { 6, 488, 2048 }, { 7, 489, 2048 }, { 7, 490, 2048 }, { 8, 491, 2048 }, { 7, 492, 2048 }, { 8, 493, 2048 }, { 8, 494, 2048 }, { 9, 495, 2048 }, + { 6, 496, 2048 }, { 7, 497, 2048 }, { 7, 498, 2048 }, { 8, 499, 2048 }, { 7, 500, 2048 }, { 8, 501, 2048 }, { 8, 502, 2048 }, { 9, 503, 2048 }, + { 7, 504, 2048 }, { 8, 505, 2048 }, { 8, 506, 2048 }, { 9, 507, 2048 }, { 8, 508, 2048 }, { 9, 509, 2048 }, { 9, 510, 2048 }, { 10, 511, 2048 }, + { 2, 512, 2048 }, { 3, 513, 2048 }, { 3, 514, 2048 }, { 4, 515, 2048 }, { 3, 516, 2048 }, { 4, 517, 2048 }, { 4, 518, 2048 }, { 5, 519, 2048 }, + { 3, 520, 2048 }, { 4, 521, 2048 }, { 4, 522, 2048 }, { 5, 523, 2048 }, { 4, 524, 2048 }, { 5, 525, 2048 }, { 5, 526, 2048 }, { 6, 527, 2048 }, + { 3, 528, 2048 }, { 4, 529, 2048 }, { 4, 530, 2048 }, { 5, 531, 2048 }, { 4, 532, 2048 }, { 5, 533, 2048 }, { 5, 534, 2048 }, { 6, 535, 2048 }, + { 4, 536, 2048 }, { 5, 537, 2048 }, { 5, 538, 2048 }, { 6, 539, 2048 }, { 5, 540, 2048 }, { 6, 541, 2048 }, { 6, 542, 2048 }, { 7, 543, 2048 }, + { 3, 544, 2048 }, { 4, 545, 2048 }, { 4, 546, 2048 }, { 5, 547, 2048 }, { 4, 548, 2048 }, { 5, 549, 2048 }, { 5, 550, 2048 }, { 6, 551, 2048 }, + { 4, 552, 2048 }, { 5, 553, 2048 }, { 5, 554, 2048 }, { 6, 555, 2048 }, { 5, 556, 2048 }, { 6, 557, 2048 }, { 6, 558, 2048 }, { 7, 559, 2048 }, + { 4, 560, 2048 }, { 5, 561, 2048 }, { 5, 562, 2048 }, { 6, 563, 2048 }, { 5, 564, 2048 }, { 6, 565, 2048 }, { 6, 566, 2048 }, { 7, 567, 2048 }, + { 5, 568, 2048 }, { 6, 569, 2048 }, { 6, 570, 2048 }, { 7, 571, 2048 }, { 6, 572, 2048 }, { 7, 573, 2048 }, { 7, 574, 2048 }, { 8, 575, 2048 }, + { 3, 576, 2048 }, { 4, 577, 2048 }, { 4, 578, 2048 }, { 5, 579, 2048 }, { 4, 580, 2048 }, { 5, 581, 2048 }, { 5, 582, 2048 }, { 6, 583, 2048 }, + { 4, 584, 2048 }, { 5, 585, 2048 }, { 5, 586, 2048 }, { 6, 587, 2048 }, { 5, 588, 2048 }, { 6, 589, 2048 }, { 6, 590, 2048 }, { 7, 591, 2048 }, + { 4, 592, 2048 }, { 5, 593, 2048 }, { 5, 594, 2048 }, { 6, 595, 2048 }, { 5, 596, 2048 }, { 6, 597, 2048 }, { 6, 598, 2048 }, { 7, 599, 2048 }, + { 5, 600, 2048 }, { 6, 601, 2048 }, { 6, 602, 2048 }, { 7, 603, 2048 }, { 6, 604, 2048 }, { 7, 605, 2048 }, { 7, 606, 2048 }, { 8, 607, 2048 }, + { 4, 608, 2048 }, { 5, 609, 2048 }, { 5, 610, 2048 }, { 6, 611, 2048 }, { 5, 612, 2048 }, { 6, 613, 2048 }, { 6, 614, 2048 }, { 7, 615, 2048 }, + { 5, 616, 2048 }, { 6, 617, 2048 }, { 6, 618, 2048 }, { 7, 619, 2048 }, { 6, 620, 2048 }, { 7, 621, 2048 }, { 7, 622, 2048 }, { 8, 623, 2048 }, + { 5, 624, 2048 }, { 6, 625, 2048 }, { 6, 626, 2048 }, { 7, 627, 2048 }, { 6, 628, 2048 }, { 7, 629, 2048 }, { 7, 630, 2048 }, { 8, 631, 2048 }, + { 6, 632, 2048 }, { 7, 633, 2048 }, { 7, 634, 2048 }, { 8, 635, 2048 }, { 7, 636, 2048 }, { 8, 637, 2048 }, { 8, 638, 2048 }, { 9, 639, 2048 }, + { 3, 640, 2048 }, { 4, 641, 2048 }, { 4, 642, 2048 }, { 5, 643, 2048 }, { 4, 644, 2048 }, { 5, 645, 2048 }, { 5, 646, 2048 }, { 6, 647, 2048 }, + { 4, 648, 2048 }, { 5, 649, 2048 }, { 5, 650, 2048 }, { 6, 651, 2048 }, { 5, 652, 2048 }, { 6, 653, 2048 }, { 6, 654, 2048 }, { 7, 655, 2048 }, + { 4, 656, 2048 }, { 5, 657, 2048 }, { 5, 658, 2048 }, { 6, 659, 2048 }, { 5, 660, 2048 }, { 6, 661, 2048 }, { 6, 662, 2048 }, { 7, 663, 2048 }, + { 5, 664, 2048 }, { 6, 665, 2048 }, { 6, 666, 2048 }, { 7, 667, 2048 }, { 6, 668, 2048 }, { 7, 669, 2048 }, { 7, 670, 2048 }, { 8, 671, 2048 }, + { 4, 672, 2048 }, { 5, 673, 2048 }, { 5, 674, 2048 }, { 6, 675, 2048 }, { 5, 676, 2048 }, { 6, 677, 2048 }, { 6, 678, 2048 }, { 7, 679, 2048 }, + { 5, 680, 2048 }, { 6, 681, 2048 }, { 6, 682, 2048 }, { 7, 683, 2048 }, { 6, 684, 2048 }, { 7, 685, 2048 }, { 7, 686, 2048 }, { 8, 687, 2048 }, + { 5, 688, 2048 }, { 6, 689, 2048 }, { 6, 690, 2048 }, { 7, 691, 2048 }, { 6, 692, 2048 }, { 7, 693, 2048 }, { 7, 694, 2048 }, { 8, 695, 2048 }, + { 6, 696, 2048 }, { 7, 697, 2048 }, { 7, 698, 2048 }, { 8, 699, 2048 }, { 7, 700, 2048 }, { 8, 701, 2048 }, { 8, 702, 2048 }, { 9, 703, 2048 }, + { 4, 704, 2048 }, { 5, 705, 2048 }, { 5, 706, 2048 }, { 6, 707, 2048 }, { 5, 708, 2048 }, { 6, 709, 2048 }, { 6, 710, 2048 }, { 7, 711, 2048 }, + { 5, 712, 2048 }, { 6, 713, 2048 }, { 6, 714, 2048 }, { 7, 715, 2048 }, { 6, 716, 2048 }, { 7, 717, 2048 }, { 7, 718, 2048 }, { 8, 719, 2048 }, + { 5, 720, 2048 }, { 6, 721, 2048 }, { 6, 722, 2048 }, { 7, 723, 2048 }, { 6, 724, 2048 }, { 7, 725, 2048 }, { 7, 726, 2048 }, { 8, 727, 2048 }, + { 6, 728, 2048 }, { 7, 729, 2048 }, { 7, 730, 2048 }, { 8, 731, 2048 }, { 7, 732, 2048 }, { 8, 733, 2048 }, { 8, 734, 2048 }, { 9, 735, 2048 }, + { 5, 736, 2048 }, { 6, 737, 2048 }, { 6, 738, 2048 }, { 7, 739, 2048 }, { 6, 740, 2048 }, { 7, 741, 2048 }, { 7, 742, 2048 }, { 8, 743, 2048 }, + { 6, 744, 2048 }, { 7, 745, 2048 }, { 7, 746, 2048 }, { 8, 747, 2048 }, { 7, 748, 2048 }, { 8, 749, 2048 }, { 8, 750, 2048 }, { 9, 751, 2048 }, + { 6, 752, 2048 }, { 7, 753, 2048 }, { 7, 754, 2048 }, { 8, 755, 2048 }, { 7, 756, 2048 }, { 8, 757, 2048 }, { 8, 758, 2048 }, { 9, 759, 2048 }, + { 7, 760, 2048 }, { 8, 761, 2048 }, { 8, 762, 2048 }, { 9, 763, 2048 }, { 8, 764, 2048 }, { 9, 765, 2048 }, { 9, 766, 2048 }, { 10, 767, 2048 }, + { 3, 768, 2048 }, { 4, 769, 2048 }, { 4, 770, 2048 }, { 5, 771, 2048 }, { 4, 772, 2048 }, { 5, 773, 2048 }, { 5, 774, 2048 }, { 6, 775, 2048 }, + { 4, 776, 2048 }, { 5, 777, 2048 }, { 5, 778, 2048 }, { 6, 779, 2048 }, { 5, 780, 2048 }, { 6, 781, 2048 }, { 6, 782, 2048 }, { 7, 783, 2048 }, + { 4, 784, 2048 }, { 5, 785, 2048 }, { 5, 786, 2048 }, { 6, 787, 2048 }, { 5, 788, 2048 }, { 6, 789, 2048 }, { 6, 790, 2048 }, { 7, 791, 2048 }, + { 5, 792, 2048 }, { 6, 793, 2048 }, { 6, 794, 2048 }, { 7, 795, 2048 }, { 6, 796, 2048 }, { 7, 797, 2048 }, { 7, 798, 2048 }, { 8, 799, 2048 }, + { 4, 800, 2048 }, { 5, 801, 2048 }, { 5, 802, 2048 }, { 6, 803, 2048 }, { 5, 804, 2048 }, { 6, 805, 2048 }, { 6, 806, 2048 }, { 7, 807, 2048 }, + { 5, 808, 2048 }, { 6, 809, 2048 }, { 6, 810, 2048 }, { 7, 811, 2048 }, { 6, 812, 2048 }, { 7, 813, 2048 }, { 7, 814, 2048 }, { 8, 815, 2048 }, + { 5, 816, 2048 }, { 6, 817, 2048 }, { 6, 818, 2048 }, { 7, 819, 2048 }, { 6, 820, 2048 }, { 7, 821, 2048 }, { 7, 822, 2048 }, { 8, 823, 2048 }, + { 6, 824, 2048 }, { 7, 825, 2048 }, { 7, 826, 2048 }, { 8, 827, 2048 }, { 7, 828, 2048 }, { 8, 829, 2048 }, { 8, 830, 2048 }, { 9, 831, 2048 }, + { 4, 832, 2048 }, { 5, 833, 2048 }, { 5, 834, 2048 }, { 6, 835, 2048 }, { 5, 836, 2048 }, { 6, 837, 2048 }, { 6, 838, 2048 }, { 7, 839, 2048 }, + { 5, 840, 2048 }, { 6, 841, 2048 }, { 6, 842, 2048 }, { 7, 843, 2048 }, { 6, 844, 2048 }, { 7, 845, 2048 }, { 7, 846, 2048 }, { 8, 847, 2048 }, + { 5, 848, 2048 }, { 6, 849, 2048 }, { 6, 850, 2048 }, { 7, 851, 2048 }, { 6, 852, 2048 }, { 7, 853, 2048 }, { 7, 854, 2048 }, { 8, 855, 2048 }, + { 6, 856, 2048 }, { 7, 857, 2048 }, { 7, 858, 2048 }, { 8, 859, 2048 }, { 7, 860, 2048 }, { 8, 861, 2048 }, { 8, 862, 2048 }, { 9, 863, 2048 }, + { 5, 864, 2048 }, { 6, 865, 2048 }, { 6, 866, 2048 }, { 7, 867, 2048 }, { 6, 868, 2048 }, { 7, 869, 2048 }, { 7, 870, 2048 }, { 8, 871, 2048 }, + { 6, 872, 2048 }, { 7, 873, 2048 }, { 7, 874, 2048 }, { 8, 875, 2048 }, { 7, 876, 2048 }, { 8, 877, 2048 }, { 8, 878, 2048 }, { 9, 879, 2048 }, + { 6, 880, 2048 }, { 7, 881, 2048 }, { 7, 882, 2048 }, { 8, 883, 2048 }, { 7, 884, 2048 }, { 8, 885, 2048 }, { 8, 886, 2048 }, { 9, 887, 2048 }, + { 7, 888, 2048 }, { 8, 889, 2048 }, { 8, 890, 2048 }, { 9, 891, 2048 }, { 8, 892, 2048 }, { 9, 893, 2048 }, { 9, 894, 2048 }, { 10, 895, 2048 }, + { 4, 896, 2048 }, { 5, 897, 2048 }, { 5, 898, 2048 }, { 6, 899, 2048 }, { 5, 900, 2048 }, { 6, 901, 2048 }, { 6, 902, 2048 }, { 7, 903, 2048 }, + { 5, 904, 2048 }, { 6, 905, 2048 }, { 6, 906, 2048 }, { 7, 907, 2048 }, { 6, 908, 2048 }, { 7, 909, 2048 }, { 7, 910, 2048 }, { 8, 911, 2048 }, + { 5, 912, 2048 }, { 6, 913, 2048 }, { 6, 914, 2048 }, { 7, 915, 2048 }, { 6, 916, 2048 }, { 7, 917, 2048 }, { 7, 918, 2048 }, { 8, 919, 2048 }, + { 6, 920, 2048 }, { 7, 921, 2048 }, { 7, 922, 2048 }, { 8, 923, 2048 }, { 7, 924, 2048 }, { 8, 925, 2048 }, { 8, 926, 2048 }, { 9, 927, 2048 }, + { 5, 928, 2048 }, { 6, 929, 2048 }, { 6, 930, 2048 }, { 7, 931, 2048 }, { 6, 932, 2048 }, { 7, 933, 2048 }, { 7, 934, 2048 }, { 8, 935, 2048 }, + { 6, 936, 2048 }, { 7, 937, 2048 }, { 7, 938, 2048 }, { 8, 939, 2048 }, { 7, 940, 2048 }, { 8, 941, 2048 }, { 8, 942, 2048 }, { 9, 943, 2048 }, + { 6, 944, 2048 }, { 7, 945, 2048 }, { 7, 946, 2048 }, { 8, 947, 2048 }, { 7, 948, 2048 }, { 8, 949, 2048 }, { 8, 950, 2048 }, { 9, 951, 2048 }, + { 7, 952, 2048 }, { 8, 953, 2048 }, { 8, 954, 2048 }, { 9, 955, 2048 }, { 8, 956, 2048 }, { 9, 957, 2048 }, { 9, 958, 2048 }, { 10, 959, 2048 }, + { 5, 960, 2048 }, { 6, 961, 2048 }, { 6, 962, 2048 }, { 7, 963, 2048 }, { 6, 964, 2048 }, { 7, 965, 2048 }, { 7, 966, 2048 }, { 8, 967, 2048 }, + { 6, 968, 2048 }, { 7, 969, 2048 }, { 7, 970, 2048 }, { 8, 971, 2048 }, { 7, 972, 2048 }, { 8, 973, 2048 }, { 8, 974, 2048 }, { 9, 975, 2048 }, + { 6, 976, 2048 }, { 7, 977, 2048 }, { 7, 978, 2048 }, { 8, 979, 2048 }, { 7, 980, 2048 }, { 8, 981, 2048 }, { 8, 982, 2048 }, { 9, 983, 2048 }, + { 7, 984, 2048 }, { 8, 985, 2048 }, { 8, 986, 2048 }, { 9, 987, 2048 }, { 8, 988, 2048 }, { 9, 989, 2048 }, { 9, 990, 2048 }, { 10, 991, 2048 }, + { 6, 992, 2048 }, { 7, 993, 2048 }, { 7, 994, 2048 }, { 8, 995, 2048 }, { 7, 996, 2048 }, { 8, 997, 2048 }, { 8, 998, 2048 }, { 9, 999, 2048 }, + { 7, 1000, 2048 }, { 8, 1001, 2048 }, { 8, 1002, 2048 }, { 9, 1003, 2048 }, { 8, 1004, 2048 }, { 9, 1005, 2048 }, { 9, 1006, 2048 }, { 10, 1007, 2048 }, + { 7, 1008, 2048 }, { 8, 1009, 2048 }, { 8, 1010, 2048 }, { 9, 1011, 2048 }, { 8, 1012, 2048 }, { 9, 1013, 2048 }, { 9, 1014, 2048 }, { 10, 1015, 2048 }, + { 8, 1016, 2048 }, { 9, 1017, 2048 }, { 9, 1018, 2048 }, { 10, 1019, 2048 }, { 9, 1020, 2048 }, { 10, 1021, 2048 }, { 10, 1022, 2048 }, { 11, 1023, 2048 }, + { 2, 1024, 2048 }, { 3, 1025, 2048 }, { 3, 1026, 2048 }, { 4, 1027, 2048 }, { 3, 1028, 2048 }, { 4, 1029, 2048 }, { 4, 1030, 2048 }, { 5, 1031, 2048 }, + { 3, 1032, 2048 }, { 4, 1033, 2048 }, { 4, 1034, 2048 }, { 5, 1035, 2048 }, { 4, 1036, 2048 }, { 5, 1037, 2048 }, { 5, 1038, 2048 }, { 6, 1039, 2048 }, + { 3, 1040, 2048 }, { 4, 1041, 2048 }, { 4, 1042, 2048 }, { 5, 1043, 2048 }, { 4, 1044, 2048 }, { 5, 1045, 2048 }, { 5, 1046, 2048 }, { 6, 1047, 2048 }, + { 4, 1048, 2048 }, { 5, 1049, 2048 }, { 5, 1050, 2048 }, { 6, 1051, 2048 }, { 5, 1052, 2048 }, { 6, 1053, 2048 }, { 6, 1054, 2048 }, { 7, 1055, 2048 }, + { 3, 1056, 2048 }, { 4, 1057, 2048 }, { 4, 1058, 2048 }, { 5, 1059, 2048 }, { 4, 1060, 2048 }, { 5, 1061, 2048 }, { 5, 1062, 2048 }, { 6, 1063, 2048 }, + { 4, 1064, 2048 }, { 5, 1065, 2048 }, { 5, 1066, 2048 }, { 6, 1067, 2048 }, { 5, 1068, 2048 }, { 6, 1069, 2048 }, { 6, 1070, 2048 }, { 7, 1071, 2048 }, + { 4, 1072, 2048 }, { 5, 1073, 2048 }, { 5, 1074, 2048 }, { 6, 1075, 2048 }, { 5, 1076, 2048 }, { 6, 1077, 2048 }, { 6, 1078, 2048 }, { 7, 1079, 2048 }, + { 5, 1080, 2048 }, { 6, 1081, 2048 }, { 6, 1082, 2048 }, { 7, 1083, 2048 }, { 6, 1084, 2048 }, { 7, 1085, 2048 }, { 7, 1086, 2048 }, { 8, 1087, 2048 }, + { 3, 1088, 2048 }, { 4, 1089, 2048 }, { 4, 1090, 2048 }, { 5, 1091, 2048 }, { 4, 1092, 2048 }, { 5, 1093, 2048 }, { 5, 1094, 2048 }, { 6, 1095, 2048 }, + { 4, 1096, 2048 }, { 5, 1097, 2048 }, { 5, 1098, 2048 }, { 6, 1099, 2048 }, { 5, 1100, 2048 }, { 6, 1101, 2048 }, { 6, 1102, 2048 }, { 7, 1103, 2048 }, + { 4, 1104, 2048 }, { 5, 1105, 2048 }, { 5, 1106, 2048 }, { 6, 1107, 2048 }, { 5, 1108, 2048 }, { 6, 1109, 2048 }, { 6, 1110, 2048 }, { 7, 1111, 2048 }, + { 5, 1112, 2048 }, { 6, 1113, 2048 }, { 6, 1114, 2048 }, { 7, 1115, 2048 }, { 6, 1116, 2048 }, { 7, 1117, 2048 }, { 7, 1118, 2048 }, { 8, 1119, 2048 }, + { 4, 1120, 2048 }, { 5, 1121, 2048 }, { 5, 1122, 2048 }, { 6, 1123, 2048 }, { 5, 1124, 2048 }, { 6, 1125, 2048 }, { 6, 1126, 2048 }, { 7, 1127, 2048 }, + { 5, 1128, 2048 }, { 6, 1129, 2048 }, { 6, 1130, 2048 }, { 7, 1131, 2048 }, { 6, 1132, 2048 }, { 7, 1133, 2048 }, { 7, 1134, 2048 }, { 8, 1135, 2048 }, + { 5, 1136, 2048 }, { 6, 1137, 2048 }, { 6, 1138, 2048 }, { 7, 1139, 2048 }, { 6, 1140, 2048 }, { 7, 1141, 2048 }, { 7, 1142, 2048 }, { 8, 1143, 2048 }, + { 6, 1144, 2048 }, { 7, 1145, 2048 }, { 7, 1146, 2048 }, { 8, 1147, 2048 }, { 7, 1148, 2048 }, { 8, 1149, 2048 }, { 8, 1150, 2048 }, { 9, 1151, 2048 }, + { 3, 1152, 2048 }, { 4, 1153, 2048 }, { 4, 1154, 2048 }, { 5, 1155, 2048 }, { 4, 1156, 2048 }, { 5, 1157, 2048 }, { 5, 1158, 2048 }, { 6, 1159, 2048 }, + { 4, 1160, 2048 }, { 5, 1161, 2048 }, { 5, 1162, 2048 }, { 6, 1163, 2048 }, { 5, 1164, 2048 }, { 6, 1165, 2048 }, { 6, 1166, 2048 }, { 7, 1167, 2048 }, + { 4, 1168, 2048 }, { 5, 1169, 2048 }, { 5, 1170, 2048 }, { 6, 1171, 2048 }, { 5, 1172, 2048 }, { 6, 1173, 2048 }, { 6, 1174, 2048 }, { 7, 1175, 2048 }, + { 5, 1176, 2048 }, { 6, 1177, 2048 }, { 6, 1178, 2048 }, { 7, 1179, 2048 }, { 6, 1180, 2048 }, { 7, 1181, 2048 }, { 7, 1182, 2048 }, { 8, 1183, 2048 }, + { 4, 1184, 2048 }, { 5, 1185, 2048 }, { 5, 1186, 2048 }, { 6, 1187, 2048 }, { 5, 1188, 2048 }, { 6, 1189, 2048 }, { 6, 1190, 2048 }, { 7, 1191, 2048 }, + { 5, 1192, 2048 }, { 6, 1193, 2048 }, { 6, 1194, 2048 }, { 7, 1195, 2048 }, { 6, 1196, 2048 }, { 7, 1197, 2048 }, { 7, 1198, 2048 }, { 8, 1199, 2048 }, + { 5, 1200, 2048 }, { 6, 1201, 2048 }, { 6, 1202, 2048 }, { 7, 1203, 2048 }, { 6, 1204, 2048 }, { 7, 1205, 2048 }, { 7, 1206, 2048 }, { 8, 1207, 2048 }, + { 6, 1208, 2048 }, { 7, 1209, 2048 }, { 7, 1210, 2048 }, { 8, 1211, 2048 }, { 7, 1212, 2048 }, { 8, 1213, 2048 }, { 8, 1214, 2048 }, { 9, 1215, 2048 }, + { 4, 1216, 2048 }, { 5, 1217, 2048 }, { 5, 1218, 2048 }, { 6, 1219, 2048 }, { 5, 1220, 2048 }, { 6, 1221, 2048 }, { 6, 1222, 2048 }, { 7, 1223, 2048 }, + { 5, 1224, 2048 }, { 6, 1225, 2048 }, { 6, 1226, 2048 }, { 7, 1227, 2048 }, { 6, 1228, 2048 }, { 7, 1229, 2048 }, { 7, 1230, 2048 }, { 8, 1231, 2048 }, + { 5, 1232, 2048 }, { 6, 1233, 2048 }, { 6, 1234, 2048 }, { 7, 1235, 2048 }, { 6, 1236, 2048 }, { 7, 1237, 2048 }, { 7, 1238, 2048 }, { 8, 1239, 2048 }, + { 6, 1240, 2048 }, { 7, 1241, 2048 }, { 7, 1242, 2048 }, { 8, 1243, 2048 }, { 7, 1244, 2048 }, { 8, 1245, 2048 }, { 8, 1246, 2048 }, { 9, 1247, 2048 }, + { 5, 1248, 2048 }, { 6, 1249, 2048 }, { 6, 1250, 2048 }, { 7, 1251, 2048 }, { 6, 1252, 2048 }, { 7, 1253, 2048 }, { 7, 1254, 2048 }, { 8, 1255, 2048 }, + { 6, 1256, 2048 }, { 7, 1257, 2048 }, { 7, 1258, 2048 }, { 8, 1259, 2048 }, { 7, 1260, 2048 }, { 8, 1261, 2048 }, { 8, 1262, 2048 }, { 9, 1263, 2048 }, + { 6, 1264, 2048 }, { 7, 1265, 2048 }, { 7, 1266, 2048 }, { 8, 1267, 2048 }, { 7, 1268, 2048 }, { 8, 1269, 2048 }, { 8, 1270, 2048 }, { 9, 1271, 2048 }, + { 7, 1272, 2048 }, { 8, 1273, 2048 }, { 8, 1274, 2048 }, { 9, 1275, 2048 }, { 8, 1276, 2048 }, { 9, 1277, 2048 }, { 9, 1278, 2048 }, { 10, 1279, 2048 }, + { 3, 1280, 2048 }, { 4, 1281, 2048 }, { 4, 1282, 2048 }, { 5, 1283, 2048 }, { 4, 1284, 2048 }, { 5, 1285, 2048 }, { 5, 1286, 2048 }, { 6, 1287, 2048 }, + { 4, 1288, 2048 }, { 5, 1289, 2048 }, { 5, 1290, 2048 }, { 6, 1291, 2048 }, { 5, 1292, 2048 }, { 6, 1293, 2048 }, { 6, 1294, 2048 }, { 7, 1295, 2048 }, + { 4, 1296, 2048 }, { 5, 1297, 2048 }, { 5, 1298, 2048 }, { 6, 1299, 2048 }, { 5, 1300, 2048 }, { 6, 1301, 2048 }, { 6, 1302, 2048 }, { 7, 1303, 2048 }, + { 5, 1304, 2048 }, { 6, 1305, 2048 }, { 6, 1306, 2048 }, { 7, 1307, 2048 }, { 6, 1308, 2048 }, { 7, 1309, 2048 }, { 7, 1310, 2048 }, { 8, 1311, 2048 }, + { 4, 1312, 2048 }, { 5, 1313, 2048 }, { 5, 1314, 2048 }, { 6, 1315, 2048 }, { 5, 1316, 2048 }, { 6, 1317, 2048 }, { 6, 1318, 2048 }, { 7, 1319, 2048 }, + { 5, 1320, 2048 }, { 6, 1321, 2048 }, { 6, 1322, 2048 }, { 7, 1323, 2048 }, { 6, 1324, 2048 }, { 7, 1325, 2048 }, { 7, 1326, 2048 }, { 8, 1327, 2048 }, + { 5, 1328, 2048 }, { 6, 1329, 2048 }, { 6, 1330, 2048 }, { 7, 1331, 2048 }, { 6, 1332, 2048 }, { 7, 1333, 2048 }, { 7, 1334, 2048 }, { 8, 1335, 2048 }, + { 6, 1336, 2048 }, { 7, 1337, 2048 }, { 7, 1338, 2048 }, { 8, 1339, 2048 }, { 7, 1340, 2048 }, { 8, 1341, 2048 }, { 8, 1342, 2048 }, { 9, 1343, 2048 }, + { 4, 1344, 2048 }, { 5, 1345, 2048 }, { 5, 1346, 2048 }, { 6, 1347, 2048 }, { 5, 1348, 2048 }, { 6, 1349, 2048 }, { 6, 1350, 2048 }, { 7, 1351, 2048 }, + { 5, 1352, 2048 }, { 6, 1353, 2048 }, { 6, 1354, 2048 }, { 7, 1355, 2048 }, { 6, 1356, 2048 }, { 7, 1357, 2048 }, { 7, 1358, 2048 }, { 8, 1359, 2048 }, + { 5, 1360, 2048 }, { 6, 1361, 2048 }, { 6, 1362, 2048 }, { 7, 1363, 2048 }, { 6, 1364, 2048 }, { 7, 1365, 2048 }, { 7, 1366, 2048 }, { 8, 1367, 2048 }, + { 6, 1368, 2048 }, { 7, 1369, 2048 }, { 7, 1370, 2048 }, { 8, 1371, 2048 }, { 7, 1372, 2048 }, { 8, 1373, 2048 }, { 8, 1374, 2048 }, { 9, 1375, 2048 }, + { 5, 1376, 2048 }, { 6, 1377, 2048 }, { 6, 1378, 2048 }, { 7, 1379, 2048 }, { 6, 1380, 2048 }, { 7, 1381, 2048 }, { 7, 1382, 2048 }, { 8, 1383, 2048 }, + { 6, 1384, 2048 }, { 7, 1385, 2048 }, { 7, 1386, 2048 }, { 8, 1387, 2048 }, { 7, 1388, 2048 }, { 8, 1389, 2048 }, { 8, 1390, 2048 }, { 9, 1391, 2048 }, + { 6, 1392, 2048 }, { 7, 1393, 2048 }, { 7, 1394, 2048 }, { 8, 1395, 2048 }, { 7, 1396, 2048 }, { 8, 1397, 2048 }, { 8, 1398, 2048 }, { 9, 1399, 2048 }, + { 7, 1400, 2048 }, { 8, 1401, 2048 }, { 8, 1402, 2048 }, { 9, 1403, 2048 }, { 8, 1404, 2048 }, { 9, 1405, 2048 }, { 9, 1406, 2048 }, { 10, 1407, 2048 }, + { 4, 1408, 2048 }, { 5, 1409, 2048 }, { 5, 1410, 2048 }, { 6, 1411, 2048 }, { 5, 1412, 2048 }, { 6, 1413, 2048 }, { 6, 1414, 2048 }, { 7, 1415, 2048 }, + { 5, 1416, 2048 }, { 6, 1417, 2048 }, { 6, 1418, 2048 }, { 7, 1419, 2048 }, { 6, 1420, 2048 }, { 7, 1421, 2048 }, { 7, 1422, 2048 }, { 8, 1423, 2048 }, + { 5, 1424, 2048 }, { 6, 1425, 2048 }, { 6, 1426, 2048 }, { 7, 1427, 2048 }, { 6, 1428, 2048 }, { 7, 1429, 2048 }, { 7, 1430, 2048 }, { 8, 1431, 2048 }, + { 6, 1432, 2048 }, { 7, 1433, 2048 }, { 7, 1434, 2048 }, { 8, 1435, 2048 }, { 7, 1436, 2048 }, { 8, 1437, 2048 }, { 8, 1438, 2048 }, { 9, 1439, 2048 }, + { 5, 1440, 2048 }, { 6, 1441, 2048 }, { 6, 1442, 2048 }, { 7, 1443, 2048 }, { 6, 1444, 2048 }, { 7, 1445, 2048 }, { 7, 1446, 2048 }, { 8, 1447, 2048 }, + { 6, 1448, 2048 }, { 7, 1449, 2048 }, { 7, 1450, 2048 }, { 8, 1451, 2048 }, { 7, 1452, 2048 }, { 8, 1453, 2048 }, { 8, 1454, 2048 }, { 9, 1455, 2048 }, + { 6, 1456, 2048 }, { 7, 1457, 2048 }, { 7, 1458, 2048 }, { 8, 1459, 2048 }, { 7, 1460, 2048 }, { 8, 1461, 2048 }, { 8, 1462, 2048 }, { 9, 1463, 2048 }, + { 7, 1464, 2048 }, { 8, 1465, 2048 }, { 8, 1466, 2048 }, { 9, 1467, 2048 }, { 8, 1468, 2048 }, { 9, 1469, 2048 }, { 9, 1470, 2048 }, { 10, 1471, 2048 }, + { 5, 1472, 2048 }, { 6, 1473, 2048 }, { 6, 1474, 2048 }, { 7, 1475, 2048 }, { 6, 1476, 2048 }, { 7, 1477, 2048 }, { 7, 1478, 2048 }, { 8, 1479, 2048 }, + { 6, 1480, 2048 }, { 7, 1481, 2048 }, { 7, 1482, 2048 }, { 8, 1483, 2048 }, { 7, 1484, 2048 }, { 8, 1485, 2048 }, { 8, 1486, 2048 }, { 9, 1487, 2048 }, + { 6, 1488, 2048 }, { 7, 1489, 2048 }, { 7, 1490, 2048 }, { 8, 1491, 2048 }, { 7, 1492, 2048 }, { 8, 1493, 2048 }, { 8, 1494, 2048 }, { 9, 1495, 2048 }, + { 7, 1496, 2048 }, { 8, 1497, 2048 }, { 8, 1498, 2048 }, { 9, 1499, 2048 }, { 8, 1500, 2048 }, { 9, 1501, 2048 }, { 9, 1502, 2048 }, { 10, 1503, 2048 }, + { 6, 1504, 2048 }, { 7, 1505, 2048 }, { 7, 1506, 2048 }, { 8, 1507, 2048 }, { 7, 1508, 2048 }, { 8, 1509, 2048 }, { 8, 1510, 2048 }, { 9, 1511, 2048 }, + { 7, 1512, 2048 }, { 8, 1513, 2048 }, { 8, 1514, 2048 }, { 9, 1515, 2048 }, { 8, 1516, 2048 }, { 9, 1517, 2048 }, { 9, 1518, 2048 }, { 10, 1519, 2048 }, + { 7, 1520, 2048 }, { 8, 1521, 2048 }, { 8, 1522, 2048 }, { 9, 1523, 2048 }, { 8, 1524, 2048 }, { 9, 1525, 2048 }, { 9, 1526, 2048 }, { 10, 1527, 2048 }, + { 8, 1528, 2048 }, { 9, 1529, 2048 }, { 9, 1530, 2048 }, { 10, 1531, 2048 }, { 9, 1532, 2048 }, { 10, 1533, 2048 }, { 10, 1534, 2048 }, { 11, 1535, 2048 }, + { 3, 1536, 2048 }, { 4, 1537, 2048 }, { 4, 1538, 2048 }, { 5, 1539, 2048 }, { 4, 1540, 2048 }, { 5, 1541, 2048 }, { 5, 1542, 2048 }, { 6, 1543, 2048 }, + { 4, 1544, 2048 }, { 5, 1545, 2048 }, { 5, 1546, 2048 }, { 6, 1547, 2048 }, { 5, 1548, 2048 }, { 6, 1549, 2048 }, { 6, 1550, 2048 }, { 7, 1551, 2048 }, + { 4, 1552, 2048 }, { 5, 1553, 2048 }, { 5, 1554, 2048 }, { 6, 1555, 2048 }, { 5, 1556, 2048 }, { 6, 1557, 2048 }, { 6, 1558, 2048 }, { 7, 1559, 2048 }, + { 5, 1560, 2048 }, { 6, 1561, 2048 }, { 6, 1562, 2048 }, { 7, 1563, 2048 }, { 6, 1564, 2048 }, { 7, 1565, 2048 }, { 7, 1566, 2048 }, { 8, 1567, 2048 }, + { 4, 1568, 2048 }, { 5, 1569, 2048 }, { 5, 1570, 2048 }, { 6, 1571, 2048 }, { 5, 1572, 2048 }, { 6, 1573, 2048 }, { 6, 1574, 2048 }, { 7, 1575, 2048 }, + { 5, 1576, 2048 }, { 6, 1577, 2048 }, { 6, 1578, 2048 }, { 7, 1579, 2048 }, { 6, 1580, 2048 }, { 7, 1581, 2048 }, { 7, 1582, 2048 }, { 8, 1583, 2048 }, + { 5, 1584, 2048 }, { 6, 1585, 2048 }, { 6, 1586, 2048 }, { 7, 1587, 2048 }, { 6, 1588, 2048 }, { 7, 1589, 2048 }, { 7, 1590, 2048 }, { 8, 1591, 2048 }, + { 6, 1592, 2048 }, { 7, 1593, 2048 }, { 7, 1594, 2048 }, { 8, 1595, 2048 }, { 7, 1596, 2048 }, { 8, 1597, 2048 }, { 8, 1598, 2048 }, { 9, 1599, 2048 }, + { 4, 1600, 2048 }, { 5, 1601, 2048 }, { 5, 1602, 2048 }, { 6, 1603, 2048 }, { 5, 1604, 2048 }, { 6, 1605, 2048 }, { 6, 1606, 2048 }, { 7, 1607, 2048 }, + { 5, 1608, 2048 }, { 6, 1609, 2048 }, { 6, 1610, 2048 }, { 7, 1611, 2048 }, { 6, 1612, 2048 }, { 7, 1613, 2048 }, { 7, 1614, 2048 }, { 8, 1615, 2048 }, + { 5, 1616, 2048 }, { 6, 1617, 2048 }, { 6, 1618, 2048 }, { 7, 1619, 2048 }, { 6, 1620, 2048 }, { 7, 1621, 2048 }, { 7, 1622, 2048 }, { 8, 1623, 2048 }, + { 6, 1624, 2048 }, { 7, 1625, 2048 }, { 7, 1626, 2048 }, { 8, 1627, 2048 }, { 7, 1628, 2048 }, { 8, 1629, 2048 }, { 8, 1630, 2048 }, { 9, 1631, 2048 }, + { 5, 1632, 2048 }, { 6, 1633, 2048 }, { 6, 1634, 2048 }, { 7, 1635, 2048 }, { 6, 1636, 2048 }, { 7, 1637, 2048 }, { 7, 1638, 2048 }, { 8, 1639, 2048 }, + { 6, 1640, 2048 }, { 7, 1641, 2048 }, { 7, 1642, 2048 }, { 8, 1643, 2048 }, { 7, 1644, 2048 }, { 8, 1645, 2048 }, { 8, 1646, 2048 }, { 9, 1647, 2048 }, + { 6, 1648, 2048 }, { 7, 1649, 2048 }, { 7, 1650, 2048 }, { 8, 1651, 2048 }, { 7, 1652, 2048 }, { 8, 1653, 2048 }, { 8, 1654, 2048 }, { 9, 1655, 2048 }, + { 7, 1656, 2048 }, { 8, 1657, 2048 }, { 8, 1658, 2048 }, { 9, 1659, 2048 }, { 8, 1660, 2048 }, { 9, 1661, 2048 }, { 9, 1662, 2048 }, { 10, 1663, 2048 }, + { 4, 1664, 2048 }, { 5, 1665, 2048 }, { 5, 1666, 2048 }, { 6, 1667, 2048 }, { 5, 1668, 2048 }, { 6, 1669, 2048 }, { 6, 1670, 2048 }, { 7, 1671, 2048 }, + { 5, 1672, 2048 }, { 6, 1673, 2048 }, { 6, 1674, 2048 }, { 7, 1675, 2048 }, { 6, 1676, 2048 }, { 7, 1677, 2048 }, { 7, 1678, 2048 }, { 8, 1679, 2048 }, + { 5, 1680, 2048 }, { 6, 1681, 2048 }, { 6, 1682, 2048 }, { 7, 1683, 2048 }, { 6, 1684, 2048 }, { 7, 1685, 2048 }, { 7, 1686, 2048 }, { 8, 1687, 2048 }, + { 6, 1688, 2048 }, { 7, 1689, 2048 }, { 7, 1690, 2048 }, { 8, 1691, 2048 }, { 7, 1692, 2048 }, { 8, 1693, 2048 }, { 8, 1694, 2048 }, { 9, 1695, 2048 }, + { 5, 1696, 2048 }, { 6, 1697, 2048 }, { 6, 1698, 2048 }, { 7, 1699, 2048 }, { 6, 1700, 2048 }, { 7, 1701, 2048 }, { 7, 1702, 2048 }, { 8, 1703, 2048 }, + { 6, 1704, 2048 }, { 7, 1705, 2048 }, { 7, 1706, 2048 }, { 8, 1707, 2048 }, { 7, 1708, 2048 }, { 8, 1709, 2048 }, { 8, 1710, 2048 }, { 9, 1711, 2048 }, + { 6, 1712, 2048 }, { 7, 1713, 2048 }, { 7, 1714, 2048 }, { 8, 1715, 2048 }, { 7, 1716, 2048 }, { 8, 1717, 2048 }, { 8, 1718, 2048 }, { 9, 1719, 2048 }, + { 7, 1720, 2048 }, { 8, 1721, 2048 }, { 8, 1722, 2048 }, { 9, 1723, 2048 }, { 8, 1724, 2048 }, { 9, 1725, 2048 }, { 9, 1726, 2048 }, { 10, 1727, 2048 }, + { 5, 1728, 2048 }, { 6, 1729, 2048 }, { 6, 1730, 2048 }, { 7, 1731, 2048 }, { 6, 1732, 2048 }, { 7, 1733, 2048 }, { 7, 1734, 2048 }, { 8, 1735, 2048 }, + { 6, 1736, 2048 }, { 7, 1737, 2048 }, { 7, 1738, 2048 }, { 8, 1739, 2048 }, { 7, 1740, 2048 }, { 8, 1741, 2048 }, { 8, 1742, 2048 }, { 9, 1743, 2048 }, + { 6, 1744, 2048 }, { 7, 1745, 2048 }, { 7, 1746, 2048 }, { 8, 1747, 2048 }, { 7, 1748, 2048 }, { 8, 1749, 2048 }, { 8, 1750, 2048 }, { 9, 1751, 2048 }, + { 7, 1752, 2048 }, { 8, 1753, 2048 }, { 8, 1754, 2048 }, { 9, 1755, 2048 }, { 8, 1756, 2048 }, { 9, 1757, 2048 }, { 9, 1758, 2048 }, { 10, 1759, 2048 }, + { 6, 1760, 2048 }, { 7, 1761, 2048 }, { 7, 1762, 2048 }, { 8, 1763, 2048 }, { 7, 1764, 2048 }, { 8, 1765, 2048 }, { 8, 1766, 2048 }, { 9, 1767, 2048 }, + { 7, 1768, 2048 }, { 8, 1769, 2048 }, { 8, 1770, 2048 }, { 9, 1771, 2048 }, { 8, 1772, 2048 }, { 9, 1773, 2048 }, { 9, 1774, 2048 }, { 10, 1775, 2048 }, + { 7, 1776, 2048 }, { 8, 1777, 2048 }, { 8, 1778, 2048 }, { 9, 1779, 2048 }, { 8, 1780, 2048 }, { 9, 1781, 2048 }, { 9, 1782, 2048 }, { 10, 1783, 2048 }, + { 8, 1784, 2048 }, { 9, 1785, 2048 }, { 9, 1786, 2048 }, { 10, 1787, 2048 }, { 9, 1788, 2048 }, { 10, 1789, 2048 }, { 10, 1790, 2048 }, { 11, 1791, 2048 }, + { 4, 1792, 2048 }, { 5, 1793, 2048 }, { 5, 1794, 2048 }, { 6, 1795, 2048 }, { 5, 1796, 2048 }, { 6, 1797, 2048 }, { 6, 1798, 2048 }, { 7, 1799, 2048 }, + { 5, 1800, 2048 }, { 6, 1801, 2048 }, { 6, 1802, 2048 }, { 7, 1803, 2048 }, { 6, 1804, 2048 }, { 7, 1805, 2048 }, { 7, 1806, 2048 }, { 8, 1807, 2048 }, + { 5, 1808, 2048 }, { 6, 1809, 2048 }, { 6, 1810, 2048 }, { 7, 1811, 2048 }, { 6, 1812, 2048 }, { 7, 1813, 2048 }, { 7, 1814, 2048 }, { 8, 1815, 2048 }, + { 6, 1816, 2048 }, { 7, 1817, 2048 }, { 7, 1818, 2048 }, { 8, 1819, 2048 }, { 7, 1820, 2048 }, { 8, 1821, 2048 }, { 8, 1822, 2048 }, { 9, 1823, 2048 }, + { 5, 1824, 2048 }, { 6, 1825, 2048 }, { 6, 1826, 2048 }, { 7, 1827, 2048 }, { 6, 1828, 2048 }, { 7, 1829, 2048 }, { 7, 1830, 2048 }, { 8, 1831, 2048 }, + { 6, 1832, 2048 }, { 7, 1833, 2048 }, { 7, 1834, 2048 }, { 8, 1835, 2048 }, { 7, 1836, 2048 }, { 8, 1837, 2048 }, { 8, 1838, 2048 }, { 9, 1839, 2048 }, + { 6, 1840, 2048 }, { 7, 1841, 2048 }, { 7, 1842, 2048 }, { 8, 1843, 2048 }, { 7, 1844, 2048 }, { 8, 1845, 2048 }, { 8, 1846, 2048 }, { 9, 1847, 2048 }, + { 7, 1848, 2048 }, { 8, 1849, 2048 }, { 8, 1850, 2048 }, { 9, 1851, 2048 }, { 8, 1852, 2048 }, { 9, 1853, 2048 }, { 9, 1854, 2048 }, { 10, 1855, 2048 }, + { 5, 1856, 2048 }, { 6, 1857, 2048 }, { 6, 1858, 2048 }, { 7, 1859, 2048 }, { 6, 1860, 2048 }, { 7, 1861, 2048 }, { 7, 1862, 2048 }, { 8, 1863, 2048 }, + { 6, 1864, 2048 }, { 7, 1865, 2048 }, { 7, 1866, 2048 }, { 8, 1867, 2048 }, { 7, 1868, 2048 }, { 8, 1869, 2048 }, { 8, 1870, 2048 }, { 9, 1871, 2048 }, + { 6, 1872, 2048 }, { 7, 1873, 2048 }, { 7, 1874, 2048 }, { 8, 1875, 2048 }, { 7, 1876, 2048 }, { 8, 1877, 2048 }, { 8, 1878, 2048 }, { 9, 1879, 2048 }, + { 7, 1880, 2048 }, { 8, 1881, 2048 }, { 8, 1882, 2048 }, { 9, 1883, 2048 }, { 8, 1884, 2048 }, { 9, 1885, 2048 }, { 9, 1886, 2048 }, { 10, 1887, 2048 }, + { 6, 1888, 2048 }, { 7, 1889, 2048 }, { 7, 1890, 2048 }, { 8, 1891, 2048 }, { 7, 1892, 2048 }, { 8, 1893, 2048 }, { 8, 1894, 2048 }, { 9, 1895, 2048 }, + { 7, 1896, 2048 }, { 8, 1897, 2048 }, { 8, 1898, 2048 }, { 9, 1899, 2048 }, { 8, 1900, 2048 }, { 9, 1901, 2048 }, { 9, 1902, 2048 }, { 10, 1903, 2048 }, + { 7, 1904, 2048 }, { 8, 1905, 2048 }, { 8, 1906, 2048 }, { 9, 1907, 2048 }, { 8, 1908, 2048 }, { 9, 1909, 2048 }, { 9, 1910, 2048 }, { 10, 1911, 2048 }, + { 8, 1912, 2048 }, { 9, 1913, 2048 }, { 9, 1914, 2048 }, { 10, 1915, 2048 }, { 9, 1916, 2048 }, { 10, 1917, 2048 }, { 10, 1918, 2048 }, { 11, 1919, 2048 }, + { 5, 1920, 2048 }, { 6, 1921, 2048 }, { 6, 1922, 2048 }, { 7, 1923, 2048 }, { 6, 1924, 2048 }, { 7, 1925, 2048 }, { 7, 1926, 2048 }, { 8, 1927, 2048 }, + { 6, 1928, 2048 }, { 7, 1929, 2048 }, { 7, 1930, 2048 }, { 8, 1931, 2048 }, { 7, 1932, 2048 }, { 8, 1933, 2048 }, { 8, 1934, 2048 }, { 9, 1935, 2048 }, + { 6, 1936, 2048 }, { 7, 1937, 2048 }, { 7, 1938, 2048 }, { 8, 1939, 2048 }, { 7, 1940, 2048 }, { 8, 1941, 2048 }, { 8, 1942, 2048 }, { 9, 1943, 2048 }, + { 7, 1944, 2048 }, { 8, 1945, 2048 }, { 8, 1946, 2048 }, { 9, 1947, 2048 }, { 8, 1948, 2048 }, { 9, 1949, 2048 }, { 9, 1950, 2048 }, { 10, 1951, 2048 }, + { 6, 1952, 2048 }, { 7, 1953, 2048 }, { 7, 1954, 2048 }, { 8, 1955, 2048 }, { 7, 1956, 2048 }, { 8, 1957, 2048 }, { 8, 1958, 2048 }, { 9, 1959, 2048 }, + { 7, 1960, 2048 }, { 8, 1961, 2048 }, { 8, 1962, 2048 }, { 9, 1963, 2048 }, { 8, 1964, 2048 }, { 9, 1965, 2048 }, { 9, 1966, 2048 }, { 10, 1967, 2048 }, + { 7, 1968, 2048 }, { 8, 1969, 2048 }, { 8, 1970, 2048 }, { 9, 1971, 2048 }, { 8, 1972, 2048 }, { 9, 1973, 2048 }, { 9, 1974, 2048 }, { 10, 1975, 2048 }, + { 8, 1976, 2048 }, { 9, 1977, 2048 }, { 9, 1978, 2048 }, { 10, 1979, 2048 }, { 9, 1980, 2048 }, { 10, 1981, 2048 }, { 10, 1982, 2048 }, { 11, 1983, 2048 }, + { 6, 1984, 2048 }, { 7, 1985, 2048 }, { 7, 1986, 2048 }, { 8, 1987, 2048 }, { 7, 1988, 2048 }, { 8, 1989, 2048 }, { 8, 1990, 2048 }, { 9, 1991, 2048 }, + { 7, 1992, 2048 }, { 8, 1993, 2048 }, { 8, 1994, 2048 }, { 9, 1995, 2048 }, { 8, 1996, 2048 }, { 9, 1997, 2048 }, { 9, 1998, 2048 }, { 10, 1999, 2048 }, + { 7, 2000, 2048 }, { 8, 2001, 2048 }, { 8, 2002, 2048 }, { 9, 2003, 2048 }, { 8, 2004, 2048 }, { 9, 2005, 2048 }, { 9, 2006, 2048 }, { 10, 2007, 2048 }, + { 8, 2008, 2048 }, { 9, 2009, 2048 }, { 9, 2010, 2048 }, { 10, 2011, 2048 }, { 9, 2012, 2048 }, { 10, 2013, 2048 }, { 10, 2014, 2048 }, { 11, 2015, 2048 }, + { 7, 2016, 2048 }, { 8, 2017, 2048 }, { 8, 2018, 2048 }, { 9, 2019, 2048 }, { 8, 2020, 2048 }, { 9, 2021, 2048 }, { 9, 2022, 2048 }, { 10, 2023, 2048 }, + { 8, 2024, 2048 }, { 9, 2025, 2048 }, { 9, 2026, 2048 }, { 10, 2027, 2048 }, { 9, 2028, 2048 }, { 10, 2029, 2048 }, { 10, 2030, 2048 }, { 11, 2031, 2048 }, + { 8, 2032, 2048 }, { 9, 2033, 2048 }, { 9, 2034, 2048 }, { 10, 2035, 2048 }, { 9, 2036, 2048 }, { 10, 2037, 2048 }, { 10, 2038, 2048 }, { 11, 2039, 2048 }, + { 9, 2040, 2048 }, { 10, 2041, 2048 }, { 10, 2042, 2048 }, { 11, 2043, 2048 }, { 10, 2044, 2048 }, { 11, 2045, 2048 }, { 11, 2046, 2048 }, { 12, 2047, 2048 }, +#endif +#endif +#endif +#endif +#endif +#endif +}; + + +/* find a hole and free as required, return -1 if no hole found */ +static int find_hole(void) +{ + unsigned x; + int y, z; + for (z = -1, y = INT_MAX, x = 0; x < FP_ENTRIES; x++) { + if (fp_cache[x].lru_count < y && fp_cache[x].lock == 0) { + z = x; + y = fp_cache[x].lru_count; + } + } + + /* decrease all */ + for (x = 0; x < FP_ENTRIES; x++) { + if (fp_cache[x].lru_count > 3) { + --(fp_cache[x].lru_count); + } + } + + /* free entry z */ + if (z >= 0 && fp_cache[z].g) { + mp_clear(&fp_cache[z].mu); + wc_ecc_del_point(fp_cache[z].g); + fp_cache[z].g = NULL; + for (x = 0; x < (1U<x, g->x) == MP_EQ && + mp_cmp(fp_cache[x].g->y, g->y) == MP_EQ && + mp_cmp(fp_cache[x].g->z, g->z) == MP_EQ) { + break; + } + } + if (x == FP_ENTRIES) { + x = -1; + } + return x; +} + +/* add a new base to the cache */ +static int add_entry(int idx, ecc_point *g) +{ + unsigned x, y; + + /* allocate base and LUT */ + fp_cache[idx].g = wc_ecc_new_point(); + if (fp_cache[idx].g == NULL) { + return GEN_MEM_ERR; + } + + /* copy x and y */ + if ((mp_copy(g->x, fp_cache[idx].g->x) != MP_OKAY) || + (mp_copy(g->y, fp_cache[idx].g->y) != MP_OKAY) || + (mp_copy(g->z, fp_cache[idx].g->z) != MP_OKAY)) { + wc_ecc_del_point(fp_cache[idx].g); + fp_cache[idx].g = NULL; + return GEN_MEM_ERR; + } + + for (x = 0; x < (1U<x, mu, modulus, + fp_cache[idx].LUT[1]->x) != MP_OKAY) || + (mp_mulmod(fp_cache[idx].g->y, mu, modulus, + fp_cache[idx].LUT[1]->y) != MP_OKAY) || + (mp_mulmod(fp_cache[idx].g->z, mu, modulus, + fp_cache[idx].LUT[1]->z) != MP_OKAY)) { + err = MP_MULMOD_E; + } + } + + /* make all single bit entries */ + for (x = 1; x < FP_LUT; x++) { + if (err != MP_OKAY) + break; + if ((mp_copy(fp_cache[idx].LUT[1<<(x-1)]->x, + fp_cache[idx].LUT[1<x) != MP_OKAY) || + (mp_copy(fp_cache[idx].LUT[1<<(x-1)]->y, + fp_cache[idx].LUT[1<y) != MP_OKAY) || + (mp_copy(fp_cache[idx].LUT[1<<(x-1)]->z, + fp_cache[idx].LUT[1<z) != MP_OKAY)){ + err = MP_INIT_E; + break; + } else { + + /* now double it bitlen/FP_LUT times */ + for (y = 0; y < lut_gap; y++) { + if ((err = ecc_projective_dbl_point(fp_cache[idx].LUT[1<z, modulus, mp); + + /* invert it */ + if (err == MP_OKAY) + err = mp_invmod(fp_cache[idx].LUT[x]->z, modulus, + fp_cache[idx].LUT[x]->z); + + if (err == MP_OKAY) + /* now square it */ + err = mp_sqrmod(fp_cache[idx].LUT[x]->z, modulus, &tmp); + + if (err == MP_OKAY) + /* fix x */ + err = mp_mulmod(fp_cache[idx].LUT[x]->x, &tmp, modulus, + fp_cache[idx].LUT[x]->x); + + if (err == MP_OKAY) + /* get 1/z^3 */ + err = mp_mulmod(&tmp, fp_cache[idx].LUT[x]->z, modulus, &tmp); + + if (err == MP_OKAY) + /* fix y */ + err = mp_mulmod(fp_cache[idx].LUT[x]->y, &tmp, modulus, + fp_cache[idx].LUT[x]->y); + + if (err == MP_OKAY) + /* free z */ + mp_clear(fp_cache[idx].LUT[x]->z); + } + + mp_clear(&tmp); + + if (err == MP_OKAY) + return MP_OKAY; + + /* err cleanup */ + for (y = 0; y < (1U< mp_unsigned_bin_size(modulus)) { + /* find order */ + y = mp_unsigned_bin_size(modulus); + for (x = 0; ecc_sets[x].size; x++) { + if (y <= (unsigned)ecc_sets[x].size) break; + } + + /* back off if we are on the 521 bit curve */ + if (y == 66) --x; + + if ((err = mp_read_radix(&order, ecc_sets[x].order, + MP_RADIX_HEX)) != MP_OKAY) { + goto done; + } + + /* k must be less than modulus */ + if (mp_cmp(k, &order) != MP_LT) { + if ((err = mp_mod(k, &order, &tk)) != MP_OKAY) { + goto done; + } + } else { + if ((err = mp_copy(k, &tk)) != MP_OKAY) { + goto done; + } + } + } else { + if ((err = mp_copy(k, &tk)) != MP_OKAY) { + goto done; + } + } + + /* get bitlen and round up to next multiple of FP_LUT */ + bitlen = mp_unsigned_bin_size(modulus) << 3; + x = bitlen % FP_LUT; + if (x) { + bitlen += FP_LUT - x; + } + lut_gap = bitlen / FP_LUT; + + /* get the k value */ + if (mp_unsigned_bin_size(&tk) > (int)(KB_SIZE - 2)) { + err = BUFFER_E; goto done; + } + + /* store k */ +#ifdef WOLFSSL_SMALL_STACK + kb = (unsigned char*)XMALLOC(KB_SIZE, NULL, DYNAMIC_TYPE_ECC_BUFFER); + if (kb == NULL) { + err = MEMORY_E; goto done; + } +#endif + + XMEMSET(kb, 0, KB_SIZE); + if ((err = mp_to_unsigned_bin(&tk, kb)) == MP_OKAY) { + /* let's reverse kb so it's little endian */ + x = 0; + y = mp_unsigned_bin_size(&tk); + if (y > 0) { + y -= 1; + } + + while ((unsigned)x < y) { + z = kb[x]; kb[x] = kb[y]; kb[y] = (byte)z; + ++x; --y; + } + + /* at this point we can start, yipee */ + first = 1; + for (x = lut_gap-1; x >= 0; x--) { + /* extract FP_LUT bits from kb spread out by lut_gap bits and offset + by x bits from the start */ + bitpos = x; + for (y = z = 0; y < FP_LUT; y++) { + z |= ((kb[bitpos>>3] >> (bitpos&7)) & 1) << y; + bitpos += lut_gap; /* it's y*lut_gap + x, but here we can avoid + the mult in each loop */ + } + + /* double if not first */ + if (!first) { + if ((err = ecc_projective_dbl_point(R, R, a, modulus, + mp)) != MP_OKAY) { + break; + } + } + + /* add if not first, otherwise copy */ + if (!first && z) { + if ((err = ecc_projective_add_point(R, fp_cache[idx].LUT[z], R, + a, modulus, mp)) != MP_OKAY) { + break; + } + } else if (z) { + if ((mp_copy(fp_cache[idx].LUT[z]->x, R->x) != MP_OKAY) || + (mp_copy(fp_cache[idx].LUT[z]->y, R->y) != MP_OKAY) || + (mp_copy(&fp_cache[idx].mu, R->z) != MP_OKAY)) { + err = GEN_MEM_ERR; + break; + } + first = 0; + } + } + } + + if (err == MP_OKAY) { + (void) z; /* Acknowledge the unused assignment */ + ForceZero(kb, KB_SIZE); + + /* map R back from projective space */ + if (map) { + err = ecc_map(R, modulus, mp); + } else { + err = MP_OKAY; + } + } + +done: + /* cleanup */ + mp_clear(&order); + mp_clear(&tk); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(kb, NULL, DYNAMIC_TYPE_ECC_BUFFER); +#endif + +#undef KB_SIZE + + return err; +} +#endif + +#ifdef ECC_SHAMIR +#ifndef WOLFSSL_SP_MATH +/* perform a fixed point ECC mulmod */ +static int accel_fp_mul2add(int idx1, int idx2, + mp_int* kA, mp_int* kB, + ecc_point *R, mp_int* a, + mp_int* modulus, mp_digit mp) +{ +#define KB_SIZE 128 + +#ifdef WOLFSSL_SMALL_STACK + unsigned char* kb[2] = {NULL, NULL}; +#else + unsigned char kb[2][KB_SIZE]; +#endif + int x, err; + unsigned y, z, bitlen, bitpos, lut_gap, first, zA, zB; + mp_int tka, tkb, order; + + if (mp_init_multi(&tka, &tkb, &order, NULL, NULL, NULL) != MP_OKAY) + return MP_INIT_E; + + /* if it's smaller than modulus we fine */ + if (mp_unsigned_bin_size(kA) > mp_unsigned_bin_size(modulus)) { + /* find order */ + y = mp_unsigned_bin_size(modulus); + for (x = 0; ecc_sets[x].size; x++) { + if (y <= (unsigned)ecc_sets[x].size) break; + } + + /* back off if we are on the 521 bit curve */ + if (y == 66) --x; + + if ((err = mp_read_radix(&order, ecc_sets[x].order, + MP_RADIX_HEX)) != MP_OKAY) { + goto done; + } + + /* kA must be less than modulus */ + if (mp_cmp(kA, &order) != MP_LT) { + if ((err = mp_mod(kA, &order, &tka)) != MP_OKAY) { + goto done; + } + } else { + if ((err = mp_copy(kA, &tka)) != MP_OKAY) { + goto done; + } + } + } else { + if ((err = mp_copy(kA, &tka)) != MP_OKAY) { + goto done; + } + } + + /* if it's smaller than modulus we fine */ + if (mp_unsigned_bin_size(kB) > mp_unsigned_bin_size(modulus)) { + /* find order */ + y = mp_unsigned_bin_size(modulus); + for (x = 0; ecc_sets[x].size; x++) { + if (y <= (unsigned)ecc_sets[x].size) break; + } + + /* back off if we are on the 521 bit curve */ + if (y == 66) --x; + + if ((err = mp_read_radix(&order, ecc_sets[x].order, + MP_RADIX_HEX)) != MP_OKAY) { + goto done; + } + + /* kB must be less than modulus */ + if (mp_cmp(kB, &order) != MP_LT) { + if ((err = mp_mod(kB, &order, &tkb)) != MP_OKAY) { + goto done; + } + } else { + if ((err = mp_copy(kB, &tkb)) != MP_OKAY) { + goto done; + } + } + } else { + if ((err = mp_copy(kB, &tkb)) != MP_OKAY) { + goto done; + } + } + + /* get bitlen and round up to next multiple of FP_LUT */ + bitlen = mp_unsigned_bin_size(modulus) << 3; + x = bitlen % FP_LUT; + if (x) { + bitlen += FP_LUT - x; + } + lut_gap = bitlen / FP_LUT; + + /* get the k value */ + if ((mp_unsigned_bin_size(&tka) > (int)(KB_SIZE - 2)) || + (mp_unsigned_bin_size(&tkb) > (int)(KB_SIZE - 2)) ) { + err = BUFFER_E; goto done; + } + + /* store k */ +#ifdef WOLFSSL_SMALL_STACK + kb[0] = (unsigned char*)XMALLOC(KB_SIZE, NULL, DYNAMIC_TYPE_ECC_BUFFER); + if (kb[0] == NULL) { + err = MEMORY_E; goto done; + } +#endif + + XMEMSET(kb[0], 0, KB_SIZE); + if ((err = mp_to_unsigned_bin(&tka, kb[0])) != MP_OKAY) { + goto done; + } + + /* let's reverse kb so it's little endian */ + x = 0; + y = mp_unsigned_bin_size(&tka); + if (y > 0) { + y -= 1; + } + mp_clear(&tka); + while ((unsigned)x < y) { + z = kb[0][x]; kb[0][x] = kb[0][y]; kb[0][y] = (byte)z; + ++x; --y; + } + + /* store b */ +#ifdef WOLFSSL_SMALL_STACK + kb[1] = (unsigned char*)XMALLOC(KB_SIZE, NULL, DYNAMIC_TYPE_ECC_BUFFER); + if (kb[1] == NULL) { + err = MEMORY_E; goto done; + } +#endif + + XMEMSET(kb[1], 0, KB_SIZE); + if ((err = mp_to_unsigned_bin(&tkb, kb[1])) == MP_OKAY) { + x = 0; + y = mp_unsigned_bin_size(&tkb); + if (y > 0) { + y -= 1; + } + + while ((unsigned)x < y) { + z = kb[1][x]; kb[1][x] = kb[1][y]; kb[1][y] = (byte)z; + ++x; --y; + } + + /* at this point we can start, yipee */ + first = 1; + for (x = lut_gap-1; x >= 0; x--) { + /* extract FP_LUT bits from kb spread out by lut_gap bits and + offset by x bits from the start */ + bitpos = x; + for (y = zA = zB = 0; y < FP_LUT; y++) { + zA |= ((kb[0][bitpos>>3] >> (bitpos&7)) & 1) << y; + zB |= ((kb[1][bitpos>>3] >> (bitpos&7)) & 1) << y; + bitpos += lut_gap; /* it's y*lut_gap + x, but here we can avoid + the mult in each loop */ + } + + /* double if not first */ + if (!first) { + if ((err = ecc_projective_dbl_point(R, R, a, modulus, + mp)) != MP_OKAY) { + break; + } + } + + /* add if not first, otherwise copy */ + if (!first) { + if (zA) { + if ((err = ecc_projective_add_point(R, fp_cache[idx1].LUT[zA], + R, a, modulus, mp)) != MP_OKAY) { + break; + } + } + if (zB) { + if ((err = ecc_projective_add_point(R, fp_cache[idx2].LUT[zB], + R, a, modulus, mp)) != MP_OKAY) { + break; + } + } + } else { + if (zA) { + if ((mp_copy(fp_cache[idx1].LUT[zA]->x, R->x) != MP_OKAY) || + (mp_copy(fp_cache[idx1].LUT[zA]->y, R->y) != MP_OKAY) || + (mp_copy(&fp_cache[idx1].mu, R->z) != MP_OKAY)) { + err = GEN_MEM_ERR; + break; + } + first = 0; + } + if (zB && first == 0) { + if (zB) { + if ((err = ecc_projective_add_point(R, + fp_cache[idx2].LUT[zB], R, a, modulus, mp)) != MP_OKAY){ + break; + } + } + } else if (zB && first == 1) { + if ((mp_copy(fp_cache[idx2].LUT[zB]->x, R->x) != MP_OKAY) || + (mp_copy(fp_cache[idx2].LUT[zB]->y, R->y) != MP_OKAY) || + (mp_copy(&fp_cache[idx2].mu, R->z) != MP_OKAY)) { + err = GEN_MEM_ERR; + break; + } + first = 0; + } + } + } + } + +done: + /* cleanup */ + mp_clear(&tkb); + mp_clear(&tka); + mp_clear(&order); + +#ifdef WOLFSSL_SMALL_STACK + if (kb[0]) +#endif + ForceZero(kb[0], KB_SIZE); +#ifdef WOLFSSL_SMALL_STACK + if (kb[1]) +#endif + ForceZero(kb[1], KB_SIZE); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(kb[0], NULL, DYNAMIC_TYPE_ECC_BUFFER); + XFREE(kb[1], NULL, DYNAMIC_TYPE_ECC_BUFFER); +#endif + +#undef KB_SIZE + + if (err != MP_OKAY) + return err; + + return ecc_map(R, modulus, mp); +} + + +/** ECC Fixed Point mulmod global with heap hint used + Computes kA*A + kB*B = C using Shamir's Trick + A First point to multiply + kA What to multiple A by + B Second point to multiply + kB What to multiple B by + C [out] Destination point (can overlap with A or B) + a ECC curve parameter a + modulus Modulus for curve + return MP_OKAY on success +*/ +int ecc_mul2add(ecc_point* A, mp_int* kA, + ecc_point* B, mp_int* kB, + ecc_point* C, mp_int* a, mp_int* modulus, void* heap) +{ + int idx1 = -1, idx2 = -1, err = MP_OKAY, mpInit = 0; + mp_digit mp; + mp_int mu; + + err = mp_init(&mu); + if (err != MP_OKAY) + return err; + +#ifndef HAVE_THREAD_LS + if (initMutex == 0) { + wc_InitMutex(&ecc_fp_lock); + initMutex = 1; + } + if (wc_LockMutex(&ecc_fp_lock) != 0) + return BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + /* find point */ + idx1 = find_base(A); + + /* no entry? */ + if (idx1 == -1) { + /* find hole and add it */ + if ((idx1 = find_hole()) >= 0) { + err = add_entry(idx1, A); + } + } + if (err == MP_OKAY && idx1 != -1) { + /* increment LRU */ + ++(fp_cache[idx1].lru_count); + } + + if (err == MP_OKAY) + /* find point */ + idx2 = find_base(B); + + if (err == MP_OKAY) { + /* no entry? */ + if (idx2 == -1) { + /* find hole and add it */ + if ((idx2 = find_hole()) >= 0) + err = add_entry(idx2, B); + } + } + + if (err == MP_OKAY && idx2 != -1) { + /* increment LRU */ + ++(fp_cache[idx2].lru_count); + } + + if (err == MP_OKAY) { + /* if it's 2 build the LUT, if it's higher just use the LUT */ + if (idx1 >= 0 && fp_cache[idx1].lru_count == 2) { + /* compute mp */ + err = mp_montgomery_setup(modulus, &mp); + + if (err == MP_OKAY) { + mpInit = 1; + err = mp_montgomery_calc_normalization(&mu, modulus); + } + + if (err == MP_OKAY) + /* build the LUT */ + err = build_lut(idx1, a, modulus, mp, &mu); + } + } + + if (err == MP_OKAY) { + /* if it's 2 build the LUT, if it's higher just use the LUT */ + if (idx2 >= 0 && fp_cache[idx2].lru_count == 2) { + if (mpInit == 0) { + /* compute mp */ + err = mp_montgomery_setup(modulus, &mp); + if (err == MP_OKAY) { + mpInit = 1; + err = mp_montgomery_calc_normalization(&mu, modulus); + } + } + + if (err == MP_OKAY) + /* build the LUT */ + err = build_lut(idx2, a, modulus, mp, &mu); + } + } + + + if (err == MP_OKAY) { + if (idx1 >=0 && idx2 >= 0 && fp_cache[idx1].lru_count >= 2 && + fp_cache[idx2].lru_count >= 2) { + if (mpInit == 0) { + /* compute mp */ + err = mp_montgomery_setup(modulus, &mp); + } + if (err == MP_OKAY) + err = accel_fp_mul2add(idx1, idx2, kA, kB, C, a, modulus, mp); + } else { + err = normal_ecc_mul2add(A, kA, B, kB, C, a, modulus, heap); + } + } + +#ifndef HAVE_THREAD_LS + wc_UnLockMutex(&ecc_fp_lock); +#endif /* HAVE_THREAD_LS */ + mp_clear(&mu); + + return err; +} +#endif +#endif /* ECC_SHAMIR */ + +/** ECC Fixed Point mulmod global + k The multiplicand + G Base point to multiply + R [out] Destination of product + a ECC curve parameter a + modulus The modulus for the curve + map [boolean] If non-zero maps the point back to affine co-ordinates, + otherwise it's left in jacobian-montgomery form + return MP_OKAY if successful +*/ +int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, mp_int* a, + mp_int* modulus, int map, void* heap) +{ +#ifndef WOLFSSL_SP_MATH + int idx, err = MP_OKAY; + mp_digit mp; + mp_int mu; + int mpSetup = 0; + + if (k == NULL || G == NULL || R == NULL || a == NULL || modulus == NULL) { + return ECC_BAD_ARG_E; + } + + if (mp_init(&mu) != MP_OKAY) + return MP_INIT_E; + +#ifndef HAVE_THREAD_LS + if (initMutex == 0) { + wc_InitMutex(&ecc_fp_lock); + initMutex = 1; + } + + if (wc_LockMutex(&ecc_fp_lock) != 0) + return BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + /* find point */ + idx = find_base(G); + + /* no entry? */ + if (idx == -1) { + /* find hole and add it */ + idx = find_hole(); + + if (idx >= 0) + err = add_entry(idx, G); + } + if (err == MP_OKAY && idx >= 0) { + /* increment LRU */ + ++(fp_cache[idx].lru_count); + } + + + if (err == MP_OKAY) { + /* if it's 2 build the LUT, if it's higher just use the LUT */ + if (idx >= 0 && fp_cache[idx].lru_count == 2) { + /* compute mp */ + err = mp_montgomery_setup(modulus, &mp); + + if (err == MP_OKAY) { + /* compute mu */ + mpSetup = 1; + err = mp_montgomery_calc_normalization(&mu, modulus); + } + + if (err == MP_OKAY) + /* build the LUT */ + err = build_lut(idx, a, modulus, mp, &mu); + } + } + + if (err == MP_OKAY) { + if (idx >= 0 && fp_cache[idx].lru_count >= 2) { + if (mpSetup == 0) { + /* compute mp */ + err = mp_montgomery_setup(modulus, &mp); + } + if (err == MP_OKAY) + err = accel_fp_mul(idx, k, R, a, modulus, mp, map); + } else { + err = normal_ecc_mulmod(k, G, R, a, modulus, map, heap); + } + } + +#ifndef HAVE_THREAD_LS + wc_UnLockMutex(&ecc_fp_lock); +#endif /* HAVE_THREAD_LS */ + mp_clear(&mu); + + return err; +#else + if (k == NULL || G == NULL || R == NULL || a == NULL || modulus == NULL) { + return ECC_BAD_ARG_E; + } + + return sp_ecc_mulmod_256(k, G, R, map, heap); +#endif +} + +#ifndef WOLFSSL_SP_MATH +/* helper function for freeing the cache ... + must be called with the cache mutex locked */ +static void wc_ecc_fp_free_cache(void) +{ + unsigned x, y; + for (x = 0; x < FP_ENTRIES; x++) { + if (fp_cache[x].g != NULL) { + for (y = 0; y < (1U<protocol == 0) + return NULL; + + if (ctx->protocol == REQ_RESP_CLIENT) { + if (ctx->cliSt == ecCLI_INIT) { + ctx->cliSt = ecCLI_SALT_GET; + return ctx->clientSalt; + } + else { + ctx->cliSt = ecCLI_BAD_STATE; + return NULL; + } + } + else if (ctx->protocol == REQ_RESP_SERVER) { + if (ctx->srvSt == ecSRV_INIT) { + ctx->srvSt = ecSRV_SALT_GET; + return ctx->serverSalt; + } + else { + ctx->srvSt = ecSRV_BAD_STATE; + return NULL; + } + } + + return NULL; +} + + +/* optional set info, can be called before or after set_peer_salt */ +int wc_ecc_ctx_set_info(ecEncCtx* ctx, const byte* info, int sz) +{ + if (ctx == NULL || info == 0 || sz < 0) + return BAD_FUNC_ARG; + + ctx->kdfInfo = info; + ctx->kdfInfoSz = sz; + + return 0; +} + + +static const char* exchange_info = "Secure Message Exchange"; + +int wc_ecc_ctx_set_peer_salt(ecEncCtx* ctx, const byte* salt) +{ + byte tmp[EXCHANGE_SALT_SZ/2]; + int halfSz = EXCHANGE_SALT_SZ/2; + + if (ctx == NULL || ctx->protocol == 0 || salt == NULL) + return BAD_FUNC_ARG; + + if (ctx->protocol == REQ_RESP_CLIENT) { + XMEMCPY(ctx->serverSalt, salt, EXCHANGE_SALT_SZ); + if (ctx->cliSt == ecCLI_SALT_GET) + ctx->cliSt = ecCLI_SALT_SET; + else { + ctx->cliSt = ecCLI_BAD_STATE; + return BAD_STATE_E; + } + } + else { + XMEMCPY(ctx->clientSalt, salt, EXCHANGE_SALT_SZ); + if (ctx->srvSt == ecSRV_SALT_GET) + ctx->srvSt = ecSRV_SALT_SET; + else { + ctx->srvSt = ecSRV_BAD_STATE; + return BAD_STATE_E; + } + } + + /* mix half and half */ + /* tmp stores 2nd half of client before overwrite */ + XMEMCPY(tmp, ctx->clientSalt + halfSz, halfSz); + XMEMCPY(ctx->clientSalt + halfSz, ctx->serverSalt, halfSz); + XMEMCPY(ctx->serverSalt, tmp, halfSz); + + ctx->kdfSalt = ctx->clientSalt; + ctx->kdfSaltSz = EXCHANGE_SALT_SZ; + + ctx->macSalt = ctx->serverSalt; + ctx->macSaltSz = EXCHANGE_SALT_SZ; + + if (ctx->kdfInfo == NULL) { + /* default info */ + ctx->kdfInfo = (const byte*)exchange_info; + ctx->kdfInfoSz = EXCHANGE_INFO_SZ; + } + + return 0; +} + + +static int ecc_ctx_set_salt(ecEncCtx* ctx, int flags, WC_RNG* rng) +{ + byte* saltBuffer = NULL; + + if (ctx == NULL || rng == NULL || flags == 0) + return BAD_FUNC_ARG; + + saltBuffer = (flags == REQ_RESP_CLIENT) ? ctx->clientSalt : ctx->serverSalt; + + return wc_RNG_GenerateBlock(rng, saltBuffer, EXCHANGE_SALT_SZ); +} + + +static void ecc_ctx_init(ecEncCtx* ctx, int flags) +{ + if (ctx) { + XMEMSET(ctx, 0, sizeof(ecEncCtx)); + + ctx->encAlgo = ecAES_128_CBC; + ctx->kdfAlgo = ecHKDF_SHA256; + ctx->macAlgo = ecHMAC_SHA256; + ctx->protocol = (byte)flags; + + if (flags == REQ_RESP_CLIENT) + ctx->cliSt = ecCLI_INIT; + if (flags == REQ_RESP_SERVER) + ctx->srvSt = ecSRV_INIT; + } +} + + +/* allow ecc context reset so user doesn't have to init/free for reuse */ +int wc_ecc_ctx_reset(ecEncCtx* ctx, WC_RNG* rng) +{ + if (ctx == NULL || rng == NULL) + return BAD_FUNC_ARG; + + ecc_ctx_init(ctx, ctx->protocol); + return ecc_ctx_set_salt(ctx, ctx->protocol, rng); +} + + +ecEncCtx* wc_ecc_ctx_new_ex(int flags, WC_RNG* rng, void* heap) +{ + int ret = 0; + ecEncCtx* ctx = (ecEncCtx*)XMALLOC(sizeof(ecEncCtx), heap, + DYNAMIC_TYPE_ECC); + + if (ctx) { + ctx->protocol = (byte)flags; + ctx->heap = heap; + } + + ret = wc_ecc_ctx_reset(ctx, rng); + if (ret != 0) { + wc_ecc_ctx_free(ctx); + ctx = NULL; + } + + return ctx; +} + + +/* alloc/init and set defaults, return new Context */ +ecEncCtx* wc_ecc_ctx_new(int flags, WC_RNG* rng) +{ + return wc_ecc_ctx_new_ex(flags, rng, NULL); +} + + +/* free any resources, clear any keys */ +void wc_ecc_ctx_free(ecEncCtx* ctx) +{ + if (ctx) { + ForceZero(ctx, sizeof(ecEncCtx)); + XFREE(ctx, ctx->heap, DYNAMIC_TYPE_ECC); + } +} + + +static int ecc_get_key_sizes(ecEncCtx* ctx, int* encKeySz, int* ivSz, + int* keysLen, word32* digestSz, word32* blockSz) +{ + if (ctx) { + switch (ctx->encAlgo) { + case ecAES_128_CBC: + *encKeySz = KEY_SIZE_128; + *ivSz = IV_SIZE_128; + *blockSz = AES_BLOCK_SIZE; + break; + default: + return BAD_FUNC_ARG; + } + + switch (ctx->macAlgo) { + case ecHMAC_SHA256: + *digestSz = WC_SHA256_DIGEST_SIZE; + break; + default: + return BAD_FUNC_ARG; + } + } else + return BAD_FUNC_ARG; + + *keysLen = *encKeySz + *ivSz + *digestSz; + + return 0; +} + + +/* ecc encrypt with shared secret run through kdf + ctx holds non default algos and inputs + msgSz should be the right size for encAlgo, i.e., already padded + return 0 on success */ +int wc_ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, + word32 msgSz, byte* out, word32* outSz, ecEncCtx* ctx) +{ + int ret = 0; + word32 blockSz; + word32 digestSz; + ecEncCtx localCtx; +#ifdef WOLFSSL_SMALL_STACK + byte* sharedSecret; + byte* keys; +#else + byte sharedSecret[ECC_MAXSIZE]; /* 521 max size */ + byte keys[ECC_BUFSIZE]; /* max size */ +#endif + word32 sharedSz = ECC_MAXSIZE; + int keysLen; + int encKeySz; + int ivSz; + int offset = 0; /* keys offset if doing msg exchange */ + byte* encKey; + byte* encIv; + byte* macKey; + + if (privKey == NULL || pubKey == NULL || msg == NULL || out == NULL || + outSz == NULL) + return BAD_FUNC_ARG; + + if (ctx == NULL) { /* use defaults */ + ecc_ctx_init(&localCtx, 0); + ctx = &localCtx; + } + + ret = ecc_get_key_sizes(ctx, &encKeySz, &ivSz, &keysLen, &digestSz, + &blockSz); + if (ret != 0) + return ret; + + if (ctx->protocol == REQ_RESP_SERVER) { + offset = keysLen; + keysLen *= 2; + + if (ctx->srvSt != ecSRV_RECV_REQ) + return BAD_STATE_E; + + ctx->srvSt = ecSRV_BAD_STATE; /* we're done no more ops allowed */ + } + else if (ctx->protocol == REQ_RESP_CLIENT) { + if (ctx->cliSt != ecCLI_SALT_SET) + return BAD_STATE_E; + + ctx->cliSt = ecCLI_SENT_REQ; /* only do this once */ + } + + if (keysLen > ECC_BUFSIZE) /* keys size */ + return BUFFER_E; + + if ( (msgSz%blockSz) != 0) + return BAD_PADDING_E; + + if (*outSz < (msgSz + digestSz)) + return BUFFER_E; + +#ifdef WOLFSSL_SMALL_STACK + sharedSecret = (byte*)XMALLOC(ECC_MAXSIZE, NULL, DYNAMIC_TYPE_ECC_BUFFER); + if (sharedSecret == NULL) + return MEMORY_E; + + keys = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_ECC_BUFFER); + if (keys == NULL) { + XFREE(sharedSecret, NULL, DYNAMIC_TYPE_ECC_BUFFER); + return MEMORY_E; + } +#endif + + do { + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + ret = wc_AsyncWait(ret, &privKey->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + if (ret != 0) + break; + #endif + ret = wc_ecc_shared_secret(privKey, pubKey, sharedSecret, &sharedSz); + } while (ret == WC_PENDING_E); + if (ret == 0) { + switch (ctx->kdfAlgo) { + case ecHKDF_SHA256 : + ret = wc_HKDF(WC_SHA256, sharedSecret, sharedSz, ctx->kdfSalt, + ctx->kdfSaltSz, ctx->kdfInfo, ctx->kdfInfoSz, + keys, keysLen); + break; + + default: + ret = BAD_FUNC_ARG; + break; + } + } + + if (ret == 0) { + encKey = keys + offset; + encIv = encKey + encKeySz; + macKey = encKey + encKeySz + ivSz; + + switch (ctx->encAlgo) { + case ecAES_128_CBC: + { + Aes aes; + ret = wc_AesInit(&aes, NULL, INVALID_DEVID); + if (ret == 0) { + ret = wc_AesSetKey(&aes, encKey, KEY_SIZE_128, encIv, + AES_ENCRYPTION); + if (ret == 0) { + ret = wc_AesCbcEncrypt(&aes, out, msg, msgSz); + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES) + ret = wc_AsyncWait(ret, &aes.asyncDev, + WC_ASYNC_FLAG_NONE); + #endif + } + wc_AesFree(&aes); + } + if (ret != 0) + break; + } + break; + + default: + ret = BAD_FUNC_ARG; + break; + } + } + + if (ret == 0) { + switch (ctx->macAlgo) { + case ecHMAC_SHA256: + { + Hmac hmac; + ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID); + if (ret == 0) { + ret = wc_HmacSetKey(&hmac, WC_SHA256, macKey, WC_SHA256_DIGEST_SIZE); + if (ret == 0) + ret = wc_HmacUpdate(&hmac, out, msgSz); + if (ret == 0) + ret = wc_HmacUpdate(&hmac, ctx->macSalt, ctx->macSaltSz); + if (ret == 0) + ret = wc_HmacFinal(&hmac, out+msgSz); + wc_HmacFree(&hmac); + } + } + break; + + default: + ret = BAD_FUNC_ARG; + break; + } + } + + if (ret == 0) + *outSz = msgSz + digestSz; + +#ifdef WOLFSSL_SMALL_STACK + XFREE(sharedSecret, NULL, DYNAMIC_TYPE_ECC_BUFFER); + XFREE(keys, NULL, DYNAMIC_TYPE_ECC_BUFFER); +#endif + + return ret; +} + + +/* ecc decrypt with shared secret run through kdf + ctx holds non default algos and inputs + return 0 on success */ +int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, + word32 msgSz, byte* out, word32* outSz, ecEncCtx* ctx) +{ + int ret = 0; + word32 blockSz; + word32 digestSz; + ecEncCtx localCtx; +#ifdef WOLFSSL_SMALL_STACK + byte* sharedSecret; + byte* keys; +#else + byte sharedSecret[ECC_MAXSIZE]; /* 521 max size */ + byte keys[ECC_BUFSIZE]; /* max size */ +#endif + word32 sharedSz = ECC_MAXSIZE; + int keysLen; + int encKeySz; + int ivSz; + int offset = 0; /* in case using msg exchange */ + byte* encKey; + byte* encIv; + byte* macKey; + + if (privKey == NULL || pubKey == NULL || msg == NULL || out == NULL || + outSz == NULL) + return BAD_FUNC_ARG; + + if (ctx == NULL) { /* use defaults */ + ecc_ctx_init(&localCtx, 0); + ctx = &localCtx; + } + + ret = ecc_get_key_sizes(ctx, &encKeySz, &ivSz, &keysLen, &digestSz, + &blockSz); + if (ret != 0) + return ret; + + if (ctx->protocol == REQ_RESP_CLIENT) { + offset = keysLen; + keysLen *= 2; + + if (ctx->cliSt != ecCLI_SENT_REQ) + return BAD_STATE_E; + + ctx->cliSt = ecSRV_BAD_STATE; /* we're done no more ops allowed */ + } + else if (ctx->protocol == REQ_RESP_SERVER) { + if (ctx->srvSt != ecSRV_SALT_SET) + return BAD_STATE_E; + + ctx->srvSt = ecSRV_RECV_REQ; /* only do this once */ + } + + if (keysLen > ECC_BUFSIZE) /* keys size */ + return BUFFER_E; + + if ( ((msgSz-digestSz) % blockSz) != 0) + return BAD_PADDING_E; + + if (*outSz < (msgSz - digestSz)) + return BUFFER_E; + +#ifdef WOLFSSL_SMALL_STACK + sharedSecret = (byte*)XMALLOC(ECC_MAXSIZE, NULL, DYNAMIC_TYPE_ECC_BUFFER); + if (sharedSecret == NULL) + return MEMORY_E; + + keys = (byte*)XMALLOC(ECC_BUFSIZE, NULL, DYNAMIC_TYPE_ECC_BUFFER); + if (keys == NULL) { + XFREE(sharedSecret, NULL, DYNAMIC_TYPE_ECC_BUFFER); + return MEMORY_E; + } +#endif + + do { + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_ECC) + ret = wc_AsyncWait(ret, &privKey->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + if (ret != 0) + break; + #endif + ret = wc_ecc_shared_secret(privKey, pubKey, sharedSecret, &sharedSz); + } while (ret == WC_PENDING_E); + if (ret == 0) { + switch (ctx->kdfAlgo) { + case ecHKDF_SHA256 : + ret = wc_HKDF(WC_SHA256, sharedSecret, sharedSz, ctx->kdfSalt, + ctx->kdfSaltSz, ctx->kdfInfo, ctx->kdfInfoSz, + keys, keysLen); + break; + + default: + ret = BAD_FUNC_ARG; + break; + } + } + + if (ret == 0) { + encKey = keys + offset; + encIv = encKey + encKeySz; + macKey = encKey + encKeySz + ivSz; + + switch (ctx->macAlgo) { + case ecHMAC_SHA256: + { + byte verify[WC_SHA256_DIGEST_SIZE]; + Hmac hmac; + + ret = wc_HmacInit(&hmac, NULL, INVALID_DEVID); + if (ret == 0) { + ret = wc_HmacSetKey(&hmac, WC_SHA256, macKey, WC_SHA256_DIGEST_SIZE); + if (ret == 0) + ret = wc_HmacUpdate(&hmac, msg, msgSz-digestSz); + if (ret == 0) + ret = wc_HmacUpdate(&hmac, ctx->macSalt, ctx->macSaltSz); + if (ret == 0) + ret = wc_HmacFinal(&hmac, verify); + if (ret == 0) { + if (XMEMCMP(verify, msg + msgSz - digestSz, digestSz) != 0) + ret = -1; + } + + wc_HmacFree(&hmac); + } + break; + } + + default: + ret = BAD_FUNC_ARG; + break; + } + } + + if (ret == 0) { + switch (ctx->encAlgo) { + #ifdef HAVE_AES_CBC + case ecAES_128_CBC: + { + Aes aes; + ret = wc_AesSetKey(&aes, encKey, KEY_SIZE_128, encIv, + AES_DECRYPTION); + if (ret != 0) + break; + ret = wc_AesCbcDecrypt(&aes, out, msg, msgSz-digestSz); + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_AES) + ret = wc_AsyncWait(ret, &aes.asyncDev, WC_ASYNC_FLAG_NONE); + #endif + } + break; + #endif + default: + ret = BAD_FUNC_ARG; + break; + } + } + + if (ret == 0) + *outSz = msgSz - digestSz; + +#ifdef WOLFSSL_SMALL_STACK + XFREE(sharedSecret, NULL, DYNAMIC_TYPE_ECC_BUFFER); + XFREE(keys, NULL, DYNAMIC_TYPE_ECC_BUFFER); +#endif + + return ret; +} + + +#endif /* HAVE_ECC_ENCRYPT */ + + +#ifdef HAVE_COMP_KEY +#if !defined(WOLFSSL_ATECC508A) && !defined(WOLFSSL_CRYPTOCELL) + +#ifndef WOLFSSL_SP_MATH +int do_mp_jacobi(mp_int* a, mp_int* n, int* c); + +int do_mp_jacobi(mp_int* a, mp_int* n, int* c) +{ + int k, s, res; + int r = 0; /* initialize to help static analysis out */ + mp_digit residue; + + /* if a < 0 return MP_VAL */ + if (mp_isneg(a) == MP_YES) { + return MP_VAL; + } + + /* if n <= 0 return MP_VAL */ + if (mp_cmp_d(n, 0) != MP_GT) { + return MP_VAL; + } + + /* step 1. handle case of a == 0 */ + if (mp_iszero (a) == MP_YES) { + /* special case of a == 0 and n == 1 */ + if (mp_cmp_d (n, 1) == MP_EQ) { + *c = 1; + } else { + *c = 0; + } + return MP_OKAY; + } + + /* step 2. if a == 1, return 1 */ + if (mp_cmp_d (a, 1) == MP_EQ) { + *c = 1; + return MP_OKAY; + } + + /* default */ + s = 0; + + /* divide out larger power of two */ + k = mp_cnt_lsb(a); + res = mp_div_2d(a, k, a, NULL); + + if (res == MP_OKAY) { + /* step 4. if e is even set s=1 */ + if ((k & 1) == 0) { + s = 1; + } else { + /* else set s=1 if p = 1/7 (mod 8) or s=-1 if p = 3/5 (mod 8) */ + residue = n->dp[0] & 7; + + if (residue == 1 || residue == 7) { + s = 1; + } else if (residue == 3 || residue == 5) { + s = -1; + } + } + + /* step 5. if p == 3 (mod 4) *and* a == 3 (mod 4) then s = -s */ + if ( ((n->dp[0] & 3) == 3) && ((a->dp[0] & 3) == 3)) { + s = -s; + } + } + + if (res == MP_OKAY) { + /* if a == 1 we're done */ + if (mp_cmp_d(a, 1) == MP_EQ) { + *c = s; + } else { + /* n1 = n mod a */ + res = mp_mod (n, a, n); + if (res == MP_OKAY) + res = do_mp_jacobi(n, a, &r); + + if (res == MP_OKAY) + *c = s * r; + } + } + + return res; +} + + +/* computes the jacobi c = (a | n) (or Legendre if n is prime) + * HAC pp. 73 Algorithm 2.149 + * HAC is wrong here, as the special case of (0 | 1) is not + * handled correctly. + */ +int mp_jacobi(mp_int* a, mp_int* n, int* c) +{ + mp_int a1, n1; + int res; + + /* step 3. write a = a1 * 2**k */ + if ((res = mp_init_multi(&a1, &n1, NULL, NULL, NULL, NULL)) != MP_OKAY) { + return res; + } + + if ((res = mp_copy(a, &a1)) != MP_OKAY) { + goto done; + } + + if ((res = mp_copy(n, &n1)) != MP_OKAY) { + goto done; + } + + res = do_mp_jacobi(&a1, &n1, c); + +done: + /* cleanup */ + mp_clear(&n1); + mp_clear(&a1); + + return res; +} + + +/* Solves the modular equation x^2 = n (mod p) + * where prime number is greater than 2 (odd prime). + * The result is returned in the third argument x + * the function returns MP_OKAY on success, MP_VAL or another error on failure + */ +int mp_sqrtmod_prime(mp_int* n, mp_int* prime, mp_int* ret) +{ +#ifdef SQRTMOD_USE_MOD_EXP + int res; + + mp_int e; + + res = mp_init(&e); + if (res == MP_OKAY) + res = mp_add_d(prime, 1, &e); + if (res == MP_OKAY) + res = mp_div_2d(&e, 2, &e, NULL); + if (res == MP_OKAY) + res = mp_exptmod(n, &e, prime, ret); + + mp_clear(&e); + + return res; +#else + int res, legendre, done = 0; + mp_int t1, C, Q, S, Z, M, T, R, two; + mp_digit i; + + /* first handle the simple cases n = 0 or n = 1 */ + if (mp_cmp_d(n, 0) == MP_EQ) { + mp_zero(ret); + return MP_OKAY; + } + if (mp_cmp_d(n, 1) == MP_EQ) { + return mp_set(ret, 1); + } + + /* prime must be odd */ + if (mp_cmp_d(prime, 2) == MP_EQ) { + return MP_VAL; + } + + /* is quadratic non-residue mod prime */ + if ((res = mp_jacobi(n, prime, &legendre)) != MP_OKAY) { + return res; + } + if (legendre == -1) { + return MP_VAL; + } + + if ((res = mp_init_multi(&t1, &C, &Q, &S, &Z, &M)) != MP_OKAY) + return res; + + if ((res = mp_init_multi(&T, &R, &two, NULL, NULL, NULL)) + != MP_OKAY) { + mp_clear(&t1); mp_clear(&C); mp_clear(&Q); mp_clear(&S); mp_clear(&Z); + mp_clear(&M); + return res; + } + + /* SPECIAL CASE: if prime mod 4 == 3 + * compute directly: res = n^(prime+1)/4 mod prime + * Handbook of Applied Cryptography algorithm 3.36 + */ + res = mp_mod_d(prime, 4, &i); + if (res == MP_OKAY && i == 3) { + res = mp_add_d(prime, 1, &t1); + + if (res == MP_OKAY) + res = mp_div_2(&t1, &t1); + if (res == MP_OKAY) + res = mp_div_2(&t1, &t1); + if (res == MP_OKAY) + res = mp_exptmod(n, &t1, prime, ret); + + done = 1; + } + + /* NOW: TonelliShanks algorithm */ + if (res == MP_OKAY && done == 0) { + + /* factor out powers of 2 from prime-1, defining Q and S + * as: prime-1 = Q*2^S */ + /* Q = prime - 1 */ + res = mp_copy(prime, &Q); + if (res == MP_OKAY) + res = mp_sub_d(&Q, 1, &Q); + + /* S = 0 */ + if (res == MP_OKAY) + mp_zero(&S); + + while (res == MP_OKAY && mp_iseven(&Q) == MP_YES) { + /* Q = Q / 2 */ + res = mp_div_2(&Q, &Q); + + /* S = S + 1 */ + if (res == MP_OKAY) + res = mp_add_d(&S, 1, &S); + } + + /* find a Z such that the Legendre symbol (Z|prime) == -1 */ + /* Z = 2 */ + if (res == MP_OKAY) + res = mp_set_int(&Z, 2); + + while (res == MP_OKAY) { + res = mp_jacobi(&Z, prime, &legendre); + if (res == MP_OKAY && legendre == -1) + break; + + /* Z = Z + 1 */ + if (res == MP_OKAY) + res = mp_add_d(&Z, 1, &Z); + } + + /* C = Z ^ Q mod prime */ + if (res == MP_OKAY) + res = mp_exptmod(&Z, &Q, prime, &C); + + /* t1 = (Q + 1) / 2 */ + if (res == MP_OKAY) + res = mp_add_d(&Q, 1, &t1); + if (res == MP_OKAY) + res = mp_div_2(&t1, &t1); + + /* R = n ^ ((Q + 1) / 2) mod prime */ + if (res == MP_OKAY) + res = mp_exptmod(n, &t1, prime, &R); + + /* T = n ^ Q mod prime */ + if (res == MP_OKAY) + res = mp_exptmod(n, &Q, prime, &T); + + /* M = S */ + if (res == MP_OKAY) + res = mp_copy(&S, &M); + + if (res == MP_OKAY) + res = mp_set_int(&two, 2); + + while (res == MP_OKAY && done == 0) { + res = mp_copy(&T, &t1); + + /* reduce to 1 and count */ + i = 0; + while (res == MP_OKAY) { + if (mp_cmp_d(&t1, 1) == MP_EQ) + break; + res = mp_exptmod(&t1, &two, prime, &t1); + if (res == MP_OKAY) + i++; + } + if (res == MP_OKAY && i == 0) { + res = mp_copy(&R, ret); + done = 1; + } + + if (done == 0) { + /* t1 = 2 ^ (M - i - 1) */ + if (res == MP_OKAY) + res = mp_sub_d(&M, i, &t1); + if (res == MP_OKAY) + res = mp_sub_d(&t1, 1, &t1); + if (res == MP_OKAY) + res = mp_exptmod(&two, &t1, prime, &t1); + + /* t1 = C ^ (2 ^ (M - i - 1)) mod prime */ + if (res == MP_OKAY) + res = mp_exptmod(&C, &t1, prime, &t1); + + /* C = (t1 * t1) mod prime */ + if (res == MP_OKAY) + res = mp_sqrmod(&t1, prime, &C); + + /* R = (R * t1) mod prime */ + if (res == MP_OKAY) + res = mp_mulmod(&R, &t1, prime, &R); + + /* T = (T * C) mod prime */ + if (res == MP_OKAY) + res = mp_mulmod(&T, &C, prime, &T); + + /* M = i */ + if (res == MP_OKAY) + res = mp_set(&M, i); + } + } + } + + /* done */ + mp_clear(&t1); + mp_clear(&C); + mp_clear(&Q); + mp_clear(&S); + mp_clear(&Z); + mp_clear(&M); + mp_clear(&T); + mp_clear(&R); + mp_clear(&two); + + return res; +#endif +} +#endif +#endif /* !WOLFSSL_ATECC508A && !WOLFSSL_CRYPTOCELL */ + + +/* export public ECC key in ANSI X9.63 format compressed */ +static int wc_ecc_export_x963_compressed(ecc_key* key, byte* out, word32* outLen) +{ + word32 numlen; + int ret = MP_OKAY; + + if (key == NULL || out == NULL || outLen == NULL) + return BAD_FUNC_ARG; + + if (wc_ecc_is_valid_idx(key->idx) == 0) { + return ECC_BAD_ARG_E; + } + numlen = key->dp->size; + + if (*outLen < (1 + numlen)) { + *outLen = 1 + numlen; + return BUFFER_E; + } + + /* store first byte */ + out[0] = mp_isodd(key->pubkey.y) == MP_YES ? ECC_POINT_COMP_ODD : ECC_POINT_COMP_EVEN; + + /* pad and store x */ + XMEMSET(out+1, 0, numlen); + ret = mp_to_unsigned_bin(key->pubkey.x, + out+1 + (numlen - mp_unsigned_bin_size(key->pubkey.x))); + *outLen = 1 + numlen; + + return ret; +} + +#endif /* HAVE_COMP_KEY */ + + +int wc_ecc_get_oid(word32 oidSum, const byte** oid, word32* oidSz) +{ + int x; + + if (oidSum == 0) { + return BAD_FUNC_ARG; + } + + /* find matching OID sum (based on encoded value) */ + for (x = 0; ecc_sets[x].size != 0; x++) { + if (ecc_sets[x].oidSum == oidSum) { + int ret = 0; + #ifdef HAVE_OID_ENCODING + /* check cache */ + oid_cache_t* o = &ecc_oid_cache[x]; + if (o->oidSz == 0) { + o->oidSz = sizeof(o->oid); + ret = EncodeObjectId(ecc_sets[x].oid, ecc_sets[x].oidSz, + o->oid, &o->oidSz); + } + if (oidSz) { + *oidSz = o->oidSz; + } + if (oid) { + *oid = o->oid; + } + #else + if (oidSz) { + *oidSz = ecc_sets[x].oidSz; + } + if (oid) { + *oid = ecc_sets[x].oid; + } + #endif + /* on success return curve id */ + if (ret == 0) { + ret = ecc_sets[x].id; + } + return ret; + } + } + + return NOT_COMPILED_IN; +} + +#ifdef WOLFSSL_CUSTOM_CURVES +int wc_ecc_set_custom_curve(ecc_key* key, const ecc_set_type* dp) +{ + if (key == NULL || dp == NULL) { + return BAD_FUNC_ARG; + } + + key->idx = ECC_CUSTOM_IDX; + key->dp = dp; + + return 0; +} +#endif /* WOLFSSL_CUSTOM_CURVES */ + +#ifdef HAVE_X963_KDF + +static WC_INLINE void IncrementX963KdfCounter(byte* inOutCtr) +{ + int i; + + /* in network byte order so start at end and work back */ + for (i = 3; i >= 0; i--) { + if (++inOutCtr[i]) /* we're done unless we overflow */ + return; + } +} + +/* ASN X9.63 Key Derivation Function (SEC1) */ +int wc_X963_KDF(enum wc_HashType type, const byte* secret, word32 secretSz, + const byte* sinfo, word32 sinfoSz, byte* out, word32 outSz) +{ + int ret, i; + int digestSz, copySz; + int remaining = outSz; + byte* outIdx; + byte counter[4]; + byte tmp[WC_MAX_DIGEST_SIZE]; + +#ifdef WOLFSSL_SMALL_STACK + wc_HashAlg* hash; +#else + wc_HashAlg hash[1]; +#endif + + if (secret == NULL || secretSz == 0 || out == NULL) + return BAD_FUNC_ARG; + + /* X9.63 allowed algos only */ + if (type != WC_HASH_TYPE_SHA && type != WC_HASH_TYPE_SHA224 && + type != WC_HASH_TYPE_SHA256 && type != WC_HASH_TYPE_SHA384 && + type != WC_HASH_TYPE_SHA512) + return BAD_FUNC_ARG; + + digestSz = wc_HashGetDigestSize(type); + if (digestSz < 0) + return digestSz; + +#ifdef WOLFSSL_SMALL_STACK + hash = (wc_HashAlg*)XMALLOC(sizeof(wc_HashAlg), NULL, + DYNAMIC_TYPE_HASHES); + if (hash == NULL) + return MEMORY_E; +#endif + + ret = wc_HashInit(hash, type); + if (ret != 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(hash, NULL, DYNAMIC_TYPE_HASHES); +#endif + return ret; + } + + outIdx = out; + XMEMSET(counter, 0, sizeof(counter)); + + for (i = 1; remaining > 0; i++) { + + IncrementX963KdfCounter(counter); + + ret = wc_HashUpdate(hash, type, secret, secretSz); + if (ret != 0) { + break; + } + + ret = wc_HashUpdate(hash, type, counter, sizeof(counter)); + if (ret != 0) { + break; + } + + if (sinfo) { + ret = wc_HashUpdate(hash, type, sinfo, sinfoSz); + if (ret != 0) { + break; + } + } + + ret = wc_HashFinal(hash, type, tmp); + if (ret != 0) { + break; + } + + copySz = min(remaining, digestSz); + XMEMCPY(outIdx, tmp, copySz); + + remaining -= copySz; + outIdx += copySz; + } + + wc_HashFree(hash, type); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(hash, NULL, DYNAMIC_TYPE_HASHES); +#endif + + return ret; +} +#endif /* HAVE_X963_KDF */ + +#endif /* HAVE_ECC */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/ecc_fp.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/ecc_fp.c new file mode 100755 index 0000000..c8acf93 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/ecc_fp.c @@ -0,0 +1 @@ +/* dummy ecc_fp.c for dist */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/ed25519.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/ed25519.c new file mode 100755 index 0000000..255cd29 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/ed25519.c @@ -0,0 +1,813 @@ +/* ed25519.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + /* Based On Daniel J Bernstein's ed25519 Public Domain ref10 work. */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +/* in case user set HAVE_ED25519 there */ +#include + +#ifdef HAVE_ED25519 + +#include +#include +#include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#ifdef FREESCALE_LTC_ECC + #include +#endif + +#if defined(HAVE_ED25519_SIGN) || defined(HAVE_ED25519_VERIFY) +#define ED25519CTX_SIZE 32 + +static const byte ed25519Ctx[ED25519CTX_SIZE+1] = + "SigEd25519 no Ed25519 collisions"; +#endif + +int wc_ed25519_make_public(ed25519_key* key, unsigned char* pubKey, + word32 pubKeySz) +{ + int ret = 0; + byte az[ED25519_PRV_KEY_SIZE]; +#if !defined(FREESCALE_LTC_ECC) + ge_p3 A; +#endif + + if (key == NULL || pubKeySz != ED25519_PUB_KEY_SIZE) + ret = BAD_FUNC_ARG; + + if (ret == 0) + ret = wc_Sha512Hash(key->k, ED25519_KEY_SIZE, az); + if (ret == 0) { + /* apply clamp */ + az[0] &= 248; + az[31] &= 63; /* same than az[31] &= 127 because of az[31] |= 64 */ + az[31] |= 64; + + #ifdef FREESCALE_LTC_ECC + ltc_pkha_ecc_point_t publicKey = {0}; + publicKey.X = key->pointX; + publicKey.Y = key->pointY; + LTC_PKHA_Ed25519_PointMul(LTC_PKHA_Ed25519_BasePoint(), az, + ED25519_KEY_SIZE, &publicKey, kLTC_Ed25519 /* result on Ed25519 */); + LTC_PKHA_Ed25519_Compress(&publicKey, pubKey); + #else + ge_scalarmult_base(&A, az); + ge_p3_tobytes(pubKey, &A); + #endif + } + + return ret; +} + +/* generate an ed25519 key pair. + * returns 0 on success + */ +int wc_ed25519_make_key(WC_RNG* rng, int keySz, ed25519_key* key) +{ + int ret; + + if (rng == NULL || key == NULL) + return BAD_FUNC_ARG; + + /* ed25519 has 32 byte key sizes */ + if (keySz != ED25519_KEY_SIZE) + return BAD_FUNC_ARG; + + ret = wc_RNG_GenerateBlock(rng, key->k, ED25519_KEY_SIZE); + if (ret != 0) + return ret; + + ret = wc_ed25519_make_public(key, key->p, ED25519_PUB_KEY_SIZE); + if (ret != 0) { + ForceZero(key->k, ED25519_KEY_SIZE); + return ret; + } + + /* put public key after private key, on the same buffer */ + XMEMMOVE(key->k + ED25519_KEY_SIZE, key->p, ED25519_PUB_KEY_SIZE); + + key->pubKeySet = 1; + + return ret; +} + + +#ifdef HAVE_ED25519_SIGN +/* + in contains the message to sign + inLen is the length of the message to sign + out is the buffer to write the signature + outLen [in/out] input size of out buf + output gets set as the final length of out + key is the ed25519 key to use when signing + type one of Ed25519, Ed25519ctx or Ed25519ph + context extra signing data + contextLen length of extra signing data + return 0 on success + */ +static int ed25519_sign_msg(const byte* in, word32 inLen, byte* out, + word32 *outLen, ed25519_key* key, byte type, + const byte* context, byte contextLen) +{ +#ifdef FREESCALE_LTC_ECC + byte tempBuf[ED25519_PRV_KEY_SIZE]; +#else + ge_p3 R; +#endif + byte nonce[WC_SHA512_DIGEST_SIZE]; + byte hram[WC_SHA512_DIGEST_SIZE]; + byte az[ED25519_PRV_KEY_SIZE]; + wc_Sha512 sha; + int ret; + + /* sanity check on arguments */ + if (in == NULL || out == NULL || outLen == NULL || key == NULL || + (context == NULL && contextLen != 0)) { + return BAD_FUNC_ARG; + } + if (!key->pubKeySet) + return BAD_FUNC_ARG; + + /* check and set up out length */ + if (*outLen < ED25519_SIG_SIZE) { + *outLen = ED25519_SIG_SIZE; + return BUFFER_E; + } + *outLen = ED25519_SIG_SIZE; + + /* step 1: create nonce to use where nonce is r in + r = H(h_b, ... ,h_2b-1,M) */ + ret = wc_Sha512Hash(key->k, ED25519_KEY_SIZE, az); + if (ret != 0) + return ret; + + /* apply clamp */ + az[0] &= 248; + az[31] &= 63; /* same than az[31] &= 127 because of az[31] |= 64 */ + az[31] |= 64; + + ret = wc_InitSha512(&sha); + if (ret != 0) + return ret; + if (type == Ed25519ctx || type == Ed25519ph) { + ret = wc_Sha512Update(&sha, ed25519Ctx, ED25519CTX_SIZE); + if (ret == 0) + ret = wc_Sha512Update(&sha, &type, sizeof(type)); + if (ret == 0) + ret = wc_Sha512Update(&sha, &contextLen, sizeof(contextLen)); + if (ret == 0 && context != NULL) + ret = wc_Sha512Update(&sha, context, contextLen); + } + if (ret == 0) + ret = wc_Sha512Update(&sha, az + ED25519_KEY_SIZE, ED25519_KEY_SIZE); + if (ret == 0) + ret = wc_Sha512Update(&sha, in, inLen); + if (ret == 0) + ret = wc_Sha512Final(&sha, nonce); + wc_Sha512Free(&sha); + if (ret != 0) + return ret; + +#ifdef FREESCALE_LTC_ECC + ltc_pkha_ecc_point_t ltcPoint = {0}; + ltcPoint.X = &tempBuf[0]; + ltcPoint.Y = &tempBuf[32]; + LTC_PKHA_sc_reduce(nonce); + LTC_PKHA_Ed25519_PointMul(LTC_PKHA_Ed25519_BasePoint(), nonce, + ED25519_KEY_SIZE, <cPoint, kLTC_Ed25519 /* result on Ed25519 */); + LTC_PKHA_Ed25519_Compress(<cPoint, out); +#else + sc_reduce(nonce); + + /* step 2: computing R = rB where rB is the scalar multiplication of + r and B */ + ge_scalarmult_base(&R,nonce); + ge_p3_tobytes(out,&R); +#endif + + /* step 3: hash R + public key + message getting H(R,A,M) then + creating S = (r + H(R,A,M)a) mod l */ + ret = wc_InitSha512(&sha); + if (ret != 0) + return ret; + if (type == Ed25519ctx || type == Ed25519ph) { + ret = wc_Sha512Update(&sha, ed25519Ctx, ED25519CTX_SIZE); + if (ret == 0) + ret = wc_Sha512Update(&sha, &type, sizeof(type)); + if (ret == 0) + ret = wc_Sha512Update(&sha, &contextLen, sizeof(contextLen)); + if (ret == 0 && context != NULL) + ret = wc_Sha512Update(&sha, context, contextLen); + } + if (ret == 0) + ret = wc_Sha512Update(&sha, out, ED25519_SIG_SIZE/2); + if (ret == 0) + ret = wc_Sha512Update(&sha, key->p, ED25519_PUB_KEY_SIZE); + if (ret == 0) + ret = wc_Sha512Update(&sha, in, inLen); + if (ret == 0) + ret = wc_Sha512Final(&sha, hram); + wc_Sha512Free(&sha); + if (ret != 0) + return ret; + +#ifdef FREESCALE_LTC_ECC + LTC_PKHA_sc_reduce(hram); + LTC_PKHA_sc_muladd(out + (ED25519_SIG_SIZE/2), hram, az, nonce); +#else + sc_reduce(hram); + sc_muladd(out + (ED25519_SIG_SIZE/2), hram, az, nonce); +#endif + + return ret; +} + +/* + in contains the message to sign + inLen is the length of the message to sign + out is the buffer to write the signature + outLen [in/out] input size of out buf + output gets set as the final length of out + key is the ed25519 key to use when signing + return 0 on success + */ +int wc_ed25519_sign_msg(const byte* in, word32 inLen, byte* out, + word32 *outLen, ed25519_key* key) +{ + return ed25519_sign_msg(in, inLen, out, outLen, key, Ed25519, NULL, 0); +} + +/* + in contains the message to sign + inLen is the length of the message to sign + out is the buffer to write the signature + outLen [in/out] input size of out buf + output gets set as the final length of out + key is the ed25519 key to use when signing + context extra signing data + contextLen length of extra signing data + return 0 on success + */ +int wc_ed25519ctx_sign_msg(const byte* in, word32 inLen, byte* out, + word32 *outLen, ed25519_key* key, + const byte* context, byte contextLen) +{ + return ed25519_sign_msg(in, inLen, out, outLen, key, Ed25519ctx, context, + contextLen); +} + +/* + hash contains the SHA-512 hash of the message to sign + hashLen is the length of the SHA-512 hash of the message to sign + out is the buffer to write the signature + outLen [in/out] input size of out buf + output gets set as the final length of out + key is the ed25519 key to use when signing + context extra signing data + contextLen length of extra signing data + return 0 on success + */ +int wc_ed25519ph_sign_hash(const byte* hash, word32 hashLen, byte* out, + word32 *outLen, ed25519_key* key, + const byte* context, byte contextLen) +{ + return ed25519_sign_msg(hash, hashLen, out, outLen, key, Ed25519ph, context, + contextLen); +} + +/* + in contains the message to sign + inLen is the length of the message to sign + out is the buffer to write the signature + outLen [in/out] input size of out buf + output gets set as the final length of out + key is the ed25519 key to use when signing + context extra signing data + contextLen length of extra signing data + return 0 on success + */ +int wc_ed25519ph_sign_msg(const byte* in, word32 inLen, byte* out, + word32 *outLen, ed25519_key* key, + const byte* context, byte contextLen) +{ + int ret; + byte hash[WC_SHA512_DIGEST_SIZE]; + + ret = wc_Sha512Hash(in, inLen, hash); + if (ret != 0) + return ret; + + return wc_ed25519ph_sign_hash(hash, sizeof(hash), out, outLen, key, context, + contextLen); +} +#endif /* HAVE_ED25519_SIGN */ + +#ifdef HAVE_ED25519_VERIFY + +/* + sig is array of bytes containing the signature + sigLen is the length of sig byte array + msg the array of bytes containing the message + msgLen length of msg array + res will be 1 on successful verify and 0 on unsuccessful + key Ed25519 public key + return 0 and res of 1 on success +*/ +static int ed25519_verify_msg(const byte* sig, word32 sigLen, const byte* msg, + word32 msgLen, int* res, ed25519_key* key, + byte type, const byte* context, byte contextLen) +{ + byte rcheck[ED25519_KEY_SIZE]; + byte h[WC_SHA512_DIGEST_SIZE]; +#ifndef FREESCALE_LTC_ECC + ge_p3 A; + ge_p2 R; +#endif + int ret; + wc_Sha512 sha; + + /* sanity check on arguments */ + if (sig == NULL || msg == NULL || res == NULL || key == NULL || + (context == NULL && contextLen != 0)) { + return BAD_FUNC_ARG; + } + + /* set verification failed by default */ + *res = 0; + + /* check on basics needed to verify signature */ + if (sigLen < ED25519_SIG_SIZE || (sig[ED25519_SIG_SIZE-1] & 224)) + return BAD_FUNC_ARG; + + /* uncompress A (public key), test if valid, and negate it */ +#ifndef FREESCALE_LTC_ECC + if (ge_frombytes_negate_vartime(&A, key->p) != 0) + return BAD_FUNC_ARG; +#endif + + /* find H(R,A,M) and store it as h */ + ret = wc_InitSha512(&sha); + if (ret != 0) + return ret; + if (type == Ed25519ctx || type == Ed25519ph) { + ret = wc_Sha512Update(&sha, ed25519Ctx, ED25519CTX_SIZE); + if (ret == 0) + ret = wc_Sha512Update(&sha, &type, sizeof(type)); + if (ret == 0) + ret = wc_Sha512Update(&sha, &contextLen, sizeof(contextLen)); + if (ret == 0 && context != NULL) + ret = wc_Sha512Update(&sha, context, contextLen); + } + if (ret == 0) + ret = wc_Sha512Update(&sha, sig, ED25519_SIG_SIZE/2); + if (ret == 0) + ret = wc_Sha512Update(&sha, key->p, ED25519_PUB_KEY_SIZE); + if (ret == 0) + ret = wc_Sha512Update(&sha, msg, msgLen); + if (ret == 0) + ret = wc_Sha512Final(&sha, h); + wc_Sha512Free(&sha); + if (ret != 0) + return ret; + +#ifdef FREESCALE_LTC_ECC + LTC_PKHA_sc_reduce(h); + LTC_PKHA_SignatureForVerify(rcheck, h, sig + (ED25519_SIG_SIZE/2), key); +#else + sc_reduce(h); + + /* + Uses a fast single-signature verification SB = R + H(R,A,M)A becomes + SB - H(R,A,M)A saving decompression of R + */ + ret = ge_double_scalarmult_vartime(&R, h, &A, sig + (ED25519_SIG_SIZE/2)); + if (ret != 0) + return ret; + + ge_tobytes(rcheck, &R); +#endif /* FREESCALE_LTC_ECC */ + + /* comparison of R created to R in sig */ + ret = ConstantCompare(rcheck, sig, ED25519_SIG_SIZE/2); + if (ret != 0) + return SIG_VERIFY_E; + + /* set the verification status */ + *res = 1; + + return ret; +} + +/* + sig is array of bytes containing the signature + sigLen is the length of sig byte array + msg the array of bytes containing the message + msgLen length of msg array + res will be 1 on successful verify and 0 on unsuccessful + key Ed25519 public key + return 0 and res of 1 on success +*/ +int wc_ed25519_verify_msg(const byte* sig, word32 sigLen, const byte* msg, + word32 msgLen, int* res, ed25519_key* key) +{ + return ed25519_verify_msg(sig, sigLen, msg, msgLen, res, key, Ed25519, NULL, + 0); +} + +/* + sig is array of bytes containing the signature + sigLen is the length of sig byte array + msg the array of bytes containing the message + msgLen length of msg array + res will be 1 on successful verify and 0 on unsuccessful + key Ed25519 public key + context extra sigining data + contextLen length of extra sigining data + return 0 and res of 1 on success +*/ +int wc_ed25519ctx_verify_msg(const byte* sig, word32 sigLen, const byte* msg, + word32 msgLen, int* res, ed25519_key* key, + const byte* context, byte contextLen) +{ + return ed25519_verify_msg(sig, sigLen, msg, msgLen, res, key, Ed25519ctx, + context, contextLen); +} + +/* + sig is array of bytes containing the signature + sigLen is the length of sig byte array + hash the array of bytes containing the SHA-512 hash of the message + hashLen length of hash array + res will be 1 on successful verify and 0 on unsuccessful + key Ed25519 public key + context extra sigining data + contextLen length of extra sigining data + return 0 and res of 1 on success +*/ +int wc_ed25519ph_verify_hash(const byte* sig, word32 sigLen, const byte* hash, + word32 hashLen, int* res, ed25519_key* key, + const byte* context, byte contextLen) +{ + return ed25519_verify_msg(sig, sigLen, hash, hashLen, res, key, Ed25519ph, + context, contextLen); +} + +/* + sig is array of bytes containing the signature + sigLen is the length of sig byte array + msg the array of bytes containing the message + msgLen length of msg array + res will be 1 on successful verify and 0 on unsuccessful + key Ed25519 public key + context extra sigining data + contextLen length of extra sigining data + return 0 and res of 1 on success +*/ +int wc_ed25519ph_verify_msg(const byte* sig, word32 sigLen, const byte* msg, + word32 msgLen, int* res, ed25519_key* key, + const byte* context, byte contextLen) +{ + int ret; + byte hash[WC_SHA512_DIGEST_SIZE]; + + ret = wc_Sha512Hash(msg, msgLen, hash); + if (ret != 0) + return ret; + + return wc_ed25519ph_verify_hash(sig, sigLen, hash, sizeof(hash), res, key, + context, contextLen); +} +#endif /* HAVE_ED25519_VERIFY */ + + +/* initialize information and memory for key */ +int wc_ed25519_init(ed25519_key* key) +{ + if (key == NULL) + return BAD_FUNC_ARG; + + XMEMSET(key, 0, sizeof(ed25519_key)); + +#ifndef FREESCALE_LTC_ECC + fe_init(); +#endif + + return 0; +} + + +/* clear memory of key */ +void wc_ed25519_free(ed25519_key* key) +{ + if (key == NULL) + return; + + ForceZero(key, sizeof(ed25519_key)); +} + + +#ifdef HAVE_ED25519_KEY_EXPORT + +/* + outLen should contain the size of out buffer when input. outLen is than set + to the final output length. + returns 0 on success + */ +int wc_ed25519_export_public(ed25519_key* key, byte* out, word32* outLen) +{ + /* sanity check on arguments */ + if (key == NULL || out == NULL || outLen == NULL) + return BAD_FUNC_ARG; + + if (*outLen < ED25519_PUB_KEY_SIZE) { + *outLen = ED25519_PUB_KEY_SIZE; + return BUFFER_E; + } + + *outLen = ED25519_PUB_KEY_SIZE; + XMEMCPY(out, key->p, ED25519_PUB_KEY_SIZE); + + return 0; +} + +#endif /* HAVE_ED25519_KEY_EXPORT */ + + +#ifdef HAVE_ED25519_KEY_IMPORT +/* + Imports a compressed/uncompressed public key. + in the byte array containing the public key + inLen the length of the byte array being passed in + key ed25519 key struct to put the public key in + */ +int wc_ed25519_import_public(const byte* in, word32 inLen, ed25519_key* key) +{ + int ret; + + /* sanity check on arguments */ + if (in == NULL || key == NULL) + return BAD_FUNC_ARG; + + if (inLen < ED25519_PUB_KEY_SIZE) + return BAD_FUNC_ARG; + + /* compressed prefix according to draft + http://www.ietf.org/id/draft-koch-eddsa-for-openpgp-02.txt */ + if (in[0] == 0x40 && inLen > ED25519_PUB_KEY_SIZE) { + /* key is stored in compressed format so just copy in */ + XMEMCPY(key->p, (in + 1), ED25519_PUB_KEY_SIZE); +#ifdef FREESCALE_LTC_ECC + /* recover X coordinate */ + ltc_pkha_ecc_point_t pubKey; + pubKey.X = key->pointX; + pubKey.Y = key->pointY; + LTC_PKHA_Ed25519_PointDecompress(key->p, ED25519_PUB_KEY_SIZE, &pubKey); +#endif + key->pubKeySet = 1; + return 0; + } + + /* importing uncompressed public key */ + if (in[0] == 0x04 && inLen > 2*ED25519_PUB_KEY_SIZE) { +#ifdef FREESCALE_LTC_ECC + /* reverse bytes for little endian byte order */ + for (int i = 0; i < ED25519_KEY_SIZE; i++) + { + key->pointX[i] = *(in + ED25519_KEY_SIZE - i); + key->pointY[i] = *(in + 2*ED25519_KEY_SIZE - i); + } + XMEMCPY(key->p, key->pointY, ED25519_KEY_SIZE); + ret = 0; +#else + /* pass in (x,y) and store compressed key */ + ret = ge_compress_key(key->p, in+1, + in+1+ED25519_PUB_KEY_SIZE, ED25519_PUB_KEY_SIZE); +#endif /* FREESCALE_LTC_ECC */ + if (ret == 0) + key->pubKeySet = 1; + return ret; + } + + /* if not specified compressed or uncompressed check key size + if key size is equal to compressed key size copy in key */ + if (inLen == ED25519_PUB_KEY_SIZE) { + XMEMCPY(key->p, in, ED25519_PUB_KEY_SIZE); +#ifdef FREESCALE_LTC_ECC + /* recover X coordinate */ + ltc_pkha_ecc_point_t pubKey; + pubKey.X = key->pointX; + pubKey.Y = key->pointY; + LTC_PKHA_Ed25519_PointDecompress(key->p, ED25519_PUB_KEY_SIZE, &pubKey); +#endif + key->pubKeySet = 1; + return 0; + } + + /* bad public key format */ + return BAD_FUNC_ARG; +} + + +/* + For importing a private key. + */ +int wc_ed25519_import_private_only(const byte* priv, word32 privSz, + ed25519_key* key) +{ + /* sanity check on arguments */ + if (priv == NULL || key == NULL) + return BAD_FUNC_ARG; + + /* key size check */ + if (privSz < ED25519_KEY_SIZE) + return BAD_FUNC_ARG; + + XMEMCPY(key->k, priv, ED25519_KEY_SIZE); + + return 0; +} + +/* + For importing a private key and its associated public key. + */ +int wc_ed25519_import_private_key(const byte* priv, word32 privSz, + const byte* pub, word32 pubSz, ed25519_key* key) +{ + int ret; + + /* sanity check on arguments */ + if (priv == NULL || pub == NULL || key == NULL) + return BAD_FUNC_ARG; + + /* key size check */ + if (privSz < ED25519_KEY_SIZE || pubSz < ED25519_PUB_KEY_SIZE) + return BAD_FUNC_ARG; + + /* import public key */ + ret = wc_ed25519_import_public(pub, pubSz, key); + if (ret != 0) + return ret; + + /* make the private key (priv + pub) */ + XMEMCPY(key->k, priv, ED25519_KEY_SIZE); + XMEMCPY(key->k + ED25519_KEY_SIZE, key->p, ED25519_PUB_KEY_SIZE); + + return ret; +} + +#endif /* HAVE_ED25519_KEY_IMPORT */ + + +#ifdef HAVE_ED25519_KEY_EXPORT + +/* + export private key only (secret part so 32 bytes) + outLen should contain the size of out buffer when input. outLen is than set + to the final output length. + returns 0 on success + */ +int wc_ed25519_export_private_only(ed25519_key* key, byte* out, word32* outLen) +{ + /* sanity checks on arguments */ + if (key == NULL || out == NULL || outLen == NULL) + return BAD_FUNC_ARG; + + if (*outLen < ED25519_KEY_SIZE) { + *outLen = ED25519_KEY_SIZE; + return BUFFER_E; + } + + *outLen = ED25519_KEY_SIZE; + XMEMCPY(out, key->k, ED25519_KEY_SIZE); + + return 0; +} + +/* + export private key, including public part + outLen should contain the size of out buffer when input. outLen is than set + to the final output length. + returns 0 on success + */ +int wc_ed25519_export_private(ed25519_key* key, byte* out, word32* outLen) +{ + /* sanity checks on arguments */ + if (key == NULL || out == NULL || outLen == NULL) + return BAD_FUNC_ARG; + + if (*outLen < ED25519_PRV_KEY_SIZE) { + *outLen = ED25519_PRV_KEY_SIZE; + return BUFFER_E; + } + + *outLen = ED25519_PRV_KEY_SIZE; + XMEMCPY(out, key->k, ED25519_PRV_KEY_SIZE); + + return 0; +} + +/* export full private key and public key + return 0 on success + */ +int wc_ed25519_export_key(ed25519_key* key, + byte* priv, word32 *privSz, + byte* pub, word32 *pubSz) +{ + int ret; + + /* export 'full' private part */ + ret = wc_ed25519_export_private(key, priv, privSz); + if (ret != 0) + return ret; + + /* export public part */ + ret = wc_ed25519_export_public(key, pub, pubSz); + + return ret; +} + +#endif /* HAVE_ED25519_KEY_EXPORT */ + +/* check the private and public keys match */ +int wc_ed25519_check_key(ed25519_key* key) +{ + int ret = 0; + unsigned char pubKey[ED25519_PUB_KEY_SIZE]; + + if (!key->pubKeySet) + ret = PUBLIC_KEY_E; + if (ret == 0) + ret = wc_ed25519_make_public(key, pubKey, sizeof(pubKey)); + if (ret == 0 && XMEMCMP(pubKey, key->p, ED25519_PUB_KEY_SIZE) != 0) + ret = PUBLIC_KEY_E; + + return ret; +} + +/* returns the private key size (secret only) in bytes */ +int wc_ed25519_size(ed25519_key* key) +{ + if (key == NULL) + return BAD_FUNC_ARG; + + return ED25519_KEY_SIZE; +} + +/* returns the private key size (secret + public) in bytes */ +int wc_ed25519_priv_size(ed25519_key* key) +{ + if (key == NULL) + return BAD_FUNC_ARG; + + return ED25519_PRV_KEY_SIZE; +} + +/* returns the compressed key size in bytes (public key) */ +int wc_ed25519_pub_size(ed25519_key* key) +{ + if (key == NULL) + return BAD_FUNC_ARG; + + return ED25519_PUB_KEY_SIZE; +} + +/* returns the size of signature in bytes */ +int wc_ed25519_sig_size(ed25519_key* key) +{ + if (key == NULL) + return BAD_FUNC_ARG; + + return ED25519_SIG_SIZE; +} + +#endif /* HAVE_ED25519 */ + diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/error.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/error.c new file mode 100755 index 0000000..eed51ba --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/error.c @@ -0,0 +1,523 @@ +/* error.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#include + +#ifdef _MSC_VER + /* 4996 warning to use MS extensions e.g., strcpy_s instead of XSTRNCPY */ + #pragma warning(disable: 4996) +#endif + +#ifndef NO_ERROR_STRINGS +const char* wc_GetErrorString(int error) +{ + switch (error) { + + case OPEN_RAN_E : + return "opening random device error"; + + case READ_RAN_E : + return "reading random device error"; + + case WINCRYPT_E : + return "windows crypt init error"; + + case CRYPTGEN_E : + return "windows crypt generation error"; + + case RAN_BLOCK_E : + return "random device read would block error"; + + case BAD_MUTEX_E : + return "Bad mutex, operation failed"; + + case WC_TIMEOUT_E: + return "Timeout error"; + + case WC_PENDING_E: + return "wolfCrypt Operation Pending (would block / eagain) error"; + + case WC_NOT_PENDING_E: + return "wolfCrypt operation not pending error"; + + case MP_INIT_E : + return "mp_init error state"; + + case MP_READ_E : + return "mp_read error state"; + + case MP_EXPTMOD_E : + return "mp_exptmod error state"; + + case MP_TO_E : + return "mp_to_xxx error state, can't convert"; + + case MP_SUB_E : + return "mp_sub error state, can't subtract"; + + case MP_ADD_E : + return "mp_add error state, can't add"; + + case MP_MUL_E : + return "mp_mul error state, can't multiply"; + + case MP_MULMOD_E : + return "mp_mulmod error state, can't multiply mod"; + + case MP_MOD_E : + return "mp_mod error state, can't mod"; + + case MP_INVMOD_E : + return "mp_invmod error state, can't inv mod"; + + case MP_CMP_E : + return "mp_cmp error state"; + + case MP_ZERO_E : + return "mp zero result, not expected"; + + case MEMORY_E : + return "out of memory error"; + + case VAR_STATE_CHANGE_E : + return "Variable state modified by different thread"; + + case RSA_WRONG_TYPE_E : + return "RSA wrong block type for RSA function"; + + case RSA_BUFFER_E : + return "RSA buffer error, output too small or input too big"; + + case BUFFER_E : + return "Buffer error, output too small or input too big"; + + case ALGO_ID_E : + return "Setting Cert AlgoID error"; + + case PUBLIC_KEY_E : + return "Setting Cert Public Key error"; + + case DATE_E : + return "Setting Cert Date validity error"; + + case SUBJECT_E : + return "Setting Cert Subject name error"; + + case ISSUER_E : + return "Setting Cert Issuer name error"; + + case CA_TRUE_E : + return "Setting basic constraint CA true error"; + + case EXTENSIONS_E : + return "Setting extensions error"; + + case ASN_PARSE_E : + return "ASN parsing error, invalid input"; + + case ASN_VERSION_E : + return "ASN version error, invalid number"; + + case ASN_GETINT_E : + return "ASN get big int error, invalid data"; + + case ASN_RSA_KEY_E : + return "ASN key init error, invalid input"; + + case ASN_OBJECT_ID_E : + return "ASN object id error, invalid id"; + + case ASN_TAG_NULL_E : + return "ASN tag error, not null"; + + case ASN_EXPECT_0_E : + return "ASN expect error, not zero"; + + case ASN_BITSTR_E : + return "ASN bit string error, wrong id"; + + case ASN_UNKNOWN_OID_E : + return "ASN oid error, unknown sum id"; + + case ASN_DATE_SZ_E : + return "ASN date error, bad size"; + + case ASN_BEFORE_DATE_E : + return "ASN date error, current date before"; + + case ASN_AFTER_DATE_E : + return "ASN date error, current date after"; + + case ASN_SIG_OID_E : + return "ASN signature error, mismatched oid"; + + case ASN_TIME_E : + return "ASN time error, unknown time type"; + + case ASN_INPUT_E : + return "ASN input error, not enough data"; + + case ASN_SIG_CONFIRM_E : + return "ASN sig error, confirm failure"; + + case ASN_SIG_HASH_E : + return "ASN sig error, unsupported hash type"; + + case ASN_SIG_KEY_E : + return "ASN sig error, unsupported key type"; + + case ASN_DH_KEY_E : + return "ASN key init error, invalid input"; + + case ASN_NTRU_KEY_E : + return "ASN NTRU key decode error, invalid input"; + + case ASN_CRIT_EXT_E: + return "X.509 Critical extension ignored or invalid"; + + case ASN_ALT_NAME_E: + return "ASN alternate name error"; + + case ECC_BAD_ARG_E : + return "ECC input argument wrong type, invalid input"; + + case ASN_ECC_KEY_E : + return "ECC ASN1 bad key data, invalid input"; + + case ECC_CURVE_OID_E : + return "ECC curve sum OID unsupported, invalid input"; + + case BAD_FUNC_ARG : + return "Bad function argument"; + + case NOT_COMPILED_IN : + return "Feature not compiled in"; + + case UNICODE_SIZE_E : + return "Unicode password too big"; + + case NO_PASSWORD : + return "No password provided by user"; + + case ALT_NAME_E : + return "Alt Name problem, too big"; + + case AES_GCM_AUTH_E: + return "AES-GCM Authentication check fail"; + + case AES_CCM_AUTH_E: + return "AES-CCM Authentication check fail"; + + case ASYNC_INIT_E: + return "Async Init error"; + + case COMPRESS_INIT_E: + return "Compress Init error"; + + case COMPRESS_E: + return "Compress error"; + + case DECOMPRESS_INIT_E: + return "DeCompress Init error"; + + case DECOMPRESS_E: + return "DeCompress error"; + + case BAD_ALIGN_E: + return "Bad alignment error, no alloc help"; + + case ASN_NO_SIGNER_E : + return "ASN no signer error to confirm failure"; + + case ASN_CRL_CONFIRM_E : + return "ASN CRL sig error, confirm failure"; + + case ASN_CRL_NO_SIGNER_E : + return "ASN CRL no signer error to confirm failure"; + + case ASN_OCSP_CONFIRM_E : + return "ASN OCSP sig error, confirm failure"; + + case ASN_NO_PEM_HEADER: + return "ASN no PEM Header Error"; + + case BAD_STATE_E: + return "Bad state operation"; + + case BAD_PADDING_E: + return "Bad padding, message wrong length"; + + case REQ_ATTRIBUTE_E: + return "Setting cert request attributes error"; + + case PKCS7_OID_E: + return "PKCS#7 error: mismatched OID value"; + + case PKCS7_RECIP_E: + return "PKCS#7 error: no matching recipient found"; + + case WC_PKCS7_WANT_READ_E: + return "PKCS#7 operations wants more input, call again"; + + case FIPS_NOT_ALLOWED_E: + return "FIPS mode not allowed error"; + + case ASN_NAME_INVALID_E: + return "Name Constraint error"; + + case RNG_FAILURE_E: + return "Random Number Generator failed"; + + case HMAC_MIN_KEYLEN_E: + return "FIPS Mode HMAC Minimum Key Length error"; + + case RSA_PAD_E: + return "Rsa Padding error"; + + case LENGTH_ONLY_E: + return "Output length only set, not for other use error"; + + case IN_CORE_FIPS_E: + return "In Core Integrity check FIPS error"; + + case AES_KAT_FIPS_E: + return "AES Known Answer Test check FIPS error"; + + case DES3_KAT_FIPS_E: + return "DES3 Known Answer Test check FIPS error"; + + case HMAC_KAT_FIPS_E: + return "HMAC Known Answer Test check FIPS error"; + + case RSA_KAT_FIPS_E: + return "RSA Known Answer Test check FIPS error"; + + case DRBG_KAT_FIPS_E: + return "DRBG Known Answer Test check FIPS error"; + + case DRBG_CONT_FIPS_E: + return "DRBG Continuous Test FIPS error"; + + case AESGCM_KAT_FIPS_E: + return "AESGCM Known Answer Test check FIPS error"; + + case THREAD_STORE_KEY_E: + return "Thread Storage Key Create error"; + + case THREAD_STORE_SET_E: + return "Thread Storage Set error"; + + case MAC_CMP_FAILED_E: + return "MAC comparison failed"; + + case IS_POINT_E: + return "ECC is point on curve failed"; + + case ECC_INF_E: + return " ECC point at infinity error"; + + case ECC_OUT_OF_RANGE_E: + return " ECC Qx or Qy out of range error"; + + case ECC_PRIV_KEY_E: + return " ECC private key is not valid error"; + + case SRP_CALL_ORDER_E: + return "SRP function called in the wrong order error"; + + case SRP_VERIFY_E: + return "SRP proof verification error"; + + case SRP_BAD_KEY_E: + return "SRP bad key values error"; + + case ASN_NO_SKID: + return "ASN no Subject Key Identifier found error"; + + case ASN_NO_AKID: + return "ASN no Authority Key Identifier found error"; + + case ASN_NO_KEYUSAGE: + return "ASN no Key Usage found error"; + + case SKID_E: + return "Setting Subject Key Identifier error"; + + case AKID_E: + return "Setting Authority Key Identifier error"; + + case KEYUSAGE_E: + return "Key Usage value error"; + + case EXTKEYUSAGE_E: + return "Extended Key Usage value error"; + + case CERTPOLICIES_E: + return "Setting Certificate Policies error"; + + case WC_INIT_E: + return "wolfCrypt Initialize Failure error"; + + case SIG_VERIFY_E: + return "Signature verify error"; + + case BAD_COND_E: + return "Bad condition variable operation error"; + + case SIG_TYPE_E: + return "Signature type not enabled/available"; + + case HASH_TYPE_E: + return "Hash type not enabled/available"; + + case WC_KEY_SIZE_E: + return "Key size error, either too small or large"; + + case ASN_COUNTRY_SIZE_E: + return "Country code size error, either too small or large"; + + case MISSING_RNG_E: + return "RNG required but not provided"; + + case ASN_PATHLEN_SIZE_E: + return "ASN CA path length value too large error"; + + case ASN_PATHLEN_INV_E: + return "ASN CA path length larger than signer error"; + + case BAD_KEYWRAP_ALG_E: + return "Unsupported key wrap algorithm error"; + + case BAD_KEYWRAP_IV_E: + return "Decrypted AES key wrap IV does not match expected"; + + case WC_CLEANUP_E: + return "wolfcrypt cleanup failed"; + + case ECC_CDH_KAT_FIPS_E: + return "wolfcrypt FIPS ECC CDH Known Answer Test Failure"; + + case DH_CHECK_PUB_E: + return "DH Check Public Key failure"; + + case BAD_PATH_ERROR: + return "Bad path for opendir error"; + + case ASYNC_OP_E: + return "Async operation error"; + + case BAD_OCSP_RESPONDER: + return "Invalid OCSP Responder, missing specific key usage extensions"; + + case ECC_PRIVATEONLY_E: + return "Invalid use of private only ECC key"; + + case WC_HW_E: + return "Error with hardware crypto use"; + + case WC_HW_WAIT_E: + return "Hardware waiting on resource"; + + case PSS_SALTLEN_E: + return "PSS - Length of salt is too big for hash algorithm"; + + case PRIME_GEN_E: + return "Unable to find a prime for RSA key"; + + case BER_INDEF_E: + return "Unable to decode an indefinite length encoded message"; + + case RSA_OUT_OF_RANGE_E: + return "Ciphertext to decrypt is out of range"; + + case RSAPSS_PAT_FIPS_E: + return "wolfcrypt FIPS RSA-PSS Pairwise Agreement Test Failure"; + + case ECDSA_PAT_FIPS_E: + return "wolfcrypt FIPS ECDSA Pairwise Agreement Test Failure"; + + case DH_KAT_FIPS_E: + return "wolfcrypt FIPS DH Known Answer Test Failure"; + + case AESCCM_KAT_FIPS_E: + return "AESCCM Known Answer Test check FIPS error"; + + case SHA3_KAT_FIPS_E: + return "SHA-3 Known Answer Test check FIPS error"; + + case ECDHE_KAT_FIPS_E: + return "wolfcrypt FIPS ECDHE Known Answer Test Failure"; + + case AES_GCM_OVERFLOW_E: + return "AES-GCM invocation counter overflow"; + + case AES_CCM_OVERFLOW_E: + return "AES-CCM invocation counter overflow"; + + case RSA_KEY_PAIR_E: + return "RSA Key Pair-Wise Consistency check fail"; + + case DH_CHECK_PRIV_E: + return "DH Check Private Key failure"; + + case WC_AFALG_SOCK_E: + return "AF_ALG socket error"; + + case WC_DEVCRYPTO_E: + return "Error with /dev/crypto"; + + case ZLIB_INIT_ERROR: + return "zlib init error"; + + case ZLIB_COMPRESS_ERROR: + return "zlib compress error"; + + case ZLIB_DECOMPRESS_ERROR: + return "zlib decompress error"; + + case PKCS7_NO_SIGNER_E: + return "No signer in PKCS#7 signed data"; + + case CRYPTOCB_UNAVAILABLE: + return "Crypto callback unavailable"; + + case PKCS7_SIGNEEDS_CHECK: + return "Signature found but no certificate to verify"; + + default: + return "unknown error number"; + + } +} + +void wc_ErrorString(int error, char* buffer) +{ + XSTRNCPY(buffer, wc_GetErrorString(error), WOLFSSL_MAX_ERROR_SZ); +} +#endif /* !NO_ERROR_STRINGS */ + diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/evp.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/evp.c new file mode 100755 index 0000000..ab0ce9c --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/evp.c @@ -0,0 +1,1624 @@ +/* evp.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#include + +#if !defined(WOLFSSL_EVP_INCLUDED) + #ifndef WOLFSSL_IGNORE_FILE_WARN + #warning evp.c does not need to be compiled seperatly from ssl.c + #endif +#else + +static unsigned int cipherType(const WOLFSSL_EVP_CIPHER *cipher); + + +/* Getter function for cipher key length + * + * c WOLFSSL_EVP_CIPHER structure to get key length from + * + * NOTE: OpenSSL_add_all_ciphers() should be called first before using this + * function + * + * Returns size of key in bytes + */ +int wolfSSL_EVP_Cipher_key_length(const WOLFSSL_EVP_CIPHER* c) +{ + WOLFSSL_ENTER("wolfSSL_EVP_Cipher_key_length"); + + if (c == NULL) { + return 0; + } + + switch (cipherType(c)) { + #if !defined(NO_AES) && defined(HAVE_AES_CBC) + case AES_128_CBC_TYPE: return 16; + case AES_192_CBC_TYPE: return 24; + case AES_256_CBC_TYPE: return 32; + #endif + #if !defined(NO_AES) && defined(WOLFSSL_AES_COUNTER) + case AES_128_CTR_TYPE: return 16; + case AES_192_CTR_TYPE: return 24; + case AES_256_CTR_TYPE: return 32; + #endif + #if !defined(NO_AES) && defined(HAVE_AES_ECB) + case AES_128_ECB_TYPE: return 16; + case AES_192_ECB_TYPE: return 24; + case AES_256_ECB_TYPE: return 32; + #endif + #ifndef NO_DES3 + case DES_CBC_TYPE: return 8; + case DES_EDE3_CBC_TYPE: return 24; + case DES_ECB_TYPE: return 8; + case DES_EDE3_ECB_TYPE: return 24; + #endif + default: + return 0; + } +} + + +WOLFSSL_API int wolfSSL_EVP_EncryptInit(WOLFSSL_EVP_CIPHER_CTX* ctx, + const WOLFSSL_EVP_CIPHER* type, + const unsigned char* key, + const unsigned char* iv) +{ + return wolfSSL_EVP_CipherInit(ctx, type, (byte*)key, (byte*)iv, 1); +} + +WOLFSSL_API int wolfSSL_EVP_EncryptInit_ex(WOLFSSL_EVP_CIPHER_CTX* ctx, + const WOLFSSL_EVP_CIPHER* type, + WOLFSSL_ENGINE *impl, + const unsigned char* key, + const unsigned char* iv) +{ + (void) impl; + return wolfSSL_EVP_CipherInit(ctx, type, (byte*)key, (byte*)iv, 1); +} + +WOLFSSL_API int wolfSSL_EVP_DecryptInit(WOLFSSL_EVP_CIPHER_CTX* ctx, + const WOLFSSL_EVP_CIPHER* type, + const unsigned char* key, + const unsigned char* iv) +{ + WOLFSSL_ENTER("wolfSSL_EVP_CipherInit"); + return wolfSSL_EVP_CipherInit(ctx, type, (byte*)key, (byte*)iv, 0); +} + +WOLFSSL_API int wolfSSL_EVP_DecryptInit_ex(WOLFSSL_EVP_CIPHER_CTX* ctx, + const WOLFSSL_EVP_CIPHER* type, + WOLFSSL_ENGINE *impl, + const unsigned char* key, + const unsigned char* iv) +{ + (void) impl; + WOLFSSL_ENTER("wolfSSL_EVP_DecryptInit"); + return wolfSSL_EVP_CipherInit(ctx, type, (byte*)key, (byte*)iv, 0); +} + + +WOLFSSL_API WOLFSSL_EVP_CIPHER_CTX *wolfSSL_EVP_CIPHER_CTX_new(void) +{ + WOLFSSL_EVP_CIPHER_CTX *ctx = (WOLFSSL_EVP_CIPHER_CTX*)XMALLOC(sizeof *ctx, + NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (ctx) { + WOLFSSL_ENTER("wolfSSL_EVP_CIPHER_CTX_new"); + wolfSSL_EVP_CIPHER_CTX_init(ctx); + } + return ctx; +} + +WOLFSSL_API void wolfSSL_EVP_CIPHER_CTX_free(WOLFSSL_EVP_CIPHER_CTX *ctx) +{ + if (ctx) { + WOLFSSL_ENTER("wolfSSL_EVP_CIPHER_CTX_free"); + wolfSSL_EVP_CIPHER_CTX_cleanup(ctx); + XFREE(ctx, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } +} + +WOLFSSL_API unsigned long wolfSSL_EVP_CIPHER_CTX_mode(const WOLFSSL_EVP_CIPHER_CTX *ctx) +{ + if (ctx == NULL) return 0; + return ctx->flags & WOLFSSL_EVP_CIPH_MODE; +} + +WOLFSSL_API int wolfSSL_EVP_EncryptFinal(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, int *outl) +{ + if (ctx && ctx->enc) { + WOLFSSL_ENTER("wolfSSL_EVP_EncryptFinal"); + return wolfSSL_EVP_CipherFinal(ctx, out, outl); + } + else + return WOLFSSL_FAILURE; +} + + +WOLFSSL_API int wolfSSL_EVP_CipherInit_ex(WOLFSSL_EVP_CIPHER_CTX* ctx, + const WOLFSSL_EVP_CIPHER* type, + WOLFSSL_ENGINE *impl, + const unsigned char* key, + const unsigned char* iv, + int enc) +{ + (void)impl; + return wolfSSL_EVP_CipherInit(ctx, type, key, iv, enc); +} + +WOLFSSL_API int wolfSSL_EVP_EncryptFinal_ex(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, int *outl) +{ + if (ctx && ctx->enc) { + WOLFSSL_ENTER("wolfSSL_EVP_EncryptFinal_ex"); + return wolfSSL_EVP_CipherFinal(ctx, out, outl); + } + else + return WOLFSSL_FAILURE; +} + +WOLFSSL_API int wolfSSL_EVP_DecryptFinal(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, int *outl) +{ + if (ctx && ctx->enc) { + WOLFSSL_ENTER("wolfSSL_EVP_DecryptFinal"); + return wolfSSL_EVP_CipherFinal(ctx, out, outl); + } + else { + return WOLFSSL_FAILURE; + } +} + +WOLFSSL_API int wolfSSL_EVP_DecryptFinal_ex(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, int *outl) +{ + if (ctx && ctx->enc) { + WOLFSSL_ENTER("wolfSSL_EVP_DecryptFinal_ex"); + return wolfSSL_EVP_CipherFinal(ctx, out, outl); + } + else { + return WOLFSSL_FAILURE; + } +} + + +WOLFSSL_API int wolfSSL_EVP_DigestInit_ex(WOLFSSL_EVP_MD_CTX* ctx, + const WOLFSSL_EVP_MD* type, + WOLFSSL_ENGINE *impl) +{ + (void) impl; + WOLFSSL_ENTER("wolfSSL_EVP_DigestInit_ex"); + return wolfSSL_EVP_DigestInit(ctx, type); +} + +#ifdef DEBUG_WOLFSSL_EVP +#define PRINT_BUF(b, sz) { int _i; for(_i=0; _i<(sz); _i++) { \ + printf("%02x(%c),", (b)[_i], (b)[_i]); if ((_i+1)%8==0)printf("\n");}} +#else +#define PRINT_BUF(b, sz) +#endif + +static int fillBuff(WOLFSSL_EVP_CIPHER_CTX *ctx, const unsigned char *in, int sz) +{ + int fill; + + if (sz > 0) { + if ((sz+ctx->bufUsed) > ctx->block_size) { + fill = ctx->block_size - ctx->bufUsed; + } else { + fill = sz; + } + XMEMCPY(&(ctx->buf[ctx->bufUsed]), in, fill); + ctx->bufUsed += fill; + return fill; + } else return 0; +} + +static int evpCipherBlock(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, + const unsigned char *in, int inl) +{ + int ret = 0; + + switch (ctx->cipherType) { + #if !defined(NO_AES) && defined(HAVE_AES_CBC) + case AES_128_CBC_TYPE: + case AES_192_CBC_TYPE: + case AES_256_CBC_TYPE: + if (ctx->enc) + ret = wc_AesCbcEncrypt(&ctx->cipher.aes, out, in, inl); + else + ret = wc_AesCbcDecrypt(&ctx->cipher.aes, out, in, inl); + break; + #endif + #if !defined(NO_AES) && defined(WOLFSSL_AES_COUNTER) + case AES_128_CTR_TYPE: + case AES_192_CTR_TYPE: + case AES_256_CTR_TYPE: + ret = wc_AesCtrEncrypt(&ctx->cipher.aes, out, in, inl); + break; + #endif + #if !defined(NO_AES) && defined(HAVE_AES_ECB) + case AES_128_ECB_TYPE: + case AES_192_ECB_TYPE: + case AES_256_ECB_TYPE: + if (ctx->enc) + ret = wc_AesEcbEncrypt(&ctx->cipher.aes, out, in, inl); + else + ret = wc_AesEcbDecrypt(&ctx->cipher.aes, out, in, inl); + break; + #endif + #ifndef NO_DES3 + case DES_CBC_TYPE: + if (ctx->enc) + ret = wc_Des_CbcEncrypt(&ctx->cipher.des, out, in, inl); + else + ret = wc_Des_CbcDecrypt(&ctx->cipher.des, out, in, inl); + break; + case DES_EDE3_CBC_TYPE: + if (ctx->enc) + ret = wc_Des3_CbcEncrypt(&ctx->cipher.des3, out, in, inl); + else + ret = wc_Des3_CbcDecrypt(&ctx->cipher.des3, out, in, inl); + break; + #if defined(WOLFSSL_DES_ECB) + case DES_ECB_TYPE: + ret = wc_Des_EcbEncrypt(&ctx->cipher.des, out, in, inl); + break; + case DES_EDE3_ECB_TYPE: + ret = wc_Des3_EcbEncrypt(&ctx->cipher.des3, out, in, inl); + break; + #endif + #endif + #ifndef NO_RC4 + case ARC4_TYPE: + wc_Arc4Process(&ctx->cipher.arc4, out, in, inl); + break; + #endif + default: + return WOLFSSL_FAILURE; + } + + if (ret != 0) + return WOLFSSL_FAILURE; /* failure */ + + (void)in; + (void)inl; + (void)out; + + return WOLFSSL_SUCCESS; /* success */ +} + +WOLFSSL_API int wolfSSL_EVP_CipherUpdate(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, int *outl, + const unsigned char *in, int inl) +{ + int blocks; + int fill; + + if ((ctx == NULL) || (inl < 0) || + (outl == NULL)|| (out == NULL) || (in == NULL)) return BAD_FUNC_ARG; + WOLFSSL_ENTER("wolfSSL_EVP_CipherUpdate"); + + *outl = 0; + if (inl == 0) return WOLFSSL_SUCCESS; + + if (ctx->bufUsed > 0) { /* concatinate them if there is anything */ + fill = fillBuff(ctx, in, inl); + inl -= fill; + in += fill; + } + if ((ctx->enc == 0)&& (ctx->lastUsed == 1)) { + PRINT_BUF(ctx->lastBlock, ctx->block_size); + XMEMCPY(out, ctx->lastBlock, ctx->block_size); + *outl+= ctx->block_size; + out += ctx->block_size; + } + if (ctx->bufUsed == ctx->block_size) { + /* the buff is full, flash out */ + PRINT_BUF(ctx->buf, ctx->block_size); + if (evpCipherBlock(ctx, out, ctx->buf, ctx->block_size) == 0) + return WOLFSSL_FAILURE; + PRINT_BUF(out, ctx->block_size); + if (ctx->enc == 0) { + ctx->lastUsed = 1; + XMEMCPY(ctx->lastBlock, out, ctx->block_size); + } else { + *outl+= ctx->block_size; + out += ctx->block_size; + } + ctx->bufUsed = 0; + } + + blocks = inl / ctx->block_size; + if (blocks > 0) { + /* process blocks */ + if (evpCipherBlock(ctx, out, in, blocks * ctx->block_size) == 0) + return WOLFSSL_FAILURE; + PRINT_BUF(in, ctx->block_size*blocks); + PRINT_BUF(out,ctx->block_size*blocks); + inl -= ctx->block_size * blocks; + in += ctx->block_size * blocks; + if (ctx->enc == 0) { + if ((ctx->flags & WOLFSSL_EVP_CIPH_NO_PADDING) || + (ctx->block_size == 1)) { + ctx->lastUsed = 0; + *outl+= ctx->block_size * blocks; + } else { + if (inl == 0) { + ctx->lastUsed = 1; + blocks = blocks - 1; /* save last block to check padding in + * EVP_CipherFinal call */ + XMEMCPY(ctx->lastBlock, &out[ctx->block_size * blocks], + ctx->block_size); + } + *outl+= ctx->block_size * blocks; + } + } else { + *outl+= ctx->block_size * blocks; + } + } + if (inl > 0) { + /* put fraction into buff */ + fillBuff(ctx, in, inl); + /* no increase of outl */ + } + + (void)out; /* silence warning in case not read */ + + return WOLFSSL_SUCCESS; +} + +static void padBlock(WOLFSSL_EVP_CIPHER_CTX *ctx) +{ + int i; + for (i = ctx->bufUsed; i < ctx->block_size; i++) + ctx->buf[i] = (byte)(ctx->block_size - ctx->bufUsed); +} + +static int checkPad(WOLFSSL_EVP_CIPHER_CTX *ctx, unsigned char *buff) +{ + int i; + int n; + n = buff[ctx->block_size-1]; + if (n > ctx->block_size) return -1; + for (i = 0; i < n; i++) { + if (buff[ctx->block_size-i-1] != n) + return -1; + } + return ctx->block_size - n; +} + +WOLFSSL_API int wolfSSL_EVP_CipherFinal(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, int *outl) +{ + int fl; + if (ctx == NULL || out == NULL || outl == NULL) + return BAD_FUNC_ARG; + + WOLFSSL_ENTER("wolfSSL_EVP_CipherFinal"); + if (ctx->flags & WOLFSSL_EVP_CIPH_NO_PADDING) { + if (ctx->bufUsed != 0) return WOLFSSL_FAILURE; + *outl = 0; + return WOLFSSL_SUCCESS; + } + if (ctx->enc) { + if (ctx->block_size == 1) { + *outl = 0; + return WOLFSSL_SUCCESS; + } + if ((ctx->bufUsed >= 0) && (ctx->block_size != 1)) { + padBlock(ctx); + PRINT_BUF(ctx->buf, ctx->block_size); + if (evpCipherBlock(ctx, out, ctx->buf, ctx->block_size) == 0) + return WOLFSSL_FAILURE; + + PRINT_BUF(out, ctx->block_size); + *outl = ctx->block_size; + } + } else { + if (ctx->block_size == 1) { + *outl = 0; + return WOLFSSL_SUCCESS; + } + if ((ctx->bufUsed % ctx->block_size) != 0) { + *outl = 0; + /* not enough padding for decrypt */ + return WOLFSSL_FAILURE; + } + if (ctx->lastUsed) { + PRINT_BUF(ctx->lastBlock, ctx->block_size); + if ((fl = checkPad(ctx, ctx->lastBlock)) >= 0) { + XMEMCPY(out, ctx->lastBlock, fl); + *outl = fl; + } + else { + return WOLFSSL_FAILURE; + } + } + /* return error in cases where the block length is incorrect */ + if (ctx->lastUsed == 0 && ctx->bufUsed == 0) { + return WOLFSSL_FAILURE; + } + } + return WOLFSSL_SUCCESS; +} + + +#ifdef WOLFSSL_EVP_DECRYPT_LEGACY +/* This is a version of DecryptFinal to work with data encrypted with + * wolfSSL_EVP_EncryptFinal() with the broken padding. (pre-v3.12.0) + * Only call this after wolfSSL_EVP_CipherFinal() fails on a decrypt. + * Note, you don't know if the padding is good or bad with the old + * encrypt, but it is likely to be or bad. It will update the output + * length with the block_size so the last block is still captured. */ +WOLFSSL_API int wolfSSL_EVP_DecryptFinal_legacy(WOLFSSL_EVP_CIPHER_CTX *ctx, + unsigned char *out, int *outl) +{ + int fl; + if (ctx == NULL || out == NULL || outl == NULL) + return BAD_FUNC_ARG; + + WOLFSSL_ENTER("wolfSSL_EVP_DecryptFinal_legacy"); + if (ctx->block_size == 1) { + *outl = 0; + return WOLFSSL_SUCCESS; + } + if ((ctx->bufUsed % ctx->block_size) != 0) { + *outl = 0; + /* not enough padding for decrypt */ + return WOLFSSL_FAILURE; + } + /* The original behavior of CipherFinal() was like it is now, + * but checkPad would return 0 in case of a bad pad. It would + * treat the pad as 0, and leave the data in the output buffer, + * and not try to copy anything. This converts checkPad's -1 error + * code to block_size. + */ + if (ctx->lastUsed) { + PRINT_BUF(ctx->lastBlock, ctx->block_size); + if ((fl = checkPad(ctx, ctx->lastBlock)) < 0) { + fl = ctx->block_size; + } + else { + XMEMCPY(out, ctx->lastBlock, fl); + } + *outl = fl; + } + /* return error in cases where the block length is incorrect */ + if (ctx->lastUsed == 0 && ctx->bufUsed == 0) { + return WOLFSSL_FAILURE; + } + + return WOLFSSL_SUCCESS; +} +#endif + + +WOLFSSL_API int wolfSSL_EVP_CIPHER_CTX_block_size(const WOLFSSL_EVP_CIPHER_CTX *ctx) +{ + if (ctx == NULL) return BAD_FUNC_ARG; + switch (ctx->cipherType) { +#if !defined(NO_AES) || !defined(NO_DES3) +#if !defined(NO_AES) && defined(HAVE_AES_CBC) + case AES_128_CBC_TYPE: + case AES_192_CBC_TYPE: + case AES_256_CBC_TYPE: +#endif +#if !defined(NO_AES) && defined(WOLFSSL_AES_COUNTER) + case AES_128_CTR_TYPE: + case AES_192_CTR_TYPE: + case AES_256_CTR_TYPE: +#endif +#if !defined(NO_AES) + case AES_128_ECB_TYPE: + case AES_192_ECB_TYPE: + case AES_256_ECB_TYPE: +#endif +#ifndef NO_DES3 + case DES_CBC_TYPE: + case DES_ECB_TYPE: + case DES_EDE3_CBC_TYPE: + case DES_EDE3_ECB_TYPE: +#endif + return ctx->block_size; +#endif /* !NO_AES || !NO_DES3 */ + default: + return 0; + } +} + +static unsigned int cipherType(const WOLFSSL_EVP_CIPHER *cipher) +{ + if (cipher == NULL) return 0; /* dummy for #ifdef */ + #ifndef NO_DES3 + else if (XSTRNCMP(cipher, EVP_DES_CBC, EVP_DES_SIZE) == 0) + return DES_CBC_TYPE; + else if (XSTRNCMP(cipher, EVP_DES_EDE3_CBC, EVP_DES_EDE3_SIZE) == 0) + return DES_EDE3_CBC_TYPE; + #if !defined(NO_DES3) + else if (XSTRNCMP(cipher, EVP_DES_ECB, EVP_DES_SIZE) == 0) + return DES_ECB_TYPE; + else if (XSTRNCMP(cipher, EVP_DES_EDE3_ECB, EVP_DES_EDE3_SIZE) == 0) + return DES_EDE3_ECB_TYPE; + #endif /* NO_DES3 && HAVE_AES_ECB */ + #endif + + #if !defined(NO_AES) && defined(HAVE_AES_CBC) + #ifdef WOLFSSL_AES_128 + else if (XSTRNCMP(cipher, EVP_AES_128_CBC, EVP_AES_SIZE) == 0) + return AES_128_CBC_TYPE; + #endif + #ifdef WOLFSSL_AES_192 + else if (XSTRNCMP(cipher, EVP_AES_192_CBC, EVP_AES_SIZE) == 0) + return AES_192_CBC_TYPE; + #endif + #ifdef WOLFSSL_AES_256 + else if (XSTRNCMP(cipher, EVP_AES_256_CBC, EVP_AES_SIZE) == 0) + return AES_256_CBC_TYPE; + #endif + #endif /* !NO_AES && HAVE_AES_CBC */ + #if !defined(NO_AES) && defined(WOLFSSL_AES_COUNTER) + #ifdef WOLFSSL_AES_128 + else if (XSTRNCMP(cipher, EVP_AES_128_CTR, EVP_AES_SIZE) == 0) + return AES_128_CTR_TYPE; + #endif + #ifdef WOLFSSL_AES_192 + else if (XSTRNCMP(cipher, EVP_AES_192_CTR, EVP_AES_SIZE) == 0) + return AES_192_CTR_TYPE; + #endif + #ifdef WOLFSSL_AES_256 + else if (XSTRNCMP(cipher, EVP_AES_256_CTR, EVP_AES_SIZE) == 0) + return AES_256_CTR_TYPE; + #endif + #endif /* !NO_AES && HAVE_AES_CBC */ + #if !defined(NO_AES) && defined(HAVE_AES_ECB) + #ifdef WOLFSSL_AES_128 + else if (XSTRNCMP(cipher, EVP_AES_128_ECB, EVP_AES_SIZE) == 0) + return AES_128_ECB_TYPE; + #endif + #ifdef WOLFSSL_AES_192 + else if (XSTRNCMP(cipher, EVP_AES_192_ECB, EVP_AES_SIZE) == 0) + return AES_192_ECB_TYPE; + #endif + #ifdef WOLFSSL_AES_256 + else if (XSTRNCMP(cipher, EVP_AES_256_ECB, EVP_AES_SIZE) == 0) + return AES_256_ECB_TYPE; + #endif + #endif /* !NO_AES && HAVE_AES_CBC */ + else return 0; +} + +WOLFSSL_API int wolfSSL_EVP_CIPHER_block_size(const WOLFSSL_EVP_CIPHER *cipher) +{ + if (cipher == NULL) return BAD_FUNC_ARG; + switch (cipherType(cipher)) { + #if !defined(NO_AES) && defined(HAVE_AES_CBC) + case AES_128_CBC_TYPE: + case AES_192_CBC_TYPE: + case AES_256_CBC_TYPE: + return AES_BLOCK_SIZE; + #endif + #if !defined(NO_AES) && defined(WOLFSSL_AES_COUNTER) + case AES_128_CTR_TYPE: + case AES_192_CTR_TYPE: + case AES_256_CTR_TYPE: + return AES_BLOCK_SIZE; + #endif + #if !defined(NO_AES) && defined(HAVE_AES_ECB) + case AES_128_ECB_TYPE: + case AES_192_ECB_TYPE: + case AES_256_ECB_TYPE: + return AES_BLOCK_SIZE; + #endif + #ifndef NO_DES3 + case DES_CBC_TYPE: return 8; + case DES_EDE3_CBC_TYPE: return 8; + case DES_ECB_TYPE: return 8; + case DES_EDE3_ECB_TYPE: return 8; + #endif + default: + return 0; + } +} + +unsigned long WOLFSSL_CIPHER_mode(const WOLFSSL_EVP_CIPHER *cipher) +{ + switch (cipherType(cipher)) { + #if !defined(NO_AES) && defined(HAVE_AES_CBC) + case AES_128_CBC_TYPE: + case AES_192_CBC_TYPE: + case AES_256_CBC_TYPE: + return WOLFSSL_EVP_CIPH_CBC_MODE; + #endif + #if !defined(NO_AES) && defined(WOLFSSL_AES_COUNTER) + case AES_128_CTR_TYPE: + case AES_192_CTR_TYPE: + case AES_256_CTR_TYPE: + return WOLFSSL_EVP_CIPH_CTR_MODE; + #endif + #if !defined(NO_AES) + case AES_128_ECB_TYPE: + case AES_192_ECB_TYPE: + case AES_256_ECB_TYPE: + return WOLFSSL_EVP_CIPH_ECB_MODE; + #endif + #ifndef NO_DES3 + case DES_CBC_TYPE: + case DES_EDE3_CBC_TYPE: + return WOLFSSL_EVP_CIPH_CBC_MODE; + case DES_ECB_TYPE: + case DES_EDE3_ECB_TYPE: + return WOLFSSL_EVP_CIPH_ECB_MODE; + #endif + #ifndef NO_RC4 + case ARC4_TYPE: + return EVP_CIPH_STREAM_CIPHER; + #endif + default: + return 0; + } +} + +WOLFSSL_API unsigned long WOLFSSL_EVP_CIPHER_mode(const WOLFSSL_EVP_CIPHER *cipher) +{ + if (cipher == NULL) return 0; + return WOLFSSL_CIPHER_mode(cipher); +} + +WOLFSSL_API void wolfSSL_EVP_CIPHER_CTX_set_flags(WOLFSSL_EVP_CIPHER_CTX *ctx, int flags) +{ + if (ctx != NULL) { + ctx->flags |= flags; + } +} + +WOLFSSL_API void wolfSSL_EVP_CIPHER_CTX_clear_flags(WOLFSSL_EVP_CIPHER_CTX *ctx, int flags) +{ + if (ctx != NULL) { + ctx->flags &= ~flags; + } +} + +WOLFSSL_API unsigned long wolfSSL_EVP_CIPHER_flags(const WOLFSSL_EVP_CIPHER *cipher) +{ + if (cipher == NULL) return 0; + return WOLFSSL_CIPHER_mode(cipher); +} + +WOLFSSL_API int wolfSSL_EVP_CIPHER_CTX_set_padding(WOLFSSL_EVP_CIPHER_CTX *ctx, int padding) +{ + if (ctx == NULL) return BAD_FUNC_ARG; + if (padding) { + ctx->flags &= ~WOLFSSL_EVP_CIPH_NO_PADDING; + } + else { + ctx->flags |= WOLFSSL_EVP_CIPH_NO_PADDING; + } + return 1; +} + +WOLFSSL_API int wolfSSL_EVP_add_digest(const WOLFSSL_EVP_MD *digest) +{ + (void)digest; + /* nothing to do */ + return 0; +} + + +/* Frees the WOLFSSL_EVP_PKEY_CTX passed in. + * + * return WOLFSSL_SUCCESS on success + */ +WOLFSSL_API int wolfSSL_EVP_PKEY_CTX_free(WOLFSSL_EVP_PKEY_CTX *ctx) +{ + if (ctx == NULL) return 0; + WOLFSSL_ENTER("EVP_PKEY_CTX_free"); + XFREE(ctx, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + return WOLFSSL_SUCCESS; +} + + +/* Creates a new WOLFSSL_EVP_PKEY_CTX structure. + * + * pkey key structure to use with new WOLFSSL_EVP_PEKY_CTX + * e engine to use. It should be NULL at this time. + * + * return the new structure on success and NULL if failed. + */ +WOLFSSL_API WOLFSSL_EVP_PKEY_CTX *wolfSSL_EVP_PKEY_CTX_new(WOLFSSL_EVP_PKEY *pkey, WOLFSSL_ENGINE *e) +{ + WOLFSSL_EVP_PKEY_CTX* ctx; + + if (pkey == NULL) return 0; + if (e != NULL) return 0; + WOLFSSL_ENTER("EVP_PKEY_CTX_new"); + + ctx = (WOLFSSL_EVP_PKEY_CTX*)XMALLOC(sizeof(WOLFSSL_EVP_PKEY_CTX), NULL, + DYNAMIC_TYPE_PUBLIC_KEY); + if (ctx == NULL) return NULL; + XMEMSET(ctx, 0, sizeof(WOLFSSL_EVP_PKEY_CTX)); + ctx->pkey = pkey; +#if !defined(NO_RSA) && !defined(HAVE_USER_RSA) + ctx->padding = RSA_PKCS1_PADDING; +#endif + + return ctx; +} + + +/* Sets the type of RSA padding to use. + * + * ctx structure to set padding in. + * padding RSA padding type + * + * returns WOLFSSL_SUCCESS on success. + */ +WOLFSSL_API int wolfSSL_EVP_PKEY_CTX_set_rsa_padding(WOLFSSL_EVP_PKEY_CTX *ctx, int padding) +{ + if (ctx == NULL) return 0; + WOLFSSL_ENTER("EVP_PKEY_CTX_set_rsa_padding"); + ctx->padding = padding; + return WOLFSSL_SUCCESS; +} + + +/* Uses the WOLFSSL_EVP_PKEY_CTX to decrypt a buffer. + * + * ctx structure to decrypt with + * out buffer to hold the results + * outlen initially holds size of out buffer and gets set to decrypt result size + * in buffer decrypt + * inlen length of in buffer + * + * returns WOLFSSL_SUCCESS on success. + */ +WOLFSSL_API int wolfSSL_EVP_PKEY_decrypt(WOLFSSL_EVP_PKEY_CTX *ctx, + unsigned char *out, size_t *outlen, + const unsigned char *in, size_t inlen) +{ + int len = 0; + + if (ctx == NULL) return 0; + WOLFSSL_ENTER("EVP_PKEY_decrypt"); + + (void)out; + (void)outlen; + (void)in; + (void)inlen; + (void)len; + + switch (ctx->pkey->type) { +#if !defined(NO_RSA) && !defined(HAVE_USER_RSA) + case EVP_PKEY_RSA: + len = wolfSSL_RSA_private_decrypt((int)inlen, (unsigned char*)in, out, + ctx->pkey->rsa, ctx->padding); + if (len < 0) break; + else { + *outlen = len; + return WOLFSSL_SUCCESS; + } +#endif /* NO_RSA */ + + case EVP_PKEY_EC: + WOLFSSL_MSG("not implemented"); + FALL_THROUGH; + default: + break; + } + return WOLFSSL_FAILURE; +} + + +/* Initialize a WOLFSSL_EVP_PKEY_CTX structure for decryption + * + * ctx WOLFSSL_EVP_PKEY_CTX structure to use with decryption + * + * Returns WOLFSSL_FAILURE on failure and WOLFSSL_SUCCESS on success + */ +WOLFSSL_API int wolfSSL_EVP_PKEY_decrypt_init(WOLFSSL_EVP_PKEY_CTX *ctx) +{ + if (ctx == NULL) return WOLFSSL_FAILURE; + WOLFSSL_ENTER("EVP_PKEY_decrypt_init"); + switch (ctx->pkey->type) { + case EVP_PKEY_RSA: + ctx->op = EVP_PKEY_OP_DECRYPT; + return WOLFSSL_SUCCESS; + case EVP_PKEY_EC: + WOLFSSL_MSG("not implemented"); + FALL_THROUGH; + default: + break; + } + return WOLFSSL_FAILURE; +} + + +/* Use a WOLFSSL_EVP_PKEY_CTX structure to encrypt data + * + * ctx WOLFSSL_EVP_PKEY_CTX structure to use with encryption + * out buffer to hold encrypted data + * outlen length of out buffer + * in data to be encrypted + * inlen length of in buffer + * + * Returns WOLFSSL_FAILURE on failure and WOLFSSL_SUCCESS on success + */ +WOLFSSL_API int wolfSSL_EVP_PKEY_encrypt(WOLFSSL_EVP_PKEY_CTX *ctx, + unsigned char *out, size_t *outlen, + const unsigned char *in, size_t inlen) +{ + int len = 0; + if (ctx == NULL) return WOLFSSL_FAILURE; + WOLFSSL_ENTER("EVP_PKEY_encrypt"); + if (ctx->op != EVP_PKEY_OP_ENCRYPT) return WOLFSSL_FAILURE; + + (void)out; + (void)outlen; + (void)in; + (void)inlen; + (void)len; + switch (ctx->pkey->type) { +#if !defined(NO_RSA) && !defined(HAVE_USER_RSA) + case EVP_PKEY_RSA: + len = wolfSSL_RSA_public_encrypt((int)inlen, (unsigned char *)in, out, + ctx->pkey->rsa, ctx->padding); + if (len < 0) + break; + else { + *outlen = len; + return WOLFSSL_SUCCESS; + } +#endif /* NO_RSA */ + + case EVP_PKEY_EC: + WOLFSSL_MSG("not implemented"); + FALL_THROUGH; + default: + break; + } + return WOLFSSL_FAILURE; +} + + +/* Initialize a WOLFSSL_EVP_PKEY_CTX structure to encrypt data + * + * ctx WOLFSSL_EVP_PKEY_CTX structure to use with encryption + * + * Returns WOLFSSL_FAILURE on failure and WOLFSSL_SUCCESS on success + */ +WOLFSSL_API int wolfSSL_EVP_PKEY_encrypt_init(WOLFSSL_EVP_PKEY_CTX *ctx) +{ + if (ctx == NULL) return WOLFSSL_FAILURE; + WOLFSSL_ENTER("EVP_PKEY_encrypt_init"); + + switch (ctx->pkey->type) { + case EVP_PKEY_RSA: + ctx->op = EVP_PKEY_OP_ENCRYPT; + return WOLFSSL_SUCCESS; + case EVP_PKEY_EC: + WOLFSSL_MSG("not implemented"); + FALL_THROUGH; + default: + break; + } + return WOLFSSL_FAILURE; +} + + +/* Get the size in bits for WOLFSSL_EVP_PKEY key + * + * pkey WOLFSSL_EVP_PKEY structure to get key size of + * + * returns the size in bits of key on success + */ +WOLFSSL_API int wolfSSL_EVP_PKEY_bits(const WOLFSSL_EVP_PKEY *pkey) +{ + int bytes; + + if (pkey == NULL) return 0; + WOLFSSL_ENTER("EVP_PKEY_bits"); + if ((bytes = wolfSSL_EVP_PKEY_size((WOLFSSL_EVP_PKEY*)pkey)) ==0) return 0; + return bytes*8; +} + + +/* Get the size in bytes for WOLFSSL_EVP_PKEY key + * + * pkey WOLFSSL_EVP_PKEY structure to get key size of + * + * returns the size of a key on success which is the maximum size of a + * signature + */ +WOLFSSL_API int wolfSSL_EVP_PKEY_size(WOLFSSL_EVP_PKEY *pkey) +{ + if (pkey == NULL) return 0; + WOLFSSL_ENTER("EVP_PKEY_size"); + + switch (pkey->type) { +#if !defined(NO_RSA) && !defined(HAVE_USER_RSA) + case EVP_PKEY_RSA: + return (int)wolfSSL_RSA_size((const WOLFSSL_RSA*)(pkey->rsa)); +#endif /* NO_RSA */ + +#ifdef HAVE_ECC + case EVP_PKEY_EC: + if (pkey->ecc == NULL || pkey->ecc->internal == NULL) { + WOLFSSL_MSG("No ECC key has been set"); + break; + } + return wc_ecc_size((ecc_key*)(pkey->ecc->internal)); +#endif /* HAVE_ECC */ + + default: + break; + } + return 0; +} + + +/* Initialize structure for signing + * + * ctx WOLFSSL_EVP_MD_CTX structure to initialize + * type is the type of message digest to use + * + * returns WOLFSSL_SUCCESS on success + */ +WOLFSSL_API int wolfSSL_EVP_SignInit(WOLFSSL_EVP_MD_CTX *ctx, const WOLFSSL_EVP_MD *type) +{ + if (ctx == NULL) return WOLFSSL_FAILURE; + WOLFSSL_ENTER("EVP_SignInit"); + return wolfSSL_EVP_DigestInit(ctx,type); +} + + +/* Update structure with data for signing + * + * ctx WOLFSSL_EVP_MD_CTX structure to update + * data buffer holding data to update with for sign + * len length of data buffer + * + * returns WOLFSSL_SUCCESS on success + */ +WOLFSSL_API int wolfSSL_EVP_SignUpdate(WOLFSSL_EVP_MD_CTX *ctx, const void *data, size_t len) +{ + if (ctx == NULL) return 0; + WOLFSSL_ENTER("EVP_SignUpdate("); + return wolfSSL_EVP_DigestUpdate(ctx, data, len); +} + +/* macro gaurd because currently only used with RSA */ +#if !defined(NO_RSA) && !defined(HAVE_USER_RSA) +/* Helper function for getting the NID value from md + * + * returns the NID value associated with md on success */ +static int md2nid(const unsigned char md) +{ + const char * d; + d = (const char *)wolfSSL_EVP_get_md(md); + if (XSTRNCMP(d, "SHA", 3) == 0) { + if (XSTRLEN(d) > 3) { + if (XSTRNCMP(d, "SHA256", 6) == 0) { + return NID_sha256; + } + if (XSTRNCMP(d, "SHA384", 6) == 0) { + return NID_sha384; + } + if (XSTRNCMP(d, "SHA512", 6) == 0) { + return NID_sha512; + } + WOLFSSL_MSG("Unknown SHA type"); + return 0; + } + else { + return NID_sha1; + } + } + if (XSTRNCMP(d, "MD5", 3) == 0) + return NID_md5; + return 0; +} +#endif /* NO_RSA */ + +/* Finalize structure for signing + * + * ctx WOLFSSL_EVP_MD_CTX structure to finalize + * sigret buffer to hold resulting signature + * siglen length of sigret buffer + * pkey key to sign with + * + * returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure + */ +WOLFSSL_API int wolfSSL_EVP_SignFinal(WOLFSSL_EVP_MD_CTX *ctx, unsigned char *sigret, + unsigned int *siglen, WOLFSSL_EVP_PKEY *pkey) +{ + unsigned int mdsize; + unsigned char md[WC_MAX_DIGEST_SIZE]; + int ret; + if (ctx == NULL) return WOLFSSL_FAILURE; + WOLFSSL_ENTER("EVP_SignFinal"); + + ret = wolfSSL_EVP_DigestFinal(ctx, md, &mdsize); + if (ret <= 0) return ret; + + (void)sigret; + (void)siglen; + + switch (pkey->type) { +#if !defined(NO_RSA) && !defined(HAVE_USER_RSA) + case EVP_PKEY_RSA: { + int nid = md2nid(ctx->macType); + if (nid < 0) break; + return wolfSSL_RSA_sign(nid, md, mdsize, sigret, + siglen, pkey->rsa); + } +#endif /* NO_RSA */ + + case EVP_PKEY_DSA: + case EVP_PKEY_EC: + WOLFSSL_MSG("not implemented"); + FALL_THROUGH; + default: + break; + } + return WOLFSSL_FAILURE; +} + + +/* Initialize structure for verifying signature + * + * ctx WOLFSSL_EVP_MD_CTX structure to initialize + * type is the type of message digest to use + * + * returns WOLFSSL_SUCCESS on success + */ +WOLFSSL_API int wolfSSL_EVP_VerifyInit(WOLFSSL_EVP_MD_CTX *ctx, const WOLFSSL_EVP_MD *type) +{ + if (ctx == NULL) return WOLFSSL_FAILURE; + WOLFSSL_ENTER("EVP_VerifyInit"); + return wolfSSL_EVP_DigestInit(ctx,type); +} + + +/* Update structure for verifying signature + * + * ctx WOLFSSL_EVP_MD_CTX structure to update + * data buffer holding data to update with for verify + * len length of data buffer + * + * returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure + */ +WOLFSSL_API int wolfSSL_EVP_VerifyUpdate(WOLFSSL_EVP_MD_CTX *ctx, const void *data, size_t len) +{ + if (ctx == NULL) return WOLFSSL_FAILURE; + WOLFSSL_ENTER("EVP_VerifyUpdate"); + return wolfSSL_EVP_DigestUpdate(ctx, data, len); +} + + +/* Finalize structure for verifying signature + * + * ctx WOLFSSL_EVP_MD_CTX structure to finalize + * sig buffer holding signature + * siglen length of sig buffer + * pkey key to verify with + * + * returns WOLFSSL_SUCCESS on success and WOLFSSL_FAILURE on failure + */ +WOLFSSL_API int wolfSSL_EVP_VerifyFinal(WOLFSSL_EVP_MD_CTX *ctx, + unsigned char*sig, unsigned int siglen, WOLFSSL_EVP_PKEY *pkey) +{ + int ret; + unsigned char md[WC_MAX_DIGEST_SIZE]; + unsigned int mdsize; + + if (ctx == NULL) return WOLFSSL_FAILURE; + WOLFSSL_ENTER("EVP_VerifyFinal"); + ret = wolfSSL_EVP_DigestFinal(ctx, md, &mdsize); + if (ret <= 0) return ret; + + (void)sig; + (void)siglen; + + switch (pkey->type) { +#if !defined(NO_RSA) && !defined(HAVE_USER_RSA) + case EVP_PKEY_RSA: { + int nid = md2nid(ctx->macType); + if (nid < 0) break; + return wolfSSL_RSA_verify(nid, md, mdsize, sig, + (unsigned int)siglen, pkey->rsa); + } +#endif /* NO_RSA */ + + case EVP_PKEY_DSA: + case EVP_PKEY_EC: + WOLFSSL_MSG("not implemented"); + FALL_THROUGH; + default: + break; + } + return WOLFSSL_FAILURE; +} + +WOLFSSL_API int wolfSSL_EVP_add_cipher(const WOLFSSL_EVP_CIPHER *cipher) +{ + (void)cipher; + /* nothing to do */ + return 0; +} + + +WOLFSSL_EVP_PKEY* wolfSSL_EVP_PKEY_new_mac_key(int type, ENGINE* e, + const unsigned char* key, int keylen) +{ + WOLFSSL_EVP_PKEY* pkey; + + (void)e; + + if (type != EVP_PKEY_HMAC || (key == NULL && keylen != 0)) + return NULL; + + pkey = wolfSSL_PKEY_new(); + if (pkey != NULL) { + pkey->pkey.ptr = (char*)XMALLOC(keylen, NULL, DYNAMIC_TYPE_PUBLIC_KEY); + if (pkey->pkey.ptr == NULL && keylen > 0) { + wolfSSL_EVP_PKEY_free(pkey); + pkey = NULL; + } + else { + XMEMCPY(pkey->pkey.ptr, key, keylen); + pkey->pkey_sz = keylen; + pkey->type = pkey->save_type = type; + } + } + + return pkey; +} + + +const unsigned char* wolfSSL_EVP_PKEY_get0_hmac(const WOLFSSL_EVP_PKEY* pkey, + size_t* len) +{ + if (pkey == NULL || len == NULL) + return NULL; + + *len = (size_t)pkey->pkey_sz; + + return (const unsigned char*)pkey->pkey.ptr; +} + + +/* Initialize an EVP_DigestSign/Verify operation. + * Initialize a digest for RSA and ECC keys, or HMAC for HMAC key. + */ +static int wolfSSL_evp_digest_pk_init(WOLFSSL_EVP_MD_CTX *ctx, + WOLFSSL_EVP_PKEY_CTX **pctx, + const WOLFSSL_EVP_MD *type, + WOLFSSL_ENGINE *e, + WOLFSSL_EVP_PKEY *pkey) +{ + if (pkey->type == EVP_PKEY_HMAC) { + int hashType; + const unsigned char* key; + size_t keySz; + + if (XSTRNCMP(type, "SHA256", 6) == 0) { + hashType = WC_SHA256; + } + #ifdef WOLFSSL_SHA224 + else if (XSTRNCMP(type, "SHA224", 6) == 0) { + hashType = WC_SHA224; + } + #endif + #ifdef WOLFSSL_SHA384 + else if (XSTRNCMP(type, "SHA384", 6) == 0) { + hashType = WC_SHA384; + } + #endif + #ifdef WOLFSSL_SHA512 + else if (XSTRNCMP(type, "SHA512", 6) == 0) { + hashType = WC_SHA512; + } + #endif + #ifndef NO_MD5 + else if (XSTRNCMP(type, "MD5", 3) == 0) { + hashType = WC_MD5; + } + #endif + #ifndef NO_SHA + /* has to be last since would pick or 224, 256, 384, or 512 too */ + else if (XSTRNCMP(type, "SHA", 3) == 0) { + hashType = WC_SHA; + } + #endif /* NO_SHA */ + else + return BAD_FUNC_ARG; + + key = wolfSSL_EVP_PKEY_get0_hmac(pkey, &keySz); + + if (wc_HmacInit(&ctx->hash.hmac, NULL, INVALID_DEVID) != 0) + return WOLFSSL_FAILURE; + + if (wc_HmacSetKey(&ctx->hash.hmac, hashType, key, (word32)keySz) != 0) + return WOLFSSL_FAILURE; + + ctx->macType = NID_hmac & 0xFF; + } + else { + int ret; + + if (ctx->pctx == NULL) + ctx->pctx = wolfSSL_EVP_PKEY_CTX_new(pkey, e); + if (ctx->pctx == NULL) + return WOLFSSL_FAILURE; + + ret = wolfSSL_EVP_DigestInit(ctx, type); + if (ret == WOLFSSL_SUCCESS && pctx != NULL) + *pctx = ctx->pctx; + return ret; + } + + return WOLFSSL_SUCCESS; +} + +/* Update an EVP_DigestSign/Verify operation. + * Update a digest for RSA and ECC keys, or HMAC for HMAC key. + */ +static int wolfssl_evp_digest_pk_update(WOLFSSL_EVP_MD_CTX *ctx, + const void *d, unsigned int cnt) +{ + if (ctx->pctx == NULL) { + if (ctx->macType != (NID_hmac & 0xFF)) + return WOLFSSL_FAILURE; + + if (wc_HmacUpdate(&ctx->hash.hmac, (const byte *)d, cnt) != 0) + return WOLFSSL_FAILURE; + + return WOLFSSL_SUCCESS; + } + else + return wolfSSL_EVP_DigestUpdate(ctx, d, cnt); +} + +/* Finalize an EVP_DigestSign/Verify operation - common part only. + * Finalize a digest for RSA and ECC keys, or HMAC for HMAC key. + * Copies the digest so that you can keep updating. + */ +static int wolfssl_evp_digest_pk_final(WOLFSSL_EVP_MD_CTX *ctx, + unsigned char *md, unsigned int* mdlen) +{ + int ret; + + if (ctx->pctx == NULL) { + Hmac hmacCopy; + + if (ctx->macType != (NID_hmac & 0xFF)) + return WOLFSSL_FAILURE; + + if (wolfSSL_HmacCopy(&hmacCopy, &ctx->hash.hmac) != WOLFSSL_SUCCESS) + return WOLFSSL_FAILURE; + ret = wc_HmacFinal(&hmacCopy, md) == 0; + wc_HmacFree(&hmacCopy); + return ret; + } + else { + WOLFSSL_EVP_MD_CTX ctxCopy; + + if (wolfSSL_EVP_MD_CTX_copy_ex(&ctxCopy, ctx) != WOLFSSL_SUCCESS) + return WOLFSSL_FAILURE; + + ret = wolfSSL_EVP_DigestFinal(&ctxCopy, md, mdlen); + wolfSSL_EVP_MD_CTX_cleanup(&ctxCopy); + return ret; + } +} + +/* Get the length of the mac based on the digest algorithm. */ +static int wolfssl_mac_len(unsigned char macType) +{ + int hashLen; + + switch (macType) { + #ifndef NO_MD5 + case WC_MD5: + hashLen = WC_MD5_DIGEST_SIZE; + break; + #endif /* !NO_MD5 */ + + #ifndef NO_SHA + case WC_SHA: + hashLen = WC_SHA_DIGEST_SIZE; + break; + #endif /* !NO_SHA */ + + #ifdef WOLFSSL_SHA224 + case WC_SHA224: + hashLen = WC_SHA224_DIGEST_SIZE; + break; + #endif /* WOLFSSL_SHA224 */ + + #ifndef NO_SHA256 + case WC_SHA256: + hashLen = WC_SHA256_DIGEST_SIZE; + break; + #endif /* !NO_SHA256 */ + + #ifdef WOLFSSL_SHA384 + case WC_SHA384: + hashLen = WC_SHA384_DIGEST_SIZE; + break; + #endif /* WOLFSSL_SHA384 */ + #ifdef WOLFSSL_SHA512 + case WC_SHA512: + hashLen = WC_SHA512_DIGEST_SIZE; + break; + #endif /* WOLFSSL_SHA512 */ + + #ifdef HAVE_BLAKE2 + case BLAKE2B_ID: + hashLen = BLAKE2B_OUTBYTES; + break; + #endif /* HAVE_BLAKE2 */ + + default: + hashLen = 0; + } + + return hashLen; +} + +int wolfSSL_EVP_DigestSignInit(WOLFSSL_EVP_MD_CTX *ctx, + WOLFSSL_EVP_PKEY_CTX **pctx, + const WOLFSSL_EVP_MD *type, + WOLFSSL_ENGINE *e, + WOLFSSL_EVP_PKEY *pkey) +{ + WOLFSSL_ENTER("EVP_DigestSignInit"); + + if (ctx == NULL || type == NULL || pkey == NULL) + return BAD_FUNC_ARG; + + return wolfSSL_evp_digest_pk_init(ctx, pctx, type, e, pkey); +} + + +int wolfSSL_EVP_DigestSignUpdate(WOLFSSL_EVP_MD_CTX *ctx, const void *d, + unsigned int cnt) +{ + WOLFSSL_ENTER("EVP_DigestSignUpdate"); + + if (ctx == NULL || d == NULL) + return BAD_FUNC_ARG; + + return wolfssl_evp_digest_pk_update(ctx, d, cnt); +} + +int wolfSSL_EVP_DigestSignFinal(WOLFSSL_EVP_MD_CTX *ctx, unsigned char *sig, + size_t *siglen) +{ + unsigned char digest[WC_MAX_DIGEST_SIZE]; + unsigned int hashLen; + int ret = WOLFSSL_FAILURE; + + WOLFSSL_ENTER("EVP_DigestSignFinal"); + + if (ctx == NULL || siglen == NULL) + return WOLFSSL_FAILURE; + + /* Return the maximum size of the signaure when sig is NULL. */ + if (ctx->pctx == NULL) { + if (ctx->macType != (NID_hmac & 0xFF)) + return WOLFSSL_FAILURE; + + hashLen = wolfssl_mac_len(ctx->hash.hmac.macType); + + if (sig == NULL) { + *siglen = hashLen; + return WOLFSSL_SUCCESS; + } + } +#if !defined(NO_RSA) && !defined(HAVE_USER_RSA) + else if (ctx->pctx->pkey->type == EVP_PKEY_RSA) { + if (sig == NULL) { + *siglen = wolfSSL_RSA_size(ctx->pctx->pkey->rsa); + return WOLFSSL_SUCCESS; + } + } +#endif +#ifdef HAVE_ECC + else if (ctx->pctx->pkey->type == EVP_PKEY_EC) { + if (sig == NULL) { + /* SEQ + INT + INT */ + *siglen = ecc_sets[ctx->pctx->pkey->ecc->group->curve_idx].size * 2 + + 8; + return WOLFSSL_SUCCESS; + } + } +#endif + + if (wolfssl_evp_digest_pk_final(ctx, digest, &hashLen) <= 0) + return WOLFSSL_FAILURE; + + if (ctx->pctx == NULL) { + /* Copy the HMAC result as signature. */ + if ((unsigned int)(*siglen) > hashLen) + *siglen = hashLen; + /* May be a truncated signature. */ + + XMEMCPY(sig, digest, *siglen); + ret = WOLFSSL_SUCCESS; + } + else { + /* Sign the digest. */ + switch (ctx->pctx->pkey->type) { + #if !defined(NO_RSA) && !defined(HAVE_USER_RSA) + case EVP_PKEY_RSA: { + unsigned int sigSz; + int nid = md2nid(ctx->macType); + if (nid < 0) + break; + ret = wolfSSL_RSA_sign(nid, digest, hashLen, sig, &sigSz, + ctx->pctx->pkey->rsa); + if (ret >= 0) + *siglen = sigSz; + break; + } + #endif /* NO_RSA */ + + #ifdef HAVE_ECC + case EVP_PKEY_EC: { + WOLFSSL_ECDSA_SIG *ecdsaSig; + ecdsaSig = wolfSSL_ECDSA_do_sign(digest, hashLen, + ctx->pctx->pkey->ecc); + if (ecdsaSig == NULL) + break; + *siglen = wolfSSL_i2d_ECDSA_SIG(ecdsaSig, &sig); + wolfSSL_ECDSA_SIG_free(ecdsaSig); + ret = WOLFSSL_SUCCESS; + break; + } + #endif + default: + break; + } + } + + ForceZero(digest, sizeof(digest)); + return ret; +} + +int wolfSSL_EVP_DigestVerifyInit(WOLFSSL_EVP_MD_CTX *ctx, + WOLFSSL_EVP_PKEY_CTX **pctx, + const WOLFSSL_EVP_MD *type, + WOLFSSL_ENGINE *e, + WOLFSSL_EVP_PKEY *pkey) +{ + WOLFSSL_ENTER("EVP_DigestVerifyInit"); + + if (ctx == NULL || type == NULL || pkey == NULL) + return BAD_FUNC_ARG; + + return wolfSSL_evp_digest_pk_init(ctx, pctx, type, e, pkey); +} + + +int wolfSSL_EVP_DigestVerifyUpdate(WOLFSSL_EVP_MD_CTX *ctx, const void *d, + size_t cnt) +{ + WOLFSSL_ENTER("EVP_DigestVerifyUpdate"); + + if (ctx == NULL || d == NULL) + return BAD_FUNC_ARG; + + return wolfssl_evp_digest_pk_update(ctx, d, (unsigned int)cnt); +} + + +int wolfSSL_EVP_DigestVerifyFinal(WOLFSSL_EVP_MD_CTX *ctx, + const unsigned char *sig, size_t siglen) +{ + unsigned char digest[WC_MAX_DIGEST_SIZE]; + unsigned int hashLen; + + WOLFSSL_ENTER("EVP_DigestVerifyFinal"); + + if (ctx == NULL || sig == NULL) + return WOLFSSL_FAILURE; + + if (ctx->pctx == NULL) { + if (ctx->macType != (NID_hmac & 0xFF)) + return WOLFSSL_FAILURE; + + hashLen = wolfssl_mac_len(ctx->hash.hmac.macType); + + if (siglen > hashLen) + return WOLFSSL_FAILURE; + /* May be a truncated signature. */ + } + + if (wolfssl_evp_digest_pk_final(ctx, digest, &hashLen) <= 0) + return WOLFSSL_FAILURE; + + if (ctx->pctx == NULL) { + /* Check HMAC result matches the signature. */ + if (XMEMCMP(sig, digest, siglen) == 0) + return WOLFSSL_SUCCESS; + return WOLFSSL_FAILURE; + } + else { + /* Verify the signature with the digest. */ + switch (ctx->pctx->pkey->type) { + #if !defined(NO_RSA) && !defined(HAVE_USER_RSA) + case EVP_PKEY_RSA: { + int nid = md2nid(ctx->macType); + if (nid < 0) + return WOLFSSL_FAILURE; + return wolfSSL_RSA_verify(nid, digest, hashLen, sig, + (unsigned int)siglen, + ctx->pctx->pkey->rsa); + } + #endif /* NO_RSA */ + + #ifdef HAVE_ECC + case EVP_PKEY_EC: { + int ret; + WOLFSSL_ECDSA_SIG *ecdsaSig; + ecdsaSig = wolfSSL_d2i_ECDSA_SIG(NULL, &sig, (long)siglen); + if (ecdsaSig == NULL) + return WOLFSSL_FAILURE; + ret = wolfSSL_ECDSA_do_verify(digest, hashLen, ecdsaSig, + ctx->pctx->pkey->ecc); + wolfSSL_ECDSA_SIG_free(ecdsaSig); + return ret; + } + #endif + default: + break; + } + } + + return WOLFSSL_FAILURE; +} +#endif /* WOLFSSL_EVP_INCLUDED */ + +#if defined(OPENSSL_EXTRA) && !defined(NO_PWDBASED) && !defined(NO_SHA) +WOLFSSL_API int wolfSSL_PKCS5_PBKDF2_HMAC_SHA1(const char *pass, int passlen, + const unsigned char *salt, + int saltlen, int iter, + int keylen, unsigned char *out) +{ + const char *nostring = ""; + int ret = 0; + + if (pass == NULL) { + passlen = 0; + pass = nostring; + } else if (passlen == -1) { + passlen = (int)XSTRLEN(pass); + } + + ret = wc_PBKDF2((byte*)out, (byte*)pass, passlen, (byte*)salt, saltlen, + iter, keylen, WC_SHA); + if (ret == 0) + return WOLFSSL_SUCCESS; + else + return WOLFSSL_FAILURE; +} +#endif /* OPENSSL_EXTRA && !NO_PWDBASED !NO_SHA*/ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/fe_low_mem.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fe_low_mem.c new file mode 100755 index 0000000..a783012 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fe_low_mem.c @@ -0,0 +1,611 @@ +/* fe_low_mem.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +/* Based from Daniel Beer's public domain work. */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#if defined(HAVE_CURVE25519) || defined(HAVE_ED25519) +#if defined(CURVE25519_SMALL) || defined(ED25519_SMALL) /* use slower code that takes less memory */ + +#include + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +void fprime_copy(byte *x, const byte *a) +{ + int i; + for (i = 0; i < F25519_SIZE; i++) + x[i] = a[i]; +} + + +void lm_copy(byte* x, const byte* a) +{ + int i; + for (i = 0; i < F25519_SIZE; i++) + x[i] = a[i]; +} + +#if ((defined(HAVE_CURVE25519) && !defined(CURVE25519_SMALL)) || \ + (defined(HAVE_ED25519) && !defined(ED25519_SMALL))) && \ + !defined(FREESCALE_LTC_ECC) + /* to be Complementary to fe_low_mem.c */ +#else +void fe_init(void) +{ +} +#endif + +#ifdef CURVE25519_SMALL + +/* Double an X-coordinate */ +static void xc_double(byte *x3, byte *z3, + const byte *x1, const byte *z1) +{ + /* Explicit formulas database: dbl-1987-m + * + * source 1987 Montgomery "Speeding the Pollard and elliptic + * curve methods of factorization", page 261, fourth display + * compute X3 = (X1^2-Z1^2)^2 + * compute Z3 = 4 X1 Z1 (X1^2 + a X1 Z1 + Z1^2) + */ + byte x1sq[F25519_SIZE]; + byte z1sq[F25519_SIZE]; + byte x1z1[F25519_SIZE]; + byte a[F25519_SIZE]; + + fe_mul__distinct(x1sq, x1, x1); + fe_mul__distinct(z1sq, z1, z1); + fe_mul__distinct(x1z1, x1, z1); + + lm_sub(a, x1sq, z1sq); + fe_mul__distinct(x3, a, a); + + fe_mul_c(a, x1z1, 486662); + lm_add(a, x1sq, a); + lm_add(a, z1sq, a); + fe_mul__distinct(x1sq, x1z1, a); + fe_mul_c(z3, x1sq, 4); +} + + +/* Differential addition */ +static void xc_diffadd(byte *x5, byte *z5, + const byte *x1, const byte *z1, + const byte *x2, const byte *z2, + const byte *x3, const byte *z3) +{ + /* Explicit formulas database: dbl-1987-m3 + * + * source 1987 Montgomery "Speeding the Pollard and elliptic curve + * methods of factorization", page 261, fifth display, plus + * common-subexpression elimination + * compute A = X2+Z2 + * compute B = X2-Z2 + * compute C = X3+Z3 + * compute D = X3-Z3 + * compute DA = D A + * compute CB = C B + * compute X5 = Z1(DA+CB)^2 + * compute Z5 = X1(DA-CB)^2 + */ + byte da[F25519_SIZE]; + byte cb[F25519_SIZE]; + byte a[F25519_SIZE]; + byte b[F25519_SIZE]; + + lm_add(a, x2, z2); + lm_sub(b, x3, z3); /* D */ + fe_mul__distinct(da, a, b); + + lm_sub(b, x2, z2); + lm_add(a, x3, z3); /* C */ + fe_mul__distinct(cb, a, b); + + lm_add(a, da, cb); + fe_mul__distinct(b, a, a); + fe_mul__distinct(x5, z1, b); + + lm_sub(a, da, cb); + fe_mul__distinct(b, a, a); + fe_mul__distinct(z5, x1, b); +} + +#ifndef FREESCALE_LTC_ECC +int curve25519(byte *result, byte *e, byte *q) +{ + /* Current point: P_m */ + byte xm[F25519_SIZE]; + byte zm[F25519_SIZE] = {1}; + + /* Predecessor: P_(m-1) */ + byte xm1[F25519_SIZE] = {1}; + byte zm1[F25519_SIZE] = {0}; + + int i; + + /* Note: bit 254 is assumed to be 1 */ + lm_copy(xm, q); + + for (i = 253; i >= 0; i--) { + const int bit = (e[i >> 3] >> (i & 7)) & 1; + byte xms[F25519_SIZE]; + byte zms[F25519_SIZE]; + + /* From P_m and P_(m-1), compute P_(2m) and P_(2m-1) */ + xc_diffadd(xm1, zm1, q, f25519_one, xm, zm, xm1, zm1); + xc_double(xm, zm, xm, zm); + + /* Compute P_(2m+1) */ + xc_diffadd(xms, zms, xm1, zm1, xm, zm, q, f25519_one); + + /* Select: + * bit = 1 --> (P_(2m+1), P_(2m)) + * bit = 0 --> (P_(2m), P_(2m-1)) + */ + fe_select(xm1, xm1, xm, bit); + fe_select(zm1, zm1, zm, bit); + fe_select(xm, xm, xms, bit); + fe_select(zm, zm, zms, bit); + } + + /* Freeze out of projective coordinates */ + fe_inv__distinct(zm1, zm); + fe_mul__distinct(result, zm1, xm); + fe_normalize(result); + return 0; +} +#endif /* !FREESCALE_LTC_ECC */ +#endif /* CURVE25519_SMALL */ + + +static void raw_add(byte *x, const byte *p) +{ + word16 c = 0; + int i; + + for (i = 0; i < F25519_SIZE; i++) { + c += ((word16)x[i]) + ((word16)p[i]); + x[i] = (byte)c; + c >>= 8; + } +} + + +static void raw_try_sub(byte *x, const byte *p) +{ + byte minusp[F25519_SIZE]; + word16 c = 0; + int i; + + for (i = 0; i < F25519_SIZE; i++) { + c = ((word16)x[i]) - ((word16)p[i]) - c; + minusp[i] = (byte)c; + c = (c >> 8) & 1; + } + + fprime_select(x, minusp, x, (byte)c); +} + + +static int prime_msb(const byte *p) +{ + int i; + byte x; + int shift = 1; + int z = F25519_SIZE - 1; + + /* + Test for any hot bits. + As soon as one instance is encountered set shift to 0. + */ + for (i = F25519_SIZE - 1; i >= 0; i--) { + shift &= ((shift ^ ((-p[i] | p[i]) >> 7)) & 1); + z -= shift; + } + x = p[z]; + z <<= 3; + shift = 1; + for (i = 0; i < 8; i++) { + shift &= ((-(x >> i) | (x >> i)) >> (7 - i) & 1); + z += shift; + } + + return z - 1; +} + + +void fprime_select(byte *dst, const byte *zero, const byte *one, byte condition) +{ + const byte mask = -condition; + int i; + + for (i = 0; i < F25519_SIZE; i++) + dst[i] = zero[i] ^ (mask & (one[i] ^ zero[i])); +} + + +void fprime_add(byte *r, const byte *a, const byte *modulus) +{ + raw_add(r, a); + raw_try_sub(r, modulus); +} + + +void fprime_sub(byte *r, const byte *a, const byte *modulus) +{ + raw_add(r, modulus); + raw_try_sub(r, a); + raw_try_sub(r, modulus); +} + + +void fprime_mul(byte *r, const byte *a, const byte *b, + const byte *modulus) +{ + word16 c = 0; + int i,j; + + XMEMSET(r, 0, F25519_SIZE); + + for (i = prime_msb(modulus); i >= 0; i--) { + const byte bit = (b[i >> 3] >> (i & 7)) & 1; + byte plusa[F25519_SIZE]; + + for (j = 0; j < F25519_SIZE; j++) { + c |= ((word16)r[j]) << 1; + r[j] = (byte)c; + c >>= 8; + } + raw_try_sub(r, modulus); + + fprime_copy(plusa, r); + fprime_add(plusa, a, modulus); + + fprime_select(r, r, plusa, bit); + } +} + + +void fe_load(byte *x, word32 c) +{ + word32 i; + + for (i = 0; i < sizeof(c); i++) { + x[i] = c; + c >>= 8; + } + + for (; i < F25519_SIZE; i++) + x[i] = 0; +} + + +void fe_normalize(byte *x) +{ + byte minusp[F25519_SIZE]; + word16 c; + int i; + + /* Reduce using 2^255 = 19 mod p */ + c = (x[31] >> 7) * 19; + x[31] &= 127; + + for (i = 0; i < F25519_SIZE; i++) { + c += x[i]; + x[i] = (byte)c; + c >>= 8; + } + + /* The number is now less than 2^255 + 18, and therefore less than + * 2p. Try subtracting p, and conditionally load the subtracted + * value if underflow did not occur. + */ + c = 19; + + for (i = 0; i + 1 < F25519_SIZE; i++) { + c += x[i]; + minusp[i] = (byte)c; + c >>= 8; + } + + c += ((word16)x[i]) - 128; + minusp[31] = (byte)c; + + /* Load x-p if no underflow */ + fe_select(x, minusp, x, (c >> 15) & 1); +} + + +void fe_select(byte *dst, + const byte *zero, const byte *one, + byte condition) +{ + const byte mask = -condition; + int i; + + for (i = 0; i < F25519_SIZE; i++) + dst[i] = zero[i] ^ (mask & (one[i] ^ zero[i])); +} + + +void lm_add(byte* r, const byte* a, const byte* b) +{ + word16 c = 0; + int i; + + /* Add */ + for (i = 0; i < F25519_SIZE; i++) { + c >>= 8; + c += ((word16)a[i]) + ((word16)b[i]); + r[i] = (byte)c; + } + + /* Reduce with 2^255 = 19 mod p */ + r[31] &= 127; + c = (c >> 7) * 19; + + for (i = 0; i < F25519_SIZE; i++) { + c += r[i]; + r[i] = (byte)c; + c >>= 8; + } +} + + +void lm_sub(byte* r, const byte* a, const byte* b) +{ + word32 c = 0; + int i; + + /* Calculate a + 2p - b, to avoid underflow */ + c = 218; + for (i = 0; i + 1 < F25519_SIZE; i++) { + c += 65280 + ((word32)a[i]) - ((word32)b[i]); + r[i] = c; + c >>= 8; + } + + c += ((word32)a[31]) - ((word32)b[31]); + r[31] = c & 127; + c = (c >> 7) * 19; + + for (i = 0; i < F25519_SIZE; i++) { + c += r[i]; + r[i] = c; + c >>= 8; + } +} + + +void lm_neg(byte* r, const byte* a) +{ + word32 c = 0; + int i; + + /* Calculate 2p - a, to avoid underflow */ + c = 218; + for (i = 0; i + 1 < F25519_SIZE; i++) { + c += 65280 - ((word32)a[i]); + r[i] = c; + c >>= 8; + } + + c -= ((word32)a[31]); + r[31] = c & 127; + c = (c >> 7) * 19; + + for (i = 0; i < F25519_SIZE; i++) { + c += r[i]; + r[i] = c; + c >>= 8; + } +} + + +void fe_mul__distinct(byte *r, const byte *a, const byte *b) +{ + word32 c = 0; + int i; + + for (i = 0; i < F25519_SIZE; i++) { + int j; + + c >>= 8; + for (j = 0; j <= i; j++) + c += ((word32)a[j]) * ((word32)b[i - j]); + + for (; j < F25519_SIZE; j++) + c += ((word32)a[j]) * + ((word32)b[i + F25519_SIZE - j]) * 38; + + r[i] = c; + } + + r[31] &= 127; + c = (c >> 7) * 19; + + for (i = 0; i < F25519_SIZE; i++) { + c += r[i]; + r[i] = c; + c >>= 8; + } +} + + +void lm_mul(byte *r, const byte* a, const byte *b) +{ + byte tmp[F25519_SIZE]; + + fe_mul__distinct(tmp, a, b); + lm_copy(r, tmp); +} + + +void fe_mul_c(byte *r, const byte *a, word32 b) +{ + word32 c = 0; + int i; + + for (i = 0; i < F25519_SIZE; i++) { + c >>= 8; + c += b * ((word32)a[i]); + r[i] = c; + } + + r[31] &= 127; + c >>= 7; + c *= 19; + + for (i = 0; i < F25519_SIZE; i++) { + c += r[i]; + r[i] = c; + c >>= 8; + } +} + + +void fe_inv__distinct(byte *r, const byte *x) +{ + byte s[F25519_SIZE]; + int i; + + /* This is a prime field, so by Fermat's little theorem: + * + * x^(p-1) = 1 mod p + * + * Therefore, raise to (p-2) = 2^255-21 to get a multiplicative + * inverse. + * + * This is a 255-bit binary number with the digits: + * + * 11111111... 01011 + * + * We compute the result by the usual binary chain, but + * alternate between keeping the accumulator in r and s, so as + * to avoid copying temporaries. + */ + + /* 1 1 */ + fe_mul__distinct(s, x, x); + fe_mul__distinct(r, s, x); + + /* 1 x 248 */ + for (i = 0; i < 248; i++) { + fe_mul__distinct(s, r, r); + fe_mul__distinct(r, s, x); + } + + /* 0 */ + fe_mul__distinct(s, r, r); + + /* 1 */ + fe_mul__distinct(r, s, s); + fe_mul__distinct(s, r, x); + + /* 0 */ + fe_mul__distinct(r, s, s); + + /* 1 */ + fe_mul__distinct(s, r, r); + fe_mul__distinct(r, s, x); + + /* 1 */ + fe_mul__distinct(s, r, r); + fe_mul__distinct(r, s, x); +} + + +void lm_invert(byte *r, const byte *x) +{ + byte tmp[F25519_SIZE]; + + fe_inv__distinct(tmp, x); + lm_copy(r, tmp); +} + + +/* Raise x to the power of (p-5)/8 = 2^252-3, using s for temporary + * storage. + */ +static void exp2523(byte *r, const byte *x, byte *s) +{ + int i; + + /* This number is a 252-bit number with the binary expansion: + * + * 111111... 01 + */ + + /* 1 1 */ + fe_mul__distinct(r, x, x); + fe_mul__distinct(s, r, x); + + /* 1 x 248 */ + for (i = 0; i < 248; i++) { + fe_mul__distinct(r, s, s); + fe_mul__distinct(s, r, x); + } + + /* 0 */ + fe_mul__distinct(r, s, s); + + /* 1 */ + fe_mul__distinct(s, r, r); + fe_mul__distinct(r, s, x); +} + + +void fe_sqrt(byte *r, const byte *a) +{ + byte v[F25519_SIZE]; + byte i[F25519_SIZE]; + byte x[F25519_SIZE]; + byte y[F25519_SIZE]; + + /* v = (2a)^((p-5)/8) [x = 2a] */ + fe_mul_c(x, a, 2); + exp2523(v, x, y); + + /* i = 2av^2 - 1 */ + fe_mul__distinct(y, v, v); + fe_mul__distinct(i, x, y); + fe_load(y, 1); + lm_sub(i, i, y); + + /* r = avi */ + fe_mul__distinct(x, v, a); + fe_mul__distinct(r, x, i); +} + +#endif /* CURVE25519_SMALL || ED25519_SMALL */ +#endif /* HAVE_CURVE25519 || HAVE_ED25519 */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/fe_operations.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fe_operations.c new file mode 100755 index 0000000..136f40e --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fe_operations.c @@ -0,0 +1,1438 @@ +/* fe_operations.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + /* Based On Daniel J Bernstein's curve25519 Public Domain ref10 work. */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#if defined(HAVE_CURVE25519) || defined(HAVE_ED25519) +#if !defined(CURVE25519_SMALL) || !defined(ED25519_SMALL) /* run when not defined to use small memory math */ + +#include +#include + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#ifdef CURVED25519_X64 +/* Assembly code in fe_x25519_asm.* */ +#elif defined(WOLFSSL_ARMASM) +/* Assembly code in fe_armv[78]_x25519.* */ +#elif defined(CURVED25519_128BIT) +#include "fe_x25519_128.i" +#else + +#if defined(HAVE_CURVE25519) || \ + (defined(HAVE_ED25519) && !defined(ED25519_SMALL)) +/* +fe means field element. +Here the field is \Z/(2^255-19). +An element t, entries t[0]...t[9], represents the integer +t[0]+2^26 t[1]+2^51 t[2]+2^77 t[3]+2^102 t[4]+...+2^230 t[9]. +Bounds on each t[i] vary depending on context. +*/ + +uint64_t load_3(const unsigned char *in) +{ + uint64_t result; + result = (uint64_t) in[0]; + result |= ((uint64_t) in[1]) << 8; + result |= ((uint64_t) in[2]) << 16; + return result; +} + + +uint64_t load_4(const unsigned char *in) +{ + uint64_t result; + result = (uint64_t) in[0]; + result |= ((uint64_t) in[1]) << 8; + result |= ((uint64_t) in[2]) << 16; + result |= ((uint64_t) in[3]) << 24; + return result; +} +#endif + +/* +h = 1 +*/ + +void fe_1(fe h) +{ + h[0] = 1; + h[1] = 0; + h[2] = 0; + h[3] = 0; + h[4] = 0; + h[5] = 0; + h[6] = 0; + h[7] = 0; + h[8] = 0; + h[9] = 0; +} + + +/* +h = 0 +*/ + +void fe_0(fe h) +{ + h[0] = 0; + h[1] = 0; + h[2] = 0; + h[3] = 0; + h[4] = 0; + h[5] = 0; + h[6] = 0; + h[7] = 0; + h[8] = 0; + h[9] = 0; +} + + +#if ((defined(HAVE_CURVE25519) && !defined(CURVE25519_SMALL)) || \ + (defined(HAVE_ED25519) && !defined(ED25519_SMALL))) && \ + !defined(FREESCALE_LTC_ECC) +/* to be Complementary to fe_low_mem.c */ +void fe_init(void) +{ +} +#endif + +#if defined(HAVE_CURVE25519) && !defined(CURVE25519_SMALL) && \ + !defined(FREESCALE_LTC_ECC) +int curve25519(byte* q, byte* n, byte* p) +{ +#if 0 + unsigned char e[32]; +#endif + fe x1; + fe x2; + fe z2; + fe x3; + fe z3; + fe tmp0; + fe tmp1; + int pos; + unsigned int swap; + unsigned int b; + + /* Clamp already done during key generation and import */ +#if 0 + { + unsigned int i; + for (i = 0;i < 32;++i) e[i] = n[i]; + e[0] &= 248; + e[31] &= 127; + e[31] |= 64; + } +#endif + + fe_frombytes(x1,p); + fe_1(x2); + fe_0(z2); + fe_copy(x3,x1); + fe_1(z3); + + swap = 0; + for (pos = 254;pos >= 0;--pos) { +#if 0 + b = e[pos / 8] >> (pos & 7); +#else + b = n[pos / 8] >> (pos & 7); +#endif + b &= 1; + swap ^= b; + fe_cswap(x2,x3,swap); + fe_cswap(z2,z3,swap); + swap = b; + + /* montgomery */ + fe_sub(tmp0,x3,z3); + fe_sub(tmp1,x2,z2); + fe_add(x2,x2,z2); + fe_add(z2,x3,z3); + fe_mul(z3,tmp0,x2); + fe_mul(z2,z2,tmp1); + fe_sq(tmp0,tmp1); + fe_sq(tmp1,x2); + fe_add(x3,z3,z2); + fe_sub(z2,z3,z2); + fe_mul(x2,tmp1,tmp0); + fe_sub(tmp1,tmp1,tmp0); + fe_sq(z2,z2); + fe_mul121666(z3,tmp1); + fe_sq(x3,x3); + fe_add(tmp0,tmp0,z3); + fe_mul(z3,x1,z2); + fe_mul(z2,tmp1,tmp0); + } + fe_cswap(x2,x3,swap); + fe_cswap(z2,z3,swap); + + fe_invert(z2,z2); + fe_mul(x2,x2,z2); + fe_tobytes(q,x2); + + return 0; +} +#endif /* HAVE_CURVE25519 && !CURVE25519_SMALL && !FREESCALE_LTC_ECC */ + + +/* +h = f * f +Can overlap h with f. + +Preconditions: + |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. + +Postconditions: + |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc. +*/ + +/* +See fe_mul.c for discussion of implementation strategy. +*/ + +void fe_sq(fe h,const fe f) +{ + int32_t f0 = f[0]; + int32_t f1 = f[1]; + int32_t f2 = f[2]; + int32_t f3 = f[3]; + int32_t f4 = f[4]; + int32_t f5 = f[5]; + int32_t f6 = f[6]; + int32_t f7 = f[7]; + int32_t f8 = f[8]; + int32_t f9 = f[9]; + int32_t f0_2 = 2 * f0; + int32_t f1_2 = 2 * f1; + int32_t f2_2 = 2 * f2; + int32_t f3_2 = 2 * f3; + int32_t f4_2 = 2 * f4; + int32_t f5_2 = 2 * f5; + int32_t f6_2 = 2 * f6; + int32_t f7_2 = 2 * f7; + int32_t f5_38 = 38 * f5; /* 1.959375*2^30 */ + int32_t f6_19 = 19 * f6; /* 1.959375*2^30 */ + int32_t f7_38 = 38 * f7; /* 1.959375*2^30 */ + int32_t f8_19 = 19 * f8; /* 1.959375*2^30 */ + int32_t f9_38 = 38 * f9; /* 1.959375*2^30 */ + int64_t f0f0 = f0 * (int64_t) f0; + int64_t f0f1_2 = f0_2 * (int64_t) f1; + int64_t f0f2_2 = f0_2 * (int64_t) f2; + int64_t f0f3_2 = f0_2 * (int64_t) f3; + int64_t f0f4_2 = f0_2 * (int64_t) f4; + int64_t f0f5_2 = f0_2 * (int64_t) f5; + int64_t f0f6_2 = f0_2 * (int64_t) f6; + int64_t f0f7_2 = f0_2 * (int64_t) f7; + int64_t f0f8_2 = f0_2 * (int64_t) f8; + int64_t f0f9_2 = f0_2 * (int64_t) f9; + int64_t f1f1_2 = f1_2 * (int64_t) f1; + int64_t f1f2_2 = f1_2 * (int64_t) f2; + int64_t f1f3_4 = f1_2 * (int64_t) f3_2; + int64_t f1f4_2 = f1_2 * (int64_t) f4; + int64_t f1f5_4 = f1_2 * (int64_t) f5_2; + int64_t f1f6_2 = f1_2 * (int64_t) f6; + int64_t f1f7_4 = f1_2 * (int64_t) f7_2; + int64_t f1f8_2 = f1_2 * (int64_t) f8; + int64_t f1f9_76 = f1_2 * (int64_t) f9_38; + int64_t f2f2 = f2 * (int64_t) f2; + int64_t f2f3_2 = f2_2 * (int64_t) f3; + int64_t f2f4_2 = f2_2 * (int64_t) f4; + int64_t f2f5_2 = f2_2 * (int64_t) f5; + int64_t f2f6_2 = f2_2 * (int64_t) f6; + int64_t f2f7_2 = f2_2 * (int64_t) f7; + int64_t f2f8_38 = f2_2 * (int64_t) f8_19; + int64_t f2f9_38 = f2 * (int64_t) f9_38; + int64_t f3f3_2 = f3_2 * (int64_t) f3; + int64_t f3f4_2 = f3_2 * (int64_t) f4; + int64_t f3f5_4 = f3_2 * (int64_t) f5_2; + int64_t f3f6_2 = f3_2 * (int64_t) f6; + int64_t f3f7_76 = f3_2 * (int64_t) f7_38; + int64_t f3f8_38 = f3_2 * (int64_t) f8_19; + int64_t f3f9_76 = f3_2 * (int64_t) f9_38; + int64_t f4f4 = f4 * (int64_t) f4; + int64_t f4f5_2 = f4_2 * (int64_t) f5; + int64_t f4f6_38 = f4_2 * (int64_t) f6_19; + int64_t f4f7_38 = f4 * (int64_t) f7_38; + int64_t f4f8_38 = f4_2 * (int64_t) f8_19; + int64_t f4f9_38 = f4 * (int64_t) f9_38; + int64_t f5f5_38 = f5 * (int64_t) f5_38; + int64_t f5f6_38 = f5_2 * (int64_t) f6_19; + int64_t f5f7_76 = f5_2 * (int64_t) f7_38; + int64_t f5f8_38 = f5_2 * (int64_t) f8_19; + int64_t f5f9_76 = f5_2 * (int64_t) f9_38; + int64_t f6f6_19 = f6 * (int64_t) f6_19; + int64_t f6f7_38 = f6 * (int64_t) f7_38; + int64_t f6f8_38 = f6_2 * (int64_t) f8_19; + int64_t f6f9_38 = f6 * (int64_t) f9_38; + int64_t f7f7_38 = f7 * (int64_t) f7_38; + int64_t f7f8_38 = f7_2 * (int64_t) f8_19; + int64_t f7f9_76 = f7_2 * (int64_t) f9_38; + int64_t f8f8_19 = f8 * (int64_t) f8_19; + int64_t f8f9_38 = f8 * (int64_t) f9_38; + int64_t f9f9_38 = f9 * (int64_t) f9_38; + int64_t h0 = f0f0 +f1f9_76+f2f8_38+f3f7_76+f4f6_38+f5f5_38; + int64_t h1 = f0f1_2+f2f9_38+f3f8_38+f4f7_38+f5f6_38; + int64_t h2 = f0f2_2+f1f1_2 +f3f9_76+f4f8_38+f5f7_76+f6f6_19; + int64_t h3 = f0f3_2+f1f2_2 +f4f9_38+f5f8_38+f6f7_38; + int64_t h4 = f0f4_2+f1f3_4 +f2f2 +f5f9_76+f6f8_38+f7f7_38; + int64_t h5 = f0f5_2+f1f4_2 +f2f3_2 +f6f9_38+f7f8_38; + int64_t h6 = f0f6_2+f1f5_4 +f2f4_2 +f3f3_2 +f7f9_76+f8f8_19; + int64_t h7 = f0f7_2+f1f6_2 +f2f5_2 +f3f4_2 +f8f9_38; + int64_t h8 = f0f8_2+f1f7_4 +f2f6_2 +f3f5_4 +f4f4 +f9f9_38; + int64_t h9 = f0f9_2+f1f8_2 +f2f7_2 +f3f6_2 +f4f5_2; + int64_t carry0; + int64_t carry1; + int64_t carry2; + int64_t carry3; + int64_t carry4; + int64_t carry5; + int64_t carry6; + int64_t carry7; + int64_t carry8; + int64_t carry9; + + carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; + carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; + + carry1 = (h1 + (int64_t) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25; + carry5 = (h5 + (int64_t) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25; + + carry2 = (h2 + (int64_t) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26; + carry6 = (h6 + (int64_t) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26; + + carry3 = (h3 + (int64_t) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25; + carry7 = (h7 + (int64_t) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25; + + carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; + carry8 = (h8 + (int64_t) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26; + + carry9 = (h9 + (int64_t) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; + + carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; + + h[0] = (int32_t)h0; + h[1] = (int32_t)h1; + h[2] = (int32_t)h2; + h[3] = (int32_t)h3; + h[4] = (int32_t)h4; + h[5] = (int32_t)h5; + h[6] = (int32_t)h6; + h[7] = (int32_t)h7; + h[8] = (int32_t)h8; + h[9] = (int32_t)h9; +} + + +/* +h = f + g +Can overlap h with f or g. + +Preconditions: + |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. + |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. + +Postconditions: + |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. +*/ + +void fe_add(fe h,const fe f,const fe g) +{ + int32_t f0 = f[0]; + int32_t f1 = f[1]; + int32_t f2 = f[2]; + int32_t f3 = f[3]; + int32_t f4 = f[4]; + int32_t f5 = f[5]; + int32_t f6 = f[6]; + int32_t f7 = f[7]; + int32_t f8 = f[8]; + int32_t f9 = f[9]; + int32_t g0 = g[0]; + int32_t g1 = g[1]; + int32_t g2 = g[2]; + int32_t g3 = g[3]; + int32_t g4 = g[4]; + int32_t g5 = g[5]; + int32_t g6 = g[6]; + int32_t g7 = g[7]; + int32_t g8 = g[8]; + int32_t g9 = g[9]; + int32_t h0 = f0 + g0; + int32_t h1 = f1 + g1; + int32_t h2 = f2 + g2; + int32_t h3 = f3 + g3; + int32_t h4 = f4 + g4; + int32_t h5 = f5 + g5; + int32_t h6 = f6 + g6; + int32_t h7 = f7 + g7; + int32_t h8 = f8 + g8; + int32_t h9 = f9 + g9; + h[0] = h0; + h[1] = h1; + h[2] = h2; + h[3] = h3; + h[4] = h4; + h[5] = h5; + h[6] = h6; + h[7] = h7; + h[8] = h8; + h[9] = h9; +} + + +/* +Preconditions: + |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. + +Write p=2^255-19; q=floor(h/p). +Basic claim: q = floor(2^(-255)(h + 19 2^(-25)h9 + 2^(-1))). + +Proof: + Have |h|<=p so |q|<=1 so |19^2 2^(-255) q|<1/4. + Also have |h-2^230 h9|<2^231 so |19 2^(-255)(h-2^230 h9)|<1/4. + + Write y=2^(-1)-19^2 2^(-255)q-19 2^(-255)(h-2^230 h9). + Then 0> 25; + q = (h0 + q) >> 26; + q = (h1 + q) >> 25; + q = (h2 + q) >> 26; + q = (h3 + q) >> 25; + q = (h4 + q) >> 26; + q = (h5 + q) >> 25; + q = (h6 + q) >> 26; + q = (h7 + q) >> 25; + q = (h8 + q) >> 26; + q = (h9 + q) >> 25; + + /* Goal: Output h-(2^255-19)q, which is between 0 and 2^255-20. */ + h0 += 19 * q; + /* Goal: Output h-2^255 q, which is between 0 and 2^255-20. */ + + carry0 = h0 >> 26; h1 += carry0; h0 -= carry0 << 26; + carry1 = h1 >> 25; h2 += carry1; h1 -= carry1 << 25; + carry2 = h2 >> 26; h3 += carry2; h2 -= carry2 << 26; + carry3 = h3 >> 25; h4 += carry3; h3 -= carry3 << 25; + carry4 = h4 >> 26; h5 += carry4; h4 -= carry4 << 26; + carry5 = h5 >> 25; h6 += carry5; h5 -= carry5 << 25; + carry6 = h6 >> 26; h7 += carry6; h6 -= carry6 << 26; + carry7 = h7 >> 25; h8 += carry7; h7 -= carry7 << 25; + carry8 = h8 >> 26; h9 += carry8; h8 -= carry8 << 26; + carry9 = h9 >> 25; h9 -= carry9 << 25; + /* h10 = carry9 */ + + /* + Goal: Output h0+...+2^255 h10-2^255 q, which is between 0 and 2^255-20. + Have h0+...+2^230 h9 between 0 and 2^255-1; + evidently 2^255 h10-2^255 q = 0. + Goal: Output h0+...+2^230 h9. + */ + + s[0] = (byte)(h0 >> 0); + s[1] = (byte)(h0 >> 8); + s[2] = (byte)(h0 >> 16); + s[3] = (byte)((h0 >> 24) | (h1 << 2)); + s[4] = (byte)(h1 >> 6); + s[5] = (byte)(h1 >> 14); + s[6] = (byte)((h1 >> 22) | (h2 << 3)); + s[7] = (byte)(h2 >> 5); + s[8] = (byte)(h2 >> 13); + s[9] = (byte)((h2 >> 21) | (h3 << 5)); + s[10] = (byte)(h3 >> 3); + s[11] = (byte)(h3 >> 11); + s[12] = (byte)((h3 >> 19) | (h4 << 6)); + s[13] = (byte)(h4 >> 2); + s[14] = (byte)(h4 >> 10); + s[15] = (byte)(h4 >> 18); + s[16] = (byte)(h5 >> 0); + s[17] = (byte)(h5 >> 8); + s[18] = (byte)(h5 >> 16); + s[19] = (byte)((h5 >> 24) | (h6 << 1)); + s[20] = (byte)(h6 >> 7); + s[21] = (byte)(h6 >> 15); + s[22] = (byte)((h6 >> 23) | (h7 << 3)); + s[23] = (byte)(h7 >> 5); + s[24] = (byte)(h7 >> 13); + s[25] = (byte)((h7 >> 21) | (h8 << 4)); + s[26] = (byte)(h8 >> 4); + s[27] = (byte)(h8 >> 12); + s[28] = (byte)((h8 >> 20) | (h9 << 6)); + s[29] = (byte)(h9 >> 2); + s[30] = (byte)(h9 >> 10); + s[31] = (byte)(h9 >> 18); +} + + +/* +h = f - g +Can overlap h with f or g. + +Preconditions: + |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. + |g| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. + +Postconditions: + |h| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. +*/ + +void fe_sub(fe h,const fe f,const fe g) +{ + int32_t f0 = f[0]; + int32_t f1 = f[1]; + int32_t f2 = f[2]; + int32_t f3 = f[3]; + int32_t f4 = f[4]; + int32_t f5 = f[5]; + int32_t f6 = f[6]; + int32_t f7 = f[7]; + int32_t f8 = f[8]; + int32_t f9 = f[9]; + int32_t g0 = g[0]; + int32_t g1 = g[1]; + int32_t g2 = g[2]; + int32_t g3 = g[3]; + int32_t g4 = g[4]; + int32_t g5 = g[5]; + int32_t g6 = g[6]; + int32_t g7 = g[7]; + int32_t g8 = g[8]; + int32_t g9 = g[9]; + int32_t h0 = f0 - g0; + int32_t h1 = f1 - g1; + int32_t h2 = f2 - g2; + int32_t h3 = f3 - g3; + int32_t h4 = f4 - g4; + int32_t h5 = f5 - g5; + int32_t h6 = f6 - g6; + int32_t h7 = f7 - g7; + int32_t h8 = f8 - g8; + int32_t h9 = f9 - g9; + h[0] = h0; + h[1] = h1; + h[2] = h2; + h[3] = h3; + h[4] = h4; + h[5] = h5; + h[6] = h6; + h[7] = h7; + h[8] = h8; + h[9] = h9; +} + + +#if defined(HAVE_CURVE25519) || \ + (defined(HAVE_ED25519) && !defined(ED25519_SMALL)) +/* +Ignores top bit of h. +*/ + +void fe_frombytes(fe h,const unsigned char *s) +{ + int64_t h0 = load_4(s); + int64_t h1 = load_3(s + 4) << 6; + int64_t h2 = load_3(s + 7) << 5; + int64_t h3 = load_3(s + 10) << 3; + int64_t h4 = load_3(s + 13) << 2; + int64_t h5 = load_4(s + 16); + int64_t h6 = load_3(s + 20) << 7; + int64_t h7 = load_3(s + 23) << 5; + int64_t h8 = load_3(s + 26) << 4; + int64_t h9 = (load_3(s + 29) & 8388607) << 2; + int64_t carry0; + int64_t carry1; + int64_t carry2; + int64_t carry3; + int64_t carry4; + int64_t carry5; + int64_t carry6; + int64_t carry7; + int64_t carry8; + int64_t carry9; + + carry9 = (h9 + (int64_t) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; + carry1 = (h1 + (int64_t) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25; + carry3 = (h3 + (int64_t) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25; + carry5 = (h5 + (int64_t) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25; + carry7 = (h7 + (int64_t) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25; + + carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; + carry2 = (h2 + (int64_t) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26; + carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; + carry6 = (h6 + (int64_t) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26; + carry8 = (h8 + (int64_t) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26; + + h[0] = (int32_t)h0; + h[1] = (int32_t)h1; + h[2] = (int32_t)h2; + h[3] = (int32_t)h3; + h[4] = (int32_t)h4; + h[5] = (int32_t)h5; + h[6] = (int32_t)h6; + h[7] = (int32_t)h7; + h[8] = (int32_t)h8; + h[9] = (int32_t)h9; +} +#endif + + +void fe_invert(fe out,const fe z) +{ + fe t0; + fe t1; + fe t2; + fe t3; + int i; + + /* pow225521 */ + fe_sq(t0,z); for (i = 1;i < 1;++i) fe_sq(t0,t0); + fe_sq(t1,t0); for (i = 1;i < 2;++i) fe_sq(t1,t1); + fe_mul(t1,z,t1); + fe_mul(t0,t0,t1); + fe_sq(t2,t0); for (i = 1;i < 1;++i) fe_sq(t2,t2); + fe_mul(t1,t1,t2); + fe_sq(t2,t1); for (i = 1;i < 5;++i) fe_sq(t2,t2); + fe_mul(t1,t2,t1); + fe_sq(t2,t1); for (i = 1;i < 10;++i) fe_sq(t2,t2); + fe_mul(t2,t2,t1); + fe_sq(t3,t2); for (i = 1;i < 20;++i) fe_sq(t3,t3); + fe_mul(t2,t3,t2); + fe_sq(t2,t2); for (i = 1;i < 10;++i) fe_sq(t2,t2); + fe_mul(t1,t2,t1); + fe_sq(t2,t1); for (i = 1;i < 50;++i) fe_sq(t2,t2); + fe_mul(t2,t2,t1); + fe_sq(t3,t2); for (i = 1;i < 100;++i) fe_sq(t3,t3); + fe_mul(t2,t3,t2); + fe_sq(t2,t2); for (i = 1;i < 50;++i) fe_sq(t2,t2); + fe_mul(t1,t2,t1); + fe_sq(t1,t1); for (i = 1;i < 5;++i) fe_sq(t1,t1); + fe_mul(out,t1,t0); + + return; +} + + +/* +h = f +*/ + +void fe_copy(fe h,const fe f) +{ + int32_t f0 = f[0]; + int32_t f1 = f[1]; + int32_t f2 = f[2]; + int32_t f3 = f[3]; + int32_t f4 = f[4]; + int32_t f5 = f[5]; + int32_t f6 = f[6]; + int32_t f7 = f[7]; + int32_t f8 = f[8]; + int32_t f9 = f[9]; + h[0] = f0; + h[1] = f1; + h[2] = f2; + h[3] = f3; + h[4] = f4; + h[5] = f5; + h[6] = f6; + h[7] = f7; + h[8] = f8; + h[9] = f9; +} + + +/* +h = f * g +Can overlap h with f or g. + +Preconditions: + |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. + |g| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. + +Postconditions: + |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc. +*/ + +/* +Notes on implementation strategy: + +Using schoolbook multiplication. +Karatsuba would save a little in some cost models. + +Most multiplications by 2 and 19 are 32-bit precomputations; +cheaper than 64-bit postcomputations. + +There is one remaining multiplication by 19 in the carry chain; +one *19 precomputation can be merged into this, +but the resulting data flow is considerably less clean. + +There are 12 carries below. +10 of them are 2-way parallelizable and vectorizable. +Can get away with 11 carries, but then data flow is much deeper. + +With tighter constraints on inputs can squeeze carries into int32. +*/ + +void fe_mul(fe h,const fe f,const fe g) +{ + int32_t f0 = f[0]; + int32_t f1 = f[1]; + int32_t f2 = f[2]; + int32_t f3 = f[3]; + int32_t f4 = f[4]; + int32_t f5 = f[5]; + int32_t f6 = f[6]; + int32_t f7 = f[7]; + int32_t f8 = f[8]; + int32_t f9 = f[9]; + int32_t g0 = g[0]; + int32_t g1 = g[1]; + int32_t g2 = g[2]; + int32_t g3 = g[3]; + int32_t g4 = g[4]; + int32_t g5 = g[5]; + int32_t g6 = g[6]; + int32_t g7 = g[7]; + int32_t g8 = g[8]; + int32_t g9 = g[9]; + int32_t g1_19 = 19 * g1; /* 1.959375*2^29 */ + int32_t g2_19 = 19 * g2; /* 1.959375*2^30; still ok */ + int32_t g3_19 = 19 * g3; + int32_t g4_19 = 19 * g4; + int32_t g5_19 = 19 * g5; + int32_t g6_19 = 19 * g6; + int32_t g7_19 = 19 * g7; + int32_t g8_19 = 19 * g8; + int32_t g9_19 = 19 * g9; + int32_t f1_2 = 2 * f1; + int32_t f3_2 = 2 * f3; + int32_t f5_2 = 2 * f5; + int32_t f7_2 = 2 * f7; + int32_t f9_2 = 2 * f9; + int64_t f0g0 = f0 * (int64_t) g0; + int64_t f0g1 = f0 * (int64_t) g1; + int64_t f0g2 = f0 * (int64_t) g2; + int64_t f0g3 = f0 * (int64_t) g3; + int64_t f0g4 = f0 * (int64_t) g4; + int64_t f0g5 = f0 * (int64_t) g5; + int64_t f0g6 = f0 * (int64_t) g6; + int64_t f0g7 = f0 * (int64_t) g7; + int64_t f0g8 = f0 * (int64_t) g8; + int64_t f0g9 = f0 * (int64_t) g9; + int64_t f1g0 = f1 * (int64_t) g0; + int64_t f1g1_2 = f1_2 * (int64_t) g1; + int64_t f1g2 = f1 * (int64_t) g2; + int64_t f1g3_2 = f1_2 * (int64_t) g3; + int64_t f1g4 = f1 * (int64_t) g4; + int64_t f1g5_2 = f1_2 * (int64_t) g5; + int64_t f1g6 = f1 * (int64_t) g6; + int64_t f1g7_2 = f1_2 * (int64_t) g7; + int64_t f1g8 = f1 * (int64_t) g8; + int64_t f1g9_38 = f1_2 * (int64_t) g9_19; + int64_t f2g0 = f2 * (int64_t) g0; + int64_t f2g1 = f2 * (int64_t) g1; + int64_t f2g2 = f2 * (int64_t) g2; + int64_t f2g3 = f2 * (int64_t) g3; + int64_t f2g4 = f2 * (int64_t) g4; + int64_t f2g5 = f2 * (int64_t) g5; + int64_t f2g6 = f2 * (int64_t) g6; + int64_t f2g7 = f2 * (int64_t) g7; + int64_t f2g8_19 = f2 * (int64_t) g8_19; + int64_t f2g9_19 = f2 * (int64_t) g9_19; + int64_t f3g0 = f3 * (int64_t) g0; + int64_t f3g1_2 = f3_2 * (int64_t) g1; + int64_t f3g2 = f3 * (int64_t) g2; + int64_t f3g3_2 = f3_2 * (int64_t) g3; + int64_t f3g4 = f3 * (int64_t) g4; + int64_t f3g5_2 = f3_2 * (int64_t) g5; + int64_t f3g6 = f3 * (int64_t) g6; + int64_t f3g7_38 = f3_2 * (int64_t) g7_19; + int64_t f3g8_19 = f3 * (int64_t) g8_19; + int64_t f3g9_38 = f3_2 * (int64_t) g9_19; + int64_t f4g0 = f4 * (int64_t) g0; + int64_t f4g1 = f4 * (int64_t) g1; + int64_t f4g2 = f4 * (int64_t) g2; + int64_t f4g3 = f4 * (int64_t) g3; + int64_t f4g4 = f4 * (int64_t) g4; + int64_t f4g5 = f4 * (int64_t) g5; + int64_t f4g6_19 = f4 * (int64_t) g6_19; + int64_t f4g7_19 = f4 * (int64_t) g7_19; + int64_t f4g8_19 = f4 * (int64_t) g8_19; + int64_t f4g9_19 = f4 * (int64_t) g9_19; + int64_t f5g0 = f5 * (int64_t) g0; + int64_t f5g1_2 = f5_2 * (int64_t) g1; + int64_t f5g2 = f5 * (int64_t) g2; + int64_t f5g3_2 = f5_2 * (int64_t) g3; + int64_t f5g4 = f5 * (int64_t) g4; + int64_t f5g5_38 = f5_2 * (int64_t) g5_19; + int64_t f5g6_19 = f5 * (int64_t) g6_19; + int64_t f5g7_38 = f5_2 * (int64_t) g7_19; + int64_t f5g8_19 = f5 * (int64_t) g8_19; + int64_t f5g9_38 = f5_2 * (int64_t) g9_19; + int64_t f6g0 = f6 * (int64_t) g0; + int64_t f6g1 = f6 * (int64_t) g1; + int64_t f6g2 = f6 * (int64_t) g2; + int64_t f6g3 = f6 * (int64_t) g3; + int64_t f6g4_19 = f6 * (int64_t) g4_19; + int64_t f6g5_19 = f6 * (int64_t) g5_19; + int64_t f6g6_19 = f6 * (int64_t) g6_19; + int64_t f6g7_19 = f6 * (int64_t) g7_19; + int64_t f6g8_19 = f6 * (int64_t) g8_19; + int64_t f6g9_19 = f6 * (int64_t) g9_19; + int64_t f7g0 = f7 * (int64_t) g0; + int64_t f7g1_2 = f7_2 * (int64_t) g1; + int64_t f7g2 = f7 * (int64_t) g2; + int64_t f7g3_38 = f7_2 * (int64_t) g3_19; + int64_t f7g4_19 = f7 * (int64_t) g4_19; + int64_t f7g5_38 = f7_2 * (int64_t) g5_19; + int64_t f7g6_19 = f7 * (int64_t) g6_19; + int64_t f7g7_38 = f7_2 * (int64_t) g7_19; + int64_t f7g8_19 = f7 * (int64_t) g8_19; + int64_t f7g9_38 = f7_2 * (int64_t) g9_19; + int64_t f8g0 = f8 * (int64_t) g0; + int64_t f8g1 = f8 * (int64_t) g1; + int64_t f8g2_19 = f8 * (int64_t) g2_19; + int64_t f8g3_19 = f8 * (int64_t) g3_19; + int64_t f8g4_19 = f8 * (int64_t) g4_19; + int64_t f8g5_19 = f8 * (int64_t) g5_19; + int64_t f8g6_19 = f8 * (int64_t) g6_19; + int64_t f8g7_19 = f8 * (int64_t) g7_19; + int64_t f8g8_19 = f8 * (int64_t) g8_19; + int64_t f8g9_19 = f8 * (int64_t) g9_19; + int64_t f9g0 = f9 * (int64_t) g0; + int64_t f9g1_38 = f9_2 * (int64_t) g1_19; + int64_t f9g2_19 = f9 * (int64_t) g2_19; + int64_t f9g3_38 = f9_2 * (int64_t) g3_19; + int64_t f9g4_19 = f9 * (int64_t) g4_19; + int64_t f9g5_38 = f9_2 * (int64_t) g5_19; + int64_t f9g6_19 = f9 * (int64_t) g6_19; + int64_t f9g7_38 = f9_2 * (int64_t) g7_19; + int64_t f9g8_19 = f9 * (int64_t) g8_19; + int64_t f9g9_38 = f9_2 * (int64_t) g9_19; + int64_t h0 = f0g0+f1g9_38+f2g8_19+f3g7_38+f4g6_19+f5g5_38+f6g4_19+f7g3_38+f8g2_19+f9g1_38; + int64_t h1 = f0g1+f1g0 +f2g9_19+f3g8_19+f4g7_19+f5g6_19+f6g5_19+f7g4_19+f8g3_19+f9g2_19; + int64_t h2 = f0g2+f1g1_2 +f2g0 +f3g9_38+f4g8_19+f5g7_38+f6g6_19+f7g5_38+f8g4_19+f9g3_38; + int64_t h3 = f0g3+f1g2 +f2g1 +f3g0 +f4g9_19+f5g8_19+f6g7_19+f7g6_19+f8g5_19+f9g4_19; + int64_t h4 = f0g4+f1g3_2 +f2g2 +f3g1_2 +f4g0 +f5g9_38+f6g8_19+f7g7_38+f8g6_19+f9g5_38; + int64_t h5 = f0g5+f1g4 +f2g3 +f3g2 +f4g1 +f5g0 +f6g9_19+f7g8_19+f8g7_19+f9g6_19; + int64_t h6 = f0g6+f1g5_2 +f2g4 +f3g3_2 +f4g2 +f5g1_2 +f6g0 +f7g9_38+f8g8_19+f9g7_38; + int64_t h7 = f0g7+f1g6 +f2g5 +f3g4 +f4g3 +f5g2 +f6g1 +f7g0 +f8g9_19+f9g8_19; + int64_t h8 = f0g8+f1g7_2 +f2g6 +f3g5_2 +f4g4 +f5g3_2 +f6g2 +f7g1_2 +f8g0 +f9g9_38; + int64_t h9 = f0g9+f1g8 +f2g7 +f3g6 +f4g5 +f5g4 +f6g3 +f7g2 +f8g1 +f9g0 ; + int64_t carry0; + int64_t carry1; + int64_t carry2; + int64_t carry3; + int64_t carry4; + int64_t carry5; + int64_t carry6; + int64_t carry7; + int64_t carry8; + int64_t carry9; + + /* + |h0| <= (1.65*1.65*2^52*(1+19+19+19+19)+1.65*1.65*2^50*(38+38+38+38+38)) + i.e. |h0| <= 1.4*2^60; narrower ranges for h2, h4, h6, h8 + |h1| <= (1.65*1.65*2^51*(1+1+19+19+19+19+19+19+19+19)) + i.e. |h1| <= 1.7*2^59; narrower ranges for h3, h5, h7, h9 + */ + + carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; + carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; + /* |h0| <= 2^25 */ + /* |h4| <= 2^25 */ + /* |h1| <= 1.71*2^59 */ + /* |h5| <= 1.71*2^59 */ + + carry1 = (h1 + (int64_t) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25; + carry5 = (h5 + (int64_t) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25; + /* |h1| <= 2^24; from now on fits into int32 */ + /* |h5| <= 2^24; from now on fits into int32 */ + /* |h2| <= 1.41*2^60 */ + /* |h6| <= 1.41*2^60 */ + + carry2 = (h2 + (int64_t) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26; + carry6 = (h6 + (int64_t) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26; + /* |h2| <= 2^25; from now on fits into int32 unchanged */ + /* |h6| <= 2^25; from now on fits into int32 unchanged */ + /* |h3| <= 1.71*2^59 */ + /* |h7| <= 1.71*2^59 */ + + carry3 = (h3 + (int64_t) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25; + carry7 = (h7 + (int64_t) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25; + /* |h3| <= 2^24; from now on fits into int32 unchanged */ + /* |h7| <= 2^24; from now on fits into int32 unchanged */ + /* |h4| <= 1.72*2^34 */ + /* |h8| <= 1.41*2^60 */ + + carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; + carry8 = (h8 + (int64_t) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26; + /* |h4| <= 2^25; from now on fits into int32 unchanged */ + /* |h8| <= 2^25; from now on fits into int32 unchanged */ + /* |h5| <= 1.01*2^24 */ + /* |h9| <= 1.71*2^59 */ + + carry9 = (h9 + (int64_t) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; + /* |h9| <= 2^24; from now on fits into int32 unchanged */ + /* |h0| <= 1.1*2^39 */ + + carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; + /* |h0| <= 2^25; from now on fits into int32 unchanged */ + /* |h1| <= 1.01*2^24 */ + + h[0] = (int32_t)h0; + h[1] = (int32_t)h1; + h[2] = (int32_t)h2; + h[3] = (int32_t)h3; + h[4] = (int32_t)h4; + h[5] = (int32_t)h5; + h[6] = (int32_t)h6; + h[7] = (int32_t)h7; + h[8] = (int32_t)h8; + h[9] = (int32_t)h9; +} + + +/* +Replace (f,g) with (g,f) if b == 1; +replace (f,g) with (f,g) if b == 0. + +Preconditions: b in {0,1}. +*/ + +void fe_cswap(fe f, fe g, int b) +{ + int32_t f0 = f[0]; + int32_t f1 = f[1]; + int32_t f2 = f[2]; + int32_t f3 = f[3]; + int32_t f4 = f[4]; + int32_t f5 = f[5]; + int32_t f6 = f[6]; + int32_t f7 = f[7]; + int32_t f8 = f[8]; + int32_t f9 = f[9]; + int32_t g0 = g[0]; + int32_t g1 = g[1]; + int32_t g2 = g[2]; + int32_t g3 = g[3]; + int32_t g4 = g[4]; + int32_t g5 = g[5]; + int32_t g6 = g[6]; + int32_t g7 = g[7]; + int32_t g8 = g[8]; + int32_t g9 = g[9]; + int32_t x0 = f0 ^ g0; + int32_t x1 = f1 ^ g1; + int32_t x2 = f2 ^ g2; + int32_t x3 = f3 ^ g3; + int32_t x4 = f4 ^ g4; + int32_t x5 = f5 ^ g5; + int32_t x6 = f6 ^ g6; + int32_t x7 = f7 ^ g7; + int32_t x8 = f8 ^ g8; + int32_t x9 = f9 ^ g9; + b = -b; + x0 &= b; + x1 &= b; + x2 &= b; + x3 &= b; + x4 &= b; + x5 &= b; + x6 &= b; + x7 &= b; + x8 &= b; + x9 &= b; + f[0] = f0 ^ x0; + f[1] = f1 ^ x1; + f[2] = f2 ^ x2; + f[3] = f3 ^ x3; + f[4] = f4 ^ x4; + f[5] = f5 ^ x5; + f[6] = f6 ^ x6; + f[7] = f7 ^ x7; + f[8] = f8 ^ x8; + f[9] = f9 ^ x9; + g[0] = g0 ^ x0; + g[1] = g1 ^ x1; + g[2] = g2 ^ x2; + g[3] = g3 ^ x3; + g[4] = g4 ^ x4; + g[5] = g5 ^ x5; + g[6] = g6 ^ x6; + g[7] = g7 ^ x7; + g[8] = g8 ^ x8; + g[9] = g9 ^ x9; +} + + +/* +h = f * 121666 +Can overlap h with f. + +Preconditions: + |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. + +Postconditions: + |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. +*/ + +void fe_mul121666(fe h,fe f) +{ + int32_t f0 = f[0]; + int32_t f1 = f[1]; + int32_t f2 = f[2]; + int32_t f3 = f[3]; + int32_t f4 = f[4]; + int32_t f5 = f[5]; + int32_t f6 = f[6]; + int32_t f7 = f[7]; + int32_t f8 = f[8]; + int32_t f9 = f[9]; + int64_t h0 = f0 * (int64_t) 121666; + int64_t h1 = f1 * (int64_t) 121666; + int64_t h2 = f2 * (int64_t) 121666; + int64_t h3 = f3 * (int64_t) 121666; + int64_t h4 = f4 * (int64_t) 121666; + int64_t h5 = f5 * (int64_t) 121666; + int64_t h6 = f6 * (int64_t) 121666; + int64_t h7 = f7 * (int64_t) 121666; + int64_t h8 = f8 * (int64_t) 121666; + int64_t h9 = f9 * (int64_t) 121666; + int64_t carry0; + int64_t carry1; + int64_t carry2; + int64_t carry3; + int64_t carry4; + int64_t carry5; + int64_t carry6; + int64_t carry7; + int64_t carry8; + int64_t carry9; + + carry9 = (h9 + (int64_t) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; + carry1 = (h1 + (int64_t) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25; + carry3 = (h3 + (int64_t) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25; + carry5 = (h5 + (int64_t) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25; + carry7 = (h7 + (int64_t) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25; + + carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; + carry2 = (h2 + (int64_t) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26; + carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; + carry6 = (h6 + (int64_t) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26; + carry8 = (h8 + (int64_t) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26; + + h[0] = (int32_t)h0; + h[1] = (int32_t)h1; + h[2] = (int32_t)h2; + h[3] = (int32_t)h3; + h[4] = (int32_t)h4; + h[5] = (int32_t)h5; + h[6] = (int32_t)h6; + h[7] = (int32_t)h7; + h[8] = (int32_t)h8; + h[9] = (int32_t)h9; +} + + +/* +h = 2 * f * f +Can overlap h with f. + +Preconditions: + |f| bounded by 1.65*2^26,1.65*2^25,1.65*2^26,1.65*2^25,etc. + +Postconditions: + |h| bounded by 1.01*2^25,1.01*2^24,1.01*2^25,1.01*2^24,etc. +*/ + +/* +See fe_mul.c for discussion of implementation strategy. +*/ + +void fe_sq2(fe h,const fe f) +{ + int32_t f0 = f[0]; + int32_t f1 = f[1]; + int32_t f2 = f[2]; + int32_t f3 = f[3]; + int32_t f4 = f[4]; + int32_t f5 = f[5]; + int32_t f6 = f[6]; + int32_t f7 = f[7]; + int32_t f8 = f[8]; + int32_t f9 = f[9]; + int32_t f0_2 = 2 * f0; + int32_t f1_2 = 2 * f1; + int32_t f2_2 = 2 * f2; + int32_t f3_2 = 2 * f3; + int32_t f4_2 = 2 * f4; + int32_t f5_2 = 2 * f5; + int32_t f6_2 = 2 * f6; + int32_t f7_2 = 2 * f7; + int32_t f5_38 = 38 * f5; /* 1.959375*2^30 */ + int32_t f6_19 = 19 * f6; /* 1.959375*2^30 */ + int32_t f7_38 = 38 * f7; /* 1.959375*2^30 */ + int32_t f8_19 = 19 * f8; /* 1.959375*2^30 */ + int32_t f9_38 = 38 * f9; /* 1.959375*2^30 */ + int64_t f0f0 = f0 * (int64_t) f0; + int64_t f0f1_2 = f0_2 * (int64_t) f1; + int64_t f0f2_2 = f0_2 * (int64_t) f2; + int64_t f0f3_2 = f0_2 * (int64_t) f3; + int64_t f0f4_2 = f0_2 * (int64_t) f4; + int64_t f0f5_2 = f0_2 * (int64_t) f5; + int64_t f0f6_2 = f0_2 * (int64_t) f6; + int64_t f0f7_2 = f0_2 * (int64_t) f7; + int64_t f0f8_2 = f0_2 * (int64_t) f8; + int64_t f0f9_2 = f0_2 * (int64_t) f9; + int64_t f1f1_2 = f1_2 * (int64_t) f1; + int64_t f1f2_2 = f1_2 * (int64_t) f2; + int64_t f1f3_4 = f1_2 * (int64_t) f3_2; + int64_t f1f4_2 = f1_2 * (int64_t) f4; + int64_t f1f5_4 = f1_2 * (int64_t) f5_2; + int64_t f1f6_2 = f1_2 * (int64_t) f6; + int64_t f1f7_4 = f1_2 * (int64_t) f7_2; + int64_t f1f8_2 = f1_2 * (int64_t) f8; + int64_t f1f9_76 = f1_2 * (int64_t) f9_38; + int64_t f2f2 = f2 * (int64_t) f2; + int64_t f2f3_2 = f2_2 * (int64_t) f3; + int64_t f2f4_2 = f2_2 * (int64_t) f4; + int64_t f2f5_2 = f2_2 * (int64_t) f5; + int64_t f2f6_2 = f2_2 * (int64_t) f6; + int64_t f2f7_2 = f2_2 * (int64_t) f7; + int64_t f2f8_38 = f2_2 * (int64_t) f8_19; + int64_t f2f9_38 = f2 * (int64_t) f9_38; + int64_t f3f3_2 = f3_2 * (int64_t) f3; + int64_t f3f4_2 = f3_2 * (int64_t) f4; + int64_t f3f5_4 = f3_2 * (int64_t) f5_2; + int64_t f3f6_2 = f3_2 * (int64_t) f6; + int64_t f3f7_76 = f3_2 * (int64_t) f7_38; + int64_t f3f8_38 = f3_2 * (int64_t) f8_19; + int64_t f3f9_76 = f3_2 * (int64_t) f9_38; + int64_t f4f4 = f4 * (int64_t) f4; + int64_t f4f5_2 = f4_2 * (int64_t) f5; + int64_t f4f6_38 = f4_2 * (int64_t) f6_19; + int64_t f4f7_38 = f4 * (int64_t) f7_38; + int64_t f4f8_38 = f4_2 * (int64_t) f8_19; + int64_t f4f9_38 = f4 * (int64_t) f9_38; + int64_t f5f5_38 = f5 * (int64_t) f5_38; + int64_t f5f6_38 = f5_2 * (int64_t) f6_19; + int64_t f5f7_76 = f5_2 * (int64_t) f7_38; + int64_t f5f8_38 = f5_2 * (int64_t) f8_19; + int64_t f5f9_76 = f5_2 * (int64_t) f9_38; + int64_t f6f6_19 = f6 * (int64_t) f6_19; + int64_t f6f7_38 = f6 * (int64_t) f7_38; + int64_t f6f8_38 = f6_2 * (int64_t) f8_19; + int64_t f6f9_38 = f6 * (int64_t) f9_38; + int64_t f7f7_38 = f7 * (int64_t) f7_38; + int64_t f7f8_38 = f7_2 * (int64_t) f8_19; + int64_t f7f9_76 = f7_2 * (int64_t) f9_38; + int64_t f8f8_19 = f8 * (int64_t) f8_19; + int64_t f8f9_38 = f8 * (int64_t) f9_38; + int64_t f9f9_38 = f9 * (int64_t) f9_38; + int64_t h0 = f0f0 +f1f9_76+f2f8_38+f3f7_76+f4f6_38+f5f5_38; + int64_t h1 = f0f1_2+f2f9_38+f3f8_38+f4f7_38+f5f6_38; + int64_t h2 = f0f2_2+f1f1_2 +f3f9_76+f4f8_38+f5f7_76+f6f6_19; + int64_t h3 = f0f3_2+f1f2_2 +f4f9_38+f5f8_38+f6f7_38; + int64_t h4 = f0f4_2+f1f3_4 +f2f2 +f5f9_76+f6f8_38+f7f7_38; + int64_t h5 = f0f5_2+f1f4_2 +f2f3_2 +f6f9_38+f7f8_38; + int64_t h6 = f0f6_2+f1f5_4 +f2f4_2 +f3f3_2 +f7f9_76+f8f8_19; + int64_t h7 = f0f7_2+f1f6_2 +f2f5_2 +f3f4_2 +f8f9_38; + int64_t h8 = f0f8_2+f1f7_4 +f2f6_2 +f3f5_4 +f4f4 +f9f9_38; + int64_t h9 = f0f9_2+f1f8_2 +f2f7_2 +f3f6_2 +f4f5_2; + int64_t carry0; + int64_t carry1; + int64_t carry2; + int64_t carry3; + int64_t carry4; + int64_t carry5; + int64_t carry6; + int64_t carry7; + int64_t carry8; + int64_t carry9; + + h0 += h0; + h1 += h1; + h2 += h2; + h3 += h3; + h4 += h4; + h5 += h5; + h6 += h6; + h7 += h7; + h8 += h8; + h9 += h9; + + carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; + carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; + + carry1 = (h1 + (int64_t) (1<<24)) >> 25; h2 += carry1; h1 -= carry1 << 25; + carry5 = (h5 + (int64_t) (1<<24)) >> 25; h6 += carry5; h5 -= carry5 << 25; + + carry2 = (h2 + (int64_t) (1<<25)) >> 26; h3 += carry2; h2 -= carry2 << 26; + carry6 = (h6 + (int64_t) (1<<25)) >> 26; h7 += carry6; h6 -= carry6 << 26; + + carry3 = (h3 + (int64_t) (1<<24)) >> 25; h4 += carry3; h3 -= carry3 << 25; + carry7 = (h7 + (int64_t) (1<<24)) >> 25; h8 += carry7; h7 -= carry7 << 25; + + carry4 = (h4 + (int64_t) (1<<25)) >> 26; h5 += carry4; h4 -= carry4 << 26; + carry8 = (h8 + (int64_t) (1<<25)) >> 26; h9 += carry8; h8 -= carry8 << 26; + + carry9 = (h9 + (int64_t) (1<<24)) >> 25; h0 += carry9 * 19; h9 -= carry9 << 25; + + carry0 = (h0 + (int64_t) (1<<25)) >> 26; h1 += carry0; h0 -= carry0 << 26; + + h[0] = (int32_t)h0; + h[1] = (int32_t)h1; + h[2] = (int32_t)h2; + h[3] = (int32_t)h3; + h[4] = (int32_t)h4; + h[5] = (int32_t)h5; + h[6] = (int32_t)h6; + h[7] = (int32_t)h7; + h[8] = (int32_t)h8; + h[9] = (int32_t)h9; +} + + +void fe_pow22523(fe out,const fe z) +{ + fe t0; + fe t1; + fe t2; + int i; + + fe_sq(t0,z); for (i = 1;i < 1;++i) fe_sq(t0,t0); + fe_sq(t1,t0); for (i = 1;i < 2;++i) fe_sq(t1,t1); + fe_mul(t1,z,t1); + fe_mul(t0,t0,t1); + fe_sq(t0,t0); for (i = 1;i < 1;++i) fe_sq(t0,t0); + fe_mul(t0,t1,t0); + fe_sq(t1,t0); for (i = 1;i < 5;++i) fe_sq(t1,t1); + fe_mul(t0,t1,t0); + fe_sq(t1,t0); for (i = 1;i < 10;++i) fe_sq(t1,t1); + fe_mul(t1,t1,t0); + fe_sq(t2,t1); for (i = 1;i < 20;++i) fe_sq(t2,t2); + fe_mul(t1,t2,t1); + fe_sq(t1,t1); for (i = 1;i < 10;++i) fe_sq(t1,t1); + fe_mul(t0,t1,t0); + fe_sq(t1,t0); for (i = 1;i < 50;++i) fe_sq(t1,t1); + fe_mul(t1,t1,t0); + fe_sq(t2,t1); for (i = 1;i < 100;++i) fe_sq(t2,t2); + fe_mul(t1,t2,t1); + fe_sq(t1,t1); for (i = 1;i < 50;++i) fe_sq(t1,t1); + fe_mul(t0,t1,t0); + fe_sq(t0,t0); for (i = 1;i < 2;++i) fe_sq(t0,t0); + fe_mul(out,t0,z); + + return; +} + + +/* +h = -f + +Preconditions: + |f| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. + +Postconditions: + |h| bounded by 1.1*2^25,1.1*2^24,1.1*2^25,1.1*2^24,etc. +*/ + +void fe_neg(fe h,const fe f) +{ + int32_t f0 = f[0]; + int32_t f1 = f[1]; + int32_t f2 = f[2]; + int32_t f3 = f[3]; + int32_t f4 = f[4]; + int32_t f5 = f[5]; + int32_t f6 = f[6]; + int32_t f7 = f[7]; + int32_t f8 = f[8]; + int32_t f9 = f[9]; + int32_t h0 = -f0; + int32_t h1 = -f1; + int32_t h2 = -f2; + int32_t h3 = -f3; + int32_t h4 = -f4; + int32_t h5 = -f5; + int32_t h6 = -f6; + int32_t h7 = -f7; + int32_t h8 = -f8; + int32_t h9 = -f9; + h[0] = h0; + h[1] = h1; + h[2] = h2; + h[3] = h3; + h[4] = h4; + h[5] = h5; + h[6] = h6; + h[7] = h7; + h[8] = h8; + h[9] = h9; +} + + +/* +Preconditions: + |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. +*/ + +static const unsigned char zero[32] = {0}; + +int fe_isnonzero(const fe f) +{ + unsigned char s[32]; + fe_tobytes(s,f); + return ConstantCompare(s,zero,32); +} + + +/* +return 1 if f is in {1,3,5,...,q-2} +return 0 if f is in {0,2,4,...,q-1} + +Preconditions: + |f| bounded by 1.1*2^26,1.1*2^25,1.1*2^26,1.1*2^25,etc. +*/ + +int fe_isnegative(const fe f) +{ + unsigned char s[32]; + fe_tobytes(s,f); + return s[0] & 1; +} + + +/* +Replace (f,g) with (g,g) if b == 1; +replace (f,g) with (f,g) if b == 0. + +Preconditions: b in {0,1}. +*/ + +void fe_cmov(fe f, const fe g, int b) +{ + int32_t f0 = f[0]; + int32_t f1 = f[1]; + int32_t f2 = f[2]; + int32_t f3 = f[3]; + int32_t f4 = f[4]; + int32_t f5 = f[5]; + int32_t f6 = f[6]; + int32_t f7 = f[7]; + int32_t f8 = f[8]; + int32_t f9 = f[9]; + int32_t g0 = g[0]; + int32_t g1 = g[1]; + int32_t g2 = g[2]; + int32_t g3 = g[3]; + int32_t g4 = g[4]; + int32_t g5 = g[5]; + int32_t g6 = g[6]; + int32_t g7 = g[7]; + int32_t g8 = g[8]; + int32_t g9 = g[9]; + int32_t x0 = f0 ^ g0; + int32_t x1 = f1 ^ g1; + int32_t x2 = f2 ^ g2; + int32_t x3 = f3 ^ g3; + int32_t x4 = f4 ^ g4; + int32_t x5 = f5 ^ g5; + int32_t x6 = f6 ^ g6; + int32_t x7 = f7 ^ g7; + int32_t x8 = f8 ^ g8; + int32_t x9 = f9 ^ g9; + b = -b; + x0 &= b; + x1 &= b; + x2 &= b; + x3 &= b; + x4 &= b; + x5 &= b; + x6 &= b; + x7 &= b; + x8 &= b; + x9 &= b; + f[0] = f0 ^ x0; + f[1] = f1 ^ x1; + f[2] = f2 ^ x2; + f[3] = f3 ^ x3; + f[4] = f4 ^ x4; + f[5] = f5 ^ x5; + f[6] = f6 ^ x6; + f[7] = f7 ^ x7; + f[8] = f8 ^ x8; + f[9] = f9 ^ x9; +} +#endif + +#endif /* !CURVE25519_SMALL || !ED25519_SMALL */ +#endif /* HAVE_CURVE25519 || HAVE_ED25519 */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/fe_x25519_128.i b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fe_x25519_128.i new file mode 100755 index 0000000..0e74750 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fe_x25519_128.i @@ -0,0 +1,625 @@ +/* fe_x25519_128.i + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +void fe_init(void) +{ +} + +/* Convert a number represented as an array of bytes to an array of words with + * 51-bits of data in each word. + * + * in An array of bytes. + * out An array of words. + */ +void fe_frombytes(fe out, const unsigned char *in) +{ + out[0] = (((int64_t)((in[ 0] ) )) ) + | (((int64_t)((in[ 1] ) )) << 8) + | (((int64_t)((in[ 2] ) )) << 16) + | (((int64_t)((in[ 3] ) )) << 24) + | (((int64_t)((in[ 4] ) )) << 32) + | (((int64_t)((in[ 5] ) )) << 40) + | (((int64_t)((in[ 6] ) & 0x07)) << 48); + out[1] = (((int64_t)((in[ 6] >> 3) & 0x1f)) ) + | (((int64_t)((in[ 7] ) )) << 5) + | (((int64_t)((in[ 8] ) )) << 13) + | (((int64_t)((in[ 9] ) )) << 21) + | (((int64_t)((in[10] ) )) << 29) + | (((int64_t)((in[11] ) )) << 37) + | (((int64_t)((in[12] ) & 0x3f)) << 45); + out[2] = (((int64_t)((in[12] >> 6) & 0x03)) ) + | (((int64_t)((in[13] ) )) << 2) + | (((int64_t)((in[14] ) )) << 10) + | (((int64_t)((in[15] ) )) << 18) + | (((int64_t)((in[16] ) )) << 26) + | (((int64_t)((in[17] ) )) << 34) + | (((int64_t)((in[18] ) )) << 42) + | (((int64_t)((in[19] ) & 0x01)) << 50); + out[3] = (((int64_t)((in[19] >> 1) & 0x7f)) ) + | (((int64_t)((in[20] ) )) << 7) + | (((int64_t)((in[21] ) )) << 15) + | (((int64_t)((in[22] ) )) << 23) + | (((int64_t)((in[23] ) )) << 31) + | (((int64_t)((in[24] ) )) << 39) + | (((int64_t)((in[25] ) & 0x0f)) << 47); + out[4] = (((int64_t)((in[25] >> 4) & 0x0f)) ) + | (((int64_t)((in[26] ) )) << 4) + | (((int64_t)((in[27] ) )) << 12) + | (((int64_t)((in[28] ) )) << 20) + | (((int64_t)((in[29] ) )) << 28) + | (((int64_t)((in[30] ) )) << 36) + | (((int64_t)((in[31] ) & 0x7f)) << 44); +} + +/* Convert a number represented as an array of words to an array of bytes. + * The array of words is normalized to an array of 51-bit data words and if + * greater than the mod, modulo reduced by the prime 2^255 - 1. + * + * n An array of words. + * out An array of bytes. + */ +void fe_tobytes(unsigned char *out, const fe n) +{ + fe in; + int64_t c; + + in[0] = n[0]; + in[1] = n[1]; + in[2] = n[2]; + in[3] = n[3]; + in[4] = n[4]; + + /* Normalize to 51-bits of data per word. */ + in[0] += (in[4] >> 51) * 19; in[4] &= 0x7ffffffffffff; + + in[1] += in[0] >> 51; in[0] &= 0x7ffffffffffff; + in[2] += in[1] >> 51; in[1] &= 0x7ffffffffffff; + in[3] += in[2] >> 51; in[2] &= 0x7ffffffffffff; + in[4] += in[3] >> 51; in[3] &= 0x7ffffffffffff; + in[0] += (in[4] >> 51) * 19; + in[4] &= 0x7ffffffffffff; + + c = (in[0] + 19) >> 51; + c = (in[1] + c) >> 51; + c = (in[2] + c) >> 51; + c = (in[3] + c) >> 51; + c = (in[4] + c) >> 51; + in[0] += c * 19; + in[1] += in[0] >> 51; in[0] &= 0x7ffffffffffff; + in[2] += in[1] >> 51; in[1] &= 0x7ffffffffffff; + in[3] += in[2] >> 51; in[2] &= 0x7ffffffffffff; + in[4] += in[3] >> 51; in[3] &= 0x7ffffffffffff; + in[4] &= 0x7ffffffffffff; + + out[ 0] = (((byte)((in[0] ) )) ); + out[ 1] = (((byte)((in[0] >> 8) )) ); + out[ 2] = (((byte)((in[0] >> 16) )) ); + out[ 3] = (((byte)((in[0] >> 24) )) ); + out[ 4] = (((byte)((in[0] >> 32) )) ); + out[ 5] = (((byte)((in[0] >> 40) )) ); + out[ 6] = (((byte)((in[0] >> 48) & 0x07)) ) + | (((byte)((in[1] ) & 0x1f)) << 3); + out[ 7] = (((byte)((in[1] >> 5) )) ); + out[ 8] = (((byte)((in[1] >> 13) )) ); + out[ 9] = (((byte)((in[1] >> 21) )) ); + out[10] = (((byte)((in[1] >> 29) )) ); + out[11] = (((byte)((in[1] >> 37) )) ); + out[12] = (((byte)((in[1] >> 45) & 0x3f)) ) + | (((byte)((in[2] ) & 0x03)) << 6); + out[13] = (((byte)((in[2] >> 2) )) ); + out[14] = (((byte)((in[2] >> 10) )) ); + out[15] = (((byte)((in[2] >> 18) )) ); + out[16] = (((byte)((in[2] >> 26) )) ); + out[17] = (((byte)((in[2] >> 34) )) ); + out[18] = (((byte)((in[2] >> 42) )) ); + out[19] = (((byte)((in[2] >> 50) & 0x01)) ) + | (((byte)((in[3] ) & 0x7f)) << 1); + out[20] = (((byte)((in[3] >> 7) )) ); + out[21] = (((byte)((in[3] >> 15) )) ); + out[22] = (((byte)((in[3] >> 23) )) ); + out[23] = (((byte)((in[3] >> 31) )) ); + out[24] = (((byte)((in[3] >> 39) )) ); + out[25] = (((byte)((in[3] >> 47) & 0x0f)) ) + | (((byte)((in[4] ) & 0x0f)) << 4); + out[26] = (((byte)((in[4] >> 4) )) ); + out[27] = (((byte)((in[4] >> 12) )) ); + out[28] = (((byte)((in[4] >> 20) )) ); + out[29] = (((byte)((in[4] >> 28) )) ); + out[30] = (((byte)((in[4] >> 36) )) ); + out[31] = (((byte)((in[4] >> 44) & 0x7f)) ); +} + +/* Set the field element to 1. + * + * n The field element number. + */ +void fe_1(fe n) +{ + n[0] = 0x0000000000001; + n[1] = 0x0000000000000; + n[2] = 0x0000000000000; + n[3] = 0x0000000000000; + n[4] = 0x0000000000000; +} + +/* Set the field element to 0. + * + * n The field element number. + */ +void fe_0(fe n) +{ + n[0] = 0x0000000000000; + n[1] = 0x0000000000000; + n[2] = 0x0000000000000; + n[3] = 0x0000000000000; + n[4] = 0x0000000000000; +} + +/* Copy field element a into field element r. + * + * r Field element to copy into. + * a Field element to copy. + */ +void fe_copy(fe r, const fe a) +{ + r[0] = a[0]; + r[1] = a[1]; + r[2] = a[2]; + r[3] = a[3]; + r[4] = a[4]; +} + +/* Constant time, conditional swap of field elements a and b. + * + * a A field element. + * b A field element. + * c If 1 then swap and if 0 then don't swap. + */ +void fe_cswap(fe a, fe b, int c) +{ + int64_t m = c; + int64_t t0, t1, t2, t3, t4; + + /* Convert conditional into mask. */ + m = -m; + t0 = m & (a[0] ^ b[0]); + t1 = m & (a[1] ^ b[1]); + t2 = m & (a[2] ^ b[2]); + t3 = m & (a[3] ^ b[3]); + t4 = m & (a[4] ^ b[4]); + + a[0] ^= t0; + a[1] ^= t1; + a[2] ^= t2; + a[3] ^= t3; + a[4] ^= t4; + + b[0] ^= t0; + b[1] ^= t1; + b[2] ^= t2; + b[3] ^= t3; + b[4] ^= t4; +} + +/* Subtract b from a into r. (r = a - b) + * + * r A field element. + * a A field element. + * b A field element. + */ +void fe_sub(fe r, const fe a, const fe b) +{ + r[0] = a[0] - b[0]; + r[1] = a[1] - b[1]; + r[2] = a[2] - b[2]; + r[3] = a[3] - b[3]; + r[4] = a[4] - b[4]; +} + +/* Add b to a into r. (r = a + b) + * + * r A field element. + * a A field element. + * b A field element. + */ +void fe_add(fe r, const fe a, const fe b) +{ + r[0] = a[0] + b[0]; + r[1] = a[1] + b[1]; + r[2] = a[2] + b[2]; + r[3] = a[3] + b[3]; + r[4] = a[4] + b[4]; +} + +/* Multiply a and b into r. (r = a * b) + * + * r A field element. + * a A field element. + * b A field element. + */ +void fe_mul(fe r, const fe a, const fe b) +{ + const __int128_t k19 = 19; + __int128_t t0 = ((__int128_t)a[0]) * b[0]; + __int128_t t1 = ((__int128_t)a[0]) * b[1] + + ((__int128_t)a[1]) * b[0]; + __int128_t t2 = ((__int128_t)a[0]) * b[2] + + ((__int128_t)a[1]) * b[1] + + ((__int128_t)a[2]) * b[0]; + __int128_t t3 = ((__int128_t)a[0]) * b[3] + + ((__int128_t)a[1]) * b[2] + + ((__int128_t)a[2]) * b[1] + + ((__int128_t)a[3]) * b[0]; + __int128_t t4 = ((__int128_t)a[0]) * b[4] + + ((__int128_t)a[1]) * b[3] + + ((__int128_t)a[2]) * b[2] + + ((__int128_t)a[3]) * b[1] + + ((__int128_t)a[4]) * b[0]; + __int128_t t5 = ((__int128_t)a[1]) * b[4] + + ((__int128_t)a[2]) * b[3] + + ((__int128_t)a[3]) * b[2] + + ((__int128_t)a[4]) * b[1]; + __int128_t t6 = ((__int128_t)a[2]) * b[4] + + ((__int128_t)a[3]) * b[3] + + ((__int128_t)a[4]) * b[2]; + __int128_t t7 = ((__int128_t)a[3]) * b[4] + + ((__int128_t)a[4]) * b[3]; + __int128_t t8 = ((__int128_t)a[4]) * b[4]; + + /* Modulo reduce double long word. */ + t0 += t5 * k19; + t1 += t6 * k19; + t2 += t7 * k19; + t3 += t8 * k19; + + /* Normalize to 51-bits of data per word. */ + t0 += (t4 >> 51) * k19; t4 &= 0x7ffffffffffff; + + t1 += t0 >> 51; r[0] = t0 & 0x7ffffffffffff; + t2 += t1 >> 51; r[1] = t1 & 0x7ffffffffffff; + t3 += t2 >> 51; r[2] = t2 & 0x7ffffffffffff; + t4 += t3 >> 51; r[3] = t3 & 0x7ffffffffffff; + r[0] += (t4 >> 51) * k19; + r[4] = t4 & 0x7ffffffffffff; +} + +/* Square a and put result in r. (r = a * a) + * + * r A field element. + * a A field element. + * b A field element. + */ +void fe_sq(fe r, const fe a) +{ + const __int128_t k19 = 19; + const __int128_t k2 = 2; + __int128_t t0 = ((__int128_t)a[0]) * a[0]; + __int128_t t1 = ((__int128_t)a[0]) * a[1] * k2; + __int128_t t2 = ((__int128_t)a[0]) * a[2] * k2 + + ((__int128_t)a[1]) * a[1]; + __int128_t t3 = ((__int128_t)a[0]) * a[3] * k2 + + ((__int128_t)a[1]) * a[2] * k2; + __int128_t t4 = ((__int128_t)a[0]) * a[4] * k2 + + ((__int128_t)a[1]) * a[3] * k2 + + ((__int128_t)a[2]) * a[2]; + __int128_t t5 = ((__int128_t)a[1]) * a[4] * k2 + + ((__int128_t)a[2]) * a[3] * k2; + __int128_t t6 = ((__int128_t)a[2]) * a[4] * k2 + + ((__int128_t)a[3]) * a[3]; + __int128_t t7 = ((__int128_t)a[3]) * a[4] * k2; + __int128_t t8 = ((__int128_t)a[4]) * a[4]; + + /* Modulo reduce double long word. */ + t0 += t5 * k19; + t1 += t6 * k19; + t2 += t7 * k19; + t3 += t8 * k19; + + /* Normalize to 51-bits of data per word. */ + t0 += (t4 >> 51) * k19; t4 &= 0x7ffffffffffff; + + t1 += t0 >> 51; r[0] = t0 & 0x7ffffffffffff; + t2 += t1 >> 51; r[1] = t1 & 0x7ffffffffffff; + t3 += t2 >> 51; r[2] = t2 & 0x7ffffffffffff; + t4 += t3 >> 51; r[3] = t3 & 0x7ffffffffffff; + r[0] += (t4 >> 51) * k19; + r[4] = t4 & 0x7ffffffffffff; +} + +/* Multiply a by 121666 and put result in r. (r = 121666 * a) + * + * r A field element. + * a A field element. + * b A field element. + */ +void fe_mul121666(fe r, fe a) +{ + const __int128_t k19 = 19; + const __int128_t k121666 = 121666; + __int128_t t0 = ((__int128_t)a[0]) * k121666; + __int128_t t1 = ((__int128_t)a[1]) * k121666; + __int128_t t2 = ((__int128_t)a[2]) * k121666; + __int128_t t3 = ((__int128_t)a[3]) * k121666; + __int128_t t4 = ((__int128_t)a[4]) * k121666; + + /* Normalize to 51-bits of data per word. */ + t0 += (t4 >> 51) * k19; t4 &= 0x7ffffffffffff; + + t1 += t0 >> 51; r[0] = t0 & 0x7ffffffffffff; + t2 += t1 >> 51; r[1] = t1 & 0x7ffffffffffff; + t3 += t2 >> 51; r[2] = t2 & 0x7ffffffffffff; + t4 += t3 >> 51; r[3] = t3 & 0x7ffffffffffff; + r[0] += (t4 >> 51) * k19; + r[4] = t4 & 0x7ffffffffffff; +} + +/* Find the inverse of a modulo 2^255 - 1 and put result in r. + * (r * a) mod (2^255 - 1) = 1 + * Implementation is constant time. + * + * r A field element. + * a A field element. + */ +void fe_invert(fe r, const fe a) +{ + fe t0, t1, t2, t3; + int i; + + /* a ^ (2^255 - 21) */ + fe_sq(t0, a); for (i = 1; i < 1; ++i) fe_sq(t0, t0); + fe_sq(t1, t0); for (i = 1; i < 2; ++i) fe_sq(t1, t1); fe_mul(t1, a, t1); + fe_mul(t0, t0, t1); + fe_sq(t2, t0); for (i = 1; i < 1; ++i) fe_sq(t2, t2); fe_mul(t1, t1, t2); + fe_sq(t2, t1); for (i = 1; i < 5; ++i) fe_sq(t2, t2); fe_mul(t1, t2, t1); + fe_sq(t2, t1); for (i = 1; i < 10; ++i) fe_sq(t2, t2); fe_mul(t2, t2, t1); + fe_sq(t3, t2); for (i = 1; i < 20; ++i) fe_sq(t3, t3); fe_mul(t2, t3, t2); + fe_sq(t2, t2); for (i = 1; i < 10; ++i) fe_sq(t2, t2); fe_mul(t1, t2, t1); + fe_sq(t2, t1); for (i = 1; i < 50; ++i) fe_sq(t2, t2); fe_mul(t2, t2, t1); + fe_sq(t3, t2); for (i = 1; i < 100; ++i) fe_sq(t3, t3); fe_mul(t2, t3, t2); + fe_sq(t2, t2); for (i = 1; i < 50; ++i) fe_sq(t2, t2); fe_mul(t1, t2, t1); + fe_sq(t1, t1); for (i = 1; i < 5; ++i) fe_sq(t1, t1); fe_mul( r, t1, t0); +} + +#ifndef CURVE25519_SMALL +/* Scalar multiply the field element a by n using Montgomery Ladder and places + * result in r. + * + * r A field element as an array of bytes. + * n The scalar as an array of bytes. + * a A field element as an array of bytes. + */ +int curve25519(byte* r, byte* n, byte* a) +{ + fe x1, x2, z2, x3, z3; + fe t0, t1; + int pos; + unsigned int swap; + unsigned int b; + + fe_frombytes(x1, a); + fe_1(x2); + fe_0(z2); + fe_copy(x3, x1); + fe_1(z3); + + swap = 0; + for (pos = 254;pos >= 0;--pos) { + b = n[pos / 8] >> (pos & 7); + b &= 1; + swap ^= b; + fe_cswap(x2, x3, swap); + fe_cswap(z2, z3, swap); + swap = b; + + fe_sub(t0, x3, z3); + fe_sub(t1, x2, z2); + fe_add(x2, x2, z2); + fe_add(z2, x3, z3); + fe_mul(z3, t0, x2); + fe_mul(z2, z2, t1); + fe_sq(t0, t1); + fe_sq(t1, x2); + fe_add(x3, z3, z2); + fe_sub(z2, z3, z2); + fe_mul(x2, t1, t0); + fe_sub(t1, t1, t0); + fe_sq(z2, z2); + fe_mul121666(z3, t1); + fe_sq(x3, x3); + fe_add(t0, t0, z3); + fe_mul(z3, x1, z2); + fe_mul(z2, t1, t0); + } + fe_cswap(x2, x3, swap); + fe_cswap(z2, z3, swap); + + fe_invert(z2, z2); + fe_mul(x2, x2, z2); + fe_tobytes(r, x2); + + return 0; +} +#endif /* !CURVE25519_SMALL */ + +/* The field element value 0 as an array of bytes. */ +static const unsigned char zero[32] = {0}; + +/* Constant time check as to whether a is not 0. + * + * a A field element. + */ +int fe_isnonzero(const fe a) +{ + unsigned char s[32]; + fe_tobytes(s, a); + return ConstantCompare(s, zero, 32); +} + +/* Checks whether a is negative. + * + * a A field element. + */ +int fe_isnegative(const fe a) +{ + unsigned char s[32]; + fe_tobytes(s, a); + return s[0] & 1; +} + +/* Negates field element a and stores the result in r. + * + * r A field element. + * a A field element. + */ +void fe_neg(fe r, const fe a) +{ + r[0] = -a[0]; + r[1] = -a[1]; + r[2] = -a[2]; + r[3] = -a[3]; + r[4] = -a[4]; +} + +/* Constant time, conditional move of b into a. + * a is not changed if the condition is 0. + * + * a A field element. + * b A field element. + * c If 1 then copy and if 0 then don't copy. + */ +void fe_cmov(fe a, const fe b, int c) +{ + int64_t m = c; + int64_t t0, t1, t2, t3, t4; + + /* Convert conditional into mask. */ + m = -m; + t0 = m & (a[0] ^ b[0]); + t1 = m & (a[1] ^ b[1]); + t2 = m & (a[2] ^ b[2]); + t3 = m & (a[3] ^ b[3]); + t4 = m & (a[4] ^ b[4]); + + a[0] ^= t0; + a[1] ^= t1; + a[2] ^= t2; + a[3] ^= t3; + a[4] ^= t4; +} + +void fe_pow22523(fe r, const fe a) +{ + fe t0, t1, t2; + int i; + + /* a ^ (2^255 - 23) */ + fe_sq(t0, a); for (i = 1; i < 1; ++i) fe_sq(t0, t0); + fe_sq(t1, t0); for (i = 1; i < 2; ++i) fe_sq(t1, t1); fe_mul(t1, a, t1); + fe_mul(t0, t0, t1); + fe_sq(t0, t0); for (i = 1; i < 1; ++i) fe_sq(t0, t0); fe_mul(t0, t1, t0); + fe_sq(t1, t0); for (i = 1; i < 5; ++i) fe_sq(t1, t1); fe_mul(t0, t1, t0); + fe_sq(t1, t0); for (i = 1; i < 10; ++i) fe_sq(t1, t1); fe_mul(t1, t1, t0); + fe_sq(t2, t1); for (i = 1; i < 20; ++i) fe_sq(t2, t2); fe_mul(t1, t2, t1); + fe_sq(t1, t1); for (i = 1; i < 10; ++i) fe_sq(t1, t1); fe_mul(t0, t1, t0); + fe_sq(t1, t0); for (i = 1; i < 50; ++i) fe_sq(t1, t1); fe_mul(t1, t1, t0); + fe_sq(t2, t1); for (i = 1; i < 100; ++i) fe_sq(t2, t2); fe_mul(t1, t2, t1); + fe_sq(t1, t1); for (i = 1; i < 50; ++i) fe_sq(t1, t1); fe_mul(t0, t1, t0); + fe_sq(t0, t0); for (i = 1; i < 2; ++i) fe_sq(t0, t0); fe_mul( r, t0, a); + + return; +} + +/* Double the square of a and put result in r. (r = 2 * a * a) + * + * r A field element. + * a A field element. + * b A field element. + */ +void fe_sq2(fe r, const fe a) +{ + const __int128_t k2 = 2; + const __int128_t k19 = 19; + __int128_t t0 = k2 * (((__int128_t)a[0]) * a[0]); + __int128_t t1 = k2 * (((__int128_t)a[0]) * a[1] * k2); + __int128_t t2 = k2 * (((__int128_t)a[0]) * a[2] * k2 + + ((__int128_t)a[1]) * a[1]); + __int128_t t3 = k2 * (((__int128_t)a[0]) * a[3] * k2 + + ((__int128_t)a[1]) * a[2] * k2); + __int128_t t4 = k2 * (((__int128_t)a[0]) * a[4] * k2 + + ((__int128_t)a[1]) * a[3] * k2 + + ((__int128_t)a[2]) * a[2]); + __int128_t t5 = k2 * (((__int128_t)a[1]) * a[4] * k2 + + ((__int128_t)a[2]) * a[3] * k2); + __int128_t t6 = k2 * (((__int128_t)a[2]) * a[4] * k2 + + ((__int128_t)a[3]) * a[3]); + __int128_t t7 = k2 * (((__int128_t)a[3]) * a[4] * k2); + __int128_t t8 = k2 * (((__int128_t)a[4]) * a[4]); + + /* Modulo reduce double long word. */ + t0 += t5 * k19; + t1 += t6 * k19; + t2 += t7 * k19; + t3 += t8 * k19; + + /* Normalize to 51-bits of data per word. */ + t0 += (t4 >> 51) * k19; t4 &= 0x7ffffffffffff; + + t1 += t0 >> 51; r[0] = t0 & 0x7ffffffffffff; + t2 += t1 >> 51; r[1] = t1 & 0x7ffffffffffff; + t3 += t2 >> 51; r[2] = t2 & 0x7ffffffffffff; + t4 += t3 >> 51; r[3] = t3 & 0x7ffffffffffff; + r[0] += (t4 >> 51) * k19; + r[4] = t4 & 0x7ffffffffffff; +} + +/* Load 3 little endian bytes into a 64-bit word. + * + * in An array of bytes. + * returns a 64-bit word. + */ +uint64_t load_3(const unsigned char *in) +{ + uint64_t result; + + result = ((((uint64_t)in[0]) ) | + (((uint64_t)in[1]) << 8) | + (((uint64_t)in[2]) << 16)); + + return result; +} + +/* Load 4 little endian bytes into a 64-bit word. + * + * in An array of bytes. + * returns a 64-bit word. + */ +uint64_t load_4(const unsigned char *in) +{ + uint64_t result; + + result = ((((uint64_t)in[0]) ) | + (((uint64_t)in[1]) << 8) | + (((uint64_t)in[2]) << 16) | + (((uint64_t)in[3]) << 24)); + + return result; +} + diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/fe_x25519_asm.S b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fe_x25519_asm.S new file mode 100755 index 0000000..a0f57c5 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fe_x25519_asm.S @@ -0,0 +1,16177 @@ +/* fe_x25519_asm + * + * Copyright (C) 2006-2018 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#ifndef HAVE_INTEL_AVX1 +#define HAVE_INTEL_AVX1 +#endif /* HAVE_INTEL_AVX1 */ +#ifndef NO_AVX2_SUPPORT +#define HAVE_INTEL_AVX2 +#endif /* NO_AVX2_SUPPORT */ + +#ifndef __APPLE__ +.text +.globl fe_init +.type fe_init,@function +.align 4 +fe_init: +#else +.section __TEXT,__text +.globl _fe_init +.p2align 2 +_fe_init: +#endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 + movl cpuFlagsSet(%rip), %eax + testl %eax, %eax + je L_fe_init_get_flags + repz retq +L_fe_init_get_flags: +#ifndef __APPLE__ + callq cpuid_get_flags@plt +#else + callq _cpuid_get_flags +#endif /* __APPLE__ */ + movl %eax, intelFlags(%rip) + andl $0x50, %eax + cmpl $0x50, %eax + jne L_fe_init_flags_done +#ifndef __APPLE__ + movq fe_mul_avx2@GOTPCREL(%rip), %rax +#else + movq fe_mul_avx2(%rip), %rax +#endif /* __APPLE__ */ + movq %rax, fe_mul_p(%rip) +#ifndef __APPLE__ + movq fe_sq_avx2@GOTPCREL(%rip), %rax +#else + movq fe_sq_avx2(%rip), %rax +#endif /* __APPLE__ */ + movq %rax, fe_sq_p(%rip) +#ifndef __APPLE__ + movq fe_mul121666_avx2@GOTPCREL(%rip), %rax +#else + movq fe_mul121666_avx2(%rip), %rax +#endif /* __APPLE__ */ + movq %rax, fe_mul121666_p(%rip) +#ifndef __APPLE__ + movq fe_sq2_avx2@GOTPCREL(%rip), %rax +#else + movq fe_sq2_avx2(%rip), %rax +#endif /* __APPLE__ */ + movq %rax, fe_sq2_p(%rip) +#ifndef __APPLE__ + movq fe_invert_avx2@GOTPCREL(%rip), %rax +#else + movq fe_invert_avx2(%rip), %rax +#endif /* __APPLE__ */ + movq %rax, fe_invert_p(%rip) +#ifndef __APPLE__ + movq curve25519_avx2@GOTPCREL(%rip), %rax +#else + movq curve25519_avx2(%rip), %rax +#endif /* __APPLE__ */ + movq %rax, curve25519_p(%rip) +#ifndef __APPLE__ + movq fe_pow22523_avx2@GOTPCREL(%rip), %rax +#else + movq fe_pow22523_avx2(%rip), %rax +#endif /* __APPLE__ */ + movq %rax, fe_pow22523_p(%rip) +#ifndef __APPLE__ + movq fe_ge_to_p2_avx2@GOTPCREL(%rip), %rax +#else + movq fe_ge_to_p2_avx2(%rip), %rax +#endif /* __APPLE__ */ + movq %rax, fe_ge_to_p2_p(%rip) +#ifndef __APPLE__ + movq fe_ge_to_p3_avx2@GOTPCREL(%rip), %rax +#else + movq fe_ge_to_p3_avx2(%rip), %rax +#endif /* __APPLE__ */ + movq %rax, fe_ge_to_p3_p(%rip) +#ifndef __APPLE__ + movq fe_ge_dbl_avx2@GOTPCREL(%rip), %rax +#else + movq fe_ge_dbl_avx2(%rip), %rax +#endif /* __APPLE__ */ + movq %rax, fe_ge_dbl_p(%rip) +#ifndef __APPLE__ + movq fe_ge_madd_avx2@GOTPCREL(%rip), %rax +#else + movq fe_ge_madd_avx2(%rip), %rax +#endif /* __APPLE__ */ + movq %rax, fe_ge_madd_p(%rip) +#ifndef __APPLE__ + movq fe_ge_msub_avx2@GOTPCREL(%rip), %rax +#else + movq fe_ge_msub_avx2(%rip), %rax +#endif /* __APPLE__ */ + movq %rax, fe_ge_msub_p(%rip) +#ifndef __APPLE__ + movq fe_ge_add_avx2@GOTPCREL(%rip), %rax +#else + movq fe_ge_add_avx2(%rip), %rax +#endif /* __APPLE__ */ + movq %rax, fe_ge_add_p(%rip) +#ifndef __APPLE__ + movq fe_ge_sub_avx2@GOTPCREL(%rip), %rax +#else + movq fe_ge_sub_avx2(%rip), %rax +#endif /* __APPLE__ */ + movq %rax, fe_ge_sub_p(%rip) +L_fe_init_flags_done: + movl $0x01, cpuFlagsSet(%rip) +#endif /* HAVE_INTEL_AVX2 */ + repz retq +#ifndef __APPLE__ +.size fe_init,.-fe_init +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_frombytes +.type fe_frombytes,@function +.align 4 +fe_frombytes: +#else +.section __TEXT,__text +.globl _fe_frombytes +.p2align 2 +_fe_frombytes: +#endif /* __APPLE__ */ + movq $0x7fffffffffffffff, %r9 + movq (%rsi), %rdx + movq 8(%rsi), %rax + movq 16(%rsi), %rcx + movq 24(%rsi), %r8 + andq %r9, %r8 + movq %rdx, (%rdi) + movq %rax, 8(%rdi) + movq %rcx, 16(%rdi) + movq %r8, 24(%rdi) + repz retq +#ifndef __APPLE__ +.size fe_frombytes,.-fe_frombytes +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_tobytes +.type fe_tobytes,@function +.align 4 +fe_tobytes: +#else +.section __TEXT,__text +.globl _fe_tobytes +.p2align 2 +_fe_tobytes: +#endif /* __APPLE__ */ + movq $0x7fffffffffffffff, %r10 + movq (%rsi), %rdx + movq 8(%rsi), %rax + movq 16(%rsi), %rcx + movq 24(%rsi), %r8 + addq $19, %rdx + adcq $0x00, %rax + adcq $0x00, %rcx + adcq $0x00, %r8 + shrq $63, %r8 + imulq $19, %r8, %r9 + movq (%rsi), %rdx + movq 8(%rsi), %rax + movq 16(%rsi), %rcx + movq 24(%rsi), %r8 + addq %r9, %rdx + adcq $0x00, %rax + adcq $0x00, %rcx + adcq $0x00, %r8 + andq %r10, %r8 + movq %rdx, (%rdi) + movq %rax, 8(%rdi) + movq %rcx, 16(%rdi) + movq %r8, 24(%rdi) + repz retq +#ifndef __APPLE__ +.size fe_tobytes,.-fe_tobytes +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_1 +.type fe_1,@function +.align 4 +fe_1: +#else +.section __TEXT,__text +.globl _fe_1 +.p2align 2 +_fe_1: +#endif /* __APPLE__ */ + # Set one + movq $0x01, (%rdi) + movq $0x00, 8(%rdi) + movq $0x00, 16(%rdi) + movq $0x00, 24(%rdi) + repz retq +#ifndef __APPLE__ +.size fe_1,.-fe_1 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_0 +.type fe_0,@function +.align 4 +fe_0: +#else +.section __TEXT,__text +.globl _fe_0 +.p2align 2 +_fe_0: +#endif /* __APPLE__ */ + # Set zero + movq $0x00, (%rdi) + movq $0x00, 8(%rdi) + movq $0x00, 16(%rdi) + movq $0x00, 24(%rdi) + repz retq +#ifndef __APPLE__ +.size fe_0,.-fe_0 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_copy +.type fe_copy,@function +.align 4 +fe_copy: +#else +.section __TEXT,__text +.globl _fe_copy +.p2align 2 +_fe_copy: +#endif /* __APPLE__ */ + # Copy + movq (%rsi), %rdx + movq 8(%rsi), %rax + movq 16(%rsi), %rcx + movq 24(%rsi), %r8 + movq %rdx, (%rdi) + movq %rax, 8(%rdi) + movq %rcx, 16(%rdi) + movq %r8, 24(%rdi) + repz retq +#ifndef __APPLE__ +.size fe_copy,.-fe_copy +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_cswap +.type fe_cswap,@function +.align 4 +fe_cswap: +#else +.section __TEXT,__text +.globl _fe_cswap +.p2align 2 +_fe_cswap: +#endif /* __APPLE__ */ + # Conditional Swap + movslq %edx, %rax + movq (%rdi), %rcx + movq 8(%rdi), %r8 + movq 16(%rdi), %r9 + movq 24(%rdi), %r10 + negq %rax + xorq (%rsi), %rcx + xorq 8(%rsi), %r8 + xorq 16(%rsi), %r9 + xorq 24(%rsi), %r10 + andq %rax, %rcx + andq %rax, %r8 + andq %rax, %r9 + andq %rax, %r10 + xorq %rcx, (%rdi) + xorq %r8, 8(%rdi) + xorq %r9, 16(%rdi) + xorq %r10, 24(%rdi) + xorq %rcx, (%rsi) + xorq %r8, 8(%rsi) + xorq %r9, 16(%rsi) + xorq %r10, 24(%rsi) + repz retq +#ifndef __APPLE__ +.size fe_cswap,.-fe_cswap +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_sub +.type fe_sub,@function +.align 4 +fe_sub: +#else +.section __TEXT,__text +.globl _fe_sub +.p2align 2 +_fe_sub: +#endif /* __APPLE__ */ + pushq %r12 + # Sub + movq (%rsi), %rax + movq 8(%rsi), %rcx + movq 16(%rsi), %r8 + movq 24(%rsi), %r9 + subq (%rdx), %rax + movq $0x00, %r10 + sbbq 8(%rdx), %rcx + movq $-19, %r11 + sbbq 16(%rdx), %r8 + movq $0x7fffffffffffffff, %r12 + sbbq 24(%rdx), %r9 + sbbq $0x00, %r10 + # Mask the modulus + andq %r10, %r11 + andq %r10, %r12 + # Add modulus (if underflow) + addq %r11, %rax + adcq %r10, %rcx + adcq %r10, %r8 + adcq %r12, %r9 + movq %rax, (%rdi) + movq %rcx, 8(%rdi) + movq %r8, 16(%rdi) + movq %r9, 24(%rdi) + popq %r12 + repz retq +#ifndef __APPLE__ +.size fe_sub,.-fe_sub +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_add +.type fe_add,@function +.align 4 +fe_add: +#else +.section __TEXT,__text +.globl _fe_add +.p2align 2 +_fe_add: +#endif /* __APPLE__ */ + pushq %r12 + # Add + movq (%rsi), %rax + movq 8(%rsi), %rcx + addq (%rdx), %rax + movq 16(%rsi), %r8 + adcq 8(%rdx), %rcx + movq 24(%rsi), %r10 + adcq 16(%rdx), %r8 + movq $-19, %r11 + adcq 24(%rdx), %r10 + movq $0x7fffffffffffffff, %r12 + movq %r10, %r9 + sarq $63, %r10 + # Mask the modulus + andq %r10, %r11 + andq %r10, %r12 + # Sub modulus (if overflow) + subq %r11, %rax + sbbq %r10, %rcx + sbbq %r10, %r8 + sbbq %r12, %r9 + movq %rax, (%rdi) + movq %rcx, 8(%rdi) + movq %r8, 16(%rdi) + movq %r9, 24(%rdi) + popq %r12 + repz retq +#ifndef __APPLE__ +.size fe_add,.-fe_add +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_neg +.type fe_neg,@function +.align 4 +fe_neg: +#else +.section __TEXT,__text +.globl _fe_neg +.p2align 2 +_fe_neg: +#endif /* __APPLE__ */ + movq $-19, %rdx + movq $-1, %rax + movq $-1, %rcx + movq $0x7fffffffffffffff, %r8 + subq (%rsi), %rdx + subq 8(%rsi), %rax + subq 16(%rsi), %rcx + subq 24(%rsi), %r8 + movq %rdx, (%rdi) + movq %rax, 8(%rdi) + movq %rcx, 16(%rdi) + movq %r8, 24(%rdi) + repz retq +#ifndef __APPLE__ +.size fe_neg,.-fe_neg +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_cmov +.type fe_cmov,@function +.align 4 +fe_cmov: +#else +.section __TEXT,__text +.globl _fe_cmov +.p2align 2 +_fe_cmov: +#endif /* __APPLE__ */ + cmpl $0x01, %edx + movq (%rdi), %rcx + movq 8(%rdi), %r8 + movq 16(%rdi), %r9 + movq 24(%rdi), %r10 + cmoveq (%rsi), %rcx + cmoveq 8(%rsi), %r8 + cmoveq 16(%rsi), %r9 + cmoveq 24(%rsi), %r10 + movq %rcx, (%rdi) + movq %r8, 8(%rdi) + movq %r9, 16(%rdi) + movq %r10, 24(%rdi) + repz retq +#ifndef __APPLE__ +.size fe_cmov,.-fe_cmov +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_isnonzero +.type fe_isnonzero,@function +.align 4 +fe_isnonzero: +#else +.section __TEXT,__text +.globl _fe_isnonzero +.p2align 2 +_fe_isnonzero: +#endif /* __APPLE__ */ + movq $0x7fffffffffffffff, %r10 + movq (%rdi), %rax + movq 8(%rdi), %rdx + movq 16(%rdi), %rcx + movq 24(%rdi), %r8 + addq $19, %rax + adcq $0x00, %rdx + adcq $0x00, %rcx + adcq $0x00, %r8 + shrq $63, %r8 + imulq $19, %r8, %r9 + movq (%rdi), %rax + movq 8(%rdi), %rdx + movq 16(%rdi), %rcx + movq 24(%rdi), %r8 + addq %r9, %rax + adcq $0x00, %rdx + adcq $0x00, %rcx + adcq $0x00, %r8 + andq %r10, %r8 + orq %rdx, %rax + orq %rcx, %rax + orq %r8, %rax + repz retq +#ifndef __APPLE__ +.size fe_isnonzero,.-fe_isnonzero +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_isnegative +.type fe_isnegative,@function +.align 4 +fe_isnegative: +#else +.section __TEXT,__text +.globl _fe_isnegative +.p2align 2 +_fe_isnegative: +#endif /* __APPLE__ */ + movq $0x7fffffffffffffff, %r10 + movq (%rdi), %rax + movq 8(%rdi), %rdx + movq 16(%rdi), %rcx + movq 24(%rdi), %r8 + addq $19, %rax + adcq $0x00, %rdx + adcq $0x00, %rcx + adcq $0x00, %r8 + shrq $63, %r8 + imulq $19, %r8, %r9 + movq (%rdi), %rax + addq %r9, %rax + andq $0x01, %rax + repz retq +#ifndef __APPLE__ +.size fe_isnegative,.-fe_isnegative +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_cmov_table +.type fe_cmov_table,@function +.align 4 +fe_cmov_table: +#else +.section __TEXT,__text +.globl _fe_cmov_table +.p2align 2 +_fe_cmov_table: +#endif /* __APPLE__ */ + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + movq %rdx, %rcx + movsbq %cl, %rax + cdq + xorb %dl, %al + subb %dl, %al + movb %al, %r15b + movq $0x01, %rax + xorq %rdx, %rdx + xorq %r8, %r8 + xorq %r9, %r9 + movq $0x01, %r10 + xorq %r11, %r11 + xorq %r12, %r12 + xorq %r13, %r13 + cmpb $0x01, %r15b + movq (%rsi), %r14 + cmoveq %r14, %rax + movq 8(%rsi), %r14 + cmoveq %r14, %rdx + movq 16(%rsi), %r14 + cmoveq %r14, %r8 + movq 24(%rsi), %r14 + cmoveq %r14, %r9 + movq 32(%rsi), %r14 + cmoveq %r14, %r10 + movq 40(%rsi), %r14 + cmoveq %r14, %r11 + movq 48(%rsi), %r14 + cmoveq %r14, %r12 + movq 56(%rsi), %r14 + cmoveq %r14, %r13 + cmpb $2, %r15b + movq 96(%rsi), %r14 + cmoveq %r14, %rax + movq 104(%rsi), %r14 + cmoveq %r14, %rdx + movq 112(%rsi), %r14 + cmoveq %r14, %r8 + movq 120(%rsi), %r14 + cmoveq %r14, %r9 + movq 128(%rsi), %r14 + cmoveq %r14, %r10 + movq 136(%rsi), %r14 + cmoveq %r14, %r11 + movq 144(%rsi), %r14 + cmoveq %r14, %r12 + movq 152(%rsi), %r14 + cmoveq %r14, %r13 + cmpb $3, %r15b + movq 192(%rsi), %r14 + cmoveq %r14, %rax + movq 200(%rsi), %r14 + cmoveq %r14, %rdx + movq 208(%rsi), %r14 + cmoveq %r14, %r8 + movq 216(%rsi), %r14 + cmoveq %r14, %r9 + movq 224(%rsi), %r14 + cmoveq %r14, %r10 + movq 232(%rsi), %r14 + cmoveq %r14, %r11 + movq 240(%rsi), %r14 + cmoveq %r14, %r12 + movq 248(%rsi), %r14 + cmoveq %r14, %r13 + cmpb $4, %r15b + movq 288(%rsi), %r14 + cmoveq %r14, %rax + movq 296(%rsi), %r14 + cmoveq %r14, %rdx + movq 304(%rsi), %r14 + cmoveq %r14, %r8 + movq 312(%rsi), %r14 + cmoveq %r14, %r9 + movq 320(%rsi), %r14 + cmoveq %r14, %r10 + movq 328(%rsi), %r14 + cmoveq %r14, %r11 + movq 336(%rsi), %r14 + cmoveq %r14, %r12 + movq 344(%rsi), %r14 + cmoveq %r14, %r13 + cmpb $5, %r15b + movq 384(%rsi), %r14 + cmoveq %r14, %rax + movq 392(%rsi), %r14 + cmoveq %r14, %rdx + movq 400(%rsi), %r14 + cmoveq %r14, %r8 + movq 408(%rsi), %r14 + cmoveq %r14, %r9 + movq 416(%rsi), %r14 + cmoveq %r14, %r10 + movq 424(%rsi), %r14 + cmoveq %r14, %r11 + movq 432(%rsi), %r14 + cmoveq %r14, %r12 + movq 440(%rsi), %r14 + cmoveq %r14, %r13 + cmpb $6, %r15b + movq 480(%rsi), %r14 + cmoveq %r14, %rax + movq 488(%rsi), %r14 + cmoveq %r14, %rdx + movq 496(%rsi), %r14 + cmoveq %r14, %r8 + movq 504(%rsi), %r14 + cmoveq %r14, %r9 + movq 512(%rsi), %r14 + cmoveq %r14, %r10 + movq 520(%rsi), %r14 + cmoveq %r14, %r11 + movq 528(%rsi), %r14 + cmoveq %r14, %r12 + movq 536(%rsi), %r14 + cmoveq %r14, %r13 + cmpb $7, %r15b + movq 576(%rsi), %r14 + cmoveq %r14, %rax + movq 584(%rsi), %r14 + cmoveq %r14, %rdx + movq 592(%rsi), %r14 + cmoveq %r14, %r8 + movq 600(%rsi), %r14 + cmoveq %r14, %r9 + movq 608(%rsi), %r14 + cmoveq %r14, %r10 + movq 616(%rsi), %r14 + cmoveq %r14, %r11 + movq 624(%rsi), %r14 + cmoveq %r14, %r12 + movq 632(%rsi), %r14 + cmoveq %r14, %r13 + cmpb $8, %r15b + movq 672(%rsi), %r14 + cmoveq %r14, %rax + movq 680(%rsi), %r14 + cmoveq %r14, %rdx + movq 688(%rsi), %r14 + cmoveq %r14, %r8 + movq 696(%rsi), %r14 + cmoveq %r14, %r9 + movq 704(%rsi), %r14 + cmoveq %r14, %r10 + movq 712(%rsi), %r14 + cmoveq %r14, %r11 + movq 720(%rsi), %r14 + cmoveq %r14, %r12 + movq 728(%rsi), %r14 + cmoveq %r14, %r13 + cmpb $0x00, %cl + movq %rax, %r14 + cmovlq %r10, %rax + cmovlq %r14, %r10 + movq %rdx, %r14 + cmovlq %r11, %rdx + cmovlq %r14, %r11 + movq %r8, %r14 + cmovlq %r12, %r8 + cmovlq %r14, %r12 + movq %r9, %r14 + cmovlq %r13, %r9 + cmovlq %r14, %r13 + movq %rax, (%rdi) + movq %rdx, 8(%rdi) + movq %r8, 16(%rdi) + movq %r9, 24(%rdi) + movq %r10, 32(%rdi) + movq %r11, 40(%rdi) + movq %r12, 48(%rdi) + movq %r13, 56(%rdi) + xorq %rax, %rax + xorq %rdx, %rdx + xorq %r8, %r8 + xorq %r9, %r9 + cmpb $0x01, %r15b + movq 64(%rsi), %r14 + cmoveq %r14, %rax + movq 72(%rsi), %r14 + cmoveq %r14, %rdx + movq 80(%rsi), %r14 + cmoveq %r14, %r8 + movq 88(%rsi), %r14 + cmoveq %r14, %r9 + cmpb $2, %r15b + movq 160(%rsi), %r14 + cmoveq %r14, %rax + movq 168(%rsi), %r14 + cmoveq %r14, %rdx + movq 176(%rsi), %r14 + cmoveq %r14, %r8 + movq 184(%rsi), %r14 + cmoveq %r14, %r9 + cmpb $3, %r15b + movq 256(%rsi), %r14 + cmoveq %r14, %rax + movq 264(%rsi), %r14 + cmoveq %r14, %rdx + movq 272(%rsi), %r14 + cmoveq %r14, %r8 + movq 280(%rsi), %r14 + cmoveq %r14, %r9 + cmpb $4, %r15b + movq 352(%rsi), %r14 + cmoveq %r14, %rax + movq 360(%rsi), %r14 + cmoveq %r14, %rdx + movq 368(%rsi), %r14 + cmoveq %r14, %r8 + movq 376(%rsi), %r14 + cmoveq %r14, %r9 + cmpb $5, %r15b + movq 448(%rsi), %r14 + cmoveq %r14, %rax + movq 456(%rsi), %r14 + cmoveq %r14, %rdx + movq 464(%rsi), %r14 + cmoveq %r14, %r8 + movq 472(%rsi), %r14 + cmoveq %r14, %r9 + cmpb $6, %r15b + movq 544(%rsi), %r14 + cmoveq %r14, %rax + movq 552(%rsi), %r14 + cmoveq %r14, %rdx + movq 560(%rsi), %r14 + cmoveq %r14, %r8 + movq 568(%rsi), %r14 + cmoveq %r14, %r9 + cmpb $7, %r15b + movq 640(%rsi), %r14 + cmoveq %r14, %rax + movq 648(%rsi), %r14 + cmoveq %r14, %rdx + movq 656(%rsi), %r14 + cmoveq %r14, %r8 + movq 664(%rsi), %r14 + cmoveq %r14, %r9 + cmpb $8, %r15b + movq 736(%rsi), %r14 + cmoveq %r14, %rax + movq 744(%rsi), %r14 + cmoveq %r14, %rdx + movq 752(%rsi), %r14 + cmoveq %r14, %r8 + movq 760(%rsi), %r14 + cmoveq %r14, %r9 + movq $-19, %r10 + movq $-1, %r11 + movq $-1, %r12 + movq $0x7fffffffffffffff, %r13 + subq %rax, %r10 + sbbq %rdx, %r11 + sbbq %r8, %r12 + sbbq %r9, %r13 + cmpb $0x00, %cl + cmovlq %r10, %rax + cmovlq %r11, %rdx + cmovlq %r12, %r8 + cmovlq %r13, %r9 + movq %rax, 64(%rdi) + movq %rdx, 72(%rdi) + movq %r8, 80(%rdi) + movq %r9, 88(%rdi) + popq %r15 + popq %r14 + popq %r13 + popq %r12 + repz retq +#ifndef __APPLE__ +.size fe_cmov_table,.-fe_cmov_table +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_mul +.type fe_mul,@function +.align 4 +fe_mul: +#else +.section __TEXT,__text +.globl _fe_mul +.p2align 2 +_fe_mul: +#endif /* __APPLE__ */ + jmpq *fe_mul_p(%rip) +#ifndef __APPLE__ +.size fe_mul,.-fe_mul +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_sq +.type fe_sq,@function +.align 4 +fe_sq: +#else +.section __TEXT,__text +.globl _fe_sq +.p2align 2 +_fe_sq: +#endif /* __APPLE__ */ + jmpq *fe_sq_p(%rip) +#ifndef __APPLE__ +.size fe_sq,.-fe_sq +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_mul121666 +.type fe_mul121666,@function +.align 4 +fe_mul121666: +#else +.section __TEXT,__text +.globl _fe_mul121666 +.p2align 2 +_fe_mul121666: +#endif /* __APPLE__ */ + jmpq *fe_mul121666_p(%rip) +#ifndef __APPLE__ +.size fe_mul121666,.-fe_mul121666 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_sq2 +.type fe_sq2,@function +.align 4 +fe_sq2: +#else +.section __TEXT,__text +.globl _fe_sq2 +.p2align 2 +_fe_sq2: +#endif /* __APPLE__ */ + jmpq *fe_sq2_p(%rip) +#ifndef __APPLE__ +.size fe_sq2,.-fe_sq2 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_invert +.type fe_invert,@function +.align 4 +fe_invert: +#else +.section __TEXT,__text +.globl _fe_invert +.p2align 2 +_fe_invert: +#endif /* __APPLE__ */ + jmpq *fe_invert_p(%rip) +#ifndef __APPLE__ +.size fe_invert,.-fe_invert +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl curve25519 +.type curve25519,@function +.align 4 +curve25519: +#else +.section __TEXT,__text +.globl _curve25519 +.p2align 2 +_curve25519: +#endif /* __APPLE__ */ + jmpq *curve25519_p(%rip) +#ifndef __APPLE__ +.size curve25519,.-curve25519 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_pow22523 +.type fe_pow22523,@function +.align 4 +fe_pow22523: +#else +.section __TEXT,__text +.globl _fe_pow22523 +.p2align 2 +_fe_pow22523: +#endif /* __APPLE__ */ + jmpq *fe_pow22523_p(%rip) +#ifndef __APPLE__ +.size fe_pow22523,.-fe_pow22523 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_ge_to_p2 +.type fe_ge_to_p2,@function +.align 4 +fe_ge_to_p2: +#else +.section __TEXT,__text +.globl _fe_ge_to_p2 +.p2align 2 +_fe_ge_to_p2: +#endif /* __APPLE__ */ + jmpq *fe_ge_to_p2_p(%rip) +#ifndef __APPLE__ +.size fe_ge_to_p2,.-fe_ge_to_p2 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_ge_to_p3 +.type fe_ge_to_p3,@function +.align 4 +fe_ge_to_p3: +#else +.section __TEXT,__text +.globl _fe_ge_to_p3 +.p2align 2 +_fe_ge_to_p3: +#endif /* __APPLE__ */ + jmpq *fe_ge_to_p3_p(%rip) +#ifndef __APPLE__ +.size fe_ge_to_p3,.-fe_ge_to_p3 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_ge_dbl +.type fe_ge_dbl,@function +.align 4 +fe_ge_dbl: +#else +.section __TEXT,__text +.globl _fe_ge_dbl +.p2align 2 +_fe_ge_dbl: +#endif /* __APPLE__ */ + jmpq *fe_ge_dbl_p(%rip) +#ifndef __APPLE__ +.size fe_ge_dbl,.-fe_ge_dbl +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_ge_madd +.type fe_ge_madd,@function +.align 4 +fe_ge_madd: +#else +.section __TEXT,__text +.globl _fe_ge_madd +.p2align 2 +_fe_ge_madd: +#endif /* __APPLE__ */ + jmpq *fe_ge_madd_p(%rip) +#ifndef __APPLE__ +.size fe_ge_madd,.-fe_ge_madd +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_ge_msub +.type fe_ge_msub,@function +.align 4 +fe_ge_msub: +#else +.section __TEXT,__text +.globl _fe_ge_msub +.p2align 2 +_fe_ge_msub: +#endif /* __APPLE__ */ + jmpq *fe_ge_msub_p(%rip) +#ifndef __APPLE__ +.size fe_ge_msub,.-fe_ge_msub +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_ge_add +.type fe_ge_add,@function +.align 4 +fe_ge_add: +#else +.section __TEXT,__text +.globl _fe_ge_add +.p2align 2 +_fe_ge_add: +#endif /* __APPLE__ */ + jmpq *fe_ge_add_p(%rip) +#ifndef __APPLE__ +.size fe_ge_add,.-fe_ge_add +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_ge_sub +.type fe_ge_sub,@function +.align 4 +fe_ge_sub: +#else +.section __TEXT,__text +.globl _fe_ge_sub +.p2align 2 +_fe_ge_sub: +#endif /* __APPLE__ */ + jmpq *fe_ge_sub_p(%rip) +#ifndef __APPLE__ +.size fe_ge_sub,.-fe_ge_sub +#endif /* __APPLE__ */ + .data + .type cpuFlagsSet, @object + .size cpuFlagsSet,4 +cpuFlagsSet: + .long 0 + .data + .type intelFlags, @object + .size intelFlags,4 +intelFlags: + .long 0 + .data + .type fe_mul_p, @object + .size fe_mul_p,8 +fe_mul_p: + .quad fe_mul_x64 + .data + .type fe_sq_p, @object + .size fe_sq_p,8 +fe_sq_p: + .quad fe_sq_x64 + .data + .type fe_mul121666_p, @object + .size fe_mul121666_p,8 +fe_mul121666_p: + .quad fe_mul121666_x64 + .data + .type fe_sq2_p, @object + .size fe_sq2_p,8 +fe_sq2_p: + .quad fe_sq2_x64 + .data + .type fe_invert_p, @object + .size fe_invert_p,8 +fe_invert_p: + .quad fe_invert_x64 + .data + .type curve25519_p, @object + .size curve25519_p,8 +curve25519_p: + .quad curve25519_x64 + .data + .type fe_pow22523_p, @object + .size fe_pow22523_p,8 +fe_pow22523_p: + .quad fe_pow22523_x64 + .data + .type fe_ge_to_p2_p, @object + .size fe_ge_to_p2_p,8 +fe_ge_to_p2_p: + .quad fe_ge_to_p2_x64 + .data + .type fe_ge_to_p3_p, @object + .size fe_ge_to_p3_p,8 +fe_ge_to_p3_p: + .quad fe_ge_to_p3_x64 + .data + .type fe_ge_dbl_p, @object + .size fe_ge_dbl_p,8 +fe_ge_dbl_p: + .quad fe_ge_dbl_x64 + .data + .type fe_ge_madd_p, @object + .size fe_ge_madd_p,8 +fe_ge_madd_p: + .quad fe_ge_madd_x64 + .data + .type fe_ge_msub_p, @object + .size fe_ge_msub_p,8 +fe_ge_msub_p: + .quad fe_ge_msub_x64 + .data + .type fe_ge_add_p, @object + .size fe_ge_add_p,8 +fe_ge_add_p: + .quad fe_ge_add_x64 + .data + .type fe_ge_sub_p, @object + .size fe_ge_sub_p,8 +fe_ge_sub_p: + .quad fe_ge_sub_x64 +#ifndef __APPLE__ +.text +.globl fe_mul_x64 +.type fe_mul_x64,@function +.align 4 +fe_mul_x64: +#else +.section __TEXT,__text +.globl _fe_mul_x64 +.p2align 2 +_fe_mul_x64: +#endif /* __APPLE__ */ + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + pushq %rbx + movq %rdx, %rcx + # Multiply + # A[0] * B[0] + movq (%rcx), %rax + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rcx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq (%rcx), %rax + mulq 8(%rsi) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 16(%rcx), %rax + mulq (%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 8(%rcx), %rax + mulq 8(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq (%rcx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 24(%rcx), %rax + mulq (%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 16(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 8(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq (%rcx), %rax + mulq 24(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 24(%rcx), %rax + mulq 8(%rsi) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 16(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 8(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 24(%rcx), %rax + mulq 16(%rsi) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 16(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 24(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rbx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rbx, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rbx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rbx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + popq %rbx + popq %r15 + popq %r14 + popq %r13 + popq %r12 + repz retq +#ifndef __APPLE__ +.size fe_mul_x64,.-fe_mul_x64 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_sq_x64 +.type fe_sq_x64,@function +.align 4 +fe_sq_x64: +#else +.section __TEXT,__text +.globl _fe_sq_x64 +.p2align 2 +_fe_sq_x64: +#endif /* __APPLE__ */ + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + # Square + # A[0] * A[1] + movq (%rsi), %rax + mulq 8(%rsi) + movq %rax, %r8 + movq %rdx, %r9 + # A[0] * A[2] + movq (%rsi), %rax + mulq 16(%rsi) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[0] * A[3] + movq (%rsi), %rax + mulq 24(%rsi) + xorq %r11, %r11 + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * A[2] + movq 8(%rsi), %rax + mulq 16(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[1] * A[3] + movq 8(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + # A[2] * A[3] + movq 16(%rsi), %rax + mulq 24(%rsi) + xorq %r13, %r13 + addq %rax, %r12 + adcq %rdx, %r13 + # Double + xorq %r14, %r14 + addq %r8, %r8 + adcq %r9, %r9 + adcq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + adcq %r13, %r13 + adcq $0x00, %r14 + # A[0] * A[0] + movq (%rsi), %rax + mulq %rax + movq %rax, %rcx + movq %rdx, %r15 + # A[1] * A[1] + movq 8(%rsi), %rax + mulq %rax + addq %r15, %r8 + adcq %rax, %r9 + adcq $0x00, %rdx + movq %rdx, %r15 + # A[2] * A[2] + movq 16(%rsi), %rax + mulq %rax + addq %r15, %r10 + adcq %rax, %r11 + adcq $0x00, %rdx + movq %rdx, %r15 + # A[3] * A[3] + movq 24(%rsi), %rax + mulq %rax + addq %rax, %r13 + adcq %rdx, %r14 + addq %r15, %r12 + adcq $0x00, %r13 + adcq $0x00, %r14 + # Reduce + movq $0x7fffffffffffffff, %r15 + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + shldq $0x01, %r10, %r11 + andq %r15, %r10 + # Multiply top half by 19 + movq $19, %rax + mulq %r11 + xorq %r11, %r11 + addq %rax, %rcx + movq $19, %rax + adcq %rdx, %r11 + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + # Add remaining product results in + addq %r11, %r8 + adcq %r12, %r9 + adcq %r13, %r10 + adcq %rax, %r10 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r10, %rdx + imulq $19, %rdx, %rax + andq %r15, %r10 + addq %rax, %rcx + adcq $0x00, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + # Reduce if top bit set + movq %r10, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %r15, %r10 + addq %rax, %rcx + adcq $0x00, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + # Store + movq %rcx, (%rdi) + movq %r8, 8(%rdi) + movq %r9, 16(%rdi) + movq %r10, 24(%rdi) + popq %r15 + popq %r14 + popq %r13 + popq %r12 + repz retq +#ifndef __APPLE__ +.size fe_sq_x64,.-fe_sq_x64 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_mul121666_x64 +.type fe_mul121666_x64,@function +.align 4 +fe_mul121666_x64: +#else +.section __TEXT,__text +.globl _fe_mul121666_x64 +.p2align 2 +_fe_mul121666_x64: +#endif /* __APPLE__ */ + pushq %r12 + # Multiply by 121666 + movq $0x1db42, %rax + mulq (%rsi) + xorq %r10, %r10 + movq %rax, %r8 + movq %rdx, %r9 + movq $0x1db42, %rax + mulq 8(%rsi) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + movq $0x1db42, %rax + mulq 16(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + movq $0x1db42, %rax + mulq 24(%rsi) + movq $0x7fffffffffffffff, %rcx + addq %rax, %r11 + adcq %rdx, %r12 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + movq $19, %rax + mulq %r12 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + popq %r12 + repz retq +#ifndef __APPLE__ +.size fe_mul121666_x64,.-fe_mul121666_x64 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_sq2_x64 +.type fe_sq2_x64,@function +.align 4 +fe_sq2_x64: +#else +.section __TEXT,__text +.globl _fe_sq2_x64 +.p2align 2 +_fe_sq2_x64: +#endif /* __APPLE__ */ + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + pushq %rbx + # Square * 2 + # A[0] * A[1] + movq (%rsi), %rax + mulq 8(%rsi) + movq %rax, %r8 + movq %rdx, %r9 + # A[0] * A[2] + movq (%rsi), %rax + mulq 16(%rsi) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[0] * A[3] + movq (%rsi), %rax + mulq 24(%rsi) + xorq %r11, %r11 + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * A[2] + movq 8(%rsi), %rax + mulq 16(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[1] * A[3] + movq 8(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + # A[2] * A[3] + movq 16(%rsi), %rax + mulq 24(%rsi) + xorq %r13, %r13 + addq %rax, %r12 + adcq %rdx, %r13 + # Double + xorq %r14, %r14 + addq %r8, %r8 + adcq %r9, %r9 + adcq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + adcq %r13, %r13 + adcq $0x00, %r14 + # A[0] * A[0] + movq (%rsi), %rax + mulq %rax + movq %rax, %rcx + movq %rdx, %r15 + # A[1] * A[1] + movq 8(%rsi), %rax + mulq %rax + addq %r15, %r8 + adcq %rax, %r9 + adcq $0x00, %rdx + movq %rdx, %r15 + # A[2] * A[2] + movq 16(%rsi), %rax + mulq %rax + addq %r15, %r10 + adcq %rax, %r11 + adcq $0x00, %rdx + movq %rdx, %r15 + # A[3] * A[3] + movq 24(%rsi), %rax + mulq %rax + addq %rax, %r13 + adcq %rdx, %r14 + addq %r15, %r12 + adcq $0x00, %r13 + adcq $0x00, %r14 + # Reduce + movq $0x7fffffffffffffff, %rbx + xorq %rax, %rax + # Move top half into t4-t7 and remove top bit from t3 + shldq $3, %r14, %rax + shldq $2, %r13, %r14 + shldq $2, %r12, %r13 + shldq $2, %r11, %r12 + shldq $2, %r10, %r11 + shldq $0x01, %r9, %r10 + shldq $0x01, %r8, %r9 + shldq $0x01, %rcx, %r8 + shlq $0x01, %rcx + andq %rbx, %r10 + # Two out left, one in right + andq %rbx, %r14 + # Multiply top bits by 19*19 + imulq $0x169, %rax, %r15 + # Multiply top half by 19 + movq $19, %rax + mulq %r11 + xorq %r11, %r11 + addq %rax, %rcx + movq $19, %rax + adcq %rdx, %r11 + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + # Add remaining produce results in + addq %r15, %rcx + adcq %r11, %r8 + adcq %r12, %r9 + adcq %r13, %r10 + adcq %rax, %r10 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r10, %rdx + imulq $19, %rdx, %rax + andq %rbx, %r10 + addq %rax, %rcx + adcq $0x00, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + # Reduce if top bit set + movq %r10, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rbx, %r10 + addq %rax, %rcx + adcq $0x00, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + # Store + movq %rcx, (%rdi) + movq %r8, 8(%rdi) + movq %r9, 16(%rdi) + movq %r10, 24(%rdi) + popq %rbx + popq %r15 + popq %r14 + popq %r13 + popq %r12 + repz retq +#ifndef __APPLE__ +.size fe_sq2_x64,.-fe_sq2_x64 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_invert_x64 +.type fe_invert_x64,@function +.align 4 +fe_invert_x64: +#else +.section __TEXT,__text +.globl _fe_invert_x64 +.p2align 2 +_fe_invert_x64: +#endif /* __APPLE__ */ + subq $0x98, %rsp + # Invert + movq %rdi, 128(%rsp) + movq %rsi, 136(%rsp) + movq %rsp, %rdi + movq 136(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + movq %rsp, %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + movq 136(%rsp), %rsi + leaq 32(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + movq %rsp, %rdi + movq %rsp, %rsi + leaq 32(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + movq %rsp, %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi + leaq 64(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 32(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + movb $4, 144(%rsp) + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi +L_fe_invert_x64_1: +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + decb 144(%rsp) + jnz L_fe_invert_x64_1 + leaq 32(%rsp), %rdi + leaq 64(%rsp), %rsi + leaq 32(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 32(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + movb $9, 144(%rsp) + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi +L_fe_invert_x64_2: +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + decb 144(%rsp) + jnz L_fe_invert_x64_2 + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi + leaq 32(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 64(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + movb $19, 144(%rsp) + leaq 96(%rsp), %rdi + leaq 96(%rsp), %rsi +L_fe_invert_x64_3: +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + decb 144(%rsp) + jnz L_fe_invert_x64_3 + leaq 64(%rsp), %rdi + leaq 96(%rsp), %rsi + leaq 64(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + movb $9, 144(%rsp) + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi +L_fe_invert_x64_4: +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + decb 144(%rsp) + jnz L_fe_invert_x64_4 + leaq 32(%rsp), %rdi + leaq 64(%rsp), %rsi + leaq 32(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 32(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + movb $49, 144(%rsp) + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi +L_fe_invert_x64_5: +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + decb 144(%rsp) + jnz L_fe_invert_x64_5 + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi + leaq 32(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 64(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + movb $0x63, 144(%rsp) + leaq 96(%rsp), %rdi + leaq 96(%rsp), %rsi +L_fe_invert_x64_6: +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + decb 144(%rsp) + jnz L_fe_invert_x64_6 + leaq 64(%rsp), %rdi + leaq 96(%rsp), %rsi + leaq 64(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + movb $49, 144(%rsp) + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi +L_fe_invert_x64_7: +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + decb 144(%rsp) + jnz L_fe_invert_x64_7 + leaq 32(%rsp), %rdi + leaq 64(%rsp), %rsi + leaq 32(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + movb $4, 144(%rsp) + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi +L_fe_invert_x64_8: +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + decb 144(%rsp) + jnz L_fe_invert_x64_8 + movq 128(%rsp), %rdi + leaq 32(%rsp), %rsi + movq %rsp, %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + movq 136(%rsp), %rsi + movq 128(%rsp), %rdi + addq $0x98, %rsp + repz retq +#ifndef __APPLE__ +.text +.globl curve25519_x64 +.type curve25519_x64,@function +.align 4 +curve25519_x64: +#else +.section __TEXT,__text +.globl _curve25519_x64 +.p2align 2 +_curve25519_x64: +#endif /* __APPLE__ */ + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + pushq %rbx + pushq %rbp + movq %rdx, %r8 + subq $0xb8, %rsp + xorq %rbx, %rbx + movq %rdi, 176(%rsp) + # Set one + movq $0x01, (%rdi) + movq $0x00, 8(%rdi) + movq $0x00, 16(%rdi) + movq $0x00, 24(%rdi) + # Set zero + movq $0x00, (%rsp) + movq $0x00, 8(%rsp) + movq $0x00, 16(%rsp) + movq $0x00, 24(%rsp) + # Set one + movq $0x01, 32(%rsp) + movq $0x00, 40(%rsp) + movq $0x00, 48(%rsp) + movq $0x00, 56(%rsp) + # Copy + movq (%r8), %rcx + movq 8(%r8), %r9 + movq 16(%r8), %r10 + movq 24(%r8), %r11 + movq %rcx, 64(%rsp) + movq %r9, 72(%rsp) + movq %r10, 80(%rsp) + movq %r11, 88(%rsp) + movb $62, 168(%rsp) + movq $3, 160(%rsp) +L_curve25519_x64_words: +L_curve25519_x64_bits: + movq 160(%rsp), %r9 + movb 168(%rsp), %cl + movq (%rsi,%r9,8), %rbp + shrq %cl, %rbp + andq $0x01, %rbp + xorq %rbp, %rbx + negq %rbx + # Conditional Swap + movq (%rdi), %rcx + movq 8(%rdi), %r9 + movq 16(%rdi), %r10 + movq 24(%rdi), %r11 + xorq 64(%rsp), %rcx + xorq 72(%rsp), %r9 + xorq 80(%rsp), %r10 + xorq 88(%rsp), %r11 + andq %rbx, %rcx + andq %rbx, %r9 + andq %rbx, %r10 + andq %rbx, %r11 + xorq %rcx, (%rdi) + xorq %r9, 8(%rdi) + xorq %r10, 16(%rdi) + xorq %r11, 24(%rdi) + xorq %rcx, 64(%rsp) + xorq %r9, 72(%rsp) + xorq %r10, 80(%rsp) + xorq %r11, 88(%rsp) + # Conditional Swap + movq (%rsp), %rcx + movq 8(%rsp), %r9 + movq 16(%rsp), %r10 + movq 24(%rsp), %r11 + xorq 32(%rsp), %rcx + xorq 40(%rsp), %r9 + xorq 48(%rsp), %r10 + xorq 56(%rsp), %r11 + andq %rbx, %rcx + andq %rbx, %r9 + andq %rbx, %r10 + andq %rbx, %r11 + xorq %rcx, (%rsp) + xorq %r9, 8(%rsp) + xorq %r10, 16(%rsp) + xorq %r11, 24(%rsp) + xorq %rcx, 32(%rsp) + xorq %r9, 40(%rsp) + xorq %r10, 48(%rsp) + xorq %r11, 56(%rsp) + movq %rbp, %rbx + # Add + movq (%rdi), %rcx + movq 8(%rdi), %r9 + movq 16(%rdi), %r10 + movq 24(%rdi), %rbp + movq %rcx, %r12 + addq (%rsp), %rcx + movq %r9, %r13 + adcq 8(%rsp), %r9 + movq %r10, %r14 + adcq 16(%rsp), %r10 + movq %rbp, %r15 + adcq 24(%rsp), %rbp + movq $-19, %rax + movq %rbp, %r11 + movq $0x7fffffffffffffff, %rdx + sarq $63, %rbp + # Mask the modulus + andq %rbp, %rax + andq %rbp, %rdx + # Sub modulus (if overflow) + subq %rax, %rcx + sbbq %rbp, %r9 + sbbq %rbp, %r10 + sbbq %rdx, %r11 + # Sub + subq (%rsp), %r12 + movq $0x00, %rbp + sbbq 8(%rsp), %r13 + movq $-19, %rax + sbbq 16(%rsp), %r14 + movq $0x7fffffffffffffff, %rdx + sbbq 24(%rsp), %r15 + sbbq $0x00, %rbp + # Mask the modulus + andq %rbp, %rax + andq %rbp, %rdx + # Add modulus (if underflow) + addq %rax, %r12 + adcq %rbp, %r13 + adcq %rbp, %r14 + adcq %rdx, %r15 + movq %rcx, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq %r12, 128(%rsp) + movq %r13, 136(%rsp) + movq %r14, 144(%rsp) + movq %r15, 152(%rsp) + # Add + movq 64(%rsp), %rcx + movq 72(%rsp), %r9 + movq 80(%rsp), %r10 + movq 88(%rsp), %rbp + movq %rcx, %r12 + addq 32(%rsp), %rcx + movq %r9, %r13 + adcq 40(%rsp), %r9 + movq %r10, %r14 + adcq 48(%rsp), %r10 + movq %rbp, %r15 + adcq 56(%rsp), %rbp + movq $-19, %rax + movq %rbp, %r11 + movq $0x7fffffffffffffff, %rdx + sarq $63, %rbp + # Mask the modulus + andq %rbp, %rax + andq %rbp, %rdx + # Sub modulus (if overflow) + subq %rax, %rcx + sbbq %rbp, %r9 + sbbq %rbp, %r10 + sbbq %rdx, %r11 + # Sub + subq 32(%rsp), %r12 + movq $0x00, %rbp + sbbq 40(%rsp), %r13 + movq $-19, %rax + sbbq 48(%rsp), %r14 + movq $0x7fffffffffffffff, %rdx + sbbq 56(%rsp), %r15 + sbbq $0x00, %rbp + # Mask the modulus + andq %rbp, %rax + andq %rbp, %rdx + # Add modulus (if underflow) + addq %rax, %r12 + adcq %rbp, %r13 + adcq %rbp, %r14 + adcq %rdx, %r15 + movq %rcx, (%rsp) + movq %r9, 8(%rsp) + movq %r10, 16(%rsp) + movq %r11, 24(%rsp) + movq %r12, 96(%rsp) + movq %r13, 104(%rsp) + movq %r14, 112(%rsp) + movq %r15, 120(%rsp) + # Multiply + # A[0] * B[0] + movq (%rdi), %rax + mulq 96(%rsp) + movq %rax, %rcx + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rdi), %rax + mulq 96(%rsp) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq (%rdi), %rax + mulq 104(%rsp) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 16(%rdi), %rax + mulq 96(%rsp) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 8(%rdi), %rax + mulq 104(%rsp) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq (%rdi), %rax + mulq 112(%rsp) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 24(%rdi), %rax + mulq 96(%rsp) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 16(%rdi), %rax + mulq 104(%rsp) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 8(%rdi), %rax + mulq 112(%rsp) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq (%rdi), %rax + mulq 120(%rsp) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 24(%rdi), %rax + mulq 104(%rsp) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 16(%rdi), %rax + mulq 112(%rsp) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 8(%rdi), %rax + mulq 120(%rsp) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 24(%rdi), %rax + mulq 112(%rsp) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 16(%rdi), %rax + mulq 120(%rsp) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 24(%rdi), %rax + mulq 120(%rsp) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rbp + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rbp, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %rcx + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rbp, %r11 + addq %rax, %rcx + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rbp, %r11 + addq %rax, %rcx + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %rcx, 32(%rsp) + movq %r9, 40(%rsp) + movq %r10, 48(%rsp) + movq %r11, 56(%rsp) + # Multiply + # A[0] * B[0] + movq 128(%rsp), %rax + mulq (%rsp) + movq %rax, %rcx + movq %rdx, %r9 + # A[0] * B[1] + movq 136(%rsp), %rax + mulq (%rsp) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq 128(%rsp), %rax + mulq 8(%rsp) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 144(%rsp), %rax + mulq (%rsp) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 136(%rsp), %rax + mulq 8(%rsp) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq 128(%rsp), %rax + mulq 16(%rsp) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 152(%rsp), %rax + mulq (%rsp) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 144(%rsp), %rax + mulq 8(%rsp) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 136(%rsp), %rax + mulq 16(%rsp) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq 128(%rsp), %rax + mulq 24(%rsp) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 152(%rsp), %rax + mulq 8(%rsp) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 144(%rsp), %rax + mulq 16(%rsp) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 136(%rsp), %rax + mulq 24(%rsp) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 152(%rsp), %rax + mulq 16(%rsp) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 144(%rsp), %rax + mulq 24(%rsp) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 152(%rsp), %rax + mulq 24(%rsp) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rbp + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rbp, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %rcx + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rbp, %r11 + addq %rax, %rcx + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rbp, %r11 + addq %rax, %rcx + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %rcx, (%rsp) + movq %r9, 8(%rsp) + movq %r10, 16(%rsp) + movq %r11, 24(%rsp) + # Square + # A[0] * A[1] + movq 128(%rsp), %rax + mulq 136(%rsp) + movq %rax, %r9 + movq %rdx, %r10 + # A[0] * A[2] + movq 128(%rsp), %rax + mulq 144(%rsp) + xorq %r11, %r11 + addq %rax, %r10 + adcq %rdx, %r11 + # A[0] * A[3] + movq 128(%rsp), %rax + mulq 152(%rsp) + xorq %r12, %r12 + addq %rax, %r11 + adcq %rdx, %r12 + # A[1] * A[2] + movq 136(%rsp), %rax + mulq 144(%rsp) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * A[3] + movq 136(%rsp), %rax + mulq 152(%rsp) + addq %rax, %r12 + adcq %rdx, %r13 + # A[2] * A[3] + movq 144(%rsp), %rax + mulq 152(%rsp) + xorq %r14, %r14 + addq %rax, %r13 + adcq %rdx, %r14 + # Double + xorq %r15, %r15 + addq %r9, %r9 + adcq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + adcq %r13, %r13 + adcq %r14, %r14 + adcq $0x00, %r15 + # A[0] * A[0] + movq 128(%rsp), %rax + mulq %rax + movq %rax, %rcx + movq %rdx, %rbp + # A[1] * A[1] + movq 136(%rsp), %rax + mulq %rax + addq %rbp, %r9 + adcq %rax, %r10 + adcq $0x00, %rdx + movq %rdx, %rbp + # A[2] * A[2] + movq 144(%rsp), %rax + mulq %rax + addq %rbp, %r11 + adcq %rax, %r12 + adcq $0x00, %rdx + movq %rdx, %rbp + # A[3] * A[3] + movq 152(%rsp), %rax + mulq %rax + addq %rax, %r14 + adcq %rdx, %r15 + addq %rbp, %r13 + adcq $0x00, %r14 + adcq $0x00, %r15 + # Reduce + movq $0x7fffffffffffffff, %rbp + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rbp, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %rcx + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rbp, %r11 + addq %rax, %rcx + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rbp, %r11 + addq %rax, %rcx + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %rcx, 96(%rsp) + movq %r9, 104(%rsp) + movq %r10, 112(%rsp) + movq %r11, 120(%rsp) + # Square + # A[0] * A[1] + movq (%rdi), %rax + mulq 8(%rdi) + movq %rax, %r9 + movq %rdx, %r10 + # A[0] * A[2] + movq (%rdi), %rax + mulq 16(%rdi) + xorq %r11, %r11 + addq %rax, %r10 + adcq %rdx, %r11 + # A[0] * A[3] + movq (%rdi), %rax + mulq 24(%rdi) + xorq %r12, %r12 + addq %rax, %r11 + adcq %rdx, %r12 + # A[1] * A[2] + movq 8(%rdi), %rax + mulq 16(%rdi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * A[3] + movq 8(%rdi), %rax + mulq 24(%rdi) + addq %rax, %r12 + adcq %rdx, %r13 + # A[2] * A[3] + movq 16(%rdi), %rax + mulq 24(%rdi) + xorq %r14, %r14 + addq %rax, %r13 + adcq %rdx, %r14 + # Double + xorq %r15, %r15 + addq %r9, %r9 + adcq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + adcq %r13, %r13 + adcq %r14, %r14 + adcq $0x00, %r15 + # A[0] * A[0] + movq (%rdi), %rax + mulq %rax + movq %rax, %rcx + movq %rdx, %rbp + # A[1] * A[1] + movq 8(%rdi), %rax + mulq %rax + addq %rbp, %r9 + adcq %rax, %r10 + adcq $0x00, %rdx + movq %rdx, %rbp + # A[2] * A[2] + movq 16(%rdi), %rax + mulq %rax + addq %rbp, %r11 + adcq %rax, %r12 + adcq $0x00, %rdx + movq %rdx, %rbp + # A[3] * A[3] + movq 24(%rdi), %rax + mulq %rax + addq %rax, %r14 + adcq %rdx, %r15 + addq %rbp, %r13 + adcq $0x00, %r14 + adcq $0x00, %r15 + # Reduce + movq $0x7fffffffffffffff, %rbp + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rbp, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %rcx + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rbp, %r11 + addq %rax, %rcx + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rbp, %r11 + addq %rax, %rcx + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %rcx, 128(%rsp) + movq %r9, 136(%rsp) + movq %r10, 144(%rsp) + movq %r11, 152(%rsp) + # Add + movq 32(%rsp), %rcx + movq 40(%rsp), %r9 + movq 48(%rsp), %r10 + movq 56(%rsp), %rbp + movq %rcx, %r12 + addq (%rsp), %rcx + movq %r9, %r13 + adcq 8(%rsp), %r9 + movq %r10, %r14 + adcq 16(%rsp), %r10 + movq %rbp, %r15 + adcq 24(%rsp), %rbp + movq $-19, %rax + movq %rbp, %r11 + movq $0x7fffffffffffffff, %rdx + sarq $63, %rbp + # Mask the modulus + andq %rbp, %rax + andq %rbp, %rdx + # Sub modulus (if overflow) + subq %rax, %rcx + sbbq %rbp, %r9 + sbbq %rbp, %r10 + sbbq %rdx, %r11 + # Sub + subq (%rsp), %r12 + movq $0x00, %rbp + sbbq 8(%rsp), %r13 + movq $-19, %rax + sbbq 16(%rsp), %r14 + movq $0x7fffffffffffffff, %rdx + sbbq 24(%rsp), %r15 + sbbq $0x00, %rbp + # Mask the modulus + andq %rbp, %rax + andq %rbp, %rdx + # Add modulus (if underflow) + addq %rax, %r12 + adcq %rbp, %r13 + adcq %rbp, %r14 + adcq %rdx, %r15 + movq %rcx, 64(%rsp) + movq %r9, 72(%rsp) + movq %r10, 80(%rsp) + movq %r11, 88(%rsp) + movq %r12, (%rsp) + movq %r13, 8(%rsp) + movq %r14, 16(%rsp) + movq %r15, 24(%rsp) + # Multiply + # A[0] * B[0] + movq 96(%rsp), %rax + mulq 128(%rsp) + movq %rax, %rcx + movq %rdx, %r9 + # A[0] * B[1] + movq 104(%rsp), %rax + mulq 128(%rsp) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq 96(%rsp), %rax + mulq 136(%rsp) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 112(%rsp), %rax + mulq 128(%rsp) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 104(%rsp), %rax + mulq 136(%rsp) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq 96(%rsp), %rax + mulq 144(%rsp) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 120(%rsp), %rax + mulq 128(%rsp) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 112(%rsp), %rax + mulq 136(%rsp) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 104(%rsp), %rax + mulq 144(%rsp) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq 96(%rsp), %rax + mulq 152(%rsp) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 120(%rsp), %rax + mulq 136(%rsp) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 112(%rsp), %rax + mulq 144(%rsp) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 104(%rsp), %rax + mulq 152(%rsp) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 120(%rsp), %rax + mulq 144(%rsp) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 112(%rsp), %rax + mulq 152(%rsp) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 120(%rsp), %rax + mulq 152(%rsp) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rbp + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rbp, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %rcx + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rbp, %r11 + addq %rax, %rcx + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rbp, %r11 + addq %rax, %rcx + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %rcx, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + # Sub + movq 128(%rsp), %rcx + movq 136(%rsp), %r9 + movq 144(%rsp), %r10 + movq 152(%rsp), %r11 + subq 96(%rsp), %rcx + movq $0x00, %rbp + sbbq 104(%rsp), %r9 + movq $-19, %rax + sbbq 112(%rsp), %r10 + movq $0x7fffffffffffffff, %rdx + sbbq 120(%rsp), %r11 + sbbq $0x00, %rbp + # Mask the modulus + andq %rbp, %rax + andq %rbp, %rdx + # Add modulus (if underflow) + addq %rax, %rcx + adcq %rbp, %r9 + adcq %rbp, %r10 + adcq %rdx, %r11 + movq %rcx, 128(%rsp) + movq %r9, 136(%rsp) + movq %r10, 144(%rsp) + movq %r11, 152(%rsp) + # Square + # A[0] * A[1] + movq (%rsp), %rax + mulq 8(%rsp) + movq %rax, %r9 + movq %rdx, %r10 + # A[0] * A[2] + movq (%rsp), %rax + mulq 16(%rsp) + xorq %r11, %r11 + addq %rax, %r10 + adcq %rdx, %r11 + # A[0] * A[3] + movq (%rsp), %rax + mulq 24(%rsp) + xorq %r12, %r12 + addq %rax, %r11 + adcq %rdx, %r12 + # A[1] * A[2] + movq 8(%rsp), %rax + mulq 16(%rsp) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * A[3] + movq 8(%rsp), %rax + mulq 24(%rsp) + addq %rax, %r12 + adcq %rdx, %r13 + # A[2] * A[3] + movq 16(%rsp), %rax + mulq 24(%rsp) + xorq %r14, %r14 + addq %rax, %r13 + adcq %rdx, %r14 + # Double + xorq %r15, %r15 + addq %r9, %r9 + adcq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + adcq %r13, %r13 + adcq %r14, %r14 + adcq $0x00, %r15 + # A[0] * A[0] + movq (%rsp), %rax + mulq %rax + movq %rax, %rcx + movq %rdx, %rbp + # A[1] * A[1] + movq 8(%rsp), %rax + mulq %rax + addq %rbp, %r9 + adcq %rax, %r10 + adcq $0x00, %rdx + movq %rdx, %rbp + # A[2] * A[2] + movq 16(%rsp), %rax + mulq %rax + addq %rbp, %r11 + adcq %rax, %r12 + adcq $0x00, %rdx + movq %rdx, %rbp + # A[3] * A[3] + movq 24(%rsp), %rax + mulq %rax + addq %rax, %r14 + adcq %rdx, %r15 + addq %rbp, %r13 + adcq $0x00, %r14 + adcq $0x00, %r15 + # Reduce + movq $0x7fffffffffffffff, %rbp + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rbp, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %rcx + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rbp, %r11 + addq %rax, %rcx + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rbp, %r11 + addq %rax, %rcx + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %rcx, (%rsp) + movq %r9, 8(%rsp) + movq %r10, 16(%rsp) + movq %r11, 24(%rsp) + # Multiply by 121666 + movq $0x1db42, %rax + mulq 128(%rsp) + xorq %r10, %r10 + movq %rax, %rcx + movq %rdx, %r9 + movq $0x1db42, %rax + mulq 136(%rsp) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + movq $0x1db42, %rax + mulq 144(%rsp) + xorq %r13, %r13 + addq %rax, %r10 + adcq %rdx, %r11 + movq $0x1db42, %rax + mulq 152(%rsp) + movq $0x7fffffffffffffff, %r12 + addq %rax, %r11 + adcq %rdx, %r13 + shldq $0x01, %r11, %r13 + andq %r12, %r11 + movq $19, %rax + mulq %r13 + addq %rax, %rcx + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + movq %rcx, 32(%rsp) + movq %r9, 40(%rsp) + movq %r10, 48(%rsp) + movq %r11, 56(%rsp) + # Square + # A[0] * A[1] + movq 64(%rsp), %rax + mulq 72(%rsp) + movq %rax, %r9 + movq %rdx, %r10 + # A[0] * A[2] + movq 64(%rsp), %rax + mulq 80(%rsp) + xorq %r11, %r11 + addq %rax, %r10 + adcq %rdx, %r11 + # A[0] * A[3] + movq 64(%rsp), %rax + mulq 88(%rsp) + xorq %r12, %r12 + addq %rax, %r11 + adcq %rdx, %r12 + # A[1] * A[2] + movq 72(%rsp), %rax + mulq 80(%rsp) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * A[3] + movq 72(%rsp), %rax + mulq 88(%rsp) + addq %rax, %r12 + adcq %rdx, %r13 + # A[2] * A[3] + movq 80(%rsp), %rax + mulq 88(%rsp) + xorq %r14, %r14 + addq %rax, %r13 + adcq %rdx, %r14 + # Double + xorq %r15, %r15 + addq %r9, %r9 + adcq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + adcq %r13, %r13 + adcq %r14, %r14 + adcq $0x00, %r15 + # A[0] * A[0] + movq 64(%rsp), %rax + mulq %rax + movq %rax, %rcx + movq %rdx, %rbp + # A[1] * A[1] + movq 72(%rsp), %rax + mulq %rax + addq %rbp, %r9 + adcq %rax, %r10 + adcq $0x00, %rdx + movq %rdx, %rbp + # A[2] * A[2] + movq 80(%rsp), %rax + mulq %rax + addq %rbp, %r11 + adcq %rax, %r12 + adcq $0x00, %rdx + movq %rdx, %rbp + # A[3] * A[3] + movq 88(%rsp), %rax + mulq %rax + addq %rax, %r14 + adcq %rdx, %r15 + addq %rbp, %r13 + adcq $0x00, %r14 + adcq $0x00, %r15 + # Reduce + movq $0x7fffffffffffffff, %rbp + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rbp, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %rcx + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rbp, %r11 + addq %rax, %rcx + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rbp, %r11 + addq %rax, %rcx + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %rcx, 64(%rsp) + movq %r9, 72(%rsp) + movq %r10, 80(%rsp) + movq %r11, 88(%rsp) + # Add + movq 96(%rsp), %rcx + movq 104(%rsp), %r9 + addq 32(%rsp), %rcx + movq 112(%rsp), %r10 + adcq 40(%rsp), %r9 + movq 120(%rsp), %rbp + adcq 48(%rsp), %r10 + movq $-19, %rax + adcq 56(%rsp), %rbp + movq $0x7fffffffffffffff, %rdx + movq %rbp, %r11 + sarq $63, %rbp + # Mask the modulus + andq %rbp, %rax + andq %rbp, %rdx + # Sub modulus (if overflow) + subq %rax, %rcx + sbbq %rbp, %r9 + sbbq %rbp, %r10 + sbbq %rdx, %r11 + movq %rcx, 96(%rsp) + movq %r9, 104(%rsp) + movq %r10, 112(%rsp) + movq %r11, 120(%rsp) + # Multiply + # A[0] * B[0] + movq (%rsp), %rax + mulq (%r8) + movq %rax, %rcx + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rsp), %rax + mulq (%r8) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq (%rsp), %rax + mulq 8(%r8) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 16(%rsp), %rax + mulq (%r8) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 8(%rsp), %rax + mulq 8(%r8) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq (%rsp), %rax + mulq 16(%r8) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 24(%rsp), %rax + mulq (%r8) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 16(%rsp), %rax + mulq 8(%r8) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 8(%rsp), %rax + mulq 16(%r8) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq (%rsp), %rax + mulq 24(%r8) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 24(%rsp), %rax + mulq 8(%r8) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 16(%rsp), %rax + mulq 16(%r8) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 8(%rsp), %rax + mulq 24(%r8) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 24(%rsp), %rax + mulq 16(%r8) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 16(%rsp), %rax + mulq 24(%r8) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 24(%rsp), %rax + mulq 24(%r8) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rbp + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rbp, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %rcx + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rbp, %r11 + addq %rax, %rcx + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rbp, %r11 + addq %rax, %rcx + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %rcx, 32(%rsp) + movq %r9, 40(%rsp) + movq %r10, 48(%rsp) + movq %r11, 56(%rsp) + # Multiply + # A[0] * B[0] + movq 96(%rsp), %rax + mulq 128(%rsp) + movq %rax, %rcx + movq %rdx, %r9 + # A[0] * B[1] + movq 104(%rsp), %rax + mulq 128(%rsp) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq 96(%rsp), %rax + mulq 136(%rsp) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 112(%rsp), %rax + mulq 128(%rsp) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 104(%rsp), %rax + mulq 136(%rsp) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq 96(%rsp), %rax + mulq 144(%rsp) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 120(%rsp), %rax + mulq 128(%rsp) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 112(%rsp), %rax + mulq 136(%rsp) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 104(%rsp), %rax + mulq 144(%rsp) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq 96(%rsp), %rax + mulq 152(%rsp) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 120(%rsp), %rax + mulq 136(%rsp) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 112(%rsp), %rax + mulq 144(%rsp) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 104(%rsp), %rax + mulq 152(%rsp) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 120(%rsp), %rax + mulq 144(%rsp) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 112(%rsp), %rax + mulq 152(%rsp) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 120(%rsp), %rax + mulq 152(%rsp) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rbp + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rbp, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %rcx + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rbp, %r11 + addq %rax, %rcx + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rbp, %r11 + addq %rax, %rcx + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %rcx, (%rsp) + movq %r9, 8(%rsp) + movq %r10, 16(%rsp) + movq %r11, 24(%rsp) + decb 168(%rsp) + jge L_curve25519_x64_bits + movq $63, 168(%rsp) + decb 160(%rsp) + jge L_curve25519_x64_words + # Invert + leaq 32(%rsp), %rdi + movq %rsp, %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 32(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + movq %rsp, %rsi + leaq 64(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi + leaq 64(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 32(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi + leaq 96(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 64(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + movb $4, 160(%rsp) + leaq 96(%rsp), %rdi + leaq 96(%rsp), %rsi +L_curve25519_x64_inv_1: +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + decb 160(%rsp) + jnz L_curve25519_x64_inv_1 + leaq 64(%rsp), %rdi + leaq 96(%rsp), %rsi + leaq 64(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 64(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + movb $9, 160(%rsp) + leaq 96(%rsp), %rdi + leaq 96(%rsp), %rsi +L_curve25519_x64_inv_2: +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + decb 160(%rsp) + jnz L_curve25519_x64_inv_2 + leaq 96(%rsp), %rdi + leaq 96(%rsp), %rsi + leaq 64(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 128(%rsp), %rdi + leaq 96(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + movb $19, 160(%rsp) + leaq 128(%rsp), %rdi + leaq 128(%rsp), %rsi +L_curve25519_x64_inv_3: +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + decb 160(%rsp) + jnz L_curve25519_x64_inv_3 + leaq 96(%rsp), %rdi + leaq 128(%rsp), %rsi + leaq 96(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 96(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + movb $9, 160(%rsp) + leaq 96(%rsp), %rdi + leaq 96(%rsp), %rsi +L_curve25519_x64_inv_4: +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + decb 160(%rsp) + jnz L_curve25519_x64_inv_4 + leaq 64(%rsp), %rdi + leaq 96(%rsp), %rsi + leaq 64(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 64(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + movb $49, 160(%rsp) + leaq 96(%rsp), %rdi + leaq 96(%rsp), %rsi +L_curve25519_x64_inv_5: +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + decb 160(%rsp) + jnz L_curve25519_x64_inv_5 + leaq 96(%rsp), %rdi + leaq 96(%rsp), %rsi + leaq 64(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 128(%rsp), %rdi + leaq 96(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + movb $0x63, 160(%rsp) + leaq 128(%rsp), %rdi + leaq 128(%rsp), %rsi +L_curve25519_x64_inv_6: +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + decb 160(%rsp) + jnz L_curve25519_x64_inv_6 + leaq 96(%rsp), %rdi + leaq 128(%rsp), %rsi + leaq 96(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 96(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + movb $49, 160(%rsp) + leaq 96(%rsp), %rdi + leaq 96(%rsp), %rsi +L_curve25519_x64_inv_7: +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + decb 160(%rsp) + jnz L_curve25519_x64_inv_7 + leaq 64(%rsp), %rdi + leaq 96(%rsp), %rsi + leaq 64(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + movb $4, 160(%rsp) + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi +L_curve25519_x64_inv_8: +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + decb 160(%rsp) + jnz L_curve25519_x64_inv_8 + movq %rsp, %rdi + leaq 64(%rsp), %rsi + leaq 32(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + movq 176(%rsp), %rdi + # Multiply + # A[0] * B[0] + movq (%rsp), %rax + mulq (%rdi) + movq %rax, %rcx + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rsp), %rax + mulq (%rdi) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq (%rsp), %rax + mulq 8(%rdi) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 16(%rsp), %rax + mulq (%rdi) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 8(%rsp), %rax + mulq 8(%rdi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq (%rsp), %rax + mulq 16(%rdi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 24(%rsp), %rax + mulq (%rdi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 16(%rsp), %rax + mulq 8(%rdi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 8(%rsp), %rax + mulq 16(%rdi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq (%rsp), %rax + mulq 24(%rdi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 24(%rsp), %rax + mulq 8(%rdi) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 16(%rsp), %rax + mulq 16(%rdi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 8(%rsp), %rax + mulq 24(%rdi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 24(%rsp), %rax + mulq 16(%rdi) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 16(%rsp), %rax + mulq 24(%rdi) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 24(%rsp), %rax + mulq 24(%rdi) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rbp + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rbp, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %rcx + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rbp, %r11 + addq %rax, %rcx + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rbp, %r11 + addq %rax, %rcx + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %rcx, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + xorq %rax, %rax + addq $0xb8, %rsp + popq %rbp + popq %rbx + popq %r15 + popq %r14 + popq %r13 + popq %r12 + repz retq +#ifndef __APPLE__ +.size curve25519_x64,.-curve25519_x64 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_pow22523_x64 +.type fe_pow22523_x64,@function +.align 4 +fe_pow22523_x64: +#else +.section __TEXT,__text +.globl _fe_pow22523_x64 +.p2align 2 +_fe_pow22523_x64: +#endif /* __APPLE__ */ + subq $0x78, %rsp + # pow22523 + movq %rdi, 96(%rsp) + movq %rsi, 104(%rsp) + movq %rsp, %rdi + movq 104(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + movq %rsp, %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + movq 104(%rsp), %rsi + leaq 32(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + movq %rsp, %rdi + movq %rsp, %rsi + leaq 32(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + movq %rsp, %rdi + movq %rsp, %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + movq %rsp, %rdi + leaq 32(%rsp), %rsi + movq %rsp, %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + movq %rsp, %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + movb $4, 112(%rsp) + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi +L_fe_pow22523_x64_1: +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + decb 112(%rsp) + jnz L_fe_pow22523_x64_1 + movq %rsp, %rdi + leaq 32(%rsp), %rsi + movq %rsp, %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + movq %rsp, %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + movb $9, 112(%rsp) + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi +L_fe_pow22523_x64_2: +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + decb 112(%rsp) + jnz L_fe_pow22523_x64_2 + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi + movq %rsp, %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 32(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + movb $19, 112(%rsp) + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi +L_fe_pow22523_x64_3: +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + decb 112(%rsp) + jnz L_fe_pow22523_x64_3 + leaq 32(%rsp), %rdi + leaq 64(%rsp), %rsi + leaq 32(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + movb $9, 112(%rsp) + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi +L_fe_pow22523_x64_4: +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + decb 112(%rsp) + jnz L_fe_pow22523_x64_4 + movq %rsp, %rdi + leaq 32(%rsp), %rsi + movq %rsp, %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + movq %rsp, %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + movb $49, 112(%rsp) + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi +L_fe_pow22523_x64_5: +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + decb 112(%rsp) + jnz L_fe_pow22523_x64_5 + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi + movq %rsp, %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 32(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + movb $0x63, 112(%rsp) + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi +L_fe_pow22523_x64_6: +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + decb 112(%rsp) + jnz L_fe_pow22523_x64_6 + leaq 32(%rsp), %rdi + leaq 64(%rsp), %rsi + leaq 32(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + movb $49, 112(%rsp) + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi +L_fe_pow22523_x64_7: +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + decb 112(%rsp) + jnz L_fe_pow22523_x64_7 + movq %rsp, %rdi + leaq 32(%rsp), %rsi + movq %rsp, %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + movq %rsp, %rdi + movq %rsp, %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + movq %rsp, %rdi + movq %rsp, %rsi +#ifndef __APPLE__ + callq fe_sq_x64@plt +#else + callq _fe_sq_x64 +#endif /* __APPLE__ */ + movq 96(%rsp), %rdi + movq %rsp, %rsi + movq 104(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_x64@plt +#else + callq _fe_mul_x64 +#endif /* __APPLE__ */ + movq 104(%rsp), %rsi + movq 96(%rsp), %rdi + addq $0x78, %rsp + repz retq +#ifndef __APPLE__ +.text +.globl fe_ge_to_p2_x64 +.type fe_ge_to_p2_x64,@function +.align 4 +fe_ge_to_p2_x64: +#else +.section __TEXT,__text +.globl _fe_ge_to_p2_x64 +.p2align 2 +_fe_ge_to_p2_x64: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + subq $40, %rsp + movq %rsi, (%rsp) + movq %rdx, 8(%rsp) + movq %rcx, 16(%rsp) + movq %r8, 24(%rsp) + movq %r9, 32(%rsp) + movq 16(%rsp), %rsi + movq 88(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rax + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rbx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq (%rbx), %rax + mulq 8(%rsi) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 16(%rbx), %rax + mulq (%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 8(%rbx), %rax + mulq 8(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq (%rbx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 24(%rbx), %rax + mulq (%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 16(%rbx), %rax + mulq 8(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 8(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq (%rbx), %rax + mulq 24(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 24(%rbx), %rax + mulq 8(%rsi) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 16(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 8(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 24(%rbx), %rax + mulq 16(%rsi) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 16(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 24(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq (%rsp), %rdi + movq 24(%rsp), %rsi + movq 32(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rax + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rbx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq (%rbx), %rax + mulq 8(%rsi) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 16(%rbx), %rax + mulq (%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 8(%rbx), %rax + mulq 8(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq (%rbx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 24(%rbx), %rax + mulq (%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 16(%rbx), %rax + mulq 8(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 8(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq (%rbx), %rax + mulq 24(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 24(%rbx), %rax + mulq 8(%rsi) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 16(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 8(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 24(%rbx), %rax + mulq 16(%rsi) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 16(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 24(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 8(%rsp), %rdi + movq 32(%rsp), %rsi + movq 88(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rax + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rbx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq (%rbx), %rax + mulq 8(%rsi) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 16(%rbx), %rax + mulq (%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 8(%rbx), %rax + mulq 8(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq (%rbx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 24(%rbx), %rax + mulq (%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 16(%rbx), %rax + mulq 8(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 8(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq (%rbx), %rax + mulq 24(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 24(%rbx), %rax + mulq 8(%rsi) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 16(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 8(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 24(%rbx), %rax + mulq 16(%rsi) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 16(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 24(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + addq $40, %rsp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size fe_ge_to_p2_x64,.-fe_ge_to_p2_x64 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_ge_to_p3_x64 +.type fe_ge_to_p3_x64,@function +.align 4 +fe_ge_to_p3_x64: +#else +.section __TEXT,__text +.globl _fe_ge_to_p3_x64 +.p2align 2 +_fe_ge_to_p3_x64: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + subq $40, %rsp + movq %rsi, (%rsp) + movq %rdx, 8(%rsp) + movq %rcx, 16(%rsp) + movq %r8, 24(%rsp) + movq %r9, 32(%rsp) + movq 24(%rsp), %rsi + movq 96(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rax + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rbx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq (%rbx), %rax + mulq 8(%rsi) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 16(%rbx), %rax + mulq (%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 8(%rbx), %rax + mulq 8(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq (%rbx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 24(%rbx), %rax + mulq (%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 16(%rbx), %rax + mulq 8(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 8(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq (%rbx), %rax + mulq 24(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 24(%rbx), %rax + mulq 8(%rsi) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 16(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 8(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 24(%rbx), %rax + mulq 16(%rsi) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 16(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 24(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq (%rsp), %rdi + movq 32(%rsp), %rsi + movq 88(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rax + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rbx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq (%rbx), %rax + mulq 8(%rsi) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 16(%rbx), %rax + mulq (%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 8(%rbx), %rax + mulq 8(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq (%rbx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 24(%rbx), %rax + mulq (%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 16(%rbx), %rax + mulq 8(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 8(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq (%rbx), %rax + mulq 24(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 24(%rbx), %rax + mulq 8(%rsi) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 16(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 8(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 24(%rbx), %rax + mulq 16(%rsi) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 16(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 24(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 8(%rsp), %rdi + movq 88(%rsp), %rsi + movq 96(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rax + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rbx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq (%rbx), %rax + mulq 8(%rsi) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 16(%rbx), %rax + mulq (%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 8(%rbx), %rax + mulq 8(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq (%rbx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 24(%rbx), %rax + mulq (%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 16(%rbx), %rax + mulq 8(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 8(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq (%rbx), %rax + mulq 24(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 24(%rbx), %rax + mulq 8(%rsi) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 16(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 8(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 24(%rbx), %rax + mulq 16(%rsi) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 16(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 24(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 16(%rsp), %rdi + movq 24(%rsp), %rsi + movq 32(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rax + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rbx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq (%rbx), %rax + mulq 8(%rsi) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 16(%rbx), %rax + mulq (%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 8(%rbx), %rax + mulq 8(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq (%rbx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 24(%rbx), %rax + mulq (%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 16(%rbx), %rax + mulq 8(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 8(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq (%rbx), %rax + mulq 24(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 24(%rbx), %rax + mulq 8(%rsi) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 16(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 8(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 24(%rbx), %rax + mulq 16(%rsi) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 16(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 24(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + addq $40, %rsp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size fe_ge_to_p3_x64,.-fe_ge_to_p3_x64 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_ge_dbl_x64 +.type fe_ge_dbl_x64,@function +.align 4 +fe_ge_dbl_x64: +#else +.section __TEXT,__text +.globl _fe_ge_dbl_x64 +.p2align 2 +_fe_ge_dbl_x64: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + subq $0x50, %rsp + movq %rdi, (%rsp) + movq %rsi, 8(%rsp) + movq %rdx, 16(%rsp) + movq %rcx, 24(%rsp) + movq %r8, 32(%rsp) + movq %r9, 40(%rsp) + movq (%rsp), %rdi + movq 32(%rsp), %rsi + # Square + # A[0] * A[1] + movq (%rsi), %rax + mulq 8(%rsi) + movq %rax, %r9 + movq %rdx, %r10 + # A[0] * A[2] + movq (%rsi), %rax + mulq 16(%rsi) + xorq %r11, %r11 + addq %rax, %r10 + adcq %rdx, %r11 + # A[0] * A[3] + movq (%rsi), %rax + mulq 24(%rsi) + xorq %r12, %r12 + addq %rax, %r11 + adcq %rdx, %r12 + # A[1] * A[2] + movq 8(%rsi), %rax + mulq 16(%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * A[3] + movq 8(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + # A[2] * A[3] + movq 16(%rsi), %rax + mulq 24(%rsi) + xorq %r14, %r14 + addq %rax, %r13 + adcq %rdx, %r14 + # Double + xorq %r15, %r15 + addq %r9, %r9 + adcq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + adcq %r13, %r13 + adcq %r14, %r14 + adcq $0x00, %r15 + # A[0] * A[0] + movq (%rsi), %rax + mulq %rax + movq %rax, %r8 + movq %rdx, %rcx + # A[1] * A[1] + movq 8(%rsi), %rax + mulq %rax + addq %rcx, %r9 + adcq %rax, %r10 + adcq $0x00, %rdx + movq %rdx, %rcx + # A[2] * A[2] + movq 16(%rsi), %rax + mulq %rax + addq %rcx, %r11 + adcq %rax, %r12 + adcq $0x00, %rdx + movq %rdx, %rcx + # A[3] * A[3] + movq 24(%rsi), %rax + mulq %rax + addq %rax, %r14 + adcq %rdx, %r15 + addq %rcx, %r13 + adcq $0x00, %r14 + adcq $0x00, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 16(%rsp), %rdi + movq 40(%rsp), %rsi + # Square + # A[0] * A[1] + movq (%rsi), %rax + mulq 8(%rsi) + movq %rax, %r9 + movq %rdx, %r10 + # A[0] * A[2] + movq (%rsi), %rax + mulq 16(%rsi) + xorq %r11, %r11 + addq %rax, %r10 + adcq %rdx, %r11 + # A[0] * A[3] + movq (%rsi), %rax + mulq 24(%rsi) + xorq %r12, %r12 + addq %rax, %r11 + adcq %rdx, %r12 + # A[1] * A[2] + movq 8(%rsi), %rax + mulq 16(%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * A[3] + movq 8(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + # A[2] * A[3] + movq 16(%rsi), %rax + mulq 24(%rsi) + xorq %r14, %r14 + addq %rax, %r13 + adcq %rdx, %r14 + # Double + xorq %r15, %r15 + addq %r9, %r9 + adcq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + adcq %r13, %r13 + adcq %r14, %r14 + adcq $0x00, %r15 + # A[0] * A[0] + movq (%rsi), %rax + mulq %rax + movq %rax, %r8 + movq %rdx, %rcx + # A[1] * A[1] + movq 8(%rsi), %rax + mulq %rax + addq %rcx, %r9 + adcq %rax, %r10 + adcq $0x00, %rdx + movq %rdx, %rcx + # A[2] * A[2] + movq 16(%rsi), %rax + mulq %rax + addq %rcx, %r11 + adcq %rax, %r12 + adcq $0x00, %rdx + movq %rdx, %rcx + # A[3] * A[3] + movq 24(%rsi), %rax + mulq %rax + addq %rax, %r14 + adcq %rdx, %r15 + addq %rcx, %r13 + adcq $0x00, %r14 + adcq $0x00, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 24(%rsp), %rdi + movq 128(%rsp), %rsi + # Square * 2 + # A[0] * A[1] + movq (%rsi), %rax + mulq 8(%rsi) + movq %rax, %r9 + movq %rdx, %r10 + # A[0] * A[2] + movq (%rsi), %rax + mulq 16(%rsi) + xorq %r11, %r11 + addq %rax, %r10 + adcq %rdx, %r11 + # A[0] * A[3] + movq (%rsi), %rax + mulq 24(%rsi) + xorq %r12, %r12 + addq %rax, %r11 + adcq %rdx, %r12 + # A[1] * A[2] + movq 8(%rsi), %rax + mulq 16(%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * A[3] + movq 8(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + # A[2] * A[3] + movq 16(%rsi), %rax + mulq 24(%rsi) + xorq %r14, %r14 + addq %rax, %r13 + adcq %rdx, %r14 + # Double + xorq %r15, %r15 + addq %r9, %r9 + adcq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + adcq %r13, %r13 + adcq %r14, %r14 + adcq $0x00, %r15 + # A[0] * A[0] + movq (%rsi), %rax + mulq %rax + movq %rax, %r8 + movq %rdx, %rcx + # A[1] * A[1] + movq 8(%rsi), %rax + mulq %rax + addq %rcx, %r9 + adcq %rax, %r10 + adcq $0x00, %rdx + movq %rdx, %rcx + # A[2] * A[2] + movq 16(%rsi), %rax + mulq %rax + addq %rcx, %r11 + adcq %rax, %r12 + adcq $0x00, %rdx + movq %rdx, %rcx + # A[3] * A[3] + movq 24(%rsi), %rax + mulq %rax + addq %rax, %r14 + adcq %rdx, %r15 + addq %rcx, %r13 + adcq $0x00, %r14 + adcq $0x00, %r15 + # Reduce + movq $0x7fffffffffffffff, %rbx + xorq %rax, %rax + # Move top half into t4-t7 and remove top bit from t3 + shldq $3, %r15, %rax + shldq $2, %r14, %r15 + shldq $2, %r13, %r14 + shldq $2, %r12, %r13 + shldq $2, %r11, %r12 + shldq $0x01, %r10, %r11 + shldq $0x01, %r9, %r10 + shldq $0x01, %r8, %r9 + shlq $0x01, %r8 + andq %rbx, %r11 + # Two out left, one in right + andq %rbx, %r15 + # Multiply top bits by 19*19 + imulq $0x169, %rax, %rcx + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining produce results in + addq %rcx, %r8 + adcq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rbx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rbx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 8(%rsp), %rdi + movq 32(%rsp), %rsi + movq 40(%rsp), %rbx + # Add + movq (%rsi), %r8 + movq 8(%rsi), %r9 + addq (%rbx), %r8 + movq 16(%rsi), %r10 + adcq 8(%rbx), %r9 + movq 24(%rsi), %rcx + adcq 16(%rbx), %r10 + movq $-19, %rax + adcq 24(%rbx), %rcx + movq $0x7fffffffffffffff, %rdx + movq %rcx, %r11 + sarq $63, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Sub modulus (if overflow) + subq %rax, %r8 + sbbq %rcx, %r9 + sbbq %rcx, %r10 + sbbq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + leaq 48(%rsp), %rdi + movq 8(%rsp), %rsi + # Square + # A[0] * A[1] + movq (%rsi), %rax + mulq 8(%rsi) + movq %rax, %r9 + movq %rdx, %r10 + # A[0] * A[2] + movq (%rsi), %rax + mulq 16(%rsi) + xorq %r11, %r11 + addq %rax, %r10 + adcq %rdx, %r11 + # A[0] * A[3] + movq (%rsi), %rax + mulq 24(%rsi) + xorq %r12, %r12 + addq %rax, %r11 + adcq %rdx, %r12 + # A[1] * A[2] + movq 8(%rsi), %rax + mulq 16(%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * A[3] + movq 8(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + # A[2] * A[3] + movq 16(%rsi), %rax + mulq 24(%rsi) + xorq %r14, %r14 + addq %rax, %r13 + adcq %rdx, %r14 + # Double + xorq %r15, %r15 + addq %r9, %r9 + adcq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + adcq %r13, %r13 + adcq %r14, %r14 + adcq $0x00, %r15 + # A[0] * A[0] + movq (%rsi), %rax + mulq %rax + movq %rax, %r8 + movq %rdx, %rcx + # A[1] * A[1] + movq 8(%rsi), %rax + mulq %rax + addq %rcx, %r9 + adcq %rax, %r10 + adcq $0x00, %rdx + movq %rdx, %rcx + # A[2] * A[2] + movq 16(%rsi), %rax + mulq %rax + addq %rcx, %r11 + adcq %rax, %r12 + adcq $0x00, %rdx + movq %rdx, %rcx + # A[3] * A[3] + movq 24(%rsi), %rax + mulq %rax + addq %rax, %r14 + adcq %rdx, %r15 + addq %rcx, %r13 + adcq $0x00, %r14 + adcq $0x00, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 8(%rsp), %rdi + movq 16(%rsp), %rsi + movq (%rsp), %rbx + # Add + movq (%rsi), %r8 + movq 8(%rsi), %r9 + addq (%rbx), %r8 + movq 16(%rsi), %r10 + adcq 8(%rbx), %r9 + movq 24(%rsi), %rcx + adcq 16(%rbx), %r10 + movq $-19, %rax + adcq 24(%rbx), %rcx + movq $0x7fffffffffffffff, %rdx + movq %rcx, %r11 + sarq $63, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Sub modulus (if overflow) + subq %rax, %r8 + sbbq %rcx, %r9 + sbbq %rcx, %r10 + sbbq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 16(%rsp), %rdi + movq 16(%rsp), %rsi + movq (%rsp), %rbx + # Sub + movq (%rsi), %r8 + movq 8(%rsi), %r9 + movq 16(%rsi), %r10 + movq 24(%rsi), %r11 + subq (%rbx), %r8 + movq $0x00, %rcx + sbbq 8(%rbx), %r9 + movq $-19, %rax + sbbq 16(%rbx), %r10 + movq $0x7fffffffffffffff, %rdx + sbbq 24(%rbx), %r11 + sbbq $0x00, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Add modulus (if underflow) + addq %rax, %r8 + adcq %rcx, %r9 + adcq %rcx, %r10 + adcq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq (%rsp), %rdi + leaq 48(%rsp), %rsi + movq 8(%rsp), %rbx + # Sub + movq (%rsi), %r8 + movq 8(%rsi), %r9 + movq 16(%rsi), %r10 + movq 24(%rsi), %r11 + subq (%rbx), %r8 + movq $0x00, %rcx + sbbq 8(%rbx), %r9 + movq $-19, %rax + sbbq 16(%rbx), %r10 + movq $0x7fffffffffffffff, %rdx + sbbq 24(%rbx), %r11 + sbbq $0x00, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Add modulus (if underflow) + addq %rax, %r8 + adcq %rcx, %r9 + adcq %rcx, %r10 + adcq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 24(%rsp), %rdi + movq 24(%rsp), %rsi + movq 16(%rsp), %rbx + # Sub + movq (%rsi), %r8 + movq 8(%rsi), %r9 + movq 16(%rsi), %r10 + movq 24(%rsi), %r11 + subq (%rbx), %r8 + movq $0x00, %rcx + sbbq 8(%rbx), %r9 + movq $-19, %rax + sbbq 16(%rbx), %r10 + movq $0x7fffffffffffffff, %rdx + sbbq 24(%rbx), %r11 + sbbq $0x00, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Add modulus (if underflow) + addq %rax, %r8 + adcq %rcx, %r9 + adcq %rcx, %r10 + adcq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + addq $0x50, %rsp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size fe_ge_dbl_x64,.-fe_ge_dbl_x64 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_ge_madd_x64 +.type fe_ge_madd_x64,@function +.align 4 +fe_ge_madd_x64: +#else +.section __TEXT,__text +.globl _fe_ge_madd_x64 +.p2align 2 +_fe_ge_madd_x64: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + subq $0x50, %rsp + movq %rdi, (%rsp) + movq %rsi, 8(%rsp) + movq %rdx, 16(%rsp) + movq %rcx, 24(%rsp) + movq %r8, 32(%rsp) + movq %r9, 40(%rsp) + movq (%rsp), %rdi + movq 40(%rsp), %rsi + movq 32(%rsp), %rbx + # Add + movq (%rsi), %r8 + movq 8(%rsi), %r9 + addq (%rbx), %r8 + movq 16(%rsi), %r10 + adcq 8(%rbx), %r9 + movq 24(%rsi), %rcx + adcq 16(%rbx), %r10 + movq $-19, %rax + adcq 24(%rbx), %rcx + movq $0x7fffffffffffffff, %rdx + movq %rcx, %r11 + sarq $63, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Sub modulus (if overflow) + subq %rax, %r8 + sbbq %rcx, %r9 + sbbq %rcx, %r10 + sbbq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 8(%rsp), %rdi + movq 40(%rsp), %rsi + movq 32(%rsp), %rbx + # Sub + movq (%rsi), %r8 + movq 8(%rsi), %r9 + movq 16(%rsi), %r10 + movq 24(%rsi), %r11 + subq (%rbx), %r8 + movq $0x00, %rcx + sbbq 8(%rbx), %r9 + movq $-19, %rax + sbbq 16(%rbx), %r10 + movq $0x7fffffffffffffff, %rdx + sbbq 24(%rbx), %r11 + sbbq $0x00, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Add modulus (if underflow) + addq %rax, %r8 + adcq %rcx, %r9 + adcq %rcx, %r10 + adcq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 16(%rsp), %rdi + movq (%rsp), %rsi + movq 152(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rax + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rbx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq (%rbx), %rax + mulq 8(%rsi) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 16(%rbx), %rax + mulq (%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 8(%rbx), %rax + mulq 8(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq (%rbx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 24(%rbx), %rax + mulq (%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 16(%rbx), %rax + mulq 8(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 8(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq (%rbx), %rax + mulq 24(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 24(%rbx), %rax + mulq 8(%rsi) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 16(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 8(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 24(%rbx), %rax + mulq 16(%rsi) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 16(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 24(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 8(%rsp), %rdi + movq 8(%rsp), %rsi + movq 160(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rax + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rbx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq (%rbx), %rax + mulq 8(%rsi) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 16(%rbx), %rax + mulq (%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 8(%rbx), %rax + mulq 8(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq (%rbx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 24(%rbx), %rax + mulq (%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 16(%rbx), %rax + mulq 8(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 8(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq (%rbx), %rax + mulq 24(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 24(%rbx), %rax + mulq 8(%rsi) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 16(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 8(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 24(%rbx), %rax + mulq 16(%rsi) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 16(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 24(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 24(%rsp), %rdi + movq 144(%rsp), %rsi + movq 136(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rax + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rbx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq (%rbx), %rax + mulq 8(%rsi) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 16(%rbx), %rax + mulq (%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 8(%rbx), %rax + mulq 8(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq (%rbx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 24(%rbx), %rax + mulq (%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 16(%rbx), %rax + mulq 8(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 8(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq (%rbx), %rax + mulq 24(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 24(%rbx), %rax + mulq 8(%rsi) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 16(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 8(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 24(%rbx), %rax + mulq 16(%rsi) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 16(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 24(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + leaq 48(%rsp), %rdi + movq 128(%rsp), %rsi + movq 128(%rsp), %rbx + # Add + movq (%rsi), %r8 + movq 8(%rsi), %r9 + addq (%rbx), %r8 + movq 16(%rsi), %r10 + adcq 8(%rbx), %r9 + movq 24(%rsi), %rcx + adcq 16(%rbx), %r10 + movq $-19, %rax + adcq 24(%rbx), %rcx + movq $0x7fffffffffffffff, %rdx + movq %rcx, %r11 + sarq $63, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Sub modulus (if overflow) + subq %rax, %r8 + sbbq %rcx, %r9 + sbbq %rcx, %r10 + sbbq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq (%rsp), %rdi + movq 16(%rsp), %rsi + movq 8(%rsp), %rbx + # Sub + movq (%rsi), %r8 + movq 8(%rsi), %r9 + movq 16(%rsi), %r10 + movq 24(%rsi), %r11 + subq (%rbx), %r8 + movq $0x00, %rcx + sbbq 8(%rbx), %r9 + movq $-19, %rax + sbbq 16(%rbx), %r10 + movq $0x7fffffffffffffff, %rdx + sbbq 24(%rbx), %r11 + sbbq $0x00, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Add modulus (if underflow) + addq %rax, %r8 + adcq %rcx, %r9 + adcq %rcx, %r10 + adcq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 8(%rsp), %rdi + movq 16(%rsp), %rsi + movq 8(%rsp), %rbx + # Add + movq (%rsi), %r8 + movq 8(%rsi), %r9 + addq (%rbx), %r8 + movq 16(%rsi), %r10 + adcq 8(%rbx), %r9 + movq 24(%rsi), %rcx + adcq 16(%rbx), %r10 + movq $-19, %rax + adcq 24(%rbx), %rcx + movq $0x7fffffffffffffff, %rdx + movq %rcx, %r11 + sarq $63, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Sub modulus (if overflow) + subq %rax, %r8 + sbbq %rcx, %r9 + sbbq %rcx, %r10 + sbbq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 16(%rsp), %rdi + leaq 48(%rsp), %rsi + movq 24(%rsp), %rbx + # Add + movq (%rsi), %r8 + movq 8(%rsi), %r9 + addq (%rbx), %r8 + movq 16(%rsi), %r10 + adcq 8(%rbx), %r9 + movq 24(%rsi), %rcx + adcq 16(%rbx), %r10 + movq $-19, %rax + adcq 24(%rbx), %rcx + movq $0x7fffffffffffffff, %rdx + movq %rcx, %r11 + sarq $63, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Sub modulus (if overflow) + subq %rax, %r8 + sbbq %rcx, %r9 + sbbq %rcx, %r10 + sbbq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 24(%rsp), %rdi + leaq 48(%rsp), %rsi + movq 24(%rsp), %rbx + # Sub + movq (%rsi), %r8 + movq 8(%rsi), %r9 + movq 16(%rsi), %r10 + movq 24(%rsi), %r11 + subq (%rbx), %r8 + movq $0x00, %rcx + sbbq 8(%rbx), %r9 + movq $-19, %rax + sbbq 16(%rbx), %r10 + movq $0x7fffffffffffffff, %rdx + sbbq 24(%rbx), %r11 + sbbq $0x00, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Add modulus (if underflow) + addq %rax, %r8 + adcq %rcx, %r9 + adcq %rcx, %r10 + adcq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + addq $0x50, %rsp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size fe_ge_madd_x64,.-fe_ge_madd_x64 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_ge_msub_x64 +.type fe_ge_msub_x64,@function +.align 4 +fe_ge_msub_x64: +#else +.section __TEXT,__text +.globl _fe_ge_msub_x64 +.p2align 2 +_fe_ge_msub_x64: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + subq $0x50, %rsp + movq %rdi, (%rsp) + movq %rsi, 8(%rsp) + movq %rdx, 16(%rsp) + movq %rcx, 24(%rsp) + movq %r8, 32(%rsp) + movq %r9, 40(%rsp) + movq (%rsp), %rdi + movq 40(%rsp), %rsi + movq 32(%rsp), %rbx + # Add + movq (%rsi), %r8 + movq 8(%rsi), %r9 + addq (%rbx), %r8 + movq 16(%rsi), %r10 + adcq 8(%rbx), %r9 + movq 24(%rsi), %rcx + adcq 16(%rbx), %r10 + movq $-19, %rax + adcq 24(%rbx), %rcx + movq $0x7fffffffffffffff, %rdx + movq %rcx, %r11 + sarq $63, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Sub modulus (if overflow) + subq %rax, %r8 + sbbq %rcx, %r9 + sbbq %rcx, %r10 + sbbq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 8(%rsp), %rdi + movq 40(%rsp), %rsi + movq 32(%rsp), %rbx + # Sub + movq (%rsi), %r8 + movq 8(%rsi), %r9 + movq 16(%rsi), %r10 + movq 24(%rsi), %r11 + subq (%rbx), %r8 + movq $0x00, %rcx + sbbq 8(%rbx), %r9 + movq $-19, %rax + sbbq 16(%rbx), %r10 + movq $0x7fffffffffffffff, %rdx + sbbq 24(%rbx), %r11 + sbbq $0x00, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Add modulus (if underflow) + addq %rax, %r8 + adcq %rcx, %r9 + adcq %rcx, %r10 + adcq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 16(%rsp), %rdi + movq (%rsp), %rsi + movq 160(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rax + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rbx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq (%rbx), %rax + mulq 8(%rsi) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 16(%rbx), %rax + mulq (%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 8(%rbx), %rax + mulq 8(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq (%rbx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 24(%rbx), %rax + mulq (%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 16(%rbx), %rax + mulq 8(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 8(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq (%rbx), %rax + mulq 24(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 24(%rbx), %rax + mulq 8(%rsi) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 16(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 8(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 24(%rbx), %rax + mulq 16(%rsi) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 16(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 24(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 8(%rsp), %rdi + movq 8(%rsp), %rsi + movq 152(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rax + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rbx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq (%rbx), %rax + mulq 8(%rsi) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 16(%rbx), %rax + mulq (%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 8(%rbx), %rax + mulq 8(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq (%rbx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 24(%rbx), %rax + mulq (%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 16(%rbx), %rax + mulq 8(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 8(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq (%rbx), %rax + mulq 24(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 24(%rbx), %rax + mulq 8(%rsi) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 16(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 8(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 24(%rbx), %rax + mulq 16(%rsi) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 16(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 24(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 24(%rsp), %rdi + movq 144(%rsp), %rsi + movq 136(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rax + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rbx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq (%rbx), %rax + mulq 8(%rsi) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 16(%rbx), %rax + mulq (%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 8(%rbx), %rax + mulq 8(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq (%rbx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 24(%rbx), %rax + mulq (%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 16(%rbx), %rax + mulq 8(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 8(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq (%rbx), %rax + mulq 24(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 24(%rbx), %rax + mulq 8(%rsi) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 16(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 8(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 24(%rbx), %rax + mulq 16(%rsi) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 16(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 24(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + leaq 48(%rsp), %rdi + movq 128(%rsp), %rsi + movq 128(%rsp), %rbx + # Add + movq (%rsi), %r8 + movq 8(%rsi), %r9 + addq (%rbx), %r8 + movq 16(%rsi), %r10 + adcq 8(%rbx), %r9 + movq 24(%rsi), %rcx + adcq 16(%rbx), %r10 + movq $-19, %rax + adcq 24(%rbx), %rcx + movq $0x7fffffffffffffff, %rdx + movq %rcx, %r11 + sarq $63, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Sub modulus (if overflow) + subq %rax, %r8 + sbbq %rcx, %r9 + sbbq %rcx, %r10 + sbbq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq (%rsp), %rdi + movq 16(%rsp), %rsi + movq 8(%rsp), %rbx + # Sub + movq (%rsi), %r8 + movq 8(%rsi), %r9 + movq 16(%rsi), %r10 + movq 24(%rsi), %r11 + subq (%rbx), %r8 + movq $0x00, %rcx + sbbq 8(%rbx), %r9 + movq $-19, %rax + sbbq 16(%rbx), %r10 + movq $0x7fffffffffffffff, %rdx + sbbq 24(%rbx), %r11 + sbbq $0x00, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Add modulus (if underflow) + addq %rax, %r8 + adcq %rcx, %r9 + adcq %rcx, %r10 + adcq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 8(%rsp), %rdi + movq 16(%rsp), %rsi + movq 8(%rsp), %rbx + # Add + movq (%rsi), %r8 + movq 8(%rsi), %r9 + addq (%rbx), %r8 + movq 16(%rsi), %r10 + adcq 8(%rbx), %r9 + movq 24(%rsi), %rcx + adcq 16(%rbx), %r10 + movq $-19, %rax + adcq 24(%rbx), %rcx + movq $0x7fffffffffffffff, %rdx + movq %rcx, %r11 + sarq $63, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Sub modulus (if overflow) + subq %rax, %r8 + sbbq %rcx, %r9 + sbbq %rcx, %r10 + sbbq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 16(%rsp), %rdi + leaq 48(%rsp), %rsi + movq 24(%rsp), %rbx + # Sub + movq (%rsi), %r8 + movq 8(%rsi), %r9 + movq 16(%rsi), %r10 + movq 24(%rsi), %r11 + subq (%rbx), %r8 + movq $0x00, %rcx + sbbq 8(%rbx), %r9 + movq $-19, %rax + sbbq 16(%rbx), %r10 + movq $0x7fffffffffffffff, %rdx + sbbq 24(%rbx), %r11 + sbbq $0x00, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Add modulus (if underflow) + addq %rax, %r8 + adcq %rcx, %r9 + adcq %rcx, %r10 + adcq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 24(%rsp), %rdi + leaq 48(%rsp), %rsi + movq 24(%rsp), %rbx + # Add + movq (%rsi), %r8 + movq 8(%rsi), %r9 + addq (%rbx), %r8 + movq 16(%rsi), %r10 + adcq 8(%rbx), %r9 + movq 24(%rsi), %rcx + adcq 16(%rbx), %r10 + movq $-19, %rax + adcq 24(%rbx), %rcx + movq $0x7fffffffffffffff, %rdx + movq %rcx, %r11 + sarq $63, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Sub modulus (if overflow) + subq %rax, %r8 + sbbq %rcx, %r9 + sbbq %rcx, %r10 + sbbq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + addq $0x50, %rsp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size fe_ge_msub_x64,.-fe_ge_msub_x64 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_ge_add_x64 +.type fe_ge_add_x64,@function +.align 4 +fe_ge_add_x64: +#else +.section __TEXT,__text +.globl _fe_ge_add_x64 +.p2align 2 +_fe_ge_add_x64: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + subq $0x50, %rsp + movq %rdi, (%rsp) + movq %rsi, 8(%rsp) + movq %rdx, 16(%rsp) + movq %rcx, 24(%rsp) + movq %r8, 32(%rsp) + movq %r9, 40(%rsp) + movq (%rsp), %rdi + movq 40(%rsp), %rsi + movq 32(%rsp), %rbx + # Add + movq (%rsi), %r8 + movq 8(%rsi), %r9 + addq (%rbx), %r8 + movq 16(%rsi), %r10 + adcq 8(%rbx), %r9 + movq 24(%rsi), %rcx + adcq 16(%rbx), %r10 + movq $-19, %rax + adcq 24(%rbx), %rcx + movq $0x7fffffffffffffff, %rdx + movq %rcx, %r11 + sarq $63, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Sub modulus (if overflow) + subq %rax, %r8 + sbbq %rcx, %r9 + sbbq %rcx, %r10 + sbbq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 8(%rsp), %rdi + movq 40(%rsp), %rsi + movq 32(%rsp), %rbx + # Sub + movq (%rsi), %r8 + movq 8(%rsi), %r9 + movq 16(%rsi), %r10 + movq 24(%rsi), %r11 + subq (%rbx), %r8 + movq $0x00, %rcx + sbbq 8(%rbx), %r9 + movq $-19, %rax + sbbq 16(%rbx), %r10 + movq $0x7fffffffffffffff, %rdx + sbbq 24(%rbx), %r11 + sbbq $0x00, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Add modulus (if underflow) + addq %rax, %r8 + adcq %rcx, %r9 + adcq %rcx, %r10 + adcq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 16(%rsp), %rdi + movq (%rsp), %rsi + movq 160(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rax + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rbx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq (%rbx), %rax + mulq 8(%rsi) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 16(%rbx), %rax + mulq (%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 8(%rbx), %rax + mulq 8(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq (%rbx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 24(%rbx), %rax + mulq (%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 16(%rbx), %rax + mulq 8(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 8(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq (%rbx), %rax + mulq 24(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 24(%rbx), %rax + mulq 8(%rsi) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 16(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 8(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 24(%rbx), %rax + mulq 16(%rsi) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 16(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 24(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 8(%rsp), %rdi + movq 8(%rsp), %rsi + movq 168(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rax + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rbx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq (%rbx), %rax + mulq 8(%rsi) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 16(%rbx), %rax + mulq (%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 8(%rbx), %rax + mulq 8(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq (%rbx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 24(%rbx), %rax + mulq (%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 16(%rbx), %rax + mulq 8(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 8(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq (%rbx), %rax + mulq 24(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 24(%rbx), %rax + mulq 8(%rsi) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 16(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 8(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 24(%rbx), %rax + mulq 16(%rsi) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 16(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 24(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 24(%rsp), %rdi + movq 152(%rsp), %rsi + movq 136(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rax + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rbx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq (%rbx), %rax + mulq 8(%rsi) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 16(%rbx), %rax + mulq (%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 8(%rbx), %rax + mulq 8(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq (%rbx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 24(%rbx), %rax + mulq (%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 16(%rbx), %rax + mulq 8(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 8(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq (%rbx), %rax + mulq 24(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 24(%rbx), %rax + mulq 8(%rsi) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 16(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 8(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 24(%rbx), %rax + mulq 16(%rsi) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 16(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 24(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq (%rsp), %rdi + movq 128(%rsp), %rsi + movq 144(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rax + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rbx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq (%rbx), %rax + mulq 8(%rsi) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 16(%rbx), %rax + mulq (%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 8(%rbx), %rax + mulq 8(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq (%rbx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 24(%rbx), %rax + mulq (%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 16(%rbx), %rax + mulq 8(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 8(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq (%rbx), %rax + mulq 24(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 24(%rbx), %rax + mulq 8(%rsi) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 16(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 8(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 24(%rbx), %rax + mulq 16(%rsi) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 16(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 24(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + leaq 48(%rsp), %rdi + movq (%rsp), %rsi + movq (%rsp), %rbx + # Add + movq (%rsi), %r8 + movq 8(%rsi), %r9 + addq (%rbx), %r8 + movq 16(%rsi), %r10 + adcq 8(%rbx), %r9 + movq 24(%rsi), %rcx + adcq 16(%rbx), %r10 + movq $-19, %rax + adcq 24(%rbx), %rcx + movq $0x7fffffffffffffff, %rdx + movq %rcx, %r11 + sarq $63, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Sub modulus (if overflow) + subq %rax, %r8 + sbbq %rcx, %r9 + sbbq %rcx, %r10 + sbbq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq (%rsp), %rdi + movq 16(%rsp), %rsi + movq 8(%rsp), %rbx + # Sub + movq (%rsi), %r8 + movq 8(%rsi), %r9 + movq 16(%rsi), %r10 + movq 24(%rsi), %r11 + subq (%rbx), %r8 + movq $0x00, %rcx + sbbq 8(%rbx), %r9 + movq $-19, %rax + sbbq 16(%rbx), %r10 + movq $0x7fffffffffffffff, %rdx + sbbq 24(%rbx), %r11 + sbbq $0x00, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Add modulus (if underflow) + addq %rax, %r8 + adcq %rcx, %r9 + adcq %rcx, %r10 + adcq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 8(%rsp), %rdi + movq 16(%rsp), %rsi + movq 8(%rsp), %rbx + # Add + movq (%rsi), %r8 + movq 8(%rsi), %r9 + addq (%rbx), %r8 + movq 16(%rsi), %r10 + adcq 8(%rbx), %r9 + movq 24(%rsi), %rcx + adcq 16(%rbx), %r10 + movq $-19, %rax + adcq 24(%rbx), %rcx + movq $0x7fffffffffffffff, %rdx + movq %rcx, %r11 + sarq $63, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Sub modulus (if overflow) + subq %rax, %r8 + sbbq %rcx, %r9 + sbbq %rcx, %r10 + sbbq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 16(%rsp), %rdi + leaq 48(%rsp), %rsi + movq 24(%rsp), %rbx + # Add + movq (%rsi), %r8 + movq 8(%rsi), %r9 + addq (%rbx), %r8 + movq 16(%rsi), %r10 + adcq 8(%rbx), %r9 + movq 24(%rsi), %rcx + adcq 16(%rbx), %r10 + movq $-19, %rax + adcq 24(%rbx), %rcx + movq $0x7fffffffffffffff, %rdx + movq %rcx, %r11 + sarq $63, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Sub modulus (if overflow) + subq %rax, %r8 + sbbq %rcx, %r9 + sbbq %rcx, %r10 + sbbq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 24(%rsp), %rdi + leaq 48(%rsp), %rsi + movq 24(%rsp), %rbx + # Sub + movq (%rsi), %r8 + movq 8(%rsi), %r9 + movq 16(%rsi), %r10 + movq 24(%rsi), %r11 + subq (%rbx), %r8 + movq $0x00, %rcx + sbbq 8(%rbx), %r9 + movq $-19, %rax + sbbq 16(%rbx), %r10 + movq $0x7fffffffffffffff, %rdx + sbbq 24(%rbx), %r11 + sbbq $0x00, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Add modulus (if underflow) + addq %rax, %r8 + adcq %rcx, %r9 + adcq %rcx, %r10 + adcq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + addq $0x50, %rsp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size fe_ge_add_x64,.-fe_ge_add_x64 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_ge_sub_x64 +.type fe_ge_sub_x64,@function +.align 4 +fe_ge_sub_x64: +#else +.section __TEXT,__text +.globl _fe_ge_sub_x64 +.p2align 2 +_fe_ge_sub_x64: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + subq $0x50, %rsp + movq %rdi, (%rsp) + movq %rsi, 8(%rsp) + movq %rdx, 16(%rsp) + movq %rcx, 24(%rsp) + movq %r8, 32(%rsp) + movq %r9, 40(%rsp) + movq (%rsp), %rdi + movq 40(%rsp), %rsi + movq 32(%rsp), %rbx + # Add + movq (%rsi), %r8 + movq 8(%rsi), %r9 + addq (%rbx), %r8 + movq 16(%rsi), %r10 + adcq 8(%rbx), %r9 + movq 24(%rsi), %rcx + adcq 16(%rbx), %r10 + movq $-19, %rax + adcq 24(%rbx), %rcx + movq $0x7fffffffffffffff, %rdx + movq %rcx, %r11 + sarq $63, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Sub modulus (if overflow) + subq %rax, %r8 + sbbq %rcx, %r9 + sbbq %rcx, %r10 + sbbq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 8(%rsp), %rdi + movq 40(%rsp), %rsi + movq 32(%rsp), %rbx + # Sub + movq (%rsi), %r8 + movq 8(%rsi), %r9 + movq 16(%rsi), %r10 + movq 24(%rsi), %r11 + subq (%rbx), %r8 + movq $0x00, %rcx + sbbq 8(%rbx), %r9 + movq $-19, %rax + sbbq 16(%rbx), %r10 + movq $0x7fffffffffffffff, %rdx + sbbq 24(%rbx), %r11 + sbbq $0x00, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Add modulus (if underflow) + addq %rax, %r8 + adcq %rcx, %r9 + adcq %rcx, %r10 + adcq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 16(%rsp), %rdi + movq (%rsp), %rsi + movq 168(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rax + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rbx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq (%rbx), %rax + mulq 8(%rsi) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 16(%rbx), %rax + mulq (%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 8(%rbx), %rax + mulq 8(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq (%rbx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 24(%rbx), %rax + mulq (%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 16(%rbx), %rax + mulq 8(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 8(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq (%rbx), %rax + mulq 24(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 24(%rbx), %rax + mulq 8(%rsi) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 16(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 8(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 24(%rbx), %rax + mulq 16(%rsi) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 16(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 24(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 8(%rsp), %rdi + movq 8(%rsp), %rsi + movq 160(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rax + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rbx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq (%rbx), %rax + mulq 8(%rsi) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 16(%rbx), %rax + mulq (%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 8(%rbx), %rax + mulq 8(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq (%rbx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 24(%rbx), %rax + mulq (%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 16(%rbx), %rax + mulq 8(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 8(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq (%rbx), %rax + mulq 24(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 24(%rbx), %rax + mulq 8(%rsi) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 16(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 8(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 24(%rbx), %rax + mulq 16(%rsi) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 16(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 24(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 24(%rsp), %rdi + movq 152(%rsp), %rsi + movq 136(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rax + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rbx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq (%rbx), %rax + mulq 8(%rsi) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 16(%rbx), %rax + mulq (%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 8(%rbx), %rax + mulq 8(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq (%rbx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 24(%rbx), %rax + mulq (%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 16(%rbx), %rax + mulq 8(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 8(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq (%rbx), %rax + mulq 24(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 24(%rbx), %rax + mulq 8(%rsi) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 16(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 8(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 24(%rbx), %rax + mulq 16(%rsi) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 16(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 24(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq (%rsp), %rdi + movq 128(%rsp), %rsi + movq 144(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rax + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rbx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r9 + adcq %rdx, %r10 + # A[1] * B[0] + movq (%rbx), %rax + mulq 8(%rsi) + xorq %r11, %r11 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0x00, %r11 + # A[0] * B[2] + movq 16(%rbx), %rax + mulq (%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[1] + movq 8(%rbx), %rax + mulq 8(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[2] * B[0] + movq (%rbx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + # A[0] * B[3] + movq 24(%rbx), %rax + mulq (%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[2] + movq 16(%rbx), %rax + mulq 8(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[2] * B[1] + movq 8(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[3] * B[0] + movq (%rbx), %rax + mulq 24(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + # A[1] * B[3] + movq 24(%rbx), %rax + mulq 8(%rsi) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[2] + movq 16(%rbx), %rax + mulq 16(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[3] * B[1] + movq 8(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0x00, %r14 + # A[2] * B[3] + movq 24(%rbx), %rax + mulq 16(%rsi) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[2] + movq 16(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0x00, %r15 + # A[3] * B[3] + movq 24(%rbx), %rax + mulq 24(%rsi) + addq %rax, %r14 + adcq %rdx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rax + mulq %r12 + xorq %r12, %r12 + addq %rax, %r8 + movq $19, %rax + adcq %rdx, %r12 + mulq %r13 + xorq %r13, %r13 + addq %rax, %r9 + movq $19, %rax + adcq %rdx, %r13 + mulq %r14 + xorq %r14, %r14 + addq %rax, %r10 + movq $19, %rax + adcq %rdx, %r14 + mulq %r15 + # Add remaining product results in + addq %r12, %r9 + adcq %r13, %r10 + adcq %r14, %r11 + adcq %rax, %r11 + adcq $0x00, %rdx + # Overflow + shldq $0x01, %r11, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + leaq 48(%rsp), %rdi + movq (%rsp), %rsi + movq (%rsp), %rbx + # Add + movq (%rsi), %r8 + movq 8(%rsi), %r9 + addq (%rbx), %r8 + movq 16(%rsi), %r10 + adcq 8(%rbx), %r9 + movq 24(%rsi), %rcx + adcq 16(%rbx), %r10 + movq $-19, %rax + adcq 24(%rbx), %rcx + movq $0x7fffffffffffffff, %rdx + movq %rcx, %r11 + sarq $63, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Sub modulus (if overflow) + subq %rax, %r8 + sbbq %rcx, %r9 + sbbq %rcx, %r10 + sbbq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq (%rsp), %rdi + movq 16(%rsp), %rsi + movq 8(%rsp), %rbx + # Sub + movq (%rsi), %r8 + movq 8(%rsi), %r9 + movq 16(%rsi), %r10 + movq 24(%rsi), %r11 + subq (%rbx), %r8 + movq $0x00, %rcx + sbbq 8(%rbx), %r9 + movq $-19, %rax + sbbq 16(%rbx), %r10 + movq $0x7fffffffffffffff, %rdx + sbbq 24(%rbx), %r11 + sbbq $0x00, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Add modulus (if underflow) + addq %rax, %r8 + adcq %rcx, %r9 + adcq %rcx, %r10 + adcq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 8(%rsp), %rdi + movq 16(%rsp), %rsi + movq 8(%rsp), %rbx + # Add + movq (%rsi), %r8 + movq 8(%rsi), %r9 + addq (%rbx), %r8 + movq 16(%rsi), %r10 + adcq 8(%rbx), %r9 + movq 24(%rsi), %rcx + adcq 16(%rbx), %r10 + movq $-19, %rax + adcq 24(%rbx), %rcx + movq $0x7fffffffffffffff, %rdx + movq %rcx, %r11 + sarq $63, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Sub modulus (if overflow) + subq %rax, %r8 + sbbq %rcx, %r9 + sbbq %rcx, %r10 + sbbq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 16(%rsp), %rdi + leaq 48(%rsp), %rsi + movq 24(%rsp), %rbx + # Sub + movq (%rsi), %r8 + movq 8(%rsi), %r9 + movq 16(%rsi), %r10 + movq 24(%rsi), %r11 + subq (%rbx), %r8 + movq $0x00, %rcx + sbbq 8(%rbx), %r9 + movq $-19, %rax + sbbq 16(%rbx), %r10 + movq $0x7fffffffffffffff, %rdx + sbbq 24(%rbx), %r11 + sbbq $0x00, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Add modulus (if underflow) + addq %rax, %r8 + adcq %rcx, %r9 + adcq %rcx, %r10 + adcq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 24(%rsp), %rdi + leaq 48(%rsp), %rsi + movq 24(%rsp), %rbx + # Add + movq (%rsi), %r8 + movq 8(%rsi), %r9 + addq (%rbx), %r8 + movq 16(%rsi), %r10 + adcq 8(%rbx), %r9 + movq 24(%rsi), %rcx + adcq 16(%rbx), %r10 + movq $-19, %rax + adcq 24(%rbx), %rcx + movq $0x7fffffffffffffff, %rdx + movq %rcx, %r11 + sarq $63, %rcx + # Mask the modulus + andq %rcx, %rax + andq %rcx, %rdx + # Sub modulus (if overflow) + subq %rax, %r8 + sbbq %rcx, %r9 + sbbq %rcx, %r10 + sbbq %rdx, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + addq $0x50, %rsp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size fe_ge_sub_x64,.-fe_ge_sub_x64 +#endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 +#ifndef __APPLE__ +.text +.globl fe_mul_avx2 +.type fe_mul_avx2,@function +.align 4 +fe_mul_avx2: +#else +.section __TEXT,__text +.globl _fe_mul_avx2 +.p2align 2 +_fe_mul_avx2: +#endif /* __APPLE__ */ + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + pushq %rbx + movq %rdx, %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rdx + mulxq (%rsi), %r8, %r9 + # A[2] * B[0] + mulxq 16(%rsi), %r10, %r11 + # A[1] * B[0] + mulxq 8(%rsi), %rax, %rcx + xorq %r15, %r15 + adcxq %rax, %r9 + # A[1] * B[3] + movq 24(%rbx), %rdx + mulxq 8(%rsi), %r12, %r13 + adcxq %rcx, %r10 + # A[0] * B[1] + movq 8(%rbx), %rdx + mulxq (%rsi), %rax, %rcx + adoxq %rax, %r9 + # A[2] * B[1] + mulxq 16(%rsi), %rax, %r14 + adoxq %rcx, %r10 + adcxq %rax, %r11 + # A[1] * B[2] + movq 16(%rbx), %rdx + mulxq 8(%rsi), %rax, %rcx + adcxq %r14, %r12 + adoxq %rax, %r11 + adcxq %r15, %r13 + adoxq %rcx, %r12 + # A[0] * B[2] + mulxq (%rsi), %rax, %rcx + adoxq %r15, %r13 + xorq %r14, %r14 + adcxq %rax, %r10 + # A[1] * B[1] + movq 8(%rbx), %rdx + mulxq 8(%rsi), %rdx, %rax + adcxq %rcx, %r11 + adoxq %rdx, %r10 + # A[3] * B[1] + movq 8(%rbx), %rdx + adoxq %rax, %r11 + mulxq 24(%rsi), %rax, %rcx + adcxq %rax, %r12 + # A[2] * B[2] + movq 16(%rbx), %rdx + mulxq 16(%rsi), %rdx, %rax + adcxq %rcx, %r13 + adoxq %rdx, %r12 + # A[3] * B[3] + movq 24(%rbx), %rdx + adoxq %rax, %r13 + mulxq 24(%rsi), %rax, %rcx + adoxq %r15, %r14 + adcxq %rax, %r14 + # A[0] * B[3] + mulxq (%rsi), %rdx, %rax + adcxq %rcx, %r15 + xorq %rcx, %rcx + adcxq %rdx, %r11 + # A[3] * B[0] + movq (%rbx), %rdx + adcxq %rax, %r12 + mulxq 24(%rsi), %rdx, %rax + adoxq %rdx, %r11 + adoxq %rax, %r12 + # A[2] * B[3] + movq 24(%rbx), %rdx + mulxq 16(%rsi), %rdx, %rax + adcxq %rdx, %r13 + # A[3] * B[2] + movq 16(%rbx), %rdx + adcxq %rax, %r14 + mulxq 24(%rsi), %rax, %rdx + adcxq %rcx, %r15 + adoxq %rax, %r13 + adoxq %rdx, %r14 + adoxq %rcx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rcx, %rcx + mulxq %r12, %rax, %r12 + adcxq %rax, %r8 + adoxq %r12, %r9 + mulxq %r13, %rax, %r13 + adcxq %rax, %r9 + adoxq %r13, %r10 + mulxq %r14, %rax, %r14 + adcxq %rax, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rcx, %rdx + adcxq %rcx, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rcx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + popq %rbx + popq %r15 + popq %r14 + popq %r13 + popq %r12 + repz retq +#ifndef __APPLE__ +.size fe_mul_avx2,.-fe_mul_avx2 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_sq_avx2 +.type fe_sq_avx2,@function +.align 4 +fe_sq_avx2: +#else +.section __TEXT,__text +.globl _fe_sq_avx2 +.p2align 2 +_fe_sq_avx2: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + # Square + # A[0] * A[1] + movq (%rsi), %rdx + mulxq 8(%rsi), %r9, %r10 + # A[0] * A[3] + mulxq 24(%rsi), %r11, %r12 + # A[2] * A[1] + movq 16(%rsi), %rdx + mulxq 8(%rsi), %rcx, %rbx + xorq %r15, %r15 + adoxq %rcx, %r11 + # A[2] * A[3] + mulxq 24(%rsi), %r13, %r14 + adoxq %rbx, %r12 + # A[2] * A[0] + mulxq (%rsi), %rcx, %rbx + adoxq %r15, %r13 + adcxq %rcx, %r10 + adoxq %r15, %r14 + # A[1] * A[3] + movq 8(%rsi), %rdx + mulxq 24(%rsi), %rax, %r8 + adcxq %rbx, %r11 + adcxq %rax, %r12 + adcxq %r8, %r13 + adcxq %r15, %r14 + # Double with Carry Flag + xorq %r15, %r15 + # A[0] * A[0] + movq (%rsi), %rdx + mulxq %rdx, %r8, %rax + adcxq %r9, %r9 + # A[1] * A[1] + movq 8(%rsi), %rdx + mulxq %rdx, %rcx, %rbx + adcxq %r10, %r10 + adoxq %rax, %r9 + adcxq %r11, %r11 + adoxq %rcx, %r10 + # A[2] * A[2] + movq 16(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adcxq %r12, %r12 + adoxq %rbx, %r11 + adcxq %r13, %r13 + adoxq %rax, %r12 + # A[3] * A[3] + movq 24(%rsi), %rdx + mulxq %rdx, %rax, %rbx + adcxq %r14, %r14 + adoxq %rcx, %r13 + adcxq %r15, %r15 + adoxq %rax, %r14 + adoxq %rbx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rcx, %rcx + mulxq %r12, %rax, %r12 + adcxq %rax, %r8 + adoxq %r12, %r9 + mulxq %r13, %rax, %r13 + adcxq %rax, %r9 + adoxq %r13, %r10 + mulxq %r14, %rax, %r14 + adcxq %rax, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rcx, %rdx + adcxq %rcx, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rcx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size fe_sq_avx2,.-fe_sq_avx2 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_mul121666_avx2 +.type fe_mul121666_avx2,@function +.align 4 +fe_mul121666_avx2: +#else +.section __TEXT,__text +.globl _fe_mul121666_avx2 +.p2align 2 +_fe_mul121666_avx2: +#endif /* __APPLE__ */ + pushq %r12 + pushq %r13 + movq $0x1db42, %rdx + mulxq (%rsi), %rax, %r13 + mulxq 8(%rsi), %rcx, %r12 + mulxq 16(%rsi), %r8, %r11 + mulxq 24(%rsi), %r9, %r10 + addq %r13, %rcx + adcq %r12, %r8 + adcq %r11, %r9 + adcq $0x00, %r10 + movq $0x7fffffffffffffff, %r13 + shldq $0x01, %r9, %r10 + andq %r13, %r9 + imulq $19, %r10, %r10 + addq %r10, %rax + adcq $0x00, %rcx + adcq $0x00, %r8 + adcq $0x00, %r9 + movq %rax, (%rdi) + movq %rcx, 8(%rdi) + movq %r8, 16(%rdi) + movq %r9, 24(%rdi) + popq %r13 + popq %r12 + repz retq +#ifndef __APPLE__ +.size fe_mul121666_avx2,.-fe_mul121666_avx2 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_sq2_avx2 +.type fe_sq2_avx2,@function +.align 4 +fe_sq2_avx2: +#else +.section __TEXT,__text +.globl _fe_sq2_avx2 +.p2align 2 +_fe_sq2_avx2: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + # Square * 2 + # A[0] * A[1] + movq (%rsi), %rdx + mulxq 8(%rsi), %r9, %r10 + # A[0] * A[3] + mulxq 24(%rsi), %r11, %r12 + # A[2] * A[1] + movq 16(%rsi), %rdx + mulxq 8(%rsi), %rcx, %rbx + xorq %r15, %r15 + adoxq %rcx, %r11 + # A[2] * A[3] + mulxq 24(%rsi), %r13, %r14 + adoxq %rbx, %r12 + # A[2] * A[0] + mulxq (%rsi), %rcx, %rbx + adoxq %r15, %r13 + adcxq %rcx, %r10 + adoxq %r15, %r14 + # A[1] * A[3] + movq 8(%rsi), %rdx + mulxq 24(%rsi), %rax, %r8 + adcxq %rbx, %r11 + adcxq %rax, %r12 + adcxq %r8, %r13 + adcxq %r15, %r14 + # Double with Carry Flag + xorq %r15, %r15 + # A[0] * A[0] + movq (%rsi), %rdx + mulxq %rdx, %r8, %rax + adcxq %r9, %r9 + # A[1] * A[1] + movq 8(%rsi), %rdx + mulxq %rdx, %rcx, %rbx + adcxq %r10, %r10 + adoxq %rax, %r9 + adcxq %r11, %r11 + adoxq %rcx, %r10 + # A[2] * A[2] + movq 16(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adcxq %r12, %r12 + adoxq %rbx, %r11 + adcxq %r13, %r13 + adoxq %rax, %r12 + # A[3] * A[3] + movq 24(%rsi), %rdx + mulxq %rdx, %rax, %rbx + adcxq %r14, %r14 + adoxq %rcx, %r13 + adcxq %r15, %r15 + adoxq %rax, %r14 + adoxq %rbx, %r15 + # Reduce + movq $0x7fffffffffffffff, %rbx + xorq %rax, %rax + # Move top half into t4-t7 and remove top bit from t3 and double + shldq $3, %r15, %rax + shldq $2, %r14, %r15 + shldq $2, %r13, %r14 + shldq $2, %r12, %r13 + shldq $2, %r11, %r12 + shldq $0x01, %r10, %r11 + shldq $0x01, %r9, %r10 + shldq $0x01, %r8, %r9 + shlq $0x01, %r8 + andq %rbx, %r11 + # Two out left, one in right + andq %rbx, %r15 + # Multiply top bits by 19*19 + imulq $0x169, %rax, %rcx + xorq %rbx, %rbx + # Multiply top half by 19 + movq $19, %rdx + adoxq %rcx, %r8 + mulxq %r12, %rax, %r12 + adcxq %rax, %r8 + adoxq %r12, %r9 + mulxq %r13, %rax, %r13 + adcxq %rax, %r9 + adoxq %r13, %r10 + mulxq %r14, %rax, %r14 + adcxq %rax, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rbx, %rdx + adcxq %rbx, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rbx + imulq $19, %rdx, %rax + andq %rbx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rbx, %r11 + addq %rax, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size fe_sq2_avx2,.-fe_sq2_avx2 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_invert_avx2 +.type fe_invert_avx2,@function +.align 4 +fe_invert_avx2: +#else +.section __TEXT,__text +.globl _fe_invert_avx2 +.p2align 2 +_fe_invert_avx2: +#endif /* __APPLE__ */ + subq $0x98, %rsp + # Invert + movq %rdi, 128(%rsp) + movq %rsi, 136(%rsp) + movq %rsp, %rdi + movq 136(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + movq %rsp, %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + movq 136(%rsp), %rsi + leaq 32(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + movq %rsp, %rdi + movq %rsp, %rsi + leaq 32(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + movq %rsp, %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi + leaq 64(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 32(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + movb $4, 144(%rsp) + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi +L_fe_invert_avx2_1: +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + decb 144(%rsp) + jnz L_fe_invert_avx2_1 + leaq 32(%rsp), %rdi + leaq 64(%rsp), %rsi + leaq 32(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 32(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + movb $9, 144(%rsp) + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi +L_fe_invert_avx2_2: +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + decb 144(%rsp) + jnz L_fe_invert_avx2_2 + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi + leaq 32(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 64(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + movb $19, 144(%rsp) + leaq 96(%rsp), %rdi + leaq 96(%rsp), %rsi +L_fe_invert_avx2_3: +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + decb 144(%rsp) + jnz L_fe_invert_avx2_3 + leaq 64(%rsp), %rdi + leaq 96(%rsp), %rsi + leaq 64(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + movb $9, 144(%rsp) + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi +L_fe_invert_avx2_4: +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + decb 144(%rsp) + jnz L_fe_invert_avx2_4 + leaq 32(%rsp), %rdi + leaq 64(%rsp), %rsi + leaq 32(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 32(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + movb $49, 144(%rsp) + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi +L_fe_invert_avx2_5: +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + decb 144(%rsp) + jnz L_fe_invert_avx2_5 + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi + leaq 32(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 64(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + movb $0x63, 144(%rsp) + leaq 96(%rsp), %rdi + leaq 96(%rsp), %rsi +L_fe_invert_avx2_6: +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + decb 144(%rsp) + jnz L_fe_invert_avx2_6 + leaq 64(%rsp), %rdi + leaq 96(%rsp), %rsi + leaq 64(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + movb $49, 144(%rsp) + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi +L_fe_invert_avx2_7: +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + decb 144(%rsp) + jnz L_fe_invert_avx2_7 + leaq 32(%rsp), %rdi + leaq 64(%rsp), %rsi + leaq 32(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + movb $4, 144(%rsp) + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi +L_fe_invert_avx2_8: +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + decb 144(%rsp) + jnz L_fe_invert_avx2_8 + movq 128(%rsp), %rdi + leaq 32(%rsp), %rsi + movq %rsp, %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + movq 136(%rsp), %rsi + movq 128(%rsp), %rdi + addq $0x98, %rsp + repz retq +#ifndef __APPLE__ +.text +.globl curve25519_avx2 +.type curve25519_avx2,@function +.align 4 +curve25519_avx2: +#else +.section __TEXT,__text +.globl _curve25519_avx2 +.p2align 2 +_curve25519_avx2: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + pushq %rbp + movq %rdx, %r8 + subq $0xc0, %rsp + movq $0x00, 184(%rsp) + movq %rdi, 176(%rsp) + # Set one + movq $0x01, (%rdi) + movq $0x00, 8(%rdi) + movq $0x00, 16(%rdi) + movq $0x00, 24(%rdi) + # Set zero + movq $0x00, (%rsp) + movq $0x00, 8(%rsp) + movq $0x00, 16(%rsp) + movq $0x00, 24(%rsp) + # Set one + movq $0x01, 32(%rsp) + movq $0x00, 40(%rsp) + movq $0x00, 48(%rsp) + movq $0x00, 56(%rsp) + # Copy + movq (%r8), %r9 + movq 8(%r8), %r10 + movq 16(%r8), %r11 + movq 24(%r8), %r12 + movq %r9, 64(%rsp) + movq %r10, 72(%rsp) + movq %r11, 80(%rsp) + movq %r12, 88(%rsp) + movb $62, 168(%rsp) + movq $3, 160(%rsp) +L_curve25519_avx2_words: +L_curve25519_avx2_bits: + movq 184(%rsp), %rbx + movq 160(%rsp), %r9 + movb 168(%rsp), %cl + movq (%rsi,%r9,8), %rax + shrq %cl, %rax + andq $0x01, %rax + xorq %rax, %rbx + negq %rbx + # Conditional Swap + movq (%rdi), %r9 + movq 8(%rdi), %r10 + movq 16(%rdi), %r11 + movq 24(%rdi), %r12 + xorq 64(%rsp), %r9 + xorq 72(%rsp), %r10 + xorq 80(%rsp), %r11 + xorq 88(%rsp), %r12 + andq %rbx, %r9 + andq %rbx, %r10 + andq %rbx, %r11 + andq %rbx, %r12 + xorq %r9, (%rdi) + xorq %r10, 8(%rdi) + xorq %r11, 16(%rdi) + xorq %r12, 24(%rdi) + xorq %r9, 64(%rsp) + xorq %r10, 72(%rsp) + xorq %r11, 80(%rsp) + xorq %r12, 88(%rsp) + # Conditional Swap + movq (%rsp), %r9 + movq 8(%rsp), %r10 + movq 16(%rsp), %r11 + movq 24(%rsp), %r12 + xorq 32(%rsp), %r9 + xorq 40(%rsp), %r10 + xorq 48(%rsp), %r11 + xorq 56(%rsp), %r12 + andq %rbx, %r9 + andq %rbx, %r10 + andq %rbx, %r11 + andq %rbx, %r12 + xorq %r9, (%rsp) + xorq %r10, 8(%rsp) + xorq %r11, 16(%rsp) + xorq %r12, 24(%rsp) + xorq %r9, 32(%rsp) + xorq %r10, 40(%rsp) + xorq %r11, 48(%rsp) + xorq %r12, 56(%rsp) + movq %rax, 184(%rsp) + # Add + movq (%rdi), %r9 + movq 8(%rdi), %r10 + movq 16(%rdi), %r11 + movq 24(%rdi), %rax + movq %r9, %r13 + addq (%rsp), %r9 + movq %r10, %r14 + adcq 8(%rsp), %r10 + movq %r11, %r15 + adcq 16(%rsp), %r11 + movq %rax, %rbp + adcq 24(%rsp), %rax + movq $-19, %rcx + movq %rax, %r12 + movq $0x7fffffffffffffff, %rbx + sarq $63, %rax + # Mask the modulus + andq %rax, %rcx + andq %rax, %rbx + # Sub modulus (if overflow) + subq %rcx, %r9 + sbbq %rax, %r10 + sbbq %rax, %r11 + sbbq %rbx, %r12 + # Sub + subq (%rsp), %r13 + movq $0x00, %rax + sbbq 8(%rsp), %r14 + movq $-19, %rcx + sbbq 16(%rsp), %r15 + movq $0x7fffffffffffffff, %rbx + sbbq 24(%rsp), %rbp + sbbq $0x00, %rax + # Mask the modulus + andq %rax, %rcx + andq %rax, %rbx + # Add modulus (if underflow) + addq %rcx, %r13 + adcq %rax, %r14 + adcq %rax, %r15 + adcq %rbx, %rbp + movq %r9, (%rdi) + movq %r10, 8(%rdi) + movq %r11, 16(%rdi) + movq %r12, 24(%rdi) + movq %r13, 128(%rsp) + movq %r14, 136(%rsp) + movq %r15, 144(%rsp) + movq %rbp, 152(%rsp) + # Add + movq 64(%rsp), %r9 + movq 72(%rsp), %r10 + movq 80(%rsp), %r11 + movq 88(%rsp), %rax + movq %r9, %r13 + addq 32(%rsp), %r9 + movq %r10, %r14 + adcq 40(%rsp), %r10 + movq %r11, %r15 + adcq 48(%rsp), %r11 + movq %rax, %rbp + adcq 56(%rsp), %rax + movq $-19, %rcx + movq %rax, %r12 + movq $0x7fffffffffffffff, %rbx + sarq $63, %rax + # Mask the modulus + andq %rax, %rcx + andq %rax, %rbx + # Sub modulus (if overflow) + subq %rcx, %r9 + sbbq %rax, %r10 + sbbq %rax, %r11 + sbbq %rbx, %r12 + # Sub + subq 32(%rsp), %r13 + movq $0x00, %rax + sbbq 40(%rsp), %r14 + movq $-19, %rcx + sbbq 48(%rsp), %r15 + movq $0x7fffffffffffffff, %rbx + sbbq 56(%rsp), %rbp + sbbq $0x00, %rax + # Mask the modulus + andq %rax, %rcx + andq %rax, %rbx + # Add modulus (if underflow) + addq %rcx, %r13 + adcq %rax, %r14 + adcq %rax, %r15 + adcq %rbx, %rbp + movq %r9, (%rsp) + movq %r10, 8(%rsp) + movq %r11, 16(%rsp) + movq %r12, 24(%rsp) + movq %r13, 96(%rsp) + movq %r14, 104(%rsp) + movq %r15, 112(%rsp) + movq %rbp, 120(%rsp) + # Multiply + # A[0] * B[0] + movq (%rdi), %rdx + mulxq 96(%rsp), %r9, %r10 + # A[2] * B[0] + mulxq 112(%rsp), %r11, %r12 + # A[1] * B[0] + mulxq 104(%rsp), %rcx, %rbx + xorq %rbp, %rbp + adcxq %rcx, %r10 + # A[1] * B[3] + movq 24(%rdi), %rdx + mulxq 104(%rsp), %r13, %r14 + adcxq %rbx, %r11 + # A[0] * B[1] + movq 8(%rdi), %rdx + mulxq 96(%rsp), %rcx, %rbx + adoxq %rcx, %r10 + # A[2] * B[1] + mulxq 112(%rsp), %rcx, %r15 + adoxq %rbx, %r11 + adcxq %rcx, %r12 + # A[1] * B[2] + movq 16(%rdi), %rdx + mulxq 104(%rsp), %rcx, %rbx + adcxq %r15, %r13 + adoxq %rcx, %r12 + adcxq %rbp, %r14 + adoxq %rbx, %r13 + # A[0] * B[2] + mulxq 96(%rsp), %rcx, %rbx + adoxq %rbp, %r14 + xorq %r15, %r15 + adcxq %rcx, %r11 + # A[1] * B[1] + movq 8(%rdi), %rdx + mulxq 104(%rsp), %rdx, %rcx + adcxq %rbx, %r12 + adoxq %rdx, %r11 + # A[3] * B[1] + movq 8(%rdi), %rdx + adoxq %rcx, %r12 + mulxq 120(%rsp), %rcx, %rbx + adcxq %rcx, %r13 + # A[2] * B[2] + movq 16(%rdi), %rdx + mulxq 112(%rsp), %rdx, %rcx + adcxq %rbx, %r14 + adoxq %rdx, %r13 + # A[3] * B[3] + movq 24(%rdi), %rdx + adoxq %rcx, %r14 + mulxq 120(%rsp), %rcx, %rbx + adoxq %rbp, %r15 + adcxq %rcx, %r15 + # A[0] * B[3] + mulxq 96(%rsp), %rdx, %rcx + adcxq %rbx, %rbp + xorq %rbx, %rbx + adcxq %rdx, %r12 + # A[3] * B[0] + movq (%rdi), %rdx + adcxq %rcx, %r13 + mulxq 120(%rsp), %rdx, %rcx + adoxq %rdx, %r12 + adoxq %rcx, %r13 + # A[2] * B[3] + movq 24(%rdi), %rdx + mulxq 112(%rsp), %rdx, %rcx + adcxq %rdx, %r14 + # A[3] * B[2] + movq 16(%rdi), %rdx + adcxq %rcx, %r15 + mulxq 120(%rsp), %rcx, %rdx + adcxq %rbx, %rbp + adoxq %rcx, %r14 + adoxq %rdx, %r15 + adoxq %rbx, %rbp + # Reduce + movq $0x7fffffffffffffff, %rbx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r15, %rbp + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + andq %rbx, %r12 + # Multiply top half by 19 + movq $19, %rdx + xorq %rbx, %rbx + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %rcx, %r15 + adcxq %rcx, %r11 + adoxq %r15, %r12 + mulxq %rbp, %rbp, %rdx + adcxq %rbp, %r12 + adoxq %rbx, %rdx + adcxq %rbx, %rdx + # Overflow + shldq $0x01, %r12, %rdx + movq $0x7fffffffffffffff, %rbx + imulq $19, %rdx, %rcx + andq %rbx, %r12 + addq %rcx, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + adcq $0x00, %r12 + # Reduce if top bit set + movq %r12, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rbx, %r12 + addq %rcx, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + adcq $0x00, %r12 + # Store + movq %r9, 32(%rsp) + movq %r10, 40(%rsp) + movq %r11, 48(%rsp) + movq %r12, 56(%rsp) + # Multiply + # A[0] * B[0] + movq 128(%rsp), %rdx + mulxq (%rsp), %r9, %r10 + # A[2] * B[0] + mulxq 16(%rsp), %r11, %r12 + # A[1] * B[0] + mulxq 8(%rsp), %rcx, %rbx + xorq %rbp, %rbp + adcxq %rcx, %r10 + # A[1] * B[3] + movq 152(%rsp), %rdx + mulxq 8(%rsp), %r13, %r14 + adcxq %rbx, %r11 + # A[0] * B[1] + movq 136(%rsp), %rdx + mulxq (%rsp), %rcx, %rbx + adoxq %rcx, %r10 + # A[2] * B[1] + mulxq 16(%rsp), %rcx, %r15 + adoxq %rbx, %r11 + adcxq %rcx, %r12 + # A[1] * B[2] + movq 144(%rsp), %rdx + mulxq 8(%rsp), %rcx, %rbx + adcxq %r15, %r13 + adoxq %rcx, %r12 + adcxq %rbp, %r14 + adoxq %rbx, %r13 + # A[0] * B[2] + mulxq (%rsp), %rcx, %rbx + adoxq %rbp, %r14 + xorq %r15, %r15 + adcxq %rcx, %r11 + # A[1] * B[1] + movq 136(%rsp), %rdx + mulxq 8(%rsp), %rdx, %rcx + adcxq %rbx, %r12 + adoxq %rdx, %r11 + # A[3] * B[1] + movq 136(%rsp), %rdx + adoxq %rcx, %r12 + mulxq 24(%rsp), %rcx, %rbx + adcxq %rcx, %r13 + # A[2] * B[2] + movq 144(%rsp), %rdx + mulxq 16(%rsp), %rdx, %rcx + adcxq %rbx, %r14 + adoxq %rdx, %r13 + # A[3] * B[3] + movq 152(%rsp), %rdx + adoxq %rcx, %r14 + mulxq 24(%rsp), %rcx, %rbx + adoxq %rbp, %r15 + adcxq %rcx, %r15 + # A[0] * B[3] + mulxq (%rsp), %rdx, %rcx + adcxq %rbx, %rbp + xorq %rbx, %rbx + adcxq %rdx, %r12 + # A[3] * B[0] + movq 128(%rsp), %rdx + adcxq %rcx, %r13 + mulxq 24(%rsp), %rdx, %rcx + adoxq %rdx, %r12 + adoxq %rcx, %r13 + # A[2] * B[3] + movq 152(%rsp), %rdx + mulxq 16(%rsp), %rdx, %rcx + adcxq %rdx, %r14 + # A[3] * B[2] + movq 144(%rsp), %rdx + adcxq %rcx, %r15 + mulxq 24(%rsp), %rcx, %rdx + adcxq %rbx, %rbp + adoxq %rcx, %r14 + adoxq %rdx, %r15 + adoxq %rbx, %rbp + # Reduce + movq $0x7fffffffffffffff, %rbx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r15, %rbp + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + andq %rbx, %r12 + # Multiply top half by 19 + movq $19, %rdx + xorq %rbx, %rbx + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %rcx, %r15 + adcxq %rcx, %r11 + adoxq %r15, %r12 + mulxq %rbp, %rbp, %rdx + adcxq %rbp, %r12 + adoxq %rbx, %rdx + adcxq %rbx, %rdx + # Overflow + shldq $0x01, %r12, %rdx + movq $0x7fffffffffffffff, %rbx + imulq $19, %rdx, %rcx + andq %rbx, %r12 + addq %rcx, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + adcq $0x00, %r12 + # Reduce if top bit set + movq %r12, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rbx, %r12 + addq %rcx, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + adcq $0x00, %r12 + # Store + movq %r9, (%rsp) + movq %r10, 8(%rsp) + movq %r11, 16(%rsp) + movq %r12, 24(%rsp) + # Square + # A[0] * A[1] + movq 128(%rsp), %rdx + mulxq 136(%rsp), %r10, %r11 + # A[0] * A[3] + mulxq 152(%rsp), %r12, %r13 + # A[2] * A[1] + movq 144(%rsp), %rdx + mulxq 136(%rsp), %rcx, %rbx + xorq %rbp, %rbp + adoxq %rcx, %r12 + # A[2] * A[3] + mulxq 152(%rsp), %r14, %r15 + adoxq %rbx, %r13 + # A[2] * A[0] + mulxq 128(%rsp), %rcx, %rbx + adoxq %rbp, %r14 + adcxq %rcx, %r11 + adoxq %rbp, %r15 + # A[1] * A[3] + movq 136(%rsp), %rdx + mulxq 152(%rsp), %rax, %r9 + adcxq %rbx, %r12 + adcxq %rax, %r13 + adcxq %r9, %r14 + adcxq %rbp, %r15 + # Double with Carry Flag + xorq %rbp, %rbp + # A[0] * A[0] + movq 128(%rsp), %rdx + mulxq %rdx, %r9, %rax + adcxq %r10, %r10 + # A[1] * A[1] + movq 136(%rsp), %rdx + mulxq %rdx, %rcx, %rbx + adcxq %r11, %r11 + adoxq %rax, %r10 + adcxq %r12, %r12 + adoxq %rcx, %r11 + # A[2] * A[2] + movq 144(%rsp), %rdx + mulxq %rdx, %rax, %rcx + adcxq %r13, %r13 + adoxq %rbx, %r12 + adcxq %r14, %r14 + adoxq %rax, %r13 + # A[3] * A[3] + movq 152(%rsp), %rdx + mulxq %rdx, %rax, %rbx + adcxq %r15, %r15 + adoxq %rcx, %r14 + adcxq %rbp, %rbp + adoxq %rax, %r15 + adoxq %rbx, %rbp + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r15, %rbp + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + andq %rcx, %r12 + # Multiply top half by 19 + movq $19, %rdx + xorq %rcx, %rcx + mulxq %r13, %rax, %r13 + adcxq %rax, %r9 + adoxq %r13, %r10 + mulxq %r14, %rax, %r14 + adcxq %rax, %r10 + adoxq %r14, %r11 + mulxq %r15, %rax, %r15 + adcxq %rax, %r11 + adoxq %r15, %r12 + mulxq %rbp, %rbp, %rdx + adcxq %rbp, %r12 + adoxq %rcx, %rdx + adcxq %rcx, %rdx + # Overflow + shldq $0x01, %r12, %rdx + movq $0x7fffffffffffffff, %rcx + imulq $19, %rdx, %rax + andq %rcx, %r12 + addq %rax, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + adcq $0x00, %r12 + # Reduce if top bit set + movq %r12, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r12 + addq %rax, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + adcq $0x00, %r12 + # Store + movq %r9, 96(%rsp) + movq %r10, 104(%rsp) + movq %r11, 112(%rsp) + movq %r12, 120(%rsp) + # Square + # A[0] * A[1] + movq (%rdi), %rdx + mulxq 8(%rdi), %r10, %r11 + # A[0] * A[3] + mulxq 24(%rdi), %r12, %r13 + # A[2] * A[1] + movq 16(%rdi), %rdx + mulxq 8(%rdi), %rcx, %rbx + xorq %rbp, %rbp + adoxq %rcx, %r12 + # A[2] * A[3] + mulxq 24(%rdi), %r14, %r15 + adoxq %rbx, %r13 + # A[2] * A[0] + mulxq (%rdi), %rcx, %rbx + adoxq %rbp, %r14 + adcxq %rcx, %r11 + adoxq %rbp, %r15 + # A[1] * A[3] + movq 8(%rdi), %rdx + mulxq 24(%rdi), %rax, %r9 + adcxq %rbx, %r12 + adcxq %rax, %r13 + adcxq %r9, %r14 + adcxq %rbp, %r15 + # Double with Carry Flag + xorq %rbp, %rbp + # A[0] * A[0] + movq (%rdi), %rdx + mulxq %rdx, %r9, %rax + adcxq %r10, %r10 + # A[1] * A[1] + movq 8(%rdi), %rdx + mulxq %rdx, %rcx, %rbx + adcxq %r11, %r11 + adoxq %rax, %r10 + adcxq %r12, %r12 + adoxq %rcx, %r11 + # A[2] * A[2] + movq 16(%rdi), %rdx + mulxq %rdx, %rax, %rcx + adcxq %r13, %r13 + adoxq %rbx, %r12 + adcxq %r14, %r14 + adoxq %rax, %r13 + # A[3] * A[3] + movq 24(%rdi), %rdx + mulxq %rdx, %rax, %rbx + adcxq %r15, %r15 + adoxq %rcx, %r14 + adcxq %rbp, %rbp + adoxq %rax, %r15 + adoxq %rbx, %rbp + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r15, %rbp + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + andq %rcx, %r12 + # Multiply top half by 19 + movq $19, %rdx + xorq %rcx, %rcx + mulxq %r13, %rax, %r13 + adcxq %rax, %r9 + adoxq %r13, %r10 + mulxq %r14, %rax, %r14 + adcxq %rax, %r10 + adoxq %r14, %r11 + mulxq %r15, %rax, %r15 + adcxq %rax, %r11 + adoxq %r15, %r12 + mulxq %rbp, %rbp, %rdx + adcxq %rbp, %r12 + adoxq %rcx, %rdx + adcxq %rcx, %rdx + # Overflow + shldq $0x01, %r12, %rdx + movq $0x7fffffffffffffff, %rcx + imulq $19, %rdx, %rax + andq %rcx, %r12 + addq %rax, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + adcq $0x00, %r12 + # Reduce if top bit set + movq %r12, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r12 + addq %rax, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + adcq $0x00, %r12 + # Store + movq %r9, 128(%rsp) + movq %r10, 136(%rsp) + movq %r11, 144(%rsp) + movq %r12, 152(%rsp) + # Add + movq 32(%rsp), %r9 + movq 40(%rsp), %r10 + movq 48(%rsp), %r11 + movq 56(%rsp), %rax + movq %r9, %r13 + addq (%rsp), %r9 + movq %r10, %r14 + adcq 8(%rsp), %r10 + movq %r11, %r15 + adcq 16(%rsp), %r11 + movq %rax, %rbp + adcq 24(%rsp), %rax + movq $-19, %rcx + movq %rax, %r12 + movq $0x7fffffffffffffff, %rbx + sarq $63, %rax + # Mask the modulus + andq %rax, %rcx + andq %rax, %rbx + # Sub modulus (if overflow) + subq %rcx, %r9 + sbbq %rax, %r10 + sbbq %rax, %r11 + sbbq %rbx, %r12 + # Sub + subq (%rsp), %r13 + movq $0x00, %rax + sbbq 8(%rsp), %r14 + movq $-19, %rcx + sbbq 16(%rsp), %r15 + movq $0x7fffffffffffffff, %rbx + sbbq 24(%rsp), %rbp + sbbq $0x00, %rax + # Mask the modulus + andq %rax, %rcx + andq %rax, %rbx + # Add modulus (if underflow) + addq %rcx, %r13 + adcq %rax, %r14 + adcq %rax, %r15 + adcq %rbx, %rbp + movq %r9, 64(%rsp) + movq %r10, 72(%rsp) + movq %r11, 80(%rsp) + movq %r12, 88(%rsp) + movq %r13, (%rsp) + movq %r14, 8(%rsp) + movq %r15, 16(%rsp) + movq %rbp, 24(%rsp) + # Multiply + # A[0] * B[0] + movq 96(%rsp), %rdx + mulxq 128(%rsp), %r9, %r10 + # A[2] * B[0] + mulxq 144(%rsp), %r11, %r12 + # A[1] * B[0] + mulxq 136(%rsp), %rcx, %rbx + xorq %rbp, %rbp + adcxq %rcx, %r10 + # A[1] * B[3] + movq 120(%rsp), %rdx + mulxq 136(%rsp), %r13, %r14 + adcxq %rbx, %r11 + # A[0] * B[1] + movq 104(%rsp), %rdx + mulxq 128(%rsp), %rcx, %rbx + adoxq %rcx, %r10 + # A[2] * B[1] + mulxq 144(%rsp), %rcx, %r15 + adoxq %rbx, %r11 + adcxq %rcx, %r12 + # A[1] * B[2] + movq 112(%rsp), %rdx + mulxq 136(%rsp), %rcx, %rbx + adcxq %r15, %r13 + adoxq %rcx, %r12 + adcxq %rbp, %r14 + adoxq %rbx, %r13 + # A[0] * B[2] + mulxq 128(%rsp), %rcx, %rbx + adoxq %rbp, %r14 + xorq %r15, %r15 + adcxq %rcx, %r11 + # A[1] * B[1] + movq 104(%rsp), %rdx + mulxq 136(%rsp), %rdx, %rcx + adcxq %rbx, %r12 + adoxq %rdx, %r11 + # A[3] * B[1] + movq 104(%rsp), %rdx + adoxq %rcx, %r12 + mulxq 152(%rsp), %rcx, %rbx + adcxq %rcx, %r13 + # A[2] * B[2] + movq 112(%rsp), %rdx + mulxq 144(%rsp), %rdx, %rcx + adcxq %rbx, %r14 + adoxq %rdx, %r13 + # A[3] * B[3] + movq 120(%rsp), %rdx + adoxq %rcx, %r14 + mulxq 152(%rsp), %rcx, %rbx + adoxq %rbp, %r15 + adcxq %rcx, %r15 + # A[0] * B[3] + mulxq 128(%rsp), %rdx, %rcx + adcxq %rbx, %rbp + xorq %rbx, %rbx + adcxq %rdx, %r12 + # A[3] * B[0] + movq 96(%rsp), %rdx + adcxq %rcx, %r13 + mulxq 152(%rsp), %rdx, %rcx + adoxq %rdx, %r12 + adoxq %rcx, %r13 + # A[2] * B[3] + movq 120(%rsp), %rdx + mulxq 144(%rsp), %rdx, %rcx + adcxq %rdx, %r14 + # A[3] * B[2] + movq 112(%rsp), %rdx + adcxq %rcx, %r15 + mulxq 152(%rsp), %rcx, %rdx + adcxq %rbx, %rbp + adoxq %rcx, %r14 + adoxq %rdx, %r15 + adoxq %rbx, %rbp + # Reduce + movq $0x7fffffffffffffff, %rbx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r15, %rbp + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + andq %rbx, %r12 + # Multiply top half by 19 + movq $19, %rdx + xorq %rbx, %rbx + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %rcx, %r15 + adcxq %rcx, %r11 + adoxq %r15, %r12 + mulxq %rbp, %rbp, %rdx + adcxq %rbp, %r12 + adoxq %rbx, %rdx + adcxq %rbx, %rdx + # Overflow + shldq $0x01, %r12, %rdx + movq $0x7fffffffffffffff, %rbx + imulq $19, %rdx, %rcx + andq %rbx, %r12 + addq %rcx, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + adcq $0x00, %r12 + # Reduce if top bit set + movq %r12, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rbx, %r12 + addq %rcx, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + adcq $0x00, %r12 + # Store + movq %r9, (%rdi) + movq %r10, 8(%rdi) + movq %r11, 16(%rdi) + movq %r12, 24(%rdi) + # Sub + movq 128(%rsp), %r9 + movq 136(%rsp), %r10 + movq 144(%rsp), %r11 + movq 152(%rsp), %r12 + subq 96(%rsp), %r9 + movq $0x00, %rax + sbbq 104(%rsp), %r10 + movq $-19, %rcx + sbbq 112(%rsp), %r11 + movq $0x7fffffffffffffff, %rbx + sbbq 120(%rsp), %r12 + sbbq $0x00, %rax + # Mask the modulus + andq %rax, %rcx + andq %rax, %rbx + # Add modulus (if underflow) + addq %rcx, %r9 + adcq %rax, %r10 + adcq %rax, %r11 + adcq %rbx, %r12 + movq %r9, 128(%rsp) + movq %r10, 136(%rsp) + movq %r11, 144(%rsp) + movq %r12, 152(%rsp) + # Square + # A[0] * A[1] + movq (%rsp), %rdx + mulxq 8(%rsp), %r10, %r11 + # A[0] * A[3] + mulxq 24(%rsp), %r12, %r13 + # A[2] * A[1] + movq 16(%rsp), %rdx + mulxq 8(%rsp), %rcx, %rbx + xorq %rbp, %rbp + adoxq %rcx, %r12 + # A[2] * A[3] + mulxq 24(%rsp), %r14, %r15 + adoxq %rbx, %r13 + # A[2] * A[0] + mulxq (%rsp), %rcx, %rbx + adoxq %rbp, %r14 + adcxq %rcx, %r11 + adoxq %rbp, %r15 + # A[1] * A[3] + movq 8(%rsp), %rdx + mulxq 24(%rsp), %rax, %r9 + adcxq %rbx, %r12 + adcxq %rax, %r13 + adcxq %r9, %r14 + adcxq %rbp, %r15 + # Double with Carry Flag + xorq %rbp, %rbp + # A[0] * A[0] + movq (%rsp), %rdx + mulxq %rdx, %r9, %rax + adcxq %r10, %r10 + # A[1] * A[1] + movq 8(%rsp), %rdx + mulxq %rdx, %rcx, %rbx + adcxq %r11, %r11 + adoxq %rax, %r10 + adcxq %r12, %r12 + adoxq %rcx, %r11 + # A[2] * A[2] + movq 16(%rsp), %rdx + mulxq %rdx, %rax, %rcx + adcxq %r13, %r13 + adoxq %rbx, %r12 + adcxq %r14, %r14 + adoxq %rax, %r13 + # A[3] * A[3] + movq 24(%rsp), %rdx + mulxq %rdx, %rax, %rbx + adcxq %r15, %r15 + adoxq %rcx, %r14 + adcxq %rbp, %rbp + adoxq %rax, %r15 + adoxq %rbx, %rbp + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r15, %rbp + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + andq %rcx, %r12 + # Multiply top half by 19 + movq $19, %rdx + xorq %rcx, %rcx + mulxq %r13, %rax, %r13 + adcxq %rax, %r9 + adoxq %r13, %r10 + mulxq %r14, %rax, %r14 + adcxq %rax, %r10 + adoxq %r14, %r11 + mulxq %r15, %rax, %r15 + adcxq %rax, %r11 + adoxq %r15, %r12 + mulxq %rbp, %rbp, %rdx + adcxq %rbp, %r12 + adoxq %rcx, %rdx + adcxq %rcx, %rdx + # Overflow + shldq $0x01, %r12, %rdx + movq $0x7fffffffffffffff, %rcx + imulq $19, %rdx, %rax + andq %rcx, %r12 + addq %rax, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + adcq $0x00, %r12 + # Reduce if top bit set + movq %r12, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r12 + addq %rax, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + adcq $0x00, %r12 + # Store + movq %r9, (%rsp) + movq %r10, 8(%rsp) + movq %r11, 16(%rsp) + movq %r12, 24(%rsp) + movq $0x1db42, %rdx + mulxq 128(%rsp), %r9, %rbp + mulxq 136(%rsp), %r10, %r15 + mulxq 144(%rsp), %r11, %r14 + mulxq 152(%rsp), %r12, %r13 + addq %rbp, %r10 + adcq %r15, %r11 + adcq %r14, %r12 + adcq $0x00, %r13 + movq $0x7fffffffffffffff, %rbp + shldq $0x01, %r12, %r13 + andq %rbp, %r12 + imulq $19, %r13, %r13 + addq %r13, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + adcq $0x00, %r12 + movq %r9, 32(%rsp) + movq %r10, 40(%rsp) + movq %r11, 48(%rsp) + movq %r12, 56(%rsp) + # Square + # A[0] * A[1] + movq 64(%rsp), %rdx + mulxq 72(%rsp), %r10, %r11 + # A[0] * A[3] + mulxq 88(%rsp), %r12, %r13 + # A[2] * A[1] + movq 80(%rsp), %rdx + mulxq 72(%rsp), %rcx, %rbx + xorq %rbp, %rbp + adoxq %rcx, %r12 + # A[2] * A[3] + mulxq 88(%rsp), %r14, %r15 + adoxq %rbx, %r13 + # A[2] * A[0] + mulxq 64(%rsp), %rcx, %rbx + adoxq %rbp, %r14 + adcxq %rcx, %r11 + adoxq %rbp, %r15 + # A[1] * A[3] + movq 72(%rsp), %rdx + mulxq 88(%rsp), %rax, %r9 + adcxq %rbx, %r12 + adcxq %rax, %r13 + adcxq %r9, %r14 + adcxq %rbp, %r15 + # Double with Carry Flag + xorq %rbp, %rbp + # A[0] * A[0] + movq 64(%rsp), %rdx + mulxq %rdx, %r9, %rax + adcxq %r10, %r10 + # A[1] * A[1] + movq 72(%rsp), %rdx + mulxq %rdx, %rcx, %rbx + adcxq %r11, %r11 + adoxq %rax, %r10 + adcxq %r12, %r12 + adoxq %rcx, %r11 + # A[2] * A[2] + movq 80(%rsp), %rdx + mulxq %rdx, %rax, %rcx + adcxq %r13, %r13 + adoxq %rbx, %r12 + adcxq %r14, %r14 + adoxq %rax, %r13 + # A[3] * A[3] + movq 88(%rsp), %rdx + mulxq %rdx, %rax, %rbx + adcxq %r15, %r15 + adoxq %rcx, %r14 + adcxq %rbp, %rbp + adoxq %rax, %r15 + adoxq %rbx, %rbp + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r15, %rbp + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + andq %rcx, %r12 + # Multiply top half by 19 + movq $19, %rdx + xorq %rcx, %rcx + mulxq %r13, %rax, %r13 + adcxq %rax, %r9 + adoxq %r13, %r10 + mulxq %r14, %rax, %r14 + adcxq %rax, %r10 + adoxq %r14, %r11 + mulxq %r15, %rax, %r15 + adcxq %rax, %r11 + adoxq %r15, %r12 + mulxq %rbp, %rbp, %rdx + adcxq %rbp, %r12 + adoxq %rcx, %rdx + adcxq %rcx, %rdx + # Overflow + shldq $0x01, %r12, %rdx + movq $0x7fffffffffffffff, %rcx + imulq $19, %rdx, %rax + andq %rcx, %r12 + addq %rax, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + adcq $0x00, %r12 + # Reduce if top bit set + movq %r12, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rax + andq %rcx, %r12 + addq %rax, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + adcq $0x00, %r12 + # Store + movq %r9, 64(%rsp) + movq %r10, 72(%rsp) + movq %r11, 80(%rsp) + movq %r12, 88(%rsp) + # Add + movq 96(%rsp), %r9 + movq 104(%rsp), %r10 + addq 32(%rsp), %r9 + movq 112(%rsp), %r11 + adcq 40(%rsp), %r10 + movq 120(%rsp), %rax + adcq 48(%rsp), %r11 + movq $-19, %rcx + adcq 56(%rsp), %rax + movq $0x7fffffffffffffff, %rbx + movq %rax, %r12 + sarq $63, %rax + # Mask the modulus + andq %rax, %rcx + andq %rax, %rbx + # Sub modulus (if overflow) + subq %rcx, %r9 + sbbq %rax, %r10 + sbbq %rax, %r11 + sbbq %rbx, %r12 + movq %r9, 96(%rsp) + movq %r10, 104(%rsp) + movq %r11, 112(%rsp) + movq %r12, 120(%rsp) + # Multiply + # A[0] * B[0] + movq (%rsp), %rdx + mulxq (%r8), %r9, %r10 + # A[2] * B[0] + mulxq 16(%r8), %r11, %r12 + # A[1] * B[0] + mulxq 8(%r8), %rcx, %rbx + xorq %rbp, %rbp + adcxq %rcx, %r10 + # A[1] * B[3] + movq 24(%rsp), %rdx + mulxq 8(%r8), %r13, %r14 + adcxq %rbx, %r11 + # A[0] * B[1] + movq 8(%rsp), %rdx + mulxq (%r8), %rcx, %rbx + adoxq %rcx, %r10 + # A[2] * B[1] + mulxq 16(%r8), %rcx, %r15 + adoxq %rbx, %r11 + adcxq %rcx, %r12 + # A[1] * B[2] + movq 16(%rsp), %rdx + mulxq 8(%r8), %rcx, %rbx + adcxq %r15, %r13 + adoxq %rcx, %r12 + adcxq %rbp, %r14 + adoxq %rbx, %r13 + # A[0] * B[2] + mulxq (%r8), %rcx, %rbx + adoxq %rbp, %r14 + xorq %r15, %r15 + adcxq %rcx, %r11 + # A[1] * B[1] + movq 8(%rsp), %rdx + mulxq 8(%r8), %rdx, %rcx + adcxq %rbx, %r12 + adoxq %rdx, %r11 + # A[3] * B[1] + movq 8(%rsp), %rdx + adoxq %rcx, %r12 + mulxq 24(%r8), %rcx, %rbx + adcxq %rcx, %r13 + # A[2] * B[2] + movq 16(%rsp), %rdx + mulxq 16(%r8), %rdx, %rcx + adcxq %rbx, %r14 + adoxq %rdx, %r13 + # A[3] * B[3] + movq 24(%rsp), %rdx + adoxq %rcx, %r14 + mulxq 24(%r8), %rcx, %rbx + adoxq %rbp, %r15 + adcxq %rcx, %r15 + # A[0] * B[3] + mulxq (%r8), %rdx, %rcx + adcxq %rbx, %rbp + xorq %rbx, %rbx + adcxq %rdx, %r12 + # A[3] * B[0] + movq (%rsp), %rdx + adcxq %rcx, %r13 + mulxq 24(%r8), %rdx, %rcx + adoxq %rdx, %r12 + adoxq %rcx, %r13 + # A[2] * B[3] + movq 24(%rsp), %rdx + mulxq 16(%r8), %rdx, %rcx + adcxq %rdx, %r14 + # A[3] * B[2] + movq 16(%rsp), %rdx + adcxq %rcx, %r15 + mulxq 24(%r8), %rcx, %rdx + adcxq %rbx, %rbp + adoxq %rcx, %r14 + adoxq %rdx, %r15 + adoxq %rbx, %rbp + # Reduce + movq $0x7fffffffffffffff, %rbx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r15, %rbp + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + andq %rbx, %r12 + # Multiply top half by 19 + movq $19, %rdx + xorq %rbx, %rbx + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %rcx, %r15 + adcxq %rcx, %r11 + adoxq %r15, %r12 + mulxq %rbp, %rbp, %rdx + adcxq %rbp, %r12 + adoxq %rbx, %rdx + adcxq %rbx, %rdx + # Overflow + shldq $0x01, %r12, %rdx + movq $0x7fffffffffffffff, %rbx + imulq $19, %rdx, %rcx + andq %rbx, %r12 + addq %rcx, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + adcq $0x00, %r12 + # Reduce if top bit set + movq %r12, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rbx, %r12 + addq %rcx, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + adcq $0x00, %r12 + # Store + movq %r9, 32(%rsp) + movq %r10, 40(%rsp) + movq %r11, 48(%rsp) + movq %r12, 56(%rsp) + # Multiply + # A[0] * B[0] + movq 96(%rsp), %rdx + mulxq 128(%rsp), %r9, %r10 + # A[2] * B[0] + mulxq 144(%rsp), %r11, %r12 + # A[1] * B[0] + mulxq 136(%rsp), %rcx, %rbx + xorq %rbp, %rbp + adcxq %rcx, %r10 + # A[1] * B[3] + movq 120(%rsp), %rdx + mulxq 136(%rsp), %r13, %r14 + adcxq %rbx, %r11 + # A[0] * B[1] + movq 104(%rsp), %rdx + mulxq 128(%rsp), %rcx, %rbx + adoxq %rcx, %r10 + # A[2] * B[1] + mulxq 144(%rsp), %rcx, %r15 + adoxq %rbx, %r11 + adcxq %rcx, %r12 + # A[1] * B[2] + movq 112(%rsp), %rdx + mulxq 136(%rsp), %rcx, %rbx + adcxq %r15, %r13 + adoxq %rcx, %r12 + adcxq %rbp, %r14 + adoxq %rbx, %r13 + # A[0] * B[2] + mulxq 128(%rsp), %rcx, %rbx + adoxq %rbp, %r14 + xorq %r15, %r15 + adcxq %rcx, %r11 + # A[1] * B[1] + movq 104(%rsp), %rdx + mulxq 136(%rsp), %rdx, %rcx + adcxq %rbx, %r12 + adoxq %rdx, %r11 + # A[3] * B[1] + movq 104(%rsp), %rdx + adoxq %rcx, %r12 + mulxq 152(%rsp), %rcx, %rbx + adcxq %rcx, %r13 + # A[2] * B[2] + movq 112(%rsp), %rdx + mulxq 144(%rsp), %rdx, %rcx + adcxq %rbx, %r14 + adoxq %rdx, %r13 + # A[3] * B[3] + movq 120(%rsp), %rdx + adoxq %rcx, %r14 + mulxq 152(%rsp), %rcx, %rbx + adoxq %rbp, %r15 + adcxq %rcx, %r15 + # A[0] * B[3] + mulxq 128(%rsp), %rdx, %rcx + adcxq %rbx, %rbp + xorq %rbx, %rbx + adcxq %rdx, %r12 + # A[3] * B[0] + movq 96(%rsp), %rdx + adcxq %rcx, %r13 + mulxq 152(%rsp), %rdx, %rcx + adoxq %rdx, %r12 + adoxq %rcx, %r13 + # A[2] * B[3] + movq 120(%rsp), %rdx + mulxq 144(%rsp), %rdx, %rcx + adcxq %rdx, %r14 + # A[3] * B[2] + movq 112(%rsp), %rdx + adcxq %rcx, %r15 + mulxq 152(%rsp), %rcx, %rdx + adcxq %rbx, %rbp + adoxq %rcx, %r14 + adoxq %rdx, %r15 + adoxq %rbx, %rbp + # Reduce + movq $0x7fffffffffffffff, %rbx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r15, %rbp + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + andq %rbx, %r12 + # Multiply top half by 19 + movq $19, %rdx + xorq %rbx, %rbx + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %rcx, %r15 + adcxq %rcx, %r11 + adoxq %r15, %r12 + mulxq %rbp, %rbp, %rdx + adcxq %rbp, %r12 + adoxq %rbx, %rdx + adcxq %rbx, %rdx + # Overflow + shldq $0x01, %r12, %rdx + movq $0x7fffffffffffffff, %rbx + imulq $19, %rdx, %rcx + andq %rbx, %r12 + addq %rcx, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + adcq $0x00, %r12 + # Reduce if top bit set + movq %r12, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rbx, %r12 + addq %rcx, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + adcq $0x00, %r12 + # Store + movq %r9, (%rsp) + movq %r10, 8(%rsp) + movq %r11, 16(%rsp) + movq %r12, 24(%rsp) + decb 168(%rsp) + jge L_curve25519_avx2_bits + movq $63, 168(%rsp) + decb 160(%rsp) + jge L_curve25519_avx2_words + # Invert + leaq 32(%rsp), %rdi + movq %rsp, %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 32(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + movq %rsp, %rsi + leaq 64(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi + leaq 64(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 32(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi + leaq 96(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 64(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + movb $4, 160(%rsp) + leaq 96(%rsp), %rdi + leaq 96(%rsp), %rsi +L_curve25519_avx2_inv_1: +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + decb 160(%rsp) + jnz L_curve25519_avx2_inv_1 + leaq 64(%rsp), %rdi + leaq 96(%rsp), %rsi + leaq 64(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 64(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + movb $9, 160(%rsp) + leaq 96(%rsp), %rdi + leaq 96(%rsp), %rsi +L_curve25519_avx2_inv_2: +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + decb 160(%rsp) + jnz L_curve25519_avx2_inv_2 + leaq 96(%rsp), %rdi + leaq 96(%rsp), %rsi + leaq 64(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 128(%rsp), %rdi + leaq 96(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + movb $19, 160(%rsp) + leaq 128(%rsp), %rdi + leaq 128(%rsp), %rsi +L_curve25519_avx2_inv_3: +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + decb 160(%rsp) + jnz L_curve25519_avx2_inv_3 + leaq 96(%rsp), %rdi + leaq 128(%rsp), %rsi + leaq 96(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 96(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + movb $9, 160(%rsp) + leaq 96(%rsp), %rdi + leaq 96(%rsp), %rsi +L_curve25519_avx2_inv_4: +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + decb 160(%rsp) + jnz L_curve25519_avx2_inv_4 + leaq 64(%rsp), %rdi + leaq 96(%rsp), %rsi + leaq 64(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 64(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + movb $49, 160(%rsp) + leaq 96(%rsp), %rdi + leaq 96(%rsp), %rsi +L_curve25519_avx2_inv_5: +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + decb 160(%rsp) + jnz L_curve25519_avx2_inv_5 + leaq 96(%rsp), %rdi + leaq 96(%rsp), %rsi + leaq 64(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 128(%rsp), %rdi + leaq 96(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + movb $0x63, 160(%rsp) + leaq 128(%rsp), %rdi + leaq 128(%rsp), %rsi +L_curve25519_avx2_inv_6: +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + decb 160(%rsp) + jnz L_curve25519_avx2_inv_6 + leaq 96(%rsp), %rdi + leaq 128(%rsp), %rsi + leaq 96(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 96(%rsp), %rdi + leaq 96(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + movb $49, 160(%rsp) + leaq 96(%rsp), %rdi + leaq 96(%rsp), %rsi +L_curve25519_avx2_inv_7: +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + decb 160(%rsp) + jnz L_curve25519_avx2_inv_7 + leaq 64(%rsp), %rdi + leaq 96(%rsp), %rsi + leaq 64(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + movb $4, 160(%rsp) + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi +L_curve25519_avx2_inv_8: +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + decb 160(%rsp) + jnz L_curve25519_avx2_inv_8 + movq %rsp, %rdi + leaq 64(%rsp), %rsi + leaq 32(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + movq 176(%rsp), %rdi + # Multiply + # A[0] * B[0] + movq (%rsp), %rdx + mulxq (%rdi), %r9, %r10 + # A[2] * B[0] + mulxq 16(%rdi), %r11, %r12 + # A[1] * B[0] + mulxq 8(%rdi), %rcx, %rbx + xorq %rbp, %rbp + adcxq %rcx, %r10 + # A[1] * B[3] + movq 24(%rsp), %rdx + mulxq 8(%rdi), %r13, %r14 + adcxq %rbx, %r11 + # A[0] * B[1] + movq 8(%rsp), %rdx + mulxq (%rdi), %rcx, %rbx + adoxq %rcx, %r10 + # A[2] * B[1] + mulxq 16(%rdi), %rcx, %r15 + adoxq %rbx, %r11 + adcxq %rcx, %r12 + # A[1] * B[2] + movq 16(%rsp), %rdx + mulxq 8(%rdi), %rcx, %rbx + adcxq %r15, %r13 + adoxq %rcx, %r12 + adcxq %rbp, %r14 + adoxq %rbx, %r13 + # A[0] * B[2] + mulxq (%rdi), %rcx, %rbx + adoxq %rbp, %r14 + xorq %r15, %r15 + adcxq %rcx, %r11 + # A[1] * B[1] + movq 8(%rsp), %rdx + mulxq 8(%rdi), %rdx, %rcx + adcxq %rbx, %r12 + adoxq %rdx, %r11 + # A[3] * B[1] + movq 8(%rsp), %rdx + adoxq %rcx, %r12 + mulxq 24(%rdi), %rcx, %rbx + adcxq %rcx, %r13 + # A[2] * B[2] + movq 16(%rsp), %rdx + mulxq 16(%rdi), %rdx, %rcx + adcxq %rbx, %r14 + adoxq %rdx, %r13 + # A[3] * B[3] + movq 24(%rsp), %rdx + adoxq %rcx, %r14 + mulxq 24(%rdi), %rcx, %rbx + adoxq %rbp, %r15 + adcxq %rcx, %r15 + # A[0] * B[3] + mulxq (%rdi), %rdx, %rcx + adcxq %rbx, %rbp + xorq %rbx, %rbx + adcxq %rdx, %r12 + # A[3] * B[0] + movq (%rsp), %rdx + adcxq %rcx, %r13 + mulxq 24(%rdi), %rdx, %rcx + adoxq %rdx, %r12 + adoxq %rcx, %r13 + # A[2] * B[3] + movq 24(%rsp), %rdx + mulxq 16(%rdi), %rdx, %rcx + adcxq %rdx, %r14 + # A[3] * B[2] + movq 16(%rsp), %rdx + adcxq %rcx, %r15 + mulxq 24(%rdi), %rcx, %rdx + adcxq %rbx, %rbp + adoxq %rcx, %r14 + adoxq %rdx, %r15 + adoxq %rbx, %rbp + # Reduce + movq $0x7fffffffffffffff, %rbx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r15, %rbp + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + andq %rbx, %r12 + # Multiply top half by 19 + movq $19, %rdx + xorq %rbx, %rbx + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %rcx, %r15 + adcxq %rcx, %r11 + adoxq %r15, %r12 + mulxq %rbp, %rbp, %rdx + adcxq %rbp, %r12 + adoxq %rbx, %rdx + adcxq %rbx, %rdx + # Overflow + shldq $0x01, %r12, %rdx + movq $0x7fffffffffffffff, %rbx + imulq $19, %rdx, %rcx + andq %rbx, %r12 + addq %rcx, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + adcq $0x00, %r12 + # Reduce if top bit set + movq %r12, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rbx, %r12 + addq %rcx, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + adcq $0x00, %r12 + # Store + movq %r9, (%rdi) + movq %r10, 8(%rdi) + movq %r11, 16(%rdi) + movq %r12, 24(%rdi) + xorq %rax, %rax + addq $0xc0, %rsp + popq %rbp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size curve25519_avx2,.-curve25519_avx2 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_pow22523_avx2 +.type fe_pow22523_avx2,@function +.align 4 +fe_pow22523_avx2: +#else +.section __TEXT,__text +.globl _fe_pow22523_avx2 +.p2align 2 +_fe_pow22523_avx2: +#endif /* __APPLE__ */ + subq $0x78, %rsp + # pow22523 + movq %rdi, 96(%rsp) + movq %rsi, 104(%rsp) + movq %rsp, %rdi + movq 104(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + movq %rsp, %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + movq 104(%rsp), %rsi + leaq 32(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + movq %rsp, %rdi + movq %rsp, %rsi + leaq 32(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + movq %rsp, %rdi + movq %rsp, %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + movq %rsp, %rdi + leaq 32(%rsp), %rsi + movq %rsp, %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + movq %rsp, %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + movb $4, 112(%rsp) + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi +L_fe_pow22523_avx2_1: +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + decb 112(%rsp) + jnz L_fe_pow22523_avx2_1 + movq %rsp, %rdi + leaq 32(%rsp), %rsi + movq %rsp, %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + movq %rsp, %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + movb $9, 112(%rsp) + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi +L_fe_pow22523_avx2_2: +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + decb 112(%rsp) + jnz L_fe_pow22523_avx2_2 + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi + movq %rsp, %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 32(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + movb $19, 112(%rsp) + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi +L_fe_pow22523_avx2_3: +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + decb 112(%rsp) + jnz L_fe_pow22523_avx2_3 + leaq 32(%rsp), %rdi + leaq 64(%rsp), %rsi + leaq 32(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + movb $9, 112(%rsp) + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi +L_fe_pow22523_avx2_4: +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + decb 112(%rsp) + jnz L_fe_pow22523_avx2_4 + movq %rsp, %rdi + leaq 32(%rsp), %rsi + movq %rsp, %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + movq %rsp, %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + movb $49, 112(%rsp) + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi +L_fe_pow22523_avx2_5: +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + decb 112(%rsp) + jnz L_fe_pow22523_avx2_5 + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi + movq %rsp, %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 64(%rsp), %rdi + leaq 32(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + movb $0x63, 112(%rsp) + leaq 64(%rsp), %rdi + leaq 64(%rsp), %rsi +L_fe_pow22523_avx2_6: +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + decb 112(%rsp) + jnz L_fe_pow22523_avx2_6 + leaq 32(%rsp), %rdi + leaq 64(%rsp), %rsi + leaq 32(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + movb $49, 112(%rsp) + leaq 32(%rsp), %rdi + leaq 32(%rsp), %rsi +L_fe_pow22523_avx2_7: +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + decb 112(%rsp) + jnz L_fe_pow22523_avx2_7 + movq %rsp, %rdi + leaq 32(%rsp), %rsi + movq %rsp, %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + movq %rsp, %rdi + movq %rsp, %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + movq %rsp, %rdi + movq %rsp, %rsi +#ifndef __APPLE__ + callq fe_sq_avx2@plt +#else + callq _fe_sq_avx2 +#endif /* __APPLE__ */ + movq 96(%rsp), %rdi + movq %rsp, %rsi + movq 104(%rsp), %rdx +#ifndef __APPLE__ + callq fe_mul_avx2@plt +#else + callq _fe_mul_avx2 +#endif /* __APPLE__ */ + movq 104(%rsp), %rsi + movq 96(%rsp), %rdi + addq $0x78, %rsp + repz retq +#ifndef __APPLE__ +.text +.globl fe_ge_to_p2_avx2 +.type fe_ge_to_p2_avx2,@function +.align 4 +fe_ge_to_p2_avx2: +#else +.section __TEXT,__text +.globl _fe_ge_to_p2_avx2 +.p2align 2 +_fe_ge_to_p2_avx2: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + subq $40, %rsp + movq %rsi, (%rsp) + movq %rdx, 8(%rsp) + movq %rcx, 16(%rsp) + movq %r8, 24(%rsp) + movq %r9, 32(%rsp) + movq 16(%rsp), %rsi + movq 88(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rdx + mulxq (%rsi), %r8, %r9 + # A[2] * B[0] + mulxq 16(%rsi), %r10, %r11 + # A[1] * B[0] + mulxq 8(%rsi), %rcx, %rax + xorq %r15, %r15 + adcxq %rcx, %r9 + # A[1] * B[3] + movq 24(%rbx), %rdx + mulxq 8(%rsi), %r12, %r13 + adcxq %rax, %r10 + # A[0] * B[1] + movq 8(%rbx), %rdx + mulxq (%rsi), %rcx, %rax + adoxq %rcx, %r9 + # A[2] * B[1] + mulxq 16(%rsi), %rcx, %r14 + adoxq %rax, %r10 + adcxq %rcx, %r11 + # A[1] * B[2] + movq 16(%rbx), %rdx + mulxq 8(%rsi), %rcx, %rax + adcxq %r14, %r12 + adoxq %rcx, %r11 + adcxq %r15, %r13 + adoxq %rax, %r12 + # A[0] * B[2] + mulxq (%rsi), %rcx, %rax + adoxq %r15, %r13 + xorq %r14, %r14 + adcxq %rcx, %r10 + # A[1] * B[1] + movq 8(%rbx), %rdx + mulxq 8(%rsi), %rdx, %rcx + adcxq %rax, %r11 + adoxq %rdx, %r10 + # A[3] * B[1] + movq 8(%rbx), %rdx + adoxq %rcx, %r11 + mulxq 24(%rsi), %rcx, %rax + adcxq %rcx, %r12 + # A[2] * B[2] + movq 16(%rbx), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rax, %r13 + adoxq %rdx, %r12 + # A[3] * B[3] + movq 24(%rbx), %rdx + adoxq %rcx, %r13 + mulxq 24(%rsi), %rcx, %rax + adoxq %r15, %r14 + adcxq %rcx, %r14 + # A[0] * B[3] + mulxq (%rsi), %rdx, %rcx + adcxq %rax, %r15 + xorq %rax, %rax + adcxq %rdx, %r11 + # A[3] * B[0] + movq (%rbx), %rdx + adcxq %rcx, %r12 + mulxq 24(%rsi), %rdx, %rcx + adoxq %rdx, %r11 + adoxq %rcx, %r12 + # A[2] * B[3] + movq 24(%rbx), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rdx, %r13 + # A[3] * B[2] + movq 16(%rbx), %rdx + adcxq %rcx, %r14 + mulxq 24(%rsi), %rcx, %rdx + adcxq %rax, %r15 + adoxq %rcx, %r13 + adoxq %rdx, %r14 + adoxq %rax, %r15 + # Reduce + movq $0x7fffffffffffffff, %rax + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rax, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rax, %rax + mulxq %r12, %rcx, %r12 + adcxq %rcx, %r8 + adoxq %r12, %r9 + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rax, %rdx + adcxq %rax, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rax + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq (%rsp), %rdi + movq 24(%rsp), %rsi + movq 32(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rdx + mulxq (%rsi), %r8, %r9 + # A[2] * B[0] + mulxq 16(%rsi), %r10, %r11 + # A[1] * B[0] + mulxq 8(%rsi), %rcx, %rax + xorq %r15, %r15 + adcxq %rcx, %r9 + # A[1] * B[3] + movq 24(%rbx), %rdx + mulxq 8(%rsi), %r12, %r13 + adcxq %rax, %r10 + # A[0] * B[1] + movq 8(%rbx), %rdx + mulxq (%rsi), %rcx, %rax + adoxq %rcx, %r9 + # A[2] * B[1] + mulxq 16(%rsi), %rcx, %r14 + adoxq %rax, %r10 + adcxq %rcx, %r11 + # A[1] * B[2] + movq 16(%rbx), %rdx + mulxq 8(%rsi), %rcx, %rax + adcxq %r14, %r12 + adoxq %rcx, %r11 + adcxq %r15, %r13 + adoxq %rax, %r12 + # A[0] * B[2] + mulxq (%rsi), %rcx, %rax + adoxq %r15, %r13 + xorq %r14, %r14 + adcxq %rcx, %r10 + # A[1] * B[1] + movq 8(%rbx), %rdx + mulxq 8(%rsi), %rdx, %rcx + adcxq %rax, %r11 + adoxq %rdx, %r10 + # A[3] * B[1] + movq 8(%rbx), %rdx + adoxq %rcx, %r11 + mulxq 24(%rsi), %rcx, %rax + adcxq %rcx, %r12 + # A[2] * B[2] + movq 16(%rbx), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rax, %r13 + adoxq %rdx, %r12 + # A[3] * B[3] + movq 24(%rbx), %rdx + adoxq %rcx, %r13 + mulxq 24(%rsi), %rcx, %rax + adoxq %r15, %r14 + adcxq %rcx, %r14 + # A[0] * B[3] + mulxq (%rsi), %rdx, %rcx + adcxq %rax, %r15 + xorq %rax, %rax + adcxq %rdx, %r11 + # A[3] * B[0] + movq (%rbx), %rdx + adcxq %rcx, %r12 + mulxq 24(%rsi), %rdx, %rcx + adoxq %rdx, %r11 + adoxq %rcx, %r12 + # A[2] * B[3] + movq 24(%rbx), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rdx, %r13 + # A[3] * B[2] + movq 16(%rbx), %rdx + adcxq %rcx, %r14 + mulxq 24(%rsi), %rcx, %rdx + adcxq %rax, %r15 + adoxq %rcx, %r13 + adoxq %rdx, %r14 + adoxq %rax, %r15 + # Reduce + movq $0x7fffffffffffffff, %rax + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rax, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rax, %rax + mulxq %r12, %rcx, %r12 + adcxq %rcx, %r8 + adoxq %r12, %r9 + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rax, %rdx + adcxq %rax, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rax + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 8(%rsp), %rdi + movq 88(%rsp), %rsi + # Multiply + # A[0] * B[0] + movq (%rsi), %rdx + mulxq (%rbx), %r8, %r9 + # A[2] * B[0] + mulxq 16(%rbx), %r10, %r11 + # A[1] * B[0] + mulxq 8(%rbx), %rcx, %rax + xorq %r15, %r15 + adcxq %rcx, %r9 + # A[1] * B[3] + movq 24(%rsi), %rdx + mulxq 8(%rbx), %r12, %r13 + adcxq %rax, %r10 + # A[0] * B[1] + movq 8(%rsi), %rdx + mulxq (%rbx), %rcx, %rax + adoxq %rcx, %r9 + # A[2] * B[1] + mulxq 16(%rbx), %rcx, %r14 + adoxq %rax, %r10 + adcxq %rcx, %r11 + # A[1] * B[2] + movq 16(%rsi), %rdx + mulxq 8(%rbx), %rcx, %rax + adcxq %r14, %r12 + adoxq %rcx, %r11 + adcxq %r15, %r13 + adoxq %rax, %r12 + # A[0] * B[2] + mulxq (%rbx), %rcx, %rax + adoxq %r15, %r13 + xorq %r14, %r14 + adcxq %rcx, %r10 + # A[1] * B[1] + movq 8(%rsi), %rdx + mulxq 8(%rbx), %rdx, %rcx + adcxq %rax, %r11 + adoxq %rdx, %r10 + # A[3] * B[1] + movq 8(%rsi), %rdx + adoxq %rcx, %r11 + mulxq 24(%rbx), %rcx, %rax + adcxq %rcx, %r12 + # A[2] * B[2] + movq 16(%rsi), %rdx + mulxq 16(%rbx), %rdx, %rcx + adcxq %rax, %r13 + adoxq %rdx, %r12 + # A[3] * B[3] + movq 24(%rsi), %rdx + adoxq %rcx, %r13 + mulxq 24(%rbx), %rcx, %rax + adoxq %r15, %r14 + adcxq %rcx, %r14 + # A[0] * B[3] + mulxq (%rbx), %rdx, %rcx + adcxq %rax, %r15 + xorq %rax, %rax + adcxq %rdx, %r11 + # A[3] * B[0] + movq (%rsi), %rdx + adcxq %rcx, %r12 + mulxq 24(%rbx), %rdx, %rcx + adoxq %rdx, %r11 + adoxq %rcx, %r12 + # A[2] * B[3] + movq 24(%rsi), %rdx + mulxq 16(%rbx), %rdx, %rcx + adcxq %rdx, %r13 + # A[3] * B[2] + movq 16(%rsi), %rdx + adcxq %rcx, %r14 + mulxq 24(%rbx), %rcx, %rdx + adcxq %rax, %r15 + adoxq %rcx, %r13 + adoxq %rdx, %r14 + adoxq %rax, %r15 + # Reduce + movq $0x7fffffffffffffff, %rax + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rax, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rax, %rax + mulxq %r12, %rcx, %r12 + adcxq %rcx, %r8 + adoxq %r12, %r9 + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rax, %rdx + adcxq %rax, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rax + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + addq $40, %rsp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size fe_ge_to_p2_avx2,.-fe_ge_to_p2_avx2 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_ge_to_p3_avx2 +.type fe_ge_to_p3_avx2,@function +.align 4 +fe_ge_to_p3_avx2: +#else +.section __TEXT,__text +.globl _fe_ge_to_p3_avx2 +.p2align 2 +_fe_ge_to_p3_avx2: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + subq $40, %rsp + movq %rsi, (%rsp) + movq %rdx, 8(%rsp) + movq %rcx, 16(%rsp) + movq %r8, 24(%rsp) + movq %r9, 32(%rsp) + movq 24(%rsp), %rsi + movq 96(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rdx + mulxq (%rsi), %r8, %r9 + # A[2] * B[0] + mulxq 16(%rsi), %r10, %r11 + # A[1] * B[0] + mulxq 8(%rsi), %rcx, %rax + xorq %r15, %r15 + adcxq %rcx, %r9 + # A[1] * B[3] + movq 24(%rbx), %rdx + mulxq 8(%rsi), %r12, %r13 + adcxq %rax, %r10 + # A[0] * B[1] + movq 8(%rbx), %rdx + mulxq (%rsi), %rcx, %rax + adoxq %rcx, %r9 + # A[2] * B[1] + mulxq 16(%rsi), %rcx, %r14 + adoxq %rax, %r10 + adcxq %rcx, %r11 + # A[1] * B[2] + movq 16(%rbx), %rdx + mulxq 8(%rsi), %rcx, %rax + adcxq %r14, %r12 + adoxq %rcx, %r11 + adcxq %r15, %r13 + adoxq %rax, %r12 + # A[0] * B[2] + mulxq (%rsi), %rcx, %rax + adoxq %r15, %r13 + xorq %r14, %r14 + adcxq %rcx, %r10 + # A[1] * B[1] + movq 8(%rbx), %rdx + mulxq 8(%rsi), %rdx, %rcx + adcxq %rax, %r11 + adoxq %rdx, %r10 + # A[3] * B[1] + movq 8(%rbx), %rdx + adoxq %rcx, %r11 + mulxq 24(%rsi), %rcx, %rax + adcxq %rcx, %r12 + # A[2] * B[2] + movq 16(%rbx), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rax, %r13 + adoxq %rdx, %r12 + # A[3] * B[3] + movq 24(%rbx), %rdx + adoxq %rcx, %r13 + mulxq 24(%rsi), %rcx, %rax + adoxq %r15, %r14 + adcxq %rcx, %r14 + # A[0] * B[3] + mulxq (%rsi), %rdx, %rcx + adcxq %rax, %r15 + xorq %rax, %rax + adcxq %rdx, %r11 + # A[3] * B[0] + movq (%rbx), %rdx + adcxq %rcx, %r12 + mulxq 24(%rsi), %rdx, %rcx + adoxq %rdx, %r11 + adoxq %rcx, %r12 + # A[2] * B[3] + movq 24(%rbx), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rdx, %r13 + # A[3] * B[2] + movq 16(%rbx), %rdx + adcxq %rcx, %r14 + mulxq 24(%rsi), %rcx, %rdx + adcxq %rax, %r15 + adoxq %rcx, %r13 + adoxq %rdx, %r14 + adoxq %rax, %r15 + # Reduce + movq $0x7fffffffffffffff, %rax + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rax, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rax, %rax + mulxq %r12, %rcx, %r12 + adcxq %rcx, %r8 + adoxq %r12, %r9 + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rax, %rdx + adcxq %rax, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rax + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq (%rsp), %rdi + movq 32(%rsp), %rsi + movq 88(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rdx + mulxq (%rsi), %r8, %r9 + # A[2] * B[0] + mulxq 16(%rsi), %r10, %r11 + # A[1] * B[0] + mulxq 8(%rsi), %rcx, %rax + xorq %r15, %r15 + adcxq %rcx, %r9 + # A[1] * B[3] + movq 24(%rbx), %rdx + mulxq 8(%rsi), %r12, %r13 + adcxq %rax, %r10 + # A[0] * B[1] + movq 8(%rbx), %rdx + mulxq (%rsi), %rcx, %rax + adoxq %rcx, %r9 + # A[2] * B[1] + mulxq 16(%rsi), %rcx, %r14 + adoxq %rax, %r10 + adcxq %rcx, %r11 + # A[1] * B[2] + movq 16(%rbx), %rdx + mulxq 8(%rsi), %rcx, %rax + adcxq %r14, %r12 + adoxq %rcx, %r11 + adcxq %r15, %r13 + adoxq %rax, %r12 + # A[0] * B[2] + mulxq (%rsi), %rcx, %rax + adoxq %r15, %r13 + xorq %r14, %r14 + adcxq %rcx, %r10 + # A[1] * B[1] + movq 8(%rbx), %rdx + mulxq 8(%rsi), %rdx, %rcx + adcxq %rax, %r11 + adoxq %rdx, %r10 + # A[3] * B[1] + movq 8(%rbx), %rdx + adoxq %rcx, %r11 + mulxq 24(%rsi), %rcx, %rax + adcxq %rcx, %r12 + # A[2] * B[2] + movq 16(%rbx), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rax, %r13 + adoxq %rdx, %r12 + # A[3] * B[3] + movq 24(%rbx), %rdx + adoxq %rcx, %r13 + mulxq 24(%rsi), %rcx, %rax + adoxq %r15, %r14 + adcxq %rcx, %r14 + # A[0] * B[3] + mulxq (%rsi), %rdx, %rcx + adcxq %rax, %r15 + xorq %rax, %rax + adcxq %rdx, %r11 + # A[3] * B[0] + movq (%rbx), %rdx + adcxq %rcx, %r12 + mulxq 24(%rsi), %rdx, %rcx + adoxq %rdx, %r11 + adoxq %rcx, %r12 + # A[2] * B[3] + movq 24(%rbx), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rdx, %r13 + # A[3] * B[2] + movq 16(%rbx), %rdx + adcxq %rcx, %r14 + mulxq 24(%rsi), %rcx, %rdx + adcxq %rax, %r15 + adoxq %rcx, %r13 + adoxq %rdx, %r14 + adoxq %rax, %r15 + # Reduce + movq $0x7fffffffffffffff, %rax + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rax, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rax, %rax + mulxq %r12, %rcx, %r12 + adcxq %rcx, %r8 + adoxq %r12, %r9 + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rax, %rdx + adcxq %rax, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rax + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 8(%rsp), %rdi + movq 96(%rsp), %rsi + # Multiply + # A[0] * B[0] + movq (%rsi), %rdx + mulxq (%rbx), %r8, %r9 + # A[2] * B[0] + mulxq 16(%rbx), %r10, %r11 + # A[1] * B[0] + mulxq 8(%rbx), %rcx, %rax + xorq %r15, %r15 + adcxq %rcx, %r9 + # A[1] * B[3] + movq 24(%rsi), %rdx + mulxq 8(%rbx), %r12, %r13 + adcxq %rax, %r10 + # A[0] * B[1] + movq 8(%rsi), %rdx + mulxq (%rbx), %rcx, %rax + adoxq %rcx, %r9 + # A[2] * B[1] + mulxq 16(%rbx), %rcx, %r14 + adoxq %rax, %r10 + adcxq %rcx, %r11 + # A[1] * B[2] + movq 16(%rsi), %rdx + mulxq 8(%rbx), %rcx, %rax + adcxq %r14, %r12 + adoxq %rcx, %r11 + adcxq %r15, %r13 + adoxq %rax, %r12 + # A[0] * B[2] + mulxq (%rbx), %rcx, %rax + adoxq %r15, %r13 + xorq %r14, %r14 + adcxq %rcx, %r10 + # A[1] * B[1] + movq 8(%rsi), %rdx + mulxq 8(%rbx), %rdx, %rcx + adcxq %rax, %r11 + adoxq %rdx, %r10 + # A[3] * B[1] + movq 8(%rsi), %rdx + adoxq %rcx, %r11 + mulxq 24(%rbx), %rcx, %rax + adcxq %rcx, %r12 + # A[2] * B[2] + movq 16(%rsi), %rdx + mulxq 16(%rbx), %rdx, %rcx + adcxq %rax, %r13 + adoxq %rdx, %r12 + # A[3] * B[3] + movq 24(%rsi), %rdx + adoxq %rcx, %r13 + mulxq 24(%rbx), %rcx, %rax + adoxq %r15, %r14 + adcxq %rcx, %r14 + # A[0] * B[3] + mulxq (%rbx), %rdx, %rcx + adcxq %rax, %r15 + xorq %rax, %rax + adcxq %rdx, %r11 + # A[3] * B[0] + movq (%rsi), %rdx + adcxq %rcx, %r12 + mulxq 24(%rbx), %rdx, %rcx + adoxq %rdx, %r11 + adoxq %rcx, %r12 + # A[2] * B[3] + movq 24(%rsi), %rdx + mulxq 16(%rbx), %rdx, %rcx + adcxq %rdx, %r13 + # A[3] * B[2] + movq 16(%rsi), %rdx + adcxq %rcx, %r14 + mulxq 24(%rbx), %rcx, %rdx + adcxq %rax, %r15 + adoxq %rcx, %r13 + adoxq %rdx, %r14 + adoxq %rax, %r15 + # Reduce + movq $0x7fffffffffffffff, %rax + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rax, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rax, %rax + mulxq %r12, %rcx, %r12 + adcxq %rcx, %r8 + adoxq %r12, %r9 + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rax, %rdx + adcxq %rax, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rax + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 16(%rsp), %rdi + movq 24(%rsp), %rsi + movq 32(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rdx + mulxq (%rsi), %r8, %r9 + # A[2] * B[0] + mulxq 16(%rsi), %r10, %r11 + # A[1] * B[0] + mulxq 8(%rsi), %rcx, %rax + xorq %r15, %r15 + adcxq %rcx, %r9 + # A[1] * B[3] + movq 24(%rbx), %rdx + mulxq 8(%rsi), %r12, %r13 + adcxq %rax, %r10 + # A[0] * B[1] + movq 8(%rbx), %rdx + mulxq (%rsi), %rcx, %rax + adoxq %rcx, %r9 + # A[2] * B[1] + mulxq 16(%rsi), %rcx, %r14 + adoxq %rax, %r10 + adcxq %rcx, %r11 + # A[1] * B[2] + movq 16(%rbx), %rdx + mulxq 8(%rsi), %rcx, %rax + adcxq %r14, %r12 + adoxq %rcx, %r11 + adcxq %r15, %r13 + adoxq %rax, %r12 + # A[0] * B[2] + mulxq (%rsi), %rcx, %rax + adoxq %r15, %r13 + xorq %r14, %r14 + adcxq %rcx, %r10 + # A[1] * B[1] + movq 8(%rbx), %rdx + mulxq 8(%rsi), %rdx, %rcx + adcxq %rax, %r11 + adoxq %rdx, %r10 + # A[3] * B[1] + movq 8(%rbx), %rdx + adoxq %rcx, %r11 + mulxq 24(%rsi), %rcx, %rax + adcxq %rcx, %r12 + # A[2] * B[2] + movq 16(%rbx), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rax, %r13 + adoxq %rdx, %r12 + # A[3] * B[3] + movq 24(%rbx), %rdx + adoxq %rcx, %r13 + mulxq 24(%rsi), %rcx, %rax + adoxq %r15, %r14 + adcxq %rcx, %r14 + # A[0] * B[3] + mulxq (%rsi), %rdx, %rcx + adcxq %rax, %r15 + xorq %rax, %rax + adcxq %rdx, %r11 + # A[3] * B[0] + movq (%rbx), %rdx + adcxq %rcx, %r12 + mulxq 24(%rsi), %rdx, %rcx + adoxq %rdx, %r11 + adoxq %rcx, %r12 + # A[2] * B[3] + movq 24(%rbx), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rdx, %r13 + # A[3] * B[2] + movq 16(%rbx), %rdx + adcxq %rcx, %r14 + mulxq 24(%rsi), %rcx, %rdx + adcxq %rax, %r15 + adoxq %rcx, %r13 + adoxq %rdx, %r14 + adoxq %rax, %r15 + # Reduce + movq $0x7fffffffffffffff, %rax + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rax, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rax, %rax + mulxq %r12, %rcx, %r12 + adcxq %rcx, %r8 + adoxq %r12, %r9 + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rax, %rdx + adcxq %rax, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rax + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + addq $40, %rsp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size fe_ge_to_p3_avx2,.-fe_ge_to_p3_avx2 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_ge_dbl_avx2 +.type fe_ge_dbl_avx2,@function +.align 4 +fe_ge_dbl_avx2: +#else +.section __TEXT,__text +.globl _fe_ge_dbl_avx2 +.p2align 2 +_fe_ge_dbl_avx2: +#endif /* __APPLE__ */ + pushq %rbp + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + subq $48, %rsp + movq %rdi, (%rsp) + movq %rsi, 8(%rsp) + movq %rdx, 16(%rsp) + movq %rcx, 24(%rsp) + movq %r8, 32(%rsp) + movq %r9, 40(%rsp) + movq 32(%rsp), %rsi + # Square + # A[0] * A[1] + movq (%rsi), %rdx + mulxq 8(%rsi), %r9, %r10 + # A[0] * A[3] + mulxq 24(%rsi), %r11, %r12 + # A[2] * A[1] + movq 16(%rsi), %rdx + mulxq 8(%rsi), %rcx, %rax + xorq %r15, %r15 + adoxq %rcx, %r11 + # A[2] * A[3] + mulxq 24(%rsi), %r13, %r14 + adoxq %rax, %r12 + # A[2] * A[0] + mulxq (%rsi), %rcx, %rax + adoxq %r15, %r13 + adcxq %rcx, %r10 + adoxq %r15, %r14 + # A[1] * A[3] + movq 8(%rsi), %rdx + mulxq 24(%rsi), %rbp, %r8 + adcxq %rax, %r11 + adcxq %rbp, %r12 + adcxq %r8, %r13 + adcxq %r15, %r14 + # Double with Carry Flag + xorq %r15, %r15 + # A[0] * A[0] + movq (%rsi), %rdx + mulxq %rdx, %r8, %rbp + adcxq %r9, %r9 + # A[1] * A[1] + movq 8(%rsi), %rdx + mulxq %rdx, %rcx, %rax + adcxq %r10, %r10 + adoxq %rbp, %r9 + adcxq %r11, %r11 + adoxq %rcx, %r10 + # A[2] * A[2] + movq 16(%rsi), %rdx + mulxq %rdx, %rbp, %rcx + adcxq %r12, %r12 + adoxq %rax, %r11 + adcxq %r13, %r13 + adoxq %rbp, %r12 + # A[3] * A[3] + movq 24(%rsi), %rdx + mulxq %rdx, %rbp, %rax + adcxq %r14, %r14 + adoxq %rcx, %r13 + adcxq %r15, %r15 + adoxq %rbp, %r14 + adoxq %rax, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rcx, %rcx + mulxq %r12, %rbp, %r12 + adcxq %rbp, %r8 + adoxq %r12, %r9 + mulxq %r13, %rbp, %r13 + adcxq %rbp, %r9 + adoxq %r13, %r10 + mulxq %r14, %rbp, %r14 + adcxq %rbp, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rcx, %rdx + adcxq %rcx, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rcx + imulq $19, %rdx, %rbp + andq %rcx, %r11 + addq %rbp, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rbp + andq %rcx, %r11 + addq %rbp, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 16(%rsp), %rdi + movq 40(%rsp), %rbx + # Square + # A[0] * A[1] + movq (%rbx), %rdx + mulxq 8(%rbx), %r9, %r10 + # A[0] * A[3] + mulxq 24(%rbx), %r11, %r12 + # A[2] * A[1] + movq 16(%rbx), %rdx + mulxq 8(%rbx), %rcx, %rax + xorq %r15, %r15 + adoxq %rcx, %r11 + # A[2] * A[3] + mulxq 24(%rbx), %r13, %r14 + adoxq %rax, %r12 + # A[2] * A[0] + mulxq (%rbx), %rcx, %rax + adoxq %r15, %r13 + adcxq %rcx, %r10 + adoxq %r15, %r14 + # A[1] * A[3] + movq 8(%rbx), %rdx + mulxq 24(%rbx), %rbp, %r8 + adcxq %rax, %r11 + adcxq %rbp, %r12 + adcxq %r8, %r13 + adcxq %r15, %r14 + # Double with Carry Flag + xorq %r15, %r15 + # A[0] * A[0] + movq (%rbx), %rdx + mulxq %rdx, %r8, %rbp + adcxq %r9, %r9 + # A[1] * A[1] + movq 8(%rbx), %rdx + mulxq %rdx, %rcx, %rax + adcxq %r10, %r10 + adoxq %rbp, %r9 + adcxq %r11, %r11 + adoxq %rcx, %r10 + # A[2] * A[2] + movq 16(%rbx), %rdx + mulxq %rdx, %rbp, %rcx + adcxq %r12, %r12 + adoxq %rax, %r11 + adcxq %r13, %r13 + adoxq %rbp, %r12 + # A[3] * A[3] + movq 24(%rbx), %rdx + mulxq %rdx, %rbp, %rax + adcxq %r14, %r14 + adoxq %rcx, %r13 + adcxq %r15, %r15 + adoxq %rbp, %r14 + adoxq %rax, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rcx, %rcx + mulxq %r12, %rbp, %r12 + adcxq %rbp, %r8 + adoxq %r12, %r9 + mulxq %r13, %rbp, %r13 + adcxq %rbp, %r9 + adoxq %r13, %r10 + mulxq %r14, %rbp, %r14 + adcxq %rbp, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rcx, %rdx + adcxq %rcx, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rcx + imulq $19, %rdx, %rbp + andq %rcx, %r11 + addq %rbp, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rbp + andq %rcx, %r11 + addq %rbp, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 8(%rsp), %rdi + # Add + movq (%rsi), %r8 + movq 8(%rsi), %r9 + addq (%rbx), %r8 + movq 16(%rsi), %r10 + adcq 8(%rbx), %r9 + movq 24(%rsi), %rdx + adcq 16(%rbx), %r10 + movq $-19, %rcx + adcq 24(%rbx), %rdx + movq $0x7fffffffffffffff, %rax + movq %rdx, %r11 + sarq $63, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Sub modulus (if overflow) + subq %rcx, %r8 + sbbq %rdx, %r9 + sbbq %rdx, %r10 + sbbq %rax, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 24(%rsp), %rsi + # Square + # A[0] * A[1] + movq (%rdi), %rdx + mulxq 8(%rdi), %r9, %r10 + # A[0] * A[3] + mulxq 24(%rdi), %r11, %r12 + # A[2] * A[1] + movq 16(%rdi), %rdx + mulxq 8(%rdi), %rcx, %rax + xorq %r15, %r15 + adoxq %rcx, %r11 + # A[2] * A[3] + mulxq 24(%rdi), %r13, %r14 + adoxq %rax, %r12 + # A[2] * A[0] + mulxq (%rdi), %rcx, %rax + adoxq %r15, %r13 + adcxq %rcx, %r10 + adoxq %r15, %r14 + # A[1] * A[3] + movq 8(%rdi), %rdx + mulxq 24(%rdi), %rbp, %r8 + adcxq %rax, %r11 + adcxq %rbp, %r12 + adcxq %r8, %r13 + adcxq %r15, %r14 + # Double with Carry Flag + xorq %r15, %r15 + # A[0] * A[0] + movq (%rdi), %rdx + mulxq %rdx, %r8, %rbp + adcxq %r9, %r9 + # A[1] * A[1] + movq 8(%rdi), %rdx + mulxq %rdx, %rcx, %rax + adcxq %r10, %r10 + adoxq %rbp, %r9 + adcxq %r11, %r11 + adoxq %rcx, %r10 + # A[2] * A[2] + movq 16(%rdi), %rdx + mulxq %rdx, %rbp, %rcx + adcxq %r12, %r12 + adoxq %rax, %r11 + adcxq %r13, %r13 + adoxq %rbp, %r12 + # A[3] * A[3] + movq 24(%rdi), %rdx + mulxq %rdx, %rbp, %rax + adcxq %r14, %r14 + adoxq %rcx, %r13 + adcxq %r15, %r15 + adoxq %rbp, %r14 + adoxq %rax, %r15 + # Reduce + movq $0x7fffffffffffffff, %rcx + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rcx, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rcx, %rcx + mulxq %r12, %rbp, %r12 + adcxq %rbp, %r8 + adoxq %r12, %r9 + mulxq %r13, %rbp, %r13 + adcxq %rbp, %r9 + adoxq %r13, %r10 + mulxq %r14, %rbp, %r14 + adcxq %rbp, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rcx, %rdx + adcxq %rcx, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rcx + imulq $19, %rdx, %rbp + andq %rcx, %r11 + addq %rbp, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rbp + andq %rcx, %r11 + addq %rbp, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rsi) + movq %r9, 8(%rsi) + movq %r10, 16(%rsi) + movq %r11, 24(%rsi) + movq 16(%rsp), %rsi + movq (%rsp), %rbx + # Add + movq (%rsi), %r8 + movq 8(%rsi), %r9 + movq 16(%rsi), %r10 + movq 24(%rsi), %rdx + movq %r8, %r12 + addq (%rbx), %r8 + movq %r9, %r13 + adcq 8(%rbx), %r9 + movq %r10, %r14 + adcq 16(%rbx), %r10 + movq %rdx, %r15 + adcq 24(%rbx), %rdx + movq $-19, %rcx + movq %rdx, %r11 + movq $0x7fffffffffffffff, %rax + sarq $63, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Sub modulus (if overflow) + subq %rcx, %r8 + sbbq %rdx, %r9 + sbbq %rdx, %r10 + sbbq %rax, %r11 + # Sub + subq (%rbx), %r12 + movq $0x00, %rdx + sbbq 8(%rbx), %r13 + movq $-19, %rcx + sbbq 16(%rbx), %r14 + movq $0x7fffffffffffffff, %rax + sbbq 24(%rbx), %r15 + sbbq $0x00, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Add modulus (if underflow) + addq %rcx, %r12 + adcq %rdx, %r13 + adcq %rdx, %r14 + adcq %rax, %r15 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq %r12, (%rsi) + movq %r13, 8(%rsi) + movq %r14, 16(%rsi) + movq %r15, 24(%rsi) + movq 24(%rsp), %rsi + # Sub + movq (%rsi), %r8 + movq 8(%rsi), %r9 + movq 16(%rsi), %r10 + movq 24(%rsi), %r11 + subq (%rdi), %r8 + movq $0x00, %rdx + sbbq 8(%rdi), %r9 + movq $-19, %rcx + sbbq 16(%rdi), %r10 + movq $0x7fffffffffffffff, %rax + sbbq 24(%rdi), %r11 + sbbq $0x00, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Add modulus (if underflow) + addq %rcx, %r8 + adcq %rdx, %r9 + adcq %rdx, %r10 + adcq %rax, %r11 + movq %r8, (%rbx) + movq %r9, 8(%rbx) + movq %r10, 16(%rbx) + movq %r11, 24(%rbx) + movq 104(%rsp), %rdi + # Square * 2 + # A[0] * A[1] + movq (%rdi), %rdx + mulxq 8(%rdi), %r9, %r10 + # A[0] * A[3] + mulxq 24(%rdi), %r11, %r12 + # A[2] * A[1] + movq 16(%rdi), %rdx + mulxq 8(%rdi), %rcx, %rax + xorq %r15, %r15 + adoxq %rcx, %r11 + # A[2] * A[3] + mulxq 24(%rdi), %r13, %r14 + adoxq %rax, %r12 + # A[2] * A[0] + mulxq (%rdi), %rcx, %rax + adoxq %r15, %r13 + adcxq %rcx, %r10 + adoxq %r15, %r14 + # A[1] * A[3] + movq 8(%rdi), %rdx + mulxq 24(%rdi), %rbp, %r8 + adcxq %rax, %r11 + adcxq %rbp, %r12 + adcxq %r8, %r13 + adcxq %r15, %r14 + # Double with Carry Flag + xorq %r15, %r15 + # A[0] * A[0] + movq (%rdi), %rdx + mulxq %rdx, %r8, %rbp + adcxq %r9, %r9 + # A[1] * A[1] + movq 8(%rdi), %rdx + mulxq %rdx, %rcx, %rax + adcxq %r10, %r10 + adoxq %rbp, %r9 + adcxq %r11, %r11 + adoxq %rcx, %r10 + # A[2] * A[2] + movq 16(%rdi), %rdx + mulxq %rdx, %rbp, %rcx + adcxq %r12, %r12 + adoxq %rax, %r11 + adcxq %r13, %r13 + adoxq %rbp, %r12 + # A[3] * A[3] + movq 24(%rdi), %rdx + mulxq %rdx, %rbp, %rax + adcxq %r14, %r14 + adoxq %rcx, %r13 + adcxq %r15, %r15 + adoxq %rbp, %r14 + adoxq %rax, %r15 + # Reduce + movq $0x7fffffffffffffff, %rax + xorq %rbp, %rbp + # Move top half into t4-t7 and remove top bit from t3 and double + shldq $3, %r15, %rbp + shldq $2, %r14, %r15 + shldq $2, %r13, %r14 + shldq $2, %r12, %r13 + shldq $2, %r11, %r12 + shldq $0x01, %r10, %r11 + shldq $0x01, %r9, %r10 + shldq $0x01, %r8, %r9 + shlq $0x01, %r8 + andq %rax, %r11 + # Two out left, one in right + andq %rax, %r15 + # Multiply top bits by 19*19 + imulq $0x169, %rbp, %rcx + xorq %rax, %rax + # Multiply top half by 19 + movq $19, %rdx + adoxq %rcx, %r8 + mulxq %r12, %rbp, %r12 + adcxq %rbp, %r8 + adoxq %r12, %r9 + mulxq %r13, %rbp, %r13 + adcxq %rbp, %r9 + adoxq %r13, %r10 + mulxq %r14, %rbp, %r14 + adcxq %rbp, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rax, %rdx + adcxq %rax, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rax + imulq $19, %rdx, %rbp + andq %rax, %r11 + addq %rbp, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rbp + andq %rax, %r11 + addq %rbp, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rsi) + movq %r9, 8(%rsi) + movq %r10, 16(%rsi) + movq %r11, 24(%rsi) + movq 16(%rsp), %rdi + # Sub + movq (%rsi), %r8 + movq 8(%rsi), %r9 + movq 16(%rsi), %r10 + movq 24(%rsi), %r11 + subq (%rdi), %r8 + movq $0x00, %rdx + sbbq 8(%rdi), %r9 + movq $-19, %rcx + sbbq 16(%rdi), %r10 + movq $0x7fffffffffffffff, %rax + sbbq 24(%rdi), %r11 + sbbq $0x00, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Add modulus (if underflow) + addq %rcx, %r8 + adcq %rdx, %r9 + adcq %rdx, %r10 + adcq %rax, %r11 + movq %r8, (%rsi) + movq %r9, 8(%rsi) + movq %r10, 16(%rsi) + movq %r11, 24(%rsi) + addq $48, %rsp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + popq %rbp + repz retq +#ifndef __APPLE__ +.size fe_ge_dbl_avx2,.-fe_ge_dbl_avx2 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_ge_madd_avx2 +.type fe_ge_madd_avx2,@function +.align 4 +fe_ge_madd_avx2: +#else +.section __TEXT,__text +.globl _fe_ge_madd_avx2 +.p2align 2 +_fe_ge_madd_avx2: +#endif /* __APPLE__ */ + pushq %rbp + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + subq $48, %rsp + movq %rdi, (%rsp) + movq %rsi, 8(%rsp) + movq %rdx, 16(%rsp) + movq %rcx, 24(%rsp) + movq %r8, 32(%rsp) + movq %r9, 40(%rsp) + movq 8(%rsp), %rsi + movq 40(%rsp), %rbx + movq 32(%rsp), %rbp + # Add + movq (%rbx), %r8 + movq 8(%rbx), %r9 + movq 16(%rbx), %r10 + movq 24(%rbx), %rdx + movq %r8, %r12 + addq (%rbp), %r8 + movq %r9, %r13 + adcq 8(%rbp), %r9 + movq %r10, %r14 + adcq 16(%rbp), %r10 + movq %rdx, %r15 + adcq 24(%rbp), %rdx + movq $-19, %rcx + movq %rdx, %r11 + movq $0x7fffffffffffffff, %rax + sarq $63, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Sub modulus (if overflow) + subq %rcx, %r8 + sbbq %rdx, %r9 + sbbq %rdx, %r10 + sbbq %rax, %r11 + # Sub + subq (%rbp), %r12 + movq $0x00, %rdx + sbbq 8(%rbp), %r13 + movq $-19, %rcx + sbbq 16(%rbp), %r14 + movq $0x7fffffffffffffff, %rax + sbbq 24(%rbp), %r15 + sbbq $0x00, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Add modulus (if underflow) + addq %rcx, %r12 + adcq %rdx, %r13 + adcq %rdx, %r14 + adcq %rax, %r15 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq %r12, (%rsi) + movq %r13, 8(%rsi) + movq %r14, 16(%rsi) + movq %r15, 24(%rsi) + movq 16(%rsp), %rbx + movq 128(%rsp), %rbp + # Multiply + # A[0] * B[0] + movq (%rbp), %rdx + mulxq (%rdi), %r8, %r9 + # A[2] * B[0] + mulxq 16(%rdi), %r10, %r11 + # A[1] * B[0] + mulxq 8(%rdi), %rcx, %rax + xorq %r15, %r15 + adcxq %rcx, %r9 + # A[1] * B[3] + movq 24(%rbp), %rdx + mulxq 8(%rdi), %r12, %r13 + adcxq %rax, %r10 + # A[0] * B[1] + movq 8(%rbp), %rdx + mulxq (%rdi), %rcx, %rax + adoxq %rcx, %r9 + # A[2] * B[1] + mulxq 16(%rdi), %rcx, %r14 + adoxq %rax, %r10 + adcxq %rcx, %r11 + # A[1] * B[2] + movq 16(%rbp), %rdx + mulxq 8(%rdi), %rcx, %rax + adcxq %r14, %r12 + adoxq %rcx, %r11 + adcxq %r15, %r13 + adoxq %rax, %r12 + # A[0] * B[2] + mulxq (%rdi), %rcx, %rax + adoxq %r15, %r13 + xorq %r14, %r14 + adcxq %rcx, %r10 + # A[1] * B[1] + movq 8(%rbp), %rdx + mulxq 8(%rdi), %rdx, %rcx + adcxq %rax, %r11 + adoxq %rdx, %r10 + # A[3] * B[1] + movq 8(%rbp), %rdx + adoxq %rcx, %r11 + mulxq 24(%rdi), %rcx, %rax + adcxq %rcx, %r12 + # A[2] * B[2] + movq 16(%rbp), %rdx + mulxq 16(%rdi), %rdx, %rcx + adcxq %rax, %r13 + adoxq %rdx, %r12 + # A[3] * B[3] + movq 24(%rbp), %rdx + adoxq %rcx, %r13 + mulxq 24(%rdi), %rcx, %rax + adoxq %r15, %r14 + adcxq %rcx, %r14 + # A[0] * B[3] + mulxq (%rdi), %rdx, %rcx + adcxq %rax, %r15 + xorq %rax, %rax + adcxq %rdx, %r11 + # A[3] * B[0] + movq (%rbp), %rdx + adcxq %rcx, %r12 + mulxq 24(%rdi), %rdx, %rcx + adoxq %rdx, %r11 + adoxq %rcx, %r12 + # A[2] * B[3] + movq 24(%rbp), %rdx + mulxq 16(%rdi), %rdx, %rcx + adcxq %rdx, %r13 + # A[3] * B[2] + movq 16(%rbp), %rdx + adcxq %rcx, %r14 + mulxq 24(%rdi), %rcx, %rdx + adcxq %rax, %r15 + adoxq %rcx, %r13 + adoxq %rdx, %r14 + adoxq %rax, %r15 + # Reduce + movq $0x7fffffffffffffff, %rax + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rax, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rax, %rax + mulxq %r12, %rcx, %r12 + adcxq %rcx, %r8 + adoxq %r12, %r9 + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rax, %rdx + adcxq %rax, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rax + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rbx) + movq %r9, 8(%rbx) + movq %r10, 16(%rbx) + movq %r11, 24(%rbx) + movq 136(%rsp), %rdi + # Multiply + # A[0] * B[0] + movq (%rdi), %rdx + mulxq (%rsi), %r8, %r9 + # A[2] * B[0] + mulxq 16(%rsi), %r10, %r11 + # A[1] * B[0] + mulxq 8(%rsi), %rcx, %rax + xorq %r15, %r15 + adcxq %rcx, %r9 + # A[1] * B[3] + movq 24(%rdi), %rdx + mulxq 8(%rsi), %r12, %r13 + adcxq %rax, %r10 + # A[0] * B[1] + movq 8(%rdi), %rdx + mulxq (%rsi), %rcx, %rax + adoxq %rcx, %r9 + # A[2] * B[1] + mulxq 16(%rsi), %rcx, %r14 + adoxq %rax, %r10 + adcxq %rcx, %r11 + # A[1] * B[2] + movq 16(%rdi), %rdx + mulxq 8(%rsi), %rcx, %rax + adcxq %r14, %r12 + adoxq %rcx, %r11 + adcxq %r15, %r13 + adoxq %rax, %r12 + # A[0] * B[2] + mulxq (%rsi), %rcx, %rax + adoxq %r15, %r13 + xorq %r14, %r14 + adcxq %rcx, %r10 + # A[1] * B[1] + movq 8(%rdi), %rdx + mulxq 8(%rsi), %rdx, %rcx + adcxq %rax, %r11 + adoxq %rdx, %r10 + # A[3] * B[1] + movq 8(%rdi), %rdx + adoxq %rcx, %r11 + mulxq 24(%rsi), %rcx, %rax + adcxq %rcx, %r12 + # A[2] * B[2] + movq 16(%rdi), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rax, %r13 + adoxq %rdx, %r12 + # A[3] * B[3] + movq 24(%rdi), %rdx + adoxq %rcx, %r13 + mulxq 24(%rsi), %rcx, %rax + adoxq %r15, %r14 + adcxq %rcx, %r14 + # A[0] * B[3] + mulxq (%rsi), %rdx, %rcx + adcxq %rax, %r15 + xorq %rax, %rax + adcxq %rdx, %r11 + # A[3] * B[0] + movq (%rdi), %rdx + adcxq %rcx, %r12 + mulxq 24(%rsi), %rdx, %rcx + adoxq %rdx, %r11 + adoxq %rcx, %r12 + # A[2] * B[3] + movq 24(%rdi), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rdx, %r13 + # A[3] * B[2] + movq 16(%rdi), %rdx + adcxq %rcx, %r14 + mulxq 24(%rsi), %rcx, %rdx + adcxq %rax, %r15 + adoxq %rcx, %r13 + adoxq %rdx, %r14 + adoxq %rax, %r15 + # Reduce + movq $0x7fffffffffffffff, %rax + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rax, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rax, %rax + mulxq %r12, %rcx, %r12 + adcxq %rcx, %r8 + adoxq %r12, %r9 + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rax, %rdx + adcxq %rax, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rax + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rsi) + movq %r9, 8(%rsi) + movq %r10, 16(%rsi) + movq %r11, 24(%rsi) + movq 24(%rsp), %rdi + movq 120(%rsp), %rsi + movq 112(%rsp), %rbp + # Multiply + # A[0] * B[0] + movq (%rbp), %rdx + mulxq (%rsi), %r8, %r9 + # A[2] * B[0] + mulxq 16(%rsi), %r10, %r11 + # A[1] * B[0] + mulxq 8(%rsi), %rcx, %rax + xorq %r15, %r15 + adcxq %rcx, %r9 + # A[1] * B[3] + movq 24(%rbp), %rdx + mulxq 8(%rsi), %r12, %r13 + adcxq %rax, %r10 + # A[0] * B[1] + movq 8(%rbp), %rdx + mulxq (%rsi), %rcx, %rax + adoxq %rcx, %r9 + # A[2] * B[1] + mulxq 16(%rsi), %rcx, %r14 + adoxq %rax, %r10 + adcxq %rcx, %r11 + # A[1] * B[2] + movq 16(%rbp), %rdx + mulxq 8(%rsi), %rcx, %rax + adcxq %r14, %r12 + adoxq %rcx, %r11 + adcxq %r15, %r13 + adoxq %rax, %r12 + # A[0] * B[2] + mulxq (%rsi), %rcx, %rax + adoxq %r15, %r13 + xorq %r14, %r14 + adcxq %rcx, %r10 + # A[1] * B[1] + movq 8(%rbp), %rdx + mulxq 8(%rsi), %rdx, %rcx + adcxq %rax, %r11 + adoxq %rdx, %r10 + # A[3] * B[1] + movq 8(%rbp), %rdx + adoxq %rcx, %r11 + mulxq 24(%rsi), %rcx, %rax + adcxq %rcx, %r12 + # A[2] * B[2] + movq 16(%rbp), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rax, %r13 + adoxq %rdx, %r12 + # A[3] * B[3] + movq 24(%rbp), %rdx + adoxq %rcx, %r13 + mulxq 24(%rsi), %rcx, %rax + adoxq %r15, %r14 + adcxq %rcx, %r14 + # A[0] * B[3] + mulxq (%rsi), %rdx, %rcx + adcxq %rax, %r15 + xorq %rax, %rax + adcxq %rdx, %r11 + # A[3] * B[0] + movq (%rbp), %rdx + adcxq %rcx, %r12 + mulxq 24(%rsi), %rdx, %rcx + adoxq %rdx, %r11 + adoxq %rcx, %r12 + # A[2] * B[3] + movq 24(%rbp), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rdx, %r13 + # A[3] * B[2] + movq 16(%rbp), %rdx + adcxq %rcx, %r14 + mulxq 24(%rsi), %rcx, %rdx + adcxq %rax, %r15 + adoxq %rcx, %r13 + adoxq %rdx, %r14 + adoxq %rax, %r15 + # Reduce + movq $0x7fffffffffffffff, %rax + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rax, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rax, %rax + mulxq %r12, %rcx, %r12 + adcxq %rcx, %r8 + adoxq %r12, %r9 + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rax, %rdx + adcxq %rax, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rax + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 8(%rsp), %rdi + movq (%rsp), %rsi + # Add + movq (%rbx), %r8 + movq 8(%rbx), %r9 + movq 16(%rbx), %r10 + movq 24(%rbx), %rdx + movq %r8, %r12 + addq (%rdi), %r8 + movq %r9, %r13 + adcq 8(%rdi), %r9 + movq %r10, %r14 + adcq 16(%rdi), %r10 + movq %rdx, %r15 + adcq 24(%rdi), %rdx + movq $-19, %rcx + movq %rdx, %r11 + movq $0x7fffffffffffffff, %rax + sarq $63, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Sub modulus (if overflow) + subq %rcx, %r8 + sbbq %rdx, %r9 + sbbq %rdx, %r10 + sbbq %rax, %r11 + # Sub + subq (%rdi), %r12 + movq $0x00, %rdx + sbbq 8(%rdi), %r13 + movq $-19, %rcx + sbbq 16(%rdi), %r14 + movq $0x7fffffffffffffff, %rax + sbbq 24(%rdi), %r15 + sbbq $0x00, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Add modulus (if underflow) + addq %rcx, %r12 + adcq %rdx, %r13 + adcq %rdx, %r14 + adcq %rax, %r15 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq %r12, (%rsi) + movq %r13, 8(%rsi) + movq %r14, 16(%rsi) + movq %r15, 24(%rsi) + movq 104(%rsp), %rdi + # Double + movq (%rdi), %r8 + movq 8(%rdi), %r9 + addq %r8, %r8 + movq 16(%rdi), %r10 + adcq %r9, %r9 + movq 24(%rdi), %rdx + adcq %r10, %r10 + movq $-19, %rcx + adcq %rdx, %rdx + movq $0x7fffffffffffffff, %rax + movq %rdx, %r11 + sarq $63, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Sub modulus (if overflow) + subq %rcx, %r8 + sbbq %rdx, %r9 + sbbq %rdx, %r10 + sbbq %rax, %r11 + movq %r8, (%rbx) + movq %r9, 8(%rbx) + movq %r10, 16(%rbx) + movq %r11, 24(%rbx) + movq 24(%rsp), %rdi + # Add + movq (%rbx), %r8 + movq 8(%rbx), %r9 + movq 16(%rbx), %r10 + movq 24(%rbx), %rdx + movq %r8, %r12 + addq (%rdi), %r8 + movq %r9, %r13 + adcq 8(%rdi), %r9 + movq %r10, %r14 + adcq 16(%rdi), %r10 + movq %rdx, %r15 + adcq 24(%rdi), %rdx + movq $-19, %rcx + movq %rdx, %r11 + movq $0x7fffffffffffffff, %rax + sarq $63, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Sub modulus (if overflow) + subq %rcx, %r8 + sbbq %rdx, %r9 + sbbq %rdx, %r10 + sbbq %rax, %r11 + # Sub + subq (%rdi), %r12 + movq $0x00, %rdx + sbbq 8(%rdi), %r13 + movq $-19, %rcx + sbbq 16(%rdi), %r14 + movq $0x7fffffffffffffff, %rax + sbbq 24(%rdi), %r15 + sbbq $0x00, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Add modulus (if underflow) + addq %rcx, %r12 + adcq %rdx, %r13 + adcq %rdx, %r14 + adcq %rax, %r15 + movq %r8, (%rbx) + movq %r9, 8(%rbx) + movq %r10, 16(%rbx) + movq %r11, 24(%rbx) + movq %r12, (%rdi) + movq %r13, 8(%rdi) + movq %r14, 16(%rdi) + movq %r15, 24(%rdi) + addq $48, %rsp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + popq %rbp + repz retq +#ifndef __APPLE__ +.size fe_ge_madd_avx2,.-fe_ge_madd_avx2 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_ge_msub_avx2 +.type fe_ge_msub_avx2,@function +.align 4 +fe_ge_msub_avx2: +#else +.section __TEXT,__text +.globl _fe_ge_msub_avx2 +.p2align 2 +_fe_ge_msub_avx2: +#endif /* __APPLE__ */ + pushq %rbp + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + subq $48, %rsp + movq %rdi, (%rsp) + movq %rsi, 8(%rsp) + movq %rdx, 16(%rsp) + movq %rcx, 24(%rsp) + movq %r8, 32(%rsp) + movq %r9, 40(%rsp) + movq 8(%rsp), %rsi + movq 40(%rsp), %rbx + movq 32(%rsp), %rbp + # Add + movq (%rbx), %r8 + movq 8(%rbx), %r9 + movq 16(%rbx), %r10 + movq 24(%rbx), %rdx + movq %r8, %r12 + addq (%rbp), %r8 + movq %r9, %r13 + adcq 8(%rbp), %r9 + movq %r10, %r14 + adcq 16(%rbp), %r10 + movq %rdx, %r15 + adcq 24(%rbp), %rdx + movq $-19, %rcx + movq %rdx, %r11 + movq $0x7fffffffffffffff, %rax + sarq $63, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Sub modulus (if overflow) + subq %rcx, %r8 + sbbq %rdx, %r9 + sbbq %rdx, %r10 + sbbq %rax, %r11 + # Sub + subq (%rbp), %r12 + movq $0x00, %rdx + sbbq 8(%rbp), %r13 + movq $-19, %rcx + sbbq 16(%rbp), %r14 + movq $0x7fffffffffffffff, %rax + sbbq 24(%rbp), %r15 + sbbq $0x00, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Add modulus (if underflow) + addq %rcx, %r12 + adcq %rdx, %r13 + adcq %rdx, %r14 + adcq %rax, %r15 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq %r12, (%rsi) + movq %r13, 8(%rsi) + movq %r14, 16(%rsi) + movq %r15, 24(%rsi) + movq 16(%rsp), %rbx + movq 136(%rsp), %rbp + # Multiply + # A[0] * B[0] + movq (%rbp), %rdx + mulxq (%rdi), %r8, %r9 + # A[2] * B[0] + mulxq 16(%rdi), %r10, %r11 + # A[1] * B[0] + mulxq 8(%rdi), %rcx, %rax + xorq %r15, %r15 + adcxq %rcx, %r9 + # A[1] * B[3] + movq 24(%rbp), %rdx + mulxq 8(%rdi), %r12, %r13 + adcxq %rax, %r10 + # A[0] * B[1] + movq 8(%rbp), %rdx + mulxq (%rdi), %rcx, %rax + adoxq %rcx, %r9 + # A[2] * B[1] + mulxq 16(%rdi), %rcx, %r14 + adoxq %rax, %r10 + adcxq %rcx, %r11 + # A[1] * B[2] + movq 16(%rbp), %rdx + mulxq 8(%rdi), %rcx, %rax + adcxq %r14, %r12 + adoxq %rcx, %r11 + adcxq %r15, %r13 + adoxq %rax, %r12 + # A[0] * B[2] + mulxq (%rdi), %rcx, %rax + adoxq %r15, %r13 + xorq %r14, %r14 + adcxq %rcx, %r10 + # A[1] * B[1] + movq 8(%rbp), %rdx + mulxq 8(%rdi), %rdx, %rcx + adcxq %rax, %r11 + adoxq %rdx, %r10 + # A[3] * B[1] + movq 8(%rbp), %rdx + adoxq %rcx, %r11 + mulxq 24(%rdi), %rcx, %rax + adcxq %rcx, %r12 + # A[2] * B[2] + movq 16(%rbp), %rdx + mulxq 16(%rdi), %rdx, %rcx + adcxq %rax, %r13 + adoxq %rdx, %r12 + # A[3] * B[3] + movq 24(%rbp), %rdx + adoxq %rcx, %r13 + mulxq 24(%rdi), %rcx, %rax + adoxq %r15, %r14 + adcxq %rcx, %r14 + # A[0] * B[3] + mulxq (%rdi), %rdx, %rcx + adcxq %rax, %r15 + xorq %rax, %rax + adcxq %rdx, %r11 + # A[3] * B[0] + movq (%rbp), %rdx + adcxq %rcx, %r12 + mulxq 24(%rdi), %rdx, %rcx + adoxq %rdx, %r11 + adoxq %rcx, %r12 + # A[2] * B[3] + movq 24(%rbp), %rdx + mulxq 16(%rdi), %rdx, %rcx + adcxq %rdx, %r13 + # A[3] * B[2] + movq 16(%rbp), %rdx + adcxq %rcx, %r14 + mulxq 24(%rdi), %rcx, %rdx + adcxq %rax, %r15 + adoxq %rcx, %r13 + adoxq %rdx, %r14 + adoxq %rax, %r15 + # Reduce + movq $0x7fffffffffffffff, %rax + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rax, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rax, %rax + mulxq %r12, %rcx, %r12 + adcxq %rcx, %r8 + adoxq %r12, %r9 + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rax, %rdx + adcxq %rax, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rax + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rbx) + movq %r9, 8(%rbx) + movq %r10, 16(%rbx) + movq %r11, 24(%rbx) + movq 128(%rsp), %rdi + # Multiply + # A[0] * B[0] + movq (%rdi), %rdx + mulxq (%rsi), %r8, %r9 + # A[2] * B[0] + mulxq 16(%rsi), %r10, %r11 + # A[1] * B[0] + mulxq 8(%rsi), %rcx, %rax + xorq %r15, %r15 + adcxq %rcx, %r9 + # A[1] * B[3] + movq 24(%rdi), %rdx + mulxq 8(%rsi), %r12, %r13 + adcxq %rax, %r10 + # A[0] * B[1] + movq 8(%rdi), %rdx + mulxq (%rsi), %rcx, %rax + adoxq %rcx, %r9 + # A[2] * B[1] + mulxq 16(%rsi), %rcx, %r14 + adoxq %rax, %r10 + adcxq %rcx, %r11 + # A[1] * B[2] + movq 16(%rdi), %rdx + mulxq 8(%rsi), %rcx, %rax + adcxq %r14, %r12 + adoxq %rcx, %r11 + adcxq %r15, %r13 + adoxq %rax, %r12 + # A[0] * B[2] + mulxq (%rsi), %rcx, %rax + adoxq %r15, %r13 + xorq %r14, %r14 + adcxq %rcx, %r10 + # A[1] * B[1] + movq 8(%rdi), %rdx + mulxq 8(%rsi), %rdx, %rcx + adcxq %rax, %r11 + adoxq %rdx, %r10 + # A[3] * B[1] + movq 8(%rdi), %rdx + adoxq %rcx, %r11 + mulxq 24(%rsi), %rcx, %rax + adcxq %rcx, %r12 + # A[2] * B[2] + movq 16(%rdi), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rax, %r13 + adoxq %rdx, %r12 + # A[3] * B[3] + movq 24(%rdi), %rdx + adoxq %rcx, %r13 + mulxq 24(%rsi), %rcx, %rax + adoxq %r15, %r14 + adcxq %rcx, %r14 + # A[0] * B[3] + mulxq (%rsi), %rdx, %rcx + adcxq %rax, %r15 + xorq %rax, %rax + adcxq %rdx, %r11 + # A[3] * B[0] + movq (%rdi), %rdx + adcxq %rcx, %r12 + mulxq 24(%rsi), %rdx, %rcx + adoxq %rdx, %r11 + adoxq %rcx, %r12 + # A[2] * B[3] + movq 24(%rdi), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rdx, %r13 + # A[3] * B[2] + movq 16(%rdi), %rdx + adcxq %rcx, %r14 + mulxq 24(%rsi), %rcx, %rdx + adcxq %rax, %r15 + adoxq %rcx, %r13 + adoxq %rdx, %r14 + adoxq %rax, %r15 + # Reduce + movq $0x7fffffffffffffff, %rax + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rax, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rax, %rax + mulxq %r12, %rcx, %r12 + adcxq %rcx, %r8 + adoxq %r12, %r9 + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rax, %rdx + adcxq %rax, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rax + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rsi) + movq %r9, 8(%rsi) + movq %r10, 16(%rsi) + movq %r11, 24(%rsi) + movq 24(%rsp), %rdi + movq 120(%rsp), %rsi + movq 112(%rsp), %rbp + # Multiply + # A[0] * B[0] + movq (%rbp), %rdx + mulxq (%rsi), %r8, %r9 + # A[2] * B[0] + mulxq 16(%rsi), %r10, %r11 + # A[1] * B[0] + mulxq 8(%rsi), %rcx, %rax + xorq %r15, %r15 + adcxq %rcx, %r9 + # A[1] * B[3] + movq 24(%rbp), %rdx + mulxq 8(%rsi), %r12, %r13 + adcxq %rax, %r10 + # A[0] * B[1] + movq 8(%rbp), %rdx + mulxq (%rsi), %rcx, %rax + adoxq %rcx, %r9 + # A[2] * B[1] + mulxq 16(%rsi), %rcx, %r14 + adoxq %rax, %r10 + adcxq %rcx, %r11 + # A[1] * B[2] + movq 16(%rbp), %rdx + mulxq 8(%rsi), %rcx, %rax + adcxq %r14, %r12 + adoxq %rcx, %r11 + adcxq %r15, %r13 + adoxq %rax, %r12 + # A[0] * B[2] + mulxq (%rsi), %rcx, %rax + adoxq %r15, %r13 + xorq %r14, %r14 + adcxq %rcx, %r10 + # A[1] * B[1] + movq 8(%rbp), %rdx + mulxq 8(%rsi), %rdx, %rcx + adcxq %rax, %r11 + adoxq %rdx, %r10 + # A[3] * B[1] + movq 8(%rbp), %rdx + adoxq %rcx, %r11 + mulxq 24(%rsi), %rcx, %rax + adcxq %rcx, %r12 + # A[2] * B[2] + movq 16(%rbp), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rax, %r13 + adoxq %rdx, %r12 + # A[3] * B[3] + movq 24(%rbp), %rdx + adoxq %rcx, %r13 + mulxq 24(%rsi), %rcx, %rax + adoxq %r15, %r14 + adcxq %rcx, %r14 + # A[0] * B[3] + mulxq (%rsi), %rdx, %rcx + adcxq %rax, %r15 + xorq %rax, %rax + adcxq %rdx, %r11 + # A[3] * B[0] + movq (%rbp), %rdx + adcxq %rcx, %r12 + mulxq 24(%rsi), %rdx, %rcx + adoxq %rdx, %r11 + adoxq %rcx, %r12 + # A[2] * B[3] + movq 24(%rbp), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rdx, %r13 + # A[3] * B[2] + movq 16(%rbp), %rdx + adcxq %rcx, %r14 + mulxq 24(%rsi), %rcx, %rdx + adcxq %rax, %r15 + adoxq %rcx, %r13 + adoxq %rdx, %r14 + adoxq %rax, %r15 + # Reduce + movq $0x7fffffffffffffff, %rax + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rax, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rax, %rax + mulxq %r12, %rcx, %r12 + adcxq %rcx, %r8 + adoxq %r12, %r9 + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rax, %rdx + adcxq %rax, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rax + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 8(%rsp), %rsi + movq (%rsp), %rbp + # Add + movq (%rbx), %r8 + movq 8(%rbx), %r9 + movq 16(%rbx), %r10 + movq 24(%rbx), %rdx + movq %r8, %r12 + addq (%rsi), %r8 + movq %r9, %r13 + adcq 8(%rsi), %r9 + movq %r10, %r14 + adcq 16(%rsi), %r10 + movq %rdx, %r15 + adcq 24(%rsi), %rdx + movq $-19, %rcx + movq %rdx, %r11 + movq $0x7fffffffffffffff, %rax + sarq $63, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Sub modulus (if overflow) + subq %rcx, %r8 + sbbq %rdx, %r9 + sbbq %rdx, %r10 + sbbq %rax, %r11 + # Sub + subq (%rsi), %r12 + movq $0x00, %rdx + sbbq 8(%rsi), %r13 + movq $-19, %rcx + sbbq 16(%rsi), %r14 + movq $0x7fffffffffffffff, %rax + sbbq 24(%rsi), %r15 + sbbq $0x00, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Add modulus (if underflow) + addq %rcx, %r12 + adcq %rdx, %r13 + adcq %rdx, %r14 + adcq %rax, %r15 + movq %r8, (%rsi) + movq %r9, 8(%rsi) + movq %r10, 16(%rsi) + movq %r11, 24(%rsi) + movq %r12, (%rbp) + movq %r13, 8(%rbp) + movq %r14, 16(%rbp) + movq %r15, 24(%rbp) + movq 104(%rsp), %rsi + # Double + movq (%rsi), %r8 + movq 8(%rsi), %r9 + addq %r8, %r8 + movq 16(%rsi), %r10 + adcq %r9, %r9 + movq 24(%rsi), %rdx + adcq %r10, %r10 + movq $-19, %rcx + adcq %rdx, %rdx + movq $0x7fffffffffffffff, %rax + movq %rdx, %r11 + sarq $63, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Sub modulus (if overflow) + subq %rcx, %r8 + sbbq %rdx, %r9 + sbbq %rdx, %r10 + sbbq %rax, %r11 + movq %r8, (%rbx) + movq %r9, 8(%rbx) + movq %r10, 16(%rbx) + movq %r11, 24(%rbx) + # Add + movq (%rbx), %r8 + movq 8(%rbx), %r9 + movq 16(%rbx), %r10 + movq 24(%rbx), %rdx + movq %r8, %r12 + addq (%rdi), %r8 + movq %r9, %r13 + adcq 8(%rdi), %r9 + movq %r10, %r14 + adcq 16(%rdi), %r10 + movq %rdx, %r15 + adcq 24(%rdi), %rdx + movq $-19, %rcx + movq %rdx, %r11 + movq $0x7fffffffffffffff, %rax + sarq $63, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Sub modulus (if overflow) + subq %rcx, %r8 + sbbq %rdx, %r9 + sbbq %rdx, %r10 + sbbq %rax, %r11 + # Sub + subq (%rdi), %r12 + movq $0x00, %rdx + sbbq 8(%rdi), %r13 + movq $-19, %rcx + sbbq 16(%rdi), %r14 + movq $0x7fffffffffffffff, %rax + sbbq 24(%rdi), %r15 + sbbq $0x00, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Add modulus (if underflow) + addq %rcx, %r12 + adcq %rdx, %r13 + adcq %rdx, %r14 + adcq %rax, %r15 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq %r12, (%rbx) + movq %r13, 8(%rbx) + movq %r14, 16(%rbx) + movq %r15, 24(%rbx) + addq $48, %rsp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + popq %rbp + repz retq +#ifndef __APPLE__ +.size fe_ge_msub_avx2,.-fe_ge_msub_avx2 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_ge_add_avx2 +.type fe_ge_add_avx2,@function +.align 4 +fe_ge_add_avx2: +#else +.section __TEXT,__text +.globl _fe_ge_add_avx2 +.p2align 2 +_fe_ge_add_avx2: +#endif /* __APPLE__ */ + pushq %rbx + pushq %rbp + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + subq $0x50, %rsp + movq %rdi, (%rsp) + movq %rsi, 8(%rsp) + movq %rdx, 16(%rsp) + movq %rcx, 24(%rsp) + movq %r8, 32(%rsp) + movq %r9, 40(%rsp) + movq 8(%rsp), %rsi + movq 40(%rsp), %rbx + movq 32(%rsp), %rbp + # Add + movq (%rbx), %r8 + movq 8(%rbx), %r9 + movq 16(%rbx), %r10 + movq 24(%rbx), %rdx + movq %r8, %r12 + addq (%rbp), %r8 + movq %r9, %r13 + adcq 8(%rbp), %r9 + movq %r10, %r14 + adcq 16(%rbp), %r10 + movq %rdx, %r15 + adcq 24(%rbp), %rdx + movq $-19, %rcx + movq %rdx, %r11 + movq $0x7fffffffffffffff, %rax + sarq $63, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Sub modulus (if overflow) + subq %rcx, %r8 + sbbq %rdx, %r9 + sbbq %rdx, %r10 + sbbq %rax, %r11 + # Sub + subq (%rbp), %r12 + movq $0x00, %rdx + sbbq 8(%rbp), %r13 + movq $-19, %rcx + sbbq 16(%rbp), %r14 + movq $0x7fffffffffffffff, %rax + sbbq 24(%rbp), %r15 + sbbq $0x00, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Add modulus (if underflow) + addq %rcx, %r12 + adcq %rdx, %r13 + adcq %rdx, %r14 + adcq %rax, %r15 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq %r12, (%rsi) + movq %r13, 8(%rsi) + movq %r14, 16(%rsi) + movq %r15, 24(%rsi) + movq 16(%rsp), %rbx + movq 168(%rsp), %rbp + # Multiply + # A[0] * B[0] + movq (%rbp), %rdx + mulxq (%rdi), %r8, %r9 + # A[2] * B[0] + mulxq 16(%rdi), %r10, %r11 + # A[1] * B[0] + mulxq 8(%rdi), %rcx, %rax + xorq %r15, %r15 + adcxq %rcx, %r9 + # A[1] * B[3] + movq 24(%rbp), %rdx + mulxq 8(%rdi), %r12, %r13 + adcxq %rax, %r10 + # A[0] * B[1] + movq 8(%rbp), %rdx + mulxq (%rdi), %rcx, %rax + adoxq %rcx, %r9 + # A[2] * B[1] + mulxq 16(%rdi), %rcx, %r14 + adoxq %rax, %r10 + adcxq %rcx, %r11 + # A[1] * B[2] + movq 16(%rbp), %rdx + mulxq 8(%rdi), %rcx, %rax + adcxq %r14, %r12 + adoxq %rcx, %r11 + adcxq %r15, %r13 + adoxq %rax, %r12 + # A[0] * B[2] + mulxq (%rdi), %rcx, %rax + adoxq %r15, %r13 + xorq %r14, %r14 + adcxq %rcx, %r10 + # A[1] * B[1] + movq 8(%rbp), %rdx + mulxq 8(%rdi), %rdx, %rcx + adcxq %rax, %r11 + adoxq %rdx, %r10 + # A[3] * B[1] + movq 8(%rbp), %rdx + adoxq %rcx, %r11 + mulxq 24(%rdi), %rcx, %rax + adcxq %rcx, %r12 + # A[2] * B[2] + movq 16(%rbp), %rdx + mulxq 16(%rdi), %rdx, %rcx + adcxq %rax, %r13 + adoxq %rdx, %r12 + # A[3] * B[3] + movq 24(%rbp), %rdx + adoxq %rcx, %r13 + mulxq 24(%rdi), %rcx, %rax + adoxq %r15, %r14 + adcxq %rcx, %r14 + # A[0] * B[3] + mulxq (%rdi), %rdx, %rcx + adcxq %rax, %r15 + xorq %rax, %rax + adcxq %rdx, %r11 + # A[3] * B[0] + movq (%rbp), %rdx + adcxq %rcx, %r12 + mulxq 24(%rdi), %rdx, %rcx + adoxq %rdx, %r11 + adoxq %rcx, %r12 + # A[2] * B[3] + movq 24(%rbp), %rdx + mulxq 16(%rdi), %rdx, %rcx + adcxq %rdx, %r13 + # A[3] * B[2] + movq 16(%rbp), %rdx + adcxq %rcx, %r14 + mulxq 24(%rdi), %rcx, %rdx + adcxq %rax, %r15 + adoxq %rcx, %r13 + adoxq %rdx, %r14 + adoxq %rax, %r15 + # Reduce + movq $0x7fffffffffffffff, %rax + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rax, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rax, %rax + mulxq %r12, %rcx, %r12 + adcxq %rcx, %r8 + adoxq %r12, %r9 + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rax, %rdx + adcxq %rax, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rax + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rbx) + movq %r9, 8(%rbx) + movq %r10, 16(%rbx) + movq %r11, 24(%rbx) + movq 176(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rdx + mulxq (%rsi), %r8, %r9 + # A[2] * B[0] + mulxq 16(%rsi), %r10, %r11 + # A[1] * B[0] + mulxq 8(%rsi), %rcx, %rax + xorq %r15, %r15 + adcxq %rcx, %r9 + # A[1] * B[3] + movq 24(%rbx), %rdx + mulxq 8(%rsi), %r12, %r13 + adcxq %rax, %r10 + # A[0] * B[1] + movq 8(%rbx), %rdx + mulxq (%rsi), %rcx, %rax + adoxq %rcx, %r9 + # A[2] * B[1] + mulxq 16(%rsi), %rcx, %r14 + adoxq %rax, %r10 + adcxq %rcx, %r11 + # A[1] * B[2] + movq 16(%rbx), %rdx + mulxq 8(%rsi), %rcx, %rax + adcxq %r14, %r12 + adoxq %rcx, %r11 + adcxq %r15, %r13 + adoxq %rax, %r12 + # A[0] * B[2] + mulxq (%rsi), %rcx, %rax + adoxq %r15, %r13 + xorq %r14, %r14 + adcxq %rcx, %r10 + # A[1] * B[1] + movq 8(%rbx), %rdx + mulxq 8(%rsi), %rdx, %rcx + adcxq %rax, %r11 + adoxq %rdx, %r10 + # A[3] * B[1] + movq 8(%rbx), %rdx + adoxq %rcx, %r11 + mulxq 24(%rsi), %rcx, %rax + adcxq %rcx, %r12 + # A[2] * B[2] + movq 16(%rbx), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rax, %r13 + adoxq %rdx, %r12 + # A[3] * B[3] + movq 24(%rbx), %rdx + adoxq %rcx, %r13 + mulxq 24(%rsi), %rcx, %rax + adoxq %r15, %r14 + adcxq %rcx, %r14 + # A[0] * B[3] + mulxq (%rsi), %rdx, %rcx + adcxq %rax, %r15 + xorq %rax, %rax + adcxq %rdx, %r11 + # A[3] * B[0] + movq (%rbx), %rdx + adcxq %rcx, %r12 + mulxq 24(%rsi), %rdx, %rcx + adoxq %rdx, %r11 + adoxq %rcx, %r12 + # A[2] * B[3] + movq 24(%rbx), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rdx, %r13 + # A[3] * B[2] + movq 16(%rbx), %rdx + adcxq %rcx, %r14 + mulxq 24(%rsi), %rcx, %rdx + adcxq %rax, %r15 + adoxq %rcx, %r13 + adoxq %rdx, %r14 + adoxq %rax, %r15 + # Reduce + movq $0x7fffffffffffffff, %rax + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rax, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rax, %rax + mulxq %r12, %rcx, %r12 + adcxq %rcx, %r8 + adoxq %r12, %r9 + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rax, %rdx + adcxq %rax, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rax + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rsi) + movq %r9, 8(%rsi) + movq %r10, 16(%rsi) + movq %r11, 24(%rsi) + movq 24(%rsp), %rsi + movq 160(%rsp), %rbx + movq 144(%rsp), %rbp + # Multiply + # A[0] * B[0] + movq (%rbp), %rdx + mulxq (%rbx), %r8, %r9 + # A[2] * B[0] + mulxq 16(%rbx), %r10, %r11 + # A[1] * B[0] + mulxq 8(%rbx), %rcx, %rax + xorq %r15, %r15 + adcxq %rcx, %r9 + # A[1] * B[3] + movq 24(%rbp), %rdx + mulxq 8(%rbx), %r12, %r13 + adcxq %rax, %r10 + # A[0] * B[1] + movq 8(%rbp), %rdx + mulxq (%rbx), %rcx, %rax + adoxq %rcx, %r9 + # A[2] * B[1] + mulxq 16(%rbx), %rcx, %r14 + adoxq %rax, %r10 + adcxq %rcx, %r11 + # A[1] * B[2] + movq 16(%rbp), %rdx + mulxq 8(%rbx), %rcx, %rax + adcxq %r14, %r12 + adoxq %rcx, %r11 + adcxq %r15, %r13 + adoxq %rax, %r12 + # A[0] * B[2] + mulxq (%rbx), %rcx, %rax + adoxq %r15, %r13 + xorq %r14, %r14 + adcxq %rcx, %r10 + # A[1] * B[1] + movq 8(%rbp), %rdx + mulxq 8(%rbx), %rdx, %rcx + adcxq %rax, %r11 + adoxq %rdx, %r10 + # A[3] * B[1] + movq 8(%rbp), %rdx + adoxq %rcx, %r11 + mulxq 24(%rbx), %rcx, %rax + adcxq %rcx, %r12 + # A[2] * B[2] + movq 16(%rbp), %rdx + mulxq 16(%rbx), %rdx, %rcx + adcxq %rax, %r13 + adoxq %rdx, %r12 + # A[3] * B[3] + movq 24(%rbp), %rdx + adoxq %rcx, %r13 + mulxq 24(%rbx), %rcx, %rax + adoxq %r15, %r14 + adcxq %rcx, %r14 + # A[0] * B[3] + mulxq (%rbx), %rdx, %rcx + adcxq %rax, %r15 + xorq %rax, %rax + adcxq %rdx, %r11 + # A[3] * B[0] + movq (%rbp), %rdx + adcxq %rcx, %r12 + mulxq 24(%rbx), %rdx, %rcx + adoxq %rdx, %r11 + adoxq %rcx, %r12 + # A[2] * B[3] + movq 24(%rbp), %rdx + mulxq 16(%rbx), %rdx, %rcx + adcxq %rdx, %r13 + # A[3] * B[2] + movq 16(%rbp), %rdx + adcxq %rcx, %r14 + mulxq 24(%rbx), %rcx, %rdx + adcxq %rax, %r15 + adoxq %rcx, %r13 + adoxq %rdx, %r14 + adoxq %rax, %r15 + # Reduce + movq $0x7fffffffffffffff, %rax + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rax, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rax, %rax + mulxq %r12, %rcx, %r12 + adcxq %rcx, %r8 + adoxq %r12, %r9 + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rax, %rdx + adcxq %rax, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rax + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rsi) + movq %r9, 8(%rsi) + movq %r10, 16(%rsi) + movq %r11, 24(%rsi) + movq 136(%rsp), %rsi + movq 152(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rdx + mulxq (%rsi), %r8, %r9 + # A[2] * B[0] + mulxq 16(%rsi), %r10, %r11 + # A[1] * B[0] + mulxq 8(%rsi), %rcx, %rax + xorq %r15, %r15 + adcxq %rcx, %r9 + # A[1] * B[3] + movq 24(%rbx), %rdx + mulxq 8(%rsi), %r12, %r13 + adcxq %rax, %r10 + # A[0] * B[1] + movq 8(%rbx), %rdx + mulxq (%rsi), %rcx, %rax + adoxq %rcx, %r9 + # A[2] * B[1] + mulxq 16(%rsi), %rcx, %r14 + adoxq %rax, %r10 + adcxq %rcx, %r11 + # A[1] * B[2] + movq 16(%rbx), %rdx + mulxq 8(%rsi), %rcx, %rax + adcxq %r14, %r12 + adoxq %rcx, %r11 + adcxq %r15, %r13 + adoxq %rax, %r12 + # A[0] * B[2] + mulxq (%rsi), %rcx, %rax + adoxq %r15, %r13 + xorq %r14, %r14 + adcxq %rcx, %r10 + # A[1] * B[1] + movq 8(%rbx), %rdx + mulxq 8(%rsi), %rdx, %rcx + adcxq %rax, %r11 + adoxq %rdx, %r10 + # A[3] * B[1] + movq 8(%rbx), %rdx + adoxq %rcx, %r11 + mulxq 24(%rsi), %rcx, %rax + adcxq %rcx, %r12 + # A[2] * B[2] + movq 16(%rbx), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rax, %r13 + adoxq %rdx, %r12 + # A[3] * B[3] + movq 24(%rbx), %rdx + adoxq %rcx, %r13 + mulxq 24(%rsi), %rcx, %rax + adoxq %r15, %r14 + adcxq %rcx, %r14 + # A[0] * B[3] + mulxq (%rsi), %rdx, %rcx + adcxq %rax, %r15 + xorq %rax, %rax + adcxq %rdx, %r11 + # A[3] * B[0] + movq (%rbx), %rdx + adcxq %rcx, %r12 + mulxq 24(%rsi), %rdx, %rcx + adoxq %rdx, %r11 + adoxq %rcx, %r12 + # A[2] * B[3] + movq 24(%rbx), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rdx, %r13 + # A[3] * B[2] + movq 16(%rbx), %rdx + adcxq %rcx, %r14 + mulxq 24(%rsi), %rcx, %rdx + adcxq %rax, %r15 + adoxq %rcx, %r13 + adoxq %rdx, %r14 + adoxq %rax, %r15 + # Reduce + movq $0x7fffffffffffffff, %rax + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rax, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rax, %rax + mulxq %r12, %rcx, %r12 + adcxq %rcx, %r8 + adoxq %r12, %r9 + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rax, %rdx + adcxq %rax, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rax + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + leaq 48(%rsp), %rsi + # Double + movq (%rdi), %r8 + movq 8(%rdi), %r9 + addq %r8, %r8 + movq 16(%rdi), %r10 + adcq %r9, %r9 + movq 24(%rdi), %rdx + adcq %r10, %r10 + movq $-19, %rcx + adcq %rdx, %rdx + movq $0x7fffffffffffffff, %rax + movq %rdx, %r11 + sarq $63, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Sub modulus (if overflow) + subq %rcx, %r8 + sbbq %rdx, %r9 + sbbq %rdx, %r10 + sbbq %rax, %r11 + movq %r8, (%rsi) + movq %r9, 8(%rsi) + movq %r10, 16(%rsi) + movq %r11, 24(%rsi) + movq 8(%rsp), %rbx + movq 16(%rsp), %rbp + # Add + movq (%rbp), %r8 + movq 8(%rbp), %r9 + movq 16(%rbp), %r10 + movq 24(%rbp), %rdx + movq %r8, %r12 + addq (%rbx), %r8 + movq %r9, %r13 + adcq 8(%rbx), %r9 + movq %r10, %r14 + adcq 16(%rbx), %r10 + movq %rdx, %r15 + adcq 24(%rbx), %rdx + movq $-19, %rcx + movq %rdx, %r11 + movq $0x7fffffffffffffff, %rax + sarq $63, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Sub modulus (if overflow) + subq %rcx, %r8 + sbbq %rdx, %r9 + sbbq %rdx, %r10 + sbbq %rax, %r11 + # Sub + subq (%rbx), %r12 + movq $0x00, %rdx + sbbq 8(%rbx), %r13 + movq $-19, %rcx + sbbq 16(%rbx), %r14 + movq $0x7fffffffffffffff, %rax + sbbq 24(%rbx), %r15 + sbbq $0x00, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Add modulus (if underflow) + addq %rcx, %r12 + adcq %rdx, %r13 + adcq %rdx, %r14 + adcq %rax, %r15 + movq %r8, (%rbx) + movq %r9, 8(%rbx) + movq %r10, 16(%rbx) + movq %r11, 24(%rbx) + movq %r12, (%rdi) + movq %r13, 8(%rdi) + movq %r14, 16(%rdi) + movq %r15, 24(%rdi) + movq 24(%rsp), %rdi + # Add + movq (%rsi), %r8 + movq 8(%rsi), %r9 + movq 16(%rsi), %r10 + movq 24(%rsi), %rdx + movq %r8, %r12 + addq (%rdi), %r8 + movq %r9, %r13 + adcq 8(%rdi), %r9 + movq %r10, %r14 + adcq 16(%rdi), %r10 + movq %rdx, %r15 + adcq 24(%rdi), %rdx + movq $-19, %rcx + movq %rdx, %r11 + movq $0x7fffffffffffffff, %rax + sarq $63, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Sub modulus (if overflow) + subq %rcx, %r8 + sbbq %rdx, %r9 + sbbq %rdx, %r10 + sbbq %rax, %r11 + # Sub + subq (%rdi), %r12 + movq $0x00, %rdx + sbbq 8(%rdi), %r13 + movq $-19, %rcx + sbbq 16(%rdi), %r14 + movq $0x7fffffffffffffff, %rax + sbbq 24(%rdi), %r15 + sbbq $0x00, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Add modulus (if underflow) + addq %rcx, %r12 + adcq %rdx, %r13 + adcq %rdx, %r14 + adcq %rax, %r15 + movq %r8, (%rbp) + movq %r9, 8(%rbp) + movq %r10, 16(%rbp) + movq %r11, 24(%rbp) + movq %r12, (%rdi) + movq %r13, 8(%rdi) + movq %r14, 16(%rdi) + movq %r15, 24(%rdi) + addq $0x50, %rsp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbp + popq %rbx + repz retq +#ifndef __APPLE__ +.size fe_ge_add_avx2,.-fe_ge_add_avx2 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl fe_ge_sub_avx2 +.type fe_ge_sub_avx2,@function +.align 4 +fe_ge_sub_avx2: +#else +.section __TEXT,__text +.globl _fe_ge_sub_avx2 +.p2align 2 +_fe_ge_sub_avx2: +#endif /* __APPLE__ */ + pushq %rbx + pushq %rbp + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + subq $0x50, %rsp + movq %rdi, (%rsp) + movq %rsi, 8(%rsp) + movq %rdx, 16(%rsp) + movq %rcx, 24(%rsp) + movq %r8, 32(%rsp) + movq %r9, 40(%rsp) + movq 8(%rsp), %rsi + movq 40(%rsp), %rbx + movq 32(%rsp), %rbp + # Add + movq (%rbx), %r8 + movq 8(%rbx), %r9 + movq 16(%rbx), %r10 + movq 24(%rbx), %rdx + movq %r8, %r12 + addq (%rbp), %r8 + movq %r9, %r13 + adcq 8(%rbp), %r9 + movq %r10, %r14 + adcq 16(%rbp), %r10 + movq %rdx, %r15 + adcq 24(%rbp), %rdx + movq $-19, %rcx + movq %rdx, %r11 + movq $0x7fffffffffffffff, %rax + sarq $63, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Sub modulus (if overflow) + subq %rcx, %r8 + sbbq %rdx, %r9 + sbbq %rdx, %r10 + sbbq %rax, %r11 + # Sub + subq (%rbp), %r12 + movq $0x00, %rdx + sbbq 8(%rbp), %r13 + movq $-19, %rcx + sbbq 16(%rbp), %r14 + movq $0x7fffffffffffffff, %rax + sbbq 24(%rbp), %r15 + sbbq $0x00, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Add modulus (if underflow) + addq %rcx, %r12 + adcq %rdx, %r13 + adcq %rdx, %r14 + adcq %rax, %r15 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq %r12, (%rsi) + movq %r13, 8(%rsi) + movq %r14, 16(%rsi) + movq %r15, 24(%rsi) + movq 16(%rsp), %rbx + movq 176(%rsp), %rbp + # Multiply + # A[0] * B[0] + movq (%rbp), %rdx + mulxq (%rdi), %r8, %r9 + # A[2] * B[0] + mulxq 16(%rdi), %r10, %r11 + # A[1] * B[0] + mulxq 8(%rdi), %rcx, %rax + xorq %r15, %r15 + adcxq %rcx, %r9 + # A[1] * B[3] + movq 24(%rbp), %rdx + mulxq 8(%rdi), %r12, %r13 + adcxq %rax, %r10 + # A[0] * B[1] + movq 8(%rbp), %rdx + mulxq (%rdi), %rcx, %rax + adoxq %rcx, %r9 + # A[2] * B[1] + mulxq 16(%rdi), %rcx, %r14 + adoxq %rax, %r10 + adcxq %rcx, %r11 + # A[1] * B[2] + movq 16(%rbp), %rdx + mulxq 8(%rdi), %rcx, %rax + adcxq %r14, %r12 + adoxq %rcx, %r11 + adcxq %r15, %r13 + adoxq %rax, %r12 + # A[0] * B[2] + mulxq (%rdi), %rcx, %rax + adoxq %r15, %r13 + xorq %r14, %r14 + adcxq %rcx, %r10 + # A[1] * B[1] + movq 8(%rbp), %rdx + mulxq 8(%rdi), %rdx, %rcx + adcxq %rax, %r11 + adoxq %rdx, %r10 + # A[3] * B[1] + movq 8(%rbp), %rdx + adoxq %rcx, %r11 + mulxq 24(%rdi), %rcx, %rax + adcxq %rcx, %r12 + # A[2] * B[2] + movq 16(%rbp), %rdx + mulxq 16(%rdi), %rdx, %rcx + adcxq %rax, %r13 + adoxq %rdx, %r12 + # A[3] * B[3] + movq 24(%rbp), %rdx + adoxq %rcx, %r13 + mulxq 24(%rdi), %rcx, %rax + adoxq %r15, %r14 + adcxq %rcx, %r14 + # A[0] * B[3] + mulxq (%rdi), %rdx, %rcx + adcxq %rax, %r15 + xorq %rax, %rax + adcxq %rdx, %r11 + # A[3] * B[0] + movq (%rbp), %rdx + adcxq %rcx, %r12 + mulxq 24(%rdi), %rdx, %rcx + adoxq %rdx, %r11 + adoxq %rcx, %r12 + # A[2] * B[3] + movq 24(%rbp), %rdx + mulxq 16(%rdi), %rdx, %rcx + adcxq %rdx, %r13 + # A[3] * B[2] + movq 16(%rbp), %rdx + adcxq %rcx, %r14 + mulxq 24(%rdi), %rcx, %rdx + adcxq %rax, %r15 + adoxq %rcx, %r13 + adoxq %rdx, %r14 + adoxq %rax, %r15 + # Reduce + movq $0x7fffffffffffffff, %rax + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rax, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rax, %rax + mulxq %r12, %rcx, %r12 + adcxq %rcx, %r8 + adoxq %r12, %r9 + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rax, %rdx + adcxq %rax, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rax + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rbx) + movq %r9, 8(%rbx) + movq %r10, 16(%rbx) + movq %r11, 24(%rbx) + movq 168(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rdx + mulxq (%rsi), %r8, %r9 + # A[2] * B[0] + mulxq 16(%rsi), %r10, %r11 + # A[1] * B[0] + mulxq 8(%rsi), %rcx, %rax + xorq %r15, %r15 + adcxq %rcx, %r9 + # A[1] * B[3] + movq 24(%rbx), %rdx + mulxq 8(%rsi), %r12, %r13 + adcxq %rax, %r10 + # A[0] * B[1] + movq 8(%rbx), %rdx + mulxq (%rsi), %rcx, %rax + adoxq %rcx, %r9 + # A[2] * B[1] + mulxq 16(%rsi), %rcx, %r14 + adoxq %rax, %r10 + adcxq %rcx, %r11 + # A[1] * B[2] + movq 16(%rbx), %rdx + mulxq 8(%rsi), %rcx, %rax + adcxq %r14, %r12 + adoxq %rcx, %r11 + adcxq %r15, %r13 + adoxq %rax, %r12 + # A[0] * B[2] + mulxq (%rsi), %rcx, %rax + adoxq %r15, %r13 + xorq %r14, %r14 + adcxq %rcx, %r10 + # A[1] * B[1] + movq 8(%rbx), %rdx + mulxq 8(%rsi), %rdx, %rcx + adcxq %rax, %r11 + adoxq %rdx, %r10 + # A[3] * B[1] + movq 8(%rbx), %rdx + adoxq %rcx, %r11 + mulxq 24(%rsi), %rcx, %rax + adcxq %rcx, %r12 + # A[2] * B[2] + movq 16(%rbx), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rax, %r13 + adoxq %rdx, %r12 + # A[3] * B[3] + movq 24(%rbx), %rdx + adoxq %rcx, %r13 + mulxq 24(%rsi), %rcx, %rax + adoxq %r15, %r14 + adcxq %rcx, %r14 + # A[0] * B[3] + mulxq (%rsi), %rdx, %rcx + adcxq %rax, %r15 + xorq %rax, %rax + adcxq %rdx, %r11 + # A[3] * B[0] + movq (%rbx), %rdx + adcxq %rcx, %r12 + mulxq 24(%rsi), %rdx, %rcx + adoxq %rdx, %r11 + adoxq %rcx, %r12 + # A[2] * B[3] + movq 24(%rbx), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rdx, %r13 + # A[3] * B[2] + movq 16(%rbx), %rdx + adcxq %rcx, %r14 + mulxq 24(%rsi), %rcx, %rdx + adcxq %rax, %r15 + adoxq %rcx, %r13 + adoxq %rdx, %r14 + adoxq %rax, %r15 + # Reduce + movq $0x7fffffffffffffff, %rax + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rax, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rax, %rax + mulxq %r12, %rcx, %r12 + adcxq %rcx, %r8 + adoxq %r12, %r9 + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rax, %rdx + adcxq %rax, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rax + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rsi) + movq %r9, 8(%rsi) + movq %r10, 16(%rsi) + movq %r11, 24(%rsi) + movq 24(%rsp), %rsi + movq 160(%rsp), %rbx + movq 144(%rsp), %rbp + # Multiply + # A[0] * B[0] + movq (%rbp), %rdx + mulxq (%rbx), %r8, %r9 + # A[2] * B[0] + mulxq 16(%rbx), %r10, %r11 + # A[1] * B[0] + mulxq 8(%rbx), %rcx, %rax + xorq %r15, %r15 + adcxq %rcx, %r9 + # A[1] * B[3] + movq 24(%rbp), %rdx + mulxq 8(%rbx), %r12, %r13 + adcxq %rax, %r10 + # A[0] * B[1] + movq 8(%rbp), %rdx + mulxq (%rbx), %rcx, %rax + adoxq %rcx, %r9 + # A[2] * B[1] + mulxq 16(%rbx), %rcx, %r14 + adoxq %rax, %r10 + adcxq %rcx, %r11 + # A[1] * B[2] + movq 16(%rbp), %rdx + mulxq 8(%rbx), %rcx, %rax + adcxq %r14, %r12 + adoxq %rcx, %r11 + adcxq %r15, %r13 + adoxq %rax, %r12 + # A[0] * B[2] + mulxq (%rbx), %rcx, %rax + adoxq %r15, %r13 + xorq %r14, %r14 + adcxq %rcx, %r10 + # A[1] * B[1] + movq 8(%rbp), %rdx + mulxq 8(%rbx), %rdx, %rcx + adcxq %rax, %r11 + adoxq %rdx, %r10 + # A[3] * B[1] + movq 8(%rbp), %rdx + adoxq %rcx, %r11 + mulxq 24(%rbx), %rcx, %rax + adcxq %rcx, %r12 + # A[2] * B[2] + movq 16(%rbp), %rdx + mulxq 16(%rbx), %rdx, %rcx + adcxq %rax, %r13 + adoxq %rdx, %r12 + # A[3] * B[3] + movq 24(%rbp), %rdx + adoxq %rcx, %r13 + mulxq 24(%rbx), %rcx, %rax + adoxq %r15, %r14 + adcxq %rcx, %r14 + # A[0] * B[3] + mulxq (%rbx), %rdx, %rcx + adcxq %rax, %r15 + xorq %rax, %rax + adcxq %rdx, %r11 + # A[3] * B[0] + movq (%rbp), %rdx + adcxq %rcx, %r12 + mulxq 24(%rbx), %rdx, %rcx + adoxq %rdx, %r11 + adoxq %rcx, %r12 + # A[2] * B[3] + movq 24(%rbp), %rdx + mulxq 16(%rbx), %rdx, %rcx + adcxq %rdx, %r13 + # A[3] * B[2] + movq 16(%rbp), %rdx + adcxq %rcx, %r14 + mulxq 24(%rbx), %rcx, %rdx + adcxq %rax, %r15 + adoxq %rcx, %r13 + adoxq %rdx, %r14 + adoxq %rax, %r15 + # Reduce + movq $0x7fffffffffffffff, %rax + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rax, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rax, %rax + mulxq %r12, %rcx, %r12 + adcxq %rcx, %r8 + adoxq %r12, %r9 + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rax, %rdx + adcxq %rax, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rax + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rsi) + movq %r9, 8(%rsi) + movq %r10, 16(%rsi) + movq %r11, 24(%rsi) + movq 136(%rsp), %rsi + movq 152(%rsp), %rbx + # Multiply + # A[0] * B[0] + movq (%rbx), %rdx + mulxq (%rsi), %r8, %r9 + # A[2] * B[0] + mulxq 16(%rsi), %r10, %r11 + # A[1] * B[0] + mulxq 8(%rsi), %rcx, %rax + xorq %r15, %r15 + adcxq %rcx, %r9 + # A[1] * B[3] + movq 24(%rbx), %rdx + mulxq 8(%rsi), %r12, %r13 + adcxq %rax, %r10 + # A[0] * B[1] + movq 8(%rbx), %rdx + mulxq (%rsi), %rcx, %rax + adoxq %rcx, %r9 + # A[2] * B[1] + mulxq 16(%rsi), %rcx, %r14 + adoxq %rax, %r10 + adcxq %rcx, %r11 + # A[1] * B[2] + movq 16(%rbx), %rdx + mulxq 8(%rsi), %rcx, %rax + adcxq %r14, %r12 + adoxq %rcx, %r11 + adcxq %r15, %r13 + adoxq %rax, %r12 + # A[0] * B[2] + mulxq (%rsi), %rcx, %rax + adoxq %r15, %r13 + xorq %r14, %r14 + adcxq %rcx, %r10 + # A[1] * B[1] + movq 8(%rbx), %rdx + mulxq 8(%rsi), %rdx, %rcx + adcxq %rax, %r11 + adoxq %rdx, %r10 + # A[3] * B[1] + movq 8(%rbx), %rdx + adoxq %rcx, %r11 + mulxq 24(%rsi), %rcx, %rax + adcxq %rcx, %r12 + # A[2] * B[2] + movq 16(%rbx), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rax, %r13 + adoxq %rdx, %r12 + # A[3] * B[3] + movq 24(%rbx), %rdx + adoxq %rcx, %r13 + mulxq 24(%rsi), %rcx, %rax + adoxq %r15, %r14 + adcxq %rcx, %r14 + # A[0] * B[3] + mulxq (%rsi), %rdx, %rcx + adcxq %rax, %r15 + xorq %rax, %rax + adcxq %rdx, %r11 + # A[3] * B[0] + movq (%rbx), %rdx + adcxq %rcx, %r12 + mulxq 24(%rsi), %rdx, %rcx + adoxq %rdx, %r11 + adoxq %rcx, %r12 + # A[2] * B[3] + movq 24(%rbx), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rdx, %r13 + # A[3] * B[2] + movq 16(%rbx), %rdx + adcxq %rcx, %r14 + mulxq 24(%rsi), %rcx, %rdx + adcxq %rax, %r15 + adoxq %rcx, %r13 + adoxq %rdx, %r14 + adoxq %rax, %r15 + # Reduce + movq $0x7fffffffffffffff, %rax + # Move top half into t4-t7 and remove top bit from t3 + shldq $0x01, %r14, %r15 + shldq $0x01, %r13, %r14 + shldq $0x01, %r12, %r13 + shldq $0x01, %r11, %r12 + andq %rax, %r11 + # Multiply top half by 19 + movq $19, %rdx + xorq %rax, %rax + mulxq %r12, %rcx, %r12 + adcxq %rcx, %r8 + adoxq %r12, %r9 + mulxq %r13, %rcx, %r13 + adcxq %rcx, %r9 + adoxq %r13, %r10 + mulxq %r14, %rcx, %r14 + adcxq %rcx, %r10 + adoxq %r14, %r11 + mulxq %r15, %r15, %rdx + adcxq %r15, %r11 + adoxq %rax, %rdx + adcxq %rax, %rdx + # Overflow + shldq $0x01, %r11, %rdx + movq $0x7fffffffffffffff, %rax + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Reduce if top bit set + movq %r11, %rdx + shrq $63, %rdx + imulq $19, %rdx, %rcx + andq %rax, %r11 + addq %rcx, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + adcq $0x00, %r11 + # Store + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + leaq 48(%rsp), %rsi + # Double + movq (%rdi), %r8 + movq 8(%rdi), %r9 + addq %r8, %r8 + movq 16(%rdi), %r10 + adcq %r9, %r9 + movq 24(%rdi), %rdx + adcq %r10, %r10 + movq $-19, %rcx + adcq %rdx, %rdx + movq $0x7fffffffffffffff, %rax + movq %rdx, %r11 + sarq $63, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Sub modulus (if overflow) + subq %rcx, %r8 + sbbq %rdx, %r9 + sbbq %rdx, %r10 + sbbq %rax, %r11 + movq %r8, (%rsi) + movq %r9, 8(%rsi) + movq %r10, 16(%rsi) + movq %r11, 24(%rsi) + movq 8(%rsp), %rbx + movq 16(%rsp), %rbp + # Add + movq (%rbp), %r8 + movq 8(%rbp), %r9 + movq 16(%rbp), %r10 + movq 24(%rbp), %rdx + movq %r8, %r12 + addq (%rbx), %r8 + movq %r9, %r13 + adcq 8(%rbx), %r9 + movq %r10, %r14 + adcq 16(%rbx), %r10 + movq %rdx, %r15 + adcq 24(%rbx), %rdx + movq $-19, %rcx + movq %rdx, %r11 + movq $0x7fffffffffffffff, %rax + sarq $63, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Sub modulus (if overflow) + subq %rcx, %r8 + sbbq %rdx, %r9 + sbbq %rdx, %r10 + sbbq %rax, %r11 + # Sub + subq (%rbx), %r12 + movq $0x00, %rdx + sbbq 8(%rbx), %r13 + movq $-19, %rcx + sbbq 16(%rbx), %r14 + movq $0x7fffffffffffffff, %rax + sbbq 24(%rbx), %r15 + sbbq $0x00, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Add modulus (if underflow) + addq %rcx, %r12 + adcq %rdx, %r13 + adcq %rdx, %r14 + adcq %rax, %r15 + movq %r8, (%rbx) + movq %r9, 8(%rbx) + movq %r10, 16(%rbx) + movq %r11, 24(%rbx) + movq %r12, (%rdi) + movq %r13, 8(%rdi) + movq %r14, 16(%rdi) + movq %r15, 24(%rdi) + movq 24(%rsp), %rdi + # Add + movq (%rsi), %r8 + movq 8(%rsi), %r9 + movq 16(%rsi), %r10 + movq 24(%rsi), %rdx + movq %r8, %r12 + addq (%rdi), %r8 + movq %r9, %r13 + adcq 8(%rdi), %r9 + movq %r10, %r14 + adcq 16(%rdi), %r10 + movq %rdx, %r15 + adcq 24(%rdi), %rdx + movq $-19, %rcx + movq %rdx, %r11 + movq $0x7fffffffffffffff, %rax + sarq $63, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Sub modulus (if overflow) + subq %rcx, %r8 + sbbq %rdx, %r9 + sbbq %rdx, %r10 + sbbq %rax, %r11 + # Sub + subq (%rdi), %r12 + movq $0x00, %rdx + sbbq 8(%rdi), %r13 + movq $-19, %rcx + sbbq 16(%rdi), %r14 + movq $0x7fffffffffffffff, %rax + sbbq 24(%rdi), %r15 + sbbq $0x00, %rdx + # Mask the modulus + andq %rdx, %rcx + andq %rdx, %rax + # Add modulus (if underflow) + addq %rcx, %r12 + adcq %rdx, %r13 + adcq %rdx, %r14 + adcq %rax, %r15 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq %r12, (%rbp) + movq %r13, 8(%rbp) + movq %r14, 16(%rbp) + movq %r15, 24(%rbp) + addq $0x50, %rsp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbp + popq %rbx + repz retq +#ifndef __APPLE__ +.size fe_ge_sub_avx2,.-fe_ge_sub_avx2 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_mont_small.i b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_mont_small.i new file mode 100755 index 0000000..626d4e3 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_mont_small.i @@ -0,0 +1,3874 @@ +/* fp_mont_small.i + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifdef TFM_SMALL_MONT_SET +/* computes x/R == x (mod N) via Montgomery Reduction */ +int fp_montgomery_reduce_small(fp_int *a, fp_int *m, fp_digit mp) +{ +#ifndef WOLFSSL_SMALL_STACK + fp_digit c[FP_SIZE]; +#else + fp_digit *c; +#endif + fp_digit *_c, *tmpm, mu, cy; + int oldused, x, y, pa; + +#ifdef WOLFSSL_SMALL_STACK + /* only allocate space for what's needed for window plus res */ + c = (fp_digit*)XMALLOC(sizeof(fp_digit)*FP_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (c == NULL) { + return FP_MEM; + } +#endif + + /* now zero the buff */ + XMEMSET(c, 0, sizeof(fp_digit)*(FP_SIZE)); + + pa = m->used; + + /* copy the input */ + oldused = a->used; + for (x = 0; x < oldused; x++) { + c[x] = a->dp[x]; + } + + MONT_START; + + switch (pa) { + case 1: + x = 0; cy = 0; + LOOP_START; + _c = c + 0; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL; ++_c; +#else + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + break; + case 2: + x = 0; cy = 0; + LOOP_START; + _c = c + 0; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 1; cy = 0; + LOOP_START; + _c = c + 1; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + break; + case 3: + x = 0; cy = 0; + LOOP_START; + _c = c + 0; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 1; cy = 0; + LOOP_START; + _c = c + 1; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 2; cy = 0; + LOOP_START; + _c = c + 2; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + break; + case 4: + x = 0; cy = 0; + LOOP_START; + _c = c + 0; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 1; cy = 0; + LOOP_START; + _c = c + 1; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 2; cy = 0; + LOOP_START; + _c = c + 2; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 3; cy = 0; + LOOP_START; + _c = c + 3; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + break; + case 5: + x = 0; cy = 0; + LOOP_START; + _c = c + 0; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 1; cy = 0; + LOOP_START; + _c = c + 1; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 2; cy = 0; + LOOP_START; + _c = c + 2; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 3; cy = 0; + LOOP_START; + _c = c + 3; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 4; cy = 0; + LOOP_START; + _c = c + 4; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + break; + case 6: + x = 0; cy = 0; + LOOP_START; + _c = c + 0; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 1; cy = 0; + LOOP_START; + _c = c + 1; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 2; cy = 0; + LOOP_START; + _c = c + 2; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 3; cy = 0; + LOOP_START; + _c = c + 3; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 4; cy = 0; + LOOP_START; + _c = c + 4; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 5; cy = 0; + LOOP_START; + _c = c + 5; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + break; + case 7: + x = 0; cy = 0; + LOOP_START; + _c = c + 0; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 1; cy = 0; + LOOP_START; + _c = c + 1; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 2; cy = 0; + LOOP_START; + _c = c + 2; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 3; cy = 0; + LOOP_START; + _c = c + 3; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 4; cy = 0; + LOOP_START; + _c = c + 4; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 5; cy = 0; + LOOP_START; + _c = c + 5; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 6; cy = 0; + LOOP_START; + _c = c + 6; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + break; + case 8: + x = 0; cy = 0; + LOOP_START; + _c = c + 0; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 1; cy = 0; + LOOP_START; + _c = c + 1; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 2; cy = 0; + LOOP_START; + _c = c + 2; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 3; cy = 0; + LOOP_START; + _c = c + 3; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 4; cy = 0; + LOOP_START; + _c = c + 4; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 5; cy = 0; + LOOP_START; + _c = c + 5; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 6; cy = 0; + LOOP_START; + _c = c + 6; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 7; cy = 0; + LOOP_START; + _c = c + 7; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + break; + case 9: + x = 0; cy = 0; + LOOP_START; + _c = c + 0; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 1; cy = 0; + LOOP_START; + _c = c + 1; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 2; cy = 0; + LOOP_START; + _c = c + 2; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 3; cy = 0; + LOOP_START; + _c = c + 3; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 4; cy = 0; + LOOP_START; + _c = c + 4; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 5; cy = 0; + LOOP_START; + _c = c + 5; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 6; cy = 0; + LOOP_START; + _c = c + 6; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 7; cy = 0; + LOOP_START; + _c = c + 7; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 8; cy = 0; + LOOP_START; + _c = c + 8; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + break; + case 10: + x = 0; cy = 0; + LOOP_START; + _c = c + 0; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 1; cy = 0; + LOOP_START; + _c = c + 1; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 2; cy = 0; + LOOP_START; + _c = c + 2; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 3; cy = 0; + LOOP_START; + _c = c + 3; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 4; cy = 0; + LOOP_START; + _c = c + 4; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 5; cy = 0; + LOOP_START; + _c = c + 5; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 6; cy = 0; + LOOP_START; + _c = c + 6; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 7; cy = 0; + LOOP_START; + _c = c + 7; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 8; cy = 0; + LOOP_START; + _c = c + 8; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 9; cy = 0; + LOOP_START; + _c = c + 9; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + break; + case 11: + x = 0; cy = 0; + LOOP_START; + _c = c + 0; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 1; cy = 0; + LOOP_START; + _c = c + 1; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 2; cy = 0; + LOOP_START; + _c = c + 2; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 3; cy = 0; + LOOP_START; + _c = c + 3; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 4; cy = 0; + LOOP_START; + _c = c + 4; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 5; cy = 0; + LOOP_START; + _c = c + 5; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 6; cy = 0; + LOOP_START; + _c = c + 6; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 7; cy = 0; + LOOP_START; + _c = c + 7; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 8; cy = 0; + LOOP_START; + _c = c + 8; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 9; cy = 0; + LOOP_START; + _c = c + 9; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 10; cy = 0; + LOOP_START; + _c = c + 10; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + break; + case 12: + x = 0; cy = 0; + LOOP_START; + _c = c + 0; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 1; cy = 0; + LOOP_START; + _c = c + 1; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 2; cy = 0; + LOOP_START; + _c = c + 2; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 3; cy = 0; + LOOP_START; + _c = c + 3; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 4; cy = 0; + LOOP_START; + _c = c + 4; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 5; cy = 0; + LOOP_START; + _c = c + 5; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 6; cy = 0; + LOOP_START; + _c = c + 6; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 7; cy = 0; + LOOP_START; + _c = c + 7; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 8; cy = 0; + LOOP_START; + _c = c + 8; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 9; cy = 0; + LOOP_START; + _c = c + 9; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 10; cy = 0; + LOOP_START; + _c = c + 10; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 11; cy = 0; + LOOP_START; + _c = c + 11; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + break; + case 13: + x = 0; cy = 0; + LOOP_START; + _c = c + 0; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 1; cy = 0; + LOOP_START; + _c = c + 1; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 2; cy = 0; + LOOP_START; + _c = c + 2; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 3; cy = 0; + LOOP_START; + _c = c + 3; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 4; cy = 0; + LOOP_START; + _c = c + 4; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 5; cy = 0; + LOOP_START; + _c = c + 5; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 6; cy = 0; + LOOP_START; + _c = c + 6; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 7; cy = 0; + LOOP_START; + _c = c + 7; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 8; cy = 0; + LOOP_START; + _c = c + 8; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 9; cy = 0; + LOOP_START; + _c = c + 9; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 10; cy = 0; + LOOP_START; + _c = c + 10; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 11; cy = 0; + LOOP_START; + _c = c + 11; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 12; cy = 0; + LOOP_START; + _c = c + 12; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + break; + case 14: + x = 0; cy = 0; + LOOP_START; + _c = c + 0; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 1; cy = 0; + LOOP_START; + _c = c + 1; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 2; cy = 0; + LOOP_START; + _c = c + 2; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 3; cy = 0; + LOOP_START; + _c = c + 3; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 4; cy = 0; + LOOP_START; + _c = c + 4; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 5; cy = 0; + LOOP_START; + _c = c + 5; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 6; cy = 0; + LOOP_START; + _c = c + 6; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 7; cy = 0; + LOOP_START; + _c = c + 7; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 8; cy = 0; + LOOP_START; + _c = c + 8; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 9; cy = 0; + LOOP_START; + _c = c + 9; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 10; cy = 0; + LOOP_START; + _c = c + 10; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 11; cy = 0; + LOOP_START; + _c = c + 11; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 12; cy = 0; + LOOP_START; + _c = c + 12; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 13; cy = 0; + LOOP_START; + _c = c + 13; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + break; + case 15: + x = 0; cy = 0; + LOOP_START; + _c = c + 0; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 1; cy = 0; + LOOP_START; + _c = c + 1; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 2; cy = 0; + LOOP_START; + _c = c + 2; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 3; cy = 0; + LOOP_START; + _c = c + 3; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 4; cy = 0; + LOOP_START; + _c = c + 4; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 5; cy = 0; + LOOP_START; + _c = c + 5; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 6; cy = 0; + LOOP_START; + _c = c + 6; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 7; cy = 0; + LOOP_START; + _c = c + 7; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 8; cy = 0; + LOOP_START; + _c = c + 8; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 9; cy = 0; + LOOP_START; + _c = c + 9; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 10; cy = 0; + LOOP_START; + _c = c + 10; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 11; cy = 0; + LOOP_START; + _c = c + 11; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 12; cy = 0; + LOOP_START; + _c = c + 12; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 13; cy = 0; + LOOP_START; + _c = c + 13; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 14; cy = 0; + LOOP_START; + _c = c + 14; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + break; + case 16: + x = 0; cy = 0; + LOOP_START; + _c = c + 0; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL8; _c += 8; tmpm += 8; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 1; cy = 0; + LOOP_START; + _c = c + 1; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL8; _c += 8; tmpm += 8; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 2; cy = 0; + LOOP_START; + _c = c + 2; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL8; _c += 8; tmpm += 8; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 3; cy = 0; + LOOP_START; + _c = c + 3; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL8; _c += 8; tmpm += 8; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 4; cy = 0; + LOOP_START; + _c = c + 4; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL8; _c += 8; tmpm += 8; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 5; cy = 0; + LOOP_START; + _c = c + 5; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL8; _c += 8; tmpm += 8; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 6; cy = 0; + LOOP_START; + _c = c + 6; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL8; _c += 8; tmpm += 8; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 7; cy = 0; + LOOP_START; + _c = c + 7; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL8; _c += 8; tmpm += 8; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 8; cy = 0; + LOOP_START; + _c = c + 8; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL8; _c += 8; tmpm += 8; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 9; cy = 0; + LOOP_START; + _c = c + 9; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL8; _c += 8; tmpm += 8; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 10; cy = 0; + LOOP_START; + _c = c + 10; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL8; _c += 8; tmpm += 8; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 11; cy = 0; + LOOP_START; + _c = c + 11; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL8; _c += 8; tmpm += 8; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 12; cy = 0; + LOOP_START; + _c = c + 12; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL8; _c += 8; tmpm += 8; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 13; cy = 0; + LOOP_START; + _c = c + 13; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL8; _c += 8; tmpm += 8; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 14; cy = 0; + LOOP_START; + _c = c + 14; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL8; _c += 8; tmpm += 8; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + x = 15; cy = 0; + LOOP_START; + _c = c + 15; + tmpm = m->dp; +#ifdef INNERMUL8 + INNERMUL8; _c += 8; tmpm += 8; + INNERMUL8; _c += 8; tmpm += 8; +#else + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; + INNERMUL; ++_c; +#endif + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + break; + } + /* now copy out */ + _c = c + pa; + tmpm = a->dp; + for (x = 0; x < pa+1; x++) { + *tmpm++ = *_c++; + } + + for (; x < oldused; x++) { + *tmpm++ = 0; + } + + MONT_FINI; + + a->used = pa+1; + fp_clamp(a); + + /* if A >= m then A = A - m */ + if (fp_cmp_mag (a, m) != FP_LT) { + s_fp_sub (a, m, a); + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(c, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; +} + +#endif diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_mul_comba_12.i b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_mul_comba_12.i new file mode 100755 index 0000000..603e496 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_mul_comba_12.i @@ -0,0 +1,147 @@ +/* fp_mul_comba_12.i + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifdef TFM_MUL12 +int fp_mul_comba12(fp_int *A, fp_int *B, fp_int *C) +{ + fp_digit c0, c1, c2; +#ifndef WOLFSSL_SMALL_STACK + fp_digit at[24]; +#else + fp_digit *at; +#endif + +#ifdef WOLFSSL_SMALL_STACK + at = (fp_digit*)XMALLOC(sizeof(fp_digit) * 24, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (at == NULL) + return FP_MEM; +#endif + + XMEMCPY(at, A->dp, 12 * sizeof(fp_digit)); + XMEMCPY(at+12, B->dp, 12 * sizeof(fp_digit)); + COMBA_START; + + COMBA_CLEAR; + /* 0 */ + MULADD(at[0], at[12]); + COMBA_STORE(C->dp[0]); + /* 1 */ + COMBA_FORWARD; + MULADD(at[0], at[13]); MULADD(at[1], at[12]); + COMBA_STORE(C->dp[1]); + /* 2 */ + COMBA_FORWARD; + MULADD(at[0], at[14]); MULADD(at[1], at[13]); MULADD(at[2], at[12]); + COMBA_STORE(C->dp[2]); + /* 3 */ + COMBA_FORWARD; + MULADD(at[0], at[15]); MULADD(at[1], at[14]); MULADD(at[2], at[13]); MULADD(at[3], at[12]); + COMBA_STORE(C->dp[3]); + /* 4 */ + COMBA_FORWARD; + MULADD(at[0], at[16]); MULADD(at[1], at[15]); MULADD(at[2], at[14]); MULADD(at[3], at[13]); MULADD(at[4], at[12]); + COMBA_STORE(C->dp[4]); + /* 5 */ + COMBA_FORWARD; + MULADD(at[0], at[17]); MULADD(at[1], at[16]); MULADD(at[2], at[15]); MULADD(at[3], at[14]); MULADD(at[4], at[13]); MULADD(at[5], at[12]); + COMBA_STORE(C->dp[5]); + /* 6 */ + COMBA_FORWARD; + MULADD(at[0], at[18]); MULADD(at[1], at[17]); MULADD(at[2], at[16]); MULADD(at[3], at[15]); MULADD(at[4], at[14]); MULADD(at[5], at[13]); MULADD(at[6], at[12]); + COMBA_STORE(C->dp[6]); + /* 7 */ + COMBA_FORWARD; + MULADD(at[0], at[19]); MULADD(at[1], at[18]); MULADD(at[2], at[17]); MULADD(at[3], at[16]); MULADD(at[4], at[15]); MULADD(at[5], at[14]); MULADD(at[6], at[13]); MULADD(at[7], at[12]); + COMBA_STORE(C->dp[7]); + /* 8 */ + COMBA_FORWARD; + MULADD(at[0], at[20]); MULADD(at[1], at[19]); MULADD(at[2], at[18]); MULADD(at[3], at[17]); MULADD(at[4], at[16]); MULADD(at[5], at[15]); MULADD(at[6], at[14]); MULADD(at[7], at[13]); MULADD(at[8], at[12]); + COMBA_STORE(C->dp[8]); + /* 9 */ + COMBA_FORWARD; + MULADD(at[0], at[21]); MULADD(at[1], at[20]); MULADD(at[2], at[19]); MULADD(at[3], at[18]); MULADD(at[4], at[17]); MULADD(at[5], at[16]); MULADD(at[6], at[15]); MULADD(at[7], at[14]); MULADD(at[8], at[13]); MULADD(at[9], at[12]); + COMBA_STORE(C->dp[9]); + /* 10 */ + COMBA_FORWARD; + MULADD(at[0], at[22]); MULADD(at[1], at[21]); MULADD(at[2], at[20]); MULADD(at[3], at[19]); MULADD(at[4], at[18]); MULADD(at[5], at[17]); MULADD(at[6], at[16]); MULADD(at[7], at[15]); MULADD(at[8], at[14]); MULADD(at[9], at[13]); MULADD(at[10], at[12]); + COMBA_STORE(C->dp[10]); + /* 11 */ + COMBA_FORWARD; + MULADD(at[0], at[23]); MULADD(at[1], at[22]); MULADD(at[2], at[21]); MULADD(at[3], at[20]); MULADD(at[4], at[19]); MULADD(at[5], at[18]); MULADD(at[6], at[17]); MULADD(at[7], at[16]); MULADD(at[8], at[15]); MULADD(at[9], at[14]); MULADD(at[10], at[13]); MULADD(at[11], at[12]); + COMBA_STORE(C->dp[11]); + /* 12 */ + COMBA_FORWARD; + MULADD(at[1], at[23]); MULADD(at[2], at[22]); MULADD(at[3], at[21]); MULADD(at[4], at[20]); MULADD(at[5], at[19]); MULADD(at[6], at[18]); MULADD(at[7], at[17]); MULADD(at[8], at[16]); MULADD(at[9], at[15]); MULADD(at[10], at[14]); MULADD(at[11], at[13]); + COMBA_STORE(C->dp[12]); + /* 13 */ + COMBA_FORWARD; + MULADD(at[2], at[23]); MULADD(at[3], at[22]); MULADD(at[4], at[21]); MULADD(at[5], at[20]); MULADD(at[6], at[19]); MULADD(at[7], at[18]); MULADD(at[8], at[17]); MULADD(at[9], at[16]); MULADD(at[10], at[15]); MULADD(at[11], at[14]); + COMBA_STORE(C->dp[13]); + /* 14 */ + COMBA_FORWARD; + MULADD(at[3], at[23]); MULADD(at[4], at[22]); MULADD(at[5], at[21]); MULADD(at[6], at[20]); MULADD(at[7], at[19]); MULADD(at[8], at[18]); MULADD(at[9], at[17]); MULADD(at[10], at[16]); MULADD(at[11], at[15]); + COMBA_STORE(C->dp[14]); + /* 15 */ + COMBA_FORWARD; + MULADD(at[4], at[23]); MULADD(at[5], at[22]); MULADD(at[6], at[21]); MULADD(at[7], at[20]); MULADD(at[8], at[19]); MULADD(at[9], at[18]); MULADD(at[10], at[17]); MULADD(at[11], at[16]); + COMBA_STORE(C->dp[15]); + /* 16 */ + COMBA_FORWARD; + MULADD(at[5], at[23]); MULADD(at[6], at[22]); MULADD(at[7], at[21]); MULADD(at[8], at[20]); MULADD(at[9], at[19]); MULADD(at[10], at[18]); MULADD(at[11], at[17]); + COMBA_STORE(C->dp[16]); + /* 17 */ + COMBA_FORWARD; + MULADD(at[6], at[23]); MULADD(at[7], at[22]); MULADD(at[8], at[21]); MULADD(at[9], at[20]); MULADD(at[10], at[19]); MULADD(at[11], at[18]); + COMBA_STORE(C->dp[17]); + /* 18 */ + COMBA_FORWARD; + MULADD(at[7], at[23]); MULADD(at[8], at[22]); MULADD(at[9], at[21]); MULADD(at[10], at[20]); MULADD(at[11], at[19]); + COMBA_STORE(C->dp[18]); + /* 19 */ + COMBA_FORWARD; + MULADD(at[8], at[23]); MULADD(at[9], at[22]); MULADD(at[10], at[21]); MULADD(at[11], at[20]); + COMBA_STORE(C->dp[19]); + /* 20 */ + COMBA_FORWARD; + MULADD(at[9], at[23]); MULADD(at[10], at[22]); MULADD(at[11], at[21]); + COMBA_STORE(C->dp[20]); + /* 21 */ + COMBA_FORWARD; + MULADD(at[10], at[23]); MULADD(at[11], at[22]); + COMBA_STORE(C->dp[21]); + /* 22 */ + COMBA_FORWARD; + MULADD(at[11], at[23]); + COMBA_STORE(C->dp[22]); + COMBA_STORE2(C->dp[23]); + C->used = 24; + C->sign = A->sign ^ B->sign; + fp_clamp(C); + COMBA_FINI; + +#ifdef WOLFSSL_SMALL_STACK + XFREE(at, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; +} +#endif diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_mul_comba_17.i b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_mul_comba_17.i new file mode 100755 index 0000000..83489fa --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_mul_comba_17.i @@ -0,0 +1,187 @@ +/* fp_mul_comba_17.i + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifdef TFM_MUL17 +int fp_mul_comba17(fp_int *A, fp_int *B, fp_int *C) +{ + fp_digit c0, c1, c2; +#ifndef WOLFSSL_SMALL_STACK + fp_digit at[34]; +#else + fp_digit *at; +#endif + +#ifdef WOLFSSL_SMALL_STACK + at = (fp_digit*)XMALLOC(sizeof(fp_digit) * 34, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (at == NULL) + return FP_MEM; +#endif + + XMEMCPY(at, A->dp, 17 * sizeof(fp_digit)); + XMEMCPY(at+17, B->dp, 17 * sizeof(fp_digit)); + COMBA_START; + + COMBA_CLEAR; + /* 0 */ + MULADD(at[0], at[17]); + COMBA_STORE(C->dp[0]); + /* 1 */ + COMBA_FORWARD; + MULADD(at[0], at[18]); MULADD(at[1], at[17]); + COMBA_STORE(C->dp[1]); + /* 2 */ + COMBA_FORWARD; + MULADD(at[0], at[19]); MULADD(at[1], at[18]); MULADD(at[2], at[17]); + COMBA_STORE(C->dp[2]); + /* 3 */ + COMBA_FORWARD; + MULADD(at[0], at[20]); MULADD(at[1], at[19]); MULADD(at[2], at[18]); MULADD(at[3], at[17]); + COMBA_STORE(C->dp[3]); + /* 4 */ + COMBA_FORWARD; + MULADD(at[0], at[21]); MULADD(at[1], at[20]); MULADD(at[2], at[19]); MULADD(at[3], at[18]); MULADD(at[4], at[17]); + COMBA_STORE(C->dp[4]); + /* 5 */ + COMBA_FORWARD; + MULADD(at[0], at[22]); MULADD(at[1], at[21]); MULADD(at[2], at[20]); MULADD(at[3], at[19]); MULADD(at[4], at[18]); MULADD(at[5], at[17]); + COMBA_STORE(C->dp[5]); + /* 6 */ + COMBA_FORWARD; + MULADD(at[0], at[23]); MULADD(at[1], at[22]); MULADD(at[2], at[21]); MULADD(at[3], at[20]); MULADD(at[4], at[19]); MULADD(at[5], at[18]); MULADD(at[6], at[17]); + COMBA_STORE(C->dp[6]); + /* 7 */ + COMBA_FORWARD; + MULADD(at[0], at[24]); MULADD(at[1], at[23]); MULADD(at[2], at[22]); MULADD(at[3], at[21]); MULADD(at[4], at[20]); MULADD(at[5], at[19]); MULADD(at[6], at[18]); MULADD(at[7], at[17]); + COMBA_STORE(C->dp[7]); + /* 8 */ + COMBA_FORWARD; + MULADD(at[0], at[25]); MULADD(at[1], at[24]); MULADD(at[2], at[23]); MULADD(at[3], at[22]); MULADD(at[4], at[21]); MULADD(at[5], at[20]); MULADD(at[6], at[19]); MULADD(at[7], at[18]); MULADD(at[8], at[17]); + COMBA_STORE(C->dp[8]); + /* 9 */ + COMBA_FORWARD; + MULADD(at[0], at[26]); MULADD(at[1], at[25]); MULADD(at[2], at[24]); MULADD(at[3], at[23]); MULADD(at[4], at[22]); MULADD(at[5], at[21]); MULADD(at[6], at[20]); MULADD(at[7], at[19]); MULADD(at[8], at[18]); MULADD(at[9], at[17]); + COMBA_STORE(C->dp[9]); + /* 10 */ + COMBA_FORWARD; + MULADD(at[0], at[27]); MULADD(at[1], at[26]); MULADD(at[2], at[25]); MULADD(at[3], at[24]); MULADD(at[4], at[23]); MULADD(at[5], at[22]); MULADD(at[6], at[21]); MULADD(at[7], at[20]); MULADD(at[8], at[19]); MULADD(at[9], at[18]); MULADD(at[10], at[17]); + COMBA_STORE(C->dp[10]); + /* 11 */ + COMBA_FORWARD; + MULADD(at[0], at[28]); MULADD(at[1], at[27]); MULADD(at[2], at[26]); MULADD(at[3], at[25]); MULADD(at[4], at[24]); MULADD(at[5], at[23]); MULADD(at[6], at[22]); MULADD(at[7], at[21]); MULADD(at[8], at[20]); MULADD(at[9], at[19]); MULADD(at[10], at[18]); MULADD(at[11], at[17]); + COMBA_STORE(C->dp[11]); + /* 12 */ + COMBA_FORWARD; + MULADD(at[0], at[29]); MULADD(at[1], at[28]); MULADD(at[2], at[27]); MULADD(at[3], at[26]); MULADD(at[4], at[25]); MULADD(at[5], at[24]); MULADD(at[6], at[23]); MULADD(at[7], at[22]); MULADD(at[8], at[21]); MULADD(at[9], at[20]); MULADD(at[10], at[19]); MULADD(at[11], at[18]); MULADD(at[12], at[17]); + COMBA_STORE(C->dp[12]); + /* 13 */ + COMBA_FORWARD; + MULADD(at[0], at[30]); MULADD(at[1], at[29]); MULADD(at[2], at[28]); MULADD(at[3], at[27]); MULADD(at[4], at[26]); MULADD(at[5], at[25]); MULADD(at[6], at[24]); MULADD(at[7], at[23]); MULADD(at[8], at[22]); MULADD(at[9], at[21]); MULADD(at[10], at[20]); MULADD(at[11], at[19]); MULADD(at[12], at[18]); MULADD(at[13], at[17]); + COMBA_STORE(C->dp[13]); + /* 14 */ + COMBA_FORWARD; + MULADD(at[0], at[31]); MULADD(at[1], at[30]); MULADD(at[2], at[29]); MULADD(at[3], at[28]); MULADD(at[4], at[27]); MULADD(at[5], at[26]); MULADD(at[6], at[25]); MULADD(at[7], at[24]); MULADD(at[8], at[23]); MULADD(at[9], at[22]); MULADD(at[10], at[21]); MULADD(at[11], at[20]); MULADD(at[12], at[19]); MULADD(at[13], at[18]); MULADD(at[14], at[17]); + COMBA_STORE(C->dp[14]); + /* 15 */ + COMBA_FORWARD; + MULADD(at[0], at[32]); MULADD(at[1], at[31]); MULADD(at[2], at[30]); MULADD(at[3], at[29]); MULADD(at[4], at[28]); MULADD(at[5], at[27]); MULADD(at[6], at[26]); MULADD(at[7], at[25]); MULADD(at[8], at[24]); MULADD(at[9], at[23]); MULADD(at[10], at[22]); MULADD(at[11], at[21]); MULADD(at[12], at[20]); MULADD(at[13], at[19]); MULADD(at[14], at[18]); MULADD(at[15], at[17]); + COMBA_STORE(C->dp[15]); + /* 16 */ + COMBA_FORWARD; + MULADD(at[0], at[33]); MULADD(at[1], at[32]); MULADD(at[2], at[31]); MULADD(at[3], at[30]); MULADD(at[4], at[29]); MULADD(at[5], at[28]); MULADD(at[6], at[27]); MULADD(at[7], at[26]); MULADD(at[8], at[25]); MULADD(at[9], at[24]); MULADD(at[10], at[23]); MULADD(at[11], at[22]); MULADD(at[12], at[21]); MULADD(at[13], at[20]); MULADD(at[14], at[19]); MULADD(at[15], at[18]); MULADD(at[16], at[17]); + COMBA_STORE(C->dp[16]); + /* 17 */ + COMBA_FORWARD; + MULADD(at[1], at[33]); MULADD(at[2], at[32]); MULADD(at[3], at[31]); MULADD(at[4], at[30]); MULADD(at[5], at[29]); MULADD(at[6], at[28]); MULADD(at[7], at[27]); MULADD(at[8], at[26]); MULADD(at[9], at[25]); MULADD(at[10], at[24]); MULADD(at[11], at[23]); MULADD(at[12], at[22]); MULADD(at[13], at[21]); MULADD(at[14], at[20]); MULADD(at[15], at[19]); MULADD(at[16], at[18]); + COMBA_STORE(C->dp[17]); + /* 18 */ + COMBA_FORWARD; + MULADD(at[2], at[33]); MULADD(at[3], at[32]); MULADD(at[4], at[31]); MULADD(at[5], at[30]); MULADD(at[6], at[29]); MULADD(at[7], at[28]); MULADD(at[8], at[27]); MULADD(at[9], at[26]); MULADD(at[10], at[25]); MULADD(at[11], at[24]); MULADD(at[12], at[23]); MULADD(at[13], at[22]); MULADD(at[14], at[21]); MULADD(at[15], at[20]); MULADD(at[16], at[19]); + COMBA_STORE(C->dp[18]); + /* 19 */ + COMBA_FORWARD; + MULADD(at[3], at[33]); MULADD(at[4], at[32]); MULADD(at[5], at[31]); MULADD(at[6], at[30]); MULADD(at[7], at[29]); MULADD(at[8], at[28]); MULADD(at[9], at[27]); MULADD(at[10], at[26]); MULADD(at[11], at[25]); MULADD(at[12], at[24]); MULADD(at[13], at[23]); MULADD(at[14], at[22]); MULADD(at[15], at[21]); MULADD(at[16], at[20]); + COMBA_STORE(C->dp[19]); + /* 20 */ + COMBA_FORWARD; + MULADD(at[4], at[33]); MULADD(at[5], at[32]); MULADD(at[6], at[31]); MULADD(at[7], at[30]); MULADD(at[8], at[29]); MULADD(at[9], at[28]); MULADD(at[10], at[27]); MULADD(at[11], at[26]); MULADD(at[12], at[25]); MULADD(at[13], at[24]); MULADD(at[14], at[23]); MULADD(at[15], at[22]); MULADD(at[16], at[21]); + COMBA_STORE(C->dp[20]); + /* 21 */ + COMBA_FORWARD; + MULADD(at[5], at[33]); MULADD(at[6], at[32]); MULADD(at[7], at[31]); MULADD(at[8], at[30]); MULADD(at[9], at[29]); MULADD(at[10], at[28]); MULADD(at[11], at[27]); MULADD(at[12], at[26]); MULADD(at[13], at[25]); MULADD(at[14], at[24]); MULADD(at[15], at[23]); MULADD(at[16], at[22]); + COMBA_STORE(C->dp[21]); + /* 22 */ + COMBA_FORWARD; + MULADD(at[6], at[33]); MULADD(at[7], at[32]); MULADD(at[8], at[31]); MULADD(at[9], at[30]); MULADD(at[10], at[29]); MULADD(at[11], at[28]); MULADD(at[12], at[27]); MULADD(at[13], at[26]); MULADD(at[14], at[25]); MULADD(at[15], at[24]); MULADD(at[16], at[23]); + COMBA_STORE(C->dp[22]); + /* 23 */ + COMBA_FORWARD; + MULADD(at[7], at[33]); MULADD(at[8], at[32]); MULADD(at[9], at[31]); MULADD(at[10], at[30]); MULADD(at[11], at[29]); MULADD(at[12], at[28]); MULADD(at[13], at[27]); MULADD(at[14], at[26]); MULADD(at[15], at[25]); MULADD(at[16], at[24]); + COMBA_STORE(C->dp[23]); + /* 24 */ + COMBA_FORWARD; + MULADD(at[8], at[33]); MULADD(at[9], at[32]); MULADD(at[10], at[31]); MULADD(at[11], at[30]); MULADD(at[12], at[29]); MULADD(at[13], at[28]); MULADD(at[14], at[27]); MULADD(at[15], at[26]); MULADD(at[16], at[25]); + COMBA_STORE(C->dp[24]); + /* 25 */ + COMBA_FORWARD; + MULADD(at[9], at[33]); MULADD(at[10], at[32]); MULADD(at[11], at[31]); MULADD(at[12], at[30]); MULADD(at[13], at[29]); MULADD(at[14], at[28]); MULADD(at[15], at[27]); MULADD(at[16], at[26]); + COMBA_STORE(C->dp[25]); + /* 26 */ + COMBA_FORWARD; + MULADD(at[10], at[33]); MULADD(at[11], at[32]); MULADD(at[12], at[31]); MULADD(at[13], at[30]); MULADD(at[14], at[29]); MULADD(at[15], at[28]); MULADD(at[16], at[27]); + COMBA_STORE(C->dp[26]); + /* 27 */ + COMBA_FORWARD; + MULADD(at[11], at[33]); MULADD(at[12], at[32]); MULADD(at[13], at[31]); MULADD(at[14], at[30]); MULADD(at[15], at[29]); MULADD(at[16], at[28]); + COMBA_STORE(C->dp[27]); + /* 28 */ + COMBA_FORWARD; + MULADD(at[12], at[33]); MULADD(at[13], at[32]); MULADD(at[14], at[31]); MULADD(at[15], at[30]); MULADD(at[16], at[29]); + COMBA_STORE(C->dp[28]); + /* 29 */ + COMBA_FORWARD; + MULADD(at[13], at[33]); MULADD(at[14], at[32]); MULADD(at[15], at[31]); MULADD(at[16], at[30]); + COMBA_STORE(C->dp[29]); + /* 30 */ + COMBA_FORWARD; + MULADD(at[14], at[33]); MULADD(at[15], at[32]); MULADD(at[16], at[31]); + COMBA_STORE(C->dp[30]); + /* 31 */ + COMBA_FORWARD; + MULADD(at[15], at[33]); MULADD(at[16], at[32]); + COMBA_STORE(C->dp[31]); + /* 32 */ + COMBA_FORWARD; + MULADD(at[16], at[33]); + COMBA_STORE(C->dp[32]); + COMBA_STORE2(C->dp[33]); + C->used = 34; + C->sign = A->sign ^ B->sign; + fp_clamp(C); + COMBA_FINI; + +#ifdef WOLFSSL_SMALL_STACK + XFREE(at, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; +} +#endif diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_mul_comba_20.i b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_mul_comba_20.i new file mode 100755 index 0000000..9d0b6de --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_mul_comba_20.i @@ -0,0 +1,210 @@ +/* fp_mul_comba_20.i + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifdef TFM_MUL20 +int fp_mul_comba20(fp_int *A, fp_int *B, fp_int *C) +{ + fp_digit c0, c1, c2; +#ifndef WOLFSSL_SMALL_STACK + fp_digit at[40]; +#else + fp_digit *at; +#endif + +#ifdef WOLFSSL_SMALL_STACK + at = (fp_digit*)XMALLOC(sizeof(fp_digit) * 40, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (at == NULL) + return FP_MEM; +#endif + + XMEMCPY(at, A->dp, 20 * sizeof(fp_digit)); + XMEMCPY(at+20, B->dp, 20 * sizeof(fp_digit)); + COMBA_START; + + COMBA_CLEAR; + /* 0 */ + MULADD(at[0], at[20]); + COMBA_STORE(C->dp[0]); + /* 1 */ + COMBA_FORWARD; + MULADD(at[0], at[21]); MULADD(at[1], at[20]); + COMBA_STORE(C->dp[1]); + /* 2 */ + COMBA_FORWARD; + MULADD(at[0], at[22]); MULADD(at[1], at[21]); MULADD(at[2], at[20]); + COMBA_STORE(C->dp[2]); + /* 3 */ + COMBA_FORWARD; + MULADD(at[0], at[23]); MULADD(at[1], at[22]); MULADD(at[2], at[21]); MULADD(at[3], at[20]); + COMBA_STORE(C->dp[3]); + /* 4 */ + COMBA_FORWARD; + MULADD(at[0], at[24]); MULADD(at[1], at[23]); MULADD(at[2], at[22]); MULADD(at[3], at[21]); MULADD(at[4], at[20]); + COMBA_STORE(C->dp[4]); + /* 5 */ + COMBA_FORWARD; + MULADD(at[0], at[25]); MULADD(at[1], at[24]); MULADD(at[2], at[23]); MULADD(at[3], at[22]); MULADD(at[4], at[21]); MULADD(at[5], at[20]); + COMBA_STORE(C->dp[5]); + /* 6 */ + COMBA_FORWARD; + MULADD(at[0], at[26]); MULADD(at[1], at[25]); MULADD(at[2], at[24]); MULADD(at[3], at[23]); MULADD(at[4], at[22]); MULADD(at[5], at[21]); MULADD(at[6], at[20]); + COMBA_STORE(C->dp[6]); + /* 7 */ + COMBA_FORWARD; + MULADD(at[0], at[27]); MULADD(at[1], at[26]); MULADD(at[2], at[25]); MULADD(at[3], at[24]); MULADD(at[4], at[23]); MULADD(at[5], at[22]); MULADD(at[6], at[21]); MULADD(at[7], at[20]); + COMBA_STORE(C->dp[7]); + /* 8 */ + COMBA_FORWARD; + MULADD(at[0], at[28]); MULADD(at[1], at[27]); MULADD(at[2], at[26]); MULADD(at[3], at[25]); MULADD(at[4], at[24]); MULADD(at[5], at[23]); MULADD(at[6], at[22]); MULADD(at[7], at[21]); MULADD(at[8], at[20]); + COMBA_STORE(C->dp[8]); + /* 9 */ + COMBA_FORWARD; + MULADD(at[0], at[29]); MULADD(at[1], at[28]); MULADD(at[2], at[27]); MULADD(at[3], at[26]); MULADD(at[4], at[25]); MULADD(at[5], at[24]); MULADD(at[6], at[23]); MULADD(at[7], at[22]); MULADD(at[8], at[21]); MULADD(at[9], at[20]); + COMBA_STORE(C->dp[9]); + /* 10 */ + COMBA_FORWARD; + MULADD(at[0], at[30]); MULADD(at[1], at[29]); MULADD(at[2], at[28]); MULADD(at[3], at[27]); MULADD(at[4], at[26]); MULADD(at[5], at[25]); MULADD(at[6], at[24]); MULADD(at[7], at[23]); MULADD(at[8], at[22]); MULADD(at[9], at[21]); MULADD(at[10], at[20]); + COMBA_STORE(C->dp[10]); + /* 11 */ + COMBA_FORWARD; + MULADD(at[0], at[31]); MULADD(at[1], at[30]); MULADD(at[2], at[29]); MULADD(at[3], at[28]); MULADD(at[4], at[27]); MULADD(at[5], at[26]); MULADD(at[6], at[25]); MULADD(at[7], at[24]); MULADD(at[8], at[23]); MULADD(at[9], at[22]); MULADD(at[10], at[21]); MULADD(at[11], at[20]); + COMBA_STORE(C->dp[11]); + /* 12 */ + COMBA_FORWARD; + MULADD(at[0], at[32]); MULADD(at[1], at[31]); MULADD(at[2], at[30]); MULADD(at[3], at[29]); MULADD(at[4], at[28]); MULADD(at[5], at[27]); MULADD(at[6], at[26]); MULADD(at[7], at[25]); MULADD(at[8], at[24]); MULADD(at[9], at[23]); MULADD(at[10], at[22]); MULADD(at[11], at[21]); MULADD(at[12], at[20]); + COMBA_STORE(C->dp[12]); + /* 13 */ + COMBA_FORWARD; + MULADD(at[0], at[33]); MULADD(at[1], at[32]); MULADD(at[2], at[31]); MULADD(at[3], at[30]); MULADD(at[4], at[29]); MULADD(at[5], at[28]); MULADD(at[6], at[27]); MULADD(at[7], at[26]); MULADD(at[8], at[25]); MULADD(at[9], at[24]); MULADD(at[10], at[23]); MULADD(at[11], at[22]); MULADD(at[12], at[21]); MULADD(at[13], at[20]); + COMBA_STORE(C->dp[13]); + /* 14 */ + COMBA_FORWARD; + MULADD(at[0], at[34]); MULADD(at[1], at[33]); MULADD(at[2], at[32]); MULADD(at[3], at[31]); MULADD(at[4], at[30]); MULADD(at[5], at[29]); MULADD(at[6], at[28]); MULADD(at[7], at[27]); MULADD(at[8], at[26]); MULADD(at[9], at[25]); MULADD(at[10], at[24]); MULADD(at[11], at[23]); MULADD(at[12], at[22]); MULADD(at[13], at[21]); MULADD(at[14], at[20]); + COMBA_STORE(C->dp[14]); + /* 15 */ + COMBA_FORWARD; + MULADD(at[0], at[35]); MULADD(at[1], at[34]); MULADD(at[2], at[33]); MULADD(at[3], at[32]); MULADD(at[4], at[31]); MULADD(at[5], at[30]); MULADD(at[6], at[29]); MULADD(at[7], at[28]); MULADD(at[8], at[27]); MULADD(at[9], at[26]); MULADD(at[10], at[25]); MULADD(at[11], at[24]); MULADD(at[12], at[23]); MULADD(at[13], at[22]); MULADD(at[14], at[21]); MULADD(at[15], at[20]); + COMBA_STORE(C->dp[15]); + /* 16 */ + COMBA_FORWARD; + MULADD(at[0], at[36]); MULADD(at[1], at[35]); MULADD(at[2], at[34]); MULADD(at[3], at[33]); MULADD(at[4], at[32]); MULADD(at[5], at[31]); MULADD(at[6], at[30]); MULADD(at[7], at[29]); MULADD(at[8], at[28]); MULADD(at[9], at[27]); MULADD(at[10], at[26]); MULADD(at[11], at[25]); MULADD(at[12], at[24]); MULADD(at[13], at[23]); MULADD(at[14], at[22]); MULADD(at[15], at[21]); MULADD(at[16], at[20]); + COMBA_STORE(C->dp[16]); + /* 17 */ + COMBA_FORWARD; + MULADD(at[0], at[37]); MULADD(at[1], at[36]); MULADD(at[2], at[35]); MULADD(at[3], at[34]); MULADD(at[4], at[33]); MULADD(at[5], at[32]); MULADD(at[6], at[31]); MULADD(at[7], at[30]); MULADD(at[8], at[29]); MULADD(at[9], at[28]); MULADD(at[10], at[27]); MULADD(at[11], at[26]); MULADD(at[12], at[25]); MULADD(at[13], at[24]); MULADD(at[14], at[23]); MULADD(at[15], at[22]); MULADD(at[16], at[21]); MULADD(at[17], at[20]); + COMBA_STORE(C->dp[17]); + /* 18 */ + COMBA_FORWARD; + MULADD(at[0], at[38]); MULADD(at[1], at[37]); MULADD(at[2], at[36]); MULADD(at[3], at[35]); MULADD(at[4], at[34]); MULADD(at[5], at[33]); MULADD(at[6], at[32]); MULADD(at[7], at[31]); MULADD(at[8], at[30]); MULADD(at[9], at[29]); MULADD(at[10], at[28]); MULADD(at[11], at[27]); MULADD(at[12], at[26]); MULADD(at[13], at[25]); MULADD(at[14], at[24]); MULADD(at[15], at[23]); MULADD(at[16], at[22]); MULADD(at[17], at[21]); MULADD(at[18], at[20]); + COMBA_STORE(C->dp[18]); + /* 19 */ + COMBA_FORWARD; + MULADD(at[0], at[39]); MULADD(at[1], at[38]); MULADD(at[2], at[37]); MULADD(at[3], at[36]); MULADD(at[4], at[35]); MULADD(at[5], at[34]); MULADD(at[6], at[33]); MULADD(at[7], at[32]); MULADD(at[8], at[31]); MULADD(at[9], at[30]); MULADD(at[10], at[29]); MULADD(at[11], at[28]); MULADD(at[12], at[27]); MULADD(at[13], at[26]); MULADD(at[14], at[25]); MULADD(at[15], at[24]); MULADD(at[16], at[23]); MULADD(at[17], at[22]); MULADD(at[18], at[21]); MULADD(at[19], at[20]); + COMBA_STORE(C->dp[19]); + /* 20 */ + COMBA_FORWARD; + MULADD(at[1], at[39]); MULADD(at[2], at[38]); MULADD(at[3], at[37]); MULADD(at[4], at[36]); MULADD(at[5], at[35]); MULADD(at[6], at[34]); MULADD(at[7], at[33]); MULADD(at[8], at[32]); MULADD(at[9], at[31]); MULADD(at[10], at[30]); MULADD(at[11], at[29]); MULADD(at[12], at[28]); MULADD(at[13], at[27]); MULADD(at[14], at[26]); MULADD(at[15], at[25]); MULADD(at[16], at[24]); MULADD(at[17], at[23]); MULADD(at[18], at[22]); MULADD(at[19], at[21]); + COMBA_STORE(C->dp[20]); + /* 21 */ + COMBA_FORWARD; + MULADD(at[2], at[39]); MULADD(at[3], at[38]); MULADD(at[4], at[37]); MULADD(at[5], at[36]); MULADD(at[6], at[35]); MULADD(at[7], at[34]); MULADD(at[8], at[33]); MULADD(at[9], at[32]); MULADD(at[10], at[31]); MULADD(at[11], at[30]); MULADD(at[12], at[29]); MULADD(at[13], at[28]); MULADD(at[14], at[27]); MULADD(at[15], at[26]); MULADD(at[16], at[25]); MULADD(at[17], at[24]); MULADD(at[18], at[23]); MULADD(at[19], at[22]); + COMBA_STORE(C->dp[21]); + /* 22 */ + COMBA_FORWARD; + MULADD(at[3], at[39]); MULADD(at[4], at[38]); MULADD(at[5], at[37]); MULADD(at[6], at[36]); MULADD(at[7], at[35]); MULADD(at[8], at[34]); MULADD(at[9], at[33]); MULADD(at[10], at[32]); MULADD(at[11], at[31]); MULADD(at[12], at[30]); MULADD(at[13], at[29]); MULADD(at[14], at[28]); MULADD(at[15], at[27]); MULADD(at[16], at[26]); MULADD(at[17], at[25]); MULADD(at[18], at[24]); MULADD(at[19], at[23]); + COMBA_STORE(C->dp[22]); + /* 23 */ + COMBA_FORWARD; + MULADD(at[4], at[39]); MULADD(at[5], at[38]); MULADD(at[6], at[37]); MULADD(at[7], at[36]); MULADD(at[8], at[35]); MULADD(at[9], at[34]); MULADD(at[10], at[33]); MULADD(at[11], at[32]); MULADD(at[12], at[31]); MULADD(at[13], at[30]); MULADD(at[14], at[29]); MULADD(at[15], at[28]); MULADD(at[16], at[27]); MULADD(at[17], at[26]); MULADD(at[18], at[25]); MULADD(at[19], at[24]); + COMBA_STORE(C->dp[23]); + /* 24 */ + COMBA_FORWARD; + MULADD(at[5], at[39]); MULADD(at[6], at[38]); MULADD(at[7], at[37]); MULADD(at[8], at[36]); MULADD(at[9], at[35]); MULADD(at[10], at[34]); MULADD(at[11], at[33]); MULADD(at[12], at[32]); MULADD(at[13], at[31]); MULADD(at[14], at[30]); MULADD(at[15], at[29]); MULADD(at[16], at[28]); MULADD(at[17], at[27]); MULADD(at[18], at[26]); MULADD(at[19], at[25]); + COMBA_STORE(C->dp[24]); + /* 25 */ + COMBA_FORWARD; + MULADD(at[6], at[39]); MULADD(at[7], at[38]); MULADD(at[8], at[37]); MULADD(at[9], at[36]); MULADD(at[10], at[35]); MULADD(at[11], at[34]); MULADD(at[12], at[33]); MULADD(at[13], at[32]); MULADD(at[14], at[31]); MULADD(at[15], at[30]); MULADD(at[16], at[29]); MULADD(at[17], at[28]); MULADD(at[18], at[27]); MULADD(at[19], at[26]); + COMBA_STORE(C->dp[25]); + /* 26 */ + COMBA_FORWARD; + MULADD(at[7], at[39]); MULADD(at[8], at[38]); MULADD(at[9], at[37]); MULADD(at[10], at[36]); MULADD(at[11], at[35]); MULADD(at[12], at[34]); MULADD(at[13], at[33]); MULADD(at[14], at[32]); MULADD(at[15], at[31]); MULADD(at[16], at[30]); MULADD(at[17], at[29]); MULADD(at[18], at[28]); MULADD(at[19], at[27]); + COMBA_STORE(C->dp[26]); + /* 27 */ + COMBA_FORWARD; + MULADD(at[8], at[39]); MULADD(at[9], at[38]); MULADD(at[10], at[37]); MULADD(at[11], at[36]); MULADD(at[12], at[35]); MULADD(at[13], at[34]); MULADD(at[14], at[33]); MULADD(at[15], at[32]); MULADD(at[16], at[31]); MULADD(at[17], at[30]); MULADD(at[18], at[29]); MULADD(at[19], at[28]); + COMBA_STORE(C->dp[27]); + /* 28 */ + COMBA_FORWARD; + MULADD(at[9], at[39]); MULADD(at[10], at[38]); MULADD(at[11], at[37]); MULADD(at[12], at[36]); MULADD(at[13], at[35]); MULADD(at[14], at[34]); MULADD(at[15], at[33]); MULADD(at[16], at[32]); MULADD(at[17], at[31]); MULADD(at[18], at[30]); MULADD(at[19], at[29]); + COMBA_STORE(C->dp[28]); + /* 29 */ + COMBA_FORWARD; + MULADD(at[10], at[39]); MULADD(at[11], at[38]); MULADD(at[12], at[37]); MULADD(at[13], at[36]); MULADD(at[14], at[35]); MULADD(at[15], at[34]); MULADD(at[16], at[33]); MULADD(at[17], at[32]); MULADD(at[18], at[31]); MULADD(at[19], at[30]); + COMBA_STORE(C->dp[29]); + /* 30 */ + COMBA_FORWARD; + MULADD(at[11], at[39]); MULADD(at[12], at[38]); MULADD(at[13], at[37]); MULADD(at[14], at[36]); MULADD(at[15], at[35]); MULADD(at[16], at[34]); MULADD(at[17], at[33]); MULADD(at[18], at[32]); MULADD(at[19], at[31]); + COMBA_STORE(C->dp[30]); + /* 31 */ + COMBA_FORWARD; + MULADD(at[12], at[39]); MULADD(at[13], at[38]); MULADD(at[14], at[37]); MULADD(at[15], at[36]); MULADD(at[16], at[35]); MULADD(at[17], at[34]); MULADD(at[18], at[33]); MULADD(at[19], at[32]); + COMBA_STORE(C->dp[31]); + /* 32 */ + COMBA_FORWARD; + MULADD(at[13], at[39]); MULADD(at[14], at[38]); MULADD(at[15], at[37]); MULADD(at[16], at[36]); MULADD(at[17], at[35]); MULADD(at[18], at[34]); MULADD(at[19], at[33]); + COMBA_STORE(C->dp[32]); + /* 33 */ + COMBA_FORWARD; + MULADD(at[14], at[39]); MULADD(at[15], at[38]); MULADD(at[16], at[37]); MULADD(at[17], at[36]); MULADD(at[18], at[35]); MULADD(at[19], at[34]); + COMBA_STORE(C->dp[33]); + /* 34 */ + COMBA_FORWARD; + MULADD(at[15], at[39]); MULADD(at[16], at[38]); MULADD(at[17], at[37]); MULADD(at[18], at[36]); MULADD(at[19], at[35]); + COMBA_STORE(C->dp[34]); + /* 35 */ + COMBA_FORWARD; + MULADD(at[16], at[39]); MULADD(at[17], at[38]); MULADD(at[18], at[37]); MULADD(at[19], at[36]); + COMBA_STORE(C->dp[35]); + /* 36 */ + COMBA_FORWARD; + MULADD(at[17], at[39]); MULADD(at[18], at[38]); MULADD(at[19], at[37]); + COMBA_STORE(C->dp[36]); + /* 37 */ + COMBA_FORWARD; + MULADD(at[18], at[39]); MULADD(at[19], at[38]); + COMBA_STORE(C->dp[37]); + /* 38 */ + COMBA_FORWARD; + MULADD(at[19], at[39]); + COMBA_STORE(C->dp[38]); + COMBA_STORE2(C->dp[39]); + C->used = 40; + C->sign = A->sign ^ B->sign; + fp_clamp(C); + COMBA_FINI; + +#ifdef WOLFSSL_SMALL_STACK + XFREE(at, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; +} +#endif diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_mul_comba_24.i b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_mul_comba_24.i new file mode 100755 index 0000000..0d624ae --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_mul_comba_24.i @@ -0,0 +1,243 @@ +/* fp_mul_comba_24.i + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifdef TFM_MUL24 +int fp_mul_comba24(fp_int *A, fp_int *B, fp_int *C) +{ + fp_digit c0, c1, c2; +#ifndef WOLFSSL_SMALL_STACK + fp_digit at[48]; +#else + fp_digit *at; +#endif + +#ifdef WOLFSSL_SMALL_STACK + at = (fp_digit*)XMALLOC(sizeof(fp_digit) * 48, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (at == NULL) + return FP_MEM; +#endif + + XMEMCPY(at, A->dp, 24 * sizeof(fp_digit)); + XMEMCPY(at+24, B->dp, 24 * sizeof(fp_digit)); + COMBA_START; + + COMBA_CLEAR; + /* 0 */ + MULADD(at[0], at[24]); + COMBA_STORE(C->dp[0]); + /* 1 */ + COMBA_FORWARD; + MULADD(at[0], at[25]); MULADD(at[1], at[24]); + COMBA_STORE(C->dp[1]); + /* 2 */ + COMBA_FORWARD; + MULADD(at[0], at[26]); MULADD(at[1], at[25]); MULADD(at[2], at[24]); + COMBA_STORE(C->dp[2]); + /* 3 */ + COMBA_FORWARD; + MULADD(at[0], at[27]); MULADD(at[1], at[26]); MULADD(at[2], at[25]); MULADD(at[3], at[24]); + COMBA_STORE(C->dp[3]); + /* 4 */ + COMBA_FORWARD; + MULADD(at[0], at[28]); MULADD(at[1], at[27]); MULADD(at[2], at[26]); MULADD(at[3], at[25]); MULADD(at[4], at[24]); + COMBA_STORE(C->dp[4]); + /* 5 */ + COMBA_FORWARD; + MULADD(at[0], at[29]); MULADD(at[1], at[28]); MULADD(at[2], at[27]); MULADD(at[3], at[26]); MULADD(at[4], at[25]); MULADD(at[5], at[24]); + COMBA_STORE(C->dp[5]); + /* 6 */ + COMBA_FORWARD; + MULADD(at[0], at[30]); MULADD(at[1], at[29]); MULADD(at[2], at[28]); MULADD(at[3], at[27]); MULADD(at[4], at[26]); MULADD(at[5], at[25]); MULADD(at[6], at[24]); + COMBA_STORE(C->dp[6]); + /* 7 */ + COMBA_FORWARD; + MULADD(at[0], at[31]); MULADD(at[1], at[30]); MULADD(at[2], at[29]); MULADD(at[3], at[28]); MULADD(at[4], at[27]); MULADD(at[5], at[26]); MULADD(at[6], at[25]); MULADD(at[7], at[24]); + COMBA_STORE(C->dp[7]); + /* 8 */ + COMBA_FORWARD; + MULADD(at[0], at[32]); MULADD(at[1], at[31]); MULADD(at[2], at[30]); MULADD(at[3], at[29]); MULADD(at[4], at[28]); MULADD(at[5], at[27]); MULADD(at[6], at[26]); MULADD(at[7], at[25]); MULADD(at[8], at[24]); + COMBA_STORE(C->dp[8]); + /* 9 */ + COMBA_FORWARD; + MULADD(at[0], at[33]); MULADD(at[1], at[32]); MULADD(at[2], at[31]); MULADD(at[3], at[30]); MULADD(at[4], at[29]); MULADD(at[5], at[28]); MULADD(at[6], at[27]); MULADD(at[7], at[26]); MULADD(at[8], at[25]); MULADD(at[9], at[24]); + COMBA_STORE(C->dp[9]); + /* 10 */ + COMBA_FORWARD; + MULADD(at[0], at[34]); MULADD(at[1], at[33]); MULADD(at[2], at[32]); MULADD(at[3], at[31]); MULADD(at[4], at[30]); MULADD(at[5], at[29]); MULADD(at[6], at[28]); MULADD(at[7], at[27]); MULADD(at[8], at[26]); MULADD(at[9], at[25]); MULADD(at[10], at[24]); + COMBA_STORE(C->dp[10]); + /* 11 */ + COMBA_FORWARD; + MULADD(at[0], at[35]); MULADD(at[1], at[34]); MULADD(at[2], at[33]); MULADD(at[3], at[32]); MULADD(at[4], at[31]); MULADD(at[5], at[30]); MULADD(at[6], at[29]); MULADD(at[7], at[28]); MULADD(at[8], at[27]); MULADD(at[9], at[26]); MULADD(at[10], at[25]); MULADD(at[11], at[24]); + COMBA_STORE(C->dp[11]); + /* 12 */ + COMBA_FORWARD; + MULADD(at[0], at[36]); MULADD(at[1], at[35]); MULADD(at[2], at[34]); MULADD(at[3], at[33]); MULADD(at[4], at[32]); MULADD(at[5], at[31]); MULADD(at[6], at[30]); MULADD(at[7], at[29]); MULADD(at[8], at[28]); MULADD(at[9], at[27]); MULADD(at[10], at[26]); MULADD(at[11], at[25]); MULADD(at[12], at[24]); + COMBA_STORE(C->dp[12]); + /* 13 */ + COMBA_FORWARD; + MULADD(at[0], at[37]); MULADD(at[1], at[36]); MULADD(at[2], at[35]); MULADD(at[3], at[34]); MULADD(at[4], at[33]); MULADD(at[5], at[32]); MULADD(at[6], at[31]); MULADD(at[7], at[30]); MULADD(at[8], at[29]); MULADD(at[9], at[28]); MULADD(at[10], at[27]); MULADD(at[11], at[26]); MULADD(at[12], at[25]); MULADD(at[13], at[24]); + COMBA_STORE(C->dp[13]); + /* 14 */ + COMBA_FORWARD; + MULADD(at[0], at[38]); MULADD(at[1], at[37]); MULADD(at[2], at[36]); MULADD(at[3], at[35]); MULADD(at[4], at[34]); MULADD(at[5], at[33]); MULADD(at[6], at[32]); MULADD(at[7], at[31]); MULADD(at[8], at[30]); MULADD(at[9], at[29]); MULADD(at[10], at[28]); MULADD(at[11], at[27]); MULADD(at[12], at[26]); MULADD(at[13], at[25]); MULADD(at[14], at[24]); + COMBA_STORE(C->dp[14]); + /* 15 */ + COMBA_FORWARD; + MULADD(at[0], at[39]); MULADD(at[1], at[38]); MULADD(at[2], at[37]); MULADD(at[3], at[36]); MULADD(at[4], at[35]); MULADD(at[5], at[34]); MULADD(at[6], at[33]); MULADD(at[7], at[32]); MULADD(at[8], at[31]); MULADD(at[9], at[30]); MULADD(at[10], at[29]); MULADD(at[11], at[28]); MULADD(at[12], at[27]); MULADD(at[13], at[26]); MULADD(at[14], at[25]); MULADD(at[15], at[24]); + COMBA_STORE(C->dp[15]); + /* 16 */ + COMBA_FORWARD; + MULADD(at[0], at[40]); MULADD(at[1], at[39]); MULADD(at[2], at[38]); MULADD(at[3], at[37]); MULADD(at[4], at[36]); MULADD(at[5], at[35]); MULADD(at[6], at[34]); MULADD(at[7], at[33]); MULADD(at[8], at[32]); MULADD(at[9], at[31]); MULADD(at[10], at[30]); MULADD(at[11], at[29]); MULADD(at[12], at[28]); MULADD(at[13], at[27]); MULADD(at[14], at[26]); MULADD(at[15], at[25]); MULADD(at[16], at[24]); + COMBA_STORE(C->dp[16]); + /* 17 */ + COMBA_FORWARD; + MULADD(at[0], at[41]); MULADD(at[1], at[40]); MULADD(at[2], at[39]); MULADD(at[3], at[38]); MULADD(at[4], at[37]); MULADD(at[5], at[36]); MULADD(at[6], at[35]); MULADD(at[7], at[34]); MULADD(at[8], at[33]); MULADD(at[9], at[32]); MULADD(at[10], at[31]); MULADD(at[11], at[30]); MULADD(at[12], at[29]); MULADD(at[13], at[28]); MULADD(at[14], at[27]); MULADD(at[15], at[26]); MULADD(at[16], at[25]); MULADD(at[17], at[24]); + COMBA_STORE(C->dp[17]); + /* 18 */ + COMBA_FORWARD; + MULADD(at[0], at[42]); MULADD(at[1], at[41]); MULADD(at[2], at[40]); MULADD(at[3], at[39]); MULADD(at[4], at[38]); MULADD(at[5], at[37]); MULADD(at[6], at[36]); MULADD(at[7], at[35]); MULADD(at[8], at[34]); MULADD(at[9], at[33]); MULADD(at[10], at[32]); MULADD(at[11], at[31]); MULADD(at[12], at[30]); MULADD(at[13], at[29]); MULADD(at[14], at[28]); MULADD(at[15], at[27]); MULADD(at[16], at[26]); MULADD(at[17], at[25]); MULADD(at[18], at[24]); + COMBA_STORE(C->dp[18]); + /* 19 */ + COMBA_FORWARD; + MULADD(at[0], at[43]); MULADD(at[1], at[42]); MULADD(at[2], at[41]); MULADD(at[3], at[40]); MULADD(at[4], at[39]); MULADD(at[5], at[38]); MULADD(at[6], at[37]); MULADD(at[7], at[36]); MULADD(at[8], at[35]); MULADD(at[9], at[34]); MULADD(at[10], at[33]); MULADD(at[11], at[32]); MULADD(at[12], at[31]); MULADD(at[13], at[30]); MULADD(at[14], at[29]); MULADD(at[15], at[28]); MULADD(at[16], at[27]); MULADD(at[17], at[26]); MULADD(at[18], at[25]); MULADD(at[19], at[24]); + COMBA_STORE(C->dp[19]); + /* 20 */ + COMBA_FORWARD; + MULADD(at[0], at[44]); MULADD(at[1], at[43]); MULADD(at[2], at[42]); MULADD(at[3], at[41]); MULADD(at[4], at[40]); MULADD(at[5], at[39]); MULADD(at[6], at[38]); MULADD(at[7], at[37]); MULADD(at[8], at[36]); MULADD(at[9], at[35]); MULADD(at[10], at[34]); MULADD(at[11], at[33]); MULADD(at[12], at[32]); MULADD(at[13], at[31]); MULADD(at[14], at[30]); MULADD(at[15], at[29]); MULADD(at[16], at[28]); MULADD(at[17], at[27]); MULADD(at[18], at[26]); MULADD(at[19], at[25]); MULADD(at[20], at[24]); + COMBA_STORE(C->dp[20]); + /* 21 */ + COMBA_FORWARD; + MULADD(at[0], at[45]); MULADD(at[1], at[44]); MULADD(at[2], at[43]); MULADD(at[3], at[42]); MULADD(at[4], at[41]); MULADD(at[5], at[40]); MULADD(at[6], at[39]); MULADD(at[7], at[38]); MULADD(at[8], at[37]); MULADD(at[9], at[36]); MULADD(at[10], at[35]); MULADD(at[11], at[34]); MULADD(at[12], at[33]); MULADD(at[13], at[32]); MULADD(at[14], at[31]); MULADD(at[15], at[30]); MULADD(at[16], at[29]); MULADD(at[17], at[28]); MULADD(at[18], at[27]); MULADD(at[19], at[26]); MULADD(at[20], at[25]); MULADD(at[21], at[24]); + COMBA_STORE(C->dp[21]); + /* 22 */ + COMBA_FORWARD; + MULADD(at[0], at[46]); MULADD(at[1], at[45]); MULADD(at[2], at[44]); MULADD(at[3], at[43]); MULADD(at[4], at[42]); MULADD(at[5], at[41]); MULADD(at[6], at[40]); MULADD(at[7], at[39]); MULADD(at[8], at[38]); MULADD(at[9], at[37]); MULADD(at[10], at[36]); MULADD(at[11], at[35]); MULADD(at[12], at[34]); MULADD(at[13], at[33]); MULADD(at[14], at[32]); MULADD(at[15], at[31]); MULADD(at[16], at[30]); MULADD(at[17], at[29]); MULADD(at[18], at[28]); MULADD(at[19], at[27]); MULADD(at[20], at[26]); MULADD(at[21], at[25]); MULADD(at[22], at[24]); + COMBA_STORE(C->dp[22]); + /* 23 */ + COMBA_FORWARD; + MULADD(at[0], at[47]); MULADD(at[1], at[46]); MULADD(at[2], at[45]); MULADD(at[3], at[44]); MULADD(at[4], at[43]); MULADD(at[5], at[42]); MULADD(at[6], at[41]); MULADD(at[7], at[40]); MULADD(at[8], at[39]); MULADD(at[9], at[38]); MULADD(at[10], at[37]); MULADD(at[11], at[36]); MULADD(at[12], at[35]); MULADD(at[13], at[34]); MULADD(at[14], at[33]); MULADD(at[15], at[32]); MULADD(at[16], at[31]); MULADD(at[17], at[30]); MULADD(at[18], at[29]); MULADD(at[19], at[28]); MULADD(at[20], at[27]); MULADD(at[21], at[26]); MULADD(at[22], at[25]); MULADD(at[23], at[24]); + COMBA_STORE(C->dp[23]); + /* 24 */ + COMBA_FORWARD; + MULADD(at[1], at[47]); MULADD(at[2], at[46]); MULADD(at[3], at[45]); MULADD(at[4], at[44]); MULADD(at[5], at[43]); MULADD(at[6], at[42]); MULADD(at[7], at[41]); MULADD(at[8], at[40]); MULADD(at[9], at[39]); MULADD(at[10], at[38]); MULADD(at[11], at[37]); MULADD(at[12], at[36]); MULADD(at[13], at[35]); MULADD(at[14], at[34]); MULADD(at[15], at[33]); MULADD(at[16], at[32]); MULADD(at[17], at[31]); MULADD(at[18], at[30]); MULADD(at[19], at[29]); MULADD(at[20], at[28]); MULADD(at[21], at[27]); MULADD(at[22], at[26]); MULADD(at[23], at[25]); + COMBA_STORE(C->dp[24]); + /* 25 */ + COMBA_FORWARD; + MULADD(at[2], at[47]); MULADD(at[3], at[46]); MULADD(at[4], at[45]); MULADD(at[5], at[44]); MULADD(at[6], at[43]); MULADD(at[7], at[42]); MULADD(at[8], at[41]); MULADD(at[9], at[40]); MULADD(at[10], at[39]); MULADD(at[11], at[38]); MULADD(at[12], at[37]); MULADD(at[13], at[36]); MULADD(at[14], at[35]); MULADD(at[15], at[34]); MULADD(at[16], at[33]); MULADD(at[17], at[32]); MULADD(at[18], at[31]); MULADD(at[19], at[30]); MULADD(at[20], at[29]); MULADD(at[21], at[28]); MULADD(at[22], at[27]); MULADD(at[23], at[26]); + COMBA_STORE(C->dp[25]); + /* 26 */ + COMBA_FORWARD; + MULADD(at[3], at[47]); MULADD(at[4], at[46]); MULADD(at[5], at[45]); MULADD(at[6], at[44]); MULADD(at[7], at[43]); MULADD(at[8], at[42]); MULADD(at[9], at[41]); MULADD(at[10], at[40]); MULADD(at[11], at[39]); MULADD(at[12], at[38]); MULADD(at[13], at[37]); MULADD(at[14], at[36]); MULADD(at[15], at[35]); MULADD(at[16], at[34]); MULADD(at[17], at[33]); MULADD(at[18], at[32]); MULADD(at[19], at[31]); MULADD(at[20], at[30]); MULADD(at[21], at[29]); MULADD(at[22], at[28]); MULADD(at[23], at[27]); + COMBA_STORE(C->dp[26]); + /* 27 */ + COMBA_FORWARD; + MULADD(at[4], at[47]); MULADD(at[5], at[46]); MULADD(at[6], at[45]); MULADD(at[7], at[44]); MULADD(at[8], at[43]); MULADD(at[9], at[42]); MULADD(at[10], at[41]); MULADD(at[11], at[40]); MULADD(at[12], at[39]); MULADD(at[13], at[38]); MULADD(at[14], at[37]); MULADD(at[15], at[36]); MULADD(at[16], at[35]); MULADD(at[17], at[34]); MULADD(at[18], at[33]); MULADD(at[19], at[32]); MULADD(at[20], at[31]); MULADD(at[21], at[30]); MULADD(at[22], at[29]); MULADD(at[23], at[28]); + COMBA_STORE(C->dp[27]); + /* 28 */ + COMBA_FORWARD; + MULADD(at[5], at[47]); MULADD(at[6], at[46]); MULADD(at[7], at[45]); MULADD(at[8], at[44]); MULADD(at[9], at[43]); MULADD(at[10], at[42]); MULADD(at[11], at[41]); MULADD(at[12], at[40]); MULADD(at[13], at[39]); MULADD(at[14], at[38]); MULADD(at[15], at[37]); MULADD(at[16], at[36]); MULADD(at[17], at[35]); MULADD(at[18], at[34]); MULADD(at[19], at[33]); MULADD(at[20], at[32]); MULADD(at[21], at[31]); MULADD(at[22], at[30]); MULADD(at[23], at[29]); + COMBA_STORE(C->dp[28]); + /* 29 */ + COMBA_FORWARD; + MULADD(at[6], at[47]); MULADD(at[7], at[46]); MULADD(at[8], at[45]); MULADD(at[9], at[44]); MULADD(at[10], at[43]); MULADD(at[11], at[42]); MULADD(at[12], at[41]); MULADD(at[13], at[40]); MULADD(at[14], at[39]); MULADD(at[15], at[38]); MULADD(at[16], at[37]); MULADD(at[17], at[36]); MULADD(at[18], at[35]); MULADD(at[19], at[34]); MULADD(at[20], at[33]); MULADD(at[21], at[32]); MULADD(at[22], at[31]); MULADD(at[23], at[30]); + COMBA_STORE(C->dp[29]); + /* 30 */ + COMBA_FORWARD; + MULADD(at[7], at[47]); MULADD(at[8], at[46]); MULADD(at[9], at[45]); MULADD(at[10], at[44]); MULADD(at[11], at[43]); MULADD(at[12], at[42]); MULADD(at[13], at[41]); MULADD(at[14], at[40]); MULADD(at[15], at[39]); MULADD(at[16], at[38]); MULADD(at[17], at[37]); MULADD(at[18], at[36]); MULADD(at[19], at[35]); MULADD(at[20], at[34]); MULADD(at[21], at[33]); MULADD(at[22], at[32]); MULADD(at[23], at[31]); + COMBA_STORE(C->dp[30]); + /* 31 */ + COMBA_FORWARD; + MULADD(at[8], at[47]); MULADD(at[9], at[46]); MULADD(at[10], at[45]); MULADD(at[11], at[44]); MULADD(at[12], at[43]); MULADD(at[13], at[42]); MULADD(at[14], at[41]); MULADD(at[15], at[40]); MULADD(at[16], at[39]); MULADD(at[17], at[38]); MULADD(at[18], at[37]); MULADD(at[19], at[36]); MULADD(at[20], at[35]); MULADD(at[21], at[34]); MULADD(at[22], at[33]); MULADD(at[23], at[32]); + COMBA_STORE(C->dp[31]); + /* 32 */ + COMBA_FORWARD; + MULADD(at[9], at[47]); MULADD(at[10], at[46]); MULADD(at[11], at[45]); MULADD(at[12], at[44]); MULADD(at[13], at[43]); MULADD(at[14], at[42]); MULADD(at[15], at[41]); MULADD(at[16], at[40]); MULADD(at[17], at[39]); MULADD(at[18], at[38]); MULADD(at[19], at[37]); MULADD(at[20], at[36]); MULADD(at[21], at[35]); MULADD(at[22], at[34]); MULADD(at[23], at[33]); + COMBA_STORE(C->dp[32]); + /* 33 */ + COMBA_FORWARD; + MULADD(at[10], at[47]); MULADD(at[11], at[46]); MULADD(at[12], at[45]); MULADD(at[13], at[44]); MULADD(at[14], at[43]); MULADD(at[15], at[42]); MULADD(at[16], at[41]); MULADD(at[17], at[40]); MULADD(at[18], at[39]); MULADD(at[19], at[38]); MULADD(at[20], at[37]); MULADD(at[21], at[36]); MULADD(at[22], at[35]); MULADD(at[23], at[34]); + COMBA_STORE(C->dp[33]); + /* 34 */ + COMBA_FORWARD; + MULADD(at[11], at[47]); MULADD(at[12], at[46]); MULADD(at[13], at[45]); MULADD(at[14], at[44]); MULADD(at[15], at[43]); MULADD(at[16], at[42]); MULADD(at[17], at[41]); MULADD(at[18], at[40]); MULADD(at[19], at[39]); MULADD(at[20], at[38]); MULADD(at[21], at[37]); MULADD(at[22], at[36]); MULADD(at[23], at[35]); + COMBA_STORE(C->dp[34]); + /* 35 */ + COMBA_FORWARD; + MULADD(at[12], at[47]); MULADD(at[13], at[46]); MULADD(at[14], at[45]); MULADD(at[15], at[44]); MULADD(at[16], at[43]); MULADD(at[17], at[42]); MULADD(at[18], at[41]); MULADD(at[19], at[40]); MULADD(at[20], at[39]); MULADD(at[21], at[38]); MULADD(at[22], at[37]); MULADD(at[23], at[36]); + COMBA_STORE(C->dp[35]); + /* 36 */ + COMBA_FORWARD; + MULADD(at[13], at[47]); MULADD(at[14], at[46]); MULADD(at[15], at[45]); MULADD(at[16], at[44]); MULADD(at[17], at[43]); MULADD(at[18], at[42]); MULADD(at[19], at[41]); MULADD(at[20], at[40]); MULADD(at[21], at[39]); MULADD(at[22], at[38]); MULADD(at[23], at[37]); + COMBA_STORE(C->dp[36]); + /* 37 */ + COMBA_FORWARD; + MULADD(at[14], at[47]); MULADD(at[15], at[46]); MULADD(at[16], at[45]); MULADD(at[17], at[44]); MULADD(at[18], at[43]); MULADD(at[19], at[42]); MULADD(at[20], at[41]); MULADD(at[21], at[40]); MULADD(at[22], at[39]); MULADD(at[23], at[38]); + COMBA_STORE(C->dp[37]); + /* 38 */ + COMBA_FORWARD; + MULADD(at[15], at[47]); MULADD(at[16], at[46]); MULADD(at[17], at[45]); MULADD(at[18], at[44]); MULADD(at[19], at[43]); MULADD(at[20], at[42]); MULADD(at[21], at[41]); MULADD(at[22], at[40]); MULADD(at[23], at[39]); + COMBA_STORE(C->dp[38]); + /* 39 */ + COMBA_FORWARD; + MULADD(at[16], at[47]); MULADD(at[17], at[46]); MULADD(at[18], at[45]); MULADD(at[19], at[44]); MULADD(at[20], at[43]); MULADD(at[21], at[42]); MULADD(at[22], at[41]); MULADD(at[23], at[40]); + COMBA_STORE(C->dp[39]); + /* 40 */ + COMBA_FORWARD; + MULADD(at[17], at[47]); MULADD(at[18], at[46]); MULADD(at[19], at[45]); MULADD(at[20], at[44]); MULADD(at[21], at[43]); MULADD(at[22], at[42]); MULADD(at[23], at[41]); + COMBA_STORE(C->dp[40]); + /* 41 */ + COMBA_FORWARD; + MULADD(at[18], at[47]); MULADD(at[19], at[46]); MULADD(at[20], at[45]); MULADD(at[21], at[44]); MULADD(at[22], at[43]); MULADD(at[23], at[42]); + COMBA_STORE(C->dp[41]); + /* 42 */ + COMBA_FORWARD; + MULADD(at[19], at[47]); MULADD(at[20], at[46]); MULADD(at[21], at[45]); MULADD(at[22], at[44]); MULADD(at[23], at[43]); + COMBA_STORE(C->dp[42]); + /* 43 */ + COMBA_FORWARD; + MULADD(at[20], at[47]); MULADD(at[21], at[46]); MULADD(at[22], at[45]); MULADD(at[23], at[44]); + COMBA_STORE(C->dp[43]); + /* 44 */ + COMBA_FORWARD; + MULADD(at[21], at[47]); MULADD(at[22], at[46]); MULADD(at[23], at[45]); + COMBA_STORE(C->dp[44]); + /* 45 */ + COMBA_FORWARD; + MULADD(at[22], at[47]); MULADD(at[23], at[46]); + COMBA_STORE(C->dp[45]); + /* 46 */ + COMBA_FORWARD; + MULADD(at[23], at[47]); + COMBA_STORE(C->dp[46]); + COMBA_STORE2(C->dp[47]); + C->used = 48; + C->sign = A->sign ^ B->sign; + fp_clamp(C); + COMBA_FINI; + +#ifdef WOLFSSL_SMALL_STACK + XFREE(at, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; +} +#endif diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_mul_comba_28.i b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_mul_comba_28.i new file mode 100755 index 0000000..dfd1478 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_mul_comba_28.i @@ -0,0 +1,275 @@ +/* fp_mul_comba_28.i + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifdef TFM_MUL28 +int fp_mul_comba28(fp_int *A, fp_int *B, fp_int *C) +{ + fp_digit c0, c1, c2; +#ifndef WOLFSSL_SMALL_STACK + fp_digit at[56]; +#else + fp_digit *at; +#endif + +#ifdef WOLFSSL_SMALL_STACK + at = (fp_digit*)XMALLOC(sizeof(fp_digit) * 56, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (at == NULL) + return FP_MEM; +#endif + + XMEMCPY(at, A->dp, 28 * sizeof(fp_digit)); + XMEMCPY(at+28, B->dp, 28 * sizeof(fp_digit)); + COMBA_START; + + COMBA_CLEAR; + /* 0 */ + MULADD(at[0], at[28]); + COMBA_STORE(C->dp[0]); + /* 1 */ + COMBA_FORWARD; + MULADD(at[0], at[29]); MULADD(at[1], at[28]); + COMBA_STORE(C->dp[1]); + /* 2 */ + COMBA_FORWARD; + MULADD(at[0], at[30]); MULADD(at[1], at[29]); MULADD(at[2], at[28]); + COMBA_STORE(C->dp[2]); + /* 3 */ + COMBA_FORWARD; + MULADD(at[0], at[31]); MULADD(at[1], at[30]); MULADD(at[2], at[29]); MULADD(at[3], at[28]); + COMBA_STORE(C->dp[3]); + /* 4 */ + COMBA_FORWARD; + MULADD(at[0], at[32]); MULADD(at[1], at[31]); MULADD(at[2], at[30]); MULADD(at[3], at[29]); MULADD(at[4], at[28]); + COMBA_STORE(C->dp[4]); + /* 5 */ + COMBA_FORWARD; + MULADD(at[0], at[33]); MULADD(at[1], at[32]); MULADD(at[2], at[31]); MULADD(at[3], at[30]); MULADD(at[4], at[29]); MULADD(at[5], at[28]); + COMBA_STORE(C->dp[5]); + /* 6 */ + COMBA_FORWARD; + MULADD(at[0], at[34]); MULADD(at[1], at[33]); MULADD(at[2], at[32]); MULADD(at[3], at[31]); MULADD(at[4], at[30]); MULADD(at[5], at[29]); MULADD(at[6], at[28]); + COMBA_STORE(C->dp[6]); + /* 7 */ + COMBA_FORWARD; + MULADD(at[0], at[35]); MULADD(at[1], at[34]); MULADD(at[2], at[33]); MULADD(at[3], at[32]); MULADD(at[4], at[31]); MULADD(at[5], at[30]); MULADD(at[6], at[29]); MULADD(at[7], at[28]); + COMBA_STORE(C->dp[7]); + /* 8 */ + COMBA_FORWARD; + MULADD(at[0], at[36]); MULADD(at[1], at[35]); MULADD(at[2], at[34]); MULADD(at[3], at[33]); MULADD(at[4], at[32]); MULADD(at[5], at[31]); MULADD(at[6], at[30]); MULADD(at[7], at[29]); MULADD(at[8], at[28]); + COMBA_STORE(C->dp[8]); + /* 9 */ + COMBA_FORWARD; + MULADD(at[0], at[37]); MULADD(at[1], at[36]); MULADD(at[2], at[35]); MULADD(at[3], at[34]); MULADD(at[4], at[33]); MULADD(at[5], at[32]); MULADD(at[6], at[31]); MULADD(at[7], at[30]); MULADD(at[8], at[29]); MULADD(at[9], at[28]); + COMBA_STORE(C->dp[9]); + /* 10 */ + COMBA_FORWARD; + MULADD(at[0], at[38]); MULADD(at[1], at[37]); MULADD(at[2], at[36]); MULADD(at[3], at[35]); MULADD(at[4], at[34]); MULADD(at[5], at[33]); MULADD(at[6], at[32]); MULADD(at[7], at[31]); MULADD(at[8], at[30]); MULADD(at[9], at[29]); MULADD(at[10], at[28]); + COMBA_STORE(C->dp[10]); + /* 11 */ + COMBA_FORWARD; + MULADD(at[0], at[39]); MULADD(at[1], at[38]); MULADD(at[2], at[37]); MULADD(at[3], at[36]); MULADD(at[4], at[35]); MULADD(at[5], at[34]); MULADD(at[6], at[33]); MULADD(at[7], at[32]); MULADD(at[8], at[31]); MULADD(at[9], at[30]); MULADD(at[10], at[29]); MULADD(at[11], at[28]); + COMBA_STORE(C->dp[11]); + /* 12 */ + COMBA_FORWARD; + MULADD(at[0], at[40]); MULADD(at[1], at[39]); MULADD(at[2], at[38]); MULADD(at[3], at[37]); MULADD(at[4], at[36]); MULADD(at[5], at[35]); MULADD(at[6], at[34]); MULADD(at[7], at[33]); MULADD(at[8], at[32]); MULADD(at[9], at[31]); MULADD(at[10], at[30]); MULADD(at[11], at[29]); MULADD(at[12], at[28]); + COMBA_STORE(C->dp[12]); + /* 13 */ + COMBA_FORWARD; + MULADD(at[0], at[41]); MULADD(at[1], at[40]); MULADD(at[2], at[39]); MULADD(at[3], at[38]); MULADD(at[4], at[37]); MULADD(at[5], at[36]); MULADD(at[6], at[35]); MULADD(at[7], at[34]); MULADD(at[8], at[33]); MULADD(at[9], at[32]); MULADD(at[10], at[31]); MULADD(at[11], at[30]); MULADD(at[12], at[29]); MULADD(at[13], at[28]); + COMBA_STORE(C->dp[13]); + /* 14 */ + COMBA_FORWARD; + MULADD(at[0], at[42]); MULADD(at[1], at[41]); MULADD(at[2], at[40]); MULADD(at[3], at[39]); MULADD(at[4], at[38]); MULADD(at[5], at[37]); MULADD(at[6], at[36]); MULADD(at[7], at[35]); MULADD(at[8], at[34]); MULADD(at[9], at[33]); MULADD(at[10], at[32]); MULADD(at[11], at[31]); MULADD(at[12], at[30]); MULADD(at[13], at[29]); MULADD(at[14], at[28]); + COMBA_STORE(C->dp[14]); + /* 15 */ + COMBA_FORWARD; + MULADD(at[0], at[43]); MULADD(at[1], at[42]); MULADD(at[2], at[41]); MULADD(at[3], at[40]); MULADD(at[4], at[39]); MULADD(at[5], at[38]); MULADD(at[6], at[37]); MULADD(at[7], at[36]); MULADD(at[8], at[35]); MULADD(at[9], at[34]); MULADD(at[10], at[33]); MULADD(at[11], at[32]); MULADD(at[12], at[31]); MULADD(at[13], at[30]); MULADD(at[14], at[29]); MULADD(at[15], at[28]); + COMBA_STORE(C->dp[15]); + /* 16 */ + COMBA_FORWARD; + MULADD(at[0], at[44]); MULADD(at[1], at[43]); MULADD(at[2], at[42]); MULADD(at[3], at[41]); MULADD(at[4], at[40]); MULADD(at[5], at[39]); MULADD(at[6], at[38]); MULADD(at[7], at[37]); MULADD(at[8], at[36]); MULADD(at[9], at[35]); MULADD(at[10], at[34]); MULADD(at[11], at[33]); MULADD(at[12], at[32]); MULADD(at[13], at[31]); MULADD(at[14], at[30]); MULADD(at[15], at[29]); MULADD(at[16], at[28]); + COMBA_STORE(C->dp[16]); + /* 17 */ + COMBA_FORWARD; + MULADD(at[0], at[45]); MULADD(at[1], at[44]); MULADD(at[2], at[43]); MULADD(at[3], at[42]); MULADD(at[4], at[41]); MULADD(at[5], at[40]); MULADD(at[6], at[39]); MULADD(at[7], at[38]); MULADD(at[8], at[37]); MULADD(at[9], at[36]); MULADD(at[10], at[35]); MULADD(at[11], at[34]); MULADD(at[12], at[33]); MULADD(at[13], at[32]); MULADD(at[14], at[31]); MULADD(at[15], at[30]); MULADD(at[16], at[29]); MULADD(at[17], at[28]); + COMBA_STORE(C->dp[17]); + /* 18 */ + COMBA_FORWARD; + MULADD(at[0], at[46]); MULADD(at[1], at[45]); MULADD(at[2], at[44]); MULADD(at[3], at[43]); MULADD(at[4], at[42]); MULADD(at[5], at[41]); MULADD(at[6], at[40]); MULADD(at[7], at[39]); MULADD(at[8], at[38]); MULADD(at[9], at[37]); MULADD(at[10], at[36]); MULADD(at[11], at[35]); MULADD(at[12], at[34]); MULADD(at[13], at[33]); MULADD(at[14], at[32]); MULADD(at[15], at[31]); MULADD(at[16], at[30]); MULADD(at[17], at[29]); MULADD(at[18], at[28]); + COMBA_STORE(C->dp[18]); + /* 19 */ + COMBA_FORWARD; + MULADD(at[0], at[47]); MULADD(at[1], at[46]); MULADD(at[2], at[45]); MULADD(at[3], at[44]); MULADD(at[4], at[43]); MULADD(at[5], at[42]); MULADD(at[6], at[41]); MULADD(at[7], at[40]); MULADD(at[8], at[39]); MULADD(at[9], at[38]); MULADD(at[10], at[37]); MULADD(at[11], at[36]); MULADD(at[12], at[35]); MULADD(at[13], at[34]); MULADD(at[14], at[33]); MULADD(at[15], at[32]); MULADD(at[16], at[31]); MULADD(at[17], at[30]); MULADD(at[18], at[29]); MULADD(at[19], at[28]); + COMBA_STORE(C->dp[19]); + /* 20 */ + COMBA_FORWARD; + MULADD(at[0], at[48]); MULADD(at[1], at[47]); MULADD(at[2], at[46]); MULADD(at[3], at[45]); MULADD(at[4], at[44]); MULADD(at[5], at[43]); MULADD(at[6], at[42]); MULADD(at[7], at[41]); MULADD(at[8], at[40]); MULADD(at[9], at[39]); MULADD(at[10], at[38]); MULADD(at[11], at[37]); MULADD(at[12], at[36]); MULADD(at[13], at[35]); MULADD(at[14], at[34]); MULADD(at[15], at[33]); MULADD(at[16], at[32]); MULADD(at[17], at[31]); MULADD(at[18], at[30]); MULADD(at[19], at[29]); MULADD(at[20], at[28]); + COMBA_STORE(C->dp[20]); + /* 21 */ + COMBA_FORWARD; + MULADD(at[0], at[49]); MULADD(at[1], at[48]); MULADD(at[2], at[47]); MULADD(at[3], at[46]); MULADD(at[4], at[45]); MULADD(at[5], at[44]); MULADD(at[6], at[43]); MULADD(at[7], at[42]); MULADD(at[8], at[41]); MULADD(at[9], at[40]); MULADD(at[10], at[39]); MULADD(at[11], at[38]); MULADD(at[12], at[37]); MULADD(at[13], at[36]); MULADD(at[14], at[35]); MULADD(at[15], at[34]); MULADD(at[16], at[33]); MULADD(at[17], at[32]); MULADD(at[18], at[31]); MULADD(at[19], at[30]); MULADD(at[20], at[29]); MULADD(at[21], at[28]); + COMBA_STORE(C->dp[21]); + /* 22 */ + COMBA_FORWARD; + MULADD(at[0], at[50]); MULADD(at[1], at[49]); MULADD(at[2], at[48]); MULADD(at[3], at[47]); MULADD(at[4], at[46]); MULADD(at[5], at[45]); MULADD(at[6], at[44]); MULADD(at[7], at[43]); MULADD(at[8], at[42]); MULADD(at[9], at[41]); MULADD(at[10], at[40]); MULADD(at[11], at[39]); MULADD(at[12], at[38]); MULADD(at[13], at[37]); MULADD(at[14], at[36]); MULADD(at[15], at[35]); MULADD(at[16], at[34]); MULADD(at[17], at[33]); MULADD(at[18], at[32]); MULADD(at[19], at[31]); MULADD(at[20], at[30]); MULADD(at[21], at[29]); MULADD(at[22], at[28]); + COMBA_STORE(C->dp[22]); + /* 23 */ + COMBA_FORWARD; + MULADD(at[0], at[51]); MULADD(at[1], at[50]); MULADD(at[2], at[49]); MULADD(at[3], at[48]); MULADD(at[4], at[47]); MULADD(at[5], at[46]); MULADD(at[6], at[45]); MULADD(at[7], at[44]); MULADD(at[8], at[43]); MULADD(at[9], at[42]); MULADD(at[10], at[41]); MULADD(at[11], at[40]); MULADD(at[12], at[39]); MULADD(at[13], at[38]); MULADD(at[14], at[37]); MULADD(at[15], at[36]); MULADD(at[16], at[35]); MULADD(at[17], at[34]); MULADD(at[18], at[33]); MULADD(at[19], at[32]); MULADD(at[20], at[31]); MULADD(at[21], at[30]); MULADD(at[22], at[29]); MULADD(at[23], at[28]); + COMBA_STORE(C->dp[23]); + /* 24 */ + COMBA_FORWARD; + MULADD(at[0], at[52]); MULADD(at[1], at[51]); MULADD(at[2], at[50]); MULADD(at[3], at[49]); MULADD(at[4], at[48]); MULADD(at[5], at[47]); MULADD(at[6], at[46]); MULADD(at[7], at[45]); MULADD(at[8], at[44]); MULADD(at[9], at[43]); MULADD(at[10], at[42]); MULADD(at[11], at[41]); MULADD(at[12], at[40]); MULADD(at[13], at[39]); MULADD(at[14], at[38]); MULADD(at[15], at[37]); MULADD(at[16], at[36]); MULADD(at[17], at[35]); MULADD(at[18], at[34]); MULADD(at[19], at[33]); MULADD(at[20], at[32]); MULADD(at[21], at[31]); MULADD(at[22], at[30]); MULADD(at[23], at[29]); MULADD(at[24], at[28]); + COMBA_STORE(C->dp[24]); + /* 25 */ + COMBA_FORWARD; + MULADD(at[0], at[53]); MULADD(at[1], at[52]); MULADD(at[2], at[51]); MULADD(at[3], at[50]); MULADD(at[4], at[49]); MULADD(at[5], at[48]); MULADD(at[6], at[47]); MULADD(at[7], at[46]); MULADD(at[8], at[45]); MULADD(at[9], at[44]); MULADD(at[10], at[43]); MULADD(at[11], at[42]); MULADD(at[12], at[41]); MULADD(at[13], at[40]); MULADD(at[14], at[39]); MULADD(at[15], at[38]); MULADD(at[16], at[37]); MULADD(at[17], at[36]); MULADD(at[18], at[35]); MULADD(at[19], at[34]); MULADD(at[20], at[33]); MULADD(at[21], at[32]); MULADD(at[22], at[31]); MULADD(at[23], at[30]); MULADD(at[24], at[29]); MULADD(at[25], at[28]); + COMBA_STORE(C->dp[25]); + /* 26 */ + COMBA_FORWARD; + MULADD(at[0], at[54]); MULADD(at[1], at[53]); MULADD(at[2], at[52]); MULADD(at[3], at[51]); MULADD(at[4], at[50]); MULADD(at[5], at[49]); MULADD(at[6], at[48]); MULADD(at[7], at[47]); MULADD(at[8], at[46]); MULADD(at[9], at[45]); MULADD(at[10], at[44]); MULADD(at[11], at[43]); MULADD(at[12], at[42]); MULADD(at[13], at[41]); MULADD(at[14], at[40]); MULADD(at[15], at[39]); MULADD(at[16], at[38]); MULADD(at[17], at[37]); MULADD(at[18], at[36]); MULADD(at[19], at[35]); MULADD(at[20], at[34]); MULADD(at[21], at[33]); MULADD(at[22], at[32]); MULADD(at[23], at[31]); MULADD(at[24], at[30]); MULADD(at[25], at[29]); MULADD(at[26], at[28]); + COMBA_STORE(C->dp[26]); + /* 27 */ + COMBA_FORWARD; + MULADD(at[0], at[55]); MULADD(at[1], at[54]); MULADD(at[2], at[53]); MULADD(at[3], at[52]); MULADD(at[4], at[51]); MULADD(at[5], at[50]); MULADD(at[6], at[49]); MULADD(at[7], at[48]); MULADD(at[8], at[47]); MULADD(at[9], at[46]); MULADD(at[10], at[45]); MULADD(at[11], at[44]); MULADD(at[12], at[43]); MULADD(at[13], at[42]); MULADD(at[14], at[41]); MULADD(at[15], at[40]); MULADD(at[16], at[39]); MULADD(at[17], at[38]); MULADD(at[18], at[37]); MULADD(at[19], at[36]); MULADD(at[20], at[35]); MULADD(at[21], at[34]); MULADD(at[22], at[33]); MULADD(at[23], at[32]); MULADD(at[24], at[31]); MULADD(at[25], at[30]); MULADD(at[26], at[29]); MULADD(at[27], at[28]); + COMBA_STORE(C->dp[27]); + /* 28 */ + COMBA_FORWARD; + MULADD(at[1], at[55]); MULADD(at[2], at[54]); MULADD(at[3], at[53]); MULADD(at[4], at[52]); MULADD(at[5], at[51]); MULADD(at[6], at[50]); MULADD(at[7], at[49]); MULADD(at[8], at[48]); MULADD(at[9], at[47]); MULADD(at[10], at[46]); MULADD(at[11], at[45]); MULADD(at[12], at[44]); MULADD(at[13], at[43]); MULADD(at[14], at[42]); MULADD(at[15], at[41]); MULADD(at[16], at[40]); MULADD(at[17], at[39]); MULADD(at[18], at[38]); MULADD(at[19], at[37]); MULADD(at[20], at[36]); MULADD(at[21], at[35]); MULADD(at[22], at[34]); MULADD(at[23], at[33]); MULADD(at[24], at[32]); MULADD(at[25], at[31]); MULADD(at[26], at[30]); MULADD(at[27], at[29]); + COMBA_STORE(C->dp[28]); + /* 29 */ + COMBA_FORWARD; + MULADD(at[2], at[55]); MULADD(at[3], at[54]); MULADD(at[4], at[53]); MULADD(at[5], at[52]); MULADD(at[6], at[51]); MULADD(at[7], at[50]); MULADD(at[8], at[49]); MULADD(at[9], at[48]); MULADD(at[10], at[47]); MULADD(at[11], at[46]); MULADD(at[12], at[45]); MULADD(at[13], at[44]); MULADD(at[14], at[43]); MULADD(at[15], at[42]); MULADD(at[16], at[41]); MULADD(at[17], at[40]); MULADD(at[18], at[39]); MULADD(at[19], at[38]); MULADD(at[20], at[37]); MULADD(at[21], at[36]); MULADD(at[22], at[35]); MULADD(at[23], at[34]); MULADD(at[24], at[33]); MULADD(at[25], at[32]); MULADD(at[26], at[31]); MULADD(at[27], at[30]); + COMBA_STORE(C->dp[29]); + /* 30 */ + COMBA_FORWARD; + MULADD(at[3], at[55]); MULADD(at[4], at[54]); MULADD(at[5], at[53]); MULADD(at[6], at[52]); MULADD(at[7], at[51]); MULADD(at[8], at[50]); MULADD(at[9], at[49]); MULADD(at[10], at[48]); MULADD(at[11], at[47]); MULADD(at[12], at[46]); MULADD(at[13], at[45]); MULADD(at[14], at[44]); MULADD(at[15], at[43]); MULADD(at[16], at[42]); MULADD(at[17], at[41]); MULADD(at[18], at[40]); MULADD(at[19], at[39]); MULADD(at[20], at[38]); MULADD(at[21], at[37]); MULADD(at[22], at[36]); MULADD(at[23], at[35]); MULADD(at[24], at[34]); MULADD(at[25], at[33]); MULADD(at[26], at[32]); MULADD(at[27], at[31]); + COMBA_STORE(C->dp[30]); + /* 31 */ + COMBA_FORWARD; + MULADD(at[4], at[55]); MULADD(at[5], at[54]); MULADD(at[6], at[53]); MULADD(at[7], at[52]); MULADD(at[8], at[51]); MULADD(at[9], at[50]); MULADD(at[10], at[49]); MULADD(at[11], at[48]); MULADD(at[12], at[47]); MULADD(at[13], at[46]); MULADD(at[14], at[45]); MULADD(at[15], at[44]); MULADD(at[16], at[43]); MULADD(at[17], at[42]); MULADD(at[18], at[41]); MULADD(at[19], at[40]); MULADD(at[20], at[39]); MULADD(at[21], at[38]); MULADD(at[22], at[37]); MULADD(at[23], at[36]); MULADD(at[24], at[35]); MULADD(at[25], at[34]); MULADD(at[26], at[33]); MULADD(at[27], at[32]); + COMBA_STORE(C->dp[31]); + /* 32 */ + COMBA_FORWARD; + MULADD(at[5], at[55]); MULADD(at[6], at[54]); MULADD(at[7], at[53]); MULADD(at[8], at[52]); MULADD(at[9], at[51]); MULADD(at[10], at[50]); MULADD(at[11], at[49]); MULADD(at[12], at[48]); MULADD(at[13], at[47]); MULADD(at[14], at[46]); MULADD(at[15], at[45]); MULADD(at[16], at[44]); MULADD(at[17], at[43]); MULADD(at[18], at[42]); MULADD(at[19], at[41]); MULADD(at[20], at[40]); MULADD(at[21], at[39]); MULADD(at[22], at[38]); MULADD(at[23], at[37]); MULADD(at[24], at[36]); MULADD(at[25], at[35]); MULADD(at[26], at[34]); MULADD(at[27], at[33]); + COMBA_STORE(C->dp[32]); + /* 33 */ + COMBA_FORWARD; + MULADD(at[6], at[55]); MULADD(at[7], at[54]); MULADD(at[8], at[53]); MULADD(at[9], at[52]); MULADD(at[10], at[51]); MULADD(at[11], at[50]); MULADD(at[12], at[49]); MULADD(at[13], at[48]); MULADD(at[14], at[47]); MULADD(at[15], at[46]); MULADD(at[16], at[45]); MULADD(at[17], at[44]); MULADD(at[18], at[43]); MULADD(at[19], at[42]); MULADD(at[20], at[41]); MULADD(at[21], at[40]); MULADD(at[22], at[39]); MULADD(at[23], at[38]); MULADD(at[24], at[37]); MULADD(at[25], at[36]); MULADD(at[26], at[35]); MULADD(at[27], at[34]); + COMBA_STORE(C->dp[33]); + /* 34 */ + COMBA_FORWARD; + MULADD(at[7], at[55]); MULADD(at[8], at[54]); MULADD(at[9], at[53]); MULADD(at[10], at[52]); MULADD(at[11], at[51]); MULADD(at[12], at[50]); MULADD(at[13], at[49]); MULADD(at[14], at[48]); MULADD(at[15], at[47]); MULADD(at[16], at[46]); MULADD(at[17], at[45]); MULADD(at[18], at[44]); MULADD(at[19], at[43]); MULADD(at[20], at[42]); MULADD(at[21], at[41]); MULADD(at[22], at[40]); MULADD(at[23], at[39]); MULADD(at[24], at[38]); MULADD(at[25], at[37]); MULADD(at[26], at[36]); MULADD(at[27], at[35]); + COMBA_STORE(C->dp[34]); + /* 35 */ + COMBA_FORWARD; + MULADD(at[8], at[55]); MULADD(at[9], at[54]); MULADD(at[10], at[53]); MULADD(at[11], at[52]); MULADD(at[12], at[51]); MULADD(at[13], at[50]); MULADD(at[14], at[49]); MULADD(at[15], at[48]); MULADD(at[16], at[47]); MULADD(at[17], at[46]); MULADD(at[18], at[45]); MULADD(at[19], at[44]); MULADD(at[20], at[43]); MULADD(at[21], at[42]); MULADD(at[22], at[41]); MULADD(at[23], at[40]); MULADD(at[24], at[39]); MULADD(at[25], at[38]); MULADD(at[26], at[37]); MULADD(at[27], at[36]); + COMBA_STORE(C->dp[35]); + /* 36 */ + COMBA_FORWARD; + MULADD(at[9], at[55]); MULADD(at[10], at[54]); MULADD(at[11], at[53]); MULADD(at[12], at[52]); MULADD(at[13], at[51]); MULADD(at[14], at[50]); MULADD(at[15], at[49]); MULADD(at[16], at[48]); MULADD(at[17], at[47]); MULADD(at[18], at[46]); MULADD(at[19], at[45]); MULADD(at[20], at[44]); MULADD(at[21], at[43]); MULADD(at[22], at[42]); MULADD(at[23], at[41]); MULADD(at[24], at[40]); MULADD(at[25], at[39]); MULADD(at[26], at[38]); MULADD(at[27], at[37]); + COMBA_STORE(C->dp[36]); + /* 37 */ + COMBA_FORWARD; + MULADD(at[10], at[55]); MULADD(at[11], at[54]); MULADD(at[12], at[53]); MULADD(at[13], at[52]); MULADD(at[14], at[51]); MULADD(at[15], at[50]); MULADD(at[16], at[49]); MULADD(at[17], at[48]); MULADD(at[18], at[47]); MULADD(at[19], at[46]); MULADD(at[20], at[45]); MULADD(at[21], at[44]); MULADD(at[22], at[43]); MULADD(at[23], at[42]); MULADD(at[24], at[41]); MULADD(at[25], at[40]); MULADD(at[26], at[39]); MULADD(at[27], at[38]); + COMBA_STORE(C->dp[37]); + /* 38 */ + COMBA_FORWARD; + MULADD(at[11], at[55]); MULADD(at[12], at[54]); MULADD(at[13], at[53]); MULADD(at[14], at[52]); MULADD(at[15], at[51]); MULADD(at[16], at[50]); MULADD(at[17], at[49]); MULADD(at[18], at[48]); MULADD(at[19], at[47]); MULADD(at[20], at[46]); MULADD(at[21], at[45]); MULADD(at[22], at[44]); MULADD(at[23], at[43]); MULADD(at[24], at[42]); MULADD(at[25], at[41]); MULADD(at[26], at[40]); MULADD(at[27], at[39]); + COMBA_STORE(C->dp[38]); + /* 39 */ + COMBA_FORWARD; + MULADD(at[12], at[55]); MULADD(at[13], at[54]); MULADD(at[14], at[53]); MULADD(at[15], at[52]); MULADD(at[16], at[51]); MULADD(at[17], at[50]); MULADD(at[18], at[49]); MULADD(at[19], at[48]); MULADD(at[20], at[47]); MULADD(at[21], at[46]); MULADD(at[22], at[45]); MULADD(at[23], at[44]); MULADD(at[24], at[43]); MULADD(at[25], at[42]); MULADD(at[26], at[41]); MULADD(at[27], at[40]); + COMBA_STORE(C->dp[39]); + /* 40 */ + COMBA_FORWARD; + MULADD(at[13], at[55]); MULADD(at[14], at[54]); MULADD(at[15], at[53]); MULADD(at[16], at[52]); MULADD(at[17], at[51]); MULADD(at[18], at[50]); MULADD(at[19], at[49]); MULADD(at[20], at[48]); MULADD(at[21], at[47]); MULADD(at[22], at[46]); MULADD(at[23], at[45]); MULADD(at[24], at[44]); MULADD(at[25], at[43]); MULADD(at[26], at[42]); MULADD(at[27], at[41]); + COMBA_STORE(C->dp[40]); + /* 41 */ + COMBA_FORWARD; + MULADD(at[14], at[55]); MULADD(at[15], at[54]); MULADD(at[16], at[53]); MULADD(at[17], at[52]); MULADD(at[18], at[51]); MULADD(at[19], at[50]); MULADD(at[20], at[49]); MULADD(at[21], at[48]); MULADD(at[22], at[47]); MULADD(at[23], at[46]); MULADD(at[24], at[45]); MULADD(at[25], at[44]); MULADD(at[26], at[43]); MULADD(at[27], at[42]); + COMBA_STORE(C->dp[41]); + /* 42 */ + COMBA_FORWARD; + MULADD(at[15], at[55]); MULADD(at[16], at[54]); MULADD(at[17], at[53]); MULADD(at[18], at[52]); MULADD(at[19], at[51]); MULADD(at[20], at[50]); MULADD(at[21], at[49]); MULADD(at[22], at[48]); MULADD(at[23], at[47]); MULADD(at[24], at[46]); MULADD(at[25], at[45]); MULADD(at[26], at[44]); MULADD(at[27], at[43]); + COMBA_STORE(C->dp[42]); + /* 43 */ + COMBA_FORWARD; + MULADD(at[16], at[55]); MULADD(at[17], at[54]); MULADD(at[18], at[53]); MULADD(at[19], at[52]); MULADD(at[20], at[51]); MULADD(at[21], at[50]); MULADD(at[22], at[49]); MULADD(at[23], at[48]); MULADD(at[24], at[47]); MULADD(at[25], at[46]); MULADD(at[26], at[45]); MULADD(at[27], at[44]); + COMBA_STORE(C->dp[43]); + /* 44 */ + COMBA_FORWARD; + MULADD(at[17], at[55]); MULADD(at[18], at[54]); MULADD(at[19], at[53]); MULADD(at[20], at[52]); MULADD(at[21], at[51]); MULADD(at[22], at[50]); MULADD(at[23], at[49]); MULADD(at[24], at[48]); MULADD(at[25], at[47]); MULADD(at[26], at[46]); MULADD(at[27], at[45]); + COMBA_STORE(C->dp[44]); + /* 45 */ + COMBA_FORWARD; + MULADD(at[18], at[55]); MULADD(at[19], at[54]); MULADD(at[20], at[53]); MULADD(at[21], at[52]); MULADD(at[22], at[51]); MULADD(at[23], at[50]); MULADD(at[24], at[49]); MULADD(at[25], at[48]); MULADD(at[26], at[47]); MULADD(at[27], at[46]); + COMBA_STORE(C->dp[45]); + /* 46 */ + COMBA_FORWARD; + MULADD(at[19], at[55]); MULADD(at[20], at[54]); MULADD(at[21], at[53]); MULADD(at[22], at[52]); MULADD(at[23], at[51]); MULADD(at[24], at[50]); MULADD(at[25], at[49]); MULADD(at[26], at[48]); MULADD(at[27], at[47]); + COMBA_STORE(C->dp[46]); + /* 47 */ + COMBA_FORWARD; + MULADD(at[20], at[55]); MULADD(at[21], at[54]); MULADD(at[22], at[53]); MULADD(at[23], at[52]); MULADD(at[24], at[51]); MULADD(at[25], at[50]); MULADD(at[26], at[49]); MULADD(at[27], at[48]); + COMBA_STORE(C->dp[47]); + /* 48 */ + COMBA_FORWARD; + MULADD(at[21], at[55]); MULADD(at[22], at[54]); MULADD(at[23], at[53]); MULADD(at[24], at[52]); MULADD(at[25], at[51]); MULADD(at[26], at[50]); MULADD(at[27], at[49]); + COMBA_STORE(C->dp[48]); + /* 49 */ + COMBA_FORWARD; + MULADD(at[22], at[55]); MULADD(at[23], at[54]); MULADD(at[24], at[53]); MULADD(at[25], at[52]); MULADD(at[26], at[51]); MULADD(at[27], at[50]); + COMBA_STORE(C->dp[49]); + /* 50 */ + COMBA_FORWARD; + MULADD(at[23], at[55]); MULADD(at[24], at[54]); MULADD(at[25], at[53]); MULADD(at[26], at[52]); MULADD(at[27], at[51]); + COMBA_STORE(C->dp[50]); + /* 51 */ + COMBA_FORWARD; + MULADD(at[24], at[55]); MULADD(at[25], at[54]); MULADD(at[26], at[53]); MULADD(at[27], at[52]); + COMBA_STORE(C->dp[51]); + /* 52 */ + COMBA_FORWARD; + MULADD(at[25], at[55]); MULADD(at[26], at[54]); MULADD(at[27], at[53]); + COMBA_STORE(C->dp[52]); + /* 53 */ + COMBA_FORWARD; + MULADD(at[26], at[55]); MULADD(at[27], at[54]); + COMBA_STORE(C->dp[53]); + /* 54 */ + COMBA_FORWARD; + MULADD(at[27], at[55]); + COMBA_STORE(C->dp[54]); + COMBA_STORE2(C->dp[55]); + C->used = 56; + C->sign = A->sign ^ B->sign; + fp_clamp(C); + COMBA_FINI; + +#ifdef WOLFSSL_SMALL_STACK + XFREE(at, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; +} +#endif diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_mul_comba_3.i b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_mul_comba_3.i new file mode 100755 index 0000000..b53937f --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_mul_comba_3.i @@ -0,0 +1,61 @@ +/* fp_mul_comba_3.i + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifdef TFM_MUL3 +int fp_mul_comba3(fp_int *A, fp_int *B, fp_int *C) +{ + fp_digit c0, c1, c2, at[6]; + + XMEMCPY(at, A->dp, 3 * sizeof(fp_digit)); + XMEMCPY(at+3, B->dp, 3 * sizeof(fp_digit)); + COMBA_START; + + COMBA_CLEAR; + /* 0 */ + MULADD(at[0], at[3]); + COMBA_STORE(C->dp[0]); + /* 1 */ + COMBA_FORWARD; + MULADD(at[0], at[4]); MULADD(at[1], at[3]); + COMBA_STORE(C->dp[1]); + /* 2 */ + COMBA_FORWARD; + MULADD(at[0], at[5]); MULADD(at[1], at[4]); MULADD(at[2], at[3]); + COMBA_STORE(C->dp[2]); + /* 3 */ + COMBA_FORWARD; + MULADD(at[1], at[5]); MULADD(at[2], at[4]); + COMBA_STORE(C->dp[3]); + /* 4 */ + COMBA_FORWARD; + MULADD(at[2], at[5]); + COMBA_STORE(C->dp[4]); + COMBA_STORE2(C->dp[5]); + C->used = 6; + C->sign = A->sign ^ B->sign; + fp_clamp(C); + COMBA_FINI; + + return FP_OKAY; +} +#endif diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_mul_comba_32.i b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_mul_comba_32.i new file mode 100755 index 0000000..b2ec005 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_mul_comba_32.i @@ -0,0 +1,321 @@ +/* fp_mul_comba_32.i + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifdef TFM_MUL32 +int fp_mul_comba32(fp_int *A, fp_int *B, fp_int *C) +{ + int out_size; + fp_digit c0, c1, c2; +#ifndef WOLFSSL_SMALL_STACK + fp_digit at[64]; +#else + fp_digit *at; +#endif + +#ifdef WOLFSSL_SMALL_STACK + at = (fp_digit*)XMALLOC(sizeof(fp_digit) * 64, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (at == NULL) + return FP_MEM; +#endif + + out_size = A->used + B->used; + XMEMCPY(at, A->dp, 32 * sizeof(fp_digit)); + XMEMCPY(at+32, B->dp, 32 * sizeof(fp_digit)); + COMBA_START; + + COMBA_CLEAR; + /* 0 */ + MULADD(at[0], at[32]); + COMBA_STORE(C->dp[0]); + /* 1 */ + COMBA_FORWARD; + MULADD(at[0], at[33]); MULADD(at[1], at[32]); + COMBA_STORE(C->dp[1]); + /* 2 */ + COMBA_FORWARD; + MULADD(at[0], at[34]); MULADD(at[1], at[33]); MULADD(at[2], at[32]); + COMBA_STORE(C->dp[2]); + /* 3 */ + COMBA_FORWARD; + MULADD(at[0], at[35]); MULADD(at[1], at[34]); MULADD(at[2], at[33]); MULADD(at[3], at[32]); + COMBA_STORE(C->dp[3]); + /* 4 */ + COMBA_FORWARD; + MULADD(at[0], at[36]); MULADD(at[1], at[35]); MULADD(at[2], at[34]); MULADD(at[3], at[33]); MULADD(at[4], at[32]); + COMBA_STORE(C->dp[4]); + /* 5 */ + COMBA_FORWARD; + MULADD(at[0], at[37]); MULADD(at[1], at[36]); MULADD(at[2], at[35]); MULADD(at[3], at[34]); MULADD(at[4], at[33]); MULADD(at[5], at[32]); + COMBA_STORE(C->dp[5]); + /* 6 */ + COMBA_FORWARD; + MULADD(at[0], at[38]); MULADD(at[1], at[37]); MULADD(at[2], at[36]); MULADD(at[3], at[35]); MULADD(at[4], at[34]); MULADD(at[5], at[33]); MULADD(at[6], at[32]); + COMBA_STORE(C->dp[6]); + /* 7 */ + COMBA_FORWARD; + MULADD(at[0], at[39]); MULADD(at[1], at[38]); MULADD(at[2], at[37]); MULADD(at[3], at[36]); MULADD(at[4], at[35]); MULADD(at[5], at[34]); MULADD(at[6], at[33]); MULADD(at[7], at[32]); + COMBA_STORE(C->dp[7]); + /* 8 */ + COMBA_FORWARD; + MULADD(at[0], at[40]); MULADD(at[1], at[39]); MULADD(at[2], at[38]); MULADD(at[3], at[37]); MULADD(at[4], at[36]); MULADD(at[5], at[35]); MULADD(at[6], at[34]); MULADD(at[7], at[33]); MULADD(at[8], at[32]); + COMBA_STORE(C->dp[8]); + /* 9 */ + COMBA_FORWARD; + MULADD(at[0], at[41]); MULADD(at[1], at[40]); MULADD(at[2], at[39]); MULADD(at[3], at[38]); MULADD(at[4], at[37]); MULADD(at[5], at[36]); MULADD(at[6], at[35]); MULADD(at[7], at[34]); MULADD(at[8], at[33]); MULADD(at[9], at[32]); + COMBA_STORE(C->dp[9]); + /* 10 */ + COMBA_FORWARD; + MULADD(at[0], at[42]); MULADD(at[1], at[41]); MULADD(at[2], at[40]); MULADD(at[3], at[39]); MULADD(at[4], at[38]); MULADD(at[5], at[37]); MULADD(at[6], at[36]); MULADD(at[7], at[35]); MULADD(at[8], at[34]); MULADD(at[9], at[33]); MULADD(at[10], at[32]); + COMBA_STORE(C->dp[10]); + /* 11 */ + COMBA_FORWARD; + MULADD(at[0], at[43]); MULADD(at[1], at[42]); MULADD(at[2], at[41]); MULADD(at[3], at[40]); MULADD(at[4], at[39]); MULADD(at[5], at[38]); MULADD(at[6], at[37]); MULADD(at[7], at[36]); MULADD(at[8], at[35]); MULADD(at[9], at[34]); MULADD(at[10], at[33]); MULADD(at[11], at[32]); + COMBA_STORE(C->dp[11]); + /* 12 */ + COMBA_FORWARD; + MULADD(at[0], at[44]); MULADD(at[1], at[43]); MULADD(at[2], at[42]); MULADD(at[3], at[41]); MULADD(at[4], at[40]); MULADD(at[5], at[39]); MULADD(at[6], at[38]); MULADD(at[7], at[37]); MULADD(at[8], at[36]); MULADD(at[9], at[35]); MULADD(at[10], at[34]); MULADD(at[11], at[33]); MULADD(at[12], at[32]); + COMBA_STORE(C->dp[12]); + /* 13 */ + COMBA_FORWARD; + MULADD(at[0], at[45]); MULADD(at[1], at[44]); MULADD(at[2], at[43]); MULADD(at[3], at[42]); MULADD(at[4], at[41]); MULADD(at[5], at[40]); MULADD(at[6], at[39]); MULADD(at[7], at[38]); MULADD(at[8], at[37]); MULADD(at[9], at[36]); MULADD(at[10], at[35]); MULADD(at[11], at[34]); MULADD(at[12], at[33]); MULADD(at[13], at[32]); + COMBA_STORE(C->dp[13]); + /* 14 */ + COMBA_FORWARD; + MULADD(at[0], at[46]); MULADD(at[1], at[45]); MULADD(at[2], at[44]); MULADD(at[3], at[43]); MULADD(at[4], at[42]); MULADD(at[5], at[41]); MULADD(at[6], at[40]); MULADD(at[7], at[39]); MULADD(at[8], at[38]); MULADD(at[9], at[37]); MULADD(at[10], at[36]); MULADD(at[11], at[35]); MULADD(at[12], at[34]); MULADD(at[13], at[33]); MULADD(at[14], at[32]); + COMBA_STORE(C->dp[14]); + /* 15 */ + COMBA_FORWARD; + MULADD(at[0], at[47]); MULADD(at[1], at[46]); MULADD(at[2], at[45]); MULADD(at[3], at[44]); MULADD(at[4], at[43]); MULADD(at[5], at[42]); MULADD(at[6], at[41]); MULADD(at[7], at[40]); MULADD(at[8], at[39]); MULADD(at[9], at[38]); MULADD(at[10], at[37]); MULADD(at[11], at[36]); MULADD(at[12], at[35]); MULADD(at[13], at[34]); MULADD(at[14], at[33]); MULADD(at[15], at[32]); + COMBA_STORE(C->dp[15]); + /* 16 */ + COMBA_FORWARD; + MULADD(at[0], at[48]); MULADD(at[1], at[47]); MULADD(at[2], at[46]); MULADD(at[3], at[45]); MULADD(at[4], at[44]); MULADD(at[5], at[43]); MULADD(at[6], at[42]); MULADD(at[7], at[41]); MULADD(at[8], at[40]); MULADD(at[9], at[39]); MULADD(at[10], at[38]); MULADD(at[11], at[37]); MULADD(at[12], at[36]); MULADD(at[13], at[35]); MULADD(at[14], at[34]); MULADD(at[15], at[33]); MULADD(at[16], at[32]); + COMBA_STORE(C->dp[16]); + /* 17 */ + COMBA_FORWARD; + MULADD(at[0], at[49]); MULADD(at[1], at[48]); MULADD(at[2], at[47]); MULADD(at[3], at[46]); MULADD(at[4], at[45]); MULADD(at[5], at[44]); MULADD(at[6], at[43]); MULADD(at[7], at[42]); MULADD(at[8], at[41]); MULADD(at[9], at[40]); MULADD(at[10], at[39]); MULADD(at[11], at[38]); MULADD(at[12], at[37]); MULADD(at[13], at[36]); MULADD(at[14], at[35]); MULADD(at[15], at[34]); MULADD(at[16], at[33]); MULADD(at[17], at[32]); + COMBA_STORE(C->dp[17]); + /* 18 */ + COMBA_FORWARD; + MULADD(at[0], at[50]); MULADD(at[1], at[49]); MULADD(at[2], at[48]); MULADD(at[3], at[47]); MULADD(at[4], at[46]); MULADD(at[5], at[45]); MULADD(at[6], at[44]); MULADD(at[7], at[43]); MULADD(at[8], at[42]); MULADD(at[9], at[41]); MULADD(at[10], at[40]); MULADD(at[11], at[39]); MULADD(at[12], at[38]); MULADD(at[13], at[37]); MULADD(at[14], at[36]); MULADD(at[15], at[35]); MULADD(at[16], at[34]); MULADD(at[17], at[33]); MULADD(at[18], at[32]); + COMBA_STORE(C->dp[18]); + /* 19 */ + COMBA_FORWARD; + MULADD(at[0], at[51]); MULADD(at[1], at[50]); MULADD(at[2], at[49]); MULADD(at[3], at[48]); MULADD(at[4], at[47]); MULADD(at[5], at[46]); MULADD(at[6], at[45]); MULADD(at[7], at[44]); MULADD(at[8], at[43]); MULADD(at[9], at[42]); MULADD(at[10], at[41]); MULADD(at[11], at[40]); MULADD(at[12], at[39]); MULADD(at[13], at[38]); MULADD(at[14], at[37]); MULADD(at[15], at[36]); MULADD(at[16], at[35]); MULADD(at[17], at[34]); MULADD(at[18], at[33]); MULADD(at[19], at[32]); + COMBA_STORE(C->dp[19]); + /* 20 */ + COMBA_FORWARD; + MULADD(at[0], at[52]); MULADD(at[1], at[51]); MULADD(at[2], at[50]); MULADD(at[3], at[49]); MULADD(at[4], at[48]); MULADD(at[5], at[47]); MULADD(at[6], at[46]); MULADD(at[7], at[45]); MULADD(at[8], at[44]); MULADD(at[9], at[43]); MULADD(at[10], at[42]); MULADD(at[11], at[41]); MULADD(at[12], at[40]); MULADD(at[13], at[39]); MULADD(at[14], at[38]); MULADD(at[15], at[37]); MULADD(at[16], at[36]); MULADD(at[17], at[35]); MULADD(at[18], at[34]); MULADD(at[19], at[33]); MULADD(at[20], at[32]); + COMBA_STORE(C->dp[20]); + /* 21 */ + COMBA_FORWARD; + MULADD(at[0], at[53]); MULADD(at[1], at[52]); MULADD(at[2], at[51]); MULADD(at[3], at[50]); MULADD(at[4], at[49]); MULADD(at[5], at[48]); MULADD(at[6], at[47]); MULADD(at[7], at[46]); MULADD(at[8], at[45]); MULADD(at[9], at[44]); MULADD(at[10], at[43]); MULADD(at[11], at[42]); MULADD(at[12], at[41]); MULADD(at[13], at[40]); MULADD(at[14], at[39]); MULADD(at[15], at[38]); MULADD(at[16], at[37]); MULADD(at[17], at[36]); MULADD(at[18], at[35]); MULADD(at[19], at[34]); MULADD(at[20], at[33]); MULADD(at[21], at[32]); + COMBA_STORE(C->dp[21]); + /* 22 */ + COMBA_FORWARD; + MULADD(at[0], at[54]); MULADD(at[1], at[53]); MULADD(at[2], at[52]); MULADD(at[3], at[51]); MULADD(at[4], at[50]); MULADD(at[5], at[49]); MULADD(at[6], at[48]); MULADD(at[7], at[47]); MULADD(at[8], at[46]); MULADD(at[9], at[45]); MULADD(at[10], at[44]); MULADD(at[11], at[43]); MULADD(at[12], at[42]); MULADD(at[13], at[41]); MULADD(at[14], at[40]); MULADD(at[15], at[39]); MULADD(at[16], at[38]); MULADD(at[17], at[37]); MULADD(at[18], at[36]); MULADD(at[19], at[35]); MULADD(at[20], at[34]); MULADD(at[21], at[33]); MULADD(at[22], at[32]); + COMBA_STORE(C->dp[22]); + /* 23 */ + COMBA_FORWARD; + MULADD(at[0], at[55]); MULADD(at[1], at[54]); MULADD(at[2], at[53]); MULADD(at[3], at[52]); MULADD(at[4], at[51]); MULADD(at[5], at[50]); MULADD(at[6], at[49]); MULADD(at[7], at[48]); MULADD(at[8], at[47]); MULADD(at[9], at[46]); MULADD(at[10], at[45]); MULADD(at[11], at[44]); MULADD(at[12], at[43]); MULADD(at[13], at[42]); MULADD(at[14], at[41]); MULADD(at[15], at[40]); MULADD(at[16], at[39]); MULADD(at[17], at[38]); MULADD(at[18], at[37]); MULADD(at[19], at[36]); MULADD(at[20], at[35]); MULADD(at[21], at[34]); MULADD(at[22], at[33]); MULADD(at[23], at[32]); + COMBA_STORE(C->dp[23]); + /* 24 */ + COMBA_FORWARD; + MULADD(at[0], at[56]); MULADD(at[1], at[55]); MULADD(at[2], at[54]); MULADD(at[3], at[53]); MULADD(at[4], at[52]); MULADD(at[5], at[51]); MULADD(at[6], at[50]); MULADD(at[7], at[49]); MULADD(at[8], at[48]); MULADD(at[9], at[47]); MULADD(at[10], at[46]); MULADD(at[11], at[45]); MULADD(at[12], at[44]); MULADD(at[13], at[43]); MULADD(at[14], at[42]); MULADD(at[15], at[41]); MULADD(at[16], at[40]); MULADD(at[17], at[39]); MULADD(at[18], at[38]); MULADD(at[19], at[37]); MULADD(at[20], at[36]); MULADD(at[21], at[35]); MULADD(at[22], at[34]); MULADD(at[23], at[33]); MULADD(at[24], at[32]); + COMBA_STORE(C->dp[24]); + /* 25 */ + COMBA_FORWARD; + MULADD(at[0], at[57]); MULADD(at[1], at[56]); MULADD(at[2], at[55]); MULADD(at[3], at[54]); MULADD(at[4], at[53]); MULADD(at[5], at[52]); MULADD(at[6], at[51]); MULADD(at[7], at[50]); MULADD(at[8], at[49]); MULADD(at[9], at[48]); MULADD(at[10], at[47]); MULADD(at[11], at[46]); MULADD(at[12], at[45]); MULADD(at[13], at[44]); MULADD(at[14], at[43]); MULADD(at[15], at[42]); MULADD(at[16], at[41]); MULADD(at[17], at[40]); MULADD(at[18], at[39]); MULADD(at[19], at[38]); MULADD(at[20], at[37]); MULADD(at[21], at[36]); MULADD(at[22], at[35]); MULADD(at[23], at[34]); MULADD(at[24], at[33]); MULADD(at[25], at[32]); + COMBA_STORE(C->dp[25]); + /* 26 */ + COMBA_FORWARD; + MULADD(at[0], at[58]); MULADD(at[1], at[57]); MULADD(at[2], at[56]); MULADD(at[3], at[55]); MULADD(at[4], at[54]); MULADD(at[5], at[53]); MULADD(at[6], at[52]); MULADD(at[7], at[51]); MULADD(at[8], at[50]); MULADD(at[9], at[49]); MULADD(at[10], at[48]); MULADD(at[11], at[47]); MULADD(at[12], at[46]); MULADD(at[13], at[45]); MULADD(at[14], at[44]); MULADD(at[15], at[43]); MULADD(at[16], at[42]); MULADD(at[17], at[41]); MULADD(at[18], at[40]); MULADD(at[19], at[39]); MULADD(at[20], at[38]); MULADD(at[21], at[37]); MULADD(at[22], at[36]); MULADD(at[23], at[35]); MULADD(at[24], at[34]); MULADD(at[25], at[33]); MULADD(at[26], at[32]); + COMBA_STORE(C->dp[26]); + /* 27 */ + COMBA_FORWARD; + MULADD(at[0], at[59]); MULADD(at[1], at[58]); MULADD(at[2], at[57]); MULADD(at[3], at[56]); MULADD(at[4], at[55]); MULADD(at[5], at[54]); MULADD(at[6], at[53]); MULADD(at[7], at[52]); MULADD(at[8], at[51]); MULADD(at[9], at[50]); MULADD(at[10], at[49]); MULADD(at[11], at[48]); MULADD(at[12], at[47]); MULADD(at[13], at[46]); MULADD(at[14], at[45]); MULADD(at[15], at[44]); MULADD(at[16], at[43]); MULADD(at[17], at[42]); MULADD(at[18], at[41]); MULADD(at[19], at[40]); MULADD(at[20], at[39]); MULADD(at[21], at[38]); MULADD(at[22], at[37]); MULADD(at[23], at[36]); MULADD(at[24], at[35]); MULADD(at[25], at[34]); MULADD(at[26], at[33]); MULADD(at[27], at[32]); + COMBA_STORE(C->dp[27]); + /* 28 */ + COMBA_FORWARD; + MULADD(at[0], at[60]); MULADD(at[1], at[59]); MULADD(at[2], at[58]); MULADD(at[3], at[57]); MULADD(at[4], at[56]); MULADD(at[5], at[55]); MULADD(at[6], at[54]); MULADD(at[7], at[53]); MULADD(at[8], at[52]); MULADD(at[9], at[51]); MULADD(at[10], at[50]); MULADD(at[11], at[49]); MULADD(at[12], at[48]); MULADD(at[13], at[47]); MULADD(at[14], at[46]); MULADD(at[15], at[45]); MULADD(at[16], at[44]); MULADD(at[17], at[43]); MULADD(at[18], at[42]); MULADD(at[19], at[41]); MULADD(at[20], at[40]); MULADD(at[21], at[39]); MULADD(at[22], at[38]); MULADD(at[23], at[37]); MULADD(at[24], at[36]); MULADD(at[25], at[35]); MULADD(at[26], at[34]); MULADD(at[27], at[33]); MULADD(at[28], at[32]); + COMBA_STORE(C->dp[28]); + /* 29 */ + COMBA_FORWARD; + MULADD(at[0], at[61]); MULADD(at[1], at[60]); MULADD(at[2], at[59]); MULADD(at[3], at[58]); MULADD(at[4], at[57]); MULADD(at[5], at[56]); MULADD(at[6], at[55]); MULADD(at[7], at[54]); MULADD(at[8], at[53]); MULADD(at[9], at[52]); MULADD(at[10], at[51]); MULADD(at[11], at[50]); MULADD(at[12], at[49]); MULADD(at[13], at[48]); MULADD(at[14], at[47]); MULADD(at[15], at[46]); MULADD(at[16], at[45]); MULADD(at[17], at[44]); MULADD(at[18], at[43]); MULADD(at[19], at[42]); MULADD(at[20], at[41]); MULADD(at[21], at[40]); MULADD(at[22], at[39]); MULADD(at[23], at[38]); MULADD(at[24], at[37]); MULADD(at[25], at[36]); MULADD(at[26], at[35]); MULADD(at[27], at[34]); MULADD(at[28], at[33]); MULADD(at[29], at[32]); + COMBA_STORE(C->dp[29]); + /* 30 */ + COMBA_FORWARD; + MULADD(at[0], at[62]); MULADD(at[1], at[61]); MULADD(at[2], at[60]); MULADD(at[3], at[59]); MULADD(at[4], at[58]); MULADD(at[5], at[57]); MULADD(at[6], at[56]); MULADD(at[7], at[55]); MULADD(at[8], at[54]); MULADD(at[9], at[53]); MULADD(at[10], at[52]); MULADD(at[11], at[51]); MULADD(at[12], at[50]); MULADD(at[13], at[49]); MULADD(at[14], at[48]); MULADD(at[15], at[47]); MULADD(at[16], at[46]); MULADD(at[17], at[45]); MULADD(at[18], at[44]); MULADD(at[19], at[43]); MULADD(at[20], at[42]); MULADD(at[21], at[41]); MULADD(at[22], at[40]); MULADD(at[23], at[39]); MULADD(at[24], at[38]); MULADD(at[25], at[37]); MULADD(at[26], at[36]); MULADD(at[27], at[35]); MULADD(at[28], at[34]); MULADD(at[29], at[33]); MULADD(at[30], at[32]); + COMBA_STORE(C->dp[30]); + /* 31 */ + COMBA_FORWARD; + MULADD(at[0], at[63]); MULADD(at[1], at[62]); MULADD(at[2], at[61]); MULADD(at[3], at[60]); MULADD(at[4], at[59]); MULADD(at[5], at[58]); MULADD(at[6], at[57]); MULADD(at[7], at[56]); MULADD(at[8], at[55]); MULADD(at[9], at[54]); MULADD(at[10], at[53]); MULADD(at[11], at[52]); MULADD(at[12], at[51]); MULADD(at[13], at[50]); MULADD(at[14], at[49]); MULADD(at[15], at[48]); MULADD(at[16], at[47]); MULADD(at[17], at[46]); MULADD(at[18], at[45]); MULADD(at[19], at[44]); MULADD(at[20], at[43]); MULADD(at[21], at[42]); MULADD(at[22], at[41]); MULADD(at[23], at[40]); MULADD(at[24], at[39]); MULADD(at[25], at[38]); MULADD(at[26], at[37]); MULADD(at[27], at[36]); MULADD(at[28], at[35]); MULADD(at[29], at[34]); MULADD(at[30], at[33]); MULADD(at[31], at[32]); + COMBA_STORE(C->dp[31]); + /* 32 */ + COMBA_FORWARD; + MULADD(at[1], at[63]); MULADD(at[2], at[62]); MULADD(at[3], at[61]); MULADD(at[4], at[60]); MULADD(at[5], at[59]); MULADD(at[6], at[58]); MULADD(at[7], at[57]); MULADD(at[8], at[56]); MULADD(at[9], at[55]); MULADD(at[10], at[54]); MULADD(at[11], at[53]); MULADD(at[12], at[52]); MULADD(at[13], at[51]); MULADD(at[14], at[50]); MULADD(at[15], at[49]); MULADD(at[16], at[48]); MULADD(at[17], at[47]); MULADD(at[18], at[46]); MULADD(at[19], at[45]); MULADD(at[20], at[44]); MULADD(at[21], at[43]); MULADD(at[22], at[42]); MULADD(at[23], at[41]); MULADD(at[24], at[40]); MULADD(at[25], at[39]); MULADD(at[26], at[38]); MULADD(at[27], at[37]); MULADD(at[28], at[36]); MULADD(at[29], at[35]); MULADD(at[30], at[34]); MULADD(at[31], at[33]); + COMBA_STORE(C->dp[32]); + /* 33 */ + COMBA_FORWARD; + MULADD(at[2], at[63]); MULADD(at[3], at[62]); MULADD(at[4], at[61]); MULADD(at[5], at[60]); MULADD(at[6], at[59]); MULADD(at[7], at[58]); MULADD(at[8], at[57]); MULADD(at[9], at[56]); MULADD(at[10], at[55]); MULADD(at[11], at[54]); MULADD(at[12], at[53]); MULADD(at[13], at[52]); MULADD(at[14], at[51]); MULADD(at[15], at[50]); MULADD(at[16], at[49]); MULADD(at[17], at[48]); MULADD(at[18], at[47]); MULADD(at[19], at[46]); MULADD(at[20], at[45]); MULADD(at[21], at[44]); MULADD(at[22], at[43]); MULADD(at[23], at[42]); MULADD(at[24], at[41]); MULADD(at[25], at[40]); MULADD(at[26], at[39]); MULADD(at[27], at[38]); MULADD(at[28], at[37]); MULADD(at[29], at[36]); MULADD(at[30], at[35]); MULADD(at[31], at[34]); + COMBA_STORE(C->dp[33]); + /* 34 */ + COMBA_FORWARD; + MULADD(at[3], at[63]); MULADD(at[4], at[62]); MULADD(at[5], at[61]); MULADD(at[6], at[60]); MULADD(at[7], at[59]); MULADD(at[8], at[58]); MULADD(at[9], at[57]); MULADD(at[10], at[56]); MULADD(at[11], at[55]); MULADD(at[12], at[54]); MULADD(at[13], at[53]); MULADD(at[14], at[52]); MULADD(at[15], at[51]); MULADD(at[16], at[50]); MULADD(at[17], at[49]); MULADD(at[18], at[48]); MULADD(at[19], at[47]); MULADD(at[20], at[46]); MULADD(at[21], at[45]); MULADD(at[22], at[44]); MULADD(at[23], at[43]); MULADD(at[24], at[42]); MULADD(at[25], at[41]); MULADD(at[26], at[40]); MULADD(at[27], at[39]); MULADD(at[28], at[38]); MULADD(at[29], at[37]); MULADD(at[30], at[36]); MULADD(at[31], at[35]); + COMBA_STORE(C->dp[34]); + /* 35 */ + COMBA_FORWARD; + MULADD(at[4], at[63]); MULADD(at[5], at[62]); MULADD(at[6], at[61]); MULADD(at[7], at[60]); MULADD(at[8], at[59]); MULADD(at[9], at[58]); MULADD(at[10], at[57]); MULADD(at[11], at[56]); MULADD(at[12], at[55]); MULADD(at[13], at[54]); MULADD(at[14], at[53]); MULADD(at[15], at[52]); MULADD(at[16], at[51]); MULADD(at[17], at[50]); MULADD(at[18], at[49]); MULADD(at[19], at[48]); MULADD(at[20], at[47]); MULADD(at[21], at[46]); MULADD(at[22], at[45]); MULADD(at[23], at[44]); MULADD(at[24], at[43]); MULADD(at[25], at[42]); MULADD(at[26], at[41]); MULADD(at[27], at[40]); MULADD(at[28], at[39]); MULADD(at[29], at[38]); MULADD(at[30], at[37]); MULADD(at[31], at[36]); + COMBA_STORE(C->dp[35]); + /* 36 */ + COMBA_FORWARD; + MULADD(at[5], at[63]); MULADD(at[6], at[62]); MULADD(at[7], at[61]); MULADD(at[8], at[60]); MULADD(at[9], at[59]); MULADD(at[10], at[58]); MULADD(at[11], at[57]); MULADD(at[12], at[56]); MULADD(at[13], at[55]); MULADD(at[14], at[54]); MULADD(at[15], at[53]); MULADD(at[16], at[52]); MULADD(at[17], at[51]); MULADD(at[18], at[50]); MULADD(at[19], at[49]); MULADD(at[20], at[48]); MULADD(at[21], at[47]); MULADD(at[22], at[46]); MULADD(at[23], at[45]); MULADD(at[24], at[44]); MULADD(at[25], at[43]); MULADD(at[26], at[42]); MULADD(at[27], at[41]); MULADD(at[28], at[40]); MULADD(at[29], at[39]); MULADD(at[30], at[38]); MULADD(at[31], at[37]); + COMBA_STORE(C->dp[36]); + /* 37 */ + COMBA_FORWARD; + MULADD(at[6], at[63]); MULADD(at[7], at[62]); MULADD(at[8], at[61]); MULADD(at[9], at[60]); MULADD(at[10], at[59]); MULADD(at[11], at[58]); MULADD(at[12], at[57]); MULADD(at[13], at[56]); MULADD(at[14], at[55]); MULADD(at[15], at[54]); MULADD(at[16], at[53]); MULADD(at[17], at[52]); MULADD(at[18], at[51]); MULADD(at[19], at[50]); MULADD(at[20], at[49]); MULADD(at[21], at[48]); MULADD(at[22], at[47]); MULADD(at[23], at[46]); MULADD(at[24], at[45]); MULADD(at[25], at[44]); MULADD(at[26], at[43]); MULADD(at[27], at[42]); MULADD(at[28], at[41]); MULADD(at[29], at[40]); MULADD(at[30], at[39]); MULADD(at[31], at[38]); + COMBA_STORE(C->dp[37]); + /* 38 */ + COMBA_FORWARD; + MULADD(at[7], at[63]); MULADD(at[8], at[62]); MULADD(at[9], at[61]); MULADD(at[10], at[60]); MULADD(at[11], at[59]); MULADD(at[12], at[58]); MULADD(at[13], at[57]); MULADD(at[14], at[56]); MULADD(at[15], at[55]); MULADD(at[16], at[54]); MULADD(at[17], at[53]); MULADD(at[18], at[52]); MULADD(at[19], at[51]); MULADD(at[20], at[50]); MULADD(at[21], at[49]); MULADD(at[22], at[48]); MULADD(at[23], at[47]); MULADD(at[24], at[46]); MULADD(at[25], at[45]); MULADD(at[26], at[44]); MULADD(at[27], at[43]); MULADD(at[28], at[42]); MULADD(at[29], at[41]); MULADD(at[30], at[40]); MULADD(at[31], at[39]); + COMBA_STORE(C->dp[38]); + + /* early out at 40 digits, 40*32==1280, or two 640 bit operands */ + if (out_size <= 40) { COMBA_STORE2(C->dp[39]); C->used = 40; C->sign = A->sign ^ B->sign; fp_clamp(C); COMBA_FINI; return FP_OKAY; } + + /* 39 */ + COMBA_FORWARD; + MULADD(at[8], at[63]); MULADD(at[9], at[62]); MULADD(at[10], at[61]); MULADD(at[11], at[60]); MULADD(at[12], at[59]); MULADD(at[13], at[58]); MULADD(at[14], at[57]); MULADD(at[15], at[56]); MULADD(at[16], at[55]); MULADD(at[17], at[54]); MULADD(at[18], at[53]); MULADD(at[19], at[52]); MULADD(at[20], at[51]); MULADD(at[21], at[50]); MULADD(at[22], at[49]); MULADD(at[23], at[48]); MULADD(at[24], at[47]); MULADD(at[25], at[46]); MULADD(at[26], at[45]); MULADD(at[27], at[44]); MULADD(at[28], at[43]); MULADD(at[29], at[42]); MULADD(at[30], at[41]); MULADD(at[31], at[40]); + COMBA_STORE(C->dp[39]); + /* 40 */ + COMBA_FORWARD; + MULADD(at[9], at[63]); MULADD(at[10], at[62]); MULADD(at[11], at[61]); MULADD(at[12], at[60]); MULADD(at[13], at[59]); MULADD(at[14], at[58]); MULADD(at[15], at[57]); MULADD(at[16], at[56]); MULADD(at[17], at[55]); MULADD(at[18], at[54]); MULADD(at[19], at[53]); MULADD(at[20], at[52]); MULADD(at[21], at[51]); MULADD(at[22], at[50]); MULADD(at[23], at[49]); MULADD(at[24], at[48]); MULADD(at[25], at[47]); MULADD(at[26], at[46]); MULADD(at[27], at[45]); MULADD(at[28], at[44]); MULADD(at[29], at[43]); MULADD(at[30], at[42]); MULADD(at[31], at[41]); + COMBA_STORE(C->dp[40]); + /* 41 */ + COMBA_FORWARD; + MULADD(at[10], at[63]); MULADD(at[11], at[62]); MULADD(at[12], at[61]); MULADD(at[13], at[60]); MULADD(at[14], at[59]); MULADD(at[15], at[58]); MULADD(at[16], at[57]); MULADD(at[17], at[56]); MULADD(at[18], at[55]); MULADD(at[19], at[54]); MULADD(at[20], at[53]); MULADD(at[21], at[52]); MULADD(at[22], at[51]); MULADD(at[23], at[50]); MULADD(at[24], at[49]); MULADD(at[25], at[48]); MULADD(at[26], at[47]); MULADD(at[27], at[46]); MULADD(at[28], at[45]); MULADD(at[29], at[44]); MULADD(at[30], at[43]); MULADD(at[31], at[42]); + COMBA_STORE(C->dp[41]); + /* 42 */ + COMBA_FORWARD; + MULADD(at[11], at[63]); MULADD(at[12], at[62]); MULADD(at[13], at[61]); MULADD(at[14], at[60]); MULADD(at[15], at[59]); MULADD(at[16], at[58]); MULADD(at[17], at[57]); MULADD(at[18], at[56]); MULADD(at[19], at[55]); MULADD(at[20], at[54]); MULADD(at[21], at[53]); MULADD(at[22], at[52]); MULADD(at[23], at[51]); MULADD(at[24], at[50]); MULADD(at[25], at[49]); MULADD(at[26], at[48]); MULADD(at[27], at[47]); MULADD(at[28], at[46]); MULADD(at[29], at[45]); MULADD(at[30], at[44]); MULADD(at[31], at[43]); + COMBA_STORE(C->dp[42]); + /* 43 */ + COMBA_FORWARD; + MULADD(at[12], at[63]); MULADD(at[13], at[62]); MULADD(at[14], at[61]); MULADD(at[15], at[60]); MULADD(at[16], at[59]); MULADD(at[17], at[58]); MULADD(at[18], at[57]); MULADD(at[19], at[56]); MULADD(at[20], at[55]); MULADD(at[21], at[54]); MULADD(at[22], at[53]); MULADD(at[23], at[52]); MULADD(at[24], at[51]); MULADD(at[25], at[50]); MULADD(at[26], at[49]); MULADD(at[27], at[48]); MULADD(at[28], at[47]); MULADD(at[29], at[46]); MULADD(at[30], at[45]); MULADD(at[31], at[44]); + COMBA_STORE(C->dp[43]); + /* 44 */ + COMBA_FORWARD; + MULADD(at[13], at[63]); MULADD(at[14], at[62]); MULADD(at[15], at[61]); MULADD(at[16], at[60]); MULADD(at[17], at[59]); MULADD(at[18], at[58]); MULADD(at[19], at[57]); MULADD(at[20], at[56]); MULADD(at[21], at[55]); MULADD(at[22], at[54]); MULADD(at[23], at[53]); MULADD(at[24], at[52]); MULADD(at[25], at[51]); MULADD(at[26], at[50]); MULADD(at[27], at[49]); MULADD(at[28], at[48]); MULADD(at[29], at[47]); MULADD(at[30], at[46]); MULADD(at[31], at[45]); + COMBA_STORE(C->dp[44]); + /* 45 */ + COMBA_FORWARD; + MULADD(at[14], at[63]); MULADD(at[15], at[62]); MULADD(at[16], at[61]); MULADD(at[17], at[60]); MULADD(at[18], at[59]); MULADD(at[19], at[58]); MULADD(at[20], at[57]); MULADD(at[21], at[56]); MULADD(at[22], at[55]); MULADD(at[23], at[54]); MULADD(at[24], at[53]); MULADD(at[25], at[52]); MULADD(at[26], at[51]); MULADD(at[27], at[50]); MULADD(at[28], at[49]); MULADD(at[29], at[48]); MULADD(at[30], at[47]); MULADD(at[31], at[46]); + COMBA_STORE(C->dp[45]); + /* 46 */ + COMBA_FORWARD; + MULADD(at[15], at[63]); MULADD(at[16], at[62]); MULADD(at[17], at[61]); MULADD(at[18], at[60]); MULADD(at[19], at[59]); MULADD(at[20], at[58]); MULADD(at[21], at[57]); MULADD(at[22], at[56]); MULADD(at[23], at[55]); MULADD(at[24], at[54]); MULADD(at[25], at[53]); MULADD(at[26], at[52]); MULADD(at[27], at[51]); MULADD(at[28], at[50]); MULADD(at[29], at[49]); MULADD(at[30], at[48]); MULADD(at[31], at[47]); + COMBA_STORE(C->dp[46]); + + /* early out at 48 digits, 48*32==1536, or two 768 bit operands */ + if (out_size <= 48) { COMBA_STORE2(C->dp[47]); C->used = 48; C->sign = A->sign ^ B->sign; fp_clamp(C); COMBA_FINI; return FP_OKAY; } + + /* 47 */ + COMBA_FORWARD; + MULADD(at[16], at[63]); MULADD(at[17], at[62]); MULADD(at[18], at[61]); MULADD(at[19], at[60]); MULADD(at[20], at[59]); MULADD(at[21], at[58]); MULADD(at[22], at[57]); MULADD(at[23], at[56]); MULADD(at[24], at[55]); MULADD(at[25], at[54]); MULADD(at[26], at[53]); MULADD(at[27], at[52]); MULADD(at[28], at[51]); MULADD(at[29], at[50]); MULADD(at[30], at[49]); MULADD(at[31], at[48]); + COMBA_STORE(C->dp[47]); + /* 48 */ + COMBA_FORWARD; + MULADD(at[17], at[63]); MULADD(at[18], at[62]); MULADD(at[19], at[61]); MULADD(at[20], at[60]); MULADD(at[21], at[59]); MULADD(at[22], at[58]); MULADD(at[23], at[57]); MULADD(at[24], at[56]); MULADD(at[25], at[55]); MULADD(at[26], at[54]); MULADD(at[27], at[53]); MULADD(at[28], at[52]); MULADD(at[29], at[51]); MULADD(at[30], at[50]); MULADD(at[31], at[49]); + COMBA_STORE(C->dp[48]); + /* 49 */ + COMBA_FORWARD; + MULADD(at[18], at[63]); MULADD(at[19], at[62]); MULADD(at[20], at[61]); MULADD(at[21], at[60]); MULADD(at[22], at[59]); MULADD(at[23], at[58]); MULADD(at[24], at[57]); MULADD(at[25], at[56]); MULADD(at[26], at[55]); MULADD(at[27], at[54]); MULADD(at[28], at[53]); MULADD(at[29], at[52]); MULADD(at[30], at[51]); MULADD(at[31], at[50]); + COMBA_STORE(C->dp[49]); + /* 50 */ + COMBA_FORWARD; + MULADD(at[19], at[63]); MULADD(at[20], at[62]); MULADD(at[21], at[61]); MULADD(at[22], at[60]); MULADD(at[23], at[59]); MULADD(at[24], at[58]); MULADD(at[25], at[57]); MULADD(at[26], at[56]); MULADD(at[27], at[55]); MULADD(at[28], at[54]); MULADD(at[29], at[53]); MULADD(at[30], at[52]); MULADD(at[31], at[51]); + COMBA_STORE(C->dp[50]); + /* 51 */ + COMBA_FORWARD; + MULADD(at[20], at[63]); MULADD(at[21], at[62]); MULADD(at[22], at[61]); MULADD(at[23], at[60]); MULADD(at[24], at[59]); MULADD(at[25], at[58]); MULADD(at[26], at[57]); MULADD(at[27], at[56]); MULADD(at[28], at[55]); MULADD(at[29], at[54]); MULADD(at[30], at[53]); MULADD(at[31], at[52]); + COMBA_STORE(C->dp[51]); + /* 52 */ + COMBA_FORWARD; + MULADD(at[21], at[63]); MULADD(at[22], at[62]); MULADD(at[23], at[61]); MULADD(at[24], at[60]); MULADD(at[25], at[59]); MULADD(at[26], at[58]); MULADD(at[27], at[57]); MULADD(at[28], at[56]); MULADD(at[29], at[55]); MULADD(at[30], at[54]); MULADD(at[31], at[53]); + COMBA_STORE(C->dp[52]); + /* 53 */ + COMBA_FORWARD; + MULADD(at[22], at[63]); MULADD(at[23], at[62]); MULADD(at[24], at[61]); MULADD(at[25], at[60]); MULADD(at[26], at[59]); MULADD(at[27], at[58]); MULADD(at[28], at[57]); MULADD(at[29], at[56]); MULADD(at[30], at[55]); MULADD(at[31], at[54]); + COMBA_STORE(C->dp[53]); + /* 54 */ + COMBA_FORWARD; + MULADD(at[23], at[63]); MULADD(at[24], at[62]); MULADD(at[25], at[61]); MULADD(at[26], at[60]); MULADD(at[27], at[59]); MULADD(at[28], at[58]); MULADD(at[29], at[57]); MULADD(at[30], at[56]); MULADD(at[31], at[55]); + COMBA_STORE(C->dp[54]); + + /* early out at 56 digits, 56*32==1792, or two 896 bit operands */ + if (out_size <= 56) { COMBA_STORE2(C->dp[55]); C->used = 56; C->sign = A->sign ^ B->sign; fp_clamp(C); COMBA_FINI; return FP_OKAY; } + + /* 55 */ + COMBA_FORWARD; + MULADD(at[24], at[63]); MULADD(at[25], at[62]); MULADD(at[26], at[61]); MULADD(at[27], at[60]); MULADD(at[28], at[59]); MULADD(at[29], at[58]); MULADD(at[30], at[57]); MULADD(at[31], at[56]); + COMBA_STORE(C->dp[55]); + /* 56 */ + COMBA_FORWARD; + MULADD(at[25], at[63]); MULADD(at[26], at[62]); MULADD(at[27], at[61]); MULADD(at[28], at[60]); MULADD(at[29], at[59]); MULADD(at[30], at[58]); MULADD(at[31], at[57]); + COMBA_STORE(C->dp[56]); + /* 57 */ + COMBA_FORWARD; + MULADD(at[26], at[63]); MULADD(at[27], at[62]); MULADD(at[28], at[61]); MULADD(at[29], at[60]); MULADD(at[30], at[59]); MULADD(at[31], at[58]); + COMBA_STORE(C->dp[57]); + /* 58 */ + COMBA_FORWARD; + MULADD(at[27], at[63]); MULADD(at[28], at[62]); MULADD(at[29], at[61]); MULADD(at[30], at[60]); MULADD(at[31], at[59]); + COMBA_STORE(C->dp[58]); + /* 59 */ + COMBA_FORWARD; + MULADD(at[28], at[63]); MULADD(at[29], at[62]); MULADD(at[30], at[61]); MULADD(at[31], at[60]); + COMBA_STORE(C->dp[59]); + /* 60 */ + COMBA_FORWARD; + MULADD(at[29], at[63]); MULADD(at[30], at[62]); MULADD(at[31], at[61]); + COMBA_STORE(C->dp[60]); + /* 61 */ + COMBA_FORWARD; + MULADD(at[30], at[63]); MULADD(at[31], at[62]); + COMBA_STORE(C->dp[61]); + /* 62 */ + COMBA_FORWARD; + MULADD(at[31], at[63]); + COMBA_STORE(C->dp[62]); + COMBA_STORE2(C->dp[63]); + C->used = 64; + C->sign = A->sign ^ B->sign; + fp_clamp(C); + COMBA_FINI; + +#ifdef WOLFSSL_SMALL_STACK + XFREE(at, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; +} +#endif diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_mul_comba_4.i b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_mul_comba_4.i new file mode 100755 index 0000000..6c4643a --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_mul_comba_4.i @@ -0,0 +1,83 @@ +/* fp_mul_comba_4.i + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifdef TFM_MUL4 +int fp_mul_comba4(fp_int *A, fp_int *B, fp_int *C) +{ + fp_digit c0, c1, c2; +#ifndef WOLFSSL_SMALL_STACK + fp_digit at[8]; +#else + fp_digit *at; +#endif + +#ifdef WOLFSSL_SMALL_STACK + at = (fp_digit*)XMALLOC(sizeof(fp_digit) * 8, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (at == NULL) + return FP_MEM; +#endif + + XMEMCPY(at, A->dp, 4 * sizeof(fp_digit)); + XMEMCPY(at+4, B->dp, 4 * sizeof(fp_digit)); + COMBA_START; + + COMBA_CLEAR; + /* 0 */ + MULADD(at[0], at[4]); + COMBA_STORE(C->dp[0]); + /* 1 */ + COMBA_FORWARD; + MULADD(at[0], at[5]); MULADD(at[1], at[4]); + COMBA_STORE(C->dp[1]); + /* 2 */ + COMBA_FORWARD; + MULADD(at[0], at[6]); MULADD(at[1], at[5]); MULADD(at[2], at[4]); + COMBA_STORE(C->dp[2]); + /* 3 */ + COMBA_FORWARD; + MULADD(at[0], at[7]); MULADD(at[1], at[6]); MULADD(at[2], at[5]); MULADD(at[3], at[4]); + COMBA_STORE(C->dp[3]); + /* 4 */ + COMBA_FORWARD; + MULADD(at[1], at[7]); MULADD(at[2], at[6]); MULADD(at[3], at[5]); + COMBA_STORE(C->dp[4]); + /* 5 */ + COMBA_FORWARD; + MULADD(at[2], at[7]); MULADD(at[3], at[6]); + COMBA_STORE(C->dp[5]); + /* 6 */ + COMBA_FORWARD; + MULADD(at[3], at[7]); + COMBA_STORE(C->dp[6]); + COMBA_STORE2(C->dp[7]); + C->used = 8; + C->sign = A->sign ^ B->sign; + fp_clamp(C); + COMBA_FINI; + +#ifdef WOLFSSL_SMALL_STACK + XFREE(at, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; +} +#endif diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_mul_comba_48.i b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_mul_comba_48.i new file mode 100755 index 0000000..8a7a010 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_mul_comba_48.i @@ -0,0 +1,435 @@ +/* fp_mul_comba_48.i + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifdef TFM_MUL48 +int fp_mul_comba48(fp_int *A, fp_int *B, fp_int *C) +{ + fp_digit c0, c1, c2; +#ifndef WOLFSSL_SMALL_STACK + fp_digit at[96]; +#else + fp_digit *at; +#endif + +#ifdef WOLFSSL_SMALL_STACK + at = (fp_digit*)XMALLOC(sizeof(fp_digit) * 96, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (at == NULL) + return FP_MEM; +#endif + + XMEMCPY(at, A->dp, 48 * sizeof(fp_digit)); + XMEMCPY(at+48, B->dp, 48 * sizeof(fp_digit)); + COMBA_START; + + COMBA_CLEAR; + /* 0 */ + MULADD(at[0], at[48]); + COMBA_STORE(C->dp[0]); + /* 1 */ + COMBA_FORWARD; + MULADD(at[0], at[49]); MULADD(at[1], at[48]); + COMBA_STORE(C->dp[1]); + /* 2 */ + COMBA_FORWARD; + MULADD(at[0], at[50]); MULADD(at[1], at[49]); MULADD(at[2], at[48]); + COMBA_STORE(C->dp[2]); + /* 3 */ + COMBA_FORWARD; + MULADD(at[0], at[51]); MULADD(at[1], at[50]); MULADD(at[2], at[49]); MULADD(at[3], at[48]); + COMBA_STORE(C->dp[3]); + /* 4 */ + COMBA_FORWARD; + MULADD(at[0], at[52]); MULADD(at[1], at[51]); MULADD(at[2], at[50]); MULADD(at[3], at[49]); MULADD(at[4], at[48]); + COMBA_STORE(C->dp[4]); + /* 5 */ + COMBA_FORWARD; + MULADD(at[0], at[53]); MULADD(at[1], at[52]); MULADD(at[2], at[51]); MULADD(at[3], at[50]); MULADD(at[4], at[49]); MULADD(at[5], at[48]); + COMBA_STORE(C->dp[5]); + /* 6 */ + COMBA_FORWARD; + MULADD(at[0], at[54]); MULADD(at[1], at[53]); MULADD(at[2], at[52]); MULADD(at[3], at[51]); MULADD(at[4], at[50]); MULADD(at[5], at[49]); MULADD(at[6], at[48]); + COMBA_STORE(C->dp[6]); + /* 7 */ + COMBA_FORWARD; + MULADD(at[0], at[55]); MULADD(at[1], at[54]); MULADD(at[2], at[53]); MULADD(at[3], at[52]); MULADD(at[4], at[51]); MULADD(at[5], at[50]); MULADD(at[6], at[49]); MULADD(at[7], at[48]); + COMBA_STORE(C->dp[7]); + /* 8 */ + COMBA_FORWARD; + MULADD(at[0], at[56]); MULADD(at[1], at[55]); MULADD(at[2], at[54]); MULADD(at[3], at[53]); MULADD(at[4], at[52]); MULADD(at[5], at[51]); MULADD(at[6], at[50]); MULADD(at[7], at[49]); MULADD(at[8], at[48]); + COMBA_STORE(C->dp[8]); + /* 9 */ + COMBA_FORWARD; + MULADD(at[0], at[57]); MULADD(at[1], at[56]); MULADD(at[2], at[55]); MULADD(at[3], at[54]); MULADD(at[4], at[53]); MULADD(at[5], at[52]); MULADD(at[6], at[51]); MULADD(at[7], at[50]); MULADD(at[8], at[49]); MULADD(at[9], at[48]); + COMBA_STORE(C->dp[9]); + /* 10 */ + COMBA_FORWARD; + MULADD(at[0], at[58]); MULADD(at[1], at[57]); MULADD(at[2], at[56]); MULADD(at[3], at[55]); MULADD(at[4], at[54]); MULADD(at[5], at[53]); MULADD(at[6], at[52]); MULADD(at[7], at[51]); MULADD(at[8], at[50]); MULADD(at[9], at[49]); MULADD(at[10], at[48]); + COMBA_STORE(C->dp[10]); + /* 11 */ + COMBA_FORWARD; + MULADD(at[0], at[59]); MULADD(at[1], at[58]); MULADD(at[2], at[57]); MULADD(at[3], at[56]); MULADD(at[4], at[55]); MULADD(at[5], at[54]); MULADD(at[6], at[53]); MULADD(at[7], at[52]); MULADD(at[8], at[51]); MULADD(at[9], at[50]); MULADD(at[10], at[49]); MULADD(at[11], at[48]); + COMBA_STORE(C->dp[11]); + /* 12 */ + COMBA_FORWARD; + MULADD(at[0], at[60]); MULADD(at[1], at[59]); MULADD(at[2], at[58]); MULADD(at[3], at[57]); MULADD(at[4], at[56]); MULADD(at[5], at[55]); MULADD(at[6], at[54]); MULADD(at[7], at[53]); MULADD(at[8], at[52]); MULADD(at[9], at[51]); MULADD(at[10], at[50]); MULADD(at[11], at[49]); MULADD(at[12], at[48]); + COMBA_STORE(C->dp[12]); + /* 13 */ + COMBA_FORWARD; + MULADD(at[0], at[61]); MULADD(at[1], at[60]); MULADD(at[2], at[59]); MULADD(at[3], at[58]); MULADD(at[4], at[57]); MULADD(at[5], at[56]); MULADD(at[6], at[55]); MULADD(at[7], at[54]); MULADD(at[8], at[53]); MULADD(at[9], at[52]); MULADD(at[10], at[51]); MULADD(at[11], at[50]); MULADD(at[12], at[49]); MULADD(at[13], at[48]); + COMBA_STORE(C->dp[13]); + /* 14 */ + COMBA_FORWARD; + MULADD(at[0], at[62]); MULADD(at[1], at[61]); MULADD(at[2], at[60]); MULADD(at[3], at[59]); MULADD(at[4], at[58]); MULADD(at[5], at[57]); MULADD(at[6], at[56]); MULADD(at[7], at[55]); MULADD(at[8], at[54]); MULADD(at[9], at[53]); MULADD(at[10], at[52]); MULADD(at[11], at[51]); MULADD(at[12], at[50]); MULADD(at[13], at[49]); MULADD(at[14], at[48]); + COMBA_STORE(C->dp[14]); + /* 15 */ + COMBA_FORWARD; + MULADD(at[0], at[63]); MULADD(at[1], at[62]); MULADD(at[2], at[61]); MULADD(at[3], at[60]); MULADD(at[4], at[59]); MULADD(at[5], at[58]); MULADD(at[6], at[57]); MULADD(at[7], at[56]); MULADD(at[8], at[55]); MULADD(at[9], at[54]); MULADD(at[10], at[53]); MULADD(at[11], at[52]); MULADD(at[12], at[51]); MULADD(at[13], at[50]); MULADD(at[14], at[49]); MULADD(at[15], at[48]); + COMBA_STORE(C->dp[15]); + /* 16 */ + COMBA_FORWARD; + MULADD(at[0], at[64]); MULADD(at[1], at[63]); MULADD(at[2], at[62]); MULADD(at[3], at[61]); MULADD(at[4], at[60]); MULADD(at[5], at[59]); MULADD(at[6], at[58]); MULADD(at[7], at[57]); MULADD(at[8], at[56]); MULADD(at[9], at[55]); MULADD(at[10], at[54]); MULADD(at[11], at[53]); MULADD(at[12], at[52]); MULADD(at[13], at[51]); MULADD(at[14], at[50]); MULADD(at[15], at[49]); MULADD(at[16], at[48]); + COMBA_STORE(C->dp[16]); + /* 17 */ + COMBA_FORWARD; + MULADD(at[0], at[65]); MULADD(at[1], at[64]); MULADD(at[2], at[63]); MULADD(at[3], at[62]); MULADD(at[4], at[61]); MULADD(at[5], at[60]); MULADD(at[6], at[59]); MULADD(at[7], at[58]); MULADD(at[8], at[57]); MULADD(at[9], at[56]); MULADD(at[10], at[55]); MULADD(at[11], at[54]); MULADD(at[12], at[53]); MULADD(at[13], at[52]); MULADD(at[14], at[51]); MULADD(at[15], at[50]); MULADD(at[16], at[49]); MULADD(at[17], at[48]); + COMBA_STORE(C->dp[17]); + /* 18 */ + COMBA_FORWARD; + MULADD(at[0], at[66]); MULADD(at[1], at[65]); MULADD(at[2], at[64]); MULADD(at[3], at[63]); MULADD(at[4], at[62]); MULADD(at[5], at[61]); MULADD(at[6], at[60]); MULADD(at[7], at[59]); MULADD(at[8], at[58]); MULADD(at[9], at[57]); MULADD(at[10], at[56]); MULADD(at[11], at[55]); MULADD(at[12], at[54]); MULADD(at[13], at[53]); MULADD(at[14], at[52]); MULADD(at[15], at[51]); MULADD(at[16], at[50]); MULADD(at[17], at[49]); MULADD(at[18], at[48]); + COMBA_STORE(C->dp[18]); + /* 19 */ + COMBA_FORWARD; + MULADD(at[0], at[67]); MULADD(at[1], at[66]); MULADD(at[2], at[65]); MULADD(at[3], at[64]); MULADD(at[4], at[63]); MULADD(at[5], at[62]); MULADD(at[6], at[61]); MULADD(at[7], at[60]); MULADD(at[8], at[59]); MULADD(at[9], at[58]); MULADD(at[10], at[57]); MULADD(at[11], at[56]); MULADD(at[12], at[55]); MULADD(at[13], at[54]); MULADD(at[14], at[53]); MULADD(at[15], at[52]); MULADD(at[16], at[51]); MULADD(at[17], at[50]); MULADD(at[18], at[49]); MULADD(at[19], at[48]); + COMBA_STORE(C->dp[19]); + /* 20 */ + COMBA_FORWARD; + MULADD(at[0], at[68]); MULADD(at[1], at[67]); MULADD(at[2], at[66]); MULADD(at[3], at[65]); MULADD(at[4], at[64]); MULADD(at[5], at[63]); MULADD(at[6], at[62]); MULADD(at[7], at[61]); MULADD(at[8], at[60]); MULADD(at[9], at[59]); MULADD(at[10], at[58]); MULADD(at[11], at[57]); MULADD(at[12], at[56]); MULADD(at[13], at[55]); MULADD(at[14], at[54]); MULADD(at[15], at[53]); MULADD(at[16], at[52]); MULADD(at[17], at[51]); MULADD(at[18], at[50]); MULADD(at[19], at[49]); MULADD(at[20], at[48]); + COMBA_STORE(C->dp[20]); + /* 21 */ + COMBA_FORWARD; + MULADD(at[0], at[69]); MULADD(at[1], at[68]); MULADD(at[2], at[67]); MULADD(at[3], at[66]); MULADD(at[4], at[65]); MULADD(at[5], at[64]); MULADD(at[6], at[63]); MULADD(at[7], at[62]); MULADD(at[8], at[61]); MULADD(at[9], at[60]); MULADD(at[10], at[59]); MULADD(at[11], at[58]); MULADD(at[12], at[57]); MULADD(at[13], at[56]); MULADD(at[14], at[55]); MULADD(at[15], at[54]); MULADD(at[16], at[53]); MULADD(at[17], at[52]); MULADD(at[18], at[51]); MULADD(at[19], at[50]); MULADD(at[20], at[49]); MULADD(at[21], at[48]); + COMBA_STORE(C->dp[21]); + /* 22 */ + COMBA_FORWARD; + MULADD(at[0], at[70]); MULADD(at[1], at[69]); MULADD(at[2], at[68]); MULADD(at[3], at[67]); MULADD(at[4], at[66]); MULADD(at[5], at[65]); MULADD(at[6], at[64]); MULADD(at[7], at[63]); MULADD(at[8], at[62]); MULADD(at[9], at[61]); MULADD(at[10], at[60]); MULADD(at[11], at[59]); MULADD(at[12], at[58]); MULADD(at[13], at[57]); MULADD(at[14], at[56]); MULADD(at[15], at[55]); MULADD(at[16], at[54]); MULADD(at[17], at[53]); MULADD(at[18], at[52]); MULADD(at[19], at[51]); MULADD(at[20], at[50]); MULADD(at[21], at[49]); MULADD(at[22], at[48]); + COMBA_STORE(C->dp[22]); + /* 23 */ + COMBA_FORWARD; + MULADD(at[0], at[71]); MULADD(at[1], at[70]); MULADD(at[2], at[69]); MULADD(at[3], at[68]); MULADD(at[4], at[67]); MULADD(at[5], at[66]); MULADD(at[6], at[65]); MULADD(at[7], at[64]); MULADD(at[8], at[63]); MULADD(at[9], at[62]); MULADD(at[10], at[61]); MULADD(at[11], at[60]); MULADD(at[12], at[59]); MULADD(at[13], at[58]); MULADD(at[14], at[57]); MULADD(at[15], at[56]); MULADD(at[16], at[55]); MULADD(at[17], at[54]); MULADD(at[18], at[53]); MULADD(at[19], at[52]); MULADD(at[20], at[51]); MULADD(at[21], at[50]); MULADD(at[22], at[49]); MULADD(at[23], at[48]); + COMBA_STORE(C->dp[23]); + /* 24 */ + COMBA_FORWARD; + MULADD(at[0], at[72]); MULADD(at[1], at[71]); MULADD(at[2], at[70]); MULADD(at[3], at[69]); MULADD(at[4], at[68]); MULADD(at[5], at[67]); MULADD(at[6], at[66]); MULADD(at[7], at[65]); MULADD(at[8], at[64]); MULADD(at[9], at[63]); MULADD(at[10], at[62]); MULADD(at[11], at[61]); MULADD(at[12], at[60]); MULADD(at[13], at[59]); MULADD(at[14], at[58]); MULADD(at[15], at[57]); MULADD(at[16], at[56]); MULADD(at[17], at[55]); MULADD(at[18], at[54]); MULADD(at[19], at[53]); MULADD(at[20], at[52]); MULADD(at[21], at[51]); MULADD(at[22], at[50]); MULADD(at[23], at[49]); MULADD(at[24], at[48]); + COMBA_STORE(C->dp[24]); + /* 25 */ + COMBA_FORWARD; + MULADD(at[0], at[73]); MULADD(at[1], at[72]); MULADD(at[2], at[71]); MULADD(at[3], at[70]); MULADD(at[4], at[69]); MULADD(at[5], at[68]); MULADD(at[6], at[67]); MULADD(at[7], at[66]); MULADD(at[8], at[65]); MULADD(at[9], at[64]); MULADD(at[10], at[63]); MULADD(at[11], at[62]); MULADD(at[12], at[61]); MULADD(at[13], at[60]); MULADD(at[14], at[59]); MULADD(at[15], at[58]); MULADD(at[16], at[57]); MULADD(at[17], at[56]); MULADD(at[18], at[55]); MULADD(at[19], at[54]); MULADD(at[20], at[53]); MULADD(at[21], at[52]); MULADD(at[22], at[51]); MULADD(at[23], at[50]); MULADD(at[24], at[49]); MULADD(at[25], at[48]); + COMBA_STORE(C->dp[25]); + /* 26 */ + COMBA_FORWARD; + MULADD(at[0], at[74]); MULADD(at[1], at[73]); MULADD(at[2], at[72]); MULADD(at[3], at[71]); MULADD(at[4], at[70]); MULADD(at[5], at[69]); MULADD(at[6], at[68]); MULADD(at[7], at[67]); MULADD(at[8], at[66]); MULADD(at[9], at[65]); MULADD(at[10], at[64]); MULADD(at[11], at[63]); MULADD(at[12], at[62]); MULADD(at[13], at[61]); MULADD(at[14], at[60]); MULADD(at[15], at[59]); MULADD(at[16], at[58]); MULADD(at[17], at[57]); MULADD(at[18], at[56]); MULADD(at[19], at[55]); MULADD(at[20], at[54]); MULADD(at[21], at[53]); MULADD(at[22], at[52]); MULADD(at[23], at[51]); MULADD(at[24], at[50]); MULADD(at[25], at[49]); MULADD(at[26], at[48]); + COMBA_STORE(C->dp[26]); + /* 27 */ + COMBA_FORWARD; + MULADD(at[0], at[75]); MULADD(at[1], at[74]); MULADD(at[2], at[73]); MULADD(at[3], at[72]); MULADD(at[4], at[71]); MULADD(at[5], at[70]); MULADD(at[6], at[69]); MULADD(at[7], at[68]); MULADD(at[8], at[67]); MULADD(at[9], at[66]); MULADD(at[10], at[65]); MULADD(at[11], at[64]); MULADD(at[12], at[63]); MULADD(at[13], at[62]); MULADD(at[14], at[61]); MULADD(at[15], at[60]); MULADD(at[16], at[59]); MULADD(at[17], at[58]); MULADD(at[18], at[57]); MULADD(at[19], at[56]); MULADD(at[20], at[55]); MULADD(at[21], at[54]); MULADD(at[22], at[53]); MULADD(at[23], at[52]); MULADD(at[24], at[51]); MULADD(at[25], at[50]); MULADD(at[26], at[49]); MULADD(at[27], at[48]); + COMBA_STORE(C->dp[27]); + /* 28 */ + COMBA_FORWARD; + MULADD(at[0], at[76]); MULADD(at[1], at[75]); MULADD(at[2], at[74]); MULADD(at[3], at[73]); MULADD(at[4], at[72]); MULADD(at[5], at[71]); MULADD(at[6], at[70]); MULADD(at[7], at[69]); MULADD(at[8], at[68]); MULADD(at[9], at[67]); MULADD(at[10], at[66]); MULADD(at[11], at[65]); MULADD(at[12], at[64]); MULADD(at[13], at[63]); MULADD(at[14], at[62]); MULADD(at[15], at[61]); MULADD(at[16], at[60]); MULADD(at[17], at[59]); MULADD(at[18], at[58]); MULADD(at[19], at[57]); MULADD(at[20], at[56]); MULADD(at[21], at[55]); MULADD(at[22], at[54]); MULADD(at[23], at[53]); MULADD(at[24], at[52]); MULADD(at[25], at[51]); MULADD(at[26], at[50]); MULADD(at[27], at[49]); MULADD(at[28], at[48]); + COMBA_STORE(C->dp[28]); + /* 29 */ + COMBA_FORWARD; + MULADD(at[0], at[77]); MULADD(at[1], at[76]); MULADD(at[2], at[75]); MULADD(at[3], at[74]); MULADD(at[4], at[73]); MULADD(at[5], at[72]); MULADD(at[6], at[71]); MULADD(at[7], at[70]); MULADD(at[8], at[69]); MULADD(at[9], at[68]); MULADD(at[10], at[67]); MULADD(at[11], at[66]); MULADD(at[12], at[65]); MULADD(at[13], at[64]); MULADD(at[14], at[63]); MULADD(at[15], at[62]); MULADD(at[16], at[61]); MULADD(at[17], at[60]); MULADD(at[18], at[59]); MULADD(at[19], at[58]); MULADD(at[20], at[57]); MULADD(at[21], at[56]); MULADD(at[22], at[55]); MULADD(at[23], at[54]); MULADD(at[24], at[53]); MULADD(at[25], at[52]); MULADD(at[26], at[51]); MULADD(at[27], at[50]); MULADD(at[28], at[49]); MULADD(at[29], at[48]); + COMBA_STORE(C->dp[29]); + /* 30 */ + COMBA_FORWARD; + MULADD(at[0], at[78]); MULADD(at[1], at[77]); MULADD(at[2], at[76]); MULADD(at[3], at[75]); MULADD(at[4], at[74]); MULADD(at[5], at[73]); MULADD(at[6], at[72]); MULADD(at[7], at[71]); MULADD(at[8], at[70]); MULADD(at[9], at[69]); MULADD(at[10], at[68]); MULADD(at[11], at[67]); MULADD(at[12], at[66]); MULADD(at[13], at[65]); MULADD(at[14], at[64]); MULADD(at[15], at[63]); MULADD(at[16], at[62]); MULADD(at[17], at[61]); MULADD(at[18], at[60]); MULADD(at[19], at[59]); MULADD(at[20], at[58]); MULADD(at[21], at[57]); MULADD(at[22], at[56]); MULADD(at[23], at[55]); MULADD(at[24], at[54]); MULADD(at[25], at[53]); MULADD(at[26], at[52]); MULADD(at[27], at[51]); MULADD(at[28], at[50]); MULADD(at[29], at[49]); MULADD(at[30], at[48]); + COMBA_STORE(C->dp[30]); + /* 31 */ + COMBA_FORWARD; + MULADD(at[0], at[79]); MULADD(at[1], at[78]); MULADD(at[2], at[77]); MULADD(at[3], at[76]); MULADD(at[4], at[75]); MULADD(at[5], at[74]); MULADD(at[6], at[73]); MULADD(at[7], at[72]); MULADD(at[8], at[71]); MULADD(at[9], at[70]); MULADD(at[10], at[69]); MULADD(at[11], at[68]); MULADD(at[12], at[67]); MULADD(at[13], at[66]); MULADD(at[14], at[65]); MULADD(at[15], at[64]); MULADD(at[16], at[63]); MULADD(at[17], at[62]); MULADD(at[18], at[61]); MULADD(at[19], at[60]); MULADD(at[20], at[59]); MULADD(at[21], at[58]); MULADD(at[22], at[57]); MULADD(at[23], at[56]); MULADD(at[24], at[55]); MULADD(at[25], at[54]); MULADD(at[26], at[53]); MULADD(at[27], at[52]); MULADD(at[28], at[51]); MULADD(at[29], at[50]); MULADD(at[30], at[49]); MULADD(at[31], at[48]); + COMBA_STORE(C->dp[31]); + /* 32 */ + COMBA_FORWARD; + MULADD(at[0], at[80]); MULADD(at[1], at[79]); MULADD(at[2], at[78]); MULADD(at[3], at[77]); MULADD(at[4], at[76]); MULADD(at[5], at[75]); MULADD(at[6], at[74]); MULADD(at[7], at[73]); MULADD(at[8], at[72]); MULADD(at[9], at[71]); MULADD(at[10], at[70]); MULADD(at[11], at[69]); MULADD(at[12], at[68]); MULADD(at[13], at[67]); MULADD(at[14], at[66]); MULADD(at[15], at[65]); MULADD(at[16], at[64]); MULADD(at[17], at[63]); MULADD(at[18], at[62]); MULADD(at[19], at[61]); MULADD(at[20], at[60]); MULADD(at[21], at[59]); MULADD(at[22], at[58]); MULADD(at[23], at[57]); MULADD(at[24], at[56]); MULADD(at[25], at[55]); MULADD(at[26], at[54]); MULADD(at[27], at[53]); MULADD(at[28], at[52]); MULADD(at[29], at[51]); MULADD(at[30], at[50]); MULADD(at[31], at[49]); MULADD(at[32], at[48]); + COMBA_STORE(C->dp[32]); + /* 33 */ + COMBA_FORWARD; + MULADD(at[0], at[81]); MULADD(at[1], at[80]); MULADD(at[2], at[79]); MULADD(at[3], at[78]); MULADD(at[4], at[77]); MULADD(at[5], at[76]); MULADD(at[6], at[75]); MULADD(at[7], at[74]); MULADD(at[8], at[73]); MULADD(at[9], at[72]); MULADD(at[10], at[71]); MULADD(at[11], at[70]); MULADD(at[12], at[69]); MULADD(at[13], at[68]); MULADD(at[14], at[67]); MULADD(at[15], at[66]); MULADD(at[16], at[65]); MULADD(at[17], at[64]); MULADD(at[18], at[63]); MULADD(at[19], at[62]); MULADD(at[20], at[61]); MULADD(at[21], at[60]); MULADD(at[22], at[59]); MULADD(at[23], at[58]); MULADD(at[24], at[57]); MULADD(at[25], at[56]); MULADD(at[26], at[55]); MULADD(at[27], at[54]); MULADD(at[28], at[53]); MULADD(at[29], at[52]); MULADD(at[30], at[51]); MULADD(at[31], at[50]); MULADD(at[32], at[49]); MULADD(at[33], at[48]); + COMBA_STORE(C->dp[33]); + /* 34 */ + COMBA_FORWARD; + MULADD(at[0], at[82]); MULADD(at[1], at[81]); MULADD(at[2], at[80]); MULADD(at[3], at[79]); MULADD(at[4], at[78]); MULADD(at[5], at[77]); MULADD(at[6], at[76]); MULADD(at[7], at[75]); MULADD(at[8], at[74]); MULADD(at[9], at[73]); MULADD(at[10], at[72]); MULADD(at[11], at[71]); MULADD(at[12], at[70]); MULADD(at[13], at[69]); MULADD(at[14], at[68]); MULADD(at[15], at[67]); MULADD(at[16], at[66]); MULADD(at[17], at[65]); MULADD(at[18], at[64]); MULADD(at[19], at[63]); MULADD(at[20], at[62]); MULADD(at[21], at[61]); MULADD(at[22], at[60]); MULADD(at[23], at[59]); MULADD(at[24], at[58]); MULADD(at[25], at[57]); MULADD(at[26], at[56]); MULADD(at[27], at[55]); MULADD(at[28], at[54]); MULADD(at[29], at[53]); MULADD(at[30], at[52]); MULADD(at[31], at[51]); MULADD(at[32], at[50]); MULADD(at[33], at[49]); MULADD(at[34], at[48]); + COMBA_STORE(C->dp[34]); + /* 35 */ + COMBA_FORWARD; + MULADD(at[0], at[83]); MULADD(at[1], at[82]); MULADD(at[2], at[81]); MULADD(at[3], at[80]); MULADD(at[4], at[79]); MULADD(at[5], at[78]); MULADD(at[6], at[77]); MULADD(at[7], at[76]); MULADD(at[8], at[75]); MULADD(at[9], at[74]); MULADD(at[10], at[73]); MULADD(at[11], at[72]); MULADD(at[12], at[71]); MULADD(at[13], at[70]); MULADD(at[14], at[69]); MULADD(at[15], at[68]); MULADD(at[16], at[67]); MULADD(at[17], at[66]); MULADD(at[18], at[65]); MULADD(at[19], at[64]); MULADD(at[20], at[63]); MULADD(at[21], at[62]); MULADD(at[22], at[61]); MULADD(at[23], at[60]); MULADD(at[24], at[59]); MULADD(at[25], at[58]); MULADD(at[26], at[57]); MULADD(at[27], at[56]); MULADD(at[28], at[55]); MULADD(at[29], at[54]); MULADD(at[30], at[53]); MULADD(at[31], at[52]); MULADD(at[32], at[51]); MULADD(at[33], at[50]); MULADD(at[34], at[49]); MULADD(at[35], at[48]); + COMBA_STORE(C->dp[35]); + /* 36 */ + COMBA_FORWARD; + MULADD(at[0], at[84]); MULADD(at[1], at[83]); MULADD(at[2], at[82]); MULADD(at[3], at[81]); MULADD(at[4], at[80]); MULADD(at[5], at[79]); MULADD(at[6], at[78]); MULADD(at[7], at[77]); MULADD(at[8], at[76]); MULADD(at[9], at[75]); MULADD(at[10], at[74]); MULADD(at[11], at[73]); MULADD(at[12], at[72]); MULADD(at[13], at[71]); MULADD(at[14], at[70]); MULADD(at[15], at[69]); MULADD(at[16], at[68]); MULADD(at[17], at[67]); MULADD(at[18], at[66]); MULADD(at[19], at[65]); MULADD(at[20], at[64]); MULADD(at[21], at[63]); MULADD(at[22], at[62]); MULADD(at[23], at[61]); MULADD(at[24], at[60]); MULADD(at[25], at[59]); MULADD(at[26], at[58]); MULADD(at[27], at[57]); MULADD(at[28], at[56]); MULADD(at[29], at[55]); MULADD(at[30], at[54]); MULADD(at[31], at[53]); MULADD(at[32], at[52]); MULADD(at[33], at[51]); MULADD(at[34], at[50]); MULADD(at[35], at[49]); MULADD(at[36], at[48]); + COMBA_STORE(C->dp[36]); + /* 37 */ + COMBA_FORWARD; + MULADD(at[0], at[85]); MULADD(at[1], at[84]); MULADD(at[2], at[83]); MULADD(at[3], at[82]); MULADD(at[4], at[81]); MULADD(at[5], at[80]); MULADD(at[6], at[79]); MULADD(at[7], at[78]); MULADD(at[8], at[77]); MULADD(at[9], at[76]); MULADD(at[10], at[75]); MULADD(at[11], at[74]); MULADD(at[12], at[73]); MULADD(at[13], at[72]); MULADD(at[14], at[71]); MULADD(at[15], at[70]); MULADD(at[16], at[69]); MULADD(at[17], at[68]); MULADD(at[18], at[67]); MULADD(at[19], at[66]); MULADD(at[20], at[65]); MULADD(at[21], at[64]); MULADD(at[22], at[63]); MULADD(at[23], at[62]); MULADD(at[24], at[61]); MULADD(at[25], at[60]); MULADD(at[26], at[59]); MULADD(at[27], at[58]); MULADD(at[28], at[57]); MULADD(at[29], at[56]); MULADD(at[30], at[55]); MULADD(at[31], at[54]); MULADD(at[32], at[53]); MULADD(at[33], at[52]); MULADD(at[34], at[51]); MULADD(at[35], at[50]); MULADD(at[36], at[49]); MULADD(at[37], at[48]); + COMBA_STORE(C->dp[37]); + /* 38 */ + COMBA_FORWARD; + MULADD(at[0], at[86]); MULADD(at[1], at[85]); MULADD(at[2], at[84]); MULADD(at[3], at[83]); MULADD(at[4], at[82]); MULADD(at[5], at[81]); MULADD(at[6], at[80]); MULADD(at[7], at[79]); MULADD(at[8], at[78]); MULADD(at[9], at[77]); MULADD(at[10], at[76]); MULADD(at[11], at[75]); MULADD(at[12], at[74]); MULADD(at[13], at[73]); MULADD(at[14], at[72]); MULADD(at[15], at[71]); MULADD(at[16], at[70]); MULADD(at[17], at[69]); MULADD(at[18], at[68]); MULADD(at[19], at[67]); MULADD(at[20], at[66]); MULADD(at[21], at[65]); MULADD(at[22], at[64]); MULADD(at[23], at[63]); MULADD(at[24], at[62]); MULADD(at[25], at[61]); MULADD(at[26], at[60]); MULADD(at[27], at[59]); MULADD(at[28], at[58]); MULADD(at[29], at[57]); MULADD(at[30], at[56]); MULADD(at[31], at[55]); MULADD(at[32], at[54]); MULADD(at[33], at[53]); MULADD(at[34], at[52]); MULADD(at[35], at[51]); MULADD(at[36], at[50]); MULADD(at[37], at[49]); MULADD(at[38], at[48]); + COMBA_STORE(C->dp[38]); + /* 39 */ + COMBA_FORWARD; + MULADD(at[0], at[87]); MULADD(at[1], at[86]); MULADD(at[2], at[85]); MULADD(at[3], at[84]); MULADD(at[4], at[83]); MULADD(at[5], at[82]); MULADD(at[6], at[81]); MULADD(at[7], at[80]); MULADD(at[8], at[79]); MULADD(at[9], at[78]); MULADD(at[10], at[77]); MULADD(at[11], at[76]); MULADD(at[12], at[75]); MULADD(at[13], at[74]); MULADD(at[14], at[73]); MULADD(at[15], at[72]); MULADD(at[16], at[71]); MULADD(at[17], at[70]); MULADD(at[18], at[69]); MULADD(at[19], at[68]); MULADD(at[20], at[67]); MULADD(at[21], at[66]); MULADD(at[22], at[65]); MULADD(at[23], at[64]); MULADD(at[24], at[63]); MULADD(at[25], at[62]); MULADD(at[26], at[61]); MULADD(at[27], at[60]); MULADD(at[28], at[59]); MULADD(at[29], at[58]); MULADD(at[30], at[57]); MULADD(at[31], at[56]); MULADD(at[32], at[55]); MULADD(at[33], at[54]); MULADD(at[34], at[53]); MULADD(at[35], at[52]); MULADD(at[36], at[51]); MULADD(at[37], at[50]); MULADD(at[38], at[49]); MULADD(at[39], at[48]); + COMBA_STORE(C->dp[39]); + /* 40 */ + COMBA_FORWARD; + MULADD(at[0], at[88]); MULADD(at[1], at[87]); MULADD(at[2], at[86]); MULADD(at[3], at[85]); MULADD(at[4], at[84]); MULADD(at[5], at[83]); MULADD(at[6], at[82]); MULADD(at[7], at[81]); MULADD(at[8], at[80]); MULADD(at[9], at[79]); MULADD(at[10], at[78]); MULADD(at[11], at[77]); MULADD(at[12], at[76]); MULADD(at[13], at[75]); MULADD(at[14], at[74]); MULADD(at[15], at[73]); MULADD(at[16], at[72]); MULADD(at[17], at[71]); MULADD(at[18], at[70]); MULADD(at[19], at[69]); MULADD(at[20], at[68]); MULADD(at[21], at[67]); MULADD(at[22], at[66]); MULADD(at[23], at[65]); MULADD(at[24], at[64]); MULADD(at[25], at[63]); MULADD(at[26], at[62]); MULADD(at[27], at[61]); MULADD(at[28], at[60]); MULADD(at[29], at[59]); MULADD(at[30], at[58]); MULADD(at[31], at[57]); MULADD(at[32], at[56]); MULADD(at[33], at[55]); MULADD(at[34], at[54]); MULADD(at[35], at[53]); MULADD(at[36], at[52]); MULADD(at[37], at[51]); MULADD(at[38], at[50]); MULADD(at[39], at[49]); MULADD(at[40], at[48]); + COMBA_STORE(C->dp[40]); + /* 41 */ + COMBA_FORWARD; + MULADD(at[0], at[89]); MULADD(at[1], at[88]); MULADD(at[2], at[87]); MULADD(at[3], at[86]); MULADD(at[4], at[85]); MULADD(at[5], at[84]); MULADD(at[6], at[83]); MULADD(at[7], at[82]); MULADD(at[8], at[81]); MULADD(at[9], at[80]); MULADD(at[10], at[79]); MULADD(at[11], at[78]); MULADD(at[12], at[77]); MULADD(at[13], at[76]); MULADD(at[14], at[75]); MULADD(at[15], at[74]); MULADD(at[16], at[73]); MULADD(at[17], at[72]); MULADD(at[18], at[71]); MULADD(at[19], at[70]); MULADD(at[20], at[69]); MULADD(at[21], at[68]); MULADD(at[22], at[67]); MULADD(at[23], at[66]); MULADD(at[24], at[65]); MULADD(at[25], at[64]); MULADD(at[26], at[63]); MULADD(at[27], at[62]); MULADD(at[28], at[61]); MULADD(at[29], at[60]); MULADD(at[30], at[59]); MULADD(at[31], at[58]); MULADD(at[32], at[57]); MULADD(at[33], at[56]); MULADD(at[34], at[55]); MULADD(at[35], at[54]); MULADD(at[36], at[53]); MULADD(at[37], at[52]); MULADD(at[38], at[51]); MULADD(at[39], at[50]); MULADD(at[40], at[49]); MULADD(at[41], at[48]); + COMBA_STORE(C->dp[41]); + /* 42 */ + COMBA_FORWARD; + MULADD(at[0], at[90]); MULADD(at[1], at[89]); MULADD(at[2], at[88]); MULADD(at[3], at[87]); MULADD(at[4], at[86]); MULADD(at[5], at[85]); MULADD(at[6], at[84]); MULADD(at[7], at[83]); MULADD(at[8], at[82]); MULADD(at[9], at[81]); MULADD(at[10], at[80]); MULADD(at[11], at[79]); MULADD(at[12], at[78]); MULADD(at[13], at[77]); MULADD(at[14], at[76]); MULADD(at[15], at[75]); MULADD(at[16], at[74]); MULADD(at[17], at[73]); MULADD(at[18], at[72]); MULADD(at[19], at[71]); MULADD(at[20], at[70]); MULADD(at[21], at[69]); MULADD(at[22], at[68]); MULADD(at[23], at[67]); MULADD(at[24], at[66]); MULADD(at[25], at[65]); MULADD(at[26], at[64]); MULADD(at[27], at[63]); MULADD(at[28], at[62]); MULADD(at[29], at[61]); MULADD(at[30], at[60]); MULADD(at[31], at[59]); MULADD(at[32], at[58]); MULADD(at[33], at[57]); MULADD(at[34], at[56]); MULADD(at[35], at[55]); MULADD(at[36], at[54]); MULADD(at[37], at[53]); MULADD(at[38], at[52]); MULADD(at[39], at[51]); MULADD(at[40], at[50]); MULADD(at[41], at[49]); MULADD(at[42], at[48]); + COMBA_STORE(C->dp[42]); + /* 43 */ + COMBA_FORWARD; + MULADD(at[0], at[91]); MULADD(at[1], at[90]); MULADD(at[2], at[89]); MULADD(at[3], at[88]); MULADD(at[4], at[87]); MULADD(at[5], at[86]); MULADD(at[6], at[85]); MULADD(at[7], at[84]); MULADD(at[8], at[83]); MULADD(at[9], at[82]); MULADD(at[10], at[81]); MULADD(at[11], at[80]); MULADD(at[12], at[79]); MULADD(at[13], at[78]); MULADD(at[14], at[77]); MULADD(at[15], at[76]); MULADD(at[16], at[75]); MULADD(at[17], at[74]); MULADD(at[18], at[73]); MULADD(at[19], at[72]); MULADD(at[20], at[71]); MULADD(at[21], at[70]); MULADD(at[22], at[69]); MULADD(at[23], at[68]); MULADD(at[24], at[67]); MULADD(at[25], at[66]); MULADD(at[26], at[65]); MULADD(at[27], at[64]); MULADD(at[28], at[63]); MULADD(at[29], at[62]); MULADD(at[30], at[61]); MULADD(at[31], at[60]); MULADD(at[32], at[59]); MULADD(at[33], at[58]); MULADD(at[34], at[57]); MULADD(at[35], at[56]); MULADD(at[36], at[55]); MULADD(at[37], at[54]); MULADD(at[38], at[53]); MULADD(at[39], at[52]); MULADD(at[40], at[51]); MULADD(at[41], at[50]); MULADD(at[42], at[49]); MULADD(at[43], at[48]); + COMBA_STORE(C->dp[43]); + /* 44 */ + COMBA_FORWARD; + MULADD(at[0], at[92]); MULADD(at[1], at[91]); MULADD(at[2], at[90]); MULADD(at[3], at[89]); MULADD(at[4], at[88]); MULADD(at[5], at[87]); MULADD(at[6], at[86]); MULADD(at[7], at[85]); MULADD(at[8], at[84]); MULADD(at[9], at[83]); MULADD(at[10], at[82]); MULADD(at[11], at[81]); MULADD(at[12], at[80]); MULADD(at[13], at[79]); MULADD(at[14], at[78]); MULADD(at[15], at[77]); MULADD(at[16], at[76]); MULADD(at[17], at[75]); MULADD(at[18], at[74]); MULADD(at[19], at[73]); MULADD(at[20], at[72]); MULADD(at[21], at[71]); MULADD(at[22], at[70]); MULADD(at[23], at[69]); MULADD(at[24], at[68]); MULADD(at[25], at[67]); MULADD(at[26], at[66]); MULADD(at[27], at[65]); MULADD(at[28], at[64]); MULADD(at[29], at[63]); MULADD(at[30], at[62]); MULADD(at[31], at[61]); MULADD(at[32], at[60]); MULADD(at[33], at[59]); MULADD(at[34], at[58]); MULADD(at[35], at[57]); MULADD(at[36], at[56]); MULADD(at[37], at[55]); MULADD(at[38], at[54]); MULADD(at[39], at[53]); MULADD(at[40], at[52]); MULADD(at[41], at[51]); MULADD(at[42], at[50]); MULADD(at[43], at[49]); MULADD(at[44], at[48]); + COMBA_STORE(C->dp[44]); + /* 45 */ + COMBA_FORWARD; + MULADD(at[0], at[93]); MULADD(at[1], at[92]); MULADD(at[2], at[91]); MULADD(at[3], at[90]); MULADD(at[4], at[89]); MULADD(at[5], at[88]); MULADD(at[6], at[87]); MULADD(at[7], at[86]); MULADD(at[8], at[85]); MULADD(at[9], at[84]); MULADD(at[10], at[83]); MULADD(at[11], at[82]); MULADD(at[12], at[81]); MULADD(at[13], at[80]); MULADD(at[14], at[79]); MULADD(at[15], at[78]); MULADD(at[16], at[77]); MULADD(at[17], at[76]); MULADD(at[18], at[75]); MULADD(at[19], at[74]); MULADD(at[20], at[73]); MULADD(at[21], at[72]); MULADD(at[22], at[71]); MULADD(at[23], at[70]); MULADD(at[24], at[69]); MULADD(at[25], at[68]); MULADD(at[26], at[67]); MULADD(at[27], at[66]); MULADD(at[28], at[65]); MULADD(at[29], at[64]); MULADD(at[30], at[63]); MULADD(at[31], at[62]); MULADD(at[32], at[61]); MULADD(at[33], at[60]); MULADD(at[34], at[59]); MULADD(at[35], at[58]); MULADD(at[36], at[57]); MULADD(at[37], at[56]); MULADD(at[38], at[55]); MULADD(at[39], at[54]); MULADD(at[40], at[53]); MULADD(at[41], at[52]); MULADD(at[42], at[51]); MULADD(at[43], at[50]); MULADD(at[44], at[49]); MULADD(at[45], at[48]); + COMBA_STORE(C->dp[45]); + /* 46 */ + COMBA_FORWARD; + MULADD(at[0], at[94]); MULADD(at[1], at[93]); MULADD(at[2], at[92]); MULADD(at[3], at[91]); MULADD(at[4], at[90]); MULADD(at[5], at[89]); MULADD(at[6], at[88]); MULADD(at[7], at[87]); MULADD(at[8], at[86]); MULADD(at[9], at[85]); MULADD(at[10], at[84]); MULADD(at[11], at[83]); MULADD(at[12], at[82]); MULADD(at[13], at[81]); MULADD(at[14], at[80]); MULADD(at[15], at[79]); MULADD(at[16], at[78]); MULADD(at[17], at[77]); MULADD(at[18], at[76]); MULADD(at[19], at[75]); MULADD(at[20], at[74]); MULADD(at[21], at[73]); MULADD(at[22], at[72]); MULADD(at[23], at[71]); MULADD(at[24], at[70]); MULADD(at[25], at[69]); MULADD(at[26], at[68]); MULADD(at[27], at[67]); MULADD(at[28], at[66]); MULADD(at[29], at[65]); MULADD(at[30], at[64]); MULADD(at[31], at[63]); MULADD(at[32], at[62]); MULADD(at[33], at[61]); MULADD(at[34], at[60]); MULADD(at[35], at[59]); MULADD(at[36], at[58]); MULADD(at[37], at[57]); MULADD(at[38], at[56]); MULADD(at[39], at[55]); MULADD(at[40], at[54]); MULADD(at[41], at[53]); MULADD(at[42], at[52]); MULADD(at[43], at[51]); MULADD(at[44], at[50]); MULADD(at[45], at[49]); MULADD(at[46], at[48]); + COMBA_STORE(C->dp[46]); + /* 47 */ + COMBA_FORWARD; + MULADD(at[0], at[95]); MULADD(at[1], at[94]); MULADD(at[2], at[93]); MULADD(at[3], at[92]); MULADD(at[4], at[91]); MULADD(at[5], at[90]); MULADD(at[6], at[89]); MULADD(at[7], at[88]); MULADD(at[8], at[87]); MULADD(at[9], at[86]); MULADD(at[10], at[85]); MULADD(at[11], at[84]); MULADD(at[12], at[83]); MULADD(at[13], at[82]); MULADD(at[14], at[81]); MULADD(at[15], at[80]); MULADD(at[16], at[79]); MULADD(at[17], at[78]); MULADD(at[18], at[77]); MULADD(at[19], at[76]); MULADD(at[20], at[75]); MULADD(at[21], at[74]); MULADD(at[22], at[73]); MULADD(at[23], at[72]); MULADD(at[24], at[71]); MULADD(at[25], at[70]); MULADD(at[26], at[69]); MULADD(at[27], at[68]); MULADD(at[28], at[67]); MULADD(at[29], at[66]); MULADD(at[30], at[65]); MULADD(at[31], at[64]); MULADD(at[32], at[63]); MULADD(at[33], at[62]); MULADD(at[34], at[61]); MULADD(at[35], at[60]); MULADD(at[36], at[59]); MULADD(at[37], at[58]); MULADD(at[38], at[57]); MULADD(at[39], at[56]); MULADD(at[40], at[55]); MULADD(at[41], at[54]); MULADD(at[42], at[53]); MULADD(at[43], at[52]); MULADD(at[44], at[51]); MULADD(at[45], at[50]); MULADD(at[46], at[49]); MULADD(at[47], at[48]); + COMBA_STORE(C->dp[47]); + /* 48 */ + COMBA_FORWARD; + MULADD(at[1], at[95]); MULADD(at[2], at[94]); MULADD(at[3], at[93]); MULADD(at[4], at[92]); MULADD(at[5], at[91]); MULADD(at[6], at[90]); MULADD(at[7], at[89]); MULADD(at[8], at[88]); MULADD(at[9], at[87]); MULADD(at[10], at[86]); MULADD(at[11], at[85]); MULADD(at[12], at[84]); MULADD(at[13], at[83]); MULADD(at[14], at[82]); MULADD(at[15], at[81]); MULADD(at[16], at[80]); MULADD(at[17], at[79]); MULADD(at[18], at[78]); MULADD(at[19], at[77]); MULADD(at[20], at[76]); MULADD(at[21], at[75]); MULADD(at[22], at[74]); MULADD(at[23], at[73]); MULADD(at[24], at[72]); MULADD(at[25], at[71]); MULADD(at[26], at[70]); MULADD(at[27], at[69]); MULADD(at[28], at[68]); MULADD(at[29], at[67]); MULADD(at[30], at[66]); MULADD(at[31], at[65]); MULADD(at[32], at[64]); MULADD(at[33], at[63]); MULADD(at[34], at[62]); MULADD(at[35], at[61]); MULADD(at[36], at[60]); MULADD(at[37], at[59]); MULADD(at[38], at[58]); MULADD(at[39], at[57]); MULADD(at[40], at[56]); MULADD(at[41], at[55]); MULADD(at[42], at[54]); MULADD(at[43], at[53]); MULADD(at[44], at[52]); MULADD(at[45], at[51]); MULADD(at[46], at[50]); MULADD(at[47], at[49]); + COMBA_STORE(C->dp[48]); + /* 49 */ + COMBA_FORWARD; + MULADD(at[2], at[95]); MULADD(at[3], at[94]); MULADD(at[4], at[93]); MULADD(at[5], at[92]); MULADD(at[6], at[91]); MULADD(at[7], at[90]); MULADD(at[8], at[89]); MULADD(at[9], at[88]); MULADD(at[10], at[87]); MULADD(at[11], at[86]); MULADD(at[12], at[85]); MULADD(at[13], at[84]); MULADD(at[14], at[83]); MULADD(at[15], at[82]); MULADD(at[16], at[81]); MULADD(at[17], at[80]); MULADD(at[18], at[79]); MULADD(at[19], at[78]); MULADD(at[20], at[77]); MULADD(at[21], at[76]); MULADD(at[22], at[75]); MULADD(at[23], at[74]); MULADD(at[24], at[73]); MULADD(at[25], at[72]); MULADD(at[26], at[71]); MULADD(at[27], at[70]); MULADD(at[28], at[69]); MULADD(at[29], at[68]); MULADD(at[30], at[67]); MULADD(at[31], at[66]); MULADD(at[32], at[65]); MULADD(at[33], at[64]); MULADD(at[34], at[63]); MULADD(at[35], at[62]); MULADD(at[36], at[61]); MULADD(at[37], at[60]); MULADD(at[38], at[59]); MULADD(at[39], at[58]); MULADD(at[40], at[57]); MULADD(at[41], at[56]); MULADD(at[42], at[55]); MULADD(at[43], at[54]); MULADD(at[44], at[53]); MULADD(at[45], at[52]); MULADD(at[46], at[51]); MULADD(at[47], at[50]); + COMBA_STORE(C->dp[49]); + /* 50 */ + COMBA_FORWARD; + MULADD(at[3], at[95]); MULADD(at[4], at[94]); MULADD(at[5], at[93]); MULADD(at[6], at[92]); MULADD(at[7], at[91]); MULADD(at[8], at[90]); MULADD(at[9], at[89]); MULADD(at[10], at[88]); MULADD(at[11], at[87]); MULADD(at[12], at[86]); MULADD(at[13], at[85]); MULADD(at[14], at[84]); MULADD(at[15], at[83]); MULADD(at[16], at[82]); MULADD(at[17], at[81]); MULADD(at[18], at[80]); MULADD(at[19], at[79]); MULADD(at[20], at[78]); MULADD(at[21], at[77]); MULADD(at[22], at[76]); MULADD(at[23], at[75]); MULADD(at[24], at[74]); MULADD(at[25], at[73]); MULADD(at[26], at[72]); MULADD(at[27], at[71]); MULADD(at[28], at[70]); MULADD(at[29], at[69]); MULADD(at[30], at[68]); MULADD(at[31], at[67]); MULADD(at[32], at[66]); MULADD(at[33], at[65]); MULADD(at[34], at[64]); MULADD(at[35], at[63]); MULADD(at[36], at[62]); MULADD(at[37], at[61]); MULADD(at[38], at[60]); MULADD(at[39], at[59]); MULADD(at[40], at[58]); MULADD(at[41], at[57]); MULADD(at[42], at[56]); MULADD(at[43], at[55]); MULADD(at[44], at[54]); MULADD(at[45], at[53]); MULADD(at[46], at[52]); MULADD(at[47], at[51]); + COMBA_STORE(C->dp[50]); + /* 51 */ + COMBA_FORWARD; + MULADD(at[4], at[95]); MULADD(at[5], at[94]); MULADD(at[6], at[93]); MULADD(at[7], at[92]); MULADD(at[8], at[91]); MULADD(at[9], at[90]); MULADD(at[10], at[89]); MULADD(at[11], at[88]); MULADD(at[12], at[87]); MULADD(at[13], at[86]); MULADD(at[14], at[85]); MULADD(at[15], at[84]); MULADD(at[16], at[83]); MULADD(at[17], at[82]); MULADD(at[18], at[81]); MULADD(at[19], at[80]); MULADD(at[20], at[79]); MULADD(at[21], at[78]); MULADD(at[22], at[77]); MULADD(at[23], at[76]); MULADD(at[24], at[75]); MULADD(at[25], at[74]); MULADD(at[26], at[73]); MULADD(at[27], at[72]); MULADD(at[28], at[71]); MULADD(at[29], at[70]); MULADD(at[30], at[69]); MULADD(at[31], at[68]); MULADD(at[32], at[67]); MULADD(at[33], at[66]); MULADD(at[34], at[65]); MULADD(at[35], at[64]); MULADD(at[36], at[63]); MULADD(at[37], at[62]); MULADD(at[38], at[61]); MULADD(at[39], at[60]); MULADD(at[40], at[59]); MULADD(at[41], at[58]); MULADD(at[42], at[57]); MULADD(at[43], at[56]); MULADD(at[44], at[55]); MULADD(at[45], at[54]); MULADD(at[46], at[53]); MULADD(at[47], at[52]); + COMBA_STORE(C->dp[51]); + /* 52 */ + COMBA_FORWARD; + MULADD(at[5], at[95]); MULADD(at[6], at[94]); MULADD(at[7], at[93]); MULADD(at[8], at[92]); MULADD(at[9], at[91]); MULADD(at[10], at[90]); MULADD(at[11], at[89]); MULADD(at[12], at[88]); MULADD(at[13], at[87]); MULADD(at[14], at[86]); MULADD(at[15], at[85]); MULADD(at[16], at[84]); MULADD(at[17], at[83]); MULADD(at[18], at[82]); MULADD(at[19], at[81]); MULADD(at[20], at[80]); MULADD(at[21], at[79]); MULADD(at[22], at[78]); MULADD(at[23], at[77]); MULADD(at[24], at[76]); MULADD(at[25], at[75]); MULADD(at[26], at[74]); MULADD(at[27], at[73]); MULADD(at[28], at[72]); MULADD(at[29], at[71]); MULADD(at[30], at[70]); MULADD(at[31], at[69]); MULADD(at[32], at[68]); MULADD(at[33], at[67]); MULADD(at[34], at[66]); MULADD(at[35], at[65]); MULADD(at[36], at[64]); MULADD(at[37], at[63]); MULADD(at[38], at[62]); MULADD(at[39], at[61]); MULADD(at[40], at[60]); MULADD(at[41], at[59]); MULADD(at[42], at[58]); MULADD(at[43], at[57]); MULADD(at[44], at[56]); MULADD(at[45], at[55]); MULADD(at[46], at[54]); MULADD(at[47], at[53]); + COMBA_STORE(C->dp[52]); + /* 53 */ + COMBA_FORWARD; + MULADD(at[6], at[95]); MULADD(at[7], at[94]); MULADD(at[8], at[93]); MULADD(at[9], at[92]); MULADD(at[10], at[91]); MULADD(at[11], at[90]); MULADD(at[12], at[89]); MULADD(at[13], at[88]); MULADD(at[14], at[87]); MULADD(at[15], at[86]); MULADD(at[16], at[85]); MULADD(at[17], at[84]); MULADD(at[18], at[83]); MULADD(at[19], at[82]); MULADD(at[20], at[81]); MULADD(at[21], at[80]); MULADD(at[22], at[79]); MULADD(at[23], at[78]); MULADD(at[24], at[77]); MULADD(at[25], at[76]); MULADD(at[26], at[75]); MULADD(at[27], at[74]); MULADD(at[28], at[73]); MULADD(at[29], at[72]); MULADD(at[30], at[71]); MULADD(at[31], at[70]); MULADD(at[32], at[69]); MULADD(at[33], at[68]); MULADD(at[34], at[67]); MULADD(at[35], at[66]); MULADD(at[36], at[65]); MULADD(at[37], at[64]); MULADD(at[38], at[63]); MULADD(at[39], at[62]); MULADD(at[40], at[61]); MULADD(at[41], at[60]); MULADD(at[42], at[59]); MULADD(at[43], at[58]); MULADD(at[44], at[57]); MULADD(at[45], at[56]); MULADD(at[46], at[55]); MULADD(at[47], at[54]); + COMBA_STORE(C->dp[53]); + /* 54 */ + COMBA_FORWARD; + MULADD(at[7], at[95]); MULADD(at[8], at[94]); MULADD(at[9], at[93]); MULADD(at[10], at[92]); MULADD(at[11], at[91]); MULADD(at[12], at[90]); MULADD(at[13], at[89]); MULADD(at[14], at[88]); MULADD(at[15], at[87]); MULADD(at[16], at[86]); MULADD(at[17], at[85]); MULADD(at[18], at[84]); MULADD(at[19], at[83]); MULADD(at[20], at[82]); MULADD(at[21], at[81]); MULADD(at[22], at[80]); MULADD(at[23], at[79]); MULADD(at[24], at[78]); MULADD(at[25], at[77]); MULADD(at[26], at[76]); MULADD(at[27], at[75]); MULADD(at[28], at[74]); MULADD(at[29], at[73]); MULADD(at[30], at[72]); MULADD(at[31], at[71]); MULADD(at[32], at[70]); MULADD(at[33], at[69]); MULADD(at[34], at[68]); MULADD(at[35], at[67]); MULADD(at[36], at[66]); MULADD(at[37], at[65]); MULADD(at[38], at[64]); MULADD(at[39], at[63]); MULADD(at[40], at[62]); MULADD(at[41], at[61]); MULADD(at[42], at[60]); MULADD(at[43], at[59]); MULADD(at[44], at[58]); MULADD(at[45], at[57]); MULADD(at[46], at[56]); MULADD(at[47], at[55]); + COMBA_STORE(C->dp[54]); + /* 55 */ + COMBA_FORWARD; + MULADD(at[8], at[95]); MULADD(at[9], at[94]); MULADD(at[10], at[93]); MULADD(at[11], at[92]); MULADD(at[12], at[91]); MULADD(at[13], at[90]); MULADD(at[14], at[89]); MULADD(at[15], at[88]); MULADD(at[16], at[87]); MULADD(at[17], at[86]); MULADD(at[18], at[85]); MULADD(at[19], at[84]); MULADD(at[20], at[83]); MULADD(at[21], at[82]); MULADD(at[22], at[81]); MULADD(at[23], at[80]); MULADD(at[24], at[79]); MULADD(at[25], at[78]); MULADD(at[26], at[77]); MULADD(at[27], at[76]); MULADD(at[28], at[75]); MULADD(at[29], at[74]); MULADD(at[30], at[73]); MULADD(at[31], at[72]); MULADD(at[32], at[71]); MULADD(at[33], at[70]); MULADD(at[34], at[69]); MULADD(at[35], at[68]); MULADD(at[36], at[67]); MULADD(at[37], at[66]); MULADD(at[38], at[65]); MULADD(at[39], at[64]); MULADD(at[40], at[63]); MULADD(at[41], at[62]); MULADD(at[42], at[61]); MULADD(at[43], at[60]); MULADD(at[44], at[59]); MULADD(at[45], at[58]); MULADD(at[46], at[57]); MULADD(at[47], at[56]); + COMBA_STORE(C->dp[55]); + /* 56 */ + COMBA_FORWARD; + MULADD(at[9], at[95]); MULADD(at[10], at[94]); MULADD(at[11], at[93]); MULADD(at[12], at[92]); MULADD(at[13], at[91]); MULADD(at[14], at[90]); MULADD(at[15], at[89]); MULADD(at[16], at[88]); MULADD(at[17], at[87]); MULADD(at[18], at[86]); MULADD(at[19], at[85]); MULADD(at[20], at[84]); MULADD(at[21], at[83]); MULADD(at[22], at[82]); MULADD(at[23], at[81]); MULADD(at[24], at[80]); MULADD(at[25], at[79]); MULADD(at[26], at[78]); MULADD(at[27], at[77]); MULADD(at[28], at[76]); MULADD(at[29], at[75]); MULADD(at[30], at[74]); MULADD(at[31], at[73]); MULADD(at[32], at[72]); MULADD(at[33], at[71]); MULADD(at[34], at[70]); MULADD(at[35], at[69]); MULADD(at[36], at[68]); MULADD(at[37], at[67]); MULADD(at[38], at[66]); MULADD(at[39], at[65]); MULADD(at[40], at[64]); MULADD(at[41], at[63]); MULADD(at[42], at[62]); MULADD(at[43], at[61]); MULADD(at[44], at[60]); MULADD(at[45], at[59]); MULADD(at[46], at[58]); MULADD(at[47], at[57]); + COMBA_STORE(C->dp[56]); + /* 57 */ + COMBA_FORWARD; + MULADD(at[10], at[95]); MULADD(at[11], at[94]); MULADD(at[12], at[93]); MULADD(at[13], at[92]); MULADD(at[14], at[91]); MULADD(at[15], at[90]); MULADD(at[16], at[89]); MULADD(at[17], at[88]); MULADD(at[18], at[87]); MULADD(at[19], at[86]); MULADD(at[20], at[85]); MULADD(at[21], at[84]); MULADD(at[22], at[83]); MULADD(at[23], at[82]); MULADD(at[24], at[81]); MULADD(at[25], at[80]); MULADD(at[26], at[79]); MULADD(at[27], at[78]); MULADD(at[28], at[77]); MULADD(at[29], at[76]); MULADD(at[30], at[75]); MULADD(at[31], at[74]); MULADD(at[32], at[73]); MULADD(at[33], at[72]); MULADD(at[34], at[71]); MULADD(at[35], at[70]); MULADD(at[36], at[69]); MULADD(at[37], at[68]); MULADD(at[38], at[67]); MULADD(at[39], at[66]); MULADD(at[40], at[65]); MULADD(at[41], at[64]); MULADD(at[42], at[63]); MULADD(at[43], at[62]); MULADD(at[44], at[61]); MULADD(at[45], at[60]); MULADD(at[46], at[59]); MULADD(at[47], at[58]); + COMBA_STORE(C->dp[57]); + /* 58 */ + COMBA_FORWARD; + MULADD(at[11], at[95]); MULADD(at[12], at[94]); MULADD(at[13], at[93]); MULADD(at[14], at[92]); MULADD(at[15], at[91]); MULADD(at[16], at[90]); MULADD(at[17], at[89]); MULADD(at[18], at[88]); MULADD(at[19], at[87]); MULADD(at[20], at[86]); MULADD(at[21], at[85]); MULADD(at[22], at[84]); MULADD(at[23], at[83]); MULADD(at[24], at[82]); MULADD(at[25], at[81]); MULADD(at[26], at[80]); MULADD(at[27], at[79]); MULADD(at[28], at[78]); MULADD(at[29], at[77]); MULADD(at[30], at[76]); MULADD(at[31], at[75]); MULADD(at[32], at[74]); MULADD(at[33], at[73]); MULADD(at[34], at[72]); MULADD(at[35], at[71]); MULADD(at[36], at[70]); MULADD(at[37], at[69]); MULADD(at[38], at[68]); MULADD(at[39], at[67]); MULADD(at[40], at[66]); MULADD(at[41], at[65]); MULADD(at[42], at[64]); MULADD(at[43], at[63]); MULADD(at[44], at[62]); MULADD(at[45], at[61]); MULADD(at[46], at[60]); MULADD(at[47], at[59]); + COMBA_STORE(C->dp[58]); + /* 59 */ + COMBA_FORWARD; + MULADD(at[12], at[95]); MULADD(at[13], at[94]); MULADD(at[14], at[93]); MULADD(at[15], at[92]); MULADD(at[16], at[91]); MULADD(at[17], at[90]); MULADD(at[18], at[89]); MULADD(at[19], at[88]); MULADD(at[20], at[87]); MULADD(at[21], at[86]); MULADD(at[22], at[85]); MULADD(at[23], at[84]); MULADD(at[24], at[83]); MULADD(at[25], at[82]); MULADD(at[26], at[81]); MULADD(at[27], at[80]); MULADD(at[28], at[79]); MULADD(at[29], at[78]); MULADD(at[30], at[77]); MULADD(at[31], at[76]); MULADD(at[32], at[75]); MULADD(at[33], at[74]); MULADD(at[34], at[73]); MULADD(at[35], at[72]); MULADD(at[36], at[71]); MULADD(at[37], at[70]); MULADD(at[38], at[69]); MULADD(at[39], at[68]); MULADD(at[40], at[67]); MULADD(at[41], at[66]); MULADD(at[42], at[65]); MULADD(at[43], at[64]); MULADD(at[44], at[63]); MULADD(at[45], at[62]); MULADD(at[46], at[61]); MULADD(at[47], at[60]); + COMBA_STORE(C->dp[59]); + /* 60 */ + COMBA_FORWARD; + MULADD(at[13], at[95]); MULADD(at[14], at[94]); MULADD(at[15], at[93]); MULADD(at[16], at[92]); MULADD(at[17], at[91]); MULADD(at[18], at[90]); MULADD(at[19], at[89]); MULADD(at[20], at[88]); MULADD(at[21], at[87]); MULADD(at[22], at[86]); MULADD(at[23], at[85]); MULADD(at[24], at[84]); MULADD(at[25], at[83]); MULADD(at[26], at[82]); MULADD(at[27], at[81]); MULADD(at[28], at[80]); MULADD(at[29], at[79]); MULADD(at[30], at[78]); MULADD(at[31], at[77]); MULADD(at[32], at[76]); MULADD(at[33], at[75]); MULADD(at[34], at[74]); MULADD(at[35], at[73]); MULADD(at[36], at[72]); MULADD(at[37], at[71]); MULADD(at[38], at[70]); MULADD(at[39], at[69]); MULADD(at[40], at[68]); MULADD(at[41], at[67]); MULADD(at[42], at[66]); MULADD(at[43], at[65]); MULADD(at[44], at[64]); MULADD(at[45], at[63]); MULADD(at[46], at[62]); MULADD(at[47], at[61]); + COMBA_STORE(C->dp[60]); + /* 61 */ + COMBA_FORWARD; + MULADD(at[14], at[95]); MULADD(at[15], at[94]); MULADD(at[16], at[93]); MULADD(at[17], at[92]); MULADD(at[18], at[91]); MULADD(at[19], at[90]); MULADD(at[20], at[89]); MULADD(at[21], at[88]); MULADD(at[22], at[87]); MULADD(at[23], at[86]); MULADD(at[24], at[85]); MULADD(at[25], at[84]); MULADD(at[26], at[83]); MULADD(at[27], at[82]); MULADD(at[28], at[81]); MULADD(at[29], at[80]); MULADD(at[30], at[79]); MULADD(at[31], at[78]); MULADD(at[32], at[77]); MULADD(at[33], at[76]); MULADD(at[34], at[75]); MULADD(at[35], at[74]); MULADD(at[36], at[73]); MULADD(at[37], at[72]); MULADD(at[38], at[71]); MULADD(at[39], at[70]); MULADD(at[40], at[69]); MULADD(at[41], at[68]); MULADD(at[42], at[67]); MULADD(at[43], at[66]); MULADD(at[44], at[65]); MULADD(at[45], at[64]); MULADD(at[46], at[63]); MULADD(at[47], at[62]); + COMBA_STORE(C->dp[61]); + /* 62 */ + COMBA_FORWARD; + MULADD(at[15], at[95]); MULADD(at[16], at[94]); MULADD(at[17], at[93]); MULADD(at[18], at[92]); MULADD(at[19], at[91]); MULADD(at[20], at[90]); MULADD(at[21], at[89]); MULADD(at[22], at[88]); MULADD(at[23], at[87]); MULADD(at[24], at[86]); MULADD(at[25], at[85]); MULADD(at[26], at[84]); MULADD(at[27], at[83]); MULADD(at[28], at[82]); MULADD(at[29], at[81]); MULADD(at[30], at[80]); MULADD(at[31], at[79]); MULADD(at[32], at[78]); MULADD(at[33], at[77]); MULADD(at[34], at[76]); MULADD(at[35], at[75]); MULADD(at[36], at[74]); MULADD(at[37], at[73]); MULADD(at[38], at[72]); MULADD(at[39], at[71]); MULADD(at[40], at[70]); MULADD(at[41], at[69]); MULADD(at[42], at[68]); MULADD(at[43], at[67]); MULADD(at[44], at[66]); MULADD(at[45], at[65]); MULADD(at[46], at[64]); MULADD(at[47], at[63]); + COMBA_STORE(C->dp[62]); + /* 63 */ + COMBA_FORWARD; + MULADD(at[16], at[95]); MULADD(at[17], at[94]); MULADD(at[18], at[93]); MULADD(at[19], at[92]); MULADD(at[20], at[91]); MULADD(at[21], at[90]); MULADD(at[22], at[89]); MULADD(at[23], at[88]); MULADD(at[24], at[87]); MULADD(at[25], at[86]); MULADD(at[26], at[85]); MULADD(at[27], at[84]); MULADD(at[28], at[83]); MULADD(at[29], at[82]); MULADD(at[30], at[81]); MULADD(at[31], at[80]); MULADD(at[32], at[79]); MULADD(at[33], at[78]); MULADD(at[34], at[77]); MULADD(at[35], at[76]); MULADD(at[36], at[75]); MULADD(at[37], at[74]); MULADD(at[38], at[73]); MULADD(at[39], at[72]); MULADD(at[40], at[71]); MULADD(at[41], at[70]); MULADD(at[42], at[69]); MULADD(at[43], at[68]); MULADD(at[44], at[67]); MULADD(at[45], at[66]); MULADD(at[46], at[65]); MULADD(at[47], at[64]); + COMBA_STORE(C->dp[63]); + /* 64 */ + COMBA_FORWARD; + MULADD(at[17], at[95]); MULADD(at[18], at[94]); MULADD(at[19], at[93]); MULADD(at[20], at[92]); MULADD(at[21], at[91]); MULADD(at[22], at[90]); MULADD(at[23], at[89]); MULADD(at[24], at[88]); MULADD(at[25], at[87]); MULADD(at[26], at[86]); MULADD(at[27], at[85]); MULADD(at[28], at[84]); MULADD(at[29], at[83]); MULADD(at[30], at[82]); MULADD(at[31], at[81]); MULADD(at[32], at[80]); MULADD(at[33], at[79]); MULADD(at[34], at[78]); MULADD(at[35], at[77]); MULADD(at[36], at[76]); MULADD(at[37], at[75]); MULADD(at[38], at[74]); MULADD(at[39], at[73]); MULADD(at[40], at[72]); MULADD(at[41], at[71]); MULADD(at[42], at[70]); MULADD(at[43], at[69]); MULADD(at[44], at[68]); MULADD(at[45], at[67]); MULADD(at[46], at[66]); MULADD(at[47], at[65]); + COMBA_STORE(C->dp[64]); + /* 65 */ + COMBA_FORWARD; + MULADD(at[18], at[95]); MULADD(at[19], at[94]); MULADD(at[20], at[93]); MULADD(at[21], at[92]); MULADD(at[22], at[91]); MULADD(at[23], at[90]); MULADD(at[24], at[89]); MULADD(at[25], at[88]); MULADD(at[26], at[87]); MULADD(at[27], at[86]); MULADD(at[28], at[85]); MULADD(at[29], at[84]); MULADD(at[30], at[83]); MULADD(at[31], at[82]); MULADD(at[32], at[81]); MULADD(at[33], at[80]); MULADD(at[34], at[79]); MULADD(at[35], at[78]); MULADD(at[36], at[77]); MULADD(at[37], at[76]); MULADD(at[38], at[75]); MULADD(at[39], at[74]); MULADD(at[40], at[73]); MULADD(at[41], at[72]); MULADD(at[42], at[71]); MULADD(at[43], at[70]); MULADD(at[44], at[69]); MULADD(at[45], at[68]); MULADD(at[46], at[67]); MULADD(at[47], at[66]); + COMBA_STORE(C->dp[65]); + /* 66 */ + COMBA_FORWARD; + MULADD(at[19], at[95]); MULADD(at[20], at[94]); MULADD(at[21], at[93]); MULADD(at[22], at[92]); MULADD(at[23], at[91]); MULADD(at[24], at[90]); MULADD(at[25], at[89]); MULADD(at[26], at[88]); MULADD(at[27], at[87]); MULADD(at[28], at[86]); MULADD(at[29], at[85]); MULADD(at[30], at[84]); MULADD(at[31], at[83]); MULADD(at[32], at[82]); MULADD(at[33], at[81]); MULADD(at[34], at[80]); MULADD(at[35], at[79]); MULADD(at[36], at[78]); MULADD(at[37], at[77]); MULADD(at[38], at[76]); MULADD(at[39], at[75]); MULADD(at[40], at[74]); MULADD(at[41], at[73]); MULADD(at[42], at[72]); MULADD(at[43], at[71]); MULADD(at[44], at[70]); MULADD(at[45], at[69]); MULADD(at[46], at[68]); MULADD(at[47], at[67]); + COMBA_STORE(C->dp[66]); + /* 67 */ + COMBA_FORWARD; + MULADD(at[20], at[95]); MULADD(at[21], at[94]); MULADD(at[22], at[93]); MULADD(at[23], at[92]); MULADD(at[24], at[91]); MULADD(at[25], at[90]); MULADD(at[26], at[89]); MULADD(at[27], at[88]); MULADD(at[28], at[87]); MULADD(at[29], at[86]); MULADD(at[30], at[85]); MULADD(at[31], at[84]); MULADD(at[32], at[83]); MULADD(at[33], at[82]); MULADD(at[34], at[81]); MULADD(at[35], at[80]); MULADD(at[36], at[79]); MULADD(at[37], at[78]); MULADD(at[38], at[77]); MULADD(at[39], at[76]); MULADD(at[40], at[75]); MULADD(at[41], at[74]); MULADD(at[42], at[73]); MULADD(at[43], at[72]); MULADD(at[44], at[71]); MULADD(at[45], at[70]); MULADD(at[46], at[69]); MULADD(at[47], at[68]); + COMBA_STORE(C->dp[67]); + /* 68 */ + COMBA_FORWARD; + MULADD(at[21], at[95]); MULADD(at[22], at[94]); MULADD(at[23], at[93]); MULADD(at[24], at[92]); MULADD(at[25], at[91]); MULADD(at[26], at[90]); MULADD(at[27], at[89]); MULADD(at[28], at[88]); MULADD(at[29], at[87]); MULADD(at[30], at[86]); MULADD(at[31], at[85]); MULADD(at[32], at[84]); MULADD(at[33], at[83]); MULADD(at[34], at[82]); MULADD(at[35], at[81]); MULADD(at[36], at[80]); MULADD(at[37], at[79]); MULADD(at[38], at[78]); MULADD(at[39], at[77]); MULADD(at[40], at[76]); MULADD(at[41], at[75]); MULADD(at[42], at[74]); MULADD(at[43], at[73]); MULADD(at[44], at[72]); MULADD(at[45], at[71]); MULADD(at[46], at[70]); MULADD(at[47], at[69]); + COMBA_STORE(C->dp[68]); + /* 69 */ + COMBA_FORWARD; + MULADD(at[22], at[95]); MULADD(at[23], at[94]); MULADD(at[24], at[93]); MULADD(at[25], at[92]); MULADD(at[26], at[91]); MULADD(at[27], at[90]); MULADD(at[28], at[89]); MULADD(at[29], at[88]); MULADD(at[30], at[87]); MULADD(at[31], at[86]); MULADD(at[32], at[85]); MULADD(at[33], at[84]); MULADD(at[34], at[83]); MULADD(at[35], at[82]); MULADD(at[36], at[81]); MULADD(at[37], at[80]); MULADD(at[38], at[79]); MULADD(at[39], at[78]); MULADD(at[40], at[77]); MULADD(at[41], at[76]); MULADD(at[42], at[75]); MULADD(at[43], at[74]); MULADD(at[44], at[73]); MULADD(at[45], at[72]); MULADD(at[46], at[71]); MULADD(at[47], at[70]); + COMBA_STORE(C->dp[69]); + /* 70 */ + COMBA_FORWARD; + MULADD(at[23], at[95]); MULADD(at[24], at[94]); MULADD(at[25], at[93]); MULADD(at[26], at[92]); MULADD(at[27], at[91]); MULADD(at[28], at[90]); MULADD(at[29], at[89]); MULADD(at[30], at[88]); MULADD(at[31], at[87]); MULADD(at[32], at[86]); MULADD(at[33], at[85]); MULADD(at[34], at[84]); MULADD(at[35], at[83]); MULADD(at[36], at[82]); MULADD(at[37], at[81]); MULADD(at[38], at[80]); MULADD(at[39], at[79]); MULADD(at[40], at[78]); MULADD(at[41], at[77]); MULADD(at[42], at[76]); MULADD(at[43], at[75]); MULADD(at[44], at[74]); MULADD(at[45], at[73]); MULADD(at[46], at[72]); MULADD(at[47], at[71]); + COMBA_STORE(C->dp[70]); + /* 71 */ + COMBA_FORWARD; + MULADD(at[24], at[95]); MULADD(at[25], at[94]); MULADD(at[26], at[93]); MULADD(at[27], at[92]); MULADD(at[28], at[91]); MULADD(at[29], at[90]); MULADD(at[30], at[89]); MULADD(at[31], at[88]); MULADD(at[32], at[87]); MULADD(at[33], at[86]); MULADD(at[34], at[85]); MULADD(at[35], at[84]); MULADD(at[36], at[83]); MULADD(at[37], at[82]); MULADD(at[38], at[81]); MULADD(at[39], at[80]); MULADD(at[40], at[79]); MULADD(at[41], at[78]); MULADD(at[42], at[77]); MULADD(at[43], at[76]); MULADD(at[44], at[75]); MULADD(at[45], at[74]); MULADD(at[46], at[73]); MULADD(at[47], at[72]); + COMBA_STORE(C->dp[71]); + /* 72 */ + COMBA_FORWARD; + MULADD(at[25], at[95]); MULADD(at[26], at[94]); MULADD(at[27], at[93]); MULADD(at[28], at[92]); MULADD(at[29], at[91]); MULADD(at[30], at[90]); MULADD(at[31], at[89]); MULADD(at[32], at[88]); MULADD(at[33], at[87]); MULADD(at[34], at[86]); MULADD(at[35], at[85]); MULADD(at[36], at[84]); MULADD(at[37], at[83]); MULADD(at[38], at[82]); MULADD(at[39], at[81]); MULADD(at[40], at[80]); MULADD(at[41], at[79]); MULADD(at[42], at[78]); MULADD(at[43], at[77]); MULADD(at[44], at[76]); MULADD(at[45], at[75]); MULADD(at[46], at[74]); MULADD(at[47], at[73]); + COMBA_STORE(C->dp[72]); + /* 73 */ + COMBA_FORWARD; + MULADD(at[26], at[95]); MULADD(at[27], at[94]); MULADD(at[28], at[93]); MULADD(at[29], at[92]); MULADD(at[30], at[91]); MULADD(at[31], at[90]); MULADD(at[32], at[89]); MULADD(at[33], at[88]); MULADD(at[34], at[87]); MULADD(at[35], at[86]); MULADD(at[36], at[85]); MULADD(at[37], at[84]); MULADD(at[38], at[83]); MULADD(at[39], at[82]); MULADD(at[40], at[81]); MULADD(at[41], at[80]); MULADD(at[42], at[79]); MULADD(at[43], at[78]); MULADD(at[44], at[77]); MULADD(at[45], at[76]); MULADD(at[46], at[75]); MULADD(at[47], at[74]); + COMBA_STORE(C->dp[73]); + /* 74 */ + COMBA_FORWARD; + MULADD(at[27], at[95]); MULADD(at[28], at[94]); MULADD(at[29], at[93]); MULADD(at[30], at[92]); MULADD(at[31], at[91]); MULADD(at[32], at[90]); MULADD(at[33], at[89]); MULADD(at[34], at[88]); MULADD(at[35], at[87]); MULADD(at[36], at[86]); MULADD(at[37], at[85]); MULADD(at[38], at[84]); MULADD(at[39], at[83]); MULADD(at[40], at[82]); MULADD(at[41], at[81]); MULADD(at[42], at[80]); MULADD(at[43], at[79]); MULADD(at[44], at[78]); MULADD(at[45], at[77]); MULADD(at[46], at[76]); MULADD(at[47], at[75]); + COMBA_STORE(C->dp[74]); + /* 75 */ + COMBA_FORWARD; + MULADD(at[28], at[95]); MULADD(at[29], at[94]); MULADD(at[30], at[93]); MULADD(at[31], at[92]); MULADD(at[32], at[91]); MULADD(at[33], at[90]); MULADD(at[34], at[89]); MULADD(at[35], at[88]); MULADD(at[36], at[87]); MULADD(at[37], at[86]); MULADD(at[38], at[85]); MULADD(at[39], at[84]); MULADD(at[40], at[83]); MULADD(at[41], at[82]); MULADD(at[42], at[81]); MULADD(at[43], at[80]); MULADD(at[44], at[79]); MULADD(at[45], at[78]); MULADD(at[46], at[77]); MULADD(at[47], at[76]); + COMBA_STORE(C->dp[75]); + /* 76 */ + COMBA_FORWARD; + MULADD(at[29], at[95]); MULADD(at[30], at[94]); MULADD(at[31], at[93]); MULADD(at[32], at[92]); MULADD(at[33], at[91]); MULADD(at[34], at[90]); MULADD(at[35], at[89]); MULADD(at[36], at[88]); MULADD(at[37], at[87]); MULADD(at[38], at[86]); MULADD(at[39], at[85]); MULADD(at[40], at[84]); MULADD(at[41], at[83]); MULADD(at[42], at[82]); MULADD(at[43], at[81]); MULADD(at[44], at[80]); MULADD(at[45], at[79]); MULADD(at[46], at[78]); MULADD(at[47], at[77]); + COMBA_STORE(C->dp[76]); + /* 77 */ + COMBA_FORWARD; + MULADD(at[30], at[95]); MULADD(at[31], at[94]); MULADD(at[32], at[93]); MULADD(at[33], at[92]); MULADD(at[34], at[91]); MULADD(at[35], at[90]); MULADD(at[36], at[89]); MULADD(at[37], at[88]); MULADD(at[38], at[87]); MULADD(at[39], at[86]); MULADD(at[40], at[85]); MULADD(at[41], at[84]); MULADD(at[42], at[83]); MULADD(at[43], at[82]); MULADD(at[44], at[81]); MULADD(at[45], at[80]); MULADD(at[46], at[79]); MULADD(at[47], at[78]); + COMBA_STORE(C->dp[77]); + /* 78 */ + COMBA_FORWARD; + MULADD(at[31], at[95]); MULADD(at[32], at[94]); MULADD(at[33], at[93]); MULADD(at[34], at[92]); MULADD(at[35], at[91]); MULADD(at[36], at[90]); MULADD(at[37], at[89]); MULADD(at[38], at[88]); MULADD(at[39], at[87]); MULADD(at[40], at[86]); MULADD(at[41], at[85]); MULADD(at[42], at[84]); MULADD(at[43], at[83]); MULADD(at[44], at[82]); MULADD(at[45], at[81]); MULADD(at[46], at[80]); MULADD(at[47], at[79]); + COMBA_STORE(C->dp[78]); + /* 79 */ + COMBA_FORWARD; + MULADD(at[32], at[95]); MULADD(at[33], at[94]); MULADD(at[34], at[93]); MULADD(at[35], at[92]); MULADD(at[36], at[91]); MULADD(at[37], at[90]); MULADD(at[38], at[89]); MULADD(at[39], at[88]); MULADD(at[40], at[87]); MULADD(at[41], at[86]); MULADD(at[42], at[85]); MULADD(at[43], at[84]); MULADD(at[44], at[83]); MULADD(at[45], at[82]); MULADD(at[46], at[81]); MULADD(at[47], at[80]); + COMBA_STORE(C->dp[79]); + /* 80 */ + COMBA_FORWARD; + MULADD(at[33], at[95]); MULADD(at[34], at[94]); MULADD(at[35], at[93]); MULADD(at[36], at[92]); MULADD(at[37], at[91]); MULADD(at[38], at[90]); MULADD(at[39], at[89]); MULADD(at[40], at[88]); MULADD(at[41], at[87]); MULADD(at[42], at[86]); MULADD(at[43], at[85]); MULADD(at[44], at[84]); MULADD(at[45], at[83]); MULADD(at[46], at[82]); MULADD(at[47], at[81]); + COMBA_STORE(C->dp[80]); + /* 81 */ + COMBA_FORWARD; + MULADD(at[34], at[95]); MULADD(at[35], at[94]); MULADD(at[36], at[93]); MULADD(at[37], at[92]); MULADD(at[38], at[91]); MULADD(at[39], at[90]); MULADD(at[40], at[89]); MULADD(at[41], at[88]); MULADD(at[42], at[87]); MULADD(at[43], at[86]); MULADD(at[44], at[85]); MULADD(at[45], at[84]); MULADD(at[46], at[83]); MULADD(at[47], at[82]); + COMBA_STORE(C->dp[81]); + /* 82 */ + COMBA_FORWARD; + MULADD(at[35], at[95]); MULADD(at[36], at[94]); MULADD(at[37], at[93]); MULADD(at[38], at[92]); MULADD(at[39], at[91]); MULADD(at[40], at[90]); MULADD(at[41], at[89]); MULADD(at[42], at[88]); MULADD(at[43], at[87]); MULADD(at[44], at[86]); MULADD(at[45], at[85]); MULADD(at[46], at[84]); MULADD(at[47], at[83]); + COMBA_STORE(C->dp[82]); + /* 83 */ + COMBA_FORWARD; + MULADD(at[36], at[95]); MULADD(at[37], at[94]); MULADD(at[38], at[93]); MULADD(at[39], at[92]); MULADD(at[40], at[91]); MULADD(at[41], at[90]); MULADD(at[42], at[89]); MULADD(at[43], at[88]); MULADD(at[44], at[87]); MULADD(at[45], at[86]); MULADD(at[46], at[85]); MULADD(at[47], at[84]); + COMBA_STORE(C->dp[83]); + /* 84 */ + COMBA_FORWARD; + MULADD(at[37], at[95]); MULADD(at[38], at[94]); MULADD(at[39], at[93]); MULADD(at[40], at[92]); MULADD(at[41], at[91]); MULADD(at[42], at[90]); MULADD(at[43], at[89]); MULADD(at[44], at[88]); MULADD(at[45], at[87]); MULADD(at[46], at[86]); MULADD(at[47], at[85]); + COMBA_STORE(C->dp[84]); + /* 85 */ + COMBA_FORWARD; + MULADD(at[38], at[95]); MULADD(at[39], at[94]); MULADD(at[40], at[93]); MULADD(at[41], at[92]); MULADD(at[42], at[91]); MULADD(at[43], at[90]); MULADD(at[44], at[89]); MULADD(at[45], at[88]); MULADD(at[46], at[87]); MULADD(at[47], at[86]); + COMBA_STORE(C->dp[85]); + /* 86 */ + COMBA_FORWARD; + MULADD(at[39], at[95]); MULADD(at[40], at[94]); MULADD(at[41], at[93]); MULADD(at[42], at[92]); MULADD(at[43], at[91]); MULADD(at[44], at[90]); MULADD(at[45], at[89]); MULADD(at[46], at[88]); MULADD(at[47], at[87]); + COMBA_STORE(C->dp[86]); + /* 87 */ + COMBA_FORWARD; + MULADD(at[40], at[95]); MULADD(at[41], at[94]); MULADD(at[42], at[93]); MULADD(at[43], at[92]); MULADD(at[44], at[91]); MULADD(at[45], at[90]); MULADD(at[46], at[89]); MULADD(at[47], at[88]); + COMBA_STORE(C->dp[87]); + /* 88 */ + COMBA_FORWARD; + MULADD(at[41], at[95]); MULADD(at[42], at[94]); MULADD(at[43], at[93]); MULADD(at[44], at[92]); MULADD(at[45], at[91]); MULADD(at[46], at[90]); MULADD(at[47], at[89]); + COMBA_STORE(C->dp[88]); + /* 89 */ + COMBA_FORWARD; + MULADD(at[42], at[95]); MULADD(at[43], at[94]); MULADD(at[44], at[93]); MULADD(at[45], at[92]); MULADD(at[46], at[91]); MULADD(at[47], at[90]); + COMBA_STORE(C->dp[89]); + /* 90 */ + COMBA_FORWARD; + MULADD(at[43], at[95]); MULADD(at[44], at[94]); MULADD(at[45], at[93]); MULADD(at[46], at[92]); MULADD(at[47], at[91]); + COMBA_STORE(C->dp[90]); + /* 91 */ + COMBA_FORWARD; + MULADD(at[44], at[95]); MULADD(at[45], at[94]); MULADD(at[46], at[93]); MULADD(at[47], at[92]); + COMBA_STORE(C->dp[91]); + /* 92 */ + COMBA_FORWARD; + MULADD(at[45], at[95]); MULADD(at[46], at[94]); MULADD(at[47], at[93]); + COMBA_STORE(C->dp[92]); + /* 93 */ + COMBA_FORWARD; + MULADD(at[46], at[95]); MULADD(at[47], at[94]); + COMBA_STORE(C->dp[93]); + /* 94 */ + COMBA_FORWARD; + MULADD(at[47], at[95]); + COMBA_STORE(C->dp[94]); + COMBA_STORE2(C->dp[95]); + C->used = 96; + C->sign = A->sign ^ B->sign; + fp_clamp(C); + COMBA_FINI; + +#ifdef WOLFSSL_SMALL_STACK + XFREE(at, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; +} +#endif diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_mul_comba_6.i b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_mul_comba_6.i new file mode 100755 index 0000000..a2fcb4a --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_mul_comba_6.i @@ -0,0 +1,99 @@ +/* fp_mul_comba_6.i + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifdef TFM_MUL6 +int fp_mul_comba6(fp_int *A, fp_int *B, fp_int *C) +{ + fp_digit c0, c1, c2; +#ifndef WOLFSSL_SMALL_STACK + fp_digit at[12]; +#else + fp_digit *at; +#endif + +#ifdef WOLFSSL_SMALL_STACK + at = (fp_digit*)XMALLOC(sizeof(fp_digit) * 12, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (at == NULL) + return FP_MEM; +#endif + + XMEMCPY(at, A->dp, 6 * sizeof(fp_digit)); + XMEMCPY(at+6, B->dp, 6 * sizeof(fp_digit)); + COMBA_START; + + COMBA_CLEAR; + /* 0 */ + MULADD(at[0], at[6]); + COMBA_STORE(C->dp[0]); + /* 1 */ + COMBA_FORWARD; + MULADD(at[0], at[7]); MULADD(at[1], at[6]); + COMBA_STORE(C->dp[1]); + /* 2 */ + COMBA_FORWARD; + MULADD(at[0], at[8]); MULADD(at[1], at[7]); MULADD(at[2], at[6]); + COMBA_STORE(C->dp[2]); + /* 3 */ + COMBA_FORWARD; + MULADD(at[0], at[9]); MULADD(at[1], at[8]); MULADD(at[2], at[7]); MULADD(at[3], at[6]); + COMBA_STORE(C->dp[3]); + /* 4 */ + COMBA_FORWARD; + MULADD(at[0], at[10]); MULADD(at[1], at[9]); MULADD(at[2], at[8]); MULADD(at[3], at[7]); MULADD(at[4], at[6]); + COMBA_STORE(C->dp[4]); + /* 5 */ + COMBA_FORWARD; + MULADD(at[0], at[11]); MULADD(at[1], at[10]); MULADD(at[2], at[9]); MULADD(at[3], at[8]); MULADD(at[4], at[7]); MULADD(at[5], at[6]); + COMBA_STORE(C->dp[5]); + /* 6 */ + COMBA_FORWARD; + MULADD(at[1], at[11]); MULADD(at[2], at[10]); MULADD(at[3], at[9]); MULADD(at[4], at[8]); MULADD(at[5], at[7]); + COMBA_STORE(C->dp[6]); + /* 7 */ + COMBA_FORWARD; + MULADD(at[2], at[11]); MULADD(at[3], at[10]); MULADD(at[4], at[9]); MULADD(at[5], at[8]); + COMBA_STORE(C->dp[7]); + /* 8 */ + COMBA_FORWARD; + MULADD(at[3], at[11]); MULADD(at[4], at[10]); MULADD(at[5], at[9]); + COMBA_STORE(C->dp[8]); + /* 9 */ + COMBA_FORWARD; + MULADD(at[4], at[11]); MULADD(at[5], at[10]); + COMBA_STORE(C->dp[9]); + /* 10 */ + COMBA_FORWARD; + MULADD(at[5], at[11]); + COMBA_STORE(C->dp[10]); + COMBA_STORE2(C->dp[11]); + C->used = 12; + C->sign = A->sign ^ B->sign; + fp_clamp(C); + COMBA_FINI; + +#ifdef WOLFSSL_SMALL_STACK + XFREE(at, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; +} +#endif diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_mul_comba_64.i b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_mul_comba_64.i new file mode 100755 index 0000000..584f8fe --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_mul_comba_64.i @@ -0,0 +1,563 @@ +/* fp_mul_comba_64.i + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifdef TFM_MUL64 +int fp_mul_comba64(fp_int *A, fp_int *B, fp_int *C) +{ + fp_digit c0, c1, c2; +#ifndef WOLFSSL_SMALL_STACK + fp_digit at[128]; +#else + fp_digit *at; +#endif + +#ifdef WOLFSSL_SMALL_STACK + at = (fp_digit*)XMALLOC(sizeof(fp_digit) * 128, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (at == NULL) + return FP_MEM; +#endif + + XMEMCPY(at, A->dp, 64 * sizeof(fp_digit)); + XMEMCPY(at+64, B->dp, 64 * sizeof(fp_digit)); + COMBA_START; + + COMBA_CLEAR; + /* 0 */ + MULADD(at[0], at[64]); + COMBA_STORE(C->dp[0]); + /* 1 */ + COMBA_FORWARD; + MULADD(at[0], at[65]); MULADD(at[1], at[64]); + COMBA_STORE(C->dp[1]); + /* 2 */ + COMBA_FORWARD; + MULADD(at[0], at[66]); MULADD(at[1], at[65]); MULADD(at[2], at[64]); + COMBA_STORE(C->dp[2]); + /* 3 */ + COMBA_FORWARD; + MULADD(at[0], at[67]); MULADD(at[1], at[66]); MULADD(at[2], at[65]); MULADD(at[3], at[64]); + COMBA_STORE(C->dp[3]); + /* 4 */ + COMBA_FORWARD; + MULADD(at[0], at[68]); MULADD(at[1], at[67]); MULADD(at[2], at[66]); MULADD(at[3], at[65]); MULADD(at[4], at[64]); + COMBA_STORE(C->dp[4]); + /* 5 */ + COMBA_FORWARD; + MULADD(at[0], at[69]); MULADD(at[1], at[68]); MULADD(at[2], at[67]); MULADD(at[3], at[66]); MULADD(at[4], at[65]); MULADD(at[5], at[64]); + COMBA_STORE(C->dp[5]); + /* 6 */ + COMBA_FORWARD; + MULADD(at[0], at[70]); MULADD(at[1], at[69]); MULADD(at[2], at[68]); MULADD(at[3], at[67]); MULADD(at[4], at[66]); MULADD(at[5], at[65]); MULADD(at[6], at[64]); + COMBA_STORE(C->dp[6]); + /* 7 */ + COMBA_FORWARD; + MULADD(at[0], at[71]); MULADD(at[1], at[70]); MULADD(at[2], at[69]); MULADD(at[3], at[68]); MULADD(at[4], at[67]); MULADD(at[5], at[66]); MULADD(at[6], at[65]); MULADD(at[7], at[64]); + COMBA_STORE(C->dp[7]); + /* 8 */ + COMBA_FORWARD; + MULADD(at[0], at[72]); MULADD(at[1], at[71]); MULADD(at[2], at[70]); MULADD(at[3], at[69]); MULADD(at[4], at[68]); MULADD(at[5], at[67]); MULADD(at[6], at[66]); MULADD(at[7], at[65]); MULADD(at[8], at[64]); + COMBA_STORE(C->dp[8]); + /* 9 */ + COMBA_FORWARD; + MULADD(at[0], at[73]); MULADD(at[1], at[72]); MULADD(at[2], at[71]); MULADD(at[3], at[70]); MULADD(at[4], at[69]); MULADD(at[5], at[68]); MULADD(at[6], at[67]); MULADD(at[7], at[66]); MULADD(at[8], at[65]); MULADD(at[9], at[64]); + COMBA_STORE(C->dp[9]); + /* 10 */ + COMBA_FORWARD; + MULADD(at[0], at[74]); MULADD(at[1], at[73]); MULADD(at[2], at[72]); MULADD(at[3], at[71]); MULADD(at[4], at[70]); MULADD(at[5], at[69]); MULADD(at[6], at[68]); MULADD(at[7], at[67]); MULADD(at[8], at[66]); MULADD(at[9], at[65]); MULADD(at[10], at[64]); + COMBA_STORE(C->dp[10]); + /* 11 */ + COMBA_FORWARD; + MULADD(at[0], at[75]); MULADD(at[1], at[74]); MULADD(at[2], at[73]); MULADD(at[3], at[72]); MULADD(at[4], at[71]); MULADD(at[5], at[70]); MULADD(at[6], at[69]); MULADD(at[7], at[68]); MULADD(at[8], at[67]); MULADD(at[9], at[66]); MULADD(at[10], at[65]); MULADD(at[11], at[64]); + COMBA_STORE(C->dp[11]); + /* 12 */ + COMBA_FORWARD; + MULADD(at[0], at[76]); MULADD(at[1], at[75]); MULADD(at[2], at[74]); MULADD(at[3], at[73]); MULADD(at[4], at[72]); MULADD(at[5], at[71]); MULADD(at[6], at[70]); MULADD(at[7], at[69]); MULADD(at[8], at[68]); MULADD(at[9], at[67]); MULADD(at[10], at[66]); MULADD(at[11], at[65]); MULADD(at[12], at[64]); + COMBA_STORE(C->dp[12]); + /* 13 */ + COMBA_FORWARD; + MULADD(at[0], at[77]); MULADD(at[1], at[76]); MULADD(at[2], at[75]); MULADD(at[3], at[74]); MULADD(at[4], at[73]); MULADD(at[5], at[72]); MULADD(at[6], at[71]); MULADD(at[7], at[70]); MULADD(at[8], at[69]); MULADD(at[9], at[68]); MULADD(at[10], at[67]); MULADD(at[11], at[66]); MULADD(at[12], at[65]); MULADD(at[13], at[64]); + COMBA_STORE(C->dp[13]); + /* 14 */ + COMBA_FORWARD; + MULADD(at[0], at[78]); MULADD(at[1], at[77]); MULADD(at[2], at[76]); MULADD(at[3], at[75]); MULADD(at[4], at[74]); MULADD(at[5], at[73]); MULADD(at[6], at[72]); MULADD(at[7], at[71]); MULADD(at[8], at[70]); MULADD(at[9], at[69]); MULADD(at[10], at[68]); MULADD(at[11], at[67]); MULADD(at[12], at[66]); MULADD(at[13], at[65]); MULADD(at[14], at[64]); + COMBA_STORE(C->dp[14]); + /* 15 */ + COMBA_FORWARD; + MULADD(at[0], at[79]); MULADD(at[1], at[78]); MULADD(at[2], at[77]); MULADD(at[3], at[76]); MULADD(at[4], at[75]); MULADD(at[5], at[74]); MULADD(at[6], at[73]); MULADD(at[7], at[72]); MULADD(at[8], at[71]); MULADD(at[9], at[70]); MULADD(at[10], at[69]); MULADD(at[11], at[68]); MULADD(at[12], at[67]); MULADD(at[13], at[66]); MULADD(at[14], at[65]); MULADD(at[15], at[64]); + COMBA_STORE(C->dp[15]); + /* 16 */ + COMBA_FORWARD; + MULADD(at[0], at[80]); MULADD(at[1], at[79]); MULADD(at[2], at[78]); MULADD(at[3], at[77]); MULADD(at[4], at[76]); MULADD(at[5], at[75]); MULADD(at[6], at[74]); MULADD(at[7], at[73]); MULADD(at[8], at[72]); MULADD(at[9], at[71]); MULADD(at[10], at[70]); MULADD(at[11], at[69]); MULADD(at[12], at[68]); MULADD(at[13], at[67]); MULADD(at[14], at[66]); MULADD(at[15], at[65]); MULADD(at[16], at[64]); + COMBA_STORE(C->dp[16]); + /* 17 */ + COMBA_FORWARD; + MULADD(at[0], at[81]); MULADD(at[1], at[80]); MULADD(at[2], at[79]); MULADD(at[3], at[78]); MULADD(at[4], at[77]); MULADD(at[5], at[76]); MULADD(at[6], at[75]); MULADD(at[7], at[74]); MULADD(at[8], at[73]); MULADD(at[9], at[72]); MULADD(at[10], at[71]); MULADD(at[11], at[70]); MULADD(at[12], at[69]); MULADD(at[13], at[68]); MULADD(at[14], at[67]); MULADD(at[15], at[66]); MULADD(at[16], at[65]); MULADD(at[17], at[64]); + COMBA_STORE(C->dp[17]); + /* 18 */ + COMBA_FORWARD; + MULADD(at[0], at[82]); MULADD(at[1], at[81]); MULADD(at[2], at[80]); MULADD(at[3], at[79]); MULADD(at[4], at[78]); MULADD(at[5], at[77]); MULADD(at[6], at[76]); MULADD(at[7], at[75]); MULADD(at[8], at[74]); MULADD(at[9], at[73]); MULADD(at[10], at[72]); MULADD(at[11], at[71]); MULADD(at[12], at[70]); MULADD(at[13], at[69]); MULADD(at[14], at[68]); MULADD(at[15], at[67]); MULADD(at[16], at[66]); MULADD(at[17], at[65]); MULADD(at[18], at[64]); + COMBA_STORE(C->dp[18]); + /* 19 */ + COMBA_FORWARD; + MULADD(at[0], at[83]); MULADD(at[1], at[82]); MULADD(at[2], at[81]); MULADD(at[3], at[80]); MULADD(at[4], at[79]); MULADD(at[5], at[78]); MULADD(at[6], at[77]); MULADD(at[7], at[76]); MULADD(at[8], at[75]); MULADD(at[9], at[74]); MULADD(at[10], at[73]); MULADD(at[11], at[72]); MULADD(at[12], at[71]); MULADD(at[13], at[70]); MULADD(at[14], at[69]); MULADD(at[15], at[68]); MULADD(at[16], at[67]); MULADD(at[17], at[66]); MULADD(at[18], at[65]); MULADD(at[19], at[64]); + COMBA_STORE(C->dp[19]); + /* 20 */ + COMBA_FORWARD; + MULADD(at[0], at[84]); MULADD(at[1], at[83]); MULADD(at[2], at[82]); MULADD(at[3], at[81]); MULADD(at[4], at[80]); MULADD(at[5], at[79]); MULADD(at[6], at[78]); MULADD(at[7], at[77]); MULADD(at[8], at[76]); MULADD(at[9], at[75]); MULADD(at[10], at[74]); MULADD(at[11], at[73]); MULADD(at[12], at[72]); MULADD(at[13], at[71]); MULADD(at[14], at[70]); MULADD(at[15], at[69]); MULADD(at[16], at[68]); MULADD(at[17], at[67]); MULADD(at[18], at[66]); MULADD(at[19], at[65]); MULADD(at[20], at[64]); + COMBA_STORE(C->dp[20]); + /* 21 */ + COMBA_FORWARD; + MULADD(at[0], at[85]); MULADD(at[1], at[84]); MULADD(at[2], at[83]); MULADD(at[3], at[82]); MULADD(at[4], at[81]); MULADD(at[5], at[80]); MULADD(at[6], at[79]); MULADD(at[7], at[78]); MULADD(at[8], at[77]); MULADD(at[9], at[76]); MULADD(at[10], at[75]); MULADD(at[11], at[74]); MULADD(at[12], at[73]); MULADD(at[13], at[72]); MULADD(at[14], at[71]); MULADD(at[15], at[70]); MULADD(at[16], at[69]); MULADD(at[17], at[68]); MULADD(at[18], at[67]); MULADD(at[19], at[66]); MULADD(at[20], at[65]); MULADD(at[21], at[64]); + COMBA_STORE(C->dp[21]); + /* 22 */ + COMBA_FORWARD; + MULADD(at[0], at[86]); MULADD(at[1], at[85]); MULADD(at[2], at[84]); MULADD(at[3], at[83]); MULADD(at[4], at[82]); MULADD(at[5], at[81]); MULADD(at[6], at[80]); MULADD(at[7], at[79]); MULADD(at[8], at[78]); MULADD(at[9], at[77]); MULADD(at[10], at[76]); MULADD(at[11], at[75]); MULADD(at[12], at[74]); MULADD(at[13], at[73]); MULADD(at[14], at[72]); MULADD(at[15], at[71]); MULADD(at[16], at[70]); MULADD(at[17], at[69]); MULADD(at[18], at[68]); MULADD(at[19], at[67]); MULADD(at[20], at[66]); MULADD(at[21], at[65]); MULADD(at[22], at[64]); + COMBA_STORE(C->dp[22]); + /* 23 */ + COMBA_FORWARD; + MULADD(at[0], at[87]); MULADD(at[1], at[86]); MULADD(at[2], at[85]); MULADD(at[3], at[84]); MULADD(at[4], at[83]); MULADD(at[5], at[82]); MULADD(at[6], at[81]); MULADD(at[7], at[80]); MULADD(at[8], at[79]); MULADD(at[9], at[78]); MULADD(at[10], at[77]); MULADD(at[11], at[76]); MULADD(at[12], at[75]); MULADD(at[13], at[74]); MULADD(at[14], at[73]); MULADD(at[15], at[72]); MULADD(at[16], at[71]); MULADD(at[17], at[70]); MULADD(at[18], at[69]); MULADD(at[19], at[68]); MULADD(at[20], at[67]); MULADD(at[21], at[66]); MULADD(at[22], at[65]); MULADD(at[23], at[64]); + COMBA_STORE(C->dp[23]); + /* 24 */ + COMBA_FORWARD; + MULADD(at[0], at[88]); MULADD(at[1], at[87]); MULADD(at[2], at[86]); MULADD(at[3], at[85]); MULADD(at[4], at[84]); MULADD(at[5], at[83]); MULADD(at[6], at[82]); MULADD(at[7], at[81]); MULADD(at[8], at[80]); MULADD(at[9], at[79]); MULADD(at[10], at[78]); MULADD(at[11], at[77]); MULADD(at[12], at[76]); MULADD(at[13], at[75]); MULADD(at[14], at[74]); MULADD(at[15], at[73]); MULADD(at[16], at[72]); MULADD(at[17], at[71]); MULADD(at[18], at[70]); MULADD(at[19], at[69]); MULADD(at[20], at[68]); MULADD(at[21], at[67]); MULADD(at[22], at[66]); MULADD(at[23], at[65]); MULADD(at[24], at[64]); + COMBA_STORE(C->dp[24]); + /* 25 */ + COMBA_FORWARD; + MULADD(at[0], at[89]); MULADD(at[1], at[88]); MULADD(at[2], at[87]); MULADD(at[3], at[86]); MULADD(at[4], at[85]); MULADD(at[5], at[84]); MULADD(at[6], at[83]); MULADD(at[7], at[82]); MULADD(at[8], at[81]); MULADD(at[9], at[80]); MULADD(at[10], at[79]); MULADD(at[11], at[78]); MULADD(at[12], at[77]); MULADD(at[13], at[76]); MULADD(at[14], at[75]); MULADD(at[15], at[74]); MULADD(at[16], at[73]); MULADD(at[17], at[72]); MULADD(at[18], at[71]); MULADD(at[19], at[70]); MULADD(at[20], at[69]); MULADD(at[21], at[68]); MULADD(at[22], at[67]); MULADD(at[23], at[66]); MULADD(at[24], at[65]); MULADD(at[25], at[64]); + COMBA_STORE(C->dp[25]); + /* 26 */ + COMBA_FORWARD; + MULADD(at[0], at[90]); MULADD(at[1], at[89]); MULADD(at[2], at[88]); MULADD(at[3], at[87]); MULADD(at[4], at[86]); MULADD(at[5], at[85]); MULADD(at[6], at[84]); MULADD(at[7], at[83]); MULADD(at[8], at[82]); MULADD(at[9], at[81]); MULADD(at[10], at[80]); MULADD(at[11], at[79]); MULADD(at[12], at[78]); MULADD(at[13], at[77]); MULADD(at[14], at[76]); MULADD(at[15], at[75]); MULADD(at[16], at[74]); MULADD(at[17], at[73]); MULADD(at[18], at[72]); MULADD(at[19], at[71]); MULADD(at[20], at[70]); MULADD(at[21], at[69]); MULADD(at[22], at[68]); MULADD(at[23], at[67]); MULADD(at[24], at[66]); MULADD(at[25], at[65]); MULADD(at[26], at[64]); + COMBA_STORE(C->dp[26]); + /* 27 */ + COMBA_FORWARD; + MULADD(at[0], at[91]); MULADD(at[1], at[90]); MULADD(at[2], at[89]); MULADD(at[3], at[88]); MULADD(at[4], at[87]); MULADD(at[5], at[86]); MULADD(at[6], at[85]); MULADD(at[7], at[84]); MULADD(at[8], at[83]); MULADD(at[9], at[82]); MULADD(at[10], at[81]); MULADD(at[11], at[80]); MULADD(at[12], at[79]); MULADD(at[13], at[78]); MULADD(at[14], at[77]); MULADD(at[15], at[76]); MULADD(at[16], at[75]); MULADD(at[17], at[74]); MULADD(at[18], at[73]); MULADD(at[19], at[72]); MULADD(at[20], at[71]); MULADD(at[21], at[70]); MULADD(at[22], at[69]); MULADD(at[23], at[68]); MULADD(at[24], at[67]); MULADD(at[25], at[66]); MULADD(at[26], at[65]); MULADD(at[27], at[64]); + COMBA_STORE(C->dp[27]); + /* 28 */ + COMBA_FORWARD; + MULADD(at[0], at[92]); MULADD(at[1], at[91]); MULADD(at[2], at[90]); MULADD(at[3], at[89]); MULADD(at[4], at[88]); MULADD(at[5], at[87]); MULADD(at[6], at[86]); MULADD(at[7], at[85]); MULADD(at[8], at[84]); MULADD(at[9], at[83]); MULADD(at[10], at[82]); MULADD(at[11], at[81]); MULADD(at[12], at[80]); MULADD(at[13], at[79]); MULADD(at[14], at[78]); MULADD(at[15], at[77]); MULADD(at[16], at[76]); MULADD(at[17], at[75]); MULADD(at[18], at[74]); MULADD(at[19], at[73]); MULADD(at[20], at[72]); MULADD(at[21], at[71]); MULADD(at[22], at[70]); MULADD(at[23], at[69]); MULADD(at[24], at[68]); MULADD(at[25], at[67]); MULADD(at[26], at[66]); MULADD(at[27], at[65]); MULADD(at[28], at[64]); + COMBA_STORE(C->dp[28]); + /* 29 */ + COMBA_FORWARD; + MULADD(at[0], at[93]); MULADD(at[1], at[92]); MULADD(at[2], at[91]); MULADD(at[3], at[90]); MULADD(at[4], at[89]); MULADD(at[5], at[88]); MULADD(at[6], at[87]); MULADD(at[7], at[86]); MULADD(at[8], at[85]); MULADD(at[9], at[84]); MULADD(at[10], at[83]); MULADD(at[11], at[82]); MULADD(at[12], at[81]); MULADD(at[13], at[80]); MULADD(at[14], at[79]); MULADD(at[15], at[78]); MULADD(at[16], at[77]); MULADD(at[17], at[76]); MULADD(at[18], at[75]); MULADD(at[19], at[74]); MULADD(at[20], at[73]); MULADD(at[21], at[72]); MULADD(at[22], at[71]); MULADD(at[23], at[70]); MULADD(at[24], at[69]); MULADD(at[25], at[68]); MULADD(at[26], at[67]); MULADD(at[27], at[66]); MULADD(at[28], at[65]); MULADD(at[29], at[64]); + COMBA_STORE(C->dp[29]); + /* 30 */ + COMBA_FORWARD; + MULADD(at[0], at[94]); MULADD(at[1], at[93]); MULADD(at[2], at[92]); MULADD(at[3], at[91]); MULADD(at[4], at[90]); MULADD(at[5], at[89]); MULADD(at[6], at[88]); MULADD(at[7], at[87]); MULADD(at[8], at[86]); MULADD(at[9], at[85]); MULADD(at[10], at[84]); MULADD(at[11], at[83]); MULADD(at[12], at[82]); MULADD(at[13], at[81]); MULADD(at[14], at[80]); MULADD(at[15], at[79]); MULADD(at[16], at[78]); MULADD(at[17], at[77]); MULADD(at[18], at[76]); MULADD(at[19], at[75]); MULADD(at[20], at[74]); MULADD(at[21], at[73]); MULADD(at[22], at[72]); MULADD(at[23], at[71]); MULADD(at[24], at[70]); MULADD(at[25], at[69]); MULADD(at[26], at[68]); MULADD(at[27], at[67]); MULADD(at[28], at[66]); MULADD(at[29], at[65]); MULADD(at[30], at[64]); + COMBA_STORE(C->dp[30]); + /* 31 */ + COMBA_FORWARD; + MULADD(at[0], at[95]); MULADD(at[1], at[94]); MULADD(at[2], at[93]); MULADD(at[3], at[92]); MULADD(at[4], at[91]); MULADD(at[5], at[90]); MULADD(at[6], at[89]); MULADD(at[7], at[88]); MULADD(at[8], at[87]); MULADD(at[9], at[86]); MULADD(at[10], at[85]); MULADD(at[11], at[84]); MULADD(at[12], at[83]); MULADD(at[13], at[82]); MULADD(at[14], at[81]); MULADD(at[15], at[80]); MULADD(at[16], at[79]); MULADD(at[17], at[78]); MULADD(at[18], at[77]); MULADD(at[19], at[76]); MULADD(at[20], at[75]); MULADD(at[21], at[74]); MULADD(at[22], at[73]); MULADD(at[23], at[72]); MULADD(at[24], at[71]); MULADD(at[25], at[70]); MULADD(at[26], at[69]); MULADD(at[27], at[68]); MULADD(at[28], at[67]); MULADD(at[29], at[66]); MULADD(at[30], at[65]); MULADD(at[31], at[64]); + COMBA_STORE(C->dp[31]); + /* 32 */ + COMBA_FORWARD; + MULADD(at[0], at[96]); MULADD(at[1], at[95]); MULADD(at[2], at[94]); MULADD(at[3], at[93]); MULADD(at[4], at[92]); MULADD(at[5], at[91]); MULADD(at[6], at[90]); MULADD(at[7], at[89]); MULADD(at[8], at[88]); MULADD(at[9], at[87]); MULADD(at[10], at[86]); MULADD(at[11], at[85]); MULADD(at[12], at[84]); MULADD(at[13], at[83]); MULADD(at[14], at[82]); MULADD(at[15], at[81]); MULADD(at[16], at[80]); MULADD(at[17], at[79]); MULADD(at[18], at[78]); MULADD(at[19], at[77]); MULADD(at[20], at[76]); MULADD(at[21], at[75]); MULADD(at[22], at[74]); MULADD(at[23], at[73]); MULADD(at[24], at[72]); MULADD(at[25], at[71]); MULADD(at[26], at[70]); MULADD(at[27], at[69]); MULADD(at[28], at[68]); MULADD(at[29], at[67]); MULADD(at[30], at[66]); MULADD(at[31], at[65]); MULADD(at[32], at[64]); + COMBA_STORE(C->dp[32]); + /* 33 */ + COMBA_FORWARD; + MULADD(at[0], at[97]); MULADD(at[1], at[96]); MULADD(at[2], at[95]); MULADD(at[3], at[94]); MULADD(at[4], at[93]); MULADD(at[5], at[92]); MULADD(at[6], at[91]); MULADD(at[7], at[90]); MULADD(at[8], at[89]); MULADD(at[9], at[88]); MULADD(at[10], at[87]); MULADD(at[11], at[86]); MULADD(at[12], at[85]); MULADD(at[13], at[84]); MULADD(at[14], at[83]); MULADD(at[15], at[82]); MULADD(at[16], at[81]); MULADD(at[17], at[80]); MULADD(at[18], at[79]); MULADD(at[19], at[78]); MULADD(at[20], at[77]); MULADD(at[21], at[76]); MULADD(at[22], at[75]); MULADD(at[23], at[74]); MULADD(at[24], at[73]); MULADD(at[25], at[72]); MULADD(at[26], at[71]); MULADD(at[27], at[70]); MULADD(at[28], at[69]); MULADD(at[29], at[68]); MULADD(at[30], at[67]); MULADD(at[31], at[66]); MULADD(at[32], at[65]); MULADD(at[33], at[64]); + COMBA_STORE(C->dp[33]); + /* 34 */ + COMBA_FORWARD; + MULADD(at[0], at[98]); MULADD(at[1], at[97]); MULADD(at[2], at[96]); MULADD(at[3], at[95]); MULADD(at[4], at[94]); MULADD(at[5], at[93]); MULADD(at[6], at[92]); MULADD(at[7], at[91]); MULADD(at[8], at[90]); MULADD(at[9], at[89]); MULADD(at[10], at[88]); MULADD(at[11], at[87]); MULADD(at[12], at[86]); MULADD(at[13], at[85]); MULADD(at[14], at[84]); MULADD(at[15], at[83]); MULADD(at[16], at[82]); MULADD(at[17], at[81]); MULADD(at[18], at[80]); MULADD(at[19], at[79]); MULADD(at[20], at[78]); MULADD(at[21], at[77]); MULADD(at[22], at[76]); MULADD(at[23], at[75]); MULADD(at[24], at[74]); MULADD(at[25], at[73]); MULADD(at[26], at[72]); MULADD(at[27], at[71]); MULADD(at[28], at[70]); MULADD(at[29], at[69]); MULADD(at[30], at[68]); MULADD(at[31], at[67]); MULADD(at[32], at[66]); MULADD(at[33], at[65]); MULADD(at[34], at[64]); + COMBA_STORE(C->dp[34]); + /* 35 */ + COMBA_FORWARD; + MULADD(at[0], at[99]); MULADD(at[1], at[98]); MULADD(at[2], at[97]); MULADD(at[3], at[96]); MULADD(at[4], at[95]); MULADD(at[5], at[94]); MULADD(at[6], at[93]); MULADD(at[7], at[92]); MULADD(at[8], at[91]); MULADD(at[9], at[90]); MULADD(at[10], at[89]); MULADD(at[11], at[88]); MULADD(at[12], at[87]); MULADD(at[13], at[86]); MULADD(at[14], at[85]); MULADD(at[15], at[84]); MULADD(at[16], at[83]); MULADD(at[17], at[82]); MULADD(at[18], at[81]); MULADD(at[19], at[80]); MULADD(at[20], at[79]); MULADD(at[21], at[78]); MULADD(at[22], at[77]); MULADD(at[23], at[76]); MULADD(at[24], at[75]); MULADD(at[25], at[74]); MULADD(at[26], at[73]); MULADD(at[27], at[72]); MULADD(at[28], at[71]); MULADD(at[29], at[70]); MULADD(at[30], at[69]); MULADD(at[31], at[68]); MULADD(at[32], at[67]); MULADD(at[33], at[66]); MULADD(at[34], at[65]); MULADD(at[35], at[64]); + COMBA_STORE(C->dp[35]); + /* 36 */ + COMBA_FORWARD; + MULADD(at[0], at[100]); MULADD(at[1], at[99]); MULADD(at[2], at[98]); MULADD(at[3], at[97]); MULADD(at[4], at[96]); MULADD(at[5], at[95]); MULADD(at[6], at[94]); MULADD(at[7], at[93]); MULADD(at[8], at[92]); MULADD(at[9], at[91]); MULADD(at[10], at[90]); MULADD(at[11], at[89]); MULADD(at[12], at[88]); MULADD(at[13], at[87]); MULADD(at[14], at[86]); MULADD(at[15], at[85]); MULADD(at[16], at[84]); MULADD(at[17], at[83]); MULADD(at[18], at[82]); MULADD(at[19], at[81]); MULADD(at[20], at[80]); MULADD(at[21], at[79]); MULADD(at[22], at[78]); MULADD(at[23], at[77]); MULADD(at[24], at[76]); MULADD(at[25], at[75]); MULADD(at[26], at[74]); MULADD(at[27], at[73]); MULADD(at[28], at[72]); MULADD(at[29], at[71]); MULADD(at[30], at[70]); MULADD(at[31], at[69]); MULADD(at[32], at[68]); MULADD(at[33], at[67]); MULADD(at[34], at[66]); MULADD(at[35], at[65]); MULADD(at[36], at[64]); + COMBA_STORE(C->dp[36]); + /* 37 */ + COMBA_FORWARD; + MULADD(at[0], at[101]); MULADD(at[1], at[100]); MULADD(at[2], at[99]); MULADD(at[3], at[98]); MULADD(at[4], at[97]); MULADD(at[5], at[96]); MULADD(at[6], at[95]); MULADD(at[7], at[94]); MULADD(at[8], at[93]); MULADD(at[9], at[92]); MULADD(at[10], at[91]); MULADD(at[11], at[90]); MULADD(at[12], at[89]); MULADD(at[13], at[88]); MULADD(at[14], at[87]); MULADD(at[15], at[86]); MULADD(at[16], at[85]); MULADD(at[17], at[84]); MULADD(at[18], at[83]); MULADD(at[19], at[82]); MULADD(at[20], at[81]); MULADD(at[21], at[80]); MULADD(at[22], at[79]); MULADD(at[23], at[78]); MULADD(at[24], at[77]); MULADD(at[25], at[76]); MULADD(at[26], at[75]); MULADD(at[27], at[74]); MULADD(at[28], at[73]); MULADD(at[29], at[72]); MULADD(at[30], at[71]); MULADD(at[31], at[70]); MULADD(at[32], at[69]); MULADD(at[33], at[68]); MULADD(at[34], at[67]); MULADD(at[35], at[66]); MULADD(at[36], at[65]); MULADD(at[37], at[64]); + COMBA_STORE(C->dp[37]); + /* 38 */ + COMBA_FORWARD; + MULADD(at[0], at[102]); MULADD(at[1], at[101]); MULADD(at[2], at[100]); MULADD(at[3], at[99]); MULADD(at[4], at[98]); MULADD(at[5], at[97]); MULADD(at[6], at[96]); MULADD(at[7], at[95]); MULADD(at[8], at[94]); MULADD(at[9], at[93]); MULADD(at[10], at[92]); MULADD(at[11], at[91]); MULADD(at[12], at[90]); MULADD(at[13], at[89]); MULADD(at[14], at[88]); MULADD(at[15], at[87]); MULADD(at[16], at[86]); MULADD(at[17], at[85]); MULADD(at[18], at[84]); MULADD(at[19], at[83]); MULADD(at[20], at[82]); MULADD(at[21], at[81]); MULADD(at[22], at[80]); MULADD(at[23], at[79]); MULADD(at[24], at[78]); MULADD(at[25], at[77]); MULADD(at[26], at[76]); MULADD(at[27], at[75]); MULADD(at[28], at[74]); MULADD(at[29], at[73]); MULADD(at[30], at[72]); MULADD(at[31], at[71]); MULADD(at[32], at[70]); MULADD(at[33], at[69]); MULADD(at[34], at[68]); MULADD(at[35], at[67]); MULADD(at[36], at[66]); MULADD(at[37], at[65]); MULADD(at[38], at[64]); + COMBA_STORE(C->dp[38]); + /* 39 */ + COMBA_FORWARD; + MULADD(at[0], at[103]); MULADD(at[1], at[102]); MULADD(at[2], at[101]); MULADD(at[3], at[100]); MULADD(at[4], at[99]); MULADD(at[5], at[98]); MULADD(at[6], at[97]); MULADD(at[7], at[96]); MULADD(at[8], at[95]); MULADD(at[9], at[94]); MULADD(at[10], at[93]); MULADD(at[11], at[92]); MULADD(at[12], at[91]); MULADD(at[13], at[90]); MULADD(at[14], at[89]); MULADD(at[15], at[88]); MULADD(at[16], at[87]); MULADD(at[17], at[86]); MULADD(at[18], at[85]); MULADD(at[19], at[84]); MULADD(at[20], at[83]); MULADD(at[21], at[82]); MULADD(at[22], at[81]); MULADD(at[23], at[80]); MULADD(at[24], at[79]); MULADD(at[25], at[78]); MULADD(at[26], at[77]); MULADD(at[27], at[76]); MULADD(at[28], at[75]); MULADD(at[29], at[74]); MULADD(at[30], at[73]); MULADD(at[31], at[72]); MULADD(at[32], at[71]); MULADD(at[33], at[70]); MULADD(at[34], at[69]); MULADD(at[35], at[68]); MULADD(at[36], at[67]); MULADD(at[37], at[66]); MULADD(at[38], at[65]); MULADD(at[39], at[64]); + COMBA_STORE(C->dp[39]); + /* 40 */ + COMBA_FORWARD; + MULADD(at[0], at[104]); MULADD(at[1], at[103]); MULADD(at[2], at[102]); MULADD(at[3], at[101]); MULADD(at[4], at[100]); MULADD(at[5], at[99]); MULADD(at[6], at[98]); MULADD(at[7], at[97]); MULADD(at[8], at[96]); MULADD(at[9], at[95]); MULADD(at[10], at[94]); MULADD(at[11], at[93]); MULADD(at[12], at[92]); MULADD(at[13], at[91]); MULADD(at[14], at[90]); MULADD(at[15], at[89]); MULADD(at[16], at[88]); MULADD(at[17], at[87]); MULADD(at[18], at[86]); MULADD(at[19], at[85]); MULADD(at[20], at[84]); MULADD(at[21], at[83]); MULADD(at[22], at[82]); MULADD(at[23], at[81]); MULADD(at[24], at[80]); MULADD(at[25], at[79]); MULADD(at[26], at[78]); MULADD(at[27], at[77]); MULADD(at[28], at[76]); MULADD(at[29], at[75]); MULADD(at[30], at[74]); MULADD(at[31], at[73]); MULADD(at[32], at[72]); MULADD(at[33], at[71]); MULADD(at[34], at[70]); MULADD(at[35], at[69]); MULADD(at[36], at[68]); MULADD(at[37], at[67]); MULADD(at[38], at[66]); MULADD(at[39], at[65]); MULADD(at[40], at[64]); + COMBA_STORE(C->dp[40]); + /* 41 */ + COMBA_FORWARD; + MULADD(at[0], at[105]); MULADD(at[1], at[104]); MULADD(at[2], at[103]); MULADD(at[3], at[102]); MULADD(at[4], at[101]); MULADD(at[5], at[100]); MULADD(at[6], at[99]); MULADD(at[7], at[98]); MULADD(at[8], at[97]); MULADD(at[9], at[96]); MULADD(at[10], at[95]); MULADD(at[11], at[94]); MULADD(at[12], at[93]); MULADD(at[13], at[92]); MULADD(at[14], at[91]); MULADD(at[15], at[90]); MULADD(at[16], at[89]); MULADD(at[17], at[88]); MULADD(at[18], at[87]); MULADD(at[19], at[86]); MULADD(at[20], at[85]); MULADD(at[21], at[84]); MULADD(at[22], at[83]); MULADD(at[23], at[82]); MULADD(at[24], at[81]); MULADD(at[25], at[80]); MULADD(at[26], at[79]); MULADD(at[27], at[78]); MULADD(at[28], at[77]); MULADD(at[29], at[76]); MULADD(at[30], at[75]); MULADD(at[31], at[74]); MULADD(at[32], at[73]); MULADD(at[33], at[72]); MULADD(at[34], at[71]); MULADD(at[35], at[70]); MULADD(at[36], at[69]); MULADD(at[37], at[68]); MULADD(at[38], at[67]); MULADD(at[39], at[66]); MULADD(at[40], at[65]); MULADD(at[41], at[64]); + COMBA_STORE(C->dp[41]); + /* 42 */ + COMBA_FORWARD; + MULADD(at[0], at[106]); MULADD(at[1], at[105]); MULADD(at[2], at[104]); MULADD(at[3], at[103]); MULADD(at[4], at[102]); MULADD(at[5], at[101]); MULADD(at[6], at[100]); MULADD(at[7], at[99]); MULADD(at[8], at[98]); MULADD(at[9], at[97]); MULADD(at[10], at[96]); MULADD(at[11], at[95]); MULADD(at[12], at[94]); MULADD(at[13], at[93]); MULADD(at[14], at[92]); MULADD(at[15], at[91]); MULADD(at[16], at[90]); MULADD(at[17], at[89]); MULADD(at[18], at[88]); MULADD(at[19], at[87]); MULADD(at[20], at[86]); MULADD(at[21], at[85]); MULADD(at[22], at[84]); MULADD(at[23], at[83]); MULADD(at[24], at[82]); MULADD(at[25], at[81]); MULADD(at[26], at[80]); MULADD(at[27], at[79]); MULADD(at[28], at[78]); MULADD(at[29], at[77]); MULADD(at[30], at[76]); MULADD(at[31], at[75]); MULADD(at[32], at[74]); MULADD(at[33], at[73]); MULADD(at[34], at[72]); MULADD(at[35], at[71]); MULADD(at[36], at[70]); MULADD(at[37], at[69]); MULADD(at[38], at[68]); MULADD(at[39], at[67]); MULADD(at[40], at[66]); MULADD(at[41], at[65]); MULADD(at[42], at[64]); + COMBA_STORE(C->dp[42]); + /* 43 */ + COMBA_FORWARD; + MULADD(at[0], at[107]); MULADD(at[1], at[106]); MULADD(at[2], at[105]); MULADD(at[3], at[104]); MULADD(at[4], at[103]); MULADD(at[5], at[102]); MULADD(at[6], at[101]); MULADD(at[7], at[100]); MULADD(at[8], at[99]); MULADD(at[9], at[98]); MULADD(at[10], at[97]); MULADD(at[11], at[96]); MULADD(at[12], at[95]); MULADD(at[13], at[94]); MULADD(at[14], at[93]); MULADD(at[15], at[92]); MULADD(at[16], at[91]); MULADD(at[17], at[90]); MULADD(at[18], at[89]); MULADD(at[19], at[88]); MULADD(at[20], at[87]); MULADD(at[21], at[86]); MULADD(at[22], at[85]); MULADD(at[23], at[84]); MULADD(at[24], at[83]); MULADD(at[25], at[82]); MULADD(at[26], at[81]); MULADD(at[27], at[80]); MULADD(at[28], at[79]); MULADD(at[29], at[78]); MULADD(at[30], at[77]); MULADD(at[31], at[76]); MULADD(at[32], at[75]); MULADD(at[33], at[74]); MULADD(at[34], at[73]); MULADD(at[35], at[72]); MULADD(at[36], at[71]); MULADD(at[37], at[70]); MULADD(at[38], at[69]); MULADD(at[39], at[68]); MULADD(at[40], at[67]); MULADD(at[41], at[66]); MULADD(at[42], at[65]); MULADD(at[43], at[64]); + COMBA_STORE(C->dp[43]); + /* 44 */ + COMBA_FORWARD; + MULADD(at[0], at[108]); MULADD(at[1], at[107]); MULADD(at[2], at[106]); MULADD(at[3], at[105]); MULADD(at[4], at[104]); MULADD(at[5], at[103]); MULADD(at[6], at[102]); MULADD(at[7], at[101]); MULADD(at[8], at[100]); MULADD(at[9], at[99]); MULADD(at[10], at[98]); MULADD(at[11], at[97]); MULADD(at[12], at[96]); MULADD(at[13], at[95]); MULADD(at[14], at[94]); MULADD(at[15], at[93]); MULADD(at[16], at[92]); MULADD(at[17], at[91]); MULADD(at[18], at[90]); MULADD(at[19], at[89]); MULADD(at[20], at[88]); MULADD(at[21], at[87]); MULADD(at[22], at[86]); MULADD(at[23], at[85]); MULADD(at[24], at[84]); MULADD(at[25], at[83]); MULADD(at[26], at[82]); MULADD(at[27], at[81]); MULADD(at[28], at[80]); MULADD(at[29], at[79]); MULADD(at[30], at[78]); MULADD(at[31], at[77]); MULADD(at[32], at[76]); MULADD(at[33], at[75]); MULADD(at[34], at[74]); MULADD(at[35], at[73]); MULADD(at[36], at[72]); MULADD(at[37], at[71]); MULADD(at[38], at[70]); MULADD(at[39], at[69]); MULADD(at[40], at[68]); MULADD(at[41], at[67]); MULADD(at[42], at[66]); MULADD(at[43], at[65]); MULADD(at[44], at[64]); + COMBA_STORE(C->dp[44]); + /* 45 */ + COMBA_FORWARD; + MULADD(at[0], at[109]); MULADD(at[1], at[108]); MULADD(at[2], at[107]); MULADD(at[3], at[106]); MULADD(at[4], at[105]); MULADD(at[5], at[104]); MULADD(at[6], at[103]); MULADD(at[7], at[102]); MULADD(at[8], at[101]); MULADD(at[9], at[100]); MULADD(at[10], at[99]); MULADD(at[11], at[98]); MULADD(at[12], at[97]); MULADD(at[13], at[96]); MULADD(at[14], at[95]); MULADD(at[15], at[94]); MULADD(at[16], at[93]); MULADD(at[17], at[92]); MULADD(at[18], at[91]); MULADD(at[19], at[90]); MULADD(at[20], at[89]); MULADD(at[21], at[88]); MULADD(at[22], at[87]); MULADD(at[23], at[86]); MULADD(at[24], at[85]); MULADD(at[25], at[84]); MULADD(at[26], at[83]); MULADD(at[27], at[82]); MULADD(at[28], at[81]); MULADD(at[29], at[80]); MULADD(at[30], at[79]); MULADD(at[31], at[78]); MULADD(at[32], at[77]); MULADD(at[33], at[76]); MULADD(at[34], at[75]); MULADD(at[35], at[74]); MULADD(at[36], at[73]); MULADD(at[37], at[72]); MULADD(at[38], at[71]); MULADD(at[39], at[70]); MULADD(at[40], at[69]); MULADD(at[41], at[68]); MULADD(at[42], at[67]); MULADD(at[43], at[66]); MULADD(at[44], at[65]); MULADD(at[45], at[64]); + COMBA_STORE(C->dp[45]); + /* 46 */ + COMBA_FORWARD; + MULADD(at[0], at[110]); MULADD(at[1], at[109]); MULADD(at[2], at[108]); MULADD(at[3], at[107]); MULADD(at[4], at[106]); MULADD(at[5], at[105]); MULADD(at[6], at[104]); MULADD(at[7], at[103]); MULADD(at[8], at[102]); MULADD(at[9], at[101]); MULADD(at[10], at[100]); MULADD(at[11], at[99]); MULADD(at[12], at[98]); MULADD(at[13], at[97]); MULADD(at[14], at[96]); MULADD(at[15], at[95]); MULADD(at[16], at[94]); MULADD(at[17], at[93]); MULADD(at[18], at[92]); MULADD(at[19], at[91]); MULADD(at[20], at[90]); MULADD(at[21], at[89]); MULADD(at[22], at[88]); MULADD(at[23], at[87]); MULADD(at[24], at[86]); MULADD(at[25], at[85]); MULADD(at[26], at[84]); MULADD(at[27], at[83]); MULADD(at[28], at[82]); MULADD(at[29], at[81]); MULADD(at[30], at[80]); MULADD(at[31], at[79]); MULADD(at[32], at[78]); MULADD(at[33], at[77]); MULADD(at[34], at[76]); MULADD(at[35], at[75]); MULADD(at[36], at[74]); MULADD(at[37], at[73]); MULADD(at[38], at[72]); MULADD(at[39], at[71]); MULADD(at[40], at[70]); MULADD(at[41], at[69]); MULADD(at[42], at[68]); MULADD(at[43], at[67]); MULADD(at[44], at[66]); MULADD(at[45], at[65]); MULADD(at[46], at[64]); + COMBA_STORE(C->dp[46]); + /* 47 */ + COMBA_FORWARD; + MULADD(at[0], at[111]); MULADD(at[1], at[110]); MULADD(at[2], at[109]); MULADD(at[3], at[108]); MULADD(at[4], at[107]); MULADD(at[5], at[106]); MULADD(at[6], at[105]); MULADD(at[7], at[104]); MULADD(at[8], at[103]); MULADD(at[9], at[102]); MULADD(at[10], at[101]); MULADD(at[11], at[100]); MULADD(at[12], at[99]); MULADD(at[13], at[98]); MULADD(at[14], at[97]); MULADD(at[15], at[96]); MULADD(at[16], at[95]); MULADD(at[17], at[94]); MULADD(at[18], at[93]); MULADD(at[19], at[92]); MULADD(at[20], at[91]); MULADD(at[21], at[90]); MULADD(at[22], at[89]); MULADD(at[23], at[88]); MULADD(at[24], at[87]); MULADD(at[25], at[86]); MULADD(at[26], at[85]); MULADD(at[27], at[84]); MULADD(at[28], at[83]); MULADD(at[29], at[82]); MULADD(at[30], at[81]); MULADD(at[31], at[80]); MULADD(at[32], at[79]); MULADD(at[33], at[78]); MULADD(at[34], at[77]); MULADD(at[35], at[76]); MULADD(at[36], at[75]); MULADD(at[37], at[74]); MULADD(at[38], at[73]); MULADD(at[39], at[72]); MULADD(at[40], at[71]); MULADD(at[41], at[70]); MULADD(at[42], at[69]); MULADD(at[43], at[68]); MULADD(at[44], at[67]); MULADD(at[45], at[66]); MULADD(at[46], at[65]); MULADD(at[47], at[64]); + COMBA_STORE(C->dp[47]); + /* 48 */ + COMBA_FORWARD; + MULADD(at[0], at[112]); MULADD(at[1], at[111]); MULADD(at[2], at[110]); MULADD(at[3], at[109]); MULADD(at[4], at[108]); MULADD(at[5], at[107]); MULADD(at[6], at[106]); MULADD(at[7], at[105]); MULADD(at[8], at[104]); MULADD(at[9], at[103]); MULADD(at[10], at[102]); MULADD(at[11], at[101]); MULADD(at[12], at[100]); MULADD(at[13], at[99]); MULADD(at[14], at[98]); MULADD(at[15], at[97]); MULADD(at[16], at[96]); MULADD(at[17], at[95]); MULADD(at[18], at[94]); MULADD(at[19], at[93]); MULADD(at[20], at[92]); MULADD(at[21], at[91]); MULADD(at[22], at[90]); MULADD(at[23], at[89]); MULADD(at[24], at[88]); MULADD(at[25], at[87]); MULADD(at[26], at[86]); MULADD(at[27], at[85]); MULADD(at[28], at[84]); MULADD(at[29], at[83]); MULADD(at[30], at[82]); MULADD(at[31], at[81]); MULADD(at[32], at[80]); MULADD(at[33], at[79]); MULADD(at[34], at[78]); MULADD(at[35], at[77]); MULADD(at[36], at[76]); MULADD(at[37], at[75]); MULADD(at[38], at[74]); MULADD(at[39], at[73]); MULADD(at[40], at[72]); MULADD(at[41], at[71]); MULADD(at[42], at[70]); MULADD(at[43], at[69]); MULADD(at[44], at[68]); MULADD(at[45], at[67]); MULADD(at[46], at[66]); MULADD(at[47], at[65]); MULADD(at[48], at[64]); + COMBA_STORE(C->dp[48]); + /* 49 */ + COMBA_FORWARD; + MULADD(at[0], at[113]); MULADD(at[1], at[112]); MULADD(at[2], at[111]); MULADD(at[3], at[110]); MULADD(at[4], at[109]); MULADD(at[5], at[108]); MULADD(at[6], at[107]); MULADD(at[7], at[106]); MULADD(at[8], at[105]); MULADD(at[9], at[104]); MULADD(at[10], at[103]); MULADD(at[11], at[102]); MULADD(at[12], at[101]); MULADD(at[13], at[100]); MULADD(at[14], at[99]); MULADD(at[15], at[98]); MULADD(at[16], at[97]); MULADD(at[17], at[96]); MULADD(at[18], at[95]); MULADD(at[19], at[94]); MULADD(at[20], at[93]); MULADD(at[21], at[92]); MULADD(at[22], at[91]); MULADD(at[23], at[90]); MULADD(at[24], at[89]); MULADD(at[25], at[88]); MULADD(at[26], at[87]); MULADD(at[27], at[86]); MULADD(at[28], at[85]); MULADD(at[29], at[84]); MULADD(at[30], at[83]); MULADD(at[31], at[82]); MULADD(at[32], at[81]); MULADD(at[33], at[80]); MULADD(at[34], at[79]); MULADD(at[35], at[78]); MULADD(at[36], at[77]); MULADD(at[37], at[76]); MULADD(at[38], at[75]); MULADD(at[39], at[74]); MULADD(at[40], at[73]); MULADD(at[41], at[72]); MULADD(at[42], at[71]); MULADD(at[43], at[70]); MULADD(at[44], at[69]); MULADD(at[45], at[68]); MULADD(at[46], at[67]); MULADD(at[47], at[66]); MULADD(at[48], at[65]); MULADD(at[49], at[64]); + COMBA_STORE(C->dp[49]); + /* 50 */ + COMBA_FORWARD; + MULADD(at[0], at[114]); MULADD(at[1], at[113]); MULADD(at[2], at[112]); MULADD(at[3], at[111]); MULADD(at[4], at[110]); MULADD(at[5], at[109]); MULADD(at[6], at[108]); MULADD(at[7], at[107]); MULADD(at[8], at[106]); MULADD(at[9], at[105]); MULADD(at[10], at[104]); MULADD(at[11], at[103]); MULADD(at[12], at[102]); MULADD(at[13], at[101]); MULADD(at[14], at[100]); MULADD(at[15], at[99]); MULADD(at[16], at[98]); MULADD(at[17], at[97]); MULADD(at[18], at[96]); MULADD(at[19], at[95]); MULADD(at[20], at[94]); MULADD(at[21], at[93]); MULADD(at[22], at[92]); MULADD(at[23], at[91]); MULADD(at[24], at[90]); MULADD(at[25], at[89]); MULADD(at[26], at[88]); MULADD(at[27], at[87]); MULADD(at[28], at[86]); MULADD(at[29], at[85]); MULADD(at[30], at[84]); MULADD(at[31], at[83]); MULADD(at[32], at[82]); MULADD(at[33], at[81]); MULADD(at[34], at[80]); MULADD(at[35], at[79]); MULADD(at[36], at[78]); MULADD(at[37], at[77]); MULADD(at[38], at[76]); MULADD(at[39], at[75]); MULADD(at[40], at[74]); MULADD(at[41], at[73]); MULADD(at[42], at[72]); MULADD(at[43], at[71]); MULADD(at[44], at[70]); MULADD(at[45], at[69]); MULADD(at[46], at[68]); MULADD(at[47], at[67]); MULADD(at[48], at[66]); MULADD(at[49], at[65]); MULADD(at[50], at[64]); + COMBA_STORE(C->dp[50]); + /* 51 */ + COMBA_FORWARD; + MULADD(at[0], at[115]); MULADD(at[1], at[114]); MULADD(at[2], at[113]); MULADD(at[3], at[112]); MULADD(at[4], at[111]); MULADD(at[5], at[110]); MULADD(at[6], at[109]); MULADD(at[7], at[108]); MULADD(at[8], at[107]); MULADD(at[9], at[106]); MULADD(at[10], at[105]); MULADD(at[11], at[104]); MULADD(at[12], at[103]); MULADD(at[13], at[102]); MULADD(at[14], at[101]); MULADD(at[15], at[100]); MULADD(at[16], at[99]); MULADD(at[17], at[98]); MULADD(at[18], at[97]); MULADD(at[19], at[96]); MULADD(at[20], at[95]); MULADD(at[21], at[94]); MULADD(at[22], at[93]); MULADD(at[23], at[92]); MULADD(at[24], at[91]); MULADD(at[25], at[90]); MULADD(at[26], at[89]); MULADD(at[27], at[88]); MULADD(at[28], at[87]); MULADD(at[29], at[86]); MULADD(at[30], at[85]); MULADD(at[31], at[84]); MULADD(at[32], at[83]); MULADD(at[33], at[82]); MULADD(at[34], at[81]); MULADD(at[35], at[80]); MULADD(at[36], at[79]); MULADD(at[37], at[78]); MULADD(at[38], at[77]); MULADD(at[39], at[76]); MULADD(at[40], at[75]); MULADD(at[41], at[74]); MULADD(at[42], at[73]); MULADD(at[43], at[72]); MULADD(at[44], at[71]); MULADD(at[45], at[70]); MULADD(at[46], at[69]); MULADD(at[47], at[68]); MULADD(at[48], at[67]); MULADD(at[49], at[66]); MULADD(at[50], at[65]); MULADD(at[51], at[64]); + COMBA_STORE(C->dp[51]); + /* 52 */ + COMBA_FORWARD; + MULADD(at[0], at[116]); MULADD(at[1], at[115]); MULADD(at[2], at[114]); MULADD(at[3], at[113]); MULADD(at[4], at[112]); MULADD(at[5], at[111]); MULADD(at[6], at[110]); MULADD(at[7], at[109]); MULADD(at[8], at[108]); MULADD(at[9], at[107]); MULADD(at[10], at[106]); MULADD(at[11], at[105]); MULADD(at[12], at[104]); MULADD(at[13], at[103]); MULADD(at[14], at[102]); MULADD(at[15], at[101]); MULADD(at[16], at[100]); MULADD(at[17], at[99]); MULADD(at[18], at[98]); MULADD(at[19], at[97]); MULADD(at[20], at[96]); MULADD(at[21], at[95]); MULADD(at[22], at[94]); MULADD(at[23], at[93]); MULADD(at[24], at[92]); MULADD(at[25], at[91]); MULADD(at[26], at[90]); MULADD(at[27], at[89]); MULADD(at[28], at[88]); MULADD(at[29], at[87]); MULADD(at[30], at[86]); MULADD(at[31], at[85]); MULADD(at[32], at[84]); MULADD(at[33], at[83]); MULADD(at[34], at[82]); MULADD(at[35], at[81]); MULADD(at[36], at[80]); MULADD(at[37], at[79]); MULADD(at[38], at[78]); MULADD(at[39], at[77]); MULADD(at[40], at[76]); MULADD(at[41], at[75]); MULADD(at[42], at[74]); MULADD(at[43], at[73]); MULADD(at[44], at[72]); MULADD(at[45], at[71]); MULADD(at[46], at[70]); MULADD(at[47], at[69]); MULADD(at[48], at[68]); MULADD(at[49], at[67]); MULADD(at[50], at[66]); MULADD(at[51], at[65]); MULADD(at[52], at[64]); + COMBA_STORE(C->dp[52]); + /* 53 */ + COMBA_FORWARD; + MULADD(at[0], at[117]); MULADD(at[1], at[116]); MULADD(at[2], at[115]); MULADD(at[3], at[114]); MULADD(at[4], at[113]); MULADD(at[5], at[112]); MULADD(at[6], at[111]); MULADD(at[7], at[110]); MULADD(at[8], at[109]); MULADD(at[9], at[108]); MULADD(at[10], at[107]); MULADD(at[11], at[106]); MULADD(at[12], at[105]); MULADD(at[13], at[104]); MULADD(at[14], at[103]); MULADD(at[15], at[102]); MULADD(at[16], at[101]); MULADD(at[17], at[100]); MULADD(at[18], at[99]); MULADD(at[19], at[98]); MULADD(at[20], at[97]); MULADD(at[21], at[96]); MULADD(at[22], at[95]); MULADD(at[23], at[94]); MULADD(at[24], at[93]); MULADD(at[25], at[92]); MULADD(at[26], at[91]); MULADD(at[27], at[90]); MULADD(at[28], at[89]); MULADD(at[29], at[88]); MULADD(at[30], at[87]); MULADD(at[31], at[86]); MULADD(at[32], at[85]); MULADD(at[33], at[84]); MULADD(at[34], at[83]); MULADD(at[35], at[82]); MULADD(at[36], at[81]); MULADD(at[37], at[80]); MULADD(at[38], at[79]); MULADD(at[39], at[78]); MULADD(at[40], at[77]); MULADD(at[41], at[76]); MULADD(at[42], at[75]); MULADD(at[43], at[74]); MULADD(at[44], at[73]); MULADD(at[45], at[72]); MULADD(at[46], at[71]); MULADD(at[47], at[70]); MULADD(at[48], at[69]); MULADD(at[49], at[68]); MULADD(at[50], at[67]); MULADD(at[51], at[66]); MULADD(at[52], at[65]); MULADD(at[53], at[64]); + COMBA_STORE(C->dp[53]); + /* 54 */ + COMBA_FORWARD; + MULADD(at[0], at[118]); MULADD(at[1], at[117]); MULADD(at[2], at[116]); MULADD(at[3], at[115]); MULADD(at[4], at[114]); MULADD(at[5], at[113]); MULADD(at[6], at[112]); MULADD(at[7], at[111]); MULADD(at[8], at[110]); MULADD(at[9], at[109]); MULADD(at[10], at[108]); MULADD(at[11], at[107]); MULADD(at[12], at[106]); MULADD(at[13], at[105]); MULADD(at[14], at[104]); MULADD(at[15], at[103]); MULADD(at[16], at[102]); MULADD(at[17], at[101]); MULADD(at[18], at[100]); MULADD(at[19], at[99]); MULADD(at[20], at[98]); MULADD(at[21], at[97]); MULADD(at[22], at[96]); MULADD(at[23], at[95]); MULADD(at[24], at[94]); MULADD(at[25], at[93]); MULADD(at[26], at[92]); MULADD(at[27], at[91]); MULADD(at[28], at[90]); MULADD(at[29], at[89]); MULADD(at[30], at[88]); MULADD(at[31], at[87]); MULADD(at[32], at[86]); MULADD(at[33], at[85]); MULADD(at[34], at[84]); MULADD(at[35], at[83]); MULADD(at[36], at[82]); MULADD(at[37], at[81]); MULADD(at[38], at[80]); MULADD(at[39], at[79]); MULADD(at[40], at[78]); MULADD(at[41], at[77]); MULADD(at[42], at[76]); MULADD(at[43], at[75]); MULADD(at[44], at[74]); MULADD(at[45], at[73]); MULADD(at[46], at[72]); MULADD(at[47], at[71]); MULADD(at[48], at[70]); MULADD(at[49], at[69]); MULADD(at[50], at[68]); MULADD(at[51], at[67]); MULADD(at[52], at[66]); MULADD(at[53], at[65]); MULADD(at[54], at[64]); + COMBA_STORE(C->dp[54]); + /* 55 */ + COMBA_FORWARD; + MULADD(at[0], at[119]); MULADD(at[1], at[118]); MULADD(at[2], at[117]); MULADD(at[3], at[116]); MULADD(at[4], at[115]); MULADD(at[5], at[114]); MULADD(at[6], at[113]); MULADD(at[7], at[112]); MULADD(at[8], at[111]); MULADD(at[9], at[110]); MULADD(at[10], at[109]); MULADD(at[11], at[108]); MULADD(at[12], at[107]); MULADD(at[13], at[106]); MULADD(at[14], at[105]); MULADD(at[15], at[104]); MULADD(at[16], at[103]); MULADD(at[17], at[102]); MULADD(at[18], at[101]); MULADD(at[19], at[100]); MULADD(at[20], at[99]); MULADD(at[21], at[98]); MULADD(at[22], at[97]); MULADD(at[23], at[96]); MULADD(at[24], at[95]); MULADD(at[25], at[94]); MULADD(at[26], at[93]); MULADD(at[27], at[92]); MULADD(at[28], at[91]); MULADD(at[29], at[90]); MULADD(at[30], at[89]); MULADD(at[31], at[88]); MULADD(at[32], at[87]); MULADD(at[33], at[86]); MULADD(at[34], at[85]); MULADD(at[35], at[84]); MULADD(at[36], at[83]); MULADD(at[37], at[82]); MULADD(at[38], at[81]); MULADD(at[39], at[80]); MULADD(at[40], at[79]); MULADD(at[41], at[78]); MULADD(at[42], at[77]); MULADD(at[43], at[76]); MULADD(at[44], at[75]); MULADD(at[45], at[74]); MULADD(at[46], at[73]); MULADD(at[47], at[72]); MULADD(at[48], at[71]); MULADD(at[49], at[70]); MULADD(at[50], at[69]); MULADD(at[51], at[68]); MULADD(at[52], at[67]); MULADD(at[53], at[66]); MULADD(at[54], at[65]); MULADD(at[55], at[64]); + COMBA_STORE(C->dp[55]); + /* 56 */ + COMBA_FORWARD; + MULADD(at[0], at[120]); MULADD(at[1], at[119]); MULADD(at[2], at[118]); MULADD(at[3], at[117]); MULADD(at[4], at[116]); MULADD(at[5], at[115]); MULADD(at[6], at[114]); MULADD(at[7], at[113]); MULADD(at[8], at[112]); MULADD(at[9], at[111]); MULADD(at[10], at[110]); MULADD(at[11], at[109]); MULADD(at[12], at[108]); MULADD(at[13], at[107]); MULADD(at[14], at[106]); MULADD(at[15], at[105]); MULADD(at[16], at[104]); MULADD(at[17], at[103]); MULADD(at[18], at[102]); MULADD(at[19], at[101]); MULADD(at[20], at[100]); MULADD(at[21], at[99]); MULADD(at[22], at[98]); MULADD(at[23], at[97]); MULADD(at[24], at[96]); MULADD(at[25], at[95]); MULADD(at[26], at[94]); MULADD(at[27], at[93]); MULADD(at[28], at[92]); MULADD(at[29], at[91]); MULADD(at[30], at[90]); MULADD(at[31], at[89]); MULADD(at[32], at[88]); MULADD(at[33], at[87]); MULADD(at[34], at[86]); MULADD(at[35], at[85]); MULADD(at[36], at[84]); MULADD(at[37], at[83]); MULADD(at[38], at[82]); MULADD(at[39], at[81]); MULADD(at[40], at[80]); MULADD(at[41], at[79]); MULADD(at[42], at[78]); MULADD(at[43], at[77]); MULADD(at[44], at[76]); MULADD(at[45], at[75]); MULADD(at[46], at[74]); MULADD(at[47], at[73]); MULADD(at[48], at[72]); MULADD(at[49], at[71]); MULADD(at[50], at[70]); MULADD(at[51], at[69]); MULADD(at[52], at[68]); MULADD(at[53], at[67]); MULADD(at[54], at[66]); MULADD(at[55], at[65]); MULADD(at[56], at[64]); + COMBA_STORE(C->dp[56]); + /* 57 */ + COMBA_FORWARD; + MULADD(at[0], at[121]); MULADD(at[1], at[120]); MULADD(at[2], at[119]); MULADD(at[3], at[118]); MULADD(at[4], at[117]); MULADD(at[5], at[116]); MULADD(at[6], at[115]); MULADD(at[7], at[114]); MULADD(at[8], at[113]); MULADD(at[9], at[112]); MULADD(at[10], at[111]); MULADD(at[11], at[110]); MULADD(at[12], at[109]); MULADD(at[13], at[108]); MULADD(at[14], at[107]); MULADD(at[15], at[106]); MULADD(at[16], at[105]); MULADD(at[17], at[104]); MULADD(at[18], at[103]); MULADD(at[19], at[102]); MULADD(at[20], at[101]); MULADD(at[21], at[100]); MULADD(at[22], at[99]); MULADD(at[23], at[98]); MULADD(at[24], at[97]); MULADD(at[25], at[96]); MULADD(at[26], at[95]); MULADD(at[27], at[94]); MULADD(at[28], at[93]); MULADD(at[29], at[92]); MULADD(at[30], at[91]); MULADD(at[31], at[90]); MULADD(at[32], at[89]); MULADD(at[33], at[88]); MULADD(at[34], at[87]); MULADD(at[35], at[86]); MULADD(at[36], at[85]); MULADD(at[37], at[84]); MULADD(at[38], at[83]); MULADD(at[39], at[82]); MULADD(at[40], at[81]); MULADD(at[41], at[80]); MULADD(at[42], at[79]); MULADD(at[43], at[78]); MULADD(at[44], at[77]); MULADD(at[45], at[76]); MULADD(at[46], at[75]); MULADD(at[47], at[74]); MULADD(at[48], at[73]); MULADD(at[49], at[72]); MULADD(at[50], at[71]); MULADD(at[51], at[70]); MULADD(at[52], at[69]); MULADD(at[53], at[68]); MULADD(at[54], at[67]); MULADD(at[55], at[66]); MULADD(at[56], at[65]); MULADD(at[57], at[64]); + COMBA_STORE(C->dp[57]); + /* 58 */ + COMBA_FORWARD; + MULADD(at[0], at[122]); MULADD(at[1], at[121]); MULADD(at[2], at[120]); MULADD(at[3], at[119]); MULADD(at[4], at[118]); MULADD(at[5], at[117]); MULADD(at[6], at[116]); MULADD(at[7], at[115]); MULADD(at[8], at[114]); MULADD(at[9], at[113]); MULADD(at[10], at[112]); MULADD(at[11], at[111]); MULADD(at[12], at[110]); MULADD(at[13], at[109]); MULADD(at[14], at[108]); MULADD(at[15], at[107]); MULADD(at[16], at[106]); MULADD(at[17], at[105]); MULADD(at[18], at[104]); MULADD(at[19], at[103]); MULADD(at[20], at[102]); MULADD(at[21], at[101]); MULADD(at[22], at[100]); MULADD(at[23], at[99]); MULADD(at[24], at[98]); MULADD(at[25], at[97]); MULADD(at[26], at[96]); MULADD(at[27], at[95]); MULADD(at[28], at[94]); MULADD(at[29], at[93]); MULADD(at[30], at[92]); MULADD(at[31], at[91]); MULADD(at[32], at[90]); MULADD(at[33], at[89]); MULADD(at[34], at[88]); MULADD(at[35], at[87]); MULADD(at[36], at[86]); MULADD(at[37], at[85]); MULADD(at[38], at[84]); MULADD(at[39], at[83]); MULADD(at[40], at[82]); MULADD(at[41], at[81]); MULADD(at[42], at[80]); MULADD(at[43], at[79]); MULADD(at[44], at[78]); MULADD(at[45], at[77]); MULADD(at[46], at[76]); MULADD(at[47], at[75]); MULADD(at[48], at[74]); MULADD(at[49], at[73]); MULADD(at[50], at[72]); MULADD(at[51], at[71]); MULADD(at[52], at[70]); MULADD(at[53], at[69]); MULADD(at[54], at[68]); MULADD(at[55], at[67]); MULADD(at[56], at[66]); MULADD(at[57], at[65]); MULADD(at[58], at[64]); + COMBA_STORE(C->dp[58]); + /* 59 */ + COMBA_FORWARD; + MULADD(at[0], at[123]); MULADD(at[1], at[122]); MULADD(at[2], at[121]); MULADD(at[3], at[120]); MULADD(at[4], at[119]); MULADD(at[5], at[118]); MULADD(at[6], at[117]); MULADD(at[7], at[116]); MULADD(at[8], at[115]); MULADD(at[9], at[114]); MULADD(at[10], at[113]); MULADD(at[11], at[112]); MULADD(at[12], at[111]); MULADD(at[13], at[110]); MULADD(at[14], at[109]); MULADD(at[15], at[108]); MULADD(at[16], at[107]); MULADD(at[17], at[106]); MULADD(at[18], at[105]); MULADD(at[19], at[104]); MULADD(at[20], at[103]); MULADD(at[21], at[102]); MULADD(at[22], at[101]); MULADD(at[23], at[100]); MULADD(at[24], at[99]); MULADD(at[25], at[98]); MULADD(at[26], at[97]); MULADD(at[27], at[96]); MULADD(at[28], at[95]); MULADD(at[29], at[94]); MULADD(at[30], at[93]); MULADD(at[31], at[92]); MULADD(at[32], at[91]); MULADD(at[33], at[90]); MULADD(at[34], at[89]); MULADD(at[35], at[88]); MULADD(at[36], at[87]); MULADD(at[37], at[86]); MULADD(at[38], at[85]); MULADD(at[39], at[84]); MULADD(at[40], at[83]); MULADD(at[41], at[82]); MULADD(at[42], at[81]); MULADD(at[43], at[80]); MULADD(at[44], at[79]); MULADD(at[45], at[78]); MULADD(at[46], at[77]); MULADD(at[47], at[76]); MULADD(at[48], at[75]); MULADD(at[49], at[74]); MULADD(at[50], at[73]); MULADD(at[51], at[72]); MULADD(at[52], at[71]); MULADD(at[53], at[70]); MULADD(at[54], at[69]); MULADD(at[55], at[68]); MULADD(at[56], at[67]); MULADD(at[57], at[66]); MULADD(at[58], at[65]); MULADD(at[59], at[64]); + COMBA_STORE(C->dp[59]); + /* 60 */ + COMBA_FORWARD; + MULADD(at[0], at[124]); MULADD(at[1], at[123]); MULADD(at[2], at[122]); MULADD(at[3], at[121]); MULADD(at[4], at[120]); MULADD(at[5], at[119]); MULADD(at[6], at[118]); MULADD(at[7], at[117]); MULADD(at[8], at[116]); MULADD(at[9], at[115]); MULADD(at[10], at[114]); MULADD(at[11], at[113]); MULADD(at[12], at[112]); MULADD(at[13], at[111]); MULADD(at[14], at[110]); MULADD(at[15], at[109]); MULADD(at[16], at[108]); MULADD(at[17], at[107]); MULADD(at[18], at[106]); MULADD(at[19], at[105]); MULADD(at[20], at[104]); MULADD(at[21], at[103]); MULADD(at[22], at[102]); MULADD(at[23], at[101]); MULADD(at[24], at[100]); MULADD(at[25], at[99]); MULADD(at[26], at[98]); MULADD(at[27], at[97]); MULADD(at[28], at[96]); MULADD(at[29], at[95]); MULADD(at[30], at[94]); MULADD(at[31], at[93]); MULADD(at[32], at[92]); MULADD(at[33], at[91]); MULADD(at[34], at[90]); MULADD(at[35], at[89]); MULADD(at[36], at[88]); MULADD(at[37], at[87]); MULADD(at[38], at[86]); MULADD(at[39], at[85]); MULADD(at[40], at[84]); MULADD(at[41], at[83]); MULADD(at[42], at[82]); MULADD(at[43], at[81]); MULADD(at[44], at[80]); MULADD(at[45], at[79]); MULADD(at[46], at[78]); MULADD(at[47], at[77]); MULADD(at[48], at[76]); MULADD(at[49], at[75]); MULADD(at[50], at[74]); MULADD(at[51], at[73]); MULADD(at[52], at[72]); MULADD(at[53], at[71]); MULADD(at[54], at[70]); MULADD(at[55], at[69]); MULADD(at[56], at[68]); MULADD(at[57], at[67]); MULADD(at[58], at[66]); MULADD(at[59], at[65]); MULADD(at[60], at[64]); + COMBA_STORE(C->dp[60]); + /* 61 */ + COMBA_FORWARD; + MULADD(at[0], at[125]); MULADD(at[1], at[124]); MULADD(at[2], at[123]); MULADD(at[3], at[122]); MULADD(at[4], at[121]); MULADD(at[5], at[120]); MULADD(at[6], at[119]); MULADD(at[7], at[118]); MULADD(at[8], at[117]); MULADD(at[9], at[116]); MULADD(at[10], at[115]); MULADD(at[11], at[114]); MULADD(at[12], at[113]); MULADD(at[13], at[112]); MULADD(at[14], at[111]); MULADD(at[15], at[110]); MULADD(at[16], at[109]); MULADD(at[17], at[108]); MULADD(at[18], at[107]); MULADD(at[19], at[106]); MULADD(at[20], at[105]); MULADD(at[21], at[104]); MULADD(at[22], at[103]); MULADD(at[23], at[102]); MULADD(at[24], at[101]); MULADD(at[25], at[100]); MULADD(at[26], at[99]); MULADD(at[27], at[98]); MULADD(at[28], at[97]); MULADD(at[29], at[96]); MULADD(at[30], at[95]); MULADD(at[31], at[94]); MULADD(at[32], at[93]); MULADD(at[33], at[92]); MULADD(at[34], at[91]); MULADD(at[35], at[90]); MULADD(at[36], at[89]); MULADD(at[37], at[88]); MULADD(at[38], at[87]); MULADD(at[39], at[86]); MULADD(at[40], at[85]); MULADD(at[41], at[84]); MULADD(at[42], at[83]); MULADD(at[43], at[82]); MULADD(at[44], at[81]); MULADD(at[45], at[80]); MULADD(at[46], at[79]); MULADD(at[47], at[78]); MULADD(at[48], at[77]); MULADD(at[49], at[76]); MULADD(at[50], at[75]); MULADD(at[51], at[74]); MULADD(at[52], at[73]); MULADD(at[53], at[72]); MULADD(at[54], at[71]); MULADD(at[55], at[70]); MULADD(at[56], at[69]); MULADD(at[57], at[68]); MULADD(at[58], at[67]); MULADD(at[59], at[66]); MULADD(at[60], at[65]); MULADD(at[61], at[64]); + COMBA_STORE(C->dp[61]); + /* 62 */ + COMBA_FORWARD; + MULADD(at[0], at[126]); MULADD(at[1], at[125]); MULADD(at[2], at[124]); MULADD(at[3], at[123]); MULADD(at[4], at[122]); MULADD(at[5], at[121]); MULADD(at[6], at[120]); MULADD(at[7], at[119]); MULADD(at[8], at[118]); MULADD(at[9], at[117]); MULADD(at[10], at[116]); MULADD(at[11], at[115]); MULADD(at[12], at[114]); MULADD(at[13], at[113]); MULADD(at[14], at[112]); MULADD(at[15], at[111]); MULADD(at[16], at[110]); MULADD(at[17], at[109]); MULADD(at[18], at[108]); MULADD(at[19], at[107]); MULADD(at[20], at[106]); MULADD(at[21], at[105]); MULADD(at[22], at[104]); MULADD(at[23], at[103]); MULADD(at[24], at[102]); MULADD(at[25], at[101]); MULADD(at[26], at[100]); MULADD(at[27], at[99]); MULADD(at[28], at[98]); MULADD(at[29], at[97]); MULADD(at[30], at[96]); MULADD(at[31], at[95]); MULADD(at[32], at[94]); MULADD(at[33], at[93]); MULADD(at[34], at[92]); MULADD(at[35], at[91]); MULADD(at[36], at[90]); MULADD(at[37], at[89]); MULADD(at[38], at[88]); MULADD(at[39], at[87]); MULADD(at[40], at[86]); MULADD(at[41], at[85]); MULADD(at[42], at[84]); MULADD(at[43], at[83]); MULADD(at[44], at[82]); MULADD(at[45], at[81]); MULADD(at[46], at[80]); MULADD(at[47], at[79]); MULADD(at[48], at[78]); MULADD(at[49], at[77]); MULADD(at[50], at[76]); MULADD(at[51], at[75]); MULADD(at[52], at[74]); MULADD(at[53], at[73]); MULADD(at[54], at[72]); MULADD(at[55], at[71]); MULADD(at[56], at[70]); MULADD(at[57], at[69]); MULADD(at[58], at[68]); MULADD(at[59], at[67]); MULADD(at[60], at[66]); MULADD(at[61], at[65]); MULADD(at[62], at[64]); + COMBA_STORE(C->dp[62]); + /* 63 */ + COMBA_FORWARD; + MULADD(at[0], at[127]); MULADD(at[1], at[126]); MULADD(at[2], at[125]); MULADD(at[3], at[124]); MULADD(at[4], at[123]); MULADD(at[5], at[122]); MULADD(at[6], at[121]); MULADD(at[7], at[120]); MULADD(at[8], at[119]); MULADD(at[9], at[118]); MULADD(at[10], at[117]); MULADD(at[11], at[116]); MULADD(at[12], at[115]); MULADD(at[13], at[114]); MULADD(at[14], at[113]); MULADD(at[15], at[112]); MULADD(at[16], at[111]); MULADD(at[17], at[110]); MULADD(at[18], at[109]); MULADD(at[19], at[108]); MULADD(at[20], at[107]); MULADD(at[21], at[106]); MULADD(at[22], at[105]); MULADD(at[23], at[104]); MULADD(at[24], at[103]); MULADD(at[25], at[102]); MULADD(at[26], at[101]); MULADD(at[27], at[100]); MULADD(at[28], at[99]); MULADD(at[29], at[98]); MULADD(at[30], at[97]); MULADD(at[31], at[96]); MULADD(at[32], at[95]); MULADD(at[33], at[94]); MULADD(at[34], at[93]); MULADD(at[35], at[92]); MULADD(at[36], at[91]); MULADD(at[37], at[90]); MULADD(at[38], at[89]); MULADD(at[39], at[88]); MULADD(at[40], at[87]); MULADD(at[41], at[86]); MULADD(at[42], at[85]); MULADD(at[43], at[84]); MULADD(at[44], at[83]); MULADD(at[45], at[82]); MULADD(at[46], at[81]); MULADD(at[47], at[80]); MULADD(at[48], at[79]); MULADD(at[49], at[78]); MULADD(at[50], at[77]); MULADD(at[51], at[76]); MULADD(at[52], at[75]); MULADD(at[53], at[74]); MULADD(at[54], at[73]); MULADD(at[55], at[72]); MULADD(at[56], at[71]); MULADD(at[57], at[70]); MULADD(at[58], at[69]); MULADD(at[59], at[68]); MULADD(at[60], at[67]); MULADD(at[61], at[66]); MULADD(at[62], at[65]); MULADD(at[63], at[64]); + COMBA_STORE(C->dp[63]); + /* 64 */ + COMBA_FORWARD; + MULADD(at[1], at[127]); MULADD(at[2], at[126]); MULADD(at[3], at[125]); MULADD(at[4], at[124]); MULADD(at[5], at[123]); MULADD(at[6], at[122]); MULADD(at[7], at[121]); MULADD(at[8], at[120]); MULADD(at[9], at[119]); MULADD(at[10], at[118]); MULADD(at[11], at[117]); MULADD(at[12], at[116]); MULADD(at[13], at[115]); MULADD(at[14], at[114]); MULADD(at[15], at[113]); MULADD(at[16], at[112]); MULADD(at[17], at[111]); MULADD(at[18], at[110]); MULADD(at[19], at[109]); MULADD(at[20], at[108]); MULADD(at[21], at[107]); MULADD(at[22], at[106]); MULADD(at[23], at[105]); MULADD(at[24], at[104]); MULADD(at[25], at[103]); MULADD(at[26], at[102]); MULADD(at[27], at[101]); MULADD(at[28], at[100]); MULADD(at[29], at[99]); MULADD(at[30], at[98]); MULADD(at[31], at[97]); MULADD(at[32], at[96]); MULADD(at[33], at[95]); MULADD(at[34], at[94]); MULADD(at[35], at[93]); MULADD(at[36], at[92]); MULADD(at[37], at[91]); MULADD(at[38], at[90]); MULADD(at[39], at[89]); MULADD(at[40], at[88]); MULADD(at[41], at[87]); MULADD(at[42], at[86]); MULADD(at[43], at[85]); MULADD(at[44], at[84]); MULADD(at[45], at[83]); MULADD(at[46], at[82]); MULADD(at[47], at[81]); MULADD(at[48], at[80]); MULADD(at[49], at[79]); MULADD(at[50], at[78]); MULADD(at[51], at[77]); MULADD(at[52], at[76]); MULADD(at[53], at[75]); MULADD(at[54], at[74]); MULADD(at[55], at[73]); MULADD(at[56], at[72]); MULADD(at[57], at[71]); MULADD(at[58], at[70]); MULADD(at[59], at[69]); MULADD(at[60], at[68]); MULADD(at[61], at[67]); MULADD(at[62], at[66]); MULADD(at[63], at[65]); + COMBA_STORE(C->dp[64]); + /* 65 */ + COMBA_FORWARD; + MULADD(at[2], at[127]); MULADD(at[3], at[126]); MULADD(at[4], at[125]); MULADD(at[5], at[124]); MULADD(at[6], at[123]); MULADD(at[7], at[122]); MULADD(at[8], at[121]); MULADD(at[9], at[120]); MULADD(at[10], at[119]); MULADD(at[11], at[118]); MULADD(at[12], at[117]); MULADD(at[13], at[116]); MULADD(at[14], at[115]); MULADD(at[15], at[114]); MULADD(at[16], at[113]); MULADD(at[17], at[112]); MULADD(at[18], at[111]); MULADD(at[19], at[110]); MULADD(at[20], at[109]); MULADD(at[21], at[108]); MULADD(at[22], at[107]); MULADD(at[23], at[106]); MULADD(at[24], at[105]); MULADD(at[25], at[104]); MULADD(at[26], at[103]); MULADD(at[27], at[102]); MULADD(at[28], at[101]); MULADD(at[29], at[100]); MULADD(at[30], at[99]); MULADD(at[31], at[98]); MULADD(at[32], at[97]); MULADD(at[33], at[96]); MULADD(at[34], at[95]); MULADD(at[35], at[94]); MULADD(at[36], at[93]); MULADD(at[37], at[92]); MULADD(at[38], at[91]); MULADD(at[39], at[90]); MULADD(at[40], at[89]); MULADD(at[41], at[88]); MULADD(at[42], at[87]); MULADD(at[43], at[86]); MULADD(at[44], at[85]); MULADD(at[45], at[84]); MULADD(at[46], at[83]); MULADD(at[47], at[82]); MULADD(at[48], at[81]); MULADD(at[49], at[80]); MULADD(at[50], at[79]); MULADD(at[51], at[78]); MULADD(at[52], at[77]); MULADD(at[53], at[76]); MULADD(at[54], at[75]); MULADD(at[55], at[74]); MULADD(at[56], at[73]); MULADD(at[57], at[72]); MULADD(at[58], at[71]); MULADD(at[59], at[70]); MULADD(at[60], at[69]); MULADD(at[61], at[68]); MULADD(at[62], at[67]); MULADD(at[63], at[66]); + COMBA_STORE(C->dp[65]); + /* 66 */ + COMBA_FORWARD; + MULADD(at[3], at[127]); MULADD(at[4], at[126]); MULADD(at[5], at[125]); MULADD(at[6], at[124]); MULADD(at[7], at[123]); MULADD(at[8], at[122]); MULADD(at[9], at[121]); MULADD(at[10], at[120]); MULADD(at[11], at[119]); MULADD(at[12], at[118]); MULADD(at[13], at[117]); MULADD(at[14], at[116]); MULADD(at[15], at[115]); MULADD(at[16], at[114]); MULADD(at[17], at[113]); MULADD(at[18], at[112]); MULADD(at[19], at[111]); MULADD(at[20], at[110]); MULADD(at[21], at[109]); MULADD(at[22], at[108]); MULADD(at[23], at[107]); MULADD(at[24], at[106]); MULADD(at[25], at[105]); MULADD(at[26], at[104]); MULADD(at[27], at[103]); MULADD(at[28], at[102]); MULADD(at[29], at[101]); MULADD(at[30], at[100]); MULADD(at[31], at[99]); MULADD(at[32], at[98]); MULADD(at[33], at[97]); MULADD(at[34], at[96]); MULADD(at[35], at[95]); MULADD(at[36], at[94]); MULADD(at[37], at[93]); MULADD(at[38], at[92]); MULADD(at[39], at[91]); MULADD(at[40], at[90]); MULADD(at[41], at[89]); MULADD(at[42], at[88]); MULADD(at[43], at[87]); MULADD(at[44], at[86]); MULADD(at[45], at[85]); MULADD(at[46], at[84]); MULADD(at[47], at[83]); MULADD(at[48], at[82]); MULADD(at[49], at[81]); MULADD(at[50], at[80]); MULADD(at[51], at[79]); MULADD(at[52], at[78]); MULADD(at[53], at[77]); MULADD(at[54], at[76]); MULADD(at[55], at[75]); MULADD(at[56], at[74]); MULADD(at[57], at[73]); MULADD(at[58], at[72]); MULADD(at[59], at[71]); MULADD(at[60], at[70]); MULADD(at[61], at[69]); MULADD(at[62], at[68]); MULADD(at[63], at[67]); + COMBA_STORE(C->dp[66]); + /* 67 */ + COMBA_FORWARD; + MULADD(at[4], at[127]); MULADD(at[5], at[126]); MULADD(at[6], at[125]); MULADD(at[7], at[124]); MULADD(at[8], at[123]); MULADD(at[9], at[122]); MULADD(at[10], at[121]); MULADD(at[11], at[120]); MULADD(at[12], at[119]); MULADD(at[13], at[118]); MULADD(at[14], at[117]); MULADD(at[15], at[116]); MULADD(at[16], at[115]); MULADD(at[17], at[114]); MULADD(at[18], at[113]); MULADD(at[19], at[112]); MULADD(at[20], at[111]); MULADD(at[21], at[110]); MULADD(at[22], at[109]); MULADD(at[23], at[108]); MULADD(at[24], at[107]); MULADD(at[25], at[106]); MULADD(at[26], at[105]); MULADD(at[27], at[104]); MULADD(at[28], at[103]); MULADD(at[29], at[102]); MULADD(at[30], at[101]); MULADD(at[31], at[100]); MULADD(at[32], at[99]); MULADD(at[33], at[98]); MULADD(at[34], at[97]); MULADD(at[35], at[96]); MULADD(at[36], at[95]); MULADD(at[37], at[94]); MULADD(at[38], at[93]); MULADD(at[39], at[92]); MULADD(at[40], at[91]); MULADD(at[41], at[90]); MULADD(at[42], at[89]); MULADD(at[43], at[88]); MULADD(at[44], at[87]); MULADD(at[45], at[86]); MULADD(at[46], at[85]); MULADD(at[47], at[84]); MULADD(at[48], at[83]); MULADD(at[49], at[82]); MULADD(at[50], at[81]); MULADD(at[51], at[80]); MULADD(at[52], at[79]); MULADD(at[53], at[78]); MULADD(at[54], at[77]); MULADD(at[55], at[76]); MULADD(at[56], at[75]); MULADD(at[57], at[74]); MULADD(at[58], at[73]); MULADD(at[59], at[72]); MULADD(at[60], at[71]); MULADD(at[61], at[70]); MULADD(at[62], at[69]); MULADD(at[63], at[68]); + COMBA_STORE(C->dp[67]); + /* 68 */ + COMBA_FORWARD; + MULADD(at[5], at[127]); MULADD(at[6], at[126]); MULADD(at[7], at[125]); MULADD(at[8], at[124]); MULADD(at[9], at[123]); MULADD(at[10], at[122]); MULADD(at[11], at[121]); MULADD(at[12], at[120]); MULADD(at[13], at[119]); MULADD(at[14], at[118]); MULADD(at[15], at[117]); MULADD(at[16], at[116]); MULADD(at[17], at[115]); MULADD(at[18], at[114]); MULADD(at[19], at[113]); MULADD(at[20], at[112]); MULADD(at[21], at[111]); MULADD(at[22], at[110]); MULADD(at[23], at[109]); MULADD(at[24], at[108]); MULADD(at[25], at[107]); MULADD(at[26], at[106]); MULADD(at[27], at[105]); MULADD(at[28], at[104]); MULADD(at[29], at[103]); MULADD(at[30], at[102]); MULADD(at[31], at[101]); MULADD(at[32], at[100]); MULADD(at[33], at[99]); MULADD(at[34], at[98]); MULADD(at[35], at[97]); MULADD(at[36], at[96]); MULADD(at[37], at[95]); MULADD(at[38], at[94]); MULADD(at[39], at[93]); MULADD(at[40], at[92]); MULADD(at[41], at[91]); MULADD(at[42], at[90]); MULADD(at[43], at[89]); MULADD(at[44], at[88]); MULADD(at[45], at[87]); MULADD(at[46], at[86]); MULADD(at[47], at[85]); MULADD(at[48], at[84]); MULADD(at[49], at[83]); MULADD(at[50], at[82]); MULADD(at[51], at[81]); MULADD(at[52], at[80]); MULADD(at[53], at[79]); MULADD(at[54], at[78]); MULADD(at[55], at[77]); MULADD(at[56], at[76]); MULADD(at[57], at[75]); MULADD(at[58], at[74]); MULADD(at[59], at[73]); MULADD(at[60], at[72]); MULADD(at[61], at[71]); MULADD(at[62], at[70]); MULADD(at[63], at[69]); + COMBA_STORE(C->dp[68]); + /* 69 */ + COMBA_FORWARD; + MULADD(at[6], at[127]); MULADD(at[7], at[126]); MULADD(at[8], at[125]); MULADD(at[9], at[124]); MULADD(at[10], at[123]); MULADD(at[11], at[122]); MULADD(at[12], at[121]); MULADD(at[13], at[120]); MULADD(at[14], at[119]); MULADD(at[15], at[118]); MULADD(at[16], at[117]); MULADD(at[17], at[116]); MULADD(at[18], at[115]); MULADD(at[19], at[114]); MULADD(at[20], at[113]); MULADD(at[21], at[112]); MULADD(at[22], at[111]); MULADD(at[23], at[110]); MULADD(at[24], at[109]); MULADD(at[25], at[108]); MULADD(at[26], at[107]); MULADD(at[27], at[106]); MULADD(at[28], at[105]); MULADD(at[29], at[104]); MULADD(at[30], at[103]); MULADD(at[31], at[102]); MULADD(at[32], at[101]); MULADD(at[33], at[100]); MULADD(at[34], at[99]); MULADD(at[35], at[98]); MULADD(at[36], at[97]); MULADD(at[37], at[96]); MULADD(at[38], at[95]); MULADD(at[39], at[94]); MULADD(at[40], at[93]); MULADD(at[41], at[92]); MULADD(at[42], at[91]); MULADD(at[43], at[90]); MULADD(at[44], at[89]); MULADD(at[45], at[88]); MULADD(at[46], at[87]); MULADD(at[47], at[86]); MULADD(at[48], at[85]); MULADD(at[49], at[84]); MULADD(at[50], at[83]); MULADD(at[51], at[82]); MULADD(at[52], at[81]); MULADD(at[53], at[80]); MULADD(at[54], at[79]); MULADD(at[55], at[78]); MULADD(at[56], at[77]); MULADD(at[57], at[76]); MULADD(at[58], at[75]); MULADD(at[59], at[74]); MULADD(at[60], at[73]); MULADD(at[61], at[72]); MULADD(at[62], at[71]); MULADD(at[63], at[70]); + COMBA_STORE(C->dp[69]); + /* 70 */ + COMBA_FORWARD; + MULADD(at[7], at[127]); MULADD(at[8], at[126]); MULADD(at[9], at[125]); MULADD(at[10], at[124]); MULADD(at[11], at[123]); MULADD(at[12], at[122]); MULADD(at[13], at[121]); MULADD(at[14], at[120]); MULADD(at[15], at[119]); MULADD(at[16], at[118]); MULADD(at[17], at[117]); MULADD(at[18], at[116]); MULADD(at[19], at[115]); MULADD(at[20], at[114]); MULADD(at[21], at[113]); MULADD(at[22], at[112]); MULADD(at[23], at[111]); MULADD(at[24], at[110]); MULADD(at[25], at[109]); MULADD(at[26], at[108]); MULADD(at[27], at[107]); MULADD(at[28], at[106]); MULADD(at[29], at[105]); MULADD(at[30], at[104]); MULADD(at[31], at[103]); MULADD(at[32], at[102]); MULADD(at[33], at[101]); MULADD(at[34], at[100]); MULADD(at[35], at[99]); MULADD(at[36], at[98]); MULADD(at[37], at[97]); MULADD(at[38], at[96]); MULADD(at[39], at[95]); MULADD(at[40], at[94]); MULADD(at[41], at[93]); MULADD(at[42], at[92]); MULADD(at[43], at[91]); MULADD(at[44], at[90]); MULADD(at[45], at[89]); MULADD(at[46], at[88]); MULADD(at[47], at[87]); MULADD(at[48], at[86]); MULADD(at[49], at[85]); MULADD(at[50], at[84]); MULADD(at[51], at[83]); MULADD(at[52], at[82]); MULADD(at[53], at[81]); MULADD(at[54], at[80]); MULADD(at[55], at[79]); MULADD(at[56], at[78]); MULADD(at[57], at[77]); MULADD(at[58], at[76]); MULADD(at[59], at[75]); MULADD(at[60], at[74]); MULADD(at[61], at[73]); MULADD(at[62], at[72]); MULADD(at[63], at[71]); + COMBA_STORE(C->dp[70]); + /* 71 */ + COMBA_FORWARD; + MULADD(at[8], at[127]); MULADD(at[9], at[126]); MULADD(at[10], at[125]); MULADD(at[11], at[124]); MULADD(at[12], at[123]); MULADD(at[13], at[122]); MULADD(at[14], at[121]); MULADD(at[15], at[120]); MULADD(at[16], at[119]); MULADD(at[17], at[118]); MULADD(at[18], at[117]); MULADD(at[19], at[116]); MULADD(at[20], at[115]); MULADD(at[21], at[114]); MULADD(at[22], at[113]); MULADD(at[23], at[112]); MULADD(at[24], at[111]); MULADD(at[25], at[110]); MULADD(at[26], at[109]); MULADD(at[27], at[108]); MULADD(at[28], at[107]); MULADD(at[29], at[106]); MULADD(at[30], at[105]); MULADD(at[31], at[104]); MULADD(at[32], at[103]); MULADD(at[33], at[102]); MULADD(at[34], at[101]); MULADD(at[35], at[100]); MULADD(at[36], at[99]); MULADD(at[37], at[98]); MULADD(at[38], at[97]); MULADD(at[39], at[96]); MULADD(at[40], at[95]); MULADD(at[41], at[94]); MULADD(at[42], at[93]); MULADD(at[43], at[92]); MULADD(at[44], at[91]); MULADD(at[45], at[90]); MULADD(at[46], at[89]); MULADD(at[47], at[88]); MULADD(at[48], at[87]); MULADD(at[49], at[86]); MULADD(at[50], at[85]); MULADD(at[51], at[84]); MULADD(at[52], at[83]); MULADD(at[53], at[82]); MULADD(at[54], at[81]); MULADD(at[55], at[80]); MULADD(at[56], at[79]); MULADD(at[57], at[78]); MULADD(at[58], at[77]); MULADD(at[59], at[76]); MULADD(at[60], at[75]); MULADD(at[61], at[74]); MULADD(at[62], at[73]); MULADD(at[63], at[72]); + COMBA_STORE(C->dp[71]); + /* 72 */ + COMBA_FORWARD; + MULADD(at[9], at[127]); MULADD(at[10], at[126]); MULADD(at[11], at[125]); MULADD(at[12], at[124]); MULADD(at[13], at[123]); MULADD(at[14], at[122]); MULADD(at[15], at[121]); MULADD(at[16], at[120]); MULADD(at[17], at[119]); MULADD(at[18], at[118]); MULADD(at[19], at[117]); MULADD(at[20], at[116]); MULADD(at[21], at[115]); MULADD(at[22], at[114]); MULADD(at[23], at[113]); MULADD(at[24], at[112]); MULADD(at[25], at[111]); MULADD(at[26], at[110]); MULADD(at[27], at[109]); MULADD(at[28], at[108]); MULADD(at[29], at[107]); MULADD(at[30], at[106]); MULADD(at[31], at[105]); MULADD(at[32], at[104]); MULADD(at[33], at[103]); MULADD(at[34], at[102]); MULADD(at[35], at[101]); MULADD(at[36], at[100]); MULADD(at[37], at[99]); MULADD(at[38], at[98]); MULADD(at[39], at[97]); MULADD(at[40], at[96]); MULADD(at[41], at[95]); MULADD(at[42], at[94]); MULADD(at[43], at[93]); MULADD(at[44], at[92]); MULADD(at[45], at[91]); MULADD(at[46], at[90]); MULADD(at[47], at[89]); MULADD(at[48], at[88]); MULADD(at[49], at[87]); MULADD(at[50], at[86]); MULADD(at[51], at[85]); MULADD(at[52], at[84]); MULADD(at[53], at[83]); MULADD(at[54], at[82]); MULADD(at[55], at[81]); MULADD(at[56], at[80]); MULADD(at[57], at[79]); MULADD(at[58], at[78]); MULADD(at[59], at[77]); MULADD(at[60], at[76]); MULADD(at[61], at[75]); MULADD(at[62], at[74]); MULADD(at[63], at[73]); + COMBA_STORE(C->dp[72]); + /* 73 */ + COMBA_FORWARD; + MULADD(at[10], at[127]); MULADD(at[11], at[126]); MULADD(at[12], at[125]); MULADD(at[13], at[124]); MULADD(at[14], at[123]); MULADD(at[15], at[122]); MULADD(at[16], at[121]); MULADD(at[17], at[120]); MULADD(at[18], at[119]); MULADD(at[19], at[118]); MULADD(at[20], at[117]); MULADD(at[21], at[116]); MULADD(at[22], at[115]); MULADD(at[23], at[114]); MULADD(at[24], at[113]); MULADD(at[25], at[112]); MULADD(at[26], at[111]); MULADD(at[27], at[110]); MULADD(at[28], at[109]); MULADD(at[29], at[108]); MULADD(at[30], at[107]); MULADD(at[31], at[106]); MULADD(at[32], at[105]); MULADD(at[33], at[104]); MULADD(at[34], at[103]); MULADD(at[35], at[102]); MULADD(at[36], at[101]); MULADD(at[37], at[100]); MULADD(at[38], at[99]); MULADD(at[39], at[98]); MULADD(at[40], at[97]); MULADD(at[41], at[96]); MULADD(at[42], at[95]); MULADD(at[43], at[94]); MULADD(at[44], at[93]); MULADD(at[45], at[92]); MULADD(at[46], at[91]); MULADD(at[47], at[90]); MULADD(at[48], at[89]); MULADD(at[49], at[88]); MULADD(at[50], at[87]); MULADD(at[51], at[86]); MULADD(at[52], at[85]); MULADD(at[53], at[84]); MULADD(at[54], at[83]); MULADD(at[55], at[82]); MULADD(at[56], at[81]); MULADD(at[57], at[80]); MULADD(at[58], at[79]); MULADD(at[59], at[78]); MULADD(at[60], at[77]); MULADD(at[61], at[76]); MULADD(at[62], at[75]); MULADD(at[63], at[74]); + COMBA_STORE(C->dp[73]); + /* 74 */ + COMBA_FORWARD; + MULADD(at[11], at[127]); MULADD(at[12], at[126]); MULADD(at[13], at[125]); MULADD(at[14], at[124]); MULADD(at[15], at[123]); MULADD(at[16], at[122]); MULADD(at[17], at[121]); MULADD(at[18], at[120]); MULADD(at[19], at[119]); MULADD(at[20], at[118]); MULADD(at[21], at[117]); MULADD(at[22], at[116]); MULADD(at[23], at[115]); MULADD(at[24], at[114]); MULADD(at[25], at[113]); MULADD(at[26], at[112]); MULADD(at[27], at[111]); MULADD(at[28], at[110]); MULADD(at[29], at[109]); MULADD(at[30], at[108]); MULADD(at[31], at[107]); MULADD(at[32], at[106]); MULADD(at[33], at[105]); MULADD(at[34], at[104]); MULADD(at[35], at[103]); MULADD(at[36], at[102]); MULADD(at[37], at[101]); MULADD(at[38], at[100]); MULADD(at[39], at[99]); MULADD(at[40], at[98]); MULADD(at[41], at[97]); MULADD(at[42], at[96]); MULADD(at[43], at[95]); MULADD(at[44], at[94]); MULADD(at[45], at[93]); MULADD(at[46], at[92]); MULADD(at[47], at[91]); MULADD(at[48], at[90]); MULADD(at[49], at[89]); MULADD(at[50], at[88]); MULADD(at[51], at[87]); MULADD(at[52], at[86]); MULADD(at[53], at[85]); MULADD(at[54], at[84]); MULADD(at[55], at[83]); MULADD(at[56], at[82]); MULADD(at[57], at[81]); MULADD(at[58], at[80]); MULADD(at[59], at[79]); MULADD(at[60], at[78]); MULADD(at[61], at[77]); MULADD(at[62], at[76]); MULADD(at[63], at[75]); + COMBA_STORE(C->dp[74]); + /* 75 */ + COMBA_FORWARD; + MULADD(at[12], at[127]); MULADD(at[13], at[126]); MULADD(at[14], at[125]); MULADD(at[15], at[124]); MULADD(at[16], at[123]); MULADD(at[17], at[122]); MULADD(at[18], at[121]); MULADD(at[19], at[120]); MULADD(at[20], at[119]); MULADD(at[21], at[118]); MULADD(at[22], at[117]); MULADD(at[23], at[116]); MULADD(at[24], at[115]); MULADD(at[25], at[114]); MULADD(at[26], at[113]); MULADD(at[27], at[112]); MULADD(at[28], at[111]); MULADD(at[29], at[110]); MULADD(at[30], at[109]); MULADD(at[31], at[108]); MULADD(at[32], at[107]); MULADD(at[33], at[106]); MULADD(at[34], at[105]); MULADD(at[35], at[104]); MULADD(at[36], at[103]); MULADD(at[37], at[102]); MULADD(at[38], at[101]); MULADD(at[39], at[100]); MULADD(at[40], at[99]); MULADD(at[41], at[98]); MULADD(at[42], at[97]); MULADD(at[43], at[96]); MULADD(at[44], at[95]); MULADD(at[45], at[94]); MULADD(at[46], at[93]); MULADD(at[47], at[92]); MULADD(at[48], at[91]); MULADD(at[49], at[90]); MULADD(at[50], at[89]); MULADD(at[51], at[88]); MULADD(at[52], at[87]); MULADD(at[53], at[86]); MULADD(at[54], at[85]); MULADD(at[55], at[84]); MULADD(at[56], at[83]); MULADD(at[57], at[82]); MULADD(at[58], at[81]); MULADD(at[59], at[80]); MULADD(at[60], at[79]); MULADD(at[61], at[78]); MULADD(at[62], at[77]); MULADD(at[63], at[76]); + COMBA_STORE(C->dp[75]); + /* 76 */ + COMBA_FORWARD; + MULADD(at[13], at[127]); MULADD(at[14], at[126]); MULADD(at[15], at[125]); MULADD(at[16], at[124]); MULADD(at[17], at[123]); MULADD(at[18], at[122]); MULADD(at[19], at[121]); MULADD(at[20], at[120]); MULADD(at[21], at[119]); MULADD(at[22], at[118]); MULADD(at[23], at[117]); MULADD(at[24], at[116]); MULADD(at[25], at[115]); MULADD(at[26], at[114]); MULADD(at[27], at[113]); MULADD(at[28], at[112]); MULADD(at[29], at[111]); MULADD(at[30], at[110]); MULADD(at[31], at[109]); MULADD(at[32], at[108]); MULADD(at[33], at[107]); MULADD(at[34], at[106]); MULADD(at[35], at[105]); MULADD(at[36], at[104]); MULADD(at[37], at[103]); MULADD(at[38], at[102]); MULADD(at[39], at[101]); MULADD(at[40], at[100]); MULADD(at[41], at[99]); MULADD(at[42], at[98]); MULADD(at[43], at[97]); MULADD(at[44], at[96]); MULADD(at[45], at[95]); MULADD(at[46], at[94]); MULADD(at[47], at[93]); MULADD(at[48], at[92]); MULADD(at[49], at[91]); MULADD(at[50], at[90]); MULADD(at[51], at[89]); MULADD(at[52], at[88]); MULADD(at[53], at[87]); MULADD(at[54], at[86]); MULADD(at[55], at[85]); MULADD(at[56], at[84]); MULADD(at[57], at[83]); MULADD(at[58], at[82]); MULADD(at[59], at[81]); MULADD(at[60], at[80]); MULADD(at[61], at[79]); MULADD(at[62], at[78]); MULADD(at[63], at[77]); + COMBA_STORE(C->dp[76]); + /* 77 */ + COMBA_FORWARD; + MULADD(at[14], at[127]); MULADD(at[15], at[126]); MULADD(at[16], at[125]); MULADD(at[17], at[124]); MULADD(at[18], at[123]); MULADD(at[19], at[122]); MULADD(at[20], at[121]); MULADD(at[21], at[120]); MULADD(at[22], at[119]); MULADD(at[23], at[118]); MULADD(at[24], at[117]); MULADD(at[25], at[116]); MULADD(at[26], at[115]); MULADD(at[27], at[114]); MULADD(at[28], at[113]); MULADD(at[29], at[112]); MULADD(at[30], at[111]); MULADD(at[31], at[110]); MULADD(at[32], at[109]); MULADD(at[33], at[108]); MULADD(at[34], at[107]); MULADD(at[35], at[106]); MULADD(at[36], at[105]); MULADD(at[37], at[104]); MULADD(at[38], at[103]); MULADD(at[39], at[102]); MULADD(at[40], at[101]); MULADD(at[41], at[100]); MULADD(at[42], at[99]); MULADD(at[43], at[98]); MULADD(at[44], at[97]); MULADD(at[45], at[96]); MULADD(at[46], at[95]); MULADD(at[47], at[94]); MULADD(at[48], at[93]); MULADD(at[49], at[92]); MULADD(at[50], at[91]); MULADD(at[51], at[90]); MULADD(at[52], at[89]); MULADD(at[53], at[88]); MULADD(at[54], at[87]); MULADD(at[55], at[86]); MULADD(at[56], at[85]); MULADD(at[57], at[84]); MULADD(at[58], at[83]); MULADD(at[59], at[82]); MULADD(at[60], at[81]); MULADD(at[61], at[80]); MULADD(at[62], at[79]); MULADD(at[63], at[78]); + COMBA_STORE(C->dp[77]); + /* 78 */ + COMBA_FORWARD; + MULADD(at[15], at[127]); MULADD(at[16], at[126]); MULADD(at[17], at[125]); MULADD(at[18], at[124]); MULADD(at[19], at[123]); MULADD(at[20], at[122]); MULADD(at[21], at[121]); MULADD(at[22], at[120]); MULADD(at[23], at[119]); MULADD(at[24], at[118]); MULADD(at[25], at[117]); MULADD(at[26], at[116]); MULADD(at[27], at[115]); MULADD(at[28], at[114]); MULADD(at[29], at[113]); MULADD(at[30], at[112]); MULADD(at[31], at[111]); MULADD(at[32], at[110]); MULADD(at[33], at[109]); MULADD(at[34], at[108]); MULADD(at[35], at[107]); MULADD(at[36], at[106]); MULADD(at[37], at[105]); MULADD(at[38], at[104]); MULADD(at[39], at[103]); MULADD(at[40], at[102]); MULADD(at[41], at[101]); MULADD(at[42], at[100]); MULADD(at[43], at[99]); MULADD(at[44], at[98]); MULADD(at[45], at[97]); MULADD(at[46], at[96]); MULADD(at[47], at[95]); MULADD(at[48], at[94]); MULADD(at[49], at[93]); MULADD(at[50], at[92]); MULADD(at[51], at[91]); MULADD(at[52], at[90]); MULADD(at[53], at[89]); MULADD(at[54], at[88]); MULADD(at[55], at[87]); MULADD(at[56], at[86]); MULADD(at[57], at[85]); MULADD(at[58], at[84]); MULADD(at[59], at[83]); MULADD(at[60], at[82]); MULADD(at[61], at[81]); MULADD(at[62], at[80]); MULADD(at[63], at[79]); + COMBA_STORE(C->dp[78]); + /* 79 */ + COMBA_FORWARD; + MULADD(at[16], at[127]); MULADD(at[17], at[126]); MULADD(at[18], at[125]); MULADD(at[19], at[124]); MULADD(at[20], at[123]); MULADD(at[21], at[122]); MULADD(at[22], at[121]); MULADD(at[23], at[120]); MULADD(at[24], at[119]); MULADD(at[25], at[118]); MULADD(at[26], at[117]); MULADD(at[27], at[116]); MULADD(at[28], at[115]); MULADD(at[29], at[114]); MULADD(at[30], at[113]); MULADD(at[31], at[112]); MULADD(at[32], at[111]); MULADD(at[33], at[110]); MULADD(at[34], at[109]); MULADD(at[35], at[108]); MULADD(at[36], at[107]); MULADD(at[37], at[106]); MULADD(at[38], at[105]); MULADD(at[39], at[104]); MULADD(at[40], at[103]); MULADD(at[41], at[102]); MULADD(at[42], at[101]); MULADD(at[43], at[100]); MULADD(at[44], at[99]); MULADD(at[45], at[98]); MULADD(at[46], at[97]); MULADD(at[47], at[96]); MULADD(at[48], at[95]); MULADD(at[49], at[94]); MULADD(at[50], at[93]); MULADD(at[51], at[92]); MULADD(at[52], at[91]); MULADD(at[53], at[90]); MULADD(at[54], at[89]); MULADD(at[55], at[88]); MULADD(at[56], at[87]); MULADD(at[57], at[86]); MULADD(at[58], at[85]); MULADD(at[59], at[84]); MULADD(at[60], at[83]); MULADD(at[61], at[82]); MULADD(at[62], at[81]); MULADD(at[63], at[80]); + COMBA_STORE(C->dp[79]); + /* 80 */ + COMBA_FORWARD; + MULADD(at[17], at[127]); MULADD(at[18], at[126]); MULADD(at[19], at[125]); MULADD(at[20], at[124]); MULADD(at[21], at[123]); MULADD(at[22], at[122]); MULADD(at[23], at[121]); MULADD(at[24], at[120]); MULADD(at[25], at[119]); MULADD(at[26], at[118]); MULADD(at[27], at[117]); MULADD(at[28], at[116]); MULADD(at[29], at[115]); MULADD(at[30], at[114]); MULADD(at[31], at[113]); MULADD(at[32], at[112]); MULADD(at[33], at[111]); MULADD(at[34], at[110]); MULADD(at[35], at[109]); MULADD(at[36], at[108]); MULADD(at[37], at[107]); MULADD(at[38], at[106]); MULADD(at[39], at[105]); MULADD(at[40], at[104]); MULADD(at[41], at[103]); MULADD(at[42], at[102]); MULADD(at[43], at[101]); MULADD(at[44], at[100]); MULADD(at[45], at[99]); MULADD(at[46], at[98]); MULADD(at[47], at[97]); MULADD(at[48], at[96]); MULADD(at[49], at[95]); MULADD(at[50], at[94]); MULADD(at[51], at[93]); MULADD(at[52], at[92]); MULADD(at[53], at[91]); MULADD(at[54], at[90]); MULADD(at[55], at[89]); MULADD(at[56], at[88]); MULADD(at[57], at[87]); MULADD(at[58], at[86]); MULADD(at[59], at[85]); MULADD(at[60], at[84]); MULADD(at[61], at[83]); MULADD(at[62], at[82]); MULADD(at[63], at[81]); + COMBA_STORE(C->dp[80]); + /* 81 */ + COMBA_FORWARD; + MULADD(at[18], at[127]); MULADD(at[19], at[126]); MULADD(at[20], at[125]); MULADD(at[21], at[124]); MULADD(at[22], at[123]); MULADD(at[23], at[122]); MULADD(at[24], at[121]); MULADD(at[25], at[120]); MULADD(at[26], at[119]); MULADD(at[27], at[118]); MULADD(at[28], at[117]); MULADD(at[29], at[116]); MULADD(at[30], at[115]); MULADD(at[31], at[114]); MULADD(at[32], at[113]); MULADD(at[33], at[112]); MULADD(at[34], at[111]); MULADD(at[35], at[110]); MULADD(at[36], at[109]); MULADD(at[37], at[108]); MULADD(at[38], at[107]); MULADD(at[39], at[106]); MULADD(at[40], at[105]); MULADD(at[41], at[104]); MULADD(at[42], at[103]); MULADD(at[43], at[102]); MULADD(at[44], at[101]); MULADD(at[45], at[100]); MULADD(at[46], at[99]); MULADD(at[47], at[98]); MULADD(at[48], at[97]); MULADD(at[49], at[96]); MULADD(at[50], at[95]); MULADD(at[51], at[94]); MULADD(at[52], at[93]); MULADD(at[53], at[92]); MULADD(at[54], at[91]); MULADD(at[55], at[90]); MULADD(at[56], at[89]); MULADD(at[57], at[88]); MULADD(at[58], at[87]); MULADD(at[59], at[86]); MULADD(at[60], at[85]); MULADD(at[61], at[84]); MULADD(at[62], at[83]); MULADD(at[63], at[82]); + COMBA_STORE(C->dp[81]); + /* 82 */ + COMBA_FORWARD; + MULADD(at[19], at[127]); MULADD(at[20], at[126]); MULADD(at[21], at[125]); MULADD(at[22], at[124]); MULADD(at[23], at[123]); MULADD(at[24], at[122]); MULADD(at[25], at[121]); MULADD(at[26], at[120]); MULADD(at[27], at[119]); MULADD(at[28], at[118]); MULADD(at[29], at[117]); MULADD(at[30], at[116]); MULADD(at[31], at[115]); MULADD(at[32], at[114]); MULADD(at[33], at[113]); MULADD(at[34], at[112]); MULADD(at[35], at[111]); MULADD(at[36], at[110]); MULADD(at[37], at[109]); MULADD(at[38], at[108]); MULADD(at[39], at[107]); MULADD(at[40], at[106]); MULADD(at[41], at[105]); MULADD(at[42], at[104]); MULADD(at[43], at[103]); MULADD(at[44], at[102]); MULADD(at[45], at[101]); MULADD(at[46], at[100]); MULADD(at[47], at[99]); MULADD(at[48], at[98]); MULADD(at[49], at[97]); MULADD(at[50], at[96]); MULADD(at[51], at[95]); MULADD(at[52], at[94]); MULADD(at[53], at[93]); MULADD(at[54], at[92]); MULADD(at[55], at[91]); MULADD(at[56], at[90]); MULADD(at[57], at[89]); MULADD(at[58], at[88]); MULADD(at[59], at[87]); MULADD(at[60], at[86]); MULADD(at[61], at[85]); MULADD(at[62], at[84]); MULADD(at[63], at[83]); + COMBA_STORE(C->dp[82]); + /* 83 */ + COMBA_FORWARD; + MULADD(at[20], at[127]); MULADD(at[21], at[126]); MULADD(at[22], at[125]); MULADD(at[23], at[124]); MULADD(at[24], at[123]); MULADD(at[25], at[122]); MULADD(at[26], at[121]); MULADD(at[27], at[120]); MULADD(at[28], at[119]); MULADD(at[29], at[118]); MULADD(at[30], at[117]); MULADD(at[31], at[116]); MULADD(at[32], at[115]); MULADD(at[33], at[114]); MULADD(at[34], at[113]); MULADD(at[35], at[112]); MULADD(at[36], at[111]); MULADD(at[37], at[110]); MULADD(at[38], at[109]); MULADD(at[39], at[108]); MULADD(at[40], at[107]); MULADD(at[41], at[106]); MULADD(at[42], at[105]); MULADD(at[43], at[104]); MULADD(at[44], at[103]); MULADD(at[45], at[102]); MULADD(at[46], at[101]); MULADD(at[47], at[100]); MULADD(at[48], at[99]); MULADD(at[49], at[98]); MULADD(at[50], at[97]); MULADD(at[51], at[96]); MULADD(at[52], at[95]); MULADD(at[53], at[94]); MULADD(at[54], at[93]); MULADD(at[55], at[92]); MULADD(at[56], at[91]); MULADD(at[57], at[90]); MULADD(at[58], at[89]); MULADD(at[59], at[88]); MULADD(at[60], at[87]); MULADD(at[61], at[86]); MULADD(at[62], at[85]); MULADD(at[63], at[84]); + COMBA_STORE(C->dp[83]); + /* 84 */ + COMBA_FORWARD; + MULADD(at[21], at[127]); MULADD(at[22], at[126]); MULADD(at[23], at[125]); MULADD(at[24], at[124]); MULADD(at[25], at[123]); MULADD(at[26], at[122]); MULADD(at[27], at[121]); MULADD(at[28], at[120]); MULADD(at[29], at[119]); MULADD(at[30], at[118]); MULADD(at[31], at[117]); MULADD(at[32], at[116]); MULADD(at[33], at[115]); MULADD(at[34], at[114]); MULADD(at[35], at[113]); MULADD(at[36], at[112]); MULADD(at[37], at[111]); MULADD(at[38], at[110]); MULADD(at[39], at[109]); MULADD(at[40], at[108]); MULADD(at[41], at[107]); MULADD(at[42], at[106]); MULADD(at[43], at[105]); MULADD(at[44], at[104]); MULADD(at[45], at[103]); MULADD(at[46], at[102]); MULADD(at[47], at[101]); MULADD(at[48], at[100]); MULADD(at[49], at[99]); MULADD(at[50], at[98]); MULADD(at[51], at[97]); MULADD(at[52], at[96]); MULADD(at[53], at[95]); MULADD(at[54], at[94]); MULADD(at[55], at[93]); MULADD(at[56], at[92]); MULADD(at[57], at[91]); MULADD(at[58], at[90]); MULADD(at[59], at[89]); MULADD(at[60], at[88]); MULADD(at[61], at[87]); MULADD(at[62], at[86]); MULADD(at[63], at[85]); + COMBA_STORE(C->dp[84]); + /* 85 */ + COMBA_FORWARD; + MULADD(at[22], at[127]); MULADD(at[23], at[126]); MULADD(at[24], at[125]); MULADD(at[25], at[124]); MULADD(at[26], at[123]); MULADD(at[27], at[122]); MULADD(at[28], at[121]); MULADD(at[29], at[120]); MULADD(at[30], at[119]); MULADD(at[31], at[118]); MULADD(at[32], at[117]); MULADD(at[33], at[116]); MULADD(at[34], at[115]); MULADD(at[35], at[114]); MULADD(at[36], at[113]); MULADD(at[37], at[112]); MULADD(at[38], at[111]); MULADD(at[39], at[110]); MULADD(at[40], at[109]); MULADD(at[41], at[108]); MULADD(at[42], at[107]); MULADD(at[43], at[106]); MULADD(at[44], at[105]); MULADD(at[45], at[104]); MULADD(at[46], at[103]); MULADD(at[47], at[102]); MULADD(at[48], at[101]); MULADD(at[49], at[100]); MULADD(at[50], at[99]); MULADD(at[51], at[98]); MULADD(at[52], at[97]); MULADD(at[53], at[96]); MULADD(at[54], at[95]); MULADD(at[55], at[94]); MULADD(at[56], at[93]); MULADD(at[57], at[92]); MULADD(at[58], at[91]); MULADD(at[59], at[90]); MULADD(at[60], at[89]); MULADD(at[61], at[88]); MULADD(at[62], at[87]); MULADD(at[63], at[86]); + COMBA_STORE(C->dp[85]); + /* 86 */ + COMBA_FORWARD; + MULADD(at[23], at[127]); MULADD(at[24], at[126]); MULADD(at[25], at[125]); MULADD(at[26], at[124]); MULADD(at[27], at[123]); MULADD(at[28], at[122]); MULADD(at[29], at[121]); MULADD(at[30], at[120]); MULADD(at[31], at[119]); MULADD(at[32], at[118]); MULADD(at[33], at[117]); MULADD(at[34], at[116]); MULADD(at[35], at[115]); MULADD(at[36], at[114]); MULADD(at[37], at[113]); MULADD(at[38], at[112]); MULADD(at[39], at[111]); MULADD(at[40], at[110]); MULADD(at[41], at[109]); MULADD(at[42], at[108]); MULADD(at[43], at[107]); MULADD(at[44], at[106]); MULADD(at[45], at[105]); MULADD(at[46], at[104]); MULADD(at[47], at[103]); MULADD(at[48], at[102]); MULADD(at[49], at[101]); MULADD(at[50], at[100]); MULADD(at[51], at[99]); MULADD(at[52], at[98]); MULADD(at[53], at[97]); MULADD(at[54], at[96]); MULADD(at[55], at[95]); MULADD(at[56], at[94]); MULADD(at[57], at[93]); MULADD(at[58], at[92]); MULADD(at[59], at[91]); MULADD(at[60], at[90]); MULADD(at[61], at[89]); MULADD(at[62], at[88]); MULADD(at[63], at[87]); + COMBA_STORE(C->dp[86]); + /* 87 */ + COMBA_FORWARD; + MULADD(at[24], at[127]); MULADD(at[25], at[126]); MULADD(at[26], at[125]); MULADD(at[27], at[124]); MULADD(at[28], at[123]); MULADD(at[29], at[122]); MULADD(at[30], at[121]); MULADD(at[31], at[120]); MULADD(at[32], at[119]); MULADD(at[33], at[118]); MULADD(at[34], at[117]); MULADD(at[35], at[116]); MULADD(at[36], at[115]); MULADD(at[37], at[114]); MULADD(at[38], at[113]); MULADD(at[39], at[112]); MULADD(at[40], at[111]); MULADD(at[41], at[110]); MULADD(at[42], at[109]); MULADD(at[43], at[108]); MULADD(at[44], at[107]); MULADD(at[45], at[106]); MULADD(at[46], at[105]); MULADD(at[47], at[104]); MULADD(at[48], at[103]); MULADD(at[49], at[102]); MULADD(at[50], at[101]); MULADD(at[51], at[100]); MULADD(at[52], at[99]); MULADD(at[53], at[98]); MULADD(at[54], at[97]); MULADD(at[55], at[96]); MULADD(at[56], at[95]); MULADD(at[57], at[94]); MULADD(at[58], at[93]); MULADD(at[59], at[92]); MULADD(at[60], at[91]); MULADD(at[61], at[90]); MULADD(at[62], at[89]); MULADD(at[63], at[88]); + COMBA_STORE(C->dp[87]); + /* 88 */ + COMBA_FORWARD; + MULADD(at[25], at[127]); MULADD(at[26], at[126]); MULADD(at[27], at[125]); MULADD(at[28], at[124]); MULADD(at[29], at[123]); MULADD(at[30], at[122]); MULADD(at[31], at[121]); MULADD(at[32], at[120]); MULADD(at[33], at[119]); MULADD(at[34], at[118]); MULADD(at[35], at[117]); MULADD(at[36], at[116]); MULADD(at[37], at[115]); MULADD(at[38], at[114]); MULADD(at[39], at[113]); MULADD(at[40], at[112]); MULADD(at[41], at[111]); MULADD(at[42], at[110]); MULADD(at[43], at[109]); MULADD(at[44], at[108]); MULADD(at[45], at[107]); MULADD(at[46], at[106]); MULADD(at[47], at[105]); MULADD(at[48], at[104]); MULADD(at[49], at[103]); MULADD(at[50], at[102]); MULADD(at[51], at[101]); MULADD(at[52], at[100]); MULADD(at[53], at[99]); MULADD(at[54], at[98]); MULADD(at[55], at[97]); MULADD(at[56], at[96]); MULADD(at[57], at[95]); MULADD(at[58], at[94]); MULADD(at[59], at[93]); MULADD(at[60], at[92]); MULADD(at[61], at[91]); MULADD(at[62], at[90]); MULADD(at[63], at[89]); + COMBA_STORE(C->dp[88]); + /* 89 */ + COMBA_FORWARD; + MULADD(at[26], at[127]); MULADD(at[27], at[126]); MULADD(at[28], at[125]); MULADD(at[29], at[124]); MULADD(at[30], at[123]); MULADD(at[31], at[122]); MULADD(at[32], at[121]); MULADD(at[33], at[120]); MULADD(at[34], at[119]); MULADD(at[35], at[118]); MULADD(at[36], at[117]); MULADD(at[37], at[116]); MULADD(at[38], at[115]); MULADD(at[39], at[114]); MULADD(at[40], at[113]); MULADD(at[41], at[112]); MULADD(at[42], at[111]); MULADD(at[43], at[110]); MULADD(at[44], at[109]); MULADD(at[45], at[108]); MULADD(at[46], at[107]); MULADD(at[47], at[106]); MULADD(at[48], at[105]); MULADD(at[49], at[104]); MULADD(at[50], at[103]); MULADD(at[51], at[102]); MULADD(at[52], at[101]); MULADD(at[53], at[100]); MULADD(at[54], at[99]); MULADD(at[55], at[98]); MULADD(at[56], at[97]); MULADD(at[57], at[96]); MULADD(at[58], at[95]); MULADD(at[59], at[94]); MULADD(at[60], at[93]); MULADD(at[61], at[92]); MULADD(at[62], at[91]); MULADD(at[63], at[90]); + COMBA_STORE(C->dp[89]); + /* 90 */ + COMBA_FORWARD; + MULADD(at[27], at[127]); MULADD(at[28], at[126]); MULADD(at[29], at[125]); MULADD(at[30], at[124]); MULADD(at[31], at[123]); MULADD(at[32], at[122]); MULADD(at[33], at[121]); MULADD(at[34], at[120]); MULADD(at[35], at[119]); MULADD(at[36], at[118]); MULADD(at[37], at[117]); MULADD(at[38], at[116]); MULADD(at[39], at[115]); MULADD(at[40], at[114]); MULADD(at[41], at[113]); MULADD(at[42], at[112]); MULADD(at[43], at[111]); MULADD(at[44], at[110]); MULADD(at[45], at[109]); MULADD(at[46], at[108]); MULADD(at[47], at[107]); MULADD(at[48], at[106]); MULADD(at[49], at[105]); MULADD(at[50], at[104]); MULADD(at[51], at[103]); MULADD(at[52], at[102]); MULADD(at[53], at[101]); MULADD(at[54], at[100]); MULADD(at[55], at[99]); MULADD(at[56], at[98]); MULADD(at[57], at[97]); MULADD(at[58], at[96]); MULADD(at[59], at[95]); MULADD(at[60], at[94]); MULADD(at[61], at[93]); MULADD(at[62], at[92]); MULADD(at[63], at[91]); + COMBA_STORE(C->dp[90]); + /* 91 */ + COMBA_FORWARD; + MULADD(at[28], at[127]); MULADD(at[29], at[126]); MULADD(at[30], at[125]); MULADD(at[31], at[124]); MULADD(at[32], at[123]); MULADD(at[33], at[122]); MULADD(at[34], at[121]); MULADD(at[35], at[120]); MULADD(at[36], at[119]); MULADD(at[37], at[118]); MULADD(at[38], at[117]); MULADD(at[39], at[116]); MULADD(at[40], at[115]); MULADD(at[41], at[114]); MULADD(at[42], at[113]); MULADD(at[43], at[112]); MULADD(at[44], at[111]); MULADD(at[45], at[110]); MULADD(at[46], at[109]); MULADD(at[47], at[108]); MULADD(at[48], at[107]); MULADD(at[49], at[106]); MULADD(at[50], at[105]); MULADD(at[51], at[104]); MULADD(at[52], at[103]); MULADD(at[53], at[102]); MULADD(at[54], at[101]); MULADD(at[55], at[100]); MULADD(at[56], at[99]); MULADD(at[57], at[98]); MULADD(at[58], at[97]); MULADD(at[59], at[96]); MULADD(at[60], at[95]); MULADD(at[61], at[94]); MULADD(at[62], at[93]); MULADD(at[63], at[92]); + COMBA_STORE(C->dp[91]); + /* 92 */ + COMBA_FORWARD; + MULADD(at[29], at[127]); MULADD(at[30], at[126]); MULADD(at[31], at[125]); MULADD(at[32], at[124]); MULADD(at[33], at[123]); MULADD(at[34], at[122]); MULADD(at[35], at[121]); MULADD(at[36], at[120]); MULADD(at[37], at[119]); MULADD(at[38], at[118]); MULADD(at[39], at[117]); MULADD(at[40], at[116]); MULADD(at[41], at[115]); MULADD(at[42], at[114]); MULADD(at[43], at[113]); MULADD(at[44], at[112]); MULADD(at[45], at[111]); MULADD(at[46], at[110]); MULADD(at[47], at[109]); MULADD(at[48], at[108]); MULADD(at[49], at[107]); MULADD(at[50], at[106]); MULADD(at[51], at[105]); MULADD(at[52], at[104]); MULADD(at[53], at[103]); MULADD(at[54], at[102]); MULADD(at[55], at[101]); MULADD(at[56], at[100]); MULADD(at[57], at[99]); MULADD(at[58], at[98]); MULADD(at[59], at[97]); MULADD(at[60], at[96]); MULADD(at[61], at[95]); MULADD(at[62], at[94]); MULADD(at[63], at[93]); + COMBA_STORE(C->dp[92]); + /* 93 */ + COMBA_FORWARD; + MULADD(at[30], at[127]); MULADD(at[31], at[126]); MULADD(at[32], at[125]); MULADD(at[33], at[124]); MULADD(at[34], at[123]); MULADD(at[35], at[122]); MULADD(at[36], at[121]); MULADD(at[37], at[120]); MULADD(at[38], at[119]); MULADD(at[39], at[118]); MULADD(at[40], at[117]); MULADD(at[41], at[116]); MULADD(at[42], at[115]); MULADD(at[43], at[114]); MULADD(at[44], at[113]); MULADD(at[45], at[112]); MULADD(at[46], at[111]); MULADD(at[47], at[110]); MULADD(at[48], at[109]); MULADD(at[49], at[108]); MULADD(at[50], at[107]); MULADD(at[51], at[106]); MULADD(at[52], at[105]); MULADD(at[53], at[104]); MULADD(at[54], at[103]); MULADD(at[55], at[102]); MULADD(at[56], at[101]); MULADD(at[57], at[100]); MULADD(at[58], at[99]); MULADD(at[59], at[98]); MULADD(at[60], at[97]); MULADD(at[61], at[96]); MULADD(at[62], at[95]); MULADD(at[63], at[94]); + COMBA_STORE(C->dp[93]); + /* 94 */ + COMBA_FORWARD; + MULADD(at[31], at[127]); MULADD(at[32], at[126]); MULADD(at[33], at[125]); MULADD(at[34], at[124]); MULADD(at[35], at[123]); MULADD(at[36], at[122]); MULADD(at[37], at[121]); MULADD(at[38], at[120]); MULADD(at[39], at[119]); MULADD(at[40], at[118]); MULADD(at[41], at[117]); MULADD(at[42], at[116]); MULADD(at[43], at[115]); MULADD(at[44], at[114]); MULADD(at[45], at[113]); MULADD(at[46], at[112]); MULADD(at[47], at[111]); MULADD(at[48], at[110]); MULADD(at[49], at[109]); MULADD(at[50], at[108]); MULADD(at[51], at[107]); MULADD(at[52], at[106]); MULADD(at[53], at[105]); MULADD(at[54], at[104]); MULADD(at[55], at[103]); MULADD(at[56], at[102]); MULADD(at[57], at[101]); MULADD(at[58], at[100]); MULADD(at[59], at[99]); MULADD(at[60], at[98]); MULADD(at[61], at[97]); MULADD(at[62], at[96]); MULADD(at[63], at[95]); + COMBA_STORE(C->dp[94]); + /* 95 */ + COMBA_FORWARD; + MULADD(at[32], at[127]); MULADD(at[33], at[126]); MULADD(at[34], at[125]); MULADD(at[35], at[124]); MULADD(at[36], at[123]); MULADD(at[37], at[122]); MULADD(at[38], at[121]); MULADD(at[39], at[120]); MULADD(at[40], at[119]); MULADD(at[41], at[118]); MULADD(at[42], at[117]); MULADD(at[43], at[116]); MULADD(at[44], at[115]); MULADD(at[45], at[114]); MULADD(at[46], at[113]); MULADD(at[47], at[112]); MULADD(at[48], at[111]); MULADD(at[49], at[110]); MULADD(at[50], at[109]); MULADD(at[51], at[108]); MULADD(at[52], at[107]); MULADD(at[53], at[106]); MULADD(at[54], at[105]); MULADD(at[55], at[104]); MULADD(at[56], at[103]); MULADD(at[57], at[102]); MULADD(at[58], at[101]); MULADD(at[59], at[100]); MULADD(at[60], at[99]); MULADD(at[61], at[98]); MULADD(at[62], at[97]); MULADD(at[63], at[96]); + COMBA_STORE(C->dp[95]); + /* 96 */ + COMBA_FORWARD; + MULADD(at[33], at[127]); MULADD(at[34], at[126]); MULADD(at[35], at[125]); MULADD(at[36], at[124]); MULADD(at[37], at[123]); MULADD(at[38], at[122]); MULADD(at[39], at[121]); MULADD(at[40], at[120]); MULADD(at[41], at[119]); MULADD(at[42], at[118]); MULADD(at[43], at[117]); MULADD(at[44], at[116]); MULADD(at[45], at[115]); MULADD(at[46], at[114]); MULADD(at[47], at[113]); MULADD(at[48], at[112]); MULADD(at[49], at[111]); MULADD(at[50], at[110]); MULADD(at[51], at[109]); MULADD(at[52], at[108]); MULADD(at[53], at[107]); MULADD(at[54], at[106]); MULADD(at[55], at[105]); MULADD(at[56], at[104]); MULADD(at[57], at[103]); MULADD(at[58], at[102]); MULADD(at[59], at[101]); MULADD(at[60], at[100]); MULADD(at[61], at[99]); MULADD(at[62], at[98]); MULADD(at[63], at[97]); + COMBA_STORE(C->dp[96]); + /* 97 */ + COMBA_FORWARD; + MULADD(at[34], at[127]); MULADD(at[35], at[126]); MULADD(at[36], at[125]); MULADD(at[37], at[124]); MULADD(at[38], at[123]); MULADD(at[39], at[122]); MULADD(at[40], at[121]); MULADD(at[41], at[120]); MULADD(at[42], at[119]); MULADD(at[43], at[118]); MULADD(at[44], at[117]); MULADD(at[45], at[116]); MULADD(at[46], at[115]); MULADD(at[47], at[114]); MULADD(at[48], at[113]); MULADD(at[49], at[112]); MULADD(at[50], at[111]); MULADD(at[51], at[110]); MULADD(at[52], at[109]); MULADD(at[53], at[108]); MULADD(at[54], at[107]); MULADD(at[55], at[106]); MULADD(at[56], at[105]); MULADD(at[57], at[104]); MULADD(at[58], at[103]); MULADD(at[59], at[102]); MULADD(at[60], at[101]); MULADD(at[61], at[100]); MULADD(at[62], at[99]); MULADD(at[63], at[98]); + COMBA_STORE(C->dp[97]); + /* 98 */ + COMBA_FORWARD; + MULADD(at[35], at[127]); MULADD(at[36], at[126]); MULADD(at[37], at[125]); MULADD(at[38], at[124]); MULADD(at[39], at[123]); MULADD(at[40], at[122]); MULADD(at[41], at[121]); MULADD(at[42], at[120]); MULADD(at[43], at[119]); MULADD(at[44], at[118]); MULADD(at[45], at[117]); MULADD(at[46], at[116]); MULADD(at[47], at[115]); MULADD(at[48], at[114]); MULADD(at[49], at[113]); MULADD(at[50], at[112]); MULADD(at[51], at[111]); MULADD(at[52], at[110]); MULADD(at[53], at[109]); MULADD(at[54], at[108]); MULADD(at[55], at[107]); MULADD(at[56], at[106]); MULADD(at[57], at[105]); MULADD(at[58], at[104]); MULADD(at[59], at[103]); MULADD(at[60], at[102]); MULADD(at[61], at[101]); MULADD(at[62], at[100]); MULADD(at[63], at[99]); + COMBA_STORE(C->dp[98]); + /* 99 */ + COMBA_FORWARD; + MULADD(at[36], at[127]); MULADD(at[37], at[126]); MULADD(at[38], at[125]); MULADD(at[39], at[124]); MULADD(at[40], at[123]); MULADD(at[41], at[122]); MULADD(at[42], at[121]); MULADD(at[43], at[120]); MULADD(at[44], at[119]); MULADD(at[45], at[118]); MULADD(at[46], at[117]); MULADD(at[47], at[116]); MULADD(at[48], at[115]); MULADD(at[49], at[114]); MULADD(at[50], at[113]); MULADD(at[51], at[112]); MULADD(at[52], at[111]); MULADD(at[53], at[110]); MULADD(at[54], at[109]); MULADD(at[55], at[108]); MULADD(at[56], at[107]); MULADD(at[57], at[106]); MULADD(at[58], at[105]); MULADD(at[59], at[104]); MULADD(at[60], at[103]); MULADD(at[61], at[102]); MULADD(at[62], at[101]); MULADD(at[63], at[100]); + COMBA_STORE(C->dp[99]); + /* 100 */ + COMBA_FORWARD; + MULADD(at[37], at[127]); MULADD(at[38], at[126]); MULADD(at[39], at[125]); MULADD(at[40], at[124]); MULADD(at[41], at[123]); MULADD(at[42], at[122]); MULADD(at[43], at[121]); MULADD(at[44], at[120]); MULADD(at[45], at[119]); MULADD(at[46], at[118]); MULADD(at[47], at[117]); MULADD(at[48], at[116]); MULADD(at[49], at[115]); MULADD(at[50], at[114]); MULADD(at[51], at[113]); MULADD(at[52], at[112]); MULADD(at[53], at[111]); MULADD(at[54], at[110]); MULADD(at[55], at[109]); MULADD(at[56], at[108]); MULADD(at[57], at[107]); MULADD(at[58], at[106]); MULADD(at[59], at[105]); MULADD(at[60], at[104]); MULADD(at[61], at[103]); MULADD(at[62], at[102]); MULADD(at[63], at[101]); + COMBA_STORE(C->dp[100]); + /* 101 */ + COMBA_FORWARD; + MULADD(at[38], at[127]); MULADD(at[39], at[126]); MULADD(at[40], at[125]); MULADD(at[41], at[124]); MULADD(at[42], at[123]); MULADD(at[43], at[122]); MULADD(at[44], at[121]); MULADD(at[45], at[120]); MULADD(at[46], at[119]); MULADD(at[47], at[118]); MULADD(at[48], at[117]); MULADD(at[49], at[116]); MULADD(at[50], at[115]); MULADD(at[51], at[114]); MULADD(at[52], at[113]); MULADD(at[53], at[112]); MULADD(at[54], at[111]); MULADD(at[55], at[110]); MULADD(at[56], at[109]); MULADD(at[57], at[108]); MULADD(at[58], at[107]); MULADD(at[59], at[106]); MULADD(at[60], at[105]); MULADD(at[61], at[104]); MULADD(at[62], at[103]); MULADD(at[63], at[102]); + COMBA_STORE(C->dp[101]); + /* 102 */ + COMBA_FORWARD; + MULADD(at[39], at[127]); MULADD(at[40], at[126]); MULADD(at[41], at[125]); MULADD(at[42], at[124]); MULADD(at[43], at[123]); MULADD(at[44], at[122]); MULADD(at[45], at[121]); MULADD(at[46], at[120]); MULADD(at[47], at[119]); MULADD(at[48], at[118]); MULADD(at[49], at[117]); MULADD(at[50], at[116]); MULADD(at[51], at[115]); MULADD(at[52], at[114]); MULADD(at[53], at[113]); MULADD(at[54], at[112]); MULADD(at[55], at[111]); MULADD(at[56], at[110]); MULADD(at[57], at[109]); MULADD(at[58], at[108]); MULADD(at[59], at[107]); MULADD(at[60], at[106]); MULADD(at[61], at[105]); MULADD(at[62], at[104]); MULADD(at[63], at[103]); + COMBA_STORE(C->dp[102]); + /* 103 */ + COMBA_FORWARD; + MULADD(at[40], at[127]); MULADD(at[41], at[126]); MULADD(at[42], at[125]); MULADD(at[43], at[124]); MULADD(at[44], at[123]); MULADD(at[45], at[122]); MULADD(at[46], at[121]); MULADD(at[47], at[120]); MULADD(at[48], at[119]); MULADD(at[49], at[118]); MULADD(at[50], at[117]); MULADD(at[51], at[116]); MULADD(at[52], at[115]); MULADD(at[53], at[114]); MULADD(at[54], at[113]); MULADD(at[55], at[112]); MULADD(at[56], at[111]); MULADD(at[57], at[110]); MULADD(at[58], at[109]); MULADD(at[59], at[108]); MULADD(at[60], at[107]); MULADD(at[61], at[106]); MULADD(at[62], at[105]); MULADD(at[63], at[104]); + COMBA_STORE(C->dp[103]); + /* 104 */ + COMBA_FORWARD; + MULADD(at[41], at[127]); MULADD(at[42], at[126]); MULADD(at[43], at[125]); MULADD(at[44], at[124]); MULADD(at[45], at[123]); MULADD(at[46], at[122]); MULADD(at[47], at[121]); MULADD(at[48], at[120]); MULADD(at[49], at[119]); MULADD(at[50], at[118]); MULADD(at[51], at[117]); MULADD(at[52], at[116]); MULADD(at[53], at[115]); MULADD(at[54], at[114]); MULADD(at[55], at[113]); MULADD(at[56], at[112]); MULADD(at[57], at[111]); MULADD(at[58], at[110]); MULADD(at[59], at[109]); MULADD(at[60], at[108]); MULADD(at[61], at[107]); MULADD(at[62], at[106]); MULADD(at[63], at[105]); + COMBA_STORE(C->dp[104]); + /* 105 */ + COMBA_FORWARD; + MULADD(at[42], at[127]); MULADD(at[43], at[126]); MULADD(at[44], at[125]); MULADD(at[45], at[124]); MULADD(at[46], at[123]); MULADD(at[47], at[122]); MULADD(at[48], at[121]); MULADD(at[49], at[120]); MULADD(at[50], at[119]); MULADD(at[51], at[118]); MULADD(at[52], at[117]); MULADD(at[53], at[116]); MULADD(at[54], at[115]); MULADD(at[55], at[114]); MULADD(at[56], at[113]); MULADD(at[57], at[112]); MULADD(at[58], at[111]); MULADD(at[59], at[110]); MULADD(at[60], at[109]); MULADD(at[61], at[108]); MULADD(at[62], at[107]); MULADD(at[63], at[106]); + COMBA_STORE(C->dp[105]); + /* 106 */ + COMBA_FORWARD; + MULADD(at[43], at[127]); MULADD(at[44], at[126]); MULADD(at[45], at[125]); MULADD(at[46], at[124]); MULADD(at[47], at[123]); MULADD(at[48], at[122]); MULADD(at[49], at[121]); MULADD(at[50], at[120]); MULADD(at[51], at[119]); MULADD(at[52], at[118]); MULADD(at[53], at[117]); MULADD(at[54], at[116]); MULADD(at[55], at[115]); MULADD(at[56], at[114]); MULADD(at[57], at[113]); MULADD(at[58], at[112]); MULADD(at[59], at[111]); MULADD(at[60], at[110]); MULADD(at[61], at[109]); MULADD(at[62], at[108]); MULADD(at[63], at[107]); + COMBA_STORE(C->dp[106]); + /* 107 */ + COMBA_FORWARD; + MULADD(at[44], at[127]); MULADD(at[45], at[126]); MULADD(at[46], at[125]); MULADD(at[47], at[124]); MULADD(at[48], at[123]); MULADD(at[49], at[122]); MULADD(at[50], at[121]); MULADD(at[51], at[120]); MULADD(at[52], at[119]); MULADD(at[53], at[118]); MULADD(at[54], at[117]); MULADD(at[55], at[116]); MULADD(at[56], at[115]); MULADD(at[57], at[114]); MULADD(at[58], at[113]); MULADD(at[59], at[112]); MULADD(at[60], at[111]); MULADD(at[61], at[110]); MULADD(at[62], at[109]); MULADD(at[63], at[108]); + COMBA_STORE(C->dp[107]); + /* 108 */ + COMBA_FORWARD; + MULADD(at[45], at[127]); MULADD(at[46], at[126]); MULADD(at[47], at[125]); MULADD(at[48], at[124]); MULADD(at[49], at[123]); MULADD(at[50], at[122]); MULADD(at[51], at[121]); MULADD(at[52], at[120]); MULADD(at[53], at[119]); MULADD(at[54], at[118]); MULADD(at[55], at[117]); MULADD(at[56], at[116]); MULADD(at[57], at[115]); MULADD(at[58], at[114]); MULADD(at[59], at[113]); MULADD(at[60], at[112]); MULADD(at[61], at[111]); MULADD(at[62], at[110]); MULADD(at[63], at[109]); + COMBA_STORE(C->dp[108]); + /* 109 */ + COMBA_FORWARD; + MULADD(at[46], at[127]); MULADD(at[47], at[126]); MULADD(at[48], at[125]); MULADD(at[49], at[124]); MULADD(at[50], at[123]); MULADD(at[51], at[122]); MULADD(at[52], at[121]); MULADD(at[53], at[120]); MULADD(at[54], at[119]); MULADD(at[55], at[118]); MULADD(at[56], at[117]); MULADD(at[57], at[116]); MULADD(at[58], at[115]); MULADD(at[59], at[114]); MULADD(at[60], at[113]); MULADD(at[61], at[112]); MULADD(at[62], at[111]); MULADD(at[63], at[110]); + COMBA_STORE(C->dp[109]); + /* 110 */ + COMBA_FORWARD; + MULADD(at[47], at[127]); MULADD(at[48], at[126]); MULADD(at[49], at[125]); MULADD(at[50], at[124]); MULADD(at[51], at[123]); MULADD(at[52], at[122]); MULADD(at[53], at[121]); MULADD(at[54], at[120]); MULADD(at[55], at[119]); MULADD(at[56], at[118]); MULADD(at[57], at[117]); MULADD(at[58], at[116]); MULADD(at[59], at[115]); MULADD(at[60], at[114]); MULADD(at[61], at[113]); MULADD(at[62], at[112]); MULADD(at[63], at[111]); + COMBA_STORE(C->dp[110]); + /* 111 */ + COMBA_FORWARD; + MULADD(at[48], at[127]); MULADD(at[49], at[126]); MULADD(at[50], at[125]); MULADD(at[51], at[124]); MULADD(at[52], at[123]); MULADD(at[53], at[122]); MULADD(at[54], at[121]); MULADD(at[55], at[120]); MULADD(at[56], at[119]); MULADD(at[57], at[118]); MULADD(at[58], at[117]); MULADD(at[59], at[116]); MULADD(at[60], at[115]); MULADD(at[61], at[114]); MULADD(at[62], at[113]); MULADD(at[63], at[112]); + COMBA_STORE(C->dp[111]); + /* 112 */ + COMBA_FORWARD; + MULADD(at[49], at[127]); MULADD(at[50], at[126]); MULADD(at[51], at[125]); MULADD(at[52], at[124]); MULADD(at[53], at[123]); MULADD(at[54], at[122]); MULADD(at[55], at[121]); MULADD(at[56], at[120]); MULADD(at[57], at[119]); MULADD(at[58], at[118]); MULADD(at[59], at[117]); MULADD(at[60], at[116]); MULADD(at[61], at[115]); MULADD(at[62], at[114]); MULADD(at[63], at[113]); + COMBA_STORE(C->dp[112]); + /* 113 */ + COMBA_FORWARD; + MULADD(at[50], at[127]); MULADD(at[51], at[126]); MULADD(at[52], at[125]); MULADD(at[53], at[124]); MULADD(at[54], at[123]); MULADD(at[55], at[122]); MULADD(at[56], at[121]); MULADD(at[57], at[120]); MULADD(at[58], at[119]); MULADD(at[59], at[118]); MULADD(at[60], at[117]); MULADD(at[61], at[116]); MULADD(at[62], at[115]); MULADD(at[63], at[114]); + COMBA_STORE(C->dp[113]); + /* 114 */ + COMBA_FORWARD; + MULADD(at[51], at[127]); MULADD(at[52], at[126]); MULADD(at[53], at[125]); MULADD(at[54], at[124]); MULADD(at[55], at[123]); MULADD(at[56], at[122]); MULADD(at[57], at[121]); MULADD(at[58], at[120]); MULADD(at[59], at[119]); MULADD(at[60], at[118]); MULADD(at[61], at[117]); MULADD(at[62], at[116]); MULADD(at[63], at[115]); + COMBA_STORE(C->dp[114]); + /* 115 */ + COMBA_FORWARD; + MULADD(at[52], at[127]); MULADD(at[53], at[126]); MULADD(at[54], at[125]); MULADD(at[55], at[124]); MULADD(at[56], at[123]); MULADD(at[57], at[122]); MULADD(at[58], at[121]); MULADD(at[59], at[120]); MULADD(at[60], at[119]); MULADD(at[61], at[118]); MULADD(at[62], at[117]); MULADD(at[63], at[116]); + COMBA_STORE(C->dp[115]); + /* 116 */ + COMBA_FORWARD; + MULADD(at[53], at[127]); MULADD(at[54], at[126]); MULADD(at[55], at[125]); MULADD(at[56], at[124]); MULADD(at[57], at[123]); MULADD(at[58], at[122]); MULADD(at[59], at[121]); MULADD(at[60], at[120]); MULADD(at[61], at[119]); MULADD(at[62], at[118]); MULADD(at[63], at[117]); + COMBA_STORE(C->dp[116]); + /* 117 */ + COMBA_FORWARD; + MULADD(at[54], at[127]); MULADD(at[55], at[126]); MULADD(at[56], at[125]); MULADD(at[57], at[124]); MULADD(at[58], at[123]); MULADD(at[59], at[122]); MULADD(at[60], at[121]); MULADD(at[61], at[120]); MULADD(at[62], at[119]); MULADD(at[63], at[118]); + COMBA_STORE(C->dp[117]); + /* 118 */ + COMBA_FORWARD; + MULADD(at[55], at[127]); MULADD(at[56], at[126]); MULADD(at[57], at[125]); MULADD(at[58], at[124]); MULADD(at[59], at[123]); MULADD(at[60], at[122]); MULADD(at[61], at[121]); MULADD(at[62], at[120]); MULADD(at[63], at[119]); + COMBA_STORE(C->dp[118]); + /* 119 */ + COMBA_FORWARD; + MULADD(at[56], at[127]); MULADD(at[57], at[126]); MULADD(at[58], at[125]); MULADD(at[59], at[124]); MULADD(at[60], at[123]); MULADD(at[61], at[122]); MULADD(at[62], at[121]); MULADD(at[63], at[120]); + COMBA_STORE(C->dp[119]); + /* 120 */ + COMBA_FORWARD; + MULADD(at[57], at[127]); MULADD(at[58], at[126]); MULADD(at[59], at[125]); MULADD(at[60], at[124]); MULADD(at[61], at[123]); MULADD(at[62], at[122]); MULADD(at[63], at[121]); + COMBA_STORE(C->dp[120]); + /* 121 */ + COMBA_FORWARD; + MULADD(at[58], at[127]); MULADD(at[59], at[126]); MULADD(at[60], at[125]); MULADD(at[61], at[124]); MULADD(at[62], at[123]); MULADD(at[63], at[122]); + COMBA_STORE(C->dp[121]); + /* 122 */ + COMBA_FORWARD; + MULADD(at[59], at[127]); MULADD(at[60], at[126]); MULADD(at[61], at[125]); MULADD(at[62], at[124]); MULADD(at[63], at[123]); + COMBA_STORE(C->dp[122]); + /* 123 */ + COMBA_FORWARD; + MULADD(at[60], at[127]); MULADD(at[61], at[126]); MULADD(at[62], at[125]); MULADD(at[63], at[124]); + COMBA_STORE(C->dp[123]); + /* 124 */ + COMBA_FORWARD; + MULADD(at[61], at[127]); MULADD(at[62], at[126]); MULADD(at[63], at[125]); + COMBA_STORE(C->dp[124]); + /* 125 */ + COMBA_FORWARD; + MULADD(at[62], at[127]); MULADD(at[63], at[126]); + COMBA_STORE(C->dp[125]); + /* 126 */ + COMBA_FORWARD; + MULADD(at[63], at[127]); + COMBA_STORE(C->dp[126]); + COMBA_STORE2(C->dp[127]); + C->used = 128; + C->sign = A->sign ^ B->sign; + fp_clamp(C); + COMBA_FINI; + +#ifdef WOLFSSL_SMALL_STACK + XFREE(at, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; +} +#endif diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_mul_comba_7.i b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_mul_comba_7.i new file mode 100755 index 0000000..a7335cc --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_mul_comba_7.i @@ -0,0 +1,107 @@ +/* fp_mul_comba_7.i + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifdef TFM_MUL7 +int fp_mul_comba7(fp_int *A, fp_int *B, fp_int *C) +{ + fp_digit c0, c1, c2; +#ifndef WOLFSSL_SMALL_STACK + fp_digit at[14]; +#else + fp_digit *at; +#endif + +#ifdef WOLFSSL_SMALL_STACK + at = (fp_digit*)XMALLOC(sizeof(fp_digit) * 14, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (at == NULL) + return FP_MEM; +#endif + + XMEMCPY(at, A->dp, 7 * sizeof(fp_digit)); + XMEMCPY(at+7, B->dp, 7 * sizeof(fp_digit)); + COMBA_START; + + COMBA_CLEAR; + /* 0 */ + MULADD(at[0], at[7]); + COMBA_STORE(C->dp[0]); + /* 1 */ + COMBA_FORWARD; + MULADD(at[0], at[8]); MULADD(at[1], at[7]); + COMBA_STORE(C->dp[1]); + /* 2 */ + COMBA_FORWARD; + MULADD(at[0], at[9]); MULADD(at[1], at[8]); MULADD(at[2], at[7]); + COMBA_STORE(C->dp[2]); + /* 3 */ + COMBA_FORWARD; + MULADD(at[0], at[10]); MULADD(at[1], at[9]); MULADD(at[2], at[8]); MULADD(at[3], at[7]); + COMBA_STORE(C->dp[3]); + /* 4 */ + COMBA_FORWARD; + MULADD(at[0], at[11]); MULADD(at[1], at[10]); MULADD(at[2], at[9]); MULADD(at[3], at[8]); MULADD(at[4], at[7]); + COMBA_STORE(C->dp[4]); + /* 5 */ + COMBA_FORWARD; + MULADD(at[0], at[12]); MULADD(at[1], at[11]); MULADD(at[2], at[10]); MULADD(at[3], at[9]); MULADD(at[4], at[8]); MULADD(at[5], at[7]); + COMBA_STORE(C->dp[5]); + /* 6 */ + COMBA_FORWARD; + MULADD(at[0], at[13]); MULADD(at[1], at[12]); MULADD(at[2], at[11]); MULADD(at[3], at[10]); MULADD(at[4], at[9]); MULADD(at[5], at[8]); MULADD(at[6], at[7]); + COMBA_STORE(C->dp[6]); + /* 7 */ + COMBA_FORWARD; + MULADD(at[1], at[13]); MULADD(at[2], at[12]); MULADD(at[3], at[11]); MULADD(at[4], at[10]); MULADD(at[5], at[9]); MULADD(at[6], at[8]); + COMBA_STORE(C->dp[7]); + /* 8 */ + COMBA_FORWARD; + MULADD(at[2], at[13]); MULADD(at[3], at[12]); MULADD(at[4], at[11]); MULADD(at[5], at[10]); MULADD(at[6], at[9]); + COMBA_STORE(C->dp[8]); + /* 9 */ + COMBA_FORWARD; + MULADD(at[3], at[13]); MULADD(at[4], at[12]); MULADD(at[5], at[11]); MULADD(at[6], at[10]); + COMBA_STORE(C->dp[9]); + /* 10 */ + COMBA_FORWARD; + MULADD(at[4], at[13]); MULADD(at[5], at[12]); MULADD(at[6], at[11]); + COMBA_STORE(C->dp[10]); + /* 11 */ + COMBA_FORWARD; + MULADD(at[5], at[13]); MULADD(at[6], at[12]); + COMBA_STORE(C->dp[11]); + /* 12 */ + COMBA_FORWARD; + MULADD(at[6], at[13]); + COMBA_STORE(C->dp[12]); + COMBA_STORE2(C->dp[13]); + C->used = 14; + C->sign = A->sign ^ B->sign; + fp_clamp(C); + COMBA_FINI; + +#ifdef WOLFSSL_SMALL_STACK + XFREE(at, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; +} +#endif diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_mul_comba_8.i b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_mul_comba_8.i new file mode 100755 index 0000000..5df8293 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_mul_comba_8.i @@ -0,0 +1,115 @@ +/* fp_mul_comba_8.i + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifdef TFM_MUL8 +int fp_mul_comba8(fp_int *A, fp_int *B, fp_int *C) +{ + fp_digit c0, c1, c2; +#ifndef WOLFSSL_SMALL_STACK + fp_digit at[16]; +#else + fp_digit *at; +#endif + +#ifdef WOLFSSL_SMALL_STACK + at = (fp_digit*)XMALLOC(sizeof(fp_digit) * 16, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (at == NULL) + return FP_MEM; +#endif + + XMEMCPY(at, A->dp, 8 * sizeof(fp_digit)); + XMEMCPY(at+8, B->dp, 8 * sizeof(fp_digit)); + COMBA_START; + + COMBA_CLEAR; + /* 0 */ + MULADD(at[0], at[8]); + COMBA_STORE(C->dp[0]); + /* 1 */ + COMBA_FORWARD; + MULADD(at[0], at[9]); MULADD(at[1], at[8]); + COMBA_STORE(C->dp[1]); + /* 2 */ + COMBA_FORWARD; + MULADD(at[0], at[10]); MULADD(at[1], at[9]); MULADD(at[2], at[8]); + COMBA_STORE(C->dp[2]); + /* 3 */ + COMBA_FORWARD; + MULADD(at[0], at[11]); MULADD(at[1], at[10]); MULADD(at[2], at[9]); MULADD(at[3], at[8]); + COMBA_STORE(C->dp[3]); + /* 4 */ + COMBA_FORWARD; + MULADD(at[0], at[12]); MULADD(at[1], at[11]); MULADD(at[2], at[10]); MULADD(at[3], at[9]); MULADD(at[4], at[8]); + COMBA_STORE(C->dp[4]); + /* 5 */ + COMBA_FORWARD; + MULADD(at[0], at[13]); MULADD(at[1], at[12]); MULADD(at[2], at[11]); MULADD(at[3], at[10]); MULADD(at[4], at[9]); MULADD(at[5], at[8]); + COMBA_STORE(C->dp[5]); + /* 6 */ + COMBA_FORWARD; + MULADD(at[0], at[14]); MULADD(at[1], at[13]); MULADD(at[2], at[12]); MULADD(at[3], at[11]); MULADD(at[4], at[10]); MULADD(at[5], at[9]); MULADD(at[6], at[8]); + COMBA_STORE(C->dp[6]); + /* 7 */ + COMBA_FORWARD; + MULADD(at[0], at[15]); MULADD(at[1], at[14]); MULADD(at[2], at[13]); MULADD(at[3], at[12]); MULADD(at[4], at[11]); MULADD(at[5], at[10]); MULADD(at[6], at[9]); MULADD(at[7], at[8]); + COMBA_STORE(C->dp[7]); + /* 8 */ + COMBA_FORWARD; + MULADD(at[1], at[15]); MULADD(at[2], at[14]); MULADD(at[3], at[13]); MULADD(at[4], at[12]); MULADD(at[5], at[11]); MULADD(at[6], at[10]); MULADD(at[7], at[9]); + COMBA_STORE(C->dp[8]); + /* 9 */ + COMBA_FORWARD; + MULADD(at[2], at[15]); MULADD(at[3], at[14]); MULADD(at[4], at[13]); MULADD(at[5], at[12]); MULADD(at[6], at[11]); MULADD(at[7], at[10]); + COMBA_STORE(C->dp[9]); + /* 10 */ + COMBA_FORWARD; + MULADD(at[3], at[15]); MULADD(at[4], at[14]); MULADD(at[5], at[13]); MULADD(at[6], at[12]); MULADD(at[7], at[11]); + COMBA_STORE(C->dp[10]); + /* 11 */ + COMBA_FORWARD; + MULADD(at[4], at[15]); MULADD(at[5], at[14]); MULADD(at[6], at[13]); MULADD(at[7], at[12]); + COMBA_STORE(C->dp[11]); + /* 12 */ + COMBA_FORWARD; + MULADD(at[5], at[15]); MULADD(at[6], at[14]); MULADD(at[7], at[13]); + COMBA_STORE(C->dp[12]); + /* 13 */ + COMBA_FORWARD; + MULADD(at[6], at[15]); MULADD(at[7], at[14]); + COMBA_STORE(C->dp[13]); + /* 14 */ + COMBA_FORWARD; + MULADD(at[7], at[15]); + COMBA_STORE(C->dp[14]); + COMBA_STORE2(C->dp[15]); + C->used = 16; + C->sign = A->sign ^ B->sign; + fp_clamp(C); + COMBA_FINI; + +#ifdef WOLFSSL_SMALL_STACK + XFREE(at, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; +} +#endif diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_mul_comba_9.i b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_mul_comba_9.i new file mode 100755 index 0000000..9ef2eae --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_mul_comba_9.i @@ -0,0 +1,123 @@ +/* fp_mul_comba_9.i + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifdef TFM_MUL9 +int fp_mul_comba9(fp_int *A, fp_int *B, fp_int *C) +{ + fp_digit c0, c1, c2; +#ifndef WOLFSSL_SMALL_STACK + fp_digit at[18]; +#else + fp_digit *at; +#endif + +#ifdef WOLFSSL_SMALL_STACK + at = (fp_digit*)XMALLOC(sizeof(fp_digit) * 18, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (at == NULL) + return FP_MEM; +#endif + + XMEMCPY(at, A->dp, 9 * sizeof(fp_digit)); + XMEMCPY(at+9, B->dp, 9 * sizeof(fp_digit)); + COMBA_START; + + COMBA_CLEAR; + /* 0 */ + MULADD(at[0], at[9]); + COMBA_STORE(C->dp[0]); + /* 1 */ + COMBA_FORWARD; + MULADD(at[0], at[10]); MULADD(at[1], at[9]); + COMBA_STORE(C->dp[1]); + /* 2 */ + COMBA_FORWARD; + MULADD(at[0], at[11]); MULADD(at[1], at[10]); MULADD(at[2], at[9]); + COMBA_STORE(C->dp[2]); + /* 3 */ + COMBA_FORWARD; + MULADD(at[0], at[12]); MULADD(at[1], at[11]); MULADD(at[2], at[10]); MULADD(at[3], at[9]); + COMBA_STORE(C->dp[3]); + /* 4 */ + COMBA_FORWARD; + MULADD(at[0], at[13]); MULADD(at[1], at[12]); MULADD(at[2], at[11]); MULADD(at[3], at[10]); MULADD(at[4], at[9]); + COMBA_STORE(C->dp[4]); + /* 5 */ + COMBA_FORWARD; + MULADD(at[0], at[14]); MULADD(at[1], at[13]); MULADD(at[2], at[12]); MULADD(at[3], at[11]); MULADD(at[4], at[10]); MULADD(at[5], at[9]); + COMBA_STORE(C->dp[5]); + /* 6 */ + COMBA_FORWARD; + MULADD(at[0], at[15]); MULADD(at[1], at[14]); MULADD(at[2], at[13]); MULADD(at[3], at[12]); MULADD(at[4], at[11]); MULADD(at[5], at[10]); MULADD(at[6], at[9]); + COMBA_STORE(C->dp[6]); + /* 7 */ + COMBA_FORWARD; + MULADD(at[0], at[16]); MULADD(at[1], at[15]); MULADD(at[2], at[14]); MULADD(at[3], at[13]); MULADD(at[4], at[12]); MULADD(at[5], at[11]); MULADD(at[6], at[10]); MULADD(at[7], at[9]); + COMBA_STORE(C->dp[7]); + /* 8 */ + COMBA_FORWARD; + MULADD(at[0], at[17]); MULADD(at[1], at[16]); MULADD(at[2], at[15]); MULADD(at[3], at[14]); MULADD(at[4], at[13]); MULADD(at[5], at[12]); MULADD(at[6], at[11]); MULADD(at[7], at[10]); MULADD(at[8], at[9]); + COMBA_STORE(C->dp[8]); + /* 9 */ + COMBA_FORWARD; + MULADD(at[1], at[17]); MULADD(at[2], at[16]); MULADD(at[3], at[15]); MULADD(at[4], at[14]); MULADD(at[5], at[13]); MULADD(at[6], at[12]); MULADD(at[7], at[11]); MULADD(at[8], at[10]); + COMBA_STORE(C->dp[9]); + /* 10 */ + COMBA_FORWARD; + MULADD(at[2], at[17]); MULADD(at[3], at[16]); MULADD(at[4], at[15]); MULADD(at[5], at[14]); MULADD(at[6], at[13]); MULADD(at[7], at[12]); MULADD(at[8], at[11]); + COMBA_STORE(C->dp[10]); + /* 11 */ + COMBA_FORWARD; + MULADD(at[3], at[17]); MULADD(at[4], at[16]); MULADD(at[5], at[15]); MULADD(at[6], at[14]); MULADD(at[7], at[13]); MULADD(at[8], at[12]); + COMBA_STORE(C->dp[11]); + /* 12 */ + COMBA_FORWARD; + MULADD(at[4], at[17]); MULADD(at[5], at[16]); MULADD(at[6], at[15]); MULADD(at[7], at[14]); MULADD(at[8], at[13]); + COMBA_STORE(C->dp[12]); + /* 13 */ + COMBA_FORWARD; + MULADD(at[5], at[17]); MULADD(at[6], at[16]); MULADD(at[7], at[15]); MULADD(at[8], at[14]); + COMBA_STORE(C->dp[13]); + /* 14 */ + COMBA_FORWARD; + MULADD(at[6], at[17]); MULADD(at[7], at[16]); MULADD(at[8], at[15]); + COMBA_STORE(C->dp[14]); + /* 15 */ + COMBA_FORWARD; + MULADD(at[7], at[17]); MULADD(at[8], at[16]); + COMBA_STORE(C->dp[15]); + /* 16 */ + COMBA_FORWARD; + MULADD(at[8], at[17]); + COMBA_STORE(C->dp[16]); + COMBA_STORE2(C->dp[17]); + C->used = 18; + C->sign = A->sign ^ B->sign; + fp_clamp(C); + COMBA_FINI; + +#ifdef WOLFSSL_SMALL_STACK + XFREE(at, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; +} +#endif diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_mul_comba_small_set.i b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_mul_comba_small_set.i new file mode 100755 index 0000000..1c0e024 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_mul_comba_small_set.i @@ -0,0 +1,1268 @@ +/* fp_mul_comba_small_set.i + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#if defined(TFM_SMALL_SET) +int fp_mul_comba_small(fp_int *A, fp_int *B, fp_int *C) +{ + fp_digit c0, c1, c2; +#ifndef WOLFSSL_SMALL_STACK + fp_digit at[32]; +#else + fp_digit *at; +#endif + +#ifdef WOLFSSL_SMALL_STACK + at = (fp_digit*)XMALLOC(sizeof(fp_digit) * 32, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (at == NULL) + return FP_MEM; +#endif + + switch (MAX(A->used, B->used)) { + + case 1: + XMEMCPY(at, A->dp, 1 * sizeof(fp_digit)); + XMEMCPY(at+1, B->dp, 1 * sizeof(fp_digit)); + COMBA_START; + + COMBA_CLEAR; + /* 0 */ + MULADD(at[0], at[1]); + COMBA_STORE(C->dp[0]); + COMBA_STORE2(C->dp[1]); + C->used = 2; + C->sign = A->sign ^ B->sign; + fp_clamp(C); + COMBA_FINI; + break; + + case 2: + XMEMCPY(at, A->dp, 2 * sizeof(fp_digit)); + XMEMCPY(at+2, B->dp, 2 * sizeof(fp_digit)); + COMBA_START; + + COMBA_CLEAR; + /* 0 */ + MULADD(at[0], at[2]); + COMBA_STORE(C->dp[0]); + /* 1 */ + COMBA_FORWARD; + MULADD(at[0], at[3]); MULADD(at[1], at[2]); + COMBA_STORE(C->dp[1]); + /* 2 */ + COMBA_FORWARD; + MULADD(at[1], at[3]); + COMBA_STORE(C->dp[2]); + COMBA_STORE2(C->dp[3]); + C->used = 4; + C->sign = A->sign ^ B->sign; + fp_clamp(C); + COMBA_FINI; + break; + + case 3: + XMEMCPY(at, A->dp, 3 * sizeof(fp_digit)); + XMEMCPY(at+3, B->dp, 3 * sizeof(fp_digit)); + COMBA_START; + + COMBA_CLEAR; + /* 0 */ + MULADD(at[0], at[3]); + COMBA_STORE(C->dp[0]); + /* 1 */ + COMBA_FORWARD; + MULADD(at[0], at[4]); MULADD(at[1], at[3]); + COMBA_STORE(C->dp[1]); + /* 2 */ + COMBA_FORWARD; + MULADD(at[0], at[5]); MULADD(at[1], at[4]); MULADD(at[2], at[3]); + COMBA_STORE(C->dp[2]); + /* 3 */ + COMBA_FORWARD; + MULADD(at[1], at[5]); MULADD(at[2], at[4]); + COMBA_STORE(C->dp[3]); + /* 4 */ + COMBA_FORWARD; + MULADD(at[2], at[5]); + COMBA_STORE(C->dp[4]); + COMBA_STORE2(C->dp[5]); + C->used = 6; + C->sign = A->sign ^ B->sign; + fp_clamp(C); + COMBA_FINI; + break; + + case 4: + XMEMCPY(at, A->dp, 4 * sizeof(fp_digit)); + XMEMCPY(at+4, B->dp, 4 * sizeof(fp_digit)); + COMBA_START; + + COMBA_CLEAR; + /* 0 */ + MULADD(at[0], at[4]); + COMBA_STORE(C->dp[0]); + /* 1 */ + COMBA_FORWARD; + MULADD(at[0], at[5]); MULADD(at[1], at[4]); + COMBA_STORE(C->dp[1]); + /* 2 */ + COMBA_FORWARD; + MULADD(at[0], at[6]); MULADD(at[1], at[5]); MULADD(at[2], at[4]); + COMBA_STORE(C->dp[2]); + /* 3 */ + COMBA_FORWARD; + MULADD(at[0], at[7]); MULADD(at[1], at[6]); MULADD(at[2], at[5]); MULADD(at[3], at[4]); + COMBA_STORE(C->dp[3]); + /* 4 */ + COMBA_FORWARD; + MULADD(at[1], at[7]); MULADD(at[2], at[6]); MULADD(at[3], at[5]); + COMBA_STORE(C->dp[4]); + /* 5 */ + COMBA_FORWARD; + MULADD(at[2], at[7]); MULADD(at[3], at[6]); + COMBA_STORE(C->dp[5]); + /* 6 */ + COMBA_FORWARD; + MULADD(at[3], at[7]); + COMBA_STORE(C->dp[6]); + COMBA_STORE2(C->dp[7]); + C->used = 8; + C->sign = A->sign ^ B->sign; + fp_clamp(C); + COMBA_FINI; + break; + + case 5: + XMEMCPY(at, A->dp, 5 * sizeof(fp_digit)); + XMEMCPY(at+5, B->dp, 5 * sizeof(fp_digit)); + COMBA_START; + + COMBA_CLEAR; + /* 0 */ + MULADD(at[0], at[5]); + COMBA_STORE(C->dp[0]); + /* 1 */ + COMBA_FORWARD; + MULADD(at[0], at[6]); MULADD(at[1], at[5]); + COMBA_STORE(C->dp[1]); + /* 2 */ + COMBA_FORWARD; + MULADD(at[0], at[7]); MULADD(at[1], at[6]); MULADD(at[2], at[5]); + COMBA_STORE(C->dp[2]); + /* 3 */ + COMBA_FORWARD; + MULADD(at[0], at[8]); MULADD(at[1], at[7]); MULADD(at[2], at[6]); MULADD(at[3], at[5]); + COMBA_STORE(C->dp[3]); + /* 4 */ + COMBA_FORWARD; + MULADD(at[0], at[9]); MULADD(at[1], at[8]); MULADD(at[2], at[7]); MULADD(at[3], at[6]); MULADD(at[4], at[5]); + COMBA_STORE(C->dp[4]); + /* 5 */ + COMBA_FORWARD; + MULADD(at[1], at[9]); MULADD(at[2], at[8]); MULADD(at[3], at[7]); MULADD(at[4], at[6]); + COMBA_STORE(C->dp[5]); + /* 6 */ + COMBA_FORWARD; + MULADD(at[2], at[9]); MULADD(at[3], at[8]); MULADD(at[4], at[7]); + COMBA_STORE(C->dp[6]); + /* 7 */ + COMBA_FORWARD; + MULADD(at[3], at[9]); MULADD(at[4], at[8]); + COMBA_STORE(C->dp[7]); + /* 8 */ + COMBA_FORWARD; + MULADD(at[4], at[9]); + COMBA_STORE(C->dp[8]); + COMBA_STORE2(C->dp[9]); + C->used = 10; + C->sign = A->sign ^ B->sign; + fp_clamp(C); + COMBA_FINI; + break; + + case 6: + XMEMCPY(at, A->dp, 6 * sizeof(fp_digit)); + XMEMCPY(at+6, B->dp, 6 * sizeof(fp_digit)); + COMBA_START; + + COMBA_CLEAR; + /* 0 */ + MULADD(at[0], at[6]); + COMBA_STORE(C->dp[0]); + /* 1 */ + COMBA_FORWARD; + MULADD(at[0], at[7]); MULADD(at[1], at[6]); + COMBA_STORE(C->dp[1]); + /* 2 */ + COMBA_FORWARD; + MULADD(at[0], at[8]); MULADD(at[1], at[7]); MULADD(at[2], at[6]); + COMBA_STORE(C->dp[2]); + /* 3 */ + COMBA_FORWARD; + MULADD(at[0], at[9]); MULADD(at[1], at[8]); MULADD(at[2], at[7]); MULADD(at[3], at[6]); + COMBA_STORE(C->dp[3]); + /* 4 */ + COMBA_FORWARD; + MULADD(at[0], at[10]); MULADD(at[1], at[9]); MULADD(at[2], at[8]); MULADD(at[3], at[7]); MULADD(at[4], at[6]); + COMBA_STORE(C->dp[4]); + /* 5 */ + COMBA_FORWARD; + MULADD(at[0], at[11]); MULADD(at[1], at[10]); MULADD(at[2], at[9]); MULADD(at[3], at[8]); MULADD(at[4], at[7]); MULADD(at[5], at[6]); + COMBA_STORE(C->dp[5]); + /* 6 */ + COMBA_FORWARD; + MULADD(at[1], at[11]); MULADD(at[2], at[10]); MULADD(at[3], at[9]); MULADD(at[4], at[8]); MULADD(at[5], at[7]); + COMBA_STORE(C->dp[6]); + /* 7 */ + COMBA_FORWARD; + MULADD(at[2], at[11]); MULADD(at[3], at[10]); MULADD(at[4], at[9]); MULADD(at[5], at[8]); + COMBA_STORE(C->dp[7]); + /* 8 */ + COMBA_FORWARD; + MULADD(at[3], at[11]); MULADD(at[4], at[10]); MULADD(at[5], at[9]); + COMBA_STORE(C->dp[8]); + /* 9 */ + COMBA_FORWARD; + MULADD(at[4], at[11]); MULADD(at[5], at[10]); + COMBA_STORE(C->dp[9]); + /* 10 */ + COMBA_FORWARD; + MULADD(at[5], at[11]); + COMBA_STORE(C->dp[10]); + COMBA_STORE2(C->dp[11]); + C->used = 12; + C->sign = A->sign ^ B->sign; + fp_clamp(C); + COMBA_FINI; + break; + + case 7: + XMEMCPY(at, A->dp, 7 * sizeof(fp_digit)); + XMEMCPY(at+7, B->dp, 7 * sizeof(fp_digit)); + COMBA_START; + + COMBA_CLEAR; + /* 0 */ + MULADD(at[0], at[7]); + COMBA_STORE(C->dp[0]); + /* 1 */ + COMBA_FORWARD; + MULADD(at[0], at[8]); MULADD(at[1], at[7]); + COMBA_STORE(C->dp[1]); + /* 2 */ + COMBA_FORWARD; + MULADD(at[0], at[9]); MULADD(at[1], at[8]); MULADD(at[2], at[7]); + COMBA_STORE(C->dp[2]); + /* 3 */ + COMBA_FORWARD; + MULADD(at[0], at[10]); MULADD(at[1], at[9]); MULADD(at[2], at[8]); MULADD(at[3], at[7]); + COMBA_STORE(C->dp[3]); + /* 4 */ + COMBA_FORWARD; + MULADD(at[0], at[11]); MULADD(at[1], at[10]); MULADD(at[2], at[9]); MULADD(at[3], at[8]); MULADD(at[4], at[7]); + COMBA_STORE(C->dp[4]); + /* 5 */ + COMBA_FORWARD; + MULADD(at[0], at[12]); MULADD(at[1], at[11]); MULADD(at[2], at[10]); MULADD(at[3], at[9]); MULADD(at[4], at[8]); MULADD(at[5], at[7]); + COMBA_STORE(C->dp[5]); + /* 6 */ + COMBA_FORWARD; + MULADD(at[0], at[13]); MULADD(at[1], at[12]); MULADD(at[2], at[11]); MULADD(at[3], at[10]); MULADD(at[4], at[9]); MULADD(at[5], at[8]); MULADD(at[6], at[7]); + COMBA_STORE(C->dp[6]); + /* 7 */ + COMBA_FORWARD; + MULADD(at[1], at[13]); MULADD(at[2], at[12]); MULADD(at[3], at[11]); MULADD(at[4], at[10]); MULADD(at[5], at[9]); MULADD(at[6], at[8]); + COMBA_STORE(C->dp[7]); + /* 8 */ + COMBA_FORWARD; + MULADD(at[2], at[13]); MULADD(at[3], at[12]); MULADD(at[4], at[11]); MULADD(at[5], at[10]); MULADD(at[6], at[9]); + COMBA_STORE(C->dp[8]); + /* 9 */ + COMBA_FORWARD; + MULADD(at[3], at[13]); MULADD(at[4], at[12]); MULADD(at[5], at[11]); MULADD(at[6], at[10]); + COMBA_STORE(C->dp[9]); + /* 10 */ + COMBA_FORWARD; + MULADD(at[4], at[13]); MULADD(at[5], at[12]); MULADD(at[6], at[11]); + COMBA_STORE(C->dp[10]); + /* 11 */ + COMBA_FORWARD; + MULADD(at[5], at[13]); MULADD(at[6], at[12]); + COMBA_STORE(C->dp[11]); + /* 12 */ + COMBA_FORWARD; + MULADD(at[6], at[13]); + COMBA_STORE(C->dp[12]); + COMBA_STORE2(C->dp[13]); + C->used = 14; + C->sign = A->sign ^ B->sign; + fp_clamp(C); + COMBA_FINI; + break; + + case 8: + XMEMCPY(at, A->dp, 8 * sizeof(fp_digit)); + XMEMCPY(at+8, B->dp, 8 * sizeof(fp_digit)); + COMBA_START; + + COMBA_CLEAR; + /* 0 */ + MULADD(at[0], at[8]); + COMBA_STORE(C->dp[0]); + /* 1 */ + COMBA_FORWARD; + MULADD(at[0], at[9]); MULADD(at[1], at[8]); + COMBA_STORE(C->dp[1]); + /* 2 */ + COMBA_FORWARD; + MULADD(at[0], at[10]); MULADD(at[1], at[9]); MULADD(at[2], at[8]); + COMBA_STORE(C->dp[2]); + /* 3 */ + COMBA_FORWARD; + MULADD(at[0], at[11]); MULADD(at[1], at[10]); MULADD(at[2], at[9]); MULADD(at[3], at[8]); + COMBA_STORE(C->dp[3]); + /* 4 */ + COMBA_FORWARD; + MULADD(at[0], at[12]); MULADD(at[1], at[11]); MULADD(at[2], at[10]); MULADD(at[3], at[9]); MULADD(at[4], at[8]); + COMBA_STORE(C->dp[4]); + /* 5 */ + COMBA_FORWARD; + MULADD(at[0], at[13]); MULADD(at[1], at[12]); MULADD(at[2], at[11]); MULADD(at[3], at[10]); MULADD(at[4], at[9]); MULADD(at[5], at[8]); + COMBA_STORE(C->dp[5]); + /* 6 */ + COMBA_FORWARD; + MULADD(at[0], at[14]); MULADD(at[1], at[13]); MULADD(at[2], at[12]); MULADD(at[3], at[11]); MULADD(at[4], at[10]); MULADD(at[5], at[9]); MULADD(at[6], at[8]); + COMBA_STORE(C->dp[6]); + /* 7 */ + COMBA_FORWARD; + MULADD(at[0], at[15]); MULADD(at[1], at[14]); MULADD(at[2], at[13]); MULADD(at[3], at[12]); MULADD(at[4], at[11]); MULADD(at[5], at[10]); MULADD(at[6], at[9]); MULADD(at[7], at[8]); + COMBA_STORE(C->dp[7]); + /* 8 */ + COMBA_FORWARD; + MULADD(at[1], at[15]); MULADD(at[2], at[14]); MULADD(at[3], at[13]); MULADD(at[4], at[12]); MULADD(at[5], at[11]); MULADD(at[6], at[10]); MULADD(at[7], at[9]); + COMBA_STORE(C->dp[8]); + /* 9 */ + COMBA_FORWARD; + MULADD(at[2], at[15]); MULADD(at[3], at[14]); MULADD(at[4], at[13]); MULADD(at[5], at[12]); MULADD(at[6], at[11]); MULADD(at[7], at[10]); + COMBA_STORE(C->dp[9]); + /* 10 */ + COMBA_FORWARD; + MULADD(at[3], at[15]); MULADD(at[4], at[14]); MULADD(at[5], at[13]); MULADD(at[6], at[12]); MULADD(at[7], at[11]); + COMBA_STORE(C->dp[10]); + /* 11 */ + COMBA_FORWARD; + MULADD(at[4], at[15]); MULADD(at[5], at[14]); MULADD(at[6], at[13]); MULADD(at[7], at[12]); + COMBA_STORE(C->dp[11]); + /* 12 */ + COMBA_FORWARD; + MULADD(at[5], at[15]); MULADD(at[6], at[14]); MULADD(at[7], at[13]); + COMBA_STORE(C->dp[12]); + /* 13 */ + COMBA_FORWARD; + MULADD(at[6], at[15]); MULADD(at[7], at[14]); + COMBA_STORE(C->dp[13]); + /* 14 */ + COMBA_FORWARD; + MULADD(at[7], at[15]); + COMBA_STORE(C->dp[14]); + COMBA_STORE2(C->dp[15]); + C->used = 16; + C->sign = A->sign ^ B->sign; + fp_clamp(C); + COMBA_FINI; + break; + + case 9: + XMEMCPY(at, A->dp, 9 * sizeof(fp_digit)); + XMEMCPY(at+9, B->dp, 9 * sizeof(fp_digit)); + COMBA_START; + + COMBA_CLEAR; + /* 0 */ + MULADD(at[0], at[9]); + COMBA_STORE(C->dp[0]); + /* 1 */ + COMBA_FORWARD; + MULADD(at[0], at[10]); MULADD(at[1], at[9]); + COMBA_STORE(C->dp[1]); + /* 2 */ + COMBA_FORWARD; + MULADD(at[0], at[11]); MULADD(at[1], at[10]); MULADD(at[2], at[9]); + COMBA_STORE(C->dp[2]); + /* 3 */ + COMBA_FORWARD; + MULADD(at[0], at[12]); MULADD(at[1], at[11]); MULADD(at[2], at[10]); MULADD(at[3], at[9]); + COMBA_STORE(C->dp[3]); + /* 4 */ + COMBA_FORWARD; + MULADD(at[0], at[13]); MULADD(at[1], at[12]); MULADD(at[2], at[11]); MULADD(at[3], at[10]); MULADD(at[4], at[9]); + COMBA_STORE(C->dp[4]); + /* 5 */ + COMBA_FORWARD; + MULADD(at[0], at[14]); MULADD(at[1], at[13]); MULADD(at[2], at[12]); MULADD(at[3], at[11]); MULADD(at[4], at[10]); MULADD(at[5], at[9]); + COMBA_STORE(C->dp[5]); + /* 6 */ + COMBA_FORWARD; + MULADD(at[0], at[15]); MULADD(at[1], at[14]); MULADD(at[2], at[13]); MULADD(at[3], at[12]); MULADD(at[4], at[11]); MULADD(at[5], at[10]); MULADD(at[6], at[9]); + COMBA_STORE(C->dp[6]); + /* 7 */ + COMBA_FORWARD; + MULADD(at[0], at[16]); MULADD(at[1], at[15]); MULADD(at[2], at[14]); MULADD(at[3], at[13]); MULADD(at[4], at[12]); MULADD(at[5], at[11]); MULADD(at[6], at[10]); MULADD(at[7], at[9]); + COMBA_STORE(C->dp[7]); + /* 8 */ + COMBA_FORWARD; + MULADD(at[0], at[17]); MULADD(at[1], at[16]); MULADD(at[2], at[15]); MULADD(at[3], at[14]); MULADD(at[4], at[13]); MULADD(at[5], at[12]); MULADD(at[6], at[11]); MULADD(at[7], at[10]); MULADD(at[8], at[9]); + COMBA_STORE(C->dp[8]); + /* 9 */ + COMBA_FORWARD; + MULADD(at[1], at[17]); MULADD(at[2], at[16]); MULADD(at[3], at[15]); MULADD(at[4], at[14]); MULADD(at[5], at[13]); MULADD(at[6], at[12]); MULADD(at[7], at[11]); MULADD(at[8], at[10]); + COMBA_STORE(C->dp[9]); + /* 10 */ + COMBA_FORWARD; + MULADD(at[2], at[17]); MULADD(at[3], at[16]); MULADD(at[4], at[15]); MULADD(at[5], at[14]); MULADD(at[6], at[13]); MULADD(at[7], at[12]); MULADD(at[8], at[11]); + COMBA_STORE(C->dp[10]); + /* 11 */ + COMBA_FORWARD; + MULADD(at[3], at[17]); MULADD(at[4], at[16]); MULADD(at[5], at[15]); MULADD(at[6], at[14]); MULADD(at[7], at[13]); MULADD(at[8], at[12]); + COMBA_STORE(C->dp[11]); + /* 12 */ + COMBA_FORWARD; + MULADD(at[4], at[17]); MULADD(at[5], at[16]); MULADD(at[6], at[15]); MULADD(at[7], at[14]); MULADD(at[8], at[13]); + COMBA_STORE(C->dp[12]); + /* 13 */ + COMBA_FORWARD; + MULADD(at[5], at[17]); MULADD(at[6], at[16]); MULADD(at[7], at[15]); MULADD(at[8], at[14]); + COMBA_STORE(C->dp[13]); + /* 14 */ + COMBA_FORWARD; + MULADD(at[6], at[17]); MULADD(at[7], at[16]); MULADD(at[8], at[15]); + COMBA_STORE(C->dp[14]); + /* 15 */ + COMBA_FORWARD; + MULADD(at[7], at[17]); MULADD(at[8], at[16]); + COMBA_STORE(C->dp[15]); + /* 16 */ + COMBA_FORWARD; + MULADD(at[8], at[17]); + COMBA_STORE(C->dp[16]); + COMBA_STORE2(C->dp[17]); + C->used = 18; + C->sign = A->sign ^ B->sign; + fp_clamp(C); + COMBA_FINI; + break; + + case 10: + XMEMCPY(at, A->dp, 10 * sizeof(fp_digit)); + XMEMCPY(at+10, B->dp, 10 * sizeof(fp_digit)); + COMBA_START; + + COMBA_CLEAR; + /* 0 */ + MULADD(at[0], at[10]); + COMBA_STORE(C->dp[0]); + /* 1 */ + COMBA_FORWARD; + MULADD(at[0], at[11]); MULADD(at[1], at[10]); + COMBA_STORE(C->dp[1]); + /* 2 */ + COMBA_FORWARD; + MULADD(at[0], at[12]); MULADD(at[1], at[11]); MULADD(at[2], at[10]); + COMBA_STORE(C->dp[2]); + /* 3 */ + COMBA_FORWARD; + MULADD(at[0], at[13]); MULADD(at[1], at[12]); MULADD(at[2], at[11]); MULADD(at[3], at[10]); + COMBA_STORE(C->dp[3]); + /* 4 */ + COMBA_FORWARD; + MULADD(at[0], at[14]); MULADD(at[1], at[13]); MULADD(at[2], at[12]); MULADD(at[3], at[11]); MULADD(at[4], at[10]); + COMBA_STORE(C->dp[4]); + /* 5 */ + COMBA_FORWARD; + MULADD(at[0], at[15]); MULADD(at[1], at[14]); MULADD(at[2], at[13]); MULADD(at[3], at[12]); MULADD(at[4], at[11]); MULADD(at[5], at[10]); + COMBA_STORE(C->dp[5]); + /* 6 */ + COMBA_FORWARD; + MULADD(at[0], at[16]); MULADD(at[1], at[15]); MULADD(at[2], at[14]); MULADD(at[3], at[13]); MULADD(at[4], at[12]); MULADD(at[5], at[11]); MULADD(at[6], at[10]); + COMBA_STORE(C->dp[6]); + /* 7 */ + COMBA_FORWARD; + MULADD(at[0], at[17]); MULADD(at[1], at[16]); MULADD(at[2], at[15]); MULADD(at[3], at[14]); MULADD(at[4], at[13]); MULADD(at[5], at[12]); MULADD(at[6], at[11]); MULADD(at[7], at[10]); + COMBA_STORE(C->dp[7]); + /* 8 */ + COMBA_FORWARD; + MULADD(at[0], at[18]); MULADD(at[1], at[17]); MULADD(at[2], at[16]); MULADD(at[3], at[15]); MULADD(at[4], at[14]); MULADD(at[5], at[13]); MULADD(at[6], at[12]); MULADD(at[7], at[11]); MULADD(at[8], at[10]); + COMBA_STORE(C->dp[8]); + /* 9 */ + COMBA_FORWARD; + MULADD(at[0], at[19]); MULADD(at[1], at[18]); MULADD(at[2], at[17]); MULADD(at[3], at[16]); MULADD(at[4], at[15]); MULADD(at[5], at[14]); MULADD(at[6], at[13]); MULADD(at[7], at[12]); MULADD(at[8], at[11]); MULADD(at[9], at[10]); + COMBA_STORE(C->dp[9]); + /* 10 */ + COMBA_FORWARD; + MULADD(at[1], at[19]); MULADD(at[2], at[18]); MULADD(at[3], at[17]); MULADD(at[4], at[16]); MULADD(at[5], at[15]); MULADD(at[6], at[14]); MULADD(at[7], at[13]); MULADD(at[8], at[12]); MULADD(at[9], at[11]); + COMBA_STORE(C->dp[10]); + /* 11 */ + COMBA_FORWARD; + MULADD(at[2], at[19]); MULADD(at[3], at[18]); MULADD(at[4], at[17]); MULADD(at[5], at[16]); MULADD(at[6], at[15]); MULADD(at[7], at[14]); MULADD(at[8], at[13]); MULADD(at[9], at[12]); + COMBA_STORE(C->dp[11]); + /* 12 */ + COMBA_FORWARD; + MULADD(at[3], at[19]); MULADD(at[4], at[18]); MULADD(at[5], at[17]); MULADD(at[6], at[16]); MULADD(at[7], at[15]); MULADD(at[8], at[14]); MULADD(at[9], at[13]); + COMBA_STORE(C->dp[12]); + /* 13 */ + COMBA_FORWARD; + MULADD(at[4], at[19]); MULADD(at[5], at[18]); MULADD(at[6], at[17]); MULADD(at[7], at[16]); MULADD(at[8], at[15]); MULADD(at[9], at[14]); + COMBA_STORE(C->dp[13]); + /* 14 */ + COMBA_FORWARD; + MULADD(at[5], at[19]); MULADD(at[6], at[18]); MULADD(at[7], at[17]); MULADD(at[8], at[16]); MULADD(at[9], at[15]); + COMBA_STORE(C->dp[14]); + /* 15 */ + COMBA_FORWARD; + MULADD(at[6], at[19]); MULADD(at[7], at[18]); MULADD(at[8], at[17]); MULADD(at[9], at[16]); + COMBA_STORE(C->dp[15]); + /* 16 */ + COMBA_FORWARD; + MULADD(at[7], at[19]); MULADD(at[8], at[18]); MULADD(at[9], at[17]); + COMBA_STORE(C->dp[16]); + /* 17 */ + COMBA_FORWARD; + MULADD(at[8], at[19]); MULADD(at[9], at[18]); + COMBA_STORE(C->dp[17]); + /* 18 */ + COMBA_FORWARD; + MULADD(at[9], at[19]); + COMBA_STORE(C->dp[18]); + COMBA_STORE2(C->dp[19]); + C->used = 20; + C->sign = A->sign ^ B->sign; + fp_clamp(C); + COMBA_FINI; + break; + + case 11: + XMEMCPY(at, A->dp, 11 * sizeof(fp_digit)); + XMEMCPY(at+11, B->dp, 11 * sizeof(fp_digit)); + COMBA_START; + + COMBA_CLEAR; + /* 0 */ + MULADD(at[0], at[11]); + COMBA_STORE(C->dp[0]); + /* 1 */ + COMBA_FORWARD; + MULADD(at[0], at[12]); MULADD(at[1], at[11]); + COMBA_STORE(C->dp[1]); + /* 2 */ + COMBA_FORWARD; + MULADD(at[0], at[13]); MULADD(at[1], at[12]); MULADD(at[2], at[11]); + COMBA_STORE(C->dp[2]); + /* 3 */ + COMBA_FORWARD; + MULADD(at[0], at[14]); MULADD(at[1], at[13]); MULADD(at[2], at[12]); MULADD(at[3], at[11]); + COMBA_STORE(C->dp[3]); + /* 4 */ + COMBA_FORWARD; + MULADD(at[0], at[15]); MULADD(at[1], at[14]); MULADD(at[2], at[13]); MULADD(at[3], at[12]); MULADD(at[4], at[11]); + COMBA_STORE(C->dp[4]); + /* 5 */ + COMBA_FORWARD; + MULADD(at[0], at[16]); MULADD(at[1], at[15]); MULADD(at[2], at[14]); MULADD(at[3], at[13]); MULADD(at[4], at[12]); MULADD(at[5], at[11]); + COMBA_STORE(C->dp[5]); + /* 6 */ + COMBA_FORWARD; + MULADD(at[0], at[17]); MULADD(at[1], at[16]); MULADD(at[2], at[15]); MULADD(at[3], at[14]); MULADD(at[4], at[13]); MULADD(at[5], at[12]); MULADD(at[6], at[11]); + COMBA_STORE(C->dp[6]); + /* 7 */ + COMBA_FORWARD; + MULADD(at[0], at[18]); MULADD(at[1], at[17]); MULADD(at[2], at[16]); MULADD(at[3], at[15]); MULADD(at[4], at[14]); MULADD(at[5], at[13]); MULADD(at[6], at[12]); MULADD(at[7], at[11]); + COMBA_STORE(C->dp[7]); + /* 8 */ + COMBA_FORWARD; + MULADD(at[0], at[19]); MULADD(at[1], at[18]); MULADD(at[2], at[17]); MULADD(at[3], at[16]); MULADD(at[4], at[15]); MULADD(at[5], at[14]); MULADD(at[6], at[13]); MULADD(at[7], at[12]); MULADD(at[8], at[11]); + COMBA_STORE(C->dp[8]); + /* 9 */ + COMBA_FORWARD; + MULADD(at[0], at[20]); MULADD(at[1], at[19]); MULADD(at[2], at[18]); MULADD(at[3], at[17]); MULADD(at[4], at[16]); MULADD(at[5], at[15]); MULADD(at[6], at[14]); MULADD(at[7], at[13]); MULADD(at[8], at[12]); MULADD(at[9], at[11]); + COMBA_STORE(C->dp[9]); + /* 10 */ + COMBA_FORWARD; + MULADD(at[0], at[21]); MULADD(at[1], at[20]); MULADD(at[2], at[19]); MULADD(at[3], at[18]); MULADD(at[4], at[17]); MULADD(at[5], at[16]); MULADD(at[6], at[15]); MULADD(at[7], at[14]); MULADD(at[8], at[13]); MULADD(at[9], at[12]); MULADD(at[10], at[11]); + COMBA_STORE(C->dp[10]); + /* 11 */ + COMBA_FORWARD; + MULADD(at[1], at[21]); MULADD(at[2], at[20]); MULADD(at[3], at[19]); MULADD(at[4], at[18]); MULADD(at[5], at[17]); MULADD(at[6], at[16]); MULADD(at[7], at[15]); MULADD(at[8], at[14]); MULADD(at[9], at[13]); MULADD(at[10], at[12]); + COMBA_STORE(C->dp[11]); + /* 12 */ + COMBA_FORWARD; + MULADD(at[2], at[21]); MULADD(at[3], at[20]); MULADD(at[4], at[19]); MULADD(at[5], at[18]); MULADD(at[6], at[17]); MULADD(at[7], at[16]); MULADD(at[8], at[15]); MULADD(at[9], at[14]); MULADD(at[10], at[13]); + COMBA_STORE(C->dp[12]); + /* 13 */ + COMBA_FORWARD; + MULADD(at[3], at[21]); MULADD(at[4], at[20]); MULADD(at[5], at[19]); MULADD(at[6], at[18]); MULADD(at[7], at[17]); MULADD(at[8], at[16]); MULADD(at[9], at[15]); MULADD(at[10], at[14]); + COMBA_STORE(C->dp[13]); + /* 14 */ + COMBA_FORWARD; + MULADD(at[4], at[21]); MULADD(at[5], at[20]); MULADD(at[6], at[19]); MULADD(at[7], at[18]); MULADD(at[8], at[17]); MULADD(at[9], at[16]); MULADD(at[10], at[15]); + COMBA_STORE(C->dp[14]); + /* 15 */ + COMBA_FORWARD; + MULADD(at[5], at[21]); MULADD(at[6], at[20]); MULADD(at[7], at[19]); MULADD(at[8], at[18]); MULADD(at[9], at[17]); MULADD(at[10], at[16]); + COMBA_STORE(C->dp[15]); + /* 16 */ + COMBA_FORWARD; + MULADD(at[6], at[21]); MULADD(at[7], at[20]); MULADD(at[8], at[19]); MULADD(at[9], at[18]); MULADD(at[10], at[17]); + COMBA_STORE(C->dp[16]); + /* 17 */ + COMBA_FORWARD; + MULADD(at[7], at[21]); MULADD(at[8], at[20]); MULADD(at[9], at[19]); MULADD(at[10], at[18]); + COMBA_STORE(C->dp[17]); + /* 18 */ + COMBA_FORWARD; + MULADD(at[8], at[21]); MULADD(at[9], at[20]); MULADD(at[10], at[19]); + COMBA_STORE(C->dp[18]); + /* 19 */ + COMBA_FORWARD; + MULADD(at[9], at[21]); MULADD(at[10], at[20]); + COMBA_STORE(C->dp[19]); + /* 20 */ + COMBA_FORWARD; + MULADD(at[10], at[21]); + COMBA_STORE(C->dp[20]); + COMBA_STORE2(C->dp[21]); + C->used = 22; + C->sign = A->sign ^ B->sign; + fp_clamp(C); + COMBA_FINI; + break; + + case 12: + XMEMCPY(at, A->dp, 12 * sizeof(fp_digit)); + XMEMCPY(at+12, B->dp, 12 * sizeof(fp_digit)); + COMBA_START; + + COMBA_CLEAR; + /* 0 */ + MULADD(at[0], at[12]); + COMBA_STORE(C->dp[0]); + /* 1 */ + COMBA_FORWARD; + MULADD(at[0], at[13]); MULADD(at[1], at[12]); + COMBA_STORE(C->dp[1]); + /* 2 */ + COMBA_FORWARD; + MULADD(at[0], at[14]); MULADD(at[1], at[13]); MULADD(at[2], at[12]); + COMBA_STORE(C->dp[2]); + /* 3 */ + COMBA_FORWARD; + MULADD(at[0], at[15]); MULADD(at[1], at[14]); MULADD(at[2], at[13]); MULADD(at[3], at[12]); + COMBA_STORE(C->dp[3]); + /* 4 */ + COMBA_FORWARD; + MULADD(at[0], at[16]); MULADD(at[1], at[15]); MULADD(at[2], at[14]); MULADD(at[3], at[13]); MULADD(at[4], at[12]); + COMBA_STORE(C->dp[4]); + /* 5 */ + COMBA_FORWARD; + MULADD(at[0], at[17]); MULADD(at[1], at[16]); MULADD(at[2], at[15]); MULADD(at[3], at[14]); MULADD(at[4], at[13]); MULADD(at[5], at[12]); + COMBA_STORE(C->dp[5]); + /* 6 */ + COMBA_FORWARD; + MULADD(at[0], at[18]); MULADD(at[1], at[17]); MULADD(at[2], at[16]); MULADD(at[3], at[15]); MULADD(at[4], at[14]); MULADD(at[5], at[13]); MULADD(at[6], at[12]); + COMBA_STORE(C->dp[6]); + /* 7 */ + COMBA_FORWARD; + MULADD(at[0], at[19]); MULADD(at[1], at[18]); MULADD(at[2], at[17]); MULADD(at[3], at[16]); MULADD(at[4], at[15]); MULADD(at[5], at[14]); MULADD(at[6], at[13]); MULADD(at[7], at[12]); + COMBA_STORE(C->dp[7]); + /* 8 */ + COMBA_FORWARD; + MULADD(at[0], at[20]); MULADD(at[1], at[19]); MULADD(at[2], at[18]); MULADD(at[3], at[17]); MULADD(at[4], at[16]); MULADD(at[5], at[15]); MULADD(at[6], at[14]); MULADD(at[7], at[13]); MULADD(at[8], at[12]); + COMBA_STORE(C->dp[8]); + /* 9 */ + COMBA_FORWARD; + MULADD(at[0], at[21]); MULADD(at[1], at[20]); MULADD(at[2], at[19]); MULADD(at[3], at[18]); MULADD(at[4], at[17]); MULADD(at[5], at[16]); MULADD(at[6], at[15]); MULADD(at[7], at[14]); MULADD(at[8], at[13]); MULADD(at[9], at[12]); + COMBA_STORE(C->dp[9]); + /* 10 */ + COMBA_FORWARD; + MULADD(at[0], at[22]); MULADD(at[1], at[21]); MULADD(at[2], at[20]); MULADD(at[3], at[19]); MULADD(at[4], at[18]); MULADD(at[5], at[17]); MULADD(at[6], at[16]); MULADD(at[7], at[15]); MULADD(at[8], at[14]); MULADD(at[9], at[13]); MULADD(at[10], at[12]); + COMBA_STORE(C->dp[10]); + /* 11 */ + COMBA_FORWARD; + MULADD(at[0], at[23]); MULADD(at[1], at[22]); MULADD(at[2], at[21]); MULADD(at[3], at[20]); MULADD(at[4], at[19]); MULADD(at[5], at[18]); MULADD(at[6], at[17]); MULADD(at[7], at[16]); MULADD(at[8], at[15]); MULADD(at[9], at[14]); MULADD(at[10], at[13]); MULADD(at[11], at[12]); + COMBA_STORE(C->dp[11]); + /* 12 */ + COMBA_FORWARD; + MULADD(at[1], at[23]); MULADD(at[2], at[22]); MULADD(at[3], at[21]); MULADD(at[4], at[20]); MULADD(at[5], at[19]); MULADD(at[6], at[18]); MULADD(at[7], at[17]); MULADD(at[8], at[16]); MULADD(at[9], at[15]); MULADD(at[10], at[14]); MULADD(at[11], at[13]); + COMBA_STORE(C->dp[12]); + /* 13 */ + COMBA_FORWARD; + MULADD(at[2], at[23]); MULADD(at[3], at[22]); MULADD(at[4], at[21]); MULADD(at[5], at[20]); MULADD(at[6], at[19]); MULADD(at[7], at[18]); MULADD(at[8], at[17]); MULADD(at[9], at[16]); MULADD(at[10], at[15]); MULADD(at[11], at[14]); + COMBA_STORE(C->dp[13]); + /* 14 */ + COMBA_FORWARD; + MULADD(at[3], at[23]); MULADD(at[4], at[22]); MULADD(at[5], at[21]); MULADD(at[6], at[20]); MULADD(at[7], at[19]); MULADD(at[8], at[18]); MULADD(at[9], at[17]); MULADD(at[10], at[16]); MULADD(at[11], at[15]); + COMBA_STORE(C->dp[14]); + /* 15 */ + COMBA_FORWARD; + MULADD(at[4], at[23]); MULADD(at[5], at[22]); MULADD(at[6], at[21]); MULADD(at[7], at[20]); MULADD(at[8], at[19]); MULADD(at[9], at[18]); MULADD(at[10], at[17]); MULADD(at[11], at[16]); + COMBA_STORE(C->dp[15]); + /* 16 */ + COMBA_FORWARD; + MULADD(at[5], at[23]); MULADD(at[6], at[22]); MULADD(at[7], at[21]); MULADD(at[8], at[20]); MULADD(at[9], at[19]); MULADD(at[10], at[18]); MULADD(at[11], at[17]); + COMBA_STORE(C->dp[16]); + /* 17 */ + COMBA_FORWARD; + MULADD(at[6], at[23]); MULADD(at[7], at[22]); MULADD(at[8], at[21]); MULADD(at[9], at[20]); MULADD(at[10], at[19]); MULADD(at[11], at[18]); + COMBA_STORE(C->dp[17]); + /* 18 */ + COMBA_FORWARD; + MULADD(at[7], at[23]); MULADD(at[8], at[22]); MULADD(at[9], at[21]); MULADD(at[10], at[20]); MULADD(at[11], at[19]); + COMBA_STORE(C->dp[18]); + /* 19 */ + COMBA_FORWARD; + MULADD(at[8], at[23]); MULADD(at[9], at[22]); MULADD(at[10], at[21]); MULADD(at[11], at[20]); + COMBA_STORE(C->dp[19]); + /* 20 */ + COMBA_FORWARD; + MULADD(at[9], at[23]); MULADD(at[10], at[22]); MULADD(at[11], at[21]); + COMBA_STORE(C->dp[20]); + /* 21 */ + COMBA_FORWARD; + MULADD(at[10], at[23]); MULADD(at[11], at[22]); + COMBA_STORE(C->dp[21]); + /* 22 */ + COMBA_FORWARD; + MULADD(at[11], at[23]); + COMBA_STORE(C->dp[22]); + COMBA_STORE2(C->dp[23]); + C->used = 24; + C->sign = A->sign ^ B->sign; + fp_clamp(C); + COMBA_FINI; + break; + + case 13: + XMEMCPY(at, A->dp, 13 * sizeof(fp_digit)); + XMEMCPY(at+13, B->dp, 13 * sizeof(fp_digit)); + COMBA_START; + + COMBA_CLEAR; + /* 0 */ + MULADD(at[0], at[13]); + COMBA_STORE(C->dp[0]); + /* 1 */ + COMBA_FORWARD; + MULADD(at[0], at[14]); MULADD(at[1], at[13]); + COMBA_STORE(C->dp[1]); + /* 2 */ + COMBA_FORWARD; + MULADD(at[0], at[15]); MULADD(at[1], at[14]); MULADD(at[2], at[13]); + COMBA_STORE(C->dp[2]); + /* 3 */ + COMBA_FORWARD; + MULADD(at[0], at[16]); MULADD(at[1], at[15]); MULADD(at[2], at[14]); MULADD(at[3], at[13]); + COMBA_STORE(C->dp[3]); + /* 4 */ + COMBA_FORWARD; + MULADD(at[0], at[17]); MULADD(at[1], at[16]); MULADD(at[2], at[15]); MULADD(at[3], at[14]); MULADD(at[4], at[13]); + COMBA_STORE(C->dp[4]); + /* 5 */ + COMBA_FORWARD; + MULADD(at[0], at[18]); MULADD(at[1], at[17]); MULADD(at[2], at[16]); MULADD(at[3], at[15]); MULADD(at[4], at[14]); MULADD(at[5], at[13]); + COMBA_STORE(C->dp[5]); + /* 6 */ + COMBA_FORWARD; + MULADD(at[0], at[19]); MULADD(at[1], at[18]); MULADD(at[2], at[17]); MULADD(at[3], at[16]); MULADD(at[4], at[15]); MULADD(at[5], at[14]); MULADD(at[6], at[13]); + COMBA_STORE(C->dp[6]); + /* 7 */ + COMBA_FORWARD; + MULADD(at[0], at[20]); MULADD(at[1], at[19]); MULADD(at[2], at[18]); MULADD(at[3], at[17]); MULADD(at[4], at[16]); MULADD(at[5], at[15]); MULADD(at[6], at[14]); MULADD(at[7], at[13]); + COMBA_STORE(C->dp[7]); + /* 8 */ + COMBA_FORWARD; + MULADD(at[0], at[21]); MULADD(at[1], at[20]); MULADD(at[2], at[19]); MULADD(at[3], at[18]); MULADD(at[4], at[17]); MULADD(at[5], at[16]); MULADD(at[6], at[15]); MULADD(at[7], at[14]); MULADD(at[8], at[13]); + COMBA_STORE(C->dp[8]); + /* 9 */ + COMBA_FORWARD; + MULADD(at[0], at[22]); MULADD(at[1], at[21]); MULADD(at[2], at[20]); MULADD(at[3], at[19]); MULADD(at[4], at[18]); MULADD(at[5], at[17]); MULADD(at[6], at[16]); MULADD(at[7], at[15]); MULADD(at[8], at[14]); MULADD(at[9], at[13]); + COMBA_STORE(C->dp[9]); + /* 10 */ + COMBA_FORWARD; + MULADD(at[0], at[23]); MULADD(at[1], at[22]); MULADD(at[2], at[21]); MULADD(at[3], at[20]); MULADD(at[4], at[19]); MULADD(at[5], at[18]); MULADD(at[6], at[17]); MULADD(at[7], at[16]); MULADD(at[8], at[15]); MULADD(at[9], at[14]); MULADD(at[10], at[13]); + COMBA_STORE(C->dp[10]); + /* 11 */ + COMBA_FORWARD; + MULADD(at[0], at[24]); MULADD(at[1], at[23]); MULADD(at[2], at[22]); MULADD(at[3], at[21]); MULADD(at[4], at[20]); MULADD(at[5], at[19]); MULADD(at[6], at[18]); MULADD(at[7], at[17]); MULADD(at[8], at[16]); MULADD(at[9], at[15]); MULADD(at[10], at[14]); MULADD(at[11], at[13]); + COMBA_STORE(C->dp[11]); + /* 12 */ + COMBA_FORWARD; + MULADD(at[0], at[25]); MULADD(at[1], at[24]); MULADD(at[2], at[23]); MULADD(at[3], at[22]); MULADD(at[4], at[21]); MULADD(at[5], at[20]); MULADD(at[6], at[19]); MULADD(at[7], at[18]); MULADD(at[8], at[17]); MULADD(at[9], at[16]); MULADD(at[10], at[15]); MULADD(at[11], at[14]); MULADD(at[12], at[13]); + COMBA_STORE(C->dp[12]); + /* 13 */ + COMBA_FORWARD; + MULADD(at[1], at[25]); MULADD(at[2], at[24]); MULADD(at[3], at[23]); MULADD(at[4], at[22]); MULADD(at[5], at[21]); MULADD(at[6], at[20]); MULADD(at[7], at[19]); MULADD(at[8], at[18]); MULADD(at[9], at[17]); MULADD(at[10], at[16]); MULADD(at[11], at[15]); MULADD(at[12], at[14]); + COMBA_STORE(C->dp[13]); + /* 14 */ + COMBA_FORWARD; + MULADD(at[2], at[25]); MULADD(at[3], at[24]); MULADD(at[4], at[23]); MULADD(at[5], at[22]); MULADD(at[6], at[21]); MULADD(at[7], at[20]); MULADD(at[8], at[19]); MULADD(at[9], at[18]); MULADD(at[10], at[17]); MULADD(at[11], at[16]); MULADD(at[12], at[15]); + COMBA_STORE(C->dp[14]); + /* 15 */ + COMBA_FORWARD; + MULADD(at[3], at[25]); MULADD(at[4], at[24]); MULADD(at[5], at[23]); MULADD(at[6], at[22]); MULADD(at[7], at[21]); MULADD(at[8], at[20]); MULADD(at[9], at[19]); MULADD(at[10], at[18]); MULADD(at[11], at[17]); MULADD(at[12], at[16]); + COMBA_STORE(C->dp[15]); + /* 16 */ + COMBA_FORWARD; + MULADD(at[4], at[25]); MULADD(at[5], at[24]); MULADD(at[6], at[23]); MULADD(at[7], at[22]); MULADD(at[8], at[21]); MULADD(at[9], at[20]); MULADD(at[10], at[19]); MULADD(at[11], at[18]); MULADD(at[12], at[17]); + COMBA_STORE(C->dp[16]); + /* 17 */ + COMBA_FORWARD; + MULADD(at[5], at[25]); MULADD(at[6], at[24]); MULADD(at[7], at[23]); MULADD(at[8], at[22]); MULADD(at[9], at[21]); MULADD(at[10], at[20]); MULADD(at[11], at[19]); MULADD(at[12], at[18]); + COMBA_STORE(C->dp[17]); + /* 18 */ + COMBA_FORWARD; + MULADD(at[6], at[25]); MULADD(at[7], at[24]); MULADD(at[8], at[23]); MULADD(at[9], at[22]); MULADD(at[10], at[21]); MULADD(at[11], at[20]); MULADD(at[12], at[19]); + COMBA_STORE(C->dp[18]); + /* 19 */ + COMBA_FORWARD; + MULADD(at[7], at[25]); MULADD(at[8], at[24]); MULADD(at[9], at[23]); MULADD(at[10], at[22]); MULADD(at[11], at[21]); MULADD(at[12], at[20]); + COMBA_STORE(C->dp[19]); + /* 20 */ + COMBA_FORWARD; + MULADD(at[8], at[25]); MULADD(at[9], at[24]); MULADD(at[10], at[23]); MULADD(at[11], at[22]); MULADD(at[12], at[21]); + COMBA_STORE(C->dp[20]); + /* 21 */ + COMBA_FORWARD; + MULADD(at[9], at[25]); MULADD(at[10], at[24]); MULADD(at[11], at[23]); MULADD(at[12], at[22]); + COMBA_STORE(C->dp[21]); + /* 22 */ + COMBA_FORWARD; + MULADD(at[10], at[25]); MULADD(at[11], at[24]); MULADD(at[12], at[23]); + COMBA_STORE(C->dp[22]); + /* 23 */ + COMBA_FORWARD; + MULADD(at[11], at[25]); MULADD(at[12], at[24]); + COMBA_STORE(C->dp[23]); + /* 24 */ + COMBA_FORWARD; + MULADD(at[12], at[25]); + COMBA_STORE(C->dp[24]); + COMBA_STORE2(C->dp[25]); + C->used = 26; + C->sign = A->sign ^ B->sign; + fp_clamp(C); + COMBA_FINI; + break; + + case 14: + XMEMCPY(at, A->dp, 14 * sizeof(fp_digit)); + XMEMCPY(at+14, B->dp, 14 * sizeof(fp_digit)); + COMBA_START; + + COMBA_CLEAR; + /* 0 */ + MULADD(at[0], at[14]); + COMBA_STORE(C->dp[0]); + /* 1 */ + COMBA_FORWARD; + MULADD(at[0], at[15]); MULADD(at[1], at[14]); + COMBA_STORE(C->dp[1]); + /* 2 */ + COMBA_FORWARD; + MULADD(at[0], at[16]); MULADD(at[1], at[15]); MULADD(at[2], at[14]); + COMBA_STORE(C->dp[2]); + /* 3 */ + COMBA_FORWARD; + MULADD(at[0], at[17]); MULADD(at[1], at[16]); MULADD(at[2], at[15]); MULADD(at[3], at[14]); + COMBA_STORE(C->dp[3]); + /* 4 */ + COMBA_FORWARD; + MULADD(at[0], at[18]); MULADD(at[1], at[17]); MULADD(at[2], at[16]); MULADD(at[3], at[15]); MULADD(at[4], at[14]); + COMBA_STORE(C->dp[4]); + /* 5 */ + COMBA_FORWARD; + MULADD(at[0], at[19]); MULADD(at[1], at[18]); MULADD(at[2], at[17]); MULADD(at[3], at[16]); MULADD(at[4], at[15]); MULADD(at[5], at[14]); + COMBA_STORE(C->dp[5]); + /* 6 */ + COMBA_FORWARD; + MULADD(at[0], at[20]); MULADD(at[1], at[19]); MULADD(at[2], at[18]); MULADD(at[3], at[17]); MULADD(at[4], at[16]); MULADD(at[5], at[15]); MULADD(at[6], at[14]); + COMBA_STORE(C->dp[6]); + /* 7 */ + COMBA_FORWARD; + MULADD(at[0], at[21]); MULADD(at[1], at[20]); MULADD(at[2], at[19]); MULADD(at[3], at[18]); MULADD(at[4], at[17]); MULADD(at[5], at[16]); MULADD(at[6], at[15]); MULADD(at[7], at[14]); + COMBA_STORE(C->dp[7]); + /* 8 */ + COMBA_FORWARD; + MULADD(at[0], at[22]); MULADD(at[1], at[21]); MULADD(at[2], at[20]); MULADD(at[3], at[19]); MULADD(at[4], at[18]); MULADD(at[5], at[17]); MULADD(at[6], at[16]); MULADD(at[7], at[15]); MULADD(at[8], at[14]); + COMBA_STORE(C->dp[8]); + /* 9 */ + COMBA_FORWARD; + MULADD(at[0], at[23]); MULADD(at[1], at[22]); MULADD(at[2], at[21]); MULADD(at[3], at[20]); MULADD(at[4], at[19]); MULADD(at[5], at[18]); MULADD(at[6], at[17]); MULADD(at[7], at[16]); MULADD(at[8], at[15]); MULADD(at[9], at[14]); + COMBA_STORE(C->dp[9]); + /* 10 */ + COMBA_FORWARD; + MULADD(at[0], at[24]); MULADD(at[1], at[23]); MULADD(at[2], at[22]); MULADD(at[3], at[21]); MULADD(at[4], at[20]); MULADD(at[5], at[19]); MULADD(at[6], at[18]); MULADD(at[7], at[17]); MULADD(at[8], at[16]); MULADD(at[9], at[15]); MULADD(at[10], at[14]); + COMBA_STORE(C->dp[10]); + /* 11 */ + COMBA_FORWARD; + MULADD(at[0], at[25]); MULADD(at[1], at[24]); MULADD(at[2], at[23]); MULADD(at[3], at[22]); MULADD(at[4], at[21]); MULADD(at[5], at[20]); MULADD(at[6], at[19]); MULADD(at[7], at[18]); MULADD(at[8], at[17]); MULADD(at[9], at[16]); MULADD(at[10], at[15]); MULADD(at[11], at[14]); + COMBA_STORE(C->dp[11]); + /* 12 */ + COMBA_FORWARD; + MULADD(at[0], at[26]); MULADD(at[1], at[25]); MULADD(at[2], at[24]); MULADD(at[3], at[23]); MULADD(at[4], at[22]); MULADD(at[5], at[21]); MULADD(at[6], at[20]); MULADD(at[7], at[19]); MULADD(at[8], at[18]); MULADD(at[9], at[17]); MULADD(at[10], at[16]); MULADD(at[11], at[15]); MULADD(at[12], at[14]); + COMBA_STORE(C->dp[12]); + /* 13 */ + COMBA_FORWARD; + MULADD(at[0], at[27]); MULADD(at[1], at[26]); MULADD(at[2], at[25]); MULADD(at[3], at[24]); MULADD(at[4], at[23]); MULADD(at[5], at[22]); MULADD(at[6], at[21]); MULADD(at[7], at[20]); MULADD(at[8], at[19]); MULADD(at[9], at[18]); MULADD(at[10], at[17]); MULADD(at[11], at[16]); MULADD(at[12], at[15]); MULADD(at[13], at[14]); + COMBA_STORE(C->dp[13]); + /* 14 */ + COMBA_FORWARD; + MULADD(at[1], at[27]); MULADD(at[2], at[26]); MULADD(at[3], at[25]); MULADD(at[4], at[24]); MULADD(at[5], at[23]); MULADD(at[6], at[22]); MULADD(at[7], at[21]); MULADD(at[8], at[20]); MULADD(at[9], at[19]); MULADD(at[10], at[18]); MULADD(at[11], at[17]); MULADD(at[12], at[16]); MULADD(at[13], at[15]); + COMBA_STORE(C->dp[14]); + /* 15 */ + COMBA_FORWARD; + MULADD(at[2], at[27]); MULADD(at[3], at[26]); MULADD(at[4], at[25]); MULADD(at[5], at[24]); MULADD(at[6], at[23]); MULADD(at[7], at[22]); MULADD(at[8], at[21]); MULADD(at[9], at[20]); MULADD(at[10], at[19]); MULADD(at[11], at[18]); MULADD(at[12], at[17]); MULADD(at[13], at[16]); + COMBA_STORE(C->dp[15]); + /* 16 */ + COMBA_FORWARD; + MULADD(at[3], at[27]); MULADD(at[4], at[26]); MULADD(at[5], at[25]); MULADD(at[6], at[24]); MULADD(at[7], at[23]); MULADD(at[8], at[22]); MULADD(at[9], at[21]); MULADD(at[10], at[20]); MULADD(at[11], at[19]); MULADD(at[12], at[18]); MULADD(at[13], at[17]); + COMBA_STORE(C->dp[16]); + /* 17 */ + COMBA_FORWARD; + MULADD(at[4], at[27]); MULADD(at[5], at[26]); MULADD(at[6], at[25]); MULADD(at[7], at[24]); MULADD(at[8], at[23]); MULADD(at[9], at[22]); MULADD(at[10], at[21]); MULADD(at[11], at[20]); MULADD(at[12], at[19]); MULADD(at[13], at[18]); + COMBA_STORE(C->dp[17]); + /* 18 */ + COMBA_FORWARD; + MULADD(at[5], at[27]); MULADD(at[6], at[26]); MULADD(at[7], at[25]); MULADD(at[8], at[24]); MULADD(at[9], at[23]); MULADD(at[10], at[22]); MULADD(at[11], at[21]); MULADD(at[12], at[20]); MULADD(at[13], at[19]); + COMBA_STORE(C->dp[18]); + /* 19 */ + COMBA_FORWARD; + MULADD(at[6], at[27]); MULADD(at[7], at[26]); MULADD(at[8], at[25]); MULADD(at[9], at[24]); MULADD(at[10], at[23]); MULADD(at[11], at[22]); MULADD(at[12], at[21]); MULADD(at[13], at[20]); + COMBA_STORE(C->dp[19]); + /* 20 */ + COMBA_FORWARD; + MULADD(at[7], at[27]); MULADD(at[8], at[26]); MULADD(at[9], at[25]); MULADD(at[10], at[24]); MULADD(at[11], at[23]); MULADD(at[12], at[22]); MULADD(at[13], at[21]); + COMBA_STORE(C->dp[20]); + /* 21 */ + COMBA_FORWARD; + MULADD(at[8], at[27]); MULADD(at[9], at[26]); MULADD(at[10], at[25]); MULADD(at[11], at[24]); MULADD(at[12], at[23]); MULADD(at[13], at[22]); + COMBA_STORE(C->dp[21]); + /* 22 */ + COMBA_FORWARD; + MULADD(at[9], at[27]); MULADD(at[10], at[26]); MULADD(at[11], at[25]); MULADD(at[12], at[24]); MULADD(at[13], at[23]); + COMBA_STORE(C->dp[22]); + /* 23 */ + COMBA_FORWARD; + MULADD(at[10], at[27]); MULADD(at[11], at[26]); MULADD(at[12], at[25]); MULADD(at[13], at[24]); + COMBA_STORE(C->dp[23]); + /* 24 */ + COMBA_FORWARD; + MULADD(at[11], at[27]); MULADD(at[12], at[26]); MULADD(at[13], at[25]); + COMBA_STORE(C->dp[24]); + /* 25 */ + COMBA_FORWARD; + MULADD(at[12], at[27]); MULADD(at[13], at[26]); + COMBA_STORE(C->dp[25]); + /* 26 */ + COMBA_FORWARD; + MULADD(at[13], at[27]); + COMBA_STORE(C->dp[26]); + COMBA_STORE2(C->dp[27]); + C->used = 28; + C->sign = A->sign ^ B->sign; + fp_clamp(C); + COMBA_FINI; + break; + + case 15: + XMEMCPY(at, A->dp, 15 * sizeof(fp_digit)); + XMEMCPY(at+15, B->dp, 15 * sizeof(fp_digit)); + COMBA_START; + + COMBA_CLEAR; + /* 0 */ + MULADD(at[0], at[15]); + COMBA_STORE(C->dp[0]); + /* 1 */ + COMBA_FORWARD; + MULADD(at[0], at[16]); MULADD(at[1], at[15]); + COMBA_STORE(C->dp[1]); + /* 2 */ + COMBA_FORWARD; + MULADD(at[0], at[17]); MULADD(at[1], at[16]); MULADD(at[2], at[15]); + COMBA_STORE(C->dp[2]); + /* 3 */ + COMBA_FORWARD; + MULADD(at[0], at[18]); MULADD(at[1], at[17]); MULADD(at[2], at[16]); MULADD(at[3], at[15]); + COMBA_STORE(C->dp[3]); + /* 4 */ + COMBA_FORWARD; + MULADD(at[0], at[19]); MULADD(at[1], at[18]); MULADD(at[2], at[17]); MULADD(at[3], at[16]); MULADD(at[4], at[15]); + COMBA_STORE(C->dp[4]); + /* 5 */ + COMBA_FORWARD; + MULADD(at[0], at[20]); MULADD(at[1], at[19]); MULADD(at[2], at[18]); MULADD(at[3], at[17]); MULADD(at[4], at[16]); MULADD(at[5], at[15]); + COMBA_STORE(C->dp[5]); + /* 6 */ + COMBA_FORWARD; + MULADD(at[0], at[21]); MULADD(at[1], at[20]); MULADD(at[2], at[19]); MULADD(at[3], at[18]); MULADD(at[4], at[17]); MULADD(at[5], at[16]); MULADD(at[6], at[15]); + COMBA_STORE(C->dp[6]); + /* 7 */ + COMBA_FORWARD; + MULADD(at[0], at[22]); MULADD(at[1], at[21]); MULADD(at[2], at[20]); MULADD(at[3], at[19]); MULADD(at[4], at[18]); MULADD(at[5], at[17]); MULADD(at[6], at[16]); MULADD(at[7], at[15]); + COMBA_STORE(C->dp[7]); + /* 8 */ + COMBA_FORWARD; + MULADD(at[0], at[23]); MULADD(at[1], at[22]); MULADD(at[2], at[21]); MULADD(at[3], at[20]); MULADD(at[4], at[19]); MULADD(at[5], at[18]); MULADD(at[6], at[17]); MULADD(at[7], at[16]); MULADD(at[8], at[15]); + COMBA_STORE(C->dp[8]); + /* 9 */ + COMBA_FORWARD; + MULADD(at[0], at[24]); MULADD(at[1], at[23]); MULADD(at[2], at[22]); MULADD(at[3], at[21]); MULADD(at[4], at[20]); MULADD(at[5], at[19]); MULADD(at[6], at[18]); MULADD(at[7], at[17]); MULADD(at[8], at[16]); MULADD(at[9], at[15]); + COMBA_STORE(C->dp[9]); + /* 10 */ + COMBA_FORWARD; + MULADD(at[0], at[25]); MULADD(at[1], at[24]); MULADD(at[2], at[23]); MULADD(at[3], at[22]); MULADD(at[4], at[21]); MULADD(at[5], at[20]); MULADD(at[6], at[19]); MULADD(at[7], at[18]); MULADD(at[8], at[17]); MULADD(at[9], at[16]); MULADD(at[10], at[15]); + COMBA_STORE(C->dp[10]); + /* 11 */ + COMBA_FORWARD; + MULADD(at[0], at[26]); MULADD(at[1], at[25]); MULADD(at[2], at[24]); MULADD(at[3], at[23]); MULADD(at[4], at[22]); MULADD(at[5], at[21]); MULADD(at[6], at[20]); MULADD(at[7], at[19]); MULADD(at[8], at[18]); MULADD(at[9], at[17]); MULADD(at[10], at[16]); MULADD(at[11], at[15]); + COMBA_STORE(C->dp[11]); + /* 12 */ + COMBA_FORWARD; + MULADD(at[0], at[27]); MULADD(at[1], at[26]); MULADD(at[2], at[25]); MULADD(at[3], at[24]); MULADD(at[4], at[23]); MULADD(at[5], at[22]); MULADD(at[6], at[21]); MULADD(at[7], at[20]); MULADD(at[8], at[19]); MULADD(at[9], at[18]); MULADD(at[10], at[17]); MULADD(at[11], at[16]); MULADD(at[12], at[15]); + COMBA_STORE(C->dp[12]); + /* 13 */ + COMBA_FORWARD; + MULADD(at[0], at[28]); MULADD(at[1], at[27]); MULADD(at[2], at[26]); MULADD(at[3], at[25]); MULADD(at[4], at[24]); MULADD(at[5], at[23]); MULADD(at[6], at[22]); MULADD(at[7], at[21]); MULADD(at[8], at[20]); MULADD(at[9], at[19]); MULADD(at[10], at[18]); MULADD(at[11], at[17]); MULADD(at[12], at[16]); MULADD(at[13], at[15]); + COMBA_STORE(C->dp[13]); + /* 14 */ + COMBA_FORWARD; + MULADD(at[0], at[29]); MULADD(at[1], at[28]); MULADD(at[2], at[27]); MULADD(at[3], at[26]); MULADD(at[4], at[25]); MULADD(at[5], at[24]); MULADD(at[6], at[23]); MULADD(at[7], at[22]); MULADD(at[8], at[21]); MULADD(at[9], at[20]); MULADD(at[10], at[19]); MULADD(at[11], at[18]); MULADD(at[12], at[17]); MULADD(at[13], at[16]); MULADD(at[14], at[15]); + COMBA_STORE(C->dp[14]); + /* 15 */ + COMBA_FORWARD; + MULADD(at[1], at[29]); MULADD(at[2], at[28]); MULADD(at[3], at[27]); MULADD(at[4], at[26]); MULADD(at[5], at[25]); MULADD(at[6], at[24]); MULADD(at[7], at[23]); MULADD(at[8], at[22]); MULADD(at[9], at[21]); MULADD(at[10], at[20]); MULADD(at[11], at[19]); MULADD(at[12], at[18]); MULADD(at[13], at[17]); MULADD(at[14], at[16]); + COMBA_STORE(C->dp[15]); + /* 16 */ + COMBA_FORWARD; + MULADD(at[2], at[29]); MULADD(at[3], at[28]); MULADD(at[4], at[27]); MULADD(at[5], at[26]); MULADD(at[6], at[25]); MULADD(at[7], at[24]); MULADD(at[8], at[23]); MULADD(at[9], at[22]); MULADD(at[10], at[21]); MULADD(at[11], at[20]); MULADD(at[12], at[19]); MULADD(at[13], at[18]); MULADD(at[14], at[17]); + COMBA_STORE(C->dp[16]); + /* 17 */ + COMBA_FORWARD; + MULADD(at[3], at[29]); MULADD(at[4], at[28]); MULADD(at[5], at[27]); MULADD(at[6], at[26]); MULADD(at[7], at[25]); MULADD(at[8], at[24]); MULADD(at[9], at[23]); MULADD(at[10], at[22]); MULADD(at[11], at[21]); MULADD(at[12], at[20]); MULADD(at[13], at[19]); MULADD(at[14], at[18]); + COMBA_STORE(C->dp[17]); + /* 18 */ + COMBA_FORWARD; + MULADD(at[4], at[29]); MULADD(at[5], at[28]); MULADD(at[6], at[27]); MULADD(at[7], at[26]); MULADD(at[8], at[25]); MULADD(at[9], at[24]); MULADD(at[10], at[23]); MULADD(at[11], at[22]); MULADD(at[12], at[21]); MULADD(at[13], at[20]); MULADD(at[14], at[19]); + COMBA_STORE(C->dp[18]); + /* 19 */ + COMBA_FORWARD; + MULADD(at[5], at[29]); MULADD(at[6], at[28]); MULADD(at[7], at[27]); MULADD(at[8], at[26]); MULADD(at[9], at[25]); MULADD(at[10], at[24]); MULADD(at[11], at[23]); MULADD(at[12], at[22]); MULADD(at[13], at[21]); MULADD(at[14], at[20]); + COMBA_STORE(C->dp[19]); + /* 20 */ + COMBA_FORWARD; + MULADD(at[6], at[29]); MULADD(at[7], at[28]); MULADD(at[8], at[27]); MULADD(at[9], at[26]); MULADD(at[10], at[25]); MULADD(at[11], at[24]); MULADD(at[12], at[23]); MULADD(at[13], at[22]); MULADD(at[14], at[21]); + COMBA_STORE(C->dp[20]); + /* 21 */ + COMBA_FORWARD; + MULADD(at[7], at[29]); MULADD(at[8], at[28]); MULADD(at[9], at[27]); MULADD(at[10], at[26]); MULADD(at[11], at[25]); MULADD(at[12], at[24]); MULADD(at[13], at[23]); MULADD(at[14], at[22]); + COMBA_STORE(C->dp[21]); + /* 22 */ + COMBA_FORWARD; + MULADD(at[8], at[29]); MULADD(at[9], at[28]); MULADD(at[10], at[27]); MULADD(at[11], at[26]); MULADD(at[12], at[25]); MULADD(at[13], at[24]); MULADD(at[14], at[23]); + COMBA_STORE(C->dp[22]); + /* 23 */ + COMBA_FORWARD; + MULADD(at[9], at[29]); MULADD(at[10], at[28]); MULADD(at[11], at[27]); MULADD(at[12], at[26]); MULADD(at[13], at[25]); MULADD(at[14], at[24]); + COMBA_STORE(C->dp[23]); + /* 24 */ + COMBA_FORWARD; + MULADD(at[10], at[29]); MULADD(at[11], at[28]); MULADD(at[12], at[27]); MULADD(at[13], at[26]); MULADD(at[14], at[25]); + COMBA_STORE(C->dp[24]); + /* 25 */ + COMBA_FORWARD; + MULADD(at[11], at[29]); MULADD(at[12], at[28]); MULADD(at[13], at[27]); MULADD(at[14], at[26]); + COMBA_STORE(C->dp[25]); + /* 26 */ + COMBA_FORWARD; + MULADD(at[12], at[29]); MULADD(at[13], at[28]); MULADD(at[14], at[27]); + COMBA_STORE(C->dp[26]); + /* 27 */ + COMBA_FORWARD; + MULADD(at[13], at[29]); MULADD(at[14], at[28]); + COMBA_STORE(C->dp[27]); + /* 28 */ + COMBA_FORWARD; + MULADD(at[14], at[29]); + COMBA_STORE(C->dp[28]); + COMBA_STORE2(C->dp[29]); + C->used = 30; + C->sign = A->sign ^ B->sign; + fp_clamp(C); + COMBA_FINI; + break; + + case 16: + XMEMCPY(at, A->dp, 16 * sizeof(fp_digit)); + XMEMCPY(at+16, B->dp, 16 * sizeof(fp_digit)); + COMBA_START; + + COMBA_CLEAR; + /* 0 */ + MULADD(at[0], at[16]); + COMBA_STORE(C->dp[0]); + /* 1 */ + COMBA_FORWARD; + MULADD(at[0], at[17]); MULADD(at[1], at[16]); + COMBA_STORE(C->dp[1]); + /* 2 */ + COMBA_FORWARD; + MULADD(at[0], at[18]); MULADD(at[1], at[17]); MULADD(at[2], at[16]); + COMBA_STORE(C->dp[2]); + /* 3 */ + COMBA_FORWARD; + MULADD(at[0], at[19]); MULADD(at[1], at[18]); MULADD(at[2], at[17]); MULADD(at[3], at[16]); + COMBA_STORE(C->dp[3]); + /* 4 */ + COMBA_FORWARD; + MULADD(at[0], at[20]); MULADD(at[1], at[19]); MULADD(at[2], at[18]); MULADD(at[3], at[17]); MULADD(at[4], at[16]); + COMBA_STORE(C->dp[4]); + /* 5 */ + COMBA_FORWARD; + MULADD(at[0], at[21]); MULADD(at[1], at[20]); MULADD(at[2], at[19]); MULADD(at[3], at[18]); MULADD(at[4], at[17]); MULADD(at[5], at[16]); + COMBA_STORE(C->dp[5]); + /* 6 */ + COMBA_FORWARD; + MULADD(at[0], at[22]); MULADD(at[1], at[21]); MULADD(at[2], at[20]); MULADD(at[3], at[19]); MULADD(at[4], at[18]); MULADD(at[5], at[17]); MULADD(at[6], at[16]); + COMBA_STORE(C->dp[6]); + /* 7 */ + COMBA_FORWARD; + MULADD(at[0], at[23]); MULADD(at[1], at[22]); MULADD(at[2], at[21]); MULADD(at[3], at[20]); MULADD(at[4], at[19]); MULADD(at[5], at[18]); MULADD(at[6], at[17]); MULADD(at[7], at[16]); + COMBA_STORE(C->dp[7]); + /* 8 */ + COMBA_FORWARD; + MULADD(at[0], at[24]); MULADD(at[1], at[23]); MULADD(at[2], at[22]); MULADD(at[3], at[21]); MULADD(at[4], at[20]); MULADD(at[5], at[19]); MULADD(at[6], at[18]); MULADD(at[7], at[17]); MULADD(at[8], at[16]); + COMBA_STORE(C->dp[8]); + /* 9 */ + COMBA_FORWARD; + MULADD(at[0], at[25]); MULADD(at[1], at[24]); MULADD(at[2], at[23]); MULADD(at[3], at[22]); MULADD(at[4], at[21]); MULADD(at[5], at[20]); MULADD(at[6], at[19]); MULADD(at[7], at[18]); MULADD(at[8], at[17]); MULADD(at[9], at[16]); + COMBA_STORE(C->dp[9]); + /* 10 */ + COMBA_FORWARD; + MULADD(at[0], at[26]); MULADD(at[1], at[25]); MULADD(at[2], at[24]); MULADD(at[3], at[23]); MULADD(at[4], at[22]); MULADD(at[5], at[21]); MULADD(at[6], at[20]); MULADD(at[7], at[19]); MULADD(at[8], at[18]); MULADD(at[9], at[17]); MULADD(at[10], at[16]); + COMBA_STORE(C->dp[10]); + /* 11 */ + COMBA_FORWARD; + MULADD(at[0], at[27]); MULADD(at[1], at[26]); MULADD(at[2], at[25]); MULADD(at[3], at[24]); MULADD(at[4], at[23]); MULADD(at[5], at[22]); MULADD(at[6], at[21]); MULADD(at[7], at[20]); MULADD(at[8], at[19]); MULADD(at[9], at[18]); MULADD(at[10], at[17]); MULADD(at[11], at[16]); + COMBA_STORE(C->dp[11]); + /* 12 */ + COMBA_FORWARD; + MULADD(at[0], at[28]); MULADD(at[1], at[27]); MULADD(at[2], at[26]); MULADD(at[3], at[25]); MULADD(at[4], at[24]); MULADD(at[5], at[23]); MULADD(at[6], at[22]); MULADD(at[7], at[21]); MULADD(at[8], at[20]); MULADD(at[9], at[19]); MULADD(at[10], at[18]); MULADD(at[11], at[17]); MULADD(at[12], at[16]); + COMBA_STORE(C->dp[12]); + /* 13 */ + COMBA_FORWARD; + MULADD(at[0], at[29]); MULADD(at[1], at[28]); MULADD(at[2], at[27]); MULADD(at[3], at[26]); MULADD(at[4], at[25]); MULADD(at[5], at[24]); MULADD(at[6], at[23]); MULADD(at[7], at[22]); MULADD(at[8], at[21]); MULADD(at[9], at[20]); MULADD(at[10], at[19]); MULADD(at[11], at[18]); MULADD(at[12], at[17]); MULADD(at[13], at[16]); + COMBA_STORE(C->dp[13]); + /* 14 */ + COMBA_FORWARD; + MULADD(at[0], at[30]); MULADD(at[1], at[29]); MULADD(at[2], at[28]); MULADD(at[3], at[27]); MULADD(at[4], at[26]); MULADD(at[5], at[25]); MULADD(at[6], at[24]); MULADD(at[7], at[23]); MULADD(at[8], at[22]); MULADD(at[9], at[21]); MULADD(at[10], at[20]); MULADD(at[11], at[19]); MULADD(at[12], at[18]); MULADD(at[13], at[17]); MULADD(at[14], at[16]); + COMBA_STORE(C->dp[14]); + /* 15 */ + COMBA_FORWARD; + MULADD(at[0], at[31]); MULADD(at[1], at[30]); MULADD(at[2], at[29]); MULADD(at[3], at[28]); MULADD(at[4], at[27]); MULADD(at[5], at[26]); MULADD(at[6], at[25]); MULADD(at[7], at[24]); MULADD(at[8], at[23]); MULADD(at[9], at[22]); MULADD(at[10], at[21]); MULADD(at[11], at[20]); MULADD(at[12], at[19]); MULADD(at[13], at[18]); MULADD(at[14], at[17]); MULADD(at[15], at[16]); + COMBA_STORE(C->dp[15]); + /* 16 */ + COMBA_FORWARD; + MULADD(at[1], at[31]); MULADD(at[2], at[30]); MULADD(at[3], at[29]); MULADD(at[4], at[28]); MULADD(at[5], at[27]); MULADD(at[6], at[26]); MULADD(at[7], at[25]); MULADD(at[8], at[24]); MULADD(at[9], at[23]); MULADD(at[10], at[22]); MULADD(at[11], at[21]); MULADD(at[12], at[20]); MULADD(at[13], at[19]); MULADD(at[14], at[18]); MULADD(at[15], at[17]); + COMBA_STORE(C->dp[16]); + /* 17 */ + COMBA_FORWARD; + MULADD(at[2], at[31]); MULADD(at[3], at[30]); MULADD(at[4], at[29]); MULADD(at[5], at[28]); MULADD(at[6], at[27]); MULADD(at[7], at[26]); MULADD(at[8], at[25]); MULADD(at[9], at[24]); MULADD(at[10], at[23]); MULADD(at[11], at[22]); MULADD(at[12], at[21]); MULADD(at[13], at[20]); MULADD(at[14], at[19]); MULADD(at[15], at[18]); + COMBA_STORE(C->dp[17]); + /* 18 */ + COMBA_FORWARD; + MULADD(at[3], at[31]); MULADD(at[4], at[30]); MULADD(at[5], at[29]); MULADD(at[6], at[28]); MULADD(at[7], at[27]); MULADD(at[8], at[26]); MULADD(at[9], at[25]); MULADD(at[10], at[24]); MULADD(at[11], at[23]); MULADD(at[12], at[22]); MULADD(at[13], at[21]); MULADD(at[14], at[20]); MULADD(at[15], at[19]); + COMBA_STORE(C->dp[18]); + /* 19 */ + COMBA_FORWARD; + MULADD(at[4], at[31]); MULADD(at[5], at[30]); MULADD(at[6], at[29]); MULADD(at[7], at[28]); MULADD(at[8], at[27]); MULADD(at[9], at[26]); MULADD(at[10], at[25]); MULADD(at[11], at[24]); MULADD(at[12], at[23]); MULADD(at[13], at[22]); MULADD(at[14], at[21]); MULADD(at[15], at[20]); + COMBA_STORE(C->dp[19]); + /* 20 */ + COMBA_FORWARD; + MULADD(at[5], at[31]); MULADD(at[6], at[30]); MULADD(at[7], at[29]); MULADD(at[8], at[28]); MULADD(at[9], at[27]); MULADD(at[10], at[26]); MULADD(at[11], at[25]); MULADD(at[12], at[24]); MULADD(at[13], at[23]); MULADD(at[14], at[22]); MULADD(at[15], at[21]); + COMBA_STORE(C->dp[20]); + /* 21 */ + COMBA_FORWARD; + MULADD(at[6], at[31]); MULADD(at[7], at[30]); MULADD(at[8], at[29]); MULADD(at[9], at[28]); MULADD(at[10], at[27]); MULADD(at[11], at[26]); MULADD(at[12], at[25]); MULADD(at[13], at[24]); MULADD(at[14], at[23]); MULADD(at[15], at[22]); + COMBA_STORE(C->dp[21]); + /* 22 */ + COMBA_FORWARD; + MULADD(at[7], at[31]); MULADD(at[8], at[30]); MULADD(at[9], at[29]); MULADD(at[10], at[28]); MULADD(at[11], at[27]); MULADD(at[12], at[26]); MULADD(at[13], at[25]); MULADD(at[14], at[24]); MULADD(at[15], at[23]); + COMBA_STORE(C->dp[22]); + /* 23 */ + COMBA_FORWARD; + MULADD(at[8], at[31]); MULADD(at[9], at[30]); MULADD(at[10], at[29]); MULADD(at[11], at[28]); MULADD(at[12], at[27]); MULADD(at[13], at[26]); MULADD(at[14], at[25]); MULADD(at[15], at[24]); + COMBA_STORE(C->dp[23]); + /* 24 */ + COMBA_FORWARD; + MULADD(at[9], at[31]); MULADD(at[10], at[30]); MULADD(at[11], at[29]); MULADD(at[12], at[28]); MULADD(at[13], at[27]); MULADD(at[14], at[26]); MULADD(at[15], at[25]); + COMBA_STORE(C->dp[24]); + /* 25 */ + COMBA_FORWARD; + MULADD(at[10], at[31]); MULADD(at[11], at[30]); MULADD(at[12], at[29]); MULADD(at[13], at[28]); MULADD(at[14], at[27]); MULADD(at[15], at[26]); + COMBA_STORE(C->dp[25]); + /* 26 */ + COMBA_FORWARD; + MULADD(at[11], at[31]); MULADD(at[12], at[30]); MULADD(at[13], at[29]); MULADD(at[14], at[28]); MULADD(at[15], at[27]); + COMBA_STORE(C->dp[26]); + /* 27 */ + COMBA_FORWARD; + MULADD(at[12], at[31]); MULADD(at[13], at[30]); MULADD(at[14], at[29]); MULADD(at[15], at[28]); + COMBA_STORE(C->dp[27]); + /* 28 */ + COMBA_FORWARD; + MULADD(at[13], at[31]); MULADD(at[14], at[30]); MULADD(at[15], at[29]); + COMBA_STORE(C->dp[28]); + /* 29 */ + COMBA_FORWARD; + MULADD(at[14], at[31]); MULADD(at[15], at[30]); + COMBA_STORE(C->dp[29]); + /* 30 */ + COMBA_FORWARD; + MULADD(at[15], at[31]); + COMBA_STORE(C->dp[30]); + COMBA_STORE2(C->dp[31]); + C->used = 32; + C->sign = A->sign ^ B->sign; + fp_clamp(C); + COMBA_FINI; + break; + + default: + break; + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(at, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; +} + +#endif diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_sqr_comba_12.i b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_sqr_comba_12.i new file mode 100755 index 0000000..82fa9fc --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_sqr_comba_12.i @@ -0,0 +1,177 @@ +/* fp_sqr_comba_12.i + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifdef TFM_SQR12 +int fp_sqr_comba12(fp_int *A, fp_int *B) +{ + fp_digit *a, c0, c1, c2, sc0 = 0, sc1 = 0, sc2 = 0; +#ifdef TFM_ISO + fp_word tt; +#endif +#ifndef WOLFSSL_SMALL_STACK + fp_digit b[24]; +#else + fp_digit *b; +#endif + +#ifdef WOLFSSL_SMALL_STACK + b = (fp_digit*)XMALLOC(sizeof(fp_digit) * 24, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (b == NULL) + return FP_MEM; +#endif + + a = A->dp; + COMBA_START; + + /* clear carries */ + CLEAR_CARRY; + + /* output 0 */ + SQRADD(a[0],a[0]); + COMBA_STORE(b[0]); + + /* output 1 */ + CARRY_FORWARD; + SQRADD2(a[0], a[1]); + COMBA_STORE(b[1]); + + /* output 2 */ + CARRY_FORWARD; + SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]); + COMBA_STORE(b[2]); + + /* output 3 */ + CARRY_FORWARD; + SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]); + COMBA_STORE(b[3]); + + /* output 4 */ + CARRY_FORWARD; + SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]); + COMBA_STORE(b[4]); + + /* output 5 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB; + COMBA_STORE(b[5]); + + /* output 6 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]); + COMBA_STORE(b[6]); + + /* output 7 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[7]); SQRADDAC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB; + COMBA_STORE(b[7]); + + /* output 8 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[8]); SQRADDAC(a[1], a[7]); SQRADDAC(a[2], a[6]); SQRADDAC(a[3], a[5]); SQRADDDB; SQRADD(a[4], a[4]); + COMBA_STORE(b[8]); + + /* output 9 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[9]); SQRADDAC(a[1], a[8]); SQRADDAC(a[2], a[7]); SQRADDAC(a[3], a[6]); SQRADDAC(a[4], a[5]); SQRADDDB; + COMBA_STORE(b[9]); + + /* output 10 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[10]); SQRADDAC(a[1], a[9]); SQRADDAC(a[2], a[8]); SQRADDAC(a[3], a[7]); SQRADDAC(a[4], a[6]); SQRADDDB; SQRADD(a[5], a[5]); + COMBA_STORE(b[10]); + + /* output 11 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[11]); SQRADDAC(a[1], a[10]); SQRADDAC(a[2], a[9]); SQRADDAC(a[3], a[8]); SQRADDAC(a[4], a[7]); SQRADDAC(a[5], a[6]); SQRADDDB; + COMBA_STORE(b[11]); + + /* output 12 */ + CARRY_FORWARD; + SQRADDSC(a[1], a[11]); SQRADDAC(a[2], a[10]); SQRADDAC(a[3], a[9]); SQRADDAC(a[4], a[8]); SQRADDAC(a[5], a[7]); SQRADDDB; SQRADD(a[6], a[6]); + COMBA_STORE(b[12]); + + /* output 13 */ + CARRY_FORWARD; + SQRADDSC(a[2], a[11]); SQRADDAC(a[3], a[10]); SQRADDAC(a[4], a[9]); SQRADDAC(a[5], a[8]); SQRADDAC(a[6], a[7]); SQRADDDB; + COMBA_STORE(b[13]); + + /* output 14 */ + CARRY_FORWARD; + SQRADDSC(a[3], a[11]); SQRADDAC(a[4], a[10]); SQRADDAC(a[5], a[9]); SQRADDAC(a[6], a[8]); SQRADDDB; SQRADD(a[7], a[7]); + COMBA_STORE(b[14]); + + /* output 15 */ + CARRY_FORWARD; + SQRADDSC(a[4], a[11]); SQRADDAC(a[5], a[10]); SQRADDAC(a[6], a[9]); SQRADDAC(a[7], a[8]); SQRADDDB; + COMBA_STORE(b[15]); + + /* output 16 */ + CARRY_FORWARD; + SQRADDSC(a[5], a[11]); SQRADDAC(a[6], a[10]); SQRADDAC(a[7], a[9]); SQRADDDB; SQRADD(a[8], a[8]); + COMBA_STORE(b[16]); + + /* output 17 */ + CARRY_FORWARD; + SQRADDSC(a[6], a[11]); SQRADDAC(a[7], a[10]); SQRADDAC(a[8], a[9]); SQRADDDB; + COMBA_STORE(b[17]); + + /* output 18 */ + CARRY_FORWARD; + SQRADD2(a[7], a[11]); SQRADD2(a[8], a[10]); SQRADD(a[9], a[9]); + COMBA_STORE(b[18]); + + /* output 19 */ + CARRY_FORWARD; + SQRADD2(a[8], a[11]); SQRADD2(a[9], a[10]); + COMBA_STORE(b[19]); + + /* output 20 */ + CARRY_FORWARD; + SQRADD2(a[9], a[11]); SQRADD(a[10], a[10]); + COMBA_STORE(b[20]); + + /* output 21 */ + CARRY_FORWARD; + SQRADD2(a[10], a[11]); + COMBA_STORE(b[21]); + + /* output 22 */ + CARRY_FORWARD; + SQRADD(a[11], a[11]); + COMBA_STORE(b[22]); + COMBA_STORE2(b[23]); + COMBA_FINI; + + B->used = 24; + B->sign = FP_ZPOS; + XMEMCPY(B->dp, b, 24 * sizeof(fp_digit)); + fp_clamp(B); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; +} +#endif + + diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_sqr_comba_17.i b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_sqr_comba_17.i new file mode 100755 index 0000000..6827867 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_sqr_comba_17.i @@ -0,0 +1,227 @@ +/* fp_sqr_comba_17.i + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifdef TFM_SQR17 +int fp_sqr_comba17(fp_int *A, fp_int *B) +{ + fp_digit *a, c0, c1, c2, sc0 = 0, sc1 = 0, sc2 = 0; +#ifdef TFM_ISO + fp_word tt; +#endif +#ifndef WOLFSSL_SMALL_STACK + fp_digit b[34]; +#else + fp_digit *b; +#endif + +#ifdef WOLFSSL_SMALL_STACK + b = (fp_digit*)XMALLOC(sizeof(fp_digit) * 34, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (b == NULL) + return FP_MEM; +#endif + + a = A->dp; + COMBA_START; + + /* clear carries */ + CLEAR_CARRY; + + /* output 0 */ + SQRADD(a[0],a[0]); + COMBA_STORE(b[0]); + + /* output 1 */ + CARRY_FORWARD; + SQRADD2(a[0], a[1]); + COMBA_STORE(b[1]); + + /* output 2 */ + CARRY_FORWARD; + SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]); + COMBA_STORE(b[2]); + + /* output 3 */ + CARRY_FORWARD; + SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]); + COMBA_STORE(b[3]); + + /* output 4 */ + CARRY_FORWARD; + SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]); + COMBA_STORE(b[4]); + + /* output 5 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB; + COMBA_STORE(b[5]); + + /* output 6 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]); + COMBA_STORE(b[6]); + + /* output 7 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[7]); SQRADDAC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB; + COMBA_STORE(b[7]); + + /* output 8 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[8]); SQRADDAC(a[1], a[7]); SQRADDAC(a[2], a[6]); SQRADDAC(a[3], a[5]); SQRADDDB; SQRADD(a[4], a[4]); + COMBA_STORE(b[8]); + + /* output 9 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[9]); SQRADDAC(a[1], a[8]); SQRADDAC(a[2], a[7]); SQRADDAC(a[3], a[6]); SQRADDAC(a[4], a[5]); SQRADDDB; + COMBA_STORE(b[9]); + + /* output 10 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[10]); SQRADDAC(a[1], a[9]); SQRADDAC(a[2], a[8]); SQRADDAC(a[3], a[7]); SQRADDAC(a[4], a[6]); SQRADDDB; SQRADD(a[5], a[5]); + COMBA_STORE(b[10]); + + /* output 11 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[11]); SQRADDAC(a[1], a[10]); SQRADDAC(a[2], a[9]); SQRADDAC(a[3], a[8]); SQRADDAC(a[4], a[7]); SQRADDAC(a[5], a[6]); SQRADDDB; + COMBA_STORE(b[11]); + + /* output 12 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[12]); SQRADDAC(a[1], a[11]); SQRADDAC(a[2], a[10]); SQRADDAC(a[3], a[9]); SQRADDAC(a[4], a[8]); SQRADDAC(a[5], a[7]); SQRADDDB; SQRADD(a[6], a[6]); + COMBA_STORE(b[12]); + + /* output 13 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[13]); SQRADDAC(a[1], a[12]); SQRADDAC(a[2], a[11]); SQRADDAC(a[3], a[10]); SQRADDAC(a[4], a[9]); SQRADDAC(a[5], a[8]); SQRADDAC(a[6], a[7]); SQRADDDB; + COMBA_STORE(b[13]); + + /* output 14 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[14]); SQRADDAC(a[1], a[13]); SQRADDAC(a[2], a[12]); SQRADDAC(a[3], a[11]); SQRADDAC(a[4], a[10]); SQRADDAC(a[5], a[9]); SQRADDAC(a[6], a[8]); SQRADDDB; SQRADD(a[7], a[7]); + COMBA_STORE(b[14]); + + /* output 15 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[15]); SQRADDAC(a[1], a[14]); SQRADDAC(a[2], a[13]); SQRADDAC(a[3], a[12]); SQRADDAC(a[4], a[11]); SQRADDAC(a[5], a[10]); SQRADDAC(a[6], a[9]); SQRADDAC(a[7], a[8]); SQRADDDB; + COMBA_STORE(b[15]); + + /* output 16 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[16]); SQRADDAC(a[1], a[15]); SQRADDAC(a[2], a[14]); SQRADDAC(a[3], a[13]); SQRADDAC(a[4], a[12]); SQRADDAC(a[5], a[11]); SQRADDAC(a[6], a[10]); SQRADDAC(a[7], a[9]); SQRADDDB; SQRADD(a[8], a[8]); + COMBA_STORE(b[16]); + + /* output 17 */ + CARRY_FORWARD; + SQRADDSC(a[1], a[16]); SQRADDAC(a[2], a[15]); SQRADDAC(a[3], a[14]); SQRADDAC(a[4], a[13]); SQRADDAC(a[5], a[12]); SQRADDAC(a[6], a[11]); SQRADDAC(a[7], a[10]); SQRADDAC(a[8], a[9]); SQRADDDB; + COMBA_STORE(b[17]); + + /* output 18 */ + CARRY_FORWARD; + SQRADDSC(a[2], a[16]); SQRADDAC(a[3], a[15]); SQRADDAC(a[4], a[14]); SQRADDAC(a[5], a[13]); SQRADDAC(a[6], a[12]); SQRADDAC(a[7], a[11]); SQRADDAC(a[8], a[10]); SQRADDDB; SQRADD(a[9], a[9]); + COMBA_STORE(b[18]); + + /* output 19 */ + CARRY_FORWARD; + SQRADDSC(a[3], a[16]); SQRADDAC(a[4], a[15]); SQRADDAC(a[5], a[14]); SQRADDAC(a[6], a[13]); SQRADDAC(a[7], a[12]); SQRADDAC(a[8], a[11]); SQRADDAC(a[9], a[10]); SQRADDDB; + COMBA_STORE(b[19]); + + /* output 20 */ + CARRY_FORWARD; + SQRADDSC(a[4], a[16]); SQRADDAC(a[5], a[15]); SQRADDAC(a[6], a[14]); SQRADDAC(a[7], a[13]); SQRADDAC(a[8], a[12]); SQRADDAC(a[9], a[11]); SQRADDDB; SQRADD(a[10], a[10]); + COMBA_STORE(b[20]); + + /* output 21 */ + CARRY_FORWARD; + SQRADDSC(a[5], a[16]); SQRADDAC(a[6], a[15]); SQRADDAC(a[7], a[14]); SQRADDAC(a[8], a[13]); SQRADDAC(a[9], a[12]); SQRADDAC(a[10], a[11]); SQRADDDB; + COMBA_STORE(b[21]); + + /* output 22 */ + CARRY_FORWARD; + SQRADDSC(a[6], a[16]); SQRADDAC(a[7], a[15]); SQRADDAC(a[8], a[14]); SQRADDAC(a[9], a[13]); SQRADDAC(a[10], a[12]); SQRADDDB; SQRADD(a[11], a[11]); + COMBA_STORE(b[22]); + + /* output 23 */ + CARRY_FORWARD; + SQRADDSC(a[7], a[16]); SQRADDAC(a[8], a[15]); SQRADDAC(a[9], a[14]); SQRADDAC(a[10], a[13]); SQRADDAC(a[11], a[12]); SQRADDDB; + COMBA_STORE(b[23]); + + /* output 24 */ + CARRY_FORWARD; + SQRADDSC(a[8], a[16]); SQRADDAC(a[9], a[15]); SQRADDAC(a[10], a[14]); SQRADDAC(a[11], a[13]); SQRADDDB; SQRADD(a[12], a[12]); + COMBA_STORE(b[24]); + + /* output 25 */ + CARRY_FORWARD; + SQRADDSC(a[9], a[16]); SQRADDAC(a[10], a[15]); SQRADDAC(a[11], a[14]); SQRADDAC(a[12], a[13]); SQRADDDB; + COMBA_STORE(b[25]); + + /* output 26 */ + CARRY_FORWARD; + SQRADDSC(a[10], a[16]); SQRADDAC(a[11], a[15]); SQRADDAC(a[12], a[14]); SQRADDDB; SQRADD(a[13], a[13]); + COMBA_STORE(b[26]); + + /* output 27 */ + CARRY_FORWARD; + SQRADDSC(a[11], a[16]); SQRADDAC(a[12], a[15]); SQRADDAC(a[13], a[14]); SQRADDDB; + COMBA_STORE(b[27]); + + /* output 28 */ + CARRY_FORWARD; + SQRADD2(a[12], a[16]); SQRADD2(a[13], a[15]); SQRADD(a[14], a[14]); + COMBA_STORE(b[28]); + + /* output 29 */ + CARRY_FORWARD; + SQRADD2(a[13], a[16]); SQRADD2(a[14], a[15]); + COMBA_STORE(b[29]); + + /* output 30 */ + CARRY_FORWARD; + SQRADD2(a[14], a[16]); SQRADD(a[15], a[15]); + COMBA_STORE(b[30]); + + /* output 31 */ + CARRY_FORWARD; + SQRADD2(a[15], a[16]); + COMBA_STORE(b[31]); + + /* output 32 */ + CARRY_FORWARD; + SQRADD(a[16], a[16]); + COMBA_STORE(b[32]); + COMBA_STORE2(b[33]); + COMBA_FINI; + + B->used = 34; + B->sign = FP_ZPOS; + XMEMCPY(B->dp, b, 34 * sizeof(fp_digit)); + fp_clamp(B); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; +} +#endif + + diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_sqr_comba_20.i b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_sqr_comba_20.i new file mode 100755 index 0000000..e226bef --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_sqr_comba_20.i @@ -0,0 +1,257 @@ +/* fp_sqr_comba_20.i + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifdef TFM_SQR20 +int fp_sqr_comba20(fp_int *A, fp_int *B) +{ + fp_digit *a, c0, c1, c2, sc0 = 0, sc1 = 0, sc2 = 0; +#ifdef TFM_ISO + fp_word tt; +#endif +#ifndef WOLFSSL_SMALL_STACK + fp_digit b[40]; +#else + fp_digit *b; +#endif + +#ifdef WOLFSSL_SMALL_STACK + b = (fp_digit*)XMALLOC(sizeof(fp_digit) * 40, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (b == NULL) + return FP_MEM; +#endif + + a = A->dp; + COMBA_START; + + /* clear carries */ + CLEAR_CARRY; + + /* output 0 */ + SQRADD(a[0],a[0]); + COMBA_STORE(b[0]); + + /* output 1 */ + CARRY_FORWARD; + SQRADD2(a[0], a[1]); + COMBA_STORE(b[1]); + + /* output 2 */ + CARRY_FORWARD; + SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]); + COMBA_STORE(b[2]); + + /* output 3 */ + CARRY_FORWARD; + SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]); + COMBA_STORE(b[3]); + + /* output 4 */ + CARRY_FORWARD; + SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]); + COMBA_STORE(b[4]); + + /* output 5 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB; + COMBA_STORE(b[5]); + + /* output 6 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]); + COMBA_STORE(b[6]); + + /* output 7 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[7]); SQRADDAC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB; + COMBA_STORE(b[7]); + + /* output 8 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[8]); SQRADDAC(a[1], a[7]); SQRADDAC(a[2], a[6]); SQRADDAC(a[3], a[5]); SQRADDDB; SQRADD(a[4], a[4]); + COMBA_STORE(b[8]); + + /* output 9 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[9]); SQRADDAC(a[1], a[8]); SQRADDAC(a[2], a[7]); SQRADDAC(a[3], a[6]); SQRADDAC(a[4], a[5]); SQRADDDB; + COMBA_STORE(b[9]); + + /* output 10 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[10]); SQRADDAC(a[1], a[9]); SQRADDAC(a[2], a[8]); SQRADDAC(a[3], a[7]); SQRADDAC(a[4], a[6]); SQRADDDB; SQRADD(a[5], a[5]); + COMBA_STORE(b[10]); + + /* output 11 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[11]); SQRADDAC(a[1], a[10]); SQRADDAC(a[2], a[9]); SQRADDAC(a[3], a[8]); SQRADDAC(a[4], a[7]); SQRADDAC(a[5], a[6]); SQRADDDB; + COMBA_STORE(b[11]); + + /* output 12 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[12]); SQRADDAC(a[1], a[11]); SQRADDAC(a[2], a[10]); SQRADDAC(a[3], a[9]); SQRADDAC(a[4], a[8]); SQRADDAC(a[5], a[7]); SQRADDDB; SQRADD(a[6], a[6]); + COMBA_STORE(b[12]); + + /* output 13 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[13]); SQRADDAC(a[1], a[12]); SQRADDAC(a[2], a[11]); SQRADDAC(a[3], a[10]); SQRADDAC(a[4], a[9]); SQRADDAC(a[5], a[8]); SQRADDAC(a[6], a[7]); SQRADDDB; + COMBA_STORE(b[13]); + + /* output 14 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[14]); SQRADDAC(a[1], a[13]); SQRADDAC(a[2], a[12]); SQRADDAC(a[3], a[11]); SQRADDAC(a[4], a[10]); SQRADDAC(a[5], a[9]); SQRADDAC(a[6], a[8]); SQRADDDB; SQRADD(a[7], a[7]); + COMBA_STORE(b[14]); + + /* output 15 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[15]); SQRADDAC(a[1], a[14]); SQRADDAC(a[2], a[13]); SQRADDAC(a[3], a[12]); SQRADDAC(a[4], a[11]); SQRADDAC(a[5], a[10]); SQRADDAC(a[6], a[9]); SQRADDAC(a[7], a[8]); SQRADDDB; + COMBA_STORE(b[15]); + + /* output 16 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[16]); SQRADDAC(a[1], a[15]); SQRADDAC(a[2], a[14]); SQRADDAC(a[3], a[13]); SQRADDAC(a[4], a[12]); SQRADDAC(a[5], a[11]); SQRADDAC(a[6], a[10]); SQRADDAC(a[7], a[9]); SQRADDDB; SQRADD(a[8], a[8]); + COMBA_STORE(b[16]); + + /* output 17 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[17]); SQRADDAC(a[1], a[16]); SQRADDAC(a[2], a[15]); SQRADDAC(a[3], a[14]); SQRADDAC(a[4], a[13]); SQRADDAC(a[5], a[12]); SQRADDAC(a[6], a[11]); SQRADDAC(a[7], a[10]); SQRADDAC(a[8], a[9]); SQRADDDB; + COMBA_STORE(b[17]); + + /* output 18 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[18]); SQRADDAC(a[1], a[17]); SQRADDAC(a[2], a[16]); SQRADDAC(a[3], a[15]); SQRADDAC(a[4], a[14]); SQRADDAC(a[5], a[13]); SQRADDAC(a[6], a[12]); SQRADDAC(a[7], a[11]); SQRADDAC(a[8], a[10]); SQRADDDB; SQRADD(a[9], a[9]); + COMBA_STORE(b[18]); + + /* output 19 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[19]); SQRADDAC(a[1], a[18]); SQRADDAC(a[2], a[17]); SQRADDAC(a[3], a[16]); SQRADDAC(a[4], a[15]); SQRADDAC(a[5], a[14]); SQRADDAC(a[6], a[13]); SQRADDAC(a[7], a[12]); SQRADDAC(a[8], a[11]); SQRADDAC(a[9], a[10]); SQRADDDB; + COMBA_STORE(b[19]); + + /* output 20 */ + CARRY_FORWARD; + SQRADDSC(a[1], a[19]); SQRADDAC(a[2], a[18]); SQRADDAC(a[3], a[17]); SQRADDAC(a[4], a[16]); SQRADDAC(a[5], a[15]); SQRADDAC(a[6], a[14]); SQRADDAC(a[7], a[13]); SQRADDAC(a[8], a[12]); SQRADDAC(a[9], a[11]); SQRADDDB; SQRADD(a[10], a[10]); + COMBA_STORE(b[20]); + + /* output 21 */ + CARRY_FORWARD; + SQRADDSC(a[2], a[19]); SQRADDAC(a[3], a[18]); SQRADDAC(a[4], a[17]); SQRADDAC(a[5], a[16]); SQRADDAC(a[6], a[15]); SQRADDAC(a[7], a[14]); SQRADDAC(a[8], a[13]); SQRADDAC(a[9], a[12]); SQRADDAC(a[10], a[11]); SQRADDDB; + COMBA_STORE(b[21]); + + /* output 22 */ + CARRY_FORWARD; + SQRADDSC(a[3], a[19]); SQRADDAC(a[4], a[18]); SQRADDAC(a[5], a[17]); SQRADDAC(a[6], a[16]); SQRADDAC(a[7], a[15]); SQRADDAC(a[8], a[14]); SQRADDAC(a[9], a[13]); SQRADDAC(a[10], a[12]); SQRADDDB; SQRADD(a[11], a[11]); + COMBA_STORE(b[22]); + + /* output 23 */ + CARRY_FORWARD; + SQRADDSC(a[4], a[19]); SQRADDAC(a[5], a[18]); SQRADDAC(a[6], a[17]); SQRADDAC(a[7], a[16]); SQRADDAC(a[8], a[15]); SQRADDAC(a[9], a[14]); SQRADDAC(a[10], a[13]); SQRADDAC(a[11], a[12]); SQRADDDB; + COMBA_STORE(b[23]); + + /* output 24 */ + CARRY_FORWARD; + SQRADDSC(a[5], a[19]); SQRADDAC(a[6], a[18]); SQRADDAC(a[7], a[17]); SQRADDAC(a[8], a[16]); SQRADDAC(a[9], a[15]); SQRADDAC(a[10], a[14]); SQRADDAC(a[11], a[13]); SQRADDDB; SQRADD(a[12], a[12]); + COMBA_STORE(b[24]); + + /* output 25 */ + CARRY_FORWARD; + SQRADDSC(a[6], a[19]); SQRADDAC(a[7], a[18]); SQRADDAC(a[8], a[17]); SQRADDAC(a[9], a[16]); SQRADDAC(a[10], a[15]); SQRADDAC(a[11], a[14]); SQRADDAC(a[12], a[13]); SQRADDDB; + COMBA_STORE(b[25]); + + /* output 26 */ + CARRY_FORWARD; + SQRADDSC(a[7], a[19]); SQRADDAC(a[8], a[18]); SQRADDAC(a[9], a[17]); SQRADDAC(a[10], a[16]); SQRADDAC(a[11], a[15]); SQRADDAC(a[12], a[14]); SQRADDDB; SQRADD(a[13], a[13]); + COMBA_STORE(b[26]); + + /* output 27 */ + CARRY_FORWARD; + SQRADDSC(a[8], a[19]); SQRADDAC(a[9], a[18]); SQRADDAC(a[10], a[17]); SQRADDAC(a[11], a[16]); SQRADDAC(a[12], a[15]); SQRADDAC(a[13], a[14]); SQRADDDB; + COMBA_STORE(b[27]); + + /* output 28 */ + CARRY_FORWARD; + SQRADDSC(a[9], a[19]); SQRADDAC(a[10], a[18]); SQRADDAC(a[11], a[17]); SQRADDAC(a[12], a[16]); SQRADDAC(a[13], a[15]); SQRADDDB; SQRADD(a[14], a[14]); + COMBA_STORE(b[28]); + + /* output 29 */ + CARRY_FORWARD; + SQRADDSC(a[10], a[19]); SQRADDAC(a[11], a[18]); SQRADDAC(a[12], a[17]); SQRADDAC(a[13], a[16]); SQRADDAC(a[14], a[15]); SQRADDDB; + COMBA_STORE(b[29]); + + /* output 30 */ + CARRY_FORWARD; + SQRADDSC(a[11], a[19]); SQRADDAC(a[12], a[18]); SQRADDAC(a[13], a[17]); SQRADDAC(a[14], a[16]); SQRADDDB; SQRADD(a[15], a[15]); + COMBA_STORE(b[30]); + + /* output 31 */ + CARRY_FORWARD; + SQRADDSC(a[12], a[19]); SQRADDAC(a[13], a[18]); SQRADDAC(a[14], a[17]); SQRADDAC(a[15], a[16]); SQRADDDB; + COMBA_STORE(b[31]); + + /* output 32 */ + CARRY_FORWARD; + SQRADDSC(a[13], a[19]); SQRADDAC(a[14], a[18]); SQRADDAC(a[15], a[17]); SQRADDDB; SQRADD(a[16], a[16]); + COMBA_STORE(b[32]); + + /* output 33 */ + CARRY_FORWARD; + SQRADDSC(a[14], a[19]); SQRADDAC(a[15], a[18]); SQRADDAC(a[16], a[17]); SQRADDDB; + COMBA_STORE(b[33]); + + /* output 34 */ + CARRY_FORWARD; + SQRADD2(a[15], a[19]); SQRADD2(a[16], a[18]); SQRADD(a[17], a[17]); + COMBA_STORE(b[34]); + + /* output 35 */ + CARRY_FORWARD; + SQRADD2(a[16], a[19]); SQRADD2(a[17], a[18]); + COMBA_STORE(b[35]); + + /* output 36 */ + CARRY_FORWARD; + SQRADD2(a[17], a[19]); SQRADD(a[18], a[18]); + COMBA_STORE(b[36]); + + /* output 37 */ + CARRY_FORWARD; + SQRADD2(a[18], a[19]); + COMBA_STORE(b[37]); + + /* output 38 */ + CARRY_FORWARD; + SQRADD(a[19], a[19]); + COMBA_STORE(b[38]); + COMBA_STORE2(b[39]); + COMBA_FINI; + + B->used = 40; + B->sign = FP_ZPOS; + XMEMCPY(B->dp, b, 40 * sizeof(fp_digit)); + fp_clamp(B); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; +} +#endif + + diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_sqr_comba_24.i b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_sqr_comba_24.i new file mode 100755 index 0000000..dc9e87a --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_sqr_comba_24.i @@ -0,0 +1,297 @@ +/* fp_sqr_comba_24.i + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifdef TFM_SQR24 +int fp_sqr_comba24(fp_int *A, fp_int *B) +{ + fp_digit *a, c0, c1, c2, sc0 = 0, sc1 = 0, sc2 = 0; +#ifdef TFM_ISO + fp_word tt; +#endif +#ifndef WOLFSSL_SMALL_STACK + fp_digit b[48]; +#else + fp_digit *b; +#endif + +#ifdef WOLFSSL_SMALL_STACK + b = (fp_digit*)XMALLOC(sizeof(fp_digit) * 48, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (b == NULL) + return FP_MEM; +#endif + + a = A->dp; + COMBA_START; + + /* clear carries */ + CLEAR_CARRY; + + /* output 0 */ + SQRADD(a[0],a[0]); + COMBA_STORE(b[0]); + + /* output 1 */ + CARRY_FORWARD; + SQRADD2(a[0], a[1]); + COMBA_STORE(b[1]); + + /* output 2 */ + CARRY_FORWARD; + SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]); + COMBA_STORE(b[2]); + + /* output 3 */ + CARRY_FORWARD; + SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]); + COMBA_STORE(b[3]); + + /* output 4 */ + CARRY_FORWARD; + SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]); + COMBA_STORE(b[4]); + + /* output 5 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB; + COMBA_STORE(b[5]); + + /* output 6 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]); + COMBA_STORE(b[6]); + + /* output 7 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[7]); SQRADDAC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB; + COMBA_STORE(b[7]); + + /* output 8 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[8]); SQRADDAC(a[1], a[7]); SQRADDAC(a[2], a[6]); SQRADDAC(a[3], a[5]); SQRADDDB; SQRADD(a[4], a[4]); + COMBA_STORE(b[8]); + + /* output 9 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[9]); SQRADDAC(a[1], a[8]); SQRADDAC(a[2], a[7]); SQRADDAC(a[3], a[6]); SQRADDAC(a[4], a[5]); SQRADDDB; + COMBA_STORE(b[9]); + + /* output 10 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[10]); SQRADDAC(a[1], a[9]); SQRADDAC(a[2], a[8]); SQRADDAC(a[3], a[7]); SQRADDAC(a[4], a[6]); SQRADDDB; SQRADD(a[5], a[5]); + COMBA_STORE(b[10]); + + /* output 11 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[11]); SQRADDAC(a[1], a[10]); SQRADDAC(a[2], a[9]); SQRADDAC(a[3], a[8]); SQRADDAC(a[4], a[7]); SQRADDAC(a[5], a[6]); SQRADDDB; + COMBA_STORE(b[11]); + + /* output 12 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[12]); SQRADDAC(a[1], a[11]); SQRADDAC(a[2], a[10]); SQRADDAC(a[3], a[9]); SQRADDAC(a[4], a[8]); SQRADDAC(a[5], a[7]); SQRADDDB; SQRADD(a[6], a[6]); + COMBA_STORE(b[12]); + + /* output 13 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[13]); SQRADDAC(a[1], a[12]); SQRADDAC(a[2], a[11]); SQRADDAC(a[3], a[10]); SQRADDAC(a[4], a[9]); SQRADDAC(a[5], a[8]); SQRADDAC(a[6], a[7]); SQRADDDB; + COMBA_STORE(b[13]); + + /* output 14 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[14]); SQRADDAC(a[1], a[13]); SQRADDAC(a[2], a[12]); SQRADDAC(a[3], a[11]); SQRADDAC(a[4], a[10]); SQRADDAC(a[5], a[9]); SQRADDAC(a[6], a[8]); SQRADDDB; SQRADD(a[7], a[7]); + COMBA_STORE(b[14]); + + /* output 15 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[15]); SQRADDAC(a[1], a[14]); SQRADDAC(a[2], a[13]); SQRADDAC(a[3], a[12]); SQRADDAC(a[4], a[11]); SQRADDAC(a[5], a[10]); SQRADDAC(a[6], a[9]); SQRADDAC(a[7], a[8]); SQRADDDB; + COMBA_STORE(b[15]); + + /* output 16 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[16]); SQRADDAC(a[1], a[15]); SQRADDAC(a[2], a[14]); SQRADDAC(a[3], a[13]); SQRADDAC(a[4], a[12]); SQRADDAC(a[5], a[11]); SQRADDAC(a[6], a[10]); SQRADDAC(a[7], a[9]); SQRADDDB; SQRADD(a[8], a[8]); + COMBA_STORE(b[16]); + + /* output 17 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[17]); SQRADDAC(a[1], a[16]); SQRADDAC(a[2], a[15]); SQRADDAC(a[3], a[14]); SQRADDAC(a[4], a[13]); SQRADDAC(a[5], a[12]); SQRADDAC(a[6], a[11]); SQRADDAC(a[7], a[10]); SQRADDAC(a[8], a[9]); SQRADDDB; + COMBA_STORE(b[17]); + + /* output 18 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[18]); SQRADDAC(a[1], a[17]); SQRADDAC(a[2], a[16]); SQRADDAC(a[3], a[15]); SQRADDAC(a[4], a[14]); SQRADDAC(a[5], a[13]); SQRADDAC(a[6], a[12]); SQRADDAC(a[7], a[11]); SQRADDAC(a[8], a[10]); SQRADDDB; SQRADD(a[9], a[9]); + COMBA_STORE(b[18]); + + /* output 19 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[19]); SQRADDAC(a[1], a[18]); SQRADDAC(a[2], a[17]); SQRADDAC(a[3], a[16]); SQRADDAC(a[4], a[15]); SQRADDAC(a[5], a[14]); SQRADDAC(a[6], a[13]); SQRADDAC(a[7], a[12]); SQRADDAC(a[8], a[11]); SQRADDAC(a[9], a[10]); SQRADDDB; + COMBA_STORE(b[19]); + + /* output 20 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[20]); SQRADDAC(a[1], a[19]); SQRADDAC(a[2], a[18]); SQRADDAC(a[3], a[17]); SQRADDAC(a[4], a[16]); SQRADDAC(a[5], a[15]); SQRADDAC(a[6], a[14]); SQRADDAC(a[7], a[13]); SQRADDAC(a[8], a[12]); SQRADDAC(a[9], a[11]); SQRADDDB; SQRADD(a[10], a[10]); + COMBA_STORE(b[20]); + + /* output 21 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[21]); SQRADDAC(a[1], a[20]); SQRADDAC(a[2], a[19]); SQRADDAC(a[3], a[18]); SQRADDAC(a[4], a[17]); SQRADDAC(a[5], a[16]); SQRADDAC(a[6], a[15]); SQRADDAC(a[7], a[14]); SQRADDAC(a[8], a[13]); SQRADDAC(a[9], a[12]); SQRADDAC(a[10], a[11]); SQRADDDB; + COMBA_STORE(b[21]); + + /* output 22 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[22]); SQRADDAC(a[1], a[21]); SQRADDAC(a[2], a[20]); SQRADDAC(a[3], a[19]); SQRADDAC(a[4], a[18]); SQRADDAC(a[5], a[17]); SQRADDAC(a[6], a[16]); SQRADDAC(a[7], a[15]); SQRADDAC(a[8], a[14]); SQRADDAC(a[9], a[13]); SQRADDAC(a[10], a[12]); SQRADDDB; SQRADD(a[11], a[11]); + COMBA_STORE(b[22]); + + /* output 23 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[23]); SQRADDAC(a[1], a[22]); SQRADDAC(a[2], a[21]); SQRADDAC(a[3], a[20]); SQRADDAC(a[4], a[19]); SQRADDAC(a[5], a[18]); SQRADDAC(a[6], a[17]); SQRADDAC(a[7], a[16]); SQRADDAC(a[8], a[15]); SQRADDAC(a[9], a[14]); SQRADDAC(a[10], a[13]); SQRADDAC(a[11], a[12]); SQRADDDB; + COMBA_STORE(b[23]); + + /* output 24 */ + CARRY_FORWARD; + SQRADDSC(a[1], a[23]); SQRADDAC(a[2], a[22]); SQRADDAC(a[3], a[21]); SQRADDAC(a[4], a[20]); SQRADDAC(a[5], a[19]); SQRADDAC(a[6], a[18]); SQRADDAC(a[7], a[17]); SQRADDAC(a[8], a[16]); SQRADDAC(a[9], a[15]); SQRADDAC(a[10], a[14]); SQRADDAC(a[11], a[13]); SQRADDDB; SQRADD(a[12], a[12]); + COMBA_STORE(b[24]); + + /* output 25 */ + CARRY_FORWARD; + SQRADDSC(a[2], a[23]); SQRADDAC(a[3], a[22]); SQRADDAC(a[4], a[21]); SQRADDAC(a[5], a[20]); SQRADDAC(a[6], a[19]); SQRADDAC(a[7], a[18]); SQRADDAC(a[8], a[17]); SQRADDAC(a[9], a[16]); SQRADDAC(a[10], a[15]); SQRADDAC(a[11], a[14]); SQRADDAC(a[12], a[13]); SQRADDDB; + COMBA_STORE(b[25]); + + /* output 26 */ + CARRY_FORWARD; + SQRADDSC(a[3], a[23]); SQRADDAC(a[4], a[22]); SQRADDAC(a[5], a[21]); SQRADDAC(a[6], a[20]); SQRADDAC(a[7], a[19]); SQRADDAC(a[8], a[18]); SQRADDAC(a[9], a[17]); SQRADDAC(a[10], a[16]); SQRADDAC(a[11], a[15]); SQRADDAC(a[12], a[14]); SQRADDDB; SQRADD(a[13], a[13]); + COMBA_STORE(b[26]); + + /* output 27 */ + CARRY_FORWARD; + SQRADDSC(a[4], a[23]); SQRADDAC(a[5], a[22]); SQRADDAC(a[6], a[21]); SQRADDAC(a[7], a[20]); SQRADDAC(a[8], a[19]); SQRADDAC(a[9], a[18]); SQRADDAC(a[10], a[17]); SQRADDAC(a[11], a[16]); SQRADDAC(a[12], a[15]); SQRADDAC(a[13], a[14]); SQRADDDB; + COMBA_STORE(b[27]); + + /* output 28 */ + CARRY_FORWARD; + SQRADDSC(a[5], a[23]); SQRADDAC(a[6], a[22]); SQRADDAC(a[7], a[21]); SQRADDAC(a[8], a[20]); SQRADDAC(a[9], a[19]); SQRADDAC(a[10], a[18]); SQRADDAC(a[11], a[17]); SQRADDAC(a[12], a[16]); SQRADDAC(a[13], a[15]); SQRADDDB; SQRADD(a[14], a[14]); + COMBA_STORE(b[28]); + + /* output 29 */ + CARRY_FORWARD; + SQRADDSC(a[6], a[23]); SQRADDAC(a[7], a[22]); SQRADDAC(a[8], a[21]); SQRADDAC(a[9], a[20]); SQRADDAC(a[10], a[19]); SQRADDAC(a[11], a[18]); SQRADDAC(a[12], a[17]); SQRADDAC(a[13], a[16]); SQRADDAC(a[14], a[15]); SQRADDDB; + COMBA_STORE(b[29]); + + /* output 30 */ + CARRY_FORWARD; + SQRADDSC(a[7], a[23]); SQRADDAC(a[8], a[22]); SQRADDAC(a[9], a[21]); SQRADDAC(a[10], a[20]); SQRADDAC(a[11], a[19]); SQRADDAC(a[12], a[18]); SQRADDAC(a[13], a[17]); SQRADDAC(a[14], a[16]); SQRADDDB; SQRADD(a[15], a[15]); + COMBA_STORE(b[30]); + + /* output 31 */ + CARRY_FORWARD; + SQRADDSC(a[8], a[23]); SQRADDAC(a[9], a[22]); SQRADDAC(a[10], a[21]); SQRADDAC(a[11], a[20]); SQRADDAC(a[12], a[19]); SQRADDAC(a[13], a[18]); SQRADDAC(a[14], a[17]); SQRADDAC(a[15], a[16]); SQRADDDB; + COMBA_STORE(b[31]); + + /* output 32 */ + CARRY_FORWARD; + SQRADDSC(a[9], a[23]); SQRADDAC(a[10], a[22]); SQRADDAC(a[11], a[21]); SQRADDAC(a[12], a[20]); SQRADDAC(a[13], a[19]); SQRADDAC(a[14], a[18]); SQRADDAC(a[15], a[17]); SQRADDDB; SQRADD(a[16], a[16]); + COMBA_STORE(b[32]); + + /* output 33 */ + CARRY_FORWARD; + SQRADDSC(a[10], a[23]); SQRADDAC(a[11], a[22]); SQRADDAC(a[12], a[21]); SQRADDAC(a[13], a[20]); SQRADDAC(a[14], a[19]); SQRADDAC(a[15], a[18]); SQRADDAC(a[16], a[17]); SQRADDDB; + COMBA_STORE(b[33]); + + /* output 34 */ + CARRY_FORWARD; + SQRADDSC(a[11], a[23]); SQRADDAC(a[12], a[22]); SQRADDAC(a[13], a[21]); SQRADDAC(a[14], a[20]); SQRADDAC(a[15], a[19]); SQRADDAC(a[16], a[18]); SQRADDDB; SQRADD(a[17], a[17]); + COMBA_STORE(b[34]); + + /* output 35 */ + CARRY_FORWARD; + SQRADDSC(a[12], a[23]); SQRADDAC(a[13], a[22]); SQRADDAC(a[14], a[21]); SQRADDAC(a[15], a[20]); SQRADDAC(a[16], a[19]); SQRADDAC(a[17], a[18]); SQRADDDB; + COMBA_STORE(b[35]); + + /* output 36 */ + CARRY_FORWARD; + SQRADDSC(a[13], a[23]); SQRADDAC(a[14], a[22]); SQRADDAC(a[15], a[21]); SQRADDAC(a[16], a[20]); SQRADDAC(a[17], a[19]); SQRADDDB; SQRADD(a[18], a[18]); + COMBA_STORE(b[36]); + + /* output 37 */ + CARRY_FORWARD; + SQRADDSC(a[14], a[23]); SQRADDAC(a[15], a[22]); SQRADDAC(a[16], a[21]); SQRADDAC(a[17], a[20]); SQRADDAC(a[18], a[19]); SQRADDDB; + COMBA_STORE(b[37]); + + /* output 38 */ + CARRY_FORWARD; + SQRADDSC(a[15], a[23]); SQRADDAC(a[16], a[22]); SQRADDAC(a[17], a[21]); SQRADDAC(a[18], a[20]); SQRADDDB; SQRADD(a[19], a[19]); + COMBA_STORE(b[38]); + + /* output 39 */ + CARRY_FORWARD; + SQRADDSC(a[16], a[23]); SQRADDAC(a[17], a[22]); SQRADDAC(a[18], a[21]); SQRADDAC(a[19], a[20]); SQRADDDB; + COMBA_STORE(b[39]); + + /* output 40 */ + CARRY_FORWARD; + SQRADDSC(a[17], a[23]); SQRADDAC(a[18], a[22]); SQRADDAC(a[19], a[21]); SQRADDDB; SQRADD(a[20], a[20]); + COMBA_STORE(b[40]); + + /* output 41 */ + CARRY_FORWARD; + SQRADDSC(a[18], a[23]); SQRADDAC(a[19], a[22]); SQRADDAC(a[20], a[21]); SQRADDDB; + COMBA_STORE(b[41]); + + /* output 42 */ + CARRY_FORWARD; + SQRADD2(a[19], a[23]); SQRADD2(a[20], a[22]); SQRADD(a[21], a[21]); + COMBA_STORE(b[42]); + + /* output 43 */ + CARRY_FORWARD; + SQRADD2(a[20], a[23]); SQRADD2(a[21], a[22]); + COMBA_STORE(b[43]); + + /* output 44 */ + CARRY_FORWARD; + SQRADD2(a[21], a[23]); SQRADD(a[22], a[22]); + COMBA_STORE(b[44]); + + /* output 45 */ + CARRY_FORWARD; + SQRADD2(a[22], a[23]); + COMBA_STORE(b[45]); + + /* output 46 */ + CARRY_FORWARD; + SQRADD(a[23], a[23]); + COMBA_STORE(b[46]); + COMBA_STORE2(b[47]); + COMBA_FINI; + + B->used = 48; + B->sign = FP_ZPOS; + XMEMCPY(B->dp, b, 48 * sizeof(fp_digit)); + fp_clamp(B); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; +} +#endif + + diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_sqr_comba_28.i b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_sqr_comba_28.i new file mode 100755 index 0000000..9655377 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_sqr_comba_28.i @@ -0,0 +1,337 @@ +/* fp_sqr_comba_28.i + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifdef TFM_SQR28 +int fp_sqr_comba28(fp_int *A, fp_int *B) +{ + fp_digit *a, c0, c1, c2, sc0 = 0, sc1 = 0, sc2 = 0; +#ifdef TFM_ISO + fp_word tt; +#endif +#ifndef WOLFSSL_SMALL_STACK + fp_digit b[56]; +#else + fp_digit *b; +#endif + +#ifdef WOLFSSL_SMALL_STACK + b = (fp_digit*)XMALLOC(sizeof(fp_digit) * 56, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (b == NULL) + return FP_MEM; +#endif + + a = A->dp; + COMBA_START; + + /* clear carries */ + CLEAR_CARRY; + + /* output 0 */ + SQRADD(a[0],a[0]); + COMBA_STORE(b[0]); + + /* output 1 */ + CARRY_FORWARD; + SQRADD2(a[0], a[1]); + COMBA_STORE(b[1]); + + /* output 2 */ + CARRY_FORWARD; + SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]); + COMBA_STORE(b[2]); + + /* output 3 */ + CARRY_FORWARD; + SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]); + COMBA_STORE(b[3]); + + /* output 4 */ + CARRY_FORWARD; + SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]); + COMBA_STORE(b[4]); + + /* output 5 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB; + COMBA_STORE(b[5]); + + /* output 6 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]); + COMBA_STORE(b[6]); + + /* output 7 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[7]); SQRADDAC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB; + COMBA_STORE(b[7]); + + /* output 8 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[8]); SQRADDAC(a[1], a[7]); SQRADDAC(a[2], a[6]); SQRADDAC(a[3], a[5]); SQRADDDB; SQRADD(a[4], a[4]); + COMBA_STORE(b[8]); + + /* output 9 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[9]); SQRADDAC(a[1], a[8]); SQRADDAC(a[2], a[7]); SQRADDAC(a[3], a[6]); SQRADDAC(a[4], a[5]); SQRADDDB; + COMBA_STORE(b[9]); + + /* output 10 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[10]); SQRADDAC(a[1], a[9]); SQRADDAC(a[2], a[8]); SQRADDAC(a[3], a[7]); SQRADDAC(a[4], a[6]); SQRADDDB; SQRADD(a[5], a[5]); + COMBA_STORE(b[10]); + + /* output 11 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[11]); SQRADDAC(a[1], a[10]); SQRADDAC(a[2], a[9]); SQRADDAC(a[3], a[8]); SQRADDAC(a[4], a[7]); SQRADDAC(a[5], a[6]); SQRADDDB; + COMBA_STORE(b[11]); + + /* output 12 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[12]); SQRADDAC(a[1], a[11]); SQRADDAC(a[2], a[10]); SQRADDAC(a[3], a[9]); SQRADDAC(a[4], a[8]); SQRADDAC(a[5], a[7]); SQRADDDB; SQRADD(a[6], a[6]); + COMBA_STORE(b[12]); + + /* output 13 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[13]); SQRADDAC(a[1], a[12]); SQRADDAC(a[2], a[11]); SQRADDAC(a[3], a[10]); SQRADDAC(a[4], a[9]); SQRADDAC(a[5], a[8]); SQRADDAC(a[6], a[7]); SQRADDDB; + COMBA_STORE(b[13]); + + /* output 14 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[14]); SQRADDAC(a[1], a[13]); SQRADDAC(a[2], a[12]); SQRADDAC(a[3], a[11]); SQRADDAC(a[4], a[10]); SQRADDAC(a[5], a[9]); SQRADDAC(a[6], a[8]); SQRADDDB; SQRADD(a[7], a[7]); + COMBA_STORE(b[14]); + + /* output 15 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[15]); SQRADDAC(a[1], a[14]); SQRADDAC(a[2], a[13]); SQRADDAC(a[3], a[12]); SQRADDAC(a[4], a[11]); SQRADDAC(a[5], a[10]); SQRADDAC(a[6], a[9]); SQRADDAC(a[7], a[8]); SQRADDDB; + COMBA_STORE(b[15]); + + /* output 16 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[16]); SQRADDAC(a[1], a[15]); SQRADDAC(a[2], a[14]); SQRADDAC(a[3], a[13]); SQRADDAC(a[4], a[12]); SQRADDAC(a[5], a[11]); SQRADDAC(a[6], a[10]); SQRADDAC(a[7], a[9]); SQRADDDB; SQRADD(a[8], a[8]); + COMBA_STORE(b[16]); + + /* output 17 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[17]); SQRADDAC(a[1], a[16]); SQRADDAC(a[2], a[15]); SQRADDAC(a[3], a[14]); SQRADDAC(a[4], a[13]); SQRADDAC(a[5], a[12]); SQRADDAC(a[6], a[11]); SQRADDAC(a[7], a[10]); SQRADDAC(a[8], a[9]); SQRADDDB; + COMBA_STORE(b[17]); + + /* output 18 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[18]); SQRADDAC(a[1], a[17]); SQRADDAC(a[2], a[16]); SQRADDAC(a[3], a[15]); SQRADDAC(a[4], a[14]); SQRADDAC(a[5], a[13]); SQRADDAC(a[6], a[12]); SQRADDAC(a[7], a[11]); SQRADDAC(a[8], a[10]); SQRADDDB; SQRADD(a[9], a[9]); + COMBA_STORE(b[18]); + + /* output 19 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[19]); SQRADDAC(a[1], a[18]); SQRADDAC(a[2], a[17]); SQRADDAC(a[3], a[16]); SQRADDAC(a[4], a[15]); SQRADDAC(a[5], a[14]); SQRADDAC(a[6], a[13]); SQRADDAC(a[7], a[12]); SQRADDAC(a[8], a[11]); SQRADDAC(a[9], a[10]); SQRADDDB; + COMBA_STORE(b[19]); + + /* output 20 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[20]); SQRADDAC(a[1], a[19]); SQRADDAC(a[2], a[18]); SQRADDAC(a[3], a[17]); SQRADDAC(a[4], a[16]); SQRADDAC(a[5], a[15]); SQRADDAC(a[6], a[14]); SQRADDAC(a[7], a[13]); SQRADDAC(a[8], a[12]); SQRADDAC(a[9], a[11]); SQRADDDB; SQRADD(a[10], a[10]); + COMBA_STORE(b[20]); + + /* output 21 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[21]); SQRADDAC(a[1], a[20]); SQRADDAC(a[2], a[19]); SQRADDAC(a[3], a[18]); SQRADDAC(a[4], a[17]); SQRADDAC(a[5], a[16]); SQRADDAC(a[6], a[15]); SQRADDAC(a[7], a[14]); SQRADDAC(a[8], a[13]); SQRADDAC(a[9], a[12]); SQRADDAC(a[10], a[11]); SQRADDDB; + COMBA_STORE(b[21]); + + /* output 22 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[22]); SQRADDAC(a[1], a[21]); SQRADDAC(a[2], a[20]); SQRADDAC(a[3], a[19]); SQRADDAC(a[4], a[18]); SQRADDAC(a[5], a[17]); SQRADDAC(a[6], a[16]); SQRADDAC(a[7], a[15]); SQRADDAC(a[8], a[14]); SQRADDAC(a[9], a[13]); SQRADDAC(a[10], a[12]); SQRADDDB; SQRADD(a[11], a[11]); + COMBA_STORE(b[22]); + + /* output 23 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[23]); SQRADDAC(a[1], a[22]); SQRADDAC(a[2], a[21]); SQRADDAC(a[3], a[20]); SQRADDAC(a[4], a[19]); SQRADDAC(a[5], a[18]); SQRADDAC(a[6], a[17]); SQRADDAC(a[7], a[16]); SQRADDAC(a[8], a[15]); SQRADDAC(a[9], a[14]); SQRADDAC(a[10], a[13]); SQRADDAC(a[11], a[12]); SQRADDDB; + COMBA_STORE(b[23]); + + /* output 24 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[24]); SQRADDAC(a[1], a[23]); SQRADDAC(a[2], a[22]); SQRADDAC(a[3], a[21]); SQRADDAC(a[4], a[20]); SQRADDAC(a[5], a[19]); SQRADDAC(a[6], a[18]); SQRADDAC(a[7], a[17]); SQRADDAC(a[8], a[16]); SQRADDAC(a[9], a[15]); SQRADDAC(a[10], a[14]); SQRADDAC(a[11], a[13]); SQRADDDB; SQRADD(a[12], a[12]); + COMBA_STORE(b[24]); + + /* output 25 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[25]); SQRADDAC(a[1], a[24]); SQRADDAC(a[2], a[23]); SQRADDAC(a[3], a[22]); SQRADDAC(a[4], a[21]); SQRADDAC(a[5], a[20]); SQRADDAC(a[6], a[19]); SQRADDAC(a[7], a[18]); SQRADDAC(a[8], a[17]); SQRADDAC(a[9], a[16]); SQRADDAC(a[10], a[15]); SQRADDAC(a[11], a[14]); SQRADDAC(a[12], a[13]); SQRADDDB; + COMBA_STORE(b[25]); + + /* output 26 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[26]); SQRADDAC(a[1], a[25]); SQRADDAC(a[2], a[24]); SQRADDAC(a[3], a[23]); SQRADDAC(a[4], a[22]); SQRADDAC(a[5], a[21]); SQRADDAC(a[6], a[20]); SQRADDAC(a[7], a[19]); SQRADDAC(a[8], a[18]); SQRADDAC(a[9], a[17]); SQRADDAC(a[10], a[16]); SQRADDAC(a[11], a[15]); SQRADDAC(a[12], a[14]); SQRADDDB; SQRADD(a[13], a[13]); + COMBA_STORE(b[26]); + + /* output 27 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[27]); SQRADDAC(a[1], a[26]); SQRADDAC(a[2], a[25]); SQRADDAC(a[3], a[24]); SQRADDAC(a[4], a[23]); SQRADDAC(a[5], a[22]); SQRADDAC(a[6], a[21]); SQRADDAC(a[7], a[20]); SQRADDAC(a[8], a[19]); SQRADDAC(a[9], a[18]); SQRADDAC(a[10], a[17]); SQRADDAC(a[11], a[16]); SQRADDAC(a[12], a[15]); SQRADDAC(a[13], a[14]); SQRADDDB; + COMBA_STORE(b[27]); + + /* output 28 */ + CARRY_FORWARD; + SQRADDSC(a[1], a[27]); SQRADDAC(a[2], a[26]); SQRADDAC(a[3], a[25]); SQRADDAC(a[4], a[24]); SQRADDAC(a[5], a[23]); SQRADDAC(a[6], a[22]); SQRADDAC(a[7], a[21]); SQRADDAC(a[8], a[20]); SQRADDAC(a[9], a[19]); SQRADDAC(a[10], a[18]); SQRADDAC(a[11], a[17]); SQRADDAC(a[12], a[16]); SQRADDAC(a[13], a[15]); SQRADDDB; SQRADD(a[14], a[14]); + COMBA_STORE(b[28]); + + /* output 29 */ + CARRY_FORWARD; + SQRADDSC(a[2], a[27]); SQRADDAC(a[3], a[26]); SQRADDAC(a[4], a[25]); SQRADDAC(a[5], a[24]); SQRADDAC(a[6], a[23]); SQRADDAC(a[7], a[22]); SQRADDAC(a[8], a[21]); SQRADDAC(a[9], a[20]); SQRADDAC(a[10], a[19]); SQRADDAC(a[11], a[18]); SQRADDAC(a[12], a[17]); SQRADDAC(a[13], a[16]); SQRADDAC(a[14], a[15]); SQRADDDB; + COMBA_STORE(b[29]); + + /* output 30 */ + CARRY_FORWARD; + SQRADDSC(a[3], a[27]); SQRADDAC(a[4], a[26]); SQRADDAC(a[5], a[25]); SQRADDAC(a[6], a[24]); SQRADDAC(a[7], a[23]); SQRADDAC(a[8], a[22]); SQRADDAC(a[9], a[21]); SQRADDAC(a[10], a[20]); SQRADDAC(a[11], a[19]); SQRADDAC(a[12], a[18]); SQRADDAC(a[13], a[17]); SQRADDAC(a[14], a[16]); SQRADDDB; SQRADD(a[15], a[15]); + COMBA_STORE(b[30]); + + /* output 31 */ + CARRY_FORWARD; + SQRADDSC(a[4], a[27]); SQRADDAC(a[5], a[26]); SQRADDAC(a[6], a[25]); SQRADDAC(a[7], a[24]); SQRADDAC(a[8], a[23]); SQRADDAC(a[9], a[22]); SQRADDAC(a[10], a[21]); SQRADDAC(a[11], a[20]); SQRADDAC(a[12], a[19]); SQRADDAC(a[13], a[18]); SQRADDAC(a[14], a[17]); SQRADDAC(a[15], a[16]); SQRADDDB; + COMBA_STORE(b[31]); + + /* output 32 */ + CARRY_FORWARD; + SQRADDSC(a[5], a[27]); SQRADDAC(a[6], a[26]); SQRADDAC(a[7], a[25]); SQRADDAC(a[8], a[24]); SQRADDAC(a[9], a[23]); SQRADDAC(a[10], a[22]); SQRADDAC(a[11], a[21]); SQRADDAC(a[12], a[20]); SQRADDAC(a[13], a[19]); SQRADDAC(a[14], a[18]); SQRADDAC(a[15], a[17]); SQRADDDB; SQRADD(a[16], a[16]); + COMBA_STORE(b[32]); + + /* output 33 */ + CARRY_FORWARD; + SQRADDSC(a[6], a[27]); SQRADDAC(a[7], a[26]); SQRADDAC(a[8], a[25]); SQRADDAC(a[9], a[24]); SQRADDAC(a[10], a[23]); SQRADDAC(a[11], a[22]); SQRADDAC(a[12], a[21]); SQRADDAC(a[13], a[20]); SQRADDAC(a[14], a[19]); SQRADDAC(a[15], a[18]); SQRADDAC(a[16], a[17]); SQRADDDB; + COMBA_STORE(b[33]); + + /* output 34 */ + CARRY_FORWARD; + SQRADDSC(a[7], a[27]); SQRADDAC(a[8], a[26]); SQRADDAC(a[9], a[25]); SQRADDAC(a[10], a[24]); SQRADDAC(a[11], a[23]); SQRADDAC(a[12], a[22]); SQRADDAC(a[13], a[21]); SQRADDAC(a[14], a[20]); SQRADDAC(a[15], a[19]); SQRADDAC(a[16], a[18]); SQRADDDB; SQRADD(a[17], a[17]); + COMBA_STORE(b[34]); + + /* output 35 */ + CARRY_FORWARD; + SQRADDSC(a[8], a[27]); SQRADDAC(a[9], a[26]); SQRADDAC(a[10], a[25]); SQRADDAC(a[11], a[24]); SQRADDAC(a[12], a[23]); SQRADDAC(a[13], a[22]); SQRADDAC(a[14], a[21]); SQRADDAC(a[15], a[20]); SQRADDAC(a[16], a[19]); SQRADDAC(a[17], a[18]); SQRADDDB; + COMBA_STORE(b[35]); + + /* output 36 */ + CARRY_FORWARD; + SQRADDSC(a[9], a[27]); SQRADDAC(a[10], a[26]); SQRADDAC(a[11], a[25]); SQRADDAC(a[12], a[24]); SQRADDAC(a[13], a[23]); SQRADDAC(a[14], a[22]); SQRADDAC(a[15], a[21]); SQRADDAC(a[16], a[20]); SQRADDAC(a[17], a[19]); SQRADDDB; SQRADD(a[18], a[18]); + COMBA_STORE(b[36]); + + /* output 37 */ + CARRY_FORWARD; + SQRADDSC(a[10], a[27]); SQRADDAC(a[11], a[26]); SQRADDAC(a[12], a[25]); SQRADDAC(a[13], a[24]); SQRADDAC(a[14], a[23]); SQRADDAC(a[15], a[22]); SQRADDAC(a[16], a[21]); SQRADDAC(a[17], a[20]); SQRADDAC(a[18], a[19]); SQRADDDB; + COMBA_STORE(b[37]); + + /* output 38 */ + CARRY_FORWARD; + SQRADDSC(a[11], a[27]); SQRADDAC(a[12], a[26]); SQRADDAC(a[13], a[25]); SQRADDAC(a[14], a[24]); SQRADDAC(a[15], a[23]); SQRADDAC(a[16], a[22]); SQRADDAC(a[17], a[21]); SQRADDAC(a[18], a[20]); SQRADDDB; SQRADD(a[19], a[19]); + COMBA_STORE(b[38]); + + /* output 39 */ + CARRY_FORWARD; + SQRADDSC(a[12], a[27]); SQRADDAC(a[13], a[26]); SQRADDAC(a[14], a[25]); SQRADDAC(a[15], a[24]); SQRADDAC(a[16], a[23]); SQRADDAC(a[17], a[22]); SQRADDAC(a[18], a[21]); SQRADDAC(a[19], a[20]); SQRADDDB; + COMBA_STORE(b[39]); + + /* output 40 */ + CARRY_FORWARD; + SQRADDSC(a[13], a[27]); SQRADDAC(a[14], a[26]); SQRADDAC(a[15], a[25]); SQRADDAC(a[16], a[24]); SQRADDAC(a[17], a[23]); SQRADDAC(a[18], a[22]); SQRADDAC(a[19], a[21]); SQRADDDB; SQRADD(a[20], a[20]); + COMBA_STORE(b[40]); + + /* output 41 */ + CARRY_FORWARD; + SQRADDSC(a[14], a[27]); SQRADDAC(a[15], a[26]); SQRADDAC(a[16], a[25]); SQRADDAC(a[17], a[24]); SQRADDAC(a[18], a[23]); SQRADDAC(a[19], a[22]); SQRADDAC(a[20], a[21]); SQRADDDB; + COMBA_STORE(b[41]); + + /* output 42 */ + CARRY_FORWARD; + SQRADDSC(a[15], a[27]); SQRADDAC(a[16], a[26]); SQRADDAC(a[17], a[25]); SQRADDAC(a[18], a[24]); SQRADDAC(a[19], a[23]); SQRADDAC(a[20], a[22]); SQRADDDB; SQRADD(a[21], a[21]); + COMBA_STORE(b[42]); + + /* output 43 */ + CARRY_FORWARD; + SQRADDSC(a[16], a[27]); SQRADDAC(a[17], a[26]); SQRADDAC(a[18], a[25]); SQRADDAC(a[19], a[24]); SQRADDAC(a[20], a[23]); SQRADDAC(a[21], a[22]); SQRADDDB; + COMBA_STORE(b[43]); + + /* output 44 */ + CARRY_FORWARD; + SQRADDSC(a[17], a[27]); SQRADDAC(a[18], a[26]); SQRADDAC(a[19], a[25]); SQRADDAC(a[20], a[24]); SQRADDAC(a[21], a[23]); SQRADDDB; SQRADD(a[22], a[22]); + COMBA_STORE(b[44]); + + /* output 45 */ + CARRY_FORWARD; + SQRADDSC(a[18], a[27]); SQRADDAC(a[19], a[26]); SQRADDAC(a[20], a[25]); SQRADDAC(a[21], a[24]); SQRADDAC(a[22], a[23]); SQRADDDB; + COMBA_STORE(b[45]); + + /* output 46 */ + CARRY_FORWARD; + SQRADDSC(a[19], a[27]); SQRADDAC(a[20], a[26]); SQRADDAC(a[21], a[25]); SQRADDAC(a[22], a[24]); SQRADDDB; SQRADD(a[23], a[23]); + COMBA_STORE(b[46]); + + /* output 47 */ + CARRY_FORWARD; + SQRADDSC(a[20], a[27]); SQRADDAC(a[21], a[26]); SQRADDAC(a[22], a[25]); SQRADDAC(a[23], a[24]); SQRADDDB; + COMBA_STORE(b[47]); + + /* output 48 */ + CARRY_FORWARD; + SQRADDSC(a[21], a[27]); SQRADDAC(a[22], a[26]); SQRADDAC(a[23], a[25]); SQRADDDB; SQRADD(a[24], a[24]); + COMBA_STORE(b[48]); + + /* output 49 */ + CARRY_FORWARD; + SQRADDSC(a[22], a[27]); SQRADDAC(a[23], a[26]); SQRADDAC(a[24], a[25]); SQRADDDB; + COMBA_STORE(b[49]); + + /* output 50 */ + CARRY_FORWARD; + SQRADD2(a[23], a[27]); SQRADD2(a[24], a[26]); SQRADD(a[25], a[25]); + COMBA_STORE(b[50]); + + /* output 51 */ + CARRY_FORWARD; + SQRADD2(a[24], a[27]); SQRADD2(a[25], a[26]); + COMBA_STORE(b[51]); + + /* output 52 */ + CARRY_FORWARD; + SQRADD2(a[25], a[27]); SQRADD(a[26], a[26]); + COMBA_STORE(b[52]); + + /* output 53 */ + CARRY_FORWARD; + SQRADD2(a[26], a[27]); + COMBA_STORE(b[53]); + + /* output 54 */ + CARRY_FORWARD; + SQRADD(a[27], a[27]); + COMBA_STORE(b[54]); + COMBA_STORE2(b[55]); + COMBA_FINI; + + B->used = 56; + B->sign = FP_ZPOS; + XMEMCPY(B->dp, b, 56 * sizeof(fp_digit)); + fp_clamp(B); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; +} +#endif + + diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_sqr_comba_3.i b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_sqr_comba_3.i new file mode 100755 index 0000000..e0355f7 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_sqr_comba_3.i @@ -0,0 +1,73 @@ +/* fp_sqr_comba_3.i + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifdef TFM_SQR3 +int fp_sqr_comba3(fp_int *A, fp_int *B) +{ + fp_digit *a, b[6], c0, c1, c2; +#ifdef TFM_ISO + fp_word tt; +#endif + + a = A->dp; + COMBA_START; + + /* clear carries */ + CLEAR_CARRY; + + /* output 0 */ + SQRADD(a[0],a[0]); + COMBA_STORE(b[0]); + + /* output 1 */ + CARRY_FORWARD; + SQRADD2(a[0], a[1]); + COMBA_STORE(b[1]); + + /* output 2 */ + CARRY_FORWARD; + SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]); + COMBA_STORE(b[2]); + + /* output 3 */ + CARRY_FORWARD; + SQRADD2(a[1], a[2]); + COMBA_STORE(b[3]); + + /* output 4 */ + CARRY_FORWARD; + SQRADD(a[2], a[2]); + COMBA_STORE(b[4]); + COMBA_STORE2(b[5]); + COMBA_FINI; + + B->used = 6; + B->sign = FP_ZPOS; + XMEMCPY(B->dp, b, 6 * sizeof(fp_digit)); + fp_clamp(B); + + return FP_OKAY; +} +#endif + + diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_sqr_comba_32.i b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_sqr_comba_32.i new file mode 100755 index 0000000..e41d928 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_sqr_comba_32.i @@ -0,0 +1,377 @@ +/* fp_sqr_comba_32.i + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifdef TFM_SQR32 +int fp_sqr_comba32(fp_int *A, fp_int *B) +{ + fp_digit *a, c0, c1, c2, sc0 = 0, sc1 = 0, sc2 = 0; +#ifdef TFM_ISO + fp_word tt; +#endif +#ifndef WOLFSSL_SMALL_STACK + fp_digit b[64]; +#else + fp_digit *b; +#endif + +#ifdef WOLFSSL_SMALL_STACK + b = (fp_digit*)XMALLOC(sizeof(fp_digit) * 64, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (b == NULL) + return FP_MEM; +#endif + + a = A->dp; + COMBA_START; + + /* clear carries */ + CLEAR_CARRY; + + /* output 0 */ + SQRADD(a[0],a[0]); + COMBA_STORE(b[0]); + + /* output 1 */ + CARRY_FORWARD; + SQRADD2(a[0], a[1]); + COMBA_STORE(b[1]); + + /* output 2 */ + CARRY_FORWARD; + SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]); + COMBA_STORE(b[2]); + + /* output 3 */ + CARRY_FORWARD; + SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]); + COMBA_STORE(b[3]); + + /* output 4 */ + CARRY_FORWARD; + SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]); + COMBA_STORE(b[4]); + + /* output 5 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB; + COMBA_STORE(b[5]); + + /* output 6 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]); + COMBA_STORE(b[6]); + + /* output 7 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[7]); SQRADDAC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB; + COMBA_STORE(b[7]); + + /* output 8 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[8]); SQRADDAC(a[1], a[7]); SQRADDAC(a[2], a[6]); SQRADDAC(a[3], a[5]); SQRADDDB; SQRADD(a[4], a[4]); + COMBA_STORE(b[8]); + + /* output 9 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[9]); SQRADDAC(a[1], a[8]); SQRADDAC(a[2], a[7]); SQRADDAC(a[3], a[6]); SQRADDAC(a[4], a[5]); SQRADDDB; + COMBA_STORE(b[9]); + + /* output 10 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[10]); SQRADDAC(a[1], a[9]); SQRADDAC(a[2], a[8]); SQRADDAC(a[3], a[7]); SQRADDAC(a[4], a[6]); SQRADDDB; SQRADD(a[5], a[5]); + COMBA_STORE(b[10]); + + /* output 11 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[11]); SQRADDAC(a[1], a[10]); SQRADDAC(a[2], a[9]); SQRADDAC(a[3], a[8]); SQRADDAC(a[4], a[7]); SQRADDAC(a[5], a[6]); SQRADDDB; + COMBA_STORE(b[11]); + + /* output 12 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[12]); SQRADDAC(a[1], a[11]); SQRADDAC(a[2], a[10]); SQRADDAC(a[3], a[9]); SQRADDAC(a[4], a[8]); SQRADDAC(a[5], a[7]); SQRADDDB; SQRADD(a[6], a[6]); + COMBA_STORE(b[12]); + + /* output 13 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[13]); SQRADDAC(a[1], a[12]); SQRADDAC(a[2], a[11]); SQRADDAC(a[3], a[10]); SQRADDAC(a[4], a[9]); SQRADDAC(a[5], a[8]); SQRADDAC(a[6], a[7]); SQRADDDB; + COMBA_STORE(b[13]); + + /* output 14 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[14]); SQRADDAC(a[1], a[13]); SQRADDAC(a[2], a[12]); SQRADDAC(a[3], a[11]); SQRADDAC(a[4], a[10]); SQRADDAC(a[5], a[9]); SQRADDAC(a[6], a[8]); SQRADDDB; SQRADD(a[7], a[7]); + COMBA_STORE(b[14]); + + /* output 15 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[15]); SQRADDAC(a[1], a[14]); SQRADDAC(a[2], a[13]); SQRADDAC(a[3], a[12]); SQRADDAC(a[4], a[11]); SQRADDAC(a[5], a[10]); SQRADDAC(a[6], a[9]); SQRADDAC(a[7], a[8]); SQRADDDB; + COMBA_STORE(b[15]); + + /* output 16 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[16]); SQRADDAC(a[1], a[15]); SQRADDAC(a[2], a[14]); SQRADDAC(a[3], a[13]); SQRADDAC(a[4], a[12]); SQRADDAC(a[5], a[11]); SQRADDAC(a[6], a[10]); SQRADDAC(a[7], a[9]); SQRADDDB; SQRADD(a[8], a[8]); + COMBA_STORE(b[16]); + + /* output 17 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[17]); SQRADDAC(a[1], a[16]); SQRADDAC(a[2], a[15]); SQRADDAC(a[3], a[14]); SQRADDAC(a[4], a[13]); SQRADDAC(a[5], a[12]); SQRADDAC(a[6], a[11]); SQRADDAC(a[7], a[10]); SQRADDAC(a[8], a[9]); SQRADDDB; + COMBA_STORE(b[17]); + + /* output 18 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[18]); SQRADDAC(a[1], a[17]); SQRADDAC(a[2], a[16]); SQRADDAC(a[3], a[15]); SQRADDAC(a[4], a[14]); SQRADDAC(a[5], a[13]); SQRADDAC(a[6], a[12]); SQRADDAC(a[7], a[11]); SQRADDAC(a[8], a[10]); SQRADDDB; SQRADD(a[9], a[9]); + COMBA_STORE(b[18]); + + /* output 19 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[19]); SQRADDAC(a[1], a[18]); SQRADDAC(a[2], a[17]); SQRADDAC(a[3], a[16]); SQRADDAC(a[4], a[15]); SQRADDAC(a[5], a[14]); SQRADDAC(a[6], a[13]); SQRADDAC(a[7], a[12]); SQRADDAC(a[8], a[11]); SQRADDAC(a[9], a[10]); SQRADDDB; + COMBA_STORE(b[19]); + + /* output 20 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[20]); SQRADDAC(a[1], a[19]); SQRADDAC(a[2], a[18]); SQRADDAC(a[3], a[17]); SQRADDAC(a[4], a[16]); SQRADDAC(a[5], a[15]); SQRADDAC(a[6], a[14]); SQRADDAC(a[7], a[13]); SQRADDAC(a[8], a[12]); SQRADDAC(a[9], a[11]); SQRADDDB; SQRADD(a[10], a[10]); + COMBA_STORE(b[20]); + + /* output 21 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[21]); SQRADDAC(a[1], a[20]); SQRADDAC(a[2], a[19]); SQRADDAC(a[3], a[18]); SQRADDAC(a[4], a[17]); SQRADDAC(a[5], a[16]); SQRADDAC(a[6], a[15]); SQRADDAC(a[7], a[14]); SQRADDAC(a[8], a[13]); SQRADDAC(a[9], a[12]); SQRADDAC(a[10], a[11]); SQRADDDB; + COMBA_STORE(b[21]); + + /* output 22 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[22]); SQRADDAC(a[1], a[21]); SQRADDAC(a[2], a[20]); SQRADDAC(a[3], a[19]); SQRADDAC(a[4], a[18]); SQRADDAC(a[5], a[17]); SQRADDAC(a[6], a[16]); SQRADDAC(a[7], a[15]); SQRADDAC(a[8], a[14]); SQRADDAC(a[9], a[13]); SQRADDAC(a[10], a[12]); SQRADDDB; SQRADD(a[11], a[11]); + COMBA_STORE(b[22]); + + /* output 23 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[23]); SQRADDAC(a[1], a[22]); SQRADDAC(a[2], a[21]); SQRADDAC(a[3], a[20]); SQRADDAC(a[4], a[19]); SQRADDAC(a[5], a[18]); SQRADDAC(a[6], a[17]); SQRADDAC(a[7], a[16]); SQRADDAC(a[8], a[15]); SQRADDAC(a[9], a[14]); SQRADDAC(a[10], a[13]); SQRADDAC(a[11], a[12]); SQRADDDB; + COMBA_STORE(b[23]); + + /* output 24 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[24]); SQRADDAC(a[1], a[23]); SQRADDAC(a[2], a[22]); SQRADDAC(a[3], a[21]); SQRADDAC(a[4], a[20]); SQRADDAC(a[5], a[19]); SQRADDAC(a[6], a[18]); SQRADDAC(a[7], a[17]); SQRADDAC(a[8], a[16]); SQRADDAC(a[9], a[15]); SQRADDAC(a[10], a[14]); SQRADDAC(a[11], a[13]); SQRADDDB; SQRADD(a[12], a[12]); + COMBA_STORE(b[24]); + + /* output 25 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[25]); SQRADDAC(a[1], a[24]); SQRADDAC(a[2], a[23]); SQRADDAC(a[3], a[22]); SQRADDAC(a[4], a[21]); SQRADDAC(a[5], a[20]); SQRADDAC(a[6], a[19]); SQRADDAC(a[7], a[18]); SQRADDAC(a[8], a[17]); SQRADDAC(a[9], a[16]); SQRADDAC(a[10], a[15]); SQRADDAC(a[11], a[14]); SQRADDAC(a[12], a[13]); SQRADDDB; + COMBA_STORE(b[25]); + + /* output 26 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[26]); SQRADDAC(a[1], a[25]); SQRADDAC(a[2], a[24]); SQRADDAC(a[3], a[23]); SQRADDAC(a[4], a[22]); SQRADDAC(a[5], a[21]); SQRADDAC(a[6], a[20]); SQRADDAC(a[7], a[19]); SQRADDAC(a[8], a[18]); SQRADDAC(a[9], a[17]); SQRADDAC(a[10], a[16]); SQRADDAC(a[11], a[15]); SQRADDAC(a[12], a[14]); SQRADDDB; SQRADD(a[13], a[13]); + COMBA_STORE(b[26]); + + /* output 27 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[27]); SQRADDAC(a[1], a[26]); SQRADDAC(a[2], a[25]); SQRADDAC(a[3], a[24]); SQRADDAC(a[4], a[23]); SQRADDAC(a[5], a[22]); SQRADDAC(a[6], a[21]); SQRADDAC(a[7], a[20]); SQRADDAC(a[8], a[19]); SQRADDAC(a[9], a[18]); SQRADDAC(a[10], a[17]); SQRADDAC(a[11], a[16]); SQRADDAC(a[12], a[15]); SQRADDAC(a[13], a[14]); SQRADDDB; + COMBA_STORE(b[27]); + + /* output 28 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[28]); SQRADDAC(a[1], a[27]); SQRADDAC(a[2], a[26]); SQRADDAC(a[3], a[25]); SQRADDAC(a[4], a[24]); SQRADDAC(a[5], a[23]); SQRADDAC(a[6], a[22]); SQRADDAC(a[7], a[21]); SQRADDAC(a[8], a[20]); SQRADDAC(a[9], a[19]); SQRADDAC(a[10], a[18]); SQRADDAC(a[11], a[17]); SQRADDAC(a[12], a[16]); SQRADDAC(a[13], a[15]); SQRADDDB; SQRADD(a[14], a[14]); + COMBA_STORE(b[28]); + + /* output 29 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[29]); SQRADDAC(a[1], a[28]); SQRADDAC(a[2], a[27]); SQRADDAC(a[3], a[26]); SQRADDAC(a[4], a[25]); SQRADDAC(a[5], a[24]); SQRADDAC(a[6], a[23]); SQRADDAC(a[7], a[22]); SQRADDAC(a[8], a[21]); SQRADDAC(a[9], a[20]); SQRADDAC(a[10], a[19]); SQRADDAC(a[11], a[18]); SQRADDAC(a[12], a[17]); SQRADDAC(a[13], a[16]); SQRADDAC(a[14], a[15]); SQRADDDB; + COMBA_STORE(b[29]); + + /* output 30 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[30]); SQRADDAC(a[1], a[29]); SQRADDAC(a[2], a[28]); SQRADDAC(a[3], a[27]); SQRADDAC(a[4], a[26]); SQRADDAC(a[5], a[25]); SQRADDAC(a[6], a[24]); SQRADDAC(a[7], a[23]); SQRADDAC(a[8], a[22]); SQRADDAC(a[9], a[21]); SQRADDAC(a[10], a[20]); SQRADDAC(a[11], a[19]); SQRADDAC(a[12], a[18]); SQRADDAC(a[13], a[17]); SQRADDAC(a[14], a[16]); SQRADDDB; SQRADD(a[15], a[15]); + COMBA_STORE(b[30]); + + /* output 31 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[31]); SQRADDAC(a[1], a[30]); SQRADDAC(a[2], a[29]); SQRADDAC(a[3], a[28]); SQRADDAC(a[4], a[27]); SQRADDAC(a[5], a[26]); SQRADDAC(a[6], a[25]); SQRADDAC(a[7], a[24]); SQRADDAC(a[8], a[23]); SQRADDAC(a[9], a[22]); SQRADDAC(a[10], a[21]); SQRADDAC(a[11], a[20]); SQRADDAC(a[12], a[19]); SQRADDAC(a[13], a[18]); SQRADDAC(a[14], a[17]); SQRADDAC(a[15], a[16]); SQRADDDB; + COMBA_STORE(b[31]); + + /* output 32 */ + CARRY_FORWARD; + SQRADDSC(a[1], a[31]); SQRADDAC(a[2], a[30]); SQRADDAC(a[3], a[29]); SQRADDAC(a[4], a[28]); SQRADDAC(a[5], a[27]); SQRADDAC(a[6], a[26]); SQRADDAC(a[7], a[25]); SQRADDAC(a[8], a[24]); SQRADDAC(a[9], a[23]); SQRADDAC(a[10], a[22]); SQRADDAC(a[11], a[21]); SQRADDAC(a[12], a[20]); SQRADDAC(a[13], a[19]); SQRADDAC(a[14], a[18]); SQRADDAC(a[15], a[17]); SQRADDDB; SQRADD(a[16], a[16]); + COMBA_STORE(b[32]); + + /* output 33 */ + CARRY_FORWARD; + SQRADDSC(a[2], a[31]); SQRADDAC(a[3], a[30]); SQRADDAC(a[4], a[29]); SQRADDAC(a[5], a[28]); SQRADDAC(a[6], a[27]); SQRADDAC(a[7], a[26]); SQRADDAC(a[8], a[25]); SQRADDAC(a[9], a[24]); SQRADDAC(a[10], a[23]); SQRADDAC(a[11], a[22]); SQRADDAC(a[12], a[21]); SQRADDAC(a[13], a[20]); SQRADDAC(a[14], a[19]); SQRADDAC(a[15], a[18]); SQRADDAC(a[16], a[17]); SQRADDDB; + COMBA_STORE(b[33]); + + /* output 34 */ + CARRY_FORWARD; + SQRADDSC(a[3], a[31]); SQRADDAC(a[4], a[30]); SQRADDAC(a[5], a[29]); SQRADDAC(a[6], a[28]); SQRADDAC(a[7], a[27]); SQRADDAC(a[8], a[26]); SQRADDAC(a[9], a[25]); SQRADDAC(a[10], a[24]); SQRADDAC(a[11], a[23]); SQRADDAC(a[12], a[22]); SQRADDAC(a[13], a[21]); SQRADDAC(a[14], a[20]); SQRADDAC(a[15], a[19]); SQRADDAC(a[16], a[18]); SQRADDDB; SQRADD(a[17], a[17]); + COMBA_STORE(b[34]); + + /* output 35 */ + CARRY_FORWARD; + SQRADDSC(a[4], a[31]); SQRADDAC(a[5], a[30]); SQRADDAC(a[6], a[29]); SQRADDAC(a[7], a[28]); SQRADDAC(a[8], a[27]); SQRADDAC(a[9], a[26]); SQRADDAC(a[10], a[25]); SQRADDAC(a[11], a[24]); SQRADDAC(a[12], a[23]); SQRADDAC(a[13], a[22]); SQRADDAC(a[14], a[21]); SQRADDAC(a[15], a[20]); SQRADDAC(a[16], a[19]); SQRADDAC(a[17], a[18]); SQRADDDB; + COMBA_STORE(b[35]); + + /* output 36 */ + CARRY_FORWARD; + SQRADDSC(a[5], a[31]); SQRADDAC(a[6], a[30]); SQRADDAC(a[7], a[29]); SQRADDAC(a[8], a[28]); SQRADDAC(a[9], a[27]); SQRADDAC(a[10], a[26]); SQRADDAC(a[11], a[25]); SQRADDAC(a[12], a[24]); SQRADDAC(a[13], a[23]); SQRADDAC(a[14], a[22]); SQRADDAC(a[15], a[21]); SQRADDAC(a[16], a[20]); SQRADDAC(a[17], a[19]); SQRADDDB; SQRADD(a[18], a[18]); + COMBA_STORE(b[36]); + + /* output 37 */ + CARRY_FORWARD; + SQRADDSC(a[6], a[31]); SQRADDAC(a[7], a[30]); SQRADDAC(a[8], a[29]); SQRADDAC(a[9], a[28]); SQRADDAC(a[10], a[27]); SQRADDAC(a[11], a[26]); SQRADDAC(a[12], a[25]); SQRADDAC(a[13], a[24]); SQRADDAC(a[14], a[23]); SQRADDAC(a[15], a[22]); SQRADDAC(a[16], a[21]); SQRADDAC(a[17], a[20]); SQRADDAC(a[18], a[19]); SQRADDDB; + COMBA_STORE(b[37]); + + /* output 38 */ + CARRY_FORWARD; + SQRADDSC(a[7], a[31]); SQRADDAC(a[8], a[30]); SQRADDAC(a[9], a[29]); SQRADDAC(a[10], a[28]); SQRADDAC(a[11], a[27]); SQRADDAC(a[12], a[26]); SQRADDAC(a[13], a[25]); SQRADDAC(a[14], a[24]); SQRADDAC(a[15], a[23]); SQRADDAC(a[16], a[22]); SQRADDAC(a[17], a[21]); SQRADDAC(a[18], a[20]); SQRADDDB; SQRADD(a[19], a[19]); + COMBA_STORE(b[38]); + + /* output 39 */ + CARRY_FORWARD; + SQRADDSC(a[8], a[31]); SQRADDAC(a[9], a[30]); SQRADDAC(a[10], a[29]); SQRADDAC(a[11], a[28]); SQRADDAC(a[12], a[27]); SQRADDAC(a[13], a[26]); SQRADDAC(a[14], a[25]); SQRADDAC(a[15], a[24]); SQRADDAC(a[16], a[23]); SQRADDAC(a[17], a[22]); SQRADDAC(a[18], a[21]); SQRADDAC(a[19], a[20]); SQRADDDB; + COMBA_STORE(b[39]); + + /* output 40 */ + CARRY_FORWARD; + SQRADDSC(a[9], a[31]); SQRADDAC(a[10], a[30]); SQRADDAC(a[11], a[29]); SQRADDAC(a[12], a[28]); SQRADDAC(a[13], a[27]); SQRADDAC(a[14], a[26]); SQRADDAC(a[15], a[25]); SQRADDAC(a[16], a[24]); SQRADDAC(a[17], a[23]); SQRADDAC(a[18], a[22]); SQRADDAC(a[19], a[21]); SQRADDDB; SQRADD(a[20], a[20]); + COMBA_STORE(b[40]); + + /* output 41 */ + CARRY_FORWARD; + SQRADDSC(a[10], a[31]); SQRADDAC(a[11], a[30]); SQRADDAC(a[12], a[29]); SQRADDAC(a[13], a[28]); SQRADDAC(a[14], a[27]); SQRADDAC(a[15], a[26]); SQRADDAC(a[16], a[25]); SQRADDAC(a[17], a[24]); SQRADDAC(a[18], a[23]); SQRADDAC(a[19], a[22]); SQRADDAC(a[20], a[21]); SQRADDDB; + COMBA_STORE(b[41]); + + /* output 42 */ + CARRY_FORWARD; + SQRADDSC(a[11], a[31]); SQRADDAC(a[12], a[30]); SQRADDAC(a[13], a[29]); SQRADDAC(a[14], a[28]); SQRADDAC(a[15], a[27]); SQRADDAC(a[16], a[26]); SQRADDAC(a[17], a[25]); SQRADDAC(a[18], a[24]); SQRADDAC(a[19], a[23]); SQRADDAC(a[20], a[22]); SQRADDDB; SQRADD(a[21], a[21]); + COMBA_STORE(b[42]); + + /* output 43 */ + CARRY_FORWARD; + SQRADDSC(a[12], a[31]); SQRADDAC(a[13], a[30]); SQRADDAC(a[14], a[29]); SQRADDAC(a[15], a[28]); SQRADDAC(a[16], a[27]); SQRADDAC(a[17], a[26]); SQRADDAC(a[18], a[25]); SQRADDAC(a[19], a[24]); SQRADDAC(a[20], a[23]); SQRADDAC(a[21], a[22]); SQRADDDB; + COMBA_STORE(b[43]); + + /* output 44 */ + CARRY_FORWARD; + SQRADDSC(a[13], a[31]); SQRADDAC(a[14], a[30]); SQRADDAC(a[15], a[29]); SQRADDAC(a[16], a[28]); SQRADDAC(a[17], a[27]); SQRADDAC(a[18], a[26]); SQRADDAC(a[19], a[25]); SQRADDAC(a[20], a[24]); SQRADDAC(a[21], a[23]); SQRADDDB; SQRADD(a[22], a[22]); + COMBA_STORE(b[44]); + + /* output 45 */ + CARRY_FORWARD; + SQRADDSC(a[14], a[31]); SQRADDAC(a[15], a[30]); SQRADDAC(a[16], a[29]); SQRADDAC(a[17], a[28]); SQRADDAC(a[18], a[27]); SQRADDAC(a[19], a[26]); SQRADDAC(a[20], a[25]); SQRADDAC(a[21], a[24]); SQRADDAC(a[22], a[23]); SQRADDDB; + COMBA_STORE(b[45]); + + /* output 46 */ + CARRY_FORWARD; + SQRADDSC(a[15], a[31]); SQRADDAC(a[16], a[30]); SQRADDAC(a[17], a[29]); SQRADDAC(a[18], a[28]); SQRADDAC(a[19], a[27]); SQRADDAC(a[20], a[26]); SQRADDAC(a[21], a[25]); SQRADDAC(a[22], a[24]); SQRADDDB; SQRADD(a[23], a[23]); + COMBA_STORE(b[46]); + + /* output 47 */ + CARRY_FORWARD; + SQRADDSC(a[16], a[31]); SQRADDAC(a[17], a[30]); SQRADDAC(a[18], a[29]); SQRADDAC(a[19], a[28]); SQRADDAC(a[20], a[27]); SQRADDAC(a[21], a[26]); SQRADDAC(a[22], a[25]); SQRADDAC(a[23], a[24]); SQRADDDB; + COMBA_STORE(b[47]); + + /* output 48 */ + CARRY_FORWARD; + SQRADDSC(a[17], a[31]); SQRADDAC(a[18], a[30]); SQRADDAC(a[19], a[29]); SQRADDAC(a[20], a[28]); SQRADDAC(a[21], a[27]); SQRADDAC(a[22], a[26]); SQRADDAC(a[23], a[25]); SQRADDDB; SQRADD(a[24], a[24]); + COMBA_STORE(b[48]); + + /* output 49 */ + CARRY_FORWARD; + SQRADDSC(a[18], a[31]); SQRADDAC(a[19], a[30]); SQRADDAC(a[20], a[29]); SQRADDAC(a[21], a[28]); SQRADDAC(a[22], a[27]); SQRADDAC(a[23], a[26]); SQRADDAC(a[24], a[25]); SQRADDDB; + COMBA_STORE(b[49]); + + /* output 50 */ + CARRY_FORWARD; + SQRADDSC(a[19], a[31]); SQRADDAC(a[20], a[30]); SQRADDAC(a[21], a[29]); SQRADDAC(a[22], a[28]); SQRADDAC(a[23], a[27]); SQRADDAC(a[24], a[26]); SQRADDDB; SQRADD(a[25], a[25]); + COMBA_STORE(b[50]); + + /* output 51 */ + CARRY_FORWARD; + SQRADDSC(a[20], a[31]); SQRADDAC(a[21], a[30]); SQRADDAC(a[22], a[29]); SQRADDAC(a[23], a[28]); SQRADDAC(a[24], a[27]); SQRADDAC(a[25], a[26]); SQRADDDB; + COMBA_STORE(b[51]); + + /* output 52 */ + CARRY_FORWARD; + SQRADDSC(a[21], a[31]); SQRADDAC(a[22], a[30]); SQRADDAC(a[23], a[29]); SQRADDAC(a[24], a[28]); SQRADDAC(a[25], a[27]); SQRADDDB; SQRADD(a[26], a[26]); + COMBA_STORE(b[52]); + + /* output 53 */ + CARRY_FORWARD; + SQRADDSC(a[22], a[31]); SQRADDAC(a[23], a[30]); SQRADDAC(a[24], a[29]); SQRADDAC(a[25], a[28]); SQRADDAC(a[26], a[27]); SQRADDDB; + COMBA_STORE(b[53]); + + /* output 54 */ + CARRY_FORWARD; + SQRADDSC(a[23], a[31]); SQRADDAC(a[24], a[30]); SQRADDAC(a[25], a[29]); SQRADDAC(a[26], a[28]); SQRADDDB; SQRADD(a[27], a[27]); + COMBA_STORE(b[54]); + + /* output 55 */ + CARRY_FORWARD; + SQRADDSC(a[24], a[31]); SQRADDAC(a[25], a[30]); SQRADDAC(a[26], a[29]); SQRADDAC(a[27], a[28]); SQRADDDB; + COMBA_STORE(b[55]); + + /* output 56 */ + CARRY_FORWARD; + SQRADDSC(a[25], a[31]); SQRADDAC(a[26], a[30]); SQRADDAC(a[27], a[29]); SQRADDDB; SQRADD(a[28], a[28]); + COMBA_STORE(b[56]); + + /* output 57 */ + CARRY_FORWARD; + SQRADDSC(a[26], a[31]); SQRADDAC(a[27], a[30]); SQRADDAC(a[28], a[29]); SQRADDDB; + COMBA_STORE(b[57]); + + /* output 58 */ + CARRY_FORWARD; + SQRADD2(a[27], a[31]); SQRADD2(a[28], a[30]); SQRADD(a[29], a[29]); + COMBA_STORE(b[58]); + + /* output 59 */ + CARRY_FORWARD; + SQRADD2(a[28], a[31]); SQRADD2(a[29], a[30]); + COMBA_STORE(b[59]); + + /* output 60 */ + CARRY_FORWARD; + SQRADD2(a[29], a[31]); SQRADD(a[30], a[30]); + COMBA_STORE(b[60]); + + /* output 61 */ + CARRY_FORWARD; + SQRADD2(a[30], a[31]); + COMBA_STORE(b[61]); + + /* output 62 */ + CARRY_FORWARD; + SQRADD(a[31], a[31]); + COMBA_STORE(b[62]); + COMBA_STORE2(b[63]); + COMBA_FINI; + + B->used = 64; + B->sign = FP_ZPOS; + XMEMCPY(B->dp, b, 64 * sizeof(fp_digit)); + fp_clamp(B); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; +} +#endif + + diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_sqr_comba_4.i b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_sqr_comba_4.i new file mode 100755 index 0000000..a6f28dd --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_sqr_comba_4.i @@ -0,0 +1,97 @@ +/* fp_sqr_comba_4.i + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifdef TFM_SQR4 +int fp_sqr_comba4(fp_int *A, fp_int *B) +{ + fp_digit *a, c0, c1, c2; +#ifdef TFM_ISO + fp_word tt; +#endif +#ifndef WOLFSSL_SMALL_STACK + fp_digit b[8]; +#else + fp_digit *b; +#endif + +#ifdef WOLFSSL_SMALL_STACK + b = (fp_digit*)XMALLOC(sizeof(fp_digit) * 8, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (b == NULL) + return FP_MEM; +#endif + + a = A->dp; + COMBA_START; + + /* clear carries */ + CLEAR_CARRY; + + /* output 0 */ + SQRADD(a[0],a[0]); + COMBA_STORE(b[0]); + + /* output 1 */ + CARRY_FORWARD; + SQRADD2(a[0], a[1]); + COMBA_STORE(b[1]); + + /* output 2 */ + CARRY_FORWARD; + SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]); + COMBA_STORE(b[2]); + + /* output 3 */ + CARRY_FORWARD; + SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]); + COMBA_STORE(b[3]); + + /* output 4 */ + CARRY_FORWARD; + SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]); + COMBA_STORE(b[4]); + + /* output 5 */ + CARRY_FORWARD; + SQRADD2(a[2], a[3]); + COMBA_STORE(b[5]); + + /* output 6 */ + CARRY_FORWARD; + SQRADD(a[3], a[3]); + COMBA_STORE(b[6]); + COMBA_STORE2(b[7]); + COMBA_FINI; + + B->used = 8; + B->sign = FP_ZPOS; + XMEMCPY(B->dp, b, 8 * sizeof(fp_digit)); + fp_clamp(B); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; +} +#endif + + diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_sqr_comba_48.i b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_sqr_comba_48.i new file mode 100755 index 0000000..a00d450 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_sqr_comba_48.i @@ -0,0 +1,537 @@ +/* fp_sqr_comba_48.i + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifdef TFM_SQR48 +int fp_sqr_comba48(fp_int *A, fp_int *B) +{ + fp_digit *a, c0, c1, c2, sc0 = 0, sc1 = 0, sc2 = 0; +#ifdef TFM_ISO + fp_word tt; +#endif +#ifndef WOLFSSL_SMALL_STACK + fp_digit b[96]; +#else + fp_digit *b; +#endif + +#ifdef WOLFSSL_SMALL_STACK + b = (fp_digit*)XMALLOC(sizeof(fp_digit) * 96, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (b == NULL) + return FP_MEM; +#endif + + a = A->dp; + COMBA_START; + + /* clear carries */ + CLEAR_CARRY; + + /* output 0 */ + SQRADD(a[0],a[0]); + COMBA_STORE(b[0]); + + /* output 1 */ + CARRY_FORWARD; + SQRADD2(a[0], a[1]); + COMBA_STORE(b[1]); + + /* output 2 */ + CARRY_FORWARD; + SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]); + COMBA_STORE(b[2]); + + /* output 3 */ + CARRY_FORWARD; + SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]); + COMBA_STORE(b[3]); + + /* output 4 */ + CARRY_FORWARD; + SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]); + COMBA_STORE(b[4]); + + /* output 5 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB; + COMBA_STORE(b[5]); + + /* output 6 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]); + COMBA_STORE(b[6]); + + /* output 7 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[7]); SQRADDAC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB; + COMBA_STORE(b[7]); + + /* output 8 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[8]); SQRADDAC(a[1], a[7]); SQRADDAC(a[2], a[6]); SQRADDAC(a[3], a[5]); SQRADDDB; SQRADD(a[4], a[4]); + COMBA_STORE(b[8]); + + /* output 9 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[9]); SQRADDAC(a[1], a[8]); SQRADDAC(a[2], a[7]); SQRADDAC(a[3], a[6]); SQRADDAC(a[4], a[5]); SQRADDDB; + COMBA_STORE(b[9]); + + /* output 10 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[10]); SQRADDAC(a[1], a[9]); SQRADDAC(a[2], a[8]); SQRADDAC(a[3], a[7]); SQRADDAC(a[4], a[6]); SQRADDDB; SQRADD(a[5], a[5]); + COMBA_STORE(b[10]); + + /* output 11 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[11]); SQRADDAC(a[1], a[10]); SQRADDAC(a[2], a[9]); SQRADDAC(a[3], a[8]); SQRADDAC(a[4], a[7]); SQRADDAC(a[5], a[6]); SQRADDDB; + COMBA_STORE(b[11]); + + /* output 12 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[12]); SQRADDAC(a[1], a[11]); SQRADDAC(a[2], a[10]); SQRADDAC(a[3], a[9]); SQRADDAC(a[4], a[8]); SQRADDAC(a[5], a[7]); SQRADDDB; SQRADD(a[6], a[6]); + COMBA_STORE(b[12]); + + /* output 13 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[13]); SQRADDAC(a[1], a[12]); SQRADDAC(a[2], a[11]); SQRADDAC(a[3], a[10]); SQRADDAC(a[4], a[9]); SQRADDAC(a[5], a[8]); SQRADDAC(a[6], a[7]); SQRADDDB; + COMBA_STORE(b[13]); + + /* output 14 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[14]); SQRADDAC(a[1], a[13]); SQRADDAC(a[2], a[12]); SQRADDAC(a[3], a[11]); SQRADDAC(a[4], a[10]); SQRADDAC(a[5], a[9]); SQRADDAC(a[6], a[8]); SQRADDDB; SQRADD(a[7], a[7]); + COMBA_STORE(b[14]); + + /* output 15 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[15]); SQRADDAC(a[1], a[14]); SQRADDAC(a[2], a[13]); SQRADDAC(a[3], a[12]); SQRADDAC(a[4], a[11]); SQRADDAC(a[5], a[10]); SQRADDAC(a[6], a[9]); SQRADDAC(a[7], a[8]); SQRADDDB; + COMBA_STORE(b[15]); + + /* output 16 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[16]); SQRADDAC(a[1], a[15]); SQRADDAC(a[2], a[14]); SQRADDAC(a[3], a[13]); SQRADDAC(a[4], a[12]); SQRADDAC(a[5], a[11]); SQRADDAC(a[6], a[10]); SQRADDAC(a[7], a[9]); SQRADDDB; SQRADD(a[8], a[8]); + COMBA_STORE(b[16]); + + /* output 17 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[17]); SQRADDAC(a[1], a[16]); SQRADDAC(a[2], a[15]); SQRADDAC(a[3], a[14]); SQRADDAC(a[4], a[13]); SQRADDAC(a[5], a[12]); SQRADDAC(a[6], a[11]); SQRADDAC(a[7], a[10]); SQRADDAC(a[8], a[9]); SQRADDDB; + COMBA_STORE(b[17]); + + /* output 18 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[18]); SQRADDAC(a[1], a[17]); SQRADDAC(a[2], a[16]); SQRADDAC(a[3], a[15]); SQRADDAC(a[4], a[14]); SQRADDAC(a[5], a[13]); SQRADDAC(a[6], a[12]); SQRADDAC(a[7], a[11]); SQRADDAC(a[8], a[10]); SQRADDDB; SQRADD(a[9], a[9]); + COMBA_STORE(b[18]); + + /* output 19 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[19]); SQRADDAC(a[1], a[18]); SQRADDAC(a[2], a[17]); SQRADDAC(a[3], a[16]); SQRADDAC(a[4], a[15]); SQRADDAC(a[5], a[14]); SQRADDAC(a[6], a[13]); SQRADDAC(a[7], a[12]); SQRADDAC(a[8], a[11]); SQRADDAC(a[9], a[10]); SQRADDDB; + COMBA_STORE(b[19]); + + /* output 20 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[20]); SQRADDAC(a[1], a[19]); SQRADDAC(a[2], a[18]); SQRADDAC(a[3], a[17]); SQRADDAC(a[4], a[16]); SQRADDAC(a[5], a[15]); SQRADDAC(a[6], a[14]); SQRADDAC(a[7], a[13]); SQRADDAC(a[8], a[12]); SQRADDAC(a[9], a[11]); SQRADDDB; SQRADD(a[10], a[10]); + COMBA_STORE(b[20]); + + /* output 21 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[21]); SQRADDAC(a[1], a[20]); SQRADDAC(a[2], a[19]); SQRADDAC(a[3], a[18]); SQRADDAC(a[4], a[17]); SQRADDAC(a[5], a[16]); SQRADDAC(a[6], a[15]); SQRADDAC(a[7], a[14]); SQRADDAC(a[8], a[13]); SQRADDAC(a[9], a[12]); SQRADDAC(a[10], a[11]); SQRADDDB; + COMBA_STORE(b[21]); + + /* output 22 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[22]); SQRADDAC(a[1], a[21]); SQRADDAC(a[2], a[20]); SQRADDAC(a[3], a[19]); SQRADDAC(a[4], a[18]); SQRADDAC(a[5], a[17]); SQRADDAC(a[6], a[16]); SQRADDAC(a[7], a[15]); SQRADDAC(a[8], a[14]); SQRADDAC(a[9], a[13]); SQRADDAC(a[10], a[12]); SQRADDDB; SQRADD(a[11], a[11]); + COMBA_STORE(b[22]); + + /* output 23 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[23]); SQRADDAC(a[1], a[22]); SQRADDAC(a[2], a[21]); SQRADDAC(a[3], a[20]); SQRADDAC(a[4], a[19]); SQRADDAC(a[5], a[18]); SQRADDAC(a[6], a[17]); SQRADDAC(a[7], a[16]); SQRADDAC(a[8], a[15]); SQRADDAC(a[9], a[14]); SQRADDAC(a[10], a[13]); SQRADDAC(a[11], a[12]); SQRADDDB; + COMBA_STORE(b[23]); + + /* output 24 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[24]); SQRADDAC(a[1], a[23]); SQRADDAC(a[2], a[22]); SQRADDAC(a[3], a[21]); SQRADDAC(a[4], a[20]); SQRADDAC(a[5], a[19]); SQRADDAC(a[6], a[18]); SQRADDAC(a[7], a[17]); SQRADDAC(a[8], a[16]); SQRADDAC(a[9], a[15]); SQRADDAC(a[10], a[14]); SQRADDAC(a[11], a[13]); SQRADDDB; SQRADD(a[12], a[12]); + COMBA_STORE(b[24]); + + /* output 25 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[25]); SQRADDAC(a[1], a[24]); SQRADDAC(a[2], a[23]); SQRADDAC(a[3], a[22]); SQRADDAC(a[4], a[21]); SQRADDAC(a[5], a[20]); SQRADDAC(a[6], a[19]); SQRADDAC(a[7], a[18]); SQRADDAC(a[8], a[17]); SQRADDAC(a[9], a[16]); SQRADDAC(a[10], a[15]); SQRADDAC(a[11], a[14]); SQRADDAC(a[12], a[13]); SQRADDDB; + COMBA_STORE(b[25]); + + /* output 26 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[26]); SQRADDAC(a[1], a[25]); SQRADDAC(a[2], a[24]); SQRADDAC(a[3], a[23]); SQRADDAC(a[4], a[22]); SQRADDAC(a[5], a[21]); SQRADDAC(a[6], a[20]); SQRADDAC(a[7], a[19]); SQRADDAC(a[8], a[18]); SQRADDAC(a[9], a[17]); SQRADDAC(a[10], a[16]); SQRADDAC(a[11], a[15]); SQRADDAC(a[12], a[14]); SQRADDDB; SQRADD(a[13], a[13]); + COMBA_STORE(b[26]); + + /* output 27 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[27]); SQRADDAC(a[1], a[26]); SQRADDAC(a[2], a[25]); SQRADDAC(a[3], a[24]); SQRADDAC(a[4], a[23]); SQRADDAC(a[5], a[22]); SQRADDAC(a[6], a[21]); SQRADDAC(a[7], a[20]); SQRADDAC(a[8], a[19]); SQRADDAC(a[9], a[18]); SQRADDAC(a[10], a[17]); SQRADDAC(a[11], a[16]); SQRADDAC(a[12], a[15]); SQRADDAC(a[13], a[14]); SQRADDDB; + COMBA_STORE(b[27]); + + /* output 28 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[28]); SQRADDAC(a[1], a[27]); SQRADDAC(a[2], a[26]); SQRADDAC(a[3], a[25]); SQRADDAC(a[4], a[24]); SQRADDAC(a[5], a[23]); SQRADDAC(a[6], a[22]); SQRADDAC(a[7], a[21]); SQRADDAC(a[8], a[20]); SQRADDAC(a[9], a[19]); SQRADDAC(a[10], a[18]); SQRADDAC(a[11], a[17]); SQRADDAC(a[12], a[16]); SQRADDAC(a[13], a[15]); SQRADDDB; SQRADD(a[14], a[14]); + COMBA_STORE(b[28]); + + /* output 29 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[29]); SQRADDAC(a[1], a[28]); SQRADDAC(a[2], a[27]); SQRADDAC(a[3], a[26]); SQRADDAC(a[4], a[25]); SQRADDAC(a[5], a[24]); SQRADDAC(a[6], a[23]); SQRADDAC(a[7], a[22]); SQRADDAC(a[8], a[21]); SQRADDAC(a[9], a[20]); SQRADDAC(a[10], a[19]); SQRADDAC(a[11], a[18]); SQRADDAC(a[12], a[17]); SQRADDAC(a[13], a[16]); SQRADDAC(a[14], a[15]); SQRADDDB; + COMBA_STORE(b[29]); + + /* output 30 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[30]); SQRADDAC(a[1], a[29]); SQRADDAC(a[2], a[28]); SQRADDAC(a[3], a[27]); SQRADDAC(a[4], a[26]); SQRADDAC(a[5], a[25]); SQRADDAC(a[6], a[24]); SQRADDAC(a[7], a[23]); SQRADDAC(a[8], a[22]); SQRADDAC(a[9], a[21]); SQRADDAC(a[10], a[20]); SQRADDAC(a[11], a[19]); SQRADDAC(a[12], a[18]); SQRADDAC(a[13], a[17]); SQRADDAC(a[14], a[16]); SQRADDDB; SQRADD(a[15], a[15]); + COMBA_STORE(b[30]); + + /* output 31 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[31]); SQRADDAC(a[1], a[30]); SQRADDAC(a[2], a[29]); SQRADDAC(a[3], a[28]); SQRADDAC(a[4], a[27]); SQRADDAC(a[5], a[26]); SQRADDAC(a[6], a[25]); SQRADDAC(a[7], a[24]); SQRADDAC(a[8], a[23]); SQRADDAC(a[9], a[22]); SQRADDAC(a[10], a[21]); SQRADDAC(a[11], a[20]); SQRADDAC(a[12], a[19]); SQRADDAC(a[13], a[18]); SQRADDAC(a[14], a[17]); SQRADDAC(a[15], a[16]); SQRADDDB; + COMBA_STORE(b[31]); + + /* output 32 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[32]); SQRADDAC(a[1], a[31]); SQRADDAC(a[2], a[30]); SQRADDAC(a[3], a[29]); SQRADDAC(a[4], a[28]); SQRADDAC(a[5], a[27]); SQRADDAC(a[6], a[26]); SQRADDAC(a[7], a[25]); SQRADDAC(a[8], a[24]); SQRADDAC(a[9], a[23]); SQRADDAC(a[10], a[22]); SQRADDAC(a[11], a[21]); SQRADDAC(a[12], a[20]); SQRADDAC(a[13], a[19]); SQRADDAC(a[14], a[18]); SQRADDAC(a[15], a[17]); SQRADDDB; SQRADD(a[16], a[16]); + COMBA_STORE(b[32]); + + /* output 33 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[33]); SQRADDAC(a[1], a[32]); SQRADDAC(a[2], a[31]); SQRADDAC(a[3], a[30]); SQRADDAC(a[4], a[29]); SQRADDAC(a[5], a[28]); SQRADDAC(a[6], a[27]); SQRADDAC(a[7], a[26]); SQRADDAC(a[8], a[25]); SQRADDAC(a[9], a[24]); SQRADDAC(a[10], a[23]); SQRADDAC(a[11], a[22]); SQRADDAC(a[12], a[21]); SQRADDAC(a[13], a[20]); SQRADDAC(a[14], a[19]); SQRADDAC(a[15], a[18]); SQRADDAC(a[16], a[17]); SQRADDDB; + COMBA_STORE(b[33]); + + /* output 34 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[34]); SQRADDAC(a[1], a[33]); SQRADDAC(a[2], a[32]); SQRADDAC(a[3], a[31]); SQRADDAC(a[4], a[30]); SQRADDAC(a[5], a[29]); SQRADDAC(a[6], a[28]); SQRADDAC(a[7], a[27]); SQRADDAC(a[8], a[26]); SQRADDAC(a[9], a[25]); SQRADDAC(a[10], a[24]); SQRADDAC(a[11], a[23]); SQRADDAC(a[12], a[22]); SQRADDAC(a[13], a[21]); SQRADDAC(a[14], a[20]); SQRADDAC(a[15], a[19]); SQRADDAC(a[16], a[18]); SQRADDDB; SQRADD(a[17], a[17]); + COMBA_STORE(b[34]); + + /* output 35 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[35]); SQRADDAC(a[1], a[34]); SQRADDAC(a[2], a[33]); SQRADDAC(a[3], a[32]); SQRADDAC(a[4], a[31]); SQRADDAC(a[5], a[30]); SQRADDAC(a[6], a[29]); SQRADDAC(a[7], a[28]); SQRADDAC(a[8], a[27]); SQRADDAC(a[9], a[26]); SQRADDAC(a[10], a[25]); SQRADDAC(a[11], a[24]); SQRADDAC(a[12], a[23]); SQRADDAC(a[13], a[22]); SQRADDAC(a[14], a[21]); SQRADDAC(a[15], a[20]); SQRADDAC(a[16], a[19]); SQRADDAC(a[17], a[18]); SQRADDDB; + COMBA_STORE(b[35]); + + /* output 36 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[36]); SQRADDAC(a[1], a[35]); SQRADDAC(a[2], a[34]); SQRADDAC(a[3], a[33]); SQRADDAC(a[4], a[32]); SQRADDAC(a[5], a[31]); SQRADDAC(a[6], a[30]); SQRADDAC(a[7], a[29]); SQRADDAC(a[8], a[28]); SQRADDAC(a[9], a[27]); SQRADDAC(a[10], a[26]); SQRADDAC(a[11], a[25]); SQRADDAC(a[12], a[24]); SQRADDAC(a[13], a[23]); SQRADDAC(a[14], a[22]); SQRADDAC(a[15], a[21]); SQRADDAC(a[16], a[20]); SQRADDAC(a[17], a[19]); SQRADDDB; SQRADD(a[18], a[18]); + COMBA_STORE(b[36]); + + /* output 37 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[37]); SQRADDAC(a[1], a[36]); SQRADDAC(a[2], a[35]); SQRADDAC(a[3], a[34]); SQRADDAC(a[4], a[33]); SQRADDAC(a[5], a[32]); SQRADDAC(a[6], a[31]); SQRADDAC(a[7], a[30]); SQRADDAC(a[8], a[29]); SQRADDAC(a[9], a[28]); SQRADDAC(a[10], a[27]); SQRADDAC(a[11], a[26]); SQRADDAC(a[12], a[25]); SQRADDAC(a[13], a[24]); SQRADDAC(a[14], a[23]); SQRADDAC(a[15], a[22]); SQRADDAC(a[16], a[21]); SQRADDAC(a[17], a[20]); SQRADDAC(a[18], a[19]); SQRADDDB; + COMBA_STORE(b[37]); + + /* output 38 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[38]); SQRADDAC(a[1], a[37]); SQRADDAC(a[2], a[36]); SQRADDAC(a[3], a[35]); SQRADDAC(a[4], a[34]); SQRADDAC(a[5], a[33]); SQRADDAC(a[6], a[32]); SQRADDAC(a[7], a[31]); SQRADDAC(a[8], a[30]); SQRADDAC(a[9], a[29]); SQRADDAC(a[10], a[28]); SQRADDAC(a[11], a[27]); SQRADDAC(a[12], a[26]); SQRADDAC(a[13], a[25]); SQRADDAC(a[14], a[24]); SQRADDAC(a[15], a[23]); SQRADDAC(a[16], a[22]); SQRADDAC(a[17], a[21]); SQRADDAC(a[18], a[20]); SQRADDDB; SQRADD(a[19], a[19]); + COMBA_STORE(b[38]); + + /* output 39 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[39]); SQRADDAC(a[1], a[38]); SQRADDAC(a[2], a[37]); SQRADDAC(a[3], a[36]); SQRADDAC(a[4], a[35]); SQRADDAC(a[5], a[34]); SQRADDAC(a[6], a[33]); SQRADDAC(a[7], a[32]); SQRADDAC(a[8], a[31]); SQRADDAC(a[9], a[30]); SQRADDAC(a[10], a[29]); SQRADDAC(a[11], a[28]); SQRADDAC(a[12], a[27]); SQRADDAC(a[13], a[26]); SQRADDAC(a[14], a[25]); SQRADDAC(a[15], a[24]); SQRADDAC(a[16], a[23]); SQRADDAC(a[17], a[22]); SQRADDAC(a[18], a[21]); SQRADDAC(a[19], a[20]); SQRADDDB; + COMBA_STORE(b[39]); + + /* output 40 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[40]); SQRADDAC(a[1], a[39]); SQRADDAC(a[2], a[38]); SQRADDAC(a[3], a[37]); SQRADDAC(a[4], a[36]); SQRADDAC(a[5], a[35]); SQRADDAC(a[6], a[34]); SQRADDAC(a[7], a[33]); SQRADDAC(a[8], a[32]); SQRADDAC(a[9], a[31]); SQRADDAC(a[10], a[30]); SQRADDAC(a[11], a[29]); SQRADDAC(a[12], a[28]); SQRADDAC(a[13], a[27]); SQRADDAC(a[14], a[26]); SQRADDAC(a[15], a[25]); SQRADDAC(a[16], a[24]); SQRADDAC(a[17], a[23]); SQRADDAC(a[18], a[22]); SQRADDAC(a[19], a[21]); SQRADDDB; SQRADD(a[20], a[20]); + COMBA_STORE(b[40]); + + /* output 41 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[41]); SQRADDAC(a[1], a[40]); SQRADDAC(a[2], a[39]); SQRADDAC(a[3], a[38]); SQRADDAC(a[4], a[37]); SQRADDAC(a[5], a[36]); SQRADDAC(a[6], a[35]); SQRADDAC(a[7], a[34]); SQRADDAC(a[8], a[33]); SQRADDAC(a[9], a[32]); SQRADDAC(a[10], a[31]); SQRADDAC(a[11], a[30]); SQRADDAC(a[12], a[29]); SQRADDAC(a[13], a[28]); SQRADDAC(a[14], a[27]); SQRADDAC(a[15], a[26]); SQRADDAC(a[16], a[25]); SQRADDAC(a[17], a[24]); SQRADDAC(a[18], a[23]); SQRADDAC(a[19], a[22]); SQRADDAC(a[20], a[21]); SQRADDDB; + COMBA_STORE(b[41]); + + /* output 42 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[42]); SQRADDAC(a[1], a[41]); SQRADDAC(a[2], a[40]); SQRADDAC(a[3], a[39]); SQRADDAC(a[4], a[38]); SQRADDAC(a[5], a[37]); SQRADDAC(a[6], a[36]); SQRADDAC(a[7], a[35]); SQRADDAC(a[8], a[34]); SQRADDAC(a[9], a[33]); SQRADDAC(a[10], a[32]); SQRADDAC(a[11], a[31]); SQRADDAC(a[12], a[30]); SQRADDAC(a[13], a[29]); SQRADDAC(a[14], a[28]); SQRADDAC(a[15], a[27]); SQRADDAC(a[16], a[26]); SQRADDAC(a[17], a[25]); SQRADDAC(a[18], a[24]); SQRADDAC(a[19], a[23]); SQRADDAC(a[20], a[22]); SQRADDDB; SQRADD(a[21], a[21]); + COMBA_STORE(b[42]); + + /* output 43 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[43]); SQRADDAC(a[1], a[42]); SQRADDAC(a[2], a[41]); SQRADDAC(a[3], a[40]); SQRADDAC(a[4], a[39]); SQRADDAC(a[5], a[38]); SQRADDAC(a[6], a[37]); SQRADDAC(a[7], a[36]); SQRADDAC(a[8], a[35]); SQRADDAC(a[9], a[34]); SQRADDAC(a[10], a[33]); SQRADDAC(a[11], a[32]); SQRADDAC(a[12], a[31]); SQRADDAC(a[13], a[30]); SQRADDAC(a[14], a[29]); SQRADDAC(a[15], a[28]); SQRADDAC(a[16], a[27]); SQRADDAC(a[17], a[26]); SQRADDAC(a[18], a[25]); SQRADDAC(a[19], a[24]); SQRADDAC(a[20], a[23]); SQRADDAC(a[21], a[22]); SQRADDDB; + COMBA_STORE(b[43]); + + /* output 44 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[44]); SQRADDAC(a[1], a[43]); SQRADDAC(a[2], a[42]); SQRADDAC(a[3], a[41]); SQRADDAC(a[4], a[40]); SQRADDAC(a[5], a[39]); SQRADDAC(a[6], a[38]); SQRADDAC(a[7], a[37]); SQRADDAC(a[8], a[36]); SQRADDAC(a[9], a[35]); SQRADDAC(a[10], a[34]); SQRADDAC(a[11], a[33]); SQRADDAC(a[12], a[32]); SQRADDAC(a[13], a[31]); SQRADDAC(a[14], a[30]); SQRADDAC(a[15], a[29]); SQRADDAC(a[16], a[28]); SQRADDAC(a[17], a[27]); SQRADDAC(a[18], a[26]); SQRADDAC(a[19], a[25]); SQRADDAC(a[20], a[24]); SQRADDAC(a[21], a[23]); SQRADDDB; SQRADD(a[22], a[22]); + COMBA_STORE(b[44]); + + /* output 45 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[45]); SQRADDAC(a[1], a[44]); SQRADDAC(a[2], a[43]); SQRADDAC(a[3], a[42]); SQRADDAC(a[4], a[41]); SQRADDAC(a[5], a[40]); SQRADDAC(a[6], a[39]); SQRADDAC(a[7], a[38]); SQRADDAC(a[8], a[37]); SQRADDAC(a[9], a[36]); SQRADDAC(a[10], a[35]); SQRADDAC(a[11], a[34]); SQRADDAC(a[12], a[33]); SQRADDAC(a[13], a[32]); SQRADDAC(a[14], a[31]); SQRADDAC(a[15], a[30]); SQRADDAC(a[16], a[29]); SQRADDAC(a[17], a[28]); SQRADDAC(a[18], a[27]); SQRADDAC(a[19], a[26]); SQRADDAC(a[20], a[25]); SQRADDAC(a[21], a[24]); SQRADDAC(a[22], a[23]); SQRADDDB; + COMBA_STORE(b[45]); + + /* output 46 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[46]); SQRADDAC(a[1], a[45]); SQRADDAC(a[2], a[44]); SQRADDAC(a[3], a[43]); SQRADDAC(a[4], a[42]); SQRADDAC(a[5], a[41]); SQRADDAC(a[6], a[40]); SQRADDAC(a[7], a[39]); SQRADDAC(a[8], a[38]); SQRADDAC(a[9], a[37]); SQRADDAC(a[10], a[36]); SQRADDAC(a[11], a[35]); SQRADDAC(a[12], a[34]); SQRADDAC(a[13], a[33]); SQRADDAC(a[14], a[32]); SQRADDAC(a[15], a[31]); SQRADDAC(a[16], a[30]); SQRADDAC(a[17], a[29]); SQRADDAC(a[18], a[28]); SQRADDAC(a[19], a[27]); SQRADDAC(a[20], a[26]); SQRADDAC(a[21], a[25]); SQRADDAC(a[22], a[24]); SQRADDDB; SQRADD(a[23], a[23]); + COMBA_STORE(b[46]); + + /* output 47 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[47]); SQRADDAC(a[1], a[46]); SQRADDAC(a[2], a[45]); SQRADDAC(a[3], a[44]); SQRADDAC(a[4], a[43]); SQRADDAC(a[5], a[42]); SQRADDAC(a[6], a[41]); SQRADDAC(a[7], a[40]); SQRADDAC(a[8], a[39]); SQRADDAC(a[9], a[38]); SQRADDAC(a[10], a[37]); SQRADDAC(a[11], a[36]); SQRADDAC(a[12], a[35]); SQRADDAC(a[13], a[34]); SQRADDAC(a[14], a[33]); SQRADDAC(a[15], a[32]); SQRADDAC(a[16], a[31]); SQRADDAC(a[17], a[30]); SQRADDAC(a[18], a[29]); SQRADDAC(a[19], a[28]); SQRADDAC(a[20], a[27]); SQRADDAC(a[21], a[26]); SQRADDAC(a[22], a[25]); SQRADDAC(a[23], a[24]); SQRADDDB; + COMBA_STORE(b[47]); + + /* output 48 */ + CARRY_FORWARD; + SQRADDSC(a[1], a[47]); SQRADDAC(a[2], a[46]); SQRADDAC(a[3], a[45]); SQRADDAC(a[4], a[44]); SQRADDAC(a[5], a[43]); SQRADDAC(a[6], a[42]); SQRADDAC(a[7], a[41]); SQRADDAC(a[8], a[40]); SQRADDAC(a[9], a[39]); SQRADDAC(a[10], a[38]); SQRADDAC(a[11], a[37]); SQRADDAC(a[12], a[36]); SQRADDAC(a[13], a[35]); SQRADDAC(a[14], a[34]); SQRADDAC(a[15], a[33]); SQRADDAC(a[16], a[32]); SQRADDAC(a[17], a[31]); SQRADDAC(a[18], a[30]); SQRADDAC(a[19], a[29]); SQRADDAC(a[20], a[28]); SQRADDAC(a[21], a[27]); SQRADDAC(a[22], a[26]); SQRADDAC(a[23], a[25]); SQRADDDB; SQRADD(a[24], a[24]); + COMBA_STORE(b[48]); + + /* output 49 */ + CARRY_FORWARD; + SQRADDSC(a[2], a[47]); SQRADDAC(a[3], a[46]); SQRADDAC(a[4], a[45]); SQRADDAC(a[5], a[44]); SQRADDAC(a[6], a[43]); SQRADDAC(a[7], a[42]); SQRADDAC(a[8], a[41]); SQRADDAC(a[9], a[40]); SQRADDAC(a[10], a[39]); SQRADDAC(a[11], a[38]); SQRADDAC(a[12], a[37]); SQRADDAC(a[13], a[36]); SQRADDAC(a[14], a[35]); SQRADDAC(a[15], a[34]); SQRADDAC(a[16], a[33]); SQRADDAC(a[17], a[32]); SQRADDAC(a[18], a[31]); SQRADDAC(a[19], a[30]); SQRADDAC(a[20], a[29]); SQRADDAC(a[21], a[28]); SQRADDAC(a[22], a[27]); SQRADDAC(a[23], a[26]); SQRADDAC(a[24], a[25]); SQRADDDB; + COMBA_STORE(b[49]); + + /* output 50 */ + CARRY_FORWARD; + SQRADDSC(a[3], a[47]); SQRADDAC(a[4], a[46]); SQRADDAC(a[5], a[45]); SQRADDAC(a[6], a[44]); SQRADDAC(a[7], a[43]); SQRADDAC(a[8], a[42]); SQRADDAC(a[9], a[41]); SQRADDAC(a[10], a[40]); SQRADDAC(a[11], a[39]); SQRADDAC(a[12], a[38]); SQRADDAC(a[13], a[37]); SQRADDAC(a[14], a[36]); SQRADDAC(a[15], a[35]); SQRADDAC(a[16], a[34]); SQRADDAC(a[17], a[33]); SQRADDAC(a[18], a[32]); SQRADDAC(a[19], a[31]); SQRADDAC(a[20], a[30]); SQRADDAC(a[21], a[29]); SQRADDAC(a[22], a[28]); SQRADDAC(a[23], a[27]); SQRADDAC(a[24], a[26]); SQRADDDB; SQRADD(a[25], a[25]); + COMBA_STORE(b[50]); + + /* output 51 */ + CARRY_FORWARD; + SQRADDSC(a[4], a[47]); SQRADDAC(a[5], a[46]); SQRADDAC(a[6], a[45]); SQRADDAC(a[7], a[44]); SQRADDAC(a[8], a[43]); SQRADDAC(a[9], a[42]); SQRADDAC(a[10], a[41]); SQRADDAC(a[11], a[40]); SQRADDAC(a[12], a[39]); SQRADDAC(a[13], a[38]); SQRADDAC(a[14], a[37]); SQRADDAC(a[15], a[36]); SQRADDAC(a[16], a[35]); SQRADDAC(a[17], a[34]); SQRADDAC(a[18], a[33]); SQRADDAC(a[19], a[32]); SQRADDAC(a[20], a[31]); SQRADDAC(a[21], a[30]); SQRADDAC(a[22], a[29]); SQRADDAC(a[23], a[28]); SQRADDAC(a[24], a[27]); SQRADDAC(a[25], a[26]); SQRADDDB; + COMBA_STORE(b[51]); + + /* output 52 */ + CARRY_FORWARD; + SQRADDSC(a[5], a[47]); SQRADDAC(a[6], a[46]); SQRADDAC(a[7], a[45]); SQRADDAC(a[8], a[44]); SQRADDAC(a[9], a[43]); SQRADDAC(a[10], a[42]); SQRADDAC(a[11], a[41]); SQRADDAC(a[12], a[40]); SQRADDAC(a[13], a[39]); SQRADDAC(a[14], a[38]); SQRADDAC(a[15], a[37]); SQRADDAC(a[16], a[36]); SQRADDAC(a[17], a[35]); SQRADDAC(a[18], a[34]); SQRADDAC(a[19], a[33]); SQRADDAC(a[20], a[32]); SQRADDAC(a[21], a[31]); SQRADDAC(a[22], a[30]); SQRADDAC(a[23], a[29]); SQRADDAC(a[24], a[28]); SQRADDAC(a[25], a[27]); SQRADDDB; SQRADD(a[26], a[26]); + COMBA_STORE(b[52]); + + /* output 53 */ + CARRY_FORWARD; + SQRADDSC(a[6], a[47]); SQRADDAC(a[7], a[46]); SQRADDAC(a[8], a[45]); SQRADDAC(a[9], a[44]); SQRADDAC(a[10], a[43]); SQRADDAC(a[11], a[42]); SQRADDAC(a[12], a[41]); SQRADDAC(a[13], a[40]); SQRADDAC(a[14], a[39]); SQRADDAC(a[15], a[38]); SQRADDAC(a[16], a[37]); SQRADDAC(a[17], a[36]); SQRADDAC(a[18], a[35]); SQRADDAC(a[19], a[34]); SQRADDAC(a[20], a[33]); SQRADDAC(a[21], a[32]); SQRADDAC(a[22], a[31]); SQRADDAC(a[23], a[30]); SQRADDAC(a[24], a[29]); SQRADDAC(a[25], a[28]); SQRADDAC(a[26], a[27]); SQRADDDB; + COMBA_STORE(b[53]); + + /* output 54 */ + CARRY_FORWARD; + SQRADDSC(a[7], a[47]); SQRADDAC(a[8], a[46]); SQRADDAC(a[9], a[45]); SQRADDAC(a[10], a[44]); SQRADDAC(a[11], a[43]); SQRADDAC(a[12], a[42]); SQRADDAC(a[13], a[41]); SQRADDAC(a[14], a[40]); SQRADDAC(a[15], a[39]); SQRADDAC(a[16], a[38]); SQRADDAC(a[17], a[37]); SQRADDAC(a[18], a[36]); SQRADDAC(a[19], a[35]); SQRADDAC(a[20], a[34]); SQRADDAC(a[21], a[33]); SQRADDAC(a[22], a[32]); SQRADDAC(a[23], a[31]); SQRADDAC(a[24], a[30]); SQRADDAC(a[25], a[29]); SQRADDAC(a[26], a[28]); SQRADDDB; SQRADD(a[27], a[27]); + COMBA_STORE(b[54]); + + /* output 55 */ + CARRY_FORWARD; + SQRADDSC(a[8], a[47]); SQRADDAC(a[9], a[46]); SQRADDAC(a[10], a[45]); SQRADDAC(a[11], a[44]); SQRADDAC(a[12], a[43]); SQRADDAC(a[13], a[42]); SQRADDAC(a[14], a[41]); SQRADDAC(a[15], a[40]); SQRADDAC(a[16], a[39]); SQRADDAC(a[17], a[38]); SQRADDAC(a[18], a[37]); SQRADDAC(a[19], a[36]); SQRADDAC(a[20], a[35]); SQRADDAC(a[21], a[34]); SQRADDAC(a[22], a[33]); SQRADDAC(a[23], a[32]); SQRADDAC(a[24], a[31]); SQRADDAC(a[25], a[30]); SQRADDAC(a[26], a[29]); SQRADDAC(a[27], a[28]); SQRADDDB; + COMBA_STORE(b[55]); + + /* output 56 */ + CARRY_FORWARD; + SQRADDSC(a[9], a[47]); SQRADDAC(a[10], a[46]); SQRADDAC(a[11], a[45]); SQRADDAC(a[12], a[44]); SQRADDAC(a[13], a[43]); SQRADDAC(a[14], a[42]); SQRADDAC(a[15], a[41]); SQRADDAC(a[16], a[40]); SQRADDAC(a[17], a[39]); SQRADDAC(a[18], a[38]); SQRADDAC(a[19], a[37]); SQRADDAC(a[20], a[36]); SQRADDAC(a[21], a[35]); SQRADDAC(a[22], a[34]); SQRADDAC(a[23], a[33]); SQRADDAC(a[24], a[32]); SQRADDAC(a[25], a[31]); SQRADDAC(a[26], a[30]); SQRADDAC(a[27], a[29]); SQRADDDB; SQRADD(a[28], a[28]); + COMBA_STORE(b[56]); + + /* output 57 */ + CARRY_FORWARD; + SQRADDSC(a[10], a[47]); SQRADDAC(a[11], a[46]); SQRADDAC(a[12], a[45]); SQRADDAC(a[13], a[44]); SQRADDAC(a[14], a[43]); SQRADDAC(a[15], a[42]); SQRADDAC(a[16], a[41]); SQRADDAC(a[17], a[40]); SQRADDAC(a[18], a[39]); SQRADDAC(a[19], a[38]); SQRADDAC(a[20], a[37]); SQRADDAC(a[21], a[36]); SQRADDAC(a[22], a[35]); SQRADDAC(a[23], a[34]); SQRADDAC(a[24], a[33]); SQRADDAC(a[25], a[32]); SQRADDAC(a[26], a[31]); SQRADDAC(a[27], a[30]); SQRADDAC(a[28], a[29]); SQRADDDB; + COMBA_STORE(b[57]); + + /* output 58 */ + CARRY_FORWARD; + SQRADDSC(a[11], a[47]); SQRADDAC(a[12], a[46]); SQRADDAC(a[13], a[45]); SQRADDAC(a[14], a[44]); SQRADDAC(a[15], a[43]); SQRADDAC(a[16], a[42]); SQRADDAC(a[17], a[41]); SQRADDAC(a[18], a[40]); SQRADDAC(a[19], a[39]); SQRADDAC(a[20], a[38]); SQRADDAC(a[21], a[37]); SQRADDAC(a[22], a[36]); SQRADDAC(a[23], a[35]); SQRADDAC(a[24], a[34]); SQRADDAC(a[25], a[33]); SQRADDAC(a[26], a[32]); SQRADDAC(a[27], a[31]); SQRADDAC(a[28], a[30]); SQRADDDB; SQRADD(a[29], a[29]); + COMBA_STORE(b[58]); + + /* output 59 */ + CARRY_FORWARD; + SQRADDSC(a[12], a[47]); SQRADDAC(a[13], a[46]); SQRADDAC(a[14], a[45]); SQRADDAC(a[15], a[44]); SQRADDAC(a[16], a[43]); SQRADDAC(a[17], a[42]); SQRADDAC(a[18], a[41]); SQRADDAC(a[19], a[40]); SQRADDAC(a[20], a[39]); SQRADDAC(a[21], a[38]); SQRADDAC(a[22], a[37]); SQRADDAC(a[23], a[36]); SQRADDAC(a[24], a[35]); SQRADDAC(a[25], a[34]); SQRADDAC(a[26], a[33]); SQRADDAC(a[27], a[32]); SQRADDAC(a[28], a[31]); SQRADDAC(a[29], a[30]); SQRADDDB; + COMBA_STORE(b[59]); + + /* output 60 */ + CARRY_FORWARD; + SQRADDSC(a[13], a[47]); SQRADDAC(a[14], a[46]); SQRADDAC(a[15], a[45]); SQRADDAC(a[16], a[44]); SQRADDAC(a[17], a[43]); SQRADDAC(a[18], a[42]); SQRADDAC(a[19], a[41]); SQRADDAC(a[20], a[40]); SQRADDAC(a[21], a[39]); SQRADDAC(a[22], a[38]); SQRADDAC(a[23], a[37]); SQRADDAC(a[24], a[36]); SQRADDAC(a[25], a[35]); SQRADDAC(a[26], a[34]); SQRADDAC(a[27], a[33]); SQRADDAC(a[28], a[32]); SQRADDAC(a[29], a[31]); SQRADDDB; SQRADD(a[30], a[30]); + COMBA_STORE(b[60]); + + /* output 61 */ + CARRY_FORWARD; + SQRADDSC(a[14], a[47]); SQRADDAC(a[15], a[46]); SQRADDAC(a[16], a[45]); SQRADDAC(a[17], a[44]); SQRADDAC(a[18], a[43]); SQRADDAC(a[19], a[42]); SQRADDAC(a[20], a[41]); SQRADDAC(a[21], a[40]); SQRADDAC(a[22], a[39]); SQRADDAC(a[23], a[38]); SQRADDAC(a[24], a[37]); SQRADDAC(a[25], a[36]); SQRADDAC(a[26], a[35]); SQRADDAC(a[27], a[34]); SQRADDAC(a[28], a[33]); SQRADDAC(a[29], a[32]); SQRADDAC(a[30], a[31]); SQRADDDB; + COMBA_STORE(b[61]); + + /* output 62 */ + CARRY_FORWARD; + SQRADDSC(a[15], a[47]); SQRADDAC(a[16], a[46]); SQRADDAC(a[17], a[45]); SQRADDAC(a[18], a[44]); SQRADDAC(a[19], a[43]); SQRADDAC(a[20], a[42]); SQRADDAC(a[21], a[41]); SQRADDAC(a[22], a[40]); SQRADDAC(a[23], a[39]); SQRADDAC(a[24], a[38]); SQRADDAC(a[25], a[37]); SQRADDAC(a[26], a[36]); SQRADDAC(a[27], a[35]); SQRADDAC(a[28], a[34]); SQRADDAC(a[29], a[33]); SQRADDAC(a[30], a[32]); SQRADDDB; SQRADD(a[31], a[31]); + COMBA_STORE(b[62]); + + /* output 63 */ + CARRY_FORWARD; + SQRADDSC(a[16], a[47]); SQRADDAC(a[17], a[46]); SQRADDAC(a[18], a[45]); SQRADDAC(a[19], a[44]); SQRADDAC(a[20], a[43]); SQRADDAC(a[21], a[42]); SQRADDAC(a[22], a[41]); SQRADDAC(a[23], a[40]); SQRADDAC(a[24], a[39]); SQRADDAC(a[25], a[38]); SQRADDAC(a[26], a[37]); SQRADDAC(a[27], a[36]); SQRADDAC(a[28], a[35]); SQRADDAC(a[29], a[34]); SQRADDAC(a[30], a[33]); SQRADDAC(a[31], a[32]); SQRADDDB; + COMBA_STORE(b[63]); + + /* output 64 */ + CARRY_FORWARD; + SQRADDSC(a[17], a[47]); SQRADDAC(a[18], a[46]); SQRADDAC(a[19], a[45]); SQRADDAC(a[20], a[44]); SQRADDAC(a[21], a[43]); SQRADDAC(a[22], a[42]); SQRADDAC(a[23], a[41]); SQRADDAC(a[24], a[40]); SQRADDAC(a[25], a[39]); SQRADDAC(a[26], a[38]); SQRADDAC(a[27], a[37]); SQRADDAC(a[28], a[36]); SQRADDAC(a[29], a[35]); SQRADDAC(a[30], a[34]); SQRADDAC(a[31], a[33]); SQRADDDB; SQRADD(a[32], a[32]); + COMBA_STORE(b[64]); + + /* output 65 */ + CARRY_FORWARD; + SQRADDSC(a[18], a[47]); SQRADDAC(a[19], a[46]); SQRADDAC(a[20], a[45]); SQRADDAC(a[21], a[44]); SQRADDAC(a[22], a[43]); SQRADDAC(a[23], a[42]); SQRADDAC(a[24], a[41]); SQRADDAC(a[25], a[40]); SQRADDAC(a[26], a[39]); SQRADDAC(a[27], a[38]); SQRADDAC(a[28], a[37]); SQRADDAC(a[29], a[36]); SQRADDAC(a[30], a[35]); SQRADDAC(a[31], a[34]); SQRADDAC(a[32], a[33]); SQRADDDB; + COMBA_STORE(b[65]); + + /* output 66 */ + CARRY_FORWARD; + SQRADDSC(a[19], a[47]); SQRADDAC(a[20], a[46]); SQRADDAC(a[21], a[45]); SQRADDAC(a[22], a[44]); SQRADDAC(a[23], a[43]); SQRADDAC(a[24], a[42]); SQRADDAC(a[25], a[41]); SQRADDAC(a[26], a[40]); SQRADDAC(a[27], a[39]); SQRADDAC(a[28], a[38]); SQRADDAC(a[29], a[37]); SQRADDAC(a[30], a[36]); SQRADDAC(a[31], a[35]); SQRADDAC(a[32], a[34]); SQRADDDB; SQRADD(a[33], a[33]); + COMBA_STORE(b[66]); + + /* output 67 */ + CARRY_FORWARD; + SQRADDSC(a[20], a[47]); SQRADDAC(a[21], a[46]); SQRADDAC(a[22], a[45]); SQRADDAC(a[23], a[44]); SQRADDAC(a[24], a[43]); SQRADDAC(a[25], a[42]); SQRADDAC(a[26], a[41]); SQRADDAC(a[27], a[40]); SQRADDAC(a[28], a[39]); SQRADDAC(a[29], a[38]); SQRADDAC(a[30], a[37]); SQRADDAC(a[31], a[36]); SQRADDAC(a[32], a[35]); SQRADDAC(a[33], a[34]); SQRADDDB; + COMBA_STORE(b[67]); + + /* output 68 */ + CARRY_FORWARD; + SQRADDSC(a[21], a[47]); SQRADDAC(a[22], a[46]); SQRADDAC(a[23], a[45]); SQRADDAC(a[24], a[44]); SQRADDAC(a[25], a[43]); SQRADDAC(a[26], a[42]); SQRADDAC(a[27], a[41]); SQRADDAC(a[28], a[40]); SQRADDAC(a[29], a[39]); SQRADDAC(a[30], a[38]); SQRADDAC(a[31], a[37]); SQRADDAC(a[32], a[36]); SQRADDAC(a[33], a[35]); SQRADDDB; SQRADD(a[34], a[34]); + COMBA_STORE(b[68]); + + /* output 69 */ + CARRY_FORWARD; + SQRADDSC(a[22], a[47]); SQRADDAC(a[23], a[46]); SQRADDAC(a[24], a[45]); SQRADDAC(a[25], a[44]); SQRADDAC(a[26], a[43]); SQRADDAC(a[27], a[42]); SQRADDAC(a[28], a[41]); SQRADDAC(a[29], a[40]); SQRADDAC(a[30], a[39]); SQRADDAC(a[31], a[38]); SQRADDAC(a[32], a[37]); SQRADDAC(a[33], a[36]); SQRADDAC(a[34], a[35]); SQRADDDB; + COMBA_STORE(b[69]); + + /* output 70 */ + CARRY_FORWARD; + SQRADDSC(a[23], a[47]); SQRADDAC(a[24], a[46]); SQRADDAC(a[25], a[45]); SQRADDAC(a[26], a[44]); SQRADDAC(a[27], a[43]); SQRADDAC(a[28], a[42]); SQRADDAC(a[29], a[41]); SQRADDAC(a[30], a[40]); SQRADDAC(a[31], a[39]); SQRADDAC(a[32], a[38]); SQRADDAC(a[33], a[37]); SQRADDAC(a[34], a[36]); SQRADDDB; SQRADD(a[35], a[35]); + COMBA_STORE(b[70]); + + /* output 71 */ + CARRY_FORWARD; + SQRADDSC(a[24], a[47]); SQRADDAC(a[25], a[46]); SQRADDAC(a[26], a[45]); SQRADDAC(a[27], a[44]); SQRADDAC(a[28], a[43]); SQRADDAC(a[29], a[42]); SQRADDAC(a[30], a[41]); SQRADDAC(a[31], a[40]); SQRADDAC(a[32], a[39]); SQRADDAC(a[33], a[38]); SQRADDAC(a[34], a[37]); SQRADDAC(a[35], a[36]); SQRADDDB; + COMBA_STORE(b[71]); + + /* output 72 */ + CARRY_FORWARD; + SQRADDSC(a[25], a[47]); SQRADDAC(a[26], a[46]); SQRADDAC(a[27], a[45]); SQRADDAC(a[28], a[44]); SQRADDAC(a[29], a[43]); SQRADDAC(a[30], a[42]); SQRADDAC(a[31], a[41]); SQRADDAC(a[32], a[40]); SQRADDAC(a[33], a[39]); SQRADDAC(a[34], a[38]); SQRADDAC(a[35], a[37]); SQRADDDB; SQRADD(a[36], a[36]); + COMBA_STORE(b[72]); + + /* output 73 */ + CARRY_FORWARD; + SQRADDSC(a[26], a[47]); SQRADDAC(a[27], a[46]); SQRADDAC(a[28], a[45]); SQRADDAC(a[29], a[44]); SQRADDAC(a[30], a[43]); SQRADDAC(a[31], a[42]); SQRADDAC(a[32], a[41]); SQRADDAC(a[33], a[40]); SQRADDAC(a[34], a[39]); SQRADDAC(a[35], a[38]); SQRADDAC(a[36], a[37]); SQRADDDB; + COMBA_STORE(b[73]); + + /* output 74 */ + CARRY_FORWARD; + SQRADDSC(a[27], a[47]); SQRADDAC(a[28], a[46]); SQRADDAC(a[29], a[45]); SQRADDAC(a[30], a[44]); SQRADDAC(a[31], a[43]); SQRADDAC(a[32], a[42]); SQRADDAC(a[33], a[41]); SQRADDAC(a[34], a[40]); SQRADDAC(a[35], a[39]); SQRADDAC(a[36], a[38]); SQRADDDB; SQRADD(a[37], a[37]); + COMBA_STORE(b[74]); + + /* output 75 */ + CARRY_FORWARD; + SQRADDSC(a[28], a[47]); SQRADDAC(a[29], a[46]); SQRADDAC(a[30], a[45]); SQRADDAC(a[31], a[44]); SQRADDAC(a[32], a[43]); SQRADDAC(a[33], a[42]); SQRADDAC(a[34], a[41]); SQRADDAC(a[35], a[40]); SQRADDAC(a[36], a[39]); SQRADDAC(a[37], a[38]); SQRADDDB; + COMBA_STORE(b[75]); + + /* output 76 */ + CARRY_FORWARD; + SQRADDSC(a[29], a[47]); SQRADDAC(a[30], a[46]); SQRADDAC(a[31], a[45]); SQRADDAC(a[32], a[44]); SQRADDAC(a[33], a[43]); SQRADDAC(a[34], a[42]); SQRADDAC(a[35], a[41]); SQRADDAC(a[36], a[40]); SQRADDAC(a[37], a[39]); SQRADDDB; SQRADD(a[38], a[38]); + COMBA_STORE(b[76]); + + /* output 77 */ + CARRY_FORWARD; + SQRADDSC(a[30], a[47]); SQRADDAC(a[31], a[46]); SQRADDAC(a[32], a[45]); SQRADDAC(a[33], a[44]); SQRADDAC(a[34], a[43]); SQRADDAC(a[35], a[42]); SQRADDAC(a[36], a[41]); SQRADDAC(a[37], a[40]); SQRADDAC(a[38], a[39]); SQRADDDB; + COMBA_STORE(b[77]); + + /* output 78 */ + CARRY_FORWARD; + SQRADDSC(a[31], a[47]); SQRADDAC(a[32], a[46]); SQRADDAC(a[33], a[45]); SQRADDAC(a[34], a[44]); SQRADDAC(a[35], a[43]); SQRADDAC(a[36], a[42]); SQRADDAC(a[37], a[41]); SQRADDAC(a[38], a[40]); SQRADDDB; SQRADD(a[39], a[39]); + COMBA_STORE(b[78]); + + /* output 79 */ + CARRY_FORWARD; + SQRADDSC(a[32], a[47]); SQRADDAC(a[33], a[46]); SQRADDAC(a[34], a[45]); SQRADDAC(a[35], a[44]); SQRADDAC(a[36], a[43]); SQRADDAC(a[37], a[42]); SQRADDAC(a[38], a[41]); SQRADDAC(a[39], a[40]); SQRADDDB; + COMBA_STORE(b[79]); + + /* output 80 */ + CARRY_FORWARD; + SQRADDSC(a[33], a[47]); SQRADDAC(a[34], a[46]); SQRADDAC(a[35], a[45]); SQRADDAC(a[36], a[44]); SQRADDAC(a[37], a[43]); SQRADDAC(a[38], a[42]); SQRADDAC(a[39], a[41]); SQRADDDB; SQRADD(a[40], a[40]); + COMBA_STORE(b[80]); + + /* output 81 */ + CARRY_FORWARD; + SQRADDSC(a[34], a[47]); SQRADDAC(a[35], a[46]); SQRADDAC(a[36], a[45]); SQRADDAC(a[37], a[44]); SQRADDAC(a[38], a[43]); SQRADDAC(a[39], a[42]); SQRADDAC(a[40], a[41]); SQRADDDB; + COMBA_STORE(b[81]); + + /* output 82 */ + CARRY_FORWARD; + SQRADDSC(a[35], a[47]); SQRADDAC(a[36], a[46]); SQRADDAC(a[37], a[45]); SQRADDAC(a[38], a[44]); SQRADDAC(a[39], a[43]); SQRADDAC(a[40], a[42]); SQRADDDB; SQRADD(a[41], a[41]); + COMBA_STORE(b[82]); + + /* output 83 */ + CARRY_FORWARD; + SQRADDSC(a[36], a[47]); SQRADDAC(a[37], a[46]); SQRADDAC(a[38], a[45]); SQRADDAC(a[39], a[44]); SQRADDAC(a[40], a[43]); SQRADDAC(a[41], a[42]); SQRADDDB; + COMBA_STORE(b[83]); + + /* output 84 */ + CARRY_FORWARD; + SQRADDSC(a[37], a[47]); SQRADDAC(a[38], a[46]); SQRADDAC(a[39], a[45]); SQRADDAC(a[40], a[44]); SQRADDAC(a[41], a[43]); SQRADDDB; SQRADD(a[42], a[42]); + COMBA_STORE(b[84]); + + /* output 85 */ + CARRY_FORWARD; + SQRADDSC(a[38], a[47]); SQRADDAC(a[39], a[46]); SQRADDAC(a[40], a[45]); SQRADDAC(a[41], a[44]); SQRADDAC(a[42], a[43]); SQRADDDB; + COMBA_STORE(b[85]); + + /* output 86 */ + CARRY_FORWARD; + SQRADDSC(a[39], a[47]); SQRADDAC(a[40], a[46]); SQRADDAC(a[41], a[45]); SQRADDAC(a[42], a[44]); SQRADDDB; SQRADD(a[43], a[43]); + COMBA_STORE(b[86]); + + /* output 87 */ + CARRY_FORWARD; + SQRADDSC(a[40], a[47]); SQRADDAC(a[41], a[46]); SQRADDAC(a[42], a[45]); SQRADDAC(a[43], a[44]); SQRADDDB; + COMBA_STORE(b[87]); + + /* output 88 */ + CARRY_FORWARD; + SQRADDSC(a[41], a[47]); SQRADDAC(a[42], a[46]); SQRADDAC(a[43], a[45]); SQRADDDB; SQRADD(a[44], a[44]); + COMBA_STORE(b[88]); + + /* output 89 */ + CARRY_FORWARD; + SQRADDSC(a[42], a[47]); SQRADDAC(a[43], a[46]); SQRADDAC(a[44], a[45]); SQRADDDB; + COMBA_STORE(b[89]); + + /* output 90 */ + CARRY_FORWARD; + SQRADD2(a[43], a[47]); SQRADD2(a[44], a[46]); SQRADD(a[45], a[45]); + COMBA_STORE(b[90]); + + /* output 91 */ + CARRY_FORWARD; + SQRADD2(a[44], a[47]); SQRADD2(a[45], a[46]); + COMBA_STORE(b[91]); + + /* output 92 */ + CARRY_FORWARD; + SQRADD2(a[45], a[47]); SQRADD(a[46], a[46]); + COMBA_STORE(b[92]); + + /* output 93 */ + CARRY_FORWARD; + SQRADD2(a[46], a[47]); + COMBA_STORE(b[93]); + + /* output 94 */ + CARRY_FORWARD; + SQRADD(a[47], a[47]); + COMBA_STORE(b[94]); + COMBA_STORE2(b[95]); + COMBA_FINI; + + B->used = 96; + B->sign = FP_ZPOS; + XMEMCPY(B->dp, b, 96 * sizeof(fp_digit)); + fp_clamp(B); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; +} +#endif + + diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_sqr_comba_6.i b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_sqr_comba_6.i new file mode 100755 index 0000000..90396d2 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_sqr_comba_6.i @@ -0,0 +1,117 @@ +/* fp_sqr_comba_6.i + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifdef TFM_SQR6 +int fp_sqr_comba6(fp_int *A, fp_int *B) +{ + fp_digit *a, c0, c1, c2, sc0 = 0, sc1 = 0, sc2 = 0; +#ifdef TFM_ISO + fp_word tt; +#endif +#ifndef WOLFSSL_SMALL_STACK + fp_digit b[12]; +#else + fp_digit *b; +#endif + +#ifdef WOLFSSL_SMALL_STACK + b = (fp_digit*)XMALLOC(sizeof(fp_digit) * 12, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (b == NULL) + return FP_MEM; +#endif + + a = A->dp; + COMBA_START; + + /* clear carries */ + CLEAR_CARRY; + + /* output 0 */ + SQRADD(a[0],a[0]); + COMBA_STORE(b[0]); + + /* output 1 */ + CARRY_FORWARD; + SQRADD2(a[0], a[1]); + COMBA_STORE(b[1]); + + /* output 2 */ + CARRY_FORWARD; + SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]); + COMBA_STORE(b[2]); + + /* output 3 */ + CARRY_FORWARD; + SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]); + COMBA_STORE(b[3]); + + /* output 4 */ + CARRY_FORWARD; + SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]); + COMBA_STORE(b[4]); + + /* output 5 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB; + COMBA_STORE(b[5]); + + /* output 6 */ + CARRY_FORWARD; + SQRADD2(a[1], a[5]); SQRADD2(a[2], a[4]); SQRADD(a[3], a[3]); + COMBA_STORE(b[6]); + + /* output 7 */ + CARRY_FORWARD; + SQRADD2(a[2], a[5]); SQRADD2(a[3], a[4]); + COMBA_STORE(b[7]); + + /* output 8 */ + CARRY_FORWARD; + SQRADD2(a[3], a[5]); SQRADD(a[4], a[4]); + COMBA_STORE(b[8]); + + /* output 9 */ + CARRY_FORWARD; + SQRADD2(a[4], a[5]); + COMBA_STORE(b[9]); + + /* output 10 */ + CARRY_FORWARD; + SQRADD(a[5], a[5]); + COMBA_STORE(b[10]); + COMBA_STORE2(b[11]); + COMBA_FINI; + + B->used = 12; + B->sign = FP_ZPOS; + XMEMCPY(B->dp, b, 12 * sizeof(fp_digit)); + fp_clamp(B); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; +} +#endif + + diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_sqr_comba_64.i b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_sqr_comba_64.i new file mode 100755 index 0000000..0ae280a --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_sqr_comba_64.i @@ -0,0 +1,697 @@ +/* fp_sqr_comba_64.i + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifdef TFM_SQR64 +int fp_sqr_comba64(fp_int *A, fp_int *B) +{ + fp_digit *a, c0, c1, c2, sc0 = 0, sc1 = 0, sc2 = 0; +#ifdef TFM_ISO + fp_word tt; +#endif +#ifndef WOLFSSL_SMALL_STACK + fp_digit b[128]; +#else + fp_digit *b; +#endif + +#ifdef WOLFSSL_SMALL_STACK + b = (fp_digit*)XMALLOC(sizeof(fp_digit) * 128, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (b == NULL) + return FP_MEM; +#endif + + a = A->dp; + COMBA_START; + + /* clear carries */ + CLEAR_CARRY; + + /* output 0 */ + SQRADD(a[0],a[0]); + COMBA_STORE(b[0]); + + /* output 1 */ + CARRY_FORWARD; + SQRADD2(a[0], a[1]); + COMBA_STORE(b[1]); + + /* output 2 */ + CARRY_FORWARD; + SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]); + COMBA_STORE(b[2]); + + /* output 3 */ + CARRY_FORWARD; + SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]); + COMBA_STORE(b[3]); + + /* output 4 */ + CARRY_FORWARD; + SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]); + COMBA_STORE(b[4]); + + /* output 5 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB; + COMBA_STORE(b[5]); + + /* output 6 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]); + COMBA_STORE(b[6]); + + /* output 7 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[7]); SQRADDAC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB; + COMBA_STORE(b[7]); + + /* output 8 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[8]); SQRADDAC(a[1], a[7]); SQRADDAC(a[2], a[6]); SQRADDAC(a[3], a[5]); SQRADDDB; SQRADD(a[4], a[4]); + COMBA_STORE(b[8]); + + /* output 9 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[9]); SQRADDAC(a[1], a[8]); SQRADDAC(a[2], a[7]); SQRADDAC(a[3], a[6]); SQRADDAC(a[4], a[5]); SQRADDDB; + COMBA_STORE(b[9]); + + /* output 10 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[10]); SQRADDAC(a[1], a[9]); SQRADDAC(a[2], a[8]); SQRADDAC(a[3], a[7]); SQRADDAC(a[4], a[6]); SQRADDDB; SQRADD(a[5], a[5]); + COMBA_STORE(b[10]); + + /* output 11 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[11]); SQRADDAC(a[1], a[10]); SQRADDAC(a[2], a[9]); SQRADDAC(a[3], a[8]); SQRADDAC(a[4], a[7]); SQRADDAC(a[5], a[6]); SQRADDDB; + COMBA_STORE(b[11]); + + /* output 12 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[12]); SQRADDAC(a[1], a[11]); SQRADDAC(a[2], a[10]); SQRADDAC(a[3], a[9]); SQRADDAC(a[4], a[8]); SQRADDAC(a[5], a[7]); SQRADDDB; SQRADD(a[6], a[6]); + COMBA_STORE(b[12]); + + /* output 13 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[13]); SQRADDAC(a[1], a[12]); SQRADDAC(a[2], a[11]); SQRADDAC(a[3], a[10]); SQRADDAC(a[4], a[9]); SQRADDAC(a[5], a[8]); SQRADDAC(a[6], a[7]); SQRADDDB; + COMBA_STORE(b[13]); + + /* output 14 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[14]); SQRADDAC(a[1], a[13]); SQRADDAC(a[2], a[12]); SQRADDAC(a[3], a[11]); SQRADDAC(a[4], a[10]); SQRADDAC(a[5], a[9]); SQRADDAC(a[6], a[8]); SQRADDDB; SQRADD(a[7], a[7]); + COMBA_STORE(b[14]); + + /* output 15 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[15]); SQRADDAC(a[1], a[14]); SQRADDAC(a[2], a[13]); SQRADDAC(a[3], a[12]); SQRADDAC(a[4], a[11]); SQRADDAC(a[5], a[10]); SQRADDAC(a[6], a[9]); SQRADDAC(a[7], a[8]); SQRADDDB; + COMBA_STORE(b[15]); + + /* output 16 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[16]); SQRADDAC(a[1], a[15]); SQRADDAC(a[2], a[14]); SQRADDAC(a[3], a[13]); SQRADDAC(a[4], a[12]); SQRADDAC(a[5], a[11]); SQRADDAC(a[6], a[10]); SQRADDAC(a[7], a[9]); SQRADDDB; SQRADD(a[8], a[8]); + COMBA_STORE(b[16]); + + /* output 17 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[17]); SQRADDAC(a[1], a[16]); SQRADDAC(a[2], a[15]); SQRADDAC(a[3], a[14]); SQRADDAC(a[4], a[13]); SQRADDAC(a[5], a[12]); SQRADDAC(a[6], a[11]); SQRADDAC(a[7], a[10]); SQRADDAC(a[8], a[9]); SQRADDDB; + COMBA_STORE(b[17]); + + /* output 18 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[18]); SQRADDAC(a[1], a[17]); SQRADDAC(a[2], a[16]); SQRADDAC(a[3], a[15]); SQRADDAC(a[4], a[14]); SQRADDAC(a[5], a[13]); SQRADDAC(a[6], a[12]); SQRADDAC(a[7], a[11]); SQRADDAC(a[8], a[10]); SQRADDDB; SQRADD(a[9], a[9]); + COMBA_STORE(b[18]); + + /* output 19 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[19]); SQRADDAC(a[1], a[18]); SQRADDAC(a[2], a[17]); SQRADDAC(a[3], a[16]); SQRADDAC(a[4], a[15]); SQRADDAC(a[5], a[14]); SQRADDAC(a[6], a[13]); SQRADDAC(a[7], a[12]); SQRADDAC(a[8], a[11]); SQRADDAC(a[9], a[10]); SQRADDDB; + COMBA_STORE(b[19]); + + /* output 20 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[20]); SQRADDAC(a[1], a[19]); SQRADDAC(a[2], a[18]); SQRADDAC(a[3], a[17]); SQRADDAC(a[4], a[16]); SQRADDAC(a[5], a[15]); SQRADDAC(a[6], a[14]); SQRADDAC(a[7], a[13]); SQRADDAC(a[8], a[12]); SQRADDAC(a[9], a[11]); SQRADDDB; SQRADD(a[10], a[10]); + COMBA_STORE(b[20]); + + /* output 21 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[21]); SQRADDAC(a[1], a[20]); SQRADDAC(a[2], a[19]); SQRADDAC(a[3], a[18]); SQRADDAC(a[4], a[17]); SQRADDAC(a[5], a[16]); SQRADDAC(a[6], a[15]); SQRADDAC(a[7], a[14]); SQRADDAC(a[8], a[13]); SQRADDAC(a[9], a[12]); SQRADDAC(a[10], a[11]); SQRADDDB; + COMBA_STORE(b[21]); + + /* output 22 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[22]); SQRADDAC(a[1], a[21]); SQRADDAC(a[2], a[20]); SQRADDAC(a[3], a[19]); SQRADDAC(a[4], a[18]); SQRADDAC(a[5], a[17]); SQRADDAC(a[6], a[16]); SQRADDAC(a[7], a[15]); SQRADDAC(a[8], a[14]); SQRADDAC(a[9], a[13]); SQRADDAC(a[10], a[12]); SQRADDDB; SQRADD(a[11], a[11]); + COMBA_STORE(b[22]); + + /* output 23 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[23]); SQRADDAC(a[1], a[22]); SQRADDAC(a[2], a[21]); SQRADDAC(a[3], a[20]); SQRADDAC(a[4], a[19]); SQRADDAC(a[5], a[18]); SQRADDAC(a[6], a[17]); SQRADDAC(a[7], a[16]); SQRADDAC(a[8], a[15]); SQRADDAC(a[9], a[14]); SQRADDAC(a[10], a[13]); SQRADDAC(a[11], a[12]); SQRADDDB; + COMBA_STORE(b[23]); + + /* output 24 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[24]); SQRADDAC(a[1], a[23]); SQRADDAC(a[2], a[22]); SQRADDAC(a[3], a[21]); SQRADDAC(a[4], a[20]); SQRADDAC(a[5], a[19]); SQRADDAC(a[6], a[18]); SQRADDAC(a[7], a[17]); SQRADDAC(a[8], a[16]); SQRADDAC(a[9], a[15]); SQRADDAC(a[10], a[14]); SQRADDAC(a[11], a[13]); SQRADDDB; SQRADD(a[12], a[12]); + COMBA_STORE(b[24]); + + /* output 25 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[25]); SQRADDAC(a[1], a[24]); SQRADDAC(a[2], a[23]); SQRADDAC(a[3], a[22]); SQRADDAC(a[4], a[21]); SQRADDAC(a[5], a[20]); SQRADDAC(a[6], a[19]); SQRADDAC(a[7], a[18]); SQRADDAC(a[8], a[17]); SQRADDAC(a[9], a[16]); SQRADDAC(a[10], a[15]); SQRADDAC(a[11], a[14]); SQRADDAC(a[12], a[13]); SQRADDDB; + COMBA_STORE(b[25]); + + /* output 26 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[26]); SQRADDAC(a[1], a[25]); SQRADDAC(a[2], a[24]); SQRADDAC(a[3], a[23]); SQRADDAC(a[4], a[22]); SQRADDAC(a[5], a[21]); SQRADDAC(a[6], a[20]); SQRADDAC(a[7], a[19]); SQRADDAC(a[8], a[18]); SQRADDAC(a[9], a[17]); SQRADDAC(a[10], a[16]); SQRADDAC(a[11], a[15]); SQRADDAC(a[12], a[14]); SQRADDDB; SQRADD(a[13], a[13]); + COMBA_STORE(b[26]); + + /* output 27 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[27]); SQRADDAC(a[1], a[26]); SQRADDAC(a[2], a[25]); SQRADDAC(a[3], a[24]); SQRADDAC(a[4], a[23]); SQRADDAC(a[5], a[22]); SQRADDAC(a[6], a[21]); SQRADDAC(a[7], a[20]); SQRADDAC(a[8], a[19]); SQRADDAC(a[9], a[18]); SQRADDAC(a[10], a[17]); SQRADDAC(a[11], a[16]); SQRADDAC(a[12], a[15]); SQRADDAC(a[13], a[14]); SQRADDDB; + COMBA_STORE(b[27]); + + /* output 28 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[28]); SQRADDAC(a[1], a[27]); SQRADDAC(a[2], a[26]); SQRADDAC(a[3], a[25]); SQRADDAC(a[4], a[24]); SQRADDAC(a[5], a[23]); SQRADDAC(a[6], a[22]); SQRADDAC(a[7], a[21]); SQRADDAC(a[8], a[20]); SQRADDAC(a[9], a[19]); SQRADDAC(a[10], a[18]); SQRADDAC(a[11], a[17]); SQRADDAC(a[12], a[16]); SQRADDAC(a[13], a[15]); SQRADDDB; SQRADD(a[14], a[14]); + COMBA_STORE(b[28]); + + /* output 29 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[29]); SQRADDAC(a[1], a[28]); SQRADDAC(a[2], a[27]); SQRADDAC(a[3], a[26]); SQRADDAC(a[4], a[25]); SQRADDAC(a[5], a[24]); SQRADDAC(a[6], a[23]); SQRADDAC(a[7], a[22]); SQRADDAC(a[8], a[21]); SQRADDAC(a[9], a[20]); SQRADDAC(a[10], a[19]); SQRADDAC(a[11], a[18]); SQRADDAC(a[12], a[17]); SQRADDAC(a[13], a[16]); SQRADDAC(a[14], a[15]); SQRADDDB; + COMBA_STORE(b[29]); + + /* output 30 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[30]); SQRADDAC(a[1], a[29]); SQRADDAC(a[2], a[28]); SQRADDAC(a[3], a[27]); SQRADDAC(a[4], a[26]); SQRADDAC(a[5], a[25]); SQRADDAC(a[6], a[24]); SQRADDAC(a[7], a[23]); SQRADDAC(a[8], a[22]); SQRADDAC(a[9], a[21]); SQRADDAC(a[10], a[20]); SQRADDAC(a[11], a[19]); SQRADDAC(a[12], a[18]); SQRADDAC(a[13], a[17]); SQRADDAC(a[14], a[16]); SQRADDDB; SQRADD(a[15], a[15]); + COMBA_STORE(b[30]); + + /* output 31 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[31]); SQRADDAC(a[1], a[30]); SQRADDAC(a[2], a[29]); SQRADDAC(a[3], a[28]); SQRADDAC(a[4], a[27]); SQRADDAC(a[5], a[26]); SQRADDAC(a[6], a[25]); SQRADDAC(a[7], a[24]); SQRADDAC(a[8], a[23]); SQRADDAC(a[9], a[22]); SQRADDAC(a[10], a[21]); SQRADDAC(a[11], a[20]); SQRADDAC(a[12], a[19]); SQRADDAC(a[13], a[18]); SQRADDAC(a[14], a[17]); SQRADDAC(a[15], a[16]); SQRADDDB; + COMBA_STORE(b[31]); + + /* output 32 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[32]); SQRADDAC(a[1], a[31]); SQRADDAC(a[2], a[30]); SQRADDAC(a[3], a[29]); SQRADDAC(a[4], a[28]); SQRADDAC(a[5], a[27]); SQRADDAC(a[6], a[26]); SQRADDAC(a[7], a[25]); SQRADDAC(a[8], a[24]); SQRADDAC(a[9], a[23]); SQRADDAC(a[10], a[22]); SQRADDAC(a[11], a[21]); SQRADDAC(a[12], a[20]); SQRADDAC(a[13], a[19]); SQRADDAC(a[14], a[18]); SQRADDAC(a[15], a[17]); SQRADDDB; SQRADD(a[16], a[16]); + COMBA_STORE(b[32]); + + /* output 33 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[33]); SQRADDAC(a[1], a[32]); SQRADDAC(a[2], a[31]); SQRADDAC(a[3], a[30]); SQRADDAC(a[4], a[29]); SQRADDAC(a[5], a[28]); SQRADDAC(a[6], a[27]); SQRADDAC(a[7], a[26]); SQRADDAC(a[8], a[25]); SQRADDAC(a[9], a[24]); SQRADDAC(a[10], a[23]); SQRADDAC(a[11], a[22]); SQRADDAC(a[12], a[21]); SQRADDAC(a[13], a[20]); SQRADDAC(a[14], a[19]); SQRADDAC(a[15], a[18]); SQRADDAC(a[16], a[17]); SQRADDDB; + COMBA_STORE(b[33]); + + /* output 34 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[34]); SQRADDAC(a[1], a[33]); SQRADDAC(a[2], a[32]); SQRADDAC(a[3], a[31]); SQRADDAC(a[4], a[30]); SQRADDAC(a[5], a[29]); SQRADDAC(a[6], a[28]); SQRADDAC(a[7], a[27]); SQRADDAC(a[8], a[26]); SQRADDAC(a[9], a[25]); SQRADDAC(a[10], a[24]); SQRADDAC(a[11], a[23]); SQRADDAC(a[12], a[22]); SQRADDAC(a[13], a[21]); SQRADDAC(a[14], a[20]); SQRADDAC(a[15], a[19]); SQRADDAC(a[16], a[18]); SQRADDDB; SQRADD(a[17], a[17]); + COMBA_STORE(b[34]); + + /* output 35 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[35]); SQRADDAC(a[1], a[34]); SQRADDAC(a[2], a[33]); SQRADDAC(a[3], a[32]); SQRADDAC(a[4], a[31]); SQRADDAC(a[5], a[30]); SQRADDAC(a[6], a[29]); SQRADDAC(a[7], a[28]); SQRADDAC(a[8], a[27]); SQRADDAC(a[9], a[26]); SQRADDAC(a[10], a[25]); SQRADDAC(a[11], a[24]); SQRADDAC(a[12], a[23]); SQRADDAC(a[13], a[22]); SQRADDAC(a[14], a[21]); SQRADDAC(a[15], a[20]); SQRADDAC(a[16], a[19]); SQRADDAC(a[17], a[18]); SQRADDDB; + COMBA_STORE(b[35]); + + /* output 36 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[36]); SQRADDAC(a[1], a[35]); SQRADDAC(a[2], a[34]); SQRADDAC(a[3], a[33]); SQRADDAC(a[4], a[32]); SQRADDAC(a[5], a[31]); SQRADDAC(a[6], a[30]); SQRADDAC(a[7], a[29]); SQRADDAC(a[8], a[28]); SQRADDAC(a[9], a[27]); SQRADDAC(a[10], a[26]); SQRADDAC(a[11], a[25]); SQRADDAC(a[12], a[24]); SQRADDAC(a[13], a[23]); SQRADDAC(a[14], a[22]); SQRADDAC(a[15], a[21]); SQRADDAC(a[16], a[20]); SQRADDAC(a[17], a[19]); SQRADDDB; SQRADD(a[18], a[18]); + COMBA_STORE(b[36]); + + /* output 37 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[37]); SQRADDAC(a[1], a[36]); SQRADDAC(a[2], a[35]); SQRADDAC(a[3], a[34]); SQRADDAC(a[4], a[33]); SQRADDAC(a[5], a[32]); SQRADDAC(a[6], a[31]); SQRADDAC(a[7], a[30]); SQRADDAC(a[8], a[29]); SQRADDAC(a[9], a[28]); SQRADDAC(a[10], a[27]); SQRADDAC(a[11], a[26]); SQRADDAC(a[12], a[25]); SQRADDAC(a[13], a[24]); SQRADDAC(a[14], a[23]); SQRADDAC(a[15], a[22]); SQRADDAC(a[16], a[21]); SQRADDAC(a[17], a[20]); SQRADDAC(a[18], a[19]); SQRADDDB; + COMBA_STORE(b[37]); + + /* output 38 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[38]); SQRADDAC(a[1], a[37]); SQRADDAC(a[2], a[36]); SQRADDAC(a[3], a[35]); SQRADDAC(a[4], a[34]); SQRADDAC(a[5], a[33]); SQRADDAC(a[6], a[32]); SQRADDAC(a[7], a[31]); SQRADDAC(a[8], a[30]); SQRADDAC(a[9], a[29]); SQRADDAC(a[10], a[28]); SQRADDAC(a[11], a[27]); SQRADDAC(a[12], a[26]); SQRADDAC(a[13], a[25]); SQRADDAC(a[14], a[24]); SQRADDAC(a[15], a[23]); SQRADDAC(a[16], a[22]); SQRADDAC(a[17], a[21]); SQRADDAC(a[18], a[20]); SQRADDDB; SQRADD(a[19], a[19]); + COMBA_STORE(b[38]); + + /* output 39 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[39]); SQRADDAC(a[1], a[38]); SQRADDAC(a[2], a[37]); SQRADDAC(a[3], a[36]); SQRADDAC(a[4], a[35]); SQRADDAC(a[5], a[34]); SQRADDAC(a[6], a[33]); SQRADDAC(a[7], a[32]); SQRADDAC(a[8], a[31]); SQRADDAC(a[9], a[30]); SQRADDAC(a[10], a[29]); SQRADDAC(a[11], a[28]); SQRADDAC(a[12], a[27]); SQRADDAC(a[13], a[26]); SQRADDAC(a[14], a[25]); SQRADDAC(a[15], a[24]); SQRADDAC(a[16], a[23]); SQRADDAC(a[17], a[22]); SQRADDAC(a[18], a[21]); SQRADDAC(a[19], a[20]); SQRADDDB; + COMBA_STORE(b[39]); + + /* output 40 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[40]); SQRADDAC(a[1], a[39]); SQRADDAC(a[2], a[38]); SQRADDAC(a[3], a[37]); SQRADDAC(a[4], a[36]); SQRADDAC(a[5], a[35]); SQRADDAC(a[6], a[34]); SQRADDAC(a[7], a[33]); SQRADDAC(a[8], a[32]); SQRADDAC(a[9], a[31]); SQRADDAC(a[10], a[30]); SQRADDAC(a[11], a[29]); SQRADDAC(a[12], a[28]); SQRADDAC(a[13], a[27]); SQRADDAC(a[14], a[26]); SQRADDAC(a[15], a[25]); SQRADDAC(a[16], a[24]); SQRADDAC(a[17], a[23]); SQRADDAC(a[18], a[22]); SQRADDAC(a[19], a[21]); SQRADDDB; SQRADD(a[20], a[20]); + COMBA_STORE(b[40]); + + /* output 41 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[41]); SQRADDAC(a[1], a[40]); SQRADDAC(a[2], a[39]); SQRADDAC(a[3], a[38]); SQRADDAC(a[4], a[37]); SQRADDAC(a[5], a[36]); SQRADDAC(a[6], a[35]); SQRADDAC(a[7], a[34]); SQRADDAC(a[8], a[33]); SQRADDAC(a[9], a[32]); SQRADDAC(a[10], a[31]); SQRADDAC(a[11], a[30]); SQRADDAC(a[12], a[29]); SQRADDAC(a[13], a[28]); SQRADDAC(a[14], a[27]); SQRADDAC(a[15], a[26]); SQRADDAC(a[16], a[25]); SQRADDAC(a[17], a[24]); SQRADDAC(a[18], a[23]); SQRADDAC(a[19], a[22]); SQRADDAC(a[20], a[21]); SQRADDDB; + COMBA_STORE(b[41]); + + /* output 42 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[42]); SQRADDAC(a[1], a[41]); SQRADDAC(a[2], a[40]); SQRADDAC(a[3], a[39]); SQRADDAC(a[4], a[38]); SQRADDAC(a[5], a[37]); SQRADDAC(a[6], a[36]); SQRADDAC(a[7], a[35]); SQRADDAC(a[8], a[34]); SQRADDAC(a[9], a[33]); SQRADDAC(a[10], a[32]); SQRADDAC(a[11], a[31]); SQRADDAC(a[12], a[30]); SQRADDAC(a[13], a[29]); SQRADDAC(a[14], a[28]); SQRADDAC(a[15], a[27]); SQRADDAC(a[16], a[26]); SQRADDAC(a[17], a[25]); SQRADDAC(a[18], a[24]); SQRADDAC(a[19], a[23]); SQRADDAC(a[20], a[22]); SQRADDDB; SQRADD(a[21], a[21]); + COMBA_STORE(b[42]); + + /* output 43 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[43]); SQRADDAC(a[1], a[42]); SQRADDAC(a[2], a[41]); SQRADDAC(a[3], a[40]); SQRADDAC(a[4], a[39]); SQRADDAC(a[5], a[38]); SQRADDAC(a[6], a[37]); SQRADDAC(a[7], a[36]); SQRADDAC(a[8], a[35]); SQRADDAC(a[9], a[34]); SQRADDAC(a[10], a[33]); SQRADDAC(a[11], a[32]); SQRADDAC(a[12], a[31]); SQRADDAC(a[13], a[30]); SQRADDAC(a[14], a[29]); SQRADDAC(a[15], a[28]); SQRADDAC(a[16], a[27]); SQRADDAC(a[17], a[26]); SQRADDAC(a[18], a[25]); SQRADDAC(a[19], a[24]); SQRADDAC(a[20], a[23]); SQRADDAC(a[21], a[22]); SQRADDDB; + COMBA_STORE(b[43]); + + /* output 44 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[44]); SQRADDAC(a[1], a[43]); SQRADDAC(a[2], a[42]); SQRADDAC(a[3], a[41]); SQRADDAC(a[4], a[40]); SQRADDAC(a[5], a[39]); SQRADDAC(a[6], a[38]); SQRADDAC(a[7], a[37]); SQRADDAC(a[8], a[36]); SQRADDAC(a[9], a[35]); SQRADDAC(a[10], a[34]); SQRADDAC(a[11], a[33]); SQRADDAC(a[12], a[32]); SQRADDAC(a[13], a[31]); SQRADDAC(a[14], a[30]); SQRADDAC(a[15], a[29]); SQRADDAC(a[16], a[28]); SQRADDAC(a[17], a[27]); SQRADDAC(a[18], a[26]); SQRADDAC(a[19], a[25]); SQRADDAC(a[20], a[24]); SQRADDAC(a[21], a[23]); SQRADDDB; SQRADD(a[22], a[22]); + COMBA_STORE(b[44]); + + /* output 45 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[45]); SQRADDAC(a[1], a[44]); SQRADDAC(a[2], a[43]); SQRADDAC(a[3], a[42]); SQRADDAC(a[4], a[41]); SQRADDAC(a[5], a[40]); SQRADDAC(a[6], a[39]); SQRADDAC(a[7], a[38]); SQRADDAC(a[8], a[37]); SQRADDAC(a[9], a[36]); SQRADDAC(a[10], a[35]); SQRADDAC(a[11], a[34]); SQRADDAC(a[12], a[33]); SQRADDAC(a[13], a[32]); SQRADDAC(a[14], a[31]); SQRADDAC(a[15], a[30]); SQRADDAC(a[16], a[29]); SQRADDAC(a[17], a[28]); SQRADDAC(a[18], a[27]); SQRADDAC(a[19], a[26]); SQRADDAC(a[20], a[25]); SQRADDAC(a[21], a[24]); SQRADDAC(a[22], a[23]); SQRADDDB; + COMBA_STORE(b[45]); + + /* output 46 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[46]); SQRADDAC(a[1], a[45]); SQRADDAC(a[2], a[44]); SQRADDAC(a[3], a[43]); SQRADDAC(a[4], a[42]); SQRADDAC(a[5], a[41]); SQRADDAC(a[6], a[40]); SQRADDAC(a[7], a[39]); SQRADDAC(a[8], a[38]); SQRADDAC(a[9], a[37]); SQRADDAC(a[10], a[36]); SQRADDAC(a[11], a[35]); SQRADDAC(a[12], a[34]); SQRADDAC(a[13], a[33]); SQRADDAC(a[14], a[32]); SQRADDAC(a[15], a[31]); SQRADDAC(a[16], a[30]); SQRADDAC(a[17], a[29]); SQRADDAC(a[18], a[28]); SQRADDAC(a[19], a[27]); SQRADDAC(a[20], a[26]); SQRADDAC(a[21], a[25]); SQRADDAC(a[22], a[24]); SQRADDDB; SQRADD(a[23], a[23]); + COMBA_STORE(b[46]); + + /* output 47 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[47]); SQRADDAC(a[1], a[46]); SQRADDAC(a[2], a[45]); SQRADDAC(a[3], a[44]); SQRADDAC(a[4], a[43]); SQRADDAC(a[5], a[42]); SQRADDAC(a[6], a[41]); SQRADDAC(a[7], a[40]); SQRADDAC(a[8], a[39]); SQRADDAC(a[9], a[38]); SQRADDAC(a[10], a[37]); SQRADDAC(a[11], a[36]); SQRADDAC(a[12], a[35]); SQRADDAC(a[13], a[34]); SQRADDAC(a[14], a[33]); SQRADDAC(a[15], a[32]); SQRADDAC(a[16], a[31]); SQRADDAC(a[17], a[30]); SQRADDAC(a[18], a[29]); SQRADDAC(a[19], a[28]); SQRADDAC(a[20], a[27]); SQRADDAC(a[21], a[26]); SQRADDAC(a[22], a[25]); SQRADDAC(a[23], a[24]); SQRADDDB; + COMBA_STORE(b[47]); + + /* output 48 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[48]); SQRADDAC(a[1], a[47]); SQRADDAC(a[2], a[46]); SQRADDAC(a[3], a[45]); SQRADDAC(a[4], a[44]); SQRADDAC(a[5], a[43]); SQRADDAC(a[6], a[42]); SQRADDAC(a[7], a[41]); SQRADDAC(a[8], a[40]); SQRADDAC(a[9], a[39]); SQRADDAC(a[10], a[38]); SQRADDAC(a[11], a[37]); SQRADDAC(a[12], a[36]); SQRADDAC(a[13], a[35]); SQRADDAC(a[14], a[34]); SQRADDAC(a[15], a[33]); SQRADDAC(a[16], a[32]); SQRADDAC(a[17], a[31]); SQRADDAC(a[18], a[30]); SQRADDAC(a[19], a[29]); SQRADDAC(a[20], a[28]); SQRADDAC(a[21], a[27]); SQRADDAC(a[22], a[26]); SQRADDAC(a[23], a[25]); SQRADDDB; SQRADD(a[24], a[24]); + COMBA_STORE(b[48]); + + /* output 49 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[49]); SQRADDAC(a[1], a[48]); SQRADDAC(a[2], a[47]); SQRADDAC(a[3], a[46]); SQRADDAC(a[4], a[45]); SQRADDAC(a[5], a[44]); SQRADDAC(a[6], a[43]); SQRADDAC(a[7], a[42]); SQRADDAC(a[8], a[41]); SQRADDAC(a[9], a[40]); SQRADDAC(a[10], a[39]); SQRADDAC(a[11], a[38]); SQRADDAC(a[12], a[37]); SQRADDAC(a[13], a[36]); SQRADDAC(a[14], a[35]); SQRADDAC(a[15], a[34]); SQRADDAC(a[16], a[33]); SQRADDAC(a[17], a[32]); SQRADDAC(a[18], a[31]); SQRADDAC(a[19], a[30]); SQRADDAC(a[20], a[29]); SQRADDAC(a[21], a[28]); SQRADDAC(a[22], a[27]); SQRADDAC(a[23], a[26]); SQRADDAC(a[24], a[25]); SQRADDDB; + COMBA_STORE(b[49]); + + /* output 50 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[50]); SQRADDAC(a[1], a[49]); SQRADDAC(a[2], a[48]); SQRADDAC(a[3], a[47]); SQRADDAC(a[4], a[46]); SQRADDAC(a[5], a[45]); SQRADDAC(a[6], a[44]); SQRADDAC(a[7], a[43]); SQRADDAC(a[8], a[42]); SQRADDAC(a[9], a[41]); SQRADDAC(a[10], a[40]); SQRADDAC(a[11], a[39]); SQRADDAC(a[12], a[38]); SQRADDAC(a[13], a[37]); SQRADDAC(a[14], a[36]); SQRADDAC(a[15], a[35]); SQRADDAC(a[16], a[34]); SQRADDAC(a[17], a[33]); SQRADDAC(a[18], a[32]); SQRADDAC(a[19], a[31]); SQRADDAC(a[20], a[30]); SQRADDAC(a[21], a[29]); SQRADDAC(a[22], a[28]); SQRADDAC(a[23], a[27]); SQRADDAC(a[24], a[26]); SQRADDDB; SQRADD(a[25], a[25]); + COMBA_STORE(b[50]); + + /* output 51 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[51]); SQRADDAC(a[1], a[50]); SQRADDAC(a[2], a[49]); SQRADDAC(a[3], a[48]); SQRADDAC(a[4], a[47]); SQRADDAC(a[5], a[46]); SQRADDAC(a[6], a[45]); SQRADDAC(a[7], a[44]); SQRADDAC(a[8], a[43]); SQRADDAC(a[9], a[42]); SQRADDAC(a[10], a[41]); SQRADDAC(a[11], a[40]); SQRADDAC(a[12], a[39]); SQRADDAC(a[13], a[38]); SQRADDAC(a[14], a[37]); SQRADDAC(a[15], a[36]); SQRADDAC(a[16], a[35]); SQRADDAC(a[17], a[34]); SQRADDAC(a[18], a[33]); SQRADDAC(a[19], a[32]); SQRADDAC(a[20], a[31]); SQRADDAC(a[21], a[30]); SQRADDAC(a[22], a[29]); SQRADDAC(a[23], a[28]); SQRADDAC(a[24], a[27]); SQRADDAC(a[25], a[26]); SQRADDDB; + COMBA_STORE(b[51]); + + /* output 52 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[52]); SQRADDAC(a[1], a[51]); SQRADDAC(a[2], a[50]); SQRADDAC(a[3], a[49]); SQRADDAC(a[4], a[48]); SQRADDAC(a[5], a[47]); SQRADDAC(a[6], a[46]); SQRADDAC(a[7], a[45]); SQRADDAC(a[8], a[44]); SQRADDAC(a[9], a[43]); SQRADDAC(a[10], a[42]); SQRADDAC(a[11], a[41]); SQRADDAC(a[12], a[40]); SQRADDAC(a[13], a[39]); SQRADDAC(a[14], a[38]); SQRADDAC(a[15], a[37]); SQRADDAC(a[16], a[36]); SQRADDAC(a[17], a[35]); SQRADDAC(a[18], a[34]); SQRADDAC(a[19], a[33]); SQRADDAC(a[20], a[32]); SQRADDAC(a[21], a[31]); SQRADDAC(a[22], a[30]); SQRADDAC(a[23], a[29]); SQRADDAC(a[24], a[28]); SQRADDAC(a[25], a[27]); SQRADDDB; SQRADD(a[26], a[26]); + COMBA_STORE(b[52]); + + /* output 53 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[53]); SQRADDAC(a[1], a[52]); SQRADDAC(a[2], a[51]); SQRADDAC(a[3], a[50]); SQRADDAC(a[4], a[49]); SQRADDAC(a[5], a[48]); SQRADDAC(a[6], a[47]); SQRADDAC(a[7], a[46]); SQRADDAC(a[8], a[45]); SQRADDAC(a[9], a[44]); SQRADDAC(a[10], a[43]); SQRADDAC(a[11], a[42]); SQRADDAC(a[12], a[41]); SQRADDAC(a[13], a[40]); SQRADDAC(a[14], a[39]); SQRADDAC(a[15], a[38]); SQRADDAC(a[16], a[37]); SQRADDAC(a[17], a[36]); SQRADDAC(a[18], a[35]); SQRADDAC(a[19], a[34]); SQRADDAC(a[20], a[33]); SQRADDAC(a[21], a[32]); SQRADDAC(a[22], a[31]); SQRADDAC(a[23], a[30]); SQRADDAC(a[24], a[29]); SQRADDAC(a[25], a[28]); SQRADDAC(a[26], a[27]); SQRADDDB; + COMBA_STORE(b[53]); + + /* output 54 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[54]); SQRADDAC(a[1], a[53]); SQRADDAC(a[2], a[52]); SQRADDAC(a[3], a[51]); SQRADDAC(a[4], a[50]); SQRADDAC(a[5], a[49]); SQRADDAC(a[6], a[48]); SQRADDAC(a[7], a[47]); SQRADDAC(a[8], a[46]); SQRADDAC(a[9], a[45]); SQRADDAC(a[10], a[44]); SQRADDAC(a[11], a[43]); SQRADDAC(a[12], a[42]); SQRADDAC(a[13], a[41]); SQRADDAC(a[14], a[40]); SQRADDAC(a[15], a[39]); SQRADDAC(a[16], a[38]); SQRADDAC(a[17], a[37]); SQRADDAC(a[18], a[36]); SQRADDAC(a[19], a[35]); SQRADDAC(a[20], a[34]); SQRADDAC(a[21], a[33]); SQRADDAC(a[22], a[32]); SQRADDAC(a[23], a[31]); SQRADDAC(a[24], a[30]); SQRADDAC(a[25], a[29]); SQRADDAC(a[26], a[28]); SQRADDDB; SQRADD(a[27], a[27]); + COMBA_STORE(b[54]); + + /* output 55 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[55]); SQRADDAC(a[1], a[54]); SQRADDAC(a[2], a[53]); SQRADDAC(a[3], a[52]); SQRADDAC(a[4], a[51]); SQRADDAC(a[5], a[50]); SQRADDAC(a[6], a[49]); SQRADDAC(a[7], a[48]); SQRADDAC(a[8], a[47]); SQRADDAC(a[9], a[46]); SQRADDAC(a[10], a[45]); SQRADDAC(a[11], a[44]); SQRADDAC(a[12], a[43]); SQRADDAC(a[13], a[42]); SQRADDAC(a[14], a[41]); SQRADDAC(a[15], a[40]); SQRADDAC(a[16], a[39]); SQRADDAC(a[17], a[38]); SQRADDAC(a[18], a[37]); SQRADDAC(a[19], a[36]); SQRADDAC(a[20], a[35]); SQRADDAC(a[21], a[34]); SQRADDAC(a[22], a[33]); SQRADDAC(a[23], a[32]); SQRADDAC(a[24], a[31]); SQRADDAC(a[25], a[30]); SQRADDAC(a[26], a[29]); SQRADDAC(a[27], a[28]); SQRADDDB; + COMBA_STORE(b[55]); + + /* output 56 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[56]); SQRADDAC(a[1], a[55]); SQRADDAC(a[2], a[54]); SQRADDAC(a[3], a[53]); SQRADDAC(a[4], a[52]); SQRADDAC(a[5], a[51]); SQRADDAC(a[6], a[50]); SQRADDAC(a[7], a[49]); SQRADDAC(a[8], a[48]); SQRADDAC(a[9], a[47]); SQRADDAC(a[10], a[46]); SQRADDAC(a[11], a[45]); SQRADDAC(a[12], a[44]); SQRADDAC(a[13], a[43]); SQRADDAC(a[14], a[42]); SQRADDAC(a[15], a[41]); SQRADDAC(a[16], a[40]); SQRADDAC(a[17], a[39]); SQRADDAC(a[18], a[38]); SQRADDAC(a[19], a[37]); SQRADDAC(a[20], a[36]); SQRADDAC(a[21], a[35]); SQRADDAC(a[22], a[34]); SQRADDAC(a[23], a[33]); SQRADDAC(a[24], a[32]); SQRADDAC(a[25], a[31]); SQRADDAC(a[26], a[30]); SQRADDAC(a[27], a[29]); SQRADDDB; SQRADD(a[28], a[28]); + COMBA_STORE(b[56]); + + /* output 57 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[57]); SQRADDAC(a[1], a[56]); SQRADDAC(a[2], a[55]); SQRADDAC(a[3], a[54]); SQRADDAC(a[4], a[53]); SQRADDAC(a[5], a[52]); SQRADDAC(a[6], a[51]); SQRADDAC(a[7], a[50]); SQRADDAC(a[8], a[49]); SQRADDAC(a[9], a[48]); SQRADDAC(a[10], a[47]); SQRADDAC(a[11], a[46]); SQRADDAC(a[12], a[45]); SQRADDAC(a[13], a[44]); SQRADDAC(a[14], a[43]); SQRADDAC(a[15], a[42]); SQRADDAC(a[16], a[41]); SQRADDAC(a[17], a[40]); SQRADDAC(a[18], a[39]); SQRADDAC(a[19], a[38]); SQRADDAC(a[20], a[37]); SQRADDAC(a[21], a[36]); SQRADDAC(a[22], a[35]); SQRADDAC(a[23], a[34]); SQRADDAC(a[24], a[33]); SQRADDAC(a[25], a[32]); SQRADDAC(a[26], a[31]); SQRADDAC(a[27], a[30]); SQRADDAC(a[28], a[29]); SQRADDDB; + COMBA_STORE(b[57]); + + /* output 58 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[58]); SQRADDAC(a[1], a[57]); SQRADDAC(a[2], a[56]); SQRADDAC(a[3], a[55]); SQRADDAC(a[4], a[54]); SQRADDAC(a[5], a[53]); SQRADDAC(a[6], a[52]); SQRADDAC(a[7], a[51]); SQRADDAC(a[8], a[50]); SQRADDAC(a[9], a[49]); SQRADDAC(a[10], a[48]); SQRADDAC(a[11], a[47]); SQRADDAC(a[12], a[46]); SQRADDAC(a[13], a[45]); SQRADDAC(a[14], a[44]); SQRADDAC(a[15], a[43]); SQRADDAC(a[16], a[42]); SQRADDAC(a[17], a[41]); SQRADDAC(a[18], a[40]); SQRADDAC(a[19], a[39]); SQRADDAC(a[20], a[38]); SQRADDAC(a[21], a[37]); SQRADDAC(a[22], a[36]); SQRADDAC(a[23], a[35]); SQRADDAC(a[24], a[34]); SQRADDAC(a[25], a[33]); SQRADDAC(a[26], a[32]); SQRADDAC(a[27], a[31]); SQRADDAC(a[28], a[30]); SQRADDDB; SQRADD(a[29], a[29]); + COMBA_STORE(b[58]); + + /* output 59 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[59]); SQRADDAC(a[1], a[58]); SQRADDAC(a[2], a[57]); SQRADDAC(a[3], a[56]); SQRADDAC(a[4], a[55]); SQRADDAC(a[5], a[54]); SQRADDAC(a[6], a[53]); SQRADDAC(a[7], a[52]); SQRADDAC(a[8], a[51]); SQRADDAC(a[9], a[50]); SQRADDAC(a[10], a[49]); SQRADDAC(a[11], a[48]); SQRADDAC(a[12], a[47]); SQRADDAC(a[13], a[46]); SQRADDAC(a[14], a[45]); SQRADDAC(a[15], a[44]); SQRADDAC(a[16], a[43]); SQRADDAC(a[17], a[42]); SQRADDAC(a[18], a[41]); SQRADDAC(a[19], a[40]); SQRADDAC(a[20], a[39]); SQRADDAC(a[21], a[38]); SQRADDAC(a[22], a[37]); SQRADDAC(a[23], a[36]); SQRADDAC(a[24], a[35]); SQRADDAC(a[25], a[34]); SQRADDAC(a[26], a[33]); SQRADDAC(a[27], a[32]); SQRADDAC(a[28], a[31]); SQRADDAC(a[29], a[30]); SQRADDDB; + COMBA_STORE(b[59]); + + /* output 60 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[60]); SQRADDAC(a[1], a[59]); SQRADDAC(a[2], a[58]); SQRADDAC(a[3], a[57]); SQRADDAC(a[4], a[56]); SQRADDAC(a[5], a[55]); SQRADDAC(a[6], a[54]); SQRADDAC(a[7], a[53]); SQRADDAC(a[8], a[52]); SQRADDAC(a[9], a[51]); SQRADDAC(a[10], a[50]); SQRADDAC(a[11], a[49]); SQRADDAC(a[12], a[48]); SQRADDAC(a[13], a[47]); SQRADDAC(a[14], a[46]); SQRADDAC(a[15], a[45]); SQRADDAC(a[16], a[44]); SQRADDAC(a[17], a[43]); SQRADDAC(a[18], a[42]); SQRADDAC(a[19], a[41]); SQRADDAC(a[20], a[40]); SQRADDAC(a[21], a[39]); SQRADDAC(a[22], a[38]); SQRADDAC(a[23], a[37]); SQRADDAC(a[24], a[36]); SQRADDAC(a[25], a[35]); SQRADDAC(a[26], a[34]); SQRADDAC(a[27], a[33]); SQRADDAC(a[28], a[32]); SQRADDAC(a[29], a[31]); SQRADDDB; SQRADD(a[30], a[30]); + COMBA_STORE(b[60]); + + /* output 61 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[61]); SQRADDAC(a[1], a[60]); SQRADDAC(a[2], a[59]); SQRADDAC(a[3], a[58]); SQRADDAC(a[4], a[57]); SQRADDAC(a[5], a[56]); SQRADDAC(a[6], a[55]); SQRADDAC(a[7], a[54]); SQRADDAC(a[8], a[53]); SQRADDAC(a[9], a[52]); SQRADDAC(a[10], a[51]); SQRADDAC(a[11], a[50]); SQRADDAC(a[12], a[49]); SQRADDAC(a[13], a[48]); SQRADDAC(a[14], a[47]); SQRADDAC(a[15], a[46]); SQRADDAC(a[16], a[45]); SQRADDAC(a[17], a[44]); SQRADDAC(a[18], a[43]); SQRADDAC(a[19], a[42]); SQRADDAC(a[20], a[41]); SQRADDAC(a[21], a[40]); SQRADDAC(a[22], a[39]); SQRADDAC(a[23], a[38]); SQRADDAC(a[24], a[37]); SQRADDAC(a[25], a[36]); SQRADDAC(a[26], a[35]); SQRADDAC(a[27], a[34]); SQRADDAC(a[28], a[33]); SQRADDAC(a[29], a[32]); SQRADDAC(a[30], a[31]); SQRADDDB; + COMBA_STORE(b[61]); + + /* output 62 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[62]); SQRADDAC(a[1], a[61]); SQRADDAC(a[2], a[60]); SQRADDAC(a[3], a[59]); SQRADDAC(a[4], a[58]); SQRADDAC(a[5], a[57]); SQRADDAC(a[6], a[56]); SQRADDAC(a[7], a[55]); SQRADDAC(a[8], a[54]); SQRADDAC(a[9], a[53]); SQRADDAC(a[10], a[52]); SQRADDAC(a[11], a[51]); SQRADDAC(a[12], a[50]); SQRADDAC(a[13], a[49]); SQRADDAC(a[14], a[48]); SQRADDAC(a[15], a[47]); SQRADDAC(a[16], a[46]); SQRADDAC(a[17], a[45]); SQRADDAC(a[18], a[44]); SQRADDAC(a[19], a[43]); SQRADDAC(a[20], a[42]); SQRADDAC(a[21], a[41]); SQRADDAC(a[22], a[40]); SQRADDAC(a[23], a[39]); SQRADDAC(a[24], a[38]); SQRADDAC(a[25], a[37]); SQRADDAC(a[26], a[36]); SQRADDAC(a[27], a[35]); SQRADDAC(a[28], a[34]); SQRADDAC(a[29], a[33]); SQRADDAC(a[30], a[32]); SQRADDDB; SQRADD(a[31], a[31]); + COMBA_STORE(b[62]); + + /* output 63 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[63]); SQRADDAC(a[1], a[62]); SQRADDAC(a[2], a[61]); SQRADDAC(a[3], a[60]); SQRADDAC(a[4], a[59]); SQRADDAC(a[5], a[58]); SQRADDAC(a[6], a[57]); SQRADDAC(a[7], a[56]); SQRADDAC(a[8], a[55]); SQRADDAC(a[9], a[54]); SQRADDAC(a[10], a[53]); SQRADDAC(a[11], a[52]); SQRADDAC(a[12], a[51]); SQRADDAC(a[13], a[50]); SQRADDAC(a[14], a[49]); SQRADDAC(a[15], a[48]); SQRADDAC(a[16], a[47]); SQRADDAC(a[17], a[46]); SQRADDAC(a[18], a[45]); SQRADDAC(a[19], a[44]); SQRADDAC(a[20], a[43]); SQRADDAC(a[21], a[42]); SQRADDAC(a[22], a[41]); SQRADDAC(a[23], a[40]); SQRADDAC(a[24], a[39]); SQRADDAC(a[25], a[38]); SQRADDAC(a[26], a[37]); SQRADDAC(a[27], a[36]); SQRADDAC(a[28], a[35]); SQRADDAC(a[29], a[34]); SQRADDAC(a[30], a[33]); SQRADDAC(a[31], a[32]); SQRADDDB; + COMBA_STORE(b[63]); + + /* output 64 */ + CARRY_FORWARD; + SQRADDSC(a[1], a[63]); SQRADDAC(a[2], a[62]); SQRADDAC(a[3], a[61]); SQRADDAC(a[4], a[60]); SQRADDAC(a[5], a[59]); SQRADDAC(a[6], a[58]); SQRADDAC(a[7], a[57]); SQRADDAC(a[8], a[56]); SQRADDAC(a[9], a[55]); SQRADDAC(a[10], a[54]); SQRADDAC(a[11], a[53]); SQRADDAC(a[12], a[52]); SQRADDAC(a[13], a[51]); SQRADDAC(a[14], a[50]); SQRADDAC(a[15], a[49]); SQRADDAC(a[16], a[48]); SQRADDAC(a[17], a[47]); SQRADDAC(a[18], a[46]); SQRADDAC(a[19], a[45]); SQRADDAC(a[20], a[44]); SQRADDAC(a[21], a[43]); SQRADDAC(a[22], a[42]); SQRADDAC(a[23], a[41]); SQRADDAC(a[24], a[40]); SQRADDAC(a[25], a[39]); SQRADDAC(a[26], a[38]); SQRADDAC(a[27], a[37]); SQRADDAC(a[28], a[36]); SQRADDAC(a[29], a[35]); SQRADDAC(a[30], a[34]); SQRADDAC(a[31], a[33]); SQRADDDB; SQRADD(a[32], a[32]); + COMBA_STORE(b[64]); + + /* output 65 */ + CARRY_FORWARD; + SQRADDSC(a[2], a[63]); SQRADDAC(a[3], a[62]); SQRADDAC(a[4], a[61]); SQRADDAC(a[5], a[60]); SQRADDAC(a[6], a[59]); SQRADDAC(a[7], a[58]); SQRADDAC(a[8], a[57]); SQRADDAC(a[9], a[56]); SQRADDAC(a[10], a[55]); SQRADDAC(a[11], a[54]); SQRADDAC(a[12], a[53]); SQRADDAC(a[13], a[52]); SQRADDAC(a[14], a[51]); SQRADDAC(a[15], a[50]); SQRADDAC(a[16], a[49]); SQRADDAC(a[17], a[48]); SQRADDAC(a[18], a[47]); SQRADDAC(a[19], a[46]); SQRADDAC(a[20], a[45]); SQRADDAC(a[21], a[44]); SQRADDAC(a[22], a[43]); SQRADDAC(a[23], a[42]); SQRADDAC(a[24], a[41]); SQRADDAC(a[25], a[40]); SQRADDAC(a[26], a[39]); SQRADDAC(a[27], a[38]); SQRADDAC(a[28], a[37]); SQRADDAC(a[29], a[36]); SQRADDAC(a[30], a[35]); SQRADDAC(a[31], a[34]); SQRADDAC(a[32], a[33]); SQRADDDB; + COMBA_STORE(b[65]); + + /* output 66 */ + CARRY_FORWARD; + SQRADDSC(a[3], a[63]); SQRADDAC(a[4], a[62]); SQRADDAC(a[5], a[61]); SQRADDAC(a[6], a[60]); SQRADDAC(a[7], a[59]); SQRADDAC(a[8], a[58]); SQRADDAC(a[9], a[57]); SQRADDAC(a[10], a[56]); SQRADDAC(a[11], a[55]); SQRADDAC(a[12], a[54]); SQRADDAC(a[13], a[53]); SQRADDAC(a[14], a[52]); SQRADDAC(a[15], a[51]); SQRADDAC(a[16], a[50]); SQRADDAC(a[17], a[49]); SQRADDAC(a[18], a[48]); SQRADDAC(a[19], a[47]); SQRADDAC(a[20], a[46]); SQRADDAC(a[21], a[45]); SQRADDAC(a[22], a[44]); SQRADDAC(a[23], a[43]); SQRADDAC(a[24], a[42]); SQRADDAC(a[25], a[41]); SQRADDAC(a[26], a[40]); SQRADDAC(a[27], a[39]); SQRADDAC(a[28], a[38]); SQRADDAC(a[29], a[37]); SQRADDAC(a[30], a[36]); SQRADDAC(a[31], a[35]); SQRADDAC(a[32], a[34]); SQRADDDB; SQRADD(a[33], a[33]); + COMBA_STORE(b[66]); + + /* output 67 */ + CARRY_FORWARD; + SQRADDSC(a[4], a[63]); SQRADDAC(a[5], a[62]); SQRADDAC(a[6], a[61]); SQRADDAC(a[7], a[60]); SQRADDAC(a[8], a[59]); SQRADDAC(a[9], a[58]); SQRADDAC(a[10], a[57]); SQRADDAC(a[11], a[56]); SQRADDAC(a[12], a[55]); SQRADDAC(a[13], a[54]); SQRADDAC(a[14], a[53]); SQRADDAC(a[15], a[52]); SQRADDAC(a[16], a[51]); SQRADDAC(a[17], a[50]); SQRADDAC(a[18], a[49]); SQRADDAC(a[19], a[48]); SQRADDAC(a[20], a[47]); SQRADDAC(a[21], a[46]); SQRADDAC(a[22], a[45]); SQRADDAC(a[23], a[44]); SQRADDAC(a[24], a[43]); SQRADDAC(a[25], a[42]); SQRADDAC(a[26], a[41]); SQRADDAC(a[27], a[40]); SQRADDAC(a[28], a[39]); SQRADDAC(a[29], a[38]); SQRADDAC(a[30], a[37]); SQRADDAC(a[31], a[36]); SQRADDAC(a[32], a[35]); SQRADDAC(a[33], a[34]); SQRADDDB; + COMBA_STORE(b[67]); + + /* output 68 */ + CARRY_FORWARD; + SQRADDSC(a[5], a[63]); SQRADDAC(a[6], a[62]); SQRADDAC(a[7], a[61]); SQRADDAC(a[8], a[60]); SQRADDAC(a[9], a[59]); SQRADDAC(a[10], a[58]); SQRADDAC(a[11], a[57]); SQRADDAC(a[12], a[56]); SQRADDAC(a[13], a[55]); SQRADDAC(a[14], a[54]); SQRADDAC(a[15], a[53]); SQRADDAC(a[16], a[52]); SQRADDAC(a[17], a[51]); SQRADDAC(a[18], a[50]); SQRADDAC(a[19], a[49]); SQRADDAC(a[20], a[48]); SQRADDAC(a[21], a[47]); SQRADDAC(a[22], a[46]); SQRADDAC(a[23], a[45]); SQRADDAC(a[24], a[44]); SQRADDAC(a[25], a[43]); SQRADDAC(a[26], a[42]); SQRADDAC(a[27], a[41]); SQRADDAC(a[28], a[40]); SQRADDAC(a[29], a[39]); SQRADDAC(a[30], a[38]); SQRADDAC(a[31], a[37]); SQRADDAC(a[32], a[36]); SQRADDAC(a[33], a[35]); SQRADDDB; SQRADD(a[34], a[34]); + COMBA_STORE(b[68]); + + /* output 69 */ + CARRY_FORWARD; + SQRADDSC(a[6], a[63]); SQRADDAC(a[7], a[62]); SQRADDAC(a[8], a[61]); SQRADDAC(a[9], a[60]); SQRADDAC(a[10], a[59]); SQRADDAC(a[11], a[58]); SQRADDAC(a[12], a[57]); SQRADDAC(a[13], a[56]); SQRADDAC(a[14], a[55]); SQRADDAC(a[15], a[54]); SQRADDAC(a[16], a[53]); SQRADDAC(a[17], a[52]); SQRADDAC(a[18], a[51]); SQRADDAC(a[19], a[50]); SQRADDAC(a[20], a[49]); SQRADDAC(a[21], a[48]); SQRADDAC(a[22], a[47]); SQRADDAC(a[23], a[46]); SQRADDAC(a[24], a[45]); SQRADDAC(a[25], a[44]); SQRADDAC(a[26], a[43]); SQRADDAC(a[27], a[42]); SQRADDAC(a[28], a[41]); SQRADDAC(a[29], a[40]); SQRADDAC(a[30], a[39]); SQRADDAC(a[31], a[38]); SQRADDAC(a[32], a[37]); SQRADDAC(a[33], a[36]); SQRADDAC(a[34], a[35]); SQRADDDB; + COMBA_STORE(b[69]); + + /* output 70 */ + CARRY_FORWARD; + SQRADDSC(a[7], a[63]); SQRADDAC(a[8], a[62]); SQRADDAC(a[9], a[61]); SQRADDAC(a[10], a[60]); SQRADDAC(a[11], a[59]); SQRADDAC(a[12], a[58]); SQRADDAC(a[13], a[57]); SQRADDAC(a[14], a[56]); SQRADDAC(a[15], a[55]); SQRADDAC(a[16], a[54]); SQRADDAC(a[17], a[53]); SQRADDAC(a[18], a[52]); SQRADDAC(a[19], a[51]); SQRADDAC(a[20], a[50]); SQRADDAC(a[21], a[49]); SQRADDAC(a[22], a[48]); SQRADDAC(a[23], a[47]); SQRADDAC(a[24], a[46]); SQRADDAC(a[25], a[45]); SQRADDAC(a[26], a[44]); SQRADDAC(a[27], a[43]); SQRADDAC(a[28], a[42]); SQRADDAC(a[29], a[41]); SQRADDAC(a[30], a[40]); SQRADDAC(a[31], a[39]); SQRADDAC(a[32], a[38]); SQRADDAC(a[33], a[37]); SQRADDAC(a[34], a[36]); SQRADDDB; SQRADD(a[35], a[35]); + COMBA_STORE(b[70]); + + /* output 71 */ + CARRY_FORWARD; + SQRADDSC(a[8], a[63]); SQRADDAC(a[9], a[62]); SQRADDAC(a[10], a[61]); SQRADDAC(a[11], a[60]); SQRADDAC(a[12], a[59]); SQRADDAC(a[13], a[58]); SQRADDAC(a[14], a[57]); SQRADDAC(a[15], a[56]); SQRADDAC(a[16], a[55]); SQRADDAC(a[17], a[54]); SQRADDAC(a[18], a[53]); SQRADDAC(a[19], a[52]); SQRADDAC(a[20], a[51]); SQRADDAC(a[21], a[50]); SQRADDAC(a[22], a[49]); SQRADDAC(a[23], a[48]); SQRADDAC(a[24], a[47]); SQRADDAC(a[25], a[46]); SQRADDAC(a[26], a[45]); SQRADDAC(a[27], a[44]); SQRADDAC(a[28], a[43]); SQRADDAC(a[29], a[42]); SQRADDAC(a[30], a[41]); SQRADDAC(a[31], a[40]); SQRADDAC(a[32], a[39]); SQRADDAC(a[33], a[38]); SQRADDAC(a[34], a[37]); SQRADDAC(a[35], a[36]); SQRADDDB; + COMBA_STORE(b[71]); + + /* output 72 */ + CARRY_FORWARD; + SQRADDSC(a[9], a[63]); SQRADDAC(a[10], a[62]); SQRADDAC(a[11], a[61]); SQRADDAC(a[12], a[60]); SQRADDAC(a[13], a[59]); SQRADDAC(a[14], a[58]); SQRADDAC(a[15], a[57]); SQRADDAC(a[16], a[56]); SQRADDAC(a[17], a[55]); SQRADDAC(a[18], a[54]); SQRADDAC(a[19], a[53]); SQRADDAC(a[20], a[52]); SQRADDAC(a[21], a[51]); SQRADDAC(a[22], a[50]); SQRADDAC(a[23], a[49]); SQRADDAC(a[24], a[48]); SQRADDAC(a[25], a[47]); SQRADDAC(a[26], a[46]); SQRADDAC(a[27], a[45]); SQRADDAC(a[28], a[44]); SQRADDAC(a[29], a[43]); SQRADDAC(a[30], a[42]); SQRADDAC(a[31], a[41]); SQRADDAC(a[32], a[40]); SQRADDAC(a[33], a[39]); SQRADDAC(a[34], a[38]); SQRADDAC(a[35], a[37]); SQRADDDB; SQRADD(a[36], a[36]); + COMBA_STORE(b[72]); + + /* output 73 */ + CARRY_FORWARD; + SQRADDSC(a[10], a[63]); SQRADDAC(a[11], a[62]); SQRADDAC(a[12], a[61]); SQRADDAC(a[13], a[60]); SQRADDAC(a[14], a[59]); SQRADDAC(a[15], a[58]); SQRADDAC(a[16], a[57]); SQRADDAC(a[17], a[56]); SQRADDAC(a[18], a[55]); SQRADDAC(a[19], a[54]); SQRADDAC(a[20], a[53]); SQRADDAC(a[21], a[52]); SQRADDAC(a[22], a[51]); SQRADDAC(a[23], a[50]); SQRADDAC(a[24], a[49]); SQRADDAC(a[25], a[48]); SQRADDAC(a[26], a[47]); SQRADDAC(a[27], a[46]); SQRADDAC(a[28], a[45]); SQRADDAC(a[29], a[44]); SQRADDAC(a[30], a[43]); SQRADDAC(a[31], a[42]); SQRADDAC(a[32], a[41]); SQRADDAC(a[33], a[40]); SQRADDAC(a[34], a[39]); SQRADDAC(a[35], a[38]); SQRADDAC(a[36], a[37]); SQRADDDB; + COMBA_STORE(b[73]); + + /* output 74 */ + CARRY_FORWARD; + SQRADDSC(a[11], a[63]); SQRADDAC(a[12], a[62]); SQRADDAC(a[13], a[61]); SQRADDAC(a[14], a[60]); SQRADDAC(a[15], a[59]); SQRADDAC(a[16], a[58]); SQRADDAC(a[17], a[57]); SQRADDAC(a[18], a[56]); SQRADDAC(a[19], a[55]); SQRADDAC(a[20], a[54]); SQRADDAC(a[21], a[53]); SQRADDAC(a[22], a[52]); SQRADDAC(a[23], a[51]); SQRADDAC(a[24], a[50]); SQRADDAC(a[25], a[49]); SQRADDAC(a[26], a[48]); SQRADDAC(a[27], a[47]); SQRADDAC(a[28], a[46]); SQRADDAC(a[29], a[45]); SQRADDAC(a[30], a[44]); SQRADDAC(a[31], a[43]); SQRADDAC(a[32], a[42]); SQRADDAC(a[33], a[41]); SQRADDAC(a[34], a[40]); SQRADDAC(a[35], a[39]); SQRADDAC(a[36], a[38]); SQRADDDB; SQRADD(a[37], a[37]); + COMBA_STORE(b[74]); + + /* output 75 */ + CARRY_FORWARD; + SQRADDSC(a[12], a[63]); SQRADDAC(a[13], a[62]); SQRADDAC(a[14], a[61]); SQRADDAC(a[15], a[60]); SQRADDAC(a[16], a[59]); SQRADDAC(a[17], a[58]); SQRADDAC(a[18], a[57]); SQRADDAC(a[19], a[56]); SQRADDAC(a[20], a[55]); SQRADDAC(a[21], a[54]); SQRADDAC(a[22], a[53]); SQRADDAC(a[23], a[52]); SQRADDAC(a[24], a[51]); SQRADDAC(a[25], a[50]); SQRADDAC(a[26], a[49]); SQRADDAC(a[27], a[48]); SQRADDAC(a[28], a[47]); SQRADDAC(a[29], a[46]); SQRADDAC(a[30], a[45]); SQRADDAC(a[31], a[44]); SQRADDAC(a[32], a[43]); SQRADDAC(a[33], a[42]); SQRADDAC(a[34], a[41]); SQRADDAC(a[35], a[40]); SQRADDAC(a[36], a[39]); SQRADDAC(a[37], a[38]); SQRADDDB; + COMBA_STORE(b[75]); + + /* output 76 */ + CARRY_FORWARD; + SQRADDSC(a[13], a[63]); SQRADDAC(a[14], a[62]); SQRADDAC(a[15], a[61]); SQRADDAC(a[16], a[60]); SQRADDAC(a[17], a[59]); SQRADDAC(a[18], a[58]); SQRADDAC(a[19], a[57]); SQRADDAC(a[20], a[56]); SQRADDAC(a[21], a[55]); SQRADDAC(a[22], a[54]); SQRADDAC(a[23], a[53]); SQRADDAC(a[24], a[52]); SQRADDAC(a[25], a[51]); SQRADDAC(a[26], a[50]); SQRADDAC(a[27], a[49]); SQRADDAC(a[28], a[48]); SQRADDAC(a[29], a[47]); SQRADDAC(a[30], a[46]); SQRADDAC(a[31], a[45]); SQRADDAC(a[32], a[44]); SQRADDAC(a[33], a[43]); SQRADDAC(a[34], a[42]); SQRADDAC(a[35], a[41]); SQRADDAC(a[36], a[40]); SQRADDAC(a[37], a[39]); SQRADDDB; SQRADD(a[38], a[38]); + COMBA_STORE(b[76]); + + /* output 77 */ + CARRY_FORWARD; + SQRADDSC(a[14], a[63]); SQRADDAC(a[15], a[62]); SQRADDAC(a[16], a[61]); SQRADDAC(a[17], a[60]); SQRADDAC(a[18], a[59]); SQRADDAC(a[19], a[58]); SQRADDAC(a[20], a[57]); SQRADDAC(a[21], a[56]); SQRADDAC(a[22], a[55]); SQRADDAC(a[23], a[54]); SQRADDAC(a[24], a[53]); SQRADDAC(a[25], a[52]); SQRADDAC(a[26], a[51]); SQRADDAC(a[27], a[50]); SQRADDAC(a[28], a[49]); SQRADDAC(a[29], a[48]); SQRADDAC(a[30], a[47]); SQRADDAC(a[31], a[46]); SQRADDAC(a[32], a[45]); SQRADDAC(a[33], a[44]); SQRADDAC(a[34], a[43]); SQRADDAC(a[35], a[42]); SQRADDAC(a[36], a[41]); SQRADDAC(a[37], a[40]); SQRADDAC(a[38], a[39]); SQRADDDB; + COMBA_STORE(b[77]); + + /* output 78 */ + CARRY_FORWARD; + SQRADDSC(a[15], a[63]); SQRADDAC(a[16], a[62]); SQRADDAC(a[17], a[61]); SQRADDAC(a[18], a[60]); SQRADDAC(a[19], a[59]); SQRADDAC(a[20], a[58]); SQRADDAC(a[21], a[57]); SQRADDAC(a[22], a[56]); SQRADDAC(a[23], a[55]); SQRADDAC(a[24], a[54]); SQRADDAC(a[25], a[53]); SQRADDAC(a[26], a[52]); SQRADDAC(a[27], a[51]); SQRADDAC(a[28], a[50]); SQRADDAC(a[29], a[49]); SQRADDAC(a[30], a[48]); SQRADDAC(a[31], a[47]); SQRADDAC(a[32], a[46]); SQRADDAC(a[33], a[45]); SQRADDAC(a[34], a[44]); SQRADDAC(a[35], a[43]); SQRADDAC(a[36], a[42]); SQRADDAC(a[37], a[41]); SQRADDAC(a[38], a[40]); SQRADDDB; SQRADD(a[39], a[39]); + COMBA_STORE(b[78]); + + /* output 79 */ + CARRY_FORWARD; + SQRADDSC(a[16], a[63]); SQRADDAC(a[17], a[62]); SQRADDAC(a[18], a[61]); SQRADDAC(a[19], a[60]); SQRADDAC(a[20], a[59]); SQRADDAC(a[21], a[58]); SQRADDAC(a[22], a[57]); SQRADDAC(a[23], a[56]); SQRADDAC(a[24], a[55]); SQRADDAC(a[25], a[54]); SQRADDAC(a[26], a[53]); SQRADDAC(a[27], a[52]); SQRADDAC(a[28], a[51]); SQRADDAC(a[29], a[50]); SQRADDAC(a[30], a[49]); SQRADDAC(a[31], a[48]); SQRADDAC(a[32], a[47]); SQRADDAC(a[33], a[46]); SQRADDAC(a[34], a[45]); SQRADDAC(a[35], a[44]); SQRADDAC(a[36], a[43]); SQRADDAC(a[37], a[42]); SQRADDAC(a[38], a[41]); SQRADDAC(a[39], a[40]); SQRADDDB; + COMBA_STORE(b[79]); + + /* output 80 */ + CARRY_FORWARD; + SQRADDSC(a[17], a[63]); SQRADDAC(a[18], a[62]); SQRADDAC(a[19], a[61]); SQRADDAC(a[20], a[60]); SQRADDAC(a[21], a[59]); SQRADDAC(a[22], a[58]); SQRADDAC(a[23], a[57]); SQRADDAC(a[24], a[56]); SQRADDAC(a[25], a[55]); SQRADDAC(a[26], a[54]); SQRADDAC(a[27], a[53]); SQRADDAC(a[28], a[52]); SQRADDAC(a[29], a[51]); SQRADDAC(a[30], a[50]); SQRADDAC(a[31], a[49]); SQRADDAC(a[32], a[48]); SQRADDAC(a[33], a[47]); SQRADDAC(a[34], a[46]); SQRADDAC(a[35], a[45]); SQRADDAC(a[36], a[44]); SQRADDAC(a[37], a[43]); SQRADDAC(a[38], a[42]); SQRADDAC(a[39], a[41]); SQRADDDB; SQRADD(a[40], a[40]); + COMBA_STORE(b[80]); + + /* output 81 */ + CARRY_FORWARD; + SQRADDSC(a[18], a[63]); SQRADDAC(a[19], a[62]); SQRADDAC(a[20], a[61]); SQRADDAC(a[21], a[60]); SQRADDAC(a[22], a[59]); SQRADDAC(a[23], a[58]); SQRADDAC(a[24], a[57]); SQRADDAC(a[25], a[56]); SQRADDAC(a[26], a[55]); SQRADDAC(a[27], a[54]); SQRADDAC(a[28], a[53]); SQRADDAC(a[29], a[52]); SQRADDAC(a[30], a[51]); SQRADDAC(a[31], a[50]); SQRADDAC(a[32], a[49]); SQRADDAC(a[33], a[48]); SQRADDAC(a[34], a[47]); SQRADDAC(a[35], a[46]); SQRADDAC(a[36], a[45]); SQRADDAC(a[37], a[44]); SQRADDAC(a[38], a[43]); SQRADDAC(a[39], a[42]); SQRADDAC(a[40], a[41]); SQRADDDB; + COMBA_STORE(b[81]); + + /* output 82 */ + CARRY_FORWARD; + SQRADDSC(a[19], a[63]); SQRADDAC(a[20], a[62]); SQRADDAC(a[21], a[61]); SQRADDAC(a[22], a[60]); SQRADDAC(a[23], a[59]); SQRADDAC(a[24], a[58]); SQRADDAC(a[25], a[57]); SQRADDAC(a[26], a[56]); SQRADDAC(a[27], a[55]); SQRADDAC(a[28], a[54]); SQRADDAC(a[29], a[53]); SQRADDAC(a[30], a[52]); SQRADDAC(a[31], a[51]); SQRADDAC(a[32], a[50]); SQRADDAC(a[33], a[49]); SQRADDAC(a[34], a[48]); SQRADDAC(a[35], a[47]); SQRADDAC(a[36], a[46]); SQRADDAC(a[37], a[45]); SQRADDAC(a[38], a[44]); SQRADDAC(a[39], a[43]); SQRADDAC(a[40], a[42]); SQRADDDB; SQRADD(a[41], a[41]); + COMBA_STORE(b[82]); + + /* output 83 */ + CARRY_FORWARD; + SQRADDSC(a[20], a[63]); SQRADDAC(a[21], a[62]); SQRADDAC(a[22], a[61]); SQRADDAC(a[23], a[60]); SQRADDAC(a[24], a[59]); SQRADDAC(a[25], a[58]); SQRADDAC(a[26], a[57]); SQRADDAC(a[27], a[56]); SQRADDAC(a[28], a[55]); SQRADDAC(a[29], a[54]); SQRADDAC(a[30], a[53]); SQRADDAC(a[31], a[52]); SQRADDAC(a[32], a[51]); SQRADDAC(a[33], a[50]); SQRADDAC(a[34], a[49]); SQRADDAC(a[35], a[48]); SQRADDAC(a[36], a[47]); SQRADDAC(a[37], a[46]); SQRADDAC(a[38], a[45]); SQRADDAC(a[39], a[44]); SQRADDAC(a[40], a[43]); SQRADDAC(a[41], a[42]); SQRADDDB; + COMBA_STORE(b[83]); + + /* output 84 */ + CARRY_FORWARD; + SQRADDSC(a[21], a[63]); SQRADDAC(a[22], a[62]); SQRADDAC(a[23], a[61]); SQRADDAC(a[24], a[60]); SQRADDAC(a[25], a[59]); SQRADDAC(a[26], a[58]); SQRADDAC(a[27], a[57]); SQRADDAC(a[28], a[56]); SQRADDAC(a[29], a[55]); SQRADDAC(a[30], a[54]); SQRADDAC(a[31], a[53]); SQRADDAC(a[32], a[52]); SQRADDAC(a[33], a[51]); SQRADDAC(a[34], a[50]); SQRADDAC(a[35], a[49]); SQRADDAC(a[36], a[48]); SQRADDAC(a[37], a[47]); SQRADDAC(a[38], a[46]); SQRADDAC(a[39], a[45]); SQRADDAC(a[40], a[44]); SQRADDAC(a[41], a[43]); SQRADDDB; SQRADD(a[42], a[42]); + COMBA_STORE(b[84]); + + /* output 85 */ + CARRY_FORWARD; + SQRADDSC(a[22], a[63]); SQRADDAC(a[23], a[62]); SQRADDAC(a[24], a[61]); SQRADDAC(a[25], a[60]); SQRADDAC(a[26], a[59]); SQRADDAC(a[27], a[58]); SQRADDAC(a[28], a[57]); SQRADDAC(a[29], a[56]); SQRADDAC(a[30], a[55]); SQRADDAC(a[31], a[54]); SQRADDAC(a[32], a[53]); SQRADDAC(a[33], a[52]); SQRADDAC(a[34], a[51]); SQRADDAC(a[35], a[50]); SQRADDAC(a[36], a[49]); SQRADDAC(a[37], a[48]); SQRADDAC(a[38], a[47]); SQRADDAC(a[39], a[46]); SQRADDAC(a[40], a[45]); SQRADDAC(a[41], a[44]); SQRADDAC(a[42], a[43]); SQRADDDB; + COMBA_STORE(b[85]); + + /* output 86 */ + CARRY_FORWARD; + SQRADDSC(a[23], a[63]); SQRADDAC(a[24], a[62]); SQRADDAC(a[25], a[61]); SQRADDAC(a[26], a[60]); SQRADDAC(a[27], a[59]); SQRADDAC(a[28], a[58]); SQRADDAC(a[29], a[57]); SQRADDAC(a[30], a[56]); SQRADDAC(a[31], a[55]); SQRADDAC(a[32], a[54]); SQRADDAC(a[33], a[53]); SQRADDAC(a[34], a[52]); SQRADDAC(a[35], a[51]); SQRADDAC(a[36], a[50]); SQRADDAC(a[37], a[49]); SQRADDAC(a[38], a[48]); SQRADDAC(a[39], a[47]); SQRADDAC(a[40], a[46]); SQRADDAC(a[41], a[45]); SQRADDAC(a[42], a[44]); SQRADDDB; SQRADD(a[43], a[43]); + COMBA_STORE(b[86]); + + /* output 87 */ + CARRY_FORWARD; + SQRADDSC(a[24], a[63]); SQRADDAC(a[25], a[62]); SQRADDAC(a[26], a[61]); SQRADDAC(a[27], a[60]); SQRADDAC(a[28], a[59]); SQRADDAC(a[29], a[58]); SQRADDAC(a[30], a[57]); SQRADDAC(a[31], a[56]); SQRADDAC(a[32], a[55]); SQRADDAC(a[33], a[54]); SQRADDAC(a[34], a[53]); SQRADDAC(a[35], a[52]); SQRADDAC(a[36], a[51]); SQRADDAC(a[37], a[50]); SQRADDAC(a[38], a[49]); SQRADDAC(a[39], a[48]); SQRADDAC(a[40], a[47]); SQRADDAC(a[41], a[46]); SQRADDAC(a[42], a[45]); SQRADDAC(a[43], a[44]); SQRADDDB; + COMBA_STORE(b[87]); + + /* output 88 */ + CARRY_FORWARD; + SQRADDSC(a[25], a[63]); SQRADDAC(a[26], a[62]); SQRADDAC(a[27], a[61]); SQRADDAC(a[28], a[60]); SQRADDAC(a[29], a[59]); SQRADDAC(a[30], a[58]); SQRADDAC(a[31], a[57]); SQRADDAC(a[32], a[56]); SQRADDAC(a[33], a[55]); SQRADDAC(a[34], a[54]); SQRADDAC(a[35], a[53]); SQRADDAC(a[36], a[52]); SQRADDAC(a[37], a[51]); SQRADDAC(a[38], a[50]); SQRADDAC(a[39], a[49]); SQRADDAC(a[40], a[48]); SQRADDAC(a[41], a[47]); SQRADDAC(a[42], a[46]); SQRADDAC(a[43], a[45]); SQRADDDB; SQRADD(a[44], a[44]); + COMBA_STORE(b[88]); + + /* output 89 */ + CARRY_FORWARD; + SQRADDSC(a[26], a[63]); SQRADDAC(a[27], a[62]); SQRADDAC(a[28], a[61]); SQRADDAC(a[29], a[60]); SQRADDAC(a[30], a[59]); SQRADDAC(a[31], a[58]); SQRADDAC(a[32], a[57]); SQRADDAC(a[33], a[56]); SQRADDAC(a[34], a[55]); SQRADDAC(a[35], a[54]); SQRADDAC(a[36], a[53]); SQRADDAC(a[37], a[52]); SQRADDAC(a[38], a[51]); SQRADDAC(a[39], a[50]); SQRADDAC(a[40], a[49]); SQRADDAC(a[41], a[48]); SQRADDAC(a[42], a[47]); SQRADDAC(a[43], a[46]); SQRADDAC(a[44], a[45]); SQRADDDB; + COMBA_STORE(b[89]); + + /* output 90 */ + CARRY_FORWARD; + SQRADDSC(a[27], a[63]); SQRADDAC(a[28], a[62]); SQRADDAC(a[29], a[61]); SQRADDAC(a[30], a[60]); SQRADDAC(a[31], a[59]); SQRADDAC(a[32], a[58]); SQRADDAC(a[33], a[57]); SQRADDAC(a[34], a[56]); SQRADDAC(a[35], a[55]); SQRADDAC(a[36], a[54]); SQRADDAC(a[37], a[53]); SQRADDAC(a[38], a[52]); SQRADDAC(a[39], a[51]); SQRADDAC(a[40], a[50]); SQRADDAC(a[41], a[49]); SQRADDAC(a[42], a[48]); SQRADDAC(a[43], a[47]); SQRADDAC(a[44], a[46]); SQRADDDB; SQRADD(a[45], a[45]); + COMBA_STORE(b[90]); + + /* output 91 */ + CARRY_FORWARD; + SQRADDSC(a[28], a[63]); SQRADDAC(a[29], a[62]); SQRADDAC(a[30], a[61]); SQRADDAC(a[31], a[60]); SQRADDAC(a[32], a[59]); SQRADDAC(a[33], a[58]); SQRADDAC(a[34], a[57]); SQRADDAC(a[35], a[56]); SQRADDAC(a[36], a[55]); SQRADDAC(a[37], a[54]); SQRADDAC(a[38], a[53]); SQRADDAC(a[39], a[52]); SQRADDAC(a[40], a[51]); SQRADDAC(a[41], a[50]); SQRADDAC(a[42], a[49]); SQRADDAC(a[43], a[48]); SQRADDAC(a[44], a[47]); SQRADDAC(a[45], a[46]); SQRADDDB; + COMBA_STORE(b[91]); + + /* output 92 */ + CARRY_FORWARD; + SQRADDSC(a[29], a[63]); SQRADDAC(a[30], a[62]); SQRADDAC(a[31], a[61]); SQRADDAC(a[32], a[60]); SQRADDAC(a[33], a[59]); SQRADDAC(a[34], a[58]); SQRADDAC(a[35], a[57]); SQRADDAC(a[36], a[56]); SQRADDAC(a[37], a[55]); SQRADDAC(a[38], a[54]); SQRADDAC(a[39], a[53]); SQRADDAC(a[40], a[52]); SQRADDAC(a[41], a[51]); SQRADDAC(a[42], a[50]); SQRADDAC(a[43], a[49]); SQRADDAC(a[44], a[48]); SQRADDAC(a[45], a[47]); SQRADDDB; SQRADD(a[46], a[46]); + COMBA_STORE(b[92]); + + /* output 93 */ + CARRY_FORWARD; + SQRADDSC(a[30], a[63]); SQRADDAC(a[31], a[62]); SQRADDAC(a[32], a[61]); SQRADDAC(a[33], a[60]); SQRADDAC(a[34], a[59]); SQRADDAC(a[35], a[58]); SQRADDAC(a[36], a[57]); SQRADDAC(a[37], a[56]); SQRADDAC(a[38], a[55]); SQRADDAC(a[39], a[54]); SQRADDAC(a[40], a[53]); SQRADDAC(a[41], a[52]); SQRADDAC(a[42], a[51]); SQRADDAC(a[43], a[50]); SQRADDAC(a[44], a[49]); SQRADDAC(a[45], a[48]); SQRADDAC(a[46], a[47]); SQRADDDB; + COMBA_STORE(b[93]); + + /* output 94 */ + CARRY_FORWARD; + SQRADDSC(a[31], a[63]); SQRADDAC(a[32], a[62]); SQRADDAC(a[33], a[61]); SQRADDAC(a[34], a[60]); SQRADDAC(a[35], a[59]); SQRADDAC(a[36], a[58]); SQRADDAC(a[37], a[57]); SQRADDAC(a[38], a[56]); SQRADDAC(a[39], a[55]); SQRADDAC(a[40], a[54]); SQRADDAC(a[41], a[53]); SQRADDAC(a[42], a[52]); SQRADDAC(a[43], a[51]); SQRADDAC(a[44], a[50]); SQRADDAC(a[45], a[49]); SQRADDAC(a[46], a[48]); SQRADDDB; SQRADD(a[47], a[47]); + COMBA_STORE(b[94]); + + /* output 95 */ + CARRY_FORWARD; + SQRADDSC(a[32], a[63]); SQRADDAC(a[33], a[62]); SQRADDAC(a[34], a[61]); SQRADDAC(a[35], a[60]); SQRADDAC(a[36], a[59]); SQRADDAC(a[37], a[58]); SQRADDAC(a[38], a[57]); SQRADDAC(a[39], a[56]); SQRADDAC(a[40], a[55]); SQRADDAC(a[41], a[54]); SQRADDAC(a[42], a[53]); SQRADDAC(a[43], a[52]); SQRADDAC(a[44], a[51]); SQRADDAC(a[45], a[50]); SQRADDAC(a[46], a[49]); SQRADDAC(a[47], a[48]); SQRADDDB; + COMBA_STORE(b[95]); + + /* output 96 */ + CARRY_FORWARD; + SQRADDSC(a[33], a[63]); SQRADDAC(a[34], a[62]); SQRADDAC(a[35], a[61]); SQRADDAC(a[36], a[60]); SQRADDAC(a[37], a[59]); SQRADDAC(a[38], a[58]); SQRADDAC(a[39], a[57]); SQRADDAC(a[40], a[56]); SQRADDAC(a[41], a[55]); SQRADDAC(a[42], a[54]); SQRADDAC(a[43], a[53]); SQRADDAC(a[44], a[52]); SQRADDAC(a[45], a[51]); SQRADDAC(a[46], a[50]); SQRADDAC(a[47], a[49]); SQRADDDB; SQRADD(a[48], a[48]); + COMBA_STORE(b[96]); + + /* output 97 */ + CARRY_FORWARD; + SQRADDSC(a[34], a[63]); SQRADDAC(a[35], a[62]); SQRADDAC(a[36], a[61]); SQRADDAC(a[37], a[60]); SQRADDAC(a[38], a[59]); SQRADDAC(a[39], a[58]); SQRADDAC(a[40], a[57]); SQRADDAC(a[41], a[56]); SQRADDAC(a[42], a[55]); SQRADDAC(a[43], a[54]); SQRADDAC(a[44], a[53]); SQRADDAC(a[45], a[52]); SQRADDAC(a[46], a[51]); SQRADDAC(a[47], a[50]); SQRADDAC(a[48], a[49]); SQRADDDB; + COMBA_STORE(b[97]); + + /* output 98 */ + CARRY_FORWARD; + SQRADDSC(a[35], a[63]); SQRADDAC(a[36], a[62]); SQRADDAC(a[37], a[61]); SQRADDAC(a[38], a[60]); SQRADDAC(a[39], a[59]); SQRADDAC(a[40], a[58]); SQRADDAC(a[41], a[57]); SQRADDAC(a[42], a[56]); SQRADDAC(a[43], a[55]); SQRADDAC(a[44], a[54]); SQRADDAC(a[45], a[53]); SQRADDAC(a[46], a[52]); SQRADDAC(a[47], a[51]); SQRADDAC(a[48], a[50]); SQRADDDB; SQRADD(a[49], a[49]); + COMBA_STORE(b[98]); + + /* output 99 */ + CARRY_FORWARD; + SQRADDSC(a[36], a[63]); SQRADDAC(a[37], a[62]); SQRADDAC(a[38], a[61]); SQRADDAC(a[39], a[60]); SQRADDAC(a[40], a[59]); SQRADDAC(a[41], a[58]); SQRADDAC(a[42], a[57]); SQRADDAC(a[43], a[56]); SQRADDAC(a[44], a[55]); SQRADDAC(a[45], a[54]); SQRADDAC(a[46], a[53]); SQRADDAC(a[47], a[52]); SQRADDAC(a[48], a[51]); SQRADDAC(a[49], a[50]); SQRADDDB; + COMBA_STORE(b[99]); + + /* output 100 */ + CARRY_FORWARD; + SQRADDSC(a[37], a[63]); SQRADDAC(a[38], a[62]); SQRADDAC(a[39], a[61]); SQRADDAC(a[40], a[60]); SQRADDAC(a[41], a[59]); SQRADDAC(a[42], a[58]); SQRADDAC(a[43], a[57]); SQRADDAC(a[44], a[56]); SQRADDAC(a[45], a[55]); SQRADDAC(a[46], a[54]); SQRADDAC(a[47], a[53]); SQRADDAC(a[48], a[52]); SQRADDAC(a[49], a[51]); SQRADDDB; SQRADD(a[50], a[50]); + COMBA_STORE(b[100]); + + /* output 101 */ + CARRY_FORWARD; + SQRADDSC(a[38], a[63]); SQRADDAC(a[39], a[62]); SQRADDAC(a[40], a[61]); SQRADDAC(a[41], a[60]); SQRADDAC(a[42], a[59]); SQRADDAC(a[43], a[58]); SQRADDAC(a[44], a[57]); SQRADDAC(a[45], a[56]); SQRADDAC(a[46], a[55]); SQRADDAC(a[47], a[54]); SQRADDAC(a[48], a[53]); SQRADDAC(a[49], a[52]); SQRADDAC(a[50], a[51]); SQRADDDB; + COMBA_STORE(b[101]); + + /* output 102 */ + CARRY_FORWARD; + SQRADDSC(a[39], a[63]); SQRADDAC(a[40], a[62]); SQRADDAC(a[41], a[61]); SQRADDAC(a[42], a[60]); SQRADDAC(a[43], a[59]); SQRADDAC(a[44], a[58]); SQRADDAC(a[45], a[57]); SQRADDAC(a[46], a[56]); SQRADDAC(a[47], a[55]); SQRADDAC(a[48], a[54]); SQRADDAC(a[49], a[53]); SQRADDAC(a[50], a[52]); SQRADDDB; SQRADD(a[51], a[51]); + COMBA_STORE(b[102]); + + /* output 103 */ + CARRY_FORWARD; + SQRADDSC(a[40], a[63]); SQRADDAC(a[41], a[62]); SQRADDAC(a[42], a[61]); SQRADDAC(a[43], a[60]); SQRADDAC(a[44], a[59]); SQRADDAC(a[45], a[58]); SQRADDAC(a[46], a[57]); SQRADDAC(a[47], a[56]); SQRADDAC(a[48], a[55]); SQRADDAC(a[49], a[54]); SQRADDAC(a[50], a[53]); SQRADDAC(a[51], a[52]); SQRADDDB; + COMBA_STORE(b[103]); + + /* output 104 */ + CARRY_FORWARD; + SQRADDSC(a[41], a[63]); SQRADDAC(a[42], a[62]); SQRADDAC(a[43], a[61]); SQRADDAC(a[44], a[60]); SQRADDAC(a[45], a[59]); SQRADDAC(a[46], a[58]); SQRADDAC(a[47], a[57]); SQRADDAC(a[48], a[56]); SQRADDAC(a[49], a[55]); SQRADDAC(a[50], a[54]); SQRADDAC(a[51], a[53]); SQRADDDB; SQRADD(a[52], a[52]); + COMBA_STORE(b[104]); + + /* output 105 */ + CARRY_FORWARD; + SQRADDSC(a[42], a[63]); SQRADDAC(a[43], a[62]); SQRADDAC(a[44], a[61]); SQRADDAC(a[45], a[60]); SQRADDAC(a[46], a[59]); SQRADDAC(a[47], a[58]); SQRADDAC(a[48], a[57]); SQRADDAC(a[49], a[56]); SQRADDAC(a[50], a[55]); SQRADDAC(a[51], a[54]); SQRADDAC(a[52], a[53]); SQRADDDB; + COMBA_STORE(b[105]); + + /* output 106 */ + CARRY_FORWARD; + SQRADDSC(a[43], a[63]); SQRADDAC(a[44], a[62]); SQRADDAC(a[45], a[61]); SQRADDAC(a[46], a[60]); SQRADDAC(a[47], a[59]); SQRADDAC(a[48], a[58]); SQRADDAC(a[49], a[57]); SQRADDAC(a[50], a[56]); SQRADDAC(a[51], a[55]); SQRADDAC(a[52], a[54]); SQRADDDB; SQRADD(a[53], a[53]); + COMBA_STORE(b[106]); + + /* output 107 */ + CARRY_FORWARD; + SQRADDSC(a[44], a[63]); SQRADDAC(a[45], a[62]); SQRADDAC(a[46], a[61]); SQRADDAC(a[47], a[60]); SQRADDAC(a[48], a[59]); SQRADDAC(a[49], a[58]); SQRADDAC(a[50], a[57]); SQRADDAC(a[51], a[56]); SQRADDAC(a[52], a[55]); SQRADDAC(a[53], a[54]); SQRADDDB; + COMBA_STORE(b[107]); + + /* output 108 */ + CARRY_FORWARD; + SQRADDSC(a[45], a[63]); SQRADDAC(a[46], a[62]); SQRADDAC(a[47], a[61]); SQRADDAC(a[48], a[60]); SQRADDAC(a[49], a[59]); SQRADDAC(a[50], a[58]); SQRADDAC(a[51], a[57]); SQRADDAC(a[52], a[56]); SQRADDAC(a[53], a[55]); SQRADDDB; SQRADD(a[54], a[54]); + COMBA_STORE(b[108]); + + /* output 109 */ + CARRY_FORWARD; + SQRADDSC(a[46], a[63]); SQRADDAC(a[47], a[62]); SQRADDAC(a[48], a[61]); SQRADDAC(a[49], a[60]); SQRADDAC(a[50], a[59]); SQRADDAC(a[51], a[58]); SQRADDAC(a[52], a[57]); SQRADDAC(a[53], a[56]); SQRADDAC(a[54], a[55]); SQRADDDB; + COMBA_STORE(b[109]); + + /* output 110 */ + CARRY_FORWARD; + SQRADDSC(a[47], a[63]); SQRADDAC(a[48], a[62]); SQRADDAC(a[49], a[61]); SQRADDAC(a[50], a[60]); SQRADDAC(a[51], a[59]); SQRADDAC(a[52], a[58]); SQRADDAC(a[53], a[57]); SQRADDAC(a[54], a[56]); SQRADDDB; SQRADD(a[55], a[55]); + COMBA_STORE(b[110]); + + /* output 111 */ + CARRY_FORWARD; + SQRADDSC(a[48], a[63]); SQRADDAC(a[49], a[62]); SQRADDAC(a[50], a[61]); SQRADDAC(a[51], a[60]); SQRADDAC(a[52], a[59]); SQRADDAC(a[53], a[58]); SQRADDAC(a[54], a[57]); SQRADDAC(a[55], a[56]); SQRADDDB; + COMBA_STORE(b[111]); + + /* output 112 */ + CARRY_FORWARD; + SQRADDSC(a[49], a[63]); SQRADDAC(a[50], a[62]); SQRADDAC(a[51], a[61]); SQRADDAC(a[52], a[60]); SQRADDAC(a[53], a[59]); SQRADDAC(a[54], a[58]); SQRADDAC(a[55], a[57]); SQRADDDB; SQRADD(a[56], a[56]); + COMBA_STORE(b[112]); + + /* output 113 */ + CARRY_FORWARD; + SQRADDSC(a[50], a[63]); SQRADDAC(a[51], a[62]); SQRADDAC(a[52], a[61]); SQRADDAC(a[53], a[60]); SQRADDAC(a[54], a[59]); SQRADDAC(a[55], a[58]); SQRADDAC(a[56], a[57]); SQRADDDB; + COMBA_STORE(b[113]); + + /* output 114 */ + CARRY_FORWARD; + SQRADDSC(a[51], a[63]); SQRADDAC(a[52], a[62]); SQRADDAC(a[53], a[61]); SQRADDAC(a[54], a[60]); SQRADDAC(a[55], a[59]); SQRADDAC(a[56], a[58]); SQRADDDB; SQRADD(a[57], a[57]); + COMBA_STORE(b[114]); + + /* output 115 */ + CARRY_FORWARD; + SQRADDSC(a[52], a[63]); SQRADDAC(a[53], a[62]); SQRADDAC(a[54], a[61]); SQRADDAC(a[55], a[60]); SQRADDAC(a[56], a[59]); SQRADDAC(a[57], a[58]); SQRADDDB; + COMBA_STORE(b[115]); + + /* output 116 */ + CARRY_FORWARD; + SQRADDSC(a[53], a[63]); SQRADDAC(a[54], a[62]); SQRADDAC(a[55], a[61]); SQRADDAC(a[56], a[60]); SQRADDAC(a[57], a[59]); SQRADDDB; SQRADD(a[58], a[58]); + COMBA_STORE(b[116]); + + /* output 117 */ + CARRY_FORWARD; + SQRADDSC(a[54], a[63]); SQRADDAC(a[55], a[62]); SQRADDAC(a[56], a[61]); SQRADDAC(a[57], a[60]); SQRADDAC(a[58], a[59]); SQRADDDB; + COMBA_STORE(b[117]); + + /* output 118 */ + CARRY_FORWARD; + SQRADDSC(a[55], a[63]); SQRADDAC(a[56], a[62]); SQRADDAC(a[57], a[61]); SQRADDAC(a[58], a[60]); SQRADDDB; SQRADD(a[59], a[59]); + COMBA_STORE(b[118]); + + /* output 119 */ + CARRY_FORWARD; + SQRADDSC(a[56], a[63]); SQRADDAC(a[57], a[62]); SQRADDAC(a[58], a[61]); SQRADDAC(a[59], a[60]); SQRADDDB; + COMBA_STORE(b[119]); + + /* output 120 */ + CARRY_FORWARD; + SQRADDSC(a[57], a[63]); SQRADDAC(a[58], a[62]); SQRADDAC(a[59], a[61]); SQRADDDB; SQRADD(a[60], a[60]); + COMBA_STORE(b[120]); + + /* output 121 */ + CARRY_FORWARD; + SQRADDSC(a[58], a[63]); SQRADDAC(a[59], a[62]); SQRADDAC(a[60], a[61]); SQRADDDB; + COMBA_STORE(b[121]); + + /* output 122 */ + CARRY_FORWARD; + SQRADD2(a[59], a[63]); SQRADD2(a[60], a[62]); SQRADD(a[61], a[61]); + COMBA_STORE(b[122]); + + /* output 123 */ + CARRY_FORWARD; + SQRADD2(a[60], a[63]); SQRADD2(a[61], a[62]); + COMBA_STORE(b[123]); + + /* output 124 */ + CARRY_FORWARD; + SQRADD2(a[61], a[63]); SQRADD(a[62], a[62]); + COMBA_STORE(b[124]); + + /* output 125 */ + CARRY_FORWARD; + SQRADD2(a[62], a[63]); + COMBA_STORE(b[125]); + + /* output 126 */ + CARRY_FORWARD; + SQRADD(a[63], a[63]); + COMBA_STORE(b[126]); + COMBA_STORE2(b[127]); + COMBA_FINI; + + B->used = 128; + B->sign = FP_ZPOS; + XMEMCPY(B->dp, b, 128 * sizeof(fp_digit)); + fp_clamp(B); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; +} +#endif + + diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_sqr_comba_7.i b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_sqr_comba_7.i new file mode 100755 index 0000000..7410cbb --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_sqr_comba_7.i @@ -0,0 +1,127 @@ +/* fp_sqr_comba_7.i + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifdef TFM_SQR7 +int fp_sqr_comba7(fp_int *A, fp_int *B) +{ + fp_digit *a, c0, c1, c2, sc0 = 0, sc1 = 0, sc2 = 0; +#ifdef TFM_ISO + fp_word tt; +#endif +#ifndef WOLFSSL_SMALL_STACK + fp_digit b[14]; +#else + fp_digit *b; +#endif + +#ifdef WOLFSSL_SMALL_STACK + b = (fp_digit*)XMALLOC(sizeof(fp_digit) * 14, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (b == NULL) + return FP_MEM; +#endif + + a = A->dp; + COMBA_START; + + /* clear carries */ + CLEAR_CARRY; + + /* output 0 */ + SQRADD(a[0],a[0]); + COMBA_STORE(b[0]); + + /* output 1 */ + CARRY_FORWARD; + SQRADD2(a[0], a[1]); + COMBA_STORE(b[1]); + + /* output 2 */ + CARRY_FORWARD; + SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]); + COMBA_STORE(b[2]); + + /* output 3 */ + CARRY_FORWARD; + SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]); + COMBA_STORE(b[3]); + + /* output 4 */ + CARRY_FORWARD; + SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]); + COMBA_STORE(b[4]); + + /* output 5 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB; + COMBA_STORE(b[5]); + + /* output 6 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]); + COMBA_STORE(b[6]); + + /* output 7 */ + CARRY_FORWARD; + SQRADDSC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB; + COMBA_STORE(b[7]); + + /* output 8 */ + CARRY_FORWARD; + SQRADD2(a[2], a[6]); SQRADD2(a[3], a[5]); SQRADD(a[4], a[4]); + COMBA_STORE(b[8]); + + /* output 9 */ + CARRY_FORWARD; + SQRADD2(a[3], a[6]); SQRADD2(a[4], a[5]); + COMBA_STORE(b[9]); + + /* output 10 */ + CARRY_FORWARD; + SQRADD2(a[4], a[6]); SQRADD(a[5], a[5]); + COMBA_STORE(b[10]); + + /* output 11 */ + CARRY_FORWARD; + SQRADD2(a[5], a[6]); + COMBA_STORE(b[11]); + + /* output 12 */ + CARRY_FORWARD; + SQRADD(a[6], a[6]); + COMBA_STORE(b[12]); + COMBA_STORE2(b[13]); + COMBA_FINI; + + B->used = 14; + B->sign = FP_ZPOS; + XMEMCPY(B->dp, b, 14 * sizeof(fp_digit)); + fp_clamp(B); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; +} +#endif + + diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_sqr_comba_8.i b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_sqr_comba_8.i new file mode 100755 index 0000000..f6a167a --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_sqr_comba_8.i @@ -0,0 +1,137 @@ +/* fp_sqr_comba_8.i + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifdef TFM_SQR8 +int fp_sqr_comba8(fp_int *A, fp_int *B) +{ + fp_digit *a, c0, c1, c2, sc0 = 0, sc1 = 0, sc2 = 0; +#ifdef TFM_ISO + fp_word tt; +#endif +#ifndef WOLFSSL_SMALL_STACK + fp_digit b[16]; +#else + fp_digit *b; +#endif + +#ifdef WOLFSSL_SMALL_STACK + b = (fp_digit*)XMALLOC(sizeof(fp_digit) * 16, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (b == NULL) + return FP_MEM; +#endif + + a = A->dp; + COMBA_START; + + /* clear carries */ + CLEAR_CARRY; + + /* output 0 */ + SQRADD(a[0],a[0]); + COMBA_STORE(b[0]); + + /* output 1 */ + CARRY_FORWARD; + SQRADD2(a[0], a[1]); + COMBA_STORE(b[1]); + + /* output 2 */ + CARRY_FORWARD; + SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]); + COMBA_STORE(b[2]); + + /* output 3 */ + CARRY_FORWARD; + SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]); + COMBA_STORE(b[3]); + + /* output 4 */ + CARRY_FORWARD; + SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]); + COMBA_STORE(b[4]); + + /* output 5 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB; + COMBA_STORE(b[5]); + + /* output 6 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]); + COMBA_STORE(b[6]); + + /* output 7 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[7]); SQRADDAC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB; + COMBA_STORE(b[7]); + + /* output 8 */ + CARRY_FORWARD; + SQRADDSC(a[1], a[7]); SQRADDAC(a[2], a[6]); SQRADDAC(a[3], a[5]); SQRADDDB; SQRADD(a[4], a[4]); + COMBA_STORE(b[8]); + + /* output 9 */ + CARRY_FORWARD; + SQRADDSC(a[2], a[7]); SQRADDAC(a[3], a[6]); SQRADDAC(a[4], a[5]); SQRADDDB; + COMBA_STORE(b[9]); + + /* output 10 */ + CARRY_FORWARD; + SQRADD2(a[3], a[7]); SQRADD2(a[4], a[6]); SQRADD(a[5], a[5]); + COMBA_STORE(b[10]); + + /* output 11 */ + CARRY_FORWARD; + SQRADD2(a[4], a[7]); SQRADD2(a[5], a[6]); + COMBA_STORE(b[11]); + + /* output 12 */ + CARRY_FORWARD; + SQRADD2(a[5], a[7]); SQRADD(a[6], a[6]); + COMBA_STORE(b[12]); + + /* output 13 */ + CARRY_FORWARD; + SQRADD2(a[6], a[7]); + COMBA_STORE(b[13]); + + /* output 14 */ + CARRY_FORWARD; + SQRADD(a[7], a[7]); + COMBA_STORE(b[14]); + COMBA_STORE2(b[15]); + COMBA_FINI; + + B->used = 16; + B->sign = FP_ZPOS; + XMEMCPY(B->dp, b, 16 * sizeof(fp_digit)); + fp_clamp(B); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; +} +#endif + + diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_sqr_comba_9.i b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_sqr_comba_9.i new file mode 100755 index 0000000..37f90d0 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_sqr_comba_9.i @@ -0,0 +1,147 @@ +/* fp_sqr_comba_9.i + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifdef TFM_SQR9 +int fp_sqr_comba9(fp_int *A, fp_int *B) +{ + fp_digit *a, c0, c1, c2, sc0 = 0, sc1 = 0, sc2 = 0; +#ifdef TFM_ISO + fp_word tt; +#endif +#ifndef WOLFSSL_SMALL_STACK + fp_digit b[18]; +#else + fp_digit *b; +#endif + +#ifdef WOLFSSL_SMALL_STACK + b = (fp_digit*)XMALLOC(sizeof(fp_digit) * 18, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (b == NULL) + return FP_MEM; +#endif + + a = A->dp; + COMBA_START; + + /* clear carries */ + CLEAR_CARRY; + + /* output 0 */ + SQRADD(a[0],a[0]); + COMBA_STORE(b[0]); + + /* output 1 */ + CARRY_FORWARD; + SQRADD2(a[0], a[1]); + COMBA_STORE(b[1]); + + /* output 2 */ + CARRY_FORWARD; + SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]); + COMBA_STORE(b[2]); + + /* output 3 */ + CARRY_FORWARD; + SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]); + COMBA_STORE(b[3]); + + /* output 4 */ + CARRY_FORWARD; + SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]); + COMBA_STORE(b[4]); + + /* output 5 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB; + COMBA_STORE(b[5]); + + /* output 6 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]); + COMBA_STORE(b[6]); + + /* output 7 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[7]); SQRADDAC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB; + COMBA_STORE(b[7]); + + /* output 8 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[8]); SQRADDAC(a[1], a[7]); SQRADDAC(a[2], a[6]); SQRADDAC(a[3], a[5]); SQRADDDB; SQRADD(a[4], a[4]); + COMBA_STORE(b[8]); + + /* output 9 */ + CARRY_FORWARD; + SQRADDSC(a[1], a[8]); SQRADDAC(a[2], a[7]); SQRADDAC(a[3], a[6]); SQRADDAC(a[4], a[5]); SQRADDDB; + COMBA_STORE(b[9]); + + /* output 10 */ + CARRY_FORWARD; + SQRADDSC(a[2], a[8]); SQRADDAC(a[3], a[7]); SQRADDAC(a[4], a[6]); SQRADDDB; SQRADD(a[5], a[5]); + COMBA_STORE(b[10]); + + /* output 11 */ + CARRY_FORWARD; + SQRADDSC(a[3], a[8]); SQRADDAC(a[4], a[7]); SQRADDAC(a[5], a[6]); SQRADDDB; + COMBA_STORE(b[11]); + + /* output 12 */ + CARRY_FORWARD; + SQRADD2(a[4], a[8]); SQRADD2(a[5], a[7]); SQRADD(a[6], a[6]); + COMBA_STORE(b[12]); + + /* output 13 */ + CARRY_FORWARD; + SQRADD2(a[5], a[8]); SQRADD2(a[6], a[7]); + COMBA_STORE(b[13]); + + /* output 14 */ + CARRY_FORWARD; + SQRADD2(a[6], a[8]); SQRADD(a[7], a[7]); + COMBA_STORE(b[14]); + + /* output 15 */ + CARRY_FORWARD; + SQRADD2(a[7], a[8]); + COMBA_STORE(b[15]); + + /* output 16 */ + CARRY_FORWARD; + SQRADD(a[8], a[8]); + COMBA_STORE(b[16]); + COMBA_STORE2(b[17]); + COMBA_FINI; + + B->used = 18; + B->sign = FP_ZPOS; + XMEMCPY(B->dp, b, 18 * sizeof(fp_digit)); + fp_clamp(B); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; +} +#endif + + diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_sqr_comba_small_set.i b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_sqr_comba_small_set.i new file mode 100755 index 0000000..dd28524 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/fp_sqr_comba_small_set.i @@ -0,0 +1,1558 @@ +/* fp_sqr_comba_small_set.i + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#if defined(TFM_SMALL_SET) +int fp_sqr_comba_small(fp_int *A, fp_int *B) +{ + fp_digit *a, c0, c1, c2, sc0 = 0, sc1 = 0, sc2 = 0; +#ifdef TFM_ISO + fp_word tt; +#endif +#ifndef WOLFSSL_SMALL_STACK + fp_digit b[32]; +#else + fp_digit *b; +#endif + +#ifdef WOLFSSL_SMALL_STACK + b = (fp_digit*)XMALLOC(sizeof(fp_digit) * 32, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (b == NULL) + return FP_MEM; +#endif + + switch (A->used) { + case 1: + a = A->dp; + COMBA_START; + + /* clear carries */ + CLEAR_CARRY; + + /* output 0 */ + SQRADD(a[0],a[0]); + COMBA_STORE(b[0]); + COMBA_STORE2(b[1]); + COMBA_FINI; + + B->used = 2; + B->sign = FP_ZPOS; + XMEMCPY(B->dp, b, 2 * sizeof(fp_digit)); + fp_clamp(B); + break; + + case 2: + a = A->dp; + COMBA_START; + + /* clear carries */ + CLEAR_CARRY; + + /* output 0 */ + SQRADD(a[0],a[0]); + COMBA_STORE(b[0]); + + /* output 1 */ + CARRY_FORWARD; + SQRADD2(a[0], a[1]); + COMBA_STORE(b[1]); + + /* output 2 */ + CARRY_FORWARD; + SQRADD(a[1], a[1]); + COMBA_STORE(b[2]); + COMBA_STORE2(b[3]); + COMBA_FINI; + + B->used = 4; + B->sign = FP_ZPOS; + XMEMCPY(B->dp, b, 4 * sizeof(fp_digit)); + fp_clamp(B); + break; + + case 3: + a = A->dp; + COMBA_START; + + /* clear carries */ + CLEAR_CARRY; + + /* output 0 */ + SQRADD(a[0],a[0]); + COMBA_STORE(b[0]); + + /* output 1 */ + CARRY_FORWARD; + SQRADD2(a[0], a[1]); + COMBA_STORE(b[1]); + + /* output 2 */ + CARRY_FORWARD; + SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]); + COMBA_STORE(b[2]); + + /* output 3 */ + CARRY_FORWARD; + SQRADD2(a[1], a[2]); + COMBA_STORE(b[3]); + + /* output 4 */ + CARRY_FORWARD; + SQRADD(a[2], a[2]); + COMBA_STORE(b[4]); + COMBA_STORE2(b[5]); + COMBA_FINI; + + B->used = 6; + B->sign = FP_ZPOS; + XMEMCPY(B->dp, b, 6 * sizeof(fp_digit)); + fp_clamp(B); + break; + + case 4: + a = A->dp; + COMBA_START; + + /* clear carries */ + CLEAR_CARRY; + + /* output 0 */ + SQRADD(a[0],a[0]); + COMBA_STORE(b[0]); + + /* output 1 */ + CARRY_FORWARD; + SQRADD2(a[0], a[1]); + COMBA_STORE(b[1]); + + /* output 2 */ + CARRY_FORWARD; + SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]); + COMBA_STORE(b[2]); + + /* output 3 */ + CARRY_FORWARD; + SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]); + COMBA_STORE(b[3]); + + /* output 4 */ + CARRY_FORWARD; + SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]); + COMBA_STORE(b[4]); + + /* output 5 */ + CARRY_FORWARD; + SQRADD2(a[2], a[3]); + COMBA_STORE(b[5]); + + /* output 6 */ + CARRY_FORWARD; + SQRADD(a[3], a[3]); + COMBA_STORE(b[6]); + COMBA_STORE2(b[7]); + COMBA_FINI; + + B->used = 8; + B->sign = FP_ZPOS; + XMEMCPY(B->dp, b, 8 * sizeof(fp_digit)); + fp_clamp(B); + break; + + case 5: + a = A->dp; + COMBA_START; + + /* clear carries */ + CLEAR_CARRY; + + /* output 0 */ + SQRADD(a[0],a[0]); + COMBA_STORE(b[0]); + + /* output 1 */ + CARRY_FORWARD; + SQRADD2(a[0], a[1]); + COMBA_STORE(b[1]); + + /* output 2 */ + CARRY_FORWARD; + SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]); + COMBA_STORE(b[2]); + + /* output 3 */ + CARRY_FORWARD; + SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]); + COMBA_STORE(b[3]); + + /* output 4 */ + CARRY_FORWARD; + SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]); + COMBA_STORE(b[4]); + + /* output 5 */ + CARRY_FORWARD; + SQRADD2(a[1], a[4]); SQRADD2(a[2], a[3]); + COMBA_STORE(b[5]); + + /* output 6 */ + CARRY_FORWARD; + SQRADD2(a[2], a[4]); SQRADD(a[3], a[3]); + COMBA_STORE(b[6]); + + /* output 7 */ + CARRY_FORWARD; + SQRADD2(a[3], a[4]); + COMBA_STORE(b[7]); + + /* output 8 */ + CARRY_FORWARD; + SQRADD(a[4], a[4]); + COMBA_STORE(b[8]); + COMBA_STORE2(b[9]); + COMBA_FINI; + + B->used = 10; + B->sign = FP_ZPOS; + XMEMCPY(B->dp, b, 10 * sizeof(fp_digit)); + fp_clamp(B); + break; + + case 6: + a = A->dp; + COMBA_START; + + /* clear carries */ + CLEAR_CARRY; + + /* output 0 */ + SQRADD(a[0],a[0]); + COMBA_STORE(b[0]); + + /* output 1 */ + CARRY_FORWARD; + SQRADD2(a[0], a[1]); + COMBA_STORE(b[1]); + + /* output 2 */ + CARRY_FORWARD; + SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]); + COMBA_STORE(b[2]); + + /* output 3 */ + CARRY_FORWARD; + SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]); + COMBA_STORE(b[3]); + + /* output 4 */ + CARRY_FORWARD; + SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]); + COMBA_STORE(b[4]); + + /* output 5 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB; + COMBA_STORE(b[5]); + + /* output 6 */ + CARRY_FORWARD; + SQRADD2(a[1], a[5]); SQRADD2(a[2], a[4]); SQRADD(a[3], a[3]); + COMBA_STORE(b[6]); + + /* output 7 */ + CARRY_FORWARD; + SQRADD2(a[2], a[5]); SQRADD2(a[3], a[4]); + COMBA_STORE(b[7]); + + /* output 8 */ + CARRY_FORWARD; + SQRADD2(a[3], a[5]); SQRADD(a[4], a[4]); + COMBA_STORE(b[8]); + + /* output 9 */ + CARRY_FORWARD; + SQRADD2(a[4], a[5]); + COMBA_STORE(b[9]); + + /* output 10 */ + CARRY_FORWARD; + SQRADD(a[5], a[5]); + COMBA_STORE(b[10]); + COMBA_STORE2(b[11]); + COMBA_FINI; + + B->used = 12; + B->sign = FP_ZPOS; + XMEMCPY(B->dp, b, 12 * sizeof(fp_digit)); + fp_clamp(B); + break; + + case 7: + a = A->dp; + COMBA_START; + + /* clear carries */ + CLEAR_CARRY; + + /* output 0 */ + SQRADD(a[0],a[0]); + COMBA_STORE(b[0]); + + /* output 1 */ + CARRY_FORWARD; + SQRADD2(a[0], a[1]); + COMBA_STORE(b[1]); + + /* output 2 */ + CARRY_FORWARD; + SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]); + COMBA_STORE(b[2]); + + /* output 3 */ + CARRY_FORWARD; + SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]); + COMBA_STORE(b[3]); + + /* output 4 */ + CARRY_FORWARD; + SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]); + COMBA_STORE(b[4]); + + /* output 5 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB; + COMBA_STORE(b[5]); + + /* output 6 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]); + COMBA_STORE(b[6]); + + /* output 7 */ + CARRY_FORWARD; + SQRADDSC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB; + COMBA_STORE(b[7]); + + /* output 8 */ + CARRY_FORWARD; + SQRADD2(a[2], a[6]); SQRADD2(a[3], a[5]); SQRADD(a[4], a[4]); + COMBA_STORE(b[8]); + + /* output 9 */ + CARRY_FORWARD; + SQRADD2(a[3], a[6]); SQRADD2(a[4], a[5]); + COMBA_STORE(b[9]); + + /* output 10 */ + CARRY_FORWARD; + SQRADD2(a[4], a[6]); SQRADD(a[5], a[5]); + COMBA_STORE(b[10]); + + /* output 11 */ + CARRY_FORWARD; + SQRADD2(a[5], a[6]); + COMBA_STORE(b[11]); + + /* output 12 */ + CARRY_FORWARD; + SQRADD(a[6], a[6]); + COMBA_STORE(b[12]); + COMBA_STORE2(b[13]); + COMBA_FINI; + + B->used = 14; + B->sign = FP_ZPOS; + XMEMCPY(B->dp, b, 14 * sizeof(fp_digit)); + fp_clamp(B); + break; + + case 8: + a = A->dp; + COMBA_START; + + /* clear carries */ + CLEAR_CARRY; + + /* output 0 */ + SQRADD(a[0],a[0]); + COMBA_STORE(b[0]); + + /* output 1 */ + CARRY_FORWARD; + SQRADD2(a[0], a[1]); + COMBA_STORE(b[1]); + + /* output 2 */ + CARRY_FORWARD; + SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]); + COMBA_STORE(b[2]); + + /* output 3 */ + CARRY_FORWARD; + SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]); + COMBA_STORE(b[3]); + + /* output 4 */ + CARRY_FORWARD; + SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]); + COMBA_STORE(b[4]); + + /* output 5 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB; + COMBA_STORE(b[5]); + + /* output 6 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]); + COMBA_STORE(b[6]); + + /* output 7 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[7]); SQRADDAC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB; + COMBA_STORE(b[7]); + + /* output 8 */ + CARRY_FORWARD; + SQRADDSC(a[1], a[7]); SQRADDAC(a[2], a[6]); SQRADDAC(a[3], a[5]); SQRADDDB; SQRADD(a[4], a[4]); + COMBA_STORE(b[8]); + + /* output 9 */ + CARRY_FORWARD; + SQRADDSC(a[2], a[7]); SQRADDAC(a[3], a[6]); SQRADDAC(a[4], a[5]); SQRADDDB; + COMBA_STORE(b[9]); + + /* output 10 */ + CARRY_FORWARD; + SQRADD2(a[3], a[7]); SQRADD2(a[4], a[6]); SQRADD(a[5], a[5]); + COMBA_STORE(b[10]); + + /* output 11 */ + CARRY_FORWARD; + SQRADD2(a[4], a[7]); SQRADD2(a[5], a[6]); + COMBA_STORE(b[11]); + + /* output 12 */ + CARRY_FORWARD; + SQRADD2(a[5], a[7]); SQRADD(a[6], a[6]); + COMBA_STORE(b[12]); + + /* output 13 */ + CARRY_FORWARD; + SQRADD2(a[6], a[7]); + COMBA_STORE(b[13]); + + /* output 14 */ + CARRY_FORWARD; + SQRADD(a[7], a[7]); + COMBA_STORE(b[14]); + COMBA_STORE2(b[15]); + COMBA_FINI; + + B->used = 16; + B->sign = FP_ZPOS; + XMEMCPY(B->dp, b, 16 * sizeof(fp_digit)); + fp_clamp(B); + break; + + case 9: + a = A->dp; + COMBA_START; + + /* clear carries */ + CLEAR_CARRY; + + /* output 0 */ + SQRADD(a[0],a[0]); + COMBA_STORE(b[0]); + + /* output 1 */ + CARRY_FORWARD; + SQRADD2(a[0], a[1]); + COMBA_STORE(b[1]); + + /* output 2 */ + CARRY_FORWARD; + SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]); + COMBA_STORE(b[2]); + + /* output 3 */ + CARRY_FORWARD; + SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]); + COMBA_STORE(b[3]); + + /* output 4 */ + CARRY_FORWARD; + SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]); + COMBA_STORE(b[4]); + + /* output 5 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB; + COMBA_STORE(b[5]); + + /* output 6 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]); + COMBA_STORE(b[6]); + + /* output 7 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[7]); SQRADDAC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB; + COMBA_STORE(b[7]); + + /* output 8 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[8]); SQRADDAC(a[1], a[7]); SQRADDAC(a[2], a[6]); SQRADDAC(a[3], a[5]); SQRADDDB; SQRADD(a[4], a[4]); + COMBA_STORE(b[8]); + + /* output 9 */ + CARRY_FORWARD; + SQRADDSC(a[1], a[8]); SQRADDAC(a[2], a[7]); SQRADDAC(a[3], a[6]); SQRADDAC(a[4], a[5]); SQRADDDB; + COMBA_STORE(b[9]); + + /* output 10 */ + CARRY_FORWARD; + SQRADDSC(a[2], a[8]); SQRADDAC(a[3], a[7]); SQRADDAC(a[4], a[6]); SQRADDDB; SQRADD(a[5], a[5]); + COMBA_STORE(b[10]); + + /* output 11 */ + CARRY_FORWARD; + SQRADDSC(a[3], a[8]); SQRADDAC(a[4], a[7]); SQRADDAC(a[5], a[6]); SQRADDDB; + COMBA_STORE(b[11]); + + /* output 12 */ + CARRY_FORWARD; + SQRADD2(a[4], a[8]); SQRADD2(a[5], a[7]); SQRADD(a[6], a[6]); + COMBA_STORE(b[12]); + + /* output 13 */ + CARRY_FORWARD; + SQRADD2(a[5], a[8]); SQRADD2(a[6], a[7]); + COMBA_STORE(b[13]); + + /* output 14 */ + CARRY_FORWARD; + SQRADD2(a[6], a[8]); SQRADD(a[7], a[7]); + COMBA_STORE(b[14]); + + /* output 15 */ + CARRY_FORWARD; + SQRADD2(a[7], a[8]); + COMBA_STORE(b[15]); + + /* output 16 */ + CARRY_FORWARD; + SQRADD(a[8], a[8]); + COMBA_STORE(b[16]); + COMBA_STORE2(b[17]); + COMBA_FINI; + + B->used = 18; + B->sign = FP_ZPOS; + XMEMCPY(B->dp, b, 18 * sizeof(fp_digit)); + fp_clamp(B); + break; + + case 10: + a = A->dp; + COMBA_START; + + /* clear carries */ + CLEAR_CARRY; + + /* output 0 */ + SQRADD(a[0],a[0]); + COMBA_STORE(b[0]); + + /* output 1 */ + CARRY_FORWARD; + SQRADD2(a[0], a[1]); + COMBA_STORE(b[1]); + + /* output 2 */ + CARRY_FORWARD; + SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]); + COMBA_STORE(b[2]); + + /* output 3 */ + CARRY_FORWARD; + SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]); + COMBA_STORE(b[3]); + + /* output 4 */ + CARRY_FORWARD; + SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]); + COMBA_STORE(b[4]); + + /* output 5 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB; + COMBA_STORE(b[5]); + + /* output 6 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]); + COMBA_STORE(b[6]); + + /* output 7 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[7]); SQRADDAC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB; + COMBA_STORE(b[7]); + + /* output 8 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[8]); SQRADDAC(a[1], a[7]); SQRADDAC(a[2], a[6]); SQRADDAC(a[3], a[5]); SQRADDDB; SQRADD(a[4], a[4]); + COMBA_STORE(b[8]); + + /* output 9 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[9]); SQRADDAC(a[1], a[8]); SQRADDAC(a[2], a[7]); SQRADDAC(a[3], a[6]); SQRADDAC(a[4], a[5]); SQRADDDB; + COMBA_STORE(b[9]); + + /* output 10 */ + CARRY_FORWARD; + SQRADDSC(a[1], a[9]); SQRADDAC(a[2], a[8]); SQRADDAC(a[3], a[7]); SQRADDAC(a[4], a[6]); SQRADDDB; SQRADD(a[5], a[5]); + COMBA_STORE(b[10]); + + /* output 11 */ + CARRY_FORWARD; + SQRADDSC(a[2], a[9]); SQRADDAC(a[3], a[8]); SQRADDAC(a[4], a[7]); SQRADDAC(a[5], a[6]); SQRADDDB; + COMBA_STORE(b[11]); + + /* output 12 */ + CARRY_FORWARD; + SQRADDSC(a[3], a[9]); SQRADDAC(a[4], a[8]); SQRADDAC(a[5], a[7]); SQRADDDB; SQRADD(a[6], a[6]); + COMBA_STORE(b[12]); + + /* output 13 */ + CARRY_FORWARD; + SQRADDSC(a[4], a[9]); SQRADDAC(a[5], a[8]); SQRADDAC(a[6], a[7]); SQRADDDB; + COMBA_STORE(b[13]); + + /* output 14 */ + CARRY_FORWARD; + SQRADD2(a[5], a[9]); SQRADD2(a[6], a[8]); SQRADD(a[7], a[7]); + COMBA_STORE(b[14]); + + /* output 15 */ + CARRY_FORWARD; + SQRADD2(a[6], a[9]); SQRADD2(a[7], a[8]); + COMBA_STORE(b[15]); + + /* output 16 */ + CARRY_FORWARD; + SQRADD2(a[7], a[9]); SQRADD(a[8], a[8]); + COMBA_STORE(b[16]); + + /* output 17 */ + CARRY_FORWARD; + SQRADD2(a[8], a[9]); + COMBA_STORE(b[17]); + + /* output 18 */ + CARRY_FORWARD; + SQRADD(a[9], a[9]); + COMBA_STORE(b[18]); + COMBA_STORE2(b[19]); + COMBA_FINI; + + B->used = 20; + B->sign = FP_ZPOS; + XMEMCPY(B->dp, b, 20 * sizeof(fp_digit)); + fp_clamp(B); + break; + + case 11: + a = A->dp; + COMBA_START; + + /* clear carries */ + CLEAR_CARRY; + + /* output 0 */ + SQRADD(a[0],a[0]); + COMBA_STORE(b[0]); + + /* output 1 */ + CARRY_FORWARD; + SQRADD2(a[0], a[1]); + COMBA_STORE(b[1]); + + /* output 2 */ + CARRY_FORWARD; + SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]); + COMBA_STORE(b[2]); + + /* output 3 */ + CARRY_FORWARD; + SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]); + COMBA_STORE(b[3]); + + /* output 4 */ + CARRY_FORWARD; + SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]); + COMBA_STORE(b[4]); + + /* output 5 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB; + COMBA_STORE(b[5]); + + /* output 6 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]); + COMBA_STORE(b[6]); + + /* output 7 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[7]); SQRADDAC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB; + COMBA_STORE(b[7]); + + /* output 8 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[8]); SQRADDAC(a[1], a[7]); SQRADDAC(a[2], a[6]); SQRADDAC(a[3], a[5]); SQRADDDB; SQRADD(a[4], a[4]); + COMBA_STORE(b[8]); + + /* output 9 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[9]); SQRADDAC(a[1], a[8]); SQRADDAC(a[2], a[7]); SQRADDAC(a[3], a[6]); SQRADDAC(a[4], a[5]); SQRADDDB; + COMBA_STORE(b[9]); + + /* output 10 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[10]); SQRADDAC(a[1], a[9]); SQRADDAC(a[2], a[8]); SQRADDAC(a[3], a[7]); SQRADDAC(a[4], a[6]); SQRADDDB; SQRADD(a[5], a[5]); + COMBA_STORE(b[10]); + + /* output 11 */ + CARRY_FORWARD; + SQRADDSC(a[1], a[10]); SQRADDAC(a[2], a[9]); SQRADDAC(a[3], a[8]); SQRADDAC(a[4], a[7]); SQRADDAC(a[5], a[6]); SQRADDDB; + COMBA_STORE(b[11]); + + /* output 12 */ + CARRY_FORWARD; + SQRADDSC(a[2], a[10]); SQRADDAC(a[3], a[9]); SQRADDAC(a[4], a[8]); SQRADDAC(a[5], a[7]); SQRADDDB; SQRADD(a[6], a[6]); + COMBA_STORE(b[12]); + + /* output 13 */ + CARRY_FORWARD; + SQRADDSC(a[3], a[10]); SQRADDAC(a[4], a[9]); SQRADDAC(a[5], a[8]); SQRADDAC(a[6], a[7]); SQRADDDB; + COMBA_STORE(b[13]); + + /* output 14 */ + CARRY_FORWARD; + SQRADDSC(a[4], a[10]); SQRADDAC(a[5], a[9]); SQRADDAC(a[6], a[8]); SQRADDDB; SQRADD(a[7], a[7]); + COMBA_STORE(b[14]); + + /* output 15 */ + CARRY_FORWARD; + SQRADDSC(a[5], a[10]); SQRADDAC(a[6], a[9]); SQRADDAC(a[7], a[8]); SQRADDDB; + COMBA_STORE(b[15]); + + /* output 16 */ + CARRY_FORWARD; + SQRADD2(a[6], a[10]); SQRADD2(a[7], a[9]); SQRADD(a[8], a[8]); + COMBA_STORE(b[16]); + + /* output 17 */ + CARRY_FORWARD; + SQRADD2(a[7], a[10]); SQRADD2(a[8], a[9]); + COMBA_STORE(b[17]); + + /* output 18 */ + CARRY_FORWARD; + SQRADD2(a[8], a[10]); SQRADD(a[9], a[9]); + COMBA_STORE(b[18]); + + /* output 19 */ + CARRY_FORWARD; + SQRADD2(a[9], a[10]); + COMBA_STORE(b[19]); + + /* output 20 */ + CARRY_FORWARD; + SQRADD(a[10], a[10]); + COMBA_STORE(b[20]); + COMBA_STORE2(b[21]); + COMBA_FINI; + + B->used = 22; + B->sign = FP_ZPOS; + XMEMCPY(B->dp, b, 22 * sizeof(fp_digit)); + fp_clamp(B); + break; + + case 12: + a = A->dp; + COMBA_START; + + /* clear carries */ + CLEAR_CARRY; + + /* output 0 */ + SQRADD(a[0],a[0]); + COMBA_STORE(b[0]); + + /* output 1 */ + CARRY_FORWARD; + SQRADD2(a[0], a[1]); + COMBA_STORE(b[1]); + + /* output 2 */ + CARRY_FORWARD; + SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]); + COMBA_STORE(b[2]); + + /* output 3 */ + CARRY_FORWARD; + SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]); + COMBA_STORE(b[3]); + + /* output 4 */ + CARRY_FORWARD; + SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]); + COMBA_STORE(b[4]); + + /* output 5 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB; + COMBA_STORE(b[5]); + + /* output 6 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]); + COMBA_STORE(b[6]); + + /* output 7 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[7]); SQRADDAC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB; + COMBA_STORE(b[7]); + + /* output 8 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[8]); SQRADDAC(a[1], a[7]); SQRADDAC(a[2], a[6]); SQRADDAC(a[3], a[5]); SQRADDDB; SQRADD(a[4], a[4]); + COMBA_STORE(b[8]); + + /* output 9 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[9]); SQRADDAC(a[1], a[8]); SQRADDAC(a[2], a[7]); SQRADDAC(a[3], a[6]); SQRADDAC(a[4], a[5]); SQRADDDB; + COMBA_STORE(b[9]); + + /* output 10 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[10]); SQRADDAC(a[1], a[9]); SQRADDAC(a[2], a[8]); SQRADDAC(a[3], a[7]); SQRADDAC(a[4], a[6]); SQRADDDB; SQRADD(a[5], a[5]); + COMBA_STORE(b[10]); + + /* output 11 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[11]); SQRADDAC(a[1], a[10]); SQRADDAC(a[2], a[9]); SQRADDAC(a[3], a[8]); SQRADDAC(a[4], a[7]); SQRADDAC(a[5], a[6]); SQRADDDB; + COMBA_STORE(b[11]); + + /* output 12 */ + CARRY_FORWARD; + SQRADDSC(a[1], a[11]); SQRADDAC(a[2], a[10]); SQRADDAC(a[3], a[9]); SQRADDAC(a[4], a[8]); SQRADDAC(a[5], a[7]); SQRADDDB; SQRADD(a[6], a[6]); + COMBA_STORE(b[12]); + + /* output 13 */ + CARRY_FORWARD; + SQRADDSC(a[2], a[11]); SQRADDAC(a[3], a[10]); SQRADDAC(a[4], a[9]); SQRADDAC(a[5], a[8]); SQRADDAC(a[6], a[7]); SQRADDDB; + COMBA_STORE(b[13]); + + /* output 14 */ + CARRY_FORWARD; + SQRADDSC(a[3], a[11]); SQRADDAC(a[4], a[10]); SQRADDAC(a[5], a[9]); SQRADDAC(a[6], a[8]); SQRADDDB; SQRADD(a[7], a[7]); + COMBA_STORE(b[14]); + + /* output 15 */ + CARRY_FORWARD; + SQRADDSC(a[4], a[11]); SQRADDAC(a[5], a[10]); SQRADDAC(a[6], a[9]); SQRADDAC(a[7], a[8]); SQRADDDB; + COMBA_STORE(b[15]); + + /* output 16 */ + CARRY_FORWARD; + SQRADDSC(a[5], a[11]); SQRADDAC(a[6], a[10]); SQRADDAC(a[7], a[9]); SQRADDDB; SQRADD(a[8], a[8]); + COMBA_STORE(b[16]); + + /* output 17 */ + CARRY_FORWARD; + SQRADDSC(a[6], a[11]); SQRADDAC(a[7], a[10]); SQRADDAC(a[8], a[9]); SQRADDDB; + COMBA_STORE(b[17]); + + /* output 18 */ + CARRY_FORWARD; + SQRADD2(a[7], a[11]); SQRADD2(a[8], a[10]); SQRADD(a[9], a[9]); + COMBA_STORE(b[18]); + + /* output 19 */ + CARRY_FORWARD; + SQRADD2(a[8], a[11]); SQRADD2(a[9], a[10]); + COMBA_STORE(b[19]); + + /* output 20 */ + CARRY_FORWARD; + SQRADD2(a[9], a[11]); SQRADD(a[10], a[10]); + COMBA_STORE(b[20]); + + /* output 21 */ + CARRY_FORWARD; + SQRADD2(a[10], a[11]); + COMBA_STORE(b[21]); + + /* output 22 */ + CARRY_FORWARD; + SQRADD(a[11], a[11]); + COMBA_STORE(b[22]); + COMBA_STORE2(b[23]); + COMBA_FINI; + + B->used = 24; + B->sign = FP_ZPOS; + XMEMCPY(B->dp, b, 24 * sizeof(fp_digit)); + fp_clamp(B); + break; + + case 13: + a = A->dp; + COMBA_START; + + /* clear carries */ + CLEAR_CARRY; + + /* output 0 */ + SQRADD(a[0],a[0]); + COMBA_STORE(b[0]); + + /* output 1 */ + CARRY_FORWARD; + SQRADD2(a[0], a[1]); + COMBA_STORE(b[1]); + + /* output 2 */ + CARRY_FORWARD; + SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]); + COMBA_STORE(b[2]); + + /* output 3 */ + CARRY_FORWARD; + SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]); + COMBA_STORE(b[3]); + + /* output 4 */ + CARRY_FORWARD; + SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]); + COMBA_STORE(b[4]); + + /* output 5 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB; + COMBA_STORE(b[5]); + + /* output 6 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]); + COMBA_STORE(b[6]); + + /* output 7 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[7]); SQRADDAC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB; + COMBA_STORE(b[7]); + + /* output 8 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[8]); SQRADDAC(a[1], a[7]); SQRADDAC(a[2], a[6]); SQRADDAC(a[3], a[5]); SQRADDDB; SQRADD(a[4], a[4]); + COMBA_STORE(b[8]); + + /* output 9 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[9]); SQRADDAC(a[1], a[8]); SQRADDAC(a[2], a[7]); SQRADDAC(a[3], a[6]); SQRADDAC(a[4], a[5]); SQRADDDB; + COMBA_STORE(b[9]); + + /* output 10 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[10]); SQRADDAC(a[1], a[9]); SQRADDAC(a[2], a[8]); SQRADDAC(a[3], a[7]); SQRADDAC(a[4], a[6]); SQRADDDB; SQRADD(a[5], a[5]); + COMBA_STORE(b[10]); + + /* output 11 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[11]); SQRADDAC(a[1], a[10]); SQRADDAC(a[2], a[9]); SQRADDAC(a[3], a[8]); SQRADDAC(a[4], a[7]); SQRADDAC(a[5], a[6]); SQRADDDB; + COMBA_STORE(b[11]); + + /* output 12 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[12]); SQRADDAC(a[1], a[11]); SQRADDAC(a[2], a[10]); SQRADDAC(a[3], a[9]); SQRADDAC(a[4], a[8]); SQRADDAC(a[5], a[7]); SQRADDDB; SQRADD(a[6], a[6]); + COMBA_STORE(b[12]); + + /* output 13 */ + CARRY_FORWARD; + SQRADDSC(a[1], a[12]); SQRADDAC(a[2], a[11]); SQRADDAC(a[3], a[10]); SQRADDAC(a[4], a[9]); SQRADDAC(a[5], a[8]); SQRADDAC(a[6], a[7]); SQRADDDB; + COMBA_STORE(b[13]); + + /* output 14 */ + CARRY_FORWARD; + SQRADDSC(a[2], a[12]); SQRADDAC(a[3], a[11]); SQRADDAC(a[4], a[10]); SQRADDAC(a[5], a[9]); SQRADDAC(a[6], a[8]); SQRADDDB; SQRADD(a[7], a[7]); + COMBA_STORE(b[14]); + + /* output 15 */ + CARRY_FORWARD; + SQRADDSC(a[3], a[12]); SQRADDAC(a[4], a[11]); SQRADDAC(a[5], a[10]); SQRADDAC(a[6], a[9]); SQRADDAC(a[7], a[8]); SQRADDDB; + COMBA_STORE(b[15]); + + /* output 16 */ + CARRY_FORWARD; + SQRADDSC(a[4], a[12]); SQRADDAC(a[5], a[11]); SQRADDAC(a[6], a[10]); SQRADDAC(a[7], a[9]); SQRADDDB; SQRADD(a[8], a[8]); + COMBA_STORE(b[16]); + + /* output 17 */ + CARRY_FORWARD; + SQRADDSC(a[5], a[12]); SQRADDAC(a[6], a[11]); SQRADDAC(a[7], a[10]); SQRADDAC(a[8], a[9]); SQRADDDB; + COMBA_STORE(b[17]); + + /* output 18 */ + CARRY_FORWARD; + SQRADDSC(a[6], a[12]); SQRADDAC(a[7], a[11]); SQRADDAC(a[8], a[10]); SQRADDDB; SQRADD(a[9], a[9]); + COMBA_STORE(b[18]); + + /* output 19 */ + CARRY_FORWARD; + SQRADDSC(a[7], a[12]); SQRADDAC(a[8], a[11]); SQRADDAC(a[9], a[10]); SQRADDDB; + COMBA_STORE(b[19]); + + /* output 20 */ + CARRY_FORWARD; + SQRADD2(a[8], a[12]); SQRADD2(a[9], a[11]); SQRADD(a[10], a[10]); + COMBA_STORE(b[20]); + + /* output 21 */ + CARRY_FORWARD; + SQRADD2(a[9], a[12]); SQRADD2(a[10], a[11]); + COMBA_STORE(b[21]); + + /* output 22 */ + CARRY_FORWARD; + SQRADD2(a[10], a[12]); SQRADD(a[11], a[11]); + COMBA_STORE(b[22]); + + /* output 23 */ + CARRY_FORWARD; + SQRADD2(a[11], a[12]); + COMBA_STORE(b[23]); + + /* output 24 */ + CARRY_FORWARD; + SQRADD(a[12], a[12]); + COMBA_STORE(b[24]); + COMBA_STORE2(b[25]); + COMBA_FINI; + + B->used = 26; + B->sign = FP_ZPOS; + XMEMCPY(B->dp, b, 26 * sizeof(fp_digit)); + fp_clamp(B); + break; + + case 14: + a = A->dp; + COMBA_START; + + /* clear carries */ + CLEAR_CARRY; + + /* output 0 */ + SQRADD(a[0],a[0]); + COMBA_STORE(b[0]); + + /* output 1 */ + CARRY_FORWARD; + SQRADD2(a[0], a[1]); + COMBA_STORE(b[1]); + + /* output 2 */ + CARRY_FORWARD; + SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]); + COMBA_STORE(b[2]); + + /* output 3 */ + CARRY_FORWARD; + SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]); + COMBA_STORE(b[3]); + + /* output 4 */ + CARRY_FORWARD; + SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]); + COMBA_STORE(b[4]); + + /* output 5 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB; + COMBA_STORE(b[5]); + + /* output 6 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]); + COMBA_STORE(b[6]); + + /* output 7 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[7]); SQRADDAC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB; + COMBA_STORE(b[7]); + + /* output 8 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[8]); SQRADDAC(a[1], a[7]); SQRADDAC(a[2], a[6]); SQRADDAC(a[3], a[5]); SQRADDDB; SQRADD(a[4], a[4]); + COMBA_STORE(b[8]); + + /* output 9 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[9]); SQRADDAC(a[1], a[8]); SQRADDAC(a[2], a[7]); SQRADDAC(a[3], a[6]); SQRADDAC(a[4], a[5]); SQRADDDB; + COMBA_STORE(b[9]); + + /* output 10 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[10]); SQRADDAC(a[1], a[9]); SQRADDAC(a[2], a[8]); SQRADDAC(a[3], a[7]); SQRADDAC(a[4], a[6]); SQRADDDB; SQRADD(a[5], a[5]); + COMBA_STORE(b[10]); + + /* output 11 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[11]); SQRADDAC(a[1], a[10]); SQRADDAC(a[2], a[9]); SQRADDAC(a[3], a[8]); SQRADDAC(a[4], a[7]); SQRADDAC(a[5], a[6]); SQRADDDB; + COMBA_STORE(b[11]); + + /* output 12 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[12]); SQRADDAC(a[1], a[11]); SQRADDAC(a[2], a[10]); SQRADDAC(a[3], a[9]); SQRADDAC(a[4], a[8]); SQRADDAC(a[5], a[7]); SQRADDDB; SQRADD(a[6], a[6]); + COMBA_STORE(b[12]); + + /* output 13 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[13]); SQRADDAC(a[1], a[12]); SQRADDAC(a[2], a[11]); SQRADDAC(a[3], a[10]); SQRADDAC(a[4], a[9]); SQRADDAC(a[5], a[8]); SQRADDAC(a[6], a[7]); SQRADDDB; + COMBA_STORE(b[13]); + + /* output 14 */ + CARRY_FORWARD; + SQRADDSC(a[1], a[13]); SQRADDAC(a[2], a[12]); SQRADDAC(a[3], a[11]); SQRADDAC(a[4], a[10]); SQRADDAC(a[5], a[9]); SQRADDAC(a[6], a[8]); SQRADDDB; SQRADD(a[7], a[7]); + COMBA_STORE(b[14]); + + /* output 15 */ + CARRY_FORWARD; + SQRADDSC(a[2], a[13]); SQRADDAC(a[3], a[12]); SQRADDAC(a[4], a[11]); SQRADDAC(a[5], a[10]); SQRADDAC(a[6], a[9]); SQRADDAC(a[7], a[8]); SQRADDDB; + COMBA_STORE(b[15]); + + /* output 16 */ + CARRY_FORWARD; + SQRADDSC(a[3], a[13]); SQRADDAC(a[4], a[12]); SQRADDAC(a[5], a[11]); SQRADDAC(a[6], a[10]); SQRADDAC(a[7], a[9]); SQRADDDB; SQRADD(a[8], a[8]); + COMBA_STORE(b[16]); + + /* output 17 */ + CARRY_FORWARD; + SQRADDSC(a[4], a[13]); SQRADDAC(a[5], a[12]); SQRADDAC(a[6], a[11]); SQRADDAC(a[7], a[10]); SQRADDAC(a[8], a[9]); SQRADDDB; + COMBA_STORE(b[17]); + + /* output 18 */ + CARRY_FORWARD; + SQRADDSC(a[5], a[13]); SQRADDAC(a[6], a[12]); SQRADDAC(a[7], a[11]); SQRADDAC(a[8], a[10]); SQRADDDB; SQRADD(a[9], a[9]); + COMBA_STORE(b[18]); + + /* output 19 */ + CARRY_FORWARD; + SQRADDSC(a[6], a[13]); SQRADDAC(a[7], a[12]); SQRADDAC(a[8], a[11]); SQRADDAC(a[9], a[10]); SQRADDDB; + COMBA_STORE(b[19]); + + /* output 20 */ + CARRY_FORWARD; + SQRADDSC(a[7], a[13]); SQRADDAC(a[8], a[12]); SQRADDAC(a[9], a[11]); SQRADDDB; SQRADD(a[10], a[10]); + COMBA_STORE(b[20]); + + /* output 21 */ + CARRY_FORWARD; + SQRADDSC(a[8], a[13]); SQRADDAC(a[9], a[12]); SQRADDAC(a[10], a[11]); SQRADDDB; + COMBA_STORE(b[21]); + + /* output 22 */ + CARRY_FORWARD; + SQRADD2(a[9], a[13]); SQRADD2(a[10], a[12]); SQRADD(a[11], a[11]); + COMBA_STORE(b[22]); + + /* output 23 */ + CARRY_FORWARD; + SQRADD2(a[10], a[13]); SQRADD2(a[11], a[12]); + COMBA_STORE(b[23]); + + /* output 24 */ + CARRY_FORWARD; + SQRADD2(a[11], a[13]); SQRADD(a[12], a[12]); + COMBA_STORE(b[24]); + + /* output 25 */ + CARRY_FORWARD; + SQRADD2(a[12], a[13]); + COMBA_STORE(b[25]); + + /* output 26 */ + CARRY_FORWARD; + SQRADD(a[13], a[13]); + COMBA_STORE(b[26]); + COMBA_STORE2(b[27]); + COMBA_FINI; + + B->used = 28; + B->sign = FP_ZPOS; + XMEMCPY(B->dp, b, 28 * sizeof(fp_digit)); + fp_clamp(B); + break; + + case 15: + a = A->dp; + COMBA_START; + + /* clear carries */ + CLEAR_CARRY; + + /* output 0 */ + SQRADD(a[0],a[0]); + COMBA_STORE(b[0]); + + /* output 1 */ + CARRY_FORWARD; + SQRADD2(a[0], a[1]); + COMBA_STORE(b[1]); + + /* output 2 */ + CARRY_FORWARD; + SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]); + COMBA_STORE(b[2]); + + /* output 3 */ + CARRY_FORWARD; + SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]); + COMBA_STORE(b[3]); + + /* output 4 */ + CARRY_FORWARD; + SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]); + COMBA_STORE(b[4]); + + /* output 5 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB; + COMBA_STORE(b[5]); + + /* output 6 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]); + COMBA_STORE(b[6]); + + /* output 7 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[7]); SQRADDAC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB; + COMBA_STORE(b[7]); + + /* output 8 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[8]); SQRADDAC(a[1], a[7]); SQRADDAC(a[2], a[6]); SQRADDAC(a[3], a[5]); SQRADDDB; SQRADD(a[4], a[4]); + COMBA_STORE(b[8]); + + /* output 9 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[9]); SQRADDAC(a[1], a[8]); SQRADDAC(a[2], a[7]); SQRADDAC(a[3], a[6]); SQRADDAC(a[4], a[5]); SQRADDDB; + COMBA_STORE(b[9]); + + /* output 10 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[10]); SQRADDAC(a[1], a[9]); SQRADDAC(a[2], a[8]); SQRADDAC(a[3], a[7]); SQRADDAC(a[4], a[6]); SQRADDDB; SQRADD(a[5], a[5]); + COMBA_STORE(b[10]); + + /* output 11 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[11]); SQRADDAC(a[1], a[10]); SQRADDAC(a[2], a[9]); SQRADDAC(a[3], a[8]); SQRADDAC(a[4], a[7]); SQRADDAC(a[5], a[6]); SQRADDDB; + COMBA_STORE(b[11]); + + /* output 12 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[12]); SQRADDAC(a[1], a[11]); SQRADDAC(a[2], a[10]); SQRADDAC(a[3], a[9]); SQRADDAC(a[4], a[8]); SQRADDAC(a[5], a[7]); SQRADDDB; SQRADD(a[6], a[6]); + COMBA_STORE(b[12]); + + /* output 13 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[13]); SQRADDAC(a[1], a[12]); SQRADDAC(a[2], a[11]); SQRADDAC(a[3], a[10]); SQRADDAC(a[4], a[9]); SQRADDAC(a[5], a[8]); SQRADDAC(a[6], a[7]); SQRADDDB; + COMBA_STORE(b[13]); + + /* output 14 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[14]); SQRADDAC(a[1], a[13]); SQRADDAC(a[2], a[12]); SQRADDAC(a[3], a[11]); SQRADDAC(a[4], a[10]); SQRADDAC(a[5], a[9]); SQRADDAC(a[6], a[8]); SQRADDDB; SQRADD(a[7], a[7]); + COMBA_STORE(b[14]); + + /* output 15 */ + CARRY_FORWARD; + SQRADDSC(a[1], a[14]); SQRADDAC(a[2], a[13]); SQRADDAC(a[3], a[12]); SQRADDAC(a[4], a[11]); SQRADDAC(a[5], a[10]); SQRADDAC(a[6], a[9]); SQRADDAC(a[7], a[8]); SQRADDDB; + COMBA_STORE(b[15]); + + /* output 16 */ + CARRY_FORWARD; + SQRADDSC(a[2], a[14]); SQRADDAC(a[3], a[13]); SQRADDAC(a[4], a[12]); SQRADDAC(a[5], a[11]); SQRADDAC(a[6], a[10]); SQRADDAC(a[7], a[9]); SQRADDDB; SQRADD(a[8], a[8]); + COMBA_STORE(b[16]); + + /* output 17 */ + CARRY_FORWARD; + SQRADDSC(a[3], a[14]); SQRADDAC(a[4], a[13]); SQRADDAC(a[5], a[12]); SQRADDAC(a[6], a[11]); SQRADDAC(a[7], a[10]); SQRADDAC(a[8], a[9]); SQRADDDB; + COMBA_STORE(b[17]); + + /* output 18 */ + CARRY_FORWARD; + SQRADDSC(a[4], a[14]); SQRADDAC(a[5], a[13]); SQRADDAC(a[6], a[12]); SQRADDAC(a[7], a[11]); SQRADDAC(a[8], a[10]); SQRADDDB; SQRADD(a[9], a[9]); + COMBA_STORE(b[18]); + + /* output 19 */ + CARRY_FORWARD; + SQRADDSC(a[5], a[14]); SQRADDAC(a[6], a[13]); SQRADDAC(a[7], a[12]); SQRADDAC(a[8], a[11]); SQRADDAC(a[9], a[10]); SQRADDDB; + COMBA_STORE(b[19]); + + /* output 20 */ + CARRY_FORWARD; + SQRADDSC(a[6], a[14]); SQRADDAC(a[7], a[13]); SQRADDAC(a[8], a[12]); SQRADDAC(a[9], a[11]); SQRADDDB; SQRADD(a[10], a[10]); + COMBA_STORE(b[20]); + + /* output 21 */ + CARRY_FORWARD; + SQRADDSC(a[7], a[14]); SQRADDAC(a[8], a[13]); SQRADDAC(a[9], a[12]); SQRADDAC(a[10], a[11]); SQRADDDB; + COMBA_STORE(b[21]); + + /* output 22 */ + CARRY_FORWARD; + SQRADDSC(a[8], a[14]); SQRADDAC(a[9], a[13]); SQRADDAC(a[10], a[12]); SQRADDDB; SQRADD(a[11], a[11]); + COMBA_STORE(b[22]); + + /* output 23 */ + CARRY_FORWARD; + SQRADDSC(a[9], a[14]); SQRADDAC(a[10], a[13]); SQRADDAC(a[11], a[12]); SQRADDDB; + COMBA_STORE(b[23]); + + /* output 24 */ + CARRY_FORWARD; + SQRADD2(a[10], a[14]); SQRADD2(a[11], a[13]); SQRADD(a[12], a[12]); + COMBA_STORE(b[24]); + + /* output 25 */ + CARRY_FORWARD; + SQRADD2(a[11], a[14]); SQRADD2(a[12], a[13]); + COMBA_STORE(b[25]); + + /* output 26 */ + CARRY_FORWARD; + SQRADD2(a[12], a[14]); SQRADD(a[13], a[13]); + COMBA_STORE(b[26]); + + /* output 27 */ + CARRY_FORWARD; + SQRADD2(a[13], a[14]); + COMBA_STORE(b[27]); + + /* output 28 */ + CARRY_FORWARD; + SQRADD(a[14], a[14]); + COMBA_STORE(b[28]); + COMBA_STORE2(b[29]); + COMBA_FINI; + + B->used = 30; + B->sign = FP_ZPOS; + XMEMCPY(B->dp, b, 30 * sizeof(fp_digit)); + fp_clamp(B); + break; + + case 16: + a = A->dp; + COMBA_START; + + /* clear carries */ + CLEAR_CARRY; + + /* output 0 */ + SQRADD(a[0],a[0]); + COMBA_STORE(b[0]); + + /* output 1 */ + CARRY_FORWARD; + SQRADD2(a[0], a[1]); + COMBA_STORE(b[1]); + + /* output 2 */ + CARRY_FORWARD; + SQRADD2(a[0], a[2]); SQRADD(a[1], a[1]); + COMBA_STORE(b[2]); + + /* output 3 */ + CARRY_FORWARD; + SQRADD2(a[0], a[3]); SQRADD2(a[1], a[2]); + COMBA_STORE(b[3]); + + /* output 4 */ + CARRY_FORWARD; + SQRADD2(a[0], a[4]); SQRADD2(a[1], a[3]); SQRADD(a[2], a[2]); + COMBA_STORE(b[4]); + + /* output 5 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[5]); SQRADDAC(a[1], a[4]); SQRADDAC(a[2], a[3]); SQRADDDB; + COMBA_STORE(b[5]); + + /* output 6 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[6]); SQRADDAC(a[1], a[5]); SQRADDAC(a[2], a[4]); SQRADDDB; SQRADD(a[3], a[3]); + COMBA_STORE(b[6]); + + /* output 7 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[7]); SQRADDAC(a[1], a[6]); SQRADDAC(a[2], a[5]); SQRADDAC(a[3], a[4]); SQRADDDB; + COMBA_STORE(b[7]); + + /* output 8 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[8]); SQRADDAC(a[1], a[7]); SQRADDAC(a[2], a[6]); SQRADDAC(a[3], a[5]); SQRADDDB; SQRADD(a[4], a[4]); + COMBA_STORE(b[8]); + + /* output 9 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[9]); SQRADDAC(a[1], a[8]); SQRADDAC(a[2], a[7]); SQRADDAC(a[3], a[6]); SQRADDAC(a[4], a[5]); SQRADDDB; + COMBA_STORE(b[9]); + + /* output 10 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[10]); SQRADDAC(a[1], a[9]); SQRADDAC(a[2], a[8]); SQRADDAC(a[3], a[7]); SQRADDAC(a[4], a[6]); SQRADDDB; SQRADD(a[5], a[5]); + COMBA_STORE(b[10]); + + /* output 11 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[11]); SQRADDAC(a[1], a[10]); SQRADDAC(a[2], a[9]); SQRADDAC(a[3], a[8]); SQRADDAC(a[4], a[7]); SQRADDAC(a[5], a[6]); SQRADDDB; + COMBA_STORE(b[11]); + + /* output 12 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[12]); SQRADDAC(a[1], a[11]); SQRADDAC(a[2], a[10]); SQRADDAC(a[3], a[9]); SQRADDAC(a[4], a[8]); SQRADDAC(a[5], a[7]); SQRADDDB; SQRADD(a[6], a[6]); + COMBA_STORE(b[12]); + + /* output 13 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[13]); SQRADDAC(a[1], a[12]); SQRADDAC(a[2], a[11]); SQRADDAC(a[3], a[10]); SQRADDAC(a[4], a[9]); SQRADDAC(a[5], a[8]); SQRADDAC(a[6], a[7]); SQRADDDB; + COMBA_STORE(b[13]); + + /* output 14 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[14]); SQRADDAC(a[1], a[13]); SQRADDAC(a[2], a[12]); SQRADDAC(a[3], a[11]); SQRADDAC(a[4], a[10]); SQRADDAC(a[5], a[9]); SQRADDAC(a[6], a[8]); SQRADDDB; SQRADD(a[7], a[7]); + COMBA_STORE(b[14]); + + /* output 15 */ + CARRY_FORWARD; + SQRADDSC(a[0], a[15]); SQRADDAC(a[1], a[14]); SQRADDAC(a[2], a[13]); SQRADDAC(a[3], a[12]); SQRADDAC(a[4], a[11]); SQRADDAC(a[5], a[10]); SQRADDAC(a[6], a[9]); SQRADDAC(a[7], a[8]); SQRADDDB; + COMBA_STORE(b[15]); + + /* output 16 */ + CARRY_FORWARD; + SQRADDSC(a[1], a[15]); SQRADDAC(a[2], a[14]); SQRADDAC(a[3], a[13]); SQRADDAC(a[4], a[12]); SQRADDAC(a[5], a[11]); SQRADDAC(a[6], a[10]); SQRADDAC(a[7], a[9]); SQRADDDB; SQRADD(a[8], a[8]); + COMBA_STORE(b[16]); + + /* output 17 */ + CARRY_FORWARD; + SQRADDSC(a[2], a[15]); SQRADDAC(a[3], a[14]); SQRADDAC(a[4], a[13]); SQRADDAC(a[5], a[12]); SQRADDAC(a[6], a[11]); SQRADDAC(a[7], a[10]); SQRADDAC(a[8], a[9]); SQRADDDB; + COMBA_STORE(b[17]); + + /* output 18 */ + CARRY_FORWARD; + SQRADDSC(a[3], a[15]); SQRADDAC(a[4], a[14]); SQRADDAC(a[5], a[13]); SQRADDAC(a[6], a[12]); SQRADDAC(a[7], a[11]); SQRADDAC(a[8], a[10]); SQRADDDB; SQRADD(a[9], a[9]); + COMBA_STORE(b[18]); + + /* output 19 */ + CARRY_FORWARD; + SQRADDSC(a[4], a[15]); SQRADDAC(a[5], a[14]); SQRADDAC(a[6], a[13]); SQRADDAC(a[7], a[12]); SQRADDAC(a[8], a[11]); SQRADDAC(a[9], a[10]); SQRADDDB; + COMBA_STORE(b[19]); + + /* output 20 */ + CARRY_FORWARD; + SQRADDSC(a[5], a[15]); SQRADDAC(a[6], a[14]); SQRADDAC(a[7], a[13]); SQRADDAC(a[8], a[12]); SQRADDAC(a[9], a[11]); SQRADDDB; SQRADD(a[10], a[10]); + COMBA_STORE(b[20]); + + /* output 21 */ + CARRY_FORWARD; + SQRADDSC(a[6], a[15]); SQRADDAC(a[7], a[14]); SQRADDAC(a[8], a[13]); SQRADDAC(a[9], a[12]); SQRADDAC(a[10], a[11]); SQRADDDB; + COMBA_STORE(b[21]); + + /* output 22 */ + CARRY_FORWARD; + SQRADDSC(a[7], a[15]); SQRADDAC(a[8], a[14]); SQRADDAC(a[9], a[13]); SQRADDAC(a[10], a[12]); SQRADDDB; SQRADD(a[11], a[11]); + COMBA_STORE(b[22]); + + /* output 23 */ + CARRY_FORWARD; + SQRADDSC(a[8], a[15]); SQRADDAC(a[9], a[14]); SQRADDAC(a[10], a[13]); SQRADDAC(a[11], a[12]); SQRADDDB; + COMBA_STORE(b[23]); + + /* output 24 */ + CARRY_FORWARD; + SQRADDSC(a[9], a[15]); SQRADDAC(a[10], a[14]); SQRADDAC(a[11], a[13]); SQRADDDB; SQRADD(a[12], a[12]); + COMBA_STORE(b[24]); + + /* output 25 */ + CARRY_FORWARD; + SQRADDSC(a[10], a[15]); SQRADDAC(a[11], a[14]); SQRADDAC(a[12], a[13]); SQRADDDB; + COMBA_STORE(b[25]); + + /* output 26 */ + CARRY_FORWARD; + SQRADD2(a[11], a[15]); SQRADD2(a[12], a[14]); SQRADD(a[13], a[13]); + COMBA_STORE(b[26]); + + /* output 27 */ + CARRY_FORWARD; + SQRADD2(a[12], a[15]); SQRADD2(a[13], a[14]); + COMBA_STORE(b[27]); + + /* output 28 */ + CARRY_FORWARD; + SQRADD2(a[13], a[15]); SQRADD(a[14], a[14]); + COMBA_STORE(b[28]); + + /* output 29 */ + CARRY_FORWARD; + SQRADD2(a[14], a[15]); + COMBA_STORE(b[29]); + + /* output 30 */ + CARRY_FORWARD; + SQRADD(a[15], a[15]); + COMBA_STORE(b[30]); + COMBA_STORE2(b[31]); + COMBA_FINI; + + B->used = 32; + B->sign = FP_ZPOS; + XMEMCPY(B->dp, b, 32 * sizeof(fp_digit)); + fp_clamp(B); + break; + + default: + break; + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; +} + +#endif /* TFM_SMALL_SET */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/ge_low_mem.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/ge_low_mem.c new file mode 100755 index 0000000..c83a385 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/ge_low_mem.c @@ -0,0 +1,563 @@ +/* ge_low_mem.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + /* Based from Daniel Beer's public domain work. */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifdef HAVE_ED25519 +#ifdef ED25519_SMALL /* use slower code that takes less memory */ + +#include +#include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +void ed25519_smult(ge_p3 *r, const ge_p3 *a, const byte *e); +void ed25519_add(ge_p3 *r, const ge_p3 *a, const ge_p3 *b); +void ed25519_double(ge_p3 *r, const ge_p3 *a); + + +static const byte ed25519_order[F25519_SIZE] = { + 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, + 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 +}; + +/*Arithmetic modulo the group order m = 2^252 + + 27742317777372353535851937790883648493 = + 7237005577332262213973186563042994240857116359379907606001950938285454250989 */ + +static const word32 m[32] = { + 0xED,0xD3,0xF5,0x5C,0x1A,0x63,0x12,0x58,0xD6,0x9C,0xF7,0xA2,0xDE,0xF9, + 0xDE,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, + 0x00,0x00,0x00,0x10 +}; + +static const word32 mu[33] = { + 0x1B,0x13,0x2C,0x0A,0xA3,0xE5,0x9C,0xED,0xA7,0x29,0x63,0x08,0x5D,0x21, + 0x06,0x21,0xEB,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, + 0xFF,0xFF,0xFF,0xFF,0x0F +}; + + +int ge_compress_key(byte* out, const byte* xIn, const byte* yIn, + word32 keySz) +{ + byte tmp[F25519_SIZE]; + byte parity; + byte pt[32]; + int i; + + lm_copy(tmp, xIn); + parity = (tmp[0] & 1) << 7; + + lm_copy(pt, yIn); + pt[31] |= parity; + + for(i = 0; i < 32; i++) { + out[32-i-1] = pt[i]; + } + (void)keySz; + return 0; +} + + +static word32 lt(word32 a,word32 b) /* 16-bit inputs */ +{ + unsigned int x = a; + x -= (unsigned int) b; /* 0..65535: no; 4294901761..4294967295: yes */ + x >>= 31; /* 0: no; 1: yes */ + return x; +} + + +/* Reduce coefficients of r before calling reduce_add_sub */ +static void reduce_add_sub(word32 *r) +{ + word32 pb = 0; + word32 b; + word32 mask; + int i; + unsigned char t[32]; + + for(i=0;i<32;i++) + { + pb += m[i]; + b = lt(r[i],pb); + t[i] = r[i]-pb+(b<<8); + pb = b; + } + mask = b - 1; + for(i=0;i<32;i++) + r[i] ^= mask & (r[i] ^ t[i]); +} + + +/* Reduce coefficients of x before calling barrett_reduce */ +static void barrett_reduce(word32* r, word32 x[64]) +{ + /* See HAC, Alg. 14.42 */ + int i,j; + word32 q2[66]; + word32 *q3 = q2 + 33; + word32 r1[33]; + word32 r2[33]; + word32 carry; + word32 pb = 0; + word32 b; + + for (i = 0;i < 66;++i) q2[i] = 0; + for (i = 0;i < 33;++i) r2[i] = 0; + + for(i=0;i<33;i++) + for(j=0;j<33;j++) + if(i+j >= 31) q2[i+j] += mu[i]*x[j+31]; + carry = q2[31] >> 8; + q2[32] += carry; + carry = q2[32] >> 8; + q2[33] += carry; + + for(i=0;i<33;i++)r1[i] = x[i]; + for(i=0;i<32;i++) + for(j=0;j<33;j++) + if(i+j < 33) r2[i+j] += m[i]*q3[j]; + + for(i=0;i<32;i++) + { + carry = r2[i] >> 8; + r2[i+1] += carry; + r2[i] &= 0xff; + } + + for(i=0;i<32;i++) + { + pb += r2[i]; + b = lt(r1[i],pb); + r[i] = r1[i]-pb+(b<<8); + pb = b; + } + + /* XXX: Can it really happen that r<0?, See HAC, Alg 14.42, Step 3 + * r is an unsigned type. + * If so: Handle it here! + */ + + reduce_add_sub(r); + reduce_add_sub(r); +} + + +void sc_reduce(unsigned char x[64]) +{ + int i; + word32 t[64]; + word32 r[32]; + for(i=0;i<64;i++) t[i] = x[i]; + barrett_reduce(r, t); + for(i=0;i<32;i++) x[i] = (r[i] & 0xFF); +} + + +void sc_muladd(byte* out, const byte* a, const byte* b, const byte* c) +{ + + byte s[32]; + byte e[64]; + + XMEMSET(e, 0, sizeof(e)); + XMEMCPY(e, b, 32); + + /* Obtain e */ + sc_reduce(e); + + /* Compute s = ze + k */ + fprime_mul(s, a, e, ed25519_order); + fprime_add(s, c, ed25519_order); + + XMEMCPY(out, s, 32); +} + + +/* Base point is (numbers wrapped): + * + * x = 151122213495354007725011514095885315114 + * 54012693041857206046113283949847762202 + * y = 463168356949264781694283940034751631413 + * 07993866256225615783033603165251855960 + * + * y is derived by transforming the original Montgomery base (u=9). x + * is the corresponding positive coordinate for the new curve equation. + * t is x*y. + */ +const ge_p3 ed25519_base = { + { + 0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, + 0xb2, 0xa7, 0x25, 0x95, 0x60, 0xc7, 0x2c, 0x69, + 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0, + 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21 + }, + { + 0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, + 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66 + }, + {1, 0}, + { + 0xa3, 0xdd, 0xb7, 0xa5, 0xb3, 0x8a, 0xde, 0x6d, + 0xf5, 0x52, 0x51, 0x77, 0x80, 0x9f, 0xf0, 0x20, + 0x7d, 0xe3, 0xab, 0x64, 0x8e, 0x4e, 0xea, 0x66, + 0x65, 0x76, 0x8b, 0xd7, 0x0f, 0x5f, 0x87, 0x67 + }, + +}; + + +const ge_p3 ed25519_neutral = { + {0}, + {1, 0}, + {1, 0}, + {0}, + +}; + + +static const byte ed25519_d[F25519_SIZE] = { + 0xa3, 0x78, 0x59, 0x13, 0xca, 0x4d, 0xeb, 0x75, + 0xab, 0xd8, 0x41, 0x41, 0x4d, 0x0a, 0x70, 0x00, + 0x98, 0xe8, 0x79, 0x77, 0x79, 0x40, 0xc7, 0x8c, + 0x73, 0xfe, 0x6f, 0x2b, 0xee, 0x6c, 0x03, 0x52 +}; + + +/* k = 2d */ +static const byte ed25519_k[F25519_SIZE] = { + 0x59, 0xf1, 0xb2, 0x26, 0x94, 0x9b, 0xd6, 0xeb, + 0x56, 0xb1, 0x83, 0x82, 0x9a, 0x14, 0xe0, 0x00, + 0x30, 0xd1, 0xf3, 0xee, 0xf2, 0x80, 0x8e, 0x19, + 0xe7, 0xfc, 0xdf, 0x56, 0xdc, 0xd9, 0x06, 0x24 +}; + + +void ed25519_add(ge_p3 *r, + const ge_p3 *p1, const ge_p3 *p2) +{ + /* Explicit formulas database: add-2008-hwcd-3 + * + * source 2008 Hisil--Wong--Carter--Dawson, + * http://eprint.iacr.org/2008/522, Section 3.1 + * appliesto extended-1 + * parameter k + * assume k = 2 d + * compute A = (Y1-X1)(Y2-X2) + * compute B = (Y1+X1)(Y2+X2) + * compute C = T1 k T2 + * compute D = Z1 2 Z2 + * compute E = B - A + * compute F = D - C + * compute G = D + C + * compute H = B + A + * compute X3 = E F + * compute Y3 = G H + * compute T3 = E H + * compute Z3 = F G + */ + byte a[F25519_SIZE]; + byte b[F25519_SIZE]; + byte c[F25519_SIZE]; + byte d[F25519_SIZE]; + byte e[F25519_SIZE]; + byte f[F25519_SIZE]; + byte g[F25519_SIZE]; + byte h[F25519_SIZE]; + + /* A = (Y1-X1)(Y2-X2) */ + lm_sub(c, p1->Y, p1->X); + lm_sub(d, p2->Y, p2->X); + fe_mul__distinct(a, c, d); + + /* B = (Y1+X1)(Y2+X2) */ + lm_add(c, p1->Y, p1->X); + lm_add(d, p2->Y, p2->X); + fe_mul__distinct(b, c, d); + + /* C = T1 k T2 */ + fe_mul__distinct(d, p1->T, p2->T); + fe_mul__distinct(c, d, ed25519_k); + + /* D = Z1 2 Z2 */ + fe_mul__distinct(d, p1->Z, p2->Z); + lm_add(d, d, d); + + /* E = B - A */ + lm_sub(e, b, a); + + /* F = D - C */ + lm_sub(f, d, c); + + /* G = D + C */ + lm_add(g, d, c); + + /* H = B + A */ + lm_add(h, b, a); + + /* X3 = E F */ + fe_mul__distinct(r->X, e, f); + + /* Y3 = G H */ + fe_mul__distinct(r->Y, g, h); + + /* T3 = E H */ + fe_mul__distinct(r->T, e, h); + + /* Z3 = F G */ + fe_mul__distinct(r->Z, f, g); +} + + +void ed25519_double(ge_p3 *r, const ge_p3 *p) +{ + /* Explicit formulas database: dbl-2008-hwcd + * + * source 2008 Hisil--Wong--Carter--Dawson, + * http://eprint.iacr.org/2008/522, Section 3.3 + * compute A = X1^2 + * compute B = Y1^2 + * compute C = 2 Z1^2 + * compute D = a A + * compute E = (X1+Y1)^2-A-B + * compute G = D + B + * compute F = G - C + * compute H = D - B + * compute X3 = E F + * compute Y3 = G H + * compute T3 = E H + * compute Z3 = F G + */ + byte a[F25519_SIZE]; + byte b[F25519_SIZE]; + byte c[F25519_SIZE]; + byte e[F25519_SIZE]; + byte f[F25519_SIZE]; + byte g[F25519_SIZE]; + byte h[F25519_SIZE]; + + /* A = X1^2 */ + fe_mul__distinct(a, p->X, p->X); + + /* B = Y1^2 */ + fe_mul__distinct(b, p->Y, p->Y); + + /* C = 2 Z1^2 */ + fe_mul__distinct(c, p->Z, p->Z); + lm_add(c, c, c); + + /* D = a A (alter sign) */ + /* E = (X1+Y1)^2-A-B */ + lm_add(f, p->X, p->Y); + fe_mul__distinct(e, f, f); + lm_sub(e, e, a); + lm_sub(e, e, b); + + /* G = D + B */ + lm_sub(g, b, a); + + /* F = G - C */ + lm_sub(f, g, c); + + /* H = D - B */ + lm_neg(h, b); + lm_sub(h, h, a); + + /* X3 = E F */ + fe_mul__distinct(r->X, e, f); + + /* Y3 = G H */ + fe_mul__distinct(r->Y, g, h); + + /* T3 = E H */ + fe_mul__distinct(r->T, e, h); + + /* Z3 = F G */ + fe_mul__distinct(r->Z, f, g); +} + + +void ed25519_smult(ge_p3 *r_out, const ge_p3 *p, const byte *e) +{ + ge_p3 r; + int i; + + XMEMCPY(&r, &ed25519_neutral, sizeof(r)); + + for (i = 255; i >= 0; i--) { + const byte bit = (e[i >> 3] >> (i & 7)) & 1; + ge_p3 s; + + ed25519_double(&r, &r); + ed25519_add(&s, &r, p); + + fe_select(r.X, r.X, s.X, bit); + fe_select(r.Y, r.Y, s.Y, bit); + fe_select(r.Z, r.Z, s.Z, bit); + fe_select(r.T, r.T, s.T, bit); + } + XMEMCPY(r_out, &r, sizeof(r)); +} + + +void ge_scalarmult_base(ge_p3 *R,const unsigned char *nonce) +{ + ed25519_smult(R, &ed25519_base, nonce); +} + + +/* pack the point h into array s */ +void ge_p3_tobytes(unsigned char *s,const ge_p3 *h) +{ + byte x[F25519_SIZE]; + byte y[F25519_SIZE]; + byte z1[F25519_SIZE]; + byte parity; + + fe_inv__distinct(z1, h->Z); + fe_mul__distinct(x, h->X, z1); + fe_mul__distinct(y, h->Y, z1); + + fe_normalize(x); + fe_normalize(y); + + parity = (x[0] & 1) << 7; + lm_copy(s, y); + fe_normalize(s); + s[31] |= parity; +} + + +/* pack the point h into array s */ +void ge_tobytes(unsigned char *s,const ge_p2 *h) +{ + byte x[F25519_SIZE]; + byte y[F25519_SIZE]; + byte z1[F25519_SIZE]; + byte parity; + + fe_inv__distinct(z1, h->Z); + fe_mul__distinct(x, h->X, z1); + fe_mul__distinct(y, h->Y, z1); + + fe_normalize(x); + fe_normalize(y); + + parity = (x[0] & 1) << 7; + lm_copy(s, y); + fe_normalize(s); + s[31] |= parity; +} + + +/* + Test if the public key can be uncompressed and negate it (-X,Y,Z,-T) + return 0 on success + */ +int ge_frombytes_negate_vartime(ge_p3 *p,const unsigned char *s) +{ + + byte parity; + byte x[F25519_SIZE]; + byte y[F25519_SIZE]; + byte a[F25519_SIZE]; + byte b[F25519_SIZE]; + byte c[F25519_SIZE]; + int ret = 0; + + /* unpack the key s */ + parity = s[31] >> 7; + lm_copy(y, s); + y[31] &= 127; + + fe_mul__distinct(c, y, y); + fe_mul__distinct(b, c, ed25519_d); + lm_add(a, b, f25519_one); + fe_inv__distinct(b, a); + lm_sub(a, c, f25519_one); + fe_mul__distinct(c, a, b); + fe_sqrt(a, c); + lm_neg(b, a); + fe_select(x, a, b, (a[0] ^ parity) & 1); + + /* test that x^2 is equal to c */ + fe_mul__distinct(a, x, x); + fe_normalize(a); + fe_normalize(c); + ret |= ConstantCompare(a, c, F25519_SIZE); + + /* project the key s onto p */ + lm_copy(p->X, x); + lm_copy(p->Y, y); + fe_load(p->Z, 1); + fe_mul__distinct(p->T, x, y); + + /* negate, the point becomes (-X,Y,Z,-T) */ + lm_neg(p->X,p->X); + lm_neg(p->T,p->T); + + return ret; +} + + +int ge_double_scalarmult_vartime(ge_p2* R, const unsigned char *h, + const ge_p3 *inA,const unsigned char *sig) +{ + ge_p3 p, A; + int ret = 0; + + XMEMCPY(&A, inA, sizeof(ge_p3)); + + /* find SB */ + ed25519_smult(&p, &ed25519_base, sig); + + /* find H(R,A,M) * -A */ + ed25519_smult(&A, &A, h); + + /* SB + -H(R,A,M)A */ + ed25519_add(&A, &p, &A); + + lm_copy(R->X, A.X); + lm_copy(R->Y, A.Y); + lm_copy(R->Z, A.Z); + + return ret; +} + +#endif /* ED25519_SMALL */ +#endif /* HAVE_ED25519 */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/ge_operations.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/ge_operations.c new file mode 100755 index 0000000..9d2ce8d --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/ge_operations.c @@ -0,0 +1,9803 @@ +/* ge_operations.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + /* Based On Daniel J Bernstein's ed25519 Public Domain ref10 work. */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifdef HAVE_ED25519 +#ifndef ED25519_SMALL /* run when not defined to use small memory math */ + +#include +#include +#include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#if defined(CURVED25519_X64) + #define CURVED25519_ASM_64BIT + #define CURVED25519_ASM +#endif +#if defined(WOLFSSL_ARMASM) + #if defined(__aarch64__) + #define CURVED25519_ASM_64BIT + #else + #define CURVED25519_ASM_32BIT + #endif + #define CURVED25519_ASM +#endif + + +static void ge_p2_0(ge_p2 *); +#ifndef CURVED25519_ASM +static void ge_precomp_0(ge_precomp *); +#endif +static void ge_p3_to_p2(ge_p2 *,const ge_p3 *); +static void ge_p3_to_cached(ge_cached *,const ge_p3 *); +static void ge_p1p1_to_p2(ge_p2 *,const ge_p1p1 *); +static void ge_p1p1_to_p3(ge_p3 *,const ge_p1p1 *); +static void ge_p2_dbl(ge_p1p1 *,const ge_p2 *); +static void ge_p3_dbl(ge_p1p1 *,const ge_p3 *); + +static void ge_madd(ge_p1p1 *,const ge_p3 *,const ge_precomp *); +static void ge_msub(ge_p1p1 *,const ge_p3 *,const ge_precomp *); +static void ge_add(ge_p1p1 *,const ge_p3 *,const ge_cached *); +static void ge_sub(ge_p1p1 *,const ge_p3 *,const ge_cached *); + +/* +ge means group element. + +Here the group is the set of pairs (x,y) of field elements (see ge_operations.h) +satisfying -x^2 + y^2 = 1 + d x^2y^2 +where d = -121665/121666. + +Representations: + ge_p2 (projective): (X:Y:Z) satisfying x=X/Z, y=Y/Z + ge_p3 (extended): (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT + ge_p1p1 (completed): ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T + ge_precomp (Duif): (y+x,y-x,2dxy) +*/ + +#if !defined(HAVE___UINT128_T) || defined(NO_CURVED25519_128BIT) +#define MASK_21 0x1fffff +#define ORDER_0 0x15d3ed +#define ORDER_1 0x18d2e7 +#define ORDER_2 0x160498 +#define ORDER_3 0xf39ac +#define ORDER_4 0x1dea2f +#define ORDER_5 0xa6f7c + +#ifdef CURVED25519_ASM_32BIT +uint64_t load_3(const unsigned char *in) +{ + uint64_t result; + result = (uint64_t) in[0]; + result |= ((uint64_t) in[1]) << 8; + result |= ((uint64_t) in[2]) << 16; + return result; +} + + +uint64_t load_4(const unsigned char *in) +{ + uint64_t result; + result = (uint64_t) in[0]; + result |= ((uint64_t) in[1]) << 8; + result |= ((uint64_t) in[2]) << 16; + result |= ((uint64_t) in[3]) << 24; + return result; +} +#endif + +/* +Input: + s[0]+256*s[1]+...+256^63*s[63] = s + +Output: + s[0]+256*s[1]+...+256^31*s[31] = s mod l + where l = 2^252 + 27742317777372353535851937790883648493. + Overwrites s in place. +*/ +void sc_reduce(byte* s) +{ + int64_t t[24]; + int64_t carry; + + t[ 0] = MASK_21 & (load_3(s + 0) >> 0); + t[ 1] = MASK_21 & (load_4(s + 2) >> 5); + t[ 2] = MASK_21 & (load_3(s + 5) >> 2); + t[ 3] = MASK_21 & (load_4(s + 7) >> 7); + t[ 4] = MASK_21 & (load_4(s + 10) >> 4); + t[ 5] = MASK_21 & (load_3(s + 13) >> 1); + t[ 6] = MASK_21 & (load_4(s + 15) >> 6); + t[ 7] = MASK_21 & (load_3(s + 18) >> 3); + t[ 8] = MASK_21 & (load_3(s + 21) >> 0); + t[ 9] = MASK_21 & (load_4(s + 23) >> 5); + t[10] = MASK_21 & (load_3(s + 26) >> 2); + t[11] = MASK_21 & (load_4(s + 28) >> 7); + t[12] = MASK_21 & (load_4(s + 31) >> 4); + t[13] = MASK_21 & (load_3(s + 34) >> 1); + t[14] = MASK_21 & (load_4(s + 36) >> 6); + t[15] = MASK_21 & (load_3(s + 39) >> 3); + t[16] = MASK_21 & (load_3(s + 42) >> 0); + t[17] = MASK_21 & (load_4(s + 44) >> 5); + t[18] = MASK_21 & (load_3(s + 47) >> 2); + t[19] = MASK_21 & (load_4(s + 49) >> 7); + t[20] = MASK_21 & (load_4(s + 52) >> 4); + t[21] = MASK_21 & (load_3(s + 55) >> 1); + t[22] = MASK_21 & (load_4(s + 57) >> 6); + t[23] = (load_4(s + 60) >> 3); + + t[11] -= t[23] * ORDER_0; + t[12] -= t[23] * ORDER_1; + t[13] -= t[23] * ORDER_2; + t[14] -= t[23] * ORDER_3; + t[15] -= t[23] * ORDER_4; + t[16] -= t[23] * ORDER_5; + + t[10] -= t[22] * ORDER_0; + t[11] -= t[22] * ORDER_1; + t[12] -= t[22] * ORDER_2; + t[13] -= t[22] * ORDER_3; + t[14] -= t[22] * ORDER_4; + t[15] -= t[22] * ORDER_5; + + t[ 9] -= t[21] * ORDER_0; + t[10] -= t[21] * ORDER_1; + t[11] -= t[21] * ORDER_2; + t[12] -= t[21] * ORDER_3; + t[13] -= t[21] * ORDER_4; + t[14] -= t[21] * ORDER_5; + + t[ 8] -= t[20] * ORDER_0; + t[ 9] -= t[20] * ORDER_1; + t[10] -= t[20] * ORDER_2; + t[11] -= t[20] * ORDER_3; + t[12] -= t[20] * ORDER_4; + t[13] -= t[20] * ORDER_5; + + t[ 7] -= t[19] * ORDER_0; + t[ 8] -= t[19] * ORDER_1; + t[ 9] -= t[19] * ORDER_2; + t[10] -= t[19] * ORDER_3; + t[11] -= t[19] * ORDER_4; + t[12] -= t[19] * ORDER_5; + + t[ 6] -= t[18] * ORDER_0; + t[ 7] -= t[18] * ORDER_1; + t[ 8] -= t[18] * ORDER_2; + t[ 9] -= t[18] * ORDER_3; + t[10] -= t[18] * ORDER_4; + t[11] -= t[18] * ORDER_5; + + carry = t[ 6] >> 21; t[ 7] += carry; t[ 6] &= MASK_21; + carry = t[ 8] >> 21; t[ 9] += carry; t[ 8] &= MASK_21; + carry = t[10] >> 21; t[11] += carry; t[10] &= MASK_21; + carry = t[12] >> 21; t[13] += carry; t[12] &= MASK_21; + carry = t[14] >> 21; t[15] += carry; t[14] &= MASK_21; + carry = t[16] >> 21; t[17] += carry; t[16] &= MASK_21; + carry = t[ 7] >> 21; t[ 8] += carry; t[ 7] &= MASK_21; + carry = t[ 9] >> 21; t[10] += carry; t[ 9] &= MASK_21; + carry = t[11] >> 21; t[12] += carry; t[11] &= MASK_21; + carry = t[13] >> 21; t[14] += carry; t[13] &= MASK_21; + carry = t[15] >> 21; t[16] += carry; t[15] &= MASK_21; + + t[ 5] -= t[17] * ORDER_0; + t[ 6] -= t[17] * ORDER_1; + t[ 7] -= t[17] * ORDER_2; + t[ 8] -= t[17] * ORDER_3; + t[ 9] -= t[17] * ORDER_4; + t[10] -= t[17] * ORDER_5; + + t[ 4] -= t[16] * ORDER_0; + t[ 5] -= t[16] * ORDER_1; + t[ 6] -= t[16] * ORDER_2; + t[ 7] -= t[16] * ORDER_3; + t[ 8] -= t[16] * ORDER_4; + t[ 9] -= t[16] * ORDER_5; + + t[ 3] -= t[15] * ORDER_0; + t[ 4] -= t[15] * ORDER_1; + t[ 5] -= t[15] * ORDER_2; + t[ 6] -= t[15] * ORDER_3; + t[ 7] -= t[15] * ORDER_4; + t[ 8] -= t[15] * ORDER_5; + + t[ 2] -= t[14] * ORDER_0; + t[ 3] -= t[14] * ORDER_1; + t[ 4] -= t[14] * ORDER_2; + t[ 5] -= t[14] * ORDER_3; + t[ 6] -= t[14] * ORDER_4; + t[ 7] -= t[14] * ORDER_5; + + t[ 1] -= t[13] * ORDER_0; + t[ 2] -= t[13] * ORDER_1; + t[ 3] -= t[13] * ORDER_2; + t[ 4] -= t[13] * ORDER_3; + t[ 5] -= t[13] * ORDER_4; + t[ 6] -= t[13] * ORDER_5; + + t[ 0] -= t[12] * ORDER_0; + t[ 1] -= t[12] * ORDER_1; + t[ 2] -= t[12] * ORDER_2; + t[ 3] -= t[12] * ORDER_3; + t[ 4] -= t[12] * ORDER_4; + t[ 5] -= t[12] * ORDER_5; + t[12] = 0; + + carry = t[ 0] >> 21; t[ 1] += carry; t[ 0] &= MASK_21; + carry = t[ 1] >> 21; t[ 2] += carry; t[ 1] &= MASK_21; + carry = t[ 2] >> 21; t[ 3] += carry; t[ 2] &= MASK_21; + carry = t[ 3] >> 21; t[ 4] += carry; t[ 3] &= MASK_21; + carry = t[ 4] >> 21; t[ 5] += carry; t[ 4] &= MASK_21; + carry = t[ 5] >> 21; t[ 6] += carry; t[ 5] &= MASK_21; + carry = t[ 6] >> 21; t[ 7] += carry; t[ 6] &= MASK_21; + carry = t[ 7] >> 21; t[ 8] += carry; t[ 7] &= MASK_21; + carry = t[ 8] >> 21; t[ 9] += carry; t[ 8] &= MASK_21; + carry = t[ 9] >> 21; t[10] += carry; t[ 9] &= MASK_21; + carry = t[10] >> 21; t[11] += carry; t[10] &= MASK_21; + carry = t[11] >> 21; t[12] += carry; t[11] &= MASK_21; + + t[ 0] -= t[12] * ORDER_0; + t[ 1] -= t[12] * ORDER_1; + t[ 2] -= t[12] * ORDER_2; + t[ 3] -= t[12] * ORDER_3; + t[ 4] -= t[12] * ORDER_4; + t[ 5] -= t[12] * ORDER_5; + + carry = t[ 0] >> 21; t[ 1] += carry; t[ 0] &= MASK_21; + carry = t[ 1] >> 21; t[ 2] += carry; t[ 1] &= MASK_21; + carry = t[ 2] >> 21; t[ 3] += carry; t[ 2] &= MASK_21; + carry = t[ 3] >> 21; t[ 4] += carry; t[ 3] &= MASK_21; + carry = t[ 4] >> 21; t[ 5] += carry; t[ 4] &= MASK_21; + carry = t[ 5] >> 21; t[ 6] += carry; t[ 5] &= MASK_21; + carry = t[ 6] >> 21; t[ 7] += carry; t[ 6] &= MASK_21; + carry = t[ 7] >> 21; t[ 8] += carry; t[ 7] &= MASK_21; + carry = t[ 8] >> 21; t[ 9] += carry; t[ 8] &= MASK_21; + carry = t[ 9] >> 21; t[10] += carry; t[ 9] &= MASK_21; + carry = t[10] >> 21; t[11] += carry; t[10] &= MASK_21; + + s[ 0] = (byte)(t[ 0] >> 0); + s[ 1] = (byte)(t[ 0] >> 8); + s[ 2] = (byte)((t[ 0] >> 16) | (t[ 1] << 5)); + s[ 3] = (byte)(t[ 1] >> 3); + s[ 4] = (byte)(t[ 1] >> 11); + s[ 5] = (byte)((t[ 1] >> 19) | (t[ 2] << 2)); + s[ 6] = (byte)(t[ 2] >> 6); + s[ 7] = (byte)((t[ 2] >> 14) | (t[ 3] << 7)); + s[ 8] = (byte)(t[ 3] >> 1); + s[ 9] = (byte)(t[ 3] >> 9); + s[10] = (byte)((t[ 3] >> 17) | (t[ 4] << 4)); + s[11] = (byte)(t[ 4] >> 4); + s[12] = (byte)(t[ 4] >> 12); + s[13] = (byte)((t[ 4] >> 20) | (t[ 5] << 1)); + s[14] = (byte)(t[ 5] >> 7); + s[15] = (byte)((t[ 5] >> 15) | (t[ 6] << 6)); + s[16] = (byte)(t[ 6] >> 2); + s[17] = (byte)(t[ 6] >> 10); + s[18] = (byte)((t[ 6] >> 18) | (t[ 7] << 3)); + s[19] = (byte)(t[ 7] >> 5); + s[20] = (byte)(t[ 7] >> 13); + s[21] = (byte)(t[ 8] >> 0); + s[22] = (byte)(t[ 8] >> 8); + s[23] = (byte)((t[ 8] >> 16) | (t[ 9] << 5)); + s[24] = (byte)(t[ 9] >> 3); + s[25] = (byte)(t[ 9] >> 11); + s[26] = (byte)((t[ 9] >> 19) | (t[10] << 2)); + s[27] = (byte)(t[10] >> 6); + s[28] = (byte)((t[10] >> 14) | (t[11] << 7)); + s[29] = (byte)(t[11] >> 1); + s[30] = (byte)(t[11] >> 9); + s[31] = (byte)(t[11] >> 17); +} + +/* +Input: + a[0]+256*a[1]+...+256^31*a[31] = a + b[0]+256*b[1]+...+256^31*b[31] = b + c[0]+256*c[1]+...+256^31*c[31] = c + +Output: + s[0]+256*s[1]+...+256^31*s[31] = (ab+c) mod l + where l = 2^252 + 27742317777372353535851937790883648493. +*/ +void sc_muladd(byte* s, const byte* a, const byte* b, const byte* c) +{ + uint32_t ad[12], bd[12], cd[12]; + int64_t t[24]; + int64_t carry; + + ad[ 0] = MASK_21 & (load_3(a + 0) >> 0); + ad[ 1] = MASK_21 & (load_4(a + 2) >> 5); + ad[ 2] = MASK_21 & (load_3(a + 5) >> 2); + ad[ 3] = MASK_21 & (load_4(a + 7) >> 7); + ad[ 4] = MASK_21 & (load_4(a + 10) >> 4); + ad[ 5] = MASK_21 & (load_3(a + 13) >> 1); + ad[ 6] = MASK_21 & (load_4(a + 15) >> 6); + ad[ 7] = MASK_21 & (load_3(a + 18) >> 3); + ad[ 8] = MASK_21 & (load_3(a + 21) >> 0); + ad[ 9] = MASK_21 & (load_4(a + 23) >> 5); + ad[10] = MASK_21 & (load_3(a + 26) >> 2); + ad[11] = (uint32_t)(load_4(a + 28) >> 7); + bd[ 0] = MASK_21 & (load_3(b + 0) >> 0); + bd[ 1] = MASK_21 & (load_4(b + 2) >> 5); + bd[ 2] = MASK_21 & (load_3(b + 5) >> 2); + bd[ 3] = MASK_21 & (load_4(b + 7) >> 7); + bd[ 4] = MASK_21 & (load_4(b + 10) >> 4); + bd[ 5] = MASK_21 & (load_3(b + 13) >> 1); + bd[ 6] = MASK_21 & (load_4(b + 15) >> 6); + bd[ 7] = MASK_21 & (load_3(b + 18) >> 3); + bd[ 8] = MASK_21 & (load_3(b + 21) >> 0); + bd[ 9] = MASK_21 & (load_4(b + 23) >> 5); + bd[10] = MASK_21 & (load_3(b + 26) >> 2); + bd[11] = (uint32_t)(load_4(b + 28) >> 7); + cd[ 0] = MASK_21 & (load_3(c + 0) >> 0); + cd[ 1] = MASK_21 & (load_4(c + 2) >> 5); + cd[ 2] = MASK_21 & (load_3(c + 5) >> 2); + cd[ 3] = MASK_21 & (load_4(c + 7) >> 7); + cd[ 4] = MASK_21 & (load_4(c + 10) >> 4); + cd[ 5] = MASK_21 & (load_3(c + 13) >> 1); + cd[ 6] = MASK_21 & (load_4(c + 15) >> 6); + cd[ 7] = MASK_21 & (load_3(c + 18) >> 3); + cd[ 8] = MASK_21 & (load_3(c + 21) >> 0); + cd[ 9] = MASK_21 & (load_4(c + 23) >> 5); + cd[10] = MASK_21 & (load_3(c + 26) >> 2); + cd[11] = (uint32_t)(load_4(c + 28) >> 7); + + t[ 0] = cd[ 0] + (int64_t)ad[ 0] * bd[ 0]; + t[ 1] = cd[ 1] + (int64_t)ad[ 0] * bd[ 1] + (int64_t)ad[ 1] * bd[ 0]; + t[ 2] = cd[ 2] + (int64_t)ad[ 0] * bd[ 2] + (int64_t)ad[ 1] * bd[ 1] + + (int64_t)ad[ 2] * bd[ 0]; + t[ 3] = cd[ 3] + (int64_t)ad[ 0] * bd[ 3] + (int64_t)ad[ 1] * bd[ 2] + + (int64_t)ad[ 2] * bd[ 1] + (int64_t)ad[ 3] * bd[ 0]; + t[ 4] = cd[ 4] + (int64_t)ad[ 0] * bd[ 4] + (int64_t)ad[ 1] * bd[ 3] + + (int64_t)ad[ 2] * bd[ 2] + (int64_t)ad[ 3] * bd[ 1] + + (int64_t)ad[ 4] * bd[ 0]; + t[ 5] = cd[ 5] + (int64_t)ad[ 0] * bd[ 5] + (int64_t)ad[ 1] * bd[ 4] + + (int64_t)ad[ 2] * bd[ 3] + (int64_t)ad[ 3] * bd[ 2] + + (int64_t)ad[ 4] * bd[ 1] + (int64_t)ad[ 5] * bd[ 0]; + t[ 6] = cd[ 6] + (int64_t)ad[ 0] * bd[ 6] + (int64_t)ad[ 1] * bd[ 5] + + (int64_t)ad[ 2] * bd[ 4] + (int64_t)ad[ 3] * bd[ 3] + + (int64_t)ad[ 4] * bd[ 2] + (int64_t)ad[ 5] * bd[ 1] + + (int64_t)ad[ 6] * bd[ 0]; + t[ 7] = cd[ 7] + (int64_t)ad[ 0] * bd[ 7] + (int64_t)ad[ 1] * bd[ 6] + + (int64_t)ad[ 2] * bd[ 5] + (int64_t)ad[ 3] * bd[ 4] + + (int64_t)ad[ 4] * bd[ 3] + (int64_t)ad[ 5] * bd[ 2] + + (int64_t)ad[ 6] * bd[ 1] + (int64_t)ad[ 7] * bd[ 0]; + t[ 8] = cd[ 8] + (int64_t)ad[ 0] * bd[ 8] + (int64_t)ad[ 1] * bd[ 7] + + (int64_t)ad[ 2] * bd[ 6] + (int64_t)ad[ 3] * bd[ 5] + + (int64_t)ad[ 4] * bd[ 4] + (int64_t)ad[ 5] * bd[ 3] + + (int64_t)ad[ 6] * bd[ 2] + (int64_t)ad[ 7] * bd[ 1] + + (int64_t)ad[ 8] * bd[ 0]; + t[ 9] = cd[ 9] + (int64_t)ad[ 0] * bd[ 9] + (int64_t)ad[ 1] * bd[ 8] + + (int64_t)ad[ 2] * bd[ 7] + (int64_t)ad[ 3] * bd[ 6] + + (int64_t)ad[ 4] * bd[ 5] + (int64_t)ad[ 5] * bd[ 4] + + (int64_t)ad[ 6] * bd[ 3] + (int64_t)ad[ 7] * bd[ 2] + + (int64_t)ad[ 8] * bd[ 1] + (int64_t)ad[ 9] * bd[ 0]; + t[10] = cd[10] + (int64_t)ad[ 0] * bd[10] + (int64_t)ad[ 1] * bd[ 9] + + (int64_t)ad[ 2] * bd[ 8] + (int64_t)ad[ 3] * bd[ 7] + + (int64_t)ad[ 4] * bd[ 6] + (int64_t)ad[ 5] * bd[ 5] + + (int64_t)ad[ 6] * bd[ 4] + (int64_t)ad[ 7] * bd[ 3] + + (int64_t)ad[ 8] * bd[ 2] + (int64_t)ad[ 9] * bd[ 1] + + (int64_t)ad[10] * bd[ 0]; + t[11] = cd[11] + (int64_t)ad[ 0] * bd[11] + (int64_t)ad[ 1] * bd[10] + + (int64_t)ad[ 2] * bd[ 9] + (int64_t)ad[ 3] * bd[ 8] + + (int64_t)ad[ 4] * bd[ 7] + (int64_t)ad[ 5] * bd[ 6] + + (int64_t)ad[ 6] * bd[ 5] + (int64_t)ad[ 7] * bd[ 4] + + (int64_t)ad[ 8] * bd[ 3] + (int64_t)ad[ 9] * bd[ 2] + + (int64_t)ad[10] * bd[ 1] + (int64_t)ad[11] * bd[ 0]; + t[12] = (int64_t)ad[ 1] * bd[11] + (int64_t)ad[ 2] * bd[10] + + (int64_t)ad[ 3] * bd[ 9] + (int64_t)ad[ 4] * bd[ 8] + + (int64_t)ad[ 5] * bd[ 7] + (int64_t)ad[ 6] * bd[ 6] + + (int64_t)ad[ 7] * bd[ 5] + (int64_t)ad[ 8] * bd[ 4] + + (int64_t)ad[ 9] * bd[ 3] + (int64_t)ad[10] * bd[ 2] + + (int64_t)ad[11] * bd[ 1]; + t[13] = (int64_t)ad[ 2] * bd[11] + (int64_t)ad[ 3] * bd[10] + + (int64_t)ad[ 4] * bd[ 9] + (int64_t)ad[ 5] * bd[ 8] + + (int64_t)ad[ 6] * bd[ 7] + (int64_t)ad[ 7] * bd[ 6] + + (int64_t)ad[ 8] * bd[ 5] + (int64_t)ad[ 9] * bd[ 4] + + (int64_t)ad[10] * bd[ 3] + (int64_t)ad[11] * bd[ 2]; + t[14] = (int64_t)ad[ 3] * bd[11] + (int64_t)ad[ 4] * bd[10] + + (int64_t)ad[ 5] * bd[ 9] + (int64_t)ad[ 6] * bd[ 8] + + (int64_t)ad[ 7] * bd[ 7] + (int64_t)ad[ 8] * bd[ 6] + + (int64_t)ad[ 9] * bd[ 5] + (int64_t)ad[10] * bd[ 4] + + (int64_t)ad[11] * bd[ 3]; + t[15] = (int64_t)ad[ 4] * bd[11] + (int64_t)ad[ 5] * bd[10] + + (int64_t)ad[ 6] * bd[ 9] + (int64_t)ad[ 7] * bd[ 8] + + (int64_t)ad[ 8] * bd[ 7] + (int64_t)ad[ 9] * bd[ 6] + + (int64_t)ad[10] * bd[ 5] + (int64_t)ad[11] * bd[ 4]; + t[16] = (int64_t)ad[ 5] * bd[11] + (int64_t)ad[ 6] * bd[10] + + (int64_t)ad[ 7] * bd[ 9] + (int64_t)ad[ 8] * bd[ 8] + + (int64_t)ad[ 9] * bd[ 7] + (int64_t)ad[10] * bd[ 6] + + (int64_t)ad[11] * bd[ 5]; + t[17] = (int64_t)ad[ 6] * bd[11] + (int64_t)ad[ 7] * bd[10] + + (int64_t)ad[ 8] * bd[ 9] + (int64_t)ad[ 9] * bd[ 8] + + (int64_t)ad[10] * bd[ 7] + (int64_t)ad[11] * bd[ 6]; + t[18] = (int64_t)ad[ 7] * bd[11] + (int64_t)ad[ 8] * bd[10] + + (int64_t)ad[ 9] * bd[ 9] + (int64_t)ad[10] * bd[ 8] + + (int64_t)ad[11] * bd[ 7]; + t[19] = (int64_t)ad[ 8] * bd[11] + (int64_t)ad[ 9] * bd[10] + + (int64_t)ad[10] * bd[ 9] + (int64_t)ad[11] * bd[ 8]; + t[20] = (int64_t)ad[ 9] * bd[11] + (int64_t)ad[10] * bd[10] + + (int64_t)ad[11] * bd[ 9]; + t[21] = (int64_t)ad[10] * bd[11] + (int64_t)ad[11] * bd[10]; + t[22] = (int64_t)ad[11] * bd[11]; + t[23] = 0; + + carry = t[ 0] >> 21; t[ 1] += carry; t[ 0] &= MASK_21; + carry = t[ 2] >> 21; t[ 3] += carry; t[ 2] &= MASK_21; + carry = t[ 4] >> 21; t[ 5] += carry; t[ 4] &= MASK_21; + carry = t[ 6] >> 21; t[ 7] += carry; t[ 6] &= MASK_21; + carry = t[ 8] >> 21; t[ 9] += carry; t[ 8] &= MASK_21; + carry = t[10] >> 21; t[11] += carry; t[10] &= MASK_21; + carry = t[12] >> 21; t[13] += carry; t[12] &= MASK_21; + carry = t[14] >> 21; t[15] += carry; t[14] &= MASK_21; + carry = t[16] >> 21; t[17] += carry; t[16] &= MASK_21; + carry = t[18] >> 21; t[19] += carry; t[18] &= MASK_21; + carry = t[20] >> 21; t[21] += carry; t[20] &= MASK_21; + carry = t[22] >> 21; t[23] += carry; t[22] &= MASK_21; + carry = t[ 1] >> 21; t[ 2] += carry; t[ 1] &= MASK_21; + carry = t[ 3] >> 21; t[ 4] += carry; t[ 3] &= MASK_21; + carry = t[ 5] >> 21; t[ 6] += carry; t[ 5] &= MASK_21; + carry = t[ 7] >> 21; t[ 8] += carry; t[ 7] &= MASK_21; + carry = t[ 9] >> 21; t[10] += carry; t[ 9] &= MASK_21; + carry = t[11] >> 21; t[12] += carry; t[11] &= MASK_21; + carry = t[13] >> 21; t[14] += carry; t[13] &= MASK_21; + carry = t[15] >> 21; t[16] += carry; t[15] &= MASK_21; + carry = t[17] >> 21; t[18] += carry; t[17] &= MASK_21; + carry = t[19] >> 21; t[20] += carry; t[19] &= MASK_21; + carry = t[21] >> 21; t[22] += carry; t[21] &= MASK_21; + + t[11] -= t[23] * ORDER_0; + t[12] -= t[23] * ORDER_1; + t[13] -= t[23] * ORDER_2; + t[14] -= t[23] * ORDER_3; + t[15] -= t[23] * ORDER_4; + t[16] -= t[23] * ORDER_5; + + t[10] -= t[22] * ORDER_0; + t[11] -= t[22] * ORDER_1; + t[12] -= t[22] * ORDER_2; + t[13] -= t[22] * ORDER_3; + t[14] -= t[22] * ORDER_4; + t[15] -= t[22] * ORDER_5; + + t[ 9] -= t[21] * ORDER_0; + t[10] -= t[21] * ORDER_1; + t[11] -= t[21] * ORDER_2; + t[12] -= t[21] * ORDER_3; + t[13] -= t[21] * ORDER_4; + t[14] -= t[21] * ORDER_5; + + t[ 8] -= t[20] * ORDER_0; + t[ 9] -= t[20] * ORDER_1; + t[10] -= t[20] * ORDER_2; + t[11] -= t[20] * ORDER_3; + t[12] -= t[20] * ORDER_4; + t[13] -= t[20] * ORDER_5; + + t[ 7] -= t[19] * ORDER_0; + t[ 8] -= t[19] * ORDER_1; + t[ 9] -= t[19] * ORDER_2; + t[10] -= t[19] * ORDER_3; + t[11] -= t[19] * ORDER_4; + t[12] -= t[19] * ORDER_5; + + t[ 6] -= t[18] * ORDER_0; + t[ 7] -= t[18] * ORDER_1; + t[ 8] -= t[18] * ORDER_2; + t[ 9] -= t[18] * ORDER_3; + t[10] -= t[18] * ORDER_4; + t[11] -= t[18] * ORDER_5; + + carry = t[ 6] >> 21; t[ 7] += carry; t[ 6] &= MASK_21; + carry = t[ 8] >> 21; t[ 9] += carry; t[ 8] &= MASK_21; + carry = t[10] >> 21; t[11] += carry; t[10] &= MASK_21; + carry = t[12] >> 21; t[13] += carry; t[12] &= MASK_21; + carry = t[14] >> 21; t[15] += carry; t[14] &= MASK_21; + carry = t[16] >> 21; t[17] += carry; t[16] &= MASK_21; + carry = t[ 7] >> 21; t[ 8] += carry; t[ 7] &= MASK_21; + carry = t[ 9] >> 21; t[10] += carry; t[ 9] &= MASK_21; + carry = t[11] >> 21; t[12] += carry; t[11] &= MASK_21; + carry = t[13] >> 21; t[14] += carry; t[13] &= MASK_21; + carry = t[15] >> 21; t[16] += carry; t[15] &= MASK_21; + + t[ 5] -= t[17] * ORDER_0; + t[ 6] -= t[17] * ORDER_1; + t[ 7] -= t[17] * ORDER_2; + t[ 8] -= t[17] * ORDER_3; + t[ 9] -= t[17] * ORDER_4; + t[10] -= t[17] * ORDER_5; + + t[ 4] -= t[16] * ORDER_0; + t[ 5] -= t[16] * ORDER_1; + t[ 6] -= t[16] * ORDER_2; + t[ 7] -= t[16] * ORDER_3; + t[ 8] -= t[16] * ORDER_4; + t[ 9] -= t[16] * ORDER_5; + + t[ 3] -= t[15] * ORDER_0; + t[ 4] -= t[15] * ORDER_1; + t[ 5] -= t[15] * ORDER_2; + t[ 6] -= t[15] * ORDER_3; + t[ 7] -= t[15] * ORDER_4; + t[ 8] -= t[15] * ORDER_5; + + t[ 2] -= t[14] * ORDER_0; + t[ 3] -= t[14] * ORDER_1; + t[ 4] -= t[14] * ORDER_2; + t[ 5] -= t[14] * ORDER_3; + t[ 6] -= t[14] * ORDER_4; + t[ 7] -= t[14] * ORDER_5; + + t[ 1] -= t[13] * ORDER_0; + t[ 2] -= t[13] * ORDER_1; + t[ 3] -= t[13] * ORDER_2; + t[ 4] -= t[13] * ORDER_3; + t[ 5] -= t[13] * ORDER_4; + t[ 6] -= t[13] * ORDER_5; + + t[ 0] -= t[12] * ORDER_0; + t[ 1] -= t[12] * ORDER_1; + t[ 2] -= t[12] * ORDER_2; + t[ 3] -= t[12] * ORDER_3; + t[ 4] -= t[12] * ORDER_4; + t[ 5] -= t[12] * ORDER_5; + t[12] = 0; + + carry = t[ 0] >> 21; t[ 1] += carry; t[ 0] &= MASK_21; + carry = t[ 1] >> 21; t[ 2] += carry; t[ 1] &= MASK_21; + carry = t[ 2] >> 21; t[ 3] += carry; t[ 2] &= MASK_21; + carry = t[ 3] >> 21; t[ 4] += carry; t[ 3] &= MASK_21; + carry = t[ 4] >> 21; t[ 5] += carry; t[ 4] &= MASK_21; + carry = t[ 5] >> 21; t[ 6] += carry; t[ 5] &= MASK_21; + carry = t[ 6] >> 21; t[ 7] += carry; t[ 6] &= MASK_21; + carry = t[ 7] >> 21; t[ 8] += carry; t[ 7] &= MASK_21; + carry = t[ 8] >> 21; t[ 9] += carry; t[ 8] &= MASK_21; + carry = t[ 9] >> 21; t[10] += carry; t[ 9] &= MASK_21; + carry = t[10] >> 21; t[11] += carry; t[10] &= MASK_21; + carry = t[11] >> 21; t[12] += carry; t[11] &= MASK_21; + + t[ 0] -= t[12] * ORDER_0; + t[ 1] -= t[12] * ORDER_1; + t[ 2] -= t[12] * ORDER_2; + t[ 3] -= t[12] * ORDER_3; + t[ 4] -= t[12] * ORDER_4; + t[ 5] -= t[12] * ORDER_5; + + carry = t[ 0] >> 21; t[ 1] += carry; t[ 0] &= MASK_21; + carry = t[ 1] >> 21; t[ 2] += carry; t[ 1] &= MASK_21; + carry = t[ 2] >> 21; t[ 3] += carry; t[ 2] &= MASK_21; + carry = t[ 3] >> 21; t[ 4] += carry; t[ 3] &= MASK_21; + carry = t[ 4] >> 21; t[ 5] += carry; t[ 4] &= MASK_21; + carry = t[ 5] >> 21; t[ 6] += carry; t[ 5] &= MASK_21; + carry = t[ 6] >> 21; t[ 7] += carry; t[ 6] &= MASK_21; + carry = t[ 7] >> 21; t[ 8] += carry; t[ 7] &= MASK_21; + carry = t[ 8] >> 21; t[ 9] += carry; t[ 8] &= MASK_21; + carry = t[ 9] >> 21; t[10] += carry; t[ 9] &= MASK_21; + carry = t[10] >> 21; t[11] += carry; t[10] &= MASK_21; + + s[ 0] = (byte)(t[ 0] >> 0); + s[ 1] = (byte)(t[ 0] >> 8); + s[ 2] = (byte)((t[ 0] >> 16) | (t[ 1] << 5)); + s[ 3] = (byte)(t[ 1] >> 3); + s[ 4] = (byte)(t[ 1] >> 11); + s[ 5] = (byte)((t[ 1] >> 19) | (t[ 2] << 2)); + s[ 6] = (byte)(t[ 2] >> 6); + s[ 7] = (byte)((t[ 2] >> 14) | (t[ 3] << 7)); + s[ 8] = (byte)(t[ 3] >> 1); + s[ 9] = (byte)(t[ 3] >> 9); + s[10] = (byte)((t[ 3] >> 17) | (t[ 4] << 4)); + s[11] = (byte)(t[ 4] >> 4); + s[12] = (byte)(t[ 4] >> 12); + s[13] = (byte)((t[ 4] >> 20) | (t[ 5] << 1)); + s[14] = (byte)(t[ 5] >> 7); + s[15] = (byte)((t[ 5] >> 15) | (t[ 6] << 6)); + s[16] = (byte)(t[ 6] >> 2); + s[17] = (byte)(t[ 6] >> 10); + s[18] = (byte)((t[ 6] >> 18) | (t[ 7] << 3)); + s[19] = (byte)(t[ 7] >> 5); + s[20] = (byte)(t[ 7] >> 13); + s[21] = (byte)(t[ 8] >> 0); + s[22] = (byte)(t[ 8] >> 8); + s[23] = (byte)((t[ 8] >> 16) | (t[ 9] << 5)); + s[24] = (byte)(t[ 9] >> 3); + s[25] = (byte)(t[ 9] >> 11); + s[26] = (byte)((t[ 9] >> 19) | (t[10] << 2)); + s[27] = (byte)(t[10] >> 6); + s[28] = (byte)((t[10] >> 14) | (t[11] << 7)); + s[29] = (byte)(t[11] >> 1); + s[30] = (byte)(t[11] >> 9); + s[31] = (byte)(t[11] >> 17); +} +#else +static uint64_t load_6(const byte* a) +{ + uint64_t n; + n = ((uint64_t)a[0] << 0) | + ((uint64_t)a[1] << 8) | + ((uint64_t)a[2] << 16) | + ((uint64_t)a[3] << 24) | + ((uint64_t)a[4] << 32) | + ((uint64_t)a[5] << 40); + return n; +} + +static uint64_t load_7(const byte* a) +{ + uint64_t n; + n = ((uint64_t)a[0] << 0) | + ((uint64_t)a[1] << 8) | + ((uint64_t)a[2] << 16) | + ((uint64_t)a[3] << 24) | + ((uint64_t)a[4] << 32) | + ((uint64_t)a[5] << 40) | + ((uint64_t)a[6] << 48); + return n; +} + +#define MASK_42 0x3ffffffffffl +#define ORDER_0 0x31a5cf5d3edl +#define ORDER_1 0x1e735960498l +#define ORDER_2 0x14def9dea2fl + +/* +Input: + s[0]+256*s[1]+...+256^63*s[63] = s + +Output: + s[0]+256*s[1]+...+256^31*s[31] = s mod l + where l = 2^252 + 27742317777372353535851937790883648493. + Overwrites s in place. +*/ +void sc_reduce(byte* s) +{ + __int128_t t[12]; + __int128_t carry; + + t[ 0] = MASK_42 & (load_6(s + 0) >> 0); + t[ 1] = MASK_42 & (load_6(s + 5) >> 2); + t[ 2] = MASK_42 & (load_6(s + 10) >> 4); + t[ 3] = MASK_42 & (load_6(s + 15) >> 6); + t[ 4] = MASK_42 & (load_6(s + 21) >> 0); + t[ 5] = MASK_42 & (load_6(s + 26) >> 2); + t[ 6] = MASK_42 & (load_6(s + 31) >> 4); + t[ 7] = MASK_42 & (load_6(s + 36) >> 6); + t[ 8] = MASK_42 & (load_6(s + 42) >> 0); + t[ 9] = MASK_42 & (load_6(s + 47) >> 2); + t[10] = MASK_42 & (load_6(s + 52) >> 4); + t[11] = (load_7(s + 57) >> 6); + + t[ 5] -= t[11] * ORDER_0; + t[ 6] -= t[11] * ORDER_1; + t[ 7] -= t[11] * ORDER_2; + + t[ 4] -= t[10] * ORDER_0; + t[ 5] -= t[10] * ORDER_1; + t[ 6] -= t[10] * ORDER_2; + + t[ 3] -= t[ 9] * ORDER_0; + t[ 4] -= t[ 9] * ORDER_1; + t[ 5] -= t[ 9] * ORDER_2; + + carry = t[ 3] >> 42; t[ 4] += carry; t[ 3] &= MASK_42; + carry = t[ 5] >> 42; t[ 6] += carry; t[ 5] &= MASK_42; + carry = t[ 7] >> 42; t[ 8] += carry; t[ 7] &= MASK_42; + carry = t[ 4] >> 42; t[ 5] += carry; t[ 4] &= MASK_42; + carry = t[ 6] >> 42; t[ 7] += carry; t[ 6] &= MASK_42; + + t[ 2] -= t[ 8] * ORDER_0; + t[ 3] -= t[ 8] * ORDER_1; + t[ 4] -= t[ 8] * ORDER_2; + + t[ 1] -= t[ 7] * ORDER_0; + t[ 2] -= t[ 7] * ORDER_1; + t[ 3] -= t[ 7] * ORDER_2; + + t[ 0] -= t[ 6] * ORDER_0; + t[ 1] -= t[ 6] * ORDER_1; + t[ 2] -= t[ 6] * ORDER_2; + t[ 6] = 0; + + carry = t[ 0] >> 42; t[ 1] += carry; t[ 0] &= MASK_42; + carry = t[ 1] >> 42; t[ 2] += carry; t[ 1] &= MASK_42; + carry = t[ 2] >> 42; t[ 3] += carry; t[ 2] &= MASK_42; + carry = t[ 3] >> 42; t[ 4] += carry; t[ 3] &= MASK_42; + carry = t[ 4] >> 42; t[ 5] += carry; t[ 4] &= MASK_42; + carry = t[ 5] >> 42; t[ 6] += carry; t[ 5] &= MASK_42; + + t[ 0] -= t[ 6] * ORDER_0; + t[ 1] -= t[ 6] * ORDER_1; + t[ 2] -= t[ 6] * ORDER_2; + + carry = t[ 0] >> 42; t[ 1] += carry; t[ 0] &= MASK_42; + carry = t[ 1] >> 42; t[ 2] += carry; t[ 1] &= MASK_42; + carry = t[ 2] >> 42; t[ 3] += carry; t[ 2] &= MASK_42; + carry = t[ 3] >> 42; t[ 4] += carry; t[ 3] &= MASK_42; + carry = t[ 4] >> 42; t[ 5] += carry; t[ 4] &= MASK_42; + + s[ 0] = (t[ 0] >> 0); + s[ 1] = (t[ 0] >> 8); + s[ 2] = (t[ 0] >> 16); + s[ 3] = (t[ 0] >> 24); + s[ 4] = (t[ 0] >> 32); + s[ 5] = (t[ 0] >> 40) | (t[ 1] << 2); + s[ 6] = (t[ 1] >> 6); + s[ 7] = (t[ 1] >> 14); + s[ 8] = (t[ 1] >> 22); + s[ 9] = (t[ 1] >> 30); + s[10] = (t[ 1] >> 38) | (t[ 2] << 4); + s[11] = (t[ 2] >> 4); + s[12] = (t[ 2] >> 12); + s[13] = (t[ 2] >> 20); + s[14] = (t[ 2] >> 28); + s[15] = (t[ 2] >> 36) | (t[ 3] << 6); + s[16] = (t[ 3] >> 2); + s[17] = (t[ 3] >> 10); + s[18] = (t[ 3] >> 18); + s[19] = (t[ 3] >> 26); + s[20] = (t[ 3] >> 34); + s[21] = (t[ 4] >> 0); + s[22] = (t[ 4] >> 8); + s[23] = (t[ 4] >> 16); + s[24] = (t[ 4] >> 24); + s[25] = (t[ 4] >> 32); + s[26] = (t[ 4] >> 40) | (t[ 5] << 2); + s[27] = (t[ 5] >> 6); + s[28] = (t[ 5] >> 14); + s[29] = (t[ 5] >> 22); + s[30] = (t[ 5] >> 30); + s[31] = (t[ 5] >> 38); +} + +/* +Input: + a[0]+256*a[1]+...+256^31*a[31] = a + b[0]+256*b[1]+...+256^31*b[31] = b + c[0]+256*c[1]+...+256^31*c[31] = c + +Output: + s[0]+256*s[1]+...+256^31*s[31] = (ab+c) mod l + where l = 2^252 + 27742317777372353535851937790883648493. +*/ +void sc_muladd(byte* s, const byte* a, const byte* b, const byte* c) +{ + uint64_t ad[6], bd[6], cd[6]; + __int128_t t[12]; + __int128_t carry; + + ad[ 0] = MASK_42 & (load_6(a + 0) >> 0); + ad[ 1] = MASK_42 & (load_6(a + 5) >> 2); + ad[ 2] = MASK_42 & (load_6(a + 10) >> 4); + ad[ 3] = MASK_42 & (load_6(a + 15) >> 6); + ad[ 4] = MASK_42 & (load_6(a + 21) >> 0); + ad[ 5] = (load_6(a + 26) >> 2); + bd[ 0] = MASK_42 & (load_6(b + 0) >> 0); + bd[ 1] = MASK_42 & (load_6(b + 5) >> 2); + bd[ 2] = MASK_42 & (load_6(b + 10) >> 4); + bd[ 3] = MASK_42 & (load_6(b + 15) >> 6); + bd[ 4] = MASK_42 & (load_6(b + 21) >> 0); + bd[ 5] = (load_6(b + 26) >> 2); + cd[ 0] = MASK_42 & (load_6(c + 0) >> 0); + cd[ 1] = MASK_42 & (load_6(c + 5) >> 2); + cd[ 2] = MASK_42 & (load_6(c + 10) >> 4); + cd[ 3] = MASK_42 & (load_6(c + 15) >> 6); + cd[ 4] = MASK_42 & (load_6(c + 21) >> 0); + cd[ 5] = (load_6(c + 26) >> 2); + + t[ 0] = cd[ 0] + (__int128_t)ad[ 0] * bd[ 0]; + t[ 1] = cd[ 1] + (__int128_t)ad[ 0] * bd[ 1] + (__int128_t)ad[ 1] * bd[ 0]; + t[ 2] = cd[ 2] + (__int128_t)ad[ 0] * bd[ 2] + (__int128_t)ad[ 1] * bd[ 1] + + (__int128_t)ad[ 2] * bd[ 0]; + t[ 3] = cd[ 3] + (__int128_t)ad[ 0] * bd[ 3] + (__int128_t)ad[ 1] * bd[ 2] + + (__int128_t)ad[ 2] * bd[ 1] + (__int128_t)ad[ 3] * bd[ 0]; + t[ 4] = cd[ 4] + (__int128_t)ad[ 0] * bd[ 4] + (__int128_t)ad[ 1] * bd[ 3] + + (__int128_t)ad[ 2] * bd[ 2] + (__int128_t)ad[ 3] * bd[ 1] + + (__int128_t)ad[ 4] * bd[ 0]; + t[ 5] = cd[ 5] + (__int128_t)ad[ 0] * bd[ 5] + (__int128_t)ad[ 1] * bd[ 4] + + (__int128_t)ad[ 2] * bd[ 3] + (__int128_t)ad[ 3] * bd[ 2] + + (__int128_t)ad[ 4] * bd[ 1] + (__int128_t)ad[ 5] * bd[ 0]; + t[ 6] = (__int128_t)ad[ 1] * bd[ 5] + (__int128_t)ad[ 2] * bd[ 4] + + (__int128_t)ad[ 3] * bd[ 3] + (__int128_t)ad[ 4] * bd[ 2] + + (__int128_t)ad[ 5] * bd[ 1]; + t[ 7] = (__int128_t)ad[ 2] * bd[ 5] + (__int128_t)ad[ 3] * bd[ 4] + + (__int128_t)ad[ 4] * bd[ 3] + (__int128_t)ad[ 5] * bd[ 2]; + t[ 8] = (__int128_t)ad[ 3] * bd[ 5] + (__int128_t)ad[ 4] * bd[ 4] + + (__int128_t)ad[ 5] * bd[ 3]; + t[ 9] = (__int128_t)ad[ 4] * bd[ 5] + (__int128_t)ad[ 5] * bd[ 4]; + t[10] = (__int128_t)ad[ 5] * bd[ 5]; + t[11] = 0; + + carry = t[ 0] >> 42; t[ 1] += carry; t[ 0] &= MASK_42; + carry = t[ 2] >> 42; t[ 3] += carry; t[ 2] &= MASK_42; + carry = t[ 4] >> 42; t[ 5] += carry; t[ 4] &= MASK_42; + carry = t[ 6] >> 42; t[ 7] += carry; t[ 6] &= MASK_42; + carry = t[ 8] >> 42; t[ 9] += carry; t[ 8] &= MASK_42; + carry = t[10] >> 42; t[11] += carry; t[10] &= MASK_42; + carry = t[ 1] >> 42; t[ 2] += carry; t[ 1] &= MASK_42; + carry = t[ 3] >> 42; t[ 4] += carry; t[ 3] &= MASK_42; + carry = t[ 5] >> 42; t[ 6] += carry; t[ 5] &= MASK_42; + carry = t[ 7] >> 42; t[ 8] += carry; t[ 7] &= MASK_42; + carry = t[ 9] >> 42; t[10] += carry; t[ 9] &= MASK_42; + + t[ 5] -= t[11] * ORDER_0; + t[ 6] -= t[11] * ORDER_1; + t[ 7] -= t[11] * ORDER_2; + + t[ 4] -= t[10] * ORDER_0; + t[ 5] -= t[10] * ORDER_1; + t[ 6] -= t[10] * ORDER_2; + + t[ 3] -= t[ 9] * ORDER_0; + t[ 4] -= t[ 9] * ORDER_1; + t[ 5] -= t[ 9] * ORDER_2; + + carry = t[ 3] >> 42; t[ 4] += carry; t[ 3] &= MASK_42; + carry = t[ 5] >> 42; t[ 6] += carry; t[ 5] &= MASK_42; + carry = t[ 7] >> 42; t[ 8] += carry; t[ 7] &= MASK_42; + carry = t[ 4] >> 42; t[ 5] += carry; t[ 4] &= MASK_42; + carry = t[ 6] >> 42; t[ 7] += carry; t[ 6] &= MASK_42; + + t[ 2] -= t[ 8] * ORDER_0; + t[ 3] -= t[ 8] * ORDER_1; + t[ 4] -= t[ 8] * ORDER_2; + + t[ 1] -= t[ 7] * ORDER_0; + t[ 2] -= t[ 7] * ORDER_1; + t[ 3] -= t[ 7] * ORDER_2; + + t[ 0] -= t[ 6] * ORDER_0; + t[ 1] -= t[ 6] * ORDER_1; + t[ 2] -= t[ 6] * ORDER_2; + t[ 6] = 0; + + carry = t[ 0] >> 42; t[ 1] += carry; t[ 0] &= MASK_42; + carry = t[ 1] >> 42; t[ 2] += carry; t[ 1] &= MASK_42; + carry = t[ 2] >> 42; t[ 3] += carry; t[ 2] &= MASK_42; + carry = t[ 3] >> 42; t[ 4] += carry; t[ 3] &= MASK_42; + carry = t[ 4] >> 42; t[ 5] += carry; t[ 4] &= MASK_42; + carry = t[ 5] >> 42; t[ 6] += carry; t[ 5] &= MASK_42; + + t[ 0] -= t[ 6] * ORDER_0; + t[ 1] -= t[ 6] * ORDER_1; + t[ 2] -= t[ 6] * ORDER_2; + + carry = t[ 0] >> 42; t[ 1] += carry; t[ 0] &= MASK_42; + carry = t[ 1] >> 42; t[ 2] += carry; t[ 1] &= MASK_42; + carry = t[ 2] >> 42; t[ 3] += carry; t[ 2] &= MASK_42; + carry = t[ 3] >> 42; t[ 4] += carry; t[ 3] &= MASK_42; + carry = t[ 4] >> 42; t[ 5] += carry; t[ 4] &= MASK_42; + + s[ 0] = (t[ 0] >> 0); + s[ 1] = (t[ 0] >> 8); + s[ 2] = (t[ 0] >> 16); + s[ 3] = (t[ 0] >> 24); + s[ 4] = (t[ 0] >> 32); + s[ 5] = (t[ 0] >> 40) | (t[ 1] << 2); + s[ 6] = (t[ 1] >> 6); + s[ 7] = (t[ 1] >> 14); + s[ 8] = (t[ 1] >> 22); + s[ 9] = (t[ 1] >> 30); + s[10] = (t[ 1] >> 38) | (t[ 2] << 4); + s[11] = (t[ 2] >> 4); + s[12] = (t[ 2] >> 12); + s[13] = (t[ 2] >> 20); + s[14] = (t[ 2] >> 28); + s[15] = (t[ 2] >> 36) | (t[ 3] << 6); + s[16] = (t[ 3] >> 2); + s[17] = (t[ 3] >> 10); + s[18] = (t[ 3] >> 18); + s[19] = (t[ 3] >> 26); + s[20] = (t[ 3] >> 34); + s[21] = (t[ 4] >> 0); + s[22] = (t[ 4] >> 8); + s[23] = (t[ 4] >> 16); + s[24] = (t[ 4] >> 24); + s[25] = (t[ 4] >> 32); + s[26] = (t[ 4] >> 40) | (t[ 5] << 2); + s[27] = (t[ 5] >> 6); + s[28] = (t[ 5] >> 14); + s[29] = (t[ 5] >> 22); + s[30] = (t[ 5] >> 30); + s[31] = (t[ 5] >> 38); +} +#endif /* !HAVE___UINT128_T || NO_CURVED25519_128BIT */ + +int ge_compress_key(byte* out, const byte* xIn, const byte* yIn, word32 keySz) +{ + ge x,y,z; + ge_p3 g; + byte bArray[ED25519_KEY_SIZE]; + word32 i; + + fe_0(x); + fe_0(y); + fe_1(z); + fe_frombytes(x, xIn); + fe_frombytes(y, yIn); + + fe_copy(g.X, x); + fe_copy(g.Y, y); + fe_copy(g.Z, z); + + ge_p3_tobytes(bArray, &g); + + for (i = 0; i < keySz; i++) { + out[keySz - 1 - i] = bArray[i]; + } + + return 0; +} + + +/* +r = p + q +*/ +static WC_INLINE void ge_add(ge_p1p1 *r,const ge_p3 *p,const ge_cached *q) +{ +#ifndef CURVED25519_ASM + ge t0; + fe_add(r->X,p->Y,p->X); + fe_sub(r->Y,p->Y,p->X); + fe_mul(r->Z,r->X,q->YplusX); + fe_mul(r->Y,r->Y,q->YminusX); + fe_mul(r->T,q->T2d,p->T); + fe_mul(r->X,p->Z,q->Z); + fe_add(t0,r->X,r->X); + fe_sub(r->X,r->Z,r->Y); + fe_add(r->Y,r->Z,r->Y); + fe_add(r->Z,t0,r->T); + fe_sub(r->T,t0,r->T); +#else + fe_ge_add(r->X, r->Y, r->Z, r->T, p->X, p->Y, p->Z, p->T, q->Z, q->T2d, + q->YplusX, q->YminusX); +#endif +} + + +#ifndef CURVED25519_ASM +/* ge_scalar mult base */ +static unsigned char equal(signed char b,signed char c) +{ + unsigned char ub = b; + unsigned char uc = c; + unsigned char x = ub ^ uc; /* 0: yes; 1..255: no */ + uint32_t y = x; /* 0: yes; 1..255: no */ + y -= 1; /* 4294967295: yes; 0..254: no */ + y >>= 31; /* 1: yes; 0: no */ + return (unsigned char)y; +} + + +static unsigned char negative(signed char b) +{ + return ((unsigned char)b) >> 7; +} + + +static WC_INLINE void cmov(ge_precomp *t,const ge_precomp *u,unsigned char b, + unsigned char n) +{ + b = equal(b,n); + fe_cmov(t->yplusx,u->yplusx,b); + fe_cmov(t->yminusx,u->yminusx,b); + fe_cmov(t->xy2d,u->xy2d,b); +} +#endif + +#ifdef CURVED25519_ASM_64BIT +static const ge_precomp base[64][8] = { +{ + { + { 0x2fbc93c6f58c3b85, -0x306cd2390473f1e7, 0x270b4898643d42c2, 0x07cf9d3a33d4ba65 }, + { -0x62efc6fa28bf6ec2, -0x02c660fa2ebf414d, -0x5a3e7bcb977075f7, 0x44fd2f9298f81267 }, + { -0x2442ea98b49044a7, 0x41e13f00eea2a5ea, -0x322b62e336a83906, 0x4f0ebe1faf16ecca } + }, + { + { -0x6ddb18036cc38e29, -0x60b9626985f00a4b, 0x5aa69a65e1d60702, 0x590c063fa87d2e2e }, + { -0x75665a9fbd4b2a58, -0x70d47ef3b19f530a, -0x1f61dc944e91c856, 0x6bb595a669c92555 }, + { 0x6e347eaadad36802, -0x450ca66c7c11b7fb, 0x3bcabe10e6076826, 0x49314f0a165ed1b8 } + }, + { + { -0x50da4f57b31168d0, 0x025a8430e8864b8a, -0x3ee4affd60fe98ce, 0x7a164e1b9a80f8f4 }, + { 0x56611fe8a4fcd265, 0x3bd353fde5c1ba7d, -0x7ece0ce5deb42943, 0x2ab91587555bda62 }, + { -0x640dee0b0e98b7cc, -0x47b194e809d2076b, -0x282190f8a48dd5b2, 0x549a04b963bb2a21 } + }, + { + { 0x287351b98efc099f, 0x6765c6f47dfd2538, -0x35cb72c204f56d9b, 0x680e910321e58727 }, + { -0x6a01faf5fa97e741, 0x327e89715660faa9, -0x3c171c32f95faf8d, 0x27933f4c7445a49a }, + { -0x40e1ba131aebd950, -0x1cd439c29245f06c, -0x1bd68b2a7307ad40, 0x44f079b1b0e64c18 } + }, + { + { -0x5ded43bbf75a44cd, -0x72afb73c38a112fe, -0x22e414f3a54013bc, 0x2945ccf146e206eb }, + { 0x7f9182c3a447d6ba, -0x2affeb2eb4d8d649, -0x1cc30ee3479b5f79, 0x154a7e73eb1b55f3 }, + { -0x37cd5e86182ffc4d, 0x5f729d0a00124d7e, 0x62c1d4a10e6d8ff3, 0x68b8ac5938b27a98 } + }, + { + { 0x3a0ceeeb77157131, -0x64d8ea76ff375078, -0x7f9a499725a658ca, 0x51e57bb6a2cc38bd }, + { 0x499806b67b7d8ca4, 0x575be28427d22739, -0x44f7a318dfbaac47, 0x38b64c41ae417884 }, + { -0x7062526e97621c5c, 0x175f2428f8fb9137, 0x050ab5329fcfb988, 0x7865dfa21354c09f } + }, + { + { 0x6b1a5cd0944ea3bf, 0x7470353ab39dc0d2, 0x71b2528228542e49, 0x461bea69283c927e }, + { -0x4590d36555cdde4f, 0x6ca021533bba23a7, -0x621589b06de6d3c6, 0x1d6edd5d2e5317e0 }, + { 0x217a8aacab0fda36, -0x5ad739abc2cab638, 0x37d05b8b13ab7568, 0x233cef623a2cbc37 } + }, + { + { 0x59b7596604dd3e8f, 0x6cb30377e288702c, -0x4ecc6399a1263cdd, 0x0915e76061bce52f }, + { -0x1d58a2120c6dcb27, -0x69c2897f1e4aa707, 0x2c2741ac6e3c23fb, 0x3a9024a1320e01c3 }, + { -0x208217ca57cb5c82, -0x741e63259767a816, 0x2c1185367167b326, 0x589eb3d9dbefd5c2 } + }, +}, +{ + { + { 0x322d04a52d9021f6, -0x463e60cc8a394064, 0x587a3a4342d20b09, 0x143b1cf8aa64fe61 }, + { 0x7ec851ca553e2df3, -0x58ed7b3459b7874d, -0x194a1be6cd772e19, 0x4cf210ec5a9a8883 }, + { -0x6079838269753555, 0x5f54258e27092729, -0x2f582cb415e7f68b, 0x21b546a3374126e1 } + }, + { + { 0x490a7a45d185218f, -0x65eac887b9fb6ccb, 0x0060ea09cc31e1f6, 0x7e041577f86ee965 }, + { -0x56b007a75d777cbd, -0x31f12ba9acec12c4, -0x0aa3c2304a40cb06, 0x0a653ca5c9eab371 }, + { 0x66b2a496ce5b67f3, -0x00ab6d2742a9686a, 0x503cec294a592cd0, 0x566943650813acb2 } + }, + { + { 0x5672f9eb1dabb69d, -0x458f4aca5017ac04, 0x47ac0f752796d66d, 0x32a5351794117275 }, + { -0x47e724f3d99df868, 0x5d5c31d9606e354a, 0x0982fa4f00a8cdc7, 0x17e12bcd4653e2d4 }, + { -0x2c59bb59209b7bc9, 0x703b6559880fbfdd, -0x347adabf52c5e55b, 0x0900b3f78e4c6468 } + }, + { + { -0x12d7f04137e952cf, 0x52d9595bd8e6efe3, 0x0fe71772f6c623f5, 0x4314030b051e293c }, + { 0x0a851b9f679d651b, -0x1ef7349efcccbd0e, -0x29fe0a801774cf5d, 0x371f3acaed2dd714 }, + { -0x2a9fffa1040f4353, -0x7148f0d12e78f3a2, 0x201f9033d084e6a0, 0x4c3a5ae1ce7b6670 } + }, + { + { -0x45078a1b36c25f23, -0x46cd7d588e46d6b3, -0x7f29c0480b393ba0, 0x6de9c73dea66c181 }, + { 0x4138a434dcb8fa95, -0x78f3098293697bf5, -0x21c77a8bd68417d4, 0x7c814db27262a55a }, + { 0x478904d5a04df8f2, -0x050451b54efebd2d, -0x0937539caaa2f668, 0x5aac4a412f90b104 } + }, + { + { 0x603a0d0abd7f5134, -0x7f7636cd1e2c51ba, -0x20da6ec67867429d, 0x1c145cd274ba0235 }, + { -0x39b0cd94c536d6f8, 0x5551b282e663e1e0, 0x476b35f54a1a4b83, 0x1b9da3fe189f68c2 }, + { 0x32e8386475f3d743, 0x365b8baf6ae5d9ef, -0x7dadc749c7a497e2, 0x234929c1167d65e1 } + }, + { + { 0x48145cc21d099fcf, 0x4535c192cc28d7e5, -0x7f183e1ab7db81ff, 0x4a5f28743b2973ee }, + { -0x67b213545f885218, 0x383f77ad19eb389d, -0x38139481d6ab286c, 0x59c77b3aeb7c3a7a }, + { -0x2c5228dadda3309e, -0x6ee5cc7e4dead3a3, -0x274c6052a4f70783, 0x6f05606b4799fe3b } + }, + { + { 0x5b433149f91b6483, -0x524a239aa5d3409e, -0x78057bed9cd7d84d, 0x60895e91ab49f8d8 }, + { -0x6001616de884569e, -0x675118e2f21a351f, 0x3ff4ae942d831044, 0x714de12e58533ac8 }, + { -0x16130d12f30793e8, -0x4b92f9edf8ca202c, -0x43625f67fb469419, 0x73e2e62fd96dc26b } + }, +}, +{ + { + { 0x2eccdd0e632f9c1d, 0x51d0b69676893115, 0x52dfb76ba8637a58, 0x6dd37d49a00eef39 }, + { -0x12a49cabb655aea2, -0x579a3b60f4397dc6, -0x7af3e016a4bd2e3c, 0x30d76d6f03d315b9 }, + { 0x6c4444172106e4c7, -0x04ac297f6d728097, -0x4b8c615b96b2c0da, 0x10c697112e864bb0 } + }, + { + { 0x0ca62aa08358c805, 0x6a3d4ae37a204247, 0x7464d3a63b11eddc, 0x03bf9baf550806ef }, + { 0x6493c4277dbe5fde, 0x265d4fad19ad7ea2, 0x0e00dfc846304590, 0x25e61cabed66fe09 }, + { 0x3f13e128cc586604, 0x6f5873ecb459747e, -0x5f49c21233ed970b, 0x566d78634586e22c } + }, + { + { -0x5efabd7a39a5d030, 0x6c64112af31667c3, 0x680ae240731aee58, 0x14fba5f34793b22a }, + { 0x1637a49f9cc10834, -0x4371a92a57643baf, 0x1cb5ec0f7f7fd2db, 0x33975bca5ecc35d9 }, + { 0x3cd746166985f7d4, 0x593e5e84c9c80057, 0x2fc3f2b67b61131e, 0x14829cea83fc526c } + }, + { + { 0x21e70b2f4e71ecb8, -0x19a92246bf5b881d, -0x409aa93131e2b080, 0x05fc3bc4535d7b7e }, + { -0x00bc847b68226a3e, 0x6c744e30aa4eb5a7, -0x61f3a29ec37a1775, 0x2fd9c71e5f758173 }, + { 0x24b8b3ae52afdedd, 0x3495638ced3b30cf, 0x33a4bc83a9be8195, 0x373767475c651f04 } + }, + { + { 0x634095cb14246590, -0x10edebbfe93eaacb, -0x61c7ebf376ef43a0, 0x6bf5905730907c8c }, + { 0x2fba99fd40d1add9, -0x4cf8e990690b2fd9, 0x4363f05215f03bae, 0x1fbea56c3b18f999 }, + { 0x0fa778f1e1415b8a, 0x06409ff7bac3a77e, 0x6f52d7b89aa29a50, 0x02521cf67a635a56 } + }, + { + { -0x4eeb98df88d0a11c, -0x17076b4e69f86532, 0x4af8224d00ac824a, 0x001753d9f7cd6cc4 }, + { 0x513fee0b0a9d5294, -0x706718a3f020a59a, -0x2b9e7977401ef832, 0x3fa00a7e71382ced }, + { 0x3c69232d963ddb34, 0x1dde87dab4973858, -0x55282e065f6e0d7b, 0x12b5fe2fa048edb6 } + }, + { + { -0x20d483d95290e16e, 0x4b66d323504b8913, -0x73bf623f8ae3743d, 0x6f7e93c20796c7b8 }, + { 0x71f0fbc496fce34d, 0x73b9826badf35bed, -0x2dfb8d9e00d73a9f, 0x749b76f96fb1206f }, + { 0x1f5af604aea6ae05, -0x3edcae0e411b6367, 0x61a808b5eeff6b66, 0x0fcec10f01e02151 } + }, + { + { 0x3df2d29dc4244e45, 0x2b020e7493d8de0a, 0x6cc8067e820c214d, 0x413779166feab90a }, + { 0x644d58a649fe1e44, 0x21fcaea231ad777e, 0x02441c5a887fd0d2, 0x4901aa7183c511f3 }, + { 0x08b1b7548c1af8f0, -0x31f08583db9d664c, -0x089f4f06e1f926c7, 0x41bb887b726d1213 } + }, +}, +{ + { + { -0x68267f1f55c6082e, 0x35d0384252c6b51c, 0x7d43f49307cd55aa, 0x56bd36cfb78ac362 }, + { -0x6d987f93a983b628, 0x066d04ccca791e6a, -0x5960a9ba1c33c6b5, 0x5c95b686a0788cd2 }, + { 0x2ac519c10d14a954, -0x150b8b4b6b4a0570, -0x19507c7d560785a6, 0x0dea6db1879be094 } + }, + { + { 0x15baeb74d6a8797a, 0x7ef55cf1fac41732, 0x29001f5a3c8b05c5, 0x0ad7cc8752eaccfb }, + { -0x559940ab8cbb1a55, -0x25eda77770e4bcf7, 0x5e87d2b3fd564b2f, 0x5b2c78885483b1dd }, + { 0x52151362793408cf, -0x14f0e8fce669c26c, -0x57cc4d0577c26b9a, 0x093a7fa775003c78 } + }, + { + { -0x47169fbb9f56ed7a, 0x7f3fd8047778d3de, 0x67d01e31bf8a5e2d, 0x7b038a06c27b653e }, + { -0x1aef8219c5e92842, -0x5c880023650ccd31, 0x70d5bf18440b677f, 0x6a252b19a4a31403 }, + { -0x6126e62a2c966f0d, 0x5213aebbdb4eb9f2, -0x38f715fab3466ecb, 0x58ded57f72260e56 } + }, + { + { -0x2592acd9a4f02b75, -0x769f7dce6c405678, -0x287536cd9e2a81d8, 0x79f2942d3a5c8143 }, + { 0x78e79dade9413d77, -0x0da8062a68d61983, 0x59db910ee37aa7e6, 0x6aa11b5bbb9e039c }, + { -0x6825d0da49377217, 0x251ba7eaacf20169, 0x09b44f87ef4eb4e4, 0x7d90ab1bbc6a7da5 } + }, + { + { 0x1a07a3f496b3c397, 0x11ceaa188f4e2532, 0x7d9498d5a7751bf0, 0x19ed161f508dd8a0 }, + { -0x6533597c58fe9402, -0x6fafa0b20d3af493, 0x6b610d5fcce435aa, 0x19a10d446198ff96 }, + { 0x560a2cd687dce6ca, 0x7f3568c48664cf4d, -0x78be16addd7fc5c8, 0x483bdab1595653fc } + }, + { + { -0x2930b2f54b257f0a, -0x7db7c1ba07cf8020, 0x05005269ae6f9da4, 0x1c7052909cf7877a }, + { -0x0587f0eb78cb05b7, 0x106f0b70360534e0, 0x2210776fe3e307bd, 0x3286c109dde6a0fe }, + { 0x32ee7de2874e98d4, 0x14c362e9b97e0c60, 0x5781dcde6a60a38a, 0x217dd5eaaa7aa840 } + }, + { + { -0x7420e0464173f138, 0x00bae7f8e30a0282, 0x4963991dad6c4f6c, 0x07058a6e5df6f60a }, + { -0x62483b2fdb71e150, -0x1f89681eb28b40ae, 0x1e6a9b173c562354, 0x7fa7c21f795a4965 }, + { -0x1614fd3b24ce0981, -0x12da0276ef4304d5, 0x46c8131f5c5cddb4, 0x33b21c13a0cb9bce } + }, + { + { -0x6550464fa11c73a5, -0x4062d2b1f8e5ec39, -0x7111919216ccd6f6, 0x1c3bab17ae109717 }, + { 0x360692f8087d8e31, -0x0b2339c82d8e9c09, 0x25a4e62065ea5963, 0x659bf72e5ac160d9 }, + { 0x1c9ab216c7cab7b0, 0x7d65d37407bbc3cc, 0x52744750504a58d5, 0x09f2606b131a2990 } + }, +}, +{ + { + { 0x7e234c597c6691ae, 0x64889d3d0a85b4c8, -0x251d36f3cab50519, 0x0a871e070c6a9e1d }, + { 0x40e87d44744346be, 0x1d48dad415b52b25, 0x7c3a8a18a13b603e, 0x4eb728c12fcdbdf7 }, + { 0x3301b5994bbc8989, 0x736bae3a5bdd4260, 0x0d61ade219d59e3c, 0x3ee7300f2685d464 } + }, + { + { 0x43fa7947841e7518, -0x1a3905a69c63b929, -0x5ef9a1e21cfad48c, 0x7d47c6a2cfb89030 }, + { -0x0a2daa1b61822949, -0x7fe9eea39ef4e154, 0x3c99975d92e187ca, 0x13815762979125c2 }, + { 0x3fdad0148ef0d6e0, -0x62c18b656eab90c4, 0x71ec621026bb8157, 0x148cf58d34c9ec80 } + }, + { + { -0x1da8d082651b8a93, 0x56c345bb88f3487f, -0x602ef492969f5773, 0x278febad4eaea1b9 }, + { 0x46a492f67934f027, 0x469984bef6840aa9, 0x5ca1bc2a89611854, 0x3ff2fa1ebd5dbbd4 }, + { -0x4e5597e0736cc69a, -0x73de6b63dfd6f368, 0x39115291219d3c52, 0x4104dd02fe9c677b } + }, + { + { -0x7edeb1f924f69548, 0x21a8b6c90ce44f35, 0x6524c12a409e2af5, 0x0165b5a48efca481 }, + { 0x72b2bf5e1124422a, -0x5e05f3cc675cc54b, -0x6b349efe05ad499a, 0x2c863b00afaf53d5 }, + { -0x0e6f5b8b5f7b958a, 0x12eff984cd2f7cc0, 0x695e290658aa2b8f, 0x591b67d9bffec8b8 } + }, + { + { -0x66464c8e60e74aa3, -0x1b9a1a055e739be2, 0x61081136c29f05ed, 0x489b4f867030128b }, + { 0x312f0d1c80b49bfa, 0x5979515eabf3ec8a, 0x727033c09ef01c88, 0x3de02ec7ca8f7bcb }, + { -0x2dcdefd2c5146d11, -0x1e9dac4b9ee9579f, 0x3d7eabe7190baa24, 0x49f5fbba496cbebf } + }, + { + { 0x155d628c1e9c572e, -0x75b279533a77b8bf, -0x6e5cad09aea89c15, 0x06a1a6c28867515b }, + { 0x30949a108a5bcfd4, -0x23bf228f439b8c15, -0x6d3d6b3ecf83f2e4, 0x5604a86dcbfa6e74 }, + { 0x7288d1d47c1764b6, 0x72541140e0418b51, -0x60fce59fe753092f, 0x20989e89fe2742c6 } + }, + { + { 0x1674278b85eaec2e, 0x5621dc077acb2bdf, 0x640a4c1661cbf45a, 0x730b9950f70595d3 }, + { 0x499777fd3a2dcc7f, 0x32857c2ca54fd892, -0x5d86279b2df81c60, 0x0403ed1d0ca67e29 }, + { -0x36b4d2ca78b13aae, -0x3a19373067db9073, -0x0834b905e93fca32, 0x5bd7454308303dcc } + }, + { + { -0x7a3b6cdeea1886d6, -0x39b3765d42322237, -0x62e1c257525c289e, 0x5bb7db123067f82c }, + { 0x7f9ad19528b24cc2, 0x7f6b54656335c181, 0x66b8b66e4fc07236, 0x133a78007380ad83 }, + { 0x0961f467c6ca62be, 0x04ec21d6211952ee, 0x182360779bd54770, 0x740dca6d58f0e0d2 } + }, +}, +{ + { + { 0x3906c72aed261ae5, -0x65497026771eff09, -0x0a16fa650cc9fe69, 0x0e53dc78bf2b6d47 }, + { 0x50b70bf5d3f0af0b, 0x4feaf48ae32e71f7, 0x60e84ed3a55bbd34, 0x00ed489b3f50d1ed }, + { -0x46f7d640868e7886, 0x5e4444636d17e631, 0x4d05c52e18276893, 0x27632d9a5a4a4af5 } + }, + { + { -0x567d7a2e78150025, -0x5a4b0444272f579c, -0x49a70d80fdd99c09, 0x3bbc2b22d99ce282 }, + { -0x2ee00faeab4d9f32, -0x27923c718d06ad90, 0x601fcd0d267cc138, 0x2b67916429e90ccd }, + { -0x46e836ada7c3f5a8, 0x653ff9b80fe4c6f3, -0x64f258284320c3f4, 0x43a0eeb6ab54d60e } + }, + { + { 0x3ac6322357875fe8, -0x262b0b130a043471, -0x72117b6cc7d449e0, 0x50c5eaa14c799fdc }, + { 0x396966a46d4a5487, -0x07ee5e7553d44c46, 0x66e4685b5628b26b, 0x70a477029d929b92 }, + { -0x22f12374290d04c4, 0x54c63aa79cc7b7a0, -0x51f4fcd4d37260e6, 0x6f9ce107602967fb } + }, + { + { 0x139693063520e0b5, 0x437fcf7c88ea03fe, -0x082b3bf42c36a644, 0x699154d1f893ded9 }, + { -0x52efab4e321e3dd6, -0x3b5716fdb714cd21, 0x5f3e7b33accdc0ea, 0x72364713fc79963e }, + { 0x315d5c75b4b27526, -0x33347bd2fdc9255b, 0x22f0c8a3345fee8e, 0x73975a617d39dbed } + }, + { + { 0x6f37f392f4433e46, 0x0e19b9a11f566b18, 0x220fb78a1fd1d662, 0x362a4258a381c94d }, + { -0x1bfdb2069c8a25f0, 0x78d3251a1830c870, -0x6fd4e6b79a7326e4, 0x7e18b10b29b7438a }, + { -0x6f8e26ecd49414d1, 0x0f26e9ad28418247, -0x1546e13642136da3, 0x4be65bc8f48af2de } + }, + { + { 0x1d50fba257c26234, 0x7bd4823adeb0678b, -0x3d4f239159ac750b, 0x5665eec6351da73e }, + { 0x78487feba36e7028, 0x5f3f13001dd8ce34, -0x6cb04ed2b4cf3b77, 0x056c244d397f0a2b }, + { -0x24c11ff6bc404df0, 0x4972018720800ac2, 0x26ab5d6173bd8667, 0x20b209c2ab204938 } + }, + { + { 0x1fcca94516bd3289, 0x448d65aa41420428, 0x59c3b7b216a55d62, 0x49992cc64e612cd8 }, + { 0x549e342ac07fb34b, 0x02d8220821373d93, -0x43d9d28f532e0a99, 0x7a92c9fdfbcac784 }, + { 0x65bd1bea70f801de, 0x1befb7c0fe49e28a, -0x579cf9324e4d51b6, 0x3b7ac0cd265c2a09 } + }, + { + { -0x0f2ab1b0dd12c659, -0x5d5516e1a9f7eaf6, -0x0bde4d161225178b, 0x31bc531d6b7de992 }, + { -0x7dd411bc73fe4314, 0x530cb525c0fbc73b, 0x48519034c1953fe9, 0x265cc261e09a0f5b }, + { -0x20c2ecb2567f068f, 0x7a4fb8d1221a22a7, 0x3df7d42035aad6d8, 0x2a14edcc6a1a125e } + }, +}, +{ + { + { 0x231a8c570478433c, -0x484ad8f13d7ebc63, -0x245566151c26f861, 0x2c03f5256c2b03d9 }, + { -0x20b711f8ad3031b2, -0x3c00050cf913f749, 0x05710b2ab95459c4, 0x161d25fa963ea38d }, + { 0x790f18757b53a47d, 0x307b0130cf0c5879, 0x31903d77257ef7f9, 0x699468bdbd96bbaf } + }, + { + { -0x2722c2199556e6b8, 0x485064c22fc0d2cc, -0x64b7db99cb0215d1, 0x293e1c4e6c4a2e3a }, + { -0x42e0d0b90b250131, 0x7cef0114a47fd6f7, -0x2ce00225b5b84c81, 0x525219a473905785 }, + { 0x376e134b925112e1, 0x703778b5dca15da0, -0x4fba7650b9e3ceef, 0x5b605c447f032823 } + }, + { + { 0x3be9fec6f0e7f04c, -0x7995a8618a1cb69e, 0x5542ef161e1de61a, 0x2f12fef4cc5abdd5 }, + { -0x469a7fa6df3b8377, -0x180feff36dc47034, 0x0001256502e2ef77, 0x24a76dcea8aeb3ee }, + { 0x0a4522b2dfc0c740, 0x10d06e7f40c9a407, -0x3930ebbe87300998, 0x5e607b2518a43790 } + }, + { + { -0x5fd3bce35a6930ec, -0x1c3bd2bf512c1c00, -0x2dbad97fd1f0d925, 0x201f33139e457068 }, + { 0x58b31d8f6cdf1818, 0x35cfa74fc36258a2, -0x1e4c00b09919e292, 0x5067acab6ccdd5f7 }, + { -0x02ad8094f7fc62af, 0x18b14964017c0006, -0x2addf14fd1da5b58, 0x397cba8862460375 } + }, + { + { 0x7815c3fbc81379e7, -0x599e6bdf221ed50f, -0x00563f077a57022b, 0x771b4022c1e1c252 }, + { 0x30c13093f05959b2, -0x1dc55e721656868a, 0x222fd491721d5e26, 0x2339d320766e6c3a }, + { -0x27822679aec5d059, -0x0a53648e062b30f8, -0x2f943ce4e15d7c4d, 0x331a189219971a76 } + }, + { + { 0x26512f3a9d7572af, 0x5bcbe28868074a9e, -0x7b123e3eee7f083c, 0x1ac9619ff649a67b }, + { -0x0ae990ba04b07f3a, -0x63c938219e388a31, -0x1c2b17e46fbe26e4, 0x31167c6b83bdfe21 }, + { -0x0dd4c7bdadb4ef98, 0x5068343bee9ce987, -0x03628e7bb59daf38, 0x612436341f08b111 } + }, + { + { -0x749cb61ce5d2d9c8, -0x622048ff642c02cb, 0x7f8bf1b8a3a06ba4, 0x1522aa3178d90445 }, + { -0x2662be2478b17673, 0x09fea5f16c07dc20, 0x793d2c67d00f9bbc, 0x46ebe2309e5eff40 }, + { 0x2c382f5369614938, -0x2501bf6548d292f0, -0x1737cc6e49b90dd9, 0x45fe70f50524306c } + }, + { + { 0x62f24920c8951491, 0x05f007c83f630ca2, 0x6fbb45d2f5c9d4b8, 0x16619f6db57a2245 }, + { -0x25b78a5969f3f474, 0x5b68d076ef0e2f20, 0x07fb51cf3d0b8fd4, 0x428d1623a0e392d4 }, + { 0x084f4a4401a308fd, -0x57dde63c895a3554, -0x214721b9bc2e4383, 0x1d81592d60bd38c6 } + }, +}, +{ + { + { 0x3a4a369a2f89c8a1, 0x63137a1d7c8de80d, -0x4353ff7587125feb, 0x2cb8b3a5b483b03f }, + { -0x27cc284113d5b3c8, 0x2c9162830acc20ed, -0x16c5b8556d208a7f, 0x702d67a3333c4a81 }, + { 0x36e417cbcb1b90a1, 0x33b3ddaa7f11794e, 0x3f510808885bc607, 0x24141dc0e6a8020d } + }, + { + { -0x6e6da233427cea83, 0x3ca1205322cc8094, 0x28e57f183f90d6e4, 0x1a4714cede2e767b }, + { 0x59f73c773fefee9d, -0x4c0e10763e306763, -0x1ca204bd1fd1aba1, 0x5766120b47a1b47c }, + { -0x24df45f047494801, -0x48cd3c4988aee05f, -0x56d4ae3f660fd277, 0x4f3875ad489ca5f1 } + }, + { + { 0x79ed13f6ee73eec0, -0x5a39ad9296eef44f, -0x1b76d73c79fc79f4, 0x722a1446fd7059f5 }, + { -0x380389d0b6cd54de, 0x7ac0edf72f4c3c1b, 0x5f6b55aa9aa895e8, 0x3680274dad0a0081 }, + { -0x2f6a6016573077e7, -0x2f566aaf7b8a5664, 0x6eac173320b09cc5, 0x628ecf04331b1095 } + }, + { + { -0x64be5307a38b330f, -0x498cce7ef7d9adaf, -0x6636d512ee524eb9, 0x7a47d70d34ecb40f }, + { -0x67434ee7562f2244, -0x11bb61cbf74b7fd5, -0x78f76dd947594efc, 0x685f349a45c7915d }, + { 0x60a0c4cbcc43a4f5, 0x775c66ca3677bea9, -0x5e855e8ad0070a13, 0x11ded9020e01fdc0 } + }, + { + { 0x471f95b03bea93b7, 0x0552d7d43313abd3, -0x426c8f1d1e81c085, 0x7b120f1db20e5bec }, + { -0x76f187f6351018fc, -0x78d7d6921cf17394, 0x4c5cd2a392aeb1c9, 0x194263d15771531f }, + { 0x17d2fb3d86502d7a, -0x4a9b27bbaf596cae, 0x7da962c8a60ed75d, 0x00d0f85b318736aa } + }, + { + { -0x598ac3e10289de3f, 0x69c0b4a7445671f5, -0x68e0ad8bfa4dc3ef, 0x387bc74851a8c7cd }, + { -0x6874ebd188837b03, -0x0bfd9bb8fa573f9e, -0x59852ae41819ed39, 0x2f7b459698dd6a33 }, + { -0x7e76b4b2b5ad5658, -0x5226c1ed09477cd1, 0x184d8548b61bd638, 0x3f1c62dbd6c9f6cd } + }, + { + { 0x3fad3e40148f693d, 0x052656e194eb9a72, 0x2f4dcbfd184f4e2f, 0x406f8db1c482e18b }, + { 0x2e8f1f0091910c1f, -0x5b20b01f400d1ed4, 0x60c6560aee927438, 0x6338283facefc8fa }, + { -0x619cf2d380e6e11c, 0x4fbf8301bc3ff670, 0x787d8e4e7afb73c4, 0x50d83d5be8f58fa5 } + }, + { + { -0x3f53306f4b2c4993, -0x58fa621a9e8cd1a0, 0x033d1f7870c6b0ba, 0x584161cd26d946e4 }, + { -0x7a97c6e93ee5e769, 0x2d69a4efe506d008, 0x39af1378f664bd01, 0x65942131361517c6 }, + { -0x440d4e5f8d2d835e, -0x40c6c3a6042138fc, -0x167244311d9d47e2, 0x02eebd0b3029b589 } + }, +}, +{ + { + { -0x789a4960847a3a18, 0x6ff0678bd168bab2, 0x3a70e77c1d330f9b, 0x3a5f6d51b0af8e7c }, + { 0x61368756a60dac5f, 0x17e02f6aebabdc57, 0x7f193f2d4cce0f7d, 0x20234a7789ecdcf0 }, + { 0x76d20db67178b252, 0x071c34f9d51ed160, -0x09d5b5df4c1bee90, 0x7cd682353cffe366 } + }, + { + { -0x599a329f97530b0d, 0x42d92d183cd7e3d3, 0x5759389d336025d9, 0x3ef0253b2b2cd8ff }, + { 0x0be1a45bd887fab6, 0x2a846a32ba403b6e, -0x266defed1691a000, 0x2838c8863bdc0943 }, + { -0x2e944f30b5b9afd0, -0x05b694beea3a8855, -0x7d3051750b54be63, 0x21dcb8a606a82812 } + }, + { + { -0x6572ff054188ce46, -0x7dfc9f819d61e777, -0x4d33fdc8bc0c2681, 0x5d840dbf6c6f678b }, + { 0x5c6004468c9d9fc8, 0x2540096ed42aa3cb, 0x125b4d4c12ee2f9c, 0x0bc3d08194a31dab }, + { 0x706e380d309fe18b, 0x6eb02da6b9e165c7, 0x57bbba997dae20ab, 0x3a4276232ac196dd } + }, + { + { 0x3bf8c172db447ecb, 0x5fcfc41fc6282dbd, -0x7f53003f8a55ea02, 0x0770c9e824e1a9f9 }, + { 0x4b42432c8a7084fa, -0x7675e61c20461abb, -0x4160ffde63a71ba3, 0x1ff177cea16debd1 }, + { -0x309e2665ba4a4a03, -0x79f67b16e4c586dc, -0x18cff6e6cfc1c177, 0x39f264fd41500b1e } + }, + { + { -0x2e64b55401f6841f, -0x5b92031e201fe6d7, -0x3c36f76bd3590e01, 0x65c621272c35f14e }, + { -0x5852cbe824181d64, -0x426bc895d463ec64, -0x5f16e4716ca68457, 0x1712d73468889840 }, + { -0x18d4760731ce6c23, 0x4d103356a125c0bb, 0x0419a93d2e1cfe83, 0x22f9800ab19ce272 } + }, + { + { 0x42029fdd9a6efdac, -0x46ed3141cb5ab6bf, 0x640f64b987bdf37b, 0x4171a4d38598cab4 }, + { 0x605a368a3e9ef8cb, -0x1c163fdd5aafb8eb, 0x553d48b05f24248f, 0x13f416cd647626e5 }, + { -0x05d8a7556636b374, 0x23006f6fb000b807, -0x042d6e225225ac6e, 0x508214fa574bd1ab } + }, + { + { 0x461a15bb53d003d6, -0x4defd777430c369b, 0x27c576756c683a5a, 0x3a7758a4c86cb447 }, + { -0x3dfd96eac12901b5, -0x59a598c6aee2883c, -0x3421d9b9d3eb506c, 0x22f960ec6faba74b }, + { 0x548111f693ae5076, 0x1dae21df1dfd54a6, 0x12248c90f3115e65, 0x5d9fd15f8de7f494 } + }, + { + { 0x3f244d2aeed7521e, -0x71c56fd7bcd169eb, -0x1e9b4588d163e92c, 0x3bc187fa47eb98d8 }, + { 0x031408d36d63727f, 0x6a379aefd7c7b533, -0x561e703a33511db5, 0x332f35914f8fbed3 }, + { 0x6d470115ea86c20c, -0x6675483493b92edb, -0x2887cd4ac599fe78, 0x450d81ce906fba03 } + }, +}, +{ + { + { 0x23264d66b2cae0b5, 0x7dbaed33ebca6576, 0x030ebed6f0d24ac8, 0x2a887f78f7635510 }, + { -0x0751b2d527bac6fe, 0x7018058ee8db2d1d, -0x554c66a0382d3ee2, 0x53b16d2324ccca79 }, + { 0x2a23b9e75c012d4f, 0x0c974651cae1f2ea, 0x2fb63273675d70ca, 0x0ba7250b864403f5 } + }, + { + { -0x229ca76c79079264, 0x61699176e13a85a4, 0x2e5111954eaa7d57, 0x32c21b57fb60bdfb }, + { -0x44f2e702fd639bdf, -0x43d2ebde76d670fe, -0x7cb8071974daf16a, 0x7b9f2fe8032d71c9 }, + { -0x2787dc32ce61f880, -0x103b303e76888a3b, 0x4854fb129a0ab3f7, 0x12c49d417238c371 } + }, + { + { 0x09b3a01783799542, 0x626dd08faad5ee3f, -0x45ff4311148feb61, 0x1421b246a0a444c9 }, + { 0x0950b533ffe83769, 0x21861c1d8e1d6bd1, -0x0fdd27c7ecfd1af0, 0x2509200c6391cab4 }, + { 0x4aa43a8e8c24a7c7, 0x04c1f540d8f05ef5, -0x5245a1f3f4c14624, 0x2ab5504448a49ce3 } + }, + { + { -0x23f8539ce3a2c506, 0x58615171f9df8c6c, 0x72a079d89d73e2b0, 0x7301f4ceb4eae15d }, + { 0x2ed227266f0f5dec, -0x67db11bea12af7dc, -0x7f8413836b972beb, 0x7093bae1b521e23f }, + { 0x6409e759d6722c41, -0x598b1e308d408d65, -0x43f5db14c3de1a97, 0x390167d24ebacb23 } + }, + { + { -0x2844fab45d0dedf5, -0x1d4631514efa7649, 0x3fe8bac8f3c0edbe, 0x4cbd40767112cb69 }, + { 0x27f58e3bba353f1c, 0x4c47764dbf6a4361, -0x50443b1a91a9d9b0, 0x07db2ee6aae1a45d }, + { 0x0b603cc029c58176, 0x5988e3825cb15d61, 0x2bb61413dcf0ad8d, 0x7b8eec6c74183287 } + }, + { + { 0x32fee570fc386b73, -0x2574febe25c57339, -0x68a002f537697ca7, 0x6ee809a1b132a855 }, + { -0x1b35bf87d32d8350, -0x25063cdc04169843, -0x4d642cb5752be162, 0x72810497626ede4d }, + { -0x6bbb44ce030279c6, 0x2fe3690a3e4e48c5, -0x23d637982f7705db, 0x13bd1e38d173292e } + }, + { + { 0x223fb5cf1dfac521, 0x325c25316f554450, 0x030b98d7659177ac, 0x1ed018b64f88a4bd }, + { -0x2cd4b327969eb64b, -0x1aa6c8287e275549, 0x0bcb2127ae122b94, 0x41e86fcfb14099b0 }, + { 0x3630dfa1b802a6b0, -0x77f078b8bd52c42b, 0x0af90d6ceec5a4d4, 0x746a247a37cdc5d9 } + }, + { + { 0x6eccd85278d941ed, 0x2254ae83d22f7843, -0x3add2fd184403249, 0x681e3351bff0e4e2 }, + { -0x2ace4742d484650a, 0x5005093537fc5b51, 0x232fcf25c593546d, 0x20a365142bb40f49 }, + { -0x749b4a627cfcb0bb, 0x2f8b71f21fa20efb, 0x69249495ba6550e4, 0x539ef98e45d5472b } + }, +}, +{ + { + { -0x2f8b2769e3518bc1, -0x0792e70a11e39c13, -0x68423aa4180b12d7, 0x4cbad279663ab108 }, + { 0x6e7bb6a1a6205275, -0x55b0de28bec3717d, 0x6f56d155e88f5cb2, 0x2de25d4ba6345be1 }, + { -0x7f2e6fdb5f28e033, -0x3ada3df504d77508, -0x4e5c68b4a0c59be7, 0x7d7fbcefe2007233 } + }, + { + { -0x3283a23a0c3d6f6c, -0x387e5d65d56efa55, -0x7f39e2c9bde3cfa8, 0x4f9cd196dcd8d4d7 }, + { -0x0510e195d994d7ff, -0x7993973b2a8c60ea, -0x0975d043e4fc89d4, 0x5975435e87b75a8d }, + { 0x199297d86a7b3768, -0x2f2fa7dbe52e859d, -0x45fd6352a3e3f3e9, 0x7ccdd084387a0307 } + }, + { + { -0x64f37be7989f336d, -0x3251ff85e54cd567, -0x577213799df425e8, 0x3593ca848190ca44 }, + { -0x2359bdd392d9fbe9, -0x51eac2af6b7dbf43, -0x563f3e4b04973989, 0x428bd0ed61d0cf53 }, + { -0x6dece765a17b6559, -0x2b273cca9a270533, -0x73adaba4ac02442f, 0x27398308da2d63e6 } + }, + { + { -0x465ef1b3f58fdbad, 0x0fa25866d57d1bde, -0x0046264a32d82509, 0x572c2945492c33fd }, + { 0x42c38d28435ed413, -0x42af0c9fcd873337, -0x44f854e58625fc11, 0x269597aebe8c3355 }, + { -0x388038ba2932cf42, -0x1b20172c1c455105, -0x5dd377cf55a225f4, 0x7f985498c05bca80 } + }, + { + { -0x2ca9eaadf0409c9d, 0x08045a45cf4dfba6, -0x113db04378c05f3e, 0x30f2653cd69b12e7 }, + { 0x3849ce889f0be117, -0x7ffa52e484ab5d78, 0x3da3c39f23fc921c, 0x76c2ec470a31f304 }, + { -0x75f736c7553ef37b, 0x46179b60db276bcb, -0x56df3fe1f1905390, 0x2f1273f1596473da } + }, + { + { 0x30488bd755a70bc0, 0x06d6b5a4f1d442e7, -0x152e596143a69e9e, 0x38ac1997edc5f784 }, + { 0x4739fc7c8ae01e11, -0x02ad8b6fb5955461, 0x41d98a8287728f2e, 0x5d9e572ad85b69f2 }, + { 0x0666b517a751b13b, 0x747d06867e9b858c, -0x53533feebab221b7, 0x22dfcd9cbfe9e69c } + }, + { + { 0x56ec59b4103be0a1, 0x2ee3baecd259f969, 0x797cb29413f5cd32, 0x0fe9877824cde472 }, + { -0x72242d1f3cf2f327, -0x527199a05344bccd, -0x7094da73cdd569e1, 0x6b2916c05448c1c7 }, + { 0x7edb34d10aba913b, 0x4ea3cd822e6dac0e, 0x66083dff6578f815, 0x4c303f307ff00a17 } + }, + { + { 0x29fc03580dd94500, -0x132d855b9044136d, 0x130a155fc2e2a7f8, 0x416b151ab706a1d5 }, + { -0x2cf5c429e84d737b, -0x3a2c8848c688c416, -0x39391873e195a341, 0x0d61b8f78b2ab7c4 }, + { 0x56a8d7efe9c136b0, -0x42f81a32a71bb4e0, -0x5019d025e4a81f55, 0x191a2af74277e8d2 } + }, +}, +{ + { + { 0x09d4b60b2fe09a14, -0x3c7b0f50244e8b82, 0x58e2ea8978b5fd6e, 0x519ef577b5e09b0a }, + { -0x2aaff6a45490b67b, 0x04f4cd5b4fbfaf1a, -0x6271d12ed5f38ac0, 0x2bc24e04b2212286 }, + { 0x1863d7d91124cca9, 0x7ac08145b88a708e, 0x2bcd7309857031f5, 0x62337a6e8ab8fae5 } + }, + { + { -0x2e54cdb1e4c5ed8d, 0x18947cf181055340, 0x3b5d9567a98c196e, 0x7fa00425802e1e68 }, + { 0x4bcef17f06ffca16, -0x21f91e2496d51e96, 0x0753702d614f42b0, 0x5f6041b45b9212d0 }, + { 0x7d531574028c2705, -0x7fce829624f28a02, 0x30fface8ef8c8ddd, 0x7e9de97bb6c3e998 } + }, + { + { -0x0ffb419d5db2bf23, -0x45f9a66efbad2be1, -0x7e3ba11e9d5bbdcc, 0x4cb829d8a22266ef }, + { 0x1558967b9e6585a3, -0x6836631f6716746e, 0x10af149b6eb3adad, 0x42181fe8f4d38cfa }, + { 0x1dbcaa8407b86681, 0x081f001e8b26753b, 0x3cd7ce6a84048e81, 0x78af11633f25f22c } + }, + { + { 0x3241c00e7d65318c, -0x19411a232f179219, 0x118b2dc2fbc08c26, 0x680d04a7fc603dc3 }, + { -0x7be9142bf4af4544, 0x1508722628208bee, -0x5ceb7050463e3c93, 0x0d07daacd32d7d5d }, + { -0x063dbeb596a55c15, -0x255bd3b3fa5970df, 0x7c6c23987f93963e, 0x210e8cd30c3954e3 } + }, + { + { 0x2b50f16137fe6c26, -0x1efd4327a91bfb28, 0x12b0f1414c561f6b, 0x51b17bc8d028ec91 }, + { -0x53bdfe0def58e3fa, 0x6a65e0aef3bfb021, -0x43bd3ca3c6c9cd09, 0x56ea8db1865f0742 }, + { -0x000a04b430acaee7, -0x0b67628620eef760, -0x4203159a65c45cdb, 0x18a11f1174d1a6f2 } + }, + { + { -0x0429c3252d85a0d4, -0x0ff03b43755ef929, 0x53fb5c1a8e64a430, 0x04eaabe50c1a2e85 }, + { 0x407375ab3f6bba29, -0x613c492766e1b7d2, -0x6637f17d1aa06d17, 0x307c13b6fb0c0ae1 }, + { 0x24751021cb8ab5e7, -0x03dcbbb6a3afef15, 0x5f1e717b4e5610a1, 0x44da5f18c2710cd5 } + }, + { + { -0x6ea9019476271534, -0x19486bae1dced95f, -0x428b9c26c6bb14b2, 0x726373f6767203ae }, + { 0x033cc55ff1b82eb5, -0x4ea51c92bee351ae, -0x45bf49e67004532d, 0x768edce1532e861f }, + { -0x1cfa358d14810976, 0x662cf31f70eadb23, 0x18f026fdb4c45b68, 0x513b5384b5d2ecbd } + }, + { + { 0x5e2702878af34ceb, -0x6ff4fbf646b92952, 0x6512ebf7dabd8512, 0x61d9b76988258f81 }, + { 0x46d46280c729989e, 0x4b93fbd05368a5dd, 0x63df3f81d1765a89, 0x34cebd64b9a0a223 }, + { -0x593a58ecb64826b5, -0x5c0c2ea7dc146bba, 0x0416fbd277484834, 0x69d45e6f2c70812f } + }, +}, +{ + { + { -0x6019d4bcb0b9f105, -0x212cfc2b59c9f82a, -0x0faddef1485f25dc, 0x237e7dbe00545b93 }, + { -0x31e908b43ac3ebcf, 0x2b9725ce2072edde, -0x47463c904a4dc119, 0x7e2e0e450b5cc908 }, + { 0x013575ed6701b430, 0x231094e69f0bfd10, 0x75320f1583e47f22, 0x71afa699b11155e3 } + }, + { + { -0x15bdc3e3b8c4af2a, 0x51e87a1f3b38ef10, -0x647b40a04d36416b, 0x00731fbc78f89a1c }, + { 0x65ce6f9b3953b61d, -0x39a7c615505ebe1a, 0x0f435ffda9f759fe, 0x021142e9c2b1c28e }, + { -0x1bcf38e7b707e780, -0x4069f3dda1313ee7, -0x49251f7c9445ea1d, 0x4c4d6f3347e15808 } + }, + { + { 0x2f0cddfc988f1970, 0x6b916227b0b9f51b, 0x6ec7b6c4779176be, 0x38bf9500a88f9fa8 }, + { 0x18f7eccfc17d1fc9, 0x6c75f5a651403c14, -0x24218ed40811f321, 0x193fddaaa7e47a22 }, + { 0x1fd2c93c37e8876f, -0x5d09e1a5e72eb9d4, 0x5080f58239241276, 0x6a6fb99ebf0d4969 } + }, + { + { -0x114edd4a491bdc3a, -0x6c628fef0d790072, -0x6f56d57ce230a274, 0x136fda9f42c5eb10 }, + { 0x6a46c1bb560855eb, 0x2416bb38f893f09d, -0x28e2eec8708e533f, 0x75f76914a31896ea }, + { -0x06b3204e5cfa422f, 0x0f364b9d9ff82c08, 0x2a87d8a5c3bb588a, 0x022183510be8dcba } + }, + { + { -0x62a58efebccf8581, -0x4f9c21613b825ba1, 0x22bbfe52be927ad3, 0x1387c441fd40426c }, + { 0x4af766385ead2d14, -0x5f71277f3583a7d0, 0x0d13a6e610211e3d, 0x6a071ce17b806c03 }, + { -0x4a2c3c2e78687508, 0x722b5a3d7f0e4413, 0x0d7b4848bb477ca0, 0x3171b26aaf1edc92 } + }, + { + { -0x59f248274d75b82f, -0x5940eb29e88f5b0f, -0x2b5e076cac2242a8, 0x6c514a63344243e9 }, + { -0x56d0ce6f68a9b358, -0x008447b3dd8a1ee7, 0x4f55fe37a4875150, 0x221fd4873cf0835a }, + { 0x2322204f3a156341, -0x048c1f1645f5fcd3, -0x031f22b3bef0fcf2, 0x48daa596fb924aaa } + }, + { + { 0x14f61d5dc84c9793, -0x66be061c10be7dfa, -0x320a4770cb9d8854, 0x58c837fa0e8a79a9 }, + { 0x6eca8e665ca59cc7, -0x57b8dab4d1c75360, 0x31afc708d21e17ce, 0x676dd6fccad84af7 }, + { 0x0cf9688596fc9058, 0x1ddcbbf37b56a01b, -0x233d1882b6ca2996, 0x1c4f73f2c6a57f0a } + }, + { + { -0x4c918f910383cb7c, 0x73dfc9b4c3c1cf61, -0x14e2863687e3381b, 0x70459adb7daf675c }, + { 0x0e7a4fbd305fa0bb, -0x7d62b31fab399c53, -0x0bde3c7cd01cc7b8, 0x795ac80d1bf64c42 }, + { 0x1b91db4991b42bb3, 0x572696234b02dcca, -0x6020611ae0738724, 0x5fe162848ce21fd3 } + }, +}, +{ + { + { 0x315c29c795115389, -0x281f1af879d08b32, 0x0c4a762185927432, 0x72de6c984a25a1e4 }, + { -0x1d86f551b2f883bf, -0x746c7d8f248b965d, 0x6eb632dc8abd16a2, 0x720814ecaa064b72 }, + { -0x51654aac40955cf0, 0x050a50a9806d6e1b, -0x6d448bfc5200aec7, 0x0394d27645be618b } + }, + { + { -0x0ac69bda4dcaba5c, 0x15a7a27e98fbb296, -0x5493ad439c90227a, 0x79d995a8419334ee }, + { 0x4d572251857eedf4, -0x1c8db1221e616c3b, -0x758ebdf1f4868fcb, 0x3b3c833687abe743 }, + { -0x32757159ee6a228b, -0x5afb2757e22657d1, 0x540dca81a35879b6, 0x60dd16a379c86a8a } + }, + { + { 0x3501d6f8153e47b8, -0x485698abeb5d09f4, 0x112ee8b6455d9523, 0x4e62a3c18112ea8a }, + { 0x35a2c8487381e559, 0x596ffea6d78082cb, -0x34688e14245849ad, 0x5a08b5019b4da685 }, + { -0x372b53fbae95487a, 0x595af3215295b23d, -0x29122dcb24fdcf3f, 0x0929efe8825b41cc } + }, + { + { -0x74ce8d4852a99ae3, 0x01581b7a3fabd717, 0x2dc94df6424df6e4, 0x30376e5d2c29284f }, + { 0x5f0601d1cbd0f2d3, 0x736e412f6132bb7f, -0x7c9fbbcddc722179, 0x1e3a5272f5c0753c }, + { -0x2d6e72587ea65a64, 0x6bdc1cd93f0713f3, 0x565f7a934acd6590, 0x53daacec4cb4c128 } + }, + { + { -0x667ad43c7ad30250, 0x2cc12e9559d6ed0b, 0x70f9e2bf9b5ac27b, 0x4f3b8c117959ae99 }, + { 0x4ca73bd79cc8a7d6, 0x4d4a738f47e9a9b2, -0x0b340ed6bd0a0200, 0x01a13ff9bdbf0752 }, + { 0x55b6c9c82ff26412, 0x1ac4a8c91fb667a8, -0x2ad840301488740e, 0x303337da7012a3be } + }, + { + { -0x6892c334052d022f, -0x34777c68c859bf58, 0x2ff00c1d6734cb25, 0x269ff4dc789c2d2b }, + { -0x6aabdddd73e36284, 0x01fac1371a9b340f, 0x7e8d9177925b48d7, 0x53f8ad5661b3e31b }, + { 0x0c003fbdc08d678d, 0x4d982fa37ead2b17, -0x3f8194324d1a7d0f, 0x296c7291df412a44 } + }, + { + { -0x204dcdfa25474a62, 0x465aeaa0c8092250, -0x2ecc3ee7658da2e8, 0x2327370261f117d1 }, + { 0x7903de2b33daf397, -0x2f00f9e63659db4d, -0x75e2dad4aaa4c1e8, 0x2b6d581c52e0b7c0 }, + { 0x3d0543d3623e7986, 0x679414c2c278a354, -0x51bc0f338d9e690a, 0x7836c41f8245eaba } + }, + { + { -0x359ae17b7fee6c84, -0x394f3b91910be5d8, -0x48fde458a0c072ae, 0x119dff99ead7b9fd }, + { -0x185dab24b616a57f, 0x5192d5d008b0ad73, 0x4d20e5b1d00afc07, 0x5d55f8012cf25f38 }, + { 0x43eadfcbf4b31d4d, -0x39afc08beeeb776e, -0x0111973af9f2c4e9, 0x329293b3dd4a0ac8 } + }, +}, +{ + { + { 0x2879852d5d7cb208, -0x4721228f97820d19, -0x23f40054de97876f, 0x2b44c043677daa35 }, + { 0x4e59214fe194961a, 0x49be7dc70d71cd4f, -0x6cff302dc4af0dd3, 0x4789d446fc917232 }, + { 0x1a1c87ab074eb78e, -0x05392e7166250b99, 0x3eacbbcd484f9067, 0x60c52eef2bb9a4e4 } + }, + { + { 0x702bc5c27cae6d11, 0x44c7699b54a48cab, -0x1043bfa945b6d14e, 0x70d77248d9b6676d }, + { 0x0b5d89bc3bfd8bf1, -0x4f946dc8360caae6, 0x0e4c16b0d53028f5, 0x10bc9c312ccfcaab }, + { -0x557517b4c13d5fa5, -0x6796610b12e87e20, 0x794513e4708e85d1, 0x63755bd3a976f413 } + }, + { + { 0x3dc7101897f1acb7, 0x5dda7d5ec165bbd8, 0x508e5b9c0fa1020f, 0x2763751737c52a56 }, + { -0x4aa05fc1d52ef7ad, 0x356f75909ee63569, -0x60060e0241964770, 0x0d8cc1c48bc16f84 }, + { 0x029402d36eb419a9, -0x0f4bb181884b9f5b, -0x30579dcf2bc3b6aa, 0x70c2dd8a7ad166e7 } + }, + { + { -0x6e2b6982471281ed, 0x74252f0ad776817a, -0x1bf67d1ff27ada9c, 0x32b8613816a53ce5 }, + { 0x656194509f6fec0e, -0x11d18156b939ae73, -0x68cc3e0c981f64a4, 0x2e0fac6363948495 }, + { 0x79e7f7bee448cd64, 0x6ac83a67087886d0, -0x07602b265f1b24d2, 0x4179215c735a4f41 } + }, + { + { -0x1b51cc46d79432cc, -0x48108149aa622924, 0x278b141fb3d38e1f, 0x31fa85662241c286 }, + { -0x738f6b18282312d6, -0x6804753cb82c6390, -0x1ec41fcc56f926fe, 0x700344a30cd99d76 }, + { -0x507d93bdd1c9dd0c, -0x3edfd67867ccafd3, -0x643e481ed4c76edd, 0x24bb2312a9952489 } + }, + { + { 0x41f80c2af5f85c6b, 0x687284c304fa6794, -0x76ba20665c45e453, 0x0d1d2af9ffeb5d16 }, + { -0x4e5712e8cd21983d, 0x3cb49418461b4948, -0x7142bcbc8930432e, 0x0fee3e871e188008 }, + { -0x5625755ecd9de121, 0x30b822a159226579, 0x4004197ba79ac193, 0x16acd79718531d76 } + }, + { + { -0x36a6393a87784953, -0x6b1e6152a06f0146, 0x16e24e62a342f504, 0x164ed34b18161700 }, + { 0x72df72af2d9b1d3d, 0x63462a36a432245a, 0x3ecea07916b39637, 0x123e0ef6b9302309 }, + { 0x487ed94c192fe69a, 0x61ae2cea3a911513, -0x7884092c465b21d9, 0x78da0fc61073f3eb } + }, + { + { -0x5d607f0e97f3c56c, 0x71f77e151ae9e7e6, 0x1100f15848017973, 0x054aa4b316b38ddd }, + { 0x5bf15d28e52bc66a, 0x2c47e31870f01a8e, 0x2419afbc06c28bdd, 0x2d25deeb256b173a }, + { -0x2037b972e6d98348, 0x0b28789c66e54daf, 0x2aeb1d2a666eec17, 0x134610a6ab7da760 } + }, +}, +{ + { + { -0x26ebcf1f23fd73c4, 0x0eb955a85217c771, 0x4b09e1ed2c99a1fa, 0x42881af2bd6a743c }, + { -0x350aa13d83a64dc1, -0x665112c1eab2fb0e, 0x68441d72e14141f4, 0x140345133932a0a2 }, + { 0x7bfec69aab5cad3d, -0x3dc1732cb34d3053, 0x685dd14bfb37d6a2, 0x0ad6d64415677a18 } + }, + { + { 0x7914892847927e9f, 0x33dad6ef370aa877, 0x1f8f24fa11122703, 0x5265ac2f2adf9592 }, + { 0x781a439e417becb5, 0x4ac5938cd10e0266, 0x5da385110692ac24, 0x11b065a2ade31233 }, + { 0x405fdd309afcb346, -0x268dc2bbd719c0ac, -0x6b3fe20fa09a5552, 0x43e4dc3ae14c0809 } + }, + { + { -0x1590853c523d395d, -0x2f16d709168e836c, -0x1d2c861529ba150b, 0x46dd8785c51ffbbe }, + { -0x43ed380e56c75ae9, 0x473028ab3180b2e1, 0x3f78571efbcd254a, 0x74e534426ff6f90f }, + { 0x709801be375c8898, 0x4b06dab5e3fd8348, 0x75880ced27230714, 0x2b09468fdd2f4c42 } + }, + { + { 0x5b97946582ffa02a, -0x25f695ae01570ab7, -0x5f9caec8a0885065, 0x1bcfde61201d1e76 }, + { -0x6838b61148fe346a, -0x7c0bc72b495c963d, 0x62962b8b9a402cd9, 0x6976c7509888df7b }, + { 0x4a4a5490246a59a2, -0x29c1422117802270, -0x26bc8398f2dc8e06, 0x69e87308d30f8ed6 } + }, + { + { 0x0f80bf028bc80303, 0x6aae16b37a18cefb, -0x22b815b828d3295d, 0x61943588f4ed39aa }, + { 0x435a8bb15656beb0, -0x07053645b0b2a436, -0x464d873beab73f8b, 0x3eb0ef76e892b622 }, + { -0x2d91a3c16efc607b, -0x3f161882090cc557, -0x176973aa8ff9956d, 0x3c34d1881faaaddd } + }, + { + { -0x42a4f470d0001f27, 0x6aa254103ed24fb9, 0x2ac7d7bcb26821c4, 0x605b394b60dca36a }, + { 0x3f9d2b5ea09f9ec0, 0x1dab3b6fb623a890, -0x5f645c158d26d93c, 0x374193513fd8b36d }, + { -0x4b17a91ba562e12e, -0x1017b7899368565e, -0x4efb309be1a11183, 0x2f50b81c88a71c8f } + }, + { + { 0x2b552ca0a7da522a, 0x3230b336449b0250, -0x0d3b3a435b466047, 0x7b2c674958074a22 }, + { 0x31723c61fc6811bb, -0x634bafb79dee7ff1, 0x768933d347995753, 0x3491a53502752fcd }, + { -0x2aae9a77c12d7321, 0x12d84fd2d362de39, 0x0a874ad3e3378e4f, 0x000d2b1f7c763e74 } + }, + { + { -0x69db8873c16b5755, 0x0ad6f3cee9a78bec, -0x6b75387ef28bc3b1, 0x76627935aaecfccc }, + { 0x3d420811d06d4a67, -0x4103fb7a6f1f001d, -0x078f394842b78422, 0x6e2a7316319afa28 }, + { 0x56a8ac24d6d59a9f, -0x37248ac1cf690ffa, 0x477f41e68f4c5299, 0x588d851cf6c86114 } + }, +}, +{ + { + { -0x32d59a18882e0aeb, 0x548991878faa60f1, -0x4e48c4432543f91b, 0x654878cba97cc9fb }, + { 0x51138ec78df6b0fe, 0x5397da89e575f51b, 0x09207a1d717af1b9, 0x2102fdba2b20d650 }, + { -0x69611bfafaa3195f, 0x36bca7681251ad29, 0x3a1af517aa7da415, 0x0ad725db29ecb2ba } + }, + { + { -0x013843f364fa907b, 0x537d5268e7f5ffd7, 0x77afc6624312aefa, 0x4f675f5302399fd9 }, + { -0x23bd984e7cb1dba9, -0x498abb4a8f31e43b, 0x1af07a0bf7d15ed7, 0x4aefcffb71a03650 }, + { -0x3cd2c9c9fbeae8e2, -0x32d410ee7667b7c5, -0x78f591522f6baef0, 0x0bccbb72a2a86561 } + }, + { + { 0x186d5e4c50fe1296, -0x1fc6847d01176082, 0x3bc7f6c5507031b0, 0x6678fd69108f37c2 }, + { 0x185e962feab1a9c8, -0x791819ca9aeb8233, -0x4f6d1fce44a4920e, 0x4024f0ab59d6b73e }, + { 0x1586fa31636863c2, 0x07f68c48572d33f2, 0x4f73cc9f789eaefc, 0x2d42e2108ead4701 } + }, + { + { 0x21717b0d0f537593, -0x6eb196f4ece1f9b4, 0x1bb687ae752ae09f, 0x420bf3a79b423c6e }, + { -0x680aecea6b202d65, 0x6155985d313f4c6a, -0x145ec0f8f7baaff0, 0x676b2608b8d2d322 }, + { -0x7ec7459ae3a4d4b9, -0x798e4913cee4e480, 0x7bff0cb1bc3135b0, 0x745d2ffa9c0cf1e0 } + }, + { + { 0x6036df5721d34e6a, -0x4e2477d866844c30, -0x2c3df63c378a9506, 0x06e15be54c1dc839 }, + { -0x40ada5e1d4363743, -0x15a4d9f7d9b8627f, -0x2aee38f120feaa25, 0x1ae23ceb960cf5d0 }, + { 0x5b725d871932994a, 0x32351cb5ceb1dab0, 0x7dc41549dab7ca05, 0x58ded861278ec1f7 } + }, + { + { 0x2dfb5ba8b6c2c9a8, 0x48eeef8ef52c598c, 0x33809107f12d1573, 0x08ba696b531d5bd8 }, + { -0x27e8c86c0d993aa4, -0x3736893a33bab1b7, 0x5ce382f8bc26c3a8, 0x2ff39de85485f6f9 }, + { 0x77ed3eeec3efc57a, 0x04e05517d4ff4811, -0x15c285c00e598e35, 0x120633b4947cfe54 } + }, + { + { -0x7d42ceb8b6edeff6, -0x21dc8492819041fa, -0x1ee189e6ee15863a, 0x07433be3cb393bde }, + { 0x0b94987891610042, 0x4ee7b13cecebfae8, 0x70be739594f0a4c0, 0x35d30a99b4d59185 }, + { -0x0086bb3fa316680c, 0x575d3de4b05c51a3, 0x583381fd5a76847c, 0x2d873ede7af6da9f } + }, + { + { -0x559dfd1eb1a2067f, -0x5df2a6e8afea1e0b, 0x18a275d3bae21d6c, 0x0543618a01600253 }, + { 0x157a316443373409, -0x054748110b557e27, -0x4f6c01190a59b7fa, 0x2e773654707fa7b6 }, + { 0x0deabdf4974c23c1, -0x5590f5da6231b96d, 0x04202cb8a29aba2c, 0x4b1443362d07960d } + }, +}, +{ + { + { 0x299b1c3f57c5715e, -0x69346d6194979270, 0x3004806447235ab3, 0x2c435c24a44d9fe1 }, + { 0x47b837f753242cec, 0x256dc48cc04212f2, -0x1ddd04041e26d73b, 0x48ea295bad8a2c07 }, + { 0x0607c97c80f8833f, 0x0e851578ca25ec5b, 0x54f7450b161ebb6f, 0x7bcb4792a0def80e } + }, + { + { 0x1cecd0a0045224c2, 0x757f1b1b69e53952, 0x775b7a925289f681, 0x1b6cc62016736148 }, + { -0x7b781c2fd438c9a7, 0x4baf8445059979df, -0x2e8368a523529041, 0x57369f0bdefc96b6 }, + { -0x0e5666fe8a9c7968, 0x353dd1beeeaa60d3, -0x7b6b8eccb3645b78, 0x63fa6e6843ade311 } + }, + { + { 0x2195becdd24b5eb7, 0x5e41f18cc0cd44f9, -0x20d7f8bbbe356122, 0x07073b98f35b7d67 }, + { -0x2ea3dfac9a683e98, -0x608c8bff672d7877, 0x18aee7f13257ba1f, 0x3418bfda07346f14 }, + { -0x2fc39893b31acf2c, 0x0b64c0473b5df9f4, 0x065cef8b19b3a31e, 0x3084d661533102c9 } + }, + { + { -0x6593178989fcde03, 0x7fe2b5109eb63ad8, 0x00e7d4ae8ac80592, 0x73d86b7abb6f723a }, + { -0x1e094861407b9653, 0x15801004e2663135, -0x65b67ccf508be7e5, 0x3ba2504f049b673c }, + { 0x0b52b5606dba5ab6, -0x56ecb0f0444e1255, 0x30a9520d9b04a635, 0x6813b8f37973e5db } + }, + { + { -0x0e6b35a90cea81d7, 0x136d35705ef528a5, -0x22b3108874fa6644, 0x7d5472af24f833ed }, + { -0x67ab4fabccbed83f, 0x105d047882fbff25, -0x24b60806bbe790b1, 0x1768e838bed0b900 }, + { -0x2f1078b250cc25b9, 0x00d3be5db6e339f9, 0x3f2a8a2f9c9ceece, 0x5d1aeb792352435a } + }, + { + { 0x12c7bfaeb61ba775, -0x47b19de01d9c4003, 0x0b47a5c35c840dcf, 0x7e83be0bccaf8634 }, + { -0x0a61944ce6329c36, 0x670c159221d06839, -0x4f92a9a4deaf354a, 0x20fb199d104f12a3 }, + { 0x61943dee6d99c120, -0x79efe0d1b9f46020, 0x6bb2f1518ee8598d, 0x76b76289fcc475cc } + }, + { + { 0x4245f1a1522ec0b3, 0x558785b22a75656d, 0x1d485a2548a1b3c0, 0x60959eccd58fe09f }, + { 0x791b4cc1756286fa, -0x24312ce828b5ea84, 0x7e732421ea72bde6, 0x01fe18491131c8e9 }, + { 0x3ebfeb7ba8ed7a09, 0x49fdc2bbe502789c, 0x44ebce5d3c119428, 0x35e1eb55be947f4a } + }, + { + { 0x14fd6dfa726ccc74, 0x3b084cfe2f53b965, -0x0cc51b0aad5d374c, 0x59aab07a0d40166a }, + { -0x242518fe3a8c722d, -0x063909ca4d90e412, 0x61e96a8042f15ef4, 0x3aa1d11faf60a4d8 }, + { 0x77bcec4c925eac25, 0x1848718460137738, 0x5b374337fea9f451, 0x1865e78ec8e6aa46 } + }, +}, +{ + { + { -0x6983ab16e3ad6335, 0x30f6269264c635fb, 0x2747aff478121965, 0x17038418eaf66f5c }, + { -0x333b48384991e086, 0x44157e25f50c2f7e, 0x3ef06dfc713eaf1c, 0x582f446752da63f7 }, + { -0x39ce842cdfcdb31c, -0x57efbd175bb7743c, -0x4de10e74b1a5ec9c, 0x0c2a1c4bcda28dc9 } + }, + { + { -0x123b7eb7964296bb, 0x0d6d907dbe1c8d22, -0x39c42ded2aa33a55, 0x5a6a9b30a314dc83 }, + { -0x2db2382f90e0fbb9, -0x4dd961c124783fa7, -0x2ea4fd8d044d2d71, 0x7c558bd1c6f64877 }, + { -0x2f13eadb2c69b9c3, 0x12bb628ac35a24f0, -0x5af3c586e343a05c, 0x0404a5ca0afbafc3 } + }, + { + { 0x62bc9e1b2a416fd1, -0x4a3908d71cafa675, 0x04343fd83d5d6967, 0x39527516e7f8ee98 }, + { -0x73e0bff8f558bc2a, -0x33452f34a4d9a118, 0x574b046b668fd2de, 0x46395bfdcadd9633 }, + { 0x117fdb2d1a5d9a9c, -0x6388ba432effa3d6, -0x102b410eab2a9016, 0x76579a29e822d016 } + }, + { + { 0x333cb51352b434f2, -0x27cdd7b66c217f1f, -0x4aaed7788af2ca32, 0x02c514bb2a2777c1 }, + { 0x45b68e7e49c02a17, 0x23cd51a2bca9a37f, 0x3ed65f11ec224c1b, 0x43a384dc9e05bdb1 }, + { 0x684bd5da8bf1b645, -0x04742c81094ab4ad, 0x313916d7a9b0d253, 0x1160920961548059 } + }, + { + { 0x7a385616369b4dcd, 0x75c02ca7655c3563, 0x7dc21bf9d4f18021, 0x2f637d7491e6e042 }, + { -0x4bb2e996d6253056, -0x25ad60b37beca671, -0x16109c35bac2aaa7, 0x351e125bc5698e0b }, + { -0x2b4b64b9e5098442, -0x29fcfc853754769f, 0x71dee19ff9a699fb, 0x7f182d06e7ce2a9a } + }, + { + { 0x09454b728e217522, -0x55a7170b2b7b4728, -0x2ca7dab280b96fc4, 0x44acc043241c5217 }, + { 0x7a7c8e64ab0168ec, -0x34a5b5aaea123abd, 0x095519d347cd0eda, 0x67d4ac8c343e93b0 }, + { 0x1c7d6bbb4f7a5777, -0x74ca012b6e7cec1f, 0x4adca1c6c96b4684, 0x556d1c8312ad71bd } + }, + { + { -0x7e0f98a94ee417df, 0x0faff82310a3f3dd, -0x074d2faa9566b9a3, 0x097abe38cc8c7f05 }, + { 0x17ef40e30c8d3982, 0x31f7073e15a3fa34, 0x4f21f3cb0773646e, 0x746c6c6d1d824eff }, + { 0x0c49c9877ea52da4, 0x4c4369559bdc1d43, 0x022c3809f7ccebd2, 0x577e14a34bee84bd } + }, + { + { -0x6b01314142b228d5, -0x0b95b025f9f0ddef, 0x124a5977c0c8d1ff, 0x705304b8fb009295 }, + { -0x0f1d97539e58c4f6, -0x0d0505efc86e5a0b, -0x3e1ec17d9492ff17, 0x60fa7ee96fd78f42 }, + { -0x49c2e2cab2d6913a, -0x0c3cfac1a052ce28, 0x670b958cb4bd42ec, 0x21398e0ca16353fd } + }, +}, +{ + { + { -0x793a03e979e48166, -0x095ccfb895d83baf, 0x01667267a1e93597, 0x05ffb9cd6082dfeb }, + { 0x216ab2ca8da7d2ef, 0x366ad9dd99f42827, -0x519b46ffb022c38b, 0x403a395b53909e62 }, + { -0x59e805600ac09ec7, 0x60f2b5e513e66cb6, -0x285741104cbb755c, 0x7a2932856f5ea192 } + }, + { + { -0x4763bbb7869c6cfe, 0x4ae4f19350c67f2c, -0x0f4ca25737e5063a, 0x39d0003546871017 }, + { 0x0b39d761b02de888, 0x5f550e7ed2414e1f, -0x59405ba7dd1e56c0, 0x050a2f7dfd447b99 }, + { 0x437c3b33a650db77, 0x6bafe81dbac52bb2, -0x0166bfd2d2482ce8, 0x2b5b7eec372ba6ce } + }, + { + { -0x596bbfb29ec5370c, 0x500c3c2bfa97e72c, -0x78befb2de0313df0, 0x1b205fb38604a8ee }, + { -0x4c43b4427c0af111, 0x508f0c998c927866, 0x43e76587c8b7e66e, 0x0f7655a3a47f98d9 }, + { 0x55ecad37d24b133c, 0x441e147d6038c90b, 0x656683a1d62c6fee, 0x0157d5dc87e0ecae } + }, + { + { -0x6ad9aaeb28e14adc, -0x19fc277ea20eba6d, 0x147cdf410d4de6b7, 0x5293b1730437c850 }, + { -0x0d5850aefcab3ec3, -0x285f4eba55c8d4a0, 0x2869b96a05a3d470, 0x6528e42d82460173 }, + { 0x23d0e0814bccf226, -0x6d38ba327e69046d, -0x749e8693a6abe1a5, 0x40a44df0c021f978 } + }, + { + { -0x793691aeb43a2f6b, -0x0df2bf6703597fb6, 0x27363d89c826ea5d, 0x39ca36565719cacf }, + { -0x25579676b0df1596, -0x15eb5c2eb39df9e8, 0x6001fccb090bf8be, 0x35f4e822947e9cf0 }, + { -0x68af90d0907848a4, -0x39db515ffcb51f90, 0x1ec856e3aad34dd6, 0x055b0be0e440e58f } + }, + { + { 0x4d12a04b6ea33da2, 0x57cf4c15e36126dd, -0x6f13698a11bb2699, 0x64ca348d2a985aac }, + { 0x6469a17d89735d12, -0x2490d82a199d460f, -0x60345cd795c6a97f, 0x363b8004d269af25 }, + { -0x66a771e61b3b6ed3, -0x1033c4b1e35a3195, 0x4522ea60fa5b98d5, 0x7064bbab1de4a819 } + }, + { + { -0x5d6f3f9ebdabded7, -0x0d1d3d514172a470, -0x30dba724895401e5, 0x02157ade83d626bf }, + { -0x46e61eaea588f9bf, -0x565d1d38b1807fc7, 0x7527250b3df23109, 0x756a7330ac27b78b }, + { 0x3e46972a1b9a038b, 0x2e4ee66a7ee03fb4, -0x7e5db78891244b36, 0x1a944ee88ecd0563 } + }, + { + { -0x44bf57a6e7dc9d2a, -0x4660aa8875b2e545, -0x72e74bd88a7aa60a, 0x26c20fe74d26235a }, + { -0x2a56e2eeaefc6c8e, 0x2ed377b799ca26de, -0x5e8dfd5302c99495, 0x0730291bd6901995 }, + { 0x648d1d9fe9cc22f5, 0x66bc561928dd577c, 0x47d3ed21652439d1, 0x49d271acedaf8b49 } + }, +}, +{ + { + { 0x2798aaf9b4b75601, 0x5eac72135c8dad72, -0x2d31559e9e485fdd, 0x1bbfb284e98f7d4e }, + { -0x760afa75c7d4cc0d, 0x5ae2ba0bad48c0b4, -0x706c4afc5ac24c92, 0x5aa3ed9d95a232e6 }, + { 0x656777e9c7d96561, -0x34d4edab8d387fca, 0x65053299d9506eee, 0x4a07e14e5e8957cc } + }, + { + { 0x240b58cdc477a49b, -0x02c725219bb80fe9, 0x19928d32a7c86aad, 0x50af7aed84afa081 }, + { 0x4ee412cb980df999, -0x5cea2890c391388f, -0x445a12216da38803, 0x3f0bac391d313402 }, + { 0x6e4fde0115f65be5, 0x29982621216109b2, 0x780205810badd6d9, 0x1921a316baebd006 } + }, + { + { -0x28a55265260c3e75, 0x566a0eef60b1c19c, 0x3e9a0bac255c0ed9, 0x7b049deca062c7f5 }, + { -0x76bdd08120478f04, 0x2c296beb4f76b3bd, 0x0738f1d436c24df7, 0x6458df41e273aeb0 }, + { -0x23341c85cabbbb7d, 0x758879330fedbe93, 0x786004c312c5dd87, 0x6093dccbc2950e64 } + }, + { + { 0x6bdeeebe6084034b, 0x3199c2b6780fb854, -0x68cc895449d2f96b, 0x6e3180c98b647d90 }, + { 0x1ff39a8585e0706d, 0x36d0a5d8b3e73933, 0x43b9f2e1718f453b, 0x57d1ea084827a97c }, + { -0x118549185ed74f8f, -0x5b3ea6926c577456, -0x084b217d4dde9ed0, 0x363e999ddd97bd18 } + }, + { + { 0x2f1848dce24baec6, 0x769b7255babcaf60, -0x6f34c391c31016cf, 0x231f979bc6f9b355 }, + { -0x6957bc3eca11e03c, -0x68914caaf71b3731, -0x4bd097fe4a732cd0, 0x48ee9b78693a052b }, + { 0x5c31de4bcc2af3c6, -0x4fb44fcf01df72e1, -0x48728ff63eb04b9a, 0x079bfa9b08792413 } + }, + { + { -0x0c36127f5d2abdbb, 0x0aa08b7877f63952, -0x2892539c2ef7ab8b, 0x1ef4fb159470636b }, + { -0x1c6fc5ae25cff20c, -0x7bc69bdcc256a550, -0x12c30ed2f4ca9b80, 0x038c77f684817194 }, + { -0x7ab1a119a4e98414, 0x59590a4296d0cdc2, 0x72b2df3498102199, 0x575ee92a4a0bff56 } + }, + { + { 0x5d46bc450aa4d801, -0x3c50edd85acc4628, 0x389e3b262b8906c2, 0x200a1e7e382f581b }, + { -0x2b3f7f6f75e7d031, 0x30e170c299489dbd, 0x05babd5752f733de, 0x43d4e7112cd3fd00 }, + { 0x518db967eaf93ac5, 0x71bc989b056652c0, -0x01d47a26a98e680b, 0x050eca52651e4e38 } + }, + { + { -0x6853c6899f199716, -0x64e64401eac54b69, 0x4cb179b534eca79f, 0x6151c09fa131ae57 }, + { -0x3cbce521bac0f364, -0x160afba1008fc465, -0x03268536127b84c3, 0x4b0ee6c21c58f4c6 }, + { 0x3af55c0dfdf05d96, -0x22d9d11fd54b1186, 0x11b2bb8712171709, 0x1fef24fa800f030b } + }, +}, +{ + { + { -0x006e59956fe99de0, -0x0ddaad51a40e1ff7, 0x7dff85d87f90df7c, 0x4f620ffe0c736fb9 }, + { -0x4b69edc5949399f7, -0x58af017a7f54a6c8, -0x0b8e40c6483d85a1, 0x507903ce77ac193c }, + { 0x62f90d65dfde3e34, -0x30d73a6d4605a053, -0x6637910639e9baf0, 0x25d448044a256c84 } + }, + { + { 0x2c7c4415c9022b55, 0x56a0d241812eb1fe, -0x0fd15e362849a1f3, 0x4180512fd5323b26 }, + { -0x4297dcf138164e91, 0x0eb1b9c1c1c5795d, 0x7943c8c495b6b1ff, 0x2f9faf620bbacf5e }, + { -0x5b00c19675b75a25, -0x4595c7f9426abfc5, -0x60831e50b82a49a3, 0x15e087e55939d2fb } + }, + { + { -0x776be7910469c0c8, 0x48a00e80dc639bd5, -0x5b17f6d41693e367, 0x5a097d54ca573661 }, + { 0x12207543745c1496, -0x2500c30225c79ef4, -0x1b1868d8d38e3cb1, 0x39c07b1934bdede9 }, + { 0x2d45892b17c9e755, -0x2fcc028d76cf7208, 0x6c2fe9d9525b8bd9, 0x2edbecf1c11cc079 } + }, + { + { -0x11f0f0222f785da1, -0x638aceaaa3c1cb12, 0x660c572e8fab3ab5, 0x0854fc44544cd3b2 }, + { 0x1616a4e3c715a0d2, 0x53623cb0f8341d4d, -0x6910acd638176635, 0x3d4e8dbba668baa6 }, + { 0x61eba0c555edad19, 0x24b533fef0a83de6, 0x3b77042883baa5f8, 0x678f82b898a47e8d } + }, + { + { 0x1e09d94057775696, -0x112ed9a3c326ae25, -0x056253d4df431e91, 0x0f7f76e0e8d089f4 }, + { -0x4eb6e2f4296ff3ac, 0x3539722c9d132636, 0x4db928920b362bc9, 0x4d7cd1fea68b69df }, + { 0x36d9ebc5d485b00c, -0x5da69b6d1b524c9b, -0x3e9a6b7f3dee6333, 0x45306349186e0d5f } + }, + { + { -0x695beb13d4f8db6f, 0x1bb2218127a7b65b, 0x6d2849596e8a4af0, 0x65f3b08ccd27765f }, + { -0x6b222f3e593200e3, 0x55f6f115e84213ae, 0x6c935f85992fcf6a, 0x067ee0f54a37f16f }, + { -0x134d6000e667fe09, -0x62c9e2e05d5f08d1, 0x25f11d2375fd2f49, 0x124cefe80fe10fe2 } + }, + { + { 0x1518e85b31b16489, -0x70552348248ef405, 0x39b0bdf4a14ae239, 0x05f4cbea503d20c1 }, + { 0x4c126cf9d18df255, -0x3e2b8e16eb859c4a, 0x2c6d3c73f3c93b5f, 0x6be3a6a2e3ff86a2 }, + { -0x31fbf1613fbeba44, -0x38e00b1df7097cb4, -0x42ab91725477b85d, 0x64666aa0a4d2aba5 } + }, + { + { -0x4f3ac408ccc816b4, 0x7cb5697e11e14f15, 0x4b84abac1930c750, 0x28dd4abfe0640468 }, + { 0x6841435a7c06d912, -0x35edc3de44c07cf5, -0x2b4c84d84e341d88, 0x1d753b84c76f5046 }, + { 0x7dc0b64c44cb9f44, 0x18a3e1ace3925dbf, 0x7a3034862d0457c4, 0x4c498bf78a0c892e } + }, +}, +{ + { + { 0x22d2aff530976b86, -0x726f47f93d2db9fc, -0x235e7693b21a451b, 0x28005fe6c8340c17 }, + { 0x37d653fb1aa73196, 0x0f9495303fd76418, -0x52dff4f604c5e84e, 0x544d49292fc8613e }, + { 0x6aefba9f34528688, 0x5c1bff9425107da1, -0x08a444329926b4ca, 0x72e472930f316dfa } + }, + { + { 0x07f3f635d32a7627, 0x7aaa4d865f6566f0, 0x3c85e79728d04450, 0x1fee7f000fe06438 }, + { 0x2695208c9781084f, -0x4eafd5f4dcbaf11f, -0x02625159fc1021fe, 0x5a9d2e8c2733a34c }, + { 0x765305da03dbf7e5, -0x5b250db6ebcb3243, 0x7b4ad5cdd24a88ec, 0x00f94051ee040543 } + }, + { + { -0x28106c44f85068ad, 0x583ed0cf3db766a7, -0x3196674091f4e13b, 0x47b7ffd25dd40452 }, + { -0x72ca94dc3c2ccf4e, -0x0de374644fb8e4fa, -0x4c93ce9391bd47c4, 0x07d79c7e8beab10d }, + { -0x7804046343f722ee, -0x75f994c51e113d65, 0x0d57242bdb1fc1bf, 0x1c3520a35ea64bb6 } + }, + { + { -0x325790bfde943fa7, 0x1fbb231d12bcd87e, -0x4b6a9561e838f670, 0x38750c3b66d12e55 }, + { -0x7f2dac5943345cb6, 0x3e61c3a13838219b, -0x6f3c49fe677d1c6a, 0x1c3d05775d0ee66f }, + { 0x692ef1409422e51a, -0x343f38c3d4a2098f, 0x21014fe7744ce029, 0x0621e2c7d330487c } + }, + { + { -0x4851e8694f240f0d, 0x54dfafb9e17ce196, 0x25923071e9aaa3b4, 0x5d8e589ca1002e9d }, + { -0x50679f337da67c73, -0x6f15b73e39606524, 0x6526483765581e30, 0x0007d6097bd3a5bc }, + { -0x3f40e26af7bd56b5, -0x4d2c3c9ca770d1c2, 0x0a961438bb51e2ef, 0x1583d7783c1cbf86 } + }, + { + { -0x6ffcb8fb3362d739, 0x1d1b679ef72cc58f, 0x16e12b5fbe5b8726, 0x4958064e83c5580a }, + { -0x13115d10a25d851f, 0x597c3a1455670174, -0x3659d5ed99f6e986, 0x252a5f2e81ed8f70 }, + { 0x0d2894265066e80d, -0x033c087acf837395, 0x1b53da780c1112fd, 0x079c170bd843b388 } + }, + { + { -0x322932af3f2a2faa, -0x6508979244fca8c5, 0x3ca6723ff3c3ef48, 0x6768c0d7317b8acc }, + { 0x0506ece464fa6fff, -0x411cbce19dfa1add, 0x3579422451b8ea42, 0x6dec05e34ac9fb00 }, + { -0x6b49da1a0eaa3e4d, 0x417bf3a7997b7b91, -0x3dd342239294da00, 0x51445e14ddcd52f4 } + }, + { + { -0x76ceb854d4415bab, -0x73ac5db06df86ed7, 0x4b49f948be30f7a7, 0x12e990086e4fd43d }, + { 0x57502b4b3b144951, -0x71980094bbb4434d, -0x474296d8e99c7a25, 0x13186f31e39295c8 }, + { -0x0ef3694c802044d2, -0x60656ca1ede31507, -0x20eec93bc5a467c1, 0x77b2e3f05d3e99af } + }, +}, +{ + { + { -0x6acd0b7033a32d65, 0x2ba851bea3ce3671, 0x32dacaa051122941, 0x478d99d9350004f2 }, + { -0x02f28a78630ed9a9, -0x17d0106b1ac5f1d7, -0x33cb580fa444b419, 0x0b251172a50c38a2 }, + { 0x1d5ad94890bb02c0, 0x50e208b10ec25115, -0x5d95dd76b10de8fe, 0x4dc923343b524805 } + }, + { + { 0x3ad3e3ebf36c4975, -0x28a2da5ac879dedb, -0x178c6bc25fda5aea, 0x6bbc7cb4c411c847 }, + { -0x1c7d73bff07f794a, 0x3f77e6f7979f0dc8, 0x7ef6de304df42cb4, 0x5265797cb6abd784 }, + { 0x3c6f9cd1d4a50d56, -0x49dbbf8839015482, 0x6ff9bf483580972e, 0x00375883b332acfb } + }, + { + { -0x3674137a938a3664, -0x1bbe7b3fff1cc30c, 0x0a676b9bba907634, 0x669e2cb571f379d7 }, + { 0x0001b2cd28cb0940, 0x63fb51a06f1c24c9, -0x4a52796e232a35cf, 0x67238dbd8c450660 }, + { -0x34ee948c5b642cf8, 0x025aad6b2392729e, -0x4b86c105c0aa264f, 0x72a1056140678bb9 } + }, + { + { 0x0d8d2909e2e505b6, -0x673587543fd6edd0, 0x77ef5569a9b12327, 0x7c77897b81439b47 }, + { -0x5d497ed4e336db63, 0x62866eee21211f58, 0x2cb5c5b85df10ece, 0x03a6b259e263ae00 }, + { -0x0e3e4a1d21cce34b, 0x5a9f5d8e15fca420, -0x605bc70e8426cd4f, 0x2a381bf01c6146e7 } + }, + { + { -0x083f41cd4acbe991, 0x27e6ca6419cf70d4, -0x6cb2082856a858a7, 0x5701461dabdec2aa }, + { -0x536467863037ee3f, -0x7482d67ec8a91a99, 0x50da4e607c70edfc, 0x5dbca62f884400b6 }, + { 0x2c6747402c915c25, 0x1bdcd1a80b0d340a, 0x5e5601bd07b43f5f, 0x2555b4e05539a242 } + }, + { + { 0x78409b1d87e463d4, -0x52b256a532049c63, -0x13d788c8aada6464, 0x69c806e9c31230ab }, + { 0x6fc09f5266ddd216, -0x231a9f58371c8fb8, -0x139a6c625d209d03, 0x7a869ae7e52ed192 }, + { 0x7b48f57414bb3f22, 0x68c7cee4aedccc88, -0x12d06c9e86127f42, 0x25d70b885f77bc4b } + }, + { + { -0x67ba62d644e51b2c, 0x56b9c4c739f954ec, -0x7cd8bc093d64b4c2, 0x21ea8e2798b6878a }, + { 0x4151c3d9762bf4de, 0x083f435f2745d82b, 0x29775a2e0d23ddd5, 0x138e3a6269a5db24 }, + { -0x78410b4b95a58464, -0x2dd662e4a03e2f9e, -0x7dbf67e722cde9b8, 0x5c5abeb1e5a2e03d } + }, + { + { 0x02cde6de1306a233, 0x7b5a52a2116f8ec7, -0x1e397e0b3ee9c4a5, 0x241d350660d32643 }, + { 0x14722af4b73c2ddb, -0x43b8f3a0a5faf9f3, 0x00943eac2581b02e, 0x0e434b3b1f499c8f }, + { 0x6be4404d0ebc52c7, -0x51b9dcc44e586e0b, 0x2aec170ed25db42b, 0x1d8dfd966645d694 } + }, +}, +{ + { + { -0x2a679c63ed224f5c, -0x5a2e60cf3fdb7995, -0x2e83d0fca7031ba0, 0x07a195152e095e8a }, + { 0x296fa9c59c2ec4de, -0x43749e40b07b0c35, 0x1c7706d917a8f908, 0x63b795fc7ad3255d }, + { -0x57c970fdc761a038, -0x6fbcc4fd30721bc5, -0x505e02a23abed9bd, 0x3e8fe83d032f0137 } + }, + { + { 0x08704c8de8efd13c, -0x203ae571cc1fc8cf, -0x5a62a25aed9f321d, 0x22d60899a6258c86 }, + { 0x2f8b15b90570a294, -0x6b0dbd8f98f7bab7, -0x21e3a51e9e44027c, 0x75ba3b797fac4007 }, + { 0x6239dbc070cdd196, 0x60fe8a8b6c7d8a9a, -0x4c77b84314bfeda0, 0x0904d07b87779e5e } + }, + { + { -0x0bcdd299b706bf47, 0x06952f0cbd2d0c39, 0x167697ada081f931, 0x6240aacebaf72a6c }, + { -0x4b31e02b22456e64, -0x30ce24c138b37256, 0x2c63cc63ad86cc51, 0x43e2143fbc1dde07 }, + { -0x07cb8b63a45d6a60, -0x296b83a435c82da6, 0x66f13ba7e7c9316a, 0x56bdaf238db40cac } + }, + { + { 0x1310d36cc19d3bb2, 0x062a6bb7622386b9, 0x7c9b8591d7a14f5c, 0x03aa31507e1e5754 }, + { 0x362ab9e3f53533eb, 0x338568d56eb93d40, -0x61f1ebade2a5aa8e, 0x1d24a86d83741318 }, + { -0x0b1389b7002b31e1, -0x1fba150fab5373e4, -0x772dda7de2f6ca84, 0x43b261dc9aeb4859 } + }, + { + { 0x19513d8b6c951364, -0x6b018ed9fff40b85, 0x028d10ddd54f9567, 0x02b4d5e242940964 }, + { -0x1aa4e1e677448645, -0x5f612f823e85ca63, -0x4fd3d11d9fc215cd, 0x326055cf5b276bc2 }, + { -0x4b5eaa34d72e720e, -0x1533b9b9e7931af8, -0x3b630b6c937dbc77, 0x27a6c809ae5d3410 } + }, + { + { -0x32d3d8f53bc296ac, -0x22b5c1a89599354e, 0x79fa592469d7036c, 0x221503603d8c2599 }, + { -0x74591432e0f24e78, 0x37d3d73a675a5be8, -0x0dd1205cea0aa7a6, 0x2cb67174ff60a17e }, + { 0x59eecdf9390be1d0, -0x56bddfbb8d731c0f, -0x7d76e399856b0f0c, 0x7b1df4b73890f436 } + }, + { + { 0x5f2e221807f8f58c, -0x1caaa3602b6bf62c, -0x4d555772e04959d0, 0x68698245d352e03d }, + { -0x1b6d0d1f4c4d5ddc, 0x7c6c9e062b551160, 0x15eb8fe20d7f7b0e, 0x61fcef2658fc5992 }, + { -0x244ea27ad5e7e786, -0x0c1b552c79225329, 0x44bae2810ff6c482, 0x46cf4c473daf01cf } + }, + { + { 0x213c6ea7f1498140, 0x7c1e7ef8392b4854, 0x2488c38c5629ceba, 0x1065aae50d8cc5bb }, + { 0x426525ed9ec4e5f9, 0x0e5eda0116903303, 0x72b1a7f2cbe5cadc, 0x29387bcd14eb5f40 }, + { 0x1c2c4525df200d57, 0x5c3b2dd6bfca674a, 0x0a07e7b1e1834030, 0x69a198e64f1ce716 } + }, +}, +{ + { + { 0x7b26e56b9e2d4734, -0x3b38ecd47e39e98b, -0x10a36ada13632181, 0x39c80b16e71743ad }, + { 0x7afcd613efa9d697, 0x0cc45aa41c067959, -0x5a901efb3e05256a, 0x3a73b70472e40365 }, + { 0x0f196e0d1b826c68, -0x08e00f1db69f1c25, 0x6113167023b7436c, 0x0cf0ea5877da7282 } + }, + { + { -0x1ccd312bc4596ba6, -0x21f4ec9e177e3fa3, 0x1ad40f095e67ed3b, 0x5da8acdab8c63d5d }, + { 0x196c80a4ddd4ccbd, 0x22e6f55d95f2dd9d, -0x38a1cc38bf2938e5, 0x7bb51279cb3c042f }, + { -0x3b4999b5c58fea61, 0x76194f0f0a904e14, -0x5a9eb3c65bf693ed, 0x6cd0ff50979feced } + }, + { + { 0x7fecfabdb04ba18e, -0x2f038403c4224309, -0x5be2b791fa85ece4, 0x641a4391f2223a61 }, + { -0x3f1f981870bbd754, 0x14835ab0a61135e3, -0x0de2eb0cc7f9d6cb, 0x6390a4c8df04849c }, + { -0x3a3946a559f95725, -0x6eb480614f97da0f, 0x2a731f6b44fc9eff, 0x30ddf38562705cfc } + }, + { + { 0x33bef2bd68bcd52c, -0x39b6244f96b7d10e, -0x4a4911f3be34e512, 0x5c294d270212a7e5 }, + { 0x4e3dcbdad1bff7f9, -0x36ee717ddf9ba8e9, -0x45333143f0e762aa, 0x1b4822e9d4467668 }, + { -0x54c9f580daa9c87f, 0x2512228a480f7958, -0x38a2fad89eeb4b1d, 0x222d9625d976fe2a } + }, + { + { 0x0f94be7e0a344f85, -0x14d05573780dd3c8, -0x631e18a1b11e90f1, 0x43e64e5418a08dea }, + { 0x1c717f85b372ace1, -0x7e6cf196b9c740e8, 0x239cad056bc08b58, 0x0b34271c87f8fff4 }, + { -0x7eaa1dade5ca319d, -0x41eff2b206edfd72, -0x4007f4075a822314, 0x57342dc96d6bc6e4 } + }, + { + { -0x0c3c4348e18f840a, 0x351d9b8c7291a762, 0x00502e6edad69a33, 0x522f521f1ec8807f }, + { -0x10110f9a3731a668, -0x40fd6aef4a34155e, -0x739b5ef9df483ba8, 0x35134fb231c24855 }, + { 0x272c1f46f9a3902b, -0x36e45c48669a8434, -0x519eb4cfb075e3f2, 0x7afcaad70b99017b } + }, + { + { -0x577ebe13107bd495, 0x55e7b14797abe6c5, -0x738b7068fc87b002, 0x5b50a1f7afcd00b7 }, + { -0x3da212ab5b4741bf, -0x6fd2ec1ee44f1d23, 0x41f43233cde82ab2, 0x1085faa5c3aae7cb }, + { -0x647bf0990ec9eceb, 0x18462242701003e9, 0x65ed45fae4a25080, 0x0a2862393fda7320 } + }, + { + { -0x69f18c84913462e9, -0x050db6b72983151f, 0x37e7a9b4d55e1b89, 0x5cb7173cb46c59eb }, + { 0x46ab13c8347cbc9d, 0x3849e8d499c12383, 0x4cea314087d64ac9, 0x1f354134b1a29ee7 }, + { 0x4a89e68b82b7abf0, -0x0be326d864594847, 0x16e6c210e18d876f, 0x7cacdb0f7f1b09c6 } + }, +}, +{ + { + { -0x1efebbcb233a3513, 0x47ed5d963c84fb33, 0x70019576ed86a0e7, 0x25b2697bd267f9e4 }, + { -0x6f9d4d1f26e58744, 0x47c9889cc8509667, -0x620ab599bfaf8f48, 0x7369e6a92493a1bf }, + { -0x6298c004ec67979c, 0x3ca5fbd9415dc7b8, -0x1fb133c420d8c4a2, 0x1420683db54e4cd2 } + }, + { + { 0x34eebb6fc1cc5ad0, 0x6a1b0ce99646ac8b, -0x2c4f25b6599421ad, 0x31e83b4161d081c1 }, + { -0x4b8742e1db622e69, 0x620c35005e58c102, -0x04fd2cd0334553a4, 0x60b63bebf508a72d }, + { -0x681738ed61f9d4b1, 0x49e48f4f29320ad8, 0x5bece14b6f18683f, 0x55cf1eb62d550317 } + }, + { + { 0x3076b5e37df58c52, -0x28c54622186633ca, -0x427ce31cb6ec11e0, 0x1a56fbaa62ba0133 }, + { 0x5879101065c23d58, -0x7462f792af6b7e64, -0x1dbfd056ed3aa059, 0x669a6564570891d4 }, + { -0x6bc194afa3623614, 0x302557bba77c371a, -0x678c51a9becb89af, 0x13c4836799c58a5c } + }, + { + { -0x3b230495a2742f80, -0x21143b13a8e5b7be, -0x2b4d177c471aac9b, 0x50bdc87dc8e5b827 }, + { 0x423a5d465ab3e1b9, -0x03ec3e78380ec09f, 0x19f83664ecb5b9b6, 0x66f80c93a637b607 }, + { 0x606d37836edfe111, 0x32353e15f011abd9, 0x64b03ac325b73b96, 0x1dd56444725fd5ae } + }, + { + { -0x3d6819fff7453766, 0x7d4cea11eae1c3e0, -0x0c1c741e60186884, 0x3a3a450f63a305cd }, + { -0x705b8007cc9ded83, -0x4360953b8e3283eb, 0x6e71454349220c8b, 0x0e645912219f732e }, + { 0x078f2f31d8394627, 0x389d3183de94a510, -0x2e1c9392e8669080, 0x318c8d9393a9a87b } + }, + { + { 0x5d669e29ab1dd398, -0x036de9a7cbd261c5, 0x55851dfdf35973cd, 0x509a41c325950af6 }, + { -0x0d8ba2fcd50001e7, 0x0c9f3c497f24db66, -0x43672c1c457a6711, 0x224c7c679a1d5314 }, + { -0x423f91235906da17, 0x793ef3f4641b1f33, -0x7d13ed7f627cc177, 0x05bff02328a11389 } + }, + { + { 0x6881a0dd0dc512e4, 0x4fe70dc844a5fafe, 0x1f748e6b8f4a5240, 0x576277cdee01a3ea }, + { 0x3632137023cae00b, 0x544acf0ad1accf59, -0x698befb62de5e378, 0x780b8cc3fa2a44a7 }, + { 0x1ef38abc234f305f, -0x65a88042ebfa21f8, 0x5e82a51434e62a0d, 0x5ff418726271b7a1 } + }, + { + { -0x1a24b817ec496ac0, -0x0ca2d5c4bcd9ef1f, -0x53e0d916c787ed8a, 0x29d4db8ca0a0cb69 }, + { 0x398e080c1789db9d, -0x589fdfda0c18870b, -0x056776b3f942fca3, 0x106a03dc25a966be }, + { -0x2652f550ccccac30, 0x38669da5acd309e5, 0x3c57658ac888f7f0, 0x4ab38a51052cbefa } + }, +}, +{ + { + { -0x09701d177f621fac, -0x1c43f695637d452f, 0x076353d40aadbf45, 0x7b9b1fb5dea1959e }, + { -0x20253411bcdb3f17, 0x054442883f955bb7, -0x2108555715ce9f61, 0x68aee70642287cff }, + { -0x0fe3370e8b8e33f4, -0x6adbd1c8a86f7d45, 0x27776093d3e46b5f, 0x2d13d55a28bd85fb } + }, + { + { -0x40fe6331851185ae, -0x57212d491bab152d, 0x3c619f0b87a8bb19, 0x3619b5d7560916d8 }, + { -0x053a2df9a4ca4726, -0x572575657a9db449, -0x332d356ec2de32f1, 0x6b8341ee8bf90d58 }, + { 0x3579f26b0282c4b2, 0x64d592f24fafefae, -0x48321284d7373840, 0x6a927b6b7173a8d7 } + }, + { + { -0x728fbf79c1317715, -0x0f1cf8567f113f74, -0x53ddaf9ef2877026, 0x056d92a43a0d478d }, + { 0x1f6db24f986e4656, 0x1021c02ed1e9105b, -0x0700c000d33f5c8b, 0x1d2a6bf8c6c82592 }, + { 0x1b05a196fc3da5a1, 0x77d7a8c243b59ed0, 0x06da3d6297d17918, 0x66fbb494f12353f7 } + }, + { + { -0x2928f6690edcf62a, -0x2404dc7a163c2ac7, 0x46d602b0f7552411, 0x270a0b0557843e0c }, + { 0x751a50b9d85c0fb8, -0x2e5023da7430f685, 0x2f16a6a38309a969, 0x14ddff9ee5b00659 }, + { 0x61ff0640a7862bcc, -0x7e353f65a0ee5402, -0x6fb87cfbaa2ed545, 0x19a4bde1945ae873 } + }, + { + { 0x40c709dec076c49f, 0x657bfaf27f3e53f6, 0x40662331eca042c4, 0x14b375487eb4df04 }, + { -0x6460d90adf59dff6, 0x64804443cf13eaf8, -0x759c98c079ce122d, 0x72bbbce11ed39dc1 }, + { -0x517ac36b549923b9, -0x149dcbc12089d292, -0x0f71f1e7904d082f, 0x4f0b1c02700ab37a } + }, + { + { 0x79fd21ccc1b2e23f, 0x4ae7c281453df52a, -0x37e8d1362eaeb795, 0x68abe9443e0a7534 }, + { -0x1e8f987827e6ae06, -0x5ef5d3714d6f3885, -0x18c7d05fc129988d, 0x0a4d84710bcc4b54 }, + { -0x25ed393bf87ce235, 0x0da230d74d5c510d, 0x4ab1531e6bd404e1, 0x4106b166bcf440ef } + }, + { + { -0x5b7a332ac61b130e, 0x5aa3f3ad0555bab5, 0x145e3439937df82d, 0x1238b51e1214283f }, + { 0x02e57a421cd23668, 0x4ad9fb5d0eaef6fd, -0x6ab198d84edbbb80, 0x7f792f9d2699f331 }, + { 0x0b886b925fd4d924, 0x60906f7a3626a80d, -0x132c984b467542ee, 0x2876beb1def344cf } + }, + { + { -0x2a6b4cccc5757a08, 0x4ea37689e78d7d58, 0x73bf9f455e8e351f, 0x5507d7d2bc41ebb4 }, + { -0x237b16ca9cebb96f, 0x632fe8a0d61f23f4, 0x4caa800612a9a8d5, 0x48f9dbfa0e9918d3 }, + { 0x1ceb2903299572fc, 0x7c8ccaa29502d0ee, -0x6e405bcbee331985, 0x5784481964a831e7 } + }, +}, +{ + { + { -0x29302e10a0223f64, -0x17d4c10208a8a232, 0x25d56b5d201634c2, 0x3041c6bb04ed2b9b }, + { -0x2583d4da98972a6d, -0x673e3fa8bbdd35ed, -0x0e57f42a35f531e3, 0x29cdd1adc088a690 }, + { 0x0ff2f2f9d956e148, -0x5218688a60ca94d2, 0x1a4698bb5f6c025c, 0x104bbd6814049a7b } + }, + { + { -0x56a265a029800e9d, -0x16d41962b338a97f, -0x4807fdb321df0da9, 0x204f2a20fb072df5 }, + { 0x51f0fd3168f1ed67, 0x2c811dcdd86f3bc2, 0x44dc5c4304d2f2de, 0x5be8cc57092a7149 }, + { -0x37ebc4c2cf144f87, 0x7589155abd652e30, 0x653c3c318f6d5c31, 0x2570fb17c279161f } + }, + { + { 0x192ea9550bb8245a, -0x37190457706faf2f, 0x7986ea2d88a4c935, 0x241c5f91de018668 }, + { 0x3efa367f2cb61575, -0x0a069089e329fd94, -0x1738ebd59a4ada9e, 0x3dcb65ea53030acd }, + { 0x28d8172940de6caa, -0x7040d30fdd268cc6, 0x16d7fcdd235b01d1, 0x08420edd5fcdf0e5 } + }, + { + { 0x0358c34e04f410ce, -0x49eca4a5d891f97b, 0x5d9670c7ebb91521, 0x04d654f321db889c }, + { -0x3200df547c9d05b6, 0x57e118d4e21a3e6e, -0x1ce869e803c619d5, 0x0d9a53efbc1769fd }, + { 0x5e7dc116ddbdb5d5, 0x2954deb68da5dd2d, 0x1cb608173334a292, 0x4a7a4f2618991ad7 } + }, + { + { 0x24c3b291af372a4b, -0x6c257d8f8e7eb80e, -0x227b7a9b7976610e, 0x4a96314223e0ee33 }, + { -0x0b58e7fda04ea06b, 0x3df65f346b5c1b8f, -0x32030f7aff1feeee, 0x11b50c4cddd31848 }, + { -0x5917d8bbf75b002a, 0x738e177e9c1576d9, 0x773348b63d02b3f2, 0x4f4bce4dce6bcc51 } + }, + { + { 0x30e2616ec49d0b6f, -0x1ba98e703513dce9, 0x48eb409bf26b4fa6, 0x3042cee561595f37 }, + { -0x58e031a51ddbda7c, 0x26ea725692f58a9e, -0x2de5f628e315c30c, 0x73fcdd14b71c01e6 }, + { 0x427e7079449bac41, -0x7aa51c92431dcef6, 0x4cae76215f841a7c, 0x389e740c9a9ce1d6 } + }, + { + { -0x36428709a8f153d8, -0x1aa4f4cdd86e631f, 0x65fc3eaba19b91ed, 0x25c425e5d6263690 }, + { 0x64fcb3ae34dcb9ce, -0x68affcdc1cb72f53, 0x45b3f07d62c6381b, 0x61545379465a6788 }, + { 0x3f3e06a6f1d7de6e, 0x3ef976278e062308, -0x73eb09d9b1759389, 0x6539a08915484759 } + }, + { + { -0x223b242beb44b5e7, 0x19b2bc3c98424f8e, 0x48a89fd736ca7169, 0x0f65320ef019bd90 }, + { -0x162de08b3c2d088d, -0x3eafabbeda3b97bb, 0x624e5ce8f9b99e33, 0x11c5e4aac5cd186c }, + { -0x2b792e4e35021f3a, 0x4f3fe6e3163b5181, 0x59a8af0dfaf2939a, 0x4cabc7bdec33072a } + }, +}, +{ + { + { -0x083f5e63e5ab5fbc, 0x4a1c5e2477bd9fbb, -0x591c35eea50dd68e, 0x1819bb953f2e9e0d }, + { 0x16faa8fb532f7428, -0x242bd15fb95b1d8e, 0x5337653b8b9ea480, 0x4065947223973f03 }, + { 0x498fbb795e042e84, 0x7d0dd89a7698b714, -0x7404f45bd8019d6b, 0x36ba82e721200524 } + }, + { + { -0x372962f5a8d8b12b, 0x45ba803260804b17, -0x20c325efddaa2054, 0x77d221232709b339 }, + { -0x29f13448bdba13bf, -0x02641761cbcb78ea, -0x36dbf5011bdd7b22, 0x4472f648d0531db4 }, + { 0x498a6d7064ad94d8, -0x5a4a37026509dd9d, -0x735712faba3ebe0c, 0x2c63bec3662d358c } + }, + { + { -0x65ae74c57a790741, -0x6118e509344e6910, -0x55f9da195dc7a30e, 0x1deb2176ddd7c8d1 }, + { 0x7fe60d8bea787955, -0x4623ee814a0bfe49, -0x6e383f65e6caa332, 0x22692ef59442bedf }, + { -0x7a9c2e65df993094, 0x401bfd8c4dcc7cd7, -0x2689594132f2709e, 0x67cfd773a278b05e } + }, + { + { 0x2d5fa9855a4e586a, 0x65f8f7a449beab7e, -0x55f8b2220de2cc2d, 0x185cba721bcb9dee }, + { -0x7213ce0510c11b8b, -0x6624007561dd026e, 0x512d11594e26cab1, 0x0cde561eec4310b9 }, + { -0x6c79625c0b1c34bf, -0x40fc6d0abf086882, 0x026204fcd0463b83, 0x3ec91a769eec6eed } + }, + { + { 0x0fad2fb7b0a3402f, 0x46615ecbfb69f4a8, -0x08ba43373a07155a, 0x7a5fa8794a94e896 }, + { 0x1e9df75bf78166ad, 0x4dfda838eb0cd7af, -0x45ffd1273e150678, 0x13fedb3e11f33cfc }, + { 0x52958faa13cd67a1, -0x69a11f7e74244ae9, 0x16e58daa2e8845b3, 0x357d397d5499da8f } + }, + { + { 0x481dacb4194bfbf8, 0x4d77e3f1bae58299, 0x1ef4612e7d1372a0, 0x3a8d867e70ff69e1 }, + { 0x1ebfa05fb0bace6c, -0x36cb9df3e35065e2, -0x3388e33be27d49e6, 0x2d94a16aa5f74fec }, + { 0x6f58cd5d55aff958, -0x45c155a38aa988df, 0x75c123999165227d, 0x69be1343c2f2b35e } + }, + { + { -0x7d44425397b4721d, -0x5d0b382fc035f8e8, 0x337f92fbe096aaa8, 0x200d4d8c63587376 }, + { 0x0e091d5ee197c92a, 0x4f51019f2945119f, 0x143679b9f034e99c, 0x7d88112e4d24c696 }, + { 0x208aed4b4893b32b, 0x3efbf23ebe59b964, -0x289d214f245a1af9, 0x69607bd681bd9d94 } + }, + { + { 0x3b7f3bd49323a902, 0x7c21b5566b2c6e53, -0x1a45700ac587ad59, 0x28bc77a5838ece00 }, + { -0x0941fdef9721e31f, -0x172ae718f12343e1, -0x1c10022fe4aafa5b, 0x35f63353d3ec3fd0 }, + { 0x63ba78a8e25d8036, 0x63651e0094333490, 0x48d82f20288ce532, 0x3a31abfa36b57524 } + }, +}, +{ + { + { -0x3f708770c0872d77, -0x01cf58d35ebfb261, -0x0d887403309a3363, 0x7ee498165acb2021 }, + { 0x239e9624089c0a2e, -0x38b73b3fc501b8c8, 0x17dbed2a764fa12a, 0x639b93f0321c8582 }, + { 0x7bd508e39111a1c3, 0x2b2b90d480907489, -0x182d513d518d02e7, 0x0edf493c85b602a6 } + }, + { + { 0x6767c4d284764113, -0x5f6fbfc0080a07cb, 0x1c8fcffacae6bede, 0x04c00c54d1dfa369 }, + { -0x51337ea7a664a598, -0x15a8b0f014521df2, 0x4fe41d7422b67f07, 0x403b92e3019d4fb4 }, + { 0x4dc22f818b465cf8, 0x71a0f35a1480eff8, -0x51174052fb3829a9, 0x355bb12ab26176f4 } + }, + { + { -0x5cfe2538a5738ce8, -0x126ffc624c3155ef, 0x6f077cbf3bae3f2d, 0x7518eaf8e052ad8e }, + { -0x58e19b338b6c440c, -0x1a427b26135c4f3d, 0x0a6bc50cfa05e785, 0x0f9b8132182ec312 }, + { -0x5b77a63be48093ce, 0x0f2d60bcf4383298, 0x1815a929c9b1d1d9, 0x47c3871bbb1755c4 } + }, + { + { -0x0419a2af37af9950, 0x62ecc4b0b3a299b0, -0x1ac8ab15bbe51720, 0x08fea02ce8d48d5f }, + { 0x5144539771ec4f48, -0x07fa4e823673a292, -0x089d3ee5b83c3995, 0x00b89b85764699dc }, + { -0x7db2228997211530, -0x379bbadfb497a2dd, -0x4aeb3032a276299b, 0x473829a74f75d537 } + }, + { + { 0x23d9533aad3902c9, 0x64c2ddceef03588f, 0x15257390cfe12fb4, 0x6c668b4d44e4d390 }, + { -0x7d2d258ab9863be8, -0x19c428274d9e7210, 0x355eef24ac47eb0a, 0x2078684c4833c6b4 }, + { 0x3b48cf217a78820c, -0x0895f54d7ed8c169, -0x56939a5873711285, 0x7411a6054f8a433f } + }, + { + { 0x579ae53d18b175b4, 0x68713159f392a102, -0x7baa1345e110ca0b, 0x1ec9a872458c398f }, + { 0x4d659d32b99dc86d, 0x044cdc75603af115, -0x4cb38ed3233d1b78, 0x7c136574fb8134ff }, + { -0x47195b2bff5daf65, -0x647e28fdf4377d4c, 0x57e7cc9bf1957561, 0x3add88a5c7cd6460 } + }, + { + { -0x7a3d672ba6c6cfba, -0x7081ca67a009a614, 0x1d2ca22af2f66e3a, 0x61ba1131a406a720 }, + { -0x5476a88f49ca230e, 0x02dfef6cf66c1fbc, -0x7aacfd9741492e79, 0x249929fccc879e74 }, + { -0x5c2f5f0ee96a6fd7, 0x023b6b6cba7ebd89, 0x7bf15a3e26783307, 0x5620310cbbd8ece7 } + }, + { + { 0x6646b5f477e285d6, 0x40e8ff676c8f6193, -0x59138cee544a6b23, 0x7ec846f3658cec4d }, + { 0x528993434934d643, -0x462407f95aeddd0b, -0x709278703c0be3de, 0x37676a2a4d9d9730 }, + { -0x64a170c0e25dd139, 0x130f1d776c01cd13, 0x214c8fcfa2989fb8, 0x6daaf723399b9dd5 } + }, +}, +{ + { + { -0x7e514422d32ecf90, -0x69d1bcda07a5f162, -0x216c6e5535200135, 0x53177fda52c230e6 }, + { 0x591e4a5610628564, 0x2a4bb87ca8b4df34, -0x21d5da8d185c71bd, 0x3cbdabd9fee5046e }, + { -0x584368f9af462187, 0x3d12a7fbc301b59b, 0x02652e68d36ae38c, 0x79d739835a6199dc } + }, + { + { 0x21c9d9920d591737, -0x6415be2d164b932a, -0x1df17bdff2764036, 0x79d99f946eae5ff8 }, + { -0x26cab209bece3e43, 0x758094a186ec5822, 0x4464ee12e459f3c2, 0x6c11fce4cb133282 }, + { -0x0e84b7ca9798cdfb, 0x387deae83caad96c, 0x61b471fd56ffe386, 0x31741195b745a599 } + }, + { + { 0x17f8ba683b02a047, 0x50212096feefb6c8, 0x70139be21556cbe2, 0x203e44a11d98915b }, + { -0x172efe6f4885c9f5, -0x66467cdf666a18fe, -0x42b0200705fdb856, 0x2772e344e0d36a87 }, + { -0x2979c145c8461c61, 0x105bc169723b5a23, 0x104f6459a65c0762, 0x567951295b4d38d4 } + }, + { + { 0x07242eb30d4b497f, 0x1ef96306b9bccc87, 0x37950934d8116f45, 0x05468d6201405b04 }, + { 0x535fd60613037524, -0x1def52094f043d96, -0x5372f564dc166f52, 0x47204d08d72fdbf9 }, + { 0x00f565a9f93267de, -0x313028723f2a7176, -0x5dea1d230ce71d72, 0x4599ee919b633352 } + }, + { + { -0x538b929479e51a87, 0x31ab0650f6aea9dc, 0x241d661140256d4c, 0x2f485e853d21a5de }, + { -0x2c3ddf358f1f1895, -0x4ed415a71560cf6c, 0x294ddec8c3271282, 0x0c3539e1a1d1d028 }, + { 0x329744839c0833f3, 0x6fe6257fd2abc484, 0x5327d1814b358817, 0x65712585893fe9bc } + }, + { + { -0x7e3d60e428f711c1, -0x2234a5fa519bf830, -0x68513e282d5c1459, 0x1590521a91d50831 }, + { -0x63efd048cd59ee9f, -0x1b71ef22cb2adf58, 0x365c63546f9a9176, 0x32f6fe4c046f6006 }, + { 0x40a3a11ec7910acc, -0x6fec20070e92d852, 0x1a9720d8abb195d4, 0x1bb9fe452ea98463 } + }, + { + { -0x30a1936a33c98b84, 0x294201536b0bc30d, 0x453ac67cee797af0, 0x5eae6ab32a8bb3c9 }, + { -0x162e26af4c2ab062, 0x2d5f9cbee00d33c1, 0x51c2c656a04fc6ac, 0x65c091ee3c1cbcc9 }, + { 0x7083661114f118ea, 0x2b37b87b94349cad, 0x7273f51cb4e99f40, 0x78a2a95823d75698 } + }, + { + { -0x4b0dc3bda107cdf9, -0x54076b2c3656cb4b, -0x2f8f73ecc6027809, 0x1876789117166130 }, + { -0x5d4f8d16a373d532, 0x69cffc96651e9c4b, 0x44328ef842e7b42b, 0x5dd996c122aadeb3 }, + { -0x6da4a10f98f3af84, -0x7e6437bd46c3cc41, 0x10792e9a70dd003f, 0x59ad4b7a6e28dc74 } + }, +}, +{ + { + { 0x583b04bfacad8ea2, 0x29b743e8148be884, 0x2b1e583b0810c5db, 0x2b5449e58eb3bbaa }, + { 0x5f3a7562eb3dbe47, -0x0815c7ab71425f48, 0x00c3e53145747299, 0x1304e9e71627d551 }, + { 0x789814d26adc9cfe, 0x3c1bab3f8b48dd0b, -0x25f01e00068639f6, 0x4468de2d7c2dd693 } + }, + { + { 0x4b9ad8c6f86307ce, 0x21113531435d0c28, -0x2b57993a9a8588d4, 0x5da6427e63247352 }, + { 0x51bb355e9419469e, 0x33e6dc4c23ddc754, -0x6c5a4929bb80669e, 0x6cce7c6ffb44bd63 }, + { 0x1a94c688deac22ca, -0x46f991084451e008, -0x775273c772a6a7f1, 0x58f29abfe79f2ca8 } + }, + { + { 0x4b5a64bf710ecdf6, -0x4eb31ac7b9d3d6c4, 0x3643d056d50b3ab9, 0x6af93724185b4870 }, + { -0x16f130547218c198, 0x54036f9f377e76a5, -0x0fb6a4f441fea67e, 0x577629c4a7f41e36 }, + { 0x3220024509c6a888, -0x2d1fc9ecb4aa768d, -0x7c1dc9dcc3ccd761, 0x701f25bb0caec18f } + }, + { + { -0x62e7092683413eed, -0x7bb5f9198b40241c, 0x20f5b522ac4e60d6, 0x720a5bc050955e51 }, + { -0x3c574f071b9e9313, -0x08ff99f161da5783, 0x61e3061ff4bca59c, 0x2e0c92bfbdc40be9 }, + { 0x0c3f09439b805a35, -0x17b174c89dbd5404, 0x691417f35c229346, 0x0e9b9cbb144ef0ec } + }, + { + { -0x7211642aa24e4112, -0x363c54c8f58dc047, 0x44a8f1bf1c68d791, 0x366d44191cfd3cde }, + { -0x04452b7004a8df53, -0x117e6e942406f2f2, -0x2b7ecead9caabc41, 0x221104eb3f337bd8 }, + { -0x61c3e8bc0d4373ec, 0x2eda26fcb5856c3b, -0x3347d0f197580469, 0x4167a4e6bc593244 } + }, + { + { -0x3d41d99a07317012, -0x169800eb177f29d4, -0x0ed19181d0c9b112, 0x34b33370cb7ed2f6 }, + { 0x643b9d2876f62700, 0x5d1d9d400e7668eb, 0x1b4b430321fc0684, 0x7938bb7e2255246a }, + { -0x323a6e11797e2934, -0x31fdef63127a58ad, -0x128b7a3ea77f777d, 0x1176fc6e2dfe65e4 } + }, + { + { -0x246f1d76b688f148, -0x670433d5530bbf5d, 0x21354ffeded7879b, 0x1f6a3e54f26906b6 }, + { -0x4b50932fa4639e65, 0x2ddfc9f4b2a58480, 0x3d4fa502ebe94dc4, 0x08fc3a4c677d5f34 }, + { 0x60a4c199d30734ea, 0x40c085b631165cd6, -0x1dccc1dc08a67d6b, 0x4f2fad0116b900d1 } + }, + { + { -0x69d326e248c449c8, -0x19fa885503ed63f8, 0x6f619b39f3b61689, 0x3451995f2944ee81 }, + { 0x44beb24194ae4e54, 0x5f541c511857ef6c, -0x59e194d2c972fb68, 0x445484a4972ef7ab }, + { -0x6ead032f60158284, 0x4a816c94b0935cf6, 0x258e9aaa47285c40, 0x10b89ca6042893b7 } + }, +}, +{ + { + { -0x29832129862cb560, -0x33f4613f33b24c61, -0x5aca5ba91ca2e6f1, 0x2e05d9eaf61f6fef }, + { -0x64d5bd91c49b9fdb, 0x32127190385ce4cf, -0x5da3003d229215bb, 0x06409010bea8de75 }, + { -0x3bb86fe529e414a7, 0x661f19bce5dc880a, 0x24685482b7ca6827, 0x293c778cefe07f26 } + }, + { + { 0x16c795d6a11ff200, -0x348f2f1d4ea7ea37, -0x760d6cdf64ac6a4b, 0x50b8c2d031e47b4f }, + { -0x797f618ff8f96f6a, -0x5528a4ea1b1afe77, 0x07f35715a21a0147, 0x0487f3f112815d5e }, + { 0x48350c08068a4962, 0x6ffdd05351092c9a, 0x17af4f4aaf6fc8dd, 0x4b0553b53cdba58b } + }, + { + { -0x40fadee4d83ead2c, 0x5ec26849bd1af639, 0x5e0b2caa8e6fab98, 0x054c8bdd50bd0840 }, + { -0x639a0341e4cd0087, -0x148a1560fc4af065, -0x0312d59393f819fa, 0x35106cd551717908 }, + { 0x38a0b12f1dcf073d, 0x4b60a8a3b7f6a276, -0x012a53da2cbfb066, 0x72e82d5e5505c229 } + }, + { + { 0x00d9cdfd69771d02, 0x410276cd6cfbf17e, 0x4c45306c1cb12ec7, 0x2857bf1627500861 }, + { 0x6b0b697ff0d844c8, -0x44ed07a3268634b7, -0x2d5abe393e25f0e1, 0x7b7c242958ce7211 }, + { -0x60de6fc0fefe9762, -0x2886202c4079effb, -0x5edd11a0c214f0e5, 0x510df84b485a00d4 } + }, + { + { 0x24b3c887c70ac15e, -0x4f0c5aa8047e48ce, -0x64d321d01a8733e5, 0x4cf7ed0703b54f8e }, + { -0x5abecc446d885e06, 0x74ec3b6263991237, 0x1a3c54dc35d2f15a, 0x2d347144e482ba3a }, + { 0x6bd47c6598fbee0f, -0x61b8cc1d54aa41d3, 0x1093f624127610c5, 0x4e05e26ad0a1eaa4 } + }, + { + { 0x1833c773e18fe6c0, -0x1c3b8ee52c378d9b, 0x3bfd3c4f0116b283, 0x1955875eb4cd4db8 }, + { -0x2564949db4ace0e0, 0x429a760e77509abb, -0x24160add17dc3480, 0x618f1856880c8f82 }, + { 0x6da6de8f0e399799, 0x7ad61aa440fda178, -0x4cd327efa1ca9c23, 0x15f6beae2ae340ae } + }, + { + { -0x4565f0846dba1deb, -0x0c979ed22673f245, 0x2e84e4cbf220b020, 0x6ba92fe962d90eda }, + { -0x79d434f3ce13c59e, -0x7ef1d4baeec70c3e, 0x788ec4b839dac2a4, 0x28f76867ae2a9281 }, + { 0x3e4df9655884e2aa, -0x429d0424242b9a5b, -0x28a69355f2161adc, 0x6e8042ccb2b1b3d7 } + }, + { + { 0x1530653616521f7e, 0x660d06b896203dba, 0x2d3989bc545f0879, 0x4b5303af78ebd7b0 }, + { -0x0ef2c3d631d73592, -0x452cbabf0349f6c3, -0x18bd91285d15d2c1, 0x08af9d4e4ff298b9 }, + { 0x72f8a6c3bebcbde8, 0x4f0fca4adc3a8e89, 0x6fa9d4e8c7bfdf7a, 0x0dcf2d679b624eb7 } + }, +}, +{ + { + { 0x753941be5a45f06e, -0x2f8351129263a09b, 0x11776b9c72ff51b6, 0x17d2d1d9ef0d4da9 }, + { 0x3d5947499718289c, 0x12ebf8c524533f26, 0x0262bfcb14c3ef15, 0x20b878d577b7518e }, + { 0x27f2af18073f3e6a, -0x02c01ae628adef97, 0x22e3b72c3ca60022, 0x72214f63cc65c6a7 } + }, + { + { 0x1d9db7b9f43b29c9, -0x29fa7db5b0ae708b, -0x0d3f8d42ced0623c, 0x1f24ac855a1545b0 }, + { -0x4b1c80bfacf8596d, -0x5458eb28d0cc986b, -0x29042f588c89ef67, 0x5fdf48c58171cbc9 }, + { 0x24d608328e9505aa, 0x4748c1d10c1420ee, -0x38001ba3f904da5e, 0x00ba739e2ae395e6 } + }, + { + { -0x51bbd90a157744da, 0x360679d984973bfb, 0x5c9f030c26694e50, 0x72297de7d518d226 }, + { 0x592e98de5c8790d6, -0x1a40482cba3d5d21, 0x115a3b60f9b49922, 0x03283a3e67ad78f3 }, + { 0x48241dc7be0cb939, 0x32f19b4d8b633080, -0x2c2036f2fdd76cf8, 0x05e1296846271945 } + }, + { + { -0x52404437dbd3bab0, -0x4337f3132fcf7e27, -0x7bca99590a37206e, 0x78cf25d38258ce4c }, + { -0x457d114cd263b6a6, -0x311037030ed44684, -0x4fd254516c4a2e20, 0x39c00c9c13698d9b }, + { 0x15ae6b8e31489d68, -0x557ae35463d40f79, -0x3658a5680fb105fb, 0x006b52076b3ff832 } + }, + { + { -0x0a3481e94631f7d3, 0x3407f14c417abc29, -0x2b4c9431d40b5855, 0x7de2e9561a9f75ce }, + { 0x29e0cfe19d95781c, -0x497e20e7699cef1e, 0x57df39d370516b39, 0x4d57e3443bc76122 }, + { -0x218f2b0b495aa135, 0x4801527f5d85db99, -0x24363bbf2c11657f, 0x6b2a90af1a6029ed } + }, + { + { 0x77ebf3245bb2d80a, -0x27cfe4b8d046f865, -0x39b8190db3118ccd, 0x465812c8276c2109 }, + { 0x6923f4fc9ae61e97, 0x5735281de03f5fd1, -0x589b51bc19122ed3, 0x5fd8f4e9d12d3e4a }, + { 0x4d43beb22a1062d9, 0x7065fb753831dc16, 0x180d4a7bde2968d7, 0x05b32c2b1cb16790 } + }, + { + { -0x08035bd3852a7e6b, 0x3214286e4333f3cc, -0x493d62f2cbf46863, 0x31771a48567307e1 }, + { -0x373fa1332db25703, -0x5e30e553fa20107d, -0x2441100d8206329f, 0x3b5556a37b471e99 }, + { 0x32b0c524e14dd482, -0x124caeabe5d45b4a, -0x5c2e9fb7d7d4a50d, 0x4fc079d27a7336eb } + }, + { + { -0x23cb74bbf3793af3, 0x1337cbc9cc94e651, 0x6422f74d643e3cb9, 0x241170c2bae3cd08 }, + { 0x51c938b089bf2f7f, 0x2497bd6502dfe9a7, -0x00003f63877f1bad, 0x124567cecaf98e92 }, + { 0x3ff9ab860ac473b4, -0x0f6ee211feec1bcb, 0x4ae75060ebc6c4af, 0x3f8612966c87000d } + }, +}, +{ + { + { 0x529fdffe638c7bf3, -0x20d4619fc774b66b, -0x1fd84cb0e452fdb7, 0x7bc92fc9b9fa74ed }, + { 0x0c9c5303f7957be4, -0x5c3ce5df1f7a3ebb, -0x4f8de28e2f7affb0, 0x0aba390eab0bf2da }, + { -0x606810d17fe52607, -0x7c9682ab865025c6, -0x16f94c0042a694b0, 0x02672b37dd3fb8e0 } + }, + { + { -0x116458d6c673580b, -0x146359da85b7b625, 0x29eb29ce7ec544e1, 0x232ca21ef736e2c8 }, + { 0x48b2ca8b260885e4, -0x5bd794137d4cb3e4, -0x6c81e5d9e80a708c, 0x741d1fcbab2ca2a5 }, + { -0x409ebdc2dac034e9, 0x08803ceafa39eb14, -0x0e79fd2067ae3851, 0x0400f3a049e3414b } + }, + { + { 0x2efba412a06e7b06, 0x146785452c8d2560, -0x2068ec1429856e39, 0x32830ac7157eadf3 }, + { -0x5431fb89459e3aa5, 0x36a3d6d7c4d39716, 0x6eb259d5e8d82d09, 0x0c9176e984d756fb }, + { 0x0e782a7ab73769e8, 0x04a05d7875b18e2c, 0x29525226ebcceae1, 0x0d794f8383eba820 } + }, + { + { 0x7be44ce7a7a2e1ac, 0x411fd93efad1b8b7, 0x1734a1d70d5f7c9b, 0x0d6592233127db16 }, + { -0x00ca0a3461eae90c, -0x117fa4309b7551bb, -0x0f28c3d446c5610d, 0x097b0bf22092a6c2 }, + { -0x3b7454eade5628cd, -0x593d151529e544db, 0x625c6c1cc6cb4305, 0x7fc90fea93eb3a67 } + }, + { + { -0x3ad8214a63834dc3, -0x6aac6e96acd7bfb2, -0x29bc6d7e8330d386, 0x6ce97dabf7d8fa11 }, + { 0x0408f1fe1f5c5926, 0x1a8f2f5e3b258bf4, 0x40a951a2fdc71669, 0x6598ee93c98b577e }, + { 0x25b5a8e50ef7c48f, -0x149fcbee90d31ace, -0x3a18ae8c1ac21ac9, 0x73119fa08c12bb03 } + }, + { + { 0x7845b94d21f4774d, -0x409d0e93876848d9, 0x671857c03c56522b, 0x3cd6a85295621212 }, + { -0x12cfed6bac0e5b35, -0x4319de36370ac879, -0x0534d4ecc7411847, 0x3025798a9ea8428c }, + { 0x3fecde923aeca999, -0x4255a4ff9d173ed1, 0x67b99dfc96988ade, 0x3f52c02852661036 } + }, + { + { -0x6da74066113be93a, -0x5375afe8562d098f, 0x629549ab16dea4ab, 0x05d0e85c99091569 }, + { -0x00155b71d5ecae3a, 0x28624754fa7f53d7, 0x0b5ba9e57582ddf1, 0x60c0104ba696ac59 }, + { 0x051de020de9cbe97, -0x05f803a94af4308c, 0x378cec9f0f11df65, 0x36853c69ab96de4d } + }, + { + { 0x4433c0b0fac5e7be, 0x724bae854c08dcbe, -0x0e0db33bb9687065, 0x4a0aff6d62825fc8 }, + { 0x36d9b8de78f39b2d, 0x7f42ed71a847b9ec, 0x241cd1d679bd3fde, 0x6a704fec92fbce6b }, + { -0x16e804619ef6acff, -0x3efd206bfd5f6d08, -0x40f61d0a0599e6f5, 0x681109bee0dcfe37 } + }, +}, +{ + { + { -0x63e70305c9fb72ed, 0x29159db373899ddd, -0x2360caf4606d2f56, 0x26f57eee878a19d4 }, + { 0x559a0cc9782a0dde, 0x551dcdb2ea718385, 0x7f62865b31ef238c, 0x504aa7767973613d }, + { 0x0cab2cd55687efb1, 0x5180d162247af17b, -0x7a3ea5cbb0a5db99, 0x4041943d9dba3069 } + }, + { + { 0x4b217743a26caadd, 0x47a6b424648ab7ce, -0x34e2b085fc04361d, 0x12d931429800d019 }, + { -0x3c3f1145bc14336a, -0x728b6363d9156351, -0x26056a11e388333a, 0x1420a1d97684340f }, + { 0x00c67799d337594f, 0x5e3c5140b23aa47b, 0x44182854e35ff395, 0x1b4f92314359a012 } + }, + { + { 0x33cf3030a49866b1, 0x251f73d2215f4859, -0x547d55bfae210b0a, 0x5ff191d56f9a23f6 }, + { 0x3e5c109d89150951, 0x39cefa912de9696a, 0x20eae43f975f3020, 0x239b572a7f132dae }, + { -0x7e612bcc53d26f98, 0x2883ab795fc98523, -0x10ba8d7faa6c14c3, 0x020c526a758f36cb } + }, + { + { -0x16ce10a60fbd3377, 0x2c589c9d8e124bb6, -0x52371e755138a669, 0x452cfe0a5602c50c }, + { 0x779834f89ed8dbbc, -0x370d550623835b94, -0x56adb3235c1e4f8c, 0x02aacc4615313877 }, + { -0x795f085f9b878821, -0x443b9bd8f19f8361, -0x54e815da0e04ee37, 0x4cfb7d7b304b877b } + }, + { + { -0x1d79663d687610ee, 0x2b6ecd71df57190d, -0x3cbc37a813368f30, 0x5b1d4cbc434d3ac5 }, + { 0x72b43d6cb89b75fe, 0x54c694d99c6adc80, -0x473c55c8c11cb361, 0x14b4622b39075364 }, + { -0x4904d9ea33f560da, 0x3a4f0e2bb88dcce5, 0x1301498b3369a705, 0x2f98f71258592dd1 } + }, + { + { 0x2e12ae444f54a701, -0x0301c10f56342822, -0x314076f28a7ca220, 0x1d8062e9e7614554 }, + { 0x0c94a74cb50f9e56, 0x5b1ff4a98e8e1320, -0x65d533de7dcff099, 0x3a6ae249d806aaf9 }, + { 0x657ada85a9907c5a, 0x1a0ea8b591b90f62, -0x72f1e20420cb4b17, 0x298b8ce8aef25ff3 } + }, + { + { -0x7c858d15f5de9a22, 0x3fab07b40bcf79f6, 0x521636c77738ae70, 0x6ba6271803a7d7dc }, + { 0x2a927953eff70cb2, 0x4b89c92a79157076, -0x6be7ba85cf583096, 0x34b8a8404d5ce485 }, + { -0x3d91134a7c96cccb, -0x2a57ec209c4a0103, -0x5d6c55655b4dda8d, 0x71d62bdd465e1c6a } + }, + { + { -0x32d24a254e08a10b, -0x28806a30e94f9a0b, 0x14571fea3f49f085, 0x1c333621262b2b3d }, + { 0x6533cc28d378df80, -0x0924bc86f5f05b4c, -0x1c9ba00608fe25a6, 0x74d5f317f3172ba4 }, + { -0x57901aab9826357f, 0x398b7c752b298c37, -0x2592f76d1c539dc5, 0x4aebcc4547e9d98c } + }, +}, +{ + { + { 0x0de9b204a059a445, -0x1ea34b55b4e852f1, -0x1e4413ade0863aa9, 0x2633f1b9d071081b }, + { 0x53175a7205d21a77, -0x4f3fbbdd2c46cb2c, -0x52260db422a21524, 0x074f46e69f10ff8c }, + { -0x3e04be88fe7466f0, -0x5915df2393f01ec0, -0x299e0c18bcab3901, 0x5ecb72e6f1a3407a } + }, + { + { -0x01151ef917179669, -0x679ccc80672f6c7d, -0x6b8fb7f155f91411, 0x038b6898d4c5c2d0 }, + { -0x5aea5ce4dda604b2, 0x0960f3972bcac52f, -0x124ad01372cbab35, 0x382e2720c476c019 }, + { -0x0c6e3ae27531af5a, 0x3142d0b9ae2d2948, -0x24b2a5e580db3580, 0x21aeba8b59250ea8 } + }, + { + { 0x53853600f0087f23, 0x4c461879da7d5784, 0x6af303deb41f6860, 0x0a3c16c5c27c18ed }, + { 0x24f13b34cf405530, 0x3c44ea4a43088af7, 0x5dd5c5170006a482, 0x118eb8f8890b086d }, + { 0x17e49c17cc947f3d, -0x33391259553e2d85, -0x209f6d314f0f71aa, 0x4909b3e22c67c36b } + }, + { + { 0x59a16676706ff64e, 0x10b953dd0d86a53d, 0x5848e1e6ce5c0b96, 0x2d8b78e712780c68 }, + { -0x63637a159c01d177, -0x41e4506ef16bed14, -0x7084557579040185, 0x0fb17f9fef968b6c }, + { 0x79d5c62eafc3902b, 0x773a215289e80728, -0x3c7519bf1efedf47, 0x09ae23717b2b1a6d } + }, + { + { 0x10ab8fa1ad32b1d0, -0x165312e41d8874dc, -0x577a943fc8c216f1, 0x66f35ddddda53996 }, + { -0x4495e6d5b1b2f7c4, 0x34ace0630029e192, -0x67dba5a655054515, 0x6d9c8a9ada97faac }, + { -0x2d826504db668cdd, 0x1bb7e07ef6f01d2e, 0x2ba7472df52ecc7f, 0x03019b4f646f9dc8 } + }, + { + { -0x50f64deb194c2395, 0x3f7573b5ad7d2f65, -0x2fe62677eff5dc50, 0x392b63a58b5c35f7 }, + { 0x04a186b5565345cd, -0x111899ef433bee96, 0x689c73b478fb2a45, 0x387dcbff65697512 }, + { 0x4093addc9c07c205, -0x3a9a41ea0acd3c82, 0x63dbecfd1583402a, 0x61722b4aef2e032e } + }, + { + { -0x294f85aa7e34f1c4, 0x290ff006d9444969, 0x08680b6a16dcda1f, 0x5568d2b75a06de59 }, + { 0x0012aafeecbd47af, 0x55a266fb1cd46309, -0x0dfc1497f69838d4, 0x39633944ca3c1429 }, + { -0x72f34773e4c8301f, 0x05b6a5a3053818f3, -0x0d1643fb487826a7, 0x6beba1249add7f64 } + }, + { + { 0x5c3cecb943f5a53b, -0x633659e2f93f720e, -0x30459c657a76abb9, 0x5a845ae80df09fd5 }, + { 0x1d06005ca5b1b143, 0x6d4c6bb87fd1cda2, 0x6ef5967653fcffe7, 0x097c29e8c1ce1ea5 }, + { 0x4ce97dbe5deb94ca, 0x38d0a4388c709c48, -0x3bc1312b5e962f69, 0x0a1249fff7e587c3 } + }, +}, +{ + { + { 0x0b408d9e7354b610, -0x7f94cdaca457a492, -0x2419c5fcb5a75df9, 0x173bd9ddc9a1df2c }, + { 0x12f0071b276d01c9, -0x1847453a793b7390, 0x5308129b71d6fba9, 0x5d88fbf95a3db792 }, + { 0x2b500f1efe5872df, 0x58d6582ed43918c1, -0x1912d8713698c520, 0x06e1cd13b19ea319 } + }, + { + { 0x472baf629e5b0353, 0x3baa0b90278d0447, 0x0c785f469643bf27, 0x7f3a6a1a8d837b13 }, + { 0x40d0ad516f166f23, 0x118e32931fab6abe, 0x3fe35e14a04d088e, 0x3080603526e16266 }, + { -0x0819bbc6a2c27ff5, -0x6a572aaa36fe120a, 0x68cd7830592c6339, 0x30d0fded2e51307e } + }, + { + { -0x634b68e19747b8b0, -0x5f6a8dd6999b4431, 0x5c8de72672fa412b, 0x4615084351c589d9 }, + { -0x1fa6b2e50dedcc4d, 0x1bdbe78ef0cc4d9c, 0x6965187f8f499a77, 0x0a9214202c099868 }, + { -0x436fe63f51465fd2, 0x55c7110d16034cae, 0x0e6df501659932ec, 0x3bca0d2895ca5dfe } + }, + { + { -0x639771496133fe41, -0x0f437c5259bb7691, -0x35d26aa0a085601e, 0x4ea8b4038df28241 }, + { 0x40f031bc3c5d62a4, 0x19fc8b3ecff07a60, -0x67e7c25decf04abb, 0x5631deddae8f13cd }, + { 0x2aed460af1cad202, 0x46305305a48cee83, -0x6ede88bab60ee5a1, 0x24ce0930542ca463 } + }, + { + { 0x3fcfa155fdf30b85, -0x2d08e971c9c8d15c, -0x4d1f9b219b6d07bc, 0x549928a7324f4280 }, + { 0x1fe890f5fd06c106, -0x4a3b97caa277ef0e, -0x7d87f701917350c2, 0x41d4e3c28a06d74b }, + { -0x0d91cd589c11e5d2, -0x516e1b482da00216, -0x43c42cc42e80b297, 0x491b66dec0dcff6a } + }, + { + { 0x75f04a8ed0da64a1, -0x12ddd350981dd7b5, -0x7dcb5c86e084845c, 0x4cf6b8b0b7018b67 }, + { -0x670a4ec23815cd59, -0x1c2a073381e92468, -0x53f540ad340726b9, 0x08f338d0c85ee4ac }, + { -0x3c7c57de66e58c43, -0x54d843fe20cdf386, -0x3ec2cce47b888f9d, 0x530d4a82eb078a99 } + }, + { + { 0x6d6973456c9abf9e, 0x257fb2fc4900a880, 0x2bacf412c8cfb850, 0x0db3e7e00cbfbd5b }, + { 0x004c3630e1f94825, 0x7e2d78268cab535a, -0x38b7dcdc337b0075, 0x65ea753f101770b9 }, + { 0x3d66fc3ee2096363, -0x7e29d3809e4a3495, 0x0fbe044213443b1a, 0x02a4ec1921e1a1db } + }, + { + { -0x0a379e9d0e3086a1, 0x118c861926ee57f2, 0x172124851c063578, 0x36d12b5dec067fcf }, + { 0x5ce6259a3b24b8a2, -0x47a88533ba505f48, -0x33341917745f8fc9, 0x3d143c51127809bf }, + { 0x126d279179154557, -0x2a1b70a30387c5f6, 0x36bdb6e8df179bac, 0x2ef517885ba82859 } + }, +}, +{ + { + { 0x1ea436837c6da1e9, -0x063e7650e0464242, 0x303001fcce5dd155, 0x28a7c99ebc57be52 }, + { -0x7742bc732ee1f2b6, 0x30cb610d43ccf308, -0x1f65f1c86e6c8434, 0x4559135b25b1720c }, + { -0x47026c66172e6163, -0x6f7e6e3469dbdc01, -0x4d46b728b838bd5d, 0x37f33226d7fb44c4 } + }, + { + { 0x33912553c821b11d, 0x66ed42c241e301df, 0x066fcc11104222fd, 0x307a3b41c192168f }, + { 0x0dae8767b55f6e08, 0x4a43b3b35b203a02, -0x1c8da5917f507387, 0x0f7a7fd1705fa7a3 }, + { -0x7114a2f8914aa320, 0x2fc536bfaa0d925a, -0x417e7cf023493918, 0x556c7045827baf52 } + }, + { + { -0x46b46ffdd40bbbfa, -0x542bdc81006f4acc, 0x7600a960faf86d3a, 0x2f45abdac2322ee3 }, + { -0x71d4ae8cfd162749, -0x1c1add96db78eb18, -0x42b04288b3569f4b, 0x6f4b4199c5ecada9 }, + { 0x61af4912c8ef8a6a, -0x1a705b01bc0491a2, -0x4a5033a2902bd831, 0x6a5393281e1e11eb } + }, + { + { 0x0fff04fe149443cf, 0x53cac6d9865cddd7, 0x31385b03531ed1b7, 0x5846a27cacd1039d }, + { -0x0c25aec65a2e1177, -0x7ebaba83006c9678, 0x3f622fed00e188c4, 0x0f513815db8b5a3d }, + { 0x4ff5cdac1eb08717, 0x67e8b29590f2e9bc, 0x44093b5e237afa99, 0x0d414bed8708b8b2 } + }, + { + { -0x7e77956dd6b53618, 0x23162b45d55547be, -0x6b3043bbfc8ea67d, 0x50eb8fdb134bc401 }, + { -0x30497d9a02f18a0a, -0x1ba4c1d7446f18f9, 0x7242a8de9ff92c7a, 0x685b3201933202dd }, + { -0x3f48c139294ccf33, -0x7b1bb7f8ecd0500f, 0x732b7352c4a5dee1, 0x5d7c7cf1aa7cd2d2 } + }, + { + { 0x33d1013e9b73a562, -0x6da310a8b713d91f, -0x580319eb22b97fa8, 0x78b0fad41e9aa438 }, + { -0x50c4b94085b5505e, -0x4878fa13b2bf2bef, 0x114f0c6aca7c15e3, 0x3f364faaa9489d4d }, + { -0x40a95bce12fa4b78, -0x5acc199363b6a382, -0x179ad450780c9ae6, 0x0241800059d66c33 } + }, + { + { 0x28350c7dcf38ea01, 0x7c6cdbc0b2917ab6, -0x531830417a8f7d09, 0x4d2845aba2d9a1e0 }, + { -0x314f88015c85a41c, -0x249bd0fd1a5a1149, -0x3d192f3ab8ed8f48, 0x4771b65538e4529c }, + { -0x44ac801fbb8f8f22, -0x3458bbbc922aa821, -0x2c4a5cb8c9ff2435, 0x4aeabbe6f9ffd7f8 } + }, + { + { 0x6a2134bcc4a9c8f2, -0x040702e37531d1c9, 0x000ae3049911a0ba, 0x046e3a616bc89b9e }, + { 0x4630119e40d8f78c, -0x5fe5643ac38ef1ef, 0x486d2b258910dd79, 0x1e6c47b3db0324e5 }, + { 0x14e65442f03906be, 0x4a019d54e362be2a, 0x68ccdfec8dc230c7, 0x7cfb7e3faf6b861c } + }, +}, +{ + { + { -0x69114004cfa4d0af, -0x2c06c752776a6948, -0x0f0ad238b92a22db, 0x57968290bb3a0095 }, + { 0x4637974e8c58aedc, -0x4610dd04540fbe5c, -0x1e7a26a9167f8e76, 0x2f1b78fab143a8a6 }, + { -0x08e547bcf5df1eff, -0x0c6c9a72db0f13b9, -0x308af657911d112f, 0x7dc43e35dc2aa3e1 } + }, + { + { 0x5a782a5c273e9718, 0x3576c6995e4efd94, 0x0f2ed8051f237d3e, 0x044fb81d82d50a99 }, + { -0x7a69999a7782263d, -0x36f064ceb44facab, -0x391f720710df864f, 0x7ef72016758cc12f }, + { -0x3e20e73a56f81c27, 0x57b3371dce4c6359, -0x358fbacb4dfe44b7, 0x7f79823f9c30dd2e } + }, + { + { 0x6a9c1ff068f587ba, 0x0827894e0050c8de, 0x3cbf99557ded5be7, 0x64a9b0431c06d6f0 }, + { -0x7ccb2dc65c4aec18, -0x3ec98f2b46e05728, 0x12b54136f590bd33, 0x0a4e0373d784d9b4 }, + { 0x2eb3d6a15b7d2919, -0x4f4b095f2ac57dcb, 0x7156ce4389a45d47, 0x071a7d0ace18346c } + }, + { + { -0x33f3caaddf1ebbcf, 0x0d65950709b15141, -0x650a9de4df62a0ca, 0x7c69bcf7617755d3 }, + { -0x2cf8d255377845f5, 0x01262905bfa562ee, -0x30abcffd3f108975, 0x2c3bcc7146ea7e9c }, + { 0x07f0d7eb04e8295f, 0x10db18252f50f37d, -0x16ae565ce8e86729, 0x6f5a9a7322aca51d } + }, + { + { -0x18d62b145c26bb42, -0x7261f6bf7f875062, 0x4525567a47869c03, 0x02ab9680ee8d3b24 }, + { -0x745efff3d0be393b, -0x3b60863ef3010465, 0x4efa47703cc51c9f, 0x494e21a2e147afca }, + { -0x105b757a221af266, 0x219a224e0fb9a249, -0x05f6e0e226e10927, 0x6b5d76cbea46bb34 } + }, + { + { -0x1f06bee8e187dade, -0x0e19518bfc96c92d, 0x408b3ea2d0fcc746, 0x16fb869c03dd313e }, + { -0x77a8aa9313f3266c, 0x6472dc6f5cd01dba, -0x50fe96eb70bd4b89, 0x0ae333f685277354 }, + { 0x288e199733b60962, 0x24fc72b4d8abe133, 0x4811f7ed0991d03e, 0x3f81e38b8f70d075 } + }, + { + { 0x0adb7f355f17c824, 0x74b923c3d74299a4, -0x2a83c17434071509, 0x0ad3e2d34cdedc3d }, + { 0x7f910fcc7ed9affe, 0x545cb8a12465874b, -0x57c6812db4f3b8fc, 0x50510fc104f50993 }, + { 0x6f0c0fc5336e249d, 0x745ede19c331cfd9, -0x0d2902fff61101e4, 0x127c158bf0fa1ebe } + }, + { + { -0x215d703b51ae468c, 0x1d9973d3744dfe96, 0x6240680b873848a8, 0x4ed82479d167df95 }, + { -0x09e683bdd167865e, -0x5bb5222bad35c9b9, -0x64bec03eb4b15335, 0x354ef87d07ef4f68 }, + { -0x011c4add9f3a268b, 0x50352efceb41b0b8, -0x77f753cf56099ac4, 0x302d92d20539236d } + }, +}, +{ + { + { -0x6a847474f20ac3d0, 0x2a1c770a8e60f098, -0x4438598fcba86922, 0x22a48f9a90c99bc9 }, + { 0x4c59023fcb3efb7c, 0x6c2fcb99c63c2a94, -0x45be6f1d3c381f7c, 0x0e545daea51874d9 }, + { 0x6b7dc0dc8d3fac58, 0x5497cd6ce6e42bfd, 0x542f7d1bf400d305, 0x4159f47f048d9136 } + }, + { + { 0x748515a8bbd24839, 0x77128347afb02b55, 0x50ba2ac649a2a17f, 0x060525513ad730f1 }, + { 0x20ad660839e31e32, -0x07e1e42a7bfa41b0, -0x07f9bfa90b254397, 0x14d23dd4ce71b975 }, + { -0x0dc671f6755d807e, 0x6d7982bb89a1b024, -0x0596bf7bdeb22db4, 0x71ab966fa32301c3 } + }, + { + { -0x4ef775f8fd7f66ab, 0x43b273ea0b43c391, -0x3564985101f97913, 0x605eecbf8335f4ed }, + { 0x2dcbd8e34ded02fc, 0x1151f3ec596f22aa, -0x435daabcb1fcd726, 0x35768fbe92411b22 }, + { -0x7cdff59a93cbfbcf, -0x60328e98711a63d1, 0x75d4613f71300f8a, 0x7a912faf60f542f9 } + }, + { + { 0x253f4f8dfa2d5597, 0x25e49c405477130c, 0x00c052e5996b1102, 0x33cb966e33bb6c4a }, + { -0x4dfba7a1a123e5bd, -0x60f1e911a76838c4, 0x5b82c0ae4e70483c, 0x624a170e2bddf9be }, + { 0x597028047f116909, -0x7d753be3e1a9bb99, 0x70417dbde6217387, 0x721627aefbac4384 } + }, + { + { -0x02cf6843bef4d0de, -0x0e5fa2584a3057bc, 0x61289a1def57ca74, 0x245ea199bb821902 }, + { -0x682fc43c78c9522b, 0x2f1422afc532b130, 0x3aa68a057101bbc4, 0x4c946cf7e74f9fa7 }, + { -0x51235996872b8808, 0x1898ba3c29117fe1, -0x308c067c8df342a8, 0x67da12e6b8b56351 } + }, + { + { 0x2b7ef3d38ec8308c, -0x7d7028138e146b55, -0x7f83c4c93af9d543, 0x0cb64cb831a94141 }, + { 0x7067e187b4bd6e07, 0x6e8f0203c7d1fe74, -0x6c3955d0c737a5d0, 0x76297d1f3d75a78a }, + { 0x3030fc33534c6378, -0x469ca3a31abe179f, 0x15d9a9bed9b2c728, 0x49233ea3f3775dcb } + }, + { + { 0x7b3985fe1c9f249b, 0x4fd6b2d5a1233293, -0x314cba6be520b29e, 0x6987ff6f542de50c }, + { 0x629398fa8dbffc3a, -0x1ed01ad22ab24bab, -0x0c41ee20250dad6b, 0x628b140dce5e7b51 }, + { 0x47e241428f83753c, 0x6317bebc866af997, -0x2544a4bcc2e567d7, 0x074d8d245287fb2d } + }, + { + { 0x481875c6c0e31488, 0x219429b2e22034b4, 0x7223c98a31283b65, 0x3420d60b342277f9 }, + { -0x7cc82632bbf403cf, 0x729d2ca1af318fd7, -0x5fbf5b5b88d3df90, 0x46002ef03a7349be }, + { -0x055dc52150019a09, 0x78261ed45be0764c, 0x441c0a1e2f164403, 0x5aea8e567a87d395 } + }, +}, +{ + { + { 0x2dbc6fb6e4e0f177, 0x04e1bf29a4bd6a93, 0x5e1966d4787af6e8, 0x0edc5f5eb426d060 }, + { 0x7813c1a2bca4283d, -0x129d0f6e5e79c227, -0x513843473d97057a, 0x10e5d3b76f1cae4c }, + { 0x5453bfd653da8e67, -0x1623e113db5609bf, -0x4078d9c4fca875dd, 0x45b46c51361cba72 } + }, + { + { -0x3162b22275801c1c, -0x54ec9ba9899df1d0, 0x4b594f7bb30e9958, 0x5c1c0aef321229df }, + { -0x56bfd540ceb0805f, -0x1da80e2371730bb0, 0x1dbbd54b23a8be84, 0x2177bfa36dcb713b }, + { 0x37081bbcfa79db8f, 0x6048811ec25f59b3, 0x087a76659c832487, 0x4ae619387d8ab5bb } + }, + { + { 0x61117e44985bfb83, -0x031fb9d58e69ceca, -0x7c53cbb72bda6fb5, 0x75685abe5ba43d64 }, + { -0x72240955acbb5cd2, 0x7d88eab4b41b4078, 0x5eb0eb974a130d60, 0x1a00d91b17bf3e03 }, + { 0x6e960933eb61f2b2, 0x543d0fa8c9ff4952, -0x208d8aef85099a97, 0x135529b623b0e6aa } + }, + { + { -0x0a38e9431dd17c02, -0x4bd414e617f67a3f, -0x136259c8ebdab552, 0x5972ea051590a613 }, + { 0x18f0dbd7add1d518, -0x68608777303ee0ef, -0x78cd1e0f8eeb8a65, 0x79b5b81a65ca3a01 }, + { 0x0fd4ac20dc8f7811, -0x65652d6b53b2b058, -0x3fe4d29b4cc9fbcc, 0x4f7e9c95905f3bdb } + }, + { + { 0x71c8443d355299fe, -0x7432c4e324141529, -0x7f6db6610e5b6b9a, 0x1942eec4a144adc8 }, + { 0x62674bbc5781302e, -0x27adf0c6765223f1, -0x73d66651ac04263a, 0x31993ad92e638e4c }, + { 0x7dac5319ae234992, 0x2c1b3d910cea3e92, 0x553ce494253c1122, 0x2a0a65314ef9ca75 } + }, + { + { -0x30c9e532c3e386c6, 0x2f9ebcac5a35bc3b, 0x60e860e9a8cda6ab, 0x055dc39b6dea1a13 }, + { 0x2db7937ff7f927c2, -0x248be0f9e82f59cb, 0x5982f3a21155af76, 0x4cf6e218647c2ded }, + { -0x4ee6dd833d72a44a, 0x07e24ebc774dffab, -0x57c387311b5cd377, 0x121a307710aa24b6 } + }, + { + { -0x29a68ec1388b7c37, -0x77401f8847d46951, 0x289e28231097bcd3, 0x527bb94a6ced3a9b }, + { -0x1b24a2a160fcb569, -0x1eac03f6cfcb43d3, 0x460546919551d3b1, 0x333fc76c7a40e52d }, + { 0x563d992a995b482e, 0x3405d07c6e383801, 0x485035de2f64d8e5, 0x6b89069b20a7a9f7 } + }, + { + { 0x4082fa8cb5c7db77, 0x068686f8c734c155, 0x29e6c8d9f6e7a57e, 0x0473d308a7639bcf }, + { -0x7ed55fbe9d8fddf3, -0x66a5760506dba4b2, -0x00523b31af8d10fb, 0x23bc2103aa73eb73 }, + { -0x351186d9fca761fb, 0x2b4b421246dcc492, 0x02a1ef74e601a94f, 0x102f73bfde04341a } + }, +}, +{ + { + { 0x358ecba293a36247, -0x5070679d4d97029b, 0x412f7e9968a01c89, 0x5786f312cd754524 }, + { -0x4a5d2af3813df2c2, -0x39b422915f368d9d, 0x56e89052c1ff734d, 0x4929c6f72b2ffaba }, + { 0x337788ffca14032c, -0x0c6defd7bb80e11d, -0x74ebf8e0dce43353, 0x4c817b4bf2344783 } + }, + { + { 0x413ba057a40b4484, -0x45b3d1e5b0a095bd, 0x614ba0a5aee1d61c, 0x78a1531a8b05dc53 }, + { 0x0ff853852871b96e, -0x1ec160549f3c0e45, -0x1102a6acdacbbbfe, 0x0a37c37075b7744b }, + { 0x6cbdf1703ad0562b, -0x7130b7cf36dade5d, -0x25142cfc027bdb19, 0x72ad82a42e5ec56f } + }, + { + { -0x3c976c6e98fdb43d, -0x71962e92b6afd026, -0x030d13c31ba0b4d7, 0x065f669ea3b4cbc4 }, + { 0x3f9e8e35bafb65f6, 0x39d69ec8f27293a1, 0x6cb8cd958cf6a3d0, 0x1734778173adae6d }, + { -0x75ff5138aacd24b3, -0x47965b1bbc1ce44f, 0x4a0f8552d3a7f515, 0x19adeb7c303d7c08 } + }, + { + { -0x62fa4582bc3ce86c, 0x2470c8ff93322526, -0x7cdc2137e9e68bc8, 0x2852709881569b53 }, + { -0x38df349eac15265d, 0x55b2c97f512b636e, -0x4e1ca4a02bfd6f4f, 0x2fd9ccf13b530ee2 }, + { 0x07bd475b47f796b8, -0x2d384fecabd370ac, 0x2dbd23f43b24f87e, 0x6551afd77b0901d6 } + }, + { + { 0x68a24ce3a1d5c9ac, -0x44885cc2ef009b9f, 0x0f86ce4425d3166e, 0x56507c0950b9623b }, + { 0x4546baaf54aac27f, -0x090990134d5ba5d8, 0x582d1b5b562bcfe8, 0x44b123f3920f785f }, + { 0x1206f0b7d1713e63, 0x353fe3d915bafc74, 0x194ceb970ad9d94d, 0x62fadd7cf9d03ad3 } + }, + { + { 0x3cd7bc61e7ce4594, -0x3294ca564822d982, -0x5f7f5437bc9910d9, 0x6ec7c46f59c79711 }, + { -0x394a6984aa675f8c, 0x5efe91ce8e493e25, -0x2b48d3bab6d7f778, 0x20ef1149a26740c2 }, + { 0x2f07ad636f09a8a2, -0x79681931dbdfa183, -0x3f5103fa11ca5ec7, 0x15e80958b5f9d897 } + }, + { + { 0x4dd1ed355bb061c4, 0x42dc0cef941c0700, 0x61305dc1fd86340e, 0x56b2cc930e55a443 }, + { 0x25a5ef7d0c3e235b, 0x6c39c17fbe134ee7, -0x388b1ecbd23a3cd9, 0x021354b892021f39 }, + { 0x1df79da6a6bfc5a2, 0x02f3a2749fde4369, -0x4cdc260d325c6f59, 0x7be0847b8774d363 } + }, + { + { 0x1466f5af5307fa11, -0x7e8033821293f50e, 0x0a6de44ec3a4a3fb, 0x74071475bc927d0b }, + { -0x736633a574c0aa3d, 0x0611d7253fded2a0, -0x12d66a00c948f5ca, 0x1f699a54d78a2619 }, + { -0x188d6d0c8c181576, 0x296537d2cb045a31, 0x1bd0653ed3274fde, 0x2f9a2c4476bd2966 } + }, +}, +{ + { + { -0x5d4b251f4aaee366, 0x7ac860292bffff06, -0x67e0c8a20aafbdcc, 0x3f6bd725da4ea12d }, + { -0x14e7465480a8ba3a, 0x023a8aee5787c690, -0x48d8ed25d2085057, 0x36597d25ea5c013d }, + { 0x734d8d7b106058ac, -0x26bfa86190396fa1, 0x6466f8f99202932d, 0x7b7ecc19da60d6d0 } + }, + { + { 0x6dae4a51a77cfa9b, -0x7dd9c9ab185c79b0, 0x09bbffcd8f2d82db, 0x03bedc661bf5caba }, + { 0x78c2373c695c690d, -0x22dad199f9bd6f92, -0x6ae2bbbbb51ed42e, 0x4235ad7601743956 }, + { 0x6258cb0d078975f5, 0x492942549189f298, -0x5f354bdc1d1c911c, 0x0e7ce2b0cdf066a1 } + }, + { + { -0x0159012026b48f07, -0x0ecf3fae3e0345d3, 0x4882d47e7f2fab89, 0x615256138aeceeb5 }, + { -0x3b6b9bc53b737a5d, -0x02c9e20bc39ec653, 0x09db17dd3ae94d48, 0x666e0a5d8fb4674a }, + { 0x2abbf64e4870cb0d, -0x329a430f55ba7495, -0x6541b1458a1767a3, 0x7f0bc810d514dee4 } + }, + { + { -0x7c5362528c8dec60, -0x60090745d108d168, 0x311e2edd43ec6957, 0x1d3a907ddec5ab75 }, + { -0x46ff945bd90bec91, -0x7298c961a81fcfcb, -0x34372026b0b9c3d8, 0x0d1f8dbcf8eedbf5 }, + { -0x45e96ccec12f7e24, 0x29329fad851b3480, 0x0128013c030321cb, 0x00011b44a31bfde3 } + }, + { + { 0x16561f696a0aa75c, -0x3e408da3a7ad4296, 0x11a8dd7f9a7966ad, 0x63d988a2d2851026 }, + { 0x3fdfa06c3fc66c0c, 0x5d40e38e4dd60dd2, 0x7ae38b38268e4d71, 0x3ac48d916e8357e1 }, + { 0x00120753afbd232e, -0x16d431470227097d, -0x07e9964c7b18d46f, 0x33fad52b2368a066 } + }, + { + { -0x72d3372f3bdd3018, 0x072b4f7b05a13acb, -0x5c01491913095a91, 0x3cc355ccb90a71e2 }, + { 0x540649c6c5e41e16, 0x0af86430333f7735, -0x4d53032d0cfa18ba, 0x16c0f429a256dca7 }, + { -0x16496bbc6fc16ecf, -0x475b6b3485a9c832, -0x37832e5b45456dbc, 0x631eaf426bae7568 } + }, + { + { 0x47d975b9a3700de8, 0x7280c5fbe2f80552, 0x53658f2732e45de1, 0x431f2c7f665f80b5 }, + { -0x4c16fbef25990161, -0x7a22b4ad93e91a5a, -0x43c2689ee106407d, 0x5599648b1ea919b5 }, + { -0x29fd9cbb7a7084e7, 0x14ab352fa1ea514a, -0x76ffbbe5df6f5629, 0x7b04715f91253b26 } + }, + { + { -0x4c893d7f3b19453a, -0x68f12c2292e264f5, -0x4f656aa7baf406bc, 0x48d0acfa57cde223 }, + { -0x7c1242d7530951bd, -0x79ca837482a3854c, -0x3fbfb8964814d3bc, 0x59b37bf5c2f6583f }, + { -0x49f0d91b8254198f, -0x0e2e5e689dd0c5c9, 0x4208ce7ee9960394, 0x16234191336d3bdb } + }, +}, +{ + { + { -0x7ad22e02c2a87442, 0x2b65ce72c3286108, 0x658c07f4eace2273, 0x0933f804ec38ab40 }, + { -0x0e651538cc59c511, 0x2c7fba5d4442454e, 0x5da87aa04795e441, 0x413051e1a4e0b0f5 }, + { -0x5854968672b69b8a, -0x7ede5521034a5438, -0x5a23ed1084ac6b8e, 0x07fd47065e45351a } + }, + { + { 0x304211559ae8e7c3, -0x0d7e4dd66bb77d5b, -0x75ec53d1c87daf1c, 0x014afa0954ba48f4 }, + { -0x37a7c3c2da72d433, 0x17029a4daf60b73f, -0x05f03629be95c87f, 0x1c1e5fba38b3fb23 }, + { -0x34ce68ffe44c9994, 0x330060524bffecb9, 0x293711991a88233c, 0x291884363d4ed364 } + }, + { + { -0x0462c83c43e54915, 0x02be14534d57a240, -0x0b28cbea075a1e0a, 0x5964f4300ccc8188 }, + { 0x033c6805dc4babfa, 0x2c15bf5e5596ecc1, 0x1bc70624b59b1d3b, 0x3ede9850a19f0ec5 }, + { -0x1bb5dcead2f69800, 0x5c08c55970866996, -0x20d249f5b9500492, 0x579155c1f856fd89 } + }, + { + { -0x4a0e949cf7e8185a, -0x7f7396dcc3caefda, 0x324a983b54cef201, 0x53c092084a485345 }, + { -0x69cdb122ed1f3611, 0x468b878df2420297, 0x199a3776a4f573be, 0x1e7fbcf18e91e92a }, + { -0x2d2beb7e0e345041, 0x231d2db6716174e5, 0x0b7d7656e2a55c98, 0x3e955cd82aa495f6 } + }, + { + { -0x54c60c109e44c5c1, -0x714bff9ad146e6c2, -0x4a219133c73ee08c, 0x654d7e9626f3c49f }, + { -0x1b70aca1c12eabcd, -0x2f8a96d5f28d8f5d, 0x40fbd21daade6387, 0x14264887cf4495f5 }, + { -0x1a9b3022a382d315, -0x7d11502128c83347, 0x6107db62d1f9b0ab, 0x0b6baac3b4358dbb } + }, + { + { 0x204abad63700a93b, -0x41ffdc2c25886c8d, -0x27a0fcb99cc548f7, 0x00496dc490820412 }, + { 0x7ae62bcb8622fe98, 0x47762256ceb891af, 0x1a5a92bcf2e406b4, 0x7d29401784e41501 }, + { 0x1c74b88dc27e6360, 0x074854268d14850c, -0x5eba0484c1f234d0, 0x10843f1b43803b23 } + }, + { + { -0x2a9098d21cdb9765, -0x2e2575124c6b567f, -0x2284a7016e973013, 0x7ce246cd4d56c1e8 }, + { -0x3a06fbaac89d8923, -0x31a6ea72289ba327, -0x6d09a2aee2c994c7, 0x11574b6e526996c4 }, + { -0x470bcf71807f41ad, 0x5f3cb8cb34a9d397, 0x18a961bd33cc2b2c, 0x710045fb3a9af671 } + }, + { + { -0x5fc0379dfa629662, 0x2370cfa19a619e69, -0x3b01c4edd07dc215, 0x1d1b056fa7f0844e }, + { 0x73f93d36101b95eb, -0x0510cc86b090bb7a, 0x5651735f8f15e562, 0x7fa3f19058b40da1 }, + { 0x1bc64631e56bf61f, -0x2c8654ef91ac7d5d, 0x4d58c57e0540168d, 0x566256628442d8e4 } + }, +}, +{ + { + { -0x22b66329e00c79c0, 0x29cd9bc3063625a0, 0x51e2d8023dd73dc3, 0x4a25707a203b9231 }, + { -0x461b662109d9800a, 0x7772ca7b742c0843, 0x23a0153fe9a4f2b1, 0x2cdfdfecd5d05006 }, + { 0x2ab7668a53f6ed6a, 0x304242581dd170a1, 0x4000144c3ae20161, 0x5721896d248e49fc } + }, + { + { 0x285d5091a1d0da4e, 0x4baa6fa7b5fe3e08, 0x63e5177ce19393b3, 0x03c935afc4b030fd }, + { 0x0b6e5517fd181bae, -0x6fdd9d60d4469c4c, 0x5509bce932064625, 0x578edd74f63c13da }, + { -0x668d8939b6d4f3c3, 0x47ccc2c4dfe205fc, -0x232d647b229dc5c4, 0x3ec2ab590288c7a2 } + }, + { + { -0x58dec5f651cd2e35, 0x0f2b87df40f5c2d5, 0x0baea4c6e81eab29, 0x0e1bf66c6adbac5e }, + { -0x5e5f2d841b278447, -0x5674b2149ec6e513, -0x665f222f8c34647d, 0x2dd5c25a200fcace }, + { -0x1d542a1686d37782, 0x1a020018cb926d5d, -0x404596324551a0e2, 0x730548b35ae88f5f } + }, + { + { -0x7fa4f6b45e291ccc, -0x40c10e88f6cac0e7, 0x423f06cb0622702b, 0x585a2277d87845dd }, + { -0x3bcaae5c34574712, 0x65a26f1db2115f16, 0x760f4f52ab8c3850, 0x3043443b411db8ca }, + { -0x5e75a07dcc2b769e, 0x6698c4b5ec78257f, -0x5871905ac8c1be01, 0x7656278950ef981f } + }, + { + { -0x1e8f8c5c15793063, 0x3a8cfbb707155fdc, 0x4853e7fc31838a8e, 0x28bbf484b613f616 }, + { 0x38c3cf59d51fc8c0, -0x64122d02faf9490e, 0x26bf109fab570e8f, 0x3f4160a8c1b846a6 }, + { -0x0d9ed0a390ec9384, -0x50152ef80922ee42, 0x527e9ad213de6f33, 0x1e79cb358188f75d } + }, + { + { 0x77e953d8f5e08181, -0x7b5af3bbd6622127, -0x2393d2f379bada1b, 0x478ab52d39d1f2f4 }, + { 0x013436c3eef7e3f1, -0x7d7495800161ef08, 0x7ff908e5bcf9defc, 0x65d7951b3a3b3831 }, + { 0x66a6a4d39252d159, -0x1a221e4378e537f9, -0x47d394bf593e3691, 0x16d87a411a212214 } + }, + { + { -0x045b2a1d2ab1fa7d, -0x1de05028d1426606, 0x497ac2736ee9778f, 0x1f990b577a5a6dde }, + { -0x4c4281a5bdf99deb, -0x78641c32f3a5db3f, 0x57c05db1d6f994b7, 0x28f87c8165f38ca6 }, + { -0x5ccbb152e417082a, 0x7d1e50ebacea798f, 0x77c6569e520de052, 0x45882fe1534d6d3e } + }, + { + { -0x275366d66bc3901c, -0x4a060e9e5c7c6d5e, 0x2699db13bec89af3, 0x7dcf843ce405f074 }, + { 0x6669345d757983d6, 0x62b6ed1117aa11a6, 0x7ddd1857985e128f, 0x688fe5b8f626f6dd }, + { 0x6c90d6484a4732c0, -0x2adebc0235a9cd67, -0x4c41d73c6ea2391f, 0x6739687e7327191b } + }, +}, +{ + { + { -0x731a552f363468e1, 0x1156aaa99fd54a29, 0x41f7247015af9b78, 0x1fe8cca8420f49aa }, + { -0x609a3a15dff7eb31, -0x7bfac91e965ce8c0, -0x74f12ec6da374b53, 0x0080dbafe936361d }, + { 0x72a1848f3c0cc82a, 0x38c560c2877c9e54, 0x5004e228ce554140, 0x042418a103429d71 } + }, + { + { 0x58e84c6f20816247, -0x724d4d491c90286d, -0x688e7da9e2b7b27b, 0x0822024f8632abd7 }, + { -0x766215ae540c00a1, -0x646c5798d03d2746, 0x2c38cb97be6ebd5c, 0x114d578497263b5d }, + { -0x4cfe448394e4135d, 0x55393f6dc6eb1375, -0x6ef2d7ef68491b15, 0x1ad4548d9d479ea3 } + }, + { + { -0x5f901992f016012d, -0x578cc5bfe3a786f7, 0x30d14d800df98953, 0x41ce5876c7b30258 }, + { -0x32a5825fc765b703, -0x4c705b556587c8e2, -0x392689e4d3247194, 0x35cf51dbc97e1443 }, + { 0x59ac3bc5d670c022, -0x151983ef64ee6bfa, -0x6867420f4c87d026, 0x651e3201fd074092 } + }, + { + { -0x5a845b5fe1035162, 0x769f4beedc308a94, -0x2e0ef114c9fc34d2, 0x4099ce5e7e441278 }, + { -0x29c27b7c10cf3a31, 0x4cd4b4962361cc0c, -0x116f1aff5b7bd954, 0x0af51d7d18c14eeb }, + { 0x1ac98e4f8a5121e9, 0x7dae9544dbfa2fe0, -0x7cdf55f229bcf207, 0x667282652c4a2fb5 } + }, + { + { -0x5257491fd6b924dd, 0x1c0ce51a7b253ab7, -0x7bb737a59922b7a5, 0x7f1fc025d0675adf }, + { -0x78b9de0b27943655, -0x4ab38441a9019016, 0x077a24257fadc22c, 0x1ab53be419b90d39 }, + { -0x2711e4e7ce615956, 0x004d88083a21f0da, 0x3bd6aa1d883a4f4b, 0x4db9a3a6dfd9fd14 } + }, + { + { -0x26a4ff4434488398, -0x22437b956e0e87b7, 0x7cf700aebe28d9b3, 0x5ce1285c85d31f3e }, + { -0x73184dc44663f8ab, 0x35c5d6edc4f50f7a, 0x7e1e2ed2ed9b50c3, 0x36305f16e8934da1 }, + { 0x31b6972d98b0bde8, 0x7d920706aca6de5b, -0x198cef076f759a61, 0x50fac2a6efdf0235 } + }, + { + { 0x295b1c86f6f449bc, 0x51b2e84a1f0ab4dd, -0x3ffe34cf5571aae3, 0x6a28d35944f43662 }, + { -0x0c2c560ca477f0a6, -0x1213faf324fc183e, -0x576967e0060f4e5e, 0x49a4ae2bac5e34a4 }, + { 0x28bb12ee04a740e0, 0x14313bbd9bce8174, 0x72f5b5e4e8c10c40, 0x7cbfb19936adcd5b } + }, + { + { -0x7186c58533c91920, -0x0605485c82a79113, 0x3a4f9692bae1f4e4, 0x1c14b03eff5f447e }, + { -0x5cee223d947686d3, 0x1b30b4c6da512664, 0x0ca77b4ccf150859, 0x1de443df1b009408 }, + { 0x19647bd114a85291, 0x57b76cb21034d3af, 0x6329db440f9d6dfa, 0x5ef43e586a571493 } + }, +}, +{ + { + { -0x5992336237f3e540, -0x685fa30be4c75bca, -0x58140c416a24283a, 0x7da0b8f68d7e7dab }, + { -0x1087dfebc7a98a5a, -0x5d9b60cf55025618, 0x4cd1eb505cdfa8cb, 0x46115aba1d4dc0b3 }, + { -0x2bf0e6ac3c4a258a, 0x1dac6f7321119e9b, 0x03cc6021feb25960, 0x5a5f887e83674b4b } + }, + { + { -0x6169d72c5f59bc47, -0x4a3c34ff193cdf9c, -0x64acfd7683d213ce, 0x43e37ae2d5d1c70c }, + { -0x709cfe308f5ec2ef, -0x303147eacaf22f3c, -0x08fd682b5b435b82, 0x3669b656e44d1434 }, + { 0x387e3f06eda6e133, 0x67301d5199a13ac0, -0x42a52707c9d9c7ef, 0x6a21e6cd4fd5e9be } + }, + { + { -0x10bed6ed99664d1d, 0x71d30847708d1301, 0x325432d01182b0bd, 0x45371b07001e8b36 }, + { -0x0e39e8f5cfb919a1, 0x58712a2a00d23524, 0x69dbbd3c8c82b755, 0x586bf9f1a195ff57 }, + { -0x5924f772a10786f5, 0x5278f0dc610937e5, -0x53fcb62d9e5e9148, 0x0eafb03790e52179 } + }, + { + { 0x5140805e0f75ae1d, -0x13fd041cd99d33d0, 0x2cebdf1eea92396d, 0x44ae3344c5435bb3 }, + { -0x69faaa3ec8b7fbd1, 0x219a41e6820baa11, 0x1c81f73873486d0c, 0x309acc675a02c661 }, + { -0x630d7646445abc12, -0x0c89f162a5368ebe, 0x1d82e5c64f9360aa, 0x62d5221b7f94678f } + }, + { + { 0x7585d4263af77a3c, -0x205184ee0116ebb3, -0x5af98f7fa608e6c3, 0x14f29a5383922037 }, + { 0x524c299c18d0936d, -0x37944a9375f3e5f4, -0x5c8afad124b579cf, 0x5c0efde4bc754562 }, + { -0x208e8123da4d280b, 0x21f970db99b53040, -0x256dcb483c12b39e, 0x5e72365c7bee093e } + }, + { + { 0x7d9339062f08b33e, 0x5b9659e5df9f32be, -0x5300c252e0614203, 0x70b20555cb7349b7 }, + { 0x575bfc074571217f, 0x3779675d0694d95b, -0x65f5c8440be6e1cd, 0x77f1104c47b4eabc }, + { -0x41aeec3aaaeed3b4, 0x6688423a9a881fcd, 0x446677855e503b47, 0x0e34398f4a06404a } + }, + { + { 0x18930b093e4b1928, 0x7de3e10e73f3f640, -0x0bcde8258cc6a291, 0x6f8aded6ca379c3e }, + { -0x4982dd26c1314218, 0x09b3e84127822f07, 0x743fa61fb05b6d8d, 0x5e5405368a362372 }, + { -0x1cbfedc202484d66, 0x487b97e1a21ab291, -0x066982fd02196b62, 0x780de72ec8d3de97 } + }, + { + { 0x671feaf300f42772, -0x708d14d5d573be56, 0x29a17fd797373292, 0x1defc6ad32b587a6 }, + { 0x0ae28545089ae7bc, 0x388ddecf1c7f4d06, 0x38ac15510a4811b8, 0x0eb28bf671928ce4 }, + { -0x50a441e510ae6a59, 0x148c1277917b15ed, 0x2991f7fb7ae5da2e, 0x467d201bf8dd2867 } + }, +}, +{ + { + { 0x745f9d56296bc318, -0x66ca7f2b27ead19b, -0x4f1a4ec0a7c61632, 0x51fc2b28d43921c0 }, + { 0x7906ee72f7bd2e6b, 0x05d270d6109abf4e, -0x72a301ba46be575c, 0x44c218671c974287 }, + { 0x1b8fd11795e2a98c, 0x1c4e5ee12b6b6291, 0x5b30e7107424b572, 0x6e6b9de84c4f4ac6 } + }, + { + { 0x6b7c5f10f80cb088, 0x736b54dc56e42151, -0x3d49df5a3910663c, 0x5f4c802cc3a06f42 }, + { -0x200da031b4e21eaf, -0x27be3f381ee3bfdb, 0x2554b3c854749c87, 0x2d292459908e0df9 }, + { -0x649a370e82f8ad26, -0x77e31cc738811800, -0x3c4aeb0fa49d061d, 0x66ed5dd5bec10d48 } + }, + { + { -0x0f520c363435fb83, -0x7e3c4d340baad095, -0x3025eed2bb8ca06d, 0x1f23a0c77e20048c }, + { 0x7d38a1c20bb2089d, -0x7f7ccb1e69332bee, -0x3b58f47393682ced, 0x2eacf8bc03007f20 }, + { -0x0dcab9841a43ea90, 0x03d2d9020dbab38c, 0x27529aa2fcf9e09e, 0x0840bef29d34bc50 } + }, + { + { -0x32ab1f9480c81b15, -0x733ea0780a169336, -0x47db744f2ca68232, 0x246affa06074400c }, + { 0x796dfb35dc10b287, 0x27176bcd5c7ff29d, 0x7f3d43e8c7b24905, 0x0304f5a191c54276 }, + { 0x37d88e68fbe45321, -0x79f68ab73f28afce, 0x4e9b13ef894a0d35, 0x25a83cac5753d325 } + }, + { + { -0x60f099d6c6ad491e, 0x33db5e0e0934267b, -0x00badad429f60124, 0x06be10f5c506e0c9 }, + { 0x10222f48eed8165e, 0x623fc1234b8bcf3a, 0x1e145c09c221e8f0, 0x7ccfa59fca782630 }, + { 0x1a9615a9b62a345f, 0x22050c564a52fecc, -0x585d877ad743f202, 0x5e82770a1a1ee71d } + }, + { + { -0x17fd17f5bdcc638c, 0x34175166a7fffae5, 0x34865d1f1c408cae, 0x2cca982c605bc5ee }, + { 0x35425183ad896a5c, -0x1798c5041872ad0a, 0x2c66f25f92a35f64, 0x09d04f3b3b86b102 }, + { -0x02d2a2cae6824192, 0x207c2eea8be4ffa3, 0x2613d8db325ae918, 0x7a325d1727741d3e } + }, + { + { -0x132d82fe81d5f896, -0x28779760e9c9b6a2, 0x52a61af0919233e5, 0x2a479df17bb1ae64 }, + { -0x2fc946442e92021e, -0x5dfaa8a83b6857d7, -0x71933699580ed999, 0x4d3b1a791239c180 }, + { -0x61a11171cc24d8f0, 0x189854ded6c43ca5, -0x5be3dd3a6d8e7ec8, 0x27ad5538a43a5e9b } + }, + { + { -0x34a5829c71b8f884, -0x7248ac9edf5e3fa7, 0x549e1e4d8bedfdcc, 0x080153b7503b179d }, + { 0x2746dd4b15350d61, -0x2fc03437116ade49, -0x1791c9a5ec798d36, 0x510e987f7e7d89e2 }, + { -0x2259626cf5c12c1d, 0x3d386ef1cd60a722, -0x37e852a74255b11a, 0x23be8d554fe7372a } + }, +}, +{ + { + { -0x43e10b42a9851857, 0x3f624cb2d64498bd, -0x1bef9b2dd3e0b138, 0x2ef9c5a5ba384001 }, + { -0x6a016e658b10b053, 0x3a827becf6a308a2, -0x69b1fe2cf65b84ff, 0x71c43c4f5ba3c797 }, + { -0x4902920905618b33, -0x0e7d87431b50d986, -0x7daa4c2f0e1066f2, 0x5a758ca390c5f293 } + }, + { + { -0x731f6e74e29e236c, -0x7212c9b9657ecf9a, -0x2b1957d65017552d, 0x0a738027f639d43f }, + { -0x5d48d8ef26b9db6b, 0x3aa8c6d2d57d5003, -0x1c2bff405f4b7836, 0x2dbae244b3eb72ec }, + { -0x67f0b5d0a8001e34, 0x00670d0de1839843, 0x105c3f4a49fb15fd, 0x2698ca635126a69c } + }, + { + { 0x2e3d702f5e3dd90e, -0x61c0f6e71b2dac7a, 0x5e773ef6024da96a, 0x3c004b0c4afa3332 }, + { -0x189ace77cd4f4588, 0x381831f7925cff8b, 0x08a81b91a0291fcc, 0x1fb43dcc49caeb07 }, + { -0x6556b953f90b47d5, 0x1ca284a5a806c4f3, 0x3ed3265fc6cd4787, 0x6b43fd01cd1fd217 } + }, + { + { -0x4a38bda7c189f10d, 0x75dc52b9ee0ab990, -0x40ebd83df8d46dc1, 0x73420b2d6ff0d9f0 }, + { -0x3858a2b4b9683abc, 0x15fdf848df0fffbf, 0x2868b9ebaa46785a, 0x5a68d7105b52f714 }, + { -0x50d30934617ae1fa, -0x70a6c6ec39ddc73c, -0x2575476966040c8d, 0x3db5632fea34bc9e } + }, + { + { 0x2e4990b1829825d5, -0x12151478c165766f, -0x110fc2c6b38fb508, 0x59197ea495df2b0e }, + { -0x0b9111d408a22628, 0x0d17b1f6396759a5, 0x1bf2d131499e7273, 0x04321adf49d75f13 }, + { 0x04e16019e4e55aae, -0x1884bc8581d06d17, -0x3831d23e90ea655c, 0x45eafdc1f4d70cc0 } + }, + { + { -0x49f1b9db30334e13, 0x59dbc292bd5c0395, 0x31a09d1ddc0481c9, 0x3f73ceea5d56d940 }, + { 0x698401858045d72b, 0x4c22faa2cf2f0651, -0x6be5c99a94ddd23a, 0x5a5eebc80362dade }, + { -0x4858402ef5b1723a, -0x41a8ff81bb364cc7, 0x60c1207f1557aefa, 0x26058891266218db } + }, + { + { 0x4c818e3cc676e542, 0x5e422c9303ceccad, -0x13f833354bed60f8, 0x0dedfa10b24443b8 }, + { 0x59f704a68360ff04, -0x3c26c021899e190c, -0x7ce4d58ced78caaf, 0x54ad0c2e4e615d57 }, + { -0x11c4982a47d4add6, 0x36f163469fa5c1eb, -0x5a4b2d0d913e602d, 0x62ecb2baa77a9408 } + }, + { + { -0x6df8d7c95049d78c, 0x5fcd5e8579e104a5, 0x5aad01adc630a14a, 0x61913d5075663f98 }, + { -0x1a1286ad9eead4c3, 0x4962357d0eddd7d1, 0x7482c8d0b96b4c71, 0x2e59f919a966d8be }, + { 0x0dc62d361a3231da, -0x05b8a7cd6bdffd90, 0x02d801513f9594ce, 0x3ddbc2a131c05d5c } + }, +}, +{ + { + { -0x048ca53dffb5ca2f, 0x31de0f433a6607c3, 0x7b8591bfc528d599, 0x55be9a25f5bb050c }, + { 0x3f50a50a4ffb81ef, -0x4e1fcaf6c40bdf41, -0x645571e33955d330, 0x32239861fa237a40 }, + { 0x0d005acd33db3dbf, 0x0111b37c80ac35e2, 0x4892d66c6f88ebeb, 0x770eadb16508fbcd } + }, + { + { -0x0e2c497e5faf8e47, 0x2207659a3592ff3a, 0x5f0169297881e40e, 0x16bedd0e86ba374e }, + { -0x7bae061fa1b17623, -0x3f9cfd004386c6c9, 0x5d22749556a6495c, 0x09a6755ca05603fb }, + { 0x5ecccc4f2c2737b5, 0x43b79e0c2dccb703, 0x33e008bc4ec43df3, 0x06c1b840f07566c0 } + }, + { + { 0x69ee9e7f9b02805c, -0x34007d75ab82e9c0, 0x3d93a869b2430968, 0x46b7b8cd3fe26972 }, + { 0x7688a5c6a388f877, 0x02a96c14deb2b6ac, 0x64c9f3431b8c2af8, 0x3628435554a1eed6 }, + { -0x167edf7901811420, 0x4cba6be72f515437, 0x1d04168b516efae9, 0x5ea1391043982cb9 } + }, + { + { 0x6f2b3be4d5d3b002, -0x5013cc2695f63780, 0x035f73a4a8bcc4cc, 0x22c5b9284662198b }, + { 0x49125c9cf4702ee1, 0x4520b71f8b25b32d, 0x33193026501fef7e, 0x656d8997c8d2eb2b }, + { -0x34a73701bcc276c7, -0x765f34d1957281b0, 0x79ca955309fbbe5a, 0x0c626616cd7fc106 } + }, + { + { -0x70203c86040bab4f, 0x45a5a970f1a4b771, -0x536de108452ca6eb, 0x42d088dca81c2192 }, + { 0x1ffeb80a4879b61f, 0x6396726e4ada21ed, 0x33c7b093368025ba, 0x471aa0c6f3c31788 }, + { -0x7025f0c85fe9ae67, 0x0adadb77c8a0e343, 0x20fbfdfcc875e820, 0x1cf2bea80c2206e7 } + }, + { + { -0x67d291e5fd3fbed1, -0x6f05b37c24a71702, 0x01c2f5bcdcb18bc0, 0x686e0c90216abc66 }, + { -0x3d220e214c9dfd54, -0x6d5a01f62d1d855b, 0x7d1648f6fc09f1d3, 0x74c2cc0513bc4959 }, + { 0x1fadbadba54395a7, -0x4be5fd5f51f25996, -0x40e60a67445c83f9, 0x6a12b8acde48430d } + }, + { + { 0x793bdd801aaeeb5f, 0x00a2a0aac1518871, -0x175c8c5ce0dec94c, 0x48aab888fc91ef19 }, + { -0x072515e0c62b6a27, 0x592c190e525f1dfc, -0x247342fb3666e2e5, 0x11f7fda3d88f0cb7 }, + { 0x041f7e925830f40e, 0x002d6ca979661c06, -0x79236006d4fb95d2, 0x760360928b0493d1 } + }, + { + { -0x4bcef71a96a5f4fb, 0x6cb00ee8ad37a38b, 0x5edad6eea3537381, 0x3f2602d4b6dc3224 }, + { 0x21bb41c6120cf9c6, -0x154d55ed21325a65, -0x3e58d2fdf55b74cc, 0x215d4d27e87d3b68 }, + { -0x374db849a4350e64, 0x49779dc3b1b2c652, -0x765e7f442a131d1e, 0x13f098a3cec8e039 } + }, +}, +{ + { + { -0x0c55a85dd86944ec, -0x77c5454864f825df, -0x1ab41de7ce5fc6e4, 0x5ee7fb38d83205f9 }, + { -0x6523f00631a13ab5, 0x039c2a6b8c2f130d, 0x028007c7f0f89515, 0x78968314ac04b36b }, + { 0x538dfdcb41446a8e, -0x5a530256bcb6c807, 0x46af908d263c8c78, 0x61d0633c9bca0d09 } + }, + { + { -0x525cd74307038c21, -0x117b96a2590fc804, 0x637fb4db38c2a909, 0x5b23ac2df8067bdc }, + { 0x63744935ffdb2566, -0x3a42947687f49745, 0x6f1b3280553eec03, 0x6e965fd847aed7f5 }, + { -0x652d46ac117fad85, -0x1770e65505219273, 0x0e711704150e82cf, 0x79b9bbb9dd95dedc } + }, + { + { -0x2e66825171608c8c, -0x5fcd5d073044f7ea, -0x329345ed92bba0f6, 0x1ba811460accb834 }, + { -0x144caabf95ced93e, -0x2d9c7c5797373c6d, 0x6c0c6429e5b97a82, 0x5065f158c9fd2147 }, + { 0x708169fb0c429954, -0x1eb9ff5328913099, 0x2eaab98a70e645ba, 0x3981f39e58a4faf2 } + }, + { + { -0x37ba205a92199022, -0x1ead5affd3bfb7c6, -0x162d1e9c384b09ce, 0x30f4452edcbc1b65 }, + { 0x18fb8a7559230a93, 0x1d168f6960e6f45d, 0x3a85a94514a93cb5, 0x38dc083705acd0fd }, + { -0x7a92d87d3a8a68c0, -0x05ecba9606634134, -0x77bb038c3f15b18f, 0x632d9a1a593f2469 } + }, + { + { -0x40f602ee12f37b59, 0x63f071810d9f693a, 0x21908c2d57cf8779, 0x3a5a7df28af64ba2 }, + { -0x094494ea47f8345a, 0x1823c7dfbc54f0d7, -0x44e268fc91d698f5, 0x0b24f48847ed4a57 }, + { -0x23252b41aee41539, -0x5bac7f8a12d9330e, -0x1e630060ffa0659b, 0x34fcf74475481f63 } + }, + { + { -0x5a44e25487305568, 0x5ceda267190b72f2, -0x6cf636eef56d9f72, 0x0119a3042fb374b0 }, + { -0x3e681fb387689836, -0x478eb234c726b983, 0x55de888283f95fa8, 0x3d3bdc164dfa63f7 }, + { 0x67a2d89ce8c2177d, 0x669da5f66895d0c1, -0x0a9a671a4d7d5d50, 0x56c088f1ede20a73 } + }, + { + { 0x581b5fac24f38f02, -0x56f41601451cf343, -0x65de96fd75306d10, 0x038b7ea48359038f }, + { 0x336d3d1110a86e17, -0x280c77cdf48a4d06, -0x06eacc89daf8d678, 0x09674c6b99108b87 }, + { -0x60b107de66ce9008, 0x2f49d282eaa78d4f, 0x0971a5ab5aef3174, 0x6e5e31025969eb65 } + }, + { + { 0x3304fb0e63066222, -0x04caf976785345c1, -0x42e6db8873ef9e5d, 0x3058ad43d1838620 }, + { -0x4e939d0a781a6c05, 0x4999eddeca5d3e71, -0x4b6e3e1feb33c193, 0x08f5114789a8dba8 }, + { 0x323c0ffde57663d0, 0x05c3df38a22ea610, -0x423875425366b066, 0x26549fa4efe3dc99 } + }, +}, +{ + { + { 0x04dbbc17f75396b9, 0x69e6a2d7d2f86746, -0x39bf62660ac1543a, 0x606175f6332e25d2 }, + { 0x738b38d787ce8f89, -0x49d9a71dbe865773, 0x30738c9cf151316d, 0x49128c7f727275c9 }, + { 0x4021370ef540e7dd, 0x0910d6f5a1f1d0a5, 0x4634aacd5b06b807, 0x6a39e6356944f235 } + }, + { + { 0x1da1965774049e9d, -0x0432915e6701cad5, -0x4e3432af33adc95a, 0x1f5ec83d3f9846e2 }, + { -0x6932a9bf206f0c19, 0x6c3a760edbfa25ea, 0x24f3ef0959e33cc4, 0x42889e7e530d2e58 }, + { -0x7104dc3ccd73348b, -0x50bd5df822789117, 0x20fbdadc5dfae796, 0x241e246b06bf9f51 } + }, + { + { 0x7eaafc9a6280bbb8, 0x22a70f12f403d809, 0x31ce40bb1bfc8d20, 0x2bc65635e8bd53ee }, + { 0x29e68e57ad6e98f6, 0x4c9260c80b462065, 0x3f00862ea51ebb4b, 0x5bc2c77fb38d9097 }, + { -0x172a23605694526d, -0x1a704e8221e6b824, 0x681532ea65185fa3, 0x1fdd6c3b034a7830 } + }, + { + { -0x63ec595ad2270857, 0x2dbb1f8c3efdcabf, -0x69e1cdbfa1f7084b, 0x48c8a121bbe6c9e5 }, + { 0x0a64e28c55dc18fe, -0x1c206166cc661423, 0x79ac432370e2e652, 0x35ff7fc33ae4cc0e }, + { -0x03bea583a69b9bbb, -0x2ddb4d283ed749eb, 0x6035c9c905fbb912, 0x42d7a91274429fab } + }, + { + { -0x565b76b86cc25a44, 0x4a58920ec2e979ec, -0x69277fffec1a53b4, 0x453692d74b48b147 }, + { 0x4e6213e3eaf72ed3, 0x6794981a43acd4e7, -0x00ab8321914af735, 0x6fed19dd10fcb532 }, + { -0x2288a26657aa6391, -0x0bd5debf20ffc1dc, 0x5223e229da928a66, 0x063f46ba6d38f22c } + }, + { + { 0x39843cb737346921, -0x58b804f8c7376bb9, -0x34727fce5dbacf82, 0x67810f8e6d82f068 }, + { -0x2d2dbd76a0ac996c, -0x35cc5d3abd6c64d4, -0x67905259382246a4, 0x5a152c042f712d5d }, + { 0x3eeb8fbcd2287db4, 0x72c7d3a301a03e93, 0x5473e88cbd98265a, 0x7324aa515921b403 } + }, + { + { -0x52dc092517dcab35, 0x6962502ab6571a6d, -0x649ae9c91c71c82f, 0x5cac5005d1a3312f }, + { -0x7a86bd0b93c34172, -0x5e2c9b4eb8cf3fba, 0x1c8ed914d23c41bf, 0x0838e161eef6d5d2 }, + { -0x733eab33161c66fc, 0x5b3a040b84de6846, -0x3b2759e34e41a292, 0x40fb897bd8861f02 } + }, + { + { -0x1a8127b8a54ef89f, 0x71435e206fd13746, 0x342f824ecd025632, 0x4b16281ea8791e7b }, + { -0x7b3a556f9d21c85f, 0x421da5000d1d96e1, 0x788286306a9242d9, 0x3c5e464a690d10da }, + { -0x2e3efe2af47ecc7f, -0x2119f0ee891197d8, 0x0cb68893383f6409, 0x6183c565f6ff484a } + }, +}, +{ + { + { -0x24b97ab650c09992, -0x288030fb0eb5f15b, 0x3df23ff7a4ba0c47, 0x3a10dfe132ce3c85 }, + { 0x741d5a461e6bf9d6, 0x2305b3fc7777a581, -0x2baa8b5d9b8b2c27, 0x1926e1dc6401e0ff }, + { -0x1f80b17515e83160, 0x2fd515463a1fc1fd, 0x175322fd31f2c0f1, 0x1fa1d01d861e5d15 } + }, + { + { 0x38dcac00d1df94ab, 0x2e712bddd1080de9, 0x7f13e93efdd5e262, 0x73fced18ee9a01e5 }, + { -0x337faa6b82a667ce, 0x1e4656da37f15520, -0x6609088bb1fa6ce0, 0x773563bc6a75cf33 }, + { 0x06b1e90863139cb3, -0x5b6c25983a5fc133, -0x72883137529c76ce, 0x1f426b701b864f44 } + }, + { + { -0x0e81ca376e5edaae, -0x48947eaca8a1638a, -0x057cbf90f2648dc2, 0x0b76bb1b3fa7e438 }, + { -0x1036d9b3be6ee3ff, -0x0e5c4847e85dd3db, 0x5875da6bf30f1447, 0x4e1af5271d31b090 }, + { 0x08b8c1f97f92939b, -0x41988e342bbb5492, 0x22e5646399bb8017, 0x7b6dd61eb772a955 } + }, + { + { 0x5730abf9ab01d2c7, 0x16fb76dc40143b18, -0x7993419a5f344d7f, 0x53fa9b659bff6afe }, + { -0x48523e17af0cc26e, 0x7998fa4f608cd5cf, -0x5269d2427203a425, 0x703e9bceaf1d2f4f }, + { 0x6c14c8e994885455, -0x7bc5a2999a512b1b, 0x181bb73ebcd65af1, 0x398d93e5c4c61f50 } + }, + { + { -0x3c78839f2d181c0e, 0x3b34aaa030828bb1, 0x283e26e7739ef138, 0x699c9c9002c30577 }, + { 0x1c4bd16733e248f3, -0x4261ed78ea40f5a1, -0x2bc0730f5ef4fc8a, 0x53b09b5ddf191b13 }, + { -0x0cf958dca6b90e34, -0x6de8e74a331a2683, 0x28cdd24781b4e975, 0x51caf30c6fcdd907 } + }, + { + { 0x737af99a18ac54c7, -0x6fcc87233ae34cf1, 0x2b89bc334ce10cc7, 0x12ae29c189f8e99a }, + { -0x59f458bd898b1ff6, 0x630e8570a17a7bf3, 0x3758563dcf3324cc, 0x5504aa292383fdaa }, + { -0x56613f34e0f2fe31, 0x0dd1efcc3a34f7ae, 0x55ca7521d09c4e22, 0x5fd14fe958eba5ea } + }, + { + { 0x3c42fe5ebf93cb8e, -0x412057aec92ba9a1, -0x1f0f7a6177bddf18, 0x7dd73f960725d128 }, + { -0x4a23d220d7ba54d4, 0x069491b10a7fe993, 0x4daaf3d64002e346, 0x093ff26e586474d1 }, + { -0x4ef2db0197fa67d7, 0x75730672dbaf23e5, 0x1367253ab457ac29, 0x2f59bcbc86b470a4 } + }, + { + { 0x7041d560b691c301, -0x7adfe4c0522818e2, 0x16c2e16311335585, 0x2aa55e3d010828b1 }, + { -0x7c7b82bd66e8eca1, -0x52e46ee0a982fc29, 0x7e7748d9be77aad1, 0x5458b42e2e51af4a }, + { -0x12ae6d19f3f8bbb1, 0x42c54e2d74421d10, 0x352b4c82fdb5c864, 0x13e9004a8a768664 } + }, +}, +{ + { + { 0x1e6284c5806b467c, -0x3a09668418a29f85, -0x749826a74c872d9e, 0x3d88d66a81cd8b70 }, + { -0x344a4aaa93fcd401, -0x208e6e48d6d685c6, -0x3e008cd952127e45, 0x71ade8bb68be03f5 }, + { -0x7489856cdfb12877, 0x762fcacb9fa0ae2a, 0x771febcc6dce4887, 0x343062158ff05fb3 } + }, + { + { -0x031de6f8d584ce4c, 0x4d7adc75aa578016, 0x0ec276a687479324, 0x6d6d9d5d1fda4beb }, + { -0x1fa25e581e0a40b7, 0x26457d6dd4736092, 0x77dcb07773cc32f6, 0x0a5d94969cdd5fcd }, + { 0x22b1a58ae9b08183, -0x026a2f8e3ea3c775, -0x567edc897af5fae9, 0x33384cbabb7f335e } + }, + { + { 0x33bc627a26218b8d, -0x157f4de03857f39f, -0x6ba74ed4e8c1611a, 0x076247be0e2f3059 }, + { 0x3c6fa2680ca2c7b5, 0x1b5082046fb64fda, -0x14accb63abce2922, 0x5278b38f6b879c89 }, + { 0x52e105f61416375a, -0x136850c97a54145c, 0x26e6b50623a67c36, 0x5cf0e856f3d4fb01 } + }, + { + { -0x415131cec24cbd58, -0x345c9ca47bd24812, -0x177399df7e80ec11, 0x1b9438aa4e76d5c6 }, + { -0x0936978ce517354c, 0x5e20741ecb4f92c5, 0x2da53be58ccdbc3e, 0x2dddfea269970df7 }, + { -0x75af8881e990fce6, 0x067b39f10fb7a328, 0x1925c9a6010fbd76, 0x6df9b575cc740905 } + }, + { + { -0x13203ca4b73521bf, 0x6a88471fb2328270, 0x740a4a2440a01b6a, 0x471e5796003b5f29 }, + { 0x42c1192927f6bdcf, -0x706e6e85bfc29e36, -0x23e3a5997461e09f, 0x1596047804ec0f8d }, + { -0x2569444c5312c854, 0x7a2423b5e9208cea, 0x24cc5c3038aebae2, 0x50c356afdc5dae2f } + }, + { + { -0x30126320e4ce469c, -0x0b79567a735ae50d, 0x14897265ea8c1f84, 0x784a53dd932acc00 }, + { 0x09dcbf4341c30318, -0x1145f9ee7ce7e232, -0x3e863f3123e1d65f, 0x1dbf7b89073f35b0 }, + { 0x2d99f9df14fc4920, 0x76ccb60cc4499fe5, -0x5becd3441a30fffd, 0x3f93d82354f000ea } + }, + { + { -0x1553ed2e861eb688, -0x006dc00c441400a2, 0x4af663e40663ce27, 0x0fd381a811a5f5ff }, + { -0x7e7c189761fb317b, 0x678fb71e04465341, -0x526dfa7099771254, 0x5da350d3532b099a }, + { -0x0da953135bc920ac, 0x108b6168ae69d6e8, 0x20d986cb6b5d036c, 0x655957b9fee2af50 } + }, + { + { -0x423ebf642ffd2f54, 0x66660245b5ccd9a6, -0x7dce823b05217a14, 0x02fe934b6ad7df0d }, + { -0x51574f8056fdfcf1, -0x077389950b9c2ebd, 0x15b083663c787a60, 0x08eab1148267a4a8 }, + { -0x10a30eff3048158c, 0x22897633a1cb42ac, -0x2b31f3ab310d7a1e, 0x30408c048a146a55 } + }, +}, +{ + { + { -0x44d1ff36e6c47881, -0x131c576f1f23af95, -0x130c483fc9219b61, 0x5f46040898de9e1a }, + { 0x739d8845832fcedb, -0x05c729365194079d, 0x32bc0dcab74ffef7, 0x73937e8814bce45e }, + { -0x46fc8ee9d6840b73, -0x562ec4dd2b0f97cc, -0x1e68eaa8b969423a, 0x2cf8a4e891d5e835 } + }, + { + { 0x2cb5487e17d06ba2, 0x24d2381c3950196b, -0x289a637e7a6875d0, 0x7a6f7f2891d6a4f6 }, + { 0x6d93fd8707110f67, -0x22b3f62c83c74ab7, 0x7cb16a4cc2736a86, 0x2049bd6e58252a09 }, + { 0x7d09fd8d6a9aef49, -0x0f119f41a4c246f5, 0x4c21b52c519ebfd4, 0x6011aadfc545941d } + }, + { + { 0x63ded0c802cbf890, -0x042f6735f2009556, 0x624d0afdb9b6ed99, 0x69ce18b779340b1e }, + { 0x5f67926dcf95f83c, 0x7c7e856171289071, -0x295e180c667085a5, 0x6fc5cc1b0b62f9e0 }, + { -0x2e10aad74d678635, -0x22e551c32b816f6e, 0x127e0442189f2352, 0x15596b3ae57101f1 } + }, + { + { 0x09ff31167e5124ca, 0x0be4158bd9c745df, 0x292b7d227ef556e5, 0x3aa4e241afb6d138 }, + { 0x462739d23f9179a2, -0x007cedce68292231, 0x1307deb553f2148a, 0x0d2237687b5f4dda }, + { 0x2cc138bf2a3305f5, 0x48583f8fa2e926c3, 0x083ab1a25549d2eb, 0x32fcaa6e4687a36c } + }, + { + { 0x3207a4732787ccdf, 0x17e31908f213e3f8, -0x2a4d132809f269b2, 0x746f6336c2600be9 }, + { 0x7bc56e8dc57d9af5, 0x3e0bd2ed9df0bdf2, -0x553feb21dd101b5d, 0x4627e9cefebd6a5c }, + { 0x3f4af345ab6c971c, -0x1d77148d66bc8ce1, 0x33596a8a0344186d, 0x7b4917007ed66293 } + }, + { + { 0x54341b28dd53a2dd, -0x55e86fa420bd03c1, 0x0ff592d94dd2f8f4, 0x1d03620fe08cd37d }, + { 0x2d85fb5cab84b064, 0x497810d289f3bc14, 0x476adc447b15ce0c, 0x122ba376f844fd7b }, + { -0x3dfdcd325d4b1aac, -0x612f02bdeea2e781, 0x2eabb4be7dd479d9, 0x02c70bf52b68ec4c } + }, + { + { -0x531acd40ba728d1f, 0x5be768e07cb73cb5, 0x56cf7d94ee8bbde7, 0x6b0697e3feb43a03 }, + { -0x5d7813b4a2f4d045, 0x415c5790074882ca, -0x1fbb59e13e2f7ea4, 0x26334f0a409ef5e0 }, + { -0x49370fb5209d5c40, 0x3ef000ef076da45d, -0x636346a7b60f2d57, 0x1cc37f43441b2fae } + }, + { + { -0x2899a90e36315147, 0x1c5b15f818e5656a, 0x26e72832844c2334, 0x3a346f772f196838 }, + { 0x508f565a5cc7324f, -0x2f9e3b3f1af956de, -0x04e75424a3ba53e7, 0x6c6809c10380314a }, + { -0x2d2aaeed1d259538, -0x1642fcce4e17ae13, -0x69f8b92271398d9e, 0x05911b9f6ef7c5d0 } + }, +}, +{ + { + { 0x01c18980c5fe9f94, -0x329a98968e902a38, -0x7e9fba3c2e6a5f7a, 0x6e2b7f3266cc7982 }, + { -0x162328a949c800d3, -0x13b3cb7036780f3c, -0x312a6d7a0c043849, 0x3305354793e1ea87 }, + { -0x337fdb97083ca971, -0x6216457de668b34d, -0x5448dd634a47eca0, 0x44e2017a6fbeba62 } + }, + { + { -0x7807d30c49359133, 0x580f893e18f4a0c2, 0x058930072604e557, 0x6cab6ac256d19c1d }, + { -0x3b3d58bcab25488c, -0x71a2b3c3b150fce6, -0x4893dc2dbd7c70e9, 0x749a098f68dce4ea }, + { -0x23201f5fd33e21a0, 0x032665ff51c5575b, 0x2c0c32f1073abeeb, 0x6a882014cd7b8606 } + }, + { + { -0x2eee2e8350b01492, 0x050bba42b33aa4a3, 0x17514c3ceeb46c30, 0x54bedb8b1bc27d75 }, + { -0x5ad56d015b8b804b, -0x23ed5bb6e05a5477, -0x27d256b447b85b32, 0x4d77edce9512cc4e }, + { 0x77c8e14577e2189c, -0x5c1b909500663bbb, 0x3144dfc86d335343, 0x3a96559e7c4216a9 } + }, + { + { 0x4493896880baaa52, 0x4c98afc4f285940e, -0x10b558645babb74a, 0x5278c510a57aae7f }, + { 0x12550d37f42ad2ee, -0x74871ffb675e040b, 0x5d53078233894cb2, 0x02c84e4e3e498d0c }, + { -0x5ab22f8bd6b3f46c, -0x0aa2b94720e7004a, -0x0f90133a72517c9a, 0x588657668190d165 } + }, + { + { -0x40a7cb0fc21da33d, -0x47783751297eab6a, 0x5105221a9481e892, 0x6760ed19f7723f93 }, + { -0x2b88edcee5108ee9, 0x50343101229e92c7, 0x7a95e1849d159b97, 0x2449959b8b5d29c9 }, + { 0x669ba3b7ac35e160, 0x2eccf73fba842056, 0x1aec1f17c0804f07, 0x0d96bc031856f4e7 } + }, + { + { -0x4e2acb4f338afa1f, 0x32cd003416c35288, -0x34c95a7ff89d3d63, 0x5bfe69b9237a0bf8 }, + { 0x3318be7775c52d82, 0x4cb764b554d0aab9, -0x5430c2d83388c26f, 0x3bf4d1848123288a }, + { 0x183eab7e78a151ab, -0x44166f3666f6c89d, -0x008e8291b5381ccb, 0x4c5cddb325f39f88 } + }, + { + { 0x57750967e7a9f902, 0x2c37fdfc4f5b467e, -0x4d9e99c5ce8845ba, 0x3a375e78dc2d532b }, + { -0x3f0948b29e6f5915, 0x20ea81a42db8f4e4, -0x5742908268cea8a0, 0x33b1d60262ac7c21 }, + { -0x7ebe18d0d2b22216, -0x191501679d39f838, 0x23c28458573cafd0, 0x46b9476f4ff97346 } + }, + { + { 0x1215505c0d58359f, 0x2a2013c7fc28c46b, 0x24a0a1af89ea664e, 0x4400b638a1130e1f }, + { 0x0c1ffea44f901e5c, 0x2b0b6fb72184b782, -0x1a78006efeeb2478, 0x37130f364785a142 }, + { 0x3a01b76496ed19c3, 0x31e00ab0ed327230, 0x520a885783ca15b1, 0x06aab9875accbec7 } + }, +}, +{ + { + { 0x5349acf3512eeaef, 0x20c141d31cc1cb49, 0x24180c07a99a688d, 0x555ef9d1c64b2d17 }, + { -0x3ecc667c0a20f145, -0x3f0c8a70aed3b354, 0x2cf1130a0bb398e1, 0x6b3cecf9aa270c62 }, + { 0x36a770ba3b73bd08, 0x624aef08a3afbf0c, 0x5737ff98b40946f2, 0x675f4de13381749d } + }, + { + { -0x5ed00926c4254ce3, 0x0725d80f9d652dfe, 0x019c4ff39abe9487, 0x60f450b882cd3c43 }, + { 0x0e2c52036b1782fc, 0x64816c816cad83b4, -0x2f234226969bf8c2, 0x13d99df70164c520 }, + { 0x014b5ec321e5c0ca, 0x4fcb69c9d719bfa2, 0x4e5f1c18750023a0, 0x1c06de9e55edac80 } + }, + { + { -0x002ad4bf00929656, 0x34530b18dc4049bb, 0x5e4a5c2fa34d9897, 0x78096f8e7d32ba2d }, + { -0x66f085295cc13b1e, 0x6608f938be2ee08e, -0x635ebc3a9cd7baeb, 0x4cf38a1fec2db60d }, + { -0x5f55559af205a319, -0x063b61d5b74ab874, 0x4f09cc7d7003725b, 0x373cad3a26091abe } + }, + { + { -0x0e41570476224453, 0x3bcb2cbc61aeaecb, -0x70a75844e0647263, 0x21547eda5112a686 }, + { -0x4d6b9cb27d360a84, 0x1fcbfde124934536, -0x6163b24cbe7324a6, 0x0040f3d9454419fc }, + { -0x210216c602a6792d, -0x0bd8d376aef5c7f4, -0x48d45bf844cee647, 0x63550a334a254df4 } + }, + { + { -0x6445a7ba8dab84b7, -0x0cfa39051d3bf720, 0x60e8fa69c734f18d, 0x39a92bafaa7d767a }, + { 0x6507d6edb569cf37, 0x178429b00ca52ee1, -0x1583ff6f149429a3, 0x3eea62c7daf78f51 }, + { -0x62db38ec196cd8b2, 0x5f63857768dbd375, 0x70525560eb8ab39a, 0x68436a0665c9c4cd } + }, + { + { 0x1e56d317e820107c, -0x3ad997bb7bf5169b, -0x3e1f5e39cdf00386, 0x5373669c91611472 }, + { -0x43fdca17dfd0c0d9, -0x38a3ff1d9b068a50, -0x6e5b162a5c73dbea, 0x17b6e7f68ab789f9 }, + { 0x5d2814ab9a0e5257, -0x6f70df7b36354c04, -0x50350a77a4d2e136, 0x1cb4b5a678f87d11 } + }, + { + { 0x6b74aa62a2a007e7, -0x0cee1f4f0f8e384f, 0x5707e438000be223, 0x2dc0fd2d82ef6eac }, + { -0x499b3f94c6b50394, 0x0c88de2498da5fb1, 0x4f8d03164bcad834, 0x330bca78de7434a2 }, + { -0x67d1007beee68bb2, -0x0696a169d4f8b8dc, -0x3a753eb04036ac05, 0x3c31be1b369f1cf5 } + }, + { + { -0x3e97436c0634bd8e, -0x51478ee038312468, 0x7f0e52aa34ac8d7a, 0x41cec1097e7d55bb }, + { -0x4f0b79b2f76b7512, 0x07dc19ee91ba1c6f, 0x7975cdaea6aca158, 0x330b61134262d4bb }, + { -0x0869e6285d927f76, -0x44e02b61e261ea93, 0x73d7c36cdba1df27, 0x26b44cd91f28777d } + }, +}, +{ + { + { -0x50bb7bd24fd7a0c9, -0x78ace76fb8103721, -0x6a8b1f6e07df6866, 0x0e378d6069615579 }, + { 0x300a9035393aa6d8, 0x2b501131a12bb1cd, 0x7b1ff677f093c222, 0x4309c1f8cab82bad }, + { -0x26056e8e7cf8a5ab, 0x4bdb5ad26b009fdc, 0x7829ad2cd63def0e, 0x078fc54975fd3877 } + }, + { + { -0x1dffb4a447cc5676, 0x44775dec2d4c3330, 0x3aa244067eace913, 0x272630e3d58e00a9 }, + { -0x782042ebd77870d3, 0x134636dd1e9421a1, 0x4f17c951257341a3, 0x5df98d4bad296cb8 }, + { -0x0c98702f1336f4ac, -0x0ffeba64edfbca67, 0x26725fbc3758b89b, 0x4325e4aa73a719ae } + }, + { + { -0x12db9d6530960a63, 0x2a4a1ccedd5abbf4, 0x3535ca1f56b2d67b, 0x5d8c68d043b1b42d }, + { 0x657dc6ef433c3493, 0x65375e9f80dbf8c3, 0x47fd2d465b372dae, 0x4966ab79796e7947 }, + { -0x11ccd2b21c4bd4f6, -0x27b1a5d4e95b9fe4, 0x78243877078ba3e4, 0x77ed1eb4184ee437 } + }, + { + { 0x185d43f89e92ed1a, -0x4fb5e11501b8e63a, 0x499fbe88a6f03f4f, 0x5d8b0d2f3c859bdd }, + { -0x402b1ec0dfe7c660, -0x5110001dc1c20e9f, -0x49a4fb0f94a2e01d, 0x52e085fb2b62fbc0 }, + { 0x124079eaa54cf2ba, -0x28db9a14ffe4d919, 0x6843bcfdc97af7fd, 0x0524b42b55eacd02 } + }, + { + { -0x43e72352647d6154, 0x23ae7d28b5f579d0, -0x3cb9edd596c7bdcd, 0x1a6110b2e7d4ac89 }, + { -0x02f2a2411babb850, 0x6cec351a092005ee, -0x665b87bba98a8635, 0x59d242a216e7fa45 }, + { 0x4f833f6ae66997ac, 0x6849762a361839a4, 0x6985dec1970ab525, 0x53045e89dcb1f546 } + }, + { + { -0x7b25c32172ba01ee, -0x42bd3de71bbb1d2e, -0x57ae6987e081ca68, 0x7642c93f5616e2b2 }, + { -0x34744cb928acac25, -0x03034db451aee1de, -0x345b72bf2af51911, 0x26e3bae5f4f7cb5d }, + { 0x2323daa74595f8e4, -0x219773747a85414c, 0x3fc48e961c59326e, 0x0b2e73ca15c9b8ba } + }, + { + { 0x0e3fbfaf79c03a55, 0x3077af054cbb5acf, -0x2a3aadba24c21c61, 0x015e68c1476a4af7 }, + { -0x2944bbd73e80afda, -0x614d8ddc04a56359, -0x1c845afce6e639bc, 0x21ce380db59a6602 }, + { -0x3e2ad7addff995c8, -0x6a9fc1adca8f510d, -0x7cd9a658dd9475b3, 0x5dd689091f8eedc9 } + }, + { + { 0x1d022591a5313084, -0x35d2b55129d8f78e, -0x795ed47ad0f402e0, 0x56e6c439ad7da748 }, + { -0x34537b21402c37aa, 0x1624c348b35ff244, -0x48077235a26352f9, 0x3b0e574da2c2ebe8 }, + { -0x38fb00b6bd42451a, 0x5e21ade2b2de1f79, -0x16a24c0ca9ad0528, 0x0822b5378f08ebc1 } + }, +}, +{ + { + { -0x1e480d6c9d8cfc7d, 0x4b5279ffebca8a2c, -0x25038875402becec, 0x7deb10149c72610f }, + { 0x51f048478f387475, -0x4da2430b634134c4, -0x6554edbb2660dfab, 0x2c709e6c1c10a5d6 }, + { -0x349d509578991186, 0x66cbec045553cd0e, 0x588001380f0be4b5, 0x08e68e9ff62ce2ea } + }, + { + { 0x2f2d09d50ab8f2f9, -0x5346de723aa6dc21, 0x4a8f342673766cb9, 0x4cb13bd738f719f5 }, + { 0x34ad500a4bc130ad, -0x72c724b6c2f42b64, -0x5da3c267aff57642, 0x2f1f3f87eeba3b09 }, + { -0x087b738a1aea49b6, -0x5a6afe4524b56fc8, -0x3df2cec0c08ae4b0, 0x19a1e353c0ae2ee8 } + }, + { + { -0x4bde8d322a694243, -0x6c1fbabc671103c0, -0x604eacb84bbef64b, 0x736bd3990266ae34 }, + { 0x7d1c7560bafa05c3, -0x4c1e5f5f391aa19f, -0x1cad68e73f299b8d, 0x41546b11c20c3486 }, + { -0x7aacd2af6ccb4c4c, 0x46fd114b60816573, -0x33a0a0cfbda37c8b, 0x412295a2b87fab5c } + }, + { + { 0x2e655261e293eac6, -0x7ba56dfcdecc5325, 0x460975cb7900996b, 0x0760bb8d195add80 }, + { 0x19c99b88f57ed6e9, 0x5393cb266df8c825, 0x5cee3213b30ad273, 0x14e153ebb52d2e34 }, + { 0x413e1a17cde6818a, 0x57156da9ed69a084, 0x2cbf268f46caccb1, 0x6b34be9bc33ac5f2 } + }, + { + { 0x11fc69656571f2d3, -0x393617baacf18c86, -0x1cc5185d2b01afcb, 0x01b9c7b62e6dd30b }, + { -0x0c20d09bc5873f4e, 0x4c3e971ef22e027c, -0x1382e3a1b63e4a5d, 0x2012c18f0922dd2d }, + { -0x77f4aa1aa53762d7, 0x1483241f45a0a763, 0x3d36efdfc2e76c1f, 0x08af5b784e4bade8 } + }, + { + { -0x1d8ceb2d7633d3b5, 0x4be4bd11a287178d, 0x18d528d6fa3364ce, 0x6423c1d5afd9826e }, + { 0x283499dc881f2533, -0x62fada25886cdc4a, -0x7685220498cbbe0c, 0x32b79d71163a168d }, + { -0x337a072612034c96, 0x22bcc28f3746e5f9, -0x1b621cc7061a2c33, 0x480a5efbc13e2dcc } + }, + { + { -0x499eb31bbd31dde1, 0x6e199dcc4c053928, 0x663fb4a4dc1cbe03, 0x24b31d47691c8e06 }, + { 0x0b51e70b01622071, 0x06b505cf8b1dafc5, 0x2c6bb061ef5aabcd, 0x47aa27600cb7bf31 }, + { 0x2a541eedc015f8c3, 0x11a4fe7e7c693f7c, -0x0f5099ecb15d872a, 0x545b585d14dda094 } + }, + { + { 0x6204e4d0e3b321e1, 0x3baa637a28ff1e95, 0x0b0ccffd5b99bd9e, 0x4d22dc3e64c8d071 }, + { 0x67bf275ea0d43a0f, -0x521971cbf7641142, 0x4289134cd479e72e, 0x0f62f9c332ba5454 }, + { -0x034b9a7629c4a0c7, 0x5cae6a3f57cbcf61, -0x01453d2d6ac505fb, 0x1c0fa01a36371436 } + }, +}, +{ + { + { -0x3ee11a17ab3ac052, 0x6a0b06c12b4f3ff4, 0x33540f80e0b67a72, 0x15f18fc3cd07e3ef }, + { -0x18ab8bb64383296e, 0x0f9abeaae6f73ddf, 0x4af01ca700837e29, 0x63ab1b5d3f1bc183 }, + { 0x32750763b028f48c, 0x06020740556a065f, -0x2ac427ed3cb6a4a8, 0x08706c9b865f508d } + }, + { + { -0x3366e4bec74bedba, 0x243b9c526f9ac26b, -0x4610b6b248345443, 0x5fba433dd082ed00 }, + { -0x0c835d54c2cbc201, 0x1a8c6a2d80abc617, -0x71b61fca2b330036, 0x48b46beebaa1d1b9 }, + { -0x63b61caa366be530, -0x468cb5218bb6707c, 0x41c3fed066663e5c, 0x0ecfedf8e8e710b3 } + }, + { + { 0x744f7463e9403762, -0x0865721172033637, 0x163a649655e4cde3, 0x3b61788db284f435 }, + { 0x76430f9f9cd470d9, -0x49d533645bd09ff8, 0x1898297c59adad5e, 0x7789dd2db78c5080 }, + { -0x4dddd7e6f291094e, -0x56b5994db931b406, 0x46c1a77a4f0b6cc7, 0x4236ccffeb7338cf } + }, + { + { 0x3bd82dbfda777df6, 0x71b177cc0b98369e, 0x1d0e8463850c3699, 0x5a71945b48e2d1f1 }, + { -0x7b68bfb2f2aa1d8c, 0x6c6663d9c4ad2b53, -0x13d04f265256a8cc, 0x2617e120cdb8f73c }, + { 0x6f203dd5405b4b42, 0x327ec60410b24509, -0x63cb8dcf53d577ba, 0x77de29fc11ffeb6a } + }, + { + { -0x7ca1ec7013312d36, -0x736150ec1569c466, -0x36a0403f4de9f15a, 0x575e66f3ad877892 }, + { -0x4f53a8367c488758, 0x53cdcca9d7fe912c, 0x61c2b854ff1f59dc, 0x3a1a2cf0f0de7dac }, + { -0x667fc5d8377034c6, 0x345a6789275ec0b0, 0x459789d0ff6c2be5, 0x62f882651e70a8b2 } + }, + { + { 0x6d822986698a19e0, -0x2367de1e8b28758f, 0x41a85f31f6cb1f47, 0x352721c2bcda9c51 }, + { 0x085ae2c759ff1be4, 0x149145c93b0e40b7, -0x3b981805800d8c87, 0x4eeecf0ad5c73a95 }, + { 0x48329952213fc985, 0x1087cf0d368a1746, -0x71ad9e4e993ea55b, 0x2d5b2d842ed24c21 } + }, + { + { 0x5eb7d13d196ac533, 0x377234ecdb80be2b, -0x1ebb3003830a51dc, 0x5226bcf9c441acec }, + { 0x02cfebd9ebd3ded1, -0x2ba4de88c6fde68c, 0x7576f813fe30a1b7, 0x5691b6f9a34ef6c2 }, + { 0x79ee6c7223e5b547, 0x6f5f50768330d679, -0x128c1e1692752317, 0x27c3da1e1d8ccc03 } + }, + { + { 0x28302e71630ef9f6, -0x3d2b5dfcd49b3120, 0x090820304b6292be, 0x5fca747aa82adf18 }, + { 0x7eb9efb23fe24c74, 0x3e50f49f1651be01, 0x3ea732dc21858dea, 0x17377bd75bb810f9 }, + { 0x232a03c35c258ea5, -0x790dc5d39434f30f, 0x3dad8d0d2e442166, 0x04a8933cab76862b } + }, +}, +{ + { + { 0x69082b0e8c936a50, -0x06365fca3e253a4a, 0x6fb73e54c4dfb634, 0x4005419b1d2bc140 }, + { -0x2d39fb49dd6bc201, -0x43734131bb304c60, 0x5d254ff397808678, 0x0fa3614f3b1ca6bf }, + { -0x5ffc014246417d10, 0x2089c1af3a44ac90, -0x07b6606ee6ab0572, 0x1fba218aef40ab42 } + }, + { + { 0x4f3e57043e7b0194, -0x57e2c111f7255081, -0x37c639546623210f, 0x6c535d13ff7761d5 }, + { -0x54ab6bb705370ac2, -0x7e0917658459c8bf, 0x74fd6c7d6c2b5e01, 0x392e3acaa8c86e42 }, + { 0x4cbd34e93e8a35af, 0x2e0781445887e816, 0x19319c76f29ab0ab, 0x25e17fe4d50ac13b } + }, + { + { -0x6ea0800a890ede59, -0x3cb5cdd8d032781d, -0x3345d021b2e41ada, 0x6bba828f8969899b }, + { 0x0a289bd71e04f676, 0x208e1c52d6420f95, 0x5186d8b034691fab, 0x255751442a9fb351 }, + { -0x1d2e43996f01c6ff, 0x4cb54a18a0997ad5, -0x68e296eb507b9f2c, 0x559d504f7f6b7be4 } + }, + { + { -0x63b76e18092d9903, 0x0744a19b0307781b, -0x77c770e29f9e1dc5, 0x123ea6a3354bd50e }, + { -0x588c7c874c14ab2b, 0x1d69d366a5553c7c, 0x0a26cf62f92800ba, 0x01ab12d5807e3217 }, + { 0x118d189041e32d96, -0x46121c3d27cea7b8, 0x1eab4271d83245d9, 0x4a3961e2c918a154 } + }, + { + { 0x0327d644f3233f1e, 0x499a260e34fcf016, -0x7c4a58e90d254687, 0x68aceead9bd4111f }, + { 0x71dc3be0f8e6bba0, -0x293107cb81001cf6, -0x566dbda01ec5b896, 0x2cd6bce3fb1db763 }, + { 0x38b4c90ef3d7c210, 0x308e6e24b7ad040c, 0x3860d9f1b7e73e23, 0x595760d5b508f597 } + }, + { + { -0x77d5341402fdd870, -0x7650ccfa3beea8a0, 0x65f492e37d3473f4, 0x2cb2c5df54515a2b }, + { 0x6129bfe104aa6397, -0x7069fff75b580335, 0x3f8bc0897d909458, 0x709fa43edcb291a9 }, + { -0x14f5a2739c02d536, -0x2dd43e99d196b101, 0x2723f36ef8cbb03a, 0x70f029ecf0c8131f } + }, + { + { 0x2a6aafaa5e10b0b9, 0x78f0a370ef041aa9, 0x773efb77aa3ad61f, 0x44eca5a2a74bd9e1 }, + { 0x461307b32eed3e33, -0x51fbd0cc5baa7e19, -0x36bbb62ce6a0fc9a, 0x0b7d5d8a6c314858 }, + { 0x25d448327b95d543, 0x70d38300a3340f1d, -0x21e3ace39f1e3ad5, 0x272224512c7de9e4 } + }, + { + { -0x40844475bd568a04, -0x73a3c68869525ca8, -0x1d803890321255b8, 0x19735fd7f6bc20a6 }, + { 0x1abc92af49c5342e, -0x001127ee4d190530, -0x105d73720337b1d7, 0x11b5df18a44cc543 }, + { -0x1c546f2fbd37bd9a, -0x147b71f080e6ab82, 0x2503a1d065a497b9, 0x0fef911191df895f } + }, +}, +{ + { + { 0x6ab5dcb85b1c16b7, -0x6b3f0317c384d85b, -0x5b4ee3e58caae842, 0x499238d0ba0eafaa }, + { -0x4eaf835e54e39147, -0x42bb70c1e949784d, 0x3455fb7f2c7a91ab, 0x7579229e2f2adec1 }, + { -0x130b91ad854574a9, 0x15a08c478bd1647b, 0x7af1c6a65f706fef, 0x6345fa78f03a30d5 } + }, + { + { -0x6c2c341642270f5c, -0x24ead3e402e88cfe, 0x7dbddc6d7f17a875, 0x3e1a71cc8f426efe }, + { -0x20fd06a0efea185f, 0x790ec41da9b40263, 0x4d3a0ea133ea1107, 0x54f70be7e33af8c9 }, + { -0x37c35c1c6f45429e, -0x7f121c98fd6e37cd, -0x377fc7332c86ff3c, 0x2c5fc0231ec31fa1 } + }, + { + { -0x3bdd1b2efdba919b, -0x78beb53e352b846f, 0x1592e2bba2b6ffdd, 0x75d9d2bff5c2100f }, + { -0x01456ee8e8fc74b1, -0x1aedc8de3621107f, 0x1c97e4e75d0d8834, 0x68afae7a23dc3bc6 }, + { 0x5bd9b4763626e81c, -0x766996c9435fd123, 0x0a41193d61f077b3, 0x3097a24200ce5471 } + }, + { + { -0x5e9d18db996a3b7a, 0x131d633435a89607, 0x30521561a0d12a37, 0x56704bada6afb363 }, + { 0x57427734c7f8b84c, -0x0ebe5ec1fe4d8f17, 0x02d1adfeb4e564a6, 0x4bb23d92ce83bd48 }, + { -0x5093b558ad06ed47, 0x5e665f6cd86770c8, 0x4c35ac83a3c8cd58, 0x2b7a29c010a58a7e } + }, + { + { 0x33810a23bf00086e, -0x50316da118c90084, 0x3d60e670e24922d4, 0x11ce9e714f96061b }, + { -0x3bff80882f3e313d, -0x72efdf49453b6d08, 0x32ec29d57e69daaf, 0x599408759d95fce0 }, + { 0x219ef713d815bac1, -0x0ebeb9a2b7a41da4, 0x6d5447cc4e513c51, 0x174926be5ef44393 } + }, + { + { 0x3ef5d41593ea022e, 0x5cbcc1a20ed0eed6, -0x702db130f8c7d374, 0x6fa42ead06d8e1ad }, + { -0x4a214d0603a42a45, -0x6d2558d51e27ef1f, -0x503b302348d5e3a7, 0x497d78813fc22a24 }, + { -0x1d897db5e08cc8e1, 0x7f7cf01c4f5b6736, 0x7e201fe304fa46e7, 0x785a36a357808c96 } + }, + { + { 0x070442985d517bc3, 0x6acd56c7ae653678, 0x00a27983985a7763, 0x5167effae512662b }, + { -0x7da042029cfeb2d5, -0x37adc9639358a875, 0x5b2fcd285c0b5df0, 0x12ab214c58048c8f }, + { -0x42b1561ef0ac3b4a, 0x1673dc5f8ac91a14, -0x5707e5b1d533e546, 0x33a92a7924332a25 } + }, + { + { 0x7ba95ba0218f2ada, -0x300bdd78ccf04636, -0x2525b692a93926f9, 0x5380c296f4beee54 }, + { -0x622e0b66d86693fe, 0x0cb3b058e04d1752, 0x1f7e88967fd02c3e, 0x2f964268cb8b3eb1 }, + { -0x62b0d8fb997672f6, 0x3d0987990aff3f7a, -0x2f610c9d982545bb, 0x7761455e7b1c669c } + }, +}, +}; +#elif defined(CURVED25519_ASM_32BIT) +static const ge_precomp base[64][8] = { +{ + { + { -0x0a73c47b, 0x2fbc93c6, -0x0473f1e7, -0x306cd23a, 0x643d42c2, 0x270b4898, 0x33d4ba65, 0x07cf9d3a }, + { -0x28bf6ec2, -0x62efc6fb, -0x2ebf414d, -0x02c660fb, 0x688f8a09, -0x5a3e7bcc, -0x6707ed99, 0x44fd2f92 }, + { 0x4b6fbb59, -0x2442ea99, -0x115d5a16, 0x41e13f00, -0x36a83906, -0x322b62e4, -0x50e91336, 0x4f0ebe1f } + }, + { + { -0x6cc38e29, -0x6ddb1804, 0x7a0ff5b5, -0x60b9626a, -0x1e29f8fe, 0x5aa69a65, -0x5782d1d2, 0x590c063f }, + { 0x42b4d5a8, -0x75665aa0, 0x4e60acf6, -0x70d47ef4, -0x4e91c856, -0x1f61dc95, 0x69c92555, 0x6bb595a6 }, + { -0x252c97fe, 0x6e347eaa, -0x7c11b7fb, -0x450ca66d, -0x19f897da, 0x3bcabe10, 0x165ed1b8, 0x49314f0a } + }, + { + { 0x4cee9730, -0x50da4f58, -0x1779b476, 0x025a8430, -0x60fe98ce, -0x3ee4affe, -0x657f070c, 0x7a164e1b }, + { -0x5b032d9b, 0x56611fe8, -0x1a3e4583, 0x3bd353fd, 0x214bd6bd, -0x7ece0ce6, 0x555bda62, 0x2ab91587 }, + { -0x0e98b7cc, -0x640dee0c, -0x09d2076b, -0x47b194e9, 0x5b722a4e, -0x282190f9, 0x63bb2a21, 0x549a04b9 } + }, + { + { -0x7103f661, 0x287351b9, 0x7dfd2538, 0x6765c6f4, -0x04f56d9b, -0x35cb72c3, 0x21e58727, 0x680e9103 }, + { 0x056818bf, -0x6a01faf6, 0x5660faa9, 0x327e8971, 0x06a05073, -0x3c171c33, 0x7445a49a, 0x27933f4c }, + { -0x1aebd950, -0x40e1ba14, 0x6dba0f94, -0x1cd439c3, -0x7307ad40, -0x1bd68b2b, -0x4f19b3e8, 0x44f079b1 } + }, + { + { 0x08a5bb33, -0x5ded43bc, -0x38a112fe, -0x72afb73d, 0x5abfec44, -0x22e414f4, 0x46e206eb, 0x2945ccf1 }, + { -0x5bb82946, 0x7f9182c3, 0x4b2729b7, -0x2affeb2f, -0x479b5f79, -0x1cc30ee4, -0x14e4aa0d, 0x154a7e73 }, + { -0x182ffc4d, -0x37cd5e87, 0x00124d7e, 0x5f729d0a, 0x0e6d8ff3, 0x62c1d4a1, 0x38b27a98, 0x68b8ac59 } + }, + { + { 0x77157131, 0x3a0ceeeb, 0x00c8af88, -0x64d8ea77, -0x25a658ca, -0x7f9a4998, -0x5d33c743, 0x51e57bb6 }, + { 0x7b7d8ca4, 0x499806b6, 0x27d22739, 0x575be284, 0x204553b9, -0x44f7a319, -0x51be877c, 0x38b64c41 }, + { 0x689de3a4, -0x7062526f, -0x07046ec9, 0x175f2428, -0x60304678, 0x050ab532, 0x1354c09f, 0x7865dfa2 } + }, + { + { -0x6bb15c41, 0x6b1a5cd0, -0x4c623f2e, 0x7470353a, 0x28542e49, 0x71b25282, 0x283c927e, 0x461bea69 }, + { -0x55cdde4f, -0x4590d366, 0x3bba23a7, 0x6ca02153, -0x6de6d3c6, -0x621589b1, 0x2e5317e0, 0x1d6edd5d }, + { -0x54f025ca, 0x217a8aac, 0x3d3549c8, -0x5ad739ac, 0x13ab7568, 0x37d05b8b, 0x3a2cbc37, 0x233cef62 } + }, + { + { 0x04dd3e8f, 0x59b75966, -0x1d778fd4, 0x6cb30377, 0x5ed9c323, -0x4ecc639a, 0x61bce52f, 0x0915e760 }, + { -0x0c6dcb27, -0x1d58a213, -0x1e4aa707, -0x69c28980, 0x6e3c23fb, 0x2c2741ac, 0x320e01c3, 0x3a9024a1 }, + { -0x57cb5c82, -0x208217cb, 0x689857ea, -0x741e6326, 0x7167b326, 0x2c118536, -0x24102a3e, 0x589eb3d9 } + }, +}, +{ + { + { 0x2d9021f6, 0x322d04a5, 0x75c6bf9c, -0x463e60cd, 0x42d20b09, 0x587a3a43, -0x559b019f, 0x143b1cf8 }, + { 0x553e2df3, 0x7ec851ca, -0x59b7874d, -0x58ed7b35, 0x3288d1e7, -0x194a1be7, 0x5a9a8883, 0x4cf210ec }, + { -0x69753555, -0x60798383, 0x27092729, 0x5f54258e, -0x15e7f68b, -0x2f582cb5, 0x374126e1, 0x21b546a3 } + }, + { + { -0x2e7ade71, 0x490a7a45, 0x46049335, -0x65eac888, -0x33ce1e0a, 0x0060ea09, -0x0791169b, 0x7e041577 }, + { -0x5d777cbd, -0x56b007a8, 0x5313ed3c, -0x31f12baa, -0x4a40cb06, -0x0aa3c231, -0x36154c8f, 0x0a653ca5 }, + { -0x31a4980d, 0x66b2a496, -0x42a9686a, -0x00ab6d28, 0x4a592cd0, 0x503cec29, 0x0813acb2, 0x56694365 } + }, + { + { 0x1dabb69d, 0x5672f9eb, -0x5017ac04, -0x458f4acb, 0x2796d66d, 0x47ac0f75, -0x6bee8d8b, 0x32a53517 }, + { 0x26620798, -0x47e724f4, 0x606e354a, 0x5d5c31d9, 0x00a8cdc7, 0x0982fa4f, 0x4653e2d4, 0x17e12bcd }, + { -0x209b7bc9, -0x2c59bb5a, -0x77f04023, 0x703b6559, -0x52c5e55b, -0x347adac0, -0x71b39b98, 0x0900b3f7 } + }, + { + { -0x37e952cf, -0x12d7f042, -0x2719101d, 0x52d9595b, -0x0939dc0b, 0x0fe71772, 0x051e293c, 0x4314030b }, + { 0x679d651b, 0x0a851b9f, 0x033342f2, -0x1ef7349f, -0x1774cf5d, -0x29fe0a81, -0x12d228ec, 0x371f3aca }, + { -0x040f4353, -0x2a9fffa2, -0x2e78f3a2, -0x7148f0d2, -0x2f7b1960, 0x201f9033, -0x31849990, 0x4c3a5ae1 } + }, + { + { -0x36c25f23, -0x45078a1c, 0x71b9294d, -0x46cd7d59, -0x0b393ba0, -0x7f29c049, -0x15993e7f, 0x6de9c73d }, + { -0x2347056b, 0x4138a434, 0x6c96840b, -0x78f30983, 0x297be82c, -0x21c77a8c, 0x7262a55a, 0x7c814db2 }, + { -0x5fb2070e, 0x478904d5, -0x4efebd2d, -0x050451b6, 0x555d0998, -0x0937539d, 0x2f90b104, 0x5aac4a41 } + }, + { + { -0x4280aecc, 0x603a0d0a, -0x1e2c51ba, -0x7f7636ce, -0x7867429d, -0x20da6ec7, 0x74ba0235, 0x1c145cd2 }, + { 0x3ac92908, -0x39b0cd95, -0x199c1e20, 0x5551b282, 0x4a1a4b83, 0x476b35f5, 0x189f68c2, 0x1b9da3fe }, + { 0x75f3d743, 0x32e83864, 0x6ae5d9ef, 0x365b8baf, 0x385b681e, -0x7dadc74a, 0x167d65e1, 0x234929c1 } + }, + { + { 0x1d099fcf, 0x48145cc2, -0x33d7281b, 0x4535c192, 0x48247e01, -0x7f183e1b, 0x3b2973ee, 0x4a5f2874 }, + { -0x5f885218, -0x67b21355, 0x19eb389d, 0x383f77ad, 0x2954d794, -0x38139482, -0x1483c586, 0x59c77b3a }, + { 0x225ccf62, -0x2c5228db, -0x4dead3a3, -0x6ee5cc7f, 0x5b08f87d, -0x274c6053, 0x4799fe3b, 0x6f05606b } + }, + { + { -0x06e49b7d, 0x5b433149, 0x5a2cbf62, -0x524a239b, 0x632827b3, -0x78057bee, -0x54b60728, 0x60895e91 }, + { 0x177ba962, -0x6001616e, 0x0de5cae1, -0x675118e3, 0x2d831044, 0x3ff4ae94, 0x58533ac8, 0x714de12e }, + { 0x0cf86c18, -0x16130d13, 0x0735dfd4, -0x4b92f9ee, 0x04b96be7, -0x43625f68, -0x26923d95, 0x73e2e62f } + }, +}, +{ + { + { 0x632f9c1d, 0x2eccdd0e, 0x76893115, 0x51d0b696, -0x579c85a8, 0x52dfb76b, -0x5ff110c7, 0x6dd37d49 }, + { 0x49aa515e, -0x12a49cac, 0x0bc6823a, -0x579a3b61, 0x5b42d1c4, -0x7af3e017, 0x03d315b9, 0x30d76d6f }, + { 0x2106e4c7, 0x6c444417, -0x6d728097, -0x04ac2980, 0x694d3f26, -0x4b8c615c, 0x2e864bb0, 0x10c69711 } + }, + { + { -0x7ca737fb, 0x0ca62aa0, 0x7a204247, 0x6a3d4ae3, 0x3b11eddc, 0x7464d3a6, 0x550806ef, 0x03bf9baf }, + { 0x7dbe5fde, 0x6493c427, 0x19ad7ea2, 0x265d4fad, 0x46304590, 0x0e00dfc8, -0x129901f7, 0x25e61cab }, + { -0x33a799fc, 0x3f13e128, -0x4ba68b82, 0x6f5873ec, -0x33ed970b, -0x5f49c213, 0x4586e22c, 0x566d7863 } + }, + { + { -0x39a5d030, -0x5efabd7b, -0x0ce9983d, 0x6c64112a, 0x731aee58, 0x680ae240, 0x4793b22a, 0x14fba5f3 }, + { -0x633ef7cc, 0x1637a49f, -0x57643baf, -0x4371a92b, 0x7f7fd2db, 0x1cb5ec0f, 0x5ecc35d9, 0x33975bca }, + { 0x6985f7d4, 0x3cd74616, -0x3637ffa9, 0x593e5e84, 0x7b61131e, 0x2fc3f2b6, -0x7c03ad94, 0x14829cea } + }, + { + { 0x4e71ecb8, 0x21e70b2f, 0x40a477e3, -0x19a92247, -0x31e2b080, -0x409aa932, 0x535d7b7e, 0x05fc3bc4 }, + { -0x68226a3e, -0x00bc847c, -0x55b14a59, 0x6c744e30, 0x3c85e88b, -0x61f3a29f, 0x5f758173, 0x2fd9c71e }, + { 0x52afdedd, 0x24b8b3ae, -0x12c4cf31, 0x3495638c, -0x56417e6b, 0x33a4bc83, 0x5c651f04, 0x37376747 } + }, + { + { 0x14246590, 0x634095cb, 0x16c15535, -0x10edebc0, -0x76ef43a0, -0x61c7ebf4, 0x30907c8c, 0x6bf59057 }, + { 0x40d1add9, 0x2fba99fd, -0x690b2fd9, -0x4cf8e991, 0x15f03bae, 0x4363f052, 0x3b18f999, 0x1fbea56c }, + { -0x1ebea476, 0x0fa778f1, -0x453c5882, 0x06409ff7, -0x655d65b0, 0x6f52d7b8, 0x7a635a56, 0x02521cf6 } + }, + { + { 0x772f5ee4, -0x4eeb98e0, -0x69f86532, -0x17076b4f, 0x00ac824a, 0x4af8224d, -0x0832933c, 0x001753d9 }, + { 0x0a9d5294, 0x513fee0b, 0x0fdf5a66, -0x706718a4, -0x401ef832, -0x2b9e7978, 0x71382ced, 0x3fa00a7e }, + { -0x69c224cc, 0x3c69232d, -0x4b68c7a8, 0x1dde87da, -0x5f6e0d7b, -0x55282e07, -0x5fb7124a, 0x12b5fe2f } + }, + { + { -0x5290e16e, -0x20d483da, 0x504b8913, 0x4b66d323, 0x751c8bc3, -0x73bf6240, 0x0796c7b8, 0x6f7e93c2 }, + { -0x69031cb3, 0x71f0fbc4, -0x520ca413, 0x73b9826b, -0x00d73a9f, -0x2dfb8d9f, 0x6fb1206f, 0x749b76f9 }, + { -0x515951fb, 0x1f5af604, -0x411b6367, -0x3edcae0f, -0x1100949a, 0x61a808b5, 0x01e02151, 0x0fcec10f } + }, + { + { -0x3bdbb1bb, 0x3df2d29d, -0x6c2721f6, 0x2b020e74, -0x7df3deb3, 0x6cc8067e, 0x6feab90a, 0x41377916 }, + { 0x49fe1e44, 0x644d58a6, 0x31ad777e, 0x21fcaea2, -0x77802f2e, 0x02441c5a, -0x7c3aee0d, 0x4901aa71 }, + { -0x73e50710, 0x08b1b754, 0x246299b4, -0x31f08584, 0x1e06d939, -0x089f4f07, 0x726d1213, 0x41bb887b } + }, +}, +{ + { + { -0x55c6082e, -0x68267f20, 0x52c6b51c, 0x35d03842, 0x07cd55aa, 0x7d43f493, -0x48753c9e, 0x56bd36cf }, + { 0x567c49d8, -0x6d987f94, -0x3586e196, 0x066d04cc, -0x1c33c6b5, -0x5960a9bb, -0x5f87732e, 0x5c95b686 }, + { 0x0d14a954, 0x2ac519c1, -0x6b4a0570, -0x150b8b4c, -0x560785a6, -0x19507c7e, -0x78641f6c, 0x0dea6db1 } + }, + { + { -0x29578686, 0x15baeb74, -0x053be8ce, 0x7ef55cf1, 0x3c8b05c5, 0x29001f5a, 0x52eaccfb, 0x0ad7cc87 }, + { 0x7344e5ab, -0x559940ac, -0x70e4bcf7, -0x25eda778, -0x02a9b4d1, 0x5e87d2b3, 0x5483b1dd, 0x5b2c7888 }, + { 0x793408cf, 0x52151362, 0x19963d94, -0x14f0e8fd, -0x77c26b9a, -0x57cc4d06, 0x75003c78, 0x093a7fa7 } + }, + { + { 0x60a91286, -0x47169fbc, 0x7778d3de, 0x7f3fd804, -0x4075a1d3, 0x67d01e31, -0x3d849ac2, 0x7b038a06 }, + { 0x3a16d7be, -0x1aef821a, -0x650ccd31, -0x5c880024, 0x440b677f, 0x70d5bf18, -0x5b5cebfd, 0x6a252b19 }, + { -0x2c966f0d, -0x6126e62b, -0x24b1460e, 0x5213aebb, 0x4cb99135, -0x38f715fb, 0x72260e56, 0x58ded57f } + }, + { + { 0x5b0fd48b, -0x2592acda, -0x6c405678, -0x769f7dcf, 0x61d57e28, -0x287536ce, 0x3a5c8143, 0x79f2942d }, + { -0x16bec289, 0x78e79dad, -0x68d61983, -0x0da8062b, -0x1c85581a, 0x59db910e, -0x4461fc64, 0x6aa11b5b }, + { -0x49377217, -0x6825d0db, -0x530dfe97, 0x251ba7ea, -0x10b14b1c, 0x09b44f87, -0x4395825b, 0x7d90ab1b } + }, + { + { -0x694c3c69, 0x1a07a3f4, -0x70b1dace, 0x11ceaa18, -0x588ae410, 0x7d9498d5, 0x508dd8a0, 0x19ed161f }, + { -0x58fe9402, -0x6533597d, -0x0d3af493, -0x6fafa0b3, -0x331bca56, 0x6b610d5f, 0x6198ff96, 0x19a10d44 }, + { -0x78231936, 0x560a2cd6, -0x799b30b3, 0x7f3568c4, 0x22803a38, -0x78be16ae, 0x595653fc, 0x483bdab1 } + }, + { + { -0x4b257f0a, -0x2930b2f6, -0x07cf8020, -0x7db7c1bb, -0x5190625c, 0x05005269, -0x63087886, 0x1c705290 }, + { -0x78cb05b7, -0x0587f0ec, 0x360534e0, 0x106f0b70, -0x1c1cf843, 0x2210776f, -0x22195f02, 0x3286c109 }, + { -0x78b1672c, 0x32ee7de2, -0x4681f3a0, 0x14c362e9, 0x6a60a38a, 0x5781dcde, -0x558557c0, 0x217dd5ea } + }, + { + { -0x4173f138, -0x7420e047, -0x1cf5fd7e, 0x00bae7f8, -0x5293b094, 0x4963991d, 0x5df6f60a, 0x07058a6e }, + { 0x248e1eb0, -0x62483b30, 0x4d74bf52, -0x1f89681f, 0x3c562354, 0x1e6a9b17, 0x795a4965, 0x7fa7c21f }, + { -0x24ce0981, -0x1614fd3c, 0x10bcfb2b, -0x12da0277, 0x5c5cddb4, 0x46c8131f, -0x5f346432, 0x33b21c13 } + }, + { + { 0x5ee38c5b, -0x65504650, 0x071a13c7, -0x4062d2b2, -0x16ccd6f6, -0x71119193, -0x51ef68e9, 0x1c3bab17 }, + { 0x087d8e31, 0x360692f8, -0x2d8e9c09, -0x0b2339c9, 0x65ea5963, 0x25a4e620, 0x5ac160d9, 0x659bf72e }, + { -0x38354850, 0x1c9ab216, 0x07bbc3cc, 0x7d65d374, 0x504a58d5, 0x52744750, 0x131a2990, 0x09f2606b } + }, +}, +{ + { + { 0x7c6691ae, 0x7e234c59, 0x0a85b4c8, 0x64889d3d, 0x354afae7, -0x251d36f4, 0x0c6a9e1d, 0x0a871e07 }, + { 0x744346be, 0x40e87d44, 0x15b52b25, 0x1d48dad4, -0x5ec49fc2, 0x7c3a8a18, 0x2fcdbdf7, 0x4eb728c1 }, + { 0x4bbc8989, 0x3301b599, 0x5bdd4260, 0x736bae3a, 0x19d59e3c, 0x0d61ade2, 0x2685d464, 0x3ee7300f } + }, + { + { -0x7be18ae8, 0x43fa7947, 0x639c46d7, -0x1a3905a7, -0x1cfad48c, -0x5ef9a1e3, -0x30476fd0, 0x7d47c6a2 }, + { -0x61822949, -0x0a2daa1c, 0x610b1eac, -0x7fe9eea4, -0x6d1e7836, 0x3c99975d, -0x686eda3e, 0x13815762 }, + { -0x710f2920, 0x3fdad014, -0x6eab90c4, -0x62c18b66, 0x26bb8157, 0x71ec6210, 0x34c9ec80, 0x148cf58d } + }, + { + { -0x651b8a93, -0x1da8d083, -0x770cb781, 0x56c345bb, 0x6960a88d, -0x602ef493, 0x4eaea1b9, 0x278febad }, + { 0x7934f027, 0x46a492f6, -0x097bf557, 0x469984be, -0x769ee7ac, 0x5ca1bc2a, -0x42a2442c, 0x3ff2fa1e }, + { -0x736cc69a, -0x4e5597e1, 0x20290c98, -0x73de6b64, 0x219d3c52, 0x39115291, -0x01639885, 0x4104dd02 } + }, + { + { -0x24f69548, -0x7edeb1fa, 0x0ce44f35, 0x21a8b6c9, 0x409e2af5, 0x6524c12a, -0x71035b7f, 0x0165b5a4 }, + { 0x1124422a, 0x72b2bf5e, -0x675cc54b, -0x5e05f3cd, -0x05ad499a, -0x6b349eff, -0x5050ac2b, 0x2c863b00 }, + { -0x5f7b958a, -0x0e6f5b8c, -0x32d08340, 0x12eff984, 0x58aa2b8f, 0x695e2906, -0x40013748, 0x591b67d9 } + }, + { + { -0x60e74aa3, -0x66464c8f, -0x5e739be2, -0x1b9a1a06, -0x3d60fa13, 0x61081136, 0x7030128b, 0x489b4f86 }, + { -0x7f4b6406, 0x312f0d1c, -0x540c1376, 0x5979515e, -0x610fe378, 0x727033c0, -0x35708435, 0x3de02ec7 }, + { 0x3aeb92ef, -0x2dcdefd3, 0x6116a861, -0x1e9dac4c, 0x190baa24, 0x3d7eabe7, 0x496cbebf, 0x49f5fbba } + }, + { + { 0x1e9c572e, 0x155d628c, -0x3a77b8bf, -0x75b27954, 0x515763eb, -0x6e5cad0a, -0x7798aea5, 0x06a1a6c2 }, + { -0x75a4302c, 0x30949a10, -0x439b8c15, -0x23bf2290, 0x307c0d1c, -0x6d3d6b3f, -0x3405918c, 0x5604a86d }, + { 0x7c1764b6, 0x7288d1d4, -0x1fbe74af, 0x72541140, 0x18acf6d1, -0x60fce5a0, -0x01d8bd3a, 0x20989e89 } + }, + { + { -0x7a1513d2, 0x1674278b, 0x7acb2bdf, 0x5621dc07, 0x61cbf45a, 0x640a4c16, -0x08fa6a2d, 0x730b9950 }, + { 0x3a2dcc7f, 0x499777fd, -0x5ab0276e, 0x32857c2c, -0x2df81c60, -0x5d86279c, 0x0ca67e29, 0x0403ed1d }, + { -0x78b13aae, -0x36b4d2cb, -0x67db9073, -0x3a193731, 0x16c035ce, -0x0834b906, 0x08303dcc, 0x5bd74543 } + }, + { + { 0x15e7792a, -0x7a3b6cdf, -0x42322237, -0x39b3765e, -0x525c289e, -0x62e1c258, 0x3067f82c, 0x5bb7db12 }, + { 0x28b24cc2, 0x7f9ad195, 0x6335c181, 0x7f6b5465, 0x4fc07236, 0x66b8b66e, 0x7380ad83, 0x133a7800 }, + { -0x39359d42, 0x0961f467, 0x211952ee, 0x04ec21d6, -0x642ab890, 0x18236077, 0x58f0e0d2, 0x740dca6d } + }, +}, +{ + { + { -0x12d9e51b, 0x3906c72a, -0x771eff09, -0x65497027, -0x0cc9fe69, -0x0a16fa66, -0x40d492b9, 0x0e53dc78 }, + { -0x2c0f50f5, 0x50b70bf5, -0x1cd18e09, 0x4feaf48a, -0x5aa442cc, 0x60e84ed3, 0x3f50d1ed, 0x00ed489b }, + { 0x7971877a, -0x46f7d641, 0x6d17e631, 0x5e444463, 0x18276893, 0x4d05c52e, 0x5a4a4af5, 0x27632d9a } + }, + { + { -0x78150025, -0x567d7a2f, -0x272f579c, -0x5a4b0445, 0x022663f7, -0x49a70d81, -0x26631d7e, 0x3bbc2b22 }, + { 0x54b260ce, -0x2ee00faf, 0x72f95270, -0x27923c72, 0x267cc138, 0x601fcd0d, 0x29e90ccd, 0x2b679164 }, + { 0x583c0a58, -0x46e836ae, 0x0fe4c6f3, 0x653ff9b8, -0x4320c3f4, -0x64f25829, -0x54ab29f2, 0x43a0eeb6 } + }, + { + { 0x57875fe8, 0x3ac63223, -0x0a043471, -0x262b0b14, 0x382bb620, -0x72117b6d, 0x4c799fdc, 0x50c5eaa1 }, + { 0x6d4a5487, 0x396966a4, -0x53d44c46, -0x07ee5e76, 0x5628b26b, 0x66e4685b, -0x626d646e, 0x70a47702 }, + { -0x290d04c4, -0x22f12375, -0x63384860, 0x54c63aa7, 0x2c8d9f1a, -0x51f4fcd5, 0x602967fb, 0x6f9ce107 } + }, + { + { 0x3520e0b5, 0x13969306, -0x7715fc02, 0x437fcf7c, -0x2c36a644, -0x082b3bf5, -0x076c2127, 0x699154d1 }, + { -0x321e3dd6, -0x52efab4f, 0x48eb32df, -0x3b5716fe, -0x53323f16, 0x5f3e7b33, -0x038669c2, 0x72364713 }, + { -0x4b4d8ada, 0x315d5c75, 0x0236daa5, -0x33347bd3, 0x345fee8e, 0x22f0c8a3, 0x7d39dbed, 0x73975a61 } + }, + { + { -0x0bbcc1ba, 0x6f37f392, 0x1f566b18, 0x0e19b9a1, 0x1fd1d662, 0x220fb78a, -0x5c7e36b3, 0x362a4258 }, + { 0x6375da10, -0x1bfdb207, 0x1830c870, 0x78d3251a, 0x658cd91c, -0x6fd4e6b8, 0x29b7438a, 0x7e18b10b }, + { 0x2b6beb2f, -0x6f8e26ed, 0x28418247, 0x0f26e9ad, -0x42136da3, -0x1546e137, -0x0b750d22, 0x4be65bc8 } + }, + { + { 0x57c26234, 0x1d50fba2, -0x214f9875, 0x7bd4823a, -0x59ac750b, -0x3d4f2392, 0x351da73e, 0x5665eec6 }, + { -0x5c918fd8, 0x78487feb, 0x1dd8ce34, 0x5f3f1300, 0x4b30c489, -0x6cb04ed3, 0x397f0a2b, 0x056c244d }, + { 0x43bfb210, -0x24c11ff7, 0x20800ac2, 0x49720187, 0x73bd8667, 0x26ab5d61, -0x54dfb6c8, 0x20b209c2 } + }, + { + { 0x16bd3289, 0x1fcca945, 0x41420428, 0x448d65aa, 0x16a55d62, 0x59c3b7b2, 0x4e612cd8, 0x49992cc6 }, + { -0x3f804cb5, 0x549e342a, 0x21373d93, 0x02d82208, -0x532e0a99, -0x43d9d290, -0x0435387c, 0x7a92c9fd }, + { 0x70f801de, 0x65bd1bea, -0x01b61d76, 0x1befb7c0, -0x4e4d51b6, -0x579cf933, 0x265c2a09, 0x3b7ac0cd } + }, + { + { 0x22ed39a7, -0x0f2ab1b1, 0x5608150a, -0x5d5516e2, -0x1225178b, -0x0bde4d17, 0x6b7de992, 0x31bc531d }, + { -0x73fe4314, -0x7dd411bd, -0x3f0438c5, 0x530cb525, -0x3e6ac017, 0x48519034, -0x1f65f0a5, 0x265cc261 }, + { -0x567f068f, -0x20c2ecb3, 0x221a22a7, 0x7a4fb8d1, 0x35aad6d8, 0x3df7d420, 0x6a1a125e, 0x2a14edcc } + }, +}, +{ + { + { 0x0478433c, 0x231a8c57, -0x3d7ebc63, -0x484ad8f2, -0x1c26f861, -0x24556616, 0x6c2b03d9, 0x2c03f525 }, + { 0x52cfce4e, -0x20b711f9, 0x06ec08b7, -0x3c00050d, -0x46aba63c, 0x05710b2a, -0x69c15c73, 0x161d25fa }, + { 0x7b53a47d, 0x790f1875, -0x30f3a787, 0x307b0130, 0x257ef7f9, 0x31903d77, -0x42694451, 0x699468bd } + }, + { + { 0x6aa91948, -0x2722c21a, 0x2fc0d2cc, 0x485064c2, 0x34fdea2f, -0x64b7db9a, 0x6c4a2e3a, 0x293e1c4e }, + { -0x0b250131, -0x42e0d0ba, -0x5b802909, 0x7cef0114, 0x4a47b37f, -0x2ce00226, 0x73905785, 0x525219a4 }, + { -0x6daeed1f, 0x376e134b, -0x235ea260, 0x703778b5, 0x461c3111, -0x4fba7651, 0x7f032823, 0x5b605c44 } + }, + { + { -0x0f180fb4, 0x3be9fec6, 0x75e34962, -0x7995a862, 0x1e1de61a, 0x5542ef16, -0x33a5422b, 0x2f12fef4 }, + { 0x20c47c89, -0x469a7fa7, -0x6dc47034, -0x180feff4, 0x02e2ef77, 0x00012565, -0x57514c12, 0x24a76dce }, + { -0x203f38c0, 0x0a4522b2, 0x40c9a407, 0x10d06e7f, 0x78cff668, -0x3930ebbf, 0x18a43790, 0x5e607b25 } + }, + { + { -0x5a6930ec, -0x5fd3bce4, -0x512c1c00, -0x1c3bd2c0, 0x2e0f26db, -0x2dbad980, -0x61ba8f98, 0x201f3313 }, + { 0x6cdf1818, 0x58b31d8f, -0x3c9da75e, 0x35cfa74f, 0x66e61d6e, -0x1e4c00b1, 0x6ccdd5f7, 0x5067acab }, + { 0x08039d51, -0x02ad8095, 0x017c0006, 0x18b14964, 0x2e25a4a8, -0x2addf150, 0x62460375, 0x397cba88 } + }, + { + { -0x37ec8619, 0x7815c3fb, -0x221ed50f, -0x599e6be0, -0x7a57022b, -0x00563f08, -0x3e1e3dae, 0x771b4022 }, + { -0x0fa6a64e, 0x30c13093, -0x1656868a, -0x1dc55e73, 0x721d5e26, 0x222fd491, 0x766e6c3a, 0x2339d320 }, + { 0x513a2fa7, -0x2782267a, -0x062b30f8, -0x0a53648f, 0x1ea283b3, -0x2f943ce5, 0x19971a76, 0x331a1892 } + }, + { + { -0x628a8d51, 0x26512f3a, 0x68074a9e, 0x5bcbe288, 0x1180f7c4, -0x7b123e3f, -0x09b65985, 0x1ac9619f }, + { -0x04b07f3a, -0x0ae990bb, 0x61c775cf, -0x63c93822, -0x6fbe26e4, -0x1c2b17e5, -0x7c4201df, 0x31167c6b }, + { 0x524b1068, -0x0dd4c7be, -0x11631679, 0x5068343b, 0x4a6250c8, -0x03628e7c, 0x1f08b111, 0x61243634 } + }, + { + { 0x1a2d2638, -0x749cb61d, -0x642c02cb, -0x62204900, -0x5c5f945c, 0x7f8bf1b8, 0x78d90445, 0x1522aa31 }, + { -0x78b17673, -0x2662be25, 0x6c07dc20, 0x09fea5f1, -0x2ff06444, 0x793d2c67, -0x61a100c0, 0x46ebe230 }, + { 0x69614938, 0x2c382f53, -0x48d292f0, -0x2501bf66, -0x49b90dd9, -0x1737cc6f, 0x0524306c, 0x45fe70f5 } + }, + { + { -0x376aeb6f, 0x62f24920, 0x3f630ca2, 0x05f007c8, -0x0a362b48, 0x6fbb45d2, -0x4a85ddbb, 0x16619f6d }, + { -0x69f3f474, -0x25b78a5a, -0x10f1d0e0, 0x5b68d076, 0x3d0b8fd4, 0x07fb51cf, -0x5f1c6d2c, 0x428d1623 }, + { 0x01a308fd, 0x084f4a44, 0x76a5caac, -0x57dde63d, 0x43d1bc7d, -0x214721ba, 0x60bd38c6, 0x1d81592d } + }, +}, +{ + { + { 0x2f89c8a1, 0x3a4a369a, 0x7c8de80d, 0x63137a1d, 0x78eda015, -0x4353ff76, -0x4b7c4fc1, 0x2cb8b3a5 }, + { -0x13d5b3c8, -0x27cc2842, 0x0acc20ed, 0x2c916283, -0x6d208a7f, -0x16c5b856, 0x333c4a81, 0x702d67a3 }, + { -0x34e46f5f, 0x36e417cb, 0x7f11794e, 0x33b3ddaa, -0x77a439f9, 0x3f510808, -0x1957fdf3, 0x24141dc0 } + }, + { + { -0x427cea83, -0x6e6da234, 0x22cc8094, 0x3ca12053, 0x3f90d6e4, 0x28e57f18, -0x21d18985, 0x1a4714ce }, + { 0x3fefee9d, 0x59f73c77, -0x3e306763, -0x4c0e1077, -0x1fd1aba1, -0x1ca204be, 0x47a1b47c, 0x5766120b }, + { -0x47494801, -0x24df45f1, 0x77511fa1, -0x48cd3c4a, -0x660fd277, -0x56d4ae40, 0x489ca5f1, 0x4f3875ad } + }, + { + { -0x118c1140, 0x79ed13f6, 0x69110bb1, -0x5a39ad93, -0x79fc79f4, -0x1b76d73d, -0x028fa60b, 0x722a1446 }, + { 0x4932ab22, -0x380389d1, 0x2f4c3c1b, 0x7ac0edf7, -0x65576a18, 0x5f6b55aa, -0x52f5ff7f, 0x3680274d }, + { -0x573077e7, -0x2f6a6017, -0x7b8a5664, -0x2f566ab0, 0x20b09cc5, 0x6eac1733, 0x331b1095, 0x628ecf04 } + }, + { + { 0x5c74ccf1, -0x64be5308, 0x08265251, -0x498cce7f, 0x11adb147, -0x6636d513, 0x34ecb40f, 0x7a47d70d }, + { -0x562f2244, -0x67434ee8, 0x08b4802b, -0x11bb61cc, -0x47594efc, -0x78f76dda, 0x45c7915d, 0x685f349a }, + { -0x33bc5b0b, 0x60a0c4cb, 0x3677bea9, 0x775c66ca, 0x2ff8f5ed, -0x5e855e8b, 0x0e01fdc0, 0x11ded902 } + }, + { + { 0x3bea93b7, 0x471f95b0, 0x3313abd3, 0x0552d7d4, -0x1e81c085, -0x426c8f1e, -0x4df1a414, 0x7b120f1d }, + { -0x351018fc, -0x76f187f7, -0x1cf17394, -0x78d7d693, -0x6d514e37, 0x4c5cd2a3, 0x5771531f, 0x194263d1 }, + { -0x79afd286, 0x17d2fb3d, 0x50a69352, -0x4a9b27bc, -0x59f128a3, 0x7da962c8, 0x318736aa, 0x00d0f85b } + }, + { + { -0x0289de3f, -0x598ac3e2, 0x445671f5, 0x69c0b4a7, 0x05b23c11, -0x68e0ad8c, 0x51a8c7cd, 0x387bc748 }, + { 0x777c84fd, -0x6874ebd2, 0x05a8c062, -0x0bfd9bb9, -0x1819ed39, -0x59852ae5, -0x672295cd, 0x2f7b4596 }, + { 0x4a52a9a8, -0x7e76b4b3, -0x09477cd1, -0x5226c1ee, -0x49e429c8, 0x184d8548, -0x29360933, 0x3f1c62db } + }, + { + { 0x148f693d, 0x3fad3e40, -0x6b14658e, 0x052656e1, 0x184f4e2f, 0x2f4dcbfd, -0x3b7d1e75, 0x406f8db1 }, + { -0x6e6ef3e1, 0x2e8f1f00, -0x400d1ed4, -0x5b20b020, -0x116d8bc8, 0x60c6560a, -0x53103706, 0x6338283f }, + { 0x7f191ee4, -0x619cf2d4, -0x43c00990, 0x4fbf8301, 0x7afb73c4, 0x787d8e4e, -0x170a705b, 0x50d83d5b } + }, + { + { -0x4b2c4993, -0x3f533070, 0x61732e60, -0x58fa621b, 0x70c6b0ba, 0x033d1f78, 0x26d946e4, 0x584161cd }, + { -0x3ee5e769, -0x7a97c6ea, -0x1af92ff8, 0x2d69a4ef, -0x099b42ff, 0x39af1378, 0x361517c6, 0x65942131 }, + { 0x72d27ca2, -0x440d4e60, -0x042138fc, -0x40c6c3a7, -0x1d9d47e2, -0x16724432, 0x3029b589, 0x02eebd0b } + }, +}, +{ + { + { 0x7b85c5e8, -0x789a4961, -0x2e97454e, 0x6ff0678b, 0x1d330f9b, 0x3a70e77c, -0x4f507184, 0x3a5f6d51 }, + { -0x59f253a1, 0x61368756, -0x145423a9, 0x17e02f6a, 0x4cce0f7d, 0x7f193f2d, -0x76132310, 0x20234a77 }, + { 0x7178b252, 0x76d20db6, -0x2ae12ea0, 0x071c34f9, -0x4c1bee90, -0x09d5b5e0, 0x3cffe366, 0x7cd68235 } + }, + { + { 0x68acf4f3, -0x599a32a0, 0x3cd7e3d3, 0x42d92d18, 0x336025d9, 0x5759389d, 0x2b2cd8ff, 0x3ef0253b }, + { -0x2778054a, 0x0be1a45b, -0x45bfc492, 0x2a846a32, -0x1691a000, -0x266defee, 0x3bdc0943, 0x2838c886 }, + { 0x4a465030, -0x2e944f31, 0x15c577ab, -0x05b694bf, -0x0b54be63, -0x7d305176, 0x06a82812, 0x21dcb8a6 } + }, + { + { -0x4188ce46, -0x6572ff06, 0x629e1889, -0x7dfc9f82, 0x43f3d97f, -0x4d33fdc9, 0x6c6f678b, 0x5d840dbf }, + { -0x73626038, 0x5c600446, -0x2bd55c35, 0x2540096e, 0x12ee2f9c, 0x125b4d4c, -0x6b5ce255, 0x0bc3d081 }, + { 0x309fe18b, 0x706e380d, -0x461e9a39, 0x6eb02da6, 0x7dae20ab, 0x57bbba99, 0x2ac196dd, 0x3a427623 } + }, + { + { -0x24bb8135, 0x3bf8c172, -0x39d7d243, 0x5fcfc41f, 0x75aa15fe, -0x7f530040, 0x24e1a9f9, 0x0770c9e8 }, + { -0x758f7b06, 0x4b42432c, -0x20461abb, -0x7675e61d, -0x63a71ba3, -0x4160ffdf, -0x5e92142f, 0x1ff177ce }, + { 0x45b5b5fd, -0x309e2666, 0x1b3a7924, -0x79f67b17, 0x303e3e89, -0x18cff6e7, 0x41500b1e, 0x39f264fd } + }, + { + { -0x01f6841f, -0x2e64b555, -0x201fe6d7, -0x5b92031f, 0x2ca6f1ff, -0x3c36f76c, 0x2c35f14e, 0x65c62127 }, + { -0x24181d64, -0x5852cbe9, 0x2b9c139c, -0x426bc896, -0x6ca68457, -0x5f16e472, 0x68889840, 0x1712d734 }, + { -0x31ce6c23, -0x18d47608, -0x5eda3f45, 0x4d103356, 0x2e1cfe83, 0x0419a93d, -0x4e631d8e, 0x22f9800a } + }, + { + { -0x65910254, 0x42029fdd, 0x34a54941, -0x46ed3142, -0x78420c85, 0x640f64b9, -0x7a67354c, 0x4171a4d3 }, + { 0x3e9ef8cb, 0x605a368a, -0x5aafb8eb, -0x1c163fde, 0x5f24248f, 0x553d48b0, 0x647626e5, 0x13f416cd }, + { -0x6636b374, -0x05d8a756, -0x4fff47f9, 0x23006f6f, -0x5225ac6e, -0x042d6e23, 0x574bd1ab, 0x508214fa } + }, + { + { 0x53d003d6, 0x461a15bb, -0x430c369b, -0x4defd778, 0x6c683a5a, 0x27c57675, -0x37934bb9, 0x3a7758a4 }, + { 0x3ed6fe4b, -0x3dfd96eb, 0x511d77c4, -0x59a598c7, 0x2c14af94, -0x3421d9ba, 0x6faba74b, 0x22f960ec }, + { -0x6c51af8a, 0x548111f6, 0x1dfd54a6, 0x1dae21df, -0x0ceea19b, 0x12248c90, -0x72180b6c, 0x5d9fd15f } + }, + { + { -0x1128ade2, 0x3f244d2a, 0x432e9615, -0x71c56fd8, 0x2e9c16d4, -0x1e9b4589, 0x47eb98d8, 0x3bc187fa }, + { 0x6d63727f, 0x031408d3, -0x28384acd, 0x6a379aef, -0x33511db5, -0x561e703b, 0x4f8fbed3, 0x332f3591 }, + { -0x15793df4, 0x6d470115, 0x6c46d125, -0x66754835, 0x3a660188, -0x2887cd4b, -0x6f9045fd, 0x450d81ce } + }, +}, +{ + { + { -0x4d351f4b, 0x23264d66, -0x14359a8a, 0x7dbaed33, -0x0f2db538, 0x030ebed6, -0x089caaf0, 0x2a887f78 }, + { -0x27bac6fe, -0x0751b2d6, -0x1724d2e3, 0x7018058e, -0x382d3ee2, -0x554c66a1, 0x24ccca79, 0x53b16d23 }, + { 0x5c012d4f, 0x2a23b9e7, -0x351e0d16, 0x0c974651, 0x675d70ca, 0x2fb63273, -0x79bbfc0b, 0x0ba7250b } + }, + { + { -0x79079264, -0x229ca76d, -0x1ec57a5c, 0x61699176, 0x4eaa7d57, 0x2e511195, -0x049f4205, 0x32c21b57 }, + { 0x029c6421, -0x44f2e703, -0x76d670fe, -0x43d2ebdf, -0x74daf16a, -0x7cb8071a, 0x032d71c9, 0x7b9f2fe8 }, + { 0x319e0780, -0x2787dc33, -0x76888a3b, -0x103b303f, -0x65f54c09, 0x4854fb12, 0x7238c371, 0x12c49d41 } + }, + { + { -0x7c866abe, 0x09b3a017, -0x552a11c1, 0x626dd08f, -0x148feb61, -0x45ff4312, -0x5f5bbb37, 0x1421b246 }, + { -0x0017c897, 0x0950b533, -0x71e2942f, 0x21861c1d, 0x1302e510, -0x0fdd27c8, 0x6391cab4, 0x2509200c }, + { -0x73db5839, 0x4aa43a8e, -0x270fa10b, 0x04c1f540, 0x0b3eb9dc, -0x5245a1f4, 0x48a49ce3, 0x2ab55044 } + }, + { + { 0x1c5d3afa, -0x23f8539d, -0x06207394, 0x58615171, -0x628c1d50, 0x72a079d8, -0x4b151ea3, 0x7301f4ce }, + { 0x6f0f5dec, 0x2ed22726, 0x5ed50824, -0x67db11bf, -0x6b972beb, -0x7f841384, -0x4ade1dc1, 0x7093bae1 }, + { -0x298dd3bf, 0x6409e759, 0x72bf729b, -0x598b1e31, 0x3c21e569, -0x43f5db15, 0x4ebacb23, 0x390167d2 } + }, + { + { -0x5d0dedf5, -0x2844fab5, -0x4efa7649, -0x1d463152, -0x0c3f1242, 0x3fe8bac8, 0x7112cb69, 0x4cbd4076 }, + { -0x45cac0e4, 0x27f58e3b, -0x4095bc9f, 0x4c47764d, 0x6e562650, -0x50443b1b, -0x551e5ba3, 0x07db2ee6 }, + { 0x29c58176, 0x0b603cc0, 0x5cb15d61, 0x5988e382, -0x230f5273, 0x2bb61413, 0x74183287, 0x7b8eec6c } + }, + { + { -0x03c7948d, 0x32fee570, -0x25c57339, -0x2574febf, -0x37697ca7, -0x68a002f6, -0x4ecd57ab, 0x6ee809a1 }, + { 0x2cd27cb0, -0x1b35bf88, -0x04169843, -0x25063cdd, -0x752be162, -0x4d642cb6, 0x626ede4d, 0x72810497 }, + { -0x030279c6, -0x6bbb44cf, 0x3e4e48c5, 0x2fe3690a, -0x2f7705db, -0x23d63799, -0x2e8cd6d2, 0x13bd1e38 } + }, + { + { 0x1dfac521, 0x223fb5cf, 0x6f554450, 0x325c2531, 0x659177ac, 0x030b98d7, 0x4f88a4bd, 0x1ed018b6 }, + { 0x696149b5, -0x2cd4b328, -0x7e275549, -0x1aa6c829, -0x51edd46c, 0x0bcb2127, -0x4ebf6650, 0x41e86fcf }, + { -0x47fd5950, 0x3630dfa1, 0x42ad3bd5, -0x77f078b9, -0x113a5b2c, 0x0af90d6c, 0x37cdc5d9, 0x746a247a } + }, + { + { 0x78d941ed, 0x6eccd852, -0x2dd087bd, 0x2254ae83, 0x7bbfcdb7, -0x3add2fd2, -0x400f1b1e, 0x681e3351 }, + { 0x2b7b9af6, -0x2ace4743, 0x37fc5b51, 0x50050935, -0x3a6cab93, 0x232fcf25, 0x2bb40f49, 0x20a36514 }, + { -0x7cfcb0bb, -0x749b4a63, 0x1fa20efb, 0x2f8b71f2, -0x459aaf1c, 0x69249495, 0x45d5472b, 0x539ef98e } + }, +}, +{ + { + { 0x1cae743f, -0x2f8b276a, -0x11e39c13, -0x0792e70b, -0x180b12d7, -0x68423aa5, 0x663ab108, 0x4cbad279 }, + { -0x59dfad8b, 0x6e7bb6a1, 0x413c8e83, -0x55b0de29, -0x1770a34e, 0x6f56d155, -0x59cba41f, 0x2de25d4b }, + { -0x5f28e033, -0x7f2e6fdc, -0x04d77508, -0x3ada3df6, 0x5f3a6419, -0x4e5c68b5, -0x1dff8dcd, 0x7d7fbcef } + }, + { + { -0x0c3d6f6c, -0x3283a23b, 0x2a9105ab, -0x387e5d66, 0x421c3058, -0x7f39e2ca, -0x23272b29, 0x4f9cd196 }, + { 0x266b2801, -0x0510e196, -0x2a8c60ea, -0x7993973c, 0x1b03762c, -0x0975d044, -0x7848a573, 0x5975435e }, + { 0x6a7b3768, 0x199297d8, 0x1ad17a63, -0x2f2fa7dc, 0x5c1c0c17, -0x45fd6353, 0x387a0307, 0x7ccdd084 } + }, + { + { 0x6760cc93, -0x64f37be8, 0x1ab32a99, -0x3251ff86, 0x620bda18, -0x5772137a, -0x7e6f35bc, 0x3593ca84 }, + { 0x6d260417, -0x2359bdd4, -0x6b7dbf43, -0x51eac2b0, -0x04973989, -0x563f3e4c, 0x61d0cf53, 0x428bd0ed }, + { 0x5e849aa7, -0x6dece766, 0x65d8facd, -0x2b273ccb, 0x53fdbbd1, -0x73adaba5, -0x25d29c1a, 0x27398308 } + }, + { + { 0x0a702453, -0x465ef1b4, -0x2a82e422, 0x0fa25866, -0x32d82509, -0x0046264b, 0x492c33fd, 0x572c2945 }, + { 0x435ed413, 0x42c38d28, 0x3278ccc9, -0x42af0ca0, 0x79da03ef, -0x44f854e6, -0x4173ccab, 0x269597ae }, + { -0x2932cf42, -0x388038bb, -0x1c455105, -0x1b20172d, -0x55a225f4, -0x5dd377d0, -0x3fa43580, 0x7f985498 } + }, + { + { 0x0fbf6363, -0x2ca9eaae, -0x30b2045a, 0x08045a45, -0x78c05f3e, -0x113db044, -0x2964ed19, 0x30f2653c }, + { -0x60f41ee9, 0x3849ce88, 0x7b54a288, -0x7ffa52e5, 0x23fc921c, 0x3da3c39f, 0x0a31f304, 0x76c2ec47 }, + { -0x553ef37b, -0x75f736c8, -0x24d89435, 0x46179b60, 0x0e6fac70, -0x56df3fe2, 0x596473da, 0x2f1273f1 } + }, + { + { 0x55a70bc0, 0x30488bd7, -0x0e2bbd19, 0x06d6b5a4, -0x43a69e9e, -0x152e5962, -0x123a087c, 0x38ac1997 }, + { -0x751fe1ef, 0x4739fc7c, 0x4a6aab9f, -0x02ad8b70, -0x788d70d2, 0x41d98a82, -0x27a4960e, 0x5d9e572a }, + { -0x58ae4ec5, 0x0666b517, 0x7e9b858c, 0x747d0686, 0x454dde49, -0x53533fef, -0x40161964, 0x22dfcd9c } + }, + { + { 0x103be0a1, 0x56ec59b4, -0x2da60697, 0x2ee3baec, 0x13f5cd32, 0x797cb294, 0x24cde472, 0x0fe98778 }, + { -0x3cf2f327, -0x72242d20, -0x5344bccd, -0x527199a1, 0x322a961f, -0x7094da74, 0x5448c1c7, 0x6b2916c0 }, + { 0x0aba913b, 0x7edb34d1, 0x2e6dac0e, 0x4ea3cd82, 0x6578f815, 0x66083dff, 0x7ff00a17, 0x4c303f30 } + }, + { + { 0x0dd94500, 0x29fc0358, 0x6fbbec93, -0x132d855c, -0x3d1d5808, 0x130a155f, -0x48f95e2b, 0x416b151a }, + { 0x17b28c85, -0x2cf5c42a, 0x39773bea, -0x3a2c8849, 0x1e6a5cbf, -0x39391874, -0x74d5483c, 0x0d61b8f7 }, + { -0x163ec950, 0x56a8d7ef, 0x58e44b20, -0x42f81a33, 0x1b57e0ab, -0x5019d026, 0x4277e8d2, 0x191a2af7 } + }, +}, +{ + { + { 0x2fe09a14, 0x09d4b60b, -0x244e8b82, -0x3c7b0f51, 0x78b5fd6e, 0x58e2ea89, -0x4a1f64f6, 0x519ef577 }, + { -0x5490b67b, -0x2aaff6a5, 0x4fbfaf1a, 0x04f4cd5b, 0x2a0c7540, -0x6271d12f, -0x4ddedd7a, 0x2bc24e04 }, + { 0x1124cca9, 0x1863d7d9, -0x47758f72, 0x7ac08145, -0x7a8fce0b, 0x2bcd7309, -0x7547051b, 0x62337a6e } + }, + { + { 0x1b3a1273, -0x2e54cdb2, -0x7efaacc0, 0x18947cf1, -0x5673e692, 0x3b5d9567, -0x7fd1e198, 0x7fa00425 }, + { 0x06ffca16, 0x4bcef17f, 0x692ae16a, -0x21f91e25, 0x614f42b0, 0x0753702d, 0x5b9212d0, 0x5f6041b4 }, + { 0x028c2705, 0x7d531574, -0x24f28a02, -0x7fce8297, -0x10737223, 0x30fface8, -0x493c1668, 0x7e9de97b } + }, + { + { -0x5db2bf23, -0x0ffb419e, 0x0452d41f, -0x45f9a66f, 0x62a44234, -0x7e3ba11f, -0x5ddd9911, 0x4cb829d8 }, + { -0x619a7a5d, 0x1558967b, -0x6716746e, -0x68366320, 0x6eb3adad, 0x10af149b, -0x0b2c7306, 0x42181fe8 }, + { 0x07b86681, 0x1dbcaa84, -0x74d98ac5, 0x081f001e, -0x7bfb717f, 0x3cd7ce6a, 0x3f25f22c, 0x78af1163 } + }, + { + { 0x7d65318c, 0x3241c00e, -0x2f179219, -0x19411a24, -0x043f73da, 0x118b2dc2, -0x039fc23d, 0x680d04a7 }, + { 0x0b50babc, -0x7be9142c, 0x28208bee, 0x15087226, -0x463e3c93, -0x5ceb7051, -0x2cd282a3, 0x0d07daac }, + { 0x695aa3eb, -0x063dbeb6, 0x05a68f21, -0x255bd3b4, 0x7f93963e, 0x7c6c2398, 0x0c3954e3, 0x210e8cd3 } + }, + { + { 0x37fe6c26, 0x2b50f161, 0x56e404d8, -0x1efd4328, 0x4c561f6b, 0x12b0f141, -0x2fd7136f, 0x51b17bc8 }, + { 0x10a71c06, -0x53bdfe0e, -0x0c404fdf, 0x6a65e0ae, 0x393632f7, -0x43bd3ca4, -0x79a0f8be, 0x56ea8db1 }, + { -0x30acaee7, -0x000a04b5, -0x20eef760, -0x0b676287, -0x65c45cdb, -0x4203159b, 0x74d1a6f2, 0x18a11f11 } + }, + { + { -0x2d85a0d4, -0x0429c326, -0x755ef929, -0x0ff03b44, -0x719b5bd0, 0x53fb5c1a, 0x0c1a2e85, 0x04eaabe5 }, + { 0x3f6bba29, 0x407375ab, -0x66e1b7d2, -0x613c4928, -0x1aa06d17, -0x6637f17e, -0x04f3f51f, 0x307c13b6 }, + { -0x34754a19, 0x24751021, 0x5c5010eb, -0x03dcbbb7, 0x4e5610a1, 0x5f1e717b, -0x3d8ef32b, 0x44da5f18 } + }, + { + { -0x76271534, -0x6ea90195, -0x1dced95f, -0x19486baf, 0x3944eb4e, -0x428b9c27, 0x767203ae, 0x726373f6 }, + { -0x0e47d14b, 0x033cc55f, 0x411cae52, -0x4ea51c93, -0x7004532d, -0x45bf49e7, 0x532e861f, 0x768edce1 }, + { -0x14810976, -0x1cfa358e, 0x70eadb23, 0x662cf31f, -0x4b3ba498, 0x18f026fd, -0x4a2d1343, 0x513b5384 } + }, + { + { -0x750cb315, 0x5e270287, -0x46b92952, -0x6ff4fbf7, -0x25427aee, 0x6512ebf7, -0x77da707f, 0x61d9b769 }, + { -0x38d66762, 0x46d46280, 0x5368a5dd, 0x4b93fbd0, -0x2e89a577, 0x63df3f81, -0x465f5ddd, 0x34cebd64 }, + { 0x49b7d94b, -0x593a58ed, 0x23eb9446, -0x5c0c2ea8, 0x77484834, 0x0416fbd2, 0x2c70812f, 0x69d45e6f } + }, +}, +{ + { + { 0x4f460efb, -0x6019d4bd, -0x59c9f82a, -0x212cfc2c, -0x485f25dc, -0x0faddef2, 0x00545b93, 0x237e7dbe }, + { -0x3ac3ebcf, -0x31e908b5, 0x2072edde, 0x2b9725ce, -0x4a4dc119, -0x47463c91, 0x0b5cc908, 0x7e2e0e45 }, + { 0x6701b430, 0x013575ed, -0x60f402f0, 0x231094e6, -0x7c1b80de, 0x75320f15, -0x4eeeaa1d, 0x71afa699 } + }, + { + { 0x473b50d6, -0x15bdc3e4, 0x3b38ef10, 0x51e87a1f, -0x4d36416b, -0x647b40a1, 0x78f89a1c, 0x00731fbc }, + { 0x3953b61d, 0x65ce6f9b, -0x505ebe1a, -0x39a7c616, -0x5608a602, 0x0f435ffd, -0x3d4e3d72, 0x021142e9 }, + { 0x48f81880, -0x1bcf38e8, 0x5ecec119, -0x4069f3de, 0x6bba15e3, -0x49251f7d, 0x47e15808, 0x4c4d6f33 } + }, + { + { -0x6770e690, 0x2f0cddfc, -0x4f460ae5, 0x6b916227, 0x779176be, 0x6ec7b6c4, -0x57706058, 0x38bf9500 }, + { -0x3e82e037, 0x18f7eccf, 0x51403c14, 0x6c75f5a6, -0x0811f321, -0x24218ed5, -0x581b85de, 0x193fddaa }, + { 0x37e8876f, 0x1fd2c93c, 0x18d1462c, -0x5d09e1a6, 0x39241276, 0x5080f582, -0x40f2b697, 0x6a6fb99e } + }, + { + { -0x491bdc3a, -0x114edd4b, -0x0d790072, -0x6c628ff0, 0x1dcf5d8c, -0x6f56d57d, 0x42c5eb10, 0x136fda9f }, + { 0x560855eb, 0x6a46c1bb, -0x076c0f63, 0x2416bb38, -0x708e533f, -0x28e2eec9, -0x5ce76916, 0x75f76914 }, + { -0x5cfa422f, -0x06b3204f, -0x6007d3f8, 0x0f364b9d, -0x3c44a776, 0x2a87d8a5, 0x0be8dcba, 0x02218351 } + }, + { + { 0x43307a7f, -0x62a58eff, -0x3b825ba1, -0x4f9c2162, -0x416d852d, 0x22bbfe52, -0x02bfbd94, 0x1387c441 }, + { 0x5ead2d14, 0x4af76638, -0x3583a7d0, -0x5f712780, 0x10211e3d, 0x0d13a6e6, 0x7b806c03, 0x6a071ce1 }, + { -0x78687508, -0x4a2c3c2f, 0x7f0e4413, 0x722b5a3d, -0x44b88360, 0x0d7b4848, -0x50e1236e, 0x3171b26a } + }, + { + { -0x4d75b82f, -0x59f24828, 0x1770a4f1, -0x5940eb2a, 0x53ddbd58, -0x2b5e076d, 0x344243e9, 0x6c514a63 }, + { -0x68a9b358, -0x56d0ce70, 0x2275e119, -0x008447b4, -0x5b78aeb0, 0x4f55fe37, 0x3cf0835a, 0x221fd487 }, + { 0x3a156341, 0x2322204f, -0x45f5fcd3, -0x048c1f17, 0x410f030e, -0x031f22b4, -0x046db556, 0x48daa596 } + }, + { + { -0x37b3686d, 0x14f61d5d, -0x10be7dfa, -0x66be061d, 0x346277ac, -0x320a4771, 0x0e8a79a9, 0x58c837fa }, + { 0x5ca59cc7, 0x6eca8e66, 0x2e38aca0, -0x57b8dab5, -0x2de1e832, 0x31afc708, -0x3527b509, 0x676dd6fc }, + { -0x69036fa8, 0x0cf96885, 0x7b56a01b, 0x1ddcbbf3, 0x4935d66a, -0x233d1883, -0x395a80f6, 0x1c4f73f2 } + }, + { + { -0x0383cb7c, -0x4c918f92, -0x3c3e309f, 0x73dfc9b4, 0x781cc7e5, -0x14e28637, 0x7daf675c, 0x70459adb }, + { 0x305fa0bb, 0x0e7a4fbd, 0x54c663ad, -0x7d62b320, 0x2fe33848, -0x0bde3c7d, 0x1bf64c42, 0x795ac80d }, + { -0x6e4bd44d, 0x1b91db49, 0x4b02dcca, 0x57269623, 0x1f8c78dc, -0x6020611b, -0x731de02d, 0x5fe16284 } + }, +}, +{ + { + { -0x6aeeac77, 0x315c29c7, -0x79d08b32, -0x281f1af9, -0x7a6d8bce, 0x0c4a7621, 0x4a25a1e4, 0x72de6c98 }, + { 0x4d077c41, -0x1d86f552, -0x248b965d, -0x746c7d90, -0x7542e95e, 0x6eb632dc, -0x55f9b48e, 0x720814ec }, + { -0x40955cf0, -0x51654aad, -0x7f9291e5, 0x050a50a9, -0x5200aec7, -0x6d448bfd, 0x45be618b, 0x0394d276 } + }, + { + { -0x4dcaba5c, -0x0ac69bdb, -0x67044d6a, 0x15a7a27e, 0x636fdd86, -0x5493ad44, 0x419334ee, 0x79d995a8 }, + { -0x7a81120c, 0x4d572251, -0x1e616c3b, -0x1c8db123, 0x0b797035, -0x758ebdf2, -0x785418bd, 0x3b3c8336 }, + { 0x1195dd75, -0x3275715a, 0x1dd9a82f, -0x5afb2758, -0x5ca7864a, 0x540dca81, 0x79c86a8a, 0x60dd16a3 } + }, + { + { 0x153e47b8, 0x3501d6f8, 0x14a2f60c, -0x485698ac, 0x455d9523, 0x112ee8b6, -0x7eed1576, 0x4e62a3c1 }, + { 0x7381e559, 0x35a2c848, -0x287f7d35, 0x596ffea6, -0x245849ad, -0x34688e15, -0x64b2597b, 0x5a08b501 }, + { 0x516ab786, -0x372b53fc, 0x5295b23d, 0x595af321, -0x24fdcf3f, -0x29122dcc, -0x7da4be34, 0x0929efe8 } + }, + { + { -0x52a99ae3, -0x74ce8d49, 0x3fabd717, 0x01581b7a, 0x424df6e4, 0x2dc94df6, 0x2c29284f, 0x30376e5d }, + { -0x342f0d2d, 0x5f0601d1, 0x6132bb7f, 0x736e412f, 0x238dde87, -0x7c9fbbce, -0x0a3f8ac4, 0x1e3a5272 }, + { -0x7ea65a64, -0x2d6e7259, 0x3f0713f3, 0x6bdc1cd9, 0x4acd6590, 0x565f7a93, 0x4cb4c128, 0x53daacec } + }, + { + { -0x7ad30250, -0x667ad43d, 0x59d6ed0b, 0x2cc12e95, -0x64a53d85, 0x70f9e2bf, 0x7959ae99, 0x4f3b8c11 }, + { -0x6337582a, 0x4ca73bd7, 0x47e9a9b2, 0x4d4a738f, 0x42f5fe00, -0x0b340ed7, -0x4240f8ae, 0x01a13ff9 }, + { 0x2ff26412, 0x55b6c9c8, 0x1fb667a8, 0x1ac4a8c9, -0x1488740e, -0x2ad84031, 0x7012a3be, 0x303337da } + }, + { + { -0x052d022f, -0x6892c335, 0x37a640a8, -0x34777c69, 0x6734cb25, 0x2ff00c1d, 0x789c2d2b, 0x269ff4dc }, + { -0x73e36284, -0x6aabddde, 0x1a9b340f, 0x01fac137, -0x6da4b729, 0x7e8d9177, 0x61b3e31b, 0x53f8ad56 }, + { -0x3f729873, 0x0c003fbd, 0x7ead2b17, 0x4d982fa3, -0x4d1a7d0f, -0x3f819433, -0x20bed5bc, 0x296c7291 } + }, + { + { -0x25474a62, -0x204dcdfb, -0x37f6ddb0, 0x465aeaa0, -0x658da2e8, -0x2ecc3ee8, 0x61f117d1, 0x23273702 }, + { 0x33daf397, 0x7903de2b, -0x3659db4d, -0x2f00f9e7, 0x555b3e18, -0x75e2dad5, 0x52e0b7c0, 0x2b6d581c }, + { 0x623e7986, 0x3d0543d3, -0x3d875cac, 0x679414c2, 0x726196f6, -0x51bc0f34, -0x7dba1546, 0x7836c41f } + }, + { + { -0x7fee6c84, -0x359ae17c, 0x6ef41a28, -0x394f3b92, 0x5f3f8d52, -0x48fde459, -0x15284603, 0x119dff99 }, + { 0x49e95a81, -0x185dab25, 0x08b0ad73, 0x5192d5d0, -0x2ff503f9, 0x4d20e5b1, 0x2cf25f38, 0x5d55f801 }, + { -0x0b4ce2b3, 0x43eadfcb, 0x11148892, -0x39afc08c, 0x060d3b17, -0x0111973b, -0x22b5f538, 0x329293b3 } + }, +}, +{ + { + { 0x5d7cb208, 0x2879852d, 0x687df2e7, -0x47212290, 0x21687891, -0x23f40055, 0x677daa35, 0x2b44c043 }, + { -0x1e6b69e6, 0x4e59214f, 0x0d71cd4f, 0x49be7dc7, 0x3b50f22d, -0x6cff302e, -0x036e8dce, 0x4789d446 }, + { 0x074eb78e, 0x1a1c87ab, -0x66250b99, -0x05392e72, 0x484f9067, 0x3eacbbcd, 0x2bb9a4e4, 0x60c52eef } + }, + { + { 0x7cae6d11, 0x702bc5c2, 0x54a48cab, 0x44c7699b, -0x45b6d14e, -0x1043bfaa, -0x26499893, 0x70d77248 }, + { 0x3bfd8bf1, 0x0b5d89bc, -0x360caae6, -0x4f946dc9, -0x2acfd70b, 0x0e4c16b0, 0x2ccfcaab, 0x10bc9c31 }, + { 0x3ec2a05b, -0x557517b5, -0x12e87e20, -0x6796610c, 0x708e85d1, 0x794513e4, -0x56890bed, 0x63755bd3 } + }, + { + { -0x680e5349, 0x3dc71018, -0x3e9a4428, 0x5dda7d5e, 0x0fa1020f, 0x508e5b9c, 0x37c52a56, 0x27637517 }, + { 0x2ad10853, -0x4aa05fc2, -0x6119ca97, 0x356f7590, -0x41964770, -0x60060e03, -0x743e907c, 0x0d8cc1c4 }, + { 0x6eb419a9, 0x029402d3, 0x77b460a5, -0x0f4bb182, -0x2bc3b6aa, -0x30579dd0, 0x7ad166e7, 0x70c2dd8a } + }, + { + { -0x471281ed, -0x6e2b6983, -0x28897e86, 0x74252f0a, 0x0d852564, -0x1bf67d20, 0x16a53ce5, 0x32b86138 }, + { -0x609013f2, 0x65619450, 0x46c6518d, -0x11d18157, 0x67e09b5c, -0x68cc3e0d, 0x63948495, 0x2e0fac63 }, + { -0x1bb7329c, 0x79e7f7be, 0x087886d0, 0x6ac83a67, -0x5f1b24d2, -0x07602b27, 0x735a4f41, 0x4179215c } + }, + { + { 0x286bcd34, -0x1b51cc47, 0x559dd6dc, -0x4810814a, -0x4c2c71e1, 0x278b141f, 0x2241c286, 0x31fa8566 }, + { -0x282312d6, -0x738f6b19, 0x47d39c70, -0x6804753d, -0x56f926fe, -0x1ec41fcd, 0x0cd99d76, 0x700344a3 }, + { 0x2e3622f4, -0x507d93be, -0x67ccafd3, -0x3edfd679, 0x2b389123, -0x643e481f, -0x566adb77, 0x24bb2312 } + }, + { + { -0x0a07a395, 0x41f80c2a, 0x04fa6794, 0x687284c3, -0x5c45e453, -0x76ba2067, -0x0014a2ea, 0x0d1d2af9 }, + { 0x32de67c3, -0x4e5712e9, 0x461b4948, 0x3cb49418, 0x76cfbcd2, -0x7142bcbd, 0x1e188008, 0x0fee3e87 }, + { 0x32621edf, -0x5625755f, 0x59226579, 0x30b822a1, -0x58653e6d, 0x4004197b, 0x18531d76, 0x16acd797 } + }, + { + { 0x7887b6ad, -0x36a6393b, 0x5f90feba, -0x6b1e6153, -0x5cbd0afc, 0x16e24e62, 0x18161700, 0x164ed34b }, + { 0x2d9b1d3d, 0x72df72af, -0x5bcddba6, 0x63462a36, 0x16b39637, 0x3ecea079, -0x46cfdcf7, 0x123e0ef6 }, + { 0x192fe69a, 0x487ed94c, 0x3a911513, 0x61ae2cea, -0x465b21d9, -0x7884092d, 0x1073f3eb, 0x78da0fc6 } + }, + { + { 0x680c3a94, -0x5d607f0f, 0x1ae9e7e6, 0x71f77e15, 0x48017973, 0x1100f158, 0x16b38ddd, 0x054aa4b3 }, + { -0x1ad43996, 0x5bf15d28, 0x70f01a8e, 0x2c47e318, 0x06c28bdd, 0x2419afbc, 0x256b173a, 0x2d25deeb }, + { 0x19267cb8, -0x2037b973, 0x66e54daf, 0x0b28789c, 0x666eec17, 0x2aeb1d2a, -0x548258a0, 0x134610a6 } + }, +}, +{ + { + { -0x23fd73c4, -0x26ebcf20, 0x5217c771, 0x0eb955a8, 0x2c99a1fa, 0x4b09e1ed, -0x42958bc4, 0x42881af2 }, + { 0x7c59b23f, -0x350aa13e, 0x154d04f2, -0x665112c2, -0x1ebebe0c, 0x68441d72, 0x3932a0a2, 0x14034513 }, + { -0x54a352c3, 0x7bfec69a, 0x4cb2cfad, -0x3dc1732d, -0x04c8295e, 0x685dd14b, 0x15677a18, 0x0ad6d644 } + }, + { + { 0x47927e9f, 0x79148928, 0x370aa877, 0x33dad6ef, 0x11122703, 0x1f8f24fa, 0x2adf9592, 0x5265ac2f }, + { 0x417becb5, 0x781a439e, -0x2ef1fd9a, 0x4ac5938c, 0x0692ac24, 0x5da38511, -0x521cedcd, 0x11b065a2 }, + { -0x65034cba, 0x405fdd30, 0x28e63f54, -0x268dc2bc, 0x5f65aaae, -0x6b3fe210, -0x1eb3f7f7, 0x43e4dc3a } + }, + { + { -0x523d395d, -0x1590853d, -0x168e836c, -0x2f16d70a, -0x29ba150b, -0x1d2c8616, -0x3ae00442, 0x46dd8785 }, + { -0x56c75ae9, -0x43ed380f, 0x3180b2e1, 0x473028ab, -0x0432dab6, 0x3f78571e, 0x6ff6f90f, 0x74e53442 }, + { 0x375c8898, 0x709801be, -0x1c027cb8, 0x4b06dab5, 0x27230714, 0x75880ced, -0x22d0b3be, 0x2b09468f } + }, + { + { -0x7d005fd6, 0x5b979465, -0x01570ab7, -0x25f695af, 0x5f77af9b, -0x5f9caec9, 0x201d1e76, 0x1bcfde61 }, + { -0x48fe346a, -0x6838b612, -0x495c963d, -0x7c0bc72c, -0x65bfd327, 0x62962b8b, -0x67772085, 0x6976c750 }, + { 0x246a59a2, 0x4a4a5490, -0x17802270, -0x29c14222, 0x0d2371fa, -0x26bc8399, -0x2cf0712a, 0x69e87308 } + }, + { + { -0x7437fcfd, 0x0f80bf02, 0x7a18cefb, 0x6aae16b3, -0x28d3295d, -0x22b815b9, -0x0b12c656, 0x61943588 }, + { 0x5656beb0, 0x435a8bb1, 0x4f4d5bca, -0x07053646, 0x1548c075, -0x464d873c, -0x176d49de, 0x3eb0ef76 }, + { -0x6efc607b, -0x2d91a3c2, -0x090cc557, -0x3f161883, 0x70066a93, -0x176973ab, 0x1faaaddd, 0x3c34d188 } + }, + { + { 0x2fffe0d9, -0x42a4f471, 0x3ed24fb9, 0x6aa25410, -0x4d97de3c, 0x2ac7d7bc, 0x60dca36a, 0x605b394b }, + { -0x5f606140, 0x3f9d2b5e, -0x49dc5770, 0x1dab3b6f, 0x72d926c4, -0x5f645c16, 0x3fd8b36d, 0x37419351 }, + { 0x5a9d1ed2, -0x4b17a91c, 0x6c97a9a2, -0x1017b78a, 0x1e5eee7d, -0x4efb309c, -0x7758e371, 0x2f50b81c } + }, + { + { -0x5825add6, 0x2b552ca0, 0x449b0250, 0x3230b336, -0x5b466047, -0x0d3b3a44, 0x58074a22, 0x7b2c6749 }, + { -0x0397ee45, 0x31723c61, 0x6211800f, -0x634bafb8, 0x47995753, 0x768933d3, 0x02752fcd, 0x3491a535 }, + { 0x3ed28cdf, -0x2aae9a78, -0x2c9d21c7, 0x12d84fd2, -0x1cc871b1, 0x0a874ad3, 0x7c763e74, 0x000d2b1f } + }, + { + { 0x3e94a8ab, -0x69db8874, -0x16587414, 0x0ad6f3ce, 0x0d743c4f, -0x6b75387f, -0x55130334, 0x76627935 }, + { -0x2f92b599, 0x3d420811, -0x6f1f001d, -0x4103fb7b, -0x42b78422, -0x078f3949, 0x319afa28, 0x6e2a7316 }, + { -0x292a6561, 0x56a8ac24, 0x3096f006, -0x37248ac2, -0x70b3ad67, 0x477f41e6, -0x09379eec, 0x588d851c } + }, +}, +{ + { + { 0x77d1f515, -0x32d59a19, -0x70559f0f, 0x54899187, -0x2543f91b, -0x4e48c444, -0x56833605, 0x654878cb }, + { -0x72094f02, 0x51138ec7, -0x1a8a0ae5, 0x5397da89, 0x717af1b9, 0x09207a1d, 0x2b20d650, 0x2102fdba }, + { 0x055ce6a1, -0x69611bfb, 0x1251ad29, 0x36bca768, -0x55825beb, 0x3a1af517, 0x29ecb2ba, 0x0ad725db } + }, + { + { -0x64fa907b, -0x013843f4, -0x180a0029, 0x537d5268, 0x4312aefa, 0x77afc662, 0x02399fd9, 0x4f675f53 }, + { -0x7cb1dba9, -0x23bd984f, 0x70ce1bc5, -0x498abb4b, -0x082ea129, 0x1af07a0b, 0x71a03650, 0x4aefcffb }, + { 0x0415171e, -0x3cd2c9ca, -0x7667b7c5, -0x32d410ef, -0x2f6baef0, -0x78f59153, -0x5d579a9f, 0x0bccbb72 } + }, + { + { 0x50fe1296, 0x186d5e4c, -0x01176082, -0x1fc6847e, 0x507031b0, 0x3bc7f6c5, 0x108f37c2, 0x6678fd69 }, + { -0x154e5638, 0x185e962f, 0x65147dcd, -0x791819cb, -0x44a4920e, -0x4f6d1fcf, 0x59d6b73e, 0x4024f0ab }, + { 0x636863c2, 0x1586fa31, 0x572d33f2, 0x07f68c48, 0x789eaefc, 0x4f73cc9f, -0x7152b8ff, 0x2d42e210 } + }, + { + { 0x0f537593, 0x21717b0d, 0x131e064c, -0x6eb196f5, 0x752ae09f, 0x1bb687ae, -0x64bdc392, 0x420bf3a7 }, + { -0x6b202d65, -0x680aeceb, 0x313f4c6a, 0x6155985d, 0x08455010, -0x145ec0f9, -0x472d2cde, 0x676b2608 }, + { 0x1c5b2b47, -0x7ec7459b, 0x311b1b80, -0x798e4914, -0x43ceca50, 0x7bff0cb1, -0x63f30e20, 0x745d2ffa } + }, + { + { 0x21d34e6a, 0x6036df57, -0x66844c30, -0x4e2477d9, -0x378a9506, -0x2c3df63d, 0x4c1dc839, 0x06e15be5 }, + { 0x2bc9c8bd, -0x40ada5e2, 0x26479d81, -0x15a4d9f8, -0x20feaa25, -0x2aee38f2, -0x69f30a30, 0x1ae23ceb }, + { 0x1932994a, 0x5b725d87, -0x314e2550, 0x32351cb5, -0x254835fb, 0x7dc41549, 0x278ec1f7, 0x58ded861 } + }, + { + { -0x493d3658, 0x2dfb5ba8, -0x0ad3a674, 0x48eeef8e, -0x0ed2ea8d, 0x33809107, 0x531d5bd8, 0x08ba696b }, + { -0x0d993aa4, -0x27e8c86d, -0x33bab1b7, -0x3736893b, -0x43d93c58, 0x5ce382f8, 0x5485f6f9, 0x2ff39de8 }, + { -0x3c103a86, 0x77ed3eee, -0x2b00b7ef, 0x04e05517, -0x0e598e35, -0x15c285c1, -0x6b8301ac, 0x120633b4 } + }, + { + { 0x4912100a, -0x7d42ceb9, 0x7e6fbe06, -0x21dc8493, 0x11ea79c6, -0x1ee189e7, -0x34c6c422, 0x07433be3 }, + { -0x6e9effbe, 0x0b949878, -0x13140518, 0x4ee7b13c, -0x6b0f5b40, 0x70be7395, -0x4b2a6e7b, 0x35d30a99 }, + { 0x5ce997f4, -0x0086bb40, -0x4fa3ae5d, 0x575d3de4, 0x5a76847c, 0x583381fd, 0x7af6da9f, 0x2d873ede } + }, + { + { 0x4e5df981, -0x559dfd1f, 0x5015e1f5, -0x5df2a6e9, -0x451de294, 0x18a275d3, 0x01600253, 0x0543618a }, + { 0x43373409, 0x157a3164, -0x0b557e27, -0x05474812, -0x0a59b7fa, -0x4f6c011a, 0x707fa7b6, 0x2e773654 }, + { -0x68b3dc3f, 0x0deabdf4, -0x6231b96d, -0x5590f5db, -0x5d6545d4, 0x04202cb8, 0x2d07960d, 0x4b144336 } + }, +}, +{ + { + { 0x57c5715e, 0x299b1c3f, 0x6b686d90, -0x69346d62, 0x47235ab3, 0x30048064, -0x5bb2601f, 0x2c435c24 }, + { 0x53242cec, 0x47b837f7, -0x3fbded0e, 0x256dc48c, -0x1e26d73b, -0x1ddd0405, -0x5275d3f9, 0x48ea295b }, + { -0x7f077cc1, 0x0607c97c, -0x35da13a5, 0x0e851578, 0x161ebb6f, 0x54f7450b, -0x5f2107f2, 0x7bcb4792 } + }, + { + { 0x045224c2, 0x1cecd0a0, 0x69e53952, 0x757f1b1b, 0x5289f681, 0x775b7a92, 0x16736148, 0x1b6cc620 }, + { 0x2bc73659, -0x7b781c30, 0x059979df, 0x4baf8445, -0x23529041, -0x2e8368a6, -0x2103694a, 0x57369f0b }, + { 0x75638698, -0x0e5666ff, -0x11559f2d, 0x353dd1be, 0x4c9ba488, -0x7b6b8ecd, 0x43ade311, 0x63fa6e68 } + }, + { + { -0x2db4a149, 0x2195becd, -0x3f32bb07, 0x5e41f18c, 0x41ca9ede, -0x20d7f8bc, -0x0ca48299, 0x07073b98 }, + { 0x6597c168, -0x2ea3dfad, -0x672d7877, -0x608c8c00, 0x3257ba1f, 0x18aee7f1, 0x07346f14, 0x3418bfda }, + { 0x4ce530d4, -0x2fc39894, 0x3b5df9f4, 0x0b64c047, 0x19b3a31e, 0x065cef8b, 0x533102c9, 0x3084d661 } + }, + { + { 0x760321fd, -0x6593178a, -0x6149c528, 0x7fe2b510, -0x7537fa6e, 0x00e7d4ae, -0x44908dc6, 0x73d86b7a }, + { -0x407b9653, -0x1e094862, -0x1d99cecb, 0x15801004, -0x508be7e5, -0x65b67cd0, 0x049b673c, 0x3ba2504f }, + { 0x6dba5ab6, 0x0b52b560, -0x444e1255, -0x56ecb0f1, -0x64fb59cb, 0x30a9520d, 0x7973e5db, 0x6813b8f3 } + }, + { + { -0x0cea81d7, -0x0e6b35aa, 0x5ef528a5, 0x136d3570, -0x74fa6644, -0x22b31089, 0x24f833ed, 0x7d5472af }, + { 0x334127c1, -0x67ab4fac, -0x7d0400db, 0x105d0478, 0x44186f4f, -0x24b60807, -0x412f4700, 0x1768e838 }, + { -0x50cc25b9, -0x2f1078b3, -0x491cc607, 0x00d3be5d, -0x63631132, 0x3f2a8a2f, 0x2352435a, 0x5d1aeb79 } + }, + { + { -0x49e4588b, 0x12c7bfae, -0x1d9c4003, -0x47b19de1, 0x5c840dcf, 0x0b47a5c3, -0x335079cc, 0x7e83be0b }, + { 0x19cd63ca, -0x0a61944d, 0x21d06839, 0x670c1592, 0x2150cab6, -0x4f92a9a5, 0x104f12a3, 0x20fb199d }, + { 0x6d99c120, 0x61943dee, 0x460b9fe0, -0x79efe0d2, -0x7117a673, 0x6bb2f151, -0x033b8a34, 0x76b76289 } + }, + { + { 0x522ec0b3, 0x4245f1a1, 0x2a75656d, 0x558785b2, 0x48a1b3c0, 0x1d485a25, -0x2a701f61, 0x60959ecc }, + { 0x756286fa, 0x791b4cc1, -0x28b5ea84, -0x24312ce9, -0x158d421a, 0x7e732421, 0x1131c8e9, 0x01fe1849 }, + { -0x571285f7, 0x3ebfeb7b, -0x1afd8764, 0x49fdc2bb, 0x3c119428, 0x44ebce5d, -0x416b80b6, 0x35e1eb55 } + }, + { + { 0x726ccc74, 0x14fd6dfa, 0x2f53b965, 0x3b084cfe, 0x52a2c8b4, -0x0cc51b0b, 0x0d40166a, 0x59aab07a }, + { -0x3a8c722d, -0x242518ff, -0x4d90e412, -0x063909cb, 0x42f15ef4, 0x61e96a80, -0x509f5b28, 0x3aa1d11f }, + { -0x6da153db, 0x77bcec4c, 0x60137738, 0x18487184, -0x01560baf, 0x5b374337, -0x371955ba, 0x1865e78e } + }, +}, +{ + { + { 0x1c529ccb, -0x6983ab17, 0x64c635fb, 0x30f62692, 0x78121965, 0x2747aff4, -0x150990a4, 0x17038418 }, + { -0x4991e086, -0x333b4839, -0x0af3d082, 0x44157e25, 0x713eaf1c, 0x3ef06dfc, 0x52da63f7, 0x582f4467 }, + { 0x20324ce4, -0x39ce842d, -0x5bb7743c, -0x57efbd18, 0x4e5a1364, -0x4de10e75, -0x325d7237, 0x0c2a1c4b } + }, + { + { 0x69bd6945, -0x123b7eb8, -0x41e372de, 0x0d6d907d, -0x2aa33a55, -0x39c42dee, -0x5ceb237d, 0x5a6a9b30 }, + { 0x6f1f0447, -0x2db23830, -0x24783fa7, -0x4dd961c2, -0x044d2d71, -0x2ea4fd8e, -0x3909b789, 0x7c558bd1 }, + { -0x2c69b9c3, -0x2f13eadc, -0x3ca5db10, 0x12bb628a, 0x1cbc5fa4, -0x5af3c587, 0x0afbafc3, 0x0404a5ca } + }, + { + { 0x2a416fd1, 0x62bc9e1b, -0x1cafa675, -0x4a3908d8, 0x3d5d6967, 0x04343fd8, -0x18071168, 0x39527516 }, + { 0x0aa743d6, -0x73e0bff9, 0x5b265ee8, -0x33452f35, 0x668fd2de, 0x574b046b, -0x352269cd, 0x46395bfd }, + { 0x1a5d9a9c, 0x117fdb2d, -0x2effa3d6, -0x6388ba44, 0x54d56fea, -0x102b410f, -0x17dd2fea, 0x76579a29 } + }, + { + { 0x52b434f2, 0x333cb513, -0x6c217f1f, -0x27cdd7b7, 0x750d35ce, -0x4aaed779, 0x2a2777c1, 0x02c514bb }, + { 0x49c02a17, 0x45b68e7e, -0x43565c81, 0x23cd51a2, -0x13ddb3e5, 0x3ed65f11, -0x61fa424f, 0x43a384dc }, + { -0x740e49bb, 0x684bd5da, -0x094ab4ad, -0x04742c82, -0x564f2dad, 0x313916d7, 0x61548059, 0x11609209 } + }, + { + { 0x369b4dcd, 0x7a385616, 0x655c3563, 0x75c02ca7, -0x2b0e7fdf, 0x7dc21bf9, -0x6e191fbe, 0x2f637d74 }, + { 0x29dacfaa, -0x4bb2e997, -0x7beca671, -0x25ad60b4, 0x453d5559, -0x16109c36, -0x3a9671f5, 0x351e125b }, + { 0x1af67bbe, -0x2b4b64ba, -0x3754769f, -0x29fcfc86, -0x06596605, 0x71dee19f, -0x1831d566, 0x7f182d06 } + }, + { + { -0x71de8ade, 0x09454b72, -0x2b7b4728, -0x55a7170c, 0x7f46903c, -0x2ca7dab3, 0x241c5217, 0x44acc043 }, + { -0x54fe9714, 0x7a7c8e64, 0x15edc543, -0x34a5b5ab, 0x47cd0eda, 0x095519d3, 0x343e93b0, 0x67d4ac8c }, + { 0x4f7a5777, 0x1c7d6bbb, -0x6e7cec1f, -0x74ca012c, -0x3694b97c, 0x4adca1c6, 0x12ad71bd, 0x556d1c83 } + }, + { + { -0x4ee417df, -0x7e0f98aa, 0x10a3f3dd, 0x0faff823, 0x6a99465d, -0x074d2fab, -0x337380fb, 0x097abe38 }, + { 0x0c8d3982, 0x17ef40e3, 0x15a3fa34, 0x31f7073e, 0x0773646e, 0x4f21f3cb, 0x1d824eff, 0x746c6c6d }, + { 0x7ea52da4, 0x0c49c987, -0x6423e2bd, 0x4c436955, -0x0833142e, 0x022c3809, 0x4bee84bd, 0x577e14a3 } + }, + { + { -0x42b228d5, -0x6b013142, 0x060f2211, -0x0b95b026, -0x3f372e01, 0x124a5977, -0x04ff6d6b, 0x705304b8 }, + { 0x61a73b0a, -0x0f1d9754, 0x3791a5f5, -0x0d0505f0, 0x6b6d00e9, -0x3e1ec17e, 0x6fd78f42, 0x60fa7ee9 }, + { 0x4d296ec6, -0x49c2e2cb, 0x5fad31d8, -0x0c3cfac2, -0x4b42bd14, 0x670b958c, -0x5e9cac03, 0x21398e0c } + }, +}, +{ + { + { -0x79e48166, -0x793a03ea, 0x6a27c451, -0x095ccfb9, -0x5e16ca69, 0x01667267, 0x6082dfeb, 0x05ffb9cd }, + { -0x72582d11, 0x216ab2ca, -0x660bd7d9, 0x366ad9dd, 0x4fdd3c75, -0x519b4700, 0x53909e62, 0x403a395b }, + { -0x0ac09ec7, -0x59e80561, 0x13e66cb6, 0x60f2b5e5, -0x4cbb755c, -0x28574111, 0x6f5ea192, 0x7a293285 } + }, + { + { 0x79639302, -0x4763bbb8, 0x50c67f2c, 0x4ae4f193, -0x37e5063a, -0x0f4ca258, 0x46871017, 0x39d00035 }, + { -0x4fd21778, 0x0b39d761, -0x2dbeb1e1, 0x5f550e7e, 0x22e1a940, -0x59405ba8, -0x02bb8467, 0x050a2f7d }, + { -0x59af2489, 0x437c3b33, -0x453ad44e, 0x6bafe81d, 0x2db7d318, -0x0166bfd3, 0x372ba6ce, 0x2b5b7eec } + }, + { + { 0x613ac8f4, -0x596bbfb3, -0x056818d4, 0x500c3c2b, 0x1fcec210, -0x78befb2e, -0x79fb5712, 0x1b205fb3 }, + { -0x7c0af111, -0x4c43b443, -0x736d879a, 0x508f0c99, -0x37481992, 0x43e76587, -0x5b806727, 0x0f7655a3 }, + { -0x2db4ecc4, 0x55ecad37, 0x6038c90b, 0x441e147d, -0x29d39012, 0x656683a1, -0x781f1352, 0x0157d5dc } + }, + { + { -0x28e14adc, -0x6ad9aaec, 0x5df14593, -0x19fc277f, 0x0d4de6b7, 0x147cdf41, 0x0437c850, 0x5293b173 }, + { 0x0354c13d, -0x0d5850af, -0x55c8d4a0, -0x285f4ebb, 0x05a3d470, 0x2869b96a, -0x7db9fe8d, 0x6528e42d }, + { 0x4bccf226, 0x23d0e081, -0x7e69046d, -0x6d38ba33, 0x59541e5b, -0x749e8694, -0x3fde0688, 0x40a44df0 } + }, + { + { 0x4bc5d095, -0x793691af, -0x03597fb6, -0x0df2bf68, -0x37d915a3, 0x27363d89, 0x5719cacf, 0x39ca3656 }, + { 0x4f20ea6a, -0x25579677, 0x4c620618, -0x15eb5c2f, 0x090bf8be, 0x6001fccb, -0x6b816310, 0x35f4e822 }, + { 0x6f87b75c, -0x68af90d1, 0x034ae070, -0x39db5160, -0x552cb22a, 0x1ec856e3, -0x1bbf1a71, 0x055b0be0 } + }, + { + { 0x6ea33da2, 0x4d12a04b, -0x1c9ed923, 0x57cf4c15, -0x11bb2699, -0x6f13698b, 0x2a985aac, 0x64ca348d }, + { -0x768ca2ee, 0x6469a17d, -0x199d460f, -0x2490d82b, 0x6a395681, -0x60345cd8, -0x2d9650db, 0x363b8004 }, + { -0x1b3b6ed3, -0x66a771e7, 0x1ca5ce6b, -0x1033c4b2, -0x05a4672b, 0x4522ea60, 0x1de4a819, 0x7064bbab } + }, + { + { 0x42542129, -0x5d6f3f9f, -0x4172a470, -0x0d1d3d52, 0x76abfe1b, -0x30dba725, -0x7c29d941, 0x02157ade }, + { 0x5a770641, -0x46e61eaf, 0x4e7f8039, -0x565d1d39, 0x3df23109, 0x7527250b, -0x53d84875, 0x756a7330 }, + { 0x1b9a038b, 0x3e46972a, 0x7ee03fb4, 0x2e4ee66a, 0x6edbb4ca, -0x7e5db789, -0x7132fa9d, 0x1a944ee8 } + }, + { + { 0x182362d6, -0x44bf57a7, -0x75b2e545, -0x4660aa89, 0x758559f6, -0x72e74bd9, 0x4d26235a, 0x26c20fe7 }, + { 0x51039372, -0x2a56e2ef, -0x6635d922, 0x2ed377b7, -0x02c99495, -0x5e8dfd54, -0x296fe66b, 0x0730291b }, + { -0x1633dd0b, 0x648d1d9f, 0x28dd577c, 0x66bc5619, 0x652439d1, 0x47d3ed21, -0x125074b7, 0x49d271ac } + }, +}, +{ + { + { -0x4b48a9ff, 0x2798aaf9, 0x5c8dad72, 0x5eac7213, 0x61b7a023, -0x2d31559f, -0x167082b2, 0x1bbfb284 }, + { 0x382b33f3, -0x760afa76, -0x52b73f4c, 0x5ae2ba0b, -0x5ac24c92, -0x706c4afd, -0x6a5dcd1a, 0x5aa3ed9d }, + { -0x38269a9f, 0x656777e9, 0x72c78036, -0x34d4edac, -0x26af9112, 0x65053299, 0x5e8957cc, 0x4a07e14e } + }, + { + { -0x3b885b65, 0x240b58cd, 0x6447f017, -0x02c72522, -0x58379553, 0x19928d32, -0x7b505f7f, 0x50af7aed }, + { -0x67f20667, 0x4ee412cb, 0x3c6ec771, -0x5cea2891, -0x6da38803, -0x445a1222, 0x1d313402, 0x3f0bac39 }, + { 0x15f65be5, 0x6e4fde01, 0x216109b2, 0x29982621, 0x0badd6d9, 0x78020581, -0x45142ffa, 0x1921a316 } + }, + { + { -0x260c3e75, -0x28a55266, 0x60b1c19c, 0x566a0eef, 0x255c0ed9, 0x3e9a0bac, -0x5f9d380b, 0x7b049dec }, + { -0x20478f04, -0x76bdd082, 0x4f76b3bd, 0x2c296beb, 0x36c24df7, 0x0738f1d4, -0x1d8c5150, 0x6458df41 }, + { 0x35444483, -0x23341c86, 0x0fedbe93, 0x75887933, 0x12c5dd87, 0x786004c3, -0x3d6af19c, 0x6093dccb } + }, + { + { 0x6084034b, 0x6bdeeebe, 0x780fb854, 0x3199c2b6, -0x49d2f96b, -0x68cc8955, -0x749b8270, 0x6e3180c9 }, + { -0x7a1f8f93, 0x1ff39a85, -0x4c18c6cd, 0x36d0a5d8, 0x718f453b, 0x43b9f2e1, 0x4827a97c, 0x57d1ea08 }, + { -0x5ed74f8f, -0x11854919, -0x6c577456, -0x5b3ea693, -0x4dde9ed0, -0x084b217e, -0x226842e8, 0x363e999d } + }, + { + { -0x1db4513a, 0x2f1848dc, -0x454350a0, 0x769b7255, 0x3cefe931, -0x6f34c392, -0x39064cab, 0x231f979b }, + { 0x35ee1fc4, -0x6957bc3f, 0x08e4c8cf, -0x68914cab, -0x4a732cd0, -0x4bd097ff, 0x693a052b, 0x48ee9b78 }, + { -0x33d50c3a, 0x5c31de4b, -0x01df72e1, -0x4fb44fd0, -0x3eb04b9a, -0x48728ff7, 0x08792413, 0x079bfa9b } + }, + { + { -0x5d2abdbb, -0x0c361280, 0x77f63952, 0x0aa08b78, -0x2ef7ab8b, -0x2892539d, -0x6b8f9c95, 0x1ef4fb15 }, + { -0x25cff20c, -0x1c6fc5af, 0x3da95ab0, -0x7bc69bdd, 0x0b356480, -0x12c30ed3, -0x7b7e8e6c, 0x038c77f6 }, + { 0x5b167bec, -0x7ab1a11a, -0x692f323e, 0x59590a42, -0x67efde67, 0x72b2df34, 0x4a0bff56, 0x575ee92a } + }, + { + { 0x0aa4d801, 0x5d46bc45, -0x5acc4628, -0x3c50edd9, 0x2b8906c2, 0x389e3b26, 0x382f581b, 0x200a1e7e }, + { -0x75e7d031, -0x2b3f7f70, -0x66b76243, 0x30e170c2, 0x52f733de, 0x05babd57, 0x2cd3fd00, 0x43d4e711 }, + { -0x1506c53b, 0x518db967, 0x056652c0, 0x71bc989b, 0x567197f5, -0x01d47a27, 0x651e4e38, 0x050eca52 } + }, + { + { 0x60e668ea, -0x6853c68a, 0x153ab497, -0x64e64402, 0x34eca79f, 0x4cb179b5, -0x5ece51a9, 0x6151c09f }, + { 0x453f0c9c, -0x3cbce522, -0x008fc465, -0x160afba2, -0x127b84c3, -0x03268537, 0x1c58f4c6, 0x4b0ee6c2 }, + { -0x020fa26a, 0x3af55c0d, 0x2ab4ee7a, -0x22d9d120, 0x12171709, 0x11b2bb87, -0x7ff0fcf5, 0x1fef24fa } + }, +}, +{ + { + { -0x6fe99de0, -0x006e5996, 0x5bf1e009, -0x0ddaad52, 0x7f90df7c, 0x7dff85d8, 0x0c736fb9, 0x4f620ffe }, + { 0x6b6c6609, -0x4b69edc6, -0x7f54a6c8, -0x58af017b, -0x483d85a1, -0x0b8e40c7, 0x77ac193c, 0x507903ce }, + { -0x2021c1cc, 0x62f90d65, -0x4605a053, -0x30d73a6e, -0x39e9baf0, -0x66379107, 0x4a256c84, 0x25d44804 } + }, + { + { -0x36fdd4ab, 0x2c7c4415, -0x7ed14e02, 0x56a0d241, -0x2849a1f3, -0x0fd15e37, -0x2acdc4da, 0x4180512f }, + { -0x38164e91, -0x4297dcf2, -0x3e3a86a3, 0x0eb1b9c1, -0x6a494e01, 0x7943c8c4, 0x0bbacf5e, 0x2f9faf62 }, + { -0x75b75a25, -0x5b00c197, -0x426abfc5, -0x4595c7fa, 0x47d5b65d, -0x60831e51, 0x5939d2fb, 0x15e087e5 } + }, + { + { -0x0469c0c8, -0x776be792, -0x239c642b, 0x48a00e80, -0x1693e367, -0x5b17f6d5, -0x35a8c99f, 0x5a097d54 }, + { 0x745c1496, 0x12207543, -0x25c79ef4, -0x2500c303, 0x2c71c34f, -0x1b1868d9, 0x34bdede9, 0x39c07b19 }, + { 0x17c9e755, 0x2d45892b, -0x76cf7208, -0x2fcc028e, 0x525b8bd9, 0x6c2fe9d9, -0x3ee33f87, 0x2edbecf1 } + }, + { + { -0x2f785da1, -0x11f0f023, 0x5c3e34ee, -0x638aceab, -0x7054c54b, 0x660c572e, 0x544cd3b2, 0x0854fc44 }, + { -0x38ea5f2e, 0x1616a4e3, -0x07cbe2b3, 0x53623cb0, -0x38176635, -0x6910acd7, -0x5997455a, 0x3d4e8dbb }, + { 0x55edad19, 0x61eba0c5, -0x0f57c21a, 0x24b533fe, -0x7c455a08, 0x3b770428, -0x675b8173, 0x678f82b8 } + }, + { + { 0x57775696, 0x1e09d940, 0x3cd951db, -0x112ed9a4, 0x20bce16f, -0x056253d5, -0x172f760c, 0x0f7f76e0 }, + { -0x296ff3ac, -0x4eb6e2f5, -0x62ecd9ca, 0x3539722c, 0x0b362bc9, 0x4db92892, -0x59749621, 0x4d7cd1fe }, + { -0x2b7a4ff4, 0x36d9ebc5, -0x1b524c9b, -0x5da69b6e, -0x3dee6333, -0x3e9a6b80, 0x186e0d5f, 0x45306349 } + }, + { + { 0x2b072491, -0x695beb14, 0x27a7b65b, 0x1bb22181, 0x6e8a4af0, 0x6d284959, -0x32d889a1, 0x65f3b08c }, + { -0x593200e3, -0x6b222f3f, -0x17bdec52, 0x55f6f115, -0x66d03096, 0x6c935f85, 0x4a37f16f, 0x067ee0f5 }, + { 0x199801f7, -0x134d6001, -0x5d5f08d1, -0x62c9e2e1, 0x75fd2f49, 0x25f11d23, 0x0fe10fe2, 0x124cefe8 } + }, + { + { 0x31b16489, 0x1518e85b, -0x248ef405, -0x70552349, -0x5eb51dc7, 0x39b0bdf4, 0x503d20c1, 0x05f4cbea }, + { -0x2e720dab, 0x4c126cf9, 0x147a63b6, -0x3e2b8e17, -0x0c36c4a1, 0x2c6d3c73, -0x1c00795e, 0x6be3a6a2 }, + { -0x3fbeba44, -0x31fbf162, 0x08f6834c, -0x38e00b1e, -0x5477b85d, -0x42ab9173, -0x5b2d545b, 0x64666aa0 } + }, + { + { 0x3337e94c, -0x4f3ac409, 0x11e14f15, 0x7cb5697e, 0x1930c750, 0x4b84abac, -0x1f9bfb98, 0x28dd4abf }, + { 0x7c06d912, 0x6841435a, -0x44c07cf5, -0x35edc3df, -0x4e341d88, -0x2b4c84d9, -0x3890afba, 0x1d753b84 }, + { 0x44cb9f44, 0x7dc0b64c, -0x1c6da241, 0x18a3e1ac, 0x2d0457c4, 0x7a303486, -0x75f376d2, 0x4c498bf7 } + }, +}, +{ + { + { 0x30976b86, 0x22d2aff5, -0x3d2db9fc, -0x726f47fa, 0x4de5bae5, -0x235e7694, -0x37cbf3e9, 0x28005fe6 }, + { 0x1aa73196, 0x37d653fb, 0x3fd76418, 0x0f949530, -0x04c5e84e, -0x52dff4f7, 0x2fc8613e, 0x544d4929 }, + { 0x34528688, 0x6aefba9f, 0x25107da1, 0x5c1bff94, 0x66d94b36, -0x08a44433, 0x0f316dfa, 0x72e47293 } + }, + { + { -0x2cd589d9, 0x07f3f635, 0x5f6566f0, 0x7aaa4d86, 0x28d04450, 0x3c85e797, 0x0fe06438, 0x1fee7f00 }, + { -0x687ef7b1, 0x2695208c, 0x23450ee1, -0x4eafd5f5, 0x03efde02, -0x0262515a, 0x2733a34c, 0x5a9d2e8c }, + { 0x03dbf7e5, 0x765305da, 0x1434cdbd, -0x5b250db7, -0x2db57714, 0x7b4ad5cd, -0x11fbfabd, 0x00f94051 } + }, + { + { 0x07af9753, -0x28106c45, 0x3db766a7, 0x583ed0cf, 0x6e0b1ec5, -0x31966741, 0x5dd40452, 0x47b7ffd2 }, + { -0x3c2ccf4e, -0x72ca94dd, -0x4fb8e4fa, -0x0de37465, 0x6e42b83c, -0x4c93ce94, -0x74154ef3, 0x07d79c7e }, + { -0x43f722ee, -0x78040464, -0x1e113d65, -0x75f994c6, -0x24e03e41, 0x0d57242b, 0x5ea64bb6, 0x1c3520a3 } + }, + { + { 0x216bc059, -0x325790c0, 0x12bcd87e, 0x1fbb231d, 0x17c70990, -0x4b6a9562, 0x66d12e55, 0x38750c3b }, + { -0x43345cb6, -0x7f2dac5a, 0x3838219b, 0x3e61c3a1, -0x677d1c6a, -0x6f3c49ff, 0x5d0ee66f, 0x1c3d0577 }, + { -0x6bdd1ae6, 0x692ef140, 0x2b5df671, -0x343f38c4, 0x744ce029, 0x21014fe7, -0x2ccfb784, 0x0621e2c7 } + }, + { + { -0x4f240f0d, -0x4851e86a, -0x1e831e6a, 0x54dfafb9, -0x16555c4c, 0x25923071, -0x5effd163, 0x5d8e589c }, + { -0x7da67c73, -0x50679f34, -0x39606524, -0x6f15b73f, 0x65581e30, 0x65264837, 0x7bd3a5bc, 0x0007d609 }, + { 0x0842a94b, -0x3f40e26b, 0x588f2e3e, -0x4d2c3c9d, -0x44ae1d11, 0x0a961438, 0x3c1cbf86, 0x1583d778 } + }, + { + { -0x3362d739, -0x6ffcb8fc, -0x08d33a71, 0x1d1b679e, -0x41a478da, 0x16e12b5f, -0x7c3aa7f6, 0x4958064e }, + { 0x5da27ae1, -0x13115d11, 0x55670174, 0x597c3a14, 0x6609167a, -0x3659d5ee, -0x7e127090, 0x252a5f2e }, + { 0x5066e80d, 0x0d289426, 0x307c8c6b, -0x033c087b, 0x0c1112fd, 0x1b53da78, -0x27bc4c78, 0x079c170b } + }, + { + { -0x3f2a2faa, -0x322932b0, -0x44fca8c5, -0x65089793, -0x0c3c10b8, 0x3ca6723f, 0x317b8acc, 0x6768c0d7 }, + { 0x64fa6fff, 0x0506ece4, 0x6205e523, -0x411cbce2, 0x51b8ea42, 0x35794224, 0x4ac9fb00, 0x6dec05e3 }, + { -0x0eaa3e4d, -0x6b49da1b, -0x6684846f, 0x417bf3a7, 0x6d6b2600, -0x3dd34224, -0x2232ad0c, 0x51445e14 } + }, + { + { 0x2bbea455, -0x76ceb855, -0x6df86ed7, -0x73ac5db1, -0x41cf0859, 0x4b49f948, 0x6e4fd43d, 0x12e99008 }, + { 0x3b144951, 0x57502b4b, 0x444bbcb3, -0x71980095, 0x166385db, -0x474296d9, -0x1c6d6a38, 0x13186f31 }, + { 0x7fdfbb2e, -0x0ef3694d, 0x121ceaf9, -0x60656ca2, 0x3a5b983f, -0x20eec93c, 0x5d3e99af, 0x77b2e3f0 } + }, +}, +{ + { + { -0x33a32d65, -0x6acd0b71, -0x5c31c98f, 0x2ba851be, 0x51122941, 0x32dacaa0, 0x350004f2, 0x478d99d9 }, + { -0x630ed9a9, -0x02f28a79, -0x1ac5f1d7, -0x17d0106c, 0x5bbb4be7, -0x33cb5810, -0x5af3c75e, 0x0b251172 }, + { -0x6f44fd40, 0x1d5ad948, 0x0ec25115, 0x50e208b1, 0x4ef21702, -0x5d95dd77, 0x3b524805, 0x4dc92334 } + }, + { + { -0x0c93b68b, 0x3ad3e3eb, 0x37862125, -0x28a2da5b, -0x5fda5aea, -0x178c6bc3, -0x3bee37b9, 0x6bbc7cb4 }, + { 0x0f8086b6, -0x1c7d73c0, -0x6860f238, 0x3f77e6f7, 0x4df42cb4, 0x7ef6de30, -0x4954287c, 0x5265797c }, + { -0x2b5af2aa, 0x3c6f9cd1, -0x39015482, -0x49dbbf89, 0x3580972e, 0x6ff9bf48, -0x4ccd5305, 0x00375883 } + }, + { + { 0x6c75c99c, -0x3674137b, 0x00e33cf4, -0x1bbe7b40, -0x456f89cc, 0x0a676b9b, 0x71f379d7, 0x669e2cb5 }, + { 0x28cb0940, 0x0001b2cd, 0x6f1c24c9, 0x63fb51a0, -0x232a35cf, -0x4a52796f, -0x73baf9a0, 0x67238dbd }, + { -0x5b642cf8, -0x34ee948d, 0x2392729e, 0x025aad6b, 0x3f55d9b1, -0x4b86c106, 0x40678bb9, 0x72a10561 } + }, + { + { -0x1d1afa4a, 0x0d8d2909, -0x3fd6edd0, -0x67358755, -0x564edcd9, 0x77ef5569, -0x7ebc64b9, 0x7c77897b }, + { 0x1cc9249d, -0x5d497ed5, 0x21211f58, 0x62866eee, 0x5df10ece, 0x2cb5c5b8, -0x1d9c5200, 0x03a6b259 }, + { -0x21cce34b, -0x0e3e4a1e, 0x15fca420, 0x5a9f5d8e, 0x7bd932b1, -0x605bc70f, 0x1c6146e7, 0x2a381bf0 } + }, + { + { -0x4acbe991, -0x083f41ce, 0x19cf70d4, 0x27e6ca64, -0x56a858a7, -0x6cb20829, -0x54213d56, 0x5701461d }, + { -0x3037ee3f, -0x53646787, 0x3756e567, -0x7482d67f, 0x7c70edfc, 0x50da4e60, -0x77bbff4a, 0x5dbca62f }, + { 0x2c915c25, 0x2c674740, 0x0b0d340a, 0x1bdcd1a8, 0x07b43f5f, 0x5e5601bd, 0x5539a242, 0x2555b4e0 } + }, + { + { -0x781b9c2c, 0x78409b1d, -0x32049c63, -0x52b256a6, 0x55259b9c, -0x13d788c9, -0x3cedcf55, 0x69c806e9 }, + { 0x66ddd216, 0x6fc09f52, -0x371c8fb8, -0x231a9f59, -0x5d209d03, -0x139a6c63, -0x1ad12e6e, 0x7a869ae7 }, + { 0x14bb3f22, 0x7b48f574, -0x51233378, 0x68c7cee4, 0x79ed80be, -0x12d06c9f, 0x5f77bc4b, 0x25d70b88 } + }, + { + { -0x44e51b2c, -0x67ba62d7, 0x39f954ec, 0x56b9c4c7, -0x3d64b4c2, -0x7cd8bc0a, -0x67497876, 0x21ea8e27 }, + { 0x762bf4de, 0x4151c3d9, 0x2745d82b, 0x083f435f, 0x0d23ddd5, 0x29775a2e, 0x69a5db24, 0x138e3a62 }, + { 0x6a5a7b9c, -0x78410b4c, 0x5fc1d062, -0x2dd662e5, -0x22cde9b8, -0x7dbf67e8, -0x1a5d1fc3, 0x5c5abeb1 } + }, + { + { 0x1306a233, 0x02cde6de, 0x116f8ec7, 0x7b5a52a2, -0x3ee9c4a5, -0x1e397e0c, 0x60d32643, 0x241d3506 }, + { -0x48c3d225, 0x14722af4, 0x5a05060d, -0x43b8f3a1, 0x2581b02e, 0x00943eac, 0x1f499c8f, 0x0e434b3b }, + { 0x0ebc52c7, 0x6be4404d, -0x4e586e0b, -0x51b9dcc5, -0x2da24bd5, 0x2aec170e, 0x6645d694, 0x1d8dfd96 } + }, +}, +{ + { + { 0x12ddb0a4, -0x2a679c64, -0x3fdb7995, -0x5a2e60d0, 0x58fce460, -0x2e83d0fd, 0x2e095e8a, 0x07a19515 }, + { -0x63d13b22, 0x296fa9c5, 0x4f84f3cb, -0x43749e41, 0x17a8f908, 0x1c7706d9, 0x7ad3255d, 0x63b795fc }, + { 0x389e5fc8, -0x57c970fe, -0x30721bc5, -0x6fbcc4fe, -0x3abed9bd, -0x505e02a3, 0x032f0137, 0x3e8fe83d } + }, + { + { -0x17102ec4, 0x08704c8d, 0x33e03731, -0x203ae572, 0x1260cde3, -0x5a62a25b, -0x59da737a, 0x22d60899 }, + { 0x0570a294, 0x2f8b15b9, 0x67084549, -0x6b0dbd90, 0x61bbfd84, -0x21e3a51f, 0x7fac4007, 0x75ba3b79 }, + { 0x70cdd196, 0x6239dbc0, 0x6c7d8a9a, 0x60fe8a8b, -0x14bfeda0, -0x4c77b844, -0x788861a2, 0x0904d07b } + }, + { + { 0x48f940b9, -0x0bcdd29a, -0x42d2f3c7, 0x06952f0c, -0x5f7e06cf, 0x167697ad, -0x4508d594, 0x6240aace }, + { -0x22456e64, -0x4b31e02c, -0x38b37256, -0x30ce24c2, -0x527933af, 0x2c63cc63, -0x43e221f9, 0x43e2143f }, + { 0x5ba295a0, -0x07cb8b64, -0x35c82da6, -0x296b83a5, -0x1836ce96, 0x66f13ba7, -0x724bf354, 0x56bdaf23 } + }, + { + { -0x3e62c44e, 0x1310d36c, 0x622386b9, 0x062a6bb7, -0x285eb0a4, 0x7c9b8591, 0x7e1e5754, 0x03aa3150 }, + { -0x0acacc15, 0x362ab9e3, 0x6eb93d40, 0x338568d5, 0x1d5a5572, -0x61f1ebae, -0x7c8bece8, 0x1d24a86d }, + { -0x002b31e1, -0x0b1389b8, 0x54ac8c1c, -0x1fba1510, 0x1d09357c, -0x772dda7e, -0x6514b7a7, 0x43b261dc } + }, + { + { 0x6c951364, 0x19513d8b, 0x000bf47b, -0x6b018eda, -0x2ab06a99, 0x028d10dd, 0x42940964, 0x02b4d5e2 }, + { -0x77448645, -0x1aa4e1e7, -0x3e85ca63, -0x5f612f83, 0x603dea33, -0x4fd3d11e, 0x5b276bc2, 0x326055cf }, + { 0x28d18df2, -0x4b5eaa35, 0x186ce508, -0x1533b9ba, 0x6c824389, -0x3b630b6d, -0x51a2cbf0, 0x27a6c809 } + }, + { + { -0x3bc296ac, -0x32d3d8f6, 0x6a66cab2, -0x22b5c1a9, 0x69d7036c, 0x79fa5924, 0x3d8c2599, 0x22150360 }, + { 0x1f0db188, -0x74591433, 0x675a5be8, 0x37d3d73a, 0x15f5585a, -0x0dd1205d, -0x009f5e82, 0x2cb67174 }, + { 0x390be1d0, 0x59eecdf9, 0x728ce3f1, -0x56bddfbc, 0x7a94f0f4, -0x7d76e39a, 0x3890f436, 0x7b1df4b7 } + }, + { + { 0x07f8f58c, 0x5f2e2218, -0x2b6bf62c, -0x1caaa361, 0x1fb6a630, -0x4d555773, -0x2cad1fc3, 0x68698245 }, + { -0x4c4d5ddc, -0x1b6d0d20, 0x2b551160, 0x7c6c9e06, 0x0d7f7b0e, 0x15eb8fe2, 0x58fc5992, 0x61fcef26 }, + { 0x2a18187a, -0x244ea27b, -0x79225329, -0x0c1b552d, 0x0ff6c482, 0x44bae281, 0x3daf01cf, 0x46cf4c47 } + }, + { + { -0x0eb67ec0, 0x213c6ea7, 0x392b4854, 0x7c1e7ef8, 0x5629ceba, 0x2488c38c, 0x0d8cc5bb, 0x1065aae5 }, + { -0x613b1a07, 0x426525ed, 0x16903303, 0x0e5eda01, -0x341a3524, 0x72b1a7f2, 0x14eb5f40, 0x29387bcd }, + { -0x20dff2a9, 0x1c2c4525, -0x403598b6, 0x5c3b2dd6, -0x1e7cbfd0, 0x0a07e7b1, 0x4f1ce716, 0x69a198e6 } + }, +}, +{ + { + { -0x61d2b8cc, 0x7b26e56b, -0x7e39e98b, -0x3b38ecd5, -0x13632181, -0x10a36adb, -0x18e8bc53, 0x39c80b16 }, + { -0x10562969, 0x7afcd613, 0x1c067959, 0x0cc45aa4, -0x3e05256a, -0x5a901efc, 0x72e40365, 0x3a73b704 }, + { 0x1b826c68, 0x0f196e0d, 0x4960e3db, -0x08e00f1e, 0x23b7436c, 0x61131670, 0x77da7282, 0x0cf0ea58 } + }, + { + { 0x3ba6945a, -0x1ccd312c, -0x177e3fa3, -0x21f4ec9f, 0x5e67ed3b, 0x1ad40f09, -0x4739c2a3, 0x5da8acda }, + { -0x222b3343, 0x196c80a4, -0x6a0d2263, 0x22e6f55d, 0x40d6c71b, -0x38a1cc39, -0x34c3fbd1, 0x7bb51279 }, + { 0x3a70159f, -0x3b4999b6, 0x0a904e14, 0x76194f0f, -0x5bf693ed, -0x5a9eb3c7, -0x68601313, 0x6cd0ff50 } + }, + { + { -0x4fb45e72, 0x7fecfabd, 0x3bddbcf7, -0x2f038404, 0x057a131c, -0x5be2b792, -0x0dddc59f, 0x641a4391 }, + { -0x70bbd754, -0x3f1f9819, -0x59eeca1d, 0x14835ab0, 0x38062935, -0x0de2eb0d, -0x20fb7b64, 0x6390a4c8 }, + { -0x59f95725, -0x3a3946a6, -0x4f97da0f, -0x6eb48062, 0x44fc9eff, 0x2a731f6b, 0x62705cfc, 0x30ddf385 } + }, + { + { 0x68bcd52c, 0x33bef2bd, 0x69482ef2, -0x39b62450, 0x41cb1aee, -0x4a4911f4, 0x0212a7e5, 0x5c294d27 }, + { -0x2e400807, 0x4e3dcbda, 0x20645717, -0x36ee717e, 0x0f189d56, -0x45333144, -0x2bb98998, 0x1b4822e9 }, + { 0x25563781, -0x54c9f581, 0x480f7958, 0x2512228a, 0x6114b4e3, -0x38a2fad9, -0x268901d6, 0x222d9625 } + }, + { + { 0x0a344f85, 0x0f94be7e, -0x780dd3c8, -0x14d05574, 0x4ee16f0f, -0x631e18a2, 0x18a08dea, 0x43e64e54 }, + { -0x4c8d531f, 0x1c717f85, 0x4638bf18, -0x7e6cf197, 0x6bc08b58, 0x239cad05, -0x7807000c, 0x0b34271c }, + { 0x1a35ce63, -0x7eaa1dae, -0x06edfd72, -0x41eff2b3, -0x5a822314, -0x4007f408, 0x6d6bc6e4, 0x57342dc9 } + }, + { + { 0x1e707bf6, -0x0c3c4349, 0x7291a762, 0x351d9b8c, -0x252965cd, 0x00502e6e, 0x1ec8807f, 0x522f521f }, + { -0x3731a668, -0x10110f9b, -0x4a34155e, -0x40fd6af0, 0x20b7c458, -0x739b5efa, 0x31c24855, 0x35134fb2 }, + { -0x065c6fd5, 0x272c1f46, -0x669a8434, -0x36e45c49, 0x4f8a1c0e, -0x519eb4d0, 0x0b99017b, 0x7afcaad7 } + }, + { + { -0x107bd495, -0x577ebe14, -0x6854193b, 0x55e7b147, 0x03784ffe, -0x738b7069, -0x5032ff49, 0x5b50a1f7 }, + { -0x5b4741bf, -0x3da212ac, 0x1bb0e2dd, -0x6fd2ec1f, -0x3217d54e, 0x41f43233, -0x3c551835, 0x1085faa5 }, + { -0x0ec9eceb, -0x647bf09a, 0x701003e9, 0x18462242, -0x1b5daf80, 0x65ed45fa, 0x3fda7320, 0x0a286239 } + }, + { + { 0x6ecb9d17, -0x69f18c85, -0x2983151f, -0x050db6b8, -0x2aa1e477, 0x37e7a9b4, -0x4b93a615, 0x5cb7173c }, + { 0x347cbc9d, 0x46ab13c8, -0x663edc7d, 0x3849e8d4, -0x7829b537, 0x4cea3140, -0x4e5d6119, 0x1f354134 }, + { -0x7d485410, 0x4a89e68b, -0x64594847, -0x0be326d9, -0x1e727891, 0x16e6c210, 0x7f1b09c6, 0x7cacdb0f } + }, +}, +{ + { + { -0x233a3513, -0x1efebbcc, 0x3c84fb33, 0x47ed5d96, -0x12795f19, 0x70019576, -0x2d98061c, 0x25b2697b }, + { -0x26e58744, -0x6f9d4d20, -0x37af6999, 0x47c9889c, 0x405070b8, -0x620ab59a, 0x2493a1bf, 0x7369e6a9 }, + { 0x13986864, -0x6298c005, 0x415dc7b8, 0x3ca5fbd9, -0x20d8c4a2, -0x1fb133c5, -0x4ab1b32e, 0x1420683d } + }, + { + { -0x3e33a530, 0x34eebb6f, -0x69b95375, 0x6a1b0ce9, -0x599421ad, -0x2c4f25b7, 0x61d081c1, 0x31e83b41 }, + { 0x249dd197, -0x4b8742e2, 0x5e58c102, 0x620c3500, -0x334553a4, -0x04fd2cd1, -0x0af758d3, 0x60b63beb }, + { -0x61f9d4b1, -0x681738ee, 0x29320ad8, 0x49e48f4f, 0x6f18683f, 0x5bece14b, 0x2d550317, 0x55cf1eb6 } + }, + { + { 0x7df58c52, 0x3076b5e3, -0x186633ca, -0x28c54623, 0x4913ee20, -0x427ce31d, 0x62ba0133, 0x1a56fbaa }, + { 0x65c23d58, 0x58791010, 0x5094819c, -0x7462f793, 0x12c55fa7, -0x1dbfd057, 0x570891d4, 0x669a6564 }, + { 0x5c9dc9ec, -0x6bc194b0, -0x5883c8e6, 0x302557bb, 0x41347651, -0x678c51aa, -0x663a75a4, 0x13c48367 } + }, + { + { 0x5d8bd080, -0x3b230496, 0x571a4842, -0x21143b14, -0x471aac9b, -0x2b4d177d, -0x371a47d9, 0x50bdc87d }, + { 0x5ab3e1b9, 0x423a5d46, -0x380ec09f, -0x03ec3e79, -0x134a464a, 0x19f83664, -0x59c849f9, 0x66f80c93 }, + { 0x6edfe111, 0x606d3783, -0x0fee5427, 0x32353e15, 0x25b73b96, 0x64b03ac3, 0x725fd5ae, 0x1dd56444 } + }, + { + { 0x08bac89a, -0x3d681a00, -0x151e3c20, 0x7d4cea11, -0x60186884, -0x0c1c741f, 0x63a305cd, 0x3a3a450f }, + { 0x3362127d, -0x705b8008, 0x71cd7c15, -0x4360953c, 0x49220c8b, 0x6e714543, 0x219f732e, 0x0e645912 }, + { -0x27c6b9d9, 0x078f2f31, -0x216b5af0, 0x389d3183, 0x17996f80, -0x2e1c9393, -0x6c565785, 0x318c8d93 } + }, + { + { -0x54e22c68, 0x5d669e29, 0x342d9e3b, -0x036de9a8, -0x0ca68c33, 0x55851dfd, 0x25950af6, 0x509a41c3 }, + { 0x2afffe19, -0x0d8ba2fd, 0x7f24db66, 0x0c9f3c49, -0x457a6711, -0x43672c1d, -0x65e2acec, 0x224c7c67 }, + { -0x5906da17, -0x423f9124, 0x641b1f33, 0x793ef3f4, -0x627cc177, -0x7d13ed80, 0x28a11389, 0x05bff023 } + }, + { + { 0x0dc512e4, 0x6881a0dd, 0x44a5fafe, 0x4fe70dc8, -0x70b5adc0, 0x1f748e6b, -0x11fe5c16, 0x576277cd }, + { 0x23cae00b, 0x36321370, -0x2e5330a7, 0x544acf0a, -0x2de5e378, -0x698befb7, -0x05d5bb59, 0x780b8cc3 }, + { 0x234f305f, 0x1ef38abc, 0x1405de08, -0x65a88043, 0x34e62a0d, 0x5e82a514, 0x6271b7a1, 0x5ff41872 } + }, + { + { 0x13b69540, -0x1a24b818, 0x432610e1, -0x0ca2d5c5, 0x38781276, -0x53e0d917, -0x5f5f3497, 0x29d4db8c }, + { 0x1789db9d, 0x398e080c, -0x0c18870b, -0x589fdfdb, 0x06bd035d, -0x056776b4, 0x25a966be, 0x106a03dc }, + { 0x333353d0, -0x2652f551, -0x532cf61b, 0x38669da5, -0x37770810, 0x3c57658a, 0x052cbefa, 0x4ab38a51 } + }, +}, +{ + { + { -0x7f621fac, -0x09701d18, -0x637d452f, -0x1c43f696, 0x0aadbf45, 0x076353d4, -0x215e6a62, 0x7b9b1fb5 }, + { 0x4324c0e9, -0x20253412, 0x3f955bb7, 0x05444288, -0x15ce9f61, -0x21085558, 0x42287cff, 0x68aee706 }, + { 0x7471cc0c, -0x0fe3370f, 0x579082bb, -0x6adbd1c9, -0x2c1b94a1, 0x27776093, 0x28bd85fb, 0x2d13d55a } + }, + { + { 0x7aee7a52, -0x40fe6332, -0x1bab152d, -0x57212d4a, -0x785744e7, 0x3c619f0b, 0x560916d8, 0x3619b5d7 }, + { 0x5b35b8da, -0x053a2dfa, -0x7a9db449, -0x57257566, 0x3d21cd0f, -0x332d356f, -0x7406f2a8, 0x6b8341ee }, + { 0x0282c4b2, 0x3579f26b, 0x4fafefae, 0x64d592f2, 0x28c8c7c0, -0x48321285, 0x7173a8d7, 0x6a927b6b } + }, + { + { 0x3ece88eb, -0x728fbf7a, -0x7f113f74, -0x0f1cf857, 0x0d788fda, -0x53ddaf9f, 0x3a0d478d, 0x056d92a4 }, + { -0x6791b9aa, 0x1f6db24f, -0x2e16efa5, 0x1021c02e, 0x2cc0a375, -0x0700c001, -0x3937da6e, 0x1d2a6bf8 }, + { -0x03c25a5f, 0x1b05a196, 0x43b59ed0, 0x77d7a8c2, -0x682e86e8, 0x06da3d62, -0x0edcac09, 0x66fbb494 } + }, + { + { -0x0edcf62a, -0x2928f66a, -0x163c2ac7, -0x2404dc7b, -0x08aadbef, 0x46d602b0, 0x57843e0c, 0x270a0b05 }, + { -0x27a3f048, 0x751a50b9, -0x7430f685, -0x2e5023db, -0x7cf65697, 0x2f16a6a3, -0x1a4ff9a7, 0x14ddff9e }, + { -0x5879d434, 0x61ff0640, 0x5f11abfe, -0x7e353f66, 0x55d12abb, -0x6fb87cfc, -0x6ba5178d, 0x19a4bde1 } + }, + { + { -0x3f893b61, 0x40c709de, 0x7f3e53f6, 0x657bfaf2, -0x135fbd3c, 0x40662331, 0x7eb4df04, 0x14b37548 }, + { 0x20a6200a, -0x6460d90b, -0x30ec1508, 0x64804443, -0x79ce122d, -0x759c98c1, 0x1ed39dc1, 0x72bbbce1 }, + { -0x549923b9, -0x517ac36c, -0x2089d292, -0x149dcbc2, 0x6fb2f7d1, -0x0f71f1e8, 0x700ab37a, 0x4f0b1c02 } + }, + { + { -0x3e4d1dc1, 0x79fd21cc, 0x453df52a, 0x4ae7c281, -0x2eaeb795, -0x37e8d137, 0x3e0a7534, 0x68abe944 }, + { -0x27e6ae06, -0x1e8f9879, -0x4d6f3885, -0x5ef5d372, 0x3ed66773, -0x18c7d060, 0x0bcc4b54, 0x0a4d8471 }, + { 0x07831dcb, -0x25ed393c, 0x4d5c510d, 0x0da230d7, 0x6bd404e1, 0x4ab1531e, -0x430bbf11, 0x4106b166 } + }, + { + { 0x39e4ecf2, -0x5b7a332b, 0x0555bab5, 0x5aa3f3ad, -0x6c8207d3, 0x145e3439, 0x1214283f, 0x1238b51e }, + { 0x1cd23668, 0x02e57a42, 0x0eaef6fd, 0x4ad9fb5d, -0x4edbbb80, -0x6ab198d9, 0x2699f331, 0x7f792f9d }, + { 0x5fd4d924, 0x0b886b92, 0x3626a80d, 0x60906f7a, -0x467542ee, -0x132c984c, -0x210cbb31, 0x2876beb1 } + }, + { + { 0x3a8a85f8, -0x2a6b4ccd, -0x187282a8, 0x4ea37689, 0x5e8e351f, 0x73bf9f45, -0x43be144c, 0x5507d7d2 }, + { 0x63144691, -0x237b16cb, -0x29e0dc0c, 0x632fe8a0, 0x12a9a8d5, 0x4caa8006, 0x0e9918d3, 0x48f9dbfa }, + { 0x299572fc, 0x1ceb2903, -0x6afd2f12, 0x7c8ccaa2, 0x11cce67b, -0x6e405bcc, 0x64a831e7, 0x57844819 } + }, +}, +{ + { + { 0x5fddc09c, -0x29302e11, -0x08a8a232, -0x17d4c103, 0x201634c2, 0x25d56b5d, 0x04ed2b9b, 0x3041c6bb }, + { 0x6768d593, -0x2583d4db, 0x4422ca13, -0x673e3fa9, -0x35f531e3, -0x0e57f42b, -0x3f775970, 0x29cdd1ad }, + { -0x26a91eb8, 0x0ff2f2f9, -0x60ca94d2, -0x5218688b, 0x5f6c025c, 0x1a4698bb, 0x14049a7b, 0x104bbd68 } + }, + { + { -0x29800e9d, -0x56a265a1, 0x4cc75681, -0x16d41963, -0x21df0da9, -0x4807fdb4, -0x04f8d20b, 0x204f2a20 }, + { 0x68f1ed67, 0x51f0fd31, -0x2790c43e, 0x2c811dcd, 0x04d2f2de, 0x44dc5c43, 0x092a7149, 0x5be8cc57 }, + { 0x30ebb079, -0x37ebc4c3, -0x429ad1d0, 0x7589155a, -0x7092a3cf, 0x653c3c31, -0x3d86e9e1, 0x2570fb17 } + }, + { + { 0x0bb8245a, 0x192ea955, -0x706faf2f, -0x37190458, -0x775b36cb, 0x7986ea2d, -0x21fe7998, 0x241c5f91 }, + { 0x2cb61575, 0x3efa367f, 0x1cd6026c, -0x0a06908a, 0x65b52562, -0x1738ebd6, 0x53030acd, 0x3dcb65ea }, + { 0x40de6caa, 0x28d81729, 0x22d9733a, -0x7040d310, 0x235b01d1, 0x16d7fcdd, 0x5fcdf0e5, 0x08420edd } + }, + { + { 0x04f410ce, 0x0358c34e, 0x276e0685, -0x49eca4a6, -0x1446eadf, 0x5d9670c7, 0x21db889c, 0x04d654f3 }, + { -0x7c9d05b6, -0x3200df55, -0x1de5c192, 0x57e118d4, -0x03c619d5, -0x1ce869e9, -0x43e89603, 0x0d9a53ef }, + { -0x22424a2b, 0x5e7dc116, -0x725a22d3, 0x2954deb6, 0x3334a292, 0x1cb60817, 0x18991ad7, 0x4a7a4f26 } + }, + { + { -0x50c8d5b5, 0x24c3b291, 0x718147f2, -0x6c257d90, -0x7976610e, -0x227b7a9c, 0x23e0ee33, 0x4a963142 }, + { 0x5fb15f95, -0x0b58e7fe, 0x6b5c1b8f, 0x3df65f34, 0x00e01112, -0x32030f7b, -0x222ce7b8, 0x11b50c4c }, + { 0x08a4ffd6, -0x5917d8bc, -0x63ea8927, 0x738e177e, 0x3d02b3f2, 0x773348b6, -0x319433af, 0x4f4bce4d } + }, + { + { -0x3b62f491, 0x30e2616e, -0x3513dce9, -0x1ba98e71, -0x0d94b05a, 0x48eb409b, 0x61595f37, 0x3042cee5 }, + { -0x1ddbda7c, -0x58e031a6, -0x6d0a7562, 0x26ea7256, 0x1cea3cf4, -0x2de5f629, -0x48e3fe1a, 0x73fcdd14 }, + { 0x449bac41, 0x427e7079, -0x431dcef6, -0x7aa51c93, 0x5f841a7c, 0x4cae7621, -0x65631e2a, 0x389e740c } + }, + { + { 0x570eac28, -0x3642870a, 0x27919ce1, -0x1aa4f4ce, -0x5e646e13, 0x65fc3eab, -0x29d9c970, 0x25c425e5 }, + { 0x34dcb9ce, 0x64fcb3ae, -0x1cb72f53, -0x68affcdd, 0x62c6381b, 0x45b3f07d, 0x465a6788, 0x61545379 }, + { -0x0e282192, 0x3f3e06a6, -0x71f9dcf8, 0x3ef97627, 0x4e8a6c77, -0x73eb09da, 0x15484759, 0x6539a089 } + }, + { + { 0x14bb4a19, -0x223b242c, -0x67bdb072, 0x19b2bc3c, 0x36ca7169, 0x48a89fd7, -0x0fe64270, 0x0f65320e }, + { -0x3c2d088d, -0x162de08c, 0x25c46845, -0x3eafabbf, -0x064661cd, 0x624e5ce8, -0x3a32e794, 0x11c5e4aa }, + { -0x35021f3a, -0x2b792e4f, 0x163b5181, 0x4f3fe6e3, -0x050d6c66, 0x59a8af0d, -0x13ccf8d6, 0x4cabc7bd } + }, +}, +{ + { + { 0x1a54a044, -0x083f5e64, 0x77bd9fbb, 0x4a1c5e24, 0x5af22972, -0x591c35ef, 0x3f2e9e0d, 0x1819bb95 }, + { 0x532f7428, 0x16faa8fb, 0x46a4e272, -0x242bd160, -0x74615b80, 0x5337653b, 0x23973f03, 0x40659472 }, + { 0x5e042e84, 0x498fbb79, 0x7698b714, 0x7d0dd89a, 0x27fe6295, -0x7404f45c, 0x21200524, 0x36ba82e7 } + }, + { + { 0x57274ed5, -0x372962f6, 0x60804b17, 0x45ba8032, 0x2255dfac, -0x20c325f0, 0x2709b339, 0x77d22123 }, + { 0x4245ec41, -0x29f13449, 0x34348716, -0x02641762, -0x1bdd7b22, -0x36dbf502, -0x2face24c, 0x4472f648 }, + { 0x64ad94d8, 0x498a6d70, -0x6509dd9d, -0x5a4a3703, 0x45c141f4, -0x735712fb, 0x662d358c, 0x2c63bec3 } + }, + { + { -0x7a790741, -0x65ae74c6, -0x344e6910, -0x6118e50a, -0x5dc7a30e, -0x55f9da1a, -0x2228372f, 0x1deb2176 }, + { -0x158786ab, 0x7fe60d8b, -0x4a0bfe49, -0x4623ee82, 0x19355cce, -0x6e383f66, -0x6bbd4121, 0x22692ef5 }, + { 0x2066cf6c, -0x7a9c2e66, 0x4dcc7cd7, 0x401bfd8c, -0x32f2709e, -0x26895942, -0x5d874fa2, 0x67cfd773 } + }, + { + { 0x5a4e586a, 0x2d5fa985, 0x49beab7e, 0x65f8f7a4, -0x0de2cc2d, -0x55f8b223, 0x1bcb9dee, 0x185cba72 }, + { -0x10c11b8b, -0x7213ce06, -0x61dd026e, -0x66240076, 0x4e26cab1, 0x512d1159, -0x13bcef47, 0x0cde561e }, + { -0x0b1c34bf, -0x6c79625d, 0x40f7977e, -0x40fc6d0b, -0x2fb9c47d, 0x026204fc, -0x61139113, 0x3ec91a76 } + }, + { + { -0x4f5cbfd1, 0x0fad2fb7, -0x04960b58, 0x46615ecb, -0x3a07155a, -0x08ba4338, 0x4a94e896, 0x7a5fa879 }, + { -0x087e9953, 0x1e9df75b, -0x14f32851, 0x4dfda838, -0x3e150678, -0x45ffd128, 0x11f33cfc, 0x13fedb3e }, + { 0x13cd67a1, 0x52958faa, -0x74244ae9, -0x69a11f7f, 0x2e8845b3, 0x16e58daa, 0x5499da8f, 0x357d397d } + }, + { + { 0x194bfbf8, 0x481dacb4, -0x451a7d67, 0x4d77e3f1, 0x7d1372a0, 0x1ef4612e, 0x70ff69e1, 0x3a8d867e }, + { -0x4f453194, 0x1ebfa05f, 0x1caf9a1e, -0x36cb9df4, 0x1d82b61a, -0x3388e33c, -0x5a08b014, 0x2d94a16a }, + { 0x55aff958, 0x6f58cd5d, 0x75567721, -0x45c155a4, -0x6e9add83, 0x75c12399, -0x3d0d4ca2, 0x69be1343 } + }, + { + { 0x684b8de3, -0x7d444254, 0x3fca0718, -0x5d0b3830, -0x1f695558, 0x337f92fb, 0x63587376, 0x200d4d8c }, + { -0x1e6836d6, 0x0e091d5e, 0x2945119f, 0x4f51019f, -0x0fcb1664, 0x143679b9, 0x4d24c696, 0x7d88112e }, + { 0x4893b32b, 0x208aed4b, -0x41a6469c, 0x3efbf23e, -0x245a1af9, -0x289d2150, -0x7e42626c, 0x69607bd6 } + }, + { + { -0x6cdc56fe, 0x3b7f3bd4, 0x6b2c6e53, 0x7c21b556, 0x3a7852a7, -0x1a45700b, -0x7c713200, 0x28bc77a5 }, + { 0x68de1ce1, -0x0941fdf0, 0x0edcbc1f, -0x172ae719, 0x1b5505a5, -0x1c100230, -0x2c13c030, 0x35f63353 }, + { -0x1da27fca, 0x63ba78a8, -0x6bcccb70, 0x63651e00, 0x288ce532, 0x48d82f20, 0x36b57524, 0x3a31abfa } + }, +}, +{ + { + { 0x3f78d289, -0x3f708771, -0x5ebfb261, -0x01cf58d4, -0x309a3363, -0x0d887404, 0x5acb2021, 0x7ee49816 }, + { 0x089c0a2e, 0x239e9624, 0x3afe4738, -0x38b73b40, 0x764fa12a, 0x17dbed2a, 0x321c8582, 0x639b93f0 }, + { -0x6eee5e3d, 0x7bd508e3, -0x7f6f8b77, 0x2b2b90d4, -0x518d02e7, -0x182d513e, -0x7a49fd5a, 0x0edf493c } + }, + { + { -0x7b89beed, 0x6767c4d2, -0x080a07cb, -0x5f6fbfc1, -0x35194122, 0x1c8fcffa, -0x2e205c97, 0x04c00c54 }, + { 0x599b5a68, -0x51337ea8, -0x14521df2, -0x15a8b0f1, 0x22b67f07, 0x4fe41d74, 0x019d4fb4, 0x403b92e3 }, + { -0x74b9a308, 0x4dc22f81, 0x1480eff8, 0x71a0f35a, 0x04c7d657, -0x51174053, -0x4d9e890c, 0x355bb12a } + }, + { + { 0x5a8c7318, -0x5cfe2539, -0x4c3155ef, -0x126ffc63, 0x3bae3f2d, 0x6f077cbf, -0x1fad5272, 0x7518eaf8 }, + { 0x7493bbf4, -0x58e19b34, -0x135c4f3d, -0x1a427b27, -0x05fa187b, 0x0a6bc50c, 0x182ec312, 0x0f9b8132 }, + { 0x1b7f6c32, -0x5b77a63c, -0x0bc7cd68, 0x0f2d60bc, -0x364e2e27, 0x1815a929, -0x44e8aa3c, 0x47c3871b } + }, + { + { -0x37af9950, -0x0419a2b0, -0x4c5d6650, 0x62ecc4b0, 0x441ae8e0, -0x1ac8ab16, -0x172b72a1, 0x08fea02c }, + { 0x71ec4f48, 0x51445397, -0x3673a292, -0x07fa4e83, 0x47c3c66b, -0x089d3ee6, 0x764699dc, 0x00b89b85 }, + { 0x68deead0, -0x7db2228a, 0x4b685d23, -0x379bbae0, 0x5d89d665, -0x4aeb3033, 0x4f75d537, 0x473829a7 } + }, + { + { -0x52c6fd37, 0x23d9533a, -0x10fca771, 0x64c2ddce, -0x301ed04c, 0x15257390, 0x44e4d390, 0x6c668b4d }, + { 0x4679c418, -0x7d2d258b, -0x4d9e7210, -0x19c42828, -0x53b814f6, 0x355eef24, 0x4833c6b4, 0x2078684c }, + { 0x7a78820c, 0x3b48cf21, -0x7ed8c169, -0x0895f54e, -0x73711285, -0x56939a59, 0x4f8a433f, 0x7411a605 } + }, + { + { 0x18b175b4, 0x579ae53d, -0x0c6d5efe, 0x68713159, 0x1eef35f5, -0x7baa1346, 0x458c398f, 0x1ec9a872 }, + { -0x46623793, 0x4d659d32, 0x603af115, 0x044cdc75, -0x233d1b78, -0x4cb38ed4, -0x047ecb01, 0x7c136574 }, + { 0x00a2509b, -0x47195b2c, 0x0bc882b4, -0x647e28fe, -0x0e6a8a9f, 0x57e7cc9b, -0x38329ba0, 0x3add88a5 } + }, + { + { 0x59393046, -0x7a3d672c, 0x5ff659ec, -0x7081ca68, -0x0d0991c6, 0x1d2ca22a, -0x5bf958e0, 0x61ba1131 }, + { -0x49ca230e, -0x5476a890, -0x0993e044, 0x02dfef6c, -0x41492e79, -0x7aacfd98, -0x3378618c, 0x249929fc }, + { 0x16959029, -0x5c2f5f0f, -0x45814277, 0x023b6b6c, 0x26783307, 0x7bf15a3e, -0x44271319, 0x5620310c } + }, + { + { 0x77e285d6, 0x6646b5f4, 0x6c8f6193, 0x40e8ff67, -0x544a6b23, -0x59138cef, 0x658cec4d, 0x7ec846f3 }, + { 0x4934d643, 0x52899343, -0x5aeddd0b, -0x462407fa, -0x3c0be3de, -0x70927871, 0x4d9d9730, 0x37676a2a }, + { 0x1da22ec7, -0x64a170c1, 0x6c01cd13, 0x130f1d77, -0x5d676048, 0x214c8fcf, 0x399b9dd5, 0x6daaf723 } + }, +}, +{ + { + { 0x2cd13070, -0x7e514423, -0x07a5f162, -0x69d1bcdb, -0x35200135, -0x216c6e56, 0x52c230e6, 0x53177fda }, + { 0x10628564, 0x591e4a56, -0x574b20cc, 0x2a4bb87c, -0x185c71bd, -0x21d5da8e, -0x011afb92, 0x3cbdabd9 }, + { 0x50b9de79, -0x584368fa, -0x3cfe4a65, 0x3d12a7fb, -0x2c951c74, 0x02652e68, 0x5a6199dc, 0x79d73983 } + }, + { + { 0x0d591737, 0x21c9d992, -0x164b932a, -0x6415be2e, 0x0d89bfca, -0x1df17be0, 0x6eae5ff8, 0x79d99f94 }, + { 0x4131c1bd, -0x26cab20a, -0x7913a7de, 0x758094a1, -0x1ba60c3e, 0x4464ee12, -0x34eccd7e, 0x6c11fce4 }, + { 0x68673205, -0x0e84b7cb, 0x3caad96c, 0x387deae8, 0x56ffe386, 0x61b471fd, -0x48ba5a67, 0x31741195 } + }, + { + { 0x3b02a047, 0x17f8ba68, -0x01104938, 0x50212096, 0x1556cbe2, 0x70139be2, 0x1d98915b, 0x203e44a1 }, + { -0x4885c9f5, -0x172efe70, -0x666a18fe, -0x66467ce0, -0x05fdb856, -0x42b02008, -0x1f2c9579, 0x2772e344 }, + { 0x37b9e39f, -0x2979c146, 0x723b5a23, 0x105bc169, -0x59a3f89e, 0x104f6459, 0x5b4d38d4, 0x56795129 } + }, + { + { 0x0d4b497f, 0x07242eb3, -0x46433379, 0x1ef96306, -0x27ee90bb, 0x37950934, 0x01405b04, 0x05468d62 }, + { 0x13037524, 0x535fd606, -0x4f043d96, -0x1def520a, 0x23e990ae, -0x5372f565, -0x28d02407, 0x47204d08 }, + { -0x06cd9822, 0x00f565a9, -0x3f2a7176, -0x31302873, -0x0ce71d72, -0x5dea1d24, -0x649cccae, 0x4599ee91 } + }, + { + { -0x79e51a87, -0x538b9295, -0x09515624, 0x31ab0650, 0x40256d4c, 0x241d6611, 0x3d21a5de, 0x2f485e85 }, + { 0x70e0e76b, -0x2c3ddf36, -0x1560cf6c, -0x4ed415a8, -0x3cd8ed7e, 0x294ddec8, -0x5e2e2fd8, 0x0c3539e1 }, + { -0x63f7cc0d, 0x32974483, -0x2d543b7c, 0x6fe6257f, 0x4b358817, 0x5327d181, -0x76c01644, 0x65712585 } + }, + { + { -0x28f711c1, -0x7e3d60e5, -0x519bf830, -0x2234a5fb, -0x2d5c1459, -0x68513e29, -0x6e2af7cf, 0x1590521a }, + { 0x32a61161, -0x63efd049, 0x34d520a8, -0x1b71ef23, 0x6f9a9176, 0x365c6354, 0x046f6006, 0x32f6fe4c }, + { -0x386ef534, 0x40a3a11e, -0x0e92d852, -0x6fec2008, -0x544e6a2c, 0x1a9720d8, 0x2ea98463, 0x1bb9fe45 } + }, + { + { -0x33c98b84, -0x30a1936b, 0x6b0bc30d, 0x29420153, -0x11868510, 0x453ac67c, 0x2a8bb3c9, 0x5eae6ab3 }, + { -0x4c2ab062, -0x162e26b0, -0x1ff2cc3f, 0x2d5f9cbe, -0x5fb03954, 0x51c2c656, 0x3c1cbcc9, 0x65c091ee }, + { 0x14f118ea, 0x70836611, -0x6bcb6353, 0x2b37b87b, -0x4b1660c0, 0x7273f51c, 0x23d75698, 0x78a2a958 } + }, + { + { 0x5ef83207, -0x4b0dc3be, -0x3656cb4b, -0x54076b2d, 0x39fd87f7, -0x2f8f73ed, 0x17166130, 0x18767891 }, + { 0x5c8c2ace, -0x5d4f8d17, 0x651e9c4b, 0x69cffc96, 0x42e7b42b, 0x44328ef8, 0x22aadeb3, 0x5dd996c1 }, + { 0x670c507c, -0x6da4a110, -0x46c3cc41, -0x7e6437be, 0x70dd003f, 0x10792e9a, 0x6e28dc74, 0x59ad4b7a } + }, +}, +{ + { + { -0x5352715e, 0x583b04bf, 0x148be884, 0x29b743e8, 0x0810c5db, 0x2b1e583b, -0x714c4456, 0x2b5449e5 }, + { -0x14c241b9, 0x5f3a7562, -0x71425f48, -0x0815c7ac, 0x45747299, 0x00c3e531, 0x1627d551, 0x1304e9e7 }, + { 0x6adc9cfe, 0x789814d2, -0x74b722f5, 0x3c1bab3f, -0x068639f6, -0x25f01e01, 0x7c2dd693, 0x4468de2d } + }, + { + { -0x079cf832, 0x4b9ad8c6, 0x435d0c28, 0x21113531, 0x657a772c, -0x2b57993b, 0x63247352, 0x5da6427e }, + { -0x6be6b962, 0x51bb355e, 0x23ddc754, 0x33e6dc4c, 0x447f9962, -0x6c5a492a, -0x04bb429d, 0x6cce7c6f }, + { -0x2153dd36, 0x1a94c688, -0x4451e008, -0x46f99109, -0x72a6a7f1, -0x775273c8, -0x1860d358, 0x58f29abf } + }, + { + { 0x710ecdf6, 0x4b5a64bf, 0x462c293c, -0x4eb31ac8, -0x2af4c547, 0x3643d056, 0x185b4870, 0x6af93724 }, + { -0x7218c198, -0x16f13055, 0x377e76a5, 0x54036f9f, -0x41fea67e, -0x0fb6a4f5, -0x580be1ca, 0x577629c4 }, + { 0x09c6a888, 0x32200245, 0x4b558973, -0x2d1fc9ed, 0x3c33289f, -0x7c1dc9dd, 0x0caec18f, 0x701f25bb } + }, + { + { 0x7cbec113, -0x62e70927, 0x74bfdbe4, -0x7bb5f91a, -0x53b19f2a, 0x20f5b522, 0x50955e51, 0x720a5bc0 }, + { -0x1b9e9313, -0x3c574f08, -0x61da5783, -0x08ff99f2, -0x0b435a64, 0x61e3061f, -0x423bf417, 0x2e0c92bf }, + { -0x647fa5cb, 0x0c3f0943, 0x6242abfc, -0x17b174c9, 0x5c229346, 0x691417f3, 0x144ef0ec, 0x0e9b9cbb } + }, + { + { 0x5db1beee, -0x7211642b, 0x0a723fb9, -0x363c54c9, 0x1c68d791, 0x44a8f1bf, 0x1cfd3cde, 0x366d4419 }, + { -0x04a8df53, -0x04452b71, -0x2406f2f2, -0x117e6e95, 0x635543bf, -0x2b7eceae, 0x3f337bd8, 0x221104eb }, + { -0x0d4373ec, -0x61c3e8bd, -0x4a7a93c5, 0x2eda26fc, 0x68a7fb97, -0x3347d0f2, -0x43a6cdbc, 0x4167a4e6 } + }, + { + { -0x07317012, -0x3d41d99b, -0x177f29d4, -0x169800ec, 0x2f364eee, -0x0ed19182, -0x34812d0a, 0x34b33370 }, + { 0x76f62700, 0x643b9d28, 0x0e7668eb, 0x5d1d9d40, 0x21fc0684, 0x1b4b4303, 0x2255246a, 0x7938bb7e }, + { -0x797e2934, -0x323a6e12, -0x127a58ad, -0x31fdef64, 0x58808883, -0x128b7a3f, 0x2dfe65e4, 0x1176fc6e } + }, + { + { 0x49770eb8, -0x246f1d77, -0x530bbf5d, -0x670433d6, -0x21287865, 0x21354ffe, -0x0d96f94a, 0x1f6a3e54 }, + { 0x5b9c619b, -0x4b509330, -0x4d5a7b80, 0x2ddfc9f4, -0x1416b23c, 0x3d4fa502, 0x677d5f34, 0x08fc3a4c }, + { -0x2cf8cb16, 0x60a4c199, 0x31165cd6, 0x40c085b6, -0x08a67d6b, -0x1dccc1dd, 0x16b900d1, 0x4f2fad01 } + }, + { + { -0x48c449c8, -0x69d326e3, -0x03ed63f8, -0x19fa8856, -0x0c49e977, 0x6f619b39, 0x2944ee81, 0x3451995f }, + { -0x6b51b1ac, 0x44beb241, 0x1857ef6c, 0x5f541c51, 0x368d0498, -0x59e194d3, -0x68d10855, 0x445484a4 }, + { -0x60158284, -0x6ead0330, -0x4f6ca30a, 0x4a816c94, 0x47285c40, 0x258e9aaa, 0x042893b7, 0x10b89ca6 } + }, +}, +{ + { + { 0x79d34aa0, -0x2983212a, -0x33b24c61, -0x33f46140, -0x1ca2e6f1, -0x5aca5baa, -0x09e09011, 0x2e05d9ea }, + { 0x3b646025, -0x64d5bd92, 0x385ce4cf, 0x32127190, -0x229215bb, -0x5da3003e, -0x4157218b, 0x06409010 }, + { -0x29e414a7, -0x3bb86fe6, -0x1a2377f6, 0x661f19bc, -0x483597d9, 0x24685482, -0x101f80da, 0x293c778c } + }, + { + { -0x5ee00e00, 0x16c795d6, -0x4ea7ea37, -0x348f2f1e, -0x64ac6a4b, -0x760d6ce0, 0x31e47b4f, 0x50b8c2d0 }, + { 0x07069096, -0x797f6190, -0x1b1afe77, -0x5528a4eb, -0x5de5feb9, 0x07f35715, 0x12815d5e, 0x0487f3f1 }, + { 0x068a4962, 0x48350c08, 0x51092c9a, 0x6ffdd053, -0x50903723, 0x17af4f4a, 0x3cdba58b, 0x4b0553b5 } + }, + { + { 0x27c152d4, -0x40fadee5, -0x42e509c7, 0x5ec26849, -0x71905468, 0x5e0b2caa, 0x50bd0840, 0x054c8bdd }, + { 0x1b32ff79, -0x639a0342, 0x03b50f9b, -0x148a1561, 0x6c07e606, -0x0312d594, 0x51717908, 0x35106cd5 }, + { 0x1dcf073d, 0x38a0b12f, -0x48095d8a, 0x4b60a8a3, -0x2cbfb066, -0x012a53db, 0x5505c229, 0x72e82d5e } + }, + { + { 0x69771d02, 0x00d9cdfd, 0x6cfbf17e, 0x410276cd, 0x1cb12ec7, 0x4c45306c, 0x27500861, 0x2857bf16 }, + { -0x0f27bb38, 0x6b0b697f, -0x268634b7, -0x44ed07a4, -0x3e25f0e1, -0x2d5abe3a, 0x58ce7211, 0x7b7c2429 }, + { 0x0101689e, -0x60de6fc1, -0x4079effb, -0x2886202d, 0x3deb0f1b, -0x5edd11a1, 0x485a00d4, 0x510df84b } + }, + { + { -0x38f53ea2, 0x24b3c887, -0x047e48ce, -0x4f0c5aa9, -0x1a8733e5, -0x64d321d1, 0x03b54f8e, 0x4cf7ed07 }, + { -0x6d885e06, -0x5abecc45, 0x63991237, 0x74ec3b62, 0x35d2f15a, 0x1a3c54dc, -0x1b7d45c6, 0x2d347144 }, + { -0x670411f1, 0x6bd47c65, -0x54aa41d3, -0x61b8cc1e, 0x127610c5, 0x1093f624, -0x2f5e155c, 0x4e05e26a } + }, + { + { -0x1e701940, 0x1833c773, -0x2c378d9b, -0x1c3b8ee6, 0x0116b283, 0x3bfd3c4f, -0x4b32b248, 0x1955875e }, + { 0x4b531f20, -0x2564949e, 0x77509abb, 0x429a760e, -0x17dc3480, -0x24160ade, -0x77f3707e, 0x618f1856 }, + { 0x0e399799, 0x6da6de8f, 0x40fda178, 0x7ad61aa4, 0x5e3563dd, -0x4cd327f0, 0x2ae340ae, 0x15f6beae } + }, + { + { -0x6dba1deb, -0x4565f085, -0x2673f245, -0x0c979ed3, -0x0ddf4fe0, 0x2e84e4cb, 0x62d90eda, 0x6ba92fe9 }, + { 0x31ec3a62, -0x79d434f4, 0x1138f3c2, -0x7ef1d4bb, 0x39dac2a4, 0x788ec4b8, -0x51d56d7f, 0x28f76867 }, + { 0x5884e2aa, 0x3e4df965, -0x242b9a5b, -0x429d0425, 0x0de9e524, -0x28a69356, -0x4d4e4c29, 0x6e8042cc } + }, + { + { 0x16521f7e, 0x15306536, -0x69dfc246, 0x660d06b8, 0x545f0879, 0x2d3989bc, 0x78ebd7b0, 0x4b5303af }, + { -0x31d73592, -0x0ef2c3d7, -0x0349f6c3, -0x452cbac0, -0x5d15d2c1, -0x18bd9129, 0x4ff298b9, 0x08af9d4e }, + { -0x41434218, 0x72f8a6c3, -0x23c57177, 0x4f0fca4a, -0x38402086, 0x6fa9d4e8, -0x649db149, 0x0dcf2d67 } + }, +}, +{ + { + { 0x5a45f06e, 0x753941be, 0x6d9c5f65, -0x2f835113, 0x72ff51b6, 0x11776b9c, -0x10f2b257, 0x17d2d1d9 }, + { -0x68e7d764, 0x3d594749, 0x24533f26, 0x12ebf8c5, 0x14c3ef15, 0x0262bfcb, 0x77b7518e, 0x20b878d5 }, + { 0x073f3e6a, 0x27f2af18, -0x28adef97, -0x02c01ae7, 0x3ca60022, 0x22e3b72c, -0x339a3959, 0x72214f63 } + }, + { + { -0x0bc4d637, 0x1d9db7b9, 0x4f518f75, -0x29fa7db6, 0x312f9dc4, -0x0d3f8d43, 0x5a1545b0, 0x1f24ac85 }, + { 0x5307a693, -0x4b1c80c0, 0x2f336795, -0x5458eb29, 0x73761099, -0x29042f59, -0x7e8e3437, 0x5fdf48c5 }, + { -0x716afa56, 0x24d60832, 0x0c1420ee, 0x4748c1d1, 0x06fb25a2, -0x38001ba4, 0x2ae395e6, 0x00ba739e } + }, + { + { -0x157744da, -0x51bbd90b, -0x7b68c405, 0x360679d9, 0x26694e50, 0x5c9f030c, -0x2ae72dda, 0x72297de7 }, + { 0x5c8790d6, 0x592e98de, 0x45c2a2df, -0x1a40482d, -0x064b66de, 0x115a3b60, 0x67ad78f3, 0x03283a3e }, + { -0x41f346c7, 0x48241dc7, -0x749ccf80, 0x32f19b4d, 0x02289308, -0x2c2036f3, 0x46271945, 0x05e12968 } + }, + { + { 0x242c4550, -0x52404438, -0x2fcf7e27, -0x4337f314, -0x0a37206e, -0x7bca995a, -0x7da731b4, 0x78cf25d3 }, + { 0x2d9c495a, -0x457d114d, -0x0ed44684, -0x31103704, -0x6c4a2e20, -0x4fd25452, 0x13698d9b, 0x39c00c9c }, + { 0x31489d68, 0x15ae6b8e, -0x63d40f79, -0x557ae355, -0x0fb105fb, -0x3658a569, 0x6b3ff832, 0x006b5207 } + }, + { + { -0x4631f7d3, -0x0a3481ea, 0x417abc29, 0x3407f14c, 0x2bf4a7ab, -0x2b4c9432, 0x1a9f75ce, 0x7de2e956 }, + { -0x626a87e4, 0x29e0cfe1, -0x699cef1e, -0x497e20e8, 0x70516b39, 0x57df39d3, 0x3bc76122, 0x4d57e344 }, + { -0x495aa135, -0x218f2b0c, 0x5d85db99, 0x4801527f, -0x2c11657f, -0x24363bc0, 0x1a6029ed, 0x6b2a90af } + }, + { + { 0x5bb2d80a, 0x77ebf324, 0x2fb9079b, -0x27cfe4b9, 0x4cee7333, -0x39b8190e, 0x276c2109, 0x465812c8 }, + { -0x6519e169, 0x6923f4fc, -0x1fc0a02f, 0x5735281d, -0x19122ed3, -0x589b51bd, -0x2ed2c1b6, 0x5fd8f4e9 }, + { 0x2a1062d9, 0x4d43beb2, 0x3831dc16, 0x7065fb75, -0x21d69729, 0x180d4a7b, 0x1cb16790, 0x05b32c2b } + }, + { + { 0x7ad58195, -0x08035bd4, 0x4333f3cc, 0x3214286e, 0x340b979d, -0x493d62f3, 0x567307e1, 0x31771a48 }, + { -0x2db25703, -0x373fa134, 0x05dfef83, -0x5e30e554, 0x7df9cd61, -0x2441100e, 0x7b471e99, 0x3b5556a3 }, + { -0x1eb22b7e, 0x32b0c524, 0x1a2ba4b6, -0x124caeac, 0x282b5af3, -0x5c2e9fb8, 0x7a7336eb, 0x4fc079d2 } + }, + { + { 0x0c86c50d, -0x23cb74bc, -0x336b19af, 0x1337cbc9, 0x643e3cb9, 0x6422f74d, -0x451c32f8, 0x241170c2 }, + { -0x7640d081, 0x51c938b0, 0x02dfe9a7, 0x2497bd65, 0x7880e453, -0x00003f64, -0x3506716e, 0x124567ce }, + { 0x0ac473b4, 0x3ff9ab86, 0x0113e435, -0x0f6ee212, -0x14393b51, 0x4ae75060, 0x6c87000d, 0x3f861296 } + }, +}, +{ + { + { 0x638c7bf3, 0x529fdffe, 0x388b4995, -0x20d461a0, 0x1bad0249, -0x1fd84cb1, -0x46058b13, 0x7bc92fc9 }, + { -0x086a841c, 0x0c9c5303, -0x1f7a3ebb, -0x5c3ce5e0, -0x2f7affb0, -0x4f8de28f, -0x54f40d26, 0x0aba390e }, + { -0x7fe52607, -0x606810d2, 0x79afda3a, -0x7c9682ac, -0x42a694b0, -0x16f94c01, -0x22c04720, 0x02672b37 } + }, + { + { 0x398ca7f5, -0x116458d7, 0x7a4849db, -0x146359db, 0x7ec544e1, 0x29eb29ce, -0x08c91d38, 0x232ca21e }, + { 0x260885e4, 0x48b2ca8b, -0x7d4cb3e4, -0x5bd79414, 0x17f58f74, -0x6c81e5da, -0x54d35d5b, 0x741d1fcb }, + { 0x253fcb17, -0x409ebdc3, -0x05c614ec, 0x08803cea, -0x67ae3851, -0x0e79fd21, 0x49e3414b, 0x0400f3a0 } + }, + { + { -0x5f9184fa, 0x2efba412, 0x2c8d2560, 0x14678545, -0x29856e39, -0x2068ec15, 0x157eadf3, 0x32830ac7 }, + { -0x459e3aa5, -0x5431fb8a, -0x3b2c68ea, 0x36a3d6d7, -0x1727d2f7, 0x6eb259d5, -0x7b28a905, 0x0c9176e9 }, + { -0x48c89618, 0x0e782a7a, 0x75b18e2c, 0x04a05d78, -0x1433151f, 0x29525226, -0x7c1457e0, 0x0d794f83 } + }, + { + { -0x585d1e54, 0x7be44ce7, -0x052e4749, 0x411fd93e, 0x0d5f7c9b, 0x1734a1d7, 0x3127db16, 0x0d659223 }, + { -0x61eae90c, -0x00ca0a35, 0x648aae45, -0x117fa431, -0x46c5610d, -0x0f28c3d5, 0x2092a6c2, 0x097b0bf2 }, + { 0x21a9d733, -0x3b7454eb, -0x29e544db, -0x593d1516, -0x3934bcfb, 0x625c6c1c, -0x6c14c599, 0x7fc90fea } + }, + { + { -0x63834dc3, -0x3ad8214b, 0x5328404e, -0x6aac6e97, 0x7ccf2c7a, -0x29bc6d7f, -0x082705ef, 0x6ce97dab }, + { 0x1f5c5926, 0x0408f1fe, 0x3b258bf4, 0x1a8f2f5e, -0x0238e997, 0x40a951a2, -0x3674a882, 0x6598ee93 }, + { 0x0ef7c48f, 0x25b5a8e5, 0x6f2ce532, -0x149fcbef, -0x1ac21ac9, -0x3a18ae8d, -0x73ed44fd, 0x73119fa0 } + }, + { + { 0x21f4774d, 0x7845b94d, 0x7897b727, -0x409d0e94, 0x3c56522b, 0x671857c0, -0x6a9dedee, 0x3cd6a852 }, + { 0x53f1a4cb, -0x12cfed6c, -0x370ac879, -0x4319de37, 0x38bee7b9, -0x0534d4ed, -0x6157bd74, 0x3025798a }, + { 0x3aeca999, 0x3fecde92, 0x62e8c12f, -0x4255a500, -0x69677522, 0x67b99dfc, 0x52661036, 0x3f52c028 } + }, + { + { -0x113be93a, -0x6da74067, -0x562d098f, -0x5375afe9, 0x16dea4ab, 0x629549ab, -0x66f6ea97, 0x05d0e85c }, + { 0x2a1351c6, -0x00155b72, -0x0580ac29, 0x28624754, 0x7582ddf1, 0x0b5ba9e5, -0x596953a7, 0x60c0104b }, + { -0x21634169, 0x051de020, -0x4af4308c, -0x05f803aa, 0x0f11df65, 0x378cec9f, -0x546921b3, 0x36853c69 } + }, + { + { -0x053a1842, 0x4433c0b0, 0x4c08dcbe, 0x724bae85, 0x46978f9b, -0x0e0db33c, 0x62825fc8, 0x4a0aff6d }, + { 0x78f39b2d, 0x36d9b8de, -0x57b84614, 0x7f42ed71, 0x79bd3fde, 0x241cd1d6, -0x6d043195, 0x6a704fec }, + { 0x61095301, -0x16e80462, 0x02a092f8, -0x3efd206c, -0x0599e6f5, -0x40f61d0b, -0x1f2301c9, 0x681109be } + }, +}, +{ + { + { 0x36048d13, -0x63e70306, 0x73899ddd, 0x29159db3, -0x606d2f56, -0x2360caf5, -0x7875e62c, 0x26f57eee }, + { 0x782a0dde, 0x559a0cc9, -0x158e7c7b, 0x551dcdb2, 0x31ef238c, 0x7f62865b, 0x7973613d, 0x504aa776 }, + { 0x5687efb1, 0x0cab2cd5, 0x247af17b, 0x5180d162, 0x4f5a2467, -0x7a3ea5cc, -0x6245cf97, 0x4041943d } + }, + { + { -0x5d935523, 0x4b217743, 0x648ab7ce, 0x47a6b424, 0x03fbc9e3, -0x34e2b086, -0x67ff2fe7, 0x12d93142 }, + { 0x43ebcc96, -0x3c3f1146, 0x26ea9caf, -0x728b6364, 0x1c77ccc6, -0x26056a12, 0x7684340f, 0x1420a1d9 }, + { -0x2cc8a6b1, 0x00c67799, -0x4dc55b85, 0x5e3c5140, -0x1ca00c6b, 0x44182854, 0x4359a012, 0x1b4f9231 } + }, + { + { -0x5b67994f, 0x33cf3030, 0x215f4859, 0x251f73d2, 0x51def4f6, -0x547d55c0, 0x6f9a23f6, 0x5ff191d5 }, + { -0x76eaf6af, 0x3e5c109d, 0x2de9696a, 0x39cefa91, -0x68a0cfe0, 0x20eae43f, 0x7f132dae, 0x239b572a }, + { -0x53d26f98, -0x7e612bcd, 0x5fc98523, 0x2883ab79, 0x5593eb3d, -0x10ba8d80, 0x758f36cb, 0x020c526a } + }, + { + { -0x0fbd3377, -0x16ce10a7, -0x71edb44a, 0x2c589c9d, -0x5138a669, -0x52371e76, 0x5602c50c, 0x452cfe0a }, + { -0x61272444, 0x779834f8, -0x23835b94, -0x370d5507, -0x5c1e4f8c, -0x56adb324, 0x15313877, 0x02aacc46 }, + { 0x647877df, -0x795f0860, 0x0e607c9f, -0x443b9bd9, -0x0e04ee37, -0x54e815db, 0x304b877b, 0x4cfb7d7b } + }, + { + { -0x687610ee, -0x1d79663e, -0x20a8e6f3, 0x2b6ecd71, -0x13368f30, -0x3cbc37a9, 0x434d3ac5, 0x5b1d4cbc }, + { -0x47648a02, 0x72b43d6c, -0x63952380, 0x54c694d9, 0x3ee34c9f, -0x473c55c9, 0x39075364, 0x14b4622b }, + { -0x33f560da, -0x4904d9eb, -0x4772331b, 0x3a4f0e2b, 0x3369a705, 0x1301498b, 0x58592dd1, 0x2f98f712 } + }, + { + { 0x4f54a701, 0x2e12ae44, -0x56342822, -0x0301c110, 0x75835de0, -0x314076f3, -0x189ebaac, 0x1d8062e9 }, + { -0x4af061aa, 0x0c94a74c, -0x7171ece0, 0x5b1ff4a9, -0x7dcff099, -0x65d533df, -0x27f95507, 0x3a6ae249 }, + { -0x566f83a6, 0x657ada85, -0x6e46f09e, 0x1a0ea8b5, -0x20cb4b17, -0x72f1e205, -0x510da00d, 0x298b8ce8 } + }, + { + { 0x0a2165de, -0x7c858d16, 0x0bcf79f6, 0x3fab07b4, 0x7738ae70, 0x521636c7, 0x03a7d7dc, 0x6ba62718 }, + { -0x1008f34e, 0x2a927953, 0x79157076, 0x4b89c92a, 0x30a7cf6a, -0x6be7ba86, 0x4d5ce485, 0x34b8a840 }, + { -0x7c96cccb, -0x3d91134b, 0x63b5fefd, -0x2a57ec21, -0x5b4dda8d, -0x5d6c5566, 0x465e1c6a, 0x71d62bdd } + }, + { + { -0x4e08a10b, -0x32d24a26, 0x16b065f5, -0x28806a31, 0x3f49f085, 0x14571fea, 0x262b2b3d, 0x1c333621 }, + { -0x2c872080, 0x6533cc28, 0x0a0fa4b4, -0x0924bc87, -0x08fe25a6, -0x1c9ba007, -0x0ce8d45c, 0x74d5f317 }, + { 0x67d9ca81, -0x57901aac, 0x2b298c37, 0x398b7c75, -0x1c539dc5, -0x2592f76e, 0x47e9d98c, 0x4aebcc45 } + }, +}, +{ + { + { -0x5fa65bbb, 0x0de9b204, 0x4b17ad0f, -0x1ea34b56, 0x1f79c557, -0x1e4413ae, -0x2f8ef7e5, 0x2633f1b9 }, + { 0x05d21a77, 0x53175a72, -0x2c46cb2c, -0x4f3fbbde, -0x22a21524, -0x52260db5, -0x60ef0074, 0x074f46e6 }, + { 0x018b9910, -0x3e04be89, 0x6c0fe140, -0x5915df24, 0x4354c6ff, -0x299e0c19, -0x0e5cbf86, 0x5ecb72e6 } + }, + { + { -0x17179669, -0x01151efa, -0x672f6c7d, -0x679ccc81, -0x55f91411, -0x6b8fb7f2, -0x2b3a3d30, 0x038b6898 }, + { 0x2259fb4e, -0x5aea5ce5, 0x2bcac52f, 0x0960f397, -0x72cbab35, -0x124ad014, -0x3b893fe7, 0x382e2720 }, + { -0x7531af5a, -0x0c6e3ae3, -0x51d2d6b8, 0x3142d0b9, 0x7f24ca80, -0x24b2a5e6, 0x59250ea8, 0x21aeba8b } + }, + { + { -0x0ff780dd, 0x53853600, -0x2582a87c, 0x4c461879, -0x4be097a0, 0x6af303de, -0x3d83e713, 0x0a3c16c5 }, + { -0x30bfaad0, 0x24f13b34, 0x43088af7, 0x3c44ea4a, 0x0006a482, 0x5dd5c517, -0x76f4f793, 0x118eb8f8 }, + { -0x336b80c3, 0x17e49c17, -0x553e2d85, -0x3339125a, -0x4f0f71aa, -0x209f6d32, 0x2c67c36b, 0x4909b3e2 } + }, + { + { 0x706ff64e, 0x59a16676, 0x0d86a53d, 0x10b953dd, -0x31a3f46a, 0x5848e1e6, 0x12780c68, 0x2d8b78e7 }, + { 0x63fe2e89, -0x63637a16, 0x0e9412ec, -0x41e4506f, -0x79040185, -0x70845576, -0x10697494, 0x0fb17f9f }, + { -0x503c6fd5, 0x79d5c62e, -0x7617f8d8, 0x773a2152, -0x1efedf47, -0x3c7519c0, 0x7b2b1a6d, 0x09ae2371 } + }, + { + { -0x52cd4e30, 0x10ab8fa1, -0x1d8874dc, -0x165312e5, 0x373de90f, -0x577a9440, -0x225ac66a, 0x66f35ddd }, + { 0x4e4d083c, -0x4495e6d6, 0x0029e192, 0x34ace063, -0x55054515, -0x67dba5a7, -0x25680554, 0x6d9c8a9a }, + { 0x24997323, -0x2d826505, -0x090fe2d2, 0x1bb7e07e, -0x0ad13381, 0x2ba7472d, 0x646f9dc8, 0x03019b4f } + }, + { + { -0x194c2395, -0x50f64dec, -0x5282d09b, 0x3f7573b5, 0x100a23b0, -0x2fe62678, -0x74a3ca09, 0x392b63a5 }, + { 0x565345cd, 0x04a186b5, -0x433bee96, -0x111899f0, 0x78fb2a45, 0x689c73b4, 0x65697512, 0x387dcbff }, + { -0x63f83dfb, 0x4093addc, -0x0acd3c82, -0x3a9a41eb, 0x1583402a, 0x63dbecfd, -0x10d1fcd2, 0x61722b4a } + }, + { + { -0x7e34f1c4, -0x294f85ab, -0x26bbb697, 0x290ff006, 0x16dcda1f, 0x08680b6a, 0x5a06de59, 0x5568d2b7 }, + { -0x1342b851, 0x0012aafe, 0x1cd46309, 0x55a266fb, 0x0967c72c, -0x0dfc1498, -0x35c3ebd7, 0x39633944 }, + { 0x1b37cfe1, -0x72f34774, 0x053818f3, 0x05b6a5a3, -0x487826a7, -0x0d1643fc, -0x6522809c, 0x6beba124 } + }, + { + { 0x43f5a53b, 0x5c3cecb9, 0x06c08df2, -0x633659e3, -0x7a76abb9, -0x30459c66, 0x0df09fd5, 0x5a845ae8 }, + { -0x5a4e4ebd, 0x1d06005c, 0x7fd1cda2, 0x6d4c6bb8, 0x53fcffe7, 0x6ef59676, -0x3e31e15b, 0x097c29e8 }, + { 0x5deb94ca, 0x4ce97dbe, -0x738f63b8, 0x38d0a438, -0x5e962f69, -0x3bc1312c, -0x081a783d, 0x0a1249ff } + }, +}, +{ + { + { 0x7354b610, 0x0b408d9e, 0x5ba85b6e, -0x7f94cdad, 0x4a58a207, -0x2419c5fd, -0x365e20d4, 0x173bd9dd }, + { 0x276d01c9, 0x12f0071b, -0x793b7390, -0x1847453b, 0x71d6fba9, 0x5308129b, 0x5a3db792, 0x5d88fbf9 }, + { -0x01a78d21, 0x2b500f1e, -0x2bc6e73f, 0x58d6582e, -0x3698c520, -0x1912d872, -0x4e615ce7, 0x06e1cd13 } + }, + { + { -0x61a4fcad, 0x472baf62, 0x278d0447, 0x3baa0b90, -0x69bc40d9, 0x0c785f46, -0x727c84ed, 0x7f3a6a1a }, + { 0x6f166f23, 0x40d0ad51, 0x1fab6abe, 0x118e3293, -0x5fb2f772, 0x3fe35e14, 0x26e16266, 0x30806035 }, + { 0x5d3d800b, -0x0819bbc7, -0x36fe120a, -0x6a572aab, 0x592c6339, 0x68cd7830, 0x2e51307e, 0x30d0fded } + }, + { + { 0x68b84750, -0x634b68e2, 0x6664bbcf, -0x5f6a8dd7, 0x72fa412b, 0x5c8de726, 0x51c589d9, 0x46150843 }, + { -0x0dedcc4d, -0x1fa6b2e6, -0x0f33b264, 0x1bdbe78e, -0x70b66589, 0x6965187f, 0x2c099868, 0x0a921420 }, + { -0x51465fd2, -0x436fe640, 0x16034cae, 0x55c7110d, 0x659932ec, 0x0e6df501, -0x6a35a202, 0x3bca0d28 } + }, + { + { -0x6133fe41, -0x6397714a, -0x59bb7691, -0x0f437c53, 0x5f7a9fe2, -0x35d26aa1, -0x720d7dbf, 0x4ea8b403 }, + { 0x3c5d62a4, 0x40f031bc, -0x300f85a0, 0x19fc8b3e, 0x130fb545, -0x67e7c25e, -0x5170ec33, 0x5631dedd }, + { -0x0e352dfe, 0x2aed460a, -0x5b73117d, 0x46305305, 0x49f11a5f, -0x6ede88bb, 0x542ca463, 0x24ce0930 } + }, + { + { -0x020cf47b, 0x3fcfa155, 0x36372ea4, -0x2d08e972, 0x6492f844, -0x4d1f9b22, 0x324f4280, 0x549928a7 }, + { -0x02f93efa, 0x1fe890f5, 0x5d8810f2, -0x4a3b97cb, 0x6e8caf3e, -0x7d87f702, -0x75f928b5, 0x41d4e3c2 }, + { 0x63ee1a2e, -0x0d91cd59, -0x2da00216, -0x516e1b49, -0x2e80b297, -0x43c42cc5, -0x3f230096, 0x491b66de } + }, + { + { -0x2f259b5f, 0x75f04a8e, 0x67e2284b, -0x12ddd351, 0x1f7b7ba4, -0x7dcb5c87, -0x48fe7499, 0x4cf6b8b0 }, + { -0x3815cd59, -0x670a4ec3, 0x7e16db98, -0x1c2a0734, -0x340726b9, -0x53f540ae, -0x37a11b54, 0x08f338d0 }, + { -0x66e58c43, -0x3c7c57df, -0x20cdf386, -0x54d843ff, -0x7b888f9d, -0x3ec2cce5, -0x14f87567, 0x530d4a82 } + }, + { + { 0x6c9abf9e, 0x6d697345, 0x4900a880, 0x257fb2fc, -0x373047b0, 0x2bacf412, 0x0cbfbd5b, 0x0db3e7e0 }, + { -0x1e06b7db, 0x004c3630, -0x7354aca6, 0x7e2d7826, -0x337b0075, -0x38b7dcdd, 0x101770b9, 0x65ea753f }, + { -0x1df69c9d, 0x3d66fc3e, 0x61b5cb6b, -0x7e29d381, 0x13443b1a, 0x0fbe0442, 0x21e1a1db, 0x02a4ec19 } + }, + { + { -0x0e3086a1, -0x0a379e9e, 0x26ee57f2, 0x118c8619, 0x1c063578, 0x17212485, -0x13f98031, 0x36d12b5d }, + { 0x3b24b8a2, 0x5ce6259a, 0x45afa0b8, -0x47a88534, -0x745f8fc9, -0x33341918, 0x127809bf, 0x3d143c51 }, + { 0x79154557, 0x126d2791, -0x0387c5f6, -0x2a1b70a4, -0x20e86454, 0x36bdb6e8, 0x5ba82859, 0x2ef51788 } + }, +}, +{ + { + { 0x7c6da1e9, 0x1ea43683, 0x1fb9bdbe, -0x063e7651, -0x31a22eab, 0x303001fc, -0x43a841ae, 0x28a7c99e }, + { -0x2ee1f2b6, -0x7742bc74, 0x43ccf308, 0x30cb610d, -0x6e6c8434, -0x1f65f1c9, 0x25b1720c, 0x4559135b }, + { -0x172e6163, -0x47026c67, -0x69dbdc01, -0x6f7e6e35, 0x47c742a3, -0x4d46b729, -0x2804bb3c, 0x37f33226 } + }, + { + { -0x37de4ee3, 0x33912553, 0x41e301df, 0x66ed42c2, 0x104222fd, 0x066fcc11, -0x3e6de971, 0x307a3b41 }, + { -0x4aa091f8, 0x0dae8767, 0x5b203a02, 0x4a43b3b3, -0x7f507387, -0x1c8da592, 0x705fa7a3, 0x0f7a7fd1 }, + { 0x6eb55ce0, -0x7114a2f9, -0x55f26da6, 0x2fc536bf, -0x23493918, -0x417e7cf1, -0x7d8450ae, 0x556c7045 } + }, + { + { 0x2bf44406, -0x46b46ffe, -0x006f4acc, -0x542bdc82, -0x050792c6, 0x7600a960, -0x3dcdd11d, 0x2f45abda }, + { 0x02e9d8b7, -0x71d4ae8d, 0x248714e8, -0x1c1add97, 0x4ca960b5, -0x42b04289, -0x3a135257, 0x6f4b4199 }, + { -0x37107596, 0x61af4912, 0x43fb6e5e, -0x1a705b02, 0x6fd427cf, -0x4a5033a3, 0x1e1e11eb, 0x6a539328 } + }, + { + { 0x149443cf, 0x0fff04fe, -0x79a32229, 0x53cac6d9, 0x531ed1b7, 0x31385b03, -0x532efc63, 0x5846a27c }, + { -0x5a2e1177, -0x0c25aec7, -0x006c9678, -0x7ebaba84, 0x00e188c4, 0x3f622fed, -0x2474a5c3, 0x0f513815 }, + { 0x1eb08717, 0x4ff5cdac, -0x6f0d1644, 0x67e8b295, 0x237afa99, 0x44093b5e, -0x78f7474e, 0x0d414bed } + }, + { + { 0x294ac9e8, -0x7e77956e, -0x2aaab842, 0x23162b45, 0x03715983, -0x6b3043bc, 0x134bc401, 0x50eb8fdb }, + { -0x02f18a0a, -0x30497d9b, -0x446f18f9, -0x1ba4c1d8, -0x6006d386, 0x7242a8de, -0x6ccdfd23, 0x685b3201 }, + { -0x294ccf33, -0x3f48c13a, 0x132faff1, -0x7b1bb7f9, -0x3b5a211f, 0x732b7352, -0x55832d2e, 0x5d7c7cf1 } + }, + { + { -0x648c5a9e, 0x33d1013e, 0x48ec26e1, -0x6da310a9, -0x22b97fa8, -0x580319ec, 0x1e9aa438, 0x78b0fad4 }, + { 0x7a4aafa2, -0x50c4b941, 0x4d40d411, -0x4878fa14, -0x3583ea1d, 0x114f0c6a, -0x56b762b3, 0x3f364faa }, + { -0x12fa4b78, -0x40a95bcf, -0x63b6a382, -0x5acc1994, -0x780c9ae6, -0x179ad451, 0x59d66c33, 0x02418000 } + }, + { + { -0x30c715ff, 0x28350c7d, -0x4d6e854a, 0x7c6cdbc0, -0x7a8f7d09, -0x53183042, -0x5d265e20, 0x4d2845ab }, + { -0x5c85a41c, -0x314f8802, -0x1a5a1149, -0x249bd0fe, 0x471270b8, -0x3d192f3b, 0x38e4529c, 0x4771b655 }, + { 0x447070de, -0x44ac8020, 0x6dd557df, -0x3458bbbd, 0x3600dbcb, -0x2c4a5cb9, -0x06002808, 0x4aeabbe6 } + }, + { + { -0x3b56370e, 0x6a2134bc, -0x7531d1c9, -0x040702e4, -0x66ee5f46, 0x000ae304, 0x6bc89b9e, 0x046e3a61 }, + { 0x40d8f78c, 0x4630119e, 0x3c710e11, -0x5fe5643b, -0x76ef2287, 0x486d2b25, -0x24fcdb1b, 0x1e6c47b3 }, + { -0x0fc6f942, 0x14e65442, -0x1c9d41d6, 0x4a019d54, -0x723dcf39, 0x68ccdfec, -0x509479e4, 0x7cfb7e3f } + }, +}, +{ + { + { 0x305b2f51, -0x69114005, -0x776a6948, -0x2c06c753, 0x46d5dd25, -0x0f0ad239, -0x44c5ff6b, 0x57968290 }, + { -0x73a75124, 0x4637974e, -0x540fbe5c, -0x4610dd05, -0x167f8e76, -0x1e7a26aa, -0x4ebc575a, 0x2f1b78fa }, + { 0x0a20e101, -0x08e547bd, 0x24f0ec47, -0x0c6c9a73, 0x6ee2eed1, -0x308af658, -0x23d55c1f, 0x7dc43e35 } + }, + { + { 0x273e9718, 0x5a782a5c, 0x5e4efd94, 0x3576c699, 0x1f237d3e, 0x0f2ed805, -0x7d2af567, 0x044fb81d }, + { -0x7782263d, -0x7a69999b, 0x4bb05355, -0x36f064cf, -0x10df864f, -0x391f7208, 0x758cc12f, 0x7ef72016 }, + { -0x56f81c27, -0x3e20e73b, -0x31b39ca7, 0x57b3371d, -0x4dfe44b7, -0x358fbacc, -0x63cf22d2, 0x7f79823f } + }, + { + { 0x68f587ba, 0x6a9c1ff0, 0x0050c8de, 0x0827894e, 0x7ded5be7, 0x3cbf9955, 0x1c06d6f0, 0x64a9b043 }, + { -0x5c4aec18, -0x7ccb2dc7, -0x46e05728, -0x3ec98f2c, -0x0a6f42cd, 0x12b54136, -0x287b264c, 0x0a4e0373 }, + { 0x5b7d2919, 0x2eb3d6a1, -0x2ac57dcb, -0x4f4b0960, -0x765ba2b9, 0x7156ce43, -0x31e7cb94, 0x071a7d0a } + }, + { + { 0x20e14431, -0x33f3caae, 0x09b15141, 0x0d659507, 0x209d5f36, -0x650a9de5, 0x617755d3, 0x7c69bcf7 }, + { -0x377845f5, -0x2cf8d256, -0x405a9d12, 0x01262905, -0x3f108975, -0x30abcffe, 0x46ea7e9c, 0x2c3bcc71 }, + { 0x04e8295f, 0x07f0d7eb, 0x2f50f37d, 0x10db1825, 0x171798d7, -0x16ae565d, 0x22aca51d, 0x6f5a9a73 } + }, + { + { -0x5c26bb42, -0x18d62b15, -0x7f875062, -0x7261f6c0, 0x47869c03, 0x4525567a, -0x1172c4dc, 0x02ab9680 }, + { 0x2f41c6c5, -0x745efff4, 0x0cfefb9b, -0x3b60863f, 0x3cc51c9f, 0x4efa4770, -0x1eb85036, 0x494e21a2 }, + { -0x221af266, -0x105b757b, 0x0fb9a249, 0x219a224e, -0x26e10927, -0x05f6e0e3, -0x15b944cc, 0x6b5d76cb } + }, + { + { 0x1e782522, -0x1f06bee9, 0x036936d3, -0x0e19518c, -0x2f0338ba, 0x408b3ea2, 0x03dd313e, 0x16fb869c }, + { -0x13f3266c, -0x77a8aa94, 0x5cd01dba, 0x6472dc6f, -0x70bd4b89, -0x50fe96ec, -0x7ad88cac, 0x0ae333f6 }, + { 0x33b60962, 0x288e1997, -0x27541ecd, 0x24fc72b4, 0x0991d03e, 0x4811f7ed, -0x708f2f8b, 0x3f81e38b } + }, + { + { 0x5f17c824, 0x0adb7f35, -0x28bd665c, 0x74b923c3, -0x34071509, -0x2a83c175, 0x4cdedc3d, 0x0ad3e2d3 }, + { 0x7ed9affe, 0x7f910fcc, 0x2465874b, 0x545cb8a1, 0x4b0c4704, -0x57c6812e, 0x04f50993, 0x50510fc1 }, + { 0x336e249d, 0x6f0c0fc5, -0x3cce3027, 0x745ede19, 0x09eefe1c, -0x0d290300, -0x0f05e142, 0x127c158b } + }, + { + { -0x51ae468c, -0x215d703c, 0x744dfe96, 0x1d9973d3, -0x78c7b758, 0x6240680b, -0x2e98206b, 0x4ed82479 }, + { 0x2e9879a2, -0x09e683be, 0x52ca3647, -0x5bb5222c, 0x4b4eaccb, -0x64bec03f, 0x07ef4f68, 0x354ef87d }, + { 0x60c5d975, -0x011c4ade, -0x14be4f48, 0x50352efc, -0x56099ac4, -0x77f753d0, 0x0539236d, 0x302d92d2 } + }, +}, +{ + { + { 0x0df53c30, -0x6a847475, -0x719f0f68, 0x2a1c770a, 0x345796de, -0x44385990, -0x6f366437, 0x22a48f9a }, + { -0x34c10484, 0x4c59023f, -0x39c3d56c, 0x6c2fcb99, -0x3c381f7c, -0x45be6f1e, -0x5ae78b27, 0x0e545dae }, + { -0x72c053a8, 0x6b7dc0dc, -0x191bd403, 0x5497cd6c, -0x0bff2cfb, 0x542f7d1b, 0x048d9136, 0x4159f47f } + }, + { + { -0x442db7c7, 0x748515a8, -0x504fd4ab, 0x77128347, 0x49a2a17f, 0x50ba2ac6, 0x3ad730f1, 0x06052551 }, + { 0x39e31e32, 0x20ad6608, -0x7bfa41b0, -0x07e1e42b, -0x0b254397, -0x07f9bfaa, -0x318e468b, 0x14d23dd4 }, + { -0x755d807e, -0x0dc671f7, -0x765e4fdc, 0x6d7982bb, 0x214dd24c, -0x0596bf7c, -0x5cdcfe3d, 0x71ab966f } + }, + { + { 0x02809955, -0x4ef775f9, 0x0b43c391, 0x43b273ea, -0x01f97913, -0x35649852, -0x7cca0b13, 0x605eecbf }, + { 0x4ded02fc, 0x2dcbd8e3, 0x596f22aa, 0x1151f3ec, 0x4e0328da, -0x435daabd, -0x6dbee4de, 0x35768fbe }, + { 0x6c340431, -0x7cdff59b, -0x711a63d1, -0x60328e99, 0x71300f8a, 0x75d4613f, 0x60f542f9, 0x7a912faf } + }, + { + { -0x05d2aa69, 0x253f4f8d, 0x5477130c, 0x25e49c40, -0x6694eefe, 0x00c052e5, 0x33bb6c4a, 0x33cb966e }, + { 0x5edc1a43, -0x4dfba7a2, 0x5897c73c, -0x60f1e912, 0x4e70483c, 0x5b82c0ae, 0x2bddf9be, 0x624a170e }, + { 0x7f116909, 0x59702804, 0x1e564467, -0x7d753be4, -0x19de8c79, 0x70417dbd, -0x0453bc7c, 0x721627ae } + }, + { + { 0x410b2f22, -0x02cf6844, -0x4a3057bc, -0x0e5fa259, -0x10a8358c, 0x61289a1d, -0x447de6fe, 0x245ea199 }, + { -0x78c9522b, -0x682fc43d, -0x3acd4ed0, 0x2f1422af, 0x7101bbc4, 0x3aa68a05, -0x18b06059, 0x4c946cf7 }, + { 0x78d477f8, -0x51235997, 0x29117fe1, 0x1898ba3c, 0x720cbd58, -0x308c067d, -0x474a9caf, 0x67da12e6 } + }, + { + { -0x7137cf74, 0x2b7ef3d3, 0x71eb94ab, -0x7d702814, -0x3af9d543, -0x7f83c4ca, 0x31a94141, 0x0cb64cb8 }, + { -0x4b4291f9, 0x7067e187, -0x382e018c, 0x6e8f0203, 0x38c85a30, -0x6c3955d1, 0x3d75a78a, 0x76297d1f }, + { 0x534c6378, 0x3030fc33, -0x1abe179f, -0x469ca3a4, -0x264d38d8, 0x15d9a9be, -0x0c88a235, 0x49233ea3 } + }, + { + { 0x1c9f249b, 0x7b3985fe, -0x5edccd6d, 0x4fd6b2d5, 0x1adf4d62, -0x314cba6c, 0x542de50c, 0x6987ff6f }, + { -0x724003c6, 0x629398fa, -0x2ab24bab, -0x1ed01ad3, -0x250dad6b, -0x0c41ee21, -0x31a184af, 0x628b140d }, + { -0x707c8ac4, 0x47e24142, -0x79950669, 0x6317bebc, 0x3d1a9829, -0x2544a4bd, 0x5287fb2d, 0x074d8d24 } + }, + { + { -0x3f1ceb78, 0x481875c6, -0x1ddfcb4c, 0x219429b2, 0x31283b65, 0x7223c98a, 0x342277f9, 0x3420d60b }, + { 0x440bfc31, -0x7cc82633, -0x50ce7029, 0x729d2ca1, 0x772c2070, -0x5fbf5b5c, 0x3a7349be, 0x46002ef0 }, + { -0x50019a09, -0x055dc522, 0x5be0764c, 0x78261ed4, 0x2f164403, 0x441c0a1e, 0x7a87d395, 0x5aea8e56 } + }, +}, +{ + { + { -0x1b1f0e89, 0x2dbc6fb6, -0x5b42956d, 0x04e1bf29, 0x787af6e8, 0x5e1966d4, -0x4bd92fa0, 0x0edc5f5e }, + { -0x435bd7c3, 0x7813c1a2, -0x5e79c227, -0x129d0f6f, -0x3d97057a, -0x51384348, 0x6f1cae4c, 0x10e5d3b7 }, + { 0x53da8e67, 0x5453bfd6, 0x24a9f641, -0x1623e114, 0x03578a23, -0x4078d9c5, 0x361cba72, 0x45b46c51 } + }, + { + { -0x75801c1c, -0x3162b223, 0x76620e30, -0x54ec9baa, -0x4cf166a8, 0x4b594f7b, 0x321229df, 0x5c1c0aef }, + { 0x314f7fa1, -0x56bfd541, -0x71730bb0, -0x1da80e24, 0x23a8be84, 0x1dbbd54b, 0x6dcb713b, 0x2177bfa3 }, + { -0x05862471, 0x37081bbc, -0x3da0a64d, 0x6048811e, -0x637cdb79, 0x087a7665, 0x7d8ab5bb, 0x4ae61938 } + }, + { + { -0x67a4047d, 0x61117e44, 0x71963136, -0x031fb9d6, -0x2bda6fb5, -0x7c53cbb8, 0x5ba43d64, 0x75685abe }, + { 0x5344a32e, -0x72240956, -0x4be4bf88, 0x7d88eab4, 0x4a130d60, 0x5eb0eb97, 0x17bf3e03, 0x1a00d91b }, + { -0x149e0d4e, 0x6e960933, -0x3600b6ae, 0x543d0fa8, 0x7af66569, -0x208d8af0, 0x23b0e6aa, 0x135529b6 } + }, + { + { -0x1dd17c02, -0x0a38e944, -0x17f67a3f, -0x4bd414e7, 0x14254aae, -0x136259c9, 0x1590a613, 0x5972ea05 }, + { -0x522e2ae8, 0x18f0dbd7, -0x303ee0ef, -0x68608778, 0x7114759b, -0x78cd1e10, 0x65ca3a01, 0x79b5b81a }, + { -0x237087ef, 0x0fd4ac20, -0x53b2b058, -0x65652d6c, -0x4cc9fbcc, -0x3fe4d29c, -0x6fa0c425, 0x4f7e9c95 } + }, + { + { 0x355299fe, 0x71c8443d, -0x24141529, -0x7432c4e4, -0x0e5b6b9a, -0x7f6db662, -0x5ebb5238, 0x1942eec4 }, + { 0x5781302e, 0x62674bbc, -0x765223f1, -0x27adf0c7, 0x53fbd9c6, -0x73d66652, 0x2e638e4c, 0x31993ad9 }, + { -0x51dcb66e, 0x7dac5319, 0x0cea3e92, 0x2c1b3d91, 0x253c1122, 0x553ce494, 0x4ef9ca75, 0x2a0a6531 } + }, + { + { 0x3c1c793a, -0x30c9e533, 0x5a35bc3b, 0x2f9ebcac, -0x57325955, 0x60e860e9, 0x6dea1a13, 0x055dc39b }, + { -0x0806d83e, 0x2db7937f, 0x17d0a635, -0x248be0fa, 0x1155af76, 0x5982f3a2, 0x647c2ded, 0x4cf6e218 }, + { -0x3d72a44a, -0x4ee6dd84, 0x774dffab, 0x07e24ebc, -0x1b5cd377, -0x57c38732, 0x10aa24b6, 0x121a3077 } + }, + { + { -0x388b7c37, -0x29a68ec2, -0x47d46951, -0x77401f89, 0x1097bcd3, 0x289e2823, 0x6ced3a9b, 0x527bb94a }, + { -0x60fcb569, -0x1b24a2a2, 0x3034bc2d, -0x1eac03f7, -0x6aae2c4f, 0x46054691, 0x7a40e52d, 0x333fc76c }, + { -0x66a4b7d2, 0x563d992a, 0x6e383801, 0x3405d07c, 0x2f64d8e5, 0x485035de, 0x20a7a9f7, 0x6b89069b } + }, + { + { -0x4a382489, 0x4082fa8c, -0x38cb3eab, 0x068686f8, -0x09185a82, 0x29e6c8d9, -0x589c6431, 0x0473d308 }, + { 0x6270220d, -0x7ed55fbf, -0x06dba4b2, -0x66a57606, 0x5072ef05, -0x00523b32, -0x558c148d, 0x23bc2103 }, + { 0x03589e05, -0x351186da, 0x46dcc492, 0x2b4b4212, -0x19fe56b1, 0x02a1ef74, -0x21fbcbe6, 0x102f73bf } + }, +}, +{ + { + { -0x6c5c9db9, 0x358ecba2, -0x4d97029b, -0x5070679e, 0x68a01c89, 0x412f7e99, -0x328abadc, 0x5786f312 }, + { 0x7ec20d3e, -0x4a5d2af4, -0x5f368d9d, -0x39b42292, -0x3e008cb3, 0x56e89052, 0x2b2ffaba, 0x4929c6f7 }, + { -0x35ebfcd4, 0x337788ff, 0x447f1ee3, -0x0c6defd8, 0x231bccad, -0x74ebf8e1, -0x0dcbb87d, 0x4c817b4b } + }, + { + { -0x5bf4bb7c, 0x413ba057, 0x4f5f6a43, -0x45b3d1e6, -0x511e29e4, 0x614ba0a5, -0x74fa23ad, 0x78a1531a }, + { 0x2871b96e, 0x0ff85385, 0x60c3f1bb, -0x1ec16055, 0x25344402, -0x1102a6ad, 0x75b7744b, 0x0a37c370 }, + { 0x3ad0562b, 0x6cbdf170, -0x36dade5d, -0x7130b7d0, -0x027bdb19, -0x25142cfd, 0x2e5ec56f, 0x72ad82a4 } + }, + { + { 0x67024bc3, -0x3c976c6f, 0x49502fda, -0x71962e93, -0x1ba0b4d7, -0x030d13c4, -0x5c4b343c, 0x065f669e }, + { -0x45049a0a, 0x3f9e8e35, -0x0d8d6c5f, 0x39d69ec8, -0x73095c30, 0x6cb8cd95, 0x73adae6d, 0x17347781 }, + { 0x5532db4d, -0x75ff5139, 0x43e31bb1, -0x47965b1c, -0x2c580aeb, 0x4a0f8552, 0x303d7c08, 0x19adeb7c } + }, + { + { 0x43c31794, -0x62fa4583, -0x6ccddada, 0x2470c8ff, 0x16197438, -0x7cdc2138, -0x7ea964ad, 0x28527098 }, + { 0x53ead9a3, -0x38df349f, 0x512b636e, 0x55b2c97f, -0x2bfd6f4f, -0x4e1ca4a1, 0x3b530ee2, 0x2fd9ccf1 }, + { 0x47f796b8, 0x07bd475b, 0x542c8f54, -0x2d384fed, 0x3b24f87e, 0x2dbd23f4, 0x7b0901d6, 0x6551afd7 } + }, + { + { -0x5e2a3654, 0x68a24ce3, 0x10ff6461, -0x44885cc3, 0x25d3166e, 0x0f86ce44, 0x50b9623b, 0x56507c09 }, + { 0x54aac27f, 0x4546baaf, -0x4d5ba5d8, -0x09099014, 0x562bcfe8, 0x582d1b5b, -0x6df087a1, 0x44b123f3 }, + { -0x2e8ec19d, 0x1206f0b7, 0x15bafc74, 0x353fe3d9, 0x0ad9d94d, 0x194ceb97, -0x062fc52d, 0x62fadd7c } + }, + { + { -0x1831ba6c, 0x3cd7bc61, -0x4822d982, -0x3294ca57, 0x4366ef27, -0x5f7f5438, 0x59c79711, 0x6ec7c46f }, + { 0x5598a074, -0x394a6985, -0x71b6c1db, 0x5efe91ce, 0x49280888, -0x2b48d3bb, -0x5d98bf3e, 0x20ef1149 }, + { 0x6f09a8a2, 0x2f07ad63, 0x24205e7d, -0x79681932, -0x11ca5ec7, -0x3f5103fb, -0x4a062769, 0x15e80958 } + }, + { + { 0x5bb061c4, 0x4dd1ed35, -0x6be3f900, 0x42dc0cef, -0x0279cbf2, 0x61305dc1, 0x0e55a443, 0x56b2cc93 }, + { 0x0c3e235b, 0x25a5ef7d, -0x41ecb119, 0x6c39c17f, 0x2dc5c327, -0x388b1ecc, -0x6dfde0c7, 0x021354b8 }, + { -0x59403a5e, 0x1df79da6, -0x6021bc97, 0x02f3a274, -0x325c6f59, -0x4cdc260e, -0x788b2c9d, 0x7be0847b } + }, + { + { 0x5307fa11, 0x1466f5af, -0x1293f50e, -0x7e803383, -0x3c5b5c05, 0x0a6de44e, -0x436d82f5, 0x74071475 }, + { -0x74c0aa3d, -0x736633a6, 0x3fded2a0, 0x0611d725, 0x36b70a36, -0x12d66a01, -0x2875d9e7, 0x1f699a54 }, + { 0x73e7ea8a, -0x188d6d0d, -0x34fba5cf, 0x296537d2, -0x2cd8b022, 0x1bd0653e, 0x76bd2966, 0x2f9a2c44 } + }, +}, +{ + { + { -0x4aaee366, -0x5d4b2520, 0x2bffff06, 0x7ac86029, -0x0aafbdcc, -0x67e0c8a3, -0x25b15ed3, 0x3f6bd725 }, + { 0x7f5745c6, -0x14e74655, 0x5787c690, 0x023a8aee, 0x2df7afa9, -0x48d8ed26, -0x15a3fec3, 0x36597d25 }, + { 0x106058ac, 0x734d8d7b, 0x6fc6905f, -0x26bfa862, -0x6dfd6cd3, 0x6466f8f9, -0x259f2930, 0x7b7ecc19 } + }, + { + { -0x58830565, 0x6dae4a51, -0x185c79b0, -0x7dd9c9ac, -0x70d27d25, 0x09bbffcd, 0x1bf5caba, 0x03bedc66 }, + { 0x695c690d, 0x78c2373c, 0x0642906e, -0x22dad19a, 0x4ae12bd2, -0x6ae2bbbc, 0x01743956, 0x4235ad76 }, + { 0x078975f5, 0x6258cb0d, -0x6e760d68, 0x49294254, -0x1d1c911c, -0x5f354bdd, -0x320f995f, 0x0e7ce2b0 } + }, + { + { -0x26b48f07, -0x01590121, -0x3e0345d3, -0x0ecf3faf, 0x7f2fab89, 0x4882d47e, -0x7513114b, 0x61525613 }, + { -0x3b737a5d, -0x3b6b9bc6, 0x3c6139ad, -0x02c9e20c, 0x3ae94d48, 0x09db17dd, -0x704b98b6, 0x666e0a5d }, + { 0x4870cb0d, 0x2abbf64e, -0x55ba7495, -0x329a4310, 0x75e8985d, -0x6541b146, -0x2aeb211c, 0x7f0bc810 } + }, + { + { 0x737213a0, -0x7c536253, 0x2ef72e98, -0x60090746, 0x43ec6957, 0x311e2edd, -0x213a548b, 0x1d3a907d }, + { 0x26f4136f, -0x46ff945c, 0x57e03035, -0x7298c962, 0x4f463c28, -0x34372027, -0x0711240b, 0x0d1f8dbc }, + { 0x3ed081dc, -0x45e96ccf, -0x7ae4cb80, 0x29329fad, 0x030321cb, 0x0128013c, -0x5ce4021d, 0x00011b44 } + }, + { + { 0x6a0aa75c, 0x16561f69, 0x5852bd6a, -0x3e408da4, -0x65869953, 0x11a8dd7f, -0x2d7aefda, 0x63d988a2 }, + { 0x3fc66c0c, 0x3fdfa06c, 0x4dd60dd2, 0x5d40e38e, 0x268e4d71, 0x7ae38b38, 0x6e8357e1, 0x3ac48d91 }, + { -0x5042dcd2, 0x00120753, -0x0227097d, -0x16d43148, -0x7b18d46f, -0x07e9964d, 0x2368a066, 0x33fad52b } + }, + { + { -0x3bdd3018, -0x72d33730, 0x05a13acb, 0x072b4f7b, -0x13095a91, -0x5c01491a, -0x46f58e1e, 0x3cc355cc }, + { -0x3a1be1ea, 0x540649c6, 0x333f7735, 0x0af86430, -0x0cfa18ba, -0x4d53032e, -0x5da92359, 0x16c0f429 }, + { -0x6fc16ecf, -0x16496bbd, 0x7a5637ce, -0x475b6b35, -0x45456dbc, -0x37832e5c, 0x6bae7568, 0x631eaf42 } + }, + { + { -0x5c8ff218, 0x47d975b9, -0x1d07faae, 0x7280c5fb, 0x32e45de1, 0x53658f27, 0x665f80b5, 0x431f2c7f }, + { -0x25990161, -0x4c16fbf0, 0x6c16e5a6, -0x7a22b4ae, 0x1ef9bf83, -0x43c2689f, 0x1ea919b5, 0x5599648b }, + { -0x7a7084e7, -0x29fd9cbc, -0x5e15aeb6, 0x14ab352f, 0x2090a9d7, -0x76ffbbe6, -0x6edac4da, 0x7b04715f } + }, + { + { -0x3b19453a, -0x4c893d80, 0x6d1d9b0b, -0x68f12c23, 0x450bf944, -0x4f656aa8, 0x57cde223, 0x48d0acfa }, + { -0x530951bd, -0x7c1242d8, 0x7d5c7ab4, -0x79ca8375, -0x4814d3bc, -0x3fbfb897, -0x3d09a7c1, 0x59b37bf5 }, + { 0x7dabe671, -0x49f0d91c, 0x622f3a37, -0x0e2e5e69, -0x1669fc6c, 0x4208ce7e, 0x336d3bdb, 0x16234191 } + }, +}, +{ + { + { 0x3d578bbe, -0x7ad22e03, -0x3cd79ef8, 0x2b65ce72, -0x1531dd8d, 0x658c07f4, -0x13c754c0, 0x0933f804 }, + { 0x33a63aef, -0x0e651539, 0x4442454e, 0x2c7fba5d, 0x4795e441, 0x5da87aa0, -0x5b1f4f0b, 0x413051e1 }, + { -0x72b69b8a, -0x58549687, -0x034a5438, -0x7ede5522, 0x7b539472, -0x5a23ed11, 0x5e45351a, 0x07fd4706 } + }, + { + { -0x6517183d, 0x30421155, -0x6bb77d5b, -0x0d7e4dd7, 0x378250e4, -0x75ec53d2, 0x54ba48f4, 0x014afa09 }, + { 0x258d2bcd, -0x37a7c3c3, -0x509f48c1, 0x17029a4d, 0x416a3781, -0x05f0362a, 0x38b3fb23, 0x1c1e5fba }, + { 0x1bb3666c, -0x34ce6900, 0x4bffecb9, 0x33006052, 0x1a88233c, 0x29371199, 0x3d4ed364, 0x29188436 } + }, + { + { -0x43e54915, -0x0462c83d, 0x4d57a240, 0x02be1453, -0x075a1e0a, -0x0b28cbeb, 0x0ccc8188, 0x5964f430 }, + { -0x23b45406, 0x033c6805, 0x5596ecc1, 0x2c15bf5e, -0x4a64e2c5, 0x1bc70624, -0x5e60f13b, 0x3ede9850 }, + { 0x2d096800, -0x1bb5dceb, 0x70866996, 0x5c08c559, 0x46affb6e, -0x20d249f6, -0x07a90277, 0x579155c1 } + }, + { + { 0x0817e7a6, -0x4a0e949d, 0x3c351026, -0x7f7396dd, 0x54cef201, 0x324a983b, 0x4a485345, 0x53c09208 }, + { 0x12e0c9ef, -0x69cdb123, -0x0dbdfd69, 0x468b878d, -0x5b0a8c42, 0x199a3776, -0x716e16d6, 0x1e7fbcf1 }, + { -0x0e345041, -0x2d2beb7f, 0x716174e5, 0x231d2db6, -0x1d5aa368, 0x0b7d7656, 0x2aa495f6, 0x3e955cd8 } + }, + { + { 0x61bb3a3f, -0x54c60c11, 0x2eb9193e, -0x714bff9b, 0x38c11f74, -0x4a219134, 0x26f3c49f, 0x654d7e96 }, + { 0x3ed15433, -0x1b70aca2, 0x0d7270a3, -0x2f8a96d6, -0x55219c79, 0x40fbd21d, -0x30bb6a0b, 0x14264887 }, + { 0x5c7d2ceb, -0x1a9b3023, -0x28c83347, -0x7d115022, -0x2e064f55, 0x6107db62, -0x4bca7245, 0x0b6baac3 } + }, + { + { 0x3700a93b, 0x204abad6, -0x25886c8d, -0x41ffdc2d, 0x633ab709, -0x27a0fcba, -0x6f7dfbee, 0x00496dc4 }, + { -0x79dd0168, 0x7ae62bcb, -0x31476e51, 0x47762256, -0x0d1bf94c, 0x1a5a92bc, -0x7b1beaff, 0x7d294017 }, + { -0x3d819ca0, 0x1c74b88d, -0x72eb7af4, 0x07485426, 0x3e0dcb30, -0x5eba0485, 0x43803b23, 0x10843f1b } + }, + { + { -0x1cdb9765, -0x2a9098d3, -0x4c6b567f, -0x2e257513, -0x6e973013, -0x2284a702, 0x4d56c1e8, 0x7ce246cd }, + { 0x376276dd, -0x3a06fbab, -0x289ba327, -0x31a6ea73, 0x1d366b39, -0x6d09a2af, 0x526996c4, 0x11574b6e }, + { 0x7f80be53, -0x470bcf72, 0x34a9d397, 0x5f3cb8cb, 0x33cc2b2c, 0x18a961bd, 0x3a9af671, 0x710045fb } + }, + { + { 0x059d699e, -0x5fc0379e, -0x659e6197, 0x2370cfa1, 0x2f823deb, -0x3b01c4ee, -0x580f7bb2, 0x1d1b056f }, + { 0x101b95eb, 0x73f93d36, 0x4f6f4486, -0x0510cc87, -0x70ea1a9e, 0x5651735f, 0x58b40da1, 0x7fa3f190 }, + { -0x1a9409e1, 0x1bc64631, 0x6e5382a3, -0x2c8654f0, 0x0540168d, 0x4d58c57e, -0x7bbd271c, 0x56625662 } + }, +}, +{ + { + { 0x1ff38640, -0x22b6632a, 0x063625a0, 0x29cd9bc3, 0x3dd73dc3, 0x51e2d802, 0x203b9231, 0x4a25707a }, + { -0x09d9800a, -0x461b6622, 0x742c0843, 0x7772ca7b, -0x165b0d4f, 0x23a0153f, -0x2a2faffa, 0x2cdfdfec }, + { 0x53f6ed6a, 0x2ab7668a, 0x1dd170a1, 0x30424258, 0x3ae20161, 0x4000144c, 0x248e49fc, 0x5721896d } + }, + { + { -0x5e2f25b2, 0x285d5091, -0x4a01c1f8, 0x4baa6fa7, -0x1e6c6c4d, 0x63e5177c, -0x3b4fcf03, 0x03c935af }, + { -0x02e7e452, 0x0b6e5517, 0x2bb963b4, -0x6fdd9d61, 0x32064625, 0x5509bce9, -0x09c3ec26, 0x578edd74 }, + { 0x492b0c3d, -0x668d893a, -0x201dfa04, 0x47ccc2c4, -0x229dc5c4, -0x232d647c, 0x0288c7a2, 0x3ec2ab59 } + }, + { + { -0x51cd2e35, -0x58dec5f7, 0x40f5c2d5, 0x0f2b87df, -0x17e154d7, 0x0baea4c6, 0x6adbac5e, 0x0e1bf66c }, + { -0x1b278447, -0x5e5f2d85, 0x61391aed, -0x5674b215, 0x73cb9b83, -0x665f2230, 0x200fcace, 0x2dd5c25a }, + { 0x792c887e, -0x1d542a17, -0x346d92a3, 0x1a020018, -0x4551a0e2, -0x40459633, 0x5ae88f5f, 0x730548b3 } + }, + { + { -0x5e291ccc, -0x7fa4f6b5, 0x09353f19, -0x40c10e89, 0x0622702b, 0x423f06cb, -0x2787ba23, 0x585a2277 }, + { -0x34574712, -0x3bcaae5d, -0x4deea0ea, 0x65a26f1d, -0x5473c7b0, 0x760f4f52, 0x411db8ca, 0x3043443b }, + { 0x33d48962, -0x5e75a07e, -0x1387da81, 0x6698c4b5, 0x373e41ff, -0x5871905b, 0x50ef981f, 0x76562789 } + }, + { + { -0x15793063, -0x1e8f8c5d, 0x07155fdc, 0x3a8cfbb7, 0x31838a8e, 0x4853e7fc, -0x49ec09ea, 0x28bbf484 }, + { -0x2ae03740, 0x38c3cf59, 0x0506b6f2, -0x64122d03, -0x54a8f171, 0x26bf109f, -0x3e47b95a, 0x3f4160a8 }, + { 0x6f136c7c, -0x0d9ed0a4, -0x0922ee42, -0x50152ef9, 0x13de6f33, 0x527e9ad2, -0x7e7708a3, 0x1e79cb35 } + }, + { + { -0x0a1f7e7f, 0x77e953d8, 0x299dded9, -0x7b5af3bc, -0x79bada1b, -0x2393d2f4, 0x39d1f2f4, 0x478ab52d }, + { -0x11081c0f, 0x013436c3, -0x0161ef08, -0x7d749581, -0x43062104, 0x7ff908e5, 0x3a3b3831, 0x65d7951b }, + { -0x6dad2ea7, 0x66a6a4d3, -0x78e537f9, -0x1a221e44, -0x593e3691, -0x47d394c0, 0x1a212214, 0x16d87a41 } + }, + { + { -0x2ab1fa7d, -0x045b2a1e, 0x2ebd99fa, -0x1de05029, 0x6ee9778f, 0x497ac273, 0x7a5a6dde, 0x1f990b57 }, + { 0x42066215, -0x4c4281a6, 0x0c5a24c1, -0x78641c33, -0x29066b49, 0x57c05db1, 0x65f38ca6, 0x28f87c81 }, + { 0x1be8f7d6, -0x5ccbb153, -0x53158671, 0x7d1e50eb, 0x520de052, 0x77c6569e, 0x534d6d3e, 0x45882fe1 } + }, + { + { -0x6bc3901c, -0x275366d7, -0x5c7c6d5e, -0x4a060e9f, -0x4137650d, 0x2699db13, -0x1bfa0f8c, 0x7dcf843c }, + { 0x757983d6, 0x6669345d, 0x17aa11a6, 0x62b6ed11, -0x67a1ed71, 0x7ddd1857, -0x09d90923, 0x688fe5b8 }, + { 0x4a4732c0, 0x6c90d648, -0x35a9cd67, -0x2adebc03, -0x6ea2391f, -0x4c41d73d, 0x7327191b, 0x6739687e } + }, +}, +{ + { + { -0x363468e1, -0x731a5530, -0x602ab5d7, 0x1156aaa9, 0x15af9b78, 0x41f72470, 0x420f49aa, 0x1fe8cca8 }, + { 0x200814cf, -0x609a3a16, 0x69a31740, -0x7bfac91f, 0x25c8b4ad, -0x74f12ec7, -0x16c9c9e3, 0x0080dbaf }, + { 0x3c0cc82a, 0x72a1848f, -0x788361ac, 0x38c560c2, -0x31aabec0, 0x5004e228, 0x03429d71, 0x042418a1 } + }, + { + { 0x20816247, 0x58e84c6f, -0x1c90286d, -0x724d4d4a, 0x1d484d85, -0x688e7daa, -0x79cd5429, 0x0822024f }, + { -0x540c00a1, -0x766215af, 0x2fc2d8ba, -0x646c5799, -0x419142a4, 0x2c38cb97, -0x68d9c4a3, 0x114d5784 }, + { 0x6b1beca3, -0x4cfe4484, -0x3914ec8b, 0x55393f6d, -0x68491b15, -0x6ef2d7f0, -0x62b8615d, 0x1ad4548d } + }, + { + { 0x0fe9fed3, -0x5f901993, 0x1c587909, -0x578cc5c0, 0x0df98953, 0x30d14d80, -0x384cfda8, 0x41ce5876 }, + { 0x389a48fd, -0x32a58260, -0x6587c8e2, -0x4c705b56, 0x2cdb8e6c, -0x392689e5, -0x3681ebbd, 0x35cf51db }, + { -0x298f3fde, 0x59ac3bc5, -0x64ee6bfa, -0x151983f0, -0x4c87d026, -0x68674210, -0x02f8bf6e, 0x651e3201 } + }, + { + { 0x1efcae9e, -0x5a845b60, -0x23cf756c, 0x769f4bee, 0x3603cb2e, -0x2e0ef115, 0x7e441278, 0x4099ce5e }, + { -0x10cf3a31, -0x29c27b7d, 0x2361cc0c, 0x4cd4b496, -0x5b7bd954, -0x116f1b00, 0x18c14eeb, 0x0af51d7d }, + { -0x75aede17, 0x1ac98e4f, -0x2405d020, 0x7dae9544, -0x29bcf207, -0x7cdf55f3, 0x2c4a2fb5, 0x66728265 } + }, + { + { 0x2946db23, -0x52574920, 0x7b253ab7, 0x1c0ce51a, 0x66dd485b, -0x7bb737a6, -0x2f98a521, 0x7f1fc025 }, + { -0x27943655, -0x78b9de0c, 0x56fe6fea, -0x4ab38442, 0x7fadc22c, 0x077a2425, 0x19b90d39, 0x1ab53be4 }, + { 0x319ea6aa, -0x2711e4e8, 0x3a21f0da, 0x004d8808, -0x77c5b0b5, 0x3bd6aa1d, -0x202602ec, 0x4db9a3a6 } + }, + { + { -0x34488398, -0x26a4ff45, -0x6e0e87b7, -0x22437b96, -0x41d7264d, 0x7cf700ae, -0x7a2ce0c2, 0x5ce1285c }, + { -0x4663f8ab, -0x73184dc5, -0x3b0af086, 0x35c5d6ed, -0x1264af3d, 0x7e1e2ed2, -0x176cb25f, 0x36305f16 }, + { -0x674f4218, 0x31b6972d, -0x535921a5, 0x7d920706, -0x6f759a61, -0x198cef08, -0x1020fdcb, 0x50fac2a6 } + }, + { + { -0x090bb644, 0x295b1c86, 0x1f0ab4dd, 0x51b2e84a, -0x5571aae3, -0x3ffe34d0, 0x44f43662, 0x6a28d359 }, + { 0x5b880f5a, -0x0c2c560d, -0x24fc183e, -0x1213faf4, -0x060f4e5e, -0x576967e1, -0x53a1cb5c, 0x49a4ae2b }, + { 0x04a740e0, 0x28bb12ee, -0x64317e8c, 0x14313bbd, -0x173ef3c0, 0x72f5b5e4, 0x36adcd5b, 0x7cbfb199 } + }, + { + { -0x33c91920, -0x7186c586, 0x7d586eed, -0x0605485d, -0x451e0b1c, 0x3a4f9692, -0x00a0bb82, 0x1c14b03e }, + { 0x6b89792d, -0x5cee223e, -0x25aed99c, 0x1b30b4c6, -0x30eaf7a7, 0x0ca77b4c, 0x1b009408, 0x1de443df }, + { 0x14a85291, 0x19647bd1, 0x1034d3af, 0x57b76cb2, 0x0f9d6dfa, 0x6329db44, 0x6a571493, 0x5ef43e58 } + }, +}, +{ + { + { -0x37f3e540, -0x59923363, 0x1b38a436, -0x685fa30c, -0x6a24283a, -0x58140c42, -0x72818255, 0x7da0b8f6 }, + { 0x385675a6, -0x1087dfec, -0x55025618, -0x5d9b60d0, 0x5cdfa8cb, 0x4cd1eb50, 0x1d4dc0b3, 0x46115aba }, + { -0x3c4a258a, -0x2bf0e6ad, 0x21119e9b, 0x1dac6f73, -0x014da6a0, 0x03cc6021, -0x7c98b4b5, 0x5a5f887e } + }, + { + { -0x5f59bc47, -0x6169d72d, -0x193cdf9c, -0x4a3c3500, 0x7c2dec32, -0x64acfd77, -0x2a2e38f4, 0x43e37ae2 }, + { 0x70a13d11, -0x709cfe31, 0x350dd0c4, -0x303147eb, -0x5b435b82, -0x08fd682c, -0x1bb2ebcc, 0x3669b656 }, + { -0x12591ecd, 0x387e3f06, -0x665ec540, 0x67301d51, 0x36263811, -0x42a52708, 0x4fd5e9be, 0x6a21e6cd } + }, + { + { 0x6699b2e3, -0x10bed6ee, 0x708d1301, 0x71d30847, 0x1182b0bd, 0x325432d0, 0x001e8b36, 0x45371b07 }, + { 0x3046e65f, -0x0e39e8f6, 0x00d23524, 0x58712a2a, -0x737d48ab, 0x69dbbd3c, -0x5e6a00a9, 0x586bf9f1 }, + { 0x5ef8790b, -0x5924f773, 0x610937e5, 0x5278f0dc, 0x61a16eb8, -0x53fcb62e, -0x6f1ade87, 0x0eafb037 } + }, + { + { 0x0f75ae1d, 0x5140805e, 0x2662cc30, -0x13fd041d, -0x156dc693, 0x2cebdf1e, -0x3abca44d, 0x44ae3344 }, + { 0x3748042f, -0x69faaa3f, -0x7df455ef, 0x219a41e6, 0x73486d0c, 0x1c81f738, 0x5a02c661, 0x309acc67 }, + { -0x445abc12, -0x630d7647, 0x5ac97142, -0x0c89f163, 0x4f9360aa, 0x1d82e5c6, 0x7f94678f, 0x62d5221b } + }, + { + { 0x3af77a3c, 0x7585d426, -0x0116ebb3, -0x205184ef, 0x59f7193d, -0x5af98f80, -0x7c6ddfc9, 0x14f29a53 }, + { 0x18d0936d, 0x524c299c, -0x75f3e5f4, -0x37944a94, -0x24b579cf, -0x5c8afad2, -0x438aba9e, 0x5c0efde4 }, + { 0x25b2d7f5, -0x208e8124, -0x664acfc0, 0x21f970db, -0x3c12b39e, -0x256dcb49, 0x7bee093e, 0x5e72365c } + }, + { + { 0x2f08b33e, 0x7d933906, -0x2060cd42, 0x5b9659e5, 0x1f9ebdfd, -0x5300c253, -0x348cb649, 0x70b20555 }, + { 0x4571217f, 0x575bfc07, 0x0694d95b, 0x3779675d, -0x0be6e1cd, -0x65f5c845, 0x47b4eabc, 0x77f1104c }, + { 0x55112c4c, -0x41aeec3b, -0x6577e033, 0x6688423a, 0x5e503b47, 0x44667785, 0x4a06404a, 0x0e34398f } + }, + { + { 0x3e4b1928, 0x18930b09, 0x73f3f640, 0x7de3e10e, 0x73395d6f, -0x0bcde826, -0x35c863c2, 0x6f8aded6 }, + { 0x3ecebde8, -0x4982dd27, 0x27822f07, 0x09b3e841, -0x4fa49273, 0x743fa61f, -0x75c9dc8e, 0x5e540536 }, + { -0x02484d66, -0x1cbfedc3, -0x5de54d6f, 0x487b97e1, -0x02196b62, -0x066982fe, -0x372c2169, 0x780de72e } + }, + { + { 0x00f42772, 0x671feaf3, 0x2a8c41aa, -0x708d14d6, -0x68c8cd6e, 0x29a17fd7, 0x32b587a6, 0x1defc6ad }, + { 0x089ae7bc, 0x0ae28545, 0x1c7f4d06, 0x388ddecf, 0x0a4811b8, 0x38ac1551, 0x71928ce4, 0x0eb28bf6 }, + { -0x10ae6a59, -0x50a441e6, -0x6e84ea13, 0x148c1277, 0x7ae5da2e, 0x2991f7fb, -0x0722d799, 0x467d201b } + }, +}, +{ + { + { 0x296bc318, 0x745f9d56, -0x27ead19b, -0x66ca7f2c, 0x5839e9ce, -0x4f1a4ec1, -0x2bc6de40, 0x51fc2b28 }, + { -0x0842d195, 0x7906ee72, 0x109abf4e, 0x05d270d6, -0x46be575c, -0x72a301bb, 0x1c974287, 0x44c21867 }, + { -0x6a1d5674, 0x1b8fd117, 0x2b6b6291, 0x1c4e5ee1, 0x7424b572, 0x5b30e710, 0x4c4f4ac6, 0x6e6b9de8 } + }, + { + { -0x07f34f78, 0x6b7c5f10, 0x56e42151, 0x736b54dc, -0x3910663c, -0x3d49df5b, -0x3c5f90be, 0x5f4c802c }, + { 0x4b1de151, -0x200da032, -0x1ee3bfdb, -0x27be3f39, 0x54749c87, 0x2554b3c8, -0x6f71f207, 0x2d292459 }, + { 0x7d0752da, -0x649a370f, -0x38811800, -0x77e31cc8, 0x5b62f9e3, -0x3c4aeb10, -0x413ef2b8, 0x66ed5dd5 } + }, + { + { -0x3435fb83, -0x0f520c37, -0x0baad095, -0x7e3c4d35, 0x44735f93, -0x3025eed3, 0x7e20048c, 0x1f23a0c7 }, + { 0x0bb2089d, 0x7d38a1c2, -0x69332bee, -0x7f7ccb1f, 0x6c97d313, -0x3b58f474, 0x03007f20, 0x2eacf8bc }, + { -0x1a43ea90, -0x0dcab985, 0x0dbab38c, 0x03d2d902, -0x03061f62, 0x27529aa2, -0x62cb43b0, 0x0840bef2 } + }, + { + { 0x7f37e4eb, -0x32ab1f95, -0x0a169336, -0x733ea079, -0x2ca68232, -0x47db7450, 0x6074400c, 0x246affa0 }, + { -0x23ef4d79, 0x796dfb35, 0x5c7ff29d, 0x27176bcd, -0x384db6fb, 0x7f3d43e8, -0x6e3abd8a, 0x0304f5a1 }, + { -0x041bacdf, 0x37d88e68, -0x3f28afce, -0x79f68ab8, -0x76b5f2cb, 0x4e9b13ef, 0x5753d325, 0x25a83cac } + }, + { + { 0x3952b6e2, -0x60f099d7, 0x0934267b, 0x33db5e0e, -0x29f60124, -0x00badad5, -0x3af91f37, 0x06be10f5 }, + { -0x1127e9a2, 0x10222f48, 0x4b8bcf3a, 0x623fc123, -0x3dde1710, 0x1e145c09, -0x3587d9d0, 0x7ccfa59f }, + { -0x49d5cba1, 0x1a9615a9, 0x4a52fecc, 0x22050c56, 0x28bc0dfe, -0x585d877b, 0x1a1ee71d, 0x5e82770a } + }, + { + { 0x42339c74, -0x17fd17f6, -0x5800051b, 0x34175166, 0x1c408cae, 0x34865d1f, 0x605bc5ee, 0x2cca982c }, + { -0x527695a4, 0x35425183, -0x1872ad0a, -0x1798c505, -0x6d5ca09c, 0x2c66f25f, 0x3b86b102, 0x09d04f3b }, + { 0x197dbe6e, -0x02d2a2cb, -0x741b005d, 0x207c2eea, 0x325ae918, 0x2613d8db, 0x27741d3e, 0x7a325d17 } + }, + { + { 0x7e2a076a, -0x132d82ff, 0x1636495e, -0x28779761, -0x6e6dcc1b, 0x52a61af0, 0x7bb1ae64, 0x2a479df1 }, + { -0x2e92021e, -0x2fc94645, -0x3b6857d7, -0x5dfaa8a9, -0x580ed999, -0x7193369a, 0x1239c180, 0x4d3b1a79 }, + { 0x33db2710, -0x61a11172, -0x293bc35b, 0x189854de, -0x6d8e7ec8, -0x5be3dd3b, -0x5bc5a165, 0x27ad5538 } + }, + { + { -0x71b8f884, -0x34a5829d, 0x20a1c059, -0x7248ac9f, -0x74120234, 0x549e1e4d, 0x503b179d, 0x080153b7 }, + { 0x15350d61, 0x2746dd4b, -0x116ade49, -0x2fc03438, 0x138672ca, -0x1791c9a6, 0x7e7d89e2, 0x510e987f }, + { 0x0a3ed3e3, -0x2259626d, -0x329f58de, 0x3d386ef1, -0x4255b11a, -0x37e852a8, 0x4fe7372a, 0x23be8d55 } + }, +}, +{ + { + { 0x567ae7a9, -0x43e10b43, -0x29bb6743, 0x3f624cb2, 0x2c1f4ec8, -0x1bef9b2e, -0x45c7bfff, 0x2ef9c5a5 }, + { 0x74ef4fad, -0x6a016e66, -0x095cf75e, 0x3a827bec, 0x09a47b01, -0x69b1fe2d, 0x5ba3c797, 0x71c43c4f }, + { -0x05618b33, -0x4902920a, -0x1b50d986, -0x0e7d8744, -0x0e1066f2, -0x7daa4c30, -0x6f3a0d6d, 0x5a758ca3 } + }, + { + { 0x1d61dc94, -0x731f6e75, -0x657ecf9a, -0x7212c9ba, -0x5017552d, -0x2b1957d7, -0x09c62bc1, 0x0a738027 }, + { -0x26b9db6b, -0x5d48d8f0, -0x2a82affd, 0x3aa8c6d2, -0x5f4b7836, -0x1c2bff41, -0x4c148d14, 0x2dbae244 }, + { 0x57ffe1cc, -0x67f0b5d1, -0x1e7c67bd, 0x00670d0d, 0x49fb15fd, 0x105c3f4a, 0x5126a69c, 0x2698ca63 } + }, + { + { 0x5e3dd90e, 0x2e3d702f, -0x1b2dac7a, -0x61c0f6e8, 0x024da96a, 0x5e773ef6, 0x4afa3332, 0x3c004b0c }, + { 0x32b0ba78, -0x189ace78, -0x6da30075, 0x381831f7, -0x5fd6e034, 0x08a81b91, 0x49caeb07, 0x1fb43dcc }, + { 0x06f4b82b, -0x6556b954, -0x57f93b0d, 0x1ca284a5, -0x3932b879, 0x3ed3265f, -0x32e02de9, 0x6b43fd01 } + }, + { + { 0x3e760ef3, -0x4a38bda8, -0x11f54670, 0x75dc52b9, 0x072b923f, -0x40ebd83e, 0x6ff0d9f0, 0x73420b2d }, + { 0x4697c544, -0x3858a2b5, -0x20f00041, 0x15fdf848, -0x55b987a6, 0x2868b9eb, 0x5b52f714, 0x5a68d710 }, + { -0x617ae1fa, -0x50d30935, -0x39ddc73c, -0x70a6c6ed, -0x66040c8d, -0x2575476a, -0x15cb4362, 0x3db5632f } + }, + { + { -0x7d67da2b, 0x2e4990b1, 0x3e9a8991, -0x12151479, 0x4c704af8, -0x110fc2c7, -0x6a20d4f2, 0x59197ea4 }, + { -0x08a22628, -0x0b9111d5, 0x396759a5, 0x0d17b1f6, 0x499e7273, 0x1bf2d131, 0x49d75f13, 0x04321adf }, + { -0x1b1aa552, 0x04e16019, 0x7e2f92e9, -0x1884bc86, 0x6f159aa4, -0x3831d23f, -0x0b28f340, 0x45eafdc1 } + }, + { + { -0x30334e13, -0x49f1b9dc, -0x42a3fc6b, 0x59dbc292, -0x23fb7e37, 0x31a09d1d, 0x5d56d940, 0x3f73ceea }, + { -0x7fba28d5, 0x69840185, -0x30d0f9af, 0x4c22faa2, 0x6b222dc6, -0x6be5c99b, 0x0362dade, 0x5a5eebc8 }, + { 0x0a4e8dc6, -0x4858402f, 0x44c9b339, -0x41a8ff82, 0x1557aefa, 0x60c1207f, 0x266218db, 0x26058891 } + }, + { + { -0x39891abe, 0x4c818e3c, 0x03ceccad, 0x5e422c93, -0x4bed60f8, -0x13f83336, -0x4dbbbc48, 0x0dedfa10 }, + { -0x7c9f00fc, 0x59f704a6, 0x7661e6f4, -0x3c26c022, 0x12873551, -0x7ce4d58d, 0x4e615d57, 0x54ad0c2e }, + { -0x47d4add6, -0x11c4982b, -0x605a3e15, 0x36f16346, 0x6ec19fd3, -0x5a4b2d0e, -0x58856bf8, 0x62ecb2ba } + }, + { + { -0x5049d78c, -0x6df8d7ca, 0x79e104a5, 0x5fcd5e85, -0x39cf5eb6, 0x5aad01ad, 0x75663f98, 0x61913d50 }, + { 0x61152b3d, -0x1a1286ae, 0x0eddd7d1, 0x4962357d, -0x4694b38f, 0x7482c8d0, -0x56992742, 0x2e59f919 }, + { 0x1a3231da, 0x0dc62d36, -0x6bdffd90, -0x05b8a7ce, 0x3f9594ce, 0x02d80151, 0x31c05d5c, 0x3ddbc2a1 } + }, +}, +{ + { + { 0x004a35d1, -0x048ca53e, 0x3a6607c3, 0x31de0f43, -0x3ad72a67, 0x7b8591bf, -0x0a44faf4, 0x55be9a25 }, + { 0x4ffb81ef, 0x3f50a50a, 0x3bf420bf, -0x4e1fcaf7, -0x3955d330, -0x645571e4, -0x05dc85c0, 0x32239861 }, + { 0x33db3dbf, 0x0d005acd, -0x7f53ca1e, 0x0111b37c, 0x6f88ebeb, 0x4892d66c, 0x6508fbcd, 0x770eadb1 } + }, + { + { -0x5faf8e47, -0x0e2c497f, 0x3592ff3a, 0x2207659a, 0x7881e40e, 0x5f016929, -0x7945c8b2, 0x16bedd0e }, + { 0x5e4e89dd, -0x7bae0620, -0x4386c6c9, -0x3f9cfd01, 0x56a6495c, 0x5d227495, -0x5fa9fc05, 0x09a6755c }, + { 0x2c2737b5, 0x5ecccc4f, 0x2dccb703, 0x43b79e0c, 0x4ec43df3, 0x33e008bc, -0x0f8a9940, 0x06c1b840 } + }, + { + { -0x64fd7fa4, 0x69ee9e7f, 0x547d1640, -0x34007d76, -0x4dbcf698, 0x3d93a869, 0x3fe26972, 0x46b7b8cd }, + { -0x5c770789, 0x7688a5c6, -0x214d4954, 0x02a96c14, 0x1b8c2af8, 0x64c9f343, 0x54a1eed6, 0x36284355 }, + { -0x01811420, -0x167edf7a, 0x2f515437, 0x4cba6be7, 0x516efae9, 0x1d04168b, 0x43982cb9, 0x5ea13910 } + }, + { + { -0x2a2c4ffe, 0x6f2b3be4, 0x6a09c880, -0x5013cc27, -0x57433b34, 0x035f73a4, 0x4662198b, 0x22c5b928 }, + { -0x0b8fd11f, 0x49125c9c, -0x74da4cd3, 0x4520b71f, 0x501fef7e, 0x33193026, -0x372d14d5, 0x656d8997 }, + { 0x433d8939, -0x34a73702, 0x6a8d7e50, -0x765f34d2, 0x09fbbe5a, 0x79ca9553, -0x32803efa, 0x0c626616 } + }, + { + { -0x040bab4f, -0x70203c87, -0x0e5b488f, 0x45a5a970, -0x452ca6eb, -0x536de109, -0x57e3de6e, 0x42d088dc }, + { 0x4879b61f, 0x1ffeb80a, 0x4ada21ed, 0x6396726e, 0x368025ba, 0x33c7b093, -0x0c3ce878, 0x471aa0c6 }, + { -0x5fe9ae67, -0x7025f0c9, -0x375f1cbd, 0x0adadb77, -0x378a17e0, 0x20fbfdfc, 0x0c2206e7, 0x1cf2bea8 } + }, + { + { 0x02c0412f, -0x67d291e6, -0x24a71702, -0x6f05b37d, -0x234e7440, 0x01c2f5bc, 0x216abc66, 0x686e0c90 }, + { -0x4c9dfd54, -0x3d220e22, -0x2d1d855b, -0x6d5a01f7, -0x03f60e2d, 0x7d1648f6, 0x13bc4959, 0x74c2cc05 }, + { -0x5abc6a59, 0x1fadbadb, -0x51f25996, -0x4be5fd60, -0x445c83f9, -0x40e60a68, -0x21b7bcf3, 0x6a12b8ac } + }, + { + { 0x1aaeeb5f, 0x793bdd80, -0x3eae778f, 0x00a2a0aa, 0x1f2136b4, -0x175c8c5d, -0x036e10e7, 0x48aab888 }, + { 0x39d495d9, -0x072515e1, 0x525f1dfc, 0x592c190e, -0x3666e2e5, -0x247342fc, -0x2770f349, 0x11f7fda3 }, + { 0x5830f40e, 0x041f7e92, 0x79661c06, 0x002d6ca9, 0x2b046a2e, -0x79236007, -0x74fb6c2f, 0x76036092 } + }, + { + { 0x695a0b05, -0x4bcef71b, -0x52c85c75, 0x6cb00ee8, -0x5cac8c7f, 0x5edad6ee, -0x4923cddc, 0x3f2602d4 }, + { 0x120cf9c6, 0x21bb41c6, -0x21325a65, -0x154d55ee, 0x0aa48b34, -0x3e58d2fe, -0x1782c498, 0x215d4d27 }, + { 0x5bcaf19c, -0x374db84a, -0x4e4d39ae, 0x49779dc3, -0x2a131d1e, -0x765e7f45, -0x31371fc7, 0x13f098a3 } + }, +}, +{ + { + { 0x2796bb14, -0x0c55a85e, -0x64f825df, -0x77c54549, 0x31a0391c, -0x1ab41de8, -0x27cdfa07, 0x5ee7fb38 }, + { -0x31a13ab5, -0x6523f007, -0x73d0ecf3, 0x039c2a6b, -0x0f076aeb, 0x028007c7, -0x53fb4c95, 0x78968314 }, + { 0x41446a8e, 0x538dfdcb, 0x434937f9, -0x5a530257, 0x263c8c78, 0x46af908d, -0x6435f2f7, 0x61d0633c } + }, + { + { -0x07038c21, -0x525cd744, -0x590fc804, -0x117b96a3, 0x38c2a909, 0x637fb4db, -0x07f98424, 0x5b23ac2d }, + { -0x0024da9a, 0x63744935, 0x780b68bb, -0x3a429477, 0x553eec03, 0x6f1b3280, 0x47aed7f5, 0x6e965fd8 }, + { -0x117fad85, -0x652d46ad, -0x05219273, -0x1770e656, 0x150e82cf, 0x0e711704, -0x226a2124, 0x79b9bbb9 } + }, + { + { -0x71608c8c, -0x2e668252, -0x3044f7ea, -0x5fcd5d08, 0x6d445f0a, -0x329345ee, 0x0accb834, 0x1ba81146 }, + { 0x6a3126c2, -0x144caac0, 0x68c8c393, -0x2d9c7c58, -0x1a46857e, 0x6c0c6429, -0x3602deb9, 0x5065f158 }, + { 0x0c429954, 0x708169fb, -0x28913099, -0x1eb9ff54, 0x70e645ba, 0x2eaab98a, 0x58a4faf2, 0x3981f39e } + }, + { + { 0x6de66fde, -0x37ba205b, 0x2c40483a, -0x1ead5b00, -0x384b09ce, -0x162d1e9d, -0x2343e49b, 0x30f4452e }, + { 0x59230a93, 0x18fb8a75, 0x60e6f45d, 0x1d168f69, 0x14a93cb5, 0x3a85a945, 0x05acd0fd, 0x38dc0837 }, + { -0x3a8a68c0, -0x7a92d87e, -0x06634134, -0x05ecba97, -0x3f15b18f, -0x77bb038d, 0x593f2469, 0x632d9a1a } + }, + { + { -0x12f37b59, -0x40f602ef, 0x0d9f693a, 0x63f07181, 0x57cf8779, 0x21908c2d, -0x7509b45e, 0x3a5a7df2 }, + { -0x47f8345a, -0x094494eb, -0x43ab0f29, 0x1823c7df, 0x6e29670b, -0x44e268fd, 0x47ed4a57, 0x0b24f488 }, + { 0x511beac7, -0x23252b42, -0x12d9330e, -0x5bac7f8b, 0x005f9a65, -0x1e630061, 0x75481f63, 0x34fcf744 } + }, + { + { 0x78cfaa98, -0x5a44e255, 0x190b72f2, 0x5ceda267, 0x0a92608e, -0x6cf636ef, 0x2fb374b0, 0x0119a304 }, + { 0x789767ca, -0x3e681fb4, 0x38d9467d, -0x478eb235, -0x7c06a058, 0x55de8882, 0x4dfa63f7, 0x3d3bdc16 }, + { -0x173de883, 0x67a2d89c, 0x6895d0c1, 0x669da5f6, -0x4d7d5d50, -0x0a9a671b, -0x121df58d, 0x56c088f1 } + }, + { + { 0x24f38f02, 0x581b5fac, -0x451cf343, -0x56f41602, -0x75306d10, -0x65de96fe, -0x7ca6fc71, 0x038b7ea4 }, + { 0x10a86e17, 0x336d3d11, 0x0b75b2fa, -0x280c77ce, 0x25072988, -0x06eacc8a, -0x66ef7479, 0x09674c6b }, + { -0x66ce9008, -0x60b107df, -0x155872b1, 0x2f49d282, 0x5aef3174, 0x0971a5ab, 0x5969eb65, 0x6e5e3102 } + }, + { + { 0x63066222, 0x3304fb0e, -0x785345c1, -0x04caf977, -0x73ef9e5d, -0x42e6db89, -0x2e7c79e0, 0x3058ad43 }, + { -0x781a6c05, -0x4e939d0b, -0x35a2c18f, 0x4999edde, 0x14cc3e6d, -0x4b6e3e20, -0x76572458, 0x08f51147 }, + { -0x1a899c30, 0x323c0ffd, -0x5dd159f0, 0x05c3df38, -0x5366b066, -0x42387543, -0x101c2367, 0x26549fa4 } + }, +}, +{ + { + { -0x08ac6947, 0x04dbbc17, -0x2d0798ba, 0x69e6a2d7, -0x0ac1543a, -0x39bf6267, 0x332e25d2, 0x606175f6 }, + { -0x78317077, 0x738b38d7, 0x4179a88d, -0x49d9a71e, -0x0eaece93, 0x30738c9c, 0x727275c9, 0x49128c7f }, + { -0x0abf1823, 0x4021370e, -0x5e0e2f5b, 0x0910d6f5, 0x5b06b807, 0x4634aacd, 0x6944f235, 0x6a39e635 } + }, + { + { 0x74049e9d, 0x1da19657, -0x6701cad5, -0x0432915f, -0x33adc95a, -0x4e3432b0, 0x3f9846e2, 0x1f5ec83d }, + { -0x206f0c19, -0x6932a9c0, -0x2405da16, 0x6c3a760e, 0x59e33cc4, 0x24f3ef09, 0x530d2e58, 0x42889e7e }, + { 0x328ccb75, -0x7104dc3d, -0x22789117, -0x50bd5df9, 0x5dfae796, 0x20fbdadc, 0x06bf9f51, 0x241e246b } + }, + { + { 0x6280bbb8, 0x7eaafc9a, -0x0bfc27f7, 0x22a70f12, 0x1bfc8d20, 0x31ce40bb, -0x1742ac12, 0x2bc65635 }, + { -0x5291670a, 0x29e68e57, 0x0b462065, 0x4c9260c8, -0x5ae144b5, 0x3f00862e, -0x4c726f69, 0x5bc2c77f }, + { -0x5694526d, -0x172a2361, -0x21e6b824, -0x1a704e83, 0x65185fa3, 0x681532ea, 0x034a7830, 0x1fdd6c3b } + }, + { + { 0x2dd8f7a9, -0x63ec595b, 0x3efdcabf, 0x2dbb1f8c, 0x5e08f7b5, -0x69e1cdc0, -0x4419361b, 0x48c8a121 }, + { 0x55dc18fe, 0x0a64e28c, 0x3399ebdd, -0x1c206167, 0x70e2e652, 0x79ac4323, 0x3ae4cc0e, 0x35ff7fc3 }, + { 0x59646445, -0x03bea584, -0x3ed749eb, -0x2ddb4d29, 0x05fbb912, 0x6035c9c9, 0x74429fab, 0x42d7a912 } + }, + { + { -0x6cc25a44, -0x565b76b9, -0x3d168614, 0x4a58920e, 0x13e5ac4c, -0x69278000, 0x4b48b147, 0x453692d7 }, + { -0x1508d12d, 0x4e6213e3, 0x43acd4e7, 0x6794981a, 0x6eb508cb, -0x00ab8322, 0x10fcb532, 0x6fed19dd }, + { -0x57aa6391, -0x2288a267, -0x20ffc1dc, -0x0bd5dec0, -0x256d759a, 0x5223e229, 0x6d38f22c, 0x063f46ba } + }, + { + { 0x37346921, 0x39843cb7, 0x38c89447, -0x58b804f9, -0x5dbacf82, -0x34727fcf, 0x6d82f068, 0x67810f8e }, + { 0x5f536694, -0x2d2dbd77, 0x42939b2c, -0x35cc5d3b, -0x382246a4, -0x6790525a, 0x2f712d5d, 0x5a152c04 }, + { -0x2dd7824c, 0x3eeb8fbc, 0x01a03e93, 0x72c7d3a3, -0x4267d9a6, 0x5473e88c, 0x5921b403, 0x7324aa51 } + }, + { + { -0x17dcab35, -0x52dc0926, -0x49a8e593, 0x6962502a, -0x1c71c82f, -0x649ae9ca, -0x2e5cced1, 0x5cac5005 }, + { 0x6c3cbe8e, -0x7a86bd0c, 0x4730c046, -0x5e2c9b4f, -0x2dc3be41, 0x1c8ed914, -0x11092a2e, 0x0838e161 }, + { -0x161c66fc, -0x733eab34, -0x7b2197ba, 0x5b3a040b, -0x4e41a292, -0x3b2759e4, -0x2779e0fe, 0x40fb897b } + }, + { + { 0x5ab10761, -0x1a8127b9, 0x6fd13746, 0x71435e20, -0x32fda9ce, 0x342f824e, -0x5786e185, 0x4b16281e }, + { 0x62de37a1, -0x7b3a5570, 0x0d1d96e1, 0x421da500, 0x6a9242d9, 0x78828630, 0x690d10da, 0x3c5e464a }, + { 0x0b813381, -0x2e3efe2b, 0x76ee6828, -0x2119f0ef, 0x383f6409, 0x0cb68893, -0x0900b7b6, 0x6183c565 } + }, +}, +{ + { + { -0x50c09992, -0x24b97ab7, -0x0eb5f15b, -0x288030fc, -0x5b45f3b9, 0x3df23ff7, 0x32ce3c85, 0x3a10dfe1 }, + { 0x1e6bf9d6, 0x741d5a46, 0x7777a581, 0x2305b3fc, 0x6474d3d9, -0x2baa8b5e, 0x6401e0ff, 0x1926e1dc }, + { -0x15e83160, -0x1f80b176, 0x3a1fc1fd, 0x2fd51546, 0x31f2c0f1, 0x175322fd, -0x79e1a2eb, 0x1fa1d01d } + }, + { + { -0x2e206b55, 0x38dcac00, -0x2ef7f217, 0x2e712bdd, -0x022a1d9e, 0x7f13e93e, -0x1165fe1b, 0x73fced18 }, + { 0x7d599832, -0x337faa6c, 0x37f15520, 0x1e4656da, 0x4e059320, -0x6609088c, 0x6a75cf33, 0x773563bc }, + { 0x63139cb3, 0x06b1e908, -0x3a5fc133, -0x5b6c2599, -0x529c76ce, -0x72883138, 0x1b864f44, 0x1f426b70 } + }, + { + { -0x6e5edaae, -0x0e81ca38, 0x575e9c76, -0x48947ead, 0x0d9b723e, -0x057cbf91, 0x3fa7e438, 0x0b76bb1b }, + { 0x41911c01, -0x1036d9b4, 0x17a22c25, -0x0e5c4848, -0x0cf0ebb9, 0x5875da6b, 0x1d31b090, 0x4e1af527 }, + { 0x7f92939b, 0x08b8c1f9, -0x2bbb5492, -0x41988e35, -0x66447fe9, 0x22e56463, -0x488d56ab, 0x7b6dd61e } + }, + { + { -0x54fe2d39, 0x5730abf9, 0x40143b18, 0x16fb76dc, -0x5f344d7f, -0x7993419b, -0x64009502, 0x53fa9b65 }, + { 0x50f33d92, -0x48523e18, 0x608cd5cf, 0x7998fa4f, -0x7203a425, -0x5269d243, -0x50e2d0b1, 0x703e9bce }, + { -0x6b77abab, 0x6c14c8e9, 0x65aed4e5, -0x7bc5a29a, -0x4329a50f, 0x181bb73e, -0x3b39e0b0, 0x398d93e5 } + }, + { + { -0x2d181c0e, -0x3c7883a0, 0x30828bb1, 0x3b34aaa0, 0x739ef138, 0x283e26e7, 0x02c30577, 0x699c9c90 }, + { 0x33e248f3, 0x1c4bd167, 0x15bf0a5f, -0x4261ed79, -0x5ef4fc8a, -0x2bc07310, -0x20e6e4ed, 0x53b09b5d }, + { 0x5946f1cc, -0x0cf958dd, -0x331a2683, -0x6de8e74b, -0x7e4b168b, 0x28cdd247, 0x6fcdd907, 0x51caf30c } + }, + { + { 0x18ac54c7, 0x737af99a, -0x3ae34cf1, -0x6fcc8724, 0x4ce10cc7, 0x2b89bc33, -0x76071666, 0x12ae29c1 }, + { 0x7674e00a, -0x59f458be, -0x5e85840d, 0x630e8570, -0x30ccdb34, 0x3758563d, 0x2383fdaa, 0x5504aa29 }, + { 0x1f0d01cf, -0x56613f35, 0x3a34f7ae, 0x0dd1efcc, -0x2f63b1de, 0x55ca7521, 0x58eba5ea, 0x5fd14fe9 } + }, + { + { -0x406c3472, 0x3c42fe5e, 0x36d4565f, -0x412057af, -0x77bddf18, -0x1f0f7a62, 0x0725d128, 0x7dd73f96 }, + { 0x2845ab2c, -0x4a23d221, 0x0a7fe993, 0x069491b1, 0x4002e346, 0x4daaf3d6, 0x586474d1, 0x093ff26e }, + { 0x68059829, -0x4ef2db02, -0x2450dc1b, 0x75730672, -0x4ba853d7, 0x1367253a, -0x794b8f5c, 0x2f59bcbc } + }, + { + { -0x496e3cff, 0x7041d560, -0x522818e2, -0x7adfe4c1, 0x11335585, 0x16c2e163, 0x010828b1, 0x2aa55e3d }, + { -0x66e8eca1, -0x7c7b82be, 0x567d03d7, -0x52e46ee1, -0x4188552f, 0x7e7748d9, 0x2e51af4a, 0x5458b42e }, + { 0x0c07444f, -0x12ae6d1a, 0x74421d10, 0x42c54e2d, -0x024a379c, 0x352b4c82, -0x7589799c, 0x13e9004a } + }, +}, +{ + { + { -0x7f94b984, 0x1e6284c5, -0x18a29f85, -0x3a096685, -0x4c872d9e, -0x749826a8, -0x7e327490, 0x3d88d66a }, + { 0x6c032bff, -0x344a4aab, 0x29297a3a, -0x208e6e49, -0x52127e45, -0x3e008cda, 0x68be03f5, 0x71ade8bb }, + { 0x204ed789, -0x7489856d, -0x605f51d6, 0x762fcacb, 0x6dce4887, 0x771febcc, -0x700fa04d, 0x34306215 } + }, + { + { 0x2a7b31b4, -0x031de6f9, -0x55a87fea, 0x4d7adc75, -0x78b86cdc, 0x0ec276a6, 0x1fda4beb, 0x6d6d9d5d }, + { -0x1e0a40b7, -0x1fa25e59, -0x2b8c9f6e, 0x26457d6d, 0x73cc32f6, 0x77dcb077, -0x6322a033, 0x0a5d9496 }, + { -0x164f7e7d, 0x22b1a58a, -0x3ea3c775, -0x026a2f8f, -0x7af5fae9, -0x567edc8a, -0x4480cca2, 0x33384cba } + }, + { + { 0x26218b8d, 0x33bc627a, -0x3857f39f, -0x157f4de1, 0x173e9ee6, -0x6ba74ed5, 0x0e2f3059, 0x076247be }, + { 0x0ca2c7b5, 0x3c6fa268, 0x6fb64fda, 0x1b508204, 0x5431d6de, -0x14accb64, 0x6b879c89, 0x5278b38f }, + { 0x1416375a, 0x52e105f6, -0x7a54145c, -0x136850ca, 0x23a67c36, 0x26e6b506, -0x0c2b04ff, 0x5cf0e856 } + }, + { + { 0x3db342a8, -0x415131cf, -0x7bd24812, -0x345c9ca5, -0x7e80ec11, -0x177399e0, 0x4e76d5c6, 0x1b9438aa }, + { 0x1ae8cab4, -0x0936978d, -0x34b06d3b, 0x5e20741e, -0x733243c2, 0x2da53be5, 0x69970df7, 0x2dddfea2 }, + { 0x166f031a, -0x75af8882, 0x0fb7a328, 0x067b39f1, 0x010fbd76, 0x1925c9a6, -0x338bf6fb, 0x6df9b575 } + }, + { + { 0x48cade41, -0x13203ca5, -0x4dcd7d90, 0x6a88471f, 0x40a01b6a, 0x740a4a24, 0x003b5f29, 0x471e5796 }, + { 0x27f6bdcf, 0x42c11929, 0x403d61ca, -0x706e6e86, -0x7461e09f, -0x23e3a59a, 0x04ec0f8d, 0x15960478 }, + { -0x5312c854, -0x2569444d, -0x16df7316, 0x7a2423b5, 0x38aebae2, 0x24cc5c30, -0x23a251d1, 0x50c356af } + }, + { + { 0x1b31b964, -0x30126321, -0x735ae50d, -0x0b79567b, -0x1573e07c, 0x14897265, -0x6cd53400, 0x784a53dd }, + { 0x41c30318, 0x09dcbf43, -0x7ce7e232, -0x1145f9ef, -0x23e1d65f, -0x3e863f32, 0x073f35b0, 0x1dbf7b89 }, + { 0x14fc4920, 0x2d99f9df, -0x3bb6601b, 0x76ccb60c, -0x1a30fffd, -0x5becd345, 0x54f000ea, 0x3f93d823 } + }, + { + { 0x79e14978, -0x1553ed2f, -0x441400a2, -0x006dc00d, 0x0663ce27, 0x4af663e4, 0x11a5f5ff, 0x0fd381a8 }, + { -0x61fb317b, -0x7e7c1898, 0x04465341, 0x678fb71e, 0x6688edac, -0x526dfa71, 0x532b099a, 0x5da350d3 }, + { -0x5bc920ac, -0x0da95314, -0x51962918, 0x108b6168, 0x6b5d036c, 0x20d986cb, -0x011d50b0, 0x655957b9 } + }, + { + { -0x2ffd2f54, -0x423ebf65, -0x4a33265a, 0x66660245, -0x05217a14, -0x7dce823c, 0x6ad7df0d, 0x02fe934b }, + { -0x56fdfcf1, -0x51574f81, -0x0b9c2ebd, -0x07738996, 0x3c787a60, 0x15b08366, -0x7d985b58, 0x08eab114 }, + { -0x3048158c, -0x10a30f00, -0x5e34bd54, 0x22897633, -0x310d7a1e, -0x2b31f3ac, -0x75eb95ab, 0x30408c04 } + }, +}, +{ + { + { 0x193b877f, -0x44d1ff37, -0x1f23af95, -0x131c5770, 0x36de649f, -0x130c4840, -0x672161e6, 0x5f460408 }, + { -0x7cd03125, 0x739d8845, -0x5194079d, -0x05c72937, -0x48b00109, 0x32bc0dca, 0x14bce45e, 0x73937e88 }, + { 0x297bf48d, -0x46fc8eea, -0x2b0f97cc, -0x562ec4de, 0x4696bdc6, -0x1e68eaa9, -0x6e2a17cb, 0x2cf8a4e8 } + }, + { + { 0x17d06ba2, 0x2cb5487e, 0x3950196b, 0x24d2381c, -0x7a6875d0, -0x289a637f, -0x6e295b0a, 0x7a6f7f28 }, + { 0x07110f67, 0x6d93fd87, 0x7c38b549, -0x22b3f62d, -0x3d8c957a, 0x7cb16a4c, 0x58252a09, 0x2049bd6e }, + { 0x6a9aef49, 0x7d09fd8d, 0x5b3db90b, -0x0f119f42, 0x519ebfd4, 0x4c21b52c, -0x3aba6be3, 0x6011aadf } + }, + { + { 0x02cbf890, 0x63ded0c8, 0x0dff6aaa, -0x042f6736, -0x46491267, 0x624d0afd, 0x79340b1e, 0x69ce18b7 }, + { -0x306a07c4, 0x5f67926d, 0x71289071, 0x7c7e8561, -0x667085a5, -0x295e180d, 0x0b62f9e0, 0x6fc5cc1b }, + { -0x4d678635, -0x2e10aad8, -0x2b816f6e, -0x22e551c4, 0x189f2352, 0x127e0442, -0x1a8efe0f, 0x15596b3a } + }, + { + { 0x7e5124ca, 0x09ff3116, -0x2638ba21, 0x0be4158b, 0x7ef556e5, 0x292b7d22, -0x50492ec8, 0x3aa4e241 }, + { 0x3f9179a2, 0x462739d2, -0x68292231, -0x007cedcf, 0x53f2148a, 0x1307deb5, 0x7b5f4dda, 0x0d223768 }, + { 0x2a3305f5, 0x2cc138bf, -0x5d16d93d, 0x48583f8f, 0x5549d2eb, 0x083ab1a2, 0x4687a36c, 0x32fcaa6e } + }, + { + { 0x2787ccdf, 0x3207a473, -0x0dec1c08, 0x17e31908, -0x09f269b2, -0x2a4d1329, -0x3d9ff417, 0x746f6336 }, + { -0x3a82650b, 0x7bc56e8d, -0x620f420e, 0x3e0bd2ed, 0x22efe4a3, -0x553feb22, -0x014295a4, 0x4627e9ce }, + { -0x549368e4, 0x3f4af345, -0x66bc8ce1, -0x1d77148e, 0x0344186d, 0x33596a8a, 0x7ed66293, 0x7b491700 } + }, + { + { -0x22ac5d23, 0x54341b28, -0x20bd03c1, -0x55e86fa5, 0x4dd2f8f4, 0x0ff592d9, -0x1f732c83, 0x1d03620f }, + { -0x547b4f9c, 0x2d85fb5c, -0x760c43ec, 0x497810d2, 0x7b15ce0c, 0x476adc44, -0x07bb0285, 0x122ba376 }, + { -0x5d4b1aac, -0x3dfdcd33, 0x115d187f, -0x612f02be, 0x7dd479d9, 0x2eabb4be, 0x2b68ec4c, 0x02c70bf5 } + }, + { + { 0x458d72e1, -0x531acd41, 0x7cb73cb5, 0x5be768e0, -0x11744219, 0x56cf7d94, -0x014bc5fd, 0x6b0697e3 }, + { 0x5d0b2fbb, -0x5d7813b5, 0x074882ca, 0x415c5790, -0x3e2f7ea4, -0x1fbb59e2, 0x409ef5e0, 0x26334f0a }, + { -0x209d5c40, -0x49370fb6, 0x076da45d, 0x3ef000ef, 0x49f0d2a9, -0x636346a8, 0x441b2fae, 0x1cc37f43 } + }, + { + { -0x36315147, -0x2899a90f, 0x18e5656a, 0x1c5b15f8, -0x7bb3dccc, 0x26e72832, 0x2f196838, 0x3a346f77 }, + { 0x5cc7324f, 0x508f565a, -0x1af956de, -0x2f9e3b40, 0x5c45ac19, -0x04e75425, 0x0380314a, 0x6c6809c1 }, + { -0x1d259538, -0x2d2aaeee, -0x4e17ae13, -0x1642fccf, -0x71398d9e, -0x69f8b923, 0x6ef7c5d0, 0x05911b9f } + }, +}, +{ + { + { -0x3a01606c, 0x01c18980, 0x716fd5c8, -0x329a9897, -0x2e6a5f7a, -0x7e9fba3d, 0x66cc7982, 0x6e2b7f32 }, + { -0x49c800d3, -0x162328aa, -0x36780f3c, -0x13b3cb71, -0x0c043849, -0x312a6d7b, -0x6c1e1579, 0x33053547 }, + { -0x083ca971, -0x337fdb98, 0x19974cb3, -0x6216457e, -0x4a47eca0, -0x5448dd64, 0x6fbeba62, 0x44e2017a } + }, + { + { -0x49359133, -0x7807d30d, 0x18f4a0c2, 0x580f893e, 0x2604e557, 0x05893007, 0x56d19c1d, 0x6cab6ac2 }, + { 0x54dab774, -0x3b3d58bd, 0x4eaf031a, -0x71a2b3c4, 0x42838f17, -0x4893dc2e, 0x68dce4ea, 0x749a098f }, + { 0x2cc1de60, -0x23201f60, 0x51c5575b, 0x032665ff, 0x073abeeb, 0x2c0c32f1, -0x328479fa, 0x6a882014 } + }, + { + { -0x50b01492, -0x2eee2e84, -0x4cc55b5d, 0x050bba42, -0x114b93d0, 0x17514c3c, 0x1bc27d75, 0x54bedb8b }, + { -0x5b8b804b, -0x5ad56d02, 0x1fa5ab89, -0x23ed5bb7, -0x47b85b32, -0x27d256b5, -0x6aed33b2, 0x4d77edce }, + { 0x77e2189c, 0x77c8e145, -0x00663bbb, -0x5c1b9096, 0x6d335343, 0x3144dfc8, 0x7c4216a9, 0x3a96559e } + }, + { + { -0x7f4555ae, 0x44938968, -0x0d7a6bf2, 0x4c98afc4, -0x5babb74a, -0x10b55865, -0x5a855181, 0x5278c510 }, + { -0x0bd52d12, 0x12550d37, -0x675e040b, -0x74871ffc, 0x33894cb2, 0x5d530782, 0x3e498d0c, 0x02c84e4e }, + { 0x294c0b94, -0x5ab22f8c, -0x20e7004a, -0x0aa2b948, -0x72517c9a, -0x0f90133b, -0x7e6f2e9b, 0x58865766 } + }, + { + { 0x3de25cc3, -0x40a7cb10, -0x297eab6a, -0x47783752, -0x6b7e176e, 0x5105221a, -0x088dc06d, 0x6760ed19 }, + { 0x1aef7117, -0x2b88edcf, 0x229e92c7, 0x50343101, -0x62ea6469, 0x7a95e184, -0x74a2d637, 0x2449959b }, + { -0x53ca1ea0, 0x669ba3b7, -0x457bdfaa, 0x2eccf73f, -0x3f7fb0f9, 0x1aec1f17, 0x1856f4e7, 0x0d96bc03 } + }, + { + { -0x338afa1f, -0x4e2acb50, 0x16c35288, 0x32cd0034, 0x0762c29d, -0x34c95a80, 0x237a0bf8, 0x5bfe69b9 }, + { 0x75c52d82, 0x3318be77, 0x54d0aab9, 0x4cb764b5, -0x3388c26f, -0x5430c2d9, -0x7edcd776, 0x3bf4d184 }, + { 0x78a151ab, 0x183eab7e, -0x66f6c89d, -0x44166f37, 0x4ac7e335, -0x008e8292, 0x25f39f88, 0x4c5cddb3 } + }, + { + { -0x185606fe, 0x57750967, 0x4f5b467e, 0x2c37fdfc, 0x3177ba46, -0x4d9e99c6, -0x23d2acd5, 0x3a375e78 }, + { 0x6190a6eb, -0x3f0948b3, 0x2db8f4e4, 0x20ea81a4, -0x68cea8a0, -0x57429083, 0x62ac7c21, 0x33b1d602 }, + { 0x2d4dddea, -0x7ebe18d1, 0x62c607c8, -0x19150168, 0x573cafd0, 0x23c28458, 0x4ff97346, 0x46b9476f } + }, + { + { 0x0d58359f, 0x1215505c, -0x03d73b95, 0x2a2013c7, -0x761599b2, 0x24a0a1af, -0x5eecf1e1, 0x4400b638 }, + { 0x4f901e5c, 0x0c1ffea4, 0x2184b782, 0x2b0b6fb7, 0x0114db88, -0x1a78006f, 0x4785a142, 0x37130f36 }, + { -0x6912e63d, 0x3a01b764, -0x12cd8dd0, 0x31e00ab0, -0x7c35ea4f, 0x520a8857, 0x5accbec7, 0x06aab987 } + }, +}, +{ + { + { 0x512eeaef, 0x5349acf3, 0x1cc1cb49, 0x20c141d3, -0x56659773, 0x24180c07, -0x39b4d2e9, 0x555ef9d1 }, + { -0x0a20f145, -0x3ecc667d, 0x512c4cac, -0x3f0c8a71, 0x0bb398e1, 0x2cf1130a, -0x55d8f39e, 0x6b3cecf9 }, + { 0x3b73bd08, 0x36a770ba, -0x5c5040f4, 0x624aef08, -0x4bf6b90e, 0x5737ff98, 0x3381749d, 0x675f4de1 } + }, + { + { 0x3bdab31d, -0x5ed00927, -0x629ad202, 0x0725d80f, -0x65416b79, 0x019c4ff3, -0x7d32c3bd, 0x60f450b8 }, + { 0x6b1782fc, 0x0e2c5203, 0x6cad83b4, 0x64816c81, 0x6964073e, -0x2f234227, 0x0164c520, 0x13d99df7 }, + { 0x21e5c0ca, 0x014b5ec3, -0x28e6405e, 0x4fcb69c9, 0x750023a0, 0x4e5f1c18, 0x55edac80, 0x1c06de9e } + }, + { + { -0x00929656, -0x002ad4c0, -0x23bfb645, 0x34530b18, -0x5cb26769, 0x5e4a5c2f, 0x7d32ba2d, 0x78096f8e }, + { -0x5cc13b1e, -0x66f0852a, -0x41d11f72, 0x6608f938, 0x63284515, -0x635ebc3b, -0x13d249f3, 0x4cf38a1f }, + { 0x0dfa5ce7, -0x5f55559b, 0x48b5478c, -0x063b61d6, 0x7003725b, 0x4f09cc7d, 0x26091abe, 0x373cad3a } + }, + { + { -0x76224453, -0x0e415705, 0x61aeaecb, 0x3bcb2cbc, 0x1f9b8d9d, -0x70a75845, 0x5112a686, 0x21547eda }, + { -0x7d360a84, -0x4d6b9cb3, 0x24934536, 0x1fcbfde1, 0x418cdb5a, -0x6163b24d, 0x454419fc, 0x0040f3d9 }, + { -0x02a6792d, -0x210216c7, 0x510a380c, -0x0bd8d377, -0x44cee647, -0x48d45bf9, 0x4a254df4, 0x63550a33 } + }, + { + { 0x72547b49, -0x6445a7bb, -0x1d3bf720, -0x0cfa3906, -0x38cb0e73, 0x60e8fa69, -0x55828986, 0x39a92baf }, + { -0x4a9630c9, 0x6507d6ed, 0x0ca52ee1, 0x178429b0, -0x149429a3, -0x1583ff70, -0x250870af, 0x3eea62c7 }, + { -0x196cd8b2, -0x62db38ed, 0x68dbd375, 0x5f638577, -0x14754c66, 0x70525560, 0x65c9c4cd, 0x68436a06 } + }, + { + { -0x17dfef84, 0x1e56d317, -0x7bf5169b, -0x3ad997bc, 0x320ffc7a, -0x3e1f5e3a, -0x6e9eeb8e, 0x5373669c }, + { 0x202f3f27, -0x43fdca18, 0x64f975b0, -0x38a3ff1e, -0x5c73dbea, -0x6e5b162b, -0x75487607, 0x17b6e7f6 }, + { -0x65f1ada9, 0x5d2814ab, -0x36354c04, -0x6f70df7c, 0x5b2d1eca, -0x50350a78, 0x78f87d11, 0x1cb4b5a6 } + }, + { + { -0x5d5ff819, 0x6b74aa62, -0x0f8e384f, -0x0cee1f50, 0x000be223, 0x5707e438, -0x7d109154, 0x2dc0fd2d }, + { 0x394afc6c, -0x499b3f95, -0x6725a04f, 0x0c88de24, 0x4bcad834, 0x4f8d0316, -0x218bcb5e, 0x330bca78 }, + { 0x1119744e, -0x67d1007c, 0x2b074724, -0x0696a16a, -0x4036ac05, -0x3a753eb1, 0x369f1cf5, 0x3c31be1b } + }, + { + { -0x0634bd8e, -0x3e97436d, -0x38312468, -0x51478ee1, 0x34ac8d7a, 0x7f0e52aa, 0x7e7d55bb, 0x41cec109 }, + { 0x08948aee, -0x4f0b79b3, -0x6e45e391, 0x07dc19ee, -0x59535ea8, 0x7975cdae, 0x4262d4bb, 0x330b6113 }, + { -0x5d927f76, -0x0869e629, 0x1d9e156d, -0x44e02b62, -0x245e20d9, 0x73d7c36c, 0x1f28777d, 0x26b44cd9 } + }, +}, +{ + { + { -0x4fd7a0c9, -0x50bb7bd3, 0x47efc8df, -0x78ace770, -0x07df6866, -0x6a8b1f6f, 0x69615579, 0x0e378d60 }, + { 0x393aa6d8, 0x300a9035, -0x5ed44e33, 0x2b501131, -0x0f6c3dde, 0x7b1ff677, -0x3547d453, 0x4309c1f8 }, + { -0x7cf8a5ab, -0x26056e8f, 0x6b009fdc, 0x4bdb5ad2, -0x29c210f2, 0x7829ad2c, 0x75fd3877, 0x078fc549 } + }, + { + { -0x47cc5676, -0x1dffb4a5, 0x2d4c3330, 0x44775dec, 0x7eace913, 0x3aa24406, -0x2a71ff57, 0x272630e3 }, + { 0x28878f2d, -0x782042ec, 0x1e9421a1, 0x134636dd, 0x257341a3, 0x4f17c951, -0x52d69348, 0x5df98d4b }, + { -0x1336f4ac, -0x0c987030, 0x12043599, -0x0ffeba65, 0x3758b89b, 0x26725fbc, 0x73a719ae, 0x4325e4aa } + }, + { + { -0x30960a63, -0x12db9d66, -0x22a5440c, 0x2a4a1cce, 0x56b2d67b, 0x3535ca1f, 0x43b1b42d, 0x5d8c68d0 }, + { 0x433c3493, 0x657dc6ef, -0x7f24073d, 0x65375e9f, 0x5b372dae, 0x47fd2d46, 0x796e7947, 0x4966ab79 }, + { -0x1c4bd4f6, -0x11ccd2b3, 0x16a4601c, -0x27b1a5d5, 0x078ba3e4, 0x78243877, 0x184ee437, 0x77ed1eb4 } + }, + { + { -0x616d12e6, 0x185d43f8, -0x01b8e63a, -0x4fb5e116, -0x590fc0b1, 0x499fbe88, 0x3c859bdd, 0x5d8b0d2f }, + { 0x201839a0, -0x402b1ec1, 0x3e3df161, -0x5110001e, 0x6b5d1fe3, -0x49a4fb10, 0x2b62fbc0, 0x52e085fb }, + { -0x5ab30d46, 0x124079ea, 0x001b26e7, -0x28db9a15, -0x36850803, 0x6843bcfd, 0x55eacd02, 0x0524b42b } + }, + { + { -0x647d6154, -0x43e72353, -0x4a0a8630, 0x23ae7d28, 0x69384233, -0x3cb9edd6, -0x182b5377, 0x1a6110b2 }, + { -0x1babb850, -0x02f2a242, 0x092005ee, 0x6cec351a, 0x567579cb, -0x665b87bc, 0x16e7fa45, 0x59d242a2 }, + { -0x19966854, 0x4f833f6a, 0x361839a4, 0x6849762a, -0x68f54adb, 0x6985dec1, -0x234e0aba, 0x53045e89 } + }, + { + { -0x72ba01ee, -0x7b25c322, -0x1bbb1d2e, -0x42bd3de8, 0x1f7e3598, -0x57ae6988, 0x5616e2b2, 0x7642c93f }, + { -0x28acac25, -0x34744cba, -0x51aee1de, -0x03034db5, -0x2af51911, -0x345b72c0, -0x0b0834a3, 0x26e3bae5 }, + { 0x4595f8e4, 0x2323daa7, -0x7a85414c, -0x21977375, 0x1c59326e, 0x3fc48e96, 0x15c9b8ba, 0x0b2e73ca } + }, + { + { 0x79c03a55, 0x0e3fbfaf, 0x4cbb5acf, 0x3077af05, -0x24c21c61, -0x2a3aadbb, 0x476a4af7, 0x015e68c1 }, + { -0x3e80afda, -0x2944bbd8, -0x04a56359, -0x614d8ddd, 0x1919c644, -0x1c845afd, -0x4a6599fe, 0x21ce380d }, + { 0x20066a38, -0x3e2ad7ae, 0x3570aef3, -0x6a9fc1ae, 0x226b8a4d, -0x7cd9a659, 0x1f8eedc9, 0x5dd68909 } + }, + { + { -0x5acecf7c, 0x1d022591, -0x29d8f78e, -0x35d2b552, 0x2f0bfd20, -0x795ed47b, -0x528258b8, 0x56e6c439 }, + { -0x402c37aa, -0x34537b22, -0x4ca00dbc, 0x1624c348, 0x5d9cad07, -0x48077236, -0x5d3d1418, 0x3b0e574d }, + { 0x42bdbae6, -0x38fb00b7, -0x4d21e087, 0x5e21ade2, 0x5652fad8, -0x16a24c0d, -0x70f7143f, 0x0822b537 } + }, +}, +{ + { + { 0x62730383, -0x1e480d6d, -0x143575d4, 0x4b5279ff, -0x402becec, -0x25038876, -0x638d9ef1, 0x7deb1014 }, + { -0x70c78b8b, 0x51f04847, -0x634134c4, -0x4da2430c, -0x2660dfab, -0x6554edbc, 0x1c10a5d6, 0x2c709e6c }, + { -0x78991186, -0x349d5096, 0x5553cd0e, 0x66cbec04, 0x0f0be4b5, 0x58800138, -0x09d31d16, 0x08e68e9f } + }, + { + { 0x0ab8f2f9, 0x2f2d09d5, -0x3aa6dc21, -0x5346de73, 0x73766cb9, 0x4a8f3426, 0x38f719f5, 0x4cb13bd7 }, + { 0x4bc130ad, 0x34ad500a, 0x3d0bd49c, -0x72c724b7, 0x500a89be, -0x5da3c268, -0x1145c4f7, 0x2f1f3f87 }, + { -0x1aea49b6, -0x087b738b, -0x24b56fc8, -0x5a6afe46, 0x3f751b50, -0x3df2cec1, -0x3f51d118, 0x19a1e353 } + }, + { + { -0x2a694243, -0x4bde8d33, -0x671103c0, -0x6c1fbabd, -0x4bbef64b, -0x604eacb9, 0x0266ae34, 0x736bd399 }, + { -0x4505fa3d, 0x7d1c7560, -0x391aa19f, -0x4c1e5f60, -0x3f299b8d, -0x1cad68e8, -0x3df3cb7a, 0x41546b11 }, + { -0x6ccb4c4c, -0x7aacd2b0, 0x60816573, 0x46fd114b, 0x425c8375, -0x33a0a0d0, -0x478054a4, 0x412295a2 } + }, + { + { -0x1d6c153a, 0x2e655261, 0x2133acdb, -0x7ba56dfd, 0x7900996b, 0x460975cb, 0x195add80, 0x0760bb8d }, + { -0x0a812917, 0x19c99b88, 0x6df8c825, 0x5393cb26, -0x4cf52d8d, 0x5cee3213, -0x4ad2d1cc, 0x14e153eb }, + { -0x32197e76, 0x413e1a17, -0x12965f7c, 0x57156da9, 0x46caccb1, 0x2cbf268f, -0x3cc53a0e, 0x6b34be9b } + }, + { + { 0x6571f2d3, 0x11fc6965, 0x530e737a, -0x393617bb, -0x2b01afcb, -0x1cc5185e, 0x2e6dd30b, 0x01b9c7b6 }, + { 0x3a78c0b2, -0x0c20d09c, -0x0dd1fd84, 0x4c3e971e, 0x49c1b5a3, -0x1382e3a2, 0x0922dd2d, 0x2012c18f }, + { 0x5ac89d29, -0x77f4aa1b, 0x45a0a763, 0x1483241f, -0x3d1893e1, 0x3d36efdf, 0x4e4bade8, 0x08af5b78 } + }, + { + { -0x7633d3b5, -0x1d8ceb2e, -0x5d78e873, 0x4be4bd11, -0x05cc9b32, 0x18d528d6, -0x50267d92, 0x6423c1d5 }, + { -0x77e0dacd, 0x283499dc, 0x779323b6, -0x62fada26, 0x673441f4, -0x76852205, 0x163a168d, 0x32b79d71 }, + { -0x12034c96, -0x337a0727, 0x3746e5f9, 0x22bcc28f, -0x061a2c33, -0x1b621cc8, -0x3ec1d234, 0x480a5efb } + }, + { + { 0x42ce221f, -0x499eb31c, 0x4c053928, 0x6e199dcc, -0x23e341fd, 0x663fb4a4, 0x691c8e06, 0x24b31d47 }, + { 0x01622071, 0x0b51e70b, -0x74e2503b, 0x06b505cf, -0x10a55433, 0x2c6bb061, 0x0cb7bf31, 0x47aa2760 }, + { -0x3fea073d, 0x2a541eed, 0x7c693f7c, 0x11a4fe7e, 0x4ea278d6, -0x0f5099ed, 0x14dda094, 0x545b585d } + }, + { + { -0x1c4cde1f, 0x6204e4d0, 0x28ff1e95, 0x3baa637a, 0x5b99bd9e, 0x0b0ccffd, 0x64c8d071, 0x4d22dc3e }, + { -0x5f2bc5f1, 0x67bf275e, 0x089beebe, -0x521971cc, -0x2b8618d2, 0x4289134c, 0x32ba5454, 0x0f62f9c3 }, + { -0x29c4a0c7, -0x034b9a77, 0x57cbcf61, 0x5cae6a3f, -0x6ac505fb, -0x01453d2e, 0x36371436, 0x1c0fa01a } + }, +}, +{ + { + { 0x54c53fae, -0x3ee11a18, 0x2b4f3ff4, 0x6a0b06c1, -0x1f49858e, 0x33540f80, -0x32f81c11, 0x15f18fc3 }, + { -0x4383296e, -0x18ab8bb7, -0x1908c221, 0x0f9abeaa, 0x00837e29, 0x4af01ca7, 0x3f1bc183, 0x63ab1b5d }, + { -0x4fd70b74, 0x32750763, 0x556a065f, 0x06020740, -0x3cb6a4a8, -0x2ac427ee, -0x79a0af73, 0x08706c9b } + }, + { + { 0x38b41246, -0x3366e4bf, 0x6f9ac26b, 0x243b9c52, -0x48345443, -0x4610b6b3, -0x2f7d1300, 0x5fba433d }, + { 0x3d343dff, -0x0c835d55, -0x7f5439e9, 0x1a8c6a2d, -0x2b330036, -0x71b61fcb, -0x455e2e47, 0x48b46bee }, + { -0x366be530, -0x63b61cab, 0x74498f84, -0x468cb522, 0x66663e5c, 0x41c3fed0, -0x1718ef4d, 0x0ecfedf8 } + }, + { + { -0x16bfc89e, 0x744f7463, -0x72033637, -0x08657212, 0x55e4cde3, 0x163a6496, -0x4d7b0bcb, 0x3b61788d }, + { -0x632b8f27, 0x76430f9f, -0x5bd09ff8, -0x49d53365, 0x59adad5e, 0x1898297c, -0x4873af80, 0x7789dd2d }, + { 0x0d6ef6b2, -0x4dddd7e7, 0x46ce4bfa, -0x56b5994e, 0x4f0b6cc7, 0x46c1a77a, -0x148cc731, 0x4236ccff } + }, + { + { -0x2588820a, 0x3bd82dbf, 0x0b98369e, 0x71b177cc, -0x7af3c967, 0x1d0e8463, 0x48e2d1f1, 0x5a71945b }, + { 0x0d55e274, -0x7b68bfb3, -0x3b52d4ad, 0x6c6663d9, -0x5256a8cc, -0x13d04f27, -0x324708c4, 0x2617e120 }, + { 0x405b4b42, 0x6f203dd5, 0x10b24509, 0x327ec604, -0x53d577ba, -0x63cb8dd0, 0x11ffeb6a, 0x77de29fc } + }, + { + { -0x13312d36, -0x7ca1ec71, -0x1569c466, -0x736150ed, -0x4de9f15a, -0x36a04040, -0x5278876e, 0x575e66f3 }, + { -0x7c488758, -0x4f53a837, -0x28016ed4, 0x53cdcca9, -0x00e0a624, 0x61c2b854, -0x0f218254, 0x3a1a2cf0 }, + { -0x377034c6, -0x667fc5d9, 0x275ec0b0, 0x345a6789, -0x0093d41b, 0x459789d0, 0x1e70a8b2, 0x62f88265 } + }, + { + { 0x698a19e0, 0x6d822986, 0x74d78a71, -0x2367de1f, -0x0934e0b9, 0x41a85f31, -0x432563af, 0x352721c2 }, + { 0x59ff1be4, 0x085ae2c7, 0x3b0e40b7, 0x149145c9, 0x7ff27379, -0x3b981806, -0x2a38c56b, 0x4eeecf0a }, + { 0x213fc985, 0x48329952, 0x368a1746, 0x1087cf0d, 0x66c15aa5, -0x71ad9e4f, 0x2ed24c21, 0x2d5b2d84 } + }, + { + { 0x196ac533, 0x5eb7d13d, -0x247f41d5, 0x377234ec, 0x7cf5ae24, -0x1ebb3004, -0x3bbe5314, 0x5226bcf9 }, + { -0x142c212f, 0x02cfebd9, 0x39021974, -0x2ba4de89, -0x01cf5e49, 0x7576f813, -0x5cb1093e, 0x5691b6f9 }, + { 0x23e5b547, 0x79ee6c72, -0x7ccf2987, 0x6f5f5076, 0x6d8adce9, -0x128c1e17, 0x1d8ccc03, 0x27c3da1e } + }, + { + { 0x630ef9f6, 0x28302e71, 0x2b64cee0, -0x3d2b5dfd, 0x4b6292be, 0x09082030, -0x57d520e8, 0x5fca747a }, + { 0x3fe24c74, 0x7eb9efb2, 0x1651be01, 0x3e50f49f, 0x21858dea, 0x3ea732dc, 0x5bb810f9, 0x17377bd7 }, + { 0x5c258ea5, 0x232a03c3, 0x6bcb0cf1, -0x790dc5d4, 0x2e442166, 0x3dad8d0d, -0x548979d5, 0x04a8933c } + }, +}, +{ + { + { -0x736c95b0, 0x69082b0e, -0x3e253a4a, -0x06365fcb, -0x3b2049cc, 0x6fb73e54, 0x1d2bc140, 0x4005419b }, + { 0x22943dff, -0x2d39fb4a, 0x44cfb3a0, -0x43734132, -0x687f7988, 0x5d254ff3, 0x3b1ca6bf, 0x0fa3614f }, + { -0x46417d10, -0x5ffc0143, 0x3a44ac90, 0x2089c1af, 0x1954fa8e, -0x07b6606f, -0x10bf54be, 0x1fba218a } + }, + { + { 0x3e7b0194, 0x4f3e5704, 0x08daaf7f, -0x57e2c112, -0x6623210f, -0x37c63955, -0x00889e2b, 0x6c535d13 }, + { -0x05370ac2, -0x54ab6bb8, 0x7ba63741, -0x7e091766, 0x6c2b5e01, 0x74fd6c7d, -0x573791be, 0x392e3aca }, + { 0x3e8a35af, 0x4cbd34e9, 0x5887e816, 0x2e078144, -0x0d654f55, 0x19319c76, -0x2af53ec5, 0x25e17fe4 } + }, + { + { 0x76f121a7, -0x6ea0800b, 0x2fcd87e3, -0x3cb5cdd9, 0x4d1be526, -0x3345d022, -0x76967665, 0x6bba828f }, + { 0x1e04f676, 0x0a289bd7, -0x29bdf06b, 0x208e1c52, 0x34691fab, 0x5186d8b0, 0x2a9fb351, 0x25575144 }, + { -0x6f01c6ff, -0x1d2e439a, -0x5f66852b, 0x4cb54a18, -0x507b9f2c, -0x68e296ec, 0x7f6b7be4, 0x559d504f } + }, + { + { -0x092d9903, -0x63b76e19, 0x0307781b, 0x0744a19b, 0x6061e23b, -0x77c770e3, 0x354bd50e, 0x123ea6a3 }, + { -0x4c14ab2b, -0x588c7c88, -0x5aaac384, 0x1d69d366, -0x06d7ff46, 0x0a26cf62, -0x7f81cde9, 0x01ab12d5 }, + { 0x41e32d96, 0x118d1890, -0x27cea7b8, -0x46121c3e, -0x27cdba27, 0x1eab4271, -0x36e75eac, 0x4a3961e2 } + }, + { + { -0x0cdcc0e2, 0x0327d644, 0x34fcf016, 0x499a260e, -0x0d254687, -0x7c4a58ea, -0x642beee1, 0x68aceead }, + { -0x07194460, 0x71dc3be0, 0x7effe30a, -0x293107cc, -0x1ec5b896, -0x566dbda1, -0x04e2489d, 0x2cd6bce3 }, + { -0x0c283df0, 0x38b4c90e, -0x4852fbf4, 0x308e6e24, -0x4818c1dd, 0x3860d9f1, -0x4af70a69, 0x595760d5 } + }, + { + { -0x02fdd870, -0x77d53415, -0x3beea8a0, -0x7650ccfb, 0x7d3473f4, 0x65f492e3, 0x54515a2b, 0x2cb2c5df }, + { 0x04aa6397, 0x6129bfe1, -0x5b580335, -0x7069fff8, 0x7d909458, 0x3f8bc089, -0x234d6e57, 0x709fa43e }, + { 0x63fd2aca, -0x14f5a274, 0x2e694eff, -0x2dd43e9a, -0x07344fc6, 0x2723f36e, -0x0f37ece1, 0x70f029ec } + }, + { + { 0x5e10b0b9, 0x2a6aafaa, -0x10fbe557, 0x78f0a370, -0x55c529e1, 0x773efb77, -0x58b4261f, 0x44eca5a2 }, + { 0x2eed3e33, 0x461307b3, -0x5baa7e19, -0x51fbd0cd, 0x195f0366, -0x36bbb62d, 0x6c314858, 0x0b7d5d8a }, + { 0x7b95d543, 0x25d44832, -0x5ccbf0e3, 0x70d38300, 0x60e1c52b, -0x21e3ace4, 0x2c7de9e4, 0x27222451 } + }, + { + { 0x42a975fc, -0x40844476, -0x69525ca8, -0x73a3c689, -0x321255b8, -0x1d803891, -0x0943df5a, 0x19735fd7 }, + { 0x49c5342e, 0x1abc92af, -0x4d190530, -0x001127ef, -0x0337b1d7, -0x105d7373, -0x5bb33abd, 0x11b5df18 }, + { 0x42c84266, -0x1c546f30, 0x7f19547e, -0x147b71f1, 0x65a497b9, 0x2503a1d0, -0x6e2076a1, 0x0fef9111 } + }, +}, +{ + { + { 0x5b1c16b7, 0x6ab5dcb8, 0x3c7b27a5, -0x6b3f0318, 0x735517be, -0x5b4ee3e6, -0x45f15056, 0x499238d0 }, + { -0x54e39147, -0x4eaf835f, 0x16b687b3, -0x42bb70c2, 0x2c7a91ab, 0x3455fb7f, 0x2f2adec1, 0x7579229e }, + { 0x7aba8b57, -0x130b91ae, -0x742e9b85, 0x15a08c47, 0x5f706fef, 0x7af1c6a6, -0x0fc5cf2b, 0x6345fa78 } + }, + { + { -0x42270f5c, -0x6c2c3417, -0x02e88cfe, -0x24ead3e5, 0x7f17a875, 0x7dbddc6d, -0x70bd9102, 0x3e1a71cc }, + { 0x1015e7a1, -0x20fd06a1, -0x564bfd9d, 0x790ec41d, 0x33ea1107, 0x4d3a0ea1, -0x1cc50737, 0x54f70be7 }, + { -0x6f45429e, -0x37c35c1d, 0x0291c833, -0x7f121c99, -0x2c86ff3c, -0x377fc734, 0x1ec31fa1, 0x2c5fc023 } + }, + { + { 0x02456e65, -0x3bdd1b2f, -0x352b846f, -0x78beb53f, -0x5d490023, 0x1592e2bb, -0x0a3deff1, 0x75d9d2bf }, + { 0x17038b4f, -0x01456ee9, -0x3621107f, -0x1aedc8df, 0x5d0d8834, 0x1c97e4e7, 0x23dc3bc6, 0x68afae7a }, + { 0x3626e81c, 0x5bd9b476, -0x435fd123, -0x766996ca, 0x61f077b3, 0x0a41193d, 0x00ce5471, 0x3097a242 } + }, + { + { 0x6695c486, -0x5e9d18dc, 0x35a89607, 0x131d6334, -0x5f2ed5c9, 0x30521561, -0x59504c9d, 0x56704bad }, + { -0x380747b4, 0x57427734, 0x01b270e9, -0x0ebe5ec2, -0x4b1a9b5a, 0x02d1adfe, -0x317c42b8, 0x4bb23d92 }, + { 0x52f912b9, -0x5093b559, -0x27988f38, 0x5e665f6c, -0x5c3732a8, 0x4c35ac83, 0x10a58a7e, 0x2b7a29c0 } + }, + { + { -0x40fff792, 0x33810a23, -0x18c90084, -0x50316da2, -0x1db6dd2c, 0x3d60e670, 0x4f96061b, 0x11ce9e71 }, + { -0x2f3e313d, -0x3bff8089, -0x453b6d08, -0x72efdf4a, 0x7e69daaf, 0x32ec29d5, -0x626a0320, 0x59940875 }, + { -0x27ea453f, 0x219ef713, 0x485be25c, -0x0ebeb9a3, 0x4e513c51, 0x6d5447cc, 0x5ef44393, 0x174926be } + }, + { + { -0x6c15fdd2, 0x3ef5d415, 0x0ed0eed6, 0x5cbcc1a2, 0x07382c8c, -0x702db131, 0x06d8e1ad, 0x6fa42ead }, + { -0x03a42a45, -0x4a214d07, -0x1e27ef1f, -0x6d2558d6, -0x48d5e3a7, -0x503b3024, 0x3fc22a24, 0x497d7881 }, + { 0x1f73371f, -0x1d897db6, 0x4f5b6736, 0x7f7cf01c, 0x04fa46e7, 0x7e201fe3, 0x57808c96, 0x785a36a3 } + }, + { + { 0x5d517bc3, 0x07044298, -0x519ac988, 0x6acd56c7, -0x67a5889d, 0x00a27983, -0x1aed99d5, 0x5167effa }, + { 0x63014d2b, -0x7da04203, 0x6ca7578b, -0x37adc964, 0x5c0b5df0, 0x5b2fcd28, 0x58048c8f, 0x12ab214c }, + { 0x0f53c4b6, -0x42b1561f, -0x7536e5ec, 0x1673dc5f, 0x2acc1aba, -0x5707e5b2, 0x24332a25, 0x33a92a79 } + }, + { + { 0x218f2ada, 0x7ba95ba0, 0x330fb9ca, -0x300bdd79, 0x56c6d907, -0x2525b693, -0x0b4111ac, 0x5380c296 }, + { 0x27996c02, -0x622e0b67, -0x1fb2e8ae, 0x0cb3b058, 0x7fd02c3e, 0x1f7e8896, -0x3474c14f, 0x2f964268 }, + { 0x66898d0a, -0x62b0d8fc, 0x0aff3f7a, 0x3d098799, 0x67daba45, -0x2f610c9e, 0x7b1c669c, 0x7761455e } + }, +}, +}; +#elif defined(CURVED25519_128BIT) +static const ge_precomp base[32][8] = { +{ + { + { 0x493c6f58c3b85, 0x0df7181c325f7, 0x0f50b0b3e4cb7, 0x5329385a44c32, 0x07cf9d3a33d4b }, + { 0x03905d740913e, 0x0ba2817d673a2, 0x23e2827f4e67c, 0x133d2e0c21a34, 0x44fd2f9298f81 }, + { 0x11205877aaa68, 0x479955893d579, 0x50d66309b67a0, 0x2d42d0dbee5ee, 0x6f117b689f0c6 }, + }, + { + { 0x4e7fc933c71d7, 0x2cf41feb6b244, 0x7581c0a7d1a76, 0x7172d534d32f0, 0x590c063fa87d2 }, + { 0x1a56042b4d5a8, 0x189cc159ed153, 0x5b8deaa3cae04, 0x2aaf04f11b5d8, 0x6bb595a669c92 }, + { 0x2a8b3a59b7a5f, 0x3abb359ef087f, 0x4f5a8c4db05af, 0x5b9a807d04205, 0x701af5b13ea50 }, + }, + { + { 0x5b0a84cee9730, 0x61d10c97155e4, 0x4059cc8096a10, 0x47a608da8014f, 0x7a164e1b9a80f }, + { 0x11fe8a4fcd265, 0x7bcb8374faacc, 0x52f5af4ef4d4f, 0x5314098f98d10, 0x2ab91587555bd }, + { 0x6933f0dd0d889, 0x44386bb4c4295, 0x3cb6d3162508c, 0x26368b872a2c6, 0x5a2826af12b9b }, + }, + { + { 0x351b98efc099f, 0x68fbfa4a7050e, 0x42a49959d971b, 0x393e51a469efd, 0x680e910321e58 }, + { 0x6050a056818bf, 0x62acc1f5532bf, 0x28141ccc9fa25, 0x24d61f471e683, 0x27933f4c7445a }, + { 0x3fbe9c476ff09, 0x0af6b982e4b42, 0x0ad1251ba78e5, 0x715aeedee7c88, 0x7f9d0cbf63553 }, + }, + { + { 0x2bc4408a5bb33, 0x078ebdda05442, 0x2ffb112354123, 0x375ee8df5862d, 0x2945ccf146e20 }, + { 0x182c3a447d6ba, 0x22964e536eff2, 0x192821f540053, 0x2f9f19e788e5c, 0x154a7e73eb1b5 }, + { 0x3dbf1812a8285, 0x0fa17ba3f9797, 0x6f69cb49c3820, 0x34d5a0db3858d, 0x43aabe696b3bb }, + }, + { + { 0x4eeeb77157131, 0x1201915f10741, 0x1669cda6c9c56, 0x45ec032db346d, 0x51e57bb6a2cc3 }, + { 0x006b67b7d8ca4, 0x084fa44e72933, 0x1154ee55d6f8a, 0x4425d842e7390, 0x38b64c41ae417 }, + { 0x4326702ea4b71, 0x06834376030b5, 0x0ef0512f9c380, 0x0f1a9f2512584, 0x10b8e91a9f0d6 }, + }, + { + { 0x25cd0944ea3bf, 0x75673b81a4d63, 0x150b925d1c0d4, 0x13f38d9294114, 0x461bea69283c9 }, + { 0x72c9aaa3221b1, 0x267774474f74d, 0x064b0e9b28085, 0x3f04ef53b27c9, 0x1d6edd5d2e531 }, + { 0x36dc801b8b3a2, 0x0e0a7d4935e30, 0x1deb7cecc0d7d, 0x053a94e20dd2c, 0x7a9fbb1c6a0f9 }, + }, + { + { 0x7596604dd3e8f, 0x6fc510e058b36, 0x3670c8db2cc0d, 0x297d899ce332f, 0x0915e76061bce }, + { 0x75dedf39234d9, 0x01c36ab1f3c54, 0x0f08fee58f5da, 0x0e19613a0d637, 0x3a9024a1320e0 }, + { 0x1f5d9c9a2911a, 0x7117994fafcf8, 0x2d8a8cae28dc5, 0x74ab1b2090c87, 0x26907c5c2ecc4 }, + }, +}, +{ + { + { 0x4dd0e632f9c1d, 0x2ced12622a5d9, 0x18de9614742da, 0x79ca96fdbb5d4, 0x6dd37d49a00ee }, + { 0x3635449aa515e, 0x3e178d0475dab, 0x50b4712a19712, 0x2dcc2860ff4ad, 0x30d76d6f03d31 }, + { 0x444172106e4c7, 0x01251afed2d88, 0x534fc9bed4f5a, 0x5d85a39cf5234, 0x10c697112e864 }, + }, + { + { 0x62aa08358c805, 0x46f440848e194, 0x447b771a8f52b, 0x377ba3269d31d, 0x03bf9baf55080 }, + { 0x3c4277dbe5fde, 0x5a335afd44c92, 0x0c1164099753e, 0x70487006fe423, 0x25e61cabed66f }, + { 0x3e128cc586604, 0x5968b2e8fc7e2, 0x049a3d5bd61cf, 0x116505b1ef6e6, 0x566d78634586e }, + }, + { + { 0x54285c65a2fd0, 0x55e62ccf87420, 0x46bb961b19044, 0x1153405712039, 0x14fba5f34793b }, + { 0x7a49f9cc10834, 0x2b513788a22c6, 0x5ff4b6ef2395b, 0x2ec8e5af607bf, 0x33975bca5ecc3 }, + { 0x746166985f7d4, 0x09939000ae79a, 0x5844c7964f97a, 0x13617e1f95b3d, 0x14829cea83fc5 }, + }, + { + { 0x70b2f4e71ecb8, 0x728148efc643c, 0x0753e03995b76, 0x5bf5fb2ab6767, 0x05fc3bc4535d7 }, + { 0x37b8497dd95c2, 0x61549d6b4ffe8, 0x217a22db1d138, 0x0b9cf062eb09e, 0x2fd9c71e5f758 }, + { 0x0b3ae52afdedd, 0x19da76619e497, 0x6fa0654d2558e, 0x78219d25e41d4, 0x373767475c651 }, + }, + { + { 0x095cb14246590, 0x002d82aa6ac68, 0x442f183bc4851, 0x6464f1c0a0644, 0x6bf5905730907 }, + { 0x299fd40d1add9, 0x5f2de9a04e5f7, 0x7c0eebacc1c59, 0x4cca1b1f8290a, 0x1fbea56c3b18f }, + { 0x778f1e1415b8a, 0x6f75874efc1f4, 0x28a694019027f, 0x52b37a96bdc4d, 0x02521cf67a635 }, + }, + { + { 0x46720772f5ee4, 0x632c0f359d622, 0x2b2092ba3e252, 0x662257c112680, 0x001753d9f7cd6 }, + { 0x7ee0b0a9d5294, 0x381fbeb4cca27, 0x7841f3a3e639d, 0x676ea30c3445f, 0x3fa00a7e71382 }, + { 0x1232d963ddb34, 0x35692e70b078d, 0x247ca14777a1f, 0x6db556be8fcd0, 0x12b5fe2fa048e }, + }, + { + { 0x37c26ad6f1e92, 0x46a0971227be5, 0x4722f0d2d9b4c, 0x3dc46204ee03a, 0x6f7e93c20796c }, + { 0x0fbc496fce34d, 0x575be6b7dae3e, 0x4a31585cee609, 0x037e9023930ff, 0x749b76f96fb12 }, + { 0x2f604aea6ae05, 0x637dc939323eb, 0x3fdad9b048d47, 0x0a8b0d4045af7, 0x0fcec10f01e02 }, + }, + { + { 0x2d29dc4244e45, 0x6927b1bc147be, 0x0308534ac0839, 0x4853664033f41, 0x413779166feab }, + { 0x558a649fe1e44, 0x44635aeefcc89, 0x1ff434887f2ba, 0x0f981220e2d44, 0x4901aa7183c51 }, + { 0x1b7548c1af8f0, 0x7848c53368116, 0x01b64e7383de9, 0x109fbb0587c8f, 0x41bb887b726d1 }, + }, +}, +{ + { + { 0x34c597c6691ae, 0x7a150b6990fc4, 0x52beb9d922274, 0x70eed7164861a, 0x0a871e070c6a9 }, + { 0x07d44744346be, 0x282b6a564a81d, 0x4ed80f875236b, 0x6fbbe1d450c50, 0x4eb728c12fcdb }, + { 0x1b5994bbc8989, 0x74b7ba84c0660, 0x75678f1cdaeb8, 0x23206b0d6f10c, 0x3ee7300f2685d }, + }, + { + { 0x27947841e7518, 0x32c7388dae87f, 0x414add3971be9, 0x01850832f0ef1, 0x7d47c6a2cfb89 }, + { 0x255e49e7dd6b7, 0x38c2163d59eba, 0x3861f2a005845, 0x2e11e4ccbaec9, 0x1381576297912 }, + { 0x2d0148ef0d6e0, 0x3522a8de787fb, 0x2ee055e74f9d2, 0x64038f6310813, 0x148cf58d34c9e }, + }, + { + { 0x72f7d9ae4756d, 0x7711e690ffc4a, 0x582a2355b0d16, 0x0dccfe885b6b4, 0x278febad4eaea }, + { 0x492f67934f027, 0x7ded0815528d4, 0x58461511a6612, 0x5ea2e50de1544, 0x3ff2fa1ebd5db }, + { 0x2681f8c933966, 0x3840521931635, 0x674f14a308652, 0x3bd9c88a94890, 0x4104dd02fe9c6 }, + }, + { + { 0x14e06db096ab8, 0x1219c89e6b024, 0x278abd486a2db, 0x240b292609520, 0x0165b5a48efca }, + { 0x2bf5e1124422a, 0x673146756ae56, 0x14ad99a87e830, 0x1eaca65b080fd, 0x2c863b00afaf5 }, + { 0x0a474a0846a76, 0x099a5ef981e32, 0x2a8ae3c4bbfe6, 0x45c34af14832c, 0x591b67d9bffec }, + }, + { + { 0x1b3719f18b55d, 0x754318c83d337, 0x27c17b7919797, 0x145b084089b61, 0x489b4f8670301 }, + { 0x70d1c80b49bfa, 0x3d57e7d914625, 0x3c0722165e545, 0x5e5b93819e04f, 0x3de02ec7ca8f7 }, + { 0x2102d3aeb92ef, 0x68c22d50c3a46, 0x42ea89385894e, 0x75f9ebf55f38c, 0x49f5fbba496cb }, + }, + { + { 0x5628c1e9c572e, 0x598b108e822ab, 0x55d8fae29361a, 0x0adc8d1a97b28, 0x06a1a6c288675 }, + { 0x49a108a5bcfd4, 0x6178c8e7d6612, 0x1f03473710375, 0x73a49614a6098, 0x5604a86dcbfa6 }, + { 0x0d1d47c1764b6, 0x01c08316a2e51, 0x2b3db45c95045, 0x1634f818d300c, 0x20989e89fe274 }, + }, + { + { 0x4278b85eaec2e, 0x0ef59657be2ce, 0x72fd169588770, 0x2e9b205260b30, 0x730b9950f7059 }, + { 0x777fd3a2dcc7f, 0x594a9fb124932, 0x01f8e80ca15f0, 0x714d13cec3269, 0x0403ed1d0ca67 }, + { 0x32d35874ec552, 0x1f3048df1b929, 0x300d73b179b23, 0x6e67be5a37d0b, 0x5bd7454308303 }, + }, + { + { 0x4932115e7792a, 0x457b9bbb930b8, 0x68f5d8b193226, 0x4164e8f1ed456, 0x5bb7db123067f }, + { 0x2d19528b24cc2, 0x4ac66b8302ff3, 0x701c8d9fdad51, 0x6c1b35c5b3727, 0x133a78007380a }, + { 0x1f467c6ca62be, 0x2c4232a5dc12c, 0x7551dc013b087, 0x0690c11b03bcd, 0x740dca6d58f0e }, + }, +}, +{ + { + { 0x28c570478433c, 0x1d8502873a463, 0x7641e7eded49c, 0x1ecedd54cf571, 0x2c03f5256c2b0 }, + { 0x0ee0752cfce4e, 0x660dd8116fbe9, 0x55167130fffeb, 0x1c682b885955c, 0x161d25fa963ea }, + { 0x718757b53a47d, 0x619e18b0f2f21, 0x5fbdfe4c1ec04, 0x5d798c81ebb92, 0x699468bdbd96b }, + }, + { + { 0x53de66aa91948, 0x045f81a599b1b, 0x3f7a8bd214193, 0x71d4da412331a, 0x293e1c4e6c4a2 }, + { 0x72f46f4dafecf, 0x2948ffadef7a3, 0x11ecdfdf3bc04, 0x3c2e98ffeed25, 0x525219a473905 }, + { 0x6134b925112e1, 0x6bb942bb406ed, 0x070c445c0dde2, 0x411d822c4d7a3, 0x5b605c447f032 }, + }, + { + { 0x1fec6f0e7f04c, 0x3cebc692c477d, 0x077986a19a95e, 0x6eaaaa1778b0f, 0x2f12fef4cc5ab }, + { 0x5805920c47c89, 0x1924771f9972c, 0x38bbddf9fc040, 0x1f7000092b281, 0x24a76dcea8aeb }, + { 0x522b2dfc0c740, 0x7e8193480e148, 0x33fd9a04341b9, 0x3c863678a20bc, 0x5e607b2518a43 }, + }, + { + { 0x4431ca596cf14, 0x015da7c801405, 0x03c9b6f8f10b5, 0x0346922934017, 0x201f33139e457 }, + { 0x31d8f6cdf1818, 0x1f86c4b144b16, 0x39875b8d73e9d, 0x2fbf0d9ffa7b3, 0x5067acab6ccdd }, + { 0x27f6b08039d51, 0x4802f8000dfaa, 0x09692a062c525, 0x1baea91075817, 0x397cba8862460 }, + }, + { + { 0x5c3fbc81379e7, 0x41bbc255e2f02, 0x6a3f756998650, 0x1297fd4e07c42, 0x771b4022c1e1c }, + { 0x13093f05959b2, 0x1bd352f2ec618, 0x075789b88ea86, 0x61d1117ea48b9, 0x2339d320766e6 }, + { 0x5d986513a2fa7, 0x63f3a99e11b0f, 0x28a0ecfd6b26d, 0x53b6835e18d8f, 0x331a189219971 }, + }, + { + { 0x12f3a9d7572af, 0x10d00e953c4ca, 0x603df116f2f8a, 0x33dc276e0e088, 0x1ac9619ff649a }, + { 0x66f45fb4f80c6, 0x3cc38eeb9fea2, 0x107647270db1f, 0x710f1ea740dc8, 0x31167c6b83bdf }, + { 0x33842524b1068, 0x77dd39d30fe45, 0x189432141a0d0, 0x088fe4eb8c225, 0x612436341f08b }, + }, + { + { 0x349e31a2d2638, 0x0137a7fa6b16c, 0x681ae92777edc, 0x222bfc5f8dc51, 0x1522aa3178d90 }, + { 0x541db874e898d, 0x62d80fb841b33, 0x03e6ef027fa97, 0x7a03c9e9633e8, 0x46ebe2309e5ef }, + { 0x02f5369614938, 0x356e5ada20587, 0x11bc89f6bf902, 0x036746419c8db, 0x45fe70f505243 }, + }, + { + { 0x24920c8951491, 0x107ec61944c5e, 0x72752e017c01f, 0x122b7dda2e97a, 0x16619f6db57a2 }, + { 0x075a6960c0b8c, 0x6dde1c5e41b49, 0x42e3f516da341, 0x16a03fda8e79e, 0x428d1623a0e39 }, + { 0x74a4401a308fd, 0x06ed4b9558109, 0x746f1f6a08867, 0x4636f5c6f2321, 0x1d81592d60bd3 }, + }, +}, +{ + { + { 0x5b69f7b85c5e8, 0x17a2d175650ec, 0x4cc3e6dbfc19e, 0x73e1d3873be0e, 0x3a5f6d51b0af8 }, + { 0x68756a60dac5f, 0x55d757b8aec26, 0x3383df45f80bd, 0x6783f8c9f96a6, 0x20234a7789ecd }, + { 0x20db67178b252, 0x73aa3da2c0eda, 0x79045c01c70d3, 0x1b37b15251059, 0x7cd682353cffe }, + }, + { + { 0x5cd6068acf4f3, 0x3079afc7a74cc, 0x58097650b64b4, 0x47fabac9c4e99, 0x3ef0253b2b2cd }, + { 0x1a45bd887fab6, 0x65748076dc17c, 0x5b98000aa11a8, 0x4a1ecc9080974, 0x2838c8863bdc0 }, + { 0x3b0cf4a465030, 0x022b8aef57a2d, 0x2ad0677e925ad, 0x4094167d7457a, 0x21dcb8a606a82 }, + }, + { + { 0x500fabe7731ba, 0x7cc53c3113351, 0x7cf65fe080d81, 0x3c5d966011ba1, 0x5d840dbf6c6f6 }, + { 0x004468c9d9fc8, 0x5da8554796b8c, 0x3b8be70950025, 0x6d5892da6a609, 0x0bc3d08194a31 }, + { 0x6380d309fe18b, 0x4d73c2cb8ee0d, 0x6b882adbac0b6, 0x36eabdddd4cbe, 0x3a4276232ac19 }, + }, + { + { 0x0c172db447ecb, 0x3f8c505b7a77f, 0x6a857f97f3f10, 0x4fcc0567fe03a, 0x0770c9e824e1a }, + { 0x2432c8a7084fa, 0x47bf73ca8a968, 0x1639176262867, 0x5e8df4f8010ce, 0x1ff177cea16de }, + { 0x1d99a45b5b5fd, 0x523674f2499ec, 0x0f8fa26182613, 0x58f7398048c98, 0x39f264fd41500 }, + }, + { + { 0x34aabfe097be1, 0x43bfc03253a33, 0x29bc7fe91b7f3, 0x0a761e4844a16, 0x65c621272c35f }, + { 0x53417dbe7e29c, 0x54573827394f5, 0x565eea6f650dd, 0x42050748dc749, 0x1712d73468889 }, + { 0x389f8ce3193dd, 0x2d424b8177ce5, 0x073fa0d3440cd, 0x139020cd49e97, 0x22f9800ab19ce }, + }, + { + { 0x29fdd9a6efdac, 0x7c694a9282840, 0x6f7cdeee44b3a, 0x55a3207b25cc3, 0x4171a4d38598c }, + { 0x2368a3e9ef8cb, 0x454aa08e2ac0b, 0x490923f8fa700, 0x372aa9ea4582f, 0x13f416cd64762 }, + { 0x758aa99c94c8c, 0x5f6001700ff44, 0x7694e488c01bd, 0x0d5fde948eed6, 0x508214fa574bd }, + }, + { + { 0x215bb53d003d6, 0x1179e792ca8c3, 0x1a0e96ac840a2, 0x22393e2bb3ab6, 0x3a7758a4c86cb }, + { 0x269153ed6fe4b, 0x72a23aef89840, 0x052be5299699c, 0x3a5e5ef132316, 0x22f960ec6faba }, + { 0x111f693ae5076, 0x3e3bfaa94ca90, 0x445799476b887, 0x24a0912464879, 0x5d9fd15f8de7f }, + }, + { + { 0x44d2aeed7521e, 0x50865d2c2a7e4, 0x2705b5238ea40, 0x46c70b25d3b97, 0x3bc187fa47eb9 }, + { 0x408d36d63727f, 0x5faf8f6a66062, 0x2bb892da8de6b, 0x769d4f0c7e2e6, 0x332f35914f8fb }, + { 0x70115ea86c20c, 0x16d88da24ada8, 0x1980622662adf, 0x501ebbc195a9d, 0x450d81ce906fb }, + }, +}, +{ + { + { 0x4d8961cae743f, 0x6bdc38c7dba0e, 0x7d3b4a7e1b463, 0x0844bdee2adf3, 0x4cbad279663ab }, + { 0x3b6a1a6205275, 0x2e82791d06dcf, 0x23d72caa93c87, 0x5f0b7ab68aaf4, 0x2de25d4ba6345 }, + { 0x19024a0d71fcd, 0x15f65115f101a, 0x4e99067149708, 0x119d8d1cba5af, 0x7d7fbcefe2007 }, + }, + { + { 0x45dc5f3c29094, 0x3455220b579af, 0x070c1631e068a, 0x26bc0630e9b21, 0x4f9cd196dcd8d }, + { 0x71e6a266b2801, 0x09aae73e2df5d, 0x40dd8b219b1a3, 0x546fb4517de0d, 0x5975435e87b75 }, + { 0x297d86a7b3768, 0x4835a2f4c6332, 0x070305f434160, 0x183dd014e56ae, 0x7ccdd084387a0 }, + }, + { + { 0x484186760cc93, 0x7435665533361, 0x02f686336b801, 0x5225446f64331, 0x3593ca848190c }, + { 0x6422c6d260417, 0x212904817bb94, 0x5a319deb854f5, 0x7a9d4e060da7d, 0x428bd0ed61d0c }, + { 0x3189a5e849aa7, 0x6acbb1f59b242, 0x7f6ef4753630c, 0x1f346292a2da9, 0x27398308da2d6 }, + }, + { + { 0x10e4c0a702453, 0x4daafa37bd734, 0x49f6bdc3e8961, 0x1feffdcecdae6, 0x572c2945492c3 }, + { 0x38d28435ed413, 0x4064f19992858, 0x7680fbef543cd, 0x1aadd83d58d3c, 0x269597aebe8c3 }, + { 0x7c745d6cd30be, 0x27c7755df78ef, 0x1776833937fa3, 0x5405116441855, 0x7f985498c05bc }, + }, + { + { 0x615520fbf6363, 0x0b9e9bf74da6a, 0x4fe8308201169, 0x173f76127de43, 0x30f2653cd69b1 }, + { 0x1ce889f0be117, 0x36f6a94510709, 0x7f248720016b4, 0x1821ed1e1cf91, 0x76c2ec470a31f }, + { 0x0c938aac10c85, 0x41b64ed797141, 0x1beb1c1185e6d, 0x1ed5490600f07, 0x2f1273f159647 }, + }, + { + { 0x08bd755a70bc0, 0x49e3a885ce609, 0x16585881b5ad6, 0x3c27568d34f5e, 0x38ac1997edc5f }, + { 0x1fc7c8ae01e11, 0x2094d5573e8e7, 0x5ca3cbbf549d2, 0x4f920ecc54143, 0x5d9e572ad85b6 }, + { 0x6b517a751b13b, 0x0cfd370b180cc, 0x5377925d1f41a, 0x34e56566008a2, 0x22dfcd9cbfe9e }, + }, + { + { 0x459b4103be0a1, 0x59a4b3f2d2add, 0x7d734c8bb8eeb, 0x2393cbe594a09, 0x0fe9877824cde }, + { 0x3d2e0c30d0cd9, 0x3f597686671bb, 0x0aa587eb63999, 0x0e3c7b592c619, 0x6b2916c05448c }, + { 0x334d10aba913b, 0x045cdb581cfdb, 0x5e3e0553a8f36, 0x50bb3041effb2, 0x4c303f307ff00 }, + }, + { + { 0x403580dd94500, 0x48df77d92653f, 0x38a9fe3b349ea, 0x0ea89850aafe1, 0x416b151ab706a }, + { 0x23bd617b28c85, 0x6e72ee77d5a61, 0x1a972ff174dde, 0x3e2636373c60f, 0x0d61b8f78b2ab }, + { 0x0d7efe9c136b0, 0x1ab1c89640ad5, 0x55f82aef41f97, 0x46957f317ed0d, 0x191a2af74277e }, + }, +}, +{ + { + { 0x62b434f460efb, 0x294c6c0fad3fc, 0x68368937b4c0f, 0x5c9f82910875b, 0x237e7dbe00545 }, + { 0x6f74bc53c1431, 0x1c40e5dbbd9c2, 0x6c8fb9cae5c97, 0x4845c5ce1b7da, 0x7e2e0e450b5cc }, + { 0x575ed6701b430, 0x4d3e17fa20026, 0x791fc888c4253, 0x2f1ba99078ac1, 0x71afa699b1115 }, + }, + { + { 0x23c1c473b50d6, 0x3e7671de21d48, 0x326fa5547a1e8, 0x50e4dc25fafd9, 0x00731fbc78f89 }, + { 0x66f9b3953b61d, 0x555f4283cccb9, 0x7dd67fb1960e7, 0x14707a1affed4, 0x021142e9c2b1c }, + { 0x0c71848f81880, 0x44bd9d8233c86, 0x6e8578efe5830, 0x4045b6d7041b5, 0x4c4d6f3347e15 }, + }, + { + { 0x4ddfc988f1970, 0x4f6173ea365e1, 0x645daf9ae4588, 0x7d43763db623b, 0x38bf9500a88f9 }, + { 0x7eccfc17d1fc9, 0x4ca280782831e, 0x7b8337db1d7d6, 0x5116def3895fb, 0x193fddaaa7e47 }, + { 0x2c93c37e8876f, 0x3431a28c583fa, 0x49049da8bd879, 0x4b4a8407ac11c, 0x6a6fb99ebf0d4 }, + }, + { + { 0x122b5b6e423c6, 0x21e50dff1ddd6, 0x73d76324e75c0, 0x588485495418e, 0x136fda9f42c5e }, + { 0x6c1bb560855eb, 0x71f127e13ad48, 0x5c6b304905aec, 0x3756b8e889bc7, 0x75f76914a3189 }, + { 0x4dfb1a305bdd1, 0x3b3ff05811f29, 0x6ed62283cd92e, 0x65d1543ec52e1, 0x022183510be8d }, + }, + { + { 0x2710143307a7f, 0x3d88fb48bf3ab, 0x249eb4ec18f7a, 0x136115dff295f, 0x1387c441fd404 }, + { 0x766385ead2d14, 0x0194f8b06095e, 0x08478f6823b62, 0x6018689d37308, 0x6a071ce17b806 }, + { 0x3c3d187978af8, 0x7afe1c88276ba, 0x51df281c8ad68, 0x64906bda4245d, 0x3171b26aaf1ed }, + }, + { + { 0x5b7d8b28a47d1, 0x2c2ee149e34c1, 0x776f5629afc53, 0x1f4ea50fc49a9, 0x6c514a6334424 }, + { 0x7319097564ca8, 0x1844ebc233525, 0x21d4543fdeee1, 0x1ad27aaff1bd2, 0x221fd4873cf08 }, + { 0x2204f3a156341, 0x537414065a464, 0x43c0c3bedcf83, 0x5557e706ea620, 0x48daa596fb924 }, + }, + { + { 0x61d5dc84c9793, 0x47de83040c29e, 0x189deb26507e7, 0x4d4e6fadc479a, 0x58c837fa0e8a7 }, + { 0x28e665ca59cc7, 0x165c715940dd9, 0x0785f3aa11c95, 0x57b98d7e38469, 0x676dd6fccad84 }, + { 0x1688596fc9058, 0x66f6ad403619f, 0x4d759a87772ef, 0x7856e6173bea4, 0x1c4f73f2c6a57 }, + }, + { + { 0x6706efc7c3484, 0x6987839ec366d, 0x0731f95cf7f26, 0x3ae758ebce4bc, 0x70459adb7daf6 }, + { 0x24fbd305fa0bb, 0x40a98cc75a1cf, 0x78ce1220a7533, 0x6217a10e1c197, 0x795ac80d1bf64 }, + { 0x1db4991b42bb3, 0x469605b994372, 0x631e3715c9a58, 0x7e9cfefcf728f, 0x5fe162848ce21 }, + }, +}, +{ + { + { 0x1852d5d7cb208, 0x60d0fbe5ce50f, 0x5a1e246e37b75, 0x51aee05ffd590, 0x2b44c043677da }, + { 0x1214fe194961a, 0x0e1ae39a9e9cb, 0x543c8b526f9f7, 0x119498067e91d, 0x4789d446fc917 }, + { 0x487ab074eb78e, 0x1d33b5e8ce343, 0x13e419feb1b46, 0x2721f565de6a4, 0x60c52eef2bb9a }, + }, + { + { 0x3c5c27cae6d11, 0x36a9491956e05, 0x124bac9131da6, 0x3b6f7de202b5d, 0x70d77248d9b66 }, + { 0x589bc3bfd8bf1, 0x6f93e6aa3416b, 0x4c0a3d6c1ae48, 0x55587260b586a, 0x10bc9c312ccfc }, + { 0x2e84b3ec2a05b, 0x69da2f03c1551, 0x23a174661a67b, 0x209bca289f238, 0x63755bd3a976f }, + }, + { + { 0x7101897f1acb7, 0x3d82cb77b07b8, 0x684083d7769f5, 0x52b28472dce07, 0x2763751737c52 }, + { 0x7a03e2ad10853, 0x213dcc6ad36ab, 0x1a6e240d5bdd6, 0x7c24ffcf8fedf, 0x0d8cc1c48bc16 }, + { 0x402d36eb419a9, 0x7cef68c14a052, 0x0f1255bc2d139, 0x373e7d431186a, 0x70c2dd8a7ad16 }, + }, + { + { 0x4967db8ed7e13, 0x15aeed02f523a, 0x6149591d094bc, 0x672f204c17006, 0x32b8613816a53 }, + { 0x194509f6fec0e, 0x528d8ca31acac, 0x7826d73b8b9fa, 0x24acb99e0f9b3, 0x2e0fac6363948 }, + { 0x7f7bee448cd64, 0x4e10f10da0f3c, 0x3936cb9ab20e9, 0x7a0fc4fea6cd0, 0x4179215c735a4 }, + }, + { + { 0x633b9286bcd34, 0x6cab3badb9c95, 0x74e387edfbdfa, 0x14313c58a0fd9, 0x31fa85662241c }, + { 0x094e7d7dced2a, 0x068fa738e118e, 0x41b640a5fee2b, 0x6bb709df019d4, 0x700344a30cd99 }, + { 0x26c422e3622f4, 0x0f3066a05b5f0, 0x4e2448f0480a6, 0x244cde0dbf095, 0x24bb2312a9952 }, + }, + { + { 0x00c2af5f85c6b, 0x0609f4cf2883f, 0x6e86eb5a1ca13, 0x68b44a2efccd1, 0x0d1d2af9ffeb5 }, + { 0x0ed1732de67c3, 0x308c369291635, 0x33ef348f2d250, 0x004475ea1a1bb, 0x0fee3e871e188 }, + { 0x28aa132621edf, 0x42b244caf353b, 0x66b064cc2e08a, 0x6bb20020cbdd3, 0x16acd79718531 }, + }, + { + { 0x1c6c57887b6ad, 0x5abf21fd7592b, 0x50bd41253867a, 0x3800b71273151, 0x164ed34b18161 }, + { 0x772af2d9b1d3d, 0x6d486448b4e5b, 0x2ce58dd8d18a8, 0x1849f67503c8b, 0x123e0ef6b9302 }, + { 0x6d94c192fe69a, 0x5475222a2690f, 0x693789d86b8b3, 0x1f5c3bdfb69dc, 0x78da0fc61073f }, + }, + { + { 0x780f1680c3a94, 0x2a35d3cfcd453, 0x005e5cdc7ddf8, 0x6ee888078ac24, 0x054aa4b316b38 }, + { 0x15d28e52bc66a, 0x30e1e0351cb7e, 0x30a2f74b11f8c, 0x39d120cd7de03, 0x2d25deeb256b1 }, + { 0x0468d19267cb8, 0x38cdca9b5fbf9, 0x1bbb05c2ca1e2, 0x3b015758e9533, 0x134610a6ab7da }, + }, +}, +{ + { + { 0x265e777d1f515, 0x0f1f54c1e39a5, 0x2f01b95522646, 0x4fdd8db9dde6d, 0x654878cba97cc }, + { 0x38ec78df6b0fe, 0x13caebea36a22, 0x5ebc6e54e5f6a, 0x32804903d0eb8, 0x2102fdba2b20d }, + { 0x6e405055ce6a1, 0x5024a35a532d3, 0x1f69054daf29d, 0x15d1d0d7a8bd5, 0x0ad725db29ecb }, + }, + { + { 0x7bc0c9b056f85, 0x51cfebffaffd8, 0x44abbe94df549, 0x7ecbbd7e33121, 0x4f675f5302399 }, + { 0x267b1834e2457, 0x6ae19c378bb88, 0x7457b5ed9d512, 0x3280d783d05fb, 0x4aefcffb71a03 }, + { 0x536360415171e, 0x2313309077865, 0x251444334afbc, 0x2b0c3853756e8, 0x0bccbb72a2a86 }, + }, + { + { 0x55e4c50fe1296, 0x05fdd13efc30d, 0x1c0c6c380e5ee, 0x3e11de3fb62a8, 0x6678fd69108f3 }, + { 0x6962feab1a9c8, 0x6aca28fb9a30b, 0x56db7ca1b9f98, 0x39f58497018dd, 0x4024f0ab59d6b }, + { 0x6fa31636863c2, 0x10ae5a67e42b0, 0x27abbf01fda31, 0x380a7b9e64fbc, 0x2d42e2108ead4 }, + }, + { + { 0x17b0d0f537593, 0x16263c0c9842e, 0x4ab827e4539a4, 0x6370ddb43d73a, 0x420bf3a79b423 }, + { 0x5131594dfd29b, 0x3a627e98d52fe, 0x1154041855661, 0x19175d09f8384, 0x676b2608b8d2d }, + { 0x0ba651c5b2b47, 0x5862363701027, 0x0c4d6c219c6db, 0x0f03dff8658de, 0x745d2ffa9c0cf }, + }, + { + { 0x6df5721d34e6a, 0x4f32f767a0c06, 0x1d5abeac76e20, 0x41ce9e104e1e4, 0x06e15be54c1dc }, + { 0x25a1e2bc9c8bd, 0x104c8f3b037ea, 0x405576fa96c98, 0x2e86a88e3876f, 0x1ae23ceb960cf }, + { 0x25d871932994a, 0x6b9d63b560b6e, 0x2df2814c8d472, 0x0fbbee20aa4ed, 0x58ded861278ec }, + }, + { + { 0x35ba8b6c2c9a8, 0x1dea58b3185bf, 0x4b455cd23bbbe, 0x5ec19c04883f8, 0x08ba696b531d5 }, + { 0x73793f266c55c, 0x0b988a9c93b02, 0x09b0ea32325db, 0x37cae71c17c5e, 0x2ff39de85485f }, + { 0x53eeec3efc57a, 0x2fa9fe9022efd, 0x699c72c138154, 0x72a751ebd1ff8, 0x120633b4947cf }, + }, + { + { 0x531474912100a, 0x5afcdf7c0d057, 0x7a9e71b788ded, 0x5ef708f3b0c88, 0x07433be3cb393 }, + { 0x4987891610042, 0x79d9d7f5d0172, 0x3c293013b9ec4, 0x0c2b85f39caca, 0x35d30a99b4d59 }, + { 0x144c05ce997f4, 0x4960b8a347fef, 0x1da11f15d74f7, 0x54fac19c0fead, 0x2d873ede7af6d }, + }, + { + { 0x202e14e5df981, 0x2ea02bc3eb54c, 0x38875b2883564, 0x1298c513ae9dd, 0x0543618a01600 }, + { 0x2316443373409, 0x5de95503b22af, 0x699201beae2df, 0x3db5849ff737a, 0x2e773654707fa }, + { 0x2bdf4974c23c1, 0x4b3b9c8d261bd, 0x26ae8b2a9bc28, 0x3068210165c51, 0x4b1443362d079 }, + }, +}, +{ + { + { 0x454e91c529ccb, 0x24c98c6bf72cf, 0x0486594c3d89a, 0x7ae13a3d7fa3c, 0x17038418eaf66 }, + { 0x4b7c7b66e1f7a, 0x4bea185efd998, 0x4fabc711055f8, 0x1fb9f7836fe38, 0x582f446752da6 }, + { 0x17bd320324ce4, 0x51489117898c6, 0x1684d92a0410b, 0x6e4d90f78c5a7, 0x0c2a1c4bcda28 }, + }, + { + { 0x4814869bd6945, 0x7b7c391a45db8, 0x57316ac35b641, 0x641e31de9096a, 0x5a6a9b30a314d }, + { 0x5c7d06f1f0447, 0x7db70f80b3a49, 0x6cb4a3ec89a78, 0x43be8ad81397d, 0x7c558bd1c6f64 }, + { 0x41524d396463d, 0x1586b449e1a1d, 0x2f17e904aed8a, 0x7e1d2861d3c8e, 0x0404a5ca0afba }, + }, + { + { 0x49e1b2a416fd1, 0x51c6a0b316c57, 0x575a59ed71bdc, 0x74c021a1fec1e, 0x39527516e7f8e }, + { 0x740070aa743d6, 0x16b64cbdd1183, 0x23f4b7b32eb43, 0x319aba58235b3, 0x46395bfdcadd9 }, + { 0x7db2d1a5d9a9c, 0x79a200b85422f, 0x355bfaa71dd16, 0x00b77ea5f78aa, 0x76579a29e822d }, + }, + { + { 0x4b51352b434f2, 0x1327bd01c2667, 0x434d73b60c8a1, 0x3e0daa89443ba, 0x02c514bb2a277 }, + { 0x68e7e49c02a17, 0x45795346fe8b6, 0x089306c8f3546, 0x6d89f6b2f88f6, 0x43a384dc9e05b }, + { 0x3d5da8bf1b645, 0x7ded6a96a6d09, 0x6c3494fee2f4d, 0x02c989c8b6bd4, 0x1160920961548 }, + }, + { + { 0x05616369b4dcd, 0x4ecab86ac6f47, 0x3c60085d700b2, 0x0213ee10dfcea, 0x2f637d7491e6e }, + { 0x5166929dacfaa, 0x190826b31f689, 0x4f55567694a7d, 0x705f4f7b1e522, 0x351e125bc5698 }, + { 0x49b461af67bbe, 0x75915712c3a96, 0x69a67ef580c0d, 0x54d38ef70cffc, 0x7f182d06e7ce2 }, + }, + { + { 0x54b728e217522, 0x69a90971b0128, 0x51a40f2a963a3, 0x10be9ac12a6bf, 0x44acc043241c5 }, + { 0x48e64ab0168ec, 0x2a2bdb8a86f4f, 0x7343b6b2d6929, 0x1d804aa8ce9a3, 0x67d4ac8c343e9 }, + { 0x56bbb4f7a5777, 0x29230627c238f, 0x5ad1a122cd7fb, 0x0dea56e50e364, 0x556d1c8312ad7 }, + }, + { + { 0x06756b11be821, 0x462147e7bb03e, 0x26519743ebfe0, 0x782fc59682ab5, 0x097abe38cc8c7 }, + { 0x740e30c8d3982, 0x7c2b47f4682fd, 0x5cd91b8c7dc1c, 0x77fa790f9e583, 0x746c6c6d1d824 }, + { 0x1c9877ea52da4, 0x2b37b83a86189, 0x733af49310da5, 0x25e81161c04fb, 0x577e14a34bee8 }, + }, + { + { 0x6cebebd4dd72b, 0x340c1e442329f, 0x32347ffd1a93f, 0x14a89252cbbe0, 0x705304b8fb009 }, + { 0x268ac61a73b0a, 0x206f234bebe1c, 0x5b403a7cbebe8, 0x7a160f09f4135, 0x60fa7ee96fd78 }, + { 0x51d354d296ec6, 0x7cbf5a63b16c7, 0x2f50bb3cf0c14, 0x1feb385cac65a, 0x21398e0ca1635 }, + }, +}, +{ + { + { 0x0aaf9b4b75601, 0x26b91b5ae44f3, 0x6de808d7ab1c8, 0x6a769675530b0, 0x1bbfb284e98f7 }, + { 0x5058a382b33f3, 0x175a91816913e, 0x4f6cdb96b8ae8, 0x17347c9da81d2, 0x5aa3ed9d95a23 }, + { 0x777e9c7d96561, 0x28e58f006ccac, 0x541bbbb2cac49, 0x3e63282994cec, 0x4a07e14e5e895 }, + }, + { + { 0x358cdc477a49b, 0x3cc88fe02e481, 0x721aab7f4e36b, 0x0408cc9469953, 0x50af7aed84afa }, + { 0x412cb980df999, 0x5e78dd8ee29dc, 0x171dff68c575d, 0x2015dd2f6ef49, 0x3f0bac391d313 }, + { 0x7de0115f65be5, 0x4242c21364dc9, 0x6b75b64a66098, 0x0033c0102c085, 0x1921a316baebd }, + }, + { + { 0x2ad9ad9f3c18b, 0x5ec1638339aeb, 0x5703b6559a83b, 0x3fa9f4d05d612, 0x7b049deca062c }, + { 0x22f7edfb870fc, 0x569eed677b128, 0x30937dcb0a5af, 0x758039c78ea1b, 0x6458df41e273a }, + { 0x3e37a35444483, 0x661fdb7d27b99, 0x317761dd621e4, 0x7323c30026189, 0x6093dccbc2950 }, + }, + { + { 0x6eebe6084034b, 0x6cf01f70a8d7b, 0x0b41a54c6670a, 0x6c84b99bb55db, 0x6e3180c98b647 }, + { 0x39a8585e0706d, 0x3167ce72663fe, 0x63d14ecdb4297, 0x4be21dcf970b8, 0x57d1ea084827a }, + { 0x2b6e7a128b071, 0x5b27511755dcf, 0x08584c2930565, 0x68c7bda6f4159, 0x363e999ddd97b }, + }, + { + { 0x048dce24baec6, 0x2b75795ec05e3, 0x3bfa4c5da6dc9, 0x1aac8659e371e, 0x231f979bc6f9b }, + { 0x043c135ee1fc4, 0x2a11c9919f2d5, 0x6334cc25dbacd, 0x295da17b400da, 0x48ee9b78693a0 }, + { 0x1de4bcc2af3c6, 0x61fc411a3eb86, 0x53ed19ac12ec0, 0x209dbc6b804e0, 0x079bfa9b08792 }, + }, + { + { 0x1ed80a2d54245, 0x70efec72a5e79, 0x42151d42a822d, 0x1b5ebb6d631e8, 0x1ef4fb1594706 }, + { 0x03a51da300df4, 0x467b52b561c72, 0x4d5920210e590, 0x0ca769e789685, 0x038c77f684817 }, + { 0x65ee65b167bec, 0x052da19b850a9, 0x0408665656429, 0x7ab39596f9a4c, 0x575ee92a4a0bf }, + }, + { + { 0x6bc450aa4d801, 0x4f4a6773b0ba8, 0x6241b0b0ebc48, 0x40d9c4f1d9315, 0x200a1e7e382f5 }, + { 0x080908a182fcf, 0x0532913b7ba98, 0x3dccf78c385c3, 0x68002dd5eaba9, 0x43d4e7112cd3f }, + { 0x5b967eaf93ac5, 0x360acca580a31, 0x1c65fd5c6f262, 0x71c7f15c2ecab, 0x050eca52651e4 }, + }, + { + { 0x4397660e668ea, 0x7c2a75692f2f5, 0x3b29e7e6c66ef, 0x72ba658bcda9a, 0x6151c09fa131a }, + { 0x31ade453f0c9c, 0x3dfee07737868, 0x611ecf7a7d411, 0x2637e6cbd64f6, 0x4b0ee6c21c58f }, + { 0x55c0dfdf05d96, 0x405569dcf475e, 0x05c5c277498bb, 0x18588d95dc389, 0x1fef24fa800f0 }, + }, +}, +{ + { + { 0x2aff530976b86, 0x0d85a48c0845a, 0x796eb963642e0, 0x60bee50c4b626, 0x28005fe6c8340 }, + { 0x653fb1aa73196, 0x607faec8306fa, 0x4e85ec83e5254, 0x09f56900584fd, 0x544d49292fc86 }, + { 0x7ba9f34528688, 0x284a20fb42d5d, 0x3652cd9706ffe, 0x6fd7baddde6b3, 0x72e472930f316 }, + }, + { + { 0x3f635d32a7627, 0x0cbecacde00fe, 0x3411141eaa936, 0x21c1e42f3cb94, 0x1fee7f000fe06 }, + { 0x5208c9781084f, 0x16468a1dc24d2, 0x7bf780ac540a8, 0x1a67eced75301, 0x5a9d2e8c2733a }, + { 0x305da03dbf7e5, 0x1228699b7aeca, 0x12a23b2936bc9, 0x2a1bda56ae6e9, 0x00f94051ee040 }, + }, + { + { 0x793bb07af9753, 0x1e7b6ecd4fafd, 0x02c7b1560fb43, 0x2296734cc5fb7, 0x47b7ffd25dd40 }, + { 0x56b23c3d330b2, 0x37608e360d1a6, 0x10ae0f3c8722e, 0x086d9b618b637, 0x07d79c7e8beab }, + { 0x3fb9cbc08dd12, 0x75c3dd85370ff, 0x47f06fe2819ac, 0x5db06ab9215ed, 0x1c3520a35ea64 }, + }, + { + { 0x06f40216bc059, 0x3a2579b0fd9b5, 0x71c26407eec8c, 0x72ada4ab54f0b, 0x38750c3b66d12 }, + { 0x253a6bccba34a, 0x427070433701a, 0x20b8e58f9870e, 0x337c861db00cc, 0x1c3d05775d0ee }, + { 0x6f1409422e51a, 0x7856bbece2d25, 0x13380a72f031c, 0x43e1080a7f3ba, 0x0621e2c7d3304 }, + }, + { + { 0x61796b0dbf0f3, 0x73c2f9c32d6f5, 0x6aa8ed1537ebe, 0x74e92c91838f4, 0x5d8e589ca1002 }, + { 0x060cc8259838d, 0x038d3f35b95f3, 0x56078c243a923, 0x2de3293241bb2, 0x0007d6097bd3a }, + { 0x71d950842a94b, 0x46b11e5c7d817, 0x5478bbecb4f0d, 0x7c3054b0a1c5d, 0x1583d7783c1cb }, + }, + { + { 0x34704cc9d28c7, 0x3dee598b1f200, 0x16e1c98746d9e, 0x4050b7095afdf, 0x4958064e83c55 }, + { 0x6a2ef5da27ae1, 0x28aace02e9d9d, 0x02459e965f0e8, 0x7b864d3150933, 0x252a5f2e81ed8 }, + { 0x094265066e80d, 0x0a60f918d61a5, 0x0444bf7f30fde, 0x1c40da9ed3c06, 0x079c170bd843b }, + }, + { + { 0x6cd50c0d5d056, 0x5b7606ae779ba, 0x70fbd226bdda1, 0x5661e53391ff9, 0x6768c0d7317b8 }, + { 0x6ece464fa6fff, 0x3cc40bca460a0, 0x6e3a90afb8d0c, 0x5801abca11228, 0x6dec05e34ac9f }, + { 0x625e5f155c1b3, 0x4f32f6f723296, 0x5ac980105efce, 0x17a61165eee36, 0x51445e14ddcd5 }, + }, + { + { 0x147ab2bbea455, 0x1f240f2253126, 0x0c3de9e314e89, 0x21ea5a4fca45f, 0x12e990086e4fd }, + { 0x02b4b3b144951, 0x5688977966aea, 0x18e176e399ffd, 0x2e45c5eb4938b, 0x13186f31e3929 }, + { 0x496b37fdfbb2e, 0x3c2439d5f3e21, 0x16e60fe7e6a4d, 0x4d7ef889b621d, 0x77b2e3f05d3e9 }, + }, +}, +{ + { + { 0x0639c12ddb0a4, 0x6180490cd7ab3, 0x3f3918297467c, 0x74568be1781ac, 0x07a195152e095 }, + { 0x7a9c59c2ec4de, 0x7e9f09e79652d, 0x6a3e422f22d86, 0x2ae8e3b836c8b, 0x63b795fc7ad32 }, + { 0x68f02389e5fc8, 0x059f1bc877506, 0x504990e410cec, 0x09bd7d0feaee2, 0x3e8fe83d032f0 }, + }, + { + { 0x04c8de8efd13c, 0x1c67c06e6210e, 0x183378f7f146a, 0x64352ceaed289, 0x22d60899a6258 }, + { 0x315b90570a294, 0x60ce108a925f1, 0x6eff61253c909, 0x003ef0e2d70b0, 0x75ba3b797fac4 }, + { 0x1dbc070cdd196, 0x16d8fb1534c47, 0x500498183fa2a, 0x72f59c423de75, 0x0904d07b87779 }, + }, + { + { 0x22d6648f940b9, 0x197a5a1873e86, 0x207e4c41a54bc, 0x5360b3b4bd6d0, 0x6240aacebaf72 }, + { 0x61fd4ddba919c, 0x7d8e991b55699, 0x61b31473cc76c, 0x7039631e631d6, 0x43e2143fbc1dd }, + { 0x4749c5ba295a0, 0x37946fa4b5f06, 0x724c5ab5a51f1, 0x65633789dd3f3, 0x56bdaf238db40 }, + }, + { + { 0x0d36cc19d3bb2, 0x6ec4470d72262, 0x6853d7018a9ae, 0x3aa3e4dc2c8eb, 0x03aa31507e1e5 }, + { 0x2b9e3f53533eb, 0x2add727a806c5, 0x56955c8ce15a3, 0x18c4f070a290e, 0x1d24a86d83741 }, + { 0x47648ffd4ce1f, 0x60a9591839e9d, 0x424d5f38117ab, 0x42cc46912c10e, 0x43b261dc9aeb4 }, + }, + { + { 0x13d8b6c951364, 0x4c0017e8f632a, 0x53e559e53f9c4, 0x4b20146886eea, 0x02b4d5e242940 }, + { 0x31e1988bb79bb, 0x7b82f46b3bcab, 0x0f7a8ce827b41, 0x5e15816177130, 0x326055cf5b276 }, + { 0x155cb28d18df2, 0x0c30d9ca11694, 0x2090e27ab3119, 0x208624e7a49b6, 0x27a6c809ae5d3 }, + }, + { + { 0x4270ac43d6954, 0x2ed4cd95659a5, 0x75c0db37528f9, 0x2ccbcfd2c9234, 0x221503603d8c2 }, + { 0x6ebcd1f0db188, 0x74ceb4b7d1174, 0x7d56168df4f5c, 0x0bf79176fd18a, 0x2cb67174ff60a }, + { 0x6cdf9390be1d0, 0x08e519c7e2b3d, 0x253c3d2a50881, 0x21b41448e333d, 0x7b1df4b73890f }, + }, + { + { 0x6221807f8f58c, 0x3fa92813a8be5, 0x6da98c38d5572, 0x01ed95554468f, 0x68698245d352e }, + { 0x2f2e0b3b2a224, 0x0c56aa22c1c92, 0x5fdec39f1b278, 0x4c90af5c7f106, 0x61fcef2658fc5 }, + { 0x15d852a18187a, 0x270dbb59afb76, 0x7db120bcf92ab, 0x0e7a25d714087, 0x46cf4c473daf0 }, + }, + { + { 0x46ea7f1498140, 0x70725690a8427, 0x0a73ae9f079fb, 0x2dd924461c62b, 0x1065aae50d8cc }, + { 0x525ed9ec4e5f9, 0x022d20660684c, 0x7972b70397b68, 0x7a03958d3f965, 0x29387bcd14eb5 }, + { 0x44525df200d57, 0x2d7f94ce94385, 0x60d00c170ecb7, 0x38b0503f3d8f0, 0x69a198e64f1ce }, + }, +}, +{ + { + { 0x14434dcc5caed, 0x2c7909f667c20, 0x61a839d1fb576, 0x4f23800cabb76, 0x25b2697bd267f }, + { 0x2b2e0d91a78bc, 0x3990a12ccf20c, 0x141c2e11f2622, 0x0dfcefaa53320, 0x7369e6a92493a }, + { 0x73ffb13986864, 0x3282bb8f713ac, 0x49ced78f297ef, 0x6697027661def, 0x1420683db54e4 }, + }, + { + { 0x6bb6fc1cc5ad0, 0x532c8d591669d, 0x1af794da86c33, 0x0e0e9d86d24d3, 0x31e83b4161d08 }, + { 0x0bd1e249dd197, 0x00bcb1820568f, 0x2eab1718830d4, 0x396fd816997e6, 0x60b63bebf508a }, + { 0x0c7129e062b4f, 0x1e526415b12fd, 0x461a0fd27923d, 0x18badf670a5b7, 0x55cf1eb62d550 }, + }, + { + { 0x6b5e37df58c52, 0x3bcf33986c60e, 0x44fb8835ceae7, 0x099dec18e71a4, 0x1a56fbaa62ba0 }, + { 0x1101065c23d58, 0x5aa1290338b0f, 0x3157e9e2e7421, 0x0ea712017d489, 0x669a656457089 }, + { 0x66b505c9dc9ec, 0x774ef86e35287, 0x4d1d944c0955e, 0x52e4c39d72b20, 0x13c4836799c58 }, + }, + { + { 0x4fb6a5d8bd080, 0x58ae34908589b, 0x3954d977baf13, 0x413ea597441dc, 0x50bdc87dc8e5b }, + { 0x25d465ab3e1b9, 0x0f8fe27ec2847, 0x2d6e6dbf04f06, 0x3038cfc1b3276, 0x66f80c93a637b }, + { 0x537836edfe111, 0x2be02357b2c0d, 0x6dcee58c8d4f8, 0x2d732581d6192, 0x1dd56444725fd }, + }, + { + { 0x7e60008bac89a, 0x23d5c387c1852, 0x79e5df1f533a8, 0x2e6f9f1c5f0cf, 0x3a3a450f63a30 }, + { 0x47ff83362127d, 0x08e39af82b1f4, 0x488322ef27dab, 0x1973738a2a1a4, 0x0e645912219f7 }, + { 0x72f31d8394627, 0x07bd294a200f1, 0x665be00e274c6, 0x43de8f1b6368b, 0x318c8d9393a9a }, + }, + { + { 0x69e29ab1dd398, 0x30685b3c76bac, 0x565cf37f24859, 0x57b2ac28efef9, 0x509a41c325950 }, + { 0x45d032afffe19, 0x12fe49b6cde4e, 0x21663bc327cf1, 0x18a5e4c69f1dd, 0x224c7c679a1d5 }, + { 0x06edca6f925e9, 0x68c8363e677b8, 0x60cfa25e4fbcf, 0x1c4c17609404e, 0x05bff02328a11 }, + }, + { + { 0x1a0dd0dc512e4, 0x10894bf5fcd10, 0x52949013f9c37, 0x1f50fba4735c7, 0x576277cdee01a }, + { 0x2137023cae00b, 0x15a3599eb26c6, 0x0687221512b3c, 0x253cb3a0824e9, 0x780b8cc3fa2a4 }, + { 0x38abc234f305f, 0x7a280bbc103de, 0x398a836695dfe, 0x3d0af41528a1a, 0x5ff418726271b }, + }, + { + { 0x347e813b69540, 0x76864c21c3cbb, 0x1e049dbcd74a8, 0x5b4d60f93749c, 0x29d4db8ca0a0c }, + { 0x6080c1789db9d, 0x4be7cef1ea731, 0x2f40d769d8080, 0x35f7d4c44a603, 0x106a03dc25a96 }, + { 0x50aaf333353d0, 0x4b59a613cbb35, 0x223dfc0e19a76, 0x77d1e2bb2c564, 0x4ab38a51052cb }, + }, +}, +{ + { + { 0x7d1ef5fddc09c, 0x7beeaebb9dad9, 0x058d30ba0acfb, 0x5cd92eab5ae90, 0x3041c6bb04ed2 }, + { 0x42b256768d593, 0x2e88459427b4f, 0x02b3876630701, 0x34878d405eae5, 0x29cdd1adc088a }, + { 0x2f2f9d956e148, 0x6b3e6ad65c1fe, 0x5b00972b79e5d, 0x53d8d234c5daf, 0x104bbd6814049 }, + }, + { + { 0x59a5fd67ff163, 0x3a998ead0352b, 0x083c95fa4af9a, 0x6fadbfc01266f, 0x204f2a20fb072 }, + { 0x0fd3168f1ed67, 0x1bb0de7784a3e, 0x34bcb78b20477, 0x0a4a26e2e2182, 0x5be8cc57092a7 }, + { 0x43b3d30ebb079, 0x357aca5c61902, 0x5b570c5d62455, 0x30fb29e1e18c7, 0x2570fb17c2791 }, + }, + { + { 0x6a9550bb8245a, 0x511f20a1a2325, 0x29324d7239bee, 0x3343cc37516c4, 0x241c5f91de018 }, + { 0x2367f2cb61575, 0x6c39ac04d87df, 0x6d4958bd7e5bd, 0x566f4638a1532, 0x3dcb65ea53030 }, + { 0x0172940de6caa, 0x6045b2e67451b, 0x56c07463efcb3, 0x0728b6bfe6e91, 0x08420edd5fcdf }, + }, + { + { 0x0c34e04f410ce, 0x344edc0d0a06b, 0x6e45486d84d6d, 0x44e2ecb3863f5, 0x04d654f321db8 }, + { 0x720ab8362fa4a, 0x29c4347cdd9bf, 0x0e798ad5f8463, 0x4fef18bcb0bfe, 0x0d9a53efbc176 }, + { 0x5c116ddbdb5d5, 0x6d1b4bba5abcf, 0x4d28a48a5537a, 0x56b8e5b040b99, 0x4a7a4f2618991 }, + }, + { + { 0x3b291af372a4b, 0x60e3028fe4498, 0x2267bca4f6a09, 0x719eec242b243, 0x4a96314223e0e }, + { 0x718025fb15f95, 0x68d6b8371fe94, 0x3804448f7d97c, 0x42466fe784280, 0x11b50c4cddd31 }, + { 0x0274408a4ffd6, 0x7d382aedb34dd, 0x40acfc9ce385d, 0x628bb99a45b1e, 0x4f4bce4dce6bc }, + }, + { + { 0x2616ec49d0b6f, 0x1f95d8462e61c, 0x1ad3e9b9159c6, 0x79ba475a04df9, 0x3042cee561595 }, + { 0x7ce5ae2242584, 0x2d25eb153d4e3, 0x3a8f3d09ba9c9, 0x0f3690d04eb8e, 0x73fcdd14b71c0 }, + { 0x67079449bac41, 0x5b79c4621484f, 0x61069f2156b8d, 0x0eb26573b10af, 0x389e740c9a9ce }, + }, + { + { 0x578f6570eac28, 0x644f2339c3937, 0x66e47b7956c2c, 0x34832fe1f55d0, 0x25c425e5d6263 }, + { 0x4b3ae34dcb9ce, 0x47c691a15ac9f, 0x318e06e5d400c, 0x3c422d9f83eb1, 0x61545379465a6 }, + { 0x606a6f1d7de6e, 0x4f1c0c46107e7, 0x229b1dcfbe5d8, 0x3acc60a7b1327, 0x6539a08915484 }, + }, + { + { 0x4dbd414bb4a19, 0x7930849f1dbb8, 0x329c5a466caf0, 0x6c824544feb9b, 0x0f65320ef019b }, + { 0x21f74c3d2f773, 0x024b88d08bd3a, 0x6e678cf054151, 0x43631272e747c, 0x11c5e4aac5cd1 }, + { 0x6d1b1cafde0c6, 0x462c76a303a90, 0x3ca4e693cff9b, 0x3952cd45786fd, 0x4cabc7bdec330 }, + }, +}, +{ + { + { 0x7788f3f78d289, 0x5942809b3f811, 0x5973277f8c29c, 0x010f93bc5fe67, 0x7ee498165acb2 }, + { 0x69624089c0a2e, 0x0075fc8e70473, 0x13e84ab1d2313, 0x2c10bedf6953b, 0x639b93f0321c8 }, + { 0x508e39111a1c3, 0x290120e912f7a, 0x1cbf464acae43, 0x15373e9576157, 0x0edf493c85b60 }, + }, + { + { 0x7c4d284764113, 0x7fefebf06acec, 0x39afb7a824100, 0x1b48e47e7fd65, 0x04c00c54d1dfa }, + { 0x48158599b5a68, 0x1fd75bc41d5d9, 0x2d9fc1fa95d3c, 0x7da27f20eba11, 0x403b92e3019d4 }, + { 0x22f818b465cf8, 0x342901dff09b8, 0x31f595dc683cd, 0x37a57745fd682, 0x355bb12ab2617 }, + }, + { + { 0x1dac75a8c7318, 0x3b679d5423460, 0x6b8fcb7b6400e, 0x6c73783be5f9d, 0x7518eaf8e052a }, + { 0x664cc7493bbf4, 0x33d94761874e3, 0x0179e1796f613, 0x1890535e2867d, 0x0f9b8132182ec }, + { 0x059c41b7f6c32, 0x79e8706531491, 0x6c747643cb582, 0x2e20c0ad494e4, 0x47c3871bbb175 }, + }, + { + { 0x65d50c85066b0, 0x6167453361f7c, 0x06ba3818bb312, 0x6aff29baa7522, 0x08fea02ce8d48 }, + { 0x4539771ec4f48, 0x7b9318badca28, 0x70f19afe016c5, 0x4ee7bb1608d23, 0x00b89b8576469 }, + { 0x5dd7668deead0, 0x4096d0ba47049, 0x6275997219114, 0x29bda8a67e6ae, 0x473829a74f75d }, + }, + { + { 0x1533aad3902c9, 0x1dde06b11e47b, 0x784bed1930b77, 0x1c80a92b9c867, 0x6c668b4d44e4d }, + { 0x2da754679c418, 0x3164c31be105a, 0x11fac2b98ef5f, 0x35a1aaf779256, 0x2078684c4833c }, + { 0x0cf217a78820c, 0x65024e7d2e769, 0x23bb5efdda82a, 0x19fd4b632d3c6, 0x7411a6054f8a4 }, + }, + { + { 0x2e53d18b175b4, 0x33e7254204af3, 0x3bcd7d5a1c4c5, 0x4c7c22af65d0f, 0x1ec9a872458c3 }, + { 0x59d32b99dc86d, 0x6ac075e22a9ac, 0x30b9220113371, 0x27fd9a638966e, 0x7c136574fb813 }, + { 0x6a4d400a2509b, 0x041791056971c, 0x655d5866e075c, 0x2302bf3e64df8, 0x3add88a5c7cd6 }, + }, + { + { 0x298d459393046, 0x30bfecb3d90b8, 0x3d9b8ea3df8d6, 0x3900e96511579, 0x61ba1131a406a }, + { 0x15770b635dcf2, 0x59ecd83f79571, 0x2db461c0b7fbd, 0x73a42a981345f, 0x249929fccc879 }, + { 0x0a0f116959029, 0x5974fd7b1347a, 0x1e0cc1c08edad, 0x673bdf8ad1f13, 0x5620310cbbd8e }, + }, + { + { 0x6b5f477e285d6, 0x4ed91ec326cc8, 0x6d6537503a3fd, 0x626d3763988d5, 0x7ec846f3658ce }, + { 0x193434934d643, 0x0d4a2445eaa51, 0x7d0708ae76fe0, 0x39847b6c3c7e1, 0x37676a2a4d9d9 }, + { 0x68f3f1da22ec7, 0x6ed8039a2736b, 0x2627ee04c3c75, 0x6ea90a647e7d1, 0x6daaf723399b9 }, + }, +}, +{ + { + { 0x304bfacad8ea2, 0x502917d108b07, 0x043176ca6dd0f, 0x5d5158f2c1d84, 0x2b5449e58eb3b }, + { 0x27562eb3dbe47, 0x291d7b4170be7, 0x5d1ca67dfa8e1, 0x2a88061f298a2, 0x1304e9e71627d }, + { 0x014d26adc9cfe, 0x7f1691ba16f13, 0x5e71828f06eac, 0x349ed07f0fffc, 0x4468de2d7c2dd }, + }, + { + { 0x2d8c6f86307ce, 0x6286ba1850973, 0x5e9dcb08444d4, 0x1a96a543362b2, 0x5da6427e63247 }, + { 0x3355e9419469e, 0x1847bb8ea8a37, 0x1fe6588cf9b71, 0x6b1c9d2db6b22, 0x6cce7c6ffb44b }, + { 0x4c688deac22ca, 0x6f775c3ff0352, 0x565603ee419bb, 0x6544456c61c46, 0x58f29abfe79f2 }, + }, + { + { 0x264bf710ecdf6, 0x708c58527896b, 0x42ceae6c53394, 0x4381b21e82b6a, 0x6af93724185b4 }, + { 0x6cfab8de73e68, 0x3e6efced4bd21, 0x0056609500dbe, 0x71b7824ad85df, 0x577629c4a7f41 }, + { 0x0024509c6a888, 0x2696ab12e6644, 0x0cca27f4b80d8, 0x0c7c1f11b119e, 0x701f25bb0caec }, + }, + { + { 0x0f6d97cbec113, 0x4ce97fb7c93a3, 0x139835a11281b, 0x728907ada9156, 0x720a5bc050955 }, + { 0x0b0f8e4616ced, 0x1d3c4b50fb875, 0x2f29673dc0198, 0x5f4b0f1830ffa, 0x2e0c92bfbdc40 }, + { 0x709439b805a35, 0x6ec48557f8187, 0x08a4d1ba13a2c, 0x076348a0bf9ae, 0x0e9b9cbb144ef }, + }, + { + { 0x69bd55db1beee, 0x6e14e47f731bd, 0x1a35e47270eac, 0x66f225478df8e, 0x366d44191cfd3 }, + { 0x2d48ffb5720ad, 0x57b7f21a1df77, 0x5550effba0645, 0x5ec6a4098a931, 0x221104eb3f337 }, + { 0x41743f2bc8c14, 0x796b0ad8773c7, 0x29fee5cbb689b, 0x122665c178734, 0x4167a4e6bc593 }, + }, + { + { 0x62665f8ce8fee, 0x29d101ac59857, 0x4d93bbba59ffc, 0x17b7897373f17, 0x34b33370cb7ed }, + { 0x39d2876f62700, 0x001cecd1d6c87, 0x7f01a11747675, 0x2350da5a18190, 0x7938bb7e22552 }, + { 0x591ee8681d6cc, 0x39db0b4ea79b8, 0x202220f380842, 0x2f276ba42e0ac, 0x1176fc6e2dfe6 }, + }, + { + { 0x0e28949770eb8, 0x5559e88147b72, 0x35e1e6e63ef30, 0x35b109aa7ff6f, 0x1f6a3e54f2690 }, + { 0x76cd05b9c619b, 0x69654b0901695, 0x7a53710b77f27, 0x79a1ea7d28175, 0x08fc3a4c677d5 }, + { 0x4c199d30734ea, 0x6c622cb9acc14, 0x5660a55030216, 0x068f1199f11fb, 0x4f2fad0116b90 }, + }, + { + { 0x4d91db73bb638, 0x55f82538112c5, 0x6d85a279815de, 0x740b7b0cd9cf9, 0x3451995f2944e }, + { 0x6b24194ae4e54, 0x2230afded8897, 0x23412617d5071, 0x3d5d30f35969b, 0x445484a4972ef }, + { 0x2fcd09fea7d7c, 0x296126b9ed22a, 0x4a171012a05b2, 0x1db92c74d5523, 0x10b89ca604289 }, + }, +}, +{ + { + { 0x141be5a45f06e, 0x5adb38becaea7, 0x3fd46db41f2bb, 0x6d488bbb5ce39, 0x17d2d1d9ef0d4 }, + { 0x147499718289c, 0x0a48a67e4c7ab, 0x30fbc544bafe3, 0x0c701315fe58a, 0x20b878d577b75 }, + { 0x2af18073f3e6a, 0x33aea420d24fe, 0x298008bf4ff94, 0x3539171db961e, 0x72214f63cc65c }, + }, + { + { 0x5b7b9f43b29c9, 0x149ea31eea3b3, 0x4be7713581609, 0x2d87960395e98, 0x1f24ac855a154 }, + { 0x37f405307a693, 0x2e5e66cf2b69c, 0x5d84266ae9c53, 0x5e4eb7de853b9, 0x5fdf48c58171c }, + { 0x608328e9505aa, 0x22182841dc49a, 0x3ec96891d2307, 0x2f363fff22e03, 0x00ba739e2ae39 }, + }, + { + { 0x426f5ea88bb26, 0x33092e77f75c8, 0x1a53940d819e7, 0x1132e4f818613, 0x72297de7d518d }, + { 0x698de5c8790d6, 0x268b8545beb25, 0x6d2648b96fedf, 0x47988ad1db07c, 0x03283a3e67ad7 }, + { 0x41dc7be0cb939, 0x1b16c66100904, 0x0a24c20cbc66d, 0x4a2e9efe48681, 0x05e1296846271 }, + }, + { + { 0x7bbc8242c4550, 0x59a06103b35b7, 0x7237e4af32033, 0x726421ab3537a, 0x78cf25d38258c }, + { 0x2eeb32d9c495a, 0x79e25772f9750, 0x6d747833bbf23, 0x6cdd816d5d749, 0x39c00c9c13698 }, + { 0x66b8e31489d68, 0x573857e10e2b5, 0x13be816aa1472, 0x41964d3ad4bf8, 0x006b52076b3ff }, + }, + { + { 0x37e16b9ce082d, 0x1882f57853eb9, 0x7d29eacd01fc5, 0x2e76a59b5e715, 0x7de2e9561a9f7 }, + { 0x0cfe19d95781c, 0x312cc621c453c, 0x145ace6da077c, 0x0912bef9ce9b8, 0x4d57e3443bc76 }, + { 0x0d4f4b6a55ecb, 0x7ebb0bb733bce, 0x7ba6a05200549, 0x4f6ede4e22069, 0x6b2a90af1a602 }, + }, + { + { 0x3f3245bb2d80a, 0x0e5f720f36efd, 0x3b9cccf60c06d, 0x084e323f37926, 0x465812c8276c2 }, + { 0x3f4fc9ae61e97, 0x3bc07ebfa2d24, 0x3b744b55cd4a0, 0x72553b25721f3, 0x5fd8f4e9d12d3 }, + { 0x3beb22a1062d9, 0x6a7063b82c9a8, 0x0a5a35dc197ed, 0x3c80c06a53def, 0x05b32c2b1cb16 }, + }, + { + { 0x4a42c7ad58195, 0x5c8667e799eff, 0x02e5e74c850a1, 0x3f0db614e869a, 0x31771a4856730 }, + { 0x05eccd24da8fd, 0x580bbfdf07918, 0x7e73586873c6a, 0x74ceddf77f93e, 0x3b5556a37b471 }, + { 0x0c524e14dd482, 0x283457496c656, 0x0ad6bcfb6cd45, 0x375d1e8b02414, 0x4fc079d27a733 }, + }, + { + { 0x48b440c86c50d, 0x139929cca3b86, 0x0f8f2e44cdf2f, 0x68432117ba6b2, 0x241170c2bae3c }, + { 0x138b089bf2f7f, 0x4a05bfd34ea39, 0x203914c925ef5, 0x7497fffe04e3c, 0x124567cecaf98 }, + { 0x1ab860ac473b4, 0x5c0227c86a7ff, 0x71b12bfc24477, 0x006a573a83075, 0x3f8612966c870 }, + }, +}, +{ + { + { 0x0fcfa36048d13, 0x66e7133bbb383, 0x64b42a8a45676, 0x4ea6e4f9a85cf, 0x26f57eee878a1 }, + { 0x20cc9782a0dde, 0x65d4e3070aab3, 0x7bc8e31547736, 0x09ebfb1432d98, 0x504aa77679736 }, + { 0x32cd55687efb1, 0x4448f5e2f6195, 0x568919d460345, 0x034c2e0ad1a27, 0x4041943d9dba3 }, + }, + { + { 0x17743a26caadd, 0x48c9156f9c964, 0x7ef278d1e9ad0, 0x00ce58ea7bd01, 0x12d931429800d }, + { 0x0eeba43ebcc96, 0x384dd5395f878, 0x1df331a35d272, 0x207ecfd4af70e, 0x1420a1d976843 }, + { 0x67799d337594f, 0x01647548f6018, 0x57fce5578f145, 0x009220c142a71, 0x1b4f92314359a }, + }, + { + { 0x73030a49866b1, 0x2442be90b2679, 0x77bd3d8947dcf, 0x1fb55c1552028, 0x5ff191d56f9a2 }, + { 0x4109d89150951, 0x225bd2d2d47cb, 0x57cc080e73bea, 0x6d71075721fcb, 0x239b572a7f132 }, + { 0x6d433ac2d9068, 0x72bf930a47033, 0x64facf4a20ead, 0x365f7a2b9402a, 0x020c526a758f3 }, + }, + { + { 0x1ef59f042cc89, 0x3b1c24976dd26, 0x31d665cb16272, 0x28656e470c557, 0x452cfe0a5602c }, + { 0x034f89ed8dbbc, 0x73b8f948d8ef3, 0x786c1d323caab, 0x43bd4a9266e51, 0x02aacc4615313 }, + { 0x0f7a0647877df, 0x4e1cc0f93f0d4, 0x7ec4726ef1190, 0x3bdd58bf512f8, 0x4cfb7d7b304b8 }, + }, + { + { 0x699c29789ef12, 0x63beae321bc50, 0x325c340adbb35, 0x562e1a1e42bf6, 0x5b1d4cbc434d3 }, + { 0x43d6cb89b75fe, 0x3338d5b900e56, 0x38d327d531a53, 0x1b25c61d51b9f, 0x14b4622b39075 }, + { 0x32615cc0a9f26, 0x57711b99cb6df, 0x5a69c14e93c38, 0x6e88980a4c599, 0x2f98f71258592 }, + }, + { + { 0x2ae444f54a701, 0x615397afbc5c2, 0x60d7783f3f8fb, 0x2aa675fc486ba, 0x1d8062e9e7614 }, + { 0x4a74cb50f9e56, 0x531d1c2640192, 0x0c03d9d6c7fd2, 0x57ccd156610c1, 0x3a6ae249d806a }, + { 0x2da85a9907c5a, 0x6b23721ec4caf, 0x4d2d3a4683aa2, 0x7f9c6870efdef, 0x298b8ce8aef25 }, + }, + { + { 0x272ea0a2165de, 0x68179ef3ed06f, 0x4e2b9c0feac1e, 0x3ee290b1b63bb, 0x6ba6271803a7d }, + { 0x27953eff70cb2, 0x54f22ae0ec552, 0x29f3da92e2724, 0x242ca0c22bd18, 0x34b8a8404d5ce }, + { 0x6ecb583693335, 0x3ec76bfdfb84d, 0x2c895cf56a04f, 0x6355149d54d52, 0x71d62bdd465e1 }, + }, + { + { 0x5b5dab1f75ef5, 0x1e2d60cbeb9a5, 0x527c2175dfe57, 0x59e8a2b8ff51f, 0x1c333621262b2 }, + { 0x3cc28d378df80, 0x72141f4968ca6, 0x407696bdb6d0d, 0x5d271b22ffcfb, 0x74d5f317f3172 }, + { 0x7e55467d9ca81, 0x6a5653186f50d, 0x6b188ece62df1, 0x4c66d36844971, 0x4aebcc4547e9d }, + }, +}, +{ + { + { 0x08d9e7354b610, 0x26b750b6dc168, 0x162881e01acc9, 0x7966df31d01a5, 0x173bd9ddc9a1d }, + { 0x0071b276d01c9, 0x0b0d8918e025e, 0x75beea79ee2eb, 0x3c92984094db8, 0x5d88fbf95a3db }, + { 0x00f1efe5872df, 0x5da872318256a, 0x59ceb81635960, 0x18cf37693c764, 0x06e1cd13b19ea }, + }, + { + { 0x3af629e5b0353, 0x204f1a088e8e5, 0x10efc9ceea82e, 0x589863c2fa34b, 0x7f3a6a1a8d837 }, + { 0x0ad516f166f23, 0x263f56d57c81a, 0x13422384638ca, 0x1331ff1af0a50, 0x3080603526e16 }, + { 0x644395d3d800b, 0x2b9203dbedefc, 0x4b18ce656a355, 0x03f3466bc182c, 0x30d0fded2e513 }, + }, + { + { 0x4971e68b84750, 0x52ccc9779f396, 0x3e904ae8255c8, 0x4ecae46f39339, 0x4615084351c58 }, + { 0x14d1af21233b3, 0x1de1989b39c0b, 0x52669dc6f6f9e, 0x43434b28c3fc7, 0x0a9214202c099 }, + { 0x019c0aeb9a02e, 0x1a2c06995d792, 0x664cbb1571c44, 0x6ff0736fa80b2, 0x3bca0d2895ca5 }, + }, + { + { 0x08eb69ecc01bf, 0x5b4c8912df38d, 0x5ea7f8bc2f20e, 0x120e516caafaf, 0x4ea8b4038df28 }, + { 0x031bc3c5d62a4, 0x7d9fe0f4c081e, 0x43ed51467f22c, 0x1e6cc0c1ed109, 0x5631deddae8f1 }, + { 0x5460af1cad202, 0x0b4919dd0655d, 0x7c4697d18c14c, 0x231c890bba2a4, 0x24ce0930542ca }, + }, + { + { 0x7a155fdf30b85, 0x1c6c6e5d487f9, 0x24be1134bdc5a, 0x1405970326f32, 0x549928a7324f4 }, + { 0x090f5fd06c106, 0x6abb1021e43fd, 0x232bcfad711a0, 0x3a5c13c047f37, 0x41d4e3c28a06d }, + { 0x632a763ee1a2e, 0x6fa4bffbd5e4d, 0x5fd35a6ba4792, 0x7b55e1de99de8, 0x491b66dec0dcf }, + }, + { + { 0x04a8ed0da64a1, 0x5ecfc45096ebe, 0x5edee93b488b2, 0x5b3c11a51bc8f, 0x4cf6b8b0b7018 }, + { 0x5b13dc7ea32a7, 0x18fc2db73131e, 0x7e3651f8f57e3, 0x25656055fa965, 0x08f338d0c85ee }, + { 0x3a821991a73bd, 0x03be6418f5870, 0x1ddc18eac9ef0, 0x54ce09e998dc2, 0x530d4a82eb078 }, + }, + { + { 0x173456c9abf9e, 0x7892015100dad, 0x33ee14095fecb, 0x6ad95d67a0964, 0x0db3e7e00cbfb }, + { 0x43630e1f94825, 0x4d1956a6b4009, 0x213fe2df8b5e0, 0x05ce3a41191e6, 0x65ea753f10177 }, + { 0x6fc3ee2096363, 0x7ec36b96d67ac, 0x510ec6a0758b1, 0x0ed87df022109, 0x02a4ec1921e1a }, + }, + { + { 0x06162f1cf795f, 0x324ddcafe5eb9, 0x018d5e0463218, 0x7e78b9092428e, 0x36d12b5dec067 }, + { 0x6259a3b24b8a2, 0x188b5f4170b9c, 0x681c0dee15deb, 0x4dfe665f37445, 0x3d143c5112780 }, + { 0x5279179154557, 0x39f8f0741424d, 0x45e6eb357923d, 0x42c9b5edb746f, 0x2ef517885ba82 }, + }, +}, +{ + { + { 0x6bffb305b2f51, 0x5b112b2d712dd, 0x35774974fe4e2, 0x04af87a96e3a3, 0x57968290bb3a0 }, + { 0x7974e8c58aedc, 0x7757e083488c6, 0x601c62ae7bc8b, 0x45370c2ecab74, 0x2f1b78fab143a }, + { 0x2b8430a20e101, 0x1a49e1d88fee3, 0x38bbb47ce4d96, 0x1f0e7ba84d437, 0x7dc43e35dc2aa }, + }, + { + { 0x02a5c273e9718, 0x32bc9dfb28b4f, 0x48df4f8d5db1a, 0x54c87976c028f, 0x044fb81d82d50 }, + { 0x66665887dd9c3, 0x629760a6ab0b2, 0x481e6c7243e6c, 0x097e37046fc77, 0x7ef72016758cc }, + { 0x718c5a907e3d9, 0x3b9c98c6b383b, 0x006ed255eccdc, 0x6976538229a59, 0x7f79823f9c30d }, + }, + { + { 0x41ff068f587ba, 0x1c00a191bcd53, 0x7b56f9c209e25, 0x3781e5fccaabe, 0x64a9b0431c06d }, + { 0x4d239a3b513e8, 0x29723f51b1066, 0x642f4cf04d9c3, 0x4da095aa09b7a, 0x0a4e0373d784d }, + { 0x3d6a15b7d2919, 0x41aa75046a5d6, 0x691751ec2d3da, 0x23638ab6721c4, 0x071a7d0ace183 }, + }, + { + { 0x4355220e14431, 0x0e1362a283981, 0x2757cd8359654, 0x2e9cd7ab10d90, 0x7c69bcf761775 }, + { 0x72daac887ba0b, 0x0b7f4ac5dda60, 0x3bdda2c0498a4, 0x74e67aa180160, 0x2c3bcc7146ea7 }, + { 0x0d7eb04e8295f, 0x4a5ea1e6fa0fe, 0x45e635c436c60, 0x28ef4a8d4d18b, 0x6f5a9a7322aca }, + }, + { + { 0x1d4eba3d944be, 0x0100f15f3dce5, 0x61a700e367825, 0x5922292ab3d23, 0x02ab9680ee8d3 }, + { 0x1000c2f41c6c5, 0x0219fdf737174, 0x314727f127de7, 0x7e5277d23b81e, 0x494e21a2e147a }, + { 0x48a85dde50d9a, 0x1c1f734493df4, 0x47bdb64866889, 0x59a7d048f8eec, 0x6b5d76cbea46b }, + }, + { + { 0x141171e782522, 0x6806d26da7c1f, 0x3f31d1bc79ab9, 0x09f20459f5168, 0x16fb869c03dd3 }, + { 0x7556cec0cd994, 0x5eb9a03b7510a, 0x50ad1dd91cb71, 0x1aa5780b48a47, 0x0ae333f685277 }, + { 0x6199733b60962, 0x69b157c266511, 0x64740f893f1ca, 0x03aa408fbf684, 0x3f81e38b8f70d }, + }, + { + { 0x37f355f17c824, 0x07ae85334815b, 0x7e3abddd2e48f, 0x61eeabe1f45e5, 0x0ad3e2d34cded }, + { 0x10fcc7ed9affe, 0x4248cb0e96ff2, 0x4311c115172e2, 0x4c9d41cbf6925, 0x50510fc104f50 }, + { 0x40fc5336e249d, 0x3386639fb2de1, 0x7bbf871d17b78, 0x75f796b7e8004, 0x127c158bf0fa1 }, + }, + { + { 0x28fc4ae51b974, 0x26e89bfd2dbd4, 0x4e122a07665cf, 0x7cab1203405c3, 0x4ed82479d167d }, + { 0x17c422e9879a2, 0x28a5946c8fec3, 0x53ab32e912b77, 0x7b44da09fe0a5, 0x354ef87d07ef4 }, + { 0x3b52260c5d975, 0x79d6836171fdc, 0x7d994f140d4bb, 0x1b6c404561854, 0x302d92d205392 }, + }, +}, +{ + { + { 0x46fb6e4e0f177, 0x53497ad5265b7, 0x1ebdba01386fc, 0x0302f0cb36a3c, 0x0edc5f5eb426d }, + { 0x3c1a2bca4283d, 0x23430c7bb2f02, 0x1a3ea1bb58bc2, 0x7265763de5c61, 0x10e5d3b76f1ca }, + { 0x3bfd653da8e67, 0x584953ec82a8a, 0x55e288fa7707b, 0x5395fc3931d81, 0x45b46c51361cb }, + }, + { + { 0x54ddd8a7fe3e4, 0x2cecc41c619d3, 0x43a6562ac4d91, 0x4efa5aca7bdd9, 0x5c1c0aef32122 }, + { 0x02abf314f7fa1, 0x391d19e8a1528, 0x6a2fa13895fc7, 0x09d8eddeaa591, 0x2177bfa36dcb7 }, + { 0x01bbcfa79db8f, 0x3d84beb3666e1, 0x20c921d812204, 0x2dd843d3b32ce, 0x4ae619387d8ab }, + }, + { + { 0x17e44985bfb83, 0x54e32c626cc22, 0x096412ff38118, 0x6b241d61a246a, 0x75685abe5ba43 }, + { 0x3f6aa5344a32e, 0x69683680f11bb, 0x04c3581f623aa, 0x701af5875cba5, 0x1a00d91b17bf3 }, + { 0x60933eb61f2b2, 0x5193fe92a4dd2, 0x3d995a550f43e, 0x3556fb93a883d, 0x135529b623b0e }, + }, + { + { 0x716bce22e83fe, 0x33d0130b83eb8, 0x0952abad0afac, 0x309f64ed31b8a, 0x5972ea051590a }, + { 0x0dbd7add1d518, 0x119f823e2231e, 0x451d66e5e7de2, 0x500c39970f838, 0x79b5b81a65ca3 }, + { 0x4ac20dc8f7811, 0x29589a9f501fa, 0x4d810d26a6b4a, 0x5ede00d96b259, 0x4f7e9c95905f3 }, + }, + { + { 0x0443d355299fe, 0x39b7d7d5aee39, 0x692519a2f34ec, 0x6e4404924cf78, 0x1942eec4a144a }, + { 0x74bbc5781302e, 0x73135bb81ec4c, 0x7ef671b61483c, 0x7264614ccd729, 0x31993ad92e638 }, + { 0x45319ae234992, 0x2219d47d24fb5, 0x4f04488b06cf6, 0x53aaa9e724a12, 0x2a0a65314ef9c }, + }, + { + { 0x61acd3c1c793a, 0x58b46b78779e6, 0x3369aacbe7af2, 0x509b0743074d4, 0x055dc39b6dea1 }, + { 0x7937ff7f927c2, 0x0c2fa14c6a5b6, 0x556bddb6dd07c, 0x6f6acc179d108, 0x4cf6e218647c2 }, + { 0x1227cc28d5bb6, 0x78ee9bff57623, 0x28cb2241f893a, 0x25b541e3c6772, 0x121a307710aa2 }, + }, + { + { 0x1713ec77483c9, 0x6f70572d5facb, 0x25ef34e22ff81, 0x54d944f141188, 0x527bb94a6ced3 }, + { 0x35d5e9f034a97, 0x126069785bc9b, 0x5474ec7854ff0, 0x296a302a348ca, 0x333fc76c7a40e }, + { 0x5992a995b482e, 0x78dc707002ac7, 0x5936394d01741, 0x4fba4281aef17, 0x6b89069b20a7a }, + }, + { + { 0x2fa8cb5c7db77, 0x718e6982aa810, 0x39e95f81a1a1b, 0x5e794f3646cfb, 0x0473d308a7639 }, + { 0x2a0416270220d, 0x75f248b69d025, 0x1cbbc16656a27, 0x5b9ffd6e26728, 0x23bc2103aa73e }, + { 0x6792603589e05, 0x248db9892595d, 0x006a53cad2d08, 0x20d0150f7ba73, 0x102f73bfde043 }, + }, +}, +{ + { + { 0x4dae0b5511c9a, 0x5257fffe0d456, 0x54108d1eb2180, 0x096cc0f9baefa, 0x3f6bd725da4ea }, + { 0x0b9ab7f5745c6, 0x5caf0f8d21d63, 0x7debea408ea2b, 0x09edb93896d16, 0x36597d25ea5c0 }, + { 0x58d7b106058ac, 0x3cdf8d20bee69, 0x00a4cb765015e, 0x36832337c7cc9, 0x7b7ecc19da60d }, + }, + { + { 0x64a51a77cfa9b, 0x29cf470ca0db5, 0x4b60b6e0898d9, 0x55d04ddffe6c7, 0x03bedc661bf5c }, + { 0x2373c695c690d, 0x4c0c8520dcf18, 0x384af4b7494b9, 0x4ab4a8ea22225, 0x4235ad7601743 }, + { 0x0cb0d078975f5, 0x292313e530c4b, 0x38dbb9124a509, 0x350d0655a11f1, 0x0e7ce2b0cdf06 }, + }, + { + { 0x6fedfd94b70f9, 0x2383f9745bfd4, 0x4beae27c4c301, 0x75aa4416a3f3f, 0x615256138aece }, + { 0x4643ac48c85a3, 0x6878c2735b892, 0x3a53523f4d877, 0x3a504ed8bee9d, 0x666e0a5d8fb46 }, + { 0x3f64e4870cb0d, 0x61548b16d6557, 0x7a261773596f3, 0x7724d5f275d3a, 0x7f0bc810d514d }, + }, + { + { 0x49dad737213a0, 0x745dee5d31075, 0x7b1a55e7fdbe2, 0x5ba988f176ea1, 0x1d3a907ddec5a }, + { 0x06ba426f4136f, 0x3cafc0606b720, 0x518f0a2359cda, 0x5fae5e46feca7, 0x0d1f8dbcf8eed }, + { 0x693313ed081dc, 0x5b0a366901742, 0x40c872ca4ca7e, 0x6f18094009e01, 0x00011b44a31bf }, + }, + { + { 0x61f696a0aa75c, 0x38b0a57ad42ca, 0x1e59ab706fdc9, 0x01308d46ebfcd, 0x63d988a2d2851 }, + { 0x7a06c3fc66c0c, 0x1c9bac1ba47fb, 0x23935c575038e, 0x3f0bd71c59c13, 0x3ac48d916e835 }, + { 0x20753afbd232e, 0x71fbb1ed06002, 0x39cae47a4af3a, 0x0337c0b34d9c2, 0x33fad52b2368a }, + }, + { + { 0x4c8d0c422cfe8, 0x760b4275971a5, 0x3da95bc1cad3d, 0x0f151ff5b7376, 0x3cc355ccb90a7 }, + { 0x649c6c5e41e16, 0x60667eee6aa80, 0x4179d182be190, 0x653d9567e6979, 0x16c0f429a256d }, + { 0x69443903e9131, 0x16f4ac6f9dd36, 0x2ea4912e29253, 0x2b4643e68d25d, 0x631eaf426bae7 }, + }, + { + { 0x175b9a3700de8, 0x77c5f00aa48fb, 0x3917785ca0317, 0x05aa9b2c79399, 0x431f2c7f665f8 }, + { 0x10410da66fe9f, 0x24d82dcb4d67d, 0x3e6fe0e17752d, 0x4dade1ecbb08f, 0x5599648b1ea91 }, + { 0x26344858f7b19, 0x5f43d4a295ac0, 0x242a75c52acd4, 0x5934480220d10, 0x7b04715f91253 }, + }, + { + { 0x6c280c4e6bac6, 0x3ada3b361766e, 0x42fe5125c3b4f, 0x111d84d4aac22, 0x48d0acfa57cde }, + { 0x5bd28acf6ae43, 0x16fab8f56907d, 0x7acb11218d5f2, 0x41fe02023b4db, 0x59b37bf5c2f65 }, + { 0x726e47dabe671, 0x2ec45e746f6c1, 0x6580e53c74686, 0x5eda104673f74, 0x16234191336d3 }, + }, +}, +{ + { + { 0x19cd61ff38640, 0x060c6c4b41ba9, 0x75cf70ca7366f, 0x118a8f16c011e, 0x4a25707a203b9 }, + { 0x499def6267ff6, 0x76e858108773c, 0x693cac5ddcb29, 0x00311d00a9ff4, 0x2cdfdfecd5d05 }, + { 0x7668a53f6ed6a, 0x303ba2e142556, 0x3880584c10909, 0x4fe20000a261d, 0x5721896d248e4 }, + }, + { + { 0x55091a1d0da4e, 0x4f6bfc7c1050b, 0x64e4ecd2ea9be, 0x07eb1f28bbe70, 0x03c935afc4b03 }, + { 0x65517fd181bae, 0x3e5772c76816d, 0x019189640898a, 0x1ed2a84de7499, 0x578edd74f63c1 }, + { 0x276c6492b0c3d, 0x09bfc40bf932e, 0x588e8f11f330b, 0x3d16e694dc26e, 0x3ec2ab590288c }, + }, + { + { 0x13a09ae32d1cb, 0x3e81eb85ab4e4, 0x07aaca43cae1f, 0x62f05d7526374, 0x0e1bf66c6adba }, + { 0x0d27be4d87bb9, 0x56c27235db434, 0x72e6e0ea62d37, 0x5674cd06ee839, 0x2dd5c25a200fc }, + { 0x3d5e9792c887e, 0x319724dabbc55, 0x2b97c78680800, 0x7afdfdd34e6dd, 0x730548b35ae88 }, + }, + { + { 0x3094ba1d6e334, 0x6e126a7e3300b, 0x089c0aefcfbc5, 0x2eea11f836583, 0x585a2277d8784 }, + { 0x551a3cba8b8ee, 0x3b6422be2d886, 0x630e1419689bc, 0x4653b07a7a955, 0x3043443b411db }, + { 0x25f8233d48962, 0x6bd8f04aff431, 0x4f907fd9a6312, 0x40fd3c737d29b, 0x7656278950ef9 }, + }, + { + { 0x073a3ea86cf9d, 0x6e0e2abfb9c2e, 0x60e2a38ea33ee, 0x30b2429f3fe18, 0x28bbf484b613f }, + { 0x3cf59d51fc8c0, 0x7a0a0d6de4718, 0x55c3a3e6fb74b, 0x353135f884fd5, 0x3f4160a8c1b84 }, + { 0x12f5c6f136c7c, 0x0fedba237de4c, 0x779bccebfab44, 0x3aea93f4d6909, 0x1e79cb358188f }, + }, + { + { 0x153d8f5e08181, 0x08533bbdb2efd, 0x1149796129431, 0x17a6e36168643, 0x478ab52d39d1f }, + { 0x436c3eef7e3f1, 0x7ffd3c21f0026, 0x3e77bf20a2da9, 0x418bffc8472de, 0x65d7951b3a3b3 }, + { 0x6a4d39252d159, 0x790e35900ecd4, 0x30725bf977786, 0x10a5c1635a053, 0x16d87a411a212 }, + }, + { + { 0x4d5e2d54e0583, 0x2e5d7b33f5f74, 0x3a5de3f887ebf, 0x6ef24bd6139b7, 0x1f990b577a5a6 }, + { 0x57e5a42066215, 0x1a18b44983677, 0x3e652de1e6f8f, 0x6532be02ed8eb, 0x28f87c8165f38 }, + { 0x44ead1be8f7d6, 0x5759d4f31f466, 0x0378149f47943, 0x69f3be32b4f29, 0x45882fe1534d6 }, + }, + { + { 0x49929943c6fe4, 0x4347072545b15, 0x3226bced7e7c5, 0x03a134ced89df, 0x7dcf843ce405f }, + { 0x1345d757983d6, 0x222f54234cccd, 0x1784a3d8adbb4, 0x36ebeee8c2bcc, 0x688fe5b8f626f }, + { 0x0d6484a4732c0, 0x7b94ac6532d92, 0x5771b8754850f, 0x48dd9df1461c8, 0x6739687e73271 }, + }, +}, +{ + { + { 0x5cc9dc80c1ac0, 0x683671486d4cd, 0x76f5f1a5e8173, 0x6d5d3f5f9df4a, 0x7da0b8f68d7e7 }, + { 0x02014385675a6, 0x6155fb53d1def, 0x37ea32e89927c, 0x059a668f5a82e, 0x46115aba1d4dc }, + { 0x71953c3b5da76, 0x6642233d37a81, 0x2c9658076b1bd, 0x5a581e63010ff, 0x5a5f887e83674 }, + }, + { + { 0x628d3a0a643b9, 0x01cd8640c93d2, 0x0b7b0cad70f2c, 0x3864da98144be, 0x43e37ae2d5d1c }, + { 0x301cf70a13d11, 0x2a6a1ba1891ec, 0x2f291fb3f3ae0, 0x21a7b814bea52, 0x3669b656e44d1 }, + { 0x63f06eda6e133, 0x233342758070f, 0x098e0459cc075, 0x4df5ead6c7c1b, 0x6a21e6cd4fd5e }, + }, + { + { 0x129126699b2e3, 0x0ee11a2603de8, 0x60ac2f5c74c21, 0x59b192a196808, 0x45371b07001e8 }, + { 0x6170a3046e65f, 0x5401a46a49e38, 0x20add5561c4a8, 0x7abb4edde9e46, 0x586bf9f1a195f }, + { 0x3088d5ef8790b, 0x38c2126fcb4db, 0x685bae149e3c3, 0x0bcd601a4e930, 0x0eafb03790e52 }, + }, + { + { 0x0805e0f75ae1d, 0x464cc59860a28, 0x248e5b7b00bef, 0x5d99675ef8f75, 0x44ae3344c5435 }, + { 0x555c13748042f, 0x4d041754232c0, 0x521b430866907, 0x3308e40fb9c39, 0x309acc675a02c }, + { 0x289b9bba543ee, 0x3ab592e28539e, 0x64d82abcdd83a, 0x3c78ec172e327, 0x62d5221b7f946 }, + }, + { + { 0x5d4263af77a3c, 0x23fdd2289aeb0, 0x7dc64f77eb9ec, 0x01bd28338402c, 0x14f29a5383922 }, + { 0x4299c18d0936d, 0x5914183418a49, 0x52a18c721aed5, 0x2b151ba82976d, 0x5c0efde4bc754 }, + { 0x17edc25b2d7f5, 0x37336a6081bee, 0x7b5318887e5c3, 0x49f6d491a5be1, 0x5e72365c7bee0 }, + }, + { + { 0x339062f08b33e, 0x4bbf3e657cfb2, 0x67af7f56e5967, 0x4dbd67f9ed68f, 0x70b20555cb734 }, + { 0x3fc074571217f, 0x3a0d29b2b6aeb, 0x06478ccdde59d, 0x55e4d051bddfa, 0x77f1104c47b4e }, + { 0x113c555112c4c, 0x7535103f9b7ca, 0x140ed1d9a2108, 0x02522333bc2af, 0x0e34398f4a064 }, + }, + { + { 0x30b093e4b1928, 0x1ce7e7ec80312, 0x4e575bdf78f84, 0x61f7a190bed39, 0x6f8aded6ca379 }, + { 0x522d93ecebde8, 0x024f045e0f6cf, 0x16db63426cfa1, 0x1b93a1fd30fd8, 0x5e5405368a362 }, + { 0x0123dfdb7b29a, 0x4344356523c68, 0x79a527921ee5f, 0x74bfccb3e817e, 0x780de72ec8d3d }, + }, + { + { 0x7eaf300f42772, 0x5455188354ce3, 0x4dcca4a3dcbac, 0x3d314d0bfebcb, 0x1defc6ad32b58 }, + { 0x28545089ae7bc, 0x1e38fe9a0c15c, 0x12046e0e2377b, 0x6721c560aa885, 0x0eb28bf671928 }, + { 0x3be1aef5195a7, 0x6f22f62bdb5eb, 0x39768b8523049, 0x43394c8fbfdbd, 0x467d201bf8dd2 }, + }, +}, +{ + { + { 0x6f4bd567ae7a9, 0x65ac89317b783, 0x07d3b20fd8932, 0x000f208326916, 0x2ef9c5a5ba384 }, + { 0x6919a74ef4fad, 0x59ed4611452bf, 0x691ec04ea09ef, 0x3cbcb2700e984, 0x71c43c4f5ba3c }, + { 0x56df6fa9e74cd, 0x79c95e4cf56df, 0x7be643bc609e2, 0x149c12ad9e878, 0x5a758ca390c5f }, + }, + { + { 0x0918b1d61dc94, 0x0d350260cd19c, 0x7a2ab4e37b4d9, 0x21fea735414d7, 0x0a738027f639d }, + { 0x72710d9462495, 0x25aafaa007456, 0x2d21f28eaa31b, 0x17671ea005fd0, 0x2dbae244b3eb7 }, + { 0x74a2f57ffe1cc, 0x1bc3073087301, 0x7ec57f4019c34, 0x34e082e1fa524, 0x2698ca635126a }, + }, + { + { 0x5702f5e3dd90e, 0x31c9a4a70c5c7, 0x136a5aa78fc24, 0x1992f3b9f7b01, 0x3c004b0c4afa3 }, + { 0x5318832b0ba78, 0x6f24b9ff17cec, 0x0a47f30e060c7, 0x58384540dc8d0, 0x1fb43dcc49cae }, + { 0x146ac06f4b82b, 0x4b500d89e7355, 0x3351e1c728a12, 0x10b9f69932fe3, 0x6b43fd01cd1fd }, + }, + { + { 0x742583e760ef3, 0x73dc1573216b8, 0x4ae48fdd7714a, 0x4f85f8a13e103, 0x73420b2d6ff0d }, + { 0x75d4b4697c544, 0x11be1fff7f8f4, 0x119e16857f7e1, 0x38a14345cf5d5, 0x5a68d7105b52f }, + { 0x4f6cb9e851e06, 0x278c4471895e5, 0x7efcdce3d64e4, 0x64f6d455c4b4c, 0x3db5632fea34b }, + }, + { + { 0x190b1829825d5, 0x0e7d3513225c9, 0x1c12be3b7abae, 0x58777781e9ca6, 0x59197ea495df2 }, + { 0x6ee2bf75dd9d8, 0x6c72ceb34be8d, 0x679c9cc345ec7, 0x7898df96898a4, 0x04321adf49d75 }, + { 0x16019e4e55aae, 0x74fc5f25d209c, 0x4566a939ded0d, 0x66063e716e0b7, 0x45eafdc1f4d70 }, + }, + { + { 0x64624cfccb1ed, 0x257ab8072b6c1, 0x0120725676f0a, 0x4a018d04e8eee, 0x3f73ceea5d56d }, + { 0x401858045d72b, 0x459e5e0ca2d30, 0x488b719308bea, 0x56f4a0d1b32b5, 0x5a5eebc80362d }, + { 0x7bfd10a4e8dc6, 0x7c899366736f4, 0x55ebbeaf95c01, 0x46db060903f8a, 0x2605889126621 }, + }, + { + { 0x18e3cc676e542, 0x26079d995a990, 0x04a7c217908b2, 0x1dc7603e6655a, 0x0dedfa10b2444 }, + { 0x704a68360ff04, 0x3cecc3cde8b3e, 0x21cd5470f64ff, 0x6abc18d953989, 0x54ad0c2e4e615 }, + { 0x367d5b82b522a, 0x0d3f4b83d7dc7, 0x3067f4cdbc58d, 0x20452da697937, 0x62ecb2baa77a9 }, + }, + { + { 0x72836afb62874, 0x0af3c2094b240, 0x0c285297f357a, 0x7cc2d5680d6e3, 0x61913d5075663 }, + { 0x5795261152b3d, 0x7a1dbbafa3cbd, 0x5ad31c52588d5, 0x45f3a4164685c, 0x2e59f919a966d }, + { 0x62d361a3231da, 0x65284004e01b8, 0x656533be91d60, 0x6ae016c00a89f, 0x3ddbc2a131c05 }, + }, +}, +{ + { + { 0x257a22796bb14, 0x6f360fb443e75, 0x680e47220eaea, 0x2fcf2a5f10c18, 0x5ee7fb38d8320 }, + { 0x40ff9ce5ec54b, 0x57185e261b35b, 0x3e254540e70a9, 0x1b5814003e3f8, 0x78968314ac04b }, + { 0x5fdcb41446a8e, 0x5286926ff2a71, 0x0f231e296b3f6, 0x684a357c84693, 0x61d0633c9bca0 }, + }, + { + { 0x328bcf8fc73df, 0x3b4de06ff95b4, 0x30aa427ba11a5, 0x5ee31bfda6d9c, 0x5b23ac2df8067 }, + { 0x44935ffdb2566, 0x12f016d176c6e, 0x4fbb00f16f5ae, 0x3fab78d99402a, 0x6e965fd847aed }, + { 0x2b953ee80527b, 0x55f5bcdb1b35a, 0x43a0b3fa23c66, 0x76e07388b820a, 0x79b9bbb9dd95d }, + }, + { + { 0x17dae8e9f7374, 0x719f76102da33, 0x5117c2a80ca8b, 0x41a66b65d0936, 0x1ba811460accb }, + { 0x355406a3126c2, 0x50d1918727d76, 0x6e5ea0b498e0e, 0x0a3b6063214f2, 0x5065f158c9fd2 }, + { 0x169fb0c429954, 0x59aedd9ecee10, 0x39916eb851802, 0x57917555cc538, 0x3981f39e58a4f }, + }, + { + { 0x5dfa56de66fde, 0x0058809075908, 0x6d3d8cb854a94, 0x5b2f4e970b1e3, 0x30f4452edcbc1 }, + { 0x38a7559230a93, 0x52c1cde8ba31f, 0x2a4f2d4745a3d, 0x07e9d42d4a28a, 0x38dc083705acd }, + { 0x52782c5759740, 0x53f3397d990ad, 0x3a939c7e84d15, 0x234c4227e39e0, 0x632d9a1a593f2 }, + }, + { + { 0x1fd11ed0c84a7, 0x021b3ed2757e1, 0x73e1de58fc1c6, 0x5d110c84616ab, 0x3a5a7df28af64 }, + { 0x36b15b807cba6, 0x3f78a9e1afed7, 0x0a59c2c608f1f, 0x52bdd8ecb81b7, 0x0b24f48847ed4 }, + { 0x2d4be511beac7, 0x6bda4d99e5b9b, 0x17e6996914e01, 0x7b1f0ce7fcf80, 0x34fcf74475481 }, + }, + { + { 0x31dab78cfaa98, 0x4e3216e5e54b7, 0x249823973b689, 0x2584984e48885, 0x0119a3042fb37 }, + { 0x7e04c789767ca, 0x1671b28cfb832, 0x7e57ea2e1c537, 0x1fbaaef444141, 0x3d3bdc164dfa6 }, + { 0x2d89ce8c2177d, 0x6cd12ba182cf4, 0x20a8ac19a7697, 0x539fab2cc72d9, 0x56c088f1ede20 }, + }, + { + { 0x35fac24f38f02, 0x7d75c6197ab03, 0x33e4bc2a42fa7, 0x1c7cd10b48145, 0x038b7ea483590 }, + { 0x53d1110a86e17, 0x6416eb65f466d, 0x41ca6235fce20, 0x5c3fc8a99bb12, 0x09674c6b99108 }, + { 0x6f82199316ff8, 0x05d54f1a9f3e9, 0x3bcc5d0bd274a, 0x5b284b8d2d5ad, 0x6e5e31025969e }, + }, + { + { 0x4fb0e63066222, 0x130f59747e660, 0x041868fecd41a, 0x3105e8c923bc6, 0x3058ad43d1838 }, + { 0x462f587e593fb, 0x3d94ba7ce362d, 0x330f9b52667b7, 0x5d45a48e0f00a, 0x08f5114789a8d }, + { 0x40ffde57663d0, 0x71445d4c20647, 0x2653e68170f7c, 0x64cdee3c55ed6, 0x26549fa4efe3d }, + }, +}, +{ + { + { 0x68549af3f666e, 0x09e2941d4bb68, 0x2e8311f5dff3c, 0x6429ef91ffbd2, 0x3a10dfe132ce3 }, + { 0x55a461e6bf9d6, 0x78eeef4b02e83, 0x1d34f648c16cf, 0x07fea2aba5132, 0x1926e1dc6401e }, + { 0x74e8aea17cea0, 0x0c743f83fbc0f, 0x7cb03c4bf5455, 0x68a8ba9917e98, 0x1fa1d01d861e5 }, + }, + { + { 0x4ac00d1df94ab, 0x3ba2101bd271b, 0x7578988b9c4af, 0x0f2bf89f49f7e, 0x73fced18ee9a0 }, + { 0x055947d599832, 0x346fe2aa41990, 0x0164c8079195b, 0x799ccfb7bba27, 0x773563bc6a75c }, + { 0x1e90863139cb3, 0x4f8b407d9a0d6, 0x58e24ca924f69, 0x7a246bbe76456, 0x1f426b701b864 }, + }, + { + { 0x635c891a12552, 0x26aebd38ede2f, 0x66dc8faddae05, 0x21c7d41a03786, 0x0b76bb1b3fa7e }, + { 0x1264c41911c01, 0x702f44584bdf9, 0x43c511fc68ede, 0x0482c3aed35f9, 0x4e1af5271d31b }, + { 0x0c1f97f92939b, 0x17a88956dc117, 0x6ee005ef99dc7, 0x4aa9172b231cc, 0x7b6dd61eb772a }, + }, + { + { 0x0abf9ab01d2c7, 0x3880287630ae6, 0x32eca045beddb, 0x57f43365f32d0, 0x53fa9b659bff6 }, + { 0x5c1e850f33d92, 0x1ec119ab9f6f5, 0x7f16f6de663e9, 0x7a7d6cb16dec6, 0x703e9bceaf1d2 }, + { 0x4c8e994885455, 0x4ccb5da9cad82, 0x3596bc610e975, 0x7a80c0ddb9f5e, 0x398d93e5c4c61 }, + }, + { + { 0x77c60d2e7e3f2, 0x4061051763870, 0x67bc4e0ecd2aa, 0x2bb941f1373b9, 0x699c9c9002c30 }, + { 0x3d16733e248f3, 0x0e2b7e14be389, 0x42c0ddaf6784a, 0x589ea1fc67850, 0x53b09b5ddf191 }, + { 0x6a7235946f1cc, 0x6b99cbb2fbe60, 0x6d3a5d6485c62, 0x4839466e923c0, 0x51caf30c6fcdd }, + }, + { + { 0x2f99a18ac54c7, 0x398a39661ee6f, 0x384331e40cde3, 0x4cd15c4de19a6, 0x12ae29c189f8e }, + { 0x3a7427674e00a, 0x6142f4f7e74c1, 0x4cc93318c3a15, 0x6d51bac2b1ee7, 0x5504aa292383f }, + { 0x6c0cb1f0d01cf, 0x187469ef5d533, 0x27138883747bf, 0x2f52ae53a90e8, 0x5fd14fe958eba }, + }, + { + { 0x2fe5ebf93cb8e, 0x226da8acbe788, 0x10883a2fb7ea1, 0x094707842cf44, 0x7dd73f960725d }, + { 0x42ddf2845ab2c, 0x6214ffd3276bb, 0x00b8d181a5246, 0x268a6d579eb20, 0x093ff26e58647 }, + { 0x524fe68059829, 0x65b75e47cb621, 0x15eb0a5d5cc19, 0x05209b3929d5a, 0x2f59bcbc86b47 }, + }, + { + { 0x1d560b691c301, 0x7f5bafce3ce08, 0x4cd561614806c, 0x4588b6170b188, 0x2aa55e3d01082 }, + { 0x47d429917135f, 0x3eacfa07af070, 0x1deab46b46e44, 0x7a53f3ba46cdf, 0x5458b42e2e51a }, + { 0x192e60c07444f, 0x5ae8843a21daa, 0x6d721910b1538, 0x3321a95a6417e, 0x13e9004a8a768 }, + }, +}, +{ + { + { 0x600c9193b877f, 0x21c1b8a0d7765, 0x379927fb38ea2, 0x70d7679dbe01b, 0x5f46040898de9 }, + { 0x58845832fcedb, 0x135cd7f0c6e73, 0x53ffbdfe8e35b, 0x22f195e06e55b, 0x73937e8814bce }, + { 0x37116297bf48d, 0x45a9e0d069720, 0x25af71aa744ec, 0x41af0cb8aaba3, 0x2cf8a4e891d5e }, + }, + { + { 0x5487e17d06ba2, 0x3872a032d6596, 0x65e28c09348e0, 0x27b6bb2ce40c2, 0x7a6f7f2891d6a }, + { 0x3fd8707110f67, 0x26f8716a92db2, 0x1cdaa1b753027, 0x504be58b52661, 0x2049bd6e58252 }, + { 0x1fd8d6a9aef49, 0x7cb67b7216fa1, 0x67aff53c3b982, 0x20ea610da9628, 0x6011aadfc5459 }, + }, + { + { 0x6d0c802cbf890, 0x141bfed554c7b, 0x6dbb667ef4263, 0x58f3126857edc, 0x69ce18b779340 }, + { 0x7926dcf95f83c, 0x42e25120e2bec, 0x63de96df1fa15, 0x4f06b50f3f9cc, 0x6fc5cc1b0b62f }, + { 0x75528b29879cb, 0x79a8fd2125a3d, 0x27c8d4b746ab8, 0x0f8893f02210c, 0x15596b3ae5710 }, + }, + { + { 0x731167e5124ca, 0x17b38e8bbe13f, 0x3d55b942f9056, 0x09c1495be913f, 0x3aa4e241afb6d }, + { 0x739d23f9179a2, 0x632fadbb9e8c4, 0x7c8522bfe0c48, 0x6ed0983ef5aa9, 0x0d2237687b5f4 }, + { 0x138bf2a3305f5, 0x1f45d24d86598, 0x5274bad2160fe, 0x1b6041d58d12a, 0x32fcaa6e4687a }, + }, + { + { 0x7a4732787ccdf, 0x11e427c7f0640, 0x03659385f8c64, 0x5f4ead9766bfb, 0x746f6336c2600 }, + { 0x56e8dc57d9af5, 0x5b3be17be4f78, 0x3bf928cf82f4b, 0x52e55600a6f11, 0x4627e9cefebd6 }, + { 0x2f345ab6c971c, 0x653286e63e7e9, 0x51061b78a23ad, 0x14999acb54501, 0x7b4917007ed66 }, + }, + { + { 0x41b28dd53a2dd, 0x37be85f87ea86, 0x74be3d2a85e41, 0x1be87fac96ca6, 0x1d03620fe08cd }, + { 0x5fb5cab84b064, 0x2513e778285b0, 0x457383125e043, 0x6bda3b56e223d, 0x122ba376f844f }, + { 0x232cda2b4e554, 0x0422ba30ff840, 0x751e7667b43f5, 0x6261755da5f3e, 0x02c70bf52b68e }, + }, + { + { 0x532bf458d72e1, 0x40f96e796b59c, 0x22ef79d6f9da3, 0x501ab67beca77, 0x6b0697e3feb43 }, + { 0x7ec4b5d0b2fbb, 0x200e910595450, 0x742057105715e, 0x2f07022530f60, 0x26334f0a409ef }, + { 0x0f04adf62a3c0, 0x5e0edb48bb6d9, 0x7c34aa4fbc003, 0x7d74e4e5cac24, 0x1cc37f43441b2 }, + }, + { + { 0x656f1c9ceaeb9, 0x7031cacad5aec, 0x1308cd0716c57, 0x41c1373941942, 0x3a346f772f196 }, + { 0x7565a5cc7324f, 0x01ca0d5244a11, 0x116b067418713, 0x0a57d8c55edae, 0x6c6809c103803 }, + { 0x55112e2da6ac8, 0x6363d0a3dba5a, 0x319c98ba6f40c, 0x2e84b03a36ec7, 0x05911b9f6ef7c }, + }, +}, +{ + { + { 0x1acf3512eeaef, 0x2639839692a69, 0x669a234830507, 0x68b920c0603d4, 0x555ef9d1c64b2 }, + { 0x39983f5df0ebb, 0x1ea2589959826, 0x6ce638703cdd6, 0x6311678898505, 0x6b3cecf9aa270 }, + { 0x770ba3b73bd08, 0x11475f7e186d4, 0x0251bc9892bbc, 0x24eab9bffcc5a, 0x675f4de133817 }, + }, + { + { 0x7f6d93bdab31d, 0x1f3aca5bfd425, 0x2fa521c1c9760, 0x62180ce27f9cd, 0x60f450b882cd3 }, + { 0x452036b1782fc, 0x02d95b07681c5, 0x5901cf99205b2, 0x290686e5eecb4, 0x13d99df70164c }, + { 0x35ec321e5c0ca, 0x13ae337f44029, 0x4008e813f2da7, 0x640272f8e0c3a, 0x1c06de9e55eda }, + }, + { + { 0x52b40ff6d69aa, 0x31b8809377ffa, 0x536625cd14c2c, 0x516af252e17d1, 0x78096f8e7d32b }, + { 0x77ad6a33ec4e2, 0x717c5dc11d321, 0x4a114559823e4, 0x306ce50a1e2b1, 0x4cf38a1fec2db }, + { 0x2aa650dfa5ce7, 0x54916a8f19415, 0x00dc96fe71278, 0x55f2784e63eb8, 0x373cad3a26091 }, + }, + { + { 0x6a8fb89ddbbad, 0x78c35d5d97e37, 0x66e3674ef2cb2, 0x34347ac53dd8f, 0x21547eda5112a }, + { 0x4634d82c9f57c, 0x4249268a6d652, 0x6336d687f2ff7, 0x4fe4f4e26d9a0, 0x0040f3d945441 }, + { 0x5e939fd5986d3, 0x12a2147019bdf, 0x4c466e7d09cb2, 0x6fa5b95d203dd, 0x63550a334a254 }, + }, + { + { 0x2584572547b49, 0x75c58811c1377, 0x4d3c637cc171b, 0x33d30747d34e3, 0x39a92bafaa7d7 }, + { 0x7d6edb569cf37, 0x60194a5dc2ca0, 0x5af59745e10a6, 0x7a8f53e004875, 0x3eea62c7daf78 }, + { 0x4c713e693274e, 0x6ed1b7a6eb3a4, 0x62ace697d8e15, 0x266b8292ab075, 0x68436a0665c9c }, + }, + { + { 0x6d317e820107c, 0x090815d2ca3ca, 0x03ff1eb1499a1, 0x23960f050e319, 0x5373669c91611 }, + { 0x235e8202f3f27, 0x44c9f2eb61780, 0x630905b1d7003, 0x4fcc8d274ead1, 0x17b6e7f68ab78 }, + { 0x014ab9a0e5257, 0x09939567f8ba5, 0x4b47b2a423c82, 0x688d7e57ac42d, 0x1cb4b5a678f87 }, + }, + { + { 0x4aa62a2a007e7, 0x61e0e38f62d6e, 0x02f888fcc4782, 0x7562b83f21c00, 0x2dc0fd2d82ef6 }, + { 0x4c06b394afc6c, 0x4931b4bf636cc, 0x72b60d0322378, 0x25127c6818b25, 0x330bca78de743 }, + { 0x6ff841119744e, 0x2c560e8e49305, 0x7254fefe5a57a, 0x67ae2c560a7df, 0x3c31be1b369f1 }, + }, + { + { 0x0bc93f9cb4272, 0x3f8f9db73182d, 0x2b235eabae1c4, 0x2ddbf8729551a, 0x41cec1097e7d5 }, + { 0x4864d08948aee, 0x5d237438df61e, 0x2b285601f7067, 0x25dbcbae6d753, 0x330b61134262d }, + { 0x619d7a26d808a, 0x3c3b3c2adbef2, 0x6877c9eec7f52, 0x3beb9ebe1b66d, 0x26b44cd91f287 }, + }, +}, +{ + { + { 0x7f29362730383, 0x7fd7951459c36, 0x7504c512d49e7, 0x087ed7e3bc55f, 0x7deb10149c726 }, + { 0x048478f387475, 0x69397d9678a3e, 0x67c8156c976f3, 0x2eb4d5589226c, 0x2c709e6c1c10a }, + { 0x2af6a8766ee7a, 0x08aaa79a1d96c, 0x42f92d59b2fb0, 0x1752c40009c07, 0x08e68e9ff62ce }, + }, + { + { 0x509d50ab8f2f9, 0x1b8ab247be5e5, 0x5d9b2e6b2e486, 0x4faa5479a1339, 0x4cb13bd738f71 }, + { 0x5500a4bc130ad, 0x127a17a938695, 0x02a26fa34e36d, 0x584d12e1ecc28, 0x2f1f3f87eeba3 }, + { 0x48c75e515b64a, 0x75b6952071ef0, 0x5d46d42965406, 0x7746106989f9f, 0x19a1e353c0ae2 }, + }, + { + { 0x172cdd596bdbd, 0x0731ddf881684, 0x10426d64f8115, 0x71a4fd8a9a3da, 0x736bd3990266a }, + { 0x47560bafa05c3, 0x418dcabcc2fa3, 0x35991cecf8682, 0x24371a94b8c60, 0x41546b11c20c3 }, + { 0x32d509334b3b4, 0x16c102cae70aa, 0x1720dd51bf445, 0x5ae662faf9821, 0x412295a2b87fa }, + }, + { + { 0x55261e293eac6, 0x06426759b65cc, 0x40265ae116a48, 0x6c02304bae5bc, 0x0760bb8d195ad }, + { 0x19b88f57ed6e9, 0x4cdbf1904a339, 0x42b49cd4e4f2c, 0x71a2e771909d9, 0x14e153ebb52d2 }, + { 0x61a17cde6818a, 0x53dad34108827, 0x32b32c55c55b6, 0x2f9165f9347a3, 0x6b34be9bc33ac }, + }, + { + { 0x469656571f2d3, 0x0aa61ce6f423f, 0x3f940d71b27a1, 0x185f19d73d16a, 0x01b9c7b62e6dd }, + { 0x72f643a78c0b2, 0x3de45c04f9e7b, 0x706d68d30fa5c, 0x696f63e8e2f24, 0x2012c18f0922d }, + { 0x355e55ac89d29, 0x3e8b414ec7101, 0x39db07c520c90, 0x6f41e9b77efe1, 0x08af5b784e4ba }, + }, + { + { 0x314d289cc2c4b, 0x23450e2f1bc4e, 0x0cd93392f92f4, 0x1370c6a946b7d, 0x6423c1d5afd98 }, + { 0x499dc881f2533, 0x34ef26476c506, 0x4d107d2741497, 0x346c4bd6efdb3, 0x32b79d71163a1 }, + { 0x5f8d9edfcb36a, 0x1e6e8dcbf3990, 0x7974f348af30a, 0x6e6724ef19c7c, 0x480a5efbc13e2 }, + }, + { + { 0x14ce442ce221f, 0x18980a72516cc, 0x072f80db86677, 0x703331fda526e, 0x24b31d47691c8 }, + { 0x1e70b01622071, 0x1f163b5f8a16a, 0x56aaf341ad417, 0x7989635d830f7, 0x47aa27600cb7b }, + { 0x41eedc015f8c3, 0x7cf8d27ef854a, 0x289e3584693f9, 0x04a7857b309a7, 0x545b585d14dda }, + }, + { + { 0x4e4d0e3b321e1, 0x7451fe3d2ac40, 0x666f678eea98d, 0x038858667fead, 0x4d22dc3e64c8d }, + { 0x7275ea0d43a0f, 0x681137dd7ccf7, 0x1e79cbab79a38, 0x22a214489a66a, 0x0f62f9c332ba5 }, + { 0x46589d63b5f39, 0x7eaf979ec3f96, 0x4ebe81572b9a8, 0x21b7f5d61694a, 0x1c0fa01a36371 }, + }, +}, +{ + { + { 0x02b0e8c936a50, 0x6b83b58b6cd21, 0x37ed8d3e72680, 0x0a037db9f2a62, 0x4005419b1d2bc }, + { 0x604b622943dff, 0x1c899f6741a58, 0x60219e2f232fb, 0x35fae92a7f9cb, 0x0fa3614f3b1ca }, + { 0x3febdb9be82f0, 0x5e74895921400, 0x553ea38822706, 0x5a17c24cfc88c, 0x1fba218aef40a }, + }, + { + { 0x657043e7b0194, 0x5c11b55efe9e7, 0x7737bc6a074fb, 0x0eae41ce355cc, 0x6c535d13ff776 }, + { 0x49448fac8f53e, 0x34f74c6e8356a, 0x0ad780607dba2, 0x7213a7eb63eb6, 0x392e3acaa8c86 }, + { 0x534e93e8a35af, 0x08b10fd02c997, 0x26ac2acb81e05, 0x09d8c98ce3b79, 0x25e17fe4d50ac }, + }, + { + { 0x77ff576f121a7, 0x4e5f9b0fc722b, 0x46f949b0d28c8, 0x4cde65d17ef26, 0x6bba828f89698 }, + { 0x09bd71e04f676, 0x25ac841f2a145, 0x1a47eac823871, 0x1a8a8c36c581a, 0x255751442a9fb }, + { 0x1bc6690fe3901, 0x314132f5abc5a, 0x611835132d528, 0x5f24b8eb48a57, 0x559d504f7f6b7 }, + }, + { + { 0x091e7f6d266fd, 0x36060ef037389, 0x18788ec1d1286, 0x287441c478eb0, 0x123ea6a3354bd }, + { 0x38378b3eb54d5, 0x4d4aaa78f94ee, 0x4a002e875a74d, 0x10b851367b17c, 0x01ab12d5807e3 }, + { 0x5189041e32d96, 0x05b062b090231, 0x0c91766e7b78f, 0x0aa0f55a138ec, 0x4a3961e2c918a }, + }, + { + { 0x7d644f3233f1e, 0x1c69f9e02c064, 0x36ae5e5266898, 0x08fc1dad38b79, 0x68aceead9bd41 }, + { 0x43be0f8e6bba0, 0x68fdffc614e3b, 0x4e91dab5b3be0, 0x3b1d4c9212ff0, 0x2cd6bce3fb1db }, + { 0x4c90ef3d7c210, 0x496f5a0818716, 0x79cf88cc239b8, 0x2cb9c306cf8db, 0x595760d5b508f }, + }, + { + { 0x2cbebfd022790, 0x0b8822aec1105, 0x4d1cfd226bccc, 0x515b2fa4971be, 0x2cb2c5df54515 }, + { 0x1bfe104aa6397, 0x11494ff996c25, 0x64251623e5800, 0x0d49fc5e044be, 0x709fa43edcb29 }, + { 0x25d8c63fd2aca, 0x4c5cd29dffd61, 0x32ec0eb48af05, 0x18f9391f9b77c, 0x70f029ecf0c81 }, + }, + { + { 0x2afaa5e10b0b9, 0x61de08355254d, 0x0eb587de3c28d, 0x4f0bb9f7dbbd5, 0x44eca5a2a74bd }, + { 0x307b32eed3e33, 0x6748ab03ce8c2, 0x57c0d9ab810bc, 0x42c64a224e98c, 0x0b7d5d8a6c314 }, + { 0x448327b95d543, 0x0146681e3a4ba, 0x38714adc34e0c, 0x4f26f0e298e30, 0x272224512c7de }, + }, + { + { 0x3bb8a42a975fc, 0x6f2d5b46b17ef, 0x7b6a9223170e5, 0x053713fe3b7e6, 0x19735fd7f6bc2 }, + { 0x492af49c5342e, 0x2365cdf5a0357, 0x32138a7ffbb60, 0x2a1f7d14646fe, 0x11b5df18a44cc }, + { 0x390d042c84266, 0x1efe32a8fdc75, 0x6925ee7ae1238, 0x4af9281d0e832, 0x0fef911191df8 }, + }, +}, +}; +#else +/* base[i][j] = (j+1)*256^i*B */ +static const ge_precomp base[32][8] = { +{ + { + { 25967493,-14356035,29566456,3660896,-12694345,4014787,27544626,-11754271,-6079156,2047605 }, + { -12545711,934262,-2722910,3049990,-727428,9406986,12720692,5043384,19500929,-15469378 }, + { -8738181,4489570,9688441,-14785194,10184609,-12363380,29287919,11864899,-24514362,-4438546 }, + }, + { + { -12815894,-12976347,-21581243,11784320,-25355658,-2750717,-11717903,-3814571,-358445,-10211303 }, + { -21703237,6903825,27185491,6451973,-29577724,-9554005,-15616551,11189268,-26829678,-5319081 }, + { 26966642,11152617,32442495,15396054,14353839,-12752335,-3128826,-9541118,-15472047,-4166697 }, + }, + { + { 15636291,-9688557,24204773,-7912398,616977,-16685262,27787600,-14772189,28944400,-1550024 }, + { 16568933,4717097,-11556148,-1102322,15682896,-11807043,16354577,-11775962,7689662,11199574 }, + { 30464156,-5976125,-11779434,-15670865,23220365,15915852,7512774,10017326,-17749093,-9920357 }, + }, + { + { -17036878,13921892,10945806,-6033431,27105052,-16084379,-28926210,15006023,3284568,-6276540 }, + { 23599295,-8306047,-11193664,-7687416,13236774,10506355,7464579,9656445,13059162,10374397 }, + { 7798556,16710257,3033922,2874086,28997861,2835604,32406664,-3839045,-641708,-101325 }, + }, + { + { 10861363,11473154,27284546,1981175,-30064349,12577861,32867885,14515107,-15438304,10819380 }, + { 4708026,6336745,20377586,9066809,-11272109,6594696,-25653668,12483688,-12668491,5581306 }, + { 19563160,16186464,-29386857,4097519,10237984,-4348115,28542350,13850243,-23678021,-15815942 }, + }, + { + { -15371964,-12862754,32573250,4720197,-26436522,5875511,-19188627,-15224819,-9818940,-12085777 }, + { -8549212,109983,15149363,2178705,22900618,4543417,3044240,-15689887,1762328,14866737 }, + { -18199695,-15951423,-10473290,1707278,-17185920,3916101,-28236412,3959421,27914454,4383652 }, + }, + { + { 5153746,9909285,1723747,-2777874,30523605,5516873,19480852,5230134,-23952439,-15175766 }, + { -30269007,-3463509,7665486,10083793,28475525,1649722,20654025,16520125,30598449,7715701 }, + { 28881845,14381568,9657904,3680757,-20181635,7843316,-31400660,1370708,29794553,-1409300 }, + }, + { + { 14499471,-2729599,-33191113,-4254652,28494862,14271267,30290735,10876454,-33154098,2381726 }, + { -7195431,-2655363,-14730155,462251,-27724326,3941372,-6236617,3696005,-32300832,15351955 }, + { 27431194,8222322,16448760,-3907995,-18707002,11938355,-32961401,-2970515,29551813,10109425 }, + }, +}, +{ + { + { -13657040,-13155431,-31283750,11777098,21447386,6519384,-2378284,-1627556,10092783,-4764171 }, + { 27939166,14210322,4677035,16277044,-22964462,-12398139,-32508754,12005538,-17810127,12803510 }, + { 17228999,-15661624,-1233527,300140,-1224870,-11714777,30364213,-9038194,18016357,4397660 }, + }, + { + { -10958843,-7690207,4776341,-14954238,27850028,-15602212,-26619106,14544525,-17477504,982639 }, + { 29253598,15796703,-2863982,-9908884,10057023,3163536,7332899,-4120128,-21047696,9934963 }, + { 5793303,16271923,-24131614,-10116404,29188560,1206517,-14747930,4559895,-30123922,-10897950 }, + }, + { + { -27643952,-11493006,16282657,-11036493,28414021,-15012264,24191034,4541697,-13338309,5500568 }, + { 12650548,-1497113,9052871,11355358,-17680037,-8400164,-17430592,12264343,10874051,13524335 }, + { 25556948,-3045990,714651,2510400,23394682,-10415330,33119038,5080568,-22528059,5376628 }, + }, + { + { -26088264,-4011052,-17013699,-3537628,-6726793,1920897,-22321305,-9447443,4535768,1569007 }, + { -2255422,14606630,-21692440,-8039818,28430649,8775819,-30494562,3044290,31848280,12543772 }, + { -22028579,2943893,-31857513,6777306,13784462,-4292203,-27377195,-2062731,7718482,14474653 }, + }, + { + { 2385315,2454213,-22631320,46603,-4437935,-15680415,656965,-7236665,24316168,-5253567 }, + { 13741529,10911568,-33233417,-8603737,-20177830,-1033297,33040651,-13424532,-20729456,8321686 }, + { 21060490,-2212744,15712757,-4336099,1639040,10656336,23845965,-11874838,-9984458,608372 }, + }, + { + { -13672732,-15087586,-10889693,-7557059,-6036909,11305547,1123968,-6780577,27229399,23887 }, + { -23244140,-294205,-11744728,14712571,-29465699,-2029617,12797024,-6440308,-1633405,16678954 }, + { -29500620,4770662,-16054387,14001338,7830047,9564805,-1508144,-4795045,-17169265,4904953 }, + }, + { + { 24059557,14617003,19037157,-15039908,19766093,-14906429,5169211,16191880,2128236,-4326833 }, + { -16981152,4124966,-8540610,-10653797,30336522,-14105247,-29806336,916033,-6882542,-2986532 }, + { -22630907,12419372,-7134229,-7473371,-16478904,16739175,285431,2763829,15736322,4143876 }, + }, + { + { 2379352,11839345,-4110402,-5988665,11274298,794957,212801,-14594663,23527084,-16458268 }, + { 33431127,-11130478,-17838966,-15626900,8909499,8376530,-32625340,4087881,-15188911,-14416214 }, + { 1767683,7197987,-13205226,-2022635,-13091350,448826,5799055,4357868,-4774191,-16323038 }, + }, +}, +{ + { + { 6721966,13833823,-23523388,-1551314,26354293,-11863321,23365147,-3949732,7390890,2759800 }, + { 4409041,2052381,23373853,10530217,7676779,-12885954,21302353,-4264057,1244380,-12919645 }, + { -4421239,7169619,4982368,-2957590,30256825,-2777540,14086413,9208236,15886429,16489664 }, + }, + { + { 1996075,10375649,14346367,13311202,-6874135,-16438411,-13693198,398369,-30606455,-712933 }, + { -25307465,9795880,-2777414,14878809,-33531835,14780363,13348553,12076947,-30836462,5113182 }, + { -17770784,11797796,31950843,13929123,-25888302,12288344,-30341101,-7336386,13847711,5387222 }, + }, + { + { -18582163,-3416217,17824843,-2340966,22744343,-10442611,8763061,3617786,-19600662,10370991 }, + { 20246567,-14369378,22358229,-543712,18507283,-10413996,14554437,-8746092,32232924,16763880 }, + { 9648505,10094563,26416693,14745928,-30374318,-6472621,11094161,15689506,3140038,-16510092 }, + }, + { + { -16160072,5472695,31895588,4744994,8823515,10365685,-27224800,9448613,-28774454,366295 }, + { 19153450,11523972,-11096490,-6503142,-24647631,5420647,28344573,8041113,719605,11671788 }, + { 8678025,2694440,-6808014,2517372,4964326,11152271,-15432916,-15266516,27000813,-10195553 }, + }, + { + { -15157904,7134312,8639287,-2814877,-7235688,10421742,564065,5336097,6750977,-14521026 }, + { 11836410,-3979488,26297894,16080799,23455045,15735944,1695823,-8819122,8169720,16220347 }, + { -18115838,8653647,17578566,-6092619,-8025777,-16012763,-11144307,-2627664,-5990708,-14166033 }, + }, + { + { -23308498,-10968312,15213228,-10081214,-30853605,-11050004,27884329,2847284,2655861,1738395 }, + { -27537433,-14253021,-25336301,-8002780,-9370762,8129821,21651608,-3239336,-19087449,-11005278 }, + { 1533110,3437855,23735889,459276,29970501,11335377,26030092,5821408,10478196,8544890 }, + }, + { + { 32173121,-16129311,24896207,3921497,22579056,-3410854,19270449,12217473,17789017,-3395995 }, + { -30552961,-2228401,-15578829,-10147201,13243889,517024,15479401,-3853233,30460520,1052596 }, + { -11614875,13323618,32618793,8175907,-15230173,12596687,27491595,-4612359,3179268,-9478891 }, + }, + { + { 31947069,-14366651,-4640583,-15339921,-15125977,-6039709,-14756777,-16411740,19072640,-9511060 }, + { 11685058,11822410,3158003,-13952594,33402194,-4165066,5977896,-5215017,473099,5040608 }, + { -20290863,8198642,-27410132,11602123,1290375,-2799760,28326862,1721092,-19558642,-3131606 }, + }, +}, +{ + { + { 7881532,10687937,7578723,7738378,-18951012,-2553952,21820786,8076149,-27868496,11538389 }, + { -19935666,3899861,18283497,-6801568,-15728660,-11249211,8754525,7446702,-5676054,5797016 }, + { -11295600,-3793569,-15782110,-7964573,12708869,-8456199,2014099,-9050574,-2369172,-5877341 }, + }, + { + { -22472376,-11568741,-27682020,1146375,18956691,16640559,1192730,-3714199,15123619,10811505 }, + { 14352098,-3419715,-18942044,10822655,32750596,4699007,-70363,15776356,-28886779,-11974553 }, + { -28241164,-8072475,-4978962,-5315317,29416931,1847569,-20654173,-16484855,4714547,-9600655 }, + }, + { + { 15200332,8368572,19679101,15970074,-31872674,1959451,24611599,-4543832,-11745876,12340220 }, + { 12876937,-10480056,33134381,6590940,-6307776,14872440,9613953,8241152,15370987,9608631 }, + { -4143277,-12014408,8446281,-391603,4407738,13629032,-7724868,15866074,-28210621,-8814099 }, + }, + { + { 26660628,-15677655,8393734,358047,-7401291,992988,-23904233,858697,20571223,8420556 }, + { 14620715,13067227,-15447274,8264467,14106269,15080814,33531827,12516406,-21574435,-12476749 }, + { 236881,10476226,57258,-14677024,6472998,2466984,17258519,7256740,8791136,15069930 }, + }, + { + { 1276410,-9371918,22949635,-16322807,-23493039,-5702186,14711875,4874229,-30663140,-2331391 }, + { 5855666,4990204,-13711848,7294284,-7804282,1924647,-1423175,-7912378,-33069337,9234253 }, + { 20590503,-9018988,31529744,-7352666,-2706834,10650548,31559055,-11609587,18979186,13396066 }, + }, + { + { 24474287,4968103,22267082,4407354,24063882,-8325180,-18816887,13594782,33514650,7021958 }, + { -11566906,-6565505,-21365085,15928892,-26158305,4315421,-25948728,-3916677,-21480480,12868082 }, + { -28635013,13504661,19988037,-2132761,21078225,6443208,-21446107,2244500,-12455797,-8089383 }, + }, + { + { -30595528,13793479,-5852820,319136,-25723172,-6263899,33086546,8957937,-15233648,5540521 }, + { -11630176,-11503902,-8119500,-7643073,2620056,1022908,-23710744,-1568984,-16128528,-14962807 }, + { 23152971,775386,27395463,14006635,-9701118,4649512,1689819,892185,-11513277,-15205948 }, + }, + { + { 9770129,9586738,26496094,4324120,1556511,-3550024,27453819,4763127,-19179614,5867134 }, + { -32765025,1927590,31726409,-4753295,23962434,-16019500,27846559,5931263,-29749703,-16108455 }, + { 27461885,-2977536,22380810,1815854,-23033753,-3031938,7283490,-15148073,-19526700,7734629 }, + }, +}, +{ + { + { -8010264,-9590817,-11120403,6196038,29344158,-13430885,7585295,-3176626,18549497,15302069 }, + { -32658337,-6171222,-7672793,-11051681,6258878,13504381,10458790,-6418461,-8872242,8424746 }, + { 24687205,8613276,-30667046,-3233545,1863892,-1830544,19206234,7134917,-11284482,-828919 }, + }, + { + { 11334899,-9218022,8025293,12707519,17523892,-10476071,10243738,-14685461,-5066034,16498837 }, + { 8911542,6887158,-9584260,-6958590,11145641,-9543680,17303925,-14124238,6536641,10543906 }, + { -28946384,15479763,-17466835,568876,-1497683,11223454,-2669190,-16625574,-27235709,8876771 }, + }, + { + { -25742899,-12566864,-15649966,-846607,-33026686,-796288,-33481822,15824474,-604426,-9039817 }, + { 10330056,70051,7957388,-9002667,9764902,15609756,27698697,-4890037,1657394,3084098 }, + { 10477963,-7470260,12119566,-13250805,29016247,-5365589,31280319,14396151,-30233575,15272409 }, + }, + { + { -12288309,3169463,28813183,16658753,25116432,-5630466,-25173957,-12636138,-25014757,1950504 }, + { -26180358,9489187,11053416,-14746161,-31053720,5825630,-8384306,-8767532,15341279,8373727 }, + { 28685821,7759505,-14378516,-12002860,-31971820,4079242,298136,-10232602,-2878207,15190420 }, + }, + { + { -32932876,13806336,-14337485,-15794431,-24004620,10940928,8669718,2742393,-26033313,-6875003 }, + { -1580388,-11729417,-25979658,-11445023,-17411874,-10912854,9291594,-16247779,-12154742,6048605 }, + { -30305315,14843444,1539301,11864366,20201677,1900163,13934231,5128323,11213262,9168384 }, + }, + { + { -26280513,11007847,19408960,-940758,-18592965,-4328580,-5088060,-11105150,20470157,-16398701 }, + { -23136053,9282192,14855179,-15390078,-7362815,-14408560,-22783952,14461608,14042978,5230683 }, + { 29969567,-2741594,-16711867,-8552442,9175486,-2468974,21556951,3506042,-5933891,-12449708 }, + }, + { + { -3144746,8744661,19704003,4581278,-20430686,6830683,-21284170,8971513,-28539189,15326563 }, + { -19464629,10110288,-17262528,-3503892,-23500387,1355669,-15523050,15300988,-20514118,9168260 }, + { -5353335,4488613,-23803248,16314347,7780487,-15638939,-28948358,9601605,33087103,-9011387 }, + }, + { + { -19443170,-15512900,-20797467,-12445323,-29824447,10229461,-27444329,-15000531,-5996870,15664672 }, + { 23294591,-16632613,-22650781,-8470978,27844204,11461195,13099750,-2460356,18151676,13417686 }, + { -24722913,-4176517,-31150679,5988919,-26858785,6685065,1661597,-12551441,15271676,-15452665 }, + }, +}, +{ + { + { 11433042,-13228665,8239631,-5279517,-1985436,-725718,-18698764,2167544,-6921301,-13440182 }, + { -31436171,15575146,30436815,12192228,-22463353,9395379,-9917708,-8638997,12215110,12028277 }, + { 14098400,6555944,23007258,5757252,-15427832,-12950502,30123440,4617780,-16900089,-655628 }, + }, + { + { -4026201,-15240835,11893168,13718664,-14809462,1847385,-15819999,10154009,23973261,-12684474 }, + { -26531820,-3695990,-1908898,2534301,-31870557,-16550355,18341390,-11419951,32013174,-10103539 }, + { -25479301,10876443,-11771086,-14625140,-12369567,1838104,21911214,6354752,4425632,-837822 }, + }, + { + { -10433389,-14612966,22229858,-3091047,-13191166,776729,-17415375,-12020462,4725005,14044970 }, + { 19268650,-7304421,1555349,8692754,-21474059,-9910664,6347390,-1411784,-19522291,-16109756 }, + { -24864089,12986008,-10898878,-5558584,-11312371,-148526,19541418,8180106,9282262,10282508 }, + }, + { + { -26205082,4428547,-8661196,-13194263,4098402,-14165257,15522535,8372215,5542595,-10702683 }, + { -10562541,14895633,26814552,-16673850,-17480754,-2489360,-2781891,6993761,-18093885,10114655 }, + { -20107055,-929418,31422704,10427861,-7110749,6150669,-29091755,-11529146,25953725,-106158 }, + }, + { + { -4234397,-8039292,-9119125,3046000,2101609,-12607294,19390020,6094296,-3315279,12831125 }, + { -15998678,7578152,5310217,14408357,-33548620,-224739,31575954,6326196,7381791,-2421839 }, + { -20902779,3296811,24736065,-16328389,18374254,7318640,6295303,8082724,-15362489,12339664 }, + }, + { + { 27724736,2291157,6088201,-14184798,1792727,5857634,13848414,15768922,25091167,14856294 }, + { -18866652,8331043,24373479,8541013,-701998,-9269457,12927300,-12695493,-22182473,-9012899 }, + { -11423429,-5421590,11632845,3405020,30536730,-11674039,-27260765,13866390,30146206,9142070 }, + }, + { + { 3924129,-15307516,-13817122,-10054960,12291820,-668366,-27702774,9326384,-8237858,4171294 }, + { -15921940,16037937,6713787,16606682,-21612135,2790944,26396185,3731949,345228,-5462949 }, + { -21327538,13448259,25284571,1143661,20614966,-8849387,2031539,-12391231,-16253183,-13582083 }, + }, + { + { 31016211,-16722429,26371392,-14451233,-5027349,14854137,17477601,3842657,28012650,-16405420 }, + { -5075835,9368966,-8562079,-4600902,-15249953,6970560,-9189873,16292057,-8867157,3507940 }, + { 29439664,3537914,23333589,6997794,-17555561,-11018068,-15209202,-15051267,-9164929,6580396 }, + }, +}, +{ + { + { -12185861,-7679788,16438269,10826160,-8696817,-6235611,17860444,-9273846,-2095802,9304567 }, + { 20714564,-4336911,29088195,7406487,11426967,-5095705,14792667,-14608617,5289421,-477127 }, + { -16665533,-10650790,-6160345,-13305760,9192020,-1802462,17271490,12349094,26939669,-3752294 }, + }, + { + { -12889898,9373458,31595848,16374215,21471720,13221525,-27283495,-12348559,-3698806,117887 }, + { 22263325,-6560050,3984570,-11174646,-15114008,-566785,28311253,5358056,-23319780,541964 }, + { 16259219,3261970,2309254,-15534474,-16885711,-4581916,24134070,-16705829,-13337066,-13552195 }, + }, + { + { 9378160,-13140186,-22845982,-12745264,28198281,-7244098,-2399684,-717351,690426,14876244 }, + { 24977353,-314384,-8223969,-13465086,28432343,-1176353,-13068804,-12297348,-22380984,6618999 }, + { -1538174,11685646,12944378,13682314,-24389511,-14413193,8044829,-13817328,32239829,-5652762 }, + }, + { + { -18603066,4762990,-926250,8885304,-28412480,-3187315,9781647,-10350059,32779359,5095274 }, + { -33008130,-5214506,-32264887,-3685216,9460461,-9327423,-24601656,14506724,21639561,-2630236 }, + { -16400943,-13112215,25239338,15531969,3987758,-4499318,-1289502,-6863535,17874574,558605 }, + }, + { + { -13600129,10240081,9171883,16131053,-20869254,9599700,33499487,5080151,2085892,5119761 }, + { -22205145,-2519528,-16381601,414691,-25019550,2170430,30634760,-8363614,-31999993,-5759884 }, + { -6845704,15791202,8550074,-1312654,29928809,-12092256,27534430,-7192145,-22351378,12961482 }, + }, + { + { -24492060,-9570771,10368194,11582341,-23397293,-2245287,16533930,8206996,-30194652,-5159638 }, + { -11121496,-3382234,2307366,6362031,-135455,8868177,-16835630,7031275,7589640,8945490 }, + { -32152748,8917967,6661220,-11677616,-1192060,-15793393,7251489,-11182180,24099109,-14456170 }, + }, + { + { 5019558,-7907470,4244127,-14714356,-26933272,6453165,-19118182,-13289025,-6231896,-10280736 }, + { 10853594,10721687,26480089,5861829,-22995819,1972175,-1866647,-10557898,-3363451,-6441124 }, + { -17002408,5906790,221599,-6563147,7828208,-13248918,24362661,-2008168,-13866408,7421392 }, + }, + { + { 8139927,-6546497,32257646,-5890546,30375719,1886181,-21175108,15441252,28826358,-4123029 }, + { 6267086,9695052,7709135,-16603597,-32869068,-1886135,14795160,-7840124,13746021,-1742048 }, + { 28584902,7787108,-6732942,-15050729,22846041,-7571236,-3181936,-363524,4771362,-8419958 }, + }, +}, +{ + { + { 24949256,6376279,-27466481,-8174608,-18646154,-9930606,33543569,-12141695,3569627,11342593 }, + { 26514989,4740088,27912651,3697550,19331575,-11472339,6809886,4608608,7325975,-14801071 }, + { -11618399,-14554430,-24321212,7655128,-1369274,5214312,-27400540,10258390,-17646694,-8186692 }, + }, + { + { 11431204,15823007,26570245,14329124,18029990,4796082,-31446179,15580664,9280358,-3973687 }, + { -160783,-10326257,-22855316,-4304997,-20861367,-13621002,-32810901,-11181622,-15545091,4387441 }, + { -20799378,12194512,3937617,-5805892,-27154820,9340370,-24513992,8548137,20617071,-7482001 }, + }, + { + { -938825,-3930586,-8714311,16124718,24603125,-6225393,-13775352,-11875822,24345683,10325460 }, + { -19855277,-1568885,-22202708,8714034,14007766,6928528,16318175,-1010689,4766743,3552007 }, + { -21751364,-16730916,1351763,-803421,-4009670,3950935,3217514,14481909,10988822,-3994762 }, + }, + { + { 15564307,-14311570,3101243,5684148,30446780,-8051356,12677127,-6505343,-8295852,13296005 }, + { -9442290,6624296,-30298964,-11913677,-4670981,-2057379,31521204,9614054,-30000824,12074674 }, + { 4771191,-135239,14290749,-13089852,27992298,14998318,-1413936,-1556716,29832613,-16391035 }, + }, + { + { 7064884,-7541174,-19161962,-5067537,-18891269,-2912736,25825242,5293297,-27122660,13101590 }, + { -2298563,2439670,-7466610,1719965,-27267541,-16328445,32512469,-5317593,-30356070,-4190957 }, + { -30006540,10162316,-33180176,3981723,-16482138,-13070044,14413974,9515896,19568978,9628812 }, + }, + { + { 33053803,199357,15894591,1583059,27380243,-4580435,-17838894,-6106839,-6291786,3437740 }, + { -18978877,3884493,19469877,12726490,15913552,13614290,-22961733,70104,7463304,4176122 }, + { -27124001,10659917,11482427,-16070381,12771467,-6635117,-32719404,-5322751,24216882,5944158 }, + }, + { + { 8894125,7450974,-2664149,-9765752,-28080517,-12389115,19345746,14680796,11632993,5847885 }, + { 26942781,-2315317,9129564,-4906607,26024105,11769399,-11518837,6367194,-9727230,4782140 }, + { 19916461,-4828410,-22910704,-11414391,25606324,-5972441,33253853,8220911,6358847,-1873857 }, + }, + { + { 801428,-2081702,16569428,11065167,29875704,96627,7908388,-4480480,-13538503,1387155 }, + { 19646058,5720633,-11416706,12814209,11607948,12749789,14147075,15156355,-21866831,11835260 }, + { 19299512,1155910,28703737,14890794,2925026,7269399,26121523,15467869,-26560550,5052483 }, + }, +}, +{ + { + { -3017432,10058206,1980837,3964243,22160966,12322533,-6431123,-12618185,12228557,-7003677 }, + { 32944382,14922211,-22844894,5188528,21913450,-8719943,4001465,13238564,-6114803,8653815 }, + { 22865569,-4652735,27603668,-12545395,14348958,8234005,24808405,5719875,28483275,2841751 }, + }, + { + { -16420968,-1113305,-327719,-12107856,21886282,-15552774,-1887966,-315658,19932058,-12739203 }, + { -11656086,10087521,-8864888,-5536143,-19278573,-3055912,3999228,13239134,-4777469,-13910208 }, + { 1382174,-11694719,17266790,9194690,-13324356,9720081,20403944,11284705,-14013818,3093230 }, + }, + { + { 16650921,-11037932,-1064178,1570629,-8329746,7352753,-302424,16271225,-24049421,-6691850 }, + { -21911077,-5927941,-4611316,-5560156,-31744103,-10785293,24123614,15193618,-21652117,-16739389 }, + { -9935934,-4289447,-25279823,4372842,2087473,10399484,31870908,14690798,17361620,11864968 }, + }, + { + { -11307610,6210372,13206574,5806320,-29017692,-13967200,-12331205,-7486601,-25578460,-16240689 }, + { 14668462,-12270235,26039039,15305210,25515617,4542480,10453892,6577524,9145645,-6443880 }, + { 5974874,3053895,-9433049,-10385191,-31865124,3225009,-7972642,3936128,-5652273,-3050304 }, + }, + { + { 30625386,-4729400,-25555961,-12792866,-20484575,7695099,17097188,-16303496,-27999779,1803632 }, + { -3553091,9865099,-5228566,4272701,-5673832,-16689700,14911344,12196514,-21405489,7047412 }, + { 20093277,9920966,-11138194,-5343857,13161587,12044805,-32856851,4124601,-32343828,-10257566 }, + }, + { + { -20788824,14084654,-13531713,7842147,19119038,-13822605,4752377,-8714640,-21679658,2288038 }, + { -26819236,-3283715,29965059,3039786,-14473765,2540457,29457502,14625692,-24819617,12570232 }, + { -1063558,-11551823,16920318,12494842,1278292,-5869109,-21159943,-3498680,-11974704,4724943 }, + }, + { + { 17960970,-11775534,-4140968,-9702530,-8876562,-1410617,-12907383,-8659932,-29576300,1903856 }, + { 23134274,-14279132,-10681997,-1611936,20684485,15770816,-12989750,3190296,26955097,14109738 }, + { 15308788,5320727,-30113809,-14318877,22902008,7767164,29425325,-11277562,31960942,11934971 }, + }, + { + { -27395711,8435796,4109644,12222639,-24627868,14818669,20638173,4875028,10491392,1379718 }, + { -13159415,9197841,3875503,-8936108,-1383712,-5879801,33518459,16176658,21432314,12180697 }, + { -11787308,11500838,13787581,-13832590,-22430679,10140205,1465425,12689540,-10301319,-13872883 }, + }, +}, +{ + { + { 5414091,-15386041,-21007664,9643570,12834970,1186149,-2622916,-1342231,26128231,6032912 }, + { -26337395,-13766162,32496025,-13653919,17847801,-12669156,3604025,8316894,-25875034,-10437358 }, + { 3296484,6223048,24680646,-12246460,-23052020,5903205,-8862297,-4639164,12376617,3188849 }, + }, + { + { 29190488,-14659046,27549113,-1183516,3520066,-10697301,32049515,-7309113,-16109234,-9852307 }, + { -14744486,-9309156,735818,-598978,-20407687,-5057904,25246078,-15795669,18640741,-960977 }, + { -6928835,-16430795,10361374,5642961,4910474,12345252,-31638386,-494430,10530747,1053335 }, + }, + { + { -29265967,-14186805,-13538216,-12117373,-19457059,-10655384,-31462369,-2948985,24018831,15026644 }, + { -22592535,-3145277,-2289276,5953843,-13440189,9425631,25310643,13003497,-2314791,-15145616 }, + { -27419985,-603321,-8043984,-1669117,-26092265,13987819,-27297622,187899,-23166419,-2531735 }, + }, + { + { -21744398,-13810475,1844840,5021428,-10434399,-15911473,9716667,16266922,-5070217,726099 }, + { 29370922,-6053998,7334071,-15342259,9385287,2247707,-13661962,-4839461,30007388,-15823341 }, + { -936379,16086691,23751945,-543318,-1167538,-5189036,9137109,730663,9835848,4555336 }, + }, + { + { -23376435,1410446,-22253753,-12899614,30867635,15826977,17693930,544696,-11985298,12422646 }, + { 31117226,-12215734,-13502838,6561947,-9876867,-12757670,-5118685,-4096706,29120153,13924425 }, + { -17400879,-14233209,19675799,-2734756,-11006962,-5858820,-9383939,-11317700,7240931,-237388 }, + }, + { + { -31361739,-11346780,-15007447,-5856218,-22453340,-12152771,1222336,4389483,3293637,-15551743 }, + { -16684801,-14444245,11038544,11054958,-13801175,-3338533,-24319580,7733547,12796905,-6335822 }, + { -8759414,-10817836,-25418864,10783769,-30615557,-9746811,-28253339,3647836,3222231,-11160462 }, + }, + { + { 18606113,1693100,-25448386,-15170272,4112353,10045021,23603893,-2048234,-7550776,2484985 }, + { 9255317,-3131197,-12156162,-1004256,13098013,-9214866,16377220,-2102812,-19802075,-3034702 }, + { -22729289,7496160,-5742199,11329249,19991973,-3347502,-31718148,9936966,-30097688,-10618797 }, + }, + { + { 21878590,-5001297,4338336,13643897,-3036865,13160960,19708896,5415497,-7360503,-4109293 }, + { 27736861,10103576,12500508,8502413,-3413016,-9633558,10436918,-1550276,-23659143,-8132100 }, + { 19492550,-12104365,-29681976,-852630,-3208171,12403437,30066266,8367329,13243957,8709688 }, + }, +}, +{ + { + { 12015105,2801261,28198131,10151021,24818120,-4743133,-11194191,-5645734,5150968,7274186 }, + { 2831366,-12492146,1478975,6122054,23825128,-12733586,31097299,6083058,31021603,-9793610 }, + { -2529932,-2229646,445613,10720828,-13849527,-11505937,-23507731,16354465,15067285,-14147707 }, + }, + { + { 7840942,14037873,-33364863,15934016,-728213,-3642706,21403988,1057586,-19379462,-12403220 }, + { 915865,-16469274,15608285,-8789130,-24357026,6060030,-17371319,8410997,-7220461,16527025 }, + { 32922597,-556987,20336074,-16184568,10903705,-5384487,16957574,52992,23834301,6588044 }, + }, + { + { 32752030,11232950,3381995,-8714866,22652988,-10744103,17159699,16689107,-20314580,-1305992 }, + { -4689649,9166776,-25710296,-10847306,11576752,12733943,7924251,-2752281,1976123,-7249027 }, + { 21251222,16309901,-2983015,-6783122,30810597,12967303,156041,-3371252,12331345,-8237197 }, + }, + { + { 8651614,-4477032,-16085636,-4996994,13002507,2950805,29054427,-5106970,10008136,-4667901 }, + { 31486080,15114593,-14261250,12951354,14369431,-7387845,16347321,-13662089,8684155,-10532952 }, + { 19443825,11385320,24468943,-9659068,-23919258,2187569,-26263207,-6086921,31316348,14219878 }, + }, + { + { -28594490,1193785,32245219,11392485,31092169,15722801,27146014,6992409,29126555,9207390 }, + { 32382935,1110093,18477781,11028262,-27411763,-7548111,-4980517,10843782,-7957600,-14435730 }, + { 2814918,7836403,27519878,-7868156,-20894015,-11553689,-21494559,8550130,28346258,1994730 }, + }, + { + { -19578299,8085545,-14000519,-3948622,2785838,-16231307,-19516951,7174894,22628102,8115180 }, + { -30405132,955511,-11133838,-15078069,-32447087,-13278079,-25651578,3317160,-9943017,930272 }, + { -15303681,-6833769,28856490,1357446,23421993,1057177,24091212,-1388970,-22765376,-10650715 }, + }, + { + { -22751231,-5303997,-12907607,-12768866,-15811511,-7797053,-14839018,-16554220,-1867018,8398970 }, + { -31969310,2106403,-4736360,1362501,12813763,16200670,22981545,-6291273,18009408,-15772772 }, + { -17220923,-9545221,-27784654,14166835,29815394,7444469,29551787,-3727419,19288549,1325865 }, + }, + { + { 15100157,-15835752,-23923978,-1005098,-26450192,15509408,12376730,-3479146,33166107,-8042750 }, + { 20909231,13023121,-9209752,16251778,-5778415,-8094914,12412151,10018715,2213263,-13878373 }, + { 32529814,-11074689,30361439,-16689753,-9135940,1513226,22922121,6382134,-5766928,8371348 }, + }, +}, +{ + { + { 9923462,11271500,12616794,3544722,-29998368,-1721626,12891687,-8193132,-26442943,10486144 }, + { -22597207,-7012665,8587003,-8257861,4084309,-12970062,361726,2610596,-23921530,-11455195 }, + { 5408411,-1136691,-4969122,10561668,24145918,14240566,31319731,-4235541,19985175,-3436086 }, + }, + { + { -13994457,16616821,14549246,3341099,32155958,13648976,-17577068,8849297,65030,8370684 }, + { -8320926,-12049626,31204563,5839400,-20627288,-1057277,-19442942,6922164,12743482,-9800518 }, + { -2361371,12678785,28815050,4759974,-23893047,4884717,23783145,11038569,18800704,255233 }, + }, + { + { -5269658,-1773886,13957886,7990715,23132995,728773,13393847,9066957,19258688,-14753793 }, + { -2936654,-10827535,-10432089,14516793,-3640786,4372541,-31934921,2209390,-1524053,2055794 }, + { 580882,16705327,5468415,-2683018,-30926419,-14696000,-7203346,-8994389,-30021019,7394435 }, + }, + { + { 23838809,1822728,-15738443,15242727,8318092,-3733104,-21672180,-3492205,-4821741,14799921 }, + { 13345610,9759151,3371034,-16137791,16353039,8577942,31129804,13496856,-9056018,7402518 }, + { 2286874,-4435931,-20042458,-2008336,-13696227,5038122,11006906,-15760352,8205061,1607563 }, + }, + { + { 14414086,-8002132,3331830,-3208217,22249151,-5594188,18364661,-2906958,30019587,-9029278 }, + { -27688051,1585953,-10775053,931069,-29120221,-11002319,-14410829,12029093,9944378,8024 }, + { 4368715,-3709630,29874200,-15022983,-20230386,-11410704,-16114594,-999085,-8142388,5640030 }, + }, + { + { 10299610,13746483,11661824,16234854,7630238,5998374,9809887,-16694564,15219798,-14327783 }, + { 27425505,-5719081,3055006,10660664,23458024,595578,-15398605,-1173195,-18342183,9742717 }, + { 6744077,2427284,26042789,2720740,-847906,1118974,32324614,7406442,12420155,1994844 }, + }, + { + { 14012521,-5024720,-18384453,-9578469,-26485342,-3936439,-13033478,-10909803,24319929,-6446333 }, + { 16412690,-4507367,10772641,15929391,-17068788,-4658621,10555945,-10484049,-30102368,-4739048 }, + { 22397382,-7767684,-9293161,-12792868,17166287,-9755136,-27333065,6199366,21880021,-12250760 }, + }, + { + { -4283307,5368523,-31117018,8163389,-30323063,3209128,16557151,8890729,8840445,4957760 }, + { -15447727,709327,-6919446,-10870178,-29777922,6522332,-21720181,12130072,-14796503,5005757 }, + { -2114751,-14308128,23019042,15765735,-25269683,6002752,10183197,-13239326,-16395286,-2176112 }, + }, +}, +{ + { + { -19025756,1632005,13466291,-7995100,-23640451,16573537,-32013908,-3057104,22208662,2000468 }, + { 3065073,-1412761,-25598674,-361432,-17683065,-5703415,-8164212,11248527,-3691214,-7414184 }, + { 10379208,-6045554,8877319,1473647,-29291284,-12507580,16690915,2553332,-3132688,16400289 }, + }, + { + { 15716668,1254266,-18472690,7446274,-8448918,6344164,-22097271,-7285580,26894937,9132066 }, + { 24158887,12938817,11085297,-8177598,-28063478,-4457083,-30576463,64452,-6817084,-2692882 }, + { 13488534,7794716,22236231,5989356,25426474,-12578208,2350710,-3418511,-4688006,2364226 }, + }, + { + { 16335052,9132434,25640582,6678888,1725628,8517937,-11807024,-11697457,15445875,-7798101 }, + { 29004207,-7867081,28661402,-640412,-12794003,-7943086,31863255,-4135540,-278050,-15759279 }, + { -6122061,-14866665,-28614905,14569919,-10857999,-3591829,10343412,-6976290,-29828287,-10815811 }, + }, + { + { 27081650,3463984,14099042,-4517604,1616303,-6205604,29542636,15372179,17293797,960709 }, + { 20263915,11434237,-5765435,11236810,13505955,-10857102,-16111345,6493122,-19384511,7639714 }, + { -2830798,-14839232,25403038,-8215196,-8317012,-16173699,18006287,-16043750,29994677,-15808121 }, + }, + { + { 9769828,5202651,-24157398,-13631392,-28051003,-11561624,-24613141,-13860782,-31184575,709464 }, + { 12286395,13076066,-21775189,-1176622,-25003198,4057652,-32018128,-8890874,16102007,13205847 }, + { 13733362,5599946,10557076,3195751,-5557991,8536970,-25540170,8525972,10151379,10394400 }, + }, + { + { 4024660,-16137551,22436262,12276534,-9099015,-2686099,19698229,11743039,-33302334,8934414 }, + { -15879800,-4525240,-8580747,-2934061,14634845,-698278,-9449077,3137094,-11536886,11721158 }, + { 17555939,-5013938,8268606,2331751,-22738815,9761013,9319229,8835153,-9205489,-1280045 }, + }, + { + { -461409,-7830014,20614118,16688288,-7514766,-4807119,22300304,505429,6108462,-6183415 }, + { -5070281,12367917,-30663534,3234473,32617080,-8422642,29880583,-13483331,-26898490,-7867459 }, + { -31975283,5726539,26934134,10237677,-3173717,-605053,24199304,3795095,7592688,-14992079 }, + }, + { + { 21594432,-14964228,17466408,-4077222,32537084,2739898,6407723,12018833,-28256052,4298412 }, + { -20650503,-11961496,-27236275,570498,3767144,-1717540,13891942,-1569194,13717174,10805743 }, + { -14676630,-15644296,15287174,11927123,24177847,-8175568,-796431,14860609,-26938930,-5863836 }, + }, +}, +{ + { + { 12962541,5311799,-10060768,11658280,18855286,-7954201,13286263,-12808704,-4381056,9882022 }, + { 18512079,11319350,-20123124,15090309,18818594,5271736,-22727904,3666879,-23967430,-3299429 }, + { -6789020,-3146043,16192429,13241070,15898607,-14206114,-10084880,-6661110,-2403099,5276065 }, + }, + { + { 30169808,-5317648,26306206,-11750859,27814964,7069267,7152851,3684982,1449224,13082861 }, + { 10342826,3098505,2119311,193222,25702612,12233820,23697382,15056736,-21016438,-8202000 }, + { -33150110,3261608,22745853,7948688,19370557,-15177665,-26171976,6482814,-10300080,-11060101 }, + }, + { + { 32869458,-5408545,25609743,15678670,-10687769,-15471071,26112421,2521008,-22664288,6904815 }, + { 29506923,4457497,3377935,-9796444,-30510046,12935080,1561737,3841096,-29003639,-6657642 }, + { 10340844,-6630377,-18656632,-2278430,12621151,-13339055,30878497,-11824370,-25584551,5181966 }, + }, + { + { 25940115,-12658025,17324188,-10307374,-8671468,15029094,24396252,-16450922,-2322852,-12388574 }, + { -21765684,9916823,-1300409,4079498,-1028346,11909559,1782390,12641087,20603771,-6561742 }, + { -18882287,-11673380,24849422,11501709,13161720,-4768874,1925523,11914390,4662781,7820689 }, + }, + { + { 12241050,-425982,8132691,9393934,32846760,-1599620,29749456,12172924,16136752,15264020 }, + { -10349955,-14680563,-8211979,2330220,-17662549,-14545780,10658213,6671822,19012087,3772772 }, + { 3753511,-3421066,10617074,2028709,14841030,-6721664,28718732,-15762884,20527771,12988982 }, + }, + { + { -14822485,-5797269,-3707987,12689773,-898983,-10914866,-24183046,-10564943,3299665,-12424953 }, + { -16777703,-15253301,-9642417,4978983,3308785,8755439,6943197,6461331,-25583147,8991218 }, + { -17226263,1816362,-1673288,-6086439,31783888,-8175991,-32948145,7417950,-30242287,1507265 }, + }, + { + { 29692663,6829891,-10498800,4334896,20945975,-11906496,-28887608,8209391,14606362,-10647073 }, + { -3481570,8707081,32188102,5672294,22096700,1711240,-33020695,9761487,4170404,-2085325 }, + { -11587470,14855945,-4127778,-1531857,-26649089,15084046,22186522,16002000,-14276837,-8400798 }, + }, + { + { -4811456,13761029,-31703877,-2483919,-3312471,7869047,-7113572,-9620092,13240845,10965870 }, + { -7742563,-8256762,-14768334,-13656260,-23232383,12387166,4498947,14147411,29514390,4302863 }, + { -13413405,-12407859,20757302,-13801832,14785143,8976368,-5061276,-2144373,17846988,-13971927 }, + }, +}, +{ + { + { -2244452,-754728,-4597030,-1066309,-6247172,1455299,-21647728,-9214789,-5222701,12650267 }, + { -9906797,-16070310,21134160,12198166,-27064575,708126,387813,13770293,-19134326,10958663 }, + { 22470984,12369526,23446014,-5441109,-21520802,-9698723,-11772496,-11574455,-25083830,4271862 }, + }, + { + { -25169565,-10053642,-19909332,15361595,-5984358,2159192,75375,-4278529,-32526221,8469673 }, + { 15854970,4148314,-8893890,7259002,11666551,13824734,-30531198,2697372,24154791,-9460943 }, + { 15446137,-15806644,29759747,14019369,30811221,-9610191,-31582008,12840104,24913809,9815020 }, + }, + { + { -4709286,-5614269,-31841498,-12288893,-14443537,10799414,-9103676,13438769,18735128,9466238 }, + { 11933045,9281483,5081055,-5183824,-2628162,-4905629,-7727821,-10896103,-22728655,16199064 }, + { 14576810,379472,-26786533,-8317236,-29426508,-10812974,-102766,1876699,30801119,2164795 }, + }, + { + { 15995086,3199873,13672555,13712240,-19378835,-4647646,-13081610,-15496269,-13492807,1268052 }, + { -10290614,-3659039,-3286592,10948818,23037027,3794475,-3470338,-12600221,-17055369,3565904 }, + { 29210088,-9419337,-5919792,-4952785,10834811,-13327726,-16512102,-10820713,-27162222,-14030531 }, + }, + { + { -13161890,15508588,16663704,-8156150,-28349942,9019123,-29183421,-3769423,2244111,-14001979 }, + { -5152875,-3800936,-9306475,-6071583,16243069,14684434,-25673088,-16180800,13491506,4641841 }, + { 10813417,643330,-19188515,-728916,30292062,-16600078,27548447,-7721242,14476989,-12767431 }, + }, + { + { 10292079,9984945,6481436,8279905,-7251514,7032743,27282937,-1644259,-27912810,12651324 }, + { -31185513,-813383,22271204,11835308,10201545,15351028,17099662,3988035,21721536,-3148940 }, + { 10202177,-6545839,-31373232,-9574638,-32150642,-8119683,-12906320,3852694,13216206,14842320 }, + }, + { + { -15815640,-10601066,-6538952,-7258995,-6984659,-6581778,-31500847,13765824,-27434397,9900184 }, + { 14465505,-13833331,-32133984,-14738873,-27443187,12990492,33046193,15796406,-7051866,-8040114 }, + { 30924417,-8279620,6359016,-12816335,16508377,9071735,-25488601,15413635,9524356,-7018878 }, + }, + { + { 12274201,-13175547,32627641,-1785326,6736625,13267305,5237659,-5109483,15663516,4035784 }, + { -2951309,8903985,17349946,601635,-16432815,-4612556,-13732739,-15889334,-22258478,4659091 }, + { -16916263,-4952973,-30393711,-15158821,20774812,15897498,5736189,15026997,-2178256,-13455585 }, + }, +}, +{ + { + { -8858980,-2219056,28571666,-10155518,-474467,-10105698,-3801496,278095,23440562,-290208 }, + { 10226241,-5928702,15139956,120818,-14867693,5218603,32937275,11551483,-16571960,-7442864 }, + { 17932739,-12437276,-24039557,10749060,11316803,7535897,22503767,5561594,-3646624,3898661 }, + }, + { + { 7749907,-969567,-16339731,-16464,-25018111,15122143,-1573531,7152530,21831162,1245233 }, + { 26958459,-14658026,4314586,8346991,-5677764,11960072,-32589295,-620035,-30402091,-16716212 }, + { -12165896,9166947,33491384,13673479,29787085,13096535,6280834,14587357,-22338025,13987525 }, + }, + { + { -24349909,7778775,21116000,15572597,-4833266,-5357778,-4300898,-5124639,-7469781,-2858068 }, + { 9681908,-6737123,-31951644,13591838,-6883821,386950,31622781,6439245,-14581012,4091397 }, + { -8426427,1470727,-28109679,-1596990,3978627,-5123623,-19622683,12092163,29077877,-14741988 }, + }, + { + { 5269168,-6859726,-13230211,-8020715,25932563,1763552,-5606110,-5505881,-20017847,2357889 }, + { 32264008,-15407652,-5387735,-1160093,-2091322,-3946900,23104804,-12869908,5727338,189038 }, + { 14609123,-8954470,-6000566,-16622781,-14577387,-7743898,-26745169,10942115,-25888931,-14884697 }, + }, + { + { 20513500,5557931,-15604613,7829531,26413943,-2019404,-21378968,7471781,13913677,-5137875 }, + { -25574376,11967826,29233242,12948236,-6754465,4713227,-8940970,14059180,12878652,8511905 }, + { -25656801,3393631,-2955415,-7075526,-2250709,9366908,-30223418,6812974,5568676,-3127656 }, + }, + { + { 11630004,12144454,2116339,13606037,27378885,15676917,-17408753,-13504373,-14395196,8070818 }, + { 27117696,-10007378,-31282771,-5570088,1127282,12772488,-29845906,10483306,-11552749,-1028714 }, + { 10637467,-5688064,5674781,1072708,-26343588,-6982302,-1683975,9177853,-27493162,15431203 }, + }, + { + { 20525145,10892566,-12742472,12779443,-29493034,16150075,-28240519,14943142,-15056790,-7935931 }, + { -30024462,5626926,-551567,-9981087,753598,11981191,25244767,-3239766,-3356550,9594024 }, + { -23752644,2636870,-5163910,-10103818,585134,7877383,11345683,-6492290,13352335,-10977084 }, + }, + { + { -1931799,-5407458,3304649,-12884869,17015806,-4877091,-29783850,-7752482,-13215537,-319204 }, + { 20239939,6607058,6203985,3483793,-18386976,-779229,-20723742,15077870,-22750759,14523817 }, + { 27406042,-6041657,27423596,-4497394,4996214,10002360,-28842031,-4545494,-30172742,-4805667 }, + }, +}, +{ + { + { 11374242,12660715,17861383,-12540833,10935568,1099227,-13886076,-9091740,-27727044,11358504 }, + { -12730809,10311867,1510375,10778093,-2119455,-9145702,32676003,11149336,-26123651,4985768 }, + { -19096303,341147,-6197485,-239033,15756973,-8796662,-983043,13794114,-19414307,-15621255 }, + }, + { + { 6490081,11940286,25495923,-7726360,8668373,-8751316,3367603,6970005,-1691065,-9004790 }, + { 1656497,13457317,15370807,6364910,13605745,8362338,-19174622,-5475723,-16796596,-5031438 }, + { -22273315,-13524424,-64685,-4334223,-18605636,-10921968,-20571065,-7007978,-99853,-10237333 }, + }, + { + { 17747465,10039260,19368299,-4050591,-20630635,-16041286,31992683,-15857976,-29260363,-5511971 }, + { 31932027,-4986141,-19612382,16366580,22023614,88450,11371999,-3744247,4882242,-10626905 }, + { 29796507,37186,19818052,10115756,-11829032,3352736,18551198,3272828,-5190932,-4162409 }, + }, + { + { 12501286,4044383,-8612957,-13392385,-32430052,5136599,-19230378,-3529697,330070,-3659409 }, + { 6384877,2899513,17807477,7663917,-2358888,12363165,25366522,-8573892,-271295,12071499 }, + { -8365515,-4042521,25133448,-4517355,-6211027,2265927,-32769618,1936675,-5159697,3829363 }, + }, + { + { 28425966,-5835433,-577090,-4697198,-14217555,6870930,7921550,-6567787,26333140,14267664 }, + { -11067219,11871231,27385719,-10559544,-4585914,-11189312,10004786,-8709488,-21761224,8930324 }, + { -21197785,-16396035,25654216,-1725397,12282012,11008919,1541940,4757911,-26491501,-16408940 }, + }, + { + { 13537262,-7759490,-20604840,10961927,-5922820,-13218065,-13156584,6217254,-15943699,13814990 }, + { -17422573,15157790,18705543,29619,24409717,-260476,27361681,9257833,-1956526,-1776914 }, + { -25045300,-10191966,15366585,15166509,-13105086,8423556,-29171540,12361135,-18685978,4578290 }, + }, + { + { 24579768,3711570,1342322,-11180126,-27005135,14124956,-22544529,14074919,21964432,8235257 }, + { -6528613,-2411497,9442966,-5925588,12025640,-1487420,-2981514,-1669206,13006806,2355433 }, + { -16304899,-13605259,-6632427,-5142349,16974359,-10911083,27202044,1719366,1141648,-12796236 }, + }, + { + { -12863944,-13219986,-8318266,-11018091,-6810145,-4843894,13475066,-3133972,32674895,13715045 }, + { 11423335,-5468059,32344216,8962751,24989809,9241752,-13265253,16086212,-28740881,-15642093 }, + { -1409668,12530728,-6368726,10847387,19531186,-14132160,-11709148,7791794,-27245943,4383347 }, + }, +}, +{ + { + { -28970898,5271447,-1266009,-9736989,-12455236,16732599,-4862407,-4906449,27193557,6245191 }, + { -15193956,5362278,-1783893,2695834,4960227,12840725,23061898,3260492,22510453,8577507 }, + { -12632451,11257346,-32692994,13548177,-721004,10879011,31168030,13952092,-29571492,-3635906 }, + }, + { + { 3877321,-9572739,32416692,5405324,-11004407,-13656635,3759769,11935320,5611860,8164018 }, + { -16275802,14667797,15906460,12155291,-22111149,-9039718,32003002,-8832289,5773085,-8422109 }, + { -23788118,-8254300,1950875,8937633,18686727,16459170,-905725,12376320,31632953,190926 }, + }, + { + { -24593607,-16138885,-8423991,13378746,14162407,6901328,-8288749,4508564,-25341555,-3627528 }, + { 8884438,-5884009,6023974,10104341,-6881569,-4941533,18722941,-14786005,-1672488,827625 }, + { -32720583,-16289296,-32503547,7101210,13354605,2659080,-1800575,-14108036,-24878478,1541286 }, + }, + { + { 2901347,-1117687,3880376,-10059388,-17620940,-3612781,-21802117,-3567481,20456845,-1885033 }, + { 27019610,12299467,-13658288,-1603234,-12861660,-4861471,-19540150,-5016058,29439641,15138866 }, + { 21536104,-6626420,-32447818,-10690208,-22408077,5175814,-5420040,-16361163,7779328,109896 }, + }, + { + { 30279744,14648750,-8044871,6425558,13639621,-743509,28698390,12180118,23177719,-554075 }, + { 26572847,3405927,-31701700,12890905,-19265668,5335866,-6493768,2378492,4439158,-13279347 }, + { -22716706,3489070,-9225266,-332753,18875722,-1140095,14819434,-12731527,-17717757,-5461437 }, + }, + { + { -5056483,16566551,15953661,3767752,-10436499,15627060,-820954,2177225,8550082,-15114165 }, + { -18473302,16596775,-381660,15663611,22860960,15585581,-27844109,-3582739,-23260460,-8428588 }, + { -32480551,15707275,-8205912,-5652081,29464558,2713815,-22725137,15860482,-21902570,1494193 }, + }, + { + { -19562091,-14087393,-25583872,-9299552,13127842,759709,21923482,16529112,8742704,12967017 }, + { -28464899,1553205,32536856,-10473729,-24691605,-406174,-8914625,-2933896,-29903758,15553883 }, + { 21877909,3230008,9881174,10539357,-4797115,2841332,11543572,14513274,19375923,-12647961 }, + }, + { + { 8832269,-14495485,13253511,5137575,5037871,4078777,24880818,-6222716,2862653,9455043 }, + { 29306751,5123106,20245049,-14149889,9592566,8447059,-2077124,-2990080,15511449,4789663 }, + { -20679756,7004547,8824831,-9434977,-4045704,-3750736,-5754762,108893,23513200,16652362 }, + }, +}, +{ + { + { -33256173,4144782,-4476029,-6579123,10770039,-7155542,-6650416,-12936300,-18319198,10212860 }, + { 2756081,8598110,7383731,-6859892,22312759,-1105012,21179801,2600940,-9988298,-12506466 }, + { -24645692,13317462,-30449259,-15653928,21365574,-10869657,11344424,864440,-2499677,-16710063 }, + }, + { + { -26432803,6148329,-17184412,-14474154,18782929,-275997,-22561534,211300,2719757,4940997 }, + { -1323882,3911313,-6948744,14759765,-30027150,7851207,21690126,8518463,26699843,5276295 }, + { -13149873,-6429067,9396249,365013,24703301,-10488939,1321586,149635,-15452774,7159369 }, + }, + { + { 9987780,-3404759,17507962,9505530,9731535,-2165514,22356009,8312176,22477218,-8403385 }, + { 18155857,-16504990,19744716,9006923,15154154,-10538976,24256460,-4864995,-22548173,9334109 }, + { 2986088,-4911893,10776628,-3473844,10620590,-7083203,-21413845,14253545,-22587149,536906 }, + }, + { + { 4377756,8115836,24567078,15495314,11625074,13064599,7390551,10589625,10838060,-15420424 }, + { -19342404,867880,9277171,-3218459,-14431572,-1986443,19295826,-15796950,6378260,699185 }, + { 7895026,4057113,-7081772,-13077756,-17886831,-323126,-716039,15693155,-5045064,-13373962 }, + }, + { + { -7737563,-5869402,-14566319,-7406919,11385654,13201616,31730678,-10962840,-3918636,-9669325 }, + { 10188286,-15770834,-7336361,13427543,22223443,14896287,30743455,7116568,-21786507,5427593 }, + { 696102,13206899,27047647,-10632082,15285305,-9853179,10798490,-4578720,19236243,12477404 }, + }, + { + { -11229439,11243796,-17054270,-8040865,-788228,-8167967,-3897669,11180504,-23169516,7733644 }, + { 17800790,-14036179,-27000429,-11766671,23887827,3149671,23466177,-10538171,10322027,15313801 }, + { 26246234,11968874,32263343,-5468728,6830755,-13323031,-15794704,-101982,-24449242,10890804 }, + }, + { + { -31365647,10271363,-12660625,-6267268,16690207,-13062544,-14982212,16484931,25180797,-5334884 }, + { -586574,10376444,-32586414,-11286356,19801893,10997610,2276632,9482883,316878,13820577 }, + { -9882808,-4510367,-2115506,16457136,-11100081,11674996,30756178,-7515054,30696930,-3712849 }, + }, + { + { 32988917,-9603412,12499366,7910787,-10617257,-11931514,-7342816,-9985397,-32349517,7392473 }, + { -8855661,15927861,9866406,-3649411,-2396914,-16655781,-30409476,-9134995,25112947,-2926644 }, + { -2504044,-436966,25621774,-5678772,15085042,-5479877,-24884878,-13526194,5537438,-13914319 }, + }, +}, +{ + { + { -11225584,2320285,-9584280,10149187,-33444663,5808648,-14876251,-1729667,31234590,6090599 }, + { -9633316,116426,26083934,2897444,-6364437,-2688086,609721,15878753,-6970405,-9034768 }, + { -27757857,247744,-15194774,-9002551,23288161,-10011936,-23869595,6503646,20650474,1804084 }, + }, + { + { -27589786,15456424,8972517,8469608,15640622,4439847,3121995,-10329713,27842616,-202328 }, + { -15306973,2839644,22530074,10026331,4602058,5048462,28248656,5031932,-11375082,12714369 }, + { 20807691,-7270825,29286141,11421711,-27876523,-13868230,-21227475,1035546,-19733229,12796920 }, + }, + { + { 12076899,-14301286,-8785001,-11848922,-25012791,16400684,-17591495,-12899438,3480665,-15182815 }, + { -32361549,5457597,28548107,7833186,7303070,-11953545,-24363064,-15921875,-33374054,2771025 }, + { -21389266,421932,26597266,6860826,22486084,-6737172,-17137485,-4210226,-24552282,15673397 }, + }, + { + { -20184622,2338216,19788685,-9620956,-4001265,-8740893,-20271184,4733254,3727144,-12934448 }, + { 6120119,814863,-11794402,-622716,6812205,-15747771,2019594,7975683,31123697,-10958981 }, + { 30069250,-11435332,30434654,2958439,18399564,-976289,12296869,9204260,-16432438,9648165 }, + }, + { + { 32705432,-1550977,30705658,7451065,-11805606,9631813,3305266,5248604,-26008332,-11377501 }, + { 17219865,2375039,-31570947,-5575615,-19459679,9219903,294711,15298639,2662509,-16297073 }, + { -1172927,-7558695,-4366770,-4287744,-21346413,-8434326,32087529,-1222777,32247248,-14389861 }, + }, + { + { 14312628,1221556,17395390,-8700143,-4945741,-8684635,-28197744,-9637817,-16027623,-13378845 }, + { -1428825,-9678990,-9235681,6549687,-7383069,-468664,23046502,9803137,17597934,2346211 }, + { 18510800,15337574,26171504,981392,-22241552,7827556,-23491134,-11323352,3059833,-11782870 }, + }, + { + { 10141598,6082907,17829293,-1947643,9830092,13613136,-25556636,-5544586,-33502212,3592096 }, + { 33114168,-15889352,-26525686,-13343397,33076705,8716171,1151462,1521897,-982665,-6837803 }, + { -32939165,-4255815,23947181,-324178,-33072974,-12305637,-16637686,3891704,26353178,693168 }, + }, + { + { 30374239,1595580,-16884039,13186931,4600344,406904,9585294,-400668,31375464,14369965 }, + { -14370654,-7772529,1510301,6434173,-18784789,-6262728,32732230,-13108839,17901441,16011505 }, + { 18171223,-11934626,-12500402,15197122,-11038147,-15230035,-19172240,-16046376,8764035,12309598 }, + }, +}, +{ + { + { 5975908,-5243188,-19459362,-9681747,-11541277,14015782,-23665757,1228319,17544096,-10593782 }, + { 5811932,-1715293,3442887,-2269310,-18367348,-8359541,-18044043,-15410127,-5565381,12348900 }, + { -31399660,11407555,25755363,6891399,-3256938,14872274,-24849353,8141295,-10632534,-585479 }, + }, + { + { -12675304,694026,-5076145,13300344,14015258,-14451394,-9698672,-11329050,30944593,1130208 }, + { 8247766,-6710942,-26562381,-7709309,-14401939,-14648910,4652152,2488540,23550156,-271232 }, + { 17294316,-3788438,7026748,15626851,22990044,113481,2267737,-5908146,-408818,-137719 }, + }, + { + { 16091085,-16253926,18599252,7340678,2137637,-1221657,-3364161,14550936,3260525,-7166271 }, + { -4910104,-13332887,18550887,10864893,-16459325,-7291596,-23028869,-13204905,-12748722,2701326 }, + { -8574695,16099415,4629974,-16340524,-20786213,-6005432,-10018363,9276971,11329923,1862132 }, + }, + { + { 14763076,-15903608,-30918270,3689867,3511892,10313526,-21951088,12219231,-9037963,-940300 }, + { 8894987,-3446094,6150753,3013931,301220,15693451,-31981216,-2909717,-15438168,11595570 }, + { 15214962,3537601,-26238722,-14058872,4418657,-15230761,13947276,10730794,-13489462,-4363670 }, + }, + { + { -2538306,7682793,32759013,263109,-29984731,-7955452,-22332124,-10188635,977108,699994 }, + { -12466472,4195084,-9211532,550904,-15565337,12917920,19118110,-439841,-30534533,-14337913 }, + { 31788461,-14507657,4799989,7372237,8808585,-14747943,9408237,-10051775,12493932,-5409317 }, + }, + { + { -25680606,5260744,-19235809,-6284470,-3695942,16566087,27218280,2607121,29375955,6024730 }, + { 842132,-2794693,-4763381,-8722815,26332018,-12405641,11831880,6985184,-9940361,2854096 }, + { -4847262,-7969331,2516242,-5847713,9695691,-7221186,16512645,960770,12121869,16648078 }, + }, + { + { -15218652,14667096,-13336229,2013717,30598287,-464137,-31504922,-7882064,20237806,2838411 }, + { -19288047,4453152,15298546,-16178388,22115043,-15972604,12544294,-13470457,1068881,-12499905 }, + { -9558883,-16518835,33238498,13506958,30505848,-1114596,-8486907,-2630053,12521378,4845654 }, + }, + { + { -28198521,10744108,-2958380,10199664,7759311,-13088600,3409348,-873400,-6482306,-12885870 }, + { -23561822,6230156,-20382013,10655314,-24040585,-11621172,10477734,-1240216,-3113227,13974498 }, + { 12966261,15550616,-32038948,-1615346,21025980,-629444,5642325,7188737,18895762,12629579 }, + }, +}, +{ + { + { 14741879,-14946887,22177208,-11721237,1279741,8058600,11758140,789443,32195181,3895677 }, + { 10758205,15755439,-4509950,9243698,-4879422,6879879,-2204575,-3566119,-8982069,4429647 }, + { -2453894,15725973,-20436342,-10410672,-5803908,-11040220,-7135870,-11642895,18047436,-15281743 }, + }, + { + { -25173001,-11307165,29759956,11776784,-22262383,-15820455,10993114,-12850837,-17620701,-9408468 }, + { 21987233,700364,-24505048,14972008,-7774265,-5718395,32155026,2581431,-29958985,8773375 }, + { -25568350,454463,-13211935,16126715,25240068,8594567,20656846,12017935,-7874389,-13920155 }, + }, + { + { 6028182,6263078,-31011806,-11301710,-818919,2461772,-31841174,-5468042,-1721788,-2776725 }, + { -12278994,16624277,987579,-5922598,32908203,1248608,7719845,-4166698,28408820,6816612 }, + { -10358094,-8237829,19549651,-12169222,22082623,16147817,20613181,13982702,-10339570,5067943 }, + }, + { + { -30505967,-3821767,12074681,13582412,-19877972,2443951,-19719286,12746132,5331210,-10105944 }, + { 30528811,3601899,-1957090,4619785,-27361822,-15436388,24180793,-12570394,27679908,-1648928 }, + { 9402404,-13957065,32834043,10838634,-26580150,-13237195,26653274,-8685565,22611444,-12715406 }, + }, + { + { 22190590,1118029,22736441,15130463,-30460692,-5991321,19189625,-4648942,4854859,6622139 }, + { -8310738,-2953450,-8262579,-3388049,-10401731,-271929,13424426,-3567227,26404409,13001963 }, + { -31241838,-15415700,-2994250,8939346,11562230,-12840670,-26064365,-11621720,-15405155,11020693 }, + }, + { + { 1866042,-7949489,-7898649,-10301010,12483315,13477547,3175636,-12424163,28761762,1406734 }, + { -448555,-1777666,13018551,3194501,-9580420,-11161737,24760585,-4347088,25577411,-13378680 }, + { -24290378,4759345,-690653,-1852816,2066747,10693769,-29595790,9884936,-9368926,4745410 }, + }, + { + { -9141284,6049714,-19531061,-4341411,-31260798,9944276,-15462008,-11311852,10931924,-11931931 }, + { -16561513,14112680,-8012645,4817318,-8040464,-11414606,-22853429,10856641,-20470770,13434654 }, + { 22759489,-10073434,-16766264,-1871422,13637442,-10168091,1765144,-12654326,28445307,-5364710 }, + }, + { + { 29875063,12493613,2795536,-3786330,1710620,15181182,-10195717,-8788675,9074234,1167180 }, + { -26205683,11014233,-9842651,-2635485,-26908120,7532294,-18716888,-9535498,3843903,9367684 }, + { -10969595,-6403711,9591134,9582310,11349256,108879,16235123,8601684,-139197,4242895 }, + }, +}, +{ + { + { 22092954,-13191123,-2042793,-11968512,32186753,-11517388,-6574341,2470660,-27417366,16625501 }, + { -11057722,3042016,13770083,-9257922,584236,-544855,-7770857,2602725,-27351616,14247413 }, + { 6314175,-10264892,-32772502,15957557,-10157730,168750,-8618807,14290061,27108877,-1180880 }, + }, + { + { -8586597,-7170966,13241782,10960156,-32991015,-13794596,33547976,-11058889,-27148451,981874 }, + { 22833440,9293594,-32649448,-13618667,-9136966,14756819,-22928859,-13970780,-10479804,-16197962 }, + { -7768587,3326786,-28111797,10783824,19178761,14905060,22680049,13906969,-15933690,3797899 }, + }, + { + { 21721356,-4212746,-12206123,9310182,-3882239,-13653110,23740224,-2709232,20491983,-8042152 }, + { 9209270,-15135055,-13256557,-6167798,-731016,15289673,25947805,15286587,30997318,-6703063 }, + { 7392032,16618386,23946583,-8039892,-13265164,-1533858,-14197445,-2321576,17649998,-250080 }, + }, + { + { -9301088,-14193827,30609526,-3049543,-25175069,-1283752,-15241566,-9525724,-2233253,7662146 }, + { -17558673,1763594,-33114336,15908610,-30040870,-12174295,7335080,-8472199,-3174674,3440183 }, + { -19889700,-5977008,-24111293,-9688870,10799743,-16571957,40450,-4431835,4862400,1133 }, + }, + { + { -32856209,-7873957,-5422389,14860950,-16319031,7956142,7258061,311861,-30594991,-7379421 }, + { -3773428,-1565936,28985340,7499440,24445838,9325937,29727763,16527196,18278453,15405622 }, + { -4381906,8508652,-19898366,-3674424,-5984453,15149970,-13313598,843523,-21875062,13626197 }, + }, + { + { 2281448,-13487055,-10915418,-2609910,1879358,16164207,-10783882,3953792,13340839,15928663 }, + { 31727126,-7179855,-18437503,-8283652,2875793,-16390330,-25269894,-7014826,-23452306,5964753 }, + { 4100420,-5959452,-17179337,6017714,-18705837,12227141,-26684835,11344144,2538215,-7570755 }, + }, + { + { -9433605,6123113,11159803,-2156608,30016280,14966241,-20474983,1485421,-629256,-15958862 }, + { -26804558,4260919,11851389,9658551,-32017107,16367492,-20205425,-13191288,11659922,-11115118 }, + { 26180396,10015009,-30844224,-8581293,5418197,9480663,2231568,-10170080,33100372,-1306171 }, + }, + { + { 15121113,-5201871,-10389905,15427821,-27509937,-15992507,21670947,4486675,-5931810,-14466380 }, + { 16166486,-9483733,-11104130,6023908,-31926798,-1364923,2340060,-16254968,-10735770,-10039824 }, + { 28042865,-3557089,-12126526,12259706,-3717498,-6945899,6766453,-8689599,18036436,5803270 }, + }, +}, +{ + { + { -817581,6763912,11803561,1585585,10958447,-2671165,23855391,4598332,-6159431,-14117438 }, + { -31031306,-14256194,17332029,-2383520,31312682,-5967183,696309,50292,-20095739,11763584 }, + { -594563,-2514283,-32234153,12643980,12650761,14811489,665117,-12613632,-19773211,-10713562 }, + }, + { + { 30464590,-11262872,-4127476,-12734478,19835327,-7105613,-24396175,2075773,-17020157,992471 }, + { 18357185,-6994433,7766382,16342475,-29324918,411174,14578841,8080033,-11574335,-10601610 }, + { 19598397,10334610,12555054,2555664,18821899,-10339780,21873263,16014234,26224780,16452269 }, + }, + { + { -30223925,5145196,5944548,16385966,3976735,2009897,-11377804,-7618186,-20533829,3698650 }, + { 14187449,3448569,-10636236,-10810935,-22663880,-3433596,7268410,-10890444,27394301,12015369 }, + { 19695761,16087646,28032085,12999827,6817792,11427614,20244189,-1312777,-13259127,-3402461 }, + }, + { + { 30860103,12735208,-1888245,-4699734,-16974906,2256940,-8166013,12298312,-8550524,-10393462 }, + { -5719826,-11245325,-1910649,15569035,26642876,-7587760,-5789354,-15118654,-4976164,12651793 }, + { -2848395,9953421,11531313,-5282879,26895123,-12697089,-13118820,-16517902,9768698,-2533218 }, + }, + { + { -24719459,1894651,-287698,-4704085,15348719,-8156530,32767513,12765450,4940095,10678226 }, + { 18860224,15980149,-18987240,-1562570,-26233012,-11071856,-7843882,13944024,-24372348,16582019 }, + { -15504260,4970268,-29893044,4175593,-20993212,-2199756,-11704054,15444560,-11003761,7989037 }, + }, + { + { 31490452,5568061,-2412803,2182383,-32336847,4531686,-32078269,6200206,-19686113,-14800171 }, + { -17308668,-15879940,-31522777,-2831,-32887382,16375549,8680158,-16371713,28550068,-6857132 }, + { -28126887,-5688091,16837845,-1820458,-6850681,12700016,-30039981,4364038,1155602,5988841 }, + }, + { + { 21890435,-13272907,-12624011,12154349,-7831873,15300496,23148983,-4470481,24618407,8283181 }, + { -33136107,-10512751,9975416,6841041,-31559793,16356536,3070187,-7025928,1466169,10740210 }, + { -1509399,-15488185,-13503385,-10655916,32799044,909394,-13938903,-5779719,-32164649,-15327040 }, + }, + { + { 3960823,-14267803,-28026090,-15918051,-19404858,13146868,15567327,951507,-3260321,-573935 }, + { 24740841,5052253,-30094131,8961361,25877428,6165135,-24368180,14397372,-7380369,-6144105 }, + { -28888365,3510803,-28103278,-1158478,-11238128,-10631454,-15441463,-14453128,-1625486,-6494814 }, + }, +}, +{ + { + { 793299,-9230478,8836302,-6235707,-27360908,-2369593,33152843,-4885251,-9906200,-621852 }, + { 5666233,525582,20782575,-8038419,-24538499,14657740,16099374,1468826,-6171428,-15186581 }, + { -4859255,-3779343,-2917758,-6748019,7778750,11688288,-30404353,-9871238,-1558923,-9863646 }, + }, + { + { 10896332,-7719704,824275,472601,-19460308,3009587,25248958,14783338,-30581476,-15757844 }, + { 10566929,12612572,-31944212,11118703,-12633376,12362879,21752402,8822496,24003793,14264025 }, + { 27713862,-7355973,-11008240,9227530,27050101,2504721,23886875,-13117525,13958495,-5732453 }, + }, + { + { -23481610,4867226,-27247128,3900521,29838369,-8212291,-31889399,-10041781,7340521,-15410068 }, + { 4646514,-8011124,-22766023,-11532654,23184553,8566613,31366726,-1381061,-15066784,-10375192 }, + { -17270517,12723032,-16993061,14878794,21619651,-6197576,27584817,3093888,-8843694,3849921 }, + }, + { + { -9064912,2103172,25561640,-15125738,-5239824,9582958,32477045,-9017955,5002294,-15550259 }, + { -12057553,-11177906,21115585,-13365155,8808712,-12030708,16489530,13378448,-25845716,12741426 }, + { -5946367,10645103,-30911586,15390284,-3286982,-7118677,24306472,15852464,28834118,-7646072 }, + }, + { + { -17335748,-9107057,-24531279,9434953,-8472084,-583362,-13090771,455841,20461858,5491305 }, + { 13669248,-16095482,-12481974,-10203039,-14569770,-11893198,-24995986,11293807,-28588204,-9421832 }, + { 28497928,6272777,-33022994,14470570,8906179,-1225630,18504674,-14165166,29867745,-8795943 }, + }, + { + { -16207023,13517196,-27799630,-13697798,24009064,-6373891,-6367600,-13175392,22853429,-4012011 }, + { 24191378,16712145,-13931797,15217831,14542237,1646131,18603514,-11037887,12876623,-2112447 }, + { 17902668,4518229,-411702,-2829247,26878217,5258055,-12860753,608397,16031844,3723494 }, + }, + { + { -28632773,12763728,-20446446,7577504,33001348,-13017745,17558842,-7872890,23896954,-4314245 }, + { -20005381,-12011952,31520464,605201,2543521,5991821,-2945064,7229064,-9919646,-8826859 }, + { 28816045,298879,-28165016,-15920938,19000928,-1665890,-12680833,-2949325,-18051778,-2082915 }, + }, + { + { 16000882,-344896,3493092,-11447198,-29504595,-13159789,12577740,16041268,-19715240,7847707 }, + { 10151868,10572098,27312476,7922682,14825339,4723128,-32855931,-6519018,-10020567,3852848 }, + { -11430470,15697596,-21121557,-4420647,5386314,15063598,16514493,-15932110,29330899,-15076224 }, + }, +}, +{ + { + { -25499735,-4378794,-15222908,-6901211,16615731,2051784,3303702,15490,-27548796,12314391 }, + { 15683520,-6003043,18109120,-9980648,15337968,-5997823,-16717435,15921866,16103996,-3731215 }, + { -23169824,-10781249,13588192,-1628807,-3798557,-1074929,-19273607,5402699,-29815713,-9841101 }, + }, + { + { 23190676,2384583,-32714340,3462154,-29903655,-1529132,-11266856,8911517,-25205859,2739713 }, + { 21374101,-3554250,-33524649,9874411,15377179,11831242,-33529904,6134907,4931255,11987849 }, + { -7732,-2978858,-16223486,7277597,105524,-322051,-31480539,13861388,-30076310,10117930 }, + }, + { + { -29501170,-10744872,-26163768,13051539,-25625564,5089643,-6325503,6704079,12890019,15728940 }, + { -21972360,-11771379,-951059,-4418840,14704840,2695116,903376,-10428139,12885167,8311031 }, + { -17516482,5352194,10384213,-13811658,7506451,13453191,26423267,4384730,1888765,-5435404 }, + }, + { + { -25817338,-3107312,-13494599,-3182506,30896459,-13921729,-32251644,-12707869,-19464434,-3340243 }, + { -23607977,-2665774,-526091,4651136,5765089,4618330,6092245,14845197,17151279,-9854116 }, + { -24830458,-12733720,-15165978,10367250,-29530908,-265356,22825805,-7087279,-16866484,16176525 }, + }, + { + { -23583256,6564961,20063689,3798228,-4740178,7359225,2006182,-10363426,-28746253,-10197509 }, + { -10626600,-4486402,-13320562,-5125317,3432136,-6393229,23632037,-1940610,32808310,1099883 }, + { 15030977,5768825,-27451236,-2887299,-6427378,-15361371,-15277896,-6809350,2051441,-15225865 }, + }, + { + { -3362323,-7239372,7517890,9824992,23555850,295369,5148398,-14154188,-22686354,16633660 }, + { 4577086,-16752288,13249841,-15304328,19958763,-14537274,18559670,-10759549,8402478,-9864273 }, + { -28406330,-1051581,-26790155,-907698,-17212414,-11030789,9453451,-14980072,17983010,9967138 }, + }, + { + { -25762494,6524722,26585488,9969270,24709298,1220360,-1677990,7806337,17507396,3651560 }, + { -10420457,-4118111,14584639,15971087,-15768321,8861010,26556809,-5574557,-18553322,-11357135 }, + { 2839101,14284142,4029895,3472686,14402957,12689363,-26642121,8459447,-5605463,-7621941 }, + }, + { + { -4839289,-3535444,9744961,2871048,25113978,3187018,-25110813,-849066,17258084,-7977739 }, + { 18164541,-10595176,-17154882,-1542417,19237078,-9745295,23357533,-15217008,26908270,12150756 }, + { -30264870,-7647865,5112249,-7036672,-1499807,-6974257,43168,-5537701,-32302074,16215819 }, + }, +}, +{ + { + { -6898905,9824394,-12304779,-4401089,-31397141,-6276835,32574489,12532905,-7503072,-8675347 }, + { -27343522,-16515468,-27151524,-10722951,946346,16291093,254968,7168080,21676107,-1943028 }, + { 21260961,-8424752,-16831886,-11920822,-23677961,3968121,-3651949,-6215466,-3556191,-7913075 }, + }, + { + { 16544754,13250366,-16804428,15546242,-4583003,12757258,-2462308,-8680336,-18907032,-9662799 }, + { -2415239,-15577728,18312303,4964443,-15272530,-12653564,26820651,16690659,25459437,-4564609 }, + { -25144690,11425020,28423002,-11020557,-6144921,-15826224,9142795,-2391602,-6432418,-1644817 }, + }, + { + { -23104652,6253476,16964147,-3768872,-25113972,-12296437,-27457225,-16344658,6335692,7249989 }, + { -30333227,13979675,7503222,-12368314,-11956721,-4621693,-30272269,2682242,25993170,-12478523 }, + { 4364628,5930691,32304656,-10044554,-8054781,15091131,22857016,-10598955,31820368,15075278 }, + }, + { + { 31879134,-8918693,17258761,90626,-8041836,-4917709,24162788,-9650886,-17970238,12833045 }, + { 19073683,14851414,-24403169,-11860168,7625278,11091125,-19619190,2074449,-9413939,14905377 }, + { 24483667,-11935567,-2518866,-11547418,-1553130,15355506,-25282080,9253129,27628530,-7555480 }, + }, + { + { 17597607,8340603,19355617,552187,26198470,-3176583,4593324,-9157582,-14110875,15297016 }, + { 510886,14337390,-31785257,16638632,6328095,2713355,-20217417,-11864220,8683221,2921426 }, + { 18606791,11874196,27155355,-5281482,-24031742,6265446,-25178240,-1278924,4674690,13890525 }, + }, + { + { 13609624,13069022,-27372361,-13055908,24360586,9592974,14977157,9835105,4389687,288396 }, + { 9922506,-519394,13613107,5883594,-18758345,-434263,-12304062,8317628,23388070,16052080 }, + { 12720016,11937594,-31970060,-5028689,26900120,8561328,-20155687,-11632979,-14754271,-10812892 }, + }, + { + { 15961858,14150409,26716931,-665832,-22794328,13603569,11829573,7467844,-28822128,929275 }, + { 11038231,-11582396,-27310482,-7316562,-10498527,-16307831,-23479533,-9371869,-21393143,2465074 }, + { 20017163,-4323226,27915242,1529148,12396362,15675764,13817261,-9658066,2463391,-4622140 }, + }, + { + { -16358878,-12663911,-12065183,4996454,-1256422,1073572,9583558,12851107,4003896,12673717 }, + { -1731589,-15155870,-3262930,16143082,19294135,13385325,14741514,-9103726,7903886,2348101 }, + { 24536016,-16515207,12715592,-3862155,1511293,10047386,-3842346,-7129159,-28377538,10048127 }, + }, +}, +{ + { + { -12622226,-6204820,30718825,2591312,-10617028,12192840,18873298,-7297090,-32297756,15221632 }, + { -26478122,-11103864,11546244,-1852483,9180880,7656409,-21343950,2095755,29769758,6593415 }, + { -31994208,-2907461,4176912,3264766,12538965,-868111,26312345,-6118678,30958054,8292160 }, + }, + { + { 31429822,-13959116,29173532,15632448,12174511,-2760094,32808831,3977186,26143136,-3148876 }, + { 22648901,1402143,-22799984,13746059,7936347,365344,-8668633,-1674433,-3758243,-2304625 }, + { -15491917,8012313,-2514730,-12702462,-23965846,-10254029,-1612713,-1535569,-16664475,8194478 }, + }, + { + { 27338066,-7507420,-7414224,10140405,-19026427,-6589889,27277191,8855376,28572286,3005164 }, + { 26287124,4821776,25476601,-4145903,-3764513,-15788984,-18008582,1182479,-26094821,-13079595 }, + { -7171154,3178080,23970071,6201893,-17195577,-4489192,-21876275,-13982627,32208683,-1198248 }, + }, + { + { -16657702,2817643,-10286362,14811298,6024667,13349505,-27315504,-10497842,-27672585,-11539858 }, + { 15941029,-9405932,-21367050,8062055,31876073,-238629,-15278393,-1444429,15397331,-4130193 }, + { 8934485,-13485467,-23286397,-13423241,-32446090,14047986,31170398,-1441021,-27505566,15087184 }, + }, + { + { -18357243,-2156491,24524913,-16677868,15520427,-6360776,-15502406,11461896,16788528,-5868942 }, + { -1947386,16013773,21750665,3714552,-17401782,-16055433,-3770287,-10323320,31322514,-11615635 }, + { 21426655,-5650218,-13648287,-5347537,-28812189,-4920970,-18275391,-14621414,13040862,-12112948 }, + }, + { + { 11293895,12478086,-27136401,15083750,-29307421,14748872,14555558,-13417103,1613711,4896935 }, + { -25894883,15323294,-8489791,-8057900,25967126,-13425460,2825960,-4897045,-23971776,-11267415 }, + { -15924766,-5229880,-17443532,6410664,3622847,10243618,20615400,12405433,-23753030,-8436416 }, + }, + { + { -7091295,12556208,-20191352,9025187,-17072479,4333801,4378436,2432030,23097949,-566018 }, + { 4565804,-16025654,20084412,-7842817,1724999,189254,24767264,10103221,-18512313,2424778 }, + { 366633,-11976806,8173090,-6890119,30788634,5745705,-7168678,1344109,-3642553,12412659 }, + }, + { + { -24001791,7690286,14929416,-168257,-32210835,-13412986,24162697,-15326504,-3141501,11179385 }, + { 18289522,-14724954,8056945,16430056,-21729724,7842514,-6001441,-1486897,-18684645,-11443503 }, + { 476239,6601091,-6152790,-9723375,17503545,-4863900,27672959,13403813,11052904,5219329 }, + }, +}, +{ + { + { 20678546,-8375738,-32671898,8849123,-5009758,14574752,31186971,-3973730,9014762,-8579056 }, + { -13644050,-10350239,-15962508,5075808,-1514661,-11534600,-33102500,9160280,8473550,-3256838 }, + { 24900749,14435722,17209120,-15292541,-22592275,9878983,-7689309,-16335821,-24568481,11788948 }, + }, + { + { -3118155,-11395194,-13802089,14797441,9652448,-6845904,-20037437,10410733,-24568470,-1458691 }, + { -15659161,16736706,-22467150,10215878,-9097177,7563911,11871841,-12505194,-18513325,8464118 }, + { -23400612,8348507,-14585951,-861714,-3950205,-6373419,14325289,8628612,33313881,-8370517 }, + }, + { + { -20186973,-4967935,22367356,5271547,-1097117,-4788838,-24805667,-10236854,-8940735,-5818269 }, + { -6948785,-1795212,-32625683,-16021179,32635414,-7374245,15989197,-12838188,28358192,-4253904 }, + { -23561781,-2799059,-32351682,-1661963,-9147719,10429267,-16637684,4072016,-5351664,5596589 }, + }, + { + { -28236598,-3390048,12312896,6213178,3117142,16078565,29266239,2557221,1768301,15373193 }, + { -7243358,-3246960,-4593467,-7553353,-127927,-912245,-1090902,-4504991,-24660491,3442910 }, + { -30210571,5124043,14181784,8197961,18964734,-11939093,22597931,7176455,-18585478,13365930 }, + }, + { + { -7877390,-1499958,8324673,4690079,6261860,890446,24538107,-8570186,-9689599,-3031667 }, + { 25008904,-10771599,-4305031,-9638010,16265036,15721635,683793,-11823784,15723479,-15163481 }, + { -9660625,12374379,-27006999,-7026148,-7724114,-12314514,11879682,5400171,519526,-1235876 }, + }, + { + { 22258397,-16332233,-7869817,14613016,-22520255,-2950923,-20353881,7315967,16648397,7605640 }, + { -8081308,-8464597,-8223311,9719710,19259459,-15348212,23994942,-5281555,-9468848,4763278 }, + { -21699244,9220969,-15730624,1084137,-25476107,-2852390,31088447,-7764523,-11356529,728112 }, + }, + { + { 26047220,-11751471,-6900323,-16521798,24092068,9158119,-4273545,-12555558,-29365436,-5498272 }, + { 17510331,-322857,5854289,8403524,17133918,-3112612,-28111007,12327945,10750447,10014012 }, + { -10312768,3936952,9156313,-8897683,16498692,-994647,-27481051,-666732,3424691,7540221 }, + }, + { + { 30322361,-6964110,11361005,-4143317,7433304,4989748,-7071422,-16317219,-9244265,15258046 }, + { 13054562,-2779497,19155474,469045,-12482797,4566042,5631406,2711395,1062915,-5136345 }, + { -19240248,-11254599,-29509029,-7499965,-5835763,13005411,-6066489,12194497,32960380,1459310 }, + }, +}, +{ + { + { 19852034,7027924,23669353,10020366,8586503,-6657907,394197,-6101885,18638003,-11174937 }, + { 31395534,15098109,26581030,8030562,-16527914,-5007134,9012486,-7584354,-6643087,-5442636 }, + { -9192165,-2347377,-1997099,4529534,25766844,607986,-13222,9677543,-32294889,-6456008 }, + }, + { + { -2444496,-149937,29348902,8186665,1873760,12489863,-30934579,-7839692,-7852844,-8138429 }, + { -15236356,-15433509,7766470,746860,26346930,-10221762,-27333451,10754588,-9431476,5203576 }, + { 31834314,14135496,-770007,5159118,20917671,-16768096,-7467973,-7337524,31809243,7347066 }, + }, + { + { -9606723,-11874240,20414459,13033986,13716524,-11691881,19797970,-12211255,15192876,-2087490 }, + { -12663563,-2181719,1168162,-3804809,26747877,-14138091,10609330,12694420,33473243,-13382104 }, + { 33184999,11180355,15832085,-11385430,-1633671,225884,15089336,-11023903,-6135662,14480053 }, + }, + { + { 31308717,-5619998,31030840,-1897099,15674547,-6582883,5496208,13685227,27595050,8737275 }, + { -20318852,-15150239,10933843,-16178022,8335352,-7546022,-31008351,-12610604,26498114,66511 }, + { 22644454,-8761729,-16671776,4884562,-3105614,-13559366,30540766,-4286747,-13327787,-7515095 }, + }, + { + { -28017847,9834845,18617207,-2681312,-3401956,-13307506,8205540,13585437,-17127465,15115439 }, + { 23711543,-672915,31206561,-8362711,6164647,-9709987,-33535882,-1426096,8236921,16492939 }, + { -23910559,-13515526,-26299483,-4503841,25005590,-7687270,19574902,10071562,6708380,-6222424 }, + }, + { + { 2101391,-4930054,19702731,2367575,-15427167,1047675,5301017,9328700,29955601,-11678310 }, + { 3096359,9271816,-21620864,-15521844,-14847996,-7592937,-25892142,-12635595,-9917575,6216608 }, + { -32615849,338663,-25195611,2510422,-29213566,-13820213,24822830,-6146567,-26767480,7525079 }, + }, + { + { -23066649,-13985623,16133487,-7896178,-3389565,778788,-910336,-2782495,-19386633,11994101 }, + { 21691500,-13624626,-641331,-14367021,3285881,-3483596,-25064666,9718258,-7477437,13381418 }, + { 18445390,-4202236,14979846,11622458,-1727110,-3582980,23111648,-6375247,28535282,15779576 }, + }, + { + { 30098053,3089662,-9234387,16662135,-21306940,11308411,-14068454,12021730,9955285,-16303356 }, + { 9734894,-14576830,-7473633,-9138735,2060392,11313496,-18426029,9924399,20194861,13380996 }, + { -26378102,-7965207,-22167821,15789297,-18055342,-6168792,-1984914,15707771,26342023,10146099 }, + }, +}, +{ + { + { -26016874,-219943,21339191,-41388,19745256,-2878700,-29637280,2227040,21612326,-545728 }, + { -13077387,1184228,23562814,-5970442,-20351244,-6348714,25764461,12243797,-20856566,11649658 }, + { -10031494,11262626,27384172,2271902,26947504,-15997771,39944,6114064,33514190,2333242 }, + }, + { + { -21433588,-12421821,8119782,7219913,-21830522,-9016134,-6679750,-12670638,24350578,-13450001 }, + { -4116307,-11271533,-23886186,4843615,-30088339,690623,-31536088,-10406836,8317860,12352766 }, + { 18200138,-14475911,-33087759,-2696619,-23702521,-9102511,-23552096,-2287550,20712163,6719373 }, + }, + { + { 26656208,6075253,-7858556,1886072,-28344043,4262326,11117530,-3763210,26224235,-3297458 }, + { -17168938,-14854097,-3395676,-16369877,-19954045,14050420,21728352,9493610,18620611,-16428628 }, + { -13323321,13325349,11432106,5964811,18609221,6062965,-5269471,-9725556,-30701573,-16479657 }, + }, + { + { -23860538,-11233159,26961357,1640861,-32413112,-16737940,12248509,-5240639,13735342,1934062 }, + { 25089769,6742589,17081145,-13406266,21909293,-16067981,-15136294,-3765346,-21277997,5473616 }, + { 31883677,-7961101,1083432,-11572403,22828471,13290673,-7125085,12469656,29111212,-5451014 }, + }, + { + { 24244947,-15050407,-26262976,2791540,-14997599,16666678,24367466,6388839,-10295587,452383 }, + { -25640782,-3417841,5217916,16224624,19987036,-4082269,-24236251,-5915248,15766062,8407814 }, + { -20406999,13990231,15495425,16395525,5377168,15166495,-8917023,-4388953,-8067909,2276718 }, + }, + { + { 30157918,12924066,-17712050,9245753,19895028,3368142,-23827587,5096219,22740376,-7303417 }, + { 2041139,-14256350,7783687,13876377,-25946985,-13352459,24051124,13742383,-15637599,13295222 }, + { 33338237,-8505733,12532113,7977527,9106186,-1715251,-17720195,-4612972,-4451357,-14669444 }, + }, + { + { -20045281,5454097,-14346548,6447146,28862071,1883651,-2469266,-4141880,7770569,9620597 }, + { 23208068,7979712,33071466,8149229,1758231,-10834995,30945528,-1694323,-33502340,-14767970 }, + { 1439958,-16270480,-1079989,-793782,4625402,10647766,-5043801,1220118,30494170,-11440799 }, + }, + { + { -5037580,-13028295,-2970559,-3061767,15640974,-6701666,-26739026,926050,-1684339,-13333647 }, + { 13908495,-3549272,30919928,-6273825,-21521863,7989039,9021034,9078865,3353509,4033511 }, + { -29663431,-15113610,32259991,-344482,24295849,-12912123,23161163,8839127,27485041,7356032 }, + }, +}, +{ + { + { 9661027,705443,11980065,-5370154,-1628543,14661173,-6346142,2625015,28431036,-16771834 }, + { -23839233,-8311415,-25945511,7480958,-17681669,-8354183,-22545972,14150565,15970762,4099461 }, + { 29262576,16756590,26350592,-8793563,8529671,-11208050,13617293,-9937143,11465739,8317062 }, + }, + { + { -25493081,-6962928,32500200,-9419051,-23038724,-2302222,14898637,3848455,20969334,-5157516 }, + { -20384450,-14347713,-18336405,13884722,-33039454,2842114,-21610826,-3649888,11177095,14989547 }, + { -24496721,-11716016,16959896,2278463,12066309,10137771,13515641,2581286,-28487508,9930240 }, + }, + { + { -17751622,-2097826,16544300,-13009300,-15914807,-14949081,18345767,-13403753,16291481,-5314038 }, + { -33229194,2553288,32678213,9875984,8534129,6889387,-9676774,6957617,4368891,9788741 }, + { 16660756,7281060,-10830758,12911820,20108584,-8101676,-21722536,-8613148,16250552,-11111103 }, + }, + { + { -19765507,2390526,-16551031,14161980,1905286,6414907,4689584,10604807,-30190403,4782747 }, + { -1354539,14736941,-7367442,-13292886,7710542,-14155590,-9981571,4383045,22546403,437323 }, + { 31665577,-12180464,-16186830,1491339,-18368625,3294682,27343084,2786261,-30633590,-14097016 }, + }, + { + { -14467279,-683715,-33374107,7448552,19294360,14334329,-19690631,2355319,-19284671,-6114373 }, + { 15121312,-15796162,6377020,-6031361,-10798111,-12957845,18952177,15496498,-29380133,11754228 }, + { -2637277,-13483075,8488727,-14303896,12728761,-1622493,7141596,11724556,22761615,-10134141 }, + }, + { + { 16918416,11729663,-18083579,3022987,-31015732,-13339659,-28741185,-12227393,32851222,11717399 }, + { 11166634,7338049,-6722523,4531520,-29468672,-7302055,31474879,3483633,-1193175,-4030831 }, + { -185635,9921305,31456609,-13536438,-12013818,13348923,33142652,6546660,-19985279,-3948376 }, + }, + { + { -32460596,11266712,-11197107,-7899103,31703694,3855903,-8537131,-12833048,-30772034,-15486313 }, + { -18006477,12709068,3991746,-6479188,-21491523,-10550425,-31135347,-16049879,10928917,3011958 }, + { -6957757,-15594337,31696059,334240,29576716,14796075,-30831056,-12805180,18008031,10258577 }, + }, + { + { -22448644,15655569,7018479,-4410003,-30314266,-1201591,-1853465,1367120,25127874,6671743 }, + { 29701166,-14373934,-10878120,9279288,-17568,13127210,21382910,11042292,25838796,4642684 }, + { -20430234,14955537,-24126347,8124619,-5369288,-5990470,30468147,-13900640,18423289,4177476 }, + }, +}, +} ; +#endif + + +static void ge_select(ge_precomp *t,int pos,signed char b) +{ +#ifndef CURVED25519_ASM + ge_precomp minust; + unsigned char bnegative = negative(b); + unsigned char babs = b - (((-bnegative) & b) << 1); + + ge_precomp_0(t); + cmov(t,&base[pos][0],babs,1); + cmov(t,&base[pos][1],babs,2); + cmov(t,&base[pos][2],babs,3); + cmov(t,&base[pos][3],babs,4); + cmov(t,&base[pos][4],babs,5); + cmov(t,&base[pos][5],babs,6); + cmov(t,&base[pos][6],babs,7); + cmov(t,&base[pos][7],babs,8); + fe_cswap(t->yminusx, t->yplusx, bnegative); + fe_neg(minust.xy2d,t->xy2d); + fe_cmov(t->xy2d,minust.xy2d,bnegative); +#else + fe_cmov_table((fe*)t, (fe*)base[pos], b); +#endif +} + +/* +h = a * B +where a = a[0]+256*a[1]+...+256^31 a[31] +B is the Ed25519 base point (x,4/5) with x positive. + +Preconditions: + a[31] <= 127 +*/ +void ge_scalarmult_base(ge_p3 *h,const unsigned char *a) +{ + signed char e[64]; + signed char carry; + ge_p1p1 r; +#ifndef CURVED25519_ASM + ge_p2 s; +#endif + ge_precomp t; + int i; + + for (i = 0;i < 32;++i) { + e[2 * i + 0] = (a[i] >> 0) & 15; + e[2 * i + 1] = (a[i] >> 4) & 15; + } + /* each e[i] is between 0 and 15 */ + /* e[63] is between 0 and 7 */ + + carry = 0; + for (i = 0;i < 63;++i) { + e[i] += carry; + carry = e[i] + 8; + carry >>= 4; + e[i] -= carry << 4; + } + e[63] += carry; + /* each e[i] is between -8 and 8 */ + +#ifndef CURVED25519_ASM + ge_select(&t,0,e[1]); + fe_sub(h->X, t.yplusx, t.yminusx); + fe_add(h->Y, t.yplusx, t.yminusx); + fe_0(h->Z); + h->Z[0] = 4; + fe_mul(h->T,h->X,h->Y); + fe_add(h->X, h->X, h->X); + fe_add(h->Y, h->Y, h->Y); + + for (i = 3;i < 64;i += 2) { + ge_select(&t,i / 2,e[i]); + ge_madd(&r,h,&t); ge_p1p1_to_p3(h,&r); + } + + ge_p3_dbl(&r,h); ge_p1p1_to_p2(&s,&r); + ge_p2_dbl(&r,&s); ge_p1p1_to_p2(&s,&r); + ge_p2_dbl(&r,&s); ge_p1p1_to_p2(&s,&r); + ge_p2_dbl(&r,&s); ge_p1p1_to_p3(h,&r); + + for (i = 0;i < 64;i += 2) { + ge_select(&t,i / 2,e[i]); + ge_madd(&r,h,&t); ge_p1p1_to_p3(h,&r); + } +#else + ge_select(&t, 0, e[0]); + fe_sub(h->X, t.yplusx, t.yminusx); + fe_add(h->Y, t.yplusx, t.yminusx); + fe_0(h->Z); + h->Z[0] = 2; + fe_copy(h->T, t.xy2d); + for (i = 1; i < 64; i++) { + ge_select(&t, i, e[i]); + ge_madd(&r,h,&t); ge_p1p1_to_p3(h,&r); + } +#endif +} + + +/* ge double scalar mult */ +static void slide(signed char *r,const unsigned char *a) +{ + int i; + int b; + int k; + + for (i = 0;i < 256;++i) + r[i] = 1 & (a[i >> 3] >> (i & 7)); + + for (i = 0;i < 256;++i) + if (r[i]) { + for (b = 1;b <= 6 && i + b < 256;++b) { + if (r[i + b]) { + if (r[i] + (r[i + b] << b) <= 15) { + r[i] += r[i + b] << b; r[i + b] = 0; + } else if (r[i] - (r[i + b] << b) >= -15) { + r[i] -= r[i + b] << b; + for (k = i + b;k < 256;++k) { + if (!r[k]) { + r[k] = 1; + break; + } + r[k] = 0; + } + } else + break; + } + } + } +} + +#ifdef CURVED25519_ASM_64BIT +static const ge_precomp Bi[8] = { + { + { 0x2fbc93c6f58c3b85, -0x306cd2390473f1e7, 0x270b4898643d42c2, 0x07cf9d3a33d4ba65, }, + { -0x62efc6fa28bf6ec2, -0x02c660fa2ebf414d, -0x5a3e7bcb977075f7, 0x44fd2f9298f81267, }, + { -0x5436edfa78855598, 0x26d9e823ccaac49e, 0x5a1b7dcbdd43598c, 0x6f117b689f0c65a8, }, + }, + { + { -0x50da4f57b31168d0, 0x025a8430e8864b8a, -0x3ee4affd60fe98ce, 0x7a164e1b9a80f8f4, }, + { 0x56611fe8a4fcd265, 0x3bd353fde5c1ba7d, -0x7ece0ce5deb42943, 0x2ab91587555bda62, }, + { 0x14ae933f0dd0d889, 0x589423221c35da62, -0x2e8f1aba730d24b4, 0x5a2826af12b9b4c6, }, + }, + { + { -0x5ded43bbf75a44cd, -0x72afb73c38a112fe, -0x22e414f3a54013bc, 0x2945ccf146e206eb, }, + { 0x7f9182c3a447d6ba, -0x2affeb2eb4d8d649, -0x1cc30ee3479b5f79, 0x154a7e73eb1b55f3, }, + { -0x4344240e7ed57d7b, 0x270e0807d0bdd1fc, -0x4be498f4e44258d3, 0x43aabe696b3bb69a, }, + }, + { + { 0x6b1a5cd0944ea3bf, 0x7470353ab39dc0d2, 0x71b2528228542e49, 0x461bea69283c927e, }, + { -0x4590d36555cdde4f, 0x6ca021533bba23a7, -0x621589b06de6d3c6, 0x1d6edd5d2e5317e0, }, + { -0x0e7c9237fe474c5e, -0x4cfca0b8fac15b66, 0x529c41ba5877adf3, 0x7a9fbb1c6a0f90a7, }, + }, + { + { -0x64d1987559579cd1, -0x59af6190ae43b93b, -0x314dcc3639790a4b, 0x34b9ed338add7f59, }, + { -0x0c91de81fc627f9c, -0x675f7e490adfbe65, -0x693439f718a14fbc, 0x49c05a51fadc9c8f, }, + { 0x06b4e8bf9045af1b, -0x1d007c1758e62dd1, -0x550903d66c2b30ea, 0x73c172021b008b06, }, + }, + { + { 0x2fbf00848a802ade, -0x1a260130fdcfd1d9, 0x113e847117703406, 0x4275aae2546d8faf, }, + { 0x315f5b0249864348, 0x3ed6b36977088381, -0x5c5f8aaa9572146b, 0x18ab598029d5c77f, }, + { -0x27d4d33a029f7617, 0x031eb4a13282e4a4, 0x44311199b51a8622, 0x3dc65522b53df948, }, + }, + { + { -0x408f3ddd5dff8093, -0x407b4c654a432125, 0x537a0e12fb07ba07, 0x234fd7eec346f241, }, + { 0x506f013b327fbf93, -0x5103143664889095, -0x62ed4dcd5552a698, 0x0267882d176024a7, }, + { 0x5360a119732ea378, 0x2437e6b1df8dd471, -0x5d10c8076e581acd, 0x497ba6fdaa097863, }, + }, + { + { 0x24cecc0313cfeaa0, -0x79b73d72e763db93, 0x2dbdbdfac1f2d4d0, 0x61e22917f12de72b, }, + { 0x040bcd86468ccf0b, -0x2c7d645bd566ef2a, 0x7508300807b25192, 0x43b5cd4218d05ebf, }, + { 0x5d9a762f9bd0b516, -0x14c750b1c8c02112, 0x032e5a7d93d64270, 0x511d61210ae4d842, }, + }, +}; +#elif defined(CURVED25519_ASM_32BIT) +static const ge_precomp Bi[8] = { + { + { -0x0a73c47b, 0x2fbc93c6, -0x0473f1e7, -0x306cd23a, 0x643d42c2, 0x270b4898, 0x33d4ba65, 0x07cf9d3a, }, + { -0x28bf6ec2, -0x62efc6fb, -0x2ebf414d, -0x02c660fb, 0x688f8a09, -0x5a3e7bcc, -0x6707ed99, 0x44fd2f92, }, + { -0x78855598, -0x5436edfb, -0x33553b62, 0x26d9e823, -0x22bca674, 0x5a1b7dcb, -0x60f39a58, 0x6f117b68, }, + }, + { + { 0x4cee9730, -0x50da4f58, -0x1779b476, 0x025a8430, -0x60fe98ce, -0x3ee4affe, -0x657f070c, 0x7a164e1b, }, + { -0x5b032d9b, 0x56611fe8, -0x1a3e4583, 0x3bd353fd, 0x214bd6bd, -0x7ece0ce6, 0x555bda62, 0x2ab91587, }, + { 0x0dd0d889, 0x14ae933f, 0x1c35da62, 0x58942322, -0x730d24b4, -0x2e8f1abb, 0x12b9b4c6, 0x5a2826af, }, + }, + { + { 0x08a5bb33, -0x5ded43bc, -0x38a112fe, -0x72afb73d, 0x5abfec44, -0x22e414f4, 0x46e206eb, 0x2945ccf1, }, + { -0x5bb82946, 0x7f9182c3, 0x4b2729b7, -0x2affeb2f, -0x479b5f79, -0x1cc30ee4, -0x14e4aa0d, 0x154a7e73, }, + { -0x7ed57d7b, -0x4344240f, -0x2f422e04, 0x270e0807, 0x1bbda72d, -0x4be498f5, 0x6b3bb69a, 0x43aabe69, }, + }, + { + { -0x6bb15c41, 0x6b1a5cd0, -0x4c623f2e, 0x7470353a, 0x28542e49, 0x71b25282, 0x283c927e, 0x461bea69, }, + { -0x55cdde4f, -0x4590d366, 0x3bba23a7, 0x6ca02153, -0x6de6d3c6, -0x621589b1, 0x2e5317e0, 0x1d6edd5d, }, + { 0x01b8b3a2, -0x0e7c9238, 0x053ea49a, -0x4cfca0b9, 0x5877adf3, 0x529c41ba, 0x6a0f90a7, 0x7a9fbb1c, }, + }, + { + { -0x59579cd1, -0x64d19876, 0x51bc46c5, -0x59af6191, -0x39790a4b, -0x314dcc37, -0x752280a7, 0x34b9ed33, }, + { 0x039d8064, -0x0c91de82, -0x0adfbe65, -0x675f7e4a, -0x18a14fbc, -0x693439f8, -0x05236371, 0x49c05a51, }, + { -0x6fba50e5, 0x06b4e8bf, -0x58e62dd1, -0x1d007c18, -0x6c2b30ea, -0x550903d7, 0x1b008b06, 0x73c17202, }, + }, + { + { -0x757fd522, 0x2fbf0084, 0x02302e27, -0x1a260131, 0x17703406, 0x113e8471, 0x546d8faf, 0x4275aae2, }, + { 0x49864348, 0x315f5b02, 0x77088381, 0x3ed6b369, 0x6a8deb95, -0x5c5f8aab, 0x29d5c77f, 0x18ab5980, }, + { -0x029f7617, -0x27d4d33b, 0x3282e4a4, 0x031eb4a1, -0x4ae579de, 0x44311199, -0x4ac206b8, 0x3dc65522, }, + }, + { + { -0x5dff8093, -0x408f3dde, -0x4a432125, -0x407b4c66, -0x04f845f9, 0x537a0e12, -0x3cb90dbf, 0x234fd7ee, }, + { 0x327fbf93, 0x506f013b, -0x64889095, -0x51031437, -0x5552a698, -0x62ed4dce, 0x176024a7, 0x0267882d, }, + { 0x732ea378, 0x5360a119, -0x20722b8f, 0x2437e6b1, -0x6e581acd, -0x5d10c808, -0x55f6879d, 0x497ba6fd, }, + }, + { + { 0x13cfeaa0, 0x24cecc03, 0x189c246d, -0x79b73d73, -0x3e0d2b30, 0x2dbdbdfa, -0x0ed218d5, 0x61e22917, }, + { 0x468ccf0b, 0x040bcd86, 0x2a9910d6, -0x2c7d645c, 0x07b25192, 0x75083008, 0x18d05ebf, 0x43b5cd42, }, + { -0x642f4aea, 0x5d9a762f, 0x373fdeee, -0x14c750b2, -0x6c29bd90, 0x032e5a7d, 0x0ae4d842, 0x511d6121, }, + }, +}; +#elif defined(CURVED25519_128BIT) +static const ge_precomp Bi[8] = { + { + { 0x493c6f58c3b85, 0x0df7181c325f7, 0x0f50b0b3e4cb7, 0x5329385a44c32, 0x07cf9d3a33d4b }, + { 0x03905d740913e, 0x0ba2817d673a2, 0x23e2827f4e67c, 0x133d2e0c21a34, 0x44fd2f9298f81 }, + { 0x11205877aaa68, 0x479955893d579, 0x50d66309b67a0, 0x2d42d0dbee5ee, 0x6f117b689f0c6 }, + }, + { + { 0x5b0a84cee9730, 0x61d10c97155e4, 0x4059cc8096a10, 0x47a608da8014f, 0x7a164e1b9a80f }, + { 0x11fe8a4fcd265, 0x7bcb8374faacc, 0x52f5af4ef4d4f, 0x5314098f98d10, 0x2ab91587555bd }, + { 0x6933f0dd0d889, 0x44386bb4c4295, 0x3cb6d3162508c, 0x26368b872a2c6, 0x5a2826af12b9b }, + }, + { + { 0x2bc4408a5bb33, 0x078ebdda05442, 0x2ffb112354123, 0x375ee8df5862d, 0x2945ccf146e20 }, + { 0x182c3a447d6ba, 0x22964e536eff2, 0x192821f540053, 0x2f9f19e788e5c, 0x154a7e73eb1b5 }, + { 0x3dbf1812a8285, 0x0fa17ba3f9797, 0x6f69cb49c3820, 0x34d5a0db3858d, 0x43aabe696b3bb }, + }, + { + { 0x25cd0944ea3bf, 0x75673b81a4d63, 0x150b925d1c0d4, 0x13f38d9294114, 0x461bea69283c9 }, + { 0x72c9aaa3221b1, 0x267774474f74d, 0x064b0e9b28085, 0x3f04ef53b27c9, 0x1d6edd5d2e531 }, + { 0x36dc801b8b3a2, 0x0e0a7d4935e30, 0x1deb7cecc0d7d, 0x053a94e20dd2c, 0x7a9fbb1c6a0f9 }, + }, + { + { 0x6678aa6a8632f, 0x5ea3788d8b365, 0x21bd6d6994279, 0x7ace75919e4e3, 0x34b9ed338add7 }, + { 0x6217e039d8064, 0x6dea408337e6d, 0x57ac112628206, 0x647cb65e30473, 0x49c05a51fadc9 }, + { 0x4e8bf9045af1b, 0x514e33a45e0d6, 0x7533c5b8bfe0f, 0x583557b7e14c9, 0x73c172021b008 }, + }, + { + { 0x700848a802ade, 0x1e04605c4e5f7, 0x5c0d01b9767fb, 0x7d7889f42388b, 0x4275aae2546d8 }, + { 0x75b0249864348, 0x52ee11070262b, 0x237ae54fb5acd, 0x3bfd1d03aaab5, 0x18ab598029d5c }, + { 0x32cc5fd6089e9, 0x426505c949b05, 0x46a18880c7ad2, 0x4a4221888ccda, 0x3dc65522b53df }, + }, + { + { 0x0c222a2007f6d, 0x356b79bdb77ee, 0x41ee81efe12ce, 0x120a9bd07097d, 0x234fd7eec346f }, + { 0x7013b327fbf93, 0x1336eeded6a0d, 0x2b565a2bbf3af, 0x253ce89591955, 0x0267882d17602 }, + { 0x0a119732ea378, 0x63bf1ba8e2a6c, 0x69f94cc90df9a, 0x431d1779bfc48, 0x497ba6fdaa097 }, + }, + { + { 0x6cc0313cfeaa0, 0x1a313848da499, 0x7cb534219230a, 0x39596dedefd60, 0x61e22917f12de }, + { 0x3cd86468ccf0b, 0x48553221ac081, 0x6c9464b4e0a6e, 0x75fba84180403, 0x43b5cd4218d05 }, + { 0x2762f9bd0b516, 0x1c6e7fbddcbb3, 0x75909c3ace2bd, 0x42101972d3ec9, 0x511d61210ae4d }, + }, +}; +#else +static const ge_precomp Bi[8] = { + { + { 25967493,-14356035,29566456,3660896,-12694345,4014787,27544626,-11754271,-6079156,2047605 }, + { -12545711,934262,-2722910,3049990,-727428,9406986,12720692,5043384,19500929,-15469378 }, + { -8738181,4489570,9688441,-14785194,10184609,-12363380,29287919,11864899,-24514362,-4438546 }, + }, + { + { 15636291,-9688557,24204773,-7912398,616977,-16685262,27787600,-14772189,28944400,-1550024 }, + { 16568933,4717097,-11556148,-1102322,15682896,-11807043,16354577,-11775962,7689662,11199574 }, + { 30464156,-5976125,-11779434,-15670865,23220365,15915852,7512774,10017326,-17749093,-9920357 }, + }, + { + { 10861363,11473154,27284546,1981175,-30064349,12577861,32867885,14515107,-15438304,10819380 }, + { 4708026,6336745,20377586,9066809,-11272109,6594696,-25653668,12483688,-12668491,5581306 }, + { 19563160,16186464,-29386857,4097519,10237984,-4348115,28542350,13850243,-23678021,-15815942 }, + }, + { + { 5153746,9909285,1723747,-2777874,30523605,5516873,19480852,5230134,-23952439,-15175766 }, + { -30269007,-3463509,7665486,10083793,28475525,1649722,20654025,16520125,30598449,7715701 }, + { 28881845,14381568,9657904,3680757,-20181635,7843316,-31400660,1370708,29794553,-1409300 }, + }, + { + { -22518993,-6692182,14201702,-8745502,-23510406,8844726,18474211,-1361450,-13062696,13821877 }, + { -6455177,-7839871,3374702,-4740862,-27098617,-10571707,31655028,-7212327,18853322,-14220951 }, + { 4566830,-12963868,-28974889,-12240689,-7602672,-2830569,-8514358,-10431137,2207753,-3209784 }, + }, + { + { -25154831,-4185821,29681144,7868801,-6854661,-9423865,-12437364,-663000,-31111463,-16132436 }, + { 25576264,-2703214,7349804,-11814844,16472782,9300885,3844789,15725684,171356,6466918 }, + { 23103977,13316479,9739013,-16149481,817875,-15038942,8965339,-14088058,-30714912,16193877 }, + }, + { + { -33521811,3180713,-2394130,14003687,-16903474,-16270840,17238398,4729455,-18074513,9256800 }, + { -25182317,-4174131,32336398,5036987,-21236817,11360617,22616405,9761698,-19827198,630305 }, + { -13720693,2639453,-24237460,-7406481,9494427,-5774029,-6554551,-15960994,-2449256,-14291300 }, + }, + { + { -3151181,-5046075,9282714,6866145,-31907062,-863023,-18940575,15033784,25105118,-7894876 }, + { -24326370,15950226,-31801215,-14592823,-11662737,-5090925,1573892,-2625887,2198790,-15804619 }, + { -3099351,10324967,-2241613,7453183,-5446979,-2735503,-13812022,-16236442,-32461234,-12290683 }, + }, +} ; +#endif + + +/* +r = a * A + b * B +where a = a[0]+256*a[1]+...+256^31 a[31]. +and b = b[0]+256*b[1]+...+256^31 b[31]. +B is the Ed25519 base point (x,4/5) with x positive. +*/ +int ge_double_scalarmult_vartime(ge_p2 *r, const unsigned char *a, + const ge_p3 *A, const unsigned char *b) +{ + signed char aslide[256]; + signed char bslide[256]; + ge_cached Ai[8]; /* A,3A,5A,7A,9A,11A,13A,15A */ + ge_p1p1 t; + ge_p3 u; + ge_p3 A2; + int i; + + slide(aslide,a); + slide(bslide,b); + + ge_p3_to_cached(&Ai[0],A); + ge_p3_dbl(&t,A); ge_p1p1_to_p3(&A2,&t); + ge_add(&t,&A2,&Ai[0]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[1],&u); + ge_add(&t,&A2,&Ai[1]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[2],&u); + ge_add(&t,&A2,&Ai[2]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[3],&u); + ge_add(&t,&A2,&Ai[3]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[4],&u); + ge_add(&t,&A2,&Ai[4]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[5],&u); + ge_add(&t,&A2,&Ai[5]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[6],&u); + ge_add(&t,&A2,&Ai[6]); ge_p1p1_to_p3(&u,&t); ge_p3_to_cached(&Ai[7],&u); + + ge_p2_0(r); + + for (i = 255;i >= 0;--i) { + if (aslide[i] || bslide[i]) break; + } + + for (;i >= 0;--i) { + ge_p2_dbl(&t,r); + + if (aslide[i] > 0) { + ge_p1p1_to_p3(&u,&t); + ge_add(&t,&u,&Ai[aslide[i]/2]); + } else if (aslide[i] < 0) { + ge_p1p1_to_p3(&u,&t); + ge_sub(&t,&u,&Ai[(-aslide[i])/2]); + } + + if (bslide[i] > 0) { + ge_p1p1_to_p3(&u,&t); + ge_madd(&t,&u,&Bi[bslide[i]/2]); + } else if (bslide[i] < 0) { + ge_p1p1_to_p3(&u,&t); + ge_msub(&t,&u,&Bi[(-bslide[i])/2]); + } + + ge_p1p1_to_p2(r,&t); + } + + return 0; +} + +#ifdef CURVED25519_ASM_64BIT +static const ge d = { + 0x75eb4dca135978a3, 0x00700a4d4141d8ab, -0x7338bf8688861768, 0x52036cee2b6ffe73, +}; +#elif defined(CURVED25519_ASM_32BIT) +static const ge d = { + 0x135978a3, 0x75eb4dca, 0x4141d8ab, 0x00700a4d, 0x7779e898, -0x7338bf87, 0x2b6ffe73, 0x52036cee, +}; +#elif defined(CURVED25519_128BIT) +static const ge d = { + 0x34dca135978a3, 0x1a8283b156ebd, 0x5e7a26001c029, 0x739c663a03cbb, + 0x52036cee2b6ff +}; +#else +static const ge d = { +-10913610,13857413,-15372611,6949391,114729, +-8787816,-6275908,-3247719,-18696448,-12055116 +}; +#endif + + +#ifdef CURVED25519_ASM_64BIT +static const ge sqrtm1 = { + -0x3b11e4d8b5f15f50, 0x2f431806ad2fe478, 0x2b4d00993dfbd7a7, 0x2b8324804fc1df0b, +}; +#elif defined(CURVED25519_ASM_32BIT) +static const ge sqrtm1 = { + 0x4a0ea0b0, -0x3b11e4d9, -0x52d01b88, 0x2f431806, 0x3dfbd7a7, 0x2b4d0099, 0x4fc1df0b, 0x2b832480, +}; +#elif defined(CURVED25519_128BIT) +static const ge sqrtm1 = { + 0x61b274a0ea0b0, 0x0d5a5fc8f189d, 0x7ef5e9cbd0c60, 0x78595a6804c9e, + 0x2b8324804fc1d +}; +#else +static const ge sqrtm1 = { +-32595792,-7943725,9377950,3500415,12389472, +-272473,-25146209,-2005654,326686,11406482 +}; +#endif + + +int ge_frombytes_negate_vartime(ge_p3 *h,const unsigned char *s) +{ + ge u; + ge v; + ge v3; + ge vxx; + ge check; + + fe_frombytes(h->Y,s); + fe_1(h->Z); + fe_sq(u,h->Y); + fe_mul(v,u,d); + fe_sub(u,u,h->Z); /* u = y^2-1 */ + fe_add(v,v,h->Z); /* v = dy^2+1 */ + + + fe_sq(v3,v); + fe_mul(v3,v3,v); /* v3 = v^3 */ + fe_sq(h->X,v3); + fe_mul(h->X,h->X,v); + fe_mul(h->X,h->X,u); /* x = uv^7 */ + + fe_pow22523(h->X,h->X); /* x = (uv^7)^((q-5)/8) */ + fe_mul(h->X,h->X,v3); + fe_mul(h->X,h->X,u); /* x = uv^3(uv^7)^((q-5)/8) */ + + fe_sq(vxx,h->X); + fe_mul(vxx,vxx,v); + fe_sub(check,vxx,u); /* vx^2-u */ + if (fe_isnonzero(check)) { + fe_add(check,vxx,u); /* vx^2+u */ + if (fe_isnonzero(check)) return -1; + fe_mul(h->X,h->X,sqrtm1); + } + + if (fe_isnegative(h->X) == (s[31] >> 7)) + fe_neg(h->X,h->X); + + fe_mul(h->T,h->X,h->Y); + return 0; +} + + +/* ge madd */ +/* +r = p + q +*/ + +static WC_INLINE void ge_madd(ge_p1p1 *r,const ge_p3 *p,const ge_precomp *q) +{ +#ifndef CURVED25519_ASM + ge t0; + fe_add(r->X,p->Y,p->X); + fe_sub(r->Y,p->Y,p->X); + fe_mul(r->Z,r->X,q->yplusx); + fe_mul(r->Y,r->Y,q->yminusx); + fe_mul(r->T,q->xy2d,p->T); + fe_add(t0,p->Z,p->Z); + fe_sub(r->X,r->Z,r->Y); + fe_add(r->Y,r->Z,r->Y); + fe_add(r->Z,t0,r->T); + fe_sub(r->T,t0,r->T); +#else + fe_ge_madd(r->X, r->Y, r->Z, r->T, p->X, p->Y, p->Z, p->T, q->xy2d, + q->yplusx, q->yminusx); +#endif +} + + +/* ge msub */ + +/* +r = p - q +*/ + +static WC_INLINE void ge_msub(ge_p1p1 *r,const ge_p3 *p,const ge_precomp *q) +{ +#ifndef CURVED25519_ASM + ge t0; + fe_add(r->X,p->Y,p->X); + fe_sub(r->Y,p->Y,p->X); + fe_mul(r->Z,r->X,q->yminusx); + fe_mul(r->Y,r->Y,q->yplusx); + fe_mul(r->T,q->xy2d,p->T); + fe_add(t0,p->Z,p->Z); + fe_sub(r->X,r->Z,r->Y); + fe_add(r->Y,r->Z,r->Y); + fe_sub(r->Z,t0,r->T); + fe_add(r->T,t0,r->T); +#else + fe_ge_msub(r->X, r->Y, r->Z, r->T, p->X, p->Y, p->Z, p->T, q->xy2d, + q->yplusx, q->yminusx); +#endif +} + + +/* ge p1p1 to p2 */ +/* +r = p +*/ + +static void ge_p1p1_to_p2(ge_p2 *r,const ge_p1p1 *p) +{ +#ifndef CURVED25519_ASM + fe_mul(r->X,p->X,p->T); + fe_mul(r->Y,p->Y,p->Z); + fe_mul(r->Z,p->Z,p->T); +#else + fe_ge_to_p2(r->X, r->Y, r->Z, p->X, p->Y, p->Z, p->T); +#endif +} + + +/* ge p1p1 to p3 */ + +/* +r = p +*/ + +static WC_INLINE void ge_p1p1_to_p3(ge_p3 *r,const ge_p1p1 *p) +{ +#ifndef CURVED25519_ASM + fe_mul(r->X,p->X,p->T); + fe_mul(r->Y,p->Y,p->Z); + fe_mul(r->Z,p->Z,p->T); + fe_mul(r->T,p->X,p->Y); +#else + fe_ge_to_p3(r->X, r->Y, r->Z, r->T, p->X, p->Y, p->Z, p->T); +#endif +} + + +/* ge p2 0 */ + +static void ge_p2_0(ge_p2 *h) +{ + fe_0(h->X); + fe_1(h->Y); + fe_1(h->Z); +} + + +/* ge p2 dbl */ + +/* +r = 2 * p +*/ + +static WC_INLINE void ge_p2_dbl(ge_p1p1 *r,const ge_p2 *p) +{ +#ifndef CURVED25519_ASM + ge t0; + fe_sq(r->X,p->X); + fe_sq(r->Z,p->Y); + fe_sq2(r->T,p->Z); + fe_add(r->Y,p->X,p->Y); + fe_sq(t0,r->Y); + fe_add(r->Y,r->Z,r->X); + fe_sub(r->Z,r->Z,r->X); + fe_sub(r->X,t0,r->Y); + fe_sub(r->T,r->T,r->Z); +#else + fe_ge_dbl(r->X, r->Y, r->Z, r->T, p->X, p->Y, p->Z); +#endif +} + + +/* ge p3 dble */ + +/* +r = 2 * p +*/ + +static void ge_p3_dbl(ge_p1p1 *r,const ge_p3 *p) +{ + ge_p2 q; + ge_p3_to_p2(&q,p); + ge_p2_dbl(r,&q); +} + + +/* ge p3 to cached */ + +/* +r = p +*/ + +#ifdef CURVED25519_ASM_64BIT +static const ge d2 = { + -0x1429646bd94d0ea7, 0x00e0149a8283b156, 0x198e80f2eef3d130, 0x2406d9dc56dffce7, +}; +#elif defined(CURVED25519_ASM_32BIT) +static const ge d2 = { + 0x26b2f159, -0x1429646c, -0x7d7c4eaa, 0x00e0149a, -0x110c2ed0, 0x198e80f2, 0x56dffce7, 0x2406d9dc, +}; +#elif defined(CURVED25519_128BIT) +static const ge d2 = { + 0x69b9426b2f159, 0x35050762add7a, 0x3cf44c0038052, 0x6738cc7407977, + 0x2406d9dc56dff +}; +#else +static const ge d2 = { +-21827239,-5839606,-30745221,13898782,229458, +15978800,-12551817,-6495438,29715968,9444199 +} ; +#endif + + +static WC_INLINE void ge_p3_to_cached(ge_cached *r,const ge_p3 *p) +{ + fe_add(r->YplusX,p->Y,p->X); + fe_sub(r->YminusX,p->Y,p->X); + fe_copy(r->Z,p->Z); + fe_mul(r->T2d,p->T,d2); +} + + +/* ge p3 to p2 */ +/* +r = p +*/ + +static void ge_p3_to_p2(ge_p2 *r,const ge_p3 *p) +{ + fe_copy(r->X,p->X); + fe_copy(r->Y,p->Y); + fe_copy(r->Z,p->Z); +} + + +/* ge p3 tobytes */ +void ge_p3_tobytes(unsigned char *s,const ge_p3 *h) +{ + ge recip; + ge x; + ge y; + + fe_invert(recip,h->Z); + fe_mul(x,h->X,recip); + fe_mul(y,h->Y,recip); + fe_tobytes(s,y); + s[31] ^= fe_isnegative(x) << 7; +} + + +#ifndef CURVED25519_ASM +/* ge_precomp_0 */ +static void ge_precomp_0(ge_precomp *h) +{ + fe_1(h->yplusx); + fe_1(h->yminusx); + fe_0(h->xy2d); +} +#endif + + +/* ge_sub */ +/* +r = p - q +*/ + +static WC_INLINE void ge_sub(ge_p1p1 *r,const ge_p3 *p,const ge_cached *q) +{ +#ifndef CURVED25519_ASM + ge t0; + fe_add(r->X,p->Y,p->X); + fe_sub(r->Y,p->Y,p->X); + fe_mul(r->Z,r->X,q->YminusX); + fe_mul(r->Y,r->Y,q->YplusX); + fe_mul(r->T,q->T2d,p->T); + fe_mul(r->X,p->Z,q->Z); + fe_add(t0,r->X,r->X); + fe_sub(r->X,r->Z,r->Y); + fe_add(r->Y,r->Z,r->Y); + fe_sub(r->Z,t0,r->T); + fe_add(r->T,t0,r->T); +#else + fe_ge_sub(r->X, r->Y, r->Z, r->T, p->X, p->Y, p->Z, p->T, q->Z, q->T2d, + q->YplusX, q->YminusX); +#endif +} + + +/* ge tobytes */ +void ge_tobytes(unsigned char *s,const ge_p2 *h) +{ + ge recip; + ge x; + ge y; + + fe_invert(recip,h->Z); + fe_mul(x,h->X,recip); + fe_mul(y,h->Y,recip); + fe_tobytes(s,y); + s[31] ^= fe_isnegative(x) << 7; +} + +#endif /* !ED25519_SMALL */ +#endif /* HAVE_ED25519 */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/hash.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/hash.c new file mode 100755 index 0000000..5fe85dd --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/hash.c @@ -0,0 +1,1628 @@ +/* hash.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include +#include +#include +#ifndef NO_ASN +#include +#endif + +#include +#include + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#if !defined(NO_ASN) || !defined(NO_DH) || defined(HAVE_ECC) + +#ifdef NO_ASN +enum Hash_Sum { + MD2h = 646, + MD5h = 649, + SHAh = 88, + SHA224h = 417, + SHA256h = 414, + SHA384h = 415, + SHA512h = 416, + SHA3_224h = 420, + SHA3_256h = 421, + SHA3_384h = 422, + SHA3_512h = 423 +}; +#endif /* !NO_ASN */ + +/* function converts int hash type to enum */ +enum wc_HashType wc_HashTypeConvert(int hashType) +{ + /* Default to hash type none as error */ + enum wc_HashType eHashType = WC_HASH_TYPE_NONE; +#if defined(HAVE_FIPS) || defined(HAVE_SELFTEST) + /* original FIPSv1 and CAVP selftest require a mapping for unique hash + type to wc_HashType */ + switch (hashType) { + #ifndef NO_MD5 + case WC_MD5: + eHashType = WC_HASH_TYPE_MD5; + break; + #endif /* !NO_MD5 */ + #ifndef NO_SHA + case WC_SHA: + eHashType = WC_HASH_TYPE_SHA; + break; + #endif /* !NO_SHA */ + + #ifdef WOLFSSL_SHA224 + case WC_SHA224: + eHashType = WC_HASH_TYPE_SHA224; + break; + #endif /* WOLFSSL_SHA224 */ + + #ifndef NO_SHA256 + case WC_SHA256: + eHashType = WC_HASH_TYPE_SHA256; + break; + #endif /* !NO_SHA256 */ + + #ifdef WOLFSSL_SHA384 + case WC_SHA384: + eHashType = WC_HASH_TYPE_SHA384; + break; + #endif /* WOLFSSL_SHA384 */ + #ifdef WOLFSSL_SHA512 + case WC_SHA512: + eHashType = WC_HASH_TYPE_SHA512; + break; + #endif /* WOLFSSL_SHA512 */ + #ifdef WOLFSSL_SHA3 + case WC_SHA3_224: + eHashType = WC_HASH_TYPE_SHA3_224; + break; + case WC_SHA3_256: + eHashType = WC_HASH_TYPE_SHA3_256; + break; + case WC_SHA3_384: + eHashType = WC_HASH_TYPE_SHA3_384; + break; + case WC_SHA3_512: + eHashType = WC_HASH_TYPE_SHA3_512; + break; + #endif /* WOLFSSL_SHA3 */ + default: + eHashType = WC_HASH_TYPE_NONE; + break; + } +#else + /* current master uses same unique types as wc_HashType */ + if (hashType > 0 && hashType <= WC_HASH_TYPE_MAX) { + eHashType = (enum wc_HashType)hashType; + } +#endif + return eHashType; +} + + +int wc_HashGetOID(enum wc_HashType hash_type) +{ + int oid = HASH_TYPE_E; /* Default to hash type error */ + switch(hash_type) + { + case WC_HASH_TYPE_MD2: + #ifdef WOLFSSL_MD2 + oid = MD2h; + #endif + break; + case WC_HASH_TYPE_MD5_SHA: + case WC_HASH_TYPE_MD5: + #ifndef NO_MD5 + oid = MD5h; + #endif + break; + case WC_HASH_TYPE_SHA: + #ifndef NO_SHA + oid = SHAh; + #endif + break; + case WC_HASH_TYPE_SHA224: + #ifdef WOLFSSL_SHA224 + oid = SHA224h; + #endif + break; + case WC_HASH_TYPE_SHA256: + #ifndef NO_SHA256 + oid = SHA256h; + #endif + break; + case WC_HASH_TYPE_SHA384: + #ifdef WOLFSSL_SHA384 + oid = SHA384h; + #endif + break; + case WC_HASH_TYPE_SHA512: + #ifdef WOLFSSL_SHA512 + oid = SHA512h; + #endif + break; + case WC_HASH_TYPE_SHA3_224: + #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_224) + oid = SHA3_224h; + #endif + break; + case WC_HASH_TYPE_SHA3_256: + #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_256) + oid = SHA3_256h; + #endif + break; + case WC_HASH_TYPE_SHA3_384: + #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_384) + oid = SHA3_384h; + #endif + break; + case WC_HASH_TYPE_SHA3_512: + #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_512) + oid = SHA3_512h; + #endif + break; + + /* Not Supported */ + case WC_HASH_TYPE_MD4: + case WC_HASH_TYPE_BLAKE2B: + case WC_HASH_TYPE_BLAKE2S: + case WC_HASH_TYPE_NONE: + default: + oid = BAD_FUNC_ARG; + break; + } + return oid; +} + +enum wc_HashType wc_OidGetHash(int oid) +{ + enum wc_HashType hash_type = WC_HASH_TYPE_NONE; + switch (oid) + { + #ifdef WOLFSSL_MD2 + case MD2h: + hash_type = WC_HASH_TYPE_MD2; + break; + #endif + case MD5h: + #ifndef NO_MD5 + hash_type = WC_HASH_TYPE_MD5; + #endif + break; + case SHAh: + #ifndef NO_SHA + hash_type = WC_HASH_TYPE_SHA; + #endif + break; + case SHA224h: + #ifdef WOLFSSL_SHA224 + hash_type = WC_HASH_TYPE_SHA224; + #endif + break; + case SHA256h: + #ifndef NO_SHA256 + hash_type = WC_HASH_TYPE_SHA256; + #endif + break; + case SHA384h: + #ifdef WOLFSSL_SHA384 + hash_type = WC_HASH_TYPE_SHA384; + #endif + break; + case SHA512h: + #ifdef WOLFSSL_SHA512 + hash_type = WC_HASH_TYPE_SHA512; + #endif + break; + #ifdef WOLFSSL_SHA3 + case SHA3_224h: + hash_type = WC_HASH_TYPE_SHA3_224; + break; + case SHA3_256h: + hash_type = WC_HASH_TYPE_SHA3_256; + break; + case SHA3_384h: + hash_type = WC_HASH_TYPE_SHA3_384; + break; + case SHA3_512h: + hash_type = WC_HASH_TYPE_SHA3_512; + break; + #endif /* WOLFSSL_SHA3 */ + default: + break; + } + return hash_type; +} +#endif /* !NO_ASN || !NO_DH || HAVE_ECC */ + + + +/* Get Hash digest size */ +int wc_HashGetDigestSize(enum wc_HashType hash_type) +{ + int dig_size = HASH_TYPE_E; /* Default to hash type error */ + switch(hash_type) + { + case WC_HASH_TYPE_MD2: + #ifdef WOLFSSL_MD2 + dig_size = MD2_DIGEST_SIZE; + #endif + break; + case WC_HASH_TYPE_MD4: + #ifndef NO_MD4 + dig_size = MD4_DIGEST_SIZE; + #endif + break; + case WC_HASH_TYPE_MD5: + #ifndef NO_MD5 + dig_size = WC_MD5_DIGEST_SIZE; + #endif + break; + case WC_HASH_TYPE_SHA: + #ifndef NO_SHA + dig_size = WC_SHA_DIGEST_SIZE; + #endif + break; + case WC_HASH_TYPE_SHA224: + #ifdef WOLFSSL_SHA224 + dig_size = WC_SHA224_DIGEST_SIZE; + #endif + break; + case WC_HASH_TYPE_SHA256: + #ifndef NO_SHA256 + dig_size = WC_SHA256_DIGEST_SIZE; + #endif + break; + case WC_HASH_TYPE_SHA384: + #ifdef WOLFSSL_SHA384 + dig_size = WC_SHA384_DIGEST_SIZE; + #endif + break; + case WC_HASH_TYPE_SHA512: + #ifdef WOLFSSL_SHA512 + dig_size = WC_SHA512_DIGEST_SIZE; + #endif + break; + case WC_HASH_TYPE_MD5_SHA: /* Old TLS Specific */ + #if !defined(NO_MD5) && !defined(NO_SHA) + dig_size = (int)WC_MD5_DIGEST_SIZE + (int)WC_SHA_DIGEST_SIZE; + #endif + break; + + case WC_HASH_TYPE_SHA3_224: + #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_224) + dig_size = WC_SHA3_224_DIGEST_SIZE; + #endif + break; + case WC_HASH_TYPE_SHA3_256: + #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_256) + dig_size = WC_SHA3_256_DIGEST_SIZE; + #endif + break; + case WC_HASH_TYPE_SHA3_384: + #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_384) + dig_size = WC_SHA3_384_DIGEST_SIZE; + #endif + break; + case WC_HASH_TYPE_SHA3_512: + #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_512) + dig_size = WC_SHA3_512_DIGEST_SIZE; + #endif + break; + case WC_HASH_TYPE_BLAKE2B: + case WC_HASH_TYPE_BLAKE2S: + #if defined(HAVE_BLAKE2) || defined(HAVE_BLAKE2S) + dig_size = BLAKE2S_OUTBYTES; + #endif + break; + + /* Not Supported */ + case WC_HASH_TYPE_NONE: + default: + dig_size = BAD_FUNC_ARG; + break; + } + return dig_size; +} + + +/* Get Hash block size */ +int wc_HashGetBlockSize(enum wc_HashType hash_type) +{ + int block_size = HASH_TYPE_E; /* Default to hash type error */ + switch (hash_type) + { + case WC_HASH_TYPE_MD2: + #ifdef WOLFSSL_MD2 + block_size = MD2_BLOCK_SIZE; + #endif + break; + case WC_HASH_TYPE_MD4: + #ifndef NO_MD4 + block_size = MD4_BLOCK_SIZE; + #endif + break; + case WC_HASH_TYPE_MD5: + #ifndef NO_MD5 + block_size = WC_MD5_BLOCK_SIZE; + #endif + break; + case WC_HASH_TYPE_SHA: + #ifndef NO_SHA + block_size = WC_SHA_BLOCK_SIZE; + #endif + break; + case WC_HASH_TYPE_SHA224: + #ifdef WOLFSSL_SHA224 + block_size = WC_SHA224_BLOCK_SIZE; + #endif + break; + case WC_HASH_TYPE_SHA256: + #ifndef NO_SHA256 + block_size = WC_SHA256_BLOCK_SIZE; + #endif + break; + case WC_HASH_TYPE_SHA384: + #ifdef WOLFSSL_SHA384 + block_size = WC_SHA384_BLOCK_SIZE; + #endif + break; + case WC_HASH_TYPE_SHA512: + #ifdef WOLFSSL_SHA512 + block_size = WC_SHA512_BLOCK_SIZE; + #endif + break; + case WC_HASH_TYPE_MD5_SHA: /* Old TLS Specific */ + #if !defined(NO_MD5) && !defined(NO_SHA) + block_size = (int)WC_MD5_BLOCK_SIZE + (int)WC_SHA_BLOCK_SIZE; + #endif + break; + + case WC_HASH_TYPE_SHA3_224: + #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_224) + block_size = WC_SHA3_224_BLOCK_SIZE; + #endif + break; + case WC_HASH_TYPE_SHA3_256: + #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_256) + block_size = WC_SHA3_256_BLOCK_SIZE; + #endif + break; + case WC_HASH_TYPE_SHA3_384: + #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_384) + block_size = WC_SHA3_384_BLOCK_SIZE; + #endif + break; + case WC_HASH_TYPE_SHA3_512: + #if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_512) + block_size = WC_SHA3_512_BLOCK_SIZE; + #endif + break; + case WC_HASH_TYPE_BLAKE2B: + case WC_HASH_TYPE_BLAKE2S: + #if defined(HAVE_BLAKE2) || defined(HAVE_BLAKE2S) + block_size = BLAKE2S_BLOCKBYTES; + #endif + break; + + /* Not Supported */ + case WC_HASH_TYPE_NONE: + default: + block_size = BAD_FUNC_ARG; + break; + } + return block_size; +} + +/* Generic Hashing Wrapper */ +int wc_Hash(enum wc_HashType hash_type, const byte* data, + word32 data_len, byte* hash, word32 hash_len) +{ + int ret = HASH_TYPE_E; /* Default to hash type error */ + word32 dig_size; + + /* Validate hash buffer size */ + dig_size = wc_HashGetDigestSize(hash_type); + if (hash_len < dig_size) { + return BUFFER_E; + } + + /* Suppress possible unused arg if all hashing is disabled */ + (void)data; + (void)data_len; + (void)hash; + (void)hash_len; + + switch(hash_type) + { + case WC_HASH_TYPE_MD5: +#ifndef NO_MD5 + ret = wc_Md5Hash(data, data_len, hash); +#endif + break; + case WC_HASH_TYPE_SHA: +#ifndef NO_SHA + ret = wc_ShaHash(data, data_len, hash); +#endif + break; + case WC_HASH_TYPE_SHA224: +#ifdef WOLFSSL_SHA224 + ret = wc_Sha224Hash(data, data_len, hash); +#endif + break; + case WC_HASH_TYPE_SHA256: +#ifndef NO_SHA256 + ret = wc_Sha256Hash(data, data_len, hash); +#endif + break; + case WC_HASH_TYPE_SHA384: +#ifdef WOLFSSL_SHA384 + ret = wc_Sha384Hash(data, data_len, hash); +#endif + break; + case WC_HASH_TYPE_SHA512: +#ifdef WOLFSSL_SHA512 + ret = wc_Sha512Hash(data, data_len, hash); +#endif + break; + case WC_HASH_TYPE_MD5_SHA: +#if !defined(NO_MD5) && !defined(NO_SHA) + ret = wc_Md5Hash(data, data_len, hash); + if (ret == 0) { + ret = wc_ShaHash(data, data_len, &hash[WC_MD5_DIGEST_SIZE]); + } +#endif + break; + + case WC_HASH_TYPE_SHA3_224: +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_224) + ret = wc_Sha3_224Hash(data, data_len, hash); +#endif + break; + case WC_HASH_TYPE_SHA3_256: +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_256) + ret = wc_Sha3_256Hash(data, data_len, hash); +#endif + break; + case WC_HASH_TYPE_SHA3_384: +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_384) + ret = wc_Sha3_384Hash(data, data_len, hash); +#endif + break; + case WC_HASH_TYPE_SHA3_512: +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_512) + ret = wc_Sha3_512Hash(data, data_len, hash); +#endif + break; + + /* Not Supported */ + case WC_HASH_TYPE_MD2: + case WC_HASH_TYPE_MD4: + case WC_HASH_TYPE_BLAKE2B: + case WC_HASH_TYPE_BLAKE2S: + case WC_HASH_TYPE_NONE: + default: + ret = BAD_FUNC_ARG; + break; + } + return ret; +} + +int wc_HashInit(wc_HashAlg* hash, enum wc_HashType type) +{ + int ret = HASH_TYPE_E; /* Default to hash type error */ + + if (hash == NULL) + return BAD_FUNC_ARG; + + switch (type) { + case WC_HASH_TYPE_MD5: +#ifndef NO_MD5 + ret = wc_InitMd5(&hash->md5); +#endif + break; + case WC_HASH_TYPE_SHA: +#ifndef NO_SHA + ret = wc_InitSha(&hash->sha); +#endif + break; + case WC_HASH_TYPE_SHA224: +#ifdef WOLFSSL_SHA224 + ret = wc_InitSha224(&hash->sha224); +#endif + break; + case WC_HASH_TYPE_SHA256: +#ifndef NO_SHA256 + ret = wc_InitSha256(&hash->sha256); +#endif + break; + case WC_HASH_TYPE_SHA384: +#ifdef WOLFSSL_SHA384 + ret = wc_InitSha384(&hash->sha384); +#endif + break; + case WC_HASH_TYPE_SHA512: +#ifdef WOLFSSL_SHA512 + ret = wc_InitSha512(&hash->sha512); +#endif + break; + + case WC_HASH_TYPE_SHA3_224: +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_224) + ret = wc_InitSha3_224(&hash->sha3, NULL, INVALID_DEVID); +#endif + break; + case WC_HASH_TYPE_SHA3_256: +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_256) + ret = wc_InitSha3_256(&hash->sha3, NULL, INVALID_DEVID); +#endif + break; + case WC_HASH_TYPE_SHA3_384: +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_384) + ret = wc_InitSha3_384(&hash->sha3, NULL, INVALID_DEVID); +#endif + break; + case WC_HASH_TYPE_SHA3_512: +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_512) + ret = wc_InitSha3_512(&hash->sha3, NULL, INVALID_DEVID); +#endif + break; + + /* not supported */ + case WC_HASH_TYPE_MD5_SHA: + case WC_HASH_TYPE_MD2: + case WC_HASH_TYPE_MD4: + case WC_HASH_TYPE_BLAKE2B: + case WC_HASH_TYPE_BLAKE2S: + case WC_HASH_TYPE_NONE: + default: + ret = BAD_FUNC_ARG; + }; + + return ret; +} + +int wc_HashUpdate(wc_HashAlg* hash, enum wc_HashType type, const byte* data, + word32 dataSz) +{ + int ret = HASH_TYPE_E; /* Default to hash type error */ + + if (hash == NULL || data == NULL) + return BAD_FUNC_ARG; + + switch (type) { + case WC_HASH_TYPE_MD5: +#ifndef NO_MD5 + ret = wc_Md5Update(&hash->md5, data, dataSz); +#endif + break; + case WC_HASH_TYPE_SHA: +#ifndef NO_SHA + ret = wc_ShaUpdate(&hash->sha, data, dataSz); +#endif + break; + case WC_HASH_TYPE_SHA224: +#ifdef WOLFSSL_SHA224 + ret = wc_Sha224Update(&hash->sha224, data, dataSz); +#endif + break; + case WC_HASH_TYPE_SHA256: +#ifndef NO_SHA256 + ret = wc_Sha256Update(&hash->sha256, data, dataSz); +#endif + break; + case WC_HASH_TYPE_SHA384: +#ifdef WOLFSSL_SHA384 + ret = wc_Sha384Update(&hash->sha384, data, dataSz); +#endif + break; + case WC_HASH_TYPE_SHA512: +#ifdef WOLFSSL_SHA512 + ret = wc_Sha512Update(&hash->sha512, data, dataSz); +#endif + break; + + case WC_HASH_TYPE_SHA3_224: +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_224) + ret = wc_Sha3_224_Update(&hash->sha3, data, dataSz); +#endif + break; + case WC_HASH_TYPE_SHA3_256: +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_256) + ret = wc_Sha3_256_Update(&hash->sha3, data, dataSz); +#endif + break; + case WC_HASH_TYPE_SHA3_384: +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_384) + ret = wc_Sha3_384_Update(&hash->sha3, data, dataSz); +#endif + break; + case WC_HASH_TYPE_SHA3_512: +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_512) + ret = wc_Sha3_512_Update(&hash->sha3, data, dataSz); +#endif + break; + + /* not supported */ + case WC_HASH_TYPE_MD5_SHA: + case WC_HASH_TYPE_MD2: + case WC_HASH_TYPE_MD4: + case WC_HASH_TYPE_BLAKE2B: + case WC_HASH_TYPE_BLAKE2S: + case WC_HASH_TYPE_NONE: + default: + ret = BAD_FUNC_ARG; + }; + + return ret; +} + +int wc_HashFinal(wc_HashAlg* hash, enum wc_HashType type, byte* out) +{ + int ret = HASH_TYPE_E; /* Default to hash type error */ + + if (hash == NULL || out == NULL) + return BAD_FUNC_ARG; + + switch (type) { + case WC_HASH_TYPE_MD5: +#ifndef NO_MD5 + ret = wc_Md5Final(&hash->md5, out); +#endif + break; + case WC_HASH_TYPE_SHA: +#ifndef NO_SHA + ret = wc_ShaFinal(&hash->sha, out); +#endif + break; + case WC_HASH_TYPE_SHA224: +#ifdef WOLFSSL_SHA224 + ret = wc_Sha224Final(&hash->sha224, out); +#endif + break; + case WC_HASH_TYPE_SHA256: +#ifndef NO_SHA256 + ret = wc_Sha256Final(&hash->sha256, out); +#endif + break; + case WC_HASH_TYPE_SHA384: +#ifdef WOLFSSL_SHA384 + ret = wc_Sha384Final(&hash->sha384, out); +#endif + break; + case WC_HASH_TYPE_SHA512: +#ifdef WOLFSSL_SHA512 + ret = wc_Sha512Final(&hash->sha512, out); +#endif + break; + + case WC_HASH_TYPE_SHA3_224: +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_224) + ret = wc_Sha3_224_Final(&hash->sha3, out); +#endif + break; + case WC_HASH_TYPE_SHA3_256: +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_256) + ret = wc_Sha3_256_Final(&hash->sha3, out); +#endif + break; + case WC_HASH_TYPE_SHA3_384: +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_384) + ret = wc_Sha3_384_Final(&hash->sha3, out); +#endif + break; + case WC_HASH_TYPE_SHA3_512: +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_512) + ret = wc_Sha3_512_Final(&hash->sha3, out); +#endif + break; + + /* not supported */ + case WC_HASH_TYPE_MD5_SHA: + case WC_HASH_TYPE_MD2: + case WC_HASH_TYPE_MD4: + case WC_HASH_TYPE_BLAKE2B: + case WC_HASH_TYPE_BLAKE2S: + case WC_HASH_TYPE_NONE: + default: + ret = BAD_FUNC_ARG; + }; + + return ret; +} + +int wc_HashFree(wc_HashAlg* hash, enum wc_HashType type) +{ + int ret = HASH_TYPE_E; /* Default to hash type error */ + + if (hash == NULL) + return BAD_FUNC_ARG; + + switch (type) { + case WC_HASH_TYPE_MD5: +#ifndef NO_MD5 + wc_Md5Free(&hash->md5); + ret = 0; +#endif + break; + case WC_HASH_TYPE_SHA: +#ifndef NO_SHA + wc_ShaFree(&hash->sha); + ret = 0; +#endif + break; + case WC_HASH_TYPE_SHA224: +#ifdef WOLFSSL_SHA224 + wc_Sha224Free(&hash->sha224); + ret = 0; +#endif + break; + case WC_HASH_TYPE_SHA256: +#ifndef NO_SHA256 + wc_Sha256Free(&hash->sha256); + ret = 0; +#endif + break; + case WC_HASH_TYPE_SHA384: +#ifdef WOLFSSL_SHA384 + wc_Sha384Free(&hash->sha384); + ret = 0; +#endif + break; + case WC_HASH_TYPE_SHA512: +#ifdef WOLFSSL_SHA512 + wc_Sha512Free(&hash->sha512); + ret = 0; +#endif + break; + + case WC_HASH_TYPE_SHA3_224: +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_224) + wc_Sha3_224_Free(&hash->sha3); + ret = 0; +#endif + break; + case WC_HASH_TYPE_SHA3_256: +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_256) + wc_Sha3_256_Free(&hash->sha3); + ret = 0; +#endif + break; + case WC_HASH_TYPE_SHA3_384: +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_384) + wc_Sha3_384_Free(&hash->sha3); + ret = 0; +#endif + break; + case WC_HASH_TYPE_SHA3_512: +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_NOSHA3_512) + wc_Sha3_512_Free(&hash->sha3); + ret = 0; +#endif + break; + + /* not supported */ + case WC_HASH_TYPE_MD5_SHA: + case WC_HASH_TYPE_MD2: + case WC_HASH_TYPE_MD4: + case WC_HASH_TYPE_BLAKE2B: + case WC_HASH_TYPE_BLAKE2S: + case WC_HASH_TYPE_NONE: + default: + ret = BAD_FUNC_ARG; + }; + + return ret; +} + +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) +int wc_HashSetFlags(wc_HashAlg* hash, enum wc_HashType type, word32 flags) +{ + int ret = HASH_TYPE_E; /* Default to hash type error */ + + if (hash == NULL) + return BAD_FUNC_ARG; + + switch (type) { + case WC_HASH_TYPE_MD5: +#ifndef NO_MD5 + ret = wc_Md5SetFlags(&hash->md5, flags); +#endif + break; + case WC_HASH_TYPE_SHA: +#ifndef NO_SHA + ret = wc_ShaSetFlags(&hash->sha, flags); +#endif + break; + case WC_HASH_TYPE_SHA224: +#ifdef WOLFSSL_SHA224 + ret = wc_Sha224SetFlags(&hash->sha224, flags); +#endif + break; + case WC_HASH_TYPE_SHA256: +#ifndef NO_SHA256 + ret = wc_Sha256SetFlags(&hash->sha256, flags); +#endif + break; + case WC_HASH_TYPE_SHA384: +#ifdef WOLFSSL_SHA384 + ret = wc_Sha384SetFlags(&hash->sha384, flags); +#endif + break; + case WC_HASH_TYPE_SHA512: +#ifdef WOLFSSL_SHA512 + ret = wc_Sha512SetFlags(&hash->sha512, flags); +#endif + break; + + case WC_HASH_TYPE_SHA3_224: + case WC_HASH_TYPE_SHA3_256: + case WC_HASH_TYPE_SHA3_384: + case WC_HASH_TYPE_SHA3_512: +#ifdef WOLFSSL_SHA3 + ret = wc_Sha3_SetFlags(&hash->sha3, flags); +#endif + break; + + /* not supported */ + case WC_HASH_TYPE_MD5_SHA: + case WC_HASH_TYPE_MD2: + case WC_HASH_TYPE_MD4: + case WC_HASH_TYPE_BLAKE2B: + case WC_HASH_TYPE_BLAKE2S: + case WC_HASH_TYPE_NONE: + default: + ret = BAD_FUNC_ARG; + }; + + return ret; +} +int wc_HashGetFlags(wc_HashAlg* hash, enum wc_HashType type, word32* flags) +{ + int ret = HASH_TYPE_E; /* Default to hash type error */ + + if (hash == NULL) + return BAD_FUNC_ARG; + + switch (type) { + case WC_HASH_TYPE_MD5: +#ifndef NO_MD5 + ret = wc_Md5GetFlags(&hash->md5, flags); +#endif + break; + case WC_HASH_TYPE_SHA: +#ifndef NO_SHA + ret = wc_ShaGetFlags(&hash->sha, flags); +#endif + break; + case WC_HASH_TYPE_SHA224: +#ifdef WOLFSSL_SHA224 + ret = wc_Sha224GetFlags(&hash->sha224, flags); +#endif + break; + case WC_HASH_TYPE_SHA256: +#ifndef NO_SHA256 + ret = wc_Sha256GetFlags(&hash->sha256, flags); +#endif + break; + case WC_HASH_TYPE_SHA384: +#ifdef WOLFSSL_SHA384 + ret = wc_Sha384GetFlags(&hash->sha384, flags); +#endif + break; + case WC_HASH_TYPE_SHA512: +#ifdef WOLFSSL_SHA512 + ret = wc_Sha512GetFlags(&hash->sha512, flags); +#endif + break; + + case WC_HASH_TYPE_SHA3_224: + case WC_HASH_TYPE_SHA3_256: + case WC_HASH_TYPE_SHA3_384: + case WC_HASH_TYPE_SHA3_512: +#ifdef WOLFSSL_SHA3 + ret = wc_Sha3_GetFlags(&hash->sha3, flags); +#endif + break; + + /* not supported */ + case WC_HASH_TYPE_MD5_SHA: + case WC_HASH_TYPE_MD2: + case WC_HASH_TYPE_MD4: + case WC_HASH_TYPE_BLAKE2B: + case WC_HASH_TYPE_BLAKE2S: + case WC_HASH_TYPE_NONE: + default: + ret = BAD_FUNC_ARG; + }; + + return ret; +} +#endif + + +#if !defined(WOLFSSL_TI_HASH) + +#if !defined(NO_MD5) + int wc_Md5Hash(const byte* data, word32 len, byte* hash) + { + int ret; + #ifdef WOLFSSL_SMALL_STACK + wc_Md5* md5; + #else + wc_Md5 md5[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + md5 = (wc_Md5*)XMALLOC(sizeof(wc_Md5), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (md5 == NULL) + return MEMORY_E; + #endif + + if ((ret = wc_InitMd5(md5)) != 0) { + WOLFSSL_MSG("InitMd5 failed"); + } + else { + if ((ret = wc_Md5Update(md5, data, len)) != 0) { + WOLFSSL_MSG("Md5Update failed"); + } + else if ((ret = wc_Md5Final(md5, hash)) != 0) { + WOLFSSL_MSG("Md5Final failed"); + } + wc_Md5Free(md5); + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(md5, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + return ret; + } +#endif /* !NO_MD5 */ + +#if !defined(NO_SHA) + int wc_ShaHash(const byte* data, word32 len, byte* hash) + { + int ret = 0; + #ifdef WOLFSSL_SMALL_STACK + wc_Sha* sha; + #else + wc_Sha sha[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + sha = (wc_Sha*)XMALLOC(sizeof(wc_Sha), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (sha == NULL) + return MEMORY_E; + #endif + + if ((ret = wc_InitSha(sha)) != 0) { + WOLFSSL_MSG("InitSha failed"); + } + else { + if ((ret = wc_ShaUpdate(sha, data, len)) != 0) { + WOLFSSL_MSG("ShaUpdate failed"); + } + else if ((ret = wc_ShaFinal(sha, hash)) != 0) { + WOLFSSL_MSG("ShaFinal failed"); + } + wc_ShaFree(sha); + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(sha, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + return ret; + } +#endif /* !NO_SHA */ + +#if defined(WOLFSSL_SHA224) + int wc_Sha224Hash(const byte* data, word32 len, byte* hash) + { + int ret = 0; + #ifdef WOLFSSL_SMALL_STACK + wc_Sha224* sha224; + #else + wc_Sha224 sha224[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + sha224 = (wc_Sha224*)XMALLOC(sizeof(wc_Sha224), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (sha224 == NULL) + return MEMORY_E; + #endif + + if ((ret = wc_InitSha224(sha224)) != 0) { + WOLFSSL_MSG("InitSha224 failed"); + } + else { + if ((ret = wc_Sha224Update(sha224, data, len)) != 0) { + WOLFSSL_MSG("Sha224Update failed"); + } + else if ((ret = wc_Sha224Final(sha224, hash)) != 0) { + WOLFSSL_MSG("Sha224Final failed"); + } + wc_Sha224Free(sha224); + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(sha224, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + return ret; +} +#endif /* WOLFSSL_SHA224 */ + +#if !defined(NO_SHA256) + int wc_Sha256Hash(const byte* data, word32 len, byte* hash) + { + int ret = 0; + #ifdef WOLFSSL_SMALL_STACK + wc_Sha256* sha256; + #else + wc_Sha256 sha256[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + sha256 = (wc_Sha256*)XMALLOC(sizeof(wc_Sha256), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (sha256 == NULL) + return MEMORY_E; + #endif + + if ((ret = wc_InitSha256(sha256)) != 0) { + WOLFSSL_MSG("InitSha256 failed"); + } + else { + if ((ret = wc_Sha256Update(sha256, data, len)) != 0) { + WOLFSSL_MSG("Sha256Update failed"); + } + else if ((ret = wc_Sha256Final(sha256, hash)) != 0) { + WOLFSSL_MSG("Sha256Final failed"); + } + wc_Sha256Free(sha256); + } + + + #ifdef WOLFSSL_SMALL_STACK + XFREE(sha256, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + return ret; + } +#endif /* !NO_SHA256 */ + +#endif /* !defined(WOLFSSL_TI_HASH) */ + + +#if defined(WOLFSSL_SHA512) + int wc_Sha512Hash(const byte* data, word32 len, byte* hash) + { + int ret = 0; + #ifdef WOLFSSL_SMALL_STACK + wc_Sha512* sha512; + #else + wc_Sha512 sha512[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + sha512 = (wc_Sha512*)XMALLOC(sizeof(wc_Sha512), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (sha512 == NULL) + return MEMORY_E; + #endif + + if ((ret = wc_InitSha512(sha512)) != 0) { + WOLFSSL_MSG("InitSha512 failed"); + } + else { + if ((ret = wc_Sha512Update(sha512, data, len)) != 0) { + WOLFSSL_MSG("Sha512Update failed"); + } + else if ((ret = wc_Sha512Final(sha512, hash)) != 0) { + WOLFSSL_MSG("Sha512Final failed"); + } + wc_Sha512Free(sha512); + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(sha512, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + return ret; + } +#endif /* WOLFSSL_SHA512 */ + +#if defined(WOLFSSL_SHA384) + int wc_Sha384Hash(const byte* data, word32 len, byte* hash) + { + int ret = 0; + #ifdef WOLFSSL_SMALL_STACK + wc_Sha384* sha384; + #else + wc_Sha384 sha384[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + sha384 = (wc_Sha384*)XMALLOC(sizeof(wc_Sha384), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (sha384 == NULL) + return MEMORY_E; + #endif + + if ((ret = wc_InitSha384(sha384)) != 0) { + WOLFSSL_MSG("InitSha384 failed"); + } + else { + if ((ret = wc_Sha384Update(sha384, data, len)) != 0) { + WOLFSSL_MSG("Sha384Update failed"); + } + else if ((ret = wc_Sha384Final(sha384, hash)) != 0) { + WOLFSSL_MSG("Sha384Final failed"); + } + wc_Sha384Free(sha384); + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(sha384, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + return ret; + } +#endif /* WOLFSSL_SHA384 */ + +#if defined(WOLFSSL_SHA3) +#if !defined(WOLFSSL_NOSHA3_224) + int wc_Sha3_224Hash(const byte* data, word32 len, byte* hash) + { + int ret = 0; + #ifdef WOLFSSL_SMALL_STACK + wc_Sha3* sha3; + #else + wc_Sha3 sha3[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + sha3 = (wc_Sha3*)XMALLOC(sizeof(wc_Sha3), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (sha3 == NULL) + return MEMORY_E; + #endif + + if ((ret = wc_InitSha3_224(sha3, NULL, INVALID_DEVID)) != 0) { + WOLFSSL_MSG("InitSha3_224 failed"); + } + else { + if ((ret = wc_Sha3_224_Update(sha3, data, len)) != 0) { + WOLFSSL_MSG("Sha3_224_Update failed"); + } + else if ((ret = wc_Sha3_224_Final(sha3, hash)) != 0) { + WOLFSSL_MSG("Sha3_224_Final failed"); + } + wc_Sha3_224_Free(sha3); + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(sha3, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + return ret; + } +#endif /* !WOLFSSL_NOSHA3_224 */ + +#if !defined(WOLFSSL_NOSHA3_256) + int wc_Sha3_256Hash(const byte* data, word32 len, byte* hash) + { + int ret = 0; + #ifdef WOLFSSL_SMALL_STACK + wc_Sha3* sha3; + #else + wc_Sha3 sha3[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + sha3 = (wc_Sha3*)XMALLOC(sizeof(wc_Sha3), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (sha3 == NULL) + return MEMORY_E; + #endif + + if ((ret = wc_InitSha3_256(sha3, NULL, INVALID_DEVID)) != 0) { + WOLFSSL_MSG("InitSha3_256 failed"); + } + else { + if ((ret = wc_Sha3_256_Update(sha3, data, len)) != 0) { + WOLFSSL_MSG("Sha3_256_Update failed"); + } + else if ((ret = wc_Sha3_256_Final(sha3, hash)) != 0) { + WOLFSSL_MSG("Sha3_256_Final failed"); + } + wc_Sha3_256_Free(sha3); + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(sha3, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + return ret; + } +#endif /* !WOLFSSL_NOSHA3_256 */ + +#if !defined(WOLFSSL_NOSHA3_384) + int wc_Sha3_384Hash(const byte* data, word32 len, byte* hash) + { + int ret = 0; + #ifdef WOLFSSL_SMALL_STACK + wc_Sha3* sha3; + #else + wc_Sha3 sha3[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + sha3 = (wc_Sha3*)XMALLOC(sizeof(wc_Sha3), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (sha3 == NULL) + return MEMORY_E; + #endif + + if ((ret = wc_InitSha3_384(sha3, NULL, INVALID_DEVID)) != 0) { + WOLFSSL_MSG("InitSha3_384 failed"); + } + else { + if ((ret = wc_Sha3_384_Update(sha3, data, len)) != 0) { + WOLFSSL_MSG("Sha3_384_Update failed"); + } + else if ((ret = wc_Sha3_384_Final(sha3, hash)) != 0) { + WOLFSSL_MSG("Sha3_384_Final failed"); + } + wc_Sha3_384_Free(sha3); + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(sha3, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + return ret; + } +#endif /* !WOLFSSL_NOSHA3_384 */ + +#if !defined(WOLFSSL_NOSHA3_512) + int wc_Sha3_512Hash(const byte* data, word32 len, byte* hash) + { + int ret = 0; + #ifdef WOLFSSL_SMALL_STACK + wc_Sha3* sha3; + #else + wc_Sha3 sha3[1]; + #endif + + #ifdef WOLFSSL_SMALL_STACK + sha3 = (wc_Sha3*)XMALLOC(sizeof(wc_Sha3), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (sha3 == NULL) + return MEMORY_E; + #endif + + if ((ret = wc_InitSha3_512(sha3, NULL, INVALID_DEVID)) != 0) { + WOLFSSL_MSG("InitSha3_512 failed"); + } + else { + if ((ret = wc_Sha3_512_Update(sha3, data, len)) != 0) { + WOLFSSL_MSG("Sha3_512_Update failed"); + } + else if ((ret = wc_Sha3_512_Final(sha3, hash)) != 0) { + WOLFSSL_MSG("Sha3_512_Final failed"); + } + wc_Sha3_512_Free(sha3); + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(sha3, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + return ret; + } +#endif /* !WOLFSSL_NOSHA3_512 */ +#endif /* WOLFSSL_SHA3 */ + +#ifdef WOLFSSL_HAVE_PRF + +#ifdef WOLFSSL_SHA384 + #define P_HASH_MAX_SIZE WC_SHA384_DIGEST_SIZE +#else + #define P_HASH_MAX_SIZE WC_SHA256_DIGEST_SIZE +#endif + +/* Pseudo Random Function for MD5, SHA-1, SHA-256, or SHA-384 */ +int wc_PRF(byte* result, word32 resLen, const byte* secret, + word32 secLen, const byte* seed, word32 seedLen, int hash, + void* heap, int devId) +{ + word32 len = P_HASH_MAX_SIZE; + word32 times; + word32 lastLen; + word32 lastTime; + word32 i; + word32 idx = 0; + int ret = 0; +#ifdef WOLFSSL_SMALL_STACK + byte* previous; + byte* current; + Hmac* hmac; +#else + byte previous[P_HASH_MAX_SIZE]; /* max size */ + byte current[P_HASH_MAX_SIZE]; /* max size */ + Hmac hmac[1]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + previous = (byte*)XMALLOC(P_HASH_MAX_SIZE, heap, DYNAMIC_TYPE_DIGEST); + current = (byte*)XMALLOC(P_HASH_MAX_SIZE, heap, DYNAMIC_TYPE_DIGEST); + hmac = (Hmac*)XMALLOC(sizeof(Hmac), heap, DYNAMIC_TYPE_HMAC); + + if (previous == NULL || current == NULL || hmac == NULL) { + if (previous) XFREE(previous, heap, DYNAMIC_TYPE_DIGEST); + if (current) XFREE(current, heap, DYNAMIC_TYPE_DIGEST); + if (hmac) XFREE(hmac, heap, DYNAMIC_TYPE_HMAC); + + return MEMORY_E; + } +#endif + + switch (hash) { + #ifndef NO_MD5 + case md5_mac: + hash = WC_MD5; + len = WC_MD5_DIGEST_SIZE; + break; + #endif + + #ifndef NO_SHA256 + case sha256_mac: + hash = WC_SHA256; + len = WC_SHA256_DIGEST_SIZE; + break; + #endif + + #ifdef WOLFSSL_SHA384 + case sha384_mac: + hash = WC_SHA384; + len = WC_SHA384_DIGEST_SIZE; + break; + #endif + + #ifndef NO_SHA + case sha_mac: + default: + hash = WC_SHA; + len = WC_SHA_DIGEST_SIZE; + break; + #endif + } + + times = resLen / len; + lastLen = resLen % len; + + if (lastLen) + times += 1; + + lastTime = times - 1; + + ret = wc_HmacInit(hmac, heap, devId); + if (ret == 0) { + ret = wc_HmacSetKey(hmac, hash, secret, secLen); + if (ret == 0) + ret = wc_HmacUpdate(hmac, seed, seedLen); /* A0 = seed */ + if (ret == 0) + ret = wc_HmacFinal(hmac, previous); /* A1 */ + if (ret == 0) { + for (i = 0; i < times; i++) { + ret = wc_HmacUpdate(hmac, previous, len); + if (ret != 0) + break; + ret = wc_HmacUpdate(hmac, seed, seedLen); + if (ret != 0) + break; + ret = wc_HmacFinal(hmac, current); + if (ret != 0) + break; + + if ((i == lastTime) && lastLen) + XMEMCPY(&result[idx], current, + min(lastLen, P_HASH_MAX_SIZE)); + else { + XMEMCPY(&result[idx], current, len); + idx += len; + ret = wc_HmacUpdate(hmac, previous, len); + if (ret != 0) + break; + ret = wc_HmacFinal(hmac, previous); + if (ret != 0) + break; + } + } + } + wc_HmacFree(hmac); + } + + ForceZero(previous, P_HASH_MAX_SIZE); + ForceZero(current, P_HASH_MAX_SIZE); + ForceZero(hmac, sizeof(Hmac)); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(previous, heap, DYNAMIC_TYPE_DIGEST); + XFREE(current, heap, DYNAMIC_TYPE_DIGEST); + XFREE(hmac, heap, DYNAMIC_TYPE_HMAC); +#endif + + return ret; +} +#undef P_HASH_MAX_SIZE + +/* compute PRF (pseudo random function) using SHA1 and MD5 for TLSv1 */ +int wc_PRF_TLSv1(byte* digest, word32 digLen, const byte* secret, + word32 secLen, const byte* label, word32 labLen, + const byte* seed, word32 seedLen, void* heap, int devId) +{ + int ret = 0; + word32 half = (secLen + 1) / 2; + +#ifdef WOLFSSL_SMALL_STACK + byte* md5_half; + byte* sha_half; + byte* md5_result; + byte* sha_result; +#else + byte md5_half[MAX_PRF_HALF]; /* half is real size */ + byte sha_half[MAX_PRF_HALF]; /* half is real size */ + byte md5_result[MAX_PRF_DIG]; /* digLen is real size */ + byte sha_result[MAX_PRF_DIG]; /* digLen is real size */ +#endif +#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH) + DECLARE_VAR(labelSeed, byte, MAX_PRF_LABSEED, heap); + if (labelSeed == NULL) + return MEMORY_E; +#else + byte labelSeed[MAX_PRF_LABSEED]; +#endif + + if (half > MAX_PRF_HALF || + labLen + seedLen > MAX_PRF_LABSEED || + digLen > MAX_PRF_DIG) + { + #if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH) + FREE_VAR(labelSeed, heap); + #endif + return BUFFER_E; + } + +#ifdef WOLFSSL_SMALL_STACK + md5_half = (byte*)XMALLOC(MAX_PRF_HALF, heap, DYNAMIC_TYPE_DIGEST); + sha_half = (byte*)XMALLOC(MAX_PRF_HALF, heap, DYNAMIC_TYPE_DIGEST); + md5_result = (byte*)XMALLOC(MAX_PRF_DIG, heap, DYNAMIC_TYPE_DIGEST); + sha_result = (byte*)XMALLOC(MAX_PRF_DIG, heap, DYNAMIC_TYPE_DIGEST); + + if (md5_half == NULL || sha_half == NULL || md5_result == NULL || + sha_result == NULL) { + if (md5_half) XFREE(md5_half, heap, DYNAMIC_TYPE_DIGEST); + if (sha_half) XFREE(sha_half, heap, DYNAMIC_TYPE_DIGEST); + if (md5_result) XFREE(md5_result, heap, DYNAMIC_TYPE_DIGEST); + if (sha_result) XFREE(sha_result, heap, DYNAMIC_TYPE_DIGEST); + #if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH) + FREE_VAR(labelSeed, heap); + #endif + + return MEMORY_E; + } +#endif + + XMEMSET(md5_result, 0, digLen); + XMEMSET(sha_result, 0, digLen); + + XMEMCPY(md5_half, secret, half); + XMEMCPY(sha_half, secret + half - secLen % 2, half); + + XMEMCPY(labelSeed, label, labLen); + XMEMCPY(labelSeed + labLen, seed, seedLen); + + if ((ret = wc_PRF(md5_result, digLen, md5_half, half, labelSeed, + labLen + seedLen, md5_mac, heap, devId)) == 0) { + if ((ret = wc_PRF(sha_result, digLen, sha_half, half, labelSeed, + labLen + seedLen, sha_mac, heap, devId)) == 0) { + /* calculate XOR for TLSv1 PRF */ + XMEMCPY(digest, md5_result, digLen); + xorbuf(digest, sha_result, digLen); + } + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(md5_half, heap, DYNAMIC_TYPE_DIGEST); + XFREE(sha_half, heap, DYNAMIC_TYPE_DIGEST); + XFREE(md5_result, heap, DYNAMIC_TYPE_DIGEST); + XFREE(sha_result, heap, DYNAMIC_TYPE_DIGEST); +#endif + +#if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH) + FREE_VAR(labelSeed, heap); +#endif + + return ret; +} + +/* Wrapper for TLS 1.2 and TLSv1 cases to calculate PRF */ +/* In TLS 1.2 case call straight thru to wc_PRF */ +int wc_PRF_TLS(byte* digest, word32 digLen, const byte* secret, word32 secLen, + const byte* label, word32 labLen, const byte* seed, word32 seedLen, + int useAtLeastSha256, int hash_type, void* heap, int devId) +{ + int ret = 0; + + if (useAtLeastSha256) { + #if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH) + DECLARE_VAR(labelSeed, byte, MAX_PRF_LABSEED, heap); + if (labelSeed == NULL) + return MEMORY_E; + #else + byte labelSeed[MAX_PRF_LABSEED]; + #endif + + if (labLen + seedLen > MAX_PRF_LABSEED) + return BUFFER_E; + + XMEMCPY(labelSeed, label, labLen); + XMEMCPY(labelSeed + labLen, seed, seedLen); + + /* If a cipher suite wants an algorithm better than sha256, it + * should use better. */ + if (hash_type < sha256_mac || hash_type == blake2b_mac) + hash_type = sha256_mac; + /* compute PRF for MD5, SHA-1, SHA-256, or SHA-384 for TLSv1.2 PRF */ + ret = wc_PRF(digest, digLen, secret, secLen, labelSeed, + labLen + seedLen, hash_type, heap, devId); + + #if defined(WOLFSSL_ASYNC_CRYPT) && !defined(WC_ASYNC_NO_HASH) + FREE_VAR(labelSeed, heap); + #endif + } +#ifndef NO_OLD_TLS + else { + /* compute TLSv1 PRF (pseudo random function using HMAC) */ + ret = wc_PRF_TLSv1(digest, digLen, secret, secLen, label, labLen, seed, + seedLen, heap, devId); + } +#endif + + return ret; +} +#endif /* WOLFSSL_HAVE_PRF */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/hc128.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/hc128.c new file mode 100755 index 0000000..dc36f5a --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/hc128.c @@ -0,0 +1,430 @@ +/* hc128.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifdef HAVE_HC128 + +#include +#include +#include +#ifdef NO_INLINE + #include + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + + +#ifdef BIG_ENDIAN_ORDER + #define LITTLE32(x) ByteReverseWord32(x) +#else + #define LITTLE32(x) (x) +#endif + + +/*h1 function*/ +#define h1(ctx, x, y) { \ + byte a,c; \ + a = (byte) (x); \ + c = (byte) ((x) >> 16); \ + y = (ctx->T[512+a])+(ctx->T[512+256+c]); \ +} + +/*h2 function*/ +#define h2(ctx, x, y) { \ + byte a,c; \ + a = (byte) (x); \ + c = (byte) ((x) >> 16); \ + y = (ctx->T[a])+(ctx->T[256+c]); \ +} + +/*one step of HC-128, update P and generate 32 bits keystream*/ +#define step_P(ctx,u,v,a,b,c,d,n){ \ + word32 tem0,tem1,tem2,tem3; \ + h1((ctx),(ctx->X[(d)]),tem3); \ + tem0 = rotrFixed((ctx->T[(v)]),23); \ + tem1 = rotrFixed((ctx->X[(c)]),10); \ + tem2 = rotrFixed((ctx->X[(b)]),8); \ + (ctx->T[(u)]) += tem2+(tem0 ^ tem1); \ + (ctx->X[(a)]) = (ctx->T[(u)]); \ + (n) = tem3 ^ (ctx->T[(u)]) ; \ +} + +/*one step of HC-128, update Q and generate 32 bits keystream*/ +#define step_Q(ctx,u,v,a,b,c,d,n){ \ + word32 tem0,tem1,tem2,tem3; \ + h2((ctx),(ctx->Y[(d)]),tem3); \ + tem0 = rotrFixed((ctx->T[(v)]),(32-23)); \ + tem1 = rotrFixed((ctx->Y[(c)]),(32-10)); \ + tem2 = rotrFixed((ctx->Y[(b)]),(32-8)); \ + (ctx->T[(u)]) += tem2 + (tem0 ^ tem1); \ + (ctx->Y[(a)]) = (ctx->T[(u)]); \ + (n) = tem3 ^ (ctx->T[(u)]) ; \ +} + +/*16 steps of HC-128, generate 512 bits keystream*/ +static void generate_keystream(HC128* ctx, word32* keystream) +{ + word32 cc,dd; + cc = ctx->counter1024 & 0x1ff; + dd = (cc+16)&0x1ff; + + if (ctx->counter1024 < 512) + { + ctx->counter1024 = (ctx->counter1024 + 16) & 0x3ff; + step_P(ctx, cc+0, cc+1, 0, 6, 13,4, keystream[0]); + step_P(ctx, cc+1, cc+2, 1, 7, 14,5, keystream[1]); + step_P(ctx, cc+2, cc+3, 2, 8, 15,6, keystream[2]); + step_P(ctx, cc+3, cc+4, 3, 9, 0, 7, keystream[3]); + step_P(ctx, cc+4, cc+5, 4, 10,1, 8, keystream[4]); + step_P(ctx, cc+5, cc+6, 5, 11,2, 9, keystream[5]); + step_P(ctx, cc+6, cc+7, 6, 12,3, 10,keystream[6]); + step_P(ctx, cc+7, cc+8, 7, 13,4, 11,keystream[7]); + step_P(ctx, cc+8, cc+9, 8, 14,5, 12,keystream[8]); + step_P(ctx, cc+9, cc+10,9, 15,6, 13,keystream[9]); + step_P(ctx, cc+10,cc+11,10,0, 7, 14,keystream[10]); + step_P(ctx, cc+11,cc+12,11,1, 8, 15,keystream[11]); + step_P(ctx, cc+12,cc+13,12,2, 9, 0, keystream[12]); + step_P(ctx, cc+13,cc+14,13,3, 10,1, keystream[13]); + step_P(ctx, cc+14,cc+15,14,4, 11,2, keystream[14]); + step_P(ctx, cc+15,dd+0, 15,5, 12,3, keystream[15]); + } + else + { + ctx->counter1024 = (ctx->counter1024 + 16) & 0x3ff; + step_Q(ctx, 512+cc+0, 512+cc+1, 0, 6, 13,4, keystream[0]); + step_Q(ctx, 512+cc+1, 512+cc+2, 1, 7, 14,5, keystream[1]); + step_Q(ctx, 512+cc+2, 512+cc+3, 2, 8, 15,6, keystream[2]); + step_Q(ctx, 512+cc+3, 512+cc+4, 3, 9, 0, 7, keystream[3]); + step_Q(ctx, 512+cc+4, 512+cc+5, 4, 10,1, 8, keystream[4]); + step_Q(ctx, 512+cc+5, 512+cc+6, 5, 11,2, 9, keystream[5]); + step_Q(ctx, 512+cc+6, 512+cc+7, 6, 12,3, 10,keystream[6]); + step_Q(ctx, 512+cc+7, 512+cc+8, 7, 13,4, 11,keystream[7]); + step_Q(ctx, 512+cc+8, 512+cc+9, 8, 14,5, 12,keystream[8]); + step_Q(ctx, 512+cc+9, 512+cc+10,9, 15,6, 13,keystream[9]); + step_Q(ctx, 512+cc+10,512+cc+11,10,0, 7, 14,keystream[10]); + step_Q(ctx, 512+cc+11,512+cc+12,11,1, 8, 15,keystream[11]); + step_Q(ctx, 512+cc+12,512+cc+13,12,2, 9, 0, keystream[12]); + step_Q(ctx, 512+cc+13,512+cc+14,13,3, 10,1, keystream[13]); + step_Q(ctx, 512+cc+14,512+cc+15,14,4, 11,2, keystream[14]); + step_Q(ctx, 512+cc+15,512+dd+0, 15,5, 12,3, keystream[15]); + } +} + + +/* The following defines the initialization functions */ +#define f1(x) (rotrFixed((x),7) ^ rotrFixed((x),18) ^ ((x) >> 3)) +#define f2(x) (rotrFixed((x),17) ^ rotrFixed((x),19) ^ ((x) >> 10)) + +/*update table P*/ +#define update_P(ctx,u,v,a,b,c,d){ \ + word32 tem0,tem1,tem2,tem3; \ + tem0 = rotrFixed((ctx->T[(v)]),23); \ + tem1 = rotrFixed((ctx->X[(c)]),10); \ + tem2 = rotrFixed((ctx->X[(b)]),8); \ + h1((ctx),(ctx->X[(d)]),tem3); \ + (ctx->T[(u)]) = ((ctx->T[(u)]) + tem2+(tem0^tem1)) ^ tem3; \ + (ctx->X[(a)]) = (ctx->T[(u)]); \ +} + +/*update table Q*/ +#define update_Q(ctx,u,v,a,b,c,d){ \ + word32 tem0,tem1,tem2,tem3; \ + tem0 = rotrFixed((ctx->T[(v)]),(32-23)); \ + tem1 = rotrFixed((ctx->Y[(c)]),(32-10)); \ + tem2 = rotrFixed((ctx->Y[(b)]),(32-8)); \ + h2((ctx),(ctx->Y[(d)]),tem3); \ + (ctx->T[(u)]) = ((ctx->T[(u)]) + tem2+(tem0^tem1)) ^ tem3; \ + (ctx->Y[(a)]) = (ctx->T[(u)]); \ +} + +/*16 steps of HC-128, without generating keystream, */ +/*but use the outputs to update P and Q*/ +static void setup_update(HC128* ctx) /*each time 16 steps*/ +{ + word32 cc,dd; + cc = ctx->counter1024 & 0x1ff; + dd = (cc+16)&0x1ff; + + if (ctx->counter1024 < 512) + { + ctx->counter1024 = (ctx->counter1024 + 16) & 0x3ff; + update_P(ctx, cc+0, cc+1, 0, 6, 13, 4); + update_P(ctx, cc+1, cc+2, 1, 7, 14, 5); + update_P(ctx, cc+2, cc+3, 2, 8, 15, 6); + update_P(ctx, cc+3, cc+4, 3, 9, 0, 7); + update_P(ctx, cc+4, cc+5, 4, 10,1, 8); + update_P(ctx, cc+5, cc+6, 5, 11,2, 9); + update_P(ctx, cc+6, cc+7, 6, 12,3, 10); + update_P(ctx, cc+7, cc+8, 7, 13,4, 11); + update_P(ctx, cc+8, cc+9, 8, 14,5, 12); + update_P(ctx, cc+9, cc+10,9, 15,6, 13); + update_P(ctx, cc+10,cc+11,10,0, 7, 14); + update_P(ctx, cc+11,cc+12,11,1, 8, 15); + update_P(ctx, cc+12,cc+13,12,2, 9, 0); + update_P(ctx, cc+13,cc+14,13,3, 10, 1); + update_P(ctx, cc+14,cc+15,14,4, 11, 2); + update_P(ctx, cc+15,dd+0, 15,5, 12, 3); + } + else + { + ctx->counter1024 = (ctx->counter1024 + 16) & 0x3ff; + update_Q(ctx, 512+cc+0, 512+cc+1, 0, 6, 13, 4); + update_Q(ctx, 512+cc+1, 512+cc+2, 1, 7, 14, 5); + update_Q(ctx, 512+cc+2, 512+cc+3, 2, 8, 15, 6); + update_Q(ctx, 512+cc+3, 512+cc+4, 3, 9, 0, 7); + update_Q(ctx, 512+cc+4, 512+cc+5, 4, 10,1, 8); + update_Q(ctx, 512+cc+5, 512+cc+6, 5, 11,2, 9); + update_Q(ctx, 512+cc+6, 512+cc+7, 6, 12,3, 10); + update_Q(ctx, 512+cc+7, 512+cc+8, 7, 13,4, 11); + update_Q(ctx, 512+cc+8, 512+cc+9, 8, 14,5, 12); + update_Q(ctx, 512+cc+9, 512+cc+10,9, 15,6, 13); + update_Q(ctx, 512+cc+10,512+cc+11,10,0, 7, 14); + update_Q(ctx, 512+cc+11,512+cc+12,11,1, 8, 15); + update_Q(ctx, 512+cc+12,512+cc+13,12,2, 9, 0); + update_Q(ctx, 512+cc+13,512+cc+14,13,3, 10, 1); + update_Q(ctx, 512+cc+14,512+cc+15,14,4, 11, 2); + update_Q(ctx, 512+cc+15,512+dd+0, 15,5, 12, 3); + } +} + + +/* for the 128-bit key: key[0]...key[15] +* key[0] is the least significant byte of ctx->key[0] (K_0); +* key[3] is the most significant byte of ctx->key[0] (K_0); +* ... +* key[12] is the least significant byte of ctx->key[3] (K_3) +* key[15] is the most significant byte of ctx->key[3] (K_3) +* +* for the 128-bit iv: iv[0]...iv[15] +* iv[0] is the least significant byte of ctx->iv[0] (IV_0); +* iv[3] is the most significant byte of ctx->iv[0] (IV_0); +* ... +* iv[12] is the least significant byte of ctx->iv[3] (IV_3) +* iv[15] is the most significant byte of ctx->iv[3] (IV_3) +*/ + + + +static void Hc128_SetIV(HC128* ctx, const byte* inIv) +{ + word32 i; + word32 iv[4]; + + if (inIv) + XMEMCPY(iv, inIv, sizeof(iv)); + else + XMEMSET(iv, 0, sizeof(iv)); + + for (i = 0; i < (128 >> 5); i++) + ctx->iv[i] = LITTLE32(iv[i]); + + for (; i < 8; i++) ctx->iv[i] = ctx->iv[i-4]; + + /* expand the key and IV into the table T */ + /* (expand the key and IV into the table P and Q) */ + + for (i = 0; i < 8; i++) ctx->T[i] = ctx->key[i]; + for (i = 8; i < 16; i++) ctx->T[i] = ctx->iv[i-8]; + + for (i = 16; i < (256+16); i++) + ctx->T[i] = f2(ctx->T[i-2]) + ctx->T[i-7] + f1(ctx->T[i-15]) + + ctx->T[i-16]+i; + + for (i = 0; i < 16; i++) ctx->T[i] = ctx->T[256+i]; + + for (i = 16; i < 1024; i++) + ctx->T[i] = f2(ctx->T[i-2]) + ctx->T[i-7] + f1(ctx->T[i-15]) + + ctx->T[i-16]+256+i; + + /* initialize counter1024, X and Y */ + ctx->counter1024 = 0; + for (i = 0; i < 16; i++) ctx->X[i] = ctx->T[512-16+i]; + for (i = 0; i < 16; i++) ctx->Y[i] = ctx->T[512+512-16+i]; + + /* run the cipher 1024 steps before generating the output */ + for (i = 0; i < 64; i++) setup_update(ctx); +} + + +static WC_INLINE int DoKey(HC128* ctx, const byte* key, const byte* iv) +{ + word32 i; + + /* Key size in bits 128 */ + for (i = 0; i < (128 >> 5); i++) + ctx->key[i] = LITTLE32(((word32*)key)[i]); + + for ( ; i < 8 ; i++) ctx->key[i] = ctx->key[i-4]; + + Hc128_SetIV(ctx, iv); + + return 0; +} + + +int wc_Hc128_SetHeap(HC128* ctx, void* heap) +{ + if (ctx == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef XSTREAM_ALIGN + ctx->heap = heap; +#endif + + (void)heap; + return 0; +} + +/* Key setup */ +int wc_Hc128_SetKey(HC128* ctx, const byte* key, const byte* iv) +{ + if (ctx == NULL || key == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef XSTREAM_ALIGN + /* default heap to NULL or heap test value */ + #ifdef WOLFSSL_HEAP_TEST + ctx->heap = (void*)WOLFSSL_HEAP_TEST; + #else + ctx->heap = NULL; + #endif /* WOLFSSL_HEAP_TEST */ + + if ((wolfssl_word)key % 4) { + int alignKey[4]; + + /* iv gets aligned in SetIV */ + WOLFSSL_MSG("Hc128SetKey unaligned key"); + + XMEMCPY(alignKey, key, sizeof(alignKey)); + + return DoKey(ctx, (const byte*)alignKey, iv); + } +#endif /* XSTREAM_ALIGN */ + + return DoKey(ctx, key, iv); +} + + + +/* The following defines the encryption of data stream */ +static WC_INLINE int DoProcess(HC128* ctx, byte* output, const byte* input, + word32 msglen) +{ + word32 i, keystream[16]; + + for ( ; msglen >= 64; msglen -= 64, input += 64, output += 64) + { + generate_keystream(ctx, keystream); + + /* unroll loop */ + ((word32*)output)[0] = ((word32*)input)[0] ^ LITTLE32(keystream[0]); + ((word32*)output)[1] = ((word32*)input)[1] ^ LITTLE32(keystream[1]); + ((word32*)output)[2] = ((word32*)input)[2] ^ LITTLE32(keystream[2]); + ((word32*)output)[3] = ((word32*)input)[3] ^ LITTLE32(keystream[3]); + ((word32*)output)[4] = ((word32*)input)[4] ^ LITTLE32(keystream[4]); + ((word32*)output)[5] = ((word32*)input)[5] ^ LITTLE32(keystream[5]); + ((word32*)output)[6] = ((word32*)input)[6] ^ LITTLE32(keystream[6]); + ((word32*)output)[7] = ((word32*)input)[7] ^ LITTLE32(keystream[7]); + ((word32*)output)[8] = ((word32*)input)[8] ^ LITTLE32(keystream[8]); + ((word32*)output)[9] = ((word32*)input)[9] ^ LITTLE32(keystream[9]); + ((word32*)output)[10] = ((word32*)input)[10] ^ LITTLE32(keystream[10]); + ((word32*)output)[11] = ((word32*)input)[11] ^ LITTLE32(keystream[11]); + ((word32*)output)[12] = ((word32*)input)[12] ^ LITTLE32(keystream[12]); + ((word32*)output)[13] = ((word32*)input)[13] ^ LITTLE32(keystream[13]); + ((word32*)output)[14] = ((word32*)input)[14] ^ LITTLE32(keystream[14]); + ((word32*)output)[15] = ((word32*)input)[15] ^ LITTLE32(keystream[15]); + } + + if (msglen > 0) + { + XMEMSET(keystream, 0, sizeof(keystream)); /* hush the static analysis */ + generate_keystream(ctx, keystream); + +#ifdef BIG_ENDIAN_ORDER + { + word32 wordsLeft = msglen / sizeof(word32); + if (msglen % sizeof(word32)) wordsLeft++; + + ByteReverseWords(keystream, keystream, wordsLeft * sizeof(word32)); + } +#endif + + for (i = 0; i < msglen; i++) + output[i] = input[i] ^ ((byte*)keystream)[i]; + } + + return 0; +} + + +/* Encrypt/decrypt a message of any size */ +int wc_Hc128_Process(HC128* ctx, byte* output, const byte* input, word32 msglen) +{ + if (ctx == NULL || output == NULL || input == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef XSTREAM_ALIGN + if ((wolfssl_word)input % 4 || (wolfssl_word)output % 4) { + #ifndef NO_WOLFSSL_ALLOC_ALIGN + byte* tmp; + WOLFSSL_MSG("Hc128Process unaligned"); + + tmp = (byte*)XMALLOC(msglen, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) return MEMORY_E; + + XMEMCPY(tmp, input, msglen); + DoProcess(ctx, tmp, tmp, msglen); + XMEMCPY(output, tmp, msglen); + + XFREE(tmp, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER); + + return 0; + #else + return BAD_ALIGN_E; + #endif + } +#endif /* XSTREAM_ALIGN */ + + return DoProcess(ctx, output, input, msglen); +} + + +#else /* HAVE_HC128 */ + + +#ifdef _MSC_VER + /* 4206 warning for blank file */ + #pragma warning(disable: 4206) +#endif + + +#endif /* HAVE_HC128 */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/hmac.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/hmac.c new file mode 100755 index 0000000..457370a --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/hmac.c @@ -0,0 +1,1355 @@ +/* hmac.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include +#include + +#ifndef NO_HMAC + +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + + /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ + #define FIPS_NO_WRAPPERS + + #ifdef USE_WINDOWS_API + #pragma code_seg(".fipsA$b") + #pragma const_seg(".fipsB$b") + #endif +#endif + +#include + +#ifdef WOLF_CRYPTO_CB + #include +#endif + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + + +/* fips wrapper calls, user can call direct */ +/* If building for old FIPS. */ +#if defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) + + /* does init */ + int wc_HmacSetKey(Hmac* hmac, int type, const byte* key, word32 keySz) + { + if (hmac == NULL || (key == NULL && keySz != 0) || + !(type == WC_MD5 || type == WC_SHA || type == WC_SHA256 || + type == WC_SHA384 || type == WC_SHA512 || + type == BLAKE2B_ID)) { + return BAD_FUNC_ARG; + } + + return HmacSetKey_fips(hmac, type, key, keySz); + } + int wc_HmacUpdate(Hmac* hmac, const byte* in, word32 sz) + { + if (hmac == NULL || (in == NULL && sz > 0)) { + return BAD_FUNC_ARG; + } + + return HmacUpdate_fips(hmac, in, sz); + } + int wc_HmacFinal(Hmac* hmac, byte* out) + { + if (hmac == NULL) { + return BAD_FUNC_ARG; + } + + return HmacFinal_fips(hmac, out); + } + int wolfSSL_GetHmacMaxSize(void) + { + return CyaSSL_GetHmacMaxSize(); + } + + int wc_HmacInit(Hmac* hmac, void* heap, int devId) + { + (void)hmac; + (void)heap; + (void)devId; + /* FIPS doesn't support: + return HmacInit(hmac, heap, devId); */ + return 0; + } + void wc_HmacFree(Hmac* hmac) + { + (void)hmac; + /* FIPS doesn't support: + HmacFree(hmac); */ + } + + #ifdef HAVE_HKDF + int wc_HKDF(int type, const byte* inKey, word32 inKeySz, + const byte* salt, word32 saltSz, + const byte* info, word32 infoSz, + byte* out, word32 outSz) + { + return HKDF(type, inKey, inKeySz, salt, saltSz, + info, infoSz, out, outSz); + } + #endif /* HAVE_HKDF */ + +#else /* else build without fips, or for new fips */ + + +int wc_HmacSizeByType(int type) +{ + int ret; + + if (!(type == WC_MD5 || type == WC_SHA || + type == WC_SHA224 || type == WC_SHA256 || + type == WC_SHA384 || type == WC_SHA512 || + type == WC_SHA3_224 || type == WC_SHA3_256 || + type == WC_SHA3_384 || type == WC_SHA3_512 || + type == BLAKE2B_ID)) { + return BAD_FUNC_ARG; + } + + switch (type) { + #ifndef NO_MD5 + case WC_MD5: + ret = WC_MD5_DIGEST_SIZE; + break; + #endif /* !NO_MD5 */ + + #ifndef NO_SHA + case WC_SHA: + ret = WC_SHA_DIGEST_SIZE; + break; + #endif /* !NO_SHA */ + + #ifdef WOLFSSL_SHA224 + case WC_SHA224: + ret = WC_SHA224_DIGEST_SIZE; + break; + #endif /* WOLFSSL_SHA224 */ + + #ifndef NO_SHA256 + case WC_SHA256: + ret = WC_SHA256_DIGEST_SIZE; + break; + #endif /* !NO_SHA256 */ + + #ifdef WOLFSSL_SHA384 + case WC_SHA384: + ret = WC_SHA384_DIGEST_SIZE; + break; + #endif /* WOLFSSL_SHA384 */ + #ifdef WOLFSSL_SHA512 + case WC_SHA512: + ret = WC_SHA512_DIGEST_SIZE; + break; + #endif /* WOLFSSL_SHA512 */ + + #ifdef HAVE_BLAKE2 + case BLAKE2B_ID: + ret = BLAKE2B_OUTBYTES; + break; + #endif /* HAVE_BLAKE2 */ + + #ifdef WOLFSSL_SHA3 + case WC_SHA3_224: + ret = WC_SHA3_224_DIGEST_SIZE; + break; + + case WC_SHA3_256: + ret = WC_SHA3_256_DIGEST_SIZE; + break; + + case WC_SHA3_384: + ret = WC_SHA3_384_DIGEST_SIZE; + break; + + case WC_SHA3_512: + ret = WC_SHA3_512_DIGEST_SIZE; + break; + + #endif + + default: + ret = BAD_FUNC_ARG; + break; + } + + return ret; +} + +int _InitHmac(Hmac* hmac, int type, void* heap) +{ + int ret = 0; + + switch (type) { + #ifndef NO_MD5 + case WC_MD5: + ret = wc_InitMd5(&hmac->hash.md5); + break; + #endif /* !NO_MD5 */ + + #ifndef NO_SHA + case WC_SHA: + ret = wc_InitSha(&hmac->hash.sha); + break; + #endif /* !NO_SHA */ + + #ifdef WOLFSSL_SHA224 + case WC_SHA224: + ret = wc_InitSha224(&hmac->hash.sha224); + break; + #endif /* WOLFSSL_SHA224 */ + + #ifndef NO_SHA256 + case WC_SHA256: + ret = wc_InitSha256(&hmac->hash.sha256); + break; + #endif /* !NO_SHA256 */ + + #ifdef WOLFSSL_SHA384 + case WC_SHA384: + ret = wc_InitSha384(&hmac->hash.sha384); + break; + #endif /* WOLFSSL_SHA384 */ + #ifdef WOLFSSL_SHA512 + case WC_SHA512: + ret = wc_InitSha512(&hmac->hash.sha512); + break; + #endif /* WOLFSSL_SHA512 */ + + #ifdef HAVE_BLAKE2 + case BLAKE2B_ID: + ret = wc_InitBlake2b(&hmac->hash.blake2b, BLAKE2B_256); + break; + #endif /* HAVE_BLAKE2 */ + + #ifdef WOLFSSL_SHA3 + #ifndef WOLFSSL_NOSHA3_224 + case WC_SHA3_224: + ret = wc_InitSha3_224(&hmac->hash.sha3, heap, INVALID_DEVID); + break; + #endif + #ifndef WOLFSSL_NOSHA3_256 + case WC_SHA3_256: + ret = wc_InitSha3_256(&hmac->hash.sha3, heap, INVALID_DEVID); + break; + #endif + #ifndef WOLFSSL_NOSHA3_384 + case WC_SHA3_384: + ret = wc_InitSha3_384(&hmac->hash.sha3, heap, INVALID_DEVID); + break; + #endif + #ifndef WOLFSSL_NOSHA3_512 + case WC_SHA3_512: + ret = wc_InitSha3_512(&hmac->hash.sha3, heap, INVALID_DEVID); + break; + #endif + #endif + + default: + ret = BAD_FUNC_ARG; + break; + } + + /* default to NULL heap hint or test value */ +#ifdef WOLFSSL_HEAP_TEST + hmac->heap = (void)WOLFSSL_HEAP_TEST; +#else + hmac->heap = heap; +#endif /* WOLFSSL_HEAP_TEST */ + + return ret; +} + + +int wc_HmacSetKey(Hmac* hmac, int type, const byte* key, word32 length) +{ + byte* ip; + byte* op; + word32 i, hmac_block_size = 0; + int ret = 0; + void* heap = NULL; + + if (hmac == NULL || (key == NULL && length != 0) || + !(type == WC_MD5 || type == WC_SHA || + type == WC_SHA224 || type == WC_SHA256 || + type == WC_SHA384 || type == WC_SHA512 || + type == WC_SHA3_224 || type == WC_SHA3_256 || + type == WC_SHA3_384 || type == WC_SHA3_512 || + type == BLAKE2B_ID)) { + return BAD_FUNC_ARG; + } + + /* if set key has already been run then make sure and free existing */ + if (hmac->macType != 0) { + wc_HmacFree(hmac); + } + + hmac->innerHashKeyed = 0; + hmac->macType = (byte)type; + + ret = _InitHmac(hmac, type, heap); + if (ret != 0) + return ret; + +#ifdef HAVE_FIPS + if (length < HMAC_FIPS_MIN_KEY) + return HMAC_MIN_KEYLEN_E; +#endif + +#ifdef WOLF_CRYPTO_CB + hmac->keyRaw = key; /* use buffer directly */ + hmac->keyLen = length; +#endif + + ip = (byte*)hmac->ipad; + op = (byte*)hmac->opad; + + switch (hmac->macType) { + #ifndef NO_MD5 + case WC_MD5: + hmac_block_size = WC_MD5_BLOCK_SIZE; + if (length <= WC_MD5_BLOCK_SIZE) { + if (key != NULL) { + XMEMCPY(ip, key, length); + } + } + else { + ret = wc_Md5Update(&hmac->hash.md5, key, length); + if (ret != 0) + break; + ret = wc_Md5Final(&hmac->hash.md5, ip); + if (ret != 0) + break; + length = WC_MD5_DIGEST_SIZE; + } + break; + #endif /* !NO_MD5 */ + + #ifndef NO_SHA + case WC_SHA: + hmac_block_size = WC_SHA_BLOCK_SIZE; + if (length <= WC_SHA_BLOCK_SIZE) { + if (key != NULL) { + XMEMCPY(ip, key, length); + } + } + else { + ret = wc_ShaUpdate(&hmac->hash.sha, key, length); + if (ret != 0) + break; + ret = wc_ShaFinal(&hmac->hash.sha, ip); + if (ret != 0) + break; + + length = WC_SHA_DIGEST_SIZE; + } + break; + #endif /* !NO_SHA */ + + #ifdef WOLFSSL_SHA224 + case WC_SHA224: + hmac_block_size = WC_SHA224_BLOCK_SIZE; + if (length <= WC_SHA224_BLOCK_SIZE) { + if (key != NULL) { + XMEMCPY(ip, key, length); + } + } + else { + ret = wc_Sha224Update(&hmac->hash.sha224, key, length); + if (ret != 0) + break; + ret = wc_Sha224Final(&hmac->hash.sha224, ip); + if (ret != 0) + break; + + length = WC_SHA224_DIGEST_SIZE; + } + break; + #endif /* WOLFSSL_SHA224 */ + #ifndef NO_SHA256 + case WC_SHA256: + hmac_block_size = WC_SHA256_BLOCK_SIZE; + if (length <= WC_SHA256_BLOCK_SIZE) { + if (key != NULL) { + XMEMCPY(ip, key, length); + } + } + else { + ret = wc_Sha256Update(&hmac->hash.sha256, key, length); + if (ret != 0) + break; + ret = wc_Sha256Final(&hmac->hash.sha256, ip); + if (ret != 0) + break; + + length = WC_SHA256_DIGEST_SIZE; + } + break; + #endif /* !NO_SHA256 */ + + #ifdef WOLFSSL_SHA384 + case WC_SHA384: + hmac_block_size = WC_SHA384_BLOCK_SIZE; + if (length <= WC_SHA384_BLOCK_SIZE) { + if (key != NULL) { + XMEMCPY(ip, key, length); + } + } + else { + ret = wc_Sha384Update(&hmac->hash.sha384, key, length); + if (ret != 0) + break; + ret = wc_Sha384Final(&hmac->hash.sha384, ip); + if (ret != 0) + break; + + length = WC_SHA384_DIGEST_SIZE; + } + break; + #endif /* WOLFSSL_SHA384 */ + #ifdef WOLFSSL_SHA512 + case WC_SHA512: + hmac_block_size = WC_SHA512_BLOCK_SIZE; + if (length <= WC_SHA512_BLOCK_SIZE) { + if (key != NULL) { + XMEMCPY(ip, key, length); + } + } + else { + ret = wc_Sha512Update(&hmac->hash.sha512, key, length); + if (ret != 0) + break; + ret = wc_Sha512Final(&hmac->hash.sha512, ip); + if (ret != 0) + break; + + length = WC_SHA512_DIGEST_SIZE; + } + break; + #endif /* WOLFSSL_SHA512 */ + + #ifdef HAVE_BLAKE2 + case BLAKE2B_ID: + hmac_block_size = BLAKE2B_BLOCKBYTES; + if (length <= BLAKE2B_BLOCKBYTES) { + if (key != NULL) { + XMEMCPY(ip, key, length); + } + } + else { + ret = wc_Blake2bUpdate(&hmac->hash.blake2b, key, length); + if (ret != 0) + break; + ret = wc_Blake2bFinal(&hmac->hash.blake2b, ip, BLAKE2B_256); + if (ret != 0) + break; + + length = BLAKE2B_256; + } + break; + #endif /* HAVE_BLAKE2 */ + + #ifdef WOLFSSL_SHA3 + #ifndef WOLFSSL_NOSHA3_224 + case WC_SHA3_224: + hmac_block_size = WC_SHA3_224_BLOCK_SIZE; + if (length <= WC_SHA3_224_BLOCK_SIZE) { + if (key != NULL) { + XMEMCPY(ip, key, length); + } + } + else { + ret = wc_Sha3_224_Update(&hmac->hash.sha3, key, length); + if (ret != 0) + break; + ret = wc_Sha3_224_Final(&hmac->hash.sha3, ip); + if (ret != 0) + break; + + length = WC_SHA3_224_DIGEST_SIZE; + } + break; + #endif + #ifndef WOLFSSL_NOSHA3_256 + case WC_SHA3_256: + hmac_block_size = WC_SHA3_256_BLOCK_SIZE; + if (length <= WC_SHA3_256_BLOCK_SIZE) { + if (key != NULL) { + XMEMCPY(ip, key, length); + } + } + else { + ret = wc_Sha3_256_Update(&hmac->hash.sha3, key, length); + if (ret != 0) + break; + ret = wc_Sha3_256_Final(&hmac->hash.sha3, ip); + if (ret != 0) + break; + + length = WC_SHA3_256_DIGEST_SIZE; + } + break; + #endif + #ifndef WOLFSSL_NOSHA3_384 + case WC_SHA3_384: + hmac_block_size = WC_SHA3_384_BLOCK_SIZE; + if (length <= WC_SHA3_384_BLOCK_SIZE) { + if (key != NULL) { + XMEMCPY(ip, key, length); + } + } + else { + ret = wc_Sha3_384_Update(&hmac->hash.sha3, key, length); + if (ret != 0) + break; + ret = wc_Sha3_384_Final(&hmac->hash.sha3, ip); + if (ret != 0) + break; + + length = WC_SHA3_384_DIGEST_SIZE; + } + break; + #endif + #ifndef WOLFSSL_NOSHA3_512 + case WC_SHA3_512: + hmac_block_size = WC_SHA3_512_BLOCK_SIZE; + if (length <= WC_SHA3_512_BLOCK_SIZE) { + if (key != NULL) { + XMEMCPY(ip, key, length); + } + } + else { + ret = wc_Sha3_512_Update(&hmac->hash.sha3, key, length); + if (ret != 0) + break; + ret = wc_Sha3_512_Final(&hmac->hash.sha3, ip); + if (ret != 0) + break; + + length = WC_SHA3_512_DIGEST_SIZE; + } + break; + #endif + #endif /* WOLFSSL_SHA3 */ + + default: + return BAD_FUNC_ARG; + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_HMAC) + if (hmac->asyncDev.marker == WOLFSSL_ASYNC_MARKER_HMAC) { + #if defined(HAVE_INTEL_QA) || defined(HAVE_CAVIUM) + #ifdef HAVE_INTEL_QA + if (IntelQaHmacGetType(hmac->macType, NULL) == 0) + #endif + { + if (length > hmac_block_size) + length = hmac_block_size; + /* update key length */ + hmac->keyLen = (word16)length; + + return ret; + } + /* no need to pad below */ + #endif + } +#endif + + if (ret == 0) { + if (length < hmac_block_size) + XMEMSET(ip + length, 0, hmac_block_size - length); + + for(i = 0; i < hmac_block_size; i++) { + op[i] = ip[i] ^ OPAD; + ip[i] ^= IPAD; + } + } + + return ret; +} + + +static int HmacKeyInnerHash(Hmac* hmac) +{ + int ret = 0; + + switch (hmac->macType) { + #ifndef NO_MD5 + case WC_MD5: + ret = wc_Md5Update(&hmac->hash.md5, (byte*)hmac->ipad, + WC_MD5_BLOCK_SIZE); + break; + #endif /* !NO_MD5 */ + + #ifndef NO_SHA + case WC_SHA: + ret = wc_ShaUpdate(&hmac->hash.sha, (byte*)hmac->ipad, + WC_SHA_BLOCK_SIZE); + break; + #endif /* !NO_SHA */ + + #ifdef WOLFSSL_SHA224 + case WC_SHA224: + ret = wc_Sha224Update(&hmac->hash.sha224, (byte*)hmac->ipad, + WC_SHA224_BLOCK_SIZE); + break; + #endif /* WOLFSSL_SHA224 */ + #ifndef NO_SHA256 + case WC_SHA256: + ret = wc_Sha256Update(&hmac->hash.sha256, (byte*)hmac->ipad, + WC_SHA256_BLOCK_SIZE); + break; + #endif /* !NO_SHA256 */ + + #ifdef WOLFSSL_SHA384 + case WC_SHA384: + ret = wc_Sha384Update(&hmac->hash.sha384, (byte*)hmac->ipad, + WC_SHA384_BLOCK_SIZE); + break; + #endif /* WOLFSSL_SHA384 */ + #ifdef WOLFSSL_SHA512 + case WC_SHA512: + ret = wc_Sha512Update(&hmac->hash.sha512, (byte*)hmac->ipad, + WC_SHA512_BLOCK_SIZE); + break; + #endif /* WOLFSSL_SHA512 */ + + #ifdef HAVE_BLAKE2 + case BLAKE2B_ID: + ret = wc_Blake2bUpdate(&hmac->hash.blake2b, (byte*)hmac->ipad, + BLAKE2B_BLOCKBYTES); + break; + #endif /* HAVE_BLAKE2 */ + + #ifdef WOLFSSL_SHA3 + #ifndef WOLFSSL_NOSHA3_224 + case WC_SHA3_224: + ret = wc_Sha3_224_Update(&hmac->hash.sha3, (byte*)hmac->ipad, + WC_SHA3_224_BLOCK_SIZE); + break; + #endif + #ifndef WOLFSSL_NOSHA3_256 + case WC_SHA3_256: + ret = wc_Sha3_256_Update(&hmac->hash.sha3, (byte*)hmac->ipad, + WC_SHA3_256_BLOCK_SIZE); + break; + #endif + #ifndef WOLFSSL_NOSHA3_384 + case WC_SHA3_384: + ret = wc_Sha3_384_Update(&hmac->hash.sha3, (byte*)hmac->ipad, + WC_SHA3_384_BLOCK_SIZE); + break; + #endif + #ifndef WOLFSSL_NOSHA3_512 + case WC_SHA3_512: + ret = wc_Sha3_512_Update(&hmac->hash.sha3, (byte*)hmac->ipad, + WC_SHA3_512_BLOCK_SIZE); + break; + #endif + #endif /* WOLFSSL_SHA3 */ + + default: + break; + } + + if (ret == 0) + hmac->innerHashKeyed = WC_HMAC_INNER_HASH_KEYED_SW; + + return ret; +} + + +int wc_HmacUpdate(Hmac* hmac, const byte* msg, word32 length) +{ + int ret = 0; + + if (hmac == NULL || (msg == NULL && length > 0)) { + return BAD_FUNC_ARG; + } + +#ifdef WOLF_CRYPTO_CB + if (hmac->devId != INVALID_DEVID) { + ret = wc_CryptoCb_Hmac(hmac, hmac->macType, msg, length, NULL); + if (ret != CRYPTOCB_UNAVAILABLE) + return ret; + /* fall-through when unavailable */ + ret = 0; /* reset error code */ + } +#endif +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_HMAC) + if (hmac->asyncDev.marker == WOLFSSL_ASYNC_MARKER_HMAC) { + #if defined(HAVE_CAVIUM) + return NitroxHmacUpdate(hmac, msg, length); + #elif defined(HAVE_INTEL_QA) + if (IntelQaHmacGetType(hmac->macType, NULL) == 0) { + return IntelQaHmac(&hmac->asyncDev, hmac->macType, + (byte*)hmac->ipad, hmac->keyLen, NULL, msg, length); + } + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + if (!hmac->innerHashKeyed) { + ret = HmacKeyInnerHash(hmac); + if (ret != 0) + return ret; + } + + switch (hmac->macType) { + #ifndef NO_MD5 + case WC_MD5: + ret = wc_Md5Update(&hmac->hash.md5, msg, length); + break; + #endif /* !NO_MD5 */ + + #ifndef NO_SHA + case WC_SHA: + ret = wc_ShaUpdate(&hmac->hash.sha, msg, length); + break; + #endif /* !NO_SHA */ + + #ifdef WOLFSSL_SHA224 + case WC_SHA224: + ret = wc_Sha224Update(&hmac->hash.sha224, msg, length); + break; + #endif /* WOLFSSL_SHA224 */ + + #ifndef NO_SHA256 + case WC_SHA256: + ret = wc_Sha256Update(&hmac->hash.sha256, msg, length); + break; + #endif /* !NO_SHA256 */ + + #ifdef WOLFSSL_SHA384 + case WC_SHA384: + ret = wc_Sha384Update(&hmac->hash.sha384, msg, length); + break; + #endif /* WOLFSSL_SHA384 */ + #ifdef WOLFSSL_SHA512 + case WC_SHA512: + ret = wc_Sha512Update(&hmac->hash.sha512, msg, length); + break; + #endif /* WOLFSSL_SHA512 */ + + #ifdef HAVE_BLAKE2 + case BLAKE2B_ID: + ret = wc_Blake2bUpdate(&hmac->hash.blake2b, msg, length); + break; + #endif /* HAVE_BLAKE2 */ + + #ifdef WOLFSSL_SHA3 + #ifndef WOLFSSL_NOSHA3_224 + case WC_SHA3_224: + ret = wc_Sha3_224_Update(&hmac->hash.sha3, msg, length); + break; + #endif + #ifndef WOLFSSL_NOSHA3_256 + case WC_SHA3_256: + ret = wc_Sha3_256_Update(&hmac->hash.sha3, msg, length); + break; + #endif + #ifndef WOLFSSL_NOSHA3_384 + case WC_SHA3_384: + ret = wc_Sha3_384_Update(&hmac->hash.sha3, msg, length); + break; + #endif + #ifndef WOLFSSL_NOSHA3_512 + case WC_SHA3_512: + ret = wc_Sha3_512_Update(&hmac->hash.sha3, msg, length); + break; + #endif + #endif /* WOLFSSL_SHA3 */ + + default: + break; + } + + return ret; +} + + +int wc_HmacFinal(Hmac* hmac, byte* hash) +{ + int ret; + + if (hmac == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef WOLF_CRYPTO_CB + if (hmac->devId != INVALID_DEVID) { + ret = wc_CryptoCb_Hmac(hmac, hmac->macType, NULL, 0, hash); + if (ret != CRYPTOCB_UNAVAILABLE) + return ret; + /* fall-through when unavailable */ + } +#endif +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_HMAC) + if (hmac->asyncDev.marker == WOLFSSL_ASYNC_MARKER_HMAC) { + int hashLen = wc_HmacSizeByType(hmac->macType); + if (hashLen <= 0) + return hashLen; + + #if defined(HAVE_CAVIUM) + return NitroxHmacFinal(hmac, hash, hashLen); + #elif defined(HAVE_INTEL_QA) + if (IntelQaHmacGetType(hmac->macType, NULL) == 0) { + return IntelQaHmac(&hmac->asyncDev, hmac->macType, + (byte*)hmac->ipad, hmac->keyLen, hash, NULL, hashLen); + } + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + if (!hmac->innerHashKeyed) { + ret = HmacKeyInnerHash(hmac); + if (ret != 0) + return ret; + } + + switch (hmac->macType) { + #ifndef NO_MD5 + case WC_MD5: + ret = wc_Md5Final(&hmac->hash.md5, (byte*)hmac->innerHash); + if (ret != 0) + break; + ret = wc_Md5Update(&hmac->hash.md5, (byte*)hmac->opad, + WC_MD5_BLOCK_SIZE); + if (ret != 0) + break; + ret = wc_Md5Update(&hmac->hash.md5, (byte*)hmac->innerHash, + WC_MD5_DIGEST_SIZE); + if (ret != 0) + break; + ret = wc_Md5Final(&hmac->hash.md5, hash); + break; + #endif /* !NO_MD5 */ + + #ifndef NO_SHA + case WC_SHA: + ret = wc_ShaFinal(&hmac->hash.sha, (byte*)hmac->innerHash); + if (ret != 0) + break; + ret = wc_ShaUpdate(&hmac->hash.sha, (byte*)hmac->opad, + WC_SHA_BLOCK_SIZE); + if (ret != 0) + break; + ret = wc_ShaUpdate(&hmac->hash.sha, (byte*)hmac->innerHash, + WC_SHA_DIGEST_SIZE); + if (ret != 0) + break; + ret = wc_ShaFinal(&hmac->hash.sha, hash); + break; + #endif /* !NO_SHA */ + + #ifdef WOLFSSL_SHA224 + case WC_SHA224: + ret = wc_Sha224Final(&hmac->hash.sha224, (byte*)hmac->innerHash); + if (ret != 0) + break; + ret = wc_Sha224Update(&hmac->hash.sha224, (byte*)hmac->opad, + WC_SHA224_BLOCK_SIZE); + if (ret != 0) + break; + ret = wc_Sha224Update(&hmac->hash.sha224, (byte*)hmac->innerHash, + WC_SHA224_DIGEST_SIZE); + if (ret != 0) + break; + ret = wc_Sha224Final(&hmac->hash.sha224, hash); + if (ret != 0) + break; + break; + #endif /* WOLFSSL_SHA224 */ + #ifndef NO_SHA256 + case WC_SHA256: + ret = wc_Sha256Final(&hmac->hash.sha256, (byte*)hmac->innerHash); + if (ret != 0) + break; + ret = wc_Sha256Update(&hmac->hash.sha256, (byte*)hmac->opad, + WC_SHA256_BLOCK_SIZE); + if (ret != 0) + break; + ret = wc_Sha256Update(&hmac->hash.sha256, (byte*)hmac->innerHash, + WC_SHA256_DIGEST_SIZE); + if (ret != 0) + break; + ret = wc_Sha256Final(&hmac->hash.sha256, hash); + break; + #endif /* !NO_SHA256 */ + + #ifdef WOLFSSL_SHA384 + case WC_SHA384: + ret = wc_Sha384Final(&hmac->hash.sha384, (byte*)hmac->innerHash); + if (ret != 0) + break; + ret = wc_Sha384Update(&hmac->hash.sha384, (byte*)hmac->opad, + WC_SHA384_BLOCK_SIZE); + if (ret != 0) + break; + ret = wc_Sha384Update(&hmac->hash.sha384, (byte*)hmac->innerHash, + WC_SHA384_DIGEST_SIZE); + if (ret != 0) + break; + ret = wc_Sha384Final(&hmac->hash.sha384, hash); + break; + #endif /* WOLFSSL_SHA384 */ + #ifdef WOLFSSL_SHA512 + case WC_SHA512: + ret = wc_Sha512Final(&hmac->hash.sha512, (byte*)hmac->innerHash); + if (ret != 0) + break; + ret = wc_Sha512Update(&hmac->hash.sha512, (byte*)hmac->opad, + WC_SHA512_BLOCK_SIZE); + if (ret != 0) + break; + ret = wc_Sha512Update(&hmac->hash.sha512, (byte*)hmac->innerHash, + WC_SHA512_DIGEST_SIZE); + if (ret != 0) + break; + ret = wc_Sha512Final(&hmac->hash.sha512, hash); + break; + #endif /* WOLFSSL_SHA512 */ + + #ifdef HAVE_BLAKE2 + case BLAKE2B_ID: + ret = wc_Blake2bFinal(&hmac->hash.blake2b, (byte*)hmac->innerHash, + BLAKE2B_256); + if (ret != 0) + break; + ret = wc_Blake2bUpdate(&hmac->hash.blake2b, (byte*)hmac->opad, + BLAKE2B_BLOCKBYTES); + if (ret != 0) + break; + ret = wc_Blake2bUpdate(&hmac->hash.blake2b, (byte*)hmac->innerHash, + BLAKE2B_256); + if (ret != 0) + break; + ret = wc_Blake2bFinal(&hmac->hash.blake2b, hash, BLAKE2B_256); + break; + #endif /* HAVE_BLAKE2 */ + + #ifdef WOLFSSL_SHA3 + #ifndef WOLFSSL_NOSHA3_224 + case WC_SHA3_224: + ret = wc_Sha3_224_Final(&hmac->hash.sha3, (byte*)hmac->innerHash); + if (ret != 0) + break; + ret = wc_Sha3_224_Update(&hmac->hash.sha3, (byte*)hmac->opad, + WC_SHA3_224_BLOCK_SIZE); + if (ret != 0) + break; + ret = wc_Sha3_224_Update(&hmac->hash.sha3, (byte*)hmac->innerHash, + WC_SHA3_224_DIGEST_SIZE); + if (ret != 0) + break; + ret = wc_Sha3_224_Final(&hmac->hash.sha3, hash); + break; + #endif + #ifndef WOLFSSL_NOSHA3_256 + case WC_SHA3_256: + ret = wc_Sha3_256_Final(&hmac->hash.sha3, (byte*)hmac->innerHash); + if (ret != 0) + break; + ret = wc_Sha3_256_Update(&hmac->hash.sha3, (byte*)hmac->opad, + WC_SHA3_256_BLOCK_SIZE); + if (ret != 0) + break; + ret = wc_Sha3_256_Update(&hmac->hash.sha3, (byte*)hmac->innerHash, + WC_SHA3_256_DIGEST_SIZE); + if (ret != 0) + break; + ret = wc_Sha3_256_Final(&hmac->hash.sha3, hash); + break; + #endif + #ifndef WOLFSSL_NOSHA3_384 + case WC_SHA3_384: + ret = wc_Sha3_384_Final(&hmac->hash.sha3, (byte*)hmac->innerHash); + if (ret != 0) + break; + ret = wc_Sha3_384_Update(&hmac->hash.sha3, (byte*)hmac->opad, + WC_SHA3_384_BLOCK_SIZE); + if (ret != 0) + break; + ret = wc_Sha3_384_Update(&hmac->hash.sha3, (byte*)hmac->innerHash, + WC_SHA3_384_DIGEST_SIZE); + if (ret != 0) + break; + ret = wc_Sha3_384_Final(&hmac->hash.sha3, hash); + break; + #endif + #ifndef WOLFSSL_NOSHA3_512 + case WC_SHA3_512: + ret = wc_Sha3_512_Final(&hmac->hash.sha3, (byte*)hmac->innerHash); + if (ret != 0) + break; + ret = wc_Sha3_512_Update(&hmac->hash.sha3, (byte*)hmac->opad, + WC_SHA3_512_BLOCK_SIZE); + if (ret != 0) + break; + ret = wc_Sha3_512_Update(&hmac->hash.sha3, (byte*)hmac->innerHash, + WC_SHA3_512_DIGEST_SIZE); + if (ret != 0) + break; + ret = wc_Sha3_512_Final(&hmac->hash.sha3, hash); + break; + #endif + #endif /* WOLFSSL_SHA3 */ + + default: + ret = BAD_FUNC_ARG; + break; + } + + if (ret == 0) { + hmac->innerHashKeyed = 0; + } + + return ret; +} + + +/* Initialize Hmac for use with async device */ +int wc_HmacInit(Hmac* hmac, void* heap, int devId) +{ + int ret = 0; + + if (hmac == NULL) + return BAD_FUNC_ARG; + + XMEMSET(hmac, 0, sizeof(Hmac)); + hmac->heap = heap; +#ifdef WOLF_CRYPTO_CB + hmac->devId = devId; + hmac->devCtx = NULL; +#endif + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_HMAC) + ret = wolfAsync_DevCtxInit(&hmac->asyncDev, WOLFSSL_ASYNC_MARKER_HMAC, + hmac->heap, devId); +#else + (void)devId; +#endif /* WOLFSSL_ASYNC_CRYPT */ + + return ret; +} + +#ifdef HAVE_PKCS11 +int wc_HmacInit_Id(Hmac* hmac, unsigned char* id, int len, void* heap, + int devId) +{ + int ret = 0; + + if (hmac == NULL) + ret = BAD_FUNC_ARG; + if (ret == 0 && (len < 0 || len > HMAC_MAX_ID_LEN)) + ret = BUFFER_E; + + if (ret == 0) + ret = wc_HmacInit(hmac, heap, devId); + if (ret == 0) { + XMEMCPY(hmac->id, id, len); + hmac->idLen = len; + } + + return ret; +} +#endif + +/* Free Hmac from use with async device */ +void wc_HmacFree(Hmac* hmac) +{ + if (hmac == NULL) + return; + +#ifdef WOLF_CRYPTO_CB + /* handle cleanup case where final is not called */ + if (hmac->devId != INVALID_DEVID && hmac->devCtx != NULL) { + int ret; + byte finalHash[WC_HMAC_BLOCK_SIZE]; + ret = wc_CryptoCb_Hmac(hmac, hmac->macType, NULL, 0, finalHash); + (void)ret; /* must ignore return code here */ + (void)finalHash; + } +#endif + + switch (hmac->macType) { + #ifndef NO_MD5 + case WC_MD5: + wc_Md5Free(&hmac->hash.md5); + break; + #endif /* !NO_MD5 */ + + #ifndef NO_SHA + case WC_SHA: + wc_ShaFree(&hmac->hash.sha); + break; + #endif /* !NO_SHA */ + + #ifdef WOLFSSL_SHA224 + case WC_SHA224: + wc_Sha224Free(&hmac->hash.sha224); + break; + #endif /* WOLFSSL_SHA224 */ + #ifndef NO_SHA256 + case WC_SHA256: + wc_Sha256Free(&hmac->hash.sha256); + break; + #endif /* !NO_SHA256 */ + + #ifdef WOLFSSL_SHA384 + case WC_SHA384: + wc_Sha384Free(&hmac->hash.sha384); + break; + #endif /* WOLFSSL_SHA384 */ + #ifdef WOLFSSL_SHA512 + case WC_SHA512: + wc_Sha512Free(&hmac->hash.sha512); + break; + #endif /* WOLFSSL_SHA512 */ + + #ifdef HAVE_BLAKE2 + case BLAKE2B_ID: + break; + #endif /* HAVE_BLAKE2 */ + + #ifdef WOLFSSL_SHA3 + #ifndef WOLFSSL_NOSHA3_224 + case WC_SHA3_224: + wc_Sha3_224_Free(&hmac->hash.sha3); + break; + #endif + #ifndef WOLFSSL_NOSHA3_256 + case WC_SHA3_256: + wc_Sha3_256_Free(&hmac->hash.sha3); + break; + #endif + #ifndef WOLFSSL_NOSHA3_384 + case WC_SHA3_384: + wc_Sha3_384_Free(&hmac->hash.sha3); + break; + #endif + #ifndef WOLFSSL_NOSHA3_512 + case WC_SHA3_512: + wc_Sha3_512_Free(&hmac->hash.sha3); + break; + #endif + #endif /* WOLFSSL_SHA3 */ + + default: + break; + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_HMAC) + wolfAsync_DevCtxFree(&hmac->asyncDev, WOLFSSL_ASYNC_MARKER_HMAC); +#endif /* WOLFSSL_ASYNC_CRYPT */ + + switch (hmac->macType) { + #ifndef NO_MD5 + case WC_MD5: + wc_Md5Free(&hmac->hash.md5); + break; + #endif /* !NO_MD5 */ + + #ifndef NO_SHA + case WC_SHA: + wc_ShaFree(&hmac->hash.sha); + break; + #endif /* !NO_SHA */ + + #ifdef WOLFSSL_SHA224 + case WC_SHA224: + wc_Sha224Free(&hmac->hash.sha224); + break; + #endif /* WOLFSSL_SHA224 */ + #ifndef NO_SHA256 + case WC_SHA256: + wc_Sha256Free(&hmac->hash.sha256); + break; + #endif /* !NO_SHA256 */ + + #ifdef WOLFSSL_SHA512 + #ifdef WOLFSSL_SHA384 + case WC_SHA384: + wc_Sha384Free(&hmac->hash.sha384); + break; + #endif /* WOLFSSL_SHA384 */ + case WC_SHA512: + wc_Sha512Free(&hmac->hash.sha512); + break; + #endif /* WOLFSSL_SHA512 */ + } +} + +int wolfSSL_GetHmacMaxSize(void) +{ + return WC_MAX_DIGEST_SIZE; +} + +#ifdef HAVE_HKDF + /* HMAC-KDF-Extract. + * RFC 5869 - HMAC-based Extract-and-Expand Key Derivation Function (HKDF). + * + * type The hash algorithm type. + * salt The optional salt value. + * saltSz The size of the salt. + * inKey The input keying material. + * inKeySz The size of the input keying material. + * out The pseudorandom key with the length that of the hash. + * returns 0 on success, otherwise failure. + */ + int wc_HKDF_Extract(int type, const byte* salt, word32 saltSz, + const byte* inKey, word32 inKeySz, byte* out) + { + byte tmp[WC_MAX_DIGEST_SIZE]; /* localSalt helper */ + Hmac myHmac; + int ret; + const byte* localSalt; /* either points to user input or tmp */ + int hashSz; + + ret = wc_HmacSizeByType(type); + if (ret < 0) + return ret; + + hashSz = ret; + localSalt = salt; + if (localSalt == NULL) { + XMEMSET(tmp, 0, hashSz); + localSalt = tmp; + saltSz = hashSz; + } + + ret = wc_HmacInit(&myHmac, NULL, INVALID_DEVID); + if (ret == 0) { + ret = wc_HmacSetKey(&myHmac, type, localSalt, saltSz); + if (ret == 0) + ret = wc_HmacUpdate(&myHmac, inKey, inKeySz); + if (ret == 0) + ret = wc_HmacFinal(&myHmac, out); + wc_HmacFree(&myHmac); + } + + return ret; + } + + /* HMAC-KDF-Expand. + * RFC 5869 - HMAC-based Extract-and-Expand Key Derivation Function (HKDF). + * + * type The hash algorithm type. + * inKey The input key. + * inKeySz The size of the input key. + * info The application specific information. + * infoSz The size of the application specific information. + * out The output keying material. + * returns 0 on success, otherwise failure. + */ + int wc_HKDF_Expand(int type, const byte* inKey, word32 inKeySz, + const byte* info, word32 infoSz, byte* out, word32 outSz) + { + byte tmp[WC_MAX_DIGEST_SIZE]; + Hmac myHmac; + int ret = 0; + word32 outIdx = 0; + word32 hashSz = wc_HmacSizeByType(type); + byte n = 0x1; + + ret = wc_HmacInit(&myHmac, NULL, INVALID_DEVID); + if (ret != 0) + return ret; + + while (outIdx < outSz) { + int tmpSz = (n == 1) ? 0 : hashSz; + word32 left = outSz - outIdx; + + ret = wc_HmacSetKey(&myHmac, type, inKey, inKeySz); + if (ret != 0) + break; + ret = wc_HmacUpdate(&myHmac, tmp, tmpSz); + if (ret != 0) + break; + ret = wc_HmacUpdate(&myHmac, info, infoSz); + if (ret != 0) + break; + ret = wc_HmacUpdate(&myHmac, &n, 1); + if (ret != 0) + break; + ret = wc_HmacFinal(&myHmac, tmp); + if (ret != 0) + break; + + left = min(left, hashSz); + XMEMCPY(out+outIdx, tmp, left); + + outIdx += hashSz; + n++; + } + + wc_HmacFree(&myHmac); + + return ret; + } + + /* HMAC-KDF. + * RFC 5869 - HMAC-based Extract-and-Expand Key Derivation Function (HKDF). + * + * type The hash algorithm type. + * inKey The input keying material. + * inKeySz The size of the input keying material. + * salt The optional salt value. + * saltSz The size of the salt. + * info The application specific information. + * infoSz The size of the application specific information. + * out The output keying material. + * returns 0 on success, otherwise failure. + */ + int wc_HKDF(int type, const byte* inKey, word32 inKeySz, + const byte* salt, word32 saltSz, + const byte* info, word32 infoSz, + byte* out, word32 outSz) + { + byte prk[WC_MAX_DIGEST_SIZE]; + int hashSz = wc_HmacSizeByType(type); + int ret; + + if (hashSz < 0) + return BAD_FUNC_ARG; + + ret = wc_HKDF_Extract(type, salt, saltSz, inKey, inKeySz, prk); + if (ret != 0) + return ret; + + return wc_HKDF_Expand(type, prk, hashSz, info, infoSz, out, outSz); + } + +#endif /* HAVE_HKDF */ + +#endif /* HAVE_FIPS */ +#endif /* NO_HMAC */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/idea.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/idea.c new file mode 100755 index 0000000..c5a4276 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/idea.c @@ -0,0 +1,303 @@ +/* idea.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifdef HAVE_IDEA + +#include + +#include +#include + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +/* multiplication of x and y modulo 2^16+1 + * IDEA specify a special case when an entry value is 0 ( x or y) + * then it must be replaced by 2^16 + */ +static WC_INLINE word16 idea_mult(word16 x, word16 y) +{ + long mul, res; + + mul = (long)x * (long)y; + if (mul) { + res = (mul & IDEA_MASK) - ((word32)mul >> 16); + if (res <= 0) + res += IDEA_MODULO; + + return (word16) (res & IDEA_MASK); + } + + if (!x) + return ((IDEA_MODULO - y) & IDEA_MASK); + + /* !y */ + return ((IDEA_MODULO - x) & IDEA_MASK); +} + +/* compute 1/a modulo 2^16+1 using Extended euclidean algorithm + * adapted from fp_invmod */ +static WC_INLINE word16 idea_invmod(word16 x) +{ + int u, v, b, d; + + if (x <= 1) + return x; + + u = IDEA_MODULO; + v = x; + d = 1; + b = 0; + + do { + while (!(u & 1)) { + u >>= 1; + if (b & 1) + b -= IDEA_MODULO; + b >>= 1; + } + + while (!(v & 1)) { + v >>= 1; + if (d & 1) { + d -= IDEA_MODULO; + } + d >>= 1; + } + + if (u >= v) { + u -= v; + b -= d; + } else { + v -= u; + d -= b; + } + } while (u != 0); + + /* d is now the inverse, put positive value if required */ + while (d < 0) + d += IDEA_MODULO; + + /* d must be < IDEA_MODULO */ + while (d >= (int)IDEA_MODULO) + d -= IDEA_MODULO; + + return (word16)(d & IDEA_MASK); +} + +/* generate the 52 16-bits key sub-blocks from the 128 key */ +int wc_IdeaSetKey(Idea *idea, const byte* key, word16 keySz, + const byte *iv, int dir) +{ + word16 idx = 0; + word32 t; + short i; + + if (idea == NULL || key == NULL || keySz != IDEA_KEY_SIZE || + (dir != IDEA_ENCRYPTION && dir != IDEA_DECRYPTION)) + return BAD_FUNC_ARG; + + /* initial key schedule for 0 -> 7 */ + for (i = 0; i < IDEA_ROUNDS; i++) { + idea->skey[i] = (word16)key[idx++] << 8; + idea->skey[i] |= (word16)key[idx++]; + } + + /* shift phase key schedule for 8 -> 51 */ + for (i = IDEA_ROUNDS; i < IDEA_SK_NUM; i++) { + t = (word32)idea->skey[((i+1) & 7) ? i-7 : i-15] << 9; + t |= (word32)idea->skey[((i+2) & 7) < 2 ? i-14 : i-6] >> 7; + idea->skey[i] = (word16)(t & IDEA_MASK); + } + + /* compute decryption key from encryption key */ + if (dir == IDEA_DECRYPTION) { + word16 enckey[IDEA_SK_NUM]; + + /* put encryption key in tmp buffer */ + XMEMCPY(enckey, idea->skey, sizeof(idea->skey)); + + idx = 0; + + idea->skey[6*IDEA_ROUNDS] = idea_invmod(enckey[idx++]); + idea->skey[6*IDEA_ROUNDS+1] = (IDEA_2EXP16 - enckey[idx++]) & IDEA_MASK; + idea->skey[6*IDEA_ROUNDS+2] = (IDEA_2EXP16 - enckey[idx++]) & IDEA_MASK; + idea->skey[6*IDEA_ROUNDS+3] = idea_invmod(enckey[idx++]); + + for (i = 6*(IDEA_ROUNDS-1); i >= 0; i -= 6) { + idea->skey[i+4] = enckey[idx++]; + idea->skey[i+5] = enckey[idx++]; + + idea->skey[i] = idea_invmod(enckey[idx++]); + if (i) { + idea->skey[i+2] = (IDEA_2EXP16 - enckey[idx++]) & IDEA_MASK; + idea->skey[i+1] = (IDEA_2EXP16 - enckey[idx++]) & IDEA_MASK; + } + else { + idea->skey[1] = (IDEA_2EXP16 - enckey[idx++]) & IDEA_MASK; + idea->skey[2] = (IDEA_2EXP16 - enckey[idx++]) & IDEA_MASK; + } + + idea->skey[i+3] = idea_invmod(enckey[idx++]); + } + + /* erase temporary buffer */ + ForceZero(enckey, sizeof(enckey)); + } + + /* set the iv */ + return wc_IdeaSetIV(idea, iv); +} + +/* set the IV in the Idea key structure */ +int wc_IdeaSetIV(Idea *idea, const byte* iv) +{ + if (idea == NULL) + return BAD_FUNC_ARG; + + if (iv != NULL) + XMEMCPY(idea->reg, iv, IDEA_BLOCK_SIZE); + else + XMEMSET(idea->reg, 0, IDEA_BLOCK_SIZE); + + return 0; +} + +/* encryption/decryption for a block (64 bits) + */ +int wc_IdeaCipher(Idea *idea, byte* out, const byte* in) +{ + word32 t1, t2; + word16 i, skey_idx = 0, idx = 0; + word16 x[4]; + + if (idea == NULL || out == NULL || in == NULL) { + return BAD_FUNC_ARG; + } + + /* put input byte block in word16 */ + for (i = 0; i < IDEA_BLOCK_SIZE/2; i++) { + x[i] = (word16)in[idx++] << 8; + x[i] |= (word16)in[idx++]; + } + + for (i = 0; i < IDEA_ROUNDS; i++) { + x[0] = idea_mult(x[0], idea->skey[skey_idx++]); + x[1] = ((word32)x[1] + (word32)idea->skey[skey_idx++]) & IDEA_MASK; + x[2] = ((word32)x[2] + (word32)idea->skey[skey_idx++]) & IDEA_MASK; + x[3] = idea_mult(x[3], idea->skey[skey_idx++]); + + t2 = x[0] ^ x[2]; + t2 = idea_mult((word16)t2, idea->skey[skey_idx++]); + t1 = (t2 + (x[1] ^ x[3])) & IDEA_MASK; + t1 = idea_mult((word16)t1, idea->skey[skey_idx++]); + t2 = (t1 + t2) & IDEA_MASK; + + x[0] ^= t1; + x[3] ^= t2; + + t2 ^= x[1]; + x[1] = x[2] ^ (word16)t1; + x[2] = (word16)t2; + } + + x[0] = idea_mult(x[0], idea->skey[skey_idx++]); + out[0] = (x[0] >> 8) & 0xFF; + out[1] = x[0] & 0xFF; + + x[2] = ((word32)x[2] + (word32)idea->skey[skey_idx++]) & IDEA_MASK; + out[2] = (x[2] >> 8) & 0xFF; + out[3] = x[2] & 0xFF; + + x[1] = ((word32)x[1] + (word32)idea->skey[skey_idx++]) & IDEA_MASK; + out[4] = (x[1] >> 8) & 0xFF; + out[5] = x[1] & 0xFF; + + x[3] = idea_mult(x[3], idea->skey[skey_idx++]); + out[6] = (x[3] >> 8) & 0xFF; + out[7] = x[3] & 0xFF; + + return 0; +} + +int wc_IdeaCbcEncrypt(Idea *idea, byte* out, const byte* in, word32 len) +{ + int blocks; + int ret; + + if (idea == NULL || out == NULL || in == NULL) + return BAD_FUNC_ARG; + + blocks = len / IDEA_BLOCK_SIZE; + while (blocks--) { + xorbuf((byte*)idea->reg, in, IDEA_BLOCK_SIZE); + ret = wc_IdeaCipher(idea, (byte*)idea->reg, (byte*)idea->reg); + if (ret != 0) { + return ret; + } + + XMEMCPY(out, idea->reg, IDEA_BLOCK_SIZE); + + out += IDEA_BLOCK_SIZE; + in += IDEA_BLOCK_SIZE; + } + + return 0; +} + +int wc_IdeaCbcDecrypt(Idea *idea, byte* out, const byte* in, word32 len) +{ + int blocks; + int ret; + + if (idea == NULL || out == NULL || in == NULL) + return BAD_FUNC_ARG; + + blocks = len / IDEA_BLOCK_SIZE; + while (blocks--) { + XMEMCPY((byte*)idea->tmp, in, IDEA_BLOCK_SIZE); + ret = wc_IdeaCipher(idea, out, (byte*)idea->tmp); + if (ret != 0) { + return ret; + } + + xorbuf(out, (byte*)idea->reg, IDEA_BLOCK_SIZE); + XMEMCPY(idea->reg, idea->tmp, IDEA_BLOCK_SIZE); + + out += IDEA_BLOCK_SIZE; + in += IDEA_BLOCK_SIZE; + } + + return 0; +} + +#endif /* HAVE_IDEA */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/include.am b/beken_os/beken378/func/wolfssl/wolfcrypt/src/include.am new file mode 100755 index 0000000..5fa0b01 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/include.am @@ -0,0 +1,114 @@ +# vim:ft=automake +# All paths should be given relative to the root + +EXTRA_DIST += src/bio.c +EXTRA_DIST += wolfcrypt/src/misc.c +EXTRA_DIST += wolfcrypt/src/evp.c +EXTRA_DIST += wolfcrypt/src/asm.c +EXTRA_DIST += wolfcrypt/src/aes_asm.asm + +EXTRA_DIST += \ + wolfcrypt/src/ecc_fp.c \ + wolfcrypt/src/fp_mont_small.i \ + wolfcrypt/src/fp_mul_comba_12.i \ + wolfcrypt/src/fp_mul_comba_17.i \ + wolfcrypt/src/fp_mul_comba_20.i \ + wolfcrypt/src/fp_mul_comba_24.i \ + wolfcrypt/src/fp_mul_comba_28.i \ + wolfcrypt/src/fp_mul_comba_32.i \ + wolfcrypt/src/fp_mul_comba_3.i \ + wolfcrypt/src/fp_mul_comba_48.i \ + wolfcrypt/src/fp_mul_comba_4.i \ + wolfcrypt/src/fp_mul_comba_64.i \ + wolfcrypt/src/fp_mul_comba_6.i \ + wolfcrypt/src/fp_mul_comba_7.i \ + wolfcrypt/src/fp_mul_comba_8.i \ + wolfcrypt/src/fp_mul_comba_9.i \ + wolfcrypt/src/fp_mul_comba_small_set.i \ + wolfcrypt/src/fp_sqr_comba_12.i \ + wolfcrypt/src/fp_sqr_comba_17.i \ + wolfcrypt/src/fp_sqr_comba_20.i \ + wolfcrypt/src/fp_sqr_comba_24.i \ + wolfcrypt/src/fp_sqr_comba_28.i \ + wolfcrypt/src/fp_sqr_comba_32.i \ + wolfcrypt/src/fp_sqr_comba_3.i \ + wolfcrypt/src/fp_sqr_comba_48.i \ + wolfcrypt/src/fp_sqr_comba_4.i \ + wolfcrypt/src/fp_sqr_comba_64.i \ + wolfcrypt/src/fp_sqr_comba_6.i \ + wolfcrypt/src/fp_sqr_comba_7.i \ + wolfcrypt/src/fp_sqr_comba_8.i \ + wolfcrypt/src/fp_sqr_comba_9.i \ + wolfcrypt/src/fp_sqr_comba_small_set.i \ + wolfcrypt/src/fe_x25519_128.i + +EXTRA_DIST += wolfcrypt/src/port/ti/ti-aes.c \ + wolfcrypt/src/port/ti/ti-des3.c \ + wolfcrypt/src/port/ti/ti-hash.c \ + wolfcrypt/src/port/ti/ti-ccm.c \ + wolfcrypt/src/port/pic32/pic32mz-crypt.c \ + wolfcrypt/src/port/nrf51.c \ + wolfcrypt/src/port/arm/armv8-aes.c \ + wolfcrypt/src/port/arm/armv8-sha256.c \ + wolfcrypt/src/port/arm/armv8-chacha.c \ + wolfcrypt/src/port/arm/armv8-curve25519.c \ + wolfcrypt/src/port/arm/armv8-32-curve25519.c \ + wolfcrypt/src/port/arm/armv8-sha512-asm.c \ + wolfcrypt/src/port/arm/armv8-32-sha512-asm.c \ + wolfcrypt/src/port/nxp/ksdk_port.c \ + wolfcrypt/src/port/atmel/README.md \ + wolfcrypt/src/port/xilinx/xil-sha3.c \ + wolfcrypt/src/port/xilinx/xil-aesgcm.c \ + wolfcrypt/src/port/caam/caam_aes.c \ + wolfcrypt/src/port/caam/caam_driver.c \ + wolfcrypt/src/port/caam/caam_init.c \ + wolfcrypt/src/port/caam/caam_sha.c \ + wolfcrypt/src/port/caam/caam_doc.pdf \ + wolfcrypt/src/port/st/stm32.c \ + wolfcrypt/src/port/st/stsafe.c \ + wolfcrypt/src/port/st/README.md \ + wolfcrypt/src/port/af_alg/afalg_aes.c \ + wolfcrypt/src/port/af_alg/afalg_hash.c \ + wolfcrypt/src/port/devcrypto/devcrypto_hash.c \ + wolfcrypt/src/port/devcrypto/wc_devcrypto.c \ + wolfcrypt/src/port/devcrypto/README.md \ + wolfcrypt/src/port/mynewt/mynewt_port.c \ + wolfcrypt/src/port/Espressif/esp32_aes.c \ + wolfcrypt/src/port/Espressif/esp32_sha.c \ + wolfcrypt/src/port/Espressif/esp32_util.c \ + wolfcrypt/src/port/Espressif/esp32_mp.c \ + wolfcrypt/src/port/Espressif/README.md \ + wolfcrypt/src/port/arm/cryptoCell.c \ + wolfcrypt/src/port/arm/cryptoCellHash.c + + +if BUILD_CRYPTOCB +src_libwolfssl_la_SOURCES += wolfcrypt/src/cryptocb.c +endif + +if BUILD_PKCS11 +src_libwolfssl_la_SOURCES += wolfcrypt/src/wc_pkcs11.c +endif + +if BUILD_DEVCRYPTO +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/devcrypto/devcrypto_hash.c +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/devcrypto/devcrypto_aes.c +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/devcrypto/wc_devcrypto.c +endif + +if BUILD_CAVIUM +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/cavium/cavium_nitrox.c + +EXTRA_DIST += wolfcrypt/src/port/cavium/README.md +endif + +if BUILD_INTEL_QA +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/intel/quickassist.c +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/intel/quickassist_mem.c + +EXTRA_DIST += wolfcrypt/src/port/intel/README.md +endif + +if BUILD_CRYPTOAUTHLIB +src_libwolfssl_la_SOURCES += wolfcrypt/src/port/atmel/atmel.c +endif diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/integer.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/integer.c new file mode 100755 index 0000000..ca66270 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/integer.c @@ -0,0 +1,5110 @@ +/* integer.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +/* + * Based on public domain LibTomMath 0.38 by Tom St Denis, tomstdenis@iahu.ca, + * http://math.libtomcrypt.com + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +/* in case user set USE_FAST_MATH there */ +#include + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#ifndef NO_BIG_INT + +#ifndef USE_FAST_MATH + +#ifndef WOLFSSL_SP_MATH + +#include + +#if defined(FREESCALE_LTC_TFM) + #include +#endif +#ifdef WOLFSSL_DEBUG_MATH + #include +#endif + +#ifndef NO_WOLFSSL_SMALL_STACK + #ifndef WOLFSSL_SMALL_STACK + #define WOLFSSL_SMALL_STACK + #endif +#endif + +#ifdef SHOW_GEN + #if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) + #if MQX_USE_IO_OLD + #include + #else + #include + #endif + #else + #include + #endif +#endif + +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) +#ifdef __cplusplus + extern "C" { +#endif +WOLFSSL_LOCAL int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, + mp_int* res); +WOLFSSL_LOCAL int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, + mp_int* res); +WOLFSSL_LOCAL int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, + mp_int* res); +WOLFSSL_LOCAL int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, + mp_int* res); +#ifdef __cplusplus + } /* extern "C" */ +#endif +#endif + +/* reverse an array, used for radix code */ +static void +bn_reverse (unsigned char *s, int len) +{ + int ix, iy; + unsigned char t; + + ix = 0; + iy = len - 1; + while (ix < iy) { + t = s[ix]; + s[ix] = s[iy]; + s[iy] = t; + ++ix; + --iy; + } +} + +/* math settings check */ +word32 CheckRunTimeSettings(void) +{ + return CTC_SETTINGS; +} + + +/* handle up to 6 inits */ +int mp_init_multi(mp_int* a, mp_int* b, mp_int* c, mp_int* d, mp_int* e, + mp_int* f) +{ + int res = MP_OKAY; + + if (a) XMEMSET(a, 0, sizeof(mp_int)); + if (b) XMEMSET(b, 0, sizeof(mp_int)); + if (c) XMEMSET(c, 0, sizeof(mp_int)); + if (d) XMEMSET(d, 0, sizeof(mp_int)); + if (e) XMEMSET(e, 0, sizeof(mp_int)); + if (f) XMEMSET(f, 0, sizeof(mp_int)); + + if (a && ((res = mp_init(a)) != MP_OKAY)) + return res; + + if (b && ((res = mp_init(b)) != MP_OKAY)) { + mp_clear(a); + return res; + } + + if (c && ((res = mp_init(c)) != MP_OKAY)) { + mp_clear(a); mp_clear(b); + return res; + } + + if (d && ((res = mp_init(d)) != MP_OKAY)) { + mp_clear(a); mp_clear(b); mp_clear(c); + return res; + } + + if (e && ((res = mp_init(e)) != MP_OKAY)) { + mp_clear(a); mp_clear(b); mp_clear(c); mp_clear(d); + return res; + } + + if (f && ((res = mp_init(f)) != MP_OKAY)) { + mp_clear(a); mp_clear(b); mp_clear(c); mp_clear(d); mp_clear(e); + return res; + } + + return res; +} + + +/* init a new mp_int */ +int mp_init (mp_int * a) +{ + /* Safeguard against passing in a null pointer */ + if (a == NULL) + return MP_VAL; + + /* defer allocation until mp_grow */ + a->dp = NULL; + + /* set the used to zero, allocated digits to the default precision + * and sign to positive */ + a->used = 0; + a->alloc = 0; + a->sign = MP_ZPOS; +#ifdef HAVE_WOLF_BIGINT + wc_bigint_init(&a->raw); +#endif + + return MP_OKAY; +} + + +/* clear one (frees) */ +void mp_clear (mp_int * a) +{ + int i; + + if (a == NULL) + return; + + /* only do anything if a hasn't been freed previously */ + if (a->dp != NULL) { + /* first zero the digits */ + for (i = 0; i < a->used; i++) { + a->dp[i] = 0; + } + + /* free ram */ + mp_free(a); + + /* reset members to make debugging easier */ + a->alloc = a->used = 0; + a->sign = MP_ZPOS; + } +} + +void mp_free (mp_int * a) +{ + /* only do anything if a hasn't been freed previously */ + if (a->dp != NULL) { + /* free ram */ + XFREE(a->dp, 0, DYNAMIC_TYPE_BIGINT); + a->dp = NULL; + } + +#ifdef HAVE_WOLF_BIGINT + wc_bigint_free(&a->raw); +#endif +} + +void mp_forcezero(mp_int * a) +{ + if (a == NULL) + return; + + /* only do anything if a hasn't been freed previously */ + if (a->dp != NULL) { + /* force zero the used digits */ + ForceZero(a->dp, a->used * sizeof(mp_digit)); +#ifdef HAVE_WOLF_BIGINT + wc_bigint_zero(&a->raw); +#endif + /* free ram */ + mp_free(a); + + /* reset members to make debugging easier */ + a->alloc = a->used = 0; + a->sign = MP_ZPOS; + } + + a->sign = MP_ZPOS; + a->used = 0; +} + + +/* get the size for an unsigned equivalent */ +int mp_unsigned_bin_size (mp_int * a) +{ + int size = mp_count_bits (a); + return (size / 8 + ((size & 7) != 0 ? 1 : 0)); +} + + +/* returns the number of bits in an int */ +int mp_count_bits (mp_int * a) +{ + int r; + mp_digit q; + + /* shortcut */ + if (a->used == 0) { + return 0; + } + + /* get number of digits and add that */ + r = (a->used - 1) * DIGIT_BIT; + + /* take the last digit and count the bits in it */ + q = a->dp[a->used - 1]; + while (q > ((mp_digit) 0)) { + ++r; + q >>= ((mp_digit) 1); + } + return r; +} + + +int mp_leading_bit (mp_int * a) +{ + int bit = 0; + mp_int t; + + if (mp_init_copy(&t, a) != MP_OKAY) + return 0; + + while (mp_iszero(&t) == MP_NO) { +#ifndef MP_8BIT + bit = (t.dp[0] & 0x80) != 0; +#else + bit = (t.dp[0] | ((t.dp[1] & 0x01) << 7)) & 0x80 != 0; +#endif + if (mp_div_2d (&t, 8, &t, NULL) != MP_OKAY) + break; + } + mp_clear(&t); + return bit; +} + +int mp_to_unsigned_bin_at_pos(int x, mp_int *t, unsigned char *b) +{ + int res = 0; + while (mp_iszero(t) == MP_NO) { +#ifndef MP_8BIT + b[x++] = (unsigned char) (t->dp[0] & 255); +#else + b[x++] = (unsigned char) (t->dp[0] | ((t->dp[1] & 0x01) << 7)); +#endif + if ((res = mp_div_2d (t, 8, t, NULL)) != MP_OKAY) { + return res; + } + res = x; + } + return res; +} + +/* store in unsigned [big endian] format */ +int mp_to_unsigned_bin (mp_int * a, unsigned char *b) +{ + int x, res; + mp_int t; + + if ((res = mp_init_copy (&t, a)) != MP_OKAY) { + return res; + } + + x = mp_to_unsigned_bin_at_pos(0, &t, b); + if (x < 0) { + mp_clear(&t); + return x; + } + + bn_reverse (b, x); + mp_clear (&t); + return res; +} + +int mp_to_unsigned_bin_len(mp_int * a, unsigned char *b, int c) +{ + int i, len; + + len = mp_unsigned_bin_size(a); + + /* pad front w/ zeros to match length */ + for (i = 0; i < c - len; i++) + b[i] = 0x00; + return mp_to_unsigned_bin(a, b + i); +} + +/* creates "a" then copies b into it */ +int mp_init_copy (mp_int * a, mp_int * b) +{ + int res; + + if ((res = mp_init_size (a, b->used)) != MP_OKAY) { + return res; + } + + if((res = mp_copy (b, a)) != MP_OKAY) { + mp_clear(a); + } + + return res; +} + + +/* copy, b = a */ +int mp_copy (mp_int * a, mp_int * b) +{ + int res, n; + + /* Safeguard against passing in a null pointer */ + if (a == NULL || b == NULL) + return MP_VAL; + + /* if dst == src do nothing */ + if (a == b) { + return MP_OKAY; + } + + /* grow dest */ + if (b->alloc < a->used || b->alloc == 0) { + if ((res = mp_grow (b, a->used)) != MP_OKAY) { + return res; + } + } + + /* zero b and copy the parameters over */ + { + mp_digit *tmpa, *tmpb; + + /* pointer aliases */ + + /* source */ + tmpa = a->dp; + + /* destination */ + tmpb = b->dp; + + /* copy all the digits */ + for (n = 0; n < a->used; n++) { + *tmpb++ = *tmpa++; + } + + /* clear high digits */ + for (; n < b->used && b->dp; n++) { + *tmpb++ = 0; + } + } + + /* copy used count and sign */ + b->used = a->used; + b->sign = a->sign; + return MP_OKAY; +} + + +/* grow as required */ +int mp_grow (mp_int * a, int size) +{ + int i; + mp_digit *tmp; + + /* if the alloc size is smaller alloc more ram */ + if (a->alloc < size || size == 0) { + /* ensure there are always at least MP_PREC digits extra on top */ + size += (MP_PREC * 2) - (size % MP_PREC); + + /* reallocate the array a->dp + * + * We store the return in a temporary variable + * in case the operation failed we don't want + * to overwrite the dp member of a. + */ + tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * size, NULL, + DYNAMIC_TYPE_BIGINT); + if (tmp == NULL) { + /* reallocation failed but "a" is still valid [can be freed] */ + return MP_MEM; + } + + /* reallocation succeeded so set a->dp */ + a->dp = tmp; + + /* zero excess digits */ + i = a->alloc; + a->alloc = size; + for (; i < a->alloc; i++) { + a->dp[i] = 0; + } + } + return MP_OKAY; +} + + +/* shift right by a certain bit count (store quotient in c, optional + remainder in d) */ +int mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d) +{ + int D, res; + mp_int t; + + + /* if the shift count is <= 0 then we do no work */ + if (b <= 0) { + res = mp_copy (a, c); + if (d != NULL) { + mp_zero (d); + } + return res; + } + + if ((res = mp_init (&t)) != MP_OKAY) { + return res; + } + + /* get the remainder */ + if (d != NULL) { + if ((res = mp_mod_2d (a, b, &t)) != MP_OKAY) { + mp_clear (&t); + return res; + } + } + + /* copy */ + if ((res = mp_copy (a, c)) != MP_OKAY) { + mp_clear (&t); + return res; + } + + /* shift by as many digits in the bit count */ + if (b >= (int)DIGIT_BIT) { + mp_rshd (c, b / DIGIT_BIT); + } + + /* shift any bit count < DIGIT_BIT */ + D = (b % DIGIT_BIT); + if (D != 0) { + mp_rshb(c, D); + } + mp_clamp (c); + if (d != NULL) { + mp_exch (&t, d); + } + mp_clear (&t); + return MP_OKAY; +} + + +/* set to zero */ +void mp_zero (mp_int * a) +{ + int n; + mp_digit *tmp; + + if (a == NULL) + return; + + a->sign = MP_ZPOS; + a->used = 0; + + tmp = a->dp; + for (n = 0; n < a->alloc; n++) { + *tmp++ = 0; + } +} + + +/* trim unused digits + * + * This is used to ensure that leading zero digits are + * trimmed and the leading "used" digit will be non-zero + * Typically very fast. Also fixes the sign if there + * are no more leading digits + */ +void mp_clamp (mp_int * a) +{ + /* decrease used while the most significant digit is + * zero. + */ + while (a->used > 0 && a->dp[a->used - 1] == 0) { + --(a->used); + } + + /* reset the sign flag if used == 0 */ + if (a->used == 0) { + a->sign = MP_ZPOS; + } +} + + +/* swap the elements of two integers, for cases where you can't simply swap the + * mp_int pointers around + */ +void mp_exch (mp_int * a, mp_int * b) +{ + mp_int t; + + t = *a; + *a = *b; + *b = t; +} + + +/* shift right a certain number of bits */ +void mp_rshb (mp_int *c, int x) +{ + mp_digit *tmpc, mask, shift; + mp_digit r, rr; + mp_digit D = x; + + /* mask */ + mask = (((mp_digit)1) << D) - 1; + + /* shift for lsb */ + shift = DIGIT_BIT - D; + + /* alias */ + tmpc = c->dp + (c->used - 1); + + /* carry */ + r = 0; + for (x = c->used - 1; x >= 0; x--) { + /* get the lower bits of this word in a temp */ + rr = *tmpc & mask; + + /* shift the current word and mix in the carry bits from previous word */ + *tmpc = (*tmpc >> D) | (r << shift); + --tmpc; + + /* set the carry to the carry bits of the current word found above */ + r = rr; + } + mp_clamp(c); +} + + +/* shift right a certain amount of digits */ +void mp_rshd (mp_int * a, int b) +{ + int x; + + /* if b <= 0 then ignore it */ + if (b <= 0) { + return; + } + + /* if b > used then simply zero it and return */ + if (a->used <= b) { + mp_zero (a); + return; + } + + { + mp_digit *bottom, *top; + + /* shift the digits down */ + + /* bottom */ + bottom = a->dp; + + /* top [offset into digits] */ + top = a->dp + b; + + /* this is implemented as a sliding window where + * the window is b-digits long and digits from + * the top of the window are copied to the bottom + * + * e.g. + + b-2 | b-1 | b0 | b1 | b2 | ... | bb | ----> + /\ | ----> + \-------------------/ ----> + */ + for (x = 0; x < (a->used - b); x++) { + *bottom++ = *top++; + } + + /* zero the top digits */ + for (; x < a->used; x++) { + *bottom++ = 0; + } + } + + /* remove excess digits */ + a->used -= b; +} + + +/* calc a value mod 2**b */ +int mp_mod_2d (mp_int * a, int b, mp_int * c) +{ + int x, res; + + /* if b is <= 0 then zero the int */ + if (b <= 0) { + mp_zero (c); + return MP_OKAY; + } + + /* if the modulus is larger than the value than return */ + if (b >= (int) (a->used * DIGIT_BIT)) { + res = mp_copy (a, c); + return res; + } + + /* copy */ + if ((res = mp_copy (a, c)) != MP_OKAY) { + return res; + } + + /* zero digits above the last digit of the modulus */ + for (x = (b / DIGIT_BIT) + ((b % DIGIT_BIT) == 0 ? 0 : 1); x < c->used; x++) { + c->dp[x] = 0; + } + /* clear the digit that is not completely outside/inside the modulus */ + c->dp[b / DIGIT_BIT] &= (mp_digit) ((((mp_digit) 1) << + (((mp_digit) b) % DIGIT_BIT)) - ((mp_digit) 1)); + mp_clamp (c); + return MP_OKAY; +} + + +/* reads a unsigned char array, assumes the msb is stored first [big endian] */ +int mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c) +{ + int res; + + /* make sure there are at least two digits */ + if (a->alloc < 2) { + if ((res = mp_grow(a, 2)) != MP_OKAY) { + return res; + } + } + + /* zero the int */ + mp_zero (a); + + /* read the bytes in */ + while (c-- > 0) { + if ((res = mp_mul_2d (a, 8, a)) != MP_OKAY) { + return res; + } + +#ifndef MP_8BIT + a->dp[0] |= *b++; + a->used += 1; +#else + a->dp[0] = (*b & MP_MASK); + a->dp[1] |= ((*b++ >> 7U) & 1); + a->used += 2; +#endif + } + mp_clamp (a); + return MP_OKAY; +} + + +/* shift left by a certain bit count */ +int mp_mul_2d (mp_int * a, int b, mp_int * c) +{ + mp_digit d; + int res; + + /* copy */ + if (a != c) { + if ((res = mp_copy (a, c)) != MP_OKAY) { + return res; + } + } + + if (c->alloc < (int)(c->used + b/DIGIT_BIT + 1)) { + if ((res = mp_grow (c, c->used + b / DIGIT_BIT + 1)) != MP_OKAY) { + return res; + } + } + + /* shift by as many digits in the bit count */ + if (b >= (int)DIGIT_BIT) { + if ((res = mp_lshd (c, b / DIGIT_BIT)) != MP_OKAY) { + return res; + } + } + + /* shift any bit count < DIGIT_BIT */ + d = (mp_digit) (b % DIGIT_BIT); + if (d != 0) { + mp_digit *tmpc, shift, mask, r, rr; + int x; + + /* bitmask for carries */ + mask = (((mp_digit)1) << d) - 1; + + /* shift for msbs */ + shift = DIGIT_BIT - d; + + /* alias */ + tmpc = c->dp; + + /* carry */ + r = 0; + for (x = 0; x < c->used; x++) { + /* get the higher bits of the current word */ + rr = (*tmpc >> shift) & mask; + + /* shift the current word and OR in the carry */ + *tmpc = (mp_digit)(((*tmpc << d) | r) & MP_MASK); + ++tmpc; + + /* set the carry to the carry bits of the current word */ + r = rr; + } + + /* set final carry */ + if (r != 0) { + c->dp[(c->used)++] = r; + } + } + mp_clamp (c); + return MP_OKAY; +} + + +/* shift left a certain amount of digits */ +int mp_lshd (mp_int * a, int b) +{ + int x, res; + + /* if its less than zero return */ + if (b <= 0) { + return MP_OKAY; + } + + /* grow to fit the new digits */ + if (a->alloc < a->used + b) { + if ((res = mp_grow (a, a->used + b)) != MP_OKAY) { + return res; + } + } + + { + mp_digit *top, *bottom; + + /* increment the used by the shift amount then copy upwards */ + a->used += b; + + /* top */ + top = a->dp + a->used - 1; + + /* base */ + bottom = a->dp + a->used - 1 - b; + + /* much like mp_rshd this is implemented using a sliding window + * except the window goes the other way around. Copying from + * the bottom to the top. see bn_mp_rshd.c for more info. + */ + for (x = a->used - 1; x >= b; x--) { + *top-- = *bottom--; + } + + /* zero the lower digits */ + top = a->dp; + for (x = 0; x < b; x++) { + *top++ = 0; + } + } + return MP_OKAY; +} + + +/* this is a shell function that calls either the normal or Montgomery + * exptmod functions. Originally the call to the montgomery code was + * embedded in the normal function but that wasted a lot of stack space + * for nothing (since 99% of the time the Montgomery code would be called) + */ +#if defined(FREESCALE_LTC_TFM) +int wolfcrypt_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) +#else +int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) +#endif +{ + int dr; + + /* modulus P must be positive */ + if (P->sign == MP_NEG) { + return MP_VAL; + } + + /* if exponent X is negative we have to recurse */ + if (X->sign == MP_NEG) { +#ifdef BN_MP_INVMOD_C + mp_int tmpG, tmpX; + int err; + + /* first compute 1/G mod P */ + if ((err = mp_init(&tmpG)) != MP_OKAY) { + return err; + } + if ((err = mp_invmod(G, P, &tmpG)) != MP_OKAY) { + mp_clear(&tmpG); + return err; + } + + /* now get |X| */ + if ((err = mp_init(&tmpX)) != MP_OKAY) { + mp_clear(&tmpG); + return err; + } + if ((err = mp_abs(X, &tmpX)) != MP_OKAY) { + mp_clear(&tmpG); + mp_clear(&tmpX); + return err; + } + + /* and now compute (1/G)**|X| instead of G**X [X < 0] */ + err = mp_exptmod(&tmpG, &tmpX, P, Y); + mp_clear(&tmpG); + mp_clear(&tmpX); + return err; +#else + /* no invmod */ + return MP_VAL; +#endif + } + +/* modified diminished radix reduction */ +#if defined(BN_MP_REDUCE_IS_2K_L_C) && defined(BN_MP_REDUCE_2K_L_C) && \ + defined(BN_S_MP_EXPTMOD_C) + if (mp_reduce_is_2k_l(P) == MP_YES) { + return s_mp_exptmod(G, X, P, Y, 1); + } +#endif + +#ifdef BN_MP_DR_IS_MODULUS_C + /* is it a DR modulus? */ + dr = mp_dr_is_modulus(P); +#else + /* default to no */ + dr = 0; +#endif + +#ifdef BN_MP_REDUCE_IS_2K_C + /* if not, is it a unrestricted DR modulus? */ + if (dr == 0) { + dr = mp_reduce_is_2k(P) << 1; + } +#endif + + /* if the modulus is odd or dr != 0 use the montgomery method */ +#ifdef BN_MP_EXPTMOD_FAST_C + if (mp_isodd (P) == MP_YES || dr != 0) { + return mp_exptmod_fast (G, X, P, Y, dr); + } else { +#endif +#ifdef BN_S_MP_EXPTMOD_C + /* otherwise use the generic Barrett reduction technique */ + return s_mp_exptmod (G, X, P, Y, 0); +#else + /* no exptmod for evens */ + return MP_VAL; +#endif +#ifdef BN_MP_EXPTMOD_FAST_C + } +#endif +} + + +/* b = |a| + * + * Simple function copies the input and fixes the sign to positive + */ +int mp_abs (mp_int * a, mp_int * b) +{ + int res; + + /* copy a to b */ + if (a != b) { + if ((res = mp_copy (a, b)) != MP_OKAY) { + return res; + } + } + + /* force the sign of b to positive */ + b->sign = MP_ZPOS; + + return MP_OKAY; +} + + +/* hac 14.61, pp608 */ +#if defined(FREESCALE_LTC_TFM) +int wolfcrypt_mp_invmod(mp_int * a, mp_int * b, mp_int * c) +#else +int mp_invmod (mp_int * a, mp_int * b, mp_int * c) +#endif +{ + /* b cannot be negative */ + if (b->sign == MP_NEG || mp_iszero(b) == MP_YES) { + return MP_VAL; + } + +#ifdef BN_FAST_MP_INVMOD_C + /* if the modulus is odd we can use a faster routine instead */ + if ((mp_isodd(b) == MP_YES) && (mp_cmp_d(b, 1) != MP_EQ)) { + return fast_mp_invmod (a, b, c); + } +#endif + +#ifdef BN_MP_INVMOD_SLOW_C + return mp_invmod_slow(a, b, c); +#else + return MP_VAL; +#endif +} + + +/* computes the modular inverse via binary extended euclidean algorithm, + * that is c = 1/a mod b + * + * Based on slow invmod except this is optimized for the case where b is + * odd as per HAC Note 14.64 on pp. 610 + */ +int fast_mp_invmod (mp_int * a, mp_int * b, mp_int * c) +{ + mp_int x, y, u, v, B, D; + int res, neg, loop_check = 0; + + /* 2. [modified] b must be odd */ + if (mp_iseven (b) == MP_YES) { + return MP_VAL; + } + + /* init all our temps */ + if ((res = mp_init_multi(&x, &y, &u, &v, &B, &D)) != MP_OKAY) { + return res; + } + + /* x == modulus, y == value to invert */ + if ((res = mp_copy (b, &x)) != MP_OKAY) { + goto LBL_ERR; + } + + /* we need y = |a| */ + if ((res = mp_mod (a, b, &y)) != MP_OKAY) { + goto LBL_ERR; + } + + /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */ + if ((res = mp_copy (&x, &u)) != MP_OKAY) { + goto LBL_ERR; + } + if ((res = mp_copy (&y, &v)) != MP_OKAY) { + goto LBL_ERR; + } + if ((res = mp_set (&D, 1)) != MP_OKAY) { + goto LBL_ERR; + } + +top: + /* 4. while u is even do */ + while (mp_iseven (&u) == MP_YES) { + /* 4.1 u = u/2 */ + if ((res = mp_div_2 (&u, &u)) != MP_OKAY) { + goto LBL_ERR; + } + /* 4.2 if B is odd then */ + if (mp_isodd (&B) == MP_YES) { + if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) { + goto LBL_ERR; + } + } + /* B = B/2 */ + if ((res = mp_div_2 (&B, &B)) != MP_OKAY) { + goto LBL_ERR; + } + } + + /* 5. while v is even do */ + while (mp_iseven (&v) == MP_YES) { + /* 5.1 v = v/2 */ + if ((res = mp_div_2 (&v, &v)) != MP_OKAY) { + goto LBL_ERR; + } + /* 5.2 if D is odd then */ + if (mp_isodd (&D) == MP_YES) { + /* D = (D-x)/2 */ + if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) { + goto LBL_ERR; + } + } + /* D = D/2 */ + if ((res = mp_div_2 (&D, &D)) != MP_OKAY) { + goto LBL_ERR; + } + } + + /* 6. if u >= v then */ + if (mp_cmp (&u, &v) != MP_LT) { + /* u = u - v, B = B - D */ + if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) { + goto LBL_ERR; + } + + if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) { + goto LBL_ERR; + } + } else { + /* v - v - u, D = D - B */ + if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) { + goto LBL_ERR; + } + + if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) { + goto LBL_ERR; + } + } + + /* if not zero goto step 4 */ + if (mp_iszero (&u) == MP_NO) { + if (++loop_check > MAX_INVMOD_SZ) { + res = MP_VAL; + goto LBL_ERR; + } + goto top; + } + + /* now a = C, b = D, gcd == g*v */ + + /* if v != 1 then there is no inverse */ + if (mp_cmp_d (&v, 1) != MP_EQ) { + res = MP_VAL; + goto LBL_ERR; + } + + /* b is now the inverse */ + neg = a->sign; + while (D.sign == MP_NEG) { + if ((res = mp_add (&D, b, &D)) != MP_OKAY) { + goto LBL_ERR; + } + } + /* too big */ + while (mp_cmp_mag(&D, b) != MP_LT) { + if ((res = mp_sub(&D, b, &D)) != MP_OKAY) { + goto LBL_ERR; + } + } + mp_exch (&D, c); + c->sign = neg; + res = MP_OKAY; + +LBL_ERR:mp_clear(&x); + mp_clear(&y); + mp_clear(&u); + mp_clear(&v); + mp_clear(&B); + mp_clear(&D); + return res; +} + + +/* hac 14.61, pp608 */ +int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c) +{ + mp_int x, y, u, v, A, B, C, D; + int res; + + /* b cannot be negative */ + if (b->sign == MP_NEG || mp_iszero(b) == MP_YES) { + return MP_VAL; + } + + /* init temps */ + if ((res = mp_init_multi(&x, &y, &u, &v, + &A, &B)) != MP_OKAY) { + return res; + } + + /* init rest of tmps temps */ + if ((res = mp_init_multi(&C, &D, 0, 0, 0, 0)) != MP_OKAY) { + mp_clear(&x); + mp_clear(&y); + mp_clear(&u); + mp_clear(&v); + mp_clear(&A); + mp_clear(&B); + return res; + } + + /* x = a, y = b */ + if ((res = mp_mod(a, b, &x)) != MP_OKAY) { + goto LBL_ERR; + } + if ((res = mp_copy (b, &y)) != MP_OKAY) { + goto LBL_ERR; + } + + /* 2. [modified] if x,y are both even then return an error! */ + if (mp_iseven (&x) == MP_YES && mp_iseven (&y) == MP_YES) { + res = MP_VAL; + goto LBL_ERR; + } + + /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */ + if ((res = mp_copy (&x, &u)) != MP_OKAY) { + goto LBL_ERR; + } + if ((res = mp_copy (&y, &v)) != MP_OKAY) { + goto LBL_ERR; + } + if ((res = mp_set (&A, 1)) != MP_OKAY) { + goto LBL_ERR; + } + if ((res = mp_set (&D, 1)) != MP_OKAY) { + goto LBL_ERR; + } + +top: + /* 4. while u is even do */ + while (mp_iseven (&u) == MP_YES) { + /* 4.1 u = u/2 */ + if ((res = mp_div_2 (&u, &u)) != MP_OKAY) { + goto LBL_ERR; + } + /* 4.2 if A or B is odd then */ + if (mp_isodd (&A) == MP_YES || mp_isodd (&B) == MP_YES) { + /* A = (A+y)/2, B = (B-x)/2 */ + if ((res = mp_add (&A, &y, &A)) != MP_OKAY) { + goto LBL_ERR; + } + if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) { + goto LBL_ERR; + } + } + /* A = A/2, B = B/2 */ + if ((res = mp_div_2 (&A, &A)) != MP_OKAY) { + goto LBL_ERR; + } + if ((res = mp_div_2 (&B, &B)) != MP_OKAY) { + goto LBL_ERR; + } + } + + /* 5. while v is even do */ + while (mp_iseven (&v) == MP_YES) { + /* 5.1 v = v/2 */ + if ((res = mp_div_2 (&v, &v)) != MP_OKAY) { + goto LBL_ERR; + } + /* 5.2 if C or D is odd then */ + if (mp_isodd (&C) == MP_YES || mp_isodd (&D) == MP_YES) { + /* C = (C+y)/2, D = (D-x)/2 */ + if ((res = mp_add (&C, &y, &C)) != MP_OKAY) { + goto LBL_ERR; + } + if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) { + goto LBL_ERR; + } + } + /* C = C/2, D = D/2 */ + if ((res = mp_div_2 (&C, &C)) != MP_OKAY) { + goto LBL_ERR; + } + if ((res = mp_div_2 (&D, &D)) != MP_OKAY) { + goto LBL_ERR; + } + } + + /* 6. if u >= v then */ + if (mp_cmp (&u, &v) != MP_LT) { + /* u = u - v, A = A - C, B = B - D */ + if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) { + goto LBL_ERR; + } + + if ((res = mp_sub (&A, &C, &A)) != MP_OKAY) { + goto LBL_ERR; + } + + if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) { + goto LBL_ERR; + } + } else { + /* v - v - u, C = C - A, D = D - B */ + if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) { + goto LBL_ERR; + } + + if ((res = mp_sub (&C, &A, &C)) != MP_OKAY) { + goto LBL_ERR; + } + + if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) { + goto LBL_ERR; + } + } + + /* if not zero goto step 4 */ + if (mp_iszero (&u) == MP_NO) + goto top; + + /* now a = C, b = D, gcd == g*v */ + + /* if v != 1 then there is no inverse */ + if (mp_cmp_d (&v, 1) != MP_EQ) { + res = MP_VAL; + goto LBL_ERR; + } + + /* if its too low */ + while (mp_cmp_d(&C, 0) == MP_LT) { + if ((res = mp_add(&C, b, &C)) != MP_OKAY) { + goto LBL_ERR; + } + } + + /* too big */ + while (mp_cmp_mag(&C, b) != MP_LT) { + if ((res = mp_sub(&C, b, &C)) != MP_OKAY) { + goto LBL_ERR; + } + } + + /* C is now the inverse */ + mp_exch (&C, c); + res = MP_OKAY; +LBL_ERR:mp_clear(&x); + mp_clear(&y); + mp_clear(&u); + mp_clear(&v); + mp_clear(&A); + mp_clear(&B); + mp_clear(&C); + mp_clear(&D); + return res; +} + + +/* compare magnitude of two ints (unsigned) */ +int mp_cmp_mag (mp_int * a, mp_int * b) +{ + int n; + mp_digit *tmpa, *tmpb; + + /* compare based on # of non-zero digits */ + if (a->used > b->used) { + return MP_GT; + } + + if (a->used < b->used) { + return MP_LT; + } + + /* alias for a */ + tmpa = a->dp + (a->used - 1); + + /* alias for b */ + tmpb = b->dp + (a->used - 1); + + /* compare based on digits */ + for (n = 0; n < a->used; ++n, --tmpa, --tmpb) { + if (*tmpa > *tmpb) { + return MP_GT; + } + + if (*tmpa < *tmpb) { + return MP_LT; + } + } + return MP_EQ; +} + + +/* compare two ints (signed)*/ +int mp_cmp (mp_int * a, mp_int * b) +{ + /* compare based on sign */ + if (a->sign != b->sign) { + if (a->sign == MP_NEG) { + return MP_LT; + } else { + return MP_GT; + } + } + + /* compare digits */ + if (a->sign == MP_NEG) { + /* if negative compare opposite direction */ + return mp_cmp_mag(b, a); + } else { + return mp_cmp_mag(a, b); + } +} + + +/* compare a digit */ +int mp_cmp_d(mp_int * a, mp_digit b) +{ + /* special case for zero*/ + if (a->used == 0 && b == 0) + return MP_EQ; + + /* compare based on sign */ + if ((b && a->used == 0) || a->sign == MP_NEG) { + return MP_LT; + } + + /* compare based on magnitude */ + if (a->used > 1) { + return MP_GT; + } + + /* compare the only digit of a to b */ + if (a->dp[0] > b) { + return MP_GT; + } else if (a->dp[0] < b) { + return MP_LT; + } else { + return MP_EQ; + } +} + + +/* set to a digit */ +int mp_set (mp_int * a, mp_digit b) +{ + int res; + mp_zero (a); + res = mp_grow (a, 1); + if (res == MP_OKAY) { + a->dp[0] = (mp_digit)(b & MP_MASK); + a->used = (a->dp[0] != 0) ? 1 : 0; + } + return res; +} + +/* chek if a bit is set */ +int mp_is_bit_set (mp_int *a, mp_digit b) +{ + if ((mp_digit)a->used < b/DIGIT_BIT) + return 0; + + return (int)((a->dp[b/DIGIT_BIT] >> b%DIGIT_BIT) & (mp_digit)1); +} + +/* c = a mod b, 0 <= c < b */ +#if defined(FREESCALE_LTC_TFM) +int wolfcrypt_mp_mod(mp_int * a, mp_int * b, mp_int * c) +#else +int mp_mod (mp_int * a, mp_int * b, mp_int * c) +#endif +{ + mp_int t; + int res; + + if ((res = mp_init_size (&t, b->used)) != MP_OKAY) { + return res; + } + + if ((res = mp_div (a, b, NULL, &t)) != MP_OKAY) { + mp_clear (&t); + return res; + } + + if ((mp_iszero(&t) != MP_NO) || (t.sign == b->sign)) { + res = MP_OKAY; + mp_exch (&t, c); + } else { + res = mp_add (b, &t, c); + } + + mp_clear (&t); + return res; +} + + +/* slower bit-bang division... also smaller */ +int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d) +{ + mp_int ta, tb, tq, q; + int res, n, n2; + + /* is divisor zero ? */ + if (mp_iszero (b) == MP_YES) { + return MP_VAL; + } + + /* if a < b then q=0, r = a */ + if (mp_cmp_mag (a, b) == MP_LT) { + if (d != NULL) { + res = mp_copy (a, d); + } else { + res = MP_OKAY; + } + if (c != NULL) { + mp_zero (c); + } + return res; + } + + /* init our temps */ + if ((res = mp_init_multi(&ta, &tb, &tq, &q, 0, 0)) != MP_OKAY) { + return res; + } + + if ((res = mp_set(&tq, 1)) != MP_OKAY) { + return res; + } + n = mp_count_bits(a) - mp_count_bits(b); + if (((res = mp_abs(a, &ta)) != MP_OKAY) || + ((res = mp_abs(b, &tb)) != MP_OKAY) || + ((res = mp_mul_2d(&tb, n, &tb)) != MP_OKAY) || + ((res = mp_mul_2d(&tq, n, &tq)) != MP_OKAY)) { + goto LBL_ERR; + } + + while (n-- >= 0) { + if (mp_cmp(&tb, &ta) != MP_GT) { + if (((res = mp_sub(&ta, &tb, &ta)) != MP_OKAY) || + ((res = mp_add(&q, &tq, &q)) != MP_OKAY)) { + goto LBL_ERR; + } + } + if (((res = mp_div_2d(&tb, 1, &tb, NULL)) != MP_OKAY) || + ((res = mp_div_2d(&tq, 1, &tq, NULL)) != MP_OKAY)) { + goto LBL_ERR; + } + } + + /* now q == quotient and ta == remainder */ + n = a->sign; + n2 = (a->sign == b->sign ? MP_ZPOS : MP_NEG); + if (c != NULL) { + mp_exch(c, &q); + c->sign = (mp_iszero(c) == MP_YES) ? MP_ZPOS : n2; + } + if (d != NULL) { + mp_exch(d, &ta); + d->sign = (mp_iszero(d) == MP_YES) ? MP_ZPOS : n; + } +LBL_ERR: + mp_clear(&ta); + mp_clear(&tb); + mp_clear(&tq); + mp_clear(&q); + return res; +} + + +/* b = a/2 */ +int mp_div_2(mp_int * a, mp_int * b) +{ + int x, res, oldused; + + /* copy */ + if (b->alloc < a->used) { + if ((res = mp_grow (b, a->used)) != MP_OKAY) { + return res; + } + } + + oldused = b->used; + b->used = a->used; + { + mp_digit r, rr, *tmpa, *tmpb; + + /* source alias */ + tmpa = a->dp + b->used - 1; + + /* dest alias */ + tmpb = b->dp + b->used - 1; + + /* carry */ + r = 0; + for (x = b->used - 1; x >= 0; x--) { + /* get the carry for the next iteration */ + rr = *tmpa & 1; + + /* shift the current digit, add in carry and store */ + *tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1)); + + /* forward carry to next iteration */ + r = rr; + } + + /* zero excess digits */ + tmpb = b->dp + b->used; + for (x = b->used; x < oldused; x++) { + *tmpb++ = 0; + } + } + b->sign = a->sign; + mp_clamp (b); + return MP_OKAY; +} + + +/* high level addition (handles signs) */ +int mp_add (mp_int * a, mp_int * b, mp_int * c) +{ + int sa, sb, res; + + /* get sign of both inputs */ + sa = a->sign; + sb = b->sign; + + /* handle two cases, not four */ + if (sa == sb) { + /* both positive or both negative */ + /* add their magnitudes, copy the sign */ + c->sign = sa; + res = s_mp_add (a, b, c); + } else { + /* one positive, the other negative */ + /* subtract the one with the greater magnitude from */ + /* the one of the lesser magnitude. The result gets */ + /* the sign of the one with the greater magnitude. */ + if (mp_cmp_mag (a, b) == MP_LT) { + c->sign = sb; + res = s_mp_sub (b, a, c); + } else { + c->sign = sa; + res = s_mp_sub (a, b, c); + } + } + return res; +} + + +/* low level addition, based on HAC pp.594, Algorithm 14.7 */ +int s_mp_add (mp_int * a, mp_int * b, mp_int * c) +{ + mp_int *x; + int olduse, res, min_ab, max_ab; + + /* find sizes, we let |a| <= |b| which means we have to sort + * them. "x" will point to the input with the most digits + */ + if (a->used > b->used) { + min_ab = b->used; + max_ab = a->used; + x = a; + } else { + min_ab = a->used; + max_ab = b->used; + x = b; + } + + /* init result */ + if (c->alloc < max_ab + 1) { + if ((res = mp_grow (c, max_ab + 1)) != MP_OKAY) { + return res; + } + } + + /* get old used digit count and set new one */ + olduse = c->used; + c->used = max_ab + 1; + + { + mp_digit u, *tmpa, *tmpb, *tmpc; + int i; + + /* alias for digit pointers */ + + /* first input */ + tmpa = a->dp; + + /* second input */ + tmpb = b->dp; + + /* destination */ + tmpc = c->dp; + + /* zero the carry */ + u = 0; + for (i = 0; i < min_ab; i++) { + /* Compute the sum at one digit, T[i] = A[i] + B[i] + U */ + *tmpc = *tmpa++ + *tmpb++ + u; + + /* U = carry bit of T[i] */ + u = *tmpc >> ((mp_digit)DIGIT_BIT); + + /* take away carry bit from T[i] */ + *tmpc++ &= MP_MASK; + } + + /* now copy higher words if any, that is in A+B + * if A or B has more digits add those in + */ + if (min_ab != max_ab) { + for (; i < max_ab; i++) { + /* T[i] = X[i] + U */ + *tmpc = x->dp[i] + u; + + /* U = carry bit of T[i] */ + u = *tmpc >> ((mp_digit)DIGIT_BIT); + + /* take away carry bit from T[i] */ + *tmpc++ &= MP_MASK; + } + } + + /* add carry */ + *tmpc++ = u; + + /* clear digits above olduse */ + for (i = c->used; i < olduse; i++) { + *tmpc++ = 0; + } + } + + mp_clamp (c); + return MP_OKAY; +} + + +/* low level subtraction (assumes |a| > |b|), HAC pp.595 Algorithm 14.9 */ +int s_mp_sub (mp_int * a, mp_int * b, mp_int * c) +{ + int olduse, res, min_b, max_a; + + /* find sizes */ + min_b = b->used; + max_a = a->used; + + /* init result */ + if (c->alloc < max_a) { + if ((res = mp_grow (c, max_a)) != MP_OKAY) { + return res; + } + } + + /* sanity check on destination */ + if (c->dp == NULL) + return MP_VAL; + + olduse = c->used; + c->used = max_a; + + { + mp_digit u, *tmpa, *tmpb, *tmpc; + int i; + + /* alias for digit pointers */ + tmpa = a->dp; + tmpb = b->dp; + tmpc = c->dp; + + /* set carry to zero */ + u = 0; + for (i = 0; i < min_b; i++) { + /* T[i] = A[i] - B[i] - U */ + *tmpc = *tmpa++ - *tmpb++ - u; + + /* U = carry bit of T[i] + * Note this saves performing an AND operation since + * if a carry does occur it will propagate all the way to the + * MSB. As a result a single shift is enough to get the carry + */ + u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1)); + + /* Clear carry from T[i] */ + *tmpc++ &= MP_MASK; + } + + /* now copy higher words if any, e.g. if A has more digits than B */ + for (; i < max_a; i++) { + /* T[i] = A[i] - U */ + *tmpc = *tmpa++ - u; + + /* U = carry bit of T[i] */ + u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1)); + + /* Clear carry from T[i] */ + *tmpc++ &= MP_MASK; + } + + /* clear digits above used (since we may not have grown result above) */ + for (i = c->used; i < olduse; i++) { + *tmpc++ = 0; + } + } + + mp_clamp (c); + return MP_OKAY; +} + + +/* high level subtraction (handles signs) */ +int mp_sub (mp_int * a, mp_int * b, mp_int * c) +{ + int sa, sb, res; + + sa = a->sign; + sb = b->sign; + + if (sa != sb) { + /* subtract a negative from a positive, OR */ + /* subtract a positive from a negative. */ + /* In either case, ADD their magnitudes, */ + /* and use the sign of the first number. */ + c->sign = sa; + res = s_mp_add (a, b, c); + } else { + /* subtract a positive from a positive, OR */ + /* subtract a negative from a negative. */ + /* First, take the difference between their */ + /* magnitudes, then... */ + if (mp_cmp_mag (a, b) != MP_LT) { + /* Copy the sign from the first */ + c->sign = sa; + /* The first has a larger or equal magnitude */ + res = s_mp_sub (a, b, c); + } else { + /* The result has the *opposite* sign from */ + /* the first number. */ + c->sign = (sa == MP_ZPOS) ? MP_NEG : MP_ZPOS; + /* The second has a larger magnitude */ + res = s_mp_sub (b, a, c); + } + } + return res; +} + + +/* determines if reduce_2k_l can be used */ +int mp_reduce_is_2k_l(mp_int *a) +{ + int ix, iy; + + if (a->used == 0) { + return MP_NO; + } else if (a->used == 1) { + return MP_YES; + } else if (a->used > 1) { + /* if more than half of the digits are -1 we're sold */ + for (iy = ix = 0; ix < a->used; ix++) { + if (a->dp[ix] == MP_MASK) { + ++iy; + } + } + return (iy >= (a->used/2)) ? MP_YES : MP_NO; + + } + return MP_NO; +} + + +/* determines if mp_reduce_2k can be used */ +int mp_reduce_is_2k(mp_int *a) +{ + int ix, iy, iw; + mp_digit iz; + + if (a->used == 0) { + return MP_NO; + } else if (a->used == 1) { + return MP_YES; + } else if (a->used > 1) { + iy = mp_count_bits(a); + iz = 1; + iw = 1; + + /* Test every bit from the second digit up, must be 1 */ + for (ix = DIGIT_BIT; ix < iy; ix++) { + if ((a->dp[iw] & iz) == 0) { + return MP_NO; + } + iz <<= 1; + if (iz > (mp_digit)MP_MASK) { + ++iw; + iz = 1; + } + } + } + return MP_YES; +} + + +/* determines if a number is a valid DR modulus */ +int mp_dr_is_modulus(mp_int *a) +{ + int ix; + + /* must be at least two digits */ + if (a->used < 2) { + return 0; + } + + /* must be of the form b**k - a [a <= b] so all + * but the first digit must be equal to -1 (mod b). + */ + for (ix = 1; ix < a->used; ix++) { + if (a->dp[ix] != MP_MASK) { + return 0; + } + } + return 1; +} + + +/* computes Y == G**X mod P, HAC pp.616, Algorithm 14.85 + * + * Uses a left-to-right k-ary sliding window to compute the modular + * exponentiation. + * The value of k changes based on the size of the exponent. + * + * Uses Montgomery or Diminished Radix reduction [whichever appropriate] + */ + +#ifdef MP_LOW_MEM + #define TAB_SIZE 32 +#else + #define TAB_SIZE 256 +#endif + +int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, + int redmode) +{ + mp_int res; + mp_digit buf, mp; + int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize; +#ifdef WOLFSSL_SMALL_STACK + mp_int* M = NULL; +#else + mp_int M[TAB_SIZE]; +#endif + /* use a pointer to the reduction algorithm. This allows us to use + * one of many reduction algorithms without modding the guts of + * the code with if statements everywhere. + */ + int (*redux)(mp_int*,mp_int*,mp_digit); + +#ifdef WOLFSSL_SMALL_STACK + M = (mp_int*) XMALLOC(sizeof(mp_int) * TAB_SIZE, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (M == NULL) + return MP_MEM; +#endif + + /* find window size */ + x = mp_count_bits (X); + if (x <= 7) { + winsize = 2; + } else if (x <= 36) { + winsize = 3; + } else if (x <= 140) { + winsize = 4; + } else if (x <= 450) { + winsize = 5; + } else if (x <= 1303) { + winsize = 6; + } else if (x <= 3529) { + winsize = 7; + } else { + winsize = 8; + } + +#ifdef MP_LOW_MEM + if (winsize > 5) { + winsize = 5; + } +#endif + + /* init M array */ + /* init first cell */ + if ((err = mp_init_size(&M[1], P->alloc)) != MP_OKAY) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(M, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; + } + + /* now init the second half of the array */ + for (x = 1<<(winsize-1); x < (1 << winsize); x++) { + if ((err = mp_init_size(&M[x], P->alloc)) != MP_OKAY) { + for (y = 1<<(winsize-1); y < x; y++) { + mp_clear (&M[y]); + } + mp_clear(&M[1]); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(M, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; + } + } + + /* determine and setup reduction code */ + if (redmode == 0) { +#ifdef BN_MP_MONTGOMERY_SETUP_C + /* now setup montgomery */ + if ((err = mp_montgomery_setup (P, &mp)) != MP_OKAY) { + goto LBL_M; + } +#else + err = MP_VAL; + goto LBL_M; +#endif + + /* automatically pick the comba one if available (saves quite a few + calls/ifs) */ +#ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C + if (((P->used * 2 + 1) < (int)MP_WARRAY) && + P->used < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { + redux = fast_mp_montgomery_reduce; + } else +#endif + { +#ifdef BN_MP_MONTGOMERY_REDUCE_C + /* use slower baseline Montgomery method */ + redux = mp_montgomery_reduce; +#else + err = MP_VAL; + goto LBL_M; +#endif + } + } else if (redmode == 1) { +#if defined(BN_MP_DR_SETUP_C) && defined(BN_MP_DR_REDUCE_C) + /* setup DR reduction for moduli of the form B**k - b */ + mp_dr_setup(P, &mp); + redux = mp_dr_reduce; +#else + err = MP_VAL; + goto LBL_M; +#endif + } else { +#if defined(BN_MP_REDUCE_2K_SETUP_C) && defined(BN_MP_REDUCE_2K_C) + /* setup DR reduction for moduli of the form 2**k - b */ + if ((err = mp_reduce_2k_setup(P, &mp)) != MP_OKAY) { + goto LBL_M; + } + redux = mp_reduce_2k; +#else + err = MP_VAL; + goto LBL_M; +#endif + } + + /* setup result */ + if ((err = mp_init_size (&res, P->alloc)) != MP_OKAY) { + goto LBL_M; + } + + /* create M table + * + + * + * The first half of the table is not computed though accept for M[0] and M[1] + */ + + if (redmode == 0) { +#ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C + /* now we need R mod m */ + if ((err = mp_montgomery_calc_normalization (&res, P)) != MP_OKAY) { + goto LBL_RES; + } + + /* now set M[1] to G * R mod m */ + if ((err = mp_mulmod (G, &res, P, &M[1])) != MP_OKAY) { + goto LBL_RES; + } +#else + err = MP_VAL; + goto LBL_RES; +#endif + } else { + if ((err = mp_set(&res, 1)) != MP_OKAY) { + goto LBL_RES; + } + if ((err = mp_mod(G, P, &M[1])) != MP_OKAY) { + goto LBL_RES; + } + } + + /* compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times*/ + if ((err = mp_copy (&M[1], &M[(mp_digit)(1 << (winsize - 1))])) != MP_OKAY) { + goto LBL_RES; + } + + for (x = 0; x < (winsize - 1); x++) { + if ((err = mp_sqr (&M[(mp_digit)(1 << (winsize - 1))], + &M[(mp_digit)(1 << (winsize - 1))])) != MP_OKAY) { + goto LBL_RES; + } + if ((err = redux (&M[(mp_digit)(1 << (winsize - 1))], P, mp)) != MP_OKAY) { + goto LBL_RES; + } + } + + /* create upper table */ + for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) { + if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) { + goto LBL_RES; + } + if ((err = redux (&M[x], P, mp)) != MP_OKAY) { + goto LBL_RES; + } + } + + /* set initial mode and bit cnt */ + mode = 0; + bitcnt = 1; + buf = 0; + digidx = X->used - 1; + bitcpy = 0; + bitbuf = 0; + + for (;;) { + /* grab next digit as required */ + if (--bitcnt == 0) { + /* if digidx == -1 we are out of digits so break */ + if (digidx == -1) { + break; + } + /* read next digit and reset bitcnt */ + buf = X->dp[digidx--]; + bitcnt = (int)DIGIT_BIT; + } + + /* grab the next msb from the exponent */ + y = (int)(buf >> (DIGIT_BIT - 1)) & 1; + buf <<= (mp_digit)1; + + /* if the bit is zero and mode == 0 then we ignore it + * These represent the leading zero bits before the first 1 bit + * in the exponent. Technically this opt is not required but it + * does lower the # of trivial squaring/reductions used + */ + if (mode == 0 && y == 0) { + continue; + } + + /* if the bit is zero and mode == 1 then we square */ + if (mode == 1 && y == 0) { + if ((err = mp_sqr (&res, &res)) != MP_OKAY) { + goto LBL_RES; + } + if ((err = redux (&res, P, mp)) != MP_OKAY) { + goto LBL_RES; + } + continue; + } + + /* else we add it to the window */ + bitbuf |= (y << (winsize - ++bitcpy)); + mode = 2; + + if (bitcpy == winsize) { + /* ok window is filled so square as required and multiply */ + /* square first */ + for (x = 0; x < winsize; x++) { + if ((err = mp_sqr (&res, &res)) != MP_OKAY) { + goto LBL_RES; + } + if ((err = redux (&res, P, mp)) != MP_OKAY) { + goto LBL_RES; + } + } + + /* then multiply */ + if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) { + goto LBL_RES; + } + if ((err = redux (&res, P, mp)) != MP_OKAY) { + goto LBL_RES; + } + + /* empty window and reset */ + bitcpy = 0; + bitbuf = 0; + mode = 1; + } + } + + /* if bits remain then square/multiply */ + if (mode == 2 && bitcpy > 0) { + /* square then multiply if the bit is set */ + for (x = 0; x < bitcpy; x++) { + if ((err = mp_sqr (&res, &res)) != MP_OKAY) { + goto LBL_RES; + } + if ((err = redux (&res, P, mp)) != MP_OKAY) { + goto LBL_RES; + } + + /* get next bit of the window */ + bitbuf <<= 1; + if ((bitbuf & (1 << winsize)) != 0) { + /* then multiply */ + if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) { + goto LBL_RES; + } + if ((err = redux (&res, P, mp)) != MP_OKAY) { + goto LBL_RES; + } + } + } + } + + if (redmode == 0) { + /* fixup result if Montgomery reduction is used + * recall that any value in a Montgomery system is + * actually multiplied by R mod n. So we have + * to reduce one more time to cancel out the factor + * of R. + */ + if ((err = redux(&res, P, mp)) != MP_OKAY) { + goto LBL_RES; + } + } + + /* swap res with Y */ + mp_exch (&res, Y); + err = MP_OKAY; +LBL_RES:mp_clear (&res); +LBL_M: + mp_clear(&M[1]); + for (x = 1<<(winsize-1); x < (1 << winsize); x++) { + mp_clear (&M[x]); + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(M, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} + + +/* setups the montgomery reduction stuff */ +int mp_montgomery_setup (mp_int * n, mp_digit * rho) +{ + mp_digit x, b; + +/* fast inversion mod 2**k + * + * Based on the fact that + * + * XA = 1 (mod 2**n) => (X(2-XA)) A = 1 (mod 2**2n) + * => 2*X*A - X*X*A*A = 1 + * => 2*(1) - (1) = 1 + */ + b = n->dp[0]; + + if ((b & 1) == 0) { + return MP_VAL; + } + + x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ + x *= 2 - b * x; /* here x*a==1 mod 2**8 */ +#if !defined(MP_8BIT) + x *= 2 - b * x; /* here x*a==1 mod 2**16 */ +#endif +#if defined(MP_64BIT) || !(defined(MP_8BIT) || defined(MP_16BIT)) + x *= 2 - b * x; /* here x*a==1 mod 2**32 */ +#endif +#ifdef MP_64BIT + x *= 2 - b * x; /* here x*a==1 mod 2**64 */ +#endif + + /* rho = -1/m mod b */ + /* TAO, switched mp_word casts to mp_digit to shut up compiler */ + *rho = (mp_digit)((((mp_digit)1 << ((mp_digit) DIGIT_BIT)) - x) & MP_MASK); + + return MP_OKAY; +} + + +/* computes xR**-1 == x (mod N) via Montgomery Reduction + * + * This is an optimized implementation of montgomery_reduce + * which uses the comba method to quickly calculate the columns of the + * reduction. + * + * Based on Algorithm 14.32 on pp.601 of HAC. +*/ +int fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) +{ + int ix, res, olduse; +#ifdef WOLFSSL_SMALL_STACK + mp_word* W; /* uses dynamic memory and slower */ +#else + mp_word W[MP_WARRAY]; +#endif + + /* get old used count */ + olduse = x->used; + + /* grow a as required */ + if (x->alloc < n->used + 1) { + if ((res = mp_grow (x, n->used + 1)) != MP_OKAY) { + return res; + } + } + +#ifdef WOLFSSL_SMALL_STACK + W = (mp_word*)XMALLOC(sizeof(mp_word) * MP_WARRAY, NULL, DYNAMIC_TYPE_BIGINT); + if (W == NULL) + return MP_MEM; +#endif + + /* first we have to get the digits of the input into + * an array of double precision words W[...] + */ + { + mp_word *_W; + mp_digit *tmpx; + + /* alias for the W[] array */ + _W = W; + + /* alias for the digits of x*/ + tmpx = x->dp; + + /* copy the digits of a into W[0..a->used-1] */ + for (ix = 0; ix < x->used; ix++) { + *_W++ = *tmpx++; + } + + /* zero the high words of W[a->used..m->used*2] */ + for (; ix < n->used * 2 + 1; ix++) { + *_W++ = 0; + } + } + + /* now we proceed to zero successive digits + * from the least significant upwards + */ + for (ix = 0; ix < n->used; ix++) { + /* mu = ai * m' mod b + * + * We avoid a double precision multiplication (which isn't required) + * by casting the value down to a mp_digit. Note this requires + * that W[ix-1] have the carry cleared (see after the inner loop) + */ + mp_digit mu; + mu = (mp_digit) (((W[ix] & MP_MASK) * rho) & MP_MASK); + + /* a = a + mu * m * b**i + * + * This is computed in place and on the fly. The multiplication + * by b**i is handled by offseting which columns the results + * are added to. + * + * Note the comba method normally doesn't handle carries in the + * inner loop In this case we fix the carry from the previous + * column since the Montgomery reduction requires digits of the + * result (so far) [see above] to work. This is + * handled by fixing up one carry after the inner loop. The + * carry fixups are done in order so after these loops the + * first m->used words of W[] have the carries fixed + */ + { + int iy; + mp_digit *tmpn; + mp_word *_W; + + /* alias for the digits of the modulus */ + tmpn = n->dp; + + /* Alias for the columns set by an offset of ix */ + _W = W + ix; + + /* inner loop */ + for (iy = 0; iy < n->used; iy++) { + *_W++ += ((mp_word)mu) * ((mp_word)*tmpn++); + } + } + + /* now fix carry for next digit, W[ix+1] */ + W[ix + 1] += W[ix] >> ((mp_word) DIGIT_BIT); + } + + /* now we have to propagate the carries and + * shift the words downward [all those least + * significant digits we zeroed]. + */ + { + mp_digit *tmpx; + mp_word *_W, *_W1; + + /* nox fix rest of carries */ + + /* alias for current word */ + _W1 = W + ix; + + /* alias for next word, where the carry goes */ + _W = W + ++ix; + + for (; ix <= n->used * 2 + 1; ix++) { + *_W++ += *_W1++ >> ((mp_word) DIGIT_BIT); + } + + /* copy out, A = A/b**n + * + * The result is A/b**n but instead of converting from an + * array of mp_word to mp_digit than calling mp_rshd + * we just copy them in the right order + */ + + /* alias for destination word */ + tmpx = x->dp; + + /* alias for shifted double precision result */ + _W = W + n->used; + + for (ix = 0; ix < n->used + 1; ix++) { + *tmpx++ = (mp_digit)(*_W++ & ((mp_word) MP_MASK)); + } + + /* zero olduse digits, if the input a was larger than + * m->used+1 we'll have to clear the digits + */ + for (; ix < olduse; ix++) { + *tmpx++ = 0; + } + } + + /* set the max used and clamp */ + x->used = n->used + 1; + mp_clamp (x); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(W, NULL, DYNAMIC_TYPE_BIGINT); +#endif + + /* if A >= m then A = A - m */ + if (mp_cmp_mag (x, n) != MP_LT) { + return s_mp_sub (x, n, x); + } + return MP_OKAY; +} + + +/* computes xR**-1 == x (mod N) via Montgomery Reduction */ +int mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho) +{ + int ix, res, digs; + mp_digit mu; + + /* can the fast reduction [comba] method be used? + * + * Note that unlike in mul you're safely allowed *less* + * than the available columns [255 per default] since carries + * are fixed up in the inner loop. + */ + digs = n->used * 2 + 1; + if ((digs < (int)MP_WARRAY) && + n->used < + (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { + return fast_mp_montgomery_reduce (x, n, rho); + } + + /* grow the input as required */ + if (x->alloc < digs) { + if ((res = mp_grow (x, digs)) != MP_OKAY) { + return res; + } + } + x->used = digs; + + for (ix = 0; ix < n->used; ix++) { + /* mu = ai * rho mod b + * + * The value of rho must be precalculated via + * montgomery_setup() such that + * it equals -1/n0 mod b this allows the + * following inner loop to reduce the + * input one digit at a time + */ + mu = (mp_digit) (((mp_word)x->dp[ix]) * ((mp_word)rho) & MP_MASK); + + /* a = a + mu * m * b**i */ + { + int iy; + mp_digit *tmpn, *tmpx, u; + mp_word r; + + /* alias for digits of the modulus */ + tmpn = n->dp; + + /* alias for the digits of x [the input] */ + tmpx = x->dp + ix; + + /* set the carry to zero */ + u = 0; + + /* Multiply and add in place */ + for (iy = 0; iy < n->used; iy++) { + /* compute product and sum */ + r = ((mp_word)mu) * ((mp_word)*tmpn++) + + ((mp_word) u) + ((mp_word) * tmpx); + + /* get carry */ + u = (mp_digit)(r >> ((mp_word) DIGIT_BIT)); + + /* fix digit */ + *tmpx++ = (mp_digit)(r & ((mp_word) MP_MASK)); + } + /* At this point the ix'th digit of x should be zero */ + + + /* propagate carries upwards as required*/ + while (u) { + *tmpx += u; + u = *tmpx >> DIGIT_BIT; + *tmpx++ &= MP_MASK; + } + } + } + + /* at this point the n.used'th least + * significant digits of x are all zero + * which means we can shift x to the + * right by n.used digits and the + * residue is unchanged. + */ + + /* x = x/b**n.used */ + mp_clamp(x); + mp_rshd (x, n->used); + + /* if x >= n then x = x - n */ + if (mp_cmp_mag (x, n) != MP_LT) { + return s_mp_sub (x, n, x); + } + + return MP_OKAY; +} + + +/* determines the setup value */ +void mp_dr_setup(mp_int *a, mp_digit *d) +{ + /* the casts are required if DIGIT_BIT is one less than + * the number of bits in a mp_digit [e.g. DIGIT_BIT==31] + */ + *d = (mp_digit)((((mp_word)1) << ((mp_word)DIGIT_BIT)) - + ((mp_word)a->dp[0])); +} + + +/* reduce "x" in place modulo "n" using the Diminished Radix algorithm. + * + * Based on algorithm from the paper + * + * "Generating Efficient Primes for Discrete Log Cryptosystems" + * Chae Hoon Lim, Pil Joong Lee, + * POSTECH Information Research Laboratories + * + * The modulus must be of a special format [see manual] + * + * Has been modified to use algorithm 7.10 from the LTM book instead + * + * Input x must be in the range 0 <= x <= (n-1)**2 + */ +int mp_dr_reduce (mp_int * x, mp_int * n, mp_digit k) +{ + int err, i, m; + mp_word r; + mp_digit mu, *tmpx1, *tmpx2; + + /* m = digits in modulus */ + m = n->used; + + /* ensure that "x" has at least 2m digits */ + if (x->alloc < m + m) { + if ((err = mp_grow (x, m + m)) != MP_OKAY) { + return err; + } + } + +/* top of loop, this is where the code resumes if + * another reduction pass is required. + */ +top: + /* aliases for digits */ + /* alias for lower half of x */ + tmpx1 = x->dp; + + /* alias for upper half of x, or x/B**m */ + tmpx2 = x->dp + m; + + /* set carry to zero */ + mu = 0; + + /* compute (x mod B**m) + k * [x/B**m] inline and inplace */ + for (i = 0; i < m; i++) { + r = ((mp_word)*tmpx2++) * ((mp_word)k) + *tmpx1 + mu; + *tmpx1++ = (mp_digit)(r & MP_MASK); + mu = (mp_digit)(r >> ((mp_word)DIGIT_BIT)); + } + + /* set final carry */ + *tmpx1++ = mu; + + /* zero words above m */ + for (i = m + 1; i < x->used; i++) { + *tmpx1++ = 0; + } + + /* clamp, sub and return */ + mp_clamp (x); + + /* if x >= n then subtract and reduce again + * Each successive "recursion" makes the input smaller and smaller. + */ + if (mp_cmp_mag (x, n) != MP_LT) { + if ((err = s_mp_sub(x, n, x)) != MP_OKAY) { + return err; + } + goto top; + } + return MP_OKAY; +} + + +/* reduces a modulo n where n is of the form 2**p - d */ +int mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d) +{ + mp_int q; + int p, res; + + if ((res = mp_init(&q)) != MP_OKAY) { + return res; + } + + p = mp_count_bits(n); +top: + /* q = a/2**p, a = a mod 2**p */ + if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) { + goto ERR; + } + + if (d != 1) { + /* q = q * d */ + if ((res = mp_mul_d(&q, d, &q)) != MP_OKAY) { + goto ERR; + } + } + + /* a = a + q */ + if ((res = s_mp_add(a, &q, a)) != MP_OKAY) { + goto ERR; + } + + if (mp_cmp_mag(a, n) != MP_LT) { + if ((res = s_mp_sub(a, n, a)) != MP_OKAY) { + goto ERR; + } + goto top; + } + +ERR: + mp_clear(&q); + return res; +} + + +/* determines the setup value */ +int mp_reduce_2k_setup(mp_int *a, mp_digit *d) +{ + int res, p; + mp_int tmp; + + if ((res = mp_init(&tmp)) != MP_OKAY) { + return res; + } + + p = mp_count_bits(a); + if ((res = mp_2expt(&tmp, p)) != MP_OKAY) { + mp_clear(&tmp); + return res; + } + + if ((res = s_mp_sub(&tmp, a, &tmp)) != MP_OKAY) { + mp_clear(&tmp); + return res; + } + + *d = tmp.dp[0]; + mp_clear(&tmp); + return MP_OKAY; +} + + +/* set the b bit of a */ +int mp_set_bit (mp_int * a, int b) +{ + int i = b / DIGIT_BIT, res; + + if (a->used < (int)(i + 1)) { + /* grow a to accommodate the single bit */ + if ((res = mp_grow (a, i + 1)) != MP_OKAY) { + return res; + } + + /* set the used count of where the bit will go */ + a->used = (int)(i + 1); + } + + /* put the single bit in its place */ + a->dp[i] |= ((mp_digit)1) << (b % DIGIT_BIT); + + return MP_OKAY; +} + +/* computes a = 2**b + * + * Simple algorithm which zeros the int, set the required bit + */ +int mp_2expt (mp_int * a, int b) +{ + /* zero a as per default */ + mp_zero (a); + + return mp_set_bit(a, b); +} + +/* multiply by a digit */ +int mp_mul_d (mp_int * a, mp_digit b, mp_int * c) +{ + mp_digit u, *tmpa, *tmpc; + mp_word r; + int ix, res, olduse; + + /* make sure c is big enough to hold a*b */ + if (c->alloc < a->used + 1) { + if ((res = mp_grow (c, a->used + 1)) != MP_OKAY) { + return res; + } + } + + /* get the original destinations used count */ + olduse = c->used; + + /* set the sign */ + c->sign = a->sign; + + /* alias for a->dp [source] */ + tmpa = a->dp; + + /* alias for c->dp [dest] */ + tmpc = c->dp; + + /* zero carry */ + u = 0; + + /* compute columns */ + for (ix = 0; ix < a->used; ix++) { + /* compute product and carry sum for this term */ + r = ((mp_word) u) + ((mp_word)*tmpa++) * ((mp_word)b); + + /* mask off higher bits to get a single digit */ + *tmpc++ = (mp_digit) (r & ((mp_word) MP_MASK)); + + /* send carry into next iteration */ + u = (mp_digit) (r >> ((mp_word) DIGIT_BIT)); + } + + /* store final carry [if any] and increment ix offset */ + *tmpc++ = u; + ++ix; + + /* now zero digits above the top */ + while (ix++ < olduse) { + *tmpc++ = 0; + } + + /* set used count */ + c->used = a->used + 1; + mp_clamp(c); + + return MP_OKAY; +} + + +/* d = a * b (mod c) */ +#if defined(FREESCALE_LTC_TFM) +int wolfcrypt_mp_mulmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d) +#else +int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d) +#endif +{ + int res; + mp_int t; + + if ((res = mp_init_size (&t, c->used)) != MP_OKAY) { + return res; + } + + res = mp_mul (a, b, &t); + if (res == MP_OKAY) { + res = mp_mod (&t, c, d); + } + + mp_clear (&t); + return res; +} + + +/* d = a - b (mod c) */ +int mp_submod(mp_int* a, mp_int* b, mp_int* c, mp_int* d) +{ + int res; + mp_int t; + + if ((res = mp_init (&t)) != MP_OKAY) { + return res; + } + + res = mp_sub (a, b, &t); + if (res == MP_OKAY) { + res = mp_mod (&t, c, d); + } + + mp_clear (&t); + + return res; +} + +/* d = a + b (mod c) */ +int mp_addmod(mp_int* a, mp_int* b, mp_int* c, mp_int* d) +{ + int res; + mp_int t; + + if ((res = mp_init (&t)) != MP_OKAY) { + return res; + } + + res = mp_add (a, b, &t); + if (res == MP_OKAY) { + res = mp_mod (&t, c, d); + } + + mp_clear (&t); + + return res; +} + +/* computes b = a*a */ +int mp_sqr (mp_int * a, mp_int * b) +{ + int res; + + { +#ifdef BN_FAST_S_MP_SQR_C + /* can we use the fast comba multiplier? */ + if ((a->used * 2 + 1) < (int)MP_WARRAY && + a->used < + (1 << (sizeof(mp_word) * CHAR_BIT - 2*DIGIT_BIT - 1))) { + res = fast_s_mp_sqr (a, b); + } else +#endif +#ifdef BN_S_MP_SQR_C + res = s_mp_sqr (a, b); +#else + res = MP_VAL; +#endif + } + b->sign = MP_ZPOS; + return res; +} + + +/* high level multiplication (handles sign) */ +#if defined(FREESCALE_LTC_TFM) +int wolfcrypt_mp_mul(mp_int *a, mp_int *b, mp_int *c) +#else +int mp_mul (mp_int * a, mp_int * b, mp_int * c) +#endif +{ + int res, neg; + neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG; + + { + /* can we use the fast multiplier? + * + * The fast multiplier can be used if the output will + * have less than MP_WARRAY digits and the number of + * digits won't affect carry propagation + */ + int digs = a->used + b->used + 1; + +#ifdef BN_FAST_S_MP_MUL_DIGS_C + if ((digs < (int)MP_WARRAY) && + MIN(a->used, b->used) <= + (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { + res = fast_s_mp_mul_digs (a, b, c, digs); + } else +#endif +#ifdef BN_S_MP_MUL_DIGS_C + res = s_mp_mul (a, b, c); /* uses s_mp_mul_digs */ +#else + res = MP_VAL; +#endif + + } + c->sign = (c->used > 0) ? neg : MP_ZPOS; + return res; +} + + +/* b = a*2 */ +int mp_mul_2(mp_int * a, mp_int * b) +{ + int x, res, oldused; + + /* grow to accommodate result */ + if (b->alloc < a->used + 1) { + if ((res = mp_grow (b, a->used + 1)) != MP_OKAY) { + return res; + } + } + + oldused = b->used; + b->used = a->used; + + { + mp_digit r, rr, *tmpa, *tmpb; + + /* alias for source */ + tmpa = a->dp; + + /* alias for dest */ + tmpb = b->dp; + + /* carry */ + r = 0; + for (x = 0; x < a->used; x++) { + + /* get what will be the *next* carry bit from the + * MSB of the current digit + */ + rr = *tmpa >> ((mp_digit)(DIGIT_BIT - 1)); + + /* now shift up this digit, add in the carry [from the previous] */ + *tmpb++ = (mp_digit)(((*tmpa++ << ((mp_digit)1)) | r) & MP_MASK); + + /* copy the carry that would be from the source + * digit into the next iteration + */ + r = rr; + } + + /* new leading digit? */ + if (r != 0) { + /* add a MSB which is always 1 at this point */ + *tmpb = 1; + ++(b->used); + } + + /* now zero any excess digits on the destination + * that we didn't write to + */ + tmpb = b->dp + b->used; + for (x = b->used; x < oldused; x++) { + *tmpb++ = 0; + } + } + b->sign = a->sign; + return MP_OKAY; +} + + +/* divide by three (based on routine from MPI and the GMP manual) */ +int mp_div_3 (mp_int * a, mp_int *c, mp_digit * d) +{ + mp_int q; + mp_word w, t; + mp_digit b; + int res, ix; + + /* b = 2**DIGIT_BIT / 3 */ + b = (mp_digit) ( (((mp_word)1) << ((mp_word)DIGIT_BIT)) / ((mp_word)3) ); + + if ((res = mp_init_size(&q, a->used)) != MP_OKAY) { + return res; + } + + q.used = a->used; + q.sign = a->sign; + w = 0; + for (ix = a->used - 1; ix >= 0; ix--) { + w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]); + + if (w >= 3) { + /* multiply w by [1/3] */ + t = (w * ((mp_word)b)) >> ((mp_word)DIGIT_BIT); + + /* now subtract 3 * [w/3] from w, to get the remainder */ + w -= t+t+t; + + /* fixup the remainder as required since + * the optimization is not exact. + */ + while (w >= 3) { + t += 1; + w -= 3; + } + } else { + t = 0; + } + q.dp[ix] = (mp_digit)t; + } + + /* [optional] store the remainder */ + if (d != NULL) { + *d = (mp_digit)w; + } + + /* [optional] store the quotient */ + if (c != NULL) { + mp_clamp(&q); + mp_exch(&q, c); + } + mp_clear(&q); + + return res; +} + + +/* init an mp_init for a given size */ +int mp_init_size (mp_int * a, int size) +{ + int x; + + /* pad size so there are always extra digits */ + size += (MP_PREC * 2) - (size % MP_PREC); + + /* alloc mem */ + a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * size, NULL, + DYNAMIC_TYPE_BIGINT); + if (a->dp == NULL) { + return MP_MEM; + } + + /* set the members */ + a->used = 0; + a->alloc = size; + a->sign = MP_ZPOS; +#ifdef HAVE_WOLF_BIGINT + wc_bigint_init(&a->raw); +#endif + + /* zero the digits */ + for (x = 0; x < size; x++) { + a->dp[x] = 0; + } + + return MP_OKAY; +} + + +/* the jist of squaring... + * you do like mult except the offset of the tmpx [one that + * starts closer to zero] can't equal the offset of tmpy. + * So basically you set up iy like before then you min it with + * (ty-tx) so that it never happens. You double all those + * you add in the inner loop + +After that loop you do the squares and add them in. +*/ + +int fast_s_mp_sqr (mp_int * a, mp_int * b) +{ + int olduse, res, pa, ix, iz; +#ifdef WOLFSSL_SMALL_STACK + mp_digit* W; /* uses dynamic memory and slower */ +#else + mp_digit W[MP_WARRAY]; +#endif + mp_digit *tmpx; + mp_word W1; + + /* grow the destination as required */ + pa = a->used + a->used; + if (b->alloc < pa) { + if ((res = mp_grow (b, pa)) != MP_OKAY) { + return res; + } + } + + if (pa > (int)MP_WARRAY) + return MP_RANGE; /* TAO range check */ + +#ifdef WOLFSSL_SMALL_STACK + W = (mp_digit*)XMALLOC(sizeof(mp_digit) * MP_WARRAY, NULL, DYNAMIC_TYPE_BIGINT); + if (W == NULL) + return MP_MEM; +#endif + + /* number of output digits to produce */ + W1 = 0; + for (ix = 0; ix < pa; ix++) { + int tx, ty, iy; + mp_word _W; + mp_digit *tmpy; + + /* clear counter */ + _W = 0; + + /* get offsets into the two bignums */ + ty = MIN(a->used-1, ix); + tx = ix - ty; + + /* setup temp aliases */ + tmpx = a->dp + tx; + tmpy = a->dp + ty; + + /* this is the number of times the loop will iterate, essentially + while (tx++ < a->used && ty-- >= 0) { ... } + */ + iy = MIN(a->used-tx, ty+1); + + /* now for squaring tx can never equal ty + * we halve the distance since they approach at a rate of 2x + * and we have to round because odd cases need to be executed + */ + iy = MIN(iy, (ty-tx+1)>>1); + + /* execute loop */ + for (iz = 0; iz < iy; iz++) { + _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--); + } + + /* double the inner product and add carry */ + _W = _W + _W + W1; + + /* even columns have the square term in them */ + if ((ix&1) == 0) { + _W += ((mp_word)a->dp[ix>>1])*((mp_word)a->dp[ix>>1]); + } + + /* store it */ + W[ix] = (mp_digit)(_W & MP_MASK); + + /* make next carry */ + W1 = _W >> ((mp_word)DIGIT_BIT); + } + + /* setup dest */ + olduse = b->used; + b->used = a->used+a->used; + + { + mp_digit *tmpb; + tmpb = b->dp; + for (ix = 0; ix < pa; ix++) { + *tmpb++ = (mp_digit)(W[ix] & MP_MASK); + } + + /* clear unused digits [that existed in the old copy of c] */ + for (; ix < olduse; ix++) { + *tmpb++ = 0; + } + } + mp_clamp (b); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(W, NULL, DYNAMIC_TYPE_BIGINT); +#endif + + return MP_OKAY; +} + + +/* Fast (comba) multiplier + * + * This is the fast column-array [comba] multiplier. It is + * designed to compute the columns of the product first + * then handle the carries afterwards. This has the effect + * of making the nested loops that compute the columns very + * simple and schedulable on super-scalar processors. + * + * This has been modified to produce a variable number of + * digits of output so if say only a half-product is required + * you don't have to compute the upper half (a feature + * required for fast Barrett reduction). + * + * Based on Algorithm 14.12 on pp.595 of HAC. + * + */ +int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) +{ + int olduse, res, pa, ix, iz; +#ifdef WOLFSSL_SMALL_STACK + mp_digit* W; /* uses dynamic memory and slower */ +#else + mp_digit W[MP_WARRAY]; +#endif + mp_word _W; + + /* grow the destination as required */ + if (c->alloc < digs) { + if ((res = mp_grow (c, digs)) != MP_OKAY) { + return res; + } + } + + /* number of output digits to produce */ + pa = MIN(digs, a->used + b->used); + if (pa > (int)MP_WARRAY) + return MP_RANGE; /* TAO range check */ + +#ifdef WOLFSSL_SMALL_STACK + W = (mp_digit*)XMALLOC(sizeof(mp_digit) * MP_WARRAY, NULL, DYNAMIC_TYPE_BIGINT); + if (W == NULL) + return MP_MEM; +#endif + + /* clear the carry */ + _W = 0; + for (ix = 0; ix < pa; ix++) { + int tx, ty; + int iy; + mp_digit *tmpx, *tmpy; + + /* get offsets into the two bignums */ + ty = MIN(b->used-1, ix); + tx = ix - ty; + + /* setup temp aliases */ + tmpx = a->dp + tx; + tmpy = b->dp + ty; + + /* this is the number of times the loop will iterate, essentially + while (tx++ < a->used && ty-- >= 0) { ... } + */ + iy = MIN(a->used-tx, ty+1); + + /* execute loop */ + for (iz = 0; iz < iy; ++iz) { + _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--); + + } + + /* store term */ + W[ix] = (mp_digit)(((mp_digit)_W) & MP_MASK); + + /* make next carry */ + _W = _W >> ((mp_word)DIGIT_BIT); + } + + /* setup dest */ + olduse = c->used; + c->used = pa; + + { + mp_digit *tmpc; + tmpc = c->dp; + for (ix = 0; ix < pa; ix++) { /* JRB, +1 could read uninitialized data */ + /* now extract the previous digit [below the carry] */ + *tmpc++ = W[ix]; + } + + /* clear unused digits [that existed in the old copy of c] */ + for (; ix < olduse; ix++) { + *tmpc++ = 0; + } + } + mp_clamp (c); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(W, NULL, DYNAMIC_TYPE_BIGINT); +#endif + + return MP_OKAY; +} + + +/* low level squaring, b = a*a, HAC pp.596-597, Algorithm 14.16 */ +int s_mp_sqr (mp_int * a, mp_int * b) +{ + mp_int t; + int res, ix, iy, pa; + mp_word r; + mp_digit u, tmpx, *tmpt; + + pa = a->used; + if ((res = mp_init_size (&t, 2*pa + 1)) != MP_OKAY) { + return res; + } + + /* default used is maximum possible size */ + t.used = 2*pa + 1; + + for (ix = 0; ix < pa; ix++) { + /* first calculate the digit at 2*ix */ + /* calculate double precision result */ + r = ((mp_word) t.dp[2*ix]) + + ((mp_word)a->dp[ix])*((mp_word)a->dp[ix]); + + /* store lower part in result */ + t.dp[ix+ix] = (mp_digit) (r & ((mp_word) MP_MASK)); + + /* get the carry */ + u = (mp_digit)(r >> ((mp_word) DIGIT_BIT)); + + /* left hand side of A[ix] * A[iy] */ + tmpx = a->dp[ix]; + + /* alias for where to store the results */ + tmpt = t.dp + (2*ix + 1); + + for (iy = ix + 1; iy < pa; iy++) { + /* first calculate the product */ + r = ((mp_word)tmpx) * ((mp_word)a->dp[iy]); + + /* now calculate the double precision result, note we use + * addition instead of *2 since it's easier to optimize + */ + r = ((mp_word) *tmpt) + r + r + ((mp_word) u); + + /* store lower part */ + *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK)); + + /* get carry */ + u = (mp_digit)(r >> ((mp_word) DIGIT_BIT)); + } + /* propagate upwards */ + while (u != ((mp_digit) 0)) { + r = ((mp_word) *tmpt) + ((mp_word) u); + *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK)); + u = (mp_digit)(r >> ((mp_word) DIGIT_BIT)); + } + } + + mp_clamp (&t); + mp_exch (&t, b); + mp_clear (&t); + return MP_OKAY; +} + + +/* multiplies |a| * |b| and only computes up to digs digits of result + * HAC pp. 595, Algorithm 14.12 Modified so you can control how + * many digits of output are created. + */ +int s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs) +{ + mp_int t; + int res, pa, pb, ix, iy; + mp_digit u; + mp_word r; + mp_digit tmpx, *tmpt, *tmpy; + + /* can we use the fast multiplier? */ + if ((digs < (int)MP_WARRAY) && + MIN (a->used, b->used) < + (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { + return fast_s_mp_mul_digs (a, b, c, digs); + } + + if ((res = mp_init_size (&t, digs)) != MP_OKAY) { + return res; + } + t.used = digs; + + /* compute the digits of the product directly */ + pa = a->used; + for (ix = 0; ix < pa; ix++) { + /* set the carry to zero */ + u = 0; + + /* limit ourselves to making digs digits of output */ + pb = MIN (b->used, digs - ix); + + /* setup some aliases */ + /* copy of the digit from a used within the nested loop */ + tmpx = a->dp[ix]; + + /* an alias for the destination shifted ix places */ + tmpt = t.dp + ix; + + /* an alias for the digits of b */ + tmpy = b->dp; + + /* compute the columns of the output and propagate the carry */ + for (iy = 0; iy < pb; iy++) { + /* compute the column as a mp_word */ + r = ((mp_word)*tmpt) + + ((mp_word)tmpx) * ((mp_word)*tmpy++) + + ((mp_word) u); + + /* the new column is the lower part of the result */ + *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK)); + + /* get the carry word from the result */ + u = (mp_digit) (r >> ((mp_word) DIGIT_BIT)); + } + /* set carry if it is placed below digs */ + if (ix + iy < digs) { + *tmpt = u; + } + } + + mp_clamp (&t); + mp_exch (&t, c); + + mp_clear (&t); + return MP_OKAY; +} + + +/* + * shifts with subtractions when the result is greater than b. + * + * The method is slightly modified to shift B unconditionally up to just under + * the leading bit of b. This saves a lot of multiple precision shifting. + */ +int mp_montgomery_calc_normalization (mp_int * a, mp_int * b) +{ + int x, bits, res; + + /* how many bits of last digit does b use */ + bits = mp_count_bits (b) % DIGIT_BIT; + + if (b->used > 1) { + if ((res = mp_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1)) + != MP_OKAY) { + return res; + } + } else { + if ((res = mp_set(a, 1)) != MP_OKAY) { + return res; + } + bits = 1; + } + + /* now compute C = A * B mod b */ + for (x = bits - 1; x < (int)DIGIT_BIT; x++) { + if ((res = mp_mul_2 (a, a)) != MP_OKAY) { + return res; + } + if (mp_cmp_mag (a, b) != MP_LT) { + if ((res = s_mp_sub (a, b, a)) != MP_OKAY) { + return res; + } + } + } + + return MP_OKAY; +} + + +#ifdef MP_LOW_MEM + #define TAB_SIZE 32 +#else + #define TAB_SIZE 256 +#endif + +int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode) +{ + mp_int M[TAB_SIZE], res, mu; + mp_digit buf; + int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize; + int (*redux)(mp_int*,mp_int*,mp_int*); + + /* find window size */ + x = mp_count_bits (X); + if (x <= 7) { + winsize = 2; + } else if (x <= 36) { + winsize = 3; + } else if (x <= 140) { + winsize = 4; + } else if (x <= 450) { + winsize = 5; + } else if (x <= 1303) { + winsize = 6; + } else if (x <= 3529) { + winsize = 7; + } else { + winsize = 8; + } + +#ifdef MP_LOW_MEM + if (winsize > 5) { + winsize = 5; + } +#endif + + /* init M array */ + /* init first cell */ + if ((err = mp_init(&M[1])) != MP_OKAY) { + return err; + } + + /* now init the second half of the array */ + for (x = 1<<(winsize-1); x < (1 << winsize); x++) { + if ((err = mp_init(&M[x])) != MP_OKAY) { + for (y = 1<<(winsize-1); y < x; y++) { + mp_clear (&M[y]); + } + mp_clear(&M[1]); + return err; + } + } + + /* create mu, used for Barrett reduction */ + if ((err = mp_init (&mu)) != MP_OKAY) { + goto LBL_M; + } + + if (redmode == 0) { + if ((err = mp_reduce_setup (&mu, P)) != MP_OKAY) { + goto LBL_MU; + } + redux = mp_reduce; + } else { + if ((err = mp_reduce_2k_setup_l (P, &mu)) != MP_OKAY) { + goto LBL_MU; + } + redux = mp_reduce_2k_l; + } + + /* create M table + * + * The M table contains powers of the base, + * e.g. M[x] = G**x mod P + * + * The first half of the table is not + * computed though accept for M[0] and M[1] + */ + if ((err = mp_mod (G, P, &M[1])) != MP_OKAY) { + goto LBL_MU; + } + + /* compute the value at M[1<<(winsize-1)] by squaring + * M[1] (winsize-1) times + */ + if ((err = mp_copy (&M[1], &M[(mp_digit)(1 << (winsize - 1))])) != MP_OKAY) { + goto LBL_MU; + } + + for (x = 0; x < (winsize - 1); x++) { + /* square it */ + if ((err = mp_sqr (&M[(mp_digit)(1 << (winsize - 1))], + &M[(mp_digit)(1 << (winsize - 1))])) != MP_OKAY) { + goto LBL_MU; + } + + /* reduce modulo P */ + if ((err = redux (&M[(mp_digit)(1 << (winsize - 1))], P, &mu)) != MP_OKAY) { + goto LBL_MU; + } + } + + /* create upper table, that is M[x] = M[x-1] * M[1] (mod P) + * for x = (2**(winsize - 1) + 1) to (2**winsize - 1) + */ + for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) { + if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) { + goto LBL_MU; + } + if ((err = redux (&M[x], P, &mu)) != MP_OKAY) { + goto LBL_MU; + } + } + + /* setup result */ + if ((err = mp_init (&res)) != MP_OKAY) { + goto LBL_MU; + } + if ((err = mp_set (&res, 1)) != MP_OKAY) { + goto LBL_MU; + } + + /* set initial mode and bit cnt */ + mode = 0; + bitcnt = 1; + buf = 0; + digidx = X->used - 1; + bitcpy = 0; + bitbuf = 0; + + for (;;) { + /* grab next digit as required */ + if (--bitcnt == 0) { + /* if digidx == -1 we are out of digits */ + if (digidx == -1) { + break; + } + /* read next digit and reset the bitcnt */ + buf = X->dp[digidx--]; + bitcnt = (int) DIGIT_BIT; + } + + /* grab the next msb from the exponent */ + y = (int)(buf >> (mp_digit)(DIGIT_BIT - 1)) & 1; + buf <<= (mp_digit)1; + + /* if the bit is zero and mode == 0 then we ignore it + * These represent the leading zero bits before the first 1 bit + * in the exponent. Technically this opt is not required but it + * does lower the # of trivial squaring/reductions used + */ + if (mode == 0 && y == 0) { + continue; + } + + /* if the bit is zero and mode == 1 then we square */ + if (mode == 1 && y == 0) { + if ((err = mp_sqr (&res, &res)) != MP_OKAY) { + goto LBL_RES; + } + if ((err = redux (&res, P, &mu)) != MP_OKAY) { + goto LBL_RES; + } + continue; + } + + /* else we add it to the window */ + bitbuf |= (y << (winsize - ++bitcpy)); + mode = 2; + + if (bitcpy == winsize) { + /* ok window is filled so square as required and multiply */ + /* square first */ + for (x = 0; x < winsize; x++) { + if ((err = mp_sqr (&res, &res)) != MP_OKAY) { + goto LBL_RES; + } + if ((err = redux (&res, P, &mu)) != MP_OKAY) { + goto LBL_RES; + } + } + + /* then multiply */ + if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) { + goto LBL_RES; + } + if ((err = redux (&res, P, &mu)) != MP_OKAY) { + goto LBL_RES; + } + + /* empty window and reset */ + bitcpy = 0; + bitbuf = 0; + mode = 1; + } + } + + /* if bits remain then square/multiply */ + if (mode == 2 && bitcpy > 0) { + /* square then multiply if the bit is set */ + for (x = 0; x < bitcpy; x++) { + if ((err = mp_sqr (&res, &res)) != MP_OKAY) { + goto LBL_RES; + } + if ((err = redux (&res, P, &mu)) != MP_OKAY) { + goto LBL_RES; + } + + bitbuf <<= 1; + if ((bitbuf & (1 << winsize)) != 0) { + /* then multiply */ + if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) { + goto LBL_RES; + } + if ((err = redux (&res, P, &mu)) != MP_OKAY) { + goto LBL_RES; + } + } + } + } + + mp_exch (&res, Y); + err = MP_OKAY; +LBL_RES:mp_clear (&res); +LBL_MU:mp_clear (&mu); +LBL_M: + mp_clear(&M[1]); + for (x = 1<<(winsize-1); x < (1 << winsize); x++) { + mp_clear (&M[x]); + } + return err; +} + + +/* pre-calculate the value required for Barrett reduction + * For a given modulus "b" it calculates the value required in "a" + */ +int mp_reduce_setup (mp_int * a, mp_int * b) +{ + int res; + + if ((res = mp_2expt (a, b->used * 2 * DIGIT_BIT)) != MP_OKAY) { + return res; + } + return mp_div (a, b, a, NULL); +} + + +/* reduces x mod m, assumes 0 < x < m**2, mu is + * precomputed via mp_reduce_setup. + * From HAC pp.604 Algorithm 14.42 + */ +int mp_reduce (mp_int * x, mp_int * m, mp_int * mu) +{ + mp_int q; + int res, um = m->used; + + /* q = x */ + if ((res = mp_init_copy (&q, x)) != MP_OKAY) { + return res; + } + + /* q1 = x / b**(k-1) */ + mp_rshd (&q, um - 1); + + /* according to HAC this optimization is ok */ + if (((mp_word) um) > (((mp_digit)1) << (DIGIT_BIT - 1))) { + if ((res = mp_mul (&q, mu, &q)) != MP_OKAY) { + goto CLEANUP; + } + } else { +#ifdef BN_S_MP_MUL_HIGH_DIGS_C + if ((res = s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) { + goto CLEANUP; + } +#elif defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C) + if ((res = fast_s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) { + goto CLEANUP; + } +#else + { + res = MP_VAL; + goto CLEANUP; + } +#endif + } + + /* q3 = q2 / b**(k+1) */ + mp_rshd (&q, um + 1); + + /* x = x mod b**(k+1), quick (no division) */ + if ((res = mp_mod_2d (x, DIGIT_BIT * (um + 1), x)) != MP_OKAY) { + goto CLEANUP; + } + + /* q = q * m mod b**(k+1), quick (no division) */ + if ((res = s_mp_mul_digs (&q, m, &q, um + 1)) != MP_OKAY) { + goto CLEANUP; + } + + /* x = x - q */ + if ((res = mp_sub (x, &q, x)) != MP_OKAY) { + goto CLEANUP; + } + + /* If x < 0, add b**(k+1) to it */ + if (mp_cmp_d (x, 0) == MP_LT) { + if ((res = mp_set (&q, 1)) != MP_OKAY) + goto CLEANUP; + if ((res = mp_lshd (&q, um + 1)) != MP_OKAY) + goto CLEANUP; + if ((res = mp_add (x, &q, x)) != MP_OKAY) + goto CLEANUP; + } + + /* Back off if it's too big */ + while (mp_cmp (x, m) != MP_LT) { + if ((res = s_mp_sub (x, m, x)) != MP_OKAY) { + goto CLEANUP; + } + } + +CLEANUP: + mp_clear (&q); + + return res; +} + + +/* reduces a modulo n where n is of the form 2**p - d + This differs from reduce_2k since "d" can be larger + than a single digit. +*/ +int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d) +{ + mp_int q; + int p, res; + + if ((res = mp_init(&q)) != MP_OKAY) { + return res; + } + + p = mp_count_bits(n); +top: + /* q = a/2**p, a = a mod 2**p */ + if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) { + goto ERR; + } + + /* q = q * d */ + if ((res = mp_mul(&q, d, &q)) != MP_OKAY) { + goto ERR; + } + + /* a = a + q */ + if ((res = s_mp_add(a, &q, a)) != MP_OKAY) { + goto ERR; + } + + if (mp_cmp_mag(a, n) != MP_LT) { + if ((res = s_mp_sub(a, n, a)) != MP_OKAY) { + goto ERR; + } + goto top; + } + +ERR: + mp_clear(&q); + return res; +} + + +/* determines the setup value */ +int mp_reduce_2k_setup_l(mp_int *a, mp_int *d) +{ + int res; + mp_int tmp; + + if ((res = mp_init(&tmp)) != MP_OKAY) { + return res; + } + + if ((res = mp_2expt(&tmp, mp_count_bits(a))) != MP_OKAY) { + goto ERR; + } + + if ((res = s_mp_sub(&tmp, a, d)) != MP_OKAY) { + goto ERR; + } + +ERR: + mp_clear(&tmp); + return res; +} + + +/* multiplies |a| * |b| and does not compute the lower digs digits + * [meant to get the higher part of the product] + */ +int s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) +{ + mp_int t; + int res, pa, pb, ix, iy; + mp_digit u; + mp_word r; + mp_digit tmpx, *tmpt, *tmpy; + + /* can we use the fast multiplier? */ +#ifdef BN_FAST_S_MP_MUL_HIGH_DIGS_C + if (((a->used + b->used + 1) < (int)MP_WARRAY) + && MIN (a->used, b->used) < + (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) { + return fast_s_mp_mul_high_digs (a, b, c, digs); + } +#endif + + if ((res = mp_init_size (&t, a->used + b->used + 1)) != MP_OKAY) { + return res; + } + t.used = a->used + b->used + 1; + + pa = a->used; + pb = b->used; + for (ix = 0; ix < pa && a->dp; ix++) { + /* clear the carry */ + u = 0; + + /* left hand side of A[ix] * B[iy] */ + tmpx = a->dp[ix]; + + /* alias to the address of where the digits will be stored */ + tmpt = &(t.dp[digs]); + + /* alias for where to read the right hand side from */ + tmpy = b->dp + (digs - ix); + + for (iy = digs - ix; iy < pb; iy++) { + /* calculate the double precision result */ + r = ((mp_word)*tmpt) + + ((mp_word)tmpx) * ((mp_word)*tmpy++) + + ((mp_word) u); + + /* get the lower part */ + *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK)); + + /* carry the carry */ + u = (mp_digit) (r >> ((mp_word) DIGIT_BIT)); + } + *tmpt = u; + } + mp_clamp (&t); + mp_exch (&t, c); + mp_clear (&t); + return MP_OKAY; +} + + +/* this is a modified version of fast_s_mul_digs that only produces + * output digits *above* digs. See the comments for fast_s_mul_digs + * to see how it works. + * + * This is used in the Barrett reduction since for one of the multiplications + * only the higher digits were needed. This essentially halves the work. + * + * Based on Algorithm 14.12 on pp.595 of HAC. + */ +int fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs) +{ + int olduse, res, pa, ix, iz; +#ifdef WOLFSSL_SMALL_STACK + mp_digit* W; /* uses dynamic memory and slower */ +#else + mp_digit W[MP_WARRAY]; +#endif + mp_word _W; + + if (a->dp == NULL) { /* JRB, avoid reading uninitialized values */ + return MP_VAL; + } + + /* grow the destination as required */ + pa = a->used + b->used; + if (c->alloc < pa) { + if ((res = mp_grow (c, pa)) != MP_OKAY) { + return res; + } + } + + if (pa > (int)MP_WARRAY) + return MP_RANGE; /* TAO range check */ + +#ifdef WOLFSSL_SMALL_STACK + W = (mp_digit*)XMALLOC(sizeof(mp_digit) * MP_WARRAY, NULL, DYNAMIC_TYPE_BIGINT); + if (W == NULL) + return MP_MEM; +#endif + + /* number of output digits to produce */ + pa = a->used + b->used; + _W = 0; + for (ix = digs; ix < pa; ix++) { /* JRB, have a->dp check at top of function*/ + int tx, ty, iy; + mp_digit *tmpx, *tmpy; + + /* get offsets into the two bignums */ + ty = MIN(b->used-1, ix); + tx = ix - ty; + + /* setup temp aliases */ + tmpx = a->dp + tx; + tmpy = b->dp + ty; + + /* this is the number of times the loop will iterate, essentially its + while (tx++ < a->used && ty-- >= 0) { ... } + */ + iy = MIN(a->used-tx, ty+1); + + /* execute loop */ + for (iz = 0; iz < iy; iz++) { + _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--); + } + + /* store term */ + W[ix] = (mp_digit)(((mp_digit)_W) & MP_MASK); + + /* make next carry */ + _W = _W >> ((mp_word)DIGIT_BIT); + } + + /* setup dest */ + olduse = c->used; + c->used = pa; + + { + mp_digit *tmpc; + + tmpc = c->dp + digs; + for (ix = digs; ix < pa; ix++) { /* TAO, <= could potentially overwrite */ + /* now extract the previous digit [below the carry] */ + *tmpc++ = W[ix]; + } + + /* clear unused digits [that existed in the old copy of c] */ + for (; ix < olduse; ix++) { + *tmpc++ = 0; + } + } + mp_clamp (c); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(W, NULL, DYNAMIC_TYPE_BIGINT); +#endif + + return MP_OKAY; +} + + +#ifndef MP_SET_CHUNK_BITS + #define MP_SET_CHUNK_BITS 4 +#endif +int mp_set_int (mp_int * a, unsigned long b) +{ + int x, res; + + /* use direct mp_set if b is less than mp_digit max */ + if (b < MP_DIGIT_MAX) { + return mp_set (a, (mp_digit)b); + } + + mp_zero (a); + + /* set chunk bits at a time */ + for (x = 0; x < (int)(sizeof(b) * 8) / MP_SET_CHUNK_BITS; x++) { + /* shift the number up chunk bits */ + if ((res = mp_mul_2d (a, MP_SET_CHUNK_BITS, a)) != MP_OKAY) { + return res; + } + + /* OR in the top bits of the source */ + a->dp[0] |= (b >> ((sizeof(b) * 8) - MP_SET_CHUNK_BITS)) & + ((1 << MP_SET_CHUNK_BITS) - 1); + + /* shift the source up to the next chunk bits */ + b <<= MP_SET_CHUNK_BITS; + + /* ensure that digits are not clamped off */ + a->used += 1; + } + mp_clamp (a); + return MP_OKAY; +} + + +#if defined(WOLFSSL_KEY_GEN) || defined(HAVE_ECC) || !defined(NO_RSA) || \ + !defined(NO_DSA) | !defined(NO_DH) + +/* c = a * a (mod b) */ +int mp_sqrmod (mp_int * a, mp_int * b, mp_int * c) +{ + int res; + mp_int t; + + if ((res = mp_init (&t)) != MP_OKAY) { + return res; + } + + if ((res = mp_sqr (a, &t)) != MP_OKAY) { + mp_clear (&t); + return res; + } + res = mp_mod (&t, b, c); + mp_clear (&t); + return res; +} + +#endif + + +#if defined(HAVE_ECC) || !defined(NO_PWDBASED) || defined(WOLFSSL_SNIFFER) || \ + defined(WOLFSSL_HAVE_WOLFSCEP) || defined(WOLFSSL_KEY_GEN) || \ + defined(OPENSSL_EXTRA) || defined(WC_RSA_BLINDING) || \ + (!defined(NO_RSA) && !defined(NO_RSA_BOUNDS_CHECK)) + +/* single digit addition */ +int mp_add_d (mp_int* a, mp_digit b, mp_int* c) +{ + int res, ix, oldused; + mp_digit *tmpa, *tmpc, mu; + + /* grow c as required */ + if (c->alloc < a->used + 1) { + if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) { + return res; + } + } + + /* if a is negative and |a| >= b, call c = |a| - b */ + if (a->sign == MP_NEG && (a->used > 1 || a->dp[0] >= b)) { + /* temporarily fix sign of a */ + a->sign = MP_ZPOS; + + /* c = |a| - b */ + res = mp_sub_d(a, b, c); + + /* fix sign */ + a->sign = c->sign = MP_NEG; + + /* clamp */ + mp_clamp(c); + + return res; + } + + /* old number of used digits in c */ + oldused = c->used; + + /* sign always positive */ + c->sign = MP_ZPOS; + + /* source alias */ + tmpa = a->dp; + + /* destination alias */ + tmpc = c->dp; + + /* if a is positive */ + if (a->sign == MP_ZPOS) { + /* add digit, after this we're propagating + * the carry. + */ + *tmpc = *tmpa++ + b; + mu = *tmpc >> DIGIT_BIT; + *tmpc++ &= MP_MASK; + + /* now handle rest of the digits */ + for (ix = 1; ix < a->used; ix++) { + *tmpc = *tmpa++ + mu; + mu = *tmpc >> DIGIT_BIT; + *tmpc++ &= MP_MASK; + } + /* set final carry */ + if (ix < c->alloc) { + ix++; + *tmpc++ = mu; + } + + /* setup size */ + c->used = a->used + 1; + } else { + /* a was negative and |a| < b */ + c->used = 1; + + /* the result is a single digit */ + if (a->used == 1) { + *tmpc++ = b - a->dp[0]; + } else { + *tmpc++ = b; + } + + /* setup count so the clearing of oldused + * can fall through correctly + */ + ix = 1; + } + + /* now zero to oldused */ + while (ix++ < oldused) { + *tmpc++ = 0; + } + mp_clamp(c); + + return MP_OKAY; +} + + +/* single digit subtraction */ +int mp_sub_d (mp_int * a, mp_digit b, mp_int * c) +{ + mp_digit *tmpa, *tmpc, mu; + int res, ix, oldused; + + /* grow c as required */ + if (c->alloc < a->used + 1) { + if ((res = mp_grow(c, a->used + 1)) != MP_OKAY) { + return res; + } + } + + /* if a is negative just do an unsigned + * addition [with fudged signs] + */ + if (a->sign == MP_NEG) { + a->sign = MP_ZPOS; + res = mp_add_d(a, b, c); + a->sign = c->sign = MP_NEG; + + /* clamp */ + mp_clamp(c); + + return res; + } + + /* setup regs */ + oldused = c->used; + tmpa = a->dp; + tmpc = c->dp; + + /* if a <= b simply fix the single digit */ + if ((a->used == 1 && a->dp[0] <= b) || a->used == 0) { + if (a->used == 1) { + *tmpc++ = b - *tmpa; + } else { + *tmpc++ = b; + } + ix = 1; + + /* negative/1digit */ + c->sign = MP_NEG; + c->used = 1; + } else { + /* positive/size */ + c->sign = MP_ZPOS; + c->used = a->used; + + /* subtract first digit */ + *tmpc = *tmpa++ - b; + mu = *tmpc >> (sizeof(mp_digit) * CHAR_BIT - 1); + *tmpc++ &= MP_MASK; + + /* handle rest of the digits */ + for (ix = 1; ix < a->used; ix++) { + *tmpc = *tmpa++ - mu; + mu = *tmpc >> (sizeof(mp_digit) * CHAR_BIT - 1); + *tmpc++ &= MP_MASK; + } + } + + /* zero excess digits */ + while (ix++ < oldused) { + *tmpc++ = 0; + } + mp_clamp(c); + return MP_OKAY; +} + +#endif /* defined(HAVE_ECC) || !defined(NO_PWDBASED) */ + + +#if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || defined(HAVE_ECC) || \ + defined(DEBUG_WOLFSSL) || !defined(NO_RSA) || !defined(NO_DSA) || \ + !defined(NO_DH) + +static const int lnz[16] = { + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 +}; + +/* Counts the number of lsbs which are zero before the first zero bit */ +int mp_cnt_lsb(mp_int *a) +{ + int x; + mp_digit q = 0, qq; + + /* easy out */ + if (mp_iszero(a) == MP_YES) { + return 0; + } + + /* scan lower digits until non-zero */ + for (x = 0; x < a->used && a->dp[x] == 0; x++) {} + if (a->dp) + q = a->dp[x]; + x *= DIGIT_BIT; + + /* now scan this digit until a 1 is found */ + if ((q & 1) == 0) { + do { + qq = q & 15; + x += lnz[qq]; + q >>= 4; + } while (qq == 0); + } + return x; +} + + + + +static int s_is_power_of_two(mp_digit b, int *p) +{ + int x; + + /* fast return if no power of two */ + if ((b==0) || (b & (b-1))) { + return 0; + } + + for (x = 0; x < DIGIT_BIT; x++) { + if (b == (((mp_digit)1)<dp[0] & ((((mp_digit)1)<used)) != MP_OKAY) { + return res; + } + + q.used = a->used; + q.sign = a->sign; + } + else { + if ((res = mp_init(&q)) != MP_OKAY) { + return res; + } + } + + + w = 0; + for (ix = a->used - 1; ix >= 0; ix--) { + w = (w << ((mp_word)DIGIT_BIT)) | ((mp_word)a->dp[ix]); + + if (w >= b) { + t = (mp_digit)(w / b); + w -= ((mp_word)t) * ((mp_word)b); + } else { + t = 0; + } + if (c != NULL) + q.dp[ix] = (mp_digit)t; + } + + if (d != NULL) { + *d = (mp_digit)w; + } + + if (c != NULL) { + mp_clamp(&q); + mp_exch(&q, c); + } + mp_clear(&q); + + return res; +} + + +int mp_mod_d (mp_int * a, mp_digit b, mp_digit * c) +{ + return mp_div_d(a, b, NULL, c); +} + +#endif /* WOLFSSL_KEY_GEN || HAVE_COMP_KEY || HAVE_ECC || DEBUG_WOLFSSL */ + +#if defined(WOLFSSL_KEY_GEN) || !defined(NO_DH) || !defined(NO_DSA) || !defined(NO_RSA) + +const mp_digit ltm_prime_tab[PRIME_SIZE] = { + 0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013, + 0x0017, 0x001D, 0x001F, 0x0025, 0x0029, 0x002B, 0x002F, 0x0035, + 0x003B, 0x003D, 0x0043, 0x0047, 0x0049, 0x004F, 0x0053, 0x0059, + 0x0061, 0x0065, 0x0067, 0x006B, 0x006D, 0x0071, 0x007F, +#ifndef MP_8BIT + 0x0083, + 0x0089, 0x008B, 0x0095, 0x0097, 0x009D, 0x00A3, 0x00A7, 0x00AD, + 0x00B3, 0x00B5, 0x00BF, 0x00C1, 0x00C5, 0x00C7, 0x00D3, 0x00DF, + 0x00E3, 0x00E5, 0x00E9, 0x00EF, 0x00F1, 0x00FB, 0x0101, 0x0107, + 0x010D, 0x010F, 0x0115, 0x0119, 0x011B, 0x0125, 0x0133, 0x0137, + + 0x0139, 0x013D, 0x014B, 0x0151, 0x015B, 0x015D, 0x0161, 0x0167, + 0x016F, 0x0175, 0x017B, 0x017F, 0x0185, 0x018D, 0x0191, 0x0199, + 0x01A3, 0x01A5, 0x01AF, 0x01B1, 0x01B7, 0x01BB, 0x01C1, 0x01C9, + 0x01CD, 0x01CF, 0x01D3, 0x01DF, 0x01E7, 0x01EB, 0x01F3, 0x01F7, + 0x01FD, 0x0209, 0x020B, 0x021D, 0x0223, 0x022D, 0x0233, 0x0239, + 0x023B, 0x0241, 0x024B, 0x0251, 0x0257, 0x0259, 0x025F, 0x0265, + 0x0269, 0x026B, 0x0277, 0x0281, 0x0283, 0x0287, 0x028D, 0x0293, + 0x0295, 0x02A1, 0x02A5, 0x02AB, 0x02B3, 0x02BD, 0x02C5, 0x02CF, + + 0x02D7, 0x02DD, 0x02E3, 0x02E7, 0x02EF, 0x02F5, 0x02F9, 0x0301, + 0x0305, 0x0313, 0x031D, 0x0329, 0x032B, 0x0335, 0x0337, 0x033B, + 0x033D, 0x0347, 0x0355, 0x0359, 0x035B, 0x035F, 0x036D, 0x0371, + 0x0373, 0x0377, 0x038B, 0x038F, 0x0397, 0x03A1, 0x03A9, 0x03AD, + 0x03B3, 0x03B9, 0x03C7, 0x03CB, 0x03D1, 0x03D7, 0x03DF, 0x03E5, + 0x03F1, 0x03F5, 0x03FB, 0x03FD, 0x0407, 0x0409, 0x040F, 0x0419, + 0x041B, 0x0425, 0x0427, 0x042D, 0x043F, 0x0443, 0x0445, 0x0449, + 0x044F, 0x0455, 0x045D, 0x0463, 0x0469, 0x047F, 0x0481, 0x048B, + + 0x0493, 0x049D, 0x04A3, 0x04A9, 0x04B1, 0x04BD, 0x04C1, 0x04C7, + 0x04CD, 0x04CF, 0x04D5, 0x04E1, 0x04EB, 0x04FD, 0x04FF, 0x0503, + 0x0509, 0x050B, 0x0511, 0x0515, 0x0517, 0x051B, 0x0527, 0x0529, + 0x052F, 0x0551, 0x0557, 0x055D, 0x0565, 0x0577, 0x0581, 0x058F, + 0x0593, 0x0595, 0x0599, 0x059F, 0x05A7, 0x05AB, 0x05AD, 0x05B3, + 0x05BF, 0x05C9, 0x05CB, 0x05CF, 0x05D1, 0x05D5, 0x05DB, 0x05E7, + 0x05F3, 0x05FB, 0x0607, 0x060D, 0x0611, 0x0617, 0x061F, 0x0623, + 0x062B, 0x062F, 0x063D, 0x0641, 0x0647, 0x0649, 0x064D, 0x0653 +#endif +}; + + +/* Miller-Rabin test of "a" to the base of "b" as described in + * HAC pp. 139 Algorithm 4.24 + * + * Sets result to 0 if definitely composite or 1 if probably prime. + * Randomly the chance of error is no more than 1/4 and often + * very much lower. + */ +static int mp_prime_miller_rabin (mp_int * a, mp_int * b, int *result) +{ + mp_int n1, y, r; + int s, j, err; + + /* default */ + *result = MP_NO; + + /* ensure b > 1 */ + if (mp_cmp_d(b, 1) != MP_GT) { + return MP_VAL; + } + + /* get n1 = a - 1 */ + if ((err = mp_init_copy (&n1, a)) != MP_OKAY) { + return err; + } + if ((err = mp_sub_d (&n1, 1, &n1)) != MP_OKAY) { + goto LBL_N1; + } + + /* set 2**s * r = n1 */ + if ((err = mp_init_copy (&r, &n1)) != MP_OKAY) { + goto LBL_N1; + } + + /* count the number of least significant bits + * which are zero + */ + s = mp_cnt_lsb(&r); + + /* now divide n - 1 by 2**s */ + if ((err = mp_div_2d (&r, s, &r, NULL)) != MP_OKAY) { + goto LBL_R; + } + + /* compute y = b**r mod a */ + if ((err = mp_init (&y)) != MP_OKAY) { + goto LBL_R; + } +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) +#ifndef WOLFSSL_SP_NO_2048 + if (mp_count_bits(a) == 1024) + err = sp_ModExp_1024(b, &r, a, &y); + else if (mp_count_bits(a) == 2048) + err = sp_ModExp_2048(b, &r, a, &y); + else +#endif +#ifndef WOLFSSL_SP_NO_3072 + if (mp_count_bits(a) == 1536) + err = sp_ModExp_1536(b, &r, a, &y); + else if (mp_count_bits(a) == 3072) + err = sp_ModExp_3072(b, &r, a, &y); + else +#endif +#endif + err = mp_exptmod (b, &r, a, &y); + if (err != MP_OKAY) + goto LBL_Y; + + /* if y != 1 and y != n1 do */ + if (mp_cmp_d (&y, 1) != MP_EQ && mp_cmp (&y, &n1) != MP_EQ) { + j = 1; + /* while j <= s-1 and y != n1 */ + while ((j <= (s - 1)) && mp_cmp (&y, &n1) != MP_EQ) { + if ((err = mp_sqrmod (&y, a, &y)) != MP_OKAY) { + goto LBL_Y; + } + + /* if y == 1 then composite */ + if (mp_cmp_d (&y, 1) == MP_EQ) { + goto LBL_Y; + } + + ++j; + } + + /* if y != n1 then composite */ + if (mp_cmp (&y, &n1) != MP_EQ) { + goto LBL_Y; + } + } + + /* probably prime now */ + *result = MP_YES; +LBL_Y:mp_clear (&y); +LBL_R:mp_clear (&r); +LBL_N1:mp_clear (&n1); + return err; +} + + +/* determines if an integers is divisible by one + * of the first PRIME_SIZE primes or not + * + * sets result to 0 if not, 1 if yes + */ +static int mp_prime_is_divisible (mp_int * a, int *result) +{ + int err, ix; + mp_digit res; + + /* default to not */ + *result = MP_NO; + + for (ix = 0; ix < PRIME_SIZE; ix++) { + /* what is a mod LBL_prime_tab[ix] */ + if ((err = mp_mod_d (a, ltm_prime_tab[ix], &res)) != MP_OKAY) { + return err; + } + + /* is the residue zero? */ + if (res == 0) { + *result = MP_YES; + return MP_OKAY; + } + } + + return MP_OKAY; +} + +/* + * Sets result to 1 if probably prime, 0 otherwise + */ +int mp_prime_is_prime (mp_int * a, int t, int *result) +{ + mp_int b; + int ix, err, res; + + /* default to no */ + *result = MP_NO; + + /* valid value of t? */ + if (t <= 0 || t > PRIME_SIZE) { + return MP_VAL; + } + + /* is the input equal to one of the primes in the table? */ + for (ix = 0; ix < PRIME_SIZE; ix++) { + if (mp_cmp_d(a, ltm_prime_tab[ix]) == MP_EQ) { + *result = 1; + return MP_OKAY; + } + } + + /* first perform trial division */ + if ((err = mp_prime_is_divisible (a, &res)) != MP_OKAY) { + return err; + } + + /* return if it was trivially divisible */ + if (res == MP_YES) { + return MP_OKAY; + } + + /* now perform the miller-rabin rounds */ + if ((err = mp_init (&b)) != MP_OKAY) { + return err; + } + + for (ix = 0; ix < t; ix++) { + /* set the prime */ + if ((err = mp_set (&b, ltm_prime_tab[ix])) != MP_OKAY) { + goto LBL_B; + } + + if ((err = mp_prime_miller_rabin (a, &b, &res)) != MP_OKAY) { + goto LBL_B; + } + + if (res == MP_NO) { + goto LBL_B; + } + } + + /* passed the test */ + *result = MP_YES; +LBL_B:mp_clear (&b); + return err; +} + + +/* + * Sets result to 1 if probably prime, 0 otherwise + */ +int mp_prime_is_prime_ex (mp_int * a, int t, int *result, WC_RNG *rng) +{ + mp_int b, c; + int ix, err, res; + byte* base = NULL; + word32 baseSz = 0; + + /* default to no */ + *result = MP_NO; + + /* valid value of t? */ + if (t <= 0 || t > PRIME_SIZE) { + return MP_VAL; + } + + /* is the input equal to one of the primes in the table? */ + for (ix = 0; ix < PRIME_SIZE; ix++) { + if (mp_cmp_d(a, ltm_prime_tab[ix]) == MP_EQ) { + *result = MP_YES; + return MP_OKAY; + } + } + + /* first perform trial division */ + if ((err = mp_prime_is_divisible (a, &res)) != MP_OKAY) { + return err; + } + + /* return if it was trivially divisible */ + if (res == MP_YES) { + return MP_OKAY; + } + + /* now perform the miller-rabin rounds */ + if ((err = mp_init (&b)) != MP_OKAY) { + return err; + } + if ((err = mp_init (&c)) != MP_OKAY) { + mp_clear(&b); + return err; + } + + baseSz = mp_count_bits(a); + baseSz = (baseSz / 8) + ((baseSz % 8) ? 1 : 0); + + base = (byte*)XMALLOC(baseSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (base == NULL) { + err = MP_MEM; + goto LBL_B; + } + + if ((err = mp_sub_d(a, 2, &c)) != MP_OKAY) { + goto LBL_B; + } + + /* now do a miller rabin with up to t random numbers, this should + * give a (1/4)^t chance of a false prime. */ + for (ix = 0; ix < t; ix++) { + /* Set a test candidate. */ + if ((err = wc_RNG_GenerateBlock(rng, base, baseSz)) != 0) { + goto LBL_B; + } + + if ((err = mp_read_unsigned_bin(&b, base, baseSz)) != MP_OKAY) { + goto LBL_B; + } + + if (mp_cmp_d(&b, 2) != MP_GT || mp_cmp(&b, &c) != MP_LT) { + ix--; + continue; + } + + if ((err = mp_prime_miller_rabin (a, &b, &res)) != MP_OKAY) { + goto LBL_B; + } + + if (res == MP_NO) { + goto LBL_B; + } + } + + /* passed the test */ + *result = MP_YES; +LBL_B:mp_clear (&b); + mp_clear (&c); + XFREE(base, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return err; +} + +#endif /* WOLFSSL_KEY_GEN NO_DH NO_DSA NO_RSA */ + +#ifdef WOLFSSL_KEY_GEN + +static const int USE_BBS = 1; + +int mp_rand_prime(mp_int* N, int len, WC_RNG* rng, void* heap) +{ + int err, res, type; + byte* buf; + + if (N == NULL || rng == NULL) + return MP_VAL; + + /* get type */ + if (len < 0) { + type = USE_BBS; + len = -len; + } else { + type = 0; + } + + /* allow sizes between 2 and 512 bytes for a prime size */ + if (len < 2 || len > 512) { + return MP_VAL; + } + + /* allocate buffer to work with */ + buf = (byte*)XMALLOC(len, heap, DYNAMIC_TYPE_RSA); + if (buf == NULL) { + return MP_MEM; + } + XMEMSET(buf, 0, len); + + do { +#ifdef SHOW_GEN + printf("."); + fflush(stdout); +#endif + /* generate value */ + err = wc_RNG_GenerateBlock(rng, buf, len); + if (err != 0) { + XFREE(buf, heap, DYNAMIC_TYPE_RSA); + return err; + } + + /* munge bits */ + buf[0] |= 0x80 | 0x40; + buf[len-1] |= 0x01 | ((type & USE_BBS) ? 0x02 : 0x00); + + /* load value */ + if ((err = mp_read_unsigned_bin(N, buf, len)) != MP_OKAY) { + XFREE(buf, heap, DYNAMIC_TYPE_RSA); + return err; + } + + /* test */ + /* Running Miller-Rabin up to 3 times gives us a 2^{-80} chance + * of a 1024-bit candidate being a false positive, when it is our + * prime candidate. (Note 4.49 of Handbook of Applied Cryptography.) + * Using 8 because we've always used 8. */ + if ((err = mp_prime_is_prime_ex(N, 8, &res, rng)) != MP_OKAY) { + XFREE(buf, heap, DYNAMIC_TYPE_RSA); + return err; + } + } while (res == MP_NO); + + XMEMSET(buf, 0, len); + XFREE(buf, heap, DYNAMIC_TYPE_RSA); + + return MP_OKAY; +} + + +/* computes least common multiple as |a*b|/(a, b) */ +int mp_lcm (mp_int * a, mp_int * b, mp_int * c) +{ + int res; + mp_int t1, t2; + + + if ((res = mp_init_multi (&t1, &t2, NULL, NULL, NULL, NULL)) != MP_OKAY) { + return res; + } + + /* t1 = get the GCD of the two inputs */ + if ((res = mp_gcd (a, b, &t1)) != MP_OKAY) { + goto LBL_T; + } + + /* divide the smallest by the GCD */ + if (mp_cmp_mag(a, b) == MP_LT) { + /* store quotient in t2 such that t2 * b is the LCM */ + if ((res = mp_div(a, &t1, &t2, NULL)) != MP_OKAY) { + goto LBL_T; + } + res = mp_mul(b, &t2, c); + } else { + /* store quotient in t2 such that t2 * a is the LCM */ + if ((res = mp_div(b, &t1, &t2, NULL)) != MP_OKAY) { + goto LBL_T; + } + res = mp_mul(a, &t2, c); + } + + /* fix the sign to positive */ + c->sign = MP_ZPOS; + +LBL_T: + mp_clear(&t1); + mp_clear(&t2); + return res; +} + + + +/* Greatest Common Divisor using the binary method */ +int mp_gcd (mp_int * a, mp_int * b, mp_int * c) +{ + mp_int u, v; + int k, u_lsb, v_lsb, res; + + /* either zero than gcd is the largest */ + if (mp_iszero (a) == MP_YES) { + return mp_abs (b, c); + } + if (mp_iszero (b) == MP_YES) { + return mp_abs (a, c); + } + + /* get copies of a and b we can modify */ + if ((res = mp_init_copy (&u, a)) != MP_OKAY) { + return res; + } + + if ((res = mp_init_copy (&v, b)) != MP_OKAY) { + goto LBL_U; + } + + /* must be positive for the remainder of the algorithm */ + u.sign = v.sign = MP_ZPOS; + + /* B1. Find the common power of two for u and v */ + u_lsb = mp_cnt_lsb(&u); + v_lsb = mp_cnt_lsb(&v); + k = MIN(u_lsb, v_lsb); + + if (k > 0) { + /* divide the power of two out */ + if ((res = mp_div_2d(&u, k, &u, NULL)) != MP_OKAY) { + goto LBL_V; + } + + if ((res = mp_div_2d(&v, k, &v, NULL)) != MP_OKAY) { + goto LBL_V; + } + } + + /* divide any remaining factors of two out */ + if (u_lsb != k) { + if ((res = mp_div_2d(&u, u_lsb - k, &u, NULL)) != MP_OKAY) { + goto LBL_V; + } + } + + if (v_lsb != k) { + if ((res = mp_div_2d(&v, v_lsb - k, &v, NULL)) != MP_OKAY) { + goto LBL_V; + } + } + + while (mp_iszero(&v) == MP_NO) { + /* make sure v is the largest */ + if (mp_cmp_mag(&u, &v) == MP_GT) { + /* swap u and v to make sure v is >= u */ + mp_exch(&u, &v); + } + + /* subtract smallest from largest */ + if ((res = s_mp_sub(&v, &u, &v)) != MP_OKAY) { + goto LBL_V; + } + + /* Divide out all factors of two */ + if ((res = mp_div_2d(&v, mp_cnt_lsb(&v), &v, NULL)) != MP_OKAY) { + goto LBL_V; + } + } + + /* multiply by 2**k which we divided out at the beginning */ + if ((res = mp_mul_2d (&u, k, c)) != MP_OKAY) { + goto LBL_V; + } + c->sign = MP_ZPOS; + res = MP_OKAY; +LBL_V:mp_clear (&v); +LBL_U:mp_clear (&u); + return res; +} + +#endif /* WOLFSSL_KEY_GEN */ + + +#if !defined(NO_DSA) || defined(HAVE_ECC) || defined(WOLFSSL_KEY_GEN) || \ + defined(HAVE_COMP_KEY) || defined(WOLFSSL_DEBUG_MATH) || \ + defined(DEBUG_WOLFSSL) || defined(OPENSSL_EXTRA) + +/* chars used in radix conversions */ +const char *mp_s_rmap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ\ + abcdefghijklmnopqrstuvwxyz+/"; +#endif + +#if !defined(NO_DSA) || defined(HAVE_ECC) +/* read a string [ASCII] in a given radix */ +int mp_read_radix (mp_int * a, const char *str, int radix) +{ + int y, res, neg; + char ch; + + /* zero the digit bignum */ + mp_zero(a); + + /* make sure the radix is ok */ + if (radix < MP_RADIX_BIN || radix > MP_RADIX_MAX) { + return MP_VAL; + } + + /* if the leading digit is a + * minus set the sign to negative. + */ + if (*str == '-') { + ++str; + neg = MP_NEG; + } else { + neg = MP_ZPOS; + } + + /* set the integer to the default of zero */ + mp_zero (a); + + /* process each digit of the string */ + while (*str != '\0') { + /* if the radix <= 36 the conversion is case insensitive + * this allows numbers like 1AB and 1ab to represent the same value + * [e.g. in hex] + */ + ch = (radix <= 36) ? (char)XTOUPPER((unsigned char)*str) : *str; + for (y = 0; y < 64; y++) { + if (ch == mp_s_rmap[y]) { + break; + } + } + + /* if the char was found in the map + * and is less than the given radix add it + * to the number, otherwise exit the loop. + */ + if (y < radix) { + if ((res = mp_mul_d (a, (mp_digit) radix, a)) != MP_OKAY) { + return res; + } + if ((res = mp_add_d (a, (mp_digit) y, a)) != MP_OKAY) { + return res; + } + } else { + break; + } + ++str; + } + + /* if digit in isn't null term, then invalid character was found */ + if (*str != '\0') { + mp_zero (a); + return MP_VAL; + } + + /* set the sign only if a != 0 */ + if (mp_iszero(a) != MP_YES) { + a->sign = neg; + } + return MP_OKAY; +} +#endif /* !defined(NO_DSA) || defined(HAVE_ECC) */ + +#ifdef WC_MP_TO_RADIX + +/* returns size of ASCII representation */ +int mp_radix_size (mp_int *a, int radix, int *size) +{ + int res, digs; + mp_int t; + mp_digit d; + + *size = 0; + + /* special case for binary */ + if (radix == MP_RADIX_BIN) { + *size = mp_count_bits (a) + (a->sign == MP_NEG ? 1 : 0) + 1; + return MP_OKAY; + } + + /* make sure the radix is in range */ + if (radix < MP_RADIX_BIN || radix > MP_RADIX_MAX) { + return MP_VAL; + } + + if (mp_iszero(a) == MP_YES) { + *size = 2; + return MP_OKAY; + } + + /* digs is the digit count */ + digs = 0; + + /* if it's negative add one for the sign */ + if (a->sign == MP_NEG) { + ++digs; + } + + /* init a copy of the input */ + if ((res = mp_init_copy (&t, a)) != MP_OKAY) { + return res; + } + + /* force temp to positive */ + t.sign = MP_ZPOS; + + /* fetch out all of the digits */ + while (mp_iszero (&t) == MP_NO) { + if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) { + mp_clear (&t); + return res; + } + ++digs; + } + mp_clear (&t); + + /* return digs + 1, the 1 is for the NULL byte that would be required. */ + *size = digs + 1; + return MP_OKAY; +} + +/* stores a bignum as a ASCII string in a given radix (2..64) */ +int mp_toradix (mp_int *a, char *str, int radix) +{ + int res, digs; + mp_int t; + mp_digit d; + char *_s = str; + + /* check range of the radix */ + if (radix < MP_RADIX_BIN || radix > MP_RADIX_MAX) { + return MP_VAL; + } + + /* quick out if its zero */ + if (mp_iszero(a) == MP_YES) { + *str++ = '0'; + *str = '\0'; + return MP_OKAY; + } + + if ((res = mp_init_copy (&t, a)) != MP_OKAY) { + return res; + } + + /* if it is negative output a - */ + if (t.sign == MP_NEG) { + ++_s; + *str++ = '-'; + t.sign = MP_ZPOS; + } + + digs = 0; + while (mp_iszero (&t) == MP_NO) { + if ((res = mp_div_d (&t, (mp_digit) radix, &t, &d)) != MP_OKAY) { + mp_clear (&t); + return res; + } + *str++ = mp_s_rmap[d]; + ++digs; + } + + /* reverse the digits of the string. In this case _s points + * to the first digit [excluding the sign] of the number] + */ + bn_reverse ((unsigned char *)_s, digs); + + /* append a NULL so the string is properly terminated */ + *str = '\0'; + + mp_clear (&t); + return MP_OKAY; +} + +#ifdef WOLFSSL_DEBUG_MATH +void mp_dump(const char* desc, mp_int* a, byte verbose) +{ + char *buffer; + int size = a->alloc; + + buffer = (char*)XMALLOC(size * sizeof(mp_digit) * 2, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (buffer == NULL) { + return; + } + + printf("%s: ptr=%p, used=%d, sign=%d, size=%d, mpd=%d\n", + desc, a, a->used, a->sign, size, (int)sizeof(mp_digit)); + + mp_tohex(a, buffer); + printf(" %s\n ", buffer); + + if (verbose) { + int i; + for(i=0; ialloc * (int)sizeof(mp_digit); i++) { + printf("%02x ", *(((byte*)a->dp) + i)); + } + printf("\n"); + } + + XFREE(buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER); +} +#endif /* WOLFSSL_DEBUG_MATH */ + +#endif /* WC_MP_TO_RADIX */ + +#endif /* WOLFSSL_SP_MATH */ + +#endif /* USE_FAST_MATH */ + +#endif /* NO_BIG_INT */ + diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/logging.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/logging.c new file mode 100755 index 0000000..e5a6e52 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/logging.c @@ -0,0 +1,784 @@ +/* logging.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#include +#include +#if defined(OPENSSL_EXTRA) && !defined(WOLFCRYPT_ONLY) +/* avoid adding WANT_READ and WANT_WRITE to error queue */ +#include +#endif + +#if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) +static wolfSSL_Mutex debug_mutex; /* mutex for access to debug structure */ + +/* accessing any node from the queue should be wrapped in a lock of + * debug_mutex */ +static void* wc_error_heap; +struct wc_error_queue { + void* heap; /* the heap hint used with nodes creation */ + struct wc_error_queue* next; + struct wc_error_queue* prev; + char error[WOLFSSL_MAX_ERROR_SZ]; + char file[WOLFSSL_MAX_ERROR_SZ]; + int value; + int line; +}; +volatile struct wc_error_queue* wc_errors; +static struct wc_error_queue* wc_current_node; +static struct wc_error_queue* wc_last_node; +/* pointer to last node in queue to make insertion O(1) */ +#endif + +#ifdef WOLFSSL_FUNC_TIME +/* WARNING: This code is only to be used for debugging performance. + * The code is not thread-safe. + * Do not use WOLFSSL_FUNC_TIME in production code. + */ +static double wc_func_start[WC_FUNC_COUNT]; +static double wc_func_time[WC_FUNC_COUNT] = { 0, }; +static const char* wc_func_name[WC_FUNC_COUNT] = { + "SendHelloRequest", + "DoHelloRequest", + "SendClientHello", + "DoClientHello", + "SendServerHello", + "DoServerHello", + "SendEncryptedExtensions", + "DoEncryptedExtensions", + "SendCertificateRequest", + "DoCertificateRequest", + "SendCertificate", + "DoCertificate", + "SendCertificateVerify", + "DoCertificateVerify", + "SendFinished", + "DoFinished", + "SendKeyUpdate", + "DoKeyUpdate", + "SendEarlyData", + "DoEarlyData", + "SendNewSessionTicket", + "DoNewSessionTicket", + "SendServerHelloDone", + "DoServerHelloDone", + "SendTicket", + "DoTicket", + "SendClientKeyExchange", + "DoClientKeyExchange", + "SendCertificateStatus", + "DoCertificateStatus", + "SendServerKeyExchange", + "DoServerKeyExchange", + "SendEarlyData", + "DoEarlyData", +}; + +#include + +/* WARNING: This function is not portable. */ +static WC_INLINE double current_time(int reset) +{ + struct timeval tv; + gettimeofday(&tv, 0); + (void)reset; + + return (double)tv.tv_sec + (double)tv.tv_usec / 1000000; +} +#endif /* WOLFSSL_FUNC_TIME */ + +#ifdef DEBUG_WOLFSSL + +/* Set these to default values initially. */ +static wolfSSL_Logging_cb log_function = NULL; +static int loggingEnabled = 0; + +#if defined(WOLFSSL_APACHE_MYNEWT) +#include "log/log.h" +static struct log mynewt_log; +#endif /* WOLFSSL_APACHE_MYNEWT */ + +#endif /* DEBUG_WOLFSSL */ + + +/* allow this to be set to NULL, so logs can be redirected to default output */ +int wolfSSL_SetLoggingCb(wolfSSL_Logging_cb f) +{ +#ifdef DEBUG_WOLFSSL + log_function = f; + return 0; +#else + (void)f; + return NOT_COMPILED_IN; +#endif +} + + +int wolfSSL_Debugging_ON(void) +{ +#ifdef DEBUG_WOLFSSL + loggingEnabled = 1; +#if defined(WOLFSSL_APACHE_MYNEWT) + log_register("wolfcrypt", &mynewt_log, &log_console_handler, NULL, LOG_SYSLEVEL); +#endif /* WOLFSSL_APACHE_MYNEWT */ + return 0; +#else + return NOT_COMPILED_IN; +#endif +} + + +void wolfSSL_Debugging_OFF(void) +{ +#ifdef DEBUG_WOLFSSL + loggingEnabled = 0; +#endif +} + +#ifdef WOLFSSL_FUNC_TIME +/* WARNING: This code is only to be used for debugging performance. + * The code is not thread-safe. + * Do not use WOLFSSL_FUNC_TIME in production code. + */ +void WOLFSSL_START(int funcNum) +{ + double now = current_time(0) * 1000.0; +#ifdef WOLFSSL_FUNC_TIME_LOG + fprintf(stderr, "%17.3f: START - %s\n", now, wc_func_name[funcNum]); +#endif + wc_func_start[funcNum] = now; +} + +void WOLFSSL_END(int funcNum) +{ + double now = current_time(0) * 1000.0; + wc_func_time[funcNum] += now - wc_func_start[funcNum]; +#ifdef WOLFSSL_FUNC_TIME_LOG + fprintf(stderr, "%17.3f: END - %s\n", now, wc_func_name[funcNum]); +#endif +} + +void WOLFSSL_TIME(int count) +{ + int i; + double avg, total = 0; + + for (i = 0; i < WC_FUNC_COUNT; i++) { + if (wc_func_time[i] > 0) { + avg = wc_func_time[i] / count; + fprintf(stderr, "%8.3f ms: %s\n", avg, wc_func_name[i]); + total += avg; + } + } + fprintf(stderr, "%8.3f ms\n", total); +} +#endif + +#ifdef DEBUG_WOLFSSL + +#if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) + #if MQX_USE_IO_OLD + #include + #else + #include + #endif +#elif defined(WOLFSSL_SGX) + /* Declare sprintf for ocall */ + int sprintf(char* buf, const char *fmt, ...); +#elif defined(WOLFSSL_DEOS) +#elif defined(MICRIUM) + #if (BSP_SER_COMM_EN == DEF_ENABLED) + #include + #endif +#elif defined(WOLFSSL_USER_LOG) + /* user includes their own headers */ +#elif defined(WOLFSSL_ESPIDF) + #include "esp_types.h" + #include "esp_log.h" +#elif defined(WOLFSSL_TELIT_M2MB) + #include + #include "m2m_log.h" +#else + #include /* for default printf stuff */ +#endif + +#if defined(THREADX) && !defined(THREADX_NO_DC_PRINTF) + int dc_log_printf(char*, ...); +#endif + +static void wolfssl_log(const int logLevel, const char *const logMessage) +{ + if (log_function) + log_function(logLevel, logMessage); + else { +#if defined(WOLFSSL_USER_LOG) + WOLFSSL_USER_LOG(logMessage); +#elif defined(WOLFSSL_LOG_PRINTF) + printf("%s\n", logMessage); + +#elif defined(THREADX) && !defined(THREADX_NO_DC_PRINTF) + dc_log_printf("%s\n", logMessage); +#elif defined(WOLFSSL_DEOS) + printf("%s\r\n", logMessage); +#elif defined(MICRIUM) + BSP_Ser_Printf("%s\r\n", logMessage); +#elif defined(WOLFSSL_MDK_ARM) + fflush(stdout) ; + printf("%s\n", logMessage); + fflush(stdout) ; +#elif defined(WOLFSSL_UTASKER) + fnDebugMsg((char*)logMessage); + fnDebugMsg("\r\n"); +#elif defined(MQX_USE_IO_OLD) + fprintf(_mqxio_stderr, "%s\n", logMessage); + +#elif defined(WOLFSSL_APACHE_MYNEWT) + LOG_DEBUG(&mynewt_log, LOG_MODULE_DEFAULT, "%s\n", logMessage); +#elif defined(WOLFSSL_ESPIDF) + ESP_LOGI("wolfssl", "%s", logMessage); +#elif defined(WOLFSSL_ZEPHYR) + printk("%s\n", logMessage); +#elif defined(WOLFSSL_TELIT_M2MB) + M2M_LOG_INFO("%s\n", logMessage); +#else + fprintf(stderr, "%s\n", logMessage); +#endif + } +} + +#ifndef WOLFSSL_DEBUG_ERRORS_ONLY +void WOLFSSL_MSG(const char* msg) +{ + if (loggingEnabled) + wolfssl_log(INFO_LOG , msg); +} + + +void WOLFSSL_BUFFER(const byte* buffer, word32 length) +{ + #define LINE_LEN 16 + + if (loggingEnabled) { + word32 i; + char line[80]; + + if (!buffer) { + wolfssl_log(INFO_LOG, "\tNULL"); + + return; + } + + sprintf(line, "\t"); + + for (i = 0; i < LINE_LEN; i++) { + if (i < length) + sprintf(line + 1 + i * 3,"%02x ", buffer[i]); + else + sprintf(line + 1 + i * 3, " "); + } + + sprintf(line + 1 + LINE_LEN * 3, "| "); + + for (i = 0; i < LINE_LEN; i++) + if (i < length) + sprintf(line + 3 + LINE_LEN * 3 + i, + "%c", 31 < buffer[i] && buffer[i] < 127 ? buffer[i] : '.'); + + wolfssl_log(INFO_LOG, line); + + if (length > LINE_LEN) + WOLFSSL_BUFFER(buffer + LINE_LEN, length - LINE_LEN); + } +} + + +void WOLFSSL_ENTER(const char* msg) +{ + if (loggingEnabled) { + char buffer[WOLFSSL_MAX_ERROR_SZ]; + XSNPRINTF(buffer, sizeof(buffer), "wolfSSL Entering %s", msg); + wolfssl_log(ENTER_LOG , buffer); + } +} + + +void WOLFSSL_LEAVE(const char* msg, int ret) +{ + if (loggingEnabled) { + char buffer[WOLFSSL_MAX_ERROR_SZ]; + XSNPRINTF(buffer, sizeof(buffer), "wolfSSL Leaving %s, return %d", + msg, ret); + wolfssl_log(LEAVE_LOG , buffer); + } +} +#endif /* !WOLFSSL_DEBUG_ERRORS_ONLY */ +#endif /* DEBUG_WOLFSSL */ + +/* + * When using OPENSSL_EXTRA or DEBUG_WOLFSSL_VERBOSE macro then WOLFSSL_ERROR is + * mapped to new funtion WOLFSSL_ERROR_LINE which gets the line # and function + * name where WOLFSSL_ERROR is called at. + */ +#if defined(DEBUG_WOLFSSL) || defined(OPENSSL_ALL) || \ + defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + +#if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) +void WOLFSSL_ERROR_LINE(int error, const char* func, unsigned int line, + const char* file, void* usrCtx) +#else +void WOLFSSL_ERROR(int error) +#endif +{ +#ifdef WOLFSSL_ASYNC_CRYPT + if (error != WC_PENDING_E) +#endif + { + char buffer[WOLFSSL_MAX_ERROR_SZ]; + + #if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) + (void)usrCtx; /* a user ctx for future flexibility */ + (void)func; + + if (wc_LockMutex(&debug_mutex) != 0) { + WOLFSSL_MSG("Lock debug mutex failed"); + XSNPRINTF(buffer, sizeof(buffer), + "wolfSSL error occurred, error = %d", error); + } + else { + #if defined(OPENSSL_EXTRA) && !defined(WOLFCRYPT_ONLY) + /* If running in compatibility mode do not add want read and + want right to error queue */ + if (error != WANT_READ && error != WANT_WRITE) { + #endif + if (error < 0) + error = error - (2 * error); /* get absolute value */ + XSNPRINTF(buffer, sizeof(buffer), + "wolfSSL error occurred, error = %d line:%d file:%s", + error, line, file); + if (wc_AddErrorNode(error, line, buffer, (char*)file) != 0) { + WOLFSSL_MSG("Error creating logging node"); + /* with void function there is no return here, continue on + * to unlock mutex and log what buffer was created. */ + } + #if defined(OPENSSL_EXTRA) && !defined(WOLFCRYPT_ONLY) + } + else { + XSNPRINTF(buffer, sizeof(buffer), + "wolfSSL error occurred, error = %d", error); + + } + #endif + + wc_UnLockMutex(&debug_mutex); + } + #else + XSNPRINTF(buffer, sizeof(buffer), + "wolfSSL error occurred, error = %d", error); + #endif + + #ifdef DEBUG_WOLFSSL + if (loggingEnabled) + wolfssl_log(ERROR_LOG , buffer); + #endif + } +} + +void WOLFSSL_ERROR_MSG(const char* msg) +{ +#ifdef DEBUG_WOLFSSL + if (loggingEnabled) + wolfssl_log(ERROR_LOG , msg); +#else + (void)msg; +#endif +} + +#endif /* DEBUG_WOLFSSL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */ + +#if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) +/* Internal function that is called by wolfCrypt_Init() */ +int wc_LoggingInit(void) +{ + if (wc_InitMutex(&debug_mutex) != 0) { + WOLFSSL_MSG("Bad Init Mutex"); + return BAD_MUTEX_E; + } + wc_errors = NULL; + wc_current_node = NULL; + wc_last_node = NULL; + + return 0; +} + + +/* internal function that is called by wolfCrypt_Cleanup */ +int wc_LoggingCleanup(void) +{ + /* clear logging entries */ + wc_ClearErrorNodes(); + + /* free mutex */ + if (wc_FreeMutex(&debug_mutex) != 0) { + WOLFSSL_MSG("Bad Mutex free"); + return BAD_MUTEX_E; + } + return 0; +} + + +/* peek at an error node + * + * idx : if -1 then the most recent node is looked at, otherwise search + * through queue for node at the given index + * file : pointer to internal file string + * reason : pointer to internal error reason + * line : line number that error happened at + * + * Returns a negative value in error case, on success returns the nodes error + * value which is positve (absolute value) + */ +int wc_PeekErrorNode(int idx, const char **file, const char **reason, + int *line) +{ + struct wc_error_queue* err; + + if (wc_LockMutex(&debug_mutex) != 0) { + WOLFSSL_MSG("Lock debug mutex failed"); + return BAD_MUTEX_E; + } + + if (idx < 0) { + err = wc_last_node; + if (err == NULL) { + WOLFSSL_MSG("No Errors in queue"); + wc_UnLockMutex(&debug_mutex); + return BAD_STATE_E; + } + } + else { + int i; + + err = (struct wc_error_queue*)wc_errors; + for (i = 0; i < idx; i++) { + if (err == NULL) { + WOLFSSL_MSG("Error node not found. Bad index?"); + wc_UnLockMutex(&debug_mutex); + return BAD_FUNC_ARG; + } + err = err->next; + } + } + + if (file != NULL) { + *file = err->file; + } + + if (reason != NULL) { + *reason = err->error; + } + + if (line != NULL) { + *line = err->line; + } + + wc_UnLockMutex(&debug_mutex); + + return err->value; +} + + +/* Pulls the current node from error queue and increments current state. + * Note: this does not delete nodes because input arguments are pointing to + * node buffers. + * + * file pointer to file that error was in. Can be NULL to return no file. + * reason error string giving reason for error. Can be NULL to return no reason. + * line return line number of where error happened. + * + * returns the error value on success and BAD_MUTEX_E or BAD_STATE_E on failure + */ +int wc_PullErrorNode(const char **file, const char **reason, int *line) +{ + struct wc_error_queue* err; + int value; + + if (wc_LockMutex(&debug_mutex) != 0) { + WOLFSSL_MSG("Lock debug mutex failed"); + return BAD_MUTEX_E; + } + + err = wc_current_node; + if (err == NULL) { + WOLFSSL_MSG("No Errors in queue"); + wc_UnLockMutex(&debug_mutex); + return BAD_STATE_E; + } + + if (file != NULL) { + *file = err->file; + } + + if (reason != NULL) { + *reason = err->error; + } + + if (line != NULL) { + *line = err->line; + } + + value = err->value; + wc_current_node = err->next; + wc_UnLockMutex(&debug_mutex); + + return value; +} + + +/* create new error node and add it to the queue + * buffers are assumed to be of size WOLFSSL_MAX_ERROR_SZ for this internal + * function. debug_mutex should be locked before a call to this function. */ +int wc_AddErrorNode(int error, int line, char* buf, char* file) +{ + + struct wc_error_queue* err; + + err = (struct wc_error_queue*)XMALLOC( + sizeof(struct wc_error_queue), wc_error_heap, DYNAMIC_TYPE_LOG); + if (err == NULL) { + WOLFSSL_MSG("Unable to create error node for log"); + return MEMORY_E; + } + else { + int sz; + + XMEMSET(err, 0, sizeof(struct wc_error_queue)); + err->heap = wc_error_heap; + sz = (int)XSTRLEN(buf); + if (sz > WOLFSSL_MAX_ERROR_SZ - 1) { + sz = WOLFSSL_MAX_ERROR_SZ - 1; + } + if (sz > 0) { + XMEMCPY(err->error, buf, sz); + } + + sz = (int)XSTRLEN(file); + if (sz > WOLFSSL_MAX_ERROR_SZ - 1) { + sz = WOLFSSL_MAX_ERROR_SZ - 1; + } + if (sz > 0) { + XMEMCPY(err->file, file, sz); + } + + err->value = error; + err->line = line; + + /* make sure is terminated */ + err->error[WOLFSSL_MAX_ERROR_SZ - 1] = '\0'; + err->file[WOLFSSL_MAX_ERROR_SZ - 1] = '\0'; + + + /* since is queue place new node at last of the list */ + if (wc_last_node == NULL) { + /* case of first node added to queue */ + if (wc_errors != NULL) { + /* check for unexpected case before over writing wc_errors */ + WOLFSSL_MSG("ERROR in adding new node to logging queue!!\n"); + /* In the event both wc_last_node and wc_errors are NULL, err + * goes unassigned to external wc_errors, wc_last_node. Free + * err in this instance since wc_ClearErrorNodes will not + */ + XFREE(err, wc_error_heap, DYNAMIC_TYPE_LOG); + } + else { + wc_errors = err; + wc_last_node = err; + wc_current_node = err; + } + } + else { + wc_last_node->next = err; + err->prev = wc_last_node; + wc_last_node = err; + + /* check the case where have read to the end of the queue and the + * current node to read needs updated */ + if (wc_current_node == NULL) { + wc_current_node = err; + } + } + } + + return 0; +} + +/* Removes the error node at the specified index. + * idx : if -1 then the most recent node is looked at, otherwise search + * through queue for node at the given index + */ +void wc_RemoveErrorNode(int idx) +{ + struct wc_error_queue* current; + + if (wc_LockMutex(&debug_mutex) != 0) { + WOLFSSL_MSG("Lock debug mutex failed"); + return; + } + + if (idx == -1) + current = wc_last_node; + else { + current = (struct wc_error_queue*)wc_errors; + for (; current != NULL && idx > 0; idx--) + current = current->next; + } + if (current != NULL) { + if (current->prev != NULL) + current->prev->next = current->next; + if (wc_last_node == current) + wc_last_node = current->prev; + if (wc_errors == current) + wc_errors = current->next; + XFREE(current, current->heap, DYNAMIC_TYPE_LOG); + } + + wc_UnLockMutex(&debug_mutex); +} + + +/* Clears out the list of error nodes. + */ +void wc_ClearErrorNodes(void) +{ +#if defined(DEBUG_WOLFSSL) || defined(WOLFSSL_NGINX) || \ + defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) + + if (wc_LockMutex(&debug_mutex) != 0) { + WOLFSSL_MSG("Lock debug mutex failed"); + return; + } + + /* free all nodes from error queue */ + { + struct wc_error_queue* current; + struct wc_error_queue* next; + + current = (struct wc_error_queue*)wc_errors; + while (current != NULL) { + next = current->next; + XFREE(current, current->heap, DYNAMIC_TYPE_LOG); + current = next; + } + } + + wc_errors = NULL; + wc_last_node = NULL; + wc_current_node = NULL; + wc_UnLockMutex(&debug_mutex); +#endif /* DEBUG_WOLFSSL || WOLFSSL_NGINX */ +} + +int wc_SetLoggingHeap(void* h) +{ + if (wc_LockMutex(&debug_mutex) != 0) { + WOLFSSL_MSG("Lock debug mutex failed"); + return BAD_MUTEX_E; + } + wc_error_heap = h; + wc_UnLockMutex(&debug_mutex); + return 0; +} + + +/* frees all nodes in the queue + * + * id this is the thread id + */ +int wc_ERR_remove_state(void) +{ + struct wc_error_queue* current; + struct wc_error_queue* next; + + if (wc_LockMutex(&debug_mutex) != 0) { + WOLFSSL_MSG("Lock debug mutex failed"); + return BAD_MUTEX_E; + } + + /* free all nodes from error queue */ + current = (struct wc_error_queue*)wc_errors; + while (current != NULL) { + next = current->next; + XFREE(current, current->heap, DYNAMIC_TYPE_LOG); + current = next; + } + + wc_errors = NULL; + wc_last_node = NULL; + + wc_UnLockMutex(&debug_mutex); + + return 0; +} + + +#if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM) +/* empties out the error queue into the file */ +void wc_ERR_print_errors_fp(XFILE fp) +{ + WOLFSSL_ENTER("wc_ERR_print_errors_fp"); + + if (wc_LockMutex(&debug_mutex) != 0) + { + WOLFSSL_MSG("Lock debug mutex failed"); + } + else + { + /* free all nodes from error queue and print them to file */ + { + struct wc_error_queue *current; + struct wc_error_queue *next; + + current = (struct wc_error_queue *)wc_errors; + while (current != NULL) + { + next = current->next; + fprintf(fp, "%s\n", current->error); + XFREE(current, current->heap, DYNAMIC_TYPE_LOG); + current = next; + } + + /* set global pointers to match having been freed */ + wc_errors = NULL; + wc_last_node = NULL; + } + + wc_UnLockMutex(&debug_mutex); + } +} +#endif /* !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM) */ + +#endif /* defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) */ + diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/md2.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/md2.c new file mode 100755 index 0000000..724eb43 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/md2.c @@ -0,0 +1,162 @@ +/* md2.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifdef WOLFSSL_MD2 + +#include +#include + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + + +void wc_InitMd2(Md2* md2) +{ + XMEMSET(md2->X, 0, MD2_X_SIZE); + XMEMSET(md2->C, 0, MD2_BLOCK_SIZE); + XMEMSET(md2->buffer, 0, MD2_BLOCK_SIZE); + md2->count = 0; +} + + +void wc_Md2Update(Md2* md2, const byte* data, word32 len) +{ + static const byte S[256] = + { + 41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6, + 19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188, + 76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24, + 138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251, + 245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63, + 148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50, + 39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165, + 181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210, + 150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157, + 112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27, + 96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15, + 85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197, + 234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65, + 129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123, + 8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233, + 203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228, + 166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237, + 31, 26, 219, 153, 141, 51, 159, 17, 131, 20 + }; + + while (len) { + word32 L = (MD2_PAD_SIZE - md2->count) < len ? + (MD2_PAD_SIZE - md2->count) : len; + XMEMCPY(md2->buffer + md2->count, data, L); + md2->count += L; + data += L; + len -= L; + + if (md2->count == MD2_PAD_SIZE) { + int i; + byte t; + + md2->count = 0; + XMEMCPY(md2->X + MD2_PAD_SIZE, md2->buffer, MD2_PAD_SIZE); + t = md2->C[15]; + + for(i = 0; i < MD2_PAD_SIZE; i++) { + md2->X[32 + i] = md2->X[MD2_PAD_SIZE + i] ^ md2->X[i]; + t = md2->C[i] ^= S[md2->buffer[i] ^ t]; + } + + t=0; + for(i = 0; i < 18; i++) { + int j; + for(j = 0; j < MD2_X_SIZE; j += 8) { + t = md2->X[j+0] ^= S[t]; + t = md2->X[j+1] ^= S[t]; + t = md2->X[j+2] ^= S[t]; + t = md2->X[j+3] ^= S[t]; + t = md2->X[j+4] ^= S[t]; + t = md2->X[j+5] ^= S[t]; + t = md2->X[j+6] ^= S[t]; + t = md2->X[j+7] ^= S[t]; + } + t = (t + i) & 0xFF; + } + } + } +} + + +void wc_Md2Final(Md2* md2, byte* hash) +{ + byte padding[MD2_BLOCK_SIZE]; + word32 padLen = MD2_PAD_SIZE - md2->count; + word32 i; + + for (i = 0; i < padLen; i++) + padding[i] = (byte)padLen; + + wc_Md2Update(md2, padding, padLen); + wc_Md2Update(md2, md2->C, MD2_BLOCK_SIZE); + + XMEMCPY(hash, md2->X, MD2_DIGEST_SIZE); + + wc_InitMd2(md2); +} + + +int wc_Md2Hash(const byte* data, word32 len, byte* hash) +{ +#ifdef WOLFSSL_SMALL_STACK + Md2* md2; +#else + Md2 md2[1]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + md2 = (Md2*)XMALLOC(sizeof(Md2), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (md2 == NULL) + return MEMORY_E; +#endif + + wc_InitMd2(md2); + wc_Md2Update(md2, data, len); + wc_Md2Final(md2, hash); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(md2, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return 0; +} + + +#endif /* WOLFSSL_MD2 */ + diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/md4.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/md4.c new file mode 100755 index 0000000..b110d71 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/md4.c @@ -0,0 +1,211 @@ +/* md4.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifndef NO_MD4 + +#include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + + +void wc_InitMd4(Md4* md4) +{ + md4->digest[0] = 0x67452301L; + md4->digest[1] = 0xefcdab89L; + md4->digest[2] = 0x98badcfeL; + md4->digest[3] = 0x10325476L; + + md4->buffLen = 0; + md4->loLen = 0; + md4->hiLen = 0; +} + + +static void Transform(Md4* md4) +{ +#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z)))) +#define G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) + + /* Copy context->state[] to working vars */ + word32 A = md4->digest[0]; + word32 B = md4->digest[1]; + word32 C = md4->digest[2]; + word32 D = md4->digest[3]; + +#define function(a,b,c,d,k,s) a=rotlFixed(a+F(b,c,d)+md4->buffer[k],s); + function(A,B,C,D, 0, 3); + function(D,A,B,C, 1, 7); + function(C,D,A,B, 2,11); + function(B,C,D,A, 3,19); + function(A,B,C,D, 4, 3); + function(D,A,B,C, 5, 7); + function(C,D,A,B, 6,11); + function(B,C,D,A, 7,19); + function(A,B,C,D, 8, 3); + function(D,A,B,C, 9, 7); + function(C,D,A,B,10,11); + function(B,C,D,A,11,19); + function(A,B,C,D,12, 3); + function(D,A,B,C,13, 7); + function(C,D,A,B,14,11); + function(B,C,D,A,15,19); + +#undef function +#define function(a,b,c,d,k,s) \ + a=rotlFixed(a+G(b,c,d)+md4->buffer[k]+0x5a827999,s); + + function(A,B,C,D, 0, 3); + function(D,A,B,C, 4, 5); + function(C,D,A,B, 8, 9); + function(B,C,D,A,12,13); + function(A,B,C,D, 1, 3); + function(D,A,B,C, 5, 5); + function(C,D,A,B, 9, 9); + function(B,C,D,A,13,13); + function(A,B,C,D, 2, 3); + function(D,A,B,C, 6, 5); + function(C,D,A,B,10, 9); + function(B,C,D,A,14,13); + function(A,B,C,D, 3, 3); + function(D,A,B,C, 7, 5); + function(C,D,A,B,11, 9); + function(B,C,D,A,15,13); + +#undef function +#define function(a,b,c,d,k,s) \ + a=rotlFixed(a+H(b,c,d)+md4->buffer[k]+0x6ed9eba1,s); + + function(A,B,C,D, 0, 3); + function(D,A,B,C, 8, 9); + function(C,D,A,B, 4,11); + function(B,C,D,A,12,15); + function(A,B,C,D, 2, 3); + function(D,A,B,C,10, 9); + function(C,D,A,B, 6,11); + function(B,C,D,A,14,15); + function(A,B,C,D, 1, 3); + function(D,A,B,C, 9, 9); + function(C,D,A,B, 5,11); + function(B,C,D,A,13,15); + function(A,B,C,D, 3, 3); + function(D,A,B,C,11, 9); + function(C,D,A,B, 7,11); + function(B,C,D,A,15,15); + + /* Add the working vars back into digest state[] */ + md4->digest[0] += A; + md4->digest[1] += B; + md4->digest[2] += C; + md4->digest[3] += D; +} + + +static WC_INLINE void AddLength(Md4* md4, word32 len) +{ + word32 tmp = md4->loLen; + if ( (md4->loLen += len) < tmp) + md4->hiLen++; /* carry low to high */ +} + + +void wc_Md4Update(Md4* md4, const byte* data, word32 len) +{ + /* do block size increments */ + byte* local = (byte*)md4->buffer; + + while (len) { + word32 add = min(len, MD4_BLOCK_SIZE - md4->buffLen); + XMEMCPY(&local[md4->buffLen], data, add); + + md4->buffLen += add; + data += add; + len -= add; + + if (md4->buffLen == MD4_BLOCK_SIZE) { + #ifdef BIG_ENDIAN_ORDER + ByteReverseWords(md4->buffer, md4->buffer, MD4_BLOCK_SIZE); + #endif + Transform(md4); + AddLength(md4, MD4_BLOCK_SIZE); + md4->buffLen = 0; + } + } +} + + +void wc_Md4Final(Md4* md4, byte* hash) +{ + byte* local = (byte*)md4->buffer; + + AddLength(md4, md4->buffLen); /* before adding pads */ + + local[md4->buffLen++] = 0x80; /* add 1 */ + + /* pad with zeros */ + if (md4->buffLen > MD4_PAD_SIZE) { + XMEMSET(&local[md4->buffLen], 0, MD4_BLOCK_SIZE - md4->buffLen); + md4->buffLen += MD4_BLOCK_SIZE - md4->buffLen; + + #ifdef BIG_ENDIAN_ORDER + ByteReverseWords(md4->buffer, md4->buffer, MD4_BLOCK_SIZE); + #endif + Transform(md4); + md4->buffLen = 0; + } + XMEMSET(&local[md4->buffLen], 0, MD4_PAD_SIZE - md4->buffLen); + + /* put lengths in bits */ + md4->hiLen = (md4->loLen >> (8*sizeof(md4->loLen) - 3)) + + (md4->hiLen << 3); + md4->loLen = md4->loLen << 3; + + /* store lengths */ + #ifdef BIG_ENDIAN_ORDER + ByteReverseWords(md4->buffer, md4->buffer, MD4_BLOCK_SIZE); + #endif + /* ! length ordering dependent on digest endian type ! */ + XMEMCPY(&local[MD4_PAD_SIZE], &md4->loLen, sizeof(word32)); + XMEMCPY(&local[MD4_PAD_SIZE + sizeof(word32)], &md4->hiLen, sizeof(word32)); + + Transform(md4); + #ifdef BIG_ENDIAN_ORDER + ByteReverseWords(md4->digest, md4->digest, MD4_DIGEST_SIZE); + #endif + XMEMCPY(hash, md4->digest, MD4_DIGEST_SIZE); + + wc_InitMd4(md4); /* reset state */ +} + + +#endif /* NO_MD4 */ + diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/md5.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/md5.c new file mode 100755 index 0000000..5adce43 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/md5.c @@ -0,0 +1,465 @@ +/* md5.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#if !defined(NO_MD5) + +#if defined(WOLFSSL_TI_HASH) + /* #include included by wc_port.c */ + +#else + +#include +#include +#include +#include + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + + +/* Hardware Acceleration */ +#if defined(STM32_HASH) + + /* Supports CubeMX HAL or Standard Peripheral Library */ + #define HAVE_MD5_CUST_API + + int wc_InitMd5_ex(wc_Md5* md5, void* heap, int devId) + { + if (md5 == NULL) { + return BAD_FUNC_ARG; + } + + (void)devId; + (void)heap; + + wc_Stm32_Hash_Init(&md5->stmCtx); + + return 0; + } + + int wc_Md5Update(wc_Md5* md5, const byte* data, word32 len) + { + int ret; + + if (md5 == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + + ret = wolfSSL_CryptHwMutexLock(); + if (ret == 0) { + ret = wc_Stm32_Hash_Update(&md5->stmCtx, HASH_AlgoSelection_MD5, + data, len); + wolfSSL_CryptHwMutexUnLock(); + } + return ret; + } + + int wc_Md5Final(wc_Md5* md5, byte* hash) + { + int ret; + + if (md5 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + + ret = wolfSSL_CryptHwMutexLock(); + if (ret == 0) { + ret = wc_Stm32_Hash_Final(&md5->stmCtx, HASH_AlgoSelection_MD5, + hash, WC_MD5_DIGEST_SIZE); + wolfSSL_CryptHwMutexUnLock(); + } + + (void)wc_InitMd5(md5); /* reset state */ + + return ret; + } + +#elif defined(FREESCALE_MMCAU_SHA) + #include "cau_api.h" + #define XTRANSFORM(S,B) Transform((S), (B)) + + static int Transform(wc_Md5* md5, byte* data) + { + int ret = wolfSSL_CryptHwMutexLock(); + if(ret == 0) { + #ifdef FREESCALE_MMCAU_CLASSIC_SHA + cau_md5_hash_n(data, 1, (unsigned char*)md5->digest); + #else + MMCAU_MD5_HashN(data, 1, (uint32_t*)md5->digest); + #endif + wolfSSL_CryptHwMutexUnLock(); + } + return ret; + } + +#elif defined(WOLFSSL_PIC32MZ_HASH) + #include + #define HAVE_MD5_CUST_API + +#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH) + /* functions implemented in wolfcrypt/src/port/caam/caam_sha.c */ + #define HAVE_MD5_CUST_API +#else + #define NEED_SOFT_MD5 + +#endif /* End Hardware Acceleration */ + + +#ifdef NEED_SOFT_MD5 + + #define XTRANSFORM(S,B) Transform((S)) + + #define F1(x, y, z) (z ^ (x & (y ^ z))) + #define F2(x, y, z) F1(z, x, y) + #define F3(x, y, z) (x ^ y ^ z) + #define F4(x, y, z) (y ^ (x | ~z)) + + #define MD5STEP(f, w, x, y, z, data, s) \ + w = rotlFixed(w + f(x, y, z) + data, s) + x + + static int Transform(wc_Md5* md5) + { + /* Copy context->state[] to working vars */ + word32 a = md5->digest[0]; + word32 b = md5->digest[1]; + word32 c = md5->digest[2]; + word32 d = md5->digest[3]; + + MD5STEP(F1, a, b, c, d, md5->buffer[0] + 0xd76aa478, 7); + MD5STEP(F1, d, a, b, c, md5->buffer[1] + 0xe8c7b756, 12); + MD5STEP(F1, c, d, a, b, md5->buffer[2] + 0x242070db, 17); + MD5STEP(F1, b, c, d, a, md5->buffer[3] + 0xc1bdceee, 22); + MD5STEP(F1, a, b, c, d, md5->buffer[4] + 0xf57c0faf, 7); + MD5STEP(F1, d, a, b, c, md5->buffer[5] + 0x4787c62a, 12); + MD5STEP(F1, c, d, a, b, md5->buffer[6] + 0xa8304613, 17); + MD5STEP(F1, b, c, d, a, md5->buffer[7] + 0xfd469501, 22); + MD5STEP(F1, a, b, c, d, md5->buffer[8] + 0x698098d8, 7); + MD5STEP(F1, d, a, b, c, md5->buffer[9] + 0x8b44f7af, 12); + MD5STEP(F1, c, d, a, b, md5->buffer[10] + 0xffff5bb1, 17); + MD5STEP(F1, b, c, d, a, md5->buffer[11] + 0x895cd7be, 22); + MD5STEP(F1, a, b, c, d, md5->buffer[12] + 0x6b901122, 7); + MD5STEP(F1, d, a, b, c, md5->buffer[13] + 0xfd987193, 12); + MD5STEP(F1, c, d, a, b, md5->buffer[14] + 0xa679438e, 17); + MD5STEP(F1, b, c, d, a, md5->buffer[15] + 0x49b40821, 22); + + MD5STEP(F2, a, b, c, d, md5->buffer[1] + 0xf61e2562, 5); + MD5STEP(F2, d, a, b, c, md5->buffer[6] + 0xc040b340, 9); + MD5STEP(F2, c, d, a, b, md5->buffer[11] + 0x265e5a51, 14); + MD5STEP(F2, b, c, d, a, md5->buffer[0] + 0xe9b6c7aa, 20); + MD5STEP(F2, a, b, c, d, md5->buffer[5] + 0xd62f105d, 5); + MD5STEP(F2, d, a, b, c, md5->buffer[10] + 0x02441453, 9); + MD5STEP(F2, c, d, a, b, md5->buffer[15] + 0xd8a1e681, 14); + MD5STEP(F2, b, c, d, a, md5->buffer[4] + 0xe7d3fbc8, 20); + MD5STEP(F2, a, b, c, d, md5->buffer[9] + 0x21e1cde6, 5); + MD5STEP(F2, d, a, b, c, md5->buffer[14] + 0xc33707d6, 9); + MD5STEP(F2, c, d, a, b, md5->buffer[3] + 0xf4d50d87, 14); + MD5STEP(F2, b, c, d, a, md5->buffer[8] + 0x455a14ed, 20); + MD5STEP(F2, a, b, c, d, md5->buffer[13] + 0xa9e3e905, 5); + MD5STEP(F2, d, a, b, c, md5->buffer[2] + 0xfcefa3f8, 9); + MD5STEP(F2, c, d, a, b, md5->buffer[7] + 0x676f02d9, 14); + MD5STEP(F2, b, c, d, a, md5->buffer[12] + 0x8d2a4c8a, 20); + + MD5STEP(F3, a, b, c, d, md5->buffer[5] + 0xfffa3942, 4); + MD5STEP(F3, d, a, b, c, md5->buffer[8] + 0x8771f681, 11); + MD5STEP(F3, c, d, a, b, md5->buffer[11] + 0x6d9d6122, 16); + MD5STEP(F3, b, c, d, a, md5->buffer[14] + 0xfde5380c, 23); + MD5STEP(F3, a, b, c, d, md5->buffer[1] + 0xa4beea44, 4); + MD5STEP(F3, d, a, b, c, md5->buffer[4] + 0x4bdecfa9, 11); + MD5STEP(F3, c, d, a, b, md5->buffer[7] + 0xf6bb4b60, 16); + MD5STEP(F3, b, c, d, a, md5->buffer[10] + 0xbebfbc70, 23); + MD5STEP(F3, a, b, c, d, md5->buffer[13] + 0x289b7ec6, 4); + MD5STEP(F3, d, a, b, c, md5->buffer[0] + 0xeaa127fa, 11); + MD5STEP(F3, c, d, a, b, md5->buffer[3] + 0xd4ef3085, 16); + MD5STEP(F3, b, c, d, a, md5->buffer[6] + 0x04881d05, 23); + MD5STEP(F3, a, b, c, d, md5->buffer[9] + 0xd9d4d039, 4); + MD5STEP(F3, d, a, b, c, md5->buffer[12] + 0xe6db99e5, 11); + MD5STEP(F3, c, d, a, b, md5->buffer[15] + 0x1fa27cf8, 16); + MD5STEP(F3, b, c, d, a, md5->buffer[2] + 0xc4ac5665, 23); + + MD5STEP(F4, a, b, c, d, md5->buffer[0] + 0xf4292244, 6); + MD5STEP(F4, d, a, b, c, md5->buffer[7] + 0x432aff97, 10); + MD5STEP(F4, c, d, a, b, md5->buffer[14] + 0xab9423a7, 15); + MD5STEP(F4, b, c, d, a, md5->buffer[5] + 0xfc93a039, 21); + MD5STEP(F4, a, b, c, d, md5->buffer[12] + 0x655b59c3, 6); + MD5STEP(F4, d, a, b, c, md5->buffer[3] + 0x8f0ccc92, 10); + MD5STEP(F4, c, d, a, b, md5->buffer[10] + 0xffeff47d, 15); + MD5STEP(F4, b, c, d, a, md5->buffer[1] + 0x85845dd1, 21); + MD5STEP(F4, a, b, c, d, md5->buffer[8] + 0x6fa87e4f, 6); + MD5STEP(F4, d, a, b, c, md5->buffer[15] + 0xfe2ce6e0, 10); + MD5STEP(F4, c, d, a, b, md5->buffer[6] + 0xa3014314, 15); + MD5STEP(F4, b, c, d, a, md5->buffer[13] + 0x4e0811a1, 21); + MD5STEP(F4, a, b, c, d, md5->buffer[4] + 0xf7537e82, 6); + MD5STEP(F4, d, a, b, c, md5->buffer[11] + 0xbd3af235, 10); + MD5STEP(F4, c, d, a, b, md5->buffer[2] + 0x2ad7d2bb, 15); + MD5STEP(F4, b, c, d, a, md5->buffer[9] + 0xeb86d391, 21); + + /* Add the working vars back into digest state[] */ + md5->digest[0] += a; + md5->digest[1] += b; + md5->digest[2] += c; + md5->digest[3] += d; + + return 0; + } +#endif /* NEED_SOFT_MD5 */ + +#ifndef HAVE_MD5_CUST_API + +static WC_INLINE void AddLength(wc_Md5* md5, word32 len) +{ + word32 tmp = md5->loLen; + if ((md5->loLen += len) < tmp) { + md5->hiLen++; /* carry low to high */ + } +} + +static int _InitMd5(wc_Md5* md5) +{ + int ret = 0; + + md5->digest[0] = 0x67452301L; + md5->digest[1] = 0xefcdab89L; + md5->digest[2] = 0x98badcfeL; + md5->digest[3] = 0x10325476L; + + md5->buffLen = 0; + md5->loLen = 0; + md5->hiLen = 0; + + return ret; +} + +int wc_InitMd5_ex(wc_Md5* md5, void* heap, int devId) +{ + int ret = 0; + + if (md5 == NULL) + return BAD_FUNC_ARG; + + md5->heap = heap; + + ret = _InitMd5(md5); + if (ret != 0) + return ret; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_MD5) + ret = wolfAsync_DevCtxInit(&md5->asyncDev, WOLFSSL_ASYNC_MARKER_MD5, + md5->heap, devId); +#else + (void)devId; +#endif + return ret; +} + +int wc_Md5Update(wc_Md5* md5, const byte* data, word32 len) +{ + int ret = 0; + byte* local; + + if (md5 == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_MD5) + if (md5->asyncDev.marker == WOLFSSL_ASYNC_MARKER_MD5) { + #if defined(HAVE_INTEL_QA) + return IntelQaSymMd5(&md5->asyncDev, NULL, data, len); + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + /* do block size increments */ + local = (byte*)md5->buffer; + + /* check that internal buffLen is valid */ + if (md5->buffLen >= WC_MD5_BLOCK_SIZE) + return BUFFER_E; + + while (len) { + word32 add = min(len, WC_MD5_BLOCK_SIZE - md5->buffLen); + XMEMCPY(&local[md5->buffLen], data, add); + + md5->buffLen += add; + data += add; + len -= add; + + if (md5->buffLen == WC_MD5_BLOCK_SIZE) { + #if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) + ByteReverseWords(md5->buffer, md5->buffer, WC_MD5_BLOCK_SIZE); + #endif + XTRANSFORM(md5, local); + AddLength(md5, WC_MD5_BLOCK_SIZE); + md5->buffLen = 0; + } + } + return ret; +} + +int wc_Md5Final(wc_Md5* md5, byte* hash) +{ + byte* local; + + if (md5 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_MD5) + if (md5->asyncDev.marker == WOLFSSL_ASYNC_MARKER_MD5) { + #if defined(HAVE_INTEL_QA) + return IntelQaSymMd5(&md5->asyncDev, hash, NULL, WC_MD5_DIGEST_SIZE); + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + local = (byte*)md5->buffer; + + AddLength(md5, md5->buffLen); /* before adding pads */ + local[md5->buffLen++] = 0x80; /* add 1 */ + + /* pad with zeros */ + if (md5->buffLen > WC_MD5_PAD_SIZE) { + XMEMSET(&local[md5->buffLen], 0, WC_MD5_BLOCK_SIZE - md5->buffLen); + md5->buffLen += WC_MD5_BLOCK_SIZE - md5->buffLen; + + #if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) + ByteReverseWords(md5->buffer, md5->buffer, WC_MD5_BLOCK_SIZE); + #endif + XTRANSFORM(md5, local); + md5->buffLen = 0; + } + XMEMSET(&local[md5->buffLen], 0, WC_MD5_PAD_SIZE - md5->buffLen); + +#if defined(BIG_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) + ByteReverseWords(md5->buffer, md5->buffer, WC_MD5_BLOCK_SIZE); +#endif + + /* put lengths in bits */ + md5->hiLen = (md5->loLen >> (8*sizeof(md5->loLen) - 3)) + + (md5->hiLen << 3); + md5->loLen = md5->loLen << 3; + + /* store lengths */ + /* ! length ordering dependent on digest endian type ! */ + XMEMCPY(&local[WC_MD5_PAD_SIZE], &md5->loLen, sizeof(word32)); + XMEMCPY(&local[WC_MD5_PAD_SIZE + sizeof(word32)], &md5->hiLen, sizeof(word32)); + + /* final transform and result to hash */ + XTRANSFORM(md5, local); +#ifdef BIG_ENDIAN_ORDER + ByteReverseWords(md5->digest, md5->digest, WC_MD5_DIGEST_SIZE); +#endif + XMEMCPY(hash, md5->digest, WC_MD5_DIGEST_SIZE); + + return _InitMd5(md5); /* reset state */ +} +#endif /* !HAVE_MD5_CUST_API */ + + +int wc_InitMd5(wc_Md5* md5) +{ + if (md5 == NULL) { + return BAD_FUNC_ARG; + } + return wc_InitMd5_ex(md5, NULL, INVALID_DEVID); +} + +void wc_Md5Free(wc_Md5* md5) +{ + if (md5 == NULL) + return; +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_MD5) + wolfAsync_DevCtxFree(&md5->asyncDev, WOLFSSL_ASYNC_MARKER_MD5); +#endif /* WOLFSSL_ASYNC_CRYPT */ + +#ifdef WOLFSSL_PIC32MZ_HASH + wc_Md5Pic32Free(md5); +#endif +} + +int wc_Md5GetHash(wc_Md5* md5, byte* hash) +{ + int ret; + wc_Md5 tmpMd5; + + if (md5 == NULL || hash == NULL) + return BAD_FUNC_ARG; + + ret = wc_Md5Copy(md5, &tmpMd5); + if (ret == 0) { + ret = wc_Md5Final(&tmpMd5, hash); + } + + return ret; +} + +int wc_Md5Copy(wc_Md5* src, wc_Md5* dst) +{ + int ret = 0; + + if (src == NULL || dst == NULL) + return BAD_FUNC_ARG; + + XMEMCPY(dst, src, sizeof(wc_Md5)); + +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev); +#endif +#ifdef WOLFSSL_PIC32MZ_HASH + ret = wc_Pic32HashCopy(&src->cache, &dst->cache); +#endif +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + dst->flags |= WC_HASH_FLAG_ISCOPY; +#endif + + return ret; +} + +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) +int wc_Md5SetFlags(wc_Md5* md5, word32 flags) +{ + if (md5) { + md5->flags = flags; + } + return 0; +} +int wc_Md5GetFlags(wc_Md5* md5, word32* flags) +{ + if (md5 && flags) { + *flags = md5->flags; + } + return 0; +} +#endif + +#endif /* WOLFSSL_TI_HASH */ +#endif /* NO_MD5 */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/memory.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/memory.c new file mode 100755 index 0000000..00c0b67 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/memory.c @@ -0,0 +1,1124 @@ +/* memory.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +/* check old macros @wc_fips */ +#if defined(USE_CYASSL_MEMORY) && !defined(USE_WOLFSSL_MEMORY) + #define USE_WOLFSSL_MEMORY +#endif +#if defined(CYASSL_MALLOC_CHECK) && !defined(WOLFSSL_MALLOC_CHECK) + #define WOLFSSL_MALLOC_CHECK +#endif + + +/* +Possible memory options: + * NO_WOLFSSL_MEMORY: Disables wolf memory callback support. When not defined settings.h defines USE_WOLFSSL_MEMORY. + * WOLFSSL_STATIC_MEMORY: Turns on the use of static memory buffers and functions. + This allows for using static memory instead of dynamic. + * WOLFSSL_STATIC_ALIGN: Define defaults to 16 to indicate static memory alignment. + * HAVE_IO_POOL: Enables use of static thread safe memory pool for input/output buffers. + * XMALLOC_OVERRIDE: Allows override of the XMALLOC, XFREE and XREALLOC macros. + * XMALLOC_USER: Allows custom XMALLOC, XFREE and XREALLOC functions to be defined. + * WOLFSSL_NO_MALLOC: Disables the fall-back case to use STDIO malloc/free when no callbacks are set. + * WOLFSSL_TRACK_MEMORY: Enables memory tracking for total stats and list of allocated memory. + * WOLFSSL_DEBUG_MEMORY: Enables extra function and line number args for memory callbacks. + * WOLFSSL_DEBUG_MEMORY_PRINT: Enables printing of each malloc/free. + * WOLFSSL_MALLOC_CHECK: Reports malloc or alignment failure using WOLFSSL_STATIC_ALIGN + * WOLFSSL_FORCE_MALLOC_FAIL_TEST: Used for internal testing to induce random malloc failures. + * WOLFSSL_HEAP_TEST: Used for internal testing of heap hint + */ + +#ifdef WOLFSSL_ZEPHYR +#undef realloc +void *z_realloc(void *ptr, size_t size) +{ + if (ptr == NULL) + ptr = malloc(size); + else + ptr = realloc(ptr, size); + + return ptr; +} +#define realloc z_realloc +#endif + +#ifdef USE_WOLFSSL_MEMORY + +#include +#include +#include + +#if defined(WOLFSSL_DEBUG_MEMORY) && defined(WOLFSSL_DEBUG_MEMORY_PRINT) +#include +#endif + +#ifdef WOLFSSL_FORCE_MALLOC_FAIL_TEST + static int gMemFailCountSeed; + static int gMemFailCount; + void wolfSSL_SetMemFailCount(int memFailCount) + { + if (gMemFailCountSeed == 0) { + gMemFailCountSeed = memFailCount; + gMemFailCount = memFailCount; + } + } +#endif +#if defined(WOLFSSL_MALLOC_CHECK) || defined(WOLFSSL_TRACK_MEMORY_FULL) || \ + defined(WOLFSSL_MEMORY_LOG) + #include +#endif + + +/* Set these to default values initially. */ +static wolfSSL_Malloc_cb malloc_function = NULL; +static wolfSSL_Free_cb free_function = NULL; +static wolfSSL_Realloc_cb realloc_function = NULL; + +int wolfSSL_SetAllocators(wolfSSL_Malloc_cb mf, + wolfSSL_Free_cb ff, + wolfSSL_Realloc_cb rf) +{ + malloc_function = mf; + free_function = ff; + realloc_function = rf; + return 0; +} + +int wolfSSL_GetAllocators(wolfSSL_Malloc_cb* mf, + wolfSSL_Free_cb* ff, + wolfSSL_Realloc_cb* rf) +{ + if (mf) *mf = malloc_function; + if (ff) *ff = free_function; + if (rf) *rf = realloc_function; + return 0; +} + +#ifndef WOLFSSL_STATIC_MEMORY +#ifdef WOLFSSL_DEBUG_MEMORY +void* wolfSSL_Malloc(size_t size, const char* func, unsigned int line) +#else +void* wolfSSL_Malloc(size_t size) +#endif +{ + void* res = 0; + if (malloc_function) { + #ifdef WOLFSSL_DEBUG_MEMORY + res = malloc_function(size, func, line); + #else + res = malloc_function(size); + #endif + } + else { + #ifndef WOLFSSL_NO_MALLOC + res = malloc(size); + #else + WOLFSSL_MSG("No malloc available"); + #endif + } + +#ifdef WOLFSSL_DEBUG_MEMORY +#if defined(WOLFSSL_DEBUG_MEMORY_PRINT) && !defined(WOLFSSL_TRACK_MEMORY) + printf("Alloc: %p -> %u at %s:%d\n", res, (word32)size, func, line); +#else + (void)func; + (void)line; +#endif +#endif + +#ifdef WOLFSSL_MALLOC_CHECK + if (res == NULL) + WOLFSSL_MSG("wolfSSL_malloc failed"); +#endif + +#ifdef WOLFSSL_FORCE_MALLOC_FAIL_TEST + if (res && --gMemFailCount == 0) { + printf("\n---FORCED MEM FAIL TEST---\n"); + if (free_function) { + #ifdef WOLFSSL_DEBUG_MEMORY + free_function(res, func, line); + #else + free_function(res); + #endif + } + else { + free(res); /* clear */ + } + gMemFailCount = gMemFailCountSeed; /* reset */ + return NULL; + } +#endif + + return res; +} + +#ifdef WOLFSSL_DEBUG_MEMORY +void wolfSSL_Free(void *ptr, const char* func, unsigned int line) +#else +void wolfSSL_Free(void *ptr) +#endif +{ +#ifdef WOLFSSL_DEBUG_MEMORY +#if defined(WOLFSSL_DEBUG_MEMORY_PRINT) && !defined(WOLFSSL_TRACK_MEMORY) + printf("Free: %p at %s:%d\n", ptr, func, line); +#else + (void)func; + (void)line; +#endif +#endif + + if (free_function) { + #ifdef WOLFSSL_DEBUG_MEMORY + free_function(ptr, func, line); + #else + free_function(ptr); + #endif + } + else { + #ifndef WOLFSSL_NO_MALLOC + free(ptr); + #else + WOLFSSL_MSG("No free available"); + #endif + } +} + +#ifdef WOLFSSL_DEBUG_MEMORY +void* wolfSSL_Realloc(void *ptr, size_t size, const char* func, unsigned int line) +#else +void* wolfSSL_Realloc(void *ptr, size_t size) +#endif +{ + void* res = 0; + + if (realloc_function) { + #ifdef WOLFSSL_DEBUG_MEMORY + res = realloc_function(ptr, size, func, line); + #else + res = realloc_function(ptr, size); + #endif + } + else { + #ifndef WOLFSSL_NO_MALLOC + res = realloc(ptr, size); + #else + WOLFSSL_MSG("No realloc available"); + #endif + } + + return res; +} +#endif /* WOLFSSL_STATIC_MEMORY */ + +#ifdef WOLFSSL_STATIC_MEMORY +struct wc_Memory { + byte* buffer; + struct wc_Memory* next; + word32 sz; +}; + + +/* returns amount of memory used on success. On error returns negative value + wc_Memory** list is the list that new buckets are prepended to + */ +static int create_memory_buckets(byte* buffer, word32 bufSz, + word32 buckSz, word32 buckNum, wc_Memory** list) { + word32 i; + byte* pt = buffer; + int ret = 0; + word32 memSz = (word32)sizeof(wc_Memory); + word32 padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1); + + /* if not enough space available for bucket size then do not try */ + if (buckSz + memSz + padSz > bufSz) { + return ret; + } + + for (i = 0; i < buckNum; i++) { + if ((buckSz + memSz + padSz) <= (bufSz - ret)) { + /* create a new struct and set its values */ + wc_Memory* mem = (struct wc_Memory*)(pt); + mem->sz = buckSz; + mem->buffer = (byte*)pt + padSz + memSz; + mem->next = NULL; + + /* add the newly created struct to front of list */ + if (*list == NULL) { + *list = mem; + } else { + mem->next = *list; + *list = mem; + } + + /* advance pointer and keep track of memory used */ + ret += buckSz + padSz + memSz; + pt += buckSz + padSz + memSz; + } + else { + break; /* not enough space left for more buckets of this size */ + } + } + + return ret; +} + +int wolfSSL_init_memory_heap(WOLFSSL_HEAP* heap) +{ + word32 wc_MemSz[WOLFMEM_DEF_BUCKETS] = { WOLFMEM_BUCKETS }; + word32 wc_Dist[WOLFMEM_DEF_BUCKETS] = { WOLFMEM_DIST }; + + if (heap == NULL) { + return BAD_FUNC_ARG; + } + + XMEMSET(heap, 0, sizeof(WOLFSSL_HEAP)); + + XMEMCPY(heap->sizeList, wc_MemSz, sizeof(wc_MemSz)); + XMEMCPY(heap->distList, wc_Dist, sizeof(wc_Dist)); + + if (wc_InitMutex(&(heap->memory_mutex)) != 0) { + WOLFSSL_MSG("Error creating heap memory mutex"); + return BAD_MUTEX_E; + } + + return 0; +} + +int wc_LoadStaticMemory(WOLFSSL_HEAP_HINT** pHint, + unsigned char* buf, unsigned int sz, int flag, int max) +{ + int ret; + WOLFSSL_HEAP* heap; + WOLFSSL_HEAP_HINT* hint; + word32 idx = 0; + + if (pHint == NULL || buf == NULL) { + return BAD_FUNC_ARG; + } + + if ((sizeof(WOLFSSL_HEAP) + sizeof(WOLFSSL_HEAP_HINT)) > sz - idx) { + return BUFFER_E; /* not enough memory for structures */ + } + + /* check if hint has already been assigned */ + if (*pHint == NULL) { + heap = (WOLFSSL_HEAP*)buf; + idx += sizeof(WOLFSSL_HEAP); + hint = (WOLFSSL_HEAP_HINT*)(buf + idx); + idx += sizeof(WOLFSSL_HEAP_HINT); + + ret = wolfSSL_init_memory_heap(heap); + if (ret != 0) { + return ret; + } + + XMEMSET(hint, 0, sizeof(WOLFSSL_HEAP_HINT)); + hint->memory = heap; + } + else { + #ifdef WOLFSSL_HEAP_TEST + /* do not load in memory if test has been set */ + if (heap == (void*)WOLFSSL_HEAP_TEST) { + return 0; + } + #endif + + hint = (WOLFSSL_HEAP_HINT*)(*pHint); + heap = hint->memory; + } + + ret = wolfSSL_load_static_memory(buf + idx, sz - idx, flag, heap); + if (ret != 1) { + WOLFSSL_MSG("Error partitioning memory"); + return -1; + } + + /* determine what max applies too */ + if ((flag & WOLFMEM_IO_POOL) || (flag & WOLFMEM_IO_POOL_FIXED)) { + heap->maxIO = max; + } + else { /* general memory used in handshakes */ + heap->maxHa = max; + } + + heap->flag |= flag; + *pHint = hint; + + (void)max; + + return 0; +} + +int wolfSSL_load_static_memory(byte* buffer, word32 sz, int flag, + WOLFSSL_HEAP* heap) +{ + word32 ava = sz; + byte* pt = buffer; + int ret = 0; + word32 memSz = (word32)sizeof(wc_Memory); + word32 padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1); + + WOLFSSL_ENTER("wolfSSL_load_static_memory"); + + if (buffer == NULL) { + return BAD_FUNC_ARG; + } + + /* align pt */ + while ((wolfssl_word)pt % WOLFSSL_STATIC_ALIGN && pt < (buffer + sz)) { + *pt = 0x00; + pt++; + ava--; + } + +#ifdef WOLFSSL_DEBUG_MEMORY + printf("Allocated %d bytes for static memory @ %p\n", ava, pt); +#endif + + /* devide into chunks of memory and add them to available list */ + while (ava >= (heap->sizeList[0] + padSz + memSz)) { + int i; + /* creating only IO buffers from memory passed in, max TLS is 16k */ + if (flag & WOLFMEM_IO_POOL || flag & WOLFMEM_IO_POOL_FIXED) { + if ((ret = create_memory_buckets(pt, ava, + WOLFMEM_IO_SZ, 1, &(heap->io))) < 0) { + WOLFSSL_LEAVE("wolfSSL_load_static_memory", ret); + return ret; + } + + /* check if no more room left for creating IO buffers */ + if (ret == 0) { + break; + } + + /* advance pointer in buffer for next buckets and keep track + of how much memory is left available */ + pt += ret; + ava -= ret; + } + else { + /* start at largest and move to smaller buckets */ + for (i = (WOLFMEM_MAX_BUCKETS - 1); i >= 0; i--) { + if ((heap->sizeList[i] + padSz + memSz) <= ava) { + if ((ret = create_memory_buckets(pt, ava, heap->sizeList[i], + heap->distList[i], &(heap->ava[i]))) < 0) { + WOLFSSL_LEAVE("wolfSSL_load_static_memory", ret); + return ret; + } + + /* advance pointer in buffer for next buckets and keep track + of how much memory is left available */ + pt += ret; + ava -= ret; + } + } + } + } + + return 1; +} + + +/* returns the size of management memory needed for each bucket. + * This is memory that is used to keep track of and align memory buckets. */ +int wolfSSL_MemoryPaddingSz(void) +{ + word32 memSz = (word32)sizeof(wc_Memory); + word32 padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1); + return memSz + padSz; +} + + +/* Used to calculate memory size for optimum use with buckets. + returns the suggested size rounded down to the nearest bucket. */ +int wolfSSL_StaticBufferSz(byte* buffer, word32 sz, int flag) +{ + word32 bucketSz[WOLFMEM_MAX_BUCKETS] = {WOLFMEM_BUCKETS}; + word32 distList[WOLFMEM_MAX_BUCKETS] = {WOLFMEM_DIST}; + + word32 ava = sz; + byte* pt = buffer; + word32 memSz = (word32)sizeof(wc_Memory); + word32 padSz = -(int)memSz & (WOLFSSL_STATIC_ALIGN - 1); + + WOLFSSL_ENTER("wolfSSL_static_size"); + + if (buffer == NULL) { + return BAD_FUNC_ARG; + } + + /* align pt */ + while ((wolfssl_word)pt % WOLFSSL_STATIC_ALIGN && pt < (buffer + sz)) { + pt++; + ava--; + } + + /* creating only IO buffers from memory passed in, max TLS is 16k */ + if (flag & WOLFMEM_IO_POOL || flag & WOLFMEM_IO_POOL_FIXED) { + if (ava < (memSz + padSz + WOLFMEM_IO_SZ)) { + return 0; /* not enough room for even one bucket */ + } + + ava = ava % (memSz + padSz + WOLFMEM_IO_SZ); + } + else { + int i, k; + + if (ava < (bucketSz[0] + padSz + memSz)) { + return 0; /* not enough room for even one bucket */ + } + + while ((ava >= (bucketSz[0] + padSz + memSz)) && (ava > 0)) { + /* start at largest and move to smaller buckets */ + for (i = (WOLFMEM_MAX_BUCKETS - 1); i >= 0; i--) { + for (k = distList[i]; k > 0; k--) { + if ((bucketSz[i] + padSz + memSz) <= ava) { + ava -= bucketSz[i] + padSz + memSz; + } + } + } + } + } + + return sz - ava; /* round down */ +} + + +int FreeFixedIO(WOLFSSL_HEAP* heap, wc_Memory** io) +{ + WOLFSSL_MSG("Freeing fixed IO buffer"); + + /* check if fixed buffer was set */ + if (*io == NULL) { + return 1; + } + + if (heap == NULL) { + WOLFSSL_MSG("No heap to return fixed IO too"); + } + else { + /* put IO buffer back into IO pool */ + (*io)->next = heap->io; + heap->io = *io; + *io = NULL; + } + + return 1; +} + + +int SetFixedIO(WOLFSSL_HEAP* heap, wc_Memory** io) +{ + WOLFSSL_MSG("Setting fixed IO for SSL"); + if (heap == NULL) { + return MEMORY_E; + } + + *io = heap->io; + + if (*io != NULL) { + heap->io = (*io)->next; + (*io)->next = NULL; + } + else { /* failed to grab an IO buffer */ + return 0; + } + + return 1; +} + + +int wolfSSL_GetMemStats(WOLFSSL_HEAP* heap, WOLFSSL_MEM_STATS* stats) +{ + word32 i; + wc_Memory* pt; + + XMEMSET(stats, 0, sizeof(WOLFSSL_MEM_STATS)); + + stats->totalAlloc = heap->alloc; + stats->totalFr = heap->frAlc; + stats->curAlloc = stats->totalAlloc - stats->totalFr; + stats->maxHa = heap->maxHa; + stats->maxIO = heap->maxIO; + for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) { + stats->blockSz[i] = heap->sizeList[i]; + for (pt = heap->ava[i]; pt != NULL; pt = pt->next) { + stats->avaBlock[i] += 1; + } + } + + for (pt = heap->io; pt != NULL; pt = pt->next) { + stats->avaIO++; + } + + stats->flag = heap->flag; /* flag used */ + + return 1; +} + + +#ifdef WOLFSSL_DEBUG_MEMORY +void* wolfSSL_Malloc(size_t size, void* heap, int type, const char* func, unsigned int line) +#else +void* wolfSSL_Malloc(size_t size, void* heap, int type) +#endif +{ + void* res = 0; + wc_Memory* pt = NULL; + int i; + + /* check for testing heap hint was set */ +#ifdef WOLFSSL_HEAP_TEST + if (heap == (void*)WOLFSSL_HEAP_TEST) { + return malloc(size); + } +#endif + + /* if no heap hint then use dynamic memory*/ + if (heap == NULL) { + #ifdef WOLFSSL_HEAP_TEST + /* allow using malloc for creating ctx and method */ + if (type == DYNAMIC_TYPE_CTX || type == DYNAMIC_TYPE_METHOD || + type == DYNAMIC_TYPE_CERT_MANAGER) { + WOLFSSL_MSG("ERROR allowing null heap hint for ctx/method\n"); + res = malloc(size); + } + else { + WOLFSSL_MSG("ERROR null heap hint passed into XMALLOC\n"); + res = NULL; + } + #else + #ifndef WOLFSSL_NO_MALLOC + #ifdef FREERTOS + res = pvPortMalloc(size); + #else + res = malloc(size); + #endif + #else + WOLFSSL_MSG("No heap hint found to use and no malloc"); + #ifdef WOLFSSL_DEBUG_MEMORY + printf("ERROR: at %s:%d\n", func, line); + #endif + #endif /* WOLFSSL_NO_MALLOC */ + #endif /* WOLFSSL_HEAP_TEST */ + } + else { + WOLFSSL_HEAP_HINT* hint = (WOLFSSL_HEAP_HINT*)heap; + WOLFSSL_HEAP* mem = hint->memory; + + if (wc_LockMutex(&(mem->memory_mutex)) != 0) { + WOLFSSL_MSG("Bad memory_mutex lock"); + return NULL; + } + + /* case of using fixed IO buffers */ + if (mem->flag & WOLFMEM_IO_POOL_FIXED && + (type == DYNAMIC_TYPE_OUT_BUFFER || + type == DYNAMIC_TYPE_IN_BUFFER)) { + if (type == DYNAMIC_TYPE_OUT_BUFFER) { + pt = hint->outBuf; + } + if (type == DYNAMIC_TYPE_IN_BUFFER) { + pt = hint->inBuf; + } + } + else { + /* check if using IO pool flag */ + if (mem->flag & WOLFMEM_IO_POOL && + (type == DYNAMIC_TYPE_OUT_BUFFER || + type == DYNAMIC_TYPE_IN_BUFFER)) { + if (mem->io != NULL) { + pt = mem->io; + mem->io = pt->next; + } + } + + /* general static memory */ + if (pt == NULL) { + for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) { + if ((word32)size < mem->sizeList[i]) { + if (mem->ava[i] != NULL) { + pt = mem->ava[i]; + mem->ava[i] = pt->next; + break; + } + #ifdef WOLFSSL_DEBUG_STATIC_MEMORY + else { + printf("Size: %ld, Empty: %d\n", size, + mem->sizeList[i]); + } + #endif + } + } + } + } + + if (pt != NULL) { + mem->inUse += pt->sz; + mem->alloc += 1; + res = pt->buffer; + + #ifdef WOLFSSL_DEBUG_MEMORY + printf("Alloc: %p -> %u at %s:%d\n", pt->buffer, pt->sz, func, line); + #endif + + /* keep track of connection statistics if flag is set */ + if (mem->flag & WOLFMEM_TRACK_STATS) { + WOLFSSL_MEM_CONN_STATS* stats = hint->stats; + if (stats != NULL) { + stats->curMem += pt->sz; + if (stats->peakMem < stats->curMem) { + stats->peakMem = stats->curMem; + } + stats->curAlloc++; + if (stats->peakAlloc < stats->curAlloc) { + stats->peakAlloc = stats->curAlloc; + } + stats->totalAlloc++; + } + } + } + else { + WOLFSSL_MSG("ERROR ran out of static memory"); + #ifdef WOLFSSL_DEBUG_MEMORY + printf("Looking for %lu bytes at %s:%d\n", size, func, line); + #endif + } + + wc_UnLockMutex(&(mem->memory_mutex)); + } + + #ifdef WOLFSSL_MALLOC_CHECK + if ((wolfssl_word)res % WOLFSSL_STATIC_ALIGN) { + WOLFSSL_MSG("ERROR memory is not alligned"); + res = NULL; + } + #endif + + + (void)i; + (void)pt; + (void)type; + + return res; +} + + +#ifdef WOLFSSL_DEBUG_MEMORY +void wolfSSL_Free(void *ptr, void* heap, int type, const char* func, unsigned int line) +#else +void wolfSSL_Free(void *ptr, void* heap, int type) +#endif +{ + int i; + wc_Memory* pt; + + if (ptr) { + /* check for testing heap hint was set */ + #ifdef WOLFSSL_HEAP_TEST + if (heap == (void*)WOLFSSL_HEAP_TEST) { + return free(ptr); + } + #endif + + if (heap == NULL) { + #ifdef WOLFSSL_HEAP_TEST + /* allow using malloc for creating ctx and method */ + if (type == DYNAMIC_TYPE_CTX || type == DYNAMIC_TYPE_METHOD || + type == DYNAMIC_TYPE_CERT_MANAGER) { + WOLFSSL_MSG("ERROR allowing null heap hint for ctx/method\n"); + } + else { + WOLFSSL_MSG("ERROR null heap hint passed into XFREE\n"); + } + #endif + #ifndef WOLFSSL_NO_MALLOC + #ifdef FREERTOS + vPortFree(ptr); + #else + free(ptr); + #endif + #else + WOLFSSL_MSG("Error trying to call free when turned off"); + #endif /* WOLFSSL_NO_MALLOC */ + } + else { + WOLFSSL_HEAP_HINT* hint = (WOLFSSL_HEAP_HINT*)heap; + WOLFSSL_HEAP* mem = hint->memory; + word32 padSz = -(int)sizeof(wc_Memory) & (WOLFSSL_STATIC_ALIGN - 1); + + /* get memory struct and add it to available list */ + pt = (wc_Memory*)((byte*)ptr - sizeof(wc_Memory) - padSz); + if (wc_LockMutex(&(mem->memory_mutex)) != 0) { + WOLFSSL_MSG("Bad memory_mutex lock"); + return; + } + + /* case of using fixed IO buffers */ + if (mem->flag & WOLFMEM_IO_POOL_FIXED && + (type == DYNAMIC_TYPE_OUT_BUFFER || + type == DYNAMIC_TYPE_IN_BUFFER)) { + /* fixed IO pools are free'd at the end of SSL lifetime + using FreeFixedIO(WOLFSSL_HEAP* heap, wc_Memory** io) */ + } + else if (mem->flag & WOLFMEM_IO_POOL && pt->sz == WOLFMEM_IO_SZ && + (type == DYNAMIC_TYPE_OUT_BUFFER || + type == DYNAMIC_TYPE_IN_BUFFER)) { + pt->next = mem->io; + mem->io = pt; + } + else { /* general memory free */ + for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) { + if (pt->sz == mem->sizeList[i]) { + pt->next = mem->ava[i]; + mem->ava[i] = pt; + break; + } + } + } + mem->inUse -= pt->sz; + mem->frAlc += 1; + + #ifdef WOLFSSL_DEBUG_MEMORY + printf("Free: %p -> %u at %s:%d\n", pt->buffer, pt->sz, func, line); + #endif + + /* keep track of connection statistics if flag is set */ + if (mem->flag & WOLFMEM_TRACK_STATS) { + WOLFSSL_MEM_CONN_STATS* stats = hint->stats; + if (stats != NULL) { + /* avoid under flow */ + if (stats->curMem > pt->sz) { + stats->curMem -= pt->sz; + } + else { + stats->curMem = 0; + } + + if (stats->curAlloc > 0) { + stats->curAlloc--; + } + stats->totalFr++; + } + } + wc_UnLockMutex(&(mem->memory_mutex)); + } + } + + (void)i; + (void)pt; + (void)type; +} + +#ifdef WOLFSSL_DEBUG_MEMORY +void* wolfSSL_Realloc(void *ptr, size_t size, void* heap, int type, const char* func, unsigned int line) +#else +void* wolfSSL_Realloc(void *ptr, size_t size, void* heap, int type) +#endif +{ + void* res = 0; + wc_Memory* pt = NULL; + word32 prvSz; + int i; + + /* check for testing heap hint was set */ +#ifdef WOLFSSL_HEAP_TEST + if (heap == (void*)WOLFSSL_HEAP_TEST) { + return realloc(ptr, size); + } +#endif + + if (heap == NULL) { + #ifdef WOLFSSL_HEAP_TEST + WOLFSSL_MSG("ERROR null heap hint passed in to XREALLOC\n"); + #endif + #ifndef WOLFSSL_NO_MALLOC + res = realloc(ptr, size); + #else + WOLFSSL_MSG("NO heap found to use for realloc"); + #endif /* WOLFSSL_NO_MALLOC */ + } + else { + WOLFSSL_HEAP_HINT* hint = (WOLFSSL_HEAP_HINT*)heap; + WOLFSSL_HEAP* mem = hint->memory; + word32 padSz = -(int)sizeof(wc_Memory) & (WOLFSSL_STATIC_ALIGN - 1); + + if (ptr == NULL) { + #ifdef WOLFSSL_DEBUG_MEMORY + return wolfSSL_Malloc(size, heap, type, func, line); + #else + return wolfSSL_Malloc(size, heap, type); + #endif + } + + if (wc_LockMutex(&(mem->memory_mutex)) != 0) { + WOLFSSL_MSG("Bad memory_mutex lock"); + return NULL; + } + + /* case of using fixed IO buffers or IO pool */ + if (((mem->flag & WOLFMEM_IO_POOL)||(mem->flag & WOLFMEM_IO_POOL_FIXED)) + && (type == DYNAMIC_TYPE_OUT_BUFFER || + type == DYNAMIC_TYPE_IN_BUFFER)) { + /* no realloc, is fixed size */ + pt = (wc_Memory*)((byte*)ptr - padSz - sizeof(wc_Memory)); + if (pt->sz < size) { + WOLFSSL_MSG("Error IO memory was not large enough"); + res = NULL; /* return NULL in error case */ + } + res = pt->buffer; + } + else { + /* general memory */ + for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) { + if ((word32)size < mem->sizeList[i]) { + if (mem->ava[i] != NULL) { + pt = mem->ava[i]; + mem->ava[i] = pt->next; + break; + } + } + } + + if (pt != NULL && res == NULL) { + res = pt->buffer; + + /* copy over original information and free ptr */ + prvSz = ((wc_Memory*)((byte*)ptr - padSz - + sizeof(wc_Memory)))->sz; + prvSz = (prvSz > pt->sz)? pt->sz: prvSz; + XMEMCPY(pt->buffer, ptr, prvSz); + mem->inUse += pt->sz; + mem->alloc += 1; + + /* free memory that was previously being used */ + wc_UnLockMutex(&(mem->memory_mutex)); + wolfSSL_Free(ptr, heap, type + #ifdef WOLFSSL_DEBUG_MEMORY + , func, line + #endif + ); + if (wc_LockMutex(&(mem->memory_mutex)) != 0) { + WOLFSSL_MSG("Bad memory_mutex lock"); + return NULL; + } + } + } + wc_UnLockMutex(&(mem->memory_mutex)); + } + + #ifdef WOLFSSL_MALLOC_CHECK + if ((wolfssl_word)res % WOLFSSL_STATIC_ALIGN) { + WOLFSSL_MSG("ERROR memory is not alligned"); + res = NULL; + } + #endif + + (void)i; + (void)pt; + (void)type; + + return res; +} +#endif /* WOLFSSL_STATIC_MEMORY */ + +#endif /* USE_WOLFSSL_MEMORY */ + + +#ifdef HAVE_IO_POOL + +/* Example for user io pool, shared build may need definitions in lib proper */ + +#include +#include + +#ifndef HAVE_THREAD_LS + #error "Oops, simple I/O pool example needs thread local storage" +#endif + + +/* allow simple per thread in and out pools */ +/* use 17k size since max record size is 16k plus overhead */ +static THREAD_LS_T byte pool_in[17*1024]; +static THREAD_LS_T byte pool_out[17*1024]; + + +void* XMALLOC(size_t n, void* heap, int type) +{ + (void)heap; + + if (type == DYNAMIC_TYPE_IN_BUFFER) { + if (n < sizeof(pool_in)) + return pool_in; + else + return NULL; + } + + if (type == DYNAMIC_TYPE_OUT_BUFFER) { + if (n < sizeof(pool_out)) + return pool_out; + else + return NULL; + } + + return malloc(n); +} + +void* XREALLOC(void *p, size_t n, void* heap, int type) +{ + (void)heap; + + if (type == DYNAMIC_TYPE_IN_BUFFER) { + if (n < sizeof(pool_in)) + return pool_in; + else + return NULL; + } + + if (type == DYNAMIC_TYPE_OUT_BUFFER) { + if (n < sizeof(pool_out)) + return pool_out; + else + return NULL; + } + + return realloc(p, n); +} + +void XFREE(void *p, void* heap, int type) +{ + (void)heap; + + if (type == DYNAMIC_TYPE_IN_BUFFER) + return; /* do nothing, static pool */ + + if (type == DYNAMIC_TYPE_OUT_BUFFER) + return; /* do nothing, static pool */ + + free(p); +} + +#endif /* HAVE_IO_POOL */ + +#ifdef WOLFSSL_MEMORY_LOG +void *xmalloc(size_t n, void* heap, int type, const char* func, + const char* file, unsigned int line) +{ + void* p; + word32* p32; + + if (malloc_function) + p32 = malloc_function(n + sizeof(word32) * 4); + else + p32 = malloc(n + sizeof(word32) * 4); + + p32[0] = (word32)n; + p = (void*)(p32 + 4); + + fprintf(stderr, "Alloc: %p -> %u (%d) at %s:%s:%d\n", p, (word32)n, type, + func, file, line); + + (void)heap; + + return p; +} +void *xrealloc(void *p, size_t n, void* heap, int type, const char* func, + const char* file, unsigned int line) +{ + void* newp = NULL; + word32* p32; + word32* oldp32 = NULL; + word32 oldLen; + + if (p != NULL) { + oldp32 = (word32*)p; + oldp32 -= 4; + oldLen = oldp32[0]; + } + + if (realloc_function) + p32 = realloc_function(oldp32, n + sizeof(word32) * 4); + else + p32 = realloc(oldp32, n + sizeof(word32) * 4); + + if (p32 != NULL) { + p32[0] = (word32)n; + newp = (void*)(p32 + 4); + + fprintf(stderr, "Alloc: %p -> %u (%d) at %s:%s:%d\n", newp, (word32)n, + type, func, file, line); + if (p != NULL) { + fprintf(stderr, "Free: %p -> %u (%d) at %s:%s:%d\n", p, oldLen, + type, func, file, line); + } + } + + (void)heap; + + return newp; +} +void xfree(void *p, void* heap, int type, const char* func, const char* file, + unsigned int line) +{ + word32* p32 = (word32*)p; + + if (p != NULL) { + p32 -= 4; + + fprintf(stderr, "Free: %p -> %u (%d) at %s:%s:%d\n", p, p32[0], type, + func, file, line); + + if (free_function) + free_function(p32); + else + free(p32); + } + + (void)heap; +} +#endif /* WOLFSSL_MEMORY_LOG */ + +#ifdef WOLFSSL_STACK_LOG +/* Note: this code only works with GCC using -finstrument-functions. */ +void __attribute__((no_instrument_function)) + __cyg_profile_func_enter(void *func, void *caller) +{ + register void* sp asm("sp"); + fprintf(stderr, "ENTER: %016lx %p\n", (size_t)func, sp); + (void)caller; +} + +void __attribute__((no_instrument_function)) + __cyg_profile_func_exit(void *func, void *caller) +{ + register void* sp asm("sp"); + fprintf(stderr, "EXIT: %016lx %p\n", (size_t)func, sp); + (void)caller; +} +#endif + diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/misc.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/misc.c new file mode 100755 index 0000000..739bd4a --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/misc.c @@ -0,0 +1,389 @@ +/* misc.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifndef WOLF_CRYPT_MISC_C +#define WOLF_CRYPT_MISC_C + +#include + +/* inlining these functions is a huge speed increase and a small size decrease, + because the functions are smaller than function call setup/cleanup, e.g., + md5 benchmark is twice as fast with inline. If you don't want it, then + define NO_INLINE and compile this file into wolfssl, otherwise it's used as + a source header + */ + +#ifdef NO_INLINE + #define WC_STATIC +#else + #define WC_STATIC static +#endif + +/* Check for if compiling misc.c when not needed. */ +#if !defined(WOLFSSL_MISC_INCLUDED) && !defined(NO_INLINE) + #ifndef WOLFSSL_IGNORE_FILE_WARN + #warning misc.c does not need to be compiled when using inline (NO_INLINE not defined) + #endif + +#else + + +#if defined(__ICCARM__) + #include +#endif + + +#ifdef INTEL_INTRINSICS + + #include /* get intrinsic definitions */ + + /* for non visual studio probably need no long version, 32 bit only + * i.e., _rotl and _rotr */ + #pragma intrinsic(_lrotl, _lrotr) + + WC_STATIC WC_INLINE word32 rotlFixed(word32 x, word32 y) + { + return y ? _lrotl(x, y) : x; + } + + WC_STATIC WC_INLINE word32 rotrFixed(word32 x, word32 y) + { + return y ? _lrotr(x, y) : x; + } + +#else /* generic */ + + WC_STATIC WC_INLINE word32 rotlFixed(word32 x, word32 y) + { + return (x << y) | (x >> (sizeof(y) * 8 - y)); + } + + + WC_STATIC WC_INLINE word32 rotrFixed(word32 x, word32 y) + { + return (x >> y) | (x << (sizeof(y) * 8 - y)); + } + +#endif + + +WC_STATIC WC_INLINE word32 ByteReverseWord32(word32 value) +{ +#ifdef PPC_INTRINSICS + /* PPC: load reverse indexed instruction */ + return (word32)__lwbrx(&value,0); +#elif defined(__ICCARM__) + return (word32)__REV(value); +#elif defined(KEIL_INTRINSICS) + return (word32)__rev(value); +#elif defined(WOLF_ALLOW_BUILTIN) && \ + defined(__GNUC_PREREQ) && __GNUC_PREREQ(4, 3) + return (word32)__builtin_bswap32(value); +#elif defined(FAST_ROTATE) + /* 5 instructions with rotate instruction, 9 without */ + return (rotrFixed(value, 8U) & 0xff00ff00) | + (rotlFixed(value, 8U) & 0x00ff00ff); +#else + /* 6 instructions with rotate instruction, 8 without */ + value = ((value & 0xFF00FF00) >> 8) | ((value & 0x00FF00FF) << 8); + return rotlFixed(value, 16U); +#endif +} + + +WC_STATIC WC_INLINE void ByteReverseWords(word32* out, const word32* in, + word32 byteCount) +{ + word32 count = byteCount/(word32)sizeof(word32), i; + + for (i = 0; i < count; i++) + out[i] = ByteReverseWord32(in[i]); + +} + + +#if defined(WORD64_AVAILABLE) && !defined(WOLFSSL_NO_WORD64_OPS) + + +WC_STATIC WC_INLINE word64 rotlFixed64(word64 x, word64 y) +{ + return (x << y) | (x >> (sizeof(y) * 8 - y)); +} + + +WC_STATIC WC_INLINE word64 rotrFixed64(word64 x, word64 y) +{ + return (x >> y) | (x << (sizeof(y) * 8 - y)); +} + + +WC_STATIC WC_INLINE word64 ByteReverseWord64(word64 value) +{ +#if defined(WOLF_ALLOW_BUILTIN) && defined(__GNUC_PREREQ) && __GNUC_PREREQ(4, 3) + return (word64)__builtin_bswap64(value); +#elif defined(WOLFCRYPT_SLOW_WORD64) + return (word64)((word64)ByteReverseWord32((word32) value)) << 32 | + (word64)ByteReverseWord32((word32)(value >> 32)); +#else + value = ((value & W64LIT(0xFF00FF00FF00FF00)) >> 8) | + ((value & W64LIT(0x00FF00FF00FF00FF)) << 8); + value = ((value & W64LIT(0xFFFF0000FFFF0000)) >> 16) | + ((value & W64LIT(0x0000FFFF0000FFFF)) << 16); + return rotlFixed64(value, 32U); +#endif +} + + +WC_STATIC WC_INLINE void ByteReverseWords64(word64* out, const word64* in, + word32 byteCount) +{ + word32 count = byteCount/(word32)sizeof(word64), i; + + for (i = 0; i < count; i++) + out[i] = ByteReverseWord64(in[i]); + +} + +#endif /* WORD64_AVAILABLE && !WOLFSSL_NO_WORD64_OPS */ + +#ifndef WOLFSSL_NO_XOR_OPS +WC_STATIC WC_INLINE void XorWords(wolfssl_word* r, const wolfssl_word* a, word32 n) +{ + word32 i; + + for (i = 0; i < n; i++) r[i] ^= a[i]; +} + + +WC_STATIC WC_INLINE void xorbuf(void* buf, const void* mask, word32 count) +{ + if (((wolfssl_word)buf | (wolfssl_word)mask | count) % WOLFSSL_WORD_SIZE == 0) + XorWords( (wolfssl_word*)buf, + (const wolfssl_word*)mask, count / WOLFSSL_WORD_SIZE); + else { + word32 i; + byte* b = (byte*)buf; + const byte* m = (const byte*)mask; + + for (i = 0; i < count; i++) b[i] ^= m[i]; + } +} +#endif + +#ifndef WOLFSSL_NO_FORCE_ZERO +/* Make sure compiler doesn't skip */ +WC_STATIC WC_INLINE void ForceZero(const void* mem, word32 len) +{ + volatile byte* z = (volatile byte*)mem; + +#if defined(WOLFSSL_X86_64_BUILD) && defined(WORD64_AVAILABLE) + volatile word64* w; + #ifndef WOLFSSL_UNALIGNED_64BIT_ACCESS + word32 l = (sizeof(word64) - ((size_t)z & (sizeof(word64)-1))) & + (sizeof(word64)-1); + + if (len < l) l = len; + len -= l; + while (l--) *z++ = 0; + #endif + for (w = (volatile word64*)z; len >= sizeof(*w); len -= sizeof(*w)) + *w++ = 0; + z = (volatile byte*)w; +#endif + + while (len--) *z++ = 0; +} +#endif + + +#ifndef WOLFSSL_NO_CONST_CMP +/* check all length bytes for equality, return 0 on success */ +WC_STATIC WC_INLINE int ConstantCompare(const byte* a, const byte* b, int length) +{ + int i; + int compareSum = 0; + + for (i = 0; i < length; i++) { + compareSum |= a[i] ^ b[i]; + } + + return compareSum; +} +#endif + + +#ifndef WOLFSSL_HAVE_MIN + #define WOLFSSL_HAVE_MIN + #if defined(HAVE_FIPS) && !defined(min) /* so ifdef check passes */ + #define min min + #endif + WC_STATIC WC_INLINE word32 min(word32 a, word32 b) + { + return a > b ? b : a; + } +#endif /* !WOLFSSL_HAVE_MIN */ + +#ifndef WOLFSSL_HAVE_MAX + #define WOLFSSL_HAVE_MAX + #if defined(HAVE_FIPS) && !defined(max) /* so ifdef check passes */ + #define max max + #endif + WC_STATIC WC_INLINE word32 max(word32 a, word32 b) + { + return a > b ? a : b; + } +#endif /* !WOLFSSL_HAVE_MAX */ + +#ifndef WOLFSSL_NO_INT_ENCODE +/* converts a 32 bit integer to 24 bit */ +WC_STATIC WC_INLINE void c32to24(word32 in, word24 out) +{ + out[0] = (in >> 16) & 0xff; + out[1] = (in >> 8) & 0xff; + out[2] = in & 0xff; +} + +/* convert 16 bit integer to opaque */ +WC_STATIC WC_INLINE void c16toa(word16 wc_u16, byte* c) +{ + c[0] = (wc_u16 >> 8) & 0xff; + c[1] = wc_u16 & 0xff; +} + +/* convert 32 bit integer to opaque */ +WC_STATIC WC_INLINE void c32toa(word32 wc_u32, byte* c) +{ + c[0] = (wc_u32 >> 24) & 0xff; + c[1] = (wc_u32 >> 16) & 0xff; + c[2] = (wc_u32 >> 8) & 0xff; + c[3] = wc_u32 & 0xff; +} +#endif + +#ifndef WOLFSSL_NO_INT_DECODE +/* convert a 24 bit integer into a 32 bit one */ +WC_STATIC WC_INLINE void c24to32(const word24 wc_u24, word32* wc_u32) +{ + *wc_u32 = ((word32)wc_u24[0] << 16) | (wc_u24[1] << 8) | wc_u24[2]; +} + + +/* convert opaque to 24 bit integer */ +WC_STATIC WC_INLINE void ato24(const byte* c, word32* wc_u24) +{ + *wc_u24 = ((word32)c[0] << 16) | (c[1] << 8) | c[2]; +} + +/* convert opaque to 16 bit integer */ +WC_STATIC WC_INLINE void ato16(const byte* c, word16* wc_u16) +{ + *wc_u16 = (word16) ((c[0] << 8) | (c[1])); +} + +/* convert opaque to 32 bit integer */ +WC_STATIC WC_INLINE void ato32(const byte* c, word32* wc_u32) +{ + *wc_u32 = ((word32)c[0] << 24) | ((word32)c[1] << 16) | (c[2] << 8) | c[3]; +} + + +WC_STATIC WC_INLINE word32 btoi(byte b) +{ + return (word32)(b - 0x30); +} +#endif + + +#ifndef WOLFSSL_NO_CT_OPS +/* Constant time - mask set when a > b. */ +WC_STATIC WC_INLINE byte ctMaskGT(int a, int b) +{ + return (((word32)a - b - 1) >> 31) - 1; +} + +/* Constant time - mask set when a >= b. */ +WC_STATIC WC_INLINE byte ctMaskGTE(int a, int b) +{ + return (((word32)a - b ) >> 31) - 1; +} + +/* Constant time - mask set when a < b. */ +WC_STATIC WC_INLINE byte ctMaskLT(int a, int b) +{ + return (((word32)b - a - 1) >> 31) - 1; +} + +/* Constant time - mask set when a <= b. */ +WC_STATIC WC_INLINE byte ctMaskLTE(int a, int b) +{ + return (((word32)b - a ) >> 31) - 1; +} + +/* Constant time - mask set when a == b. */ +WC_STATIC WC_INLINE byte ctMaskEq(int a, int b) +{ + return 0 - (a == b); +} + +WC_STATIC WC_INLINE word16 ctMask16Eq(int a, int b) +{ + return 0 - (a == b); +} + +/* Constant time - mask set when a != b. */ +WC_STATIC WC_INLINE byte ctMaskNotEq(int a, int b) +{ + return 0 - (a != b); +} + +/* Constant time - select a when mask is set and b otherwise. */ +WC_STATIC WC_INLINE byte ctMaskSel(byte m, byte a, byte b) +{ + return (b & ((byte)~(word32)m)) | (a & m); +} + +/* Constant time - select integer a when mask is set and integer b otherwise. */ +WC_STATIC WC_INLINE int ctMaskSelInt(byte m, int a, int b) +{ + return (b & (~(signed int)(signed char)m)) | + (a & ( (signed int)(signed char)m)); +} + +/* Constant time - bit set when a <= b. */ +WC_STATIC WC_INLINE byte ctSetLTE(int a, int b) +{ + return ((word32)a - b - 1) >> 31; +} +#endif + + +#undef WC_STATIC + +#endif /* !WOLFSSL_MISC_INCLUDED && !NO_INLINE */ + +#endif /* WOLF_CRYPT_MISC_C */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/pkcs12.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/pkcs12.c new file mode 100755 index 0000000..d387784 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/pkcs12.c @@ -0,0 +1,2079 @@ +/* pkcs12.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#if !defined(NO_ASN) && !defined(NO_PWDBASED) && defined(HAVE_PKCS12) + +#include +#include +#include +#include +#include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif +#include +#include +#include + + +#define ERROR_OUT(err, eLabel) { ret = (err); goto eLabel; } + +enum { + WC_PKCS12_KeyBag = 667, + WC_PKCS12_ShroudedKeyBag = 668, + WC_PKCS12_CertBag = 669, + WC_PKCS12_CertBag_Type1 = 675, + WC_PKCS12_CrlBag = 670, + WC_PKCS12_SecretBag = 671, + WC_PKCS12_SafeContentsBag = 672, + WC_PKCS12_DATA = 651, + WC_PKCS12_ENCRYPTED_DATA = 656, + + WC_PKCS12_DATA_OBJ_SZ = 11, +}; + +/* static const byte WC_PKCS12_ENCRYPTED_OID[] = + {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x06}; */ +static const byte WC_PKCS12_DATA_OID[] = + {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x07, 0x01}; +static const byte WC_PKCS12_CertBag_Type1_OID[] = + {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x16, 0x01}; +static const byte WC_PKCS12_CertBag_OID[] = + {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0c, 0x0a, 0x01, 0x03}; +static const byte WC_PKCS12_KeyBag_OID[] = + {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0c, 0x0a, 0x01, 0x01}; +static const byte WC_PKCS12_ShroudedKeyBag_OID[] = + {0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x0c, 0x0a, 0x01, 0x02}; + + +typedef struct ContentInfo { + byte* data; + struct ContentInfo* next; + word32 encC; /* encryptedContent */ + word32 dataSz; + int type; /* DATA / encrypted / enveloped */ +} ContentInfo; + + +typedef struct AuthenticatedSafe { + ContentInfo* CI; + byte* data; /* T contents.... */ + word32 oid; /* encrypted or not */ + word32 numCI; /* number of Content Info structs */ + word32 dataSz; +} AuthenticatedSafe; + + +typedef struct MacData { + byte* digest; + byte* salt; + word32 oid; + word32 digestSz; + word32 saltSz; + int itt; /* number of iterations when creating HMAC key */ +} MacData; + + +struct WC_PKCS12 { + void* heap; + AuthenticatedSafe* safe; + MacData* signData; + word32 oid; /* DATA / Enveloped DATA ... */ +}; + + +/* for friendlyName, localKeyId .... */ +typedef struct WC_PKCS12_ATTRIBUTE { + byte* data; + word32 oid; + word32 dataSz; +} WC_PKCS12_ATTRIBUTE; + + +WC_PKCS12* wc_PKCS12_new(void) +{ + WC_PKCS12* pkcs12 = (WC_PKCS12*)XMALLOC(sizeof(WC_PKCS12), + NULL, DYNAMIC_TYPE_PKCS); + if (pkcs12 == NULL) { + WOLFSSL_MSG("Memory issue when creating WC_PKCS12 struct"); + return NULL; + } + + XMEMSET(pkcs12, 0, sizeof(WC_PKCS12)); + + return pkcs12; +} + + +static void freeSafe(AuthenticatedSafe* safe, void* heap) +{ + int i; + + if (safe == NULL) { + return; + } + + /* free content info structs */ + for (i = safe->numCI; i > 0; i--) { + ContentInfo* ci = safe->CI; + safe->CI = ci->next; + XFREE(ci, heap, DYNAMIC_TYPE_PKCS); + } + if (safe->data != NULL) { + XFREE(safe->data, heap, DYNAMIC_TYPE_PKCS); + } + XFREE(safe, heap, DYNAMIC_TYPE_PKCS); + + (void)heap; +} + + +void wc_PKCS12_free(WC_PKCS12* pkcs12) +{ + void* heap; + + /* if null pointer is passed in do nothing */ + if (pkcs12 == NULL) { + WOLFSSL_MSG("Trying to free null WC_PKCS12 object"); + return; + } + + heap = pkcs12->heap; + if (pkcs12->safe != NULL) { + freeSafe(pkcs12->safe, heap); + } + + /* free mac data */ + if (pkcs12->signData != NULL) { + if (pkcs12->signData->digest != NULL) { + XFREE(pkcs12->signData->digest, heap, DYNAMIC_TYPE_DIGEST); + pkcs12->signData->digest = NULL; + } + if (pkcs12->signData->salt != NULL) { + XFREE(pkcs12->signData->salt, heap, DYNAMIC_TYPE_SALT); + pkcs12->signData->salt = NULL; + } + XFREE(pkcs12->signData, heap, DYNAMIC_TYPE_PKCS); + pkcs12->signData = NULL; + } + + XFREE(pkcs12, NULL, DYNAMIC_TYPE_PKCS); + pkcs12 = NULL; +} + + +static int GetSafeContent(WC_PKCS12* pkcs12, const byte* input, + word32* idx, int maxIdx) +{ + AuthenticatedSafe* safe; + word32 oid; + word32 localIdx = *idx; + int ret; + int size = 0; + + safe = (AuthenticatedSafe*)XMALLOC(sizeof(AuthenticatedSafe), pkcs12->heap, + DYNAMIC_TYPE_PKCS); + if (safe == NULL) { + return MEMORY_E; + } + XMEMSET(safe, 0, sizeof(AuthenticatedSafe)); + + ret = GetObjectId(input, &localIdx, &oid, oidIgnoreType, maxIdx); + if (ret < 0) { + WOLFSSL_LEAVE("Get object id failed", ret); + freeSafe(safe, pkcs12->heap); + return ASN_PARSE_E; + } + + safe->oid = oid; + /* check tag, length */ + if (input[localIdx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { + WOLFSSL_MSG("Unexpected tag in PKCS12 DER"); + freeSafe(safe, pkcs12->heap); + return ASN_PARSE_E; + } + if ((ret = GetLength(input, &localIdx, &size, maxIdx)) <= 0) { + freeSafe(safe, pkcs12->heap); + return ret; + } + + switch (oid) { + case WC_PKCS12_ENCRYPTED_DATA: + WOLFSSL_MSG("Found PKCS12 OBJECT: ENCRYPTED DATA\n"); + break; + + case WC_PKCS12_DATA: + WOLFSSL_MSG("Found PKCS12 OBJECT: DATA"); + /* get octets holding contents */ + if (input[localIdx++] != ASN_OCTET_STRING) { + WOLFSSL_MSG("Wrong tag with content PKCS12 type DATA"); + freeSafe(safe, pkcs12->heap); + return ASN_PARSE_E; + } + if ((ret = GetLength(input, &localIdx, &size, maxIdx)) <= 0) { + freeSafe(safe, pkcs12->heap); + return ret; + } + + break; + } + + safe->dataSz = size; + safe->data = (byte*)XMALLOC(size, pkcs12->heap, DYNAMIC_TYPE_PKCS); + if (safe->data == NULL) { + freeSafe(safe, pkcs12->heap); + return MEMORY_E; + } + XMEMCPY(safe->data, input + localIdx, size); + *idx = localIdx; + + /* an instance of AuthenticatedSafe is created from + * ContentInfo's strung together in a SEQUENCE. Here we iterate + * through the ContentInfo's and add them to our + * AuthenticatedSafe struct */ + localIdx = 0; + input = safe->data; + { + int CISz; + ret = GetSequence(input, &localIdx, &CISz, safe->dataSz); + if (ret < 0) { + freeSafe(safe, pkcs12->heap); + return ASN_PARSE_E; + } + CISz += localIdx; + while ((int)localIdx < CISz) { + int curSz = 0; + word32 curIdx; + ContentInfo* ci = NULL; + + #ifdef WOLFSSL_DEBUG_PKCS12 + printf("\t\tlooking for Content Info.... "); + #endif + + if ((ret = GetSequence(input, &localIdx, &curSz, safe->dataSz)) + < 0) { + freeSafe(safe, pkcs12->heap); + return ret; + } + + if (curSz > CISz) { + /* subset should not be larger than universe */ + freeSafe(safe, pkcs12->heap); + return ASN_PARSE_E; + } + + curIdx = localIdx; + if ((ret = GetObjectId(input, &localIdx, &oid, oidIgnoreType, + safe->dataSz)) < 0) { + WOLFSSL_LEAVE("Get object id failed", ret); + freeSafe(safe, pkcs12->heap); + return ret; + } + + /* create new content info struct ... possible OID sanity check? */ + ci = (ContentInfo*)XMALLOC(sizeof(ContentInfo), pkcs12->heap, + DYNAMIC_TYPE_PKCS); + if (ci == NULL) { + freeSafe(safe, pkcs12->heap); + return MEMORY_E; + } + + ci->type = oid; + ci->dataSz = curSz - (localIdx-curIdx); + ci->data = (byte*)input + localIdx; + localIdx += ci->dataSz; + + #ifdef WOLFSSL_DEBUG_PKCS12 + switch (oid) { + case WC_PKCS12_ENCRYPTED_DATA: + printf("CONTENT INFO: ENCRYPTED DATA, size = %d\n", ci->dataSz); + break; + + case WC_PKCS12_DATA: + printf("CONTENT INFO: DATA, size = %d\n", ci->dataSz); + break; + default: + printf("CONTENT INFO: UNKNOWN, size = %d\n", ci->dataSz); + } + #endif + + /* insert to head of list */ + ci->next = safe->CI; + safe->CI = ci; + safe->numCI += 1; + } + } + + pkcs12->safe = safe; + *idx += localIdx; + + return ret; +} + + +/* optional mac data */ +static int GetSignData(WC_PKCS12* pkcs12, const byte* mem, word32* idx, + word32 totalSz) +{ + MacData* mac; + word32 curIdx = *idx; + word32 oid = 0; + int size, ret; + + /* Digest Info : Sequence + * DigestAlgorithmIdentifier + * Digest + */ + if ((ret = GetSequence(mem, &curIdx, &size, totalSz)) <= 0) { + WOLFSSL_MSG("Failed to get PKCS12 sequence"); + return ret; + } + +#ifdef WOLFSSL_DEBUG_PKCS12 + printf("\t\tSEQUENCE: DigestInfo size = %d\n", size); +#endif + + mac = (MacData*)XMALLOC(sizeof(MacData), pkcs12->heap, DYNAMIC_TYPE_PKCS); + if (mac == NULL) { + return MEMORY_E; + } + XMEMSET(mac, 0, sizeof(MacData)); + + /* DigestAlgorithmIdentifier */ + if ((ret = GetAlgoId(mem, &curIdx, &oid, oidIgnoreType, totalSz)) < 0) { + WOLFSSL_MSG("Failed to get PKCS12 sequence"); + XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS); + return ret; + } + mac->oid = oid; + +#ifdef WOLFSSL_DEBUG_PKCS12 + printf("\t\tALGO ID = %d\n", oid); +#endif + + /* Digest: should be octet type holding digest */ + if (mem[curIdx++] != ASN_OCTET_STRING) { + WOLFSSL_MSG("Failed to get digest"); + XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS); + return ASN_PARSE_E; + } + + if ((ret = GetLength(mem, &curIdx, &size, totalSz)) <= 0) { + XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS); + return ret; + } + mac->digestSz = size; + mac->digest = (byte*)XMALLOC(mac->digestSz, pkcs12->heap, + DYNAMIC_TYPE_DIGEST); + if (mac->digest == NULL || mac->digestSz + curIdx > totalSz) { + ERROR_OUT(MEMORY_E, exit_gsd); + } + XMEMCPY(mac->digest, mem + curIdx, mac->digestSz); + +#ifdef WOLFSSL_DEBUG_PKCS12 + { + byte* p; + for (printf("\t\tDigest = "), p = (byte*)mem+curIdx; + p < (byte*)mem + curIdx + mac->digestSz; + printf("%02X", *p), p++); + printf(" : size = %d\n", mac->digestSz); + } +#endif + + curIdx += mac->digestSz; + + /* get salt, should be octet string */ + if (mem[curIdx++] != ASN_OCTET_STRING) { + WOLFSSL_MSG("Failed to get salt"); + ERROR_OUT(ASN_PARSE_E, exit_gsd); + } + + if ((ret = GetLength(mem, &curIdx, &size, totalSz)) < 0) { + goto exit_gsd; + } + mac->saltSz = size; + mac->salt = (byte*)XMALLOC(mac->saltSz, pkcs12->heap, DYNAMIC_TYPE_SALT); + if (mac->salt == NULL || mac->saltSz + curIdx > totalSz) { + ERROR_OUT(MEMORY_E, exit_gsd); + } + XMEMCPY(mac->salt, mem + curIdx, mac->saltSz); + +#ifdef WOLFSSL_DEBUG_PKCS12 + { + byte* p; + for (printf("\t\tSalt = "), p = (byte*)mem + curIdx; + p < (byte*)mem + curIdx + mac->saltSz; + printf("%02X", *p), p++); + printf(" : size = %d\n", mac->saltSz); + } +#endif + + curIdx += mac->saltSz; + + /* check for MAC iterations, default to 1 */ + mac->itt = WC_PKCS12_MAC_DEFAULT; + if (curIdx < totalSz) { + int number = 0; + if ((ret = GetShortInt(mem, &curIdx, &number, totalSz)) >= 0) { + /* found a iteration value */ + mac->itt = number; + } + } + +#ifdef WOLFSSL_DEBUG_PKCS12 + printf("\t\tITERATIONS : %d\n", mac->itt); +#endif + + *idx = curIdx; + pkcs12->signData = mac; + ret = 0; /* success */ + +exit_gsd: + + /* failure cleanup */ + if (ret != 0) { + if (mac) { + if (mac->digest) + XFREE(mac->digest, pkcs12->heap, DYNAMIC_TYPE_DIGEST); + XFREE(mac, pkcs12->heap, DYNAMIC_TYPE_PKCS); + } + } + + return ret; +} + + +/* expects PKCS12 signData to be set up with OID + * + * returns the size of mac created on success. A negative value will be returned + * in the case that an error happened. + */ +static int wc_PKCS12_create_mac(WC_PKCS12* pkcs12, byte* data, word32 dataSz, + const byte* psw, word32 pswSz, byte* out, word32 outSz) +{ + Hmac hmac; + MacData* mac; + int ret, kLen; + enum wc_HashType hashT; + int idx = 0; + int id = 3; /* value from RFC 7292 indicating key is used for MAC */ + word32 i; + byte unicodePasswd[MAX_UNICODE_SZ]; + byte key[MAX_KEY_SIZE]; + + if (pkcs12 == NULL || pkcs12->signData == NULL || data == NULL || + out == NULL) { + return BAD_FUNC_ARG; + } + + mac = pkcs12->signData; + + /* unicode set up from asn.c */ + if ((pswSz * 2 + 2) > (int)sizeof(unicodePasswd)) { + WOLFSSL_MSG("PKCS12 max unicode size too small"); + return UNICODE_SIZE_E; + } + + for (i = 0; i < pswSz; i++) { + unicodePasswd[idx++] = 0x00; + unicodePasswd[idx++] = (byte)psw[i]; + } + /* add trailing NULL */ + unicodePasswd[idx++] = 0x00; + unicodePasswd[idx++] = 0x00; + + /* get hash type used and resulting size of HMAC key */ + hashT = wc_OidGetHash(mac->oid); + if (hashT == WC_HASH_TYPE_NONE) { + WOLFSSL_MSG("Unsupported hash used"); + return BAD_FUNC_ARG; + } + kLen = wc_HashGetDigestSize(hashT); + + /* check out buffer is large enough */ + if (kLen < 0 || outSz < (word32)kLen) { + return BAD_FUNC_ARG; + } + + /* idx contains size of unicodePasswd */ + if ((ret = wc_PKCS12_PBKDF_ex(key, unicodePasswd, idx, mac->salt, + mac->saltSz, mac->itt, kLen, (int)hashT, id, pkcs12->heap)) < 0) { + return ret; + } + + /* now that key has been created use it to get HMAC hash on data */ + if ((ret = wc_HmacInit(&hmac, pkcs12->heap, INVALID_DEVID)) != 0) { + return ret; + } + ret = wc_HmacSetKey(&hmac, (int)hashT, key, kLen); + if (ret == 0) + ret = wc_HmacUpdate(&hmac, data, dataSz); + if (ret == 0) + ret = wc_HmacFinal(&hmac, out); + wc_HmacFree(&hmac); + + if (ret != 0) + return ret; + + return kLen; /* same as digest size */ +} + + +/* check mac on pkcs12, pkcs12->mac has been sanity checked before entering * + * returns the result of comparison, success is 0 */ +static int wc_PKCS12_verify(WC_PKCS12* pkcs12, byte* data, word32 dataSz, + const byte* psw, word32 pswSz) +{ + MacData* mac; + int ret; + byte digest[WC_MAX_DIGEST_SIZE]; + + if (pkcs12 == NULL || pkcs12->signData == NULL || data == NULL) { + return BAD_FUNC_ARG; + } + + mac = pkcs12->signData; + +#ifdef WOLFSSL_DEBUG_PKCS12 + printf("Verifying MAC with OID = %d\n", mac->oid); +#endif + + /* check if this builds digest size is too small */ + if (mac->digestSz > WC_MAX_DIGEST_SIZE) { + WOLFSSL_MSG("PKCS12 max digest size too small"); + return BAD_FUNC_ARG; + } + + if ((ret = wc_PKCS12_create_mac(pkcs12, data, dataSz, psw, pswSz, + digest, WC_MAX_DIGEST_SIZE)) < 0) { + return ret; + } + +#ifdef WOLFSSL_DEBUG_PKCS12 + { + byte* p; + for (printf("\t\tHash = "), p = (byte*)digest; + p < (byte*)digest + mac->digestSz; + printf("%02X", *p), p++); + printf(" : size = %d\n", mac->digestSz); + } +#endif + + return XMEMCMP(digest, mac->digest, mac->digestSz); +} + + +/* Convert DER format stored in der buffer to WC_PKCS12 struct + * Puts the raw contents of Content Info into structure without completely + * parsing or decoding. + * der : pointer to der buffer holding PKCS12 + * derSz : size of der buffer + * pkcs12 : non-null pkcs12 pointer + * return 0 on success and negative on failure. + */ +int wc_d2i_PKCS12(const byte* der, word32 derSz, WC_PKCS12* pkcs12) +{ + word32 idx = 0; + word32 totalSz = 0; + int ret; + int size = 0; + int version = 0; + + WOLFSSL_ENTER("wolfSSL_d2i_PKCS12_bio"); + + if (der == NULL || pkcs12 == NULL) { + return BAD_FUNC_ARG; + } + + totalSz = derSz; + if ((ret = GetSequence(der, &idx, &size, totalSz)) <= 0) { + WOLFSSL_MSG("Failed to get PKCS12 sequence"); + return ret; + } + + /* get version */ + if ((ret = GetMyVersion(der, &idx, &version, totalSz)) < 0) { + return ret; + } + +#ifdef WOLFSSL_DEBUG_PKCS12 + printf("\nBEGIN: PKCS12 size = %d\n", totalSz); + printf("version = %d\n", version); +#endif + + if (version != 3) { + WOLFSSL_MSG("PKCS12 unsupported version!"); + return ASN_VERSION_E; + } + + if ((ret = GetSequence(der, &idx, &size, totalSz)) < 0) { + return ret; + } + +#ifdef WOLFSSL_DEBUG_PKCS12 + printf("\tSEQUENCE: AuthenticatedSafe size = %d\n", size); +#endif + + if ((ret = GetSafeContent(pkcs12, der, &idx, size + idx)) < 0) { + WOLFSSL_MSG("GetSafeContent error"); + return ret; + } + + /* if more buffer left check for MAC data */ + if (idx < totalSz) { + if ((ret = GetSequence(der, &idx, &size, totalSz)) < 0) { + WOLFSSL_MSG("Ignoring unknown data at end of PKCS12 DER buffer"); + } + else { + #ifdef WOLFSSL_DEBUG_PKCS12 + printf("\tSEQUENCE: Signature size = %d\n", size); + #endif + + if ((ret = GetSignData(pkcs12, der, &idx, totalSz)) < 0) { + return ASN_PARSE_E; + } + } + } + +#ifdef WOLFSSL_DEBUG_PKCS12 + printf("END: PKCS12\n"); +#endif + + return ret; +} + + +/* helper function to free WC_DerCertList */ +void wc_FreeCertList(WC_DerCertList* list, void* heap) +{ + WC_DerCertList* current = list; + WC_DerCertList* next; + + if (list == NULL) { + return; + } + + while (current != NULL) { + next = current->next; + if (current->buffer != NULL) { + XFREE(current->buffer, heap, DYNAMIC_TYPE_PKCS); + } + XFREE(current, heap, DYNAMIC_TYPE_PKCS); + current = next; + } + + (void)heap; +} + +static void freeDecCertList(WC_DerCertList** list, byte** pkey, word32* pkeySz, + byte** cert, word32* certSz, void* heap) +{ + WC_DerCertList* current = *list; + WC_DerCertList* previous = NULL; + DecodedCert DeCert; + + while (current != NULL) { + + InitDecodedCert(&DeCert, current->buffer, current->bufferSz, heap); + if (ParseCertRelative(&DeCert, CERT_TYPE, NO_VERIFY, NULL) == 0) { + if (wc_CheckPrivateKey(*pkey, *pkeySz, &DeCert) == 1) { + WOLFSSL_MSG("Key Pair found"); + *cert = current->buffer; + *certSz = current->bufferSz; + + if (previous == NULL) { + *list = current->next; + } + else { + previous->next = current->next; + } + FreeDecodedCert(&DeCert); + XFREE(current, heap, DYNAMIC_TYPE_PKCS); + break; + } + } + FreeDecodedCert(&DeCert); + + previous = current; + current = current->next; + } +} + + +/* return 0 on success and negative on failure. + * By side effect returns private key, cert, and optionally ca. + * Parses and decodes the parts of PKCS12 + * + * NOTE: can parse with USER RSA enabled but may return cert that is not the + * pair for the key when using RSA key pairs. + * + * pkcs12 : non-null WC_PKCS12 struct + * psw : password to use for PKCS12 decode + * pkey : Private key returned + * cert : x509 cert returned + * ca : optional ca returned + */ +int wc_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, + byte** pkey, word32* pkeySz, byte** cert, word32* certSz, + WC_DerCertList** ca) +{ + ContentInfo* ci = NULL; + WC_DerCertList* certList = NULL; + WC_DerCertList* tailList = NULL; + byte* buf = NULL; + word32 i, oid; + int ret, pswSz; + word32 algId; + + WOLFSSL_ENTER("wc_PKCS12_parse"); + + if (pkcs12 == NULL || psw == NULL || cert == NULL || certSz == NULL || + pkey == NULL || pkeySz == NULL) { + return BAD_FUNC_ARG; + } + + pswSz = (int)XSTRLEN(psw); + *cert = NULL; + *pkey = NULL; + if (ca != NULL) + *ca = NULL; + + /* if there is sign data then verify the MAC */ + if (pkcs12->signData != NULL ) { + if ((ret = wc_PKCS12_verify(pkcs12, pkcs12->safe->data, + pkcs12->safe->dataSz, (byte*)psw, pswSz)) != 0) { + WOLFSSL_MSG("PKCS12 Bad MAC on verify"); + WOLFSSL_LEAVE("wc_PKCS12_parse verify ", ret); + return MAC_CMP_FAILED_E; + } + } + + if (pkcs12->safe == NULL) { + WOLFSSL_MSG("No PKCS12 safes to parse"); + return BAD_FUNC_ARG; + } + + /* Decode content infos */ + ci = pkcs12->safe->CI; + for (i = 0; i < pkcs12->safe->numCI; i++) { + byte* data; + word32 idx = 0; + int size, totalSz; + + if (ci->type == WC_PKCS12_ENCRYPTED_DATA) { + int number; + + WOLFSSL_MSG("Decrypting PKCS12 Content Info Container"); + data = ci->data; + if (data[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { + ERROR_OUT(ASN_PARSE_E, exit_pk12par); + } + if ((ret = GetLength(data, &idx, &size, ci->dataSz)) < 0) { + goto exit_pk12par; + } + + if ((ret = GetSequence(data, &idx, &size, ci->dataSz)) < 0) { + goto exit_pk12par; + } + + if ((ret = GetShortInt(data, &idx, &number, ci->dataSz)) < 0) { + goto exit_pk12par; + } + + if (number != 0) { + WOLFSSL_MSG("Expecting 0 for Integer with Encrypted PKCS12"); + } + + if ((ret = GetSequence(data, &idx, &size, ci->dataSz)) < 0) { + goto exit_pk12par; + } + + ret = GetObjectId(data, &idx, &oid, oidIgnoreType, ci->dataSz); + if (ret < 0 || oid != WC_PKCS12_DATA) { + WOLFSSL_MSG("Not PKCS12 DATA object or get object parse error"); + ERROR_OUT(ASN_PARSE_E, exit_pk12par); + } + + /* decrypted content overwrites input buffer */ + size = ci->dataSz - idx; + buf = (byte*)XMALLOC(size, pkcs12->heap, DYNAMIC_TYPE_PKCS); + if (buf == NULL) { + ERROR_OUT(MEMORY_E, exit_pk12par); + } + XMEMCPY(buf, data + idx, size); + + if ((ret = DecryptContent(buf, size, psw, pswSz)) < 0) { + WOLFSSL_MSG("Decryption failed, algorithm not compiled in?"); + goto exit_pk12par; + } + + data = buf; + idx = 0; + + #ifdef WOLFSSL_DEBUG_PKCS12 + { + byte* p; + for (printf("\tData = "), p = (byte*)buf; + p < (byte*)buf + size; + printf("%02X", *p), p++); + printf("\n"); + } + #endif + } + else { /* type DATA */ + WOLFSSL_MSG("Parsing PKCS12 DATA Content Info Container"); + data = ci->data; + if (data[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { + ERROR_OUT(ASN_PARSE_E, exit_pk12par); + } + if ((ret = GetLength(data, &idx, &size, ci->dataSz)) <= 0) { + goto exit_pk12par; + } + if (data[idx++] != ASN_OCTET_STRING) { + ERROR_OUT(ASN_PARSE_E, exit_pk12par); + } + if ((ret = GetLength(data, &idx, &size, ci->dataSz)) < 0) { + goto exit_pk12par; + } + + } + + /* parse through bags in ContentInfo */ + if ((ret = GetSequence(data, &idx, &totalSz, ci->dataSz)) < 0) { + goto exit_pk12par; + } + totalSz += idx; + + while ((int)idx < totalSz) { + int bagSz; + if ((ret = GetSequence(data, &idx, &bagSz, ci->dataSz)) < 0) { + goto exit_pk12par; + } + bagSz += idx; + + if ((ret = GetObjectId(data, &idx, &oid, oidIgnoreType, + ci->dataSz)) < 0) { + goto exit_pk12par; + } + + switch (oid) { + case WC_PKCS12_KeyBag: /* 667 */ + WOLFSSL_MSG("PKCS12 Key Bag found"); + if (data[idx++] != + (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { + ERROR_OUT(ASN_PARSE_E, exit_pk12par); + } + if ((ret = GetLength(data, &idx, &size, ci->dataSz)) <= 0) { + goto exit_pk12par; + } + if (*pkey == NULL) { + *pkey = (byte*)XMALLOC(size, pkcs12->heap, + DYNAMIC_TYPE_PUBLIC_KEY); + if (*pkey == NULL) { + ERROR_OUT(MEMORY_E, exit_pk12par); + } + XMEMCPY(*pkey, data + idx, size); + *pkeySz = ToTraditional_ex(*pkey, size, &algId); + } + + #ifdef WOLFSSL_DEBUG_PKCS12 + { + byte* p; + for (printf("\tKey = "), p = (byte*)*pkey; + p < (byte*)*pkey + size; + printf("%02X", *p), p++); + printf("\n"); + } + #endif + idx += size; + break; + + case WC_PKCS12_ShroudedKeyBag: /* 668 */ + { + byte* k; + + WOLFSSL_MSG("PKCS12 Shrouded Key Bag found"); + if (data[idx++] != + (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { + ERROR_OUT(ASN_PARSE_E, exit_pk12par); + } + if ((ret = GetLength(data, &idx, &size, + ci->dataSz)) < 0) { + goto exit_pk12par; + } + + k = (byte*)XMALLOC(size, pkcs12->heap, + DYNAMIC_TYPE_PUBLIC_KEY); + if (k == NULL) { + ERROR_OUT(MEMORY_E, exit_pk12par); + } + XMEMCPY(k, data + idx, size); + + /* overwrites input, be warned */ + if ((ret = ToTraditionalEnc(k, size, psw, pswSz, + &algId)) < 0) { + XFREE(k, pkcs12->heap, DYNAMIC_TYPE_PUBLIC_KEY); + goto exit_pk12par; + } + + if (ret < size) { + /* shrink key buffer */ + byte* tmp = (byte*)XMALLOC(ret, pkcs12->heap, + DYNAMIC_TYPE_PUBLIC_KEY); + if (tmp == NULL) { + XFREE(k, pkcs12->heap, DYNAMIC_TYPE_PUBLIC_KEY); + ERROR_OUT(MEMORY_E, exit_pk12par); + } + XMEMCPY(tmp, k, ret); + XFREE(k, pkcs12->heap, DYNAMIC_TYPE_PUBLIC_KEY); + k = tmp; + } + size = ret; + + if (*pkey == NULL) { + *pkey = k; + *pkeySz = size; + } + else { /* only expecting one key */ + XFREE(k, pkcs12->heap, DYNAMIC_TYPE_PUBLIC_KEY); + } + idx += size; + + #ifdef WOLFSSL_DEBUG_PKCS12 + { + byte* p; + for (printf("\tKey = "), p = (byte*)k; + p < (byte*)k + ret; + printf("%02X", *p), p++); + printf("\n"); + } + #endif + } + break; + + case WC_PKCS12_CertBag: /* 669 */ + { + WC_DerCertList* node; + WOLFSSL_MSG("PKCS12 Cert Bag found"); + if (data[idx++] != + (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { + ERROR_OUT(ASN_PARSE_E, exit_pk12par); + } + if ((ret = GetLength(data, &idx, &size, ci->dataSz)) < 0) { + goto exit_pk12par; + } + + /* get cert bag type */ + if ((ret = GetSequence(data, &idx, &size, ci->dataSz)) <0) { + goto exit_pk12par; + } + + if ((ret = GetObjectId(data, &idx, &oid, oidIgnoreType, + ci->dataSz)) < 0) { + goto exit_pk12par; + } + + switch (oid) { + case WC_PKCS12_CertBag_Type1: /* 675 */ + /* type 1 */ + WOLFSSL_MSG("PKCS12 cert bag type 1"); + if (data[idx++] != + (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC)) { + ERROR_OUT(ASN_PARSE_E, exit_pk12par); + } + if ((ret = GetLength(data, &idx, &size, ci->dataSz)) + <= 0) { + goto exit_pk12par; + } + if (data[idx++] != ASN_OCTET_STRING) { + ERROR_OUT(ASN_PARSE_E, exit_pk12par); + + } + if ((ret = GetLength(data, &idx, &size, ci->dataSz)) + < 0) { + goto exit_pk12par; + } + break; + default: + WOLFSSL_MSG("Unknown PKCS12 cert bag type"); + } + + if (size + idx > (word32)bagSz) { + ERROR_OUT(ASN_PARSE_E, exit_pk12par); + } + + /* list to hold all certs found */ + node = (WC_DerCertList*)XMALLOC(sizeof(WC_DerCertList), + pkcs12->heap, DYNAMIC_TYPE_PKCS); + if (node == NULL) { + ERROR_OUT(MEMORY_E, exit_pk12par); + } + XMEMSET(node, 0, sizeof(WC_DerCertList)); + + node->buffer = (byte*)XMALLOC(size, pkcs12->heap, + DYNAMIC_TYPE_PKCS); + if (node->buffer == NULL) { + XFREE(node, pkcs12->heap, DYNAMIC_TYPE_PKCS); + ERROR_OUT(MEMORY_E, exit_pk12par); + } + XMEMCPY(node->buffer, data + idx, size); + node->bufferSz = size; + + /* put the new node into the list */ + if (certList != NULL) { + WOLFSSL_MSG("Pushing new cert onto queue"); + tailList->next = node; + tailList = node; + } + else { + certList = node; + tailList = node; + } + + /* on to next */ + idx += size; + } + break; + + case WC_PKCS12_CrlBag: /* 670 */ + WOLFSSL_MSG("PKCS12 CRL BAG not yet supported"); + break; + + case WC_PKCS12_SecretBag: /* 671 */ + WOLFSSL_MSG("PKCS12 Secret BAG not yet supported"); + break; + + case WC_PKCS12_SafeContentsBag: /* 672 */ + WOLFSSL_MSG("PKCS12 Safe Contents BAG not yet supported"); + break; + + default: + WOLFSSL_MSG("Unknown PKCS12 BAG type found"); + } + + /* Attribute, unknown bag or unsupported */ + if ((int)idx < bagSz) { + idx = bagSz; /* skip for now */ + } + } + + /* free temporary buffer */ + if (buf != NULL) { + XFREE(buf, pkcs12->heap, DYNAMIC_TYPE_PKCS); + buf = NULL; + } + + ci = ci->next; + WOLFSSL_MSG("Done Parsing PKCS12 Content Info Container"); + } + + /* check if key pair, remove from list */ + if (*pkey != NULL) { + freeDecCertList(&certList, pkey, pkeySz, cert, certSz, pkcs12->heap); + } + + /* if ca arg provided return certList, otherwise free it */ + if (ca != NULL) { + *ca = certList; + } + else { + /* free list, not wanted */ + wc_FreeCertList(certList, pkcs12->heap); + } + (void)tailList; /* not used */ + + ret = 0; /* success */ + +exit_pk12par: + + if (ret != 0) { + /* failure cleanup */ + if (*pkey) { + XFREE(*pkey, pkcs12->heap, DYNAMIC_TYPE_PUBLIC_KEY); + *pkey = NULL; + } + if (buf) { + XFREE(buf, pkcs12->heap, DYNAMIC_TYPE_PKCS); + buf = NULL; + } + + wc_FreeCertList(certList, pkcs12->heap); + } + + return ret; +} + + +/* Helper function to shroud keys. + * + * pkcs12 structure to use with shrouding key + * rng random number generator used + * out buffer to hold results + * outSz size of out buffer + * key key that is going to be shrouded + * keySz size of key buffer + * vAlgo algorithm version + * pass password to use + * passSz size of pass buffer + * itt number of iterations + * + * returns the size of the shrouded key on success + */ +static int wc_PKCS12_shroud_key(WC_PKCS12* pkcs12, WC_RNG* rng, + byte* out, word32* outSz, byte* key, word32 keySz, int vAlgo, + const char* pass, int passSz, int itt) +{ + void* heap; + word32 tmpIdx = 0; + int vPKCS = 1; /* PKCS#12 default set to 1 */ + word32 sz; + word32 totalSz = 0; + int ret; + + + if (outSz == NULL || pkcs12 == NULL || rng == NULL || key == NULL || + pass == NULL) { + return BAD_FUNC_ARG; + } + + heap = wc_PKCS12_GetHeap(pkcs12); + + /* check if trying to get size */ + if (out != NULL) { + tmpIdx += MAX_LENGTH_SZ + 1; /* save room for length and tag (+1) */ + sz = *outSz - tmpIdx; + } + + /* case of no encryption */ + if (vAlgo < 0) { + const byte* curveOID = NULL; + word32 oidSz = 0; + int algoID; + + WOLFSSL_MSG("creating PKCS12 Key Bag"); + + /* check key type and get OID if ECC */ + if ((ret = wc_GetKeyOID(key, keySz, &curveOID, &oidSz, &algoID, heap)) + < 0) { + return ret; + } + + /* PKCS#8 wrapping around key */ + ret = wc_CreatePKCS8Key(out + tmpIdx, &sz, key, keySz, algoID, + curveOID, oidSz); + } + else { + WOLFSSL_MSG("creating PKCS12 Shrouded Key Bag"); + + if (vAlgo == PBE_SHA1_DES) { + vPKCS = PKCS5; + vAlgo = 10; + } + + ret = UnTraditionalEnc(key, keySz, out + tmpIdx, &sz, pass, passSz, + vPKCS, vAlgo, NULL, 0, itt, rng, heap); + } + if (ret == LENGTH_ONLY_E) { + *outSz = sz + MAX_LENGTH_SZ + 1; + return LENGTH_ONLY_E; + } + if (ret < 0) { + return ret; + } + + totalSz += ret; + + /* out should not be null at this point but check before writing */ + if (out == NULL) { + return BAD_FUNC_ARG; + } + + /* rewind index and set tag and length */ + tmpIdx -= MAX_LENGTH_SZ + 1; + sz = SetExplicit(0, ret, out + tmpIdx); + tmpIdx += sz; totalSz += sz; + XMEMMOVE(out + tmpIdx, out + MAX_LENGTH_SZ + 1, ret); + + return totalSz; +} + + +/* Helper function to create key bag. + * + * pkcs12 structure to use with key bag + * rng random number generator used + * out buffer to hold results + * outSz size of out buffer + * key key that is going into key bag + * keySz size of key buffer + * algo algorithm version + * iter number of iterations + * pass password to use + * passSz size of pass buffer + * + * returns the size of the key bag on success + */ +static int wc_PKCS12_create_key_bag(WC_PKCS12* pkcs12, WC_RNG* rng, + byte* out, word32* outSz, byte* key, word32 keySz, int algo, int iter, + char* pass, int passSz) +{ + void* heap; + byte* tmp; + word32 length = 0; + word32 idx = 0; + word32 totalSz = 0; + word32 sz; + word32 i; + word32 tmpSz; + int ret; + + /* get max size for shrouded key */ + ret = wc_PKCS12_shroud_key(pkcs12, rng, NULL, &length, key, keySz, + algo, pass, passSz, iter); + if (ret != LENGTH_ONLY_E && ret < 0) { + return ret; + } + + if (out == NULL) { + *outSz = MAX_SEQ_SZ + WC_PKCS12_DATA_OBJ_SZ + 1 + MAX_LENGTH_SZ + + length; + return LENGTH_ONLY_E; + } + + heap = wc_PKCS12_GetHeap(pkcs12); + + /* leave room for sequence */ + idx += MAX_SEQ_SZ; + + if (algo < 0) { /* not encrypted */ + out[idx++] = ASN_OBJECT_ID; totalSz++; + sz = SetLength(sizeof(WC_PKCS12_KeyBag_OID), out + idx); + idx += sz; totalSz += sz; + for (i = 0; i < sizeof(WC_PKCS12_KeyBag_OID); i++) { + out[idx++] = WC_PKCS12_KeyBag_OID[i]; totalSz++; + } + } + else { /* encrypted */ + out[idx++] = ASN_OBJECT_ID; totalSz++; + sz = SetLength(sizeof(WC_PKCS12_ShroudedKeyBag_OID), out + idx); + idx += sz; totalSz += sz; + for (i = 0; i < sizeof(WC_PKCS12_ShroudedKeyBag_OID); i++) { + out[idx++] = WC_PKCS12_ShroudedKeyBag_OID[i]; totalSz++; + } + } + + /* shroud key */ + tmp = (byte*)XMALLOC(length, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) { + return MEMORY_E; + } + + ret = wc_PKCS12_shroud_key(pkcs12, rng, tmp, &length, key, keySz, + algo, pass, passSz, iter); + if (ret < 0) { + XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + length = ret; + XMEMCPY(out + idx, tmp, length); + XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + totalSz += length; + + /* set beginning sequence */ + tmpSz = SetSequence(totalSz, out); + XMEMMOVE(out + tmpSz, out + MAX_SEQ_SZ, totalSz); + + (void)heap; + return totalSz + tmpSz; +} + + +/* Helper function to create cert bag. + * + * pkcs12 structure to use with cert bag + * out buffer to hold results + * outSz size of out buffer + * cert cert that is going into cert bag + * certSz size of cert buffer + * + * returns the size of the cert bag on success + */ +static int wc_PKCS12_create_cert_bag(WC_PKCS12* pkcs12, + byte* out, word32* outSz, byte* cert, word32 certSz) +{ + word32 length = 0; + word32 idx = 0; + word32 totalSz = 0; + word32 sz; + int WC_CERTBAG_OBJECT_ID = 13; + int WC_CERTBAG1_OBJECT_ID = 12; + word32 i; + word32 tmpSz; + + if (out == NULL) { + *outSz = MAX_SEQ_SZ + WC_CERTBAG_OBJECT_ID + 1 + MAX_LENGTH_SZ + + MAX_SEQ_SZ + WC_CERTBAG1_OBJECT_ID + 1 + MAX_LENGTH_SZ + 1 + + MAX_LENGTH_SZ + certSz; + return LENGTH_ONLY_E; + } + + /* check buffer size able to handle max size */ + if (*outSz < (MAX_SEQ_SZ + WC_CERTBAG_OBJECT_ID + 1 + MAX_LENGTH_SZ + + MAX_SEQ_SZ + WC_CERTBAG1_OBJECT_ID + 1 + MAX_LENGTH_SZ + 1 + + MAX_LENGTH_SZ + certSz)) { + return BUFFER_E; + } + + /* save room for sequence */ + idx += MAX_SEQ_SZ; + + /* objectId WC_PKCS12_CertBag */ + out[idx++] = ASN_OBJECT_ID; totalSz++; + sz = SetLength(sizeof(WC_PKCS12_CertBag_OID), out + idx); + idx += sz; totalSz += sz; + for (i = 0; i < sizeof(WC_PKCS12_CertBag_OID); i++) { + out[idx++] = WC_PKCS12_CertBag_OID[i]; totalSz++; + } + + /**** Cert Bag type 1 ****/ + out[idx++] = (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC); totalSz++; + + /* save room for length and sequence */ + idx += MAX_LENGTH_SZ; + idx += MAX_SEQ_SZ; + + /* object id WC_PKCS12_CertBag_Type1 */ + out[idx++] = ASN_OBJECT_ID; length++; + sz = SetLength(sizeof(WC_PKCS12_CertBag_Type1_OID), out + idx); + idx += sz; length += sz; + for (i = 0; i < sizeof(WC_PKCS12_CertBag_Type1_OID); i++) { + out[idx++] = WC_PKCS12_CertBag_Type1_OID[i]; length++; + } + + out[idx++] = (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC); length++; + sz = 0; + idx += MAX_LENGTH_SZ; /* save room for length */ + + /* place the cert in the buffer */ + out[idx++] = ASN_OCTET_STRING; sz++; + tmpSz = SetLength(certSz, out + idx); + idx += tmpSz; sz += tmpSz; + XMEMCPY(out + idx, cert, certSz); + idx += certSz; sz += certSz; + + /* rewind idx and place length */ + idx -= (sz + MAX_LENGTH_SZ); + tmpSz = SetLength(sz, out + idx); + XMEMMOVE(out + idx + tmpSz, out + idx + MAX_LENGTH_SZ, sz); + idx += tmpSz + sz; length += tmpSz + sz; + + /* rewind idx and set sequence */ + idx -= (length + MAX_SEQ_SZ); + tmpSz = SetSequence(length, out + idx); + XMEMMOVE(out + idx + tmpSz, out + idx + MAX_SEQ_SZ, length); + length += tmpSz; + + /* place final length */ + idx -= MAX_LENGTH_SZ; + tmpSz = SetLength(length, out + idx); + XMEMMOVE(out + idx + tmpSz, out + idx + MAX_LENGTH_SZ, length); + length += tmpSz; + + /* place final sequence */ + totalSz += length; + tmpSz = SetSequence(totalSz, out); + XMEMMOVE(out + tmpSz, out + MAX_SEQ_SZ, totalSz); + + (void)pkcs12; + + return totalSz + tmpSz; +} + + +/* Helper function to encrypt content. + * + * pkcs12 structure to use with key bag + * rng random number generator used + * out buffer to hold results + * outSz size of out buffer + * content content to encrypt + * contentSz size of content buffer + * vAlgo algorithm version + * pass password to use + * passSz size of pass buffer + * iter number of iterations + * type content type i.e WC_PKCS12_ENCRYPTED_DATA or WC_PKCS12_DATA + * + * returns the size of result on success + */ +static int wc_PKCS12_encrypt_content(WC_PKCS12* pkcs12, WC_RNG* rng, + byte* out, word32* outSz, byte* content, word32 contentSz, int vAlgo, + const char* pass, int passSz, int iter, int type) +{ + void* heap; + int vPKCS = 1; /* PKCS#12 is always set to 1 */ + int ret; + byte* tmp; + word32 idx = 0; + word32 totalSz = 0; + word32 length = 0; + word32 tmpSz; + word32 encSz; + word32 i; + + WOLFSSL_MSG("encrypting PKCS12 content"); + + heap = wc_PKCS12_GetHeap(pkcs12); + + /* ENCRYPTED DATA + * ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC + * length + * sequence + * short int + * sequence + * get object id */ + if (type == WC_PKCS12_ENCRYPTED_DATA) { + if (out == NULL) { + *outSz = 1 + MAX_LENGTH_SZ + MAX_SEQ_SZ + MAX_VERSION_SZ + + MAX_SEQ_SZ + WC_PKCS12_DATA_OBJ_SZ; + ret = EncryptContent(NULL, contentSz + MAX_SEQ_SZ, NULL, &encSz, + pass, passSz, vPKCS, vAlgo, NULL, 0, iter, rng, heap); + if (ret != LENGTH_ONLY_E) { + return ret; + } + + *outSz += encSz; + return LENGTH_ONLY_E; + } + + if (*outSz < (1 + MAX_LENGTH_SZ + MAX_SEQ_SZ + MAX_VERSION_SZ)) { + return BUFFER_E; + } + out[idx++] = (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC); totalSz++; + + /* save room for length and sequence */ + idx += MAX_LENGTH_SZ; + idx += MAX_SEQ_SZ; + + tmpSz = SetMyVersion(0, out + idx, 0); + idx += tmpSz; length += tmpSz; + + encSz = contentSz; + if ((ret = EncryptContent(NULL, contentSz, NULL, &encSz, + pass, passSz, vPKCS, vAlgo, NULL, 0, iter, rng, heap)) < 0) { + if (ret != LENGTH_ONLY_E) { + return ret; + } + } + + if (*outSz < (idx + MAX_SEQ_SZ + WC_PKCS12_DATA_OBJ_SZ + encSz)) { + return BUFFER_E; + } + tmp = (byte*)XMALLOC(encSz, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) { + return MEMORY_E; + } + + if ((ret = EncryptContent(content, contentSz, tmp, &encSz, + pass, passSz, vPKCS, vAlgo, NULL, 0, iter, rng, heap)) < 0) { + XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + encSz = ret; + + #ifdef WOLFSSL_DEBUG_PKCS12 + { + byte* p; + for (printf("(size %u) Encrypted Content = ", encSz), + p = (byte*)tmp; + p < (byte*)tmp + encSz; + printf("%02X", *p), p++); + printf("\n"); + } + #endif + + tmpSz = SetSequence(WC_PKCS12_DATA_OBJ_SZ + encSz, out + idx); + idx += tmpSz; length += tmpSz; + + out[idx++] = ASN_OBJECT_ID; length++; + tmpSz = SetLength(sizeof(WC_PKCS12_DATA_OID), out + idx); + idx += tmpSz; length += tmpSz; + for (i = 0; i < sizeof(WC_PKCS12_DATA_OID); i++) { + out[idx++] = WC_PKCS12_DATA_OID[i]; length++; + } + + /* copy over encrypted data */ + XMEMCPY(out + idx, tmp, encSz); + XFREE(tmp, heap, DYNAMIC_TYPE_TMP_BUFFER); + idx += encSz; length += encSz; + + /* rewind and place sequence */ + idx -= (length + MAX_SEQ_SZ); + tmpSz = SetSequence(length, out + idx); + XMEMMOVE(out + idx + tmpSz, out + idx + MAX_SEQ_SZ, length); + length += tmpSz; + + /* now place length */ + idx -= MAX_LENGTH_SZ; + tmpSz = SetLength(length, out + idx); + XMEMMOVE(out + idx + tmpSz, out + idx + MAX_LENGTH_SZ, length); + totalSz += length + tmpSz; + + return totalSz; + } + + /* DATA + * ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC + * length + * ASN_OCTET_STRING + * length + * sequence containing all bags */ + if (type == WC_PKCS12_DATA) { + if (out == NULL) { + *outSz = 1 + MAX_LENGTH_SZ + 1 + MAX_LENGTH_SZ + contentSz; + return LENGTH_ONLY_E; + } + + if (*outSz < (1 + MAX_LENGTH_SZ + 1 + MAX_LENGTH_SZ + contentSz)) { + return BUFFER_E; + } + + out[idx++] = (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC); + totalSz++; + + /* save room for length */ + idx += MAX_LENGTH_SZ; + + out[idx++] = ASN_OCTET_STRING; length++; + tmpSz = SetLength(contentSz, out + idx); + idx += tmpSz; length += tmpSz; + + /* sequence containing all bags */ + XMEMCPY(out + idx, content, contentSz); + idx += contentSz; length += contentSz; + + idx -= (MAX_LENGTH_SZ + length); + tmpSz = SetLength(length, out + idx); + XMEMMOVE(out + idx + tmpSz, out + idx + MAX_LENGTH_SZ, length); + totalSz += length + tmpSz; + + return totalSz; + } + + WOLFSSL_MSG("Unknown/Unsupported content type"); + return BAD_FUNC_ARG; +} + + +/* + * pass : password to use with encryption + * passSz : size of the password buffer + * name : friendlyName to use + * key : DER format of key + * keySz : size of key buffer + * cert : DER format of certificate + * certSz : size of the certificate buffer + * ca : a list of extra certificates + * nidKey : type of encryption to use on the key (-1 means no encryption) + * nidCert : type of encryption to use on the certificate + * (-1 means no encryption) + * iter : number of iterations with encryption + * macIter : number of iterations when creating MAC + * keyType : flag for signature and/or encryption key + * heap : pointer to allocate from memory + * + * returns a pointer to a new WC_PKCS12 structure on success and NULL if failed + */ +WC_PKCS12* wc_PKCS12_create(char* pass, word32 passSz, char* name, + byte* key, word32 keySz, byte* cert, word32 certSz, WC_DerCertList* ca, + int nidKey, int nidCert, int iter, int macIter, int keyType, void* heap) +{ + WC_PKCS12* pkcs12; + AuthenticatedSafe* safe; + ContentInfo* ci; + WC_RNG rng; + int algo; + int ret; + int type; + word32 idx; + word32 sz; + word32 tmpSz; + + byte* certCi = NULL; + word32 certCiSz; + byte* keyCi; + word32 keyCiSz; + + byte* certBuf = NULL; + word32 certBufSz; + byte* keyBuf; + word32 keyBufSz = 0; + + WOLFSSL_ENTER("wc_PKCS12_create()"); + + if ((ret = wc_InitRng_ex(&rng, heap, INVALID_DEVID)) != 0) { + return NULL; + } + + if ((pkcs12 = wc_PKCS12_new()) == NULL) { + wc_FreeRng(&rng); + WOLFSSL_LEAVE("wc_PKCS12_create", MEMORY_E); + return NULL; + } + + if ((ret = wc_PKCS12_SetHeap(pkcs12, heap)) != 0) { + wc_PKCS12_free(pkcs12); + wc_FreeRng(&rng); + WOLFSSL_LEAVE("wc_PKCS12_create", ret); + return NULL; + } + + if (iter <= 0) { + iter = WC_PKCS12_ITT_DEFAULT; + } + + /**** add private key bag ****/ + switch (nidKey) { + case PBE_SHA1_RC4_128: + algo = 1; + break; + + case PBE_SHA1_DES: + algo = 2; + break; + + case PBE_SHA1_DES3: + algo = 3; + break; + + /* no encryption */ + case -1: + algo = -1; + break; + + default: + WOLFSSL_MSG("Unknown/Unsupported key encryption"); + wc_PKCS12_free(pkcs12); + wc_FreeRng(&rng); + return NULL; + } + + /* get max size for key bag */ + ret = wc_PKCS12_create_key_bag(pkcs12, &rng, NULL, &keyBufSz, key, keySz, + algo, iter, pass, passSz); + if (ret != LENGTH_ONLY_E && ret < 0) { + wc_PKCS12_free(pkcs12); + wc_FreeRng(&rng); + WOLFSSL_LEAVE("wc_PKCS12_create", ret); + return NULL; + } + + /* account for sequence around bag */ + keyBufSz += MAX_SEQ_SZ; + + keyBuf = (byte*)XMALLOC(keyBufSz, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (keyBuf == NULL) { + wc_PKCS12_free(pkcs12); + wc_FreeRng(&rng); + WOLFSSL_LEAVE("wc_PKCS12_create", MEMORY_E); + return NULL; + } + + ret = wc_PKCS12_create_key_bag(pkcs12, &rng, keyBuf + MAX_SEQ_SZ, &keyBufSz, + key, keySz, algo, iter, pass, passSz); + if (ret < 0) { + wc_PKCS12_free(pkcs12); + wc_FreeRng(&rng); + XFREE(keyBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); + WOLFSSL_LEAVE("wc_PKCS12_create", ret); + return NULL; + } + keyBufSz = ret; + + tmpSz = SetSequence(keyBufSz, keyBuf); + XMEMMOVE(keyBuf + tmpSz, keyBuf + MAX_SEQ_SZ, keyBufSz); + keyBufSz += tmpSz; + + ret = wc_PKCS12_encrypt_content(pkcs12, &rng, NULL, &keyCiSz, + NULL, keyBufSz, algo, pass, passSz, iter, WC_PKCS12_DATA); + if (ret != LENGTH_ONLY_E) { + wc_PKCS12_free(pkcs12); + wc_FreeRng(&rng); + XFREE(keyBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); + WOLFSSL_LEAVE("wc_PKCS12_create", ret); + return NULL; + } + keyCi = (byte*)XMALLOC(keyCiSz, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (keyCi == NULL) { + wc_PKCS12_free(pkcs12); + wc_FreeRng(&rng); + XFREE(keyBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); + return NULL; + } + + ret = wc_PKCS12_encrypt_content(pkcs12, &rng, keyCi, &keyCiSz, + keyBuf, keyBufSz, algo, pass, passSz, iter, WC_PKCS12_DATA); + if (ret < 0 ) { + wc_PKCS12_free(pkcs12); + wc_FreeRng(&rng); + XFREE(keyBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER); + WOLFSSL_LEAVE("wc_PKCS12_create", ret); + return NULL; + } + keyCiSz = ret; + XFREE(keyBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); + + #ifdef WOLFSSL_DEBUG_PKCS12 + { + byte* p; + for (printf("(size %u) Key Content Info = ", keyCiSz), p = (byte*)keyCi; + p < (byte*)keyCi + keyCiSz; + printf("%02X", *p), p++); + printf("\n"); + } + #endif + + + /**** add main certificate bag and extras ****/ + switch (nidCert) { + case PBE_SHA1_RC4_128: + type = WC_PKCS12_ENCRYPTED_DATA; + algo = 1; + break; + + case PBE_SHA1_DES: + type = WC_PKCS12_ENCRYPTED_DATA; + algo = 2; + break; + + case PBE_SHA1_DES3: + type = WC_PKCS12_ENCRYPTED_DATA; + algo = 3; + break; + + case -1: + type = WC_PKCS12_DATA; + algo = -1; + break; + + default: + WOLFSSL_MSG("Unknown/Unsupported certificate encryption"); + XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS12_free(pkcs12); + wc_FreeRng(&rng); + return NULL; + } + + /* get max size of buffer needed */ + ret = wc_PKCS12_create_cert_bag(pkcs12, NULL, &certBufSz, cert, certSz); + if (ret != LENGTH_ONLY_E) { + XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS12_free(pkcs12); + wc_FreeRng(&rng); + return NULL; + } + + if (ca != NULL) { + WC_DerCertList* current = ca; + word32 curBufSz = 0; + + /* get max buffer size */ + while (current != NULL) { + ret = wc_PKCS12_create_cert_bag(pkcs12, NULL, &curBufSz, + current->buffer, current->bufferSz); + if (ret != LENGTH_ONLY_E) { + XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS12_free(pkcs12); + wc_FreeRng(&rng); + return NULL; + } + certBufSz += curBufSz; + current = current->next; + } + } + + /* account for Sequence that holds all certificate bags */ + certBufSz += MAX_SEQ_SZ; + + /* completed getting max size, now create buffer and start adding bags */ + certBuf = (byte*)XMALLOC(certBufSz, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (certBuf == NULL) { + XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS12_free(pkcs12); + wc_FreeRng(&rng); + WOLFSSL_MSG("Memory error creating certificate bags"); + return NULL; + } + + idx = 0; + idx += MAX_SEQ_SZ; + + sz = certBufSz - idx; + if ((ret = wc_PKCS12_create_cert_bag(pkcs12, certBuf + idx, &sz, + cert, certSz)) < 0) { + XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(certBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS12_free(pkcs12); + wc_FreeRng(&rng); + return NULL; + } + idx += ret; + + if (ca != NULL) { + WC_DerCertList* current = ca; + + while (current != NULL) { + sz = certBufSz - idx; + if ((ret = wc_PKCS12_create_cert_bag(pkcs12, certBuf + idx, &sz, + current->buffer, current->bufferSz)) < 0) { + XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(certBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS12_free(pkcs12); + wc_FreeRng(&rng); + return NULL; + } + idx += ret; + current = current->next; + } + } + + /* set sequence and create encrypted content with all certificate bags */ + tmpSz = SetSequence(idx - MAX_SEQ_SZ, certBuf); + XMEMMOVE(certBuf + tmpSz, certBuf + MAX_SEQ_SZ, idx - MAX_SEQ_SZ); + certBufSz = tmpSz + (idx - MAX_SEQ_SZ); + + /* get buffer size needed for content info */ + ret = wc_PKCS12_encrypt_content(pkcs12, &rng, NULL, &certCiSz, + NULL, certBufSz, algo, pass, passSz, iter, type); + if (ret != LENGTH_ONLY_E) { + XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(certBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS12_free(pkcs12); + wc_FreeRng(&rng); + WOLFSSL_LEAVE("wc_PKCS12_create()", ret); + return NULL; + } + certCi = (byte*)XMALLOC(certCiSz, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (certCi == NULL) { + XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(certBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS12_free(pkcs12); + wc_FreeRng(&rng); + return NULL; + } + + ret = wc_PKCS12_encrypt_content(pkcs12, &rng, certCi, &certCiSz, + certBuf, certBufSz, algo, pass, passSz, iter, type); + if (ret < 0) { + XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(certBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(certCi, heap, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS12_free(pkcs12); + wc_FreeRng(&rng); + WOLFSSL_LEAVE("wc_PKCS12_create()", ret); + return NULL; + } + certCiSz = ret; + XFREE(certBuf, heap, DYNAMIC_TYPE_TMP_BUFFER); + + #ifdef WOLFSSL_DEBUG_PKCS12 + { + byte* p; + for (printf("(size %u) Encrypted Certificate Content Info = ",certCiSz), + p = (byte*)certCi; + p < (byte*)certCi + certCiSz; + printf("%02X", *p), p++); + printf("\n"); + } + #endif + + /**** create safe and and Content Info ****/ + safe = (AuthenticatedSafe*)XMALLOC(sizeof(AuthenticatedSafe), heap, + DYNAMIC_TYPE_PKCS); + if (safe == NULL) { + XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(certCi, heap, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS12_free(pkcs12); + wc_FreeRng(&rng); + return NULL; + } + pkcs12->safe = safe; /* set so all of safe is free'd with wc_PKCS12_free */ + XMEMSET(safe, 0, sizeof(AuthenticatedSafe)); + + safe->dataSz = certCiSz + keyCiSz; + safe->data = (byte*)XMALLOC(safe->dataSz, heap, DYNAMIC_TYPE_PKCS); + if (safe->data == NULL) { + XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(certCi, heap, DYNAMIC_TYPE_TMP_BUFFER); + wc_PKCS12_free(pkcs12); + wc_FreeRng(&rng); + return NULL; + } + XMEMCPY(safe->data, certCi, certCiSz); + XMEMCPY(safe->data + certCiSz, keyCi, keyCiSz); + XFREE(certCi, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyCi, heap, DYNAMIC_TYPE_TMP_BUFFER); + + safe->numCI = 2; + + /* add Content Info structs to safe, key first then cert */ + ci = (ContentInfo*)XMALLOC(sizeof(ContentInfo), heap, DYNAMIC_TYPE_PKCS); + if (ci == NULL) { + wc_PKCS12_free(pkcs12); + wc_FreeRng(&rng); + return NULL; + } + XMEMSET(ci, 0, sizeof(ContentInfo)); + safe->CI = ci; + ci->data = safe->data + certCiSz; + ci->dataSz = keyCiSz; + ci->type = WC_PKCS12_DATA; + + ci = (ContentInfo*)XMALLOC(sizeof(ContentInfo), heap, DYNAMIC_TYPE_PKCS); + if (ci == NULL) { + wc_PKCS12_free(pkcs12); + wc_FreeRng(&rng); + return NULL; + } + XMEMSET(ci, 0, sizeof(ContentInfo)); + ci->next = safe->CI; + safe->CI = ci; + ci->data = safe->data; + ci->dataSz = certCiSz; + if (nidCert < 0) { + ci->type = WC_PKCS12_DATA; + } + else { + ci->type = WC_PKCS12_ENCRYPTED_DATA; + } + + /* create MAC */ + if (macIter > 0) { + MacData* mac; + byte digest[WC_MAX_DIGEST_SIZE]; /* for MAC */ + + mac = (MacData*)XMALLOC(sizeof(MacData), heap, DYNAMIC_TYPE_PKCS); + if (mac == NULL) { + wc_PKCS12_free(pkcs12); + wc_FreeRng(&rng); + return NULL; + } + XMEMSET(mac, 0, sizeof(MacData)); + pkcs12->signData = mac; /* now wc_PKCS12_free will free all mac too */ + + #ifndef NO_SHA256 + mac->oid = SHA256h; + #elif !defined(NO_SHA) + mac->oid = SHA; + #elif defined(WOLFSSL_SHA384) + mac->oid = SHA384; + #elif defined(WOLFSSL_SHA512) + mac->oid = SHA512; + #else + WOLFSSL_MSG("No supported hash algorithm compiled in!"); + wc_PKCS12_free(pkcs12); + wc_FreeRng(&rng); + return NULL; + #endif + + /* store number of iterations */ + mac->itt = macIter; + + /* set mac salt */ + mac->saltSz = 8; + mac->salt = (byte*)XMALLOC(mac->saltSz, heap, DYNAMIC_TYPE_PKCS); + if (mac->salt == NULL) { + wc_PKCS12_free(pkcs12); + wc_FreeRng(&rng); + return NULL; + } + + if ((ret = wc_RNG_GenerateBlock(&rng, mac->salt, mac->saltSz)) != 0) { + WOLFSSL_MSG("Error generating random salt"); + wc_PKCS12_free(pkcs12); + wc_FreeRng(&rng); + return NULL; + } + ret = wc_PKCS12_create_mac(pkcs12, safe->data, safe->dataSz, + (const byte*)pass, passSz, digest, WC_MAX_DIGEST_SIZE); + if (ret < 0) { + wc_PKCS12_free(pkcs12); + wc_FreeRng(&rng); + return NULL; + } + + mac->digestSz = ret; + mac->digest = (byte*)XMALLOC(ret, heap, DYNAMIC_TYPE_PKCS); + if (mac->digest == NULL) { + wc_PKCS12_free(pkcs12); + wc_FreeRng(&rng); + return NULL; + } + XMEMCPY(mac->digest, digest, mac->digestSz); + } + else { + pkcs12->signData = NULL; + } + + wc_FreeRng(&rng); + (void)name; + (void)keyType; + + return pkcs12; +} + + +/* if using a specific memory heap */ +int wc_PKCS12_SetHeap(WC_PKCS12* pkcs12, void* heap) +{ + if (pkcs12 == NULL) { + return BAD_FUNC_ARG; + } + pkcs12->heap = heap; + + return 0; +} + + +/* getter for heap */ +void* wc_PKCS12_GetHeap(WC_PKCS12* pkcs12) +{ + if (pkcs12 == NULL) { + return NULL; + } + + return pkcs12->heap; +} + +#undef ERROR_OUT + +#endif /* !NO_ASN && !NO_PWDBASED && HAVE_PKCS12 */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/pkcs7.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/pkcs7.c new file mode 100755 index 0000000..8931d68 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/pkcs7.c @@ -0,0 +1,12083 @@ +/* pkcs7.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifdef HAVE_PKCS7 + +#include +#include +#include +#include +#ifndef NO_RSA + #include +#endif +#ifdef HAVE_ECC + #include +#endif +#ifdef HAVE_LIBZ + #include +#endif +#ifndef NO_PWDBASED + #include +#endif +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +/* direction for processing, encoding or decoding */ +typedef enum { + WC_PKCS7_ENCODE, + WC_PKCS7_DECODE +} pkcs7Direction; + +#define NO_USER_CHECK 0 + +/* holds information about the signers */ +struct PKCS7SignerInfo { + int version; + byte *sid; + word32 sidSz; +}; + + +#ifndef NO_PKCS7_STREAM + +#define MAX_PKCS7_STREAM_BUFFER 256 +struct PKCS7State { + byte* tmpCert; + byte* bufferPt; + byte* key; + byte* nonce; /* stored nonce */ + byte* aad; /* additional data for AEAD algos */ + byte* tag; /* tag data for AEAD algos */ + byte* content; + byte* buffer; /* main internal read buffer */ + + /* stack variables to store for when returning */ + word32 varOne; + int varTwo; + int varThree; + + word32 vers; + word32 idx; /* index read into current input buffer */ + word32 maxLen; /* sanity cap on maximum amount of data to allow + * needed for GetSequence and other calls */ + word32 length; /* amount of data stored */ + word32 bufferSz; /* size of internal buffer */ + word32 expected; /* next amount of data expected, if needed */ + word32 totalRd; /* total amount of bytes read */ + word32 nonceSz; /* size of nonce stored */ + word32 aadSz; /* size of additional AEAD data */ + word32 tagSz; /* size of tag for AEAD */ + word32 contentSz; + byte tmpIv[MAX_CONTENT_IV_SIZE]; /* store IV if needed */ +#ifdef WC_PKCS7_STREAM_DEBUG + word32 peakUsed; /* most bytes used for struct at any one time */ + word32 peakRead; /* most bytes used by read buffer */ +#endif + byte multi:1; /* flag for if content is in multiple parts */ + byte flagOne:1; + byte detached:1; /* flag to indicate detached signature is present */ +}; + + +enum PKCS7_MaxLen { + PKCS7_DEFAULT_PEEK = 0, + PKCS7_SEQ_PEEK +}; + +/* creates a PKCS7State structure and returns 0 on success */ +static int wc_PKCS7_CreateStream(PKCS7* pkcs7) +{ + WOLFSSL_MSG("creating PKCS7 stream structure"); + pkcs7->stream = (PKCS7State*)XMALLOC(sizeof(PKCS7State), pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (pkcs7->stream == NULL) { + return MEMORY_E; + } + XMEMSET(pkcs7->stream, 0, sizeof(PKCS7State)); +#ifdef WC_PKCS7_STREAM_DEBUG + printf("\nCreating new PKCS#7 stream %p\n", pkcs7->stream); +#endif + return 0; +} + + +static void wc_PKCS7_ResetStream(PKCS7* pkcs7) +{ + if (pkcs7 != NULL && pkcs7->stream != NULL) { +#ifdef WC_PKCS7_STREAM_DEBUG + /* collect final data point in case more was read right before reset */ + if (pkcs7->stream->length > pkcs7->stream->peakRead) { + pkcs7->stream->peakRead = pkcs7->stream->length; + } + if (pkcs7->stream->bufferSz + pkcs7->stream->aadSz + + pkcs7->stream->nonceSz + pkcs7->stream->tagSz > + pkcs7->stream->peakUsed) { + pkcs7->stream->peakUsed = pkcs7->stream->bufferSz + + pkcs7->stream->aadSz + pkcs7->stream->nonceSz + + pkcs7->stream->tagSz; + } + + /* print out debugging statistics */ + if (pkcs7->stream->peakUsed > 0 || pkcs7->stream->peakRead > 0) { + printf("PKCS#7 STREAM:\n\tPeak heap used by struct = %d" + "\n\tPeak read buffer bytes = %d" + "\n\tTotal bytes read = %d" + "\n", + pkcs7->stream->peakUsed, pkcs7->stream->peakRead, + pkcs7->stream->totalRd); + } + printf("PKCS#7 stream reset : Address [%p]\n", pkcs7->stream); + #endif + + /* free any buffers that may be allocated */ + XFREE(pkcs7->stream->aad, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(pkcs7->stream->tag, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(pkcs7->stream->nonce, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(pkcs7->stream->buffer, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(pkcs7->stream->key, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + pkcs7->stream->aad = NULL; + pkcs7->stream->tag = NULL; + pkcs7->stream->nonce = NULL; + pkcs7->stream->buffer = NULL; + pkcs7->stream->key = NULL; + + /* reset values, note that content and tmpCert are saved */ + pkcs7->stream->maxLen = 0; + pkcs7->stream->length = 0; + pkcs7->stream->idx = 0; + pkcs7->stream->expected = 0; + pkcs7->stream->totalRd = 0; + pkcs7->stream->bufferSz = 0; + + pkcs7->stream->multi = 0; + pkcs7->stream->flagOne = 0; + pkcs7->stream->detached = 0; + pkcs7->stream->varOne = 0; + pkcs7->stream->varTwo = 0; + pkcs7->stream->varThree = 0; + } +} + + +static void wc_PKCS7_FreeStream(PKCS7* pkcs7) +{ + if (pkcs7 != NULL && pkcs7->stream != NULL) { + wc_PKCS7_ResetStream(pkcs7); + + XFREE(pkcs7->stream->content, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(pkcs7->stream->tmpCert, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + pkcs7->stream->content = NULL; + pkcs7->stream->tmpCert = NULL; + + XFREE(pkcs7->stream, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + pkcs7->stream = NULL; + } +} + + +/* used to increase the max size for internal buffer + * returns 0 on success */ +static int wc_PKCS7_GrowStream(PKCS7* pkcs7, word32 newSz) +{ + byte* pt; + + pt = (byte*)XMALLOC(newSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (pt == NULL) { + return MEMORY_E; + } + XMEMCPY(pt, pkcs7->stream->buffer, pkcs7->stream->bufferSz); + +#ifdef WC_PKCS7_STREAM_DEBUG + printf("PKCS7 increasing internal stream buffer %d -> %d\n", + pkcs7->stream->bufferSz, newSz); +#endif + pkcs7->stream->bufferSz = newSz; + XFREE(pkcs7->stream->buffer, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + pkcs7->stream->buffer = pt; + return 0; +} + + +/* pt gets set to the buffer that is holding data in the case that stream struct + * is used. + * + * Sets idx to be the current offset into "pt" buffer + * returns 0 on success + */ +static int wc_PKCS7_AddDataToStream(PKCS7* pkcs7, byte* in, word32 inSz, + word32 expected, byte** pt, word32* idx) +{ + word32 rdSz = pkcs7->stream->idx; + + /* If the input size minus current index into input buffer is greater than + * the expected size then use the input buffer. If data is already stored + * in stream buffer or if there is not enough input data available then use + * the stream buffer. */ + if (inSz - rdSz >= expected && pkcs7->stream->length == 0) { + /* storing input buffer is not needed */ + *pt = in; /* reset in case previously used internal buffer */ + *idx = rdSz; + return 0; + } + + /* is there enough stored in buffer already? */ + if (pkcs7->stream->length >= expected) { + *idx = 0; /* start reading from beginning of stream buffer */ + *pt = pkcs7->stream->buffer; + return 0; + } + + /* check if all data has been read from input */ + if (rdSz >= inSz) { + /* no more input to read, reset input index and request more data */ + pkcs7->stream->idx = 0; + return WC_PKCS7_WANT_READ_E; + } + + /* try to store input data into stream buffer */ + if (inSz - rdSz > 0 && pkcs7->stream->length < expected) { + int len = min(inSz - rdSz, expected - pkcs7->stream->length); + + /* sanity check that the input buffer is not internal buffer */ + if (in == pkcs7->stream->buffer) { + return WC_PKCS7_WANT_READ_E; + } + + /* check if internal buffer size needs to be increased */ + if (len + pkcs7->stream->length > pkcs7->stream->bufferSz) { + int ret = wc_PKCS7_GrowStream(pkcs7, expected); + if (ret < 0) { + return ret; + } + } + XMEMCPY(pkcs7->stream->buffer + pkcs7->stream->length, in + rdSz, len); + pkcs7->stream->length += len; + pkcs7->stream->idx += len; + pkcs7->stream->totalRd += len; + } + +#ifdef WC_PKCS7_STREAM_DEBUG + /* collects memory usage for debugging */ + if (pkcs7->stream->length > pkcs7->stream->peakRead) { + pkcs7->stream->peakRead = pkcs7->stream->length; + } + if (pkcs7->stream->bufferSz + pkcs7->stream->aadSz + pkcs7->stream->nonceSz + + pkcs7->stream->tagSz > pkcs7->stream->peakUsed) { + pkcs7->stream->peakUsed = pkcs7->stream->bufferSz + + pkcs7->stream->aadSz + pkcs7->stream->nonceSz + pkcs7->stream->tagSz; + } +#endif + + /* if not enough data was read in then request more */ + if (pkcs7->stream->length < expected) { + pkcs7->stream->idx = 0; + return WC_PKCS7_WANT_READ_E; + } + + /* adjust pointer to read from stored buffer */ + *idx = 0; + *pt = pkcs7->stream->buffer; + return 0; +} + + +/* Does two things + * 1) Tries to get the length from current buffer and set it as max length + * 2) Retrieves the set max length + * + * if no flag value is set then the stored max length is returned. + * returns length found on success and defSz if no stored data is found + */ +static long wc_PKCS7_GetMaxStream(PKCS7* pkcs7, byte flag, byte* in, + word32 defSz) +{ + /* check there is a buffer to read from */ + if (pkcs7) { + int length = 0, ret; + word32 idx = 0, maxIdx; + byte* pt; + + if (flag != PKCS7_DEFAULT_PEEK) { + if (pkcs7->stream->length > 0) { + length = pkcs7->stream->length; + pt = pkcs7->stream->buffer; + } + else { + length = defSz; + pt = in; + } + maxIdx = (word32)length; + + if (length < MAX_SEQ_SZ) { + WOLFSSL_MSG("PKCS7 Error not enough data for SEQ peek\n"); + return 0; + } + if (flag == PKCS7_SEQ_PEEK) { + if ((ret = GetSequence_ex(pt, &idx, &length, maxIdx, + NO_USER_CHECK)) < 0) { + return ret; + } + + #ifdef ASN_BER_TO_DER + if (length == 0 && ret == 0) { + idx = 0; + if ((ret = wc_BerToDer(pt, defSz, NULL, + (word32*)&length)) != LENGTH_ONLY_E) { + return ret; + } + } + #endif /* ASN_BER_TO_DER */ + pkcs7->stream->maxLen = length + idx; + } + } + + if (pkcs7->stream->maxLen == 0) { + pkcs7->stream->maxLen = defSz; + } + + return pkcs7->stream->maxLen; + } + + return defSz; +} + + +/* setter function for stored variables */ +static void wc_PKCS7_StreamStoreVar(PKCS7* pkcs7, word32 var1, int var2, + int var3) +{ + if (pkcs7 != NULL && pkcs7->stream != NULL) { + pkcs7->stream->varOne = var1; + pkcs7->stream->varTwo = var2; + pkcs7->stream->varThree = var3; + } +} + +/* getter function for stored variables */ +static void wc_PKCS7_StreamGetVar(PKCS7* pkcs7, word32* var1, int* var2, + int* var3) +{ + if (pkcs7 != NULL && pkcs7->stream != NULL) { + if (var1 != NULL) *var1 = pkcs7->stream->varOne; + if (var2 != NULL) *var2 = pkcs7->stream->varTwo; + if (var3 != NULL) *var3 = pkcs7->stream->varThree; + } +} + + +/* common update of index and total read after section complete + * returns 0 on success */ +static int wc_PKCS7_StreamEndCase(PKCS7* pkcs7, word32* tmpIdx, word32* idx) +{ + int ret = 0; + + if (pkcs7->stream->length > 0) { + if (pkcs7->stream->length < *idx) { + WOLFSSL_MSG("PKCS7 read too much data from internal buffer"); + ret = BUFFER_E; + } + else { + XMEMMOVE(pkcs7->stream->buffer, pkcs7->stream->buffer + *idx, + pkcs7->stream->length - *idx); + pkcs7->stream->length -= *idx; + } + } + else { + pkcs7->stream->totalRd += *idx - *tmpIdx; + pkcs7->stream->idx = *idx; /* adjust index into input buffer */ + *tmpIdx = *idx; + } + + return ret; +} +#endif /* NO_PKCS7_STREAM */ + +#ifdef WC_PKCS7_STREAM_DEBUG +/* used to print out human readable state for debugging */ +static const char* wc_PKCS7_GetStateName(int in) +{ + switch (in) { + case WC_PKCS7_START: return "WC_PKCS7_START"; + + case WC_PKCS7_STAGE2: return "WC_PKCS7_STAGE2"; + case WC_PKCS7_STAGE3: return "WC_PKCS7_STAGE3"; + case WC_PKCS7_STAGE4: return "WC_PKCS7_STAGE4"; + case WC_PKCS7_STAGE5: return "WC_PKCS7_STAGE5"; + case WC_PKCS7_STAGE6: return "WC_PKCS7_STAGE6"; + + /* parse info set */ + case WC_PKCS7_INFOSET_START: return "WC_PKCS7_INFOSET_START"; + case WC_PKCS7_INFOSET_BER: return "WC_PKCS7_INFOSET_BER"; + case WC_PKCS7_INFOSET_STAGE1: return "WC_PKCS7_INFOSET_STAGE1"; + case WC_PKCS7_INFOSET_STAGE2: return "WC_PKCS7_INFOSET_STAGE2"; + case WC_PKCS7_INFOSET_END: return "WC_PKCS7_INFOSET_END"; + + /* decode enveloped data */ + case WC_PKCS7_ENV_2: return "WC_PKCS7_ENV_2"; + case WC_PKCS7_ENV_3: return "WC_PKCS7_ENV_3"; + case WC_PKCS7_ENV_4: return "WC_PKCS7_ENV_4"; + case WC_PKCS7_ENV_5: return "WC_PKCS7_ENV_5"; + + /* decode auth enveloped */ + case WC_PKCS7_AUTHENV_2: return "WC_PKCS7_AUTHENV_2"; + case WC_PKCS7_AUTHENV_3: return "WC_PKCS7_AUTHENV_3"; + case WC_PKCS7_AUTHENV_4: return "WC_PKCS7_AUTHENV_4"; + case WC_PKCS7_AUTHENV_5: return "WC_PKCS7_AUTHENV_5"; + case WC_PKCS7_AUTHENV_6: return "WC_PKCS7_AUTHENV_6"; + case WC_PKCS7_AUTHENV_ATRB: return "WC_PKCS7_AUTHENV_ATRB"; + case WC_PKCS7_AUTHENV_ATRBEND: return "WC_PKCS7_AUTHENV_ATRBEND"; + case WC_PKCS7_AUTHENV_7: return "WC_PKCS7_AUTHENV_7"; + + /* decryption state types */ + case WC_PKCS7_DECRYPT_KTRI: return "WC_PKCS7_DECRYPT_KTRI"; + case WC_PKCS7_DECRYPT_KTRI_2: return "WC_PKCS7_DECRYPT_KTRI_2"; + case WC_PKCS7_DECRYPT_KTRI_3: return "WC_PKCS7_DECRYPT_KTRI_3"; + + case WC_PKCS7_DECRYPT_KARI: return "WC_PKCS7_DECRYPT_KARI"; + case WC_PKCS7_DECRYPT_KEKRI: return "WC_PKCS7_DECRYPT_KEKRI"; + case WC_PKCS7_DECRYPT_PWRI: return "WC_PKCS7_DECRYPT_PWRI"; + case WC_PKCS7_DECRYPT_ORI: return "WC_PKCS7_DECRYPT_ORI"; + case WC_PKCS7_DECRYPT_DONE: return "WC_PKCS7_DECRYPT_DONE"; + + case WC_PKCS7_VERIFY_STAGE2: return "WC_PKCS7_VERIFY_STAGE2"; + case WC_PKCS7_VERIFY_STAGE3: return "WC_PKCS7_VERIFY_STAGE3"; + case WC_PKCS7_VERIFY_STAGE4: return "WC_PKCS7_VERIFY_STAGE4"; + case WC_PKCS7_VERIFY_STAGE5: return "WC_PKCS7_VERIFY_STAGE5"; + case WC_PKCS7_VERIFY_STAGE6: return "WC_PKCS7_VERIFY_STAGE6"; + + default: + return "Unknown state"; + } +} +#endif + +/* Used to change the PKCS7 state. Having state change as a function allows + * for easier debugging */ +static void wc_PKCS7_ChangeState(PKCS7* pkcs7, int newState) +{ +#ifdef WC_PKCS7_STREAM_DEBUG + printf("\tChanging from state [%02d] %s to [%02d] %s\n", + pkcs7->state, wc_PKCS7_GetStateName(pkcs7->state), + newState, wc_PKCS7_GetStateName(newState)); +#endif + pkcs7->state = newState; +} + +#define MAX_PKCS7_DIGEST_SZ (MAX_SEQ_SZ + MAX_ALGO_SZ + \ + MAX_OCTET_STR_SZ + WC_MAX_DIGEST_SIZE) + + +/* placed ASN.1 contentType OID into *output, return idx on success, + * 0 upon failure */ +static int wc_SetContentType(int pkcs7TypeOID, byte* output, word32 outputSz) +{ + /* PKCS#7 content types, RFC 2315, section 14 */ + const byte pkcs7[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, + 0x0D, 0x01, 0x07 }; + const byte data[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, + 0x0D, 0x01, 0x07, 0x01 }; + const byte signedData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, + 0x0D, 0x01, 0x07, 0x02}; + const byte envelopedData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, + 0x0D, 0x01, 0x07, 0x03 }; + const byte authEnvelopedData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, + 0x0D, 0x01, 0x09, 0x10, 0x01, 0x17}; + const byte signedAndEnveloped[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, + 0x0D, 0x01, 0x07, 0x04 }; + const byte digestedData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, + 0x0D, 0x01, 0x07, 0x05 }; +#ifndef NO_PKCS7_ENCRYPTED_DATA + const byte encryptedData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, + 0x0D, 0x01, 0x07, 0x06 }; +#endif + /* FirmwarePkgData (1.2.840.113549.1.9.16.1.16), RFC 4108 */ + const byte firmwarePkgData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, + 0x01, 0x09, 0x10, 0x01, 0x10 }; +#if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA) + /* id-ct-compressedData (1.2.840.113549.1.9.16.1.9), RFC 3274 */ + const byte compressedData[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, + 0x01, 0x09, 0x10, 0x01, 0x09 }; +#endif + +#if !defined(NO_PWDBASED) && !defined(NO_SHA) + const byte pwriKek[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, + 0x01, 0x09, 0x10, 0x03, 0x09 }; + const byte pbkdf2[] = { 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, + 0x01, 0x05, 0x0C }; +#endif + + int idSz, idx = 0; + word32 typeSz = 0; + const byte* typeName = 0; + byte ID_Length[MAX_LENGTH_SZ]; + + switch (pkcs7TypeOID) { + case PKCS7_MSG: + typeSz = sizeof(pkcs7); + typeName = pkcs7; + break; + + case DATA: + typeSz = sizeof(data); + typeName = data; + break; + + case SIGNED_DATA: + typeSz = sizeof(signedData); + typeName = signedData; + break; + + case ENVELOPED_DATA: + typeSz = sizeof(envelopedData); + typeName = envelopedData; + break; + + case AUTH_ENVELOPED_DATA: + typeSz = sizeof(authEnvelopedData); + typeName = authEnvelopedData; + break; + + case SIGNED_AND_ENVELOPED_DATA: + typeSz = sizeof(signedAndEnveloped); + typeName = signedAndEnveloped; + break; + + case DIGESTED_DATA: + typeSz = sizeof(digestedData); + typeName = digestedData; + break; + +#ifndef NO_PKCS7_ENCRYPTED_DATA + case ENCRYPTED_DATA: + typeSz = sizeof(encryptedData); + typeName = encryptedData; + break; +#endif +#if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA) + case COMPRESSED_DATA: + typeSz = sizeof(compressedData); + typeName = compressedData; + break; +#endif + case FIRMWARE_PKG_DATA: + typeSz = sizeof(firmwarePkgData); + typeName = firmwarePkgData; + break; + +#if !defined(NO_PWDBASED) && !defined(NO_SHA) + case PWRI_KEK_WRAP: + typeSz = sizeof(pwriKek); + typeName = pwriKek; + break; + + case PBKDF2_OID: + typeSz = sizeof(pbkdf2); + typeName = pbkdf2; + break; +#endif + + default: + WOLFSSL_MSG("Unknown PKCS#7 Type"); + return 0; + }; + + if (outputSz < (MAX_LENGTH_SZ + 1 + typeSz)) { + WOLFSSL_MSG("CMS content type buffer too small"); + return BAD_FUNC_ARG; + } + + idSz = SetLength(typeSz, ID_Length); + output[idx++] = ASN_OBJECT_ID; + XMEMCPY(output + idx, ID_Length, idSz); + idx += idSz; + XMEMCPY(output + idx, typeName, typeSz); + idx += typeSz; + + return idx; +} + + +/* get ASN.1 contentType OID sum, return 0 on success, <0 on failure */ +static int wc_GetContentType(const byte* input, word32* inOutIdx, word32* oid, + word32 maxIdx) +{ + WOLFSSL_ENTER("wc_GetContentType"); + if (GetObjectId(input, inOutIdx, oid, oidIgnoreType, maxIdx) < 0) + return ASN_PARSE_E; + + return 0; +} + + +/* return block size for algorithm represented by oid, or <0 on error */ +static int wc_PKCS7_GetOIDBlockSize(int oid) +{ + int blockSz; + + switch (oid) { +#ifndef NO_AES + #ifdef WOLFSSL_AES_128 + case AES128CBCb: + case AES128GCMb: + case AES128CCMb: + #endif + #ifdef WOLFSSL_AES_192 + case AES192CBCb: + case AES192GCMb: + case AES192CCMb: + #endif + #ifdef WOLFSSL_AES_256 + case AES256CBCb: + case AES256GCMb: + case AES256CCMb: + #endif + blockSz = AES_BLOCK_SIZE; + break; +#endif +#ifndef NO_DES3 + case DESb: + case DES3b: + blockSz = DES_BLOCK_SIZE; + break; +#endif + default: + WOLFSSL_MSG("Unsupported content cipher type"); + return ALGO_ID_E; + }; + + return blockSz; +} + + +/* get key size for algorithm represented by oid, or <0 on error */ +static int wc_PKCS7_GetOIDKeySize(int oid) +{ + int blockKeySz; + + switch (oid) { +#ifndef NO_AES + #ifdef WOLFSSL_AES_128 + case AES128CBCb: + case AES128GCMb: + case AES128CCMb: + case AES128_WRAP: + blockKeySz = 16; + break; + #endif + #ifdef WOLFSSL_AES_192 + case AES192CBCb: + case AES192GCMb: + case AES192CCMb: + case AES192_WRAP: + blockKeySz = 24; + break; + #endif + #ifdef WOLFSSL_AES_256 + case AES256CBCb: + case AES256GCMb: + case AES256CCMb: + case AES256_WRAP: + blockKeySz = 32; + break; + #endif +#endif +#ifndef NO_DES3 + case DESb: + blockKeySz = DES_KEYLEN; + break; + + case DES3b: + blockKeySz = DES3_KEYLEN; + break; +#endif + default: + WOLFSSL_MSG("Unsupported content cipher type"); + return ALGO_ID_E; + }; + + return blockKeySz; +} + + +PKCS7* wc_PKCS7_New(void* heap, int devId) +{ + PKCS7* pkcs7 = (PKCS7*)XMALLOC(sizeof(PKCS7), heap, DYNAMIC_TYPE_PKCS7); + if (pkcs7) { + XMEMSET(pkcs7, 0, sizeof(PKCS7)); + if (wc_PKCS7_Init(pkcs7, heap, devId) == 0) { + pkcs7->isDynamic = 1; + } + else { + XFREE(pkcs7, heap, DYNAMIC_TYPE_PKCS7); + pkcs7 = NULL; + } + } + return pkcs7; +} + +/* This is to initialize a PKCS7 structure. It sets all values to 0 and can be + * used to set the heap hint. + * + * pkcs7 PKCS7 structure to initialize + * heap memory heap hint for PKCS7 structure to use + * devId currently not used but a place holder for async operations + * + * returns 0 on success or a negative value for failure + */ +int wc_PKCS7_Init(PKCS7* pkcs7, void* heap, int devId) +{ + word16 isDynamic; + + WOLFSSL_ENTER("wc_PKCS7_Init"); + + if (pkcs7 == NULL) { + return BAD_FUNC_ARG; + } + + isDynamic = pkcs7->isDynamic; + XMEMSET(pkcs7, 0, sizeof(PKCS7)); + pkcs7->isDynamic = isDynamic; +#ifdef WOLFSSL_HEAP_TEST + pkcs7->heap = (void*)WOLFSSL_HEAP_TEST; +#else + pkcs7->heap = heap; +#endif + pkcs7->devId = devId; + + return 0; +} + + +/* Certificate structure holding der pointer, size, and pointer to next + * Pkcs7Cert struct. Used when creating SignedData types with multiple + * certificates. */ +struct Pkcs7Cert { + byte* der; + word32 derSz; + Pkcs7Cert* next; +}; + + +/* Linked list of ASN.1 encoded RecipientInfos */ +struct Pkcs7EncodedRecip { + byte recip[MAX_RECIP_SZ]; + word32 recipSz; + int recipType; + int recipVersion; + Pkcs7EncodedRecip* next; +}; + + +/* free all members of Pkcs7Cert linked list */ +static void wc_PKCS7_FreeCertSet(PKCS7* pkcs7) +{ + Pkcs7Cert* curr = NULL; + Pkcs7Cert* next = NULL; + + if (pkcs7 == NULL) + return; + + curr = pkcs7->certList; + pkcs7->certList = NULL; + + while (curr != NULL) { + next = curr->next; + curr->next = NULL; + XFREE(curr, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + curr = next; + } + + return; +} + + +/* Get total size of all recipients in recipient list. + * + * Returns total size of recipients, or negative upon error */ +static int wc_PKCS7_GetRecipientListSize(PKCS7* pkcs7) +{ + int totalSz = 0; + Pkcs7EncodedRecip* tmp = NULL; + + if (pkcs7 == NULL) + return BAD_FUNC_ARG; + + tmp = pkcs7->recipList; + + while (tmp != NULL) { + totalSz += tmp->recipSz; + tmp = tmp->next; + } + + return totalSz; +} + + +/* free all members of Pkcs7EncodedRecip linked list */ +static void wc_PKCS7_FreeEncodedRecipientSet(PKCS7* pkcs7) +{ + Pkcs7EncodedRecip* curr = NULL; + Pkcs7EncodedRecip* next = NULL; + + if (pkcs7 == NULL) + return; + + curr = pkcs7->recipList; + pkcs7->recipList = NULL; + + while (curr != NULL) { + next = curr->next; + curr->next = NULL; + XFREE(curr, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + curr = next; + } + + return; +} + + +/* search through RecipientInfo list for specific type. + * return 1 if ANY recipient of type specified is present, otherwise + * return 0 */ +static int wc_PKCS7_RecipientListIncludesType(PKCS7* pkcs7, int type) +{ + Pkcs7EncodedRecip* tmp = NULL; + + if (pkcs7 == NULL) + return BAD_FUNC_ARG; + + tmp = pkcs7->recipList; + + while (tmp != NULL) { + if (tmp->recipType == type) + return 1; + + tmp = tmp->next; + } + + return 0; +} + + +/* searches through RecipientInfo list, returns 1 if all structure + * versions are set to 0, otherwise returns 0 */ +static int wc_PKCS7_RecipientListVersionsAllZero(PKCS7* pkcs7) +{ + Pkcs7EncodedRecip* tmp = NULL; + + if (pkcs7 == NULL) + return BAD_FUNC_ARG; + + tmp = pkcs7->recipList; + + while (tmp != NULL) { + if (tmp->recipVersion != 0) + return 0; + + tmp = tmp->next; + } + + return 1; +} + + +/* Init PKCS7 struct with recipient cert, decode into DecodedCert + * NOTE: keeps previously set pkcs7 heap hint, devId and isDynamic */ +int wc_PKCS7_InitWithCert(PKCS7* pkcs7, byte* derCert, word32 derCertSz) +{ + int ret = 0; + void* heap; + int devId; + Pkcs7Cert* cert; + Pkcs7Cert* lastCert; + + if (pkcs7 == NULL || (derCert == NULL && derCertSz != 0)) { + return BAD_FUNC_ARG; + } + + heap = pkcs7->heap; + devId = pkcs7->devId; + cert = pkcs7->certList; + ret = wc_PKCS7_Init(pkcs7, heap, devId); + if (ret != 0) + return ret; + pkcs7->certList = cert; + + if (derCert != NULL && derCertSz > 0) { +#ifdef WOLFSSL_SMALL_STACK + DecodedCert* dCert; + + dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), pkcs7->heap, + DYNAMIC_TYPE_DCERT); + if (dCert == NULL) + return MEMORY_E; +#else + DecodedCert dCert[1]; +#endif + + pkcs7->singleCert = derCert; + pkcs7->singleCertSz = derCertSz; + pkcs7->cert[0] = derCert; + pkcs7->certSz[0] = derCertSz; + + /* create new Pkcs7Cert for recipient, freed during cleanup */ + cert = (Pkcs7Cert*)XMALLOC(sizeof(Pkcs7Cert), pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + XMEMSET(cert, 0, sizeof(Pkcs7Cert)); + cert->der = derCert; + cert->derSz = derCertSz; + cert->next = NULL; + + /* free existing cert list if existing */ + wc_PKCS7_FreeCertSet(pkcs7); + + /* add cert to list */ + if (pkcs7->certList == NULL) { + pkcs7->certList = cert; + } else { + lastCert = pkcs7->certList; + while (lastCert->next != NULL) { + lastCert = lastCert->next; + } + lastCert->next = cert; + } + + InitDecodedCert(dCert, derCert, derCertSz, pkcs7->heap); + ret = ParseCert(dCert, CA_TYPE, NO_VERIFY, 0); + if (ret < 0) { + FreeDecodedCert(dCert); +#ifdef WOLFSSL_SMALL_STACK + XFREE(dCert, pkcs7->heap, DYNAMIC_TYPE_DCERT); +#endif + return ret; + } + + XMEMCPY(pkcs7->publicKey, dCert->publicKey, dCert->pubKeySize); + pkcs7->publicKeySz = dCert->pubKeySize; + pkcs7->publicKeyOID = dCert->keyOID; + XMEMCPY(pkcs7->issuerHash, dCert->issuerHash, KEYID_SIZE); + pkcs7->issuer = dCert->issuerRaw; + pkcs7->issuerSz = dCert->issuerRawLen; + XMEMCPY(pkcs7->issuerSn, dCert->serial, dCert->serialSz); + pkcs7->issuerSnSz = dCert->serialSz; + XMEMCPY(pkcs7->issuerSubjKeyId, dCert->extSubjKeyId, KEYID_SIZE); + + /* default to IssuerAndSerialNumber for SignerIdentifier */ + pkcs7->sidType = CMS_ISSUER_AND_SERIAL_NUMBER; + + /* free existing recipient list if existing */ + wc_PKCS7_FreeEncodedRecipientSet(pkcs7); + + FreeDecodedCert(dCert); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(dCert, pkcs7->heap, DYNAMIC_TYPE_DCERT); +#endif + } + + return ret; +} + + +/* Adds one DER-formatted certificate to the internal PKCS7/CMS certificate + * list, to be added as part of the certificates CertificateSet. Currently + * used in SignedData content type. + * + * Must be called after wc_PKCS7_Init() or wc_PKCS7_InitWithCert(). + * + * Does not represent the recipient/signer certificate, only certificates that + * are part of the certificate chain used to build and verify signer + * certificates. + * + * This API does not currently validate certificates. + * + * Returns 0 on success, negative upon error */ +int wc_PKCS7_AddCertificate(PKCS7* pkcs7, byte* derCert, word32 derCertSz) +{ + Pkcs7Cert* cert; + + if (pkcs7 == NULL || derCert == NULL || derCertSz == 0) + return BAD_FUNC_ARG; + + cert = (Pkcs7Cert*)XMALLOC(sizeof(Pkcs7Cert), pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (cert == NULL) + return MEMORY_E; + + cert->der = derCert; + cert->derSz = derCertSz; + + if (pkcs7->certList == NULL) { + pkcs7->certList = cert; + } else { + cert->next = pkcs7->certList; + pkcs7->certList = cert; + } + + return 0; +} + + +/* free linked list of PKCS7DecodedAttrib structs */ +static void wc_PKCS7_FreeDecodedAttrib(PKCS7DecodedAttrib* attrib, void* heap) +{ + PKCS7DecodedAttrib* current; + + if (attrib == NULL) { + return; + } + + current = attrib; + while (current != NULL) { + PKCS7DecodedAttrib* next = current->next; + if (current->oid != NULL) { + XFREE(current->oid, heap, DYNAMIC_TYPE_PKCS7); + } + if (current->value != NULL) { + XFREE(current->value, heap, DYNAMIC_TYPE_PKCS7); + } + XFREE(current, heap, DYNAMIC_TYPE_PKCS7); + current = next; + } + + (void)heap; +} + + +/* return 0 on success */ +static int wc_PKCS7_SignerInfoNew(PKCS7* pkcs7) +{ + if (pkcs7->signerInfo != NULL) { + XFREE(pkcs7->signerInfo, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + pkcs7->signerInfo = NULL; + } + + pkcs7->signerInfo = (PKCS7SignerInfo*)XMALLOC(sizeof(PKCS7SignerInfo), + pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (pkcs7->signerInfo == NULL) { + WOLFSSL_MSG("Unable to malloc memory for signer info"); + return MEMORY_E; + } + XMEMSET(pkcs7->signerInfo, 0, sizeof(PKCS7SignerInfo)); + return 0; +} + + +static void wc_PKCS7_SignerInfoFree(PKCS7* pkcs7) +{ + if (pkcs7->signerInfo != NULL) { + if (pkcs7->signerInfo->sid != NULL) { + XFREE(pkcs7->signerInfo->sid, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + pkcs7->signerInfo->sid = NULL; + } + XFREE(pkcs7->signerInfo, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + pkcs7->signerInfo = NULL; + } +} + + +/* free's any current SID and sets it to "in" + * returns 0 on success + */ +static int wc_PKCS7_SignerInfoSetSID(PKCS7* pkcs7, byte* in, int inSz) +{ + if (pkcs7 == NULL || in == NULL || inSz < 0) { + return BAD_FUNC_ARG; + } + + if (pkcs7->signerInfo->sid != NULL) { + XFREE(pkcs7->signerInfo->sid, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + pkcs7->signerInfo->sid = NULL; + } + pkcs7->signerInfo->sid = (byte*)XMALLOC(inSz, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (pkcs7->signerInfo->sid == NULL) { + return MEMORY_E; + } + XMEMCPY(pkcs7->signerInfo->sid, in, inSz); + pkcs7->signerInfo->sidSz = inSz; + return 0; +} + + +/* releases any memory allocated by a PKCS7 initializer */ +void wc_PKCS7_Free(PKCS7* pkcs7) +{ + if (pkcs7 == NULL) + return; + +#ifndef NO_PKCS7_STREAM + wc_PKCS7_FreeStream(pkcs7); +#endif + + wc_PKCS7_SignerInfoFree(pkcs7); + wc_PKCS7_FreeDecodedAttrib(pkcs7->decodedAttrib, pkcs7->heap); + wc_PKCS7_FreeCertSet(pkcs7); + +#ifdef ASN_BER_TO_DER + if (pkcs7->der != NULL) + XFREE(pkcs7->der, pkcs7->heap, DYNAMIC_TYPE_PKCS7); +#endif + if (pkcs7->contentDynamic != NULL) + XFREE(pkcs7->contentDynamic, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + + if (pkcs7->cek != NULL) { + ForceZero(pkcs7->cek, pkcs7->cekSz); + XFREE(pkcs7->cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + } + + pkcs7->contentTypeSz = 0; + + if (pkcs7->signature) { + XFREE(pkcs7->signature, pkcs7->heap, DYNAMIC_TYPE_SIGANTURE); + pkcs7->signature = NULL; + pkcs7->signatureSz = 0; + } + if (pkcs7->plainDigest) { + XFREE(pkcs7->plainDigest, pkcs7->heap, DYNAMIC_TYPE_DIGEST); + pkcs7->plainDigest = NULL; + pkcs7->plainDigestSz = 0; + } + if (pkcs7->pkcs7Digest) { + XFREE(pkcs7->pkcs7Digest, pkcs7->heap, DYNAMIC_TYPE_DIGEST); + pkcs7->pkcs7Digest = NULL; + pkcs7->pkcs7DigestSz = 0; + } + + if (pkcs7->isDynamic) { + pkcs7->isDynamic = 0; + XFREE(pkcs7, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + } +} + + +/* helper function for parsing through attributes and finding a specific one. + * returns PKCS7DecodedAttrib pointer on success */ +static PKCS7DecodedAttrib* findAttrib(PKCS7* pkcs7, const byte* oid, word32 oidSz) +{ + PKCS7DecodedAttrib* list; + + if (pkcs7 == NULL || oid == NULL) { + return NULL; + } + + /* search attributes for pkiStatus */ + list = pkcs7->decodedAttrib; + while (list != NULL) { + word32 sz = oidSz; + word32 idx = 0; + int length = 0; + + if (list->oid[idx++] != ASN_OBJECT_ID) { + WOLFSSL_MSG("Bad attribute ASN1 syntax"); + return NULL; + } + + if (GetLength(list->oid, &idx, &length, list->oidSz) < 0) { + WOLFSSL_MSG("Bad attribute length"); + return NULL; + } + + sz = (sz < (word32)length)? sz : (word32)length; + if (XMEMCMP(oid, list->oid + idx, sz) == 0) { + return list; + } + list = list->next; + } + return NULL; +} + + +/* Searches through decoded attributes and returns the value for the first one + * matching the oid passed in. Note that this value includes the leading ASN1 + * syntax. So for a printable string of "3" this would be something like + * + * 0x13, 0x01, 0x33 + * ID SIZE "3" + * + * pkcs7 structure to get value from + * oid OID value to search for with attributes + * oidSz size of oid buffer + * out buffer to hold result + * outSz size of out buffer (if out is NULL this is set to needed size and + LENGTH_ONLY_E is returned) + * + * returns size of value on success + */ +int wc_PKCS7_GetAttributeValue(PKCS7* pkcs7, const byte* oid, word32 oidSz, + byte* out, word32* outSz) +{ + PKCS7DecodedAttrib* attrib; + + if (pkcs7 == NULL || oid == NULL || outSz == NULL) { + return BAD_FUNC_ARG; + } + + attrib = findAttrib(pkcs7, oid, oidSz); + if (attrib == NULL) { + return ASN_PARSE_E; + } + + if (out == NULL) { + *outSz = attrib->valueSz; + return LENGTH_ONLY_E; + } + + if (*outSz < attrib->valueSz) { + return BUFFER_E; + } + + XMEMCPY(out, attrib->value, attrib->valueSz); + return attrib->valueSz; +} + + +/* build PKCS#7 data content type */ +int wc_PKCS7_EncodeData(PKCS7* pkcs7, byte* output, word32 outputSz) +{ + static const byte oid[] = + { ASN_OBJECT_ID, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, + 0x07, 0x01 }; + byte seq[MAX_SEQ_SZ]; + byte octetStr[MAX_OCTET_STR_SZ]; + word32 seqSz; + word32 octetStrSz; + word32 oidSz = (word32)sizeof(oid); + int idx = 0; + + if (pkcs7 == NULL || output == NULL) { + return BAD_FUNC_ARG; + } + + octetStrSz = SetOctetString(pkcs7->contentSz, octetStr); + seqSz = SetSequence(pkcs7->contentSz + octetStrSz + oidSz, seq); + + if (outputSz < pkcs7->contentSz + octetStrSz + oidSz + seqSz) + return BUFFER_E; + + XMEMCPY(output, seq, seqSz); + idx += seqSz; + XMEMCPY(output + idx, oid, oidSz); + idx += oidSz; + XMEMCPY(output + idx, octetStr, octetStrSz); + idx += octetStrSz; + XMEMCPY(output + idx, pkcs7->content, pkcs7->contentSz); + idx += pkcs7->contentSz; + + return idx; +} + + +typedef struct EncodedAttrib { + byte valueSeq[MAX_SEQ_SZ]; + const byte* oid; + byte valueSet[MAX_SET_SZ]; + const byte* value; + word32 valueSeqSz, oidSz, idSz, valueSetSz, valueSz, totalSz; +} EncodedAttrib; + + +typedef struct ESD { + wc_HashAlg hash; + enum wc_HashType hashType; + byte contentDigest[WC_MAX_DIGEST_SIZE + 2]; /* content only + ASN.1 heading */ + byte contentAttribsDigest[WC_MAX_DIGEST_SIZE]; + byte encContentDigest[MAX_ENCRYPTED_KEY_SZ]; + + byte outerSeq[MAX_SEQ_SZ]; + byte outerContent[MAX_EXP_SZ]; + byte innerSeq[MAX_SEQ_SZ]; + byte version[MAX_VERSION_SZ]; + byte digAlgoIdSet[MAX_SET_SZ]; + byte singleDigAlgoId[MAX_ALGO_SZ]; + + byte contentInfoSeq[MAX_SEQ_SZ]; + byte innerContSeq[MAX_EXP_SZ]; + byte innerOctets[MAX_OCTET_STR_SZ]; + + byte certsSet[MAX_SET_SZ]; + + byte signerInfoSet[MAX_SET_SZ]; + byte signerInfoSeq[MAX_SEQ_SZ]; + byte signerVersion[MAX_VERSION_SZ]; + /* issuerAndSerialNumber ...*/ + byte issuerSnSeq[MAX_SEQ_SZ]; + byte issuerName[MAX_SEQ_SZ]; + byte issuerSn[MAX_SN_SZ]; + /* OR subjectKeyIdentifier */ + byte issuerSKIDSeq[MAX_SEQ_SZ]; + byte issuerSKID[MAX_OCTET_STR_SZ]; + byte signerDigAlgoId[MAX_ALGO_SZ]; + byte digEncAlgoId[MAX_ALGO_SZ]; + byte signedAttribSet[MAX_SET_SZ]; + EncodedAttrib signedAttribs[7]; + byte signerDigest[MAX_OCTET_STR_SZ]; + word32 innerOctetsSz, innerContSeqSz, contentInfoSeqSz; + word32 outerSeqSz, outerContentSz, innerSeqSz, versionSz, digAlgoIdSetSz, + singleDigAlgoIdSz, certsSetSz; + word32 signerInfoSetSz, signerInfoSeqSz, signerVersionSz, + issuerSnSeqSz, issuerNameSz, issuerSnSz, issuerSKIDSz, + issuerSKIDSeqSz, signerDigAlgoIdSz, digEncAlgoIdSz, signerDigestSz; + word32 encContentDigestSz, signedAttribsSz, signedAttribsCount, + signedAttribSetSz; +} ESD; + + +static int EncodeAttributes(EncodedAttrib* ea, int eaSz, + PKCS7Attrib* attribs, int attribsSz) +{ + int i; + int maxSz = min(eaSz, attribsSz); + int allAttribsSz = 0; + + for (i = 0; i < maxSz; i++) + { + int attribSz = 0; + + ea[i].value = attribs[i].value; + ea[i].valueSz = attribs[i].valueSz; + attribSz += ea[i].valueSz; + ea[i].valueSetSz = SetSet(attribSz, ea[i].valueSet); + attribSz += ea[i].valueSetSz; + ea[i].oid = attribs[i].oid; + ea[i].oidSz = attribs[i].oidSz; + attribSz += ea[i].oidSz; + ea[i].valueSeqSz = SetSequence(attribSz, ea[i].valueSeq); + attribSz += ea[i].valueSeqSz; + ea[i].totalSz = attribSz; + + allAttribsSz += attribSz; + } + return allAttribsSz; +} + + +typedef struct FlatAttrib { + byte* data; + word32 dataSz; +} FlatAttrib; + + +/* Free FlatAttrib array and memory allocated to internal struct members */ +static void FreeAttribArray(PKCS7* pkcs7, FlatAttrib** arr, int rows) +{ + int i; + + if (arr) { + for (i = 0; i < rows; i++) { + if (arr[i]) { + if (arr[i]->data) { + ForceZero(arr[i]->data, arr[i]->dataSz); + XFREE(arr[i]->data, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + } + ForceZero(arr[i], sizeof(FlatAttrib)); + XFREE(arr[i], pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + } + } + ForceZero(arr, rows); + XFREE(arr, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + } + (void)pkcs7; +} + + +/* Sort FlatAttrib array in ascending order */ +static int SortAttribArray(FlatAttrib** arr, int rows) +{ + int i, j; + word32 minSz, minIdx; + FlatAttrib* a = NULL; + FlatAttrib* b = NULL; + FlatAttrib* tmp = NULL; + + if (arr == NULL) { + return BAD_FUNC_ARG; + } + + for (i = 0; i < rows; i++) { + a = arr[i]; + minSz = a->dataSz; + minIdx = i; + for (j = i+1; j < rows; j++) { + b = arr[j]; + if (b->dataSz < minSz) { + minSz = b->dataSz; + minIdx = j; + } + } + if (minSz < a->dataSz) { + /* swap array positions */ + tmp = arr[i]; + arr[i] = arr[minIdx]; + arr[minIdx] = tmp; + } + } + + return 0; +} + + +/* Build up array of FlatAttrib structs from EncodedAttrib ones. FlatAttrib + * holds flattened DER encoding of each attribute */ +static int FlattenEncodedAttribs(PKCS7* pkcs7, FlatAttrib** derArr, int rows, + EncodedAttrib* ea, int eaSz) +{ + int i, idx, sz; + byte* output = NULL; + FlatAttrib* fa = NULL; + + if (pkcs7 == NULL || derArr == NULL || ea == NULL) { + WOLFSSL_MSG("Invalid arguments to FlattenEncodedAttribs"); + return BAD_FUNC_ARG; + } + + if (rows != eaSz) { + WOLFSSL_MSG("DER array not large enough to hold attribute count"); + return BAD_FUNC_ARG; + } + + for (i = 0; i < eaSz; i++) { + sz = ea[i].valueSeqSz + ea[i].oidSz + ea[i].valueSetSz + ea[i].valueSz; + + output = (byte*)XMALLOC(sz, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (output == NULL) { + return MEMORY_E; + } + + idx = 0; + XMEMCPY(output + idx, ea[i].valueSeq, ea[i].valueSeqSz); + idx += ea[i].valueSeqSz; + XMEMCPY(output + idx, ea[i].oid, ea[i].oidSz); + idx += ea[i].oidSz; + XMEMCPY(output + idx, ea[i].valueSet, ea[i].valueSetSz); + idx += ea[i].valueSetSz; + XMEMCPY(output + idx, ea[i].value, ea[i].valueSz); + + fa = derArr[i]; + fa->data = output; + fa->dataSz = sz; + } + + return 0; +} + + +/* Sort and Flatten EncodedAttrib attributes into output buffer */ +static int FlattenAttributes(PKCS7* pkcs7, byte* output, EncodedAttrib* ea, + int eaSz) +{ + int i, idx, ret; + FlatAttrib** derArr = NULL; + FlatAttrib* fa = NULL; + + if (pkcs7 == NULL || output == NULL || ea == NULL) { + return BAD_FUNC_ARG; + } + + /* create array of FlatAttrib struct pointers to hold DER attribs */ + derArr = (FlatAttrib**) XMALLOC(eaSz * sizeof(FlatAttrib*), pkcs7->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (derArr == NULL) { + return MEMORY_E; + } + ForceZero(derArr, eaSz); + + for (i = 0; i < eaSz; i++) { + derArr[i] = (FlatAttrib*) XMALLOC(sizeof(FlatAttrib), pkcs7->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (derArr[i] == NULL) { + FreeAttribArray(pkcs7, derArr, eaSz); + return MEMORY_E; + } + ForceZero(derArr[i], sizeof(FlatAttrib)); + } + + /* flatten EncodedAttrib into DER byte arrays */ + ret = FlattenEncodedAttribs(pkcs7, derArr, eaSz, ea, eaSz); + if (ret != 0) { + FreeAttribArray(pkcs7, derArr, eaSz); + return ret; + } + + /* SET OF DER signed attributes must be sorted in ascending order */ + ret = SortAttribArray(derArr, eaSz); + if (ret != 0) { + FreeAttribArray(pkcs7, derArr, eaSz); + return ret; + } + + /* copy sorted DER attribute arrays into output buffer */ + idx = 0; + for (i = 0; i < eaSz; i++) { + fa = derArr[i]; + XMEMCPY(output + idx, fa->data, fa->dataSz); + idx += fa->dataSz; + } + + FreeAttribArray(pkcs7, derArr, eaSz); + + return 0; +} + + +#ifndef NO_RSA + +/* returns size of signature put into out, negative on error */ +static int wc_PKCS7_RsaSign(PKCS7* pkcs7, byte* in, word32 inSz, ESD* esd) +{ + int ret; + word32 idx; +#ifdef WOLFSSL_SMALL_STACK + RsaKey* privKey; +#else + RsaKey privKey[1]; +#endif + + if (pkcs7 == NULL || pkcs7->rng == NULL || in == NULL || esd == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + privKey = (RsaKey*)XMALLOC(sizeof(RsaKey), pkcs7->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (privKey == NULL) + return MEMORY_E; +#endif + + ret = wc_InitRsaKey_ex(privKey, pkcs7->heap, pkcs7->devId); + if (ret == 0) { + if (pkcs7->privateKey != NULL && pkcs7->privateKeySz > 0) { + idx = 0; + ret = wc_RsaPrivateKeyDecode(pkcs7->privateKey, &idx, privKey, + pkcs7->privateKeySz); + } + else if (pkcs7->devId == INVALID_DEVID) { + ret = BAD_FUNC_ARG; + } + } + if (ret == 0) { + #ifdef WOLFSSL_ASYNC_CRYPT + do { + ret = wc_AsyncWait(ret, &privKey->asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) { + ret = wc_RsaSSL_Sign(in, inSz, esd->encContentDigest, + sizeof(esd->encContentDigest), + privKey, pkcs7->rng); + } + #ifdef WOLFSSL_ASYNC_CRYPT + } while (ret == WC_PENDING_E); + #endif + } + + wc_FreeRsaKey(privKey); +#ifdef WOLFSSL_SMALL_STACK + XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +#endif /* NO_RSA */ + + +#ifdef HAVE_ECC + +/* returns size of signature put into out, negative on error */ +static int wc_PKCS7_EcdsaSign(PKCS7* pkcs7, byte* in, word32 inSz, ESD* esd) +{ + int ret; + word32 outSz, idx; +#ifdef WOLFSSL_SMALL_STACK + ecc_key* privKey; +#else + ecc_key privKey[1]; +#endif + + if (pkcs7 == NULL || pkcs7->rng == NULL || in == NULL || esd == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + privKey = (ecc_key*)XMALLOC(sizeof(ecc_key), pkcs7->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (privKey == NULL) + return MEMORY_E; +#endif + + ret = wc_ecc_init_ex(privKey, pkcs7->heap, pkcs7->devId); + if (ret == 0) { + if (pkcs7->privateKey != NULL && pkcs7->privateKeySz > 0) { + idx = 0; + ret = wc_EccPrivateKeyDecode(pkcs7->privateKey, &idx, privKey, + pkcs7->privateKeySz); + } + else if (pkcs7->devId == INVALID_DEVID) { + ret = BAD_FUNC_ARG; + } + } + if (ret == 0) { + outSz = sizeof(esd->encContentDigest); + #ifdef WOLFSSL_ASYNC_CRYPT + do { + ret = wc_AsyncWait(ret, &privKey->asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) { + ret = wc_ecc_sign_hash(in, inSz, esd->encContentDigest, + &outSz, pkcs7->rng, privKey); + } + #ifdef WOLFSSL_ASYNC_CRYPT + } while (ret == WC_PENDING_E); + #endif + if (ret == 0) + ret = (int)outSz; + } + + wc_ecc_free(privKey); +#ifdef WOLFSSL_SMALL_STACK + XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +#endif /* HAVE_ECC */ + + +/* builds up SignedData signed attributes, including default ones. + * + * pkcs7 - pointer to initialized PKCS7 structure + * esd - pointer to initialized ESD structure, used for output + * + * return 0 on success, negative on error */ +static int wc_PKCS7_BuildSignedAttributes(PKCS7* pkcs7, ESD* esd, + const byte* contentType, word32 contentTypeSz, + const byte* contentTypeOid, word32 contentTypeOidSz, + const byte* messageDigestOid, word32 messageDigestOidSz, + const byte* signingTimeOid, word32 signingTimeOidSz, + byte* signingTime, word32 signingTimeSz) +{ + int hashSz; +#ifdef NO_ASN_TIME + PKCS7Attrib cannedAttribs[2]; +#else + time_t tm; + int timeSz; + PKCS7Attrib cannedAttribs[3]; +#endif + word32 idx = 0; + word32 cannedAttribsCount; + + if (pkcs7 == NULL || esd == NULL || contentType == NULL || + contentTypeOid == NULL || messageDigestOid == NULL || + signingTimeOid == NULL) { + return BAD_FUNC_ARG; + } + + if (pkcs7->skipDefaultSignedAttribs == 0) { + hashSz = wc_HashGetDigestSize(esd->hashType); + if (hashSz < 0) + return hashSz; + + #ifndef NO_ASN_TIME + if (signingTime == NULL || signingTimeSz == 0) + return BAD_FUNC_ARG; + + tm = XTIME(0); + timeSz = GetAsnTimeString(&tm, signingTime, signingTimeSz); + if (timeSz < 0) + return timeSz; + #endif + + cannedAttribsCount = sizeof(cannedAttribs)/sizeof(PKCS7Attrib); + + cannedAttribs[idx].oid = contentTypeOid; + cannedAttribs[idx].oidSz = contentTypeOidSz; + cannedAttribs[idx].value = contentType; + cannedAttribs[idx].valueSz = contentTypeSz; + idx++; + #ifndef NO_ASN_TIME + cannedAttribs[idx].oid = signingTimeOid; + cannedAttribs[idx].oidSz = signingTimeOidSz; + cannedAttribs[idx].value = signingTime; + cannedAttribs[idx].valueSz = timeSz; + idx++; + #endif + cannedAttribs[idx].oid = messageDigestOid; + cannedAttribs[idx].oidSz = messageDigestOidSz; + cannedAttribs[idx].value = esd->contentDigest; + cannedAttribs[idx].valueSz = hashSz + 2; /* ASN.1 heading */ + + esd->signedAttribsCount += cannedAttribsCount; + esd->signedAttribsSz += EncodeAttributes(&esd->signedAttribs[0], 3, + cannedAttribs, cannedAttribsCount); + } else { + esd->signedAttribsCount = 0; + esd->signedAttribsSz = 0; + } + + /* add custom signed attributes if set */ + if (pkcs7->signedAttribsSz > 0 && pkcs7->signedAttribs != NULL) { + esd->signedAttribsCount += pkcs7->signedAttribsSz; + #ifdef NO_ASN_TIME + esd->signedAttribsSz += EncodeAttributes(&esd->signedAttribs[2], 4, + pkcs7->signedAttribs, pkcs7->signedAttribsSz); + #else + esd->signedAttribsSz += EncodeAttributes(&esd->signedAttribs[3], 4, + pkcs7->signedAttribs, pkcs7->signedAttribsSz); + #endif + } + +#ifdef NO_ASN_TIME + (void)signingTimeOidSz; + (void)signingTime; + (void)signingTimeSz; +#endif + + return 0; +} + + +/* gets correct encryption algo ID for SignedData, either CTC_wRSA or + * CTC_wECDSA, from pkcs7->publicKeyOID and pkcs7->hashOID. + * + * pkcs7 - pointer to PKCS7 structure + * digEncAlgoId - [OUT] output int to store correct algo ID in + * digEncAlgoType - [OUT] output for algo ID type + * + * return 0 on success, negative on error */ +static int wc_PKCS7_SignedDataGetEncAlgoId(PKCS7* pkcs7, int* digEncAlgoId, + int* digEncAlgoType) +{ + int algoId = 0; + int algoType = 0; + + if (pkcs7 == NULL || digEncAlgoId == NULL || digEncAlgoType == NULL) + return BAD_FUNC_ARG; + + if (pkcs7->publicKeyOID == RSAk) { + + algoType = oidSigType; + + switch (pkcs7->hashOID) { + #ifndef NO_SHA + case SHAh: + algoId = CTC_SHAwRSA; + break; + #endif + #ifdef WOLFSSL_SHA224 + case SHA224h: + algoId = CTC_SHA224wRSA; + break; + #endif + #ifndef NO_SHA256 + case SHA256h: + algoId = CTC_SHA256wRSA; + break; + #endif + #ifdef WOLFSSL_SHA384 + case SHA384h: + algoId = CTC_SHA384wRSA; + break; + #endif + #ifdef WOLFSSL_SHA512 + case SHA512h: + algoId = CTC_SHA512wRSA; + break; + #endif + } + + } +#ifdef HAVE_ECC + else if (pkcs7->publicKeyOID == ECDSAk) { + + algoType = oidSigType; + + switch (pkcs7->hashOID) { + #ifndef NO_SHA + case SHAh: + algoId = CTC_SHAwECDSA; + break; + #endif + #ifdef WOLFSSL_SHA224 + case SHA224h: + algoId = CTC_SHA224wECDSA; + break; + #endif + #ifndef NO_SHA256 + case SHA256h: + algoId = CTC_SHA256wECDSA; + break; + #endif + #ifdef WOLFSSL_SHA384 + case SHA384h: + algoId = CTC_SHA384wECDSA; + break; + #endif + #ifdef WOLFSSL_SHA512 + case SHA512h: + algoId = CTC_SHA512wECDSA; + break; + #endif + } + } +#endif /* HAVE_ECC */ + + if (algoId == 0) { + WOLFSSL_MSG("Invalid signature algorithm type"); + return BAD_FUNC_ARG; + } + + *digEncAlgoId = algoId; + *digEncAlgoType = algoType; + + return 0; +} + + +/* build SignedData DigestInfo for use with PKCS#7/RSA + * + * pkcs7 - pointer to initialized PKCS7 struct + * flatSignedAttribs - flattened, signed attributes + * flatSignedAttrbsSz - size of flatSignedAttribs, octets + * esd - pointer to initialized ESD struct + * digestInfo - [OUT] output array for DigestInfo + * digestInfoSz - [IN/OUT] - input size of array, size of digestInfo + * + * return 0 on success, negative on error */ +static int wc_PKCS7_BuildDigestInfo(PKCS7* pkcs7, byte* flatSignedAttribs, + word32 flatSignedAttribsSz, ESD* esd, + byte* digestInfo, word32* digestInfoSz) +{ + int ret, hashSz, digIdx = 0; + byte digestInfoSeq[MAX_SEQ_SZ]; + byte digestStr[MAX_OCTET_STR_SZ]; + byte attribSet[MAX_SET_SZ]; + byte algoId[MAX_ALGO_SZ]; + word32 digestInfoSeqSz, digestStrSz, algoIdSz; + word32 attribSetSz; + + if (pkcs7 == NULL || esd == NULL || digestInfo == NULL || + digestInfoSz == NULL) { + return BAD_FUNC_ARG; + } + + hashSz = wc_HashGetDigestSize(esd->hashType); + if (hashSz < 0) + return hashSz; + + if (flatSignedAttribsSz != 0) { + + if (flatSignedAttribs == NULL) + return BAD_FUNC_ARG; + + attribSetSz = SetSet(flatSignedAttribsSz, attribSet); + + ret = wc_HashInit(&esd->hash, esd->hashType); + if (ret < 0) + return ret; + + ret = wc_HashUpdate(&esd->hash, esd->hashType, + attribSet, attribSetSz); + if (ret == 0) + ret = wc_HashUpdate(&esd->hash, esd->hashType, + flatSignedAttribs, flatSignedAttribsSz); + if (ret == 0) + ret = wc_HashFinal(&esd->hash, esd->hashType, + esd->contentAttribsDigest); + wc_HashFree(&esd->hash, esd->hashType); + + if (ret < 0) + return ret; + + } else { + /* when no attrs, digest is contentDigest without tag and length */ + XMEMCPY(esd->contentAttribsDigest, esd->contentDigest + 2, hashSz); + } + + /* set algoID, with NULL attributes */ + algoIdSz = SetAlgoID(pkcs7->hashOID, algoId, oidHashType, 0); + + digestStrSz = SetOctetString(hashSz, digestStr); + digestInfoSeqSz = SetSequence(algoIdSz + digestStrSz + hashSz, + digestInfoSeq); + + if (*digestInfoSz < (digestInfoSeqSz + algoIdSz + digestStrSz + hashSz)) { + return BUFFER_E; + } + + XMEMCPY(digestInfo + digIdx, digestInfoSeq, digestInfoSeqSz); + digIdx += digestInfoSeqSz; + XMEMCPY(digestInfo + digIdx, algoId, algoIdSz); + digIdx += algoIdSz; + XMEMCPY(digestInfo + digIdx, digestStr, digestStrSz); + digIdx += digestStrSz; + XMEMCPY(digestInfo + digIdx, esd->contentAttribsDigest, hashSz); + digIdx += hashSz; + + *digestInfoSz = digIdx; + + return 0; +} + + +/* build SignedData signature over DigestInfo or content digest + * + * pkcs7 - pointer to initialized PKCS7 struct + * flatSignedAttribs - flattened, signed attributes + * flatSignedAttribsSz - size of flatSignedAttribs, octets + * esd - pointer to initialized ESD struct + * + * returns length of signature on success, negative on error */ +static int wc_PKCS7_SignedDataBuildSignature(PKCS7* pkcs7, + byte* flatSignedAttribs, + word32 flatSignedAttribsSz, + ESD* esd) +{ + int ret = 0; +#ifdef HAVE_ECC + int hashSz = 0; +#endif + word32 digestInfoSz = MAX_PKCS7_DIGEST_SZ; +#ifdef WOLFSSL_SMALL_STACK + byte* digestInfo; +#else + byte digestInfo[MAX_PKCS7_DIGEST_SZ]; +#endif + + if (pkcs7 == NULL || esd == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_SMALL_STACK + digestInfo = (byte*)XMALLOC(digestInfoSz, pkcs7->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (digestInfo == NULL) { + return MEMORY_E; + } +#endif + XMEMSET(digestInfo, 0, digestInfoSz); + + ret = wc_PKCS7_BuildDigestInfo(pkcs7, flatSignedAttribs, + flatSignedAttribsSz, esd, digestInfo, + &digestInfoSz); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + /* sign digestInfo */ + switch (pkcs7->publicKeyOID) { + +#ifndef NO_RSA + case RSAk: + ret = wc_PKCS7_RsaSign(pkcs7, digestInfo, digestInfoSz, esd); + break; +#endif + +#ifdef HAVE_ECC + case ECDSAk: + /* CMS with ECDSA does not sign DigestInfo structure + * like PKCS#7 with RSA does */ + hashSz = wc_HashGetDigestSize(esd->hashType); + if (hashSz < 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return hashSz; + } + + ret = wc_PKCS7_EcdsaSign(pkcs7, esd->contentAttribsDigest, + hashSz, esd); + break; +#endif + + default: + WOLFSSL_MSG("Unsupported public key type"); + ret = BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + if (ret >= 0) { + esd->encContentDigestSz = (word32)ret; + } + + return ret; +} + + +/* build PKCS#7 signedData content type */ +static int PKCS7_EncodeSigned(PKCS7* pkcs7, ESD* esd, + const byte* hashBuf, word32 hashSz, byte* output, word32* outputSz, + byte* output2, word32* output2Sz) +{ + /* contentType OID (1.2.840.113549.1.9.3) */ + const byte contentTypeOid[] = + { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xF7, 0x0d, 0x01, + 0x09, 0x03 }; + + /* messageDigest OID (1.2.840.113549.1.9.4) */ + const byte messageDigestOid[] = + { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x09, 0x04 }; + + /* signingTime OID () */ + byte signingTimeOid[] = + { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, + 0x09, 0x05}; + + Pkcs7Cert* certPtr = NULL; + word32 certSetSz = 0; + + word32 signerInfoSz = 0; + word32 totalSz, total2Sz; + int idx = 0, ret = 0; + int digEncAlgoId, digEncAlgoType; + byte* flatSignedAttribs = NULL; + word32 flatSignedAttribsSz = 0; + + byte signedDataOid[MAX_OID_SZ]; + word32 signedDataOidSz; + + byte signingTime[MAX_TIME_STRING_SZ]; + + if (pkcs7 == NULL || pkcs7->contentSz == 0 || + pkcs7->encryptOID == 0 || pkcs7->hashOID == 0 || pkcs7->rng == 0 || + output == NULL || outputSz == NULL || *outputSz == 0 || hashSz == 0 || + hashBuf == NULL) { + return BAD_FUNC_ARG; + } + + /* verify the hash size matches */ +#ifdef WOLFSSL_SMALL_STACK + esd = (ESD*)XMALLOC(sizeof(ESD), pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (esd == NULL) + return MEMORY_E; +#endif + + XMEMSET(esd, 0, sizeof(ESD)); + + /* set content type based on contentOID, unless user has set custom one + with wc_PKCS7_SetContentType() */ + if (pkcs7->contentTypeSz == 0) { + + /* default to DATA content type if user has not set */ + if (pkcs7->contentOID == 0) { + pkcs7->contentOID = DATA; + } + + ret = wc_SetContentType(pkcs7->contentOID, pkcs7->contentType, + sizeof(pkcs7->contentType)); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + pkcs7->contentTypeSz = ret; + } + + /* set signedData outer content type */ + ret = wc_SetContentType(SIGNED_DATA, signedDataOid, sizeof(signedDataOid)); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + signedDataOidSz = ret; + + if (pkcs7->sidType != DEGENERATE_SID) { + esd->hashType = wc_OidGetHash(pkcs7->hashOID); + if (wc_HashGetDigestSize(esd->hashType) != (int)hashSz) { + WOLFSSL_MSG("hashSz did not match hashOID"); + #ifdef WOLFSSL_SMALL_STACK + XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return BUFFER_E; + } + + /* include hash */ + esd->contentDigest[0] = ASN_OCTET_STRING; + esd->contentDigest[1] = (byte)hashSz; + XMEMCPY(&esd->contentDigest[2], hashBuf, hashSz); + } + + if (pkcs7->detached == 1) { + /* do not include content if generating detached signature */ + esd->innerOctetsSz = 0; + esd->innerContSeqSz = 0; + esd->contentInfoSeqSz = SetSequence(pkcs7->contentTypeSz, + esd->contentInfoSeq); + } else { + esd->innerOctetsSz = SetOctetString(pkcs7->contentSz, esd->innerOctets); + esd->innerContSeqSz = SetExplicit(0, esd->innerOctetsSz + + pkcs7->contentSz, esd->innerContSeq); + esd->contentInfoSeqSz = SetSequence(pkcs7->contentSz + + esd->innerOctetsSz + pkcs7->contentTypeSz + + esd->innerContSeqSz, esd->contentInfoSeq); + } + + /* SignerIdentifier */ + if (pkcs7->sidType == CMS_ISSUER_AND_SERIAL_NUMBER) { + /* IssuerAndSerialNumber */ + esd->issuerSnSz = SetSerialNumber(pkcs7->issuerSn, pkcs7->issuerSnSz, + esd->issuerSn, MAX_SN_SZ); + signerInfoSz += esd->issuerSnSz; + esd->issuerNameSz = SetSequence(pkcs7->issuerSz, esd->issuerName); + signerInfoSz += esd->issuerNameSz + pkcs7->issuerSz; + esd->issuerSnSeqSz = SetSequence(signerInfoSz, esd->issuerSnSeq); + signerInfoSz += esd->issuerSnSeqSz; + + if (pkcs7->version == 3) { + /* RFC 4108 version MUST be 3 for firmware package signer */ + esd->signerVersionSz = SetMyVersion(3, esd->signerVersion, 0); + } + else { + /* version MUST be 1 otherwise*/ + esd->signerVersionSz = SetMyVersion(1, esd->signerVersion, 0); + } + + } else if (pkcs7->sidType == CMS_SKID) { + /* SubjectKeyIdentifier */ + esd->issuerSKIDSz = SetOctetString(KEYID_SIZE, esd->issuerSKID); + esd->issuerSKIDSeqSz = SetExplicit(0, esd->issuerSKIDSz + KEYID_SIZE, + esd->issuerSKIDSeq); + signerInfoSz += (esd->issuerSKIDSz + esd->issuerSKIDSeqSz + + KEYID_SIZE); + + /* version MUST be 3 */ + esd->signerVersionSz = SetMyVersion(3, esd->signerVersion, 0); + } else if (pkcs7->sidType == DEGENERATE_SID) { + /* no signer info added */ + } else { + #ifdef WOLFSSL_SMALL_STACK + XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return SKID_E; + } + + if (pkcs7->sidType != DEGENERATE_SID) { + signerInfoSz += esd->signerVersionSz; + esd->signerDigAlgoIdSz = SetAlgoID(pkcs7->hashOID, esd->signerDigAlgoId, + oidHashType, 0); + signerInfoSz += esd->signerDigAlgoIdSz; + + /* set signatureAlgorithm */ + ret = wc_PKCS7_SignedDataGetEncAlgoId(pkcs7, &digEncAlgoId, + &digEncAlgoType); + if (ret < 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ret; + } + esd->digEncAlgoIdSz = SetAlgoID(digEncAlgoId, esd->digEncAlgoId, + digEncAlgoType, 0); + signerInfoSz += esd->digEncAlgoIdSz; + + /* build up signed attributes, include contentType, signingTime, and + messageDigest by default */ + ret = wc_PKCS7_BuildSignedAttributes(pkcs7, esd, pkcs7->contentType, + pkcs7->contentTypeSz, + contentTypeOid, sizeof(contentTypeOid), + messageDigestOid, sizeof(messageDigestOid), + signingTimeOid, sizeof(signingTimeOid), + signingTime, sizeof(signingTime)); + if (ret < 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ret; + } + + if (esd->signedAttribsSz > 0) { + flatSignedAttribs = (byte*)XMALLOC(esd->signedAttribsSz, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + flatSignedAttribsSz = esd->signedAttribsSz; + if (flatSignedAttribs == NULL) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return MEMORY_E; + } + + FlattenAttributes(pkcs7, flatSignedAttribs, + esd->signedAttribs, esd->signedAttribsCount); + esd->signedAttribSetSz = SetImplicit(ASN_SET, 0, esd->signedAttribsSz, + esd->signedAttribSet); + } else { + esd->signedAttribSetSz = 0; + } + + /* Calculate the final hash and encrypt it. */ + ret = wc_PKCS7_SignedDataBuildSignature(pkcs7, flatSignedAttribs, + flatSignedAttribsSz, esd); + if (ret < 0) { + if (pkcs7->signedAttribsSz != 0) + XFREE(flatSignedAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #ifdef WOLFSSL_SMALL_STACK + XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ret; + } + + signerInfoSz += flatSignedAttribsSz + esd->signedAttribSetSz; + + esd->signerDigestSz = SetOctetString(esd->encContentDigestSz, + esd->signerDigest); + signerInfoSz += esd->signerDigestSz + esd->encContentDigestSz; + + esd->signerInfoSeqSz = SetSequence(signerInfoSz, esd->signerInfoSeq); + signerInfoSz += esd->signerInfoSeqSz; + } + esd->signerInfoSetSz = SetSet(signerInfoSz, esd->signerInfoSet); + signerInfoSz += esd->signerInfoSetSz; + + /* certificates [0] IMPLICIT CertificateSet */ + /* get total certificates size */ + certPtr = pkcs7->certList; + while (certPtr != NULL) { + certSetSz += certPtr->derSz; + certPtr = certPtr->next; + } + certPtr = NULL; + + if (certSetSz > 0) + esd->certsSetSz = SetImplicit(ASN_SET, 0, certSetSz, esd->certsSet); + + if (pkcs7->sidType != DEGENERATE_SID) { + esd->singleDigAlgoIdSz = SetAlgoID(pkcs7->hashOID, esd->singleDigAlgoId, + oidHashType, 0); + } + esd->digAlgoIdSetSz = SetSet(esd->singleDigAlgoIdSz, esd->digAlgoIdSet); + + if (pkcs7->version == 3) { + /* RFC 4108 version MUST be 3 for firmware package signer */ + esd->versionSz = SetMyVersion(3, esd->version, 0); + } + else { + esd->versionSz = SetMyVersion(1, esd->version, 0); + } + + totalSz = esd->versionSz + esd->singleDigAlgoIdSz + esd->digAlgoIdSetSz + + esd->contentInfoSeqSz + pkcs7->contentTypeSz + + esd->innerContSeqSz + esd->innerOctetsSz + pkcs7->contentSz; + total2Sz = esd->certsSetSz + certSetSz + signerInfoSz; + + if (pkcs7->detached) { + totalSz -= pkcs7->contentSz; + } + + esd->innerSeqSz = SetSequence(totalSz + total2Sz, esd->innerSeq); + totalSz += esd->innerSeqSz; + esd->outerContentSz = SetExplicit(0, totalSz + total2Sz, esd->outerContent); + totalSz += esd->outerContentSz + signedDataOidSz; + esd->outerSeqSz = SetSequence(totalSz + total2Sz, esd->outerSeq); + totalSz += esd->outerSeqSz; + + /* if using header/footer, we are not returning the content */ + if (output2 && output2Sz) { + if (total2Sz > *output2Sz) { + if (pkcs7->signedAttribsSz != 0) + XFREE(flatSignedAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #ifdef WOLFSSL_SMALL_STACK + XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return BUFFER_E; + } + + if (!pkcs7->detached) { + totalSz -= pkcs7->contentSz; + } + } + else { + /* if using single output buffer include content and footer */ + totalSz += total2Sz; + } + + if (totalSz > *outputSz) { + if (pkcs7->signedAttribsSz != 0) + XFREE(flatSignedAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #ifdef WOLFSSL_SMALL_STACK + XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return BUFFER_E; + } + + idx = 0; + XMEMCPY(output + idx, esd->outerSeq, esd->outerSeqSz); + idx += esd->outerSeqSz; + XMEMCPY(output + idx, signedDataOid, signedDataOidSz); + idx += signedDataOidSz; + XMEMCPY(output + idx, esd->outerContent, esd->outerContentSz); + idx += esd->outerContentSz; + XMEMCPY(output + idx, esd->innerSeq, esd->innerSeqSz); + idx += esd->innerSeqSz; + XMEMCPY(output + idx, esd->version, esd->versionSz); + idx += esd->versionSz; + XMEMCPY(output + idx, esd->digAlgoIdSet, esd->digAlgoIdSetSz); + idx += esd->digAlgoIdSetSz; + XMEMCPY(output + idx, esd->singleDigAlgoId, esd->singleDigAlgoIdSz); + idx += esd->singleDigAlgoIdSz; + XMEMCPY(output + idx, esd->contentInfoSeq, esd->contentInfoSeqSz); + idx += esd->contentInfoSeqSz; + XMEMCPY(output + idx, pkcs7->contentType, pkcs7->contentTypeSz); + idx += pkcs7->contentTypeSz; + XMEMCPY(output + idx, esd->innerContSeq, esd->innerContSeqSz); + idx += esd->innerContSeqSz; + XMEMCPY(output + idx, esd->innerOctets, esd->innerOctetsSz); + idx += esd->innerOctetsSz; + + /* support returning header and footer without content */ + if (output2 && output2Sz) { + *outputSz = idx; + idx = 0; + } + else { + if (!pkcs7->detached) { + XMEMCPY(output + idx, pkcs7->content, pkcs7->contentSz); + idx += pkcs7->contentSz; + } + output2 = output; + } + + /* certificates */ + XMEMCPY(output2 + idx, esd->certsSet, esd->certsSetSz); + idx += esd->certsSetSz; + certPtr = pkcs7->certList; + while (certPtr != NULL) { + XMEMCPY(output2 + idx, certPtr->der, certPtr->derSz); + idx += certPtr->derSz; + certPtr = certPtr->next; + } + wc_PKCS7_FreeCertSet(pkcs7); + + XMEMCPY(output2 + idx, esd->signerInfoSet, esd->signerInfoSetSz); + idx += esd->signerInfoSetSz; + XMEMCPY(output2 + idx, esd->signerInfoSeq, esd->signerInfoSeqSz); + idx += esd->signerInfoSeqSz; + XMEMCPY(output2 + idx, esd->signerVersion, esd->signerVersionSz); + idx += esd->signerVersionSz; + /* SignerIdentifier */ + if (pkcs7->sidType == CMS_ISSUER_AND_SERIAL_NUMBER) { + /* IssuerAndSerialNumber */ + XMEMCPY(output2 + idx, esd->issuerSnSeq, esd->issuerSnSeqSz); + idx += esd->issuerSnSeqSz; + XMEMCPY(output2 + idx, esd->issuerName, esd->issuerNameSz); + idx += esd->issuerNameSz; + XMEMCPY(output2 + idx, pkcs7->issuer, pkcs7->issuerSz); + idx += pkcs7->issuerSz; + XMEMCPY(output2 + idx, esd->issuerSn, esd->issuerSnSz); + idx += esd->issuerSnSz; + } else if (pkcs7->sidType == CMS_SKID) { + /* SubjectKeyIdentifier */ + XMEMCPY(output2 + idx, esd->issuerSKIDSeq, esd->issuerSKIDSeqSz); + idx += esd->issuerSKIDSeqSz; + XMEMCPY(output2 + idx, esd->issuerSKID, esd->issuerSKIDSz); + idx += esd->issuerSKIDSz; + XMEMCPY(output2 + idx, pkcs7->issuerSubjKeyId, KEYID_SIZE); + idx += KEYID_SIZE; + } else if (pkcs7->sidType == DEGENERATE_SID) { + /* no signer infos in degenerate case */ + } else { + #ifdef WOLFSSL_SMALL_STACK + XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return SKID_E; + } + XMEMCPY(output2 + idx, esd->signerDigAlgoId, esd->signerDigAlgoIdSz); + idx += esd->signerDigAlgoIdSz; + + /* SignerInfo:Attributes */ + if (flatSignedAttribsSz > 0) { + XMEMCPY(output2 + idx, esd->signedAttribSet, esd->signedAttribSetSz); + idx += esd->signedAttribSetSz; + XMEMCPY(output2 + idx, flatSignedAttribs, flatSignedAttribsSz); + idx += flatSignedAttribsSz; + XFREE(flatSignedAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + } + + XMEMCPY(output2 + idx, esd->digEncAlgoId, esd->digEncAlgoIdSz); + idx += esd->digEncAlgoIdSz; + XMEMCPY(output2 + idx, esd->signerDigest, esd->signerDigestSz); + idx += esd->signerDigestSz; + XMEMCPY(output2 + idx, esd->encContentDigest, esd->encContentDigestSz); + idx += esd->encContentDigestSz; + + if (output2 && output2Sz) { + *output2Sz = idx; + idx = 0; /* success */ + } + else { + *outputSz = idx; + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return idx; +} + +/* hashBuf: The computed digest for the pkcs7->content + * hashSz: The size of computed digest for the pkcs7->content based on hashOID + * outputHead: The PKCS7 header that goes on top of the raw data signed. + * outputFoot: The PKCS7 footer that goes at the end of the raw data signed. + * pkcs7->content: Not used + * pkcs7->contentSz: Must be provided as actual sign of raw data + * return codes: 0=success, negative=error + */ +int wc_PKCS7_EncodeSignedData_ex(PKCS7* pkcs7, const byte* hashBuf, word32 hashSz, + byte* outputHead, word32* outputHeadSz, byte* outputFoot, word32* outputFootSz) +{ + int ret; +#ifdef WOLFSSL_SMALL_STACK + ESD* esd; +#else + ESD esd[1]; +#endif + + /* other args checked in wc_PKCS7_EncodeSigned_ex */ + if (pkcs7 == NULL || outputFoot == NULL || outputFootSz == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + esd = (ESD*)XMALLOC(sizeof(ESD), pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (esd == NULL) + return MEMORY_E; +#endif + + XMEMSET(esd, 0, sizeof(ESD)); + + ret = PKCS7_EncodeSigned(pkcs7, esd, hashBuf, hashSz, + outputHead, outputHeadSz, outputFoot, outputFootSz); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +/* Toggle detached signature mode on/off for PKCS#7/CMS SignedData content type. + * By default wolfCrypt includes the data to be signed in the SignedData + * bundle. This data can be omitted in the case when a detached signature is + * being created. To enable generation of detached signatures, set flag to "1", + * otherwise set to "0": + * + * flag 1 turns on support + * flag 0 turns off support + * + * pkcs7 - pointer to initialized PKCS7 structure + * flag - turn on/off detached signature generation (1 or 0) + * + * Returns 0 on success, negative upon error. */ +int wc_PKCS7_SetDetached(PKCS7* pkcs7, word16 flag) +{ + if (pkcs7 == NULL || (flag != 0 && flag != 1)) + return BAD_FUNC_ARG; + + pkcs7->detached = flag; + + return 0; +} + +/* By default, SignedData bundles have the following signed attributes attached: + * contentType (1.2.840.113549.1.9.3) + * signgingTime (1.2.840.113549.1.9.5) + * messageDigest (1.2.840.113549.1.9.4) + * + * Calling this API before wc_PKCS7_EncodeSignedData() will disable the + * inclusion of those attributes. + * + * pkcs7 - pointer to initialized PKCS7 structure + * + * Returns 0 on success, negative upon error. */ +int wc_PKCS7_NoDefaultSignedAttribs(PKCS7* pkcs7) +{ + if (pkcs7 == NULL) + return BAD_FUNC_ARG; + + pkcs7->skipDefaultSignedAttribs = 1; + + return 0; +} + +/* return codes: >0: Size of signed PKCS7 output buffer, negative: error */ +int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, byte* output, word32 outputSz) +{ + int ret; + int hashSz; + enum wc_HashType hashType; + byte hashBuf[WC_MAX_DIGEST_SIZE]; +#ifdef WOLFSSL_SMALL_STACK + ESD* esd; +#else + ESD esd[1]; +#endif + + /* other args checked in wc_PKCS7_EncodeSigned_ex */ + if (pkcs7 == NULL || pkcs7->contentSz == 0 || pkcs7->content == NULL) { + return BAD_FUNC_ARG; + } + + /* get hash type and size, validate hashOID */ + hashType = wc_OidGetHash(pkcs7->hashOID); + hashSz = wc_HashGetDigestSize(hashType); + if (hashSz < 0) + return hashSz; + +#ifdef WOLFSSL_SMALL_STACK + esd = (ESD*)XMALLOC(sizeof(ESD), pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (esd == NULL) + return MEMORY_E; +#endif + + XMEMSET(esd, 0, sizeof(ESD)); + esd->hashType = hashType; + + /* calculate hash for content */ + ret = wc_HashInit(&esd->hash, esd->hashType); + if (ret == 0) { + ret = wc_HashUpdate(&esd->hash, esd->hashType, + pkcs7->content, pkcs7->contentSz); + if (ret == 0) { + ret = wc_HashFinal(&esd->hash, esd->hashType, hashBuf); + } + wc_HashFree(&esd->hash, esd->hashType); + } + + if (ret == 0) { + ret = PKCS7_EncodeSigned(pkcs7, esd, hashBuf, hashSz, + output, &outputSz, NULL, NULL); + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(esd, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + + +/* Single-shot API to generate a CMS SignedData bundle that encapsulates a + * content of type FirmwarePkgData. Any recipient certificates should be + * loaded into the PKCS7 structure prior to calling this function, using + * wc_PKCS7_InitWithCert() and/or wc_PKCS7_AddCertificate(). + * + * pkcs7 - pointer to initialized PKCS7 struct + * privateKey - private RSA/ECC key, used for signing SignedData + * privateKeySz - size of privateKey, octets + * signOID - public key algorithm OID, used for sign operation + * hashOID - hash algorithm OID, used for signature generation + * content - content to be encapsulated, of type FirmwarePkgData + * contentSz - size of content, octets + * signedAttribs - optional signed attributes + * signedAttribsSz - number of PKCS7Attrib members in signedAttribs + * output - output buffer for final bundle + * outputSz - size of output buffer, octets + * + * Returns length of generated bundle on success, negative upon error. */ +int wc_PKCS7_EncodeSignedFPD(PKCS7* pkcs7, byte* privateKey, + word32 privateKeySz, int signOID, int hashOID, + byte* content, word32 contentSz, + PKCS7Attrib* signedAttribs, word32 signedAttribsSz, + byte* output, word32 outputSz) +{ + int ret = 0; + WC_RNG rng; + + if (pkcs7 == NULL || privateKey == NULL || privateKeySz == 0 || + content == NULL || contentSz == 0 || output == NULL || outputSz == 0) + return BAD_FUNC_ARG; + + ret = wc_InitRng(&rng); + if (ret != 0) + return ret; + + pkcs7->rng = &rng; + pkcs7->content = content; + pkcs7->contentSz = contentSz; + pkcs7->contentOID = FIRMWARE_PKG_DATA; + pkcs7->hashOID = hashOID; + pkcs7->encryptOID = signOID; + pkcs7->privateKey = privateKey; + pkcs7->privateKeySz = privateKeySz; + pkcs7->signedAttribs = signedAttribs; + pkcs7->signedAttribsSz = signedAttribsSz; + pkcs7->version = 3; + + ret = wc_PKCS7_EncodeSignedData(pkcs7, output, outputSz); + if (ret <= 0) { + WOLFSSL_MSG("Error encoding CMS SignedData content type"); + wc_FreeRng(&rng); + return ret; + } + + wc_FreeRng(&rng); + + return ret; +} + +#ifndef NO_PKCS7_ENCRYPTED_DATA + +/* Single-shot API to generate a CMS SignedData bundle that encapsulates a + * CMS EncryptedData bundle. Content of inner EncryptedData is set to that + * of FirmwarePkgData. Any recipient certificates should be loaded into the + * PKCS7 structure prior to calling this function, using wc_PKCS7_InitWithCert() + * and/or wc_PKCS7_AddCertificate(). + * + * pkcs7 - pointer to initialized PKCS7 struct + * encryptKey - encryption key used for encrypting EncryptedData + * encryptKeySz - size of encryptKey, octets + * privateKey - private RSA/ECC key, used for signing SignedData + * privateKeySz - size of privateKey, octets + * encryptOID - encryption algorithm OID, to be used as encryption + * algorithm for EncryptedData + * signOID - public key algorithm OID, to be used for sign + * operation in SignedData generation + * hashOID - hash algorithm OID, to be used for signature in + * SignedData generation + * content - content to be encapsulated + * contentSz - size of content, octets + * unprotectedAttribs - optional unprotected attributes, for EncryptedData + * unprotectedAttribsSz - number of PKCS7Attrib members in unprotectedAttribs + * signedAttribs - optional signed attributes, for SignedData + * signedAttribsSz - number of PKCS7Attrib members in signedAttribs + * output - output buffer for final bundle + * outputSz - size of output buffer, octets + * + * Returns length of generated bundle on success, negative upon error. */ +int wc_PKCS7_EncodeSignedEncryptedFPD(PKCS7* pkcs7, byte* encryptKey, + word32 encryptKeySz, byte* privateKey, + word32 privateKeySz, int encryptOID, + int signOID, int hashOID, + byte* content, word32 contentSz, + PKCS7Attrib* unprotectedAttribs, + word32 unprotectedAttribsSz, + PKCS7Attrib* signedAttribs, + word32 signedAttribsSz, + byte* output, word32 outputSz) +{ + int ret = 0, encryptedSz = 0; + byte* encrypted = NULL; + WC_RNG rng; + + if (pkcs7 == NULL || encryptKey == NULL || encryptKeySz == 0 || + privateKey == NULL || privateKeySz == 0 || content == NULL || + contentSz == 0 || output == NULL || outputSz == 0) { + return BAD_FUNC_ARG; + } + + /* 1: build up EncryptedData using FirmwarePkgData type, use output + * buffer as tmp for storage and to get size */ + + /* set struct elements, inner content type is FirmwarePkgData */ + pkcs7->content = content; + pkcs7->contentSz = contentSz; + pkcs7->contentOID = FIRMWARE_PKG_DATA; + pkcs7->encryptOID = encryptOID; + pkcs7->encryptionKey = encryptKey; + pkcs7->encryptionKeySz = encryptKeySz; + pkcs7->unprotectedAttribs = unprotectedAttribs; + pkcs7->unprotectedAttribsSz = unprotectedAttribsSz; + pkcs7->version = 3; + + encryptedSz = wc_PKCS7_EncodeEncryptedData(pkcs7, output, outputSz); + if (encryptedSz < 0) { + WOLFSSL_MSG("Error encoding CMS EncryptedData content type"); + return encryptedSz; + } + + /* save encryptedData, reset output buffer and struct */ + encrypted = (byte*)XMALLOC(encryptedSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (encrypted == NULL) { + ForceZero(output, outputSz); + return MEMORY_E; + } + + XMEMCPY(encrypted, output, encryptedSz); + ForceZero(output, outputSz); + + ret = wc_InitRng(&rng); + if (ret != 0) { + ForceZero(encrypted, encryptedSz); + XFREE(encrypted, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + /* 2: build up SignedData, encapsulating EncryptedData */ + pkcs7->rng = &rng; + pkcs7->content = encrypted; + pkcs7->contentSz = encryptedSz; + pkcs7->contentOID = ENCRYPTED_DATA; + pkcs7->hashOID = hashOID; + pkcs7->encryptOID = signOID; + pkcs7->privateKey = privateKey; + pkcs7->privateKeySz = privateKeySz; + pkcs7->signedAttribs = signedAttribs; + pkcs7->signedAttribsSz = signedAttribsSz; + + ret = wc_PKCS7_EncodeSignedData(pkcs7, output, outputSz); + if (ret <= 0) { + WOLFSSL_MSG("Error encoding CMS SignedData content type"); + ForceZero(encrypted, encryptedSz); + XFREE(encrypted, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + wc_FreeRng(&rng); + return ret; + } + + ForceZero(encrypted, encryptedSz); + XFREE(encrypted, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + wc_FreeRng(&rng); + + return ret; +} + +#endif /* NO_PKCS7_ENCRYPTED_DATA */ + +#if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA) +/* Single-shot API to generate a CMS SignedData bundle that encapsulates a + * CMS CompressedData bundle. Content of inner CompressedData is set to that + * of FirmwarePkgData. Any recipient certificates should be loaded into the + * PKCS7 structure prior to calling this function, using wc_PKCS7_InitWithCert() + * and/or wc_PKCS7_AddCertificate(). + * + * pkcs7 - pointer to initialized PKCS7 struct + * privateKey - private RSA/ECC key, used for signing SignedData + * privateKeySz - size of privateKey, octets + * signOID - public key algorithm OID, to be used for sign + * operation in SignedData generation + * hashOID - hash algorithm OID, to be used for signature in + * SignedData generation + * content - content to be encapsulated + * contentSz - size of content, octets + * signedAttribs - optional signed attributes, for SignedData + * signedAttribsSz - number of PKCS7Attrib members in signedAttribs + * output - output buffer for final bundle + * outputSz - size of output buffer, octets + * + * Returns length of generated bundle on success, negative upon error. */ +int wc_PKCS7_EncodeSignedCompressedFPD(PKCS7* pkcs7, byte* privateKey, + word32 privateKeySz, int signOID, + int hashOID, byte* content, + word32 contentSz, + PKCS7Attrib* signedAttribs, + word32 signedAttribsSz, byte* output, + word32 outputSz) +{ + int ret = 0, compressedSz = 0; + byte* compressed = NULL; + WC_RNG rng; + + if (pkcs7 == NULL || privateKey == NULL || privateKeySz == 0 || + content == NULL || contentSz == 0 || output == NULL || outputSz == 0) { + return BAD_FUNC_ARG; + } + + /* 1: build up CompressedData using FirmwarePkgData type, use output + * buffer as tmp for storage and to get size */ + + /* set struct elements, inner content type is FirmwarePkgData */ + pkcs7->content = content; + pkcs7->contentSz = contentSz; + pkcs7->contentOID = FIRMWARE_PKG_DATA; + pkcs7->version = 3; + + compressedSz = wc_PKCS7_EncodeCompressedData(pkcs7, output, outputSz); + if (compressedSz < 0) { + WOLFSSL_MSG("Error encoding CMS CompressedData content type"); + return compressedSz; + } + + /* save compressedData, reset output buffer and struct */ + compressed = (byte*)XMALLOC(compressedSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (compressed == NULL) { + ForceZero(output, outputSz); + return MEMORY_E; + } + + XMEMCPY(compressed, output, compressedSz); + ForceZero(output, outputSz); + + ret = wc_InitRng(&rng); + if (ret != 0) { + ForceZero(compressed, compressedSz); + XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + /* 2: build up SignedData, encapsulating EncryptedData */ + pkcs7->rng = &rng; + pkcs7->content = compressed; + pkcs7->contentSz = compressedSz; + pkcs7->contentOID = COMPRESSED_DATA; + pkcs7->hashOID = hashOID; + pkcs7->encryptOID = signOID; + pkcs7->privateKey = privateKey; + pkcs7->privateKeySz = privateKeySz; + pkcs7->signedAttribs = signedAttribs; + pkcs7->signedAttribsSz = signedAttribsSz; + + ret = wc_PKCS7_EncodeSignedData(pkcs7, output, outputSz); + if (ret <= 0) { + WOLFSSL_MSG("Error encoding CMS SignedData content type"); + ForceZero(compressed, compressedSz); + XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + wc_FreeRng(&rng); + return ret; + } + + ForceZero(compressed, compressedSz); + XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + wc_FreeRng(&rng); + + return ret; +} + +#ifndef NO_PKCS7_ENCRYPTED_DATA + +/* Single-shot API to generate a CMS SignedData bundle that encapsulates a + * CMS EncryptedData bundle, which then encapsulates a CMS CompressedData + * bundle. Content of inner CompressedData is set to that of FirmwarePkgData. + * Any recipient certificates should be loaded into the PKCS7 structure prior + * to calling this function, using wc_PKCS7_InitWithCert() and/or + * wc_PKCS7_AddCertificate(). + * + * pkcs7 - pointer to initialized PKCS7 struct + * encryptKey - encryption key used for encrypting EncryptedData + * encryptKeySz - size of encryptKey, octets + * privateKey - private RSA/ECC key, used for signing SignedData + * privateKeySz - size of privateKey, octets + * encryptOID - encryption algorithm OID, to be used as encryption + * algorithm for EncryptedData + * signOID - public key algorithm OID, to be used for sign + * operation in SignedData generation + * hashOID - hash algorithm OID, to be used for signature in + * SignedData generation + * content - content to be encapsulated + * contentSz - size of content, octets + * unprotectedAttribs - optional unprotected attributes, for EncryptedData + * unprotectedAttribsSz - number of PKCS7Attrib members in unprotectedAttribs + * signedAttribs - optional signed attributes, for SignedData + * signedAttribsSz - number of PKCS7Attrib members in signedAttribs + * output - output buffer for final bundle + * outputSz - size of output buffer, octets + * + * Returns length of generated bundle on success, negative upon error. */ +int wc_PKCS7_EncodeSignedEncryptedCompressedFPD(PKCS7* pkcs7, byte* encryptKey, + word32 encryptKeySz, byte* privateKey, + word32 privateKeySz, int encryptOID, + int signOID, int hashOID, byte* content, + word32 contentSz, + PKCS7Attrib* unprotectedAttribs, + word32 unprotectedAttribsSz, + PKCS7Attrib* signedAttribs, + word32 signedAttribsSz, + byte* output, word32 outputSz) +{ + int ret = 0, compressedSz = 0, encryptedSz = 0; + byte* compressed = NULL; + byte* encrypted = NULL; + WC_RNG rng; + + if (pkcs7 == NULL || encryptKey == NULL || encryptKeySz == 0 || + privateKey == NULL || privateKeySz == 0 || content == NULL || + contentSz == 0 || output == NULL || outputSz == 0) { + return BAD_FUNC_ARG; + } + + /* 1: build up CompressedData using FirmwarePkgData type, use output + * buffer as tmp for storage and to get size */ + pkcs7->content = content; + pkcs7->contentSz = contentSz; + pkcs7->contentOID = FIRMWARE_PKG_DATA; + pkcs7->version = 3; + + compressedSz = wc_PKCS7_EncodeCompressedData(pkcs7, output, outputSz); + if (compressedSz < 0) { + WOLFSSL_MSG("Error encoding CMS CompressedData content type"); + return compressedSz; + } + + /* save compressedData, reset output buffer and struct */ + compressed = (byte*)XMALLOC(compressedSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (compressed == NULL) + return MEMORY_E; + + XMEMCPY(compressed, output, compressedSz); + ForceZero(output, outputSz); + + /* 2: build up EncryptedData using CompressedData, use output + * buffer as tmp for storage and to get size */ + pkcs7->content = compressed; + pkcs7->contentSz = compressedSz; + pkcs7->contentOID = COMPRESSED_DATA; + pkcs7->encryptOID = encryptOID; + pkcs7->encryptionKey = encryptKey; + pkcs7->encryptionKeySz = encryptKeySz; + pkcs7->unprotectedAttribs = unprotectedAttribs; + pkcs7->unprotectedAttribsSz = unprotectedAttribsSz; + + encryptedSz = wc_PKCS7_EncodeEncryptedData(pkcs7, output, outputSz); + if (encryptedSz < 0) { + WOLFSSL_MSG("Error encoding CMS EncryptedData content type"); + XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return encryptedSz; + } + + /* save encryptedData, reset output buffer and struct */ + encrypted = (byte*)XMALLOC(encryptedSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (encrypted == NULL) { + ForceZero(compressed, compressedSz); + XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } + + XMEMCPY(encrypted, output, encryptedSz); + ForceZero(compressed, compressedSz); + XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + ForceZero(output, outputSz); + + ret = wc_InitRng(&rng); + if (ret != 0) { + ForceZero(encrypted, encryptedSz); + XFREE(encrypted, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + /* 3: build up SignedData, encapsulating EncryptedData */ + pkcs7->rng = &rng; + pkcs7->content = encrypted; + pkcs7->contentSz = encryptedSz; + pkcs7->contentOID = ENCRYPTED_DATA; + pkcs7->hashOID = hashOID; + pkcs7->encryptOID = signOID; + pkcs7->privateKey = privateKey; + pkcs7->privateKeySz = privateKeySz; + pkcs7->signedAttribs = signedAttribs; + pkcs7->signedAttribsSz = signedAttribsSz; + + ret = wc_PKCS7_EncodeSignedData(pkcs7, output, outputSz); + if (ret <= 0) { + WOLFSSL_MSG("Error encoding CMS SignedData content type"); + ForceZero(encrypted, encryptedSz); + XFREE(encrypted, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + wc_FreeRng(&rng); + return ret; + } + + ForceZero(encrypted, encryptedSz); + XFREE(encrypted, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + wc_FreeRng(&rng); + + return ret; +} + +#endif /* !NO_PKCS7_ENCRYPTED_DATA */ +#endif /* HAVE_LIBZ && !NO_PKCS7_COMPRESSED_DATA */ + + +#ifndef NO_RSA + +/* returns size of signature put into out, negative on error */ +static int wc_PKCS7_RsaVerify(PKCS7* pkcs7, byte* sig, int sigSz, + byte* hash, word32 hashSz) +{ + int ret = 0, i; + word32 scratch = 0, verified = 0; +#ifdef WOLFSSL_SMALL_STACK + byte* digest; + RsaKey* key; + DecodedCert* dCert; +#else + byte digest[MAX_PKCS7_DIGEST_SZ]; + RsaKey key[1]; + DecodedCert stack_dCert; + DecodedCert* dCert = &stack_dCert; +#endif + + if (pkcs7 == NULL || sig == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + digest = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, pkcs7->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (digest == NULL) + return MEMORY_E; + + key = (RsaKey*)XMALLOC(sizeof(RsaKey), pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (key == NULL) { + XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } + + dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), pkcs7->heap, + DYNAMIC_TYPE_DCERT); + if (dCert == NULL) { + XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#endif + + XMEMSET(digest, 0, MAX_PKCS7_DIGEST_SZ); + + /* loop over certs received in certificates set, try to find one + * that will validate signature */ + for (i = 0; i < MAX_PKCS7_CERTS; i++) { + + verified = 0; + scratch = 0; + + if (pkcs7->certSz[i] == 0) + continue; + + ret = wc_InitRsaKey_ex(key, pkcs7->heap, pkcs7->devId); + if (ret != 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(dCert, pkcs7->heap, DYNAMIC_TYPE_DCERT); +#endif + return ret; + } + + InitDecodedCert(dCert, pkcs7->cert[i], pkcs7->certSz[i], pkcs7->heap); + /* not verifying, only using this to extract public key */ + ret = ParseCert(dCert, CA_TYPE, NO_VERIFY, 0); + if (ret < 0) { + WOLFSSL_MSG("ASN RSA cert parse error"); + FreeDecodedCert(dCert); + wc_FreeRsaKey(key); + continue; + } + + if (wc_RsaPublicKeyDecode(dCert->publicKey, &scratch, key, + dCert->pubKeySize) < 0) { + WOLFSSL_MSG("ASN RSA key decode error"); + FreeDecodedCert(dCert); + wc_FreeRsaKey(key); + continue; + } + + #ifdef WOLFSSL_ASYNC_CRYPT + do { + ret = wc_AsyncWait(ret, &key->asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) { + ret = wc_RsaSSL_Verify(sig, sigSz, digest, MAX_PKCS7_DIGEST_SZ, + key); + } + #ifdef WOLFSSL_ASYNC_CRYPT + } while (ret == WC_PENDING_E); + #endif + FreeDecodedCert(dCert); + wc_FreeRsaKey(key); + + if ((ret > 0) && (hashSz == (word32)ret)) { + if (XMEMCMP(digest, hash, hashSz) == 0) { + /* found signer that successfully verified signature */ + verified = 1; + break; + } + } + } + + if (verified == 0) { + ret = SIG_VERIFY_E; + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(dCert, pkcs7->heap, DYNAMIC_TYPE_DCERT); +#endif + + return ret; +} + +#endif /* NO_RSA */ + + +#ifdef HAVE_ECC + +/* returns size of signature put into out, negative on error */ +static int wc_PKCS7_EcdsaVerify(PKCS7* pkcs7, byte* sig, int sigSz, + byte* hash, word32 hashSz) +{ + int ret = 0, i; + int res = 0; + int verified = 0; +#ifdef WOLFSSL_SMALL_STACK + byte* digest; + ecc_key* key; + DecodedCert* dCert; +#else + byte digest[MAX_PKCS7_DIGEST_SZ]; + ecc_key key[1]; + DecodedCert stack_dCert; + DecodedCert* dCert = &stack_dCert; +#endif + word32 idx = 0; + + if (pkcs7 == NULL || sig == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_SMALL_STACK + digest = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, pkcs7->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (digest == NULL) + return MEMORY_E; + + key = (ecc_key*)XMALLOC(sizeof(ecc_key), pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (key == NULL) { + XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } + + dCert = (DecodedCert*)XMALLOC(sizeof(DecodedCert), pkcs7->heap, + DYNAMIC_TYPE_DCERT); + if (dCert == NULL) { + XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#endif + + XMEMSET(digest, 0, MAX_PKCS7_DIGEST_SZ); + + /* loop over certs received in certificates set, try to find one + * that will validate signature */ + for (i = 0; i < MAX_PKCS7_CERTS; i++) { + + verified = 0; + + if (pkcs7->certSz[i] == 0) + continue; + + ret = wc_ecc_init_ex(key, pkcs7->heap, pkcs7->devId); + if (ret != 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(dCert, pkcs7->heap, DYNAMIC_TYPE_DCERT); +#endif + return ret; + } + + InitDecodedCert(dCert, pkcs7->cert[i], pkcs7->certSz[i], pkcs7->heap); + /* not verifying, only using this to extract public key */ + ret = ParseCert(dCert, CA_TYPE, NO_VERIFY, 0); + if (ret < 0) { + WOLFSSL_MSG("ASN ECC cert parse error"); + FreeDecodedCert(dCert); + wc_ecc_free(key); + continue; + } + + if (wc_EccPublicKeyDecode(pkcs7->publicKey, &idx, key, + pkcs7->publicKeySz) < 0) { + WOLFSSL_MSG("ASN ECC key decode error"); + FreeDecodedCert(dCert); + wc_ecc_free(key); + continue; + } + + #ifdef WOLFSSL_ASYNC_CRYPT + do { + ret = wc_AsyncWait(ret, &key->asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) { + ret = wc_ecc_verify_hash(sig, sigSz, hash, hashSz, &res, key); + } + #ifdef WOLFSSL_ASYNC_CRYPT + } while (ret == WC_PENDING_E); + #endif + + FreeDecodedCert(dCert); + wc_ecc_free(key); + + if (ret == 0 && res == 1) { + /* found signer that successfully verified signature */ + verified = 1; + break; + } + } + + if (verified == 0) { + ret = SIG_VERIFY_E; + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(key, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(dCert, pkcs7->heap, DYNAMIC_TYPE_DCERT); +#endif + + return ret; +} + +#endif /* HAVE_ECC */ + + +/* build SignedData digest, both in PKCS#7 DigestInfo format and + * as plain digest for CMS. + * + * pkcs7 - pointer to initialized PKCS7 struct + * signedAttrib - signed attributes + * signedAttribSz - size of signedAttrib, octets + * pkcs7Digest - [OUT] PKCS#7 DigestInfo + * pkcs7DigestSz - [IN/OUT] size of pkcs7Digest + * plainDigest - [OUT] pointer to plain digest, offset into pkcs7Digest + * plainDigestSz - [OUT] size of digest at plainDigest + * + * returns 0 on success, negative on error */ +static int wc_PKCS7_BuildSignedDataDigest(PKCS7* pkcs7, byte* signedAttrib, + word32 signedAttribSz, byte* pkcs7Digest, + word32* pkcs7DigestSz, byte** plainDigest, + word32* plainDigestSz, + const byte* hashBuf, word32 hashBufSz) +{ + int ret = 0, digIdx = 0; + word32 attribSetSz = 0, hashSz = 0; + byte attribSet[MAX_SET_SZ]; + byte digest[WC_MAX_DIGEST_SIZE]; + byte digestInfoSeq[MAX_SEQ_SZ]; + byte digestStr[MAX_OCTET_STR_SZ]; + byte algoId[MAX_ALGO_SZ]; + word32 digestInfoSeqSz, digestStrSz, algoIdSz; +#ifdef WOLFSSL_SMALL_STACK + byte* digestInfo; +#else + byte digestInfo[MAX_PKCS7_DIGEST_SZ]; +#endif + + wc_HashAlg hash; + enum wc_HashType hashType; + + /* check arguments */ + if (pkcs7 == NULL || pkcs7Digest == NULL || + pkcs7DigestSz == NULL || plainDigest == NULL) { + return BAD_FUNC_ARG; + } + + hashType = wc_OidGetHash(pkcs7->hashOID); + ret = wc_HashGetDigestSize(hashType); + if (ret < 0) + return ret; + hashSz = ret; + + if (signedAttribSz > 0) { + if (signedAttrib == NULL) + return BAD_FUNC_ARG; + } + else { + if (hashBuf && hashBufSz > 0) { + if (hashSz != hashBufSz) + return BAD_FUNC_ARG; + } + else if (pkcs7->content == NULL) + return BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + digestInfo = (byte*)XMALLOC(MAX_PKCS7_DIGEST_SZ, pkcs7->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (digestInfo == NULL) + return MEMORY_E; +#endif + + XMEMSET(pkcs7Digest, 0, *pkcs7DigestSz); + XMEMSET(digest, 0, WC_MAX_DIGEST_SIZE); + XMEMSET(digestInfo, 0, MAX_PKCS7_DIGEST_SZ); + + + /* calculate digest */ + if (hashBuf && hashBufSz > 0 && signedAttribSz == 0) { + XMEMCPY(digest, hashBuf, hashBufSz); + } + else { + ret = wc_HashInit(&hash, hashType); + if (ret < 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ret; + } + + if (signedAttribSz > 0) { + attribSetSz = SetSet(signedAttribSz, attribSet); + + /* calculate digest */ + ret = wc_HashUpdate(&hash, hashType, attribSet, attribSetSz); + if (ret == 0) + ret = wc_HashUpdate(&hash, hashType, signedAttrib, signedAttribSz); + if (ret == 0) + ret = wc_HashFinal(&hash, hashType, digest); + } else { + ret = wc_HashUpdate(&hash, hashType, pkcs7->content, pkcs7->contentSz); + if (ret == 0) + ret = wc_HashFinal(&hash, hashType, digest); + } + + wc_HashFree(&hash, hashType); + if (ret < 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ret; + } + } + + /* Set algoID, with NULL attributes */ + algoIdSz = SetAlgoID(pkcs7->hashOID, algoId, oidHashType, 0); + + digestStrSz = SetOctetString(hashSz, digestStr); + digestInfoSeqSz = SetSequence(algoIdSz + digestStrSz + hashSz, + digestInfoSeq); + + XMEMCPY(digestInfo + digIdx, digestInfoSeq, digestInfoSeqSz); + digIdx += digestInfoSeqSz; + XMEMCPY(digestInfo + digIdx, algoId, algoIdSz); + digIdx += algoIdSz; + XMEMCPY(digestInfo + digIdx, digestStr, digestStrSz); + digIdx += digestStrSz; + XMEMCPY(digestInfo + digIdx, digest, hashSz); + digIdx += hashSz; + + XMEMCPY(pkcs7Digest, digestInfo, digIdx); + *pkcs7DigestSz = digIdx; + + /* set plain digest pointer */ + *plainDigest = pkcs7Digest + digIdx - hashSz; + *plainDigestSz = hashSz; + +#ifdef WOLFSSL_SMALL_STACK + XFREE(digestInfo, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return 0; +} + + +/* verifies SignedData signature, over either PKCS#7 DigestInfo or + * content digest. + * + * pkcs7 - pointer to initialized PKCS7 struct + * sig - signature to verify + * sigSz - size of sig + * signedAttrib - signed attributes, or null if empty + * signedAttribSz - size of signedAttributes + * + * return 0 on success, negative on error */ +static int wc_PKCS7_SignedDataVerifySignature(PKCS7* pkcs7, byte* sig, + word32 sigSz, byte* signedAttrib, + word32 signedAttribSz, + const byte* hashBuf, word32 hashSz) +{ + int ret = 0; + word32 plainDigestSz = 0, pkcs7DigestSz; + byte* plainDigest = NULL; /* offset into pkcs7Digest */ +#ifdef WOLFSSL_SMALL_STACK + byte* pkcs7Digest; +#else + byte pkcs7Digest[MAX_PKCS7_DIGEST_SZ]; +#endif + + if (pkcs7 == NULL) + return BAD_FUNC_ARG; + + /* build hash to verify against */ + pkcs7DigestSz = MAX_PKCS7_DIGEST_SZ; +#ifdef WOLFSSL_SMALL_STACK + pkcs7Digest = (byte*)XMALLOC(pkcs7DigestSz, pkcs7->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (pkcs7Digest == NULL) + return MEMORY_E; +#endif + + XMEMSET(pkcs7Digest, 0, pkcs7DigestSz); + + ret = wc_PKCS7_BuildSignedDataDigest(pkcs7, signedAttrib, + signedAttribSz, pkcs7Digest, + &pkcs7DigestSz, &plainDigest, + &plainDigestSz, hashBuf, hashSz); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(pkcs7Digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + /* If no certificates are available then store the signature and hash for + * user to verify. Make sure that different return value than success is + * returned because the signature was not verified here. */ + if (ret == 0) { + byte haveCert = 0; + int i; + + for (i = 0; i < MAX_PKCS7_CERTS; i++) { + if (pkcs7->certSz[i] == 0) + continue; + haveCert = 1; + } + + if (!haveCert) { + WOLFSSL_MSG("No certificates in bundle to verify signature"); + + /* store signature */ + XFREE(pkcs7->signature, pkcs7->heap, DYNAMIC_TYPE_SIGANTURE); + pkcs7->signature = NULL; + pkcs7->signatureSz = 0; + pkcs7->signature = (byte*)XMALLOC(sigSz, pkcs7->heap, + DYNAMIC_TYPE_SIGNATURE); + if (pkcs7->signature == NULL) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(pkcs7Digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return MEMORY_E; + } + XMEMCPY(pkcs7->signature, sig, sigSz); + pkcs7->signatureSz = sigSz; + + /* store plain digest (CMS and ECC) */ + XFREE(pkcs7->plainDigest, pkcs7->heap, DYNAMIC_TYPE_DIGEST); + pkcs7->plainDigest = NULL; + pkcs7->plainDigestSz = 0; + pkcs7->plainDigest = (byte*)XMALLOC(plainDigestSz, pkcs7->heap, + DYNAMIC_TYPE_DIGEST); + if (pkcs7->plainDigest == NULL) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(pkcs7Digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return MEMORY_E; + } + XMEMCPY(pkcs7->plainDigest, plainDigest, plainDigestSz); + pkcs7->plainDigestSz = plainDigestSz; + + /* store pkcs7 digest (default RSA) */ + XFREE(pkcs7->pkcs7Digest, pkcs7->heap, DYNAMIC_TYPE_DIGEST); + pkcs7->pkcs7Digest = NULL; + pkcs7->pkcs7DigestSz = 0; + pkcs7->pkcs7Digest = (byte*)XMALLOC(pkcs7DigestSz, pkcs7->heap, + DYNAMIC_TYPE_DIGEST); + if (pkcs7->pkcs7Digest == NULL) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(pkcs7Digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return MEMORY_E; + } + XMEMCPY(pkcs7->pkcs7Digest, pkcs7Digest, pkcs7DigestSz); + pkcs7->pkcs7DigestSz = pkcs7DigestSz; + + #ifdef WOLFSSL_SMALL_STACK + XFREE(pkcs7Digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return PKCS7_SIGNEEDS_CHECK; + } + } + + + + switch (pkcs7->publicKeyOID) { + +#ifndef NO_RSA + case RSAk: + ret = wc_PKCS7_RsaVerify(pkcs7, sig, sigSz, pkcs7Digest, + pkcs7DigestSz); + if (ret < 0) { + WOLFSSL_MSG("PKCS#7 verification failed, trying CMS"); + ret = wc_PKCS7_RsaVerify(pkcs7, sig, sigSz, plainDigest, + plainDigestSz); + } + break; +#endif + +#ifdef HAVE_ECC + case ECDSAk: + ret = wc_PKCS7_EcdsaVerify(pkcs7, sig, sigSz, plainDigest, + plainDigestSz); + break; +#endif + + default: + WOLFSSL_MSG("Unsupported public key type"); + ret = BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(pkcs7Digest, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; +} + + +/* set correct public key OID based on signature OID, stores in + * pkcs7->publicKeyOID and returns same value */ +static int wc_PKCS7_SetPublicKeyOID(PKCS7* pkcs7, int sigOID) +{ + if (pkcs7 == NULL) + return BAD_FUNC_ARG; + + pkcs7->publicKeyOID = 0; + + switch (sigOID) { + + #ifndef NO_RSA + /* RSA signature types */ + case CTC_MD2wRSA: + case CTC_MD5wRSA: + case CTC_SHAwRSA: + case CTC_SHA224wRSA: + case CTC_SHA256wRSA: + case CTC_SHA384wRSA: + case CTC_SHA512wRSA: + pkcs7->publicKeyOID = RSAk; + break; + + /* if sigOID is already RSAk */ + case RSAk: + pkcs7->publicKeyOID = sigOID; + break; + #endif + + #ifndef NO_DSA + /* DSA signature types */ + case CTC_SHAwDSA: + pkcs7->publicKeyOID = DSAk; + break; + + /* if sigOID is already DSAk */ + case DSAk: + pkcs7->publicKeyOID = sigOID; + break; + #endif + + #ifdef HAVE_ECC + /* ECDSA signature types */ + case CTC_SHAwECDSA: + case CTC_SHA224wECDSA: + case CTC_SHA256wECDSA: + case CTC_SHA384wECDSA: + case CTC_SHA512wECDSA: + pkcs7->publicKeyOID = ECDSAk; + break; + + /* if sigOID is already ECDSAk */ + case ECDSAk: + pkcs7->publicKeyOID = sigOID; + break; + #endif + + default: + WOLFSSL_MSG("Unsupported public key algorithm"); + return ASN_SIG_KEY_E; + } + + return pkcs7->publicKeyOID; +} + + +/* Parses through the attributes and adds them to the PKCS7 structure + * Creates dynamic attribute structures that are free'd with calling + * wc_PKCS7_Free() + * + * NOTE: An attribute has the ASN1 format of + ** Sequence + ****** Object ID + ****** Set + ********** {PritnableString, UTCTime, OCTET STRING ...} + * + * pkcs7 the PKCS7 structure to put the parsed attributes into + * in buffer holding all attributes + * inSz size of in buffer + * + * returns the number of attributes parsed on success + */ +static int wc_PKCS7_ParseAttribs(PKCS7* pkcs7, byte* in, int inSz) +{ + int found = 0; + word32 idx = 0; + word32 oid; + + if (pkcs7 == NULL || in == NULL || inSz < 0) { + return BAD_FUNC_ARG; + } + + while (idx < (word32)inSz) { + int length = 0; + int oidIdx; + PKCS7DecodedAttrib* attrib; + + if (GetSequence(in, &idx, &length, inSz) < 0) + return ASN_PARSE_E; + + attrib = (PKCS7DecodedAttrib*)XMALLOC(sizeof(PKCS7DecodedAttrib), + pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (attrib == NULL) { + return MEMORY_E; + } + XMEMSET(attrib, 0, sizeof(PKCS7DecodedAttrib)); + + oidIdx = idx; + if (GetObjectId(in, &idx, &oid, oidIgnoreType, inSz) + < 0) { + XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + attrib->oidSz = idx - oidIdx; + attrib->oid = (byte*)XMALLOC(attrib->oidSz, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (attrib->oid == NULL) { + XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } + XMEMCPY(attrib->oid, in + oidIdx, attrib->oidSz); + + /* Get Set that contains the printable string value */ + if (GetSet(in, &idx, &length, inSz) < 0) { + XFREE(attrib->oid, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + if ((inSz - idx) < (word32)length) { + XFREE(attrib->oid, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + attrib->valueSz = (word32)length; + attrib->value = (byte*)XMALLOC(attrib->valueSz, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (attrib->value == NULL) { + XFREE(attrib->oid, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(attrib, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } + XMEMCPY(attrib->value, in + idx, attrib->valueSz); + idx += length; + + /* store attribute in linked list */ + if (pkcs7->decodedAttrib != NULL) { + attrib->next = pkcs7->decodedAttrib; + pkcs7->decodedAttrib = attrib; + } else { + pkcs7->decodedAttrib = attrib; + } + found++; + } + + return found; +} + + +/* option to turn off support for degenerate cases + * flag 0 turns off support + * flag 1 turns on support + * + * by default support for SignedData degenerate cases is on + */ +void wc_PKCS7_AllowDegenerate(PKCS7* pkcs7, word16 flag) +{ + if (pkcs7) { + if (flag) { /* flag of 1 turns on support for degenerate */ + pkcs7->noDegenerate = 0; + } + else { /* flag of 0 turns off support */ + pkcs7->noDegenerate = 1; + } + } +} + +/* Parses through a signerInfo set. Reads buffer "in" from "idxIn" to "idxIn" + + * length treating the current "idxIn" plus the length of set as max possible + * index. + * + * In the case that signed attributes are found "signedAttrib" gets set to point + * at their location in the buffer "in". Also in this case signedAttribSz gets + * set to the size of the signedAttrib buffer. + * + * returns 0 on success + */ +static int wc_PKCS7_ParseSignerInfo(PKCS7* pkcs7, byte* in, word32 inSz, + word32* idxIn, int degenerate, byte** signedAttrib, int* signedAttribSz) +{ + int ret = 0; + int length; + int version; + word32 sigOID = 0, hashOID = 0; + word32 idx = *idxIn; + + WOLFSSL_ENTER("wc_PKCS7_ParseSignerInfo"); + /* require a signer if degenerate case not allowed */ + if (inSz == 0 && pkcs7->noDegenerate == 1) { + WOLFSSL_MSG("Set to not allow degenerate cases"); + return PKCS7_NO_SIGNER_E; + } + + if (inSz == 0 && degenerate == 0) { + WOLFSSL_MSG("PKCS7 signers expected"); + return PKCS7_NO_SIGNER_E; + } + + /* not a degenerate case and there is elements in the set */ + if (inSz > 0 && degenerate == 0) { + ret = wc_PKCS7_SignerInfoNew(pkcs7); + + /* Get the sequence of the first signerInfo */ + if (ret == 0 && GetSequence(in, &idx, &length, inSz) < 0) + ret = ASN_PARSE_E; + + /* Get the version */ + if (ret == 0 && GetMyVersion(in, &idx, &version, inSz) < 0) + ret = ASN_PARSE_E; + + if (ret == 0) { + pkcs7->signerInfo->version = version; + } + + if (ret == 0 && version == 1) { + /* Get the sequence of IssuerAndSerialNumber */ + if (GetSequence(in, &idx, &length, inSz) < 0) + ret = ASN_PARSE_E; + + if (ret == 0) { + ret = wc_PKCS7_SignerInfoSetSID(pkcs7, in + idx, length); + idx += length; + } + + } else if (ret == 0 && version == 3) { + /* Get the sequence of SubjectKeyIdentifier */ + if (idx + 1 > inSz) + ret = BUFFER_E; + + if (ret == 0 && in[idx] == + (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { + idx++; + + if (ret == 0 && GetLength(in, &idx, &length, inSz) <= 0) { + ret = ASN_PARSE_E; + } + + if (idx + 1 > inSz) + ret = BUFFER_E; + + if (ret == 0 && in[idx++] != ASN_OCTET_STRING) + ret = ASN_PARSE_E; + + if (ret == 0 && GetLength(in, &idx, &length, inSz) < 0) + ret = ASN_PARSE_E; + } + else { + /* check if SKID with ASN_CONTEXT_SPECIFIC otherwise in version + * 3 try to get issuerAndSerial */ + if (in[idx] == ASN_CONTEXT_SPECIFIC) { + idx++; + if (ret == 0 && GetLength(in, &idx, &length, inSz) < 0) + ret = ASN_PARSE_E; + } + else { + if (pkcs7->version != 3) { + WOLFSSL_MSG("Unexpected signer info found with version"); + ret = ASN_PARSE_E; + } + + if (ret == 0 && GetSequence(in, &idx, &length, inSz) < 0) + ret = ASN_PARSE_E; + } + } + + if (ret == 0) { + ret = wc_PKCS7_SignerInfoSetSID(pkcs7, in + idx, length); + idx += length; + } + + } else { + WOLFSSL_MSG("PKCS#7 signerInfo version must be 1 or 3"); + ret = ASN_VERSION_E; + } + + /* Get the sequence of digestAlgorithm */ + if (ret == 0 && GetAlgoId(in, &idx, &hashOID, oidHashType, inSz) < 0) { + ret = ASN_PARSE_E; + } + pkcs7->hashOID = (int)hashOID; + + /* Get the IMPLICIT[0] SET OF signedAttributes */ + if (ret == 0 && in[idx] == + (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { + idx++; + + if (GetLength(in, &idx, &length, inSz) < 0) + ret = ASN_PARSE_E; + + /* save pointer and length */ + *signedAttrib = &in[idx]; + *signedAttribSz = length; + + if (ret == 0 && wc_PKCS7_ParseAttribs(pkcs7, *signedAttrib, + *signedAttribSz) < 0) { + WOLFSSL_MSG("Error parsing signed attributes"); + ret = ASN_PARSE_E; + } + + idx += length; + } + + /* Get digestEncryptionAlgorithm */ + if (ret == 0 && GetAlgoId(in, &idx, &sigOID, oidSigType, inSz) < 0) { + ret = ASN_PARSE_E; + } + + /* store public key type based on digestEncryptionAlgorithm */ + if (ret == 0) { + ret = wc_PKCS7_SetPublicKeyOID(pkcs7, sigOID); + if (ret < 0) { + WOLFSSL_MSG("Failed to set public key OID from signature"); + } + else { + /* if previous return was positive then was success */ + ret = 0; + } + } + } + + /* update index on success */ + if (ret == 0) { + *idxIn = idx; + } + + return ret; +} + + +/* Finds the certificates in the message and saves it. By default allows + * degenerate cases which can have no signer. + * + * By default expects type SIGNED_DATA (SignedData) which can have any number of + * elements in signerInfos collection, including zero. (RFC2315 section 9.1) + * When adding support for the case of SignedAndEnvelopedData content types a + * signer is required. In this case the PKCS7 flag noDegenerate could be set. + */ +static int PKCS7_VerifySignedData(PKCS7* pkcs7, const byte* hashBuf, + word32 hashSz, byte* in, word32 inSz, + byte* in2, word32 in2Sz) +{ + word32 idx, maxIdx = inSz, outerContentType, contentTypeSz = 0, totalSz = 0; + int length = 0, version = 0, ret = 0; + byte* content = NULL; + byte* contentDynamic = NULL; + byte* sig = NULL; + byte* cert = NULL; + byte* signedAttrib = NULL; + byte* contentType = NULL; + int contentSz = 0, sigSz = 0, certSz = 0, signedAttribSz = 0; + word32 localIdx, start; + byte degenerate = 0; + byte detached = 0; +#ifdef ASN_BER_TO_DER + byte* der; +#endif + int multiPart = 0, keepContent; + int contentLen = 0; + + byte* pkiMsg = in; + word32 pkiMsgSz = inSz; +#ifndef NO_PKCS7_STREAM + word32 stateIdx = 0; + long rc; +#endif + + byte* pkiMsg2 = in2; + word32 pkiMsg2Sz = in2Sz; + + if (pkcs7 == NULL) + return BAD_FUNC_ARG; + +#ifndef NO_PKCS7_STREAM + /* allow for 0 size inputs with stream mode */ + if (pkcs7 == NULL || (pkiMsg == NULL && pkiMsgSz > 0)) + return BAD_FUNC_ARG; + +#else + if (pkiMsg == NULL || pkiMsgSz == 0) + return BAD_FUNC_ARG; + +#endif + + if ((hashSz > 0 && hashBuf == NULL) || (pkiMsg2Sz > 0 && pkiMsg2 == NULL)) { + return BAD_FUNC_ARG; + } + idx = 0; + +#ifdef ASN_BER_TO_DER + if (pkcs7->derSz > 0 && pkcs7->der) { + pkiMsg = in = pkcs7->der; + } +#endif + +#ifndef NO_PKCS7_STREAM + if (pkcs7->stream == NULL) { + if ((ret = wc_PKCS7_CreateStream(pkcs7)) != 0) { + return ret; + } + } +#endif + + switch (pkcs7->state) { + case WC_PKCS7_START: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_SEQ_SZ + + MAX_VERSION_SZ + MAX_SEQ_SZ + MAX_LENGTH_SZ + + ASN_TAG_SZ + MAX_OID_SZ + MAX_SEQ_SZ, + &pkiMsg, &idx)) != 0) { + break; + } + + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, in, inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length :inSz; + #endif + + /* determine total message size */ + totalSz = pkiMsgSz; + if (pkiMsg2 && pkiMsg2Sz > 0) { + totalSz += pkiMsg2Sz + pkcs7->contentSz; + } + + /* Get the contentInfo sequence */ + if (ret == 0 && GetSequence_ex(pkiMsg, &idx, &length, totalSz, + NO_USER_CHECK) < 0) + ret = ASN_PARSE_E; + + if (ret == 0 && length == 0 && pkiMsg[idx-1] == 0x80) { + #ifdef ASN_BER_TO_DER + word32 len = 0; + + ret = wc_BerToDer(pkiMsg, pkiMsgSz, NULL, &len); + if (ret != LENGTH_ONLY_E) + return ret; + pkcs7->der = (byte*)XMALLOC(len, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (pkcs7->der == NULL) + return MEMORY_E; + ret = wc_BerToDer(pkiMsg, pkiMsgSz, pkcs7->der, &len); + if (ret < 0) + return ret; + + pkiMsg = in = pkcs7->der; + pkiMsgSz = pkcs7->derSz = len; + idx = 0; + if (GetSequence_ex(pkiMsg, &idx, &length, pkiMsgSz, + NO_USER_CHECK) < 0) + return ASN_PARSE_E; + + #ifndef NO_PKCS7_STREAM + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, + pkiMsg, pkiMsgSz); + if (rc < 0) { + ret = (int)rc; + break; + } + #endif + #else + ret = BER_INDEF_E; + #endif + } + + /* Get the contentInfo contentType */ + if (ret == 0 && wc_GetContentType(pkiMsg, &idx, &outerContentType, + pkiMsgSz) < 0) + ret = ASN_PARSE_E; + + if (ret == 0 && outerContentType != SIGNED_DATA) { + WOLFSSL_MSG("PKCS#7 input not of type SignedData"); + ret = PKCS7_OID_E; + } + + /* get the ContentInfo content */ + if (ret == 0 && pkiMsg[idx++] != + (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) + ret = ASN_PARSE_E; + + if (ret == 0 && GetLength_ex(pkiMsg, &idx, &length, totalSz, + NO_USER_CHECK) < 0) + ret = ASN_PARSE_E; + + /* Get the signedData sequence */ + if (ret == 0 && GetSequence_ex(pkiMsg, &idx, &length, totalSz, + NO_USER_CHECK) < 0) + ret = ASN_PARSE_E; + + /* Get the version */ + if (ret == 0 && GetMyVersion(pkiMsg, &idx, &version, pkiMsgSz) < 0) + ret = ASN_PARSE_E; + + + /* version 1 follows RFC 2315 */ + /* version 3 follows RFC 4108 */ + if (ret == 0 && (version != 1 && version != 3)) { + WOLFSSL_MSG("PKCS#7 signedData needs to be version 1 or 3"); + ret = ASN_VERSION_E; + } + pkcs7->version = version; + + /* Get the set of DigestAlgorithmIdentifiers */ + if (ret == 0 && GetSet(pkiMsg, &idx, &length, pkiMsgSz) < 0) + ret = ASN_PARSE_E; + + /* Skip the set. */ + idx += length; + degenerate = (length == 0)? 1 : 0; + if (pkcs7->noDegenerate == 1 && degenerate == 1) { + ret = PKCS7_NO_SIGNER_E; + } + + if (ret != 0) + break; + + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &stateIdx, &idx)) != 0) { + break; + } + if (pkiMsg2 && pkiMsg2Sz > 0) { + pkcs7->stream->maxLen += pkiMsg2Sz + pkcs7->contentSz; + } + wc_PKCS7_StreamStoreVar(pkcs7, totalSz, 0, 0); + #endif + + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_VERIFY_STAGE2); + FALL_THROUGH; + + case WC_PKCS7_VERIFY_STAGE2: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz + in2Sz, + MAX_SEQ_SZ + MAX_OID_SZ + ASN_TAG_SZ + MAX_LENGTH_SZ + + ASN_TAG_SZ + MAX_LENGTH_SZ, &pkiMsg, &idx)) != 0) { + break; + } + + wc_PKCS7_StreamGetVar(pkcs7, &totalSz, 0, 0); + if (pkcs7->stream->length > 0) + pkiMsgSz = pkcs7->stream->length; + #ifdef ASN_BER_TO_DER + else if (pkcs7->der) + pkiMsgSz = pkcs7->derSz; + #endif + else + pkiMsgSz = inSz; + + #endif + /* Get the inner ContentInfo sequence */ + if (GetSequence_ex(pkiMsg, &idx, &length, pkiMsgSz, + NO_USER_CHECK) < 0) + ret = ASN_PARSE_E; + + /* Get the inner ContentInfo contentType */ + if (ret == 0) { + word32 tmpIdx = idx; + + if (GetASNObjectId(pkiMsg, &idx, &length, pkiMsgSz) != 0) + ret = ASN_PARSE_E; + + contentType = pkiMsg + tmpIdx; + contentTypeSz = length + (idx - tmpIdx); + + idx += length; + } + + if (ret != 0) + break; + + /* Check for content info, it could be omitted when degenerate */ + localIdx = idx; + ret = 0; + if (localIdx + 1 > pkiMsgSz) { + ret = BUFFER_E; + break; + } + + if (pkiMsg[localIdx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) + ret = ASN_PARSE_E; + + if (ret == 0 && GetLength_ex(pkiMsg, &localIdx, &length, pkiMsgSz, + NO_USER_CHECK) <= 0) + ret = ASN_PARSE_E; + + + /* get length of content in the case that there is multiple parts */ + if (ret == 0 && pkiMsg[localIdx] == (ASN_OCTET_STRING | ASN_CONSTRUCTED)) { + multiPart = 1; + + localIdx++; + /* Get length of all OCTET_STRINGs. */ + if (GetLength_ex(pkiMsg, &localIdx, &contentLen, pkiMsgSz, + NO_USER_CHECK) < 0) + ret = ASN_PARSE_E; + + /* Check whether there is one OCTET_STRING inside. */ + start = localIdx; + if (ret == 0 && pkiMsg[localIdx++] != ASN_OCTET_STRING) + ret = ASN_PARSE_E; + + if (ret == 0 && GetLength_ex(pkiMsg, &localIdx, &length, pkiMsgSz, + NO_USER_CHECK) < 0) + ret = ASN_PARSE_E; + + if (ret == 0) { + /* Use single OCTET_STRING directly. */ + if (localIdx - start + length == (word32)contentLen) + multiPart = 0; + localIdx = start; + } + } + + /* get length of content in case of single part */ + if (ret == 0 && !multiPart) { + if (pkiMsg[localIdx++] != ASN_OCTET_STRING) + ret = ASN_PARSE_E; + + if (ret == 0 && GetLength_ex(pkiMsg, &localIdx, + &length, pkiMsgSz, NO_USER_CHECK) < 0) + ret = ASN_PARSE_E; + } + + /* update idx if successful */ + if (ret == 0) { + /* support using header and footer without content */ + if (pkiMsg2 && pkiMsg2Sz > 0 && hashBuf && hashSz > 0) { + localIdx = 0; + } + idx = localIdx; + } + else { + + /* if pkcs7->content and pkcs7->contentSz are set, try to + process as a detached signature */ + if (!degenerate && + (pkcs7->content != NULL && pkcs7->contentSz != 0)) { + detached = 1; + } + + if (!degenerate && !detached && ret != 0) + break; + + length = 0; /* no content to read */ + pkiMsg2 = pkiMsg; + pkiMsg2Sz = pkiMsgSz; + } + + #ifndef NO_PKCS7_STREAM + /* save detached flag value */ + pkcs7->stream->detached = detached; + + /* save contentType */ + pkcs7->stream->nonce = (byte*)XMALLOC(contentTypeSz, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (pkcs7->stream->nonce == NULL) { + ret = MEMORY_E; + break; + } + else { + pkcs7->stream->nonceSz = contentTypeSz; + XMEMCPY(pkcs7->stream->nonce, contentType, contentTypeSz); + } + + /* content expected? */ + if ((ret == 0 && length > 0) && + !(pkiMsg2 && pkiMsg2Sz > 0 && hashBuf && hashSz > 0)) { + pkcs7->stream->expected = length + ASN_TAG_SZ + MAX_LENGTH_SZ; + } + else { + pkcs7->stream->expected = ASN_TAG_SZ + MAX_LENGTH_SZ; + } + + if (pkcs7->stream->expected > (pkcs7->stream->maxLen - idx)) { + pkcs7->stream->expected = pkcs7->stream->maxLen - idx; + } + + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &stateIdx, &idx)) != 0) { + break; + } + wc_PKCS7_StreamStoreVar(pkcs7, pkiMsg2Sz, localIdx, length); + + /* content length is in multiple parts */ + if (multiPart) { + pkcs7->stream->expected = contentLen + ASN_TAG_SZ; + } + pkcs7->stream->multi = multiPart; + + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_VERIFY_STAGE3); + FALL_THROUGH; + + case WC_PKCS7_VERIFY_STAGE3: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz + in2Sz, + pkcs7->stream->expected, &pkiMsg, &idx)) != 0) { + break; + } + + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, + pkiMsg, pkiMsgSz); + if (rc < 0) { + ret = (int)rc; + break; + } + #ifdef ASN_BER_TO_DER + if (pkcs7->derSz != 0) + pkiMsgSz = pkcs7->derSz; + else + #endif + pkiMsgSz = (word32)rc; + wc_PKCS7_StreamGetVar(pkcs7, &pkiMsg2Sz, (int*)&localIdx, &length); + + if (pkcs7->stream->length > 0) { + localIdx = 0; + } + multiPart = pkcs7->stream->multi; + detached = pkcs7->stream->detached; + maxIdx = idx + pkcs7->stream->expected; + #endif + + /* Break out before content because it can be optional in degenerate + * cases. */ + if (ret != 0 && !degenerate) + break; + + /* get parts of content */ + if (ret == 0 && multiPart) { + int i = 0; + keepContent = !(pkiMsg2 && pkiMsg2Sz > 0 && hashBuf && hashSz > 0); + + if (keepContent) { + /* Create a buffer to hold content of OCTET_STRINGs. */ + pkcs7->contentDynamic = (byte*)XMALLOC(contentLen, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (pkcs7->contentDynamic == NULL) + ret = MEMORY_E; + } + + start = localIdx; + /* Use the data from each OCTET_STRING. */ + while (ret == 0 && localIdx < start + contentLen) { + if (pkiMsg[localIdx++] != ASN_OCTET_STRING) + ret = ASN_PARSE_E; + + if (ret == 0 && GetLength(pkiMsg, &localIdx, &length, totalSz) < 0) + ret = ASN_PARSE_E; + if (ret == 0 && length + localIdx > start + contentLen) + ret = ASN_PARSE_E; + + if (ret == 0) { + if (keepContent) { + XMEMCPY(pkcs7->contentDynamic + i, pkiMsg + localIdx, + length); + } + i += length; + localIdx += length; + } + } + localIdx = start; /* reset for sanity check, increment later */ + length = i; + } + + /* Save the inner data as the content. */ + if (ret == 0 && length > 0) { + contentSz = length; + + /* support using header and footer without content */ + if (pkiMsg2 && pkiMsg2Sz > 0 && hashBuf && hashSz > 0) { + /* Content not provided, use provided pkiMsg2 footer */ + content = NULL; + localIdx = 0; + if (contentSz != (int)pkcs7->contentSz) { + WOLFSSL_MSG("Data signed does not match contentSz provided"); + ret = BUFFER_E; + } + } + else { + if ((word32)length > pkiMsgSz - localIdx) { + ret = BUFFER_E; + } + + /* Content pointer for calculating hashes later */ + if (ret == 0 && !multiPart) { + content = &pkiMsg[localIdx]; + } + if (ret == 0 && multiPart) { + content = pkcs7->contentDynamic; + } + + if (ret == 0) { + idx += length; + + pkiMsg2 = pkiMsg; + pkiMsg2Sz = pkiMsgSz; + #ifndef NO_PKCS7_STREAM + pkcs7->stream->varOne = pkiMsg2Sz; + pkcs7->stream->flagOne = 1; + #endif + } + } + } + else { + pkiMsg2 = pkiMsg; + pkiMsg2Sz = pkiMsgSz; + #ifndef NO_PKCS7_STREAM + pkcs7->stream->varOne = pkiMsg2Sz; + pkcs7->stream->flagOne = 1; + #endif + } + + /* If getting the content info failed with non degenerate then return the + * error case. Otherwise with a degenerate it is ok if the content + * info was omitted */ + if (!degenerate && !detached && (ret != 0)) { + break; + } + else { + ret = 0; /* reset ret state on degenerate case */ + } + + #ifndef NO_PKCS7_STREAM + /* save content */ + if (detached == 1) { + /* if detached, use content from user in pkcs7 struct */ + content = pkcs7->content; + contentSz = pkcs7->contentSz; + } + + if (content != NULL) { + XFREE(pkcs7->stream->content, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + pkcs7->stream->content = (byte*)XMALLOC(contentSz, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (pkcs7->stream->content == NULL) { + ret = MEMORY_E; + break; + } + else { + XMEMCPY(pkcs7->stream->content, content, contentSz); + pkcs7->stream->contentSz = contentSz; + } + } + #endif /* !NO_PKCS7_STREAM */ + + /* Get the implicit[0] set of certificates */ + if (ret == 0 && idx >= pkiMsg2Sz) + ret = BUFFER_E; + + length = 0; /* set length to 0 to check if reading in any certs */ + if (ret == 0 && pkiMsg2[idx] == + (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { + idx++; + if (GetLength_ex(pkiMsg2, &idx, &length, maxIdx, NO_USER_CHECK) + < 0) + ret = ASN_PARSE_E; + } + + if (ret != 0) { + break; + } + #ifndef NO_PKCS7_STREAM + if (in2 && in2Sz > 0 && hashBuf && hashSz > 0) { + stateIdx = idx; /* case where all data was read from in2 */ + } + + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &stateIdx, &idx)) != 0) { + break; + } + wc_PKCS7_StreamStoreVar(pkcs7, pkiMsg2Sz, 0, length); + if (length > 0) { + pkcs7->stream->expected = length; + } + else { + pkcs7->stream->expected = MAX_SEQ_SZ; + if (pkcs7->stream->expected > (pkcs7->stream->maxLen - + pkcs7->stream->totalRd) + pkcs7->stream->length) { + pkcs7->stream->expected = (pkcs7->stream->maxLen - + pkcs7->stream->totalRd) + pkcs7->stream->length; + } + } + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_VERIFY_STAGE4); + FALL_THROUGH; + + case WC_PKCS7_VERIFY_STAGE4: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz + in2Sz, + pkcs7->stream->expected, &pkiMsg, &idx)) != 0) { + break; + } + + wc_PKCS7_StreamGetVar(pkcs7, &pkiMsg2Sz, 0, &length); + if (pkcs7->stream->flagOne) { + pkiMsg2 = pkiMsg; + } + + /* restore content */ + content = pkcs7->stream->content; + contentSz = pkcs7->stream->contentSz; + + /* restore detached flag */ + detached = pkcs7->stream->detached; + + /* store certificate if needed */ + if (length > 0 && in2Sz == 0) { + /* free tmpCert if not NULL */ + XFREE(pkcs7->stream->tmpCert, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + pkcs7->stream->tmpCert = (byte*)XMALLOC(length, + pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (pkcs7->stream->tmpCert == NULL) { + ret = MEMORY_E; + break; + } + XMEMCPY(pkcs7->stream->tmpCert, pkiMsg2 + idx, length); + pkiMsg2 = pkcs7->stream->tmpCert; + pkiMsg2Sz = length; + idx = 0; + } + #endif + + if (length > 0) { + /* At this point, idx is at the first certificate in + * a set of certificates. There may be more than one, + * or none, or they may be a PKCS 6 extended + * certificate. We want to save the first cert if it + * is X.509. */ + + word32 certIdx = idx; + + if (length < MAX_LENGTH_SZ + ASN_TAG_SZ) + ret = BUFFER_E; + + if (pkiMsg2[certIdx++] == (ASN_CONSTRUCTED | ASN_SEQUENCE)) { + if (GetLength(pkiMsg2, &certIdx, &certSz, pkiMsg2Sz) < 0) + ret = ASN_PARSE_E; + + cert = &pkiMsg2[idx]; + certSz += (certIdx - idx); + if (certSz > length) { + ret = BUFFER_E; + break; + } + } + #ifdef ASN_BER_TO_DER + der = pkcs7->der; + #endif + contentDynamic = pkcs7->contentDynamic; + version = pkcs7->version; + + + if (ret == 0) { + #ifndef NO_PKCS7_STREAM + PKCS7State* stream = pkcs7->stream; + #endif + /* This will reset PKCS7 structure and then set the + * certificate */ + ret = wc_PKCS7_InitWithCert(pkcs7, cert, certSz); + #ifndef NO_PKCS7_STREAM + pkcs7->stream = stream; + #endif + } + pkcs7->contentDynamic = contentDynamic; + pkcs7->version = version; + #ifdef ASN_BER_TO_DER + pkcs7->der = der; + #endif + if (ret != 0) + break; + + /* iterate through any additional certificates */ + if (ret == 0 && MAX_PKCS7_CERTS > 0) { + int sz = 0; + int i; + + pkcs7->cert[0] = cert; + pkcs7->certSz[0] = certSz; + certIdx = idx + certSz; + + for (i = 1; i < MAX_PKCS7_CERTS && + certIdx + 1 < pkiMsg2Sz && + certIdx + 1 < (word32)length; i++) { + localIdx = certIdx; + + if (pkiMsg2[certIdx++] == + (ASN_CONSTRUCTED | ASN_SEQUENCE)) { + if (GetLength(pkiMsg2, &certIdx, &sz, + pkiMsg2Sz) < 0) { + ret = ASN_PARSE_E; + break; + } + + pkcs7->cert[i] = &pkiMsg2[localIdx]; + pkcs7->certSz[i] = sz + (certIdx - localIdx); + certIdx += sz; + } + } + } + } + idx += length; + + if (!detached) { + /* set content and size after init of PKCS7 structure */ + pkcs7->content = content; + pkcs7->contentSz = contentSz; + } + #ifndef NO_PKCS7_STREAM + else { + /* save content if detached and using streaming API */ + if (pkcs7->content != NULL) { + XFREE(pkcs7->stream->content, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + pkcs7->stream->content = (byte*)XMALLOC(pkcs7->contentSz, + pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (pkcs7->stream->content == NULL) { + ret = MEMORY_E; + break; + } + else { + XMEMCPY(pkcs7->stream->content, pkcs7->content, + contentSz); + pkcs7->stream->contentSz = pkcs7->contentSz; + } + } + } + #endif + + if (ret != 0) { + break; + } + #ifndef NO_PKCS7_STREAM + /* factor in that recent idx was in cert buffer. If in2 buffer was + * used then don't advance idx. */ + if (length > 0 && pkcs7->stream->flagOne && + pkcs7->stream->length == 0) { + idx = stateIdx + idx; + if (idx > inSz) { + /* index is more than input size */ + ret = BUFFER_E; + break; + } + } + else { + stateIdx = idx; /* didn't read any from internal buffer */ + } + + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &stateIdx, &idx)) != 0) { + break; + } + if (pkcs7->stream->flagOne && pkcs7->stream->length > 0) { + idx = stateIdx + idx; + } + + pkcs7->stream->expected = MAX_OID_SZ + ASN_TAG_SZ + MAX_LENGTH_SZ + + MAX_SET_SZ; + + if (pkcs7->stream->expected > (pkcs7->stream->maxLen - + pkcs7->stream->totalRd) + pkcs7->stream->length) + pkcs7->stream->expected = (pkcs7->stream->maxLen - + pkcs7->stream->totalRd) + pkcs7->stream->length; + + wc_PKCS7_StreamGetVar(pkcs7, &pkiMsg2Sz, 0, 0); + wc_PKCS7_StreamStoreVar(pkcs7, pkiMsg2Sz, 0, length); + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_VERIFY_STAGE5); + FALL_THROUGH; + + case WC_PKCS7_VERIFY_STAGE5: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz + in2Sz, + pkcs7->stream->expected, &pkiMsg, &idx)) != 0) { + break; + } + wc_PKCS7_StreamGetVar(pkcs7, &pkiMsg2Sz, 0, &length); + if (pkcs7->stream->flagOne) { + pkiMsg2 = pkiMsg; + } + + /* restore content type */ + contentType = pkcs7->stream->nonce; + contentTypeSz = pkcs7->stream->nonceSz; + + maxIdx = idx + pkcs7->stream->expected; + if (maxIdx > pkiMsg2Sz) { + ret = BUFFER_E; + break; + } + #endif + + /* set contentType and size after init of PKCS7 structure */ + if (ret == 0 && wc_PKCS7_SetContentType(pkcs7, contentType, + contentTypeSz) < 0) + ret = ASN_PARSE_E; + + /* Get the implicit[1] set of crls */ + if (ret == 0 && idx >= maxIdx) + ret = BUFFER_E; + + if (ret == 0 && pkiMsg2[idx] == + (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) { + idx++; + if (GetLength(pkiMsg2, &idx, &length, pkiMsg2Sz) < 0) + ret = ASN_PARSE_E; + + /* Skip the set */ + idx += length; + } + + /* Get the set of signerInfos */ + if (ret == 0 && GetSet_ex(pkiMsg2, &idx, &length, maxIdx, + NO_USER_CHECK) < 0) + ret = ASN_PARSE_E; + + if (ret != 0) + break; + #ifndef NO_PKCS7_STREAM + if (!pkcs7->stream->flagOne) { + stateIdx = idx; /* didn't read any from internal buffer */ + } + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &stateIdx, &idx)) != 0) { + break; + } + wc_PKCS7_StreamStoreVar(pkcs7, pkiMsg2Sz, 0, length); + + if (in2 && in2Sz > 0 && hashBuf && hashSz > 0) { + if (length > 0) { + pkcs7->stream->expected = length; + } + else { + pkcs7->stream->expected = 0; + } + } + else { + /* last state expect the reset of the buffer */ + pkcs7->stream->expected = (pkcs7->stream->maxLen - + pkcs7->stream->totalRd) + pkcs7->stream->length; + } + + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_VERIFY_STAGE6); + FALL_THROUGH; + + case WC_PKCS7_VERIFY_STAGE6: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz + in2Sz, + pkcs7->stream->expected, &pkiMsg, &idx)) != 0) { + break; + } + + wc_PKCS7_StreamGetVar(pkcs7, &pkiMsg2Sz, 0, &length); + if (pkcs7->stream->flagOne) { + pkiMsg2 = pkiMsg; + } + + /* restore content */ + content = pkcs7->stream->content; + contentSz = pkcs7->stream->contentSz; + #endif + + ret = wc_PKCS7_ParseSignerInfo(pkcs7, pkiMsg2, pkiMsg2Sz, &idx, + degenerate, &signedAttrib, &signedAttribSz); + + /* parse out the signature if present and verify it */ + if (ret == 0 && length > 0 && degenerate == 0) { + WOLFSSL_MSG("Parsing signature and verifying"); + if (idx >= pkiMsg2Sz) + ret = BUFFER_E; + + /* Get the signature */ + if (ret == 0 && pkiMsg2[idx] == ASN_OCTET_STRING) { + idx++; + + if (GetLength(pkiMsg2, &idx, &length, pkiMsg2Sz) < 0) + ret = ASN_PARSE_E; + + /* save pointer and length */ + sig = &pkiMsg2[idx]; + sigSz = length; + + idx += length; + } + + pkcs7->content = content; + pkcs7->contentSz = contentSz; + + if (ret == 0) { + ret = wc_PKCS7_SignedDataVerifySignature(pkcs7, sig, sigSz, + signedAttrib, signedAttribSz, + hashBuf, hashSz); + } + } + + if (ret < 0) + break; + + ret = 0; /* success */ + #ifndef NO_PKCS7_STREAM + wc_PKCS7_ResetStream(pkcs7); + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START); + break; + + default: + WOLFSSL_MSG("PKCS7 Unknown verify state"); + ret = BAD_FUNC_ARG; + } + + if (ret != 0 && ret != WC_PKCS7_WANT_READ_E) { + #ifndef NO_PKCS7_STREAM + wc_PKCS7_ResetStream(pkcs7); + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START); + } + return ret; +} + + +/* Gets a copy of the SID parsed from signerInfo. This can be called after + * wc_PKCS7_VerifySignedData has been called. SID can be SKID in version 3 case + * or issuerAndSerialNumber. + * + * return 0 on success and LENGTH_ONLY_E if just setting "outSz" for buffer + * length needed. + */ +int wc_PKCS7_GetSignerSID(PKCS7* pkcs7, byte* out, word32* outSz) +{ + if (outSz == NULL || pkcs7 == NULL) { + return BAD_FUNC_ARG; + } + + if (pkcs7->signerInfo == NULL) { + WOLFSSL_MSG("Either the bundle had no signers or" + "wc_PKCS7_VerifySignedData needs called yet"); + return PKCS7_NO_SIGNER_E; + } + + if (pkcs7->signerInfo->sidSz == 0) { + WOLFSSL_MSG("Bundle had no signer SID set"); + return PKCS7_NO_SIGNER_E; + } + + if (out == NULL) { + *outSz = pkcs7->signerInfo->sidSz; + return LENGTH_ONLY_E; + } + + if (*outSz < pkcs7->signerInfo->sidSz) { + WOLFSSL_MSG("Buffer being passed in is not large enough for SKID"); + return BUFFER_E; + } + XMEMCPY(out, pkcs7->signerInfo->sid, pkcs7->signerInfo->sidSz); + *outSz = pkcs7->signerInfo->sidSz; + return 0; +} + + +/* variant that allows computed data hash and header/foot, + * which is useful for large data signing */ +int wc_PKCS7_VerifySignedData_ex(PKCS7* pkcs7, const byte* hashBuf, + word32 hashSz, byte* pkiMsgHead, word32 pkiMsgHeadSz, byte* pkiMsgFoot, + word32 pkiMsgFootSz) +{ + return PKCS7_VerifySignedData(pkcs7, hashBuf, hashSz, + pkiMsgHead, pkiMsgHeadSz, pkiMsgFoot, pkiMsgFootSz); +} + +int wc_PKCS7_VerifySignedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz) +{ + return PKCS7_VerifySignedData(pkcs7, NULL, 0, pkiMsg, pkiMsgSz, NULL, 0); +} + + +/* Generate random content encryption key, store into pkcs7->cek and + * pkcs7->cekSz. + * + * pkcs7 - pointer to initialized PKCS7 structure + * len - length of key to be generated + * + * Returns 0 on success, negative upon error */ +static int PKCS7_GenerateContentEncryptionKey(PKCS7* pkcs7, word32 len) +{ + int ret; + WC_RNG rng; + byte* tmpKey; + + if (pkcs7 == NULL || len == 0) + return BAD_FUNC_ARG; + + /* if key already exists, don't need to re-generate */ + if (pkcs7->cek != NULL && pkcs7->cekSz != 0) { + + /* if key exists, but is different size, return error */ + if (pkcs7->cekSz != len) { + WOLFSSL_MSG("Random content-encryption key size is inconsistent " + "between CMS recipients"); + return WC_KEY_SIZE_E; + } + + return 0; + } + + /* allocate space for cek */ + tmpKey = (byte*)XMALLOC(len, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (tmpKey == NULL) + return MEMORY_E; + + XMEMSET(tmpKey, 0, len); + + ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId); + if (ret != 0) { + XFREE(tmpKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + ret = wc_RNG_GenerateBlock(&rng, tmpKey, len); + if (ret != 0) { + wc_FreeRng(&rng); + XFREE(tmpKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + /* store into PKCS7, memory freed during final cleanup */ + pkcs7->cek = tmpKey; + pkcs7->cekSz = len; + + wc_FreeRng(&rng); + + return 0; +} + + +/* wrap CEK (content encryption key) with KEK, 0 on success, < 0 on error */ +static int wc_PKCS7_KeyWrap(byte* cek, word32 cekSz, byte* kek, + word32 kekSz, byte* out, word32 outSz, + int keyWrapAlgo, int direction) +{ + int ret; + + if (cek == NULL || kek == NULL || out == NULL) + return BAD_FUNC_ARG; + + switch (keyWrapAlgo) { +#ifndef NO_AES + #ifdef WOLFSSL_AES_128 + case AES128_WRAP: + #endif + #ifdef WOLFSSL_AES_192 + case AES192_WRAP: + #endif + #ifdef WOLFSSL_AES_256 + case AES256_WRAP: + #endif + + if (direction == AES_ENCRYPTION) { + + ret = wc_AesKeyWrap(kek, kekSz, cek, cekSz, + out, outSz, NULL); + + } else if (direction == AES_DECRYPTION) { + + ret = wc_AesKeyUnWrap(kek, kekSz, cek, cekSz, + out, outSz, NULL); + } else { + WOLFSSL_MSG("Bad key un/wrap direction"); + return BAD_FUNC_ARG; + } + + if (ret <= 0) + return ret; + break; +#endif /* NO_AES */ + + default: + WOLFSSL_MSG("Unsupported key wrap algorithm"); + return BAD_KEYWRAP_ALG_E; + }; + + (void)cekSz; + (void)kekSz; + (void)outSz; + (void)direction; + return ret; +} + + +#ifdef HAVE_ECC + +/* KARI == KeyAgreeRecipientInfo (key agreement) */ +typedef struct WC_PKCS7_KARI { + DecodedCert* decoded; /* decoded recip cert */ + void* heap; /* user heap, points to PKCS7->heap */ + int devId; /* device ID for HW based private key */ + ecc_key* recipKey; /* recip key (pub | priv) */ + ecc_key* senderKey; /* sender key (pub | priv) */ + byte* senderKeyExport; /* sender ephemeral key DER */ + byte* kek; /* key encryption key */ + byte* ukm; /* OPTIONAL user keying material */ + byte* sharedInfo; /* ECC-CMS-SharedInfo ASN.1 encoded blob */ + word32 senderKeyExportSz; /* size of sender ephemeral key DER */ + word32 kekSz; /* size of key encryption key */ + word32 ukmSz; /* size of user keying material */ + word32 sharedInfoSz; /* size of ECC-CMS-SharedInfo encoded */ + byte ukmOwner; /* do we own ukm buffer? 1:yes, 0:no */ + byte direction; /* WC_PKCS7_ENCODE | WC_PKCS7_DECODE */ + byte decodedInit : 1; /* indicates decoded was initialized */ + byte recipKeyInit : 1; /* indicates recipKey was initialized */ + byte senderKeyInit : 1; /* indicates senderKey was initialized */ +} WC_PKCS7_KARI; + + +/* allocate and create new WC_PKCS7_KARI struct, + * returns struct pointer on success, NULL on failure */ +static WC_PKCS7_KARI* wc_PKCS7_KariNew(PKCS7* pkcs7, byte direction) +{ + WC_PKCS7_KARI* kari = NULL; + + if (pkcs7 == NULL) + return NULL; + + kari = (WC_PKCS7_KARI*)XMALLOC(sizeof(WC_PKCS7_KARI), pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (kari == NULL) { + WOLFSSL_MSG("Failed to allocate WC_PKCS7_KARI"); + return NULL; + } + + kari->decoded = (DecodedCert*)XMALLOC(sizeof(DecodedCert), pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (kari->decoded == NULL) { + WOLFSSL_MSG("Failed to allocate DecodedCert"); + XFREE(kari, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return NULL; + } + + kari->recipKey = (ecc_key*)XMALLOC(sizeof(ecc_key), pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (kari->recipKey == NULL) { + WOLFSSL_MSG("Failed to allocate recipient ecc_key"); + XFREE(kari->decoded, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kari, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return NULL; + } + + kari->senderKey = (ecc_key*)XMALLOC(sizeof(ecc_key), pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (kari->senderKey == NULL) { + WOLFSSL_MSG("Failed to allocate sender ecc_key"); + XFREE(kari->recipKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kari->decoded, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kari, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return NULL; + } + + kari->senderKeyExport = NULL; + kari->senderKeyExportSz = 0; + kari->kek = NULL; + kari->kekSz = 0; + kari->ukm = NULL; + kari->ukmSz = 0; + kari->ukmOwner = 0; + kari->sharedInfo = NULL; + kari->sharedInfoSz = 0; + kari->direction = direction; + kari->decodedInit = 0; + kari->recipKeyInit = 0; + kari->senderKeyInit = 0; + + kari->heap = pkcs7->heap; + kari->devId = pkcs7->devId; + + return kari; +} + + +/* free WC_PKCS7_KARI struct, return 0 on success */ +static int wc_PKCS7_KariFree(WC_PKCS7_KARI* kari) +{ + void* heap; + + if (kari) { + heap = kari->heap; + + if (kari->decoded) { + if (kari->decodedInit) + FreeDecodedCert(kari->decoded); + XFREE(kari->decoded, heap, DYNAMIC_TYPE_PKCS7); + } + if (kari->senderKey) { + if (kari->senderKeyInit) + wc_ecc_free(kari->senderKey); + XFREE(kari->senderKey, heap, DYNAMIC_TYPE_PKCS7); + } + if (kari->recipKey) { + if (kari->recipKeyInit) + wc_ecc_free(kari->recipKey); + XFREE(kari->recipKey, heap, DYNAMIC_TYPE_PKCS7); + } + if (kari->senderKeyExport) { + ForceZero(kari->senderKeyExport, kari->senderKeyExportSz); + XFREE(kari->senderKeyExport, heap, DYNAMIC_TYPE_PKCS7); + kari->senderKeyExportSz = 0; + } + if (kari->kek) { + ForceZero(kari->kek, kari->kekSz); + XFREE(kari->kek, heap, DYNAMIC_TYPE_PKCS7); + kari->kekSz = 0; + } + if (kari->ukm) { + if (kari->ukmOwner == 1) { + XFREE(kari->ukm, heap, DYNAMIC_TYPE_PKCS7); + } + kari->ukmSz = 0; + } + if (kari->sharedInfo) { + ForceZero(kari->sharedInfo, kari->sharedInfoSz); + XFREE(kari->sharedInfo, heap, DYNAMIC_TYPE_PKCS7); + kari->sharedInfoSz = 0; + } + XFREE(kari, heap, DYNAMIC_TYPE_PKCS7); + } + + (void)heap; + + return 0; +} + + +/* parse recipient cert/key, return 0 on success, negative on error + * key/keySz only needed during decoding (WC_PKCS7_DECODE) */ +static int wc_PKCS7_KariParseRecipCert(WC_PKCS7_KARI* kari, const byte* cert, + word32 certSz, const byte* key, + word32 keySz) +{ + int ret; + word32 idx; + + if (kari == NULL || kari->decoded == NULL || + cert == NULL || certSz == 0) + return BAD_FUNC_ARG; + + /* decode certificate */ + InitDecodedCert(kari->decoded, (byte*)cert, certSz, kari->heap); + kari->decodedInit = 1; + ret = ParseCert(kari->decoded, CA_TYPE, NO_VERIFY, 0); + if (ret < 0) + return ret; + + /* only supports ECDSA for now */ + if (kari->decoded->keyOID != ECDSAk) { + WOLFSSL_MSG("CMS KARI only supports ECDSA key types"); + return BAD_FUNC_ARG; + } + + /* make sure subject key id was read from cert */ + if (kari->decoded->extSubjKeyIdSet == 0) { + WOLFSSL_MSG("Failed to read subject key ID from recipient cert"); + return BAD_FUNC_ARG; + } + + ret = wc_ecc_init_ex(kari->recipKey, kari->heap, kari->devId); + if (ret != 0) + return ret; + + kari->recipKeyInit = 1; + + /* get recip public key */ + if (kari->direction == WC_PKCS7_ENCODE) { + + idx = 0; + ret = wc_EccPublicKeyDecode(kari->decoded->publicKey, &idx, + kari->recipKey, kari->decoded->pubKeySize); + if (ret != 0) + return ret; + } + /* get recip private key */ + else if (kari->direction == WC_PKCS7_DECODE) { + if (key != NULL && keySz > 0) { + idx = 0; + ret = wc_EccPrivateKeyDecode(key, &idx, kari->recipKey, keySz); + } + else if (kari->devId == INVALID_DEVID) { + ret = BAD_FUNC_ARG; + } + if (ret != 0) + return ret; + + } else { + /* bad direction */ + return BAD_FUNC_ARG; + } + + (void)idx; + + return 0; +} + + +/* create ephemeral ECC key, places ecc_key in kari->senderKey, + * DER encoded in kari->senderKeyExport. return 0 on success, + * negative on error */ +static int wc_PKCS7_KariGenerateEphemeralKey(WC_PKCS7_KARI* kari) +{ + int ret; + WC_RNG rng; + + if (kari == NULL || kari->decoded == NULL || + kari->recipKey == NULL || kari->recipKey->dp == NULL) + return BAD_FUNC_ARG; + + kari->senderKeyExport = (byte*)XMALLOC(kari->decoded->pubKeySize, + kari->heap, DYNAMIC_TYPE_PKCS7); + if (kari->senderKeyExport == NULL) + return MEMORY_E; + + kari->senderKeyExportSz = kari->decoded->pubKeySize; + + ret = wc_ecc_init_ex(kari->senderKey, kari->heap, kari->devId); + if (ret != 0) { + XFREE(kari->senderKeyExport, kari->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + kari->senderKeyInit = 1; + + ret = wc_InitRng_ex(&rng, kari->heap, kari->devId); + if (ret != 0) { + XFREE(kari->senderKeyExport, kari->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + ret = wc_ecc_make_key_ex(&rng, kari->recipKey->dp->size, + kari->senderKey, kari->recipKey->dp->id); + if (ret != 0) { + XFREE(kari->senderKeyExport, kari->heap, DYNAMIC_TYPE_PKCS7); + wc_FreeRng(&rng); + return ret; + } + + wc_FreeRng(&rng); + + /* dump generated key to X.963 DER for output in CMS bundle */ + ret = wc_ecc_export_x963(kari->senderKey, kari->senderKeyExport, + &kari->senderKeyExportSz); + if (ret != 0) { + XFREE(kari->senderKeyExport, kari->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + return 0; +} + + +/* create ASN.1 encoded ECC-CMS-SharedInfo using specified key wrap algorithm, + * place in kari->sharedInfo. returns 0 on success, negative on error */ +static int wc_PKCS7_KariGenerateSharedInfo(WC_PKCS7_KARI* kari, int keyWrapOID) +{ + int idx = 0; + int sharedInfoSeqSz = 0; + int keyInfoSz = 0; + int suppPubInfoSeqSz = 0; + int entityUInfoOctetSz = 0; + int entityUInfoExplicitSz = 0; + int kekOctetSz = 0; + int sharedInfoSz = 0; + + word32 kekBitSz = 0; + + byte sharedInfoSeq[MAX_SEQ_SZ]; + byte keyInfo[MAX_ALGO_SZ]; + byte suppPubInfoSeq[MAX_SEQ_SZ]; + byte entityUInfoOctet[MAX_OCTET_STR_SZ]; + byte entityUInfoExplicitSeq[MAX_SEQ_SZ]; + byte kekOctet[MAX_OCTET_STR_SZ]; + + if (kari == NULL) + return BAD_FUNC_ARG; + + if ((kari->ukmSz > 0) && (kari->ukm == NULL)) + return BAD_FUNC_ARG; + + /* kekOctet */ + kekOctetSz = SetOctetString(sizeof(word32), kekOctet); + sharedInfoSz += (kekOctetSz + sizeof(word32)); + + /* suppPubInfo */ + suppPubInfoSeqSz = SetImplicit(ASN_SEQUENCE, 2, + kekOctetSz + sizeof(word32), + suppPubInfoSeq); + sharedInfoSz += suppPubInfoSeqSz; + + /* optional ukm/entityInfo */ + if (kari->ukmSz > 0) { + entityUInfoOctetSz = SetOctetString(kari->ukmSz, entityUInfoOctet); + sharedInfoSz += (entityUInfoOctetSz + kari->ukmSz); + + entityUInfoExplicitSz = SetExplicit(0, entityUInfoOctetSz + + kari->ukmSz, + entityUInfoExplicitSeq); + sharedInfoSz += entityUInfoExplicitSz; + } + + /* keyInfo */ + keyInfoSz = SetAlgoID(keyWrapOID, keyInfo, oidKeyWrapType, 0); + sharedInfoSz += keyInfoSz; + + /* sharedInfo */ + sharedInfoSeqSz = SetSequence(sharedInfoSz, sharedInfoSeq); + sharedInfoSz += sharedInfoSeqSz; + + kari->sharedInfo = (byte*)XMALLOC(sharedInfoSz, kari->heap, + DYNAMIC_TYPE_PKCS7); + if (kari->sharedInfo == NULL) + return MEMORY_E; + + kari->sharedInfoSz = sharedInfoSz; + + XMEMCPY(kari->sharedInfo + idx, sharedInfoSeq, sharedInfoSeqSz); + idx += sharedInfoSeqSz; + XMEMCPY(kari->sharedInfo + idx, keyInfo, keyInfoSz); + idx += keyInfoSz; + if (kari->ukmSz > 0) { + XMEMCPY(kari->sharedInfo + idx, entityUInfoExplicitSeq, + entityUInfoExplicitSz); + idx += entityUInfoExplicitSz; + XMEMCPY(kari->sharedInfo + idx, entityUInfoOctet, entityUInfoOctetSz); + idx += entityUInfoOctetSz; + XMEMCPY(kari->sharedInfo + idx, kari->ukm, kari->ukmSz); + idx += kari->ukmSz; + } + XMEMCPY(kari->sharedInfo + idx, suppPubInfoSeq, suppPubInfoSeqSz); + idx += suppPubInfoSeqSz; + XMEMCPY(kari->sharedInfo + idx, kekOctet, kekOctetSz); + idx += kekOctetSz; + + kekBitSz = (kari->kekSz) * 8; /* convert to bits */ +#ifdef LITTLE_ENDIAN_ORDER + kekBitSz = ByteReverseWord32(kekBitSz); /* network byte order */ +#endif + XMEMCPY(kari->sharedInfo + idx, &kekBitSz, sizeof(kekBitSz)); + + return 0; +} + + +/* create key encryption key (KEK) using key wrap algorithm and key encryption + * algorithm, place in kari->kek. return 0 on success, <0 on error. */ +static int wc_PKCS7_KariGenerateKEK(WC_PKCS7_KARI* kari, + int keyWrapOID, int keyEncOID) +{ + int ret; + int kSz; + enum wc_HashType kdfType; + byte* secret; + word32 secretSz; + + if (kari == NULL || kari->recipKey == NULL || + kari->senderKey == NULL || kari->senderKey->dp == NULL) + return BAD_FUNC_ARG; + + /* get KEK size, allocate buff */ + kSz = wc_PKCS7_GetOIDKeySize(keyWrapOID); + if (kSz < 0) + return kSz; + + kari->kek = (byte*)XMALLOC(kSz, kari->heap, DYNAMIC_TYPE_PKCS7); + if (kari->kek == NULL) + return MEMORY_E; + + kari->kekSz = (word32)kSz; + + /* generate ECC-CMS-SharedInfo */ + ret = wc_PKCS7_KariGenerateSharedInfo(kari, keyWrapOID); + if (ret != 0) + return ret; + + /* generate shared secret */ + secretSz = kari->senderKey->dp->size; + secret = (byte*)XMALLOC(secretSz, kari->heap, DYNAMIC_TYPE_PKCS7); + if (secret == NULL) + return MEMORY_E; + + if (kari->direction == WC_PKCS7_ENCODE) { + + ret = wc_ecc_shared_secret(kari->senderKey, kari->recipKey, + secret, &secretSz); + + } else if (kari->direction == WC_PKCS7_DECODE) { + + ret = wc_ecc_shared_secret(kari->recipKey, kari->senderKey, + secret, &secretSz); + + } else { + /* bad direction */ + XFREE(secret, kari->heap, DYNAMIC_TYPE_PKCS7); + return BAD_FUNC_ARG; + } + + if (ret != 0) { + XFREE(secret, kari->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + /* run through KDF */ + switch (keyEncOID) { + + #ifndef NO_SHA + case dhSinglePass_stdDH_sha1kdf_scheme: + kdfType = WC_HASH_TYPE_SHA; + break; + #endif + #ifndef WOLFSSL_SHA224 + case dhSinglePass_stdDH_sha224kdf_scheme: + kdfType = WC_HASH_TYPE_SHA224; + break; + #endif + #ifndef NO_SHA256 + case dhSinglePass_stdDH_sha256kdf_scheme: + kdfType = WC_HASH_TYPE_SHA256; + break; + #endif + #ifdef WOLFSSL_SHA384 + case dhSinglePass_stdDH_sha384kdf_scheme: + kdfType = WC_HASH_TYPE_SHA384; + break; + #endif + #ifdef WOLFSSL_SHA512 + case dhSinglePass_stdDH_sha512kdf_scheme: + kdfType = WC_HASH_TYPE_SHA512; + break; + #endif + default: + WOLFSSL_MSG("Unsupported key agreement algorithm"); + XFREE(secret, kari->heap, DYNAMIC_TYPE_PKCS7); + return BAD_FUNC_ARG; + }; + + ret = wc_X963_KDF(kdfType, secret, secretSz, kari->sharedInfo, + kari->sharedInfoSz, kari->kek, kari->kekSz); + if (ret != 0) { + XFREE(secret, kari->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + XFREE(secret, kari->heap, DYNAMIC_TYPE_PKCS7); + + return 0; +} + + +/* Encode and add CMS EnvelopedData KARI (KeyAgreeRecipientInfo) RecipientInfo + * to CMS/PKCS#7 EnvelopedData structure. + * + * Returns 0 on success, negative upon error */ +int wc_PKCS7_AddRecipient_KARI(PKCS7* pkcs7, const byte* cert, word32 certSz, + int keyWrapOID, int keyAgreeOID, byte* ukm, + word32 ukmSz, int options) +{ + Pkcs7EncodedRecip* recip = NULL; + Pkcs7EncodedRecip* lastRecip = NULL; + WC_PKCS7_KARI* kari = NULL; + + word32 idx = 0; + word32 encryptedKeySz = MAX_ENCRYPTED_KEY_SZ; + + int ret = 0; + int keySz, direction = 0; + int blockKeySz = 0; + + /* ASN.1 layout */ + int totalSz = 0; + int kariSeqSz = 0; + byte kariSeq[MAX_SEQ_SZ]; /* IMPLICIT [1] */ + int verSz = 0; + byte ver[MAX_VERSION_SZ]; + + int origIdOrKeySeqSz = 0; + byte origIdOrKeySeq[MAX_SEQ_SZ]; /* IMPLICIT [0] */ + int origPubKeySeqSz = 0; + byte origPubKeySeq[MAX_SEQ_SZ]; /* IMPLICIT [1] */ + int origAlgIdSz = 0; + byte origAlgId[MAX_ALGO_SZ]; + int origPubKeyStrSz = 0; + byte origPubKeyStr[MAX_OCTET_STR_SZ]; + + /* optional user keying material */ + int ukmOctetSz = 0; + byte ukmOctetStr[MAX_OCTET_STR_SZ]; + int ukmExplicitSz = 0; + byte ukmExplicitSeq[MAX_SEQ_SZ]; + + int keyEncryptAlgoIdSz = 0; + byte keyEncryptAlgoId[MAX_ALGO_SZ]; + int keyWrapAlgSz = 0; + byte keyWrapAlg[MAX_ALGO_SZ]; + + int recipEncKeysSeqSz = 0; + byte recipEncKeysSeq[MAX_SEQ_SZ]; + int recipEncKeySeqSz = 0; + byte recipEncKeySeq[MAX_SEQ_SZ]; + int recipKeyIdSeqSz = 0; + byte recipKeyIdSeq[MAX_SEQ_SZ]; /* IMPLICIT [0] */ + int subjKeyIdOctetSz = 0; + byte subjKeyIdOctet[MAX_OCTET_STR_SZ]; + int encryptedKeyOctetSz = 0; + byte encryptedKeyOctet[MAX_OCTET_STR_SZ]; + +#ifdef WOLFSSL_SMALL_STACK + byte* encryptedKey; + + encryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (encryptedKey == NULL) { + return MEMORY_E; + } +#else + byte encryptedKey[MAX_ENCRYPTED_KEY_SZ]; +#endif + + /* allocate and init memory for recipient */ + recip = (Pkcs7EncodedRecip*)XMALLOC(sizeof(Pkcs7EncodedRecip), pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (recip == NULL) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return MEMORY_E; + } + XMEMSET(recip, 0, sizeof(Pkcs7EncodedRecip)); + + /* get key size for content-encryption key based on algorithm */ + blockKeySz = wc_PKCS7_GetOIDKeySize(pkcs7->encryptOID); + if (blockKeySz < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return blockKeySz; + } + + /* generate random content encryption key, if needed */ + ret = PKCS7_GenerateContentEncryptionKey(pkcs7, blockKeySz); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + /* set direction based on keyWrapAlgo */ + switch (keyWrapOID) { +#ifndef NO_AES + #ifdef WOLFSSL_AES_128 + case AES128_WRAP: + #endif + #ifdef WOLFSSL_AES_192 + case AES192_WRAP: + #endif + #ifdef WOLFSSL_AES_256 + case AES256_WRAP: + #endif + direction = AES_ENCRYPTION; + break; +#endif + default: + WOLFSSL_MSG("Unsupported key wrap algorithm"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return BAD_KEYWRAP_ALG_E; + } + + kari = wc_PKCS7_KariNew(pkcs7, WC_PKCS7_ENCODE); + if (kari == NULL) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } + + /* set user keying material if available */ + if (ukmSz > 0 && ukm != NULL) { + kari->ukm = ukm; + kari->ukmSz = ukmSz; + kari->ukmOwner = 0; + } + + /* parse recipient cert, get public key */ + ret = wc_PKCS7_KariParseRecipCert(kari, cert, certSz, NULL, 0); + if (ret != 0) { + wc_PKCS7_KariFree(kari); +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + /* generate sender ephemeral ECC key */ + ret = wc_PKCS7_KariGenerateEphemeralKey(kari); + if (ret != 0) { + wc_PKCS7_KariFree(kari); +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + /* generate KEK (key encryption key) */ + ret = wc_PKCS7_KariGenerateKEK(kari, keyWrapOID, keyAgreeOID); + if (ret != 0) { + wc_PKCS7_KariFree(kari); +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + /* encrypt CEK with KEK */ + keySz = wc_PKCS7_KeyWrap(pkcs7->cek, pkcs7->cekSz, kari->kek, + kari->kekSz, encryptedKey, encryptedKeySz, + keyWrapOID, direction); + if (keySz <= 0) { + wc_PKCS7_KariFree(kari); +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return keySz; + } + encryptedKeySz = (word32)keySz; + + /* Start of RecipientEncryptedKeys */ + + /* EncryptedKey */ + encryptedKeyOctetSz = SetOctetString(encryptedKeySz, encryptedKeyOctet); + totalSz += (encryptedKeyOctetSz + encryptedKeySz); + + /* SubjectKeyIdentifier */ + subjKeyIdOctetSz = SetOctetString(KEYID_SIZE, subjKeyIdOctet); + totalSz += (subjKeyIdOctetSz + KEYID_SIZE); + + /* RecipientKeyIdentifier IMPLICIT [0] */ + recipKeyIdSeqSz = SetImplicit(ASN_SEQUENCE, 0, subjKeyIdOctetSz + + KEYID_SIZE, recipKeyIdSeq); + totalSz += recipKeyIdSeqSz; + + /* RecipientEncryptedKey */ + recipEncKeySeqSz = SetSequence(totalSz, recipEncKeySeq); + totalSz += recipEncKeySeqSz; + + /* RecipientEncryptedKeys */ + recipEncKeysSeqSz = SetSequence(totalSz, recipEncKeysSeq); + totalSz += recipEncKeysSeqSz; + + /* Start of optional UserKeyingMaterial */ + + if (kari->ukmSz > 0) { + ukmOctetSz = SetOctetString(kari->ukmSz, ukmOctetStr); + totalSz += (ukmOctetSz + kari->ukmSz); + + ukmExplicitSz = SetExplicit(1, ukmOctetSz + kari->ukmSz, + ukmExplicitSeq); + totalSz += ukmExplicitSz; + } + + /* Start of KeyEncryptionAlgorithmIdentifier */ + + /* KeyWrapAlgorithm */ + keyWrapAlgSz = SetAlgoID(keyWrapOID, keyWrapAlg, oidKeyWrapType, 0); + totalSz += keyWrapAlgSz; + + /* KeyEncryptionAlgorithmIdentifier */ + keyEncryptAlgoIdSz = SetAlgoID(keyAgreeOID, keyEncryptAlgoId, + oidCmsKeyAgreeType, keyWrapAlgSz); + totalSz += keyEncryptAlgoIdSz; + + /* Start of OriginatorIdentifierOrKey */ + + /* recipient ECPoint, public key */ + XMEMSET(origPubKeyStr, 0, sizeof(origPubKeyStr)); /* no unused bits */ + origPubKeyStr[0] = ASN_BIT_STRING; + origPubKeyStrSz = SetLength(kari->senderKeyExportSz + 1, + origPubKeyStr + 1) + 2; + totalSz += (origPubKeyStrSz + kari->senderKeyExportSz); + + /* Originator AlgorithmIdentifier, params set to NULL for interop + compatibility */ + origAlgIdSz = SetAlgoID(ECDSAk, origAlgId, oidKeyType, 2); + origAlgId[origAlgIdSz++] = ASN_TAG_NULL; + origAlgId[origAlgIdSz++] = 0; + totalSz += origAlgIdSz; + + /* outer OriginatorPublicKey IMPLICIT [1] */ + origPubKeySeqSz = SetImplicit(ASN_SEQUENCE, 1, + origAlgIdSz + origPubKeyStrSz + + kari->senderKeyExportSz, origPubKeySeq); + totalSz += origPubKeySeqSz; + + /* outer OriginatorIdentiferOrKey IMPLICIT [0] */ + origIdOrKeySeqSz = SetImplicit(ASN_SEQUENCE, 0, + origPubKeySeqSz + origAlgIdSz + + origPubKeyStrSz + kari->senderKeyExportSz, + origIdOrKeySeq); + totalSz += origIdOrKeySeqSz; + + /* version, always 3 */ + verSz = SetMyVersion(3, ver, 0); + totalSz += verSz; + recip->recipVersion = 3; + + /* outer IMPLICIT [1] kari */ + kariSeqSz = SetImplicit(ASN_SEQUENCE, 1, totalSz, kariSeq); + totalSz += kariSeqSz; + + if (totalSz > MAX_RECIP_SZ) { + WOLFSSL_MSG("KeyAgreeRecipientInfo output buffer too small"); + wc_PKCS7_KariFree(kari); +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return BUFFER_E; + } + + XMEMCPY(recip->recip + idx, kariSeq, kariSeqSz); + idx += kariSeqSz; + XMEMCPY(recip->recip + idx, ver, verSz); + idx += verSz; + + XMEMCPY(recip->recip + idx, origIdOrKeySeq, origIdOrKeySeqSz); + idx += origIdOrKeySeqSz; + XMEMCPY(recip->recip + idx, origPubKeySeq, origPubKeySeqSz); + idx += origPubKeySeqSz; + + /* AlgorithmIdentifier with NULL parameter */ + XMEMCPY(recip->recip + idx, origAlgId, origAlgIdSz); + idx += origAlgIdSz; + + XMEMCPY(recip->recip + idx, origPubKeyStr, origPubKeyStrSz); + idx += origPubKeyStrSz; + /* ephemeral public key */ + XMEMCPY(recip->recip + idx, kari->senderKeyExport, kari->senderKeyExportSz); + idx += kari->senderKeyExportSz; + + if (kari->ukmSz > 0) { + XMEMCPY(recip->recip + idx, ukmExplicitSeq, ukmExplicitSz); + idx += ukmExplicitSz; + XMEMCPY(recip->recip + idx, ukmOctetStr, ukmOctetSz); + idx += ukmOctetSz; + XMEMCPY(recip->recip + idx, kari->ukm, kari->ukmSz); + idx += kari->ukmSz; + } + + XMEMCPY(recip->recip + idx, keyEncryptAlgoId, keyEncryptAlgoIdSz); + idx += keyEncryptAlgoIdSz; + XMEMCPY(recip->recip + idx, keyWrapAlg, keyWrapAlgSz); + idx += keyWrapAlgSz; + + XMEMCPY(recip->recip + idx, recipEncKeysSeq, recipEncKeysSeqSz); + idx += recipEncKeysSeqSz; + XMEMCPY(recip->recip + idx, recipEncKeySeq, recipEncKeySeqSz); + idx += recipEncKeySeqSz; + XMEMCPY(recip->recip + idx, recipKeyIdSeq, recipKeyIdSeqSz); + idx += recipKeyIdSeqSz; + XMEMCPY(recip->recip + idx, subjKeyIdOctet, subjKeyIdOctetSz); + idx += subjKeyIdOctetSz; + /* subject key id */ + XMEMCPY(recip->recip + idx, kari->decoded->extSubjKeyId, KEYID_SIZE); + idx += KEYID_SIZE; + XMEMCPY(recip->recip + idx, encryptedKeyOctet, encryptedKeyOctetSz); + idx += encryptedKeyOctetSz; + /* encrypted CEK */ + XMEMCPY(recip->recip + idx, encryptedKey, encryptedKeySz); + idx += encryptedKeySz; + + wc_PKCS7_KariFree(kari); +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + /* store recipient size */ + recip->recipSz = idx; + recip->recipType = PKCS7_KARI; + + /* add recipient to recip list */ + if (pkcs7->recipList == NULL) { + pkcs7->recipList = recip; + } else { + lastRecip = pkcs7->recipList; + while (lastRecip->next != NULL) { + lastRecip = lastRecip->next; + } + lastRecip->next = recip; + } + + (void)options; + + return idx; +} + +#endif /* HAVE_ECC */ + +#ifndef NO_RSA + +/* Encode and add CMS EnvelopedData KTRI (KeyTransRecipientInfo) RecipientInfo + * to CMS/PKCS#7 EnvelopedData structure. + * + * Returns 0 on success, negative upon error */ +int wc_PKCS7_AddRecipient_KTRI(PKCS7* pkcs7, const byte* cert, word32 certSz, + int options) +{ + Pkcs7EncodedRecip* recip = NULL; + Pkcs7EncodedRecip* lastRecip = NULL; + + WC_RNG rng; + word32 idx = 0; + word32 encryptedKeySz = 0; + + int ret = 0, blockKeySz; + int verSz = 0, issuerSz = 0, snSz = 0, keyEncAlgSz = 0; + int issuerSeqSz = 0, recipSeqSz = 0, issuerSerialSeqSz = 0; + int encKeyOctetStrSz; + int sidType; + + byte ver[MAX_VERSION_SZ]; + byte issuerSerialSeq[MAX_SEQ_SZ]; + byte recipSeq[MAX_SEQ_SZ]; + byte issuerSeq[MAX_SEQ_SZ]; + byte encKeyOctetStr[MAX_OCTET_STR_SZ]; + + byte issuerSKIDSeq[MAX_SEQ_SZ]; + byte issuerSKID[MAX_OCTET_STR_SZ]; + word32 issuerSKIDSeqSz = 0, issuerSKIDSz = 0; + +#ifdef WOLFSSL_SMALL_STACK + byte* serial; + byte* keyAlgArray; + byte* encryptedKey; + RsaKey* pubKey; + DecodedCert* decoded; + + serial = (byte*)XMALLOC(MAX_SN_SZ, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + keyAlgArray = (byte*)XMALLOC(MAX_SN_SZ, pkcs7->heap, + DYNAMIC_TYPE_TMP_BUFFER); + encryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap, + DYNAMIC_TYPE_TMP_BUFFER); + decoded = (DecodedCert*)XMALLOC(sizeof(DecodedCert), pkcs7->heap, + DYNAMIC_TYPE_TMP_BUFFER); + + if (decoded == NULL || serial == NULL || + encryptedKey == NULL || keyAlgArray == NULL) { + if (serial) + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (keyAlgArray) + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (encryptedKey) + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (decoded) + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#else + byte serial[MAX_SN_SZ]; + byte keyAlgArray[MAX_ALGO_SZ]; + byte encryptedKey[MAX_ENCRYPTED_KEY_SZ]; + + RsaKey pubKey[1]; + DecodedCert decoded[1]; +#endif + + encryptedKeySz = MAX_ENCRYPTED_KEY_SZ; + XMEMSET(encryptedKey, 0, encryptedKeySz); + + /* default to IssuerAndSerialNumber if not set */ + if (pkcs7->sidType != 0) { + sidType = pkcs7->sidType; + } else { + sidType = CMS_ISSUER_AND_SERIAL_NUMBER; + } + + /* allow options to override SubjectIdentifier type if set */ + if (options & CMS_SKID) { + sidType = CMS_SKID; + } else if (options & CMS_ISSUER_AND_SERIAL_NUMBER) { + sidType = CMS_ISSUER_AND_SERIAL_NUMBER; + } + + /* allocate recipient struct */ + recip = (Pkcs7EncodedRecip*)XMALLOC(sizeof(Pkcs7EncodedRecip), pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (recip == NULL) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return MEMORY_E; + } + XMEMSET(recip, 0, sizeof(Pkcs7EncodedRecip)); + + /* get key size for content-encryption key based on algorithm */ + blockKeySz = wc_PKCS7_GetOIDKeySize(pkcs7->encryptOID); + if (blockKeySz < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return blockKeySz; + } + + /* generate random content encryption key, if needed */ + ret = PKCS7_GenerateContentEncryptionKey(pkcs7, blockKeySz); + if (ret < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + InitDecodedCert(decoded, (byte*)cert, certSz, pkcs7->heap); + ret = ParseCert(decoded, CA_TYPE, NO_VERIFY, 0); + if (ret < 0) { + FreeDecodedCert(decoded); +#ifdef WOLFSSL_SMALL_STACK + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + if (sidType == CMS_ISSUER_AND_SERIAL_NUMBER) { + + /* version, must be 0 for IssuerAndSerialNumber */ + verSz = SetMyVersion(0, ver, 0); + recip->recipVersion = 0; + + /* IssuerAndSerialNumber */ + if (decoded->issuerRaw == NULL || decoded->issuerRawLen == 0) { + WOLFSSL_MSG("DecodedCert lacks raw issuer pointer and length"); + FreeDecodedCert(decoded); +#ifdef WOLFSSL_SMALL_STACK + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return -1; + } + issuerSz = decoded->issuerRawLen; + issuerSeqSz = SetSequence(issuerSz, issuerSeq); + + if (decoded->serialSz == 0) { + WOLFSSL_MSG("DecodedCert missing serial number"); + FreeDecodedCert(decoded); +#ifdef WOLFSSL_SMALL_STACK + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return -1; + } + snSz = SetSerialNumber(decoded->serial, decoded->serialSz, serial, + MAX_SN_SZ); + + issuerSerialSeqSz = SetSequence(issuerSeqSz + issuerSz + snSz, + issuerSerialSeq); + + } else if (sidType == CMS_SKID) { + + /* version, must be 2 for SubjectKeyIdentifier */ + verSz = SetMyVersion(2, ver, 0); + recip->recipVersion = 2; + + issuerSKIDSz = SetOctetString(KEYID_SIZE, issuerSKID); + issuerSKIDSeqSz = SetExplicit(0, issuerSKIDSz + KEYID_SIZE, + issuerSKIDSeq); + } else { + FreeDecodedCert(decoded); +#ifdef WOLFSSL_SMALL_STACK + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return PKCS7_RECIP_E; + } + + pkcs7->publicKeyOID = decoded->keyOID; + + /* KeyEncryptionAlgorithmIdentifier, only support RSA now */ + if (pkcs7->publicKeyOID != RSAk) { + FreeDecodedCert(decoded); +#ifdef WOLFSSL_SMALL_STACK + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ALGO_ID_E; + } + + keyEncAlgSz = SetAlgoID(pkcs7->publicKeyOID, keyAlgArray, oidKeyType, 0); + if (keyEncAlgSz == 0) { + FreeDecodedCert(decoded); +#ifdef WOLFSSL_SMALL_STACK + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + pubKey = (RsaKey*)XMALLOC(sizeof(RsaKey), pkcs7->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (pubKey == NULL) { + FreeDecodedCert(decoded); + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } +#endif + + /* EncryptedKey */ + ret = wc_InitRsaKey_ex(pubKey, pkcs7->heap, INVALID_DEVID); + if (ret != 0) { + FreeDecodedCert(decoded); +#ifdef WOLFSSL_SMALL_STACK + XFREE(pubKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + if (wc_RsaPublicKeyDecode(decoded->publicKey, &idx, pubKey, + decoded->pubKeySize) < 0) { + WOLFSSL_MSG("ASN RSA key decode error"); + wc_FreeRsaKey(pubKey); + FreeDecodedCert(decoded); +#ifdef WOLFSSL_SMALL_STACK + XFREE(pubKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return PUBLIC_KEY_E; + } + + ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId); + if (ret != 0) { + wc_FreeRsaKey(pubKey); + FreeDecodedCert(decoded); +#ifdef WOLFSSL_SMALL_STACK + XFREE(pubKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } + + + ret = wc_RsaPublicEncrypt(pkcs7->cek, pkcs7->cekSz, encryptedKey, + encryptedKeySz, pubKey, &rng); + wc_FreeRsaKey(pubKey); + wc_FreeRng(&rng); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(pubKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + if (ret < 0) { + WOLFSSL_MSG("RSA Public Encrypt failed"); + FreeDecodedCert(decoded); +#ifdef WOLFSSL_SMALL_STACK + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + encryptedKeySz = ret; + + encKeyOctetStrSz = SetOctetString(encryptedKeySz, encKeyOctetStr); + + /* RecipientInfo */ + if (sidType == CMS_ISSUER_AND_SERIAL_NUMBER) { + recipSeqSz = SetSequence(verSz + issuerSerialSeqSz + issuerSeqSz + + issuerSz + snSz + keyEncAlgSz + + encKeyOctetStrSz + encryptedKeySz, recipSeq); + + if (recipSeqSz + verSz + issuerSerialSeqSz + issuerSeqSz + snSz + + keyEncAlgSz + encKeyOctetStrSz + encryptedKeySz > MAX_RECIP_SZ) { + WOLFSSL_MSG("RecipientInfo output buffer too small"); + FreeDecodedCert(decoded); +#ifdef WOLFSSL_SMALL_STACK + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return BUFFER_E; + } + + } else { + recipSeqSz = SetSequence(verSz + issuerSKIDSeqSz + issuerSKIDSz + + KEYID_SIZE + keyEncAlgSz + encKeyOctetStrSz + + encryptedKeySz, recipSeq); + + if (recipSeqSz + verSz + issuerSKIDSeqSz + issuerSKIDSz + KEYID_SIZE + + keyEncAlgSz + encKeyOctetStrSz + encryptedKeySz > MAX_RECIP_SZ) { + WOLFSSL_MSG("RecipientInfo output buffer too small"); + FreeDecodedCert(decoded); +#ifdef WOLFSSL_SMALL_STACK + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return BUFFER_E; + } + } + + idx = 0; + XMEMCPY(recip->recip + idx, recipSeq, recipSeqSz); + idx += recipSeqSz; + XMEMCPY(recip->recip + idx, ver, verSz); + idx += verSz; + if (sidType == CMS_ISSUER_AND_SERIAL_NUMBER) { + XMEMCPY(recip->recip + idx, issuerSerialSeq, issuerSerialSeqSz); + idx += issuerSerialSeqSz; + XMEMCPY(recip->recip + idx, issuerSeq, issuerSeqSz); + idx += issuerSeqSz; + XMEMCPY(recip->recip + idx, decoded->issuerRaw, issuerSz); + idx += issuerSz; + XMEMCPY(recip->recip + idx, serial, snSz); + idx += snSz; + } else { + XMEMCPY(recip->recip + idx, issuerSKIDSeq, issuerSKIDSeqSz); + idx += issuerSKIDSeqSz; + XMEMCPY(recip->recip + idx, issuerSKID, issuerSKIDSz); + idx += issuerSKIDSz; + XMEMCPY(recip->recip + idx, pkcs7->issuerSubjKeyId, KEYID_SIZE); + idx += KEYID_SIZE; + } + XMEMCPY(recip->recip + idx, keyAlgArray, keyEncAlgSz); + idx += keyEncAlgSz; + XMEMCPY(recip->recip + idx, encKeyOctetStr, encKeyOctetStrSz); + idx += encKeyOctetStrSz; + XMEMCPY(recip->recip + idx, encryptedKey, encryptedKeySz); + idx += encryptedKeySz; + + FreeDecodedCert(decoded); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(serial, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(keyAlgArray, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(decoded, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + /* store recipient size */ + recip->recipSz = idx; + recip->recipType = PKCS7_KTRI; + + /* add recipient to recip list */ + if (pkcs7->recipList == NULL) { + pkcs7->recipList = recip; + } else { + lastRecip = pkcs7->recipList; + while (lastRecip->next != NULL) { + lastRecip = lastRecip->next; + } + lastRecip->next = recip; + } + + return idx; +} + +#endif /* !NO_RSA */ + + +/* encrypt content using encryptOID algo */ +static int wc_PKCS7_EncryptContent(int encryptOID, byte* key, int keySz, + byte* iv, int ivSz, byte* aad, word32 aadSz, + byte* authTag, word32 authTagSz, byte* in, + int inSz, byte* out) +{ + int ret; +#ifndef NO_AES + Aes aes; +#endif +#ifndef NO_DES3 + Des des; + Des3 des3; +#endif + + if (key == NULL || iv == NULL || in == NULL || out == NULL) + return BAD_FUNC_ARG; + + switch (encryptOID) { +#ifndef NO_AES + #ifdef WOLFSSL_AES_128 + case AES128CBCb: + #endif + #ifdef WOLFSSL_AES_192 + case AES192CBCb: + #endif + #ifdef WOLFSSL_AES_256 + case AES256CBCb: + #endif + if ( + #ifdef WOLFSSL_AES_128 + (encryptOID == AES128CBCb && keySz != 16 ) || + #endif + #ifdef WOLFSSL_AES_192 + (encryptOID == AES192CBCb && keySz != 24 ) || + #endif + #ifdef WOLFSSL_AES_256 + (encryptOID == AES256CBCb && keySz != 32 ) || + #endif + (ivSz != AES_BLOCK_SIZE) ) + return BAD_FUNC_ARG; + + ret = wc_AesInit(&aes, NULL, INVALID_DEVID); + if (ret == 0) { + ret = wc_AesSetKey(&aes, key, keySz, iv, AES_ENCRYPTION); + if (ret == 0) + ret = wc_AesCbcEncrypt(&aes, out, in, inSz); + wc_AesFree(&aes); + } + break; + #ifdef HAVE_AESGCM + #ifdef WOLFSSL_AES_128 + case AES128GCMb: + #endif + #ifdef WOLFSSL_AES_192 + case AES192GCMb: + #endif + #ifdef WOLFSSL_AES_256 + case AES256GCMb: + #endif + #if defined(WOLFSSL_AES_128) || defined(WOLFSSL_AES_192) || \ + defined(WOLFSSL_AES_256) + if (authTag == NULL) + return BAD_FUNC_ARG; + + ret = wc_AesInit(&aes, NULL, INVALID_DEVID); + if (ret == 0) { + ret = wc_AesGcmSetKey(&aes, key, keySz); + if (ret == 0) + ret = wc_AesGcmEncrypt(&aes, out, in, inSz, iv, ivSz, + authTag, authTagSz, aad, aadSz); + wc_AesFree(&aes); + } + break; + #endif + #endif /* HAVE_AESGCM */ + #ifdef HAVE_AESCCM + #ifdef WOLFSSL_AES_128 + case AES128CCMb: + #endif + #ifdef WOLFSSL_AES_192 + case AES192CCMb: + #endif + #ifdef WOLFSSL_AES_256 + case AES256CCMb: + #endif + #if defined(WOLFSSL_AES_128) || defined(WOLFSSL_AES_192) || \ + defined(WOLFSSL_AES_256) + if (authTag == NULL) + return BAD_FUNC_ARG; + + ret = wc_AesInit(&aes, NULL, INVALID_DEVID); + if (ret == 0) { + ret = wc_AesCcmSetKey(&aes, key, keySz); + if (ret == 0) + ret = wc_AesCcmEncrypt(&aes, out, in, inSz, iv, ivSz, + authTag, authTagSz, aad, aadSz); + wc_AesFree(&aes); + } + break; + #endif + #endif /* HAVE_AESCCM */ +#endif /* NO_AES */ +#ifndef NO_DES3 + case DESb: + if (keySz != DES_KEYLEN || ivSz != DES_BLOCK_SIZE) + return BAD_FUNC_ARG; + + ret = wc_Des_SetKey(&des, key, iv, DES_ENCRYPTION); + if (ret == 0) + ret = wc_Des_CbcEncrypt(&des, out, in, inSz); + + break; + + case DES3b: + if (keySz != DES3_KEYLEN || ivSz != DES_BLOCK_SIZE) + return BAD_FUNC_ARG; + + ret = wc_Des3Init(&des3, NULL, INVALID_DEVID); + if (ret == 0) { + ret = wc_Des3_SetKey(&des3, key, iv, DES_ENCRYPTION); + if (ret == 0) + ret = wc_Des3_CbcEncrypt(&des3, out, in, inSz); + wc_Des3Free(&des3); + } + break; +#endif + default: + WOLFSSL_MSG("Unsupported content cipher type"); + return ALGO_ID_E; + }; + +#if defined(NO_AES) || (!defined(HAVE_AESGCM) && !defined(HAVE_AESCCM)) + (void)authTag; + (void)authTagSz; + (void)aad; + (void)aadSz; +#endif + return ret; +} + + +/* decrypt content using encryptOID algo */ +static int wc_PKCS7_DecryptContent(int encryptOID, byte* key, int keySz, + byte* iv, int ivSz, byte* aad, word32 aadSz, + byte* authTag, word32 authTagSz, byte* in, + int inSz, byte* out) +{ + int ret; +#ifndef NO_AES + Aes aes; +#endif +#ifndef NO_DES3 + Des des; + Des3 des3; +#endif + + if (key == NULL || iv == NULL || in == NULL || out == NULL) + return BAD_FUNC_ARG; + + switch (encryptOID) { +#ifndef NO_AES + #ifdef WOLFSSL_AES_128 + case AES128CBCb: + #endif + #ifdef WOLFSSL_AES_192 + case AES192CBCb: + #endif + #ifdef WOLFSSL_AES_256 + case AES256CBCb: + #endif + if ( + #ifdef WOLFSSL_AES_128 + (encryptOID == AES128CBCb && keySz != 16 ) || + #endif + #ifdef WOLFSSL_AES_192 + (encryptOID == AES192CBCb && keySz != 24 ) || + #endif + #ifdef WOLFSSL_AES_256 + (encryptOID == AES256CBCb && keySz != 32 ) || + #endif + (ivSz != AES_BLOCK_SIZE) ) + return BAD_FUNC_ARG; + ret = wc_AesInit(&aes, NULL, INVALID_DEVID); + if (ret == 0) { + ret = wc_AesSetKey(&aes, key, keySz, iv, AES_DECRYPTION); + if (ret == 0) + ret = wc_AesCbcDecrypt(&aes, out, in, inSz); + wc_AesFree(&aes); + } + break; + #ifdef HAVE_AESGCM + #ifdef WOLFSSL_AES_128 + case AES128GCMb: + #endif + #ifdef WOLFSSL_AES_192 + case AES192GCMb: + #endif + #ifdef WOLFSSL_AES_256 + case AES256GCMb: + #endif + #if defined(WOLFSSL_AES_128) || defined(WOLFSSL_AES_192) || \ + defined(WOLFSSL_AES_256) + if (authTag == NULL) + return BAD_FUNC_ARG; + + ret = wc_AesInit(&aes, NULL, INVALID_DEVID); + if (ret == 0) { + ret = wc_AesGcmSetKey(&aes, key, keySz); + if (ret == 0) + ret = wc_AesGcmDecrypt(&aes, out, in, inSz, iv, ivSz, + authTag, authTagSz, aad, aadSz); + wc_AesFree(&aes); + } + break; + #endif + #endif /* HAVE_AESGCM */ + #ifdef HAVE_AESCCM + #ifdef WOLFSSL_AES_128 + case AES128CCMb: + #endif + #ifdef WOLFSSL_AES_192 + case AES192CCMb: + #endif + #ifdef WOLFSSL_AES_256 + case AES256CCMb: + #endif + #if defined(WOLFSSL_AES_128) || defined(WOLFSSL_AES_192) || \ + defined(WOLFSSL_AES_256) + if (authTag == NULL) + return BAD_FUNC_ARG; + + ret = wc_AesInit(&aes, NULL, INVALID_DEVID); + if (ret == 0) { + ret = wc_AesCcmSetKey(&aes, key, keySz); + if (ret == 0) + ret = wc_AesCcmDecrypt(&aes, out, in, inSz, iv, ivSz, + authTag, authTagSz, aad, aadSz); + wc_AesFree(&aes); + } + break; + #endif + #endif /* HAVE_AESCCM */ +#endif /* NO_AES */ +#ifndef NO_DES3 + case DESb: + if (keySz != DES_KEYLEN || ivSz != DES_BLOCK_SIZE) + return BAD_FUNC_ARG; + + ret = wc_Des_SetKey(&des, key, iv, DES_DECRYPTION); + if (ret == 0) + ret = wc_Des_CbcDecrypt(&des, out, in, inSz); + + break; + case DES3b: + if (keySz != DES3_KEYLEN || ivSz != DES_BLOCK_SIZE) + return BAD_FUNC_ARG; + + ret = wc_Des3Init(&des3, NULL, INVALID_DEVID); + if (ret == 0) { + ret = wc_Des3_SetKey(&des3, key, iv, DES_DECRYPTION); + if (ret == 0) + ret = wc_Des3_CbcDecrypt(&des3, out, in, inSz); + wc_Des3Free(&des3); + } + + break; +#endif + default: + WOLFSSL_MSG("Unsupported content cipher type"); + return ALGO_ID_E; + }; + +#if defined(NO_AES) || (!defined(HAVE_AESGCM) && !defined(HAVE_AESCCM)) + (void)authTag; + (void)authTagSz; + (void)aad; + (void)aadSz; +#endif + + return ret; +} + + +/* Generate random block, place in out, return 0 on success negative on error. + * Used for generation of IV, nonce, etc */ +static int wc_PKCS7_GenerateBlock(PKCS7* pkcs7, WC_RNG* rng, byte* out, + word32 outSz) +{ + int ret; + WC_RNG* rnd = NULL; + + if (out == NULL || outSz == 0) + return BAD_FUNC_ARG; + + /* input RNG is optional, init local one if input rng is NULL */ + if (rng == NULL) { + rnd = (WC_RNG*)XMALLOC(sizeof(WC_RNG), pkcs7->heap, DYNAMIC_TYPE_RNG); + if (rnd == NULL) + return MEMORY_E; + + ret = wc_InitRng_ex(rnd, pkcs7->heap, pkcs7->devId); + if (ret != 0) { + XFREE(rnd, pkcs7->heap, DYNAMIC_TYPE_RNG); + return ret; + } + + } else { + rnd = rng; + } + + ret = wc_RNG_GenerateBlock(rnd, out, outSz); + + if (rng == NULL) { + wc_FreeRng(rnd); + XFREE(rnd, pkcs7->heap, DYNAMIC_TYPE_RNG); + } + + return ret; +} + + +/* Set default SignerIdentifier type to be used. Is either + * IssuerAndSerialNumber or SubjectKeyIdentifier. Encoding defaults to using + * IssuerAndSerialNumber unless set with this function or explicitly + * overriden via options when adding RecipientInfo type. + * + * Using the type DEGENERATE_SID skips over signer information. In degenerate + * cases there are no signers. + * + * pkcs7 - pointer to initialized PKCS7 structure + * type - either CMS_ISSUER_AND_SERIAL_NUMBER, CMS_SKID or DEGENERATE_SID + * + * return 0 on success, negative upon error */ +int wc_PKCS7_SetSignerIdentifierType(PKCS7* pkcs7, int type) +{ + if (pkcs7 == NULL) + return BAD_FUNC_ARG; + + if (type != CMS_ISSUER_AND_SERIAL_NUMBER && + type != CMS_SKID && + type != DEGENERATE_SID) { + return BAD_FUNC_ARG; + } + + pkcs7->sidType = type; + + return 0; +} + + +/* Set custom contentType, currently supported with SignedData type + * + * pkcs7 - pointer to initialized PKCS7 structure + * contentType - pointer to array with ASN.1 encoded OID value + * sz - length of contentType array, octets + * + * return 0 on success, negative upon error */ +int wc_PKCS7_SetContentType(PKCS7* pkcs7, byte* contentType, word32 sz) +{ + if (pkcs7 == NULL || contentType == NULL || sz == 0) + return BAD_FUNC_ARG; + + if (sz > MAX_OID_SZ) { + WOLFSSL_MSG("input array too large, bounded by MAX_OID_SZ"); + return BAD_FUNC_ARG; + } + + XMEMCPY(pkcs7->contentType, contentType, sz); + pkcs7->contentTypeSz = sz; + + return 0; +} + + +/* return size of padded data, padded to blockSz chunks, or negative on error */ +int wc_PKCS7_GetPadSize(word32 inputSz, word32 blockSz) +{ + int padSz; + + if (blockSz == 0) + return BAD_FUNC_ARG; + + padSz = blockSz - (inputSz % blockSz); + + return padSz; +} + + +/* pad input data to blockSz chunk, place in outSz. out must be big enough + * for input + pad bytes. See wc_PKCS7_GetPadSize() helper. */ +int wc_PKCS7_PadData(byte* in, word32 inSz, byte* out, word32 outSz, + word32 blockSz) +{ + int i, padSz; + + if (in == NULL || inSz == 0 || + out == NULL || outSz == 0) + return BAD_FUNC_ARG; + + padSz = wc_PKCS7_GetPadSize(inSz, blockSz); + + if (outSz < (inSz + padSz)) + return BAD_FUNC_ARG; + + XMEMCPY(out, in, inSz); + + for (i = 0; i < padSz; i++) { + out[inSz + i] = (byte)padSz; + } + + return inSz + padSz; +} + + +/* Encode and add CMS EnvelopedData ORI (OtherRecipientInfo) RecipientInfo + * to CMS/PKCS#7 EnvelopedData structure. + * + * Return 0 on success, negative upon error */ +int wc_PKCS7_AddRecipient_ORI(PKCS7* pkcs7, CallbackOriEncrypt oriEncryptCb, + int options) +{ + int oriTypeLenSz, blockKeySz, ret; + word32 idx, recipSeqSz; + + Pkcs7EncodedRecip* recip = NULL; + Pkcs7EncodedRecip* lastRecip = NULL; + + byte recipSeq[MAX_SEQ_SZ]; + byte oriTypeLen[MAX_LENGTH_SZ]; + + byte oriType[MAX_ORI_TYPE_SZ]; + byte oriValue[MAX_ORI_VALUE_SZ]; + word32 oriTypeSz = MAX_ORI_TYPE_SZ; + word32 oriValueSz = MAX_ORI_VALUE_SZ; + + if (pkcs7 == NULL || oriEncryptCb == NULL) { + return BAD_FUNC_ARG; + } + + /* allocate memory for RecipientInfo, KEK, encrypted key */ + recip = (Pkcs7EncodedRecip*)XMALLOC(sizeof(Pkcs7EncodedRecip), + pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (recip == NULL) + return MEMORY_E; + XMEMSET(recip, 0, sizeof(Pkcs7EncodedRecip)); + + /* get key size for content-encryption key based on algorithm */ + blockKeySz = wc_PKCS7_GetOIDKeySize(pkcs7->encryptOID); + if (blockKeySz < 0) { + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return blockKeySz; + } + + /* generate random content encryption key, if needed */ + ret = PKCS7_GenerateContentEncryptionKey(pkcs7, blockKeySz); + if (ret < 0) { + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + /* call user callback to encrypt CEK and get oriType and oriValue + values back */ + ret = oriEncryptCb(pkcs7, pkcs7->cek, pkcs7->cekSz, oriType, &oriTypeSz, + oriValue, &oriValueSz, pkcs7->oriEncryptCtx); + if (ret != 0) { + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + oriTypeLenSz = SetLength(oriTypeSz, oriTypeLen); + + recipSeqSz = SetImplicit(ASN_SEQUENCE, 4, 1 + oriTypeLenSz + oriTypeSz + + oriValueSz, recipSeq); + + idx = 0; + XMEMCPY(recip->recip + idx, recipSeq, recipSeqSz); + idx += recipSeqSz; + /* oriType */ + recip->recip[idx] = ASN_OBJECT_ID; + idx += 1; + XMEMCPY(recip->recip + idx, oriTypeLen, oriTypeLenSz); + idx += oriTypeLenSz; + XMEMCPY(recip->recip + idx, oriType, oriTypeSz); + idx += oriTypeSz; + /* oriValue, input MUST already be ASN.1 encoded */ + XMEMCPY(recip->recip + idx, oriValue, oriValueSz); + idx += oriValueSz; + + /* store recipient size */ + recip->recipSz = idx; + recip->recipType = PKCS7_ORI; + recip->recipVersion = 4; + + /* add recipient to recip list */ + if (pkcs7->recipList == NULL) { + pkcs7->recipList = recip; + } else { + lastRecip = pkcs7->recipList; + while (lastRecip->next != NULL) { + lastRecip = lastRecip->next; + } + lastRecip->next = recip; + } + + (void)options; + + return idx; +} + +#if !defined(NO_PWDBASED) && !defined(NO_SHA) + + +static int wc_PKCS7_GenerateKEK_PWRI(PKCS7* pkcs7, byte* passwd, word32 pLen, + byte* salt, word32 saltSz, int kdfOID, + int prfOID, int iterations, byte* out, + word32 outSz) +{ + int ret; + + if (pkcs7 == NULL || passwd == NULL || salt == NULL || out == NULL) + return BAD_FUNC_ARG; + + switch (kdfOID) { + + case PBKDF2_OID: + + ret = wc_PBKDF2(out, passwd, pLen, salt, saltSz, iterations, + outSz, prfOID); + if (ret != 0) { + return ret; + } + + break; + + default: + WOLFSSL_MSG("Unsupported KDF OID"); + return PKCS7_OID_E; + } + + return 0; +} + + +/* RFC3211 (Section 2.3.1) key wrap algorithm (id-alg-PWRI-KEK). + * + * Returns output size on success, negative upon error */ +static int wc_PKCS7_PwriKek_KeyWrap(PKCS7* pkcs7, const byte* kek, word32 kekSz, + const byte* cek, word32 cekSz, + byte* out, word32 *outSz, + const byte* iv, word32 ivSz, int algID) +{ + WC_RNG rng; + int blockSz, outLen, ret; + word32 padSz; + byte* lastBlock; + + if (kek == NULL || cek == NULL || iv == NULL || outSz == NULL) + return BAD_FUNC_ARG; + + /* get encryption algorithm block size */ + blockSz = wc_PKCS7_GetOIDBlockSize(algID); + if (blockSz < 0) + return blockSz; + + /* get pad bytes needed to block boundary */ + padSz = blockSz - ((4 + cekSz) % blockSz); + outLen = 4 + cekSz + padSz; + + /* must be at least two blocks long */ + if (outLen < 2 * blockSz) + padSz += blockSz; + + /* if user set out to NULL, give back required length */ + if (out == NULL) { + *outSz = outLen; + return LENGTH_ONLY_E; + } + + /* verify output buffer is large enough */ + if (*outSz < (word32)outLen) + return BUFFER_E; + + out[0] = cekSz; + out[1] = ~cek[0]; + out[2] = ~cek[1]; + out[3] = ~cek[2]; + XMEMCPY(out + 4, cek, cekSz); + + /* random padding of size padSz */ + ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId); + if (ret != 0) + return ret; + + ret = wc_RNG_GenerateBlock(&rng, out + 4 + cekSz, padSz); + + if (ret == 0) { + /* encrypt, normal */ + ret = wc_PKCS7_EncryptContent(algID, (byte*)kek, kekSz, (byte*)iv, + ivSz, NULL, 0, NULL, 0, out, outLen, out); + } + + if (ret == 0) { + /* encrypt again, using last ciphertext block as IV */ + lastBlock = out + (((outLen / blockSz) - 1) * blockSz); + ret = wc_PKCS7_EncryptContent(algID, (byte*)kek, kekSz, lastBlock, + blockSz, NULL, 0, NULL, 0, out, + outLen, out); + } + + if (ret == 0) { + *outSz = outLen; + } else { + outLen = ret; + } + + wc_FreeRng(&rng); + + return outLen; +} + + +/* RFC3211 (Section 2.3.2) key unwrap algorithm (id-alg-PWRI-KEK). + * + * Returns cek size on success, negative upon error */ +static int wc_PKCS7_PwriKek_KeyUnWrap(PKCS7* pkcs7, const byte* kek, + word32 kekSz, const byte* in, word32 inSz, + byte* out, word32 outSz, const byte* iv, + word32 ivSz, int algID) +{ + int blockSz, cekLen, ret; + byte* tmpIv = NULL; + byte* lastBlock = NULL; + byte* outTmp = NULL; + + if (pkcs7 == NULL || kek == NULL || in == NULL || + out == NULL || iv == NULL) { + return BAD_FUNC_ARG; + } + + outTmp = (byte*)XMALLOC(inSz, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (outTmp == NULL) + return MEMORY_E; + + /* get encryption algorithm block size */ + blockSz = wc_PKCS7_GetOIDBlockSize(algID); + if (blockSz < 0) { + XFREE(outTmp, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + return blockSz; + } + + /* input needs to be blockSz multiple and at least 2 * blockSz */ + if (((inSz % blockSz) != 0) || (inSz < (2 * (word32)blockSz))) { + WOLFSSL_MSG("PWRI-KEK unwrap input must of block size and >= 2 " + "times block size"); + XFREE(outTmp, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + return BAD_FUNC_ARG; + } + + /* use block out[n-1] as IV to decrypt block out[n] */ + lastBlock = (byte*)in + inSz - blockSz; + tmpIv = lastBlock - blockSz; + + /* decrypt last block */ + ret = wc_PKCS7_DecryptContent(algID, (byte*)kek, kekSz, tmpIv, blockSz, + NULL, 0, NULL, 0, lastBlock, blockSz, + outTmp + inSz - blockSz); + + if (ret == 0) { + /* using last decrypted block as IV, decrypt [0 ... n-1] blocks */ + lastBlock = outTmp + inSz - blockSz; + ret = wc_PKCS7_DecryptContent(algID, (byte*)kek, kekSz, lastBlock, + blockSz, NULL, 0, NULL, 0, (byte*)in, + inSz - blockSz, outTmp); + } + + if (ret == 0) { + /* decrypt using original kek and iv */ + ret = wc_PKCS7_DecryptContent(algID, (byte*)kek, kekSz, (byte*)iv, + ivSz, NULL, 0, NULL, 0, outTmp, inSz, + outTmp); + } + + if (ret != 0) { + ForceZero(outTmp, inSz); + XFREE(outTmp, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + + cekLen = outTmp[0]; + + /* verify length */ + if ((word32)cekLen > inSz) { + ForceZero(outTmp, inSz); + XFREE(outTmp, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + return BAD_FUNC_ARG; + } + + /* verify check bytes */ + if ((outTmp[1] ^ outTmp[4]) != 0xFF || + (outTmp[2] ^ outTmp[5]) != 0xFF || + (outTmp[3] ^ outTmp[6]) != 0xFF) { + ForceZero(outTmp, inSz); + XFREE(outTmp, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + return BAD_FUNC_ARG; + } + + if (outSz < (word32)cekLen) { + ForceZero(outTmp, inSz); + XFREE(outTmp, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + return BUFFER_E; + } + + XMEMCPY(out, outTmp + 4, outTmp[0]); + ForceZero(outTmp, inSz); + XFREE(outTmp, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + + return cekLen; +} + + +/* Encode and add CMS EnvelopedData PWRI (PasswordRecipientInfo) RecipientInfo + * to CMS/PKCS#7 EnvelopedData structure. + * + * Return 0 on success, negative upon error */ +int wc_PKCS7_AddRecipient_PWRI(PKCS7* pkcs7, byte* passwd, word32 pLen, + byte* salt, word32 saltSz, int kdfOID, + int hashOID, int iterations, int kekEncryptOID, + int options) +{ + Pkcs7EncodedRecip* recip = NULL; + Pkcs7EncodedRecip* lastRecip = NULL; + + /* PasswordRecipientInfo */ + byte recipSeq[MAX_SEQ_SZ]; + byte ver[MAX_VERSION_SZ]; + word32 recipSeqSz, verSz; + + /* KeyDerivationAlgorithmIdentifier */ + byte kdfAlgoIdSeq[MAX_SEQ_SZ]; + byte kdfAlgoId[MAX_OID_SZ]; + byte kdfParamsSeq[MAX_SEQ_SZ]; /* PBKDF2-params */ + byte kdfSaltOctetStr[MAX_OCTET_STR_SZ]; /* salt OCTET STRING */ + byte kdfIterations[MAX_VERSION_SZ]; + word32 kdfAlgoIdSeqSz, kdfAlgoIdSz; + word32 kdfParamsSeqSz, kdfSaltOctetStrSz, kdfIterationsSz; + /* OPTIONAL: keyLength, not supported yet */ + /* OPTIONAL: prf AlgorithIdentifier, not supported yet */ + + /* KeyEncryptionAlgorithmIdentifier */ + byte keyEncAlgoIdSeq[MAX_SEQ_SZ]; + byte keyEncAlgoId[MAX_OID_SZ]; /* id-alg-PWRI-KEK */ + byte pwriEncAlgoId[MAX_ALGO_SZ]; + byte ivOctetString[MAX_OCTET_STR_SZ]; + word32 keyEncAlgoIdSeqSz, keyEncAlgoIdSz; + word32 pwriEncAlgoIdSz, ivOctetStringSz; + + /* EncryptedKey */ + byte encKeyOctetStr[MAX_OCTET_STR_SZ]; + word32 encKeyOctetStrSz; + + byte tmpIv[MAX_CONTENT_IV_SIZE]; + byte* encryptedKey = NULL; + byte* kek = NULL; + + int cekKeySz = 0, kekKeySz = 0, kekBlockSz = 0, ret = 0; + int encryptOID; + word32 idx, totalSz = 0, encryptedKeySz; + + if (pkcs7 == NULL || passwd == NULL || pLen == 0 || + salt == NULL || saltSz == 0) { + return BAD_FUNC_ARG; + } + + /* allow user to use different KEK encryption algorithm than used for + * main content encryption algorithm, if passed in */ + if (kekEncryptOID != 0) { + encryptOID = kekEncryptOID; + } else { + encryptOID = pkcs7->encryptOID; + } + + /* get content-encryption key size, based on algorithm */ + cekKeySz = wc_PKCS7_GetOIDKeySize(pkcs7->encryptOID); + if (cekKeySz < 0) + return cekKeySz; + + /* get KEK encryption key size, based on algorithm */ + if (encryptOID != pkcs7->encryptOID) { + kekKeySz = wc_PKCS7_GetOIDKeySize(encryptOID); + } else { + kekKeySz = cekKeySz; + } + + /* get KEK encryption block size */ + kekBlockSz = wc_PKCS7_GetOIDBlockSize(encryptOID); + if (kekBlockSz < 0) + return kekBlockSz; + + /* generate random CEK */ + ret = PKCS7_GenerateContentEncryptionKey(pkcs7, cekKeySz); + if (ret < 0) + return ret; + + /* generate random IV */ + ret = wc_PKCS7_GenerateBlock(pkcs7, NULL, tmpIv, kekBlockSz); + if (ret != 0) + return ret; + + /* allocate memory for RecipientInfo, KEK, encrypted key */ + recip = (Pkcs7EncodedRecip*)XMALLOC(sizeof(Pkcs7EncodedRecip), + pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (recip == NULL) + return MEMORY_E; + + kek = (byte*)XMALLOC(kekKeySz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (kek == NULL) { + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } + + encryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, + pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (encryptedKey == NULL) { + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } + + encryptedKeySz = MAX_ENCRYPTED_KEY_SZ; + XMEMSET(recip, 0, sizeof(Pkcs7EncodedRecip)); + XMEMSET(kek, 0, kekKeySz); + XMEMSET(encryptedKey, 0, encryptedKeySz); + + /* generate KEK: expand password into KEK */ + ret = wc_PKCS7_GenerateKEK_PWRI(pkcs7, passwd, pLen, salt, saltSz, + kdfOID, hashOID, iterations, kek, + kekKeySz); + if (ret < 0) { + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + /* generate encrypted key: encrypt CEK with KEK */ + ret = wc_PKCS7_PwriKek_KeyWrap(pkcs7, kek, kekKeySz, pkcs7->cek, + pkcs7->cekSz, encryptedKey, &encryptedKeySz, + tmpIv, kekBlockSz, encryptOID); + if (ret < 0) { + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + encryptedKeySz = ret; + + /* put together encrypted key OCTET STRING */ + encKeyOctetStrSz = SetOctetString(encryptedKeySz, encKeyOctetStr); + totalSz += (encKeyOctetStrSz + encryptedKeySz); + + /* put together IV OCTET STRING */ + ivOctetStringSz = SetOctetString(kekBlockSz, ivOctetString); + totalSz += (ivOctetStringSz + kekBlockSz); + + /* set PWRIAlgorithms AlgorithmIdentifier, adding (ivOctetStringSz + + blockKeySz) for IV OCTET STRING */ + pwriEncAlgoIdSz = SetAlgoID(encryptOID, pwriEncAlgoId, + oidBlkType, ivOctetStringSz + kekBlockSz); + totalSz += pwriEncAlgoIdSz; + + /* set KeyEncryptionAlgorithms OID */ + ret = wc_SetContentType(PWRI_KEK_WRAP, keyEncAlgoId, sizeof(keyEncAlgoId)); + if (ret <= 0) { + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + keyEncAlgoIdSz = ret; + totalSz += keyEncAlgoIdSz; + + /* KeyEncryptionAlgorithm SEQ */ + keyEncAlgoIdSeqSz = SetSequence(keyEncAlgoIdSz + pwriEncAlgoIdSz + + ivOctetStringSz + kekBlockSz, + keyEncAlgoIdSeq); + totalSz += keyEncAlgoIdSeqSz; + + /* set KDF salt */ + kdfSaltOctetStrSz = SetOctetString(saltSz, kdfSaltOctetStr); + totalSz += (kdfSaltOctetStrSz + saltSz); + + /* set KDF iteration count */ + kdfIterationsSz = SetMyVersion(iterations, kdfIterations, 0); + totalSz += kdfIterationsSz; + + /* set KDF params SEQ */ + kdfParamsSeqSz = SetSequence(kdfSaltOctetStrSz + saltSz + kdfIterationsSz, + kdfParamsSeq); + totalSz += kdfParamsSeqSz; + + /* set KDF algo OID */ + ret = wc_SetContentType(kdfOID, kdfAlgoId, sizeof(kdfAlgoId)); + if (ret <= 0) { + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + kdfAlgoIdSz = ret; + totalSz += kdfAlgoIdSz; + + /* set KeyDerivationAlgorithmIdentifier EXPLICIT [0] SEQ */ + kdfAlgoIdSeqSz = SetExplicit(0, kdfAlgoIdSz + kdfParamsSeqSz + + kdfSaltOctetStrSz + saltSz + kdfIterationsSz, + kdfAlgoIdSeq); + totalSz += kdfAlgoIdSeqSz; + + /* set PasswordRecipientInfo CMSVersion, MUST be 0 */ + verSz = SetMyVersion(0, ver, 0); + totalSz += verSz; + recip->recipVersion = 0; + + /* set PasswordRecipientInfo SEQ */ + recipSeqSz = SetImplicit(ASN_SEQUENCE, 3, totalSz, recipSeq); + totalSz += recipSeqSz; + + if (totalSz > MAX_RECIP_SZ) { + WOLFSSL_MSG("CMS Recipient output buffer too small"); + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return BUFFER_E; + } + + idx = 0; + XMEMCPY(recip->recip + idx, recipSeq, recipSeqSz); + idx += recipSeqSz; + XMEMCPY(recip->recip + idx, ver, verSz); + idx += verSz; + XMEMCPY(recip->recip + idx, kdfAlgoIdSeq, kdfAlgoIdSeqSz); + idx += kdfAlgoIdSeqSz; + XMEMCPY(recip->recip + idx, kdfAlgoId, kdfAlgoIdSz); + idx += kdfAlgoIdSz; + XMEMCPY(recip->recip + idx, kdfParamsSeq, kdfParamsSeqSz); + idx += kdfParamsSeqSz; + XMEMCPY(recip->recip + idx, kdfSaltOctetStr, kdfSaltOctetStrSz); + idx += kdfSaltOctetStrSz; + XMEMCPY(recip->recip + idx, salt, saltSz); + idx += saltSz; + XMEMCPY(recip->recip + idx, kdfIterations, kdfIterationsSz); + idx += kdfIterationsSz; + XMEMCPY(recip->recip + idx, keyEncAlgoIdSeq, keyEncAlgoIdSeqSz); + idx += keyEncAlgoIdSeqSz; + XMEMCPY(recip->recip + idx, keyEncAlgoId, keyEncAlgoIdSz); + idx += keyEncAlgoIdSz; + XMEMCPY(recip->recip + idx, pwriEncAlgoId, pwriEncAlgoIdSz); + idx += pwriEncAlgoIdSz; + XMEMCPY(recip->recip + idx, ivOctetString, ivOctetStringSz); + idx += ivOctetStringSz; + XMEMCPY(recip->recip + idx, tmpIv, kekBlockSz); + idx += kekBlockSz; + XMEMCPY(recip->recip + idx, encKeyOctetStr, encKeyOctetStrSz); + idx += encKeyOctetStrSz; + XMEMCPY(recip->recip + idx, encryptedKey, encryptedKeySz); + idx += encryptedKeySz; + + ForceZero(kek, kekBlockSz); + ForceZero(encryptedKey, encryptedKeySz); + XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + + /* store recipient size */ + recip->recipSz = idx; + recip->recipType = PKCS7_PWRI; + + /* add recipient to recip list */ + if (pkcs7->recipList == NULL) { + pkcs7->recipList = recip; + } else { + lastRecip = pkcs7->recipList; + while (lastRecip->next != NULL) { + lastRecip = lastRecip->next; + } + lastRecip->next = recip; + } + + (void)options; + + return idx; +} + +/* Import password and KDF settings into a PKCS7 structure. Used for setting + * the password info for decryption a EnvelopedData PWRI RecipientInfo. + * + * Returns 0 on success, negative upon error */ +int wc_PKCS7_SetPassword(PKCS7* pkcs7, byte* passwd, word32 pLen) +{ + if (pkcs7 == NULL || passwd == NULL || pLen == 0) + return BAD_FUNC_ARG; + + pkcs7->pass = passwd; + pkcs7->passSz = pLen; + + return 0; +} + +#endif /* NO_PWDBASED */ + + +/* Encode and add CMS EnvelopedData KEKRI (KEKRecipientInfo) RecipientInfo + * to CMS/PKCS#7 EnvelopedData structure. + * + * pkcs7 - pointer to initialized PKCS7 structure + * keyWrapOID - OID sum of key wrap algorithm identifier + * kek - key encryption key + * kekSz - size of kek, bytes + * keyID - key-encryption key identifier, pre-distributed to endpoints + * keyIDSz - size of keyID, bytes + * timePtr - pointer to "time_t", which is typically "long" (OPTIONAL) + * otherOID - ASN.1 encoded OID of other attribute (OPTIONAL) + * otherOIDSz - size of otherOID, bytes (OPTIONAL) + * other - other attribute (OPTIONAL) + * otherSz - size of other (OPTIONAL) + * + * Returns 0 on success, negative upon error */ +int wc_PKCS7_AddRecipient_KEKRI(PKCS7* pkcs7, int keyWrapOID, byte* kek, + word32 kekSz, byte* keyId, word32 keyIdSz, + void* timePtr, byte* otherOID, + word32 otherOIDSz, byte* other, word32 otherSz, + int options) +{ + Pkcs7EncodedRecip* recip = NULL; + Pkcs7EncodedRecip* lastRecip = NULL; + + byte recipSeq[MAX_SEQ_SZ]; + byte ver[MAX_VERSION_SZ]; + byte kekIdSeq[MAX_SEQ_SZ]; + byte kekIdOctetStr[MAX_OCTET_STR_SZ]; + byte genTime[ASN_GENERALIZED_TIME_SIZE]; + byte otherAttSeq[MAX_SEQ_SZ]; + byte encAlgoId[MAX_ALGO_SZ]; + byte encKeyOctetStr[MAX_OCTET_STR_SZ]; +#ifdef WOLFSSL_SMALL_STACK + byte* encryptedKey; +#else + byte encryptedKey[MAX_ENCRYPTED_KEY_SZ]; +#endif + + int blockKeySz = 0, ret = 0, direction; + word32 idx = 0; + word32 totalSz = 0; + word32 recipSeqSz = 0, verSz = 0; + word32 kekIdSeqSz = 0, kekIdOctetStrSz = 0; + word32 otherAttSeqSz = 0, encAlgoIdSz = 0, encKeyOctetStrSz = 0; + int encryptedKeySz; + + int timeSz = 0; +#ifndef NO_ASN_TIME + time_t* tm = NULL; +#endif + + if (pkcs7 == NULL || kek == NULL || keyId == NULL) + return BAD_FUNC_ARG; + + recip = (Pkcs7EncodedRecip*)XMALLOC(sizeof(Pkcs7EncodedRecip), pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (recip == NULL) + return MEMORY_E; + + XMEMSET(recip, 0, sizeof(Pkcs7EncodedRecip)); + + /* get key size for content-encryption key based on algorithm */ + blockKeySz = wc_PKCS7_GetOIDKeySize(pkcs7->encryptOID); + if (blockKeySz < 0) { + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return blockKeySz; + } + + /* generate random content encryption key, if needed */ + ret = PKCS7_GenerateContentEncryptionKey(pkcs7, blockKeySz); + if (ret < 0) { + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + /* EncryptedKey */ +#ifdef WOLFSSL_SMALL_STACK + encryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (encryptedKey == NULL) { + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } +#endif + encryptedKeySz = MAX_ENCRYPTED_KEY_SZ; + XMEMSET(encryptedKey, 0, encryptedKeySz); + + #ifndef NO_AES + direction = AES_ENCRYPTION; + #else + direction = DES_ENCRYPTION; + #endif + + encryptedKeySz = wc_PKCS7_KeyWrap(pkcs7->cek, pkcs7->cekSz, kek, kekSz, + encryptedKey, encryptedKeySz, keyWrapOID, + direction); + if (encryptedKeySz < 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return encryptedKeySz; + } + /* handle a zero size encKey case as WC_KEY_SIZE_E */ + if (encryptedKeySz == 0 || encryptedKeySz > MAX_ENCRYPTED_KEY_SZ) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #endif + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return WC_KEY_SIZE_E; + } + + encKeyOctetStrSz = SetOctetString(encryptedKeySz, encKeyOctetStr); + totalSz += (encKeyOctetStrSz + encryptedKeySz); + + /* KeyEncryptionAlgorithmIdentifier */ + encAlgoIdSz = SetAlgoID(keyWrapOID, encAlgoId, oidKeyWrapType, 0); + totalSz += encAlgoIdSz; + + /* KEKIdentifier: keyIdentifier */ + kekIdOctetStrSz = SetOctetString(keyIdSz, kekIdOctetStr); + totalSz += (kekIdOctetStrSz + keyIdSz); + + /* KEKIdentifier: GeneralizedTime (OPTIONAL) */ +#ifndef NO_ASN_TIME + if (timePtr != NULL) { + tm = (time_t*)timePtr; + timeSz = GetAsnTimeString(tm, genTime, sizeof(genTime)); + if (timeSz < 0) { + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #endif + return timeSz; + } + totalSz += timeSz; + } +#endif + + /* KEKIdentifier: OtherKeyAttribute SEQ (OPTIONAL) */ + if (other != NULL && otherSz > 0) { + otherAttSeqSz = SetSequence(otherOIDSz + otherSz, otherAttSeq); + totalSz += otherAttSeqSz + otherOIDSz + otherSz; + } + + /* KEKIdentifier SEQ */ + kekIdSeqSz = SetSequence(kekIdOctetStrSz + keyIdSz + timeSz + + otherAttSeqSz + otherOIDSz + otherSz, kekIdSeq); + totalSz += kekIdSeqSz; + + /* version */ + verSz = SetMyVersion(4, ver, 0); + totalSz += verSz; + recip->recipVersion = 4; + + /* KEKRecipientInfo SEQ */ + recipSeqSz = SetImplicit(ASN_SEQUENCE, 2, totalSz, recipSeq); + totalSz += recipSeqSz; + + if (totalSz > MAX_RECIP_SZ) { + WOLFSSL_MSG("CMS Recipient output buffer too small"); + XFREE(recip, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #endif + return BUFFER_E; + } + + XMEMCPY(recip->recip + idx, recipSeq, recipSeqSz); + idx += recipSeqSz; + XMEMCPY(recip->recip + idx, ver, verSz); + idx += verSz; + XMEMCPY(recip->recip + idx, kekIdSeq, kekIdSeqSz); + idx += kekIdSeqSz; + XMEMCPY(recip->recip + idx, kekIdOctetStr, kekIdOctetStrSz); + idx += kekIdOctetStrSz; + XMEMCPY(recip->recip + idx, keyId, keyIdSz); + idx += keyIdSz; + if (timePtr != NULL) { + XMEMCPY(recip->recip + idx, genTime, timeSz); + idx += timeSz; + } + if (other != NULL && otherSz > 0) { + XMEMCPY(recip->recip + idx, otherAttSeq, otherAttSeqSz); + idx += otherAttSeqSz; + XMEMCPY(recip->recip + idx, otherOID, otherOIDSz); + idx += otherOIDSz; + XMEMCPY(recip->recip + idx, other, otherSz); + idx += otherSz; + } + XMEMCPY(recip->recip + idx, encAlgoId, encAlgoIdSz); + idx += encAlgoIdSz; + XMEMCPY(recip->recip + idx, encKeyOctetStr, encKeyOctetStrSz); + idx += encKeyOctetStrSz; + XMEMCPY(recip->recip + idx, encryptedKey, encryptedKeySz); + idx += encryptedKeySz; + +#ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); +#endif + + /* store recipient size */ + recip->recipSz = idx; + recip->recipType = PKCS7_KEKRI; + + /* add recipient to recip list */ + if (pkcs7->recipList == NULL) { + pkcs7->recipList = recip; + } else { + lastRecip = pkcs7->recipList; + while(lastRecip->next != NULL) { + lastRecip = lastRecip->next; + } + lastRecip->next = recip; + } + + (void)options; + + return idx; +} + + +static int wc_PKCS7_GetCMSVersion(PKCS7* pkcs7, int cmsContentType) +{ + int version = -1; + + if (pkcs7 == NULL) + return BAD_FUNC_ARG; + + switch (cmsContentType) { + case ENVELOPED_DATA: + + /* NOTE: EnvelopedData does not currently support + originatorInfo or unprotectedAttributes. When either of these + are added, version checking below needs to be updated to match + Section 6.1 of RFC 5652 */ + + /* if RecipientInfos include pwri or ori, version is 3 */ + if (wc_PKCS7_RecipientListIncludesType(pkcs7, PKCS7_PWRI) || + wc_PKCS7_RecipientListIncludesType(pkcs7, PKCS7_ORI)) { + version = 3; + break; + } + + /* if unprotectedAttrs is absent AND all RecipientInfo structs + are version 0, version is 0 */ + if (wc_PKCS7_RecipientListVersionsAllZero(pkcs7)) { + version = 0; + break; + } + + /* otherwise, version is 2 */ + version = 2; + break; + + default: + break; + } + + return version; +} + + +/* build PKCS#7 envelopedData content type, return enveloped size */ +int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, byte* output, word32 outputSz) +{ + int ret, idx = 0; + int totalSz, padSz, encryptedOutSz; + + int contentInfoSeqSz = 0, outerContentTypeSz = 0, outerContentSz; + byte contentInfoSeq[MAX_SEQ_SZ]; + byte outerContentType[MAX_ALGO_SZ]; + byte outerContent[MAX_SEQ_SZ]; + + int kariVersion; + int envDataSeqSz, verSz; + byte envDataSeq[MAX_SEQ_SZ]; + byte ver[MAX_VERSION_SZ]; + + WC_RNG rng; + int blockSz, blockKeySz; + byte* plain; + byte* encryptedContent; + + Pkcs7EncodedRecip* tmpRecip = NULL; + int recipSz, recipSetSz; + byte recipSet[MAX_SET_SZ]; + + int encContentOctetSz, encContentSeqSz, contentTypeSz; + int contentEncAlgoSz, ivOctetStringSz; + byte encContentSeq[MAX_SEQ_SZ]; + byte contentType[MAX_ALGO_SZ]; + byte contentEncAlgo[MAX_ALGO_SZ]; + byte tmpIv[MAX_CONTENT_IV_SIZE]; + byte ivOctetString[MAX_OCTET_STR_SZ]; + byte encContentOctet[MAX_OCTET_STR_SZ]; + + if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0) + return BAD_FUNC_ARG; + + if (output == NULL || outputSz == 0) + return BAD_FUNC_ARG; + + blockKeySz = wc_PKCS7_GetOIDKeySize(pkcs7->encryptOID); + if (blockKeySz < 0) + return blockKeySz; + + blockSz = wc_PKCS7_GetOIDBlockSize(pkcs7->encryptOID); + if (blockSz < 0) + return blockSz; + + if (pkcs7->contentOID != FIRMWARE_PKG_DATA) { + /* outer content type */ + ret = wc_SetContentType(ENVELOPED_DATA, outerContentType, + sizeof(outerContentType)); + if (ret < 0) + return ret; + + outerContentTypeSz = ret; + } + + /* generate random content encryption key */ + ret = PKCS7_GenerateContentEncryptionKey(pkcs7, blockKeySz); + if (ret != 0) { + return ret; + } + + /* build RecipientInfo, only if user manually set singleCert and size */ + if (pkcs7->singleCert != NULL && pkcs7->singleCertSz > 0) { + switch (pkcs7->publicKeyOID) { + #ifndef NO_RSA + case RSAk: + ret = wc_PKCS7_AddRecipient_KTRI(pkcs7, pkcs7->singleCert, + pkcs7->singleCertSz, 0); + break; + #endif + #ifdef HAVE_ECC + case ECDSAk: + ret = wc_PKCS7_AddRecipient_KARI(pkcs7, pkcs7->singleCert, + pkcs7->singleCertSz, + pkcs7->keyWrapOID, + pkcs7->keyAgreeOID, pkcs7->ukm, + pkcs7->ukmSz, 0); + break; + #endif + + default: + WOLFSSL_MSG("Unsupported RecipientInfo public key type"); + return BAD_FUNC_ARG; + }; + + if (ret < 0) { + WOLFSSL_MSG("Failed to create RecipientInfo"); + return ret; + } + } + + recipSz = wc_PKCS7_GetRecipientListSize(pkcs7); + if (recipSz < 0) { + return ret; + + } else if (recipSz == 0) { + WOLFSSL_MSG("You must add at least one CMS recipient"); + return PKCS7_RECIP_E; + } + recipSetSz = SetSet(recipSz, recipSet); + + /* version, defined in Section 6.1 of RFC 5652 */ + kariVersion = wc_PKCS7_GetCMSVersion(pkcs7, ENVELOPED_DATA); + if (kariVersion < 0) { + WOLFSSL_MSG("Failed to set CMS EnvelopedData version"); + return PKCS7_RECIP_E; + } + + verSz = SetMyVersion(kariVersion, ver, 0); + + ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId); + if (ret != 0) + return ret; + + /* generate IV for block cipher */ + ret = wc_PKCS7_GenerateBlock(pkcs7, &rng, tmpIv, blockSz); + wc_FreeRng(&rng); + if (ret != 0) + return ret; + + /* EncryptedContentInfo */ + ret = wc_SetContentType(pkcs7->contentOID, contentType, + sizeof(contentType)); + if (ret < 0) + return ret; + + contentTypeSz = ret; + + /* allocate encrypted content buffer and PKCS#7 padding */ + padSz = wc_PKCS7_GetPadSize(pkcs7->contentSz, blockSz); + if (padSz < 0) + return padSz; + + encryptedOutSz = pkcs7->contentSz + padSz; + + plain = (byte*)XMALLOC(encryptedOutSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (plain == NULL) + return MEMORY_E; + + ret = wc_PKCS7_PadData(pkcs7->content, pkcs7->contentSz, plain, + encryptedOutSz, blockSz); + if (ret < 0) { + XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + encryptedContent = (byte*)XMALLOC(encryptedOutSz, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (encryptedContent == NULL) { + XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } + + /* put together IV OCTET STRING */ + ivOctetStringSz = SetOctetString(blockSz, ivOctetString); + + /* build up our ContentEncryptionAlgorithmIdentifier sequence, + * adding (ivOctetStringSz + blockSz) for IV OCTET STRING */ + contentEncAlgoSz = SetAlgoID(pkcs7->encryptOID, contentEncAlgo, + oidBlkType, ivOctetStringSz + blockSz); + + if (contentEncAlgoSz == 0) { + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return BAD_FUNC_ARG; + } + + /* encrypt content */ + ret = wc_PKCS7_EncryptContent(pkcs7->encryptOID, pkcs7->cek, + pkcs7->cekSz, tmpIv, blockSz, NULL, 0, NULL, 0, plain, + encryptedOutSz, encryptedContent); + + if (ret != 0) { + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + encContentOctetSz = SetImplicit(ASN_OCTET_STRING, 0, encryptedOutSz, + encContentOctet); + + encContentSeqSz = SetSequence(contentTypeSz + contentEncAlgoSz + + ivOctetStringSz + blockSz + + encContentOctetSz + encryptedOutSz, + encContentSeq); + + /* keep track of sizes for outer wrapper layering */ + totalSz = verSz + recipSetSz + recipSz + encContentSeqSz + contentTypeSz + + contentEncAlgoSz + ivOctetStringSz + blockSz + + encContentOctetSz + encryptedOutSz; + + /* EnvelopedData */ + envDataSeqSz = SetSequence(totalSz, envDataSeq); + totalSz += envDataSeqSz; + + /* outer content */ + outerContentSz = SetExplicit(0, totalSz, outerContent); + totalSz += outerContentTypeSz; + totalSz += outerContentSz; + + if (pkcs7->contentOID != FIRMWARE_PKG_DATA) { + /* ContentInfo */ + contentInfoSeqSz = SetSequence(totalSz, contentInfoSeq); + totalSz += contentInfoSeqSz; + } + + if (totalSz > (int)outputSz) { + WOLFSSL_MSG("Pkcs7_encrypt output buffer too small"); + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + return BUFFER_E; + } + + if (pkcs7->contentOID != FIRMWARE_PKG_DATA) { + XMEMCPY(output + idx, contentInfoSeq, contentInfoSeqSz); + idx += contentInfoSeqSz; + XMEMCPY(output + idx, outerContentType, outerContentTypeSz); + idx += outerContentTypeSz; + XMEMCPY(output + idx, outerContent, outerContentSz); + idx += outerContentSz; + } + XMEMCPY(output + idx, envDataSeq, envDataSeqSz); + idx += envDataSeqSz; + XMEMCPY(output + idx, ver, verSz); + idx += verSz; + XMEMCPY(output + idx, recipSet, recipSetSz); + idx += recipSetSz; + /* copy in recipients from list */ + tmpRecip = pkcs7->recipList; + while (tmpRecip != NULL) { + XMEMCPY(output + idx, tmpRecip->recip, tmpRecip->recipSz); + idx += tmpRecip->recipSz; + tmpRecip = tmpRecip->next; + } + wc_PKCS7_FreeEncodedRecipientSet(pkcs7); + XMEMCPY(output + idx, encContentSeq, encContentSeqSz); + idx += encContentSeqSz; + XMEMCPY(output + idx, contentType, contentTypeSz); + idx += contentTypeSz; + XMEMCPY(output + idx, contentEncAlgo, contentEncAlgoSz); + idx += contentEncAlgoSz; + XMEMCPY(output + idx, ivOctetString, ivOctetStringSz); + idx += ivOctetStringSz; + XMEMCPY(output + idx, tmpIv, blockSz); + idx += blockSz; + XMEMCPY(output + idx, encContentOctet, encContentOctetSz); + idx += encContentOctetSz; + XMEMCPY(output + idx, encryptedContent, encryptedOutSz); + idx += encryptedOutSz; + + XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + + return idx; +} + +#ifndef NO_RSA +/* decode KeyTransRecipientInfo (ktri), return 0 on success, <0 on error */ +static int wc_PKCS7_DecryptKtri(PKCS7* pkcs7, byte* in, word32 inSz, + word32* idx, byte* decryptedKey, + word32* decryptedKeySz, int* recipFound) +{ + int length, encryptedKeySz = 0, ret = 0; + int keySz, version, sidType = 0; + word32 encOID; + word32 keyIdx; + byte issuerHash[KEYID_SIZE]; + byte* outKey = NULL; + byte* pkiMsg = in; + word32 pkiMsgSz = inSz; + +#ifndef NO_PKCS7_STREAM + word32 tmpIdx = *idx; + long rc; +#endif +#ifdef WC_RSA_BLINDING + WC_RNG rng; +#endif + +#ifdef WOLFSSL_SMALL_STACK + mp_int* serialNum = NULL; + byte* encryptedKey = NULL; + RsaKey* privKey = NULL; +#else + mp_int serialNum[1]; + byte encryptedKey[MAX_ENCRYPTED_KEY_SZ]; + RsaKey privKey[1]; +#endif + + switch (pkcs7->state) { + case WC_PKCS7_DECRYPT_KTRI: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_VERSION_SZ, + &pkiMsg, idx)) != 0) { + return ret; + } + + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, + in, inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + + #endif + if (GetMyVersion(pkiMsg, idx, &version, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (version == 0) { + sidType = CMS_ISSUER_AND_SERIAL_NUMBER; + } else if (version == 2) { + sidType = CMS_SKID; + } else { + return ASN_VERSION_E; + } + + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { + break; + } + wc_PKCS7_StreamStoreVar(pkcs7, 0, sidType, version); + + /* @TODO getting total amount left because of GetInt call later on + * this could be optimized to stream better */ + pkcs7->stream->expected = (pkcs7->stream->maxLen - + pkcs7->stream->totalRd) + pkcs7->stream->length; + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_DECRYPT_KTRI_2); + FALL_THROUGH; + + case WC_PKCS7_DECRYPT_KTRI_2: + #ifndef NO_PKCS7_STREAM + + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, pkcs7->stream->expected, + &pkiMsg, idx)) != 0) { + return ret; + } + + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, + in, inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + + wc_PKCS7_StreamGetVar(pkcs7, NULL, &sidType, &version); + + /* @TODO get expected size for next part, does not account for + * GetInt call well */ + if (pkcs7->stream->expected == MAX_SEQ_SZ) { + int sz; + word32 lidx; + + if (sidType == CMS_ISSUER_AND_SERIAL_NUMBER) { + lidx = *idx; + ret = GetSequence(pkiMsg, &lidx, &sz, pkiMsgSz); + if (ret < 0) + return ret; + } + else { + lidx = *idx + ASN_TAG_SZ; + ret = GetLength(pkiMsg, &lidx, &sz, pkiMsgSz); + if (ret < 0) + return ret; + } + + pkcs7->stream->expected = sz + MAX_ALGO_SZ + ASN_TAG_SZ + + MAX_LENGTH_SZ; + if (pkcs7->stream->length > 0 && + pkcs7->stream->length < pkcs7->stream->expected) { + return WC_PKCS7_WANT_READ_E; + } + } + #endif /* !NO_PKCS7_STREAM */ + + if (sidType == CMS_ISSUER_AND_SERIAL_NUMBER) { + + /* remove IssuerAndSerialNumber */ + if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (GetNameHash(pkiMsg, idx, issuerHash, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* if we found correct recipient, issuer hashes will match */ + if (XMEMCMP(issuerHash, pkcs7->issuerHash, KEYID_SIZE) == 0) { + *recipFound = 1; + } + + #ifdef WOLFSSL_SMALL_STACK + serialNum = (mp_int*)XMALLOC(sizeof(mp_int), pkcs7->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (serialNum == NULL) + return MEMORY_E; + #endif + + if (GetInt(serialNum, pkiMsg, idx, pkiMsgSz) < 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(serialNum, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ASN_PARSE_E; + } + + mp_clear(serialNum); + + #ifdef WOLFSSL_SMALL_STACK + XFREE(serialNum, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + } else { + + /* remove SubjectKeyIdentifier */ + if (pkiMsg[(*idx)++] != + (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) + return ASN_PARSE_E; + + if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (pkiMsg[(*idx)++] != ASN_OCTET_STRING) + return ASN_PARSE_E; + + if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* if we found correct recipient, SKID will match */ + if (XMEMCMP(pkiMsg + (*idx), pkcs7->issuerSubjKeyId, + KEYID_SIZE) == 0) { + *recipFound = 1; + } + (*idx) += KEYID_SIZE; + } + + if (GetAlgoId(pkiMsg, idx, &encOID, oidKeyType, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* key encryption algorithm must be RSA for now */ + if (encOID != RSAk) + return ALGO_ID_E; + + /* read encryptedKey */ + if (pkiMsg[(*idx)++] != ASN_OCTET_STRING) { + return ASN_PARSE_E; + } + + if (GetLength(pkiMsg, idx, &encryptedKeySz, pkiMsgSz) < 0) { + return ASN_PARSE_E; + } + if (encryptedKeySz > MAX_ENCRYPTED_KEY_SZ) { + return BUFFER_E; + } + + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { + break; + } + wc_PKCS7_StreamStoreVar(pkcs7, encryptedKeySz, sidType, version); + pkcs7->stream->expected = encryptedKeySz; + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_DECRYPT_KTRI_3); + FALL_THROUGH; + + case WC_PKCS7_DECRYPT_KTRI_3: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, + pkcs7->stream->expected, &pkiMsg, idx)) != 0) { + return ret; + } + encryptedKeySz = pkcs7->stream->expected; + #endif + + #ifdef WOLFSSL_SMALL_STACK + encryptedKey = (byte*)XMALLOC(encryptedKeySz, pkcs7->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (encryptedKey == NULL) + return MEMORY_E; + #endif + + if (*recipFound == 1) + XMEMCPY(encryptedKey, &pkiMsg[*idx], encryptedKeySz); + *idx += encryptedKeySz; + + /* load private key */ + #ifdef WOLFSSL_SMALL_STACK + privKey = (RsaKey*)XMALLOC(sizeof(RsaKey), pkcs7->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (privKey == NULL) { + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } + #endif + + ret = wc_InitRsaKey_ex(privKey, pkcs7->heap, INVALID_DEVID); + if (ret != 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ret; + } + + if (pkcs7->privateKey != NULL && pkcs7->privateKeySz > 0) { + keyIdx = 0; + ret = wc_RsaPrivateKeyDecode(pkcs7->privateKey, &keyIdx, + privKey, pkcs7->privateKeySz); + } + else if (pkcs7->devId == INVALID_DEVID) { + ret = BAD_FUNC_ARG; + } + if (ret != 0) { + WOLFSSL_MSG("Failed to decode RSA private key"); + wc_FreeRsaKey(privKey); + #ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return ret; + } + + /* decrypt encryptedKey */ + #ifdef WC_RSA_BLINDING + ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId); + if (ret == 0) { + ret = wc_RsaSetRNG(privKey, &rng); + } + #endif + if (ret == 0) { + keySz = wc_RsaPrivateDecryptInline(encryptedKey, encryptedKeySz, + &outKey, privKey); + #ifdef WC_RSA_BLINDING + wc_FreeRng(&rng); + #endif + } else { + keySz = ret; + } + wc_FreeRsaKey(privKey); + + if (keySz <= 0 || outKey == NULL) { + ForceZero(encryptedKey, encryptedKeySz); + #ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return keySz; + } else { + *decryptedKeySz = keySz; + XMEMCPY(decryptedKey, outKey, keySz); + ForceZero(encryptedKey, encryptedKeySz); + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(privKey, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + #endif + + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { + break; + } + #endif + ret = 0; /* success */ + break; + + default: + WOLFSSL_MSG("PKCS7 Unknown KTRI decrypt state"); + ret = BAD_FUNC_ARG; + } + + return ret; +} +#endif /* !NO_RSA */ + +#ifdef HAVE_ECC + +/* remove ASN.1 OriginatorIdentifierOrKey, return 0 on success, <0 on error */ +static int wc_PKCS7_KariGetOriginatorIdentifierOrKey(WC_PKCS7_KARI* kari, + byte* pkiMsg, word32 pkiMsgSz, word32* idx) +{ + int ret, length; + word32 keyOID; + + if (kari == NULL || pkiMsg == NULL || idx == NULL) + return BAD_FUNC_ARG; + + /* remove OriginatorIdentifierOrKey */ + if (pkiMsg[*idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) { + (*idx)++; + if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + } else { + return ASN_PARSE_E; + } + + /* remove OriginatorPublicKey */ + if (pkiMsg[*idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) { + (*idx)++; + if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + } else { + return ASN_PARSE_E; + } + + /* remove AlgorithmIdentifier */ + if (GetAlgoId(pkiMsg, idx, &keyOID, oidKeyType, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (keyOID != ECDSAk) + return ASN_PARSE_E; + + /* remove ECPoint BIT STRING */ + if ((pkiMsgSz > (*idx + 1)) && (pkiMsg[(*idx)++] != ASN_BIT_STRING)) + return ASN_PARSE_E; + + if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if ((pkiMsgSz < (*idx + 1)) || (pkiMsg[(*idx)++] != 0x00)) + return ASN_EXPECT_0_E; + + /* get sender ephemeral public ECDSA key */ + ret = wc_ecc_init_ex(kari->senderKey, kari->heap, kari->devId); + if (ret != 0) + return ret; + + kari->senderKeyInit = 1; + + /* length-1 for unused bits counter */ + ret = wc_ecc_import_x963(pkiMsg + (*idx), length - 1, kari->senderKey); + if (ret != 0) { + ret = wc_EccPublicKeyDecode(pkiMsg, idx, kari->senderKey, *idx + length - 1); + if (ret != 0) + return ret; + } + else { + (*idx) += length - 1; + } + + return 0; +} + + +/* remove optional UserKeyingMaterial if available, return 0 on success, + * < 0 on error */ +static int wc_PKCS7_KariGetUserKeyingMaterial(WC_PKCS7_KARI* kari, + byte* pkiMsg, word32 pkiMsgSz, word32* idx) +{ + int length; + word32 savedIdx; + + if (kari == NULL || pkiMsg == NULL || idx == NULL) + return BAD_FUNC_ARG; + + savedIdx = *idx; + + /* starts with EXPLICIT [1] */ + if (pkiMsg[(*idx)++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) { + *idx = savedIdx; + return 0; + } + + if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) { + *idx = savedIdx; + return 0; + } + + /* get OCTET STRING */ + if ( (pkiMsgSz > ((*idx) + 1)) && + (pkiMsg[(*idx)++] != ASN_OCTET_STRING) ) { + *idx = savedIdx; + return 0; + } + + if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) { + *idx = savedIdx; + return 0; + } + + kari->ukm = NULL; + if (length > 0) { + kari->ukm = (byte*)XMALLOC(length, kari->heap, DYNAMIC_TYPE_PKCS7); + if (kari->ukm == NULL) + return MEMORY_E; + + XMEMCPY(kari->ukm, pkiMsg + (*idx), length); + kari->ukmOwner = 1; + } + + (*idx) += length; + kari->ukmSz = length; + + return 0; +} + + +/* remove ASN.1 KeyEncryptionAlgorithmIdentifier, return 0 on success, + * < 0 on error */ +static int wc_PKCS7_KariGetKeyEncryptionAlgorithmId(WC_PKCS7_KARI* kari, + byte* pkiMsg, word32 pkiMsgSz, word32* idx, + word32* keyAgreeOID, word32* keyWrapOID) +{ + int length = 0; + word32 localIdx = *idx; + + if (kari == NULL || pkiMsg == NULL || idx == NULL || + keyAgreeOID == NULL || keyWrapOID == NULL) + return BAD_FUNC_ARG; + + /* remove KeyEncryptionAlgorithmIdentifier */ + if (GetSequence(pkiMsg, &localIdx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + localIdx = *idx; + if (GetAlgoId(pkiMsg, &localIdx, keyAgreeOID, oidCmsKeyAgreeType, + pkiMsgSz) < 0) { + return ASN_PARSE_E; + } + + if (localIdx < *idx + length) { + *idx = localIdx; + } + /* remove KeyWrapAlgorithm, stored in parameter of KeyEncAlgoId */ + if (GetAlgoId(pkiMsg, idx, keyWrapOID, oidKeyWrapType, pkiMsgSz) < 0) + return ASN_PARSE_E; + + return 0; +} + + +/* remove ASN.1 SubjectKeyIdentifier, return 0 on success, < 0 on error + * if subject key ID matches, recipFound is set to 1 */ +static int wc_PKCS7_KariGetSubjectKeyIdentifier(WC_PKCS7_KARI* kari, + byte* pkiMsg, word32 pkiMsgSz, word32* idx, + int* recipFound, byte* rid) +{ + int length; + + if (kari == NULL || pkiMsg == NULL || idx == NULL || recipFound == NULL || + rid == NULL) + return BAD_FUNC_ARG; + + /* remove RecipientKeyIdentifier IMPLICIT [0] */ + if ( (pkiMsgSz > (*idx + 1)) && + (pkiMsg[(*idx)++] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) ) { + + if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + } else { + return ASN_PARSE_E; + } + + /* remove SubjectKeyIdentifier */ + if ( (pkiMsgSz > (*idx + 1)) && + (pkiMsg[(*idx)++] != ASN_OCTET_STRING) ) + return ASN_PARSE_E; + + if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (length != KEYID_SIZE) + return ASN_PARSE_E; + + XMEMCPY(rid, pkiMsg + (*idx), KEYID_SIZE); + (*idx) += length; + + /* subject key id should match if recipient found */ + if (XMEMCMP(rid, kari->decoded->extSubjKeyId, KEYID_SIZE) == 0) { + *recipFound = 1; + } + + return 0; +} + + +/* remove ASN.1 IssuerAndSerialNumber, return 0 on success, < 0 on error + * if issuer and serial number match, recipFound is set to 1 */ +static int wc_PKCS7_KariGetIssuerAndSerialNumber(WC_PKCS7_KARI* kari, + byte* pkiMsg, word32 pkiMsgSz, word32* idx, + int* recipFound, byte* rid) +{ + int length, ret; +#ifdef WOLFSSL_SMALL_STACK + mp_int* serial; + mp_int* recipSerial; +#else + mp_int serial[1]; + mp_int recipSerial[1]; +#endif + + if (rid == NULL) { + return BAD_FUNC_ARG; + } + + /* remove IssuerAndSerialNumber */ + if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (GetNameHash(pkiMsg, idx, rid, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* if we found correct recipient, issuer hashes will match */ + if (XMEMCMP(rid, kari->decoded->issuerHash, KEYID_SIZE) == 0) { + *recipFound = 1; + } + +#ifdef WOLFSSL_SMALL_STACK + serial = (mp_int*)XMALLOC(sizeof(mp_int), kari->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (serial == NULL) + return MEMORY_E; + + recipSerial = (mp_int*)XMALLOC(sizeof(mp_int), kari->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (recipSerial == NULL) { + XFREE(serial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#endif + + if (GetInt(serial, pkiMsg, idx, pkiMsgSz) < 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(serial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(recipSerial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ASN_PARSE_E; + } + + ret = mp_read_unsigned_bin(recipSerial, kari->decoded->serial, + kari->decoded->serialSz); + if (ret != MP_OKAY) { + mp_clear(serial); + WOLFSSL_MSG("Failed to parse CMS recipient serial number"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(serial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(recipSerial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + if (mp_cmp(recipSerial, serial) != MP_EQ) { + mp_clear(serial); + mp_clear(recipSerial); + WOLFSSL_MSG("CMS serial number does not match recipient"); +#ifdef WOLFSSL_SMALL_STACK + XFREE(serial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(recipSerial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return PKCS7_RECIP_E; + } + + mp_clear(serial); + mp_clear(recipSerial); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(serial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(recipSerial, kari->heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return 0; +} + + +/* remove ASN.1 RecipientEncryptedKeys, return 0 on success, < 0 on error */ +static int wc_PKCS7_KariGetRecipientEncryptedKeys(WC_PKCS7_KARI* kari, + byte* pkiMsg, word32 pkiMsgSz, word32* idx, + int* recipFound, byte* encryptedKey, + int* encryptedKeySz, byte* rid) +{ + int length; + int ret = 0; + + if (kari == NULL || pkiMsg == NULL || idx == NULL || + recipFound == NULL || encryptedKey == NULL) + return BAD_FUNC_ARG; + + /* remove RecipientEncryptedKeys */ + if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* remove RecipientEncryptedKeys */ + if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* KeyAgreeRecipientIdentifier is CHOICE of IssuerAndSerialNumber + * or [0] IMMPLICIT RecipientKeyIdentifier */ + if ( (pkiMsgSz > (*idx + 1)) && + (pkiMsg[*idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) ) { + + /* try to get RecipientKeyIdentifier */ + ret = wc_PKCS7_KariGetSubjectKeyIdentifier(kari, pkiMsg, pkiMsgSz, + idx, recipFound, rid); + } else { + /* try to get IssuerAndSerialNumber */ + ret = wc_PKCS7_KariGetIssuerAndSerialNumber(kari, pkiMsg, pkiMsgSz, + idx, recipFound, rid); + } + + /* if we don't have either option, malformed CMS */ + if (ret != 0) + return ret; + + /* remove EncryptedKey */ + if ( (pkiMsgSz > (*idx + 1)) && + (pkiMsg[(*idx)++] != ASN_OCTET_STRING) ) + return ASN_PARSE_E; + + if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* put encrypted CEK in decryptedKey buffer for now, decrypt later */ + if (length > *encryptedKeySz) + return BUFFER_E; + + XMEMCPY(encryptedKey, pkiMsg + (*idx), length); + *encryptedKeySz = length; + (*idx) += length; + + return 0; +} + +#endif /* HAVE_ECC */ + + +int wc_PKCS7_SetOriEncryptCtx(PKCS7* pkcs7, void* ctx) +{ + if (pkcs7 == NULL) + return BAD_FUNC_ARG; + + pkcs7->oriEncryptCtx = ctx; + + return 0; +} + + +int wc_PKCS7_SetOriDecryptCtx(PKCS7* pkcs7, void* ctx) +{ + + if (pkcs7 == NULL) + return BAD_FUNC_ARG; + + pkcs7->oriDecryptCtx = ctx; + + return 0; +} + + +int wc_PKCS7_SetOriDecryptCb(PKCS7* pkcs7, CallbackOriDecrypt cb) +{ + if (pkcs7 == NULL) + return BAD_FUNC_ARG; + + pkcs7->oriDecryptCb = cb; + + return 0; +} + + +/* return 0 on success */ +int wc_PKCS7_SetWrapCEKCb(PKCS7* pkcs7, CallbackWrapCEK cb) +{ + if (pkcs7 == NULL) + return BAD_FUNC_ARG; + + pkcs7->wrapCEKCb = cb; + + return 0; +} + +/* Decrypt ASN.1 OtherRecipientInfo (ori), as defined by: + * + * OtherRecipientInfo ::= SEQUENCE { + * oriType OBJECT IDENTIFIER, + * oriValue ANY DEFINED BY oriType } + * + * pkcs7 - pointer to initialized PKCS7 structure + * pkiMsg - pointer to encoded CMS bundle + * pkiMsgSz - size of pkiMsg, bytes + * idx - [IN/OUT] pointer to index into pkiMsg + * decryptedKey - [OUT] output buf for decrypted content encryption key + * decryptedKeySz - [IN/OUT] size of buffer, size of decrypted key + * recipFound - [OUT] 1 if recipient has been found, 0 if not + * + * Return 0 on success, negative upon error. + */ +static int wc_PKCS7_DecryptOri(PKCS7* pkcs7, byte* in, word32 inSz, + word32* idx, byte* decryptedKey, + word32* decryptedKeySz, int* recipFound) +{ + int ret, seqSz, oriOIDSz; + word32 oriValueSz, tmpIdx; + byte* oriValue; + byte oriOID[MAX_OID_SZ]; + + byte* pkiMsg = in; + word32 pkiMsgSz = inSz; +#ifndef NO_PKCS7_STREAM + word32 stateIdx = *idx; + long rc; +#endif + + if (pkcs7->oriDecryptCb == NULL) { + WOLFSSL_MSG("You must register an ORI Decrypt callback"); + return BAD_FUNC_ARG; + } + + switch (pkcs7->state) { + + case WC_PKCS7_DECRYPT_ORI: + #ifndef NO_PKCS7_STREAM + /* @TODO for now just get full buffer, needs divided up */ + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, + (pkcs7->stream->maxLen - pkcs7->stream->totalRd) + + pkcs7->stream->length, &pkiMsg, idx)) != 0) { + return ret; + } + + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, + inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + #endif + /* get OtherRecipientInfo sequence length */ + if (GetLength(pkiMsg, idx, &seqSz, pkiMsgSz) < 0) + return ASN_PARSE_E; + + tmpIdx = *idx; + + /* remove and store oriType OBJECT IDENTIFIER */ + if (GetASNObjectId(pkiMsg, idx, &oriOIDSz, pkiMsgSz) != 0) + return ASN_PARSE_E; + + XMEMCPY(oriOID, pkiMsg + *idx, oriOIDSz); + *idx += oriOIDSz; + + /* get oriValue, increment idx */ + oriValue = pkiMsg + *idx; + oriValueSz = seqSz - (*idx - tmpIdx); + *idx += oriValueSz; + + /* pass oriOID and oriValue to user callback, expect back + decryptedKey and size */ + ret = pkcs7->oriDecryptCb(pkcs7, oriOID, (word32)oriOIDSz, oriValue, + oriValueSz, decryptedKey, decryptedKeySz, + pkcs7->oriDecryptCtx); + + if (ret != 0 || decryptedKey == NULL || *decryptedKeySz == 0) { + /* decrypt operation failed */ + *recipFound = 0; + return PKCS7_RECIP_E; + } + + /* mark recipFound, since we only support one RecipientInfo for now */ + *recipFound = 1; + + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &stateIdx, idx)) != 0) { + break; + } + #endif + ret = 0; /* success */ + break; + + default: + WOLFSSL_MSG("PKCS7 ORI unknown state"); + ret = BAD_FUNC_ARG; + + } + + return ret; +} + +#if !defined(NO_PWDBASED) && !defined(NO_SHA) + +/* decode ASN.1 PasswordRecipientInfo (pwri), return 0 on success, + * < 0 on error */ +static int wc_PKCS7_DecryptPwri(PKCS7* pkcs7, byte* in, word32 inSz, + word32* idx, byte* decryptedKey, + word32* decryptedKeySz, int* recipFound) +{ + byte* salt; + byte* cek; + byte* kek; + + byte tmpIv[MAX_CONTENT_IV_SIZE]; + + int ret = 0, length, saltSz, iterations, blockSz, kekKeySz; + int hashOID = WC_SHA; /* default to SHA1 */ + word32 kdfAlgoId, pwriEncAlgoId, keyEncAlgoId, cekSz; + byte* pkiMsg = in; + word32 pkiMsgSz = inSz; +#ifndef NO_PKCS7_STREAM + word32 tmpIdx = *idx; + long rc; +#endif + + switch (pkcs7->state) { + case WC_PKCS7_DECRYPT_PWRI: + #ifndef NO_PKCS7_STREAM + /*@TODO for now just get full buffer, needs divided up */ + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, + (pkcs7->stream->maxLen - pkcs7->stream->totalRd) + + pkcs7->stream->length, &pkiMsg, idx)) != 0) { + return ret; + } + + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, + inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + #endif + /* remove KeyDerivationAlgorithmIdentifier */ + if (pkiMsg[(*idx)++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) + return ASN_PARSE_E; + + if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* get KeyDerivationAlgorithmIdentifier */ + if (wc_GetContentType(pkiMsg, idx, &kdfAlgoId, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* get KDF params SEQ */ + if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* get KDF salt OCTET STRING */ + if ( (pkiMsgSz > ((*idx) + 1)) && + (pkiMsg[(*idx)++] != ASN_OCTET_STRING) ) { + return ASN_PARSE_E; + } + + if (GetLength(pkiMsg, idx, &saltSz, pkiMsgSz) < 0) + return ASN_PARSE_E; + + salt = (byte*)XMALLOC(saltSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (salt == NULL) + return MEMORY_E; + + XMEMCPY(salt, pkiMsg + (*idx), saltSz); + *idx += saltSz; + + /* get KDF iterations */ + if (GetMyVersion(pkiMsg, idx, &iterations, pkiMsgSz) < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + /* get KeyEncAlgoId SEQ */ + if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + /* get KeyEncAlgoId */ + if (wc_GetContentType(pkiMsg, idx, &keyEncAlgoId, pkiMsgSz) < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + /* get pwriEncAlgoId */ + if (GetAlgoId(pkiMsg, idx, &pwriEncAlgoId, oidBlkType, pkiMsgSz) < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + blockSz = wc_PKCS7_GetOIDBlockSize(pwriEncAlgoId); + if (blockSz < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return blockSz; + } + + /* get content-encryption key size, based on algorithm */ + kekKeySz = wc_PKCS7_GetOIDKeySize(pwriEncAlgoId); + if (kekKeySz < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return kekKeySz; + } + + /* get block cipher IV, stored in OPTIONAL parameter of AlgoID */ + if ( (pkiMsgSz > ((*idx) + 1)) && + (pkiMsg[(*idx)++] != ASN_OCTET_STRING) ) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + if (length != blockSz) { + WOLFSSL_MSG("Incorrect IV length, must be of content alg block size"); + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + XMEMCPY(tmpIv, pkiMsg + (*idx), length); + *idx += length; + + /* get EncryptedKey */ + if ( (pkiMsgSz < ((*idx) + 1)) || + (pkiMsg[(*idx)++] != ASN_OCTET_STRING) ) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + /* allocate temporary space for decrypted key */ + cekSz = length; + cek = (byte*)XMALLOC(cekSz, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (cek == NULL) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } + + /* generate KEK */ + kek = (byte*)XMALLOC(kekKeySz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (kek == NULL) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } + + ret = wc_PKCS7_GenerateKEK_PWRI(pkcs7, pkcs7->pass, pkcs7->passSz, + salt, saltSz, kdfAlgoId, hashOID, + iterations, kek, kekKeySz); + if (ret < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ASN_PARSE_E; + } + + /* decrypt CEK with KEK */ + ret = wc_PKCS7_PwriKek_KeyUnWrap(pkcs7, kek, kekKeySz, + pkiMsg + (*idx), length, cek, + cekSz, tmpIv, blockSz, + pwriEncAlgoId); + if (ret < 0) { + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + cekSz = ret; + + if (*decryptedKeySz < cekSz) { + WOLFSSL_MSG("Decrypted key buffer too small for CEK"); + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return BUFFER_E; + } + + XMEMCPY(decryptedKey, cek, cekSz); + *decryptedKeySz = cekSz; + + XFREE(salt, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(kek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(cek, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + + /* mark recipFound, since we only support one RecipientInfo for now */ + *recipFound = 1; + *idx += length; + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { + break; + } + #endif + ret = 0; /* success */ + break; + + default: + WOLFSSL_MSG("PKCS7 PWRI unknown state"); + ret = BAD_FUNC_ARG; + } + + return ret; +} + +#endif /* NO_PWDBASED | NO_SHA */ + +/* decode ASN.1 KEKRecipientInfo (kekri), return 0 on success, + * < 0 on error */ +static int wc_PKCS7_DecryptKekri(PKCS7* pkcs7, byte* in, word32 inSz, + word32* idx, byte* decryptedKey, + word32* decryptedKeySz, int* recipFound) +{ + int length, keySz, dateLen, direction; + byte* keyId = NULL; + const byte* datePtr = NULL; + byte dateFormat; + word32 keyIdSz, kekIdSz, keyWrapOID; + + int ret = 0; + byte* pkiMsg = in; + word32 pkiMsgSz = inSz; +#ifndef NO_PKCS7_STREAM + word32 tmpIdx = *idx; + long rc; +#endif + + WOLFSSL_ENTER("wc_PKCS7_DecryptKekri"); + switch (pkcs7->state) { + case WC_PKCS7_DECRYPT_KEKRI: + #ifndef NO_PKCS7_STREAM + /* @TODO for now just get full buffer, needs divided up */ + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, + (pkcs7->stream->maxLen - pkcs7->stream->totalRd) + + pkcs7->stream->length, &pkiMsg, idx)) != 0) { + return ret; + } + + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, + inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + #endif + /* remove KEKIdentifier */ + if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + kekIdSz = length; + + if (pkiMsg[(*idx)++] != ASN_OCTET_STRING) + return ASN_PARSE_E; + + if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* save keyIdentifier and length */ + keyId = pkiMsg + *idx; + keyIdSz = length; + *idx += keyIdSz; + + /* may have OPTIONAL GeneralizedTime */ + if ((*idx < kekIdSz) && (pkiMsg[*idx] == ASN_GENERALIZED_TIME)) { + if (wc_GetDateInfo(pkiMsg + *idx, pkiMsgSz, &datePtr, &dateFormat, + &dateLen) != 0) { + return ASN_PARSE_E; + } + *idx += (dateLen + 1); + } + + /* may have OPTIONAL OtherKeyAttribute */ + if ((*idx < kekIdSz) && (pkiMsg[*idx] == + (ASN_SEQUENCE | ASN_CONSTRUCTED))) { + + if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* skip it */ + *idx += length; + } + + /* get KeyEncryptionAlgorithmIdentifier */ + if (GetAlgoId(pkiMsg, idx, &keyWrapOID, oidKeyWrapType, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* get EncryptedKey */ + if (pkiMsg[(*idx)++] != ASN_OCTET_STRING) + return ASN_PARSE_E; + + if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + #ifndef NO_AES + direction = AES_DECRYPTION; + #else + direction = DES_DECRYPTION; + #endif + + /* decrypt CEK with KEK */ + if (pkcs7->wrapCEKCb) { + keySz = pkcs7->wrapCEKCb(pkcs7, pkiMsg + *idx, length, keyId, + keyIdSz, NULL, 0, decryptedKey, + *decryptedKeySz, keyWrapOID, + (int)PKCS7_KEKRI, direction); + } + else { + keySz = wc_PKCS7_KeyWrap(pkiMsg + *idx, length, pkcs7->privateKey, + pkcs7->privateKeySz, decryptedKey, *decryptedKeySz, + keyWrapOID, direction); + } + if (keySz <= 0) + return keySz; + + *decryptedKeySz = (word32)keySz; + + /* mark recipFound, since we only support one RecipientInfo for now */ + *recipFound = 1; + *idx += length; + + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { + break; + } + #endif + ret = 0; /* success */ + break; + + default: + WOLFSSL_MSG("PKCS7 KEKRI unknown state"); + ret = BAD_FUNC_ARG; + + } + + (void)keyId; + return ret; +} + + +/* decode ASN.1 KeyAgreeRecipientInfo (kari), return 0 on success, + * < 0 on error */ +static int wc_PKCS7_DecryptKari(PKCS7* pkcs7, byte* in, word32 inSz, + word32* idx, byte* decryptedKey, + word32* decryptedKeySz, int* recipFound) +{ +#ifdef HAVE_ECC + int ret, keySz; + int encryptedKeySz; + int direction = 0; + word32 keyAgreeOID, keyWrapOID; + byte rid[KEYID_SIZE]; + +#ifdef WOLFSSL_SMALL_STACK + byte* encryptedKey; +#else + byte encryptedKey[MAX_ENCRYPTED_KEY_SZ]; +#endif + + byte* pkiMsg = in; + word32 pkiMsgSz = inSz; +#ifndef NO_PKCS7_STREAM + word32 tmpIdx = (idx) ? *idx : 0; + long rc; +#endif + + WOLFSSL_ENTER("wc_PKCS7_DecryptKari"); + if (pkcs7 == NULL || pkiMsg == NULL || + ((pkcs7->singleCert == NULL || pkcs7->singleCertSz == 0) && + pkcs7->wrapCEKCb == NULL) || + idx == NULL || decryptedKey == NULL || decryptedKeySz == NULL) { + return BAD_FUNC_ARG; + } + + switch (pkcs7->state) { + case WC_PKCS7_DECRYPT_KARI: { + #ifndef NO_PKCS7_STREAM + /* @TODO for now just get full buffer, needs divided up */ + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, + (pkcs7->stream->maxLen - pkcs7->stream->totalRd) + + pkcs7->stream->length, &pkiMsg, idx)) != 0) { + return ret; + } + + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, + inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + #endif + WC_PKCS7_KARI* kari; + + kari = wc_PKCS7_KariNew(pkcs7, WC_PKCS7_DECODE); + if (kari == NULL) + return MEMORY_E; + + #ifdef WOLFSSL_SMALL_STACK + encryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (encryptedKey == NULL) { + wc_PKCS7_KariFree(kari); + return MEMORY_E; + } + #endif + encryptedKeySz = MAX_ENCRYPTED_KEY_SZ; + + /* parse cert and key */ + if (pkcs7->singleCert != NULL) { + ret = wc_PKCS7_KariParseRecipCert(kari, (byte*)pkcs7->singleCert, + pkcs7->singleCertSz, pkcs7->privateKey, + pkcs7->privateKeySz); + if (ret != 0) { + wc_PKCS7_KariFree(kari); + #ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #endif + return ret; + } + } + + /* remove OriginatorIdentifierOrKey */ + ret = wc_PKCS7_KariGetOriginatorIdentifierOrKey(kari, pkiMsg, + pkiMsgSz, idx); + if (ret != 0) { + wc_PKCS7_KariFree(kari); + #ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #endif + return ret; + } + + /* try and remove optional UserKeyingMaterial */ + ret = wc_PKCS7_KariGetUserKeyingMaterial(kari, pkiMsg, pkiMsgSz, idx); + if (ret != 0) { + wc_PKCS7_KariFree(kari); + #ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #endif + return ret; + } + + /* remove KeyEncryptionAlgorithmIdentifier */ + ret = wc_PKCS7_KariGetKeyEncryptionAlgorithmId(kari, pkiMsg, + pkiMsgSz, idx, &keyAgreeOID, &keyWrapOID); + if (ret != 0) { + wc_PKCS7_KariFree(kari); + #ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #endif + return ret; + } + + /* if user has not explicitly set keyAgreeOID, set from one in bundle */ + if (pkcs7->keyAgreeOID == 0) + pkcs7->keyAgreeOID = keyAgreeOID; + + /* set direction based on key wrap algorithm */ + switch (keyWrapOID) { + #ifndef NO_AES + #ifdef WOLFSSL_AES_128 + case AES128_WRAP: + #endif + #ifdef WOLFSSL_AES_192 + case AES192_WRAP: + #endif + #ifdef WOLFSSL_AES_256 + case AES256_WRAP: + #endif + direction = AES_DECRYPTION; + break; + #endif + default: + wc_PKCS7_KariFree(kari); + #ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #endif + WOLFSSL_MSG("AES key wrap algorithm unsupported"); + return BAD_KEYWRAP_ALG_E; + } + + /* remove RecipientEncryptedKeys */ + ret = wc_PKCS7_KariGetRecipientEncryptedKeys(kari, pkiMsg, pkiMsgSz, + idx, recipFound, encryptedKey, &encryptedKeySz, rid); + if (ret != 0) { + wc_PKCS7_KariFree(kari); + #ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #endif + return ret; + } + + /* decrypt CEK with KEK */ + if (pkcs7->wrapCEKCb) { + word32 tmpKeySz = 0; + byte* tmpKeyDer = NULL; + + ret = wc_ecc_export_x963(kari->senderKey, NULL, &tmpKeySz); + if (ret != LENGTH_ONLY_E) { + return ret; + } + + /* buffer space for algorithm/curve */ + tmpKeySz += MAX_SEQ_SZ; + tmpKeySz += 2 * MAX_ALGO_SZ; + + /* buffer space for public key sequence */ + tmpKeySz += MAX_SEQ_SZ; + tmpKeySz += TRAILING_ZERO; + + tmpKeyDer = (byte*)XMALLOC(tmpKeySz, pkcs7->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (tmpKeyDer == NULL) { + return MEMORY_E; + } + + ret = wc_EccPublicKeyToDer(kari->senderKey, tmpKeyDer, + tmpKeySz, 1); + if (ret < 0) { + XFREE(tmpKeyDer, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + return ret; + } + tmpKeySz = (word32)ret; + + keySz = pkcs7->wrapCEKCb(pkcs7, encryptedKey, encryptedKeySz, + rid, KEYID_SIZE, tmpKeyDer, tmpKeySz, + decryptedKey, *decryptedKeySz, + keyWrapOID, (int)PKCS7_KARI, direction); + XFREE(tmpKeyDer, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + } + else { + /* create KEK */ + ret = wc_PKCS7_KariGenerateKEK(kari, keyWrapOID, pkcs7->keyAgreeOID); + if (ret != 0) { + wc_PKCS7_KariFree(kari); + #ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #endif + return ret; + } + + /* decrypt CEK with KEK */ + keySz = wc_PKCS7_KeyWrap(encryptedKey, encryptedKeySz, kari->kek, + kari->kekSz, decryptedKey, *decryptedKeySz, + keyWrapOID, direction); + } + if (keySz <= 0) { + wc_PKCS7_KariFree(kari); + #ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #endif + return keySz; + } + *decryptedKeySz = (word32)keySz; + + wc_PKCS7_KariFree(kari); + #ifdef WOLFSSL_SMALL_STACK + XFREE(encryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + #endif + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { + break; + } + #endif + ret = 0; /* success */ + } + break; + + default: + WOLFSSL_MSG("PKCS7 kari unknown state"); + ret = BAD_FUNC_ARG; + + } + + (void)pkiMsg; + (void)pkiMsgSz; + + return ret; +#else + (void)in; + (void)inSz; + (void)pkcs7; + (void)idx; + (void)decryptedKey; + (void)decryptedKeySz; + (void)recipFound; + + return NOT_COMPILED_IN; +#endif /* HAVE_ECC */ +} + + +/* decode ASN.1 RecipientInfos SET, return 0 on success, < 0 on error */ +static int wc_PKCS7_DecryptRecipientInfos(PKCS7* pkcs7, byte* in, + word32 inSz, word32* idx, byte* decryptedKey, + word32* decryptedKeySz, int* recipFound) +{ + word32 savedIdx; + int version, ret = 0, length; + byte* pkiMsg = in; + word32 pkiMsgSz = inSz; +#ifndef NO_PKCS7_STREAM + word32 tmpIdx; + long rc; +#endif + + if (pkcs7 == NULL || pkiMsg == NULL || idx == NULL || + decryptedKey == NULL || decryptedKeySz == NULL || + recipFound == NULL) { + return BAD_FUNC_ARG; + } + + WOLFSSL_ENTER("wc_PKCS7_DecryptRecipientInfos"); +#ifndef NO_PKCS7_STREAM + tmpIdx = *idx; +#endif + + /* check if in the process of decrypting */ + switch (pkcs7->state) { + case WC_PKCS7_DECRYPT_KTRI: + case WC_PKCS7_DECRYPT_KTRI_2: + case WC_PKCS7_DECRYPT_KTRI_3: + #ifndef NO_RSA + ret = wc_PKCS7_DecryptKtri(pkcs7, in, inSz, idx, + decryptedKey, decryptedKeySz, recipFound); + #else + return NOT_COMPILED_IN; + #endif + break; + + case WC_PKCS7_DECRYPT_KARI: + ret = wc_PKCS7_DecryptKari(pkcs7, in, inSz, idx, + decryptedKey, decryptedKeySz, recipFound); + break; + + case WC_PKCS7_DECRYPT_KEKRI: + ret = wc_PKCS7_DecryptKekri(pkcs7, in, inSz, idx, + decryptedKey, decryptedKeySz, recipFound); + break; + + case WC_PKCS7_DECRYPT_PWRI: + #if !defined(NO_PWDBASED) && !defined(NO_SHA) + ret = wc_PKCS7_DecryptPwri(pkcs7, in, inSz, idx, + decryptedKey, decryptedKeySz, recipFound); + #else + return NOT_COMPILED_IN; + #endif + break; + + case WC_PKCS7_DECRYPT_ORI: + ret = wc_PKCS7_DecryptOri(pkcs7, in, inSz, idx, + decryptedKey, decryptedKeySz, recipFound); + break; + + default: + /* not in decrypting state */ + break; + } + + if (ret < 0) { + return ret; + } + + savedIdx = *idx; +#ifndef NO_PKCS7_STREAM + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, inSz); + if (rc < 0) { + return (int)rc; + } + pkiMsgSz = (word32)rc; + if (pkcs7->stream->length > 0) + pkiMsg = pkcs7->stream->buffer; +#endif + + /* when looking for next recipient, use first sequence and version to + * indicate there is another, if not, move on */ + while(*recipFound == 0) { + + /* remove RecipientInfo, if we don't have a SEQUENCE, back up idx to + * last good saved one */ + if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) > 0) { + + #ifndef NO_RSA + /* found ktri */ + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { + break; + } + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_DECRYPT_KTRI); + ret = wc_PKCS7_DecryptKtri(pkcs7, in, inSz, idx, + decryptedKey, decryptedKeySz, + recipFound); + if (ret != 0) + return ret; + #else + return NOT_COMPILED_IN; + #endif + } + else { + /* kari is IMPLICIT[1] */ + *idx = savedIdx; + if (pkiMsg[*idx] == (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) { + + (*idx)++; + + if (GetLength(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (GetMyVersion(pkiMsg, idx, &version, pkiMsgSz) < 0) { + *idx = savedIdx; + break; + } + + if (version != 3) + return ASN_VERSION_E; + + /* found kari */ + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { + break; + } + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_DECRYPT_KARI); + ret = wc_PKCS7_DecryptKari(pkcs7, in, inSz, idx, + decryptedKey, decryptedKeySz, + recipFound); + if (ret != 0) + return ret; + + /* kekri is IMPLICIT[2] */ + } else if (pkiMsg[*idx] == (ASN_CONSTRUCTED | + ASN_CONTEXT_SPECIFIC | 2)) { + (*idx)++; + + if (GetLength(pkiMsg, idx, &version, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (GetMyVersion(pkiMsg, idx, &version, pkiMsgSz) < 0) { + *idx = savedIdx; + break; + } + + if (version != 4) + return ASN_VERSION_E; + + /* found kekri */ + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { + break; + } + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_DECRYPT_KEKRI); + ret = wc_PKCS7_DecryptKekri(pkcs7, in, inSz, idx, + decryptedKey, decryptedKeySz, + recipFound); + if (ret != 0) + return ret; + + /* pwri is IMPLICIT[3] */ + } else if (pkiMsg[*idx] == (ASN_CONSTRUCTED | + ASN_CONTEXT_SPECIFIC | 3)) { + #if !defined(NO_PWDBASED) && !defined(NO_SHA) + (*idx)++; + + if (GetLength(pkiMsg, idx, &version, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (GetMyVersion(pkiMsg, idx, &version, pkiMsgSz) < 0) { + *idx = savedIdx; + break; + } + + if (version != 0) + return ASN_VERSION_E; + + /* found pwri */ + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { + break; + } + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_DECRYPT_PWRI); + ret = wc_PKCS7_DecryptPwri(pkcs7, in, inSz, idx, + decryptedKey, decryptedKeySz, + recipFound); + if (ret != 0) + return ret; + #else + return NOT_COMPILED_IN; + #endif + + /* ori is IMPLICIT[4] */ + } else if (pkiMsg[*idx] == (ASN_CONSTRUCTED | + ASN_CONTEXT_SPECIFIC | 4)) { + (*idx)++; + + /* found ori */ + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { + break; + } + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_DECRYPT_ORI); + ret = wc_PKCS7_DecryptOri(pkcs7, in, inSz, idx, + decryptedKey, decryptedKeySz, + recipFound); + if (ret != 0) + return ret; + + } else { + /* failed to find RecipientInfo, restore idx and continue */ + *idx = savedIdx; + break; + } + } + + /* update good idx */ + savedIdx = *idx; + } + + return ret; +} + + +/* Parse encoded EnvelopedData bundle up to RecipientInfo set. + * + * return size of RecipientInfo SET on success, negative upon error */ +static int wc_PKCS7_ParseToRecipientInfoSet(PKCS7* pkcs7, byte* in, + word32 inSz, word32* idx, + int type) +{ + int version = 0, length, ret = 0; + word32 contentType; + byte* pkiMsg = in; + word32 pkiMsgSz = inSz; +#ifndef NO_PKCS7_STREAM + word32 tmpIdx = 0; + long rc; +#endif + + if (pkcs7 == NULL || pkiMsg == NULL || pkiMsgSz == 0 || idx == NULL) + return BAD_FUNC_ARG; + + if ((type != ENVELOPED_DATA) && (type != AUTH_ENVELOPED_DATA) && + pkcs7->contentOID != FIRMWARE_PKG_DATA) + return BAD_FUNC_ARG; + +#ifndef NO_PKCS7_STREAM + if (pkcs7->stream == NULL) { + if ((ret = wc_PKCS7_CreateStream(pkcs7)) != 0) { + return ret; + } + } +#endif + + switch (pkcs7->state) { + case WC_PKCS7_INFOSET_START: + case WC_PKCS7_INFOSET_BER: + case WC_PKCS7_INFOSET_STAGE1: + case WC_PKCS7_INFOSET_STAGE2: + case WC_PKCS7_INFOSET_END: + break; + + default: + WOLFSSL_MSG("Warning, setting PKCS7 info state to start"); + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_INFOSET_START); + } + + switch (pkcs7->state) { + case WC_PKCS7_INFOSET_START: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_SEQ_SZ + + ASN_TAG_SZ, &pkiMsg, idx)) != 0) { + return ret; + } + + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, in, inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + #endif + /* read past ContentInfo, verify type is envelopedData */ + if (ret == 0 && GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) + { + ret = ASN_PARSE_E; + } + + if (ret == 0 && length == 0 && pkiMsg[(*idx)-1] == 0x80) { + #ifdef ASN_BER_TO_DER + word32 len; + + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_INFOSET_BER); + FALL_THROUGH; + + /* full buffer is needed for conversion */ + case WC_PKCS7_INFOSET_BER: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, + pkcs7->stream->maxLen - pkcs7->stream->length, + &pkiMsg, idx)) != 0) { + return ret; + } + + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, + in, inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + #endif + + len = 0; + + ret = wc_BerToDer(pkiMsg, pkiMsgSz, NULL, &len); + if (ret != LENGTH_ONLY_E) + return ret; + pkcs7->der = (byte*)XMALLOC(len, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (pkcs7->der == NULL) + return MEMORY_E; + ret = wc_BerToDer(pkiMsg, pkiMsgSz, pkcs7->der, &len); + if (ret < 0) + return ret; + + pkiMsg = in = pkcs7->der; + pkiMsgSz = pkcs7->derSz = len; + *idx = 0; + + if (GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + #else + return BER_INDEF_E; + #endif + } + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { + break; + } + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_INFOSET_STAGE1); + FALL_THROUGH; + + case WC_PKCS7_INFOSET_STAGE1: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_OID_SZ + + MAX_LENGTH_SZ + ASN_TAG_SZ, &pkiMsg, idx)) != 0) { + return ret; + } + + pkiMsgSz = (pkcs7->stream->length > 0)? pkcs7->stream->length :inSz; + #endif + if (pkcs7->contentOID != FIRMWARE_PKG_DATA || + type == AUTH_ENVELOPED_DATA) { + if (ret == 0 && wc_GetContentType(pkiMsg, idx, &contentType, + pkiMsgSz) < 0) + ret = ASN_PARSE_E; + + if (ret == 0) { + if (type == ENVELOPED_DATA && contentType != ENVELOPED_DATA) { + WOLFSSL_MSG("PKCS#7 input not of type EnvelopedData"); + ret = PKCS7_OID_E; + } else if (type == AUTH_ENVELOPED_DATA && + contentType != AUTH_ENVELOPED_DATA) { + WOLFSSL_MSG("PKCS#7 input not of type AuthEnvelopedData"); + ret = PKCS7_OID_E; + } + } + + if (ret == 0 && pkiMsg[(*idx)++] != + (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) + ret = ASN_PARSE_E; + + if (ret == 0 && GetLength_ex(pkiMsg, idx, &length, pkiMsgSz, + NO_USER_CHECK) < 0) + ret = ASN_PARSE_E; + } + + if (ret < 0) + break; + + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { + break; + } + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_INFOSET_STAGE2); + FALL_THROUGH; + + case WC_PKCS7_INFOSET_STAGE2: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_SEQ_SZ + + MAX_VERSION_SZ, &pkiMsg, idx)) != 0) { + return ret; + } + + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, + inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + #endif + /* remove EnvelopedData and version */ + if (pkcs7->contentOID != FIRMWARE_PKG_DATA || + type == AUTH_ENVELOPED_DATA) { + if (ret == 0 && GetSequence(pkiMsg, idx, &length, pkiMsgSz) < 0) + ret = ASN_PARSE_E; + } + + if (ret == 0 && GetMyVersion(pkiMsg, idx, &version, pkiMsgSz) < 0) + ret = ASN_PARSE_E; + + if (ret < 0) + break; + + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { + break; + } + + pkcs7->stream->varOne = version; + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_INFOSET_END); + FALL_THROUGH; + + case WC_PKCS7_INFOSET_END: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, + MAX_SET_SZ, &pkiMsg, idx)) != 0) { + return ret; + } + + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, + inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + version = pkcs7->stream->varOne; + #endif + + if (type == ENVELOPED_DATA) { + /* TODO :: make this more accurate */ + if ((pkcs7->publicKeyOID == RSAk && + (version != 0 && version != 2)) + #ifdef HAVE_ECC + || (pkcs7->publicKeyOID == ECDSAk && + (version != 0 && version != 2 && version != 3)) + #endif + ) { + WOLFSSL_MSG("PKCS#7 envelopedData version incorrect"); + ret = ASN_VERSION_E; + } + } else { + /* AuthEnvelopedData version MUST be 0 */ + if (version != 0) { + WOLFSSL_MSG("PKCS#7 AuthEnvelopedData needs to be of version 0"); + ret = ASN_VERSION_E; + } + } + + /* remove RecipientInfo set, get length of set */ + if (ret == 0 && GetSet(pkiMsg, idx, &length, pkiMsgSz) < 0) + ret = ASN_PARSE_E; + + if (ret < 0) + break; + + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, idx)) != 0) { + break; + } + #endif + + if (ret == 0) + ret = length; + + break; + + default: + WOLFSSL_MSG("Bad PKCS7 info set state"); + ret = BAD_FUNC_ARG; + break; + } + + return ret; +} + + +/* Import secret/private key into a PKCS7 structure. Used for setting + * the secret key for decryption a EnvelopedData KEKRI RecipientInfo. + * + * Returns 0 on success, negative upon error */ +WOLFSSL_API int wc_PKCS7_SetKey(PKCS7* pkcs7, byte* key, word32 keySz) +{ + if (pkcs7 == NULL || key == NULL || keySz == 0) + return BAD_FUNC_ARG; + + pkcs7->privateKey = key; + pkcs7->privateKeySz = keySz; + + return 0; +} + + +/* unwrap and decrypt PKCS#7 envelopedData object, return decoded size */ +WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* in, + word32 inSz, byte* output, + word32 outputSz) +{ + int recipFound = 0; + int ret, length = 0; + word32 idx = 0; +#ifndef NO_PKCS7_STREAM + word32 tmpIdx = 0; + long rc; +#endif + word32 contentType, encOID = 0; + word32 decryptedKeySz = MAX_ENCRYPTED_KEY_SZ; + + int expBlockSz = 0, blockKeySz = 0; + byte tmpIvBuf[MAX_CONTENT_IV_SIZE]; + byte* tmpIv = tmpIvBuf; + + byte* pkiMsg = in; + word32 pkiMsgSz = inSz; + byte* decryptedKey = NULL; + int encryptedContentSz = 0; + byte padLen; + byte* encryptedContent = NULL; + int explicitOctet; + + if (pkcs7 == NULL) + return BAD_FUNC_ARG; + + if (pkiMsg == NULL || pkiMsgSz == 0 || + output == NULL || outputSz == 0) + return BAD_FUNC_ARG; + +#ifndef NO_PKCS7_STREAM + (void)tmpIv; /* help out static analysis */ + if (pkcs7->stream == NULL) { + if ((ret = wc_PKCS7_CreateStream(pkcs7)) != 0) { + return ret; + } + } +#endif + + switch (pkcs7->state) { + case WC_PKCS7_START: + case WC_PKCS7_INFOSET_START: + case WC_PKCS7_INFOSET_BER: + case WC_PKCS7_INFOSET_STAGE1: + case WC_PKCS7_INFOSET_STAGE2: + case WC_PKCS7_INFOSET_END: + ret = wc_PKCS7_ParseToRecipientInfoSet(pkcs7, pkiMsg, pkiMsgSz, + &idx, ENVELOPED_DATA); + if (ret < 0) { + break; + } + + #ifdef ASN_BER_TO_DER + /* check if content was BER and has been converted to DER */ + if (pkcs7->derSz > 0) + pkiMsg = in = pkcs7->der; + #endif + + decryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (decryptedKey == NULL) + return MEMORY_E; + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_ENV_2); + #ifndef NO_PKCS7_STREAM + tmpIdx = idx; + pkcs7->stream->aad = decryptedKey; + #endif + FALL_THROUGH; + + case WC_PKCS7_ENV_2: + #ifndef NO_PKCS7_STREAM + /* store up enough buffer for initial info set decode */ + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_LENGTH_SZ + + MAX_VERSION_SZ + ASN_TAG_SZ, &pkiMsg, &idx)) != 0) { + return ret; + } + #endif + FALL_THROUGH; + + case WC_PKCS7_DECRYPT_KTRI: + case WC_PKCS7_DECRYPT_KTRI_2: + case WC_PKCS7_DECRYPT_KTRI_3: + case WC_PKCS7_DECRYPT_KARI: + case WC_PKCS7_DECRYPT_KEKRI: + case WC_PKCS7_DECRYPT_PWRI: + case WC_PKCS7_DECRYPT_ORI: + #ifndef NO_PKCS7_STREAM + decryptedKey = pkcs7->stream->aad; + decryptedKeySz = MAX_ENCRYPTED_KEY_SZ; + #endif + + ret = wc_PKCS7_DecryptRecipientInfos(pkcs7, in, inSz, &idx, + decryptedKey, &decryptedKeySz, + &recipFound); + if (ret == 0 && recipFound == 0) { + WOLFSSL_MSG("No recipient found in envelopedData that matches input"); + ret = PKCS7_RECIP_E; + } + + if (ret != 0) + break; + #ifndef NO_PKCS7_STREAM + tmpIdx = idx; + pkcs7->stream->aadSz = decryptedKeySz; + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_ENV_3); + FALL_THROUGH; + + case WC_PKCS7_ENV_3: + + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_LENGTH_SZ + + MAX_VERSION_SZ + ASN_TAG_SZ + + MAX_LENGTH_SZ, &pkiMsg, &idx)) + != 0) { + return ret; + } + + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, + inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + #else + ret = 0; + #endif + + /* remove EncryptedContentInfo */ + if (ret == 0 && GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) { + ret = ASN_PARSE_E; + } + + if (ret == 0 && wc_GetContentType(pkiMsg, &idx, &contentType, + pkiMsgSz) < 0) { + ret = ASN_PARSE_E; + } + + if (ret == 0 && GetAlgoId(pkiMsg, &idx, &encOID, oidBlkType, + pkiMsgSz) < 0) { + ret = ASN_PARSE_E; + } + + blockKeySz = wc_PKCS7_GetOIDKeySize(encOID); + if (ret == 0 && blockKeySz < 0) { + ret = blockKeySz; + } + + expBlockSz = wc_PKCS7_GetOIDBlockSize(encOID); + if (ret == 0 && expBlockSz < 0) { + ret = expBlockSz; + } + + /* get block cipher IV, stored in OPTIONAL parameter of AlgoID */ + if (ret == 0 && pkiMsg[idx++] != ASN_OCTET_STRING) { + ret = ASN_PARSE_E; + } + + if (ret == 0 && GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) { + ret = ASN_PARSE_E; + } + + if (ret == 0 && length != expBlockSz) { + WOLFSSL_MSG("Incorrect IV length, must be of content alg block size"); + ret = ASN_PARSE_E; + } + + if (ret != 0) + break; + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { + break; + } + wc_PKCS7_StreamStoreVar(pkcs7, encOID, expBlockSz, length); + pkcs7->stream->contentSz = blockKeySz; + pkcs7->stream->expected = length + MAX_LENGTH_SZ + MAX_LENGTH_SZ + + ASN_TAG_SZ + ASN_TAG_SZ; + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_ENV_4); + FALL_THROUGH; + + case WC_PKCS7_ENV_4: + + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, + pkcs7->stream->expected, &pkiMsg, &idx)) != 0) { + return ret; + } + + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, + inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + + wc_PKCS7_StreamGetVar(pkcs7, 0, 0, &length); + tmpIv = pkcs7->stream->tmpIv; + if (tmpIv == NULL) { + /* check added to help out static analysis tool */ + ret = MEMORY_E; + break; + } + #else + ret = 0; + #endif + + XMEMCPY(tmpIv, &pkiMsg[idx], length); + idx += length; + + explicitOctet = pkiMsg[idx] == + (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0); + + /* read encryptedContent, cont[0] */ + if (ret == 0 && pkiMsg[idx] != (ASN_CONTEXT_SPECIFIC | 0) && + pkiMsg[idx] != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0)) { + ret = ASN_PARSE_E; + } + idx++; + + if (ret == 0 && GetLength(pkiMsg, &idx, &encryptedContentSz, + pkiMsgSz) <= 0) { + ret = ASN_PARSE_E; + } + + if (ret == 0 && explicitOctet) { + if (ret == 0 && pkiMsg[idx++] != ASN_OCTET_STRING) { + ret = ASN_PARSE_E; + break; + } + + if (ret == 0 && GetLength(pkiMsg, &idx, &encryptedContentSz, + pkiMsgSz) <= 0) { + ret = ASN_PARSE_E; + break; + } + } + + if (ret != 0) + break; + + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { + break; + } + pkcs7->stream->expected = encryptedContentSz; + wc_PKCS7_StreamGetVar(pkcs7, &encOID, &expBlockSz, 0); + wc_PKCS7_StreamStoreVar(pkcs7, encOID, expBlockSz, + encryptedContentSz); + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_ENV_5); + FALL_THROUGH; + + case WC_PKCS7_ENV_5: + + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, + pkcs7->stream->expected, &pkiMsg, &idx)) != 0) { + return ret; + } + + wc_PKCS7_StreamGetVar(pkcs7, &encOID, &expBlockSz, + &encryptedContentSz); + tmpIv = pkcs7->stream->tmpIv; + + /* restore decrypted key */ + decryptedKey = pkcs7->stream->aad; + decryptedKeySz = pkcs7->stream->aadSz; + blockKeySz = pkcs7->stream->contentSz; + #else + ret = 0; + #endif + encryptedContent = (byte*)XMALLOC(encryptedContentSz, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (ret == 0 && encryptedContent == NULL) { + ret = MEMORY_E; + break; + } + + if (ret == 0) { + XMEMCPY(encryptedContent, &pkiMsg[idx], encryptedContentSz); + } + + /* decrypt encryptedContent */ + ret = wc_PKCS7_DecryptContent(encOID, decryptedKey, blockKeySz, + tmpIv, expBlockSz, NULL, 0, NULL, 0, + encryptedContent, encryptedContentSz, + encryptedContent); + if (ret != 0) { + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + break; + } + + padLen = encryptedContent[encryptedContentSz-1]; + + /* copy plaintext to output */ + if (padLen > encryptedContentSz || + (word32)(encryptedContentSz - padLen) > outputSz) { + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + ret = BUFFER_E; + break; + } + XMEMCPY(output, encryptedContent, encryptedContentSz - padLen); + + /* free memory, zero out keys */ + ForceZero(decryptedKey, MAX_ENCRYPTED_KEY_SZ); + ForceZero(encryptedContent, encryptedContentSz); + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + + ret = encryptedContentSz - padLen; + #ifndef NO_PKCS7_STREAM + pkcs7->stream->aad = NULL; + pkcs7->stream->aadSz = 0; + wc_PKCS7_ResetStream(pkcs7); + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START); + break; + + default: + WOLFSSL_MSG("PKCS#7 unknown decode enveloped state"); + ret = BAD_FUNC_ARG; + } + +#ifndef NO_PKCS7_STREAM + if (ret < 0 && ret != WC_PKCS7_WANT_READ_E) { + wc_PKCS7_ResetStream(pkcs7); + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START); + } +#else + if (decryptedKey != NULL && ret < 0) { + ForceZero(decryptedKey, MAX_ENCRYPTED_KEY_SZ); + XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + } +#endif + return ret; +} + + +/* build PKCS#7 authEnvelopedData content type, return enveloped size */ +int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, byte* output, + word32 outputSz) +{ +#if defined(HAVE_AESGCM) || defined(HAVE_AESCCM) + int ret, idx = 0; + int totalSz, encryptedOutSz; + + int contentInfoSeqSz, outerContentTypeSz, outerContentSz; + byte contentInfoSeq[MAX_SEQ_SZ]; + byte outerContentType[MAX_ALGO_SZ]; + byte outerContent[MAX_SEQ_SZ]; + + int envDataSeqSz, verSz; + byte envDataSeq[MAX_SEQ_SZ]; + byte ver[MAX_VERSION_SZ]; + + WC_RNG rng; + int blockSz, blockKeySz; + byte* encryptedContent; + + Pkcs7EncodedRecip* tmpRecip = NULL; + int recipSz, recipSetSz; + byte recipSet[MAX_SET_SZ]; + + int encContentOctetSz, encContentSeqSz, contentTypeSz; + int contentEncAlgoSz, nonceOctetStringSz, macOctetStringSz; + byte encContentSeq[MAX_SEQ_SZ]; + byte contentType[MAX_ALGO_SZ]; + byte contentEncAlgo[MAX_ALGO_SZ]; + byte nonceOctetString[MAX_OCTET_STR_SZ]; + byte encContentOctet[MAX_OCTET_STR_SZ]; + byte macOctetString[MAX_OCTET_STR_SZ]; + + byte authTag[AES_BLOCK_SIZE]; + byte nonce[GCM_NONCE_MID_SZ]; /* GCM nonce is larger than CCM */ + byte macInt[MAX_VERSION_SZ]; + word32 nonceSz = 0, macIntSz = 0; + + /* authAttribs */ + byte* flatAuthAttribs = NULL; + byte authAttribSet[MAX_SET_SZ]; + EncodedAttrib authAttribs[MAX_AUTH_ATTRIBS_SZ]; + word32 authAttribsSz = 0, authAttribsCount = 0; + word32 authAttribsSetSz = 0; + + byte* aadBuffer = NULL; + word32 aadBufferSz = 0; + byte authAttribAadSet[MAX_SET_SZ]; + word32 authAttribsAadSetSz = 0; + + /* unauthAttribs */ + byte* flatUnauthAttribs = NULL; + byte unauthAttribSet[MAX_SET_SZ]; + EncodedAttrib unauthAttribs[MAX_UNAUTH_ATTRIBS_SZ]; + word32 unauthAttribsSz = 0, unauthAttribsCount = 0; + word32 unauthAttribsSetSz = 0; + + + PKCS7Attrib contentTypeAttrib; + byte contentTypeValue[MAX_OID_SZ]; + /* contentType OID (1.2.840.113549.1.9.3) */ + const byte contentTypeOid[] = + { ASN_OBJECT_ID, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xF7, 0x0d, 0x01, + 0x09, 0x03 }; + + if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0) + return BAD_FUNC_ARG; + + if (output == NULL || outputSz == 0) + return BAD_FUNC_ARG; + + switch (pkcs7->encryptOID) { +#ifdef HAVE_AESGCM + #ifdef WOLFSSL_AES_128 + case AES128GCMb: + break; + #endif + #ifdef WOLFSSL_AES_192 + case AES192GCMb: + break; + #endif + #ifdef WOLFSSL_AES_256 + case AES256GCMb: + break; + #endif +#endif +#ifdef HAVE_AESCCM + #ifdef WOLFSSL_AES_128 + case AES128CCMb: + break; + #endif + #ifdef WOLFSSL_AES_192 + case AES192CCMb: + break; + #endif + #ifdef WOLFSSL_AES_256 + case AES256CCMb: + break; + #endif +#endif + default: + WOLFSSL_MSG("CMS AuthEnvelopedData must use AES-GCM or AES-CCM"); + return BAD_FUNC_ARG; + } + + blockKeySz = wc_PKCS7_GetOIDKeySize(pkcs7->encryptOID); + if (blockKeySz < 0) + return blockKeySz; + + blockSz = wc_PKCS7_GetOIDBlockSize(pkcs7->encryptOID); + if (blockKeySz < 0 || blockSz < 0) + return blockSz; + + /* outer content type */ + ret = wc_SetContentType(AUTH_ENVELOPED_DATA, outerContentType, + sizeof(outerContentType)); + if (ret < 0) + return ret; + + outerContentTypeSz = ret; + + /* version, defined as 0 in RFC 5083 */ + verSz = SetMyVersion(0, ver, 0); + + /* generate random content encryption key */ + ret = PKCS7_GenerateContentEncryptionKey(pkcs7, blockKeySz); + if (ret != 0) { + return ret; + } + + /* build RecipientInfo, only if user manually set singleCert and size */ + if (pkcs7->singleCert != NULL && pkcs7->singleCertSz > 0) { + switch (pkcs7->publicKeyOID) { + #ifndef NO_RSA + case RSAk: + ret = wc_PKCS7_AddRecipient_KTRI(pkcs7, pkcs7->singleCert, + pkcs7->singleCertSz, 0); + break; + #endif + #ifdef HAVE_ECC + case ECDSAk: + ret = wc_PKCS7_AddRecipient_KARI(pkcs7, pkcs7->singleCert, + pkcs7->singleCertSz, + pkcs7->keyWrapOID, + pkcs7->keyAgreeOID, pkcs7->ukm, + pkcs7->ukmSz, 0); + break; + #endif + + default: + WOLFSSL_MSG("Unsupported RecipientInfo public key type"); + return BAD_FUNC_ARG; + }; + + if (ret < 0) { + WOLFSSL_MSG("Failed to create RecipientInfo"); + return ret; + } + } + + recipSz = wc_PKCS7_GetRecipientListSize(pkcs7); + if (recipSz < 0) { + return ret; + + } else if (recipSz == 0) { + WOLFSSL_MSG("You must add at least one CMS recipient"); + return PKCS7_RECIP_E; + } + recipSetSz = SetSet(recipSz, recipSet); + + /* generate random nonce and IV for encryption */ + switch (pkcs7->encryptOID) { +#ifdef HAVE_AESGCM + #ifdef WOLFSSL_AES_128 + case AES128GCMb: + FALL_THROUGH; + #endif + #ifdef WOLFSSL_AES_192 + case AES192GCMb: + FALL_THROUGH; + #endif + #ifdef WOLFSSL_AES_256 + case AES256GCMb: + #endif + #if defined(WOLFSSL_AES_128) || defined(WOLFSSL_AES_192) || \ + defined(WOLFSSL_AES_256) + /* GCM nonce is GCM_NONCE_MID_SZ (12) */ + nonceSz = GCM_NONCE_MID_SZ; + break; + #endif +#endif /* HAVE_AESGCM */ +#ifdef HAVE_AESCCM + #ifdef WOLFSSL_AES_128 + case AES128CCMb: + FALL_THROUGH; + #endif + #ifdef WOLFSSL_AES_192 + case AES192CCMb: + FALL_THROUGH; + #endif + #ifdef WOLFSSL_AES_256 + case AES256CCMb: + #endif + #if defined(WOLFSSL_AES_128) || defined(WOLFSSL_AES_192) || \ + defined(WOLFSSL_AES_256) + /* CCM nonce is CCM_NONCE_MIN_SZ (7) */ + nonceSz = CCM_NONCE_MIN_SZ; + break; + #endif +#endif /* HAVE_AESCCM */ + } + + ret = wc_InitRng_ex(&rng, pkcs7->heap, pkcs7->devId); + if (ret != 0) + return ret; + + ret = wc_PKCS7_GenerateBlock(pkcs7, &rng, nonce, nonceSz); + wc_FreeRng(&rng); + if (ret != 0) { + return ret; + } + + + /* authAttribs: add contentType attrib if needed */ + if (pkcs7->contentOID != DATA) { + + /* if type is not id-data, contentType attribute MUST be added */ + contentTypeAttrib.oid = contentTypeOid; + contentTypeAttrib.oidSz = sizeof(contentTypeOid); + + /* try to set from contentOID first, known types */ + ret = wc_SetContentType(pkcs7->contentOID, contentTypeValue, + sizeof(contentTypeValue)); + if (ret > 0) { + contentTypeAttrib.value = contentTypeValue; + contentTypeAttrib.valueSz = ret; + + /* otherwise, try to set from custom content type */ + } else if (ret <= 0) { + if (pkcs7->contentTypeSz == 0) { + WOLFSSL_MSG("CMS pkcs7->contentType must be set if " + "contentOID is not"); + return BAD_FUNC_ARG; + } + contentTypeAttrib.value = pkcs7->contentType; + contentTypeAttrib.valueSz = pkcs7->contentTypeSz; + } + + authAttribsSz += EncodeAttributes(authAttribs, 1, + &contentTypeAttrib, 1); + authAttribsCount += 1; + } + + /* authAttribs: add in user authenticated attributes */ + if (pkcs7->authAttribs != NULL && pkcs7->authAttribsSz > 0) { + authAttribsSz += EncodeAttributes(authAttribs + authAttribsCount, + MAX_AUTH_ATTRIBS_SZ - authAttribsCount, + pkcs7->authAttribs, + pkcs7->authAttribsSz); + authAttribsCount += pkcs7->authAttribsSz; + } + + /* authAttribs: flatten authAttribs */ + if (authAttribsSz > 0 && authAttribsCount > 0) { + flatAuthAttribs = (byte*)XMALLOC(authAttribsSz, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (flatAuthAttribs == NULL) { + return MEMORY_E; + } + + FlattenAttributes(pkcs7, flatAuthAttribs, authAttribs, + authAttribsCount); + + authAttribsSetSz = SetImplicit(ASN_SET, 1, authAttribsSz, + authAttribSet); + + /* From RFC5083, "For the purpose of constructing the AAD, the + * IMPLICIT [1] tag in the authAttrs field is not used for the + * DER encoding: rather a universal SET OF tag is used. */ + authAttribsAadSetSz = SetSet(authAttribsSz, authAttribAadSet); + + /* allocate temp buffer to hold alternate attrib encoding for aad */ + aadBuffer = (byte*)XMALLOC(authAttribsSz + authAttribsAadSetSz, + pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (aadBuffer == NULL) { + XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } + + /* build up alternate attrib encoding for aad */ + aadBufferSz = 0; + XMEMCPY(aadBuffer + aadBufferSz, authAttribAadSet, authAttribsAadSetSz); + aadBufferSz += authAttribsAadSetSz; + XMEMCPY(aadBuffer + aadBufferSz, flatAuthAttribs, authAttribsSz); + aadBufferSz += authAttribsSz; + } + + /* build up unauthenticated attributes (unauthAttrs) */ + if (pkcs7->unauthAttribsSz > 0) { + unauthAttribsSz = EncodeAttributes(unauthAttribs + unauthAttribsCount, + MAX_UNAUTH_ATTRIBS_SZ - unauthAttribsCount, + pkcs7->unauthAttribs, + pkcs7->unauthAttribsSz); + unauthAttribsCount = pkcs7->unauthAttribsSz; + + flatUnauthAttribs = (byte*)XMALLOC(unauthAttribsSz, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (flatUnauthAttribs == NULL) { + if (aadBuffer) + XFREE(aadBuffer, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (flatAuthAttribs) + XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } + + FlattenAttributes(pkcs7, flatUnauthAttribs, unauthAttribs, + unauthAttribsCount); + unauthAttribsSetSz = SetImplicit(ASN_SET, 2, unauthAttribsSz, + unauthAttribSet); + } + + /* allocate encrypted content buffer */ + encryptedOutSz = pkcs7->contentSz; + encryptedContent = (byte*)XMALLOC(encryptedOutSz, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (encryptedContent == NULL) { + if (aadBuffer) + XFREE(aadBuffer, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (flatUnauthAttribs) + XFREE(flatUnauthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (flatAuthAttribs) + XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } + + /* encrypt content */ + ret = wc_PKCS7_EncryptContent(pkcs7->encryptOID, pkcs7->cek, + pkcs7->cekSz, nonce, nonceSz, aadBuffer, aadBufferSz, authTag, + sizeof(authTag), pkcs7->content, encryptedOutSz, encryptedContent); + + if (aadBuffer) { + XFREE(aadBuffer, pkcs7->heap, DYNAMIC_TYPE_TMP_BUFFER); + aadBuffer = NULL; + } + + if (ret != 0) { + if (flatUnauthAttribs) + XFREE(flatUnauthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (flatAuthAttribs) + XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + /* EncryptedContentInfo */ + ret = wc_SetContentType(pkcs7->contentOID, contentType, + sizeof(contentType)); + if (ret < 0) { + if (flatUnauthAttribs) + XFREE(flatUnauthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (flatAuthAttribs) + XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + contentTypeSz = ret; + + /* put together nonce OCTET STRING */ + nonceOctetStringSz = SetOctetString(nonceSz, nonceOctetString); + + /* put together aes-ICVlen INTEGER */ + macIntSz = SetMyVersion(sizeof(authTag), macInt, 0); + + /* build up our ContentEncryptionAlgorithmIdentifier sequence, + * adding (nonceOctetStringSz + blockSz + macIntSz) for nonce OCTET STRING + * and tag size */ + contentEncAlgoSz = SetAlgoID(pkcs7->encryptOID, contentEncAlgo, + oidBlkType, nonceOctetStringSz + nonceSz + + macIntSz); + + if (contentEncAlgoSz == 0) { + if (flatUnauthAttribs) + XFREE(flatUnauthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (flatAuthAttribs) + XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return BAD_FUNC_ARG; + } + + encContentOctetSz = SetImplicit(ASN_OCTET_STRING, 0, encryptedOutSz, + encContentOctet); + + encContentSeqSz = SetSequence(contentTypeSz + contentEncAlgoSz + + nonceOctetStringSz + nonceSz + macIntSz + + encContentOctetSz + encryptedOutSz, + encContentSeq); + + macOctetStringSz = SetOctetString(sizeof(authTag), macOctetString); + + /* keep track of sizes for outer wrapper layering */ + totalSz = verSz + recipSetSz + recipSz + encContentSeqSz + contentTypeSz + + contentEncAlgoSz + nonceOctetStringSz + nonceSz + macIntSz + + encContentOctetSz + encryptedOutSz + authAttribsSz + + authAttribsSetSz + macOctetStringSz + sizeof(authTag) + + unauthAttribsSz + unauthAttribsSetSz; + + /* EnvelopedData */ + envDataSeqSz = SetSequence(totalSz, envDataSeq); + totalSz += envDataSeqSz; + + /* outer content */ + outerContentSz = SetExplicit(0, totalSz, outerContent); + totalSz += outerContentTypeSz; + totalSz += outerContentSz; + + /* ContentInfo */ + contentInfoSeqSz = SetSequence(totalSz, contentInfoSeq); + totalSz += contentInfoSeqSz; + + if (totalSz > (int)outputSz) { + WOLFSSL_MSG("Pkcs7_encrypt output buffer too small"); + if (flatUnauthAttribs) + XFREE(flatUnauthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (flatAuthAttribs) + XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return BUFFER_E; + } + + XMEMCPY(output + idx, contentInfoSeq, contentInfoSeqSz); + idx += contentInfoSeqSz; + XMEMCPY(output + idx, outerContentType, outerContentTypeSz); + idx += outerContentTypeSz; + XMEMCPY(output + idx, outerContent, outerContentSz); + idx += outerContentSz; + XMEMCPY(output + idx, envDataSeq, envDataSeqSz); + idx += envDataSeqSz; + XMEMCPY(output + idx, ver, verSz); + idx += verSz; + XMEMCPY(output + idx, recipSet, recipSetSz); + idx += recipSetSz; + /* copy in recipients from list */ + tmpRecip = pkcs7->recipList; + while (tmpRecip != NULL) { + XMEMCPY(output + idx, tmpRecip->recip, tmpRecip->recipSz); + idx += tmpRecip->recipSz; + tmpRecip = tmpRecip->next; + } + wc_PKCS7_FreeEncodedRecipientSet(pkcs7); + XMEMCPY(output + idx, encContentSeq, encContentSeqSz); + idx += encContentSeqSz; + XMEMCPY(output + idx, contentType, contentTypeSz); + idx += contentTypeSz; + XMEMCPY(output + idx, contentEncAlgo, contentEncAlgoSz); + idx += contentEncAlgoSz; + XMEMCPY(output + idx, nonceOctetString, nonceOctetStringSz); + idx += nonceOctetStringSz; + XMEMCPY(output + idx, nonce, nonceSz); + idx += nonceSz; + XMEMCPY(output + idx, macInt, macIntSz); + idx += macIntSz; + XMEMCPY(output + idx, encContentOctet, encContentOctetSz); + idx += encContentOctetSz; + XMEMCPY(output + idx, encryptedContent, encryptedOutSz); + idx += encryptedOutSz; + + /* authenticated attributes */ + if (flatAuthAttribs && authAttribsSz > 0) { + XMEMCPY(output + idx, authAttribSet, authAttribsSetSz); + idx += authAttribsSetSz; + XMEMCPY(output + idx, flatAuthAttribs, authAttribsSz); + idx += authAttribsSz; + XFREE(flatAuthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + } + + XMEMCPY(output + idx, macOctetString, macOctetStringSz); + idx += macOctetStringSz; + XMEMCPY(output + idx, authTag, sizeof(authTag)); + idx += sizeof(authTag); + + /* unauthenticated attributes */ + if (unauthAttribsSz > 0) { + XMEMCPY(output + idx, unauthAttribSet, unauthAttribsSetSz); + idx += unauthAttribsSetSz; + XMEMCPY(output + idx, flatUnauthAttribs, unauthAttribsSz); + idx += unauthAttribsSz; + } + + if (flatUnauthAttribs != NULL) { + XFREE(flatUnauthAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + } + + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + + return idx; + +#else + WOLFSSL_MSG("AuthEnvelopedData requires AES-GCM or AES-CCM to be enabled"); + (void)pkcs7; + (void)output; + (void)outputSz; + + return NOT_COMPILED_IN; +#endif /* HAVE_AESGCM | HAVE_AESCCM */ +} + + +/* unwrap and decrypt PKCS#7 AuthEnvelopedData object, return decoded size */ +WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* in, + word32 inSz, byte* output, + word32 outputSz) +{ +#if defined(HAVE_AESGCM) || defined(HAVE_AESCC) + int recipFound = 0; + int ret = 0, length; + word32 idx = 0; +#ifndef NO_PKCS7_STREAM + word32 tmpIdx = 0; + long rc; +#endif + word32 contentType, encOID = 0; + word32 decryptedKeySz = 0; + byte* pkiMsg = in; + word32 pkiMsgSz = inSz; + + int expBlockSz = 0, blockKeySz = 0; + byte authTag[AES_BLOCK_SIZE]; + byte nonce[GCM_NONCE_MID_SZ]; /* GCM nonce is larger than CCM */ + int nonceSz = 0, authTagSz = 0, macSz = 0; + +#ifdef WOLFSSL_SMALL_STACK + byte* decryptedKey = NULL; +#else + byte decryptedKey[MAX_ENCRYPTED_KEY_SZ]; +#endif + int encryptedContentSz = 0; + byte* encryptedContent = NULL; + int explicitOctet = 0; + + byte authAttribSetByte = 0; + byte* encodedAttribs = NULL; + word32 encodedAttribIdx = 0, encodedAttribSz = 0; + byte* authAttrib = NULL; + int authAttribSz = 0; + + if (pkcs7 == NULL) + return BAD_FUNC_ARG; + + if (pkiMsg == NULL || pkiMsgSz == 0 || + output == NULL || outputSz == 0) + return BAD_FUNC_ARG; +#ifndef NO_PKCS7_STREAM + if (pkcs7->stream == NULL) { + if ((ret = wc_PKCS7_CreateStream(pkcs7)) != 0) { + return ret; + } + } +#endif + + switch (pkcs7->state) { + case WC_PKCS7_START: + case WC_PKCS7_INFOSET_START: + case WC_PKCS7_INFOSET_STAGE1: + case WC_PKCS7_INFOSET_STAGE2: + case WC_PKCS7_INFOSET_END: + ret = wc_PKCS7_ParseToRecipientInfoSet(pkcs7, pkiMsg, pkiMsgSz, + &idx, AUTH_ENVELOPED_DATA); + if (ret < 0) + break; + + #ifndef NO_PKCS7_STREAM + tmpIdx = idx; + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_2); + FALL_THROUGH; + + case WC_PKCS7_AUTHENV_2: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_LENGTH_SZ + + MAX_VERSION_SZ + ASN_TAG_SZ, &pkiMsg, &idx)) != 0) { + break; + } + #endif + #ifdef WOLFSSL_SMALL_STACK + decryptedKey = (byte*)XMALLOC(MAX_ENCRYPTED_KEY_SZ, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (decryptedKey == NULL) { + ret = MEMORY_E; + break; + } + #ifndef NO_PKCS7_STREAM + pkcs7->stream->key = decryptedKey; + #endif + #endif + FALL_THROUGH; + + case WC_PKCS7_DECRYPT_KTRI: + case WC_PKCS7_DECRYPT_KTRI_2: + case WC_PKCS7_DECRYPT_KTRI_3: + case WC_PKCS7_DECRYPT_KARI: + case WC_PKCS7_DECRYPT_KEKRI: + case WC_PKCS7_DECRYPT_PWRI: + case WC_PKCS7_DECRYPT_ORI: + + decryptedKeySz = MAX_ENCRYPTED_KEY_SZ; + #ifdef WOLFSSL_SMALL_STACK + #ifndef NO_PKCS7_STREAM + decryptedKey = pkcs7->stream->key; + #endif + #endif + + ret = wc_PKCS7_DecryptRecipientInfos(pkcs7, in, inSz, &idx, + decryptedKey, &decryptedKeySz, + &recipFound); + if (ret != 0) { + break; + } + + if (recipFound == 0) { + WOLFSSL_MSG("No recipient found in envelopedData that matches input"); + ret = PKCS7_RECIP_E; + break; + } + + #ifndef NO_PKCS7_STREAM + tmpIdx = idx; + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_3); + FALL_THROUGH; + + case WC_PKCS7_AUTHENV_3: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_SEQ_SZ + + MAX_ALGO_SZ + MAX_ALGO_SZ + ASN_TAG_SZ, + &pkiMsg, &idx)) != 0) { + break; + } + + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, + in, inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + #endif + + /* remove EncryptedContentInfo */ + if (ret == 0 && GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) { + ret = ASN_PARSE_E; + } + + if (ret == 0 && wc_GetContentType(pkiMsg, &idx, &contentType, + pkiMsgSz) < 0) { + ret = ASN_PARSE_E; + } + + if (ret == 0 && GetAlgoId(pkiMsg, &idx, &encOID, oidBlkType, + pkiMsgSz) < 0) { + ret = ASN_PARSE_E; + } + + blockKeySz = wc_PKCS7_GetOIDKeySize(encOID); + if (ret == 0 && blockKeySz < 0) { + ret = blockKeySz; + } + + expBlockSz = wc_PKCS7_GetOIDBlockSize(encOID); + if (ret == 0 && expBlockSz < 0) { + ret = expBlockSz; + } + + /* get nonce, stored in OPTIONAL parameter of AlgoID */ + if (ret == 0 && pkiMsg[idx++] != ASN_OCTET_STRING) { + ret = ASN_PARSE_E; + } + + if (ret < 0) + break; + + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { + break; + } + wc_PKCS7_StreamStoreVar(pkcs7, encOID, blockKeySz, 0); + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_4); + FALL_THROUGH; + + case WC_PKCS7_AUTHENV_4: + + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_LENGTH_SZ + + MAX_VERSION_SZ + ASN_TAG_SZ + MAX_LENGTH_SZ, + &pkiMsg, &idx)) != 0) { + break; + } + + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, + inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + #endif + if (ret == 0 && GetLength(pkiMsg, &idx, &nonceSz, pkiMsgSz) < 0) { + ret = ASN_PARSE_E; + } + + if (ret == 0 && nonceSz > (int)sizeof(nonce)) { + WOLFSSL_MSG("AuthEnvelopedData nonce too large for buffer"); + ret = ASN_PARSE_E; + } + + if (ret == 0) { + XMEMCPY(nonce, &pkiMsg[idx], nonceSz); + idx += nonceSz; + } + + /* get mac size, also stored in OPTIONAL parameter of AlgoID */ + if (ret == 0 && GetMyVersion(pkiMsg, &idx, &macSz, pkiMsgSz) < 0) { + ret = ASN_PARSE_E; + } + + if (ret == 0) { + explicitOctet = pkiMsg[idx] == + (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0); + } + + /* read encryptedContent, cont[0] */ + if (ret == 0 && pkiMsg[idx] != (ASN_CONTEXT_SPECIFIC | 0) && + pkiMsg[idx] != (ASN_CONTEXT_SPECIFIC | ASN_CONSTRUCTED | 0)) { + ret = ASN_PARSE_E; + } + idx++; + + if (ret == 0 && GetLength(pkiMsg, &idx, &encryptedContentSz, + pkiMsgSz) <= 0) { + ret = ASN_PARSE_E; + } + + if (explicitOctet) { + if (ret == 0 && pkiMsg[idx++] != ASN_OCTET_STRING) { + ret = ASN_PARSE_E; + } + + if (ret == 0 && GetLength(pkiMsg, &idx, &encryptedContentSz, + pkiMsgSz) <= 0) { + ret = ASN_PARSE_E; + } + } + + if (ret < 0) + break; + + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { + break; + } + + /* store nonce for later */ + if (nonceSz > 0) { + pkcs7->stream->nonceSz = nonceSz; + pkcs7->stream->nonce = (byte*)XMALLOC(nonceSz, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (pkcs7->stream->nonce == NULL) { + ret = MEMORY_E; + break; + } + else { + XMEMCPY(pkcs7->stream->nonce, nonce, nonceSz); + } + } + + pkcs7->stream->expected = encryptedContentSz; + wc_PKCS7_StreamStoreVar(pkcs7, encOID, blockKeySz, + encryptedContentSz); + #endif + + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_5); + FALL_THROUGH; + + case WC_PKCS7_AUTHENV_5: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_LENGTH_SZ + + ASN_TAG_SZ + ASN_TAG_SZ + pkcs7->stream->expected, + &pkiMsg, &idx)) != 0) { + break; + } + + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, + inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + + encryptedContentSz = pkcs7->stream->expected; + #endif + + encryptedContent = (byte*)XMALLOC(encryptedContentSz, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (ret == 0 && encryptedContent == NULL) { + ret = MEMORY_E; + } + + if (ret == 0) { + XMEMCPY(encryptedContent, &pkiMsg[idx], encryptedContentSz); + idx += encryptedContentSz; + } + #ifndef NO_PKCS7_STREAM + pkcs7->stream->bufferPt = encryptedContent; + #endif + + /* may have IMPLICIT [1] authenticatedAttributes */ + if (ret == 0 && pkiMsg[idx] == + (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) { + encodedAttribIdx = idx; + encodedAttribs = pkiMsg + idx; + idx++; + + if (ret == 0 && GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) + ret = ASN_PARSE_E; + #ifndef NO_PKCS7_STREAM + pkcs7->stream->expected = length; + #endif + encodedAttribSz = length + (idx - encodedAttribIdx); + + if (ret != 0) + break; + + #ifndef NO_PKCS7_STREAM + if (encodedAttribSz > 0) { + pkcs7->stream->aadSz = encodedAttribSz; + pkcs7->stream->aad = (byte*)XMALLOC(encodedAttribSz, + pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (pkcs7->stream->aad == NULL) { + ret = MEMORY_E; + break; + } + else { + XMEMCPY(pkcs7->stream->aad, encodedAttribs, + (idx - encodedAttribIdx)); + } + } + + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { + break; + } + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_ATRB); + } + else { + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { + break; + } + #endif + goto authenv_atrbend; /* jump over attribute cases */ + } + FALL_THROUGH; + + case WC_PKCS7_AUTHENV_ATRB: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, + pkcs7->stream->expected, &pkiMsg, &idx)) != 0) { + return ret; + } + + length = pkcs7->stream->expected; + encodedAttribs = pkcs7->stream->aad; + #else + length = 0; + #endif + + /* save pointer and length */ + authAttrib = &pkiMsg[idx]; + authAttribSz = length; + + if (ret == 0 && wc_PKCS7_ParseAttribs(pkcs7, authAttrib, authAttribSz) < 0) { + WOLFSSL_MSG("Error parsing authenticated attributes"); + ret = ASN_PARSE_E; + break; + } + + idx += length; + + #ifndef NO_PKCS7_STREAM + if (encodedAttribSz > 0) { + XMEMCPY(pkcs7->stream->aad + (encodedAttribSz - length), + authAttrib, authAttribSz); + } + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { + break; + } + + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_ATRBEND); + FALL_THROUGH; + +authenv_atrbend: + case WC_PKCS7_AUTHENV_ATRBEND: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_LENGTH_SZ + + ASN_TAG_SZ, &pkiMsg, &idx)) != 0) { + return ret; + } + + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, + in, inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + + if (pkcs7->stream->aadSz > 0) { + encodedAttribSz = pkcs7->stream->aadSz; + encodedAttribs = pkcs7->stream->aad; + } + #endif + + + /* get authTag OCTET STRING */ + if (ret == 0 && pkiMsg[idx++] != ASN_OCTET_STRING) { + ret = ASN_PARSE_E; + } + + if (ret == 0 && GetLength(pkiMsg, &idx, &authTagSz, pkiMsgSz) < 0) { + ret = ASN_PARSE_E; + } + + if (ret == 0 && authTagSz > (int)sizeof(authTag)) { + WOLFSSL_MSG("AuthEnvelopedData authTag too large for buffer"); + ret = ASN_PARSE_E; + } + + if (ret == 0) { + XMEMCPY(authTag, &pkiMsg[idx], authTagSz); + idx += authTagSz; + } + + if (ret == 0 && authAttrib != NULL) { + /* temporarily swap authAttribs byte[0] to SET OF instead of + * IMPLICIT [1], for aad calculation */ + authAttribSetByte = encodedAttribs[0]; + + encodedAttribs[0] = ASN_SET | ASN_CONSTRUCTED; + } + + if (ret < 0) + break; + + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { + break; + } + pkcs7->stream->expected = (pkcs7->stream->maxLen - + pkcs7->stream->totalRd) + pkcs7->stream->length; + + + /* store tag for later */ + if (authTagSz > 0) { + pkcs7->stream->tagSz = authTagSz; + pkcs7->stream->tag = (byte*)XMALLOC(authTagSz, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (pkcs7->stream->tag == NULL) { + ret = MEMORY_E; + break; + } + else { + XMEMCPY(pkcs7->stream->tag, authTag, authTagSz); + } + } + + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_AUTHENV_6); + FALL_THROUGH; + + case WC_PKCS7_AUTHENV_6: + #ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, + pkcs7->stream->expected, &pkiMsg, &idx)) != 0) { + break; + } + + /* restore all variables needed */ + if (pkcs7->stream->nonceSz > 0) { + nonceSz = pkcs7->stream->nonceSz; + if (nonceSz > GCM_NONCE_MID_SZ) { + WOLFSSL_MSG("PKCS7 saved nonce is too large"); + ret = BUFFER_E; + break; + } + else { + XMEMCPY(nonce, pkcs7->stream->nonce, nonceSz); + } + } + + if (pkcs7->stream->tagSz > 0) { + authTagSz = pkcs7->stream->tagSz; + if (authTagSz > AES_BLOCK_SIZE) { + WOLFSSL_MSG("PKCS7 saved tag is too large"); + ret = BUFFER_E; + break; + } + else { + XMEMCPY(authTag, pkcs7->stream->tag, authTagSz); + } + } + + if (pkcs7->stream->aadSz > 0) { + encodedAttribSz = pkcs7->stream->aadSz; + encodedAttribs = pkcs7->stream->aad; + } + + wc_PKCS7_StreamGetVar(pkcs7, &encOID, &blockKeySz, &encryptedContentSz); + encryptedContent = pkcs7->stream->bufferPt; + #ifdef WOLFSSL_SMALL_STACK + decryptedKey = pkcs7->stream->key; + #endif + #endif + + /* decrypt encryptedContent */ + ret = wc_PKCS7_DecryptContent(encOID, decryptedKey, blockKeySz, + nonce, nonceSz, encodedAttribs, + encodedAttribSz, authTag, authTagSz, + encryptedContent, encryptedContentSz, + encryptedContent); + if (ret != 0) { + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + if (authAttrib != NULL) { + /* restore authAttrib IMPLICIT [1] */ + encodedAttribs[0] = authAttribSetByte; + } + + /* copy plaintext to output */ + XMEMCPY(output, encryptedContent, encryptedContentSz); + + /* free memory, zero out keys */ + ForceZero(encryptedContent, encryptedContentSz); + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + ForceZero(decryptedKey, MAX_ENCRYPTED_KEY_SZ); + #ifdef WOLFSSL_SMALL_STACK + XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + decryptedKey = NULL; + #ifdef WOLFSSL_SMALL_STACK + pkcs7->stream->key = NULL; + #endif + #endif + ret = encryptedContentSz; + #ifndef NO_PKCS7_STREAM + wc_PKCS7_ResetStream(pkcs7); + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START); + break; + default: + WOLFSSL_MSG("Unknown PKCS7 state"); + ret = BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + if (ret != 0 && ret != WC_PKCS7_WANT_READ_E) { + if (decryptedKey != NULL) { + ForceZero(decryptedKey, MAX_ENCRYPTED_KEY_SZ); + } + XFREE(decryptedKey, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + } +#endif +#ifndef NO_PKCS7_STREAM + if (ret != 0 && ret != WC_PKCS7_WANT_READ_E) { + wc_PKCS7_ResetStream(pkcs7); + } +#endif + + return ret; + +#else + WOLFSSL_MSG("AuthEnvelopedData requires AES-GCM or AES-CCM to be enabled"); + (void)pkcs7; + (void)in; + (void)inSz; + (void)output; + (void)outputSz; + + return NOT_COMPILED_IN; +#endif /* HAVE_AESGCM | HAVE_AESCCM */ +} + + +#ifndef NO_PKCS7_ENCRYPTED_DATA + +/* build PKCS#7 encryptedData content type, return encrypted size */ +int wc_PKCS7_EncodeEncryptedData(PKCS7* pkcs7, byte* output, word32 outputSz) +{ + int ret, idx = 0; + int totalSz, padSz, encryptedOutSz; + + int contentInfoSeqSz, outerContentTypeSz, outerContentSz; + byte contentInfoSeq[MAX_SEQ_SZ]; + byte outerContentType[MAX_ALGO_SZ]; + byte outerContent[MAX_SEQ_SZ]; + + int encDataSeqSz, verSz, blockSz; + byte encDataSeq[MAX_SEQ_SZ]; + byte ver[MAX_VERSION_SZ]; + + byte* plain = NULL; + byte* encryptedContent = NULL; + + int encContentOctetSz, encContentSeqSz, contentTypeSz; + int contentEncAlgoSz, ivOctetStringSz; + byte encContentSeq[MAX_SEQ_SZ]; + byte contentType[MAX_OID_SZ]; + byte contentEncAlgo[MAX_ALGO_SZ]; + byte tmpIv[MAX_CONTENT_IV_SIZE]; + byte ivOctetString[MAX_OCTET_STR_SZ]; + byte encContentOctet[MAX_OCTET_STR_SZ]; + + byte attribSet[MAX_SET_SZ]; + EncodedAttrib* attribs = NULL; + word32 attribsSz; + word32 attribsCount; + word32 attribsSetSz; + + byte* flatAttribs = NULL; + + if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0 || + pkcs7->encryptOID == 0 || pkcs7->encryptionKey == NULL || + pkcs7->encryptionKeySz == 0) + return BAD_FUNC_ARG; + + if (output == NULL || outputSz == 0) + return BAD_FUNC_ARG; + + if (pkcs7->version == 3) { + verSz = SetMyVersion(0, ver, 0); + outerContentTypeSz = 0; + } + else { + /* outer content type */ + ret = wc_SetContentType(ENCRYPTED_DATA, outerContentType, + sizeof(outerContentType)); + if (ret < 0) + return ret; + + outerContentTypeSz = ret; + + /* version, 2 if unprotectedAttrs present, 0 if absent */ + if (pkcs7->unprotectedAttribsSz > 0) { + verSz = SetMyVersion(2, ver, 0); + } else { + verSz = SetMyVersion(0, ver, 0); + } + } + + /* EncryptedContentInfo */ + ret = wc_SetContentType(pkcs7->contentOID, contentType, + sizeof(contentType)); + if (ret < 0) + return ret; + + contentTypeSz = ret; + + /* allocate encrypted content buffer, do PKCS#7 padding */ + blockSz = wc_PKCS7_GetOIDBlockSize(pkcs7->encryptOID); + if (blockSz < 0) + return blockSz; + + padSz = wc_PKCS7_GetPadSize(pkcs7->contentSz, blockSz); + if (padSz < 0) + return padSz; + + encryptedOutSz = pkcs7->contentSz + padSz; + + plain = (byte*)XMALLOC(encryptedOutSz, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (plain == NULL) + return MEMORY_E; + + ret = wc_PKCS7_PadData(pkcs7->content, pkcs7->contentSz, plain, + encryptedOutSz, blockSz); + if (ret < 0) { + XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + encryptedContent = (byte*)XMALLOC(encryptedOutSz, pkcs7->heap, + DYNAMIC_TYPE_PKCS7); + if (encryptedContent == NULL) { + XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } + + /* put together IV OCTET STRING */ + ivOctetStringSz = SetOctetString(blockSz, ivOctetString); + + /* build up ContentEncryptionAlgorithmIdentifier sequence, + adding (ivOctetStringSz + blockSz) for IV OCTET STRING */ + contentEncAlgoSz = SetAlgoID(pkcs7->encryptOID, contentEncAlgo, + oidBlkType, ivOctetStringSz + blockSz); + if (contentEncAlgoSz == 0) { + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return BAD_FUNC_ARG; + } + + /* encrypt content */ + WOLFSSL_MSG("Encrypting the content"); + ret = wc_PKCS7_GenerateBlock(pkcs7, NULL, tmpIv, blockSz); + if (ret != 0) { + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + ret = wc_PKCS7_EncryptContent(pkcs7->encryptOID, pkcs7->encryptionKey, + pkcs7->encryptionKeySz, tmpIv, blockSz, NULL, 0, NULL, 0, + plain, encryptedOutSz, encryptedContent); + if (ret != 0) { + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + encContentOctetSz = SetImplicit(ASN_OCTET_STRING, 0, + encryptedOutSz, encContentOctet); + + encContentSeqSz = SetSequence(contentTypeSz + contentEncAlgoSz + + ivOctetStringSz + blockSz + + encContentOctetSz + encryptedOutSz, + encContentSeq); + + /* optional UnprotectedAttributes */ + if (pkcs7->unprotectedAttribsSz != 0) { + + if (pkcs7->unprotectedAttribs == NULL) { + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return BAD_FUNC_ARG; + } + + attribs = (EncodedAttrib*)XMALLOC( + sizeof(EncodedAttrib) * pkcs7->unprotectedAttribsSz, + pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (attribs == NULL) { + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } + + attribsCount = pkcs7->unprotectedAttribsSz; + attribsSz = EncodeAttributes(attribs, pkcs7->unprotectedAttribsSz, + pkcs7->unprotectedAttribs, + pkcs7->unprotectedAttribsSz); + + flatAttribs = (byte*)XMALLOC(attribsSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (flatAttribs == NULL) { + XFREE(attribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return MEMORY_E; + } + + FlattenAttributes(pkcs7, flatAttribs, attribs, attribsCount); + attribsSetSz = SetImplicit(ASN_SET, 1, attribsSz, attribSet); + + } else { + attribsSz = 0; + attribsSetSz = 0; + } + + /* keep track of sizes for outer wrapper layering */ + totalSz = verSz + encContentSeqSz + contentTypeSz + contentEncAlgoSz + + ivOctetStringSz + blockSz + encContentOctetSz + encryptedOutSz + + attribsSz + attribsSetSz; + + /* EncryptedData */ + encDataSeqSz = SetSequence(totalSz, encDataSeq); + totalSz += encDataSeqSz; + + if (pkcs7->version != 3) { + /* outer content */ + outerContentSz = SetExplicit(0, totalSz, outerContent); + totalSz += outerContentTypeSz; + totalSz += outerContentSz; + /* ContentInfo */ + contentInfoSeqSz = SetSequence(totalSz, contentInfoSeq); + totalSz += contentInfoSeqSz; + } else { + contentInfoSeqSz = 0; + outerContentSz = 0; + } + + if (totalSz > (int)outputSz) { + WOLFSSL_MSG("PKCS#7 output buffer too small"); + if (pkcs7->unprotectedAttribsSz != 0) { + XFREE(attribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(flatAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + } + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return BUFFER_E; + } + + XMEMCPY(output + idx, contentInfoSeq, contentInfoSeqSz); + idx += contentInfoSeqSz; + XMEMCPY(output + idx, outerContentType, outerContentTypeSz); + idx += outerContentTypeSz; + XMEMCPY(output + idx, outerContent, outerContentSz); + idx += outerContentSz; + XMEMCPY(output + idx, encDataSeq, encDataSeqSz); + idx += encDataSeqSz; + XMEMCPY(output + idx, ver, verSz); + idx += verSz; + XMEMCPY(output + idx, encContentSeq, encContentSeqSz); + idx += encContentSeqSz; + XMEMCPY(output + idx, contentType, contentTypeSz); + idx += contentTypeSz; + XMEMCPY(output + idx, contentEncAlgo, contentEncAlgoSz); + idx += contentEncAlgoSz; + XMEMCPY(output + idx, ivOctetString, ivOctetStringSz); + idx += ivOctetStringSz; + XMEMCPY(output + idx, tmpIv, blockSz); + idx += blockSz; + XMEMCPY(output + idx, encContentOctet, encContentOctetSz); + idx += encContentOctetSz; + XMEMCPY(output + idx, encryptedContent, encryptedOutSz); + idx += encryptedOutSz; + + if (pkcs7->unprotectedAttribsSz != 0) { + XMEMCPY(output + idx, attribSet, attribsSetSz); + idx += attribsSetSz; + XMEMCPY(output + idx, flatAttribs, attribsSz); + idx += attribsSz; + XFREE(attribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(flatAttribs, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + } + + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + XFREE(plain, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + + return idx; +} + + +/* decode and store unprotected attributes in PKCS7->decodedAttrib. Return + * 0 on success, negative on error. User must call wc_PKCS7_Free(). */ +static int wc_PKCS7_DecodeUnprotectedAttributes(PKCS7* pkcs7, byte* pkiMsg, + word32 pkiMsgSz, word32* inOutIdx) +{ + int ret, attribLen; + word32 idx; + + if (pkcs7 == NULL || pkiMsg == NULL || + pkiMsgSz == 0 || inOutIdx == NULL) + return BAD_FUNC_ARG; + + idx = *inOutIdx; + + if (pkiMsg[idx] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 1)) + return ASN_PARSE_E; + idx++; + + if (GetLength(pkiMsg, &idx, &attribLen, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* loop through attributes */ + if ((ret = wc_PKCS7_ParseAttribs(pkcs7, pkiMsg + idx, attribLen)) < 0) { + return ret; + } + + *inOutIdx = idx; + + return 0; +} + + +/* unwrap and decrypt PKCS#7/CMS encrypted-data object, returned decoded size */ +int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* in, word32 inSz, + byte* output, word32 outputSz) +{ + int ret = 0, version, length = 0, haveAttribs = 0; + word32 idx = 0; + +#ifndef NO_PKCS7_STREAM + word32 tmpIdx = 0; + long rc; +#endif + word32 contentType, encOID; + + int expBlockSz = 0; + byte tmpIvBuf[MAX_CONTENT_IV_SIZE]; + byte *tmpIv = tmpIvBuf; + + int encryptedContentSz = 0; + byte padLen; + byte* encryptedContent = NULL; + + byte* pkiMsg = in; + word32 pkiMsgSz = inSz; + + if (pkcs7 == NULL || + ((pkcs7->encryptionKey == NULL || pkcs7->encryptionKeySz == 0) && + pkcs7->decryptionCb == NULL)) + return BAD_FUNC_ARG; + + if (pkiMsg == NULL || pkiMsgSz == 0 || + output == NULL || outputSz == 0) + return BAD_FUNC_ARG; + +#ifndef NO_PKCS7_STREAM + (void)tmpIv; /* help out static analysis */ + if (pkcs7->stream == NULL) { + if ((ret = wc_PKCS7_CreateStream(pkcs7)) != 0) { + return ret; + } + } +#endif + + switch (pkcs7->state) { + case WC_PKCS7_START: +#ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, MAX_SEQ_SZ + + MAX_ALGO_SZ, &pkiMsg, &idx)) != 0) { + return ret; + } + + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_SEQ_PEEK, in, inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; +#endif + + if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) + ret = ASN_PARSE_E; + + if (pkcs7->version != 3) { /* ContentInfo not in firmware bundles */ + /* read past ContentInfo, verify type is encrypted-data */ + if (ret == 0 && wc_GetContentType(pkiMsg, &idx, &contentType, + pkiMsgSz) < 0) + ret = ASN_PARSE_E; + + if (ret == 0 && contentType != ENCRYPTED_DATA) { + WOLFSSL_MSG("PKCS#7 input not of type EncryptedData"); + ret = PKCS7_OID_E; + } + } + if (ret != 0) break; +#ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { + break; + } +#endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_STAGE2); + FALL_THROUGH; + /* end of stage 1 */ + + case WC_PKCS7_STAGE2: +#ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, + MAX_LENGTH_SZ + MAX_SEQ_SZ + ASN_TAG_SZ, &pkiMsg, + &idx)) != 0) { + return ret; + } + + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, + inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; +#endif + if (pkcs7->version != 3) { + if (ret == 0 && pkiMsg[idx++] != (ASN_CONSTRUCTED | + ASN_CONTEXT_SPECIFIC | 0)) + ret = ASN_PARSE_E; + + if (ret == 0 && GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) + ret = ASN_PARSE_E; + + /* remove EncryptedData and version */ + if (ret == 0 && GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) + ret = ASN_PARSE_E; + } + + if (ret != 0) break; +#ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { + break; + } +#endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_STAGE3); + FALL_THROUGH; + /* end of stage 2 */ + + case WC_PKCS7_STAGE3: +#ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, + MAX_VERSION_SZ + MAX_SEQ_SZ + MAX_ALGO_SZ * 2, + &pkiMsg, &idx)) != 0) { + return ret; + } + + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, + inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; +#endif + /* get version, check later */ + haveAttribs = 0; + if (ret == 0 && GetMyVersion(pkiMsg, &idx, &version, pkiMsgSz) < 0) + ret = ASN_PARSE_E; + + /* remove EncryptedContentInfo */ + if (ret == 0 && GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) + ret = ASN_PARSE_E; + + if (ret == 0 && wc_GetContentType(pkiMsg, &idx, &contentType, + pkiMsgSz) < 0) + ret = ASN_PARSE_E; + + if (ret == 0 && (ret = GetAlgoId(pkiMsg, &idx, &encOID, oidBlkType, + pkiMsgSz)) < 0) + ret = ASN_PARSE_E; + if (ret == 0 && (expBlockSz = wc_PKCS7_GetOIDBlockSize(encOID)) < 0) + ret = expBlockSz; + + if (ret != 0) break; +#ifndef NO_PKCS7_STREAM + /* store expBlockSz for later */ + pkcs7->stream->varOne = expBlockSz; + pkcs7->stream->varTwo = encOID; + + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { + break; + } + + /* store version for later */ + pkcs7->stream->vers = version; +#endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_STAGE4); + FALL_THROUGH; + /* end of stage 3 */ + + /* get block cipher IV, stored in OPTIONAL parameter of AlgoID */ + case WC_PKCS7_STAGE4: +#ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, + ASN_TAG_SZ + MAX_LENGTH_SZ, &pkiMsg, &idx)) != 0) { + return ret; + } + + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, + inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + + /* restore saved variables */ + expBlockSz = pkcs7->stream->varOne; +#endif + if (ret == 0 && pkiMsg[idx++] != ASN_OCTET_STRING) + ret = ASN_PARSE_E; + + if (ret == 0 && GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) + ret = ASN_PARSE_E; + + if (ret == 0 && length != expBlockSz) { + WOLFSSL_MSG("Incorrect IV length, must be of content alg block size"); + ret = ASN_PARSE_E; + } + + if (ret != 0) break; +#ifndef NO_PKCS7_STREAM + /* next chunk of data expected should have the IV */ + pkcs7->stream->expected = length; + + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { + break; + } +#endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_STAGE5); + FALL_THROUGH; + /* end of stage 4 */ + + case WC_PKCS7_STAGE5: +#ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, + pkcs7->stream->expected + ASN_TAG_SZ + + MAX_LENGTH_SZ, &pkiMsg, &idx)) != 0) { + return ret; + } + + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, + inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + + /* use IV buffer from stream structure */ + tmpIv = pkcs7->stream->tmpIv; + length = pkcs7->stream->expected; +#endif + XMEMCPY(tmpIv, &pkiMsg[idx], length); + idx += length; + /* read encryptedContent, cont[0] */ + if (ret == 0 && pkiMsg[idx++] != (ASN_CONTEXT_SPECIFIC | 0)) + ret = ASN_PARSE_E; + + if (ret == 0 && GetLength(pkiMsg, &idx, &encryptedContentSz, + pkiMsgSz) <= 0) + ret = ASN_PARSE_E; + + if (ret < 0) + break; +#ifndef NO_PKCS7_STREAM + /* next chunk of data should contain encrypted content */ + pkcs7->stream->varThree = encryptedContentSz; + if ((ret = wc_PKCS7_StreamEndCase(pkcs7, &tmpIdx, &idx)) != 0) { + break; + } + + if (pkcs7->stream->totalRd + encryptedContentSz < pkiMsgSz) { + pkcs7->stream->flagOne = 1; + } + + pkcs7->stream->expected = (pkcs7->stream->maxLen - + pkcs7->stream->totalRd) + pkcs7->stream->length; + +#endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_STAGE6); + FALL_THROUGH; + /* end of stage 5 */ + + case WC_PKCS7_STAGE6: +#ifndef NO_PKCS7_STREAM + if ((ret = wc_PKCS7_AddDataToStream(pkcs7, in, inSz, + pkcs7->stream->expected, &pkiMsg, &idx)) != 0) { + return ret; + } + + rc = wc_PKCS7_GetMaxStream(pkcs7, PKCS7_DEFAULT_PEEK, in, + inSz); + if (rc < 0) { + ret = (int)rc; + break; + } + pkiMsgSz = (word32)rc; + + /* restore saved variables */ + expBlockSz = pkcs7->stream->varOne; + encOID = pkcs7->stream->varTwo; + encryptedContentSz = pkcs7->stream->varThree; + version = pkcs7->stream->vers; + tmpIv = pkcs7->stream->tmpIv; +#else + encOID = 0; +#endif + if (ret == 0 && (encryptedContent = (byte*)XMALLOC( + encryptedContentSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7)) == NULL) { + ret = MEMORY_E; + break; + } + + if (ret == 0) { + XMEMCPY(encryptedContent, &pkiMsg[idx], encryptedContentSz); + idx += encryptedContentSz; + } + + /* decrypt encryptedContent */ + if (ret == 0) { + if (pkcs7->decryptionCb != NULL) { + ret = pkcs7->decryptionCb(pkcs7, encOID, tmpIv, expBlockSz, + NULL, 0, NULL, 0, encryptedContent, + encryptedContentSz, encryptedContent, + pkcs7->decryptionCtx); + } + else { + ret = wc_PKCS7_DecryptContent(encOID, pkcs7->encryptionKey, + pkcs7->encryptionKeySz, tmpIv, expBlockSz, + NULL, 0, NULL, 0, encryptedContent, + encryptedContentSz, encryptedContent); + } + if (ret != 0) { + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + } + } + + if (ret == 0) { + padLen = encryptedContent[encryptedContentSz-1]; + + if (padLen > encryptedContentSz) { + WOLFSSL_MSG("Bad padding size found"); + ret = BUFFER_E; + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + break; + } + + /* copy plaintext to output */ + XMEMCPY(output, encryptedContent, encryptedContentSz - padLen); + + /* get implicit[1] unprotected attributes, optional */ + wc_PKCS7_FreeDecodedAttrib(pkcs7->decodedAttrib, pkcs7->heap); + pkcs7->decodedAttrib = NULL; + #ifndef NO_PKCS7_STREAM + if (pkcs7->stream->flagOne) + #else + if (idx < pkiMsgSz) + #endif + { + haveAttribs = 1; + + ret = wc_PKCS7_DecodeUnprotectedAttributes(pkcs7, pkiMsg, + pkiMsgSz, &idx); + if (ret != 0) { + ForceZero(encryptedContent, encryptedContentSz); + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + ret = ASN_PARSE_E; + } + } + } + + if (ret == 0) { + ForceZero(encryptedContent, encryptedContentSz); + XFREE(encryptedContent, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + + /* go back and check the version now that attribs have been processed */ + if (pkcs7->version == 3 && version != 0) { + WOLFSSL_MSG("Wrong PKCS#7 FirmwareEncryptedData version"); + return ASN_VERSION_E; + } + + if (pkcs7->version != 3 && + ((haveAttribs == 0 && version != 0) || + (haveAttribs == 1 && version != 2))) { + WOLFSSL_MSG("Wrong PKCS#7 EncryptedData version"); + return ASN_VERSION_E; + } + ret = encryptedContentSz - padLen; + } + + if (ret != 0) break; + #ifndef NO_PKCS7_STREAM + wc_PKCS7_ResetStream(pkcs7); + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START); + break; + + default: + WOLFSSL_MSG("Error in unknown PKCS#7 Decode Encrypted Data state"); + return BAD_STATE_E; + } + + if (ret != 0) { + #ifndef NO_PKCS7_STREAM + /* restart in error case */ + wc_PKCS7_ResetStream(pkcs7); + #endif + wc_PKCS7_ChangeState(pkcs7, WC_PKCS7_START); + } + return ret; +} + + +/* Function to set callback during decryption, this overrides the default + * decryption function and can be used for choosing a key at run time based + * on the parsed bundle so far. + * returns 0 on success + */ +int wc_PKCS7_SetDecodeEncryptedCb(PKCS7* pkcs7, + CallbackDecryptContent decryptionCb) +{ + if (pkcs7 != NULL) { + pkcs7->decryptionCb = decryptionCb; + } + return 0; +} + + +/* Set an optional user context that gets passed to callback + * returns 0 on success + */ +int wc_PKCS7_SetDecodeEncryptedCtx(PKCS7* pkcs7, void* ctx) +{ + if (pkcs7 != NULL) { + pkcs7->decryptionCtx = ctx; + } + return 0; +} +#endif /* NO_PKCS7_ENCRYPTED_DATA */ + +#if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA) + +/* build PKCS#7 compressedData content type, return encrypted size */ +int wc_PKCS7_EncodeCompressedData(PKCS7* pkcs7, byte* output, word32 outputSz) +{ + byte contentInfoSeq[MAX_SEQ_SZ]; + byte contentInfoTypeOid[MAX_OID_SZ]; + byte contentInfoContentSeq[MAX_SEQ_SZ]; /* EXPLICIT [0] */ + byte compressedDataSeq[MAX_SEQ_SZ]; + byte cmsVersion[MAX_VERSION_SZ]; + byte compressAlgId[MAX_ALGO_SZ]; + byte encapContentInfoSeq[MAX_SEQ_SZ]; + byte contentTypeOid[MAX_OID_SZ]; + byte contentSeq[MAX_SEQ_SZ]; /* EXPLICIT [0] */ + byte contentOctetStr[MAX_OCTET_STR_SZ]; + + int ret; + word32 totalSz, idx; + word32 contentInfoSeqSz, contentInfoContentSeqSz, contentInfoTypeOidSz; + word32 compressedDataSeqSz, cmsVersionSz, compressAlgIdSz; + word32 encapContentInfoSeqSz, contentTypeOidSz, contentSeqSz; + word32 contentOctetStrSz; + + byte* compressed; + word32 compressedSz; + + if (pkcs7 == NULL || pkcs7->content == NULL || pkcs7->contentSz == 0 || + output == NULL || outputSz == 0) { + return BAD_FUNC_ARG; + } + + /* allocate space for compressed content. The libz code says the compressed + * buffer should be srcSz + 0.1% + 12. */ + compressedSz = (pkcs7->contentSz + (word32)(pkcs7->contentSz * 0.001) + 12); + compressed = (byte*)XMALLOC(compressedSz, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (compressed == NULL) { + WOLFSSL_MSG("Error allocating memory for CMS compressed content"); + return MEMORY_E; + } + + /* compress content */ + ret = wc_Compress(compressed, compressedSz, pkcs7->content, + pkcs7->contentSz, 0); + if (ret < 0) { + XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + compressedSz = (word32)ret; + + /* eContent OCTET STRING, working backwards */ + contentOctetStrSz = SetOctetString(compressedSz, contentOctetStr); + totalSz = contentOctetStrSz + compressedSz; + + /* EXPLICIT [0] eContentType */ + contentSeqSz = SetExplicit(0, totalSz, contentSeq); + totalSz += contentSeqSz; + + /* eContentType OBJECT IDENTIFIER */ + ret = wc_SetContentType(pkcs7->contentOID, contentTypeOid, + sizeof(contentTypeOid)); + if (ret < 0) { + XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + contentTypeOidSz = ret; + totalSz += contentTypeOidSz; + + /* EncapsulatedContentInfo SEQUENCE */ + encapContentInfoSeqSz = SetSequence(totalSz, encapContentInfoSeq); + totalSz += encapContentInfoSeqSz; + + /* compressionAlgorithm AlgorithmIdentifier */ + /* Only supports zlib for compression currently: + * id-alg-zlibCompress (1.2.840.113549.1.9.16.3.8) */ + compressAlgIdSz = SetAlgoID(ZLIBc, compressAlgId, oidCompressType, 0); + totalSz += compressAlgIdSz; + + /* version */ + cmsVersionSz = SetMyVersion(0, cmsVersion, 0); + totalSz += cmsVersionSz; + + /* CompressedData SEQUENCE */ + compressedDataSeqSz = SetSequence(totalSz, compressedDataSeq); + totalSz += compressedDataSeqSz; + + /* ContentInfo content EXPLICIT SEQUENCE */ + contentInfoContentSeqSz = SetExplicit(0, totalSz, contentInfoContentSeq); + totalSz += contentInfoContentSeqSz; + + /* ContentInfo ContentType (compressedData) */ + if (pkcs7->version == 3) { + contentInfoTypeOidSz = 0; + } + else { + ret = wc_SetContentType(COMPRESSED_DATA, contentInfoTypeOid, + sizeof(contentInfoTypeOid)); + if (ret < 0) { + XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + + contentInfoTypeOidSz = ret; + totalSz += contentInfoTypeOidSz; + } + + /* ContentInfo SEQUENCE */ + contentInfoSeqSz = SetSequence(totalSz, contentInfoSeq); + totalSz += contentInfoSeqSz; + + if (outputSz < totalSz) { + XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return BUFFER_E; + } + + idx = 0; + XMEMCPY(output + idx, contentInfoSeq, contentInfoSeqSz); + idx += contentInfoSeqSz; + XMEMCPY(output + idx, contentInfoTypeOid, contentInfoTypeOidSz); + idx += contentInfoTypeOidSz; + XMEMCPY(output + idx, contentInfoContentSeq, contentInfoContentSeqSz); + idx += contentInfoContentSeqSz; + XMEMCPY(output + idx, compressedDataSeq, compressedDataSeqSz); + idx += compressedDataSeqSz; + XMEMCPY(output + idx, cmsVersion, cmsVersionSz); + idx += cmsVersionSz; + XMEMCPY(output + idx, compressAlgId, compressAlgIdSz); + idx += compressAlgIdSz; + XMEMCPY(output + idx, encapContentInfoSeq, encapContentInfoSeqSz); + idx += encapContentInfoSeqSz; + XMEMCPY(output + idx, contentTypeOid, contentTypeOidSz); + idx += contentTypeOidSz; + XMEMCPY(output + idx, contentSeq, contentSeqSz); + idx += contentSeqSz; + XMEMCPY(output + idx, contentOctetStr, contentOctetStrSz); + idx += contentOctetStrSz; + XMEMCPY(output + idx, compressed, compressedSz); + idx += compressedSz; + + XFREE(compressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + + return idx; +} + +/* unwrap and decompress PKCS#7/CMS compressedData object, + * returned decoded size */ +int wc_PKCS7_DecodeCompressedData(PKCS7* pkcs7, byte* pkiMsg, word32 pkiMsgSz, + byte* output, word32 outputSz) +{ + int length, version, ret; + word32 idx = 0, algOID, contentType; + + byte* decompressed; + word32 decompressedSz; + + if (pkcs7 == NULL || pkiMsg == NULL || pkiMsgSz == 0 || + output == NULL || outputSz == 0) { + return BAD_FUNC_ARG; + } + + /* get ContentInfo SEQUENCE */ + if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (pkcs7->version != 3) { + /* get ContentInfo contentType */ + if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (contentType != COMPRESSED_DATA) + return ASN_PARSE_E; + } + + /* get ContentInfo content EXPLICIT SEQUENCE */ + if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) + return ASN_PARSE_E; + + if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* get CompressedData SEQUENCE */ + if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* get version */ + if (GetMyVersion(pkiMsg, &idx, &version, pkiMsgSz) < 0) + return ASN_PARSE_E; + + if (version != 0) { + WOLFSSL_MSG("CMS CompressedData version MUST be 0, but is not"); + return ASN_PARSE_E; + } + + /* get CompressionAlgorithmIdentifier */ + if (GetAlgoId(pkiMsg, &idx, &algOID, oidIgnoreType, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* Only supports zlib for compression currently: + * id-alg-zlibCompress (1.2.840.113549.1.9.16.3.8) */ + if (algOID != ZLIBc) { + WOLFSSL_MSG("CMS CompressedData only supports zlib algorithm"); + return ASN_PARSE_E; + } + + /* get EncapsulatedContentInfo SEQUENCE */ + if (GetSequence(pkiMsg, &idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* get ContentType OID */ + if (wc_GetContentType(pkiMsg, &idx, &contentType, pkiMsgSz) < 0) + return ASN_PARSE_E; + + pkcs7->contentOID = contentType; + + /* get eContent EXPLICIT SEQUENCE */ + if (pkiMsg[idx++] != (ASN_CONSTRUCTED | ASN_CONTEXT_SPECIFIC | 0)) + return ASN_PARSE_E; + + if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* get content OCTET STRING */ + if (pkiMsg[idx++] != ASN_OCTET_STRING) + return ASN_PARSE_E; + + if (GetLength(pkiMsg, &idx, &length, pkiMsgSz) < 0) + return ASN_PARSE_E; + + /* allocate space for decompressed data */ + decompressed = (byte*)XMALLOC(length, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + if (decompressed == NULL) { + WOLFSSL_MSG("Error allocating memory for CMS decompression buffer"); + return MEMORY_E; + } + + /* decompress content */ + ret = wc_DeCompress(decompressed, length, &pkiMsg[idx], length); + if (ret < 0) { + XFREE(decompressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return ret; + } + decompressedSz = (word32)ret; + + /* get content */ + if (outputSz < decompressedSz) { + WOLFSSL_MSG("CMS output buffer too small to hold decompressed data"); + XFREE(decompressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + return BUFFER_E; + } + + XMEMCPY(output, decompressed, decompressedSz); + XFREE(decompressed, pkcs7->heap, DYNAMIC_TYPE_PKCS7); + + return decompressedSz; +} + +#endif /* HAVE_LIBZ && !NO_PKCS7_COMPRESSED_DATA */ + +#else /* HAVE_PKCS7 */ + + +#ifdef _MSC_VER + /* 4206 warning for blank file */ + #pragma warning(disable: 4206) +#endif + + +#endif /* HAVE_PKCS7 */ + diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/poly1305.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/poly1305.c new file mode 100755 index 0000000..b3a4752 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/poly1305.c @@ -0,0 +1,823 @@ +/* poly1305.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/* + * Based off the public domain implementations by Andrew Moon + * and Daniel J. Bernstein + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifdef HAVE_POLY1305 +#include +#include +#include +#include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif +#ifdef CHACHA_AEAD_TEST + #include +#endif + +#ifdef _MSC_VER + /* 4127 warning constant while(1) */ + #pragma warning(disable: 4127) +#endif + +#ifdef USE_INTEL_SPEEDUP + #include + #include + + #if defined(__GNUC__) && ((__GNUC__ < 4) || \ + (__GNUC__ == 4 && __GNUC_MINOR__ <= 8)) + #undef NO_AVX2_SUPPORT + #define NO_AVX2_SUPPORT + #endif + #if defined(__clang__) && ((__clang_major__ < 3) || \ + (__clang_major__ == 3 && __clang_minor__ <= 5)) + #define NO_AVX2_SUPPORT + #elif defined(__clang__) && defined(NO_AVX2_SUPPORT) + #undef NO_AVX2_SUPPORT + #endif + + #define HAVE_INTEL_AVX1 + #ifndef NO_AVX2_SUPPORT + #define HAVE_INTEL_AVX2 + #endif +#endif + +#ifdef USE_INTEL_SPEEDUP +static word32 intel_flags = 0; +static word32 cpu_flags_set = 0; +#endif + +#if defined(USE_INTEL_SPEEDUP) || defined(POLY130564) + #if defined(_MSC_VER) + #define POLY1305_NOINLINE __declspec(noinline) + #elif defined(__GNUC__) + #define POLY1305_NOINLINE __attribute__((noinline)) + #else + #define POLY1305_NOINLINE + #endif + + #if defined(_MSC_VER) + #include + + typedef struct word128 { + word64 lo; + word64 hi; + } word128; + + #define MUL(out, x, y) out.lo = _umul128((x), (y), &out.hi) + #define ADD(out, in) { word64 t = out.lo; out.lo += in.lo; \ + out.hi += (out.lo < t) + in.hi; } + #define ADDLO(out, in) { word64 t = out.lo; out.lo += in; \ + out.hi += (out.lo < t); } + #define SHR(in, shift) (__shiftright128(in.lo, in.hi, (shift))) + #define LO(in) (in.lo) + + #elif defined(__GNUC__) + #if defined(__SIZEOF_INT128__) + typedef unsigned __int128 word128; + #else + typedef unsigned word128 __attribute__((mode(TI))); + #endif + + #define MUL(out, x, y) out = ((word128)x * y) + #define ADD(out, in) out += in + #define ADDLO(out, in) out += in + #define SHR(in, shift) (word64)(in >> (shift)) + #define LO(in) (word64)(in) + #endif +#endif + +#ifdef USE_INTEL_SPEEDUP +#ifdef __cplusplus + extern "C" { +#endif + +#ifdef HAVE_INTEL_AVX1 +/* Process one block (16 bytes) of data. + * + * ctx Poly1305 context. + * m One block of message data. + */ +extern void poly1305_block_avx(Poly1305* ctx, const unsigned char *m); +/* Process multiple blocks (n * 16 bytes) of data. + * + * ctx Poly1305 context. + * m Blocks of message data. + * bytes The number of bytes to process. + */ +extern void poly1305_blocks_avx(Poly1305* ctx, const unsigned char* m, + size_t bytes); +/* Set the key to use when processing data. + * Initialize the context. + * + * ctx Poly1305 context. + * key The key data (16 bytes). + */ +extern void poly1305_setkey_avx(Poly1305* ctx, const byte* key); +/* Calculate the final result - authentication data. + * Zeros out the private data in the context. + * + * ctx Poly1305 context. + * mac Buffer to hold 16 bytes. + */ +extern void poly1305_final_avx(Poly1305* ctx, byte* mac); +#endif + +#ifdef HAVE_INTEL_AVX2 +/* Process multiple blocks (n * 16 bytes) of data. + * + * ctx Poly1305 context. + * m Blocks of message data. + * bytes The number of bytes to process. + */ +extern void poly1305_blocks_avx2(Poly1305* ctx, const unsigned char* m, + size_t bytes); +/* Calculate R^1, R^2, R^3 and R^4 and store them in the context. + * + * ctx Poly1305 context. + */ +extern void poly1305_calc_powers_avx2(Poly1305* ctx); +/* Set the key to use when processing data. + * Initialize the context. + * Calls AVX set key function as final function calls AVX code. + * + * ctx Poly1305 context. + * key The key data (16 bytes). + */ +extern void poly1305_setkey_avx2(Poly1305* ctx, const byte* key); +/* Calculate the final result - authentication data. + * Zeros out the private data in the context. + * Calls AVX final function to quickly process last blocks. + * + * ctx Poly1305 context. + * mac Buffer to hold 16 bytes - authentication data. + */ +extern void poly1305_final_avx2(Poly1305* ctx, byte* mac); +#endif + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#elif defined(POLY130564) +#ifndef WOLFSSL_ARMASM + static word64 U8TO64(const byte* p) + { + return + (((word64)(p[0] & 0xff) ) | + ((word64)(p[1] & 0xff) << 8) | + ((word64)(p[2] & 0xff) << 16) | + ((word64)(p[3] & 0xff) << 24) | + ((word64)(p[4] & 0xff) << 32) | + ((word64)(p[5] & 0xff) << 40) | + ((word64)(p[6] & 0xff) << 48) | + ((word64)(p[7] & 0xff) << 56)); + } + + static void U64TO8(byte* p, word64 v) { + p[0] = (v ) & 0xff; + p[1] = (v >> 8) & 0xff; + p[2] = (v >> 16) & 0xff; + p[3] = (v >> 24) & 0xff; + p[4] = (v >> 32) & 0xff; + p[5] = (v >> 40) & 0xff; + p[6] = (v >> 48) & 0xff; + p[7] = (v >> 56) & 0xff; + } +#endif/* WOLFSSL_ARMASM */ +#else /* if not 64 bit then use 32 bit */ + + static word32 U8TO32(const byte *p) + { + return + (((word32)(p[0] & 0xff) ) | + ((word32)(p[1] & 0xff) << 8) | + ((word32)(p[2] & 0xff) << 16) | + ((word32)(p[3] & 0xff) << 24)); + } + + static void U32TO8(byte *p, word32 v) { + p[0] = (v ) & 0xff; + p[1] = (v >> 8) & 0xff; + p[2] = (v >> 16) & 0xff; + p[3] = (v >> 24) & 0xff; + } +#endif + + +static void U32TO64(word32 v, byte* p) +{ + XMEMSET(p, 0, 8); + p[0] = (v & 0xFF); + p[1] = (v >> 8) & 0xFF; + p[2] = (v >> 16) & 0xFF; + p[3] = (v >> 24) & 0xFF; +} + +#if !defined(WOLFSSL_ARMASM) || !defined(__aarch64__) +void poly1305_blocks(Poly1305* ctx, const unsigned char *m, + size_t bytes) +{ +#ifdef USE_INTEL_SPEEDUP + /* AVX2 is handled in wc_Poly1305Update. */ + poly1305_blocks_avx(ctx, m, bytes); +#elif defined(POLY130564) + const word64 hibit = (ctx->finished) ? 0 : ((word64)1 << 40); /* 1 << 128 */ + word64 r0,r1,r2; + word64 s1,s2; + word64 h0,h1,h2; + word64 c; + word128 d0,d1,d2,d; + + r0 = ctx->r[0]; + r1 = ctx->r[1]; + r2 = ctx->r[2]; + + h0 = ctx->h[0]; + h1 = ctx->h[1]; + h2 = ctx->h[2]; + + s1 = r1 * (5 << 2); + s2 = r2 * (5 << 2); + + while (bytes >= POLY1305_BLOCK_SIZE) { + word64 t0,t1; + + /* h += m[i] */ + t0 = U8TO64(&m[0]); + t1 = U8TO64(&m[8]); + + h0 += (( t0 ) & 0xfffffffffff); + h1 += (((t0 >> 44) | (t1 << 20)) & 0xfffffffffff); + h2 += (((t1 >> 24) ) & 0x3ffffffffff) | hibit; + + /* h *= r */ + MUL(d0, h0, r0); MUL(d, h1, s2); ADD(d0, d); MUL(d, h2, s1); ADD(d0, d); + MUL(d1, h0, r1); MUL(d, h1, r0); ADD(d1, d); MUL(d, h2, s2); ADD(d1, d); + MUL(d2, h0, r2); MUL(d, h1, r1); ADD(d2, d); MUL(d, h2, r0); ADD(d2, d); + + /* (partial) h %= p */ + c = SHR(d0, 44); h0 = LO(d0) & 0xfffffffffff; + ADDLO(d1, c); c = SHR(d1, 44); h1 = LO(d1) & 0xfffffffffff; + ADDLO(d2, c); c = SHR(d2, 42); h2 = LO(d2) & 0x3ffffffffff; + h0 += c * 5; c = (h0 >> 44); h0 = h0 & 0xfffffffffff; + h1 += c; + + m += POLY1305_BLOCK_SIZE; + bytes -= POLY1305_BLOCK_SIZE; + } + + ctx->h[0] = h0; + ctx->h[1] = h1; + ctx->h[2] = h2; + +#else /* if not 64 bit then use 32 bit */ + const word32 hibit = (ctx->finished) ? 0 : ((word32)1 << 24); /* 1 << 128 */ + word32 r0,r1,r2,r3,r4; + word32 s1,s2,s3,s4; + word32 h0,h1,h2,h3,h4; + word64 d0,d1,d2,d3,d4; + word32 c; + + + r0 = ctx->r[0]; + r1 = ctx->r[1]; + r2 = ctx->r[2]; + r3 = ctx->r[3]; + r4 = ctx->r[4]; + + s1 = r1 * 5; + s2 = r2 * 5; + s3 = r3 * 5; + s4 = r4 * 5; + + h0 = ctx->h[0]; + h1 = ctx->h[1]; + h2 = ctx->h[2]; + h3 = ctx->h[3]; + h4 = ctx->h[4]; + + while (bytes >= POLY1305_BLOCK_SIZE) { + /* h += m[i] */ + h0 += (U8TO32(m+ 0) ) & 0x3ffffff; + h1 += (U8TO32(m+ 3) >> 2) & 0x3ffffff; + h2 += (U8TO32(m+ 6) >> 4) & 0x3ffffff; + h3 += (U8TO32(m+ 9) >> 6) & 0x3ffffff; + h4 += (U8TO32(m+12) >> 8) | hibit; + + /* h *= r */ + d0 = ((word64)h0 * r0) + ((word64)h1 * s4) + ((word64)h2 * s3) + + ((word64)h3 * s2) + ((word64)h4 * s1); + d1 = ((word64)h0 * r1) + ((word64)h1 * r0) + ((word64)h2 * s4) + + ((word64)h3 * s3) + ((word64)h4 * s2); + d2 = ((word64)h0 * r2) + ((word64)h1 * r1) + ((word64)h2 * r0) + + ((word64)h3 * s4) + ((word64)h4 * s3); + d3 = ((word64)h0 * r3) + ((word64)h1 * r2) + ((word64)h2 * r1) + + ((word64)h3 * r0) + ((word64)h4 * s4); + d4 = ((word64)h0 * r4) + ((word64)h1 * r3) + ((word64)h2 * r2) + + ((word64)h3 * r1) + ((word64)h4 * r0); + + /* (partial) h %= p */ + c = (word32)(d0 >> 26); h0 = (word32)d0 & 0x3ffffff; + d1 += c; c = (word32)(d1 >> 26); h1 = (word32)d1 & 0x3ffffff; + d2 += c; c = (word32)(d2 >> 26); h2 = (word32)d2 & 0x3ffffff; + d3 += c; c = (word32)(d3 >> 26); h3 = (word32)d3 & 0x3ffffff; + d4 += c; c = (word32)(d4 >> 26); h4 = (word32)d4 & 0x3ffffff; + h0 += c * 5; c = (h0 >> 26); h0 = h0 & 0x3ffffff; + h1 += c; + + m += POLY1305_BLOCK_SIZE; + bytes -= POLY1305_BLOCK_SIZE; + } + + ctx->h[0] = h0; + ctx->h[1] = h1; + ctx->h[2] = h2; + ctx->h[3] = h3; + ctx->h[4] = h4; + +#endif /* end of 64 bit cpu blocks or 32 bit cpu */ +} + +void poly1305_block(Poly1305* ctx, const unsigned char *m) +{ +#ifdef USE_INTEL_SPEEDUP + /* No call to poly1305_block when AVX2, AVX2 does 4 blocks at a time. */ + poly1305_block_avx(ctx, m); +#else + poly1305_blocks(ctx, m, POLY1305_BLOCK_SIZE); +#endif +} +#endif /* !defined(WOLFSSL_ARMASM) || !defined(__aarch64__) */ + +#if !defined(WOLFSSL_ARMASM) || !defined(__aarch64__) +int wc_Poly1305SetKey(Poly1305* ctx, const byte* key, word32 keySz) +{ +#if defined(POLY130564) + word64 t0,t1; +#endif + + if (key == NULL) + return BAD_FUNC_ARG; + +#ifdef CHACHA_AEAD_TEST + word32 k; + printf("Poly key used:\n"); + for (k = 0; k < keySz; k++) { + printf("%02x", key[k]); + if ((k+1) % 8 == 0) + printf("\n"); + } + printf("\n"); +#endif + + if (keySz != 32 || ctx == NULL) + return BAD_FUNC_ARG; + +#ifdef USE_INTEL_SPEEDUP + if (!cpu_flags_set) { + intel_flags = cpuid_get_flags(); + cpu_flags_set = 1; + } + #ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_AVX2(intel_flags)) + poly1305_setkey_avx2(ctx, key); + else + #endif + poly1305_setkey_avx(ctx, key); +#elif defined(POLY130564) + + /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */ + t0 = U8TO64(key + 0); + t1 = U8TO64(key + 8); + + ctx->r[0] = ( t0 ) & 0xffc0fffffff; + ctx->r[1] = ((t0 >> 44) | (t1 << 20)) & 0xfffffc0ffff; + ctx->r[2] = ((t1 >> 24) ) & 0x00ffffffc0f; + + /* h (accumulator) = 0 */ + ctx->h[0] = 0; + ctx->h[1] = 0; + ctx->h[2] = 0; + + /* save pad for later */ + ctx->pad[0] = U8TO64(key + 16); + ctx->pad[1] = U8TO64(key + 24); + + ctx->leftover = 0; + ctx->finished = 0; + +#else /* if not 64 bit then use 32 bit */ + + /* r &= 0xffffffc0ffffffc0ffffffc0fffffff */ + ctx->r[0] = (U8TO32(key + 0) ) & 0x3ffffff; + ctx->r[1] = (U8TO32(key + 3) >> 2) & 0x3ffff03; + ctx->r[2] = (U8TO32(key + 6) >> 4) & 0x3ffc0ff; + ctx->r[3] = (U8TO32(key + 9) >> 6) & 0x3f03fff; + ctx->r[4] = (U8TO32(key + 12) >> 8) & 0x00fffff; + + /* h = 0 */ + ctx->h[0] = 0; + ctx->h[1] = 0; + ctx->h[2] = 0; + ctx->h[3] = 0; + ctx->h[4] = 0; + + /* save pad for later */ + ctx->pad[0] = U8TO32(key + 16); + ctx->pad[1] = U8TO32(key + 20); + ctx->pad[2] = U8TO32(key + 24); + ctx->pad[3] = U8TO32(key + 28); + + ctx->leftover = 0; + ctx->finished = 0; + +#endif + + return 0; +} + +int wc_Poly1305Final(Poly1305* ctx, byte* mac) +{ +#ifdef USE_INTEL_SPEEDUP +#elif defined(POLY130564) + + word64 h0,h1,h2,c; + word64 g0,g1,g2; + word64 t0,t1; + +#else + + word32 h0,h1,h2,h3,h4,c; + word32 g0,g1,g2,g3,g4; + word64 f; + word32 mask; + +#endif + + if (ctx == NULL) + return BAD_FUNC_ARG; + +#ifdef USE_INTEL_SPEEDUP + #ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_AVX2(intel_flags)) + poly1305_final_avx2(ctx, mac); + else + #endif + poly1305_final_avx(ctx, mac); +#elif defined(POLY130564) + + /* process the remaining block */ + if (ctx->leftover) { + size_t i = ctx->leftover; + ctx->buffer[i] = 1; + for (i = i + 1; i < POLY1305_BLOCK_SIZE; i++) + ctx->buffer[i] = 0; + ctx->finished = 1; + poly1305_block(ctx, ctx->buffer); + } + + /* fully carry h */ + h0 = ctx->h[0]; + h1 = ctx->h[1]; + h2 = ctx->h[2]; + + c = (h1 >> 44); h1 &= 0xfffffffffff; + h2 += c; c = (h2 >> 42); h2 &= 0x3ffffffffff; + h0 += c * 5; c = (h0 >> 44); h0 &= 0xfffffffffff; + h1 += c; c = (h1 >> 44); h1 &= 0xfffffffffff; + h2 += c; c = (h2 >> 42); h2 &= 0x3ffffffffff; + h0 += c * 5; c = (h0 >> 44); h0 &= 0xfffffffffff; + h1 += c; + + /* compute h + -p */ + g0 = h0 + 5; c = (g0 >> 44); g0 &= 0xfffffffffff; + g1 = h1 + c; c = (g1 >> 44); g1 &= 0xfffffffffff; + g2 = h2 + c - ((word64)1 << 42); + + /* select h if h < p, or h + -p if h >= p */ + c = (g2 >> ((sizeof(word64) * 8) - 1)) - 1; + g0 &= c; + g1 &= c; + g2 &= c; + c = ~c; + h0 = (h0 & c) | g0; + h1 = (h1 & c) | g1; + h2 = (h2 & c) | g2; + + /* h = (h + pad) */ + t0 = ctx->pad[0]; + t1 = ctx->pad[1]; + + h0 += (( t0 ) & 0xfffffffffff) ; + c = (h0 >> 44); h0 &= 0xfffffffffff; + h1 += (((t0 >> 44) | (t1 << 20)) & 0xfffffffffff) + c; + c = (h1 >> 44); h1 &= 0xfffffffffff; + h2 += (((t1 >> 24) ) & 0x3ffffffffff) + c; + h2 &= 0x3ffffffffff; + + /* mac = h % (2^128) */ + h0 = ((h0 ) | (h1 << 44)); + h1 = ((h1 >> 20) | (h2 << 24)); + + U64TO8(mac + 0, h0); + U64TO8(mac + 8, h1); + + /* zero out the state */ + ctx->h[0] = 0; + ctx->h[1] = 0; + ctx->h[2] = 0; + ctx->r[0] = 0; + ctx->r[1] = 0; + ctx->r[2] = 0; + ctx->pad[0] = 0; + ctx->pad[1] = 0; + +#else /* if not 64 bit then use 32 bit */ + + /* process the remaining block */ + if (ctx->leftover) { + size_t i = ctx->leftover; + ctx->buffer[i++] = 1; + for (; i < POLY1305_BLOCK_SIZE; i++) + ctx->buffer[i] = 0; + ctx->finished = 1; + poly1305_block(ctx, ctx->buffer); + } + + /* fully carry h */ + h0 = ctx->h[0]; + h1 = ctx->h[1]; + h2 = ctx->h[2]; + h3 = ctx->h[3]; + h4 = ctx->h[4]; + + c = h1 >> 26; h1 = h1 & 0x3ffffff; + h2 += c; c = h2 >> 26; h2 = h2 & 0x3ffffff; + h3 += c; c = h3 >> 26; h3 = h3 & 0x3ffffff; + h4 += c; c = h4 >> 26; h4 = h4 & 0x3ffffff; + h0 += c * 5; c = h0 >> 26; h0 = h0 & 0x3ffffff; + h1 += c; + + /* compute h + -p */ + g0 = h0 + 5; c = g0 >> 26; g0 &= 0x3ffffff; + g1 = h1 + c; c = g1 >> 26; g1 &= 0x3ffffff; + g2 = h2 + c; c = g2 >> 26; g2 &= 0x3ffffff; + g3 = h3 + c; c = g3 >> 26; g3 &= 0x3ffffff; + g4 = h4 + c - ((word32)1 << 26); + + /* select h if h < p, or h + -p if h >= p */ + mask = ((word32)g4 >> ((sizeof(word32) * 8) - 1)) - 1; + g0 &= mask; + g1 &= mask; + g2 &= mask; + g3 &= mask; + g4 &= mask; + mask = ~mask; + h0 = (h0 & mask) | g0; + h1 = (h1 & mask) | g1; + h2 = (h2 & mask) | g2; + h3 = (h3 & mask) | g3; + h4 = (h4 & mask) | g4; + + /* h = h % (2^128) */ + h0 = ((h0 ) | (h1 << 26)) & 0xffffffff; + h1 = ((h1 >> 6) | (h2 << 20)) & 0xffffffff; + h2 = ((h2 >> 12) | (h3 << 14)) & 0xffffffff; + h3 = ((h3 >> 18) | (h4 << 8)) & 0xffffffff; + + /* mac = (h + pad) % (2^128) */ + f = (word64)h0 + ctx->pad[0] ; h0 = (word32)f; + f = (word64)h1 + ctx->pad[1] + (f >> 32); h1 = (word32)f; + f = (word64)h2 + ctx->pad[2] + (f >> 32); h2 = (word32)f; + f = (word64)h3 + ctx->pad[3] + (f >> 32); h3 = (word32)f; + + U32TO8(mac + 0, h0); + U32TO8(mac + 4, h1); + U32TO8(mac + 8, h2); + U32TO8(mac + 12, h3); + + /* zero out the state */ + ctx->h[0] = 0; + ctx->h[1] = 0; + ctx->h[2] = 0; + ctx->h[3] = 0; + ctx->h[4] = 0; + ctx->r[0] = 0; + ctx->r[1] = 0; + ctx->r[2] = 0; + ctx->r[3] = 0; + ctx->r[4] = 0; + ctx->pad[0] = 0; + ctx->pad[1] = 0; + ctx->pad[2] = 0; + ctx->pad[3] = 0; + +#endif + + return 0; +} +#endif /* !defined(WOLFSSL_ARMASM) || !defined(__aarch64__) */ + + +int wc_Poly1305Update(Poly1305* ctx, const byte* m, word32 bytes) +{ + size_t i; + +#ifdef CHACHA_AEAD_TEST + word32 k; + printf("Raw input to poly:\n"); + for (k = 0; k < bytes; k++) { + printf("%02x", m[k]); + if ((k+1) % 16 == 0) + printf("\n"); + } + printf("\n"); +#endif + + if (ctx == NULL) + return BAD_FUNC_ARG; + +#ifdef USE_INTEL_SPEEDUP + #ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_AVX2(intel_flags)) { + /* handle leftover */ + if (ctx->leftover) { + size_t want = sizeof(ctx->buffer) - ctx->leftover; + if (want > bytes) + want = bytes; + + for (i = 0; i < want; i++) + ctx->buffer[ctx->leftover + i] = m[i]; + bytes -= (word32)want; + m += want; + ctx->leftover += want; + if (ctx->leftover < sizeof(ctx->buffer)) + return 0; + + if (!ctx->started) + poly1305_calc_powers_avx2(ctx); + poly1305_blocks_avx2(ctx, ctx->buffer, sizeof(ctx->buffer)); + ctx->leftover = 0; + } + + /* process full blocks */ + if (bytes >= sizeof(ctx->buffer)) { + size_t want = bytes & ~(sizeof(ctx->buffer) - 1); + + if (!ctx->started) + poly1305_calc_powers_avx2(ctx); + poly1305_blocks_avx2(ctx, m, want); + m += want; + bytes -= (word32)want; + } + + /* store leftover */ + if (bytes) { + for (i = 0; i < bytes; i++) + ctx->buffer[ctx->leftover + i] = m[i]; + ctx->leftover += bytes; + } + } + else + #endif +#endif + { + /* handle leftover */ + if (ctx->leftover) { + size_t want = (POLY1305_BLOCK_SIZE - ctx->leftover); + if (want > bytes) + want = bytes; + for (i = 0; i < want; i++) + ctx->buffer[ctx->leftover + i] = m[i]; + bytes -= (word32)want; + m += want; + ctx->leftover += want; + if (ctx->leftover < POLY1305_BLOCK_SIZE) + return 0; + poly1305_block(ctx, ctx->buffer); + ctx->leftover = 0; + } + + /* process full blocks */ + if (bytes >= POLY1305_BLOCK_SIZE) { + size_t want = (bytes & ~(POLY1305_BLOCK_SIZE - 1)); + poly1305_blocks(ctx, m, want); + m += want; + bytes -= (word32)want; + } + + /* store leftover */ + if (bytes) { + for (i = 0; i < bytes; i++) + ctx->buffer[ctx->leftover + i] = m[i]; + ctx->leftover += bytes; + } + } + + return 0; +} + + +/* Takes in an initialized Poly1305 struct that has a key loaded and creates + a MAC (tag) using recent TLS AEAD padding scheme. + ctx : Initialized Poly1305 struct to use + additional : Additional data to use + addSz : Size of additional buffer + input : Input buffer to create tag from + sz : Size of input buffer + tag : Buffer to hold created tag + tagSz : Size of input tag buffer (must be at least + WC_POLY1305_MAC_SZ(16)) + */ +int wc_Poly1305_MAC(Poly1305* ctx, byte* additional, word32 addSz, + byte* input, word32 sz, byte* tag, word32 tagSz) +{ + int ret; + byte padding[WC_POLY1305_PAD_SZ - 1]; + word32 paddingLen; + byte little64[16]; + + XMEMSET(padding, 0, sizeof(padding)); + + /* sanity check on arguments */ + if (ctx == NULL || input == NULL || tag == NULL || + tagSz < WC_POLY1305_MAC_SZ) { + return BAD_FUNC_ARG; + } + + /* additional allowed to be 0 */ + if (addSz > 0) { + if (additional == NULL) + return BAD_FUNC_ARG; + + /* additional data plus padding */ + if ((ret = wc_Poly1305Update(ctx, additional, addSz)) != 0) { + return ret; + } + paddingLen = -((int)addSz) & (WC_POLY1305_PAD_SZ - 1); + if (paddingLen) { + if ((ret = wc_Poly1305Update(ctx, padding, paddingLen)) != 0) { + return ret; + } + } + } + + /* input plus padding */ + if ((ret = wc_Poly1305Update(ctx, input, sz)) != 0) { + return ret; + } + paddingLen = -((int)sz) & (WC_POLY1305_PAD_SZ - 1); + if (paddingLen) { + if ((ret = wc_Poly1305Update(ctx, padding, paddingLen)) != 0) { + return ret; + } + } + + /* size of additional data and input as little endian 64 bit types */ + U32TO64(addSz, little64); + U32TO64(sz, little64 + 8); + ret = wc_Poly1305Update(ctx, little64, sizeof(little64)); + if (ret) + { + return ret; + } + + /* Finalize the auth tag */ + ret = wc_Poly1305Final(ctx, tag); + + return ret; + +} +#endif /* HAVE_POLY1305 */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/poly1305_asm.S b/beken_os/beken378/func/wolfssl/wolfcrypt/src/poly1305_asm.S new file mode 100755 index 0000000..7a932ba --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/poly1305_asm.S @@ -0,0 +1,1104 @@ +/* poly1305_asm + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#ifndef HAVE_INTEL_AVX1 +#define HAVE_INTEL_AVX1 +#endif /* HAVE_INTEL_AVX1 */ +#ifndef HAVE_INTEL_AVX2 +#define HAVE_INTEL_AVX2 +#endif /* HAVE_INTEL_AVX2 */ + +#ifdef HAVE_INTEL_AVX1 +#ifndef __APPLE__ +.text +.globl poly1305_setkey_avx +.type poly1305_setkey_avx,@function +.align 4 +poly1305_setkey_avx: +#else +.section __TEXT,__text +.globl _poly1305_setkey_avx +.p2align 2 +_poly1305_setkey_avx: +#endif /* __APPLE__ */ + movabsq $0xffffffc0fffffff, %r10 + movabsq $0xffffffc0ffffffc, %r11 + movq (%rsi), %rdx + movq 8(%rsi), %rax + movq 16(%rsi), %rcx + movq 24(%rsi), %r8 + andq %r10, %rdx + andq %r11, %rax + movq %rdx, %r10 + movq %rax, %r11 + xorq %r9, %r9 + movq %rdx, (%rdi) + movq %rax, 8(%rdi) + movq %r9, 24(%rdi) + movq %r9, 32(%rdi) + movq %r9, 40(%rdi) + movq %rcx, 48(%rdi) + movq %r8, 56(%rdi) + movq %r9, 352(%rdi) + movq %r9, 408(%rdi) + movq %rdx, 360(%rdi) + movq %rax, 416(%rdi) + addq %rdx, %r10 + addq %rax, %r11 + movq %r10, 368(%rdi) + movq %r11, 424(%rdi) + addq %rdx, %r10 + addq %rax, %r11 + movq %r10, 376(%rdi) + movq %r11, 432(%rdi) + addq %rdx, %r10 + addq %rax, %r11 + movq %r10, 384(%rdi) + movq %r11, 440(%rdi) + addq %rdx, %r10 + addq %rax, %r11 + movq %r10, 392(%rdi) + movq %r11, 448(%rdi) + addq %rdx, %r10 + addq %rax, %r11 + movq %r10, 400(%rdi) + movq %r11, 456(%rdi) + movq %r9, 608(%rdi) + movb $0x01, 616(%rdi) + repz retq +#ifndef __APPLE__ +.size poly1305_setkey_avx,.-poly1305_setkey_avx +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl poly1305_block_avx +.type poly1305_block_avx,@function +.align 4 +poly1305_block_avx: +#else +.section __TEXT,__text +.globl _poly1305_block_avx +.p2align 2 +_poly1305_block_avx: +#endif /* __APPLE__ */ + pushq %r15 + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + movq (%rdi), %r15 + movq 8(%rdi), %rbx + movq 24(%rdi), %r8 + movq 32(%rdi), %r9 + movq 40(%rdi), %r10 + xorq %r14, %r14 + movb 616(%rdi), %r14b + # h += m + movq (%rsi), %r11 + movq 8(%rsi), %r12 + addq %r11, %r8 + adcq %r12, %r9 + movq %rbx, %rax + adcq %r14, %r10 + # r[1] * h[0] => rdx, rax ==> t2, t1 + mulq %r8 + movq %rax, %r12 + movq %rdx, %r13 + # r[0] * h[1] => rdx, rax ++> t2, t1 + movq %r15, %rax + mulq %r9 + addq %rax, %r12 + movq %r15, %rax + adcq %rdx, %r13 + # r[0] * h[0] => rdx, rax ==> t4, t0 + mulq %r8 + movq %rax, %r11 + movq %rdx, %r8 + # r[1] * h[1] => rdx, rax =+> t3, t2 + movq %rbx, %rax + mulq %r9 + # r[0] * h[2] +> t2 + addq 352(%rdi,%r10,8), %r13 + movq %rdx, %r14 + addq %r8, %r12 + adcq %rax, %r13 + # r[1] * h[2] +> t3 + adcq 408(%rdi,%r10,8), %r14 + # r * h in r14, r13, r12, r11 + # h = (r * h) mod 2^130 - 5 + movq %r13, %r10 + andq $-4, %r13 + andq $3, %r10 + addq %r13, %r11 + movq %r13, %r8 + adcq %r14, %r12 + adcq $0x00, %r10 + shrdq $2, %r14, %r8 + shrq $2, %r14 + addq %r11, %r8 + adcq %r14, %r12 + movq %r12, %r9 + adcq $0x00, %r10 + # h in r10, r9, r8 + # Store h to ctx + movq %r8, 24(%rdi) + movq %r9, 32(%rdi) + movq %r10, 40(%rdi) + popq %r14 + popq %r13 + popq %r12 + popq %rbx + popq %r15 + repz retq +#ifndef __APPLE__ +.size poly1305_block_avx,.-poly1305_block_avx +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl poly1305_blocks_avx +.type poly1305_blocks_avx,@function +.align 4 +poly1305_blocks_avx: +#else +.section __TEXT,__text +.globl _poly1305_blocks_avx +.p2align 2 +_poly1305_blocks_avx: +#endif /* __APPLE__ */ + pushq %r15 + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + movq %rdx, %rcx + movq (%rdi), %r15 + movq 8(%rdi), %rbx + movq 24(%rdi), %r8 + movq 32(%rdi), %r9 + movq 40(%rdi), %r10 +L_poly1305_avx_blocks_start: + # h += m + movq (%rsi), %r11 + movq 8(%rsi), %r12 + addq %r11, %r8 + adcq %r12, %r9 + movq %rbx, %rax + adcq $0x00, %r10 + # r[1] * h[0] => rdx, rax ==> t2, t1 + mulq %r8 + movq %rax, %r12 + movq %rdx, %r13 + # r[0] * h[1] => rdx, rax ++> t2, t1 + movq %r15, %rax + mulq %r9 + addq %rax, %r12 + movq %r15, %rax + adcq %rdx, %r13 + # r[0] * h[0] => rdx, rax ==> t4, t0 + mulq %r8 + movq %rax, %r11 + movq %rdx, %r8 + # r[1] * h[1] => rdx, rax =+> t3, t2 + movq %rbx, %rax + mulq %r9 + # r[0] * h[2] +> t2 + addq 360(%rdi,%r10,8), %r13 + movq %rdx, %r14 + addq %r8, %r12 + adcq %rax, %r13 + # r[1] * h[2] +> t3 + adcq 416(%rdi,%r10,8), %r14 + # r * h in r14, r13, r12, r11 + # h = (r * h) mod 2^130 - 5 + movq %r13, %r10 + andq $-4, %r13 + andq $3, %r10 + addq %r13, %r11 + movq %r13, %r8 + adcq %r14, %r12 + adcq $0x00, %r10 + shrdq $2, %r14, %r8 + shrq $2, %r14 + addq %r11, %r8 + adcq %r14, %r12 + movq %r12, %r9 + adcq $0x00, %r10 + # h in r10, r9, r8 + # Next block from message + addq $16, %rsi + subq $16, %rcx + jg L_poly1305_avx_blocks_start + # Store h to ctx + movq %r8, 24(%rdi) + movq %r9, 32(%rdi) + movq %r10, 40(%rdi) + popq %r14 + popq %r13 + popq %r12 + popq %rbx + popq %r15 + repz retq +#ifndef __APPLE__ +.size poly1305_blocks_avx,.-poly1305_blocks_avx +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl poly1305_final_avx +.type poly1305_final_avx,@function +.align 4 +poly1305_final_avx: +#else +.section __TEXT,__text +.globl _poly1305_final_avx +.p2align 2 +_poly1305_final_avx: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + movq %rsi, %rbx + movq 608(%rdi), %rax + testq %rax, %rax + je L_poly1305_avx_final_no_more + movb $0x01, 480(%rdi,%rax,1) + jmp L_poly1305_avx_final_cmp_rem +L_poly1305_avx_final_zero_rem: + movb $0x00, 480(%rdi,%rax,1) +L_poly1305_avx_final_cmp_rem: + incb %al + cmpq $16, %rax + jl L_poly1305_avx_final_zero_rem + movb $0x00, 616(%rdi) + leaq 480(%rdi), %rsi +#ifndef __APPLE__ + callq poly1305_block_avx@plt +#else + callq _poly1305_block_avx +#endif /* __APPLE__ */ +L_poly1305_avx_final_no_more: + movq 24(%rdi), %rax + movq 32(%rdi), %rdx + movq 40(%rdi), %rcx + movq 48(%rdi), %r11 + movq 56(%rdi), %r12 + # h %= p + # h = (h + pad) + # mod 2^130 - 5 + movq %rcx, %r8 + andq $3, %rcx + shrq $2, %r8 + # Multily by 5 + leaq 0(%r8,%r8,4), %r8 + addq %r8, %rax + adcq $0x00, %rdx + adcq $0x00, %rcx + # Fixup when between (1 << 130) - 1 and (1 << 130) - 5 + movq %rax, %r8 + movq %rdx, %r9 + movq %rcx, %r10 + addq $5, %r8 + adcq $0x00, %r9 + adcq $0x00, %r10 + cmpq $4, %r10 + cmoveq %r8, %rax + cmoveq %r9, %rdx + # h += pad + addq %r11, %rax + adcq %r12, %rdx + movq %rax, (%rbx) + movq %rdx, 8(%rbx) + # Zero out r + movq $0x00, (%rdi) + movq $0x00, 8(%rdi) + # Zero out h + movq $0x00, 24(%rdi) + movq $0x00, 32(%rdi) + movq $0x00, 40(%rdi) + # Zero out pad + movq $0x00, 48(%rdi) + movq $0x00, 56(%rdi) + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size poly1305_final_avx,.-poly1305_final_avx +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX1 */ +#ifdef HAVE_INTEL_AVX2 +#ifndef __APPLE__ +.text +.globl poly1305_calc_powers_avx2 +.type poly1305_calc_powers_avx2,@function +.align 4 +poly1305_calc_powers_avx2: +#else +.section __TEXT,__text +.globl _poly1305_calc_powers_avx2 +.p2align 2 +_poly1305_calc_powers_avx2: +#endif /* __APPLE__ */ + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + pushq %rbx + pushq %rbp + movq (%rdi), %rcx + movq 8(%rdi), %r8 + xorq %r9, %r9 + # Convert to 26 bits in 32 + movq %rcx, %rax + movq %rcx, %rdx + movq %rcx, %rsi + movq %r8, %rbx + movq %r8, %rbp + shrq $26, %rdx + shrdq $52, %r8, %rsi + shrq $14, %rbx + shrdq $40, %r9, %rbp + andq $0x3ffffff, %rax + andq $0x3ffffff, %rdx + andq $0x3ffffff, %rsi + andq $0x3ffffff, %rbx + andq $0x3ffffff, %rbp + movl %eax, 224(%rdi) + movl %edx, 228(%rdi) + movl %esi, 232(%rdi) + movl %ebx, 236(%rdi) + movl %ebp, 240(%rdi) + movl $0x00, 244(%rdi) + # Square 128-bit + movq %r8, %rax + mulq %rcx + xorq %r13, %r13 + movq %rax, %r11 + movq %rdx, %r12 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0x00, %r13 + movq %rcx, %rax + mulq %rax + movq %rax, %r10 + movq %rdx, %r15 + movq %r8, %rax + mulq %rax + addq %r15, %r11 + adcq %rax, %r12 + adcq %rdx, %r13 + # Reduce 256-bit to 130-bit + movq %r12, %rax + movq %r13, %rdx + andq $-4, %rax + andq $3, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + shrdq $2, %rdx, %rax + shrq $2, %rdx + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0x00, %r12 + movq %r12, %rax + shrq $2, %rax + leaq 0(%rax,%rax,4), %rax + addq %rax, %r10 + adcq $0x00, %r11 + adcq $0x00, %r12 + # Convert to 26 bits in 32 + movq %r10, %rax + movq %r10, %rdx + movq %r10, %rsi + movq %r11, %rbx + movq %r11, %rbp + shrq $26, %rdx + shrdq $52, %r11, %rsi + shrq $14, %rbx + shrdq $40, %r12, %rbp + andq $0x3ffffff, %rax + andq $0x3ffffff, %rdx + andq $0x3ffffff, %rsi + andq $0x3ffffff, %rbx + andq $0x3ffffff, %rbp + movl %eax, 256(%rdi) + movl %edx, 260(%rdi) + movl %esi, 264(%rdi) + movl %ebx, 268(%rdi) + movl %ebp, 272(%rdi) + movl $0x00, 276(%rdi) + # Multiply 128-bit by 130-bit + # r1[0] * r2[0] + movq %rcx, %rax + mulq %r10 + movq %rax, %r13 + movq %rdx, %r14 + # r1[0] * r2[1] + movq %rcx, %rax + mulq %r11 + movq $0x00, %r15 + addq %rax, %r14 + adcq %rdx, %r15 + # r1[1] * r2[0] + movq %r8, %rax + mulq %r10 + movq $0x00, %rsi + addq %rax, %r14 + adcq %rdx, %r15 + adcq $0x00, %rsi + # r1[0] * r2[2] + movq %rcx, %rax + mulq %r12 + addq %rax, %r15 + adcq %rdx, %rsi + # r1[1] * r2[1] + movq %r8, %rax + mulq %r11 + movq $0x00, %rbx + addq %rax, %r15 + adcq %rdx, %rsi + adcq $0x00, %rbx + # r1[1] * r2[2] + movq %r8, %rax + mulq %r12 + addq %rax, %rsi + adcq %rdx, %rbx + # Reduce 260-bit to 130-bit + movq %r15, %rax + movq %rsi, %rdx + movq %rbx, %rbx + andq $-4, %rax + andq $3, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq %rbx, %r15 + shrdq $2, %rdx, %rax + shrdq $2, %rbx, %rdx + shrq $2, %rbx + addq %rax, %r13 + adcq %rdx, %r14 + adcq %rbx, %r15 + movq %r15, %rax + andq $3, %r15 + shrq $2, %rax + leaq 0(%rax,%rax,4), %rax + addq %rax, %r13 + adcq $0x00, %r14 + adcq $0x00, %r15 + # Convert to 26 bits in 32 + movq %r13, %rax + movq %r13, %rdx + movq %r13, %rsi + movq %r14, %rbx + movq %r14, %rbp + shrq $26, %rdx + shrdq $52, %r14, %rsi + shrq $14, %rbx + shrdq $40, %r15, %rbp + andq $0x3ffffff, %rax + andq $0x3ffffff, %rdx + andq $0x3ffffff, %rsi + andq $0x3ffffff, %rbx + andq $0x3ffffff, %rbp + movl %eax, 288(%rdi) + movl %edx, 292(%rdi) + movl %esi, 296(%rdi) + movl %ebx, 300(%rdi) + movl %ebp, 304(%rdi) + movl $0x00, 308(%rdi) + # Square 130-bit + movq %r11, %rax + mulq %r10 + xorq %r13, %r13 + movq %rax, %r8 + movq %rdx, %r9 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0x00, %r13 + movq %r10, %rax + mulq %rax + movq %rax, %rcx + movq %rdx, %r15 + movq %r11, %rax + mulq %rax + addq %r15, %r8 + adcq %rax, %r9 + adcq %rdx, %r13 + movq %r12, %rax + mulq %rax + movq %rax, %r14 + movq %r12, %rax + mulq %r10 + addq %rax, %r9 + adcq %rdx, %r13 + adcq $0x00, %r14 + addq %rax, %r9 + adcq %rdx, %r13 + adcq $0x00, %r14 + movq %r12, %rax + mulq %r11 + addq %rax, %r13 + adcq %rdx, %r14 + addq %rax, %r13 + adcq %rdx, %r14 + # Reduce 260-bit to 130-bit + movq %r9, %rax + movq %r13, %rdx + movq %r14, %r15 + andq $-4, %rax + andq $3, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq %r15, %r9 + shrdq $2, %rdx, %rax + shrdq $2, %r15, %rdx + shrq $2, %r15 + addq %rax, %rcx + adcq %rdx, %r8 + adcq %r15, %r9 + movq %r9, %rax + andq $3, %r9 + shrq $2, %rax + leaq 0(%rax,%rax,4), %rax + addq %rax, %rcx + adcq $0x00, %r8 + adcq $0x00, %r9 + # Convert to 26 bits in 32 + movq %rcx, %rax + movq %rcx, %rdx + movq %rcx, %rsi + movq %r8, %rbx + movq %r8, %rbp + shrq $26, %rdx + shrdq $52, %r8, %rsi + shrq $14, %rbx + shrdq $40, %r9, %rbp + andq $0x3ffffff, %rax + andq $0x3ffffff, %rdx + andq $0x3ffffff, %rsi + andq $0x3ffffff, %rbx + andq $0x3ffffff, %rbp + movl %eax, 320(%rdi) + movl %edx, 324(%rdi) + movl %esi, 328(%rdi) + movl %ebx, 332(%rdi) + movl %ebp, 336(%rdi) + movl $0x00, 340(%rdi) + popq %rbp + popq %rbx + popq %r15 + popq %r14 + popq %r13 + popq %r12 + repz retq +#ifndef __APPLE__ +.size poly1305_calc_powers_avx2,.-poly1305_calc_powers_avx2 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl poly1305_setkey_avx2 +.type poly1305_setkey_avx2,@function +.align 4 +poly1305_setkey_avx2: +#else +.section __TEXT,__text +.globl _poly1305_setkey_avx2 +.p2align 2 +_poly1305_setkey_avx2: +#endif /* __APPLE__ */ +#ifndef __APPLE__ + callq poly1305_setkey_avx@plt +#else + callq _poly1305_setkey_avx +#endif /* __APPLE__ */ + vpxor %ymm0, %ymm0, %ymm0 + vmovdqu %ymm0, 64(%rdi) + vmovdqu %ymm0, 96(%rdi) + vmovdqu %ymm0, 128(%rdi) + vmovdqu %ymm0, 160(%rdi) + vmovdqu %ymm0, 192(%rdi) + movq $0x00, 608(%rdi) + movw $0x00, 616(%rdi) + repz retq +#ifndef __APPLE__ +.size poly1305_setkey_avx2,.-poly1305_setkey_avx2 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 32 +#else +.p2align 5 +#endif /* __APPLE__ */ +L_poly1305_avx2_blocks_mask: +.quad 0x3ffffff, 0x3ffffff +.quad 0x3ffffff, 0x3ffffff +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 32 +#else +.p2align 5 +#endif /* __APPLE__ */ +L_poly1305_avx2_blocks_hibit: +.quad 0x1000000, 0x1000000 +.quad 0x1000000, 0x1000000 +#ifndef __APPLE__ +.text +.globl poly1305_blocks_avx2 +.type poly1305_blocks_avx2,@function +.align 4 +poly1305_blocks_avx2: +#else +.section __TEXT,__text +.globl _poly1305_blocks_avx2 +.p2align 2 +_poly1305_blocks_avx2: +#endif /* __APPLE__ */ + pushq %r12 + pushq %rbx + subq $0x140, %rsp + movq %rsp, %rcx + andq $-32, %rcx + addq $32, %rcx + vpxor %ymm15, %ymm15, %ymm15 + movq %rcx, %rbx + leaq 64(%rdi), %rax + addq $0xa0, %rbx + cmpw $0x00, 616(%rdi) + jne L_poly1305_avx2_blocks_begin_h + # Load the message data + vmovdqu (%rsi), %ymm0 + vmovdqu 32(%rsi), %ymm1 + vperm2i128 $32, %ymm1, %ymm0, %ymm2 + vperm2i128 $49, %ymm1, %ymm0, %ymm0 + vpunpckldq %ymm0, %ymm2, %ymm1 + vpunpckhdq %ymm0, %ymm2, %ymm3 + vpunpckldq %ymm15, %ymm1, %ymm0 + vpunpckhdq %ymm15, %ymm1, %ymm1 + vpunpckldq %ymm15, %ymm3, %ymm2 + vpunpckhdq %ymm15, %ymm3, %ymm3 + vmovdqu L_poly1305_avx2_blocks_hibit(%rip), %ymm4 + vpsllq $6, %ymm1, %ymm1 + vpsllq $12, %ymm2, %ymm2 + vpsllq $18, %ymm3, %ymm3 + vmovdqu L_poly1305_avx2_blocks_mask(%rip), %ymm14 + # Reduce, in place, the message data + vpsrlq $26, %ymm0, %ymm10 + vpsrlq $26, %ymm3, %ymm11 + vpand %ymm14, %ymm0, %ymm0 + vpand %ymm14, %ymm3, %ymm3 + vpaddq %ymm1, %ymm10, %ymm1 + vpaddq %ymm4, %ymm11, %ymm4 + vpsrlq $26, %ymm1, %ymm10 + vpsrlq $26, %ymm4, %ymm11 + vpand %ymm14, %ymm1, %ymm1 + vpand %ymm14, %ymm4, %ymm4 + vpaddq %ymm2, %ymm10, %ymm2 + vpslld $2, %ymm11, %ymm12 + vpaddd %ymm12, %ymm11, %ymm12 + vpsrlq $26, %ymm2, %ymm10 + vpaddq %ymm0, %ymm12, %ymm0 + vpsrlq $26, %ymm0, %ymm11 + vpand %ymm14, %ymm2, %ymm2 + vpand %ymm14, %ymm0, %ymm0 + vpaddq %ymm3, %ymm10, %ymm3 + vpaddq %ymm1, %ymm11, %ymm1 + vpsrlq $26, %ymm3, %ymm10 + vpand %ymm14, %ymm3, %ymm3 + vpaddq %ymm4, %ymm10, %ymm4 + addq $0x40, %rsi + subq $0x40, %rdx + jz L_poly1305_avx2_blocks_store + jmp L_poly1305_avx2_blocks_load_r4 +L_poly1305_avx2_blocks_begin_h: + # Load the H values. + vmovdqu (%rax), %ymm0 + vmovdqu 32(%rax), %ymm1 + vmovdqu 64(%rax), %ymm2 + vmovdqu 96(%rax), %ymm3 + vmovdqu 128(%rax), %ymm4 + # Check if there is a power of r to load - otherwise use r^4. + cmpb $0x00, 616(%rdi) + je L_poly1305_avx2_blocks_load_r4 + # Load the 4 powers of r - r^4, r^3, r^2, r^1. + vmovdqu 224(%rdi), %ymm8 + vmovdqu 256(%rdi), %ymm7 + vmovdqu 288(%rdi), %ymm6 + vmovdqu 320(%rdi), %ymm5 + vpermq $0xd8, %ymm5, %ymm5 + vpermq $0xd8, %ymm6, %ymm6 + vpermq $0xd8, %ymm7, %ymm7 + vpermq $0xd8, %ymm8, %ymm8 + vpunpcklqdq %ymm6, %ymm5, %ymm10 + vpunpckhqdq %ymm6, %ymm5, %ymm11 + vpunpcklqdq %ymm8, %ymm7, %ymm12 + vpunpckhqdq %ymm8, %ymm7, %ymm13 + vperm2i128 $32, %ymm12, %ymm10, %ymm5 + vperm2i128 $49, %ymm12, %ymm10, %ymm7 + vperm2i128 $32, %ymm13, %ymm11, %ymm9 + vpsrlq $32, %ymm5, %ymm6 + vpsrlq $32, %ymm7, %ymm8 + jmp L_poly1305_avx2_blocks_mul_5 +L_poly1305_avx2_blocks_load_r4: + # Load r^4 into all four positions. + vmovdqu 320(%rdi), %ymm13 + vpermq $0x00, %ymm13, %ymm5 + vpsrlq $32, %ymm13, %ymm14 + vpermq $0x55, %ymm13, %ymm7 + vpermq $0xaa, %ymm13, %ymm9 + vpermq $0x00, %ymm14, %ymm6 + vpermq $0x55, %ymm14, %ymm8 +L_poly1305_avx2_blocks_mul_5: + # Multiply top 4 26-bit values of all four H by 5 + vpslld $2, %ymm6, %ymm10 + vpslld $2, %ymm7, %ymm11 + vpslld $2, %ymm8, %ymm12 + vpslld $2, %ymm9, %ymm13 + vpaddq %ymm10, %ymm6, %ymm10 + vpaddq %ymm11, %ymm7, %ymm11 + vpaddq %ymm12, %ymm8, %ymm12 + vpaddq %ymm13, %ymm9, %ymm13 + # Store powers of r and multiple of 5 for use in multiply. + vmovdqa %ymm10, (%rbx) + vmovdqa %ymm11, 32(%rbx) + vmovdqa %ymm12, 64(%rbx) + vmovdqa %ymm13, 96(%rbx) + vmovdqa %ymm5, (%rcx) + vmovdqa %ymm6, 32(%rcx) + vmovdqa %ymm7, 64(%rcx) + vmovdqa %ymm8, 96(%rcx) + vmovdqa %ymm9, 128(%rcx) + vmovdqu L_poly1305_avx2_blocks_mask(%rip), %ymm14 + # If not finished then loop over data + cmpb $0x01, 616(%rdi) + jne L_poly1305_avx2_blocks_start + # Do last multiply, reduce, add the four H together and move to + # 32-bit registers + vpmuludq (%rbx), %ymm4, %ymm5 + vpmuludq 32(%rbx), %ymm3, %ymm10 + vpmuludq 32(%rbx), %ymm4, %ymm6 + vpmuludq 64(%rbx), %ymm3, %ymm11 + vpmuludq 64(%rbx), %ymm4, %ymm7 + vpaddq %ymm5, %ymm10, %ymm5 + vpmuludq 64(%rbx), %ymm2, %ymm12 + vpmuludq 96(%rbx), %ymm4, %ymm8 + vpaddq %ymm6, %ymm11, %ymm6 + vpmuludq 96(%rbx), %ymm1, %ymm13 + vpmuludq 96(%rbx), %ymm2, %ymm10 + vpaddq %ymm5, %ymm12, %ymm5 + vpmuludq 96(%rbx), %ymm3, %ymm11 + vpmuludq (%rcx), %ymm3, %ymm12 + vpaddq %ymm5, %ymm13, %ymm5 + vpmuludq (%rcx), %ymm4, %ymm9 + vpaddq %ymm6, %ymm10, %ymm6 + vpmuludq (%rcx), %ymm0, %ymm13 + vpaddq %ymm7, %ymm11, %ymm7 + vpmuludq (%rcx), %ymm1, %ymm10 + vpaddq %ymm8, %ymm12, %ymm8 + vpmuludq (%rcx), %ymm2, %ymm11 + vpmuludq 32(%rcx), %ymm2, %ymm12 + vpaddq %ymm5, %ymm13, %ymm5 + vpmuludq 32(%rcx), %ymm3, %ymm13 + vpaddq %ymm6, %ymm10, %ymm6 + vpmuludq 32(%rcx), %ymm0, %ymm10 + vpaddq %ymm7, %ymm11, %ymm7 + vpmuludq 32(%rcx), %ymm1, %ymm11 + vpaddq %ymm8, %ymm12, %ymm8 + vpmuludq 64(%rcx), %ymm1, %ymm12 + vpaddq %ymm9, %ymm13, %ymm9 + vpmuludq 64(%rcx), %ymm2, %ymm13 + vpaddq %ymm6, %ymm10, %ymm6 + vpmuludq 64(%rcx), %ymm0, %ymm10 + vpaddq %ymm7, %ymm11, %ymm7 + vpmuludq 96(%rcx), %ymm0, %ymm11 + vpaddq %ymm8, %ymm12, %ymm8 + vpmuludq 96(%rcx), %ymm1, %ymm12 + vpaddq %ymm9, %ymm13, %ymm9 + vpaddq %ymm7, %ymm10, %ymm7 + vpmuludq 128(%rcx), %ymm0, %ymm13 + vpaddq %ymm8, %ymm11, %ymm8 + vpaddq %ymm9, %ymm12, %ymm9 + vpaddq %ymm9, %ymm13, %ymm9 + vpsrlq $26, %ymm5, %ymm10 + vpsrlq $26, %ymm8, %ymm11 + vpand %ymm14, %ymm5, %ymm5 + vpand %ymm14, %ymm8, %ymm8 + vpaddq %ymm6, %ymm10, %ymm6 + vpaddq %ymm9, %ymm11, %ymm9 + vpsrlq $26, %ymm6, %ymm10 + vpsrlq $26, %ymm9, %ymm11 + vpand %ymm14, %ymm6, %ymm1 + vpand %ymm14, %ymm9, %ymm4 + vpaddq %ymm7, %ymm10, %ymm7 + vpslld $2, %ymm11, %ymm12 + vpaddd %ymm12, %ymm11, %ymm12 + vpsrlq $26, %ymm7, %ymm10 + vpaddq %ymm5, %ymm12, %ymm5 + vpsrlq $26, %ymm5, %ymm11 + vpand %ymm14, %ymm7, %ymm2 + vpand %ymm14, %ymm5, %ymm0 + vpaddq %ymm8, %ymm10, %ymm8 + vpaddq %ymm1, %ymm11, %ymm1 + vpsrlq $26, %ymm8, %ymm10 + vpand %ymm14, %ymm8, %ymm3 + vpaddq %ymm4, %ymm10, %ymm4 + vpsrldq $8, %ymm0, %ymm5 + vpsrldq $8, %ymm1, %ymm6 + vpsrldq $8, %ymm2, %ymm7 + vpsrldq $8, %ymm3, %ymm8 + vpsrldq $8, %ymm4, %ymm9 + vpaddq %ymm0, %ymm5, %ymm0 + vpaddq %ymm1, %ymm6, %ymm1 + vpaddq %ymm2, %ymm7, %ymm2 + vpaddq %ymm3, %ymm8, %ymm3 + vpaddq %ymm4, %ymm9, %ymm4 + vpermq $2, %ymm0, %ymm5 + vpermq $2, %ymm1, %ymm6 + vpermq $2, %ymm2, %ymm7 + vpermq $2, %ymm3, %ymm8 + vpermq $2, %ymm4, %ymm9 + vpaddq %ymm0, %ymm5, %ymm0 + vpaddq %ymm1, %ymm6, %ymm1 + vpaddq %ymm2, %ymm7, %ymm2 + vpaddq %ymm3, %ymm8, %ymm3 + vpaddq %ymm4, %ymm9, %ymm4 + vmovd %xmm0, %r8d + vmovd %xmm1, %r9d + vmovd %xmm2, %r10d + vmovd %xmm3, %r11d + vmovd %xmm4, %r12d + jmp L_poly1305_avx2_blocks_end_calc +L_poly1305_avx2_blocks_start: + vmovdqu (%rsi), %ymm5 + vmovdqu 32(%rsi), %ymm6 + vperm2i128 $32, %ymm6, %ymm5, %ymm7 + vperm2i128 $49, %ymm6, %ymm5, %ymm5 + vpunpckldq %ymm5, %ymm7, %ymm6 + vpunpckhdq %ymm5, %ymm7, %ymm8 + vpunpckldq %ymm15, %ymm6, %ymm5 + vpunpckhdq %ymm15, %ymm6, %ymm6 + vpunpckldq %ymm15, %ymm8, %ymm7 + vpunpckhdq %ymm15, %ymm8, %ymm8 + vmovdqu L_poly1305_avx2_blocks_hibit(%rip), %ymm9 + vpsllq $6, %ymm6, %ymm6 + vpsllq $12, %ymm7, %ymm7 + vpsllq $18, %ymm8, %ymm8 + vpmuludq (%rbx), %ymm4, %ymm10 + vpaddq %ymm5, %ymm10, %ymm5 + vpmuludq 32(%rbx), %ymm3, %ymm10 + vpmuludq 32(%rbx), %ymm4, %ymm11 + vpaddq %ymm6, %ymm11, %ymm6 + vpmuludq 64(%rbx), %ymm3, %ymm11 + vpmuludq 64(%rbx), %ymm4, %ymm12 + vpaddq %ymm7, %ymm12, %ymm7 + vpaddq %ymm5, %ymm10, %ymm5 + vpmuludq 64(%rbx), %ymm2, %ymm12 + vpmuludq 96(%rbx), %ymm4, %ymm13 + vpaddq %ymm8, %ymm13, %ymm8 + vpaddq %ymm6, %ymm11, %ymm6 + vpmuludq 96(%rbx), %ymm1, %ymm13 + vpmuludq 96(%rbx), %ymm2, %ymm10 + vpaddq %ymm5, %ymm12, %ymm5 + vpmuludq 96(%rbx), %ymm3, %ymm11 + vpmuludq (%rcx), %ymm3, %ymm12 + vpaddq %ymm5, %ymm13, %ymm5 + vpmuludq (%rcx), %ymm4, %ymm13 + vpaddq %ymm9, %ymm13, %ymm9 + vpaddq %ymm6, %ymm10, %ymm6 + vpmuludq (%rcx), %ymm0, %ymm13 + vpaddq %ymm7, %ymm11, %ymm7 + vpmuludq (%rcx), %ymm1, %ymm10 + vpaddq %ymm8, %ymm12, %ymm8 + vpmuludq (%rcx), %ymm2, %ymm11 + vpmuludq 32(%rcx), %ymm2, %ymm12 + vpaddq %ymm5, %ymm13, %ymm5 + vpmuludq 32(%rcx), %ymm3, %ymm13 + vpaddq %ymm6, %ymm10, %ymm6 + vpmuludq 32(%rcx), %ymm0, %ymm10 + vpaddq %ymm7, %ymm11, %ymm7 + vpmuludq 32(%rcx), %ymm1, %ymm11 + vpaddq %ymm8, %ymm12, %ymm8 + vpmuludq 64(%rcx), %ymm1, %ymm12 + vpaddq %ymm9, %ymm13, %ymm9 + vpmuludq 64(%rcx), %ymm2, %ymm13 + vpaddq %ymm6, %ymm10, %ymm6 + vpmuludq 64(%rcx), %ymm0, %ymm10 + vpaddq %ymm7, %ymm11, %ymm7 + vpmuludq 96(%rcx), %ymm0, %ymm11 + vpaddq %ymm8, %ymm12, %ymm8 + vpmuludq 96(%rcx), %ymm1, %ymm12 + vpaddq %ymm9, %ymm13, %ymm9 + vpaddq %ymm7, %ymm10, %ymm7 + vpmuludq 128(%rcx), %ymm0, %ymm13 + vpaddq %ymm8, %ymm11, %ymm8 + vpaddq %ymm9, %ymm12, %ymm9 + vpaddq %ymm9, %ymm13, %ymm9 + vpsrlq $26, %ymm5, %ymm10 + vpsrlq $26, %ymm8, %ymm11 + vpand %ymm14, %ymm5, %ymm5 + vpand %ymm14, %ymm8, %ymm8 + vpaddq %ymm6, %ymm10, %ymm6 + vpaddq %ymm9, %ymm11, %ymm9 + vpsrlq $26, %ymm6, %ymm10 + vpsrlq $26, %ymm9, %ymm11 + vpand %ymm14, %ymm6, %ymm1 + vpand %ymm14, %ymm9, %ymm4 + vpaddq %ymm7, %ymm10, %ymm7 + vpslld $2, %ymm11, %ymm12 + vpaddd %ymm12, %ymm11, %ymm12 + vpsrlq $26, %ymm7, %ymm10 + vpaddq %ymm5, %ymm12, %ymm5 + vpsrlq $26, %ymm5, %ymm11 + vpand %ymm14, %ymm7, %ymm2 + vpand %ymm14, %ymm5, %ymm0 + vpaddq %ymm8, %ymm10, %ymm8 + vpaddq %ymm1, %ymm11, %ymm1 + vpsrlq $26, %ymm8, %ymm10 + vpand %ymm14, %ymm8, %ymm3 + vpaddq %ymm4, %ymm10, %ymm4 + addq $0x40, %rsi + subq $0x40, %rdx + jnz L_poly1305_avx2_blocks_start +L_poly1305_avx2_blocks_store: + # Store four H values - state + vmovdqu %ymm0, (%rax) + vmovdqu %ymm1, 32(%rax) + vmovdqu %ymm2, 64(%rax) + vmovdqu %ymm3, 96(%rax) + vmovdqu %ymm4, 128(%rax) +L_poly1305_avx2_blocks_end_calc: + cmpb $0x00, 616(%rdi) + je L_poly1305_avx2_blocks_complete + movq %r8, %rax + movq %r10, %rdx + movq %r12, %rcx + shrq $12, %rdx + shrq $24, %rcx + shlq $26, %r9 + shlq $52, %r10 + shlq $14, %r11 + shlq $40, %r12 + addq %r9, %rax + adcq %r10, %rax + addq %r11, %rdx + adcq %r12, %rdx + adcq $0x00, %rcx + movq %rcx, %r8 + andq $3, %rcx + shrq $2, %r8 + leaq 0(%r8,%r8,4), %r8 + addq %r8, %rax + adcq $0x00, %rdx + adcq $0x00, %rcx + movq %rax, 24(%rdi) + movq %rdx, 32(%rdi) + movq %rcx, 40(%rdi) +L_poly1305_avx2_blocks_complete: + movb $0x01, 617(%rdi) + addq $0x140, %rsp + popq %rbx + popq %r12 + repz retq +#ifndef __APPLE__ +.size poly1305_blocks_avx2,.-poly1305_blocks_avx2 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl poly1305_final_avx2 +.type poly1305_final_avx2,@function +.align 4 +poly1305_final_avx2: +#else +.section __TEXT,__text +.globl _poly1305_final_avx2 +.p2align 2 +_poly1305_final_avx2: +#endif /* __APPLE__ */ + movb $0x01, 616(%rdi) + movb 617(%rdi), %cl + cmpb $0x00, %cl + je L_poly1305_avx2_final_done_blocks_X4 + pushq %rsi + movq $0x40, %rdx + xorq %rsi, %rsi +#ifndef __APPLE__ + callq poly1305_blocks_avx2@plt +#else + callq _poly1305_blocks_avx2 +#endif /* __APPLE__ */ + popq %rsi +L_poly1305_avx2_final_done_blocks_X4: + movq 608(%rdi), %rax + movq %rax, %rcx + andq $-16, %rcx + cmpb $0x00, %cl + je L_poly1305_avx2_final_done_blocks + pushq %rcx + pushq %rax + pushq %rsi + movq %rcx, %rdx + leaq 480(%rdi), %rsi +#ifndef __APPLE__ + callq poly1305_blocks_avx@plt +#else + callq _poly1305_blocks_avx +#endif /* __APPLE__ */ + popq %rsi + popq %rax + popq %rcx +L_poly1305_avx2_final_done_blocks: + subq %rcx, 608(%rdi) + xorq %rdx, %rdx + jmp L_poly1305_avx2_final_cmp_copy +L_poly1305_avx2_final_start_copy: + movb 480(%rdi,%rcx,1), %r8b + movb %r8b, 480(%rdi,%rdx,1) + incb %cl + incb %dl +L_poly1305_avx2_final_cmp_copy: + cmp %rcx, %rax + jne L_poly1305_avx2_final_start_copy +#ifndef __APPLE__ + callq poly1305_final_avx@plt +#else + callq _poly1305_final_avx +#endif /* __APPLE__ */ + vpxor %ymm0, %ymm0, %ymm0 + vmovdqu %ymm0, 64(%rdi) + vmovdqu %ymm0, 96(%rdi) + vmovdqu %ymm0, 128(%rdi) + vmovdqu %ymm0, 160(%rdi) + vmovdqu %ymm0, 192(%rdi) + vmovdqu %ymm0, 224(%rdi) + vmovdqu %ymm0, 256(%rdi) + vmovdqu %ymm0, 288(%rdi) + vmovdqu %ymm0, 320(%rdi) + movq $0x00, 608(%rdi) + movw $0x00, 616(%rdi) + repz retq +#ifndef __APPLE__ +.size poly1305_final_avx2,.-poly1305_final_avx2 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/pwdbased.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/pwdbased.c new file mode 100755 index 0000000..542f0b6 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/pwdbased.c @@ -0,0 +1,753 @@ +/* pwdbased.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifndef NO_PWDBASED + +#include +#include +#include +#include +#include + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + + +#ifdef HAVE_PBKDF1 + +/* PKCS#5 v1.5 with non standard extension to optionally derive the extra data (IV) */ +int wc_PBKDF1_ex(byte* key, int keyLen, byte* iv, int ivLen, + const byte* passwd, int passwdLen, const byte* salt, int saltLen, + int iterations, int hashType, void* heap) +{ + int err; + int keyLeft, ivLeft, i; + int digestLeft, store; + int keyOutput = 0; + int diestLen; + byte digest[WC_MAX_DIGEST_SIZE]; +#ifdef WOLFSSL_SMALL_STACK + wc_HashAlg* hash = NULL; +#else + wc_HashAlg hash[1]; +#endif + enum wc_HashType hashT; + + (void)heap; + + if (key == NULL || keyLen < 0 || passwdLen < 0 || saltLen < 0 || ivLen < 0){ + return BAD_FUNC_ARG; + } + + if (iterations <= 0) + iterations = 1; + + hashT = wc_HashTypeConvert(hashType); + err = wc_HashGetDigestSize(hashT); + if (err < 0) + return err; + diestLen = err; + + /* initialize hash */ +#ifdef WOLFSSL_SMALL_STACK + hash = (wc_HashAlg*)XMALLOC(sizeof(wc_HashAlg), heap, + DYNAMIC_TYPE_HASHCTX); + if (hash == NULL) + return MEMORY_E; +#endif + + err = wc_HashInit(hash, hashT); + if (err != 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(hash, heap, DYNAMIC_TYPE_HASHCTX); + #endif + return err; + } + + keyLeft = keyLen; + ivLeft = ivLen; + while (keyOutput < (keyLen + ivLen)) { + digestLeft = diestLen; + /* D_(i - 1) */ + if (keyOutput) { /* first time D_0 is empty */ + err = wc_HashUpdate(hash, hashT, digest, diestLen); + if (err != 0) break; + } + + /* data */ + err = wc_HashUpdate(hash, hashT, passwd, passwdLen); + if (err != 0) break; + + /* salt */ + if (salt) { + err = wc_HashUpdate(hash, hashT, salt, saltLen); + if (err != 0) break; + } + + err = wc_HashFinal(hash, hashT, digest); + if (err != 0) break; + + /* count */ + for (i = 1; i < iterations; i++) { + err = wc_HashUpdate(hash, hashT, digest, diestLen); + if (err != 0) break; + + err = wc_HashFinal(hash, hashT, digest); + if (err != 0) break; + } + + if (keyLeft) { + store = min(keyLeft, diestLen); + XMEMCPY(&key[keyLen - keyLeft], digest, store); + + keyOutput += store; + keyLeft -= store; + digestLeft -= store; + } + + if (ivLeft && digestLeft) { + store = min(ivLeft, digestLeft); + if (iv != NULL) + XMEMCPY(&iv[ivLen - ivLeft], + &digest[diestLen - digestLeft], store); + keyOutput += store; + ivLeft -= store; + } + } + + wc_HashFree(hash, hashT); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(hash, heap, DYNAMIC_TYPE_HASHCTX); +#endif + + if (err != 0) + return err; + + if (keyOutput != (keyLen + ivLen)) + return BUFFER_E; + + return err; +} + +/* PKCS#5 v1.5 */ +int wc_PBKDF1(byte* output, const byte* passwd, int pLen, const byte* salt, + int sLen, int iterations, int kLen, int hashType) +{ + return wc_PBKDF1_ex(output, kLen, NULL, 0, + passwd, pLen, salt, sLen, iterations, hashType, NULL); +} + +#endif /* HAVE_PKCS5 */ + +#ifdef HAVE_PBKDF2 + +int wc_PBKDF2(byte* output, const byte* passwd, int pLen, const byte* salt, + int sLen, int iterations, int kLen, int hashType) +{ + word32 i = 1; + int hLen; + int j, ret; +#ifdef WOLFSSL_SMALL_STACK + byte* buffer; + Hmac* hmac; +#else + byte buffer[WC_MAX_DIGEST_SIZE]; + Hmac hmac[1]; +#endif + enum wc_HashType hashT; + + if (output == NULL || pLen < 0 || sLen < 0 || kLen < 0) { + return BAD_FUNC_ARG; + } + + if (iterations <= 0) + iterations = 1; + + hashT = wc_HashTypeConvert(hashType); + hLen = wc_HashGetDigestSize(hashT); + if (hLen < 0) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_SMALL_STACK + buffer = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (buffer == NULL) + return MEMORY_E; + hmac = (Hmac*)XMALLOC(sizeof(Hmac), NULL, DYNAMIC_TYPE_HMAC); + if (hmac == NULL) { + XFREE(buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#endif + + ret = wc_HmacInit(hmac, NULL, INVALID_DEVID); + if (ret == 0) { + /* use int hashType here, since HMAC FIPS uses the old unique value */ + ret = wc_HmacSetKey(hmac, hashType, passwd, pLen); + + while (ret == 0 && kLen) { + int currentLen; + + ret = wc_HmacUpdate(hmac, salt, sLen); + if (ret != 0) + break; + + /* encode i */ + for (j = 0; j < 4; j++) { + byte b = (byte)(i >> ((3-j) * 8)); + + ret = wc_HmacUpdate(hmac, &b, 1); + if (ret != 0) + break; + } + + /* check ret from inside for loop */ + if (ret != 0) + break; + + ret = wc_HmacFinal(hmac, buffer); + if (ret != 0) + break; + + currentLen = min(kLen, hLen); + XMEMCPY(output, buffer, currentLen); + + for (j = 1; j < iterations; j++) { + ret = wc_HmacUpdate(hmac, buffer, hLen); + if (ret != 0) + break; + ret = wc_HmacFinal(hmac, buffer); + if (ret != 0) + break; + xorbuf(output, buffer, currentLen); + } + + /* check ret from inside for loop */ + if (ret != 0) + break; + + output += currentLen; + kLen -= currentLen; + i++; + } + wc_HmacFree(hmac); + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(buffer, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(hmac, NULL, DYNAMIC_TYPE_HMAC); +#endif + + return ret; +} + +#endif /* HAVE_PBKDF2 */ + +#ifdef HAVE_PKCS12 + +/* helper for PKCS12_PBKDF(), does hash operation */ +static int DoPKCS12Hash(int hashType, byte* buffer, word32 totalLen, + byte* Ai, word32 u, int iterations) +{ + int i; + int ret = 0; +#ifdef WOLFSSL_SMALL_STACK + wc_HashAlg* hash = NULL; +#else + wc_HashAlg hash[1]; +#endif + enum wc_HashType hashT; + + if (buffer == NULL || Ai == NULL) { + return BAD_FUNC_ARG; + } + + hashT = wc_HashTypeConvert(hashType); + + /* initialize hash */ +#ifdef WOLFSSL_SMALL_STACK + hash = (wc_HashAlg*)XMALLOC(sizeof(wc_HashAlg), NULL, + DYNAMIC_TYPE_HASHCTX); + if (hash == NULL) + return MEMORY_E; +#endif + + ret = wc_HashInit(hash, hashT); + if (ret != 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(hash, NULL, DYNAMIC_TYPE_HASHCTX); + #endif + return ret; + } + + ret = wc_HashUpdate(hash, hashT, buffer, totalLen); + + if (ret == 0) + ret = wc_HashFinal(hash, hashT, Ai); + + for (i = 1; i < iterations; i++) { + if (ret == 0) + ret = wc_HashUpdate(hash, hashT, Ai, u); + if (ret == 0) + ret = wc_HashFinal(hash, hashT, Ai); + } + + wc_HashFree(hash, hashT); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(hash, NULL, DYNAMIC_TYPE_HASHCTX); +#endif + + return ret; +} + + +int wc_PKCS12_PBKDF(byte* output, const byte* passwd, int passLen, + const byte* salt, int saltLen, int iterations, int kLen, int hashType, + int id) +{ + return wc_PKCS12_PBKDF_ex(output, passwd, passLen, salt, saltLen, + iterations, kLen, hashType, id, NULL); +} + + +/* extended API that allows a heap hint to be used */ +int wc_PKCS12_PBKDF_ex(byte* output, const byte* passwd, int passLen, + const byte* salt, int saltLen, int iterations, int kLen, + int hashType, int id, void* heap) +{ + /* all in bytes instead of bits */ + word32 u, v, dLen, pLen, iLen, sLen, totalLen; + int dynamic = 0; + int ret = 0; + int i; + byte *D, *S, *P, *I; +#ifdef WOLFSSL_SMALL_STACK + byte staticBuffer[1]; /* force dynamic usage */ +#else + byte staticBuffer[1024]; +#endif + byte* buffer = staticBuffer; + +#ifdef WOLFSSL_SMALL_STACK + byte* Ai; + byte* B; +#else + byte Ai[WC_MAX_DIGEST_SIZE]; + byte B[WC_MAX_BLOCK_SIZE]; +#endif + enum wc_HashType hashT; + + (void)heap; + + if (output == NULL || passLen < 0 || saltLen < 0 || kLen < 0) { + return BAD_FUNC_ARG; + } + + if (iterations <= 0) + iterations = 1; + + hashT = wc_HashTypeConvert(hashType); + ret = wc_HashGetDigestSize(hashT); + if (ret < 0) + return ret; + u = ret; + + ret = wc_HashGetBlockSize(hashT); + if (ret < 0) + return ret; + v = ret; + +#ifdef WOLFSSL_SMALL_STACK + Ai = (byte*)XMALLOC(WC_MAX_DIGEST_SIZE, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (Ai == NULL) + return MEMORY_E; + + B = (byte*)XMALLOC(WC_MAX_BLOCK_SIZE, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (B == NULL) { + XFREE(Ai, heap, DYNAMIC_TYPE_TMP_BUFFER); + return MEMORY_E; + } +#endif + + XMEMSET(Ai, 0, WC_MAX_DIGEST_SIZE); + XMEMSET(B, 0, WC_MAX_BLOCK_SIZE); + + dLen = v; + sLen = v * ((saltLen + v - 1) / v); + if (passLen) + pLen = v * ((passLen + v - 1) / v); + else + pLen = 0; + iLen = sLen + pLen; + + totalLen = dLen + sLen + pLen; + + if (totalLen > sizeof(staticBuffer)) { + buffer = (byte*)XMALLOC(totalLen, heap, DYNAMIC_TYPE_KEY); + if (buffer == NULL) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(Ai, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(B, heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return MEMORY_E; + } + dynamic = 1; + } + + D = buffer; + S = D + dLen; + P = S + sLen; + I = S; + + XMEMSET(D, id, dLen); + + for (i = 0; i < (int)sLen; i++) + S[i] = salt[i % saltLen]; + for (i = 0; i < (int)pLen; i++) + P[i] = passwd[i % passLen]; + + while (kLen > 0) { + word32 currentLen; + mp_int B1; + + ret = DoPKCS12Hash(hashType, buffer, totalLen, Ai, u, iterations); + if (ret < 0) + break; + + for (i = 0; i < (int)v; i++) + B[i] = Ai[i % u]; + + if (mp_init(&B1) != MP_OKAY) + ret = MP_INIT_E; + else if (mp_read_unsigned_bin(&B1, B, v) != MP_OKAY) + ret = MP_READ_E; + else if (mp_add_d(&B1, (mp_digit)1, &B1) != MP_OKAY) + ret = MP_ADD_E; + + if (ret != 0) { + mp_clear(&B1); + break; + } + + for (i = 0; i < (int)iLen; i += v) { + int outSz; + mp_int i1; + mp_int res; + + if (mp_init_multi(&i1, &res, NULL, NULL, NULL, NULL) != MP_OKAY) { + ret = MP_INIT_E; + break; + } + if (mp_read_unsigned_bin(&i1, I + i, v) != MP_OKAY) + ret = MP_READ_E; + else if (mp_add(&i1, &B1, &res) != MP_OKAY) + ret = MP_ADD_E; + else if ( (outSz = mp_unsigned_bin_size(&res)) < 0) + ret = MP_TO_E; + else { + if (outSz > (int)v) { + /* take off MSB */ + byte tmp[129]; + ret = mp_to_unsigned_bin(&res, tmp); + XMEMCPY(I + i, tmp + 1, v); + } + else if (outSz < (int)v) { + XMEMSET(I + i, 0, v - outSz); + ret = mp_to_unsigned_bin(&res, I + i + v - outSz); + } + else + ret = mp_to_unsigned_bin(&res, I + i); + } + + mp_clear(&i1); + mp_clear(&res); + if (ret < 0) break; + } + + currentLen = min(kLen, (int)u); + XMEMCPY(output, Ai, currentLen); + output += currentLen; + kLen -= currentLen; + mp_clear(&B1); + } + + if (dynamic) XFREE(buffer, heap, DYNAMIC_TYPE_KEY); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(Ai, heap, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(B, heap, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +#endif /* HAVE_PKCS12 */ + +#ifdef HAVE_SCRYPT +/* Rotate the 32-bit value a by b bits to the left. + * + * a 32-bit value. + * b Number of bits to rotate. + * returns rotated value. + */ +#define R(a, b) rotlFixed(a, b) + +/* One round of Salsa20/8. + * Code taken from RFC 7914: scrypt PBKDF. + * + * out Output buffer. + * in Input data to hash. + */ +static void scryptSalsa(word32* out, word32* in) +{ + int i; + word32 x[16]; + +#ifdef LITTLE_ENDIAN_ORDER + for (i = 0; i < 16; ++i) + x[i] = in[i]; +#else + for (i = 0; i < 16; i++) + x[i] = ByteReverseWord32(in[i]); +#endif + for (i = 8; i > 0; i -= 2) { + x[ 4] ^= R(x[ 0] + x[12], 7); x[ 8] ^= R(x[ 4] + x[ 0], 9); + x[12] ^= R(x[ 8] + x[ 4], 13); x[ 0] ^= R(x[12] + x[ 8], 18); + x[ 9] ^= R(x[ 5] + x[ 1], 7); x[13] ^= R(x[ 9] + x[ 5], 9); + x[ 1] ^= R(x[13] + x[ 9], 13); x[ 5] ^= R(x[ 1] + x[13], 18); + x[14] ^= R(x[10] + x[ 6], 7); x[ 2] ^= R(x[14] + x[10], 9); + x[ 6] ^= R(x[ 2] + x[14], 13); x[10] ^= R(x[ 6] + x[ 2], 18); + x[ 3] ^= R(x[15] + x[11], 7); x[ 7] ^= R(x[ 3] + x[15], 9); + x[11] ^= R(x[ 7] + x[ 3], 13); x[15] ^= R(x[11] + x[ 7], 18); + x[ 1] ^= R(x[ 0] + x[ 3], 7); x[ 2] ^= R(x[ 1] + x[ 0], 9); + x[ 3] ^= R(x[ 2] + x[ 1], 13); x[ 0] ^= R(x[ 3] + x[ 2], 18); + x[ 6] ^= R(x[ 5] + x[ 4], 7); x[ 7] ^= R(x[ 6] + x[ 5], 9); + x[ 4] ^= R(x[ 7] + x[ 6], 13); x[ 5] ^= R(x[ 4] + x[ 7], 18); + x[11] ^= R(x[10] + x[ 9], 7); x[ 8] ^= R(x[11] + x[10], 9); + x[ 9] ^= R(x[ 8] + x[11], 13); x[10] ^= R(x[ 9] + x[ 8], 18); + x[12] ^= R(x[15] + x[14], 7); x[13] ^= R(x[12] + x[15], 9); + x[14] ^= R(x[13] + x[12], 13); x[15] ^= R(x[14] + x[13], 18); + } +#ifdef LITTLE_ENDIAN_ORDER + for (i = 0; i < 16; ++i) + out[i] = in[i] + x[i]; +#else + for (i = 0; i < 16; i++) + out[i] = ByteReverseWord32(ByteReverseWord32(in[i]) + x[i]); +#endif +} + +/* Mix a block using Salsa20/8. + * Based on RFC 7914: scrypt PBKDF. + * + * b Blocks to mix. + * y Temporary storage. + * r Size of the block. + */ +static void scryptBlockMix(byte* b, byte* y, int r) +{ + byte x[64]; +#ifdef WORD64_AVAILABLE + word64* b64 = (word64*)b; + word64* y64 = (word64*)y; + word64* x64 = (word64*)x; +#else + word32* b32 = (word32*)b; + word32* y32 = (word32*)y; + word32* x32 = (word32*)x; +#endif + int i; + int j; + + /* Step 1. */ + XMEMCPY(x, b + (2 * r - 1) * 64, sizeof(x)); + /* Step 2. */ + for (i = 0; i < 2 * r; i++) + { +#ifdef WORD64_AVAILABLE + for (j = 0; j < 8; j++) + x64[j] ^= b64[i * 8 + j]; +#else + for (j = 0; j < 16; j++) + x32[j] ^= b32[i * 16 + j]; +#endif + scryptSalsa((word32*)x, (word32*)x); + XMEMCPY(y + i * 64, x, sizeof(x)); + } + /* Step 3. */ + for (i = 0; i < r; i++) { +#ifdef WORD64_AVAILABLE + for (j = 0; j < 8; j++) { + b64[i * 8 + j] = y64[2 * i * 8 + j]; + b64[(r + i) * 8 + j] = y64[(2 * i + 1) * 8 + j]; + } +#else + for (j = 0; j < 16; j++) { + b32[i * 16 + j] = y32[2 * i * 16 + j]; + b32[(r + i) * 16 + j] = y32[(2 * i + 1) * 16 + j]; + } +#endif + } +} + +/* Random oracles mix. + * Based on RFC 7914: scrypt PBKDF. + * + * x Data to mix. + * v Temporary buffer. + * y Temporary buffer for the block mix. + * r Block size parameter. + * n CPU/Memory cost parameter. + */ +static void scryptROMix(byte* x, byte* v, byte* y, int r, word32 n) +{ + word32 i; + word32 j; + word32 k; + word32 bSz = 128 * r; +#ifdef WORD64_AVAILABLE + word64* x64 = (word64*)x; + word64* v64 = (word64*)v; +#else + word32* x32 = (word32*)x; + word32* v32 = (word32*)v; +#endif + + /* Step 1. X = B (B not needed therefore not implemented) */ + /* Step 2. */ + for (i = 0; i < n; i++) + { + XMEMCPY(v + i * bSz, x, bSz); + scryptBlockMix(x, y, r); + } + + /* Step 3. */ + for (i = 0; i < n; i++) + { +#ifdef LITTLE_ENDIAN_ORDER +#ifdef WORD64_AVAILABLE + j = *(word64*)(x + (2*r - 1) * 64) & (n-1); +#else + j = *(word32*)(x + (2*r - 1) * 64) & (n-1); +#endif +#else + byte* t = x + (2*r - 1) * 64; + j = (t[0] | (t[1] << 8) | (t[2] << 16) | ((word32)t[3] << 24)) & (n-1); +#endif +#ifdef WORD64_AVAILABLE + for (k = 0; k < bSz / 8; k++) + x64[k] ^= v64[j * bSz / 8 + k]; +#else + for (k = 0; k < bSz / 4; k++) + x32[k] ^= v32[j * bSz / 4 + k]; +#endif + scryptBlockMix(x, y, r); + } + /* Step 4. B' = X (B = X = B' so not needed, therefore not implemented) */ +} + +/* Generates an key derived from a password and salt using a memory hard + * algorithm. + * Implements RFC 7914: scrypt PBKDF. + * + * output The derived key. + * passwd The password to derive key from. + * passLen The length of the password. + * salt The key specific data. + * saltLen The length of the salt data. + * cost The CPU/memory cost parameter. Range: 1..(128*r/8-1) + * (Iterations = 2^cost) + * blockSize The number of 128 byte octets in a working block. + * parallel The number of parallel mix operations to perform. + * (Note: this implementation does not use threads.) + * dkLen The length of the derived key in bytes. + * returns BAD_FUNC_ARG when: parallel not 1, blockSize is too large for cost. + */ +int wc_scrypt(byte* output, const byte* passwd, int passLen, + const byte* salt, int saltLen, int cost, int blockSize, + int parallel, int dkLen) +{ + int ret = 0; + int i; + byte* v = NULL; + byte* y = NULL; + byte* blocks = NULL; + word32 blocksSz; + word32 bSz; + + if (blockSize > 8) + return BAD_FUNC_ARG; + + if (cost < 1 || cost >= 128 * blockSize / 8) + return BAD_FUNC_ARG; + + bSz = 128 * blockSize; + blocksSz = bSz * parallel; + blocks = (byte*)XMALLOC(blocksSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (blocks == NULL) + goto end; + /* Temporary for scryptROMix. */ + v = (byte*)XMALLOC((1 << cost) * bSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (v == NULL) + goto end; + /* Temporary for scryptBlockMix. */ + y = (byte*)XMALLOC(blockSize * 128, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (y == NULL) + goto end; + + /* Step 1. */ + ret = wc_PBKDF2(blocks, passwd, passLen, salt, saltLen, 1, blocksSz, + WC_SHA256); + if (ret != 0) + goto end; + + /* Step 2. */ + for (i = 0; i < parallel; i++) + scryptROMix(blocks + i * bSz, v, y, blockSize, 1 << cost); + + /* Step 3. */ + ret = wc_PBKDF2(output, passwd, passLen, blocks, blocksSz, 1, dkLen, + WC_SHA256); +end: + if (blocks != NULL) + XFREE(blocks, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (v != NULL) + XFREE(v, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (y != NULL) + XFREE(y, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return ret; +} +#endif /* HAVE_SCRYPT */ + +#endif /* NO_PWDBASED */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/rabbit.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/rabbit.c new file mode 100755 index 0000000..f3357e4 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/rabbit.c @@ -0,0 +1,342 @@ +/* rabbit.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifndef NO_RABBIT + +#include +#include +#include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + + +#ifdef BIG_ENDIAN_ORDER + #define LITTLE32(x) ByteReverseWord32(x) +#else + #define LITTLE32(x) (x) +#endif + +#define U32V(x) ((word32)(x) & 0xFFFFFFFFU) + + +/* Square a 32-bit unsigned integer to obtain the 64-bit result and return */ +/* the upper 32 bits XOR the lower 32 bits */ +static word32 RABBIT_g_func(word32 x) +{ + /* Temporary variables */ + word32 a, b, h, l; + + /* Construct high and low argument for squaring */ + a = x&0xFFFF; + b = x>>16; + + /* Calculate high and low result of squaring */ + h = (((U32V(a*a)>>17) + U32V(a*b))>>15) + b*b; + l = x*x; + + /* Return high XOR low */ + return U32V(h^l); +} + + +/* Calculate the next internal state */ +static void RABBIT_next_state(RabbitCtx* ctx) +{ + /* Temporary variables */ + word32 g[8], c_old[8], i; + + /* Save old counter values */ + for (i=0; i<8; i++) + c_old[i] = ctx->c[i]; + + /* Calculate new counter values */ + ctx->c[0] = U32V(ctx->c[0] + 0x4D34D34D + ctx->carry); + ctx->c[1] = U32V(ctx->c[1] + 0xD34D34D3 + (ctx->c[0] < c_old[0])); + ctx->c[2] = U32V(ctx->c[2] + 0x34D34D34 + (ctx->c[1] < c_old[1])); + ctx->c[3] = U32V(ctx->c[3] + 0x4D34D34D + (ctx->c[2] < c_old[2])); + ctx->c[4] = U32V(ctx->c[4] + 0xD34D34D3 + (ctx->c[3] < c_old[3])); + ctx->c[5] = U32V(ctx->c[5] + 0x34D34D34 + (ctx->c[4] < c_old[4])); + ctx->c[6] = U32V(ctx->c[6] + 0x4D34D34D + (ctx->c[5] < c_old[5])); + ctx->c[7] = U32V(ctx->c[7] + 0xD34D34D3 + (ctx->c[6] < c_old[6])); + ctx->carry = (ctx->c[7] < c_old[7]); + + /* Calculate the g-values */ + for (i=0;i<8;i++) + g[i] = RABBIT_g_func(U32V(ctx->x[i] + ctx->c[i])); + + /* Calculate new state values */ + ctx->x[0] = U32V(g[0] + rotlFixed(g[7],16) + rotlFixed(g[6], 16)); + ctx->x[1] = U32V(g[1] + rotlFixed(g[0], 8) + g[7]); + ctx->x[2] = U32V(g[2] + rotlFixed(g[1],16) + rotlFixed(g[0], 16)); + ctx->x[3] = U32V(g[3] + rotlFixed(g[2], 8) + g[1]); + ctx->x[4] = U32V(g[4] + rotlFixed(g[3],16) + rotlFixed(g[2], 16)); + ctx->x[5] = U32V(g[5] + rotlFixed(g[4], 8) + g[3]); + ctx->x[6] = U32V(g[6] + rotlFixed(g[5],16) + rotlFixed(g[4], 16)); + ctx->x[7] = U32V(g[7] + rotlFixed(g[6], 8) + g[5]); +} + + +/* IV setup */ +static void wc_RabbitSetIV(Rabbit* ctx, const byte* inIv) +{ + /* Temporary variables */ + word32 i0, i1, i2, i3, i; + word32 iv[2]; + + if (inIv) + XMEMCPY(iv, inIv, sizeof(iv)); + else + XMEMSET(iv, 0, sizeof(iv)); + + /* Generate four subvectors */ + i0 = LITTLE32(iv[0]); + i2 = LITTLE32(iv[1]); + i1 = (i0>>16) | (i2&0xFFFF0000); + i3 = (i2<<16) | (i0&0x0000FFFF); + + /* Modify counter values */ + ctx->workCtx.c[0] = ctx->masterCtx.c[0] ^ i0; + ctx->workCtx.c[1] = ctx->masterCtx.c[1] ^ i1; + ctx->workCtx.c[2] = ctx->masterCtx.c[2] ^ i2; + ctx->workCtx.c[3] = ctx->masterCtx.c[3] ^ i3; + ctx->workCtx.c[4] = ctx->masterCtx.c[4] ^ i0; + ctx->workCtx.c[5] = ctx->masterCtx.c[5] ^ i1; + ctx->workCtx.c[6] = ctx->masterCtx.c[6] ^ i2; + ctx->workCtx.c[7] = ctx->masterCtx.c[7] ^ i3; + + /* Copy state variables */ + for (i=0; i<8; i++) + ctx->workCtx.x[i] = ctx->masterCtx.x[i]; + ctx->workCtx.carry = ctx->masterCtx.carry; + + /* Iterate the system four times */ + for (i=0; i<4; i++) + RABBIT_next_state(&(ctx->workCtx)); +} + + +/* Key setup */ +static WC_INLINE int DoKey(Rabbit* ctx, const byte* key, const byte* iv) +{ + /* Temporary variables */ + word32 k0, k1, k2, k3, i; + + /* Generate four subkeys */ + k0 = LITTLE32(*(word32*)(key+ 0)); + k1 = LITTLE32(*(word32*)(key+ 4)); + k2 = LITTLE32(*(word32*)(key+ 8)); + k3 = LITTLE32(*(word32*)(key+12)); + + /* Generate initial state variables */ + ctx->masterCtx.x[0] = k0; + ctx->masterCtx.x[2] = k1; + ctx->masterCtx.x[4] = k2; + ctx->masterCtx.x[6] = k3; + ctx->masterCtx.x[1] = U32V(k3<<16) | (k2>>16); + ctx->masterCtx.x[3] = U32V(k0<<16) | (k3>>16); + ctx->masterCtx.x[5] = U32V(k1<<16) | (k0>>16); + ctx->masterCtx.x[7] = U32V(k2<<16) | (k1>>16); + + /* Generate initial counter values */ + ctx->masterCtx.c[0] = rotlFixed(k2, 16); + ctx->masterCtx.c[2] = rotlFixed(k3, 16); + ctx->masterCtx.c[4] = rotlFixed(k0, 16); + ctx->masterCtx.c[6] = rotlFixed(k1, 16); + ctx->masterCtx.c[1] = (k0&0xFFFF0000) | (k1&0xFFFF); + ctx->masterCtx.c[3] = (k1&0xFFFF0000) | (k2&0xFFFF); + ctx->masterCtx.c[5] = (k2&0xFFFF0000) | (k3&0xFFFF); + ctx->masterCtx.c[7] = (k3&0xFFFF0000) | (k0&0xFFFF); + + /* Clear carry bit */ + ctx->masterCtx.carry = 0; + + /* Iterate the system four times */ + for (i=0; i<4; i++) + RABBIT_next_state(&(ctx->masterCtx)); + + /* Modify the counters */ + for (i=0; i<8; i++) + ctx->masterCtx.c[i] ^= ctx->masterCtx.x[(i+4)&0x7]; + + /* Copy master instance to work instance */ + for (i=0; i<8; i++) { + ctx->workCtx.x[i] = ctx->masterCtx.x[i]; + ctx->workCtx.c[i] = ctx->masterCtx.c[i]; + } + ctx->workCtx.carry = ctx->masterCtx.carry; + + wc_RabbitSetIV(ctx, iv); + + return 0; +} + + +int wc_Rabbit_SetHeap(Rabbit* ctx, void* heap) +{ + if (ctx == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef XSTREAM_ALIGN + ctx->heap = heap; +#endif + + (void)heap; + return 0; +} + + +/* Key setup */ +int wc_RabbitSetKey(Rabbit* ctx, const byte* key, const byte* iv) +{ + if (ctx == NULL || key == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef XSTREAM_ALIGN + /* default heap to NULL or heap test value */ + #ifdef WOLFSSL_HEAP_TEST + ctx->heap = (void*)WOLFSSL_HEAP_TEST; + #else + ctx->heap = NULL; + #endif /* WOLFSSL_HEAP_TEST */ + + if ((wolfssl_word)key % 4) { + int alignKey[4]; + + /* iv aligned in SetIV */ + WOLFSSL_MSG("wc_RabbitSetKey unaligned key"); + + XMEMCPY(alignKey, key, sizeof(alignKey)); + + return DoKey(ctx, (const byte*)alignKey, iv); + } +#endif /* XSTREAM_ALIGN */ + + return DoKey(ctx, key, iv); +} + + +/* Encrypt/decrypt a message of any size */ +static WC_INLINE int DoProcess(Rabbit* ctx, byte* output, const byte* input, + word32 msglen) +{ + /* Encrypt/decrypt all full blocks */ + while (msglen >= 16) { + /* Iterate the system */ + RABBIT_next_state(&(ctx->workCtx)); + + /* Encrypt/decrypt 16 bytes of data */ + *(word32*)(output+ 0) = *(word32*)(input+ 0) ^ + LITTLE32(ctx->workCtx.x[0] ^ (ctx->workCtx.x[5]>>16) ^ + U32V(ctx->workCtx.x[3]<<16)); + *(word32*)(output+ 4) = *(word32*)(input+ 4) ^ + LITTLE32(ctx->workCtx.x[2] ^ (ctx->workCtx.x[7]>>16) ^ + U32V(ctx->workCtx.x[5]<<16)); + *(word32*)(output+ 8) = *(word32*)(input+ 8) ^ + LITTLE32(ctx->workCtx.x[4] ^ (ctx->workCtx.x[1]>>16) ^ + U32V(ctx->workCtx.x[7]<<16)); + *(word32*)(output+12) = *(word32*)(input+12) ^ + LITTLE32(ctx->workCtx.x[6] ^ (ctx->workCtx.x[3]>>16) ^ + U32V(ctx->workCtx.x[1]<<16)); + + /* Increment pointers and decrement length */ + input += 16; + output += 16; + msglen -= 16; + } + + /* Encrypt/decrypt remaining data */ + if (msglen) { + + word32 i; + word32 tmp[4]; + byte* buffer = (byte*)tmp; + + XMEMSET(tmp, 0, sizeof(tmp)); /* help static analysis */ + + /* Iterate the system */ + RABBIT_next_state(&(ctx->workCtx)); + + /* Generate 16 bytes of pseudo-random data */ + tmp[0] = LITTLE32(ctx->workCtx.x[0] ^ + (ctx->workCtx.x[5]>>16) ^ U32V(ctx->workCtx.x[3]<<16)); + tmp[1] = LITTLE32(ctx->workCtx.x[2] ^ + (ctx->workCtx.x[7]>>16) ^ U32V(ctx->workCtx.x[5]<<16)); + tmp[2] = LITTLE32(ctx->workCtx.x[4] ^ + (ctx->workCtx.x[1]>>16) ^ U32V(ctx->workCtx.x[7]<<16)); + tmp[3] = LITTLE32(ctx->workCtx.x[6] ^ + (ctx->workCtx.x[3]>>16) ^ U32V(ctx->workCtx.x[1]<<16)); + + /* Encrypt/decrypt the data */ + for (i=0; iheap, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) return MEMORY_E; + + XMEMCPY(tmp, input, msglen); + DoProcess(ctx, tmp, tmp, msglen); + XMEMCPY(output, tmp, msglen); + + XFREE(tmp, ctx->heap, DYNAMIC_TYPE_TMP_BUFFER); + + return 0; + #else + return BAD_ALIGN_E; + #endif + } +#endif /* XSTREAM_ALIGN */ + + return DoProcess(ctx, output, input, msglen); +} + + +#endif /* NO_RABBIT */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/random.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/random.c new file mode 100755 index 0000000..247b9b1 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/random.c @@ -0,0 +1,2396 @@ +/* random.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include +#include + +/* on HPUX 11 you may need to install /dev/random see + http://h20293.www2.hp.com/portal/swdepot/displayProductInfo.do?productNumber=KRNG11I + +*/ + +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + + /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ + #define FIPS_NO_WRAPPERS + + #ifdef USE_WINDOWS_API + #pragma code_seg(".fipsA$c") + #pragma const_seg(".fipsB$c") + #endif +#endif + + +#include +#include + +#ifndef __maybe_unused +#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) +#define __maybe_unused __attribute__((unused)) +#else +#define __maybe_unused +#endif /* __GNUC__ */ +#endif + + + +/* If building for old FIPS. */ +#if defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) + +int wc_GenerateSeed(OS_Seed* os, byte* seed, word32 sz) +{ + return GenerateSeed(os, seed, sz); +} + +int wc_InitRng_ex(WC_RNG* rng, void* heap, int devId) +{ + (void)heap; + (void)devId; + return InitRng_fips(rng); +} + +int wc_InitRng(WC_RNG* rng) +{ + return InitRng_fips(rng); +} + + +int wc_RNG_GenerateBlock(WC_RNG* rng, byte* b, word32 sz) +{ + return RNG_GenerateBlock_fips(rng, b, sz); +} + + +int wc_RNG_GenerateByte(WC_RNG* rng, byte* b) +{ + return RNG_GenerateByte(rng, b); +} + +#ifdef HAVE_HASHDRBG + + int wc_FreeRng(WC_RNG* rng) + { + return FreeRng_fips(rng); + } + + int wc_RNG_HealthTest(int reseed, const byte* seedA, word32 seedASz, + const byte* seedB, word32 seedBSz, + byte* output, word32 outputSz) + { + return RNG_HealthTest_fips(reseed, seedA, seedASz, + seedB, seedBSz, output, outputSz); + } +#endif /* HAVE_HASHDRBG */ + +#else /* else build without fips, or for new fips */ + +#ifndef WC_NO_RNG /* if not FIPS and RNG is disabled then do not compile */ + +#include + +#ifdef WOLF_CRYPTO_CB + #include +#endif + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#if defined(WOLFSSL_SGX) + #include +#elif defined(USE_WINDOWS_API) + #ifndef _WIN32_WINNT + #define _WIN32_WINNT 0x0400 + #endif + #include + #include +#elif defined(HAVE_WNR) + #include + #include + wolfSSL_Mutex wnr_mutex; /* global netRandom mutex */ + int wnr_timeout = 0; /* entropy timeout, mililseconds */ + int wnr_mutex_init = 0; /* flag for mutex init */ + wnr_context* wnr_ctx; /* global netRandom context */ +#elif defined(FREESCALE_KSDK_2_0_TRNG) + #include "fsl_trng.h" +#elif defined(FREESCALE_KSDK_2_0_RNGA) + #include "fsl_rnga.h" +#elif defined(WOLFSSL_WICED) + #include "wiced_crypto.h" +#elif defined(NO_DEV_RANDOM) +#elif defined(CUSTOM_RAND_GENERATE) +#elif defined(CUSTOM_RAND_GENERATE_BLOCK) +#elif defined(CUSTOM_RAND_GENERATE_SEED) +#elif defined(WOLFSSL_GENSEED_FORTEST) +#elif defined(WOLFSSL_MDK_ARM) +#elif defined(WOLFSSL_IAR_ARM) +#elif defined(WOLFSSL_ROWLEY_ARM) +#elif defined(WOLFSSL_EMBOS) +#elif defined(WOLFSSL_DEOS) +#elif defined(MICRIUM) +#elif defined(WOLFSSL_NUCLEUS) +#elif defined(WOLFSSL_PB) +#elif defined(WOLFSSL_ZEPHYR) +#elif defined(WOLFSSL_TELIT_M2MB) +#else + /* include headers that may be needed to get good seed */ + #include + #ifndef EBSNET + #include + #endif +#endif + + +#if defined(HAVE_INTEL_RDRAND) || defined(HAVE_INTEL_RDSEED) + static word32 intel_flags = 0; + static void wc_InitRng_IntelRD(void) + { + intel_flags = cpuid_get_flags(); + } + #ifdef HAVE_INTEL_RDSEED + static int wc_GenerateSeed_IntelRD(OS_Seed* os, byte* output, word32 sz); + #endif + #ifdef HAVE_INTEL_RDRAND + static int wc_GenerateRand_IntelRD(OS_Seed* os, byte* output, word32 sz); + #endif + +#ifdef USE_WINDOWS_API + #include +#endif /* USE_WINDOWS_API */ +#endif + +/* Start NIST DRBG code */ +#ifdef HAVE_HASHDRBG + +#define OUTPUT_BLOCK_LEN (WC_SHA256_DIGEST_SIZE) +#define MAX_REQUEST_LEN (0x10000) +#define RESEED_INTERVAL WC_RESEED_INTERVAL + + +/* For FIPS builds, the user should not be adjusting the values. */ +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + #if defined(RNG_SECURITY_STRENGTH) \ + || defined(ENTROPY_SCALE_FACTOR) \ + || defined(SEED_BLOCK_SZ) + + #error "Do not change the RNG parameters for FIPS builds." + #endif +#endif + + +/* The security strength for the RNG is the target number of bits of + * entropy you are looking for in a seed. */ +#ifndef RNG_SECURITY_STRENGTH + #if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + /* SHA-256 requires a minimum of 256-bits of entropy. The goal + * of 1024 will provide 4 times that. */ + #define RNG_SECURITY_STRENGTH (1024) + #else + /* If not using FIPS or using old FIPS, set the number down a bit. + * More is better, but more is also slower. */ + #define RNG_SECURITY_STRENGTH (256) + #endif +#endif + +#ifndef ENTROPY_SCALE_FACTOR + /* The entropy scale factor should be the whole number inverse of the + * minimum bits of entropy per bit of NDRNG output. */ + #if defined(HAVE_INTEL_RDSEED) || defined(HAVE_INTEL_RDRAND) + /* The value of 2 applies to Intel's RDSEED which provides about + * 0.5 bits minimum of entropy per bit. */ + #define ENTROPY_SCALE_FACTOR 2 + #else + /* Setting the default to 1. */ + #define ENTROPY_SCALE_FACTOR 1 + #endif +#endif + +#ifndef SEED_BLOCK_SZ + /* The seed block size, is the size of the output of the underlying NDRNG. + * This value is used for testing the output of the NDRNG. */ + #if defined(HAVE_INTEL_RDSEED) || defined(HAVE_INTEL_RDRAND) + /* RDSEED outputs in blocks of 64-bits. */ + #define SEED_BLOCK_SZ sizeof(word64) + #else + /* Setting the default to 4. */ + #define SEED_BLOCK_SZ 4 + #endif +#endif + +#define SEED_SZ (RNG_SECURITY_STRENGTH*ENTROPY_SCALE_FACTOR/8) + +/* The maximum seed size will be the seed size plus a seed block for the + * test, and an additional half of the seed size. This additional half + * is in case the user does not supply a nonce. A nonce will be obtained + * from the NDRNG. */ +#define MAX_SEED_SZ (SEED_SZ + SEED_SZ/2 + SEED_BLOCK_SZ) + + +/* Internal return codes */ +#define DRBG_SUCCESS 0 +#define DRBG_FAILURE 1 +#define DRBG_NEED_RESEED 2 +#define DRBG_CONT_FAILURE 3 + +/* RNG health states */ +#define DRBG_NOT_INIT 0 +#define DRBG_OK 1 +#define DRBG_FAILED 2 +#define DRBG_CONT_FAILED 3 + +#define RNG_HEALTH_TEST_CHECK_SIZE (WC_SHA256_DIGEST_SIZE * 4) + +/* Verify max gen block len */ +#if RNG_MAX_BLOCK_LEN > MAX_REQUEST_LEN + #error RNG_MAX_BLOCK_LEN is larger than NIST DBRG max request length +#endif + +enum { + drbgInitC = 0, + drbgReseed = 1, + drbgGenerateW = 2, + drbgGenerateH = 3, + drbgInitV +}; + +/* NOTE: if DRBG struct is changed please update random.h drbg_data size */ +typedef struct DRBG { + word32 reseedCtr; + word32 lastBlock; + byte V[DRBG_SEED_LEN]; + byte C[DRBG_SEED_LEN]; +#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB) + void* heap; + int devId; +#endif + byte matchCount; +#ifdef WOLFSSL_SMALL_STACK_CACHE + wc_Sha256 sha256; +#endif +} DRBG; + + +static int wc_RNG_HealthTestLocal(int reseed); + +/* Hash Derivation Function */ +/* Returns: DRBG_SUCCESS or DRBG_FAILURE */ +static int Hash_df(DRBG* drbg, byte* out, word32 outSz, byte type, + const byte* inA, word32 inASz, + const byte* inB, word32 inBSz) +{ + int ret = DRBG_FAILURE; + byte ctr; + int i; + int len; + word32 bits = (outSz * 8); /* reverse byte order */ +#ifdef WOLFSSL_SMALL_STACK_CACHE + wc_Sha256* sha = &drbg->sha256; +#else + wc_Sha256 sha[1]; +#endif +#ifdef WC_ASYNC_ENABLE_SHA256 + DECLARE_VAR(digest, byte, WC_SHA256_DIGEST_SIZE, drbg->heap); +#else + byte digest[WC_SHA256_DIGEST_SIZE]; +#endif + + (void)drbg; +#ifdef WC_ASYNC_ENABLE_SHA256 + if (digest == NULL) + return DRBG_FAILURE; +#endif + +#ifdef LITTLE_ENDIAN_ORDER + bits = ByteReverseWord32(bits); +#endif + len = (outSz / OUTPUT_BLOCK_LEN) + + ((outSz % OUTPUT_BLOCK_LEN) ? 1 : 0); + + for (i = 0, ctr = 1; i < len; i++, ctr++) { +#ifndef WOLFSSL_SMALL_STACK_CACHE + #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB) + ret = wc_InitSha256_ex(sha, drbg->heap, drbg->devId); + #else + ret = wc_InitSha256(sha); + #endif + if (ret != 0) + break; + + if (ret == 0) +#endif + ret = wc_Sha256Update(sha, &ctr, sizeof(ctr)); + if (ret == 0) + ret = wc_Sha256Update(sha, (byte*)&bits, sizeof(bits)); + + if (ret == 0) { + /* churning V is the only string that doesn't have the type added */ + if (type != drbgInitV) + ret = wc_Sha256Update(sha, &type, sizeof(type)); + } + if (ret == 0) + ret = wc_Sha256Update(sha, inA, inASz); + if (ret == 0) { + if (inB != NULL && inBSz > 0) + ret = wc_Sha256Update(sha, inB, inBSz); + } + if (ret == 0) + ret = wc_Sha256Final(sha, digest); + +#ifndef WOLFSSL_SMALL_STACK_CACHE + wc_Sha256Free(sha); +#endif + if (ret == 0) { + if (outSz > OUTPUT_BLOCK_LEN) { + XMEMCPY(out, digest, OUTPUT_BLOCK_LEN); + outSz -= OUTPUT_BLOCK_LEN; + out += OUTPUT_BLOCK_LEN; + } + else { + XMEMCPY(out, digest, outSz); + } + } + } + + ForceZero(digest, WC_SHA256_DIGEST_SIZE); + +#ifdef WC_ASYNC_ENABLE_SHA256 + FREE_VAR(digest, drbg->heap); +#endif + + return (ret == 0) ? DRBG_SUCCESS : DRBG_FAILURE; +} + +/* Returns: DRBG_SUCCESS or DRBG_FAILURE */ +static int Hash_DRBG_Reseed(DRBG* drbg, const byte* seed, word32 seedSz) +{ + byte newV[DRBG_SEED_LEN]; + + XMEMSET(newV, 0, DRBG_SEED_LEN); + + if (Hash_df(drbg, newV, sizeof(newV), drbgReseed, + drbg->V, sizeof(drbg->V), seed, seedSz) != DRBG_SUCCESS) { + return DRBG_FAILURE; + } + + XMEMCPY(drbg->V, newV, sizeof(drbg->V)); + ForceZero(newV, sizeof(newV)); + + if (Hash_df(drbg, drbg->C, sizeof(drbg->C), drbgInitC, drbg->V, + sizeof(drbg->V), NULL, 0) != DRBG_SUCCESS) { + return DRBG_FAILURE; + } + + drbg->reseedCtr = 1; + drbg->lastBlock = 0; + drbg->matchCount = 0; + return DRBG_SUCCESS; +} + +/* Returns: DRBG_SUCCESS and DRBG_FAILURE or BAD_FUNC_ARG on fail */ +int wc_RNG_DRBG_Reseed(WC_RNG* rng, const byte* seed, word32 seedSz) +{ + if (rng == NULL || seed == NULL) { + return BAD_FUNC_ARG; + } + + return Hash_DRBG_Reseed(rng->drbg, seed, seedSz); +} + +static WC_INLINE void array_add_one(byte* data, word32 dataSz) +{ + int i; + + for (i = dataSz - 1; i >= 0; i--) + { + data[i]++; + if (data[i] != 0) break; + } +} + +/* Returns: DRBG_SUCCESS or DRBG_FAILURE */ +static int Hash_gen(DRBG* drbg, byte* out, word32 outSz, const byte* V) +{ + int ret = DRBG_FAILURE; + byte data[DRBG_SEED_LEN]; + int i; + int len; + word32 checkBlock; +#ifdef WOLFSSL_SMALL_STACK_CACHE + wc_Sha256* sha = &drbg->sha256; +#else + wc_Sha256 sha[1]; +#endif +#ifdef WC_ASYNC_ENABLE_SHA256 + DECLARE_VAR(digest, byte, WC_SHA256_DIGEST_SIZE, drbg->heap); +#else + byte digest[WC_SHA256_DIGEST_SIZE]; +#endif + + /* Special case: outSz is 0 and out is NULL. wc_Generate a block to save for + * the continuous test. */ + + if (outSz == 0) outSz = 1; + + len = (outSz / OUTPUT_BLOCK_LEN) + ((outSz % OUTPUT_BLOCK_LEN) ? 1 : 0); + + XMEMCPY(data, V, sizeof(data)); + for (i = 0; i < len; i++) { +#ifndef WOLFSSL_SMALL_STACK_CACHE + #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB) + ret = wc_InitSha256_ex(sha, drbg->heap, drbg->devId); + #else + ret = wc_InitSha256(sha); + #endif + if (ret == 0) +#endif + ret = wc_Sha256Update(sha, data, sizeof(data)); + if (ret == 0) + ret = wc_Sha256Final(sha, digest); +#ifndef WOLFSSL_SMALL_STACK_CACHE + wc_Sha256Free(sha); +#endif + + if (ret == 0) { + XMEMCPY(&checkBlock, digest, sizeof(word32)); + if (drbg->reseedCtr > 1 && checkBlock == drbg->lastBlock) { + if (drbg->matchCount == 1) { + return DRBG_CONT_FAILURE; + } + else { + if (i == len) { + len++; + } + drbg->matchCount = 1; + } + } + else { + drbg->matchCount = 0; + drbg->lastBlock = checkBlock; + } + + if (out != NULL && outSz != 0) { + if (outSz >= OUTPUT_BLOCK_LEN) { + XMEMCPY(out, digest, OUTPUT_BLOCK_LEN); + outSz -= OUTPUT_BLOCK_LEN; + out += OUTPUT_BLOCK_LEN; + array_add_one(data, DRBG_SEED_LEN); + } + else { + XMEMCPY(out, digest, outSz); + outSz = 0; + } + } + } + } + ForceZero(data, sizeof(data)); + +#ifdef WC_ASYNC_ENABLE_SHA256 + FREE_VAR(digest, drbg->heap); +#endif + + return (ret == 0) ? DRBG_SUCCESS : DRBG_FAILURE; +} + +static WC_INLINE void array_add(byte* d, word32 dLen, const byte* s, word32 sLen) +{ + word16 carry = 0; + + if (dLen > 0 && sLen > 0 && dLen >= sLen) { + int sIdx, dIdx; + + for (sIdx = sLen - 1, dIdx = dLen - 1; sIdx >= 0; dIdx--, sIdx--) + { + carry += d[dIdx] + s[sIdx]; + d[dIdx] = (byte)carry; + carry >>= 8; + } + + for (; carry != 0 && dIdx >= 0; dIdx--) { + carry += d[dIdx]; + d[dIdx] = (byte)carry; + carry >>= 8; + } + } +} + +/* Returns: DRBG_SUCCESS, DRBG_NEED_RESEED, or DRBG_FAILURE */ +static int Hash_DRBG_Generate(DRBG* drbg, byte* out, word32 outSz) +{ + int ret; +#ifdef WOLFSSL_SMALL_STACK_CACHE + wc_Sha256* sha = &drbg->sha256; +#else + wc_Sha256 sha[1]; +#endif + byte type; + word32 reseedCtr; + + if (drbg->reseedCtr == RESEED_INTERVAL) { + return DRBG_NEED_RESEED; + } else { + #ifdef WC_ASYNC_ENABLE_SHA256 + DECLARE_VAR(digest, byte, WC_SHA256_DIGEST_SIZE, drbg->heap); + #else + byte digest[WC_SHA256_DIGEST_SIZE]; + #endif + type = drbgGenerateH; + reseedCtr = drbg->reseedCtr; + + ret = Hash_gen(drbg, out, outSz, drbg->V); + if (ret == DRBG_SUCCESS) { +#ifndef WOLFSSL_SMALL_STACK_CACHE + #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB) + ret = wc_InitSha256_ex(sha, drbg->heap, drbg->devId); + #else + ret = wc_InitSha256(sha); + #endif + if (ret == 0) +#endif + ret = wc_Sha256Update(sha, &type, sizeof(type)); + if (ret == 0) + ret = wc_Sha256Update(sha, drbg->V, sizeof(drbg->V)); + if (ret == 0) + ret = wc_Sha256Final(sha, digest); + +#ifndef WOLFSSL_SMALL_STACK_CACHE + wc_Sha256Free(sha); +#endif + + if (ret == 0) { + array_add(drbg->V, sizeof(drbg->V), digest, WC_SHA256_DIGEST_SIZE); + array_add(drbg->V, sizeof(drbg->V), drbg->C, sizeof(drbg->C)); + #ifdef LITTLE_ENDIAN_ORDER + reseedCtr = ByteReverseWord32(reseedCtr); + #endif + array_add(drbg->V, sizeof(drbg->V), + (byte*)&reseedCtr, sizeof(reseedCtr)); + ret = DRBG_SUCCESS; + } + drbg->reseedCtr++; + } + ForceZero(digest, WC_SHA256_DIGEST_SIZE); + #ifdef WC_ASYNC_ENABLE_SHA256 + FREE_VAR(digest, drbg->heap); + #endif + } + + return (ret == 0) ? DRBG_SUCCESS : DRBG_FAILURE; +} + +/* Returns: DRBG_SUCCESS or DRBG_FAILURE */ +static int Hash_DRBG_Instantiate(DRBG* drbg, const byte* seed, word32 seedSz, + const byte* nonce, word32 nonceSz, + void* heap, int devId) +{ + int ret = DRBG_FAILURE; + + XMEMSET(drbg, 0, sizeof(DRBG)); +#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB) + drbg->heap = heap; + drbg->devId = devId; +#else + (void)heap; + (void)devId; +#endif + +#ifdef WOLFSSL_SMALL_STACK_CACHE + #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB) + ret = wc_InitSha256_ex(&drbg->sha256, drbg->heap, drbg->devId); + #else + ret = wc_InitSha256(&drbg->sha256); + #endif + if (ret != 0) + return ret; +#endif + + if (Hash_df(drbg, drbg->V, sizeof(drbg->V), drbgInitV, seed, seedSz, + nonce, nonceSz) == DRBG_SUCCESS && + Hash_df(drbg, drbg->C, sizeof(drbg->C), drbgInitC, drbg->V, + sizeof(drbg->V), NULL, 0) == DRBG_SUCCESS) { + + drbg->reseedCtr = 1; + drbg->lastBlock = 0; + drbg->matchCount = 0; + ret = DRBG_SUCCESS; + } + + return ret; +} + +/* Returns: DRBG_SUCCESS or DRBG_FAILURE */ +static int Hash_DRBG_Uninstantiate(DRBG* drbg) +{ + word32 i; + int compareSum = 0; + byte* compareDrbg = (byte*)drbg; + +#ifdef WOLFSSL_SMALL_STACK_CACHE + wc_Sha256Free(&drbg->sha256); +#endif + + ForceZero(drbg, sizeof(DRBG)); + + for (i = 0; i < sizeof(DRBG); i++) + compareSum |= compareDrbg[i] ^ 0; + + return (compareSum == 0) ? DRBG_SUCCESS : DRBG_FAILURE; +} + + +int wc_RNG_TestSeed(const byte* seed, word32 seedSz) +{ + int ret = DRBG_SUCCESS; + + /* Check the seed for duplicate words. */ + word32 seedIdx = 0; + word32 scratchSz = min(SEED_BLOCK_SZ, seedSz - SEED_BLOCK_SZ); + + while (seedIdx < seedSz - SEED_BLOCK_SZ) { + if (ConstantCompare(seed + seedIdx, + seed + seedIdx + scratchSz, + scratchSz) == 0) { + + ret = DRBG_CONT_FAILURE; + } + seedIdx += SEED_BLOCK_SZ; + scratchSz = min(SEED_BLOCK_SZ, (seedSz - seedIdx)); + } + + return ret; +} +#endif /* HAVE_HASHDRBG */ +/* End NIST DRBG Code */ + + +static int _InitRng(WC_RNG* rng, byte* nonce, word32 nonceSz, + void* heap, int devId) +{ + int ret = RNG_FAILURE_E; +#ifdef HAVE_HASHDRBG + word32 seedSz __maybe_unused = SEED_SZ + SEED_BLOCK_SZ; +#endif + + (void)nonce; + (void)nonceSz; + + if (rng == NULL) + return BAD_FUNC_ARG; + if (nonce == NULL && nonceSz != 0) + return BAD_FUNC_ARG; + +#ifdef WOLFSSL_HEAP_TEST + rng->heap = (void*)WOLFSSL_HEAP_TEST; + (void)heap; +#else + rng->heap = heap; +#endif +#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB) + rng->devId = devId; + #if defined(WOLF_CRYPTO_CB) + rng->seed.devId = devId; + #endif +#else + (void)devId; +#endif + +#ifdef HAVE_HASHDRBG + /* init the DBRG to known values */ + rng->drbg = NULL; + rng->status = DRBG_NOT_INIT; +#endif + +#if defined(HAVE_INTEL_RDSEED) || defined(HAVE_INTEL_RDRAND) + /* init the intel RD seed and/or rand */ + wc_InitRng_IntelRD(); +#endif + + /* configure async RNG source if available */ +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfAsync_DevCtxInit(&rng->asyncDev, WOLFSSL_ASYNC_MARKER_RNG, + rng->heap, rng->devId); + if (ret != 0) + return ret; +#endif + +#ifdef HAVE_INTEL_RDRAND + /* if CPU supports RDRAND, use it directly and by-pass DRBG init */ + if (IS_INTEL_RDRAND(intel_flags)) + return 0; +#endif + +#ifdef CUSTOM_RAND_GENERATE_BLOCK + ret = 0; /* success */ +#else +#ifdef HAVE_HASHDRBG + if (nonceSz == 0) + seedSz = MAX_SEED_SZ; + + if (wc_RNG_HealthTestLocal(0) == 0) { + #ifdef WC_ASYNC_ENABLE_SHA256 + DECLARE_VAR(seed, byte, MAX_SEED_SZ, rng->heap); + #else + byte seed[MAX_SEED_SZ]; + #endif + +#if !defined(WOLFSSL_NO_MALLOC) || defined(WOLFSSL_STATIC_MEMORY) + rng->drbg = + (struct DRBG*)XMALLOC(sizeof(DRBG), rng->heap, + DYNAMIC_TYPE_RNG); +#else + /* compile-time validation of drbg_data size */ + typedef char drbg_data_test[sizeof(rng->drbg_data) >= + sizeof(struct DRBG) ? 1 : -1]; + (void)sizeof(drbg_data_test); + rng->drbg = (struct DRBG*)rng->drbg_data; +#endif + + if (rng->drbg == NULL) { + ret = MEMORY_E; + } + else { + ret = wc_GenerateSeed(&rng->seed, seed, seedSz); + if (ret != 0) + ret = DRBG_FAILURE; + else + ret = wc_RNG_TestSeed(seed, seedSz); + + if (ret == DRBG_SUCCESS) + ret = Hash_DRBG_Instantiate(rng->drbg, + seed + SEED_BLOCK_SZ, seedSz - SEED_BLOCK_SZ, + nonce, nonceSz, rng->heap, devId); + + if (ret != DRBG_SUCCESS) { + #if !defined(WOLFSSL_NO_MALLOC) || defined(WOLFSSL_STATIC_MEMORY) + XFREE(rng->drbg, rng->heap, DYNAMIC_TYPE_RNG); + #endif + rng->drbg = NULL; + } + } + + ForceZero(seed, seedSz); + #ifdef WC_ASYNC_ENABLE_SHA256 + FREE_VAR(seed, rng->heap); + #endif + } + else + ret = DRBG_CONT_FAILURE; + + if (ret == DRBG_SUCCESS) { + rng->status = DRBG_OK; + ret = 0; + } + else if (ret == DRBG_CONT_FAILURE) { + rng->status = DRBG_CONT_FAILED; + ret = DRBG_CONT_FIPS_E; + } + else if (ret == DRBG_FAILURE) { + rng->status = DRBG_FAILED; + ret = RNG_FAILURE_E; + } + else { + rng->status = DRBG_FAILED; + } +#endif /* HAVE_HASHDRBG */ +#endif /* CUSTOM_RAND_GENERATE_BLOCK */ + + return ret; +} + + +int wc_InitRng(WC_RNG* rng) +{ + return _InitRng(rng, NULL, 0, NULL, INVALID_DEVID); +} + + +int wc_InitRng_ex(WC_RNG* rng, void* heap, int devId) +{ + return _InitRng(rng, NULL, 0, heap, devId); +} + + +int wc_InitRngNonce(WC_RNG* rng, byte* nonce, word32 nonceSz) +{ + return _InitRng(rng, nonce, nonceSz, NULL, INVALID_DEVID); +} + + +int wc_InitRngNonce_ex(WC_RNG* rng, byte* nonce, word32 nonceSz, + void* heap, int devId) +{ + return _InitRng(rng, nonce, nonceSz, heap, devId); +} + + +/* place a generated block in output */ +int wc_RNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz) +{ + int ret; + + if (rng == NULL || output == NULL) + return BAD_FUNC_ARG; + +#ifdef WOLF_CRYPTO_CB + if (rng->devId != INVALID_DEVID) { + ret = wc_CryptoCb_RandomBlock(rng, output, sz); + if (ret != CRYPTOCB_UNAVAILABLE) + return ret; + /* fall-through when unavailable */ + } +#endif + +#ifdef HAVE_INTEL_RDRAND + if (IS_INTEL_RDRAND(intel_flags)) + return wc_GenerateRand_IntelRD(NULL, output, sz); +#endif + +#if defined(WOLFSSL_ASYNC_CRYPT) + if (rng->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RNG) { + /* these are blocking */ + #ifdef HAVE_CAVIUM + return NitroxRngGenerateBlock(rng, output, sz); + #elif defined(HAVE_INTEL_QA) && defined(QAT_ENABLE_RNG) + return IntelQaDrbg(&rng->asyncDev, output, sz); + #else + /* simulator not supported */ + #endif + } +#endif + +#ifdef CUSTOM_RAND_GENERATE_BLOCK + XMEMSET(output, 0, sz); + ret = CUSTOM_RAND_GENERATE_BLOCK(output, sz); +#else + +#ifdef HAVE_HASHDRBG + if (sz > RNG_MAX_BLOCK_LEN) + return BAD_FUNC_ARG; + + if (rng->status != DRBG_OK) + return RNG_FAILURE_E; + + ret = Hash_DRBG_Generate(rng->drbg, output, sz); + if (ret == DRBG_NEED_RESEED) { + if (wc_RNG_HealthTestLocal(1) == 0) { + byte newSeed[SEED_SZ + SEED_BLOCK_SZ]; + + ret = wc_GenerateSeed(&rng->seed, newSeed, + SEED_SZ + SEED_BLOCK_SZ); + if (ret != 0) + ret = DRBG_FAILURE; + else + ret = wc_RNG_TestSeed(newSeed, SEED_SZ + SEED_BLOCK_SZ); + + if (ret == DRBG_SUCCESS) + ret = Hash_DRBG_Reseed(rng->drbg, newSeed + SEED_BLOCK_SZ, + SEED_SZ); + if (ret == DRBG_SUCCESS) + ret = Hash_DRBG_Generate(rng->drbg, output, sz); + + ForceZero(newSeed, sizeof(newSeed)); + } + else + ret = DRBG_CONT_FAILURE; + } + + if (ret == DRBG_SUCCESS) { + ret = 0; + } + else if (ret == DRBG_CONT_FAILURE) { + ret = DRBG_CONT_FIPS_E; + rng->status = DRBG_CONT_FAILED; + } + else { + ret = RNG_FAILURE_E; + rng->status = DRBG_FAILED; + } +#else + + /* if we get here then there is an RNG configuration error */ + ret = RNG_FAILURE_E; + +#endif /* HAVE_HASHDRBG */ +#endif /* CUSTOM_RAND_GENERATE_BLOCK */ + + return ret; +} + + +int wc_RNG_GenerateByte(WC_RNG* rng, byte* b) +{ + return wc_RNG_GenerateBlock(rng, b, 1); +} + + +int wc_FreeRng(WC_RNG* rng) +{ + int ret = 0; + + if (rng == NULL) + return BAD_FUNC_ARG; + +#if defined(WOLFSSL_ASYNC_CRYPT) + wolfAsync_DevCtxFree(&rng->asyncDev, WOLFSSL_ASYNC_MARKER_RNG); +#endif + +#ifdef HAVE_HASHDRBG + if (rng->drbg != NULL) { + if (Hash_DRBG_Uninstantiate(rng->drbg) != DRBG_SUCCESS) + ret = RNG_FAILURE_E; + + #if !defined(WOLFSSL_NO_MALLOC) || defined(WOLFSSL_STATIC_MEMORY) + XFREE(rng->drbg, rng->heap, DYNAMIC_TYPE_RNG); + #endif + rng->drbg = NULL; + } + + rng->status = DRBG_NOT_INIT; +#endif /* HAVE_HASHDRBG */ + + return ret; +} + +#ifdef HAVE_HASHDRBG +int wc_RNG_HealthTest(int reseed, const byte* seedA, word32 seedASz, + const byte* seedB, word32 seedBSz, + byte* output, word32 outputSz) +{ + return wc_RNG_HealthTest_ex(reseed, NULL, 0, + seedA, seedASz, seedB, seedBSz, + output, outputSz, + NULL, INVALID_DEVID); +} + + +int wc_RNG_HealthTest_ex(int reseed, const byte* nonce, word32 nonceSz, + const byte* seedA, word32 seedASz, + const byte* seedB, word32 seedBSz, + byte* output, word32 outputSz, + void* heap, int devId) +{ + int ret = -1; + DRBG* drbg; +#ifndef WOLFSSL_SMALL_STACK + DRBG drbg_var; +#endif + + if (seedA == NULL || output == NULL) { + return BAD_FUNC_ARG; + } + + if (reseed != 0 && seedB == NULL) { + return BAD_FUNC_ARG; + } + + if (outputSz != RNG_HEALTH_TEST_CHECK_SIZE) { + return ret; + } + +#ifdef WOLFSSL_SMALL_STACK + drbg = (DRBG*)XMALLOC(sizeof(DRBG), NULL, DYNAMIC_TYPE_RNG); + if (drbg == NULL) { + return MEMORY_E; + } +#else + drbg = &drbg_var; +#endif + + if (Hash_DRBG_Instantiate(drbg, seedA, seedASz, nonce, nonceSz, + heap, devId) != 0) { + goto exit_rng_ht; + } + + if (reseed) { + if (Hash_DRBG_Reseed(drbg, seedB, seedBSz) != 0) { + goto exit_rng_ht; + } + } + + /* This call to generate is prescribed by the NIST DRBGVS + * procedure. The results are thrown away. The known + * answer test checks the second block of DRBG out of + * the generator to ensure the internal state is updated + * as expected. */ + if (Hash_DRBG_Generate(drbg, output, outputSz) != 0) { + goto exit_rng_ht; + } + + if (Hash_DRBG_Generate(drbg, output, outputSz) != 0) { + goto exit_rng_ht; + } + + /* Mark success */ + ret = 0; + +exit_rng_ht: + + /* This is safe to call even if Hash_DRBG_Instantiate fails */ + if (Hash_DRBG_Uninstantiate(drbg) != 0) { + ret = -1; + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(drbg, NULL, DYNAMIC_TYPE_RNG); +#endif + + return ret; +} + + +const byte seedA[] = { + 0x63, 0x36, 0x33, 0x77, 0xe4, 0x1e, 0x86, 0x46, 0x8d, 0xeb, 0x0a, 0xb4, + 0xa8, 0xed, 0x68, 0x3f, 0x6a, 0x13, 0x4e, 0x47, 0xe0, 0x14, 0xc7, 0x00, + 0x45, 0x4e, 0x81, 0xe9, 0x53, 0x58, 0xa5, 0x69, 0x80, 0x8a, 0xa3, 0x8f, + 0x2a, 0x72, 0xa6, 0x23, 0x59, 0x91, 0x5a, 0x9f, 0x8a, 0x04, 0xca, 0x68 +}; + +const byte reseedSeedA[] = { + 0xe6, 0x2b, 0x8a, 0x8e, 0xe8, 0xf1, 0x41, 0xb6, 0x98, 0x05, 0x66, 0xe3, + 0xbf, 0xe3, 0xc0, 0x49, 0x03, 0xda, 0xd4, 0xac, 0x2c, 0xdf, 0x9f, 0x22, + 0x80, 0x01, 0x0a, 0x67, 0x39, 0xbc, 0x83, 0xd3 +}; + +const byte outputA[] = { + 0x04, 0xee, 0xc6, 0x3b, 0xb2, 0x31, 0xdf, 0x2c, 0x63, 0x0a, 0x1a, 0xfb, + 0xe7, 0x24, 0x94, 0x9d, 0x00, 0x5a, 0x58, 0x78, 0x51, 0xe1, 0xaa, 0x79, + 0x5e, 0x47, 0x73, 0x47, 0xc8, 0xb0, 0x56, 0x62, 0x1c, 0x18, 0xbd, 0xdc, + 0xdd, 0x8d, 0x99, 0xfc, 0x5f, 0xc2, 0xb9, 0x20, 0x53, 0xd8, 0xcf, 0xac, + 0xfb, 0x0b, 0xb8, 0x83, 0x12, 0x05, 0xfa, 0xd1, 0xdd, 0xd6, 0xc0, 0x71, + 0x31, 0x8a, 0x60, 0x18, 0xf0, 0x3b, 0x73, 0xf5, 0xed, 0xe4, 0xd4, 0xd0, + 0x71, 0xf9, 0xde, 0x03, 0xfd, 0x7a, 0xea, 0x10, 0x5d, 0x92, 0x99, 0xb8, + 0xaf, 0x99, 0xaa, 0x07, 0x5b, 0xdb, 0x4d, 0xb9, 0xaa, 0x28, 0xc1, 0x8d, + 0x17, 0x4b, 0x56, 0xee, 0x2a, 0x01, 0x4d, 0x09, 0x88, 0x96, 0xff, 0x22, + 0x82, 0xc9, 0x55, 0xa8, 0x19, 0x69, 0xe0, 0x69, 0xfa, 0x8c, 0xe0, 0x07, + 0xa1, 0x80, 0x18, 0x3a, 0x07, 0xdf, 0xae, 0x17 +}; + +const byte seedB[] = { + 0xa6, 0x5a, 0xd0, 0xf3, 0x45, 0xdb, 0x4e, 0x0e, 0xff, 0xe8, 0x75, 0xc3, + 0xa2, 0xe7, 0x1f, 0x42, 0xc7, 0x12, 0x9d, 0x62, 0x0f, 0xf5, 0xc1, 0x19, + 0xa9, 0xef, 0x55, 0xf0, 0x51, 0x85, 0xe0, 0xfb, /* nonce next */ + 0x85, 0x81, 0xf9, 0x31, 0x75, 0x17, 0x27, 0x6e, 0x06, 0xe9, 0x60, 0x7d, + 0xdb, 0xcb, 0xcc, 0x2e +}; + +const byte outputB[] = { + 0xd3, 0xe1, 0x60, 0xc3, 0x5b, 0x99, 0xf3, 0x40, 0xb2, 0x62, 0x82, 0x64, + 0xd1, 0x75, 0x10, 0x60, 0xe0, 0x04, 0x5d, 0xa3, 0x83, 0xff, 0x57, 0xa5, + 0x7d, 0x73, 0xa6, 0x73, 0xd2, 0xb8, 0xd8, 0x0d, 0xaa, 0xf6, 0xa6, 0xc3, + 0x5a, 0x91, 0xbb, 0x45, 0x79, 0xd7, 0x3f, 0xd0, 0xc8, 0xfe, 0xd1, 0x11, + 0xb0, 0x39, 0x13, 0x06, 0x82, 0x8a, 0xdf, 0xed, 0x52, 0x8f, 0x01, 0x81, + 0x21, 0xb3, 0xfe, 0xbd, 0xc3, 0x43, 0xe7, 0x97, 0xb8, 0x7d, 0xbb, 0x63, + 0xdb, 0x13, 0x33, 0xde, 0xd9, 0xd1, 0xec, 0xe1, 0x77, 0xcf, 0xa6, 0xb7, + 0x1f, 0xe8, 0xab, 0x1d, 0xa4, 0x66, 0x24, 0xed, 0x64, 0x15, 0xe5, 0x1c, + 0xcd, 0xe2, 0xc7, 0xca, 0x86, 0xe2, 0x83, 0x99, 0x0e, 0xea, 0xeb, 0x91, + 0x12, 0x04, 0x15, 0x52, 0x8b, 0x22, 0x95, 0x91, 0x02, 0x81, 0xb0, 0x2d, + 0xd4, 0x31, 0xf4, 0xc9, 0xf7, 0x04, 0x27, 0xdf +}; + + +static int wc_RNG_HealthTestLocal(int reseed) +{ + int ret = 0; +#ifdef WOLFSSL_SMALL_STACK + byte* check; +#else + byte check[RNG_HEALTH_TEST_CHECK_SIZE]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + check = (byte*)XMALLOC(RNG_HEALTH_TEST_CHECK_SIZE, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (check == NULL) { + return MEMORY_E; + } +#endif + + if (reseed) { + ret = wc_RNG_HealthTest(1, seedA, sizeof(seedA), + reseedSeedA, sizeof(reseedSeedA), + check, RNG_HEALTH_TEST_CHECK_SIZE); + if (ret == 0) { + if (ConstantCompare(check, outputA, + RNG_HEALTH_TEST_CHECK_SIZE) != 0) + ret = -1; + } + } + else { + ret = wc_RNG_HealthTest(0, seedB, sizeof(seedB), + NULL, 0, + check, RNG_HEALTH_TEST_CHECK_SIZE); + if (ret == 0) { + if (ConstantCompare(check, outputB, + RNG_HEALTH_TEST_CHECK_SIZE) != 0) + ret = -1; + } + + /* The previous test cases use a large seed instead of a seed and nonce. + * seedB is actually from a test case with a seed and nonce, and + * just concatenates them. The pivot point between seed and nonce is + * byte 32, feed them into the health test separately. */ + if (ret == 0) { + ret = wc_RNG_HealthTest_ex(0, + seedB + 32, sizeof(seedB) - 32, + seedB, 32, + NULL, 0, + check, RNG_HEALTH_TEST_CHECK_SIZE, + NULL, INVALID_DEVID); + if (ret == 0) { + if (ConstantCompare(check, outputB, sizeof(outputB)) != 0) + ret = -1; + } + } + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(check, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +#endif /* HAVE_HASHDRBG */ + + +#ifdef HAVE_WNR + +/* + * Init global Whitewood netRandom context + * Returns 0 on success, negative on error + */ +int wc_InitNetRandom(const char* configFile, wnr_hmac_key hmac_cb, int timeout) +{ + if (configFile == NULL || timeout < 0) + return BAD_FUNC_ARG; + + if (wnr_mutex_init > 0) { + WOLFSSL_MSG("netRandom context already created, skipping"); + return 0; + } + + if (wc_InitMutex(&wnr_mutex) != 0) { + WOLFSSL_MSG("Bad Init Mutex wnr_mutex"); + return BAD_MUTEX_E; + } + wnr_mutex_init = 1; + + if (wc_LockMutex(&wnr_mutex) != 0) { + WOLFSSL_MSG("Bad Lock Mutex wnr_mutex"); + return BAD_MUTEX_E; + } + + /* store entropy timeout */ + wnr_timeout = timeout; + + /* create global wnr_context struct */ + if (wnr_create(&wnr_ctx) != WNR_ERROR_NONE) { + WOLFSSL_MSG("Error creating global netRandom context"); + return RNG_FAILURE_E; + } + + /* load config file */ + if (wnr_config_loadf(wnr_ctx, (char*)configFile) != WNR_ERROR_NONE) { + WOLFSSL_MSG("Error loading config file into netRandom context"); + wnr_destroy(wnr_ctx); + wnr_ctx = NULL; + return RNG_FAILURE_E; + } + + /* create/init polling mechanism */ + if (wnr_poll_create() != WNR_ERROR_NONE) { + printf("ERROR: wnr_poll_create() failed\n"); + WOLFSSL_MSG("Error initializing netRandom polling mechanism"); + wnr_destroy(wnr_ctx); + wnr_ctx = NULL; + return RNG_FAILURE_E; + } + + /* validate config, set HMAC callback (optional) */ + if (wnr_setup(wnr_ctx, hmac_cb) != WNR_ERROR_NONE) { + WOLFSSL_MSG("Error setting up netRandom context"); + wnr_destroy(wnr_ctx); + wnr_ctx = NULL; + wnr_poll_destroy(); + return RNG_FAILURE_E; + } + + wc_UnLockMutex(&wnr_mutex); + + return 0; +} + +/* + * Free global Whitewood netRandom context + * Returns 0 on success, negative on error + */ +int wc_FreeNetRandom(void) +{ + if (wnr_mutex_init > 0) { + + if (wc_LockMutex(&wnr_mutex) != 0) { + WOLFSSL_MSG("Bad Lock Mutex wnr_mutex"); + return BAD_MUTEX_E; + } + + if (wnr_ctx != NULL) { + wnr_destroy(wnr_ctx); + wnr_ctx = NULL; + } + wnr_poll_destroy(); + + wc_UnLockMutex(&wnr_mutex); + + wc_FreeMutex(&wnr_mutex); + wnr_mutex_init = 0; + } + + return 0; +} + +#endif /* HAVE_WNR */ + + +#if defined(HAVE_INTEL_RDRAND) || defined(HAVE_INTEL_RDSEED) + +#ifdef WOLFSSL_ASYNC_CRYPT + /* need more retries if multiple cores */ + #define INTELRD_RETRY (32 * 8) +#else + #define INTELRD_RETRY 32 +#endif + +#ifdef HAVE_INTEL_RDSEED + +#ifndef USE_WINDOWS_API + + /* return 0 on success */ + static WC_INLINE int IntelRDseed64(word64* seed) + { + unsigned char ok; + + __asm__ volatile("rdseed %0; setc %1":"=r"(*seed), "=qm"(ok)); + return (ok) ? 0 : -1; + } + +#else /* USE_WINDOWS_API */ + /* The compiler Visual Studio uses does not allow inline assembly. + * It does allow for Intel intrinsic functions. */ + + /* return 0 on success */ + static WC_INLINE int IntelRDseed64(word64* seed) + { + int ok; + + ok = _rdseed64_step(seed); + return (ok) ? 0 : -1; + } + +#endif /* USE_WINDOWS_API */ + +/* return 0 on success */ +static WC_INLINE int IntelRDseed64_r(word64* rnd) +{ + int i; + for (i = 0; i < INTELRD_RETRY; i++) { + if (IntelRDseed64(rnd) == 0) + return 0; + } + return -1; +} + +/* return 0 on success */ +static int wc_GenerateSeed_IntelRD(OS_Seed* os, byte* output, word32 sz) +{ + int ret; + word64 rndTmp; + + (void)os; + + if (!IS_INTEL_RDSEED(intel_flags)) + return -1; + + for (; (sz / sizeof(word64)) > 0; sz -= sizeof(word64), + output += sizeof(word64)) { + ret = IntelRDseed64_r((word64*)output); + if (ret != 0) + return ret; + } + if (sz == 0) + return 0; + + /* handle unaligned remainder */ + ret = IntelRDseed64_r(&rndTmp); + if (ret != 0) + return ret; + + XMEMCPY(output, &rndTmp, sz); + ForceZero(&rndTmp, sizeof(rndTmp)); + + return 0; +} + +#endif /* HAVE_INTEL_RDSEED */ + +#ifdef HAVE_INTEL_RDRAND + +#ifndef USE_WINDOWS_API + +/* return 0 on success */ +static WC_INLINE int IntelRDrand64(word64 *rnd) +{ + unsigned char ok; + + __asm__ volatile("rdrand %0; setc %1":"=r"(*rnd), "=qm"(ok)); + + return (ok) ? 0 : -1; +} + +#else /* USE_WINDOWS_API */ + /* The compiler Visual Studio uses does not allow inline assembly. + * It does allow for Intel intrinsic functions. */ + +/* return 0 on success */ +static WC_INLINE int IntelRDrand64(word64 *rnd) +{ + int ok; + + ok = _rdrand64_step(rnd); + + return (ok) ? 0 : -1; +} + +#endif /* USE_WINDOWS_API */ + +/* return 0 on success */ +static WC_INLINE int IntelRDrand64_r(word64 *rnd) +{ + int i; + for (i = 0; i < INTELRD_RETRY; i++) { + if (IntelRDrand64(rnd) == 0) + return 0; + } + return -1; +} + +/* return 0 on success */ +static int wc_GenerateRand_IntelRD(OS_Seed* os, byte* output, word32 sz) +{ + int ret; + word64 rndTmp; + + (void)os; + + if (!IS_INTEL_RDRAND(intel_flags)) + return -1; + + for (; (sz / sizeof(word64)) > 0; sz -= sizeof(word64), + output += sizeof(word64)) { + ret = IntelRDrand64_r((word64 *)output); + if (ret != 0) + return ret; + } + if (sz == 0) + return 0; + + /* handle unaligned remainder */ + ret = IntelRDrand64_r(&rndTmp); + if (ret != 0) + return ret; + + XMEMCPY(output, &rndTmp, sz); + + return 0; +} + +#endif /* HAVE_INTEL_RDRAND */ +#endif /* HAVE_INTEL_RDRAND || HAVE_INTEL_RDSEED */ + + +/* Begin wc_GenerateSeed Implementations */ +#if defined(CUSTOM_RAND_GENERATE_SEED) + + /* Implement your own random generation function + * Return 0 to indicate success + * int rand_gen_seed(byte* output, word32 sz); + * #define CUSTOM_RAND_GENERATE_SEED rand_gen_seed */ + + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + (void)os; /* Suppress unused arg warning */ + return CUSTOM_RAND_GENERATE_SEED(output, sz); + } + +#elif defined(CUSTOM_RAND_GENERATE_SEED_OS) + + /* Implement your own random generation function, + * which includes OS_Seed. + * Return 0 to indicate success + * int rand_gen_seed(OS_Seed* os, byte* output, word32 sz); + * #define CUSTOM_RAND_GENERATE_SEED_OS rand_gen_seed */ + + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + return CUSTOM_RAND_GENERATE_SEED_OS(os, output, sz); + } + +#elif defined(CUSTOM_RAND_GENERATE) + + /* Implement your own random generation function + * word32 rand_gen(void); + * #define CUSTOM_RAND_GENERATE rand_gen */ + + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + word32 i = 0; + + (void)os; + + while (i < sz) + { + /* If not aligned or there is odd/remainder */ + if( (i + sizeof(CUSTOM_RAND_TYPE)) > sz || + ((wolfssl_word)&output[i] % sizeof(CUSTOM_RAND_TYPE)) != 0 + ) { + /* Single byte at a time */ + output[i++] = (byte)CUSTOM_RAND_GENERATE(); + } + else { + /* Use native 8, 16, 32 or 64 copy instruction */ + *((CUSTOM_RAND_TYPE*)&output[i]) = CUSTOM_RAND_GENERATE(); + i += sizeof(CUSTOM_RAND_TYPE); + } + } + + return 0; + } + +#elif defined(WOLFSSL_SGX) + +int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) +{ + int ret = !SGX_SUCCESS; + int i, read_max = 10; + + for (i = 0; i < read_max && ret != SGX_SUCCESS; i++) { + ret = sgx_read_rand(output, sz); + } + + (void)os; + return (ret == SGX_SUCCESS) ? 0 : 1; +} + +#elif defined(USE_WINDOWS_API) + +int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) +{ +#ifdef WOLF_CRYPTO_CB + int ret; + + if (os != NULL && os->devId != INVALID_DEVID) { + ret = wc_CryptoCb_RandomSeed(os, output, sz); + if (ret != CRYPTOCB_UNAVAILABLE) + return ret; + /* fall-through when unavailable */ + } +#endif + + #ifdef HAVE_INTEL_RDSEED + if (IS_INTEL_RDSEED(intel_flags)) { + if (!wc_GenerateSeed_IntelRD(NULL, output, sz)) { + /* success, we're done */ + return 0; + } + #ifdef FORCE_FAILURE_RDSEED + /* don't fall back to CryptoAPI */ + return READ_RAN_E; + #endif + } + #endif /* HAVE_INTEL_RDSEED */ + + if(!CryptAcquireContext(&os->handle, 0, 0, PROV_RSA_FULL, + CRYPT_VERIFYCONTEXT)) + return WINCRYPT_E; + + if (!CryptGenRandom(os->handle, sz, output)) + return CRYPTGEN_E; + + CryptReleaseContext(os->handle, 0); + + return 0; +} + + +#elif defined(HAVE_RTP_SYS) || defined(EBSNET) + +#include "rtprand.h" /* rtp_rand () */ +#include "rtptime.h" /* rtp_get_system_msec() */ + + +int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) +{ + int i; + rtp_srand(rtp_get_system_msec()); + + for (i = 0; i < sz; i++ ) { + output[i] = rtp_rand() % 256; + if ( (i % 8) == 7) + rtp_srand(rtp_get_system_msec()); + } + + return 0; +} + + +#elif defined(MICROCHIP_PIC32) + + #ifdef MICROCHIP_MPLAB_HARMONY + #ifdef MICROCHIP_MPLAB_HARMONY_3 + #include "system/time/sys_time.h" + #define PIC32_SEED_COUNT SYS_TIME_CounterGet + #else + #define PIC32_SEED_COUNT _CP0_GET_COUNT + #endif + #else + #if !defined(WOLFSSL_MICROCHIP_PIC32MZ) + #include + #endif + extern word32 ReadCoreTimer(void); + #define PIC32_SEED_COUNT ReadCoreTimer + #endif + + #ifdef WOLFSSL_PIC32MZ_RNG + #include "xc.h" + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + int i; + byte rnd[8]; + word32 *rnd32 = (word32 *)rnd; + word32 size = sz; + byte* op = output; + +#if ((__PIC32_FEATURE_SET0 == 'E') && (__PIC32_FEATURE_SET1 == 'C')) + RNGNUMGEN1 = _CP0_GET_COUNT(); + RNGPOLY1 = _CP0_GET_COUNT(); + RNGPOLY2 = _CP0_GET_COUNT(); + RNGNUMGEN2 = _CP0_GET_COUNT(); +#else + // All others can be seeded from the TRNG + RNGCONbits.TRNGMODE = 1; + RNGCONbits.TRNGEN = 1; + while (RNGCNT < 64); + RNGCONbits.LOAD = 1; + while (RNGCONbits.LOAD == 1); + while (RNGCNT < 64); + RNGPOLY2 = RNGSEED2; + RNGPOLY1 = RNGSEED1; +#endif + + RNGCONbits.PLEN = 0x40; + RNGCONbits.PRNGEN = 1; + for (i=0; i<5; i++) { /* wait for RNGNUMGEN ready */ + volatile int x; + x = RNGNUMGEN1; + x = RNGNUMGEN2; + (void)x; + } + do { + rnd32[0] = RNGNUMGEN1; + rnd32[1] = RNGNUMGEN2; + + for(i=0; i<8; i++, op++) { + *op = rnd[i]; + size --; + if(size==0)break; + } + } while(size); + return 0; + } + #else /* WOLFSSL_PIC32MZ_RNG */ + /* uses the core timer, in nanoseconds to seed srand */ + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + int i; + srand(PIC32_SEED_COUNT() * 25); + + for (i = 0; i < sz; i++ ) { + output[i] = rand() % 256; + if ( (i % 8) == 7) + srand(PIC32_SEED_COUNT() * 25); + } + return 0; + } + #endif /* WOLFSSL_PIC32MZ_RNG */ + +#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) || \ + defined(FREESCALE_KSDK_BM) || defined(FREESCALE_FREE_RTOS) + + #if defined(FREESCALE_K70_RNGA) || defined(FREESCALE_RNGA) + /* + * wc_Generates a RNG seed using the Random Number Generator Accelerator + * on the Kinetis K70. Documentation located in Chapter 37 of + * K70 Sub-Family Reference Manual (see Note 3 in the README for link). + */ + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + word32 i; + + /* turn on RNGA module */ + #if defined(SIM_SCGC3_RNGA_MASK) + SIM_SCGC3 |= SIM_SCGC3_RNGA_MASK; + #endif + #if defined(SIM_SCGC6_RNGA_MASK) + /* additionally needed for at least K64F */ + SIM_SCGC6 |= SIM_SCGC6_RNGA_MASK; + #endif + + /* set SLP bit to 0 - "RNGA is not in sleep mode" */ + RNG_CR &= ~RNG_CR_SLP_MASK; + + /* set HA bit to 1 - "security violations masked" */ + RNG_CR |= RNG_CR_HA_MASK; + + /* set GO bit to 1 - "output register loaded with data" */ + RNG_CR |= RNG_CR_GO_MASK; + + for (i = 0; i < sz; i++) { + + /* wait for RNG FIFO to be full */ + while((RNG_SR & RNG_SR_OREG_LVL(0xF)) == 0) {} + + /* get value */ + output[i] = RNG_OR; + } + + return 0; + } + + #elif defined(FREESCALE_K53_RNGB) || defined(FREESCALE_RNGB) + /* + * wc_Generates a RNG seed using the Random Number Generator (RNGB) + * on the Kinetis K53. Documentation located in Chapter 33 of + * K53 Sub-Family Reference Manual (see note in the README for link). + */ + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + int i; + + /* turn on RNGB module */ + SIM_SCGC3 |= SIM_SCGC3_RNGB_MASK; + + /* reset RNGB */ + RNG_CMD |= RNG_CMD_SR_MASK; + + /* FIFO generate interrupt, return all zeros on underflow, + * set auto reseed */ + RNG_CR |= (RNG_CR_FUFMOD_MASK | RNG_CR_AR_MASK); + + /* gen seed, clear interrupts, clear errors */ + RNG_CMD |= (RNG_CMD_GS_MASK | RNG_CMD_CI_MASK | RNG_CMD_CE_MASK); + + /* wait for seeding to complete */ + while ((RNG_SR & RNG_SR_SDN_MASK) == 0) {} + + for (i = 0; i < sz; i++) { + + /* wait for a word to be available from FIFO */ + while((RNG_SR & RNG_SR_FIFO_LVL_MASK) == 0) {} + + /* get value */ + output[i] = RNG_OUT; + } + + return 0; + } + + #elif defined(FREESCALE_KSDK_2_0_TRNG) + + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + status_t status; + status = TRNG_GetRandomData(TRNG0, output, sz); + if (status == kStatus_Success) + { + return(0); + } + else + { + return RAN_BLOCK_E; + } + } + + #elif defined(FREESCALE_KSDK_2_0_RNGA) + + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + status_t status; + status = RNGA_GetRandomData(RNG, output, sz); + if (status == kStatus_Success) + { + return(0); + } + else + { + return RAN_BLOCK_E; + } + } + + + #elif defined(FREESCALE_RNGA) + + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + RNGA_DRV_GetRandomData(RNGA_INSTANCE, output, sz); + return 0; + } + + #else + #define USE_TEST_GENSEED + #endif /* FREESCALE_K70_RNGA */ + +#elif defined(STM32_RNG) + /* Generate a RNG seed using the hardware random number generator + * on the STM32F2/F4/F7/L4. */ + + #ifdef WOLFSSL_STM32_CUBEMX + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + RNG_HandleTypeDef hrng; + word32 i = 0; + (void)os; + + /* enable RNG clock source */ + __HAL_RCC_RNG_CLK_ENABLE(); + + /* enable RNG peripheral */ + XMEMSET(&hrng, 0, sizeof(hrng)); + hrng.Instance = RNG; + HAL_RNG_Init(&hrng); + + while (i < sz) { + /* If not aligned or there is odd/remainder */ + if( (i + sizeof(word32)) > sz || + ((wolfssl_word)&output[i] % sizeof(word32)) != 0 + ) { + /* Single byte at a time */ + uint32_t tmpRng = 0; + if (HAL_RNG_GenerateRandomNumber(&hrng, &tmpRng) != HAL_OK) { + return RAN_BLOCK_E; + } + output[i++] = (byte)tmpRng; + } + else { + /* Use native 32 instruction */ + if (HAL_RNG_GenerateRandomNumber(&hrng, (uint32_t*)&output[i]) != HAL_OK) { + return RAN_BLOCK_E; + } + i += sizeof(word32); + } + } + + return 0; + } + #elif defined(WOLFSSL_STM32F427_RNG) || defined(WOLFSSL_STM32_RNG_NOLIB) + + /* Generate a RNG seed using the hardware RNG on the STM32F427 + * directly, following steps outlined in STM32F4 Reference + * Manual (Chapter 24) for STM32F4xx family. */ + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + int i; + (void)os; + + /* enable RNG peripheral clock */ + RCC->AHB2ENR |= RCC_AHB2ENR_RNGEN; + + /* enable RNG interrupt, set IE bit in RNG->CR register */ + RNG->CR |= RNG_CR_IE; + + /* enable RNG, set RNGEN bit in RNG->CR. Activates RNG, + * RNG_LFSR, and error detector */ + RNG->CR |= RNG_CR_RNGEN; + + /* verify no errors, make sure SEIS and CEIS bits are 0 + * in RNG->SR register */ + if (RNG->SR & (RNG_SR_SECS | RNG_SR_CECS)) + return RNG_FAILURE_E; + + for (i = 0; i < (int)sz; i++) { + /* wait until RNG number is ready */ + while ((RNG->SR & RNG_SR_DRDY) == 0) { } + + /* get value */ + output[i] = RNG->DR; + } + + return 0; + } + + #else + + /* Generate a RNG seed using the STM32 Standard Peripheral Library */ + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + int i; + (void)os; + + /* enable RNG clock source */ + RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_RNG, ENABLE); + + /* reset RNG */ + RNG_DeInit(); + + /* enable RNG peripheral */ + RNG_Cmd(ENABLE); + + /* verify no errors with RNG_CLK or Seed */ + if (RNG_GetFlagStatus(RNG_FLAG_SECS | RNG_FLAG_CECS) != RESET) + return RNG_FAILURE_E; + + for (i = 0; i < (int)sz; i++) { + /* wait until RNG number is ready */ + while (RNG_GetFlagStatus(RNG_FLAG_DRDY) == RESET) { } + + /* get value */ + output[i] = RNG_GetRandomNumber(); + } + + return 0; + } + #endif /* WOLFSSL_STM32_CUBEMX */ + +#elif defined(WOLFSSL_TIRTOS) + + #include + #include + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + int i; + srand(xdc_runtime_Timestamp_get32()); + + for (i = 0; i < sz; i++ ) { + output[i] = rand() % 256; + if ((i % 8) == 7) { + srand(xdc_runtime_Timestamp_get32()); + } + } + + return 0; + } + +#elif defined(WOLFSSL_PB) + + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + word32 i; + for (i = 0; i < sz; i++) + output[i] = UTL_Rand(); + + (void)os; + + return 0; + } + +#elif defined(WOLFSSL_NUCLEUS) +#include "nucleus.h" +#include "kernel/plus_common.h" + +#warning "potential for not enough entropy, currently being used for testing" +int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) +{ + int i; + srand(NU_Get_Time_Stamp()); + + for (i = 0; i < sz; i++ ) { + output[i] = rand() % 256; + if ((i % 8) == 7) { + srand(NU_Get_Time_Stamp()); + } + } + + return 0; +} +#elif defined(WOLFSSL_DEOS) && !defined(CUSTOM_RAND_GENERATE) + #include "stdlib.h" + + #warning "potential for not enough entropy, currently being used for testing Deos" + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + int i; + int seed = XTIME(0); + (void)os; + + for (i = 0; i < sz; i++ ) { + output[i] = rand_r(&seed) % 256; + if ((i % 8) == 7) { + seed = XTIME(0); + rand_r(&seed); + } + } + + return 0; + } +#elif defined(WOLFSSL_VXWORKS) + + #include + + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) { + STATUS status; + + #ifdef VXWORKS_SIM + /* cannot generate true entropy with VxWorks simulator */ + #warning "not enough entropy, simulator for testing only" + int i = 0; + + for (i = 0; i < 1000; i++) { + randomAddTimeStamp(); + } + #endif + + status = randBytes (output, sz); + if (status == ERROR) { + return RNG_FAILURE_E; + } + + return 0; + } + +#elif defined(WOLFSSL_NRF51) + #include "app_error.h" + #include "nrf_drv_rng.h" + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + int remaining = sz, length, pos = 0; + uint8_t available; + uint32_t err_code; + + (void)os; + + /* Make sure RNG is running */ + err_code = nrf_drv_rng_init(NULL); + if (err_code != NRF_SUCCESS && err_code != NRF_ERROR_INVALID_STATE) { + return -1; + } + + while (remaining > 0) { + err_code = nrf_drv_rng_bytes_available(&available); + if (err_code == NRF_SUCCESS) { + length = (remaining < available) ? remaining : available; + if (length > 0) { + err_code = nrf_drv_rng_rand(&output[pos], length); + remaining -= length; + pos += length; + } + } + + if (err_code != NRF_SUCCESS) { + break; + } + } + + return (err_code == NRF_SUCCESS) ? 0 : -1; + } + +#elif defined(HAVE_WNR) + + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + if (os == NULL || output == NULL || wnr_ctx == NULL || + wnr_timeout < 0) { + return BAD_FUNC_ARG; + } + + if (wnr_mutex_init == 0) { + WOLFSSL_MSG("netRandom context must be created before use"); + return RNG_FAILURE_E; + } + + if (wc_LockMutex(&wnr_mutex) != 0) { + WOLFSSL_MSG("Bad Lock Mutex wnr_mutex\n"); + return BAD_MUTEX_E; + } + + if (wnr_get_entropy(wnr_ctx, wnr_timeout, output, sz, sz) != + WNR_ERROR_NONE) + return RNG_FAILURE_E; + + wc_UnLockMutex(&wnr_mutex); + + return 0; + } + +#elif defined(WOLFSSL_ATMEL) + #include + + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + int ret = 0; + + (void)os; + if (output == NULL) { + return BUFFER_E; + } + + ret = atmel_get_random_number(sz, output); + + return ret; + } + +#elif defined(INTIME_RTOS) + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + int ret = 0; + + (void)os; + + if (output == NULL) { + return BUFFER_E; + } + + /* Note: Investigate better solution */ + /* no return to check */ + arc4random_buf(output, sz); + + return ret; + } + +#elif defined(WOLFSSL_WICED) + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + int ret; + (void)os; + + if (output == NULL || UINT16_MAX < sz) { + return BUFFER_E; + } + + if ((ret = wiced_crypto_get_random((void*) output, sz) ) + != WICED_SUCCESS) { + return ret; + } + + return ret; + } + +#elif defined(IDIRECT_DEV_RANDOM) + + extern int getRandom( int sz, unsigned char *output ); + + int GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + int num_bytes_returned = 0; + + num_bytes_returned = getRandom( (int) sz, (unsigned char *) output ); + + return 0; + } + +#elif (defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG)) + + #include + #include + + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + Buffer buf[1]; + int ret = 0; + int times = 1000, i; + + (void)os; + + if (output == NULL) { + return BUFFER_E; + } + + buf[0].BufferType = DataBuffer | LastBuffer; + buf[0].TheAddress = (Address)output; + buf[0].Length = sz; + + /* Check Waiting to make sure entropy is ready */ + for (i = 0; i < times; i++) { + ret = wc_caamAddAndWait(buf, NULL, CAAM_ENTROPY); + if (ret == Success) { + break; + } + + /* driver could be waiting for entropy */ + if (ret != RAN_BLOCK_E) { + return ret; + } + usleep(100); + } + + if (i == times && ret != Success) { + return RNG_FAILURE_E; + } + else { /* Success case */ + ret = 0; + } + + return ret; + } + +#elif defined(WOLFSSL_APACHE_MYNEWT) + + #include + #include "os/os_time.h" + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + int i; + srand(os_time_get()); + + for (i = 0; i < sz; i++ ) { + output[i] = rand() % 256; + if ((i % 8) == 7) { + srand(os_time_get()); + } + } + + return 0; + } + +#elif defined(WOLFSSL_BEKEN) + unsigned long os_random(void); + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + word32 rand; + while (sz > 0) { + word32 len = sizeof(rand); + if (sz < len) + len = sz; + /* Get one random 32-bit word from hw RNG */ + rand = os_random( ); + XMEMCPY(output, &rand, len); + output += len; + sz -= len; + } + + return 0; + } +#elif defined(WOLFSSL_ESPIDF) + #if defined(WOLFSSL_ESPWROOM32) || defined(WOLFSSL_ESPWROOM32SE) + #include + + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + word32 rand; + while (sz > 0) { + word32 len = sizeof(rand); + if (sz < len) + len = sz; + /* Get one random 32-bit word from hw RNG */ + rand = esp_random( ); + XMEMCPY(output, &rand, len); + output += len; + sz -= len; + } + + return 0; + } + #endif /* end WOLFSSL_ESPWROOM32 */ + +#elif defined(CUSTOM_RAND_GENERATE_BLOCK) + /* #define CUSTOM_RAND_GENERATE_BLOCK myRngFunc + * extern int myRngFunc(byte* output, word32 sz); + */ + +#elif defined(WOLFSSL_SAFERTOS) || defined(WOLFSSL_LEANPSK) || \ + defined(WOLFSSL_IAR_ARM) || defined(WOLFSSL_MDK_ARM) || \ + defined(WOLFSSL_uITRON4) || defined(WOLFSSL_uTKERNEL2) || \ + defined(WOLFSSL_LPC43xx) || defined(WOLFSSL_STM32F2xx) || \ + defined(MBED) || defined(WOLFSSL_EMBOS) || \ + defined(WOLFSSL_GENSEED_FORTEST) || defined(WOLFSSL_CHIBIOS) || \ + defined(WOLFSSL_CONTIKI) + + /* these platforms do not have a default random seed and + you'll need to implement your own wc_GenerateSeed or define via + CUSTOM_RAND_GENERATE_BLOCK */ + + #define USE_TEST_GENSEED + +#elif defined(WOLFSSL_ZEPHYR) + + #include + #ifndef _POSIX_C_SOURCE + #include + #else + #include + #endif + + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + int ret = 0; + word32 rand; + while (sz > 0) { + word32 len = sizeof(rand); + if (sz < len) + len = sz; + rand = sys_rand32_get(); + XMEMCPY(output, &rand, len); + output += len; + sz -= len; + } + + return ret; + } + +#elif defined(WOLFSSL_TELIT_M2MB) + + #include "stdlib.h" + static long get_timestamp(void) { + long myTime = 0; + INT32 fd = m2mb_rtc_open("/dev/rtc0", 0); + if (fd >= 0) { + M2MB_RTC_TIMEVAL_T timeval; + m2mb_rtc_ioctl(fd, M2MB_RTC_IOCTL_GET_TIMEVAL, &timeval); + myTime = timeval.msec; + m2mb_rtc_close(fd); + } + return myTime; + } + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + int i; + srand(get_timestamp()); + for (i = 0; i < sz; i++ ) { + output[i] = rand() % 256; + if ((i % 8) == 7) { + srand(get_timestamp()); + } + } + return 0; + } + +#elif defined(NO_DEV_RANDOM) + + #error "you need to write an os specific wc_GenerateSeed() here" + + /* + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + return 0; + } + */ + +#else + + /* may block */ + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + int ret = 0; + +#ifdef WOLF_CRYPTO_CB + if (os != NULL && os->devId != INVALID_DEVID) { + ret = wc_CryptoCb_RandomSeed(os, output, sz); + if (ret != CRYPTOCB_UNAVAILABLE) + return ret; + /* fall-through when unavailable */ + ret = 0; /* reset error code */ + } +#endif + + #ifdef HAVE_INTEL_RDSEED + if (IS_INTEL_RDSEED(intel_flags)) { + ret = wc_GenerateSeed_IntelRD(NULL, output, sz); + if (ret == 0) { + /* success, we're done */ + return ret; + } + #ifdef FORCE_FAILURE_RDSEED + /* don't fallback to /dev/urandom */ + return ret; + #else + /* reset error and fallback to using /dev/urandom */ + ret = 0; + #endif + } + #endif /* HAVE_INTEL_RDSEED */ + + #ifndef NO_DEV_URANDOM /* way to disable use of /dev/urandom */ + os->fd = open("/dev/urandom", O_RDONLY); + if (os->fd == -1) + #endif + { + /* may still have /dev/random */ + os->fd = open("/dev/random", O_RDONLY); + if (os->fd == -1) + return OPEN_RAN_E; + } + + while (sz) { + int len = (int)read(os->fd, output, sz); + if (len == -1) { + ret = READ_RAN_E; + break; + } + + sz -= len; + output += len; + + if (sz) { + #if defined(BLOCKING) || defined(WC_RNG_BLOCKING) + sleep(0); /* context switch */ + #else + ret = RAN_BLOCK_E; + break; + #endif + } + } + close(os->fd); + + return ret; + } + +#endif + +#ifdef USE_TEST_GENSEED + #ifndef _MSC_VER + #warning "write a real random seed!!!!, just for testing now" + #else + #pragma message("Warning: write a real random seed!!!!, just for testing now") + #endif + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + word32 i; + for (i = 0; i < sz; i++ ) + output[i] = i; + + (void)os; + + return 0; + } +#endif + + +/* End wc_GenerateSeed */ +#endif /* WC_NO_RNG */ +#endif /* HAVE_FIPS */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/ripemd.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/ripemd.c new file mode 100755 index 0000000..670b318 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/ripemd.c @@ -0,0 +1,366 @@ +/* ripemd.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifdef WOLFSSL_RIPEMD + +#include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#include + +int wc_InitRipeMd(RipeMd* ripemd) +{ + if (ripemd == NULL) { + return BAD_FUNC_ARG; + } + + ripemd->digest[0] = 0x67452301L; + ripemd->digest[1] = 0xEFCDAB89L; + ripemd->digest[2] = 0x98BADCFEL; + ripemd->digest[3] = 0x10325476L; + ripemd->digest[4] = 0xC3D2E1F0L; + + ripemd->buffLen = 0; + ripemd->loLen = 0; + ripemd->hiLen = 0; + + return 0; +} + + +/* for all */ +#define F(x, y, z) (x ^ y ^ z) +#define G(x, y, z) (z ^ (x & (y^z))) +#define H(x, y, z) (z ^ (x | ~y)) +#define I(x, y, z) (y ^ (z & (x^y))) +#define J(x, y, z) (x ^ (y | ~z)) + +#define k0 0 +#define k1 0x5a827999 +#define k2 0x6ed9eba1 +#define k3 0x8f1bbcdc +#define k4 0xa953fd4e +#define k5 0x50a28be6 +#define k6 0x5c4dd124 +#define k7 0x6d703ef3 +#define k8 0x7a6d76e9 +#define k9 0 + +/* for 160 and 320 */ +#define Subround(f, a, b, c, d, e, x, s, k) \ + a += f(b, c, d) + x + k;\ + a = rotlFixed((word32)a, s) + e;\ + c = rotlFixed((word32)c, 10U) + +static void Transform(RipeMd* ripemd) +{ + word32 a1, b1, c1, d1, e1, a2, b2, c2, d2, e2; + a1 = a2 = ripemd->digest[0]; + b1 = b2 = ripemd->digest[1]; + c1 = c2 = ripemd->digest[2]; + d1 = d2 = ripemd->digest[3]; + e1 = e2 = ripemd->digest[4]; + + Subround(F, a1, b1, c1, d1, e1, ripemd->buffer[ 0], 11, k0); + Subround(F, e1, a1, b1, c1, d1, ripemd->buffer[ 1], 14, k0); + Subround(F, d1, e1, a1, b1, c1, ripemd->buffer[ 2], 15, k0); + Subround(F, c1, d1, e1, a1, b1, ripemd->buffer[ 3], 12, k0); + Subround(F, b1, c1, d1, e1, a1, ripemd->buffer[ 4], 5, k0); + Subround(F, a1, b1, c1, d1, e1, ripemd->buffer[ 5], 8, k0); + Subround(F, e1, a1, b1, c1, d1, ripemd->buffer[ 6], 7, k0); + Subround(F, d1, e1, a1, b1, c1, ripemd->buffer[ 7], 9, k0); + Subround(F, c1, d1, e1, a1, b1, ripemd->buffer[ 8], 11, k0); + Subround(F, b1, c1, d1, e1, a1, ripemd->buffer[ 9], 13, k0); + Subround(F, a1, b1, c1, d1, e1, ripemd->buffer[10], 14, k0); + Subround(F, e1, a1, b1, c1, d1, ripemd->buffer[11], 15, k0); + Subround(F, d1, e1, a1, b1, c1, ripemd->buffer[12], 6, k0); + Subround(F, c1, d1, e1, a1, b1, ripemd->buffer[13], 7, k0); + Subround(F, b1, c1, d1, e1, a1, ripemd->buffer[14], 9, k0); + Subround(F, a1, b1, c1, d1, e1, ripemd->buffer[15], 8, k0); + + Subround(G, e1, a1, b1, c1, d1, ripemd->buffer[ 7], 7, k1); + Subround(G, d1, e1, a1, b1, c1, ripemd->buffer[ 4], 6, k1); + Subround(G, c1, d1, e1, a1, b1, ripemd->buffer[13], 8, k1); + Subround(G, b1, c1, d1, e1, a1, ripemd->buffer[ 1], 13, k1); + Subround(G, a1, b1, c1, d1, e1, ripemd->buffer[10], 11, k1); + Subround(G, e1, a1, b1, c1, d1, ripemd->buffer[ 6], 9, k1); + Subround(G, d1, e1, a1, b1, c1, ripemd->buffer[15], 7, k1); + Subround(G, c1, d1, e1, a1, b1, ripemd->buffer[ 3], 15, k1); + Subround(G, b1, c1, d1, e1, a1, ripemd->buffer[12], 7, k1); + Subround(G, a1, b1, c1, d1, e1, ripemd->buffer[ 0], 12, k1); + Subround(G, e1, a1, b1, c1, d1, ripemd->buffer[ 9], 15, k1); + Subround(G, d1, e1, a1, b1, c1, ripemd->buffer[ 5], 9, k1); + Subround(G, c1, d1, e1, a1, b1, ripemd->buffer[ 2], 11, k1); + Subround(G, b1, c1, d1, e1, a1, ripemd->buffer[14], 7, k1); + Subround(G, a1, b1, c1, d1, e1, ripemd->buffer[11], 13, k1); + Subround(G, e1, a1, b1, c1, d1, ripemd->buffer[ 8], 12, k1); + + Subround(H, d1, e1, a1, b1, c1, ripemd->buffer[ 3], 11, k2); + Subround(H, c1, d1, e1, a1, b1, ripemd->buffer[10], 13, k2); + Subround(H, b1, c1, d1, e1, a1, ripemd->buffer[14], 6, k2); + Subround(H, a1, b1, c1, d1, e1, ripemd->buffer[ 4], 7, k2); + Subround(H, e1, a1, b1, c1, d1, ripemd->buffer[ 9], 14, k2); + Subround(H, d1, e1, a1, b1, c1, ripemd->buffer[15], 9, k2); + Subround(H, c1, d1, e1, a1, b1, ripemd->buffer[ 8], 13, k2); + Subround(H, b1, c1, d1, e1, a1, ripemd->buffer[ 1], 15, k2); + Subround(H, a1, b1, c1, d1, e1, ripemd->buffer[ 2], 14, k2); + Subround(H, e1, a1, b1, c1, d1, ripemd->buffer[ 7], 8, k2); + Subround(H, d1, e1, a1, b1, c1, ripemd->buffer[ 0], 13, k2); + Subround(H, c1, d1, e1, a1, b1, ripemd->buffer[ 6], 6, k2); + Subround(H, b1, c1, d1, e1, a1, ripemd->buffer[13], 5, k2); + Subround(H, a1, b1, c1, d1, e1, ripemd->buffer[11], 12, k2); + Subround(H, e1, a1, b1, c1, d1, ripemd->buffer[ 5], 7, k2); + Subround(H, d1, e1, a1, b1, c1, ripemd->buffer[12], 5, k2); + + Subround(I, c1, d1, e1, a1, b1, ripemd->buffer[ 1], 11, k3); + Subround(I, b1, c1, d1, e1, a1, ripemd->buffer[ 9], 12, k3); + Subround(I, a1, b1, c1, d1, e1, ripemd->buffer[11], 14, k3); + Subround(I, e1, a1, b1, c1, d1, ripemd->buffer[10], 15, k3); + Subround(I, d1, e1, a1, b1, c1, ripemd->buffer[ 0], 14, k3); + Subround(I, c1, d1, e1, a1, b1, ripemd->buffer[ 8], 15, k3); + Subround(I, b1, c1, d1, e1, a1, ripemd->buffer[12], 9, k3); + Subround(I, a1, b1, c1, d1, e1, ripemd->buffer[ 4], 8, k3); + Subround(I, e1, a1, b1, c1, d1, ripemd->buffer[13], 9, k3); + Subround(I, d1, e1, a1, b1, c1, ripemd->buffer[ 3], 14, k3); + Subround(I, c1, d1, e1, a1, b1, ripemd->buffer[ 7], 5, k3); + Subround(I, b1, c1, d1, e1, a1, ripemd->buffer[15], 6, k3); + Subround(I, a1, b1, c1, d1, e1, ripemd->buffer[14], 8, k3); + Subround(I, e1, a1, b1, c1, d1, ripemd->buffer[ 5], 6, k3); + Subround(I, d1, e1, a1, b1, c1, ripemd->buffer[ 6], 5, k3); + Subround(I, c1, d1, e1, a1, b1, ripemd->buffer[ 2], 12, k3); + + Subround(J, b1, c1, d1, e1, a1, ripemd->buffer[ 4], 9, k4); + Subround(J, a1, b1, c1, d1, e1, ripemd->buffer[ 0], 15, k4); + Subround(J, e1, a1, b1, c1, d1, ripemd->buffer[ 5], 5, k4); + Subround(J, d1, e1, a1, b1, c1, ripemd->buffer[ 9], 11, k4); + Subround(J, c1, d1, e1, a1, b1, ripemd->buffer[ 7], 6, k4); + Subround(J, b1, c1, d1, e1, a1, ripemd->buffer[12], 8, k4); + Subround(J, a1, b1, c1, d1, e1, ripemd->buffer[ 2], 13, k4); + Subround(J, e1, a1, b1, c1, d1, ripemd->buffer[10], 12, k4); + Subround(J, d1, e1, a1, b1, c1, ripemd->buffer[14], 5, k4); + Subround(J, c1, d1, e1, a1, b1, ripemd->buffer[ 1], 12, k4); + Subround(J, b1, c1, d1, e1, a1, ripemd->buffer[ 3], 13, k4); + Subround(J, a1, b1, c1, d1, e1, ripemd->buffer[ 8], 14, k4); + Subround(J, e1, a1, b1, c1, d1, ripemd->buffer[11], 11, k4); + Subround(J, d1, e1, a1, b1, c1, ripemd->buffer[ 6], 8, k4); + Subround(J, c1, d1, e1, a1, b1, ripemd->buffer[15], 5, k4); + Subround(J, b1, c1, d1, e1, a1, ripemd->buffer[13], 6, k4); + + Subround(J, a2, b2, c2, d2, e2, ripemd->buffer[ 5], 8, k5); + Subround(J, e2, a2, b2, c2, d2, ripemd->buffer[14], 9, k5); + Subround(J, d2, e2, a2, b2, c2, ripemd->buffer[ 7], 9, k5); + Subround(J, c2, d2, e2, a2, b2, ripemd->buffer[ 0], 11, k5); + Subround(J, b2, c2, d2, e2, a2, ripemd->buffer[ 9], 13, k5); + Subround(J, a2, b2, c2, d2, e2, ripemd->buffer[ 2], 15, k5); + Subround(J, e2, a2, b2, c2, d2, ripemd->buffer[11], 15, k5); + Subround(J, d2, e2, a2, b2, c2, ripemd->buffer[ 4], 5, k5); + Subround(J, c2, d2, e2, a2, b2, ripemd->buffer[13], 7, k5); + Subround(J, b2, c2, d2, e2, a2, ripemd->buffer[ 6], 7, k5); + Subround(J, a2, b2, c2, d2, e2, ripemd->buffer[15], 8, k5); + Subround(J, e2, a2, b2, c2, d2, ripemd->buffer[ 8], 11, k5); + Subround(J, d2, e2, a2, b2, c2, ripemd->buffer[ 1], 14, k5); + Subround(J, c2, d2, e2, a2, b2, ripemd->buffer[10], 14, k5); + Subround(J, b2, c2, d2, e2, a2, ripemd->buffer[ 3], 12, k5); + Subround(J, a2, b2, c2, d2, e2, ripemd->buffer[12], 6, k5); + + Subround(I, e2, a2, b2, c2, d2, ripemd->buffer[ 6], 9, k6); + Subround(I, d2, e2, a2, b2, c2, ripemd->buffer[11], 13, k6); + Subround(I, c2, d2, e2, a2, b2, ripemd->buffer[ 3], 15, k6); + Subround(I, b2, c2, d2, e2, a2, ripemd->buffer[ 7], 7, k6); + Subround(I, a2, b2, c2, d2, e2, ripemd->buffer[ 0], 12, k6); + Subround(I, e2, a2, b2, c2, d2, ripemd->buffer[13], 8, k6); + Subround(I, d2, e2, a2, b2, c2, ripemd->buffer[ 5], 9, k6); + Subround(I, c2, d2, e2, a2, b2, ripemd->buffer[10], 11, k6); + Subround(I, b2, c2, d2, e2, a2, ripemd->buffer[14], 7, k6); + Subround(I, a2, b2, c2, d2, e2, ripemd->buffer[15], 7, k6); + Subround(I, e2, a2, b2, c2, d2, ripemd->buffer[ 8], 12, k6); + Subround(I, d2, e2, a2, b2, c2, ripemd->buffer[12], 7, k6); + Subround(I, c2, d2, e2, a2, b2, ripemd->buffer[ 4], 6, k6); + Subround(I, b2, c2, d2, e2, a2, ripemd->buffer[ 9], 15, k6); + Subround(I, a2, b2, c2, d2, e2, ripemd->buffer[ 1], 13, k6); + Subround(I, e2, a2, b2, c2, d2, ripemd->buffer[ 2], 11, k6); + + Subround(H, d2, e2, a2, b2, c2, ripemd->buffer[15], 9, k7); + Subround(H, c2, d2, e2, a2, b2, ripemd->buffer[ 5], 7, k7); + Subround(H, b2, c2, d2, e2, a2, ripemd->buffer[ 1], 15, k7); + Subround(H, a2, b2, c2, d2, e2, ripemd->buffer[ 3], 11, k7); + Subround(H, e2, a2, b2, c2, d2, ripemd->buffer[ 7], 8, k7); + Subround(H, d2, e2, a2, b2, c2, ripemd->buffer[14], 6, k7); + Subround(H, c2, d2, e2, a2, b2, ripemd->buffer[ 6], 6, k7); + Subround(H, b2, c2, d2, e2, a2, ripemd->buffer[ 9], 14, k7); + Subround(H, a2, b2, c2, d2, e2, ripemd->buffer[11], 12, k7); + Subround(H, e2, a2, b2, c2, d2, ripemd->buffer[ 8], 13, k7); + Subround(H, d2, e2, a2, b2, c2, ripemd->buffer[12], 5, k7); + Subround(H, c2, d2, e2, a2, b2, ripemd->buffer[ 2], 14, k7); + Subround(H, b2, c2, d2, e2, a2, ripemd->buffer[10], 13, k7); + Subround(H, a2, b2, c2, d2, e2, ripemd->buffer[ 0], 13, k7); + Subround(H, e2, a2, b2, c2, d2, ripemd->buffer[ 4], 7, k7); + Subround(H, d2, e2, a2, b2, c2, ripemd->buffer[13], 5, k7); + + Subround(G, c2, d2, e2, a2, b2, ripemd->buffer[ 8], 15, k8); + Subround(G, b2, c2, d2, e2, a2, ripemd->buffer[ 6], 5, k8); + Subround(G, a2, b2, c2, d2, e2, ripemd->buffer[ 4], 8, k8); + Subround(G, e2, a2, b2, c2, d2, ripemd->buffer[ 1], 11, k8); + Subround(G, d2, e2, a2, b2, c2, ripemd->buffer[ 3], 14, k8); + Subround(G, c2, d2, e2, a2, b2, ripemd->buffer[11], 14, k8); + Subround(G, b2, c2, d2, e2, a2, ripemd->buffer[15], 6, k8); + Subround(G, a2, b2, c2, d2, e2, ripemd->buffer[ 0], 14, k8); + Subround(G, e2, a2, b2, c2, d2, ripemd->buffer[ 5], 6, k8); + Subround(G, d2, e2, a2, b2, c2, ripemd->buffer[12], 9, k8); + Subround(G, c2, d2, e2, a2, b2, ripemd->buffer[ 2], 12, k8); + Subround(G, b2, c2, d2, e2, a2, ripemd->buffer[13], 9, k8); + Subround(G, a2, b2, c2, d2, e2, ripemd->buffer[ 9], 12, k8); + Subround(G, e2, a2, b2, c2, d2, ripemd->buffer[ 7], 5, k8); + Subround(G, d2, e2, a2, b2, c2, ripemd->buffer[10], 15, k8); + Subround(G, c2, d2, e2, a2, b2, ripemd->buffer[14], 8, k8); + + Subround(F, b2, c2, d2, e2, a2, ripemd->buffer[12], 8, k9); + Subround(F, a2, b2, c2, d2, e2, ripemd->buffer[15], 5, k9); + Subround(F, e2, a2, b2, c2, d2, ripemd->buffer[10], 12, k9); + Subround(F, d2, e2, a2, b2, c2, ripemd->buffer[ 4], 9, k9); + Subround(F, c2, d2, e2, a2, b2, ripemd->buffer[ 1], 12, k9); + Subround(F, b2, c2, d2, e2, a2, ripemd->buffer[ 5], 5, k9); + Subround(F, a2, b2, c2, d2, e2, ripemd->buffer[ 8], 14, k9); + Subround(F, e2, a2, b2, c2, d2, ripemd->buffer[ 7], 6, k9); + Subround(F, d2, e2, a2, b2, c2, ripemd->buffer[ 6], 8, k9); + Subround(F, c2, d2, e2, a2, b2, ripemd->buffer[ 2], 13, k9); + Subround(F, b2, c2, d2, e2, a2, ripemd->buffer[13], 6, k9); + Subround(F, a2, b2, c2, d2, e2, ripemd->buffer[14], 5, k9); + Subround(F, e2, a2, b2, c2, d2, ripemd->buffer[ 0], 15, k9); + Subround(F, d2, e2, a2, b2, c2, ripemd->buffer[ 3], 13, k9); + Subround(F, c2, d2, e2, a2, b2, ripemd->buffer[ 9], 11, k9); + Subround(F, b2, c2, d2, e2, a2, ripemd->buffer[11], 11, k9); + + c1 = ripemd->digest[1] + c1 + d2; + ripemd->digest[1] = ripemd->digest[2] + d1 + e2; + ripemd->digest[2] = ripemd->digest[3] + e1 + a2; + ripemd->digest[3] = ripemd->digest[4] + a1 + b2; + ripemd->digest[4] = ripemd->digest[0] + b1 + c2; + ripemd->digest[0] = c1; +} + + +static WC_INLINE void AddLength(RipeMd* ripemd, word32 len) +{ + word32 tmp = ripemd->loLen; + if ( (ripemd->loLen += len) < tmp) + ripemd->hiLen++; /* carry low to high */ +} + + +int wc_RipeMdUpdate(RipeMd* ripemd, const byte* data, word32 len) +{ + /* do block size increments */ + byte* local; + + if (ripemd == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + + local = (byte*)ripemd->buffer; + + while (len) { + word32 add = min(len, RIPEMD_BLOCK_SIZE - ripemd->buffLen); + XMEMCPY(&local[ripemd->buffLen], data, add); + + ripemd->buffLen += add; + data += add; + len -= add; + + if (ripemd->buffLen == RIPEMD_BLOCK_SIZE) { + #ifdef BIG_ENDIAN_ORDER + ByteReverseWords(ripemd->buffer, ripemd->buffer, + RIPEMD_BLOCK_SIZE); + #endif + Transform(ripemd); + AddLength(ripemd, RIPEMD_BLOCK_SIZE); + ripemd->buffLen = 0; + } + } + return 0; +} + + +int wc_RipeMdFinal(RipeMd* ripemd, byte* hash) +{ + byte* local; + + if (ripemd == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + + local = (byte*)ripemd->buffer; + + AddLength(ripemd, ripemd->buffLen); /* before adding pads */ + + local[ripemd->buffLen++] = 0x80; /* add 1 */ + + /* pad with zeros */ + if (ripemd->buffLen > RIPEMD_PAD_SIZE) { + XMEMSET(&local[ripemd->buffLen], 0, RIPEMD_BLOCK_SIZE - ripemd->buffLen); + ripemd->buffLen += RIPEMD_BLOCK_SIZE - ripemd->buffLen; + + #ifdef BIG_ENDIAN_ORDER + ByteReverseWords(ripemd->buffer, ripemd->buffer, RIPEMD_BLOCK_SIZE); + #endif + Transform(ripemd); + ripemd->buffLen = 0; + } + XMEMSET(&local[ripemd->buffLen], 0, RIPEMD_PAD_SIZE - ripemd->buffLen); + + /* put lengths in bits */ + ripemd->loLen = ripemd->loLen << 3; + ripemd->hiLen = (ripemd->loLen >> (8*sizeof(ripemd->loLen) - 3)) + + (ripemd->hiLen << 3); + + /* store lengths */ + #ifdef BIG_ENDIAN_ORDER + ByteReverseWords(ripemd->buffer, ripemd->buffer, RIPEMD_BLOCK_SIZE); + #endif + /* ! length ordering dependent on digest endian type ! */ + XMEMCPY(&local[RIPEMD_PAD_SIZE], &ripemd->loLen, sizeof(word32)); + XMEMCPY(&local[RIPEMD_PAD_SIZE + sizeof(word32)], &ripemd->hiLen, + sizeof(word32)); + + Transform(ripemd); + #ifdef BIG_ENDIAN_ORDER + ByteReverseWords(ripemd->digest, ripemd->digest, RIPEMD_DIGEST_SIZE); + #endif + XMEMCPY(hash, ripemd->digest, RIPEMD_DIGEST_SIZE); + + return wc_InitRipeMd(ripemd); /* reset state */ +} + + +#endif /* WOLFSSL_RIPEMD */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/rsa.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/rsa.c new file mode 100755 index 0000000..78b69f6 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/rsa.c @@ -0,0 +1,3837 @@ +/* rsa.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include +#include + +#ifndef NO_RSA + +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + + /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ + #define FIPS_NO_WRAPPERS + + #ifdef USE_WINDOWS_API + #pragma code_seg(".fipsA$e") + #pragma const_seg(".fipsB$e") + #endif +#endif + +#include + +#ifdef WOLFSSL_AFALG_XILINX_RSA +#include +#endif + +#ifdef WOLFSSL_HAVE_SP_RSA +#include +#endif + +/* +Possible RSA enable options: + * NO_RSA: Overall control of RSA default: on (not defined) + * WC_RSA_BLINDING: Uses Blinding w/ Private Ops default: off + Note: slower by ~20% + * WOLFSSL_KEY_GEN: Allows Private Key Generation default: off + * RSA_LOW_MEM: NON CRT Private Operations, less memory default: off + * WC_NO_RSA_OAEP: Disables RSA OAEP padding default: on (not defined) + * WC_RSA_NONBLOCK: Enables support for RSA non-blocking default: off + * WC_RSA_NONBLOCK_TIME:Enables support for time based blocking default: off + * time calculation. +*/ + +/* +RSA Key Size Configuration: + * FP_MAX_BITS: With USE_FAST_MATH only default: 4096 + If USE_FAST_MATH then use this to override default. + Value is key size * 2. Example: RSA 3072 = 6144 +*/ + + +/* If building for old FIPS. */ +#if defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) + +int wc_InitRsaKey(RsaKey* key, void* ptr) +{ + if (key == NULL) { + return BAD_FUNC_ARG; + } + + return InitRsaKey_fips(key, ptr); +} + + +int wc_InitRsaKey_ex(RsaKey* key, void* ptr, int devId) +{ + (void)devId; + if (key == NULL) { + return BAD_FUNC_ARG; + } + return InitRsaKey_fips(key, ptr); +} + + +int wc_FreeRsaKey(RsaKey* key) +{ + return FreeRsaKey_fips(key); +} + + +#ifndef WOLFSSL_RSA_VERIFY_ONLY +int wc_RsaPublicEncrypt(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key, WC_RNG* rng) +{ + if (in == NULL || out == NULL || key == NULL || rng == NULL) { + return BAD_FUNC_ARG; + } + return RsaPublicEncrypt_fips(in, inLen, out, outLen, key, rng); +} +#endif + + +#ifndef WOLFSSL_RSA_PUBLIC_ONLY +int wc_RsaPrivateDecryptInline(byte* in, word32 inLen, byte** out, + RsaKey* key) +{ + if (in == NULL || out == NULL || key == NULL) { + return BAD_FUNC_ARG; + } + return RsaPrivateDecryptInline_fips(in, inLen, out, key); +} + + +int wc_RsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key) +{ + if (in == NULL || out == NULL || key == NULL) { + return BAD_FUNC_ARG; + } + return RsaPrivateDecrypt_fips(in, inLen, out, outLen, key); +} + + +int wc_RsaSSL_Sign(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key, WC_RNG* rng) +{ + if (in == NULL || out == NULL || key == NULL || inLen == 0) { + return BAD_FUNC_ARG; + } + return RsaSSL_Sign_fips(in, inLen, out, outLen, key, rng); +} +#endif + + +int wc_RsaSSL_VerifyInline(byte* in, word32 inLen, byte** out, RsaKey* key) +{ + if (in == NULL || out == NULL || key == NULL) { + return BAD_FUNC_ARG; + } + return RsaSSL_VerifyInline_fips(in, inLen, out, key); +} + + +int wc_RsaSSL_Verify(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key) +{ + if (in == NULL || out == NULL || key == NULL || inLen == 0) { + return BAD_FUNC_ARG; + } + return RsaSSL_Verify_fips(in, inLen, out, outLen, key); +} + + +int wc_RsaEncryptSize(RsaKey* key) +{ + if (key == NULL) { + return BAD_FUNC_ARG; + } + return RsaEncryptSize_fips(key); +} + + +#ifndef WOLFSSL_RSA_VERIFY_ONLY +int wc_RsaFlattenPublicKey(RsaKey* key, byte* a, word32* aSz, byte* b, + word32* bSz) +{ + + /* not specified as fips so not needing _fips */ + return RsaFlattenPublicKey(key, a, aSz, b, bSz); +} +#endif + + +#ifdef WOLFSSL_KEY_GEN + int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) + { + return MakeRsaKey(key, size, e, rng); + } +#endif + + +/* these are functions in asn and are routed to wolfssl/wolfcrypt/asn.c +* wc_RsaPrivateKeyDecode +* wc_RsaPublicKeyDecode +*/ + +#else /* else build without fips, or for new fips */ + +#include +#include +#ifdef WOLF_CRYPTO_CB + #include +#endif +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + + +enum { + RSA_STATE_NONE = 0, + + RSA_STATE_ENCRYPT_PAD, + RSA_STATE_ENCRYPT_EXPTMOD, + RSA_STATE_ENCRYPT_RES, + + RSA_STATE_DECRYPT_EXPTMOD, + RSA_STATE_DECRYPT_UNPAD, + RSA_STATE_DECRYPT_RES, +}; + + +static void wc_RsaCleanup(RsaKey* key) +{ +#ifndef WOLFSSL_RSA_VERIFY_INLINE + if (key && key->data) { + /* make sure any allocated memory is free'd */ + if (key->dataIsAlloc) { + #ifndef WOLFSSL_RSA_PUBLIC_ONLY + if (key->type == RSA_PRIVATE_DECRYPT || + key->type == RSA_PRIVATE_ENCRYPT) { + ForceZero(key->data, key->dataLen); + } + #endif + XFREE(key->data, key->heap, DYNAMIC_TYPE_WOLF_BIGINT); + key->dataIsAlloc = 0; + } + key->data = NULL; + key->dataLen = 0; + } +#else + (void)key; +#endif +} + +int wc_InitRsaKey_ex(RsaKey* key, void* heap, int devId) +{ + int ret = 0; + + if (key == NULL) { + return BAD_FUNC_ARG; + } + + XMEMSET(key, 0, sizeof(RsaKey)); + + key->type = RSA_TYPE_UNKNOWN; + key->state = RSA_STATE_NONE; + key->heap = heap; +#ifndef WOLFSSL_RSA_VERIFY_INLINE + key->dataIsAlloc = 0; + key->data = NULL; +#endif + key->dataLen = 0; +#ifdef WC_RSA_BLINDING + key->rng = NULL; +#endif + +#ifdef WOLF_CRYPTO_CB + key->devId = devId; +#else + (void)devId; +#endif + +#ifdef WOLFSSL_ASYNC_CRYPT + #ifdef WOLFSSL_CERT_GEN + XMEMSET(&key->certSignCtx, 0, sizeof(CertSignCtx)); + #endif + + #ifdef WC_ASYNC_ENABLE_RSA + /* handle as async */ + ret = wolfAsync_DevCtxInit(&key->asyncDev, WOLFSSL_ASYNC_MARKER_RSA, + key->heap, devId); + if (ret != 0) + return ret; + #endif /* WC_ASYNC_ENABLE_RSA */ +#endif /* WOLFSSL_ASYNC_CRYPT */ + +#ifndef WOLFSSL_RSA_PUBLIC_ONLY + ret = mp_init_multi(&key->n, &key->e, NULL, NULL, NULL, NULL); + if (ret != MP_OKAY) + return ret; + +#if !defined(WOLFSSL_KEY_GEN) && !defined(OPENSSL_EXTRA) && defined(RSA_LOW_MEM) + ret = mp_init_multi(&key->d, &key->p, &key->q, NULL, NULL, NULL); +#else + ret = mp_init_multi(&key->d, &key->p, &key->q, &key->dP, &key->dQ, &key->u); +#endif + if (ret != MP_OKAY) { + mp_clear(&key->n); + mp_clear(&key->e); + return ret; + } +#else + ret = mp_init(&key->n); + if (ret != MP_OKAY) + return ret; + ret = mp_init(&key->e); + if (ret != MP_OKAY) { + mp_clear(&key->n); + return ret; + } +#endif + +#ifdef WOLFSSL_XILINX_CRYPT + key->pubExp = 0; + key->mod = NULL; +#endif + +#ifdef WOLFSSL_AFALG_XILINX_RSA + key->alFd = WC_SOCK_NOTSET; + key->rdFd = WC_SOCK_NOTSET; +#endif + + return ret; +} + +int wc_InitRsaKey(RsaKey* key, void* heap) +{ + return wc_InitRsaKey_ex(key, heap, INVALID_DEVID); +} + +#ifdef HAVE_PKCS11 +int wc_InitRsaKey_Id(RsaKey* key, unsigned char* id, int len, void* heap, + int devId) +{ + int ret = 0; + + if (key == NULL) + ret = BAD_FUNC_ARG; + if (ret == 0 && (len < 0 || len > RSA_MAX_ID_LEN)) + ret = BUFFER_E; + + if (ret == 0) + ret = wc_InitRsaKey_ex(key, heap, devId); + + if (ret == 0 && id != NULL && len != 0) { + XMEMCPY(key->id, id, len); + key->idLen = len; + } + + return ret; +} +#endif + + +#ifdef WOLFSSL_XILINX_CRYPT +#define MAX_E_SIZE 4 +/* Used to setup hardware state + * + * key the RSA key to setup + * + * returns 0 on success + */ +int wc_InitRsaHw(RsaKey* key) +{ + unsigned char* m; /* RSA modulous */ + word32 e = 0; /* RSA public exponent */ + int mSz; + int eSz; + + if (key == NULL) { + return BAD_FUNC_ARG; + } + + mSz = mp_unsigned_bin_size(&(key->n)); + m = (unsigned char*)XMALLOC(mSz, key->heap, DYNAMIC_TYPE_KEY); + if (m == 0) { + return MEMORY_E; + } + + if (mp_to_unsigned_bin(&(key->n), m) != MP_OKAY) { + WOLFSSL_MSG("Unable to get RSA key modulus"); + XFREE(m, key->heap, DYNAMIC_TYPE_KEY); + return MP_READ_E; + } + + eSz = mp_unsigned_bin_size(&(key->e)); + if (eSz > MAX_E_SIZE) { + WOLFSSL_MSG("Exponent of size 4 bytes expected"); + XFREE(m, key->heap, DYNAMIC_TYPE_KEY); + return BAD_FUNC_ARG; + } + + if (mp_to_unsigned_bin(&(key->e), (byte*)&e + (MAX_E_SIZE - eSz)) + != MP_OKAY) { + XFREE(m, key->heap, DYNAMIC_TYPE_KEY); + WOLFSSL_MSG("Unable to get RSA key exponent"); + return MP_READ_E; + } + + /* check for existing mod buffer to avoid memory leak */ + if (key->mod != NULL) { + XFREE(key->mod, key->heap, DYNAMIC_TYPE_KEY); + } + + key->pubExp = e; + key->mod = m; + + if (XSecure_RsaInitialize(&(key->xRsa), key->mod, NULL, + (byte*)&(key->pubExp)) != XST_SUCCESS) { + WOLFSSL_MSG("Unable to initialize RSA on hardware"); + XFREE(m, key->heap, DYNAMIC_TYPE_KEY); + return BAD_STATE_E; + } + +#ifdef WOLFSSL_XILINX_PATCH + /* currently a patch of xsecure_rsa.c for 2048 bit keys */ + if (wc_RsaEncryptSize(key) == 256) { + if (XSecure_RsaSetSize(&(key->xRsa), 2048) != XST_SUCCESS) { + WOLFSSL_MSG("Unable to set RSA key size on hardware"); + XFREE(m, key->heap, DYNAMIC_TYPE_KEY); + return BAD_STATE_E; + } + } +#endif + return 0; +} /* WOLFSSL_XILINX_CRYPT*/ + +#elif defined(WOLFSSL_CRYPTOCELL) + +int wc_InitRsaHw(RsaKey* key) +{ + CRYSError_t ret = 0; + byte e[3]; + word32 eSz = sizeof(e); + byte n[256]; + word32 nSz = sizeof(n); + byte d[256]; + word32 dSz = sizeof(d); + byte p[128]; + word32 pSz = sizeof(p); + byte q[128]; + word32 qSz = sizeof(q); + + if (key == NULL) { + return BAD_FUNC_ARG; + } + + ret = wc_RsaExportKey(key, e, &eSz, n, &nSz, d, &dSz, p, &pSz, q, &qSz); + if (ret != 0) + return MP_READ_E; + + ret = CRYS_RSA_Build_PubKey(&key->ctx.pubKey, e, eSz, n, nSz); + if (ret != SA_SILIB_RET_OK){ + WOLFSSL_MSG("CRYS_RSA_Build_PubKey failed"); + return ret; + } + + ret = CRYS_RSA_Build_PrivKey(&key->ctx.privKey, d, dSz, e, eSz, n, nSz); + + if (ret != SA_SILIB_RET_OK){ + WOLFSSL_MSG("CRYS_RSA_Build_PrivKey failed"); + return ret; + } + key->type = RSA_PRIVATE; + return 0; +} +static int cc310_RSA_GenerateKeyPair(RsaKey* key, int size, long e) +{ + CRYSError_t ret = 0; + CRYS_RSAKGData_t KeyGenData; + CRYS_RSAKGFipsContext_t FipsCtx; + byte ex[3]; + uint16_t eSz = sizeof(ex); + byte n[256]; + uint16_t nSz = sizeof(n); + + ret = CRYS_RSA_KG_GenerateKeyPair(&wc_rndState, + wc_rndGenVectFunc, + (byte*)&e, + 3*sizeof(uint8_t), + size, + &key->ctx.privKey, + &key->ctx.pubKey, + &KeyGenData, + &FipsCtx); + + if (ret != SA_SILIB_RET_OK){ + WOLFSSL_MSG("CRYS_RSA_KG_GenerateKeyPair failed"); + return ret; + } + + ret = CRYS_RSA_Get_PubKey(&key->ctx.pubKey, ex, &eSz, n, &nSz); + if (ret != SA_SILIB_RET_OK){ + WOLFSSL_MSG("CRYS_RSA_Get_PubKey failed"); + return ret; + } + ret = wc_RsaPublicKeyDecodeRaw(n, nSz, ex, eSz, key); + + key->type = RSA_PRIVATE; + + return ret; +} +#endif /* WOLFSSL_CRYPTOCELL */ + +int wc_FreeRsaKey(RsaKey* key) +{ + int ret = 0; + + if (key == NULL) { + return BAD_FUNC_ARG; + } + + wc_RsaCleanup(key); + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA) + wolfAsync_DevCtxFree(&key->asyncDev, WOLFSSL_ASYNC_MARKER_RSA); +#endif + +#ifndef WOLFSSL_RSA_PUBLIC_ONLY + if (key->type == RSA_PRIVATE) { +#if defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || !defined(RSA_LOW_MEM) + mp_forcezero(&key->u); + mp_forcezero(&key->dQ); + mp_forcezero(&key->dP); +#endif + mp_forcezero(&key->q); + mp_forcezero(&key->p); + mp_forcezero(&key->d); + } + /* private part */ +#if defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || !defined(RSA_LOW_MEM) + mp_clear(&key->u); + mp_clear(&key->dQ); + mp_clear(&key->dP); +#endif + mp_clear(&key->q); + mp_clear(&key->p); + mp_clear(&key->d); +#endif /* WOLFSSL_RSA_PUBLIC_ONLY */ + + /* public part */ + mp_clear(&key->e); + mp_clear(&key->n); + +#ifdef WOLFSSL_XILINX_CRYPT + XFREE(key->mod, key->heap, DYNAMIC_TYPE_KEY); + key->mod = NULL; +#endif + +#ifdef WOLFSSL_AFALG_XILINX_RSA + /* make sure that sockets are closed on cleanup */ + if (key->alFd > 0) { + close(key->alFd); + key->alFd = WC_SOCK_NOTSET; + } + if (key->rdFd > 0) { + close(key->rdFd); + key->rdFd = WC_SOCK_NOTSET; + } +#endif + + return ret; +} + +#ifndef WOLFSSL_RSA_PUBLIC_ONLY +#if defined(WOLFSSL_KEY_GEN) && !defined(WOLFSSL_NO_RSA_KEY_CHECK) +/* Check the pair-wise consistency of the RSA key. + * From NIST SP 800-56B, section 6.4.1.1. + * Verify that k = (k^e)^d, for some k: 1 < k < n-1. */ +int wc_CheckRsaKey(RsaKey* key) +{ +#if defined(WOLFSSL_CRYPTOCELL) + return 0; +#endif +#ifdef WOLFSSL_SMALL_STACK + mp_int *k = NULL, *tmp = NULL; +#else + mp_int k[1], tmp[1]; +#endif + int ret = 0; + +#ifdef WOLFSSL_SMALL_STACK + k = (mp_int*)XMALLOC(sizeof(mp_int) * 2, NULL, DYNAMIC_TYPE_RSA); + if (k == NULL) + return MEMORY_E; + tmp = k + 1; +#endif + + if (mp_init_multi(k, tmp, NULL, NULL, NULL, NULL) != MP_OKAY) + ret = MP_INIT_E; + + if (ret == 0) { + if (key == NULL) + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + if (mp_set_int(k, 0x2342) != MP_OKAY) + ret = MP_READ_E; + } + +#ifdef WOLFSSL_SP_RSA +#ifndef WOLFSSL_SP_NO_2048 + if (mp_count_bits(&key->n) == 2048) { + ret = sp_ModExp_2048(k, &key->e, &key->n, tmp); + if (ret != 0) + ret = MP_EXPTMOD_E; + ret = sp_ModExp_2048(tmp, &key->d, &key->n, tmp); + if (ret != 0) + ret = MP_EXPTMOD_E; + } + else +#endif +#ifndef WOLFSSL_SP_NO_3072 + if (mp_count_bits(&key->n) == 3072) { + ret = sp_ModExp_3072(k, &key->e, &key->n, tmp); + if (ret != 0) + ret = MP_EXPTMOD_E; + ret = sp_ModExp_3072(tmp, &key->d, &key->n, tmp); + if (ret != 0) + ret = MP_EXPTMOD_E; + } + else +#endif +#endif +#ifdef WOLFSSL_SP_MATH + { + ret = WC_KEY_SIZE_E; + } +#else + { + if (ret == 0) { + if (mp_exptmod(k, &key->e, &key->n, tmp) != MP_OKAY) + ret = MP_EXPTMOD_E; + } + + if (ret == 0) { + if (mp_exptmod(tmp, &key->d, &key->n, tmp) != MP_OKAY) + ret = MP_EXPTMOD_E; + } + } +#endif + + if (ret == 0) { + if (mp_cmp(k, tmp) != MP_EQ) + ret = RSA_KEY_PAIR_E; + } + + mp_forcezero(tmp); + mp_clear(tmp); + mp_clear(k); +#ifdef WOLFSSL_SMALL_STACK + XFREE(k, NULL, DYNAMIC_TYPE_RSA); +#endif + + return ret; +} +#endif +#endif + + +#if !defined(WC_NO_RSA_OAEP) || defined(WC_RSA_PSS) +/* Uses MGF1 standard as a mask generation function + hType: hash type used + seed: seed to use for generating mask + seedSz: size of seed buffer + out: mask output after generation + outSz: size of output buffer + */ +static int RsaMGF1(enum wc_HashType hType, byte* seed, word32 seedSz, + byte* out, word32 outSz, void* heap) +{ + byte* tmp; + /* needs to be large enough for seed size plus counter(4) */ + byte tmpA[WC_MAX_DIGEST_SIZE + 4]; + byte tmpF; /* 1 if dynamic memory needs freed */ + word32 tmpSz; + int hLen; + int ret; + word32 counter; + word32 idx; + hLen = wc_HashGetDigestSize(hType); + counter = 0; + idx = 0; + + (void)heap; + + /* check error return of wc_HashGetDigestSize */ + if (hLen < 0) { + return hLen; + } + + /* if tmp is not large enough than use some dynamic memory */ + if ((seedSz + 4) > sizeof(tmpA) || (word32)hLen > sizeof(tmpA)) { + /* find largest amount of memory needed which will be the max of + * hLen and (seedSz + 4) since tmp is used to store the hash digest */ + tmpSz = ((seedSz + 4) > (word32)hLen)? seedSz + 4: (word32)hLen; + tmp = (byte*)XMALLOC(tmpSz, heap, DYNAMIC_TYPE_RSA_BUFFER); + if (tmp == NULL) { + return MEMORY_E; + } + tmpF = 1; /* make sure to free memory when done */ + } + else { + /* use array on the stack */ + tmpSz = sizeof(tmpA); + tmp = tmpA; + tmpF = 0; /* no need to free memory at end */ + } + + do { + int i = 0; + XMEMCPY(tmp, seed, seedSz); + + /* counter to byte array appended to tmp */ + tmp[seedSz] = (counter >> 24) & 0xFF; + tmp[seedSz + 1] = (counter >> 16) & 0xFF; + tmp[seedSz + 2] = (counter >> 8) & 0xFF; + tmp[seedSz + 3] = (counter) & 0xFF; + + /* hash and append to existing output */ + if ((ret = wc_Hash(hType, tmp, (seedSz + 4), tmp, tmpSz)) != 0) { + /* check for if dynamic memory was needed, then free */ + if (tmpF) { + XFREE(tmp, heap, DYNAMIC_TYPE_RSA_BUFFER); + } + return ret; + } + + for (i = 0; i < hLen && idx < outSz; i++) { + out[idx++] = tmp[i]; + } + counter++; + } while (idx < outSz); + + /* check for if dynamic memory was needed, then free */ + if (tmpF) { + XFREE(tmp, heap, DYNAMIC_TYPE_RSA_BUFFER); + } + + return 0; +} + +/* helper function to direct which mask generation function is used + switeched on type input + */ +static int RsaMGF(int type, byte* seed, word32 seedSz, byte* out, + word32 outSz, void* heap) +{ + int ret; + + switch(type) { + #ifndef NO_SHA + case WC_MGF1SHA1: + ret = RsaMGF1(WC_HASH_TYPE_SHA, seed, seedSz, out, outSz, heap); + break; + #endif + #ifndef NO_SHA256 + #ifdef WOLFSSL_SHA224 + case WC_MGF1SHA224: + ret = RsaMGF1(WC_HASH_TYPE_SHA224, seed, seedSz, out, outSz, heap); + break; + #endif + case WC_MGF1SHA256: + ret = RsaMGF1(WC_HASH_TYPE_SHA256, seed, seedSz, out, outSz, heap); + break; + #endif + #ifdef WOLFSSL_SHA384 + case WC_MGF1SHA384: + ret = RsaMGF1(WC_HASH_TYPE_SHA384, seed, seedSz, out, outSz, heap); + break; + #endif + #ifdef WOLFSSL_SHA512 + case WC_MGF1SHA512: + ret = RsaMGF1(WC_HASH_TYPE_SHA512, seed, seedSz, out, outSz, heap); + break; + #endif + default: + WOLFSSL_MSG("Unknown MGF type: check build options"); + ret = BAD_FUNC_ARG; + } + + /* in case of default avoid unused warning */ + (void)seed; + (void)seedSz; + (void)out; + (void)outSz; + (void)heap; + + return ret; +} +#endif /* !WC_NO_RSA_OAEP */ + + +/* Padding */ +#ifndef WOLFSSL_RSA_VERIFY_ONLY +#ifndef WC_NO_RNG +#ifndef WC_NO_RSA_OAEP +static int RsaPad_OAEP(const byte* input, word32 inputLen, byte* pkcsBlock, + word32 pkcsBlockLen, byte padValue, WC_RNG* rng, + enum wc_HashType hType, int mgf, byte* optLabel, word32 labelLen, + void* heap) +{ + int ret; + int hLen; + int psLen; + int i; + word32 idx; + + byte* dbMask; + + #ifdef WOLFSSL_SMALL_STACK + byte* lHash = NULL; + byte* seed = NULL; + #else + /* must be large enough to contain largest hash */ + byte lHash[WC_MAX_DIGEST_SIZE]; + byte seed[ WC_MAX_DIGEST_SIZE]; + #endif + + /* no label is allowed, but catch if no label provided and length > 0 */ + if (optLabel == NULL && labelLen > 0) { + return BUFFER_E; + } + + /* limit of label is the same as limit of hash function which is massive */ + hLen = wc_HashGetDigestSize(hType); + if (hLen < 0) { + return hLen; + } + + #ifdef WOLFSSL_SMALL_STACK + lHash = (byte*)XMALLOC(hLen, heap, DYNAMIC_TYPE_RSA_BUFFER); + if (lHash == NULL) { + return MEMORY_E; + } + seed = (byte*)XMALLOC(hLen, heap, DYNAMIC_TYPE_RSA_BUFFER); + if (seed == NULL) { + XFREE(lHash, heap, DYNAMIC_TYPE_RSA_BUFFER); + return MEMORY_E; + } + #else + /* hLen should never be larger than lHash since size is max digest size, + but check before blindly calling wc_Hash */ + if ((word32)hLen > sizeof(lHash)) { + WOLFSSL_MSG("OAEP lHash to small for digest!!"); + return MEMORY_E; + } + #endif + + if ((ret = wc_Hash(hType, optLabel, labelLen, lHash, hLen)) != 0) { + WOLFSSL_MSG("OAEP hash type possibly not supported or lHash to small"); + #ifdef WOLFSSL_SMALL_STACK + XFREE(lHash, heap, DYNAMIC_TYPE_RSA_BUFFER); + XFREE(seed, heap, DYNAMIC_TYPE_RSA_BUFFER); + #endif + return ret; + } + + /* handles check of location for idx as well as psLen, cast to int to check + for pkcsBlockLen(k) - 2 * hLen - 2 being negative + This check is similar to decryption where k > 2 * hLen + 2 as msg + size approaches 0. In decryption if k is less than or equal -- then there + is no possible room for msg. + k = RSA key size + hLen = hash digest size -- will always be >= 0 at this point + */ + if ((word32)(2 * hLen + 2) > pkcsBlockLen) { + WOLFSSL_MSG("OAEP pad error hash to big for RSA key size"); + #ifdef WOLFSSL_SMALL_STACK + XFREE(lHash, heap, DYNAMIC_TYPE_RSA_BUFFER); + XFREE(seed, heap, DYNAMIC_TYPE_RSA_BUFFER); + #endif + return BAD_FUNC_ARG; + } + + if (inputLen > (pkcsBlockLen - 2 * hLen - 2)) { + WOLFSSL_MSG("OAEP pad error message too long"); + #ifdef WOLFSSL_SMALL_STACK + XFREE(lHash, heap, DYNAMIC_TYPE_RSA_BUFFER); + XFREE(seed, heap, DYNAMIC_TYPE_RSA_BUFFER); + #endif + return BAD_FUNC_ARG; + } + + /* concatenate lHash || PS || 0x01 || msg */ + idx = pkcsBlockLen - 1 - inputLen; + psLen = pkcsBlockLen - inputLen - 2 * hLen - 2; + if (pkcsBlockLen < inputLen) { /*make sure not writing over end of buffer */ + #ifdef WOLFSSL_SMALL_STACK + XFREE(lHash, heap, DYNAMIC_TYPE_RSA_BUFFER); + XFREE(seed, heap, DYNAMIC_TYPE_RSA_BUFFER); + #endif + return BUFFER_E; + } + XMEMCPY(pkcsBlock + (pkcsBlockLen - inputLen), input, inputLen); + pkcsBlock[idx--] = 0x01; /* PS and M separator */ + while (psLen > 0 && idx > 0) { + pkcsBlock[idx--] = 0x00; + psLen--; + } + + idx = idx - hLen + 1; + XMEMCPY(pkcsBlock + idx, lHash, hLen); + + /* generate random seed */ + if ((ret = wc_RNG_GenerateBlock(rng, seed, hLen)) != 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(lHash, heap, DYNAMIC_TYPE_RSA_BUFFER); + XFREE(seed, heap, DYNAMIC_TYPE_RSA_BUFFER); + #endif + return ret; + } + + /* create maskedDB from dbMask */ + dbMask = (byte*)XMALLOC(pkcsBlockLen - hLen - 1, heap, DYNAMIC_TYPE_RSA); + if (dbMask == NULL) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(lHash, heap, DYNAMIC_TYPE_RSA_BUFFER); + XFREE(seed, heap, DYNAMIC_TYPE_RSA_BUFFER); + #endif + return MEMORY_E; + } + XMEMSET(dbMask, 0, pkcsBlockLen - hLen - 1); /* help static analyzer */ + + ret = RsaMGF(mgf, seed, hLen, dbMask, pkcsBlockLen - hLen - 1, heap); + if (ret != 0) { + XFREE(dbMask, heap, DYNAMIC_TYPE_RSA); + #ifdef WOLFSSL_SMALL_STACK + XFREE(lHash, heap, DYNAMIC_TYPE_RSA_BUFFER); + XFREE(seed, heap, DYNAMIC_TYPE_RSA_BUFFER); + #endif + return ret; + } + + i = 0; + idx = hLen + 1; + while (idx < pkcsBlockLen && (word32)i < (pkcsBlockLen - hLen -1)) { + pkcsBlock[idx] = dbMask[i++] ^ pkcsBlock[idx]; + idx++; + } + XFREE(dbMask, heap, DYNAMIC_TYPE_RSA); + + + /* create maskedSeed from seedMask */ + idx = 0; + pkcsBlock[idx++] = 0x00; + /* create seedMask inline */ + if ((ret = RsaMGF(mgf, pkcsBlock + hLen + 1, pkcsBlockLen - hLen - 1, + pkcsBlock + 1, hLen, heap)) != 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(lHash, heap, DYNAMIC_TYPE_RSA_BUFFER); + XFREE(seed, heap, DYNAMIC_TYPE_RSA_BUFFER); + #endif + return ret; + } + + /* xor created seedMask with seed to make maskedSeed */ + i = 0; + while (idx < (word32)(hLen + 1) && i < hLen) { + pkcsBlock[idx] = pkcsBlock[idx] ^ seed[i++]; + idx++; + } + + #ifdef WOLFSSL_SMALL_STACK + XFREE(lHash, heap, DYNAMIC_TYPE_RSA_BUFFER); + XFREE(seed, heap, DYNAMIC_TYPE_RSA_BUFFER); + #endif + (void)padValue; + + return 0; +} +#endif /* !WC_NO_RSA_OAEP */ + +#ifdef WC_RSA_PSS + +/* 0x00 .. 0x00 0x01 | Salt | Gen Hash | 0xbc + * XOR MGF over all bytes down to end of Salt + * Gen Hash = HASH(8 * 0x00 | Message Hash | Salt) + * + * input Digest of the message. + * inputLen Length of digest. + * pkcsBlock Buffer to write to. + * pkcsBlockLen Length of buffer to write to. + * rng Random number generator (for salt). + * htype Hash function to use. + * mgf Mask generation function. + * saltLen Length of salt to put in padding. + * bits Length of key in bits. + * heap Used for dynamic memory allocation. + * returns 0 on success, PSS_SALTLEN_E when the salt length is invalid + * and other negative values on error. + */ +static int RsaPad_PSS(const byte* input, word32 inputLen, byte* pkcsBlock, + word32 pkcsBlockLen, WC_RNG* rng, enum wc_HashType hType, int mgf, + int saltLen, int bits, void* heap) +{ + int ret; + int hLen, i; + byte* s; + byte* m; + byte* h; + byte salt[WC_MAX_DIGEST_SIZE]; + + hLen = wc_HashGetDigestSize(hType); + if (hLen < 0) + return hLen; + + if (saltLen == -1) { + saltLen = hLen; + #ifdef WOLFSSL_SHA512 + /* See FIPS 186-4 section 5.5 item (e). */ + if (bits == 1024 && hLen == WC_SHA512_DIGEST_SIZE) + saltLen = RSA_PSS_SALT_MAX_SZ; + #endif + } + else if (saltLen > hLen || saltLen < -1) + return PSS_SALTLEN_E; + if ((int)pkcsBlockLen - hLen < saltLen + 2) + return PSS_SALTLEN_E; + + s = m = pkcsBlock; + XMEMSET(m, 0, RSA_PSS_PAD_SZ); + m += RSA_PSS_PAD_SZ; + XMEMCPY(m, input, inputLen); + m += inputLen; + if ((ret = wc_RNG_GenerateBlock(rng, salt, saltLen)) != 0) + return ret; + XMEMCPY(m, salt, saltLen); + m += saltLen; + + h = pkcsBlock + pkcsBlockLen - 1 - hLen; + if ((ret = wc_Hash(hType, s, (word32)(m - s), h, hLen)) != 0) + return ret; + pkcsBlock[pkcsBlockLen - 1] = RSA_PSS_PAD_TERM; + + ret = RsaMGF(mgf, h, hLen, pkcsBlock, pkcsBlockLen - hLen - 1, heap); + if (ret != 0) + return ret; + pkcsBlock[0] &= (1 << ((bits - 1) & 0x7)) - 1; + + m = pkcsBlock + pkcsBlockLen - 1 - saltLen - hLen - 1; + *(m++) ^= 0x01; + for (i = 0; i < saltLen; i++) + m[i] ^= salt[i]; + + return 0; +} +#endif /* WC_RSA_PSS */ + +static int RsaPad(const byte* input, word32 inputLen, byte* pkcsBlock, + word32 pkcsBlockLen, byte padValue, WC_RNG* rng) +{ + if (input == NULL || inputLen == 0 || pkcsBlock == NULL || + pkcsBlockLen == 0) { + return BAD_FUNC_ARG; + } + + pkcsBlock[0] = 0x0; /* set first byte to zero and advance */ + pkcsBlock++; pkcsBlockLen--; + pkcsBlock[0] = padValue; /* insert padValue */ + + if (padValue == RSA_BLOCK_TYPE_1) { + if (pkcsBlockLen < inputLen + 2) { + WOLFSSL_MSG("RsaPad error, invalid length"); + return RSA_PAD_E; + } + + /* pad with 0xff bytes */ + XMEMSET(&pkcsBlock[1], 0xFF, pkcsBlockLen - inputLen - 2); + } + else { +#ifndef WOLFSSL_RSA_VERIFY_ONLY + /* pad with non-zero random bytes */ + word32 padLen, i; + int ret; + + if (pkcsBlockLen < inputLen + 1) { + WOLFSSL_MSG("RsaPad error, invalid length"); + return RSA_PAD_E; + } + + padLen = pkcsBlockLen - inputLen - 1; + ret = wc_RNG_GenerateBlock(rng, &pkcsBlock[1], padLen); + if (ret != 0) { + return ret; + } + + /* remove zeros */ + for (i = 1; i < padLen; i++) { + if (pkcsBlock[i] == 0) pkcsBlock[i] = 0x01; + } +#else + (void)rng; + return RSA_WRONG_TYPE_E; +#endif + } + + pkcsBlock[pkcsBlockLen-inputLen-1] = 0; /* separator */ + XMEMCPY(pkcsBlock+pkcsBlockLen-inputLen, input, inputLen); + + return 0; +} +#endif /* !WC_NO_RNG */ + +/* helper function to direct which padding is used */ +static int wc_RsaPad_ex(const byte* input, word32 inputLen, byte* pkcsBlock, + word32 pkcsBlockLen, byte padValue, WC_RNG* rng, int padType, + enum wc_HashType hType, int mgf, byte* optLabel, word32 labelLen, + int saltLen, int bits, void* heap) +{ + int ret; + + switch (padType) + { +#ifndef WC_NO_RNG + case WC_RSA_PKCSV15_PAD: + /*WOLFSSL_MSG("wolfSSL Using RSA PKCSV15 padding");*/ + ret = RsaPad(input, inputLen, pkcsBlock, pkcsBlockLen, + padValue, rng); + break; + + #ifndef WC_NO_RSA_OAEP + case WC_RSA_OAEP_PAD: + WOLFSSL_MSG("wolfSSL Using RSA OAEP padding"); + ret = RsaPad_OAEP(input, inputLen, pkcsBlock, pkcsBlockLen, + padValue, rng, hType, mgf, optLabel, labelLen, heap); + break; + #endif + + #ifdef WC_RSA_PSS + case WC_RSA_PSS_PAD: + WOLFSSL_MSG("wolfSSL Using RSA PSS padding"); + ret = RsaPad_PSS(input, inputLen, pkcsBlock, pkcsBlockLen, rng, + hType, mgf, saltLen, bits, heap); + break; + #endif +#endif /* !WC_NO_RNG */ + + #ifdef WC_RSA_NO_PADDING + case WC_RSA_NO_PAD: + WOLFSSL_MSG("wolfSSL Using NO padding"); + + /* In the case of no padding being used check that input is exactly + * the RSA key length */ + if (bits <= 0 || inputLen != ((word32)bits/WOLFSSL_BIT_SIZE)) { + WOLFSSL_MSG("Bad input size"); + ret = RSA_PAD_E; + } + else { + XMEMCPY(pkcsBlock, input, inputLen); + ret = 0; + } + break; + #endif + + default: + WOLFSSL_MSG("Unknown RSA Pad Type"); + ret = RSA_PAD_E; + } + + /* silence warning if not used with padding scheme */ + (void)input; + (void)inputLen; + (void)pkcsBlock; + (void)pkcsBlockLen; + (void)padValue; + (void)rng; + (void)padType; + (void)hType; + (void)mgf; + (void)optLabel; + (void)labelLen; + (void)saltLen; + (void)bits; + (void)heap; + + return ret; +} +#endif /* WOLFSSL_RSA_VERIFY_ONLY */ + + +/* UnPadding */ +#ifndef WC_NO_RSA_OAEP +/* UnPad plaintext, set start to *output, return length of plaintext, + * < 0 on error */ +static int RsaUnPad_OAEP(byte *pkcsBlock, unsigned int pkcsBlockLen, + byte **output, enum wc_HashType hType, int mgf, + byte* optLabel, word32 labelLen, void* heap) +{ + int hLen; + int ret; + byte h[WC_MAX_DIGEST_SIZE]; /* max digest size */ + byte* tmp; + word32 idx; + + /* no label is allowed, but catch if no label provided and length > 0 */ + if (optLabel == NULL && labelLen > 0) { + return BUFFER_E; + } + + hLen = wc_HashGetDigestSize(hType); + if ((hLen < 0) || (pkcsBlockLen < (2 * (word32)hLen + 2))) { + return BAD_FUNC_ARG; + } + + tmp = (byte*)XMALLOC(pkcsBlockLen, heap, DYNAMIC_TYPE_RSA_BUFFER); + if (tmp == NULL) { + return MEMORY_E; + } + XMEMSET(tmp, 0, pkcsBlockLen); + + /* find seedMask value */ + if ((ret = RsaMGF(mgf, (byte*)(pkcsBlock + (hLen + 1)), + pkcsBlockLen - hLen - 1, tmp, hLen, heap)) != 0) { + XFREE(tmp, heap, DYNAMIC_TYPE_RSA_BUFFER); + return ret; + } + + /* xor seedMask value with maskedSeed to get seed value */ + for (idx = 0; idx < (word32)hLen; idx++) { + tmp[idx] = tmp[idx] ^ pkcsBlock[1 + idx]; + } + + /* get dbMask value */ + if ((ret = RsaMGF(mgf, tmp, hLen, tmp + hLen, + pkcsBlockLen - hLen - 1, heap)) != 0) { + XFREE(tmp, NULL, DYNAMIC_TYPE_RSA_BUFFER); + return ret; + } + + /* get DB value by doing maskedDB xor dbMask */ + for (idx = 0; idx < (pkcsBlockLen - hLen - 1); idx++) { + pkcsBlock[hLen + 1 + idx] = pkcsBlock[hLen + 1 + idx] ^ tmp[idx + hLen]; + } + + /* done with use of tmp buffer */ + XFREE(tmp, heap, DYNAMIC_TYPE_RSA_BUFFER); + + /* advance idx to index of PS and msg separator, account for PS size of 0*/ + idx = hLen + 1 + hLen; + while (idx < pkcsBlockLen && pkcsBlock[idx] == 0) {idx++;} + + /* create hash of label for comparison with hash sent */ + if ((ret = wc_Hash(hType, optLabel, labelLen, h, hLen)) != 0) { + return ret; + } + + /* say no to chosen ciphertext attack. + Comparison of lHash, Y, and separator value needs to all happen in + constant time. + Attackers should not be able to get error condition from the timing of + these checks. + */ + ret = 0; + ret |= ConstantCompare(pkcsBlock + hLen + 1, h, hLen); + ret += pkcsBlock[idx++] ^ 0x01; /* separator value is 0x01 */ + ret += pkcsBlock[0] ^ 0x00; /* Y, the first value, should be 0 */ + + /* Return 0 data length on error. */ + idx = ctMaskSelInt(ctMaskEq(ret, 0), idx, pkcsBlockLen); + + /* adjust pointer to correct location in array and return size of M */ + *output = (byte*)(pkcsBlock + idx); + return pkcsBlockLen - idx; +} +#endif /* WC_NO_RSA_OAEP */ + +#ifdef WC_RSA_PSS +/* 0x00 .. 0x00 0x01 | Salt | Gen Hash | 0xbc + * MGF over all bytes down to end of Salt + * + * pkcsBlock Buffer holding decrypted data. + * pkcsBlockLen Length of buffer. + * htype Hash function to use. + * mgf Mask generation function. + * saltLen Length of salt to put in padding. + * bits Length of key in bits. + * heap Used for dynamic memory allocation. + * returns 0 on success, PSS_SALTLEN_E when the salt length is invalid, + * BAD_PADDING_E when the padding is not valid, MEMORY_E when allocation fails + * and other negative values on error. + */ +static int RsaUnPad_PSS(byte *pkcsBlock, unsigned int pkcsBlockLen, + byte **output, enum wc_HashType hType, int mgf, + int saltLen, int bits, void* heap) +{ + int ret; + byte* tmp; + int hLen, i; +#if defined(WOLFSSL_NO_MALLOC) && !defined(WOLFSSL_STATIC_MEMORY) + byte tmp_buf[RSA_MAX_SIZE/8]; + tmp = tmp_buf; + + if (pkcsBlockLen > RSA_MAX_SIZE/8) { + return MEMORY_E; + } +#endif + + hLen = wc_HashGetDigestSize(hType); + if (hLen < 0) + return hLen; + + if (saltLen == -1) { + saltLen = hLen; + #ifdef WOLFSSL_SHA512 + /* See FIPS 186-4 section 5.5 item (e). */ + if (bits == 1024 && hLen == WC_SHA512_DIGEST_SIZE) + saltLen = RSA_PSS_SALT_MAX_SZ; + #endif + } + else if (saltLen > hLen || saltLen < -1) + return PSS_SALTLEN_E; + if ((int)pkcsBlockLen - hLen < saltLen + 2) + return PSS_SALTLEN_E; + + if (pkcsBlock[pkcsBlockLen - 1] != RSA_PSS_PAD_TERM) { + WOLFSSL_MSG("RsaUnPad_PSS: Padding Term Error"); + return BAD_PADDING_E; + } + +#if !defined(WOLFSSL_NO_MALLOC) || defined(WOLFSSL_STATIC_MEMORY) + tmp = (byte*)XMALLOC(pkcsBlockLen, heap, DYNAMIC_TYPE_RSA_BUFFER); + if (tmp == NULL) + return MEMORY_E; +#endif + + if ((ret = RsaMGF(mgf, pkcsBlock + pkcsBlockLen - 1 - hLen, hLen, + tmp, pkcsBlockLen - 1 - hLen, heap)) != 0) { + XFREE(tmp, heap, DYNAMIC_TYPE_RSA_BUFFER); + return ret; + } + + tmp[0] &= (1 << ((bits - 1) & 0x7)) - 1; + for (i = 0; i < (int)(pkcsBlockLen - 1 - saltLen - hLen - 1); i++) { + if (tmp[i] != pkcsBlock[i]) { + XFREE(tmp, heap, DYNAMIC_TYPE_RSA_BUFFER); + WOLFSSL_MSG("RsaUnPad_PSS: Padding Error Match"); + return BAD_PADDING_E; + } + } + if (tmp[i] != (pkcsBlock[i] ^ 0x01)) { + XFREE(tmp, heap, DYNAMIC_TYPE_RSA_BUFFER); + WOLFSSL_MSG("RsaUnPad_PSS: Padding Error End"); + return BAD_PADDING_E; + } + for (i++; i < (int)(pkcsBlockLen - 1 - hLen); i++) + pkcsBlock[i] ^= tmp[i]; + +#if !defined(WOLFSSL_NO_MALLOC) || defined(WOLFSSL_STATIC_MEMORY) + XFREE(tmp, heap, DYNAMIC_TYPE_RSA_BUFFER); +#endif + + *output = pkcsBlock + pkcsBlockLen - (hLen + saltLen + 1); + return saltLen + hLen; +} +#endif + +/* UnPad plaintext, set start to *output, return length of plaintext, + * < 0 on error */ +static int RsaUnPad(const byte *pkcsBlock, unsigned int pkcsBlockLen, + byte **output, byte padValue) +{ + int ret = BAD_FUNC_ARG; + word16 i; +#ifndef WOLFSSL_RSA_VERIFY_ONLY + byte invalid = 0; +#endif + + if (output == NULL || pkcsBlockLen == 0) { + return BAD_FUNC_ARG; + } + + if (padValue == RSA_BLOCK_TYPE_1) { + /* First byte must be 0x00 and Second byte, block type, 0x01 */ + if (pkcsBlock[0] != 0 || pkcsBlock[1] != RSA_BLOCK_TYPE_1) { + WOLFSSL_MSG("RsaUnPad error, invalid formatting"); + return RSA_PAD_E; + } + + /* check the padding until we find the separator */ + for (i = 2; i < pkcsBlockLen && pkcsBlock[i++] == 0xFF; ) { } + + /* Minimum of 11 bytes of pre-message data and must have separator. */ + if (i < RSA_MIN_PAD_SZ || pkcsBlock[i-1] != 0) { + WOLFSSL_MSG("RsaUnPad error, bad formatting"); + return RSA_PAD_E; + } + + *output = (byte *)(pkcsBlock + i); + ret = pkcsBlockLen - i; + } +#ifndef WOLFSSL_RSA_VERIFY_ONLY + else { + word16 j; + word16 pastSep = 0; + + /* Decrypted with private key - unpad must be constant time. */ + for (i = 0, j = 2; j < pkcsBlockLen; j++) { + /* Update i if not passed the separator and at separator. */ + i |= (~pastSep) & ctMask16Eq(pkcsBlock[j], 0x00) & (j + 1); + pastSep |= ctMask16Eq(pkcsBlock[j], 0x00); + } + + /* Minimum of 11 bytes of pre-message data - including leading 0x00. */ + invalid |= ctMaskLT(i, RSA_MIN_PAD_SZ); + /* Must have seen separator. */ + invalid |= ~pastSep; + /* First byte must be 0x00. */ + invalid |= ctMaskNotEq(pkcsBlock[0], 0x00); + /* Check against expected block type: padValue */ + invalid |= ctMaskNotEq(pkcsBlock[1], padValue); + + *output = (byte *)(pkcsBlock + i); + ret = ((int)~invalid) & (pkcsBlockLen - i); + } +#endif + + return ret; +} + +/* helper function to direct unpadding + * + * bits is the key modulus size in bits + */ +static int wc_RsaUnPad_ex(byte* pkcsBlock, word32 pkcsBlockLen, byte** out, + byte padValue, int padType, enum wc_HashType hType, + int mgf, byte* optLabel, word32 labelLen, int saltLen, + int bits, void* heap) +{ + int ret; + + switch (padType) { + case WC_RSA_PKCSV15_PAD: + /*WOLFSSL_MSG("wolfSSL Using RSA PKCSV15 un-padding");*/ + ret = RsaUnPad(pkcsBlock, pkcsBlockLen, out, padValue); + break; + + #ifndef WC_NO_RSA_OAEP + case WC_RSA_OAEP_PAD: + WOLFSSL_MSG("wolfSSL Using RSA OAEP un-padding"); + ret = RsaUnPad_OAEP((byte*)pkcsBlock, pkcsBlockLen, out, + hType, mgf, optLabel, labelLen, heap); + break; + #endif + + #ifdef WC_RSA_PSS + case WC_RSA_PSS_PAD: + WOLFSSL_MSG("wolfSSL Using RSA PSS un-padding"); + ret = RsaUnPad_PSS((byte*)pkcsBlock, pkcsBlockLen, out, hType, mgf, + saltLen, bits, heap); + break; + #endif + + #ifdef WC_RSA_NO_PADDING + case WC_RSA_NO_PAD: + WOLFSSL_MSG("wolfSSL Using NO un-padding"); + + /* In the case of no padding being used check that input is exactly + * the RSA key length */ + if (bits <= 0 || pkcsBlockLen != ((word32)bits/WOLFSSL_BIT_SIZE)) { + WOLFSSL_MSG("Bad input size"); + ret = RSA_PAD_E; + } + else { + if (out != NULL) { + *out = pkcsBlock; + } + ret = pkcsBlockLen; + } + break; + #endif /* WC_RSA_NO_PADDING */ + + default: + WOLFSSL_MSG("Unknown RSA UnPad Type"); + ret = RSA_PAD_E; + } + + /* silence warning if not used with padding scheme */ + (void)hType; + (void)mgf; + (void)optLabel; + (void)labelLen; + (void)saltLen; + (void)bits; + (void)heap; + + return ret; +} + +#if defined(WOLFSSL_XILINX_CRYPT) +/* + * Xilinx hardened crypto acceleration. + * + * Returns 0 on success and negative values on error. + */ +static int wc_RsaFunctionXil(const byte* in, word32 inLen, byte* out, + word32* outLen, int type, RsaKey* key, WC_RNG* rng) +{ + int ret = 0; + word32 keyLen, len; + (void)rng; + + keyLen = wc_RsaEncryptSize(key); + if (keyLen > *outLen) { + WOLFSSL_MSG("Output buffer is not big enough"); + return BAD_FUNC_ARG; + } + + if (inLen != keyLen) { + WOLFSSL_MSG("Expected that inLen equals RSA key length"); + return BAD_FUNC_ARG; + } + + switch(type) { + case RSA_PRIVATE_DECRYPT: + case RSA_PRIVATE_ENCRYPT: + /* Currently public exponent is loaded by default. + * In SDK 2017.1 RSA exponent values are expected to be of 4 bytes + * leading to private key operations with Xsecure_RsaDecrypt not being + * supported */ + ret = RSA_WRONG_TYPE_E; + break; + case RSA_PUBLIC_ENCRYPT: + case RSA_PUBLIC_DECRYPT: + if (XSecure_RsaDecrypt(&(key->xRsa), in, out) != XST_SUCCESS) { + ret = BAD_STATE_E; + } + break; + default: + ret = RSA_WRONG_TYPE_E; + } + + *outLen = keyLen; + + return ret; +} +#endif /* WOLFSSL_XILINX_CRYPT */ + +#ifdef WC_RSA_NONBLOCK +static int wc_RsaFunctionNonBlock(const byte* in, word32 inLen, byte* out, + word32* outLen, int type, RsaKey* key) +{ + int ret = 0; + word32 keyLen, len; + + if (key == NULL || key->nb == NULL) { + return BAD_FUNC_ARG; + } + + if (key->nb->exptmod.state == TFM_EXPTMOD_NB_INIT) { + if (mp_init(&key->nb->tmp) != MP_OKAY) { + ret = MP_INIT_E; + } + + if (ret == 0) { + if (mp_read_unsigned_bin(&key->nb->tmp, (byte*)in, inLen) != MP_OKAY) { + ret = MP_READ_E; + } + } + } + + if (ret == 0) { + switch(type) { + case RSA_PRIVATE_DECRYPT: + case RSA_PRIVATE_ENCRYPT: + ret = fp_exptmod_nb(&key->nb->exptmod, &key->nb->tmp, &key->d, + &key->n, &key->nb->tmp); + if (ret == FP_WOULDBLOCK) + return ret; + if (ret != MP_OKAY) + ret = MP_EXPTMOD_E; + break; + + case RSA_PUBLIC_ENCRYPT: + case RSA_PUBLIC_DECRYPT: + ret = fp_exptmod_nb(&key->nb->exptmod, &key->nb->tmp, &key->e, + &key->n, &key->nb->tmp); + if (ret == FP_WOULDBLOCK) + return ret; + if (ret != MP_OKAY) + ret = MP_EXPTMOD_E; + break; + default: + ret = RSA_WRONG_TYPE_E; + break; + } + } + + if (ret == 0) { + keyLen = wc_RsaEncryptSize(key); + if (keyLen > *outLen) + ret = RSA_BUFFER_E; + } + if (ret == 0) { + len = mp_unsigned_bin_size(&key->nb->tmp); + + /* pad front w/ zeros to match key length */ + while (len < keyLen) { + *out++ = 0x00; + len++; + } + + *outLen = keyLen; + + /* convert */ + if (mp_to_unsigned_bin(&key->nb->tmp, out) != MP_OKAY) { + ret = MP_TO_E; + } + } + + mp_clear(&key->nb->tmp); + + return ret; +} +#endif /* WC_RSA_NONBLOCK */ + +#ifdef WOLFSSL_AFALG_XILINX_RSA +#ifndef ERROR_OUT +#define ERROR_OUT(x) ret = (x); goto done +#endif + +static const char WC_TYPE_ASYMKEY[] = "skcipher"; +static const char WC_NAME_RSA[] = "xilinx-zynqmp-rsa"; +#ifndef MAX_XILINX_RSA_KEY + /* max key size of 4096 bits / 512 bytes */ + #define MAX_XILINX_RSA_KEY 512 +#endif +static const byte XILINX_RSA_FLAG[] = {0x1}; + + +/* AF_ALG implementation of RSA */ +static int wc_RsaFunctionSync(const byte* in, word32 inLen, byte* out, + word32* outLen, int type, RsaKey* key, WC_RNG* rng) +{ + struct msghdr msg; + struct cmsghdr* cmsg; + struct iovec iov; + byte* keyBuf = NULL; + word32 keyBufSz = 0; + char cbuf[CMSG_SPACE(4) + CMSG_SPACE(sizeof(struct af_alg_iv) + 1)] = {0}; + int ret = 0; + int op = 0; /* decryption vs encryption flag */ + word32 keyLen; + + /* input and output buffer need to be aligned */ + ALIGN64 byte outBuf[MAX_XILINX_RSA_KEY]; + ALIGN64 byte inBuf[MAX_XILINX_RSA_KEY]; + + XMEMSET(&msg, 0, sizeof(struct msghdr)); + (void)rng; + + keyLen = wc_RsaEncryptSize(key); + if (keyLen > *outLen) { + ERROR_OUT(RSA_BUFFER_E); + } + + if (keyLen > MAX_XILINX_RSA_KEY) { + WOLFSSL_MSG("RSA key size larger than supported"); + ERROR_OUT(BAD_FUNC_ARG); + } + + if ((keyBuf = (byte*)XMALLOC(keyLen * 2, key->heap, DYNAMIC_TYPE_KEY)) + == NULL) { + ERROR_OUT(MEMORY_E); + } + + if ((ret = mp_to_unsigned_bin(&(key->n), keyBuf)) != MP_OKAY) { + ERROR_OUT(MP_TO_E); + } + + switch(type) { + case RSA_PRIVATE_DECRYPT: + case RSA_PRIVATE_ENCRYPT: + op = 1; /* set as decrypt */ + { + keyBufSz = mp_unsigned_bin_size(&(key->d)); + if ((mp_to_unsigned_bin(&(key->d), keyBuf + keyLen)) + != MP_OKAY) { + ERROR_OUT(MP_TO_E); + } + } + break; + + case RSA_PUBLIC_DECRYPT: + case RSA_PUBLIC_ENCRYPT: { + word32 exp = 0; + word32 eSz = mp_unsigned_bin_size(&(key->e)); + if ((mp_to_unsigned_bin(&(key->e), (byte*)&exp + + (sizeof(word32) - eSz))) != MP_OKAY) { + ERROR_OUT(MP_TO_E); + } + keyBufSz = sizeof(word32); + XMEMCPY(keyBuf + keyLen, (byte*)&exp, keyBufSz); + break; + } + + default: + ERROR_OUT(RSA_WRONG_TYPE_E); + } + keyBufSz += keyLen; /* add size of modulus */ + + /* check for existing sockets before creating new ones */ + if (key->alFd > 0) { + close(key->alFd); + key->alFd = WC_SOCK_NOTSET; + } + if (key->rdFd > 0) { + close(key->rdFd); + key->rdFd = WC_SOCK_NOTSET; + } + + /* create new sockets and set the key to use */ + if ((key->alFd = wc_Afalg_Socket()) < 0) { + WOLFSSL_MSG("Unable to create socket"); + ERROR_OUT(key->alFd); + } + if ((key->rdFd = wc_Afalg_CreateRead(key->alFd, WC_TYPE_ASYMKEY, + WC_NAME_RSA)) < 0) { + WOLFSSL_MSG("Unable to bind and create read/send socket"); + ERROR_OUT(key->rdFd); + } + if ((ret = setsockopt(key->alFd, SOL_ALG, ALG_SET_KEY, keyBuf, + keyBufSz)) < 0) { + WOLFSSL_MSG("Error setting RSA key"); + ERROR_OUT(ret); + } + + msg.msg_control = cbuf; + msg.msg_controllen = sizeof(cbuf); + cmsg = CMSG_FIRSTHDR(&msg); + if ((ret = wc_Afalg_SetOp(cmsg, op)) < 0) { + ERROR_OUT(ret); + } + + /* set flag in IV spot, needed for Xilinx hardware acceleration use */ + cmsg = CMSG_NXTHDR(&msg, cmsg); + if ((ret = wc_Afalg_SetIv(cmsg, (byte*)XILINX_RSA_FLAG, + sizeof(XILINX_RSA_FLAG))) != 0) { + ERROR_OUT(ret); + } + + /* compose and send msg */ + XMEMCPY(inBuf, (byte*)in, inLen); /* for alignment */ + iov.iov_base = inBuf; + iov.iov_len = inLen; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + if ((ret = sendmsg(key->rdFd, &msg, 0)) <= 0) { + ERROR_OUT(WC_AFALG_SOCK_E); + } + + if ((ret = read(key->rdFd, outBuf, inLen)) <= 0) { + ERROR_OUT(WC_AFALG_SOCK_E); + } + XMEMCPY(out, outBuf, ret); + *outLen = keyLen; + +done: + /* clear key data and free buffer */ + if (keyBuf != NULL) { + ForceZero(keyBuf, keyBufSz); + } + XFREE(keyBuf, key->heap, DYNAMIC_TYPE_KEY); + + if (key->alFd > 0) { + close(key->alFd); + key->alFd = WC_SOCK_NOTSET; + } + if (key->rdFd > 0) { + close(key->rdFd); + key->rdFd = WC_SOCK_NOTSET; + } + + return ret; +} + +#else +static int wc_RsaFunctionSync(const byte* in, word32 inLen, byte* out, + word32* outLen, int type, RsaKey* key, WC_RNG* rng) +{ +#ifndef WOLFSSL_SP_MATH +#ifdef WOLFSSL_SMALL_STACK + mp_int* tmp = NULL; +#ifdef WC_RSA_BLINDING + mp_int* rnd = NULL; + mp_int* rndi = NULL; +#endif +#else + mp_int tmp[1]; +#ifdef WC_RSA_BLINDING + mp_int rnd[1], rndi[1]; +#endif +#endif + int ret = 0; + word32 keyLen = 0; +#endif + +#ifdef WOLFSSL_HAVE_SP_RSA +#ifndef WOLFSSL_SP_NO_2048 + if (mp_count_bits(&key->n) == 2048) { + switch(type) { +#ifndef WOLFSSL_RSA_PUBLIC_ONLY + case RSA_PRIVATE_DECRYPT: + case RSA_PRIVATE_ENCRYPT: + #ifdef WC_RSA_BLINDING + if (rng == NULL) + return MISSING_RNG_E; + #endif + #ifndef RSA_LOW_MEM + return sp_RsaPrivate_2048(in, inLen, &key->d, &key->p, &key->q, + &key->dP, &key->dQ, &key->u, &key->n, + out, outLen); + #else + return sp_RsaPrivate_2048(in, inLen, &key->d, &key->p, &key->q, + NULL, NULL, NULL, &key->n, out, outLen); + #endif +#endif + case RSA_PUBLIC_ENCRYPT: + case RSA_PUBLIC_DECRYPT: + return sp_RsaPublic_2048(in, inLen, &key->e, &key->n, out, outLen); + } + } +#endif +#ifndef WOLFSSL_SP_NO_3072 + if (mp_count_bits(&key->n) == 3072) { + switch(type) { +#ifndef WOLFSSL_RSA_PUBLIC_ONLY + case RSA_PRIVATE_DECRYPT: + case RSA_PRIVATE_ENCRYPT: + #ifdef WC_RSA_BLINDING + if (rng == NULL) + return MISSING_RNG_E; + #endif + #ifndef RSA_LOW_MEM + return sp_RsaPrivate_3072(in, inLen, &key->d, &key->p, &key->q, + &key->dP, &key->dQ, &key->u, &key->n, + out, outLen); + #else + return sp_RsaPrivate_3072(in, inLen, &key->d, &key->p, &key->q, + NULL, NULL, NULL, &key->n, out, outLen); + #endif +#endif + case RSA_PUBLIC_ENCRYPT: + case RSA_PUBLIC_DECRYPT: + return sp_RsaPublic_3072(in, inLen, &key->e, &key->n, out, outLen); + } + } +#endif +#endif /* WOLFSSL_HAVE_SP_RSA */ + +#ifdef WOLFSSL_SP_MATH + (void)rng; + WOLFSSL_MSG("SP Key Size Error"); + return WC_KEY_SIZE_E; +#else + (void)rng; + +#ifdef WOLFSSL_SMALL_STACK + tmp = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_RSA); + if (tmp == NULL) + return MEMORY_E; +#ifdef WC_RSA_BLINDING + rnd = (mp_int*)XMALLOC(sizeof(mp_int) * 2, key->heap, DYNAMIC_TYPE_RSA); + if (rnd == NULL) { + XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA); + return MEMORY_E; + } + rndi = rnd + 1; +#endif /* WC_RSA_BLINDING */ +#endif /* WOLFSSL_SMALL_STACK */ + + if (mp_init(tmp) != MP_OKAY) + ret = MP_INIT_E; + +#ifdef WC_RSA_BLINDING + if (ret == 0) { + if (type == RSA_PRIVATE_DECRYPT || type == RSA_PRIVATE_ENCRYPT) { + if (mp_init_multi(rnd, rndi, NULL, NULL, NULL, NULL) != MP_OKAY) { + mp_clear(tmp); + ret = MP_INIT_E; + } + } + } +#endif + +#ifndef TEST_UNPAD_CONSTANT_TIME + if (ret == 0 && mp_read_unsigned_bin(tmp, (byte*)in, inLen) != MP_OKAY) + ret = MP_READ_E; + + if (ret == 0) { + switch(type) { + #ifndef WOLFSSL_RSA_PUBLIC_ONLY + case RSA_PRIVATE_DECRYPT: + case RSA_PRIVATE_ENCRYPT: + { + #if defined(WC_RSA_BLINDING) && !defined(WC_NO_RNG) + /* blind */ + ret = mp_rand(rnd, get_digit_count(&key->n), rng); + + /* rndi = 1/rnd mod n */ + if (ret == 0 && mp_invmod(rnd, &key->n, rndi) != MP_OKAY) + ret = MP_INVMOD_E; + + /* rnd = rnd^e */ + if (ret == 0 && mp_exptmod(rnd, &key->e, &key->n, rnd) != MP_OKAY) + ret = MP_EXPTMOD_E; + + /* tmp = tmp*rnd mod n */ + if (ret == 0 && mp_mulmod(tmp, rnd, &key->n, tmp) != MP_OKAY) + ret = MP_MULMOD_E; + #endif /* WC_RSA_BLINDING && !WC_NO_RNG */ + + #ifdef RSA_LOW_MEM /* half as much memory but twice as slow */ + if (ret == 0 && mp_exptmod(tmp, &key->d, &key->n, tmp) != MP_OKAY) + ret = MP_EXPTMOD_E; + #else + if (ret == 0) { + #ifdef WOLFSSL_SMALL_STACK + mp_int* tmpa = NULL; + mp_int* tmpb = NULL; + #else + mp_int tmpa[1], tmpb[1]; + #endif + int cleara = 0, clearb = 0; + + #ifdef WOLFSSL_SMALL_STACK + tmpa = (mp_int*)XMALLOC(sizeof(mp_int) * 2, + key->heap, DYNAMIC_TYPE_RSA); + if (tmpa != NULL) + tmpb = tmpa + 1; + else + ret = MEMORY_E; + #endif + + if (ret == 0) { + if (mp_init(tmpa) != MP_OKAY) + ret = MP_INIT_E; + else + cleara = 1; + } + + if (ret == 0) { + if (mp_init(tmpb) != MP_OKAY) + ret = MP_INIT_E; + else + clearb = 1; + } + + /* tmpa = tmp^dP mod p */ + if (ret == 0 && mp_exptmod(tmp, &key->dP, &key->p, + tmpa) != MP_OKAY) + ret = MP_EXPTMOD_E; + + /* tmpb = tmp^dQ mod q */ + if (ret == 0 && mp_exptmod(tmp, &key->dQ, &key->q, + tmpb) != MP_OKAY) + ret = MP_EXPTMOD_E; + + /* tmp = (tmpa - tmpb) * qInv (mod p) */ + if (ret == 0 && mp_sub(tmpa, tmpb, tmp) != MP_OKAY) + ret = MP_SUB_E; + + if (ret == 0 && mp_mulmod(tmp, &key->u, &key->p, + tmp) != MP_OKAY) + ret = MP_MULMOD_E; + + /* tmp = tmpb + q * tmp */ + if (ret == 0 && mp_mul(tmp, &key->q, tmp) != MP_OKAY) + ret = MP_MUL_E; + + if (ret == 0 && mp_add(tmp, tmpb, tmp) != MP_OKAY) + ret = MP_ADD_E; + + #ifdef WOLFSSL_SMALL_STACK + if (tmpa != NULL) + #endif + { + if (cleara) + mp_clear(tmpa); + if (clearb) + mp_clear(tmpb); + #ifdef WOLFSSL_SMALL_STACK + XFREE(tmpa, key->heap, DYNAMIC_TYPE_RSA); + #endif + } + } /* tmpa/b scope */ + #endif /* RSA_LOW_MEM */ + + #ifdef WC_RSA_BLINDING + /* unblind */ + if (ret == 0 && mp_mulmod(tmp, rndi, &key->n, tmp) != MP_OKAY) + ret = MP_MULMOD_E; + #endif /* WC_RSA_BLINDING */ + + break; + } + #endif + case RSA_PUBLIC_ENCRYPT: + case RSA_PUBLIC_DECRYPT: + #ifdef WOLFSSL_XILINX_CRYPT + ret = wc_RsaFunctionXil(in, inLen, out, outLen, type, key, rng); + #else + if (mp_exptmod(tmp, &key->e, &key->n, tmp) != MP_OKAY) + ret = MP_EXPTMOD_E; + break; + #endif + default: + ret = RSA_WRONG_TYPE_E; + break; + } + } + + if (ret == 0) { + keyLen = wc_RsaEncryptSize(key); + if (keyLen > *outLen) + ret = RSA_BUFFER_E; + } + if (ret == 0) { + *outLen = keyLen; + if (mp_to_unsigned_bin_len(tmp, out, keyLen) != MP_OKAY) + ret = MP_TO_E; + } +#else + (void)type; + (void)key; + (void)keyLen; + XMEMCPY(out, in, inLen); + *outLen = inLen; +#endif + + mp_clear(tmp); +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmp, key->heap, DYNAMIC_TYPE_RSA); +#endif +#ifdef WC_RSA_BLINDING + if (type == RSA_PRIVATE_DECRYPT || type == RSA_PRIVATE_ENCRYPT) { + mp_clear(rndi); + mp_clear(rnd); + } +#ifdef WOLFSSL_SMALL_STACK + XFREE(rnd, key->heap, DYNAMIC_TYPE_RSA); +#endif +#endif /* WC_RSA_BLINDING */ + return ret; +#endif /* WOLFSSL_SP_MATH */ +} +#endif + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA) +static int wc_RsaFunctionAsync(const byte* in, word32 inLen, byte* out, + word32* outLen, int type, RsaKey* key, WC_RNG* rng) +{ + int ret = 0; + + (void)rng; + +#ifdef WOLFSSL_ASYNC_CRYPT_TEST + if (wc_AsyncTestInit(&key->asyncDev, ASYNC_TEST_RSA_FUNC)) { + WC_ASYNC_TEST* testDev = &key->asyncDev.test; + testDev->rsaFunc.in = in; + testDev->rsaFunc.inSz = inLen; + testDev->rsaFunc.out = out; + testDev->rsaFunc.outSz = outLen; + testDev->rsaFunc.type = type; + testDev->rsaFunc.key = key; + testDev->rsaFunc.rng = rng; + return WC_PENDING_E; + } +#endif /* WOLFSSL_ASYNC_CRYPT_TEST */ + + switch(type) { +#ifndef WOLFSSL_RSA_PUBLIC_ONLY + case RSA_PRIVATE_DECRYPT: + case RSA_PRIVATE_ENCRYPT: + #ifdef HAVE_CAVIUM + key->dataLen = key->n.raw.len; + ret = NitroxRsaExptMod(in, inLen, + key->d.raw.buf, key->d.raw.len, + key->n.raw.buf, key->n.raw.len, + out, outLen, key); + #elif defined(HAVE_INTEL_QA) + #ifdef RSA_LOW_MEM + ret = IntelQaRsaPrivate(&key->asyncDev, in, inLen, + &key->d.raw, &key->n.raw, + out, outLen); + #else + ret = IntelQaRsaCrtPrivate(&key->asyncDev, in, inLen, + &key->p.raw, &key->q.raw, + &key->dP.raw, &key->dQ.raw, + &key->u.raw, + out, outLen); + #endif + #else /* WOLFSSL_ASYNC_CRYPT_TEST */ + ret = wc_RsaFunctionSync(in, inLen, out, outLen, type, key, rng); + #endif + break; +#endif + + case RSA_PUBLIC_ENCRYPT: + case RSA_PUBLIC_DECRYPT: + #ifdef HAVE_CAVIUM + key->dataLen = key->n.raw.len; + ret = NitroxRsaExptMod(in, inLen, + key->e.raw.buf, key->e.raw.len, + key->n.raw.buf, key->n.raw.len, + out, outLen, key); + #elif defined(HAVE_INTEL_QA) + ret = IntelQaRsaPublic(&key->asyncDev, in, inLen, + &key->e.raw, &key->n.raw, + out, outLen); + #else /* WOLFSSL_ASYNC_CRYPT_TEST */ + ret = wc_RsaFunctionSync(in, inLen, out, outLen, type, key, rng); + #endif + break; + + default: + ret = RSA_WRONG_TYPE_E; + } + + return ret; +} +#endif /* WOLFSSL_ASYNC_CRYPT && WC_ASYNC_ENABLE_RSA */ + +#if defined(WC_RSA_DIRECT) || defined(WC_RSA_NO_PADDING) +/* Function that does the RSA operation directly with no padding. + * + * in buffer to do operation on + * inLen length of input buffer + * out buffer to hold results + * outSz gets set to size of result buffer. Should be passed in as length + * of out buffer. If the pointer "out" is null then outSz gets set to + * the expected buffer size needed and LENGTH_ONLY_E gets returned. + * key RSA key to use for encrypt/decrypt + * type if using private or public key {RSA_PUBLIC_ENCRYPT, + * RSA_PUBLIC_DECRYPT, RSA_PRIVATE_ENCRYPT, RSA_PRIVATE_DECRYPT} + * rng wolfSSL RNG to use if needed + * + * returns size of result on success + */ +int wc_RsaDirect(byte* in, word32 inLen, byte* out, word32* outSz, + RsaKey* key, int type, WC_RNG* rng) +{ + int ret; + + if (in == NULL || outSz == NULL || key == NULL) { + return BAD_FUNC_ARG; + } + + /* sanity check on type of RSA operation */ + switch (type) { + case RSA_PUBLIC_ENCRYPT: + case RSA_PUBLIC_DECRYPT: + case RSA_PRIVATE_ENCRYPT: + case RSA_PRIVATE_DECRYPT: + break; + default: + WOLFSSL_MSG("Bad RSA type"); + return BAD_FUNC_ARG; + } + + if ((ret = wc_RsaEncryptSize(key)) < 0) { + return BAD_FUNC_ARG; + } + + if (inLen != (word32)ret) { + WOLFSSL_MSG("Bad input length. Should be RSA key size"); + return BAD_FUNC_ARG; + } + + if (out == NULL) { + *outSz = inLen; + return LENGTH_ONLY_E; + } + + switch (key->state) { + case RSA_STATE_NONE: + case RSA_STATE_ENCRYPT_PAD: + case RSA_STATE_ENCRYPT_EXPTMOD: + case RSA_STATE_DECRYPT_EXPTMOD: + case RSA_STATE_DECRYPT_UNPAD: + key->state = (type == RSA_PRIVATE_ENCRYPT || + type == RSA_PUBLIC_ENCRYPT) ? RSA_STATE_ENCRYPT_EXPTMOD: + RSA_STATE_DECRYPT_EXPTMOD; + + key->dataLen = *outSz; + + ret = wc_RsaFunction(in, inLen, out, &key->dataLen, type, key, rng); + if (ret >= 0 || ret == WC_PENDING_E) { + key->state = (type == RSA_PRIVATE_ENCRYPT || + type == RSA_PUBLIC_ENCRYPT) ? RSA_STATE_ENCRYPT_RES: + RSA_STATE_DECRYPT_RES; + } + if (ret < 0) { + break; + } + + FALL_THROUGH; + + case RSA_STATE_ENCRYPT_RES: + case RSA_STATE_DECRYPT_RES: + ret = key->dataLen; + break; + + default: + ret = BAD_STATE_E; + } + + /* if async pending then skip cleanup*/ + if (ret == WC_PENDING_E + #ifdef WC_RSA_NONBLOCK + || ret == FP_WOULDBLOCK + #endif + ) { + return ret; + } + + key->state = RSA_STATE_NONE; + wc_RsaCleanup(key); + + return ret; +} +#endif /* WC_RSA_DIRECT || WC_RSA_NO_PADDING */ + +#if defined(WOLFSSL_CRYPTOCELL) +static int cc310_RsaPublicEncrypt(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key) +{ + CRYSError_t ret = 0; + CRYS_RSAPrimeData_t primeData; + int modulusSize = wc_RsaEncryptSize(key); + + /* The out buffer must be at least modulus size bytes long. */ + if (outLen < modulusSize) + return BAD_FUNC_ARG; + + ret = CRYS_RSA_PKCS1v15_Encrypt(&wc_rndState, + wc_rndGenVectFunc, + &key->ctx.pubKey, + &primeData, + (byte*)in, + inLen, + out); + + if (ret != SA_SILIB_RET_OK){ + WOLFSSL_MSG("CRYS_RSA_PKCS1v15_Encrypt failed"); + return -1; + } + + return modulusSize; +} +static int cc310_RsaPublicDecrypt(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key) +{ + CRYSError_t ret = 0; + CRYS_RSAPrimeData_t primeData; + uint16_t actualOutLen = outLen; + + ret = CRYS_RSA_PKCS1v15_Decrypt(&key->ctx.privKey, + &primeData, + (byte*)in, + inLen, + out, + &actualOutLen); + + if (ret != SA_SILIB_RET_OK){ + WOLFSSL_MSG("CRYS_RSA_PKCS1v15_Decrypt failed"); + return -1; + } + return actualOutLen; +} + +static int cc310_RsaSSL_Sign(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key, enum wc_HashType hash) +{ + CRYSError_t ret = 0; + uint16_t actualOutLen = outLen*sizeof(byte); + CRYS_RSAPrivUserContext_t contextPrivate; + CRYS_RSA_HASH_OpMode_t mode = cc310_hashModeRSA(hash); + + if (mode == CRYS_RSA_After_HASH_NOT_KNOWN_mode) { + mode = CRYS_RSA_HASH_SHA256_mode; + } + + ret = CRYS_RSA_PKCS1v15_Sign(&wc_rndState, + wc_rndGenVectFunc, + &contextPrivate, + &key->ctx.privKey, + mode, + (byte*)in, + inLen, + out, + &actualOutLen); + + if (ret != SA_SILIB_RET_OK){ + WOLFSSL_MSG("CRYS_RSA_PKCS1v15_Sign failed"); + return -1; + } + return actualOutLen; +} + +static int cc310_RsaSSL_Verify(const byte* in, word32 inLen, byte* sig, + RsaKey* key, enum wc_HashType hash) +{ + CRYSError_t ret = 0; + CRYS_RSAPubUserContext_t contextPub; + CRYS_RSA_HASH_OpMode_t mode = cc310_hashModeRSA(hash); + + if (mode == CRYS_RSA_After_HASH_NOT_KNOWN_mode) { + mode = CRYS_RSA_HASH_SHA256_mode; + } + /* verify the signature in the sig pointer */ + ret = CRYS_RSA_PKCS1v15_Verify(&contextPub, + &key->ctx.pubKey, + mode, + (byte*)in, + inLen, + sig); + + if (ret != SA_SILIB_RET_OK){ + WOLFSSL_MSG("CRYS_RSA_PKCS1v15_Verify failed"); + return -1; + } + + return ret; +} +#endif /* WOLFSSL_CRYPTOCELL */ + +int wc_RsaFunction(const byte* in, word32 inLen, byte* out, + word32* outLen, int type, RsaKey* key, WC_RNG* rng) +{ + int ret = 0; + + if (key == NULL || in == NULL || inLen == 0 || out == NULL || + outLen == NULL || *outLen == 0 || type == RSA_TYPE_UNKNOWN) { + return BAD_FUNC_ARG; + } + +#ifdef WOLF_CRYPTO_CB + if (key->devId != INVALID_DEVID) { + ret = wc_CryptoCb_Rsa(in, inLen, out, outLen, type, key, rng); + if (ret != CRYPTOCB_UNAVAILABLE) + return ret; + /* fall-through when unavailable */ + ret = 0; /* reset error code and try using software */ + } +#endif + +#ifndef TEST_UNPAD_CONSTANT_TIME +#ifndef NO_RSA_BOUNDS_CHECK + if (type == RSA_PRIVATE_DECRYPT && + key->state == RSA_STATE_DECRYPT_EXPTMOD) { + + /* Check that 1 < in < n-1. (Requirement of 800-56B.) */ +#ifdef WOLFSSL_SMALL_STACK + mp_int* c = NULL; +#else + mp_int c[1]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + c = (mp_int*)XMALLOC(sizeof(mp_int), key->heap, DYNAMIC_TYPE_RSA); + if (c == NULL) + ret = MEMORY_E; +#endif + + if (mp_init(c) != MP_OKAY) + ret = MEMORY_E; + if (ret == 0) { + if (mp_read_unsigned_bin(c, in, inLen) != 0) + ret = MP_READ_E; + } + if (ret == 0) { + /* check c > 1 */ + if (mp_cmp_d(c, 1) != MP_GT) + ret = RSA_OUT_OF_RANGE_E; + } + if (ret == 0) { + /* add c+1 */ + if (mp_add_d(c, 1, c) != MP_OKAY) + ret = MP_ADD_E; + } + if (ret == 0) { + /* check c+1 < n */ + if (mp_cmp(c, &key->n) != MP_LT) + ret = RSA_OUT_OF_RANGE_E; + } + mp_clear(c); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(c, key->heap, DYNAMIC_TYPE_RSA); +#endif + + if (ret != 0) + return ret; + } +#endif /* NO_RSA_BOUNDS_CHECK */ +#endif + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA) + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA && + key->n.raw.len > 0) { + ret = wc_RsaFunctionAsync(in, inLen, out, outLen, type, key, rng); + } + else +#endif +#ifdef WC_RSA_NONBLOCK + if (key->nb) { + ret = wc_RsaFunctionNonBlock(in, inLen, out, outLen, type, key); + } + else +#endif + { + ret = wc_RsaFunctionSync(in, inLen, out, outLen, type, key, rng); + } + + /* handle error */ + if (ret < 0 && ret != WC_PENDING_E + #ifdef WC_RSA_NONBLOCK + && ret != FP_WOULDBLOCK + #endif + ) { + if (ret == MP_EXPTMOD_E) { + /* This can happen due to incorrectly set FP_MAX_BITS or missing XREALLOC */ + WOLFSSL_MSG("RSA_FUNCTION MP_EXPTMOD_E: memory/config problem"); + } + + key->state = RSA_STATE_NONE; + wc_RsaCleanup(key); + } + + return ret; +} + + +#ifndef WOLFSSL_RSA_VERIFY_ONLY +/* Internal Wrappers */ +/* Gives the option of choosing padding type + in : input to be encrypted + inLen: length of input buffer + out: encrypted output + outLen: length of encrypted output buffer + key : wolfSSL initialized RSA key struct + rng : wolfSSL initialized random number struct + rsa_type : type of RSA: RSA_PUBLIC_ENCRYPT, RSA_PUBLIC_DECRYPT, + RSA_PRIVATE_ENCRYPT or RSA_PRIVATE_DECRYPT + pad_value: RSA_BLOCK_TYPE_1 or RSA_BLOCK_TYPE_2 + pad_type : type of padding: WC_RSA_PKCSV15_PAD, WC_RSA_OAEP_PAD, + WC_RSA_NO_PAD or WC_RSA_PSS_PAD + hash : type of hash algorithm to use found in wolfssl/wolfcrypt/hash.h + mgf : type of mask generation function to use + label : optional label + labelSz : size of optional label buffer + saltLen : Length of salt used in PSS + rng : random number generator */ +static int RsaPublicEncryptEx(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key, int rsa_type, + byte pad_value, int pad_type, + enum wc_HashType hash, int mgf, + byte* label, word32 labelSz, int saltLen, + WC_RNG* rng) +{ + int ret, sz; + + if (in == NULL || inLen == 0 || out == NULL || key == NULL) { + return BAD_FUNC_ARG; + } + + sz = wc_RsaEncryptSize(key); + if (sz > (int)outLen) { + return RSA_BUFFER_E; + } + + if (sz < RSA_MIN_PAD_SZ) { + return WC_KEY_SIZE_E; + } + + if (inLen > (word32)(sz - RSA_MIN_PAD_SZ)) { +#ifdef WC_RSA_NO_PADDING + /* In the case that no padding is used the input length can and should + * be the same size as the RSA key. */ + if (pad_type != WC_RSA_NO_PAD) +#endif + return RSA_BUFFER_E; + } + + switch (key->state) { + case RSA_STATE_NONE: + case RSA_STATE_ENCRYPT_PAD: + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA) && \ + defined(HAVE_CAVIUM) + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA && + pad_type != WC_RSA_PSS_PAD && key->n.raw.buf) { + /* Async operations that include padding */ + if (rsa_type == RSA_PUBLIC_ENCRYPT && + pad_value == RSA_BLOCK_TYPE_2) { + key->state = RSA_STATE_ENCRYPT_RES; + key->dataLen = key->n.raw.len; + return NitroxRsaPublicEncrypt(in, inLen, out, outLen, key); + } + else if (rsa_type == RSA_PRIVATE_ENCRYPT && + pad_value == RSA_BLOCK_TYPE_1) { + key->state = RSA_STATE_ENCRYPT_RES; + key->dataLen = key->n.raw.len; + return NitroxRsaSSL_Sign(in, inLen, out, outLen, key); + } + } + #elif defined(WOLFSSL_CRYPTOCELL) + if (rsa_type == RSA_PUBLIC_ENCRYPT && + pad_value == RSA_BLOCK_TYPE_2) { + + return cc310_RsaPublicEncrypt(in, inLen, out, outLen, key); + } + else if (rsa_type == RSA_PRIVATE_ENCRYPT && + pad_value == RSA_BLOCK_TYPE_1) { + return cc310_RsaSSL_Sign(in, inLen, out, outLen, key, hash); + } + #endif /* WOLFSSL_CRYPTOCELL */ + + key->state = RSA_STATE_ENCRYPT_PAD; + ret = wc_RsaPad_ex(in, inLen, out, sz, pad_value, rng, pad_type, hash, + mgf, label, labelSz, saltLen, mp_count_bits(&key->n), + key->heap); + if (ret < 0) { + break; + } + + key->state = RSA_STATE_ENCRYPT_EXPTMOD; + FALL_THROUGH; + + case RSA_STATE_ENCRYPT_EXPTMOD: + + key->dataLen = outLen; + ret = wc_RsaFunction(out, sz, out, &key->dataLen, rsa_type, key, rng); + + if (ret >= 0 || ret == WC_PENDING_E) { + key->state = RSA_STATE_ENCRYPT_RES; + } + if (ret < 0) { + break; + } + + FALL_THROUGH; + + case RSA_STATE_ENCRYPT_RES: + ret = key->dataLen; + break; + + default: + ret = BAD_STATE_E; + break; + } + + /* if async pending then return and skip done cleanup below */ + if (ret == WC_PENDING_E + #ifdef WC_RSA_NONBLOCK + || ret == FP_WOULDBLOCK + #endif + ) { + return ret; + } + + key->state = RSA_STATE_NONE; + wc_RsaCleanup(key); + + return ret; +} + +#endif + +/* Gives the option of choosing padding type + in : input to be decrypted + inLen: length of input buffer + out: decrypted message + outLen: length of decrypted message in bytes + outPtr: optional inline output pointer (if provided doing inline) + key : wolfSSL initialized RSA key struct + rsa_type : type of RSA: RSA_PUBLIC_ENCRYPT, RSA_PUBLIC_DECRYPT, + RSA_PRIVATE_ENCRYPT or RSA_PRIVATE_DECRYPT + pad_value: RSA_BLOCK_TYPE_1 or RSA_BLOCK_TYPE_2 + pad_type : type of padding: WC_RSA_PKCSV15_PAD, WC_RSA_OAEP_PAD, + WC_RSA_NO_PAD, WC_RSA_PSS_PAD + hash : type of hash algorithm to use found in wolfssl/wolfcrypt/hash.h + mgf : type of mask generation function to use + label : optional label + labelSz : size of optional label buffer + saltLen : Length of salt used in PSS + rng : random number generator */ +static int RsaPrivateDecryptEx(byte* in, word32 inLen, byte* out, + word32 outLen, byte** outPtr, RsaKey* key, + int rsa_type, byte pad_value, int pad_type, + enum wc_HashType hash, int mgf, + byte* label, word32 labelSz, int saltLen, + WC_RNG* rng) +{ + int ret = RSA_WRONG_TYPE_E; + + if (in == NULL || inLen == 0 || out == NULL || key == NULL) { + return BAD_FUNC_ARG; + } + + switch (key->state) { + case RSA_STATE_NONE: + key->dataLen = inLen; + + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA) && \ + defined(HAVE_CAVIUM) + /* Async operations that include padding */ + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA && + pad_type != WC_RSA_PSS_PAD) { +#ifndef WOLFSSL_RSA_PUBLIC_ONLY + if (rsa_type == RSA_PRIVATE_DECRYPT && + pad_value == RSA_BLOCK_TYPE_2) { + key->state = RSA_STATE_DECRYPT_RES; + key->data = NULL; + return NitroxRsaPrivateDecrypt(in, inLen, out, &key->dataLen, + key); +#endif + } + else if (rsa_type == RSA_PUBLIC_DECRYPT && + pad_value == RSA_BLOCK_TYPE_1) { + key->state = RSA_STATE_DECRYPT_RES; + key->data = NULL; + return NitroxRsaSSL_Verify(in, inLen, out, &key->dataLen, key); + } + } + #elif defined(WOLFSSL_CRYPTOCELL) + if (rsa_type == RSA_PRIVATE_DECRYPT && + pad_value == RSA_BLOCK_TYPE_2) { + ret = cc310_RsaPublicDecrypt(in, inLen, out, outLen, key); + if (outPtr != NULL) + *outPtr = out; /* for inline */ + return ret; + } + else if (rsa_type == RSA_PUBLIC_DECRYPT && + pad_value == RSA_BLOCK_TYPE_1) { + return cc310_RsaSSL_Verify(in, inLen, out, key, hash); + } + #endif /* WOLFSSL_CRYPTOCELL */ + + +#if !defined(WOLFSSL_RSA_VERIFY_ONLY) && !defined(WOLFSSL_RSA_VERIFY_INLINE) + /* verify the tmp ptr is NULL, otherwise indicates bad state */ + if (key->data != NULL) { + ret = BAD_STATE_E; + break; + } + + /* if not doing this inline then allocate a buffer for it */ + if (outPtr == NULL) { + key->data = (byte*)XMALLOC(inLen, key->heap, + DYNAMIC_TYPE_WOLF_BIGINT); + key->dataIsAlloc = 1; + if (key->data == NULL) { + ret = MEMORY_E; + break; + } + XMEMCPY(key->data, in, inLen); + } + else { + key->data = out; + } +#endif + + key->state = RSA_STATE_DECRYPT_EXPTMOD; + FALL_THROUGH; + + case RSA_STATE_DECRYPT_EXPTMOD: +#if !defined(WOLFSSL_RSA_VERIFY_ONLY) && !defined(WOLFSSL_RSA_VERIFY_INLINE) + ret = wc_RsaFunction(key->data, inLen, key->data, &key->dataLen, + rsa_type, key, rng); +#else + ret = wc_RsaFunction(out, inLen, out, &key->dataLen, rsa_type, key, + rng); +#endif + + if (ret >= 0 || ret == WC_PENDING_E) { + key->state = RSA_STATE_DECRYPT_UNPAD; + } + if (ret < 0) { + break; + } + + FALL_THROUGH; + + case RSA_STATE_DECRYPT_UNPAD: + { + byte* pad = NULL; +#if !defined(WOLFSSL_RSA_VERIFY_ONLY) && !defined(WOLFSSL_RSA_VERIFY_INLINE) + ret = wc_RsaUnPad_ex(key->data, key->dataLen, &pad, pad_value, pad_type, + hash, mgf, label, labelSz, saltLen, + mp_count_bits(&key->n), key->heap); +#else + ret = wc_RsaUnPad_ex(out, key->dataLen, &pad, pad_value, pad_type, hash, + mgf, label, labelSz, saltLen, + mp_count_bits(&key->n), key->heap); +#endif + if (rsa_type == RSA_PUBLIC_DECRYPT && ret > (int)outLen) + ret = RSA_BUFFER_E; + else if (ret >= 0 && pad != NULL) { +#if !defined(WOLFSSL_RSA_VERIFY_ONLY) + signed char c; +#endif + + /* only copy output if not inline */ + if (outPtr == NULL) { +#if !defined(WOLFSSL_RSA_VERIFY_ONLY) + word32 i, j; + int start = (int)((size_t)pad - (size_t)key->data); + + for (i = 0, j = 0; j < key->dataLen; j++) { + out[i] = key->data[j]; + c = ctMaskGTE(j, start); + c &= ctMaskLT(i, outLen); + /* 0 - no add, -1 add */ + i += (word32)((byte)(-c)); + } +#else + XMEMCPY(out, pad, ret); +#endif + } + else + *outPtr = pad; + +#if !defined(WOLFSSL_RSA_VERIFY_ONLY) + ret = ctMaskSelInt(ctMaskLTE(ret, outLen), ret, RSA_BUFFER_E); + ret = ctMaskSelInt(ctMaskNotEq(ret, 0), ret, RSA_BUFFER_E); +#else + if (outLen < (word32)ret) + ret = RSA_BUFFER_E; +#endif + } + + key->state = RSA_STATE_DECRYPT_RES; + + FALL_THROUGH; + } + case RSA_STATE_DECRYPT_RES: + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA) && \ + defined(HAVE_CAVIUM) + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA && + pad_type != WC_RSA_PSS_PAD) { + if (ret > 0) { + /* convert result */ + byte* dataLen = (byte*)&key->dataLen; + ret = (dataLen[0] << 8) | (dataLen[1]); + + if (outPtr) + *outPtr = in; + } + } + #endif + break; + + default: + ret = BAD_STATE_E; + break; + } + + /* if async pending then return and skip done cleanup below */ + if (ret == WC_PENDING_E + #ifdef WC_RSA_NONBLOCK + || ret == FP_WOULDBLOCK + #endif + ) { + return ret; + } + + key->state = RSA_STATE_NONE; + wc_RsaCleanup(key); + + return ret; +} + + +#ifndef WOLFSSL_RSA_VERIFY_ONLY +/* Public RSA Functions */ +int wc_RsaPublicEncrypt(const byte* in, word32 inLen, byte* out, word32 outLen, + RsaKey* key, WC_RNG* rng) +{ + return RsaPublicEncryptEx(in, inLen, out, outLen, key, + RSA_PUBLIC_ENCRYPT, RSA_BLOCK_TYPE_2, WC_RSA_PKCSV15_PAD, + WC_HASH_TYPE_NONE, WC_MGF1NONE, NULL, 0, 0, rng); +} + + +#if !defined(WC_NO_RSA_OAEP) || defined(WC_RSA_NO_PADDING) +int wc_RsaPublicEncrypt_ex(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key, WC_RNG* rng, int type, + enum wc_HashType hash, int mgf, byte* label, + word32 labelSz) +{ + return RsaPublicEncryptEx(in, inLen, out, outLen, key, RSA_PUBLIC_ENCRYPT, + RSA_BLOCK_TYPE_2, type, hash, mgf, label, labelSz, 0, rng); +} +#endif /* WC_NO_RSA_OAEP */ +#endif + + +#ifndef WOLFSSL_RSA_PUBLIC_ONLY +int wc_RsaPrivateDecryptInline(byte* in, word32 inLen, byte** out, RsaKey* key) +{ + WC_RNG* rng = NULL; +#ifdef WC_RSA_BLINDING + rng = key->rng; +#endif + return RsaPrivateDecryptEx(in, inLen, in, inLen, out, key, + RSA_PRIVATE_DECRYPT, RSA_BLOCK_TYPE_2, WC_RSA_PKCSV15_PAD, + WC_HASH_TYPE_NONE, WC_MGF1NONE, NULL, 0, 0, rng); +} + + +#ifndef WC_NO_RSA_OAEP +int wc_RsaPrivateDecryptInline_ex(byte* in, word32 inLen, byte** out, + RsaKey* key, int type, enum wc_HashType hash, + int mgf, byte* label, word32 labelSz) +{ + WC_RNG* rng = NULL; +#ifdef WC_RSA_BLINDING + rng = key->rng; +#endif + return RsaPrivateDecryptEx(in, inLen, in, inLen, out, key, + RSA_PRIVATE_DECRYPT, RSA_BLOCK_TYPE_2, type, hash, + mgf, label, labelSz, 0, rng); +} +#endif /* WC_NO_RSA_OAEP */ + + +int wc_RsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key) +{ + WC_RNG* rng = NULL; +#ifdef WC_RSA_BLINDING + rng = key->rng; +#endif + return RsaPrivateDecryptEx((byte*)in, inLen, out, outLen, NULL, key, + RSA_PRIVATE_DECRYPT, RSA_BLOCK_TYPE_2, WC_RSA_PKCSV15_PAD, + WC_HASH_TYPE_NONE, WC_MGF1NONE, NULL, 0, 0, rng); +} + +#if !defined(WC_NO_RSA_OAEP) || defined(WC_RSA_NO_PADDING) +int wc_RsaPrivateDecrypt_ex(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key, int type, + enum wc_HashType hash, int mgf, byte* label, + word32 labelSz) +{ + WC_RNG* rng = NULL; +#ifdef WC_RSA_BLINDING + rng = key->rng; +#endif + return RsaPrivateDecryptEx((byte*)in, inLen, out, outLen, NULL, key, + RSA_PRIVATE_DECRYPT, RSA_BLOCK_TYPE_2, type, hash, mgf, label, + labelSz, 0, rng); +} +#endif /* WC_NO_RSA_OAEP || WC_RSA_NO_PADDING */ +#endif /* WOLFSSL_RSA_PUBLIC_ONLY */ + + +int wc_RsaSSL_VerifyInline(byte* in, word32 inLen, byte** out, RsaKey* key) +{ + WC_RNG* rng = NULL; +#ifdef WC_RSA_BLINDING + rng = key->rng; +#endif + return RsaPrivateDecryptEx(in, inLen, in, inLen, out, key, + RSA_PUBLIC_DECRYPT, RSA_BLOCK_TYPE_1, WC_RSA_PKCSV15_PAD, + WC_HASH_TYPE_NONE, WC_MGF1NONE, NULL, 0, 0, rng); +} + +#ifndef WOLFSSL_RSA_VERIFY_ONLY +int wc_RsaSSL_Verify(const byte* in, word32 inLen, byte* out, word32 outLen, + RsaKey* key) +{ + WC_RNG* rng; + + if (key == NULL) { + return BAD_FUNC_ARG; + } + + rng = NULL; +#ifdef WC_RSA_BLINDING + rng = key->rng; +#endif + + return RsaPrivateDecryptEx((byte*)in, inLen, out, outLen, NULL, key, + RSA_PUBLIC_DECRYPT, RSA_BLOCK_TYPE_1, WC_RSA_PKCSV15_PAD, + WC_HASH_TYPE_NONE, WC_MGF1NONE, NULL, 0, 0, rng); +} +#endif + +#ifdef WC_RSA_PSS +/* Verify the message signed with RSA-PSS. + * The input buffer is reused for the ouput buffer. + * Salt length is equal to hash length. + * + * in Buffer holding encrypted data. + * inLen Length of data in buffer. + * out Pointer to address containing the PSS data. + * hash Hash algorithm. + * mgf Mask generation function. + * key Public RSA key. + * returns the length of the PSS data on success and negative indicates failure. + */ +int wc_RsaPSS_VerifyInline(byte* in, word32 inLen, byte** out, + enum wc_HashType hash, int mgf, RsaKey* key) +{ + return wc_RsaPSS_VerifyInline_ex(in, inLen, out, hash, mgf, -1, key); +} + +/* Verify the message signed with RSA-PSS. + * The input buffer is reused for the ouput buffer. + * + * in Buffer holding encrypted data. + * inLen Length of data in buffer. + * out Pointer to address containing the PSS data. + * hash Hash algorithm. + * mgf Mask generation function. + * key Public RSA key. + * saltLen Length of salt used. -1 indicates salt length is the same as the + * hash length. + * returns the length of the PSS data on success and negative indicates failure. + */ +int wc_RsaPSS_VerifyInline_ex(byte* in, word32 inLen, byte** out, + enum wc_HashType hash, int mgf, int saltLen, + RsaKey* key) +{ + WC_RNG* rng = NULL; +#ifdef WC_RSA_BLINDING + rng = key->rng; +#endif + return RsaPrivateDecryptEx(in, inLen, in, inLen, out, key, + RSA_PUBLIC_DECRYPT, RSA_BLOCK_TYPE_1, WC_RSA_PSS_PAD, + hash, mgf, NULL, 0, saltLen, rng); +} + +/* Verify the message signed with RSA-PSS. + * Salt length is equal to hash length. + * + * in Buffer holding encrypted data. + * inLen Length of data in buffer. + * out Pointer to address containing the PSS data. + * hash Hash algorithm. + * mgf Mask generation function. + * key Public RSA key. + * returns the length of the PSS data on success and negative indicates failure. + */ +int wc_RsaPSS_Verify(byte* in, word32 inLen, byte* out, word32 outLen, + enum wc_HashType hash, int mgf, RsaKey* key) +{ + return wc_RsaPSS_Verify_ex(in, inLen, out, outLen, hash, mgf, -1, key); +} + +/* Verify the message signed with RSA-PSS. + * + * in Buffer holding encrypted data. + * inLen Length of data in buffer. + * out Pointer to address containing the PSS data. + * hash Hash algorithm. + * mgf Mask generation function. + * key Public RSA key. + * saltLen Length of salt used. -1 indicates salt length is the same as the + * hash length. + * returns the length of the PSS data on success and negative indicates failure. + */ +int wc_RsaPSS_Verify_ex(byte* in, word32 inLen, byte* out, word32 outLen, + enum wc_HashType hash, int mgf, int saltLen, + RsaKey* key) +{ + WC_RNG* rng = NULL; +#ifdef WC_RSA_BLINDING + rng = key->rng; +#endif + return RsaPrivateDecryptEx(in, inLen, out, outLen, NULL, key, + RSA_PUBLIC_DECRYPT, RSA_BLOCK_TYPE_1, WC_RSA_PSS_PAD, + hash, mgf, NULL, 0, saltLen, rng); +} + + +/* Checks the PSS data to ensure that the signature matches. + * Salt length is equal to hash length. + * + * in Hash of the data that is being verified. + * inSz Length of hash. + * sig Buffer holding PSS data. + * sigSz Size of PSS data. + * hashType Hash algorithm. + * returns BAD_PADDING_E when the PSS data is invalid, BAD_FUNC_ARG when + * NULL is passed in to in or sig or inSz is not the same as the hash + * algorithm length and 0 on success. + */ +int wc_RsaPSS_CheckPadding(const byte* in, word32 inSz, byte* sig, + word32 sigSz, enum wc_HashType hashType) +{ + return wc_RsaPSS_CheckPadding_ex(in, inSz, sig, sigSz, hashType, inSz, 0); +} + +/* Checks the PSS data to ensure that the signature matches. + * + * in Hash of the data that is being verified. + * inSz Length of hash. + * sig Buffer holding PSS data. + * sigSz Size of PSS data. + * hashType Hash algorithm. + * saltLen Length of salt used. -1 indicates salt length is the same as the + * hash length. + * returns BAD_PADDING_E when the PSS data is invalid, BAD_FUNC_ARG when + * NULL is passed in to in or sig or inSz is not the same as the hash + * algorithm length and 0 on success. + */ +int wc_RsaPSS_CheckPadding_ex(const byte* in, word32 inSz, byte* sig, + word32 sigSz, enum wc_HashType hashType, + int saltLen, int bits) +{ + int ret = 0; + byte sigCheck[WC_MAX_DIGEST_SIZE*2 + RSA_PSS_PAD_SZ]; + + (void)bits; + + if (in == NULL || sig == NULL || + inSz != (word32)wc_HashGetDigestSize(hashType)) + ret = BAD_FUNC_ARG; + + if (ret == 0) { + if (saltLen == -1) { + saltLen = inSz; + #ifdef WOLFSSL_SHA512 + /* See FIPS 186-4 section 5.5 item (e). */ + if (bits == 1024 && inSz == WC_SHA512_DIGEST_SIZE) + saltLen = RSA_PSS_SALT_MAX_SZ; + #endif + } + else if (saltLen < -1 || (word32)saltLen > inSz) + ret = PSS_SALTLEN_E; + } + + /* Sig = Salt | Exp Hash */ + if (ret == 0) { + if (sigSz != inSz + saltLen) + ret = BAD_PADDING_E; + } + + /* Exp Hash = HASH(8 * 0x00 | Message Hash | Salt) */ + if (ret == 0) { + XMEMSET(sigCheck, 0, RSA_PSS_PAD_SZ); + XMEMCPY(sigCheck + RSA_PSS_PAD_SZ, in, inSz); + XMEMCPY(sigCheck + RSA_PSS_PAD_SZ + inSz, sig, saltLen); + ret = wc_Hash(hashType, sigCheck, RSA_PSS_PAD_SZ + inSz + saltLen, + sigCheck, inSz); + } + if (ret == 0) { + if (XMEMCMP(sigCheck, sig + saltLen, inSz) != 0) { + WOLFSSL_MSG("RsaPSS_CheckPadding: Padding Error"); + ret = BAD_PADDING_E; + } + } + + return ret; +} + + +/* Verify the message signed with RSA-PSS. + * The input buffer is reused for the ouput buffer. + * Salt length is equal to hash length. + * + * in Buffer holding encrypted data. + * inLen Length of data in buffer. + * out Pointer to address containing the PSS data. + * digest Hash of the data that is being verified. + * digestLen Length of hash. + * hash Hash algorithm. + * mgf Mask generation function. + * key Public RSA key. + * returns the length of the PSS data on success and negative indicates failure. + */ +int wc_RsaPSS_VerifyCheckInline(byte* in, word32 inLen, byte** out, + const byte* digest, word32 digestLen, + enum wc_HashType hash, int mgf, RsaKey* key) +{ + int ret = 0, verify, saltLen, hLen, bits = 0; + + hLen = wc_HashGetDigestSize(hash); + if (hLen < 0) + return hLen; + if ((word32)hLen != digestLen) + return BAD_FUNC_ARG; + + saltLen = hLen; + #ifdef WOLFSSL_SHA512 + /* See FIPS 186-4 section 5.5 item (e). */ + bits = mp_count_bits(&key->n); + if (bits == 1024 && hLen == WC_SHA512_DIGEST_SIZE) + saltLen = RSA_PSS_SALT_MAX_SZ; + #endif + + verify = wc_RsaPSS_VerifyInline_ex(in, inLen, out, hash, mgf, saltLen, key); + if (verify > 0) + ret = wc_RsaPSS_CheckPadding_ex(digest, digestLen, *out, verify, + hash, saltLen, bits); + if (ret == 0) + ret = verify; + + return ret; +} + + +/* Verify the message signed with RSA-PSS. + * Salt length is equal to hash length. + * + * in Buffer holding encrypted data. + * inLen Length of data in buffer. + * out Pointer to address containing the PSS data. + * outLen Length of the output. + * digest Hash of the data that is being verified. + * digestLen Length of hash. + * hash Hash algorithm. + * mgf Mask generation function. + * key Public RSA key. + * returns the length of the PSS data on success and negative indicates failure. + */ +int wc_RsaPSS_VerifyCheck(byte* in, word32 inLen, byte* out, word32 outLen, + const byte* digest, word32 digestLen, + enum wc_HashType hash, int mgf, + RsaKey* key) +{ + int ret = 0, verify, saltLen, hLen, bits = 0; + + hLen = wc_HashGetDigestSize(hash); + if (hLen < 0) + return hLen; + if ((word32)hLen != digestLen) + return BAD_FUNC_ARG; + + saltLen = hLen; + #ifdef WOLFSSL_SHA512 + /* See FIPS 186-4 section 5.5 item (e). */ + bits = mp_count_bits(&key->n); + if (bits == 1024 && hLen == WC_SHA512_DIGEST_SIZE) + saltLen = RSA_PSS_SALT_MAX_SZ; + #endif + + verify = wc_RsaPSS_Verify_ex(in, inLen, out, outLen, hash, + mgf, saltLen, key); + if (verify > 0) + ret = wc_RsaPSS_CheckPadding_ex(digest, digestLen, out, verify, + hash, saltLen, bits); + if (ret == 0) + ret = verify; + + return ret; +} + +#endif + +#ifndef WOLFSSL_RSA_PUBLIC_ONLY +int wc_RsaSSL_Sign(const byte* in, word32 inLen, byte* out, word32 outLen, + RsaKey* key, WC_RNG* rng) +{ + return RsaPublicEncryptEx(in, inLen, out, outLen, key, + RSA_PRIVATE_ENCRYPT, RSA_BLOCK_TYPE_1, WC_RSA_PKCSV15_PAD, + WC_HASH_TYPE_NONE, WC_MGF1NONE, NULL, 0, 0, rng); +} + +#ifdef WC_RSA_PSS +/* Sign the hash of a message using RSA-PSS. + * Salt length is equal to hash length. + * + * in Buffer holding hash of message. + * inLen Length of data in buffer (hash length). + * out Buffer to write encrypted signature into. + * outLen Size of buffer to write to. + * hash Hash algorithm. + * mgf Mask generation function. + * key Public RSA key. + * rng Random number generator. + * returns the length of the encrypted signature on success, a negative value + * indicates failure. + */ +int wc_RsaPSS_Sign(const byte* in, word32 inLen, byte* out, word32 outLen, + enum wc_HashType hash, int mgf, RsaKey* key, WC_RNG* rng) +{ + return wc_RsaPSS_Sign_ex(in, inLen, out, outLen, hash, mgf, -1, key, rng); +} + +/* Sign the hash of a message using RSA-PSS. + * + * in Buffer holding hash of message. + * inLen Length of data in buffer (hash length). + * out Buffer to write encrypted signature into. + * outLen Size of buffer to write to. + * hash Hash algorithm. + * mgf Mask generation function. + * saltLen Length of salt used. -1 indicates salt length is the same as the + * hash length. + * key Public RSA key. + * rng Random number generator. + * returns the length of the encrypted signature on success, a negative value + * indicates failure. + */ +int wc_RsaPSS_Sign_ex(const byte* in, word32 inLen, byte* out, word32 outLen, + enum wc_HashType hash, int mgf, int saltLen, RsaKey* key, + WC_RNG* rng) +{ + return RsaPublicEncryptEx(in, inLen, out, outLen, key, + RSA_PRIVATE_ENCRYPT, RSA_BLOCK_TYPE_1, WC_RSA_PSS_PAD, + hash, mgf, NULL, 0, saltLen, rng); +} +#endif +#endif + +#if !defined(WOLFSSL_RSA_VERIFY_ONLY) || !defined(WOLFSSL_SP_MATH) || \ + defined(WC_RSA_PSS) +int wc_RsaEncryptSize(RsaKey* key) +{ + int ret; + + if (key == NULL) { + return BAD_FUNC_ARG; + } + + ret = mp_unsigned_bin_size(&key->n); + +#ifdef WOLF_CRYPTO_CB + if (ret == 0 && key->devId != INVALID_DEVID) { + ret = 2048/8; /* hardware handles, use 2048-bit as default */ + } +#endif + + return ret; +} +#endif + +#ifndef WOLFSSL_RSA_VERIFY_ONLY +/* flatten RsaKey structure into individual elements (e, n) */ +int wc_RsaFlattenPublicKey(RsaKey* key, byte* e, word32* eSz, byte* n, + word32* nSz) +{ + int sz, ret; + + if (key == NULL || e == NULL || eSz == NULL || n == NULL || nSz == NULL) { + return BAD_FUNC_ARG; + } + + sz = mp_unsigned_bin_size(&key->e); + if ((word32)sz > *eSz) + return RSA_BUFFER_E; + ret = mp_to_unsigned_bin(&key->e, e); + if (ret != MP_OKAY) + return ret; + *eSz = (word32)sz; + + sz = wc_RsaEncryptSize(key); + if ((word32)sz > *nSz) + return RSA_BUFFER_E; + ret = mp_to_unsigned_bin(&key->n, n); + if (ret != MP_OKAY) + return ret; + *nSz = (word32)sz; + + return 0; +} +#endif + +#endif /* HAVE_FIPS */ + + +#ifndef WOLFSSL_RSA_VERIFY_ONLY +static int RsaGetValue(mp_int* in, byte* out, word32* outSz) +{ + word32 sz; + int ret = 0; + + /* Parameters ensured by calling function. */ + + sz = (word32)mp_unsigned_bin_size(in); + if (sz > *outSz) + ret = RSA_BUFFER_E; + + if (ret == 0) + ret = mp_to_unsigned_bin(in, out); + + if (ret == MP_OKAY) + *outSz = sz; + + return ret; +} + + +int wc_RsaExportKey(RsaKey* key, + byte* e, word32* eSz, byte* n, word32* nSz, + byte* d, word32* dSz, byte* p, word32* pSz, + byte* q, word32* qSz) +{ + int ret = BAD_FUNC_ARG; + + if (key && e && eSz && n && nSz && d && dSz && p && pSz && q && qSz) + ret = 0; + + if (ret == 0) + ret = RsaGetValue(&key->e, e, eSz); + if (ret == 0) + ret = RsaGetValue(&key->n, n, nSz); +#ifndef WOLFSSL_RSA_PUBLIC_ONLY + if (ret == 0) + ret = RsaGetValue(&key->d, d, dSz); + if (ret == 0) + ret = RsaGetValue(&key->p, p, pSz); + if (ret == 0) + ret = RsaGetValue(&key->q, q, qSz); +#else + /* no private parts to key */ + if (d == NULL || p == NULL || q == NULL || dSz == NULL || pSz == NULL + || qSz == NULL) { + ret = BAD_FUNC_ARG; + } + else { + *dSz = 0; + *pSz = 0; + *qSz = 0; + } +#endif /* WOLFSSL_RSA_PUBLIC_ONLY */ + + return ret; +} +#endif + + +#ifdef WOLFSSL_KEY_GEN + +/* Check that |p-q| > 2^((size/2)-100) */ +static int wc_CompareDiffPQ(mp_int* p, mp_int* q, int size) +{ + mp_int c, d; + int ret; + + if (p == NULL || q == NULL) + return BAD_FUNC_ARG; + + ret = mp_init_multi(&c, &d, NULL, NULL, NULL, NULL); + + /* c = 2^((size/2)-100) */ + if (ret == 0) + ret = mp_2expt(&c, (size/2)-100); + + /* d = |p-q| */ + if (ret == 0) + ret = mp_sub(p, q, &d); + + if (ret == 0) + ret = mp_abs(&d, &d); + + /* compare */ + if (ret == 0) + ret = mp_cmp(&d, &c); + + if (ret == MP_GT) + ret = MP_OKAY; + + mp_clear(&d); + mp_clear(&c); + + return ret; +} + + +/* The lower_bound value is floor(2^(0.5) * 2^((nlen/2)-1)) where nlen is 4096. + * This number was calculated using a small test tool written with a common + * large number math library. Other values of nlen may be checked with a subset + * of lower_bound. */ +static const byte lower_bound[] = { + 0xB5, 0x04, 0xF3, 0x33, 0xF9, 0xDE, 0x64, 0x84, + 0x59, 0x7D, 0x89, 0xB3, 0x75, 0x4A, 0xBE, 0x9F, + 0x1D, 0x6F, 0x60, 0xBA, 0x89, 0x3B, 0xA8, 0x4C, + 0xED, 0x17, 0xAC, 0x85, 0x83, 0x33, 0x99, 0x15, +/* 512 */ + 0x4A, 0xFC, 0x83, 0x04, 0x3A, 0xB8, 0xA2, 0xC3, + 0xA8, 0xB1, 0xFE, 0x6F, 0xDC, 0x83, 0xDB, 0x39, + 0x0F, 0x74, 0xA8, 0x5E, 0x43, 0x9C, 0x7B, 0x4A, + 0x78, 0x04, 0x87, 0x36, 0x3D, 0xFA, 0x27, 0x68, +/* 1024 */ + 0xD2, 0x20, 0x2E, 0x87, 0x42, 0xAF, 0x1F, 0x4E, + 0x53, 0x05, 0x9C, 0x60, 0x11, 0xBC, 0x33, 0x7B, + 0xCA, 0xB1, 0xBC, 0x91, 0x16, 0x88, 0x45, 0x8A, + 0x46, 0x0A, 0xBC, 0x72, 0x2F, 0x7C, 0x4E, 0x33, + 0xC6, 0xD5, 0xA8, 0xA3, 0x8B, 0xB7, 0xE9, 0xDC, + 0xCB, 0x2A, 0x63, 0x43, 0x31, 0xF3, 0xC8, 0x4D, + 0xF5, 0x2F, 0x12, 0x0F, 0x83, 0x6E, 0x58, 0x2E, + 0xEA, 0xA4, 0xA0, 0x89, 0x90, 0x40, 0xCA, 0x4A, +/* 2048 */ + 0x81, 0x39, 0x4A, 0xB6, 0xD8, 0xFD, 0x0E, 0xFD, + 0xF4, 0xD3, 0xA0, 0x2C, 0xEB, 0xC9, 0x3E, 0x0C, + 0x42, 0x64, 0xDA, 0xBC, 0xD5, 0x28, 0xB6, 0x51, + 0xB8, 0xCF, 0x34, 0x1B, 0x6F, 0x82, 0x36, 0xC7, + 0x01, 0x04, 0xDC, 0x01, 0xFE, 0x32, 0x35, 0x2F, + 0x33, 0x2A, 0x5E, 0x9F, 0x7B, 0xDA, 0x1E, 0xBF, + 0xF6, 0xA1, 0xBE, 0x3F, 0xCA, 0x22, 0x13, 0x07, + 0xDE, 0xA0, 0x62, 0x41, 0xF7, 0xAA, 0x81, 0xC2, +/* 3072 */ + 0xC1, 0xFC, 0xBD, 0xDE, 0xA2, 0xF7, 0xDC, 0x33, + 0x18, 0x83, 0x8A, 0x2E, 0xAF, 0xF5, 0xF3, 0xB2, + 0xD2, 0x4F, 0x4A, 0x76, 0x3F, 0xAC, 0xB8, 0x82, + 0xFD, 0xFE, 0x17, 0x0F, 0xD3, 0xB1, 0xF7, 0x80, + 0xF9, 0xAC, 0xCE, 0x41, 0x79, 0x7F, 0x28, 0x05, + 0xC2, 0x46, 0x78, 0x5E, 0x92, 0x95, 0x70, 0x23, + 0x5F, 0xCF, 0x8F, 0x7B, 0xCA, 0x3E, 0xA3, 0x3B, + 0x4D, 0x7C, 0x60, 0xA5, 0xE6, 0x33, 0xE3, 0xE1 +/* 4096 */ +}; + + +/* returns 1 on key size ok and 0 if not ok */ +static WC_INLINE int RsaSizeCheck(int size) +{ + if (size < RSA_MIN_SIZE || size > RSA_MAX_SIZE) { + return 0; + } + +#ifdef HAVE_FIPS + /* Key size requirements for CAVP */ + switch (size) { + case 1024: + case 2048: + case 3072: + case 4096: + return 1; + } + + return 0; +#else + return 1; /* allow unusual key sizes in non FIPS mode */ +#endif /* HAVE_FIPS */ +} + + +static int _CheckProbablePrime(mp_int* p, mp_int* q, mp_int* e, int nlen, + int* isPrime, WC_RNG* rng) +{ + int ret; + mp_int tmp1, tmp2; + mp_int* prime; + + if (p == NULL || e == NULL || isPrime == NULL) + return BAD_FUNC_ARG; + + if (!RsaSizeCheck(nlen)) + return BAD_FUNC_ARG; + + *isPrime = MP_NO; + + if (q != NULL) { + /* 5.4 - check that |p-q| <= (2^(1/2))(2^((nlen/2)-1)) */ + ret = wc_CompareDiffPQ(p, q, nlen); + if (ret != MP_OKAY) goto notOkay; + prime = q; + } + else + prime = p; + + ret = mp_init_multi(&tmp1, &tmp2, NULL, NULL, NULL, NULL); + if (ret != MP_OKAY) goto notOkay; + + /* 4.4,5.5 - Check that prime >= (2^(1/2))(2^((nlen/2)-1)) + * This is a comparison against lowerBound */ + ret = mp_read_unsigned_bin(&tmp1, lower_bound, nlen/16); + if (ret != MP_OKAY) goto notOkay; + ret = mp_cmp(prime, &tmp1); + if (ret == MP_LT) goto exit; + + /* 4.5,5.6 - Check that GCD(p-1, e) == 1 */ + ret = mp_sub_d(prime, 1, &tmp1); /* tmp1 = prime-1 */ + if (ret != MP_OKAY) goto notOkay; + ret = mp_gcd(&tmp1, e, &tmp2); /* tmp2 = gcd(prime-1, e) */ + if (ret != MP_OKAY) goto notOkay; + ret = mp_cmp_d(&tmp2, 1); + if (ret != MP_EQ) goto exit; /* e divides p-1 */ + + /* 4.5.1,5.6.1 - Check primality of p with 8 rounds of M-R. + * mp_prime_is_prime_ex() performs test divisions against the first 256 + * prime numbers. After that it performs 8 rounds of M-R using random + * bases between 2 and n-2. + * mp_prime_is_prime() performs the same test divisions and then does + * M-R with the first 8 primes. Both functions set isPrime as a + * side-effect. */ + if (rng != NULL) + ret = mp_prime_is_prime_ex(prime, 8, isPrime, rng); + else + ret = mp_prime_is_prime(prime, 8, isPrime); + if (ret != MP_OKAY) goto notOkay; + +exit: + ret = MP_OKAY; +notOkay: + mp_clear(&tmp1); + mp_clear(&tmp2); + return ret; +} + + +int wc_CheckProbablePrime_ex(const byte* pRaw, word32 pRawSz, + const byte* qRaw, word32 qRawSz, + const byte* eRaw, word32 eRawSz, + int nlen, int* isPrime, WC_RNG* rng) +{ + mp_int p, q, e; + mp_int* Q = NULL; + int ret; + + if (pRaw == NULL || pRawSz == 0 || + eRaw == NULL || eRawSz == 0 || + isPrime == NULL) { + + return BAD_FUNC_ARG; + } + + if ((qRaw != NULL && qRawSz == 0) || (qRaw == NULL && qRawSz != 0)) + return BAD_FUNC_ARG; + + ret = mp_init_multi(&p, &q, &e, NULL, NULL, NULL); + + if (ret == MP_OKAY) + ret = mp_read_unsigned_bin(&p, pRaw, pRawSz); + + if (ret == MP_OKAY) { + if (qRaw != NULL) { + ret = mp_read_unsigned_bin(&q, qRaw, qRawSz); + if (ret == MP_OKAY) + Q = &q; + } + } + + if (ret == MP_OKAY) + ret = mp_read_unsigned_bin(&e, eRaw, eRawSz); + + if (ret == MP_OKAY) + ret = _CheckProbablePrime(&p, Q, &e, nlen, isPrime, rng); + + ret = (ret == MP_OKAY) ? 0 : PRIME_GEN_E; + + mp_clear(&p); + mp_clear(&q); + mp_clear(&e); + + return ret; +} + + +int wc_CheckProbablePrime(const byte* pRaw, word32 pRawSz, + const byte* qRaw, word32 qRawSz, + const byte* eRaw, word32 eRawSz, + int nlen, int* isPrime) +{ + return wc_CheckProbablePrime_ex(pRaw, pRawSz, qRaw, qRawSz, + eRaw, eRawSz, nlen, isPrime, NULL); +} + +#if !defined(HAVE_FIPS) || (defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) +/* Make an RSA key for size bits, with e specified, 65537 is a good e */ +int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng) +{ +#ifndef WC_NO_RNG + mp_int p, q, tmp1, tmp2, tmp3; + int err, i, failCount, primeSz, isPrime = 0; + byte* buf = NULL; + + if (key == NULL || rng == NULL) + return BAD_FUNC_ARG; + + if (!RsaSizeCheck(size)) + return BAD_FUNC_ARG; + + if (e < 3 || (e & 1) == 0) + return BAD_FUNC_ARG; + +#if defined(WOLFSSL_CRYPTOCELL) + + return cc310_RSA_GenerateKeyPair(key, size, e); + +#endif /*WOLFSSL_CRYPTOCELL*/ + +#ifdef WOLF_CRYPTO_CB + if (key->devId != INVALID_DEVID) { + int ret = wc_CryptoCb_MakeRsaKey(key, size, e, rng); + if (ret != CRYPTOCB_UNAVAILABLE) + return ret; + /* fall-through when unavailable */ + } +#endif + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_RSA) && \ + defined(WC_ASYNC_ENABLE_RSA_KEYGEN) + if (key->asyncDev.marker == WOLFSSL_ASYNC_MARKER_RSA) { + #ifdef HAVE_CAVIUM + /* TODO: Not implemented */ + #elif defined(HAVE_INTEL_QA) + return IntelQaRsaKeyGen(&key->asyncDev, key, size, e, rng); + #else + if (wc_AsyncTestInit(&key->asyncDev, ASYNC_TEST_RSA_MAKE)) { + WC_ASYNC_TEST* testDev = &key->asyncDev.test; + testDev->rsaMake.rng = rng; + testDev->rsaMake.key = key; + testDev->rsaMake.size = size; + testDev->rsaMake.e = e; + return WC_PENDING_E; + } + #endif + } +#endif + + err = mp_init_multi(&p, &q, &tmp1, &tmp2, &tmp3, NULL); + + if (err == MP_OKAY) + err = mp_set_int(&tmp3, e); + + /* The failCount value comes from NIST FIPS 186-4, section B.3.3, + * process steps 4.7 and 5.8. */ + failCount = 5 * (size / 2); + primeSz = size / 16; /* size is the size of n in bits. + primeSz is in bytes. */ + + /* allocate buffer to work with */ + if (err == MP_OKAY) { + buf = (byte*)XMALLOC(primeSz, key->heap, DYNAMIC_TYPE_RSA); + if (buf == NULL) + err = MEMORY_E; + } + + /* make p */ + if (err == MP_OKAY) { + isPrime = 0; + i = 0; + do { +#ifdef SHOW_GEN + printf("."); + fflush(stdout); +#endif + /* generate value */ + err = wc_RNG_GenerateBlock(rng, buf, primeSz); + if (err == 0) { + /* prime lower bound has the MSB set, set it in candidate */ + buf[0] |= 0x80; + /* make candidate odd */ + buf[primeSz-1] |= 0x01; + /* load value */ + err = mp_read_unsigned_bin(&p, buf, primeSz); + } + + if (err == MP_OKAY) + err = _CheckProbablePrime(&p, NULL, &tmp3, size, &isPrime, rng); + +#ifdef HAVE_FIPS + i++; +#else + /* Keep the old retry behavior in non-FIPS build. */ + (void)i; +#endif + } while (err == MP_OKAY && !isPrime && i < failCount); + } + + if (err == MP_OKAY && !isPrime) + err = PRIME_GEN_E; + + /* make q */ + if (err == MP_OKAY) { + isPrime = 0; + i = 0; + do { +#ifdef SHOW_GEN + printf("."); + fflush(stdout); +#endif + /* generate value */ + err = wc_RNG_GenerateBlock(rng, buf, primeSz); + if (err == 0) { + /* prime lower bound has the MSB set, set it in candidate */ + buf[0] |= 0x80; + /* make candidate odd */ + buf[primeSz-1] |= 0x01; + /* load value */ + err = mp_read_unsigned_bin(&q, buf, primeSz); + } + + if (err == MP_OKAY) + err = _CheckProbablePrime(&p, &q, &tmp3, size, &isPrime, rng); + +#ifdef HAVE_FIPS + i++; +#else + /* Keep the old retry behavior in non-FIPS build. */ + (void)i; +#endif + } while (err == MP_OKAY && !isPrime && i < failCount); + } + + if (err == MP_OKAY && !isPrime) + err = PRIME_GEN_E; + + if (buf) { + ForceZero(buf, primeSz); + XFREE(buf, key->heap, DYNAMIC_TYPE_RSA); + } + + + /* Setup RsaKey buffers */ + if (err == MP_OKAY) + err = mp_init_multi(&key->n, &key->e, &key->d, &key->p, &key->q, NULL); + if (err == MP_OKAY) + err = mp_init_multi(&key->dP, &key->dQ, &key->u, NULL, NULL, NULL); + + /* Software Key Calculation */ + if (err == MP_OKAY) /* tmp1 = p-1 */ + err = mp_sub_d(&p, 1, &tmp1); + if (err == MP_OKAY) /* tmp2 = q-1 */ + err = mp_sub_d(&q, 1, &tmp2); + if (err == MP_OKAY) /* tmp3 = lcm(p-1, q-1), last loop */ + err = mp_lcm(&tmp1, &tmp2, &tmp3); + /* make key */ + if (err == MP_OKAY) /* key->e = e */ + err = mp_set_int(&key->e, (mp_digit)e); + if (err == MP_OKAY) /* key->d = 1/e mod lcm(p-1, q-1) */ + err = mp_invmod(&key->e, &tmp3, &key->d); + if (err == MP_OKAY) /* key->n = pq */ + err = mp_mul(&p, &q, &key->n); + if (err == MP_OKAY) /* key->dP = d mod(p-1) */ + err = mp_mod(&key->d, &tmp1, &key->dP); + if (err == MP_OKAY) /* key->dQ = d mod(q-1) */ + err = mp_mod(&key->d, &tmp2, &key->dQ); + if (err == MP_OKAY) /* key->u = 1/q mod p */ + err = mp_invmod(&q, &p, &key->u); + if (err == MP_OKAY) + err = mp_copy(&p, &key->p); + if (err == MP_OKAY) + err = mp_copy(&q, &key->q); + +#ifdef HAVE_WOLF_BIGINT + /* make sure raw unsigned bin version is available */ + if (err == MP_OKAY) + err = wc_mp_to_bigint(&key->n, &key->n.raw); + if (err == MP_OKAY) + err = wc_mp_to_bigint(&key->e, &key->e.raw); + if (err == MP_OKAY) + err = wc_mp_to_bigint(&key->d, &key->d.raw); + if (err == MP_OKAY) + err = wc_mp_to_bigint(&key->p, &key->p.raw); + if (err == MP_OKAY) + err = wc_mp_to_bigint(&key->q, &key->q.raw); + if (err == MP_OKAY) + err = wc_mp_to_bigint(&key->dP, &key->dP.raw); + if (err == MP_OKAY) + err = wc_mp_to_bigint(&key->dQ, &key->dQ.raw); + if (err == MP_OKAY) + err = wc_mp_to_bigint(&key->u, &key->u.raw); +#endif + + if (err == MP_OKAY) + key->type = RSA_PRIVATE; + + mp_clear(&tmp1); + mp_clear(&tmp2); + mp_clear(&tmp3); + mp_clear(&p); + mp_clear(&q); + +#if defined(WOLFSSL_KEY_GEN) && !defined(WOLFSSL_NO_RSA_KEY_CHECK) + /* Perform the pair-wise consistency test on the new key. */ + if (err == 0) + err = wc_CheckRsaKey(key); +#endif + + if (err != 0) { + wc_FreeRsaKey(key); + return err; + } + +#if defined(WOLFSSL_XILINX_CRYPT) || defined(WOLFSSL_CRYPTOCELL) + if (wc_InitRsaHw(key) != 0) { + return BAD_STATE_E; + } +#endif + return 0; +#else + return NOT_COMPILED_IN; +#endif +} +#endif /* !FIPS || FIPS_VER >= 2 */ +#endif /* WOLFSSL_KEY_GEN */ + + +#ifdef WC_RSA_BLINDING +int wc_RsaSetRNG(RsaKey* key, WC_RNG* rng) +{ + if (key == NULL) + return BAD_FUNC_ARG; + + key->rng = rng; + + return 0; +} +#endif /* WC_RSA_BLINDING */ + +#ifdef WC_RSA_NONBLOCK +int wc_RsaSetNonBlock(RsaKey* key, RsaNb* nb) +{ + if (key == NULL) + return BAD_FUNC_ARG; + + if (nb) { + XMEMSET(nb, 0, sizeof(RsaNb)); + } + + /* Allow nb == NULL to clear non-block mode */ + key->nb = nb; + + return 0; +} +#ifdef WC_RSA_NONBLOCK_TIME +int wc_RsaSetNonBlockTime(RsaKey* key, word32 maxBlockUs, word32 cpuMHz) +{ + if (key == NULL || key->nb == NULL) { + return BAD_FUNC_ARG; + } + + /* calculate maximum number of instructions to block */ + key->nb->exptmod.maxBlockInst = cpuMHz * maxBlockUs; + + return 0; +} +#endif /* WC_RSA_NONBLOCK_TIME */ +#endif /* WC_RSA_NONBLOCK */ + +#endif /* NO_RSA */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/sha.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/sha.c new file mode 100755 index 0000000..7e2be25 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/sha.c @@ -0,0 +1,743 @@ +/* sha.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#if !defined(NO_SHA) + +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + + /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ + #define FIPS_NO_WRAPPERS + + #ifdef USE_WINDOWS_API + #pragma code_seg(".fipsA$j") + #pragma const_seg(".fipsB$j") + #endif +#endif + +#include +#include +#include + +#ifdef WOLF_CRYPTO_CB + #include +#endif + +/* fips wrapper calls, user can call direct */ +#if defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) + + int wc_InitSha(wc_Sha* sha) + { + if (sha == NULL) { + return BAD_FUNC_ARG; + } + return InitSha_fips(sha); + } + int wc_InitSha_ex(wc_Sha* sha, void* heap, int devId) + { + (void)heap; + (void)devId; + if (sha == NULL) { + return BAD_FUNC_ARG; + } + return InitSha_fips(sha); + } + + int wc_ShaUpdate(wc_Sha* sha, const byte* data, word32 len) + { + if (sha == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + return ShaUpdate_fips(sha, data, len); + } + + int wc_ShaFinal(wc_Sha* sha, byte* out) + { + if (sha == NULL || out == NULL) { + return BAD_FUNC_ARG; + } + return ShaFinal_fips(sha,out); + } + void wc_ShaFree(wc_Sha* sha) + { + (void)sha; + /* Not supported in FIPS */ + } + +#else /* else build without fips, or for FIPS v2 */ + + +#if defined(WOLFSSL_TI_HASH) + /* #include included by wc_port.c */ + +#else + +#include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + + +/* Hardware Acceleration */ +#if defined(WOLFSSL_PIC32MZ_HASH) + #include + +#elif defined(STM32_HASH) + + /* Supports CubeMX HAL or Standard Peripheral Library */ + int wc_InitSha_ex(wc_Sha* sha, void* heap, int devId) + { + if (sha == NULL) { + return BAD_FUNC_ARG; + } + + (void)devId; + (void)heap; + + wc_Stm32_Hash_Init(&sha->stmCtx); + + return 0; + } + + int wc_ShaUpdate(wc_Sha* sha, const byte* data, word32 len) + { + int ret; + + if (sha == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + + ret = wolfSSL_CryptHwMutexLock(); + if (ret == 0) { + ret = wc_Stm32_Hash_Update(&sha->stmCtx, HASH_AlgoSelection_SHA1, + data, len); + wolfSSL_CryptHwMutexUnLock(); + } + return ret; + } + + int wc_ShaFinal(wc_Sha* sha, byte* hash) + { + int ret; + + if (sha == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + + ret = wolfSSL_CryptHwMutexLock(); + if (ret == 0) { + ret = wc_Stm32_Hash_Final(&sha->stmCtx, HASH_AlgoSelection_SHA1, + hash, WC_SHA_DIGEST_SIZE); + wolfSSL_CryptHwMutexUnLock(); + } + + (void)wc_InitSha(sha); /* reset state */ + + return ret; + } + + +#elif defined(FREESCALE_LTC_SHA) + + #include "fsl_ltc.h" + int wc_InitSha_ex(wc_Sha* sha, void* heap, int devId) + { + if (sha == NULL) { + return BAD_FUNC_ARG; + } + + (void)devId; + (void)heap; + + LTC_HASH_Init(LTC_BASE, &sha->ctx, kLTC_Sha1, NULL, 0); + return 0; + } + + int wc_ShaUpdate(wc_Sha* sha, const byte* data, word32 len) + { + LTC_HASH_Update(&sha->ctx, data, len); + return 0; + } + + int wc_ShaFinal(wc_Sha* sha, byte* hash) + { + uint32_t hashlen = WC_SHA_DIGEST_SIZE; + LTC_HASH_Finish(&sha->ctx, hash, &hashlen); + return wc_InitSha(sha); /* reset state */ + } + + +#elif defined(FREESCALE_MMCAU_SHA) + + #ifdef FREESCALE_MMCAU_CLASSIC_SHA + #include "cau_api.h" + #else + #include "fsl_mmcau.h" + #endif + + #define USE_SHA_SOFTWARE_IMPL /* Only for API's, actual transform is here */ + #define XTRANSFORM(S,B) Transform((S),(B)) + + static int InitSha(wc_Sha* sha) + { + int ret = 0; + ret = wolfSSL_CryptHwMutexLock(); + if (ret != 0) { + return ret; + } + #ifdef FREESCALE_MMCAU_CLASSIC_SHA + cau_sha1_initialize_output(sha->digest); + #else + MMCAU_SHA1_InitializeOutput((uint32_t*)sha->digest); + #endif + wolfSSL_CryptHwMutexUnLock(); + + sha->buffLen = 0; + sha->loLen = 0; + sha->hiLen = 0; + + return ret; + } + + static int Transform(wc_Sha* sha, byte* data) + { + int ret = wolfSSL_CryptHwMutexLock(); + if(ret == 0) { + #ifdef FREESCALE_MMCAU_CLASSIC_SHA + cau_sha1_hash_n(data, 1, sha->digest); + #else + MMCAU_SHA1_HashN(data, 1, (uint32_t*)sha->digest); + #endif + wolfSSL_CryptHwMutexUnLock(); + } + return ret; + } + +#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH) + /* wolfcrypt/src/port/caam/caam_sha.c */ + +#elif defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + + #include "wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h" + + #define USE_SHA_SOFTWARE_IMPL + + static int InitSha(wc_Sha* sha) + { + int ret = 0; + + sha->digest[0] = 0x67452301L; + sha->digest[1] = 0xEFCDAB89L; + sha->digest[2] = 0x98BADCFEL; + sha->digest[3] = 0x10325476L; + sha->digest[4] = 0xC3D2E1F0L; + + sha->buffLen = 0; + sha->loLen = 0; + sha->hiLen = 0; + + /* alwasy start firstblock = 1 when using hw engine */ + sha->ctx.isfirstblock = 1; + sha->ctx.sha_type = SHA1; + if(sha->ctx.mode == ESP32_SHA_HW){ + /* release hw engine */ + esp_sha_hw_unlock(); + } + /* always set mode as INIT + * whether using HW or SW is detemined at first call of update() + */ + sha->ctx.mode = ESP32_SHA_INIT; + + return ret; + } + +#else + /* Software implementation */ + #define USE_SHA_SOFTWARE_IMPL + + static int InitSha(wc_Sha* sha) + { + int ret = 0; + + sha->digest[0] = 0x67452301L; + sha->digest[1] = 0xEFCDAB89L; + sha->digest[2] = 0x98BADCFEL; + sha->digest[3] = 0x10325476L; + sha->digest[4] = 0xC3D2E1F0L; + + sha->buffLen = 0; + sha->loLen = 0; + sha->hiLen = 0; + + return ret; + } + +#endif /* End Hardware Acceleration */ + + +/* Software implementation */ +#ifdef USE_SHA_SOFTWARE_IMPL + +static WC_INLINE void AddLength(wc_Sha* sha, word32 len) +{ + word32 tmp = sha->loLen; + if ((sha->loLen += len) < tmp) + sha->hiLen++; /* carry low to high */ +} + +/* Check if custom wc_Sha transform is used */ +#ifndef XTRANSFORM + #define XTRANSFORM(S,B) Transform((S),(B)) + + #define blk0(i) (W[i] = sha->buffer[i]) + #define blk1(i) (W[(i)&15] = \ + rotlFixed(W[((i)+13)&15]^W[((i)+8)&15]^W[((i)+2)&15]^W[(i)&15],1)) + + #define f1(x,y,z) ((z)^((x) &((y)^(z)))) + #define f2(x,y,z) ((x)^(y)^(z)) + #define f3(x,y,z) (((x)&(y))|((z)&((x)|(y)))) + #define f4(x,y,z) ((x)^(y)^(z)) + + #ifdef WOLFSSL_NUCLEUS_1_2 + /* nucleus.h also defines R1-R4 */ + #undef R1 + #undef R2 + #undef R3 + #undef R4 + #endif + + /* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */ + #define R0(v,w,x,y,z,i) (z)+= f1((w),(x),(y)) + blk0((i)) + 0x5A827999+ \ + rotlFixed((v),5); (w) = rotlFixed((w),30); + #define R1(v,w,x,y,z,i) (z)+= f1((w),(x),(y)) + blk1((i)) + 0x5A827999+ \ + rotlFixed((v),5); (w) = rotlFixed((w),30); + #define R2(v,w,x,y,z,i) (z)+= f2((w),(x),(y)) + blk1((i)) + 0x6ED9EBA1+ \ + rotlFixed((v),5); (w) = rotlFixed((w),30); + #define R3(v,w,x,y,z,i) (z)+= f3((w),(x),(y)) + blk1((i)) + 0x8F1BBCDC+ \ + rotlFixed((v),5); (w) = rotlFixed((w),30); + #define R4(v,w,x,y,z,i) (z)+= f4((w),(x),(y)) + blk1((i)) + 0xCA62C1D6+ \ + rotlFixed((v),5); (w) = rotlFixed((w),30); + + static void Transform(wc_Sha* sha, byte* data) + { + word32 W[WC_SHA_BLOCK_SIZE / sizeof(word32)]; + + /* Copy context->state[] to working vars */ + word32 a = sha->digest[0]; + word32 b = sha->digest[1]; + word32 c = sha->digest[2]; + word32 d = sha->digest[3]; + word32 e = sha->digest[4]; + + #ifdef USE_SLOW_SHA + word32 t, i; + + for (i = 0; i < 16; i++) { + R0(a, b, c, d, e, i); + t = e; e = d; d = c; c = b; b = a; a = t; + } + + for (; i < 20; i++) { + R1(a, b, c, d, e, i); + t = e; e = d; d = c; c = b; b = a; a = t; + } + + for (; i < 40; i++) { + R2(a, b, c, d, e, i); + t = e; e = d; d = c; c = b; b = a; a = t; + } + + for (; i < 60; i++) { + R3(a, b, c, d, e, i); + t = e; e = d; d = c; c = b; b = a; a = t; + } + + for (; i < 80; i++) { + R4(a, b, c, d, e, i); + t = e; e = d; d = c; c = b; b = a; a = t; + } + #else + /* nearly 1 K bigger in code size but 25% faster */ + /* 4 rounds of 20 operations each. Loop unrolled. */ + R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3); + R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7); + R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11); + R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15); + + R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19); + + R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23); + R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27); + R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31); + R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35); + R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39); + + R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43); + R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47); + R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51); + R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55); + R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59); + + R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63); + R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67); + R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71); + R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75); + R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79); + #endif + + /* Add the working vars back into digest state[] */ + sha->digest[0] += a; + sha->digest[1] += b; + sha->digest[2] += c; + sha->digest[3] += d; + sha->digest[4] += e; + + (void)data; /* Not used */ + } +#endif /* !USE_CUSTOM_SHA_TRANSFORM */ + + +int wc_InitSha_ex(wc_Sha* sha, void* heap, int devId) +{ + int ret = 0; + + if (sha == NULL) + return BAD_FUNC_ARG; + + sha->heap = heap; +#ifdef WOLF_CRYPTO_CB + sha->devId = devId; +#endif + +#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + sha->ctx.mode = ESP32_SHA_INIT; + sha->ctx.isfirstblock = 1; +#endif + ret = InitSha(sha); + if (ret != 0) + return ret; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA) + ret = wolfAsync_DevCtxInit(&sha->asyncDev, WOLFSSL_ASYNC_MARKER_SHA, + sha->heap, devId); +#else + (void)devId; +#endif /* WOLFSSL_ASYNC_CRYPT */ + + return ret; +} + +int wc_ShaUpdate(wc_Sha* sha, const byte* data, word32 len) +{ + byte* local; + + if (sha == NULL ||(data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + + /* do block size increments */ + local = (byte*)sha->buffer; + +#ifdef WOLF_CRYPTO_CB + if (sha->devId != INVALID_DEVID) { + int ret = wc_CryptoCb_ShaHash(sha, data, len, NULL); + if (ret != CRYPTOCB_UNAVAILABLE) + return ret; + /* fall-through when unavailable */ + } +#endif +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA) + if (sha->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA) { + #if defined(HAVE_INTEL_QA) + return IntelQaSymSha(&sha->asyncDev, NULL, data, len); + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + /* check that internal buffLen is valid */ + if (sha->buffLen >= WC_SHA_BLOCK_SIZE) + return BUFFER_E; + + while (len) { + word32 add = min(len, WC_SHA_BLOCK_SIZE - sha->buffLen); + XMEMCPY(&local[sha->buffLen], data, add); + + sha->buffLen += add; + data += add; + len -= add; + + if (sha->buffLen == WC_SHA_BLOCK_SIZE) { +#if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) + ByteReverseWords(sha->buffer, sha->buffer, WC_SHA_BLOCK_SIZE); +#endif +#if !defined(WOLFSSL_ESP32WROOM32_CRYPT) || \ + defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + XTRANSFORM(sha, local); +#else + if(sha->ctx.mode == ESP32_SHA_INIT){ + esp_sha_try_hw_lock(&sha->ctx); + } + if(sha->ctx.mode == ESP32_SHA_SW){ + XTRANSFORM(sha, local); + } else { + esp_sha_process(sha); + } +#endif + AddLength(sha, WC_SHA_BLOCK_SIZE); + sha->buffLen = 0; + } + } + + return 0; +} + +int wc_ShaFinalRaw(wc_Sha* sha, byte* hash) +{ +#ifdef LITTLE_ENDIAN_ORDER + word32 digest[WC_SHA_DIGEST_SIZE / sizeof(word32)]; +#endif + + if (sha == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef LITTLE_ENDIAN_ORDER + ByteReverseWords((word32*)digest, (word32*)sha->digest, WC_SHA_DIGEST_SIZE); + XMEMCPY(hash, digest, WC_SHA_DIGEST_SIZE); +#else + XMEMCPY(hash, sha->digest, WC_SHA_DIGEST_SIZE); +#endif + + return 0; +} + +int wc_ShaFinal(wc_Sha* sha, byte* hash) +{ + byte* local; + + if (sha == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + + local = (byte*)sha->buffer; + +#ifdef WOLF_CRYPTO_CB + if (sha->devId != INVALID_DEVID) { + int ret = wc_CryptoCb_ShaHash(sha, NULL, 0, hash); + if (ret != CRYPTOCB_UNAVAILABLE) + return ret; + /* fall-through when unavailable */ + } +#endif +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA) + if (sha->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA) { + #if defined(HAVE_INTEL_QA) + return IntelQaSymSha(&sha->asyncDev, hash, NULL, WC_SHA_DIGEST_SIZE); + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + AddLength(sha, sha->buffLen); /* before adding pads */ + + local[sha->buffLen++] = 0x80; /* add 1 */ + + /* pad with zeros */ + if (sha->buffLen > WC_SHA_PAD_SIZE) { + XMEMSET(&local[sha->buffLen], 0, WC_SHA_BLOCK_SIZE - sha->buffLen); + sha->buffLen += WC_SHA_BLOCK_SIZE - sha->buffLen; + +#if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) + ByteReverseWords(sha->buffer, sha->buffer, WC_SHA_BLOCK_SIZE); +#endif +#if !defined(WOLFSSL_ESP32WROOM32_CRYPT) || \ + defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + XTRANSFORM(sha, local); +#else + if(sha->ctx.mode == ESP32_SHA_INIT){ + esp_sha_try_hw_lock(&sha->ctx); + } + if(sha->ctx.mode == ESP32_SHA_SW){ + XTRANSFORM(sha, local); + } else { + esp_sha_process(sha); + } +#endif + sha->buffLen = 0; + } + XMEMSET(&local[sha->buffLen], 0, WC_SHA_PAD_SIZE - sha->buffLen); + +#if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) + ByteReverseWords(sha->buffer, sha->buffer, WC_SHA_BLOCK_SIZE); +#endif + + /* store lengths */ + /* put lengths in bits */ + sha->hiLen = (sha->loLen >> (8*sizeof(sha->loLen) - 3)) + (sha->hiLen << 3); + sha->loLen = sha->loLen << 3; + + /* ! length ordering dependent on digest endian type ! */ + XMEMCPY(&local[WC_SHA_PAD_SIZE], &sha->hiLen, sizeof(word32)); + XMEMCPY(&local[WC_SHA_PAD_SIZE + sizeof(word32)], &sha->loLen, sizeof(word32)); + +#if defined(FREESCALE_MMCAU_SHA) + /* Kinetis requires only these bytes reversed */ + ByteReverseWords(&sha->buffer[WC_SHA_PAD_SIZE/sizeof(word32)], + &sha->buffer[WC_SHA_PAD_SIZE/sizeof(word32)], + 2 * sizeof(word32)); +#endif + +#if !defined(WOLFSSL_ESP32WROOM32_CRYPT) || \ + defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + XTRANSFORM(sha, local); +#else + if(sha->ctx.mode == ESP32_SHA_INIT){ + esp_sha_try_hw_lock(&sha->ctx); + } + if(sha->ctx.mode == ESP32_SHA_SW){ + XTRANSFORM(sha, local); + } else { + esp_sha_digest_process(sha, 1); + } +#endif + +#ifdef LITTLE_ENDIAN_ORDER + ByteReverseWords(sha->digest, sha->digest, WC_SHA_DIGEST_SIZE); +#endif + XMEMCPY(hash, sha->digest, WC_SHA_DIGEST_SIZE); + + return InitSha(sha); /* reset state */ +} + +#endif /* USE_SHA_SOFTWARE_IMPL */ + + +int wc_InitSha(wc_Sha* sha) +{ + return wc_InitSha_ex(sha, NULL, INVALID_DEVID); +} + +void wc_ShaFree(wc_Sha* sha) +{ + if (sha == NULL) + return; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA) + wolfAsync_DevCtxFree(&sha->asyncDev, WOLFSSL_ASYNC_MARKER_SHA); +#endif /* WOLFSSL_ASYNC_CRYPT */ + +#ifdef WOLFSSL_PIC32MZ_HASH + wc_ShaPic32Free(sha); +#endif +} + +#endif /* !WOLFSSL_TI_HASH */ +#endif /* HAVE_FIPS */ + +#ifndef WOLFSSL_TI_HASH +int wc_ShaGetHash(wc_Sha* sha, byte* hash) +{ + int ret; + wc_Sha tmpSha; + + if (sha == NULL || hash == NULL) + return BAD_FUNC_ARG; + +#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + if(sha->ctx.mode == ESP32_SHA_INIT){ + esp_sha_try_hw_lock(&sha->ctx); + } + if(sha->ctx.mode != ESP32_SHA_SW) + esp_sha_digest_process(sha, 0); +#endif + + ret = wc_ShaCopy(sha, &tmpSha); + if (ret == 0) { + ret = wc_ShaFinal(&tmpSha, hash); +#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + sha->ctx.mode = ESP32_SHA_SW; +#endif + } + return ret; +} + +int wc_ShaCopy(wc_Sha* src, wc_Sha* dst) +{ + int ret = 0; + + if (src == NULL || dst == NULL) + return BAD_FUNC_ARG; + + XMEMCPY(dst, src, sizeof(wc_Sha)); + +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev); +#endif +#ifdef WOLFSSL_PIC32MZ_HASH + ret = wc_Pic32HashCopy(&src->cache, &dst->cache); +#endif +#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + dst->ctx.mode = src->ctx.mode; + dst->ctx.isfirstblock = src->ctx.isfirstblock; + dst->ctx.sha_type = src->ctx.sha_type; +#endif +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + dst->flags |= WC_HASH_FLAG_ISCOPY; +#endif + + return ret; +} +#endif /* !WOLFSSL_TI_HASH */ + + +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) +int wc_ShaSetFlags(wc_Sha* sha, word32 flags) +{ + if (sha) { + sha->flags = flags; + } + return 0; +} +int wc_ShaGetFlags(wc_Sha* sha, word32* flags) +{ + if (sha && flags) { + *flags = sha->flags; + } + return 0; +} +#endif + +#endif /* !NO_SHA */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/sha256.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/sha256.c new file mode 100755 index 0000000..059f224 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/sha256.c @@ -0,0 +1,1509 @@ +/* sha256.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +/* + * SHA256 Build Options: + * USE_SLOW_SHA256: Reduces code size by not partially unrolling + (~2KB smaller and ~25% slower) (default OFF) + * WOLFSSL_SHA256_BY_SPEC: Uses the Ch/Maj based on SHA256 specification + (default ON) + * WOLFSSL_SHA256_ALT_CH_MAJ: Alternate Ch/Maj that is easier for compilers to + optimize and recognize as SHA256 (default OFF) + * SHA256_MANY_REGISTERS: A SHA256 version that keeps all data in registers + and partial unrolled (default OFF) + */ + +/* Default SHA256 to use Ch/Maj based on specification */ +#if !defined(WOLFSSL_SHA256_BY_SPEC) && !defined(WOLFSSL_SHA256_ALT_CH_MAJ) + #define WOLFSSL_SHA256_BY_SPEC +#endif + + +#if !defined(NO_SHA256) && !defined(WOLFSSL_ARMASM) + +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + + /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ + #define FIPS_NO_WRAPPERS + + #ifdef USE_WINDOWS_API + #pragma code_seg(".fipsA$d") + #pragma const_seg(".fipsB$d") + #endif +#endif + +#include +#include +#include +#include + +#ifdef WOLF_CRYPTO_CB + #include +#endif + +/* fips wrapper calls, user can call direct */ +#if defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) + + int wc_InitSha256(wc_Sha256* sha) + { + if (sha == NULL) { + return BAD_FUNC_ARG; + } + return InitSha256_fips(sha); + } + int wc_InitSha256_ex(wc_Sha256* sha, void* heap, int devId) + { + (void)heap; + (void)devId; + if (sha == NULL) { + return BAD_FUNC_ARG; + } + return InitSha256_fips(sha); + } + int wc_Sha256Update(wc_Sha256* sha, const byte* data, word32 len) + { + if (sha == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + + if (data == NULL && len == 0) { + /* valid, but do nothing */ + return 0; + } + + return Sha256Update_fips(sha, data, len); + } + int wc_Sha256Final(wc_Sha256* sha, byte* out) + { + if (sha == NULL || out == NULL) { + return BAD_FUNC_ARG; + } + return Sha256Final_fips(sha, out); + } + void wc_Sha256Free(wc_Sha256* sha) + { + (void)sha; + /* Not supported in FIPS */ + } + +#else /* else build without fips, or for FIPS v2 */ + + +#if defined(WOLFSSL_TI_HASH) + /* #include included by wc_port.c */ +#elif defined(WOLFSSL_CRYPTOCELL) + /* wc_port.c includes wolfcrypt/src/port/arm/cryptoCellHash.c */ +#else + +#include + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#ifdef WOLFSSL_DEVCRYPTO_HASH + #include +#endif + + + +#if defined(USE_INTEL_SPEEDUP) + #if defined(__GNUC__) && ((__GNUC__ < 4) || \ + (__GNUC__ == 4 && __GNUC_MINOR__ <= 8)) + #undef NO_AVX2_SUPPORT + #define NO_AVX2_SUPPORT + #endif + #if defined(__clang__) && ((__clang_major__ < 3) || \ + (__clang_major__ == 3 && __clang_minor__ <= 5)) + #define NO_AVX2_SUPPORT + #elif defined(__clang__) && defined(NO_AVX2_SUPPORT) + #undef NO_AVX2_SUPPORT + #endif + + #define HAVE_INTEL_AVX1 + #ifndef NO_AVX2_SUPPORT + #define HAVE_INTEL_AVX2 + #endif +#endif /* USE_INTEL_SPEEDUP */ + +#if defined(HAVE_INTEL_AVX2) + #define HAVE_INTEL_RORX +#endif + + +#if !defined(WOLFSSL_PIC32MZ_HASH) && !defined(STM32_HASH_SHA2) && \ + (!defined(WOLFSSL_IMX6_CAAM) || defined(NO_IMX6_CAAM_HASH)) && \ + !defined(WOLFSSL_AFALG_HASH) && !defined(WOLFSSL_DEVCRYPTO_HASH) && \ + (!defined(WOLFSSL_ESP32WROOM32_CRYPT) || defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)) +static int InitSha256(wc_Sha256* sha256) +{ + int ret = 0; + + if (sha256 == NULL) + return BAD_FUNC_ARG; + + XMEMSET(sha256->digest, 0, sizeof(sha256->digest)); + sha256->digest[0] = 0x6A09E667L; + sha256->digest[1] = 0xBB67AE85L; + sha256->digest[2] = 0x3C6EF372L; + sha256->digest[3] = 0xA54FF53AL; + sha256->digest[4] = 0x510E527FL; + sha256->digest[5] = 0x9B05688CL; + sha256->digest[6] = 0x1F83D9ABL; + sha256->digest[7] = 0x5BE0CD19L; + + sha256->buffLen = 0; + sha256->loLen = 0; + sha256->hiLen = 0; + + return ret; +} +#endif + + +/* Hardware Acceleration */ +#if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + + /* in case intel instructions aren't available, plus we need the K[] global */ + #define NEED_SOFT_SHA256 + + /***** + Intel AVX1/AVX2 Macro Control Structure + + #define HAVE_INTEL_AVX1 + #define HAVE_INTEL_AVX2 + + #define HAVE_INTEL_RORX + + + int InitSha256(wc_Sha256* sha256) { + Save/Recover XMM, YMM + ... + } + + #if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) + Transform_Sha256(); Function prototype + #else + Transform_Sha256() { } + int Sha256Final() { + Save/Recover XMM, YMM + ... + } + #endif + + #if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) + #if defined(HAVE_INTEL_RORX + #define RND with rorx instuction + #else + #define RND + #endif + #endif + + #if defined(HAVE_INTEL_AVX1) + + #define XMM Instructions/inline asm + + int Transform_Sha256() { + Stitched Message Sched/Round + } + + #elif defined(HAVE_INTEL_AVX2) + + #define YMM Instructions/inline asm + + int Transform_Sha256() { + More granural Stitched Message Sched/Round + } + + #endif + + */ + + /* Each platform needs to query info type 1 from cpuid to see if aesni is + * supported. Also, let's setup a macro for proper linkage w/o ABI conflicts + */ + + /* #if defined(HAVE_INTEL_AVX1/2) at the tail of sha256 */ + static int Transform_Sha256(wc_Sha256* sha256); + +#ifdef __cplusplus + extern "C" { +#endif + + #if defined(HAVE_INTEL_AVX1) + extern int Transform_Sha256_AVX1(wc_Sha256 *sha256); + extern int Transform_Sha256_AVX1_Len(wc_Sha256* sha256, + const byte* data, word32 len); + #endif + #if defined(HAVE_INTEL_AVX2) + extern int Transform_Sha256_AVX2(wc_Sha256 *sha256); + extern int Transform_Sha256_AVX2_Len(wc_Sha256* sha256, + const byte* data, word32 len); + #ifdef HAVE_INTEL_RORX + extern int Transform_Sha256_AVX1_RORX(wc_Sha256 *sha256); + extern int Transform_Sha256_AVX1_RORX_Len(wc_Sha256* sha256, + const byte* data, word32 len); + extern int Transform_Sha256_AVX2_RORX(wc_Sha256 *sha256); + extern int Transform_Sha256_AVX2_RORX_Len(wc_Sha256* sha256, + const byte* data, word32 len); + #endif + #endif + +#ifdef __cplusplus + } /* extern "C" */ +#endif + + static int (*Transform_Sha256_p)(wc_Sha256* sha256); + /* = _Transform_Sha256 */ + static int (*Transform_Sha256_Len_p)(wc_Sha256* sha256, const byte* data, + word32 len); + /* = NULL */ + static int transform_check = 0; + static word32 intel_flags; + #define XTRANSFORM(S) (*Transform_Sha256_p)((S)) + #define XTRANSFORM_LEN(S, D, L) (*Transform_Sha256_Len_p)((S),(D),(L)) + + static void Sha256_SetTransform(void) + { + + if (transform_check) + return; + + intel_flags = cpuid_get_flags(); + + #ifdef HAVE_INTEL_AVX2 + if (1 && IS_INTEL_AVX2(intel_flags)) { + #ifdef HAVE_INTEL_RORX + if (IS_INTEL_BMI2(intel_flags)) { + Transform_Sha256_p = Transform_Sha256_AVX2_RORX; + Transform_Sha256_Len_p = Transform_Sha256_AVX2_RORX_Len; + } + else + #endif + if (1) + { + Transform_Sha256_p = Transform_Sha256_AVX2; + Transform_Sha256_Len_p = Transform_Sha256_AVX2_Len; + } + #ifdef HAVE_INTEL_RORX + else { + Transform_Sha256_p = Transform_Sha256_AVX1_RORX; + Transform_Sha256_Len_p = Transform_Sha256_AVX1_RORX_Len; + } + #endif + } + else + #endif + #ifdef HAVE_INTEL_AVX1 + if (IS_INTEL_AVX1(intel_flags)) { + Transform_Sha256_p = Transform_Sha256_AVX1; + Transform_Sha256_Len_p = Transform_Sha256_AVX1_Len; + } + else + #endif + { + Transform_Sha256_p = Transform_Sha256; + Transform_Sha256_Len_p = NULL; + } + + transform_check = 1; + } + + int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId) + { + int ret = 0; + if (sha256 == NULL) + return BAD_FUNC_ARG; + + sha256->heap = heap; + #ifdef WOLF_CRYPTO_CB + sha256->devId = devId; + #endif + + ret = InitSha256(sha256); + if (ret != 0) + return ret; + + /* choose best Transform function under this runtime environment */ + Sha256_SetTransform(); + + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA256) + ret = wolfAsync_DevCtxInit(&sha256->asyncDev, + WOLFSSL_ASYNC_MARKER_SHA256, sha256->heap, devId); + #else + (void)devId; + #endif /* WOLFSSL_ASYNC_CRYPT */ + + return ret; + } + +#elif defined(FREESCALE_LTC_SHA) + int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId) + { + (void)heap; + (void)devId; + + LTC_HASH_Init(LTC_BASE, &sha256->ctx, kLTC_Sha256, NULL, 0); + + return 0; + } + +#elif defined(FREESCALE_MMCAU_SHA) + + #ifdef FREESCALE_MMCAU_CLASSIC_SHA + #include "cau_api.h" + #else + #include "fsl_mmcau.h" + #endif + + #define XTRANSFORM(S) Transform_Sha256((S)) + #define XTRANSFORM_LEN(S, D, L) Transform_Sha256_Len((S),(D),(L)) + + int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId) + { + int ret = 0; + + (void)heap; + (void)devId; + + ret = wolfSSL_CryptHwMutexLock(); + if (ret != 0) { + return ret; + } + #ifdef FREESCALE_MMCAU_CLASSIC_SHA + cau_sha256_initialize_output(sha256->digest); + #else + MMCAU_SHA256_InitializeOutput((uint32_t*)sha256->digest); + #endif + wolfSSL_CryptHwMutexUnLock(); + + sha256->buffLen = 0; + sha256->loLen = 0; + sha256->hiLen = 0; + + return ret; + } + + static int Transform_Sha256(wc_Sha256* sha256) + { + int ret = wolfSSL_CryptHwMutexLock(); + if (ret == 0) { + #ifdef FREESCALE_MMCAU_CLASSIC_SHA + cau_sha256_hash_n((byte*)sha256->buffer, 1, sha256->digest); + #else + MMCAU_SHA256_HashN((byte*)sha256->buffer, 1, sha256->digest); + #endif + wolfSSL_CryptHwMutexUnLock(); + } + return ret; + } + +#elif defined(WOLFSSL_PIC32MZ_HASH) + #include + +#elif defined(STM32_HASH_SHA2) + + /* Supports CubeMX HAL or Standard Peripheral Library */ + + int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId) + { + if (sha256 == NULL) + return BAD_FUNC_ARG; + + (void)devId; + (void)heap; + + wc_Stm32_Hash_Init(&sha256->stmCtx); + return 0; + } + + int wc_Sha256Update(wc_Sha256* sha256, const byte* data, word32 len) + { + int ret = 0; + + if (sha256 == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + + ret = wolfSSL_CryptHwMutexLock(); + if (ret == 0) { + ret = wc_Stm32_Hash_Update(&sha256->stmCtx, + HASH_AlgoSelection_SHA256, data, len); + wolfSSL_CryptHwMutexUnLock(); + } + return ret; + } + + int wc_Sha256Final(wc_Sha256* sha256, byte* hash) + { + int ret = 0; + + if (sha256 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + + ret = wolfSSL_CryptHwMutexLock(); + if (ret == 0) { + ret = wc_Stm32_Hash_Final(&sha256->stmCtx, + HASH_AlgoSelection_SHA256, hash, WC_SHA256_DIGEST_SIZE); + wolfSSL_CryptHwMutexUnLock(); + } + + (void)wc_InitSha256(sha256); /* reset state */ + + return ret; + } + +#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH) + /* functions defined in wolfcrypt/src/port/caam/caam_sha256.c */ + +#elif defined(WOLFSSL_AFALG_HASH) + /* implemented in wolfcrypt/src/port/af_alg/afalg_hash.c */ + +#elif defined(WOLFSSL_DEVCRYPTO_HASH) + /* implemented in wolfcrypt/src/port/devcrypto/devcrypt_hash.c */ + +#elif defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + + #define NEED_SOFT_SHA256 + + static int InitSha256(wc_Sha256* sha256) + { + int ret = 0; + + if (sha256 == NULL) + return BAD_FUNC_ARG; + + XMEMSET(sha256->digest, 0, sizeof(sha256->digest)); + sha256->digest[0] = 0x6A09E667L; + sha256->digest[1] = 0xBB67AE85L; + sha256->digest[2] = 0x3C6EF372L; + sha256->digest[3] = 0xA54FF53AL; + sha256->digest[4] = 0x510E527FL; + sha256->digest[5] = 0x9B05688CL; + sha256->digest[6] = 0x1F83D9ABL; + sha256->digest[7] = 0x5BE0CD19L; + + sha256->buffLen = 0; + sha256->loLen = 0; + sha256->hiLen = 0; + + /* always start firstblock = 1 when using hw engine */ + sha256->ctx.isfirstblock = 1; + sha256->ctx.sha_type = SHA2_256; + if(sha256->ctx.mode == ESP32_SHA_HW) { + /* release hw */ + esp_sha_hw_unlock(); + } + /* always set mode as INIT + * whether using HW or SW is detemined at first call of update() + */ + sha256->ctx.mode = ESP32_SHA_INIT; + + return ret; + } + int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId) + { + int ret = 0; + + if (sha256 == NULL) + return BAD_FUNC_ARG; + + XMEMSET(sha256, 0, sizeof(wc_Sha256)); + sha256->ctx.mode = ESP32_SHA_INIT; + sha256->ctx.isfirstblock = 1; + (void)devId; + + ret = InitSha256(sha256); + + return ret; + } +#else + #define NEED_SOFT_SHA256 + + int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId) + { + int ret = 0; + if (sha256 == NULL) + return BAD_FUNC_ARG; + + sha256->heap = heap; + #ifdef WOLF_CRYPTO_CB + sha256->devId = devId; + sha256->devCtx = NULL; + #endif + + ret = InitSha256(sha256); + if (ret != 0) + return ret; + + #ifdef WOLFSSL_SMALL_STACK_CACHE + sha256->W = NULL; + #endif + + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA256) + ret = wolfAsync_DevCtxInit(&sha256->asyncDev, + WOLFSSL_ASYNC_MARKER_SHA256, sha256->heap, devId); + #else + (void)devId; + #endif /* WOLFSSL_ASYNC_CRYPT */ + + return ret; + } +#endif /* End Hardware Acceleration */ + +#ifdef NEED_SOFT_SHA256 + + static const ALIGN32 word32 K[64] = { + 0x428A2F98L, 0x71374491L, 0xB5C0FBCFL, 0xE9B5DBA5L, 0x3956C25BL, + 0x59F111F1L, 0x923F82A4L, 0xAB1C5ED5L, 0xD807AA98L, 0x12835B01L, + 0x243185BEL, 0x550C7DC3L, 0x72BE5D74L, 0x80DEB1FEL, 0x9BDC06A7L, + 0xC19BF174L, 0xE49B69C1L, 0xEFBE4786L, 0x0FC19DC6L, 0x240CA1CCL, + 0x2DE92C6FL, 0x4A7484AAL, 0x5CB0A9DCL, 0x76F988DAL, 0x983E5152L, + 0xA831C66DL, 0xB00327C8L, 0xBF597FC7L, 0xC6E00BF3L, 0xD5A79147L, + 0x06CA6351L, 0x14292967L, 0x27B70A85L, 0x2E1B2138L, 0x4D2C6DFCL, + 0x53380D13L, 0x650A7354L, 0x766A0ABBL, 0x81C2C92EL, 0x92722C85L, + 0xA2BFE8A1L, 0xA81A664BL, 0xC24B8B70L, 0xC76C51A3L, 0xD192E819L, + 0xD6990624L, 0xF40E3585L, 0x106AA070L, 0x19A4C116L, 0x1E376C08L, + 0x2748774CL, 0x34B0BCB5L, 0x391C0CB3L, 0x4ED8AA4AL, 0x5B9CCA4FL, + 0x682E6FF3L, 0x748F82EEL, 0x78A5636FL, 0x84C87814L, 0x8CC70208L, + 0x90BEFFFAL, 0xA4506CEBL, 0xBEF9A3F7L, 0xC67178F2L + }; + +/* Both versions of Ch and Maj are logically the same, but with the second set + the compilers can recognize them better for optimization */ +#ifdef WOLFSSL_SHA256_BY_SPEC + /* SHA256 math based on specification */ + #define Ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z)))) + #define Maj(x,y,z) ((((x) | (y)) & (z)) | ((x) & (y))) +#else + /* SHA256 math reworked for easier compiler optimization */ + #define Ch(x,y,z) ((((y) ^ (z)) & (x)) ^ (z)) + #define Maj(x,y,z) ((((x) ^ (y)) & ((y) ^ (z))) ^ (y)) +#endif + #define R(x, n) (((x) & 0xFFFFFFFFU) >> (n)) + + #define S(x, n) rotrFixed(x, n) + #define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22)) + #define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25)) + #define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3)) + #define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10)) + + #define a(i) S[(0-i) & 7] + #define b(i) S[(1-i) & 7] + #define c(i) S[(2-i) & 7] + #define d(i) S[(3-i) & 7] + #define e(i) S[(4-i) & 7] + #define f(i) S[(5-i) & 7] + #define g(i) S[(6-i) & 7] + #define h(i) S[(7-i) & 7] + +#ifndef SHA256_MANY_REGISTERS + #define RND(j) \ + t0 = h(j) + Sigma1(e(j)) + Ch(e(j), f(j), g(j)) + K[i+j] + W[i+j]; \ + t1 = Sigma0(a(j)) + Maj(a(j), b(j), c(j)); \ + d(j) += t0; \ + h(j) = t0 + t1 + + #ifndef XTRANSFORM + #define XTRANSFORM(S) Transform_Sha256((S)) + #define XTRANSFORM_LEN(S, D, L) Transform_Sha256_Len((S),(D),(L)) + #endif + + static int Transform_Sha256(wc_Sha256* sha256) + { + word32 S[8], t0, t1; + int i; + + #ifdef WOLFSSL_SMALL_STACK_CACHE + word32* W = sha256->W; + if (W == NULL) { + W = (word32*)XMALLOC(sizeof(word32) * WC_SHA256_BLOCK_SIZE, NULL, + DYNAMIC_TYPE_DIGEST); + if (W == NULL) + return MEMORY_E; + sha256->W = W; + } + #elif defined(WOLFSSL_SMALL_STACK) + word32* W; + W = (word32*)XMALLOC(sizeof(word32) * WC_SHA256_BLOCK_SIZE, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (W == NULL) + return MEMORY_E; + #else + word32 W[WC_SHA256_BLOCK_SIZE]; + #endif + + /* Copy context->state[] to working vars */ + for (i = 0; i < 8; i++) + S[i] = sha256->digest[i]; + + for (i = 0; i < 16; i++) + W[i] = sha256->buffer[i]; + + for (i = 16; i < WC_SHA256_BLOCK_SIZE; i++) + W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15]) + W[i-16]; + + #ifdef USE_SLOW_SHA256 + /* not unrolled - ~2k smaller and ~25% slower */ + for (i = 0; i < WC_SHA256_BLOCK_SIZE; i += 8) { + int j; + for (j = 0; j < 8; j++) { /* braces needed here for macros {} */ + RND(j); + } + } + #else + /* partially loop unrolled */ + for (i = 0; i < WC_SHA256_BLOCK_SIZE; i += 8) { + RND(0); RND(1); RND(2); RND(3); + RND(4); RND(5); RND(6); RND(7); + } + #endif /* USE_SLOW_SHA256 */ + + /* Add the working vars back into digest state[] */ + for (i = 0; i < 8; i++) { + sha256->digest[i] += S[i]; + } + + #if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SMALL_STACK_CACHE) + XFREE(W, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return 0; + } +#else + /* SHA256 version that keeps all data in registers */ + #define SCHED1(j) (W[j] = sha256->buffer[j]) + #define SCHED(j) ( \ + W[ j & 15] += \ + Gamma1(W[(j-2) & 15])+ \ + W[(j-7) & 15] + \ + Gamma0(W[(j-15) & 15]) \ + ) + + #define RND1(j) \ + t0 = h(j) + Sigma1(e(j)) + Ch(e(j), f(j), g(j)) + K[i+j] + SCHED1(j); \ + t1 = Sigma0(a(j)) + Maj(a(j), b(j), c(j)); \ + d(j) += t0; \ + h(j) = t0 + t1 + #define RNDN(j) \ + t0 = h(j) + Sigma1(e(j)) + Ch(e(j), f(j), g(j)) + K[i+j] + SCHED(j); \ + t1 = Sigma0(a(j)) + Maj(a(j), b(j), c(j)); \ + d(j) += t0; \ + h(j) = t0 + t1 + + #ifndef XTRANSFORM + #define XTRANSFORM(S) Transform_Sha256((S)) + #define XTRANSFORM_LEN(S, D, L) Transform_Sha256_Len((S),(D),(L)) + #endif + + static int Transform_Sha256(wc_Sha256* sha256) + { + word32 S[8], t0, t1; + int i; + word32 W[WC_SHA256_BLOCK_SIZE/sizeof(word32)]; + + /* Copy digest to working vars */ + S[0] = sha256->digest[0]; + S[1] = sha256->digest[1]; + S[2] = sha256->digest[2]; + S[3] = sha256->digest[3]; + S[4] = sha256->digest[4]; + S[5] = sha256->digest[5]; + S[6] = sha256->digest[6]; + S[7] = sha256->digest[7]; + + i = 0; + RND1( 0); RND1( 1); RND1( 2); RND1( 3); + RND1( 4); RND1( 5); RND1( 6); RND1( 7); + RND1( 8); RND1( 9); RND1(10); RND1(11); + RND1(12); RND1(13); RND1(14); RND1(15); + /* 64 operations, partially loop unrolled */ + for (i = 16; i < 64; i += 16) { + RNDN( 0); RNDN( 1); RNDN( 2); RNDN( 3); + RNDN( 4); RNDN( 5); RNDN( 6); RNDN( 7); + RNDN( 8); RNDN( 9); RNDN(10); RNDN(11); + RNDN(12); RNDN(13); RNDN(14); RNDN(15); + } + + /* Add the working vars back into digest */ + sha256->digest[0] += S[0]; + sha256->digest[1] += S[1]; + sha256->digest[2] += S[2]; + sha256->digest[3] += S[3]; + sha256->digest[4] += S[4]; + sha256->digest[5] += S[5]; + sha256->digest[6] += S[6]; + sha256->digest[7] += S[7]; + + return 0; + } +#endif /* SHA256_MANY_REGISTERS */ +#endif +/* End wc_ software implementation */ + + +#ifdef XTRANSFORM + + static WC_INLINE void AddLength(wc_Sha256* sha256, word32 len) + { + word32 tmp = sha256->loLen; + if ((sha256->loLen += len) < tmp) + sha256->hiLen++; /* carry low to high */ + } + + static WC_INLINE int Sha256Update(wc_Sha256* sha256, const byte* data, word32 len) + { + int ret = 0; + byte* local; + + if (sha256 == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + + if (data == NULL && len == 0) { + /* valid, but do nothing */ + return 0; + } + + AddLength(sha256, len); + + /* do block size increments */ + local = (byte*)sha256->buffer; + + /* check that internal buffLen is valid */ + if (sha256->buffLen >= WC_SHA256_BLOCK_SIZE) + return BUFFER_E; + + if (sha256->buffLen > 0) { + word32 add = min(len, WC_SHA256_BLOCK_SIZE - sha256->buffLen); + XMEMCPY(&local[sha256->buffLen], data, add); + + sha256->buffLen += add; + data += add; + len -= add; + + if (sha256->buffLen == WC_SHA256_BLOCK_SIZE) { + #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) + #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + if (!IS_INTEL_AVX1(intel_flags) && !IS_INTEL_AVX2(intel_flags)) + #endif + { + ByteReverseWords(sha256->buffer, sha256->buffer, + WC_SHA256_BLOCK_SIZE); + } + #endif + + #if !defined(WOLFSSL_ESP32WROOM32_CRYPT) || \ + defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + ret = XTRANSFORM(sha256); + #else + if(sha256->ctx.mode == ESP32_SHA_INIT) { + esp_sha_try_hw_lock(&sha256->ctx); + } + if(sha256->ctx.mode == ESP32_SHA_SW){ + ret = XTRANSFORM(sha256); + } else { + esp_sha256_process(sha256); + } + #endif + if (ret == 0) + sha256->buffLen = 0; + else + len = 0; + } + } + + #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + if (Transform_Sha256_Len_p != NULL) { + word32 blocksLen = len & ~(WC_SHA256_BLOCK_SIZE-1); + if (blocksLen > 0) { + /* Byte reversal performed in function if required. */ + XTRANSFORM_LEN(sha256, data, blocksLen); + data += blocksLen; + len -= blocksLen; + } + } + else + #endif + #if !defined(LITTLE_ENDIAN_ORDER) || defined(FREESCALE_MMCAU_SHA) || \ + defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + { + while (len >= WC_SHA256_BLOCK_SIZE) { + XMEMCPY(local, data, WC_SHA256_BLOCK_SIZE); + + data += WC_SHA256_BLOCK_SIZE; + len -= WC_SHA256_BLOCK_SIZE; + + #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + if (!IS_INTEL_AVX1(intel_flags) && !IS_INTEL_AVX2(intel_flags)) + { + ByteReverseWords(sha256->buffer, sha256->buffer, + WC_SHA256_BLOCK_SIZE); + } + #endif + ret = XTRANSFORM(sha256); + if (ret != 0) + break; + } + } + #else + { + while (len >= WC_SHA256_BLOCK_SIZE) { + XMEMCPY(local, data, WC_SHA256_BLOCK_SIZE); + + data += WC_SHA256_BLOCK_SIZE; + len -= WC_SHA256_BLOCK_SIZE; + + ByteReverseWords(sha256->buffer, sha256->buffer, + WC_SHA256_BLOCK_SIZE); + #if !defined(WOLFSSL_ESP32WROOM32_CRYPT) || \ + defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + ret = XTRANSFORM(sha256); + #else + if(sha256->ctx.mode == ESP32_SHA_INIT){ + esp_sha_try_hw_lock(&sha256->ctx); + } + + if(sha256->ctx.mode == ESP32_SHA_SW){ + ret = XTRANSFORM(sha256); + } else { + esp_sha256_process(sha256); + } + #endif + if (ret != 0) + break; + } + } + #endif + + if (len > 0) { + XMEMCPY(local, data, len); + sha256->buffLen = len; + } + + return ret; + } + + int wc_Sha256Update(wc_Sha256* sha256, const byte* data, word32 len) + { + if (sha256 == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + + if (data == NULL && len == 0) { + /* valid, but do nothing */ + return 0; + } + + #ifdef WOLF_CRYPTO_CB + if (sha256->devId != INVALID_DEVID) { + int ret = wc_CryptoCb_Sha256Hash(sha256, data, len, NULL); + if (ret != CRYPTOCB_UNAVAILABLE) + return ret; + /* fall-through when unavailable */ + } + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA256) + if (sha256->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA256) { + #if defined(HAVE_INTEL_QA) + return IntelQaSymSha256(&sha256->asyncDev, NULL, data, len); + #endif + } + #endif /* WOLFSSL_ASYNC_CRYPT */ + + return Sha256Update(sha256, data, len); + } + + static WC_INLINE int Sha256Final(wc_Sha256* sha256) + { + + int ret; + byte* local = (byte*)sha256->buffer; + + if (sha256 == NULL) { + return BAD_FUNC_ARG; + } + + local[sha256->buffLen++] = 0x80; /* add 1 */ + + /* pad with zeros */ + if (sha256->buffLen > WC_SHA256_PAD_SIZE) { + XMEMSET(&local[sha256->buffLen], 0, + WC_SHA256_BLOCK_SIZE - sha256->buffLen); + sha256->buffLen += WC_SHA256_BLOCK_SIZE - sha256->buffLen; + + { + #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) + #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + if (!IS_INTEL_AVX1(intel_flags) && !IS_INTEL_AVX2(intel_flags)) + #endif + { + ByteReverseWords(sha256->buffer, sha256->buffer, + WC_SHA256_BLOCK_SIZE); + } + #endif + } + #if !defined(WOLFSSL_ESP32WROOM32_CRYPT) || \ + defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + ret = XTRANSFORM(sha256); + #else + if(sha256->ctx.mode == ESP32_SHA_INIT){ + esp_sha_try_hw_lock(&sha256->ctx); + } + if(sha256->ctx.mode == ESP32_SHA_SW){ + ret = XTRANSFORM(sha256); + } else { + ret = esp_sha256_process(sha256); + } + #endif + if (ret != 0) + return ret; + + sha256->buffLen = 0; + } + XMEMSET(&local[sha256->buffLen], 0, WC_SHA256_PAD_SIZE - sha256->buffLen); + + /* put lengths in bits */ + sha256->hiLen = (sha256->loLen >> (8 * sizeof(sha256->loLen) - 3)) + + (sha256->hiLen << 3); + sha256->loLen = sha256->loLen << 3; + + /* store lengths */ + #if defined(LITTLE_ENDIAN_ORDER) && !defined(FREESCALE_MMCAU_SHA) + #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + if (!IS_INTEL_AVX1(intel_flags) && !IS_INTEL_AVX2(intel_flags)) + #endif + { + ByteReverseWords(sha256->buffer, sha256->buffer, + WC_SHA256_BLOCK_SIZE); + } + #endif + /* ! length ordering dependent on digest endian type ! */ + XMEMCPY(&local[WC_SHA256_PAD_SIZE], &sha256->hiLen, sizeof(word32)); + XMEMCPY(&local[WC_SHA256_PAD_SIZE + sizeof(word32)], &sha256->loLen, + sizeof(word32)); + + #if defined(FREESCALE_MMCAU_SHA) || defined(HAVE_INTEL_AVX1) || \ + defined(HAVE_INTEL_AVX2) + /* Kinetis requires only these bytes reversed */ + #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + if (IS_INTEL_AVX1(intel_flags) || IS_INTEL_AVX2(intel_flags)) + #endif + { + ByteReverseWords( + &sha256->buffer[WC_SHA256_PAD_SIZE / sizeof(word32)], + &sha256->buffer[WC_SHA256_PAD_SIZE / sizeof(word32)], + 2 * sizeof(word32)); + } + #endif + + #if !defined(WOLFSSL_ESP32WROOM32_CRYPT) || \ + defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + return XTRANSFORM(sha256); + #else + if(sha256->ctx.mode == ESP32_SHA_INIT){ + esp_sha_try_hw_lock(&sha256->ctx); + } + if(sha256->ctx.mode == ESP32_SHA_SW){ + return XTRANSFORM(sha256); + } else { + ret = esp_sha256_digest_process(sha256, 1); + } + return ret; + #endif + } + + int wc_Sha256FinalRaw(wc_Sha256* sha256, byte* hash) + { + #ifdef LITTLE_ENDIAN_ORDER + word32 digest[WC_SHA256_DIGEST_SIZE / sizeof(word32)]; + #endif + + if (sha256 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + + #ifdef LITTLE_ENDIAN_ORDER + ByteReverseWords((word32*)digest, (word32*)sha256->digest, + WC_SHA256_DIGEST_SIZE); + XMEMCPY(hash, digest, WC_SHA256_DIGEST_SIZE); + #else + XMEMCPY(hash, sha256->digest, WC_SHA256_DIGEST_SIZE); + #endif + + return 0; + } + + int wc_Sha256Final(wc_Sha256* sha256, byte* hash) + { + int ret; + + if (sha256 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + + #ifdef WOLF_CRYPTO_CB + if (sha256->devId != INVALID_DEVID) { + ret = wc_CryptoCb_Sha256Hash(sha256, NULL, 0, hash); + if (ret != CRYPTOCB_UNAVAILABLE) + return ret; + /* fall-through when unavailable */ + } + #endif + + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA256) + if (sha256->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA256) { + #if defined(HAVE_INTEL_QA) + return IntelQaSymSha256(&sha256->asyncDev, hash, NULL, + WC_SHA256_DIGEST_SIZE); + #endif + } + #endif /* WOLFSSL_ASYNC_CRYPT */ + + ret = Sha256Final(sha256); + if (ret != 0) + return ret; + + #if defined(LITTLE_ENDIAN_ORDER) + ByteReverseWords(sha256->digest, sha256->digest, WC_SHA256_DIGEST_SIZE); + #endif + XMEMCPY(hash, sha256->digest, WC_SHA256_DIGEST_SIZE); + + return InitSha256(sha256); /* reset state */ + } + +#endif /* XTRANSFORM */ + +#ifdef WOLFSSL_SHA224 + +#ifdef STM32_HASH_SHA2 + + /* Supports CubeMX HAL or Standard Peripheral Library */ + + int wc_InitSha224_ex(wc_Sha224* sha224, void* heap, int devId) + { + if (sha224 == NULL) + return BAD_FUNC_ARG; + + (void)devId; + (void)heap; + + wc_Stm32_Hash_Init(&sha224->stmCtx); + return 0; + } + + int wc_Sha224Update(wc_Sha224* sha224, const byte* data, word32 len) + { + int ret = 0; + + if (sha224 == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + + ret = wolfSSL_CryptHwMutexLock(); + if (ret == 0) { + ret = wc_Stm32_Hash_Update(&sha224->stmCtx, + HASH_AlgoSelection_SHA224, data, len); + wolfSSL_CryptHwMutexUnLock(); + } + return ret; + } + + int wc_Sha224Final(wc_Sha224* sha224, byte* hash) + { + int ret = 0; + + if (sha224 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + + ret = wolfSSL_CryptHwMutexLock(); + if (ret == 0) { + ret = wc_Stm32_Hash_Final(&sha224->stmCtx, + HASH_AlgoSelection_SHA224, hash, WC_SHA224_DIGEST_SIZE); + wolfSSL_CryptHwMutexUnLock(); + } + + (void)wc_InitSha224(sha224); /* reset state */ + + return ret; + } + +#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH) + /* functions defined in wolfcrypt/src/port/caam/caam_sha256.c */ + +#elif defined(WOLFSSL_AFALG_HASH) + #error SHA224 currently not supported with AF_ALG enabled + +#elif defined(WOLFSSL_DEVCRYPTO_HASH) + /* implemented in wolfcrypt/src/port/devcrypto/devcrypt_hash.c */ + +#else + + #define NEED_SOFT_SHA224 + + + static int InitSha224(wc_Sha224* sha224) + { + int ret = 0; + + if (sha224 == NULL) { + return BAD_FUNC_ARG; + } + + sha224->digest[0] = 0xc1059ed8; + sha224->digest[1] = 0x367cd507; + sha224->digest[2] = 0x3070dd17; + sha224->digest[3] = 0xf70e5939; + sha224->digest[4] = 0xffc00b31; + sha224->digest[5] = 0x68581511; + sha224->digest[6] = 0x64f98fa7; + sha224->digest[7] = 0xbefa4fa4; + + sha224->buffLen = 0; + sha224->loLen = 0; + sha224->hiLen = 0; + + #if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) + /* choose best Transform function under this runtime environment */ + Sha256_SetTransform(); + #endif + + return ret; + } + +#endif + +#ifdef NEED_SOFT_SHA224 + int wc_InitSha224_ex(wc_Sha224* sha224, void* heap, int devId) + { + int ret = 0; + + if (sha224 == NULL) + return BAD_FUNC_ARG; + + sha224->heap = heap; + + ret = InitSha224(sha224); + if (ret != 0) + return ret; + + #ifdef WOLFSSL_SMALL_STACK_CACHE + sha224->W = NULL; + #endif + + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA224) + ret = wolfAsync_DevCtxInit(&sha224->asyncDev, + WOLFSSL_ASYNC_MARKER_SHA224, sha224->heap, devId); + #else + (void)devId; + #endif /* WOLFSSL_ASYNC_CRYPT */ + + return ret; + } + + int wc_Sha224Update(wc_Sha224* sha224, const byte* data, word32 len) + { + int ret; + + if (sha224 == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA224) + if (sha224->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA224) { + #if defined(HAVE_INTEL_QA) + return IntelQaSymSha224(&sha224->asyncDev, NULL, data, len); + #endif + } + #endif /* WOLFSSL_ASYNC_CRYPT */ + + ret = Sha256Update((wc_Sha256*)sha224, data, len); + + return ret; + } + + int wc_Sha224Final(wc_Sha224* sha224, byte* hash) + { + int ret; + + if (sha224 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA224) + if (sha224->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA224) { + #if defined(HAVE_INTEL_QA) + return IntelQaSymSha224(&sha224->asyncDev, hash, NULL, + WC_SHA224_DIGEST_SIZE); + #endif + } + #endif /* WOLFSSL_ASYNC_CRYPT */ + + ret = Sha256Final((wc_Sha256*)sha224); + if (ret != 0) + return ret; + + #if defined(LITTLE_ENDIAN_ORDER) + ByteReverseWords(sha224->digest, sha224->digest, WC_SHA224_DIGEST_SIZE); + #endif + XMEMCPY(hash, sha224->digest, WC_SHA224_DIGEST_SIZE); + + return InitSha224(sha224); /* reset state */ + } +#endif /* end of SHA224 software implementation */ + + int wc_InitSha224(wc_Sha224* sha224) + { + return wc_InitSha224_ex(sha224, NULL, INVALID_DEVID); + } + + void wc_Sha224Free(wc_Sha224* sha224) + { + if (sha224 == NULL) + return; + +#ifdef WOLFSSL_SMALL_STACK_CACHE + if (sha224->W != NULL) { + XFREE(sha224->W, NULL, DYNAMIC_TYPE_DIGEST); + sha224->W = NULL; + } +#endif + + #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA224) + wolfAsync_DevCtxFree(&sha224->asyncDev, WOLFSSL_ASYNC_MARKER_SHA224); + #endif /* WOLFSSL_ASYNC_CRYPT */ + + #ifdef WOLFSSL_PIC32MZ_HASH + wc_Sha256Pic32Free(sha224); + #endif + } +#endif /* WOLFSSL_SHA224 */ + + +int wc_InitSha256(wc_Sha256* sha256) +{ + return wc_InitSha256_ex(sha256, NULL, INVALID_DEVID); +} + +void wc_Sha256Free(wc_Sha256* sha256) +{ + if (sha256 == NULL) + return; + +#ifdef WOLFSSL_SMALL_STACK_CACHE + if (sha256->W != NULL) { + XFREE(sha256->W, NULL, DYNAMIC_TYPE_DIGEST); + sha256->W = NULL; + } +#endif + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA256) + wolfAsync_DevCtxFree(&sha256->asyncDev, WOLFSSL_ASYNC_MARKER_SHA256); +#endif /* WOLFSSL_ASYNC_CRYPT */ +#ifdef WOLFSSL_PIC32MZ_HASH + wc_Sha256Pic32Free(sha256); +#endif +#if defined(WOLFSSL_AFALG_HASH) + if (sha256->alFd > 0) { + close(sha256->alFd); + sha256->alFd = -1; /* avoid possible double close on socket */ + } + if (sha256->rdFd > 0) { + close(sha256->rdFd); + sha256->rdFd = -1; /* avoid possible double close on socket */ + } +#endif /* WOLFSSL_AFALG_HASH */ +#ifdef WOLFSSL_DEVCRYPTO_HASH + wc_DevCryptoFree(&sha256->ctx); +#endif /* WOLFSSL_DEVCRYPTO */ +#if (defined(WOLFSSL_AFALG_HASH) && defined(WOLFSSL_AFALG_HASH_KEEP)) || \ + (defined(WOLFSSL_DEVCRYPTO_HASH) && defined(WOLFSSL_DEVCRYPTO_HASH_KEEP)) + if (sha256->msg != NULL) { + XFREE(sha256->msg, sha256->heap, DYNAMIC_TYPE_TMP_BUFFER); + sha256->msg = NULL; + } +#endif +} + +#endif /* !WOLFSSL_TI_HASH */ +#endif /* HAVE_FIPS */ + + +#ifndef WOLFSSL_TI_HASH +#ifdef WOLFSSL_SHA224 + int wc_Sha224GetHash(wc_Sha224* sha224, byte* hash) + { + int ret; + wc_Sha224 tmpSha224; + + if (sha224 == NULL || hash == NULL) + return BAD_FUNC_ARG; + + ret = wc_Sha224Copy(sha224, &tmpSha224); + if (ret == 0) { + ret = wc_Sha224Final(&tmpSha224, hash); + wc_Sha224Free(&tmpSha224); + } + return ret; + } + int wc_Sha224Copy(wc_Sha224* src, wc_Sha224* dst) + { + int ret = 0; + + if (src == NULL || dst == NULL) + return BAD_FUNC_ARG; + + XMEMCPY(dst, src, sizeof(wc_Sha224)); + #ifdef WOLFSSL_SMALL_STACK_CACHE + dst->W = NULL; + #endif + + #ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev); + #endif + #if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + dst->flags |= WC_HASH_FLAG_ISCOPY; + #endif + + return ret; + } + +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + int wc_Sha224SetFlags(wc_Sha224* sha224, word32 flags) + { + if (sha224) { + sha224->flags = flags; + } + return 0; + } + int wc_Sha224GetFlags(wc_Sha224* sha224, word32* flags) + { + if (sha224 && flags) { + *flags = sha224->flags; + } + return 0; + } +#endif + +#endif /* WOLFSSL_SHA224 */ + +#ifdef WOLFSSL_AFALG_HASH + /* implemented in wolfcrypt/src/port/af_alg/afalg_hash.c */ + +#elif defined(WOLFSSL_DEVCRYPTO_HASH) + /* implemented in wolfcrypt/src/port/devcrypto/devcrypt_hash.c */ + +#else + +int wc_Sha256GetHash(wc_Sha256* sha256, byte* hash) +{ + int ret; + wc_Sha256 tmpSha256; + + if (sha256 == NULL || hash == NULL) + return BAD_FUNC_ARG; + +#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + if(sha256->ctx.mode == ESP32_SHA_INIT){ + esp_sha_try_hw_lock(&sha256->ctx); + } + if(sha256->ctx.mode == ESP32_SHA_HW) + { + esp_sha256_digest_process(sha256, 0); + } +#endif + ret = wc_Sha256Copy(sha256, &tmpSha256); + if (ret == 0) { + ret = wc_Sha256Final(&tmpSha256, hash); +#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + sha256->ctx.mode = ESP32_SHA_SW; +#endif + wc_Sha256Free(&tmpSha256); + } + return ret; +} +int wc_Sha256Copy(wc_Sha256* src, wc_Sha256* dst) +{ + int ret = 0; + + if (src == NULL || dst == NULL) + return BAD_FUNC_ARG; + + XMEMCPY(dst, src, sizeof(wc_Sha256)); +#ifdef WOLFSSL_SMALL_STACK_CACHE + dst->W = NULL; +#endif + +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev); +#endif +#ifdef WOLFSSL_PIC32MZ_HASH + ret = wc_Pic32HashCopy(&src->cache, &dst->cache); +#endif +#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + dst->ctx.mode = src->ctx.mode; + dst->ctx.isfirstblock = src->ctx.isfirstblock; + dst->ctx.sha_type = src->ctx.sha_type; +#endif +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + dst->flags |= WC_HASH_FLAG_ISCOPY; +#endif + + return ret; +} + +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) +int wc_Sha256SetFlags(wc_Sha256* sha256, word32 flags) +{ + if (sha256) { + sha256->flags = flags; + } + return 0; +} +int wc_Sha256GetFlags(wc_Sha256* sha256, word32* flags) +{ + if (sha256 && flags) { + *flags = sha256->flags; + } + return 0; +} +#endif + +#endif +#endif /* !WOLFSSL_TI_HASH */ + +#endif /* NO_SHA256 */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/sha256_asm.S b/beken_os/beken378/func/wolfssl/wolfcrypt/src/sha256_asm.S new file mode 100755 index 0000000..ac34e36 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/sha256_asm.S @@ -0,0 +1,22653 @@ +/* sha256_asm + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#ifndef HAVE_INTEL_AVX1 +#define HAVE_INTEL_AVX1 +#endif /* HAVE_INTEL_AVX1 */ +#ifndef HAVE_INTEL_AVX2 +#define HAVE_INTEL_AVX2 +#endif /* HAVE_INTEL_AVX2 */ + +#ifdef HAVE_INTEL_AVX1 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +L_avx1_sha256_k: +.long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5 +.long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5 +.long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3 +.long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174 +.long 0xe49b69c1,0xefbe4786,0xfc19dc6,0x240ca1cc +.long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da +.long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7 +.long 0xc6e00bf3,0xd5a79147,0x6ca6351,0x14292967 +.long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13 +.long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85 +.long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3 +.long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070 +.long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5 +.long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3 +.long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208 +.long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx1_sha256_shuf_00BA: +.quad 0xb0a090803020100, 0xffffffffffffffff +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx1_sha256_shuf_DC00: +.quad 0xffffffffffffffff, 0xb0a090803020100 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx1_sha256_flip_mask: +.quad 0x405060700010203, 0xc0d0e0f08090a0b +#ifndef __APPLE__ +.text +.globl Transform_Sha256_AVX1 +.type Transform_Sha256_AVX1,@function +.align 4 +Transform_Sha256_AVX1: +#else +.section __TEXT,__text +.globl _Transform_Sha256_AVX1 +.p2align 2 +_Transform_Sha256_AVX1: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + subq $0x40, %rsp + leaq 32(%rdi), %rax + vmovdqa L_avx1_sha256_flip_mask(%rip), %xmm13 + vmovdqa L_avx1_sha256_shuf_00BA(%rip), %xmm11 + vmovdqa L_avx1_sha256_shuf_DC00(%rip), %xmm12 + movl (%rdi), %r8d + movl 4(%rdi), %r9d + movl 8(%rdi), %r10d + movl 12(%rdi), %r11d + movl 16(%rdi), %r12d + movl 20(%rdi), %r13d + movl 24(%rdi), %r14d + movl 28(%rdi), %r15d + # X0, X1, X2, X3 = W[0..15] + vmovdqu (%rax), %xmm0 + vmovdqu 16(%rax), %xmm1 + vpshufb %xmm13, %xmm0, %xmm0 + vpshufb %xmm13, %xmm1, %xmm1 + vmovdqu 32(%rax), %xmm2 + vmovdqu 48(%rax), %xmm3 + vpshufb %xmm13, %xmm2, %xmm2 + vpshufb %xmm13, %xmm3, %xmm3 + movl %r9d, %ebx + movl %r12d, %edx + xorl %r10d, %ebx + # set_w_k_xfer_4: 0 + vpaddd 0+L_avx1_sha256_k(%rip), %xmm0, %xmm4 + vpaddd 16+L_avx1_sha256_k(%rip), %xmm1, %xmm5 + vmovdqu %xmm4, (%rsp) + vmovdqu %xmm5, 16(%rsp) + vpaddd 32+L_avx1_sha256_k(%rip), %xmm2, %xmm6 + vpaddd 48+L_avx1_sha256_k(%rip), %xmm3, %xmm7 + vmovdqu %xmm6, 32(%rsp) + vmovdqu %xmm7, 48(%rsp) + # msg_sched: 0-3 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %xmm0, %xmm1, %xmm5 + vpalignr $4, %xmm2, %xmm3, %xmm4 + # rnd_0: 1 - 2 + movl %r9d, %eax + movl %r13d, %ecx + addl (%rsp), %r15d + xorl %r14d, %ecx + xorl %r12d, %edx + andl %r12d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r14d, %ecx + xorl %r12d, %edx + addl %ecx, %r15d + rorl $6, %edx + xorl %r8d, %eax + addl %edx, %r15d + movl %r8d, %ecx + vpsrld $18, %xmm5, %xmm8 + vpslld $14, %xmm5, %xmm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + vpor %xmm6, %xmm7, %xmm6 + vpor %xmm8, %xmm9, %xmm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r8d, %ebx + movl %r12d, %ecx + addl 4(%rsp), %r14d + xorl %r13d, %ecx + vpsrld $3, %xmm5, %xmm9 + vpxor %xmm6, %xmm8, %xmm6 + # rnd_1: 2 - 3 + xorl %r11d, %edx + andl %r11d, %ecx + rorl $5, %edx + xorl %r13d, %ecx + xorl %r11d, %edx + addl %ecx, %r14d + vpxor %xmm6, %xmm9, %xmm5 + vpshufd $0xfa, %xmm3, %xmm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r15d, %ebx + addl %edx, %r14d + movl %r15d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r15d, %ecx + xorl %r8d, %eax + vpsrld $10, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm0, %xmm4, %xmm4 + # rnd_0: 1 - 3 + movl %r15d, %eax + movl %r11d, %ecx + addl 8(%rsp), %r13d + xorl %r12d, %ecx + xorl %r10d, %edx + andl %r10d, %ecx + rorl $5, %edx + xorl %r12d, %ecx + xorl %r10d, %edx + addl %ecx, %r13d + vpxor %xmm6, %xmm7, %xmm6 + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r14d, %eax + addl %edx, %r13d + movl %r14d, %ecx + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r14d, %ecx + xorl %r15d, %ebx + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + movl %r14d, %ebx + movl %r10d, %ecx + addl 12(%rsp), %r12d + xorl %r11d, %ecx + vpsrlq $0x11, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 2 - 3 + xorl %r9d, %edx + andl %r9d, %ecx + rorl $5, %edx + xorl %r11d, %ecx + xorl %r9d, %edx + addl %ecx, %r12d + vpsrld $10, %xmm6, %xmm9 + vpxor %xmm8, %xmm7, %xmm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r13d, %ebx + addl %edx, %r12d + movl %r13d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r13d, %ecx + xorl %r14d, %eax + vpxor %xmm9, %xmm8, %xmm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + vpaddd %xmm4, %xmm9, %xmm0 + # msg_sched done: 0-3 + # msg_sched: 4-7 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %xmm1, %xmm2, %xmm5 + vpalignr $4, %xmm3, %xmm0, %xmm4 + # rnd_0: 1 - 2 + movl %r13d, %eax + movl %r9d, %ecx + addl 16(%rsp), %r11d + xorl %r10d, %ecx + xorl %r8d, %edx + andl %r8d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r10d, %ecx + xorl %r8d, %edx + addl %ecx, %r11d + rorl $6, %edx + xorl %r12d, %eax + addl %edx, %r11d + movl %r12d, %ecx + vpsrld $18, %xmm5, %xmm8 + vpslld $14, %xmm5, %xmm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + vpor %xmm6, %xmm7, %xmm6 + vpor %xmm8, %xmm9, %xmm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r12d, %ebx + movl %r8d, %ecx + addl 20(%rsp), %r10d + xorl %r9d, %ecx + vpsrld $3, %xmm5, %xmm9 + vpxor %xmm6, %xmm8, %xmm6 + # rnd_1: 2 - 3 + xorl %r15d, %edx + andl %r15d, %ecx + rorl $5, %edx + xorl %r9d, %ecx + xorl %r15d, %edx + addl %ecx, %r10d + vpxor %xmm6, %xmm9, %xmm5 + vpshufd $0xfa, %xmm0, %xmm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r11d, %ebx + addl %edx, %r10d + movl %r11d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r11d, %ecx + xorl %r12d, %eax + vpsrld $10, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm1, %xmm4, %xmm4 + # rnd_0: 1 - 3 + movl %r11d, %eax + movl %r15d, %ecx + addl 24(%rsp), %r9d + xorl %r8d, %ecx + xorl %r14d, %edx + andl %r14d, %ecx + rorl $5, %edx + xorl %r8d, %ecx + xorl %r14d, %edx + addl %ecx, %r9d + vpxor %xmm6, %xmm7, %xmm6 + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r10d, %eax + addl %edx, %r9d + movl %r10d, %ecx + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r10d, %ecx + xorl %r11d, %ebx + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + movl %r10d, %ebx + movl %r14d, %ecx + addl 28(%rsp), %r8d + xorl %r15d, %ecx + vpsrlq $0x11, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 2 - 3 + xorl %r13d, %edx + andl %r13d, %ecx + rorl $5, %edx + xorl %r15d, %ecx + xorl %r13d, %edx + addl %ecx, %r8d + vpsrld $10, %xmm6, %xmm9 + vpxor %xmm8, %xmm7, %xmm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r9d, %ebx + addl %edx, %r8d + movl %r9d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r9d, %ecx + xorl %r10d, %eax + vpxor %xmm9, %xmm8, %xmm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + vpaddd %xmm4, %xmm9, %xmm1 + # msg_sched done: 4-7 + # msg_sched: 8-11 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %xmm2, %xmm3, %xmm5 + vpalignr $4, %xmm0, %xmm1, %xmm4 + # rnd_0: 1 - 2 + movl %r9d, %eax + movl %r13d, %ecx + addl 32(%rsp), %r15d + xorl %r14d, %ecx + xorl %r12d, %edx + andl %r12d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r14d, %ecx + xorl %r12d, %edx + addl %ecx, %r15d + rorl $6, %edx + xorl %r8d, %eax + addl %edx, %r15d + movl %r8d, %ecx + vpsrld $18, %xmm5, %xmm8 + vpslld $14, %xmm5, %xmm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + vpor %xmm6, %xmm7, %xmm6 + vpor %xmm8, %xmm9, %xmm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r8d, %ebx + movl %r12d, %ecx + addl 36(%rsp), %r14d + xorl %r13d, %ecx + vpsrld $3, %xmm5, %xmm9 + vpxor %xmm6, %xmm8, %xmm6 + # rnd_1: 2 - 3 + xorl %r11d, %edx + andl %r11d, %ecx + rorl $5, %edx + xorl %r13d, %ecx + xorl %r11d, %edx + addl %ecx, %r14d + vpxor %xmm6, %xmm9, %xmm5 + vpshufd $0xfa, %xmm1, %xmm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r15d, %ebx + addl %edx, %r14d + movl %r15d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r15d, %ecx + xorl %r8d, %eax + vpsrld $10, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm2, %xmm4, %xmm4 + # rnd_0: 1 - 3 + movl %r15d, %eax + movl %r11d, %ecx + addl 40(%rsp), %r13d + xorl %r12d, %ecx + xorl %r10d, %edx + andl %r10d, %ecx + rorl $5, %edx + xorl %r12d, %ecx + xorl %r10d, %edx + addl %ecx, %r13d + vpxor %xmm6, %xmm7, %xmm6 + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r14d, %eax + addl %edx, %r13d + movl %r14d, %ecx + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r14d, %ecx + xorl %r15d, %ebx + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + movl %r14d, %ebx + movl %r10d, %ecx + addl 44(%rsp), %r12d + xorl %r11d, %ecx + vpsrlq $0x11, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 2 - 3 + xorl %r9d, %edx + andl %r9d, %ecx + rorl $5, %edx + xorl %r11d, %ecx + xorl %r9d, %edx + addl %ecx, %r12d + vpsrld $10, %xmm6, %xmm9 + vpxor %xmm8, %xmm7, %xmm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r13d, %ebx + addl %edx, %r12d + movl %r13d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r13d, %ecx + xorl %r14d, %eax + vpxor %xmm9, %xmm8, %xmm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + vpaddd %xmm4, %xmm9, %xmm2 + # msg_sched done: 8-11 + # msg_sched: 12-15 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %xmm3, %xmm0, %xmm5 + vpalignr $4, %xmm1, %xmm2, %xmm4 + # rnd_0: 1 - 2 + movl %r13d, %eax + movl %r9d, %ecx + addl 48(%rsp), %r11d + xorl %r10d, %ecx + xorl %r8d, %edx + andl %r8d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r10d, %ecx + xorl %r8d, %edx + addl %ecx, %r11d + rorl $6, %edx + xorl %r12d, %eax + addl %edx, %r11d + movl %r12d, %ecx + vpsrld $18, %xmm5, %xmm8 + vpslld $14, %xmm5, %xmm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + vpor %xmm6, %xmm7, %xmm6 + vpor %xmm8, %xmm9, %xmm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r12d, %ebx + movl %r8d, %ecx + addl 52(%rsp), %r10d + xorl %r9d, %ecx + vpsrld $3, %xmm5, %xmm9 + vpxor %xmm6, %xmm8, %xmm6 + # rnd_1: 2 - 3 + xorl %r15d, %edx + andl %r15d, %ecx + rorl $5, %edx + xorl %r9d, %ecx + xorl %r15d, %edx + addl %ecx, %r10d + vpxor %xmm6, %xmm9, %xmm5 + vpshufd $0xfa, %xmm2, %xmm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r11d, %ebx + addl %edx, %r10d + movl %r11d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r11d, %ecx + xorl %r12d, %eax + vpsrld $10, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm3, %xmm4, %xmm4 + # rnd_0: 1 - 3 + movl %r11d, %eax + movl %r15d, %ecx + addl 56(%rsp), %r9d + xorl %r8d, %ecx + xorl %r14d, %edx + andl %r14d, %ecx + rorl $5, %edx + xorl %r8d, %ecx + xorl %r14d, %edx + addl %ecx, %r9d + vpxor %xmm6, %xmm7, %xmm6 + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r10d, %eax + addl %edx, %r9d + movl %r10d, %ecx + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r10d, %ecx + xorl %r11d, %ebx + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + movl %r10d, %ebx + movl %r14d, %ecx + addl 60(%rsp), %r8d + xorl %r15d, %ecx + vpsrlq $0x11, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 2 - 3 + xorl %r13d, %edx + andl %r13d, %ecx + rorl $5, %edx + xorl %r15d, %ecx + xorl %r13d, %edx + addl %ecx, %r8d + vpsrld $10, %xmm6, %xmm9 + vpxor %xmm8, %xmm7, %xmm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r9d, %ebx + addl %edx, %r8d + movl %r9d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r9d, %ecx + xorl %r10d, %eax + vpxor %xmm9, %xmm8, %xmm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + vpaddd %xmm4, %xmm9, %xmm3 + # msg_sched done: 12-15 + # set_w_k_xfer_4: 4 + vpaddd 64+L_avx1_sha256_k(%rip), %xmm0, %xmm4 + vpaddd 80+L_avx1_sha256_k(%rip), %xmm1, %xmm5 + vmovdqu %xmm4, (%rsp) + vmovdqu %xmm5, 16(%rsp) + vpaddd 96+L_avx1_sha256_k(%rip), %xmm2, %xmm6 + vpaddd 112+L_avx1_sha256_k(%rip), %xmm3, %xmm7 + vmovdqu %xmm6, 32(%rsp) + vmovdqu %xmm7, 48(%rsp) + # msg_sched: 0-3 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %xmm0, %xmm1, %xmm5 + vpalignr $4, %xmm2, %xmm3, %xmm4 + # rnd_0: 1 - 2 + movl %r9d, %eax + movl %r13d, %ecx + addl (%rsp), %r15d + xorl %r14d, %ecx + xorl %r12d, %edx + andl %r12d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r14d, %ecx + xorl %r12d, %edx + addl %ecx, %r15d + rorl $6, %edx + xorl %r8d, %eax + addl %edx, %r15d + movl %r8d, %ecx + vpsrld $18, %xmm5, %xmm8 + vpslld $14, %xmm5, %xmm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + vpor %xmm6, %xmm7, %xmm6 + vpor %xmm8, %xmm9, %xmm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r8d, %ebx + movl %r12d, %ecx + addl 4(%rsp), %r14d + xorl %r13d, %ecx + vpsrld $3, %xmm5, %xmm9 + vpxor %xmm6, %xmm8, %xmm6 + # rnd_1: 2 - 3 + xorl %r11d, %edx + andl %r11d, %ecx + rorl $5, %edx + xorl %r13d, %ecx + xorl %r11d, %edx + addl %ecx, %r14d + vpxor %xmm6, %xmm9, %xmm5 + vpshufd $0xfa, %xmm3, %xmm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r15d, %ebx + addl %edx, %r14d + movl %r15d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r15d, %ecx + xorl %r8d, %eax + vpsrld $10, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm0, %xmm4, %xmm4 + # rnd_0: 1 - 3 + movl %r15d, %eax + movl %r11d, %ecx + addl 8(%rsp), %r13d + xorl %r12d, %ecx + xorl %r10d, %edx + andl %r10d, %ecx + rorl $5, %edx + xorl %r12d, %ecx + xorl %r10d, %edx + addl %ecx, %r13d + vpxor %xmm6, %xmm7, %xmm6 + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r14d, %eax + addl %edx, %r13d + movl %r14d, %ecx + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r14d, %ecx + xorl %r15d, %ebx + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + movl %r14d, %ebx + movl %r10d, %ecx + addl 12(%rsp), %r12d + xorl %r11d, %ecx + vpsrlq $0x11, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 2 - 3 + xorl %r9d, %edx + andl %r9d, %ecx + rorl $5, %edx + xorl %r11d, %ecx + xorl %r9d, %edx + addl %ecx, %r12d + vpsrld $10, %xmm6, %xmm9 + vpxor %xmm8, %xmm7, %xmm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r13d, %ebx + addl %edx, %r12d + movl %r13d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r13d, %ecx + xorl %r14d, %eax + vpxor %xmm9, %xmm8, %xmm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + vpaddd %xmm4, %xmm9, %xmm0 + # msg_sched done: 0-3 + # msg_sched: 4-7 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %xmm1, %xmm2, %xmm5 + vpalignr $4, %xmm3, %xmm0, %xmm4 + # rnd_0: 1 - 2 + movl %r13d, %eax + movl %r9d, %ecx + addl 16(%rsp), %r11d + xorl %r10d, %ecx + xorl %r8d, %edx + andl %r8d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r10d, %ecx + xorl %r8d, %edx + addl %ecx, %r11d + rorl $6, %edx + xorl %r12d, %eax + addl %edx, %r11d + movl %r12d, %ecx + vpsrld $18, %xmm5, %xmm8 + vpslld $14, %xmm5, %xmm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + vpor %xmm6, %xmm7, %xmm6 + vpor %xmm8, %xmm9, %xmm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r12d, %ebx + movl %r8d, %ecx + addl 20(%rsp), %r10d + xorl %r9d, %ecx + vpsrld $3, %xmm5, %xmm9 + vpxor %xmm6, %xmm8, %xmm6 + # rnd_1: 2 - 3 + xorl %r15d, %edx + andl %r15d, %ecx + rorl $5, %edx + xorl %r9d, %ecx + xorl %r15d, %edx + addl %ecx, %r10d + vpxor %xmm6, %xmm9, %xmm5 + vpshufd $0xfa, %xmm0, %xmm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r11d, %ebx + addl %edx, %r10d + movl %r11d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r11d, %ecx + xorl %r12d, %eax + vpsrld $10, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm1, %xmm4, %xmm4 + # rnd_0: 1 - 3 + movl %r11d, %eax + movl %r15d, %ecx + addl 24(%rsp), %r9d + xorl %r8d, %ecx + xorl %r14d, %edx + andl %r14d, %ecx + rorl $5, %edx + xorl %r8d, %ecx + xorl %r14d, %edx + addl %ecx, %r9d + vpxor %xmm6, %xmm7, %xmm6 + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r10d, %eax + addl %edx, %r9d + movl %r10d, %ecx + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r10d, %ecx + xorl %r11d, %ebx + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + movl %r10d, %ebx + movl %r14d, %ecx + addl 28(%rsp), %r8d + xorl %r15d, %ecx + vpsrlq $0x11, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 2 - 3 + xorl %r13d, %edx + andl %r13d, %ecx + rorl $5, %edx + xorl %r15d, %ecx + xorl %r13d, %edx + addl %ecx, %r8d + vpsrld $10, %xmm6, %xmm9 + vpxor %xmm8, %xmm7, %xmm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r9d, %ebx + addl %edx, %r8d + movl %r9d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r9d, %ecx + xorl %r10d, %eax + vpxor %xmm9, %xmm8, %xmm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + vpaddd %xmm4, %xmm9, %xmm1 + # msg_sched done: 4-7 + # msg_sched: 8-11 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %xmm2, %xmm3, %xmm5 + vpalignr $4, %xmm0, %xmm1, %xmm4 + # rnd_0: 1 - 2 + movl %r9d, %eax + movl %r13d, %ecx + addl 32(%rsp), %r15d + xorl %r14d, %ecx + xorl %r12d, %edx + andl %r12d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r14d, %ecx + xorl %r12d, %edx + addl %ecx, %r15d + rorl $6, %edx + xorl %r8d, %eax + addl %edx, %r15d + movl %r8d, %ecx + vpsrld $18, %xmm5, %xmm8 + vpslld $14, %xmm5, %xmm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + vpor %xmm6, %xmm7, %xmm6 + vpor %xmm8, %xmm9, %xmm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r8d, %ebx + movl %r12d, %ecx + addl 36(%rsp), %r14d + xorl %r13d, %ecx + vpsrld $3, %xmm5, %xmm9 + vpxor %xmm6, %xmm8, %xmm6 + # rnd_1: 2 - 3 + xorl %r11d, %edx + andl %r11d, %ecx + rorl $5, %edx + xorl %r13d, %ecx + xorl %r11d, %edx + addl %ecx, %r14d + vpxor %xmm6, %xmm9, %xmm5 + vpshufd $0xfa, %xmm1, %xmm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r15d, %ebx + addl %edx, %r14d + movl %r15d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r15d, %ecx + xorl %r8d, %eax + vpsrld $10, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm2, %xmm4, %xmm4 + # rnd_0: 1 - 3 + movl %r15d, %eax + movl %r11d, %ecx + addl 40(%rsp), %r13d + xorl %r12d, %ecx + xorl %r10d, %edx + andl %r10d, %ecx + rorl $5, %edx + xorl %r12d, %ecx + xorl %r10d, %edx + addl %ecx, %r13d + vpxor %xmm6, %xmm7, %xmm6 + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r14d, %eax + addl %edx, %r13d + movl %r14d, %ecx + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r14d, %ecx + xorl %r15d, %ebx + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + movl %r14d, %ebx + movl %r10d, %ecx + addl 44(%rsp), %r12d + xorl %r11d, %ecx + vpsrlq $0x11, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 2 - 3 + xorl %r9d, %edx + andl %r9d, %ecx + rorl $5, %edx + xorl %r11d, %ecx + xorl %r9d, %edx + addl %ecx, %r12d + vpsrld $10, %xmm6, %xmm9 + vpxor %xmm8, %xmm7, %xmm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r13d, %ebx + addl %edx, %r12d + movl %r13d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r13d, %ecx + xorl %r14d, %eax + vpxor %xmm9, %xmm8, %xmm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + vpaddd %xmm4, %xmm9, %xmm2 + # msg_sched done: 8-11 + # msg_sched: 12-15 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %xmm3, %xmm0, %xmm5 + vpalignr $4, %xmm1, %xmm2, %xmm4 + # rnd_0: 1 - 2 + movl %r13d, %eax + movl %r9d, %ecx + addl 48(%rsp), %r11d + xorl %r10d, %ecx + xorl %r8d, %edx + andl %r8d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r10d, %ecx + xorl %r8d, %edx + addl %ecx, %r11d + rorl $6, %edx + xorl %r12d, %eax + addl %edx, %r11d + movl %r12d, %ecx + vpsrld $18, %xmm5, %xmm8 + vpslld $14, %xmm5, %xmm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + vpor %xmm6, %xmm7, %xmm6 + vpor %xmm8, %xmm9, %xmm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r12d, %ebx + movl %r8d, %ecx + addl 52(%rsp), %r10d + xorl %r9d, %ecx + vpsrld $3, %xmm5, %xmm9 + vpxor %xmm6, %xmm8, %xmm6 + # rnd_1: 2 - 3 + xorl %r15d, %edx + andl %r15d, %ecx + rorl $5, %edx + xorl %r9d, %ecx + xorl %r15d, %edx + addl %ecx, %r10d + vpxor %xmm6, %xmm9, %xmm5 + vpshufd $0xfa, %xmm2, %xmm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r11d, %ebx + addl %edx, %r10d + movl %r11d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r11d, %ecx + xorl %r12d, %eax + vpsrld $10, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm3, %xmm4, %xmm4 + # rnd_0: 1 - 3 + movl %r11d, %eax + movl %r15d, %ecx + addl 56(%rsp), %r9d + xorl %r8d, %ecx + xorl %r14d, %edx + andl %r14d, %ecx + rorl $5, %edx + xorl %r8d, %ecx + xorl %r14d, %edx + addl %ecx, %r9d + vpxor %xmm6, %xmm7, %xmm6 + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r10d, %eax + addl %edx, %r9d + movl %r10d, %ecx + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r10d, %ecx + xorl %r11d, %ebx + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + movl %r10d, %ebx + movl %r14d, %ecx + addl 60(%rsp), %r8d + xorl %r15d, %ecx + vpsrlq $0x11, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 2 - 3 + xorl %r13d, %edx + andl %r13d, %ecx + rorl $5, %edx + xorl %r15d, %ecx + xorl %r13d, %edx + addl %ecx, %r8d + vpsrld $10, %xmm6, %xmm9 + vpxor %xmm8, %xmm7, %xmm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r9d, %ebx + addl %edx, %r8d + movl %r9d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r9d, %ecx + xorl %r10d, %eax + vpxor %xmm9, %xmm8, %xmm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + vpaddd %xmm4, %xmm9, %xmm3 + # msg_sched done: 12-15 + # set_w_k_xfer_4: 8 + vpaddd 128+L_avx1_sha256_k(%rip), %xmm0, %xmm4 + vpaddd 144+L_avx1_sha256_k(%rip), %xmm1, %xmm5 + vmovdqu %xmm4, (%rsp) + vmovdqu %xmm5, 16(%rsp) + vpaddd 160+L_avx1_sha256_k(%rip), %xmm2, %xmm6 + vpaddd 176+L_avx1_sha256_k(%rip), %xmm3, %xmm7 + vmovdqu %xmm6, 32(%rsp) + vmovdqu %xmm7, 48(%rsp) + # msg_sched: 0-3 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %xmm0, %xmm1, %xmm5 + vpalignr $4, %xmm2, %xmm3, %xmm4 + # rnd_0: 1 - 2 + movl %r9d, %eax + movl %r13d, %ecx + addl (%rsp), %r15d + xorl %r14d, %ecx + xorl %r12d, %edx + andl %r12d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r14d, %ecx + xorl %r12d, %edx + addl %ecx, %r15d + rorl $6, %edx + xorl %r8d, %eax + addl %edx, %r15d + movl %r8d, %ecx + vpsrld $18, %xmm5, %xmm8 + vpslld $14, %xmm5, %xmm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + vpor %xmm6, %xmm7, %xmm6 + vpor %xmm8, %xmm9, %xmm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r8d, %ebx + movl %r12d, %ecx + addl 4(%rsp), %r14d + xorl %r13d, %ecx + vpsrld $3, %xmm5, %xmm9 + vpxor %xmm6, %xmm8, %xmm6 + # rnd_1: 2 - 3 + xorl %r11d, %edx + andl %r11d, %ecx + rorl $5, %edx + xorl %r13d, %ecx + xorl %r11d, %edx + addl %ecx, %r14d + vpxor %xmm6, %xmm9, %xmm5 + vpshufd $0xfa, %xmm3, %xmm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r15d, %ebx + addl %edx, %r14d + movl %r15d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r15d, %ecx + xorl %r8d, %eax + vpsrld $10, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm0, %xmm4, %xmm4 + # rnd_0: 1 - 3 + movl %r15d, %eax + movl %r11d, %ecx + addl 8(%rsp), %r13d + xorl %r12d, %ecx + xorl %r10d, %edx + andl %r10d, %ecx + rorl $5, %edx + xorl %r12d, %ecx + xorl %r10d, %edx + addl %ecx, %r13d + vpxor %xmm6, %xmm7, %xmm6 + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r14d, %eax + addl %edx, %r13d + movl %r14d, %ecx + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r14d, %ecx + xorl %r15d, %ebx + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + movl %r14d, %ebx + movl %r10d, %ecx + addl 12(%rsp), %r12d + xorl %r11d, %ecx + vpsrlq $0x11, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 2 - 3 + xorl %r9d, %edx + andl %r9d, %ecx + rorl $5, %edx + xorl %r11d, %ecx + xorl %r9d, %edx + addl %ecx, %r12d + vpsrld $10, %xmm6, %xmm9 + vpxor %xmm8, %xmm7, %xmm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r13d, %ebx + addl %edx, %r12d + movl %r13d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r13d, %ecx + xorl %r14d, %eax + vpxor %xmm9, %xmm8, %xmm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + vpaddd %xmm4, %xmm9, %xmm0 + # msg_sched done: 0-3 + # msg_sched: 4-7 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %xmm1, %xmm2, %xmm5 + vpalignr $4, %xmm3, %xmm0, %xmm4 + # rnd_0: 1 - 2 + movl %r13d, %eax + movl %r9d, %ecx + addl 16(%rsp), %r11d + xorl %r10d, %ecx + xorl %r8d, %edx + andl %r8d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r10d, %ecx + xorl %r8d, %edx + addl %ecx, %r11d + rorl $6, %edx + xorl %r12d, %eax + addl %edx, %r11d + movl %r12d, %ecx + vpsrld $18, %xmm5, %xmm8 + vpslld $14, %xmm5, %xmm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + vpor %xmm6, %xmm7, %xmm6 + vpor %xmm8, %xmm9, %xmm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r12d, %ebx + movl %r8d, %ecx + addl 20(%rsp), %r10d + xorl %r9d, %ecx + vpsrld $3, %xmm5, %xmm9 + vpxor %xmm6, %xmm8, %xmm6 + # rnd_1: 2 - 3 + xorl %r15d, %edx + andl %r15d, %ecx + rorl $5, %edx + xorl %r9d, %ecx + xorl %r15d, %edx + addl %ecx, %r10d + vpxor %xmm6, %xmm9, %xmm5 + vpshufd $0xfa, %xmm0, %xmm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r11d, %ebx + addl %edx, %r10d + movl %r11d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r11d, %ecx + xorl %r12d, %eax + vpsrld $10, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm1, %xmm4, %xmm4 + # rnd_0: 1 - 3 + movl %r11d, %eax + movl %r15d, %ecx + addl 24(%rsp), %r9d + xorl %r8d, %ecx + xorl %r14d, %edx + andl %r14d, %ecx + rorl $5, %edx + xorl %r8d, %ecx + xorl %r14d, %edx + addl %ecx, %r9d + vpxor %xmm6, %xmm7, %xmm6 + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r10d, %eax + addl %edx, %r9d + movl %r10d, %ecx + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r10d, %ecx + xorl %r11d, %ebx + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + movl %r10d, %ebx + movl %r14d, %ecx + addl 28(%rsp), %r8d + xorl %r15d, %ecx + vpsrlq $0x11, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 2 - 3 + xorl %r13d, %edx + andl %r13d, %ecx + rorl $5, %edx + xorl %r15d, %ecx + xorl %r13d, %edx + addl %ecx, %r8d + vpsrld $10, %xmm6, %xmm9 + vpxor %xmm8, %xmm7, %xmm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r9d, %ebx + addl %edx, %r8d + movl %r9d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r9d, %ecx + xorl %r10d, %eax + vpxor %xmm9, %xmm8, %xmm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + vpaddd %xmm4, %xmm9, %xmm1 + # msg_sched done: 4-7 + # msg_sched: 8-11 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %xmm2, %xmm3, %xmm5 + vpalignr $4, %xmm0, %xmm1, %xmm4 + # rnd_0: 1 - 2 + movl %r9d, %eax + movl %r13d, %ecx + addl 32(%rsp), %r15d + xorl %r14d, %ecx + xorl %r12d, %edx + andl %r12d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r14d, %ecx + xorl %r12d, %edx + addl %ecx, %r15d + rorl $6, %edx + xorl %r8d, %eax + addl %edx, %r15d + movl %r8d, %ecx + vpsrld $18, %xmm5, %xmm8 + vpslld $14, %xmm5, %xmm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + vpor %xmm6, %xmm7, %xmm6 + vpor %xmm8, %xmm9, %xmm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r8d, %ebx + movl %r12d, %ecx + addl 36(%rsp), %r14d + xorl %r13d, %ecx + vpsrld $3, %xmm5, %xmm9 + vpxor %xmm6, %xmm8, %xmm6 + # rnd_1: 2 - 3 + xorl %r11d, %edx + andl %r11d, %ecx + rorl $5, %edx + xorl %r13d, %ecx + xorl %r11d, %edx + addl %ecx, %r14d + vpxor %xmm6, %xmm9, %xmm5 + vpshufd $0xfa, %xmm1, %xmm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r15d, %ebx + addl %edx, %r14d + movl %r15d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r15d, %ecx + xorl %r8d, %eax + vpsrld $10, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm2, %xmm4, %xmm4 + # rnd_0: 1 - 3 + movl %r15d, %eax + movl %r11d, %ecx + addl 40(%rsp), %r13d + xorl %r12d, %ecx + xorl %r10d, %edx + andl %r10d, %ecx + rorl $5, %edx + xorl %r12d, %ecx + xorl %r10d, %edx + addl %ecx, %r13d + vpxor %xmm6, %xmm7, %xmm6 + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r14d, %eax + addl %edx, %r13d + movl %r14d, %ecx + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r14d, %ecx + xorl %r15d, %ebx + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + movl %r14d, %ebx + movl %r10d, %ecx + addl 44(%rsp), %r12d + xorl %r11d, %ecx + vpsrlq $0x11, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 2 - 3 + xorl %r9d, %edx + andl %r9d, %ecx + rorl $5, %edx + xorl %r11d, %ecx + xorl %r9d, %edx + addl %ecx, %r12d + vpsrld $10, %xmm6, %xmm9 + vpxor %xmm8, %xmm7, %xmm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r13d, %ebx + addl %edx, %r12d + movl %r13d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r13d, %ecx + xorl %r14d, %eax + vpxor %xmm9, %xmm8, %xmm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + vpaddd %xmm4, %xmm9, %xmm2 + # msg_sched done: 8-11 + # msg_sched: 12-15 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %xmm3, %xmm0, %xmm5 + vpalignr $4, %xmm1, %xmm2, %xmm4 + # rnd_0: 1 - 2 + movl %r13d, %eax + movl %r9d, %ecx + addl 48(%rsp), %r11d + xorl %r10d, %ecx + xorl %r8d, %edx + andl %r8d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r10d, %ecx + xorl %r8d, %edx + addl %ecx, %r11d + rorl $6, %edx + xorl %r12d, %eax + addl %edx, %r11d + movl %r12d, %ecx + vpsrld $18, %xmm5, %xmm8 + vpslld $14, %xmm5, %xmm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + vpor %xmm6, %xmm7, %xmm6 + vpor %xmm8, %xmm9, %xmm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r12d, %ebx + movl %r8d, %ecx + addl 52(%rsp), %r10d + xorl %r9d, %ecx + vpsrld $3, %xmm5, %xmm9 + vpxor %xmm6, %xmm8, %xmm6 + # rnd_1: 2 - 3 + xorl %r15d, %edx + andl %r15d, %ecx + rorl $5, %edx + xorl %r9d, %ecx + xorl %r15d, %edx + addl %ecx, %r10d + vpxor %xmm6, %xmm9, %xmm5 + vpshufd $0xfa, %xmm2, %xmm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r11d, %ebx + addl %edx, %r10d + movl %r11d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r11d, %ecx + xorl %r12d, %eax + vpsrld $10, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm3, %xmm4, %xmm4 + # rnd_0: 1 - 3 + movl %r11d, %eax + movl %r15d, %ecx + addl 56(%rsp), %r9d + xorl %r8d, %ecx + xorl %r14d, %edx + andl %r14d, %ecx + rorl $5, %edx + xorl %r8d, %ecx + xorl %r14d, %edx + addl %ecx, %r9d + vpxor %xmm6, %xmm7, %xmm6 + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r10d, %eax + addl %edx, %r9d + movl %r10d, %ecx + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r10d, %ecx + xorl %r11d, %ebx + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + movl %r10d, %ebx + movl %r14d, %ecx + addl 60(%rsp), %r8d + xorl %r15d, %ecx + vpsrlq $0x11, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 2 - 3 + xorl %r13d, %edx + andl %r13d, %ecx + rorl $5, %edx + xorl %r15d, %ecx + xorl %r13d, %edx + addl %ecx, %r8d + vpsrld $10, %xmm6, %xmm9 + vpxor %xmm8, %xmm7, %xmm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r9d, %ebx + addl %edx, %r8d + movl %r9d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r9d, %ecx + xorl %r10d, %eax + vpxor %xmm9, %xmm8, %xmm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + vpaddd %xmm4, %xmm9, %xmm3 + # msg_sched done: 12-15 + # set_w_k_xfer_4: 12 + vpaddd 192+L_avx1_sha256_k(%rip), %xmm0, %xmm4 + vpaddd 208+L_avx1_sha256_k(%rip), %xmm1, %xmm5 + vmovdqu %xmm4, (%rsp) + vmovdqu %xmm5, 16(%rsp) + vpaddd 224+L_avx1_sha256_k(%rip), %xmm2, %xmm6 + vpaddd 240+L_avx1_sha256_k(%rip), %xmm3, %xmm7 + vmovdqu %xmm6, 32(%rsp) + vmovdqu %xmm7, 48(%rsp) + # rnd_all_4: 0-3 + addl (%rsp), %r15d + movl %r13d, %ecx + movl %r9d, %eax + xorl %r14d, %ecx + rorl $14, %edx + andl %r12d, %ecx + xorl %r12d, %edx + xorl %r14d, %ecx + rorl $5, %edx + addl %ecx, %r15d + xorl %r12d, %edx + xorl %r8d, %eax + rorl $6, %edx + movl %r8d, %ecx + addl %edx, %r15d + rorl $9, %ecx + andl %eax, %ebx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + addl 4(%rsp), %r14d + movl %r12d, %ecx + movl %r8d, %ebx + xorl %r13d, %ecx + rorl $14, %edx + andl %r11d, %ecx + xorl %r11d, %edx + xorl %r13d, %ecx + rorl $5, %edx + addl %ecx, %r14d + xorl %r11d, %edx + xorl %r15d, %ebx + rorl $6, %edx + movl %r15d, %ecx + addl %edx, %r14d + rorl $9, %ecx + andl %ebx, %eax + xorl %r15d, %ecx + xorl %r8d, %eax + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + addl 8(%rsp), %r13d + movl %r11d, %ecx + movl %r15d, %eax + xorl %r12d, %ecx + rorl $14, %edx + andl %r10d, %ecx + xorl %r10d, %edx + xorl %r12d, %ecx + rorl $5, %edx + addl %ecx, %r13d + xorl %r10d, %edx + xorl %r14d, %eax + rorl $6, %edx + movl %r14d, %ecx + addl %edx, %r13d + rorl $9, %ecx + andl %eax, %ebx + xorl %r14d, %ecx + xorl %r15d, %ebx + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + addl 12(%rsp), %r12d + movl %r10d, %ecx + movl %r14d, %ebx + xorl %r11d, %ecx + rorl $14, %edx + andl %r9d, %ecx + xorl %r9d, %edx + xorl %r11d, %ecx + rorl $5, %edx + addl %ecx, %r12d + xorl %r9d, %edx + xorl %r13d, %ebx + rorl $6, %edx + movl %r13d, %ecx + addl %edx, %r12d + rorl $9, %ecx + andl %ebx, %eax + xorl %r13d, %ecx + xorl %r14d, %eax + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + # rnd_all_4: 1-4 + addl 16(%rsp), %r11d + movl %r9d, %ecx + movl %r13d, %eax + xorl %r10d, %ecx + rorl $14, %edx + andl %r8d, %ecx + xorl %r8d, %edx + xorl %r10d, %ecx + rorl $5, %edx + addl %ecx, %r11d + xorl %r8d, %edx + xorl %r12d, %eax + rorl $6, %edx + movl %r12d, %ecx + addl %edx, %r11d + rorl $9, %ecx + andl %eax, %ebx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + addl 20(%rsp), %r10d + movl %r8d, %ecx + movl %r12d, %ebx + xorl %r9d, %ecx + rorl $14, %edx + andl %r15d, %ecx + xorl %r15d, %edx + xorl %r9d, %ecx + rorl $5, %edx + addl %ecx, %r10d + xorl %r15d, %edx + xorl %r11d, %ebx + rorl $6, %edx + movl %r11d, %ecx + addl %edx, %r10d + rorl $9, %ecx + andl %ebx, %eax + xorl %r11d, %ecx + xorl %r12d, %eax + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + addl 24(%rsp), %r9d + movl %r15d, %ecx + movl %r11d, %eax + xorl %r8d, %ecx + rorl $14, %edx + andl %r14d, %ecx + xorl %r14d, %edx + xorl %r8d, %ecx + rorl $5, %edx + addl %ecx, %r9d + xorl %r14d, %edx + xorl %r10d, %eax + rorl $6, %edx + movl %r10d, %ecx + addl %edx, %r9d + rorl $9, %ecx + andl %eax, %ebx + xorl %r10d, %ecx + xorl %r11d, %ebx + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + addl 28(%rsp), %r8d + movl %r14d, %ecx + movl %r10d, %ebx + xorl %r15d, %ecx + rorl $14, %edx + andl %r13d, %ecx + xorl %r13d, %edx + xorl %r15d, %ecx + rorl $5, %edx + addl %ecx, %r8d + xorl %r13d, %edx + xorl %r9d, %ebx + rorl $6, %edx + movl %r9d, %ecx + addl %edx, %r8d + rorl $9, %ecx + andl %ebx, %eax + xorl %r9d, %ecx + xorl %r10d, %eax + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + # rnd_all_4: 2-5 + addl 32(%rsp), %r15d + movl %r13d, %ecx + movl %r9d, %eax + xorl %r14d, %ecx + rorl $14, %edx + andl %r12d, %ecx + xorl %r12d, %edx + xorl %r14d, %ecx + rorl $5, %edx + addl %ecx, %r15d + xorl %r12d, %edx + xorl %r8d, %eax + rorl $6, %edx + movl %r8d, %ecx + addl %edx, %r15d + rorl $9, %ecx + andl %eax, %ebx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + addl 36(%rsp), %r14d + movl %r12d, %ecx + movl %r8d, %ebx + xorl %r13d, %ecx + rorl $14, %edx + andl %r11d, %ecx + xorl %r11d, %edx + xorl %r13d, %ecx + rorl $5, %edx + addl %ecx, %r14d + xorl %r11d, %edx + xorl %r15d, %ebx + rorl $6, %edx + movl %r15d, %ecx + addl %edx, %r14d + rorl $9, %ecx + andl %ebx, %eax + xorl %r15d, %ecx + xorl %r8d, %eax + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + addl 40(%rsp), %r13d + movl %r11d, %ecx + movl %r15d, %eax + xorl %r12d, %ecx + rorl $14, %edx + andl %r10d, %ecx + xorl %r10d, %edx + xorl %r12d, %ecx + rorl $5, %edx + addl %ecx, %r13d + xorl %r10d, %edx + xorl %r14d, %eax + rorl $6, %edx + movl %r14d, %ecx + addl %edx, %r13d + rorl $9, %ecx + andl %eax, %ebx + xorl %r14d, %ecx + xorl %r15d, %ebx + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + addl 44(%rsp), %r12d + movl %r10d, %ecx + movl %r14d, %ebx + xorl %r11d, %ecx + rorl $14, %edx + andl %r9d, %ecx + xorl %r9d, %edx + xorl %r11d, %ecx + rorl $5, %edx + addl %ecx, %r12d + xorl %r9d, %edx + xorl %r13d, %ebx + rorl $6, %edx + movl %r13d, %ecx + addl %edx, %r12d + rorl $9, %ecx + andl %ebx, %eax + xorl %r13d, %ecx + xorl %r14d, %eax + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + # rnd_all_4: 3-6 + addl 48(%rsp), %r11d + movl %r9d, %ecx + movl %r13d, %eax + xorl %r10d, %ecx + rorl $14, %edx + andl %r8d, %ecx + xorl %r8d, %edx + xorl %r10d, %ecx + rorl $5, %edx + addl %ecx, %r11d + xorl %r8d, %edx + xorl %r12d, %eax + rorl $6, %edx + movl %r12d, %ecx + addl %edx, %r11d + rorl $9, %ecx + andl %eax, %ebx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + addl 52(%rsp), %r10d + movl %r8d, %ecx + movl %r12d, %ebx + xorl %r9d, %ecx + rorl $14, %edx + andl %r15d, %ecx + xorl %r15d, %edx + xorl %r9d, %ecx + rorl $5, %edx + addl %ecx, %r10d + xorl %r15d, %edx + xorl %r11d, %ebx + rorl $6, %edx + movl %r11d, %ecx + addl %edx, %r10d + rorl $9, %ecx + andl %ebx, %eax + xorl %r11d, %ecx + xorl %r12d, %eax + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + addl 56(%rsp), %r9d + movl %r15d, %ecx + movl %r11d, %eax + xorl %r8d, %ecx + rorl $14, %edx + andl %r14d, %ecx + xorl %r14d, %edx + xorl %r8d, %ecx + rorl $5, %edx + addl %ecx, %r9d + xorl %r14d, %edx + xorl %r10d, %eax + rorl $6, %edx + movl %r10d, %ecx + addl %edx, %r9d + rorl $9, %ecx + andl %eax, %ebx + xorl %r10d, %ecx + xorl %r11d, %ebx + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + addl 60(%rsp), %r8d + movl %r14d, %ecx + movl %r10d, %ebx + xorl %r15d, %ecx + rorl $14, %edx + andl %r13d, %ecx + xorl %r13d, %edx + xorl %r15d, %ecx + rorl $5, %edx + addl %ecx, %r8d + xorl %r13d, %edx + xorl %r9d, %ebx + rorl $6, %edx + movl %r9d, %ecx + addl %edx, %r8d + rorl $9, %ecx + andl %ebx, %eax + xorl %r9d, %ecx + xorl %r10d, %eax + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + addl %r8d, (%rdi) + addl %r9d, 4(%rdi) + addl %r10d, 8(%rdi) + addl %r11d, 12(%rdi) + addl %r12d, 16(%rdi) + addl %r13d, 20(%rdi) + addl %r14d, 24(%rdi) + addl %r15d, 28(%rdi) + xorq %rax, %rax + vzeroupper + addq $0x40, %rsp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size Transform_Sha256_AVX1,.-Transform_Sha256_AVX1 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl Transform_Sha256_AVX1_Len +.type Transform_Sha256_AVX1_Len,@function +.align 4 +Transform_Sha256_AVX1_Len: +#else +.section __TEXT,__text +.globl _Transform_Sha256_AVX1_Len +.p2align 2 +_Transform_Sha256_AVX1_Len: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + pushq %rbp + movq %rsi, %rbp + movq %rdx, %rsi + subq $0x40, %rsp + vmovdqa L_avx1_sha256_flip_mask(%rip), %xmm13 + vmovdqa L_avx1_sha256_shuf_00BA(%rip), %xmm11 + vmovdqa L_avx1_sha256_shuf_DC00(%rip), %xmm12 + movl (%rdi), %r8d + movl 4(%rdi), %r9d + movl 8(%rdi), %r10d + movl 12(%rdi), %r11d + movl 16(%rdi), %r12d + movl 20(%rdi), %r13d + movl 24(%rdi), %r14d + movl 28(%rdi), %r15d + # Start of loop processing a block +L_sha256_len_avx1_start: + # X0, X1, X2, X3 = W[0..15] + vmovdqu (%rbp), %xmm0 + vmovdqu 16(%rbp), %xmm1 + vpshufb %xmm13, %xmm0, %xmm0 + vpshufb %xmm13, %xmm1, %xmm1 + vmovdqu 32(%rbp), %xmm2 + vmovdqu 48(%rbp), %xmm3 + vpshufb %xmm13, %xmm2, %xmm2 + vpshufb %xmm13, %xmm3, %xmm3 + movl %r9d, %ebx + movl %r12d, %edx + xorl %r10d, %ebx + # set_w_k_xfer_4: 0 + vpaddd 0+L_avx1_sha256_k(%rip), %xmm0, %xmm4 + vpaddd 16+L_avx1_sha256_k(%rip), %xmm1, %xmm5 + vmovdqu %xmm4, (%rsp) + vmovdqu %xmm5, 16(%rsp) + vpaddd 32+L_avx1_sha256_k(%rip), %xmm2, %xmm6 + vpaddd 48+L_avx1_sha256_k(%rip), %xmm3, %xmm7 + vmovdqu %xmm6, 32(%rsp) + vmovdqu %xmm7, 48(%rsp) + # msg_sched: 0-3 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %xmm0, %xmm1, %xmm5 + vpalignr $4, %xmm2, %xmm3, %xmm4 + # rnd_0: 1 - 2 + movl %r9d, %eax + movl %r13d, %ecx + addl (%rsp), %r15d + xorl %r14d, %ecx + xorl %r12d, %edx + andl %r12d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r14d, %ecx + xorl %r12d, %edx + addl %ecx, %r15d + rorl $6, %edx + xorl %r8d, %eax + addl %edx, %r15d + movl %r8d, %ecx + vpsrld $18, %xmm5, %xmm8 + vpslld $14, %xmm5, %xmm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + vpor %xmm6, %xmm7, %xmm6 + vpor %xmm8, %xmm9, %xmm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r8d, %ebx + movl %r12d, %ecx + addl 4(%rsp), %r14d + xorl %r13d, %ecx + vpsrld $3, %xmm5, %xmm9 + vpxor %xmm6, %xmm8, %xmm6 + # rnd_1: 2 - 3 + xorl %r11d, %edx + andl %r11d, %ecx + rorl $5, %edx + xorl %r13d, %ecx + xorl %r11d, %edx + addl %ecx, %r14d + vpxor %xmm6, %xmm9, %xmm5 + vpshufd $0xfa, %xmm3, %xmm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r15d, %ebx + addl %edx, %r14d + movl %r15d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r15d, %ecx + xorl %r8d, %eax + vpsrld $10, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm0, %xmm4, %xmm4 + # rnd_0: 1 - 3 + movl %r15d, %eax + movl %r11d, %ecx + addl 8(%rsp), %r13d + xorl %r12d, %ecx + xorl %r10d, %edx + andl %r10d, %ecx + rorl $5, %edx + xorl %r12d, %ecx + xorl %r10d, %edx + addl %ecx, %r13d + vpxor %xmm6, %xmm7, %xmm6 + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r14d, %eax + addl %edx, %r13d + movl %r14d, %ecx + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r14d, %ecx + xorl %r15d, %ebx + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + movl %r14d, %ebx + movl %r10d, %ecx + addl 12(%rsp), %r12d + xorl %r11d, %ecx + vpsrlq $0x11, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 2 - 3 + xorl %r9d, %edx + andl %r9d, %ecx + rorl $5, %edx + xorl %r11d, %ecx + xorl %r9d, %edx + addl %ecx, %r12d + vpsrld $10, %xmm6, %xmm9 + vpxor %xmm8, %xmm7, %xmm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r13d, %ebx + addl %edx, %r12d + movl %r13d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r13d, %ecx + xorl %r14d, %eax + vpxor %xmm9, %xmm8, %xmm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + vpaddd %xmm4, %xmm9, %xmm0 + # msg_sched done: 0-3 + # msg_sched: 4-7 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %xmm1, %xmm2, %xmm5 + vpalignr $4, %xmm3, %xmm0, %xmm4 + # rnd_0: 1 - 2 + movl %r13d, %eax + movl %r9d, %ecx + addl 16(%rsp), %r11d + xorl %r10d, %ecx + xorl %r8d, %edx + andl %r8d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r10d, %ecx + xorl %r8d, %edx + addl %ecx, %r11d + rorl $6, %edx + xorl %r12d, %eax + addl %edx, %r11d + movl %r12d, %ecx + vpsrld $18, %xmm5, %xmm8 + vpslld $14, %xmm5, %xmm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + vpor %xmm6, %xmm7, %xmm6 + vpor %xmm8, %xmm9, %xmm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r12d, %ebx + movl %r8d, %ecx + addl 20(%rsp), %r10d + xorl %r9d, %ecx + vpsrld $3, %xmm5, %xmm9 + vpxor %xmm6, %xmm8, %xmm6 + # rnd_1: 2 - 3 + xorl %r15d, %edx + andl %r15d, %ecx + rorl $5, %edx + xorl %r9d, %ecx + xorl %r15d, %edx + addl %ecx, %r10d + vpxor %xmm6, %xmm9, %xmm5 + vpshufd $0xfa, %xmm0, %xmm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r11d, %ebx + addl %edx, %r10d + movl %r11d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r11d, %ecx + xorl %r12d, %eax + vpsrld $10, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm1, %xmm4, %xmm4 + # rnd_0: 1 - 3 + movl %r11d, %eax + movl %r15d, %ecx + addl 24(%rsp), %r9d + xorl %r8d, %ecx + xorl %r14d, %edx + andl %r14d, %ecx + rorl $5, %edx + xorl %r8d, %ecx + xorl %r14d, %edx + addl %ecx, %r9d + vpxor %xmm6, %xmm7, %xmm6 + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r10d, %eax + addl %edx, %r9d + movl %r10d, %ecx + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r10d, %ecx + xorl %r11d, %ebx + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + movl %r10d, %ebx + movl %r14d, %ecx + addl 28(%rsp), %r8d + xorl %r15d, %ecx + vpsrlq $0x11, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 2 - 3 + xorl %r13d, %edx + andl %r13d, %ecx + rorl $5, %edx + xorl %r15d, %ecx + xorl %r13d, %edx + addl %ecx, %r8d + vpsrld $10, %xmm6, %xmm9 + vpxor %xmm8, %xmm7, %xmm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r9d, %ebx + addl %edx, %r8d + movl %r9d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r9d, %ecx + xorl %r10d, %eax + vpxor %xmm9, %xmm8, %xmm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + vpaddd %xmm4, %xmm9, %xmm1 + # msg_sched done: 4-7 + # msg_sched: 8-11 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %xmm2, %xmm3, %xmm5 + vpalignr $4, %xmm0, %xmm1, %xmm4 + # rnd_0: 1 - 2 + movl %r9d, %eax + movl %r13d, %ecx + addl 32(%rsp), %r15d + xorl %r14d, %ecx + xorl %r12d, %edx + andl %r12d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r14d, %ecx + xorl %r12d, %edx + addl %ecx, %r15d + rorl $6, %edx + xorl %r8d, %eax + addl %edx, %r15d + movl %r8d, %ecx + vpsrld $18, %xmm5, %xmm8 + vpslld $14, %xmm5, %xmm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + vpor %xmm6, %xmm7, %xmm6 + vpor %xmm8, %xmm9, %xmm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r8d, %ebx + movl %r12d, %ecx + addl 36(%rsp), %r14d + xorl %r13d, %ecx + vpsrld $3, %xmm5, %xmm9 + vpxor %xmm6, %xmm8, %xmm6 + # rnd_1: 2 - 3 + xorl %r11d, %edx + andl %r11d, %ecx + rorl $5, %edx + xorl %r13d, %ecx + xorl %r11d, %edx + addl %ecx, %r14d + vpxor %xmm6, %xmm9, %xmm5 + vpshufd $0xfa, %xmm1, %xmm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r15d, %ebx + addl %edx, %r14d + movl %r15d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r15d, %ecx + xorl %r8d, %eax + vpsrld $10, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm2, %xmm4, %xmm4 + # rnd_0: 1 - 3 + movl %r15d, %eax + movl %r11d, %ecx + addl 40(%rsp), %r13d + xorl %r12d, %ecx + xorl %r10d, %edx + andl %r10d, %ecx + rorl $5, %edx + xorl %r12d, %ecx + xorl %r10d, %edx + addl %ecx, %r13d + vpxor %xmm6, %xmm7, %xmm6 + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r14d, %eax + addl %edx, %r13d + movl %r14d, %ecx + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r14d, %ecx + xorl %r15d, %ebx + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + movl %r14d, %ebx + movl %r10d, %ecx + addl 44(%rsp), %r12d + xorl %r11d, %ecx + vpsrlq $0x11, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 2 - 3 + xorl %r9d, %edx + andl %r9d, %ecx + rorl $5, %edx + xorl %r11d, %ecx + xorl %r9d, %edx + addl %ecx, %r12d + vpsrld $10, %xmm6, %xmm9 + vpxor %xmm8, %xmm7, %xmm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r13d, %ebx + addl %edx, %r12d + movl %r13d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r13d, %ecx + xorl %r14d, %eax + vpxor %xmm9, %xmm8, %xmm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + vpaddd %xmm4, %xmm9, %xmm2 + # msg_sched done: 8-11 + # msg_sched: 12-15 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %xmm3, %xmm0, %xmm5 + vpalignr $4, %xmm1, %xmm2, %xmm4 + # rnd_0: 1 - 2 + movl %r13d, %eax + movl %r9d, %ecx + addl 48(%rsp), %r11d + xorl %r10d, %ecx + xorl %r8d, %edx + andl %r8d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r10d, %ecx + xorl %r8d, %edx + addl %ecx, %r11d + rorl $6, %edx + xorl %r12d, %eax + addl %edx, %r11d + movl %r12d, %ecx + vpsrld $18, %xmm5, %xmm8 + vpslld $14, %xmm5, %xmm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + vpor %xmm6, %xmm7, %xmm6 + vpor %xmm8, %xmm9, %xmm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r12d, %ebx + movl %r8d, %ecx + addl 52(%rsp), %r10d + xorl %r9d, %ecx + vpsrld $3, %xmm5, %xmm9 + vpxor %xmm6, %xmm8, %xmm6 + # rnd_1: 2 - 3 + xorl %r15d, %edx + andl %r15d, %ecx + rorl $5, %edx + xorl %r9d, %ecx + xorl %r15d, %edx + addl %ecx, %r10d + vpxor %xmm6, %xmm9, %xmm5 + vpshufd $0xfa, %xmm2, %xmm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r11d, %ebx + addl %edx, %r10d + movl %r11d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r11d, %ecx + xorl %r12d, %eax + vpsrld $10, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm3, %xmm4, %xmm4 + # rnd_0: 1 - 3 + movl %r11d, %eax + movl %r15d, %ecx + addl 56(%rsp), %r9d + xorl %r8d, %ecx + xorl %r14d, %edx + andl %r14d, %ecx + rorl $5, %edx + xorl %r8d, %ecx + xorl %r14d, %edx + addl %ecx, %r9d + vpxor %xmm6, %xmm7, %xmm6 + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r10d, %eax + addl %edx, %r9d + movl %r10d, %ecx + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r10d, %ecx + xorl %r11d, %ebx + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + movl %r10d, %ebx + movl %r14d, %ecx + addl 60(%rsp), %r8d + xorl %r15d, %ecx + vpsrlq $0x11, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 2 - 3 + xorl %r13d, %edx + andl %r13d, %ecx + rorl $5, %edx + xorl %r15d, %ecx + xorl %r13d, %edx + addl %ecx, %r8d + vpsrld $10, %xmm6, %xmm9 + vpxor %xmm8, %xmm7, %xmm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r9d, %ebx + addl %edx, %r8d + movl %r9d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r9d, %ecx + xorl %r10d, %eax + vpxor %xmm9, %xmm8, %xmm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + vpaddd %xmm4, %xmm9, %xmm3 + # msg_sched done: 12-15 + # set_w_k_xfer_4: 4 + vpaddd 64+L_avx1_sha256_k(%rip), %xmm0, %xmm4 + vpaddd 80+L_avx1_sha256_k(%rip), %xmm1, %xmm5 + vmovdqu %xmm4, (%rsp) + vmovdqu %xmm5, 16(%rsp) + vpaddd 96+L_avx1_sha256_k(%rip), %xmm2, %xmm6 + vpaddd 112+L_avx1_sha256_k(%rip), %xmm3, %xmm7 + vmovdqu %xmm6, 32(%rsp) + vmovdqu %xmm7, 48(%rsp) + # msg_sched: 0-3 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %xmm0, %xmm1, %xmm5 + vpalignr $4, %xmm2, %xmm3, %xmm4 + # rnd_0: 1 - 2 + movl %r9d, %eax + movl %r13d, %ecx + addl (%rsp), %r15d + xorl %r14d, %ecx + xorl %r12d, %edx + andl %r12d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r14d, %ecx + xorl %r12d, %edx + addl %ecx, %r15d + rorl $6, %edx + xorl %r8d, %eax + addl %edx, %r15d + movl %r8d, %ecx + vpsrld $18, %xmm5, %xmm8 + vpslld $14, %xmm5, %xmm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + vpor %xmm6, %xmm7, %xmm6 + vpor %xmm8, %xmm9, %xmm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r8d, %ebx + movl %r12d, %ecx + addl 4(%rsp), %r14d + xorl %r13d, %ecx + vpsrld $3, %xmm5, %xmm9 + vpxor %xmm6, %xmm8, %xmm6 + # rnd_1: 2 - 3 + xorl %r11d, %edx + andl %r11d, %ecx + rorl $5, %edx + xorl %r13d, %ecx + xorl %r11d, %edx + addl %ecx, %r14d + vpxor %xmm6, %xmm9, %xmm5 + vpshufd $0xfa, %xmm3, %xmm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r15d, %ebx + addl %edx, %r14d + movl %r15d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r15d, %ecx + xorl %r8d, %eax + vpsrld $10, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm0, %xmm4, %xmm4 + # rnd_0: 1 - 3 + movl %r15d, %eax + movl %r11d, %ecx + addl 8(%rsp), %r13d + xorl %r12d, %ecx + xorl %r10d, %edx + andl %r10d, %ecx + rorl $5, %edx + xorl %r12d, %ecx + xorl %r10d, %edx + addl %ecx, %r13d + vpxor %xmm6, %xmm7, %xmm6 + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r14d, %eax + addl %edx, %r13d + movl %r14d, %ecx + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r14d, %ecx + xorl %r15d, %ebx + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + movl %r14d, %ebx + movl %r10d, %ecx + addl 12(%rsp), %r12d + xorl %r11d, %ecx + vpsrlq $0x11, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 2 - 3 + xorl %r9d, %edx + andl %r9d, %ecx + rorl $5, %edx + xorl %r11d, %ecx + xorl %r9d, %edx + addl %ecx, %r12d + vpsrld $10, %xmm6, %xmm9 + vpxor %xmm8, %xmm7, %xmm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r13d, %ebx + addl %edx, %r12d + movl %r13d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r13d, %ecx + xorl %r14d, %eax + vpxor %xmm9, %xmm8, %xmm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + vpaddd %xmm4, %xmm9, %xmm0 + # msg_sched done: 0-3 + # msg_sched: 4-7 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %xmm1, %xmm2, %xmm5 + vpalignr $4, %xmm3, %xmm0, %xmm4 + # rnd_0: 1 - 2 + movl %r13d, %eax + movl %r9d, %ecx + addl 16(%rsp), %r11d + xorl %r10d, %ecx + xorl %r8d, %edx + andl %r8d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r10d, %ecx + xorl %r8d, %edx + addl %ecx, %r11d + rorl $6, %edx + xorl %r12d, %eax + addl %edx, %r11d + movl %r12d, %ecx + vpsrld $18, %xmm5, %xmm8 + vpslld $14, %xmm5, %xmm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + vpor %xmm6, %xmm7, %xmm6 + vpor %xmm8, %xmm9, %xmm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r12d, %ebx + movl %r8d, %ecx + addl 20(%rsp), %r10d + xorl %r9d, %ecx + vpsrld $3, %xmm5, %xmm9 + vpxor %xmm6, %xmm8, %xmm6 + # rnd_1: 2 - 3 + xorl %r15d, %edx + andl %r15d, %ecx + rorl $5, %edx + xorl %r9d, %ecx + xorl %r15d, %edx + addl %ecx, %r10d + vpxor %xmm6, %xmm9, %xmm5 + vpshufd $0xfa, %xmm0, %xmm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r11d, %ebx + addl %edx, %r10d + movl %r11d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r11d, %ecx + xorl %r12d, %eax + vpsrld $10, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm1, %xmm4, %xmm4 + # rnd_0: 1 - 3 + movl %r11d, %eax + movl %r15d, %ecx + addl 24(%rsp), %r9d + xorl %r8d, %ecx + xorl %r14d, %edx + andl %r14d, %ecx + rorl $5, %edx + xorl %r8d, %ecx + xorl %r14d, %edx + addl %ecx, %r9d + vpxor %xmm6, %xmm7, %xmm6 + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r10d, %eax + addl %edx, %r9d + movl %r10d, %ecx + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r10d, %ecx + xorl %r11d, %ebx + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + movl %r10d, %ebx + movl %r14d, %ecx + addl 28(%rsp), %r8d + xorl %r15d, %ecx + vpsrlq $0x11, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 2 - 3 + xorl %r13d, %edx + andl %r13d, %ecx + rorl $5, %edx + xorl %r15d, %ecx + xorl %r13d, %edx + addl %ecx, %r8d + vpsrld $10, %xmm6, %xmm9 + vpxor %xmm8, %xmm7, %xmm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r9d, %ebx + addl %edx, %r8d + movl %r9d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r9d, %ecx + xorl %r10d, %eax + vpxor %xmm9, %xmm8, %xmm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + vpaddd %xmm4, %xmm9, %xmm1 + # msg_sched done: 4-7 + # msg_sched: 8-11 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %xmm2, %xmm3, %xmm5 + vpalignr $4, %xmm0, %xmm1, %xmm4 + # rnd_0: 1 - 2 + movl %r9d, %eax + movl %r13d, %ecx + addl 32(%rsp), %r15d + xorl %r14d, %ecx + xorl %r12d, %edx + andl %r12d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r14d, %ecx + xorl %r12d, %edx + addl %ecx, %r15d + rorl $6, %edx + xorl %r8d, %eax + addl %edx, %r15d + movl %r8d, %ecx + vpsrld $18, %xmm5, %xmm8 + vpslld $14, %xmm5, %xmm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + vpor %xmm6, %xmm7, %xmm6 + vpor %xmm8, %xmm9, %xmm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r8d, %ebx + movl %r12d, %ecx + addl 36(%rsp), %r14d + xorl %r13d, %ecx + vpsrld $3, %xmm5, %xmm9 + vpxor %xmm6, %xmm8, %xmm6 + # rnd_1: 2 - 3 + xorl %r11d, %edx + andl %r11d, %ecx + rorl $5, %edx + xorl %r13d, %ecx + xorl %r11d, %edx + addl %ecx, %r14d + vpxor %xmm6, %xmm9, %xmm5 + vpshufd $0xfa, %xmm1, %xmm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r15d, %ebx + addl %edx, %r14d + movl %r15d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r15d, %ecx + xorl %r8d, %eax + vpsrld $10, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm2, %xmm4, %xmm4 + # rnd_0: 1 - 3 + movl %r15d, %eax + movl %r11d, %ecx + addl 40(%rsp), %r13d + xorl %r12d, %ecx + xorl %r10d, %edx + andl %r10d, %ecx + rorl $5, %edx + xorl %r12d, %ecx + xorl %r10d, %edx + addl %ecx, %r13d + vpxor %xmm6, %xmm7, %xmm6 + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r14d, %eax + addl %edx, %r13d + movl %r14d, %ecx + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r14d, %ecx + xorl %r15d, %ebx + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + movl %r14d, %ebx + movl %r10d, %ecx + addl 44(%rsp), %r12d + xorl %r11d, %ecx + vpsrlq $0x11, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 2 - 3 + xorl %r9d, %edx + andl %r9d, %ecx + rorl $5, %edx + xorl %r11d, %ecx + xorl %r9d, %edx + addl %ecx, %r12d + vpsrld $10, %xmm6, %xmm9 + vpxor %xmm8, %xmm7, %xmm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r13d, %ebx + addl %edx, %r12d + movl %r13d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r13d, %ecx + xorl %r14d, %eax + vpxor %xmm9, %xmm8, %xmm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + vpaddd %xmm4, %xmm9, %xmm2 + # msg_sched done: 8-11 + # msg_sched: 12-15 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %xmm3, %xmm0, %xmm5 + vpalignr $4, %xmm1, %xmm2, %xmm4 + # rnd_0: 1 - 2 + movl %r13d, %eax + movl %r9d, %ecx + addl 48(%rsp), %r11d + xorl %r10d, %ecx + xorl %r8d, %edx + andl %r8d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r10d, %ecx + xorl %r8d, %edx + addl %ecx, %r11d + rorl $6, %edx + xorl %r12d, %eax + addl %edx, %r11d + movl %r12d, %ecx + vpsrld $18, %xmm5, %xmm8 + vpslld $14, %xmm5, %xmm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + vpor %xmm6, %xmm7, %xmm6 + vpor %xmm8, %xmm9, %xmm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r12d, %ebx + movl %r8d, %ecx + addl 52(%rsp), %r10d + xorl %r9d, %ecx + vpsrld $3, %xmm5, %xmm9 + vpxor %xmm6, %xmm8, %xmm6 + # rnd_1: 2 - 3 + xorl %r15d, %edx + andl %r15d, %ecx + rorl $5, %edx + xorl %r9d, %ecx + xorl %r15d, %edx + addl %ecx, %r10d + vpxor %xmm6, %xmm9, %xmm5 + vpshufd $0xfa, %xmm2, %xmm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r11d, %ebx + addl %edx, %r10d + movl %r11d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r11d, %ecx + xorl %r12d, %eax + vpsrld $10, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm3, %xmm4, %xmm4 + # rnd_0: 1 - 3 + movl %r11d, %eax + movl %r15d, %ecx + addl 56(%rsp), %r9d + xorl %r8d, %ecx + xorl %r14d, %edx + andl %r14d, %ecx + rorl $5, %edx + xorl %r8d, %ecx + xorl %r14d, %edx + addl %ecx, %r9d + vpxor %xmm6, %xmm7, %xmm6 + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r10d, %eax + addl %edx, %r9d + movl %r10d, %ecx + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r10d, %ecx + xorl %r11d, %ebx + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + movl %r10d, %ebx + movl %r14d, %ecx + addl 60(%rsp), %r8d + xorl %r15d, %ecx + vpsrlq $0x11, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 2 - 3 + xorl %r13d, %edx + andl %r13d, %ecx + rorl $5, %edx + xorl %r15d, %ecx + xorl %r13d, %edx + addl %ecx, %r8d + vpsrld $10, %xmm6, %xmm9 + vpxor %xmm8, %xmm7, %xmm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r9d, %ebx + addl %edx, %r8d + movl %r9d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r9d, %ecx + xorl %r10d, %eax + vpxor %xmm9, %xmm8, %xmm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + vpaddd %xmm4, %xmm9, %xmm3 + # msg_sched done: 12-15 + # set_w_k_xfer_4: 8 + vpaddd 128+L_avx1_sha256_k(%rip), %xmm0, %xmm4 + vpaddd 144+L_avx1_sha256_k(%rip), %xmm1, %xmm5 + vmovdqu %xmm4, (%rsp) + vmovdqu %xmm5, 16(%rsp) + vpaddd 160+L_avx1_sha256_k(%rip), %xmm2, %xmm6 + vpaddd 176+L_avx1_sha256_k(%rip), %xmm3, %xmm7 + vmovdqu %xmm6, 32(%rsp) + vmovdqu %xmm7, 48(%rsp) + # msg_sched: 0-3 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %xmm0, %xmm1, %xmm5 + vpalignr $4, %xmm2, %xmm3, %xmm4 + # rnd_0: 1 - 2 + movl %r9d, %eax + movl %r13d, %ecx + addl (%rsp), %r15d + xorl %r14d, %ecx + xorl %r12d, %edx + andl %r12d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r14d, %ecx + xorl %r12d, %edx + addl %ecx, %r15d + rorl $6, %edx + xorl %r8d, %eax + addl %edx, %r15d + movl %r8d, %ecx + vpsrld $18, %xmm5, %xmm8 + vpslld $14, %xmm5, %xmm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + vpor %xmm6, %xmm7, %xmm6 + vpor %xmm8, %xmm9, %xmm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r8d, %ebx + movl %r12d, %ecx + addl 4(%rsp), %r14d + xorl %r13d, %ecx + vpsrld $3, %xmm5, %xmm9 + vpxor %xmm6, %xmm8, %xmm6 + # rnd_1: 2 - 3 + xorl %r11d, %edx + andl %r11d, %ecx + rorl $5, %edx + xorl %r13d, %ecx + xorl %r11d, %edx + addl %ecx, %r14d + vpxor %xmm6, %xmm9, %xmm5 + vpshufd $0xfa, %xmm3, %xmm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r15d, %ebx + addl %edx, %r14d + movl %r15d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r15d, %ecx + xorl %r8d, %eax + vpsrld $10, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm0, %xmm4, %xmm4 + # rnd_0: 1 - 3 + movl %r15d, %eax + movl %r11d, %ecx + addl 8(%rsp), %r13d + xorl %r12d, %ecx + xorl %r10d, %edx + andl %r10d, %ecx + rorl $5, %edx + xorl %r12d, %ecx + xorl %r10d, %edx + addl %ecx, %r13d + vpxor %xmm6, %xmm7, %xmm6 + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r14d, %eax + addl %edx, %r13d + movl %r14d, %ecx + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r14d, %ecx + xorl %r15d, %ebx + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + movl %r14d, %ebx + movl %r10d, %ecx + addl 12(%rsp), %r12d + xorl %r11d, %ecx + vpsrlq $0x11, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 2 - 3 + xorl %r9d, %edx + andl %r9d, %ecx + rorl $5, %edx + xorl %r11d, %ecx + xorl %r9d, %edx + addl %ecx, %r12d + vpsrld $10, %xmm6, %xmm9 + vpxor %xmm8, %xmm7, %xmm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r13d, %ebx + addl %edx, %r12d + movl %r13d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r13d, %ecx + xorl %r14d, %eax + vpxor %xmm9, %xmm8, %xmm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + vpaddd %xmm4, %xmm9, %xmm0 + # msg_sched done: 0-3 + # msg_sched: 4-7 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %xmm1, %xmm2, %xmm5 + vpalignr $4, %xmm3, %xmm0, %xmm4 + # rnd_0: 1 - 2 + movl %r13d, %eax + movl %r9d, %ecx + addl 16(%rsp), %r11d + xorl %r10d, %ecx + xorl %r8d, %edx + andl %r8d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r10d, %ecx + xorl %r8d, %edx + addl %ecx, %r11d + rorl $6, %edx + xorl %r12d, %eax + addl %edx, %r11d + movl %r12d, %ecx + vpsrld $18, %xmm5, %xmm8 + vpslld $14, %xmm5, %xmm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + vpor %xmm6, %xmm7, %xmm6 + vpor %xmm8, %xmm9, %xmm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r12d, %ebx + movl %r8d, %ecx + addl 20(%rsp), %r10d + xorl %r9d, %ecx + vpsrld $3, %xmm5, %xmm9 + vpxor %xmm6, %xmm8, %xmm6 + # rnd_1: 2 - 3 + xorl %r15d, %edx + andl %r15d, %ecx + rorl $5, %edx + xorl %r9d, %ecx + xorl %r15d, %edx + addl %ecx, %r10d + vpxor %xmm6, %xmm9, %xmm5 + vpshufd $0xfa, %xmm0, %xmm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r11d, %ebx + addl %edx, %r10d + movl %r11d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r11d, %ecx + xorl %r12d, %eax + vpsrld $10, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm1, %xmm4, %xmm4 + # rnd_0: 1 - 3 + movl %r11d, %eax + movl %r15d, %ecx + addl 24(%rsp), %r9d + xorl %r8d, %ecx + xorl %r14d, %edx + andl %r14d, %ecx + rorl $5, %edx + xorl %r8d, %ecx + xorl %r14d, %edx + addl %ecx, %r9d + vpxor %xmm6, %xmm7, %xmm6 + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r10d, %eax + addl %edx, %r9d + movl %r10d, %ecx + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r10d, %ecx + xorl %r11d, %ebx + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + movl %r10d, %ebx + movl %r14d, %ecx + addl 28(%rsp), %r8d + xorl %r15d, %ecx + vpsrlq $0x11, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 2 - 3 + xorl %r13d, %edx + andl %r13d, %ecx + rorl $5, %edx + xorl %r15d, %ecx + xorl %r13d, %edx + addl %ecx, %r8d + vpsrld $10, %xmm6, %xmm9 + vpxor %xmm8, %xmm7, %xmm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r9d, %ebx + addl %edx, %r8d + movl %r9d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r9d, %ecx + xorl %r10d, %eax + vpxor %xmm9, %xmm8, %xmm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + vpaddd %xmm4, %xmm9, %xmm1 + # msg_sched done: 4-7 + # msg_sched: 8-11 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %xmm2, %xmm3, %xmm5 + vpalignr $4, %xmm0, %xmm1, %xmm4 + # rnd_0: 1 - 2 + movl %r9d, %eax + movl %r13d, %ecx + addl 32(%rsp), %r15d + xorl %r14d, %ecx + xorl %r12d, %edx + andl %r12d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r14d, %ecx + xorl %r12d, %edx + addl %ecx, %r15d + rorl $6, %edx + xorl %r8d, %eax + addl %edx, %r15d + movl %r8d, %ecx + vpsrld $18, %xmm5, %xmm8 + vpslld $14, %xmm5, %xmm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + vpor %xmm6, %xmm7, %xmm6 + vpor %xmm8, %xmm9, %xmm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r8d, %ebx + movl %r12d, %ecx + addl 36(%rsp), %r14d + xorl %r13d, %ecx + vpsrld $3, %xmm5, %xmm9 + vpxor %xmm6, %xmm8, %xmm6 + # rnd_1: 2 - 3 + xorl %r11d, %edx + andl %r11d, %ecx + rorl $5, %edx + xorl %r13d, %ecx + xorl %r11d, %edx + addl %ecx, %r14d + vpxor %xmm6, %xmm9, %xmm5 + vpshufd $0xfa, %xmm1, %xmm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r15d, %ebx + addl %edx, %r14d + movl %r15d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r15d, %ecx + xorl %r8d, %eax + vpsrld $10, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm2, %xmm4, %xmm4 + # rnd_0: 1 - 3 + movl %r15d, %eax + movl %r11d, %ecx + addl 40(%rsp), %r13d + xorl %r12d, %ecx + xorl %r10d, %edx + andl %r10d, %ecx + rorl $5, %edx + xorl %r12d, %ecx + xorl %r10d, %edx + addl %ecx, %r13d + vpxor %xmm6, %xmm7, %xmm6 + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r14d, %eax + addl %edx, %r13d + movl %r14d, %ecx + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r14d, %ecx + xorl %r15d, %ebx + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + movl %r14d, %ebx + movl %r10d, %ecx + addl 44(%rsp), %r12d + xorl %r11d, %ecx + vpsrlq $0x11, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 2 - 3 + xorl %r9d, %edx + andl %r9d, %ecx + rorl $5, %edx + xorl %r11d, %ecx + xorl %r9d, %edx + addl %ecx, %r12d + vpsrld $10, %xmm6, %xmm9 + vpxor %xmm8, %xmm7, %xmm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r13d, %ebx + addl %edx, %r12d + movl %r13d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r13d, %ecx + xorl %r14d, %eax + vpxor %xmm9, %xmm8, %xmm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + vpaddd %xmm4, %xmm9, %xmm2 + # msg_sched done: 8-11 + # msg_sched: 12-15 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %xmm3, %xmm0, %xmm5 + vpalignr $4, %xmm1, %xmm2, %xmm4 + # rnd_0: 1 - 2 + movl %r13d, %eax + movl %r9d, %ecx + addl 48(%rsp), %r11d + xorl %r10d, %ecx + xorl %r8d, %edx + andl %r8d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r10d, %ecx + xorl %r8d, %edx + addl %ecx, %r11d + rorl $6, %edx + xorl %r12d, %eax + addl %edx, %r11d + movl %r12d, %ecx + vpsrld $18, %xmm5, %xmm8 + vpslld $14, %xmm5, %xmm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + vpor %xmm6, %xmm7, %xmm6 + vpor %xmm8, %xmm9, %xmm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r12d, %ebx + movl %r8d, %ecx + addl 52(%rsp), %r10d + xorl %r9d, %ecx + vpsrld $3, %xmm5, %xmm9 + vpxor %xmm6, %xmm8, %xmm6 + # rnd_1: 2 - 3 + xorl %r15d, %edx + andl %r15d, %ecx + rorl $5, %edx + xorl %r9d, %ecx + xorl %r15d, %edx + addl %ecx, %r10d + vpxor %xmm6, %xmm9, %xmm5 + vpshufd $0xfa, %xmm2, %xmm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r11d, %ebx + addl %edx, %r10d + movl %r11d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r11d, %ecx + xorl %r12d, %eax + vpsrld $10, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm3, %xmm4, %xmm4 + # rnd_0: 1 - 3 + movl %r11d, %eax + movl %r15d, %ecx + addl 56(%rsp), %r9d + xorl %r8d, %ecx + xorl %r14d, %edx + andl %r14d, %ecx + rorl $5, %edx + xorl %r8d, %ecx + xorl %r14d, %edx + addl %ecx, %r9d + vpxor %xmm6, %xmm7, %xmm6 + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r10d, %eax + addl %edx, %r9d + movl %r10d, %ecx + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r10d, %ecx + xorl %r11d, %ebx + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + movl %r10d, %ebx + movl %r14d, %ecx + addl 60(%rsp), %r8d + xorl %r15d, %ecx + vpsrlq $0x11, %xmm6, %xmm8 + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 2 - 3 + xorl %r13d, %edx + andl %r13d, %ecx + rorl $5, %edx + xorl %r15d, %ecx + xorl %r13d, %edx + addl %ecx, %r8d + vpsrld $10, %xmm6, %xmm9 + vpxor %xmm8, %xmm7, %xmm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r9d, %ebx + addl %edx, %r8d + movl %r9d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r9d, %ecx + xorl %r10d, %eax + vpxor %xmm9, %xmm8, %xmm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + vpaddd %xmm4, %xmm9, %xmm3 + # msg_sched done: 12-15 + # set_w_k_xfer_4: 12 + vpaddd 192+L_avx1_sha256_k(%rip), %xmm0, %xmm4 + vpaddd 208+L_avx1_sha256_k(%rip), %xmm1, %xmm5 + vmovdqu %xmm4, (%rsp) + vmovdqu %xmm5, 16(%rsp) + vpaddd 224+L_avx1_sha256_k(%rip), %xmm2, %xmm6 + vpaddd 240+L_avx1_sha256_k(%rip), %xmm3, %xmm7 + vmovdqu %xmm6, 32(%rsp) + vmovdqu %xmm7, 48(%rsp) + # rnd_all_4: 0-3 + addl (%rsp), %r15d + movl %r13d, %ecx + movl %r9d, %eax + xorl %r14d, %ecx + rorl $14, %edx + andl %r12d, %ecx + xorl %r12d, %edx + xorl %r14d, %ecx + rorl $5, %edx + addl %ecx, %r15d + xorl %r12d, %edx + xorl %r8d, %eax + rorl $6, %edx + movl %r8d, %ecx + addl %edx, %r15d + rorl $9, %ecx + andl %eax, %ebx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + addl 4(%rsp), %r14d + movl %r12d, %ecx + movl %r8d, %ebx + xorl %r13d, %ecx + rorl $14, %edx + andl %r11d, %ecx + xorl %r11d, %edx + xorl %r13d, %ecx + rorl $5, %edx + addl %ecx, %r14d + xorl %r11d, %edx + xorl %r15d, %ebx + rorl $6, %edx + movl %r15d, %ecx + addl %edx, %r14d + rorl $9, %ecx + andl %ebx, %eax + xorl %r15d, %ecx + xorl %r8d, %eax + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + addl 8(%rsp), %r13d + movl %r11d, %ecx + movl %r15d, %eax + xorl %r12d, %ecx + rorl $14, %edx + andl %r10d, %ecx + xorl %r10d, %edx + xorl %r12d, %ecx + rorl $5, %edx + addl %ecx, %r13d + xorl %r10d, %edx + xorl %r14d, %eax + rorl $6, %edx + movl %r14d, %ecx + addl %edx, %r13d + rorl $9, %ecx + andl %eax, %ebx + xorl %r14d, %ecx + xorl %r15d, %ebx + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + addl 12(%rsp), %r12d + movl %r10d, %ecx + movl %r14d, %ebx + xorl %r11d, %ecx + rorl $14, %edx + andl %r9d, %ecx + xorl %r9d, %edx + xorl %r11d, %ecx + rorl $5, %edx + addl %ecx, %r12d + xorl %r9d, %edx + xorl %r13d, %ebx + rorl $6, %edx + movl %r13d, %ecx + addl %edx, %r12d + rorl $9, %ecx + andl %ebx, %eax + xorl %r13d, %ecx + xorl %r14d, %eax + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + # rnd_all_4: 1-4 + addl 16(%rsp), %r11d + movl %r9d, %ecx + movl %r13d, %eax + xorl %r10d, %ecx + rorl $14, %edx + andl %r8d, %ecx + xorl %r8d, %edx + xorl %r10d, %ecx + rorl $5, %edx + addl %ecx, %r11d + xorl %r8d, %edx + xorl %r12d, %eax + rorl $6, %edx + movl %r12d, %ecx + addl %edx, %r11d + rorl $9, %ecx + andl %eax, %ebx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + addl 20(%rsp), %r10d + movl %r8d, %ecx + movl %r12d, %ebx + xorl %r9d, %ecx + rorl $14, %edx + andl %r15d, %ecx + xorl %r15d, %edx + xorl %r9d, %ecx + rorl $5, %edx + addl %ecx, %r10d + xorl %r15d, %edx + xorl %r11d, %ebx + rorl $6, %edx + movl %r11d, %ecx + addl %edx, %r10d + rorl $9, %ecx + andl %ebx, %eax + xorl %r11d, %ecx + xorl %r12d, %eax + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + addl 24(%rsp), %r9d + movl %r15d, %ecx + movl %r11d, %eax + xorl %r8d, %ecx + rorl $14, %edx + andl %r14d, %ecx + xorl %r14d, %edx + xorl %r8d, %ecx + rorl $5, %edx + addl %ecx, %r9d + xorl %r14d, %edx + xorl %r10d, %eax + rorl $6, %edx + movl %r10d, %ecx + addl %edx, %r9d + rorl $9, %ecx + andl %eax, %ebx + xorl %r10d, %ecx + xorl %r11d, %ebx + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + addl 28(%rsp), %r8d + movl %r14d, %ecx + movl %r10d, %ebx + xorl %r15d, %ecx + rorl $14, %edx + andl %r13d, %ecx + xorl %r13d, %edx + xorl %r15d, %ecx + rorl $5, %edx + addl %ecx, %r8d + xorl %r13d, %edx + xorl %r9d, %ebx + rorl $6, %edx + movl %r9d, %ecx + addl %edx, %r8d + rorl $9, %ecx + andl %ebx, %eax + xorl %r9d, %ecx + xorl %r10d, %eax + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + # rnd_all_4: 2-5 + addl 32(%rsp), %r15d + movl %r13d, %ecx + movl %r9d, %eax + xorl %r14d, %ecx + rorl $14, %edx + andl %r12d, %ecx + xorl %r12d, %edx + xorl %r14d, %ecx + rorl $5, %edx + addl %ecx, %r15d + xorl %r12d, %edx + xorl %r8d, %eax + rorl $6, %edx + movl %r8d, %ecx + addl %edx, %r15d + rorl $9, %ecx + andl %eax, %ebx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + addl 36(%rsp), %r14d + movl %r12d, %ecx + movl %r8d, %ebx + xorl %r13d, %ecx + rorl $14, %edx + andl %r11d, %ecx + xorl %r11d, %edx + xorl %r13d, %ecx + rorl $5, %edx + addl %ecx, %r14d + xorl %r11d, %edx + xorl %r15d, %ebx + rorl $6, %edx + movl %r15d, %ecx + addl %edx, %r14d + rorl $9, %ecx + andl %ebx, %eax + xorl %r15d, %ecx + xorl %r8d, %eax + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + addl 40(%rsp), %r13d + movl %r11d, %ecx + movl %r15d, %eax + xorl %r12d, %ecx + rorl $14, %edx + andl %r10d, %ecx + xorl %r10d, %edx + xorl %r12d, %ecx + rorl $5, %edx + addl %ecx, %r13d + xorl %r10d, %edx + xorl %r14d, %eax + rorl $6, %edx + movl %r14d, %ecx + addl %edx, %r13d + rorl $9, %ecx + andl %eax, %ebx + xorl %r14d, %ecx + xorl %r15d, %ebx + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + addl 44(%rsp), %r12d + movl %r10d, %ecx + movl %r14d, %ebx + xorl %r11d, %ecx + rorl $14, %edx + andl %r9d, %ecx + xorl %r9d, %edx + xorl %r11d, %ecx + rorl $5, %edx + addl %ecx, %r12d + xorl %r9d, %edx + xorl %r13d, %ebx + rorl $6, %edx + movl %r13d, %ecx + addl %edx, %r12d + rorl $9, %ecx + andl %ebx, %eax + xorl %r13d, %ecx + xorl %r14d, %eax + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + # rnd_all_4: 3-6 + addl 48(%rsp), %r11d + movl %r9d, %ecx + movl %r13d, %eax + xorl %r10d, %ecx + rorl $14, %edx + andl %r8d, %ecx + xorl %r8d, %edx + xorl %r10d, %ecx + rorl $5, %edx + addl %ecx, %r11d + xorl %r8d, %edx + xorl %r12d, %eax + rorl $6, %edx + movl %r12d, %ecx + addl %edx, %r11d + rorl $9, %ecx + andl %eax, %ebx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + addl 52(%rsp), %r10d + movl %r8d, %ecx + movl %r12d, %ebx + xorl %r9d, %ecx + rorl $14, %edx + andl %r15d, %ecx + xorl %r15d, %edx + xorl %r9d, %ecx + rorl $5, %edx + addl %ecx, %r10d + xorl %r15d, %edx + xorl %r11d, %ebx + rorl $6, %edx + movl %r11d, %ecx + addl %edx, %r10d + rorl $9, %ecx + andl %ebx, %eax + xorl %r11d, %ecx + xorl %r12d, %eax + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + addl 56(%rsp), %r9d + movl %r15d, %ecx + movl %r11d, %eax + xorl %r8d, %ecx + rorl $14, %edx + andl %r14d, %ecx + xorl %r14d, %edx + xorl %r8d, %ecx + rorl $5, %edx + addl %ecx, %r9d + xorl %r14d, %edx + xorl %r10d, %eax + rorl $6, %edx + movl %r10d, %ecx + addl %edx, %r9d + rorl $9, %ecx + andl %eax, %ebx + xorl %r10d, %ecx + xorl %r11d, %ebx + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + addl 60(%rsp), %r8d + movl %r14d, %ecx + movl %r10d, %ebx + xorl %r15d, %ecx + rorl $14, %edx + andl %r13d, %ecx + xorl %r13d, %edx + xorl %r15d, %ecx + rorl $5, %edx + addl %ecx, %r8d + xorl %r13d, %edx + xorl %r9d, %ebx + rorl $6, %edx + movl %r9d, %ecx + addl %edx, %r8d + rorl $9, %ecx + andl %ebx, %eax + xorl %r9d, %ecx + xorl %r10d, %eax + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + addl (%rdi), %r8d + addl 4(%rdi), %r9d + addl 8(%rdi), %r10d + addl 12(%rdi), %r11d + addl 16(%rdi), %r12d + addl 20(%rdi), %r13d + addl 24(%rdi), %r14d + addl 28(%rdi), %r15d + addq $0x40, %rbp + subl $0x40, %esi + movl %r8d, (%rdi) + movl %r9d, 4(%rdi) + movl %r10d, 8(%rdi) + movl %r11d, 12(%rdi) + movl %r12d, 16(%rdi) + movl %r13d, 20(%rdi) + movl %r14d, 24(%rdi) + movl %r15d, 28(%rdi) + jnz L_sha256_len_avx1_start + xorq %rax, %rax + vzeroupper + addq $0x40, %rsp + popq %rbp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size Transform_Sha256_AVX1_Len,.-Transform_Sha256_AVX1_Len +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +L_avx1_rorx_sha256_k: +.long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5 +.long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5 +.long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3 +.long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174 +.long 0xe49b69c1,0xefbe4786,0xfc19dc6,0x240ca1cc +.long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da +.long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7 +.long 0xc6e00bf3,0xd5a79147,0x6ca6351,0x14292967 +.long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13 +.long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85 +.long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3 +.long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070 +.long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5 +.long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3 +.long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208 +.long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx1_rorx_sha256_shuf_00BA: +.quad 0xb0a090803020100, 0xffffffffffffffff +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx1_rorx_sha256_shuf_DC00: +.quad 0xffffffffffffffff, 0xb0a090803020100 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx1_rorx_sha256_flip_mask: +.quad 0x405060700010203, 0xc0d0e0f08090a0b +#ifndef __APPLE__ +.text +.globl Transform_Sha256_AVX1_RORX +.type Transform_Sha256_AVX1_RORX,@function +.align 4 +Transform_Sha256_AVX1_RORX: +#else +.section __TEXT,__text +.globl _Transform_Sha256_AVX1_RORX +.p2align 2 +_Transform_Sha256_AVX1_RORX: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + subq $0x40, %rsp + vmovdqa L_avx1_rorx_sha256_flip_mask(%rip), %xmm13 + vmovdqa L_avx1_rorx_sha256_shuf_00BA(%rip), %xmm11 + vmovdqa L_avx1_rorx_sha256_shuf_DC00(%rip), %xmm12 + leaq 32(%rdi), %rax + # X0, X1, X2, X3 = W[0..15] + vmovdqu (%rax), %xmm0 + vmovdqu 16(%rax), %xmm1 + vpshufb %xmm13, %xmm0, %xmm0 + vpshufb %xmm13, %xmm1, %xmm1 + vmovdqu 32(%rax), %xmm2 + vmovdqu 48(%rax), %xmm3 + vpshufb %xmm13, %xmm2, %xmm2 + vpshufb %xmm13, %xmm3, %xmm3 + movl (%rdi), %r8d + movl 4(%rdi), %r9d + movl 8(%rdi), %r10d + movl 12(%rdi), %r11d + movl 16(%rdi), %r12d + movl 20(%rdi), %r13d + movl 24(%rdi), %r14d + movl 28(%rdi), %r15d + # set_w_k_xfer_4: 0 + vpaddd 0+L_avx1_rorx_sha256_k(%rip), %xmm0, %xmm4 + vpaddd 16+L_avx1_rorx_sha256_k(%rip), %xmm1, %xmm5 + vmovdqu %xmm4, (%rsp) + vmovdqu %xmm5, 16(%rsp) + vpaddd 32+L_avx1_rorx_sha256_k(%rip), %xmm2, %xmm6 + vpaddd 48+L_avx1_rorx_sha256_k(%rip), %xmm3, %xmm7 + vmovdqu %xmm6, 32(%rsp) + vmovdqu %xmm7, 48(%rsp) + movl %r9d, %ebx + rorxl $6, %r12d, %edx + xorl %r10d, %ebx + # msg_sched: 0-3 + # rnd_0: 0 - 0 + movl %r13d, %eax + rorxl $11, %r12d, %ecx + addl (%rsp), %r15d + vpalignr $4, %xmm2, %xmm3, %xmm4 + vpalignr $4, %xmm0, %xmm1, %xmm5 + # rnd_0: 1 - 2 + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + andl %r12d, %eax + xorl %ecx, %edx + rorxl $13, %r8d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + addl %edx, %r15d + rorxl $2, %r8d, %edx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + vpsrld $3, %xmm5, %xmm8 + vpor %xmm6, %xmm7, %xmm7 + # rnd_0: 5 - 7 + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + addl %edx, %r15d + andl %eax, %ebx + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + addl %ebx, %r15d + # rnd_1: 0 - 0 + movl %r12d, %ebx + rorxl $11, %r11d, %ecx + addl 4(%rsp), %r14d + vpsrld $18, %xmm5, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + vpslld $14, %xmm5, %xmm5 + # rnd_1: 2 - 2 + andl %r11d, %ebx + xorl %ecx, %edx + rorxl $13, %r15d, %ecx + vpxor %xmm5, %xmm7, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r14d + rorxl $2, %r15d, %edx + xorl %r13d, %ebx + vpxor %xmm6, %xmm7, %xmm7 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + vpshufd $0xfa, %xmm3, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r8d, %ebx + addl %r14d, %r10d + vpxor %xmm8, %xmm7, %xmm5 + # rnd_1: 6 - 6 + xorl %r15d, %ebx + addl %edx, %r14d + andl %ebx, %eax + vpsrld $10, %xmm6, %xmm8 + # rnd_1: 7 - 7 + xorl %r8d, %eax + rorxl $6, %r10d, %edx + addl %eax, %r14d + # rnd_0: 0 - 0 + movl %r11d, %eax + rorxl $11, %r10d, %ecx + addl 8(%rsp), %r13d + vpsrlq $19, %xmm6, %xmm7 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm0, %xmm4, %xmm4 + # rnd_0: 2 - 2 + andl %r10d, %eax + xorl %ecx, %edx + rorxl $13, %r14d, %ecx + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 3 - 3 + addl %edx, %r13d + rorxl $2, %r14d, %edx + xorl %r12d, %eax + vpxor %xmm7, %xmm6, %xmm6 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + xorl %r14d, %eax + addl %edx, %r13d + andl %eax, %ebx + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + addl %ebx, %r13d + # rnd_1: 0 - 0 + movl %r10d, %ebx + rorxl $11, %r9d, %ecx + addl 12(%rsp), %r12d + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + vpsrld $10, %xmm6, %xmm9 + # rnd_1: 2 - 2 + andl %r9d, %ebx + xorl %ecx, %edx + rorxl $13, %r13d, %ecx + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r12d + rorxl $2, %r13d, %edx + xorl %r11d, %ebx + vpsrlq $0x11, %xmm6, %xmm6 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + vpxor %xmm7, %xmm6, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r14d, %ebx + addl %r12d, %r8d + vpxor %xmm6, %xmm9, %xmm9 + # rnd_1: 6 - 6 + xorl %r13d, %ebx + addl %edx, %r12d + andl %ebx, %eax + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + xorl %r14d, %eax + rorxl $6, %r8d, %edx + addl %eax, %r12d + vpaddd %xmm4, %xmm9, %xmm0 + # msg_sched done: 0-3 + # msg_sched: 4-7 + # rnd_0: 0 - 0 + movl %r9d, %eax + rorxl $11, %r8d, %ecx + addl 16(%rsp), %r11d + vpalignr $4, %xmm3, %xmm0, %xmm4 + vpalignr $4, %xmm1, %xmm2, %xmm5 + # rnd_0: 1 - 2 + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + andl %r8d, %eax + xorl %ecx, %edx + rorxl $13, %r12d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + addl %edx, %r11d + rorxl $2, %r12d, %edx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + vpsrld $3, %xmm5, %xmm8 + vpor %xmm6, %xmm7, %xmm7 + # rnd_0: 5 - 7 + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + addl %edx, %r11d + andl %eax, %ebx + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + addl %ebx, %r11d + # rnd_1: 0 - 0 + movl %r8d, %ebx + rorxl $11, %r15d, %ecx + addl 20(%rsp), %r10d + vpsrld $18, %xmm5, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + vpslld $14, %xmm5, %xmm5 + # rnd_1: 2 - 2 + andl %r15d, %ebx + xorl %ecx, %edx + rorxl $13, %r11d, %ecx + vpxor %xmm5, %xmm7, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r10d + rorxl $2, %r11d, %edx + xorl %r9d, %ebx + vpxor %xmm6, %xmm7, %xmm7 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + vpshufd $0xfa, %xmm0, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r12d, %ebx + addl %r10d, %r14d + vpxor %xmm8, %xmm7, %xmm5 + # rnd_1: 6 - 6 + xorl %r11d, %ebx + addl %edx, %r10d + andl %ebx, %eax + vpsrld $10, %xmm6, %xmm8 + # rnd_1: 7 - 7 + xorl %r12d, %eax + rorxl $6, %r14d, %edx + addl %eax, %r10d + # rnd_0: 0 - 0 + movl %r15d, %eax + rorxl $11, %r14d, %ecx + addl 24(%rsp), %r9d + vpsrlq $19, %xmm6, %xmm7 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm1, %xmm4, %xmm4 + # rnd_0: 2 - 2 + andl %r14d, %eax + xorl %ecx, %edx + rorxl $13, %r10d, %ecx + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 3 - 3 + addl %edx, %r9d + rorxl $2, %r10d, %edx + xorl %r8d, %eax + vpxor %xmm7, %xmm6, %xmm6 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + xorl %r10d, %eax + addl %edx, %r9d + andl %eax, %ebx + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + addl %ebx, %r9d + # rnd_1: 0 - 0 + movl %r14d, %ebx + rorxl $11, %r13d, %ecx + addl 28(%rsp), %r8d + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + vpsrld $10, %xmm6, %xmm9 + # rnd_1: 2 - 2 + andl %r13d, %ebx + xorl %ecx, %edx + rorxl $13, %r9d, %ecx + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r8d + rorxl $2, %r9d, %edx + xorl %r15d, %ebx + vpsrlq $0x11, %xmm6, %xmm6 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + vpxor %xmm7, %xmm6, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r10d, %ebx + addl %r8d, %r12d + vpxor %xmm6, %xmm9, %xmm9 + # rnd_1: 6 - 6 + xorl %r9d, %ebx + addl %edx, %r8d + andl %ebx, %eax + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + xorl %r10d, %eax + rorxl $6, %r12d, %edx + addl %eax, %r8d + vpaddd %xmm4, %xmm9, %xmm1 + # msg_sched done: 4-7 + # msg_sched: 8-11 + # rnd_0: 0 - 0 + movl %r13d, %eax + rorxl $11, %r12d, %ecx + addl 32(%rsp), %r15d + vpalignr $4, %xmm0, %xmm1, %xmm4 + vpalignr $4, %xmm2, %xmm3, %xmm5 + # rnd_0: 1 - 2 + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + andl %r12d, %eax + xorl %ecx, %edx + rorxl $13, %r8d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + addl %edx, %r15d + rorxl $2, %r8d, %edx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + vpsrld $3, %xmm5, %xmm8 + vpor %xmm6, %xmm7, %xmm7 + # rnd_0: 5 - 7 + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + addl %edx, %r15d + andl %eax, %ebx + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + addl %ebx, %r15d + # rnd_1: 0 - 0 + movl %r12d, %ebx + rorxl $11, %r11d, %ecx + addl 36(%rsp), %r14d + vpsrld $18, %xmm5, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + vpslld $14, %xmm5, %xmm5 + # rnd_1: 2 - 2 + andl %r11d, %ebx + xorl %ecx, %edx + rorxl $13, %r15d, %ecx + vpxor %xmm5, %xmm7, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r14d + rorxl $2, %r15d, %edx + xorl %r13d, %ebx + vpxor %xmm6, %xmm7, %xmm7 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + vpshufd $0xfa, %xmm1, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r8d, %ebx + addl %r14d, %r10d + vpxor %xmm8, %xmm7, %xmm5 + # rnd_1: 6 - 6 + xorl %r15d, %ebx + addl %edx, %r14d + andl %ebx, %eax + vpsrld $10, %xmm6, %xmm8 + # rnd_1: 7 - 7 + xorl %r8d, %eax + rorxl $6, %r10d, %edx + addl %eax, %r14d + # rnd_0: 0 - 0 + movl %r11d, %eax + rorxl $11, %r10d, %ecx + addl 40(%rsp), %r13d + vpsrlq $19, %xmm6, %xmm7 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm2, %xmm4, %xmm4 + # rnd_0: 2 - 2 + andl %r10d, %eax + xorl %ecx, %edx + rorxl $13, %r14d, %ecx + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 3 - 3 + addl %edx, %r13d + rorxl $2, %r14d, %edx + xorl %r12d, %eax + vpxor %xmm7, %xmm6, %xmm6 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + xorl %r14d, %eax + addl %edx, %r13d + andl %eax, %ebx + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + addl %ebx, %r13d + # rnd_1: 0 - 0 + movl %r10d, %ebx + rorxl $11, %r9d, %ecx + addl 44(%rsp), %r12d + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + vpsrld $10, %xmm6, %xmm9 + # rnd_1: 2 - 2 + andl %r9d, %ebx + xorl %ecx, %edx + rorxl $13, %r13d, %ecx + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r12d + rorxl $2, %r13d, %edx + xorl %r11d, %ebx + vpsrlq $0x11, %xmm6, %xmm6 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + vpxor %xmm7, %xmm6, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r14d, %ebx + addl %r12d, %r8d + vpxor %xmm6, %xmm9, %xmm9 + # rnd_1: 6 - 6 + xorl %r13d, %ebx + addl %edx, %r12d + andl %ebx, %eax + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + xorl %r14d, %eax + rorxl $6, %r8d, %edx + addl %eax, %r12d + vpaddd %xmm4, %xmm9, %xmm2 + # msg_sched done: 8-11 + # msg_sched: 12-15 + # rnd_0: 0 - 0 + movl %r9d, %eax + rorxl $11, %r8d, %ecx + addl 48(%rsp), %r11d + vpalignr $4, %xmm1, %xmm2, %xmm4 + vpalignr $4, %xmm3, %xmm0, %xmm5 + # rnd_0: 1 - 2 + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + andl %r8d, %eax + xorl %ecx, %edx + rorxl $13, %r12d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + addl %edx, %r11d + rorxl $2, %r12d, %edx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + vpsrld $3, %xmm5, %xmm8 + vpor %xmm6, %xmm7, %xmm7 + # rnd_0: 5 - 7 + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + addl %edx, %r11d + andl %eax, %ebx + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + addl %ebx, %r11d + # rnd_1: 0 - 0 + movl %r8d, %ebx + rorxl $11, %r15d, %ecx + addl 52(%rsp), %r10d + vpsrld $18, %xmm5, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + vpslld $14, %xmm5, %xmm5 + # rnd_1: 2 - 2 + andl %r15d, %ebx + xorl %ecx, %edx + rorxl $13, %r11d, %ecx + vpxor %xmm5, %xmm7, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r10d + rorxl $2, %r11d, %edx + xorl %r9d, %ebx + vpxor %xmm6, %xmm7, %xmm7 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + vpshufd $0xfa, %xmm2, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r12d, %ebx + addl %r10d, %r14d + vpxor %xmm8, %xmm7, %xmm5 + # rnd_1: 6 - 6 + xorl %r11d, %ebx + addl %edx, %r10d + andl %ebx, %eax + vpsrld $10, %xmm6, %xmm8 + # rnd_1: 7 - 7 + xorl %r12d, %eax + rorxl $6, %r14d, %edx + addl %eax, %r10d + # rnd_0: 0 - 0 + movl %r15d, %eax + rorxl $11, %r14d, %ecx + addl 56(%rsp), %r9d + vpsrlq $19, %xmm6, %xmm7 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm3, %xmm4, %xmm4 + # rnd_0: 2 - 2 + andl %r14d, %eax + xorl %ecx, %edx + rorxl $13, %r10d, %ecx + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 3 - 3 + addl %edx, %r9d + rorxl $2, %r10d, %edx + xorl %r8d, %eax + vpxor %xmm7, %xmm6, %xmm6 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + xorl %r10d, %eax + addl %edx, %r9d + andl %eax, %ebx + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + addl %ebx, %r9d + # rnd_1: 0 - 0 + movl %r14d, %ebx + rorxl $11, %r13d, %ecx + addl 60(%rsp), %r8d + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + vpsrld $10, %xmm6, %xmm9 + # rnd_1: 2 - 2 + andl %r13d, %ebx + xorl %ecx, %edx + rorxl $13, %r9d, %ecx + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r8d + rorxl $2, %r9d, %edx + xorl %r15d, %ebx + vpsrlq $0x11, %xmm6, %xmm6 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + vpxor %xmm7, %xmm6, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r10d, %ebx + addl %r8d, %r12d + vpxor %xmm6, %xmm9, %xmm9 + # rnd_1: 6 - 6 + xorl %r9d, %ebx + addl %edx, %r8d + andl %ebx, %eax + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + xorl %r10d, %eax + rorxl $6, %r12d, %edx + addl %eax, %r8d + vpaddd %xmm4, %xmm9, %xmm3 + # msg_sched done: 12-15 + # set_w_k_xfer_4: 4 + vpaddd 64+L_avx1_rorx_sha256_k(%rip), %xmm0, %xmm4 + vpaddd 80+L_avx1_rorx_sha256_k(%rip), %xmm1, %xmm5 + vmovdqu %xmm4, (%rsp) + vmovdqu %xmm5, 16(%rsp) + vpaddd 96+L_avx1_rorx_sha256_k(%rip), %xmm2, %xmm6 + vpaddd 112+L_avx1_rorx_sha256_k(%rip), %xmm3, %xmm7 + vmovdqu %xmm6, 32(%rsp) + vmovdqu %xmm7, 48(%rsp) + # msg_sched: 0-3 + # rnd_0: 0 - 0 + movl %r13d, %eax + rorxl $11, %r12d, %ecx + addl (%rsp), %r15d + vpalignr $4, %xmm2, %xmm3, %xmm4 + vpalignr $4, %xmm0, %xmm1, %xmm5 + # rnd_0: 1 - 2 + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + andl %r12d, %eax + xorl %ecx, %edx + rorxl $13, %r8d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + addl %edx, %r15d + rorxl $2, %r8d, %edx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + vpsrld $3, %xmm5, %xmm8 + vpor %xmm6, %xmm7, %xmm7 + # rnd_0: 5 - 7 + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + addl %edx, %r15d + andl %eax, %ebx + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + addl %ebx, %r15d + # rnd_1: 0 - 0 + movl %r12d, %ebx + rorxl $11, %r11d, %ecx + addl 4(%rsp), %r14d + vpsrld $18, %xmm5, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + vpslld $14, %xmm5, %xmm5 + # rnd_1: 2 - 2 + andl %r11d, %ebx + xorl %ecx, %edx + rorxl $13, %r15d, %ecx + vpxor %xmm5, %xmm7, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r14d + rorxl $2, %r15d, %edx + xorl %r13d, %ebx + vpxor %xmm6, %xmm7, %xmm7 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + vpshufd $0xfa, %xmm3, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r8d, %ebx + addl %r14d, %r10d + vpxor %xmm8, %xmm7, %xmm5 + # rnd_1: 6 - 6 + xorl %r15d, %ebx + addl %edx, %r14d + andl %ebx, %eax + vpsrld $10, %xmm6, %xmm8 + # rnd_1: 7 - 7 + xorl %r8d, %eax + rorxl $6, %r10d, %edx + addl %eax, %r14d + # rnd_0: 0 - 0 + movl %r11d, %eax + rorxl $11, %r10d, %ecx + addl 8(%rsp), %r13d + vpsrlq $19, %xmm6, %xmm7 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm0, %xmm4, %xmm4 + # rnd_0: 2 - 2 + andl %r10d, %eax + xorl %ecx, %edx + rorxl $13, %r14d, %ecx + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 3 - 3 + addl %edx, %r13d + rorxl $2, %r14d, %edx + xorl %r12d, %eax + vpxor %xmm7, %xmm6, %xmm6 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + xorl %r14d, %eax + addl %edx, %r13d + andl %eax, %ebx + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + addl %ebx, %r13d + # rnd_1: 0 - 0 + movl %r10d, %ebx + rorxl $11, %r9d, %ecx + addl 12(%rsp), %r12d + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + vpsrld $10, %xmm6, %xmm9 + # rnd_1: 2 - 2 + andl %r9d, %ebx + xorl %ecx, %edx + rorxl $13, %r13d, %ecx + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r12d + rorxl $2, %r13d, %edx + xorl %r11d, %ebx + vpsrlq $0x11, %xmm6, %xmm6 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + vpxor %xmm7, %xmm6, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r14d, %ebx + addl %r12d, %r8d + vpxor %xmm6, %xmm9, %xmm9 + # rnd_1: 6 - 6 + xorl %r13d, %ebx + addl %edx, %r12d + andl %ebx, %eax + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + xorl %r14d, %eax + rorxl $6, %r8d, %edx + addl %eax, %r12d + vpaddd %xmm4, %xmm9, %xmm0 + # msg_sched done: 0-3 + # msg_sched: 4-7 + # rnd_0: 0 - 0 + movl %r9d, %eax + rorxl $11, %r8d, %ecx + addl 16(%rsp), %r11d + vpalignr $4, %xmm3, %xmm0, %xmm4 + vpalignr $4, %xmm1, %xmm2, %xmm5 + # rnd_0: 1 - 2 + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + andl %r8d, %eax + xorl %ecx, %edx + rorxl $13, %r12d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + addl %edx, %r11d + rorxl $2, %r12d, %edx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + vpsrld $3, %xmm5, %xmm8 + vpor %xmm6, %xmm7, %xmm7 + # rnd_0: 5 - 7 + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + addl %edx, %r11d + andl %eax, %ebx + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + addl %ebx, %r11d + # rnd_1: 0 - 0 + movl %r8d, %ebx + rorxl $11, %r15d, %ecx + addl 20(%rsp), %r10d + vpsrld $18, %xmm5, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + vpslld $14, %xmm5, %xmm5 + # rnd_1: 2 - 2 + andl %r15d, %ebx + xorl %ecx, %edx + rorxl $13, %r11d, %ecx + vpxor %xmm5, %xmm7, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r10d + rorxl $2, %r11d, %edx + xorl %r9d, %ebx + vpxor %xmm6, %xmm7, %xmm7 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + vpshufd $0xfa, %xmm0, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r12d, %ebx + addl %r10d, %r14d + vpxor %xmm8, %xmm7, %xmm5 + # rnd_1: 6 - 6 + xorl %r11d, %ebx + addl %edx, %r10d + andl %ebx, %eax + vpsrld $10, %xmm6, %xmm8 + # rnd_1: 7 - 7 + xorl %r12d, %eax + rorxl $6, %r14d, %edx + addl %eax, %r10d + # rnd_0: 0 - 0 + movl %r15d, %eax + rorxl $11, %r14d, %ecx + addl 24(%rsp), %r9d + vpsrlq $19, %xmm6, %xmm7 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm1, %xmm4, %xmm4 + # rnd_0: 2 - 2 + andl %r14d, %eax + xorl %ecx, %edx + rorxl $13, %r10d, %ecx + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 3 - 3 + addl %edx, %r9d + rorxl $2, %r10d, %edx + xorl %r8d, %eax + vpxor %xmm7, %xmm6, %xmm6 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + xorl %r10d, %eax + addl %edx, %r9d + andl %eax, %ebx + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + addl %ebx, %r9d + # rnd_1: 0 - 0 + movl %r14d, %ebx + rorxl $11, %r13d, %ecx + addl 28(%rsp), %r8d + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + vpsrld $10, %xmm6, %xmm9 + # rnd_1: 2 - 2 + andl %r13d, %ebx + xorl %ecx, %edx + rorxl $13, %r9d, %ecx + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r8d + rorxl $2, %r9d, %edx + xorl %r15d, %ebx + vpsrlq $0x11, %xmm6, %xmm6 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + vpxor %xmm7, %xmm6, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r10d, %ebx + addl %r8d, %r12d + vpxor %xmm6, %xmm9, %xmm9 + # rnd_1: 6 - 6 + xorl %r9d, %ebx + addl %edx, %r8d + andl %ebx, %eax + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + xorl %r10d, %eax + rorxl $6, %r12d, %edx + addl %eax, %r8d + vpaddd %xmm4, %xmm9, %xmm1 + # msg_sched done: 4-7 + # msg_sched: 8-11 + # rnd_0: 0 - 0 + movl %r13d, %eax + rorxl $11, %r12d, %ecx + addl 32(%rsp), %r15d + vpalignr $4, %xmm0, %xmm1, %xmm4 + vpalignr $4, %xmm2, %xmm3, %xmm5 + # rnd_0: 1 - 2 + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + andl %r12d, %eax + xorl %ecx, %edx + rorxl $13, %r8d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + addl %edx, %r15d + rorxl $2, %r8d, %edx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + vpsrld $3, %xmm5, %xmm8 + vpor %xmm6, %xmm7, %xmm7 + # rnd_0: 5 - 7 + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + addl %edx, %r15d + andl %eax, %ebx + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + addl %ebx, %r15d + # rnd_1: 0 - 0 + movl %r12d, %ebx + rorxl $11, %r11d, %ecx + addl 36(%rsp), %r14d + vpsrld $18, %xmm5, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + vpslld $14, %xmm5, %xmm5 + # rnd_1: 2 - 2 + andl %r11d, %ebx + xorl %ecx, %edx + rorxl $13, %r15d, %ecx + vpxor %xmm5, %xmm7, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r14d + rorxl $2, %r15d, %edx + xorl %r13d, %ebx + vpxor %xmm6, %xmm7, %xmm7 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + vpshufd $0xfa, %xmm1, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r8d, %ebx + addl %r14d, %r10d + vpxor %xmm8, %xmm7, %xmm5 + # rnd_1: 6 - 6 + xorl %r15d, %ebx + addl %edx, %r14d + andl %ebx, %eax + vpsrld $10, %xmm6, %xmm8 + # rnd_1: 7 - 7 + xorl %r8d, %eax + rorxl $6, %r10d, %edx + addl %eax, %r14d + # rnd_0: 0 - 0 + movl %r11d, %eax + rorxl $11, %r10d, %ecx + addl 40(%rsp), %r13d + vpsrlq $19, %xmm6, %xmm7 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm2, %xmm4, %xmm4 + # rnd_0: 2 - 2 + andl %r10d, %eax + xorl %ecx, %edx + rorxl $13, %r14d, %ecx + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 3 - 3 + addl %edx, %r13d + rorxl $2, %r14d, %edx + xorl %r12d, %eax + vpxor %xmm7, %xmm6, %xmm6 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + xorl %r14d, %eax + addl %edx, %r13d + andl %eax, %ebx + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + addl %ebx, %r13d + # rnd_1: 0 - 0 + movl %r10d, %ebx + rorxl $11, %r9d, %ecx + addl 44(%rsp), %r12d + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + vpsrld $10, %xmm6, %xmm9 + # rnd_1: 2 - 2 + andl %r9d, %ebx + xorl %ecx, %edx + rorxl $13, %r13d, %ecx + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r12d + rorxl $2, %r13d, %edx + xorl %r11d, %ebx + vpsrlq $0x11, %xmm6, %xmm6 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + vpxor %xmm7, %xmm6, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r14d, %ebx + addl %r12d, %r8d + vpxor %xmm6, %xmm9, %xmm9 + # rnd_1: 6 - 6 + xorl %r13d, %ebx + addl %edx, %r12d + andl %ebx, %eax + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + xorl %r14d, %eax + rorxl $6, %r8d, %edx + addl %eax, %r12d + vpaddd %xmm4, %xmm9, %xmm2 + # msg_sched done: 8-11 + # msg_sched: 12-15 + # rnd_0: 0 - 0 + movl %r9d, %eax + rorxl $11, %r8d, %ecx + addl 48(%rsp), %r11d + vpalignr $4, %xmm1, %xmm2, %xmm4 + vpalignr $4, %xmm3, %xmm0, %xmm5 + # rnd_0: 1 - 2 + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + andl %r8d, %eax + xorl %ecx, %edx + rorxl $13, %r12d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + addl %edx, %r11d + rorxl $2, %r12d, %edx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + vpsrld $3, %xmm5, %xmm8 + vpor %xmm6, %xmm7, %xmm7 + # rnd_0: 5 - 7 + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + addl %edx, %r11d + andl %eax, %ebx + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + addl %ebx, %r11d + # rnd_1: 0 - 0 + movl %r8d, %ebx + rorxl $11, %r15d, %ecx + addl 52(%rsp), %r10d + vpsrld $18, %xmm5, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + vpslld $14, %xmm5, %xmm5 + # rnd_1: 2 - 2 + andl %r15d, %ebx + xorl %ecx, %edx + rorxl $13, %r11d, %ecx + vpxor %xmm5, %xmm7, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r10d + rorxl $2, %r11d, %edx + xorl %r9d, %ebx + vpxor %xmm6, %xmm7, %xmm7 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + vpshufd $0xfa, %xmm2, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r12d, %ebx + addl %r10d, %r14d + vpxor %xmm8, %xmm7, %xmm5 + # rnd_1: 6 - 6 + xorl %r11d, %ebx + addl %edx, %r10d + andl %ebx, %eax + vpsrld $10, %xmm6, %xmm8 + # rnd_1: 7 - 7 + xorl %r12d, %eax + rorxl $6, %r14d, %edx + addl %eax, %r10d + # rnd_0: 0 - 0 + movl %r15d, %eax + rorxl $11, %r14d, %ecx + addl 56(%rsp), %r9d + vpsrlq $19, %xmm6, %xmm7 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm3, %xmm4, %xmm4 + # rnd_0: 2 - 2 + andl %r14d, %eax + xorl %ecx, %edx + rorxl $13, %r10d, %ecx + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 3 - 3 + addl %edx, %r9d + rorxl $2, %r10d, %edx + xorl %r8d, %eax + vpxor %xmm7, %xmm6, %xmm6 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + xorl %r10d, %eax + addl %edx, %r9d + andl %eax, %ebx + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + addl %ebx, %r9d + # rnd_1: 0 - 0 + movl %r14d, %ebx + rorxl $11, %r13d, %ecx + addl 60(%rsp), %r8d + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + vpsrld $10, %xmm6, %xmm9 + # rnd_1: 2 - 2 + andl %r13d, %ebx + xorl %ecx, %edx + rorxl $13, %r9d, %ecx + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r8d + rorxl $2, %r9d, %edx + xorl %r15d, %ebx + vpsrlq $0x11, %xmm6, %xmm6 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + vpxor %xmm7, %xmm6, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r10d, %ebx + addl %r8d, %r12d + vpxor %xmm6, %xmm9, %xmm9 + # rnd_1: 6 - 6 + xorl %r9d, %ebx + addl %edx, %r8d + andl %ebx, %eax + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + xorl %r10d, %eax + rorxl $6, %r12d, %edx + addl %eax, %r8d + vpaddd %xmm4, %xmm9, %xmm3 + # msg_sched done: 12-15 + # set_w_k_xfer_4: 8 + vpaddd 128+L_avx1_rorx_sha256_k(%rip), %xmm0, %xmm4 + vpaddd 144+L_avx1_rorx_sha256_k(%rip), %xmm1, %xmm5 + vmovdqu %xmm4, (%rsp) + vmovdqu %xmm5, 16(%rsp) + vpaddd 160+L_avx1_rorx_sha256_k(%rip), %xmm2, %xmm6 + vpaddd 176+L_avx1_rorx_sha256_k(%rip), %xmm3, %xmm7 + vmovdqu %xmm6, 32(%rsp) + vmovdqu %xmm7, 48(%rsp) + # msg_sched: 0-3 + # rnd_0: 0 - 0 + movl %r13d, %eax + rorxl $11, %r12d, %ecx + addl (%rsp), %r15d + vpalignr $4, %xmm2, %xmm3, %xmm4 + vpalignr $4, %xmm0, %xmm1, %xmm5 + # rnd_0: 1 - 2 + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + andl %r12d, %eax + xorl %ecx, %edx + rorxl $13, %r8d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + addl %edx, %r15d + rorxl $2, %r8d, %edx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + vpsrld $3, %xmm5, %xmm8 + vpor %xmm6, %xmm7, %xmm7 + # rnd_0: 5 - 7 + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + addl %edx, %r15d + andl %eax, %ebx + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + addl %ebx, %r15d + # rnd_1: 0 - 0 + movl %r12d, %ebx + rorxl $11, %r11d, %ecx + addl 4(%rsp), %r14d + vpsrld $18, %xmm5, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + vpslld $14, %xmm5, %xmm5 + # rnd_1: 2 - 2 + andl %r11d, %ebx + xorl %ecx, %edx + rorxl $13, %r15d, %ecx + vpxor %xmm5, %xmm7, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r14d + rorxl $2, %r15d, %edx + xorl %r13d, %ebx + vpxor %xmm6, %xmm7, %xmm7 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + vpshufd $0xfa, %xmm3, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r8d, %ebx + addl %r14d, %r10d + vpxor %xmm8, %xmm7, %xmm5 + # rnd_1: 6 - 6 + xorl %r15d, %ebx + addl %edx, %r14d + andl %ebx, %eax + vpsrld $10, %xmm6, %xmm8 + # rnd_1: 7 - 7 + xorl %r8d, %eax + rorxl $6, %r10d, %edx + addl %eax, %r14d + # rnd_0: 0 - 0 + movl %r11d, %eax + rorxl $11, %r10d, %ecx + addl 8(%rsp), %r13d + vpsrlq $19, %xmm6, %xmm7 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm0, %xmm4, %xmm4 + # rnd_0: 2 - 2 + andl %r10d, %eax + xorl %ecx, %edx + rorxl $13, %r14d, %ecx + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 3 - 3 + addl %edx, %r13d + rorxl $2, %r14d, %edx + xorl %r12d, %eax + vpxor %xmm7, %xmm6, %xmm6 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + xorl %r14d, %eax + addl %edx, %r13d + andl %eax, %ebx + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + addl %ebx, %r13d + # rnd_1: 0 - 0 + movl %r10d, %ebx + rorxl $11, %r9d, %ecx + addl 12(%rsp), %r12d + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + vpsrld $10, %xmm6, %xmm9 + # rnd_1: 2 - 2 + andl %r9d, %ebx + xorl %ecx, %edx + rorxl $13, %r13d, %ecx + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r12d + rorxl $2, %r13d, %edx + xorl %r11d, %ebx + vpsrlq $0x11, %xmm6, %xmm6 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + vpxor %xmm7, %xmm6, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r14d, %ebx + addl %r12d, %r8d + vpxor %xmm6, %xmm9, %xmm9 + # rnd_1: 6 - 6 + xorl %r13d, %ebx + addl %edx, %r12d + andl %ebx, %eax + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + xorl %r14d, %eax + rorxl $6, %r8d, %edx + addl %eax, %r12d + vpaddd %xmm4, %xmm9, %xmm0 + # msg_sched done: 0-3 + # msg_sched: 4-7 + # rnd_0: 0 - 0 + movl %r9d, %eax + rorxl $11, %r8d, %ecx + addl 16(%rsp), %r11d + vpalignr $4, %xmm3, %xmm0, %xmm4 + vpalignr $4, %xmm1, %xmm2, %xmm5 + # rnd_0: 1 - 2 + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + andl %r8d, %eax + xorl %ecx, %edx + rorxl $13, %r12d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + addl %edx, %r11d + rorxl $2, %r12d, %edx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + vpsrld $3, %xmm5, %xmm8 + vpor %xmm6, %xmm7, %xmm7 + # rnd_0: 5 - 7 + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + addl %edx, %r11d + andl %eax, %ebx + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + addl %ebx, %r11d + # rnd_1: 0 - 0 + movl %r8d, %ebx + rorxl $11, %r15d, %ecx + addl 20(%rsp), %r10d + vpsrld $18, %xmm5, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + vpslld $14, %xmm5, %xmm5 + # rnd_1: 2 - 2 + andl %r15d, %ebx + xorl %ecx, %edx + rorxl $13, %r11d, %ecx + vpxor %xmm5, %xmm7, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r10d + rorxl $2, %r11d, %edx + xorl %r9d, %ebx + vpxor %xmm6, %xmm7, %xmm7 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + vpshufd $0xfa, %xmm0, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r12d, %ebx + addl %r10d, %r14d + vpxor %xmm8, %xmm7, %xmm5 + # rnd_1: 6 - 6 + xorl %r11d, %ebx + addl %edx, %r10d + andl %ebx, %eax + vpsrld $10, %xmm6, %xmm8 + # rnd_1: 7 - 7 + xorl %r12d, %eax + rorxl $6, %r14d, %edx + addl %eax, %r10d + # rnd_0: 0 - 0 + movl %r15d, %eax + rorxl $11, %r14d, %ecx + addl 24(%rsp), %r9d + vpsrlq $19, %xmm6, %xmm7 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm1, %xmm4, %xmm4 + # rnd_0: 2 - 2 + andl %r14d, %eax + xorl %ecx, %edx + rorxl $13, %r10d, %ecx + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 3 - 3 + addl %edx, %r9d + rorxl $2, %r10d, %edx + xorl %r8d, %eax + vpxor %xmm7, %xmm6, %xmm6 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + xorl %r10d, %eax + addl %edx, %r9d + andl %eax, %ebx + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + addl %ebx, %r9d + # rnd_1: 0 - 0 + movl %r14d, %ebx + rorxl $11, %r13d, %ecx + addl 28(%rsp), %r8d + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + vpsrld $10, %xmm6, %xmm9 + # rnd_1: 2 - 2 + andl %r13d, %ebx + xorl %ecx, %edx + rorxl $13, %r9d, %ecx + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r8d + rorxl $2, %r9d, %edx + xorl %r15d, %ebx + vpsrlq $0x11, %xmm6, %xmm6 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + vpxor %xmm7, %xmm6, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r10d, %ebx + addl %r8d, %r12d + vpxor %xmm6, %xmm9, %xmm9 + # rnd_1: 6 - 6 + xorl %r9d, %ebx + addl %edx, %r8d + andl %ebx, %eax + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + xorl %r10d, %eax + rorxl $6, %r12d, %edx + addl %eax, %r8d + vpaddd %xmm4, %xmm9, %xmm1 + # msg_sched done: 4-7 + # msg_sched: 8-11 + # rnd_0: 0 - 0 + movl %r13d, %eax + rorxl $11, %r12d, %ecx + addl 32(%rsp), %r15d + vpalignr $4, %xmm0, %xmm1, %xmm4 + vpalignr $4, %xmm2, %xmm3, %xmm5 + # rnd_0: 1 - 2 + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + andl %r12d, %eax + xorl %ecx, %edx + rorxl $13, %r8d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + addl %edx, %r15d + rorxl $2, %r8d, %edx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + vpsrld $3, %xmm5, %xmm8 + vpor %xmm6, %xmm7, %xmm7 + # rnd_0: 5 - 7 + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + addl %edx, %r15d + andl %eax, %ebx + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + addl %ebx, %r15d + # rnd_1: 0 - 0 + movl %r12d, %ebx + rorxl $11, %r11d, %ecx + addl 36(%rsp), %r14d + vpsrld $18, %xmm5, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + vpslld $14, %xmm5, %xmm5 + # rnd_1: 2 - 2 + andl %r11d, %ebx + xorl %ecx, %edx + rorxl $13, %r15d, %ecx + vpxor %xmm5, %xmm7, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r14d + rorxl $2, %r15d, %edx + xorl %r13d, %ebx + vpxor %xmm6, %xmm7, %xmm7 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + vpshufd $0xfa, %xmm1, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r8d, %ebx + addl %r14d, %r10d + vpxor %xmm8, %xmm7, %xmm5 + # rnd_1: 6 - 6 + xorl %r15d, %ebx + addl %edx, %r14d + andl %ebx, %eax + vpsrld $10, %xmm6, %xmm8 + # rnd_1: 7 - 7 + xorl %r8d, %eax + rorxl $6, %r10d, %edx + addl %eax, %r14d + # rnd_0: 0 - 0 + movl %r11d, %eax + rorxl $11, %r10d, %ecx + addl 40(%rsp), %r13d + vpsrlq $19, %xmm6, %xmm7 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm2, %xmm4, %xmm4 + # rnd_0: 2 - 2 + andl %r10d, %eax + xorl %ecx, %edx + rorxl $13, %r14d, %ecx + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 3 - 3 + addl %edx, %r13d + rorxl $2, %r14d, %edx + xorl %r12d, %eax + vpxor %xmm7, %xmm6, %xmm6 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + xorl %r14d, %eax + addl %edx, %r13d + andl %eax, %ebx + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + addl %ebx, %r13d + # rnd_1: 0 - 0 + movl %r10d, %ebx + rorxl $11, %r9d, %ecx + addl 44(%rsp), %r12d + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + vpsrld $10, %xmm6, %xmm9 + # rnd_1: 2 - 2 + andl %r9d, %ebx + xorl %ecx, %edx + rorxl $13, %r13d, %ecx + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r12d + rorxl $2, %r13d, %edx + xorl %r11d, %ebx + vpsrlq $0x11, %xmm6, %xmm6 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + vpxor %xmm7, %xmm6, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r14d, %ebx + addl %r12d, %r8d + vpxor %xmm6, %xmm9, %xmm9 + # rnd_1: 6 - 6 + xorl %r13d, %ebx + addl %edx, %r12d + andl %ebx, %eax + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + xorl %r14d, %eax + rorxl $6, %r8d, %edx + addl %eax, %r12d + vpaddd %xmm4, %xmm9, %xmm2 + # msg_sched done: 8-11 + # msg_sched: 12-15 + # rnd_0: 0 - 0 + movl %r9d, %eax + rorxl $11, %r8d, %ecx + addl 48(%rsp), %r11d + vpalignr $4, %xmm1, %xmm2, %xmm4 + vpalignr $4, %xmm3, %xmm0, %xmm5 + # rnd_0: 1 - 2 + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + andl %r8d, %eax + xorl %ecx, %edx + rorxl $13, %r12d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + addl %edx, %r11d + rorxl $2, %r12d, %edx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + vpsrld $3, %xmm5, %xmm8 + vpor %xmm6, %xmm7, %xmm7 + # rnd_0: 5 - 7 + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + addl %edx, %r11d + andl %eax, %ebx + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + addl %ebx, %r11d + # rnd_1: 0 - 0 + movl %r8d, %ebx + rorxl $11, %r15d, %ecx + addl 52(%rsp), %r10d + vpsrld $18, %xmm5, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + vpslld $14, %xmm5, %xmm5 + # rnd_1: 2 - 2 + andl %r15d, %ebx + xorl %ecx, %edx + rorxl $13, %r11d, %ecx + vpxor %xmm5, %xmm7, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r10d + rorxl $2, %r11d, %edx + xorl %r9d, %ebx + vpxor %xmm6, %xmm7, %xmm7 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + vpshufd $0xfa, %xmm2, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r12d, %ebx + addl %r10d, %r14d + vpxor %xmm8, %xmm7, %xmm5 + # rnd_1: 6 - 6 + xorl %r11d, %ebx + addl %edx, %r10d + andl %ebx, %eax + vpsrld $10, %xmm6, %xmm8 + # rnd_1: 7 - 7 + xorl %r12d, %eax + rorxl $6, %r14d, %edx + addl %eax, %r10d + # rnd_0: 0 - 0 + movl %r15d, %eax + rorxl $11, %r14d, %ecx + addl 56(%rsp), %r9d + vpsrlq $19, %xmm6, %xmm7 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm3, %xmm4, %xmm4 + # rnd_0: 2 - 2 + andl %r14d, %eax + xorl %ecx, %edx + rorxl $13, %r10d, %ecx + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 3 - 3 + addl %edx, %r9d + rorxl $2, %r10d, %edx + xorl %r8d, %eax + vpxor %xmm7, %xmm6, %xmm6 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + xorl %r10d, %eax + addl %edx, %r9d + andl %eax, %ebx + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + addl %ebx, %r9d + # rnd_1: 0 - 0 + movl %r14d, %ebx + rorxl $11, %r13d, %ecx + addl 60(%rsp), %r8d + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + vpsrld $10, %xmm6, %xmm9 + # rnd_1: 2 - 2 + andl %r13d, %ebx + xorl %ecx, %edx + rorxl $13, %r9d, %ecx + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r8d + rorxl $2, %r9d, %edx + xorl %r15d, %ebx + vpsrlq $0x11, %xmm6, %xmm6 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + vpxor %xmm7, %xmm6, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r10d, %ebx + addl %r8d, %r12d + vpxor %xmm6, %xmm9, %xmm9 + # rnd_1: 6 - 6 + xorl %r9d, %ebx + addl %edx, %r8d + andl %ebx, %eax + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + xorl %r10d, %eax + rorxl $6, %r12d, %edx + addl %eax, %r8d + vpaddd %xmm4, %xmm9, %xmm3 + # msg_sched done: 12-15 + # set_w_k_xfer_4: 12 + vpaddd 192+L_avx1_rorx_sha256_k(%rip), %xmm0, %xmm4 + vpaddd 208+L_avx1_rorx_sha256_k(%rip), %xmm1, %xmm5 + vmovdqu %xmm4, (%rsp) + vmovdqu %xmm5, 16(%rsp) + vpaddd 224+L_avx1_rorx_sha256_k(%rip), %xmm2, %xmm6 + vpaddd 240+L_avx1_rorx_sha256_k(%rip), %xmm3, %xmm7 + vmovdqu %xmm6, 32(%rsp) + vmovdqu %xmm7, 48(%rsp) + xorl %eax, %eax + # rnd_all_4: 0-3 + rorxl $6, %r12d, %edx + rorxl $11, %r12d, %ecx + addl %eax, %r8d + addl (%rsp), %r15d + movl %r13d, %eax + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + xorl %ecx, %edx + andl %r12d, %eax + addl %edx, %r15d + rorxl $2, %r8d, %edx + rorxl $13, %r8d, %ecx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + andl %eax, %ebx + addl %edx, %r15d + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + rorxl $11, %r11d, %ecx + addl %ebx, %r15d + addl 4(%rsp), %r14d + movl %r12d, %ebx + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + xorl %ecx, %edx + andl %r11d, %ebx + addl %edx, %r14d + rorxl $2, %r15d, %edx + rorxl $13, %r15d, %ecx + xorl %r13d, %ebx + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + xorl %ecx, %edx + movl %r8d, %ebx + addl %r14d, %r10d + xorl %r15d, %ebx + andl %ebx, %eax + addl %edx, %r14d + xorl %r8d, %eax + rorxl $6, %r10d, %edx + rorxl $11, %r10d, %ecx + addl %eax, %r14d + addl 8(%rsp), %r13d + movl %r11d, %eax + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + xorl %ecx, %edx + andl %r10d, %eax + addl %edx, %r13d + rorxl $2, %r14d, %edx + rorxl $13, %r14d, %ecx + xorl %r12d, %eax + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + xorl %r14d, %eax + andl %eax, %ebx + addl %edx, %r13d + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + rorxl $11, %r9d, %ecx + addl %ebx, %r13d + addl 12(%rsp), %r12d + movl %r10d, %ebx + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + xorl %ecx, %edx + andl %r9d, %ebx + addl %edx, %r12d + rorxl $2, %r13d, %edx + rorxl $13, %r13d, %ecx + xorl %r11d, %ebx + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + xorl %ecx, %edx + movl %r14d, %ebx + addl %r12d, %r8d + xorl %r13d, %ebx + andl %ebx, %eax + addl %edx, %r12d + xorl %r14d, %eax + # rnd_all_4: 1-4 + rorxl $6, %r8d, %edx + rorxl $11, %r8d, %ecx + addl %eax, %r12d + addl 16(%rsp), %r11d + movl %r9d, %eax + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + xorl %ecx, %edx + andl %r8d, %eax + addl %edx, %r11d + rorxl $2, %r12d, %edx + rorxl $13, %r12d, %ecx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + andl %eax, %ebx + addl %edx, %r11d + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + rorxl $11, %r15d, %ecx + addl %ebx, %r11d + addl 20(%rsp), %r10d + movl %r8d, %ebx + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + xorl %ecx, %edx + andl %r15d, %ebx + addl %edx, %r10d + rorxl $2, %r11d, %edx + rorxl $13, %r11d, %ecx + xorl %r9d, %ebx + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + xorl %ecx, %edx + movl %r12d, %ebx + addl %r10d, %r14d + xorl %r11d, %ebx + andl %ebx, %eax + addl %edx, %r10d + xorl %r12d, %eax + rorxl $6, %r14d, %edx + rorxl $11, %r14d, %ecx + addl %eax, %r10d + addl 24(%rsp), %r9d + movl %r15d, %eax + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + xorl %ecx, %edx + andl %r14d, %eax + addl %edx, %r9d + rorxl $2, %r10d, %edx + rorxl $13, %r10d, %ecx + xorl %r8d, %eax + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + xorl %r10d, %eax + andl %eax, %ebx + addl %edx, %r9d + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + rorxl $11, %r13d, %ecx + addl %ebx, %r9d + addl 28(%rsp), %r8d + movl %r14d, %ebx + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + xorl %ecx, %edx + andl %r13d, %ebx + addl %edx, %r8d + rorxl $2, %r9d, %edx + rorxl $13, %r9d, %ecx + xorl %r15d, %ebx + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + xorl %ecx, %edx + movl %r10d, %ebx + addl %r8d, %r12d + xorl %r9d, %ebx + andl %ebx, %eax + addl %edx, %r8d + xorl %r10d, %eax + # rnd_all_4: 2-5 + rorxl $6, %r12d, %edx + rorxl $11, %r12d, %ecx + addl %eax, %r8d + addl 32(%rsp), %r15d + movl %r13d, %eax + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + xorl %ecx, %edx + andl %r12d, %eax + addl %edx, %r15d + rorxl $2, %r8d, %edx + rorxl $13, %r8d, %ecx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + andl %eax, %ebx + addl %edx, %r15d + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + rorxl $11, %r11d, %ecx + addl %ebx, %r15d + addl 36(%rsp), %r14d + movl %r12d, %ebx + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + xorl %ecx, %edx + andl %r11d, %ebx + addl %edx, %r14d + rorxl $2, %r15d, %edx + rorxl $13, %r15d, %ecx + xorl %r13d, %ebx + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + xorl %ecx, %edx + movl %r8d, %ebx + addl %r14d, %r10d + xorl %r15d, %ebx + andl %ebx, %eax + addl %edx, %r14d + xorl %r8d, %eax + rorxl $6, %r10d, %edx + rorxl $11, %r10d, %ecx + addl %eax, %r14d + addl 40(%rsp), %r13d + movl %r11d, %eax + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + xorl %ecx, %edx + andl %r10d, %eax + addl %edx, %r13d + rorxl $2, %r14d, %edx + rorxl $13, %r14d, %ecx + xorl %r12d, %eax + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + xorl %r14d, %eax + andl %eax, %ebx + addl %edx, %r13d + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + rorxl $11, %r9d, %ecx + addl %ebx, %r13d + addl 44(%rsp), %r12d + movl %r10d, %ebx + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + xorl %ecx, %edx + andl %r9d, %ebx + addl %edx, %r12d + rorxl $2, %r13d, %edx + rorxl $13, %r13d, %ecx + xorl %r11d, %ebx + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + xorl %ecx, %edx + movl %r14d, %ebx + addl %r12d, %r8d + xorl %r13d, %ebx + andl %ebx, %eax + addl %edx, %r12d + xorl %r14d, %eax + # rnd_all_4: 3-6 + rorxl $6, %r8d, %edx + rorxl $11, %r8d, %ecx + addl %eax, %r12d + addl 48(%rsp), %r11d + movl %r9d, %eax + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + xorl %ecx, %edx + andl %r8d, %eax + addl %edx, %r11d + rorxl $2, %r12d, %edx + rorxl $13, %r12d, %ecx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + andl %eax, %ebx + addl %edx, %r11d + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + rorxl $11, %r15d, %ecx + addl %ebx, %r11d + addl 52(%rsp), %r10d + movl %r8d, %ebx + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + xorl %ecx, %edx + andl %r15d, %ebx + addl %edx, %r10d + rorxl $2, %r11d, %edx + rorxl $13, %r11d, %ecx + xorl %r9d, %ebx + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + xorl %ecx, %edx + movl %r12d, %ebx + addl %r10d, %r14d + xorl %r11d, %ebx + andl %ebx, %eax + addl %edx, %r10d + xorl %r12d, %eax + rorxl $6, %r14d, %edx + rorxl $11, %r14d, %ecx + addl %eax, %r10d + addl 56(%rsp), %r9d + movl %r15d, %eax + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + xorl %ecx, %edx + andl %r14d, %eax + addl %edx, %r9d + rorxl $2, %r10d, %edx + rorxl $13, %r10d, %ecx + xorl %r8d, %eax + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + xorl %r10d, %eax + andl %eax, %ebx + addl %edx, %r9d + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + rorxl $11, %r13d, %ecx + addl %ebx, %r9d + addl 60(%rsp), %r8d + movl %r14d, %ebx + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + xorl %ecx, %edx + andl %r13d, %ebx + addl %edx, %r8d + rorxl $2, %r9d, %edx + rorxl $13, %r9d, %ecx + xorl %r15d, %ebx + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + xorl %ecx, %edx + movl %r10d, %ebx + addl %r8d, %r12d + xorl %r9d, %ebx + andl %ebx, %eax + addl %edx, %r8d + xorl %r10d, %eax + addl %eax, %r8d + addl %r8d, (%rdi) + addl %r9d, 4(%rdi) + addl %r10d, 8(%rdi) + addl %r11d, 12(%rdi) + addl %r12d, 16(%rdi) + addl %r13d, 20(%rdi) + addl %r14d, 24(%rdi) + addl %r15d, 28(%rdi) + xorq %rax, %rax + vzeroupper + addq $0x40, %rsp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size Transform_Sha256_AVX1_RORX,.-Transform_Sha256_AVX1_RORX +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl Transform_Sha256_AVX1_RORX_Len +.type Transform_Sha256_AVX1_RORX_Len,@function +.align 4 +Transform_Sha256_AVX1_RORX_Len: +#else +.section __TEXT,__text +.globl _Transform_Sha256_AVX1_RORX_Len +.p2align 2 +_Transform_Sha256_AVX1_RORX_Len: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + pushq %rbp + movq %rsi, %rbp + movq %rdx, %rsi + subq $0x40, %rsp + vmovdqa L_avx1_rorx_sha256_flip_mask(%rip), %xmm13 + vmovdqa L_avx1_rorx_sha256_shuf_00BA(%rip), %xmm11 + vmovdqa L_avx1_rorx_sha256_shuf_DC00(%rip), %xmm12 + movl (%rdi), %r8d + movl 4(%rdi), %r9d + movl 8(%rdi), %r10d + movl 12(%rdi), %r11d + movl 16(%rdi), %r12d + movl 20(%rdi), %r13d + movl 24(%rdi), %r14d + movl 28(%rdi), %r15d + # Start of loop processing a block +L_sha256_len_avx1_len_rorx_start: + # X0, X1, X2, X3 = W[0..15] + vmovdqu (%rbp), %xmm0 + vmovdqu 16(%rbp), %xmm1 + vpshufb %xmm13, %xmm0, %xmm0 + vpshufb %xmm13, %xmm1, %xmm1 + vmovdqu 32(%rbp), %xmm2 + vmovdqu 48(%rbp), %xmm3 + vpshufb %xmm13, %xmm2, %xmm2 + vpshufb %xmm13, %xmm3, %xmm3 + # set_w_k_xfer_4: 0 + vpaddd 0+L_avx1_rorx_sha256_k(%rip), %xmm0, %xmm4 + vpaddd 16+L_avx1_rorx_sha256_k(%rip), %xmm1, %xmm5 + vmovdqu %xmm4, (%rsp) + vmovdqu %xmm5, 16(%rsp) + vpaddd 32+L_avx1_rorx_sha256_k(%rip), %xmm2, %xmm6 + vpaddd 48+L_avx1_rorx_sha256_k(%rip), %xmm3, %xmm7 + vmovdqu %xmm6, 32(%rsp) + vmovdqu %xmm7, 48(%rsp) + movl %r9d, %ebx + rorxl $6, %r12d, %edx + xorl %r10d, %ebx + # msg_sched: 0-3 + # rnd_0: 0 - 0 + movl %r13d, %eax + rorxl $11, %r12d, %ecx + addl (%rsp), %r15d + vpalignr $4, %xmm2, %xmm3, %xmm4 + vpalignr $4, %xmm0, %xmm1, %xmm5 + # rnd_0: 1 - 2 + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + andl %r12d, %eax + xorl %ecx, %edx + rorxl $13, %r8d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + addl %edx, %r15d + rorxl $2, %r8d, %edx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + vpsrld $3, %xmm5, %xmm8 + vpor %xmm6, %xmm7, %xmm7 + # rnd_0: 5 - 7 + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + addl %edx, %r15d + andl %eax, %ebx + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + addl %ebx, %r15d + # rnd_1: 0 - 0 + movl %r12d, %ebx + rorxl $11, %r11d, %ecx + addl 4(%rsp), %r14d + vpsrld $18, %xmm5, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + vpslld $14, %xmm5, %xmm5 + # rnd_1: 2 - 2 + andl %r11d, %ebx + xorl %ecx, %edx + rorxl $13, %r15d, %ecx + vpxor %xmm5, %xmm7, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r14d + rorxl $2, %r15d, %edx + xorl %r13d, %ebx + vpxor %xmm6, %xmm7, %xmm7 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + vpshufd $0xfa, %xmm3, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r8d, %ebx + addl %r14d, %r10d + vpxor %xmm8, %xmm7, %xmm5 + # rnd_1: 6 - 6 + xorl %r15d, %ebx + addl %edx, %r14d + andl %ebx, %eax + vpsrld $10, %xmm6, %xmm8 + # rnd_1: 7 - 7 + xorl %r8d, %eax + rorxl $6, %r10d, %edx + addl %eax, %r14d + # rnd_0: 0 - 0 + movl %r11d, %eax + rorxl $11, %r10d, %ecx + addl 8(%rsp), %r13d + vpsrlq $19, %xmm6, %xmm7 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm0, %xmm4, %xmm4 + # rnd_0: 2 - 2 + andl %r10d, %eax + xorl %ecx, %edx + rorxl $13, %r14d, %ecx + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 3 - 3 + addl %edx, %r13d + rorxl $2, %r14d, %edx + xorl %r12d, %eax + vpxor %xmm7, %xmm6, %xmm6 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + xorl %r14d, %eax + addl %edx, %r13d + andl %eax, %ebx + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + addl %ebx, %r13d + # rnd_1: 0 - 0 + movl %r10d, %ebx + rorxl $11, %r9d, %ecx + addl 12(%rsp), %r12d + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + vpsrld $10, %xmm6, %xmm9 + # rnd_1: 2 - 2 + andl %r9d, %ebx + xorl %ecx, %edx + rorxl $13, %r13d, %ecx + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r12d + rorxl $2, %r13d, %edx + xorl %r11d, %ebx + vpsrlq $0x11, %xmm6, %xmm6 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + vpxor %xmm7, %xmm6, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r14d, %ebx + addl %r12d, %r8d + vpxor %xmm6, %xmm9, %xmm9 + # rnd_1: 6 - 6 + xorl %r13d, %ebx + addl %edx, %r12d + andl %ebx, %eax + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + xorl %r14d, %eax + rorxl $6, %r8d, %edx + addl %eax, %r12d + vpaddd %xmm4, %xmm9, %xmm0 + # msg_sched done: 0-3 + # msg_sched: 4-7 + # rnd_0: 0 - 0 + movl %r9d, %eax + rorxl $11, %r8d, %ecx + addl 16(%rsp), %r11d + vpalignr $4, %xmm3, %xmm0, %xmm4 + vpalignr $4, %xmm1, %xmm2, %xmm5 + # rnd_0: 1 - 2 + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + andl %r8d, %eax + xorl %ecx, %edx + rorxl $13, %r12d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + addl %edx, %r11d + rorxl $2, %r12d, %edx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + vpsrld $3, %xmm5, %xmm8 + vpor %xmm6, %xmm7, %xmm7 + # rnd_0: 5 - 7 + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + addl %edx, %r11d + andl %eax, %ebx + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + addl %ebx, %r11d + # rnd_1: 0 - 0 + movl %r8d, %ebx + rorxl $11, %r15d, %ecx + addl 20(%rsp), %r10d + vpsrld $18, %xmm5, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + vpslld $14, %xmm5, %xmm5 + # rnd_1: 2 - 2 + andl %r15d, %ebx + xorl %ecx, %edx + rorxl $13, %r11d, %ecx + vpxor %xmm5, %xmm7, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r10d + rorxl $2, %r11d, %edx + xorl %r9d, %ebx + vpxor %xmm6, %xmm7, %xmm7 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + vpshufd $0xfa, %xmm0, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r12d, %ebx + addl %r10d, %r14d + vpxor %xmm8, %xmm7, %xmm5 + # rnd_1: 6 - 6 + xorl %r11d, %ebx + addl %edx, %r10d + andl %ebx, %eax + vpsrld $10, %xmm6, %xmm8 + # rnd_1: 7 - 7 + xorl %r12d, %eax + rorxl $6, %r14d, %edx + addl %eax, %r10d + # rnd_0: 0 - 0 + movl %r15d, %eax + rorxl $11, %r14d, %ecx + addl 24(%rsp), %r9d + vpsrlq $19, %xmm6, %xmm7 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm1, %xmm4, %xmm4 + # rnd_0: 2 - 2 + andl %r14d, %eax + xorl %ecx, %edx + rorxl $13, %r10d, %ecx + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 3 - 3 + addl %edx, %r9d + rorxl $2, %r10d, %edx + xorl %r8d, %eax + vpxor %xmm7, %xmm6, %xmm6 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + xorl %r10d, %eax + addl %edx, %r9d + andl %eax, %ebx + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + addl %ebx, %r9d + # rnd_1: 0 - 0 + movl %r14d, %ebx + rorxl $11, %r13d, %ecx + addl 28(%rsp), %r8d + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + vpsrld $10, %xmm6, %xmm9 + # rnd_1: 2 - 2 + andl %r13d, %ebx + xorl %ecx, %edx + rorxl $13, %r9d, %ecx + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r8d + rorxl $2, %r9d, %edx + xorl %r15d, %ebx + vpsrlq $0x11, %xmm6, %xmm6 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + vpxor %xmm7, %xmm6, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r10d, %ebx + addl %r8d, %r12d + vpxor %xmm6, %xmm9, %xmm9 + # rnd_1: 6 - 6 + xorl %r9d, %ebx + addl %edx, %r8d + andl %ebx, %eax + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + xorl %r10d, %eax + rorxl $6, %r12d, %edx + addl %eax, %r8d + vpaddd %xmm4, %xmm9, %xmm1 + # msg_sched done: 4-7 + # msg_sched: 8-11 + # rnd_0: 0 - 0 + movl %r13d, %eax + rorxl $11, %r12d, %ecx + addl 32(%rsp), %r15d + vpalignr $4, %xmm0, %xmm1, %xmm4 + vpalignr $4, %xmm2, %xmm3, %xmm5 + # rnd_0: 1 - 2 + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + andl %r12d, %eax + xorl %ecx, %edx + rorxl $13, %r8d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + addl %edx, %r15d + rorxl $2, %r8d, %edx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + vpsrld $3, %xmm5, %xmm8 + vpor %xmm6, %xmm7, %xmm7 + # rnd_0: 5 - 7 + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + addl %edx, %r15d + andl %eax, %ebx + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + addl %ebx, %r15d + # rnd_1: 0 - 0 + movl %r12d, %ebx + rorxl $11, %r11d, %ecx + addl 36(%rsp), %r14d + vpsrld $18, %xmm5, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + vpslld $14, %xmm5, %xmm5 + # rnd_1: 2 - 2 + andl %r11d, %ebx + xorl %ecx, %edx + rorxl $13, %r15d, %ecx + vpxor %xmm5, %xmm7, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r14d + rorxl $2, %r15d, %edx + xorl %r13d, %ebx + vpxor %xmm6, %xmm7, %xmm7 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + vpshufd $0xfa, %xmm1, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r8d, %ebx + addl %r14d, %r10d + vpxor %xmm8, %xmm7, %xmm5 + # rnd_1: 6 - 6 + xorl %r15d, %ebx + addl %edx, %r14d + andl %ebx, %eax + vpsrld $10, %xmm6, %xmm8 + # rnd_1: 7 - 7 + xorl %r8d, %eax + rorxl $6, %r10d, %edx + addl %eax, %r14d + # rnd_0: 0 - 0 + movl %r11d, %eax + rorxl $11, %r10d, %ecx + addl 40(%rsp), %r13d + vpsrlq $19, %xmm6, %xmm7 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm2, %xmm4, %xmm4 + # rnd_0: 2 - 2 + andl %r10d, %eax + xorl %ecx, %edx + rorxl $13, %r14d, %ecx + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 3 - 3 + addl %edx, %r13d + rorxl $2, %r14d, %edx + xorl %r12d, %eax + vpxor %xmm7, %xmm6, %xmm6 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + xorl %r14d, %eax + addl %edx, %r13d + andl %eax, %ebx + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + addl %ebx, %r13d + # rnd_1: 0 - 0 + movl %r10d, %ebx + rorxl $11, %r9d, %ecx + addl 44(%rsp), %r12d + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + vpsrld $10, %xmm6, %xmm9 + # rnd_1: 2 - 2 + andl %r9d, %ebx + xorl %ecx, %edx + rorxl $13, %r13d, %ecx + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r12d + rorxl $2, %r13d, %edx + xorl %r11d, %ebx + vpsrlq $0x11, %xmm6, %xmm6 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + vpxor %xmm7, %xmm6, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r14d, %ebx + addl %r12d, %r8d + vpxor %xmm6, %xmm9, %xmm9 + # rnd_1: 6 - 6 + xorl %r13d, %ebx + addl %edx, %r12d + andl %ebx, %eax + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + xorl %r14d, %eax + rorxl $6, %r8d, %edx + addl %eax, %r12d + vpaddd %xmm4, %xmm9, %xmm2 + # msg_sched done: 8-11 + # msg_sched: 12-15 + # rnd_0: 0 - 0 + movl %r9d, %eax + rorxl $11, %r8d, %ecx + addl 48(%rsp), %r11d + vpalignr $4, %xmm1, %xmm2, %xmm4 + vpalignr $4, %xmm3, %xmm0, %xmm5 + # rnd_0: 1 - 2 + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + andl %r8d, %eax + xorl %ecx, %edx + rorxl $13, %r12d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + addl %edx, %r11d + rorxl $2, %r12d, %edx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + vpsrld $3, %xmm5, %xmm8 + vpor %xmm6, %xmm7, %xmm7 + # rnd_0: 5 - 7 + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + addl %edx, %r11d + andl %eax, %ebx + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + addl %ebx, %r11d + # rnd_1: 0 - 0 + movl %r8d, %ebx + rorxl $11, %r15d, %ecx + addl 52(%rsp), %r10d + vpsrld $18, %xmm5, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + vpslld $14, %xmm5, %xmm5 + # rnd_1: 2 - 2 + andl %r15d, %ebx + xorl %ecx, %edx + rorxl $13, %r11d, %ecx + vpxor %xmm5, %xmm7, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r10d + rorxl $2, %r11d, %edx + xorl %r9d, %ebx + vpxor %xmm6, %xmm7, %xmm7 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + vpshufd $0xfa, %xmm2, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r12d, %ebx + addl %r10d, %r14d + vpxor %xmm8, %xmm7, %xmm5 + # rnd_1: 6 - 6 + xorl %r11d, %ebx + addl %edx, %r10d + andl %ebx, %eax + vpsrld $10, %xmm6, %xmm8 + # rnd_1: 7 - 7 + xorl %r12d, %eax + rorxl $6, %r14d, %edx + addl %eax, %r10d + # rnd_0: 0 - 0 + movl %r15d, %eax + rorxl $11, %r14d, %ecx + addl 56(%rsp), %r9d + vpsrlq $19, %xmm6, %xmm7 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm3, %xmm4, %xmm4 + # rnd_0: 2 - 2 + andl %r14d, %eax + xorl %ecx, %edx + rorxl $13, %r10d, %ecx + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 3 - 3 + addl %edx, %r9d + rorxl $2, %r10d, %edx + xorl %r8d, %eax + vpxor %xmm7, %xmm6, %xmm6 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + xorl %r10d, %eax + addl %edx, %r9d + andl %eax, %ebx + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + addl %ebx, %r9d + # rnd_1: 0 - 0 + movl %r14d, %ebx + rorxl $11, %r13d, %ecx + addl 60(%rsp), %r8d + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + vpsrld $10, %xmm6, %xmm9 + # rnd_1: 2 - 2 + andl %r13d, %ebx + xorl %ecx, %edx + rorxl $13, %r9d, %ecx + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r8d + rorxl $2, %r9d, %edx + xorl %r15d, %ebx + vpsrlq $0x11, %xmm6, %xmm6 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + vpxor %xmm7, %xmm6, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r10d, %ebx + addl %r8d, %r12d + vpxor %xmm6, %xmm9, %xmm9 + # rnd_1: 6 - 6 + xorl %r9d, %ebx + addl %edx, %r8d + andl %ebx, %eax + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + xorl %r10d, %eax + rorxl $6, %r12d, %edx + addl %eax, %r8d + vpaddd %xmm4, %xmm9, %xmm3 + # msg_sched done: 12-15 + # set_w_k_xfer_4: 4 + vpaddd 64+L_avx1_rorx_sha256_k(%rip), %xmm0, %xmm4 + vpaddd 80+L_avx1_rorx_sha256_k(%rip), %xmm1, %xmm5 + vmovdqu %xmm4, (%rsp) + vmovdqu %xmm5, 16(%rsp) + vpaddd 96+L_avx1_rorx_sha256_k(%rip), %xmm2, %xmm6 + vpaddd 112+L_avx1_rorx_sha256_k(%rip), %xmm3, %xmm7 + vmovdqu %xmm6, 32(%rsp) + vmovdqu %xmm7, 48(%rsp) + # msg_sched: 0-3 + # rnd_0: 0 - 0 + movl %r13d, %eax + rorxl $11, %r12d, %ecx + addl (%rsp), %r15d + vpalignr $4, %xmm2, %xmm3, %xmm4 + vpalignr $4, %xmm0, %xmm1, %xmm5 + # rnd_0: 1 - 2 + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + andl %r12d, %eax + xorl %ecx, %edx + rorxl $13, %r8d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + addl %edx, %r15d + rorxl $2, %r8d, %edx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + vpsrld $3, %xmm5, %xmm8 + vpor %xmm6, %xmm7, %xmm7 + # rnd_0: 5 - 7 + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + addl %edx, %r15d + andl %eax, %ebx + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + addl %ebx, %r15d + # rnd_1: 0 - 0 + movl %r12d, %ebx + rorxl $11, %r11d, %ecx + addl 4(%rsp), %r14d + vpsrld $18, %xmm5, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + vpslld $14, %xmm5, %xmm5 + # rnd_1: 2 - 2 + andl %r11d, %ebx + xorl %ecx, %edx + rorxl $13, %r15d, %ecx + vpxor %xmm5, %xmm7, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r14d + rorxl $2, %r15d, %edx + xorl %r13d, %ebx + vpxor %xmm6, %xmm7, %xmm7 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + vpshufd $0xfa, %xmm3, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r8d, %ebx + addl %r14d, %r10d + vpxor %xmm8, %xmm7, %xmm5 + # rnd_1: 6 - 6 + xorl %r15d, %ebx + addl %edx, %r14d + andl %ebx, %eax + vpsrld $10, %xmm6, %xmm8 + # rnd_1: 7 - 7 + xorl %r8d, %eax + rorxl $6, %r10d, %edx + addl %eax, %r14d + # rnd_0: 0 - 0 + movl %r11d, %eax + rorxl $11, %r10d, %ecx + addl 8(%rsp), %r13d + vpsrlq $19, %xmm6, %xmm7 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm0, %xmm4, %xmm4 + # rnd_0: 2 - 2 + andl %r10d, %eax + xorl %ecx, %edx + rorxl $13, %r14d, %ecx + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 3 - 3 + addl %edx, %r13d + rorxl $2, %r14d, %edx + xorl %r12d, %eax + vpxor %xmm7, %xmm6, %xmm6 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + xorl %r14d, %eax + addl %edx, %r13d + andl %eax, %ebx + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + addl %ebx, %r13d + # rnd_1: 0 - 0 + movl %r10d, %ebx + rorxl $11, %r9d, %ecx + addl 12(%rsp), %r12d + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + vpsrld $10, %xmm6, %xmm9 + # rnd_1: 2 - 2 + andl %r9d, %ebx + xorl %ecx, %edx + rorxl $13, %r13d, %ecx + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r12d + rorxl $2, %r13d, %edx + xorl %r11d, %ebx + vpsrlq $0x11, %xmm6, %xmm6 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + vpxor %xmm7, %xmm6, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r14d, %ebx + addl %r12d, %r8d + vpxor %xmm6, %xmm9, %xmm9 + # rnd_1: 6 - 6 + xorl %r13d, %ebx + addl %edx, %r12d + andl %ebx, %eax + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + xorl %r14d, %eax + rorxl $6, %r8d, %edx + addl %eax, %r12d + vpaddd %xmm4, %xmm9, %xmm0 + # msg_sched done: 0-3 + # msg_sched: 4-7 + # rnd_0: 0 - 0 + movl %r9d, %eax + rorxl $11, %r8d, %ecx + addl 16(%rsp), %r11d + vpalignr $4, %xmm3, %xmm0, %xmm4 + vpalignr $4, %xmm1, %xmm2, %xmm5 + # rnd_0: 1 - 2 + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + andl %r8d, %eax + xorl %ecx, %edx + rorxl $13, %r12d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + addl %edx, %r11d + rorxl $2, %r12d, %edx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + vpsrld $3, %xmm5, %xmm8 + vpor %xmm6, %xmm7, %xmm7 + # rnd_0: 5 - 7 + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + addl %edx, %r11d + andl %eax, %ebx + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + addl %ebx, %r11d + # rnd_1: 0 - 0 + movl %r8d, %ebx + rorxl $11, %r15d, %ecx + addl 20(%rsp), %r10d + vpsrld $18, %xmm5, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + vpslld $14, %xmm5, %xmm5 + # rnd_1: 2 - 2 + andl %r15d, %ebx + xorl %ecx, %edx + rorxl $13, %r11d, %ecx + vpxor %xmm5, %xmm7, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r10d + rorxl $2, %r11d, %edx + xorl %r9d, %ebx + vpxor %xmm6, %xmm7, %xmm7 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + vpshufd $0xfa, %xmm0, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r12d, %ebx + addl %r10d, %r14d + vpxor %xmm8, %xmm7, %xmm5 + # rnd_1: 6 - 6 + xorl %r11d, %ebx + addl %edx, %r10d + andl %ebx, %eax + vpsrld $10, %xmm6, %xmm8 + # rnd_1: 7 - 7 + xorl %r12d, %eax + rorxl $6, %r14d, %edx + addl %eax, %r10d + # rnd_0: 0 - 0 + movl %r15d, %eax + rorxl $11, %r14d, %ecx + addl 24(%rsp), %r9d + vpsrlq $19, %xmm6, %xmm7 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm1, %xmm4, %xmm4 + # rnd_0: 2 - 2 + andl %r14d, %eax + xorl %ecx, %edx + rorxl $13, %r10d, %ecx + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 3 - 3 + addl %edx, %r9d + rorxl $2, %r10d, %edx + xorl %r8d, %eax + vpxor %xmm7, %xmm6, %xmm6 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + xorl %r10d, %eax + addl %edx, %r9d + andl %eax, %ebx + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + addl %ebx, %r9d + # rnd_1: 0 - 0 + movl %r14d, %ebx + rorxl $11, %r13d, %ecx + addl 28(%rsp), %r8d + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + vpsrld $10, %xmm6, %xmm9 + # rnd_1: 2 - 2 + andl %r13d, %ebx + xorl %ecx, %edx + rorxl $13, %r9d, %ecx + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r8d + rorxl $2, %r9d, %edx + xorl %r15d, %ebx + vpsrlq $0x11, %xmm6, %xmm6 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + vpxor %xmm7, %xmm6, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r10d, %ebx + addl %r8d, %r12d + vpxor %xmm6, %xmm9, %xmm9 + # rnd_1: 6 - 6 + xorl %r9d, %ebx + addl %edx, %r8d + andl %ebx, %eax + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + xorl %r10d, %eax + rorxl $6, %r12d, %edx + addl %eax, %r8d + vpaddd %xmm4, %xmm9, %xmm1 + # msg_sched done: 4-7 + # msg_sched: 8-11 + # rnd_0: 0 - 0 + movl %r13d, %eax + rorxl $11, %r12d, %ecx + addl 32(%rsp), %r15d + vpalignr $4, %xmm0, %xmm1, %xmm4 + vpalignr $4, %xmm2, %xmm3, %xmm5 + # rnd_0: 1 - 2 + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + andl %r12d, %eax + xorl %ecx, %edx + rorxl $13, %r8d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + addl %edx, %r15d + rorxl $2, %r8d, %edx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + vpsrld $3, %xmm5, %xmm8 + vpor %xmm6, %xmm7, %xmm7 + # rnd_0: 5 - 7 + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + addl %edx, %r15d + andl %eax, %ebx + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + addl %ebx, %r15d + # rnd_1: 0 - 0 + movl %r12d, %ebx + rorxl $11, %r11d, %ecx + addl 36(%rsp), %r14d + vpsrld $18, %xmm5, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + vpslld $14, %xmm5, %xmm5 + # rnd_1: 2 - 2 + andl %r11d, %ebx + xorl %ecx, %edx + rorxl $13, %r15d, %ecx + vpxor %xmm5, %xmm7, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r14d + rorxl $2, %r15d, %edx + xorl %r13d, %ebx + vpxor %xmm6, %xmm7, %xmm7 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + vpshufd $0xfa, %xmm1, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r8d, %ebx + addl %r14d, %r10d + vpxor %xmm8, %xmm7, %xmm5 + # rnd_1: 6 - 6 + xorl %r15d, %ebx + addl %edx, %r14d + andl %ebx, %eax + vpsrld $10, %xmm6, %xmm8 + # rnd_1: 7 - 7 + xorl %r8d, %eax + rorxl $6, %r10d, %edx + addl %eax, %r14d + # rnd_0: 0 - 0 + movl %r11d, %eax + rorxl $11, %r10d, %ecx + addl 40(%rsp), %r13d + vpsrlq $19, %xmm6, %xmm7 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm2, %xmm4, %xmm4 + # rnd_0: 2 - 2 + andl %r10d, %eax + xorl %ecx, %edx + rorxl $13, %r14d, %ecx + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 3 - 3 + addl %edx, %r13d + rorxl $2, %r14d, %edx + xorl %r12d, %eax + vpxor %xmm7, %xmm6, %xmm6 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + xorl %r14d, %eax + addl %edx, %r13d + andl %eax, %ebx + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + addl %ebx, %r13d + # rnd_1: 0 - 0 + movl %r10d, %ebx + rorxl $11, %r9d, %ecx + addl 44(%rsp), %r12d + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + vpsrld $10, %xmm6, %xmm9 + # rnd_1: 2 - 2 + andl %r9d, %ebx + xorl %ecx, %edx + rorxl $13, %r13d, %ecx + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r12d + rorxl $2, %r13d, %edx + xorl %r11d, %ebx + vpsrlq $0x11, %xmm6, %xmm6 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + vpxor %xmm7, %xmm6, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r14d, %ebx + addl %r12d, %r8d + vpxor %xmm6, %xmm9, %xmm9 + # rnd_1: 6 - 6 + xorl %r13d, %ebx + addl %edx, %r12d + andl %ebx, %eax + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + xorl %r14d, %eax + rorxl $6, %r8d, %edx + addl %eax, %r12d + vpaddd %xmm4, %xmm9, %xmm2 + # msg_sched done: 8-11 + # msg_sched: 12-15 + # rnd_0: 0 - 0 + movl %r9d, %eax + rorxl $11, %r8d, %ecx + addl 48(%rsp), %r11d + vpalignr $4, %xmm1, %xmm2, %xmm4 + vpalignr $4, %xmm3, %xmm0, %xmm5 + # rnd_0: 1 - 2 + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + andl %r8d, %eax + xorl %ecx, %edx + rorxl $13, %r12d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + addl %edx, %r11d + rorxl $2, %r12d, %edx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + vpsrld $3, %xmm5, %xmm8 + vpor %xmm6, %xmm7, %xmm7 + # rnd_0: 5 - 7 + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + addl %edx, %r11d + andl %eax, %ebx + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + addl %ebx, %r11d + # rnd_1: 0 - 0 + movl %r8d, %ebx + rorxl $11, %r15d, %ecx + addl 52(%rsp), %r10d + vpsrld $18, %xmm5, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + vpslld $14, %xmm5, %xmm5 + # rnd_1: 2 - 2 + andl %r15d, %ebx + xorl %ecx, %edx + rorxl $13, %r11d, %ecx + vpxor %xmm5, %xmm7, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r10d + rorxl $2, %r11d, %edx + xorl %r9d, %ebx + vpxor %xmm6, %xmm7, %xmm7 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + vpshufd $0xfa, %xmm2, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r12d, %ebx + addl %r10d, %r14d + vpxor %xmm8, %xmm7, %xmm5 + # rnd_1: 6 - 6 + xorl %r11d, %ebx + addl %edx, %r10d + andl %ebx, %eax + vpsrld $10, %xmm6, %xmm8 + # rnd_1: 7 - 7 + xorl %r12d, %eax + rorxl $6, %r14d, %edx + addl %eax, %r10d + # rnd_0: 0 - 0 + movl %r15d, %eax + rorxl $11, %r14d, %ecx + addl 56(%rsp), %r9d + vpsrlq $19, %xmm6, %xmm7 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm3, %xmm4, %xmm4 + # rnd_0: 2 - 2 + andl %r14d, %eax + xorl %ecx, %edx + rorxl $13, %r10d, %ecx + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 3 - 3 + addl %edx, %r9d + rorxl $2, %r10d, %edx + xorl %r8d, %eax + vpxor %xmm7, %xmm6, %xmm6 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + xorl %r10d, %eax + addl %edx, %r9d + andl %eax, %ebx + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + addl %ebx, %r9d + # rnd_1: 0 - 0 + movl %r14d, %ebx + rorxl $11, %r13d, %ecx + addl 60(%rsp), %r8d + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + vpsrld $10, %xmm6, %xmm9 + # rnd_1: 2 - 2 + andl %r13d, %ebx + xorl %ecx, %edx + rorxl $13, %r9d, %ecx + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r8d + rorxl $2, %r9d, %edx + xorl %r15d, %ebx + vpsrlq $0x11, %xmm6, %xmm6 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + vpxor %xmm7, %xmm6, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r10d, %ebx + addl %r8d, %r12d + vpxor %xmm6, %xmm9, %xmm9 + # rnd_1: 6 - 6 + xorl %r9d, %ebx + addl %edx, %r8d + andl %ebx, %eax + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + xorl %r10d, %eax + rorxl $6, %r12d, %edx + addl %eax, %r8d + vpaddd %xmm4, %xmm9, %xmm3 + # msg_sched done: 12-15 + # set_w_k_xfer_4: 8 + vpaddd 128+L_avx1_rorx_sha256_k(%rip), %xmm0, %xmm4 + vpaddd 144+L_avx1_rorx_sha256_k(%rip), %xmm1, %xmm5 + vmovdqu %xmm4, (%rsp) + vmovdqu %xmm5, 16(%rsp) + vpaddd 160+L_avx1_rorx_sha256_k(%rip), %xmm2, %xmm6 + vpaddd 176+L_avx1_rorx_sha256_k(%rip), %xmm3, %xmm7 + vmovdqu %xmm6, 32(%rsp) + vmovdqu %xmm7, 48(%rsp) + # msg_sched: 0-3 + # rnd_0: 0 - 0 + movl %r13d, %eax + rorxl $11, %r12d, %ecx + addl (%rsp), %r15d + vpalignr $4, %xmm2, %xmm3, %xmm4 + vpalignr $4, %xmm0, %xmm1, %xmm5 + # rnd_0: 1 - 2 + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + andl %r12d, %eax + xorl %ecx, %edx + rorxl $13, %r8d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + addl %edx, %r15d + rorxl $2, %r8d, %edx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + vpsrld $3, %xmm5, %xmm8 + vpor %xmm6, %xmm7, %xmm7 + # rnd_0: 5 - 7 + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + addl %edx, %r15d + andl %eax, %ebx + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + addl %ebx, %r15d + # rnd_1: 0 - 0 + movl %r12d, %ebx + rorxl $11, %r11d, %ecx + addl 4(%rsp), %r14d + vpsrld $18, %xmm5, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + vpslld $14, %xmm5, %xmm5 + # rnd_1: 2 - 2 + andl %r11d, %ebx + xorl %ecx, %edx + rorxl $13, %r15d, %ecx + vpxor %xmm5, %xmm7, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r14d + rorxl $2, %r15d, %edx + xorl %r13d, %ebx + vpxor %xmm6, %xmm7, %xmm7 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + vpshufd $0xfa, %xmm3, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r8d, %ebx + addl %r14d, %r10d + vpxor %xmm8, %xmm7, %xmm5 + # rnd_1: 6 - 6 + xorl %r15d, %ebx + addl %edx, %r14d + andl %ebx, %eax + vpsrld $10, %xmm6, %xmm8 + # rnd_1: 7 - 7 + xorl %r8d, %eax + rorxl $6, %r10d, %edx + addl %eax, %r14d + # rnd_0: 0 - 0 + movl %r11d, %eax + rorxl $11, %r10d, %ecx + addl 8(%rsp), %r13d + vpsrlq $19, %xmm6, %xmm7 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm0, %xmm4, %xmm4 + # rnd_0: 2 - 2 + andl %r10d, %eax + xorl %ecx, %edx + rorxl $13, %r14d, %ecx + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 3 - 3 + addl %edx, %r13d + rorxl $2, %r14d, %edx + xorl %r12d, %eax + vpxor %xmm7, %xmm6, %xmm6 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + xorl %r14d, %eax + addl %edx, %r13d + andl %eax, %ebx + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + addl %ebx, %r13d + # rnd_1: 0 - 0 + movl %r10d, %ebx + rorxl $11, %r9d, %ecx + addl 12(%rsp), %r12d + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + vpsrld $10, %xmm6, %xmm9 + # rnd_1: 2 - 2 + andl %r9d, %ebx + xorl %ecx, %edx + rorxl $13, %r13d, %ecx + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r12d + rorxl $2, %r13d, %edx + xorl %r11d, %ebx + vpsrlq $0x11, %xmm6, %xmm6 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + vpxor %xmm7, %xmm6, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r14d, %ebx + addl %r12d, %r8d + vpxor %xmm6, %xmm9, %xmm9 + # rnd_1: 6 - 6 + xorl %r13d, %ebx + addl %edx, %r12d + andl %ebx, %eax + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + xorl %r14d, %eax + rorxl $6, %r8d, %edx + addl %eax, %r12d + vpaddd %xmm4, %xmm9, %xmm0 + # msg_sched done: 0-3 + # msg_sched: 4-7 + # rnd_0: 0 - 0 + movl %r9d, %eax + rorxl $11, %r8d, %ecx + addl 16(%rsp), %r11d + vpalignr $4, %xmm3, %xmm0, %xmm4 + vpalignr $4, %xmm1, %xmm2, %xmm5 + # rnd_0: 1 - 2 + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + andl %r8d, %eax + xorl %ecx, %edx + rorxl $13, %r12d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + addl %edx, %r11d + rorxl $2, %r12d, %edx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + vpsrld $3, %xmm5, %xmm8 + vpor %xmm6, %xmm7, %xmm7 + # rnd_0: 5 - 7 + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + addl %edx, %r11d + andl %eax, %ebx + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + addl %ebx, %r11d + # rnd_1: 0 - 0 + movl %r8d, %ebx + rorxl $11, %r15d, %ecx + addl 20(%rsp), %r10d + vpsrld $18, %xmm5, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + vpslld $14, %xmm5, %xmm5 + # rnd_1: 2 - 2 + andl %r15d, %ebx + xorl %ecx, %edx + rorxl $13, %r11d, %ecx + vpxor %xmm5, %xmm7, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r10d + rorxl $2, %r11d, %edx + xorl %r9d, %ebx + vpxor %xmm6, %xmm7, %xmm7 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + vpshufd $0xfa, %xmm0, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r12d, %ebx + addl %r10d, %r14d + vpxor %xmm8, %xmm7, %xmm5 + # rnd_1: 6 - 6 + xorl %r11d, %ebx + addl %edx, %r10d + andl %ebx, %eax + vpsrld $10, %xmm6, %xmm8 + # rnd_1: 7 - 7 + xorl %r12d, %eax + rorxl $6, %r14d, %edx + addl %eax, %r10d + # rnd_0: 0 - 0 + movl %r15d, %eax + rorxl $11, %r14d, %ecx + addl 24(%rsp), %r9d + vpsrlq $19, %xmm6, %xmm7 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm1, %xmm4, %xmm4 + # rnd_0: 2 - 2 + andl %r14d, %eax + xorl %ecx, %edx + rorxl $13, %r10d, %ecx + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 3 - 3 + addl %edx, %r9d + rorxl $2, %r10d, %edx + xorl %r8d, %eax + vpxor %xmm7, %xmm6, %xmm6 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + xorl %r10d, %eax + addl %edx, %r9d + andl %eax, %ebx + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + addl %ebx, %r9d + # rnd_1: 0 - 0 + movl %r14d, %ebx + rorxl $11, %r13d, %ecx + addl 28(%rsp), %r8d + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + vpsrld $10, %xmm6, %xmm9 + # rnd_1: 2 - 2 + andl %r13d, %ebx + xorl %ecx, %edx + rorxl $13, %r9d, %ecx + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r8d + rorxl $2, %r9d, %edx + xorl %r15d, %ebx + vpsrlq $0x11, %xmm6, %xmm6 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + vpxor %xmm7, %xmm6, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r10d, %ebx + addl %r8d, %r12d + vpxor %xmm6, %xmm9, %xmm9 + # rnd_1: 6 - 6 + xorl %r9d, %ebx + addl %edx, %r8d + andl %ebx, %eax + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + xorl %r10d, %eax + rorxl $6, %r12d, %edx + addl %eax, %r8d + vpaddd %xmm4, %xmm9, %xmm1 + # msg_sched done: 4-7 + # msg_sched: 8-11 + # rnd_0: 0 - 0 + movl %r13d, %eax + rorxl $11, %r12d, %ecx + addl 32(%rsp), %r15d + vpalignr $4, %xmm0, %xmm1, %xmm4 + vpalignr $4, %xmm2, %xmm3, %xmm5 + # rnd_0: 1 - 2 + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + andl %r12d, %eax + xorl %ecx, %edx + rorxl $13, %r8d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + addl %edx, %r15d + rorxl $2, %r8d, %edx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + vpsrld $3, %xmm5, %xmm8 + vpor %xmm6, %xmm7, %xmm7 + # rnd_0: 5 - 7 + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + addl %edx, %r15d + andl %eax, %ebx + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + addl %ebx, %r15d + # rnd_1: 0 - 0 + movl %r12d, %ebx + rorxl $11, %r11d, %ecx + addl 36(%rsp), %r14d + vpsrld $18, %xmm5, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + vpslld $14, %xmm5, %xmm5 + # rnd_1: 2 - 2 + andl %r11d, %ebx + xorl %ecx, %edx + rorxl $13, %r15d, %ecx + vpxor %xmm5, %xmm7, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r14d + rorxl $2, %r15d, %edx + xorl %r13d, %ebx + vpxor %xmm6, %xmm7, %xmm7 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + vpshufd $0xfa, %xmm1, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r8d, %ebx + addl %r14d, %r10d + vpxor %xmm8, %xmm7, %xmm5 + # rnd_1: 6 - 6 + xorl %r15d, %ebx + addl %edx, %r14d + andl %ebx, %eax + vpsrld $10, %xmm6, %xmm8 + # rnd_1: 7 - 7 + xorl %r8d, %eax + rorxl $6, %r10d, %edx + addl %eax, %r14d + # rnd_0: 0 - 0 + movl %r11d, %eax + rorxl $11, %r10d, %ecx + addl 40(%rsp), %r13d + vpsrlq $19, %xmm6, %xmm7 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm2, %xmm4, %xmm4 + # rnd_0: 2 - 2 + andl %r10d, %eax + xorl %ecx, %edx + rorxl $13, %r14d, %ecx + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 3 - 3 + addl %edx, %r13d + rorxl $2, %r14d, %edx + xorl %r12d, %eax + vpxor %xmm7, %xmm6, %xmm6 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + xorl %r14d, %eax + addl %edx, %r13d + andl %eax, %ebx + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + addl %ebx, %r13d + # rnd_1: 0 - 0 + movl %r10d, %ebx + rorxl $11, %r9d, %ecx + addl 44(%rsp), %r12d + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + vpsrld $10, %xmm6, %xmm9 + # rnd_1: 2 - 2 + andl %r9d, %ebx + xorl %ecx, %edx + rorxl $13, %r13d, %ecx + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r12d + rorxl $2, %r13d, %edx + xorl %r11d, %ebx + vpsrlq $0x11, %xmm6, %xmm6 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + vpxor %xmm7, %xmm6, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r14d, %ebx + addl %r12d, %r8d + vpxor %xmm6, %xmm9, %xmm9 + # rnd_1: 6 - 6 + xorl %r13d, %ebx + addl %edx, %r12d + andl %ebx, %eax + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + xorl %r14d, %eax + rorxl $6, %r8d, %edx + addl %eax, %r12d + vpaddd %xmm4, %xmm9, %xmm2 + # msg_sched done: 8-11 + # msg_sched: 12-15 + # rnd_0: 0 - 0 + movl %r9d, %eax + rorxl $11, %r8d, %ecx + addl 48(%rsp), %r11d + vpalignr $4, %xmm1, %xmm2, %xmm4 + vpalignr $4, %xmm3, %xmm0, %xmm5 + # rnd_0: 1 - 2 + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + andl %r8d, %eax + xorl %ecx, %edx + rorxl $13, %r12d, %ecx + vpsrld $7, %xmm5, %xmm6 + vpslld $25, %xmm5, %xmm7 + # rnd_0: 3 - 4 + addl %edx, %r11d + rorxl $2, %r12d, %edx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + vpsrld $3, %xmm5, %xmm8 + vpor %xmm6, %xmm7, %xmm7 + # rnd_0: 5 - 7 + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + addl %edx, %r11d + andl %eax, %ebx + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + addl %ebx, %r11d + # rnd_1: 0 - 0 + movl %r8d, %ebx + rorxl $11, %r15d, %ecx + addl 52(%rsp), %r10d + vpsrld $18, %xmm5, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + vpslld $14, %xmm5, %xmm5 + # rnd_1: 2 - 2 + andl %r15d, %ebx + xorl %ecx, %edx + rorxl $13, %r11d, %ecx + vpxor %xmm5, %xmm7, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r10d + rorxl $2, %r11d, %edx + xorl %r9d, %ebx + vpxor %xmm6, %xmm7, %xmm7 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + vpshufd $0xfa, %xmm2, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r12d, %ebx + addl %r10d, %r14d + vpxor %xmm8, %xmm7, %xmm5 + # rnd_1: 6 - 6 + xorl %r11d, %ebx + addl %edx, %r10d + andl %ebx, %eax + vpsrld $10, %xmm6, %xmm8 + # rnd_1: 7 - 7 + xorl %r12d, %eax + rorxl $6, %r14d, %edx + addl %eax, %r10d + # rnd_0: 0 - 0 + movl %r15d, %eax + rorxl $11, %r14d, %ecx + addl 56(%rsp), %r9d + vpsrlq $19, %xmm6, %xmm7 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + vpsrlq $0x11, %xmm6, %xmm6 + vpaddd %xmm3, %xmm4, %xmm4 + # rnd_0: 2 - 2 + andl %r14d, %eax + xorl %ecx, %edx + rorxl $13, %r10d, %ecx + vpaddd %xmm5, %xmm4, %xmm4 + # rnd_0: 3 - 3 + addl %edx, %r9d + rorxl $2, %r10d, %edx + xorl %r8d, %eax + vpxor %xmm7, %xmm6, %xmm6 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + vpxor %xmm6, %xmm8, %xmm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + vpshufb %xmm11, %xmm8, %xmm8 + # rnd_0: 6 - 6 + xorl %r10d, %eax + addl %edx, %r9d + andl %eax, %ebx + vpaddd %xmm8, %xmm4, %xmm4 + # rnd_0: 7 - 7 + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + addl %ebx, %r9d + # rnd_1: 0 - 0 + movl %r14d, %ebx + rorxl $11, %r13d, %ecx + addl 60(%rsp), %r8d + vpshufd $0x50, %xmm4, %xmm6 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + vpsrld $10, %xmm6, %xmm9 + # rnd_1: 2 - 2 + andl %r13d, %ebx + xorl %ecx, %edx + rorxl $13, %r9d, %ecx + vpsrlq $19, %xmm6, %xmm7 + # rnd_1: 3 - 3 + addl %edx, %r8d + rorxl $2, %r9d, %edx + xorl %r15d, %ebx + vpsrlq $0x11, %xmm6, %xmm6 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + vpxor %xmm7, %xmm6, %xmm6 + # rnd_1: 5 - 5 + xorl %ecx, %edx + movl %r10d, %ebx + addl %r8d, %r12d + vpxor %xmm6, %xmm9, %xmm9 + # rnd_1: 6 - 6 + xorl %r9d, %ebx + addl %edx, %r8d + andl %ebx, %eax + vpshufb %xmm12, %xmm9, %xmm9 + # rnd_1: 7 - 7 + xorl %r10d, %eax + rorxl $6, %r12d, %edx + addl %eax, %r8d + vpaddd %xmm4, %xmm9, %xmm3 + # msg_sched done: 12-15 + # set_w_k_xfer_4: 12 + vpaddd 192+L_avx1_rorx_sha256_k(%rip), %xmm0, %xmm4 + vpaddd 208+L_avx1_rorx_sha256_k(%rip), %xmm1, %xmm5 + vmovdqu %xmm4, (%rsp) + vmovdqu %xmm5, 16(%rsp) + vpaddd 224+L_avx1_rorx_sha256_k(%rip), %xmm2, %xmm6 + vpaddd 240+L_avx1_rorx_sha256_k(%rip), %xmm3, %xmm7 + vmovdqu %xmm6, 32(%rsp) + vmovdqu %xmm7, 48(%rsp) + xorl %eax, %eax + xorl %ecx, %ecx + # rnd_all_4: 0-3 + rorxl $6, %r12d, %edx + rorxl $11, %r12d, %ecx + addl %eax, %r8d + addl (%rsp), %r15d + movl %r13d, %eax + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + xorl %ecx, %edx + andl %r12d, %eax + addl %edx, %r15d + rorxl $2, %r8d, %edx + rorxl $13, %r8d, %ecx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + andl %eax, %ebx + addl %edx, %r15d + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + rorxl $11, %r11d, %ecx + addl %ebx, %r15d + addl 4(%rsp), %r14d + movl %r12d, %ebx + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + xorl %ecx, %edx + andl %r11d, %ebx + addl %edx, %r14d + rorxl $2, %r15d, %edx + rorxl $13, %r15d, %ecx + xorl %r13d, %ebx + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + xorl %ecx, %edx + movl %r8d, %ebx + addl %r14d, %r10d + xorl %r15d, %ebx + andl %ebx, %eax + addl %edx, %r14d + xorl %r8d, %eax + rorxl $6, %r10d, %edx + rorxl $11, %r10d, %ecx + addl %eax, %r14d + addl 8(%rsp), %r13d + movl %r11d, %eax + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + xorl %ecx, %edx + andl %r10d, %eax + addl %edx, %r13d + rorxl $2, %r14d, %edx + rorxl $13, %r14d, %ecx + xorl %r12d, %eax + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + xorl %r14d, %eax + andl %eax, %ebx + addl %edx, %r13d + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + rorxl $11, %r9d, %ecx + addl %ebx, %r13d + addl 12(%rsp), %r12d + movl %r10d, %ebx + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + xorl %ecx, %edx + andl %r9d, %ebx + addl %edx, %r12d + rorxl $2, %r13d, %edx + rorxl $13, %r13d, %ecx + xorl %r11d, %ebx + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + xorl %ecx, %edx + movl %r14d, %ebx + addl %r12d, %r8d + xorl %r13d, %ebx + andl %ebx, %eax + addl %edx, %r12d + xorl %r14d, %eax + # rnd_all_4: 1-4 + rorxl $6, %r8d, %edx + rorxl $11, %r8d, %ecx + addl %eax, %r12d + addl 16(%rsp), %r11d + movl %r9d, %eax + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + xorl %ecx, %edx + andl %r8d, %eax + addl %edx, %r11d + rorxl $2, %r12d, %edx + rorxl $13, %r12d, %ecx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + andl %eax, %ebx + addl %edx, %r11d + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + rorxl $11, %r15d, %ecx + addl %ebx, %r11d + addl 20(%rsp), %r10d + movl %r8d, %ebx + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + xorl %ecx, %edx + andl %r15d, %ebx + addl %edx, %r10d + rorxl $2, %r11d, %edx + rorxl $13, %r11d, %ecx + xorl %r9d, %ebx + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + xorl %ecx, %edx + movl %r12d, %ebx + addl %r10d, %r14d + xorl %r11d, %ebx + andl %ebx, %eax + addl %edx, %r10d + xorl %r12d, %eax + rorxl $6, %r14d, %edx + rorxl $11, %r14d, %ecx + addl %eax, %r10d + addl 24(%rsp), %r9d + movl %r15d, %eax + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + xorl %ecx, %edx + andl %r14d, %eax + addl %edx, %r9d + rorxl $2, %r10d, %edx + rorxl $13, %r10d, %ecx + xorl %r8d, %eax + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + xorl %r10d, %eax + andl %eax, %ebx + addl %edx, %r9d + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + rorxl $11, %r13d, %ecx + addl %ebx, %r9d + addl 28(%rsp), %r8d + movl %r14d, %ebx + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + xorl %ecx, %edx + andl %r13d, %ebx + addl %edx, %r8d + rorxl $2, %r9d, %edx + rorxl $13, %r9d, %ecx + xorl %r15d, %ebx + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + xorl %ecx, %edx + movl %r10d, %ebx + addl %r8d, %r12d + xorl %r9d, %ebx + andl %ebx, %eax + addl %edx, %r8d + xorl %r10d, %eax + # rnd_all_4: 2-5 + rorxl $6, %r12d, %edx + rorxl $11, %r12d, %ecx + addl %eax, %r8d + addl 32(%rsp), %r15d + movl %r13d, %eax + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + xorl %ecx, %edx + andl %r12d, %eax + addl %edx, %r15d + rorxl $2, %r8d, %edx + rorxl $13, %r8d, %ecx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + andl %eax, %ebx + addl %edx, %r15d + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + rorxl $11, %r11d, %ecx + addl %ebx, %r15d + addl 36(%rsp), %r14d + movl %r12d, %ebx + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + xorl %ecx, %edx + andl %r11d, %ebx + addl %edx, %r14d + rorxl $2, %r15d, %edx + rorxl $13, %r15d, %ecx + xorl %r13d, %ebx + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + xorl %ecx, %edx + movl %r8d, %ebx + addl %r14d, %r10d + xorl %r15d, %ebx + andl %ebx, %eax + addl %edx, %r14d + xorl %r8d, %eax + rorxl $6, %r10d, %edx + rorxl $11, %r10d, %ecx + addl %eax, %r14d + addl 40(%rsp), %r13d + movl %r11d, %eax + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + xorl %ecx, %edx + andl %r10d, %eax + addl %edx, %r13d + rorxl $2, %r14d, %edx + rorxl $13, %r14d, %ecx + xorl %r12d, %eax + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + xorl %r14d, %eax + andl %eax, %ebx + addl %edx, %r13d + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + rorxl $11, %r9d, %ecx + addl %ebx, %r13d + addl 44(%rsp), %r12d + movl %r10d, %ebx + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + xorl %ecx, %edx + andl %r9d, %ebx + addl %edx, %r12d + rorxl $2, %r13d, %edx + rorxl $13, %r13d, %ecx + xorl %r11d, %ebx + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + xorl %ecx, %edx + movl %r14d, %ebx + addl %r12d, %r8d + xorl %r13d, %ebx + andl %ebx, %eax + addl %edx, %r12d + xorl %r14d, %eax + # rnd_all_4: 3-6 + rorxl $6, %r8d, %edx + rorxl $11, %r8d, %ecx + addl %eax, %r12d + addl 48(%rsp), %r11d + movl %r9d, %eax + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + xorl %ecx, %edx + andl %r8d, %eax + addl %edx, %r11d + rorxl $2, %r12d, %edx + rorxl $13, %r12d, %ecx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + andl %eax, %ebx + addl %edx, %r11d + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + rorxl $11, %r15d, %ecx + addl %ebx, %r11d + addl 52(%rsp), %r10d + movl %r8d, %ebx + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + xorl %ecx, %edx + andl %r15d, %ebx + addl %edx, %r10d + rorxl $2, %r11d, %edx + rorxl $13, %r11d, %ecx + xorl %r9d, %ebx + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + xorl %ecx, %edx + movl %r12d, %ebx + addl %r10d, %r14d + xorl %r11d, %ebx + andl %ebx, %eax + addl %edx, %r10d + xorl %r12d, %eax + rorxl $6, %r14d, %edx + rorxl $11, %r14d, %ecx + addl %eax, %r10d + addl 56(%rsp), %r9d + movl %r15d, %eax + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + xorl %ecx, %edx + andl %r14d, %eax + addl %edx, %r9d + rorxl $2, %r10d, %edx + rorxl $13, %r10d, %ecx + xorl %r8d, %eax + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + xorl %r10d, %eax + andl %eax, %ebx + addl %edx, %r9d + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + rorxl $11, %r13d, %ecx + addl %ebx, %r9d + addl 60(%rsp), %r8d + movl %r14d, %ebx + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + xorl %ecx, %edx + andl %r13d, %ebx + addl %edx, %r8d + rorxl $2, %r9d, %edx + rorxl $13, %r9d, %ecx + xorl %r15d, %ebx + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + xorl %ecx, %edx + movl %r10d, %ebx + addl %r8d, %r12d + xorl %r9d, %ebx + andl %ebx, %eax + addl %edx, %r8d + xorl %r10d, %eax + addl %eax, %r8d + addl (%rdi), %r8d + addl 4(%rdi), %r9d + addl 8(%rdi), %r10d + addl 12(%rdi), %r11d + addl 16(%rdi), %r12d + addl 20(%rdi), %r13d + addl 24(%rdi), %r14d + addl 28(%rdi), %r15d + addq $0x40, %rbp + subl $0x40, %esi + movl %r8d, (%rdi) + movl %r9d, 4(%rdi) + movl %r10d, 8(%rdi) + movl %r11d, 12(%rdi) + movl %r12d, 16(%rdi) + movl %r13d, 20(%rdi) + movl %r14d, 24(%rdi) + movl %r15d, 28(%rdi) + jnz L_sha256_len_avx1_len_rorx_start + xorq %rax, %rax + vzeroupper + addq $0x40, %rsp + popq %rbp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size Transform_Sha256_AVX1_RORX_Len,.-Transform_Sha256_AVX1_RORX_Len +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX1 */ +#ifdef HAVE_INTEL_AVX2 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +L_avx2_sha256_k: +.long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5 +.long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5 +.long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5 +.long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5 +.long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3 +.long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3 +.long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174 +.long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174 +.long 0xe49b69c1,0xefbe4786,0xfc19dc6,0x240ca1cc +.long 0xe49b69c1,0xefbe4786,0xfc19dc6,0x240ca1cc +.long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da +.long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da +.long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7 +.long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7 +.long 0xc6e00bf3,0xd5a79147,0x6ca6351,0x14292967 +.long 0xc6e00bf3,0xd5a79147,0x6ca6351,0x14292967 +.long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13 +.long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13 +.long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85 +.long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85 +.long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3 +.long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3 +.long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070 +.long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070 +.long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5 +.long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5 +.long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3 +.long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3 +.long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208 +.long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208 +.long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 +.long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 32 +#else +.p2align 5 +#endif /* __APPLE__ */ +L_avx2_sha256_shuf_00BA: +.quad 0xb0a090803020100, 0xffffffffffffffff +.quad 0xb0a090803020100, 0xffffffffffffffff +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 32 +#else +.p2align 5 +#endif /* __APPLE__ */ +L_avx2_sha256_shuf_DC00: +.quad 0xffffffffffffffff, 0xb0a090803020100 +.quad 0xffffffffffffffff, 0xb0a090803020100 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 32 +#else +.p2align 5 +#endif /* __APPLE__ */ +L_avx2_sha256_flip_mask: +.quad 0x405060700010203, 0xc0d0e0f08090a0b +.quad 0x405060700010203, 0xc0d0e0f08090a0b +#ifndef __APPLE__ +.text +.globl Transform_Sha256_AVX2 +.type Transform_Sha256_AVX2,@function +.align 4 +Transform_Sha256_AVX2: +#else +.section __TEXT,__text +.globl _Transform_Sha256_AVX2 +.p2align 2 +_Transform_Sha256_AVX2: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + subq $0x200, %rsp + leaq 32(%rdi), %rax + vmovdqa L_avx2_sha256_flip_mask(%rip), %xmm13 + vmovdqa L_avx2_sha256_shuf_00BA(%rip), %ymm11 + vmovdqa L_avx2_sha256_shuf_DC00(%rip), %ymm12 + movl (%rdi), %r8d + movl 4(%rdi), %r9d + movl 8(%rdi), %r10d + movl 12(%rdi), %r11d + movl 16(%rdi), %r12d + movl 20(%rdi), %r13d + movl 24(%rdi), %r14d + movl 28(%rdi), %r15d + # X0, X1, X2, X3 = W[0..15] + vmovdqu (%rax), %xmm0 + vmovdqu 16(%rax), %xmm1 + vpshufb %xmm13, %xmm0, %xmm0 + vpshufb %xmm13, %xmm1, %xmm1 + vmovdqu 32(%rax), %xmm2 + vmovdqu 48(%rax), %xmm3 + vpshufb %xmm13, %xmm2, %xmm2 + vpshufb %xmm13, %xmm3, %xmm3 + movl %r9d, %ebx + movl %r12d, %edx + xorl %r10d, %ebx + # set_w_k_xfer_4: 0 + vpaddd 0+L_avx2_sha256_k(%rip), %ymm0, %ymm4 + vpaddd 32+L_avx2_sha256_k(%rip), %ymm1, %ymm5 + vmovdqu %ymm4, (%rsp) + vmovdqu %ymm5, 32(%rsp) + vpaddd 64+L_avx2_sha256_k(%rip), %ymm2, %ymm4 + vpaddd 96+L_avx2_sha256_k(%rip), %ymm3, %ymm5 + vmovdqu %ymm4, 64(%rsp) + vmovdqu %ymm5, 96(%rsp) + # msg_sched: 0-3 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %ymm0, %ymm1, %ymm5 + vpalignr $4, %ymm2, %ymm3, %ymm4 + # rnd_0: 1 - 2 + movl %r9d, %eax + movl %r13d, %ecx + addl (%rsp), %r15d + xorl %r14d, %ecx + xorl %r12d, %edx + andl %r12d, %ecx + vpsrld $7, %ymm5, %ymm6 + vpslld $25, %ymm5, %ymm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r14d, %ecx + xorl %r12d, %edx + addl %ecx, %r15d + rorl $6, %edx + xorl %r8d, %eax + addl %edx, %r15d + movl %r8d, %ecx + vpsrld $18, %ymm5, %ymm8 + vpslld $14, %ymm5, %ymm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + vpor %ymm6, %ymm7, %ymm6 + vpor %ymm8, %ymm9, %ymm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r8d, %ebx + movl %r12d, %ecx + addl 4(%rsp), %r14d + xorl %r13d, %ecx + vpsrld $3, %ymm5, %ymm9 + vpxor %ymm6, %ymm8, %ymm6 + # rnd_1: 2 - 3 + xorl %r11d, %edx + andl %r11d, %ecx + rorl $5, %edx + xorl %r13d, %ecx + xorl %r11d, %edx + addl %ecx, %r14d + vpxor %ymm6, %ymm9, %ymm5 + vpshufd $0xfa, %ymm3, %ymm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r15d, %ebx + addl %edx, %r14d + movl %r15d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r15d, %ecx + xorl %r8d, %eax + vpsrld $10, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %ymm6, %ymm6 + vpaddd %ymm0, %ymm4, %ymm4 + # rnd_0: 1 - 3 + movl %r15d, %eax + movl %r11d, %ecx + addl 8(%rsp), %r13d + xorl %r12d, %ecx + xorl %r10d, %edx + andl %r10d, %ecx + rorl $5, %edx + xorl %r12d, %ecx + xorl %r10d, %edx + addl %ecx, %r13d + vpxor %ymm6, %ymm7, %ymm6 + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r14d, %eax + addl %edx, %r13d + movl %r14d, %ecx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r14d, %ecx + xorl %r15d, %ebx + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %ymm4, %ymm6 + # rnd_1: 1 - 1 + movl %r14d, %ebx + movl %r10d, %ecx + addl 12(%rsp), %r12d + xorl %r11d, %ecx + vpsrlq $0x11, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 2 - 3 + xorl %r9d, %edx + andl %r9d, %ecx + rorl $5, %edx + xorl %r11d, %ecx + xorl %r9d, %edx + addl %ecx, %r12d + vpsrld $10, %ymm6, %ymm9 + vpxor %ymm8, %ymm7, %ymm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r13d, %ebx + addl %edx, %r12d + movl %r13d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r13d, %ecx + xorl %r14d, %eax + vpxor %ymm9, %ymm8, %ymm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + vpaddd %ymm4, %ymm9, %ymm0 + # msg_sched done: 0-3 + # msg_sched: 8-11 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %ymm1, %ymm2, %ymm5 + vpalignr $4, %ymm3, %ymm0, %ymm4 + # rnd_0: 1 - 2 + movl %r13d, %eax + movl %r9d, %ecx + addl 32(%rsp), %r11d + xorl %r10d, %ecx + xorl %r8d, %edx + andl %r8d, %ecx + vpsrld $7, %ymm5, %ymm6 + vpslld $25, %ymm5, %ymm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r10d, %ecx + xorl %r8d, %edx + addl %ecx, %r11d + rorl $6, %edx + xorl %r12d, %eax + addl %edx, %r11d + movl %r12d, %ecx + vpsrld $18, %ymm5, %ymm8 + vpslld $14, %ymm5, %ymm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + vpor %ymm6, %ymm7, %ymm6 + vpor %ymm8, %ymm9, %ymm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r12d, %ebx + movl %r8d, %ecx + addl 36(%rsp), %r10d + xorl %r9d, %ecx + vpsrld $3, %ymm5, %ymm9 + vpxor %ymm6, %ymm8, %ymm6 + # rnd_1: 2 - 3 + xorl %r15d, %edx + andl %r15d, %ecx + rorl $5, %edx + xorl %r9d, %ecx + xorl %r15d, %edx + addl %ecx, %r10d + vpxor %ymm6, %ymm9, %ymm5 + vpshufd $0xfa, %ymm0, %ymm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r11d, %ebx + addl %edx, %r10d + movl %r11d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r11d, %ecx + xorl %r12d, %eax + vpsrld $10, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %ymm6, %ymm6 + vpaddd %ymm1, %ymm4, %ymm4 + # rnd_0: 1 - 3 + movl %r11d, %eax + movl %r15d, %ecx + addl 40(%rsp), %r9d + xorl %r8d, %ecx + xorl %r14d, %edx + andl %r14d, %ecx + rorl $5, %edx + xorl %r8d, %ecx + xorl %r14d, %edx + addl %ecx, %r9d + vpxor %ymm6, %ymm7, %ymm6 + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r10d, %eax + addl %edx, %r9d + movl %r10d, %ecx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r10d, %ecx + xorl %r11d, %ebx + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %ymm4, %ymm6 + # rnd_1: 1 - 1 + movl %r10d, %ebx + movl %r14d, %ecx + addl 44(%rsp), %r8d + xorl %r15d, %ecx + vpsrlq $0x11, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 2 - 3 + xorl %r13d, %edx + andl %r13d, %ecx + rorl $5, %edx + xorl %r15d, %ecx + xorl %r13d, %edx + addl %ecx, %r8d + vpsrld $10, %ymm6, %ymm9 + vpxor %ymm8, %ymm7, %ymm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r9d, %ebx + addl %edx, %r8d + movl %r9d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r9d, %ecx + xorl %r10d, %eax + vpxor %ymm9, %ymm8, %ymm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + vpaddd %ymm4, %ymm9, %ymm1 + # msg_sched done: 8-11 + # msg_sched: 16-19 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %ymm2, %ymm3, %ymm5 + vpalignr $4, %ymm0, %ymm1, %ymm4 + # rnd_0: 1 - 2 + movl %r9d, %eax + movl %r13d, %ecx + addl 64(%rsp), %r15d + xorl %r14d, %ecx + xorl %r12d, %edx + andl %r12d, %ecx + vpsrld $7, %ymm5, %ymm6 + vpslld $25, %ymm5, %ymm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r14d, %ecx + xorl %r12d, %edx + addl %ecx, %r15d + rorl $6, %edx + xorl %r8d, %eax + addl %edx, %r15d + movl %r8d, %ecx + vpsrld $18, %ymm5, %ymm8 + vpslld $14, %ymm5, %ymm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + vpor %ymm6, %ymm7, %ymm6 + vpor %ymm8, %ymm9, %ymm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r8d, %ebx + movl %r12d, %ecx + addl 68(%rsp), %r14d + xorl %r13d, %ecx + vpsrld $3, %ymm5, %ymm9 + vpxor %ymm6, %ymm8, %ymm6 + # rnd_1: 2 - 3 + xorl %r11d, %edx + andl %r11d, %ecx + rorl $5, %edx + xorl %r13d, %ecx + xorl %r11d, %edx + addl %ecx, %r14d + vpxor %ymm6, %ymm9, %ymm5 + vpshufd $0xfa, %ymm1, %ymm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r15d, %ebx + addl %edx, %r14d + movl %r15d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r15d, %ecx + xorl %r8d, %eax + vpsrld $10, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %ymm6, %ymm6 + vpaddd %ymm2, %ymm4, %ymm4 + # rnd_0: 1 - 3 + movl %r15d, %eax + movl %r11d, %ecx + addl 72(%rsp), %r13d + xorl %r12d, %ecx + xorl %r10d, %edx + andl %r10d, %ecx + rorl $5, %edx + xorl %r12d, %ecx + xorl %r10d, %edx + addl %ecx, %r13d + vpxor %ymm6, %ymm7, %ymm6 + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r14d, %eax + addl %edx, %r13d + movl %r14d, %ecx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r14d, %ecx + xorl %r15d, %ebx + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %ymm4, %ymm6 + # rnd_1: 1 - 1 + movl %r14d, %ebx + movl %r10d, %ecx + addl 76(%rsp), %r12d + xorl %r11d, %ecx + vpsrlq $0x11, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 2 - 3 + xorl %r9d, %edx + andl %r9d, %ecx + rorl $5, %edx + xorl %r11d, %ecx + xorl %r9d, %edx + addl %ecx, %r12d + vpsrld $10, %ymm6, %ymm9 + vpxor %ymm8, %ymm7, %ymm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r13d, %ebx + addl %edx, %r12d + movl %r13d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r13d, %ecx + xorl %r14d, %eax + vpxor %ymm9, %ymm8, %ymm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + vpaddd %ymm4, %ymm9, %ymm2 + # msg_sched done: 16-19 + # msg_sched: 24-27 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %ymm3, %ymm0, %ymm5 + vpalignr $4, %ymm1, %ymm2, %ymm4 + # rnd_0: 1 - 2 + movl %r13d, %eax + movl %r9d, %ecx + addl 96(%rsp), %r11d + xorl %r10d, %ecx + xorl %r8d, %edx + andl %r8d, %ecx + vpsrld $7, %ymm5, %ymm6 + vpslld $25, %ymm5, %ymm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r10d, %ecx + xorl %r8d, %edx + addl %ecx, %r11d + rorl $6, %edx + xorl %r12d, %eax + addl %edx, %r11d + movl %r12d, %ecx + vpsrld $18, %ymm5, %ymm8 + vpslld $14, %ymm5, %ymm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + vpor %ymm6, %ymm7, %ymm6 + vpor %ymm8, %ymm9, %ymm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r12d, %ebx + movl %r8d, %ecx + addl 100(%rsp), %r10d + xorl %r9d, %ecx + vpsrld $3, %ymm5, %ymm9 + vpxor %ymm6, %ymm8, %ymm6 + # rnd_1: 2 - 3 + xorl %r15d, %edx + andl %r15d, %ecx + rorl $5, %edx + xorl %r9d, %ecx + xorl %r15d, %edx + addl %ecx, %r10d + vpxor %ymm6, %ymm9, %ymm5 + vpshufd $0xfa, %ymm2, %ymm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r11d, %ebx + addl %edx, %r10d + movl %r11d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r11d, %ecx + xorl %r12d, %eax + vpsrld $10, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %ymm6, %ymm6 + vpaddd %ymm3, %ymm4, %ymm4 + # rnd_0: 1 - 3 + movl %r11d, %eax + movl %r15d, %ecx + addl 104(%rsp), %r9d + xorl %r8d, %ecx + xorl %r14d, %edx + andl %r14d, %ecx + rorl $5, %edx + xorl %r8d, %ecx + xorl %r14d, %edx + addl %ecx, %r9d + vpxor %ymm6, %ymm7, %ymm6 + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r10d, %eax + addl %edx, %r9d + movl %r10d, %ecx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r10d, %ecx + xorl %r11d, %ebx + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %ymm4, %ymm6 + # rnd_1: 1 - 1 + movl %r10d, %ebx + movl %r14d, %ecx + addl 108(%rsp), %r8d + xorl %r15d, %ecx + vpsrlq $0x11, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 2 - 3 + xorl %r13d, %edx + andl %r13d, %ecx + rorl $5, %edx + xorl %r15d, %ecx + xorl %r13d, %edx + addl %ecx, %r8d + vpsrld $10, %ymm6, %ymm9 + vpxor %ymm8, %ymm7, %ymm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r9d, %ebx + addl %edx, %r8d + movl %r9d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r9d, %ecx + xorl %r10d, %eax + vpxor %ymm9, %ymm8, %ymm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + vpaddd %ymm4, %ymm9, %ymm3 + # msg_sched done: 24-27 + # set_w_k_xfer_4: 4 + vpaddd 128+L_avx2_sha256_k(%rip), %ymm0, %ymm4 + vpaddd 160+L_avx2_sha256_k(%rip), %ymm1, %ymm5 + vmovdqu %ymm4, 128(%rsp) + vmovdqu %ymm5, 160(%rsp) + vpaddd 192+L_avx2_sha256_k(%rip), %ymm2, %ymm4 + vpaddd 224+L_avx2_sha256_k(%rip), %ymm3, %ymm5 + vmovdqu %ymm4, 192(%rsp) + vmovdqu %ymm5, 224(%rsp) + # msg_sched: 32-35 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %ymm0, %ymm1, %ymm5 + vpalignr $4, %ymm2, %ymm3, %ymm4 + # rnd_0: 1 - 2 + movl %r9d, %eax + movl %r13d, %ecx + addl 128(%rsp), %r15d + xorl %r14d, %ecx + xorl %r12d, %edx + andl %r12d, %ecx + vpsrld $7, %ymm5, %ymm6 + vpslld $25, %ymm5, %ymm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r14d, %ecx + xorl %r12d, %edx + addl %ecx, %r15d + rorl $6, %edx + xorl %r8d, %eax + addl %edx, %r15d + movl %r8d, %ecx + vpsrld $18, %ymm5, %ymm8 + vpslld $14, %ymm5, %ymm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + vpor %ymm6, %ymm7, %ymm6 + vpor %ymm8, %ymm9, %ymm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r8d, %ebx + movl %r12d, %ecx + addl 132(%rsp), %r14d + xorl %r13d, %ecx + vpsrld $3, %ymm5, %ymm9 + vpxor %ymm6, %ymm8, %ymm6 + # rnd_1: 2 - 3 + xorl %r11d, %edx + andl %r11d, %ecx + rorl $5, %edx + xorl %r13d, %ecx + xorl %r11d, %edx + addl %ecx, %r14d + vpxor %ymm6, %ymm9, %ymm5 + vpshufd $0xfa, %ymm3, %ymm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r15d, %ebx + addl %edx, %r14d + movl %r15d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r15d, %ecx + xorl %r8d, %eax + vpsrld $10, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %ymm6, %ymm6 + vpaddd %ymm0, %ymm4, %ymm4 + # rnd_0: 1 - 3 + movl %r15d, %eax + movl %r11d, %ecx + addl 136(%rsp), %r13d + xorl %r12d, %ecx + xorl %r10d, %edx + andl %r10d, %ecx + rorl $5, %edx + xorl %r12d, %ecx + xorl %r10d, %edx + addl %ecx, %r13d + vpxor %ymm6, %ymm7, %ymm6 + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r14d, %eax + addl %edx, %r13d + movl %r14d, %ecx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r14d, %ecx + xorl %r15d, %ebx + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %ymm4, %ymm6 + # rnd_1: 1 - 1 + movl %r14d, %ebx + movl %r10d, %ecx + addl 140(%rsp), %r12d + xorl %r11d, %ecx + vpsrlq $0x11, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 2 - 3 + xorl %r9d, %edx + andl %r9d, %ecx + rorl $5, %edx + xorl %r11d, %ecx + xorl %r9d, %edx + addl %ecx, %r12d + vpsrld $10, %ymm6, %ymm9 + vpxor %ymm8, %ymm7, %ymm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r13d, %ebx + addl %edx, %r12d + movl %r13d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r13d, %ecx + xorl %r14d, %eax + vpxor %ymm9, %ymm8, %ymm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + vpaddd %ymm4, %ymm9, %ymm0 + # msg_sched done: 32-35 + # msg_sched: 40-43 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %ymm1, %ymm2, %ymm5 + vpalignr $4, %ymm3, %ymm0, %ymm4 + # rnd_0: 1 - 2 + movl %r13d, %eax + movl %r9d, %ecx + addl 160(%rsp), %r11d + xorl %r10d, %ecx + xorl %r8d, %edx + andl %r8d, %ecx + vpsrld $7, %ymm5, %ymm6 + vpslld $25, %ymm5, %ymm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r10d, %ecx + xorl %r8d, %edx + addl %ecx, %r11d + rorl $6, %edx + xorl %r12d, %eax + addl %edx, %r11d + movl %r12d, %ecx + vpsrld $18, %ymm5, %ymm8 + vpslld $14, %ymm5, %ymm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + vpor %ymm6, %ymm7, %ymm6 + vpor %ymm8, %ymm9, %ymm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r12d, %ebx + movl %r8d, %ecx + addl 164(%rsp), %r10d + xorl %r9d, %ecx + vpsrld $3, %ymm5, %ymm9 + vpxor %ymm6, %ymm8, %ymm6 + # rnd_1: 2 - 3 + xorl %r15d, %edx + andl %r15d, %ecx + rorl $5, %edx + xorl %r9d, %ecx + xorl %r15d, %edx + addl %ecx, %r10d + vpxor %ymm6, %ymm9, %ymm5 + vpshufd $0xfa, %ymm0, %ymm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r11d, %ebx + addl %edx, %r10d + movl %r11d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r11d, %ecx + xorl %r12d, %eax + vpsrld $10, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %ymm6, %ymm6 + vpaddd %ymm1, %ymm4, %ymm4 + # rnd_0: 1 - 3 + movl %r11d, %eax + movl %r15d, %ecx + addl 168(%rsp), %r9d + xorl %r8d, %ecx + xorl %r14d, %edx + andl %r14d, %ecx + rorl $5, %edx + xorl %r8d, %ecx + xorl %r14d, %edx + addl %ecx, %r9d + vpxor %ymm6, %ymm7, %ymm6 + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r10d, %eax + addl %edx, %r9d + movl %r10d, %ecx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r10d, %ecx + xorl %r11d, %ebx + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %ymm4, %ymm6 + # rnd_1: 1 - 1 + movl %r10d, %ebx + movl %r14d, %ecx + addl 172(%rsp), %r8d + xorl %r15d, %ecx + vpsrlq $0x11, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 2 - 3 + xorl %r13d, %edx + andl %r13d, %ecx + rorl $5, %edx + xorl %r15d, %ecx + xorl %r13d, %edx + addl %ecx, %r8d + vpsrld $10, %ymm6, %ymm9 + vpxor %ymm8, %ymm7, %ymm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r9d, %ebx + addl %edx, %r8d + movl %r9d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r9d, %ecx + xorl %r10d, %eax + vpxor %ymm9, %ymm8, %ymm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + vpaddd %ymm4, %ymm9, %ymm1 + # msg_sched done: 40-43 + # msg_sched: 48-51 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %ymm2, %ymm3, %ymm5 + vpalignr $4, %ymm0, %ymm1, %ymm4 + # rnd_0: 1 - 2 + movl %r9d, %eax + movl %r13d, %ecx + addl 192(%rsp), %r15d + xorl %r14d, %ecx + xorl %r12d, %edx + andl %r12d, %ecx + vpsrld $7, %ymm5, %ymm6 + vpslld $25, %ymm5, %ymm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r14d, %ecx + xorl %r12d, %edx + addl %ecx, %r15d + rorl $6, %edx + xorl %r8d, %eax + addl %edx, %r15d + movl %r8d, %ecx + vpsrld $18, %ymm5, %ymm8 + vpslld $14, %ymm5, %ymm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + vpor %ymm6, %ymm7, %ymm6 + vpor %ymm8, %ymm9, %ymm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r8d, %ebx + movl %r12d, %ecx + addl 196(%rsp), %r14d + xorl %r13d, %ecx + vpsrld $3, %ymm5, %ymm9 + vpxor %ymm6, %ymm8, %ymm6 + # rnd_1: 2 - 3 + xorl %r11d, %edx + andl %r11d, %ecx + rorl $5, %edx + xorl %r13d, %ecx + xorl %r11d, %edx + addl %ecx, %r14d + vpxor %ymm6, %ymm9, %ymm5 + vpshufd $0xfa, %ymm1, %ymm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r15d, %ebx + addl %edx, %r14d + movl %r15d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r15d, %ecx + xorl %r8d, %eax + vpsrld $10, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %ymm6, %ymm6 + vpaddd %ymm2, %ymm4, %ymm4 + # rnd_0: 1 - 3 + movl %r15d, %eax + movl %r11d, %ecx + addl 200(%rsp), %r13d + xorl %r12d, %ecx + xorl %r10d, %edx + andl %r10d, %ecx + rorl $5, %edx + xorl %r12d, %ecx + xorl %r10d, %edx + addl %ecx, %r13d + vpxor %ymm6, %ymm7, %ymm6 + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r14d, %eax + addl %edx, %r13d + movl %r14d, %ecx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r14d, %ecx + xorl %r15d, %ebx + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %ymm4, %ymm6 + # rnd_1: 1 - 1 + movl %r14d, %ebx + movl %r10d, %ecx + addl 204(%rsp), %r12d + xorl %r11d, %ecx + vpsrlq $0x11, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 2 - 3 + xorl %r9d, %edx + andl %r9d, %ecx + rorl $5, %edx + xorl %r11d, %ecx + xorl %r9d, %edx + addl %ecx, %r12d + vpsrld $10, %ymm6, %ymm9 + vpxor %ymm8, %ymm7, %ymm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r13d, %ebx + addl %edx, %r12d + movl %r13d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r13d, %ecx + xorl %r14d, %eax + vpxor %ymm9, %ymm8, %ymm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + vpaddd %ymm4, %ymm9, %ymm2 + # msg_sched done: 48-51 + # msg_sched: 56-59 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %ymm3, %ymm0, %ymm5 + vpalignr $4, %ymm1, %ymm2, %ymm4 + # rnd_0: 1 - 2 + movl %r13d, %eax + movl %r9d, %ecx + addl 224(%rsp), %r11d + xorl %r10d, %ecx + xorl %r8d, %edx + andl %r8d, %ecx + vpsrld $7, %ymm5, %ymm6 + vpslld $25, %ymm5, %ymm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r10d, %ecx + xorl %r8d, %edx + addl %ecx, %r11d + rorl $6, %edx + xorl %r12d, %eax + addl %edx, %r11d + movl %r12d, %ecx + vpsrld $18, %ymm5, %ymm8 + vpslld $14, %ymm5, %ymm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + vpor %ymm6, %ymm7, %ymm6 + vpor %ymm8, %ymm9, %ymm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r12d, %ebx + movl %r8d, %ecx + addl 228(%rsp), %r10d + xorl %r9d, %ecx + vpsrld $3, %ymm5, %ymm9 + vpxor %ymm6, %ymm8, %ymm6 + # rnd_1: 2 - 3 + xorl %r15d, %edx + andl %r15d, %ecx + rorl $5, %edx + xorl %r9d, %ecx + xorl %r15d, %edx + addl %ecx, %r10d + vpxor %ymm6, %ymm9, %ymm5 + vpshufd $0xfa, %ymm2, %ymm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r11d, %ebx + addl %edx, %r10d + movl %r11d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r11d, %ecx + xorl %r12d, %eax + vpsrld $10, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %ymm6, %ymm6 + vpaddd %ymm3, %ymm4, %ymm4 + # rnd_0: 1 - 3 + movl %r11d, %eax + movl %r15d, %ecx + addl 232(%rsp), %r9d + xorl %r8d, %ecx + xorl %r14d, %edx + andl %r14d, %ecx + rorl $5, %edx + xorl %r8d, %ecx + xorl %r14d, %edx + addl %ecx, %r9d + vpxor %ymm6, %ymm7, %ymm6 + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r10d, %eax + addl %edx, %r9d + movl %r10d, %ecx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r10d, %ecx + xorl %r11d, %ebx + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %ymm4, %ymm6 + # rnd_1: 1 - 1 + movl %r10d, %ebx + movl %r14d, %ecx + addl 236(%rsp), %r8d + xorl %r15d, %ecx + vpsrlq $0x11, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 2 - 3 + xorl %r13d, %edx + andl %r13d, %ecx + rorl $5, %edx + xorl %r15d, %ecx + xorl %r13d, %edx + addl %ecx, %r8d + vpsrld $10, %ymm6, %ymm9 + vpxor %ymm8, %ymm7, %ymm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r9d, %ebx + addl %edx, %r8d + movl %r9d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r9d, %ecx + xorl %r10d, %eax + vpxor %ymm9, %ymm8, %ymm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + vpaddd %ymm4, %ymm9, %ymm3 + # msg_sched done: 56-59 + # set_w_k_xfer_4: 8 + vpaddd 256+L_avx2_sha256_k(%rip), %ymm0, %ymm4 + vpaddd 288+L_avx2_sha256_k(%rip), %ymm1, %ymm5 + vmovdqu %ymm4, 256(%rsp) + vmovdqu %ymm5, 288(%rsp) + vpaddd 320+L_avx2_sha256_k(%rip), %ymm2, %ymm4 + vpaddd 352+L_avx2_sha256_k(%rip), %ymm3, %ymm5 + vmovdqu %ymm4, 320(%rsp) + vmovdqu %ymm5, 352(%rsp) + # msg_sched: 64-67 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %ymm0, %ymm1, %ymm5 + vpalignr $4, %ymm2, %ymm3, %ymm4 + # rnd_0: 1 - 2 + movl %r9d, %eax + movl %r13d, %ecx + addl 256(%rsp), %r15d + xorl %r14d, %ecx + xorl %r12d, %edx + andl %r12d, %ecx + vpsrld $7, %ymm5, %ymm6 + vpslld $25, %ymm5, %ymm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r14d, %ecx + xorl %r12d, %edx + addl %ecx, %r15d + rorl $6, %edx + xorl %r8d, %eax + addl %edx, %r15d + movl %r8d, %ecx + vpsrld $18, %ymm5, %ymm8 + vpslld $14, %ymm5, %ymm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + vpor %ymm6, %ymm7, %ymm6 + vpor %ymm8, %ymm9, %ymm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r8d, %ebx + movl %r12d, %ecx + addl 260(%rsp), %r14d + xorl %r13d, %ecx + vpsrld $3, %ymm5, %ymm9 + vpxor %ymm6, %ymm8, %ymm6 + # rnd_1: 2 - 3 + xorl %r11d, %edx + andl %r11d, %ecx + rorl $5, %edx + xorl %r13d, %ecx + xorl %r11d, %edx + addl %ecx, %r14d + vpxor %ymm6, %ymm9, %ymm5 + vpshufd $0xfa, %ymm3, %ymm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r15d, %ebx + addl %edx, %r14d + movl %r15d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r15d, %ecx + xorl %r8d, %eax + vpsrld $10, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %ymm6, %ymm6 + vpaddd %ymm0, %ymm4, %ymm4 + # rnd_0: 1 - 3 + movl %r15d, %eax + movl %r11d, %ecx + addl 264(%rsp), %r13d + xorl %r12d, %ecx + xorl %r10d, %edx + andl %r10d, %ecx + rorl $5, %edx + xorl %r12d, %ecx + xorl %r10d, %edx + addl %ecx, %r13d + vpxor %ymm6, %ymm7, %ymm6 + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r14d, %eax + addl %edx, %r13d + movl %r14d, %ecx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r14d, %ecx + xorl %r15d, %ebx + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %ymm4, %ymm6 + # rnd_1: 1 - 1 + movl %r14d, %ebx + movl %r10d, %ecx + addl 268(%rsp), %r12d + xorl %r11d, %ecx + vpsrlq $0x11, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 2 - 3 + xorl %r9d, %edx + andl %r9d, %ecx + rorl $5, %edx + xorl %r11d, %ecx + xorl %r9d, %edx + addl %ecx, %r12d + vpsrld $10, %ymm6, %ymm9 + vpxor %ymm8, %ymm7, %ymm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r13d, %ebx + addl %edx, %r12d + movl %r13d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r13d, %ecx + xorl %r14d, %eax + vpxor %ymm9, %ymm8, %ymm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + vpaddd %ymm4, %ymm9, %ymm0 + # msg_sched done: 64-67 + # msg_sched: 72-75 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %ymm1, %ymm2, %ymm5 + vpalignr $4, %ymm3, %ymm0, %ymm4 + # rnd_0: 1 - 2 + movl %r13d, %eax + movl %r9d, %ecx + addl 288(%rsp), %r11d + xorl %r10d, %ecx + xorl %r8d, %edx + andl %r8d, %ecx + vpsrld $7, %ymm5, %ymm6 + vpslld $25, %ymm5, %ymm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r10d, %ecx + xorl %r8d, %edx + addl %ecx, %r11d + rorl $6, %edx + xorl %r12d, %eax + addl %edx, %r11d + movl %r12d, %ecx + vpsrld $18, %ymm5, %ymm8 + vpslld $14, %ymm5, %ymm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + vpor %ymm6, %ymm7, %ymm6 + vpor %ymm8, %ymm9, %ymm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r12d, %ebx + movl %r8d, %ecx + addl 292(%rsp), %r10d + xorl %r9d, %ecx + vpsrld $3, %ymm5, %ymm9 + vpxor %ymm6, %ymm8, %ymm6 + # rnd_1: 2 - 3 + xorl %r15d, %edx + andl %r15d, %ecx + rorl $5, %edx + xorl %r9d, %ecx + xorl %r15d, %edx + addl %ecx, %r10d + vpxor %ymm6, %ymm9, %ymm5 + vpshufd $0xfa, %ymm0, %ymm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r11d, %ebx + addl %edx, %r10d + movl %r11d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r11d, %ecx + xorl %r12d, %eax + vpsrld $10, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %ymm6, %ymm6 + vpaddd %ymm1, %ymm4, %ymm4 + # rnd_0: 1 - 3 + movl %r11d, %eax + movl %r15d, %ecx + addl 296(%rsp), %r9d + xorl %r8d, %ecx + xorl %r14d, %edx + andl %r14d, %ecx + rorl $5, %edx + xorl %r8d, %ecx + xorl %r14d, %edx + addl %ecx, %r9d + vpxor %ymm6, %ymm7, %ymm6 + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r10d, %eax + addl %edx, %r9d + movl %r10d, %ecx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r10d, %ecx + xorl %r11d, %ebx + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %ymm4, %ymm6 + # rnd_1: 1 - 1 + movl %r10d, %ebx + movl %r14d, %ecx + addl 300(%rsp), %r8d + xorl %r15d, %ecx + vpsrlq $0x11, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 2 - 3 + xorl %r13d, %edx + andl %r13d, %ecx + rorl $5, %edx + xorl %r15d, %ecx + xorl %r13d, %edx + addl %ecx, %r8d + vpsrld $10, %ymm6, %ymm9 + vpxor %ymm8, %ymm7, %ymm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r9d, %ebx + addl %edx, %r8d + movl %r9d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r9d, %ecx + xorl %r10d, %eax + vpxor %ymm9, %ymm8, %ymm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + vpaddd %ymm4, %ymm9, %ymm1 + # msg_sched done: 72-75 + # msg_sched: 80-83 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %ymm2, %ymm3, %ymm5 + vpalignr $4, %ymm0, %ymm1, %ymm4 + # rnd_0: 1 - 2 + movl %r9d, %eax + movl %r13d, %ecx + addl 320(%rsp), %r15d + xorl %r14d, %ecx + xorl %r12d, %edx + andl %r12d, %ecx + vpsrld $7, %ymm5, %ymm6 + vpslld $25, %ymm5, %ymm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r14d, %ecx + xorl %r12d, %edx + addl %ecx, %r15d + rorl $6, %edx + xorl %r8d, %eax + addl %edx, %r15d + movl %r8d, %ecx + vpsrld $18, %ymm5, %ymm8 + vpslld $14, %ymm5, %ymm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + vpor %ymm6, %ymm7, %ymm6 + vpor %ymm8, %ymm9, %ymm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r8d, %ebx + movl %r12d, %ecx + addl 324(%rsp), %r14d + xorl %r13d, %ecx + vpsrld $3, %ymm5, %ymm9 + vpxor %ymm6, %ymm8, %ymm6 + # rnd_1: 2 - 3 + xorl %r11d, %edx + andl %r11d, %ecx + rorl $5, %edx + xorl %r13d, %ecx + xorl %r11d, %edx + addl %ecx, %r14d + vpxor %ymm6, %ymm9, %ymm5 + vpshufd $0xfa, %ymm1, %ymm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r15d, %ebx + addl %edx, %r14d + movl %r15d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r15d, %ecx + xorl %r8d, %eax + vpsrld $10, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %ymm6, %ymm6 + vpaddd %ymm2, %ymm4, %ymm4 + # rnd_0: 1 - 3 + movl %r15d, %eax + movl %r11d, %ecx + addl 328(%rsp), %r13d + xorl %r12d, %ecx + xorl %r10d, %edx + andl %r10d, %ecx + rorl $5, %edx + xorl %r12d, %ecx + xorl %r10d, %edx + addl %ecx, %r13d + vpxor %ymm6, %ymm7, %ymm6 + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r14d, %eax + addl %edx, %r13d + movl %r14d, %ecx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r14d, %ecx + xorl %r15d, %ebx + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %ymm4, %ymm6 + # rnd_1: 1 - 1 + movl %r14d, %ebx + movl %r10d, %ecx + addl 332(%rsp), %r12d + xorl %r11d, %ecx + vpsrlq $0x11, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 2 - 3 + xorl %r9d, %edx + andl %r9d, %ecx + rorl $5, %edx + xorl %r11d, %ecx + xorl %r9d, %edx + addl %ecx, %r12d + vpsrld $10, %ymm6, %ymm9 + vpxor %ymm8, %ymm7, %ymm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r13d, %ebx + addl %edx, %r12d + movl %r13d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r13d, %ecx + xorl %r14d, %eax + vpxor %ymm9, %ymm8, %ymm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + vpaddd %ymm4, %ymm9, %ymm2 + # msg_sched done: 80-83 + # msg_sched: 88-91 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %ymm3, %ymm0, %ymm5 + vpalignr $4, %ymm1, %ymm2, %ymm4 + # rnd_0: 1 - 2 + movl %r13d, %eax + movl %r9d, %ecx + addl 352(%rsp), %r11d + xorl %r10d, %ecx + xorl %r8d, %edx + andl %r8d, %ecx + vpsrld $7, %ymm5, %ymm6 + vpslld $25, %ymm5, %ymm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r10d, %ecx + xorl %r8d, %edx + addl %ecx, %r11d + rorl $6, %edx + xorl %r12d, %eax + addl %edx, %r11d + movl %r12d, %ecx + vpsrld $18, %ymm5, %ymm8 + vpslld $14, %ymm5, %ymm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + vpor %ymm6, %ymm7, %ymm6 + vpor %ymm8, %ymm9, %ymm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r12d, %ebx + movl %r8d, %ecx + addl 356(%rsp), %r10d + xorl %r9d, %ecx + vpsrld $3, %ymm5, %ymm9 + vpxor %ymm6, %ymm8, %ymm6 + # rnd_1: 2 - 3 + xorl %r15d, %edx + andl %r15d, %ecx + rorl $5, %edx + xorl %r9d, %ecx + xorl %r15d, %edx + addl %ecx, %r10d + vpxor %ymm6, %ymm9, %ymm5 + vpshufd $0xfa, %ymm2, %ymm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r11d, %ebx + addl %edx, %r10d + movl %r11d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r11d, %ecx + xorl %r12d, %eax + vpsrld $10, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %ymm6, %ymm6 + vpaddd %ymm3, %ymm4, %ymm4 + # rnd_0: 1 - 3 + movl %r11d, %eax + movl %r15d, %ecx + addl 360(%rsp), %r9d + xorl %r8d, %ecx + xorl %r14d, %edx + andl %r14d, %ecx + rorl $5, %edx + xorl %r8d, %ecx + xorl %r14d, %edx + addl %ecx, %r9d + vpxor %ymm6, %ymm7, %ymm6 + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r10d, %eax + addl %edx, %r9d + movl %r10d, %ecx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r10d, %ecx + xorl %r11d, %ebx + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %ymm4, %ymm6 + # rnd_1: 1 - 1 + movl %r10d, %ebx + movl %r14d, %ecx + addl 364(%rsp), %r8d + xorl %r15d, %ecx + vpsrlq $0x11, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 2 - 3 + xorl %r13d, %edx + andl %r13d, %ecx + rorl $5, %edx + xorl %r15d, %ecx + xorl %r13d, %edx + addl %ecx, %r8d + vpsrld $10, %ymm6, %ymm9 + vpxor %ymm8, %ymm7, %ymm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r9d, %ebx + addl %edx, %r8d + movl %r9d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r9d, %ecx + xorl %r10d, %eax + vpxor %ymm9, %ymm8, %ymm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + vpaddd %ymm4, %ymm9, %ymm3 + # msg_sched done: 88-91 + # set_w_k_xfer_4: 12 + vpaddd 384+L_avx2_sha256_k(%rip), %ymm0, %ymm4 + vpaddd 416+L_avx2_sha256_k(%rip), %ymm1, %ymm5 + vmovdqu %ymm4, 384(%rsp) + vmovdqu %ymm5, 416(%rsp) + vpaddd 448+L_avx2_sha256_k(%rip), %ymm2, %ymm4 + vpaddd 480+L_avx2_sha256_k(%rip), %ymm3, %ymm5 + vmovdqu %ymm4, 448(%rsp) + vmovdqu %ymm5, 480(%rsp) + # rnd_all_4: 24-27 + addl 384(%rsp), %r15d + movl %r13d, %ecx + movl %r9d, %eax + xorl %r14d, %ecx + rorl $14, %edx + andl %r12d, %ecx + xorl %r12d, %edx + xorl %r14d, %ecx + rorl $5, %edx + addl %ecx, %r15d + xorl %r12d, %edx + xorl %r8d, %eax + rorl $6, %edx + movl %r8d, %ecx + addl %edx, %r15d + rorl $9, %ecx + andl %eax, %ebx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + addl 388(%rsp), %r14d + movl %r12d, %ecx + movl %r8d, %ebx + xorl %r13d, %ecx + rorl $14, %edx + andl %r11d, %ecx + xorl %r11d, %edx + xorl %r13d, %ecx + rorl $5, %edx + addl %ecx, %r14d + xorl %r11d, %edx + xorl %r15d, %ebx + rorl $6, %edx + movl %r15d, %ecx + addl %edx, %r14d + rorl $9, %ecx + andl %ebx, %eax + xorl %r15d, %ecx + xorl %r8d, %eax + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + addl 392(%rsp), %r13d + movl %r11d, %ecx + movl %r15d, %eax + xorl %r12d, %ecx + rorl $14, %edx + andl %r10d, %ecx + xorl %r10d, %edx + xorl %r12d, %ecx + rorl $5, %edx + addl %ecx, %r13d + xorl %r10d, %edx + xorl %r14d, %eax + rorl $6, %edx + movl %r14d, %ecx + addl %edx, %r13d + rorl $9, %ecx + andl %eax, %ebx + xorl %r14d, %ecx + xorl %r15d, %ebx + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + addl 396(%rsp), %r12d + movl %r10d, %ecx + movl %r14d, %ebx + xorl %r11d, %ecx + rorl $14, %edx + andl %r9d, %ecx + xorl %r9d, %edx + xorl %r11d, %ecx + rorl $5, %edx + addl %ecx, %r12d + xorl %r9d, %edx + xorl %r13d, %ebx + rorl $6, %edx + movl %r13d, %ecx + addl %edx, %r12d + rorl $9, %ecx + andl %ebx, %eax + xorl %r13d, %ecx + xorl %r14d, %eax + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + # rnd_all_4: 26-29 + addl 416(%rsp), %r11d + movl %r9d, %ecx + movl %r13d, %eax + xorl %r10d, %ecx + rorl $14, %edx + andl %r8d, %ecx + xorl %r8d, %edx + xorl %r10d, %ecx + rorl $5, %edx + addl %ecx, %r11d + xorl %r8d, %edx + xorl %r12d, %eax + rorl $6, %edx + movl %r12d, %ecx + addl %edx, %r11d + rorl $9, %ecx + andl %eax, %ebx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + addl 420(%rsp), %r10d + movl %r8d, %ecx + movl %r12d, %ebx + xorl %r9d, %ecx + rorl $14, %edx + andl %r15d, %ecx + xorl %r15d, %edx + xorl %r9d, %ecx + rorl $5, %edx + addl %ecx, %r10d + xorl %r15d, %edx + xorl %r11d, %ebx + rorl $6, %edx + movl %r11d, %ecx + addl %edx, %r10d + rorl $9, %ecx + andl %ebx, %eax + xorl %r11d, %ecx + xorl %r12d, %eax + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + addl 424(%rsp), %r9d + movl %r15d, %ecx + movl %r11d, %eax + xorl %r8d, %ecx + rorl $14, %edx + andl %r14d, %ecx + xorl %r14d, %edx + xorl %r8d, %ecx + rorl $5, %edx + addl %ecx, %r9d + xorl %r14d, %edx + xorl %r10d, %eax + rorl $6, %edx + movl %r10d, %ecx + addl %edx, %r9d + rorl $9, %ecx + andl %eax, %ebx + xorl %r10d, %ecx + xorl %r11d, %ebx + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + addl 428(%rsp), %r8d + movl %r14d, %ecx + movl %r10d, %ebx + xorl %r15d, %ecx + rorl $14, %edx + andl %r13d, %ecx + xorl %r13d, %edx + xorl %r15d, %ecx + rorl $5, %edx + addl %ecx, %r8d + xorl %r13d, %edx + xorl %r9d, %ebx + rorl $6, %edx + movl %r9d, %ecx + addl %edx, %r8d + rorl $9, %ecx + andl %ebx, %eax + xorl %r9d, %ecx + xorl %r10d, %eax + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + # rnd_all_4: 28-31 + addl 448(%rsp), %r15d + movl %r13d, %ecx + movl %r9d, %eax + xorl %r14d, %ecx + rorl $14, %edx + andl %r12d, %ecx + xorl %r12d, %edx + xorl %r14d, %ecx + rorl $5, %edx + addl %ecx, %r15d + xorl %r12d, %edx + xorl %r8d, %eax + rorl $6, %edx + movl %r8d, %ecx + addl %edx, %r15d + rorl $9, %ecx + andl %eax, %ebx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + addl 452(%rsp), %r14d + movl %r12d, %ecx + movl %r8d, %ebx + xorl %r13d, %ecx + rorl $14, %edx + andl %r11d, %ecx + xorl %r11d, %edx + xorl %r13d, %ecx + rorl $5, %edx + addl %ecx, %r14d + xorl %r11d, %edx + xorl %r15d, %ebx + rorl $6, %edx + movl %r15d, %ecx + addl %edx, %r14d + rorl $9, %ecx + andl %ebx, %eax + xorl %r15d, %ecx + xorl %r8d, %eax + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + addl 456(%rsp), %r13d + movl %r11d, %ecx + movl %r15d, %eax + xorl %r12d, %ecx + rorl $14, %edx + andl %r10d, %ecx + xorl %r10d, %edx + xorl %r12d, %ecx + rorl $5, %edx + addl %ecx, %r13d + xorl %r10d, %edx + xorl %r14d, %eax + rorl $6, %edx + movl %r14d, %ecx + addl %edx, %r13d + rorl $9, %ecx + andl %eax, %ebx + xorl %r14d, %ecx + xorl %r15d, %ebx + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + addl 460(%rsp), %r12d + movl %r10d, %ecx + movl %r14d, %ebx + xorl %r11d, %ecx + rorl $14, %edx + andl %r9d, %ecx + xorl %r9d, %edx + xorl %r11d, %ecx + rorl $5, %edx + addl %ecx, %r12d + xorl %r9d, %edx + xorl %r13d, %ebx + rorl $6, %edx + movl %r13d, %ecx + addl %edx, %r12d + rorl $9, %ecx + andl %ebx, %eax + xorl %r13d, %ecx + xorl %r14d, %eax + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + # rnd_all_4: 30-33 + addl 480(%rsp), %r11d + movl %r9d, %ecx + movl %r13d, %eax + xorl %r10d, %ecx + rorl $14, %edx + andl %r8d, %ecx + xorl %r8d, %edx + xorl %r10d, %ecx + rorl $5, %edx + addl %ecx, %r11d + xorl %r8d, %edx + xorl %r12d, %eax + rorl $6, %edx + movl %r12d, %ecx + addl %edx, %r11d + rorl $9, %ecx + andl %eax, %ebx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + addl 484(%rsp), %r10d + movl %r8d, %ecx + movl %r12d, %ebx + xorl %r9d, %ecx + rorl $14, %edx + andl %r15d, %ecx + xorl %r15d, %edx + xorl %r9d, %ecx + rorl $5, %edx + addl %ecx, %r10d + xorl %r15d, %edx + xorl %r11d, %ebx + rorl $6, %edx + movl %r11d, %ecx + addl %edx, %r10d + rorl $9, %ecx + andl %ebx, %eax + xorl %r11d, %ecx + xorl %r12d, %eax + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + addl 488(%rsp), %r9d + movl %r15d, %ecx + movl %r11d, %eax + xorl %r8d, %ecx + rorl $14, %edx + andl %r14d, %ecx + xorl %r14d, %edx + xorl %r8d, %ecx + rorl $5, %edx + addl %ecx, %r9d + xorl %r14d, %edx + xorl %r10d, %eax + rorl $6, %edx + movl %r10d, %ecx + addl %edx, %r9d + rorl $9, %ecx + andl %eax, %ebx + xorl %r10d, %ecx + xorl %r11d, %ebx + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + addl 492(%rsp), %r8d + movl %r14d, %ecx + movl %r10d, %ebx + xorl %r15d, %ecx + rorl $14, %edx + andl %r13d, %ecx + xorl %r13d, %edx + xorl %r15d, %ecx + rorl $5, %edx + addl %ecx, %r8d + xorl %r13d, %edx + xorl %r9d, %ebx + rorl $6, %edx + movl %r9d, %ecx + addl %edx, %r8d + rorl $9, %ecx + andl %ebx, %eax + xorl %r9d, %ecx + xorl %r10d, %eax + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + addl %r8d, (%rdi) + addl %r9d, 4(%rdi) + addl %r10d, 8(%rdi) + addl %r11d, 12(%rdi) + addl %r12d, 16(%rdi) + addl %r13d, 20(%rdi) + addl %r14d, 24(%rdi) + addl %r15d, 28(%rdi) + xorq %rax, %rax + vzeroupper + addq $0x200, %rsp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size Transform_Sha256_AVX2,.-Transform_Sha256_AVX2 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl Transform_Sha256_AVX2_Len +.type Transform_Sha256_AVX2_Len,@function +.align 4 +Transform_Sha256_AVX2_Len: +#else +.section __TEXT,__text +.globl _Transform_Sha256_AVX2_Len +.p2align 2 +_Transform_Sha256_AVX2_Len: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + pushq %rbp + movq %rsi, %rbp + movq %rdx, %rsi + subq $0x200, %rsp + testb $0x40, %sil + je L_sha256_len_avx2_block + vmovdqu (%rbp), %ymm0 + vmovdqu 32(%rbp), %ymm1 + vmovups %ymm0, 32(%rdi) + vmovups %ymm1, 64(%rdi) +#ifndef __APPLE__ + call Transform_Sha256_AVX2@plt +#else + call _Transform_Sha256_AVX2 +#endif /* __APPLE__ */ + addq $0x40, %rbp + subl $0x40, %esi + jz L_sha256_len_avx2_done +L_sha256_len_avx2_block: + vmovdqa L_avx2_sha256_flip_mask(%rip), %ymm13 + vmovdqa L_avx2_sha256_shuf_00BA(%rip), %ymm11 + vmovdqa L_avx2_sha256_shuf_DC00(%rip), %ymm12 + movl (%rdi), %r8d + movl 4(%rdi), %r9d + movl 8(%rdi), %r10d + movl 12(%rdi), %r11d + movl 16(%rdi), %r12d + movl 20(%rdi), %r13d + movl 24(%rdi), %r14d + movl 28(%rdi), %r15d + # Start of loop processing two blocks +L_sha256_len_avx2_start: + # X0, X1, X2, X3 = W[0..15] + vmovdqu (%rbp), %xmm0 + vmovdqu 16(%rbp), %xmm1 + vmovdqu 64(%rbp), %xmm4 + vmovdqu 80(%rbp), %xmm5 + vinserti128 $0x01, %xmm4, %ymm0, %ymm0 + vinserti128 $0x01, %xmm5, %ymm1, %ymm1 + vpshufb %ymm13, %ymm0, %ymm0 + vpshufb %ymm13, %ymm1, %ymm1 + vmovdqu 32(%rbp), %xmm2 + vmovdqu 48(%rbp), %xmm3 + vmovdqu 96(%rbp), %xmm6 + vmovdqu 112(%rbp), %xmm7 + vinserti128 $0x01, %xmm6, %ymm2, %ymm2 + vinserti128 $0x01, %xmm7, %ymm3, %ymm3 + vpshufb %ymm13, %ymm2, %ymm2 + vpshufb %ymm13, %ymm3, %ymm3 + movl %r9d, %ebx + movl %r12d, %edx + xorl %r10d, %ebx + # set_w_k_xfer_4: 0 + vpaddd 0+L_avx2_sha256_k(%rip), %ymm0, %ymm4 + vpaddd 32+L_avx2_sha256_k(%rip), %ymm1, %ymm5 + vmovdqu %ymm4, (%rsp) + vmovdqu %ymm5, 32(%rsp) + vpaddd 64+L_avx2_sha256_k(%rip), %ymm2, %ymm4 + vpaddd 96+L_avx2_sha256_k(%rip), %ymm3, %ymm5 + vmovdqu %ymm4, 64(%rsp) + vmovdqu %ymm5, 96(%rsp) + # msg_sched: 0-3 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %ymm0, %ymm1, %ymm5 + vpalignr $4, %ymm2, %ymm3, %ymm4 + # rnd_0: 1 - 2 + movl %r9d, %eax + movl %r13d, %ecx + addl (%rsp), %r15d + xorl %r14d, %ecx + xorl %r12d, %edx + andl %r12d, %ecx + vpsrld $7, %ymm5, %ymm6 + vpslld $25, %ymm5, %ymm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r14d, %ecx + xorl %r12d, %edx + addl %ecx, %r15d + rorl $6, %edx + xorl %r8d, %eax + addl %edx, %r15d + movl %r8d, %ecx + vpsrld $18, %ymm5, %ymm8 + vpslld $14, %ymm5, %ymm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + vpor %ymm6, %ymm7, %ymm6 + vpor %ymm8, %ymm9, %ymm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r8d, %ebx + movl %r12d, %ecx + addl 4(%rsp), %r14d + xorl %r13d, %ecx + vpsrld $3, %ymm5, %ymm9 + vpxor %ymm6, %ymm8, %ymm6 + # rnd_1: 2 - 3 + xorl %r11d, %edx + andl %r11d, %ecx + rorl $5, %edx + xorl %r13d, %ecx + xorl %r11d, %edx + addl %ecx, %r14d + vpxor %ymm6, %ymm9, %ymm5 + vpshufd $0xfa, %ymm3, %ymm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r15d, %ebx + addl %edx, %r14d + movl %r15d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r15d, %ecx + xorl %r8d, %eax + vpsrld $10, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %ymm6, %ymm6 + vpaddd %ymm0, %ymm4, %ymm4 + # rnd_0: 1 - 3 + movl %r15d, %eax + movl %r11d, %ecx + addl 8(%rsp), %r13d + xorl %r12d, %ecx + xorl %r10d, %edx + andl %r10d, %ecx + rorl $5, %edx + xorl %r12d, %ecx + xorl %r10d, %edx + addl %ecx, %r13d + vpxor %ymm6, %ymm7, %ymm6 + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r14d, %eax + addl %edx, %r13d + movl %r14d, %ecx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r14d, %ecx + xorl %r15d, %ebx + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %ymm4, %ymm6 + # rnd_1: 1 - 1 + movl %r14d, %ebx + movl %r10d, %ecx + addl 12(%rsp), %r12d + xorl %r11d, %ecx + vpsrlq $0x11, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 2 - 3 + xorl %r9d, %edx + andl %r9d, %ecx + rorl $5, %edx + xorl %r11d, %ecx + xorl %r9d, %edx + addl %ecx, %r12d + vpsrld $10, %ymm6, %ymm9 + vpxor %ymm8, %ymm7, %ymm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r13d, %ebx + addl %edx, %r12d + movl %r13d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r13d, %ecx + xorl %r14d, %eax + vpxor %ymm9, %ymm8, %ymm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + vpaddd %ymm4, %ymm9, %ymm0 + # msg_sched done: 0-3 + # msg_sched: 8-11 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %ymm1, %ymm2, %ymm5 + vpalignr $4, %ymm3, %ymm0, %ymm4 + # rnd_0: 1 - 2 + movl %r13d, %eax + movl %r9d, %ecx + addl 32(%rsp), %r11d + xorl %r10d, %ecx + xorl %r8d, %edx + andl %r8d, %ecx + vpsrld $7, %ymm5, %ymm6 + vpslld $25, %ymm5, %ymm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r10d, %ecx + xorl %r8d, %edx + addl %ecx, %r11d + rorl $6, %edx + xorl %r12d, %eax + addl %edx, %r11d + movl %r12d, %ecx + vpsrld $18, %ymm5, %ymm8 + vpslld $14, %ymm5, %ymm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + vpor %ymm6, %ymm7, %ymm6 + vpor %ymm8, %ymm9, %ymm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r12d, %ebx + movl %r8d, %ecx + addl 36(%rsp), %r10d + xorl %r9d, %ecx + vpsrld $3, %ymm5, %ymm9 + vpxor %ymm6, %ymm8, %ymm6 + # rnd_1: 2 - 3 + xorl %r15d, %edx + andl %r15d, %ecx + rorl $5, %edx + xorl %r9d, %ecx + xorl %r15d, %edx + addl %ecx, %r10d + vpxor %ymm6, %ymm9, %ymm5 + vpshufd $0xfa, %ymm0, %ymm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r11d, %ebx + addl %edx, %r10d + movl %r11d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r11d, %ecx + xorl %r12d, %eax + vpsrld $10, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %ymm6, %ymm6 + vpaddd %ymm1, %ymm4, %ymm4 + # rnd_0: 1 - 3 + movl %r11d, %eax + movl %r15d, %ecx + addl 40(%rsp), %r9d + xorl %r8d, %ecx + xorl %r14d, %edx + andl %r14d, %ecx + rorl $5, %edx + xorl %r8d, %ecx + xorl %r14d, %edx + addl %ecx, %r9d + vpxor %ymm6, %ymm7, %ymm6 + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r10d, %eax + addl %edx, %r9d + movl %r10d, %ecx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r10d, %ecx + xorl %r11d, %ebx + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %ymm4, %ymm6 + # rnd_1: 1 - 1 + movl %r10d, %ebx + movl %r14d, %ecx + addl 44(%rsp), %r8d + xorl %r15d, %ecx + vpsrlq $0x11, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 2 - 3 + xorl %r13d, %edx + andl %r13d, %ecx + rorl $5, %edx + xorl %r15d, %ecx + xorl %r13d, %edx + addl %ecx, %r8d + vpsrld $10, %ymm6, %ymm9 + vpxor %ymm8, %ymm7, %ymm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r9d, %ebx + addl %edx, %r8d + movl %r9d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r9d, %ecx + xorl %r10d, %eax + vpxor %ymm9, %ymm8, %ymm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + vpaddd %ymm4, %ymm9, %ymm1 + # msg_sched done: 8-11 + # msg_sched: 16-19 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %ymm2, %ymm3, %ymm5 + vpalignr $4, %ymm0, %ymm1, %ymm4 + # rnd_0: 1 - 2 + movl %r9d, %eax + movl %r13d, %ecx + addl 64(%rsp), %r15d + xorl %r14d, %ecx + xorl %r12d, %edx + andl %r12d, %ecx + vpsrld $7, %ymm5, %ymm6 + vpslld $25, %ymm5, %ymm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r14d, %ecx + xorl %r12d, %edx + addl %ecx, %r15d + rorl $6, %edx + xorl %r8d, %eax + addl %edx, %r15d + movl %r8d, %ecx + vpsrld $18, %ymm5, %ymm8 + vpslld $14, %ymm5, %ymm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + vpor %ymm6, %ymm7, %ymm6 + vpor %ymm8, %ymm9, %ymm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r8d, %ebx + movl %r12d, %ecx + addl 68(%rsp), %r14d + xorl %r13d, %ecx + vpsrld $3, %ymm5, %ymm9 + vpxor %ymm6, %ymm8, %ymm6 + # rnd_1: 2 - 3 + xorl %r11d, %edx + andl %r11d, %ecx + rorl $5, %edx + xorl %r13d, %ecx + xorl %r11d, %edx + addl %ecx, %r14d + vpxor %ymm6, %ymm9, %ymm5 + vpshufd $0xfa, %ymm1, %ymm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r15d, %ebx + addl %edx, %r14d + movl %r15d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r15d, %ecx + xorl %r8d, %eax + vpsrld $10, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %ymm6, %ymm6 + vpaddd %ymm2, %ymm4, %ymm4 + # rnd_0: 1 - 3 + movl %r15d, %eax + movl %r11d, %ecx + addl 72(%rsp), %r13d + xorl %r12d, %ecx + xorl %r10d, %edx + andl %r10d, %ecx + rorl $5, %edx + xorl %r12d, %ecx + xorl %r10d, %edx + addl %ecx, %r13d + vpxor %ymm6, %ymm7, %ymm6 + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r14d, %eax + addl %edx, %r13d + movl %r14d, %ecx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r14d, %ecx + xorl %r15d, %ebx + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %ymm4, %ymm6 + # rnd_1: 1 - 1 + movl %r14d, %ebx + movl %r10d, %ecx + addl 76(%rsp), %r12d + xorl %r11d, %ecx + vpsrlq $0x11, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 2 - 3 + xorl %r9d, %edx + andl %r9d, %ecx + rorl $5, %edx + xorl %r11d, %ecx + xorl %r9d, %edx + addl %ecx, %r12d + vpsrld $10, %ymm6, %ymm9 + vpxor %ymm8, %ymm7, %ymm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r13d, %ebx + addl %edx, %r12d + movl %r13d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r13d, %ecx + xorl %r14d, %eax + vpxor %ymm9, %ymm8, %ymm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + vpaddd %ymm4, %ymm9, %ymm2 + # msg_sched done: 16-19 + # msg_sched: 24-27 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %ymm3, %ymm0, %ymm5 + vpalignr $4, %ymm1, %ymm2, %ymm4 + # rnd_0: 1 - 2 + movl %r13d, %eax + movl %r9d, %ecx + addl 96(%rsp), %r11d + xorl %r10d, %ecx + xorl %r8d, %edx + andl %r8d, %ecx + vpsrld $7, %ymm5, %ymm6 + vpslld $25, %ymm5, %ymm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r10d, %ecx + xorl %r8d, %edx + addl %ecx, %r11d + rorl $6, %edx + xorl %r12d, %eax + addl %edx, %r11d + movl %r12d, %ecx + vpsrld $18, %ymm5, %ymm8 + vpslld $14, %ymm5, %ymm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + vpor %ymm6, %ymm7, %ymm6 + vpor %ymm8, %ymm9, %ymm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r12d, %ebx + movl %r8d, %ecx + addl 100(%rsp), %r10d + xorl %r9d, %ecx + vpsrld $3, %ymm5, %ymm9 + vpxor %ymm6, %ymm8, %ymm6 + # rnd_1: 2 - 3 + xorl %r15d, %edx + andl %r15d, %ecx + rorl $5, %edx + xorl %r9d, %ecx + xorl %r15d, %edx + addl %ecx, %r10d + vpxor %ymm6, %ymm9, %ymm5 + vpshufd $0xfa, %ymm2, %ymm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r11d, %ebx + addl %edx, %r10d + movl %r11d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r11d, %ecx + xorl %r12d, %eax + vpsrld $10, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %ymm6, %ymm6 + vpaddd %ymm3, %ymm4, %ymm4 + # rnd_0: 1 - 3 + movl %r11d, %eax + movl %r15d, %ecx + addl 104(%rsp), %r9d + xorl %r8d, %ecx + xorl %r14d, %edx + andl %r14d, %ecx + rorl $5, %edx + xorl %r8d, %ecx + xorl %r14d, %edx + addl %ecx, %r9d + vpxor %ymm6, %ymm7, %ymm6 + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r10d, %eax + addl %edx, %r9d + movl %r10d, %ecx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r10d, %ecx + xorl %r11d, %ebx + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %ymm4, %ymm6 + # rnd_1: 1 - 1 + movl %r10d, %ebx + movl %r14d, %ecx + addl 108(%rsp), %r8d + xorl %r15d, %ecx + vpsrlq $0x11, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 2 - 3 + xorl %r13d, %edx + andl %r13d, %ecx + rorl $5, %edx + xorl %r15d, %ecx + xorl %r13d, %edx + addl %ecx, %r8d + vpsrld $10, %ymm6, %ymm9 + vpxor %ymm8, %ymm7, %ymm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r9d, %ebx + addl %edx, %r8d + movl %r9d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r9d, %ecx + xorl %r10d, %eax + vpxor %ymm9, %ymm8, %ymm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + vpaddd %ymm4, %ymm9, %ymm3 + # msg_sched done: 24-27 + # set_w_k_xfer_4: 4 + vpaddd 128+L_avx2_sha256_k(%rip), %ymm0, %ymm4 + vpaddd 160+L_avx2_sha256_k(%rip), %ymm1, %ymm5 + vmovdqu %ymm4, 128(%rsp) + vmovdqu %ymm5, 160(%rsp) + vpaddd 192+L_avx2_sha256_k(%rip), %ymm2, %ymm4 + vpaddd 224+L_avx2_sha256_k(%rip), %ymm3, %ymm5 + vmovdqu %ymm4, 192(%rsp) + vmovdqu %ymm5, 224(%rsp) + # msg_sched: 32-35 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %ymm0, %ymm1, %ymm5 + vpalignr $4, %ymm2, %ymm3, %ymm4 + # rnd_0: 1 - 2 + movl %r9d, %eax + movl %r13d, %ecx + addl 128(%rsp), %r15d + xorl %r14d, %ecx + xorl %r12d, %edx + andl %r12d, %ecx + vpsrld $7, %ymm5, %ymm6 + vpslld $25, %ymm5, %ymm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r14d, %ecx + xorl %r12d, %edx + addl %ecx, %r15d + rorl $6, %edx + xorl %r8d, %eax + addl %edx, %r15d + movl %r8d, %ecx + vpsrld $18, %ymm5, %ymm8 + vpslld $14, %ymm5, %ymm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + vpor %ymm6, %ymm7, %ymm6 + vpor %ymm8, %ymm9, %ymm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r8d, %ebx + movl %r12d, %ecx + addl 132(%rsp), %r14d + xorl %r13d, %ecx + vpsrld $3, %ymm5, %ymm9 + vpxor %ymm6, %ymm8, %ymm6 + # rnd_1: 2 - 3 + xorl %r11d, %edx + andl %r11d, %ecx + rorl $5, %edx + xorl %r13d, %ecx + xorl %r11d, %edx + addl %ecx, %r14d + vpxor %ymm6, %ymm9, %ymm5 + vpshufd $0xfa, %ymm3, %ymm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r15d, %ebx + addl %edx, %r14d + movl %r15d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r15d, %ecx + xorl %r8d, %eax + vpsrld $10, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %ymm6, %ymm6 + vpaddd %ymm0, %ymm4, %ymm4 + # rnd_0: 1 - 3 + movl %r15d, %eax + movl %r11d, %ecx + addl 136(%rsp), %r13d + xorl %r12d, %ecx + xorl %r10d, %edx + andl %r10d, %ecx + rorl $5, %edx + xorl %r12d, %ecx + xorl %r10d, %edx + addl %ecx, %r13d + vpxor %ymm6, %ymm7, %ymm6 + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r14d, %eax + addl %edx, %r13d + movl %r14d, %ecx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r14d, %ecx + xorl %r15d, %ebx + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %ymm4, %ymm6 + # rnd_1: 1 - 1 + movl %r14d, %ebx + movl %r10d, %ecx + addl 140(%rsp), %r12d + xorl %r11d, %ecx + vpsrlq $0x11, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 2 - 3 + xorl %r9d, %edx + andl %r9d, %ecx + rorl $5, %edx + xorl %r11d, %ecx + xorl %r9d, %edx + addl %ecx, %r12d + vpsrld $10, %ymm6, %ymm9 + vpxor %ymm8, %ymm7, %ymm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r13d, %ebx + addl %edx, %r12d + movl %r13d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r13d, %ecx + xorl %r14d, %eax + vpxor %ymm9, %ymm8, %ymm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + vpaddd %ymm4, %ymm9, %ymm0 + # msg_sched done: 32-35 + # msg_sched: 40-43 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %ymm1, %ymm2, %ymm5 + vpalignr $4, %ymm3, %ymm0, %ymm4 + # rnd_0: 1 - 2 + movl %r13d, %eax + movl %r9d, %ecx + addl 160(%rsp), %r11d + xorl %r10d, %ecx + xorl %r8d, %edx + andl %r8d, %ecx + vpsrld $7, %ymm5, %ymm6 + vpslld $25, %ymm5, %ymm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r10d, %ecx + xorl %r8d, %edx + addl %ecx, %r11d + rorl $6, %edx + xorl %r12d, %eax + addl %edx, %r11d + movl %r12d, %ecx + vpsrld $18, %ymm5, %ymm8 + vpslld $14, %ymm5, %ymm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + vpor %ymm6, %ymm7, %ymm6 + vpor %ymm8, %ymm9, %ymm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r12d, %ebx + movl %r8d, %ecx + addl 164(%rsp), %r10d + xorl %r9d, %ecx + vpsrld $3, %ymm5, %ymm9 + vpxor %ymm6, %ymm8, %ymm6 + # rnd_1: 2 - 3 + xorl %r15d, %edx + andl %r15d, %ecx + rorl $5, %edx + xorl %r9d, %ecx + xorl %r15d, %edx + addl %ecx, %r10d + vpxor %ymm6, %ymm9, %ymm5 + vpshufd $0xfa, %ymm0, %ymm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r11d, %ebx + addl %edx, %r10d + movl %r11d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r11d, %ecx + xorl %r12d, %eax + vpsrld $10, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %ymm6, %ymm6 + vpaddd %ymm1, %ymm4, %ymm4 + # rnd_0: 1 - 3 + movl %r11d, %eax + movl %r15d, %ecx + addl 168(%rsp), %r9d + xorl %r8d, %ecx + xorl %r14d, %edx + andl %r14d, %ecx + rorl $5, %edx + xorl %r8d, %ecx + xorl %r14d, %edx + addl %ecx, %r9d + vpxor %ymm6, %ymm7, %ymm6 + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r10d, %eax + addl %edx, %r9d + movl %r10d, %ecx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r10d, %ecx + xorl %r11d, %ebx + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %ymm4, %ymm6 + # rnd_1: 1 - 1 + movl %r10d, %ebx + movl %r14d, %ecx + addl 172(%rsp), %r8d + xorl %r15d, %ecx + vpsrlq $0x11, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 2 - 3 + xorl %r13d, %edx + andl %r13d, %ecx + rorl $5, %edx + xorl %r15d, %ecx + xorl %r13d, %edx + addl %ecx, %r8d + vpsrld $10, %ymm6, %ymm9 + vpxor %ymm8, %ymm7, %ymm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r9d, %ebx + addl %edx, %r8d + movl %r9d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r9d, %ecx + xorl %r10d, %eax + vpxor %ymm9, %ymm8, %ymm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + vpaddd %ymm4, %ymm9, %ymm1 + # msg_sched done: 40-43 + # msg_sched: 48-51 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %ymm2, %ymm3, %ymm5 + vpalignr $4, %ymm0, %ymm1, %ymm4 + # rnd_0: 1 - 2 + movl %r9d, %eax + movl %r13d, %ecx + addl 192(%rsp), %r15d + xorl %r14d, %ecx + xorl %r12d, %edx + andl %r12d, %ecx + vpsrld $7, %ymm5, %ymm6 + vpslld $25, %ymm5, %ymm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r14d, %ecx + xorl %r12d, %edx + addl %ecx, %r15d + rorl $6, %edx + xorl %r8d, %eax + addl %edx, %r15d + movl %r8d, %ecx + vpsrld $18, %ymm5, %ymm8 + vpslld $14, %ymm5, %ymm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + vpor %ymm6, %ymm7, %ymm6 + vpor %ymm8, %ymm9, %ymm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r8d, %ebx + movl %r12d, %ecx + addl 196(%rsp), %r14d + xorl %r13d, %ecx + vpsrld $3, %ymm5, %ymm9 + vpxor %ymm6, %ymm8, %ymm6 + # rnd_1: 2 - 3 + xorl %r11d, %edx + andl %r11d, %ecx + rorl $5, %edx + xorl %r13d, %ecx + xorl %r11d, %edx + addl %ecx, %r14d + vpxor %ymm6, %ymm9, %ymm5 + vpshufd $0xfa, %ymm1, %ymm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r15d, %ebx + addl %edx, %r14d + movl %r15d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r15d, %ecx + xorl %r8d, %eax + vpsrld $10, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %ymm6, %ymm6 + vpaddd %ymm2, %ymm4, %ymm4 + # rnd_0: 1 - 3 + movl %r15d, %eax + movl %r11d, %ecx + addl 200(%rsp), %r13d + xorl %r12d, %ecx + xorl %r10d, %edx + andl %r10d, %ecx + rorl $5, %edx + xorl %r12d, %ecx + xorl %r10d, %edx + addl %ecx, %r13d + vpxor %ymm6, %ymm7, %ymm6 + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r14d, %eax + addl %edx, %r13d + movl %r14d, %ecx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r14d, %ecx + xorl %r15d, %ebx + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %ymm4, %ymm6 + # rnd_1: 1 - 1 + movl %r14d, %ebx + movl %r10d, %ecx + addl 204(%rsp), %r12d + xorl %r11d, %ecx + vpsrlq $0x11, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 2 - 3 + xorl %r9d, %edx + andl %r9d, %ecx + rorl $5, %edx + xorl %r11d, %ecx + xorl %r9d, %edx + addl %ecx, %r12d + vpsrld $10, %ymm6, %ymm9 + vpxor %ymm8, %ymm7, %ymm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r13d, %ebx + addl %edx, %r12d + movl %r13d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r13d, %ecx + xorl %r14d, %eax + vpxor %ymm9, %ymm8, %ymm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + vpaddd %ymm4, %ymm9, %ymm2 + # msg_sched done: 48-51 + # msg_sched: 56-59 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %ymm3, %ymm0, %ymm5 + vpalignr $4, %ymm1, %ymm2, %ymm4 + # rnd_0: 1 - 2 + movl %r13d, %eax + movl %r9d, %ecx + addl 224(%rsp), %r11d + xorl %r10d, %ecx + xorl %r8d, %edx + andl %r8d, %ecx + vpsrld $7, %ymm5, %ymm6 + vpslld $25, %ymm5, %ymm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r10d, %ecx + xorl %r8d, %edx + addl %ecx, %r11d + rorl $6, %edx + xorl %r12d, %eax + addl %edx, %r11d + movl %r12d, %ecx + vpsrld $18, %ymm5, %ymm8 + vpslld $14, %ymm5, %ymm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + vpor %ymm6, %ymm7, %ymm6 + vpor %ymm8, %ymm9, %ymm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r12d, %ebx + movl %r8d, %ecx + addl 228(%rsp), %r10d + xorl %r9d, %ecx + vpsrld $3, %ymm5, %ymm9 + vpxor %ymm6, %ymm8, %ymm6 + # rnd_1: 2 - 3 + xorl %r15d, %edx + andl %r15d, %ecx + rorl $5, %edx + xorl %r9d, %ecx + xorl %r15d, %edx + addl %ecx, %r10d + vpxor %ymm6, %ymm9, %ymm5 + vpshufd $0xfa, %ymm2, %ymm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r11d, %ebx + addl %edx, %r10d + movl %r11d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r11d, %ecx + xorl %r12d, %eax + vpsrld $10, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %ymm6, %ymm6 + vpaddd %ymm3, %ymm4, %ymm4 + # rnd_0: 1 - 3 + movl %r11d, %eax + movl %r15d, %ecx + addl 232(%rsp), %r9d + xorl %r8d, %ecx + xorl %r14d, %edx + andl %r14d, %ecx + rorl $5, %edx + xorl %r8d, %ecx + xorl %r14d, %edx + addl %ecx, %r9d + vpxor %ymm6, %ymm7, %ymm6 + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r10d, %eax + addl %edx, %r9d + movl %r10d, %ecx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r10d, %ecx + xorl %r11d, %ebx + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %ymm4, %ymm6 + # rnd_1: 1 - 1 + movl %r10d, %ebx + movl %r14d, %ecx + addl 236(%rsp), %r8d + xorl %r15d, %ecx + vpsrlq $0x11, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 2 - 3 + xorl %r13d, %edx + andl %r13d, %ecx + rorl $5, %edx + xorl %r15d, %ecx + xorl %r13d, %edx + addl %ecx, %r8d + vpsrld $10, %ymm6, %ymm9 + vpxor %ymm8, %ymm7, %ymm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r9d, %ebx + addl %edx, %r8d + movl %r9d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r9d, %ecx + xorl %r10d, %eax + vpxor %ymm9, %ymm8, %ymm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + vpaddd %ymm4, %ymm9, %ymm3 + # msg_sched done: 56-59 + # set_w_k_xfer_4: 8 + vpaddd 256+L_avx2_sha256_k(%rip), %ymm0, %ymm4 + vpaddd 288+L_avx2_sha256_k(%rip), %ymm1, %ymm5 + vmovdqu %ymm4, 256(%rsp) + vmovdqu %ymm5, 288(%rsp) + vpaddd 320+L_avx2_sha256_k(%rip), %ymm2, %ymm4 + vpaddd 352+L_avx2_sha256_k(%rip), %ymm3, %ymm5 + vmovdqu %ymm4, 320(%rsp) + vmovdqu %ymm5, 352(%rsp) + # msg_sched: 64-67 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %ymm0, %ymm1, %ymm5 + vpalignr $4, %ymm2, %ymm3, %ymm4 + # rnd_0: 1 - 2 + movl %r9d, %eax + movl %r13d, %ecx + addl 256(%rsp), %r15d + xorl %r14d, %ecx + xorl %r12d, %edx + andl %r12d, %ecx + vpsrld $7, %ymm5, %ymm6 + vpslld $25, %ymm5, %ymm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r14d, %ecx + xorl %r12d, %edx + addl %ecx, %r15d + rorl $6, %edx + xorl %r8d, %eax + addl %edx, %r15d + movl %r8d, %ecx + vpsrld $18, %ymm5, %ymm8 + vpslld $14, %ymm5, %ymm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + vpor %ymm6, %ymm7, %ymm6 + vpor %ymm8, %ymm9, %ymm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r8d, %ebx + movl %r12d, %ecx + addl 260(%rsp), %r14d + xorl %r13d, %ecx + vpsrld $3, %ymm5, %ymm9 + vpxor %ymm6, %ymm8, %ymm6 + # rnd_1: 2 - 3 + xorl %r11d, %edx + andl %r11d, %ecx + rorl $5, %edx + xorl %r13d, %ecx + xorl %r11d, %edx + addl %ecx, %r14d + vpxor %ymm6, %ymm9, %ymm5 + vpshufd $0xfa, %ymm3, %ymm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r15d, %ebx + addl %edx, %r14d + movl %r15d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r15d, %ecx + xorl %r8d, %eax + vpsrld $10, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %ymm6, %ymm6 + vpaddd %ymm0, %ymm4, %ymm4 + # rnd_0: 1 - 3 + movl %r15d, %eax + movl %r11d, %ecx + addl 264(%rsp), %r13d + xorl %r12d, %ecx + xorl %r10d, %edx + andl %r10d, %ecx + rorl $5, %edx + xorl %r12d, %ecx + xorl %r10d, %edx + addl %ecx, %r13d + vpxor %ymm6, %ymm7, %ymm6 + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r14d, %eax + addl %edx, %r13d + movl %r14d, %ecx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r14d, %ecx + xorl %r15d, %ebx + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %ymm4, %ymm6 + # rnd_1: 1 - 1 + movl %r14d, %ebx + movl %r10d, %ecx + addl 268(%rsp), %r12d + xorl %r11d, %ecx + vpsrlq $0x11, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 2 - 3 + xorl %r9d, %edx + andl %r9d, %ecx + rorl $5, %edx + xorl %r11d, %ecx + xorl %r9d, %edx + addl %ecx, %r12d + vpsrld $10, %ymm6, %ymm9 + vpxor %ymm8, %ymm7, %ymm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r13d, %ebx + addl %edx, %r12d + movl %r13d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r13d, %ecx + xorl %r14d, %eax + vpxor %ymm9, %ymm8, %ymm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + vpaddd %ymm4, %ymm9, %ymm0 + # msg_sched done: 64-67 + # msg_sched: 72-75 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %ymm1, %ymm2, %ymm5 + vpalignr $4, %ymm3, %ymm0, %ymm4 + # rnd_0: 1 - 2 + movl %r13d, %eax + movl %r9d, %ecx + addl 288(%rsp), %r11d + xorl %r10d, %ecx + xorl %r8d, %edx + andl %r8d, %ecx + vpsrld $7, %ymm5, %ymm6 + vpslld $25, %ymm5, %ymm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r10d, %ecx + xorl %r8d, %edx + addl %ecx, %r11d + rorl $6, %edx + xorl %r12d, %eax + addl %edx, %r11d + movl %r12d, %ecx + vpsrld $18, %ymm5, %ymm8 + vpslld $14, %ymm5, %ymm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + vpor %ymm6, %ymm7, %ymm6 + vpor %ymm8, %ymm9, %ymm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r12d, %ebx + movl %r8d, %ecx + addl 292(%rsp), %r10d + xorl %r9d, %ecx + vpsrld $3, %ymm5, %ymm9 + vpxor %ymm6, %ymm8, %ymm6 + # rnd_1: 2 - 3 + xorl %r15d, %edx + andl %r15d, %ecx + rorl $5, %edx + xorl %r9d, %ecx + xorl %r15d, %edx + addl %ecx, %r10d + vpxor %ymm6, %ymm9, %ymm5 + vpshufd $0xfa, %ymm0, %ymm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r11d, %ebx + addl %edx, %r10d + movl %r11d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r11d, %ecx + xorl %r12d, %eax + vpsrld $10, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %ymm6, %ymm6 + vpaddd %ymm1, %ymm4, %ymm4 + # rnd_0: 1 - 3 + movl %r11d, %eax + movl %r15d, %ecx + addl 296(%rsp), %r9d + xorl %r8d, %ecx + xorl %r14d, %edx + andl %r14d, %ecx + rorl $5, %edx + xorl %r8d, %ecx + xorl %r14d, %edx + addl %ecx, %r9d + vpxor %ymm6, %ymm7, %ymm6 + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r10d, %eax + addl %edx, %r9d + movl %r10d, %ecx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r10d, %ecx + xorl %r11d, %ebx + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %ymm4, %ymm6 + # rnd_1: 1 - 1 + movl %r10d, %ebx + movl %r14d, %ecx + addl 300(%rsp), %r8d + xorl %r15d, %ecx + vpsrlq $0x11, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 2 - 3 + xorl %r13d, %edx + andl %r13d, %ecx + rorl $5, %edx + xorl %r15d, %ecx + xorl %r13d, %edx + addl %ecx, %r8d + vpsrld $10, %ymm6, %ymm9 + vpxor %ymm8, %ymm7, %ymm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r9d, %ebx + addl %edx, %r8d + movl %r9d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r9d, %ecx + xorl %r10d, %eax + vpxor %ymm9, %ymm8, %ymm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + vpaddd %ymm4, %ymm9, %ymm1 + # msg_sched done: 72-75 + # msg_sched: 80-83 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %ymm2, %ymm3, %ymm5 + vpalignr $4, %ymm0, %ymm1, %ymm4 + # rnd_0: 1 - 2 + movl %r9d, %eax + movl %r13d, %ecx + addl 320(%rsp), %r15d + xorl %r14d, %ecx + xorl %r12d, %edx + andl %r12d, %ecx + vpsrld $7, %ymm5, %ymm6 + vpslld $25, %ymm5, %ymm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r14d, %ecx + xorl %r12d, %edx + addl %ecx, %r15d + rorl $6, %edx + xorl %r8d, %eax + addl %edx, %r15d + movl %r8d, %ecx + vpsrld $18, %ymm5, %ymm8 + vpslld $14, %ymm5, %ymm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + vpor %ymm6, %ymm7, %ymm6 + vpor %ymm8, %ymm9, %ymm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r8d, %ebx + movl %r12d, %ecx + addl 324(%rsp), %r14d + xorl %r13d, %ecx + vpsrld $3, %ymm5, %ymm9 + vpxor %ymm6, %ymm8, %ymm6 + # rnd_1: 2 - 3 + xorl %r11d, %edx + andl %r11d, %ecx + rorl $5, %edx + xorl %r13d, %ecx + xorl %r11d, %edx + addl %ecx, %r14d + vpxor %ymm6, %ymm9, %ymm5 + vpshufd $0xfa, %ymm1, %ymm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r15d, %ebx + addl %edx, %r14d + movl %r15d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r15d, %ecx + xorl %r8d, %eax + vpsrld $10, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %ymm6, %ymm6 + vpaddd %ymm2, %ymm4, %ymm4 + # rnd_0: 1 - 3 + movl %r15d, %eax + movl %r11d, %ecx + addl 328(%rsp), %r13d + xorl %r12d, %ecx + xorl %r10d, %edx + andl %r10d, %ecx + rorl $5, %edx + xorl %r12d, %ecx + xorl %r10d, %edx + addl %ecx, %r13d + vpxor %ymm6, %ymm7, %ymm6 + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r14d, %eax + addl %edx, %r13d + movl %r14d, %ecx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r14d, %ecx + xorl %r15d, %ebx + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %ymm4, %ymm6 + # rnd_1: 1 - 1 + movl %r14d, %ebx + movl %r10d, %ecx + addl 332(%rsp), %r12d + xorl %r11d, %ecx + vpsrlq $0x11, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 2 - 3 + xorl %r9d, %edx + andl %r9d, %ecx + rorl $5, %edx + xorl %r11d, %ecx + xorl %r9d, %edx + addl %ecx, %r12d + vpsrld $10, %ymm6, %ymm9 + vpxor %ymm8, %ymm7, %ymm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r13d, %ebx + addl %edx, %r12d + movl %r13d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r13d, %ecx + xorl %r14d, %eax + vpxor %ymm9, %ymm8, %ymm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + vpaddd %ymm4, %ymm9, %ymm2 + # msg_sched done: 80-83 + # msg_sched: 88-91 + # rnd_0: 0 - 0 + rorl $14, %edx + vpalignr $4, %ymm3, %ymm0, %ymm5 + vpalignr $4, %ymm1, %ymm2, %ymm4 + # rnd_0: 1 - 2 + movl %r13d, %eax + movl %r9d, %ecx + addl 352(%rsp), %r11d + xorl %r10d, %ecx + xorl %r8d, %edx + andl %r8d, %ecx + vpsrld $7, %ymm5, %ymm6 + vpslld $25, %ymm5, %ymm7 + # rnd_0: 3 - 4 + rorl $5, %edx + xorl %r10d, %ecx + xorl %r8d, %edx + addl %ecx, %r11d + rorl $6, %edx + xorl %r12d, %eax + addl %edx, %r11d + movl %r12d, %ecx + vpsrld $18, %ymm5, %ymm8 + vpslld $14, %ymm5, %ymm9 + # rnd_0: 5 - 6 + andl %eax, %ebx + rorl $9, %ecx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + vpor %ymm6, %ymm7, %ymm6 + vpor %ymm8, %ymm9, %ymm8 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + # rnd_1: 0 - 1 + rorl $14, %edx + movl %r12d, %ebx + movl %r8d, %ecx + addl 356(%rsp), %r10d + xorl %r9d, %ecx + vpsrld $3, %ymm5, %ymm9 + vpxor %ymm6, %ymm8, %ymm6 + # rnd_1: 2 - 3 + xorl %r15d, %edx + andl %r15d, %ecx + rorl $5, %edx + xorl %r9d, %ecx + xorl %r15d, %edx + addl %ecx, %r10d + vpxor %ymm6, %ymm9, %ymm5 + vpshufd $0xfa, %ymm2, %ymm6 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r11d, %ebx + addl %edx, %r10d + movl %r11d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r11d, %ecx + xorl %r12d, %eax + vpsrld $10, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 6 - 7 + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + # rnd_0: 0 - 0 + rorl $14, %edx + vpsrlq $0x11, %ymm6, %ymm6 + vpaddd %ymm3, %ymm4, %ymm4 + # rnd_0: 1 - 3 + movl %r11d, %eax + movl %r15d, %ecx + addl 360(%rsp), %r9d + xorl %r8d, %ecx + xorl %r14d, %edx + andl %r14d, %ecx + rorl $5, %edx + xorl %r8d, %ecx + xorl %r14d, %edx + addl %ecx, %r9d + vpxor %ymm6, %ymm7, %ymm6 + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 4 - 4 + rorl $6, %edx + xorl %r10d, %eax + addl %edx, %r9d + movl %r10d, %ecx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 5 - 5 + andl %eax, %ebx + rorl $9, %ecx + xorl %r10d, %ecx + xorl %r11d, %ebx + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 6 - 6 + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 7 - 7 + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + # rnd_1: 0 - 0 + rorl $14, %edx + vpshufd $0x50, %ymm4, %ymm6 + # rnd_1: 1 - 1 + movl %r10d, %ebx + movl %r14d, %ecx + addl 364(%rsp), %r8d + xorl %r15d, %ecx + vpsrlq $0x11, %ymm6, %ymm8 + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 2 - 3 + xorl %r13d, %edx + andl %r13d, %ecx + rorl $5, %edx + xorl %r15d, %ecx + xorl %r13d, %edx + addl %ecx, %r8d + vpsrld $10, %ymm6, %ymm9 + vpxor %ymm8, %ymm7, %ymm8 + # rnd_1: 4 - 5 + rorl $6, %edx + xorl %r9d, %ebx + addl %edx, %r8d + movl %r9d, %ecx + andl %ebx, %eax + rorl $9, %ecx + xorl %r9d, %ecx + xorl %r10d, %eax + vpxor %ymm9, %ymm8, %ymm9 + # rnd_1: 6 - 6 + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 7 - 7 + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + vpaddd %ymm4, %ymm9, %ymm3 + # msg_sched done: 88-91 + # set_w_k_xfer_4: 12 + vpaddd 384+L_avx2_sha256_k(%rip), %ymm0, %ymm4 + vpaddd 416+L_avx2_sha256_k(%rip), %ymm1, %ymm5 + vmovdqu %ymm4, 384(%rsp) + vmovdqu %ymm5, 416(%rsp) + vpaddd 448+L_avx2_sha256_k(%rip), %ymm2, %ymm4 + vpaddd 480+L_avx2_sha256_k(%rip), %ymm3, %ymm5 + vmovdqu %ymm4, 448(%rsp) + vmovdqu %ymm5, 480(%rsp) + # rnd_all_4: 24-27 + addl 384(%rsp), %r15d + movl %r13d, %ecx + movl %r9d, %eax + xorl %r14d, %ecx + rorl $14, %edx + andl %r12d, %ecx + xorl %r12d, %edx + xorl %r14d, %ecx + rorl $5, %edx + addl %ecx, %r15d + xorl %r12d, %edx + xorl %r8d, %eax + rorl $6, %edx + movl %r8d, %ecx + addl %edx, %r15d + rorl $9, %ecx + andl %eax, %ebx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + addl 388(%rsp), %r14d + movl %r12d, %ecx + movl %r8d, %ebx + xorl %r13d, %ecx + rorl $14, %edx + andl %r11d, %ecx + xorl %r11d, %edx + xorl %r13d, %ecx + rorl $5, %edx + addl %ecx, %r14d + xorl %r11d, %edx + xorl %r15d, %ebx + rorl $6, %edx + movl %r15d, %ecx + addl %edx, %r14d + rorl $9, %ecx + andl %ebx, %eax + xorl %r15d, %ecx + xorl %r8d, %eax + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + addl 392(%rsp), %r13d + movl %r11d, %ecx + movl %r15d, %eax + xorl %r12d, %ecx + rorl $14, %edx + andl %r10d, %ecx + xorl %r10d, %edx + xorl %r12d, %ecx + rorl $5, %edx + addl %ecx, %r13d + xorl %r10d, %edx + xorl %r14d, %eax + rorl $6, %edx + movl %r14d, %ecx + addl %edx, %r13d + rorl $9, %ecx + andl %eax, %ebx + xorl %r14d, %ecx + xorl %r15d, %ebx + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + addl 396(%rsp), %r12d + movl %r10d, %ecx + movl %r14d, %ebx + xorl %r11d, %ecx + rorl $14, %edx + andl %r9d, %ecx + xorl %r9d, %edx + xorl %r11d, %ecx + rorl $5, %edx + addl %ecx, %r12d + xorl %r9d, %edx + xorl %r13d, %ebx + rorl $6, %edx + movl %r13d, %ecx + addl %edx, %r12d + rorl $9, %ecx + andl %ebx, %eax + xorl %r13d, %ecx + xorl %r14d, %eax + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + # rnd_all_4: 26-29 + addl 416(%rsp), %r11d + movl %r9d, %ecx + movl %r13d, %eax + xorl %r10d, %ecx + rorl $14, %edx + andl %r8d, %ecx + xorl %r8d, %edx + xorl %r10d, %ecx + rorl $5, %edx + addl %ecx, %r11d + xorl %r8d, %edx + xorl %r12d, %eax + rorl $6, %edx + movl %r12d, %ecx + addl %edx, %r11d + rorl $9, %ecx + andl %eax, %ebx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + addl 420(%rsp), %r10d + movl %r8d, %ecx + movl %r12d, %ebx + xorl %r9d, %ecx + rorl $14, %edx + andl %r15d, %ecx + xorl %r15d, %edx + xorl %r9d, %ecx + rorl $5, %edx + addl %ecx, %r10d + xorl %r15d, %edx + xorl %r11d, %ebx + rorl $6, %edx + movl %r11d, %ecx + addl %edx, %r10d + rorl $9, %ecx + andl %ebx, %eax + xorl %r11d, %ecx + xorl %r12d, %eax + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + addl 424(%rsp), %r9d + movl %r15d, %ecx + movl %r11d, %eax + xorl %r8d, %ecx + rorl $14, %edx + andl %r14d, %ecx + xorl %r14d, %edx + xorl %r8d, %ecx + rorl $5, %edx + addl %ecx, %r9d + xorl %r14d, %edx + xorl %r10d, %eax + rorl $6, %edx + movl %r10d, %ecx + addl %edx, %r9d + rorl $9, %ecx + andl %eax, %ebx + xorl %r10d, %ecx + xorl %r11d, %ebx + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + addl 428(%rsp), %r8d + movl %r14d, %ecx + movl %r10d, %ebx + xorl %r15d, %ecx + rorl $14, %edx + andl %r13d, %ecx + xorl %r13d, %edx + xorl %r15d, %ecx + rorl $5, %edx + addl %ecx, %r8d + xorl %r13d, %edx + xorl %r9d, %ebx + rorl $6, %edx + movl %r9d, %ecx + addl %edx, %r8d + rorl $9, %ecx + andl %ebx, %eax + xorl %r9d, %ecx + xorl %r10d, %eax + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + # rnd_all_4: 28-31 + addl 448(%rsp), %r15d + movl %r13d, %ecx + movl %r9d, %eax + xorl %r14d, %ecx + rorl $14, %edx + andl %r12d, %ecx + xorl %r12d, %edx + xorl %r14d, %ecx + rorl $5, %edx + addl %ecx, %r15d + xorl %r12d, %edx + xorl %r8d, %eax + rorl $6, %edx + movl %r8d, %ecx + addl %edx, %r15d + rorl $9, %ecx + andl %eax, %ebx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + addl 452(%rsp), %r14d + movl %r12d, %ecx + movl %r8d, %ebx + xorl %r13d, %ecx + rorl $14, %edx + andl %r11d, %ecx + xorl %r11d, %edx + xorl %r13d, %ecx + rorl $5, %edx + addl %ecx, %r14d + xorl %r11d, %edx + xorl %r15d, %ebx + rorl $6, %edx + movl %r15d, %ecx + addl %edx, %r14d + rorl $9, %ecx + andl %ebx, %eax + xorl %r15d, %ecx + xorl %r8d, %eax + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + addl 456(%rsp), %r13d + movl %r11d, %ecx + movl %r15d, %eax + xorl %r12d, %ecx + rorl $14, %edx + andl %r10d, %ecx + xorl %r10d, %edx + xorl %r12d, %ecx + rorl $5, %edx + addl %ecx, %r13d + xorl %r10d, %edx + xorl %r14d, %eax + rorl $6, %edx + movl %r14d, %ecx + addl %edx, %r13d + rorl $9, %ecx + andl %eax, %ebx + xorl %r14d, %ecx + xorl %r15d, %ebx + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + addl 460(%rsp), %r12d + movl %r10d, %ecx + movl %r14d, %ebx + xorl %r11d, %ecx + rorl $14, %edx + andl %r9d, %ecx + xorl %r9d, %edx + xorl %r11d, %ecx + rorl $5, %edx + addl %ecx, %r12d + xorl %r9d, %edx + xorl %r13d, %ebx + rorl $6, %edx + movl %r13d, %ecx + addl %edx, %r12d + rorl $9, %ecx + andl %ebx, %eax + xorl %r13d, %ecx + xorl %r14d, %eax + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + # rnd_all_4: 30-33 + addl 480(%rsp), %r11d + movl %r9d, %ecx + movl %r13d, %eax + xorl %r10d, %ecx + rorl $14, %edx + andl %r8d, %ecx + xorl %r8d, %edx + xorl %r10d, %ecx + rorl $5, %edx + addl %ecx, %r11d + xorl %r8d, %edx + xorl %r12d, %eax + rorl $6, %edx + movl %r12d, %ecx + addl %edx, %r11d + rorl $9, %ecx + andl %eax, %ebx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + addl 484(%rsp), %r10d + movl %r8d, %ecx + movl %r12d, %ebx + xorl %r9d, %ecx + rorl $14, %edx + andl %r15d, %ecx + xorl %r15d, %edx + xorl %r9d, %ecx + rorl $5, %edx + addl %ecx, %r10d + xorl %r15d, %edx + xorl %r11d, %ebx + rorl $6, %edx + movl %r11d, %ecx + addl %edx, %r10d + rorl $9, %ecx + andl %ebx, %eax + xorl %r11d, %ecx + xorl %r12d, %eax + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + addl 488(%rsp), %r9d + movl %r15d, %ecx + movl %r11d, %eax + xorl %r8d, %ecx + rorl $14, %edx + andl %r14d, %ecx + xorl %r14d, %edx + xorl %r8d, %ecx + rorl $5, %edx + addl %ecx, %r9d + xorl %r14d, %edx + xorl %r10d, %eax + rorl $6, %edx + movl %r10d, %ecx + addl %edx, %r9d + rorl $9, %ecx + andl %eax, %ebx + xorl %r10d, %ecx + xorl %r11d, %ebx + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + addl 492(%rsp), %r8d + movl %r14d, %ecx + movl %r10d, %ebx + xorl %r15d, %ecx + rorl $14, %edx + andl %r13d, %ecx + xorl %r13d, %edx + xorl %r15d, %ecx + rorl $5, %edx + addl %ecx, %r8d + xorl %r13d, %edx + xorl %r9d, %ebx + rorl $6, %edx + movl %r9d, %ecx + addl %edx, %r8d + rorl $9, %ecx + andl %ebx, %eax + xorl %r9d, %ecx + xorl %r10d, %eax + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + addl (%rdi), %r8d + addl 4(%rdi), %r9d + addl 8(%rdi), %r10d + addl 12(%rdi), %r11d + addl 16(%rdi), %r12d + addl 20(%rdi), %r13d + addl 24(%rdi), %r14d + addl 28(%rdi), %r15d + movl %r8d, (%rdi) + movl %r9d, 4(%rdi) + movl %r10d, 8(%rdi) + movl %r11d, 12(%rdi) + movl %r12d, 16(%rdi) + movl %r13d, 20(%rdi) + movl %r14d, 24(%rdi) + movl %r15d, 28(%rdi) + movl %r9d, %ebx + movl %r12d, %edx + xorl %r10d, %ebx + # rnd_all_4: 1-4 + addl 16(%rsp), %r15d + movl %r13d, %ecx + movl %r9d, %eax + xorl %r14d, %ecx + rorl $14, %edx + andl %r12d, %ecx + xorl %r12d, %edx + xorl %r14d, %ecx + rorl $5, %edx + addl %ecx, %r15d + xorl %r12d, %edx + xorl %r8d, %eax + rorl $6, %edx + movl %r8d, %ecx + addl %edx, %r15d + rorl $9, %ecx + andl %eax, %ebx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + addl 20(%rsp), %r14d + movl %r12d, %ecx + movl %r8d, %ebx + xorl %r13d, %ecx + rorl $14, %edx + andl %r11d, %ecx + xorl %r11d, %edx + xorl %r13d, %ecx + rorl $5, %edx + addl %ecx, %r14d + xorl %r11d, %edx + xorl %r15d, %ebx + rorl $6, %edx + movl %r15d, %ecx + addl %edx, %r14d + rorl $9, %ecx + andl %ebx, %eax + xorl %r15d, %ecx + xorl %r8d, %eax + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + addl 24(%rsp), %r13d + movl %r11d, %ecx + movl %r15d, %eax + xorl %r12d, %ecx + rorl $14, %edx + andl %r10d, %ecx + xorl %r10d, %edx + xorl %r12d, %ecx + rorl $5, %edx + addl %ecx, %r13d + xorl %r10d, %edx + xorl %r14d, %eax + rorl $6, %edx + movl %r14d, %ecx + addl %edx, %r13d + rorl $9, %ecx + andl %eax, %ebx + xorl %r14d, %ecx + xorl %r15d, %ebx + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + addl 28(%rsp), %r12d + movl %r10d, %ecx + movl %r14d, %ebx + xorl %r11d, %ecx + rorl $14, %edx + andl %r9d, %ecx + xorl %r9d, %edx + xorl %r11d, %ecx + rorl $5, %edx + addl %ecx, %r12d + xorl %r9d, %edx + xorl %r13d, %ebx + rorl $6, %edx + movl %r13d, %ecx + addl %edx, %r12d + rorl $9, %ecx + andl %ebx, %eax + xorl %r13d, %ecx + xorl %r14d, %eax + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + # rnd_all_4: 3-6 + addl 48(%rsp), %r11d + movl %r9d, %ecx + movl %r13d, %eax + xorl %r10d, %ecx + rorl $14, %edx + andl %r8d, %ecx + xorl %r8d, %edx + xorl %r10d, %ecx + rorl $5, %edx + addl %ecx, %r11d + xorl %r8d, %edx + xorl %r12d, %eax + rorl $6, %edx + movl %r12d, %ecx + addl %edx, %r11d + rorl $9, %ecx + andl %eax, %ebx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + addl 52(%rsp), %r10d + movl %r8d, %ecx + movl %r12d, %ebx + xorl %r9d, %ecx + rorl $14, %edx + andl %r15d, %ecx + xorl %r15d, %edx + xorl %r9d, %ecx + rorl $5, %edx + addl %ecx, %r10d + xorl %r15d, %edx + xorl %r11d, %ebx + rorl $6, %edx + movl %r11d, %ecx + addl %edx, %r10d + rorl $9, %ecx + andl %ebx, %eax + xorl %r11d, %ecx + xorl %r12d, %eax + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + addl 56(%rsp), %r9d + movl %r15d, %ecx + movl %r11d, %eax + xorl %r8d, %ecx + rorl $14, %edx + andl %r14d, %ecx + xorl %r14d, %edx + xorl %r8d, %ecx + rorl $5, %edx + addl %ecx, %r9d + xorl %r14d, %edx + xorl %r10d, %eax + rorl $6, %edx + movl %r10d, %ecx + addl %edx, %r9d + rorl $9, %ecx + andl %eax, %ebx + xorl %r10d, %ecx + xorl %r11d, %ebx + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + addl 60(%rsp), %r8d + movl %r14d, %ecx + movl %r10d, %ebx + xorl %r15d, %ecx + rorl $14, %edx + andl %r13d, %ecx + xorl %r13d, %edx + xorl %r15d, %ecx + rorl $5, %edx + addl %ecx, %r8d + xorl %r13d, %edx + xorl %r9d, %ebx + rorl $6, %edx + movl %r9d, %ecx + addl %edx, %r8d + rorl $9, %ecx + andl %ebx, %eax + xorl %r9d, %ecx + xorl %r10d, %eax + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + # rnd_all_4: 5-8 + addl 80(%rsp), %r15d + movl %r13d, %ecx + movl %r9d, %eax + xorl %r14d, %ecx + rorl $14, %edx + andl %r12d, %ecx + xorl %r12d, %edx + xorl %r14d, %ecx + rorl $5, %edx + addl %ecx, %r15d + xorl %r12d, %edx + xorl %r8d, %eax + rorl $6, %edx + movl %r8d, %ecx + addl %edx, %r15d + rorl $9, %ecx + andl %eax, %ebx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + addl 84(%rsp), %r14d + movl %r12d, %ecx + movl %r8d, %ebx + xorl %r13d, %ecx + rorl $14, %edx + andl %r11d, %ecx + xorl %r11d, %edx + xorl %r13d, %ecx + rorl $5, %edx + addl %ecx, %r14d + xorl %r11d, %edx + xorl %r15d, %ebx + rorl $6, %edx + movl %r15d, %ecx + addl %edx, %r14d + rorl $9, %ecx + andl %ebx, %eax + xorl %r15d, %ecx + xorl %r8d, %eax + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + addl 88(%rsp), %r13d + movl %r11d, %ecx + movl %r15d, %eax + xorl %r12d, %ecx + rorl $14, %edx + andl %r10d, %ecx + xorl %r10d, %edx + xorl %r12d, %ecx + rorl $5, %edx + addl %ecx, %r13d + xorl %r10d, %edx + xorl %r14d, %eax + rorl $6, %edx + movl %r14d, %ecx + addl %edx, %r13d + rorl $9, %ecx + andl %eax, %ebx + xorl %r14d, %ecx + xorl %r15d, %ebx + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + addl 92(%rsp), %r12d + movl %r10d, %ecx + movl %r14d, %ebx + xorl %r11d, %ecx + rorl $14, %edx + andl %r9d, %ecx + xorl %r9d, %edx + xorl %r11d, %ecx + rorl $5, %edx + addl %ecx, %r12d + xorl %r9d, %edx + xorl %r13d, %ebx + rorl $6, %edx + movl %r13d, %ecx + addl %edx, %r12d + rorl $9, %ecx + andl %ebx, %eax + xorl %r13d, %ecx + xorl %r14d, %eax + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + # rnd_all_4: 7-10 + addl 112(%rsp), %r11d + movl %r9d, %ecx + movl %r13d, %eax + xorl %r10d, %ecx + rorl $14, %edx + andl %r8d, %ecx + xorl %r8d, %edx + xorl %r10d, %ecx + rorl $5, %edx + addl %ecx, %r11d + xorl %r8d, %edx + xorl %r12d, %eax + rorl $6, %edx + movl %r12d, %ecx + addl %edx, %r11d + rorl $9, %ecx + andl %eax, %ebx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + addl 116(%rsp), %r10d + movl %r8d, %ecx + movl %r12d, %ebx + xorl %r9d, %ecx + rorl $14, %edx + andl %r15d, %ecx + xorl %r15d, %edx + xorl %r9d, %ecx + rorl $5, %edx + addl %ecx, %r10d + xorl %r15d, %edx + xorl %r11d, %ebx + rorl $6, %edx + movl %r11d, %ecx + addl %edx, %r10d + rorl $9, %ecx + andl %ebx, %eax + xorl %r11d, %ecx + xorl %r12d, %eax + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + addl 120(%rsp), %r9d + movl %r15d, %ecx + movl %r11d, %eax + xorl %r8d, %ecx + rorl $14, %edx + andl %r14d, %ecx + xorl %r14d, %edx + xorl %r8d, %ecx + rorl $5, %edx + addl %ecx, %r9d + xorl %r14d, %edx + xorl %r10d, %eax + rorl $6, %edx + movl %r10d, %ecx + addl %edx, %r9d + rorl $9, %ecx + andl %eax, %ebx + xorl %r10d, %ecx + xorl %r11d, %ebx + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + addl 124(%rsp), %r8d + movl %r14d, %ecx + movl %r10d, %ebx + xorl %r15d, %ecx + rorl $14, %edx + andl %r13d, %ecx + xorl %r13d, %edx + xorl %r15d, %ecx + rorl $5, %edx + addl %ecx, %r8d + xorl %r13d, %edx + xorl %r9d, %ebx + rorl $6, %edx + movl %r9d, %ecx + addl %edx, %r8d + rorl $9, %ecx + andl %ebx, %eax + xorl %r9d, %ecx + xorl %r10d, %eax + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + # rnd_all_4: 9-12 + addl 144(%rsp), %r15d + movl %r13d, %ecx + movl %r9d, %eax + xorl %r14d, %ecx + rorl $14, %edx + andl %r12d, %ecx + xorl %r12d, %edx + xorl %r14d, %ecx + rorl $5, %edx + addl %ecx, %r15d + xorl %r12d, %edx + xorl %r8d, %eax + rorl $6, %edx + movl %r8d, %ecx + addl %edx, %r15d + rorl $9, %ecx + andl %eax, %ebx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + addl 148(%rsp), %r14d + movl %r12d, %ecx + movl %r8d, %ebx + xorl %r13d, %ecx + rorl $14, %edx + andl %r11d, %ecx + xorl %r11d, %edx + xorl %r13d, %ecx + rorl $5, %edx + addl %ecx, %r14d + xorl %r11d, %edx + xorl %r15d, %ebx + rorl $6, %edx + movl %r15d, %ecx + addl %edx, %r14d + rorl $9, %ecx + andl %ebx, %eax + xorl %r15d, %ecx + xorl %r8d, %eax + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + addl 152(%rsp), %r13d + movl %r11d, %ecx + movl %r15d, %eax + xorl %r12d, %ecx + rorl $14, %edx + andl %r10d, %ecx + xorl %r10d, %edx + xorl %r12d, %ecx + rorl $5, %edx + addl %ecx, %r13d + xorl %r10d, %edx + xorl %r14d, %eax + rorl $6, %edx + movl %r14d, %ecx + addl %edx, %r13d + rorl $9, %ecx + andl %eax, %ebx + xorl %r14d, %ecx + xorl %r15d, %ebx + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + addl 156(%rsp), %r12d + movl %r10d, %ecx + movl %r14d, %ebx + xorl %r11d, %ecx + rorl $14, %edx + andl %r9d, %ecx + xorl %r9d, %edx + xorl %r11d, %ecx + rorl $5, %edx + addl %ecx, %r12d + xorl %r9d, %edx + xorl %r13d, %ebx + rorl $6, %edx + movl %r13d, %ecx + addl %edx, %r12d + rorl $9, %ecx + andl %ebx, %eax + xorl %r13d, %ecx + xorl %r14d, %eax + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + # rnd_all_4: 11-14 + addl 176(%rsp), %r11d + movl %r9d, %ecx + movl %r13d, %eax + xorl %r10d, %ecx + rorl $14, %edx + andl %r8d, %ecx + xorl %r8d, %edx + xorl %r10d, %ecx + rorl $5, %edx + addl %ecx, %r11d + xorl %r8d, %edx + xorl %r12d, %eax + rorl $6, %edx + movl %r12d, %ecx + addl %edx, %r11d + rorl $9, %ecx + andl %eax, %ebx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + addl 180(%rsp), %r10d + movl %r8d, %ecx + movl %r12d, %ebx + xorl %r9d, %ecx + rorl $14, %edx + andl %r15d, %ecx + xorl %r15d, %edx + xorl %r9d, %ecx + rorl $5, %edx + addl %ecx, %r10d + xorl %r15d, %edx + xorl %r11d, %ebx + rorl $6, %edx + movl %r11d, %ecx + addl %edx, %r10d + rorl $9, %ecx + andl %ebx, %eax + xorl %r11d, %ecx + xorl %r12d, %eax + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + addl 184(%rsp), %r9d + movl %r15d, %ecx + movl %r11d, %eax + xorl %r8d, %ecx + rorl $14, %edx + andl %r14d, %ecx + xorl %r14d, %edx + xorl %r8d, %ecx + rorl $5, %edx + addl %ecx, %r9d + xorl %r14d, %edx + xorl %r10d, %eax + rorl $6, %edx + movl %r10d, %ecx + addl %edx, %r9d + rorl $9, %ecx + andl %eax, %ebx + xorl %r10d, %ecx + xorl %r11d, %ebx + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + addl 188(%rsp), %r8d + movl %r14d, %ecx + movl %r10d, %ebx + xorl %r15d, %ecx + rorl $14, %edx + andl %r13d, %ecx + xorl %r13d, %edx + xorl %r15d, %ecx + rorl $5, %edx + addl %ecx, %r8d + xorl %r13d, %edx + xorl %r9d, %ebx + rorl $6, %edx + movl %r9d, %ecx + addl %edx, %r8d + rorl $9, %ecx + andl %ebx, %eax + xorl %r9d, %ecx + xorl %r10d, %eax + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + # rnd_all_4: 13-16 + addl 208(%rsp), %r15d + movl %r13d, %ecx + movl %r9d, %eax + xorl %r14d, %ecx + rorl $14, %edx + andl %r12d, %ecx + xorl %r12d, %edx + xorl %r14d, %ecx + rorl $5, %edx + addl %ecx, %r15d + xorl %r12d, %edx + xorl %r8d, %eax + rorl $6, %edx + movl %r8d, %ecx + addl %edx, %r15d + rorl $9, %ecx + andl %eax, %ebx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + addl 212(%rsp), %r14d + movl %r12d, %ecx + movl %r8d, %ebx + xorl %r13d, %ecx + rorl $14, %edx + andl %r11d, %ecx + xorl %r11d, %edx + xorl %r13d, %ecx + rorl $5, %edx + addl %ecx, %r14d + xorl %r11d, %edx + xorl %r15d, %ebx + rorl $6, %edx + movl %r15d, %ecx + addl %edx, %r14d + rorl $9, %ecx + andl %ebx, %eax + xorl %r15d, %ecx + xorl %r8d, %eax + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + addl 216(%rsp), %r13d + movl %r11d, %ecx + movl %r15d, %eax + xorl %r12d, %ecx + rorl $14, %edx + andl %r10d, %ecx + xorl %r10d, %edx + xorl %r12d, %ecx + rorl $5, %edx + addl %ecx, %r13d + xorl %r10d, %edx + xorl %r14d, %eax + rorl $6, %edx + movl %r14d, %ecx + addl %edx, %r13d + rorl $9, %ecx + andl %eax, %ebx + xorl %r14d, %ecx + xorl %r15d, %ebx + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + addl 220(%rsp), %r12d + movl %r10d, %ecx + movl %r14d, %ebx + xorl %r11d, %ecx + rorl $14, %edx + andl %r9d, %ecx + xorl %r9d, %edx + xorl %r11d, %ecx + rorl $5, %edx + addl %ecx, %r12d + xorl %r9d, %edx + xorl %r13d, %ebx + rorl $6, %edx + movl %r13d, %ecx + addl %edx, %r12d + rorl $9, %ecx + andl %ebx, %eax + xorl %r13d, %ecx + xorl %r14d, %eax + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + # rnd_all_4: 15-18 + addl 240(%rsp), %r11d + movl %r9d, %ecx + movl %r13d, %eax + xorl %r10d, %ecx + rorl $14, %edx + andl %r8d, %ecx + xorl %r8d, %edx + xorl %r10d, %ecx + rorl $5, %edx + addl %ecx, %r11d + xorl %r8d, %edx + xorl %r12d, %eax + rorl $6, %edx + movl %r12d, %ecx + addl %edx, %r11d + rorl $9, %ecx + andl %eax, %ebx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + addl 244(%rsp), %r10d + movl %r8d, %ecx + movl %r12d, %ebx + xorl %r9d, %ecx + rorl $14, %edx + andl %r15d, %ecx + xorl %r15d, %edx + xorl %r9d, %ecx + rorl $5, %edx + addl %ecx, %r10d + xorl %r15d, %edx + xorl %r11d, %ebx + rorl $6, %edx + movl %r11d, %ecx + addl %edx, %r10d + rorl $9, %ecx + andl %ebx, %eax + xorl %r11d, %ecx + xorl %r12d, %eax + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + addl 248(%rsp), %r9d + movl %r15d, %ecx + movl %r11d, %eax + xorl %r8d, %ecx + rorl $14, %edx + andl %r14d, %ecx + xorl %r14d, %edx + xorl %r8d, %ecx + rorl $5, %edx + addl %ecx, %r9d + xorl %r14d, %edx + xorl %r10d, %eax + rorl $6, %edx + movl %r10d, %ecx + addl %edx, %r9d + rorl $9, %ecx + andl %eax, %ebx + xorl %r10d, %ecx + xorl %r11d, %ebx + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + addl 252(%rsp), %r8d + movl %r14d, %ecx + movl %r10d, %ebx + xorl %r15d, %ecx + rorl $14, %edx + andl %r13d, %ecx + xorl %r13d, %edx + xorl %r15d, %ecx + rorl $5, %edx + addl %ecx, %r8d + xorl %r13d, %edx + xorl %r9d, %ebx + rorl $6, %edx + movl %r9d, %ecx + addl %edx, %r8d + rorl $9, %ecx + andl %ebx, %eax + xorl %r9d, %ecx + xorl %r10d, %eax + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + # rnd_all_4: 17-20 + addl 272(%rsp), %r15d + movl %r13d, %ecx + movl %r9d, %eax + xorl %r14d, %ecx + rorl $14, %edx + andl %r12d, %ecx + xorl %r12d, %edx + xorl %r14d, %ecx + rorl $5, %edx + addl %ecx, %r15d + xorl %r12d, %edx + xorl %r8d, %eax + rorl $6, %edx + movl %r8d, %ecx + addl %edx, %r15d + rorl $9, %ecx + andl %eax, %ebx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + addl 276(%rsp), %r14d + movl %r12d, %ecx + movl %r8d, %ebx + xorl %r13d, %ecx + rorl $14, %edx + andl %r11d, %ecx + xorl %r11d, %edx + xorl %r13d, %ecx + rorl $5, %edx + addl %ecx, %r14d + xorl %r11d, %edx + xorl %r15d, %ebx + rorl $6, %edx + movl %r15d, %ecx + addl %edx, %r14d + rorl $9, %ecx + andl %ebx, %eax + xorl %r15d, %ecx + xorl %r8d, %eax + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + addl 280(%rsp), %r13d + movl %r11d, %ecx + movl %r15d, %eax + xorl %r12d, %ecx + rorl $14, %edx + andl %r10d, %ecx + xorl %r10d, %edx + xorl %r12d, %ecx + rorl $5, %edx + addl %ecx, %r13d + xorl %r10d, %edx + xorl %r14d, %eax + rorl $6, %edx + movl %r14d, %ecx + addl %edx, %r13d + rorl $9, %ecx + andl %eax, %ebx + xorl %r14d, %ecx + xorl %r15d, %ebx + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + addl 284(%rsp), %r12d + movl %r10d, %ecx + movl %r14d, %ebx + xorl %r11d, %ecx + rorl $14, %edx + andl %r9d, %ecx + xorl %r9d, %edx + xorl %r11d, %ecx + rorl $5, %edx + addl %ecx, %r12d + xorl %r9d, %edx + xorl %r13d, %ebx + rorl $6, %edx + movl %r13d, %ecx + addl %edx, %r12d + rorl $9, %ecx + andl %ebx, %eax + xorl %r13d, %ecx + xorl %r14d, %eax + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + # rnd_all_4: 19-22 + addl 304(%rsp), %r11d + movl %r9d, %ecx + movl %r13d, %eax + xorl %r10d, %ecx + rorl $14, %edx + andl %r8d, %ecx + xorl %r8d, %edx + xorl %r10d, %ecx + rorl $5, %edx + addl %ecx, %r11d + xorl %r8d, %edx + xorl %r12d, %eax + rorl $6, %edx + movl %r12d, %ecx + addl %edx, %r11d + rorl $9, %ecx + andl %eax, %ebx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + addl 308(%rsp), %r10d + movl %r8d, %ecx + movl %r12d, %ebx + xorl %r9d, %ecx + rorl $14, %edx + andl %r15d, %ecx + xorl %r15d, %edx + xorl %r9d, %ecx + rorl $5, %edx + addl %ecx, %r10d + xorl %r15d, %edx + xorl %r11d, %ebx + rorl $6, %edx + movl %r11d, %ecx + addl %edx, %r10d + rorl $9, %ecx + andl %ebx, %eax + xorl %r11d, %ecx + xorl %r12d, %eax + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + addl 312(%rsp), %r9d + movl %r15d, %ecx + movl %r11d, %eax + xorl %r8d, %ecx + rorl $14, %edx + andl %r14d, %ecx + xorl %r14d, %edx + xorl %r8d, %ecx + rorl $5, %edx + addl %ecx, %r9d + xorl %r14d, %edx + xorl %r10d, %eax + rorl $6, %edx + movl %r10d, %ecx + addl %edx, %r9d + rorl $9, %ecx + andl %eax, %ebx + xorl %r10d, %ecx + xorl %r11d, %ebx + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + addl 316(%rsp), %r8d + movl %r14d, %ecx + movl %r10d, %ebx + xorl %r15d, %ecx + rorl $14, %edx + andl %r13d, %ecx + xorl %r13d, %edx + xorl %r15d, %ecx + rorl $5, %edx + addl %ecx, %r8d + xorl %r13d, %edx + xorl %r9d, %ebx + rorl $6, %edx + movl %r9d, %ecx + addl %edx, %r8d + rorl $9, %ecx + andl %ebx, %eax + xorl %r9d, %ecx + xorl %r10d, %eax + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + # rnd_all_4: 21-24 + addl 336(%rsp), %r15d + movl %r13d, %ecx + movl %r9d, %eax + xorl %r14d, %ecx + rorl $14, %edx + andl %r12d, %ecx + xorl %r12d, %edx + xorl %r14d, %ecx + rorl $5, %edx + addl %ecx, %r15d + xorl %r12d, %edx + xorl %r8d, %eax + rorl $6, %edx + movl %r8d, %ecx + addl %edx, %r15d + rorl $9, %ecx + andl %eax, %ebx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + addl 340(%rsp), %r14d + movl %r12d, %ecx + movl %r8d, %ebx + xorl %r13d, %ecx + rorl $14, %edx + andl %r11d, %ecx + xorl %r11d, %edx + xorl %r13d, %ecx + rorl $5, %edx + addl %ecx, %r14d + xorl %r11d, %edx + xorl %r15d, %ebx + rorl $6, %edx + movl %r15d, %ecx + addl %edx, %r14d + rorl $9, %ecx + andl %ebx, %eax + xorl %r15d, %ecx + xorl %r8d, %eax + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + addl 344(%rsp), %r13d + movl %r11d, %ecx + movl %r15d, %eax + xorl %r12d, %ecx + rorl $14, %edx + andl %r10d, %ecx + xorl %r10d, %edx + xorl %r12d, %ecx + rorl $5, %edx + addl %ecx, %r13d + xorl %r10d, %edx + xorl %r14d, %eax + rorl $6, %edx + movl %r14d, %ecx + addl %edx, %r13d + rorl $9, %ecx + andl %eax, %ebx + xorl %r14d, %ecx + xorl %r15d, %ebx + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + addl 348(%rsp), %r12d + movl %r10d, %ecx + movl %r14d, %ebx + xorl %r11d, %ecx + rorl $14, %edx + andl %r9d, %ecx + xorl %r9d, %edx + xorl %r11d, %ecx + rorl $5, %edx + addl %ecx, %r12d + xorl %r9d, %edx + xorl %r13d, %ebx + rorl $6, %edx + movl %r13d, %ecx + addl %edx, %r12d + rorl $9, %ecx + andl %ebx, %eax + xorl %r13d, %ecx + xorl %r14d, %eax + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + # rnd_all_4: 23-26 + addl 368(%rsp), %r11d + movl %r9d, %ecx + movl %r13d, %eax + xorl %r10d, %ecx + rorl $14, %edx + andl %r8d, %ecx + xorl %r8d, %edx + xorl %r10d, %ecx + rorl $5, %edx + addl %ecx, %r11d + xorl %r8d, %edx + xorl %r12d, %eax + rorl $6, %edx + movl %r12d, %ecx + addl %edx, %r11d + rorl $9, %ecx + andl %eax, %ebx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + addl 372(%rsp), %r10d + movl %r8d, %ecx + movl %r12d, %ebx + xorl %r9d, %ecx + rorl $14, %edx + andl %r15d, %ecx + xorl %r15d, %edx + xorl %r9d, %ecx + rorl $5, %edx + addl %ecx, %r10d + xorl %r15d, %edx + xorl %r11d, %ebx + rorl $6, %edx + movl %r11d, %ecx + addl %edx, %r10d + rorl $9, %ecx + andl %ebx, %eax + xorl %r11d, %ecx + xorl %r12d, %eax + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + addl 376(%rsp), %r9d + movl %r15d, %ecx + movl %r11d, %eax + xorl %r8d, %ecx + rorl $14, %edx + andl %r14d, %ecx + xorl %r14d, %edx + xorl %r8d, %ecx + rorl $5, %edx + addl %ecx, %r9d + xorl %r14d, %edx + xorl %r10d, %eax + rorl $6, %edx + movl %r10d, %ecx + addl %edx, %r9d + rorl $9, %ecx + andl %eax, %ebx + xorl %r10d, %ecx + xorl %r11d, %ebx + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + addl 380(%rsp), %r8d + movl %r14d, %ecx + movl %r10d, %ebx + xorl %r15d, %ecx + rorl $14, %edx + andl %r13d, %ecx + xorl %r13d, %edx + xorl %r15d, %ecx + rorl $5, %edx + addl %ecx, %r8d + xorl %r13d, %edx + xorl %r9d, %ebx + rorl $6, %edx + movl %r9d, %ecx + addl %edx, %r8d + rorl $9, %ecx + andl %ebx, %eax + xorl %r9d, %ecx + xorl %r10d, %eax + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + # rnd_all_4: 25-28 + addl 400(%rsp), %r15d + movl %r13d, %ecx + movl %r9d, %eax + xorl %r14d, %ecx + rorl $14, %edx + andl %r12d, %ecx + xorl %r12d, %edx + xorl %r14d, %ecx + rorl $5, %edx + addl %ecx, %r15d + xorl %r12d, %edx + xorl %r8d, %eax + rorl $6, %edx + movl %r8d, %ecx + addl %edx, %r15d + rorl $9, %ecx + andl %eax, %ebx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + addl 404(%rsp), %r14d + movl %r12d, %ecx + movl %r8d, %ebx + xorl %r13d, %ecx + rorl $14, %edx + andl %r11d, %ecx + xorl %r11d, %edx + xorl %r13d, %ecx + rorl $5, %edx + addl %ecx, %r14d + xorl %r11d, %edx + xorl %r15d, %ebx + rorl $6, %edx + movl %r15d, %ecx + addl %edx, %r14d + rorl $9, %ecx + andl %ebx, %eax + xorl %r15d, %ecx + xorl %r8d, %eax + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + addl 408(%rsp), %r13d + movl %r11d, %ecx + movl %r15d, %eax + xorl %r12d, %ecx + rorl $14, %edx + andl %r10d, %ecx + xorl %r10d, %edx + xorl %r12d, %ecx + rorl $5, %edx + addl %ecx, %r13d + xorl %r10d, %edx + xorl %r14d, %eax + rorl $6, %edx + movl %r14d, %ecx + addl %edx, %r13d + rorl $9, %ecx + andl %eax, %ebx + xorl %r14d, %ecx + xorl %r15d, %ebx + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + addl 412(%rsp), %r12d + movl %r10d, %ecx + movl %r14d, %ebx + xorl %r11d, %ecx + rorl $14, %edx + andl %r9d, %ecx + xorl %r9d, %edx + xorl %r11d, %ecx + rorl $5, %edx + addl %ecx, %r12d + xorl %r9d, %edx + xorl %r13d, %ebx + rorl $6, %edx + movl %r13d, %ecx + addl %edx, %r12d + rorl $9, %ecx + andl %ebx, %eax + xorl %r13d, %ecx + xorl %r14d, %eax + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + # rnd_all_4: 27-30 + addl 432(%rsp), %r11d + movl %r9d, %ecx + movl %r13d, %eax + xorl %r10d, %ecx + rorl $14, %edx + andl %r8d, %ecx + xorl %r8d, %edx + xorl %r10d, %ecx + rorl $5, %edx + addl %ecx, %r11d + xorl %r8d, %edx + xorl %r12d, %eax + rorl $6, %edx + movl %r12d, %ecx + addl %edx, %r11d + rorl $9, %ecx + andl %eax, %ebx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + addl 436(%rsp), %r10d + movl %r8d, %ecx + movl %r12d, %ebx + xorl %r9d, %ecx + rorl $14, %edx + andl %r15d, %ecx + xorl %r15d, %edx + xorl %r9d, %ecx + rorl $5, %edx + addl %ecx, %r10d + xorl %r15d, %edx + xorl %r11d, %ebx + rorl $6, %edx + movl %r11d, %ecx + addl %edx, %r10d + rorl $9, %ecx + andl %ebx, %eax + xorl %r11d, %ecx + xorl %r12d, %eax + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + addl 440(%rsp), %r9d + movl %r15d, %ecx + movl %r11d, %eax + xorl %r8d, %ecx + rorl $14, %edx + andl %r14d, %ecx + xorl %r14d, %edx + xorl %r8d, %ecx + rorl $5, %edx + addl %ecx, %r9d + xorl %r14d, %edx + xorl %r10d, %eax + rorl $6, %edx + movl %r10d, %ecx + addl %edx, %r9d + rorl $9, %ecx + andl %eax, %ebx + xorl %r10d, %ecx + xorl %r11d, %ebx + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + addl 444(%rsp), %r8d + movl %r14d, %ecx + movl %r10d, %ebx + xorl %r15d, %ecx + rorl $14, %edx + andl %r13d, %ecx + xorl %r13d, %edx + xorl %r15d, %ecx + rorl $5, %edx + addl %ecx, %r8d + xorl %r13d, %edx + xorl %r9d, %ebx + rorl $6, %edx + movl %r9d, %ecx + addl %edx, %r8d + rorl $9, %ecx + andl %ebx, %eax + xorl %r9d, %ecx + xorl %r10d, %eax + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + # rnd_all_4: 29-32 + addl 464(%rsp), %r15d + movl %r13d, %ecx + movl %r9d, %eax + xorl %r14d, %ecx + rorl $14, %edx + andl %r12d, %ecx + xorl %r12d, %edx + xorl %r14d, %ecx + rorl $5, %edx + addl %ecx, %r15d + xorl %r12d, %edx + xorl %r8d, %eax + rorl $6, %edx + movl %r8d, %ecx + addl %edx, %r15d + rorl $9, %ecx + andl %eax, %ebx + xorl %r8d, %ecx + xorl %r9d, %ebx + rorl $11, %ecx + addl %r15d, %r11d + xorl %r8d, %ecx + addl %ebx, %r15d + rorl $2, %ecx + movl %r11d, %edx + addl %ecx, %r15d + addl 468(%rsp), %r14d + movl %r12d, %ecx + movl %r8d, %ebx + xorl %r13d, %ecx + rorl $14, %edx + andl %r11d, %ecx + xorl %r11d, %edx + xorl %r13d, %ecx + rorl $5, %edx + addl %ecx, %r14d + xorl %r11d, %edx + xorl %r15d, %ebx + rorl $6, %edx + movl %r15d, %ecx + addl %edx, %r14d + rorl $9, %ecx + andl %ebx, %eax + xorl %r15d, %ecx + xorl %r8d, %eax + rorl $11, %ecx + addl %r14d, %r10d + xorl %r15d, %ecx + addl %eax, %r14d + rorl $2, %ecx + movl %r10d, %edx + addl %ecx, %r14d + addl 472(%rsp), %r13d + movl %r11d, %ecx + movl %r15d, %eax + xorl %r12d, %ecx + rorl $14, %edx + andl %r10d, %ecx + xorl %r10d, %edx + xorl %r12d, %ecx + rorl $5, %edx + addl %ecx, %r13d + xorl %r10d, %edx + xorl %r14d, %eax + rorl $6, %edx + movl %r14d, %ecx + addl %edx, %r13d + rorl $9, %ecx + andl %eax, %ebx + xorl %r14d, %ecx + xorl %r15d, %ebx + rorl $11, %ecx + addl %r13d, %r9d + xorl %r14d, %ecx + addl %ebx, %r13d + rorl $2, %ecx + movl %r9d, %edx + addl %ecx, %r13d + addl 476(%rsp), %r12d + movl %r10d, %ecx + movl %r14d, %ebx + xorl %r11d, %ecx + rorl $14, %edx + andl %r9d, %ecx + xorl %r9d, %edx + xorl %r11d, %ecx + rorl $5, %edx + addl %ecx, %r12d + xorl %r9d, %edx + xorl %r13d, %ebx + rorl $6, %edx + movl %r13d, %ecx + addl %edx, %r12d + rorl $9, %ecx + andl %ebx, %eax + xorl %r13d, %ecx + xorl %r14d, %eax + rorl $11, %ecx + addl %r12d, %r8d + xorl %r13d, %ecx + addl %eax, %r12d + rorl $2, %ecx + movl %r8d, %edx + addl %ecx, %r12d + # rnd_all_4: 31-34 + addl 496(%rsp), %r11d + movl %r9d, %ecx + movl %r13d, %eax + xorl %r10d, %ecx + rorl $14, %edx + andl %r8d, %ecx + xorl %r8d, %edx + xorl %r10d, %ecx + rorl $5, %edx + addl %ecx, %r11d + xorl %r8d, %edx + xorl %r12d, %eax + rorl $6, %edx + movl %r12d, %ecx + addl %edx, %r11d + rorl $9, %ecx + andl %eax, %ebx + xorl %r12d, %ecx + xorl %r13d, %ebx + rorl $11, %ecx + addl %r11d, %r15d + xorl %r12d, %ecx + addl %ebx, %r11d + rorl $2, %ecx + movl %r15d, %edx + addl %ecx, %r11d + addl 500(%rsp), %r10d + movl %r8d, %ecx + movl %r12d, %ebx + xorl %r9d, %ecx + rorl $14, %edx + andl %r15d, %ecx + xorl %r15d, %edx + xorl %r9d, %ecx + rorl $5, %edx + addl %ecx, %r10d + xorl %r15d, %edx + xorl %r11d, %ebx + rorl $6, %edx + movl %r11d, %ecx + addl %edx, %r10d + rorl $9, %ecx + andl %ebx, %eax + xorl %r11d, %ecx + xorl %r12d, %eax + rorl $11, %ecx + addl %r10d, %r14d + xorl %r11d, %ecx + addl %eax, %r10d + rorl $2, %ecx + movl %r14d, %edx + addl %ecx, %r10d + addl 504(%rsp), %r9d + movl %r15d, %ecx + movl %r11d, %eax + xorl %r8d, %ecx + rorl $14, %edx + andl %r14d, %ecx + xorl %r14d, %edx + xorl %r8d, %ecx + rorl $5, %edx + addl %ecx, %r9d + xorl %r14d, %edx + xorl %r10d, %eax + rorl $6, %edx + movl %r10d, %ecx + addl %edx, %r9d + rorl $9, %ecx + andl %eax, %ebx + xorl %r10d, %ecx + xorl %r11d, %ebx + rorl $11, %ecx + addl %r9d, %r13d + xorl %r10d, %ecx + addl %ebx, %r9d + rorl $2, %ecx + movl %r13d, %edx + addl %ecx, %r9d + addl 508(%rsp), %r8d + movl %r14d, %ecx + movl %r10d, %ebx + xorl %r15d, %ecx + rorl $14, %edx + andl %r13d, %ecx + xorl %r13d, %edx + xorl %r15d, %ecx + rorl $5, %edx + addl %ecx, %r8d + xorl %r13d, %edx + xorl %r9d, %ebx + rorl $6, %edx + movl %r9d, %ecx + addl %edx, %r8d + rorl $9, %ecx + andl %ebx, %eax + xorl %r9d, %ecx + xorl %r10d, %eax + rorl $11, %ecx + addl %r8d, %r12d + xorl %r9d, %ecx + addl %eax, %r8d + rorl $2, %ecx + movl %r12d, %edx + addl %ecx, %r8d + addl (%rdi), %r8d + addl 4(%rdi), %r9d + addl 8(%rdi), %r10d + addl 12(%rdi), %r11d + addl 16(%rdi), %r12d + addl 20(%rdi), %r13d + addl 24(%rdi), %r14d + addl 28(%rdi), %r15d + addq $0x80, %rbp + subl $0x80, %esi + movl %r8d, (%rdi) + movl %r9d, 4(%rdi) + movl %r10d, 8(%rdi) + movl %r11d, 12(%rdi) + movl %r12d, 16(%rdi) + movl %r13d, 20(%rdi) + movl %r14d, 24(%rdi) + movl %r15d, 28(%rdi) + jnz L_sha256_len_avx2_start +L_sha256_len_avx2_done: + xorq %rax, %rax + vzeroupper + addq $0x200, %rsp + popq %rbp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size Transform_Sha256_AVX2_Len,.-Transform_Sha256_AVX2_Len +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +L_avx2_rorx_sha256_k: +.long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5 +.long 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5 +.long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5 +.long 0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5 +.long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3 +.long 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3 +.long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174 +.long 0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174 +.long 0xe49b69c1,0xefbe4786,0xfc19dc6,0x240ca1cc +.long 0xe49b69c1,0xefbe4786,0xfc19dc6,0x240ca1cc +.long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da +.long 0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da +.long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7 +.long 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7 +.long 0xc6e00bf3,0xd5a79147,0x6ca6351,0x14292967 +.long 0xc6e00bf3,0xd5a79147,0x6ca6351,0x14292967 +.long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13 +.long 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13 +.long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85 +.long 0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85 +.long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3 +.long 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3 +.long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070 +.long 0xd192e819,0xd6990624,0xf40e3585,0x106aa070 +.long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5 +.long 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5 +.long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3 +.long 0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3 +.long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208 +.long 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208 +.long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 +.long 0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 32 +#else +.p2align 5 +#endif /* __APPLE__ */ +L_avx2_rorx_sha256_flip_mask: +.quad 0x405060700010203, 0xc0d0e0f08090a0b +.quad 0x405060700010203, 0xc0d0e0f08090a0b +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 32 +#else +.p2align 5 +#endif /* __APPLE__ */ +L_avx2_rorx_sha256_shuf_00BA: +.quad 0xb0a090803020100, 0xffffffffffffffff +.quad 0xb0a090803020100, 0xffffffffffffffff +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 32 +#else +.p2align 5 +#endif /* __APPLE__ */ +L_avx2_rorx_sha256_shuf_DC00: +.quad 0xffffffffffffffff, 0xb0a090803020100 +.quad 0xffffffffffffffff, 0xb0a090803020100 +#ifndef __APPLE__ +.text +.globl Transform_Sha256_AVX2_RORX +.type Transform_Sha256_AVX2_RORX,@function +.align 4 +Transform_Sha256_AVX2_RORX: +#else +.section __TEXT,__text +.globl _Transform_Sha256_AVX2_RORX +.p2align 2 +_Transform_Sha256_AVX2_RORX: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + subq $0x200, %rsp + leaq 32(%rdi), %rax + vmovdqa L_avx2_rorx_sha256_flip_mask(%rip), %xmm13 + vmovdqa L_avx2_rorx_sha256_shuf_00BA(%rip), %ymm11 + vmovdqa L_avx2_rorx_sha256_shuf_DC00(%rip), %ymm12 + # X0, X1, X2, X3 = W[0..15] + vmovdqu (%rax), %xmm0 + vmovdqu 16(%rax), %xmm1 + vpshufb %xmm13, %xmm0, %xmm0 + vpshufb %xmm13, %xmm1, %xmm1 + vpaddd 0+L_avx2_rorx_sha256_k(%rip), %ymm0, %ymm4 + vpaddd 32+L_avx2_rorx_sha256_k(%rip), %ymm1, %ymm5 + vmovdqu %ymm4, (%rsp) + vmovdqu %ymm5, 32(%rsp) + vmovdqu 32(%rax), %xmm2 + vmovdqu 48(%rax), %xmm3 + vpshufb %xmm13, %xmm2, %xmm2 + vpshufb %xmm13, %xmm3, %xmm3 + vpaddd 64+L_avx2_rorx_sha256_k(%rip), %ymm2, %ymm4 + vpaddd 96+L_avx2_rorx_sha256_k(%rip), %ymm3, %ymm5 + vmovdqu %ymm4, 64(%rsp) + vmovdqu %ymm5, 96(%rsp) + movl (%rdi), %r8d + movl 4(%rdi), %r9d + movl 8(%rdi), %r10d + movl 12(%rdi), %r11d + movl 16(%rdi), %r12d + movl 20(%rdi), %r13d + movl 24(%rdi), %r14d + movl 28(%rdi), %r15d + movl %r9d, %ebx + rorxl $6, %r12d, %edx + xorl %r10d, %ebx + # rnd_0: 0 - 0 + movl %r13d, %eax + rorxl $11, %r12d, %ecx + addl (%rsp), %r15d + vpalignr $4, %ymm0, %ymm1, %ymm5 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + vpalignr $4, %ymm2, %ymm3, %ymm4 + # rnd_0: 2 - 2 + andl %r12d, %eax + xorl %ecx, %edx + rorxl $13, %r8d, %ecx + vpsrld $7, %ymm5, %ymm6 + # rnd_0: 3 - 3 + addl %edx, %r15d + rorxl $2, %r8d, %edx + xorl %r14d, %eax + vpslld $25, %ymm5, %ymm7 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + vpsrld $18, %ymm5, %ymm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + vpslld $14, %ymm5, %ymm9 + # rnd_0: 6 - 6 + xorl %r8d, %eax + addl %edx, %r15d + andl %eax, %ebx + vpor %ymm7, %ymm6, %ymm6 + # rnd_0: 7 - 7 + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + addl %ebx, %r15d + vpor %ymm9, %ymm8, %ymm8 + # rnd_1: 0 - 0 + movl %r12d, %ebx + rorxl $11, %r11d, %ecx + addl 4(%rsp), %r14d + vpsrld $3, %ymm5, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + vpxor %ymm8, %ymm6, %ymm6 + # rnd_1: 2 - 2 + andl %r11d, %ebx + xorl %ecx, %edx + rorxl $13, %r15d, %ecx + vpshufd $0xfa, %ymm3, %ymm7 + # rnd_1: 3 - 3 + addl %edx, %r14d + rorxl $2, %r15d, %edx + xorl %r13d, %ebx + vpxor %ymm6, %ymm9, %ymm5 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + vpsrld $10, %ymm7, %ymm8 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r14d, %r10d + movl %r8d, %ebx + vpsrlq $19, %ymm7, %ymm6 + # rnd_1: 6 - 6 + xorl %r15d, %ebx + addl %edx, %r14d + andl %ebx, %eax + vpsrlq $0x11, %ymm7, %ymm7 + # rnd_1: 7 - 7 + xorl %r8d, %eax + rorxl $6, %r10d, %edx + addl %eax, %r14d + vpaddd %ymm0, %ymm4, %ymm4 + # rnd_0: 0 - 0 + movl %r11d, %eax + rorxl $11, %r10d, %ecx + addl 8(%rsp), %r13d + vpxor %ymm7, %ymm6, %ymm6 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 2 - 2 + andl %r10d, %eax + xorl %ecx, %edx + rorxl $13, %r14d, %ecx + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 3 - 3 + addl %edx, %r13d + rorxl $2, %r14d, %edx + xorl %r12d, %eax + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + vpshufd $0x50, %ymm4, %ymm6 + # rnd_0: 6 - 6 + xorl %r14d, %eax + addl %edx, %r13d + andl %eax, %ebx + vpsrlq $0x11, %ymm6, %ymm8 + # rnd_0: 7 - 7 + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + addl %ebx, %r13d + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 0 - 0 + movl %r10d, %ebx + rorxl $11, %r9d, %ecx + addl 12(%rsp), %r12d + vpsrld $10, %ymm6, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + vpxor %ymm7, %ymm8, %ymm8 + # rnd_1: 2 - 2 + andl %r9d, %ebx + xorl %ecx, %edx + rorxl $13, %r13d, %ecx + vpxor %ymm8, %ymm9, %ymm9 + # rnd_1: 3 - 3 + addl %edx, %r12d + rorxl $2, %r13d, %edx + xorl %r11d, %ebx + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + vpaddd %ymm4, %ymm9, %ymm0 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r12d, %r8d + movl %r14d, %ebx + vpaddd 128+L_avx2_rorx_sha256_k(%rip), %ymm0, %ymm4 + # rnd_1: 6 - 6 + xorl %r13d, %ebx + addl %edx, %r12d + andl %ebx, %eax + # rnd_1: 7 - 7 + xorl %r14d, %eax + rorxl $6, %r8d, %edx + addl %eax, %r12d + vmovdqu %ymm4, 128(%rsp) + # rnd_0: 0 - 0 + movl %r9d, %eax + rorxl $11, %r8d, %ecx + addl 32(%rsp), %r11d + vpalignr $4, %ymm1, %ymm2, %ymm5 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + vpalignr $4, %ymm3, %ymm0, %ymm4 + # rnd_0: 2 - 2 + andl %r8d, %eax + xorl %ecx, %edx + rorxl $13, %r12d, %ecx + vpsrld $7, %ymm5, %ymm6 + # rnd_0: 3 - 3 + addl %edx, %r11d + rorxl $2, %r12d, %edx + xorl %r10d, %eax + vpslld $25, %ymm5, %ymm7 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + vpsrld $18, %ymm5, %ymm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + vpslld $14, %ymm5, %ymm9 + # rnd_0: 6 - 6 + xorl %r12d, %eax + addl %edx, %r11d + andl %eax, %ebx + vpor %ymm7, %ymm6, %ymm6 + # rnd_0: 7 - 7 + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + addl %ebx, %r11d + vpor %ymm9, %ymm8, %ymm8 + # rnd_1: 0 - 0 + movl %r8d, %ebx + rorxl $11, %r15d, %ecx + addl 36(%rsp), %r10d + vpsrld $3, %ymm5, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + vpxor %ymm8, %ymm6, %ymm6 + # rnd_1: 2 - 2 + andl %r15d, %ebx + xorl %ecx, %edx + rorxl $13, %r11d, %ecx + vpshufd $0xfa, %ymm0, %ymm7 + # rnd_1: 3 - 3 + addl %edx, %r10d + rorxl $2, %r11d, %edx + xorl %r9d, %ebx + vpxor %ymm6, %ymm9, %ymm5 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + vpsrld $10, %ymm7, %ymm8 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r10d, %r14d + movl %r12d, %ebx + vpsrlq $19, %ymm7, %ymm6 + # rnd_1: 6 - 6 + xorl %r11d, %ebx + addl %edx, %r10d + andl %ebx, %eax + vpsrlq $0x11, %ymm7, %ymm7 + # rnd_1: 7 - 7 + xorl %r12d, %eax + rorxl $6, %r14d, %edx + addl %eax, %r10d + vpaddd %ymm1, %ymm4, %ymm4 + # rnd_0: 0 - 0 + movl %r15d, %eax + rorxl $11, %r14d, %ecx + addl 40(%rsp), %r9d + vpxor %ymm7, %ymm6, %ymm6 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 2 - 2 + andl %r14d, %eax + xorl %ecx, %edx + rorxl $13, %r10d, %ecx + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 3 - 3 + addl %edx, %r9d + rorxl $2, %r10d, %edx + xorl %r8d, %eax + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + vpshufd $0x50, %ymm4, %ymm6 + # rnd_0: 6 - 6 + xorl %r10d, %eax + addl %edx, %r9d + andl %eax, %ebx + vpsrlq $0x11, %ymm6, %ymm8 + # rnd_0: 7 - 7 + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + addl %ebx, %r9d + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 0 - 0 + movl %r14d, %ebx + rorxl $11, %r13d, %ecx + addl 44(%rsp), %r8d + vpsrld $10, %ymm6, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + vpxor %ymm7, %ymm8, %ymm8 + # rnd_1: 2 - 2 + andl %r13d, %ebx + xorl %ecx, %edx + rorxl $13, %r9d, %ecx + vpxor %ymm8, %ymm9, %ymm9 + # rnd_1: 3 - 3 + addl %edx, %r8d + rorxl $2, %r9d, %edx + xorl %r15d, %ebx + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + vpaddd %ymm4, %ymm9, %ymm1 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r8d, %r12d + movl %r10d, %ebx + vpaddd 160+L_avx2_rorx_sha256_k(%rip), %ymm1, %ymm4 + # rnd_1: 6 - 6 + xorl %r9d, %ebx + addl %edx, %r8d + andl %ebx, %eax + # rnd_1: 7 - 7 + xorl %r10d, %eax + rorxl $6, %r12d, %edx + addl %eax, %r8d + vmovdqu %ymm4, 160(%rsp) + # rnd_0: 0 - 0 + movl %r13d, %eax + rorxl $11, %r12d, %ecx + addl 64(%rsp), %r15d + vpalignr $4, %ymm2, %ymm3, %ymm5 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + vpalignr $4, %ymm0, %ymm1, %ymm4 + # rnd_0: 2 - 2 + andl %r12d, %eax + xorl %ecx, %edx + rorxl $13, %r8d, %ecx + vpsrld $7, %ymm5, %ymm6 + # rnd_0: 3 - 3 + addl %edx, %r15d + rorxl $2, %r8d, %edx + xorl %r14d, %eax + vpslld $25, %ymm5, %ymm7 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + vpsrld $18, %ymm5, %ymm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + vpslld $14, %ymm5, %ymm9 + # rnd_0: 6 - 6 + xorl %r8d, %eax + addl %edx, %r15d + andl %eax, %ebx + vpor %ymm7, %ymm6, %ymm6 + # rnd_0: 7 - 7 + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + addl %ebx, %r15d + vpor %ymm9, %ymm8, %ymm8 + # rnd_1: 0 - 0 + movl %r12d, %ebx + rorxl $11, %r11d, %ecx + addl 68(%rsp), %r14d + vpsrld $3, %ymm5, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + vpxor %ymm8, %ymm6, %ymm6 + # rnd_1: 2 - 2 + andl %r11d, %ebx + xorl %ecx, %edx + rorxl $13, %r15d, %ecx + vpshufd $0xfa, %ymm1, %ymm7 + # rnd_1: 3 - 3 + addl %edx, %r14d + rorxl $2, %r15d, %edx + xorl %r13d, %ebx + vpxor %ymm6, %ymm9, %ymm5 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + vpsrld $10, %ymm7, %ymm8 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r14d, %r10d + movl %r8d, %ebx + vpsrlq $19, %ymm7, %ymm6 + # rnd_1: 6 - 6 + xorl %r15d, %ebx + addl %edx, %r14d + andl %ebx, %eax + vpsrlq $0x11, %ymm7, %ymm7 + # rnd_1: 7 - 7 + xorl %r8d, %eax + rorxl $6, %r10d, %edx + addl %eax, %r14d + vpaddd %ymm2, %ymm4, %ymm4 + # rnd_0: 0 - 0 + movl %r11d, %eax + rorxl $11, %r10d, %ecx + addl 72(%rsp), %r13d + vpxor %ymm7, %ymm6, %ymm6 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 2 - 2 + andl %r10d, %eax + xorl %ecx, %edx + rorxl $13, %r14d, %ecx + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 3 - 3 + addl %edx, %r13d + rorxl $2, %r14d, %edx + xorl %r12d, %eax + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + vpshufd $0x50, %ymm4, %ymm6 + # rnd_0: 6 - 6 + xorl %r14d, %eax + addl %edx, %r13d + andl %eax, %ebx + vpsrlq $0x11, %ymm6, %ymm8 + # rnd_0: 7 - 7 + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + addl %ebx, %r13d + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 0 - 0 + movl %r10d, %ebx + rorxl $11, %r9d, %ecx + addl 76(%rsp), %r12d + vpsrld $10, %ymm6, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + vpxor %ymm7, %ymm8, %ymm8 + # rnd_1: 2 - 2 + andl %r9d, %ebx + xorl %ecx, %edx + rorxl $13, %r13d, %ecx + vpxor %ymm8, %ymm9, %ymm9 + # rnd_1: 3 - 3 + addl %edx, %r12d + rorxl $2, %r13d, %edx + xorl %r11d, %ebx + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + vpaddd %ymm4, %ymm9, %ymm2 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r12d, %r8d + movl %r14d, %ebx + vpaddd 192+L_avx2_rorx_sha256_k(%rip), %ymm2, %ymm4 + # rnd_1: 6 - 6 + xorl %r13d, %ebx + addl %edx, %r12d + andl %ebx, %eax + # rnd_1: 7 - 7 + xorl %r14d, %eax + rorxl $6, %r8d, %edx + addl %eax, %r12d + vmovdqu %ymm4, 192(%rsp) + # rnd_0: 0 - 0 + movl %r9d, %eax + rorxl $11, %r8d, %ecx + addl 96(%rsp), %r11d + vpalignr $4, %ymm3, %ymm0, %ymm5 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + vpalignr $4, %ymm1, %ymm2, %ymm4 + # rnd_0: 2 - 2 + andl %r8d, %eax + xorl %ecx, %edx + rorxl $13, %r12d, %ecx + vpsrld $7, %ymm5, %ymm6 + # rnd_0: 3 - 3 + addl %edx, %r11d + rorxl $2, %r12d, %edx + xorl %r10d, %eax + vpslld $25, %ymm5, %ymm7 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + vpsrld $18, %ymm5, %ymm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + vpslld $14, %ymm5, %ymm9 + # rnd_0: 6 - 6 + xorl %r12d, %eax + addl %edx, %r11d + andl %eax, %ebx + vpor %ymm7, %ymm6, %ymm6 + # rnd_0: 7 - 7 + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + addl %ebx, %r11d + vpor %ymm9, %ymm8, %ymm8 + # rnd_1: 0 - 0 + movl %r8d, %ebx + rorxl $11, %r15d, %ecx + addl 100(%rsp), %r10d + vpsrld $3, %ymm5, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + vpxor %ymm8, %ymm6, %ymm6 + # rnd_1: 2 - 2 + andl %r15d, %ebx + xorl %ecx, %edx + rorxl $13, %r11d, %ecx + vpshufd $0xfa, %ymm2, %ymm7 + # rnd_1: 3 - 3 + addl %edx, %r10d + rorxl $2, %r11d, %edx + xorl %r9d, %ebx + vpxor %ymm6, %ymm9, %ymm5 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + vpsrld $10, %ymm7, %ymm8 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r10d, %r14d + movl %r12d, %ebx + vpsrlq $19, %ymm7, %ymm6 + # rnd_1: 6 - 6 + xorl %r11d, %ebx + addl %edx, %r10d + andl %ebx, %eax + vpsrlq $0x11, %ymm7, %ymm7 + # rnd_1: 7 - 7 + xorl %r12d, %eax + rorxl $6, %r14d, %edx + addl %eax, %r10d + vpaddd %ymm3, %ymm4, %ymm4 + # rnd_0: 0 - 0 + movl %r15d, %eax + rorxl $11, %r14d, %ecx + addl 104(%rsp), %r9d + vpxor %ymm7, %ymm6, %ymm6 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 2 - 2 + andl %r14d, %eax + xorl %ecx, %edx + rorxl $13, %r10d, %ecx + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 3 - 3 + addl %edx, %r9d + rorxl $2, %r10d, %edx + xorl %r8d, %eax + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + vpshufd $0x50, %ymm4, %ymm6 + # rnd_0: 6 - 6 + xorl %r10d, %eax + addl %edx, %r9d + andl %eax, %ebx + vpsrlq $0x11, %ymm6, %ymm8 + # rnd_0: 7 - 7 + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + addl %ebx, %r9d + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 0 - 0 + movl %r14d, %ebx + rorxl $11, %r13d, %ecx + addl 108(%rsp), %r8d + vpsrld $10, %ymm6, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + vpxor %ymm7, %ymm8, %ymm8 + # rnd_1: 2 - 2 + andl %r13d, %ebx + xorl %ecx, %edx + rorxl $13, %r9d, %ecx + vpxor %ymm8, %ymm9, %ymm9 + # rnd_1: 3 - 3 + addl %edx, %r8d + rorxl $2, %r9d, %edx + xorl %r15d, %ebx + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + vpaddd %ymm4, %ymm9, %ymm3 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r8d, %r12d + movl %r10d, %ebx + vpaddd 224+L_avx2_rorx_sha256_k(%rip), %ymm3, %ymm4 + # rnd_1: 6 - 6 + xorl %r9d, %ebx + addl %edx, %r8d + andl %ebx, %eax + # rnd_1: 7 - 7 + xorl %r10d, %eax + rorxl $6, %r12d, %edx + addl %eax, %r8d + vmovdqu %ymm4, 224(%rsp) + # rnd_0: 0 - 0 + movl %r13d, %eax + rorxl $11, %r12d, %ecx + addl 128(%rsp), %r15d + vpalignr $4, %ymm0, %ymm1, %ymm5 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + vpalignr $4, %ymm2, %ymm3, %ymm4 + # rnd_0: 2 - 2 + andl %r12d, %eax + xorl %ecx, %edx + rorxl $13, %r8d, %ecx + vpsrld $7, %ymm5, %ymm6 + # rnd_0: 3 - 3 + addl %edx, %r15d + rorxl $2, %r8d, %edx + xorl %r14d, %eax + vpslld $25, %ymm5, %ymm7 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + vpsrld $18, %ymm5, %ymm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + vpslld $14, %ymm5, %ymm9 + # rnd_0: 6 - 6 + xorl %r8d, %eax + addl %edx, %r15d + andl %eax, %ebx + vpor %ymm7, %ymm6, %ymm6 + # rnd_0: 7 - 7 + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + addl %ebx, %r15d + vpor %ymm9, %ymm8, %ymm8 + # rnd_1: 0 - 0 + movl %r12d, %ebx + rorxl $11, %r11d, %ecx + addl 132(%rsp), %r14d + vpsrld $3, %ymm5, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + vpxor %ymm8, %ymm6, %ymm6 + # rnd_1: 2 - 2 + andl %r11d, %ebx + xorl %ecx, %edx + rorxl $13, %r15d, %ecx + vpshufd $0xfa, %ymm3, %ymm7 + # rnd_1: 3 - 3 + addl %edx, %r14d + rorxl $2, %r15d, %edx + xorl %r13d, %ebx + vpxor %ymm6, %ymm9, %ymm5 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + vpsrld $10, %ymm7, %ymm8 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r14d, %r10d + movl %r8d, %ebx + vpsrlq $19, %ymm7, %ymm6 + # rnd_1: 6 - 6 + xorl %r15d, %ebx + addl %edx, %r14d + andl %ebx, %eax + vpsrlq $0x11, %ymm7, %ymm7 + # rnd_1: 7 - 7 + xorl %r8d, %eax + rorxl $6, %r10d, %edx + addl %eax, %r14d + vpaddd %ymm0, %ymm4, %ymm4 + # rnd_0: 0 - 0 + movl %r11d, %eax + rorxl $11, %r10d, %ecx + addl 136(%rsp), %r13d + vpxor %ymm7, %ymm6, %ymm6 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 2 - 2 + andl %r10d, %eax + xorl %ecx, %edx + rorxl $13, %r14d, %ecx + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 3 - 3 + addl %edx, %r13d + rorxl $2, %r14d, %edx + xorl %r12d, %eax + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + vpshufd $0x50, %ymm4, %ymm6 + # rnd_0: 6 - 6 + xorl %r14d, %eax + addl %edx, %r13d + andl %eax, %ebx + vpsrlq $0x11, %ymm6, %ymm8 + # rnd_0: 7 - 7 + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + addl %ebx, %r13d + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 0 - 0 + movl %r10d, %ebx + rorxl $11, %r9d, %ecx + addl 140(%rsp), %r12d + vpsrld $10, %ymm6, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + vpxor %ymm7, %ymm8, %ymm8 + # rnd_1: 2 - 2 + andl %r9d, %ebx + xorl %ecx, %edx + rorxl $13, %r13d, %ecx + vpxor %ymm8, %ymm9, %ymm9 + # rnd_1: 3 - 3 + addl %edx, %r12d + rorxl $2, %r13d, %edx + xorl %r11d, %ebx + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + vpaddd %ymm4, %ymm9, %ymm0 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r12d, %r8d + movl %r14d, %ebx + vpaddd 256+L_avx2_rorx_sha256_k(%rip), %ymm0, %ymm4 + # rnd_1: 6 - 6 + xorl %r13d, %ebx + addl %edx, %r12d + andl %ebx, %eax + # rnd_1: 7 - 7 + xorl %r14d, %eax + rorxl $6, %r8d, %edx + addl %eax, %r12d + vmovdqu %ymm4, 256(%rsp) + # rnd_0: 0 - 0 + movl %r9d, %eax + rorxl $11, %r8d, %ecx + addl 160(%rsp), %r11d + vpalignr $4, %ymm1, %ymm2, %ymm5 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + vpalignr $4, %ymm3, %ymm0, %ymm4 + # rnd_0: 2 - 2 + andl %r8d, %eax + xorl %ecx, %edx + rorxl $13, %r12d, %ecx + vpsrld $7, %ymm5, %ymm6 + # rnd_0: 3 - 3 + addl %edx, %r11d + rorxl $2, %r12d, %edx + xorl %r10d, %eax + vpslld $25, %ymm5, %ymm7 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + vpsrld $18, %ymm5, %ymm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + vpslld $14, %ymm5, %ymm9 + # rnd_0: 6 - 6 + xorl %r12d, %eax + addl %edx, %r11d + andl %eax, %ebx + vpor %ymm7, %ymm6, %ymm6 + # rnd_0: 7 - 7 + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + addl %ebx, %r11d + vpor %ymm9, %ymm8, %ymm8 + # rnd_1: 0 - 0 + movl %r8d, %ebx + rorxl $11, %r15d, %ecx + addl 164(%rsp), %r10d + vpsrld $3, %ymm5, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + vpxor %ymm8, %ymm6, %ymm6 + # rnd_1: 2 - 2 + andl %r15d, %ebx + xorl %ecx, %edx + rorxl $13, %r11d, %ecx + vpshufd $0xfa, %ymm0, %ymm7 + # rnd_1: 3 - 3 + addl %edx, %r10d + rorxl $2, %r11d, %edx + xorl %r9d, %ebx + vpxor %ymm6, %ymm9, %ymm5 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + vpsrld $10, %ymm7, %ymm8 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r10d, %r14d + movl %r12d, %ebx + vpsrlq $19, %ymm7, %ymm6 + # rnd_1: 6 - 6 + xorl %r11d, %ebx + addl %edx, %r10d + andl %ebx, %eax + vpsrlq $0x11, %ymm7, %ymm7 + # rnd_1: 7 - 7 + xorl %r12d, %eax + rorxl $6, %r14d, %edx + addl %eax, %r10d + vpaddd %ymm1, %ymm4, %ymm4 + # rnd_0: 0 - 0 + movl %r15d, %eax + rorxl $11, %r14d, %ecx + addl 168(%rsp), %r9d + vpxor %ymm7, %ymm6, %ymm6 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 2 - 2 + andl %r14d, %eax + xorl %ecx, %edx + rorxl $13, %r10d, %ecx + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 3 - 3 + addl %edx, %r9d + rorxl $2, %r10d, %edx + xorl %r8d, %eax + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + vpshufd $0x50, %ymm4, %ymm6 + # rnd_0: 6 - 6 + xorl %r10d, %eax + addl %edx, %r9d + andl %eax, %ebx + vpsrlq $0x11, %ymm6, %ymm8 + # rnd_0: 7 - 7 + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + addl %ebx, %r9d + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 0 - 0 + movl %r14d, %ebx + rorxl $11, %r13d, %ecx + addl 172(%rsp), %r8d + vpsrld $10, %ymm6, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + vpxor %ymm7, %ymm8, %ymm8 + # rnd_1: 2 - 2 + andl %r13d, %ebx + xorl %ecx, %edx + rorxl $13, %r9d, %ecx + vpxor %ymm8, %ymm9, %ymm9 + # rnd_1: 3 - 3 + addl %edx, %r8d + rorxl $2, %r9d, %edx + xorl %r15d, %ebx + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + vpaddd %ymm4, %ymm9, %ymm1 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r8d, %r12d + movl %r10d, %ebx + vpaddd 288+L_avx2_rorx_sha256_k(%rip), %ymm1, %ymm4 + # rnd_1: 6 - 6 + xorl %r9d, %ebx + addl %edx, %r8d + andl %ebx, %eax + # rnd_1: 7 - 7 + xorl %r10d, %eax + rorxl $6, %r12d, %edx + addl %eax, %r8d + vmovdqu %ymm4, 288(%rsp) + # rnd_0: 0 - 0 + movl %r13d, %eax + rorxl $11, %r12d, %ecx + addl 192(%rsp), %r15d + vpalignr $4, %ymm2, %ymm3, %ymm5 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + vpalignr $4, %ymm0, %ymm1, %ymm4 + # rnd_0: 2 - 2 + andl %r12d, %eax + xorl %ecx, %edx + rorxl $13, %r8d, %ecx + vpsrld $7, %ymm5, %ymm6 + # rnd_0: 3 - 3 + addl %edx, %r15d + rorxl $2, %r8d, %edx + xorl %r14d, %eax + vpslld $25, %ymm5, %ymm7 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + vpsrld $18, %ymm5, %ymm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + vpslld $14, %ymm5, %ymm9 + # rnd_0: 6 - 6 + xorl %r8d, %eax + addl %edx, %r15d + andl %eax, %ebx + vpor %ymm7, %ymm6, %ymm6 + # rnd_0: 7 - 7 + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + addl %ebx, %r15d + vpor %ymm9, %ymm8, %ymm8 + # rnd_1: 0 - 0 + movl %r12d, %ebx + rorxl $11, %r11d, %ecx + addl 196(%rsp), %r14d + vpsrld $3, %ymm5, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + vpxor %ymm8, %ymm6, %ymm6 + # rnd_1: 2 - 2 + andl %r11d, %ebx + xorl %ecx, %edx + rorxl $13, %r15d, %ecx + vpshufd $0xfa, %ymm1, %ymm7 + # rnd_1: 3 - 3 + addl %edx, %r14d + rorxl $2, %r15d, %edx + xorl %r13d, %ebx + vpxor %ymm6, %ymm9, %ymm5 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + vpsrld $10, %ymm7, %ymm8 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r14d, %r10d + movl %r8d, %ebx + vpsrlq $19, %ymm7, %ymm6 + # rnd_1: 6 - 6 + xorl %r15d, %ebx + addl %edx, %r14d + andl %ebx, %eax + vpsrlq $0x11, %ymm7, %ymm7 + # rnd_1: 7 - 7 + xorl %r8d, %eax + rorxl $6, %r10d, %edx + addl %eax, %r14d + vpaddd %ymm2, %ymm4, %ymm4 + # rnd_0: 0 - 0 + movl %r11d, %eax + rorxl $11, %r10d, %ecx + addl 200(%rsp), %r13d + vpxor %ymm7, %ymm6, %ymm6 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 2 - 2 + andl %r10d, %eax + xorl %ecx, %edx + rorxl $13, %r14d, %ecx + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 3 - 3 + addl %edx, %r13d + rorxl $2, %r14d, %edx + xorl %r12d, %eax + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + vpshufd $0x50, %ymm4, %ymm6 + # rnd_0: 6 - 6 + xorl %r14d, %eax + addl %edx, %r13d + andl %eax, %ebx + vpsrlq $0x11, %ymm6, %ymm8 + # rnd_0: 7 - 7 + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + addl %ebx, %r13d + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 0 - 0 + movl %r10d, %ebx + rorxl $11, %r9d, %ecx + addl 204(%rsp), %r12d + vpsrld $10, %ymm6, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + vpxor %ymm7, %ymm8, %ymm8 + # rnd_1: 2 - 2 + andl %r9d, %ebx + xorl %ecx, %edx + rorxl $13, %r13d, %ecx + vpxor %ymm8, %ymm9, %ymm9 + # rnd_1: 3 - 3 + addl %edx, %r12d + rorxl $2, %r13d, %edx + xorl %r11d, %ebx + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + vpaddd %ymm4, %ymm9, %ymm2 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r12d, %r8d + movl %r14d, %ebx + vpaddd 320+L_avx2_rorx_sha256_k(%rip), %ymm2, %ymm4 + # rnd_1: 6 - 6 + xorl %r13d, %ebx + addl %edx, %r12d + andl %ebx, %eax + # rnd_1: 7 - 7 + xorl %r14d, %eax + rorxl $6, %r8d, %edx + addl %eax, %r12d + vmovdqu %ymm4, 320(%rsp) + # rnd_0: 0 - 0 + movl %r9d, %eax + rorxl $11, %r8d, %ecx + addl 224(%rsp), %r11d + vpalignr $4, %ymm3, %ymm0, %ymm5 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + vpalignr $4, %ymm1, %ymm2, %ymm4 + # rnd_0: 2 - 2 + andl %r8d, %eax + xorl %ecx, %edx + rorxl $13, %r12d, %ecx + vpsrld $7, %ymm5, %ymm6 + # rnd_0: 3 - 3 + addl %edx, %r11d + rorxl $2, %r12d, %edx + xorl %r10d, %eax + vpslld $25, %ymm5, %ymm7 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + vpsrld $18, %ymm5, %ymm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + vpslld $14, %ymm5, %ymm9 + # rnd_0: 6 - 6 + xorl %r12d, %eax + addl %edx, %r11d + andl %eax, %ebx + vpor %ymm7, %ymm6, %ymm6 + # rnd_0: 7 - 7 + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + addl %ebx, %r11d + vpor %ymm9, %ymm8, %ymm8 + # rnd_1: 0 - 0 + movl %r8d, %ebx + rorxl $11, %r15d, %ecx + addl 228(%rsp), %r10d + vpsrld $3, %ymm5, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + vpxor %ymm8, %ymm6, %ymm6 + # rnd_1: 2 - 2 + andl %r15d, %ebx + xorl %ecx, %edx + rorxl $13, %r11d, %ecx + vpshufd $0xfa, %ymm2, %ymm7 + # rnd_1: 3 - 3 + addl %edx, %r10d + rorxl $2, %r11d, %edx + xorl %r9d, %ebx + vpxor %ymm6, %ymm9, %ymm5 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + vpsrld $10, %ymm7, %ymm8 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r10d, %r14d + movl %r12d, %ebx + vpsrlq $19, %ymm7, %ymm6 + # rnd_1: 6 - 6 + xorl %r11d, %ebx + addl %edx, %r10d + andl %ebx, %eax + vpsrlq $0x11, %ymm7, %ymm7 + # rnd_1: 7 - 7 + xorl %r12d, %eax + rorxl $6, %r14d, %edx + addl %eax, %r10d + vpaddd %ymm3, %ymm4, %ymm4 + # rnd_0: 0 - 0 + movl %r15d, %eax + rorxl $11, %r14d, %ecx + addl 232(%rsp), %r9d + vpxor %ymm7, %ymm6, %ymm6 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 2 - 2 + andl %r14d, %eax + xorl %ecx, %edx + rorxl $13, %r10d, %ecx + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 3 - 3 + addl %edx, %r9d + rorxl $2, %r10d, %edx + xorl %r8d, %eax + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + vpshufd $0x50, %ymm4, %ymm6 + # rnd_0: 6 - 6 + xorl %r10d, %eax + addl %edx, %r9d + andl %eax, %ebx + vpsrlq $0x11, %ymm6, %ymm8 + # rnd_0: 7 - 7 + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + addl %ebx, %r9d + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 0 - 0 + movl %r14d, %ebx + rorxl $11, %r13d, %ecx + addl 236(%rsp), %r8d + vpsrld $10, %ymm6, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + vpxor %ymm7, %ymm8, %ymm8 + # rnd_1: 2 - 2 + andl %r13d, %ebx + xorl %ecx, %edx + rorxl $13, %r9d, %ecx + vpxor %ymm8, %ymm9, %ymm9 + # rnd_1: 3 - 3 + addl %edx, %r8d + rorxl $2, %r9d, %edx + xorl %r15d, %ebx + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + vpaddd %ymm4, %ymm9, %ymm3 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r8d, %r12d + movl %r10d, %ebx + vpaddd 352+L_avx2_rorx_sha256_k(%rip), %ymm3, %ymm4 + # rnd_1: 6 - 6 + xorl %r9d, %ebx + addl %edx, %r8d + andl %ebx, %eax + # rnd_1: 7 - 7 + xorl %r10d, %eax + rorxl $6, %r12d, %edx + addl %eax, %r8d + vmovdqu %ymm4, 352(%rsp) + # rnd_0: 0 - 0 + movl %r13d, %eax + rorxl $11, %r12d, %ecx + addl 256(%rsp), %r15d + vpalignr $4, %ymm0, %ymm1, %ymm5 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + vpalignr $4, %ymm2, %ymm3, %ymm4 + # rnd_0: 2 - 2 + andl %r12d, %eax + xorl %ecx, %edx + rorxl $13, %r8d, %ecx + vpsrld $7, %ymm5, %ymm6 + # rnd_0: 3 - 3 + addl %edx, %r15d + rorxl $2, %r8d, %edx + xorl %r14d, %eax + vpslld $25, %ymm5, %ymm7 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + vpsrld $18, %ymm5, %ymm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + vpslld $14, %ymm5, %ymm9 + # rnd_0: 6 - 6 + xorl %r8d, %eax + addl %edx, %r15d + andl %eax, %ebx + vpor %ymm7, %ymm6, %ymm6 + # rnd_0: 7 - 7 + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + addl %ebx, %r15d + vpor %ymm9, %ymm8, %ymm8 + # rnd_1: 0 - 0 + movl %r12d, %ebx + rorxl $11, %r11d, %ecx + addl 260(%rsp), %r14d + vpsrld $3, %ymm5, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + vpxor %ymm8, %ymm6, %ymm6 + # rnd_1: 2 - 2 + andl %r11d, %ebx + xorl %ecx, %edx + rorxl $13, %r15d, %ecx + vpshufd $0xfa, %ymm3, %ymm7 + # rnd_1: 3 - 3 + addl %edx, %r14d + rorxl $2, %r15d, %edx + xorl %r13d, %ebx + vpxor %ymm6, %ymm9, %ymm5 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + vpsrld $10, %ymm7, %ymm8 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r14d, %r10d + movl %r8d, %ebx + vpsrlq $19, %ymm7, %ymm6 + # rnd_1: 6 - 6 + xorl %r15d, %ebx + addl %edx, %r14d + andl %ebx, %eax + vpsrlq $0x11, %ymm7, %ymm7 + # rnd_1: 7 - 7 + xorl %r8d, %eax + rorxl $6, %r10d, %edx + addl %eax, %r14d + vpaddd %ymm0, %ymm4, %ymm4 + # rnd_0: 0 - 0 + movl %r11d, %eax + rorxl $11, %r10d, %ecx + addl 264(%rsp), %r13d + vpxor %ymm7, %ymm6, %ymm6 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 2 - 2 + andl %r10d, %eax + xorl %ecx, %edx + rorxl $13, %r14d, %ecx + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 3 - 3 + addl %edx, %r13d + rorxl $2, %r14d, %edx + xorl %r12d, %eax + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + vpshufd $0x50, %ymm4, %ymm6 + # rnd_0: 6 - 6 + xorl %r14d, %eax + addl %edx, %r13d + andl %eax, %ebx + vpsrlq $0x11, %ymm6, %ymm8 + # rnd_0: 7 - 7 + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + addl %ebx, %r13d + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 0 - 0 + movl %r10d, %ebx + rorxl $11, %r9d, %ecx + addl 268(%rsp), %r12d + vpsrld $10, %ymm6, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + vpxor %ymm7, %ymm8, %ymm8 + # rnd_1: 2 - 2 + andl %r9d, %ebx + xorl %ecx, %edx + rorxl $13, %r13d, %ecx + vpxor %ymm8, %ymm9, %ymm9 + # rnd_1: 3 - 3 + addl %edx, %r12d + rorxl $2, %r13d, %edx + xorl %r11d, %ebx + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + vpaddd %ymm4, %ymm9, %ymm0 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r12d, %r8d + movl %r14d, %ebx + vpaddd 384+L_avx2_rorx_sha256_k(%rip), %ymm0, %ymm4 + # rnd_1: 6 - 6 + xorl %r13d, %ebx + addl %edx, %r12d + andl %ebx, %eax + # rnd_1: 7 - 7 + xorl %r14d, %eax + rorxl $6, %r8d, %edx + addl %eax, %r12d + vmovdqu %ymm4, 384(%rsp) + # rnd_0: 0 - 0 + movl %r9d, %eax + rorxl $11, %r8d, %ecx + addl 288(%rsp), %r11d + vpalignr $4, %ymm1, %ymm2, %ymm5 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + vpalignr $4, %ymm3, %ymm0, %ymm4 + # rnd_0: 2 - 2 + andl %r8d, %eax + xorl %ecx, %edx + rorxl $13, %r12d, %ecx + vpsrld $7, %ymm5, %ymm6 + # rnd_0: 3 - 3 + addl %edx, %r11d + rorxl $2, %r12d, %edx + xorl %r10d, %eax + vpslld $25, %ymm5, %ymm7 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + vpsrld $18, %ymm5, %ymm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + vpslld $14, %ymm5, %ymm9 + # rnd_0: 6 - 6 + xorl %r12d, %eax + addl %edx, %r11d + andl %eax, %ebx + vpor %ymm7, %ymm6, %ymm6 + # rnd_0: 7 - 7 + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + addl %ebx, %r11d + vpor %ymm9, %ymm8, %ymm8 + # rnd_1: 0 - 0 + movl %r8d, %ebx + rorxl $11, %r15d, %ecx + addl 292(%rsp), %r10d + vpsrld $3, %ymm5, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + vpxor %ymm8, %ymm6, %ymm6 + # rnd_1: 2 - 2 + andl %r15d, %ebx + xorl %ecx, %edx + rorxl $13, %r11d, %ecx + vpshufd $0xfa, %ymm0, %ymm7 + # rnd_1: 3 - 3 + addl %edx, %r10d + rorxl $2, %r11d, %edx + xorl %r9d, %ebx + vpxor %ymm6, %ymm9, %ymm5 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + vpsrld $10, %ymm7, %ymm8 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r10d, %r14d + movl %r12d, %ebx + vpsrlq $19, %ymm7, %ymm6 + # rnd_1: 6 - 6 + xorl %r11d, %ebx + addl %edx, %r10d + andl %ebx, %eax + vpsrlq $0x11, %ymm7, %ymm7 + # rnd_1: 7 - 7 + xorl %r12d, %eax + rorxl $6, %r14d, %edx + addl %eax, %r10d + vpaddd %ymm1, %ymm4, %ymm4 + # rnd_0: 0 - 0 + movl %r15d, %eax + rorxl $11, %r14d, %ecx + addl 296(%rsp), %r9d + vpxor %ymm7, %ymm6, %ymm6 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 2 - 2 + andl %r14d, %eax + xorl %ecx, %edx + rorxl $13, %r10d, %ecx + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 3 - 3 + addl %edx, %r9d + rorxl $2, %r10d, %edx + xorl %r8d, %eax + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + vpshufd $0x50, %ymm4, %ymm6 + # rnd_0: 6 - 6 + xorl %r10d, %eax + addl %edx, %r9d + andl %eax, %ebx + vpsrlq $0x11, %ymm6, %ymm8 + # rnd_0: 7 - 7 + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + addl %ebx, %r9d + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 0 - 0 + movl %r14d, %ebx + rorxl $11, %r13d, %ecx + addl 300(%rsp), %r8d + vpsrld $10, %ymm6, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + vpxor %ymm7, %ymm8, %ymm8 + # rnd_1: 2 - 2 + andl %r13d, %ebx + xorl %ecx, %edx + rorxl $13, %r9d, %ecx + vpxor %ymm8, %ymm9, %ymm9 + # rnd_1: 3 - 3 + addl %edx, %r8d + rorxl $2, %r9d, %edx + xorl %r15d, %ebx + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + vpaddd %ymm4, %ymm9, %ymm1 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r8d, %r12d + movl %r10d, %ebx + vpaddd 416+L_avx2_rorx_sha256_k(%rip), %ymm1, %ymm4 + # rnd_1: 6 - 6 + xorl %r9d, %ebx + addl %edx, %r8d + andl %ebx, %eax + # rnd_1: 7 - 7 + xorl %r10d, %eax + rorxl $6, %r12d, %edx + addl %eax, %r8d + vmovdqu %ymm4, 416(%rsp) + # rnd_0: 0 - 0 + movl %r13d, %eax + rorxl $11, %r12d, %ecx + addl 320(%rsp), %r15d + vpalignr $4, %ymm2, %ymm3, %ymm5 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + vpalignr $4, %ymm0, %ymm1, %ymm4 + # rnd_0: 2 - 2 + andl %r12d, %eax + xorl %ecx, %edx + rorxl $13, %r8d, %ecx + vpsrld $7, %ymm5, %ymm6 + # rnd_0: 3 - 3 + addl %edx, %r15d + rorxl $2, %r8d, %edx + xorl %r14d, %eax + vpslld $25, %ymm5, %ymm7 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + vpsrld $18, %ymm5, %ymm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + vpslld $14, %ymm5, %ymm9 + # rnd_0: 6 - 6 + xorl %r8d, %eax + addl %edx, %r15d + andl %eax, %ebx + vpor %ymm7, %ymm6, %ymm6 + # rnd_0: 7 - 7 + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + addl %ebx, %r15d + vpor %ymm9, %ymm8, %ymm8 + # rnd_1: 0 - 0 + movl %r12d, %ebx + rorxl $11, %r11d, %ecx + addl 324(%rsp), %r14d + vpsrld $3, %ymm5, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + vpxor %ymm8, %ymm6, %ymm6 + # rnd_1: 2 - 2 + andl %r11d, %ebx + xorl %ecx, %edx + rorxl $13, %r15d, %ecx + vpshufd $0xfa, %ymm1, %ymm7 + # rnd_1: 3 - 3 + addl %edx, %r14d + rorxl $2, %r15d, %edx + xorl %r13d, %ebx + vpxor %ymm6, %ymm9, %ymm5 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + vpsrld $10, %ymm7, %ymm8 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r14d, %r10d + movl %r8d, %ebx + vpsrlq $19, %ymm7, %ymm6 + # rnd_1: 6 - 6 + xorl %r15d, %ebx + addl %edx, %r14d + andl %ebx, %eax + vpsrlq $0x11, %ymm7, %ymm7 + # rnd_1: 7 - 7 + xorl %r8d, %eax + rorxl $6, %r10d, %edx + addl %eax, %r14d + vpaddd %ymm2, %ymm4, %ymm4 + # rnd_0: 0 - 0 + movl %r11d, %eax + rorxl $11, %r10d, %ecx + addl 328(%rsp), %r13d + vpxor %ymm7, %ymm6, %ymm6 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 2 - 2 + andl %r10d, %eax + xorl %ecx, %edx + rorxl $13, %r14d, %ecx + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 3 - 3 + addl %edx, %r13d + rorxl $2, %r14d, %edx + xorl %r12d, %eax + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + vpshufd $0x50, %ymm4, %ymm6 + # rnd_0: 6 - 6 + xorl %r14d, %eax + addl %edx, %r13d + andl %eax, %ebx + vpsrlq $0x11, %ymm6, %ymm8 + # rnd_0: 7 - 7 + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + addl %ebx, %r13d + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 0 - 0 + movl %r10d, %ebx + rorxl $11, %r9d, %ecx + addl 332(%rsp), %r12d + vpsrld $10, %ymm6, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + vpxor %ymm7, %ymm8, %ymm8 + # rnd_1: 2 - 2 + andl %r9d, %ebx + xorl %ecx, %edx + rorxl $13, %r13d, %ecx + vpxor %ymm8, %ymm9, %ymm9 + # rnd_1: 3 - 3 + addl %edx, %r12d + rorxl $2, %r13d, %edx + xorl %r11d, %ebx + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + vpaddd %ymm4, %ymm9, %ymm2 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r12d, %r8d + movl %r14d, %ebx + vpaddd 448+L_avx2_rorx_sha256_k(%rip), %ymm2, %ymm4 + # rnd_1: 6 - 6 + xorl %r13d, %ebx + addl %edx, %r12d + andl %ebx, %eax + # rnd_1: 7 - 7 + xorl %r14d, %eax + rorxl $6, %r8d, %edx + addl %eax, %r12d + vmovdqu %ymm4, 448(%rsp) + # rnd_0: 0 - 0 + movl %r9d, %eax + rorxl $11, %r8d, %ecx + addl 352(%rsp), %r11d + vpalignr $4, %ymm3, %ymm0, %ymm5 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + vpalignr $4, %ymm1, %ymm2, %ymm4 + # rnd_0: 2 - 2 + andl %r8d, %eax + xorl %ecx, %edx + rorxl $13, %r12d, %ecx + vpsrld $7, %ymm5, %ymm6 + # rnd_0: 3 - 3 + addl %edx, %r11d + rorxl $2, %r12d, %edx + xorl %r10d, %eax + vpslld $25, %ymm5, %ymm7 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + vpsrld $18, %ymm5, %ymm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + vpslld $14, %ymm5, %ymm9 + # rnd_0: 6 - 6 + xorl %r12d, %eax + addl %edx, %r11d + andl %eax, %ebx + vpor %ymm7, %ymm6, %ymm6 + # rnd_0: 7 - 7 + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + addl %ebx, %r11d + vpor %ymm9, %ymm8, %ymm8 + # rnd_1: 0 - 0 + movl %r8d, %ebx + rorxl $11, %r15d, %ecx + addl 356(%rsp), %r10d + vpsrld $3, %ymm5, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + vpxor %ymm8, %ymm6, %ymm6 + # rnd_1: 2 - 2 + andl %r15d, %ebx + xorl %ecx, %edx + rorxl $13, %r11d, %ecx + vpshufd $0xfa, %ymm2, %ymm7 + # rnd_1: 3 - 3 + addl %edx, %r10d + rorxl $2, %r11d, %edx + xorl %r9d, %ebx + vpxor %ymm6, %ymm9, %ymm5 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + vpsrld $10, %ymm7, %ymm8 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r10d, %r14d + movl %r12d, %ebx + vpsrlq $19, %ymm7, %ymm6 + # rnd_1: 6 - 6 + xorl %r11d, %ebx + addl %edx, %r10d + andl %ebx, %eax + vpsrlq $0x11, %ymm7, %ymm7 + # rnd_1: 7 - 7 + xorl %r12d, %eax + rorxl $6, %r14d, %edx + addl %eax, %r10d + vpaddd %ymm3, %ymm4, %ymm4 + # rnd_0: 0 - 0 + movl %r15d, %eax + rorxl $11, %r14d, %ecx + addl 360(%rsp), %r9d + vpxor %ymm7, %ymm6, %ymm6 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 2 - 2 + andl %r14d, %eax + xorl %ecx, %edx + rorxl $13, %r10d, %ecx + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 3 - 3 + addl %edx, %r9d + rorxl $2, %r10d, %edx + xorl %r8d, %eax + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + vpshufd $0x50, %ymm4, %ymm6 + # rnd_0: 6 - 6 + xorl %r10d, %eax + addl %edx, %r9d + andl %eax, %ebx + vpsrlq $0x11, %ymm6, %ymm8 + # rnd_0: 7 - 7 + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + addl %ebx, %r9d + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 0 - 0 + movl %r14d, %ebx + rorxl $11, %r13d, %ecx + addl 364(%rsp), %r8d + vpsrld $10, %ymm6, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + vpxor %ymm7, %ymm8, %ymm8 + # rnd_1: 2 - 2 + andl %r13d, %ebx + xorl %ecx, %edx + rorxl $13, %r9d, %ecx + vpxor %ymm8, %ymm9, %ymm9 + # rnd_1: 3 - 3 + addl %edx, %r8d + rorxl $2, %r9d, %edx + xorl %r15d, %ebx + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + vpaddd %ymm4, %ymm9, %ymm3 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r8d, %r12d + movl %r10d, %ebx + vpaddd 480+L_avx2_rorx_sha256_k(%rip), %ymm3, %ymm4 + # rnd_1: 6 - 6 + xorl %r9d, %ebx + addl %edx, %r8d + andl %ebx, %eax + # rnd_1: 7 - 7 + xorl %r10d, %eax + rorxl $6, %r12d, %edx + addl %eax, %r8d + vmovdqu %ymm4, 480(%rsp) + xorl %eax, %eax + xorl %ecx, %ecx + rorxl $6, %r12d, %edx + rorxl $11, %r12d, %ecx + leal (%r8,%rax,1), %r8d + addl 384(%rsp), %r15d + movl %r13d, %eax + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + xorl %ecx, %edx + andl %r12d, %eax + addl %edx, %r15d + rorxl $2, %r8d, %edx + rorxl $13, %r8d, %ecx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + andl %eax, %ebx + addl %edx, %r15d + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + rorxl $11, %r11d, %ecx + addl %ebx, %r15d + addl 388(%rsp), %r14d + movl %r12d, %ebx + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + xorl %ecx, %edx + andl %r11d, %ebx + addl %edx, %r14d + rorxl $2, %r15d, %edx + rorxl $13, %r15d, %ecx + xorl %r13d, %ebx + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + xorl %ecx, %edx + movl %r8d, %ebx + leal (%r10,%r14,1), %r10d + xorl %r15d, %ebx + andl %ebx, %eax + addl %edx, %r14d + xorl %r8d, %eax + rorxl $6, %r10d, %edx + rorxl $11, %r10d, %ecx + leal (%r14,%rax,1), %r14d + addl 392(%rsp), %r13d + movl %r11d, %eax + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + xorl %ecx, %edx + andl %r10d, %eax + addl %edx, %r13d + rorxl $2, %r14d, %edx + rorxl $13, %r14d, %ecx + xorl %r12d, %eax + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + xorl %r14d, %eax + andl %eax, %ebx + addl %edx, %r13d + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + rorxl $11, %r9d, %ecx + addl %ebx, %r13d + addl 396(%rsp), %r12d + movl %r10d, %ebx + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + xorl %ecx, %edx + andl %r9d, %ebx + addl %edx, %r12d + rorxl $2, %r13d, %edx + rorxl $13, %r13d, %ecx + xorl %r11d, %ebx + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + xorl %ecx, %edx + movl %r14d, %ebx + leal (%r8,%r12,1), %r8d + xorl %r13d, %ebx + andl %ebx, %eax + addl %edx, %r12d + xorl %r14d, %eax + rorxl $6, %r8d, %edx + rorxl $11, %r8d, %ecx + leal (%r12,%rax,1), %r12d + addl 416(%rsp), %r11d + movl %r9d, %eax + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + xorl %ecx, %edx + andl %r8d, %eax + addl %edx, %r11d + rorxl $2, %r12d, %edx + rorxl $13, %r12d, %ecx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + andl %eax, %ebx + addl %edx, %r11d + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + rorxl $11, %r15d, %ecx + addl %ebx, %r11d + addl 420(%rsp), %r10d + movl %r8d, %ebx + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + xorl %ecx, %edx + andl %r15d, %ebx + addl %edx, %r10d + rorxl $2, %r11d, %edx + rorxl $13, %r11d, %ecx + xorl %r9d, %ebx + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + xorl %ecx, %edx + movl %r12d, %ebx + leal (%r14,%r10,1), %r14d + xorl %r11d, %ebx + andl %ebx, %eax + addl %edx, %r10d + xorl %r12d, %eax + rorxl $6, %r14d, %edx + rorxl $11, %r14d, %ecx + leal (%r10,%rax,1), %r10d + addl 424(%rsp), %r9d + movl %r15d, %eax + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + xorl %ecx, %edx + andl %r14d, %eax + addl %edx, %r9d + rorxl $2, %r10d, %edx + rorxl $13, %r10d, %ecx + xorl %r8d, %eax + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + xorl %r10d, %eax + andl %eax, %ebx + addl %edx, %r9d + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + rorxl $11, %r13d, %ecx + addl %ebx, %r9d + addl 428(%rsp), %r8d + movl %r14d, %ebx + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + xorl %ecx, %edx + andl %r13d, %ebx + addl %edx, %r8d + rorxl $2, %r9d, %edx + rorxl $13, %r9d, %ecx + xorl %r15d, %ebx + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + xorl %ecx, %edx + movl %r10d, %ebx + leal (%r12,%r8,1), %r12d + xorl %r9d, %ebx + andl %ebx, %eax + addl %edx, %r8d + xorl %r10d, %eax + rorxl $6, %r12d, %edx + rorxl $11, %r12d, %ecx + leal (%r8,%rax,1), %r8d + addl 448(%rsp), %r15d + movl %r13d, %eax + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + xorl %ecx, %edx + andl %r12d, %eax + addl %edx, %r15d + rorxl $2, %r8d, %edx + rorxl $13, %r8d, %ecx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + andl %eax, %ebx + addl %edx, %r15d + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + rorxl $11, %r11d, %ecx + addl %ebx, %r15d + addl 452(%rsp), %r14d + movl %r12d, %ebx + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + xorl %ecx, %edx + andl %r11d, %ebx + addl %edx, %r14d + rorxl $2, %r15d, %edx + rorxl $13, %r15d, %ecx + xorl %r13d, %ebx + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + xorl %ecx, %edx + movl %r8d, %ebx + leal (%r10,%r14,1), %r10d + xorl %r15d, %ebx + andl %ebx, %eax + addl %edx, %r14d + xorl %r8d, %eax + rorxl $6, %r10d, %edx + rorxl $11, %r10d, %ecx + leal (%r14,%rax,1), %r14d + addl 456(%rsp), %r13d + movl %r11d, %eax + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + xorl %ecx, %edx + andl %r10d, %eax + addl %edx, %r13d + rorxl $2, %r14d, %edx + rorxl $13, %r14d, %ecx + xorl %r12d, %eax + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + xorl %r14d, %eax + andl %eax, %ebx + addl %edx, %r13d + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + rorxl $11, %r9d, %ecx + addl %ebx, %r13d + addl 460(%rsp), %r12d + movl %r10d, %ebx + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + xorl %ecx, %edx + andl %r9d, %ebx + addl %edx, %r12d + rorxl $2, %r13d, %edx + rorxl $13, %r13d, %ecx + xorl %r11d, %ebx + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + xorl %ecx, %edx + movl %r14d, %ebx + leal (%r8,%r12,1), %r8d + xorl %r13d, %ebx + andl %ebx, %eax + addl %edx, %r12d + xorl %r14d, %eax + rorxl $6, %r8d, %edx + rorxl $11, %r8d, %ecx + leal (%r12,%rax,1), %r12d + addl 480(%rsp), %r11d + movl %r9d, %eax + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + xorl %ecx, %edx + andl %r8d, %eax + addl %edx, %r11d + rorxl $2, %r12d, %edx + rorxl $13, %r12d, %ecx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + andl %eax, %ebx + addl %edx, %r11d + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + rorxl $11, %r15d, %ecx + addl %ebx, %r11d + addl 484(%rsp), %r10d + movl %r8d, %ebx + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + xorl %ecx, %edx + andl %r15d, %ebx + addl %edx, %r10d + rorxl $2, %r11d, %edx + rorxl $13, %r11d, %ecx + xorl %r9d, %ebx + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + xorl %ecx, %edx + movl %r12d, %ebx + leal (%r14,%r10,1), %r14d + xorl %r11d, %ebx + andl %ebx, %eax + addl %edx, %r10d + xorl %r12d, %eax + rorxl $6, %r14d, %edx + rorxl $11, %r14d, %ecx + leal (%r10,%rax,1), %r10d + addl 488(%rsp), %r9d + movl %r15d, %eax + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + xorl %ecx, %edx + andl %r14d, %eax + addl %edx, %r9d + rorxl $2, %r10d, %edx + rorxl $13, %r10d, %ecx + xorl %r8d, %eax + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + xorl %r10d, %eax + andl %eax, %ebx + addl %edx, %r9d + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + rorxl $11, %r13d, %ecx + addl %ebx, %r9d + addl 492(%rsp), %r8d + movl %r14d, %ebx + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + xorl %ecx, %edx + andl %r13d, %ebx + addl %edx, %r8d + rorxl $2, %r9d, %edx + rorxl $13, %r9d, %ecx + xorl %r15d, %ebx + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + xorl %ecx, %edx + movl %r10d, %ebx + leal (%r12,%r8,1), %r12d + xorl %r9d, %ebx + andl %ebx, %eax + addl %edx, %r8d + xorl %r10d, %eax + addl %eax, %r8d + addl %r8d, (%rdi) + addl %r9d, 4(%rdi) + addl %r10d, 8(%rdi) + addl %r11d, 12(%rdi) + addl %r12d, 16(%rdi) + addl %r13d, 20(%rdi) + addl %r14d, 24(%rdi) + addl %r15d, 28(%rdi) + xorq %rax, %rax + vzeroupper + addq $0x200, %rsp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size Transform_Sha256_AVX2_RORX,.-Transform_Sha256_AVX2_RORX +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl Transform_Sha256_AVX2_RORX_Len +.type Transform_Sha256_AVX2_RORX_Len,@function +.align 4 +Transform_Sha256_AVX2_RORX_Len: +#else +.section __TEXT,__text +.globl _Transform_Sha256_AVX2_RORX_Len +.p2align 2 +_Transform_Sha256_AVX2_RORX_Len: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + pushq %rbp + movq %rsi, %rbp + movq %rdx, %rsi + subq $0x200, %rsp + testb $0x40, %sil + je L_sha256_len_avx2_rorx_block + vmovdqu (%rbp), %ymm0 + vmovdqu 32(%rbp), %ymm1 + vmovups %ymm0, 32(%rdi) + vmovups %ymm1, 64(%rdi) +#ifndef __APPLE__ + call Transform_Sha256_AVX2_RORX@plt +#else + call _Transform_Sha256_AVX2_RORX +#endif /* __APPLE__ */ + addq $0x40, %rbp + subl $0x40, %esi + jz L_sha256_len_avx2_rorx_done +L_sha256_len_avx2_rorx_block: + vmovdqa L_avx2_rorx_sha256_flip_mask(%rip), %ymm13 + vmovdqa L_avx2_rorx_sha256_shuf_00BA(%rip), %ymm11 + vmovdqa L_avx2_rorx_sha256_shuf_DC00(%rip), %ymm12 + movl (%rdi), %r8d + movl 4(%rdi), %r9d + movl 8(%rdi), %r10d + movl 12(%rdi), %r11d + movl 16(%rdi), %r12d + movl 20(%rdi), %r13d + movl 24(%rdi), %r14d + movl 28(%rdi), %r15d + # Start of loop processing two blocks +L_sha256_len_avx2_rorx_start: + # X0, X1, X2, X3 = W[0..15] + vmovdqu (%rbp), %xmm0 + vmovdqu 16(%rbp), %xmm1 + vinserti128 $0x01, 64(%rbp), %ymm0, %ymm0 + vinserti128 $0x01, 80(%rbp), %ymm1, %ymm1 + vpshufb %ymm13, %ymm0, %ymm0 + vpshufb %ymm13, %ymm1, %ymm1 + vpaddd 0+L_avx2_rorx_sha256_k(%rip), %ymm0, %ymm4 + vpaddd 32+L_avx2_rorx_sha256_k(%rip), %ymm1, %ymm5 + vmovdqu %ymm4, (%rsp) + vmovdqu %ymm5, 32(%rsp) + vmovdqu 32(%rbp), %xmm2 + vmovdqu 48(%rbp), %xmm3 + vinserti128 $0x01, 96(%rbp), %ymm2, %ymm2 + vinserti128 $0x01, 112(%rbp), %ymm3, %ymm3 + vpshufb %ymm13, %ymm2, %ymm2 + vpshufb %ymm13, %ymm3, %ymm3 + vpaddd 64+L_avx2_rorx_sha256_k(%rip), %ymm2, %ymm4 + vpaddd 96+L_avx2_rorx_sha256_k(%rip), %ymm3, %ymm5 + vmovdqu %ymm4, 64(%rsp) + vmovdqu %ymm5, 96(%rsp) + movl %r9d, %ebx + rorxl $6, %r12d, %edx + xorl %r10d, %ebx + # rnd_0: 0 - 0 + movl %r13d, %eax + rorxl $11, %r12d, %ecx + addl (%rsp), %r15d + vpalignr $4, %ymm0, %ymm1, %ymm5 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + vpalignr $4, %ymm2, %ymm3, %ymm4 + # rnd_0: 2 - 2 + andl %r12d, %eax + xorl %ecx, %edx + rorxl $13, %r8d, %ecx + vpsrld $7, %ymm5, %ymm6 + # rnd_0: 3 - 3 + addl %edx, %r15d + rorxl $2, %r8d, %edx + xorl %r14d, %eax + vpslld $25, %ymm5, %ymm7 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + vpsrld $18, %ymm5, %ymm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + vpslld $14, %ymm5, %ymm9 + # rnd_0: 6 - 6 + xorl %r8d, %eax + addl %edx, %r15d + andl %eax, %ebx + vpor %ymm7, %ymm6, %ymm6 + # rnd_0: 7 - 7 + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + addl %ebx, %r15d + vpor %ymm9, %ymm8, %ymm8 + # rnd_1: 0 - 0 + movl %r12d, %ebx + rorxl $11, %r11d, %ecx + addl 4(%rsp), %r14d + vpsrld $3, %ymm5, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + vpxor %ymm8, %ymm6, %ymm6 + # rnd_1: 2 - 2 + andl %r11d, %ebx + xorl %ecx, %edx + rorxl $13, %r15d, %ecx + vpshufd $0xfa, %ymm3, %ymm7 + # rnd_1: 3 - 3 + addl %edx, %r14d + rorxl $2, %r15d, %edx + xorl %r13d, %ebx + vpxor %ymm6, %ymm9, %ymm5 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + vpsrld $10, %ymm7, %ymm8 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r14d, %r10d + movl %r8d, %ebx + vpsrlq $19, %ymm7, %ymm6 + # rnd_1: 6 - 6 + xorl %r15d, %ebx + addl %edx, %r14d + andl %ebx, %eax + vpsrlq $0x11, %ymm7, %ymm7 + # rnd_1: 7 - 7 + xorl %r8d, %eax + rorxl $6, %r10d, %edx + addl %eax, %r14d + vpaddd %ymm0, %ymm4, %ymm4 + # rnd_0: 0 - 0 + movl %r11d, %eax + rorxl $11, %r10d, %ecx + addl 8(%rsp), %r13d + vpxor %ymm7, %ymm6, %ymm6 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 2 - 2 + andl %r10d, %eax + xorl %ecx, %edx + rorxl $13, %r14d, %ecx + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 3 - 3 + addl %edx, %r13d + rorxl $2, %r14d, %edx + xorl %r12d, %eax + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + vpshufd $0x50, %ymm4, %ymm6 + # rnd_0: 6 - 6 + xorl %r14d, %eax + addl %edx, %r13d + andl %eax, %ebx + vpsrlq $0x11, %ymm6, %ymm8 + # rnd_0: 7 - 7 + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + addl %ebx, %r13d + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 0 - 0 + movl %r10d, %ebx + rorxl $11, %r9d, %ecx + addl 12(%rsp), %r12d + vpsrld $10, %ymm6, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + vpxor %ymm7, %ymm8, %ymm8 + # rnd_1: 2 - 2 + andl %r9d, %ebx + xorl %ecx, %edx + rorxl $13, %r13d, %ecx + vpxor %ymm8, %ymm9, %ymm9 + # rnd_1: 3 - 3 + addl %edx, %r12d + rorxl $2, %r13d, %edx + xorl %r11d, %ebx + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + vpaddd %ymm4, %ymm9, %ymm0 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r12d, %r8d + movl %r14d, %ebx + vpaddd 128+L_avx2_rorx_sha256_k(%rip), %ymm0, %ymm4 + # rnd_1: 6 - 6 + xorl %r13d, %ebx + addl %edx, %r12d + andl %ebx, %eax + # rnd_1: 7 - 7 + xorl %r14d, %eax + rorxl $6, %r8d, %edx + addl %eax, %r12d + vmovdqu %ymm4, 128(%rsp) + # rnd_0: 0 - 0 + movl %r9d, %eax + rorxl $11, %r8d, %ecx + addl 32(%rsp), %r11d + vpalignr $4, %ymm1, %ymm2, %ymm5 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + vpalignr $4, %ymm3, %ymm0, %ymm4 + # rnd_0: 2 - 2 + andl %r8d, %eax + xorl %ecx, %edx + rorxl $13, %r12d, %ecx + vpsrld $7, %ymm5, %ymm6 + # rnd_0: 3 - 3 + addl %edx, %r11d + rorxl $2, %r12d, %edx + xorl %r10d, %eax + vpslld $25, %ymm5, %ymm7 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + vpsrld $18, %ymm5, %ymm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + vpslld $14, %ymm5, %ymm9 + # rnd_0: 6 - 6 + xorl %r12d, %eax + addl %edx, %r11d + andl %eax, %ebx + vpor %ymm7, %ymm6, %ymm6 + # rnd_0: 7 - 7 + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + addl %ebx, %r11d + vpor %ymm9, %ymm8, %ymm8 + # rnd_1: 0 - 0 + movl %r8d, %ebx + rorxl $11, %r15d, %ecx + addl 36(%rsp), %r10d + vpsrld $3, %ymm5, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + vpxor %ymm8, %ymm6, %ymm6 + # rnd_1: 2 - 2 + andl %r15d, %ebx + xorl %ecx, %edx + rorxl $13, %r11d, %ecx + vpshufd $0xfa, %ymm0, %ymm7 + # rnd_1: 3 - 3 + addl %edx, %r10d + rorxl $2, %r11d, %edx + xorl %r9d, %ebx + vpxor %ymm6, %ymm9, %ymm5 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + vpsrld $10, %ymm7, %ymm8 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r10d, %r14d + movl %r12d, %ebx + vpsrlq $19, %ymm7, %ymm6 + # rnd_1: 6 - 6 + xorl %r11d, %ebx + addl %edx, %r10d + andl %ebx, %eax + vpsrlq $0x11, %ymm7, %ymm7 + # rnd_1: 7 - 7 + xorl %r12d, %eax + rorxl $6, %r14d, %edx + addl %eax, %r10d + vpaddd %ymm1, %ymm4, %ymm4 + # rnd_0: 0 - 0 + movl %r15d, %eax + rorxl $11, %r14d, %ecx + addl 40(%rsp), %r9d + vpxor %ymm7, %ymm6, %ymm6 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 2 - 2 + andl %r14d, %eax + xorl %ecx, %edx + rorxl $13, %r10d, %ecx + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 3 - 3 + addl %edx, %r9d + rorxl $2, %r10d, %edx + xorl %r8d, %eax + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + vpshufd $0x50, %ymm4, %ymm6 + # rnd_0: 6 - 6 + xorl %r10d, %eax + addl %edx, %r9d + andl %eax, %ebx + vpsrlq $0x11, %ymm6, %ymm8 + # rnd_0: 7 - 7 + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + addl %ebx, %r9d + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 0 - 0 + movl %r14d, %ebx + rorxl $11, %r13d, %ecx + addl 44(%rsp), %r8d + vpsrld $10, %ymm6, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + vpxor %ymm7, %ymm8, %ymm8 + # rnd_1: 2 - 2 + andl %r13d, %ebx + xorl %ecx, %edx + rorxl $13, %r9d, %ecx + vpxor %ymm8, %ymm9, %ymm9 + # rnd_1: 3 - 3 + addl %edx, %r8d + rorxl $2, %r9d, %edx + xorl %r15d, %ebx + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + vpaddd %ymm4, %ymm9, %ymm1 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r8d, %r12d + movl %r10d, %ebx + vpaddd 160+L_avx2_rorx_sha256_k(%rip), %ymm1, %ymm4 + # rnd_1: 6 - 6 + xorl %r9d, %ebx + addl %edx, %r8d + andl %ebx, %eax + # rnd_1: 7 - 7 + xorl %r10d, %eax + rorxl $6, %r12d, %edx + addl %eax, %r8d + vmovdqu %ymm4, 160(%rsp) + # rnd_0: 0 - 0 + movl %r13d, %eax + rorxl $11, %r12d, %ecx + addl 64(%rsp), %r15d + vpalignr $4, %ymm2, %ymm3, %ymm5 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + vpalignr $4, %ymm0, %ymm1, %ymm4 + # rnd_0: 2 - 2 + andl %r12d, %eax + xorl %ecx, %edx + rorxl $13, %r8d, %ecx + vpsrld $7, %ymm5, %ymm6 + # rnd_0: 3 - 3 + addl %edx, %r15d + rorxl $2, %r8d, %edx + xorl %r14d, %eax + vpslld $25, %ymm5, %ymm7 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + vpsrld $18, %ymm5, %ymm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + vpslld $14, %ymm5, %ymm9 + # rnd_0: 6 - 6 + xorl %r8d, %eax + addl %edx, %r15d + andl %eax, %ebx + vpor %ymm7, %ymm6, %ymm6 + # rnd_0: 7 - 7 + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + addl %ebx, %r15d + vpor %ymm9, %ymm8, %ymm8 + # rnd_1: 0 - 0 + movl %r12d, %ebx + rorxl $11, %r11d, %ecx + addl 68(%rsp), %r14d + vpsrld $3, %ymm5, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + vpxor %ymm8, %ymm6, %ymm6 + # rnd_1: 2 - 2 + andl %r11d, %ebx + xorl %ecx, %edx + rorxl $13, %r15d, %ecx + vpshufd $0xfa, %ymm1, %ymm7 + # rnd_1: 3 - 3 + addl %edx, %r14d + rorxl $2, %r15d, %edx + xorl %r13d, %ebx + vpxor %ymm6, %ymm9, %ymm5 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + vpsrld $10, %ymm7, %ymm8 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r14d, %r10d + movl %r8d, %ebx + vpsrlq $19, %ymm7, %ymm6 + # rnd_1: 6 - 6 + xorl %r15d, %ebx + addl %edx, %r14d + andl %ebx, %eax + vpsrlq $0x11, %ymm7, %ymm7 + # rnd_1: 7 - 7 + xorl %r8d, %eax + rorxl $6, %r10d, %edx + addl %eax, %r14d + vpaddd %ymm2, %ymm4, %ymm4 + # rnd_0: 0 - 0 + movl %r11d, %eax + rorxl $11, %r10d, %ecx + addl 72(%rsp), %r13d + vpxor %ymm7, %ymm6, %ymm6 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 2 - 2 + andl %r10d, %eax + xorl %ecx, %edx + rorxl $13, %r14d, %ecx + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 3 - 3 + addl %edx, %r13d + rorxl $2, %r14d, %edx + xorl %r12d, %eax + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + vpshufd $0x50, %ymm4, %ymm6 + # rnd_0: 6 - 6 + xorl %r14d, %eax + addl %edx, %r13d + andl %eax, %ebx + vpsrlq $0x11, %ymm6, %ymm8 + # rnd_0: 7 - 7 + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + addl %ebx, %r13d + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 0 - 0 + movl %r10d, %ebx + rorxl $11, %r9d, %ecx + addl 76(%rsp), %r12d + vpsrld $10, %ymm6, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + vpxor %ymm7, %ymm8, %ymm8 + # rnd_1: 2 - 2 + andl %r9d, %ebx + xorl %ecx, %edx + rorxl $13, %r13d, %ecx + vpxor %ymm8, %ymm9, %ymm9 + # rnd_1: 3 - 3 + addl %edx, %r12d + rorxl $2, %r13d, %edx + xorl %r11d, %ebx + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + vpaddd %ymm4, %ymm9, %ymm2 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r12d, %r8d + movl %r14d, %ebx + vpaddd 192+L_avx2_rorx_sha256_k(%rip), %ymm2, %ymm4 + # rnd_1: 6 - 6 + xorl %r13d, %ebx + addl %edx, %r12d + andl %ebx, %eax + # rnd_1: 7 - 7 + xorl %r14d, %eax + rorxl $6, %r8d, %edx + addl %eax, %r12d + vmovdqu %ymm4, 192(%rsp) + # rnd_0: 0 - 0 + movl %r9d, %eax + rorxl $11, %r8d, %ecx + addl 96(%rsp), %r11d + vpalignr $4, %ymm3, %ymm0, %ymm5 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + vpalignr $4, %ymm1, %ymm2, %ymm4 + # rnd_0: 2 - 2 + andl %r8d, %eax + xorl %ecx, %edx + rorxl $13, %r12d, %ecx + vpsrld $7, %ymm5, %ymm6 + # rnd_0: 3 - 3 + addl %edx, %r11d + rorxl $2, %r12d, %edx + xorl %r10d, %eax + vpslld $25, %ymm5, %ymm7 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + vpsrld $18, %ymm5, %ymm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + vpslld $14, %ymm5, %ymm9 + # rnd_0: 6 - 6 + xorl %r12d, %eax + addl %edx, %r11d + andl %eax, %ebx + vpor %ymm7, %ymm6, %ymm6 + # rnd_0: 7 - 7 + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + addl %ebx, %r11d + vpor %ymm9, %ymm8, %ymm8 + # rnd_1: 0 - 0 + movl %r8d, %ebx + rorxl $11, %r15d, %ecx + addl 100(%rsp), %r10d + vpsrld $3, %ymm5, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + vpxor %ymm8, %ymm6, %ymm6 + # rnd_1: 2 - 2 + andl %r15d, %ebx + xorl %ecx, %edx + rorxl $13, %r11d, %ecx + vpshufd $0xfa, %ymm2, %ymm7 + # rnd_1: 3 - 3 + addl %edx, %r10d + rorxl $2, %r11d, %edx + xorl %r9d, %ebx + vpxor %ymm6, %ymm9, %ymm5 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + vpsrld $10, %ymm7, %ymm8 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r10d, %r14d + movl %r12d, %ebx + vpsrlq $19, %ymm7, %ymm6 + # rnd_1: 6 - 6 + xorl %r11d, %ebx + addl %edx, %r10d + andl %ebx, %eax + vpsrlq $0x11, %ymm7, %ymm7 + # rnd_1: 7 - 7 + xorl %r12d, %eax + rorxl $6, %r14d, %edx + addl %eax, %r10d + vpaddd %ymm3, %ymm4, %ymm4 + # rnd_0: 0 - 0 + movl %r15d, %eax + rorxl $11, %r14d, %ecx + addl 104(%rsp), %r9d + vpxor %ymm7, %ymm6, %ymm6 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 2 - 2 + andl %r14d, %eax + xorl %ecx, %edx + rorxl $13, %r10d, %ecx + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 3 - 3 + addl %edx, %r9d + rorxl $2, %r10d, %edx + xorl %r8d, %eax + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + vpshufd $0x50, %ymm4, %ymm6 + # rnd_0: 6 - 6 + xorl %r10d, %eax + addl %edx, %r9d + andl %eax, %ebx + vpsrlq $0x11, %ymm6, %ymm8 + # rnd_0: 7 - 7 + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + addl %ebx, %r9d + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 0 - 0 + movl %r14d, %ebx + rorxl $11, %r13d, %ecx + addl 108(%rsp), %r8d + vpsrld $10, %ymm6, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + vpxor %ymm7, %ymm8, %ymm8 + # rnd_1: 2 - 2 + andl %r13d, %ebx + xorl %ecx, %edx + rorxl $13, %r9d, %ecx + vpxor %ymm8, %ymm9, %ymm9 + # rnd_1: 3 - 3 + addl %edx, %r8d + rorxl $2, %r9d, %edx + xorl %r15d, %ebx + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + vpaddd %ymm4, %ymm9, %ymm3 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r8d, %r12d + movl %r10d, %ebx + vpaddd 224+L_avx2_rorx_sha256_k(%rip), %ymm3, %ymm4 + # rnd_1: 6 - 6 + xorl %r9d, %ebx + addl %edx, %r8d + andl %ebx, %eax + # rnd_1: 7 - 7 + xorl %r10d, %eax + rorxl $6, %r12d, %edx + addl %eax, %r8d + vmovdqu %ymm4, 224(%rsp) + # rnd_0: 0 - 0 + movl %r13d, %eax + rorxl $11, %r12d, %ecx + addl 128(%rsp), %r15d + vpalignr $4, %ymm0, %ymm1, %ymm5 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + vpalignr $4, %ymm2, %ymm3, %ymm4 + # rnd_0: 2 - 2 + andl %r12d, %eax + xorl %ecx, %edx + rorxl $13, %r8d, %ecx + vpsrld $7, %ymm5, %ymm6 + # rnd_0: 3 - 3 + addl %edx, %r15d + rorxl $2, %r8d, %edx + xorl %r14d, %eax + vpslld $25, %ymm5, %ymm7 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + vpsrld $18, %ymm5, %ymm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + vpslld $14, %ymm5, %ymm9 + # rnd_0: 6 - 6 + xorl %r8d, %eax + addl %edx, %r15d + andl %eax, %ebx + vpor %ymm7, %ymm6, %ymm6 + # rnd_0: 7 - 7 + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + addl %ebx, %r15d + vpor %ymm9, %ymm8, %ymm8 + # rnd_1: 0 - 0 + movl %r12d, %ebx + rorxl $11, %r11d, %ecx + addl 132(%rsp), %r14d + vpsrld $3, %ymm5, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + vpxor %ymm8, %ymm6, %ymm6 + # rnd_1: 2 - 2 + andl %r11d, %ebx + xorl %ecx, %edx + rorxl $13, %r15d, %ecx + vpshufd $0xfa, %ymm3, %ymm7 + # rnd_1: 3 - 3 + addl %edx, %r14d + rorxl $2, %r15d, %edx + xorl %r13d, %ebx + vpxor %ymm6, %ymm9, %ymm5 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + vpsrld $10, %ymm7, %ymm8 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r14d, %r10d + movl %r8d, %ebx + vpsrlq $19, %ymm7, %ymm6 + # rnd_1: 6 - 6 + xorl %r15d, %ebx + addl %edx, %r14d + andl %ebx, %eax + vpsrlq $0x11, %ymm7, %ymm7 + # rnd_1: 7 - 7 + xorl %r8d, %eax + rorxl $6, %r10d, %edx + addl %eax, %r14d + vpaddd %ymm0, %ymm4, %ymm4 + # rnd_0: 0 - 0 + movl %r11d, %eax + rorxl $11, %r10d, %ecx + addl 136(%rsp), %r13d + vpxor %ymm7, %ymm6, %ymm6 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 2 - 2 + andl %r10d, %eax + xorl %ecx, %edx + rorxl $13, %r14d, %ecx + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 3 - 3 + addl %edx, %r13d + rorxl $2, %r14d, %edx + xorl %r12d, %eax + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + vpshufd $0x50, %ymm4, %ymm6 + # rnd_0: 6 - 6 + xorl %r14d, %eax + addl %edx, %r13d + andl %eax, %ebx + vpsrlq $0x11, %ymm6, %ymm8 + # rnd_0: 7 - 7 + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + addl %ebx, %r13d + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 0 - 0 + movl %r10d, %ebx + rorxl $11, %r9d, %ecx + addl 140(%rsp), %r12d + vpsrld $10, %ymm6, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + vpxor %ymm7, %ymm8, %ymm8 + # rnd_1: 2 - 2 + andl %r9d, %ebx + xorl %ecx, %edx + rorxl $13, %r13d, %ecx + vpxor %ymm8, %ymm9, %ymm9 + # rnd_1: 3 - 3 + addl %edx, %r12d + rorxl $2, %r13d, %edx + xorl %r11d, %ebx + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + vpaddd %ymm4, %ymm9, %ymm0 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r12d, %r8d + movl %r14d, %ebx + vpaddd 256+L_avx2_rorx_sha256_k(%rip), %ymm0, %ymm4 + # rnd_1: 6 - 6 + xorl %r13d, %ebx + addl %edx, %r12d + andl %ebx, %eax + # rnd_1: 7 - 7 + xorl %r14d, %eax + rorxl $6, %r8d, %edx + addl %eax, %r12d + vmovdqu %ymm4, 256(%rsp) + # rnd_0: 0 - 0 + movl %r9d, %eax + rorxl $11, %r8d, %ecx + addl 160(%rsp), %r11d + vpalignr $4, %ymm1, %ymm2, %ymm5 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + vpalignr $4, %ymm3, %ymm0, %ymm4 + # rnd_0: 2 - 2 + andl %r8d, %eax + xorl %ecx, %edx + rorxl $13, %r12d, %ecx + vpsrld $7, %ymm5, %ymm6 + # rnd_0: 3 - 3 + addl %edx, %r11d + rorxl $2, %r12d, %edx + xorl %r10d, %eax + vpslld $25, %ymm5, %ymm7 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + vpsrld $18, %ymm5, %ymm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + vpslld $14, %ymm5, %ymm9 + # rnd_0: 6 - 6 + xorl %r12d, %eax + addl %edx, %r11d + andl %eax, %ebx + vpor %ymm7, %ymm6, %ymm6 + # rnd_0: 7 - 7 + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + addl %ebx, %r11d + vpor %ymm9, %ymm8, %ymm8 + # rnd_1: 0 - 0 + movl %r8d, %ebx + rorxl $11, %r15d, %ecx + addl 164(%rsp), %r10d + vpsrld $3, %ymm5, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + vpxor %ymm8, %ymm6, %ymm6 + # rnd_1: 2 - 2 + andl %r15d, %ebx + xorl %ecx, %edx + rorxl $13, %r11d, %ecx + vpshufd $0xfa, %ymm0, %ymm7 + # rnd_1: 3 - 3 + addl %edx, %r10d + rorxl $2, %r11d, %edx + xorl %r9d, %ebx + vpxor %ymm6, %ymm9, %ymm5 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + vpsrld $10, %ymm7, %ymm8 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r10d, %r14d + movl %r12d, %ebx + vpsrlq $19, %ymm7, %ymm6 + # rnd_1: 6 - 6 + xorl %r11d, %ebx + addl %edx, %r10d + andl %ebx, %eax + vpsrlq $0x11, %ymm7, %ymm7 + # rnd_1: 7 - 7 + xorl %r12d, %eax + rorxl $6, %r14d, %edx + addl %eax, %r10d + vpaddd %ymm1, %ymm4, %ymm4 + # rnd_0: 0 - 0 + movl %r15d, %eax + rorxl $11, %r14d, %ecx + addl 168(%rsp), %r9d + vpxor %ymm7, %ymm6, %ymm6 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 2 - 2 + andl %r14d, %eax + xorl %ecx, %edx + rorxl $13, %r10d, %ecx + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 3 - 3 + addl %edx, %r9d + rorxl $2, %r10d, %edx + xorl %r8d, %eax + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + vpshufd $0x50, %ymm4, %ymm6 + # rnd_0: 6 - 6 + xorl %r10d, %eax + addl %edx, %r9d + andl %eax, %ebx + vpsrlq $0x11, %ymm6, %ymm8 + # rnd_0: 7 - 7 + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + addl %ebx, %r9d + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 0 - 0 + movl %r14d, %ebx + rorxl $11, %r13d, %ecx + addl 172(%rsp), %r8d + vpsrld $10, %ymm6, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + vpxor %ymm7, %ymm8, %ymm8 + # rnd_1: 2 - 2 + andl %r13d, %ebx + xorl %ecx, %edx + rorxl $13, %r9d, %ecx + vpxor %ymm8, %ymm9, %ymm9 + # rnd_1: 3 - 3 + addl %edx, %r8d + rorxl $2, %r9d, %edx + xorl %r15d, %ebx + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + vpaddd %ymm4, %ymm9, %ymm1 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r8d, %r12d + movl %r10d, %ebx + vpaddd 288+L_avx2_rorx_sha256_k(%rip), %ymm1, %ymm4 + # rnd_1: 6 - 6 + xorl %r9d, %ebx + addl %edx, %r8d + andl %ebx, %eax + # rnd_1: 7 - 7 + xorl %r10d, %eax + rorxl $6, %r12d, %edx + addl %eax, %r8d + vmovdqu %ymm4, 288(%rsp) + # rnd_0: 0 - 0 + movl %r13d, %eax + rorxl $11, %r12d, %ecx + addl 192(%rsp), %r15d + vpalignr $4, %ymm2, %ymm3, %ymm5 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + vpalignr $4, %ymm0, %ymm1, %ymm4 + # rnd_0: 2 - 2 + andl %r12d, %eax + xorl %ecx, %edx + rorxl $13, %r8d, %ecx + vpsrld $7, %ymm5, %ymm6 + # rnd_0: 3 - 3 + addl %edx, %r15d + rorxl $2, %r8d, %edx + xorl %r14d, %eax + vpslld $25, %ymm5, %ymm7 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + vpsrld $18, %ymm5, %ymm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + vpslld $14, %ymm5, %ymm9 + # rnd_0: 6 - 6 + xorl %r8d, %eax + addl %edx, %r15d + andl %eax, %ebx + vpor %ymm7, %ymm6, %ymm6 + # rnd_0: 7 - 7 + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + addl %ebx, %r15d + vpor %ymm9, %ymm8, %ymm8 + # rnd_1: 0 - 0 + movl %r12d, %ebx + rorxl $11, %r11d, %ecx + addl 196(%rsp), %r14d + vpsrld $3, %ymm5, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + vpxor %ymm8, %ymm6, %ymm6 + # rnd_1: 2 - 2 + andl %r11d, %ebx + xorl %ecx, %edx + rorxl $13, %r15d, %ecx + vpshufd $0xfa, %ymm1, %ymm7 + # rnd_1: 3 - 3 + addl %edx, %r14d + rorxl $2, %r15d, %edx + xorl %r13d, %ebx + vpxor %ymm6, %ymm9, %ymm5 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + vpsrld $10, %ymm7, %ymm8 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r14d, %r10d + movl %r8d, %ebx + vpsrlq $19, %ymm7, %ymm6 + # rnd_1: 6 - 6 + xorl %r15d, %ebx + addl %edx, %r14d + andl %ebx, %eax + vpsrlq $0x11, %ymm7, %ymm7 + # rnd_1: 7 - 7 + xorl %r8d, %eax + rorxl $6, %r10d, %edx + addl %eax, %r14d + vpaddd %ymm2, %ymm4, %ymm4 + # rnd_0: 0 - 0 + movl %r11d, %eax + rorxl $11, %r10d, %ecx + addl 200(%rsp), %r13d + vpxor %ymm7, %ymm6, %ymm6 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 2 - 2 + andl %r10d, %eax + xorl %ecx, %edx + rorxl $13, %r14d, %ecx + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 3 - 3 + addl %edx, %r13d + rorxl $2, %r14d, %edx + xorl %r12d, %eax + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + vpshufd $0x50, %ymm4, %ymm6 + # rnd_0: 6 - 6 + xorl %r14d, %eax + addl %edx, %r13d + andl %eax, %ebx + vpsrlq $0x11, %ymm6, %ymm8 + # rnd_0: 7 - 7 + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + addl %ebx, %r13d + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 0 - 0 + movl %r10d, %ebx + rorxl $11, %r9d, %ecx + addl 204(%rsp), %r12d + vpsrld $10, %ymm6, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + vpxor %ymm7, %ymm8, %ymm8 + # rnd_1: 2 - 2 + andl %r9d, %ebx + xorl %ecx, %edx + rorxl $13, %r13d, %ecx + vpxor %ymm8, %ymm9, %ymm9 + # rnd_1: 3 - 3 + addl %edx, %r12d + rorxl $2, %r13d, %edx + xorl %r11d, %ebx + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + vpaddd %ymm4, %ymm9, %ymm2 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r12d, %r8d + movl %r14d, %ebx + vpaddd 320+L_avx2_rorx_sha256_k(%rip), %ymm2, %ymm4 + # rnd_1: 6 - 6 + xorl %r13d, %ebx + addl %edx, %r12d + andl %ebx, %eax + # rnd_1: 7 - 7 + xorl %r14d, %eax + rorxl $6, %r8d, %edx + addl %eax, %r12d + vmovdqu %ymm4, 320(%rsp) + # rnd_0: 0 - 0 + movl %r9d, %eax + rorxl $11, %r8d, %ecx + addl 224(%rsp), %r11d + vpalignr $4, %ymm3, %ymm0, %ymm5 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + vpalignr $4, %ymm1, %ymm2, %ymm4 + # rnd_0: 2 - 2 + andl %r8d, %eax + xorl %ecx, %edx + rorxl $13, %r12d, %ecx + vpsrld $7, %ymm5, %ymm6 + # rnd_0: 3 - 3 + addl %edx, %r11d + rorxl $2, %r12d, %edx + xorl %r10d, %eax + vpslld $25, %ymm5, %ymm7 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + vpsrld $18, %ymm5, %ymm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + vpslld $14, %ymm5, %ymm9 + # rnd_0: 6 - 6 + xorl %r12d, %eax + addl %edx, %r11d + andl %eax, %ebx + vpor %ymm7, %ymm6, %ymm6 + # rnd_0: 7 - 7 + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + addl %ebx, %r11d + vpor %ymm9, %ymm8, %ymm8 + # rnd_1: 0 - 0 + movl %r8d, %ebx + rorxl $11, %r15d, %ecx + addl 228(%rsp), %r10d + vpsrld $3, %ymm5, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + vpxor %ymm8, %ymm6, %ymm6 + # rnd_1: 2 - 2 + andl %r15d, %ebx + xorl %ecx, %edx + rorxl $13, %r11d, %ecx + vpshufd $0xfa, %ymm2, %ymm7 + # rnd_1: 3 - 3 + addl %edx, %r10d + rorxl $2, %r11d, %edx + xorl %r9d, %ebx + vpxor %ymm6, %ymm9, %ymm5 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + vpsrld $10, %ymm7, %ymm8 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r10d, %r14d + movl %r12d, %ebx + vpsrlq $19, %ymm7, %ymm6 + # rnd_1: 6 - 6 + xorl %r11d, %ebx + addl %edx, %r10d + andl %ebx, %eax + vpsrlq $0x11, %ymm7, %ymm7 + # rnd_1: 7 - 7 + xorl %r12d, %eax + rorxl $6, %r14d, %edx + addl %eax, %r10d + vpaddd %ymm3, %ymm4, %ymm4 + # rnd_0: 0 - 0 + movl %r15d, %eax + rorxl $11, %r14d, %ecx + addl 232(%rsp), %r9d + vpxor %ymm7, %ymm6, %ymm6 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 2 - 2 + andl %r14d, %eax + xorl %ecx, %edx + rorxl $13, %r10d, %ecx + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 3 - 3 + addl %edx, %r9d + rorxl $2, %r10d, %edx + xorl %r8d, %eax + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + vpshufd $0x50, %ymm4, %ymm6 + # rnd_0: 6 - 6 + xorl %r10d, %eax + addl %edx, %r9d + andl %eax, %ebx + vpsrlq $0x11, %ymm6, %ymm8 + # rnd_0: 7 - 7 + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + addl %ebx, %r9d + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 0 - 0 + movl %r14d, %ebx + rorxl $11, %r13d, %ecx + addl 236(%rsp), %r8d + vpsrld $10, %ymm6, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + vpxor %ymm7, %ymm8, %ymm8 + # rnd_1: 2 - 2 + andl %r13d, %ebx + xorl %ecx, %edx + rorxl $13, %r9d, %ecx + vpxor %ymm8, %ymm9, %ymm9 + # rnd_1: 3 - 3 + addl %edx, %r8d + rorxl $2, %r9d, %edx + xorl %r15d, %ebx + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + vpaddd %ymm4, %ymm9, %ymm3 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r8d, %r12d + movl %r10d, %ebx + vpaddd 352+L_avx2_rorx_sha256_k(%rip), %ymm3, %ymm4 + # rnd_1: 6 - 6 + xorl %r9d, %ebx + addl %edx, %r8d + andl %ebx, %eax + # rnd_1: 7 - 7 + xorl %r10d, %eax + rorxl $6, %r12d, %edx + addl %eax, %r8d + vmovdqu %ymm4, 352(%rsp) + # rnd_0: 0 - 0 + movl %r13d, %eax + rorxl $11, %r12d, %ecx + addl 256(%rsp), %r15d + vpalignr $4, %ymm0, %ymm1, %ymm5 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + vpalignr $4, %ymm2, %ymm3, %ymm4 + # rnd_0: 2 - 2 + andl %r12d, %eax + xorl %ecx, %edx + rorxl $13, %r8d, %ecx + vpsrld $7, %ymm5, %ymm6 + # rnd_0: 3 - 3 + addl %edx, %r15d + rorxl $2, %r8d, %edx + xorl %r14d, %eax + vpslld $25, %ymm5, %ymm7 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + vpsrld $18, %ymm5, %ymm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + vpslld $14, %ymm5, %ymm9 + # rnd_0: 6 - 6 + xorl %r8d, %eax + addl %edx, %r15d + andl %eax, %ebx + vpor %ymm7, %ymm6, %ymm6 + # rnd_0: 7 - 7 + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + addl %ebx, %r15d + vpor %ymm9, %ymm8, %ymm8 + # rnd_1: 0 - 0 + movl %r12d, %ebx + rorxl $11, %r11d, %ecx + addl 260(%rsp), %r14d + vpsrld $3, %ymm5, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + vpxor %ymm8, %ymm6, %ymm6 + # rnd_1: 2 - 2 + andl %r11d, %ebx + xorl %ecx, %edx + rorxl $13, %r15d, %ecx + vpshufd $0xfa, %ymm3, %ymm7 + # rnd_1: 3 - 3 + addl %edx, %r14d + rorxl $2, %r15d, %edx + xorl %r13d, %ebx + vpxor %ymm6, %ymm9, %ymm5 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + vpsrld $10, %ymm7, %ymm8 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r14d, %r10d + movl %r8d, %ebx + vpsrlq $19, %ymm7, %ymm6 + # rnd_1: 6 - 6 + xorl %r15d, %ebx + addl %edx, %r14d + andl %ebx, %eax + vpsrlq $0x11, %ymm7, %ymm7 + # rnd_1: 7 - 7 + xorl %r8d, %eax + rorxl $6, %r10d, %edx + addl %eax, %r14d + vpaddd %ymm0, %ymm4, %ymm4 + # rnd_0: 0 - 0 + movl %r11d, %eax + rorxl $11, %r10d, %ecx + addl 264(%rsp), %r13d + vpxor %ymm7, %ymm6, %ymm6 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 2 - 2 + andl %r10d, %eax + xorl %ecx, %edx + rorxl $13, %r14d, %ecx + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 3 - 3 + addl %edx, %r13d + rorxl $2, %r14d, %edx + xorl %r12d, %eax + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + vpshufd $0x50, %ymm4, %ymm6 + # rnd_0: 6 - 6 + xorl %r14d, %eax + addl %edx, %r13d + andl %eax, %ebx + vpsrlq $0x11, %ymm6, %ymm8 + # rnd_0: 7 - 7 + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + addl %ebx, %r13d + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 0 - 0 + movl %r10d, %ebx + rorxl $11, %r9d, %ecx + addl 268(%rsp), %r12d + vpsrld $10, %ymm6, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + vpxor %ymm7, %ymm8, %ymm8 + # rnd_1: 2 - 2 + andl %r9d, %ebx + xorl %ecx, %edx + rorxl $13, %r13d, %ecx + vpxor %ymm8, %ymm9, %ymm9 + # rnd_1: 3 - 3 + addl %edx, %r12d + rorxl $2, %r13d, %edx + xorl %r11d, %ebx + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + vpaddd %ymm4, %ymm9, %ymm0 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r12d, %r8d + movl %r14d, %ebx + vpaddd 384+L_avx2_rorx_sha256_k(%rip), %ymm0, %ymm4 + # rnd_1: 6 - 6 + xorl %r13d, %ebx + addl %edx, %r12d + andl %ebx, %eax + # rnd_1: 7 - 7 + xorl %r14d, %eax + rorxl $6, %r8d, %edx + addl %eax, %r12d + vmovdqu %ymm4, 384(%rsp) + # rnd_0: 0 - 0 + movl %r9d, %eax + rorxl $11, %r8d, %ecx + addl 288(%rsp), %r11d + vpalignr $4, %ymm1, %ymm2, %ymm5 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + vpalignr $4, %ymm3, %ymm0, %ymm4 + # rnd_0: 2 - 2 + andl %r8d, %eax + xorl %ecx, %edx + rorxl $13, %r12d, %ecx + vpsrld $7, %ymm5, %ymm6 + # rnd_0: 3 - 3 + addl %edx, %r11d + rorxl $2, %r12d, %edx + xorl %r10d, %eax + vpslld $25, %ymm5, %ymm7 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + vpsrld $18, %ymm5, %ymm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + vpslld $14, %ymm5, %ymm9 + # rnd_0: 6 - 6 + xorl %r12d, %eax + addl %edx, %r11d + andl %eax, %ebx + vpor %ymm7, %ymm6, %ymm6 + # rnd_0: 7 - 7 + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + addl %ebx, %r11d + vpor %ymm9, %ymm8, %ymm8 + # rnd_1: 0 - 0 + movl %r8d, %ebx + rorxl $11, %r15d, %ecx + addl 292(%rsp), %r10d + vpsrld $3, %ymm5, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + vpxor %ymm8, %ymm6, %ymm6 + # rnd_1: 2 - 2 + andl %r15d, %ebx + xorl %ecx, %edx + rorxl $13, %r11d, %ecx + vpshufd $0xfa, %ymm0, %ymm7 + # rnd_1: 3 - 3 + addl %edx, %r10d + rorxl $2, %r11d, %edx + xorl %r9d, %ebx + vpxor %ymm6, %ymm9, %ymm5 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + vpsrld $10, %ymm7, %ymm8 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r10d, %r14d + movl %r12d, %ebx + vpsrlq $19, %ymm7, %ymm6 + # rnd_1: 6 - 6 + xorl %r11d, %ebx + addl %edx, %r10d + andl %ebx, %eax + vpsrlq $0x11, %ymm7, %ymm7 + # rnd_1: 7 - 7 + xorl %r12d, %eax + rorxl $6, %r14d, %edx + addl %eax, %r10d + vpaddd %ymm1, %ymm4, %ymm4 + # rnd_0: 0 - 0 + movl %r15d, %eax + rorxl $11, %r14d, %ecx + addl 296(%rsp), %r9d + vpxor %ymm7, %ymm6, %ymm6 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 2 - 2 + andl %r14d, %eax + xorl %ecx, %edx + rorxl $13, %r10d, %ecx + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 3 - 3 + addl %edx, %r9d + rorxl $2, %r10d, %edx + xorl %r8d, %eax + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + vpshufd $0x50, %ymm4, %ymm6 + # rnd_0: 6 - 6 + xorl %r10d, %eax + addl %edx, %r9d + andl %eax, %ebx + vpsrlq $0x11, %ymm6, %ymm8 + # rnd_0: 7 - 7 + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + addl %ebx, %r9d + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 0 - 0 + movl %r14d, %ebx + rorxl $11, %r13d, %ecx + addl 300(%rsp), %r8d + vpsrld $10, %ymm6, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + vpxor %ymm7, %ymm8, %ymm8 + # rnd_1: 2 - 2 + andl %r13d, %ebx + xorl %ecx, %edx + rorxl $13, %r9d, %ecx + vpxor %ymm8, %ymm9, %ymm9 + # rnd_1: 3 - 3 + addl %edx, %r8d + rorxl $2, %r9d, %edx + xorl %r15d, %ebx + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + vpaddd %ymm4, %ymm9, %ymm1 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r8d, %r12d + movl %r10d, %ebx + vpaddd 416+L_avx2_rorx_sha256_k(%rip), %ymm1, %ymm4 + # rnd_1: 6 - 6 + xorl %r9d, %ebx + addl %edx, %r8d + andl %ebx, %eax + # rnd_1: 7 - 7 + xorl %r10d, %eax + rorxl $6, %r12d, %edx + addl %eax, %r8d + vmovdqu %ymm4, 416(%rsp) + # rnd_0: 0 - 0 + movl %r13d, %eax + rorxl $11, %r12d, %ecx + addl 320(%rsp), %r15d + vpalignr $4, %ymm2, %ymm3, %ymm5 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + vpalignr $4, %ymm0, %ymm1, %ymm4 + # rnd_0: 2 - 2 + andl %r12d, %eax + xorl %ecx, %edx + rorxl $13, %r8d, %ecx + vpsrld $7, %ymm5, %ymm6 + # rnd_0: 3 - 3 + addl %edx, %r15d + rorxl $2, %r8d, %edx + xorl %r14d, %eax + vpslld $25, %ymm5, %ymm7 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + vpsrld $18, %ymm5, %ymm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + vpslld $14, %ymm5, %ymm9 + # rnd_0: 6 - 6 + xorl %r8d, %eax + addl %edx, %r15d + andl %eax, %ebx + vpor %ymm7, %ymm6, %ymm6 + # rnd_0: 7 - 7 + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + addl %ebx, %r15d + vpor %ymm9, %ymm8, %ymm8 + # rnd_1: 0 - 0 + movl %r12d, %ebx + rorxl $11, %r11d, %ecx + addl 324(%rsp), %r14d + vpsrld $3, %ymm5, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + vpxor %ymm8, %ymm6, %ymm6 + # rnd_1: 2 - 2 + andl %r11d, %ebx + xorl %ecx, %edx + rorxl $13, %r15d, %ecx + vpshufd $0xfa, %ymm1, %ymm7 + # rnd_1: 3 - 3 + addl %edx, %r14d + rorxl $2, %r15d, %edx + xorl %r13d, %ebx + vpxor %ymm6, %ymm9, %ymm5 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + vpsrld $10, %ymm7, %ymm8 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r14d, %r10d + movl %r8d, %ebx + vpsrlq $19, %ymm7, %ymm6 + # rnd_1: 6 - 6 + xorl %r15d, %ebx + addl %edx, %r14d + andl %ebx, %eax + vpsrlq $0x11, %ymm7, %ymm7 + # rnd_1: 7 - 7 + xorl %r8d, %eax + rorxl $6, %r10d, %edx + addl %eax, %r14d + vpaddd %ymm2, %ymm4, %ymm4 + # rnd_0: 0 - 0 + movl %r11d, %eax + rorxl $11, %r10d, %ecx + addl 328(%rsp), %r13d + vpxor %ymm7, %ymm6, %ymm6 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 2 - 2 + andl %r10d, %eax + xorl %ecx, %edx + rorxl $13, %r14d, %ecx + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 3 - 3 + addl %edx, %r13d + rorxl $2, %r14d, %edx + xorl %r12d, %eax + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + vpshufd $0x50, %ymm4, %ymm6 + # rnd_0: 6 - 6 + xorl %r14d, %eax + addl %edx, %r13d + andl %eax, %ebx + vpsrlq $0x11, %ymm6, %ymm8 + # rnd_0: 7 - 7 + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + addl %ebx, %r13d + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 0 - 0 + movl %r10d, %ebx + rorxl $11, %r9d, %ecx + addl 332(%rsp), %r12d + vpsrld $10, %ymm6, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + vpxor %ymm7, %ymm8, %ymm8 + # rnd_1: 2 - 2 + andl %r9d, %ebx + xorl %ecx, %edx + rorxl $13, %r13d, %ecx + vpxor %ymm8, %ymm9, %ymm9 + # rnd_1: 3 - 3 + addl %edx, %r12d + rorxl $2, %r13d, %edx + xorl %r11d, %ebx + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + vpaddd %ymm4, %ymm9, %ymm2 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r12d, %r8d + movl %r14d, %ebx + vpaddd 448+L_avx2_rorx_sha256_k(%rip), %ymm2, %ymm4 + # rnd_1: 6 - 6 + xorl %r13d, %ebx + addl %edx, %r12d + andl %ebx, %eax + # rnd_1: 7 - 7 + xorl %r14d, %eax + rorxl $6, %r8d, %edx + addl %eax, %r12d + vmovdqu %ymm4, 448(%rsp) + # rnd_0: 0 - 0 + movl %r9d, %eax + rorxl $11, %r8d, %ecx + addl 352(%rsp), %r11d + vpalignr $4, %ymm3, %ymm0, %ymm5 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + vpalignr $4, %ymm1, %ymm2, %ymm4 + # rnd_0: 2 - 2 + andl %r8d, %eax + xorl %ecx, %edx + rorxl $13, %r12d, %ecx + vpsrld $7, %ymm5, %ymm6 + # rnd_0: 3 - 3 + addl %edx, %r11d + rorxl $2, %r12d, %edx + xorl %r10d, %eax + vpslld $25, %ymm5, %ymm7 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + vpsrld $18, %ymm5, %ymm8 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + vpslld $14, %ymm5, %ymm9 + # rnd_0: 6 - 6 + xorl %r12d, %eax + addl %edx, %r11d + andl %eax, %ebx + vpor %ymm7, %ymm6, %ymm6 + # rnd_0: 7 - 7 + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + addl %ebx, %r11d + vpor %ymm9, %ymm8, %ymm8 + # rnd_1: 0 - 0 + movl %r8d, %ebx + rorxl $11, %r15d, %ecx + addl 356(%rsp), %r10d + vpsrld $3, %ymm5, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + vpxor %ymm8, %ymm6, %ymm6 + # rnd_1: 2 - 2 + andl %r15d, %ebx + xorl %ecx, %edx + rorxl $13, %r11d, %ecx + vpshufd $0xfa, %ymm2, %ymm7 + # rnd_1: 3 - 3 + addl %edx, %r10d + rorxl $2, %r11d, %edx + xorl %r9d, %ebx + vpxor %ymm6, %ymm9, %ymm5 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + vpsrld $10, %ymm7, %ymm8 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r10d, %r14d + movl %r12d, %ebx + vpsrlq $19, %ymm7, %ymm6 + # rnd_1: 6 - 6 + xorl %r11d, %ebx + addl %edx, %r10d + andl %ebx, %eax + vpsrlq $0x11, %ymm7, %ymm7 + # rnd_1: 7 - 7 + xorl %r12d, %eax + rorxl $6, %r14d, %edx + addl %eax, %r10d + vpaddd %ymm3, %ymm4, %ymm4 + # rnd_0: 0 - 0 + movl %r15d, %eax + rorxl $11, %r14d, %ecx + addl 360(%rsp), %r9d + vpxor %ymm7, %ymm6, %ymm6 + # rnd_0: 1 - 1 + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + vpxor %ymm6, %ymm8, %ymm8 + # rnd_0: 2 - 2 + andl %r14d, %eax + xorl %ecx, %edx + rorxl $13, %r10d, %ecx + vpaddd %ymm5, %ymm4, %ymm4 + # rnd_0: 3 - 3 + addl %edx, %r9d + rorxl $2, %r10d, %edx + xorl %r8d, %eax + vpshufb %ymm11, %ymm8, %ymm8 + # rnd_0: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + vpaddd %ymm8, %ymm4, %ymm4 + # rnd_0: 5 - 5 + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + vpshufd $0x50, %ymm4, %ymm6 + # rnd_0: 6 - 6 + xorl %r10d, %eax + addl %edx, %r9d + andl %eax, %ebx + vpsrlq $0x11, %ymm6, %ymm8 + # rnd_0: 7 - 7 + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + addl %ebx, %r9d + vpsrlq $19, %ymm6, %ymm7 + # rnd_1: 0 - 0 + movl %r14d, %ebx + rorxl $11, %r13d, %ecx + addl 364(%rsp), %r8d + vpsrld $10, %ymm6, %ymm9 + # rnd_1: 1 - 1 + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + vpxor %ymm7, %ymm8, %ymm8 + # rnd_1: 2 - 2 + andl %r13d, %ebx + xorl %ecx, %edx + rorxl $13, %r9d, %ecx + vpxor %ymm8, %ymm9, %ymm9 + # rnd_1: 3 - 3 + addl %edx, %r8d + rorxl $2, %r9d, %edx + xorl %r15d, %ebx + vpshufb %ymm12, %ymm9, %ymm9 + # rnd_1: 4 - 4 + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + vpaddd %ymm4, %ymm9, %ymm3 + # rnd_1: 5 - 5 + xorl %ecx, %edx + addl %r8d, %r12d + movl %r10d, %ebx + vpaddd 480+L_avx2_rorx_sha256_k(%rip), %ymm3, %ymm4 + # rnd_1: 6 - 6 + xorl %r9d, %ebx + addl %edx, %r8d + andl %ebx, %eax + # rnd_1: 7 - 7 + xorl %r10d, %eax + rorxl $6, %r12d, %edx + addl %eax, %r8d + vmovdqu %ymm4, 480(%rsp) + xorl %eax, %eax + xorl %ecx, %ecx + rorxl $6, %r12d, %edx + rorxl $11, %r12d, %ecx + leal (%r8,%rax,1), %r8d + addl 384(%rsp), %r15d + movl %r13d, %eax + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + xorl %ecx, %edx + andl %r12d, %eax + addl %edx, %r15d + rorxl $2, %r8d, %edx + rorxl $13, %r8d, %ecx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + andl %eax, %ebx + addl %edx, %r15d + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + rorxl $11, %r11d, %ecx + addl %ebx, %r15d + addl 388(%rsp), %r14d + movl %r12d, %ebx + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + xorl %ecx, %edx + andl %r11d, %ebx + addl %edx, %r14d + rorxl $2, %r15d, %edx + rorxl $13, %r15d, %ecx + xorl %r13d, %ebx + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + xorl %ecx, %edx + movl %r8d, %ebx + leal (%r10,%r14,1), %r10d + xorl %r15d, %ebx + andl %ebx, %eax + addl %edx, %r14d + xorl %r8d, %eax + rorxl $6, %r10d, %edx + rorxl $11, %r10d, %ecx + leal (%r14,%rax,1), %r14d + addl 392(%rsp), %r13d + movl %r11d, %eax + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + xorl %ecx, %edx + andl %r10d, %eax + addl %edx, %r13d + rorxl $2, %r14d, %edx + rorxl $13, %r14d, %ecx + xorl %r12d, %eax + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + xorl %r14d, %eax + andl %eax, %ebx + addl %edx, %r13d + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + rorxl $11, %r9d, %ecx + addl %ebx, %r13d + addl 396(%rsp), %r12d + movl %r10d, %ebx + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + xorl %ecx, %edx + andl %r9d, %ebx + addl %edx, %r12d + rorxl $2, %r13d, %edx + rorxl $13, %r13d, %ecx + xorl %r11d, %ebx + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + xorl %ecx, %edx + movl %r14d, %ebx + leal (%r8,%r12,1), %r8d + xorl %r13d, %ebx + andl %ebx, %eax + addl %edx, %r12d + xorl %r14d, %eax + rorxl $6, %r8d, %edx + rorxl $11, %r8d, %ecx + leal (%r12,%rax,1), %r12d + addl 416(%rsp), %r11d + movl %r9d, %eax + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + xorl %ecx, %edx + andl %r8d, %eax + addl %edx, %r11d + rorxl $2, %r12d, %edx + rorxl $13, %r12d, %ecx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + andl %eax, %ebx + addl %edx, %r11d + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + rorxl $11, %r15d, %ecx + addl %ebx, %r11d + addl 420(%rsp), %r10d + movl %r8d, %ebx + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + xorl %ecx, %edx + andl %r15d, %ebx + addl %edx, %r10d + rorxl $2, %r11d, %edx + rorxl $13, %r11d, %ecx + xorl %r9d, %ebx + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + xorl %ecx, %edx + movl %r12d, %ebx + leal (%r14,%r10,1), %r14d + xorl %r11d, %ebx + andl %ebx, %eax + addl %edx, %r10d + xorl %r12d, %eax + rorxl $6, %r14d, %edx + rorxl $11, %r14d, %ecx + leal (%r10,%rax,1), %r10d + addl 424(%rsp), %r9d + movl %r15d, %eax + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + xorl %ecx, %edx + andl %r14d, %eax + addl %edx, %r9d + rorxl $2, %r10d, %edx + rorxl $13, %r10d, %ecx + xorl %r8d, %eax + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + xorl %r10d, %eax + andl %eax, %ebx + addl %edx, %r9d + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + rorxl $11, %r13d, %ecx + addl %ebx, %r9d + addl 428(%rsp), %r8d + movl %r14d, %ebx + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + xorl %ecx, %edx + andl %r13d, %ebx + addl %edx, %r8d + rorxl $2, %r9d, %edx + rorxl $13, %r9d, %ecx + xorl %r15d, %ebx + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + xorl %ecx, %edx + movl %r10d, %ebx + leal (%r12,%r8,1), %r12d + xorl %r9d, %ebx + andl %ebx, %eax + addl %edx, %r8d + xorl %r10d, %eax + rorxl $6, %r12d, %edx + rorxl $11, %r12d, %ecx + leal (%r8,%rax,1), %r8d + addl 448(%rsp), %r15d + movl %r13d, %eax + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + xorl %ecx, %edx + andl %r12d, %eax + addl %edx, %r15d + rorxl $2, %r8d, %edx + rorxl $13, %r8d, %ecx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + andl %eax, %ebx + addl %edx, %r15d + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + rorxl $11, %r11d, %ecx + addl %ebx, %r15d + addl 452(%rsp), %r14d + movl %r12d, %ebx + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + xorl %ecx, %edx + andl %r11d, %ebx + addl %edx, %r14d + rorxl $2, %r15d, %edx + rorxl $13, %r15d, %ecx + xorl %r13d, %ebx + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + xorl %ecx, %edx + movl %r8d, %ebx + leal (%r10,%r14,1), %r10d + xorl %r15d, %ebx + andl %ebx, %eax + addl %edx, %r14d + xorl %r8d, %eax + rorxl $6, %r10d, %edx + rorxl $11, %r10d, %ecx + leal (%r14,%rax,1), %r14d + addl 456(%rsp), %r13d + movl %r11d, %eax + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + xorl %ecx, %edx + andl %r10d, %eax + addl %edx, %r13d + rorxl $2, %r14d, %edx + rorxl $13, %r14d, %ecx + xorl %r12d, %eax + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + xorl %r14d, %eax + andl %eax, %ebx + addl %edx, %r13d + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + rorxl $11, %r9d, %ecx + addl %ebx, %r13d + addl 460(%rsp), %r12d + movl %r10d, %ebx + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + xorl %ecx, %edx + andl %r9d, %ebx + addl %edx, %r12d + rorxl $2, %r13d, %edx + rorxl $13, %r13d, %ecx + xorl %r11d, %ebx + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + xorl %ecx, %edx + movl %r14d, %ebx + leal (%r8,%r12,1), %r8d + xorl %r13d, %ebx + andl %ebx, %eax + addl %edx, %r12d + xorl %r14d, %eax + rorxl $6, %r8d, %edx + rorxl $11, %r8d, %ecx + leal (%r12,%rax,1), %r12d + addl 480(%rsp), %r11d + movl %r9d, %eax + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + xorl %ecx, %edx + andl %r8d, %eax + addl %edx, %r11d + rorxl $2, %r12d, %edx + rorxl $13, %r12d, %ecx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + andl %eax, %ebx + addl %edx, %r11d + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + rorxl $11, %r15d, %ecx + addl %ebx, %r11d + addl 484(%rsp), %r10d + movl %r8d, %ebx + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + xorl %ecx, %edx + andl %r15d, %ebx + addl %edx, %r10d + rorxl $2, %r11d, %edx + rorxl $13, %r11d, %ecx + xorl %r9d, %ebx + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + xorl %ecx, %edx + movl %r12d, %ebx + leal (%r14,%r10,1), %r14d + xorl %r11d, %ebx + andl %ebx, %eax + addl %edx, %r10d + xorl %r12d, %eax + rorxl $6, %r14d, %edx + rorxl $11, %r14d, %ecx + leal (%r10,%rax,1), %r10d + addl 488(%rsp), %r9d + movl %r15d, %eax + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + xorl %ecx, %edx + andl %r14d, %eax + addl %edx, %r9d + rorxl $2, %r10d, %edx + rorxl $13, %r10d, %ecx + xorl %r8d, %eax + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + xorl %r10d, %eax + andl %eax, %ebx + addl %edx, %r9d + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + rorxl $11, %r13d, %ecx + addl %ebx, %r9d + addl 492(%rsp), %r8d + movl %r14d, %ebx + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + xorl %ecx, %edx + andl %r13d, %ebx + addl %edx, %r8d + rorxl $2, %r9d, %edx + rorxl $13, %r9d, %ecx + xorl %r15d, %ebx + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + xorl %ecx, %edx + movl %r10d, %ebx + leal (%r12,%r8,1), %r12d + xorl %r9d, %ebx + andl %ebx, %eax + addl %edx, %r8d + xorl %r10d, %eax + addl %eax, %r8d + xorl %ecx, %ecx + addl (%rdi), %r8d + addl 4(%rdi), %r9d + addl 8(%rdi), %r10d + addl 12(%rdi), %r11d + addl 16(%rdi), %r12d + addl 20(%rdi), %r13d + addl 24(%rdi), %r14d + addl 28(%rdi), %r15d + movl %r8d, (%rdi) + movl %r9d, 4(%rdi) + movl %r10d, 8(%rdi) + movl %r11d, 12(%rdi) + movl %r12d, 16(%rdi) + movl %r13d, 20(%rdi) + movl %r14d, 24(%rdi) + movl %r15d, 28(%rdi) + movl %r9d, %ebx + xorl %eax, %eax + xorl %r10d, %ebx + rorxl $6, %r12d, %edx + rorxl $11, %r12d, %ecx + leal (%r8,%rax,1), %r8d + addl 16(%rsp), %r15d + movl %r13d, %eax + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + xorl %ecx, %edx + andl %r12d, %eax + addl %edx, %r15d + rorxl $2, %r8d, %edx + rorxl $13, %r8d, %ecx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + andl %eax, %ebx + addl %edx, %r15d + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + rorxl $11, %r11d, %ecx + addl %ebx, %r15d + addl 20(%rsp), %r14d + movl %r12d, %ebx + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + xorl %ecx, %edx + andl %r11d, %ebx + addl %edx, %r14d + rorxl $2, %r15d, %edx + rorxl $13, %r15d, %ecx + xorl %r13d, %ebx + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + xorl %ecx, %edx + movl %r8d, %ebx + leal (%r10,%r14,1), %r10d + xorl %r15d, %ebx + andl %ebx, %eax + addl %edx, %r14d + xorl %r8d, %eax + rorxl $6, %r10d, %edx + rorxl $11, %r10d, %ecx + leal (%r14,%rax,1), %r14d + addl 24(%rsp), %r13d + movl %r11d, %eax + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + xorl %ecx, %edx + andl %r10d, %eax + addl %edx, %r13d + rorxl $2, %r14d, %edx + rorxl $13, %r14d, %ecx + xorl %r12d, %eax + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + xorl %r14d, %eax + andl %eax, %ebx + addl %edx, %r13d + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + rorxl $11, %r9d, %ecx + addl %ebx, %r13d + addl 28(%rsp), %r12d + movl %r10d, %ebx + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + xorl %ecx, %edx + andl %r9d, %ebx + addl %edx, %r12d + rorxl $2, %r13d, %edx + rorxl $13, %r13d, %ecx + xorl %r11d, %ebx + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + xorl %ecx, %edx + movl %r14d, %ebx + leal (%r8,%r12,1), %r8d + xorl %r13d, %ebx + andl %ebx, %eax + addl %edx, %r12d + xorl %r14d, %eax + rorxl $6, %r8d, %edx + rorxl $11, %r8d, %ecx + leal (%r12,%rax,1), %r12d + addl 48(%rsp), %r11d + movl %r9d, %eax + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + xorl %ecx, %edx + andl %r8d, %eax + addl %edx, %r11d + rorxl $2, %r12d, %edx + rorxl $13, %r12d, %ecx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + andl %eax, %ebx + addl %edx, %r11d + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + rorxl $11, %r15d, %ecx + addl %ebx, %r11d + addl 52(%rsp), %r10d + movl %r8d, %ebx + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + xorl %ecx, %edx + andl %r15d, %ebx + addl %edx, %r10d + rorxl $2, %r11d, %edx + rorxl $13, %r11d, %ecx + xorl %r9d, %ebx + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + xorl %ecx, %edx + movl %r12d, %ebx + leal (%r14,%r10,1), %r14d + xorl %r11d, %ebx + andl %ebx, %eax + addl %edx, %r10d + xorl %r12d, %eax + rorxl $6, %r14d, %edx + rorxl $11, %r14d, %ecx + leal (%r10,%rax,1), %r10d + addl 56(%rsp), %r9d + movl %r15d, %eax + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + xorl %ecx, %edx + andl %r14d, %eax + addl %edx, %r9d + rorxl $2, %r10d, %edx + rorxl $13, %r10d, %ecx + xorl %r8d, %eax + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + xorl %r10d, %eax + andl %eax, %ebx + addl %edx, %r9d + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + rorxl $11, %r13d, %ecx + addl %ebx, %r9d + addl 60(%rsp), %r8d + movl %r14d, %ebx + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + xorl %ecx, %edx + andl %r13d, %ebx + addl %edx, %r8d + rorxl $2, %r9d, %edx + rorxl $13, %r9d, %ecx + xorl %r15d, %ebx + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + xorl %ecx, %edx + movl %r10d, %ebx + leal (%r12,%r8,1), %r12d + xorl %r9d, %ebx + andl %ebx, %eax + addl %edx, %r8d + xorl %r10d, %eax + rorxl $6, %r12d, %edx + rorxl $11, %r12d, %ecx + leal (%r8,%rax,1), %r8d + addl 80(%rsp), %r15d + movl %r13d, %eax + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + xorl %ecx, %edx + andl %r12d, %eax + addl %edx, %r15d + rorxl $2, %r8d, %edx + rorxl $13, %r8d, %ecx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + andl %eax, %ebx + addl %edx, %r15d + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + rorxl $11, %r11d, %ecx + addl %ebx, %r15d + addl 84(%rsp), %r14d + movl %r12d, %ebx + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + xorl %ecx, %edx + andl %r11d, %ebx + addl %edx, %r14d + rorxl $2, %r15d, %edx + rorxl $13, %r15d, %ecx + xorl %r13d, %ebx + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + xorl %ecx, %edx + movl %r8d, %ebx + leal (%r10,%r14,1), %r10d + xorl %r15d, %ebx + andl %ebx, %eax + addl %edx, %r14d + xorl %r8d, %eax + rorxl $6, %r10d, %edx + rorxl $11, %r10d, %ecx + leal (%r14,%rax,1), %r14d + addl 88(%rsp), %r13d + movl %r11d, %eax + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + xorl %ecx, %edx + andl %r10d, %eax + addl %edx, %r13d + rorxl $2, %r14d, %edx + rorxl $13, %r14d, %ecx + xorl %r12d, %eax + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + xorl %r14d, %eax + andl %eax, %ebx + addl %edx, %r13d + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + rorxl $11, %r9d, %ecx + addl %ebx, %r13d + addl 92(%rsp), %r12d + movl %r10d, %ebx + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + xorl %ecx, %edx + andl %r9d, %ebx + addl %edx, %r12d + rorxl $2, %r13d, %edx + rorxl $13, %r13d, %ecx + xorl %r11d, %ebx + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + xorl %ecx, %edx + movl %r14d, %ebx + leal (%r8,%r12,1), %r8d + xorl %r13d, %ebx + andl %ebx, %eax + addl %edx, %r12d + xorl %r14d, %eax + rorxl $6, %r8d, %edx + rorxl $11, %r8d, %ecx + leal (%r12,%rax,1), %r12d + addl 112(%rsp), %r11d + movl %r9d, %eax + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + xorl %ecx, %edx + andl %r8d, %eax + addl %edx, %r11d + rorxl $2, %r12d, %edx + rorxl $13, %r12d, %ecx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + andl %eax, %ebx + addl %edx, %r11d + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + rorxl $11, %r15d, %ecx + addl %ebx, %r11d + addl 116(%rsp), %r10d + movl %r8d, %ebx + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + xorl %ecx, %edx + andl %r15d, %ebx + addl %edx, %r10d + rorxl $2, %r11d, %edx + rorxl $13, %r11d, %ecx + xorl %r9d, %ebx + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + xorl %ecx, %edx + movl %r12d, %ebx + leal (%r14,%r10,1), %r14d + xorl %r11d, %ebx + andl %ebx, %eax + addl %edx, %r10d + xorl %r12d, %eax + rorxl $6, %r14d, %edx + rorxl $11, %r14d, %ecx + leal (%r10,%rax,1), %r10d + addl 120(%rsp), %r9d + movl %r15d, %eax + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + xorl %ecx, %edx + andl %r14d, %eax + addl %edx, %r9d + rorxl $2, %r10d, %edx + rorxl $13, %r10d, %ecx + xorl %r8d, %eax + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + xorl %r10d, %eax + andl %eax, %ebx + addl %edx, %r9d + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + rorxl $11, %r13d, %ecx + addl %ebx, %r9d + addl 124(%rsp), %r8d + movl %r14d, %ebx + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + xorl %ecx, %edx + andl %r13d, %ebx + addl %edx, %r8d + rorxl $2, %r9d, %edx + rorxl $13, %r9d, %ecx + xorl %r15d, %ebx + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + xorl %ecx, %edx + movl %r10d, %ebx + leal (%r12,%r8,1), %r12d + xorl %r9d, %ebx + andl %ebx, %eax + addl %edx, %r8d + xorl %r10d, %eax + rorxl $6, %r12d, %edx + rorxl $11, %r12d, %ecx + leal (%r8,%rax,1), %r8d + addl 144(%rsp), %r15d + movl %r13d, %eax + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + xorl %ecx, %edx + andl %r12d, %eax + addl %edx, %r15d + rorxl $2, %r8d, %edx + rorxl $13, %r8d, %ecx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + andl %eax, %ebx + addl %edx, %r15d + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + rorxl $11, %r11d, %ecx + addl %ebx, %r15d + addl 148(%rsp), %r14d + movl %r12d, %ebx + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + xorl %ecx, %edx + andl %r11d, %ebx + addl %edx, %r14d + rorxl $2, %r15d, %edx + rorxl $13, %r15d, %ecx + xorl %r13d, %ebx + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + xorl %ecx, %edx + movl %r8d, %ebx + leal (%r10,%r14,1), %r10d + xorl %r15d, %ebx + andl %ebx, %eax + addl %edx, %r14d + xorl %r8d, %eax + rorxl $6, %r10d, %edx + rorxl $11, %r10d, %ecx + leal (%r14,%rax,1), %r14d + addl 152(%rsp), %r13d + movl %r11d, %eax + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + xorl %ecx, %edx + andl %r10d, %eax + addl %edx, %r13d + rorxl $2, %r14d, %edx + rorxl $13, %r14d, %ecx + xorl %r12d, %eax + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + xorl %r14d, %eax + andl %eax, %ebx + addl %edx, %r13d + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + rorxl $11, %r9d, %ecx + addl %ebx, %r13d + addl 156(%rsp), %r12d + movl %r10d, %ebx + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + xorl %ecx, %edx + andl %r9d, %ebx + addl %edx, %r12d + rorxl $2, %r13d, %edx + rorxl $13, %r13d, %ecx + xorl %r11d, %ebx + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + xorl %ecx, %edx + movl %r14d, %ebx + leal (%r8,%r12,1), %r8d + xorl %r13d, %ebx + andl %ebx, %eax + addl %edx, %r12d + xorl %r14d, %eax + rorxl $6, %r8d, %edx + rorxl $11, %r8d, %ecx + leal (%r12,%rax,1), %r12d + addl 176(%rsp), %r11d + movl %r9d, %eax + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + xorl %ecx, %edx + andl %r8d, %eax + addl %edx, %r11d + rorxl $2, %r12d, %edx + rorxl $13, %r12d, %ecx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + andl %eax, %ebx + addl %edx, %r11d + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + rorxl $11, %r15d, %ecx + addl %ebx, %r11d + addl 180(%rsp), %r10d + movl %r8d, %ebx + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + xorl %ecx, %edx + andl %r15d, %ebx + addl %edx, %r10d + rorxl $2, %r11d, %edx + rorxl $13, %r11d, %ecx + xorl %r9d, %ebx + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + xorl %ecx, %edx + movl %r12d, %ebx + leal (%r14,%r10,1), %r14d + xorl %r11d, %ebx + andl %ebx, %eax + addl %edx, %r10d + xorl %r12d, %eax + rorxl $6, %r14d, %edx + rorxl $11, %r14d, %ecx + leal (%r10,%rax,1), %r10d + addl 184(%rsp), %r9d + movl %r15d, %eax + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + xorl %ecx, %edx + andl %r14d, %eax + addl %edx, %r9d + rorxl $2, %r10d, %edx + rorxl $13, %r10d, %ecx + xorl %r8d, %eax + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + xorl %r10d, %eax + andl %eax, %ebx + addl %edx, %r9d + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + rorxl $11, %r13d, %ecx + addl %ebx, %r9d + addl 188(%rsp), %r8d + movl %r14d, %ebx + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + xorl %ecx, %edx + andl %r13d, %ebx + addl %edx, %r8d + rorxl $2, %r9d, %edx + rorxl $13, %r9d, %ecx + xorl %r15d, %ebx + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + xorl %ecx, %edx + movl %r10d, %ebx + leal (%r12,%r8,1), %r12d + xorl %r9d, %ebx + andl %ebx, %eax + addl %edx, %r8d + xorl %r10d, %eax + rorxl $6, %r12d, %edx + rorxl $11, %r12d, %ecx + leal (%r8,%rax,1), %r8d + addl 208(%rsp), %r15d + movl %r13d, %eax + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + xorl %ecx, %edx + andl %r12d, %eax + addl %edx, %r15d + rorxl $2, %r8d, %edx + rorxl $13, %r8d, %ecx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + andl %eax, %ebx + addl %edx, %r15d + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + rorxl $11, %r11d, %ecx + addl %ebx, %r15d + addl 212(%rsp), %r14d + movl %r12d, %ebx + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + xorl %ecx, %edx + andl %r11d, %ebx + addl %edx, %r14d + rorxl $2, %r15d, %edx + rorxl $13, %r15d, %ecx + xorl %r13d, %ebx + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + xorl %ecx, %edx + movl %r8d, %ebx + leal (%r10,%r14,1), %r10d + xorl %r15d, %ebx + andl %ebx, %eax + addl %edx, %r14d + xorl %r8d, %eax + rorxl $6, %r10d, %edx + rorxl $11, %r10d, %ecx + leal (%r14,%rax,1), %r14d + addl 216(%rsp), %r13d + movl %r11d, %eax + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + xorl %ecx, %edx + andl %r10d, %eax + addl %edx, %r13d + rorxl $2, %r14d, %edx + rorxl $13, %r14d, %ecx + xorl %r12d, %eax + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + xorl %r14d, %eax + andl %eax, %ebx + addl %edx, %r13d + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + rorxl $11, %r9d, %ecx + addl %ebx, %r13d + addl 220(%rsp), %r12d + movl %r10d, %ebx + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + xorl %ecx, %edx + andl %r9d, %ebx + addl %edx, %r12d + rorxl $2, %r13d, %edx + rorxl $13, %r13d, %ecx + xorl %r11d, %ebx + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + xorl %ecx, %edx + movl %r14d, %ebx + leal (%r8,%r12,1), %r8d + xorl %r13d, %ebx + andl %ebx, %eax + addl %edx, %r12d + xorl %r14d, %eax + rorxl $6, %r8d, %edx + rorxl $11, %r8d, %ecx + leal (%r12,%rax,1), %r12d + addl 240(%rsp), %r11d + movl %r9d, %eax + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + xorl %ecx, %edx + andl %r8d, %eax + addl %edx, %r11d + rorxl $2, %r12d, %edx + rorxl $13, %r12d, %ecx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + andl %eax, %ebx + addl %edx, %r11d + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + rorxl $11, %r15d, %ecx + addl %ebx, %r11d + addl 244(%rsp), %r10d + movl %r8d, %ebx + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + xorl %ecx, %edx + andl %r15d, %ebx + addl %edx, %r10d + rorxl $2, %r11d, %edx + rorxl $13, %r11d, %ecx + xorl %r9d, %ebx + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + xorl %ecx, %edx + movl %r12d, %ebx + leal (%r14,%r10,1), %r14d + xorl %r11d, %ebx + andl %ebx, %eax + addl %edx, %r10d + xorl %r12d, %eax + rorxl $6, %r14d, %edx + rorxl $11, %r14d, %ecx + leal (%r10,%rax,1), %r10d + addl 248(%rsp), %r9d + movl %r15d, %eax + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + xorl %ecx, %edx + andl %r14d, %eax + addl %edx, %r9d + rorxl $2, %r10d, %edx + rorxl $13, %r10d, %ecx + xorl %r8d, %eax + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + xorl %r10d, %eax + andl %eax, %ebx + addl %edx, %r9d + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + rorxl $11, %r13d, %ecx + addl %ebx, %r9d + addl 252(%rsp), %r8d + movl %r14d, %ebx + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + xorl %ecx, %edx + andl %r13d, %ebx + addl %edx, %r8d + rorxl $2, %r9d, %edx + rorxl $13, %r9d, %ecx + xorl %r15d, %ebx + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + xorl %ecx, %edx + movl %r10d, %ebx + leal (%r12,%r8,1), %r12d + xorl %r9d, %ebx + andl %ebx, %eax + addl %edx, %r8d + xorl %r10d, %eax + rorxl $6, %r12d, %edx + rorxl $11, %r12d, %ecx + leal (%r8,%rax,1), %r8d + addl 272(%rsp), %r15d + movl %r13d, %eax + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + xorl %ecx, %edx + andl %r12d, %eax + addl %edx, %r15d + rorxl $2, %r8d, %edx + rorxl $13, %r8d, %ecx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + andl %eax, %ebx + addl %edx, %r15d + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + rorxl $11, %r11d, %ecx + addl %ebx, %r15d + addl 276(%rsp), %r14d + movl %r12d, %ebx + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + xorl %ecx, %edx + andl %r11d, %ebx + addl %edx, %r14d + rorxl $2, %r15d, %edx + rorxl $13, %r15d, %ecx + xorl %r13d, %ebx + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + xorl %ecx, %edx + movl %r8d, %ebx + leal (%r10,%r14,1), %r10d + xorl %r15d, %ebx + andl %ebx, %eax + addl %edx, %r14d + xorl %r8d, %eax + rorxl $6, %r10d, %edx + rorxl $11, %r10d, %ecx + leal (%r14,%rax,1), %r14d + addl 280(%rsp), %r13d + movl %r11d, %eax + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + xorl %ecx, %edx + andl %r10d, %eax + addl %edx, %r13d + rorxl $2, %r14d, %edx + rorxl $13, %r14d, %ecx + xorl %r12d, %eax + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + xorl %r14d, %eax + andl %eax, %ebx + addl %edx, %r13d + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + rorxl $11, %r9d, %ecx + addl %ebx, %r13d + addl 284(%rsp), %r12d + movl %r10d, %ebx + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + xorl %ecx, %edx + andl %r9d, %ebx + addl %edx, %r12d + rorxl $2, %r13d, %edx + rorxl $13, %r13d, %ecx + xorl %r11d, %ebx + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + xorl %ecx, %edx + movl %r14d, %ebx + leal (%r8,%r12,1), %r8d + xorl %r13d, %ebx + andl %ebx, %eax + addl %edx, %r12d + xorl %r14d, %eax + rorxl $6, %r8d, %edx + rorxl $11, %r8d, %ecx + leal (%r12,%rax,1), %r12d + addl 304(%rsp), %r11d + movl %r9d, %eax + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + xorl %ecx, %edx + andl %r8d, %eax + addl %edx, %r11d + rorxl $2, %r12d, %edx + rorxl $13, %r12d, %ecx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + andl %eax, %ebx + addl %edx, %r11d + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + rorxl $11, %r15d, %ecx + addl %ebx, %r11d + addl 308(%rsp), %r10d + movl %r8d, %ebx + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + xorl %ecx, %edx + andl %r15d, %ebx + addl %edx, %r10d + rorxl $2, %r11d, %edx + rorxl $13, %r11d, %ecx + xorl %r9d, %ebx + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + xorl %ecx, %edx + movl %r12d, %ebx + leal (%r14,%r10,1), %r14d + xorl %r11d, %ebx + andl %ebx, %eax + addl %edx, %r10d + xorl %r12d, %eax + rorxl $6, %r14d, %edx + rorxl $11, %r14d, %ecx + leal (%r10,%rax,1), %r10d + addl 312(%rsp), %r9d + movl %r15d, %eax + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + xorl %ecx, %edx + andl %r14d, %eax + addl %edx, %r9d + rorxl $2, %r10d, %edx + rorxl $13, %r10d, %ecx + xorl %r8d, %eax + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + xorl %r10d, %eax + andl %eax, %ebx + addl %edx, %r9d + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + rorxl $11, %r13d, %ecx + addl %ebx, %r9d + addl 316(%rsp), %r8d + movl %r14d, %ebx + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + xorl %ecx, %edx + andl %r13d, %ebx + addl %edx, %r8d + rorxl $2, %r9d, %edx + rorxl $13, %r9d, %ecx + xorl %r15d, %ebx + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + xorl %ecx, %edx + movl %r10d, %ebx + leal (%r12,%r8,1), %r12d + xorl %r9d, %ebx + andl %ebx, %eax + addl %edx, %r8d + xorl %r10d, %eax + rorxl $6, %r12d, %edx + rorxl $11, %r12d, %ecx + leal (%r8,%rax,1), %r8d + addl 336(%rsp), %r15d + movl %r13d, %eax + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + xorl %ecx, %edx + andl %r12d, %eax + addl %edx, %r15d + rorxl $2, %r8d, %edx + rorxl $13, %r8d, %ecx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + andl %eax, %ebx + addl %edx, %r15d + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + rorxl $11, %r11d, %ecx + addl %ebx, %r15d + addl 340(%rsp), %r14d + movl %r12d, %ebx + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + xorl %ecx, %edx + andl %r11d, %ebx + addl %edx, %r14d + rorxl $2, %r15d, %edx + rorxl $13, %r15d, %ecx + xorl %r13d, %ebx + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + xorl %ecx, %edx + movl %r8d, %ebx + leal (%r10,%r14,1), %r10d + xorl %r15d, %ebx + andl %ebx, %eax + addl %edx, %r14d + xorl %r8d, %eax + rorxl $6, %r10d, %edx + rorxl $11, %r10d, %ecx + leal (%r14,%rax,1), %r14d + addl 344(%rsp), %r13d + movl %r11d, %eax + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + xorl %ecx, %edx + andl %r10d, %eax + addl %edx, %r13d + rorxl $2, %r14d, %edx + rorxl $13, %r14d, %ecx + xorl %r12d, %eax + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + xorl %r14d, %eax + andl %eax, %ebx + addl %edx, %r13d + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + rorxl $11, %r9d, %ecx + addl %ebx, %r13d + addl 348(%rsp), %r12d + movl %r10d, %ebx + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + xorl %ecx, %edx + andl %r9d, %ebx + addl %edx, %r12d + rorxl $2, %r13d, %edx + rorxl $13, %r13d, %ecx + xorl %r11d, %ebx + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + xorl %ecx, %edx + movl %r14d, %ebx + leal (%r8,%r12,1), %r8d + xorl %r13d, %ebx + andl %ebx, %eax + addl %edx, %r12d + xorl %r14d, %eax + rorxl $6, %r8d, %edx + rorxl $11, %r8d, %ecx + leal (%r12,%rax,1), %r12d + addl 368(%rsp), %r11d + movl %r9d, %eax + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + xorl %ecx, %edx + andl %r8d, %eax + addl %edx, %r11d + rorxl $2, %r12d, %edx + rorxl $13, %r12d, %ecx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + andl %eax, %ebx + addl %edx, %r11d + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + rorxl $11, %r15d, %ecx + addl %ebx, %r11d + addl 372(%rsp), %r10d + movl %r8d, %ebx + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + xorl %ecx, %edx + andl %r15d, %ebx + addl %edx, %r10d + rorxl $2, %r11d, %edx + rorxl $13, %r11d, %ecx + xorl %r9d, %ebx + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + xorl %ecx, %edx + movl %r12d, %ebx + leal (%r14,%r10,1), %r14d + xorl %r11d, %ebx + andl %ebx, %eax + addl %edx, %r10d + xorl %r12d, %eax + rorxl $6, %r14d, %edx + rorxl $11, %r14d, %ecx + leal (%r10,%rax,1), %r10d + addl 376(%rsp), %r9d + movl %r15d, %eax + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + xorl %ecx, %edx + andl %r14d, %eax + addl %edx, %r9d + rorxl $2, %r10d, %edx + rorxl $13, %r10d, %ecx + xorl %r8d, %eax + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + xorl %r10d, %eax + andl %eax, %ebx + addl %edx, %r9d + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + rorxl $11, %r13d, %ecx + addl %ebx, %r9d + addl 380(%rsp), %r8d + movl %r14d, %ebx + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + xorl %ecx, %edx + andl %r13d, %ebx + addl %edx, %r8d + rorxl $2, %r9d, %edx + rorxl $13, %r9d, %ecx + xorl %r15d, %ebx + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + xorl %ecx, %edx + movl %r10d, %ebx + leal (%r12,%r8,1), %r12d + xorl %r9d, %ebx + andl %ebx, %eax + addl %edx, %r8d + xorl %r10d, %eax + rorxl $6, %r12d, %edx + rorxl $11, %r12d, %ecx + leal (%r8,%rax,1), %r8d + addl 400(%rsp), %r15d + movl %r13d, %eax + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + xorl %ecx, %edx + andl %r12d, %eax + addl %edx, %r15d + rorxl $2, %r8d, %edx + rorxl $13, %r8d, %ecx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + andl %eax, %ebx + addl %edx, %r15d + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + rorxl $11, %r11d, %ecx + addl %ebx, %r15d + addl 404(%rsp), %r14d + movl %r12d, %ebx + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + xorl %ecx, %edx + andl %r11d, %ebx + addl %edx, %r14d + rorxl $2, %r15d, %edx + rorxl $13, %r15d, %ecx + xorl %r13d, %ebx + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + xorl %ecx, %edx + movl %r8d, %ebx + leal (%r10,%r14,1), %r10d + xorl %r15d, %ebx + andl %ebx, %eax + addl %edx, %r14d + xorl %r8d, %eax + rorxl $6, %r10d, %edx + rorxl $11, %r10d, %ecx + leal (%r14,%rax,1), %r14d + addl 408(%rsp), %r13d + movl %r11d, %eax + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + xorl %ecx, %edx + andl %r10d, %eax + addl %edx, %r13d + rorxl $2, %r14d, %edx + rorxl $13, %r14d, %ecx + xorl %r12d, %eax + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + xorl %r14d, %eax + andl %eax, %ebx + addl %edx, %r13d + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + rorxl $11, %r9d, %ecx + addl %ebx, %r13d + addl 412(%rsp), %r12d + movl %r10d, %ebx + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + xorl %ecx, %edx + andl %r9d, %ebx + addl %edx, %r12d + rorxl $2, %r13d, %edx + rorxl $13, %r13d, %ecx + xorl %r11d, %ebx + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + xorl %ecx, %edx + movl %r14d, %ebx + leal (%r8,%r12,1), %r8d + xorl %r13d, %ebx + andl %ebx, %eax + addl %edx, %r12d + xorl %r14d, %eax + rorxl $6, %r8d, %edx + rorxl $11, %r8d, %ecx + leal (%r12,%rax,1), %r12d + addl 432(%rsp), %r11d + movl %r9d, %eax + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + xorl %ecx, %edx + andl %r8d, %eax + addl %edx, %r11d + rorxl $2, %r12d, %edx + rorxl $13, %r12d, %ecx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + andl %eax, %ebx + addl %edx, %r11d + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + rorxl $11, %r15d, %ecx + addl %ebx, %r11d + addl 436(%rsp), %r10d + movl %r8d, %ebx + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + xorl %ecx, %edx + andl %r15d, %ebx + addl %edx, %r10d + rorxl $2, %r11d, %edx + rorxl $13, %r11d, %ecx + xorl %r9d, %ebx + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + xorl %ecx, %edx + movl %r12d, %ebx + leal (%r14,%r10,1), %r14d + xorl %r11d, %ebx + andl %ebx, %eax + addl %edx, %r10d + xorl %r12d, %eax + rorxl $6, %r14d, %edx + rorxl $11, %r14d, %ecx + leal (%r10,%rax,1), %r10d + addl 440(%rsp), %r9d + movl %r15d, %eax + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + xorl %ecx, %edx + andl %r14d, %eax + addl %edx, %r9d + rorxl $2, %r10d, %edx + rorxl $13, %r10d, %ecx + xorl %r8d, %eax + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + xorl %r10d, %eax + andl %eax, %ebx + addl %edx, %r9d + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + rorxl $11, %r13d, %ecx + addl %ebx, %r9d + addl 444(%rsp), %r8d + movl %r14d, %ebx + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + xorl %ecx, %edx + andl %r13d, %ebx + addl %edx, %r8d + rorxl $2, %r9d, %edx + rorxl $13, %r9d, %ecx + xorl %r15d, %ebx + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + xorl %ecx, %edx + movl %r10d, %ebx + leal (%r12,%r8,1), %r12d + xorl %r9d, %ebx + andl %ebx, %eax + addl %edx, %r8d + xorl %r10d, %eax + rorxl $6, %r12d, %edx + rorxl $11, %r12d, %ecx + leal (%r8,%rax,1), %r8d + addl 464(%rsp), %r15d + movl %r13d, %eax + xorl %edx, %ecx + xorl %r14d, %eax + rorxl $25, %r12d, %edx + xorl %ecx, %edx + andl %r12d, %eax + addl %edx, %r15d + rorxl $2, %r8d, %edx + rorxl $13, %r8d, %ecx + xorl %r14d, %eax + xorl %edx, %ecx + rorxl $22, %r8d, %edx + addl %eax, %r15d + xorl %ecx, %edx + movl %r9d, %eax + addl %r15d, %r11d + xorl %r8d, %eax + andl %eax, %ebx + addl %edx, %r15d + xorl %r9d, %ebx + rorxl $6, %r11d, %edx + rorxl $11, %r11d, %ecx + addl %ebx, %r15d + addl 468(%rsp), %r14d + movl %r12d, %ebx + xorl %edx, %ecx + xorl %r13d, %ebx + rorxl $25, %r11d, %edx + xorl %ecx, %edx + andl %r11d, %ebx + addl %edx, %r14d + rorxl $2, %r15d, %edx + rorxl $13, %r15d, %ecx + xorl %r13d, %ebx + xorl %edx, %ecx + rorxl $22, %r15d, %edx + addl %ebx, %r14d + xorl %ecx, %edx + movl %r8d, %ebx + leal (%r10,%r14,1), %r10d + xorl %r15d, %ebx + andl %ebx, %eax + addl %edx, %r14d + xorl %r8d, %eax + rorxl $6, %r10d, %edx + rorxl $11, %r10d, %ecx + leal (%r14,%rax,1), %r14d + addl 472(%rsp), %r13d + movl %r11d, %eax + xorl %edx, %ecx + xorl %r12d, %eax + rorxl $25, %r10d, %edx + xorl %ecx, %edx + andl %r10d, %eax + addl %edx, %r13d + rorxl $2, %r14d, %edx + rorxl $13, %r14d, %ecx + xorl %r12d, %eax + xorl %edx, %ecx + rorxl $22, %r14d, %edx + addl %eax, %r13d + xorl %ecx, %edx + movl %r15d, %eax + addl %r13d, %r9d + xorl %r14d, %eax + andl %eax, %ebx + addl %edx, %r13d + xorl %r15d, %ebx + rorxl $6, %r9d, %edx + rorxl $11, %r9d, %ecx + addl %ebx, %r13d + addl 476(%rsp), %r12d + movl %r10d, %ebx + xorl %edx, %ecx + xorl %r11d, %ebx + rorxl $25, %r9d, %edx + xorl %ecx, %edx + andl %r9d, %ebx + addl %edx, %r12d + rorxl $2, %r13d, %edx + rorxl $13, %r13d, %ecx + xorl %r11d, %ebx + xorl %edx, %ecx + rorxl $22, %r13d, %edx + addl %ebx, %r12d + xorl %ecx, %edx + movl %r14d, %ebx + leal (%r8,%r12,1), %r8d + xorl %r13d, %ebx + andl %ebx, %eax + addl %edx, %r12d + xorl %r14d, %eax + rorxl $6, %r8d, %edx + rorxl $11, %r8d, %ecx + leal (%r12,%rax,1), %r12d + addl 496(%rsp), %r11d + movl %r9d, %eax + xorl %edx, %ecx + xorl %r10d, %eax + rorxl $25, %r8d, %edx + xorl %ecx, %edx + andl %r8d, %eax + addl %edx, %r11d + rorxl $2, %r12d, %edx + rorxl $13, %r12d, %ecx + xorl %r10d, %eax + xorl %edx, %ecx + rorxl $22, %r12d, %edx + addl %eax, %r11d + xorl %ecx, %edx + movl %r13d, %eax + addl %r11d, %r15d + xorl %r12d, %eax + andl %eax, %ebx + addl %edx, %r11d + xorl %r13d, %ebx + rorxl $6, %r15d, %edx + rorxl $11, %r15d, %ecx + addl %ebx, %r11d + addl 500(%rsp), %r10d + movl %r8d, %ebx + xorl %edx, %ecx + xorl %r9d, %ebx + rorxl $25, %r15d, %edx + xorl %ecx, %edx + andl %r15d, %ebx + addl %edx, %r10d + rorxl $2, %r11d, %edx + rorxl $13, %r11d, %ecx + xorl %r9d, %ebx + xorl %edx, %ecx + rorxl $22, %r11d, %edx + addl %ebx, %r10d + xorl %ecx, %edx + movl %r12d, %ebx + leal (%r14,%r10,1), %r14d + xorl %r11d, %ebx + andl %ebx, %eax + addl %edx, %r10d + xorl %r12d, %eax + rorxl $6, %r14d, %edx + rorxl $11, %r14d, %ecx + leal (%r10,%rax,1), %r10d + addl 504(%rsp), %r9d + movl %r15d, %eax + xorl %edx, %ecx + xorl %r8d, %eax + rorxl $25, %r14d, %edx + xorl %ecx, %edx + andl %r14d, %eax + addl %edx, %r9d + rorxl $2, %r10d, %edx + rorxl $13, %r10d, %ecx + xorl %r8d, %eax + xorl %edx, %ecx + rorxl $22, %r10d, %edx + addl %eax, %r9d + xorl %ecx, %edx + movl %r11d, %eax + addl %r9d, %r13d + xorl %r10d, %eax + andl %eax, %ebx + addl %edx, %r9d + xorl %r11d, %ebx + rorxl $6, %r13d, %edx + rorxl $11, %r13d, %ecx + addl %ebx, %r9d + addl 508(%rsp), %r8d + movl %r14d, %ebx + xorl %edx, %ecx + xorl %r15d, %ebx + rorxl $25, %r13d, %edx + xorl %ecx, %edx + andl %r13d, %ebx + addl %edx, %r8d + rorxl $2, %r9d, %edx + rorxl $13, %r9d, %ecx + xorl %r15d, %ebx + xorl %edx, %ecx + rorxl $22, %r9d, %edx + addl %ebx, %r8d + xorl %ecx, %edx + movl %r10d, %ebx + leal (%r12,%r8,1), %r12d + xorl %r9d, %ebx + andl %ebx, %eax + addl %edx, %r8d + xorl %r10d, %eax + addl %eax, %r8d + addq $0x80, %rbp + addl (%rdi), %r8d + addl 4(%rdi), %r9d + addl 8(%rdi), %r10d + addl 12(%rdi), %r11d + addl 16(%rdi), %r12d + addl 20(%rdi), %r13d + addl 24(%rdi), %r14d + addl 28(%rdi), %r15d + subl $0x80, %esi + movl %r8d, (%rdi) + movl %r9d, 4(%rdi) + movl %r10d, 8(%rdi) + movl %r11d, 12(%rdi) + movl %r12d, 16(%rdi) + movl %r13d, 20(%rdi) + movl %r14d, 24(%rdi) + movl %r15d, 28(%rdi) + jnz L_sha256_len_avx2_rorx_start +L_sha256_len_avx2_rorx_done: + xorq %rax, %rax + vzeroupper + addq $0x200, %rsp + popq %rbp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size Transform_Sha256_AVX2_RORX_Len,.-Transform_Sha256_AVX2_RORX_Len +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/sha3.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/sha3.c new file mode 100755 index 0000000..d0cf9b7 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/sha3.c @@ -0,0 +1,1134 @@ +/* sha3.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#if defined(WOLFSSL_SHA3) && !defined(WOLFSSL_XILINX_CRYPT) && \ + !defined(WOLFSSL_AFALG_XILINX_SHA3) + +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + + /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ + #define FIPS_NO_WRAPPERS + + #ifdef USE_WINDOWS_API + #pragma code_seg(".fipsA$l") + #pragma const_seg(".fipsB$l") + #endif +#endif + +#include +#include +#include + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + + +#ifdef WOLFSSL_SHA3_SMALL +/* Rotate a 64-bit value left. + * + * a Number to rotate left. + * r Number od bits to rotate left. + * returns the rotated number. + */ +#define ROTL64(a, n) (((a)<<(n))|((a)>>(64-(n)))) + +/* An array of values to XOR for block operation. */ +static const word64 hash_keccak_r[24] = +{ + 0x0000000000000001UL, 0x0000000000008082UL, + 0x800000000000808aUL, 0x8000000080008000UL, + 0x000000000000808bUL, 0x0000000080000001UL, + 0x8000000080008081UL, 0x8000000000008009UL, + 0x000000000000008aUL, 0x0000000000000088UL, + 0x0000000080008009UL, 0x000000008000000aUL, + 0x000000008000808bUL, 0x800000000000008bUL, + 0x8000000000008089UL, 0x8000000000008003UL, + 0x8000000000008002UL, 0x8000000000000080UL, + 0x000000000000800aUL, 0x800000008000000aUL, + 0x8000000080008081UL, 0x8000000000008080UL, + 0x0000000080000001UL, 0x8000000080008008UL +}; + +/* Indeces used in swap and rotate operation. */ +#define K_I_0 10 +#define K_I_1 7 +#define K_I_2 11 +#define K_I_3 17 +#define K_I_4 18 +#define K_I_5 3 +#define K_I_6 5 +#define K_I_7 16 +#define K_I_8 8 +#define K_I_9 21 +#define K_I_10 24 +#define K_I_11 4 +#define K_I_12 15 +#define K_I_13 23 +#define K_I_14 19 +#define K_I_15 13 +#define K_I_16 12 +#define K_I_17 2 +#define K_I_18 20 +#define K_I_19 14 +#define K_I_20 22 +#define K_I_21 9 +#define K_I_22 6 +#define K_I_23 1 + +/* Number of bits to rotate in swap and rotate operation. */ +#define K_R_0 1 +#define K_R_1 3 +#define K_R_2 6 +#define K_R_3 10 +#define K_R_4 15 +#define K_R_5 21 +#define K_R_6 28 +#define K_R_7 36 +#define K_R_8 45 +#define K_R_9 55 +#define K_R_10 2 +#define K_R_11 14 +#define K_R_12 27 +#define K_R_13 41 +#define K_R_14 56 +#define K_R_15 8 +#define K_R_16 25 +#define K_R_17 43 +#define K_R_18 62 +#define K_R_19 18 +#define K_R_20 39 +#define K_R_21 61 +#define K_R_22 20 +#define K_R_23 44 + +/* Swap and rotate left operation. + * + * s The state. + * t1 Temporary value. + * t2 Second temporary value. + * i The index of the loop. + */ +#define SWAP_ROTL(s, t1, t2, i) \ +do \ +{ \ + t2 = s[K_I_##i]; s[K_I_##i] = ROTL64(t1, K_R_##i); \ +} \ +while (0) + +/* Mix the XOR of the column's values into each number by column. + * + * s The state. + * b Temporary array of XORed column values. + * x The index of the column. + * t Temporary variable. + */ +#define COL_MIX(s, b, x, t) \ +do \ +{ \ + for (x = 0; x < 5; x++) \ + b[x] = s[x + 0] ^ s[x + 5] ^ s[x + 10] ^ s[x + 15] ^ s[x + 20]; \ + for (x = 0; x < 5; x++) \ + { \ + t = b[(x + 4) % 5] ^ ROTL64(b[(x + 1) % 5], 1); \ + s[x + 0] ^= t; \ + s[x + 5] ^= t; \ + s[x + 10] ^= t; \ + s[x + 15] ^= t; \ + s[x + 20] ^= t; \ + } \ +} \ +while (0) + +#ifdef SHA3_BY_SPEC +/* Mix the row values. + * BMI1 has ANDN instruction ((~a) & b) - Haswell and above. + * + * s The state. + * b Temporary array of XORed row values. + * y The index of the row to work on. + * x The index of the column. + * t0 Temporary variable. + * t1 Temporary variable. + */ +#define ROW_MIX(s, b, y, x, t0, t1) \ +do \ +{ \ + for (y = 0; y < 5; y++) \ + { \ + for (x = 0; x < 5; x++) \ + b[x] = s[y * 5 + x]; \ + for (x = 0; x < 5; x++) \ + s[y * 5 + x] = b[x] ^ (~b[(x + 1) % 5] & b[(x + 2) % 5]); \ + } \ +} \ +while (0) +#else +/* Mix the row values. + * a ^ (~b & c) == a ^ (c & (b ^ c)) == (a ^ b) ^ (b | c) + * + * s The state. + * b Temporary array of XORed row values. + * y The index of the row to work on. + * x The index of the column. + * t0 Temporary variable. + * t1 Temporary variable. + */ +#define ROW_MIX(s, b, y, x, t12, t34) \ +do \ +{ \ + for (y = 0; y < 5; y++) \ + { \ + for (x = 0; x < 5; x++) \ + b[x] = s[y * 5 + x]; \ + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); \ + s[y * 5 + 0] = b[0] ^ (b[2] & t12); \ + s[y * 5 + 1] = t12 ^ (b[2] | b[3]); \ + s[y * 5 + 2] = b[2] ^ (b[4] & t34); \ + s[y * 5 + 3] = t34 ^ (b[4] | b[0]); \ + s[y * 5 + 4] = b[4] ^ (b[1] & (b[0] ^ b[1])); \ + } \ +} \ +while (0) +#endif /* SHA3_BY_SPEC */ + +/* The block operation performed on the state. + * + * s The state. + */ +static void BlockSha3(word64 *s) +{ + byte i, x, y; + word64 t0, t1; + word64 b[5]; + + for (i = 0; i < 24; i++) + { + COL_MIX(s, b, x, t0); + + t0 = s[1]; + SWAP_ROTL(s, t0, t1, 0); + SWAP_ROTL(s, t1, t0, 1); + SWAP_ROTL(s, t0, t1, 2); + SWAP_ROTL(s, t1, t0, 3); + SWAP_ROTL(s, t0, t1, 4); + SWAP_ROTL(s, t1, t0, 5); + SWAP_ROTL(s, t0, t1, 6); + SWAP_ROTL(s, t1, t0, 7); + SWAP_ROTL(s, t0, t1, 8); + SWAP_ROTL(s, t1, t0, 9); + SWAP_ROTL(s, t0, t1, 10); + SWAP_ROTL(s, t1, t0, 11); + SWAP_ROTL(s, t0, t1, 12); + SWAP_ROTL(s, t1, t0, 13); + SWAP_ROTL(s, t0, t1, 14); + SWAP_ROTL(s, t1, t0, 15); + SWAP_ROTL(s, t0, t1, 16); + SWAP_ROTL(s, t1, t0, 17); + SWAP_ROTL(s, t0, t1, 18); + SWAP_ROTL(s, t1, t0, 19); + SWAP_ROTL(s, t0, t1, 20); + SWAP_ROTL(s, t1, t0, 21); + SWAP_ROTL(s, t0, t1, 22); + SWAP_ROTL(s, t1, t0, 23); + + ROW_MIX(s, b, y, x, t0, t1); + + s[0] ^= hash_keccak_r[i]; + } +} +#else +/* Rotate a 64-bit value left. + * + * a Number to rotate left. + * r Number od bits to rotate left. + * returns the rotated number. + */ +#define ROTL64(a, n) (((a)<<(n))|((a)>>(64-(n)))) + +/* An array of values to XOR for block operation. */ +static const word64 hash_keccak_r[24] = +{ + 0x0000000000000001UL, 0x0000000000008082UL, + 0x800000000000808aUL, 0x8000000080008000UL, + 0x000000000000808bUL, 0x0000000080000001UL, + 0x8000000080008081UL, 0x8000000000008009UL, + 0x000000000000008aUL, 0x0000000000000088UL, + 0x0000000080008009UL, 0x000000008000000aUL, + 0x000000008000808bUL, 0x800000000000008bUL, + 0x8000000000008089UL, 0x8000000000008003UL, + 0x8000000000008002UL, 0x8000000000000080UL, + 0x000000000000800aUL, 0x800000008000000aUL, + 0x8000000080008081UL, 0x8000000000008080UL, + 0x0000000080000001UL, 0x8000000080008008UL +}; + +/* Indeces used in swap and rotate operation. */ +#define KI_0 6 +#define KI_1 12 +#define KI_2 18 +#define KI_3 24 +#define KI_4 3 +#define KI_5 9 +#define KI_6 10 +#define KI_7 16 +#define KI_8 22 +#define KI_9 1 +#define KI_10 7 +#define KI_11 13 +#define KI_12 19 +#define KI_13 20 +#define KI_14 4 +#define KI_15 5 +#define KI_16 11 +#define KI_17 17 +#define KI_18 23 +#define KI_19 2 +#define KI_20 8 +#define KI_21 14 +#define KI_22 15 +#define KI_23 21 + +/* Number of bits to rotate in swap and rotate operation. */ +#define KR_0 44 +#define KR_1 43 +#define KR_2 21 +#define KR_3 14 +#define KR_4 28 +#define KR_5 20 +#define KR_6 3 +#define KR_7 45 +#define KR_8 61 +#define KR_9 1 +#define KR_10 6 +#define KR_11 25 +#define KR_12 8 +#define KR_13 18 +#define KR_14 27 +#define KR_15 36 +#define KR_16 10 +#define KR_17 15 +#define KR_18 56 +#define KR_19 62 +#define KR_20 55 +#define KR_21 39 +#define KR_22 41 +#define KR_23 2 + +/* Mix the XOR of the column's values into each number by column. + * + * s The state. + * b Temporary array of XORed column values. + * x The index of the column. + * t Temporary variable. + */ +#define COL_MIX(s, b, x, t) \ +do \ +{ \ + b[0] = s[0] ^ s[5] ^ s[10] ^ s[15] ^ s[20]; \ + b[1] = s[1] ^ s[6] ^ s[11] ^ s[16] ^ s[21]; \ + b[2] = s[2] ^ s[7] ^ s[12] ^ s[17] ^ s[22]; \ + b[3] = s[3] ^ s[8] ^ s[13] ^ s[18] ^ s[23]; \ + b[4] = s[4] ^ s[9] ^ s[14] ^ s[19] ^ s[24]; \ + t = b[(0 + 4) % 5] ^ ROTL64(b[(0 + 1) % 5], 1); \ + s[ 0] ^= t; s[ 5] ^= t; s[10] ^= t; s[15] ^= t; s[20] ^= t; \ + t = b[(1 + 4) % 5] ^ ROTL64(b[(1 + 1) % 5], 1); \ + s[ 1] ^= t; s[ 6] ^= t; s[11] ^= t; s[16] ^= t; s[21] ^= t; \ + t = b[(2 + 4) % 5] ^ ROTL64(b[(2 + 1) % 5], 1); \ + s[ 2] ^= t; s[ 7] ^= t; s[12] ^= t; s[17] ^= t; s[22] ^= t; \ + t = b[(3 + 4) % 5] ^ ROTL64(b[(3 + 1) % 5], 1); \ + s[ 3] ^= t; s[ 8] ^= t; s[13] ^= t; s[18] ^= t; s[23] ^= t; \ + t = b[(4 + 4) % 5] ^ ROTL64(b[(4 + 1) % 5], 1); \ + s[ 4] ^= t; s[ 9] ^= t; s[14] ^= t; s[19] ^= t; s[24] ^= t; \ +} \ +while (0) + +#define S(s1, i) ROTL64(s1[KI_##i], KR_##i) + +#ifdef SHA3_BY_SPEC +/* Mix the row values. + * BMI1 has ANDN instruction ((~a) & b) - Haswell and above. + * + * s2 The new state. + * s1 The current state. + * b Temporary array of XORed row values. + * t0 Temporary variable. (Unused) + * t1 Temporary variable. (Unused) + */ +#define ROW_MIX(s2, s1, b, t0, t1) \ +do \ +{ \ + b[0] = s1[0]; \ + b[1] = S(s1, 0); \ + b[2] = S(s1, 1); \ + b[3] = S(s1, 2); \ + b[4] = S(s1, 3); \ + s2[0] = b[0] ^ (~b[1] & b[2]); \ + s2[1] = b[1] ^ (~b[2] & b[3]); \ + s2[2] = b[2] ^ (~b[3] & b[4]); \ + s2[3] = b[3] ^ (~b[4] & b[0]); \ + s2[4] = b[4] ^ (~b[0] & b[1]); \ + b[0] = S(s1, 4); \ + b[1] = S(s1, 5); \ + b[2] = S(s1, 6); \ + b[3] = S(s1, 7); \ + b[4] = S(s1, 8); \ + s2[5] = b[0] ^ (~b[1] & b[2]); \ + s2[6] = b[1] ^ (~b[2] & b[3]); \ + s2[7] = b[2] ^ (~b[3] & b[4]); \ + s2[8] = b[3] ^ (~b[4] & b[0]); \ + s2[9] = b[4] ^ (~b[0] & b[1]); \ + b[0] = S(s1, 9); \ + b[1] = S(s1, 10); \ + b[2] = S(s1, 11); \ + b[3] = S(s1, 12); \ + b[4] = S(s1, 13); \ + s2[10] = b[0] ^ (~b[1] & b[2]); \ + s2[11] = b[1] ^ (~b[2] & b[3]); \ + s2[12] = b[2] ^ (~b[3] & b[4]); \ + s2[13] = b[3] ^ (~b[4] & b[0]); \ + s2[14] = b[4] ^ (~b[0] & b[1]); \ + b[0] = S(s1, 14); \ + b[1] = S(s1, 15); \ + b[2] = S(s1, 16); \ + b[3] = S(s1, 17); \ + b[4] = S(s1, 18); \ + s2[15] = b[0] ^ (~b[1] & b[2]); \ + s2[16] = b[1] ^ (~b[2] & b[3]); \ + s2[17] = b[2] ^ (~b[3] & b[4]); \ + s2[18] = b[3] ^ (~b[4] & b[0]); \ + s2[19] = b[4] ^ (~b[0] & b[1]); \ + b[0] = S(s1, 19); \ + b[1] = S(s1, 20); \ + b[2] = S(s1, 21); \ + b[3] = S(s1, 22); \ + b[4] = S(s1, 23); \ + s2[20] = b[0] ^ (~b[1] & b[2]); \ + s2[21] = b[1] ^ (~b[2] & b[3]); \ + s2[22] = b[2] ^ (~b[3] & b[4]); \ + s2[23] = b[3] ^ (~b[4] & b[0]); \ + s2[24] = b[4] ^ (~b[0] & b[1]); \ +} \ +while (0) +#else +/* Mix the row values. + * a ^ (~b & c) == a ^ (c & (b ^ c)) == (a ^ b) ^ (b | c) + * + * s2 The new state. + * s1 The current state. + * b Temporary array of XORed row values. + * t12 Temporary variable. + * t34 Temporary variable. + */ +#define ROW_MIX(s2, s1, b, t12, t34) \ +do \ +{ \ + b[0] = s1[0]; \ + b[1] = S(s1, 0); \ + b[2] = S(s1, 1); \ + b[3] = S(s1, 2); \ + b[4] = S(s1, 3); \ + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); \ + s2[0] = b[0] ^ (b[2] & t12); \ + s2[1] = t12 ^ (b[2] | b[3]); \ + s2[2] = b[2] ^ (b[4] & t34); \ + s2[3] = t34 ^ (b[4] | b[0]); \ + s2[4] = b[4] ^ (b[1] & (b[0] ^ b[1])); \ + b[0] = S(s1, 4); \ + b[1] = S(s1, 5); \ + b[2] = S(s1, 6); \ + b[3] = S(s1, 7); \ + b[4] = S(s1, 8); \ + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); \ + s2[5] = b[0] ^ (b[2] & t12); \ + s2[6] = t12 ^ (b[2] | b[3]); \ + s2[7] = b[2] ^ (b[4] & t34); \ + s2[8] = t34 ^ (b[4] | b[0]); \ + s2[9] = b[4] ^ (b[1] & (b[0] ^ b[1])); \ + b[0] = S(s1, 9); \ + b[1] = S(s1, 10); \ + b[2] = S(s1, 11); \ + b[3] = S(s1, 12); \ + b[4] = S(s1, 13); \ + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); \ + s2[10] = b[0] ^ (b[2] & t12); \ + s2[11] = t12 ^ (b[2] | b[3]); \ + s2[12] = b[2] ^ (b[4] & t34); \ + s2[13] = t34 ^ (b[4] | b[0]); \ + s2[14] = b[4] ^ (b[1] & (b[0] ^ b[1])); \ + b[0] = S(s1, 14); \ + b[1] = S(s1, 15); \ + b[2] = S(s1, 16); \ + b[3] = S(s1, 17); \ + b[4] = S(s1, 18); \ + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); \ + s2[15] = b[0] ^ (b[2] & t12); \ + s2[16] = t12 ^ (b[2] | b[3]); \ + s2[17] = b[2] ^ (b[4] & t34); \ + s2[18] = t34 ^ (b[4] | b[0]); \ + s2[19] = b[4] ^ (b[1] & (b[0] ^ b[1])); \ + b[0] = S(s1, 19); \ + b[1] = S(s1, 20); \ + b[2] = S(s1, 21); \ + b[3] = S(s1, 22); \ + b[4] = S(s1, 23); \ + t12 = (b[1] ^ b[2]); t34 = (b[3] ^ b[4]); \ + s2[20] = b[0] ^ (b[2] & t12); \ + s2[21] = t12 ^ (b[2] | b[3]); \ + s2[22] = b[2] ^ (b[4] & t34); \ + s2[23] = t34 ^ (b[4] | b[0]); \ + s2[24] = b[4] ^ (b[1] & (b[0] ^ b[1])); \ +} \ +while (0) +#endif /* SHA3_BY_SPEC */ + +/* The block operation performed on the state. + * + * s The state. + */ +static void BlockSha3(word64 *s) +{ + word64 n[25]; + word64 b[5]; + word64 t0; +#ifndef SHA3_BY_SPEC + word64 t1; +#endif + byte i; + + for (i = 0; i < 24; i += 2) + { + COL_MIX(s, b, x, t0); + ROW_MIX(n, s, b, t0, t1); + n[0] ^= hash_keccak_r[i]; + + COL_MIX(n, b, x, t0); + ROW_MIX(s, n, b, t0, t1); + s[0] ^= hash_keccak_r[i+1]; + } +} +#endif /* WOLFSSL_SHA3_SMALL */ + +/* Convert the array of bytes, in little-endian order, to a 64-bit integer. + * + * a Array of bytes. + * returns a 64-bit integer. + */ +static word64 Load64BitBigEndian(const byte* a) +{ +#ifdef BIG_ENDIAN_ORDER + word64 n = 0; + int i; + + for (i = 0; i < 8; i++) + n |= (word64)a[i] << (8 * i); + + return n; +#else + return *(word64*)a; +#endif +} + +/* Initialize the state for a SHA3-224 hash operation. + * + * sha3 wc_Sha3 object holding state. + * returns 0 on success. + */ +static int InitSha3(wc_Sha3* sha3) +{ + int i; + + for (i = 0; i < 25; i++) + sha3->s[i] = 0; + sha3->i = 0; + + return 0; +} + +/* Update the SHA-3 hash state with message data. + * + * sha3 wc_Sha3 object holding state. + * data Message data to be hashed. + * len Length of the message data. + * p Number of 64-bit numbers in a block of data to process. + * returns 0 on success. + */ +static int Sha3Update(wc_Sha3* sha3, const byte* data, word32 len, byte p) +{ + byte i; + byte l; + byte *t; + + if (sha3->i > 0) + { + l = p * 8 - sha3->i; + if (l > len) { + l = (byte)len; + } + + t = &sha3->t[sha3->i]; + for (i = 0; i < l; i++) + t[i] = data[i]; + data += i; + len -= i; + sha3->i += i; + + if (sha3->i == p * 8) + { + for (i = 0; i < p; i++) + sha3->s[i] ^= Load64BitBigEndian(sha3->t + 8 * i); + BlockSha3(sha3->s); + sha3->i = 0; + } + } + while (len >= ((word32)(p * 8))) + { + for (i = 0; i < p; i++) + sha3->s[i] ^= Load64BitBigEndian(data + 8 * i); + BlockSha3(sha3->s); + len -= p * 8; + data += p * 8; + } + for (i = 0; i < len; i++) + sha3->t[i] = data[i]; + sha3->i += i; + + return 0; +} + +/* Calculate the SHA-3 hash based on all the message data seen. + * + * sha3 wc_Sha3 object holding state. + * hash Buffer to hold the hash result. + * p Number of 64-bit numbers in a block of data to process. + * len Number of bytes in output. + * returns 0 on success. + */ +static int Sha3Final(wc_Sha3* sha3, byte* hash, byte p, byte l) +{ + byte i; + byte *s8 = (byte *)sha3->s; + + sha3->t[p * 8 - 1] = 0x00; + sha3->t[ sha3->i] = 0x06; + sha3->t[p * 8 - 1] |= 0x80; + for (i=sha3->i + 1; i < p * 8 - 1; i++) + sha3->t[i] = 0; + for (i = 0; i < p; i++) + sha3->s[i] ^= Load64BitBigEndian(sha3->t + 8 * i); + BlockSha3(sha3->s); +#if defined(BIG_ENDIAN_ORDER) + ByteReverseWords64(sha3->s, sha3->s, ((l+7)/8)*8); +#endif + for (i = 0; i < l; i++) + hash[i] = s8[i]; + + return 0; +} + +/* Initialize the state for a SHA-3 hash operation. + * + * sha3 wc_Sha3 object holding state. + * heap Heap reference for dynamic memory allocation. (Used in async ops.) + * devId Device identifier for asynchronous operation. + * returns 0 on success. + */ +static int wc_InitSha3(wc_Sha3* sha3, void* heap, int devId) +{ + int ret = 0; + + if (sha3 == NULL) + return BAD_FUNC_ARG; + + sha3->heap = heap; + ret = InitSha3(sha3); + if (ret != 0) + return ret; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA3) + ret = wolfAsync_DevCtxInit(&sha3->asyncDev, + WOLFSSL_ASYNC_MARKER_SHA3, sha3->heap, devId); +#else + (void)devId; +#endif /* WOLFSSL_ASYNC_CRYPT */ + + return ret; +} + +/* Update the SHA-3 hash state with message data. + * + * sha3 wc_Sha3 object holding state. + * data Message data to be hashed. + * len Length of the message data. + * p Number of 64-bit numbers in a block of data to process. + * returns 0 on success. + */ +static int wc_Sha3Update(wc_Sha3* sha3, const byte* data, word32 len, byte p) +{ + int ret; + + if (sha3 == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA3) + if (sha3->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA3) { + #if defined(HAVE_INTEL_QA) && defined(QAT_V2) + /* QAT only supports SHA3_256 */ + if (p == WC_SHA3_256_COUNT) { + ret = IntelQaSymSha3(&sha3->asyncDev, NULL, data, len); + if (ret != NOT_COMPILED_IN) + return ret; + /* fall-through when unavailable */ + } + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + ret = Sha3Update(sha3, data, len, p); + + return ret; +} + +/* Calculate the SHA-3 hash based on all the message data seen. + * + * sha3 wc_Sha3 object holding state. + * hash Buffer to hold the hash result. + * p Number of 64-bit numbers in a block of data to process. + * len Number of bytes in output. + * returns 0 on success. + */ +static int wc_Sha3Final(wc_Sha3* sha3, byte* hash, byte p, byte len) +{ + int ret; + + if (sha3 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA3) + if (sha3->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA3) { + #if defined(HAVE_INTEL_QA) && defined(QAT_V2) + /* QAT only supports SHA3_256 */ + /* QAT SHA-3 only supported on v2 (8970 or later cards) */ + if (len == WC_SHA3_256_DIGEST_SIZE) { + ret = IntelQaSymSha3(&sha3->asyncDev, hash, NULL, len); + if (ret != NOT_COMPILED_IN) + return ret; + /* fall-through when unavailable */ + } + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + ret = Sha3Final(sha3, hash, p, len); + if (ret != 0) + return ret; + + return InitSha3(sha3); /* reset state */ +} + +/* Dispose of any dynamically allocated data from the SHA3-384 operation. + * (Required for async ops.) + * + * sha3 wc_Sha3 object holding state. + * returns 0 on success. + */ +static void wc_Sha3Free(wc_Sha3* sha3) +{ + (void)sha3; + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA3) + if (sha3 == NULL) + return; + + wolfAsync_DevCtxFree(&sha3->asyncDev, WOLFSSL_ASYNC_MARKER_SHA3); +#endif /* WOLFSSL_ASYNC_CRYPT */ +} + + +/* Copy the state of the SHA3 operation. + * + * src wc_Sha3 object holding state top copy. + * dst wc_Sha3 object to copy into. + * returns 0 on success. + */ +static int wc_Sha3Copy(wc_Sha3* src, wc_Sha3* dst) +{ + int ret = 0; + + if (src == NULL || dst == NULL) + return BAD_FUNC_ARG; + + XMEMCPY(dst, src, sizeof(wc_Sha3)); + +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev); +#endif +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + dst->flags |= WC_HASH_FLAG_ISCOPY; +#endif + + return ret; +} + +/* Calculate the SHA3-224 hash based on all the message data so far. + * More message data can be added, after this operation, using the current + * state. + * + * sha3 wc_Sha3 object holding state. + * hash Buffer to hold the hash result. Must be at least 28 bytes. + * p Number of 64-bit numbers in a block of data to process. + * len Number of bytes in output. + * returns 0 on success. + */ +static int wc_Sha3GetHash(wc_Sha3* sha3, byte* hash, byte p, byte len) +{ + int ret; + wc_Sha3 tmpSha3; + + if (sha3 == NULL || hash == NULL) + return BAD_FUNC_ARG; + + ret = wc_Sha3Copy(sha3, &tmpSha3); + if (ret == 0) { + ret = wc_Sha3Final(&tmpSha3, hash, p, len); + } + return ret; +} + + +/* Initialize the state for a SHA3-224 hash operation. + * + * sha3 wc_Sha3 object holding state. + * heap Heap reference for dynamic memory allocation. (Used in async ops.) + * devId Device identifier for asynchronous operation. + * returns 0 on success. + */ +int wc_InitSha3_224(wc_Sha3* sha3, void* heap, int devId) +{ + return wc_InitSha3(sha3, heap, devId); +} + +/* Update the SHA3-224 hash state with message data. + * + * sha3 wc_Sha3 object holding state. + * data Message data to be hashed. + * len Length of the message data. + * returns 0 on success. + */ +int wc_Sha3_224_Update(wc_Sha3* sha3, const byte* data, word32 len) +{ + return wc_Sha3Update(sha3, data, len, WC_SHA3_224_COUNT); +} + +/* Calculate the SHA3-224 hash based on all the message data seen. + * The state is initialized ready for a new message to hash. + * + * sha3 wc_Sha3 object holding state. + * hash Buffer to hold the hash result. Must be at least 28 bytes. + * returns 0 on success. + */ +int wc_Sha3_224_Final(wc_Sha3* sha3, byte* hash) +{ + return wc_Sha3Final(sha3, hash, WC_SHA3_224_COUNT, WC_SHA3_224_DIGEST_SIZE); +} + +/* Dispose of any dynamically allocated data from the SHA3-224 operation. + * (Required for async ops.) + * + * sha3 wc_Sha3 object holding state. + * returns 0 on success. + */ +void wc_Sha3_224_Free(wc_Sha3* sha3) +{ + wc_Sha3Free(sha3); +} + +/* Calculate the SHA3-224 hash based on all the message data so far. + * More message data can be added, after this operation, using the current + * state. + * + * sha3 wc_Sha3 object holding state. + * hash Buffer to hold the hash result. Must be at least 28 bytes. + * returns 0 on success. + */ +int wc_Sha3_224_GetHash(wc_Sha3* sha3, byte* hash) +{ + return wc_Sha3GetHash(sha3, hash, WC_SHA3_224_COUNT, WC_SHA3_224_DIGEST_SIZE); +} + +/* Copy the state of the SHA3-224 operation. + * + * src wc_Sha3 object holding state top copy. + * dst wc_Sha3 object to copy into. + * returns 0 on success. + */ +int wc_Sha3_224_Copy(wc_Sha3* src, wc_Sha3* dst) +{ + return wc_Sha3Copy(src, dst); +} + + +/* Initialize the state for a SHA3-256 hash operation. + * + * sha3 wc_Sha3 object holding state. + * heap Heap reference for dynamic memory allocation. (Used in async ops.) + * devId Device identifier for asynchronous operation. + * returns 0 on success. + */ +int wc_InitSha3_256(wc_Sha3* sha3, void* heap, int devId) +{ + return wc_InitSha3(sha3, heap, devId); +} + +/* Update the SHA3-256 hash state with message data. + * + * sha3 wc_Sha3 object holding state. + * data Message data to be hashed. + * len Length of the message data. + * returns 0 on success. + */ +int wc_Sha3_256_Update(wc_Sha3* sha3, const byte* data, word32 len) +{ + return wc_Sha3Update(sha3, data, len, WC_SHA3_256_COUNT); +} + +/* Calculate the SHA3-256 hash based on all the message data seen. + * The state is initialized ready for a new message to hash. + * + * sha3 wc_Sha3 object holding state. + * hash Buffer to hold the hash result. Must be at least 32 bytes. + * returns 0 on success. + */ +int wc_Sha3_256_Final(wc_Sha3* sha3, byte* hash) +{ + return wc_Sha3Final(sha3, hash, WC_SHA3_256_COUNT, WC_SHA3_256_DIGEST_SIZE); +} + +/* Dispose of any dynamically allocated data from the SHA3-256 operation. + * (Required for async ops.) + * + * sha3 wc_Sha3 object holding state. + * returns 0 on success. + */ +void wc_Sha3_256_Free(wc_Sha3* sha3) +{ + wc_Sha3Free(sha3); +} + +/* Calculate the SHA3-256 hash based on all the message data so far. + * More message data can be added, after this operation, using the current + * state. + * + * sha3 wc_Sha3 object holding state. + * hash Buffer to hold the hash result. Must be at least 32 bytes. + * returns 0 on success. + */ +int wc_Sha3_256_GetHash(wc_Sha3* sha3, byte* hash) +{ + return wc_Sha3GetHash(sha3, hash, WC_SHA3_256_COUNT, WC_SHA3_256_DIGEST_SIZE); +} + +/* Copy the state of the SHA3-256 operation. + * + * src wc_Sha3 object holding state top copy. + * dst wc_Sha3 object to copy into. + * returns 0 on success. + */ +int wc_Sha3_256_Copy(wc_Sha3* src, wc_Sha3* dst) +{ + return wc_Sha3Copy(src, dst); +} + + +/* Initialize the state for a SHA3-384 hash operation. + * + * sha3 wc_Sha3 object holding state. + * heap Heap reference for dynamic memory allocation. (Used in async ops.) + * devId Device identifier for asynchronous operation. + * returns 0 on success. + */ +int wc_InitSha3_384(wc_Sha3* sha3, void* heap, int devId) +{ + return wc_InitSha3(sha3, heap, devId); +} + +/* Update the SHA3-384 hash state with message data. + * + * sha3 wc_Sha3 object holding state. + * data Message data to be hashed. + * len Length of the message data. + * returns 0 on success. + */ +int wc_Sha3_384_Update(wc_Sha3* sha3, const byte* data, word32 len) +{ + return wc_Sha3Update(sha3, data, len, WC_SHA3_384_COUNT); +} + +/* Calculate the SHA3-384 hash based on all the message data seen. + * The state is initialized ready for a new message to hash. + * + * sha3 wc_Sha3 object holding state. + * hash Buffer to hold the hash result. Must be at least 48 bytes. + * returns 0 on success. + */ +int wc_Sha3_384_Final(wc_Sha3* sha3, byte* hash) +{ + return wc_Sha3Final(sha3, hash, WC_SHA3_384_COUNT, WC_SHA3_384_DIGEST_SIZE); +} + +/* Dispose of any dynamically allocated data from the SHA3-384 operation. + * (Required for async ops.) + * + * sha3 wc_Sha3 object holding state. + * returns 0 on success. + */ +void wc_Sha3_384_Free(wc_Sha3* sha3) +{ + wc_Sha3Free(sha3); +} + +/* Calculate the SHA3-384 hash based on all the message data so far. + * More message data can be added, after this operation, using the current + * state. + * + * sha3 wc_Sha3 object holding state. + * hash Buffer to hold the hash result. Must be at least 48 bytes. + * returns 0 on success. + */ +int wc_Sha3_384_GetHash(wc_Sha3* sha3, byte* hash) +{ + return wc_Sha3GetHash(sha3, hash, WC_SHA3_384_COUNT, WC_SHA3_384_DIGEST_SIZE); +} + +/* Copy the state of the SHA3-384 operation. + * + * src wc_Sha3 object holding state top copy. + * dst wc_Sha3 object to copy into. + * returns 0 on success. + */ +int wc_Sha3_384_Copy(wc_Sha3* src, wc_Sha3* dst) +{ + return wc_Sha3Copy(src, dst); +} + + +/* Initialize the state for a SHA3-512 hash operation. + * + * sha3 wc_Sha3 object holding state. + * heap Heap reference for dynamic memory allocation. (Used in async ops.) + * devId Device identifier for asynchronous operation. + * returns 0 on success. + */ +int wc_InitSha3_512(wc_Sha3* sha3, void* heap, int devId) +{ + return wc_InitSha3(sha3, heap, devId); +} + +/* Update the SHA3-512 hash state with message data. + * + * sha3 wc_Sha3 object holding state. + * data Message data to be hashed. + * len Length of the message data. + * returns 0 on success. + */ +int wc_Sha3_512_Update(wc_Sha3* sha3, const byte* data, word32 len) +{ + return wc_Sha3Update(sha3, data, len, WC_SHA3_512_COUNT); +} + +/* Calculate the SHA3-512 hash based on all the message data seen. + * The state is initialized ready for a new message to hash. + * + * sha3 wc_Sha3 object holding state. + * hash Buffer to hold the hash result. Must be at least 64 bytes. + * returns 0 on success. + */ +int wc_Sha3_512_Final(wc_Sha3* sha3, byte* hash) +{ + return wc_Sha3Final(sha3, hash, WC_SHA3_512_COUNT, WC_SHA3_512_DIGEST_SIZE); +} + +/* Dispose of any dynamically allocated data from the SHA3-512 operation. + * (Required for async ops.) + * + * sha3 wc_Sha3 object holding state. + * returns 0 on success. + */ +void wc_Sha3_512_Free(wc_Sha3* sha3) +{ + wc_Sha3Free(sha3); +} + +/* Calculate the SHA3-512 hash based on all the message data so far. + * More message data can be added, after this operation, using the current + * state. + * + * sha3 wc_Sha3 object holding state. + * hash Buffer to hold the hash result. Must be at least 64 bytes. + * returns 0 on success. + */ +int wc_Sha3_512_GetHash(wc_Sha3* sha3, byte* hash) +{ + return wc_Sha3GetHash(sha3, hash, WC_SHA3_512_COUNT, WC_SHA3_512_DIGEST_SIZE); +} + +/* Copy the state of the SHA3-512 operation. + * + * src wc_Sha3 object holding state top copy. + * dst wc_Sha3 object to copy into. + * returns 0 on success. + */ +int wc_Sha3_512_Copy(wc_Sha3* src, wc_Sha3* dst) +{ + return wc_Sha3Copy(src, dst); +} + +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) +int wc_Sha3_SetFlags(wc_Sha3* sha3, word32 flags) +{ + if (sha3) { + sha3->flags = flags; + } + return 0; +} +int wc_Sha3_GetFlags(wc_Sha3* sha3, word32* flags) +{ + if (sha3 && flags) { + *flags = sha3->flags; + } + return 0; +} +#endif + +#endif /* WOLFSSL_SHA3 */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/sha512.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/sha512.c new file mode 100755 index 0000000..f327df9 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/sha512.c @@ -0,0 +1,1219 @@ +/* sha512.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#if defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384) + +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + + /* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */ + #define FIPS_NO_WRAPPERS + + #ifdef USE_WINDOWS_API + #pragma code_seg(".fipsA$k") + #pragma const_seg(".fipsB$k") + #endif +#endif + +#include +#include +#include +#include + +/* deprecated USE_SLOW_SHA2 (replaced with USE_SLOW_SHA512) */ +#if defined(USE_SLOW_SHA2) && !defined(USE_SLOW_SHA512) + #define USE_SLOW_SHA512 +#endif + +/* fips wrapper calls, user can call direct */ +#if defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) + + #ifdef WOLFSSL_SHA512 + + int wc_InitSha512(wc_Sha512* sha) + { + if (sha == NULL) { + return BAD_FUNC_ARG; + } + + return InitSha512_fips(sha); + } + int wc_InitSha512_ex(wc_Sha512* sha, void* heap, int devId) + { + (void)heap; + (void)devId; + if (sha == NULL) { + return BAD_FUNC_ARG; + } + return InitSha512_fips(sha); + } + int wc_Sha512Update(wc_Sha512* sha, const byte* data, word32 len) + { + if (sha == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + + return Sha512Update_fips(sha, data, len); + } + int wc_Sha512Final(wc_Sha512* sha, byte* out) + { + if (sha == NULL || out == NULL) { + return BAD_FUNC_ARG; + } + + return Sha512Final_fips(sha, out); + } + void wc_Sha512Free(wc_Sha512* sha) + { + (void)sha; + /* Not supported in FIPS */ + } + #endif + + #if defined(WOLFSSL_SHA384) || defined(HAVE_AESGCM) + int wc_InitSha384(wc_Sha384* sha) + { + if (sha == NULL) { + return BAD_FUNC_ARG; + } + return InitSha384_fips(sha); + } + int wc_InitSha384_ex(wc_Sha384* sha, void* heap, int devId) + { + (void)heap; + (void)devId; + if (sha == NULL) { + return BAD_FUNC_ARG; + } + return InitSha384_fips(sha); + } + int wc_Sha384Update(wc_Sha384* sha, const byte* data, word32 len) + { + if (sha == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + return Sha384Update_fips(sha, data, len); + } + int wc_Sha384Final(wc_Sha384* sha, byte* out) + { + if (sha == NULL || out == NULL) { + return BAD_FUNC_ARG; + } + return Sha384Final_fips(sha, out); + } + void wc_Sha384Free(wc_Sha384* sha) + { + (void)sha; + /* Not supported in FIPS */ + } + #endif /* WOLFSSL_SHA384 || HAVE_AESGCM */ + +#else /* else build without fips, or for FIPS v2 */ + +#include + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + + +#if defined(USE_INTEL_SPEEDUP) + #if defined(__GNUC__) && ((__GNUC__ < 4) || \ + (__GNUC__ == 4 && __GNUC_MINOR__ <= 8)) + #undef NO_AVX2_SUPPORT + #define NO_AVX2_SUPPORT + #endif + #if defined(__clang__) && ((__clang_major__ < 3) || \ + (__clang_major__ == 3 && __clang_minor__ <= 5)) + #define NO_AVX2_SUPPORT + #elif defined(__clang__) && defined(NO_AVX2_SUPPORT) + #undef NO_AVX2_SUPPORT + #endif + + #define HAVE_INTEL_AVX1 + #ifndef NO_AVX2_SUPPORT + #define HAVE_INTEL_AVX2 + #endif +#endif + +#if defined(HAVE_INTEL_AVX1) + /* #define DEBUG_XMM */ +#endif + +#if defined(HAVE_INTEL_AVX2) + #define HAVE_INTEL_RORX + /* #define DEBUG_YMM */ +#endif + +#if defined(HAVE_BYTEREVERSE64) && \ + !defined(HAVE_INTEL_AVX1) && !defined(HAVE_INTEL_AVX2) + #define ByteReverseWords64(out, in, size) ByteReverseWords64_1(out, size) + #define ByteReverseWords64_1(buf, size) \ + { unsigned int i ;\ + for(i=0; i< size/sizeof(word64); i++){\ + __asm__ volatile("bswapq %0":"+r"(buf[i])::) ;\ + }\ + } +#endif + +#if defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH) + /* functions defined in wolfcrypt/src/port/caam/caam_sha.c */ + +#else + +#ifdef WOLFSSL_SHA512 + +static int InitSha512(wc_Sha512* sha512) +{ + if (sha512 == NULL) + return BAD_FUNC_ARG; + + sha512->digest[0] = W64LIT(0x6a09e667f3bcc908); + sha512->digest[1] = W64LIT(0xbb67ae8584caa73b); + sha512->digest[2] = W64LIT(0x3c6ef372fe94f82b); + sha512->digest[3] = W64LIT(0xa54ff53a5f1d36f1); + sha512->digest[4] = W64LIT(0x510e527fade682d1); + sha512->digest[5] = W64LIT(0x9b05688c2b3e6c1f); + sha512->digest[6] = W64LIT(0x1f83d9abfb41bd6b); + sha512->digest[7] = W64LIT(0x5be0cd19137e2179); + + sha512->buffLen = 0; + sha512->loLen = 0; + sha512->hiLen = 0; + +#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + + sha512->ctx.sha_type = SHA2_512; + /* always start firstblock = 1 when using hw engine */ + sha512->ctx.isfirstblock = 1; + if(sha512->ctx.mode == ESP32_SHA_HW) { + /* release hw */ + esp_sha_hw_unlock(); + } + /* always set mode as INIT + * whether using HW or SW is detemined at first call of update() + */ + sha512->ctx.mode = ESP32_SHA_INIT; +#endif + return 0; +} + +#endif /* WOLFSSL_SHA512 */ + +/* Hardware Acceleration */ +#if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + +#ifdef WOLFSSL_SHA512 + + /***** + Intel AVX1/AVX2 Macro Control Structure + + #if defined(HAVE_INteL_SPEEDUP) + #define HAVE_INTEL_AVX1 + #define HAVE_INTEL_AVX2 + #endif + + int InitSha512(wc_Sha512* sha512) { + Save/Recover XMM, YMM + ... + + Check Intel AVX cpuid flags + } + + #if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2) + Transform_Sha512_AVX1(); # Function prototype + Transform_Sha512_AVX2(); # + #endif + + _Transform_Sha512() { # Native Transform Function body + + } + + int Sha512Update() { + Save/Recover XMM, YMM + ... + } + + int Sha512Final() { + Save/Recover XMM, YMM + ... + } + + + #if defined(HAVE_INTEL_AVX1) + + XMM Instructions/INLINE asm Definitions + + #endif + + #if defined(HAVE_INTEL_AVX2) + + YMM Instructions/INLINE asm Definitions + + #endif + + #if defnied(HAVE_INTEL_AVX1) + + int Transform_Sha512_AVX1() { + Stitched Message Sched/Round + } + + #endif + + #if defnied(HAVE_INTEL_AVX2) + + int Transform_Sha512_AVX2() { + Stitched Message Sched/Round + } + #endif + + */ + + + /* Each platform needs to query info type 1 from cpuid to see if aesni is + * supported. Also, let's setup a macro for proper linkage w/o ABI conflicts + */ + +#ifdef __cplusplus + extern "C" { +#endif + + #if defined(HAVE_INTEL_AVX1) + extern int Transform_Sha512_AVX1(wc_Sha512 *sha512); + extern int Transform_Sha512_AVX1_Len(wc_Sha512 *sha512, word32 len); + #endif + #if defined(HAVE_INTEL_AVX2) + extern int Transform_Sha512_AVX2(wc_Sha512 *sha512); + extern int Transform_Sha512_AVX2_Len(wc_Sha512 *sha512, word32 len); + #if defined(HAVE_INTEL_RORX) + extern int Transform_Sha512_AVX1_RORX(wc_Sha512 *sha512); + extern int Transform_Sha512_AVX1_RORX_Len(wc_Sha512 *sha512, + word32 len); + extern int Transform_Sha512_AVX2_RORX(wc_Sha512 *sha512); + extern int Transform_Sha512_AVX2_RORX_Len(wc_Sha512 *sha512, + word32 len); + #endif + #endif + +#ifdef __cplusplus + } /* extern "C" */ +#endif + + static int _Transform_Sha512(wc_Sha512 *sha512); + static int (*Transform_Sha512_p)(wc_Sha512* sha512) = _Transform_Sha512; + static int (*Transform_Sha512_Len_p)(wc_Sha512* sha512, word32 len) = NULL; + static int transform_check = 0; + static int intel_flags; + #define Transform_Sha512(sha512) (*Transform_Sha512_p)(sha512) + #define Transform_Sha512_Len(sha512, len) \ + (*Transform_Sha512_Len_p)(sha512, len) + + static void Sha512_SetTransform() + { + if (transform_check) + return; + + intel_flags = cpuid_get_flags(); + + #if defined(HAVE_INTEL_AVX2) + if (IS_INTEL_AVX2(intel_flags)) { + #ifdef HAVE_INTEL_RORX + if (IS_INTEL_BMI2(intel_flags)) { + Transform_Sha512_p = Transform_Sha512_AVX2_RORX; + Transform_Sha512_Len_p = Transform_Sha512_AVX2_RORX_Len; + } + else + #endif + if (1) { + Transform_Sha512_p = Transform_Sha512_AVX2; + Transform_Sha512_Len_p = Transform_Sha512_AVX2_Len; + } + #ifdef HAVE_INTEL_RORX + else { + Transform_Sha512_p = Transform_Sha512_AVX1_RORX; + Transform_Sha512_Len_p = Transform_Sha512_AVX1_RORX_Len; + } + #endif + } + else + #endif + #if defined(HAVE_INTEL_AVX1) + if (IS_INTEL_AVX1(intel_flags)) { + Transform_Sha512_p = Transform_Sha512_AVX1; + Transform_Sha512_Len_p = Transform_Sha512_AVX1_Len; + } + else + #endif + Transform_Sha512_p = _Transform_Sha512; + + transform_check = 1; + } +#endif /* WOLFSSL_SHA512 */ + +#else + #define Transform_Sha512(sha512) _Transform_Sha512(sha512) + +#endif + +#ifdef WOLFSSL_SHA512 + +int wc_InitSha512_ex(wc_Sha512* sha512, void* heap, int devId) +{ + int ret = 0; + + if (sha512 == NULL) + return BAD_FUNC_ARG; + + sha512->heap = heap; + + ret = InitSha512(sha512); + if (ret != 0) + return ret; + +#if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + Sha512_SetTransform(); +#endif + +#ifdef WOLFSSL_SMALL_STACK_CACHE + sha512->W = NULL; +#endif + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA512) + ret = wolfAsync_DevCtxInit(&sha512->asyncDev, + WOLFSSL_ASYNC_MARKER_SHA512, sha512->heap, devId); +#else + (void)devId; +#endif /* WOLFSSL_ASYNC_CRYPT */ + + return ret; +} + +#endif /* WOLFSSL_SHA512 */ + + +static const word64 K512[80] = { + W64LIT(0x428a2f98d728ae22), W64LIT(0x7137449123ef65cd), + W64LIT(0xb5c0fbcfec4d3b2f), W64LIT(0xe9b5dba58189dbbc), + W64LIT(0x3956c25bf348b538), W64LIT(0x59f111f1b605d019), + W64LIT(0x923f82a4af194f9b), W64LIT(0xab1c5ed5da6d8118), + W64LIT(0xd807aa98a3030242), W64LIT(0x12835b0145706fbe), + W64LIT(0x243185be4ee4b28c), W64LIT(0x550c7dc3d5ffb4e2), + W64LIT(0x72be5d74f27b896f), W64LIT(0x80deb1fe3b1696b1), + W64LIT(0x9bdc06a725c71235), W64LIT(0xc19bf174cf692694), + W64LIT(0xe49b69c19ef14ad2), W64LIT(0xefbe4786384f25e3), + W64LIT(0x0fc19dc68b8cd5b5), W64LIT(0x240ca1cc77ac9c65), + W64LIT(0x2de92c6f592b0275), W64LIT(0x4a7484aa6ea6e483), + W64LIT(0x5cb0a9dcbd41fbd4), W64LIT(0x76f988da831153b5), + W64LIT(0x983e5152ee66dfab), W64LIT(0xa831c66d2db43210), + W64LIT(0xb00327c898fb213f), W64LIT(0xbf597fc7beef0ee4), + W64LIT(0xc6e00bf33da88fc2), W64LIT(0xd5a79147930aa725), + W64LIT(0x06ca6351e003826f), W64LIT(0x142929670a0e6e70), + W64LIT(0x27b70a8546d22ffc), W64LIT(0x2e1b21385c26c926), + W64LIT(0x4d2c6dfc5ac42aed), W64LIT(0x53380d139d95b3df), + W64LIT(0x650a73548baf63de), W64LIT(0x766a0abb3c77b2a8), + W64LIT(0x81c2c92e47edaee6), W64LIT(0x92722c851482353b), + W64LIT(0xa2bfe8a14cf10364), W64LIT(0xa81a664bbc423001), + W64LIT(0xc24b8b70d0f89791), W64LIT(0xc76c51a30654be30), + W64LIT(0xd192e819d6ef5218), W64LIT(0xd69906245565a910), + W64LIT(0xf40e35855771202a), W64LIT(0x106aa07032bbd1b8), + W64LIT(0x19a4c116b8d2d0c8), W64LIT(0x1e376c085141ab53), + W64LIT(0x2748774cdf8eeb99), W64LIT(0x34b0bcb5e19b48a8), + W64LIT(0x391c0cb3c5c95a63), W64LIT(0x4ed8aa4ae3418acb), + W64LIT(0x5b9cca4f7763e373), W64LIT(0x682e6ff3d6b2b8a3), + W64LIT(0x748f82ee5defb2fc), W64LIT(0x78a5636f43172f60), + W64LIT(0x84c87814a1f0ab72), W64LIT(0x8cc702081a6439ec), + W64LIT(0x90befffa23631e28), W64LIT(0xa4506cebde82bde9), + W64LIT(0xbef9a3f7b2c67915), W64LIT(0xc67178f2e372532b), + W64LIT(0xca273eceea26619c), W64LIT(0xd186b8c721c0c207), + W64LIT(0xeada7dd6cde0eb1e), W64LIT(0xf57d4f7fee6ed178), + W64LIT(0x06f067aa72176fba), W64LIT(0x0a637dc5a2c898a6), + W64LIT(0x113f9804bef90dae), W64LIT(0x1b710b35131c471b), + W64LIT(0x28db77f523047d84), W64LIT(0x32caab7b40c72493), + W64LIT(0x3c9ebe0a15c9bebc), W64LIT(0x431d67c49c100d4c), + W64LIT(0x4cc5d4becb3e42b6), W64LIT(0x597f299cfc657e2a), + W64LIT(0x5fcb6fab3ad6faec), W64LIT(0x6c44198c4a475817) +}; + +#define blk0(i) (W[i] = sha512->buffer[i]) + +#define blk2(i) (\ + W[ i & 15] += \ + s1(W[(i-2) & 15])+ \ + W[(i-7) & 15] + \ + s0(W[(i-15) & 15]) \ + ) + +#define Ch(x,y,z) (z ^ (x & (y ^ z))) +#define Maj(x,y,z) ((x & y) | (z & (x | y))) + +#define a(i) T[(0-i) & 7] +#define b(i) T[(1-i) & 7] +#define c(i) T[(2-i) & 7] +#define d(i) T[(3-i) & 7] +#define e(i) T[(4-i) & 7] +#define f(i) T[(5-i) & 7] +#define g(i) T[(6-i) & 7] +#define h(i) T[(7-i) & 7] + +#define S0(x) (rotrFixed64(x,28) ^ rotrFixed64(x,34) ^ rotrFixed64(x,39)) +#define S1(x) (rotrFixed64(x,14) ^ rotrFixed64(x,18) ^ rotrFixed64(x,41)) +#define s0(x) (rotrFixed64(x,1) ^ rotrFixed64(x,8) ^ (x>>7)) +#define s1(x) (rotrFixed64(x,19) ^ rotrFixed64(x,61) ^ (x>>6)) + +#define R(i) \ + h(i) += S1(e(i)) + Ch(e(i),f(i),g(i)) + K[i+j] + (j ? blk2(i) : blk0(i)); \ + d(i) += h(i); \ + h(i) += S0(a(i)) + Maj(a(i),b(i),c(i)) + +static int _Transform_Sha512(wc_Sha512* sha512) +{ + const word64* K = K512; + word32 j; + word64 T[8]; + +#ifdef WOLFSSL_SMALL_STACK_CACHE + word64* W = sha512->W; + if (W == NULL) { + W = (word64*) XMALLOC(sizeof(word64) * 16, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (W == NULL) + return MEMORY_E; + sha512->W = W; + } +#elif defined(WOLFSSL_SMALL_STACK) + word64* W; + W = (word64*) XMALLOC(sizeof(word64) * 16, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (W == NULL) + return MEMORY_E; +#else + word64 W[16]; +#endif + + /* Copy digest to working vars */ + XMEMCPY(T, sha512->digest, sizeof(T)); + +#ifdef USE_SLOW_SHA512 + /* over twice as small, but 50% slower */ + /* 80 operations, not unrolled */ + for (j = 0; j < 80; j += 16) { + int m; + for (m = 0; m < 16; m++) { /* braces needed here for macros {} */ + R(m); + } + } +#else + /* 80 operations, partially loop unrolled */ + for (j = 0; j < 80; j += 16) { + R( 0); R( 1); R( 2); R( 3); + R( 4); R( 5); R( 6); R( 7); + R( 8); R( 9); R(10); R(11); + R(12); R(13); R(14); R(15); + } +#endif /* USE_SLOW_SHA512 */ + + /* Add the working vars back into digest */ + sha512->digest[0] += a(0); + sha512->digest[1] += b(0); + sha512->digest[2] += c(0); + sha512->digest[3] += d(0); + sha512->digest[4] += e(0); + sha512->digest[5] += f(0); + sha512->digest[6] += g(0); + sha512->digest[7] += h(0); + + /* Wipe variables */ + ForceZero(W, sizeof(word64) * 16); + ForceZero(T, sizeof(T)); + +#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SMALL_STACK_CACHE) + XFREE(W, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return 0; +} + + +static WC_INLINE void AddLength(wc_Sha512* sha512, word32 len) +{ + word64 tmp = sha512->loLen; + if ( (sha512->loLen += len) < tmp) + sha512->hiLen++; /* carry low to high */ +} + +static WC_INLINE int Sha512Update(wc_Sha512* sha512, const byte* data, word32 len) +{ + int ret = 0; + /* do block size increments */ + byte* local = (byte*)sha512->buffer; + + /* check that internal buffLen is valid */ + if (sha512->buffLen >= WC_SHA512_BLOCK_SIZE) + return BUFFER_E; + + AddLength(sha512, len); + + if (sha512->buffLen > 0) { + word32 add = min(len, WC_SHA512_BLOCK_SIZE - sha512->buffLen); + if (add > 0) { + XMEMCPY(&local[sha512->buffLen], data, add); + + sha512->buffLen += add; + data += add; + len -= add; + } + + if (sha512->buffLen == WC_SHA512_BLOCK_SIZE) { + #if defined(LITTLE_ENDIAN_ORDER) + #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + if (!IS_INTEL_AVX1(intel_flags) && !IS_INTEL_AVX2(intel_flags)) + #endif + { + #if !defined(WOLFSSL_ESP32WROOM32_CRYPT) || \ + defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + ByteReverseWords64(sha512->buffer, sha512->buffer, + WC_SHA512_BLOCK_SIZE); + #endif + } + #endif + #if !defined(WOLFSSL_ESP32WROOM32_CRYPT) || \ + defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + ret = Transform_Sha512(sha512); + #else + if(sha512->ctx.mode == ESP32_SHA_INIT) { + esp_sha_try_hw_lock(&sha512->ctx); + } + ret = esp_sha512_process(sha512); + if(ret == 0 && sha512->ctx.mode == ESP32_SHA_SW){ + ret = Transform_Sha512(sha512); + } + #endif + if (ret == 0) + sha512->buffLen = 0; + else + len = 0; + } + } + +#if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + if (Transform_Sha512_Len_p != NULL) { + word32 blocksLen = len & ~(WC_SHA512_BLOCK_SIZE-1); + + if (blocksLen > 0) { + sha512->data = data; + /* Byte reversal performed in function if required. */ + Transform_Sha512_Len(sha512, blocksLen); + data += blocksLen; + len -= blocksLen; + } + } + else +#endif +#if !defined(LITTLE_ENDIAN_ORDER) || defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + { + while (len >= WC_SHA512_BLOCK_SIZE) { + XMEMCPY(local, data, WC_SHA512_BLOCK_SIZE); + + data += WC_SHA512_BLOCK_SIZE; + len -= WC_SHA512_BLOCK_SIZE; + + #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + if (!IS_INTEL_AVX1(intel_flags) && !IS_INTEL_AVX2(intel_flags)) + { + ByteReverseWords64(sha512->buffer, sha512->buffer, + WC_SHA512_BLOCK_SIZE); + } + #endif + /* Byte reversal performed in function if required. */ + ret = Transform_Sha512(sha512); + if (ret != 0) + break; + } + } +#else + { + while (len >= WC_SHA512_BLOCK_SIZE) { + XMEMCPY(local, data, WC_SHA512_BLOCK_SIZE); + + data += WC_SHA512_BLOCK_SIZE; + len -= WC_SHA512_BLOCK_SIZE; + #if !defined(WOLFSSL_ESP32WROOM32_CRYPT) || \ + defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + ByteReverseWords64(sha512->buffer, sha512->buffer, + WC_SHA512_BLOCK_SIZE); + #endif + #if !defined(WOLFSSL_ESP32WROOM32_CRYPT) || \ + defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + ret = Transform_Sha512(sha512); + #else + if(sha512->ctx.mode == ESP32_SHA_INIT) { + esp_sha_try_hw_lock(&sha512->ctx); + } + ret = esp_sha512_process(sha512); + if(ret == 0 && sha512->ctx.mode == ESP32_SHA_SW){ + ret = Transform_Sha512(sha512); + } + #endif + if (ret != 0) + break; + } + } +#endif + + if (len > 0) { + XMEMCPY(local, data, len); + sha512->buffLen = len; + } + + return ret; +} + +#ifdef WOLFSSL_SHA512 + +int wc_Sha512Update(wc_Sha512* sha512, const byte* data, word32 len) +{ + if (sha512 == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA512) + if (sha512->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA512) { + #if defined(HAVE_INTEL_QA) + return IntelQaSymSha512(&sha512->asyncDev, NULL, data, len); + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + return Sha512Update(sha512, data, len); +} + +#endif /* WOLFSSL_SHA512 */ + +#endif /* WOLFSSL_IMX6_CAAM */ + +static WC_INLINE int Sha512Final(wc_Sha512* sha512) +{ + byte* local = (byte*)sha512->buffer; + int ret; + + if (sha512 == NULL) { + return BAD_FUNC_ARG; + } + + local[sha512->buffLen++] = 0x80; /* add 1 */ + + /* pad with zeros */ + if (sha512->buffLen > WC_SHA512_PAD_SIZE) { + XMEMSET(&local[sha512->buffLen], 0, WC_SHA512_BLOCK_SIZE - sha512->buffLen); + sha512->buffLen += WC_SHA512_BLOCK_SIZE - sha512->buffLen; +#if defined(LITTLE_ENDIAN_ORDER) + #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + if (!IS_INTEL_AVX1(intel_flags) && !IS_INTEL_AVX2(intel_flags)) + #endif + { + + #if !defined(WOLFSSL_ESP32WROOM32_CRYPT) || \ + defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + ByteReverseWords64(sha512->buffer,sha512->buffer, + WC_SHA512_BLOCK_SIZE); + #endif + } +#endif /* LITTLE_ENDIAN_ORDER */ +#if !defined(WOLFSSL_ESP32WROOM32_CRYPT) || \ + defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + ret = Transform_Sha512(sha512); +#else + if(sha512->ctx.mode == ESP32_SHA_INIT) { + esp_sha_try_hw_lock(&sha512->ctx); + } + ret = esp_sha512_process(sha512); + if(ret == 0 && sha512->ctx.mode == ESP32_SHA_SW){ + ret = Transform_Sha512(sha512); + } +#endif + if (ret != 0) + return ret; + + sha512->buffLen = 0; + } + XMEMSET(&local[sha512->buffLen], 0, WC_SHA512_PAD_SIZE - sha512->buffLen); + + /* put lengths in bits */ + sha512->hiLen = (sha512->loLen >> (8 * sizeof(sha512->loLen) - 3)) + + (sha512->hiLen << 3); + sha512->loLen = sha512->loLen << 3; + + /* store lengths */ +#if defined(LITTLE_ENDIAN_ORDER) + #if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + if (!IS_INTEL_AVX1(intel_flags) && !IS_INTEL_AVX2(intel_flags)) + #endif + #if !defined(WOLFSSL_ESP32WROOM32_CRYPT) || \ + defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + ByteReverseWords64(sha512->buffer, sha512->buffer, WC_SHA512_PAD_SIZE); + #endif +#endif + /* ! length ordering dependent on digest endian type ! */ + +#if !defined(WOLFSSL_ESP32WROOM32_CRYPT) || \ + defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + sha512->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 2] = sha512->hiLen; + sha512->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 1] = sha512->loLen; +#endif + +#if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + if (IS_INTEL_AVX1(intel_flags) || IS_INTEL_AVX2(intel_flags)) + ByteReverseWords64(&(sha512->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 2]), + &(sha512->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 2]), + WC_SHA512_BLOCK_SIZE - WC_SHA512_PAD_SIZE); +#endif +#if !defined(WOLFSSL_ESP32WROOM32_CRYPT) || \ + defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + ret = Transform_Sha512(sha512); +#else + if(sha512->ctx.mode == ESP32_SHA_INIT) { + esp_sha_try_hw_lock(&sha512->ctx); + } + ret = esp_sha512_digest_process(sha512, 1); + if(ret == 0 && sha512->ctx.mode == ESP32_SHA_SW) { + ret = Transform_Sha512(sha512); + } +#endif + if (ret != 0) + return ret; + + #ifdef LITTLE_ENDIAN_ORDER + ByteReverseWords64(sha512->digest, sha512->digest, WC_SHA512_DIGEST_SIZE); + #endif + + return 0; +} + +#ifdef WOLFSSL_SHA512 + +int wc_Sha512FinalRaw(wc_Sha512* sha512, byte* hash) +{ +#ifdef LITTLE_ENDIAN_ORDER + word64 digest[WC_SHA512_DIGEST_SIZE / sizeof(word64)]; +#endif + + if (sha512 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef LITTLE_ENDIAN_ORDER + ByteReverseWords64((word64*)digest, (word64*)sha512->digest, + WC_SHA512_DIGEST_SIZE); + XMEMCPY(hash, digest, WC_SHA512_DIGEST_SIZE); +#else + XMEMCPY(hash, sha512->digest, WC_SHA512_DIGEST_SIZE); +#endif + + return 0; +} + +int wc_Sha512Final(wc_Sha512* sha512, byte* hash) +{ + int ret; + + if (sha512 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA512) + if (sha512->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA512) { + #if defined(HAVE_INTEL_QA) + return IntelQaSymSha512(&sha512->asyncDev, hash, NULL, + WC_SHA512_DIGEST_SIZE); + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + ret = Sha512Final(sha512); + if (ret != 0) + return ret; + + XMEMCPY(hash, sha512->digest, WC_SHA512_DIGEST_SIZE); + + return InitSha512(sha512); /* reset state */ +} + +int wc_InitSha512(wc_Sha512* sha512) +{ + return wc_InitSha512_ex(sha512, NULL, INVALID_DEVID); +} + +void wc_Sha512Free(wc_Sha512* sha512) +{ + if (sha512 == NULL) + return; + +#ifdef WOLFSSL_SMALL_STACK_CACHE + if (sha512->W != NULL) { + XFREE(sha512->W, NULL, DYNAMIC_TYPE_TMP_BUFFER); + sha512->W = NULL; + } +#endif + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA512) + wolfAsync_DevCtxFree(&sha512->asyncDev, WOLFSSL_ASYNC_MARKER_SHA512); +#endif /* WOLFSSL_ASYNC_CRYPT */ +} + +#endif /* WOLFSSL_SHA512 */ + +/* -------------------------------------------------------------------------- */ +/* SHA384 */ +/* -------------------------------------------------------------------------- */ +#ifdef WOLFSSL_SHA384 + +#if defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH) + /* functions defined in wolfcrypt/src/port/caam/caam_sha.c */ + +#else + +static int InitSha384(wc_Sha384* sha384) +{ + if (sha384 == NULL) { + return BAD_FUNC_ARG; + } + + sha384->digest[0] = W64LIT(0xcbbb9d5dc1059ed8); + sha384->digest[1] = W64LIT(0x629a292a367cd507); + sha384->digest[2] = W64LIT(0x9159015a3070dd17); + sha384->digest[3] = W64LIT(0x152fecd8f70e5939); + sha384->digest[4] = W64LIT(0x67332667ffc00b31); + sha384->digest[5] = W64LIT(0x8eb44a8768581511); + sha384->digest[6] = W64LIT(0xdb0c2e0d64f98fa7); + sha384->digest[7] = W64LIT(0x47b5481dbefa4fa4); + + sha384->buffLen = 0; + sha384->loLen = 0; + sha384->hiLen = 0; + +#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + sha384->ctx.sha_type = SHA2_384; + /* always start firstblock = 1 when using hw engine */ + sha384->ctx.isfirstblock = 1; + if(sha384->ctx.mode == ESP32_SHA_HW) { + /* release hw */ + esp_sha_hw_unlock(); + } + /* always set mode as INIT + * whether using HW or SW is detemined at first call of update() + */ + sha384->ctx.mode = ESP32_SHA_INIT; + +#endif + + return 0; +} + +int wc_Sha384Update(wc_Sha384* sha384, const byte* data, word32 len) +{ + if (sha384 == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA384) + if (sha384->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA384) { + #if defined(HAVE_INTEL_QA) + return IntelQaSymSha384(&sha384->asyncDev, NULL, data, len); + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + return Sha512Update((wc_Sha512*)sha384, data, len); +} + + +int wc_Sha384FinalRaw(wc_Sha384* sha384, byte* hash) +{ +#ifdef LITTLE_ENDIAN_ORDER + word64 digest[WC_SHA384_DIGEST_SIZE / sizeof(word64)]; +#endif + + if (sha384 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef LITTLE_ENDIAN_ORDER + ByteReverseWords64((word64*)digest, (word64*)sha384->digest, + WC_SHA384_DIGEST_SIZE); + XMEMCPY(hash, digest, WC_SHA384_DIGEST_SIZE); +#else + XMEMCPY(hash, sha384->digest, WC_SHA384_DIGEST_SIZE); +#endif + + return 0; +} + +int wc_Sha384Final(wc_Sha384* sha384, byte* hash) +{ + int ret; + + if (sha384 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA384) + if (sha384->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA384) { + #if defined(HAVE_INTEL_QA) + return IntelQaSymSha384(&sha384->asyncDev, hash, NULL, + WC_SHA384_DIGEST_SIZE); + #endif + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + ret = Sha512Final((wc_Sha512*)sha384); + if (ret != 0) + return ret; + + XMEMCPY(hash, sha384->digest, WC_SHA384_DIGEST_SIZE); + + return InitSha384(sha384); /* reset state */ +} + +int wc_InitSha384_ex(wc_Sha384* sha384, void* heap, int devId) +{ + int ret; + + if (sha384 == NULL) { + return BAD_FUNC_ARG; + } + + sha384->heap = heap; + ret = InitSha384(sha384); + if (ret != 0) + return ret; + +#if defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2) + Sha512_SetTransform(); +#endif +#ifdef WOLFSSL_SMALL_STACK_CACHE + sha384->W = NULL; +#endif + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA384) + ret = wolfAsync_DevCtxInit(&sha384->asyncDev, WOLFSSL_ASYNC_MARKER_SHA384, + sha384->heap, devId); +#else + (void)devId; +#endif /* WOLFSSL_ASYNC_CRYPT */ + + return ret; +} + +#endif /* WOLFSSL_IMX6_CAAM */ + +int wc_InitSha384(wc_Sha384* sha384) +{ + return wc_InitSha384_ex(sha384, NULL, INVALID_DEVID); +} + +void wc_Sha384Free(wc_Sha384* sha384) +{ + if (sha384 == NULL) + return; + +#ifdef WOLFSSL_SMALL_STACK_CACHE + if (sha384->W != NULL) { + XFREE(sha384->W, NULL, DYNAMIC_TYPE_TMP_BUFFER); + sha384->W = NULL; + } +#endif + +#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA384) + wolfAsync_DevCtxFree(&sha384->asyncDev, WOLFSSL_ASYNC_MARKER_SHA384); +#endif /* WOLFSSL_ASYNC_CRYPT */ +} + +#endif /* WOLFSSL_SHA384 */ + +#endif /* HAVE_FIPS */ + +#ifdef WOLFSSL_SHA512 + +int wc_Sha512GetHash(wc_Sha512* sha512, byte* hash) +{ + int ret; + wc_Sha512 tmpSha512; + + if (sha512 == NULL || hash == NULL) + return BAD_FUNC_ARG; + +#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + if(sha512->ctx.mode == ESP32_SHA_INIT) { + esp_sha_try_hw_lock(&sha512->ctx); + } + if(sha512->ctx.mode != ESP32_SHA_SW) + esp_sha512_digest_process(sha512, 0); +#endif + + ret = wc_Sha512Copy(sha512, &tmpSha512); + if (ret == 0) { + ret = wc_Sha512Final(&tmpSha512, hash); +#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + sha512->ctx.mode = ESP32_SHA_SW;; +#endif + wc_Sha512Free(&tmpSha512); + } + return ret; +} + +int wc_Sha512Copy(wc_Sha512* src, wc_Sha512* dst) +{ + int ret = 0; + + if (src == NULL || dst == NULL) + return BAD_FUNC_ARG; + + XMEMCPY(dst, src, sizeof(wc_Sha512)); +#ifdef WOLFSSL_SMALL_STACK_CACHE + dst->W = NULL; +#endif + +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev); +#endif +#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + dst->ctx.mode = src->ctx.mode; + dst->ctx.isfirstblock = src->ctx.isfirstblock; + dst->ctx.sha_type = src->ctx.sha_type; +#endif +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + dst->flags |= WC_HASH_FLAG_ISCOPY; +#endif + + return ret; +} + +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) +int wc_Sha512SetFlags(wc_Sha512* sha512, word32 flags) +{ + if (sha512) { + sha512->flags = flags; + } + return 0; +} +int wc_Sha512GetFlags(wc_Sha512* sha512, word32* flags) +{ + if (sha512 && flags) { + *flags = sha512->flags; + } + return 0; +} +#endif + +#endif /* WOLFSSL_SHA512 */ + +#ifdef WOLFSSL_SHA384 + +int wc_Sha384GetHash(wc_Sha384* sha384, byte* hash) +{ + int ret; + wc_Sha384 tmpSha384; + + if (sha384 == NULL || hash == NULL) + return BAD_FUNC_ARG; +#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + if(sha384->ctx.mode == ESP32_SHA_INIT) { + esp_sha_try_hw_lock(&sha384->ctx); + } + if(sha384->ctx.mode != ESP32_SHA_SW) { + esp_sha512_digest_process(sha384, 0); + } +#endif + ret = wc_Sha384Copy(sha384, &tmpSha384); + if (ret == 0) { + ret = wc_Sha384Final(&tmpSha384, hash); +#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + sha384->ctx.mode = ESP32_SHA_SW; +#endif + wc_Sha384Free(&tmpSha384); + } + return ret; +} +int wc_Sha384Copy(wc_Sha384* src, wc_Sha384* dst) +{ + int ret = 0; + + if (src == NULL || dst == NULL) + return BAD_FUNC_ARG; + + XMEMCPY(dst, src, sizeof(wc_Sha384)); +#ifdef WOLFSSL_SMALL_STACK_CACHE + dst->W = NULL; +#endif + +#ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev); +#endif +#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + dst->ctx.mode = src->ctx.mode; + dst->ctx.isfirstblock = src->ctx.isfirstblock; + dst->ctx.sha_type = src->ctx.sha_type; +#endif +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + dst->flags |= WC_HASH_FLAG_ISCOPY; +#endif + + return ret; +} + +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) +int wc_Sha384SetFlags(wc_Sha384* sha384, word32 flags) +{ + if (sha384) { + sha384->flags = flags; + } + return 0; +} +int wc_Sha384GetFlags(wc_Sha384* sha384, word32* flags) +{ + if (sha384 && flags) { + *flags = sha384->flags; + } + return 0; +} +#endif + +#endif /* WOLFSSL_SHA384 */ + +#endif /* WOLFSSL_SHA512 || WOLFSSL_SHA384 */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/sha512_asm.S b/beken_os/beken378/func/wolfssl/wolfcrypt/src/sha512_asm.S new file mode 100755 index 0000000..c5f7145 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/sha512_asm.S @@ -0,0 +1,10741 @@ +/* sha512_asm + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#ifndef HAVE_INTEL_AVX1 +#define HAVE_INTEL_AVX1 +#endif /* HAVE_INTEL_AVX1 */ +#ifndef HAVE_INTEL_AVX2 +#define HAVE_INTEL_AVX2 +#endif /* HAVE_INTEL_AVX2 */ + +#ifdef HAVE_INTEL_AVX1 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx1_sha512_k: +.quad 0x428a2f98d728ae22,0x7137449123ef65cd +.quad 0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc +.quad 0x3956c25bf348b538,0x59f111f1b605d019 +.quad 0x923f82a4af194f9b,0xab1c5ed5da6d8118 +.quad 0xd807aa98a3030242,0x12835b0145706fbe +.quad 0x243185be4ee4b28c,0x550c7dc3d5ffb4e2 +.quad 0x72be5d74f27b896f,0x80deb1fe3b1696b1 +.quad 0x9bdc06a725c71235,0xc19bf174cf692694 +.quad 0xe49b69c19ef14ad2,0xefbe4786384f25e3 +.quad 0xfc19dc68b8cd5b5,0x240ca1cc77ac9c65 +.quad 0x2de92c6f592b0275,0x4a7484aa6ea6e483 +.quad 0x5cb0a9dcbd41fbd4,0x76f988da831153b5 +.quad 0x983e5152ee66dfab,0xa831c66d2db43210 +.quad 0xb00327c898fb213f,0xbf597fc7beef0ee4 +.quad 0xc6e00bf33da88fc2,0xd5a79147930aa725 +.quad 0x6ca6351e003826f,0x142929670a0e6e70 +.quad 0x27b70a8546d22ffc,0x2e1b21385c26c926 +.quad 0x4d2c6dfc5ac42aed,0x53380d139d95b3df +.quad 0x650a73548baf63de,0x766a0abb3c77b2a8 +.quad 0x81c2c92e47edaee6,0x92722c851482353b +.quad 0xa2bfe8a14cf10364,0xa81a664bbc423001 +.quad 0xc24b8b70d0f89791,0xc76c51a30654be30 +.quad 0xd192e819d6ef5218,0xd69906245565a910 +.quad 0xf40e35855771202a,0x106aa07032bbd1b8 +.quad 0x19a4c116b8d2d0c8,0x1e376c085141ab53 +.quad 0x2748774cdf8eeb99,0x34b0bcb5e19b48a8 +.quad 0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb +.quad 0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3 +.quad 0x748f82ee5defb2fc,0x78a5636f43172f60 +.quad 0x84c87814a1f0ab72,0x8cc702081a6439ec +.quad 0x90befffa23631e28,0xa4506cebde82bde9 +.quad 0xbef9a3f7b2c67915,0xc67178f2e372532b +.quad 0xca273eceea26619c,0xd186b8c721c0c207 +.quad 0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178 +.quad 0x6f067aa72176fba,0xa637dc5a2c898a6 +.quad 0x113f9804bef90dae,0x1b710b35131c471b +.quad 0x28db77f523047d84,0x32caab7b40c72493 +.quad 0x3c9ebe0a15c9bebc,0x431d67c49c100d4c +.quad 0x4cc5d4becb3e42b6,0x597f299cfc657e2a +.quad 0x5fcb6fab3ad6faec,0x6c44198c4a475817 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx1_sha512_flip_mask: +.quad 0x1020304050607, 0x8090a0b0c0d0e0f +#ifndef __APPLE__ +.text +.globl Transform_Sha512_AVX1 +.type Transform_Sha512_AVX1,@function +.align 4 +Transform_Sha512_AVX1: +#else +.section __TEXT,__text +.globl _Transform_Sha512_AVX1 +.p2align 2 +_Transform_Sha512_AVX1: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + subq $0x88, %rsp + leaq 64(%rdi), %rax + vmovdqa L_avx1_sha512_flip_mask(%rip), %xmm14 + movq (%rdi), %r8 + movq 8(%rdi), %r9 + movq 16(%rdi), %r10 + movq 24(%rdi), %r11 + movq 32(%rdi), %r12 + movq 40(%rdi), %r13 + movq 48(%rdi), %r14 + movq 56(%rdi), %r15 + vmovdqu (%rax), %xmm0 + vmovdqu 16(%rax), %xmm1 + vpshufb %xmm14, %xmm0, %xmm0 + vpshufb %xmm14, %xmm1, %xmm1 + vmovdqu 32(%rax), %xmm2 + vmovdqu 48(%rax), %xmm3 + vpshufb %xmm14, %xmm2, %xmm2 + vpshufb %xmm14, %xmm3, %xmm3 + vmovdqu 64(%rax), %xmm4 + vmovdqu 80(%rax), %xmm5 + vpshufb %xmm14, %xmm4, %xmm4 + vpshufb %xmm14, %xmm5, %xmm5 + vmovdqu 96(%rax), %xmm6 + vmovdqu 112(%rax), %xmm7 + vpshufb %xmm14, %xmm6, %xmm6 + vpshufb %xmm14, %xmm7, %xmm7 + movl $4, 128(%rsp) + leaq L_avx1_sha512_k(%rip), %rsi + movq %r9, %rbx + movq %r12, %rax + xorq %r10, %rbx + # Start of 16 rounds +L_sha256_len_avx1_start: + vpaddq (%rsi), %xmm0, %xmm8 + vpaddq 16(%rsi), %xmm1, %xmm9 + vmovdqu %xmm8, (%rsp) + vmovdqu %xmm9, 16(%rsp) + vpaddq 32(%rsi), %xmm2, %xmm8 + vpaddq 48(%rsi), %xmm3, %xmm9 + vmovdqu %xmm8, 32(%rsp) + vmovdqu %xmm9, 48(%rsp) + vpaddq 64(%rsi), %xmm4, %xmm8 + vpaddq 80(%rsi), %xmm5, %xmm9 + vmovdqu %xmm8, 64(%rsp) + vmovdqu %xmm9, 80(%rsp) + vpaddq 96(%rsi), %xmm6, %xmm8 + vpaddq 112(%rsi), %xmm7, %xmm9 + vmovdqu %xmm8, 96(%rsp) + vmovdqu %xmm9, 112(%rsp) + addq $0x80, %rsi + # msg_sched: 0-1 + # rnd_0: 0 - 0 + rorq $23, %rax + vpalignr $8, %xmm0, %xmm1, %xmm12 + vpalignr $8, %xmm4, %xmm5, %xmm13 + # rnd_0: 1 - 1 + movq %r8, %rdx + movq %r13, %rcx + addq (%rsp), %r15 + xorq %r14, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 3 + xorq %r12, %rax + andq %r12, %rcx + rorq $4, %rax + xorq %r14, %rcx + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 4 - 5 + xorq %r12, %rax + addq %rcx, %r15 + rorq $14, %rax + xorq %r9, %rdx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 6 - 7 + addq %rax, %r15 + movq %r8, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 8 - 9 + xorq %r8, %rcx + xorq %r9, %rbx + rorq $6, %rcx + addq %r15, %r11 + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm0, %xmm13, %xmm0 + # rnd_0: 10 - 11 + xorq %r8, %rcx + addq %rbx, %r15 + rorq $28, %rcx + movq %r11, %rax + addq %rcx, %r15 + # rnd_1: 0 - 0 + rorq $23, %rax + vpaddq %xmm0, %xmm8, %xmm0 + # rnd_1: 1 - 1 + movq %r15, %rbx + movq %r12, %rcx + addq 8(%rsp), %r14 + xorq %r13, %rcx + vpsrlq $19, %xmm7, %xmm8 + vpsllq $45, %xmm7, %xmm9 + # rnd_1: 2 - 3 + xorq %r11, %rax + andq %r11, %rcx + rorq $4, %rax + xorq %r13, %rcx + vpsrlq $61, %xmm7, %xmm10 + vpsllq $3, %xmm7, %xmm11 + # rnd_1: 4 - 6 + xorq %r11, %rax + addq %rcx, %r14 + rorq $14, %rax + xorq %r8, %rbx + addq %rax, %r14 + movq %r15, %rcx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 7 - 8 + andq %rbx, %rdx + rorq $5, %rcx + xorq %r15, %rcx + xorq %r8, %rdx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm7, %xmm11 + # rnd_1: 9 - 10 + rorq $6, %rcx + addq %r14, %r10 + xorq %r15, %rcx + addq %rdx, %r14 + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 11 - 11 + rorq $28, %rcx + movq %r10, %rax + addq %rcx, %r14 + vpaddq %xmm0, %xmm8, %xmm0 + # msg_sched done: 0-3 + # msg_sched: 2-3 + # rnd_0: 0 - 0 + rorq $23, %rax + vpalignr $8, %xmm1, %xmm2, %xmm12 + vpalignr $8, %xmm5, %xmm6, %xmm13 + # rnd_0: 1 - 1 + movq %r14, %rdx + movq %r11, %rcx + addq 16(%rsp), %r13 + xorq %r12, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 3 + xorq %r10, %rax + andq %r10, %rcx + rorq $4, %rax + xorq %r12, %rcx + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 4 - 5 + xorq %r10, %rax + addq %rcx, %r13 + rorq $14, %rax + xorq %r15, %rdx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 6 - 7 + addq %rax, %r13 + movq %r14, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 8 - 9 + xorq %r14, %rcx + xorq %r15, %rbx + rorq $6, %rcx + addq %r13, %r9 + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm1, %xmm13, %xmm1 + # rnd_0: 10 - 11 + xorq %r14, %rcx + addq %rbx, %r13 + rorq $28, %rcx + movq %r9, %rax + addq %rcx, %r13 + # rnd_1: 0 - 0 + rorq $23, %rax + vpaddq %xmm1, %xmm8, %xmm1 + # rnd_1: 1 - 1 + movq %r13, %rbx + movq %r10, %rcx + addq 24(%rsp), %r12 + xorq %r11, %rcx + vpsrlq $19, %xmm0, %xmm8 + vpsllq $45, %xmm0, %xmm9 + # rnd_1: 2 - 3 + xorq %r9, %rax + andq %r9, %rcx + rorq $4, %rax + xorq %r11, %rcx + vpsrlq $61, %xmm0, %xmm10 + vpsllq $3, %xmm0, %xmm11 + # rnd_1: 4 - 6 + xorq %r9, %rax + addq %rcx, %r12 + rorq $14, %rax + xorq %r14, %rbx + addq %rax, %r12 + movq %r13, %rcx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 7 - 8 + andq %rbx, %rdx + rorq $5, %rcx + xorq %r13, %rcx + xorq %r14, %rdx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm0, %xmm11 + # rnd_1: 9 - 10 + rorq $6, %rcx + addq %r12, %r8 + xorq %r13, %rcx + addq %rdx, %r12 + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 11 - 11 + rorq $28, %rcx + movq %r8, %rax + addq %rcx, %r12 + vpaddq %xmm1, %xmm8, %xmm1 + # msg_sched done: 2-5 + # msg_sched: 4-5 + # rnd_0: 0 - 0 + rorq $23, %rax + vpalignr $8, %xmm2, %xmm3, %xmm12 + vpalignr $8, %xmm6, %xmm7, %xmm13 + # rnd_0: 1 - 1 + movq %r12, %rdx + movq %r9, %rcx + addq 32(%rsp), %r11 + xorq %r10, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 3 + xorq %r8, %rax + andq %r8, %rcx + rorq $4, %rax + xorq %r10, %rcx + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 4 - 5 + xorq %r8, %rax + addq %rcx, %r11 + rorq $14, %rax + xorq %r13, %rdx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 6 - 7 + addq %rax, %r11 + movq %r12, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 8 - 9 + xorq %r12, %rcx + xorq %r13, %rbx + rorq $6, %rcx + addq %r11, %r15 + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm2, %xmm13, %xmm2 + # rnd_0: 10 - 11 + xorq %r12, %rcx + addq %rbx, %r11 + rorq $28, %rcx + movq %r15, %rax + addq %rcx, %r11 + # rnd_1: 0 - 0 + rorq $23, %rax + vpaddq %xmm2, %xmm8, %xmm2 + # rnd_1: 1 - 1 + movq %r11, %rbx + movq %r8, %rcx + addq 40(%rsp), %r10 + xorq %r9, %rcx + vpsrlq $19, %xmm1, %xmm8 + vpsllq $45, %xmm1, %xmm9 + # rnd_1: 2 - 3 + xorq %r15, %rax + andq %r15, %rcx + rorq $4, %rax + xorq %r9, %rcx + vpsrlq $61, %xmm1, %xmm10 + vpsllq $3, %xmm1, %xmm11 + # rnd_1: 4 - 6 + xorq %r15, %rax + addq %rcx, %r10 + rorq $14, %rax + xorq %r12, %rbx + addq %rax, %r10 + movq %r11, %rcx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 7 - 8 + andq %rbx, %rdx + rorq $5, %rcx + xorq %r11, %rcx + xorq %r12, %rdx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm1, %xmm11 + # rnd_1: 9 - 10 + rorq $6, %rcx + addq %r10, %r14 + xorq %r11, %rcx + addq %rdx, %r10 + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 11 - 11 + rorq $28, %rcx + movq %r14, %rax + addq %rcx, %r10 + vpaddq %xmm2, %xmm8, %xmm2 + # msg_sched done: 4-7 + # msg_sched: 6-7 + # rnd_0: 0 - 0 + rorq $23, %rax + vpalignr $8, %xmm3, %xmm4, %xmm12 + vpalignr $8, %xmm7, %xmm0, %xmm13 + # rnd_0: 1 - 1 + movq %r10, %rdx + movq %r15, %rcx + addq 48(%rsp), %r9 + xorq %r8, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 3 + xorq %r14, %rax + andq %r14, %rcx + rorq $4, %rax + xorq %r8, %rcx + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 4 - 5 + xorq %r14, %rax + addq %rcx, %r9 + rorq $14, %rax + xorq %r11, %rdx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 6 - 7 + addq %rax, %r9 + movq %r10, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 8 - 9 + xorq %r10, %rcx + xorq %r11, %rbx + rorq $6, %rcx + addq %r9, %r13 + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm3, %xmm13, %xmm3 + # rnd_0: 10 - 11 + xorq %r10, %rcx + addq %rbx, %r9 + rorq $28, %rcx + movq %r13, %rax + addq %rcx, %r9 + # rnd_1: 0 - 0 + rorq $23, %rax + vpaddq %xmm3, %xmm8, %xmm3 + # rnd_1: 1 - 1 + movq %r9, %rbx + movq %r14, %rcx + addq 56(%rsp), %r8 + xorq %r15, %rcx + vpsrlq $19, %xmm2, %xmm8 + vpsllq $45, %xmm2, %xmm9 + # rnd_1: 2 - 3 + xorq %r13, %rax + andq %r13, %rcx + rorq $4, %rax + xorq %r15, %rcx + vpsrlq $61, %xmm2, %xmm10 + vpsllq $3, %xmm2, %xmm11 + # rnd_1: 4 - 6 + xorq %r13, %rax + addq %rcx, %r8 + rorq $14, %rax + xorq %r10, %rbx + addq %rax, %r8 + movq %r9, %rcx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 7 - 8 + andq %rbx, %rdx + rorq $5, %rcx + xorq %r9, %rcx + xorq %r10, %rdx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm2, %xmm11 + # rnd_1: 9 - 10 + rorq $6, %rcx + addq %r8, %r12 + xorq %r9, %rcx + addq %rdx, %r8 + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 11 - 11 + rorq $28, %rcx + movq %r12, %rax + addq %rcx, %r8 + vpaddq %xmm3, %xmm8, %xmm3 + # msg_sched done: 6-9 + # msg_sched: 8-9 + # rnd_0: 0 - 0 + rorq $23, %rax + vpalignr $8, %xmm4, %xmm5, %xmm12 + vpalignr $8, %xmm0, %xmm1, %xmm13 + # rnd_0: 1 - 1 + movq %r8, %rdx + movq %r13, %rcx + addq 64(%rsp), %r15 + xorq %r14, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 3 + xorq %r12, %rax + andq %r12, %rcx + rorq $4, %rax + xorq %r14, %rcx + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 4 - 5 + xorq %r12, %rax + addq %rcx, %r15 + rorq $14, %rax + xorq %r9, %rdx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 6 - 7 + addq %rax, %r15 + movq %r8, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 8 - 9 + xorq %r8, %rcx + xorq %r9, %rbx + rorq $6, %rcx + addq %r15, %r11 + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm4, %xmm13, %xmm4 + # rnd_0: 10 - 11 + xorq %r8, %rcx + addq %rbx, %r15 + rorq $28, %rcx + movq %r11, %rax + addq %rcx, %r15 + # rnd_1: 0 - 0 + rorq $23, %rax + vpaddq %xmm4, %xmm8, %xmm4 + # rnd_1: 1 - 1 + movq %r15, %rbx + movq %r12, %rcx + addq 72(%rsp), %r14 + xorq %r13, %rcx + vpsrlq $19, %xmm3, %xmm8 + vpsllq $45, %xmm3, %xmm9 + # rnd_1: 2 - 3 + xorq %r11, %rax + andq %r11, %rcx + rorq $4, %rax + xorq %r13, %rcx + vpsrlq $61, %xmm3, %xmm10 + vpsllq $3, %xmm3, %xmm11 + # rnd_1: 4 - 6 + xorq %r11, %rax + addq %rcx, %r14 + rorq $14, %rax + xorq %r8, %rbx + addq %rax, %r14 + movq %r15, %rcx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 7 - 8 + andq %rbx, %rdx + rorq $5, %rcx + xorq %r15, %rcx + xorq %r8, %rdx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm3, %xmm11 + # rnd_1: 9 - 10 + rorq $6, %rcx + addq %r14, %r10 + xorq %r15, %rcx + addq %rdx, %r14 + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 11 - 11 + rorq $28, %rcx + movq %r10, %rax + addq %rcx, %r14 + vpaddq %xmm4, %xmm8, %xmm4 + # msg_sched done: 8-11 + # msg_sched: 10-11 + # rnd_0: 0 - 0 + rorq $23, %rax + vpalignr $8, %xmm5, %xmm6, %xmm12 + vpalignr $8, %xmm1, %xmm2, %xmm13 + # rnd_0: 1 - 1 + movq %r14, %rdx + movq %r11, %rcx + addq 80(%rsp), %r13 + xorq %r12, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 3 + xorq %r10, %rax + andq %r10, %rcx + rorq $4, %rax + xorq %r12, %rcx + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 4 - 5 + xorq %r10, %rax + addq %rcx, %r13 + rorq $14, %rax + xorq %r15, %rdx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 6 - 7 + addq %rax, %r13 + movq %r14, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 8 - 9 + xorq %r14, %rcx + xorq %r15, %rbx + rorq $6, %rcx + addq %r13, %r9 + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm5, %xmm13, %xmm5 + # rnd_0: 10 - 11 + xorq %r14, %rcx + addq %rbx, %r13 + rorq $28, %rcx + movq %r9, %rax + addq %rcx, %r13 + # rnd_1: 0 - 0 + rorq $23, %rax + vpaddq %xmm5, %xmm8, %xmm5 + # rnd_1: 1 - 1 + movq %r13, %rbx + movq %r10, %rcx + addq 88(%rsp), %r12 + xorq %r11, %rcx + vpsrlq $19, %xmm4, %xmm8 + vpsllq $45, %xmm4, %xmm9 + # rnd_1: 2 - 3 + xorq %r9, %rax + andq %r9, %rcx + rorq $4, %rax + xorq %r11, %rcx + vpsrlq $61, %xmm4, %xmm10 + vpsllq $3, %xmm4, %xmm11 + # rnd_1: 4 - 6 + xorq %r9, %rax + addq %rcx, %r12 + rorq $14, %rax + xorq %r14, %rbx + addq %rax, %r12 + movq %r13, %rcx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 7 - 8 + andq %rbx, %rdx + rorq $5, %rcx + xorq %r13, %rcx + xorq %r14, %rdx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm4, %xmm11 + # rnd_1: 9 - 10 + rorq $6, %rcx + addq %r12, %r8 + xorq %r13, %rcx + addq %rdx, %r12 + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 11 - 11 + rorq $28, %rcx + movq %r8, %rax + addq %rcx, %r12 + vpaddq %xmm5, %xmm8, %xmm5 + # msg_sched done: 10-13 + # msg_sched: 12-13 + # rnd_0: 0 - 0 + rorq $23, %rax + vpalignr $8, %xmm6, %xmm7, %xmm12 + vpalignr $8, %xmm2, %xmm3, %xmm13 + # rnd_0: 1 - 1 + movq %r12, %rdx + movq %r9, %rcx + addq 96(%rsp), %r11 + xorq %r10, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 3 + xorq %r8, %rax + andq %r8, %rcx + rorq $4, %rax + xorq %r10, %rcx + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 4 - 5 + xorq %r8, %rax + addq %rcx, %r11 + rorq $14, %rax + xorq %r13, %rdx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 6 - 7 + addq %rax, %r11 + movq %r12, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 8 - 9 + xorq %r12, %rcx + xorq %r13, %rbx + rorq $6, %rcx + addq %r11, %r15 + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm6, %xmm13, %xmm6 + # rnd_0: 10 - 11 + xorq %r12, %rcx + addq %rbx, %r11 + rorq $28, %rcx + movq %r15, %rax + addq %rcx, %r11 + # rnd_1: 0 - 0 + rorq $23, %rax + vpaddq %xmm6, %xmm8, %xmm6 + # rnd_1: 1 - 1 + movq %r11, %rbx + movq %r8, %rcx + addq 104(%rsp), %r10 + xorq %r9, %rcx + vpsrlq $19, %xmm5, %xmm8 + vpsllq $45, %xmm5, %xmm9 + # rnd_1: 2 - 3 + xorq %r15, %rax + andq %r15, %rcx + rorq $4, %rax + xorq %r9, %rcx + vpsrlq $61, %xmm5, %xmm10 + vpsllq $3, %xmm5, %xmm11 + # rnd_1: 4 - 6 + xorq %r15, %rax + addq %rcx, %r10 + rorq $14, %rax + xorq %r12, %rbx + addq %rax, %r10 + movq %r11, %rcx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 7 - 8 + andq %rbx, %rdx + rorq $5, %rcx + xorq %r11, %rcx + xorq %r12, %rdx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm5, %xmm11 + # rnd_1: 9 - 10 + rorq $6, %rcx + addq %r10, %r14 + xorq %r11, %rcx + addq %rdx, %r10 + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 11 - 11 + rorq $28, %rcx + movq %r14, %rax + addq %rcx, %r10 + vpaddq %xmm6, %xmm8, %xmm6 + # msg_sched done: 12-15 + # msg_sched: 14-15 + # rnd_0: 0 - 0 + rorq $23, %rax + vpalignr $8, %xmm7, %xmm0, %xmm12 + vpalignr $8, %xmm3, %xmm4, %xmm13 + # rnd_0: 1 - 1 + movq %r10, %rdx + movq %r15, %rcx + addq 112(%rsp), %r9 + xorq %r8, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 3 + xorq %r14, %rax + andq %r14, %rcx + rorq $4, %rax + xorq %r8, %rcx + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 4 - 5 + xorq %r14, %rax + addq %rcx, %r9 + rorq $14, %rax + xorq %r11, %rdx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 6 - 7 + addq %rax, %r9 + movq %r10, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 8 - 9 + xorq %r10, %rcx + xorq %r11, %rbx + rorq $6, %rcx + addq %r9, %r13 + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm7, %xmm13, %xmm7 + # rnd_0: 10 - 11 + xorq %r10, %rcx + addq %rbx, %r9 + rorq $28, %rcx + movq %r13, %rax + addq %rcx, %r9 + # rnd_1: 0 - 0 + rorq $23, %rax + vpaddq %xmm7, %xmm8, %xmm7 + # rnd_1: 1 - 1 + movq %r9, %rbx + movq %r14, %rcx + addq 120(%rsp), %r8 + xorq %r15, %rcx + vpsrlq $19, %xmm6, %xmm8 + vpsllq $45, %xmm6, %xmm9 + # rnd_1: 2 - 3 + xorq %r13, %rax + andq %r13, %rcx + rorq $4, %rax + xorq %r15, %rcx + vpsrlq $61, %xmm6, %xmm10 + vpsllq $3, %xmm6, %xmm11 + # rnd_1: 4 - 6 + xorq %r13, %rax + addq %rcx, %r8 + rorq $14, %rax + xorq %r10, %rbx + addq %rax, %r8 + movq %r9, %rcx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 7 - 8 + andq %rbx, %rdx + rorq $5, %rcx + xorq %r9, %rcx + xorq %r10, %rdx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm6, %xmm11 + # rnd_1: 9 - 10 + rorq $6, %rcx + addq %r8, %r12 + xorq %r9, %rcx + addq %rdx, %r8 + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 11 - 11 + rorq $28, %rcx + movq %r12, %rax + addq %rcx, %r8 + vpaddq %xmm7, %xmm8, %xmm7 + # msg_sched done: 14-17 + subl $0x01, 128(%rsp) + jne L_sha256_len_avx1_start + vpaddq (%rsi), %xmm0, %xmm8 + vpaddq 16(%rsi), %xmm1, %xmm9 + vmovdqu %xmm8, (%rsp) + vmovdqu %xmm9, 16(%rsp) + vpaddq 32(%rsi), %xmm2, %xmm8 + vpaddq 48(%rsi), %xmm3, %xmm9 + vmovdqu %xmm8, 32(%rsp) + vmovdqu %xmm9, 48(%rsp) + vpaddq 64(%rsi), %xmm4, %xmm8 + vpaddq 80(%rsi), %xmm5, %xmm9 + vmovdqu %xmm8, 64(%rsp) + vmovdqu %xmm9, 80(%rsp) + vpaddq 96(%rsi), %xmm6, %xmm8 + vpaddq 112(%rsi), %xmm7, %xmm9 + vmovdqu %xmm8, 96(%rsp) + vmovdqu %xmm9, 112(%rsp) + # rnd_all_2: 0-1 + # rnd_0: 0 - 11 + rorq $23, %rax + movq %r8, %rdx + movq %r13, %rcx + addq (%rsp), %r15 + xorq %r14, %rcx + xorq %r12, %rax + andq %r12, %rcx + rorq $4, %rax + xorq %r14, %rcx + xorq %r12, %rax + addq %rcx, %r15 + rorq $14, %rax + xorq %r9, %rdx + addq %rax, %r15 + movq %r8, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r8, %rcx + xorq %r9, %rbx + rorq $6, %rcx + addq %r15, %r11 + xorq %r8, %rcx + addq %rbx, %r15 + rorq $28, %rcx + movq %r11, %rax + addq %rcx, %r15 + # rnd_1: 0 - 11 + rorq $23, %rax + movq %r15, %rbx + movq %r12, %rcx + addq 8(%rsp), %r14 + xorq %r13, %rcx + xorq %r11, %rax + andq %r11, %rcx + rorq $4, %rax + xorq %r13, %rcx + xorq %r11, %rax + addq %rcx, %r14 + rorq $14, %rax + xorq %r8, %rbx + addq %rax, %r14 + movq %r15, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r15, %rcx + xorq %r8, %rdx + rorq $6, %rcx + addq %r14, %r10 + xorq %r15, %rcx + addq %rdx, %r14 + rorq $28, %rcx + movq %r10, %rax + addq %rcx, %r14 + # rnd_all_2: 2-3 + # rnd_0: 0 - 11 + rorq $23, %rax + movq %r14, %rdx + movq %r11, %rcx + addq 16(%rsp), %r13 + xorq %r12, %rcx + xorq %r10, %rax + andq %r10, %rcx + rorq $4, %rax + xorq %r12, %rcx + xorq %r10, %rax + addq %rcx, %r13 + rorq $14, %rax + xorq %r15, %rdx + addq %rax, %r13 + movq %r14, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r14, %rcx + xorq %r15, %rbx + rorq $6, %rcx + addq %r13, %r9 + xorq %r14, %rcx + addq %rbx, %r13 + rorq $28, %rcx + movq %r9, %rax + addq %rcx, %r13 + # rnd_1: 0 - 11 + rorq $23, %rax + movq %r13, %rbx + movq %r10, %rcx + addq 24(%rsp), %r12 + xorq %r11, %rcx + xorq %r9, %rax + andq %r9, %rcx + rorq $4, %rax + xorq %r11, %rcx + xorq %r9, %rax + addq %rcx, %r12 + rorq $14, %rax + xorq %r14, %rbx + addq %rax, %r12 + movq %r13, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r13, %rcx + xorq %r14, %rdx + rorq $6, %rcx + addq %r12, %r8 + xorq %r13, %rcx + addq %rdx, %r12 + rorq $28, %rcx + movq %r8, %rax + addq %rcx, %r12 + # rnd_all_2: 4-5 + # rnd_0: 0 - 11 + rorq $23, %rax + movq %r12, %rdx + movq %r9, %rcx + addq 32(%rsp), %r11 + xorq %r10, %rcx + xorq %r8, %rax + andq %r8, %rcx + rorq $4, %rax + xorq %r10, %rcx + xorq %r8, %rax + addq %rcx, %r11 + rorq $14, %rax + xorq %r13, %rdx + addq %rax, %r11 + movq %r12, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r12, %rcx + xorq %r13, %rbx + rorq $6, %rcx + addq %r11, %r15 + xorq %r12, %rcx + addq %rbx, %r11 + rorq $28, %rcx + movq %r15, %rax + addq %rcx, %r11 + # rnd_1: 0 - 11 + rorq $23, %rax + movq %r11, %rbx + movq %r8, %rcx + addq 40(%rsp), %r10 + xorq %r9, %rcx + xorq %r15, %rax + andq %r15, %rcx + rorq $4, %rax + xorq %r9, %rcx + xorq %r15, %rax + addq %rcx, %r10 + rorq $14, %rax + xorq %r12, %rbx + addq %rax, %r10 + movq %r11, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r11, %rcx + xorq %r12, %rdx + rorq $6, %rcx + addq %r10, %r14 + xorq %r11, %rcx + addq %rdx, %r10 + rorq $28, %rcx + movq %r14, %rax + addq %rcx, %r10 + # rnd_all_2: 6-7 + # rnd_0: 0 - 11 + rorq $23, %rax + movq %r10, %rdx + movq %r15, %rcx + addq 48(%rsp), %r9 + xorq %r8, %rcx + xorq %r14, %rax + andq %r14, %rcx + rorq $4, %rax + xorq %r8, %rcx + xorq %r14, %rax + addq %rcx, %r9 + rorq $14, %rax + xorq %r11, %rdx + addq %rax, %r9 + movq %r10, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r10, %rcx + xorq %r11, %rbx + rorq $6, %rcx + addq %r9, %r13 + xorq %r10, %rcx + addq %rbx, %r9 + rorq $28, %rcx + movq %r13, %rax + addq %rcx, %r9 + # rnd_1: 0 - 11 + rorq $23, %rax + movq %r9, %rbx + movq %r14, %rcx + addq 56(%rsp), %r8 + xorq %r15, %rcx + xorq %r13, %rax + andq %r13, %rcx + rorq $4, %rax + xorq %r15, %rcx + xorq %r13, %rax + addq %rcx, %r8 + rorq $14, %rax + xorq %r10, %rbx + addq %rax, %r8 + movq %r9, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r9, %rcx + xorq %r10, %rdx + rorq $6, %rcx + addq %r8, %r12 + xorq %r9, %rcx + addq %rdx, %r8 + rorq $28, %rcx + movq %r12, %rax + addq %rcx, %r8 + # rnd_all_2: 8-9 + # rnd_0: 0 - 11 + rorq $23, %rax + movq %r8, %rdx + movq %r13, %rcx + addq 64(%rsp), %r15 + xorq %r14, %rcx + xorq %r12, %rax + andq %r12, %rcx + rorq $4, %rax + xorq %r14, %rcx + xorq %r12, %rax + addq %rcx, %r15 + rorq $14, %rax + xorq %r9, %rdx + addq %rax, %r15 + movq %r8, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r8, %rcx + xorq %r9, %rbx + rorq $6, %rcx + addq %r15, %r11 + xorq %r8, %rcx + addq %rbx, %r15 + rorq $28, %rcx + movq %r11, %rax + addq %rcx, %r15 + # rnd_1: 0 - 11 + rorq $23, %rax + movq %r15, %rbx + movq %r12, %rcx + addq 72(%rsp), %r14 + xorq %r13, %rcx + xorq %r11, %rax + andq %r11, %rcx + rorq $4, %rax + xorq %r13, %rcx + xorq %r11, %rax + addq %rcx, %r14 + rorq $14, %rax + xorq %r8, %rbx + addq %rax, %r14 + movq %r15, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r15, %rcx + xorq %r8, %rdx + rorq $6, %rcx + addq %r14, %r10 + xorq %r15, %rcx + addq %rdx, %r14 + rorq $28, %rcx + movq %r10, %rax + addq %rcx, %r14 + # rnd_all_2: 10-11 + # rnd_0: 0 - 11 + rorq $23, %rax + movq %r14, %rdx + movq %r11, %rcx + addq 80(%rsp), %r13 + xorq %r12, %rcx + xorq %r10, %rax + andq %r10, %rcx + rorq $4, %rax + xorq %r12, %rcx + xorq %r10, %rax + addq %rcx, %r13 + rorq $14, %rax + xorq %r15, %rdx + addq %rax, %r13 + movq %r14, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r14, %rcx + xorq %r15, %rbx + rorq $6, %rcx + addq %r13, %r9 + xorq %r14, %rcx + addq %rbx, %r13 + rorq $28, %rcx + movq %r9, %rax + addq %rcx, %r13 + # rnd_1: 0 - 11 + rorq $23, %rax + movq %r13, %rbx + movq %r10, %rcx + addq 88(%rsp), %r12 + xorq %r11, %rcx + xorq %r9, %rax + andq %r9, %rcx + rorq $4, %rax + xorq %r11, %rcx + xorq %r9, %rax + addq %rcx, %r12 + rorq $14, %rax + xorq %r14, %rbx + addq %rax, %r12 + movq %r13, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r13, %rcx + xorq %r14, %rdx + rorq $6, %rcx + addq %r12, %r8 + xorq %r13, %rcx + addq %rdx, %r12 + rorq $28, %rcx + movq %r8, %rax + addq %rcx, %r12 + # rnd_all_2: 12-13 + # rnd_0: 0 - 11 + rorq $23, %rax + movq %r12, %rdx + movq %r9, %rcx + addq 96(%rsp), %r11 + xorq %r10, %rcx + xorq %r8, %rax + andq %r8, %rcx + rorq $4, %rax + xorq %r10, %rcx + xorq %r8, %rax + addq %rcx, %r11 + rorq $14, %rax + xorq %r13, %rdx + addq %rax, %r11 + movq %r12, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r12, %rcx + xorq %r13, %rbx + rorq $6, %rcx + addq %r11, %r15 + xorq %r12, %rcx + addq %rbx, %r11 + rorq $28, %rcx + movq %r15, %rax + addq %rcx, %r11 + # rnd_1: 0 - 11 + rorq $23, %rax + movq %r11, %rbx + movq %r8, %rcx + addq 104(%rsp), %r10 + xorq %r9, %rcx + xorq %r15, %rax + andq %r15, %rcx + rorq $4, %rax + xorq %r9, %rcx + xorq %r15, %rax + addq %rcx, %r10 + rorq $14, %rax + xorq %r12, %rbx + addq %rax, %r10 + movq %r11, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r11, %rcx + xorq %r12, %rdx + rorq $6, %rcx + addq %r10, %r14 + xorq %r11, %rcx + addq %rdx, %r10 + rorq $28, %rcx + movq %r14, %rax + addq %rcx, %r10 + # rnd_all_2: 14-15 + # rnd_0: 0 - 11 + rorq $23, %rax + movq %r10, %rdx + movq %r15, %rcx + addq 112(%rsp), %r9 + xorq %r8, %rcx + xorq %r14, %rax + andq %r14, %rcx + rorq $4, %rax + xorq %r8, %rcx + xorq %r14, %rax + addq %rcx, %r9 + rorq $14, %rax + xorq %r11, %rdx + addq %rax, %r9 + movq %r10, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r10, %rcx + xorq %r11, %rbx + rorq $6, %rcx + addq %r9, %r13 + xorq %r10, %rcx + addq %rbx, %r9 + rorq $28, %rcx + movq %r13, %rax + addq %rcx, %r9 + # rnd_1: 0 - 11 + rorq $23, %rax + movq %r9, %rbx + movq %r14, %rcx + addq 120(%rsp), %r8 + xorq %r15, %rcx + xorq %r13, %rax + andq %r13, %rcx + rorq $4, %rax + xorq %r15, %rcx + xorq %r13, %rax + addq %rcx, %r8 + rorq $14, %rax + xorq %r10, %rbx + addq %rax, %r8 + movq %r9, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r9, %rcx + xorq %r10, %rdx + rorq $6, %rcx + addq %r8, %r12 + xorq %r9, %rcx + addq %rdx, %r8 + rorq $28, %rcx + movq %r12, %rax + addq %rcx, %r8 + addq %r8, (%rdi) + addq %r9, 8(%rdi) + addq %r10, 16(%rdi) + addq %r11, 24(%rdi) + addq %r12, 32(%rdi) + addq %r13, 40(%rdi) + addq %r14, 48(%rdi) + addq %r15, 56(%rdi) + xorq %rax, %rax + vzeroupper + addq $0x88, %rsp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size Transform_Sha512_AVX1,.-Transform_Sha512_AVX1 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl Transform_Sha512_AVX1_Len +.type Transform_Sha512_AVX1_Len,@function +.align 4 +Transform_Sha512_AVX1_Len: +#else +.section __TEXT,__text +.globl _Transform_Sha512_AVX1_Len +.p2align 2 +_Transform_Sha512_AVX1_Len: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + pushq %rbp + movq %rsi, %rbp + subq $0x90, %rsp + movq 224(%rdi), %rsi + leaq L_avx1_sha512_k(%rip), %rdx + vmovdqa L_avx1_sha512_flip_mask(%rip), %xmm14 + movq (%rdi), %r8 + movq 8(%rdi), %r9 + movq 16(%rdi), %r10 + movq 24(%rdi), %r11 + movq 32(%rdi), %r12 + movq 40(%rdi), %r13 + movq 48(%rdi), %r14 + movq 56(%rdi), %r15 + # Start of loop processing a block +L_sha512_len_avx1_begin: + vmovdqu (%rsi), %xmm0 + vmovdqu 16(%rsi), %xmm1 + vpshufb %xmm14, %xmm0, %xmm0 + vpshufb %xmm14, %xmm1, %xmm1 + vmovdqu 32(%rsi), %xmm2 + vmovdqu 48(%rsi), %xmm3 + vpshufb %xmm14, %xmm2, %xmm2 + vpshufb %xmm14, %xmm3, %xmm3 + vmovdqu 64(%rsi), %xmm4 + vmovdqu 80(%rsi), %xmm5 + vpshufb %xmm14, %xmm4, %xmm4 + vpshufb %xmm14, %xmm5, %xmm5 + vmovdqu 96(%rsi), %xmm6 + vmovdqu 112(%rsi), %xmm7 + vpshufb %xmm14, %xmm6, %xmm6 + vpshufb %xmm14, %xmm7, %xmm7 + movl $4, 128(%rsp) + movq %r9, %rbx + movq %r12, %rax + xorq %r10, %rbx + vpaddq (%rdx), %xmm0, %xmm8 + vpaddq 16(%rdx), %xmm1, %xmm9 + vmovdqu %xmm8, (%rsp) + vmovdqu %xmm9, 16(%rsp) + vpaddq 32(%rdx), %xmm2, %xmm8 + vpaddq 48(%rdx), %xmm3, %xmm9 + vmovdqu %xmm8, 32(%rsp) + vmovdqu %xmm9, 48(%rsp) + vpaddq 64(%rdx), %xmm4, %xmm8 + vpaddq 80(%rdx), %xmm5, %xmm9 + vmovdqu %xmm8, 64(%rsp) + vmovdqu %xmm9, 80(%rsp) + vpaddq 96(%rdx), %xmm6, %xmm8 + vpaddq 112(%rdx), %xmm7, %xmm9 + vmovdqu %xmm8, 96(%rsp) + vmovdqu %xmm9, 112(%rsp) + # Start of 16 rounds +L_sha512_len_avx1_start: + addq $0x80, %rdx + movq %rdx, 136(%rsp) + # msg_sched: 0-1 + # rnd_0: 0 - 0 + rorq $23, %rax + vpalignr $8, %xmm0, %xmm1, %xmm12 + vpalignr $8, %xmm4, %xmm5, %xmm13 + # rnd_0: 1 - 1 + movq %r8, %rdx + movq %r13, %rcx + addq (%rsp), %r15 + xorq %r14, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 3 + xorq %r12, %rax + andq %r12, %rcx + rorq $4, %rax + xorq %r14, %rcx + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 4 - 5 + xorq %r12, %rax + addq %rcx, %r15 + rorq $14, %rax + xorq %r9, %rdx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 6 - 7 + addq %rax, %r15 + movq %r8, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 8 - 9 + xorq %r8, %rcx + xorq %r9, %rbx + rorq $6, %rcx + addq %r15, %r11 + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm0, %xmm13, %xmm0 + # rnd_0: 10 - 11 + xorq %r8, %rcx + addq %rbx, %r15 + rorq $28, %rcx + movq %r11, %rax + addq %rcx, %r15 + # rnd_1: 0 - 0 + rorq $23, %rax + vpaddq %xmm0, %xmm8, %xmm0 + # rnd_1: 1 - 1 + movq %r15, %rbx + movq %r12, %rcx + addq 8(%rsp), %r14 + xorq %r13, %rcx + vpsrlq $19, %xmm7, %xmm8 + vpsllq $45, %xmm7, %xmm9 + # rnd_1: 2 - 3 + xorq %r11, %rax + andq %r11, %rcx + rorq $4, %rax + xorq %r13, %rcx + vpsrlq $61, %xmm7, %xmm10 + vpsllq $3, %xmm7, %xmm11 + # rnd_1: 4 - 6 + xorq %r11, %rax + addq %rcx, %r14 + rorq $14, %rax + xorq %r8, %rbx + addq %rax, %r14 + movq %r15, %rcx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 7 - 8 + andq %rbx, %rdx + rorq $5, %rcx + xorq %r15, %rcx + xorq %r8, %rdx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm7, %xmm11 + # rnd_1: 9 - 10 + rorq $6, %rcx + addq %r14, %r10 + xorq %r15, %rcx + addq %rdx, %r14 + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 11 - 11 + rorq $28, %rcx + movq %r10, %rax + addq %rcx, %r14 + vpaddq %xmm0, %xmm8, %xmm0 + # msg_sched done: 0-3 + # msg_sched: 2-3 + # rnd_0: 0 - 0 + rorq $23, %rax + vpalignr $8, %xmm1, %xmm2, %xmm12 + vpalignr $8, %xmm5, %xmm6, %xmm13 + # rnd_0: 1 - 1 + movq %r14, %rdx + movq %r11, %rcx + addq 16(%rsp), %r13 + xorq %r12, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 3 + xorq %r10, %rax + andq %r10, %rcx + rorq $4, %rax + xorq %r12, %rcx + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 4 - 5 + xorq %r10, %rax + addq %rcx, %r13 + rorq $14, %rax + xorq %r15, %rdx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 6 - 7 + addq %rax, %r13 + movq %r14, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 8 - 9 + xorq %r14, %rcx + xorq %r15, %rbx + rorq $6, %rcx + addq %r13, %r9 + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm1, %xmm13, %xmm1 + # rnd_0: 10 - 11 + xorq %r14, %rcx + addq %rbx, %r13 + rorq $28, %rcx + movq %r9, %rax + addq %rcx, %r13 + # rnd_1: 0 - 0 + rorq $23, %rax + vpaddq %xmm1, %xmm8, %xmm1 + # rnd_1: 1 - 1 + movq %r13, %rbx + movq %r10, %rcx + addq 24(%rsp), %r12 + xorq %r11, %rcx + vpsrlq $19, %xmm0, %xmm8 + vpsllq $45, %xmm0, %xmm9 + # rnd_1: 2 - 3 + xorq %r9, %rax + andq %r9, %rcx + rorq $4, %rax + xorq %r11, %rcx + vpsrlq $61, %xmm0, %xmm10 + vpsllq $3, %xmm0, %xmm11 + # rnd_1: 4 - 6 + xorq %r9, %rax + addq %rcx, %r12 + rorq $14, %rax + xorq %r14, %rbx + addq %rax, %r12 + movq %r13, %rcx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 7 - 8 + andq %rbx, %rdx + rorq $5, %rcx + xorq %r13, %rcx + xorq %r14, %rdx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm0, %xmm11 + # rnd_1: 9 - 10 + rorq $6, %rcx + addq %r12, %r8 + xorq %r13, %rcx + addq %rdx, %r12 + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 11 - 11 + rorq $28, %rcx + movq %r8, %rax + addq %rcx, %r12 + vpaddq %xmm1, %xmm8, %xmm1 + # msg_sched done: 2-5 + # msg_sched: 4-5 + # rnd_0: 0 - 0 + rorq $23, %rax + vpalignr $8, %xmm2, %xmm3, %xmm12 + vpalignr $8, %xmm6, %xmm7, %xmm13 + # rnd_0: 1 - 1 + movq %r12, %rdx + movq %r9, %rcx + addq 32(%rsp), %r11 + xorq %r10, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 3 + xorq %r8, %rax + andq %r8, %rcx + rorq $4, %rax + xorq %r10, %rcx + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 4 - 5 + xorq %r8, %rax + addq %rcx, %r11 + rorq $14, %rax + xorq %r13, %rdx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 6 - 7 + addq %rax, %r11 + movq %r12, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 8 - 9 + xorq %r12, %rcx + xorq %r13, %rbx + rorq $6, %rcx + addq %r11, %r15 + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm2, %xmm13, %xmm2 + # rnd_0: 10 - 11 + xorq %r12, %rcx + addq %rbx, %r11 + rorq $28, %rcx + movq %r15, %rax + addq %rcx, %r11 + # rnd_1: 0 - 0 + rorq $23, %rax + vpaddq %xmm2, %xmm8, %xmm2 + # rnd_1: 1 - 1 + movq %r11, %rbx + movq %r8, %rcx + addq 40(%rsp), %r10 + xorq %r9, %rcx + vpsrlq $19, %xmm1, %xmm8 + vpsllq $45, %xmm1, %xmm9 + # rnd_1: 2 - 3 + xorq %r15, %rax + andq %r15, %rcx + rorq $4, %rax + xorq %r9, %rcx + vpsrlq $61, %xmm1, %xmm10 + vpsllq $3, %xmm1, %xmm11 + # rnd_1: 4 - 6 + xorq %r15, %rax + addq %rcx, %r10 + rorq $14, %rax + xorq %r12, %rbx + addq %rax, %r10 + movq %r11, %rcx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 7 - 8 + andq %rbx, %rdx + rorq $5, %rcx + xorq %r11, %rcx + xorq %r12, %rdx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm1, %xmm11 + # rnd_1: 9 - 10 + rorq $6, %rcx + addq %r10, %r14 + xorq %r11, %rcx + addq %rdx, %r10 + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 11 - 11 + rorq $28, %rcx + movq %r14, %rax + addq %rcx, %r10 + vpaddq %xmm2, %xmm8, %xmm2 + # msg_sched done: 4-7 + # msg_sched: 6-7 + # rnd_0: 0 - 0 + rorq $23, %rax + vpalignr $8, %xmm3, %xmm4, %xmm12 + vpalignr $8, %xmm7, %xmm0, %xmm13 + # rnd_0: 1 - 1 + movq %r10, %rdx + movq %r15, %rcx + addq 48(%rsp), %r9 + xorq %r8, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 3 + xorq %r14, %rax + andq %r14, %rcx + rorq $4, %rax + xorq %r8, %rcx + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 4 - 5 + xorq %r14, %rax + addq %rcx, %r9 + rorq $14, %rax + xorq %r11, %rdx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 6 - 7 + addq %rax, %r9 + movq %r10, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 8 - 9 + xorq %r10, %rcx + xorq %r11, %rbx + rorq $6, %rcx + addq %r9, %r13 + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm3, %xmm13, %xmm3 + # rnd_0: 10 - 11 + xorq %r10, %rcx + addq %rbx, %r9 + rorq $28, %rcx + movq %r13, %rax + addq %rcx, %r9 + # rnd_1: 0 - 0 + rorq $23, %rax + vpaddq %xmm3, %xmm8, %xmm3 + # rnd_1: 1 - 1 + movq %r9, %rbx + movq %r14, %rcx + addq 56(%rsp), %r8 + xorq %r15, %rcx + vpsrlq $19, %xmm2, %xmm8 + vpsllq $45, %xmm2, %xmm9 + # rnd_1: 2 - 3 + xorq %r13, %rax + andq %r13, %rcx + rorq $4, %rax + xorq %r15, %rcx + vpsrlq $61, %xmm2, %xmm10 + vpsllq $3, %xmm2, %xmm11 + # rnd_1: 4 - 6 + xorq %r13, %rax + addq %rcx, %r8 + rorq $14, %rax + xorq %r10, %rbx + addq %rax, %r8 + movq %r9, %rcx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 7 - 8 + andq %rbx, %rdx + rorq $5, %rcx + xorq %r9, %rcx + xorq %r10, %rdx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm2, %xmm11 + # rnd_1: 9 - 10 + rorq $6, %rcx + addq %r8, %r12 + xorq %r9, %rcx + addq %rdx, %r8 + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 11 - 11 + rorq $28, %rcx + movq %r12, %rax + addq %rcx, %r8 + vpaddq %xmm3, %xmm8, %xmm3 + # msg_sched done: 6-9 + # msg_sched: 8-9 + # rnd_0: 0 - 0 + rorq $23, %rax + vpalignr $8, %xmm4, %xmm5, %xmm12 + vpalignr $8, %xmm0, %xmm1, %xmm13 + # rnd_0: 1 - 1 + movq %r8, %rdx + movq %r13, %rcx + addq 64(%rsp), %r15 + xorq %r14, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 3 + xorq %r12, %rax + andq %r12, %rcx + rorq $4, %rax + xorq %r14, %rcx + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 4 - 5 + xorq %r12, %rax + addq %rcx, %r15 + rorq $14, %rax + xorq %r9, %rdx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 6 - 7 + addq %rax, %r15 + movq %r8, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 8 - 9 + xorq %r8, %rcx + xorq %r9, %rbx + rorq $6, %rcx + addq %r15, %r11 + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm4, %xmm13, %xmm4 + # rnd_0: 10 - 11 + xorq %r8, %rcx + addq %rbx, %r15 + rorq $28, %rcx + movq %r11, %rax + addq %rcx, %r15 + # rnd_1: 0 - 0 + rorq $23, %rax + vpaddq %xmm4, %xmm8, %xmm4 + # rnd_1: 1 - 1 + movq %r15, %rbx + movq %r12, %rcx + addq 72(%rsp), %r14 + xorq %r13, %rcx + vpsrlq $19, %xmm3, %xmm8 + vpsllq $45, %xmm3, %xmm9 + # rnd_1: 2 - 3 + xorq %r11, %rax + andq %r11, %rcx + rorq $4, %rax + xorq %r13, %rcx + vpsrlq $61, %xmm3, %xmm10 + vpsllq $3, %xmm3, %xmm11 + # rnd_1: 4 - 6 + xorq %r11, %rax + addq %rcx, %r14 + rorq $14, %rax + xorq %r8, %rbx + addq %rax, %r14 + movq %r15, %rcx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 7 - 8 + andq %rbx, %rdx + rorq $5, %rcx + xorq %r15, %rcx + xorq %r8, %rdx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm3, %xmm11 + # rnd_1: 9 - 10 + rorq $6, %rcx + addq %r14, %r10 + xorq %r15, %rcx + addq %rdx, %r14 + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 11 - 11 + rorq $28, %rcx + movq %r10, %rax + addq %rcx, %r14 + vpaddq %xmm4, %xmm8, %xmm4 + # msg_sched done: 8-11 + # msg_sched: 10-11 + # rnd_0: 0 - 0 + rorq $23, %rax + vpalignr $8, %xmm5, %xmm6, %xmm12 + vpalignr $8, %xmm1, %xmm2, %xmm13 + # rnd_0: 1 - 1 + movq %r14, %rdx + movq %r11, %rcx + addq 80(%rsp), %r13 + xorq %r12, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 3 + xorq %r10, %rax + andq %r10, %rcx + rorq $4, %rax + xorq %r12, %rcx + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 4 - 5 + xorq %r10, %rax + addq %rcx, %r13 + rorq $14, %rax + xorq %r15, %rdx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 6 - 7 + addq %rax, %r13 + movq %r14, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 8 - 9 + xorq %r14, %rcx + xorq %r15, %rbx + rorq $6, %rcx + addq %r13, %r9 + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm5, %xmm13, %xmm5 + # rnd_0: 10 - 11 + xorq %r14, %rcx + addq %rbx, %r13 + rorq $28, %rcx + movq %r9, %rax + addq %rcx, %r13 + # rnd_1: 0 - 0 + rorq $23, %rax + vpaddq %xmm5, %xmm8, %xmm5 + # rnd_1: 1 - 1 + movq %r13, %rbx + movq %r10, %rcx + addq 88(%rsp), %r12 + xorq %r11, %rcx + vpsrlq $19, %xmm4, %xmm8 + vpsllq $45, %xmm4, %xmm9 + # rnd_1: 2 - 3 + xorq %r9, %rax + andq %r9, %rcx + rorq $4, %rax + xorq %r11, %rcx + vpsrlq $61, %xmm4, %xmm10 + vpsllq $3, %xmm4, %xmm11 + # rnd_1: 4 - 6 + xorq %r9, %rax + addq %rcx, %r12 + rorq $14, %rax + xorq %r14, %rbx + addq %rax, %r12 + movq %r13, %rcx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 7 - 8 + andq %rbx, %rdx + rorq $5, %rcx + xorq %r13, %rcx + xorq %r14, %rdx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm4, %xmm11 + # rnd_1: 9 - 10 + rorq $6, %rcx + addq %r12, %r8 + xorq %r13, %rcx + addq %rdx, %r12 + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 11 - 11 + rorq $28, %rcx + movq %r8, %rax + addq %rcx, %r12 + vpaddq %xmm5, %xmm8, %xmm5 + # msg_sched done: 10-13 + # msg_sched: 12-13 + # rnd_0: 0 - 0 + rorq $23, %rax + vpalignr $8, %xmm6, %xmm7, %xmm12 + vpalignr $8, %xmm2, %xmm3, %xmm13 + # rnd_0: 1 - 1 + movq %r12, %rdx + movq %r9, %rcx + addq 96(%rsp), %r11 + xorq %r10, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 3 + xorq %r8, %rax + andq %r8, %rcx + rorq $4, %rax + xorq %r10, %rcx + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 4 - 5 + xorq %r8, %rax + addq %rcx, %r11 + rorq $14, %rax + xorq %r13, %rdx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 6 - 7 + addq %rax, %r11 + movq %r12, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 8 - 9 + xorq %r12, %rcx + xorq %r13, %rbx + rorq $6, %rcx + addq %r11, %r15 + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm6, %xmm13, %xmm6 + # rnd_0: 10 - 11 + xorq %r12, %rcx + addq %rbx, %r11 + rorq $28, %rcx + movq %r15, %rax + addq %rcx, %r11 + # rnd_1: 0 - 0 + rorq $23, %rax + vpaddq %xmm6, %xmm8, %xmm6 + # rnd_1: 1 - 1 + movq %r11, %rbx + movq %r8, %rcx + addq 104(%rsp), %r10 + xorq %r9, %rcx + vpsrlq $19, %xmm5, %xmm8 + vpsllq $45, %xmm5, %xmm9 + # rnd_1: 2 - 3 + xorq %r15, %rax + andq %r15, %rcx + rorq $4, %rax + xorq %r9, %rcx + vpsrlq $61, %xmm5, %xmm10 + vpsllq $3, %xmm5, %xmm11 + # rnd_1: 4 - 6 + xorq %r15, %rax + addq %rcx, %r10 + rorq $14, %rax + xorq %r12, %rbx + addq %rax, %r10 + movq %r11, %rcx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 7 - 8 + andq %rbx, %rdx + rorq $5, %rcx + xorq %r11, %rcx + xorq %r12, %rdx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm5, %xmm11 + # rnd_1: 9 - 10 + rorq $6, %rcx + addq %r10, %r14 + xorq %r11, %rcx + addq %rdx, %r10 + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 11 - 11 + rorq $28, %rcx + movq %r14, %rax + addq %rcx, %r10 + vpaddq %xmm6, %xmm8, %xmm6 + # msg_sched done: 12-15 + # msg_sched: 14-15 + # rnd_0: 0 - 0 + rorq $23, %rax + vpalignr $8, %xmm7, %xmm0, %xmm12 + vpalignr $8, %xmm3, %xmm4, %xmm13 + # rnd_0: 1 - 1 + movq %r10, %rdx + movq %r15, %rcx + addq 112(%rsp), %r9 + xorq %r8, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 3 + xorq %r14, %rax + andq %r14, %rcx + rorq $4, %rax + xorq %r8, %rcx + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 4 - 5 + xorq %r14, %rax + addq %rcx, %r9 + rorq $14, %rax + xorq %r11, %rdx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 6 - 7 + addq %rax, %r9 + movq %r10, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 8 - 9 + xorq %r10, %rcx + xorq %r11, %rbx + rorq $6, %rcx + addq %r9, %r13 + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm7, %xmm13, %xmm7 + # rnd_0: 10 - 11 + xorq %r10, %rcx + addq %rbx, %r9 + rorq $28, %rcx + movq %r13, %rax + addq %rcx, %r9 + # rnd_1: 0 - 0 + rorq $23, %rax + vpaddq %xmm7, %xmm8, %xmm7 + # rnd_1: 1 - 1 + movq %r9, %rbx + movq %r14, %rcx + addq 120(%rsp), %r8 + xorq %r15, %rcx + vpsrlq $19, %xmm6, %xmm8 + vpsllq $45, %xmm6, %xmm9 + # rnd_1: 2 - 3 + xorq %r13, %rax + andq %r13, %rcx + rorq $4, %rax + xorq %r15, %rcx + vpsrlq $61, %xmm6, %xmm10 + vpsllq $3, %xmm6, %xmm11 + # rnd_1: 4 - 6 + xorq %r13, %rax + addq %rcx, %r8 + rorq $14, %rax + xorq %r10, %rbx + addq %rax, %r8 + movq %r9, %rcx + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 7 - 8 + andq %rbx, %rdx + rorq $5, %rcx + xorq %r9, %rcx + xorq %r10, %rdx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm6, %xmm11 + # rnd_1: 9 - 10 + rorq $6, %rcx + addq %r8, %r12 + xorq %r9, %rcx + addq %rdx, %r8 + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 11 - 11 + rorq $28, %rcx + movq %r12, %rax + addq %rcx, %r8 + vpaddq %xmm7, %xmm8, %xmm7 + # msg_sched done: 14-17 + movq 136(%rsp), %rdx + vpaddq (%rdx), %xmm0, %xmm8 + vpaddq 16(%rdx), %xmm1, %xmm9 + vmovdqu %xmm8, (%rsp) + vmovdqu %xmm9, 16(%rsp) + vpaddq 32(%rdx), %xmm2, %xmm8 + vpaddq 48(%rdx), %xmm3, %xmm9 + vmovdqu %xmm8, 32(%rsp) + vmovdqu %xmm9, 48(%rsp) + vpaddq 64(%rdx), %xmm4, %xmm8 + vpaddq 80(%rdx), %xmm5, %xmm9 + vmovdqu %xmm8, 64(%rsp) + vmovdqu %xmm9, 80(%rsp) + vpaddq 96(%rdx), %xmm6, %xmm8 + vpaddq 112(%rdx), %xmm7, %xmm9 + vmovdqu %xmm8, 96(%rsp) + vmovdqu %xmm9, 112(%rsp) + subl $0x01, 128(%rsp) + jne L_sha512_len_avx1_start + # rnd_all_2: 0-1 + # rnd_0: 0 - 11 + rorq $23, %rax + movq %r8, %rdx + movq %r13, %rcx + addq (%rsp), %r15 + xorq %r14, %rcx + xorq %r12, %rax + andq %r12, %rcx + rorq $4, %rax + xorq %r14, %rcx + xorq %r12, %rax + addq %rcx, %r15 + rorq $14, %rax + xorq %r9, %rdx + addq %rax, %r15 + movq %r8, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r8, %rcx + xorq %r9, %rbx + rorq $6, %rcx + addq %r15, %r11 + xorq %r8, %rcx + addq %rbx, %r15 + rorq $28, %rcx + movq %r11, %rax + addq %rcx, %r15 + # rnd_1: 0 - 11 + rorq $23, %rax + movq %r15, %rbx + movq %r12, %rcx + addq 8(%rsp), %r14 + xorq %r13, %rcx + xorq %r11, %rax + andq %r11, %rcx + rorq $4, %rax + xorq %r13, %rcx + xorq %r11, %rax + addq %rcx, %r14 + rorq $14, %rax + xorq %r8, %rbx + addq %rax, %r14 + movq %r15, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r15, %rcx + xorq %r8, %rdx + rorq $6, %rcx + addq %r14, %r10 + xorq %r15, %rcx + addq %rdx, %r14 + rorq $28, %rcx + movq %r10, %rax + addq %rcx, %r14 + # rnd_all_2: 2-3 + # rnd_0: 0 - 11 + rorq $23, %rax + movq %r14, %rdx + movq %r11, %rcx + addq 16(%rsp), %r13 + xorq %r12, %rcx + xorq %r10, %rax + andq %r10, %rcx + rorq $4, %rax + xorq %r12, %rcx + xorq %r10, %rax + addq %rcx, %r13 + rorq $14, %rax + xorq %r15, %rdx + addq %rax, %r13 + movq %r14, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r14, %rcx + xorq %r15, %rbx + rorq $6, %rcx + addq %r13, %r9 + xorq %r14, %rcx + addq %rbx, %r13 + rorq $28, %rcx + movq %r9, %rax + addq %rcx, %r13 + # rnd_1: 0 - 11 + rorq $23, %rax + movq %r13, %rbx + movq %r10, %rcx + addq 24(%rsp), %r12 + xorq %r11, %rcx + xorq %r9, %rax + andq %r9, %rcx + rorq $4, %rax + xorq %r11, %rcx + xorq %r9, %rax + addq %rcx, %r12 + rorq $14, %rax + xorq %r14, %rbx + addq %rax, %r12 + movq %r13, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r13, %rcx + xorq %r14, %rdx + rorq $6, %rcx + addq %r12, %r8 + xorq %r13, %rcx + addq %rdx, %r12 + rorq $28, %rcx + movq %r8, %rax + addq %rcx, %r12 + # rnd_all_2: 4-5 + # rnd_0: 0 - 11 + rorq $23, %rax + movq %r12, %rdx + movq %r9, %rcx + addq 32(%rsp), %r11 + xorq %r10, %rcx + xorq %r8, %rax + andq %r8, %rcx + rorq $4, %rax + xorq %r10, %rcx + xorq %r8, %rax + addq %rcx, %r11 + rorq $14, %rax + xorq %r13, %rdx + addq %rax, %r11 + movq %r12, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r12, %rcx + xorq %r13, %rbx + rorq $6, %rcx + addq %r11, %r15 + xorq %r12, %rcx + addq %rbx, %r11 + rorq $28, %rcx + movq %r15, %rax + addq %rcx, %r11 + # rnd_1: 0 - 11 + rorq $23, %rax + movq %r11, %rbx + movq %r8, %rcx + addq 40(%rsp), %r10 + xorq %r9, %rcx + xorq %r15, %rax + andq %r15, %rcx + rorq $4, %rax + xorq %r9, %rcx + xorq %r15, %rax + addq %rcx, %r10 + rorq $14, %rax + xorq %r12, %rbx + addq %rax, %r10 + movq %r11, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r11, %rcx + xorq %r12, %rdx + rorq $6, %rcx + addq %r10, %r14 + xorq %r11, %rcx + addq %rdx, %r10 + rorq $28, %rcx + movq %r14, %rax + addq %rcx, %r10 + # rnd_all_2: 6-7 + # rnd_0: 0 - 11 + rorq $23, %rax + movq %r10, %rdx + movq %r15, %rcx + addq 48(%rsp), %r9 + xorq %r8, %rcx + xorq %r14, %rax + andq %r14, %rcx + rorq $4, %rax + xorq %r8, %rcx + xorq %r14, %rax + addq %rcx, %r9 + rorq $14, %rax + xorq %r11, %rdx + addq %rax, %r9 + movq %r10, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r10, %rcx + xorq %r11, %rbx + rorq $6, %rcx + addq %r9, %r13 + xorq %r10, %rcx + addq %rbx, %r9 + rorq $28, %rcx + movq %r13, %rax + addq %rcx, %r9 + # rnd_1: 0 - 11 + rorq $23, %rax + movq %r9, %rbx + movq %r14, %rcx + addq 56(%rsp), %r8 + xorq %r15, %rcx + xorq %r13, %rax + andq %r13, %rcx + rorq $4, %rax + xorq %r15, %rcx + xorq %r13, %rax + addq %rcx, %r8 + rorq $14, %rax + xorq %r10, %rbx + addq %rax, %r8 + movq %r9, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r9, %rcx + xorq %r10, %rdx + rorq $6, %rcx + addq %r8, %r12 + xorq %r9, %rcx + addq %rdx, %r8 + rorq $28, %rcx + movq %r12, %rax + addq %rcx, %r8 + # rnd_all_2: 8-9 + # rnd_0: 0 - 11 + rorq $23, %rax + movq %r8, %rdx + movq %r13, %rcx + addq 64(%rsp), %r15 + xorq %r14, %rcx + xorq %r12, %rax + andq %r12, %rcx + rorq $4, %rax + xorq %r14, %rcx + xorq %r12, %rax + addq %rcx, %r15 + rorq $14, %rax + xorq %r9, %rdx + addq %rax, %r15 + movq %r8, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r8, %rcx + xorq %r9, %rbx + rorq $6, %rcx + addq %r15, %r11 + xorq %r8, %rcx + addq %rbx, %r15 + rorq $28, %rcx + movq %r11, %rax + addq %rcx, %r15 + # rnd_1: 0 - 11 + rorq $23, %rax + movq %r15, %rbx + movq %r12, %rcx + addq 72(%rsp), %r14 + xorq %r13, %rcx + xorq %r11, %rax + andq %r11, %rcx + rorq $4, %rax + xorq %r13, %rcx + xorq %r11, %rax + addq %rcx, %r14 + rorq $14, %rax + xorq %r8, %rbx + addq %rax, %r14 + movq %r15, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r15, %rcx + xorq %r8, %rdx + rorq $6, %rcx + addq %r14, %r10 + xorq %r15, %rcx + addq %rdx, %r14 + rorq $28, %rcx + movq %r10, %rax + addq %rcx, %r14 + # rnd_all_2: 10-11 + # rnd_0: 0 - 11 + rorq $23, %rax + movq %r14, %rdx + movq %r11, %rcx + addq 80(%rsp), %r13 + xorq %r12, %rcx + xorq %r10, %rax + andq %r10, %rcx + rorq $4, %rax + xorq %r12, %rcx + xorq %r10, %rax + addq %rcx, %r13 + rorq $14, %rax + xorq %r15, %rdx + addq %rax, %r13 + movq %r14, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r14, %rcx + xorq %r15, %rbx + rorq $6, %rcx + addq %r13, %r9 + xorq %r14, %rcx + addq %rbx, %r13 + rorq $28, %rcx + movq %r9, %rax + addq %rcx, %r13 + # rnd_1: 0 - 11 + rorq $23, %rax + movq %r13, %rbx + movq %r10, %rcx + addq 88(%rsp), %r12 + xorq %r11, %rcx + xorq %r9, %rax + andq %r9, %rcx + rorq $4, %rax + xorq %r11, %rcx + xorq %r9, %rax + addq %rcx, %r12 + rorq $14, %rax + xorq %r14, %rbx + addq %rax, %r12 + movq %r13, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r13, %rcx + xorq %r14, %rdx + rorq $6, %rcx + addq %r12, %r8 + xorq %r13, %rcx + addq %rdx, %r12 + rorq $28, %rcx + movq %r8, %rax + addq %rcx, %r12 + # rnd_all_2: 12-13 + # rnd_0: 0 - 11 + rorq $23, %rax + movq %r12, %rdx + movq %r9, %rcx + addq 96(%rsp), %r11 + xorq %r10, %rcx + xorq %r8, %rax + andq %r8, %rcx + rorq $4, %rax + xorq %r10, %rcx + xorq %r8, %rax + addq %rcx, %r11 + rorq $14, %rax + xorq %r13, %rdx + addq %rax, %r11 + movq %r12, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r12, %rcx + xorq %r13, %rbx + rorq $6, %rcx + addq %r11, %r15 + xorq %r12, %rcx + addq %rbx, %r11 + rorq $28, %rcx + movq %r15, %rax + addq %rcx, %r11 + # rnd_1: 0 - 11 + rorq $23, %rax + movq %r11, %rbx + movq %r8, %rcx + addq 104(%rsp), %r10 + xorq %r9, %rcx + xorq %r15, %rax + andq %r15, %rcx + rorq $4, %rax + xorq %r9, %rcx + xorq %r15, %rax + addq %rcx, %r10 + rorq $14, %rax + xorq %r12, %rbx + addq %rax, %r10 + movq %r11, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r11, %rcx + xorq %r12, %rdx + rorq $6, %rcx + addq %r10, %r14 + xorq %r11, %rcx + addq %rdx, %r10 + rorq $28, %rcx + movq %r14, %rax + addq %rcx, %r10 + # rnd_all_2: 14-15 + # rnd_0: 0 - 11 + rorq $23, %rax + movq %r10, %rdx + movq %r15, %rcx + addq 112(%rsp), %r9 + xorq %r8, %rcx + xorq %r14, %rax + andq %r14, %rcx + rorq $4, %rax + xorq %r8, %rcx + xorq %r14, %rax + addq %rcx, %r9 + rorq $14, %rax + xorq %r11, %rdx + addq %rax, %r9 + movq %r10, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r10, %rcx + xorq %r11, %rbx + rorq $6, %rcx + addq %r9, %r13 + xorq %r10, %rcx + addq %rbx, %r9 + rorq $28, %rcx + movq %r13, %rax + addq %rcx, %r9 + # rnd_1: 0 - 11 + rorq $23, %rax + movq %r9, %rbx + movq %r14, %rcx + addq 120(%rsp), %r8 + xorq %r15, %rcx + xorq %r13, %rax + andq %r13, %rcx + rorq $4, %rax + xorq %r15, %rcx + xorq %r13, %rax + addq %rcx, %r8 + rorq $14, %rax + xorq %r10, %rbx + addq %rax, %r8 + movq %r9, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r9, %rcx + xorq %r10, %rdx + rorq $6, %rcx + addq %r8, %r12 + xorq %r9, %rcx + addq %rdx, %r8 + rorq $28, %rcx + movq %r12, %rax + addq %rcx, %r8 + addq (%rdi), %r8 + addq 8(%rdi), %r9 + addq 16(%rdi), %r10 + addq 24(%rdi), %r11 + addq 32(%rdi), %r12 + addq 40(%rdi), %r13 + addq 48(%rdi), %r14 + addq 56(%rdi), %r15 + leaq L_avx1_sha512_k(%rip), %rdx + addq $0x80, %rsi + subl $0x80, %ebp + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq %r12, 32(%rdi) + movq %r13, 40(%rdi) + movq %r14, 48(%rdi) + movq %r15, 56(%rdi) + jnz L_sha512_len_avx1_begin + xorq %rax, %rax + vzeroupper + addq $0x90, %rsp + popq %rbp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size Transform_Sha512_AVX1_Len,.-Transform_Sha512_AVX1_Len +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx1_rorx_sha512_k: +.quad 0x428a2f98d728ae22,0x7137449123ef65cd +.quad 0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc +.quad 0x3956c25bf348b538,0x59f111f1b605d019 +.quad 0x923f82a4af194f9b,0xab1c5ed5da6d8118 +.quad 0xd807aa98a3030242,0x12835b0145706fbe +.quad 0x243185be4ee4b28c,0x550c7dc3d5ffb4e2 +.quad 0x72be5d74f27b896f,0x80deb1fe3b1696b1 +.quad 0x9bdc06a725c71235,0xc19bf174cf692694 +.quad 0xe49b69c19ef14ad2,0xefbe4786384f25e3 +.quad 0xfc19dc68b8cd5b5,0x240ca1cc77ac9c65 +.quad 0x2de92c6f592b0275,0x4a7484aa6ea6e483 +.quad 0x5cb0a9dcbd41fbd4,0x76f988da831153b5 +.quad 0x983e5152ee66dfab,0xa831c66d2db43210 +.quad 0xb00327c898fb213f,0xbf597fc7beef0ee4 +.quad 0xc6e00bf33da88fc2,0xd5a79147930aa725 +.quad 0x6ca6351e003826f,0x142929670a0e6e70 +.quad 0x27b70a8546d22ffc,0x2e1b21385c26c926 +.quad 0x4d2c6dfc5ac42aed,0x53380d139d95b3df +.quad 0x650a73548baf63de,0x766a0abb3c77b2a8 +.quad 0x81c2c92e47edaee6,0x92722c851482353b +.quad 0xa2bfe8a14cf10364,0xa81a664bbc423001 +.quad 0xc24b8b70d0f89791,0xc76c51a30654be30 +.quad 0xd192e819d6ef5218,0xd69906245565a910 +.quad 0xf40e35855771202a,0x106aa07032bbd1b8 +.quad 0x19a4c116b8d2d0c8,0x1e376c085141ab53 +.quad 0x2748774cdf8eeb99,0x34b0bcb5e19b48a8 +.quad 0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb +.quad 0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3 +.quad 0x748f82ee5defb2fc,0x78a5636f43172f60 +.quad 0x84c87814a1f0ab72,0x8cc702081a6439ec +.quad 0x90befffa23631e28,0xa4506cebde82bde9 +.quad 0xbef9a3f7b2c67915,0xc67178f2e372532b +.quad 0xca273eceea26619c,0xd186b8c721c0c207 +.quad 0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178 +.quad 0x6f067aa72176fba,0xa637dc5a2c898a6 +.quad 0x113f9804bef90dae,0x1b710b35131c471b +.quad 0x28db77f523047d84,0x32caab7b40c72493 +.quad 0x3c9ebe0a15c9bebc,0x431d67c49c100d4c +.quad 0x4cc5d4becb3e42b6,0x597f299cfc657e2a +.quad 0x5fcb6fab3ad6faec,0x6c44198c4a475817 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx1_rorx_sha512_flip_mask: +.quad 0x1020304050607, 0x8090a0b0c0d0e0f +#ifndef __APPLE__ +.text +.globl Transform_Sha512_AVX1_RORX +.type Transform_Sha512_AVX1_RORX,@function +.align 4 +Transform_Sha512_AVX1_RORX: +#else +.section __TEXT,__text +.globl _Transform_Sha512_AVX1_RORX +.p2align 2 +_Transform_Sha512_AVX1_RORX: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + subq $0x88, %rsp + leaq 64(%rdi), %rax + vmovdqa L_avx1_rorx_sha512_flip_mask(%rip), %xmm14 + movq (%rdi), %r8 + movq 8(%rdi), %r9 + movq 16(%rdi), %r10 + movq 24(%rdi), %r11 + movq 32(%rdi), %r12 + movq 40(%rdi), %r13 + movq 48(%rdi), %r14 + movq 56(%rdi), %r15 + vmovdqu (%rax), %xmm0 + vmovdqu 16(%rax), %xmm1 + vpshufb %xmm14, %xmm0, %xmm0 + vpshufb %xmm14, %xmm1, %xmm1 + vmovdqu 32(%rax), %xmm2 + vmovdqu 48(%rax), %xmm3 + vpshufb %xmm14, %xmm2, %xmm2 + vpshufb %xmm14, %xmm3, %xmm3 + vmovdqu 64(%rax), %xmm4 + vmovdqu 80(%rax), %xmm5 + vpshufb %xmm14, %xmm4, %xmm4 + vpshufb %xmm14, %xmm5, %xmm5 + vmovdqu 96(%rax), %xmm6 + vmovdqu 112(%rax), %xmm7 + vpshufb %xmm14, %xmm6, %xmm6 + vpshufb %xmm14, %xmm7, %xmm7 + movl $4, 128(%rsp) + leaq L_avx1_rorx_sha512_k(%rip), %rsi + movq %r9, %rbx + xorq %rdx, %rdx + xorq %r10, %rbx + vpaddq (%rsi), %xmm0, %xmm8 + vpaddq 16(%rsi), %xmm1, %xmm9 + vmovdqu %xmm8, (%rsp) + vmovdqu %xmm9, 16(%rsp) + vpaddq 32(%rsi), %xmm2, %xmm8 + vpaddq 48(%rsi), %xmm3, %xmm9 + vmovdqu %xmm8, 32(%rsp) + vmovdqu %xmm9, 48(%rsp) + vpaddq 64(%rsi), %xmm4, %xmm8 + vpaddq 80(%rsi), %xmm5, %xmm9 + vmovdqu %xmm8, 64(%rsp) + vmovdqu %xmm9, 80(%rsp) + vpaddq 96(%rsi), %xmm6, %xmm8 + vpaddq 112(%rsi), %xmm7, %xmm9 + vmovdqu %xmm8, 96(%rsp) + vmovdqu %xmm9, 112(%rsp) + # Start of 16 rounds +L_sha256_len_avx1_rorx_start: + addq $0x80, %rsi + # msg_sched: 0-1 + # rnd_0: 0 - 0 + rorxq $14, %r12, %rax + rorxq $18, %r12, %rcx + addq %rdx, %r8 + vpalignr $8, %xmm0, %xmm1, %xmm12 + vpalignr $8, %xmm4, %xmm5, %xmm13 + # rnd_0: 1 - 1 + addq (%rsp), %r15 + movq %r13, %rdx + xorq %rax, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 2 + xorq %r14, %rdx + rorxq $41, %r12, %rax + xorq %rcx, %rax + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 3 - 3 + andq %r12, %rdx + addq %rax, %r15 + rorxq $28, %r8, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 4 - 4 + rorxq $34, %r8, %rcx + xorq %r14, %rdx + xorq %rax, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 5 - 5 + rorxq $39, %r8, %rax + addq %rdx, %r15 + xorq %rcx, %rax + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm0, %xmm13, %xmm0 + # rnd_0: 6 - 7 + movq %r9, %rdx + addq %r15, %r11 + xorq %r8, %rdx + andq %rdx, %rbx + addq %rax, %r15 + xorq %r9, %rbx + vpaddq %xmm0, %xmm8, %xmm0 + # rnd_1: 0 - 0 + rorxq $14, %r11, %rax + rorxq $18, %r11, %rcx + addq %rbx, %r15 + vpsrlq $19, %xmm7, %xmm8 + vpsllq $45, %xmm7, %xmm9 + # rnd_1: 1 - 1 + addq 8(%rsp), %r14 + movq %r12, %rbx + xorq %rax, %rcx + vpsrlq $61, %xmm7, %xmm10 + vpsllq $3, %xmm7, %xmm11 + # rnd_1: 2 - 2 + xorq %r13, %rbx + rorxq $41, %r11, %rax + xorq %rcx, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 3 - 4 + andq %r11, %rbx + addq %rax, %r14 + rorxq $28, %r15, %rax + rorxq $34, %r15, %rcx + xorq %r13, %rbx + xorq %rax, %rcx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm7, %xmm11 + # rnd_1: 5 - 6 + rorxq $39, %r15, %rax + addq %rbx, %r14 + xorq %rcx, %rax + movq %r8, %rbx + addq %r14, %r10 + xorq %r15, %rbx + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 7 - 7 + andq %rbx, %rdx + addq %rax, %r14 + xorq %r8, %rdx + vpaddq %xmm0, %xmm8, %xmm0 + # msg_sched done: 0-3 + # msg_sched: 2-3 + # rnd_0: 0 - 0 + rorxq $14, %r10, %rax + rorxq $18, %r10, %rcx + addq %rdx, %r14 + vpalignr $8, %xmm1, %xmm2, %xmm12 + vpalignr $8, %xmm5, %xmm6, %xmm13 + # rnd_0: 1 - 1 + addq 16(%rsp), %r13 + movq %r11, %rdx + xorq %rax, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 2 + xorq %r12, %rdx + rorxq $41, %r10, %rax + xorq %rcx, %rax + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 3 - 3 + andq %r10, %rdx + addq %rax, %r13 + rorxq $28, %r14, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 4 - 4 + rorxq $34, %r14, %rcx + xorq %r12, %rdx + xorq %rax, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 5 - 5 + rorxq $39, %r14, %rax + addq %rdx, %r13 + xorq %rcx, %rax + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm1, %xmm13, %xmm1 + # rnd_0: 6 - 7 + movq %r15, %rdx + addq %r13, %r9 + xorq %r14, %rdx + andq %rdx, %rbx + addq %rax, %r13 + xorq %r15, %rbx + vpaddq %xmm1, %xmm8, %xmm1 + # rnd_1: 0 - 0 + rorxq $14, %r9, %rax + rorxq $18, %r9, %rcx + addq %rbx, %r13 + vpsrlq $19, %xmm0, %xmm8 + vpsllq $45, %xmm0, %xmm9 + # rnd_1: 1 - 1 + addq 24(%rsp), %r12 + movq %r10, %rbx + xorq %rax, %rcx + vpsrlq $61, %xmm0, %xmm10 + vpsllq $3, %xmm0, %xmm11 + # rnd_1: 2 - 2 + xorq %r11, %rbx + rorxq $41, %r9, %rax + xorq %rcx, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 3 - 4 + andq %r9, %rbx + addq %rax, %r12 + rorxq $28, %r13, %rax + rorxq $34, %r13, %rcx + xorq %r11, %rbx + xorq %rax, %rcx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm0, %xmm11 + # rnd_1: 5 - 6 + rorxq $39, %r13, %rax + addq %rbx, %r12 + xorq %rcx, %rax + movq %r14, %rbx + addq %r12, %r8 + xorq %r13, %rbx + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 7 - 7 + andq %rbx, %rdx + addq %rax, %r12 + xorq %r14, %rdx + vpaddq %xmm1, %xmm8, %xmm1 + # msg_sched done: 2-5 + # msg_sched: 4-5 + # rnd_0: 0 - 0 + rorxq $14, %r8, %rax + rorxq $18, %r8, %rcx + addq %rdx, %r12 + vpalignr $8, %xmm2, %xmm3, %xmm12 + vpalignr $8, %xmm6, %xmm7, %xmm13 + # rnd_0: 1 - 1 + addq 32(%rsp), %r11 + movq %r9, %rdx + xorq %rax, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 2 + xorq %r10, %rdx + rorxq $41, %r8, %rax + xorq %rcx, %rax + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 3 - 3 + andq %r8, %rdx + addq %rax, %r11 + rorxq $28, %r12, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 4 - 4 + rorxq $34, %r12, %rcx + xorq %r10, %rdx + xorq %rax, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 5 - 5 + rorxq $39, %r12, %rax + addq %rdx, %r11 + xorq %rcx, %rax + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm2, %xmm13, %xmm2 + # rnd_0: 6 - 7 + movq %r13, %rdx + addq %r11, %r15 + xorq %r12, %rdx + andq %rdx, %rbx + addq %rax, %r11 + xorq %r13, %rbx + vpaddq %xmm2, %xmm8, %xmm2 + # rnd_1: 0 - 0 + rorxq $14, %r15, %rax + rorxq $18, %r15, %rcx + addq %rbx, %r11 + vpsrlq $19, %xmm1, %xmm8 + vpsllq $45, %xmm1, %xmm9 + # rnd_1: 1 - 1 + addq 40(%rsp), %r10 + movq %r8, %rbx + xorq %rax, %rcx + vpsrlq $61, %xmm1, %xmm10 + vpsllq $3, %xmm1, %xmm11 + # rnd_1: 2 - 2 + xorq %r9, %rbx + rorxq $41, %r15, %rax + xorq %rcx, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 3 - 4 + andq %r15, %rbx + addq %rax, %r10 + rorxq $28, %r11, %rax + rorxq $34, %r11, %rcx + xorq %r9, %rbx + xorq %rax, %rcx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm1, %xmm11 + # rnd_1: 5 - 6 + rorxq $39, %r11, %rax + addq %rbx, %r10 + xorq %rcx, %rax + movq %r12, %rbx + addq %r10, %r14 + xorq %r11, %rbx + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 7 - 7 + andq %rbx, %rdx + addq %rax, %r10 + xorq %r12, %rdx + vpaddq %xmm2, %xmm8, %xmm2 + # msg_sched done: 4-7 + # msg_sched: 6-7 + # rnd_0: 0 - 0 + rorxq $14, %r14, %rax + rorxq $18, %r14, %rcx + addq %rdx, %r10 + vpalignr $8, %xmm3, %xmm4, %xmm12 + vpalignr $8, %xmm7, %xmm0, %xmm13 + # rnd_0: 1 - 1 + addq 48(%rsp), %r9 + movq %r15, %rdx + xorq %rax, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 2 + xorq %r8, %rdx + rorxq $41, %r14, %rax + xorq %rcx, %rax + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 3 - 3 + andq %r14, %rdx + addq %rax, %r9 + rorxq $28, %r10, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 4 - 4 + rorxq $34, %r10, %rcx + xorq %r8, %rdx + xorq %rax, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 5 - 5 + rorxq $39, %r10, %rax + addq %rdx, %r9 + xorq %rcx, %rax + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm3, %xmm13, %xmm3 + # rnd_0: 6 - 7 + movq %r11, %rdx + addq %r9, %r13 + xorq %r10, %rdx + andq %rdx, %rbx + addq %rax, %r9 + xorq %r11, %rbx + vpaddq %xmm3, %xmm8, %xmm3 + # rnd_1: 0 - 0 + rorxq $14, %r13, %rax + rorxq $18, %r13, %rcx + addq %rbx, %r9 + vpsrlq $19, %xmm2, %xmm8 + vpsllq $45, %xmm2, %xmm9 + # rnd_1: 1 - 1 + addq 56(%rsp), %r8 + movq %r14, %rbx + xorq %rax, %rcx + vpsrlq $61, %xmm2, %xmm10 + vpsllq $3, %xmm2, %xmm11 + # rnd_1: 2 - 2 + xorq %r15, %rbx + rorxq $41, %r13, %rax + xorq %rcx, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 3 - 4 + andq %r13, %rbx + addq %rax, %r8 + rorxq $28, %r9, %rax + rorxq $34, %r9, %rcx + xorq %r15, %rbx + xorq %rax, %rcx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm2, %xmm11 + # rnd_1: 5 - 6 + rorxq $39, %r9, %rax + addq %rbx, %r8 + xorq %rcx, %rax + movq %r10, %rbx + addq %r8, %r12 + xorq %r9, %rbx + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 7 - 7 + andq %rbx, %rdx + addq %rax, %r8 + xorq %r10, %rdx + vpaddq %xmm3, %xmm8, %xmm3 + # msg_sched done: 6-9 + # msg_sched: 8-9 + # rnd_0: 0 - 0 + rorxq $14, %r12, %rax + rorxq $18, %r12, %rcx + addq %rdx, %r8 + vpalignr $8, %xmm4, %xmm5, %xmm12 + vpalignr $8, %xmm0, %xmm1, %xmm13 + # rnd_0: 1 - 1 + addq 64(%rsp), %r15 + movq %r13, %rdx + xorq %rax, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 2 + xorq %r14, %rdx + rorxq $41, %r12, %rax + xorq %rcx, %rax + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 3 - 3 + andq %r12, %rdx + addq %rax, %r15 + rorxq $28, %r8, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 4 - 4 + rorxq $34, %r8, %rcx + xorq %r14, %rdx + xorq %rax, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 5 - 5 + rorxq $39, %r8, %rax + addq %rdx, %r15 + xorq %rcx, %rax + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm4, %xmm13, %xmm4 + # rnd_0: 6 - 7 + movq %r9, %rdx + addq %r15, %r11 + xorq %r8, %rdx + andq %rdx, %rbx + addq %rax, %r15 + xorq %r9, %rbx + vpaddq %xmm4, %xmm8, %xmm4 + # rnd_1: 0 - 0 + rorxq $14, %r11, %rax + rorxq $18, %r11, %rcx + addq %rbx, %r15 + vpsrlq $19, %xmm3, %xmm8 + vpsllq $45, %xmm3, %xmm9 + # rnd_1: 1 - 1 + addq 72(%rsp), %r14 + movq %r12, %rbx + xorq %rax, %rcx + vpsrlq $61, %xmm3, %xmm10 + vpsllq $3, %xmm3, %xmm11 + # rnd_1: 2 - 2 + xorq %r13, %rbx + rorxq $41, %r11, %rax + xorq %rcx, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 3 - 4 + andq %r11, %rbx + addq %rax, %r14 + rorxq $28, %r15, %rax + rorxq $34, %r15, %rcx + xorq %r13, %rbx + xorq %rax, %rcx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm3, %xmm11 + # rnd_1: 5 - 6 + rorxq $39, %r15, %rax + addq %rbx, %r14 + xorq %rcx, %rax + movq %r8, %rbx + addq %r14, %r10 + xorq %r15, %rbx + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 7 - 7 + andq %rbx, %rdx + addq %rax, %r14 + xorq %r8, %rdx + vpaddq %xmm4, %xmm8, %xmm4 + # msg_sched done: 8-11 + # msg_sched: 10-11 + # rnd_0: 0 - 0 + rorxq $14, %r10, %rax + rorxq $18, %r10, %rcx + addq %rdx, %r14 + vpalignr $8, %xmm5, %xmm6, %xmm12 + vpalignr $8, %xmm1, %xmm2, %xmm13 + # rnd_0: 1 - 1 + addq 80(%rsp), %r13 + movq %r11, %rdx + xorq %rax, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 2 + xorq %r12, %rdx + rorxq $41, %r10, %rax + xorq %rcx, %rax + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 3 - 3 + andq %r10, %rdx + addq %rax, %r13 + rorxq $28, %r14, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 4 - 4 + rorxq $34, %r14, %rcx + xorq %r12, %rdx + xorq %rax, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 5 - 5 + rorxq $39, %r14, %rax + addq %rdx, %r13 + xorq %rcx, %rax + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm5, %xmm13, %xmm5 + # rnd_0: 6 - 7 + movq %r15, %rdx + addq %r13, %r9 + xorq %r14, %rdx + andq %rdx, %rbx + addq %rax, %r13 + xorq %r15, %rbx + vpaddq %xmm5, %xmm8, %xmm5 + # rnd_1: 0 - 0 + rorxq $14, %r9, %rax + rorxq $18, %r9, %rcx + addq %rbx, %r13 + vpsrlq $19, %xmm4, %xmm8 + vpsllq $45, %xmm4, %xmm9 + # rnd_1: 1 - 1 + addq 88(%rsp), %r12 + movq %r10, %rbx + xorq %rax, %rcx + vpsrlq $61, %xmm4, %xmm10 + vpsllq $3, %xmm4, %xmm11 + # rnd_1: 2 - 2 + xorq %r11, %rbx + rorxq $41, %r9, %rax + xorq %rcx, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 3 - 4 + andq %r9, %rbx + addq %rax, %r12 + rorxq $28, %r13, %rax + rorxq $34, %r13, %rcx + xorq %r11, %rbx + xorq %rax, %rcx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm4, %xmm11 + # rnd_1: 5 - 6 + rorxq $39, %r13, %rax + addq %rbx, %r12 + xorq %rcx, %rax + movq %r14, %rbx + addq %r12, %r8 + xorq %r13, %rbx + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 7 - 7 + andq %rbx, %rdx + addq %rax, %r12 + xorq %r14, %rdx + vpaddq %xmm5, %xmm8, %xmm5 + # msg_sched done: 10-13 + # msg_sched: 12-13 + # rnd_0: 0 - 0 + rorxq $14, %r8, %rax + rorxq $18, %r8, %rcx + addq %rdx, %r12 + vpalignr $8, %xmm6, %xmm7, %xmm12 + vpalignr $8, %xmm2, %xmm3, %xmm13 + # rnd_0: 1 - 1 + addq 96(%rsp), %r11 + movq %r9, %rdx + xorq %rax, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 2 + xorq %r10, %rdx + rorxq $41, %r8, %rax + xorq %rcx, %rax + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 3 - 3 + andq %r8, %rdx + addq %rax, %r11 + rorxq $28, %r12, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 4 - 4 + rorxq $34, %r12, %rcx + xorq %r10, %rdx + xorq %rax, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 5 - 5 + rorxq $39, %r12, %rax + addq %rdx, %r11 + xorq %rcx, %rax + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm6, %xmm13, %xmm6 + # rnd_0: 6 - 7 + movq %r13, %rdx + addq %r11, %r15 + xorq %r12, %rdx + andq %rdx, %rbx + addq %rax, %r11 + xorq %r13, %rbx + vpaddq %xmm6, %xmm8, %xmm6 + # rnd_1: 0 - 0 + rorxq $14, %r15, %rax + rorxq $18, %r15, %rcx + addq %rbx, %r11 + vpsrlq $19, %xmm5, %xmm8 + vpsllq $45, %xmm5, %xmm9 + # rnd_1: 1 - 1 + addq 104(%rsp), %r10 + movq %r8, %rbx + xorq %rax, %rcx + vpsrlq $61, %xmm5, %xmm10 + vpsllq $3, %xmm5, %xmm11 + # rnd_1: 2 - 2 + xorq %r9, %rbx + rorxq $41, %r15, %rax + xorq %rcx, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 3 - 4 + andq %r15, %rbx + addq %rax, %r10 + rorxq $28, %r11, %rax + rorxq $34, %r11, %rcx + xorq %r9, %rbx + xorq %rax, %rcx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm5, %xmm11 + # rnd_1: 5 - 6 + rorxq $39, %r11, %rax + addq %rbx, %r10 + xorq %rcx, %rax + movq %r12, %rbx + addq %r10, %r14 + xorq %r11, %rbx + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 7 - 7 + andq %rbx, %rdx + addq %rax, %r10 + xorq %r12, %rdx + vpaddq %xmm6, %xmm8, %xmm6 + # msg_sched done: 12-15 + # msg_sched: 14-15 + # rnd_0: 0 - 0 + rorxq $14, %r14, %rax + rorxq $18, %r14, %rcx + addq %rdx, %r10 + vpalignr $8, %xmm7, %xmm0, %xmm12 + vpalignr $8, %xmm3, %xmm4, %xmm13 + # rnd_0: 1 - 1 + addq 112(%rsp), %r9 + movq %r15, %rdx + xorq %rax, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 2 + xorq %r8, %rdx + rorxq $41, %r14, %rax + xorq %rcx, %rax + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 3 - 3 + andq %r14, %rdx + addq %rax, %r9 + rorxq $28, %r10, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 4 - 4 + rorxq $34, %r10, %rcx + xorq %r8, %rdx + xorq %rax, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 5 - 5 + rorxq $39, %r10, %rax + addq %rdx, %r9 + xorq %rcx, %rax + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm7, %xmm13, %xmm7 + # rnd_0: 6 - 7 + movq %r11, %rdx + addq %r9, %r13 + xorq %r10, %rdx + andq %rdx, %rbx + addq %rax, %r9 + xorq %r11, %rbx + vpaddq %xmm7, %xmm8, %xmm7 + # rnd_1: 0 - 0 + rorxq $14, %r13, %rax + rorxq $18, %r13, %rcx + addq %rbx, %r9 + vpsrlq $19, %xmm6, %xmm8 + vpsllq $45, %xmm6, %xmm9 + # rnd_1: 1 - 1 + addq 120(%rsp), %r8 + movq %r14, %rbx + xorq %rax, %rcx + vpsrlq $61, %xmm6, %xmm10 + vpsllq $3, %xmm6, %xmm11 + # rnd_1: 2 - 2 + xorq %r15, %rbx + rorxq $41, %r13, %rax + xorq %rcx, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 3 - 4 + andq %r13, %rbx + addq %rax, %r8 + rorxq $28, %r9, %rax + rorxq $34, %r9, %rcx + xorq %r15, %rbx + xorq %rax, %rcx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm6, %xmm11 + # rnd_1: 5 - 6 + rorxq $39, %r9, %rax + addq %rbx, %r8 + xorq %rcx, %rax + movq %r10, %rbx + addq %r8, %r12 + xorq %r9, %rbx + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 7 - 7 + andq %rbx, %rdx + addq %rax, %r8 + xorq %r10, %rdx + vpaddq %xmm7, %xmm8, %xmm7 + # msg_sched done: 14-17 + vpaddq (%rsi), %xmm0, %xmm8 + vpaddq 16(%rsi), %xmm1, %xmm9 + vmovdqu %xmm8, (%rsp) + vmovdqu %xmm9, 16(%rsp) + vpaddq 32(%rsi), %xmm2, %xmm8 + vpaddq 48(%rsi), %xmm3, %xmm9 + vmovdqu %xmm8, 32(%rsp) + vmovdqu %xmm9, 48(%rsp) + vpaddq 64(%rsi), %xmm4, %xmm8 + vpaddq 80(%rsi), %xmm5, %xmm9 + vmovdqu %xmm8, 64(%rsp) + vmovdqu %xmm9, 80(%rsp) + vpaddq 96(%rsi), %xmm6, %xmm8 + vpaddq 112(%rsi), %xmm7, %xmm9 + vmovdqu %xmm8, 96(%rsp) + vmovdqu %xmm9, 112(%rsp) + subl $0x01, 128(%rsp) + jne L_sha256_len_avx1_rorx_start + # rnd_all_2: 0-1 + # rnd_0: 0 - 7 + rorxq $14, %r12, %rax + rorxq $18, %r12, %rcx + addq %rdx, %r8 + addq (%rsp), %r15 + movq %r13, %rdx + xorq %rax, %rcx + xorq %r14, %rdx + rorxq $41, %r12, %rax + xorq %rcx, %rax + andq %r12, %rdx + addq %rax, %r15 + rorxq $28, %r8, %rax + rorxq $34, %r8, %rcx + xorq %r14, %rdx + xorq %rax, %rcx + rorxq $39, %r8, %rax + addq %rdx, %r15 + xorq %rcx, %rax + movq %r9, %rdx + addq %r15, %r11 + xorq %r8, %rdx + andq %rdx, %rbx + addq %rax, %r15 + xorq %r9, %rbx + # rnd_1: 0 - 7 + rorxq $14, %r11, %rax + rorxq $18, %r11, %rcx + addq %rbx, %r15 + addq 8(%rsp), %r14 + movq %r12, %rbx + xorq %rax, %rcx + xorq %r13, %rbx + rorxq $41, %r11, %rax + xorq %rcx, %rax + andq %r11, %rbx + addq %rax, %r14 + rorxq $28, %r15, %rax + rorxq $34, %r15, %rcx + xorq %r13, %rbx + xorq %rax, %rcx + rorxq $39, %r15, %rax + addq %rbx, %r14 + xorq %rcx, %rax + movq %r8, %rbx + addq %r14, %r10 + xorq %r15, %rbx + andq %rbx, %rdx + addq %rax, %r14 + xorq %r8, %rdx + # rnd_all_2: 2-3 + # rnd_0: 0 - 7 + rorxq $14, %r10, %rax + rorxq $18, %r10, %rcx + addq %rdx, %r14 + addq 16(%rsp), %r13 + movq %r11, %rdx + xorq %rax, %rcx + xorq %r12, %rdx + rorxq $41, %r10, %rax + xorq %rcx, %rax + andq %r10, %rdx + addq %rax, %r13 + rorxq $28, %r14, %rax + rorxq $34, %r14, %rcx + xorq %r12, %rdx + xorq %rax, %rcx + rorxq $39, %r14, %rax + addq %rdx, %r13 + xorq %rcx, %rax + movq %r15, %rdx + addq %r13, %r9 + xorq %r14, %rdx + andq %rdx, %rbx + addq %rax, %r13 + xorq %r15, %rbx + # rnd_1: 0 - 7 + rorxq $14, %r9, %rax + rorxq $18, %r9, %rcx + addq %rbx, %r13 + addq 24(%rsp), %r12 + movq %r10, %rbx + xorq %rax, %rcx + xorq %r11, %rbx + rorxq $41, %r9, %rax + xorq %rcx, %rax + andq %r9, %rbx + addq %rax, %r12 + rorxq $28, %r13, %rax + rorxq $34, %r13, %rcx + xorq %r11, %rbx + xorq %rax, %rcx + rorxq $39, %r13, %rax + addq %rbx, %r12 + xorq %rcx, %rax + movq %r14, %rbx + addq %r12, %r8 + xorq %r13, %rbx + andq %rbx, %rdx + addq %rax, %r12 + xorq %r14, %rdx + # rnd_all_2: 4-5 + # rnd_0: 0 - 7 + rorxq $14, %r8, %rax + rorxq $18, %r8, %rcx + addq %rdx, %r12 + addq 32(%rsp), %r11 + movq %r9, %rdx + xorq %rax, %rcx + xorq %r10, %rdx + rorxq $41, %r8, %rax + xorq %rcx, %rax + andq %r8, %rdx + addq %rax, %r11 + rorxq $28, %r12, %rax + rorxq $34, %r12, %rcx + xorq %r10, %rdx + xorq %rax, %rcx + rorxq $39, %r12, %rax + addq %rdx, %r11 + xorq %rcx, %rax + movq %r13, %rdx + addq %r11, %r15 + xorq %r12, %rdx + andq %rdx, %rbx + addq %rax, %r11 + xorq %r13, %rbx + # rnd_1: 0 - 7 + rorxq $14, %r15, %rax + rorxq $18, %r15, %rcx + addq %rbx, %r11 + addq 40(%rsp), %r10 + movq %r8, %rbx + xorq %rax, %rcx + xorq %r9, %rbx + rorxq $41, %r15, %rax + xorq %rcx, %rax + andq %r15, %rbx + addq %rax, %r10 + rorxq $28, %r11, %rax + rorxq $34, %r11, %rcx + xorq %r9, %rbx + xorq %rax, %rcx + rorxq $39, %r11, %rax + addq %rbx, %r10 + xorq %rcx, %rax + movq %r12, %rbx + addq %r10, %r14 + xorq %r11, %rbx + andq %rbx, %rdx + addq %rax, %r10 + xorq %r12, %rdx + # rnd_all_2: 6-7 + # rnd_0: 0 - 7 + rorxq $14, %r14, %rax + rorxq $18, %r14, %rcx + addq %rdx, %r10 + addq 48(%rsp), %r9 + movq %r15, %rdx + xorq %rax, %rcx + xorq %r8, %rdx + rorxq $41, %r14, %rax + xorq %rcx, %rax + andq %r14, %rdx + addq %rax, %r9 + rorxq $28, %r10, %rax + rorxq $34, %r10, %rcx + xorq %r8, %rdx + xorq %rax, %rcx + rorxq $39, %r10, %rax + addq %rdx, %r9 + xorq %rcx, %rax + movq %r11, %rdx + addq %r9, %r13 + xorq %r10, %rdx + andq %rdx, %rbx + addq %rax, %r9 + xorq %r11, %rbx + # rnd_1: 0 - 7 + rorxq $14, %r13, %rax + rorxq $18, %r13, %rcx + addq %rbx, %r9 + addq 56(%rsp), %r8 + movq %r14, %rbx + xorq %rax, %rcx + xorq %r15, %rbx + rorxq $41, %r13, %rax + xorq %rcx, %rax + andq %r13, %rbx + addq %rax, %r8 + rorxq $28, %r9, %rax + rorxq $34, %r9, %rcx + xorq %r15, %rbx + xorq %rax, %rcx + rorxq $39, %r9, %rax + addq %rbx, %r8 + xorq %rcx, %rax + movq %r10, %rbx + addq %r8, %r12 + xorq %r9, %rbx + andq %rbx, %rdx + addq %rax, %r8 + xorq %r10, %rdx + # rnd_all_2: 8-9 + # rnd_0: 0 - 7 + rorxq $14, %r12, %rax + rorxq $18, %r12, %rcx + addq %rdx, %r8 + addq 64(%rsp), %r15 + movq %r13, %rdx + xorq %rax, %rcx + xorq %r14, %rdx + rorxq $41, %r12, %rax + xorq %rcx, %rax + andq %r12, %rdx + addq %rax, %r15 + rorxq $28, %r8, %rax + rorxq $34, %r8, %rcx + xorq %r14, %rdx + xorq %rax, %rcx + rorxq $39, %r8, %rax + addq %rdx, %r15 + xorq %rcx, %rax + movq %r9, %rdx + addq %r15, %r11 + xorq %r8, %rdx + andq %rdx, %rbx + addq %rax, %r15 + xorq %r9, %rbx + # rnd_1: 0 - 7 + rorxq $14, %r11, %rax + rorxq $18, %r11, %rcx + addq %rbx, %r15 + addq 72(%rsp), %r14 + movq %r12, %rbx + xorq %rax, %rcx + xorq %r13, %rbx + rorxq $41, %r11, %rax + xorq %rcx, %rax + andq %r11, %rbx + addq %rax, %r14 + rorxq $28, %r15, %rax + rorxq $34, %r15, %rcx + xorq %r13, %rbx + xorq %rax, %rcx + rorxq $39, %r15, %rax + addq %rbx, %r14 + xorq %rcx, %rax + movq %r8, %rbx + addq %r14, %r10 + xorq %r15, %rbx + andq %rbx, %rdx + addq %rax, %r14 + xorq %r8, %rdx + # rnd_all_2: 10-11 + # rnd_0: 0 - 7 + rorxq $14, %r10, %rax + rorxq $18, %r10, %rcx + addq %rdx, %r14 + addq 80(%rsp), %r13 + movq %r11, %rdx + xorq %rax, %rcx + xorq %r12, %rdx + rorxq $41, %r10, %rax + xorq %rcx, %rax + andq %r10, %rdx + addq %rax, %r13 + rorxq $28, %r14, %rax + rorxq $34, %r14, %rcx + xorq %r12, %rdx + xorq %rax, %rcx + rorxq $39, %r14, %rax + addq %rdx, %r13 + xorq %rcx, %rax + movq %r15, %rdx + addq %r13, %r9 + xorq %r14, %rdx + andq %rdx, %rbx + addq %rax, %r13 + xorq %r15, %rbx + # rnd_1: 0 - 7 + rorxq $14, %r9, %rax + rorxq $18, %r9, %rcx + addq %rbx, %r13 + addq 88(%rsp), %r12 + movq %r10, %rbx + xorq %rax, %rcx + xorq %r11, %rbx + rorxq $41, %r9, %rax + xorq %rcx, %rax + andq %r9, %rbx + addq %rax, %r12 + rorxq $28, %r13, %rax + rorxq $34, %r13, %rcx + xorq %r11, %rbx + xorq %rax, %rcx + rorxq $39, %r13, %rax + addq %rbx, %r12 + xorq %rcx, %rax + movq %r14, %rbx + addq %r12, %r8 + xorq %r13, %rbx + andq %rbx, %rdx + addq %rax, %r12 + xorq %r14, %rdx + # rnd_all_2: 12-13 + # rnd_0: 0 - 7 + rorxq $14, %r8, %rax + rorxq $18, %r8, %rcx + addq %rdx, %r12 + addq 96(%rsp), %r11 + movq %r9, %rdx + xorq %rax, %rcx + xorq %r10, %rdx + rorxq $41, %r8, %rax + xorq %rcx, %rax + andq %r8, %rdx + addq %rax, %r11 + rorxq $28, %r12, %rax + rorxq $34, %r12, %rcx + xorq %r10, %rdx + xorq %rax, %rcx + rorxq $39, %r12, %rax + addq %rdx, %r11 + xorq %rcx, %rax + movq %r13, %rdx + addq %r11, %r15 + xorq %r12, %rdx + andq %rdx, %rbx + addq %rax, %r11 + xorq %r13, %rbx + # rnd_1: 0 - 7 + rorxq $14, %r15, %rax + rorxq $18, %r15, %rcx + addq %rbx, %r11 + addq 104(%rsp), %r10 + movq %r8, %rbx + xorq %rax, %rcx + xorq %r9, %rbx + rorxq $41, %r15, %rax + xorq %rcx, %rax + andq %r15, %rbx + addq %rax, %r10 + rorxq $28, %r11, %rax + rorxq $34, %r11, %rcx + xorq %r9, %rbx + xorq %rax, %rcx + rorxq $39, %r11, %rax + addq %rbx, %r10 + xorq %rcx, %rax + movq %r12, %rbx + addq %r10, %r14 + xorq %r11, %rbx + andq %rbx, %rdx + addq %rax, %r10 + xorq %r12, %rdx + # rnd_all_2: 14-15 + # rnd_0: 0 - 7 + rorxq $14, %r14, %rax + rorxq $18, %r14, %rcx + addq %rdx, %r10 + addq 112(%rsp), %r9 + movq %r15, %rdx + xorq %rax, %rcx + xorq %r8, %rdx + rorxq $41, %r14, %rax + xorq %rcx, %rax + andq %r14, %rdx + addq %rax, %r9 + rorxq $28, %r10, %rax + rorxq $34, %r10, %rcx + xorq %r8, %rdx + xorq %rax, %rcx + rorxq $39, %r10, %rax + addq %rdx, %r9 + xorq %rcx, %rax + movq %r11, %rdx + addq %r9, %r13 + xorq %r10, %rdx + andq %rdx, %rbx + addq %rax, %r9 + xorq %r11, %rbx + # rnd_1: 0 - 7 + rorxq $14, %r13, %rax + rorxq $18, %r13, %rcx + addq %rbx, %r9 + addq 120(%rsp), %r8 + movq %r14, %rbx + xorq %rax, %rcx + xorq %r15, %rbx + rorxq $41, %r13, %rax + xorq %rcx, %rax + andq %r13, %rbx + addq %rax, %r8 + rorxq $28, %r9, %rax + rorxq $34, %r9, %rcx + xorq %r15, %rbx + xorq %rax, %rcx + rorxq $39, %r9, %rax + addq %rbx, %r8 + xorq %rcx, %rax + movq %r10, %rbx + addq %r8, %r12 + xorq %r9, %rbx + andq %rbx, %rdx + addq %rax, %r8 + xorq %r10, %rdx + addq %rdx, %r8 + addq %r8, (%rdi) + addq %r9, 8(%rdi) + addq %r10, 16(%rdi) + addq %r11, 24(%rdi) + addq %r12, 32(%rdi) + addq %r13, 40(%rdi) + addq %r14, 48(%rdi) + addq %r15, 56(%rdi) + xorq %rax, %rax + vzeroupper + addq $0x88, %rsp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size Transform_Sha512_AVX1_RORX,.-Transform_Sha512_AVX1_RORX +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl Transform_Sha512_AVX1_RORX_Len +.type Transform_Sha512_AVX1_RORX_Len,@function +.align 4 +Transform_Sha512_AVX1_RORX_Len: +#else +.section __TEXT,__text +.globl _Transform_Sha512_AVX1_RORX_Len +.p2align 2 +_Transform_Sha512_AVX1_RORX_Len: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + pushq %rbp + movq %rsi, %rbp + subq $0x90, %rsp + movq 224(%rdi), %rsi + leaq L_avx1_rorx_sha512_k(%rip), %rcx + vmovdqa L_avx1_rorx_sha512_flip_mask(%rip), %xmm14 + movq (%rdi), %r8 + movq 8(%rdi), %r9 + movq 16(%rdi), %r10 + movq 24(%rdi), %r11 + movq 32(%rdi), %r12 + movq 40(%rdi), %r13 + movq 48(%rdi), %r14 + movq 56(%rdi), %r15 + # Start of loop processing a block +L_sha512_len_avx1_rorx_begin: + vmovdqu (%rsi), %xmm0 + vmovdqu 16(%rsi), %xmm1 + vpshufb %xmm14, %xmm0, %xmm0 + vpshufb %xmm14, %xmm1, %xmm1 + vmovdqu 32(%rsi), %xmm2 + vmovdqu 48(%rsi), %xmm3 + vpshufb %xmm14, %xmm2, %xmm2 + vpshufb %xmm14, %xmm3, %xmm3 + vmovdqu 64(%rsi), %xmm4 + vmovdqu 80(%rsi), %xmm5 + vpshufb %xmm14, %xmm4, %xmm4 + vpshufb %xmm14, %xmm5, %xmm5 + vmovdqu 96(%rsi), %xmm6 + vmovdqu 112(%rsi), %xmm7 + vpshufb %xmm14, %xmm6, %xmm6 + vpshufb %xmm14, %xmm7, %xmm7 + movl $4, 128(%rsp) + movq %r9, %rbx + xorq %rdx, %rdx + xorq %r10, %rbx + vpaddq (%rcx), %xmm0, %xmm8 + vpaddq 16(%rcx), %xmm1, %xmm9 + vmovdqu %xmm8, (%rsp) + vmovdqu %xmm9, 16(%rsp) + vpaddq 32(%rcx), %xmm2, %xmm8 + vpaddq 48(%rcx), %xmm3, %xmm9 + vmovdqu %xmm8, 32(%rsp) + vmovdqu %xmm9, 48(%rsp) + vpaddq 64(%rcx), %xmm4, %xmm8 + vpaddq 80(%rcx), %xmm5, %xmm9 + vmovdqu %xmm8, 64(%rsp) + vmovdqu %xmm9, 80(%rsp) + vpaddq 96(%rcx), %xmm6, %xmm8 + vpaddq 112(%rcx), %xmm7, %xmm9 + vmovdqu %xmm8, 96(%rsp) + vmovdqu %xmm9, 112(%rsp) + # Start of 16 rounds +L_sha512_len_avx1_rorx_start: + addq $0x80, %rcx + movq %rcx, 136(%rsp) + # msg_sched: 0-1 + # rnd_0: 0 - 0 + rorxq $14, %r12, %rax + rorxq $18, %r12, %rcx + addq %rdx, %r8 + vpalignr $8, %xmm0, %xmm1, %xmm12 + vpalignr $8, %xmm4, %xmm5, %xmm13 + # rnd_0: 1 - 1 + addq (%rsp), %r15 + movq %r13, %rdx + xorq %rax, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 2 + xorq %r14, %rdx + rorxq $41, %r12, %rax + xorq %rcx, %rax + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 3 - 3 + andq %r12, %rdx + addq %rax, %r15 + rorxq $28, %r8, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 4 - 4 + rorxq $34, %r8, %rcx + xorq %r14, %rdx + xorq %rax, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 5 - 5 + rorxq $39, %r8, %rax + addq %rdx, %r15 + xorq %rcx, %rax + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm0, %xmm13, %xmm0 + # rnd_0: 6 - 7 + movq %r9, %rdx + addq %r15, %r11 + xorq %r8, %rdx + andq %rdx, %rbx + addq %rax, %r15 + xorq %r9, %rbx + vpaddq %xmm0, %xmm8, %xmm0 + # rnd_1: 0 - 0 + rorxq $14, %r11, %rax + rorxq $18, %r11, %rcx + addq %rbx, %r15 + vpsrlq $19, %xmm7, %xmm8 + vpsllq $45, %xmm7, %xmm9 + # rnd_1: 1 - 1 + addq 8(%rsp), %r14 + movq %r12, %rbx + xorq %rax, %rcx + vpsrlq $61, %xmm7, %xmm10 + vpsllq $3, %xmm7, %xmm11 + # rnd_1: 2 - 2 + xorq %r13, %rbx + rorxq $41, %r11, %rax + xorq %rcx, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 3 - 4 + andq %r11, %rbx + addq %rax, %r14 + rorxq $28, %r15, %rax + rorxq $34, %r15, %rcx + xorq %r13, %rbx + xorq %rax, %rcx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm7, %xmm11 + # rnd_1: 5 - 6 + rorxq $39, %r15, %rax + addq %rbx, %r14 + xorq %rcx, %rax + movq %r8, %rbx + addq %r14, %r10 + xorq %r15, %rbx + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 7 - 7 + andq %rbx, %rdx + addq %rax, %r14 + xorq %r8, %rdx + vpaddq %xmm0, %xmm8, %xmm0 + # msg_sched done: 0-3 + # msg_sched: 2-3 + # rnd_0: 0 - 0 + rorxq $14, %r10, %rax + rorxq $18, %r10, %rcx + addq %rdx, %r14 + vpalignr $8, %xmm1, %xmm2, %xmm12 + vpalignr $8, %xmm5, %xmm6, %xmm13 + # rnd_0: 1 - 1 + addq 16(%rsp), %r13 + movq %r11, %rdx + xorq %rax, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 2 + xorq %r12, %rdx + rorxq $41, %r10, %rax + xorq %rcx, %rax + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 3 - 3 + andq %r10, %rdx + addq %rax, %r13 + rorxq $28, %r14, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 4 - 4 + rorxq $34, %r14, %rcx + xorq %r12, %rdx + xorq %rax, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 5 - 5 + rorxq $39, %r14, %rax + addq %rdx, %r13 + xorq %rcx, %rax + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm1, %xmm13, %xmm1 + # rnd_0: 6 - 7 + movq %r15, %rdx + addq %r13, %r9 + xorq %r14, %rdx + andq %rdx, %rbx + addq %rax, %r13 + xorq %r15, %rbx + vpaddq %xmm1, %xmm8, %xmm1 + # rnd_1: 0 - 0 + rorxq $14, %r9, %rax + rorxq $18, %r9, %rcx + addq %rbx, %r13 + vpsrlq $19, %xmm0, %xmm8 + vpsllq $45, %xmm0, %xmm9 + # rnd_1: 1 - 1 + addq 24(%rsp), %r12 + movq %r10, %rbx + xorq %rax, %rcx + vpsrlq $61, %xmm0, %xmm10 + vpsllq $3, %xmm0, %xmm11 + # rnd_1: 2 - 2 + xorq %r11, %rbx + rorxq $41, %r9, %rax + xorq %rcx, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 3 - 4 + andq %r9, %rbx + addq %rax, %r12 + rorxq $28, %r13, %rax + rorxq $34, %r13, %rcx + xorq %r11, %rbx + xorq %rax, %rcx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm0, %xmm11 + # rnd_1: 5 - 6 + rorxq $39, %r13, %rax + addq %rbx, %r12 + xorq %rcx, %rax + movq %r14, %rbx + addq %r12, %r8 + xorq %r13, %rbx + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 7 - 7 + andq %rbx, %rdx + addq %rax, %r12 + xorq %r14, %rdx + vpaddq %xmm1, %xmm8, %xmm1 + # msg_sched done: 2-5 + # msg_sched: 4-5 + # rnd_0: 0 - 0 + rorxq $14, %r8, %rax + rorxq $18, %r8, %rcx + addq %rdx, %r12 + vpalignr $8, %xmm2, %xmm3, %xmm12 + vpalignr $8, %xmm6, %xmm7, %xmm13 + # rnd_0: 1 - 1 + addq 32(%rsp), %r11 + movq %r9, %rdx + xorq %rax, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 2 + xorq %r10, %rdx + rorxq $41, %r8, %rax + xorq %rcx, %rax + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 3 - 3 + andq %r8, %rdx + addq %rax, %r11 + rorxq $28, %r12, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 4 - 4 + rorxq $34, %r12, %rcx + xorq %r10, %rdx + xorq %rax, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 5 - 5 + rorxq $39, %r12, %rax + addq %rdx, %r11 + xorq %rcx, %rax + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm2, %xmm13, %xmm2 + # rnd_0: 6 - 7 + movq %r13, %rdx + addq %r11, %r15 + xorq %r12, %rdx + andq %rdx, %rbx + addq %rax, %r11 + xorq %r13, %rbx + vpaddq %xmm2, %xmm8, %xmm2 + # rnd_1: 0 - 0 + rorxq $14, %r15, %rax + rorxq $18, %r15, %rcx + addq %rbx, %r11 + vpsrlq $19, %xmm1, %xmm8 + vpsllq $45, %xmm1, %xmm9 + # rnd_1: 1 - 1 + addq 40(%rsp), %r10 + movq %r8, %rbx + xorq %rax, %rcx + vpsrlq $61, %xmm1, %xmm10 + vpsllq $3, %xmm1, %xmm11 + # rnd_1: 2 - 2 + xorq %r9, %rbx + rorxq $41, %r15, %rax + xorq %rcx, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 3 - 4 + andq %r15, %rbx + addq %rax, %r10 + rorxq $28, %r11, %rax + rorxq $34, %r11, %rcx + xorq %r9, %rbx + xorq %rax, %rcx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm1, %xmm11 + # rnd_1: 5 - 6 + rorxq $39, %r11, %rax + addq %rbx, %r10 + xorq %rcx, %rax + movq %r12, %rbx + addq %r10, %r14 + xorq %r11, %rbx + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 7 - 7 + andq %rbx, %rdx + addq %rax, %r10 + xorq %r12, %rdx + vpaddq %xmm2, %xmm8, %xmm2 + # msg_sched done: 4-7 + # msg_sched: 6-7 + # rnd_0: 0 - 0 + rorxq $14, %r14, %rax + rorxq $18, %r14, %rcx + addq %rdx, %r10 + vpalignr $8, %xmm3, %xmm4, %xmm12 + vpalignr $8, %xmm7, %xmm0, %xmm13 + # rnd_0: 1 - 1 + addq 48(%rsp), %r9 + movq %r15, %rdx + xorq %rax, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 2 + xorq %r8, %rdx + rorxq $41, %r14, %rax + xorq %rcx, %rax + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 3 - 3 + andq %r14, %rdx + addq %rax, %r9 + rorxq $28, %r10, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 4 - 4 + rorxq $34, %r10, %rcx + xorq %r8, %rdx + xorq %rax, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 5 - 5 + rorxq $39, %r10, %rax + addq %rdx, %r9 + xorq %rcx, %rax + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm3, %xmm13, %xmm3 + # rnd_0: 6 - 7 + movq %r11, %rdx + addq %r9, %r13 + xorq %r10, %rdx + andq %rdx, %rbx + addq %rax, %r9 + xorq %r11, %rbx + vpaddq %xmm3, %xmm8, %xmm3 + # rnd_1: 0 - 0 + rorxq $14, %r13, %rax + rorxq $18, %r13, %rcx + addq %rbx, %r9 + vpsrlq $19, %xmm2, %xmm8 + vpsllq $45, %xmm2, %xmm9 + # rnd_1: 1 - 1 + addq 56(%rsp), %r8 + movq %r14, %rbx + xorq %rax, %rcx + vpsrlq $61, %xmm2, %xmm10 + vpsllq $3, %xmm2, %xmm11 + # rnd_1: 2 - 2 + xorq %r15, %rbx + rorxq $41, %r13, %rax + xorq %rcx, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 3 - 4 + andq %r13, %rbx + addq %rax, %r8 + rorxq $28, %r9, %rax + rorxq $34, %r9, %rcx + xorq %r15, %rbx + xorq %rax, %rcx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm2, %xmm11 + # rnd_1: 5 - 6 + rorxq $39, %r9, %rax + addq %rbx, %r8 + xorq %rcx, %rax + movq %r10, %rbx + addq %r8, %r12 + xorq %r9, %rbx + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 7 - 7 + andq %rbx, %rdx + addq %rax, %r8 + xorq %r10, %rdx + vpaddq %xmm3, %xmm8, %xmm3 + # msg_sched done: 6-9 + # msg_sched: 8-9 + # rnd_0: 0 - 0 + rorxq $14, %r12, %rax + rorxq $18, %r12, %rcx + addq %rdx, %r8 + vpalignr $8, %xmm4, %xmm5, %xmm12 + vpalignr $8, %xmm0, %xmm1, %xmm13 + # rnd_0: 1 - 1 + addq 64(%rsp), %r15 + movq %r13, %rdx + xorq %rax, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 2 + xorq %r14, %rdx + rorxq $41, %r12, %rax + xorq %rcx, %rax + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 3 - 3 + andq %r12, %rdx + addq %rax, %r15 + rorxq $28, %r8, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 4 - 4 + rorxq $34, %r8, %rcx + xorq %r14, %rdx + xorq %rax, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 5 - 5 + rorxq $39, %r8, %rax + addq %rdx, %r15 + xorq %rcx, %rax + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm4, %xmm13, %xmm4 + # rnd_0: 6 - 7 + movq %r9, %rdx + addq %r15, %r11 + xorq %r8, %rdx + andq %rdx, %rbx + addq %rax, %r15 + xorq %r9, %rbx + vpaddq %xmm4, %xmm8, %xmm4 + # rnd_1: 0 - 0 + rorxq $14, %r11, %rax + rorxq $18, %r11, %rcx + addq %rbx, %r15 + vpsrlq $19, %xmm3, %xmm8 + vpsllq $45, %xmm3, %xmm9 + # rnd_1: 1 - 1 + addq 72(%rsp), %r14 + movq %r12, %rbx + xorq %rax, %rcx + vpsrlq $61, %xmm3, %xmm10 + vpsllq $3, %xmm3, %xmm11 + # rnd_1: 2 - 2 + xorq %r13, %rbx + rorxq $41, %r11, %rax + xorq %rcx, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 3 - 4 + andq %r11, %rbx + addq %rax, %r14 + rorxq $28, %r15, %rax + rorxq $34, %r15, %rcx + xorq %r13, %rbx + xorq %rax, %rcx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm3, %xmm11 + # rnd_1: 5 - 6 + rorxq $39, %r15, %rax + addq %rbx, %r14 + xorq %rcx, %rax + movq %r8, %rbx + addq %r14, %r10 + xorq %r15, %rbx + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 7 - 7 + andq %rbx, %rdx + addq %rax, %r14 + xorq %r8, %rdx + vpaddq %xmm4, %xmm8, %xmm4 + # msg_sched done: 8-11 + # msg_sched: 10-11 + # rnd_0: 0 - 0 + rorxq $14, %r10, %rax + rorxq $18, %r10, %rcx + addq %rdx, %r14 + vpalignr $8, %xmm5, %xmm6, %xmm12 + vpalignr $8, %xmm1, %xmm2, %xmm13 + # rnd_0: 1 - 1 + addq 80(%rsp), %r13 + movq %r11, %rdx + xorq %rax, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 2 + xorq %r12, %rdx + rorxq $41, %r10, %rax + xorq %rcx, %rax + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 3 - 3 + andq %r10, %rdx + addq %rax, %r13 + rorxq $28, %r14, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 4 - 4 + rorxq $34, %r14, %rcx + xorq %r12, %rdx + xorq %rax, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 5 - 5 + rorxq $39, %r14, %rax + addq %rdx, %r13 + xorq %rcx, %rax + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm5, %xmm13, %xmm5 + # rnd_0: 6 - 7 + movq %r15, %rdx + addq %r13, %r9 + xorq %r14, %rdx + andq %rdx, %rbx + addq %rax, %r13 + xorq %r15, %rbx + vpaddq %xmm5, %xmm8, %xmm5 + # rnd_1: 0 - 0 + rorxq $14, %r9, %rax + rorxq $18, %r9, %rcx + addq %rbx, %r13 + vpsrlq $19, %xmm4, %xmm8 + vpsllq $45, %xmm4, %xmm9 + # rnd_1: 1 - 1 + addq 88(%rsp), %r12 + movq %r10, %rbx + xorq %rax, %rcx + vpsrlq $61, %xmm4, %xmm10 + vpsllq $3, %xmm4, %xmm11 + # rnd_1: 2 - 2 + xorq %r11, %rbx + rorxq $41, %r9, %rax + xorq %rcx, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 3 - 4 + andq %r9, %rbx + addq %rax, %r12 + rorxq $28, %r13, %rax + rorxq $34, %r13, %rcx + xorq %r11, %rbx + xorq %rax, %rcx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm4, %xmm11 + # rnd_1: 5 - 6 + rorxq $39, %r13, %rax + addq %rbx, %r12 + xorq %rcx, %rax + movq %r14, %rbx + addq %r12, %r8 + xorq %r13, %rbx + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 7 - 7 + andq %rbx, %rdx + addq %rax, %r12 + xorq %r14, %rdx + vpaddq %xmm5, %xmm8, %xmm5 + # msg_sched done: 10-13 + # msg_sched: 12-13 + # rnd_0: 0 - 0 + rorxq $14, %r8, %rax + rorxq $18, %r8, %rcx + addq %rdx, %r12 + vpalignr $8, %xmm6, %xmm7, %xmm12 + vpalignr $8, %xmm2, %xmm3, %xmm13 + # rnd_0: 1 - 1 + addq 96(%rsp), %r11 + movq %r9, %rdx + xorq %rax, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 2 + xorq %r10, %rdx + rorxq $41, %r8, %rax + xorq %rcx, %rax + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 3 - 3 + andq %r8, %rdx + addq %rax, %r11 + rorxq $28, %r12, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 4 - 4 + rorxq $34, %r12, %rcx + xorq %r10, %rdx + xorq %rax, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 5 - 5 + rorxq $39, %r12, %rax + addq %rdx, %r11 + xorq %rcx, %rax + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm6, %xmm13, %xmm6 + # rnd_0: 6 - 7 + movq %r13, %rdx + addq %r11, %r15 + xorq %r12, %rdx + andq %rdx, %rbx + addq %rax, %r11 + xorq %r13, %rbx + vpaddq %xmm6, %xmm8, %xmm6 + # rnd_1: 0 - 0 + rorxq $14, %r15, %rax + rorxq $18, %r15, %rcx + addq %rbx, %r11 + vpsrlq $19, %xmm5, %xmm8 + vpsllq $45, %xmm5, %xmm9 + # rnd_1: 1 - 1 + addq 104(%rsp), %r10 + movq %r8, %rbx + xorq %rax, %rcx + vpsrlq $61, %xmm5, %xmm10 + vpsllq $3, %xmm5, %xmm11 + # rnd_1: 2 - 2 + xorq %r9, %rbx + rorxq $41, %r15, %rax + xorq %rcx, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 3 - 4 + andq %r15, %rbx + addq %rax, %r10 + rorxq $28, %r11, %rax + rorxq $34, %r11, %rcx + xorq %r9, %rbx + xorq %rax, %rcx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm5, %xmm11 + # rnd_1: 5 - 6 + rorxq $39, %r11, %rax + addq %rbx, %r10 + xorq %rcx, %rax + movq %r12, %rbx + addq %r10, %r14 + xorq %r11, %rbx + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 7 - 7 + andq %rbx, %rdx + addq %rax, %r10 + xorq %r12, %rdx + vpaddq %xmm6, %xmm8, %xmm6 + # msg_sched done: 12-15 + # msg_sched: 14-15 + # rnd_0: 0 - 0 + rorxq $14, %r14, %rax + rorxq $18, %r14, %rcx + addq %rdx, %r10 + vpalignr $8, %xmm7, %xmm0, %xmm12 + vpalignr $8, %xmm3, %xmm4, %xmm13 + # rnd_0: 1 - 1 + addq 112(%rsp), %r9 + movq %r15, %rdx + xorq %rax, %rcx + vpsrlq $0x01, %xmm12, %xmm8 + vpsllq $63, %xmm12, %xmm9 + # rnd_0: 2 - 2 + xorq %r8, %rdx + rorxq $41, %r14, %rax + xorq %rcx, %rax + vpsrlq $8, %xmm12, %xmm10 + vpsllq $56, %xmm12, %xmm11 + # rnd_0: 3 - 3 + andq %r14, %rdx + addq %rax, %r9 + rorxq $28, %r10, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_0: 4 - 4 + rorxq $34, %r10, %rcx + xorq %r8, %rdx + xorq %rax, %rcx + vpsrlq $7, %xmm12, %xmm11 + vpxor %xmm10, %xmm8, %xmm8 + # rnd_0: 5 - 5 + rorxq $39, %r10, %rax + addq %rdx, %r9 + xorq %rcx, %rax + vpxor %xmm11, %xmm8, %xmm8 + vpaddq %xmm7, %xmm13, %xmm7 + # rnd_0: 6 - 7 + movq %r11, %rdx + addq %r9, %r13 + xorq %r10, %rdx + andq %rdx, %rbx + addq %rax, %r9 + xorq %r11, %rbx + vpaddq %xmm7, %xmm8, %xmm7 + # rnd_1: 0 - 0 + rorxq $14, %r13, %rax + rorxq $18, %r13, %rcx + addq %rbx, %r9 + vpsrlq $19, %xmm6, %xmm8 + vpsllq $45, %xmm6, %xmm9 + # rnd_1: 1 - 1 + addq 120(%rsp), %r8 + movq %r14, %rbx + xorq %rax, %rcx + vpsrlq $61, %xmm6, %xmm10 + vpsllq $3, %xmm6, %xmm11 + # rnd_1: 2 - 2 + xorq %r15, %rbx + rorxq $41, %r13, %rax + xorq %rcx, %rax + vpor %xmm9, %xmm8, %xmm8 + vpor %xmm11, %xmm10, %xmm10 + # rnd_1: 3 - 4 + andq %r13, %rbx + addq %rax, %r8 + rorxq $28, %r9, %rax + rorxq $34, %r9, %rcx + xorq %r15, %rbx + xorq %rax, %rcx + vpxor %xmm10, %xmm8, %xmm8 + vpsrlq $6, %xmm6, %xmm11 + # rnd_1: 5 - 6 + rorxq $39, %r9, %rax + addq %rbx, %r8 + xorq %rcx, %rax + movq %r10, %rbx + addq %r8, %r12 + xorq %r9, %rbx + vpxor %xmm11, %xmm8, %xmm8 + # rnd_1: 7 - 7 + andq %rbx, %rdx + addq %rax, %r8 + xorq %r10, %rdx + vpaddq %xmm7, %xmm8, %xmm7 + # msg_sched done: 14-17 + movq 136(%rsp), %rcx + vpaddq (%rcx), %xmm0, %xmm8 + vpaddq 16(%rcx), %xmm1, %xmm9 + vmovdqu %xmm8, (%rsp) + vmovdqu %xmm9, 16(%rsp) + vpaddq 32(%rcx), %xmm2, %xmm8 + vpaddq 48(%rcx), %xmm3, %xmm9 + vmovdqu %xmm8, 32(%rsp) + vmovdqu %xmm9, 48(%rsp) + vpaddq 64(%rcx), %xmm4, %xmm8 + vpaddq 80(%rcx), %xmm5, %xmm9 + vmovdqu %xmm8, 64(%rsp) + vmovdqu %xmm9, 80(%rsp) + vpaddq 96(%rcx), %xmm6, %xmm8 + vpaddq 112(%rcx), %xmm7, %xmm9 + vmovdqu %xmm8, 96(%rsp) + vmovdqu %xmm9, 112(%rsp) + subl $0x01, 128(%rsp) + jne L_sha512_len_avx1_rorx_start + vpaddq (%rcx), %xmm0, %xmm8 + vpaddq 16(%rcx), %xmm1, %xmm9 + vmovdqu %xmm8, (%rsp) + vmovdqu %xmm9, 16(%rsp) + vpaddq 32(%rcx), %xmm2, %xmm8 + vpaddq 48(%rcx), %xmm3, %xmm9 + vmovdqu %xmm8, 32(%rsp) + vmovdqu %xmm9, 48(%rsp) + vpaddq 64(%rcx), %xmm4, %xmm8 + vpaddq 80(%rcx), %xmm5, %xmm9 + vmovdqu %xmm8, 64(%rsp) + vmovdqu %xmm9, 80(%rsp) + vpaddq 96(%rcx), %xmm6, %xmm8 + vpaddq 112(%rcx), %xmm7, %xmm9 + vmovdqu %xmm8, 96(%rsp) + vmovdqu %xmm9, 112(%rsp) + # rnd_all_2: 0-1 + # rnd_0: 0 - 7 + rorxq $14, %r12, %rax + rorxq $18, %r12, %rcx + addq %rdx, %r8 + addq (%rsp), %r15 + movq %r13, %rdx + xorq %rax, %rcx + xorq %r14, %rdx + rorxq $41, %r12, %rax + xorq %rcx, %rax + andq %r12, %rdx + addq %rax, %r15 + rorxq $28, %r8, %rax + rorxq $34, %r8, %rcx + xorq %r14, %rdx + xorq %rax, %rcx + rorxq $39, %r8, %rax + addq %rdx, %r15 + xorq %rcx, %rax + movq %r9, %rdx + addq %r15, %r11 + xorq %r8, %rdx + andq %rdx, %rbx + addq %rax, %r15 + xorq %r9, %rbx + # rnd_1: 0 - 7 + rorxq $14, %r11, %rax + rorxq $18, %r11, %rcx + addq %rbx, %r15 + addq 8(%rsp), %r14 + movq %r12, %rbx + xorq %rax, %rcx + xorq %r13, %rbx + rorxq $41, %r11, %rax + xorq %rcx, %rax + andq %r11, %rbx + addq %rax, %r14 + rorxq $28, %r15, %rax + rorxq $34, %r15, %rcx + xorq %r13, %rbx + xorq %rax, %rcx + rorxq $39, %r15, %rax + addq %rbx, %r14 + xorq %rcx, %rax + movq %r8, %rbx + addq %r14, %r10 + xorq %r15, %rbx + andq %rbx, %rdx + addq %rax, %r14 + xorq %r8, %rdx + # rnd_all_2: 2-3 + # rnd_0: 0 - 7 + rorxq $14, %r10, %rax + rorxq $18, %r10, %rcx + addq %rdx, %r14 + addq 16(%rsp), %r13 + movq %r11, %rdx + xorq %rax, %rcx + xorq %r12, %rdx + rorxq $41, %r10, %rax + xorq %rcx, %rax + andq %r10, %rdx + addq %rax, %r13 + rorxq $28, %r14, %rax + rorxq $34, %r14, %rcx + xorq %r12, %rdx + xorq %rax, %rcx + rorxq $39, %r14, %rax + addq %rdx, %r13 + xorq %rcx, %rax + movq %r15, %rdx + addq %r13, %r9 + xorq %r14, %rdx + andq %rdx, %rbx + addq %rax, %r13 + xorq %r15, %rbx + # rnd_1: 0 - 7 + rorxq $14, %r9, %rax + rorxq $18, %r9, %rcx + addq %rbx, %r13 + addq 24(%rsp), %r12 + movq %r10, %rbx + xorq %rax, %rcx + xorq %r11, %rbx + rorxq $41, %r9, %rax + xorq %rcx, %rax + andq %r9, %rbx + addq %rax, %r12 + rorxq $28, %r13, %rax + rorxq $34, %r13, %rcx + xorq %r11, %rbx + xorq %rax, %rcx + rorxq $39, %r13, %rax + addq %rbx, %r12 + xorq %rcx, %rax + movq %r14, %rbx + addq %r12, %r8 + xorq %r13, %rbx + andq %rbx, %rdx + addq %rax, %r12 + xorq %r14, %rdx + # rnd_all_2: 4-5 + # rnd_0: 0 - 7 + rorxq $14, %r8, %rax + rorxq $18, %r8, %rcx + addq %rdx, %r12 + addq 32(%rsp), %r11 + movq %r9, %rdx + xorq %rax, %rcx + xorq %r10, %rdx + rorxq $41, %r8, %rax + xorq %rcx, %rax + andq %r8, %rdx + addq %rax, %r11 + rorxq $28, %r12, %rax + rorxq $34, %r12, %rcx + xorq %r10, %rdx + xorq %rax, %rcx + rorxq $39, %r12, %rax + addq %rdx, %r11 + xorq %rcx, %rax + movq %r13, %rdx + addq %r11, %r15 + xorq %r12, %rdx + andq %rdx, %rbx + addq %rax, %r11 + xorq %r13, %rbx + # rnd_1: 0 - 7 + rorxq $14, %r15, %rax + rorxq $18, %r15, %rcx + addq %rbx, %r11 + addq 40(%rsp), %r10 + movq %r8, %rbx + xorq %rax, %rcx + xorq %r9, %rbx + rorxq $41, %r15, %rax + xorq %rcx, %rax + andq %r15, %rbx + addq %rax, %r10 + rorxq $28, %r11, %rax + rorxq $34, %r11, %rcx + xorq %r9, %rbx + xorq %rax, %rcx + rorxq $39, %r11, %rax + addq %rbx, %r10 + xorq %rcx, %rax + movq %r12, %rbx + addq %r10, %r14 + xorq %r11, %rbx + andq %rbx, %rdx + addq %rax, %r10 + xorq %r12, %rdx + # rnd_all_2: 6-7 + # rnd_0: 0 - 7 + rorxq $14, %r14, %rax + rorxq $18, %r14, %rcx + addq %rdx, %r10 + addq 48(%rsp), %r9 + movq %r15, %rdx + xorq %rax, %rcx + xorq %r8, %rdx + rorxq $41, %r14, %rax + xorq %rcx, %rax + andq %r14, %rdx + addq %rax, %r9 + rorxq $28, %r10, %rax + rorxq $34, %r10, %rcx + xorq %r8, %rdx + xorq %rax, %rcx + rorxq $39, %r10, %rax + addq %rdx, %r9 + xorq %rcx, %rax + movq %r11, %rdx + addq %r9, %r13 + xorq %r10, %rdx + andq %rdx, %rbx + addq %rax, %r9 + xorq %r11, %rbx + # rnd_1: 0 - 7 + rorxq $14, %r13, %rax + rorxq $18, %r13, %rcx + addq %rbx, %r9 + addq 56(%rsp), %r8 + movq %r14, %rbx + xorq %rax, %rcx + xorq %r15, %rbx + rorxq $41, %r13, %rax + xorq %rcx, %rax + andq %r13, %rbx + addq %rax, %r8 + rorxq $28, %r9, %rax + rorxq $34, %r9, %rcx + xorq %r15, %rbx + xorq %rax, %rcx + rorxq $39, %r9, %rax + addq %rbx, %r8 + xorq %rcx, %rax + movq %r10, %rbx + addq %r8, %r12 + xorq %r9, %rbx + andq %rbx, %rdx + addq %rax, %r8 + xorq %r10, %rdx + # rnd_all_2: 8-9 + # rnd_0: 0 - 7 + rorxq $14, %r12, %rax + rorxq $18, %r12, %rcx + addq %rdx, %r8 + addq 64(%rsp), %r15 + movq %r13, %rdx + xorq %rax, %rcx + xorq %r14, %rdx + rorxq $41, %r12, %rax + xorq %rcx, %rax + andq %r12, %rdx + addq %rax, %r15 + rorxq $28, %r8, %rax + rorxq $34, %r8, %rcx + xorq %r14, %rdx + xorq %rax, %rcx + rorxq $39, %r8, %rax + addq %rdx, %r15 + xorq %rcx, %rax + movq %r9, %rdx + addq %r15, %r11 + xorq %r8, %rdx + andq %rdx, %rbx + addq %rax, %r15 + xorq %r9, %rbx + # rnd_1: 0 - 7 + rorxq $14, %r11, %rax + rorxq $18, %r11, %rcx + addq %rbx, %r15 + addq 72(%rsp), %r14 + movq %r12, %rbx + xorq %rax, %rcx + xorq %r13, %rbx + rorxq $41, %r11, %rax + xorq %rcx, %rax + andq %r11, %rbx + addq %rax, %r14 + rorxq $28, %r15, %rax + rorxq $34, %r15, %rcx + xorq %r13, %rbx + xorq %rax, %rcx + rorxq $39, %r15, %rax + addq %rbx, %r14 + xorq %rcx, %rax + movq %r8, %rbx + addq %r14, %r10 + xorq %r15, %rbx + andq %rbx, %rdx + addq %rax, %r14 + xorq %r8, %rdx + # rnd_all_2: 10-11 + # rnd_0: 0 - 7 + rorxq $14, %r10, %rax + rorxq $18, %r10, %rcx + addq %rdx, %r14 + addq 80(%rsp), %r13 + movq %r11, %rdx + xorq %rax, %rcx + xorq %r12, %rdx + rorxq $41, %r10, %rax + xorq %rcx, %rax + andq %r10, %rdx + addq %rax, %r13 + rorxq $28, %r14, %rax + rorxq $34, %r14, %rcx + xorq %r12, %rdx + xorq %rax, %rcx + rorxq $39, %r14, %rax + addq %rdx, %r13 + xorq %rcx, %rax + movq %r15, %rdx + addq %r13, %r9 + xorq %r14, %rdx + andq %rdx, %rbx + addq %rax, %r13 + xorq %r15, %rbx + # rnd_1: 0 - 7 + rorxq $14, %r9, %rax + rorxq $18, %r9, %rcx + addq %rbx, %r13 + addq 88(%rsp), %r12 + movq %r10, %rbx + xorq %rax, %rcx + xorq %r11, %rbx + rorxq $41, %r9, %rax + xorq %rcx, %rax + andq %r9, %rbx + addq %rax, %r12 + rorxq $28, %r13, %rax + rorxq $34, %r13, %rcx + xorq %r11, %rbx + xorq %rax, %rcx + rorxq $39, %r13, %rax + addq %rbx, %r12 + xorq %rcx, %rax + movq %r14, %rbx + addq %r12, %r8 + xorq %r13, %rbx + andq %rbx, %rdx + addq %rax, %r12 + xorq %r14, %rdx + # rnd_all_2: 12-13 + # rnd_0: 0 - 7 + rorxq $14, %r8, %rax + rorxq $18, %r8, %rcx + addq %rdx, %r12 + addq 96(%rsp), %r11 + movq %r9, %rdx + xorq %rax, %rcx + xorq %r10, %rdx + rorxq $41, %r8, %rax + xorq %rcx, %rax + andq %r8, %rdx + addq %rax, %r11 + rorxq $28, %r12, %rax + rorxq $34, %r12, %rcx + xorq %r10, %rdx + xorq %rax, %rcx + rorxq $39, %r12, %rax + addq %rdx, %r11 + xorq %rcx, %rax + movq %r13, %rdx + addq %r11, %r15 + xorq %r12, %rdx + andq %rdx, %rbx + addq %rax, %r11 + xorq %r13, %rbx + # rnd_1: 0 - 7 + rorxq $14, %r15, %rax + rorxq $18, %r15, %rcx + addq %rbx, %r11 + addq 104(%rsp), %r10 + movq %r8, %rbx + xorq %rax, %rcx + xorq %r9, %rbx + rorxq $41, %r15, %rax + xorq %rcx, %rax + andq %r15, %rbx + addq %rax, %r10 + rorxq $28, %r11, %rax + rorxq $34, %r11, %rcx + xorq %r9, %rbx + xorq %rax, %rcx + rorxq $39, %r11, %rax + addq %rbx, %r10 + xorq %rcx, %rax + movq %r12, %rbx + addq %r10, %r14 + xorq %r11, %rbx + andq %rbx, %rdx + addq %rax, %r10 + xorq %r12, %rdx + # rnd_all_2: 14-15 + # rnd_0: 0 - 7 + rorxq $14, %r14, %rax + rorxq $18, %r14, %rcx + addq %rdx, %r10 + addq 112(%rsp), %r9 + movq %r15, %rdx + xorq %rax, %rcx + xorq %r8, %rdx + rorxq $41, %r14, %rax + xorq %rcx, %rax + andq %r14, %rdx + addq %rax, %r9 + rorxq $28, %r10, %rax + rorxq $34, %r10, %rcx + xorq %r8, %rdx + xorq %rax, %rcx + rorxq $39, %r10, %rax + addq %rdx, %r9 + xorq %rcx, %rax + movq %r11, %rdx + addq %r9, %r13 + xorq %r10, %rdx + andq %rdx, %rbx + addq %rax, %r9 + xorq %r11, %rbx + # rnd_1: 0 - 7 + rorxq $14, %r13, %rax + rorxq $18, %r13, %rcx + addq %rbx, %r9 + addq 120(%rsp), %r8 + movq %r14, %rbx + xorq %rax, %rcx + xorq %r15, %rbx + rorxq $41, %r13, %rax + xorq %rcx, %rax + andq %r13, %rbx + addq %rax, %r8 + rorxq $28, %r9, %rax + rorxq $34, %r9, %rcx + xorq %r15, %rbx + xorq %rax, %rcx + rorxq $39, %r9, %rax + addq %rbx, %r8 + xorq %rcx, %rax + movq %r10, %rbx + addq %r8, %r12 + xorq %r9, %rbx + andq %rbx, %rdx + addq %rax, %r8 + xorq %r10, %rdx + addq %rdx, %r8 + addq (%rdi), %r8 + addq 8(%rdi), %r9 + addq 16(%rdi), %r10 + addq 24(%rdi), %r11 + addq 32(%rdi), %r12 + addq 40(%rdi), %r13 + addq 48(%rdi), %r14 + addq 56(%rdi), %r15 + leaq L_avx1_rorx_sha512_k(%rip), %rcx + addq $0x80, %rsi + subl $0x80, %ebp + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq %r12, 32(%rdi) + movq %r13, 40(%rdi) + movq %r14, 48(%rdi) + movq %r15, 56(%rdi) + jnz L_sha512_len_avx1_rorx_begin + xorq %rax, %rax + vzeroupper + addq $0x90, %rsp + popq %rbp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size Transform_Sha512_AVX1_RORX_Len,.-Transform_Sha512_AVX1_RORX_Len +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX1 */ +#ifdef HAVE_INTEL_AVX2 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx2_sha512_k: +.quad 0x428a2f98d728ae22,0x7137449123ef65cd +.quad 0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc +.quad 0x3956c25bf348b538,0x59f111f1b605d019 +.quad 0x923f82a4af194f9b,0xab1c5ed5da6d8118 +.quad 0xd807aa98a3030242,0x12835b0145706fbe +.quad 0x243185be4ee4b28c,0x550c7dc3d5ffb4e2 +.quad 0x72be5d74f27b896f,0x80deb1fe3b1696b1 +.quad 0x9bdc06a725c71235,0xc19bf174cf692694 +.quad 0xe49b69c19ef14ad2,0xefbe4786384f25e3 +.quad 0xfc19dc68b8cd5b5,0x240ca1cc77ac9c65 +.quad 0x2de92c6f592b0275,0x4a7484aa6ea6e483 +.quad 0x5cb0a9dcbd41fbd4,0x76f988da831153b5 +.quad 0x983e5152ee66dfab,0xa831c66d2db43210 +.quad 0xb00327c898fb213f,0xbf597fc7beef0ee4 +.quad 0xc6e00bf33da88fc2,0xd5a79147930aa725 +.quad 0x6ca6351e003826f,0x142929670a0e6e70 +.quad 0x27b70a8546d22ffc,0x2e1b21385c26c926 +.quad 0x4d2c6dfc5ac42aed,0x53380d139d95b3df +.quad 0x650a73548baf63de,0x766a0abb3c77b2a8 +.quad 0x81c2c92e47edaee6,0x92722c851482353b +.quad 0xa2bfe8a14cf10364,0xa81a664bbc423001 +.quad 0xc24b8b70d0f89791,0xc76c51a30654be30 +.quad 0xd192e819d6ef5218,0xd69906245565a910 +.quad 0xf40e35855771202a,0x106aa07032bbd1b8 +.quad 0x19a4c116b8d2d0c8,0x1e376c085141ab53 +.quad 0x2748774cdf8eeb99,0x34b0bcb5e19b48a8 +.quad 0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb +.quad 0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3 +.quad 0x748f82ee5defb2fc,0x78a5636f43172f60 +.quad 0x84c87814a1f0ab72,0x8cc702081a6439ec +.quad 0x90befffa23631e28,0xa4506cebde82bde9 +.quad 0xbef9a3f7b2c67915,0xc67178f2e372532b +.quad 0xca273eceea26619c,0xd186b8c721c0c207 +.quad 0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178 +.quad 0x6f067aa72176fba,0xa637dc5a2c898a6 +.quad 0x113f9804bef90dae,0x1b710b35131c471b +.quad 0x28db77f523047d84,0x32caab7b40c72493 +.quad 0x3c9ebe0a15c9bebc,0x431d67c49c100d4c +.quad 0x4cc5d4becb3e42b6,0x597f299cfc657e2a +.quad 0x5fcb6fab3ad6faec,0x6c44198c4a475817 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx2_sha512_k_2: +.quad 0x428a2f98d728ae22,0x7137449123ef65cd +.quad 0x428a2f98d728ae22,0x7137449123ef65cd +.quad 0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc +.quad 0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc +.quad 0x3956c25bf348b538,0x59f111f1b605d019 +.quad 0x3956c25bf348b538,0x59f111f1b605d019 +.quad 0x923f82a4af194f9b,0xab1c5ed5da6d8118 +.quad 0x923f82a4af194f9b,0xab1c5ed5da6d8118 +.quad 0xd807aa98a3030242,0x12835b0145706fbe +.quad 0xd807aa98a3030242,0x12835b0145706fbe +.quad 0x243185be4ee4b28c,0x550c7dc3d5ffb4e2 +.quad 0x243185be4ee4b28c,0x550c7dc3d5ffb4e2 +.quad 0x72be5d74f27b896f,0x80deb1fe3b1696b1 +.quad 0x72be5d74f27b896f,0x80deb1fe3b1696b1 +.quad 0x9bdc06a725c71235,0xc19bf174cf692694 +.quad 0x9bdc06a725c71235,0xc19bf174cf692694 +.quad 0xe49b69c19ef14ad2,0xefbe4786384f25e3 +.quad 0xe49b69c19ef14ad2,0xefbe4786384f25e3 +.quad 0xfc19dc68b8cd5b5,0x240ca1cc77ac9c65 +.quad 0xfc19dc68b8cd5b5,0x240ca1cc77ac9c65 +.quad 0x2de92c6f592b0275,0x4a7484aa6ea6e483 +.quad 0x2de92c6f592b0275,0x4a7484aa6ea6e483 +.quad 0x5cb0a9dcbd41fbd4,0x76f988da831153b5 +.quad 0x5cb0a9dcbd41fbd4,0x76f988da831153b5 +.quad 0x983e5152ee66dfab,0xa831c66d2db43210 +.quad 0x983e5152ee66dfab,0xa831c66d2db43210 +.quad 0xb00327c898fb213f,0xbf597fc7beef0ee4 +.quad 0xb00327c898fb213f,0xbf597fc7beef0ee4 +.quad 0xc6e00bf33da88fc2,0xd5a79147930aa725 +.quad 0xc6e00bf33da88fc2,0xd5a79147930aa725 +.quad 0x6ca6351e003826f,0x142929670a0e6e70 +.quad 0x6ca6351e003826f,0x142929670a0e6e70 +.quad 0x27b70a8546d22ffc,0x2e1b21385c26c926 +.quad 0x27b70a8546d22ffc,0x2e1b21385c26c926 +.quad 0x4d2c6dfc5ac42aed,0x53380d139d95b3df +.quad 0x4d2c6dfc5ac42aed,0x53380d139d95b3df +.quad 0x650a73548baf63de,0x766a0abb3c77b2a8 +.quad 0x650a73548baf63de,0x766a0abb3c77b2a8 +.quad 0x81c2c92e47edaee6,0x92722c851482353b +.quad 0x81c2c92e47edaee6,0x92722c851482353b +.quad 0xa2bfe8a14cf10364,0xa81a664bbc423001 +.quad 0xa2bfe8a14cf10364,0xa81a664bbc423001 +.quad 0xc24b8b70d0f89791,0xc76c51a30654be30 +.quad 0xc24b8b70d0f89791,0xc76c51a30654be30 +.quad 0xd192e819d6ef5218,0xd69906245565a910 +.quad 0xd192e819d6ef5218,0xd69906245565a910 +.quad 0xf40e35855771202a,0x106aa07032bbd1b8 +.quad 0xf40e35855771202a,0x106aa07032bbd1b8 +.quad 0x19a4c116b8d2d0c8,0x1e376c085141ab53 +.quad 0x19a4c116b8d2d0c8,0x1e376c085141ab53 +.quad 0x2748774cdf8eeb99,0x34b0bcb5e19b48a8 +.quad 0x2748774cdf8eeb99,0x34b0bcb5e19b48a8 +.quad 0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb +.quad 0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb +.quad 0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3 +.quad 0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3 +.quad 0x748f82ee5defb2fc,0x78a5636f43172f60 +.quad 0x748f82ee5defb2fc,0x78a5636f43172f60 +.quad 0x84c87814a1f0ab72,0x8cc702081a6439ec +.quad 0x84c87814a1f0ab72,0x8cc702081a6439ec +.quad 0x90befffa23631e28,0xa4506cebde82bde9 +.quad 0x90befffa23631e28,0xa4506cebde82bde9 +.quad 0xbef9a3f7b2c67915,0xc67178f2e372532b +.quad 0xbef9a3f7b2c67915,0xc67178f2e372532b +.quad 0xca273eceea26619c,0xd186b8c721c0c207 +.quad 0xca273eceea26619c,0xd186b8c721c0c207 +.quad 0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178 +.quad 0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178 +.quad 0x6f067aa72176fba,0xa637dc5a2c898a6 +.quad 0x6f067aa72176fba,0xa637dc5a2c898a6 +.quad 0x113f9804bef90dae,0x1b710b35131c471b +.quad 0x113f9804bef90dae,0x1b710b35131c471b +.quad 0x28db77f523047d84,0x32caab7b40c72493 +.quad 0x28db77f523047d84,0x32caab7b40c72493 +.quad 0x3c9ebe0a15c9bebc,0x431d67c49c100d4c +.quad 0x3c9ebe0a15c9bebc,0x431d67c49c100d4c +.quad 0x4cc5d4becb3e42b6,0x597f299cfc657e2a +.quad 0x4cc5d4becb3e42b6,0x597f299cfc657e2a +.quad 0x5fcb6fab3ad6faec,0x6c44198c4a475817 +.quad 0x5fcb6fab3ad6faec,0x6c44198c4a475817 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 8 +#else +.p2align 3 +#endif /* __APPLE__ */ +L_avx2_sha512_k_2_end: +.quad 1024+L_avx2_sha512_k_2 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 32 +#else +.p2align 5 +#endif /* __APPLE__ */ +L_avx2_sha512_flip_mask: +.quad 0x1020304050607, 0x8090a0b0c0d0e0f +.quad 0x1020304050607, 0x8090a0b0c0d0e0f +#ifndef __APPLE__ +.text +.globl Transform_Sha512_AVX2 +.type Transform_Sha512_AVX2,@function +.align 4 +Transform_Sha512_AVX2: +#else +.section __TEXT,__text +.globl _Transform_Sha512_AVX2 +.p2align 2 +_Transform_Sha512_AVX2: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + subq $0x88, %rsp + leaq 64(%rdi), %rax + vmovdqa L_avx2_sha512_flip_mask(%rip), %ymm15 + movq (%rdi), %r8 + movq 8(%rdi), %r9 + movq 16(%rdi), %r10 + movq 24(%rdi), %r11 + movq 32(%rdi), %r12 + movq 40(%rdi), %r13 + movq 48(%rdi), %r14 + movq 56(%rdi), %r15 + vmovdqu (%rax), %ymm0 + vmovdqu 32(%rax), %ymm1 + vpshufb %ymm15, %ymm0, %ymm0 + vpshufb %ymm15, %ymm1, %ymm1 + vmovdqu 64(%rax), %ymm2 + vmovdqu 96(%rax), %ymm3 + vpshufb %ymm15, %ymm2, %ymm2 + vpshufb %ymm15, %ymm3, %ymm3 + movl $4, 128(%rsp) + leaq L_avx2_sha512_k(%rip), %rsi + movq %r9, %rbx + movq %r12, %rax + xorq %r10, %rbx + vpaddq (%rsi), %ymm0, %ymm8 + vpaddq 32(%rsi), %ymm1, %ymm9 + vmovdqu %ymm8, (%rsp) + vmovdqu %ymm9, 32(%rsp) + vpaddq 64(%rsi), %ymm2, %ymm8 + vpaddq 96(%rsi), %ymm3, %ymm9 + vmovdqu %ymm8, 64(%rsp) + vmovdqu %ymm9, 96(%rsp) + # Start of 16 rounds +L_sha256_avx2_start: + addq $0x80, %rsi + rorq $23, %rax + vpblendd $3, %ymm1, %ymm0, %ymm12 + vpblendd $3, %ymm3, %ymm2, %ymm13 + movq %r8, %rdx + movq %r13, %rcx + addq (%rsp), %r15 + xorq %r14, %rcx + xorq %r12, %rax + andq %r12, %rcx + vpermq $57, %ymm12, %ymm12 + rorq $4, %rax + xorq %r14, %rcx + vpermq $57, %ymm13, %ymm13 + xorq %r12, %rax + addq %rcx, %r15 + rorq $14, %rax + xorq %r9, %rdx + vpsrlq $0x01, %ymm12, %ymm8 + addq %rax, %r15 + movq %r8, %rcx + vpsllq $63, %ymm12, %ymm9 + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $8, %ymm12, %ymm10 + xorq %r8, %rcx + xorq %r9, %rbx + vpsllq $56, %ymm12, %ymm11 + rorq $6, %rcx + addq %r15, %r11 + vpor %ymm9, %ymm8, %ymm8 + xorq %r8, %rcx + addq %rbx, %r15 + vpor %ymm11, %ymm10, %ymm10 + rorq $28, %rcx + movq %r11, %rax + addq %rcx, %r15 + rorq $23, %rax + vpsrlq $7, %ymm12, %ymm11 + movq %r15, %rbx + movq %r12, %rcx + vpxor %ymm10, %ymm8, %ymm8 + addq 8(%rsp), %r14 + xorq %r13, %rcx + vpxor %ymm11, %ymm8, %ymm8 + xorq %r11, %rax + andq %r11, %rcx + vpaddq %ymm0, %ymm13, %ymm0 + rorq $4, %rax + xorq %r13, %rcx + vpaddq %ymm0, %ymm8, %ymm0 + xorq %r11, %rax + addq %rcx, %r14 + vperm2I128 $0x81, %ymm3, %ymm3, %ymm14 + rorq $14, %rax + xorq %r8, %rbx + addq %rax, %r14 + movq %r15, %rcx + andq %rbx, %rdx + rorq $5, %rcx + vpsrlq $19, %ymm14, %ymm8 + xorq %r15, %rcx + xorq %r8, %rdx + vpsllq $45, %ymm14, %ymm9 + rorq $6, %rcx + addq %r14, %r10 + vpsrlq $61, %ymm14, %ymm10 + xorq %r15, %rcx + addq %rdx, %r14 + vpsllq $3, %ymm14, %ymm11 + rorq $28, %rcx + movq %r10, %rax + addq %rcx, %r14 + rorq $23, %rax + vpor %ymm9, %ymm8, %ymm8 + movq %r14, %rdx + movq %r11, %rcx + addq 16(%rsp), %r13 + xorq %r12, %rcx + vpor %ymm11, %ymm10, %ymm10 + xorq %r10, %rax + andq %r10, %rcx + vpxor %ymm10, %ymm8, %ymm8 + rorq $4, %rax + xorq %r12, %rcx + vpsrlq $6, %ymm14, %ymm11 + xorq %r10, %rax + addq %rcx, %r13 + vpxor %ymm11, %ymm8, %ymm8 + rorq $14, %rax + xorq %r15, %rdx + vpaddq %ymm0, %ymm8, %ymm0 + addq %rax, %r13 + movq %r14, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vperm2I128 $8, %ymm0, %ymm0, %ymm14 + xorq %r14, %rcx + xorq %r15, %rbx + rorq $6, %rcx + addq %r13, %r9 + vpsrlq $19, %ymm14, %ymm8 + xorq %r14, %rcx + addq %rbx, %r13 + vpsllq $45, %ymm14, %ymm9 + rorq $28, %rcx + movq %r9, %rax + addq %rcx, %r13 + rorq $23, %rax + vpsrlq $61, %ymm14, %ymm10 + movq %r13, %rbx + movq %r10, %rcx + addq 24(%rsp), %r12 + xorq %r11, %rcx + vpsllq $3, %ymm14, %ymm11 + xorq %r9, %rax + andq %r9, %rcx + vpor %ymm9, %ymm8, %ymm8 + rorq $4, %rax + xorq %r11, %rcx + vpor %ymm11, %ymm10, %ymm10 + xorq %r9, %rax + addq %rcx, %r12 + vpxor %ymm10, %ymm8, %ymm8 + rorq $14, %rax + xorq %r14, %rbx + vpsrlq $6, %ymm14, %ymm11 + addq %rax, %r12 + movq %r13, %rcx + vpxor %ymm11, %ymm8, %ymm8 + andq %rbx, %rdx + rorq $5, %rcx + vpaddq %ymm0, %ymm8, %ymm0 + xorq %r13, %rcx + xorq %r14, %rdx + rorq $6, %rcx + addq %r12, %r8 + xorq %r13, %rcx + addq %rdx, %r12 + rorq $28, %rcx + movq %r8, %rax + addq %rcx, %r12 + rorq $23, %rax + vpblendd $3, %ymm2, %ymm1, %ymm12 + vpblendd $3, %ymm0, %ymm3, %ymm13 + movq %r12, %rdx + movq %r9, %rcx + addq 32(%rsp), %r11 + xorq %r10, %rcx + xorq %r8, %rax + andq %r8, %rcx + vpermq $57, %ymm12, %ymm12 + rorq $4, %rax + xorq %r10, %rcx + vpermq $57, %ymm13, %ymm13 + xorq %r8, %rax + addq %rcx, %r11 + rorq $14, %rax + xorq %r13, %rdx + vpsrlq $0x01, %ymm12, %ymm8 + addq %rax, %r11 + movq %r12, %rcx + vpsllq $63, %ymm12, %ymm9 + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $8, %ymm12, %ymm10 + xorq %r12, %rcx + xorq %r13, %rbx + vpsllq $56, %ymm12, %ymm11 + rorq $6, %rcx + addq %r11, %r15 + vpor %ymm9, %ymm8, %ymm8 + xorq %r12, %rcx + addq %rbx, %r11 + vpor %ymm11, %ymm10, %ymm10 + rorq $28, %rcx + movq %r15, %rax + addq %rcx, %r11 + rorq $23, %rax + vpsrlq $7, %ymm12, %ymm11 + movq %r11, %rbx + movq %r8, %rcx + vpxor %ymm10, %ymm8, %ymm8 + addq 40(%rsp), %r10 + xorq %r9, %rcx + vpxor %ymm11, %ymm8, %ymm8 + xorq %r15, %rax + andq %r15, %rcx + vpaddq %ymm1, %ymm13, %ymm1 + rorq $4, %rax + xorq %r9, %rcx + vpaddq %ymm1, %ymm8, %ymm1 + xorq %r15, %rax + addq %rcx, %r10 + vperm2I128 $0x81, %ymm0, %ymm0, %ymm14 + rorq $14, %rax + xorq %r12, %rbx + addq %rax, %r10 + movq %r11, %rcx + andq %rbx, %rdx + rorq $5, %rcx + vpsrlq $19, %ymm14, %ymm8 + xorq %r11, %rcx + xorq %r12, %rdx + vpsllq $45, %ymm14, %ymm9 + rorq $6, %rcx + addq %r10, %r14 + vpsrlq $61, %ymm14, %ymm10 + xorq %r11, %rcx + addq %rdx, %r10 + vpsllq $3, %ymm14, %ymm11 + rorq $28, %rcx + movq %r14, %rax + addq %rcx, %r10 + rorq $23, %rax + vpor %ymm9, %ymm8, %ymm8 + movq %r10, %rdx + movq %r15, %rcx + addq 48(%rsp), %r9 + xorq %r8, %rcx + vpor %ymm11, %ymm10, %ymm10 + xorq %r14, %rax + andq %r14, %rcx + vpxor %ymm10, %ymm8, %ymm8 + rorq $4, %rax + xorq %r8, %rcx + vpsrlq $6, %ymm14, %ymm11 + xorq %r14, %rax + addq %rcx, %r9 + vpxor %ymm11, %ymm8, %ymm8 + rorq $14, %rax + xorq %r11, %rdx + vpaddq %ymm1, %ymm8, %ymm1 + addq %rax, %r9 + movq %r10, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vperm2I128 $8, %ymm1, %ymm1, %ymm14 + xorq %r10, %rcx + xorq %r11, %rbx + rorq $6, %rcx + addq %r9, %r13 + vpsrlq $19, %ymm14, %ymm8 + xorq %r10, %rcx + addq %rbx, %r9 + vpsllq $45, %ymm14, %ymm9 + rorq $28, %rcx + movq %r13, %rax + addq %rcx, %r9 + rorq $23, %rax + vpsrlq $61, %ymm14, %ymm10 + movq %r9, %rbx + movq %r14, %rcx + addq 56(%rsp), %r8 + xorq %r15, %rcx + vpsllq $3, %ymm14, %ymm11 + xorq %r13, %rax + andq %r13, %rcx + vpor %ymm9, %ymm8, %ymm8 + rorq $4, %rax + xorq %r15, %rcx + vpor %ymm11, %ymm10, %ymm10 + xorq %r13, %rax + addq %rcx, %r8 + vpxor %ymm10, %ymm8, %ymm8 + rorq $14, %rax + xorq %r10, %rbx + vpsrlq $6, %ymm14, %ymm11 + addq %rax, %r8 + movq %r9, %rcx + vpxor %ymm11, %ymm8, %ymm8 + andq %rbx, %rdx + rorq $5, %rcx + vpaddq %ymm1, %ymm8, %ymm1 + xorq %r9, %rcx + xorq %r10, %rdx + rorq $6, %rcx + addq %r8, %r12 + xorq %r9, %rcx + addq %rdx, %r8 + rorq $28, %rcx + movq %r12, %rax + addq %rcx, %r8 + rorq $23, %rax + vpblendd $3, %ymm3, %ymm2, %ymm12 + vpblendd $3, %ymm1, %ymm0, %ymm13 + movq %r8, %rdx + movq %r13, %rcx + addq 64(%rsp), %r15 + xorq %r14, %rcx + xorq %r12, %rax + andq %r12, %rcx + vpermq $57, %ymm12, %ymm12 + rorq $4, %rax + xorq %r14, %rcx + vpermq $57, %ymm13, %ymm13 + xorq %r12, %rax + addq %rcx, %r15 + rorq $14, %rax + xorq %r9, %rdx + vpsrlq $0x01, %ymm12, %ymm8 + addq %rax, %r15 + movq %r8, %rcx + vpsllq $63, %ymm12, %ymm9 + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $8, %ymm12, %ymm10 + xorq %r8, %rcx + xorq %r9, %rbx + vpsllq $56, %ymm12, %ymm11 + rorq $6, %rcx + addq %r15, %r11 + vpor %ymm9, %ymm8, %ymm8 + xorq %r8, %rcx + addq %rbx, %r15 + vpor %ymm11, %ymm10, %ymm10 + rorq $28, %rcx + movq %r11, %rax + addq %rcx, %r15 + rorq $23, %rax + vpsrlq $7, %ymm12, %ymm11 + movq %r15, %rbx + movq %r12, %rcx + vpxor %ymm10, %ymm8, %ymm8 + addq 72(%rsp), %r14 + xorq %r13, %rcx + vpxor %ymm11, %ymm8, %ymm8 + xorq %r11, %rax + andq %r11, %rcx + vpaddq %ymm2, %ymm13, %ymm2 + rorq $4, %rax + xorq %r13, %rcx + vpaddq %ymm2, %ymm8, %ymm2 + xorq %r11, %rax + addq %rcx, %r14 + vperm2I128 $0x81, %ymm1, %ymm1, %ymm14 + rorq $14, %rax + xorq %r8, %rbx + addq %rax, %r14 + movq %r15, %rcx + andq %rbx, %rdx + rorq $5, %rcx + vpsrlq $19, %ymm14, %ymm8 + xorq %r15, %rcx + xorq %r8, %rdx + vpsllq $45, %ymm14, %ymm9 + rorq $6, %rcx + addq %r14, %r10 + vpsrlq $61, %ymm14, %ymm10 + xorq %r15, %rcx + addq %rdx, %r14 + vpsllq $3, %ymm14, %ymm11 + rorq $28, %rcx + movq %r10, %rax + addq %rcx, %r14 + rorq $23, %rax + vpor %ymm9, %ymm8, %ymm8 + movq %r14, %rdx + movq %r11, %rcx + addq 80(%rsp), %r13 + xorq %r12, %rcx + vpor %ymm11, %ymm10, %ymm10 + xorq %r10, %rax + andq %r10, %rcx + vpxor %ymm10, %ymm8, %ymm8 + rorq $4, %rax + xorq %r12, %rcx + vpsrlq $6, %ymm14, %ymm11 + xorq %r10, %rax + addq %rcx, %r13 + vpxor %ymm11, %ymm8, %ymm8 + rorq $14, %rax + xorq %r15, %rdx + vpaddq %ymm2, %ymm8, %ymm2 + addq %rax, %r13 + movq %r14, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vperm2I128 $8, %ymm2, %ymm2, %ymm14 + xorq %r14, %rcx + xorq %r15, %rbx + rorq $6, %rcx + addq %r13, %r9 + vpsrlq $19, %ymm14, %ymm8 + xorq %r14, %rcx + addq %rbx, %r13 + vpsllq $45, %ymm14, %ymm9 + rorq $28, %rcx + movq %r9, %rax + addq %rcx, %r13 + rorq $23, %rax + vpsrlq $61, %ymm14, %ymm10 + movq %r13, %rbx + movq %r10, %rcx + addq 88(%rsp), %r12 + xorq %r11, %rcx + vpsllq $3, %ymm14, %ymm11 + xorq %r9, %rax + andq %r9, %rcx + vpor %ymm9, %ymm8, %ymm8 + rorq $4, %rax + xorq %r11, %rcx + vpor %ymm11, %ymm10, %ymm10 + xorq %r9, %rax + addq %rcx, %r12 + vpxor %ymm10, %ymm8, %ymm8 + rorq $14, %rax + xorq %r14, %rbx + vpsrlq $6, %ymm14, %ymm11 + addq %rax, %r12 + movq %r13, %rcx + vpxor %ymm11, %ymm8, %ymm8 + andq %rbx, %rdx + rorq $5, %rcx + vpaddq %ymm2, %ymm8, %ymm2 + xorq %r13, %rcx + xorq %r14, %rdx + rorq $6, %rcx + addq %r12, %r8 + xorq %r13, %rcx + addq %rdx, %r12 + rorq $28, %rcx + movq %r8, %rax + addq %rcx, %r12 + rorq $23, %rax + vpblendd $3, %ymm0, %ymm3, %ymm12 + vpblendd $3, %ymm2, %ymm1, %ymm13 + movq %r12, %rdx + movq %r9, %rcx + addq 96(%rsp), %r11 + xorq %r10, %rcx + xorq %r8, %rax + andq %r8, %rcx + vpermq $57, %ymm12, %ymm12 + rorq $4, %rax + xorq %r10, %rcx + vpermq $57, %ymm13, %ymm13 + xorq %r8, %rax + addq %rcx, %r11 + rorq $14, %rax + xorq %r13, %rdx + vpsrlq $0x01, %ymm12, %ymm8 + addq %rax, %r11 + movq %r12, %rcx + vpsllq $63, %ymm12, %ymm9 + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $8, %ymm12, %ymm10 + xorq %r12, %rcx + xorq %r13, %rbx + vpsllq $56, %ymm12, %ymm11 + rorq $6, %rcx + addq %r11, %r15 + vpor %ymm9, %ymm8, %ymm8 + xorq %r12, %rcx + addq %rbx, %r11 + vpor %ymm11, %ymm10, %ymm10 + rorq $28, %rcx + movq %r15, %rax + addq %rcx, %r11 + rorq $23, %rax + vpsrlq $7, %ymm12, %ymm11 + movq %r11, %rbx + movq %r8, %rcx + vpxor %ymm10, %ymm8, %ymm8 + addq 104(%rsp), %r10 + xorq %r9, %rcx + vpxor %ymm11, %ymm8, %ymm8 + xorq %r15, %rax + andq %r15, %rcx + vpaddq %ymm3, %ymm13, %ymm3 + rorq $4, %rax + xorq %r9, %rcx + vpaddq %ymm3, %ymm8, %ymm3 + xorq %r15, %rax + addq %rcx, %r10 + vperm2I128 $0x81, %ymm2, %ymm2, %ymm14 + rorq $14, %rax + xorq %r12, %rbx + addq %rax, %r10 + movq %r11, %rcx + andq %rbx, %rdx + rorq $5, %rcx + vpsrlq $19, %ymm14, %ymm8 + xorq %r11, %rcx + xorq %r12, %rdx + vpsllq $45, %ymm14, %ymm9 + rorq $6, %rcx + addq %r10, %r14 + vpsrlq $61, %ymm14, %ymm10 + xorq %r11, %rcx + addq %rdx, %r10 + vpsllq $3, %ymm14, %ymm11 + rorq $28, %rcx + movq %r14, %rax + addq %rcx, %r10 + rorq $23, %rax + vpor %ymm9, %ymm8, %ymm8 + movq %r10, %rdx + movq %r15, %rcx + addq 112(%rsp), %r9 + xorq %r8, %rcx + vpor %ymm11, %ymm10, %ymm10 + xorq %r14, %rax + andq %r14, %rcx + vpxor %ymm10, %ymm8, %ymm8 + rorq $4, %rax + xorq %r8, %rcx + vpsrlq $6, %ymm14, %ymm11 + xorq %r14, %rax + addq %rcx, %r9 + vpxor %ymm11, %ymm8, %ymm8 + rorq $14, %rax + xorq %r11, %rdx + vpaddq %ymm3, %ymm8, %ymm3 + addq %rax, %r9 + movq %r10, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vperm2I128 $8, %ymm3, %ymm3, %ymm14 + xorq %r10, %rcx + xorq %r11, %rbx + rorq $6, %rcx + addq %r9, %r13 + vpsrlq $19, %ymm14, %ymm8 + xorq %r10, %rcx + addq %rbx, %r9 + vpsllq $45, %ymm14, %ymm9 + rorq $28, %rcx + movq %r13, %rax + addq %rcx, %r9 + rorq $23, %rax + vpsrlq $61, %ymm14, %ymm10 + movq %r9, %rbx + movq %r14, %rcx + addq 120(%rsp), %r8 + xorq %r15, %rcx + vpsllq $3, %ymm14, %ymm11 + xorq %r13, %rax + andq %r13, %rcx + vpor %ymm9, %ymm8, %ymm8 + rorq $4, %rax + xorq %r15, %rcx + vpor %ymm11, %ymm10, %ymm10 + xorq %r13, %rax + addq %rcx, %r8 + vpxor %ymm10, %ymm8, %ymm8 + rorq $14, %rax + xorq %r10, %rbx + vpsrlq $6, %ymm14, %ymm11 + addq %rax, %r8 + movq %r9, %rcx + vpxor %ymm11, %ymm8, %ymm8 + andq %rbx, %rdx + rorq $5, %rcx + vpaddq %ymm3, %ymm8, %ymm3 + xorq %r9, %rcx + xorq %r10, %rdx + rorq $6, %rcx + addq %r8, %r12 + xorq %r9, %rcx + addq %rdx, %r8 + rorq $28, %rcx + movq %r12, %rax + addq %rcx, %r8 + vpaddq (%rsi), %ymm0, %ymm8 + vpaddq 32(%rsi), %ymm1, %ymm9 + vmovdqu %ymm8, (%rsp) + vmovdqu %ymm9, 32(%rsp) + vpaddq 64(%rsi), %ymm2, %ymm8 + vpaddq 96(%rsi), %ymm3, %ymm9 + vmovdqu %ymm8, 64(%rsp) + vmovdqu %ymm9, 96(%rsp) + subl $0x01, 128(%rsp) + jne L_sha256_avx2_start + rorq $23, %rax + movq %r8, %rdx + movq %r13, %rcx + addq (%rsp), %r15 + xorq %r14, %rcx + xorq %r12, %rax + andq %r12, %rcx + rorq $4, %rax + xorq %r14, %rcx + xorq %r12, %rax + addq %rcx, %r15 + rorq $14, %rax + xorq %r9, %rdx + addq %rax, %r15 + movq %r8, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r8, %rcx + xorq %r9, %rbx + rorq $6, %rcx + addq %r15, %r11 + xorq %r8, %rcx + addq %rbx, %r15 + rorq $28, %rcx + movq %r11, %rax + addq %rcx, %r15 + rorq $23, %rax + movq %r15, %rbx + movq %r12, %rcx + addq 8(%rsp), %r14 + xorq %r13, %rcx + xorq %r11, %rax + andq %r11, %rcx + rorq $4, %rax + xorq %r13, %rcx + xorq %r11, %rax + addq %rcx, %r14 + rorq $14, %rax + xorq %r8, %rbx + addq %rax, %r14 + movq %r15, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r15, %rcx + xorq %r8, %rdx + rorq $6, %rcx + addq %r14, %r10 + xorq %r15, %rcx + addq %rdx, %r14 + rorq $28, %rcx + movq %r10, %rax + addq %rcx, %r14 + rorq $23, %rax + movq %r14, %rdx + movq %r11, %rcx + addq 16(%rsp), %r13 + xorq %r12, %rcx + xorq %r10, %rax + andq %r10, %rcx + rorq $4, %rax + xorq %r12, %rcx + xorq %r10, %rax + addq %rcx, %r13 + rorq $14, %rax + xorq %r15, %rdx + addq %rax, %r13 + movq %r14, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r14, %rcx + xorq %r15, %rbx + rorq $6, %rcx + addq %r13, %r9 + xorq %r14, %rcx + addq %rbx, %r13 + rorq $28, %rcx + movq %r9, %rax + addq %rcx, %r13 + rorq $23, %rax + movq %r13, %rbx + movq %r10, %rcx + addq 24(%rsp), %r12 + xorq %r11, %rcx + xorq %r9, %rax + andq %r9, %rcx + rorq $4, %rax + xorq %r11, %rcx + xorq %r9, %rax + addq %rcx, %r12 + rorq $14, %rax + xorq %r14, %rbx + addq %rax, %r12 + movq %r13, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r13, %rcx + xorq %r14, %rdx + rorq $6, %rcx + addq %r12, %r8 + xorq %r13, %rcx + addq %rdx, %r12 + rorq $28, %rcx + movq %r8, %rax + addq %rcx, %r12 + rorq $23, %rax + movq %r12, %rdx + movq %r9, %rcx + addq 32(%rsp), %r11 + xorq %r10, %rcx + xorq %r8, %rax + andq %r8, %rcx + rorq $4, %rax + xorq %r10, %rcx + xorq %r8, %rax + addq %rcx, %r11 + rorq $14, %rax + xorq %r13, %rdx + addq %rax, %r11 + movq %r12, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r12, %rcx + xorq %r13, %rbx + rorq $6, %rcx + addq %r11, %r15 + xorq %r12, %rcx + addq %rbx, %r11 + rorq $28, %rcx + movq %r15, %rax + addq %rcx, %r11 + rorq $23, %rax + movq %r11, %rbx + movq %r8, %rcx + addq 40(%rsp), %r10 + xorq %r9, %rcx + xorq %r15, %rax + andq %r15, %rcx + rorq $4, %rax + xorq %r9, %rcx + xorq %r15, %rax + addq %rcx, %r10 + rorq $14, %rax + xorq %r12, %rbx + addq %rax, %r10 + movq %r11, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r11, %rcx + xorq %r12, %rdx + rorq $6, %rcx + addq %r10, %r14 + xorq %r11, %rcx + addq %rdx, %r10 + rorq $28, %rcx + movq %r14, %rax + addq %rcx, %r10 + rorq $23, %rax + movq %r10, %rdx + movq %r15, %rcx + addq 48(%rsp), %r9 + xorq %r8, %rcx + xorq %r14, %rax + andq %r14, %rcx + rorq $4, %rax + xorq %r8, %rcx + xorq %r14, %rax + addq %rcx, %r9 + rorq $14, %rax + xorq %r11, %rdx + addq %rax, %r9 + movq %r10, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r10, %rcx + xorq %r11, %rbx + rorq $6, %rcx + addq %r9, %r13 + xorq %r10, %rcx + addq %rbx, %r9 + rorq $28, %rcx + movq %r13, %rax + addq %rcx, %r9 + rorq $23, %rax + movq %r9, %rbx + movq %r14, %rcx + addq 56(%rsp), %r8 + xorq %r15, %rcx + xorq %r13, %rax + andq %r13, %rcx + rorq $4, %rax + xorq %r15, %rcx + xorq %r13, %rax + addq %rcx, %r8 + rorq $14, %rax + xorq %r10, %rbx + addq %rax, %r8 + movq %r9, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r9, %rcx + xorq %r10, %rdx + rorq $6, %rcx + addq %r8, %r12 + xorq %r9, %rcx + addq %rdx, %r8 + rorq $28, %rcx + movq %r12, %rax + addq %rcx, %r8 + rorq $23, %rax + movq %r8, %rdx + movq %r13, %rcx + addq 64(%rsp), %r15 + xorq %r14, %rcx + xorq %r12, %rax + andq %r12, %rcx + rorq $4, %rax + xorq %r14, %rcx + xorq %r12, %rax + addq %rcx, %r15 + rorq $14, %rax + xorq %r9, %rdx + addq %rax, %r15 + movq %r8, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r8, %rcx + xorq %r9, %rbx + rorq $6, %rcx + addq %r15, %r11 + xorq %r8, %rcx + addq %rbx, %r15 + rorq $28, %rcx + movq %r11, %rax + addq %rcx, %r15 + rorq $23, %rax + movq %r15, %rbx + movq %r12, %rcx + addq 72(%rsp), %r14 + xorq %r13, %rcx + xorq %r11, %rax + andq %r11, %rcx + rorq $4, %rax + xorq %r13, %rcx + xorq %r11, %rax + addq %rcx, %r14 + rorq $14, %rax + xorq %r8, %rbx + addq %rax, %r14 + movq %r15, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r15, %rcx + xorq %r8, %rdx + rorq $6, %rcx + addq %r14, %r10 + xorq %r15, %rcx + addq %rdx, %r14 + rorq $28, %rcx + movq %r10, %rax + addq %rcx, %r14 + rorq $23, %rax + movq %r14, %rdx + movq %r11, %rcx + addq 80(%rsp), %r13 + xorq %r12, %rcx + xorq %r10, %rax + andq %r10, %rcx + rorq $4, %rax + xorq %r12, %rcx + xorq %r10, %rax + addq %rcx, %r13 + rorq $14, %rax + xorq %r15, %rdx + addq %rax, %r13 + movq %r14, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r14, %rcx + xorq %r15, %rbx + rorq $6, %rcx + addq %r13, %r9 + xorq %r14, %rcx + addq %rbx, %r13 + rorq $28, %rcx + movq %r9, %rax + addq %rcx, %r13 + rorq $23, %rax + movq %r13, %rbx + movq %r10, %rcx + addq 88(%rsp), %r12 + xorq %r11, %rcx + xorq %r9, %rax + andq %r9, %rcx + rorq $4, %rax + xorq %r11, %rcx + xorq %r9, %rax + addq %rcx, %r12 + rorq $14, %rax + xorq %r14, %rbx + addq %rax, %r12 + movq %r13, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r13, %rcx + xorq %r14, %rdx + rorq $6, %rcx + addq %r12, %r8 + xorq %r13, %rcx + addq %rdx, %r12 + rorq $28, %rcx + movq %r8, %rax + addq %rcx, %r12 + rorq $23, %rax + movq %r12, %rdx + movq %r9, %rcx + addq 96(%rsp), %r11 + xorq %r10, %rcx + xorq %r8, %rax + andq %r8, %rcx + rorq $4, %rax + xorq %r10, %rcx + xorq %r8, %rax + addq %rcx, %r11 + rorq $14, %rax + xorq %r13, %rdx + addq %rax, %r11 + movq %r12, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r12, %rcx + xorq %r13, %rbx + rorq $6, %rcx + addq %r11, %r15 + xorq %r12, %rcx + addq %rbx, %r11 + rorq $28, %rcx + movq %r15, %rax + addq %rcx, %r11 + rorq $23, %rax + movq %r11, %rbx + movq %r8, %rcx + addq 104(%rsp), %r10 + xorq %r9, %rcx + xorq %r15, %rax + andq %r15, %rcx + rorq $4, %rax + xorq %r9, %rcx + xorq %r15, %rax + addq %rcx, %r10 + rorq $14, %rax + xorq %r12, %rbx + addq %rax, %r10 + movq %r11, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r11, %rcx + xorq %r12, %rdx + rorq $6, %rcx + addq %r10, %r14 + xorq %r11, %rcx + addq %rdx, %r10 + rorq $28, %rcx + movq %r14, %rax + addq %rcx, %r10 + rorq $23, %rax + movq %r10, %rdx + movq %r15, %rcx + addq 112(%rsp), %r9 + xorq %r8, %rcx + xorq %r14, %rax + andq %r14, %rcx + rorq $4, %rax + xorq %r8, %rcx + xorq %r14, %rax + addq %rcx, %r9 + rorq $14, %rax + xorq %r11, %rdx + addq %rax, %r9 + movq %r10, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r10, %rcx + xorq %r11, %rbx + rorq $6, %rcx + addq %r9, %r13 + xorq %r10, %rcx + addq %rbx, %r9 + rorq $28, %rcx + movq %r13, %rax + addq %rcx, %r9 + rorq $23, %rax + movq %r9, %rbx + movq %r14, %rcx + addq 120(%rsp), %r8 + xorq %r15, %rcx + xorq %r13, %rax + andq %r13, %rcx + rorq $4, %rax + xorq %r15, %rcx + xorq %r13, %rax + addq %rcx, %r8 + rorq $14, %rax + xorq %r10, %rbx + addq %rax, %r8 + movq %r9, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r9, %rcx + xorq %r10, %rdx + rorq $6, %rcx + addq %r8, %r12 + xorq %r9, %rcx + addq %rdx, %r8 + rorq $28, %rcx + movq %r12, %rax + addq %rcx, %r8 + addq %r8, (%rdi) + addq %r9, 8(%rdi) + addq %r10, 16(%rdi) + addq %r11, 24(%rdi) + addq %r12, 32(%rdi) + addq %r13, 40(%rdi) + addq %r14, 48(%rdi) + addq %r15, 56(%rdi) + xorq %rax, %rax + vzeroupper + addq $0x88, %rsp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size Transform_Sha512_AVX2,.-Transform_Sha512_AVX2 +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl Transform_Sha512_AVX2_Len +.type Transform_Sha512_AVX2_Len,@function +.align 4 +Transform_Sha512_AVX2_Len: +#else +.section __TEXT,__text +.globl _Transform_Sha512_AVX2_Len +.p2align 2 +_Transform_Sha512_AVX2_Len: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + pushq %rbp + movq %rsi, %rbp + testb $0x80, %bpl + je L_sha512_len_avx2_block + movq 224(%rdi), %rcx + vmovdqu (%rcx), %ymm0 + vmovdqu 32(%rcx), %ymm1 + vmovdqu 64(%rcx), %ymm2 + vmovdqu 96(%rcx), %ymm3 + vmovups %ymm0, 64(%rdi) + vmovups %ymm1, 96(%rdi) + vmovups %ymm2, 128(%rdi) + vmovups %ymm3, 160(%rdi) +#ifndef __APPLE__ + call Transform_Sha512_AVX2@plt +#else + call _Transform_Sha512_AVX2 +#endif /* __APPLE__ */ + addq $0x80, 224(%rdi) + subl $0x80, %ebp + jz L_sha512_len_avx2_done +L_sha512_len_avx2_block: + movq 224(%rdi), %rcx + vmovdqa L_avx2_sha512_flip_mask(%rip), %ymm15 + movq (%rdi), %r8 + movq 8(%rdi), %r9 + movq 16(%rdi), %r10 + movq 24(%rdi), %r11 + movq 32(%rdi), %r12 + movq 40(%rdi), %r13 + movq 48(%rdi), %r14 + movq 56(%rdi), %r15 + # Start of loop processing two blocks +L_sha512_len_avx2_begin: + subq $0x540, %rsp + leaq L_avx2_sha512_k_2(%rip), %rsi + movq %r9, %rbx + movq %r12, %rax + vmovdqu (%rcx), %xmm0 + vmovdqu 16(%rcx), %xmm1 + vinserti128 $0x01, 128(%rcx), %ymm0, %ymm0 + vinserti128 $0x01, 144(%rcx), %ymm1, %ymm1 + vpshufb %ymm15, %ymm0, %ymm0 + vpshufb %ymm15, %ymm1, %ymm1 + vmovdqu 32(%rcx), %xmm2 + vmovdqu 48(%rcx), %xmm3 + vinserti128 $0x01, 160(%rcx), %ymm2, %ymm2 + vinserti128 $0x01, 176(%rcx), %ymm3, %ymm3 + vpshufb %ymm15, %ymm2, %ymm2 + vpshufb %ymm15, %ymm3, %ymm3 + vmovdqu 64(%rcx), %xmm4 + vmovdqu 80(%rcx), %xmm5 + vinserti128 $0x01, 192(%rcx), %ymm4, %ymm4 + vinserti128 $0x01, 208(%rcx), %ymm5, %ymm5 + vpshufb %ymm15, %ymm4, %ymm4 + vpshufb %ymm15, %ymm5, %ymm5 + vmovdqu 96(%rcx), %xmm6 + vmovdqu 112(%rcx), %xmm7 + vinserti128 $0x01, 224(%rcx), %ymm6, %ymm6 + vinserti128 $0x01, 240(%rcx), %ymm7, %ymm7 + vpshufb %ymm15, %ymm6, %ymm6 + vpshufb %ymm15, %ymm7, %ymm7 + xorq %r10, %rbx + # Start of 16 rounds +L_sha512_len_avx2_start: + vpaddq (%rsi), %ymm0, %ymm8 + vpaddq 32(%rsi), %ymm1, %ymm9 + vmovdqu %ymm8, (%rsp) + vmovdqu %ymm9, 32(%rsp) + vpaddq 64(%rsi), %ymm2, %ymm8 + vpaddq 96(%rsi), %ymm3, %ymm9 + vmovdqu %ymm8, 64(%rsp) + vmovdqu %ymm9, 96(%rsp) + vpaddq 128(%rsi), %ymm4, %ymm8 + vpaddq 160(%rsi), %ymm5, %ymm9 + vmovdqu %ymm8, 128(%rsp) + vmovdqu %ymm9, 160(%rsp) + vpaddq 192(%rsi), %ymm6, %ymm8 + vpaddq 224(%rsi), %ymm7, %ymm9 + vmovdqu %ymm8, 192(%rsp) + vmovdqu %ymm9, 224(%rsp) + # msg_sched: 0-1 + rorq $23, %rax + vpalignr $8, %ymm0, %ymm1, %ymm12 + vpalignr $8, %ymm4, %ymm5, %ymm13 + movq %r8, %rdx + movq %r13, %rcx + addq (%rsp), %r15 + xorq %r14, %rcx + vpsrlq $0x01, %ymm12, %ymm8 + vpsllq $63, %ymm12, %ymm9 + xorq %r12, %rax + andq %r12, %rcx + rorq $4, %rax + xorq %r14, %rcx + vpsrlq $8, %ymm12, %ymm10 + vpsllq $56, %ymm12, %ymm11 + xorq %r12, %rax + addq %rcx, %r15 + rorq $14, %rax + xorq %r9, %rdx + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + addq %rax, %r15 + movq %r8, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $7, %ymm12, %ymm11 + vpxor %ymm10, %ymm8, %ymm8 + xorq %r8, %rcx + xorq %r9, %rbx + rorq $6, %rcx + addq %r15, %r11 + vpxor %ymm11, %ymm8, %ymm8 + vpaddq %ymm0, %ymm13, %ymm0 + xorq %r8, %rcx + addq %rbx, %r15 + rorq $28, %rcx + movq %r11, %rax + addq %rcx, %r15 + rorq $23, %rax + vpaddq %ymm0, %ymm8, %ymm0 + movq %r15, %rbx + movq %r12, %rcx + addq 8(%rsp), %r14 + xorq %r13, %rcx + vpsrlq $19, %ymm7, %ymm8 + vpsllq $45, %ymm7, %ymm9 + xorq %r11, %rax + andq %r11, %rcx + rorq $4, %rax + xorq %r13, %rcx + vpsrlq $61, %ymm7, %ymm10 + vpsllq $3, %ymm7, %ymm11 + xorq %r11, %rax + addq %rcx, %r14 + rorq $14, %rax + xorq %r8, %rbx + addq %rax, %r14 + movq %r15, %rcx + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + andq %rbx, %rdx + rorq $5, %rcx + xorq %r15, %rcx + xorq %r8, %rdx + vpxor %ymm10, %ymm8, %ymm8 + vpsrlq $6, %ymm7, %ymm11 + rorq $6, %rcx + addq %r14, %r10 + xorq %r15, %rcx + addq %rdx, %r14 + vpxor %ymm11, %ymm8, %ymm8 + rorq $28, %rcx + movq %r10, %rax + addq %rcx, %r14 + vpaddq %ymm0, %ymm8, %ymm0 + # msg_sched done: 0-3 + # msg_sched: 4-5 + rorq $23, %rax + vpalignr $8, %ymm1, %ymm2, %ymm12 + vpalignr $8, %ymm5, %ymm6, %ymm13 + movq %r14, %rdx + movq %r11, %rcx + addq 32(%rsp), %r13 + xorq %r12, %rcx + vpsrlq $0x01, %ymm12, %ymm8 + vpsllq $63, %ymm12, %ymm9 + xorq %r10, %rax + andq %r10, %rcx + rorq $4, %rax + xorq %r12, %rcx + vpsrlq $8, %ymm12, %ymm10 + vpsllq $56, %ymm12, %ymm11 + xorq %r10, %rax + addq %rcx, %r13 + rorq $14, %rax + xorq %r15, %rdx + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + addq %rax, %r13 + movq %r14, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $7, %ymm12, %ymm11 + vpxor %ymm10, %ymm8, %ymm8 + xorq %r14, %rcx + xorq %r15, %rbx + rorq $6, %rcx + addq %r13, %r9 + vpxor %ymm11, %ymm8, %ymm8 + vpaddq %ymm1, %ymm13, %ymm1 + xorq %r14, %rcx + addq %rbx, %r13 + rorq $28, %rcx + movq %r9, %rax + addq %rcx, %r13 + rorq $23, %rax + vpaddq %ymm1, %ymm8, %ymm1 + movq %r13, %rbx + movq %r10, %rcx + addq 40(%rsp), %r12 + xorq %r11, %rcx + vpsrlq $19, %ymm0, %ymm8 + vpsllq $45, %ymm0, %ymm9 + xorq %r9, %rax + andq %r9, %rcx + rorq $4, %rax + xorq %r11, %rcx + vpsrlq $61, %ymm0, %ymm10 + vpsllq $3, %ymm0, %ymm11 + xorq %r9, %rax + addq %rcx, %r12 + rorq $14, %rax + xorq %r14, %rbx + addq %rax, %r12 + movq %r13, %rcx + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + andq %rbx, %rdx + rorq $5, %rcx + xorq %r13, %rcx + xorq %r14, %rdx + vpxor %ymm10, %ymm8, %ymm8 + vpsrlq $6, %ymm0, %ymm11 + rorq $6, %rcx + addq %r12, %r8 + xorq %r13, %rcx + addq %rdx, %r12 + vpxor %ymm11, %ymm8, %ymm8 + rorq $28, %rcx + movq %r8, %rax + addq %rcx, %r12 + vpaddq %ymm1, %ymm8, %ymm1 + # msg_sched done: 4-7 + # msg_sched: 8-9 + rorq $23, %rax + vpalignr $8, %ymm2, %ymm3, %ymm12 + vpalignr $8, %ymm6, %ymm7, %ymm13 + movq %r12, %rdx + movq %r9, %rcx + addq 64(%rsp), %r11 + xorq %r10, %rcx + vpsrlq $0x01, %ymm12, %ymm8 + vpsllq $63, %ymm12, %ymm9 + xorq %r8, %rax + andq %r8, %rcx + rorq $4, %rax + xorq %r10, %rcx + vpsrlq $8, %ymm12, %ymm10 + vpsllq $56, %ymm12, %ymm11 + xorq %r8, %rax + addq %rcx, %r11 + rorq $14, %rax + xorq %r13, %rdx + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + addq %rax, %r11 + movq %r12, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $7, %ymm12, %ymm11 + vpxor %ymm10, %ymm8, %ymm8 + xorq %r12, %rcx + xorq %r13, %rbx + rorq $6, %rcx + addq %r11, %r15 + vpxor %ymm11, %ymm8, %ymm8 + vpaddq %ymm2, %ymm13, %ymm2 + xorq %r12, %rcx + addq %rbx, %r11 + rorq $28, %rcx + movq %r15, %rax + addq %rcx, %r11 + rorq $23, %rax + vpaddq %ymm2, %ymm8, %ymm2 + movq %r11, %rbx + movq %r8, %rcx + addq 72(%rsp), %r10 + xorq %r9, %rcx + vpsrlq $19, %ymm1, %ymm8 + vpsllq $45, %ymm1, %ymm9 + xorq %r15, %rax + andq %r15, %rcx + rorq $4, %rax + xorq %r9, %rcx + vpsrlq $61, %ymm1, %ymm10 + vpsllq $3, %ymm1, %ymm11 + xorq %r15, %rax + addq %rcx, %r10 + rorq $14, %rax + xorq %r12, %rbx + addq %rax, %r10 + movq %r11, %rcx + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + andq %rbx, %rdx + rorq $5, %rcx + xorq %r11, %rcx + xorq %r12, %rdx + vpxor %ymm10, %ymm8, %ymm8 + vpsrlq $6, %ymm1, %ymm11 + rorq $6, %rcx + addq %r10, %r14 + xorq %r11, %rcx + addq %rdx, %r10 + vpxor %ymm11, %ymm8, %ymm8 + rorq $28, %rcx + movq %r14, %rax + addq %rcx, %r10 + vpaddq %ymm2, %ymm8, %ymm2 + # msg_sched done: 8-11 + # msg_sched: 12-13 + rorq $23, %rax + vpalignr $8, %ymm3, %ymm4, %ymm12 + vpalignr $8, %ymm7, %ymm0, %ymm13 + movq %r10, %rdx + movq %r15, %rcx + addq 96(%rsp), %r9 + xorq %r8, %rcx + vpsrlq $0x01, %ymm12, %ymm8 + vpsllq $63, %ymm12, %ymm9 + xorq %r14, %rax + andq %r14, %rcx + rorq $4, %rax + xorq %r8, %rcx + vpsrlq $8, %ymm12, %ymm10 + vpsllq $56, %ymm12, %ymm11 + xorq %r14, %rax + addq %rcx, %r9 + rorq $14, %rax + xorq %r11, %rdx + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + addq %rax, %r9 + movq %r10, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $7, %ymm12, %ymm11 + vpxor %ymm10, %ymm8, %ymm8 + xorq %r10, %rcx + xorq %r11, %rbx + rorq $6, %rcx + addq %r9, %r13 + vpxor %ymm11, %ymm8, %ymm8 + vpaddq %ymm3, %ymm13, %ymm3 + xorq %r10, %rcx + addq %rbx, %r9 + rorq $28, %rcx + movq %r13, %rax + addq %rcx, %r9 + rorq $23, %rax + vpaddq %ymm3, %ymm8, %ymm3 + movq %r9, %rbx + movq %r14, %rcx + addq 104(%rsp), %r8 + xorq %r15, %rcx + vpsrlq $19, %ymm2, %ymm8 + vpsllq $45, %ymm2, %ymm9 + xorq %r13, %rax + andq %r13, %rcx + rorq $4, %rax + xorq %r15, %rcx + vpsrlq $61, %ymm2, %ymm10 + vpsllq $3, %ymm2, %ymm11 + xorq %r13, %rax + addq %rcx, %r8 + rorq $14, %rax + xorq %r10, %rbx + addq %rax, %r8 + movq %r9, %rcx + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + andq %rbx, %rdx + rorq $5, %rcx + xorq %r9, %rcx + xorq %r10, %rdx + vpxor %ymm10, %ymm8, %ymm8 + vpsrlq $6, %ymm2, %ymm11 + rorq $6, %rcx + addq %r8, %r12 + xorq %r9, %rcx + addq %rdx, %r8 + vpxor %ymm11, %ymm8, %ymm8 + rorq $28, %rcx + movq %r12, %rax + addq %rcx, %r8 + vpaddq %ymm3, %ymm8, %ymm3 + # msg_sched done: 12-15 + # msg_sched: 16-17 + rorq $23, %rax + vpalignr $8, %ymm4, %ymm5, %ymm12 + vpalignr $8, %ymm0, %ymm1, %ymm13 + movq %r8, %rdx + movq %r13, %rcx + addq 128(%rsp), %r15 + xorq %r14, %rcx + vpsrlq $0x01, %ymm12, %ymm8 + vpsllq $63, %ymm12, %ymm9 + xorq %r12, %rax + andq %r12, %rcx + rorq $4, %rax + xorq %r14, %rcx + vpsrlq $8, %ymm12, %ymm10 + vpsllq $56, %ymm12, %ymm11 + xorq %r12, %rax + addq %rcx, %r15 + rorq $14, %rax + xorq %r9, %rdx + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + addq %rax, %r15 + movq %r8, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $7, %ymm12, %ymm11 + vpxor %ymm10, %ymm8, %ymm8 + xorq %r8, %rcx + xorq %r9, %rbx + rorq $6, %rcx + addq %r15, %r11 + vpxor %ymm11, %ymm8, %ymm8 + vpaddq %ymm4, %ymm13, %ymm4 + xorq %r8, %rcx + addq %rbx, %r15 + rorq $28, %rcx + movq %r11, %rax + addq %rcx, %r15 + rorq $23, %rax + vpaddq %ymm4, %ymm8, %ymm4 + movq %r15, %rbx + movq %r12, %rcx + addq 136(%rsp), %r14 + xorq %r13, %rcx + vpsrlq $19, %ymm3, %ymm8 + vpsllq $45, %ymm3, %ymm9 + xorq %r11, %rax + andq %r11, %rcx + rorq $4, %rax + xorq %r13, %rcx + vpsrlq $61, %ymm3, %ymm10 + vpsllq $3, %ymm3, %ymm11 + xorq %r11, %rax + addq %rcx, %r14 + rorq $14, %rax + xorq %r8, %rbx + addq %rax, %r14 + movq %r15, %rcx + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + andq %rbx, %rdx + rorq $5, %rcx + xorq %r15, %rcx + xorq %r8, %rdx + vpxor %ymm10, %ymm8, %ymm8 + vpsrlq $6, %ymm3, %ymm11 + rorq $6, %rcx + addq %r14, %r10 + xorq %r15, %rcx + addq %rdx, %r14 + vpxor %ymm11, %ymm8, %ymm8 + rorq $28, %rcx + movq %r10, %rax + addq %rcx, %r14 + vpaddq %ymm4, %ymm8, %ymm4 + # msg_sched done: 16-19 + # msg_sched: 20-21 + rorq $23, %rax + vpalignr $8, %ymm5, %ymm6, %ymm12 + vpalignr $8, %ymm1, %ymm2, %ymm13 + movq %r14, %rdx + movq %r11, %rcx + addq 160(%rsp), %r13 + xorq %r12, %rcx + vpsrlq $0x01, %ymm12, %ymm8 + vpsllq $63, %ymm12, %ymm9 + xorq %r10, %rax + andq %r10, %rcx + rorq $4, %rax + xorq %r12, %rcx + vpsrlq $8, %ymm12, %ymm10 + vpsllq $56, %ymm12, %ymm11 + xorq %r10, %rax + addq %rcx, %r13 + rorq $14, %rax + xorq %r15, %rdx + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + addq %rax, %r13 + movq %r14, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $7, %ymm12, %ymm11 + vpxor %ymm10, %ymm8, %ymm8 + xorq %r14, %rcx + xorq %r15, %rbx + rorq $6, %rcx + addq %r13, %r9 + vpxor %ymm11, %ymm8, %ymm8 + vpaddq %ymm5, %ymm13, %ymm5 + xorq %r14, %rcx + addq %rbx, %r13 + rorq $28, %rcx + movq %r9, %rax + addq %rcx, %r13 + rorq $23, %rax + vpaddq %ymm5, %ymm8, %ymm5 + movq %r13, %rbx + movq %r10, %rcx + addq 168(%rsp), %r12 + xorq %r11, %rcx + vpsrlq $19, %ymm4, %ymm8 + vpsllq $45, %ymm4, %ymm9 + xorq %r9, %rax + andq %r9, %rcx + rorq $4, %rax + xorq %r11, %rcx + vpsrlq $61, %ymm4, %ymm10 + vpsllq $3, %ymm4, %ymm11 + xorq %r9, %rax + addq %rcx, %r12 + rorq $14, %rax + xorq %r14, %rbx + addq %rax, %r12 + movq %r13, %rcx + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + andq %rbx, %rdx + rorq $5, %rcx + xorq %r13, %rcx + xorq %r14, %rdx + vpxor %ymm10, %ymm8, %ymm8 + vpsrlq $6, %ymm4, %ymm11 + rorq $6, %rcx + addq %r12, %r8 + xorq %r13, %rcx + addq %rdx, %r12 + vpxor %ymm11, %ymm8, %ymm8 + rorq $28, %rcx + movq %r8, %rax + addq %rcx, %r12 + vpaddq %ymm5, %ymm8, %ymm5 + # msg_sched done: 20-23 + # msg_sched: 24-25 + rorq $23, %rax + vpalignr $8, %ymm6, %ymm7, %ymm12 + vpalignr $8, %ymm2, %ymm3, %ymm13 + movq %r12, %rdx + movq %r9, %rcx + addq 192(%rsp), %r11 + xorq %r10, %rcx + vpsrlq $0x01, %ymm12, %ymm8 + vpsllq $63, %ymm12, %ymm9 + xorq %r8, %rax + andq %r8, %rcx + rorq $4, %rax + xorq %r10, %rcx + vpsrlq $8, %ymm12, %ymm10 + vpsllq $56, %ymm12, %ymm11 + xorq %r8, %rax + addq %rcx, %r11 + rorq $14, %rax + xorq %r13, %rdx + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + addq %rax, %r11 + movq %r12, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $7, %ymm12, %ymm11 + vpxor %ymm10, %ymm8, %ymm8 + xorq %r12, %rcx + xorq %r13, %rbx + rorq $6, %rcx + addq %r11, %r15 + vpxor %ymm11, %ymm8, %ymm8 + vpaddq %ymm6, %ymm13, %ymm6 + xorq %r12, %rcx + addq %rbx, %r11 + rorq $28, %rcx + movq %r15, %rax + addq %rcx, %r11 + rorq $23, %rax + vpaddq %ymm6, %ymm8, %ymm6 + movq %r11, %rbx + movq %r8, %rcx + addq 200(%rsp), %r10 + xorq %r9, %rcx + vpsrlq $19, %ymm5, %ymm8 + vpsllq $45, %ymm5, %ymm9 + xorq %r15, %rax + andq %r15, %rcx + rorq $4, %rax + xorq %r9, %rcx + vpsrlq $61, %ymm5, %ymm10 + vpsllq $3, %ymm5, %ymm11 + xorq %r15, %rax + addq %rcx, %r10 + rorq $14, %rax + xorq %r12, %rbx + addq %rax, %r10 + movq %r11, %rcx + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + andq %rbx, %rdx + rorq $5, %rcx + xorq %r11, %rcx + xorq %r12, %rdx + vpxor %ymm10, %ymm8, %ymm8 + vpsrlq $6, %ymm5, %ymm11 + rorq $6, %rcx + addq %r10, %r14 + xorq %r11, %rcx + addq %rdx, %r10 + vpxor %ymm11, %ymm8, %ymm8 + rorq $28, %rcx + movq %r14, %rax + addq %rcx, %r10 + vpaddq %ymm6, %ymm8, %ymm6 + # msg_sched done: 24-27 + # msg_sched: 28-29 + rorq $23, %rax + vpalignr $8, %ymm7, %ymm0, %ymm12 + vpalignr $8, %ymm3, %ymm4, %ymm13 + movq %r10, %rdx + movq %r15, %rcx + addq 224(%rsp), %r9 + xorq %r8, %rcx + vpsrlq $0x01, %ymm12, %ymm8 + vpsllq $63, %ymm12, %ymm9 + xorq %r14, %rax + andq %r14, %rcx + rorq $4, %rax + xorq %r8, %rcx + vpsrlq $8, %ymm12, %ymm10 + vpsllq $56, %ymm12, %ymm11 + xorq %r14, %rax + addq %rcx, %r9 + rorq $14, %rax + xorq %r11, %rdx + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + addq %rax, %r9 + movq %r10, %rcx + andq %rdx, %rbx + rorq $5, %rcx + vpsrlq $7, %ymm12, %ymm11 + vpxor %ymm10, %ymm8, %ymm8 + xorq %r10, %rcx + xorq %r11, %rbx + rorq $6, %rcx + addq %r9, %r13 + vpxor %ymm11, %ymm8, %ymm8 + vpaddq %ymm7, %ymm13, %ymm7 + xorq %r10, %rcx + addq %rbx, %r9 + rorq $28, %rcx + movq %r13, %rax + addq %rcx, %r9 + rorq $23, %rax + vpaddq %ymm7, %ymm8, %ymm7 + movq %r9, %rbx + movq %r14, %rcx + addq 232(%rsp), %r8 + xorq %r15, %rcx + vpsrlq $19, %ymm6, %ymm8 + vpsllq $45, %ymm6, %ymm9 + xorq %r13, %rax + andq %r13, %rcx + rorq $4, %rax + xorq %r15, %rcx + vpsrlq $61, %ymm6, %ymm10 + vpsllq $3, %ymm6, %ymm11 + xorq %r13, %rax + addq %rcx, %r8 + rorq $14, %rax + xorq %r10, %rbx + addq %rax, %r8 + movq %r9, %rcx + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + andq %rbx, %rdx + rorq $5, %rcx + xorq %r9, %rcx + xorq %r10, %rdx + vpxor %ymm10, %ymm8, %ymm8 + vpsrlq $6, %ymm6, %ymm11 + rorq $6, %rcx + addq %r8, %r12 + xorq %r9, %rcx + addq %rdx, %r8 + vpxor %ymm11, %ymm8, %ymm8 + rorq $28, %rcx + movq %r12, %rax + addq %rcx, %r8 + vpaddq %ymm7, %ymm8, %ymm7 + # msg_sched done: 28-31 + addq $0x100, %rsi + addq $0x100, %rsp + cmpq L_avx2_sha512_k_2_end(%rip), %rsi + jne L_sha512_len_avx2_start + vpaddq (%rsi), %ymm0, %ymm8 + vpaddq 32(%rsi), %ymm1, %ymm9 + vmovdqu %ymm8, (%rsp) + vmovdqu %ymm9, 32(%rsp) + vpaddq 64(%rsi), %ymm2, %ymm8 + vpaddq 96(%rsi), %ymm3, %ymm9 + vmovdqu %ymm8, 64(%rsp) + vmovdqu %ymm9, 96(%rsp) + vpaddq 128(%rsi), %ymm4, %ymm8 + vpaddq 160(%rsi), %ymm5, %ymm9 + vmovdqu %ymm8, 128(%rsp) + vmovdqu %ymm9, 160(%rsp) + vpaddq 192(%rsi), %ymm6, %ymm8 + vpaddq 224(%rsi), %ymm7, %ymm9 + vmovdqu %ymm8, 192(%rsp) + vmovdqu %ymm9, 224(%rsp) + rorq $23, %rax + movq %r8, %rdx + movq %r13, %rcx + addq (%rsp), %r15 + xorq %r14, %rcx + xorq %r12, %rax + andq %r12, %rcx + rorq $4, %rax + xorq %r14, %rcx + xorq %r12, %rax + addq %rcx, %r15 + rorq $14, %rax + xorq %r9, %rdx + addq %rax, %r15 + movq %r8, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r8, %rcx + xorq %r9, %rbx + rorq $6, %rcx + addq %r15, %r11 + xorq %r8, %rcx + addq %rbx, %r15 + rorq $28, %rcx + movq %r11, %rax + addq %rcx, %r15 + rorq $23, %rax + movq %r15, %rbx + movq %r12, %rcx + addq 8(%rsp), %r14 + xorq %r13, %rcx + xorq %r11, %rax + andq %r11, %rcx + rorq $4, %rax + xorq %r13, %rcx + xorq %r11, %rax + addq %rcx, %r14 + rorq $14, %rax + xorq %r8, %rbx + addq %rax, %r14 + movq %r15, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r15, %rcx + xorq %r8, %rdx + rorq $6, %rcx + addq %r14, %r10 + xorq %r15, %rcx + addq %rdx, %r14 + rorq $28, %rcx + movq %r10, %rax + addq %rcx, %r14 + rorq $23, %rax + movq %r14, %rdx + movq %r11, %rcx + addq 32(%rsp), %r13 + xorq %r12, %rcx + xorq %r10, %rax + andq %r10, %rcx + rorq $4, %rax + xorq %r12, %rcx + xorq %r10, %rax + addq %rcx, %r13 + rorq $14, %rax + xorq %r15, %rdx + addq %rax, %r13 + movq %r14, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r14, %rcx + xorq %r15, %rbx + rorq $6, %rcx + addq %r13, %r9 + xorq %r14, %rcx + addq %rbx, %r13 + rorq $28, %rcx + movq %r9, %rax + addq %rcx, %r13 + rorq $23, %rax + movq %r13, %rbx + movq %r10, %rcx + addq 40(%rsp), %r12 + xorq %r11, %rcx + xorq %r9, %rax + andq %r9, %rcx + rorq $4, %rax + xorq %r11, %rcx + xorq %r9, %rax + addq %rcx, %r12 + rorq $14, %rax + xorq %r14, %rbx + addq %rax, %r12 + movq %r13, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r13, %rcx + xorq %r14, %rdx + rorq $6, %rcx + addq %r12, %r8 + xorq %r13, %rcx + addq %rdx, %r12 + rorq $28, %rcx + movq %r8, %rax + addq %rcx, %r12 + rorq $23, %rax + movq %r12, %rdx + movq %r9, %rcx + addq 64(%rsp), %r11 + xorq %r10, %rcx + xorq %r8, %rax + andq %r8, %rcx + rorq $4, %rax + xorq %r10, %rcx + xorq %r8, %rax + addq %rcx, %r11 + rorq $14, %rax + xorq %r13, %rdx + addq %rax, %r11 + movq %r12, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r12, %rcx + xorq %r13, %rbx + rorq $6, %rcx + addq %r11, %r15 + xorq %r12, %rcx + addq %rbx, %r11 + rorq $28, %rcx + movq %r15, %rax + addq %rcx, %r11 + rorq $23, %rax + movq %r11, %rbx + movq %r8, %rcx + addq 72(%rsp), %r10 + xorq %r9, %rcx + xorq %r15, %rax + andq %r15, %rcx + rorq $4, %rax + xorq %r9, %rcx + xorq %r15, %rax + addq %rcx, %r10 + rorq $14, %rax + xorq %r12, %rbx + addq %rax, %r10 + movq %r11, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r11, %rcx + xorq %r12, %rdx + rorq $6, %rcx + addq %r10, %r14 + xorq %r11, %rcx + addq %rdx, %r10 + rorq $28, %rcx + movq %r14, %rax + addq %rcx, %r10 + rorq $23, %rax + movq %r10, %rdx + movq %r15, %rcx + addq 96(%rsp), %r9 + xorq %r8, %rcx + xorq %r14, %rax + andq %r14, %rcx + rorq $4, %rax + xorq %r8, %rcx + xorq %r14, %rax + addq %rcx, %r9 + rorq $14, %rax + xorq %r11, %rdx + addq %rax, %r9 + movq %r10, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r10, %rcx + xorq %r11, %rbx + rorq $6, %rcx + addq %r9, %r13 + xorq %r10, %rcx + addq %rbx, %r9 + rorq $28, %rcx + movq %r13, %rax + addq %rcx, %r9 + rorq $23, %rax + movq %r9, %rbx + movq %r14, %rcx + addq 104(%rsp), %r8 + xorq %r15, %rcx + xorq %r13, %rax + andq %r13, %rcx + rorq $4, %rax + xorq %r15, %rcx + xorq %r13, %rax + addq %rcx, %r8 + rorq $14, %rax + xorq %r10, %rbx + addq %rax, %r8 + movq %r9, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r9, %rcx + xorq %r10, %rdx + rorq $6, %rcx + addq %r8, %r12 + xorq %r9, %rcx + addq %rdx, %r8 + rorq $28, %rcx + movq %r12, %rax + addq %rcx, %r8 + rorq $23, %rax + movq %r8, %rdx + movq %r13, %rcx + addq 128(%rsp), %r15 + xorq %r14, %rcx + xorq %r12, %rax + andq %r12, %rcx + rorq $4, %rax + xorq %r14, %rcx + xorq %r12, %rax + addq %rcx, %r15 + rorq $14, %rax + xorq %r9, %rdx + addq %rax, %r15 + movq %r8, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r8, %rcx + xorq %r9, %rbx + rorq $6, %rcx + addq %r15, %r11 + xorq %r8, %rcx + addq %rbx, %r15 + rorq $28, %rcx + movq %r11, %rax + addq %rcx, %r15 + rorq $23, %rax + movq %r15, %rbx + movq %r12, %rcx + addq 136(%rsp), %r14 + xorq %r13, %rcx + xorq %r11, %rax + andq %r11, %rcx + rorq $4, %rax + xorq %r13, %rcx + xorq %r11, %rax + addq %rcx, %r14 + rorq $14, %rax + xorq %r8, %rbx + addq %rax, %r14 + movq %r15, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r15, %rcx + xorq %r8, %rdx + rorq $6, %rcx + addq %r14, %r10 + xorq %r15, %rcx + addq %rdx, %r14 + rorq $28, %rcx + movq %r10, %rax + addq %rcx, %r14 + rorq $23, %rax + movq %r14, %rdx + movq %r11, %rcx + addq 160(%rsp), %r13 + xorq %r12, %rcx + xorq %r10, %rax + andq %r10, %rcx + rorq $4, %rax + xorq %r12, %rcx + xorq %r10, %rax + addq %rcx, %r13 + rorq $14, %rax + xorq %r15, %rdx + addq %rax, %r13 + movq %r14, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r14, %rcx + xorq %r15, %rbx + rorq $6, %rcx + addq %r13, %r9 + xorq %r14, %rcx + addq %rbx, %r13 + rorq $28, %rcx + movq %r9, %rax + addq %rcx, %r13 + rorq $23, %rax + movq %r13, %rbx + movq %r10, %rcx + addq 168(%rsp), %r12 + xorq %r11, %rcx + xorq %r9, %rax + andq %r9, %rcx + rorq $4, %rax + xorq %r11, %rcx + xorq %r9, %rax + addq %rcx, %r12 + rorq $14, %rax + xorq %r14, %rbx + addq %rax, %r12 + movq %r13, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r13, %rcx + xorq %r14, %rdx + rorq $6, %rcx + addq %r12, %r8 + xorq %r13, %rcx + addq %rdx, %r12 + rorq $28, %rcx + movq %r8, %rax + addq %rcx, %r12 + rorq $23, %rax + movq %r12, %rdx + movq %r9, %rcx + addq 192(%rsp), %r11 + xorq %r10, %rcx + xorq %r8, %rax + andq %r8, %rcx + rorq $4, %rax + xorq %r10, %rcx + xorq %r8, %rax + addq %rcx, %r11 + rorq $14, %rax + xorq %r13, %rdx + addq %rax, %r11 + movq %r12, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r12, %rcx + xorq %r13, %rbx + rorq $6, %rcx + addq %r11, %r15 + xorq %r12, %rcx + addq %rbx, %r11 + rorq $28, %rcx + movq %r15, %rax + addq %rcx, %r11 + rorq $23, %rax + movq %r11, %rbx + movq %r8, %rcx + addq 200(%rsp), %r10 + xorq %r9, %rcx + xorq %r15, %rax + andq %r15, %rcx + rorq $4, %rax + xorq %r9, %rcx + xorq %r15, %rax + addq %rcx, %r10 + rorq $14, %rax + xorq %r12, %rbx + addq %rax, %r10 + movq %r11, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r11, %rcx + xorq %r12, %rdx + rorq $6, %rcx + addq %r10, %r14 + xorq %r11, %rcx + addq %rdx, %r10 + rorq $28, %rcx + movq %r14, %rax + addq %rcx, %r10 + rorq $23, %rax + movq %r10, %rdx + movq %r15, %rcx + addq 224(%rsp), %r9 + xorq %r8, %rcx + xorq %r14, %rax + andq %r14, %rcx + rorq $4, %rax + xorq %r8, %rcx + xorq %r14, %rax + addq %rcx, %r9 + rorq $14, %rax + xorq %r11, %rdx + addq %rax, %r9 + movq %r10, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r10, %rcx + xorq %r11, %rbx + rorq $6, %rcx + addq %r9, %r13 + xorq %r10, %rcx + addq %rbx, %r9 + rorq $28, %rcx + movq %r13, %rax + addq %rcx, %r9 + rorq $23, %rax + movq %r9, %rbx + movq %r14, %rcx + addq 232(%rsp), %r8 + xorq %r15, %rcx + xorq %r13, %rax + andq %r13, %rcx + rorq $4, %rax + xorq %r15, %rcx + xorq %r13, %rax + addq %rcx, %r8 + rorq $14, %rax + xorq %r10, %rbx + addq %rax, %r8 + movq %r9, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r9, %rcx + xorq %r10, %rdx + rorq $6, %rcx + addq %r8, %r12 + xorq %r9, %rcx + addq %rdx, %r8 + rorq $28, %rcx + movq %r12, %rax + addq %rcx, %r8 + subq $0x400, %rsp + addq (%rdi), %r8 + addq 8(%rdi), %r9 + addq 16(%rdi), %r10 + addq 24(%rdi), %r11 + addq 32(%rdi), %r12 + addq 40(%rdi), %r13 + addq 48(%rdi), %r14 + addq 56(%rdi), %r15 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq %r12, 32(%rdi) + movq %r13, 40(%rdi) + movq %r14, 48(%rdi) + movq %r15, 56(%rdi) + movq %r9, %rbx + movq %r12, %rax + xorq %r10, %rbx + movq $5, %rsi +L_sha512_len_avx2_tail: + rorq $23, %rax + movq %r8, %rdx + movq %r13, %rcx + addq 16(%rsp), %r15 + xorq %r14, %rcx + xorq %r12, %rax + andq %r12, %rcx + rorq $4, %rax + xorq %r14, %rcx + xorq %r12, %rax + addq %rcx, %r15 + rorq $14, %rax + xorq %r9, %rdx + addq %rax, %r15 + movq %r8, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r8, %rcx + xorq %r9, %rbx + rorq $6, %rcx + addq %r15, %r11 + xorq %r8, %rcx + addq %rbx, %r15 + rorq $28, %rcx + movq %r11, %rax + addq %rcx, %r15 + rorq $23, %rax + movq %r15, %rbx + movq %r12, %rcx + addq 24(%rsp), %r14 + xorq %r13, %rcx + xorq %r11, %rax + andq %r11, %rcx + rorq $4, %rax + xorq %r13, %rcx + xorq %r11, %rax + addq %rcx, %r14 + rorq $14, %rax + xorq %r8, %rbx + addq %rax, %r14 + movq %r15, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r15, %rcx + xorq %r8, %rdx + rorq $6, %rcx + addq %r14, %r10 + xorq %r15, %rcx + addq %rdx, %r14 + rorq $28, %rcx + movq %r10, %rax + addq %rcx, %r14 + rorq $23, %rax + movq %r14, %rdx + movq %r11, %rcx + addq 48(%rsp), %r13 + xorq %r12, %rcx + xorq %r10, %rax + andq %r10, %rcx + rorq $4, %rax + xorq %r12, %rcx + xorq %r10, %rax + addq %rcx, %r13 + rorq $14, %rax + xorq %r15, %rdx + addq %rax, %r13 + movq %r14, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r14, %rcx + xorq %r15, %rbx + rorq $6, %rcx + addq %r13, %r9 + xorq %r14, %rcx + addq %rbx, %r13 + rorq $28, %rcx + movq %r9, %rax + addq %rcx, %r13 + rorq $23, %rax + movq %r13, %rbx + movq %r10, %rcx + addq 56(%rsp), %r12 + xorq %r11, %rcx + xorq %r9, %rax + andq %r9, %rcx + rorq $4, %rax + xorq %r11, %rcx + xorq %r9, %rax + addq %rcx, %r12 + rorq $14, %rax + xorq %r14, %rbx + addq %rax, %r12 + movq %r13, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r13, %rcx + xorq %r14, %rdx + rorq $6, %rcx + addq %r12, %r8 + xorq %r13, %rcx + addq %rdx, %r12 + rorq $28, %rcx + movq %r8, %rax + addq %rcx, %r12 + rorq $23, %rax + movq %r12, %rdx + movq %r9, %rcx + addq 80(%rsp), %r11 + xorq %r10, %rcx + xorq %r8, %rax + andq %r8, %rcx + rorq $4, %rax + xorq %r10, %rcx + xorq %r8, %rax + addq %rcx, %r11 + rorq $14, %rax + xorq %r13, %rdx + addq %rax, %r11 + movq %r12, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r12, %rcx + xorq %r13, %rbx + rorq $6, %rcx + addq %r11, %r15 + xorq %r12, %rcx + addq %rbx, %r11 + rorq $28, %rcx + movq %r15, %rax + addq %rcx, %r11 + rorq $23, %rax + movq %r11, %rbx + movq %r8, %rcx + addq 88(%rsp), %r10 + xorq %r9, %rcx + xorq %r15, %rax + andq %r15, %rcx + rorq $4, %rax + xorq %r9, %rcx + xorq %r15, %rax + addq %rcx, %r10 + rorq $14, %rax + xorq %r12, %rbx + addq %rax, %r10 + movq %r11, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r11, %rcx + xorq %r12, %rdx + rorq $6, %rcx + addq %r10, %r14 + xorq %r11, %rcx + addq %rdx, %r10 + rorq $28, %rcx + movq %r14, %rax + addq %rcx, %r10 + rorq $23, %rax + movq %r10, %rdx + movq %r15, %rcx + addq 112(%rsp), %r9 + xorq %r8, %rcx + xorq %r14, %rax + andq %r14, %rcx + rorq $4, %rax + xorq %r8, %rcx + xorq %r14, %rax + addq %rcx, %r9 + rorq $14, %rax + xorq %r11, %rdx + addq %rax, %r9 + movq %r10, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r10, %rcx + xorq %r11, %rbx + rorq $6, %rcx + addq %r9, %r13 + xorq %r10, %rcx + addq %rbx, %r9 + rorq $28, %rcx + movq %r13, %rax + addq %rcx, %r9 + rorq $23, %rax + movq %r9, %rbx + movq %r14, %rcx + addq 120(%rsp), %r8 + xorq %r15, %rcx + xorq %r13, %rax + andq %r13, %rcx + rorq $4, %rax + xorq %r15, %rcx + xorq %r13, %rax + addq %rcx, %r8 + rorq $14, %rax + xorq %r10, %rbx + addq %rax, %r8 + movq %r9, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r9, %rcx + xorq %r10, %rdx + rorq $6, %rcx + addq %r8, %r12 + xorq %r9, %rcx + addq %rdx, %r8 + rorq $28, %rcx + movq %r12, %rax + addq %rcx, %r8 + rorq $23, %rax + movq %r8, %rdx + movq %r13, %rcx + addq 144(%rsp), %r15 + xorq %r14, %rcx + xorq %r12, %rax + andq %r12, %rcx + rorq $4, %rax + xorq %r14, %rcx + xorq %r12, %rax + addq %rcx, %r15 + rorq $14, %rax + xorq %r9, %rdx + addq %rax, %r15 + movq %r8, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r8, %rcx + xorq %r9, %rbx + rorq $6, %rcx + addq %r15, %r11 + xorq %r8, %rcx + addq %rbx, %r15 + rorq $28, %rcx + movq %r11, %rax + addq %rcx, %r15 + rorq $23, %rax + movq %r15, %rbx + movq %r12, %rcx + addq 152(%rsp), %r14 + xorq %r13, %rcx + xorq %r11, %rax + andq %r11, %rcx + rorq $4, %rax + xorq %r13, %rcx + xorq %r11, %rax + addq %rcx, %r14 + rorq $14, %rax + xorq %r8, %rbx + addq %rax, %r14 + movq %r15, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r15, %rcx + xorq %r8, %rdx + rorq $6, %rcx + addq %r14, %r10 + xorq %r15, %rcx + addq %rdx, %r14 + rorq $28, %rcx + movq %r10, %rax + addq %rcx, %r14 + rorq $23, %rax + movq %r14, %rdx + movq %r11, %rcx + addq 176(%rsp), %r13 + xorq %r12, %rcx + xorq %r10, %rax + andq %r10, %rcx + rorq $4, %rax + xorq %r12, %rcx + xorq %r10, %rax + addq %rcx, %r13 + rorq $14, %rax + xorq %r15, %rdx + addq %rax, %r13 + movq %r14, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r14, %rcx + xorq %r15, %rbx + rorq $6, %rcx + addq %r13, %r9 + xorq %r14, %rcx + addq %rbx, %r13 + rorq $28, %rcx + movq %r9, %rax + addq %rcx, %r13 + rorq $23, %rax + movq %r13, %rbx + movq %r10, %rcx + addq 184(%rsp), %r12 + xorq %r11, %rcx + xorq %r9, %rax + andq %r9, %rcx + rorq $4, %rax + xorq %r11, %rcx + xorq %r9, %rax + addq %rcx, %r12 + rorq $14, %rax + xorq %r14, %rbx + addq %rax, %r12 + movq %r13, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r13, %rcx + xorq %r14, %rdx + rorq $6, %rcx + addq %r12, %r8 + xorq %r13, %rcx + addq %rdx, %r12 + rorq $28, %rcx + movq %r8, %rax + addq %rcx, %r12 + rorq $23, %rax + movq %r12, %rdx + movq %r9, %rcx + addq 208(%rsp), %r11 + xorq %r10, %rcx + xorq %r8, %rax + andq %r8, %rcx + rorq $4, %rax + xorq %r10, %rcx + xorq %r8, %rax + addq %rcx, %r11 + rorq $14, %rax + xorq %r13, %rdx + addq %rax, %r11 + movq %r12, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r12, %rcx + xorq %r13, %rbx + rorq $6, %rcx + addq %r11, %r15 + xorq %r12, %rcx + addq %rbx, %r11 + rorq $28, %rcx + movq %r15, %rax + addq %rcx, %r11 + rorq $23, %rax + movq %r11, %rbx + movq %r8, %rcx + addq 216(%rsp), %r10 + xorq %r9, %rcx + xorq %r15, %rax + andq %r15, %rcx + rorq $4, %rax + xorq %r9, %rcx + xorq %r15, %rax + addq %rcx, %r10 + rorq $14, %rax + xorq %r12, %rbx + addq %rax, %r10 + movq %r11, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r11, %rcx + xorq %r12, %rdx + rorq $6, %rcx + addq %r10, %r14 + xorq %r11, %rcx + addq %rdx, %r10 + rorq $28, %rcx + movq %r14, %rax + addq %rcx, %r10 + rorq $23, %rax + movq %r10, %rdx + movq %r15, %rcx + addq 240(%rsp), %r9 + xorq %r8, %rcx + xorq %r14, %rax + andq %r14, %rcx + rorq $4, %rax + xorq %r8, %rcx + xorq %r14, %rax + addq %rcx, %r9 + rorq $14, %rax + xorq %r11, %rdx + addq %rax, %r9 + movq %r10, %rcx + andq %rdx, %rbx + rorq $5, %rcx + xorq %r10, %rcx + xorq %r11, %rbx + rorq $6, %rcx + addq %r9, %r13 + xorq %r10, %rcx + addq %rbx, %r9 + rorq $28, %rcx + movq %r13, %rax + addq %rcx, %r9 + rorq $23, %rax + movq %r9, %rbx + movq %r14, %rcx + addq 248(%rsp), %r8 + xorq %r15, %rcx + xorq %r13, %rax + andq %r13, %rcx + rorq $4, %rax + xorq %r15, %rcx + xorq %r13, %rax + addq %rcx, %r8 + rorq $14, %rax + xorq %r10, %rbx + addq %rax, %r8 + movq %r9, %rcx + andq %rbx, %rdx + rorq $5, %rcx + xorq %r9, %rcx + xorq %r10, %rdx + rorq $6, %rcx + addq %r8, %r12 + xorq %r9, %rcx + addq %rdx, %r8 + rorq $28, %rcx + movq %r12, %rax + addq %rcx, %r8 + addq $0x100, %rsp + subq $0x01, %rsi + jnz L_sha512_len_avx2_tail + addq (%rdi), %r8 + addq 8(%rdi), %r9 + addq 16(%rdi), %r10 + addq 24(%rdi), %r11 + addq 32(%rdi), %r12 + addq 40(%rdi), %r13 + addq 48(%rdi), %r14 + addq 56(%rdi), %r15 + movq 224(%rdi), %rcx + addq $0x40, %rsp + addq $0x100, %rcx + subl $0x100, %ebp + movq %rcx, 224(%rdi) + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq %r12, 32(%rdi) + movq %r13, 40(%rdi) + movq %r14, 48(%rdi) + movq %r15, 56(%rdi) + jnz L_sha512_len_avx2_begin +L_sha512_len_avx2_done: + xorq %rax, %rax + vzeroupper + popq %rbp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size Transform_Sha512_AVX2_Len,.-Transform_Sha512_AVX2_Len +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx2_rorx_sha512_k: +.quad 0x428a2f98d728ae22,0x7137449123ef65cd +.quad 0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc +.quad 0x3956c25bf348b538,0x59f111f1b605d019 +.quad 0x923f82a4af194f9b,0xab1c5ed5da6d8118 +.quad 0xd807aa98a3030242,0x12835b0145706fbe +.quad 0x243185be4ee4b28c,0x550c7dc3d5ffb4e2 +.quad 0x72be5d74f27b896f,0x80deb1fe3b1696b1 +.quad 0x9bdc06a725c71235,0xc19bf174cf692694 +.quad 0xe49b69c19ef14ad2,0xefbe4786384f25e3 +.quad 0xfc19dc68b8cd5b5,0x240ca1cc77ac9c65 +.quad 0x2de92c6f592b0275,0x4a7484aa6ea6e483 +.quad 0x5cb0a9dcbd41fbd4,0x76f988da831153b5 +.quad 0x983e5152ee66dfab,0xa831c66d2db43210 +.quad 0xb00327c898fb213f,0xbf597fc7beef0ee4 +.quad 0xc6e00bf33da88fc2,0xd5a79147930aa725 +.quad 0x6ca6351e003826f,0x142929670a0e6e70 +.quad 0x27b70a8546d22ffc,0x2e1b21385c26c926 +.quad 0x4d2c6dfc5ac42aed,0x53380d139d95b3df +.quad 0x650a73548baf63de,0x766a0abb3c77b2a8 +.quad 0x81c2c92e47edaee6,0x92722c851482353b +.quad 0xa2bfe8a14cf10364,0xa81a664bbc423001 +.quad 0xc24b8b70d0f89791,0xc76c51a30654be30 +.quad 0xd192e819d6ef5218,0xd69906245565a910 +.quad 0xf40e35855771202a,0x106aa07032bbd1b8 +.quad 0x19a4c116b8d2d0c8,0x1e376c085141ab53 +.quad 0x2748774cdf8eeb99,0x34b0bcb5e19b48a8 +.quad 0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb +.quad 0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3 +.quad 0x748f82ee5defb2fc,0x78a5636f43172f60 +.quad 0x84c87814a1f0ab72,0x8cc702081a6439ec +.quad 0x90befffa23631e28,0xa4506cebde82bde9 +.quad 0xbef9a3f7b2c67915,0xc67178f2e372532b +.quad 0xca273eceea26619c,0xd186b8c721c0c207 +.quad 0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178 +.quad 0x6f067aa72176fba,0xa637dc5a2c898a6 +.quad 0x113f9804bef90dae,0x1b710b35131c471b +.quad 0x28db77f523047d84,0x32caab7b40c72493 +.quad 0x3c9ebe0a15c9bebc,0x431d67c49c100d4c +.quad 0x4cc5d4becb3e42b6,0x597f299cfc657e2a +.quad 0x5fcb6fab3ad6faec,0x6c44198c4a475817 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 16 +#else +.p2align 4 +#endif /* __APPLE__ */ +L_avx2_rorx_sha512_k_2: +.quad 0x428a2f98d728ae22,0x7137449123ef65cd +.quad 0x428a2f98d728ae22,0x7137449123ef65cd +.quad 0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc +.quad 0xb5c0fbcfec4d3b2f,0xe9b5dba58189dbbc +.quad 0x3956c25bf348b538,0x59f111f1b605d019 +.quad 0x3956c25bf348b538,0x59f111f1b605d019 +.quad 0x923f82a4af194f9b,0xab1c5ed5da6d8118 +.quad 0x923f82a4af194f9b,0xab1c5ed5da6d8118 +.quad 0xd807aa98a3030242,0x12835b0145706fbe +.quad 0xd807aa98a3030242,0x12835b0145706fbe +.quad 0x243185be4ee4b28c,0x550c7dc3d5ffb4e2 +.quad 0x243185be4ee4b28c,0x550c7dc3d5ffb4e2 +.quad 0x72be5d74f27b896f,0x80deb1fe3b1696b1 +.quad 0x72be5d74f27b896f,0x80deb1fe3b1696b1 +.quad 0x9bdc06a725c71235,0xc19bf174cf692694 +.quad 0x9bdc06a725c71235,0xc19bf174cf692694 +.quad 0xe49b69c19ef14ad2,0xefbe4786384f25e3 +.quad 0xe49b69c19ef14ad2,0xefbe4786384f25e3 +.quad 0xfc19dc68b8cd5b5,0x240ca1cc77ac9c65 +.quad 0xfc19dc68b8cd5b5,0x240ca1cc77ac9c65 +.quad 0x2de92c6f592b0275,0x4a7484aa6ea6e483 +.quad 0x2de92c6f592b0275,0x4a7484aa6ea6e483 +.quad 0x5cb0a9dcbd41fbd4,0x76f988da831153b5 +.quad 0x5cb0a9dcbd41fbd4,0x76f988da831153b5 +.quad 0x983e5152ee66dfab,0xa831c66d2db43210 +.quad 0x983e5152ee66dfab,0xa831c66d2db43210 +.quad 0xb00327c898fb213f,0xbf597fc7beef0ee4 +.quad 0xb00327c898fb213f,0xbf597fc7beef0ee4 +.quad 0xc6e00bf33da88fc2,0xd5a79147930aa725 +.quad 0xc6e00bf33da88fc2,0xd5a79147930aa725 +.quad 0x6ca6351e003826f,0x142929670a0e6e70 +.quad 0x6ca6351e003826f,0x142929670a0e6e70 +.quad 0x27b70a8546d22ffc,0x2e1b21385c26c926 +.quad 0x27b70a8546d22ffc,0x2e1b21385c26c926 +.quad 0x4d2c6dfc5ac42aed,0x53380d139d95b3df +.quad 0x4d2c6dfc5ac42aed,0x53380d139d95b3df +.quad 0x650a73548baf63de,0x766a0abb3c77b2a8 +.quad 0x650a73548baf63de,0x766a0abb3c77b2a8 +.quad 0x81c2c92e47edaee6,0x92722c851482353b +.quad 0x81c2c92e47edaee6,0x92722c851482353b +.quad 0xa2bfe8a14cf10364,0xa81a664bbc423001 +.quad 0xa2bfe8a14cf10364,0xa81a664bbc423001 +.quad 0xc24b8b70d0f89791,0xc76c51a30654be30 +.quad 0xc24b8b70d0f89791,0xc76c51a30654be30 +.quad 0xd192e819d6ef5218,0xd69906245565a910 +.quad 0xd192e819d6ef5218,0xd69906245565a910 +.quad 0xf40e35855771202a,0x106aa07032bbd1b8 +.quad 0xf40e35855771202a,0x106aa07032bbd1b8 +.quad 0x19a4c116b8d2d0c8,0x1e376c085141ab53 +.quad 0x19a4c116b8d2d0c8,0x1e376c085141ab53 +.quad 0x2748774cdf8eeb99,0x34b0bcb5e19b48a8 +.quad 0x2748774cdf8eeb99,0x34b0bcb5e19b48a8 +.quad 0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb +.quad 0x391c0cb3c5c95a63,0x4ed8aa4ae3418acb +.quad 0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3 +.quad 0x5b9cca4f7763e373,0x682e6ff3d6b2b8a3 +.quad 0x748f82ee5defb2fc,0x78a5636f43172f60 +.quad 0x748f82ee5defb2fc,0x78a5636f43172f60 +.quad 0x84c87814a1f0ab72,0x8cc702081a6439ec +.quad 0x84c87814a1f0ab72,0x8cc702081a6439ec +.quad 0x90befffa23631e28,0xa4506cebde82bde9 +.quad 0x90befffa23631e28,0xa4506cebde82bde9 +.quad 0xbef9a3f7b2c67915,0xc67178f2e372532b +.quad 0xbef9a3f7b2c67915,0xc67178f2e372532b +.quad 0xca273eceea26619c,0xd186b8c721c0c207 +.quad 0xca273eceea26619c,0xd186b8c721c0c207 +.quad 0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178 +.quad 0xeada7dd6cde0eb1e,0xf57d4f7fee6ed178 +.quad 0x6f067aa72176fba,0xa637dc5a2c898a6 +.quad 0x6f067aa72176fba,0xa637dc5a2c898a6 +.quad 0x113f9804bef90dae,0x1b710b35131c471b +.quad 0x113f9804bef90dae,0x1b710b35131c471b +.quad 0x28db77f523047d84,0x32caab7b40c72493 +.quad 0x28db77f523047d84,0x32caab7b40c72493 +.quad 0x3c9ebe0a15c9bebc,0x431d67c49c100d4c +.quad 0x3c9ebe0a15c9bebc,0x431d67c49c100d4c +.quad 0x4cc5d4becb3e42b6,0x597f299cfc657e2a +.quad 0x4cc5d4becb3e42b6,0x597f299cfc657e2a +.quad 0x5fcb6fab3ad6faec,0x6c44198c4a475817 +.quad 0x5fcb6fab3ad6faec,0x6c44198c4a475817 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 8 +#else +.p2align 3 +#endif /* __APPLE__ */ +L_avx2_rorx_sha512_k_2_end: +.quad 1024+L_avx2_rorx_sha512_k_2 +#ifndef __APPLE__ +.data +#else +.section __DATA,__data +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.align 32 +#else +.p2align 5 +#endif /* __APPLE__ */ +L_avx2_rorx_sha512_flip_mask: +.quad 0x1020304050607, 0x8090a0b0c0d0e0f +.quad 0x1020304050607, 0x8090a0b0c0d0e0f +#ifndef __APPLE__ +.text +.globl Transform_Sha512_AVX2_RORX +.type Transform_Sha512_AVX2_RORX,@function +.align 4 +Transform_Sha512_AVX2_RORX: +#else +.section __TEXT,__text +.globl _Transform_Sha512_AVX2_RORX +.p2align 2 +_Transform_Sha512_AVX2_RORX: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + subq $0x88, %rsp + leaq 64(%rdi), %rcx + vmovdqa L_avx2_rorx_sha512_flip_mask(%rip), %ymm15 + movq (%rdi), %r8 + movq 8(%rdi), %r9 + movq 16(%rdi), %r10 + movq 24(%rdi), %r11 + movq 32(%rdi), %r12 + movq 40(%rdi), %r13 + movq 48(%rdi), %r14 + movq 56(%rdi), %r15 + vmovdqu (%rcx), %ymm0 + vmovdqu 32(%rcx), %ymm1 + vpshufb %ymm15, %ymm0, %ymm0 + vpshufb %ymm15, %ymm1, %ymm1 + vmovdqu 64(%rcx), %ymm2 + vmovdqu 96(%rcx), %ymm3 + vpshufb %ymm15, %ymm2, %ymm2 + vpshufb %ymm15, %ymm3, %ymm3 + movl $4, 128(%rsp) + leaq L_avx2_rorx_sha512_k(%rip), %rsi + movq %r9, %rbx + xorq %rdx, %rdx + xorq %r10, %rbx + # set_w_k: 0 + vpaddq (%rsi), %ymm0, %ymm8 + vpaddq 32(%rsi), %ymm1, %ymm9 + vmovdqu %ymm8, (%rsp) + vmovdqu %ymm9, 32(%rsp) + vpaddq 64(%rsi), %ymm2, %ymm8 + vpaddq 96(%rsi), %ymm3, %ymm9 + vmovdqu %ymm8, 64(%rsp) + vmovdqu %ymm9, 96(%rsp) + # Start of 16 rounds +L_sha256_len_avx2_rorx_start: + addq $0x80, %rsi + rorxq $14, %r12, %rax + rorxq $18, %r12, %rcx + addq %rdx, %r8 + vpblendd $3, %ymm1, %ymm0, %ymm12 + vpblendd $3, %ymm3, %ymm2, %ymm13 + addq (%rsp), %r15 + movq %r13, %rdx + xorq %rax, %rcx + vpermq $57, %ymm12, %ymm12 + xorq %r14, %rdx + rorxq $41, %r12, %rax + xorq %rcx, %rax + vpermq $57, %ymm13, %ymm13 + andq %r12, %rdx + addq %rax, %r15 + rorxq $28, %r8, %rax + vpsrlq $0x01, %ymm12, %ymm8 + vpsllq $63, %ymm12, %ymm9 + rorxq $34, %r8, %rcx + xorq %r14, %rdx + xorq %rax, %rcx + vpsrlq $8, %ymm12, %ymm10 + vpsllq $56, %ymm12, %ymm11 + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + rorxq $39, %r8, %rax + addq %rdx, %r15 + xorq %rcx, %rax + vpsrlq $7, %ymm12, %ymm11 + movq %r9, %rdx + addq %r15, %r11 + xorq %r8, %rdx + vperm2I128 $0x81, %ymm3, %ymm3, %ymm14 + andq %rdx, %rbx + addq %rax, %r15 + xorq %r9, %rbx + rorxq $14, %r11, %rax + rorxq $18, %r11, %rcx + addq %rbx, %r15 + vpxor %ymm10, %ymm8, %ymm8 + addq 8(%rsp), %r14 + movq %r12, %rbx + xorq %rax, %rcx + vpxor %ymm11, %ymm8, %ymm8 + xorq %r13, %rbx + rorxq $41, %r11, %rax + xorq %rcx, %rax + vpaddq %ymm0, %ymm13, %ymm0 + vpaddq %ymm0, %ymm8, %ymm0 + andq %r11, %rbx + addq %rax, %r14 + rorxq $28, %r15, %rax + vpsrlq $19, %ymm14, %ymm8 + vpsllq $45, %ymm14, %ymm9 + rorxq $34, %r15, %rcx + xorq %r13, %rbx + xorq %rax, %rcx + vpsrlq $61, %ymm14, %ymm10 + vpsllq $3, %ymm14, %ymm11 + vpor %ymm9, %ymm8, %ymm8 + rorxq $39, %r15, %rax + addq %rbx, %r14 + xorq %rcx, %rax + vpor %ymm11, %ymm10, %ymm10 + movq %r8, %rbx + leaq (%r10,%r14,1), %r10 + xorq %r15, %rbx + vpxor %ymm10, %ymm8, %ymm8 + andq %rbx, %rdx + addq %rax, %r14 + xorq %r8, %rdx + vpsrlq $6, %ymm14, %ymm11 + rorxq $14, %r10, %rax + rorxq $18, %r10, %rcx + addq %rdx, %r14 + vpxor %ymm11, %ymm8, %ymm8 + addq 16(%rsp), %r13 + movq %r11, %rdx + xorq %rax, %rcx + vpaddq %ymm0, %ymm8, %ymm0 + xorq %r12, %rdx + rorxq $41, %r10, %rax + xorq %rcx, %rax + vperm2I128 $8, %ymm0, %ymm0, %ymm14 + andq %r10, %rdx + addq %rax, %r13 + rorxq $28, %r14, %rax + rorxq $34, %r14, %rcx + xorq %r12, %rdx + xorq %rax, %rcx + vpsrlq $19, %ymm14, %ymm8 + vpsllq $45, %ymm14, %ymm9 + rorxq $39, %r14, %rax + addq %rdx, %r13 + xorq %rcx, %rax + vpsrlq $61, %ymm14, %ymm10 + vpsllq $3, %ymm14, %ymm11 + vpor %ymm9, %ymm8, %ymm8 + movq %r15, %rdx + addq %r13, %r9 + xorq %r14, %rdx + vpor %ymm11, %ymm10, %ymm10 + andq %rdx, %rbx + addq %rax, %r13 + xorq %r15, %rbx + vpxor %ymm10, %ymm8, %ymm8 + rorxq $14, %r9, %rax + rorxq $18, %r9, %rcx + addq %rbx, %r13 + vpsrlq $6, %ymm14, %ymm11 + addq 24(%rsp), %r12 + movq %r10, %rbx + xorq %rax, %rcx + xorq %r11, %rbx + rorxq $41, %r9, %rax + xorq %rcx, %rax + vpxor %ymm11, %ymm8, %ymm8 + andq %r9, %rbx + addq %rax, %r12 + rorxq $28, %r13, %rax + rorxq $34, %r13, %rcx + xorq %r11, %rbx + xorq %rax, %rcx + vpaddq %ymm0, %ymm8, %ymm0 + rorxq $39, %r13, %rax + addq %rbx, %r12 + xorq %rcx, %rax + vpaddq (%rsi), %ymm0, %ymm8 + movq %r14, %rbx + leaq (%r8,%r12,1), %r8 + xorq %r13, %rbx + andq %rbx, %rdx + addq %rax, %r12 + xorq %r14, %rdx + vmovdqu %ymm8, (%rsp) + rorxq $14, %r8, %rax + rorxq $18, %r8, %rcx + addq %rdx, %r12 + vpblendd $3, %ymm2, %ymm1, %ymm12 + vpblendd $3, %ymm0, %ymm3, %ymm13 + addq 32(%rsp), %r11 + movq %r9, %rdx + xorq %rax, %rcx + vpermq $57, %ymm12, %ymm12 + xorq %r10, %rdx + rorxq $41, %r8, %rax + xorq %rcx, %rax + vpermq $57, %ymm13, %ymm13 + andq %r8, %rdx + addq %rax, %r11 + rorxq $28, %r12, %rax + vpsrlq $0x01, %ymm12, %ymm8 + vpsllq $63, %ymm12, %ymm9 + rorxq $34, %r12, %rcx + xorq %r10, %rdx + xorq %rax, %rcx + vpsrlq $8, %ymm12, %ymm10 + vpsllq $56, %ymm12, %ymm11 + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + rorxq $39, %r12, %rax + addq %rdx, %r11 + xorq %rcx, %rax + vpsrlq $7, %ymm12, %ymm11 + movq %r13, %rdx + addq %r11, %r15 + xorq %r12, %rdx + vperm2I128 $0x81, %ymm0, %ymm0, %ymm14 + andq %rdx, %rbx + addq %rax, %r11 + xorq %r13, %rbx + rorxq $14, %r15, %rax + rorxq $18, %r15, %rcx + addq %rbx, %r11 + vpxor %ymm10, %ymm8, %ymm8 + addq 40(%rsp), %r10 + movq %r8, %rbx + xorq %rax, %rcx + vpxor %ymm11, %ymm8, %ymm8 + xorq %r9, %rbx + rorxq $41, %r15, %rax + xorq %rcx, %rax + vpaddq %ymm1, %ymm13, %ymm1 + vpaddq %ymm1, %ymm8, %ymm1 + andq %r15, %rbx + addq %rax, %r10 + rorxq $28, %r11, %rax + vpsrlq $19, %ymm14, %ymm8 + vpsllq $45, %ymm14, %ymm9 + rorxq $34, %r11, %rcx + xorq %r9, %rbx + xorq %rax, %rcx + vpsrlq $61, %ymm14, %ymm10 + vpsllq $3, %ymm14, %ymm11 + vpor %ymm9, %ymm8, %ymm8 + rorxq $39, %r11, %rax + addq %rbx, %r10 + xorq %rcx, %rax + vpor %ymm11, %ymm10, %ymm10 + movq %r12, %rbx + leaq (%r14,%r10,1), %r14 + xorq %r11, %rbx + vpxor %ymm10, %ymm8, %ymm8 + andq %rbx, %rdx + addq %rax, %r10 + xorq %r12, %rdx + vpsrlq $6, %ymm14, %ymm11 + rorxq $14, %r14, %rax + rorxq $18, %r14, %rcx + addq %rdx, %r10 + vpxor %ymm11, %ymm8, %ymm8 + addq 48(%rsp), %r9 + movq %r15, %rdx + xorq %rax, %rcx + vpaddq %ymm1, %ymm8, %ymm1 + xorq %r8, %rdx + rorxq $41, %r14, %rax + xorq %rcx, %rax + vperm2I128 $8, %ymm1, %ymm1, %ymm14 + andq %r14, %rdx + addq %rax, %r9 + rorxq $28, %r10, %rax + rorxq $34, %r10, %rcx + xorq %r8, %rdx + xorq %rax, %rcx + vpsrlq $19, %ymm14, %ymm8 + vpsllq $45, %ymm14, %ymm9 + rorxq $39, %r10, %rax + addq %rdx, %r9 + xorq %rcx, %rax + vpsrlq $61, %ymm14, %ymm10 + vpsllq $3, %ymm14, %ymm11 + vpor %ymm9, %ymm8, %ymm8 + movq %r11, %rdx + addq %r9, %r13 + xorq %r10, %rdx + vpor %ymm11, %ymm10, %ymm10 + andq %rdx, %rbx + addq %rax, %r9 + xorq %r11, %rbx + vpxor %ymm10, %ymm8, %ymm8 + rorxq $14, %r13, %rax + rorxq $18, %r13, %rcx + addq %rbx, %r9 + vpsrlq $6, %ymm14, %ymm11 + addq 56(%rsp), %r8 + movq %r14, %rbx + xorq %rax, %rcx + xorq %r15, %rbx + rorxq $41, %r13, %rax + xorq %rcx, %rax + vpxor %ymm11, %ymm8, %ymm8 + andq %r13, %rbx + addq %rax, %r8 + rorxq $28, %r9, %rax + rorxq $34, %r9, %rcx + xorq %r15, %rbx + xorq %rax, %rcx + vpaddq %ymm1, %ymm8, %ymm1 + rorxq $39, %r9, %rax + addq %rbx, %r8 + xorq %rcx, %rax + vpaddq 32(%rsi), %ymm1, %ymm8 + movq %r10, %rbx + leaq (%r12,%r8,1), %r12 + xorq %r9, %rbx + andq %rbx, %rdx + addq %rax, %r8 + xorq %r10, %rdx + vmovdqu %ymm8, 32(%rsp) + rorxq $14, %r12, %rax + rorxq $18, %r12, %rcx + addq %rdx, %r8 + vpblendd $3, %ymm3, %ymm2, %ymm12 + vpblendd $3, %ymm1, %ymm0, %ymm13 + addq 64(%rsp), %r15 + movq %r13, %rdx + xorq %rax, %rcx + vpermq $57, %ymm12, %ymm12 + xorq %r14, %rdx + rorxq $41, %r12, %rax + xorq %rcx, %rax + vpermq $57, %ymm13, %ymm13 + andq %r12, %rdx + addq %rax, %r15 + rorxq $28, %r8, %rax + vpsrlq $0x01, %ymm12, %ymm8 + vpsllq $63, %ymm12, %ymm9 + rorxq $34, %r8, %rcx + xorq %r14, %rdx + xorq %rax, %rcx + vpsrlq $8, %ymm12, %ymm10 + vpsllq $56, %ymm12, %ymm11 + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + rorxq $39, %r8, %rax + addq %rdx, %r15 + xorq %rcx, %rax + vpsrlq $7, %ymm12, %ymm11 + movq %r9, %rdx + addq %r15, %r11 + xorq %r8, %rdx + vperm2I128 $0x81, %ymm1, %ymm1, %ymm14 + andq %rdx, %rbx + addq %rax, %r15 + xorq %r9, %rbx + rorxq $14, %r11, %rax + rorxq $18, %r11, %rcx + addq %rbx, %r15 + vpxor %ymm10, %ymm8, %ymm8 + addq 72(%rsp), %r14 + movq %r12, %rbx + xorq %rax, %rcx + vpxor %ymm11, %ymm8, %ymm8 + xorq %r13, %rbx + rorxq $41, %r11, %rax + xorq %rcx, %rax + vpaddq %ymm2, %ymm13, %ymm2 + vpaddq %ymm2, %ymm8, %ymm2 + andq %r11, %rbx + addq %rax, %r14 + rorxq $28, %r15, %rax + vpsrlq $19, %ymm14, %ymm8 + vpsllq $45, %ymm14, %ymm9 + rorxq $34, %r15, %rcx + xorq %r13, %rbx + xorq %rax, %rcx + vpsrlq $61, %ymm14, %ymm10 + vpsllq $3, %ymm14, %ymm11 + vpor %ymm9, %ymm8, %ymm8 + rorxq $39, %r15, %rax + addq %rbx, %r14 + xorq %rcx, %rax + vpor %ymm11, %ymm10, %ymm10 + movq %r8, %rbx + leaq (%r10,%r14,1), %r10 + xorq %r15, %rbx + vpxor %ymm10, %ymm8, %ymm8 + andq %rbx, %rdx + addq %rax, %r14 + xorq %r8, %rdx + vpsrlq $6, %ymm14, %ymm11 + rorxq $14, %r10, %rax + rorxq $18, %r10, %rcx + addq %rdx, %r14 + vpxor %ymm11, %ymm8, %ymm8 + addq 80(%rsp), %r13 + movq %r11, %rdx + xorq %rax, %rcx + vpaddq %ymm2, %ymm8, %ymm2 + xorq %r12, %rdx + rorxq $41, %r10, %rax + xorq %rcx, %rax + vperm2I128 $8, %ymm2, %ymm2, %ymm14 + andq %r10, %rdx + addq %rax, %r13 + rorxq $28, %r14, %rax + rorxq $34, %r14, %rcx + xorq %r12, %rdx + xorq %rax, %rcx + vpsrlq $19, %ymm14, %ymm8 + vpsllq $45, %ymm14, %ymm9 + rorxq $39, %r14, %rax + addq %rdx, %r13 + xorq %rcx, %rax + vpsrlq $61, %ymm14, %ymm10 + vpsllq $3, %ymm14, %ymm11 + vpor %ymm9, %ymm8, %ymm8 + movq %r15, %rdx + addq %r13, %r9 + xorq %r14, %rdx + vpor %ymm11, %ymm10, %ymm10 + andq %rdx, %rbx + addq %rax, %r13 + xorq %r15, %rbx + vpxor %ymm10, %ymm8, %ymm8 + rorxq $14, %r9, %rax + rorxq $18, %r9, %rcx + addq %rbx, %r13 + vpsrlq $6, %ymm14, %ymm11 + addq 88(%rsp), %r12 + movq %r10, %rbx + xorq %rax, %rcx + xorq %r11, %rbx + rorxq $41, %r9, %rax + xorq %rcx, %rax + vpxor %ymm11, %ymm8, %ymm8 + andq %r9, %rbx + addq %rax, %r12 + rorxq $28, %r13, %rax + rorxq $34, %r13, %rcx + xorq %r11, %rbx + xorq %rax, %rcx + vpaddq %ymm2, %ymm8, %ymm2 + rorxq $39, %r13, %rax + addq %rbx, %r12 + xorq %rcx, %rax + vpaddq 64(%rsi), %ymm2, %ymm8 + movq %r14, %rbx + leaq (%r8,%r12,1), %r8 + xorq %r13, %rbx + andq %rbx, %rdx + addq %rax, %r12 + xorq %r14, %rdx + vmovdqu %ymm8, 64(%rsp) + rorxq $14, %r8, %rax + rorxq $18, %r8, %rcx + addq %rdx, %r12 + vpblendd $3, %ymm0, %ymm3, %ymm12 + vpblendd $3, %ymm2, %ymm1, %ymm13 + addq 96(%rsp), %r11 + movq %r9, %rdx + xorq %rax, %rcx + vpermq $57, %ymm12, %ymm12 + xorq %r10, %rdx + rorxq $41, %r8, %rax + xorq %rcx, %rax + vpermq $57, %ymm13, %ymm13 + andq %r8, %rdx + addq %rax, %r11 + rorxq $28, %r12, %rax + vpsrlq $0x01, %ymm12, %ymm8 + vpsllq $63, %ymm12, %ymm9 + rorxq $34, %r12, %rcx + xorq %r10, %rdx + xorq %rax, %rcx + vpsrlq $8, %ymm12, %ymm10 + vpsllq $56, %ymm12, %ymm11 + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + rorxq $39, %r12, %rax + addq %rdx, %r11 + xorq %rcx, %rax + vpsrlq $7, %ymm12, %ymm11 + movq %r13, %rdx + addq %r11, %r15 + xorq %r12, %rdx + vperm2I128 $0x81, %ymm2, %ymm2, %ymm14 + andq %rdx, %rbx + addq %rax, %r11 + xorq %r13, %rbx + rorxq $14, %r15, %rax + rorxq $18, %r15, %rcx + addq %rbx, %r11 + vpxor %ymm10, %ymm8, %ymm8 + addq 104(%rsp), %r10 + movq %r8, %rbx + xorq %rax, %rcx + vpxor %ymm11, %ymm8, %ymm8 + xorq %r9, %rbx + rorxq $41, %r15, %rax + xorq %rcx, %rax + vpaddq %ymm3, %ymm13, %ymm3 + vpaddq %ymm3, %ymm8, %ymm3 + andq %r15, %rbx + addq %rax, %r10 + rorxq $28, %r11, %rax + vpsrlq $19, %ymm14, %ymm8 + vpsllq $45, %ymm14, %ymm9 + rorxq $34, %r11, %rcx + xorq %r9, %rbx + xorq %rax, %rcx + vpsrlq $61, %ymm14, %ymm10 + vpsllq $3, %ymm14, %ymm11 + vpor %ymm9, %ymm8, %ymm8 + rorxq $39, %r11, %rax + addq %rbx, %r10 + xorq %rcx, %rax + vpor %ymm11, %ymm10, %ymm10 + movq %r12, %rbx + leaq (%r14,%r10,1), %r14 + xorq %r11, %rbx + vpxor %ymm10, %ymm8, %ymm8 + andq %rbx, %rdx + addq %rax, %r10 + xorq %r12, %rdx + vpsrlq $6, %ymm14, %ymm11 + rorxq $14, %r14, %rax + rorxq $18, %r14, %rcx + addq %rdx, %r10 + vpxor %ymm11, %ymm8, %ymm8 + addq 112(%rsp), %r9 + movq %r15, %rdx + xorq %rax, %rcx + vpaddq %ymm3, %ymm8, %ymm3 + xorq %r8, %rdx + rorxq $41, %r14, %rax + xorq %rcx, %rax + vperm2I128 $8, %ymm3, %ymm3, %ymm14 + andq %r14, %rdx + addq %rax, %r9 + rorxq $28, %r10, %rax + rorxq $34, %r10, %rcx + xorq %r8, %rdx + xorq %rax, %rcx + vpsrlq $19, %ymm14, %ymm8 + vpsllq $45, %ymm14, %ymm9 + rorxq $39, %r10, %rax + addq %rdx, %r9 + xorq %rcx, %rax + vpsrlq $61, %ymm14, %ymm10 + vpsllq $3, %ymm14, %ymm11 + vpor %ymm9, %ymm8, %ymm8 + movq %r11, %rdx + addq %r9, %r13 + xorq %r10, %rdx + vpor %ymm11, %ymm10, %ymm10 + andq %rdx, %rbx + addq %rax, %r9 + xorq %r11, %rbx + vpxor %ymm10, %ymm8, %ymm8 + rorxq $14, %r13, %rax + rorxq $18, %r13, %rcx + addq %rbx, %r9 + vpsrlq $6, %ymm14, %ymm11 + addq 120(%rsp), %r8 + movq %r14, %rbx + xorq %rax, %rcx + xorq %r15, %rbx + rorxq $41, %r13, %rax + xorq %rcx, %rax + vpxor %ymm11, %ymm8, %ymm8 + andq %r13, %rbx + addq %rax, %r8 + rorxq $28, %r9, %rax + rorxq $34, %r9, %rcx + xorq %r15, %rbx + xorq %rax, %rcx + vpaddq %ymm3, %ymm8, %ymm3 + rorxq $39, %r9, %rax + addq %rbx, %r8 + xorq %rcx, %rax + vpaddq 96(%rsi), %ymm3, %ymm8 + movq %r10, %rbx + leaq (%r12,%r8,1), %r12 + xorq %r9, %rbx + andq %rbx, %rdx + addq %rax, %r8 + xorq %r10, %rdx + vmovdqu %ymm8, 96(%rsp) + subl $0x01, 128(%rsp) + jne L_sha256_len_avx2_rorx_start + # rnd_all_4: 0-3 + rorxq $14, %r12, %rax + rorxq $18, %r12, %rcx + addq %rdx, %r8 + addq (%rsp), %r15 + movq %r13, %rdx + xorq %rax, %rcx + xorq %r14, %rdx + rorxq $41, %r12, %rax + xorq %rcx, %rax + andq %r12, %rdx + addq %rax, %r15 + rorxq $28, %r8, %rax + rorxq $34, %r8, %rcx + xorq %r14, %rdx + xorq %rax, %rcx + rorxq $39, %r8, %rax + addq %rdx, %r15 + xorq %rcx, %rax + movq %r9, %rdx + addq %r15, %r11 + xorq %r8, %rdx + andq %rdx, %rbx + addq %rax, %r15 + xorq %r9, %rbx + rorxq $14, %r11, %rax + rorxq $18, %r11, %rcx + addq %rbx, %r15 + addq 8(%rsp), %r14 + movq %r12, %rbx + xorq %rax, %rcx + xorq %r13, %rbx + rorxq $41, %r11, %rax + xorq %rcx, %rax + andq %r11, %rbx + addq %rax, %r14 + rorxq $28, %r15, %rax + rorxq $34, %r15, %rcx + xorq %r13, %rbx + xorq %rax, %rcx + rorxq $39, %r15, %rax + addq %rbx, %r14 + xorq %rcx, %rax + movq %r8, %rbx + leaq (%r10,%r14,1), %r10 + xorq %r15, %rbx + andq %rbx, %rdx + addq %rax, %r14 + xorq %r8, %rdx + rorxq $14, %r10, %rax + rorxq $18, %r10, %rcx + addq %rdx, %r14 + addq 16(%rsp), %r13 + movq %r11, %rdx + xorq %rax, %rcx + xorq %r12, %rdx + rorxq $41, %r10, %rax + xorq %rcx, %rax + andq %r10, %rdx + addq %rax, %r13 + rorxq $28, %r14, %rax + rorxq $34, %r14, %rcx + xorq %r12, %rdx + xorq %rax, %rcx + rorxq $39, %r14, %rax + addq %rdx, %r13 + xorq %rcx, %rax + movq %r15, %rdx + addq %r13, %r9 + xorq %r14, %rdx + andq %rdx, %rbx + addq %rax, %r13 + xorq %r15, %rbx + rorxq $14, %r9, %rax + rorxq $18, %r9, %rcx + addq %rbx, %r13 + addq 24(%rsp), %r12 + movq %r10, %rbx + xorq %rax, %rcx + xorq %r11, %rbx + rorxq $41, %r9, %rax + xorq %rcx, %rax + andq %r9, %rbx + addq %rax, %r12 + rorxq $28, %r13, %rax + rorxq $34, %r13, %rcx + xorq %r11, %rbx + xorq %rax, %rcx + rorxq $39, %r13, %rax + addq %rbx, %r12 + xorq %rcx, %rax + movq %r14, %rbx + leaq (%r8,%r12,1), %r8 + xorq %r13, %rbx + andq %rbx, %rdx + addq %rax, %r12 + xorq %r14, %rdx + # rnd_all_4: 4-7 + rorxq $14, %r8, %rax + rorxq $18, %r8, %rcx + addq %rdx, %r12 + addq 32(%rsp), %r11 + movq %r9, %rdx + xorq %rax, %rcx + xorq %r10, %rdx + rorxq $41, %r8, %rax + xorq %rcx, %rax + andq %r8, %rdx + addq %rax, %r11 + rorxq $28, %r12, %rax + rorxq $34, %r12, %rcx + xorq %r10, %rdx + xorq %rax, %rcx + rorxq $39, %r12, %rax + addq %rdx, %r11 + xorq %rcx, %rax + movq %r13, %rdx + addq %r11, %r15 + xorq %r12, %rdx + andq %rdx, %rbx + addq %rax, %r11 + xorq %r13, %rbx + rorxq $14, %r15, %rax + rorxq $18, %r15, %rcx + addq %rbx, %r11 + addq 40(%rsp), %r10 + movq %r8, %rbx + xorq %rax, %rcx + xorq %r9, %rbx + rorxq $41, %r15, %rax + xorq %rcx, %rax + andq %r15, %rbx + addq %rax, %r10 + rorxq $28, %r11, %rax + rorxq $34, %r11, %rcx + xorq %r9, %rbx + xorq %rax, %rcx + rorxq $39, %r11, %rax + addq %rbx, %r10 + xorq %rcx, %rax + movq %r12, %rbx + leaq (%r14,%r10,1), %r14 + xorq %r11, %rbx + andq %rbx, %rdx + addq %rax, %r10 + xorq %r12, %rdx + rorxq $14, %r14, %rax + rorxq $18, %r14, %rcx + addq %rdx, %r10 + addq 48(%rsp), %r9 + movq %r15, %rdx + xorq %rax, %rcx + xorq %r8, %rdx + rorxq $41, %r14, %rax + xorq %rcx, %rax + andq %r14, %rdx + addq %rax, %r9 + rorxq $28, %r10, %rax + rorxq $34, %r10, %rcx + xorq %r8, %rdx + xorq %rax, %rcx + rorxq $39, %r10, %rax + addq %rdx, %r9 + xorq %rcx, %rax + movq %r11, %rdx + addq %r9, %r13 + xorq %r10, %rdx + andq %rdx, %rbx + addq %rax, %r9 + xorq %r11, %rbx + rorxq $14, %r13, %rax + rorxq $18, %r13, %rcx + addq %rbx, %r9 + addq 56(%rsp), %r8 + movq %r14, %rbx + xorq %rax, %rcx + xorq %r15, %rbx + rorxq $41, %r13, %rax + xorq %rcx, %rax + andq %r13, %rbx + addq %rax, %r8 + rorxq $28, %r9, %rax + rorxq $34, %r9, %rcx + xorq %r15, %rbx + xorq %rax, %rcx + rorxq $39, %r9, %rax + addq %rbx, %r8 + xorq %rcx, %rax + movq %r10, %rbx + leaq (%r12,%r8,1), %r12 + xorq %r9, %rbx + andq %rbx, %rdx + addq %rax, %r8 + xorq %r10, %rdx + # rnd_all_4: 8-11 + rorxq $14, %r12, %rax + rorxq $18, %r12, %rcx + addq %rdx, %r8 + addq 64(%rsp), %r15 + movq %r13, %rdx + xorq %rax, %rcx + xorq %r14, %rdx + rorxq $41, %r12, %rax + xorq %rcx, %rax + andq %r12, %rdx + addq %rax, %r15 + rorxq $28, %r8, %rax + rorxq $34, %r8, %rcx + xorq %r14, %rdx + xorq %rax, %rcx + rorxq $39, %r8, %rax + addq %rdx, %r15 + xorq %rcx, %rax + movq %r9, %rdx + addq %r15, %r11 + xorq %r8, %rdx + andq %rdx, %rbx + addq %rax, %r15 + xorq %r9, %rbx + rorxq $14, %r11, %rax + rorxq $18, %r11, %rcx + addq %rbx, %r15 + addq 72(%rsp), %r14 + movq %r12, %rbx + xorq %rax, %rcx + xorq %r13, %rbx + rorxq $41, %r11, %rax + xorq %rcx, %rax + andq %r11, %rbx + addq %rax, %r14 + rorxq $28, %r15, %rax + rorxq $34, %r15, %rcx + xorq %r13, %rbx + xorq %rax, %rcx + rorxq $39, %r15, %rax + addq %rbx, %r14 + xorq %rcx, %rax + movq %r8, %rbx + leaq (%r10,%r14,1), %r10 + xorq %r15, %rbx + andq %rbx, %rdx + addq %rax, %r14 + xorq %r8, %rdx + rorxq $14, %r10, %rax + rorxq $18, %r10, %rcx + addq %rdx, %r14 + addq 80(%rsp), %r13 + movq %r11, %rdx + xorq %rax, %rcx + xorq %r12, %rdx + rorxq $41, %r10, %rax + xorq %rcx, %rax + andq %r10, %rdx + addq %rax, %r13 + rorxq $28, %r14, %rax + rorxq $34, %r14, %rcx + xorq %r12, %rdx + xorq %rax, %rcx + rorxq $39, %r14, %rax + addq %rdx, %r13 + xorq %rcx, %rax + movq %r15, %rdx + addq %r13, %r9 + xorq %r14, %rdx + andq %rdx, %rbx + addq %rax, %r13 + xorq %r15, %rbx + rorxq $14, %r9, %rax + rorxq $18, %r9, %rcx + addq %rbx, %r13 + addq 88(%rsp), %r12 + movq %r10, %rbx + xorq %rax, %rcx + xorq %r11, %rbx + rorxq $41, %r9, %rax + xorq %rcx, %rax + andq %r9, %rbx + addq %rax, %r12 + rorxq $28, %r13, %rax + rorxq $34, %r13, %rcx + xorq %r11, %rbx + xorq %rax, %rcx + rorxq $39, %r13, %rax + addq %rbx, %r12 + xorq %rcx, %rax + movq %r14, %rbx + leaq (%r8,%r12,1), %r8 + xorq %r13, %rbx + andq %rbx, %rdx + addq %rax, %r12 + xorq %r14, %rdx + # rnd_all_4: 12-15 + rorxq $14, %r8, %rax + rorxq $18, %r8, %rcx + addq %rdx, %r12 + addq 96(%rsp), %r11 + movq %r9, %rdx + xorq %rax, %rcx + xorq %r10, %rdx + rorxq $41, %r8, %rax + xorq %rcx, %rax + andq %r8, %rdx + addq %rax, %r11 + rorxq $28, %r12, %rax + rorxq $34, %r12, %rcx + xorq %r10, %rdx + xorq %rax, %rcx + rorxq $39, %r12, %rax + addq %rdx, %r11 + xorq %rcx, %rax + movq %r13, %rdx + addq %r11, %r15 + xorq %r12, %rdx + andq %rdx, %rbx + addq %rax, %r11 + xorq %r13, %rbx + rorxq $14, %r15, %rax + rorxq $18, %r15, %rcx + addq %rbx, %r11 + addq 104(%rsp), %r10 + movq %r8, %rbx + xorq %rax, %rcx + xorq %r9, %rbx + rorxq $41, %r15, %rax + xorq %rcx, %rax + andq %r15, %rbx + addq %rax, %r10 + rorxq $28, %r11, %rax + rorxq $34, %r11, %rcx + xorq %r9, %rbx + xorq %rax, %rcx + rorxq $39, %r11, %rax + addq %rbx, %r10 + xorq %rcx, %rax + movq %r12, %rbx + leaq (%r14,%r10,1), %r14 + xorq %r11, %rbx + andq %rbx, %rdx + addq %rax, %r10 + xorq %r12, %rdx + rorxq $14, %r14, %rax + rorxq $18, %r14, %rcx + addq %rdx, %r10 + addq 112(%rsp), %r9 + movq %r15, %rdx + xorq %rax, %rcx + xorq %r8, %rdx + rorxq $41, %r14, %rax + xorq %rcx, %rax + andq %r14, %rdx + addq %rax, %r9 + rorxq $28, %r10, %rax + rorxq $34, %r10, %rcx + xorq %r8, %rdx + xorq %rax, %rcx + rorxq $39, %r10, %rax + addq %rdx, %r9 + xorq %rcx, %rax + movq %r11, %rdx + addq %r9, %r13 + xorq %r10, %rdx + andq %rdx, %rbx + addq %rax, %r9 + xorq %r11, %rbx + rorxq $14, %r13, %rax + rorxq $18, %r13, %rcx + addq %rbx, %r9 + addq 120(%rsp), %r8 + movq %r14, %rbx + xorq %rax, %rcx + xorq %r15, %rbx + rorxq $41, %r13, %rax + xorq %rcx, %rax + andq %r13, %rbx + addq %rax, %r8 + rorxq $28, %r9, %rax + rorxq $34, %r9, %rcx + xorq %r15, %rbx + xorq %rax, %rcx + rorxq $39, %r9, %rax + addq %rbx, %r8 + xorq %rcx, %rax + movq %r10, %rbx + leaq (%r12,%r8,1), %r12 + xorq %r9, %rbx + andq %rbx, %rdx + addq %rax, %r8 + xorq %r10, %rdx + addq %rdx, %r8 + addq %r8, (%rdi) + addq %r9, 8(%rdi) + addq %r10, 16(%rdi) + addq %r11, 24(%rdi) + addq %r12, 32(%rdi) + addq %r13, 40(%rdi) + addq %r14, 48(%rdi) + addq %r15, 56(%rdi) + xorq %rax, %rax + vzeroupper + addq $0x88, %rsp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size Transform_Sha512_AVX2_RORX,.-Transform_Sha512_AVX2_RORX +#endif /* __APPLE__ */ +#ifndef __APPLE__ +.text +.globl Transform_Sha512_AVX2_RORX_Len +.type Transform_Sha512_AVX2_RORX_Len,@function +.align 4 +Transform_Sha512_AVX2_RORX_Len: +#else +.section __TEXT,__text +.globl _Transform_Sha512_AVX2_RORX_Len +.p2align 2 +_Transform_Sha512_AVX2_RORX_Len: +#endif /* __APPLE__ */ + pushq %rbx + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + pushq %rbp + testb $0x80, %sil + je L_sha512_len_avx2_rorx_block + movq 224(%rdi), %rax + push %rsi + vmovdqu (%rax), %ymm0 + vmovdqu 32(%rax), %ymm1 + vmovdqu 64(%rax), %ymm2 + vmovdqu 96(%rax), %ymm3 + vmovups %ymm0, 64(%rdi) + vmovups %ymm1, 96(%rdi) + vmovups %ymm2, 128(%rdi) + vmovups %ymm3, 160(%rdi) +#ifndef __APPLE__ + call Transform_Sha512_AVX2_RORX@plt +#else + call _Transform_Sha512_AVX2_RORX +#endif /* __APPLE__ */ + pop %rsi + addq $0x80, 224(%rdi) + subl $0x80, %esi + jz L_sha512_len_avx2_rorx_done +L_sha512_len_avx2_rorx_block: + movq 224(%rdi), %rax + vmovdqa L_avx2_rorx_sha512_flip_mask(%rip), %ymm15 + movq (%rdi), %r8 + movq 8(%rdi), %r9 + movq 16(%rdi), %r10 + movq 24(%rdi), %r11 + movq 32(%rdi), %r12 + movq 40(%rdi), %r13 + movq 48(%rdi), %r14 + movq 56(%rdi), %r15 + # Start of loop processing two blocks +L_sha512_len_avx2_rorx_begin: + subq $0x540, %rsp + leaq L_avx2_rorx_sha512_k_2(%rip), %rbp + movq %r9, %rbx + xorq %rdx, %rdx + vmovdqu (%rax), %xmm0 + vmovdqu 16(%rax), %xmm1 + vinserti128 $0x01, 128(%rax), %ymm0, %ymm0 + vinserti128 $0x01, 144(%rax), %ymm1, %ymm1 + vpshufb %ymm15, %ymm0, %ymm0 + vpshufb %ymm15, %ymm1, %ymm1 + vmovdqu 32(%rax), %xmm2 + vmovdqu 48(%rax), %xmm3 + vinserti128 $0x01, 160(%rax), %ymm2, %ymm2 + vinserti128 $0x01, 176(%rax), %ymm3, %ymm3 + vpshufb %ymm15, %ymm2, %ymm2 + vpshufb %ymm15, %ymm3, %ymm3 + vmovdqu 64(%rax), %xmm4 + vmovdqu 80(%rax), %xmm5 + vinserti128 $0x01, 192(%rax), %ymm4, %ymm4 + vinserti128 $0x01, 208(%rax), %ymm5, %ymm5 + vpshufb %ymm15, %ymm4, %ymm4 + vpshufb %ymm15, %ymm5, %ymm5 + vmovdqu 96(%rax), %xmm6 + vmovdqu 112(%rax), %xmm7 + vinserti128 $0x01, 224(%rax), %ymm6, %ymm6 + vinserti128 $0x01, 240(%rax), %ymm7, %ymm7 + vpshufb %ymm15, %ymm6, %ymm6 + vpshufb %ymm15, %ymm7, %ymm7 + xorq %r10, %rbx + # Start of 16 rounds +L_sha512_len_avx2_rorx_start: + vpaddq (%rbp), %ymm0, %ymm8 + vpaddq 32(%rbp), %ymm1, %ymm9 + vmovdqu %ymm8, (%rsp) + vmovdqu %ymm9, 32(%rsp) + vpaddq 64(%rbp), %ymm2, %ymm8 + vpaddq 96(%rbp), %ymm3, %ymm9 + vmovdqu %ymm8, 64(%rsp) + vmovdqu %ymm9, 96(%rsp) + vpaddq 128(%rbp), %ymm4, %ymm8 + vpaddq 160(%rbp), %ymm5, %ymm9 + vmovdqu %ymm8, 128(%rsp) + vmovdqu %ymm9, 160(%rsp) + vpaddq 192(%rbp), %ymm6, %ymm8 + vpaddq 224(%rbp), %ymm7, %ymm9 + vmovdqu %ymm8, 192(%rsp) + vmovdqu %ymm9, 224(%rsp) + # msg_sched: 0-1 + rorxq $14, %r12, %rax + rorxq $18, %r12, %rcx + addq %rdx, %r8 + vpalignr $8, %ymm0, %ymm1, %ymm12 + addq (%rsp), %r15 + movq %r13, %rdx + xorq %rax, %rcx + vpalignr $8, %ymm4, %ymm5, %ymm13 + xorq %r14, %rdx + rorxq $41, %r12, %rax + xorq %rcx, %rax + vpsrlq $0x01, %ymm12, %ymm8 + vpsllq $63, %ymm12, %ymm9 + andq %r12, %rdx + addq %rax, %r15 + rorxq $28, %r8, %rax + vpsrlq $8, %ymm12, %ymm10 + vpsllq $56, %ymm12, %ymm11 + rorxq $34, %r8, %rcx + xorq %r14, %rdx + xorq %rax, %rcx + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + rorxq $39, %r8, %rax + addq %rdx, %r15 + xorq %rcx, %rax + vpsrlq $7, %ymm12, %ymm11 + vpxor %ymm10, %ymm8, %ymm8 + movq %r9, %rdx + addq %r15, %r11 + xorq %r8, %rdx + vpxor %ymm11, %ymm8, %ymm8 + vpaddq %ymm0, %ymm13, %ymm0 + andq %rdx, %rbx + addq %rax, %r15 + xorq %r9, %rbx + vpaddq %ymm0, %ymm8, %ymm0 + rorxq $14, %r11, %rax + rorxq $18, %r11, %rcx + addq %rbx, %r15 + vpsrlq $19, %ymm7, %ymm8 + vpsllq $45, %ymm7, %ymm9 + addq 8(%rsp), %r14 + movq %r12, %rbx + xorq %rax, %rcx + vpsrlq $61, %ymm7, %ymm10 + vpsllq $3, %ymm7, %ymm11 + xorq %r13, %rbx + rorxq $41, %r11, %rax + xorq %rcx, %rax + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + andq %r11, %rbx + addq %rax, %r14 + rorxq $28, %r15, %rax + rorxq $34, %r15, %rcx + xorq %r13, %rbx + xorq %rax, %rcx + vpxor %ymm10, %ymm8, %ymm8 + vpsrlq $6, %ymm7, %ymm11 + rorxq $39, %r15, %rax + addq %rbx, %r14 + xorq %rcx, %rax + movq %r8, %rbx + leaq (%r10,%r14,1), %r10 + xorq %r15, %rbx + vpxor %ymm11, %ymm8, %ymm8 + andq %rbx, %rdx + addq %rax, %r14 + xorq %r8, %rdx + vpaddq %ymm0, %ymm8, %ymm0 + # msg_sched done: 0-3 + # msg_sched: 4-5 + rorxq $14, %r10, %rax + rorxq $18, %r10, %rcx + addq %rdx, %r14 + vpalignr $8, %ymm1, %ymm2, %ymm12 + addq 32(%rsp), %r13 + movq %r11, %rdx + xorq %rax, %rcx + vpalignr $8, %ymm5, %ymm6, %ymm13 + xorq %r12, %rdx + rorxq $41, %r10, %rax + xorq %rcx, %rax + vpsrlq $0x01, %ymm12, %ymm8 + vpsllq $63, %ymm12, %ymm9 + andq %r10, %rdx + addq %rax, %r13 + rorxq $28, %r14, %rax + vpsrlq $8, %ymm12, %ymm10 + vpsllq $56, %ymm12, %ymm11 + rorxq $34, %r14, %rcx + xorq %r12, %rdx + xorq %rax, %rcx + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + rorxq $39, %r14, %rax + addq %rdx, %r13 + xorq %rcx, %rax + vpsrlq $7, %ymm12, %ymm11 + vpxor %ymm10, %ymm8, %ymm8 + movq %r15, %rdx + addq %r13, %r9 + xorq %r14, %rdx + vpxor %ymm11, %ymm8, %ymm8 + vpaddq %ymm1, %ymm13, %ymm1 + andq %rdx, %rbx + addq %rax, %r13 + xorq %r15, %rbx + vpaddq %ymm1, %ymm8, %ymm1 + rorxq $14, %r9, %rax + rorxq $18, %r9, %rcx + addq %rbx, %r13 + vpsrlq $19, %ymm0, %ymm8 + vpsllq $45, %ymm0, %ymm9 + addq 40(%rsp), %r12 + movq %r10, %rbx + xorq %rax, %rcx + vpsrlq $61, %ymm0, %ymm10 + vpsllq $3, %ymm0, %ymm11 + xorq %r11, %rbx + rorxq $41, %r9, %rax + xorq %rcx, %rax + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + andq %r9, %rbx + addq %rax, %r12 + rorxq $28, %r13, %rax + rorxq $34, %r13, %rcx + xorq %r11, %rbx + xorq %rax, %rcx + vpxor %ymm10, %ymm8, %ymm8 + vpsrlq $6, %ymm0, %ymm11 + rorxq $39, %r13, %rax + addq %rbx, %r12 + xorq %rcx, %rax + movq %r14, %rbx + leaq (%r8,%r12,1), %r8 + xorq %r13, %rbx + vpxor %ymm11, %ymm8, %ymm8 + andq %rbx, %rdx + addq %rax, %r12 + xorq %r14, %rdx + vpaddq %ymm1, %ymm8, %ymm1 + # msg_sched done: 4-7 + # msg_sched: 8-9 + rorxq $14, %r8, %rax + rorxq $18, %r8, %rcx + addq %rdx, %r12 + vpalignr $8, %ymm2, %ymm3, %ymm12 + addq 64(%rsp), %r11 + movq %r9, %rdx + xorq %rax, %rcx + vpalignr $8, %ymm6, %ymm7, %ymm13 + xorq %r10, %rdx + rorxq $41, %r8, %rax + xorq %rcx, %rax + vpsrlq $0x01, %ymm12, %ymm8 + vpsllq $63, %ymm12, %ymm9 + andq %r8, %rdx + addq %rax, %r11 + rorxq $28, %r12, %rax + vpsrlq $8, %ymm12, %ymm10 + vpsllq $56, %ymm12, %ymm11 + rorxq $34, %r12, %rcx + xorq %r10, %rdx + xorq %rax, %rcx + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + rorxq $39, %r12, %rax + addq %rdx, %r11 + xorq %rcx, %rax + vpsrlq $7, %ymm12, %ymm11 + vpxor %ymm10, %ymm8, %ymm8 + movq %r13, %rdx + addq %r11, %r15 + xorq %r12, %rdx + vpxor %ymm11, %ymm8, %ymm8 + vpaddq %ymm2, %ymm13, %ymm2 + andq %rdx, %rbx + addq %rax, %r11 + xorq %r13, %rbx + vpaddq %ymm2, %ymm8, %ymm2 + rorxq $14, %r15, %rax + rorxq $18, %r15, %rcx + addq %rbx, %r11 + vpsrlq $19, %ymm1, %ymm8 + vpsllq $45, %ymm1, %ymm9 + addq 72(%rsp), %r10 + movq %r8, %rbx + xorq %rax, %rcx + vpsrlq $61, %ymm1, %ymm10 + vpsllq $3, %ymm1, %ymm11 + xorq %r9, %rbx + rorxq $41, %r15, %rax + xorq %rcx, %rax + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + andq %r15, %rbx + addq %rax, %r10 + rorxq $28, %r11, %rax + rorxq $34, %r11, %rcx + xorq %r9, %rbx + xorq %rax, %rcx + vpxor %ymm10, %ymm8, %ymm8 + vpsrlq $6, %ymm1, %ymm11 + rorxq $39, %r11, %rax + addq %rbx, %r10 + xorq %rcx, %rax + movq %r12, %rbx + leaq (%r14,%r10,1), %r14 + xorq %r11, %rbx + vpxor %ymm11, %ymm8, %ymm8 + andq %rbx, %rdx + addq %rax, %r10 + xorq %r12, %rdx + vpaddq %ymm2, %ymm8, %ymm2 + # msg_sched done: 8-11 + # msg_sched: 12-13 + rorxq $14, %r14, %rax + rorxq $18, %r14, %rcx + addq %rdx, %r10 + vpalignr $8, %ymm3, %ymm4, %ymm12 + addq 96(%rsp), %r9 + movq %r15, %rdx + xorq %rax, %rcx + vpalignr $8, %ymm7, %ymm0, %ymm13 + xorq %r8, %rdx + rorxq $41, %r14, %rax + xorq %rcx, %rax + vpsrlq $0x01, %ymm12, %ymm8 + vpsllq $63, %ymm12, %ymm9 + andq %r14, %rdx + addq %rax, %r9 + rorxq $28, %r10, %rax + vpsrlq $8, %ymm12, %ymm10 + vpsllq $56, %ymm12, %ymm11 + rorxq $34, %r10, %rcx + xorq %r8, %rdx + xorq %rax, %rcx + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + rorxq $39, %r10, %rax + addq %rdx, %r9 + xorq %rcx, %rax + vpsrlq $7, %ymm12, %ymm11 + vpxor %ymm10, %ymm8, %ymm8 + movq %r11, %rdx + addq %r9, %r13 + xorq %r10, %rdx + vpxor %ymm11, %ymm8, %ymm8 + vpaddq %ymm3, %ymm13, %ymm3 + andq %rdx, %rbx + addq %rax, %r9 + xorq %r11, %rbx + vpaddq %ymm3, %ymm8, %ymm3 + rorxq $14, %r13, %rax + rorxq $18, %r13, %rcx + addq %rbx, %r9 + vpsrlq $19, %ymm2, %ymm8 + vpsllq $45, %ymm2, %ymm9 + addq 104(%rsp), %r8 + movq %r14, %rbx + xorq %rax, %rcx + vpsrlq $61, %ymm2, %ymm10 + vpsllq $3, %ymm2, %ymm11 + xorq %r15, %rbx + rorxq $41, %r13, %rax + xorq %rcx, %rax + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + andq %r13, %rbx + addq %rax, %r8 + rorxq $28, %r9, %rax + rorxq $34, %r9, %rcx + xorq %r15, %rbx + xorq %rax, %rcx + vpxor %ymm10, %ymm8, %ymm8 + vpsrlq $6, %ymm2, %ymm11 + rorxq $39, %r9, %rax + addq %rbx, %r8 + xorq %rcx, %rax + movq %r10, %rbx + leaq (%r12,%r8,1), %r12 + xorq %r9, %rbx + vpxor %ymm11, %ymm8, %ymm8 + andq %rbx, %rdx + addq %rax, %r8 + xorq %r10, %rdx + vpaddq %ymm3, %ymm8, %ymm3 + # msg_sched done: 12-15 + # msg_sched: 16-17 + rorxq $14, %r12, %rax + rorxq $18, %r12, %rcx + addq %rdx, %r8 + vpalignr $8, %ymm4, %ymm5, %ymm12 + addq 128(%rsp), %r15 + movq %r13, %rdx + xorq %rax, %rcx + vpalignr $8, %ymm0, %ymm1, %ymm13 + xorq %r14, %rdx + rorxq $41, %r12, %rax + xorq %rcx, %rax + vpsrlq $0x01, %ymm12, %ymm8 + vpsllq $63, %ymm12, %ymm9 + andq %r12, %rdx + addq %rax, %r15 + rorxq $28, %r8, %rax + vpsrlq $8, %ymm12, %ymm10 + vpsllq $56, %ymm12, %ymm11 + rorxq $34, %r8, %rcx + xorq %r14, %rdx + xorq %rax, %rcx + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + rorxq $39, %r8, %rax + addq %rdx, %r15 + xorq %rcx, %rax + vpsrlq $7, %ymm12, %ymm11 + vpxor %ymm10, %ymm8, %ymm8 + movq %r9, %rdx + addq %r15, %r11 + xorq %r8, %rdx + vpxor %ymm11, %ymm8, %ymm8 + vpaddq %ymm4, %ymm13, %ymm4 + andq %rdx, %rbx + addq %rax, %r15 + xorq %r9, %rbx + vpaddq %ymm4, %ymm8, %ymm4 + rorxq $14, %r11, %rax + rorxq $18, %r11, %rcx + addq %rbx, %r15 + vpsrlq $19, %ymm3, %ymm8 + vpsllq $45, %ymm3, %ymm9 + addq 136(%rsp), %r14 + movq %r12, %rbx + xorq %rax, %rcx + vpsrlq $61, %ymm3, %ymm10 + vpsllq $3, %ymm3, %ymm11 + xorq %r13, %rbx + rorxq $41, %r11, %rax + xorq %rcx, %rax + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + andq %r11, %rbx + addq %rax, %r14 + rorxq $28, %r15, %rax + rorxq $34, %r15, %rcx + xorq %r13, %rbx + xorq %rax, %rcx + vpxor %ymm10, %ymm8, %ymm8 + vpsrlq $6, %ymm3, %ymm11 + rorxq $39, %r15, %rax + addq %rbx, %r14 + xorq %rcx, %rax + movq %r8, %rbx + leaq (%r10,%r14,1), %r10 + xorq %r15, %rbx + vpxor %ymm11, %ymm8, %ymm8 + andq %rbx, %rdx + addq %rax, %r14 + xorq %r8, %rdx + vpaddq %ymm4, %ymm8, %ymm4 + # msg_sched done: 16-19 + # msg_sched: 20-21 + rorxq $14, %r10, %rax + rorxq $18, %r10, %rcx + addq %rdx, %r14 + vpalignr $8, %ymm5, %ymm6, %ymm12 + addq 160(%rsp), %r13 + movq %r11, %rdx + xorq %rax, %rcx + vpalignr $8, %ymm1, %ymm2, %ymm13 + xorq %r12, %rdx + rorxq $41, %r10, %rax + xorq %rcx, %rax + vpsrlq $0x01, %ymm12, %ymm8 + vpsllq $63, %ymm12, %ymm9 + andq %r10, %rdx + addq %rax, %r13 + rorxq $28, %r14, %rax + vpsrlq $8, %ymm12, %ymm10 + vpsllq $56, %ymm12, %ymm11 + rorxq $34, %r14, %rcx + xorq %r12, %rdx + xorq %rax, %rcx + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + rorxq $39, %r14, %rax + addq %rdx, %r13 + xorq %rcx, %rax + vpsrlq $7, %ymm12, %ymm11 + vpxor %ymm10, %ymm8, %ymm8 + movq %r15, %rdx + addq %r13, %r9 + xorq %r14, %rdx + vpxor %ymm11, %ymm8, %ymm8 + vpaddq %ymm5, %ymm13, %ymm5 + andq %rdx, %rbx + addq %rax, %r13 + xorq %r15, %rbx + vpaddq %ymm5, %ymm8, %ymm5 + rorxq $14, %r9, %rax + rorxq $18, %r9, %rcx + addq %rbx, %r13 + vpsrlq $19, %ymm4, %ymm8 + vpsllq $45, %ymm4, %ymm9 + addq 168(%rsp), %r12 + movq %r10, %rbx + xorq %rax, %rcx + vpsrlq $61, %ymm4, %ymm10 + vpsllq $3, %ymm4, %ymm11 + xorq %r11, %rbx + rorxq $41, %r9, %rax + xorq %rcx, %rax + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + andq %r9, %rbx + addq %rax, %r12 + rorxq $28, %r13, %rax + rorxq $34, %r13, %rcx + xorq %r11, %rbx + xorq %rax, %rcx + vpxor %ymm10, %ymm8, %ymm8 + vpsrlq $6, %ymm4, %ymm11 + rorxq $39, %r13, %rax + addq %rbx, %r12 + xorq %rcx, %rax + movq %r14, %rbx + leaq (%r8,%r12,1), %r8 + xorq %r13, %rbx + vpxor %ymm11, %ymm8, %ymm8 + andq %rbx, %rdx + addq %rax, %r12 + xorq %r14, %rdx + vpaddq %ymm5, %ymm8, %ymm5 + # msg_sched done: 20-23 + # msg_sched: 24-25 + rorxq $14, %r8, %rax + rorxq $18, %r8, %rcx + addq %rdx, %r12 + vpalignr $8, %ymm6, %ymm7, %ymm12 + addq 192(%rsp), %r11 + movq %r9, %rdx + xorq %rax, %rcx + vpalignr $8, %ymm2, %ymm3, %ymm13 + xorq %r10, %rdx + rorxq $41, %r8, %rax + xorq %rcx, %rax + vpsrlq $0x01, %ymm12, %ymm8 + vpsllq $63, %ymm12, %ymm9 + andq %r8, %rdx + addq %rax, %r11 + rorxq $28, %r12, %rax + vpsrlq $8, %ymm12, %ymm10 + vpsllq $56, %ymm12, %ymm11 + rorxq $34, %r12, %rcx + xorq %r10, %rdx + xorq %rax, %rcx + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + rorxq $39, %r12, %rax + addq %rdx, %r11 + xorq %rcx, %rax + vpsrlq $7, %ymm12, %ymm11 + vpxor %ymm10, %ymm8, %ymm8 + movq %r13, %rdx + addq %r11, %r15 + xorq %r12, %rdx + vpxor %ymm11, %ymm8, %ymm8 + vpaddq %ymm6, %ymm13, %ymm6 + andq %rdx, %rbx + addq %rax, %r11 + xorq %r13, %rbx + vpaddq %ymm6, %ymm8, %ymm6 + rorxq $14, %r15, %rax + rorxq $18, %r15, %rcx + addq %rbx, %r11 + vpsrlq $19, %ymm5, %ymm8 + vpsllq $45, %ymm5, %ymm9 + addq 200(%rsp), %r10 + movq %r8, %rbx + xorq %rax, %rcx + vpsrlq $61, %ymm5, %ymm10 + vpsllq $3, %ymm5, %ymm11 + xorq %r9, %rbx + rorxq $41, %r15, %rax + xorq %rcx, %rax + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + andq %r15, %rbx + addq %rax, %r10 + rorxq $28, %r11, %rax + rorxq $34, %r11, %rcx + xorq %r9, %rbx + xorq %rax, %rcx + vpxor %ymm10, %ymm8, %ymm8 + vpsrlq $6, %ymm5, %ymm11 + rorxq $39, %r11, %rax + addq %rbx, %r10 + xorq %rcx, %rax + movq %r12, %rbx + leaq (%r14,%r10,1), %r14 + xorq %r11, %rbx + vpxor %ymm11, %ymm8, %ymm8 + andq %rbx, %rdx + addq %rax, %r10 + xorq %r12, %rdx + vpaddq %ymm6, %ymm8, %ymm6 + # msg_sched done: 24-27 + # msg_sched: 28-29 + rorxq $14, %r14, %rax + rorxq $18, %r14, %rcx + addq %rdx, %r10 + vpalignr $8, %ymm7, %ymm0, %ymm12 + addq 224(%rsp), %r9 + movq %r15, %rdx + xorq %rax, %rcx + vpalignr $8, %ymm3, %ymm4, %ymm13 + xorq %r8, %rdx + rorxq $41, %r14, %rax + xorq %rcx, %rax + vpsrlq $0x01, %ymm12, %ymm8 + vpsllq $63, %ymm12, %ymm9 + andq %r14, %rdx + addq %rax, %r9 + rorxq $28, %r10, %rax + vpsrlq $8, %ymm12, %ymm10 + vpsllq $56, %ymm12, %ymm11 + rorxq $34, %r10, %rcx + xorq %r8, %rdx + xorq %rax, %rcx + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + rorxq $39, %r10, %rax + addq %rdx, %r9 + xorq %rcx, %rax + vpsrlq $7, %ymm12, %ymm11 + vpxor %ymm10, %ymm8, %ymm8 + movq %r11, %rdx + addq %r9, %r13 + xorq %r10, %rdx + vpxor %ymm11, %ymm8, %ymm8 + vpaddq %ymm7, %ymm13, %ymm7 + andq %rdx, %rbx + addq %rax, %r9 + xorq %r11, %rbx + vpaddq %ymm7, %ymm8, %ymm7 + rorxq $14, %r13, %rax + rorxq $18, %r13, %rcx + addq %rbx, %r9 + vpsrlq $19, %ymm6, %ymm8 + vpsllq $45, %ymm6, %ymm9 + addq 232(%rsp), %r8 + movq %r14, %rbx + xorq %rax, %rcx + vpsrlq $61, %ymm6, %ymm10 + vpsllq $3, %ymm6, %ymm11 + xorq %r15, %rbx + rorxq $41, %r13, %rax + xorq %rcx, %rax + vpor %ymm9, %ymm8, %ymm8 + vpor %ymm11, %ymm10, %ymm10 + andq %r13, %rbx + addq %rax, %r8 + rorxq $28, %r9, %rax + rorxq $34, %r9, %rcx + xorq %r15, %rbx + xorq %rax, %rcx + vpxor %ymm10, %ymm8, %ymm8 + vpsrlq $6, %ymm6, %ymm11 + rorxq $39, %r9, %rax + addq %rbx, %r8 + xorq %rcx, %rax + movq %r10, %rbx + leaq (%r12,%r8,1), %r12 + xorq %r9, %rbx + vpxor %ymm11, %ymm8, %ymm8 + andq %rbx, %rdx + addq %rax, %r8 + xorq %r10, %rdx + vpaddq %ymm7, %ymm8, %ymm7 + # msg_sched done: 28-31 + addq $0x100, %rbp + addq $0x100, %rsp + cmpq L_avx2_rorx_sha512_k_2_end(%rip), %rbp + jne L_sha512_len_avx2_rorx_start + vpaddq (%rbp), %ymm0, %ymm8 + vpaddq 32(%rbp), %ymm1, %ymm9 + vmovdqu %ymm8, (%rsp) + vmovdqu %ymm9, 32(%rsp) + vpaddq 64(%rbp), %ymm2, %ymm8 + vpaddq 96(%rbp), %ymm3, %ymm9 + vmovdqu %ymm8, 64(%rsp) + vmovdqu %ymm9, 96(%rsp) + vpaddq 128(%rbp), %ymm4, %ymm8 + vpaddq 160(%rbp), %ymm5, %ymm9 + vmovdqu %ymm8, 128(%rsp) + vmovdqu %ymm9, 160(%rsp) + vpaddq 192(%rbp), %ymm6, %ymm8 + vpaddq 224(%rbp), %ymm7, %ymm9 + vmovdqu %ymm8, 192(%rsp) + vmovdqu %ymm9, 224(%rsp) + # rnd_all_2: 0-1 + rorxq $14, %r12, %rax + rorxq $18, %r12, %rcx + addq %rdx, %r8 + addq (%rsp), %r15 + movq %r13, %rdx + xorq %rax, %rcx + xorq %r14, %rdx + rorxq $41, %r12, %rax + xorq %rcx, %rax + andq %r12, %rdx + addq %rax, %r15 + rorxq $28, %r8, %rax + rorxq $34, %r8, %rcx + xorq %r14, %rdx + xorq %rax, %rcx + rorxq $39, %r8, %rax + addq %rdx, %r15 + xorq %rcx, %rax + movq %r9, %rdx + addq %r15, %r11 + xorq %r8, %rdx + andq %rdx, %rbx + addq %rax, %r15 + xorq %r9, %rbx + rorxq $14, %r11, %rax + rorxq $18, %r11, %rcx + addq %rbx, %r15 + addq 8(%rsp), %r14 + movq %r12, %rbx + xorq %rax, %rcx + xorq %r13, %rbx + rorxq $41, %r11, %rax + xorq %rcx, %rax + andq %r11, %rbx + addq %rax, %r14 + rorxq $28, %r15, %rax + rorxq $34, %r15, %rcx + xorq %r13, %rbx + xorq %rax, %rcx + rorxq $39, %r15, %rax + addq %rbx, %r14 + xorq %rcx, %rax + movq %r8, %rbx + leaq (%r10,%r14,1), %r10 + xorq %r15, %rbx + andq %rbx, %rdx + addq %rax, %r14 + xorq %r8, %rdx + # rnd_all_2: 4-5 + rorxq $14, %r10, %rax + rorxq $18, %r10, %rcx + addq %rdx, %r14 + addq 32(%rsp), %r13 + movq %r11, %rdx + xorq %rax, %rcx + xorq %r12, %rdx + rorxq $41, %r10, %rax + xorq %rcx, %rax + andq %r10, %rdx + addq %rax, %r13 + rorxq $28, %r14, %rax + rorxq $34, %r14, %rcx + xorq %r12, %rdx + xorq %rax, %rcx + rorxq $39, %r14, %rax + addq %rdx, %r13 + xorq %rcx, %rax + movq %r15, %rdx + addq %r13, %r9 + xorq %r14, %rdx + andq %rdx, %rbx + addq %rax, %r13 + xorq %r15, %rbx + rorxq $14, %r9, %rax + rorxq $18, %r9, %rcx + addq %rbx, %r13 + addq 40(%rsp), %r12 + movq %r10, %rbx + xorq %rax, %rcx + xorq %r11, %rbx + rorxq $41, %r9, %rax + xorq %rcx, %rax + andq %r9, %rbx + addq %rax, %r12 + rorxq $28, %r13, %rax + rorxq $34, %r13, %rcx + xorq %r11, %rbx + xorq %rax, %rcx + rorxq $39, %r13, %rax + addq %rbx, %r12 + xorq %rcx, %rax + movq %r14, %rbx + leaq (%r8,%r12,1), %r8 + xorq %r13, %rbx + andq %rbx, %rdx + addq %rax, %r12 + xorq %r14, %rdx + # rnd_all_2: 8-9 + rorxq $14, %r8, %rax + rorxq $18, %r8, %rcx + addq %rdx, %r12 + addq 64(%rsp), %r11 + movq %r9, %rdx + xorq %rax, %rcx + xorq %r10, %rdx + rorxq $41, %r8, %rax + xorq %rcx, %rax + andq %r8, %rdx + addq %rax, %r11 + rorxq $28, %r12, %rax + rorxq $34, %r12, %rcx + xorq %r10, %rdx + xorq %rax, %rcx + rorxq $39, %r12, %rax + addq %rdx, %r11 + xorq %rcx, %rax + movq %r13, %rdx + addq %r11, %r15 + xorq %r12, %rdx + andq %rdx, %rbx + addq %rax, %r11 + xorq %r13, %rbx + rorxq $14, %r15, %rax + rorxq $18, %r15, %rcx + addq %rbx, %r11 + addq 72(%rsp), %r10 + movq %r8, %rbx + xorq %rax, %rcx + xorq %r9, %rbx + rorxq $41, %r15, %rax + xorq %rcx, %rax + andq %r15, %rbx + addq %rax, %r10 + rorxq $28, %r11, %rax + rorxq $34, %r11, %rcx + xorq %r9, %rbx + xorq %rax, %rcx + rorxq $39, %r11, %rax + addq %rbx, %r10 + xorq %rcx, %rax + movq %r12, %rbx + leaq (%r14,%r10,1), %r14 + xorq %r11, %rbx + andq %rbx, %rdx + addq %rax, %r10 + xorq %r12, %rdx + # rnd_all_2: 12-13 + rorxq $14, %r14, %rax + rorxq $18, %r14, %rcx + addq %rdx, %r10 + addq 96(%rsp), %r9 + movq %r15, %rdx + xorq %rax, %rcx + xorq %r8, %rdx + rorxq $41, %r14, %rax + xorq %rcx, %rax + andq %r14, %rdx + addq %rax, %r9 + rorxq $28, %r10, %rax + rorxq $34, %r10, %rcx + xorq %r8, %rdx + xorq %rax, %rcx + rorxq $39, %r10, %rax + addq %rdx, %r9 + xorq %rcx, %rax + movq %r11, %rdx + addq %r9, %r13 + xorq %r10, %rdx + andq %rdx, %rbx + addq %rax, %r9 + xorq %r11, %rbx + rorxq $14, %r13, %rax + rorxq $18, %r13, %rcx + addq %rbx, %r9 + addq 104(%rsp), %r8 + movq %r14, %rbx + xorq %rax, %rcx + xorq %r15, %rbx + rorxq $41, %r13, %rax + xorq %rcx, %rax + andq %r13, %rbx + addq %rax, %r8 + rorxq $28, %r9, %rax + rorxq $34, %r9, %rcx + xorq %r15, %rbx + xorq %rax, %rcx + rorxq $39, %r9, %rax + addq %rbx, %r8 + xorq %rcx, %rax + movq %r10, %rbx + leaq (%r12,%r8,1), %r12 + xorq %r9, %rbx + andq %rbx, %rdx + addq %rax, %r8 + xorq %r10, %rdx + # rnd_all_2: 16-17 + rorxq $14, %r12, %rax + rorxq $18, %r12, %rcx + addq %rdx, %r8 + addq 128(%rsp), %r15 + movq %r13, %rdx + xorq %rax, %rcx + xorq %r14, %rdx + rorxq $41, %r12, %rax + xorq %rcx, %rax + andq %r12, %rdx + addq %rax, %r15 + rorxq $28, %r8, %rax + rorxq $34, %r8, %rcx + xorq %r14, %rdx + xorq %rax, %rcx + rorxq $39, %r8, %rax + addq %rdx, %r15 + xorq %rcx, %rax + movq %r9, %rdx + addq %r15, %r11 + xorq %r8, %rdx + andq %rdx, %rbx + addq %rax, %r15 + xorq %r9, %rbx + rorxq $14, %r11, %rax + rorxq $18, %r11, %rcx + addq %rbx, %r15 + addq 136(%rsp), %r14 + movq %r12, %rbx + xorq %rax, %rcx + xorq %r13, %rbx + rorxq $41, %r11, %rax + xorq %rcx, %rax + andq %r11, %rbx + addq %rax, %r14 + rorxq $28, %r15, %rax + rorxq $34, %r15, %rcx + xorq %r13, %rbx + xorq %rax, %rcx + rorxq $39, %r15, %rax + addq %rbx, %r14 + xorq %rcx, %rax + movq %r8, %rbx + leaq (%r10,%r14,1), %r10 + xorq %r15, %rbx + andq %rbx, %rdx + addq %rax, %r14 + xorq %r8, %rdx + # rnd_all_2: 20-21 + rorxq $14, %r10, %rax + rorxq $18, %r10, %rcx + addq %rdx, %r14 + addq 160(%rsp), %r13 + movq %r11, %rdx + xorq %rax, %rcx + xorq %r12, %rdx + rorxq $41, %r10, %rax + xorq %rcx, %rax + andq %r10, %rdx + addq %rax, %r13 + rorxq $28, %r14, %rax + rorxq $34, %r14, %rcx + xorq %r12, %rdx + xorq %rax, %rcx + rorxq $39, %r14, %rax + addq %rdx, %r13 + xorq %rcx, %rax + movq %r15, %rdx + addq %r13, %r9 + xorq %r14, %rdx + andq %rdx, %rbx + addq %rax, %r13 + xorq %r15, %rbx + rorxq $14, %r9, %rax + rorxq $18, %r9, %rcx + addq %rbx, %r13 + addq 168(%rsp), %r12 + movq %r10, %rbx + xorq %rax, %rcx + xorq %r11, %rbx + rorxq $41, %r9, %rax + xorq %rcx, %rax + andq %r9, %rbx + addq %rax, %r12 + rorxq $28, %r13, %rax + rorxq $34, %r13, %rcx + xorq %r11, %rbx + xorq %rax, %rcx + rorxq $39, %r13, %rax + addq %rbx, %r12 + xorq %rcx, %rax + movq %r14, %rbx + leaq (%r8,%r12,1), %r8 + xorq %r13, %rbx + andq %rbx, %rdx + addq %rax, %r12 + xorq %r14, %rdx + # rnd_all_2: 24-25 + rorxq $14, %r8, %rax + rorxq $18, %r8, %rcx + addq %rdx, %r12 + addq 192(%rsp), %r11 + movq %r9, %rdx + xorq %rax, %rcx + xorq %r10, %rdx + rorxq $41, %r8, %rax + xorq %rcx, %rax + andq %r8, %rdx + addq %rax, %r11 + rorxq $28, %r12, %rax + rorxq $34, %r12, %rcx + xorq %r10, %rdx + xorq %rax, %rcx + rorxq $39, %r12, %rax + addq %rdx, %r11 + xorq %rcx, %rax + movq %r13, %rdx + addq %r11, %r15 + xorq %r12, %rdx + andq %rdx, %rbx + addq %rax, %r11 + xorq %r13, %rbx + rorxq $14, %r15, %rax + rorxq $18, %r15, %rcx + addq %rbx, %r11 + addq 200(%rsp), %r10 + movq %r8, %rbx + xorq %rax, %rcx + xorq %r9, %rbx + rorxq $41, %r15, %rax + xorq %rcx, %rax + andq %r15, %rbx + addq %rax, %r10 + rorxq $28, %r11, %rax + rorxq $34, %r11, %rcx + xorq %r9, %rbx + xorq %rax, %rcx + rorxq $39, %r11, %rax + addq %rbx, %r10 + xorq %rcx, %rax + movq %r12, %rbx + leaq (%r14,%r10,1), %r14 + xorq %r11, %rbx + andq %rbx, %rdx + addq %rax, %r10 + xorq %r12, %rdx + # rnd_all_2: 28-29 + rorxq $14, %r14, %rax + rorxq $18, %r14, %rcx + addq %rdx, %r10 + addq 224(%rsp), %r9 + movq %r15, %rdx + xorq %rax, %rcx + xorq %r8, %rdx + rorxq $41, %r14, %rax + xorq %rcx, %rax + andq %r14, %rdx + addq %rax, %r9 + rorxq $28, %r10, %rax + rorxq $34, %r10, %rcx + xorq %r8, %rdx + xorq %rax, %rcx + rorxq $39, %r10, %rax + addq %rdx, %r9 + xorq %rcx, %rax + movq %r11, %rdx + addq %r9, %r13 + xorq %r10, %rdx + andq %rdx, %rbx + addq %rax, %r9 + xorq %r11, %rbx + rorxq $14, %r13, %rax + rorxq $18, %r13, %rcx + addq %rbx, %r9 + addq 232(%rsp), %r8 + movq %r14, %rbx + xorq %rax, %rcx + xorq %r15, %rbx + rorxq $41, %r13, %rax + xorq %rcx, %rax + andq %r13, %rbx + addq %rax, %r8 + rorxq $28, %r9, %rax + rorxq $34, %r9, %rcx + xorq %r15, %rbx + xorq %rax, %rcx + rorxq $39, %r9, %rax + addq %rbx, %r8 + xorq %rcx, %rax + movq %r10, %rbx + leaq (%r12,%r8,1), %r12 + xorq %r9, %rbx + andq %rbx, %rdx + addq %rax, %r8 + xorq %r10, %rdx + addq %rdx, %r8 + subq $0x400, %rsp + addq (%rdi), %r8 + addq 8(%rdi), %r9 + addq 16(%rdi), %r10 + addq 24(%rdi), %r11 + addq 32(%rdi), %r12 + addq 40(%rdi), %r13 + addq 48(%rdi), %r14 + addq 56(%rdi), %r15 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq %r12, 32(%rdi) + movq %r13, 40(%rdi) + movq %r14, 48(%rdi) + movq %r15, 56(%rdi) + movq %r9, %rbx + xorq %rdx, %rdx + xorq %r10, %rbx + movq $5, %rbp +L_sha512_len_avx2_rorx_tail: + # rnd_all_2: 2-3 + rorxq $14, %r12, %rax + rorxq $18, %r12, %rcx + addq %rdx, %r8 + addq 16(%rsp), %r15 + movq %r13, %rdx + xorq %rax, %rcx + xorq %r14, %rdx + rorxq $41, %r12, %rax + xorq %rcx, %rax + andq %r12, %rdx + addq %rax, %r15 + rorxq $28, %r8, %rax + rorxq $34, %r8, %rcx + xorq %r14, %rdx + xorq %rax, %rcx + rorxq $39, %r8, %rax + addq %rdx, %r15 + xorq %rcx, %rax + movq %r9, %rdx + addq %r15, %r11 + xorq %r8, %rdx + andq %rdx, %rbx + addq %rax, %r15 + xorq %r9, %rbx + rorxq $14, %r11, %rax + rorxq $18, %r11, %rcx + addq %rbx, %r15 + addq 24(%rsp), %r14 + movq %r12, %rbx + xorq %rax, %rcx + xorq %r13, %rbx + rorxq $41, %r11, %rax + xorq %rcx, %rax + andq %r11, %rbx + addq %rax, %r14 + rorxq $28, %r15, %rax + rorxq $34, %r15, %rcx + xorq %r13, %rbx + xorq %rax, %rcx + rorxq $39, %r15, %rax + addq %rbx, %r14 + xorq %rcx, %rax + movq %r8, %rbx + leaq (%r10,%r14,1), %r10 + xorq %r15, %rbx + andq %rbx, %rdx + addq %rax, %r14 + xorq %r8, %rdx + # rnd_all_2: 6-7 + rorxq $14, %r10, %rax + rorxq $18, %r10, %rcx + addq %rdx, %r14 + addq 48(%rsp), %r13 + movq %r11, %rdx + xorq %rax, %rcx + xorq %r12, %rdx + rorxq $41, %r10, %rax + xorq %rcx, %rax + andq %r10, %rdx + addq %rax, %r13 + rorxq $28, %r14, %rax + rorxq $34, %r14, %rcx + xorq %r12, %rdx + xorq %rax, %rcx + rorxq $39, %r14, %rax + addq %rdx, %r13 + xorq %rcx, %rax + movq %r15, %rdx + addq %r13, %r9 + xorq %r14, %rdx + andq %rdx, %rbx + addq %rax, %r13 + xorq %r15, %rbx + rorxq $14, %r9, %rax + rorxq $18, %r9, %rcx + addq %rbx, %r13 + addq 56(%rsp), %r12 + movq %r10, %rbx + xorq %rax, %rcx + xorq %r11, %rbx + rorxq $41, %r9, %rax + xorq %rcx, %rax + andq %r9, %rbx + addq %rax, %r12 + rorxq $28, %r13, %rax + rorxq $34, %r13, %rcx + xorq %r11, %rbx + xorq %rax, %rcx + rorxq $39, %r13, %rax + addq %rbx, %r12 + xorq %rcx, %rax + movq %r14, %rbx + leaq (%r8,%r12,1), %r8 + xorq %r13, %rbx + andq %rbx, %rdx + addq %rax, %r12 + xorq %r14, %rdx + # rnd_all_2: 10-11 + rorxq $14, %r8, %rax + rorxq $18, %r8, %rcx + addq %rdx, %r12 + addq 80(%rsp), %r11 + movq %r9, %rdx + xorq %rax, %rcx + xorq %r10, %rdx + rorxq $41, %r8, %rax + xorq %rcx, %rax + andq %r8, %rdx + addq %rax, %r11 + rorxq $28, %r12, %rax + rorxq $34, %r12, %rcx + xorq %r10, %rdx + xorq %rax, %rcx + rorxq $39, %r12, %rax + addq %rdx, %r11 + xorq %rcx, %rax + movq %r13, %rdx + addq %r11, %r15 + xorq %r12, %rdx + andq %rdx, %rbx + addq %rax, %r11 + xorq %r13, %rbx + rorxq $14, %r15, %rax + rorxq $18, %r15, %rcx + addq %rbx, %r11 + addq 88(%rsp), %r10 + movq %r8, %rbx + xorq %rax, %rcx + xorq %r9, %rbx + rorxq $41, %r15, %rax + xorq %rcx, %rax + andq %r15, %rbx + addq %rax, %r10 + rorxq $28, %r11, %rax + rorxq $34, %r11, %rcx + xorq %r9, %rbx + xorq %rax, %rcx + rorxq $39, %r11, %rax + addq %rbx, %r10 + xorq %rcx, %rax + movq %r12, %rbx + leaq (%r14,%r10,1), %r14 + xorq %r11, %rbx + andq %rbx, %rdx + addq %rax, %r10 + xorq %r12, %rdx + # rnd_all_2: 14-15 + rorxq $14, %r14, %rax + rorxq $18, %r14, %rcx + addq %rdx, %r10 + addq 112(%rsp), %r9 + movq %r15, %rdx + xorq %rax, %rcx + xorq %r8, %rdx + rorxq $41, %r14, %rax + xorq %rcx, %rax + andq %r14, %rdx + addq %rax, %r9 + rorxq $28, %r10, %rax + rorxq $34, %r10, %rcx + xorq %r8, %rdx + xorq %rax, %rcx + rorxq $39, %r10, %rax + addq %rdx, %r9 + xorq %rcx, %rax + movq %r11, %rdx + addq %r9, %r13 + xorq %r10, %rdx + andq %rdx, %rbx + addq %rax, %r9 + xorq %r11, %rbx + rorxq $14, %r13, %rax + rorxq $18, %r13, %rcx + addq %rbx, %r9 + addq 120(%rsp), %r8 + movq %r14, %rbx + xorq %rax, %rcx + xorq %r15, %rbx + rorxq $41, %r13, %rax + xorq %rcx, %rax + andq %r13, %rbx + addq %rax, %r8 + rorxq $28, %r9, %rax + rorxq $34, %r9, %rcx + xorq %r15, %rbx + xorq %rax, %rcx + rorxq $39, %r9, %rax + addq %rbx, %r8 + xorq %rcx, %rax + movq %r10, %rbx + leaq (%r12,%r8,1), %r12 + xorq %r9, %rbx + andq %rbx, %rdx + addq %rax, %r8 + xorq %r10, %rdx + # rnd_all_2: 18-19 + rorxq $14, %r12, %rax + rorxq $18, %r12, %rcx + addq %rdx, %r8 + addq 144(%rsp), %r15 + movq %r13, %rdx + xorq %rax, %rcx + xorq %r14, %rdx + rorxq $41, %r12, %rax + xorq %rcx, %rax + andq %r12, %rdx + addq %rax, %r15 + rorxq $28, %r8, %rax + rorxq $34, %r8, %rcx + xorq %r14, %rdx + xorq %rax, %rcx + rorxq $39, %r8, %rax + addq %rdx, %r15 + xorq %rcx, %rax + movq %r9, %rdx + addq %r15, %r11 + xorq %r8, %rdx + andq %rdx, %rbx + addq %rax, %r15 + xorq %r9, %rbx + rorxq $14, %r11, %rax + rorxq $18, %r11, %rcx + addq %rbx, %r15 + addq 152(%rsp), %r14 + movq %r12, %rbx + xorq %rax, %rcx + xorq %r13, %rbx + rorxq $41, %r11, %rax + xorq %rcx, %rax + andq %r11, %rbx + addq %rax, %r14 + rorxq $28, %r15, %rax + rorxq $34, %r15, %rcx + xorq %r13, %rbx + xorq %rax, %rcx + rorxq $39, %r15, %rax + addq %rbx, %r14 + xorq %rcx, %rax + movq %r8, %rbx + leaq (%r10,%r14,1), %r10 + xorq %r15, %rbx + andq %rbx, %rdx + addq %rax, %r14 + xorq %r8, %rdx + # rnd_all_2: 22-23 + rorxq $14, %r10, %rax + rorxq $18, %r10, %rcx + addq %rdx, %r14 + addq 176(%rsp), %r13 + movq %r11, %rdx + xorq %rax, %rcx + xorq %r12, %rdx + rorxq $41, %r10, %rax + xorq %rcx, %rax + andq %r10, %rdx + addq %rax, %r13 + rorxq $28, %r14, %rax + rorxq $34, %r14, %rcx + xorq %r12, %rdx + xorq %rax, %rcx + rorxq $39, %r14, %rax + addq %rdx, %r13 + xorq %rcx, %rax + movq %r15, %rdx + addq %r13, %r9 + xorq %r14, %rdx + andq %rdx, %rbx + addq %rax, %r13 + xorq %r15, %rbx + rorxq $14, %r9, %rax + rorxq $18, %r9, %rcx + addq %rbx, %r13 + addq 184(%rsp), %r12 + movq %r10, %rbx + xorq %rax, %rcx + xorq %r11, %rbx + rorxq $41, %r9, %rax + xorq %rcx, %rax + andq %r9, %rbx + addq %rax, %r12 + rorxq $28, %r13, %rax + rorxq $34, %r13, %rcx + xorq %r11, %rbx + xorq %rax, %rcx + rorxq $39, %r13, %rax + addq %rbx, %r12 + xorq %rcx, %rax + movq %r14, %rbx + leaq (%r8,%r12,1), %r8 + xorq %r13, %rbx + andq %rbx, %rdx + addq %rax, %r12 + xorq %r14, %rdx + # rnd_all_2: 26-27 + rorxq $14, %r8, %rax + rorxq $18, %r8, %rcx + addq %rdx, %r12 + addq 208(%rsp), %r11 + movq %r9, %rdx + xorq %rax, %rcx + xorq %r10, %rdx + rorxq $41, %r8, %rax + xorq %rcx, %rax + andq %r8, %rdx + addq %rax, %r11 + rorxq $28, %r12, %rax + rorxq $34, %r12, %rcx + xorq %r10, %rdx + xorq %rax, %rcx + rorxq $39, %r12, %rax + addq %rdx, %r11 + xorq %rcx, %rax + movq %r13, %rdx + addq %r11, %r15 + xorq %r12, %rdx + andq %rdx, %rbx + addq %rax, %r11 + xorq %r13, %rbx + rorxq $14, %r15, %rax + rorxq $18, %r15, %rcx + addq %rbx, %r11 + addq 216(%rsp), %r10 + movq %r8, %rbx + xorq %rax, %rcx + xorq %r9, %rbx + rorxq $41, %r15, %rax + xorq %rcx, %rax + andq %r15, %rbx + addq %rax, %r10 + rorxq $28, %r11, %rax + rorxq $34, %r11, %rcx + xorq %r9, %rbx + xorq %rax, %rcx + rorxq $39, %r11, %rax + addq %rbx, %r10 + xorq %rcx, %rax + movq %r12, %rbx + leaq (%r14,%r10,1), %r14 + xorq %r11, %rbx + andq %rbx, %rdx + addq %rax, %r10 + xorq %r12, %rdx + # rnd_all_2: 30-31 + rorxq $14, %r14, %rax + rorxq $18, %r14, %rcx + addq %rdx, %r10 + addq 240(%rsp), %r9 + movq %r15, %rdx + xorq %rax, %rcx + xorq %r8, %rdx + rorxq $41, %r14, %rax + xorq %rcx, %rax + andq %r14, %rdx + addq %rax, %r9 + rorxq $28, %r10, %rax + rorxq $34, %r10, %rcx + xorq %r8, %rdx + xorq %rax, %rcx + rorxq $39, %r10, %rax + addq %rdx, %r9 + xorq %rcx, %rax + movq %r11, %rdx + addq %r9, %r13 + xorq %r10, %rdx + andq %rdx, %rbx + addq %rax, %r9 + xorq %r11, %rbx + rorxq $14, %r13, %rax + rorxq $18, %r13, %rcx + addq %rbx, %r9 + addq 248(%rsp), %r8 + movq %r14, %rbx + xorq %rax, %rcx + xorq %r15, %rbx + rorxq $41, %r13, %rax + xorq %rcx, %rax + andq %r13, %rbx + addq %rax, %r8 + rorxq $28, %r9, %rax + rorxq $34, %r9, %rcx + xorq %r15, %rbx + xorq %rax, %rcx + rorxq $39, %r9, %rax + addq %rbx, %r8 + xorq %rcx, %rax + movq %r10, %rbx + leaq (%r12,%r8,1), %r12 + xorq %r9, %rbx + andq %rbx, %rdx + addq %rax, %r8 + xorq %r10, %rdx + addq $0x100, %rsp + subq $0x01, %rbp + jnz L_sha512_len_avx2_rorx_tail + addq %rdx, %r8 + addq (%rdi), %r8 + addq 8(%rdi), %r9 + addq 16(%rdi), %r10 + addq 24(%rdi), %r11 + addq 32(%rdi), %r12 + addq 40(%rdi), %r13 + addq 48(%rdi), %r14 + addq 56(%rdi), %r15 + movq 224(%rdi), %rax + addq $0x40, %rsp + addq $0x100, %rax + subl $0x100, %esi + movq %rax, 224(%rdi) + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq %r12, 32(%rdi) + movq %r13, 40(%rdi) + movq %r14, 48(%rdi) + movq %r15, 56(%rdi) + jnz L_sha512_len_avx2_rorx_begin +L_sha512_len_avx2_rorx_done: + xorq %rax, %rax + vzeroupper + popq %rbp + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbx + repz retq +#ifndef __APPLE__ +.size Transform_Sha512_AVX2_RORX_Len,.-Transform_Sha512_AVX2_RORX_Len +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/signature.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/signature.c new file mode 100755 index 0000000..57d3275 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/signature.c @@ -0,0 +1,477 @@ +/* signature.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include +#include +#include +#include +#ifndef NO_ASN +#include +#endif +#ifdef HAVE_ECC +#include +#endif +#ifndef NO_RSA +#include +#endif + +/* If ECC and RSA are disabled then disable signature wrapper */ +#if (!defined(HAVE_ECC) || (defined(HAVE_ECC) && !defined(HAVE_ECC_SIGN) \ + && !defined(HAVE_ECC_VERIFY))) && defined(NO_RSA) + #undef NO_SIG_WRAPPER + #define NO_SIG_WRAPPER +#endif + +/* Signature wrapper disabled check */ +#ifndef NO_SIG_WRAPPER + +#if !defined(NO_RSA) && !defined(NO_ASN) +static int wc_SignatureDerEncode(enum wc_HashType hash_type, byte* hash_data, + word32 hash_len, word32* hash_enc_len) +{ + int ret, oid; + + ret = wc_HashGetOID(hash_type); + if (ret < 0) { + return ret; + } + oid = ret; + + ret = wc_EncodeSignature(hash_data, hash_data, hash_len, oid); + if (ret > 0) { + *hash_enc_len = ret; + ret = 0; + } + + return ret; +} +#endif /* !NO_RSA && !NO_ASN */ + +int wc_SignatureGetSize(enum wc_SignatureType sig_type, + const void* key, word32 key_len) +{ + int sig_len = BAD_FUNC_ARG; + + /* Suppress possible unused args if all signature types are disabled */ + (void)key; + (void)key_len; + + switch(sig_type) { + case WC_SIGNATURE_TYPE_ECC: +#ifdef HAVE_ECC + /* Sanity check that void* key is at least ecc_key in size */ + if (key_len >= sizeof(ecc_key)) { + sig_len = wc_ecc_sig_size((ecc_key*)key); + } + else { + WOLFSSL_MSG("wc_SignatureGetSize: Invalid ECC key size"); + } +#else + sig_len = SIG_TYPE_E; +#endif + break; + + case WC_SIGNATURE_TYPE_RSA_W_ENC: + case WC_SIGNATURE_TYPE_RSA: +#ifndef NO_RSA + /* Sanity check that void* key is at least RsaKey in size */ + if (key_len >= sizeof(RsaKey)) { + sig_len = wc_RsaEncryptSize((RsaKey*)key); + } + else { + WOLFSSL_MSG("wc_SignatureGetSize: Invalid RsaKey key size"); + } +#else + sig_len = SIG_TYPE_E; +#endif + break; + + case WC_SIGNATURE_TYPE_NONE: + default: + sig_len = BAD_FUNC_ARG; + break; + } + return sig_len; +} + +int wc_SignatureVerifyHash( + enum wc_HashType hash_type, enum wc_SignatureType sig_type, + const byte* hash_data, word32 hash_len, + const byte* sig, word32 sig_len, + const void* key, word32 key_len) +{ + int ret; + + /* Check arguments */ + if (hash_data == NULL || hash_len <= 0 || + sig == NULL || sig_len <= 0 || + key == NULL || key_len <= 0) { + return BAD_FUNC_ARG; + } + + /* Validate signature len (1 to max is okay) */ + if ((int)sig_len > wc_SignatureGetSize(sig_type, key, key_len)) { + WOLFSSL_MSG("wc_SignatureVerify: Invalid sig type/len"); + return BAD_FUNC_ARG; + } + + /* Validate hash size */ + ret = wc_HashGetDigestSize(hash_type); + if (ret < 0) { + WOLFSSL_MSG("wc_SignatureVerify: Invalid hash type/len"); + return ret; + } + ret = 0; + + /* Verify signature using hash */ + switch (sig_type) { + case WC_SIGNATURE_TYPE_ECC: + { +#if defined(HAVE_ECC) && defined(HAVE_ECC_VERIFY) + int is_valid_sig = 0; + + /* Perform verification of signature using provided ECC key */ + do { + #ifdef WOLFSSL_ASYNC_CRYPT + ret = wc_AsyncWait(ret, &((ecc_key*)key)->asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) + ret = wc_ecc_verify_hash(sig, sig_len, hash_data, hash_len, + &is_valid_sig, (ecc_key*)key); + } while (ret == WC_PENDING_E); + if (ret != 0 || is_valid_sig != 1) { + ret = SIG_VERIFY_E; + } +#else + ret = SIG_TYPE_E; +#endif + break; + } + + case WC_SIGNATURE_TYPE_RSA_W_ENC: + case WC_SIGNATURE_TYPE_RSA: + { +#ifndef NO_RSA +#if defined(WOLFSSL_CRYPTOCELL) + /* the signature must propagate to the cryptocell to get verfied */ + ret = wc_RsaSSL_Verify(hash_data, hash_len, (byte*)sig, sig_len, (RsaKey*)key); + if (ret != 0) { + WOLFSSL_MSG("RSA Signature Verify difference!"); + ret = SIG_VERIFY_E; + } + +#else /* WOLFSSL_CRYPTOCELL */ + + word32 plain_len = hash_len; + byte *plain_data; + + /* Make sure the plain text output is at least key size */ + if (plain_len < sig_len) { + plain_len = sig_len; + } + plain_data = (byte*)XMALLOC(plain_len, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (plain_data) { + /* Perform verification of signature using provided RSA key */ + do { + #ifdef WOLFSSL_ASYNC_CRYPT + ret = wc_AsyncWait(ret, &((RsaKey*)key)->asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) + ret = wc_RsaSSL_Verify(sig, sig_len, plain_data, + plain_len, (RsaKey*)key); + } while (ret == WC_PENDING_E); + if (ret >= 0) { + if ((word32)ret == hash_len && + XMEMCMP(plain_data, hash_data, hash_len) == 0) { + ret = 0; /* Success */ + } + else { + WOLFSSL_MSG("RSA Signature Verify difference!"); + ret = SIG_VERIFY_E; + } + } + XFREE(plain_data, NULL, DYNAMIC_TYPE_TMP_BUFFER); + } + else { + ret = MEMORY_E; + } +#endif /* !WOLFSSL_CRYPTOCELL */ +#else + ret = SIG_TYPE_E; +#endif + break; + } + + case WC_SIGNATURE_TYPE_NONE: + default: + ret = BAD_FUNC_ARG; + break; + } + + return ret; +} + +int wc_SignatureVerify( + enum wc_HashType hash_type, enum wc_SignatureType sig_type, + const byte* data, word32 data_len, + const byte* sig, word32 sig_len, + const void* key, word32 key_len) +{ + int ret; + word32 hash_len, hash_enc_len; +#ifdef WOLFSSL_SMALL_STACK + byte *hash_data; +#else + byte hash_data[MAX_DER_DIGEST_SZ]; +#endif + + /* Check arguments */ + if (data == NULL || data_len <= 0 || + sig == NULL || sig_len <= 0 || + key == NULL || key_len <= 0) { + return BAD_FUNC_ARG; + } + + /* Validate signature len (1 to max is okay) */ + if ((int)sig_len > wc_SignatureGetSize(sig_type, key, key_len)) { + WOLFSSL_MSG("wc_SignatureVerify: Invalid sig type/len"); + return BAD_FUNC_ARG; + } + + /* Validate hash size */ + ret = wc_HashGetDigestSize(hash_type); + if (ret < 0) { + WOLFSSL_MSG("wc_SignatureVerify: Invalid hash type/len"); + return ret; + } + hash_enc_len = hash_len = ret; + +#ifndef NO_RSA + if (sig_type == WC_SIGNATURE_TYPE_RSA_W_ENC) { + /* For RSA with ASN.1 encoding include room */ + hash_enc_len += MAX_DER_DIGEST_ASN_SZ; + } +#endif + +#ifdef WOLFSSL_SMALL_STACK + /* Allocate temporary buffer for hash data */ + hash_data = (byte*)XMALLOC(hash_enc_len, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (hash_data == NULL) { + return MEMORY_E; + } +#endif + + /* Perform hash of data */ + ret = wc_Hash(hash_type, data, data_len, hash_data, hash_len); + if (ret == 0) { + /* Handle RSA with DER encoding */ + if (sig_type == WC_SIGNATURE_TYPE_RSA_W_ENC) { + #if defined(NO_RSA) || defined(NO_ASN) + ret = SIG_TYPE_E; + #else + ret = wc_SignatureDerEncode(hash_type, hash_data, hash_len, + &hash_enc_len); + #endif + } + + if (ret == 0) { + /* Verify signature using hash */ + ret = wc_SignatureVerifyHash(hash_type, sig_type, + hash_data, hash_enc_len, sig, sig_len, key, key_len); + } + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(hash_data, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + + +int wc_SignatureGenerateHash( + enum wc_HashType hash_type, enum wc_SignatureType sig_type, + const byte* hash_data, word32 hash_len, + byte* sig, word32 *sig_len, + const void* key, word32 key_len, WC_RNG* rng) +{ + int ret; + + /* Suppress possible unused arg if all signature types are disabled */ + (void)rng; + + /* Check arguments */ + if (hash_data == NULL || hash_len <= 0 || + sig == NULL || sig_len == NULL || *sig_len <= 0 || + key == NULL || key_len <= 0) { + return BAD_FUNC_ARG; + } + + /* Validate signature len (needs to be at least max) */ + if ((int)*sig_len < wc_SignatureGetSize(sig_type, key, key_len)) { + WOLFSSL_MSG("wc_SignatureGenerate: Invalid sig type/len"); + return BAD_FUNC_ARG; + } + + /* Validate hash size */ + ret = wc_HashGetDigestSize(hash_type); + if (ret < 0) { + WOLFSSL_MSG("wc_SignatureGenerate: Invalid hash type/len"); + return ret; + } + ret = 0; + + /* Create signature using hash as data */ + switch (sig_type) { + case WC_SIGNATURE_TYPE_ECC: +#if defined(HAVE_ECC) && defined(HAVE_ECC_SIGN) + /* Create signature using provided ECC key */ + do { + #ifdef WOLFSSL_ASYNC_CRYPT + ret = wc_AsyncWait(ret, &((ecc_key*)key)->asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) + ret = wc_ecc_sign_hash(hash_data, hash_len, sig, sig_len, + rng, (ecc_key*)key); + } while (ret == WC_PENDING_E); +#else + ret = SIG_TYPE_E; +#endif + break; + + case WC_SIGNATURE_TYPE_RSA_W_ENC: + case WC_SIGNATURE_TYPE_RSA: +#if !defined(NO_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) + /* Create signature using provided RSA key */ + do { + #ifdef WOLFSSL_ASYNC_CRYPT + ret = wc_AsyncWait(ret, &((RsaKey*)key)->asyncDev, + WC_ASYNC_FLAG_CALL_AGAIN); + #endif + if (ret >= 0) + ret = wc_RsaSSL_Sign(hash_data, hash_len, sig, *sig_len, + (RsaKey*)key, rng); + } while (ret == WC_PENDING_E); + if (ret >= 0) { + *sig_len = ret; + ret = 0; /* Success */ + } +#else + ret = SIG_TYPE_E; +#endif + break; + + case WC_SIGNATURE_TYPE_NONE: + default: + ret = BAD_FUNC_ARG; + break; + } + + return ret; +} + +int wc_SignatureGenerate( + enum wc_HashType hash_type, enum wc_SignatureType sig_type, + const byte* data, word32 data_len, + byte* sig, word32 *sig_len, + const void* key, word32 key_len, WC_RNG* rng) +{ + int ret; + word32 hash_len, hash_enc_len; +#ifdef WOLFSSL_SMALL_STACK + byte *hash_data; +#else + byte hash_data[MAX_DER_DIGEST_SZ]; +#endif + + /* Check arguments */ + if (data == NULL || data_len <= 0 || + sig == NULL || sig_len == NULL || *sig_len <= 0 || + key == NULL || key_len <= 0) { + return BAD_FUNC_ARG; + } + + /* Validate signature len (needs to be at least max) */ + if ((int)*sig_len < wc_SignatureGetSize(sig_type, key, key_len)) { + WOLFSSL_MSG("wc_SignatureGenerate: Invalid sig type/len"); + return BAD_FUNC_ARG; + } + + /* Validate hash size */ + ret = wc_HashGetDigestSize(hash_type); + if (ret < 0) { + WOLFSSL_MSG("wc_SignatureGenerate: Invalid hash type/len"); + return ret; + } + hash_enc_len = hash_len = ret; + +#if !defined(NO_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) + if (sig_type == WC_SIGNATURE_TYPE_RSA_W_ENC) { + /* For RSA with ASN.1 encoding include room */ + hash_enc_len += MAX_DER_DIGEST_ASN_SZ; + } +#endif + +#ifdef WOLFSSL_SMALL_STACK + /* Allocate temporary buffer for hash data */ + hash_data = (byte*)XMALLOC(hash_enc_len, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (hash_data == NULL) { + return MEMORY_E; + } +#endif + + /* Perform hash of data */ + ret = wc_Hash(hash_type, data, data_len, hash_data, hash_len); + if (ret == 0) { + /* Handle RSA with DER encoding */ + if (sig_type == WC_SIGNATURE_TYPE_RSA_W_ENC) { + #if defined(NO_RSA) || defined(NO_ASN) || \ + defined(WOLFSSL_RSA_PUBLIC_ONLY) + ret = SIG_TYPE_E; + #else + ret = wc_SignatureDerEncode(hash_type, hash_data, hash_len, + &hash_enc_len); + #endif + } + + if (ret == 0) { + /* Generate signature using hash */ + ret = wc_SignatureGenerateHash(hash_type, sig_type, + hash_data, hash_enc_len, sig, sig_len, key, key_len, rng); + } + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(hash_data, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +#endif /* NO_SIG_WRAPPER */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/sp_arm32.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/sp_arm32.c new file mode 100755 index 0000000..47e82de --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/sp_arm32.c @@ -0,0 +1,25077 @@ +/* sp.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/* Implementation by Sean Parkinson. */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include +#include +#include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) || \ + defined(WOLFSSL_HAVE_SP_ECC) + +#ifdef RSA_LOW_MEM +#ifndef WOLFSSL_SP_SMALL +#define WOLFSSL_SP_SMALL +#endif +#endif + +#include + +#ifdef WOLFSSL_SP_ARM32_ASM +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) +#ifndef WOLFSSL_SP_NO_2048 +/* Read big endian unsigned byte aray into r. + * + * r A single precision integer. + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_2048_from_bin(sp_digit* r, int max, const byte* a, int n) +{ + int i, j = 0, s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= ((sp_digit)a[i]) << s; + if (s >= 24) { + r[j] &= 0xffffffff; + s = 32 - s; + if (j + 1 >= max) + break; + r[++j] = a[i] >> s; + s = 8 - s; + } + else + s += 8; + } + + for (j++; j < max; j++) + r[j] = 0; +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * a A multi-precision integer. + */ +static void sp_2048_from_mp(sp_digit* r, int max, mp_int* a) +{ +#if DIGIT_BIT == 32 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < max; j++) + r[j] = 0; +#elif DIGIT_BIT > 32 + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= a->dp[i] << s; + r[j] &= 0xffffffff; + s = 32 - s; + if (j + 1 >= max) + break; + r[++j] = a->dp[i] >> s; + while (s + 32 <= DIGIT_BIT) { + s += 32; + r[j] &= 0xffffffff; + if (j + 1 >= max) + break; + if (s < DIGIT_BIT) + r[++j] = a->dp[i] >> s; + else + r[++j] = 0; + } + s = DIGIT_BIT - s; + } + + for (j++; j < max; j++) + r[j] = 0; +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 32) { + r[j] &= 0xffffffff; + if (j + 1 >= max) + break; + s = 32 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else + s += DIGIT_BIT; + } + + for (j++; j < max; j++) + r[j] = 0; +#endif +} + +/* Write r as big endian to byte aray. + * Fixed length number of bytes written: 256 + * + * r A single precision integer. + * a Byte array. + */ +static void sp_2048_to_bin(sp_digit* r, byte* a) +{ + int i, j, s = 0, b; + + j = 2048 / 8 - 1; + a[j] = 0; + for (i=0; i<64 && j>=0; i++) { + b = 0; + a[j--] |= r[i] << s; b += 8 - s; + if (j < 0) + break; + while (b < 32) { + a[j--] = r[i] >> b; b += 8; + if (j < 0) + break; + } + s = 8 - (b - 32); + if (j >= 0) + a[j] = 0; + if (s != 0) + j++; + } +} + +#ifndef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_2048_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + __asm__ __volatile__ ( + "sub sp, sp, #32\n\t" + "mov r10, #0\n\t" + "# A[0] * B[0]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r3, r4, r8, r9\n\t" + "mov r5, #0\n\t" + "str r3, [sp]\n\t" + "# A[0] * B[1]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[1] * B[0]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #4]\n\t" + "# A[0] * B[2]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[1] * B[1]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[2] * B[0]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [sp, #8]\n\t" + "# A[0] * B[3]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[1] * B[2]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[2] * B[1]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[0]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [sp, #12]\n\t" + "# A[0] * B[4]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[1] * B[3]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[2] * B[2]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[3] * B[1]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[4] * B[0]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #16]\n\t" + "# A[0] * B[5]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[1] * B[4]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[2] * B[3]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[3] * B[2]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[4] * B[1]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[5] * B[0]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [sp, #20]\n\t" + "# A[0] * B[6]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[1] * B[5]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[2] * B[4]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[3]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[4] * B[2]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[5] * B[1]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[6] * B[0]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [sp, #24]\n\t" + "# A[0] * B[7]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[1] * B[6]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[2] * B[5]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[3] * B[4]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[4] * B[3]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[5] * B[2]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[6] * B[1]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[7] * B[0]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #28]\n\t" + "# A[1] * B[7]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[2] * B[6]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[3] * B[5]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[4] * B[4]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[5] * B[3]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[6] * B[2]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[7] * B[1]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #32]\n\t" + "# A[2] * B[7]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[3] * B[6]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[4] * B[5]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[5] * B[4]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[6] * B[3]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[7] * B[2]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #36]\n\t" + "# A[3] * B[7]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[4] * B[6]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[5] * B[5]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[6] * B[4]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[7] * B[3]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #40]\n\t" + "# A[4] * B[7]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[5] * B[6]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[6] * B[5]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[7] * B[4]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #44]\n\t" + "# A[5] * B[7]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[6] * B[6]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[7] * B[5]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #48]\n\t" + "# A[6] * B[7]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[7] * B[6]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #52]\n\t" + "# A[7] * B[7]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adc r3, r3, r7\n\t" + "str r5, [%[r], #56]\n\t" + "str r3, [%[r], #60]\n\t" + "ldr r3, [sp, #0]\n\t" + "ldr r4, [sp, #4]\n\t" + "ldr r5, [sp, #8]\n\t" + "ldr r6, [sp, #12]\n\t" + "str r3, [%[r], #0]\n\t" + "str r4, [%[r], #4]\n\t" + "str r5, [%[r], #8]\n\t" + "str r6, [%[r], #12]\n\t" + "ldr r3, [sp, #16]\n\t" + "ldr r4, [sp, #20]\n\t" + "ldr r5, [sp, #24]\n\t" + "ldr r6, [sp, #28]\n\t" + "str r3, [%[r], #16]\n\t" + "str r4, [%[r], #20]\n\t" + "str r5, [%[r], #24]\n\t" + "str r6, [%[r], #28]\n\t" + "add sp, sp, #32\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10" + ); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_2048_sqr_8(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "sub sp, sp, #32\n\t" + "mov r14, #0\n\t" + "# A[0] * A[0]\n\t" + "ldr r10, [%[a], #0]\n\t" + "umull r8, r3, r10, r10\n\t" + "mov r4, #0\n\t" + "str r8, [sp]\n\t" + "# A[0] * A[1]\n\t" + "ldr r10, [%[a], #4]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r14, r14\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "str r3, [sp, #4]\n\t" + "# A[0] * A[2]\n\t" + "ldr r10, [%[a], #8]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r14, r14\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r14\n\t" + "# A[1] * A[1]\n\t" + "ldr r10, [%[a], #4]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r14\n\t" + "str r4, [sp, #8]\n\t" + "# A[0] * A[3]\n\t" + "ldr r10, [%[a], #12]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r14, r14\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r14\n\t" + "# A[1] * A[2]\n\t" + "ldr r10, [%[a], #8]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r14\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r14\n\t" + "str r2, [sp, #12]\n\t" + "# A[0] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r14, r14\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "# A[1] * A[3]\n\t" + "ldr r10, [%[a], #12]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "# A[2] * A[2]\n\t" + "ldr r10, [%[a], #8]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "str r3, [sp, #16]\n\t" + "# A[0] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[3]\n\t" + "ldr r10, [%[a], #12]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [sp, #20]\n\t" + "# A[0] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[3]\n\t" + "ldr r10, [%[a], #12]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [sp, #24]\n\t" + "# A[0] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [sp, #28]\n\t" + "# A[1] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[2] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [%[r], #32]\n\t" + "# A[2] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[3] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [%[r], #36]\n\t" + "# A[3] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r14, r14\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "# A[4] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "# A[5] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "str r3, [%[r], #40]\n\t" + "# A[4] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r14, r14\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r14\n\t" + "# A[5] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r14\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r14\n\t" + "str r4, [%[r], #44]\n\t" + "# A[5] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r14, r14\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r14\n\t" + "# A[6] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r14\n\t" + "str r2, [%[r], #48]\n\t" + "# A[6] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r14, r14\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "str r3, [%[r], #52]\n\t" + "# A[7] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r4, r4, r8\n\t" + "adc r2, r2, r9\n\t" + "str r4, [%[r], #56]\n\t" + "str r2, [%[r], #60]\n\t" + "ldr r2, [sp, #0]\n\t" + "ldr r3, [sp, #4]\n\t" + "ldr r4, [sp, #8]\n\t" + "ldr r8, [sp, #12]\n\t" + "str r2, [%[r], #0]\n\t" + "str r3, [%[r], #4]\n\t" + "str r4, [%[r], #8]\n\t" + "str r8, [%[r], #12]\n\t" + "ldr r2, [sp, #16]\n\t" + "ldr r3, [sp, #20]\n\t" + "ldr r4, [sp, #24]\n\t" + "ldr r8, [sp, #28]\n\t" + "str r2, [%[r], #16]\n\t" + "str r3, [%[r], #20]\n\t" + "str r4, [%[r], #24]\n\t" + "str r8, [%[r], #28]\n\t" + "add sp, sp, #32\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r8", "r9", "r10", "r8", "r5", "r6", "r7", "r14" + ); +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_2048_add_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r12, #0\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[a], #4]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #12]\n\t" + "ldr r8, [%[b], #0]\n\t" + "ldr r9, [%[b], #4]\n\t" + "ldr r10, [%[b], #8]\n\t" + "ldr r14, [%[b], #12]\n\t" + "adds r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #0]\n\t" + "str r5, [%[r], #4]\n\t" + "str r6, [%[r], #8]\n\t" + "str r7, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[a], #20]\n\t" + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[a], #28]\n\t" + "ldr r8, [%[b], #16]\n\t" + "ldr r9, [%[b], #20]\n\t" + "ldr r10, [%[b], #24]\n\t" + "ldr r14, [%[b], #28]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #16]\n\t" + "str r5, [%[r], #20]\n\t" + "str r6, [%[r], #24]\n\t" + "str r7, [%[r], #28]\n\t" + "adc %[c], r12, r12\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + return c; +} + +/* Sub b from a into a. (a -= b) + * + * a A single precision integer and result. + * b A single precision integer. + */ +static sp_digit sp_2048_sub_in_place_16(sp_digit* a, const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r2, [%[a], #0]\n\t" + "ldr r3, [%[a], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[a], #12]\n\t" + "ldr r6, [%[b], #0]\n\t" + "ldr r7, [%[b], #4]\n\t" + "ldr r8, [%[b], #8]\n\t" + "ldr r9, [%[b], #12]\n\t" + "subs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #0]\n\t" + "str r3, [%[a], #4]\n\t" + "str r4, [%[a], #8]\n\t" + "str r5, [%[a], #12]\n\t" + "ldr r2, [%[a], #16]\n\t" + "ldr r3, [%[a], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[a], #28]\n\t" + "ldr r6, [%[b], #16]\n\t" + "ldr r7, [%[b], #20]\n\t" + "ldr r8, [%[b], #24]\n\t" + "ldr r9, [%[b], #28]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #16]\n\t" + "str r3, [%[a], #20]\n\t" + "str r4, [%[a], #24]\n\t" + "str r5, [%[a], #28]\n\t" + "ldr r2, [%[a], #32]\n\t" + "ldr r3, [%[a], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[a], #44]\n\t" + "ldr r6, [%[b], #32]\n\t" + "ldr r7, [%[b], #36]\n\t" + "ldr r8, [%[b], #40]\n\t" + "ldr r9, [%[b], #44]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #32]\n\t" + "str r3, [%[a], #36]\n\t" + "str r4, [%[a], #40]\n\t" + "str r5, [%[a], #44]\n\t" + "ldr r2, [%[a], #48]\n\t" + "ldr r3, [%[a], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[a], #60]\n\t" + "ldr r6, [%[b], #48]\n\t" + "ldr r7, [%[b], #52]\n\t" + "ldr r8, [%[b], #56]\n\t" + "ldr r9, [%[b], #60]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #48]\n\t" + "str r3, [%[a], #52]\n\t" + "str r4, [%[a], #56]\n\t" + "str r5, [%[a], #60]\n\t" + "sbc %[c], r9, r9\n\t" + : [c] "+r" (c) + : [a] "r" (a), [b] "r" (b) + : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9" + ); + + return c; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_2048_add_16(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r12, #0\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[a], #4]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #12]\n\t" + "ldr r8, [%[b], #0]\n\t" + "ldr r9, [%[b], #4]\n\t" + "ldr r10, [%[b], #8]\n\t" + "ldr r14, [%[b], #12]\n\t" + "adds r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #0]\n\t" + "str r5, [%[r], #4]\n\t" + "str r6, [%[r], #8]\n\t" + "str r7, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[a], #20]\n\t" + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[a], #28]\n\t" + "ldr r8, [%[b], #16]\n\t" + "ldr r9, [%[b], #20]\n\t" + "ldr r10, [%[b], #24]\n\t" + "ldr r14, [%[b], #28]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #16]\n\t" + "str r5, [%[r], #20]\n\t" + "str r6, [%[r], #24]\n\t" + "str r7, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[a], #36]\n\t" + "ldr r6, [%[a], #40]\n\t" + "ldr r7, [%[a], #44]\n\t" + "ldr r8, [%[b], #32]\n\t" + "ldr r9, [%[b], #36]\n\t" + "ldr r10, [%[b], #40]\n\t" + "ldr r14, [%[b], #44]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #32]\n\t" + "str r5, [%[r], #36]\n\t" + "str r6, [%[r], #40]\n\t" + "str r7, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[a], #52]\n\t" + "ldr r6, [%[a], #56]\n\t" + "ldr r7, [%[a], #60]\n\t" + "ldr r8, [%[b], #48]\n\t" + "ldr r9, [%[b], #52]\n\t" + "ldr r10, [%[b], #56]\n\t" + "ldr r14, [%[b], #60]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #48]\n\t" + "str r5, [%[r], #52]\n\t" + "str r6, [%[r], #56]\n\t" + "str r7, [%[r], #60]\n\t" + "adc %[c], r12, r12\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + return c; +} + +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_2048_mask_8(sp_digit* r, sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<8; i++) + r[i] = a[i] & m; +#else + r[0] = a[0] & m; + r[1] = a[1] & m; + r[2] = a[2] & m; + r[3] = a[3] & m; + r[4] = a[4] & m; + r[5] = a[5] & m; + r[6] = a[6] & m; + r[7] = a[7] & m; +#endif +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_2048_mul_16(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[16]; + sp_digit a1[8]; + sp_digit b1[8]; + sp_digit z2[16]; + sp_digit u, ca, cb; + + ca = sp_2048_add_8(a1, a, &a[8]); + cb = sp_2048_add_8(b1, b, &b[8]); + u = ca & cb; + sp_2048_mul_8(z1, a1, b1); + sp_2048_mul_8(z2, &a[8], &b[8]); + sp_2048_mul_8(z0, a, b); + sp_2048_mask_8(r + 16, a1, 0 - cb); + sp_2048_mask_8(b1, b1, 0 - ca); + u += sp_2048_add_8(r + 16, r + 16, b1); + u += sp_2048_sub_in_place_16(z1, z2); + u += sp_2048_sub_in_place_16(z1, z0); + u += sp_2048_add_16(r + 8, r + 8, z1); + r[24] = u; + XMEMSET(r + 24 + 1, 0, sizeof(sp_digit) * (8 - 1)); + sp_2048_add_16(r + 16, r + 16, z2); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_2048_sqr_16(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z2[16]; + sp_digit z1[16]; + sp_digit a1[8]; + sp_digit u; + + u = sp_2048_add_8(a1, a, &a[8]); + sp_2048_sqr_8(z1, a1); + sp_2048_sqr_8(z2, &a[8]); + sp_2048_sqr_8(z0, a); + sp_2048_mask_8(r + 16, a1, 0 - u); + u += sp_2048_add_8(r + 16, r + 16, r + 16); + u += sp_2048_sub_in_place_16(z1, z2); + u += sp_2048_sub_in_place_16(z1, z0); + u += sp_2048_add_16(r + 8, r + 8, z1); + r[24] = u; + XMEMSET(r + 24 + 1, 0, sizeof(sp_digit) * (8 - 1)); + sp_2048_add_16(r + 16, r + 16, z2); +} + +/* Sub b from a into a. (a -= b) + * + * a A single precision integer and result. + * b A single precision integer. + */ +static sp_digit sp_2048_sub_in_place_32(sp_digit* a, const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r2, [%[a], #0]\n\t" + "ldr r3, [%[a], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[a], #12]\n\t" + "ldr r6, [%[b], #0]\n\t" + "ldr r7, [%[b], #4]\n\t" + "ldr r8, [%[b], #8]\n\t" + "ldr r9, [%[b], #12]\n\t" + "subs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #0]\n\t" + "str r3, [%[a], #4]\n\t" + "str r4, [%[a], #8]\n\t" + "str r5, [%[a], #12]\n\t" + "ldr r2, [%[a], #16]\n\t" + "ldr r3, [%[a], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[a], #28]\n\t" + "ldr r6, [%[b], #16]\n\t" + "ldr r7, [%[b], #20]\n\t" + "ldr r8, [%[b], #24]\n\t" + "ldr r9, [%[b], #28]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #16]\n\t" + "str r3, [%[a], #20]\n\t" + "str r4, [%[a], #24]\n\t" + "str r5, [%[a], #28]\n\t" + "ldr r2, [%[a], #32]\n\t" + "ldr r3, [%[a], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[a], #44]\n\t" + "ldr r6, [%[b], #32]\n\t" + "ldr r7, [%[b], #36]\n\t" + "ldr r8, [%[b], #40]\n\t" + "ldr r9, [%[b], #44]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #32]\n\t" + "str r3, [%[a], #36]\n\t" + "str r4, [%[a], #40]\n\t" + "str r5, [%[a], #44]\n\t" + "ldr r2, [%[a], #48]\n\t" + "ldr r3, [%[a], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[a], #60]\n\t" + "ldr r6, [%[b], #48]\n\t" + "ldr r7, [%[b], #52]\n\t" + "ldr r8, [%[b], #56]\n\t" + "ldr r9, [%[b], #60]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #48]\n\t" + "str r3, [%[a], #52]\n\t" + "str r4, [%[a], #56]\n\t" + "str r5, [%[a], #60]\n\t" + "ldr r2, [%[a], #64]\n\t" + "ldr r3, [%[a], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[a], #76]\n\t" + "ldr r6, [%[b], #64]\n\t" + "ldr r7, [%[b], #68]\n\t" + "ldr r8, [%[b], #72]\n\t" + "ldr r9, [%[b], #76]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #64]\n\t" + "str r3, [%[a], #68]\n\t" + "str r4, [%[a], #72]\n\t" + "str r5, [%[a], #76]\n\t" + "ldr r2, [%[a], #80]\n\t" + "ldr r3, [%[a], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[a], #92]\n\t" + "ldr r6, [%[b], #80]\n\t" + "ldr r7, [%[b], #84]\n\t" + "ldr r8, [%[b], #88]\n\t" + "ldr r9, [%[b], #92]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #80]\n\t" + "str r3, [%[a], #84]\n\t" + "str r4, [%[a], #88]\n\t" + "str r5, [%[a], #92]\n\t" + "ldr r2, [%[a], #96]\n\t" + "ldr r3, [%[a], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[a], #108]\n\t" + "ldr r6, [%[b], #96]\n\t" + "ldr r7, [%[b], #100]\n\t" + "ldr r8, [%[b], #104]\n\t" + "ldr r9, [%[b], #108]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #96]\n\t" + "str r3, [%[a], #100]\n\t" + "str r4, [%[a], #104]\n\t" + "str r5, [%[a], #108]\n\t" + "ldr r2, [%[a], #112]\n\t" + "ldr r3, [%[a], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[a], #124]\n\t" + "ldr r6, [%[b], #112]\n\t" + "ldr r7, [%[b], #116]\n\t" + "ldr r8, [%[b], #120]\n\t" + "ldr r9, [%[b], #124]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #112]\n\t" + "str r3, [%[a], #116]\n\t" + "str r4, [%[a], #120]\n\t" + "str r5, [%[a], #124]\n\t" + "sbc %[c], r9, r9\n\t" + : [c] "+r" (c) + : [a] "r" (a), [b] "r" (b) + : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9" + ); + + return c; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_2048_add_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r12, #0\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[a], #4]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #12]\n\t" + "ldr r8, [%[b], #0]\n\t" + "ldr r9, [%[b], #4]\n\t" + "ldr r10, [%[b], #8]\n\t" + "ldr r14, [%[b], #12]\n\t" + "adds r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #0]\n\t" + "str r5, [%[r], #4]\n\t" + "str r6, [%[r], #8]\n\t" + "str r7, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[a], #20]\n\t" + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[a], #28]\n\t" + "ldr r8, [%[b], #16]\n\t" + "ldr r9, [%[b], #20]\n\t" + "ldr r10, [%[b], #24]\n\t" + "ldr r14, [%[b], #28]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #16]\n\t" + "str r5, [%[r], #20]\n\t" + "str r6, [%[r], #24]\n\t" + "str r7, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[a], #36]\n\t" + "ldr r6, [%[a], #40]\n\t" + "ldr r7, [%[a], #44]\n\t" + "ldr r8, [%[b], #32]\n\t" + "ldr r9, [%[b], #36]\n\t" + "ldr r10, [%[b], #40]\n\t" + "ldr r14, [%[b], #44]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #32]\n\t" + "str r5, [%[r], #36]\n\t" + "str r6, [%[r], #40]\n\t" + "str r7, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[a], #52]\n\t" + "ldr r6, [%[a], #56]\n\t" + "ldr r7, [%[a], #60]\n\t" + "ldr r8, [%[b], #48]\n\t" + "ldr r9, [%[b], #52]\n\t" + "ldr r10, [%[b], #56]\n\t" + "ldr r14, [%[b], #60]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #48]\n\t" + "str r5, [%[r], #52]\n\t" + "str r6, [%[r], #56]\n\t" + "str r7, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[a], #68]\n\t" + "ldr r6, [%[a], #72]\n\t" + "ldr r7, [%[a], #76]\n\t" + "ldr r8, [%[b], #64]\n\t" + "ldr r9, [%[b], #68]\n\t" + "ldr r10, [%[b], #72]\n\t" + "ldr r14, [%[b], #76]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #64]\n\t" + "str r5, [%[r], #68]\n\t" + "str r6, [%[r], #72]\n\t" + "str r7, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[a], #84]\n\t" + "ldr r6, [%[a], #88]\n\t" + "ldr r7, [%[a], #92]\n\t" + "ldr r8, [%[b], #80]\n\t" + "ldr r9, [%[b], #84]\n\t" + "ldr r10, [%[b], #88]\n\t" + "ldr r14, [%[b], #92]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #80]\n\t" + "str r5, [%[r], #84]\n\t" + "str r6, [%[r], #88]\n\t" + "str r7, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[a], #100]\n\t" + "ldr r6, [%[a], #104]\n\t" + "ldr r7, [%[a], #108]\n\t" + "ldr r8, [%[b], #96]\n\t" + "ldr r9, [%[b], #100]\n\t" + "ldr r10, [%[b], #104]\n\t" + "ldr r14, [%[b], #108]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #96]\n\t" + "str r5, [%[r], #100]\n\t" + "str r6, [%[r], #104]\n\t" + "str r7, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[a], #116]\n\t" + "ldr r6, [%[a], #120]\n\t" + "ldr r7, [%[a], #124]\n\t" + "ldr r8, [%[b], #112]\n\t" + "ldr r9, [%[b], #116]\n\t" + "ldr r10, [%[b], #120]\n\t" + "ldr r14, [%[b], #124]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #112]\n\t" + "str r5, [%[r], #116]\n\t" + "str r6, [%[r], #120]\n\t" + "str r7, [%[r], #124]\n\t" + "adc %[c], r12, r12\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + return c; +} + +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_2048_mask_16(sp_digit* r, sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<16; i++) + r[i] = a[i] & m; +#else + int i; + + for (i = 0; i < 16; i += 8) { + r[i+0] = a[i+0] & m; + r[i+1] = a[i+1] & m; + r[i+2] = a[i+2] & m; + r[i+3] = a[i+3] & m; + r[i+4] = a[i+4] & m; + r[i+5] = a[i+5] & m; + r[i+6] = a[i+6] & m; + r[i+7] = a[i+7] & m; + } +#endif +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_2048_mul_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[32]; + sp_digit a1[16]; + sp_digit b1[16]; + sp_digit z2[32]; + sp_digit u, ca, cb; + + ca = sp_2048_add_16(a1, a, &a[16]); + cb = sp_2048_add_16(b1, b, &b[16]); + u = ca & cb; + sp_2048_mul_16(z1, a1, b1); + sp_2048_mul_16(z2, &a[16], &b[16]); + sp_2048_mul_16(z0, a, b); + sp_2048_mask_16(r + 32, a1, 0 - cb); + sp_2048_mask_16(b1, b1, 0 - ca); + u += sp_2048_add_16(r + 32, r + 32, b1); + u += sp_2048_sub_in_place_32(z1, z2); + u += sp_2048_sub_in_place_32(z1, z0); + u += sp_2048_add_32(r + 16, r + 16, z1); + r[48] = u; + XMEMSET(r + 48 + 1, 0, sizeof(sp_digit) * (16 - 1)); + sp_2048_add_32(r + 32, r + 32, z2); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_2048_sqr_32(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z2[32]; + sp_digit z1[32]; + sp_digit a1[16]; + sp_digit u; + + u = sp_2048_add_16(a1, a, &a[16]); + sp_2048_sqr_16(z1, a1); + sp_2048_sqr_16(z2, &a[16]); + sp_2048_sqr_16(z0, a); + sp_2048_mask_16(r + 32, a1, 0 - u); + u += sp_2048_add_16(r + 32, r + 32, r + 32); + u += sp_2048_sub_in_place_32(z1, z2); + u += sp_2048_sub_in_place_32(z1, z0); + u += sp_2048_add_32(r + 16, r + 16, z1); + r[48] = u; + XMEMSET(r + 48 + 1, 0, sizeof(sp_digit) * (16 - 1)); + sp_2048_add_32(r + 32, r + 32, z2); +} + +/* Sub b from a into a. (a -= b) + * + * a A single precision integer and result. + * b A single precision integer. + */ +static sp_digit sp_2048_sub_in_place_64(sp_digit* a, const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r2, [%[a], #0]\n\t" + "ldr r3, [%[a], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[a], #12]\n\t" + "ldr r6, [%[b], #0]\n\t" + "ldr r7, [%[b], #4]\n\t" + "ldr r8, [%[b], #8]\n\t" + "ldr r9, [%[b], #12]\n\t" + "subs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #0]\n\t" + "str r3, [%[a], #4]\n\t" + "str r4, [%[a], #8]\n\t" + "str r5, [%[a], #12]\n\t" + "ldr r2, [%[a], #16]\n\t" + "ldr r3, [%[a], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[a], #28]\n\t" + "ldr r6, [%[b], #16]\n\t" + "ldr r7, [%[b], #20]\n\t" + "ldr r8, [%[b], #24]\n\t" + "ldr r9, [%[b], #28]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #16]\n\t" + "str r3, [%[a], #20]\n\t" + "str r4, [%[a], #24]\n\t" + "str r5, [%[a], #28]\n\t" + "ldr r2, [%[a], #32]\n\t" + "ldr r3, [%[a], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[a], #44]\n\t" + "ldr r6, [%[b], #32]\n\t" + "ldr r7, [%[b], #36]\n\t" + "ldr r8, [%[b], #40]\n\t" + "ldr r9, [%[b], #44]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #32]\n\t" + "str r3, [%[a], #36]\n\t" + "str r4, [%[a], #40]\n\t" + "str r5, [%[a], #44]\n\t" + "ldr r2, [%[a], #48]\n\t" + "ldr r3, [%[a], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[a], #60]\n\t" + "ldr r6, [%[b], #48]\n\t" + "ldr r7, [%[b], #52]\n\t" + "ldr r8, [%[b], #56]\n\t" + "ldr r9, [%[b], #60]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #48]\n\t" + "str r3, [%[a], #52]\n\t" + "str r4, [%[a], #56]\n\t" + "str r5, [%[a], #60]\n\t" + "ldr r2, [%[a], #64]\n\t" + "ldr r3, [%[a], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[a], #76]\n\t" + "ldr r6, [%[b], #64]\n\t" + "ldr r7, [%[b], #68]\n\t" + "ldr r8, [%[b], #72]\n\t" + "ldr r9, [%[b], #76]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #64]\n\t" + "str r3, [%[a], #68]\n\t" + "str r4, [%[a], #72]\n\t" + "str r5, [%[a], #76]\n\t" + "ldr r2, [%[a], #80]\n\t" + "ldr r3, [%[a], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[a], #92]\n\t" + "ldr r6, [%[b], #80]\n\t" + "ldr r7, [%[b], #84]\n\t" + "ldr r8, [%[b], #88]\n\t" + "ldr r9, [%[b], #92]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #80]\n\t" + "str r3, [%[a], #84]\n\t" + "str r4, [%[a], #88]\n\t" + "str r5, [%[a], #92]\n\t" + "ldr r2, [%[a], #96]\n\t" + "ldr r3, [%[a], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[a], #108]\n\t" + "ldr r6, [%[b], #96]\n\t" + "ldr r7, [%[b], #100]\n\t" + "ldr r8, [%[b], #104]\n\t" + "ldr r9, [%[b], #108]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #96]\n\t" + "str r3, [%[a], #100]\n\t" + "str r4, [%[a], #104]\n\t" + "str r5, [%[a], #108]\n\t" + "ldr r2, [%[a], #112]\n\t" + "ldr r3, [%[a], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[a], #124]\n\t" + "ldr r6, [%[b], #112]\n\t" + "ldr r7, [%[b], #116]\n\t" + "ldr r8, [%[b], #120]\n\t" + "ldr r9, [%[b], #124]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #112]\n\t" + "str r3, [%[a], #116]\n\t" + "str r4, [%[a], #120]\n\t" + "str r5, [%[a], #124]\n\t" + "ldr r2, [%[a], #128]\n\t" + "ldr r3, [%[a], #132]\n\t" + "ldr r4, [%[a], #136]\n\t" + "ldr r5, [%[a], #140]\n\t" + "ldr r6, [%[b], #128]\n\t" + "ldr r7, [%[b], #132]\n\t" + "ldr r8, [%[b], #136]\n\t" + "ldr r9, [%[b], #140]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #128]\n\t" + "str r3, [%[a], #132]\n\t" + "str r4, [%[a], #136]\n\t" + "str r5, [%[a], #140]\n\t" + "ldr r2, [%[a], #144]\n\t" + "ldr r3, [%[a], #148]\n\t" + "ldr r4, [%[a], #152]\n\t" + "ldr r5, [%[a], #156]\n\t" + "ldr r6, [%[b], #144]\n\t" + "ldr r7, [%[b], #148]\n\t" + "ldr r8, [%[b], #152]\n\t" + "ldr r9, [%[b], #156]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #144]\n\t" + "str r3, [%[a], #148]\n\t" + "str r4, [%[a], #152]\n\t" + "str r5, [%[a], #156]\n\t" + "ldr r2, [%[a], #160]\n\t" + "ldr r3, [%[a], #164]\n\t" + "ldr r4, [%[a], #168]\n\t" + "ldr r5, [%[a], #172]\n\t" + "ldr r6, [%[b], #160]\n\t" + "ldr r7, [%[b], #164]\n\t" + "ldr r8, [%[b], #168]\n\t" + "ldr r9, [%[b], #172]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #160]\n\t" + "str r3, [%[a], #164]\n\t" + "str r4, [%[a], #168]\n\t" + "str r5, [%[a], #172]\n\t" + "ldr r2, [%[a], #176]\n\t" + "ldr r3, [%[a], #180]\n\t" + "ldr r4, [%[a], #184]\n\t" + "ldr r5, [%[a], #188]\n\t" + "ldr r6, [%[b], #176]\n\t" + "ldr r7, [%[b], #180]\n\t" + "ldr r8, [%[b], #184]\n\t" + "ldr r9, [%[b], #188]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #176]\n\t" + "str r3, [%[a], #180]\n\t" + "str r4, [%[a], #184]\n\t" + "str r5, [%[a], #188]\n\t" + "ldr r2, [%[a], #192]\n\t" + "ldr r3, [%[a], #196]\n\t" + "ldr r4, [%[a], #200]\n\t" + "ldr r5, [%[a], #204]\n\t" + "ldr r6, [%[b], #192]\n\t" + "ldr r7, [%[b], #196]\n\t" + "ldr r8, [%[b], #200]\n\t" + "ldr r9, [%[b], #204]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #192]\n\t" + "str r3, [%[a], #196]\n\t" + "str r4, [%[a], #200]\n\t" + "str r5, [%[a], #204]\n\t" + "ldr r2, [%[a], #208]\n\t" + "ldr r3, [%[a], #212]\n\t" + "ldr r4, [%[a], #216]\n\t" + "ldr r5, [%[a], #220]\n\t" + "ldr r6, [%[b], #208]\n\t" + "ldr r7, [%[b], #212]\n\t" + "ldr r8, [%[b], #216]\n\t" + "ldr r9, [%[b], #220]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #208]\n\t" + "str r3, [%[a], #212]\n\t" + "str r4, [%[a], #216]\n\t" + "str r5, [%[a], #220]\n\t" + "ldr r2, [%[a], #224]\n\t" + "ldr r3, [%[a], #228]\n\t" + "ldr r4, [%[a], #232]\n\t" + "ldr r5, [%[a], #236]\n\t" + "ldr r6, [%[b], #224]\n\t" + "ldr r7, [%[b], #228]\n\t" + "ldr r8, [%[b], #232]\n\t" + "ldr r9, [%[b], #236]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #224]\n\t" + "str r3, [%[a], #228]\n\t" + "str r4, [%[a], #232]\n\t" + "str r5, [%[a], #236]\n\t" + "ldr r2, [%[a], #240]\n\t" + "ldr r3, [%[a], #244]\n\t" + "ldr r4, [%[a], #248]\n\t" + "ldr r5, [%[a], #252]\n\t" + "ldr r6, [%[b], #240]\n\t" + "ldr r7, [%[b], #244]\n\t" + "ldr r8, [%[b], #248]\n\t" + "ldr r9, [%[b], #252]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #240]\n\t" + "str r3, [%[a], #244]\n\t" + "str r4, [%[a], #248]\n\t" + "str r5, [%[a], #252]\n\t" + "sbc %[c], r9, r9\n\t" + : [c] "+r" (c) + : [a] "r" (a), [b] "r" (b) + : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9" + ); + + return c; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_2048_add_64(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r12, #0\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[a], #4]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #12]\n\t" + "ldr r8, [%[b], #0]\n\t" + "ldr r9, [%[b], #4]\n\t" + "ldr r10, [%[b], #8]\n\t" + "ldr r14, [%[b], #12]\n\t" + "adds r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #0]\n\t" + "str r5, [%[r], #4]\n\t" + "str r6, [%[r], #8]\n\t" + "str r7, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[a], #20]\n\t" + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[a], #28]\n\t" + "ldr r8, [%[b], #16]\n\t" + "ldr r9, [%[b], #20]\n\t" + "ldr r10, [%[b], #24]\n\t" + "ldr r14, [%[b], #28]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #16]\n\t" + "str r5, [%[r], #20]\n\t" + "str r6, [%[r], #24]\n\t" + "str r7, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[a], #36]\n\t" + "ldr r6, [%[a], #40]\n\t" + "ldr r7, [%[a], #44]\n\t" + "ldr r8, [%[b], #32]\n\t" + "ldr r9, [%[b], #36]\n\t" + "ldr r10, [%[b], #40]\n\t" + "ldr r14, [%[b], #44]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #32]\n\t" + "str r5, [%[r], #36]\n\t" + "str r6, [%[r], #40]\n\t" + "str r7, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[a], #52]\n\t" + "ldr r6, [%[a], #56]\n\t" + "ldr r7, [%[a], #60]\n\t" + "ldr r8, [%[b], #48]\n\t" + "ldr r9, [%[b], #52]\n\t" + "ldr r10, [%[b], #56]\n\t" + "ldr r14, [%[b], #60]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #48]\n\t" + "str r5, [%[r], #52]\n\t" + "str r6, [%[r], #56]\n\t" + "str r7, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[a], #68]\n\t" + "ldr r6, [%[a], #72]\n\t" + "ldr r7, [%[a], #76]\n\t" + "ldr r8, [%[b], #64]\n\t" + "ldr r9, [%[b], #68]\n\t" + "ldr r10, [%[b], #72]\n\t" + "ldr r14, [%[b], #76]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #64]\n\t" + "str r5, [%[r], #68]\n\t" + "str r6, [%[r], #72]\n\t" + "str r7, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[a], #84]\n\t" + "ldr r6, [%[a], #88]\n\t" + "ldr r7, [%[a], #92]\n\t" + "ldr r8, [%[b], #80]\n\t" + "ldr r9, [%[b], #84]\n\t" + "ldr r10, [%[b], #88]\n\t" + "ldr r14, [%[b], #92]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #80]\n\t" + "str r5, [%[r], #84]\n\t" + "str r6, [%[r], #88]\n\t" + "str r7, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[a], #100]\n\t" + "ldr r6, [%[a], #104]\n\t" + "ldr r7, [%[a], #108]\n\t" + "ldr r8, [%[b], #96]\n\t" + "ldr r9, [%[b], #100]\n\t" + "ldr r10, [%[b], #104]\n\t" + "ldr r14, [%[b], #108]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #96]\n\t" + "str r5, [%[r], #100]\n\t" + "str r6, [%[r], #104]\n\t" + "str r7, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[a], #116]\n\t" + "ldr r6, [%[a], #120]\n\t" + "ldr r7, [%[a], #124]\n\t" + "ldr r8, [%[b], #112]\n\t" + "ldr r9, [%[b], #116]\n\t" + "ldr r10, [%[b], #120]\n\t" + "ldr r14, [%[b], #124]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #112]\n\t" + "str r5, [%[r], #116]\n\t" + "str r6, [%[r], #120]\n\t" + "str r7, [%[r], #124]\n\t" + "ldr r4, [%[a], #128]\n\t" + "ldr r5, [%[a], #132]\n\t" + "ldr r6, [%[a], #136]\n\t" + "ldr r7, [%[a], #140]\n\t" + "ldr r8, [%[b], #128]\n\t" + "ldr r9, [%[b], #132]\n\t" + "ldr r10, [%[b], #136]\n\t" + "ldr r14, [%[b], #140]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #128]\n\t" + "str r5, [%[r], #132]\n\t" + "str r6, [%[r], #136]\n\t" + "str r7, [%[r], #140]\n\t" + "ldr r4, [%[a], #144]\n\t" + "ldr r5, [%[a], #148]\n\t" + "ldr r6, [%[a], #152]\n\t" + "ldr r7, [%[a], #156]\n\t" + "ldr r8, [%[b], #144]\n\t" + "ldr r9, [%[b], #148]\n\t" + "ldr r10, [%[b], #152]\n\t" + "ldr r14, [%[b], #156]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #144]\n\t" + "str r5, [%[r], #148]\n\t" + "str r6, [%[r], #152]\n\t" + "str r7, [%[r], #156]\n\t" + "ldr r4, [%[a], #160]\n\t" + "ldr r5, [%[a], #164]\n\t" + "ldr r6, [%[a], #168]\n\t" + "ldr r7, [%[a], #172]\n\t" + "ldr r8, [%[b], #160]\n\t" + "ldr r9, [%[b], #164]\n\t" + "ldr r10, [%[b], #168]\n\t" + "ldr r14, [%[b], #172]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #160]\n\t" + "str r5, [%[r], #164]\n\t" + "str r6, [%[r], #168]\n\t" + "str r7, [%[r], #172]\n\t" + "ldr r4, [%[a], #176]\n\t" + "ldr r5, [%[a], #180]\n\t" + "ldr r6, [%[a], #184]\n\t" + "ldr r7, [%[a], #188]\n\t" + "ldr r8, [%[b], #176]\n\t" + "ldr r9, [%[b], #180]\n\t" + "ldr r10, [%[b], #184]\n\t" + "ldr r14, [%[b], #188]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #176]\n\t" + "str r5, [%[r], #180]\n\t" + "str r6, [%[r], #184]\n\t" + "str r7, [%[r], #188]\n\t" + "ldr r4, [%[a], #192]\n\t" + "ldr r5, [%[a], #196]\n\t" + "ldr r6, [%[a], #200]\n\t" + "ldr r7, [%[a], #204]\n\t" + "ldr r8, [%[b], #192]\n\t" + "ldr r9, [%[b], #196]\n\t" + "ldr r10, [%[b], #200]\n\t" + "ldr r14, [%[b], #204]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #192]\n\t" + "str r5, [%[r], #196]\n\t" + "str r6, [%[r], #200]\n\t" + "str r7, [%[r], #204]\n\t" + "ldr r4, [%[a], #208]\n\t" + "ldr r5, [%[a], #212]\n\t" + "ldr r6, [%[a], #216]\n\t" + "ldr r7, [%[a], #220]\n\t" + "ldr r8, [%[b], #208]\n\t" + "ldr r9, [%[b], #212]\n\t" + "ldr r10, [%[b], #216]\n\t" + "ldr r14, [%[b], #220]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #208]\n\t" + "str r5, [%[r], #212]\n\t" + "str r6, [%[r], #216]\n\t" + "str r7, [%[r], #220]\n\t" + "ldr r4, [%[a], #224]\n\t" + "ldr r5, [%[a], #228]\n\t" + "ldr r6, [%[a], #232]\n\t" + "ldr r7, [%[a], #236]\n\t" + "ldr r8, [%[b], #224]\n\t" + "ldr r9, [%[b], #228]\n\t" + "ldr r10, [%[b], #232]\n\t" + "ldr r14, [%[b], #236]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #224]\n\t" + "str r5, [%[r], #228]\n\t" + "str r6, [%[r], #232]\n\t" + "str r7, [%[r], #236]\n\t" + "ldr r4, [%[a], #240]\n\t" + "ldr r5, [%[a], #244]\n\t" + "ldr r6, [%[a], #248]\n\t" + "ldr r7, [%[a], #252]\n\t" + "ldr r8, [%[b], #240]\n\t" + "ldr r9, [%[b], #244]\n\t" + "ldr r10, [%[b], #248]\n\t" + "ldr r14, [%[b], #252]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #240]\n\t" + "str r5, [%[r], #244]\n\t" + "str r6, [%[r], #248]\n\t" + "str r7, [%[r], #252]\n\t" + "adc %[c], r12, r12\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + return c; +} + +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_2048_mask_32(sp_digit* r, sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<32; i++) + r[i] = a[i] & m; +#else + int i; + + for (i = 0; i < 32; i += 8) { + r[i+0] = a[i+0] & m; + r[i+1] = a[i+1] & m; + r[i+2] = a[i+2] & m; + r[i+3] = a[i+3] & m; + r[i+4] = a[i+4] & m; + r[i+5] = a[i+5] & m; + r[i+6] = a[i+6] & m; + r[i+7] = a[i+7] & m; + } +#endif +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_2048_mul_64(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[64]; + sp_digit a1[32]; + sp_digit b1[32]; + sp_digit z2[64]; + sp_digit u, ca, cb; + + ca = sp_2048_add_32(a1, a, &a[32]); + cb = sp_2048_add_32(b1, b, &b[32]); + u = ca & cb; + sp_2048_mul_32(z1, a1, b1); + sp_2048_mul_32(z2, &a[32], &b[32]); + sp_2048_mul_32(z0, a, b); + sp_2048_mask_32(r + 64, a1, 0 - cb); + sp_2048_mask_32(b1, b1, 0 - ca); + u += sp_2048_add_32(r + 64, r + 64, b1); + u += sp_2048_sub_in_place_64(z1, z2); + u += sp_2048_sub_in_place_64(z1, z0); + u += sp_2048_add_64(r + 32, r + 32, z1); + r[96] = u; + XMEMSET(r + 96 + 1, 0, sizeof(sp_digit) * (32 - 1)); + sp_2048_add_64(r + 64, r + 64, z2); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_2048_sqr_64(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z2[64]; + sp_digit z1[64]; + sp_digit a1[32]; + sp_digit u; + + u = sp_2048_add_32(a1, a, &a[32]); + sp_2048_sqr_32(z1, a1); + sp_2048_sqr_32(z2, &a[32]); + sp_2048_sqr_32(z0, a); + sp_2048_mask_32(r + 64, a1, 0 - u); + u += sp_2048_add_32(r + 64, r + 64, r + 64); + u += sp_2048_sub_in_place_64(z1, z2); + u += sp_2048_sub_in_place_64(z1, z0); + u += sp_2048_add_64(r + 32, r + 32, z1); + r[96] = u; + XMEMSET(r + 96 + 1, 0, sizeof(sp_digit) * (32 - 1)); + sp_2048_add_64(r + 64, r + 64, z2); +} + +#endif /* !WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_2048_add_64(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "add r12, %[a], #256\n\t" + "\n1:\n\t" + "adds %[c], %[c], #-1\n\t" + "ldr r4, [%[a]], #4\n\t" + "ldr r5, [%[a]], #4\n\t" + "ldr r6, [%[a]], #4\n\t" + "ldr r7, [%[a]], #4\n\t" + "ldr r8, [%[b]], #4\n\t" + "ldr r9, [%[b]], #4\n\t" + "ldr r10, [%[b]], #4\n\t" + "ldr r14, [%[b]], #4\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r]], #4\n\t" + "str r5, [%[r]], #4\n\t" + "str r6, [%[r]], #4\n\t" + "str r7, [%[r]], #4\n\t" + "mov r4, #0\n\t" + "adc %[c], r4, #0\n\t" + "cmp %[a], r12\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into a. (a -= b) + * + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_2048_sub_in_place_64(sp_digit* a, const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r14, #0\n\t" + "add r12, %[a], #256\n\t" + "\n1:\n\t" + "subs %[c], r14, %[c]\n\t" + "ldr r3, [%[a]]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[a], #8]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b]], #4\n\t" + "ldr r8, [%[b]], #4\n\t" + "ldr r9, [%[b]], #4\n\t" + "ldr r10, [%[b]], #4\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "str r3, [%[a]], #4\n\t" + "str r4, [%[a]], #4\n\t" + "str r5, [%[a]], #4\n\t" + "str r6, [%[a]], #4\n\t" + "sbc %[c], r14, r14\n\t" + "cmp %[a], r12\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r12", "r14" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_2048_mul_64(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + __asm__ __volatile__ ( + "sub sp, sp, #512\n\t" + "mov r5, #0\n\t" + "mov r6, #0\n\t" + "mov r7, #0\n\t" + "mov r8, #0\n\t" + "\n1:\n\t" + "subs r3, r5, #252\n\t" + "movcc r3, #0\n\t" + "sub r4, r5, r3\n\t" + "\n2:\n\t" + "ldr r14, [%[a], r3]\n\t" + "ldr r12, [%[b], r4]\n\t" + "umull r9, r10, r14, r12\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, #0\n\t" + "add r3, r3, #4\n\t" + "sub r4, r4, #4\n\t" + "cmp r3, #256\n\t" + "beq 3f\n\t" + "cmp r3, r5\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "str r6, [sp, r5]\n\t" + "mov r6, r7\n\t" + "mov r7, r8\n\t" + "mov r8, #0\n\t" + "add r5, r5, #4\n\t" + "cmp r5, #504\n\t" + "ble 1b\n\t" + "str r6, [sp, r5]\n\t" + "\n4:\n\t" + "ldr r6, [sp, #0]\n\t" + "ldr r7, [sp, #4]\n\t" + "ldr r8, [sp, #8]\n\t" + "ldr r3, [sp, #12]\n\t" + "str r6, [%[r], #0]\n\t" + "str r7, [%[r], #4]\n\t" + "str r8, [%[r], #8]\n\t" + "str r3, [%[r], #12]\n\t" + "add sp, sp, #16\n\t" + "add %[r], %[r], #16\n\t" + "subs r5, r5, #16\n\t" + "bgt 4b\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_2048_sqr_64(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "sub sp, sp, #512\n\t" + "mov r12, #0\n\t" + "mov r6, #0\n\t" + "mov r7, #0\n\t" + "mov r8, #0\n\t" + "mov r5, #0\n\t" + "\n1:\n\t" + "subs r3, r5, #252\n\t" + "movcc r3, r12\n\t" + "sub r4, r5, r3\n\t" + "\n2:\n\t" + "cmp r4, r3\n\t" + "beq 4f\n\t" + "ldr r14, [%[a], r3]\n\t" + "ldr r9, [%[a], r4]\n\t" + "umull r9, r10, r14, r9\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, r12\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, r12\n\t" + "bal 5f\n\t" + "\n4:\n\t" + "ldr r14, [%[a], r3]\n\t" + "umull r9, r10, r14, r14\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, r12\n\t" + "\n5:\n\t" + "add r3, r3, #4\n\t" + "sub r4, r4, #4\n\t" + "cmp r3, #256\n\t" + "beq 3f\n\t" + "cmp r3, r4\n\t" + "bgt 3f\n\t" + "cmp r3, r5\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "str r6, [sp, r5]\n\t" + "mov r6, r7\n\t" + "mov r7, r8\n\t" + "mov r8, #0\n\t" + "add r5, r5, #4\n\t" + "cmp r5, #504\n\t" + "ble 1b\n\t" + "str r6, [sp, r5]\n\t" + "\n4:\n\t" + "ldr r6, [sp, #0]\n\t" + "ldr r7, [sp, #4]\n\t" + "ldr r8, [sp, #8]\n\t" + "ldr r3, [sp, #12]\n\t" + "str r6, [%[r], #0]\n\t" + "str r7, [%[r], #4]\n\t" + "str r8, [%[r], #8]\n\t" + "str r3, [%[r], #12]\n\t" + "add sp, sp, #16\n\t" + "add %[r], %[r], #16\n\t" + "subs r5, r5, #16\n\t" + "bgt 4b\n\t" + : [r] "+r" (r) + : [a] "r" (a) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r9", "r12" + ); +} + +#endif /* WOLFSSL_SP_SMALL */ +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +#ifdef WOLFSSL_SP_SMALL +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_2048_mask_32(sp_digit* r, sp_digit* a, sp_digit m) +{ + int i; + + for (i=0; i<32; i++) + r[i] = a[i] & m; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_2048_add_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "add r12, %[a], #128\n\t" + "\n1:\n\t" + "adds %[c], %[c], #-1\n\t" + "ldr r4, [%[a]], #4\n\t" + "ldr r5, [%[a]], #4\n\t" + "ldr r6, [%[a]], #4\n\t" + "ldr r7, [%[a]], #4\n\t" + "ldr r8, [%[b]], #4\n\t" + "ldr r9, [%[b]], #4\n\t" + "ldr r10, [%[b]], #4\n\t" + "ldr r14, [%[b]], #4\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r]], #4\n\t" + "str r5, [%[r]], #4\n\t" + "str r6, [%[r]], #4\n\t" + "str r7, [%[r]], #4\n\t" + "mov r4, #0\n\t" + "adc %[c], r4, #0\n\t" + "cmp %[a], r12\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into a. (a -= b) + * + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_2048_sub_in_place_32(sp_digit* a, const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r14, #0\n\t" + "add r12, %[a], #128\n\t" + "\n1:\n\t" + "subs %[c], r14, %[c]\n\t" + "ldr r3, [%[a]]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[a], #8]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b]], #4\n\t" + "ldr r8, [%[b]], #4\n\t" + "ldr r9, [%[b]], #4\n\t" + "ldr r10, [%[b]], #4\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "str r3, [%[a]], #4\n\t" + "str r4, [%[a]], #4\n\t" + "str r5, [%[a]], #4\n\t" + "str r6, [%[a]], #4\n\t" + "sbc %[c], r14, r14\n\t" + "cmp %[a], r12\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r12", "r14" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_2048_mul_32(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + __asm__ __volatile__ ( + "sub sp, sp, #256\n\t" + "mov r5, #0\n\t" + "mov r6, #0\n\t" + "mov r7, #0\n\t" + "mov r8, #0\n\t" + "\n1:\n\t" + "subs r3, r5, #124\n\t" + "movcc r3, #0\n\t" + "sub r4, r5, r3\n\t" + "\n2:\n\t" + "ldr r14, [%[a], r3]\n\t" + "ldr r12, [%[b], r4]\n\t" + "umull r9, r10, r14, r12\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, #0\n\t" + "add r3, r3, #4\n\t" + "sub r4, r4, #4\n\t" + "cmp r3, #128\n\t" + "beq 3f\n\t" + "cmp r3, r5\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "str r6, [sp, r5]\n\t" + "mov r6, r7\n\t" + "mov r7, r8\n\t" + "mov r8, #0\n\t" + "add r5, r5, #4\n\t" + "cmp r5, #248\n\t" + "ble 1b\n\t" + "str r6, [sp, r5]\n\t" + "\n4:\n\t" + "ldr r6, [sp, #0]\n\t" + "ldr r7, [sp, #4]\n\t" + "ldr r8, [sp, #8]\n\t" + "ldr r3, [sp, #12]\n\t" + "str r6, [%[r], #0]\n\t" + "str r7, [%[r], #4]\n\t" + "str r8, [%[r], #8]\n\t" + "str r3, [%[r], #12]\n\t" + "add sp, sp, #16\n\t" + "add %[r], %[r], #16\n\t" + "subs r5, r5, #16\n\t" + "bgt 4b\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_2048_sqr_32(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "sub sp, sp, #256\n\t" + "mov r12, #0\n\t" + "mov r6, #0\n\t" + "mov r7, #0\n\t" + "mov r8, #0\n\t" + "mov r5, #0\n\t" + "\n1:\n\t" + "subs r3, r5, #124\n\t" + "movcc r3, r12\n\t" + "sub r4, r5, r3\n\t" + "\n2:\n\t" + "cmp r4, r3\n\t" + "beq 4f\n\t" + "ldr r14, [%[a], r3]\n\t" + "ldr r9, [%[a], r4]\n\t" + "umull r9, r10, r14, r9\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, r12\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, r12\n\t" + "bal 5f\n\t" + "\n4:\n\t" + "ldr r14, [%[a], r3]\n\t" + "umull r9, r10, r14, r14\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, r12\n\t" + "\n5:\n\t" + "add r3, r3, #4\n\t" + "sub r4, r4, #4\n\t" + "cmp r3, #128\n\t" + "beq 3f\n\t" + "cmp r3, r4\n\t" + "bgt 3f\n\t" + "cmp r3, r5\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "str r6, [sp, r5]\n\t" + "mov r6, r7\n\t" + "mov r7, r8\n\t" + "mov r8, #0\n\t" + "add r5, r5, #4\n\t" + "cmp r5, #248\n\t" + "ble 1b\n\t" + "str r6, [sp, r5]\n\t" + "\n4:\n\t" + "ldr r6, [sp, #0]\n\t" + "ldr r7, [sp, #4]\n\t" + "ldr r8, [sp, #8]\n\t" + "ldr r3, [sp, #12]\n\t" + "str r6, [%[r], #0]\n\t" + "str r7, [%[r], #4]\n\t" + "str r8, [%[r], #8]\n\t" + "str r3, [%[r], #12]\n\t" + "add sp, sp, #16\n\t" + "add %[r], %[r], #16\n\t" + "subs r5, r5, #16\n\t" + "bgt 4b\n\t" + : [r] "+r" (r) + : [a] "r" (a) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r9", "r12" + ); +} + +#endif /* WOLFSSL_SP_SMALL */ +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +/* Caclulate the bottom digit of -1/a mod 2^n. + * + * a A single precision number. + * rho Bottom word of inverse. + */ +static void sp_2048_mont_setup(sp_digit* a, sp_digit* rho) +{ + sp_digit x, b; + + b = a[0]; + x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ + x *= 2 - b * x; /* here x*a==1 mod 2**8 */ + x *= 2 - b * x; /* here x*a==1 mod 2**16 */ + x *= 2 - b * x; /* here x*a==1 mod 2**32 */ + + /* rho = -1/m mod b */ + *rho = -x; +} + +/* Mul a by digit b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision digit. + */ +static void sp_2048_mul_d_64(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov r10, #0\n\t" + "# A[0] * B\n\t" + "ldr r8, [%[a]]\n\t" + "umull r5, r3, %[b], r8\n\t" + "mov r4, #0\n\t" + "str r5, [%[r]]\n\t" + "mov r5, #0\n\t" + "mov r9, #4\n\t" + "1:\n\t" + "ldr r8, [%[a], r9]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], r9]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "add r9, r9, #4\n\t" + "cmp r9, #256\n\t" + "blt 1b\n\t" + "str r3, [%[r], #256]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10" + ); +#else + __asm__ __volatile__ ( + "mov r10, #0\n\t" + "# A[0] * B\n\t" + "ldr r8, [%[a]]\n\t" + "umull r3, r4, %[b], r8\n\t" + "mov r5, #0\n\t" + "str r3, [%[r]]\n\t" + "# A[1] * B\n\t" + "ldr r8, [%[a], #4]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #4]\n\t" + "# A[2] * B\n\t" + "ldr r8, [%[a], #8]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #8]\n\t" + "# A[3] * B\n\t" + "ldr r8, [%[a], #12]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #12]\n\t" + "# A[4] * B\n\t" + "ldr r8, [%[a], #16]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #16]\n\t" + "# A[5] * B\n\t" + "ldr r8, [%[a], #20]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #20]\n\t" + "# A[6] * B\n\t" + "ldr r8, [%[a], #24]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #24]\n\t" + "# A[7] * B\n\t" + "ldr r8, [%[a], #28]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #28]\n\t" + "# A[8] * B\n\t" + "ldr r8, [%[a], #32]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #32]\n\t" + "# A[9] * B\n\t" + "ldr r8, [%[a], #36]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #36]\n\t" + "# A[10] * B\n\t" + "ldr r8, [%[a], #40]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #40]\n\t" + "# A[11] * B\n\t" + "ldr r8, [%[a], #44]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #44]\n\t" + "# A[12] * B\n\t" + "ldr r8, [%[a], #48]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #48]\n\t" + "# A[13] * B\n\t" + "ldr r8, [%[a], #52]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #52]\n\t" + "# A[14] * B\n\t" + "ldr r8, [%[a], #56]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #56]\n\t" + "# A[15] * B\n\t" + "ldr r8, [%[a], #60]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #60]\n\t" + "# A[16] * B\n\t" + "ldr r8, [%[a], #64]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #64]\n\t" + "# A[17] * B\n\t" + "ldr r8, [%[a], #68]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #68]\n\t" + "# A[18] * B\n\t" + "ldr r8, [%[a], #72]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #72]\n\t" + "# A[19] * B\n\t" + "ldr r8, [%[a], #76]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #76]\n\t" + "# A[20] * B\n\t" + "ldr r8, [%[a], #80]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #80]\n\t" + "# A[21] * B\n\t" + "ldr r8, [%[a], #84]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #84]\n\t" + "# A[22] * B\n\t" + "ldr r8, [%[a], #88]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #88]\n\t" + "# A[23] * B\n\t" + "ldr r8, [%[a], #92]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #92]\n\t" + "# A[24] * B\n\t" + "ldr r8, [%[a], #96]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #96]\n\t" + "# A[25] * B\n\t" + "ldr r8, [%[a], #100]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #100]\n\t" + "# A[26] * B\n\t" + "ldr r8, [%[a], #104]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #104]\n\t" + "# A[27] * B\n\t" + "ldr r8, [%[a], #108]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #108]\n\t" + "# A[28] * B\n\t" + "ldr r8, [%[a], #112]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #112]\n\t" + "# A[29] * B\n\t" + "ldr r8, [%[a], #116]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #116]\n\t" + "# A[30] * B\n\t" + "ldr r8, [%[a], #120]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #120]\n\t" + "# A[31] * B\n\t" + "ldr r8, [%[a], #124]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #124]\n\t" + "# A[32] * B\n\t" + "ldr r8, [%[a], #128]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #128]\n\t" + "# A[33] * B\n\t" + "ldr r8, [%[a], #132]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #132]\n\t" + "# A[34] * B\n\t" + "ldr r8, [%[a], #136]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #136]\n\t" + "# A[35] * B\n\t" + "ldr r8, [%[a], #140]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #140]\n\t" + "# A[36] * B\n\t" + "ldr r8, [%[a], #144]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #144]\n\t" + "# A[37] * B\n\t" + "ldr r8, [%[a], #148]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #148]\n\t" + "# A[38] * B\n\t" + "ldr r8, [%[a], #152]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #152]\n\t" + "# A[39] * B\n\t" + "ldr r8, [%[a], #156]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #156]\n\t" + "# A[40] * B\n\t" + "ldr r8, [%[a], #160]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #160]\n\t" + "# A[41] * B\n\t" + "ldr r8, [%[a], #164]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #164]\n\t" + "# A[42] * B\n\t" + "ldr r8, [%[a], #168]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #168]\n\t" + "# A[43] * B\n\t" + "ldr r8, [%[a], #172]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #172]\n\t" + "# A[44] * B\n\t" + "ldr r8, [%[a], #176]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #176]\n\t" + "# A[45] * B\n\t" + "ldr r8, [%[a], #180]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #180]\n\t" + "# A[46] * B\n\t" + "ldr r8, [%[a], #184]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #184]\n\t" + "# A[47] * B\n\t" + "ldr r8, [%[a], #188]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #188]\n\t" + "# A[48] * B\n\t" + "ldr r8, [%[a], #192]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #192]\n\t" + "# A[49] * B\n\t" + "ldr r8, [%[a], #196]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #196]\n\t" + "# A[50] * B\n\t" + "ldr r8, [%[a], #200]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #200]\n\t" + "# A[51] * B\n\t" + "ldr r8, [%[a], #204]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #204]\n\t" + "# A[52] * B\n\t" + "ldr r8, [%[a], #208]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #208]\n\t" + "# A[53] * B\n\t" + "ldr r8, [%[a], #212]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #212]\n\t" + "# A[54] * B\n\t" + "ldr r8, [%[a], #216]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #216]\n\t" + "# A[55] * B\n\t" + "ldr r8, [%[a], #220]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #220]\n\t" + "# A[56] * B\n\t" + "ldr r8, [%[a], #224]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #224]\n\t" + "# A[57] * B\n\t" + "ldr r8, [%[a], #228]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #228]\n\t" + "# A[58] * B\n\t" + "ldr r8, [%[a], #232]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #232]\n\t" + "# A[59] * B\n\t" + "ldr r8, [%[a], #236]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #236]\n\t" + "# A[60] * B\n\t" + "ldr r8, [%[a], #240]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #240]\n\t" + "# A[61] * B\n\t" + "ldr r8, [%[a], #244]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #244]\n\t" + "# A[62] * B\n\t" + "ldr r8, [%[a], #248]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #248]\n\t" + "# A[63] * B\n\t" + "ldr r8, [%[a], #252]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r3, [%[r], #252]\n\t" + "str r4, [%[r], #256]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10" + ); +#endif +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +/* r = 2^n mod m where n is the number of bits to reduce by. + * Given m must be 2048 bits, just need to subtract. + * + * r A single precision number. + * m A signle precision number. + */ +static void sp_2048_mont_norm_32(sp_digit* r, sp_digit* m) +{ + XMEMSET(r, 0, sizeof(sp_digit) * 32); + + /* r = 2^n mod m */ + sp_2048_sub_in_place_32(r, m); +} + +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not copying. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +static sp_digit sp_2048_cond_sub_32(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit m) +{ + sp_digit c = 0; + +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov r9, #0\n\t" + "mov r8, #0\n\t" + "1:\n\t" + "subs %[c], r9, %[c]\n\t" + "ldr r4, [%[a], r8]\n\t" + "ldr r5, [%[b], r8]\n\t" + "and r5, r5, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbc %[c], r9, r9\n\t" + "str r4, [%[r], r8]\n\t" + "add r8, r8, #4\n\t" + "cmp r8, #128\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r4", "r6", "r5", "r7", "r8", "r9" + ); +#else + __asm__ __volatile__ ( + + "mov r9, #0\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r6, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r7, [%[b], #4]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "subs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #0]\n\t" + "str r6, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r7, [%[b], #12]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #8]\n\t" + "str r6, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r6, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r7, [%[b], #20]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #16]\n\t" + "str r6, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r6, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r7, [%[b], #28]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #24]\n\t" + "str r6, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r6, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r7, [%[b], #36]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #32]\n\t" + "str r6, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r6, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r7, [%[b], #44]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #40]\n\t" + "str r6, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r6, [%[a], #52]\n\t" + "ldr r5, [%[b], #48]\n\t" + "ldr r7, [%[b], #52]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #48]\n\t" + "str r6, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r6, [%[a], #60]\n\t" + "ldr r5, [%[b], #56]\n\t" + "ldr r7, [%[b], #60]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #56]\n\t" + "str r6, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r6, [%[a], #68]\n\t" + "ldr r5, [%[b], #64]\n\t" + "ldr r7, [%[b], #68]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #64]\n\t" + "str r6, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r6, [%[a], #76]\n\t" + "ldr r5, [%[b], #72]\n\t" + "ldr r7, [%[b], #76]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #72]\n\t" + "str r6, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r6, [%[a], #84]\n\t" + "ldr r5, [%[b], #80]\n\t" + "ldr r7, [%[b], #84]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #80]\n\t" + "str r6, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r6, [%[a], #92]\n\t" + "ldr r5, [%[b], #88]\n\t" + "ldr r7, [%[b], #92]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #88]\n\t" + "str r6, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r6, [%[a], #100]\n\t" + "ldr r5, [%[b], #96]\n\t" + "ldr r7, [%[b], #100]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #96]\n\t" + "str r6, [%[r], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r6, [%[a], #108]\n\t" + "ldr r5, [%[b], #104]\n\t" + "ldr r7, [%[b], #108]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #104]\n\t" + "str r6, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r6, [%[a], #116]\n\t" + "ldr r5, [%[b], #112]\n\t" + "ldr r7, [%[b], #116]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #112]\n\t" + "str r6, [%[r], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r6, [%[a], #124]\n\t" + "ldr r5, [%[b], #120]\n\t" + "ldr r7, [%[b], #124]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #120]\n\t" + "str r6, [%[r], #124]\n\t" + "sbc %[c], r9, r9\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r4", "r6", "r5", "r7", "r8", "r9" + ); +#endif /* WOLFSSL_SP_SMALL */ + + return c; +} + +/* Reduce the number back to 2048 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "# i = 0\n\t" + "mov r12, #0\n\t" + "ldr r10, [%[a], #0]\n\t" + "ldr r14, [%[a], #4]\n\t" + "\n1:\n\t" + "# mu = a[i] * mp\n\t" + "mul r8, %[mp], r10\n\t" + "# a[i+0] += m[0] * mu\n\t" + "ldr r7, [%[m], #0]\n\t" + "ldr r9, [%[a], #0]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r10, r10, r6\n\t" + "adc r5, r7, #0\n\t" + "# a[i+1] += m[1] * mu\n\t" + "ldr r7, [%[m], #4]\n\t" + "ldr r9, [%[a], #4]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r10, r14, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r10, r10, r5\n\t" + "adc r4, r4, #0\n\t" + "# a[i+2] += m[2] * mu\n\t" + "ldr r7, [%[m], #8]\n\t" + "ldr r14, [%[a], #8]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r14, r14, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r14, r14, r4\n\t" + "adc r5, r5, #0\n\t" + "# a[i+3] += m[3] * mu\n\t" + "ldr r7, [%[m], #12]\n\t" + "ldr r9, [%[a], #12]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #12]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+4] += m[4] * mu\n\t" + "ldr r7, [%[m], #16]\n\t" + "ldr r9, [%[a], #16]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #16]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+5] += m[5] * mu\n\t" + "ldr r7, [%[m], #20]\n\t" + "ldr r9, [%[a], #20]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #20]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+6] += m[6] * mu\n\t" + "ldr r7, [%[m], #24]\n\t" + "ldr r9, [%[a], #24]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #24]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+7] += m[7] * mu\n\t" + "ldr r7, [%[m], #28]\n\t" + "ldr r9, [%[a], #28]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #28]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+8] += m[8] * mu\n\t" + "ldr r7, [%[m], #32]\n\t" + "ldr r9, [%[a], #32]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #32]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+9] += m[9] * mu\n\t" + "ldr r7, [%[m], #36]\n\t" + "ldr r9, [%[a], #36]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #36]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+10] += m[10] * mu\n\t" + "ldr r7, [%[m], #40]\n\t" + "ldr r9, [%[a], #40]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #40]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+11] += m[11] * mu\n\t" + "ldr r7, [%[m], #44]\n\t" + "ldr r9, [%[a], #44]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #44]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+12] += m[12] * mu\n\t" + "ldr r7, [%[m], #48]\n\t" + "ldr r9, [%[a], #48]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #48]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+13] += m[13] * mu\n\t" + "ldr r7, [%[m], #52]\n\t" + "ldr r9, [%[a], #52]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #52]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+14] += m[14] * mu\n\t" + "ldr r7, [%[m], #56]\n\t" + "ldr r9, [%[a], #56]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #56]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+15] += m[15] * mu\n\t" + "ldr r7, [%[m], #60]\n\t" + "ldr r9, [%[a], #60]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #60]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+16] += m[16] * mu\n\t" + "ldr r7, [%[m], #64]\n\t" + "ldr r9, [%[a], #64]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #64]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+17] += m[17] * mu\n\t" + "ldr r7, [%[m], #68]\n\t" + "ldr r9, [%[a], #68]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #68]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+18] += m[18] * mu\n\t" + "ldr r7, [%[m], #72]\n\t" + "ldr r9, [%[a], #72]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #72]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+19] += m[19] * mu\n\t" + "ldr r7, [%[m], #76]\n\t" + "ldr r9, [%[a], #76]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #76]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+20] += m[20] * mu\n\t" + "ldr r7, [%[m], #80]\n\t" + "ldr r9, [%[a], #80]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #80]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+21] += m[21] * mu\n\t" + "ldr r7, [%[m], #84]\n\t" + "ldr r9, [%[a], #84]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #84]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+22] += m[22] * mu\n\t" + "ldr r7, [%[m], #88]\n\t" + "ldr r9, [%[a], #88]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #88]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+23] += m[23] * mu\n\t" + "ldr r7, [%[m], #92]\n\t" + "ldr r9, [%[a], #92]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #92]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+24] += m[24] * mu\n\t" + "ldr r7, [%[m], #96]\n\t" + "ldr r9, [%[a], #96]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #96]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+25] += m[25] * mu\n\t" + "ldr r7, [%[m], #100]\n\t" + "ldr r9, [%[a], #100]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #100]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+26] += m[26] * mu\n\t" + "ldr r7, [%[m], #104]\n\t" + "ldr r9, [%[a], #104]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #104]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+27] += m[27] * mu\n\t" + "ldr r7, [%[m], #108]\n\t" + "ldr r9, [%[a], #108]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #108]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+28] += m[28] * mu\n\t" + "ldr r7, [%[m], #112]\n\t" + "ldr r9, [%[a], #112]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #112]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+29] += m[29] * mu\n\t" + "ldr r7, [%[m], #116]\n\t" + "ldr r9, [%[a], #116]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #116]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+30] += m[30] * mu\n\t" + "ldr r7, [%[m], #120]\n\t" + "ldr r9, [%[a], #120]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #120]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+31] += m[31] * mu\n\t" + "ldr r7, [%[m], #124]\n\t" + "ldr r9, [%[a], #124]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r7, r7, %[ca]\n\t" + "mov %[ca], #0\n\t" + "adc %[ca], %[ca], %[ca]\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #124]\n\t" + "ldr r9, [%[a], #128]\n\t" + "adcs r9, r9, r7\n\t" + "str r9, [%[a], #128]\n\t" + "adc %[ca], %[ca], #0\n\t" + "# i += 1\n\t" + "add %[a], %[a], #4\n\t" + "add r12, r12, #4\n\t" + "cmp r12, #128\n\t" + "blt 1b\n\t" + "str r10, [%[a], #0]\n\t" + "str r14, [%[a], #4]\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + sp_2048_cond_sub_32(a - 32, a, m, (sp_digit)0 - ca); +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_2048_mont_mul_32(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_2048_mul_32(r, a, b); + sp_2048_mont_reduce_32(r, m, mp); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_2048_mont_sqr_32(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_2048_sqr_32(r, a); + sp_2048_mont_reduce_32(r, m, mp); +} + +/* Mul a by digit b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision digit. + */ +static void sp_2048_mul_d_32(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov r10, #0\n\t" + "# A[0] * B\n\t" + "ldr r8, [%[a]]\n\t" + "umull r5, r3, %[b], r8\n\t" + "mov r4, #0\n\t" + "str r5, [%[r]]\n\t" + "mov r5, #0\n\t" + "mov r9, #4\n\t" + "1:\n\t" + "ldr r8, [%[a], r9]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], r9]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "add r9, r9, #4\n\t" + "cmp r9, #128\n\t" + "blt 1b\n\t" + "str r3, [%[r], #128]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10" + ); +#else + __asm__ __volatile__ ( + "mov r10, #0\n\t" + "# A[0] * B\n\t" + "ldr r8, [%[a]]\n\t" + "umull r3, r4, %[b], r8\n\t" + "mov r5, #0\n\t" + "str r3, [%[r]]\n\t" + "# A[1] * B\n\t" + "ldr r8, [%[a], #4]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #4]\n\t" + "# A[2] * B\n\t" + "ldr r8, [%[a], #8]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #8]\n\t" + "# A[3] * B\n\t" + "ldr r8, [%[a], #12]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #12]\n\t" + "# A[4] * B\n\t" + "ldr r8, [%[a], #16]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #16]\n\t" + "# A[5] * B\n\t" + "ldr r8, [%[a], #20]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #20]\n\t" + "# A[6] * B\n\t" + "ldr r8, [%[a], #24]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #24]\n\t" + "# A[7] * B\n\t" + "ldr r8, [%[a], #28]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #28]\n\t" + "# A[8] * B\n\t" + "ldr r8, [%[a], #32]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #32]\n\t" + "# A[9] * B\n\t" + "ldr r8, [%[a], #36]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #36]\n\t" + "# A[10] * B\n\t" + "ldr r8, [%[a], #40]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #40]\n\t" + "# A[11] * B\n\t" + "ldr r8, [%[a], #44]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #44]\n\t" + "# A[12] * B\n\t" + "ldr r8, [%[a], #48]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #48]\n\t" + "# A[13] * B\n\t" + "ldr r8, [%[a], #52]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #52]\n\t" + "# A[14] * B\n\t" + "ldr r8, [%[a], #56]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #56]\n\t" + "# A[15] * B\n\t" + "ldr r8, [%[a], #60]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #60]\n\t" + "# A[16] * B\n\t" + "ldr r8, [%[a], #64]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #64]\n\t" + "# A[17] * B\n\t" + "ldr r8, [%[a], #68]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #68]\n\t" + "# A[18] * B\n\t" + "ldr r8, [%[a], #72]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #72]\n\t" + "# A[19] * B\n\t" + "ldr r8, [%[a], #76]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #76]\n\t" + "# A[20] * B\n\t" + "ldr r8, [%[a], #80]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #80]\n\t" + "# A[21] * B\n\t" + "ldr r8, [%[a], #84]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #84]\n\t" + "# A[22] * B\n\t" + "ldr r8, [%[a], #88]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #88]\n\t" + "# A[23] * B\n\t" + "ldr r8, [%[a], #92]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #92]\n\t" + "# A[24] * B\n\t" + "ldr r8, [%[a], #96]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #96]\n\t" + "# A[25] * B\n\t" + "ldr r8, [%[a], #100]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #100]\n\t" + "# A[26] * B\n\t" + "ldr r8, [%[a], #104]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #104]\n\t" + "# A[27] * B\n\t" + "ldr r8, [%[a], #108]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #108]\n\t" + "# A[28] * B\n\t" + "ldr r8, [%[a], #112]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #112]\n\t" + "# A[29] * B\n\t" + "ldr r8, [%[a], #116]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #116]\n\t" + "# A[30] * B\n\t" + "ldr r8, [%[a], #120]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #120]\n\t" + "# A[31] * B\n\t" + "ldr r8, [%[a], #124]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adc r5, r5, r7\n\t" + "str r4, [%[r], #124]\n\t" + "str r5, [%[r], #128]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10" + ); +#endif +} + +/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) + * + * d1 The high order half of the number to divide. + * d0 The low order half of the number to divide. + * div The dividend. + * returns the result of the division. + * + * Note that this is an approximate div. It may give an answer 1 larger. + */ +static sp_digit div_2048_word_32(sp_digit d1, sp_digit d0, sp_digit div) +{ + sp_digit r = 0; + + __asm__ __volatile__ ( + "lsr r5, %[div], #1\n\t" + "add r5, r5, #1\n\t" + "mov r6, %[d0]\n\t" + "mov r7, %[d1]\n\t" + "# Do top 32\n\t" + "subs r8, r5, r7\n\t" + "sbc r8, r8, r8\n\t" + "add %[r], %[r], %[r]\n\t" + "sub %[r], %[r], r8\n\t" + "and r8, r8, r5\n\t" + "subs r7, r7, r8\n\t" + "# Next 30 bits\n\t" + "mov r4, #29\n\t" + "1:\n\t" + "movs r6, r6, lsl #1\n\t" + "adc r7, r7, r7\n\t" + "subs r8, r5, r7\n\t" + "sbc r8, r8, r8\n\t" + "add %[r], %[r], %[r]\n\t" + "sub %[r], %[r], r8\n\t" + "and r8, r8, r5\n\t" + "subs r7, r7, r8\n\t" + "subs r4, r4, #1\n\t" + "bpl 1b\n\t" + "add %[r], %[r], %[r]\n\t" + "add %[r], %[r], #1\n\t" + "umull r4, r5, %[r], %[div]\n\t" + "subs r4, %[d0], r4\n\t" + "sbc r5, %[d1], r5\n\t" + "add %[r], %[r], r5\n\t" + "umull r4, r5, %[r], %[div]\n\t" + "subs r4, %[d0], r4\n\t" + "sbc r5, %[d1], r5\n\t" + "add %[r], %[r], r5\n\t" + "subs r8, %[div], r4\n\t" + "sbc r8, r8, r8\n\t" + "sub %[r], %[r], r8\n\t" + : [r] "+r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "r4", "r5", "r6", "r7", "r8" + ); + return r; +} + +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +static int32_t sp_2048_cmp_32(sp_digit* a, sp_digit* b) +{ + sp_digit r = -1; + sp_digit one = 1; + + +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov r7, #0\n\t" + "mov r3, #-1\n\t" + "mov r6, #124\n\t" + "1:\n\t" + "ldr r4, [%[a], r6]\n\t" + "ldr r5, [%[b], r6]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "sub r6, r6, #4\n\t" + "bcc 1b\n\t" + "eor %[r], %[r], r3\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [one] "r" (one) + : "r3", "r4", "r5", "r6", "r7" + ); +#else + __asm__ __volatile__ ( + "mov r7, #0\n\t" + "mov r3, #-1\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #124]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[b], #120]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #116]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[b], #112]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #108]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[b], #104]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #100]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[b], #96]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #92]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[b], #88]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #84]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[b], #80]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #76]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[b], #72]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #68]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[b], #64]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #60]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[b], #56]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #52]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[b], #48]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "eor %[r], %[r], r3\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [one] "r" (one) + : "r3", "r4", "r5", "r6", "r7" + ); +#endif + + return r; +} + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_2048_div_32(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[64], t2[33]; + sp_digit div, r1; + int i; + + (void)m; + + div = d[31]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 32); + for (i=31; i>=0; i--) { + r1 = div_2048_word_32(t1[32 + i], t1[32 + i - 1], div); + + sp_2048_mul_d_32(t2, d, r1); + t1[32 + i] += sp_2048_sub_in_place_32(&t1[i], t2); + t1[32 + i] -= t2[32]; + sp_2048_mask_32(t2, d, t1[32 + i]); + t1[32 + i] += sp_2048_add_32(&t1[i], &t1[i], t2); + sp_2048_mask_32(t2, d, t1[32 + i]); + t1[32 + i] += sp_2048_add_32(&t1[i], &t1[i], t2); + } + + r1 = sp_2048_cmp_32(t1, d) >= 0; + sp_2048_cond_sub_32(r, t1, d, (sp_digit)0 - r1); + + return MP_OKAY; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_2048_mod_32(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_2048_div_32(a, m, NULL, r); +} + +#ifdef WOLFSSL_SP_SMALL +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_2048_mod_exp_32(sp_digit* r, sp_digit* a, sp_digit* e, + int bits, sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[16][64]; +#else + sp_digit* t[16]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 64, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<16; i++) + t[i] = td + i * 64; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_32(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 32); + if (reduceA) { + err = sp_2048_mod_32(t[1] + 32, a, m); + if (err == MP_OKAY) + err = sp_2048_mod_32(t[1], t[1], m); + } + else { + XMEMCPY(t[1] + 32, a, sizeof(sp_digit) * 32); + err = sp_2048_mod_32(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_2048_mont_sqr_32(t[ 2], t[ 1], m, mp); + sp_2048_mont_mul_32(t[ 3], t[ 2], t[ 1], m, mp); + sp_2048_mont_sqr_32(t[ 4], t[ 2], m, mp); + sp_2048_mont_mul_32(t[ 5], t[ 3], t[ 2], m, mp); + sp_2048_mont_sqr_32(t[ 6], t[ 3], m, mp); + sp_2048_mont_mul_32(t[ 7], t[ 4], t[ 3], m, mp); + sp_2048_mont_sqr_32(t[ 8], t[ 4], m, mp); + sp_2048_mont_mul_32(t[ 9], t[ 5], t[ 4], m, mp); + sp_2048_mont_sqr_32(t[10], t[ 5], m, mp); + sp_2048_mont_mul_32(t[11], t[ 6], t[ 5], m, mp); + sp_2048_mont_sqr_32(t[12], t[ 6], m, mp); + sp_2048_mont_mul_32(t[13], t[ 7], t[ 6], m, mp); + sp_2048_mont_sqr_32(t[14], t[ 7], m, mp); + sp_2048_mont_mul_32(t[15], t[ 8], t[ 7], m, mp); + + i = (bits - 1) / 32; + n = e[i--]; + y = n >> 28; + n <<= 4; + c = 28; + XMEMCPY(r, t[y], sizeof(sp_digit) * 32); + for (; i>=0 || c>=4; ) { + if (c == 0) { + n = e[i--]; + y = n >> 28; + n <<= 4; + c = 28; + } + else if (c < 4) { + y = n >> 28; + n = e[i--]; + c = 4 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 28) & 0xf; + n <<= 4; + c -= 4; + } + + sp_2048_mont_sqr_32(r, r, m, mp); + sp_2048_mont_sqr_32(r, r, m, mp); + sp_2048_mont_sqr_32(r, r, m, mp); + sp_2048_mont_sqr_32(r, r, m, mp); + + sp_2048_mont_mul_32(r, r, t[y], m, mp); + } + y = e[0] & ((1 << c) - 1); + for (; c > 0; c--) + sp_2048_mont_sqr_32(r, r, m, mp); + sp_2048_mont_mul_32(r, r, t[y], m, mp); + + XMEMSET(&r[32], 0, sizeof(sp_digit) * 32); + sp_2048_mont_reduce_32(r, m, mp); + + mask = 0 - (sp_2048_cmp_32(r, m) >= 0); + sp_2048_cond_sub_32(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#else +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_2048_mod_exp_32(sp_digit* r, sp_digit* a, sp_digit* e, + int bits, sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][64]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 64, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<32; i++) + t[i] = td + i * 64; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_32(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 32); + if (reduceA) { + err = sp_2048_mod_32(t[1] + 32, a, m); + if (err == MP_OKAY) + err = sp_2048_mod_32(t[1], t[1], m); + } + else { + XMEMCPY(t[1] + 32, a, sizeof(sp_digit) * 32); + err = sp_2048_mod_32(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_2048_mont_sqr_32(t[ 2], t[ 1], m, mp); + sp_2048_mont_mul_32(t[ 3], t[ 2], t[ 1], m, mp); + sp_2048_mont_sqr_32(t[ 4], t[ 2], m, mp); + sp_2048_mont_mul_32(t[ 5], t[ 3], t[ 2], m, mp); + sp_2048_mont_sqr_32(t[ 6], t[ 3], m, mp); + sp_2048_mont_mul_32(t[ 7], t[ 4], t[ 3], m, mp); + sp_2048_mont_sqr_32(t[ 8], t[ 4], m, mp); + sp_2048_mont_mul_32(t[ 9], t[ 5], t[ 4], m, mp); + sp_2048_mont_sqr_32(t[10], t[ 5], m, mp); + sp_2048_mont_mul_32(t[11], t[ 6], t[ 5], m, mp); + sp_2048_mont_sqr_32(t[12], t[ 6], m, mp); + sp_2048_mont_mul_32(t[13], t[ 7], t[ 6], m, mp); + sp_2048_mont_sqr_32(t[14], t[ 7], m, mp); + sp_2048_mont_mul_32(t[15], t[ 8], t[ 7], m, mp); + sp_2048_mont_sqr_32(t[16], t[ 8], m, mp); + sp_2048_mont_mul_32(t[17], t[ 9], t[ 8], m, mp); + sp_2048_mont_sqr_32(t[18], t[ 9], m, mp); + sp_2048_mont_mul_32(t[19], t[10], t[ 9], m, mp); + sp_2048_mont_sqr_32(t[20], t[10], m, mp); + sp_2048_mont_mul_32(t[21], t[11], t[10], m, mp); + sp_2048_mont_sqr_32(t[22], t[11], m, mp); + sp_2048_mont_mul_32(t[23], t[12], t[11], m, mp); + sp_2048_mont_sqr_32(t[24], t[12], m, mp); + sp_2048_mont_mul_32(t[25], t[13], t[12], m, mp); + sp_2048_mont_sqr_32(t[26], t[13], m, mp); + sp_2048_mont_mul_32(t[27], t[14], t[13], m, mp); + sp_2048_mont_sqr_32(t[28], t[14], m, mp); + sp_2048_mont_mul_32(t[29], t[15], t[14], m, mp); + sp_2048_mont_sqr_32(t[30], t[15], m, mp); + sp_2048_mont_mul_32(t[31], t[16], t[15], m, mp); + + i = (bits - 1) / 32; + n = e[i--]; + y = n >> 27; + n <<= 5; + c = 27; + XMEMCPY(r, t[y], sizeof(sp_digit) * 32); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 27; + n <<= 5; + c = 27; + } + else if (c < 5) { + y = n >> 27; + n = e[i--]; + c = 5 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 27) & 0x1f; + n <<= 5; + c -= 5; + } + + sp_2048_mont_sqr_32(r, r, m, mp); + sp_2048_mont_sqr_32(r, r, m, mp); + sp_2048_mont_sqr_32(r, r, m, mp); + sp_2048_mont_sqr_32(r, r, m, mp); + sp_2048_mont_sqr_32(r, r, m, mp); + + sp_2048_mont_mul_32(r, r, t[y], m, mp); + } + y = e[0] & ((1 << c) - 1); + for (; c > 0; c--) + sp_2048_mont_sqr_32(r, r, m, mp); + sp_2048_mont_mul_32(r, r, t[y], m, mp); + + XMEMSET(&r[32], 0, sizeof(sp_digit) * 32); + sp_2048_mont_reduce_32(r, m, mp); + + mask = 0 - (sp_2048_cmp_32(r, m) >= 0); + sp_2048_cond_sub_32(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#endif /* WOLFSSL_SP_SMALL */ + +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) +/* r = 2^n mod m where n is the number of bits to reduce by. + * Given m must be 2048 bits, just need to subtract. + * + * r A single precision number. + * m A signle precision number. + */ +static void sp_2048_mont_norm_64(sp_digit* r, sp_digit* m) +{ + XMEMSET(r, 0, sizeof(sp_digit) * 64); + + /* r = 2^n mod m */ + sp_2048_sub_in_place_64(r, m); +} + +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not copying. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +static sp_digit sp_2048_cond_sub_64(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit m) +{ + sp_digit c = 0; + +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov r9, #0\n\t" + "mov r8, #0\n\t" + "1:\n\t" + "subs %[c], r9, %[c]\n\t" + "ldr r4, [%[a], r8]\n\t" + "ldr r5, [%[b], r8]\n\t" + "and r5, r5, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbc %[c], r9, r9\n\t" + "str r4, [%[r], r8]\n\t" + "add r8, r8, #4\n\t" + "cmp r8, #256\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r4", "r6", "r5", "r7", "r8", "r9" + ); +#else + __asm__ __volatile__ ( + + "mov r9, #0\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r6, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r7, [%[b], #4]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "subs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #0]\n\t" + "str r6, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r7, [%[b], #12]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #8]\n\t" + "str r6, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r6, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r7, [%[b], #20]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #16]\n\t" + "str r6, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r6, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r7, [%[b], #28]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #24]\n\t" + "str r6, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r6, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r7, [%[b], #36]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #32]\n\t" + "str r6, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r6, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r7, [%[b], #44]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #40]\n\t" + "str r6, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r6, [%[a], #52]\n\t" + "ldr r5, [%[b], #48]\n\t" + "ldr r7, [%[b], #52]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #48]\n\t" + "str r6, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r6, [%[a], #60]\n\t" + "ldr r5, [%[b], #56]\n\t" + "ldr r7, [%[b], #60]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #56]\n\t" + "str r6, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r6, [%[a], #68]\n\t" + "ldr r5, [%[b], #64]\n\t" + "ldr r7, [%[b], #68]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #64]\n\t" + "str r6, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r6, [%[a], #76]\n\t" + "ldr r5, [%[b], #72]\n\t" + "ldr r7, [%[b], #76]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #72]\n\t" + "str r6, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r6, [%[a], #84]\n\t" + "ldr r5, [%[b], #80]\n\t" + "ldr r7, [%[b], #84]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #80]\n\t" + "str r6, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r6, [%[a], #92]\n\t" + "ldr r5, [%[b], #88]\n\t" + "ldr r7, [%[b], #92]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #88]\n\t" + "str r6, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r6, [%[a], #100]\n\t" + "ldr r5, [%[b], #96]\n\t" + "ldr r7, [%[b], #100]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #96]\n\t" + "str r6, [%[r], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r6, [%[a], #108]\n\t" + "ldr r5, [%[b], #104]\n\t" + "ldr r7, [%[b], #108]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #104]\n\t" + "str r6, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r6, [%[a], #116]\n\t" + "ldr r5, [%[b], #112]\n\t" + "ldr r7, [%[b], #116]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #112]\n\t" + "str r6, [%[r], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r6, [%[a], #124]\n\t" + "ldr r5, [%[b], #120]\n\t" + "ldr r7, [%[b], #124]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #120]\n\t" + "str r6, [%[r], #124]\n\t" + "ldr r4, [%[a], #128]\n\t" + "ldr r6, [%[a], #132]\n\t" + "ldr r5, [%[b], #128]\n\t" + "ldr r7, [%[b], #132]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #128]\n\t" + "str r6, [%[r], #132]\n\t" + "ldr r4, [%[a], #136]\n\t" + "ldr r6, [%[a], #140]\n\t" + "ldr r5, [%[b], #136]\n\t" + "ldr r7, [%[b], #140]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #136]\n\t" + "str r6, [%[r], #140]\n\t" + "ldr r4, [%[a], #144]\n\t" + "ldr r6, [%[a], #148]\n\t" + "ldr r5, [%[b], #144]\n\t" + "ldr r7, [%[b], #148]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #144]\n\t" + "str r6, [%[r], #148]\n\t" + "ldr r4, [%[a], #152]\n\t" + "ldr r6, [%[a], #156]\n\t" + "ldr r5, [%[b], #152]\n\t" + "ldr r7, [%[b], #156]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #152]\n\t" + "str r6, [%[r], #156]\n\t" + "ldr r4, [%[a], #160]\n\t" + "ldr r6, [%[a], #164]\n\t" + "ldr r5, [%[b], #160]\n\t" + "ldr r7, [%[b], #164]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #160]\n\t" + "str r6, [%[r], #164]\n\t" + "ldr r4, [%[a], #168]\n\t" + "ldr r6, [%[a], #172]\n\t" + "ldr r5, [%[b], #168]\n\t" + "ldr r7, [%[b], #172]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #168]\n\t" + "str r6, [%[r], #172]\n\t" + "ldr r4, [%[a], #176]\n\t" + "ldr r6, [%[a], #180]\n\t" + "ldr r5, [%[b], #176]\n\t" + "ldr r7, [%[b], #180]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #176]\n\t" + "str r6, [%[r], #180]\n\t" + "ldr r4, [%[a], #184]\n\t" + "ldr r6, [%[a], #188]\n\t" + "ldr r5, [%[b], #184]\n\t" + "ldr r7, [%[b], #188]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #184]\n\t" + "str r6, [%[r], #188]\n\t" + "ldr r4, [%[a], #192]\n\t" + "ldr r6, [%[a], #196]\n\t" + "ldr r5, [%[b], #192]\n\t" + "ldr r7, [%[b], #196]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #192]\n\t" + "str r6, [%[r], #196]\n\t" + "ldr r4, [%[a], #200]\n\t" + "ldr r6, [%[a], #204]\n\t" + "ldr r5, [%[b], #200]\n\t" + "ldr r7, [%[b], #204]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #200]\n\t" + "str r6, [%[r], #204]\n\t" + "ldr r4, [%[a], #208]\n\t" + "ldr r6, [%[a], #212]\n\t" + "ldr r5, [%[b], #208]\n\t" + "ldr r7, [%[b], #212]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #208]\n\t" + "str r6, [%[r], #212]\n\t" + "ldr r4, [%[a], #216]\n\t" + "ldr r6, [%[a], #220]\n\t" + "ldr r5, [%[b], #216]\n\t" + "ldr r7, [%[b], #220]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #216]\n\t" + "str r6, [%[r], #220]\n\t" + "ldr r4, [%[a], #224]\n\t" + "ldr r6, [%[a], #228]\n\t" + "ldr r5, [%[b], #224]\n\t" + "ldr r7, [%[b], #228]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #224]\n\t" + "str r6, [%[r], #228]\n\t" + "ldr r4, [%[a], #232]\n\t" + "ldr r6, [%[a], #236]\n\t" + "ldr r5, [%[b], #232]\n\t" + "ldr r7, [%[b], #236]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #232]\n\t" + "str r6, [%[r], #236]\n\t" + "ldr r4, [%[a], #240]\n\t" + "ldr r6, [%[a], #244]\n\t" + "ldr r5, [%[b], #240]\n\t" + "ldr r7, [%[b], #244]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #240]\n\t" + "str r6, [%[r], #244]\n\t" + "ldr r4, [%[a], #248]\n\t" + "ldr r6, [%[a], #252]\n\t" + "ldr r5, [%[b], #248]\n\t" + "ldr r7, [%[b], #252]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #248]\n\t" + "str r6, [%[r], #252]\n\t" + "sbc %[c], r9, r9\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r4", "r6", "r5", "r7", "r8", "r9" + ); +#endif /* WOLFSSL_SP_SMALL */ + + return c; +} + +/* Reduce the number back to 2048 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "# i = 0\n\t" + "mov r12, #0\n\t" + "ldr r10, [%[a], #0]\n\t" + "ldr r14, [%[a], #4]\n\t" + "\n1:\n\t" + "# mu = a[i] * mp\n\t" + "mul r8, %[mp], r10\n\t" + "# a[i+0] += m[0] * mu\n\t" + "ldr r7, [%[m], #0]\n\t" + "ldr r9, [%[a], #0]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r10, r10, r6\n\t" + "adc r5, r7, #0\n\t" + "# a[i+1] += m[1] * mu\n\t" + "ldr r7, [%[m], #4]\n\t" + "ldr r9, [%[a], #4]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r10, r14, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r10, r10, r5\n\t" + "adc r4, r4, #0\n\t" + "# a[i+2] += m[2] * mu\n\t" + "ldr r7, [%[m], #8]\n\t" + "ldr r14, [%[a], #8]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r14, r14, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r14, r14, r4\n\t" + "adc r5, r5, #0\n\t" + "# a[i+3] += m[3] * mu\n\t" + "ldr r7, [%[m], #12]\n\t" + "ldr r9, [%[a], #12]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #12]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+4] += m[4] * mu\n\t" + "ldr r7, [%[m], #16]\n\t" + "ldr r9, [%[a], #16]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #16]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+5] += m[5] * mu\n\t" + "ldr r7, [%[m], #20]\n\t" + "ldr r9, [%[a], #20]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #20]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+6] += m[6] * mu\n\t" + "ldr r7, [%[m], #24]\n\t" + "ldr r9, [%[a], #24]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #24]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+7] += m[7] * mu\n\t" + "ldr r7, [%[m], #28]\n\t" + "ldr r9, [%[a], #28]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #28]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+8] += m[8] * mu\n\t" + "ldr r7, [%[m], #32]\n\t" + "ldr r9, [%[a], #32]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #32]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+9] += m[9] * mu\n\t" + "ldr r7, [%[m], #36]\n\t" + "ldr r9, [%[a], #36]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #36]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+10] += m[10] * mu\n\t" + "ldr r7, [%[m], #40]\n\t" + "ldr r9, [%[a], #40]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #40]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+11] += m[11] * mu\n\t" + "ldr r7, [%[m], #44]\n\t" + "ldr r9, [%[a], #44]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #44]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+12] += m[12] * mu\n\t" + "ldr r7, [%[m], #48]\n\t" + "ldr r9, [%[a], #48]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #48]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+13] += m[13] * mu\n\t" + "ldr r7, [%[m], #52]\n\t" + "ldr r9, [%[a], #52]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #52]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+14] += m[14] * mu\n\t" + "ldr r7, [%[m], #56]\n\t" + "ldr r9, [%[a], #56]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #56]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+15] += m[15] * mu\n\t" + "ldr r7, [%[m], #60]\n\t" + "ldr r9, [%[a], #60]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #60]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+16] += m[16] * mu\n\t" + "ldr r7, [%[m], #64]\n\t" + "ldr r9, [%[a], #64]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #64]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+17] += m[17] * mu\n\t" + "ldr r7, [%[m], #68]\n\t" + "ldr r9, [%[a], #68]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #68]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+18] += m[18] * mu\n\t" + "ldr r7, [%[m], #72]\n\t" + "ldr r9, [%[a], #72]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #72]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+19] += m[19] * mu\n\t" + "ldr r7, [%[m], #76]\n\t" + "ldr r9, [%[a], #76]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #76]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+20] += m[20] * mu\n\t" + "ldr r7, [%[m], #80]\n\t" + "ldr r9, [%[a], #80]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #80]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+21] += m[21] * mu\n\t" + "ldr r7, [%[m], #84]\n\t" + "ldr r9, [%[a], #84]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #84]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+22] += m[22] * mu\n\t" + "ldr r7, [%[m], #88]\n\t" + "ldr r9, [%[a], #88]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #88]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+23] += m[23] * mu\n\t" + "ldr r7, [%[m], #92]\n\t" + "ldr r9, [%[a], #92]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #92]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+24] += m[24] * mu\n\t" + "ldr r7, [%[m], #96]\n\t" + "ldr r9, [%[a], #96]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #96]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+25] += m[25] * mu\n\t" + "ldr r7, [%[m], #100]\n\t" + "ldr r9, [%[a], #100]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #100]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+26] += m[26] * mu\n\t" + "ldr r7, [%[m], #104]\n\t" + "ldr r9, [%[a], #104]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #104]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+27] += m[27] * mu\n\t" + "ldr r7, [%[m], #108]\n\t" + "ldr r9, [%[a], #108]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #108]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+28] += m[28] * mu\n\t" + "ldr r7, [%[m], #112]\n\t" + "ldr r9, [%[a], #112]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #112]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+29] += m[29] * mu\n\t" + "ldr r7, [%[m], #116]\n\t" + "ldr r9, [%[a], #116]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #116]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+30] += m[30] * mu\n\t" + "ldr r7, [%[m], #120]\n\t" + "ldr r9, [%[a], #120]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #120]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+31] += m[31] * mu\n\t" + "ldr r7, [%[m], #124]\n\t" + "ldr r9, [%[a], #124]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #124]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+32] += m[32] * mu\n\t" + "ldr r7, [%[m], #128]\n\t" + "ldr r9, [%[a], #128]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #128]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+33] += m[33] * mu\n\t" + "ldr r7, [%[m], #132]\n\t" + "ldr r9, [%[a], #132]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #132]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+34] += m[34] * mu\n\t" + "ldr r7, [%[m], #136]\n\t" + "ldr r9, [%[a], #136]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #136]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+35] += m[35] * mu\n\t" + "ldr r7, [%[m], #140]\n\t" + "ldr r9, [%[a], #140]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #140]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+36] += m[36] * mu\n\t" + "ldr r7, [%[m], #144]\n\t" + "ldr r9, [%[a], #144]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #144]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+37] += m[37] * mu\n\t" + "ldr r7, [%[m], #148]\n\t" + "ldr r9, [%[a], #148]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #148]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+38] += m[38] * mu\n\t" + "ldr r7, [%[m], #152]\n\t" + "ldr r9, [%[a], #152]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #152]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+39] += m[39] * mu\n\t" + "ldr r7, [%[m], #156]\n\t" + "ldr r9, [%[a], #156]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #156]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+40] += m[40] * mu\n\t" + "ldr r7, [%[m], #160]\n\t" + "ldr r9, [%[a], #160]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #160]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+41] += m[41] * mu\n\t" + "ldr r7, [%[m], #164]\n\t" + "ldr r9, [%[a], #164]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #164]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+42] += m[42] * mu\n\t" + "ldr r7, [%[m], #168]\n\t" + "ldr r9, [%[a], #168]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #168]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+43] += m[43] * mu\n\t" + "ldr r7, [%[m], #172]\n\t" + "ldr r9, [%[a], #172]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #172]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+44] += m[44] * mu\n\t" + "ldr r7, [%[m], #176]\n\t" + "ldr r9, [%[a], #176]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #176]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+45] += m[45] * mu\n\t" + "ldr r7, [%[m], #180]\n\t" + "ldr r9, [%[a], #180]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #180]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+46] += m[46] * mu\n\t" + "ldr r7, [%[m], #184]\n\t" + "ldr r9, [%[a], #184]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #184]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+47] += m[47] * mu\n\t" + "ldr r7, [%[m], #188]\n\t" + "ldr r9, [%[a], #188]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #188]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+48] += m[48] * mu\n\t" + "ldr r7, [%[m], #192]\n\t" + "ldr r9, [%[a], #192]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #192]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+49] += m[49] * mu\n\t" + "ldr r7, [%[m], #196]\n\t" + "ldr r9, [%[a], #196]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #196]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+50] += m[50] * mu\n\t" + "ldr r7, [%[m], #200]\n\t" + "ldr r9, [%[a], #200]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #200]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+51] += m[51] * mu\n\t" + "ldr r7, [%[m], #204]\n\t" + "ldr r9, [%[a], #204]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #204]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+52] += m[52] * mu\n\t" + "ldr r7, [%[m], #208]\n\t" + "ldr r9, [%[a], #208]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #208]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+53] += m[53] * mu\n\t" + "ldr r7, [%[m], #212]\n\t" + "ldr r9, [%[a], #212]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #212]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+54] += m[54] * mu\n\t" + "ldr r7, [%[m], #216]\n\t" + "ldr r9, [%[a], #216]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #216]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+55] += m[55] * mu\n\t" + "ldr r7, [%[m], #220]\n\t" + "ldr r9, [%[a], #220]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #220]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+56] += m[56] * mu\n\t" + "ldr r7, [%[m], #224]\n\t" + "ldr r9, [%[a], #224]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #224]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+57] += m[57] * mu\n\t" + "ldr r7, [%[m], #228]\n\t" + "ldr r9, [%[a], #228]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #228]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+58] += m[58] * mu\n\t" + "ldr r7, [%[m], #232]\n\t" + "ldr r9, [%[a], #232]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #232]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+59] += m[59] * mu\n\t" + "ldr r7, [%[m], #236]\n\t" + "ldr r9, [%[a], #236]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #236]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+60] += m[60] * mu\n\t" + "ldr r7, [%[m], #240]\n\t" + "ldr r9, [%[a], #240]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #240]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+61] += m[61] * mu\n\t" + "ldr r7, [%[m], #244]\n\t" + "ldr r9, [%[a], #244]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #244]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+62] += m[62] * mu\n\t" + "ldr r7, [%[m], #248]\n\t" + "ldr r9, [%[a], #248]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #248]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+63] += m[63] * mu\n\t" + "ldr r7, [%[m], #252]\n\t" + "ldr r9, [%[a], #252]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r7, r7, %[ca]\n\t" + "mov %[ca], #0\n\t" + "adc %[ca], %[ca], %[ca]\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #252]\n\t" + "ldr r9, [%[a], #256]\n\t" + "adcs r9, r9, r7\n\t" + "str r9, [%[a], #256]\n\t" + "adc %[ca], %[ca], #0\n\t" + "# i += 1\n\t" + "add %[a], %[a], #4\n\t" + "add r12, r12, #4\n\t" + "cmp r12, #256\n\t" + "blt 1b\n\t" + "str r10, [%[a], #0]\n\t" + "str r14, [%[a], #4]\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + sp_2048_cond_sub_64(a - 64, a, m, (sp_digit)0 - ca); +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_2048_mont_mul_64(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_2048_mul_64(r, a, b); + sp_2048_mont_reduce_64(r, m, mp); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_2048_mont_sqr_64(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_2048_sqr_64(r, a); + sp_2048_mont_reduce_64(r, m, mp); +} + +#ifndef WOLFSSL_RSA_PUBLIC_ONLY +/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) + * + * d1 The high order half of the number to divide. + * d0 The low order half of the number to divide. + * div The dividend. + * returns the result of the division. + * + * Note that this is an approximate div. It may give an answer 1 larger. + */ +static sp_digit div_2048_word_64(sp_digit d1, sp_digit d0, sp_digit div) +{ + sp_digit r = 0; + + __asm__ __volatile__ ( + "lsr r5, %[div], #1\n\t" + "add r5, r5, #1\n\t" + "mov r6, %[d0]\n\t" + "mov r7, %[d1]\n\t" + "# Do top 32\n\t" + "subs r8, r5, r7\n\t" + "sbc r8, r8, r8\n\t" + "add %[r], %[r], %[r]\n\t" + "sub %[r], %[r], r8\n\t" + "and r8, r8, r5\n\t" + "subs r7, r7, r8\n\t" + "# Next 30 bits\n\t" + "mov r4, #29\n\t" + "1:\n\t" + "movs r6, r6, lsl #1\n\t" + "adc r7, r7, r7\n\t" + "subs r8, r5, r7\n\t" + "sbc r8, r8, r8\n\t" + "add %[r], %[r], %[r]\n\t" + "sub %[r], %[r], r8\n\t" + "and r8, r8, r5\n\t" + "subs r7, r7, r8\n\t" + "subs r4, r4, #1\n\t" + "bpl 1b\n\t" + "add %[r], %[r], %[r]\n\t" + "add %[r], %[r], #1\n\t" + "umull r4, r5, %[r], %[div]\n\t" + "subs r4, %[d0], r4\n\t" + "sbc r5, %[d1], r5\n\t" + "add %[r], %[r], r5\n\t" + "umull r4, r5, %[r], %[div]\n\t" + "subs r4, %[d0], r4\n\t" + "sbc r5, %[d1], r5\n\t" + "add %[r], %[r], r5\n\t" + "subs r8, %[div], r4\n\t" + "sbc r8, r8, r8\n\t" + "sub %[r], %[r], r8\n\t" + : [r] "+r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "r4", "r5", "r6", "r7", "r8" + ); + return r; +} + +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_2048_mask_64(sp_digit* r, sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<64; i++) + r[i] = a[i] & m; +#else + int i; + + for (i = 0; i < 64; i += 8) { + r[i+0] = a[i+0] & m; + r[i+1] = a[i+1] & m; + r[i+2] = a[i+2] & m; + r[i+3] = a[i+3] & m; + r[i+4] = a[i+4] & m; + r[i+5] = a[i+5] & m; + r[i+6] = a[i+6] & m; + r[i+7] = a[i+7] & m; + } +#endif +} + +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +static int32_t sp_2048_cmp_64(sp_digit* a, sp_digit* b) +{ + sp_digit r = -1; + sp_digit one = 1; + + +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov r7, #0\n\t" + "mov r3, #-1\n\t" + "mov r6, #252\n\t" + "1:\n\t" + "ldr r4, [%[a], r6]\n\t" + "ldr r5, [%[b], r6]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "sub r6, r6, #4\n\t" + "bcc 1b\n\t" + "eor %[r], %[r], r3\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [one] "r" (one) + : "r3", "r4", "r5", "r6", "r7" + ); +#else + __asm__ __volatile__ ( + "mov r7, #0\n\t" + "mov r3, #-1\n\t" + "ldr r4, [%[a], #252]\n\t" + "ldr r5, [%[b], #252]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #248]\n\t" + "ldr r5, [%[b], #248]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #244]\n\t" + "ldr r5, [%[b], #244]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #240]\n\t" + "ldr r5, [%[b], #240]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #236]\n\t" + "ldr r5, [%[b], #236]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #232]\n\t" + "ldr r5, [%[b], #232]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #228]\n\t" + "ldr r5, [%[b], #228]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #224]\n\t" + "ldr r5, [%[b], #224]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #220]\n\t" + "ldr r5, [%[b], #220]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #216]\n\t" + "ldr r5, [%[b], #216]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #212]\n\t" + "ldr r5, [%[b], #212]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #208]\n\t" + "ldr r5, [%[b], #208]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #204]\n\t" + "ldr r5, [%[b], #204]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #200]\n\t" + "ldr r5, [%[b], #200]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #196]\n\t" + "ldr r5, [%[b], #196]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #192]\n\t" + "ldr r5, [%[b], #192]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #188]\n\t" + "ldr r5, [%[b], #188]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #184]\n\t" + "ldr r5, [%[b], #184]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #180]\n\t" + "ldr r5, [%[b], #180]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #176]\n\t" + "ldr r5, [%[b], #176]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #172]\n\t" + "ldr r5, [%[b], #172]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #168]\n\t" + "ldr r5, [%[b], #168]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #164]\n\t" + "ldr r5, [%[b], #164]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #160]\n\t" + "ldr r5, [%[b], #160]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #156]\n\t" + "ldr r5, [%[b], #156]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #152]\n\t" + "ldr r5, [%[b], #152]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #148]\n\t" + "ldr r5, [%[b], #148]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #144]\n\t" + "ldr r5, [%[b], #144]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #140]\n\t" + "ldr r5, [%[b], #140]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #136]\n\t" + "ldr r5, [%[b], #136]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #132]\n\t" + "ldr r5, [%[b], #132]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #128]\n\t" + "ldr r5, [%[b], #128]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #124]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[b], #120]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #116]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[b], #112]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #108]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[b], #104]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #100]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[b], #96]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #92]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[b], #88]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #84]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[b], #80]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #76]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[b], #72]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #68]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[b], #64]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #60]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[b], #56]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #52]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[b], #48]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "eor %[r], %[r], r3\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [one] "r" (one) + : "r3", "r4", "r5", "r6", "r7" + ); +#endif + + return r; +} + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_2048_div_64(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[128], t2[65]; + sp_digit div, r1; + int i; + + (void)m; + + div = d[63]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 64); + for (i=63; i>=0; i--) { + r1 = div_2048_word_64(t1[64 + i], t1[64 + i - 1], div); + + sp_2048_mul_d_64(t2, d, r1); + t1[64 + i] += sp_2048_sub_in_place_64(&t1[i], t2); + t1[64 + i] -= t2[64]; + sp_2048_mask_64(t2, d, t1[64 + i]); + t1[64 + i] += sp_2048_add_64(&t1[i], &t1[i], t2); + sp_2048_mask_64(t2, d, t1[64 + i]); + t1[64 + i] += sp_2048_add_64(&t1[i], &t1[i], t2); + } + + r1 = sp_2048_cmp_64(t1, d) >= 0; + sp_2048_cond_sub_64(r, t1, d, (sp_digit)0 - r1); + + return MP_OKAY; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_2048_mod_64(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_2048_div_64(a, m, NULL, r); +} + +#endif /* WOLFSSL_RSA_PUBLIC_ONLY */ +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_2048_div_64_cond(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[128], t2[65]; + sp_digit div, r1; + int i; + + (void)m; + + div = d[63]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 64); + for (i=63; i>=0; i--) { + r1 = div_2048_word_64(t1[64 + i], t1[64 + i - 1], div); + + sp_2048_mul_d_64(t2, d, r1); + t1[64 + i] += sp_2048_sub_in_place_64(&t1[i], t2); + t1[64 + i] -= t2[64]; + if (t1[64 + i] != 0) { + t1[64 + i] += sp_2048_add_64(&t1[i], &t1[i], d); + if (t1[64 + i] != 0) + t1[64 + i] += sp_2048_add_64(&t1[i], &t1[i], d); + } + } + + r1 = sp_2048_cmp_64(t1, d) >= 0; + sp_2048_cond_sub_64(r, t1, d, (sp_digit)0 - r1); + + return MP_OKAY; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_2048_mod_64_cond(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_2048_div_64_cond(a, m, NULL, r); +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \ + defined(WOLFSSL_HAVE_SP_DH) +#ifdef WOLFSSL_SP_SMALL +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_2048_mod_exp_64(sp_digit* r, sp_digit* a, sp_digit* e, + int bits, sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[16][128]; +#else + sp_digit* t[16]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 128, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<16; i++) + t[i] = td + i * 128; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_64(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 64); + if (reduceA) { + err = sp_2048_mod_64(t[1] + 64, a, m); + if (err == MP_OKAY) + err = sp_2048_mod_64(t[1], t[1], m); + } + else { + XMEMCPY(t[1] + 64, a, sizeof(sp_digit) * 64); + err = sp_2048_mod_64(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_2048_mont_sqr_64(t[ 2], t[ 1], m, mp); + sp_2048_mont_mul_64(t[ 3], t[ 2], t[ 1], m, mp); + sp_2048_mont_sqr_64(t[ 4], t[ 2], m, mp); + sp_2048_mont_mul_64(t[ 5], t[ 3], t[ 2], m, mp); + sp_2048_mont_sqr_64(t[ 6], t[ 3], m, mp); + sp_2048_mont_mul_64(t[ 7], t[ 4], t[ 3], m, mp); + sp_2048_mont_sqr_64(t[ 8], t[ 4], m, mp); + sp_2048_mont_mul_64(t[ 9], t[ 5], t[ 4], m, mp); + sp_2048_mont_sqr_64(t[10], t[ 5], m, mp); + sp_2048_mont_mul_64(t[11], t[ 6], t[ 5], m, mp); + sp_2048_mont_sqr_64(t[12], t[ 6], m, mp); + sp_2048_mont_mul_64(t[13], t[ 7], t[ 6], m, mp); + sp_2048_mont_sqr_64(t[14], t[ 7], m, mp); + sp_2048_mont_mul_64(t[15], t[ 8], t[ 7], m, mp); + + i = (bits - 1) / 32; + n = e[i--]; + y = n >> 28; + n <<= 4; + c = 28; + XMEMCPY(r, t[y], sizeof(sp_digit) * 64); + for (; i>=0 || c>=4; ) { + if (c == 0) { + n = e[i--]; + y = n >> 28; + n <<= 4; + c = 28; + } + else if (c < 4) { + y = n >> 28; + n = e[i--]; + c = 4 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 28) & 0xf; + n <<= 4; + c -= 4; + } + + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + + sp_2048_mont_mul_64(r, r, t[y], m, mp); + } + y = e[0] & ((1 << c) - 1); + for (; c > 0; c--) + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_mul_64(r, r, t[y], m, mp); + + XMEMSET(&r[64], 0, sizeof(sp_digit) * 64); + sp_2048_mont_reduce_64(r, m, mp); + + mask = 0 - (sp_2048_cmp_64(r, m) >= 0); + sp_2048_cond_sub_64(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#else +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_2048_mod_exp_64(sp_digit* r, sp_digit* a, sp_digit* e, + int bits, sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][128]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 128, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<32; i++) + t[i] = td + i * 128; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_64(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 64); + if (reduceA) { + err = sp_2048_mod_64(t[1] + 64, a, m); + if (err == MP_OKAY) + err = sp_2048_mod_64(t[1], t[1], m); + } + else { + XMEMCPY(t[1] + 64, a, sizeof(sp_digit) * 64); + err = sp_2048_mod_64(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_2048_mont_sqr_64(t[ 2], t[ 1], m, mp); + sp_2048_mont_mul_64(t[ 3], t[ 2], t[ 1], m, mp); + sp_2048_mont_sqr_64(t[ 4], t[ 2], m, mp); + sp_2048_mont_mul_64(t[ 5], t[ 3], t[ 2], m, mp); + sp_2048_mont_sqr_64(t[ 6], t[ 3], m, mp); + sp_2048_mont_mul_64(t[ 7], t[ 4], t[ 3], m, mp); + sp_2048_mont_sqr_64(t[ 8], t[ 4], m, mp); + sp_2048_mont_mul_64(t[ 9], t[ 5], t[ 4], m, mp); + sp_2048_mont_sqr_64(t[10], t[ 5], m, mp); + sp_2048_mont_mul_64(t[11], t[ 6], t[ 5], m, mp); + sp_2048_mont_sqr_64(t[12], t[ 6], m, mp); + sp_2048_mont_mul_64(t[13], t[ 7], t[ 6], m, mp); + sp_2048_mont_sqr_64(t[14], t[ 7], m, mp); + sp_2048_mont_mul_64(t[15], t[ 8], t[ 7], m, mp); + sp_2048_mont_sqr_64(t[16], t[ 8], m, mp); + sp_2048_mont_mul_64(t[17], t[ 9], t[ 8], m, mp); + sp_2048_mont_sqr_64(t[18], t[ 9], m, mp); + sp_2048_mont_mul_64(t[19], t[10], t[ 9], m, mp); + sp_2048_mont_sqr_64(t[20], t[10], m, mp); + sp_2048_mont_mul_64(t[21], t[11], t[10], m, mp); + sp_2048_mont_sqr_64(t[22], t[11], m, mp); + sp_2048_mont_mul_64(t[23], t[12], t[11], m, mp); + sp_2048_mont_sqr_64(t[24], t[12], m, mp); + sp_2048_mont_mul_64(t[25], t[13], t[12], m, mp); + sp_2048_mont_sqr_64(t[26], t[13], m, mp); + sp_2048_mont_mul_64(t[27], t[14], t[13], m, mp); + sp_2048_mont_sqr_64(t[28], t[14], m, mp); + sp_2048_mont_mul_64(t[29], t[15], t[14], m, mp); + sp_2048_mont_sqr_64(t[30], t[15], m, mp); + sp_2048_mont_mul_64(t[31], t[16], t[15], m, mp); + + i = (bits - 1) / 32; + n = e[i--]; + y = n >> 27; + n <<= 5; + c = 27; + XMEMCPY(r, t[y], sizeof(sp_digit) * 64); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 27; + n <<= 5; + c = 27; + } + else if (c < 5) { + y = n >> 27; + n = e[i--]; + c = 5 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 27) & 0x1f; + n <<= 5; + c -= 5; + } + + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + + sp_2048_mont_mul_64(r, r, t[y], m, mp); + } + y = e[0] & ((1 << c) - 1); + for (; c > 0; c--) + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_mul_64(r, r, t[y], m, mp); + + XMEMSET(&r[64], 0, sizeof(sp_digit) * 64); + sp_2048_mont_reduce_64(r, m, mp); + + mask = 0 - (sp_2048_cmp_64(r, m) >= 0); + sp_2048_cond_sub_64(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#endif /* WOLFSSL_SP_SMALL */ +#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ + +#ifdef WOLFSSL_HAVE_SP_RSA +/* RSA public key operation. + * + * in Array of bytes representing the number to exponentiate, base. + * inLen Number of bytes in base. + * em Public exponent. + * mm Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 256 bytes long. + * outLen Number of bytes in result. + * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when + * an array is too long and MEMORY_E when dynamic memory allocation fails. + */ +int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm, + byte* out, word32* outLen) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit ad[128], md[64], rd[128]; +#else + sp_digit* d = NULL; +#endif + sp_digit* a; + sp_digit *ah; + sp_digit* m; + sp_digit* r; + sp_digit e[1]; + int err = MP_OKAY; + + if (*outLen < 256) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(em) > 32 || inLen > 256 || + mp_count_bits(mm) != 2048)) + err = MP_READ_E; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 64 * 5, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + a = d; + r = a + 64 * 2; + m = r + 64 * 2; + ah = a + 64; + } +#else + a = ad; + m = md; + r = rd; + ah = a + 64; +#endif + + if (err == MP_OKAY) { + sp_2048_from_bin(ah, 64, in, inLen); +#if DIGIT_BIT >= 32 + e[0] = em->dp[0]; +#else + e[0] = em->dp[0]; + if (em->used > 1) + e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT; +#endif + if (e[0] == 0) + err = MP_EXPTMOD_E; + } + if (err == MP_OKAY) { + sp_2048_from_mp(m, 64, mm); + + if (e[0] == 0x3) { + if (err == MP_OKAY) { + sp_2048_sqr_64(r, ah); + err = sp_2048_mod_64_cond(r, r, m); + } + if (err == MP_OKAY) { + sp_2048_mul_64(r, ah, r); + err = sp_2048_mod_64_cond(r, r, m); + } + } + else { + int i; + sp_digit mp; + + sp_2048_mont_setup(m, &mp); + + /* Convert to Montgomery form. */ + XMEMSET(a, 0, sizeof(sp_digit) * 64); + err = sp_2048_mod_64_cond(a, a, m); + + if (err == MP_OKAY) { + for (i=31; i>=0; i--) + if (e[0] >> i) + break; + + XMEMCPY(r, a, sizeof(sp_digit) * 64); + for (i--; i>=0; i--) { + sp_2048_mont_sqr_64(r, r, m, mp); + if (((e[0] >> i) & 1) == 1) + sp_2048_mont_mul_64(r, r, a, m, mp); + } + XMEMSET(&r[64], 0, sizeof(sp_digit) * 64); + sp_2048_mont_reduce_64(r, m, mp); + + for (i = 63; i > 0; i--) { + if (r[i] != m[i]) + break; + } + if (r[i] >= m[i]) + sp_2048_sub_in_place_64(r, m); + } + } + } + + if (err == MP_OKAY) { + sp_2048_to_bin(r, out); + *outLen = 256; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_RSA); +#endif + + return err; +} + +#ifndef WOLFSSL_RSA_PUBLIC_ONLY +/* RSA private key operation. + * + * in Array of bytes representing the number to exponentiate, base. + * inLen Number of bytes in base. + * dm Private exponent. + * pm First prime. + * qm Second prime. + * dpm First prime's CRT exponent. + * dqm Second prime's CRT exponent. + * qim Inverse of second prime mod p. + * mm Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 256 bytes long. + * outLen Number of bytes in result. + * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when + * an array is too long and MEMORY_E when dynamic memory allocation fails. + */ +int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, + mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm, + byte* out, word32* outLen) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit ad[64 * 2]; + sp_digit pd[32], qd[32], dpd[32]; + sp_digit tmpad[64], tmpbd[64]; +#else + sp_digit* t = NULL; +#endif + sp_digit* a; + sp_digit* p; + sp_digit* q; + sp_digit* dp; + sp_digit* dq; + sp_digit* qi; + sp_digit* tmp; + sp_digit* tmpa; + sp_digit* tmpb; + sp_digit* r; + sp_digit c; + int err = MP_OKAY; + + (void)dm; + (void)mm; + + if (*outLen < 256) + err = MP_TO_E; + if (err == MP_OKAY && (inLen > 256 || mp_count_bits(mm) != 2048)) + err = MP_READ_E; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 11, NULL, + DYNAMIC_TYPE_RSA); + if (t == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + a = t; + p = a + 64 * 2; + q = p + 32; + qi = dq = dp = q + 32; + tmpa = qi + 32; + tmpb = tmpa + 64; + + tmp = t; + r = tmp + 64; + } +#else + r = a = ad; + p = pd; + q = qd; + qi = dq = dp = dpd; + tmpa = tmpad; + tmpb = tmpbd; + tmp = a + 64; +#endif + + if (err == MP_OKAY) { + sp_2048_from_bin(a, 64, in, inLen); + sp_2048_from_mp(p, 32, pm); + sp_2048_from_mp(q, 32, qm); + sp_2048_from_mp(dp, 32, dpm); + + err = sp_2048_mod_exp_32(tmpa, a, dp, 1024, p, 1); + } + if (err == MP_OKAY) { + sp_2048_from_mp(dq, 32, dqm); + err = sp_2048_mod_exp_32(tmpb, a, dq, 1024, q, 1); + } + + if (err == MP_OKAY) { + c = sp_2048_sub_in_place_32(tmpa, tmpb); + sp_2048_mask_32(tmp, p, c); + sp_2048_add_32(tmpa, tmpa, tmp); + + sp_2048_from_mp(qi, 32, qim); + sp_2048_mul_32(tmpa, tmpa, qi); + err = sp_2048_mod_32(tmpa, tmpa, p); + } + + if (err == MP_OKAY) { + sp_2048_mul_32(tmpa, q, tmpa); + XMEMSET(&tmpb[32], 0, sizeof(sp_digit) * 32); + sp_2048_add_64(r, tmpb, tmpa); + + sp_2048_to_bin(r, out); + *outLen = 256; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_digit) * 32 * 11); + XFREE(t, NULL, DYNAMIC_TYPE_RSA); + } +#else + XMEMSET(tmpad, 0, sizeof(tmpad)); + XMEMSET(tmpbd, 0, sizeof(tmpbd)); + XMEMSET(pd, 0, sizeof(pd)); + XMEMSET(qd, 0, sizeof(qd)); + XMEMSET(dpd, 0, sizeof(dpd)); +#endif + + return err; +} +#endif +#endif /* WOLFSSL_HAVE_SP_RSA */ +#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \ + !defined(WOLFSSL_RSA_PUBLIC_ONLY)) +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_2048_to_mp(sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (2048 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { +#if DIGIT_BIT == 32 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 64); + r->used = 64; + mp_clamp(r); +#elif DIGIT_BIT < 32 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 64; i++) { + r->dp[j] |= a[i] << s; + r->dp[j] &= (1l << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + while (s + DIGIT_BIT <= 32) { + s += DIGIT_BIT; + r->dp[j] &= (1l << DIGIT_BIT) - 1; + r->dp[++j] = a[i] >> s; + } + s = 32 - s; + } + r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 64; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 32 >= DIGIT_BIT) { + #if DIGIT_BIT < 32 + r->dp[j] &= (1l << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 32 - s; + } + else + s += 32; + } + r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returs 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ + int err = MP_OKAY; + sp_digit b[128], e[64], m[64]; + sp_digit* r = b; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 2048 || expBits > 2048 || + mp_count_bits(mod) != 2048) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + sp_2048_from_mp(b, 64, base); + sp_2048_from_mp(e, 64, exp); + sp_2048_from_mp(m, 64, mod); + + err = sp_2048_mod_exp_64(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + err = sp_2048_to_mp(r, res); + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} + +#ifdef WOLFSSL_HAVE_SP_DH +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. + * exp Array of bytes that is the exponent. + * expLen Length of data, in bytes, in exponent. + * mod Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 256 bytes long. + * outLen Length, in bytes, of exponentiation result. + * returs 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen, + mp_int* mod, byte* out, word32* outLen) +{ + int err = MP_OKAY; + sp_digit b[128], e[64], m[64]; + sp_digit* r = b; + word32 i; + + if (mp_count_bits(base) > 2048 || expLen > 256 || + mp_count_bits(mod) != 2048) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + sp_2048_from_mp(b, 64, base); + sp_2048_from_bin(e, 64, exp, expLen); + sp_2048_from_mp(m, 64, mod); + + err = sp_2048_mod_exp_64(r, b, e, expLen * 8, m, 0); + } + + if (err == MP_OKAY) { + sp_2048_to_bin(r, out); + *outLen = 256; + for (i=0; i<256 && out[i] == 0; i++) { + } + *outLen -= i; + XMEMMOVE(out, out + i, *outLen); + + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} +#endif /* WOLFSSL_HAVE_SP_DH */ + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returs 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ + int err = MP_OKAY; + sp_digit b[64], e[32], m[32]; + sp_digit* r = b; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 1024 || expBits > 1024 || + mp_count_bits(mod) != 1024) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + sp_2048_from_mp(b, 32, base); + sp_2048_from_mp(e, 32, exp); + sp_2048_from_mp(m, 32, mod); + + err = sp_2048_mod_exp_32(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + XMEMSET(r + 32, 0, sizeof(*r) * 32); + err = sp_2048_to_mp(r, res); + res->used = mod->used; + mp_clamp(res); + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} + +#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ + +#endif /* !WOLFSSL_SP_NO_2048 */ + +#ifndef WOLFSSL_SP_NO_3072 +/* Read big endian unsigned byte aray into r. + * + * r A single precision integer. + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_3072_from_bin(sp_digit* r, int max, const byte* a, int n) +{ + int i, j = 0, s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= ((sp_digit)a[i]) << s; + if (s >= 24) { + r[j] &= 0xffffffff; + s = 32 - s; + if (j + 1 >= max) + break; + r[++j] = a[i] >> s; + s = 8 - s; + } + else + s += 8; + } + + for (j++; j < max; j++) + r[j] = 0; +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * a A multi-precision integer. + */ +static void sp_3072_from_mp(sp_digit* r, int max, mp_int* a) +{ +#if DIGIT_BIT == 32 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < max; j++) + r[j] = 0; +#elif DIGIT_BIT > 32 + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= a->dp[i] << s; + r[j] &= 0xffffffff; + s = 32 - s; + if (j + 1 >= max) + break; + r[++j] = a->dp[i] >> s; + while (s + 32 <= DIGIT_BIT) { + s += 32; + r[j] &= 0xffffffff; + if (j + 1 >= max) + break; + if (s < DIGIT_BIT) + r[++j] = a->dp[i] >> s; + else + r[++j] = 0; + } + s = DIGIT_BIT - s; + } + + for (j++; j < max; j++) + r[j] = 0; +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 32) { + r[j] &= 0xffffffff; + if (j + 1 >= max) + break; + s = 32 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else + s += DIGIT_BIT; + } + + for (j++; j < max; j++) + r[j] = 0; +#endif +} + +/* Write r as big endian to byte aray. + * Fixed length number of bytes written: 384 + * + * r A single precision integer. + * a Byte array. + */ +static void sp_3072_to_bin(sp_digit* r, byte* a) +{ + int i, j, s = 0, b; + + j = 3072 / 8 - 1; + a[j] = 0; + for (i=0; i<96 && j>=0; i++) { + b = 0; + a[j--] |= r[i] << s; b += 8 - s; + if (j < 0) + break; + while (b < 32) { + a[j--] = r[i] >> b; b += 8; + if (j < 0) + break; + } + s = 8 - (b - 32); + if (j >= 0) + a[j] = 0; + if (s != 0) + j++; + } +} + +#ifndef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_3072_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + __asm__ __volatile__ ( + "sub sp, sp, #32\n\t" + "mov r10, #0\n\t" + "# A[0] * B[0]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r3, r4, r8, r9\n\t" + "mov r5, #0\n\t" + "str r3, [sp]\n\t" + "# A[0] * B[1]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[1] * B[0]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #4]\n\t" + "# A[0] * B[2]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[1] * B[1]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[2] * B[0]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [sp, #8]\n\t" + "# A[0] * B[3]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[1] * B[2]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[2] * B[1]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[0]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [sp, #12]\n\t" + "# A[0] * B[4]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[1] * B[3]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[2] * B[2]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[3] * B[1]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[4] * B[0]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #16]\n\t" + "# A[0] * B[5]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[1] * B[4]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[2] * B[3]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[3] * B[2]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[4] * B[1]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[5] * B[0]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [sp, #20]\n\t" + "# A[0] * B[6]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[1] * B[5]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[2] * B[4]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[3]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[4] * B[2]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[5] * B[1]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[6] * B[0]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [sp, #24]\n\t" + "# A[0] * B[7]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[1] * B[6]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[2] * B[5]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[3] * B[4]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[4] * B[3]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[5] * B[2]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[6] * B[1]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[7] * B[0]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #28]\n\t" + "# A[1] * B[7]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[2] * B[6]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[3] * B[5]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[4] * B[4]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[5] * B[3]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[6] * B[2]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[7] * B[1]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #32]\n\t" + "# A[2] * B[7]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[3] * B[6]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[4] * B[5]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[5] * B[4]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[6] * B[3]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[7] * B[2]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #36]\n\t" + "# A[3] * B[7]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[4] * B[6]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[5] * B[5]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[6] * B[4]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[7] * B[3]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #40]\n\t" + "# A[4] * B[7]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[5] * B[6]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[6] * B[5]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[7] * B[4]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #44]\n\t" + "# A[5] * B[7]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[6] * B[6]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[7] * B[5]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #48]\n\t" + "# A[6] * B[7]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[7] * B[6]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #52]\n\t" + "# A[7] * B[7]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adc r3, r3, r7\n\t" + "str r5, [%[r], #56]\n\t" + "str r3, [%[r], #60]\n\t" + "ldr r3, [sp, #0]\n\t" + "ldr r4, [sp, #4]\n\t" + "ldr r5, [sp, #8]\n\t" + "ldr r6, [sp, #12]\n\t" + "str r3, [%[r], #0]\n\t" + "str r4, [%[r], #4]\n\t" + "str r5, [%[r], #8]\n\t" + "str r6, [%[r], #12]\n\t" + "ldr r3, [sp, #16]\n\t" + "ldr r4, [sp, #20]\n\t" + "ldr r5, [sp, #24]\n\t" + "ldr r6, [sp, #28]\n\t" + "str r3, [%[r], #16]\n\t" + "str r4, [%[r], #20]\n\t" + "str r5, [%[r], #24]\n\t" + "str r6, [%[r], #28]\n\t" + "add sp, sp, #32\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10" + ); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_3072_sqr_8(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "sub sp, sp, #32\n\t" + "mov r14, #0\n\t" + "# A[0] * A[0]\n\t" + "ldr r10, [%[a], #0]\n\t" + "umull r8, r3, r10, r10\n\t" + "mov r4, #0\n\t" + "str r8, [sp]\n\t" + "# A[0] * A[1]\n\t" + "ldr r10, [%[a], #4]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r14, r14\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "str r3, [sp, #4]\n\t" + "# A[0] * A[2]\n\t" + "ldr r10, [%[a], #8]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r14, r14\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r14\n\t" + "# A[1] * A[1]\n\t" + "ldr r10, [%[a], #4]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r14\n\t" + "str r4, [sp, #8]\n\t" + "# A[0] * A[3]\n\t" + "ldr r10, [%[a], #12]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r14, r14\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r14\n\t" + "# A[1] * A[2]\n\t" + "ldr r10, [%[a], #8]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r14\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r14\n\t" + "str r2, [sp, #12]\n\t" + "# A[0] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r14, r14\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "# A[1] * A[3]\n\t" + "ldr r10, [%[a], #12]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "# A[2] * A[2]\n\t" + "ldr r10, [%[a], #8]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "str r3, [sp, #16]\n\t" + "# A[0] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[3]\n\t" + "ldr r10, [%[a], #12]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [sp, #20]\n\t" + "# A[0] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[3]\n\t" + "ldr r10, [%[a], #12]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [sp, #24]\n\t" + "# A[0] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [sp, #28]\n\t" + "# A[1] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[2] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [%[r], #32]\n\t" + "# A[2] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[3] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [%[r], #36]\n\t" + "# A[3] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r14, r14\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "# A[4] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "# A[5] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "str r3, [%[r], #40]\n\t" + "# A[4] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r14, r14\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r14\n\t" + "# A[5] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r14\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r14\n\t" + "str r4, [%[r], #44]\n\t" + "# A[5] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r14, r14\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r14\n\t" + "# A[6] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r14\n\t" + "str r2, [%[r], #48]\n\t" + "# A[6] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r14, r14\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "str r3, [%[r], #52]\n\t" + "# A[7] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r4, r4, r8\n\t" + "adc r2, r2, r9\n\t" + "str r4, [%[r], #56]\n\t" + "str r2, [%[r], #60]\n\t" + "ldr r2, [sp, #0]\n\t" + "ldr r3, [sp, #4]\n\t" + "ldr r4, [sp, #8]\n\t" + "ldr r8, [sp, #12]\n\t" + "str r2, [%[r], #0]\n\t" + "str r3, [%[r], #4]\n\t" + "str r4, [%[r], #8]\n\t" + "str r8, [%[r], #12]\n\t" + "ldr r2, [sp, #16]\n\t" + "ldr r3, [sp, #20]\n\t" + "ldr r4, [sp, #24]\n\t" + "ldr r8, [sp, #28]\n\t" + "str r2, [%[r], #16]\n\t" + "str r3, [%[r], #20]\n\t" + "str r4, [%[r], #24]\n\t" + "str r8, [%[r], #28]\n\t" + "add sp, sp, #32\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r8", "r9", "r10", "r8", "r5", "r6", "r7", "r14" + ); +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_3072_add_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r12, #0\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[a], #4]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #12]\n\t" + "ldr r8, [%[b], #0]\n\t" + "ldr r9, [%[b], #4]\n\t" + "ldr r10, [%[b], #8]\n\t" + "ldr r14, [%[b], #12]\n\t" + "adds r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #0]\n\t" + "str r5, [%[r], #4]\n\t" + "str r6, [%[r], #8]\n\t" + "str r7, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[a], #20]\n\t" + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[a], #28]\n\t" + "ldr r8, [%[b], #16]\n\t" + "ldr r9, [%[b], #20]\n\t" + "ldr r10, [%[b], #24]\n\t" + "ldr r14, [%[b], #28]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #16]\n\t" + "str r5, [%[r], #20]\n\t" + "str r6, [%[r], #24]\n\t" + "str r7, [%[r], #28]\n\t" + "adc %[c], r12, r12\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + return c; +} + +/* Sub b from a into a. (a -= b) + * + * a A single precision integer and result. + * b A single precision integer. + */ +static sp_digit sp_3072_sub_in_place_16(sp_digit* a, const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r2, [%[a], #0]\n\t" + "ldr r3, [%[a], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[a], #12]\n\t" + "ldr r6, [%[b], #0]\n\t" + "ldr r7, [%[b], #4]\n\t" + "ldr r8, [%[b], #8]\n\t" + "ldr r9, [%[b], #12]\n\t" + "subs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #0]\n\t" + "str r3, [%[a], #4]\n\t" + "str r4, [%[a], #8]\n\t" + "str r5, [%[a], #12]\n\t" + "ldr r2, [%[a], #16]\n\t" + "ldr r3, [%[a], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[a], #28]\n\t" + "ldr r6, [%[b], #16]\n\t" + "ldr r7, [%[b], #20]\n\t" + "ldr r8, [%[b], #24]\n\t" + "ldr r9, [%[b], #28]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #16]\n\t" + "str r3, [%[a], #20]\n\t" + "str r4, [%[a], #24]\n\t" + "str r5, [%[a], #28]\n\t" + "ldr r2, [%[a], #32]\n\t" + "ldr r3, [%[a], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[a], #44]\n\t" + "ldr r6, [%[b], #32]\n\t" + "ldr r7, [%[b], #36]\n\t" + "ldr r8, [%[b], #40]\n\t" + "ldr r9, [%[b], #44]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #32]\n\t" + "str r3, [%[a], #36]\n\t" + "str r4, [%[a], #40]\n\t" + "str r5, [%[a], #44]\n\t" + "ldr r2, [%[a], #48]\n\t" + "ldr r3, [%[a], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[a], #60]\n\t" + "ldr r6, [%[b], #48]\n\t" + "ldr r7, [%[b], #52]\n\t" + "ldr r8, [%[b], #56]\n\t" + "ldr r9, [%[b], #60]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #48]\n\t" + "str r3, [%[a], #52]\n\t" + "str r4, [%[a], #56]\n\t" + "str r5, [%[a], #60]\n\t" + "sbc %[c], r9, r9\n\t" + : [c] "+r" (c) + : [a] "r" (a), [b] "r" (b) + : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9" + ); + + return c; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_3072_add_16(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r12, #0\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[a], #4]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #12]\n\t" + "ldr r8, [%[b], #0]\n\t" + "ldr r9, [%[b], #4]\n\t" + "ldr r10, [%[b], #8]\n\t" + "ldr r14, [%[b], #12]\n\t" + "adds r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #0]\n\t" + "str r5, [%[r], #4]\n\t" + "str r6, [%[r], #8]\n\t" + "str r7, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[a], #20]\n\t" + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[a], #28]\n\t" + "ldr r8, [%[b], #16]\n\t" + "ldr r9, [%[b], #20]\n\t" + "ldr r10, [%[b], #24]\n\t" + "ldr r14, [%[b], #28]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #16]\n\t" + "str r5, [%[r], #20]\n\t" + "str r6, [%[r], #24]\n\t" + "str r7, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[a], #36]\n\t" + "ldr r6, [%[a], #40]\n\t" + "ldr r7, [%[a], #44]\n\t" + "ldr r8, [%[b], #32]\n\t" + "ldr r9, [%[b], #36]\n\t" + "ldr r10, [%[b], #40]\n\t" + "ldr r14, [%[b], #44]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #32]\n\t" + "str r5, [%[r], #36]\n\t" + "str r6, [%[r], #40]\n\t" + "str r7, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[a], #52]\n\t" + "ldr r6, [%[a], #56]\n\t" + "ldr r7, [%[a], #60]\n\t" + "ldr r8, [%[b], #48]\n\t" + "ldr r9, [%[b], #52]\n\t" + "ldr r10, [%[b], #56]\n\t" + "ldr r14, [%[b], #60]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #48]\n\t" + "str r5, [%[r], #52]\n\t" + "str r6, [%[r], #56]\n\t" + "str r7, [%[r], #60]\n\t" + "adc %[c], r12, r12\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + return c; +} + +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_3072_mask_8(sp_digit* r, sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<8; i++) + r[i] = a[i] & m; +#else + r[0] = a[0] & m; + r[1] = a[1] & m; + r[2] = a[2] & m; + r[3] = a[3] & m; + r[4] = a[4] & m; + r[5] = a[5] & m; + r[6] = a[6] & m; + r[7] = a[7] & m; +#endif +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_3072_mul_16(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[16]; + sp_digit a1[8]; + sp_digit b1[8]; + sp_digit z2[16]; + sp_digit u, ca, cb; + + ca = sp_3072_add_8(a1, a, &a[8]); + cb = sp_3072_add_8(b1, b, &b[8]); + u = ca & cb; + sp_3072_mul_8(z1, a1, b1); + sp_3072_mul_8(z2, &a[8], &b[8]); + sp_3072_mul_8(z0, a, b); + sp_3072_mask_8(r + 16, a1, 0 - cb); + sp_3072_mask_8(b1, b1, 0 - ca); + u += sp_3072_add_8(r + 16, r + 16, b1); + u += sp_3072_sub_in_place_16(z1, z2); + u += sp_3072_sub_in_place_16(z1, z0); + u += sp_3072_add_16(r + 8, r + 8, z1); + r[24] = u; + XMEMSET(r + 24 + 1, 0, sizeof(sp_digit) * (8 - 1)); + sp_3072_add_16(r + 16, r + 16, z2); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_3072_sqr_16(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z2[16]; + sp_digit z1[16]; + sp_digit a1[8]; + sp_digit u; + + u = sp_3072_add_8(a1, a, &a[8]); + sp_3072_sqr_8(z1, a1); + sp_3072_sqr_8(z2, &a[8]); + sp_3072_sqr_8(z0, a); + sp_3072_mask_8(r + 16, a1, 0 - u); + u += sp_3072_add_8(r + 16, r + 16, r + 16); + u += sp_3072_sub_in_place_16(z1, z2); + u += sp_3072_sub_in_place_16(z1, z0); + u += sp_3072_add_16(r + 8, r + 8, z1); + r[24] = u; + XMEMSET(r + 24 + 1, 0, sizeof(sp_digit) * (8 - 1)); + sp_3072_add_16(r + 16, r + 16, z2); +} + +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_3072_sub_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[a], #8]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b], #0]\n\t" + "ldr r8, [%[b], #4]\n\t" + "ldr r9, [%[b], #8]\n\t" + "ldr r10, [%[b], #12]\n\t" + "subs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "str r3, [%[r], #0]\n\t" + "str r4, [%[r], #4]\n\t" + "str r5, [%[r], #8]\n\t" + "str r6, [%[r], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[a], #24]\n\t" + "ldr r6, [%[a], #28]\n\t" + "ldr r7, [%[b], #16]\n\t" + "ldr r8, [%[b], #20]\n\t" + "ldr r9, [%[b], #24]\n\t" + "ldr r10, [%[b], #28]\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "str r3, [%[r], #16]\n\t" + "str r4, [%[r], #20]\n\t" + "str r5, [%[r], #24]\n\t" + "str r6, [%[r], #28]\n\t" + "ldr r3, [%[a], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[a], #40]\n\t" + "ldr r6, [%[a], #44]\n\t" + "ldr r7, [%[b], #32]\n\t" + "ldr r8, [%[b], #36]\n\t" + "ldr r9, [%[b], #40]\n\t" + "ldr r10, [%[b], #44]\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "str r3, [%[r], #32]\n\t" + "str r4, [%[r], #36]\n\t" + "str r5, [%[r], #40]\n\t" + "str r6, [%[r], #44]\n\t" + "ldr r3, [%[a], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[a], #56]\n\t" + "ldr r6, [%[a], #60]\n\t" + "ldr r7, [%[b], #48]\n\t" + "ldr r8, [%[b], #52]\n\t" + "ldr r9, [%[b], #56]\n\t" + "ldr r10, [%[b], #60]\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "str r3, [%[r], #48]\n\t" + "str r4, [%[r], #52]\n\t" + "str r5, [%[r], #56]\n\t" + "str r6, [%[r], #60]\n\t" + "ldr r3, [%[a], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[a], #72]\n\t" + "ldr r6, [%[a], #76]\n\t" + "ldr r7, [%[b], #64]\n\t" + "ldr r8, [%[b], #68]\n\t" + "ldr r9, [%[b], #72]\n\t" + "ldr r10, [%[b], #76]\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "str r3, [%[r], #64]\n\t" + "str r4, [%[r], #68]\n\t" + "str r5, [%[r], #72]\n\t" + "str r6, [%[r], #76]\n\t" + "ldr r3, [%[a], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[a], #88]\n\t" + "ldr r6, [%[a], #92]\n\t" + "ldr r7, [%[b], #80]\n\t" + "ldr r8, [%[b], #84]\n\t" + "ldr r9, [%[b], #88]\n\t" + "ldr r10, [%[b], #92]\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "str r3, [%[r], #80]\n\t" + "str r4, [%[r], #84]\n\t" + "str r5, [%[r], #88]\n\t" + "str r6, [%[r], #92]\n\t" + "ldr r3, [%[a], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[a], #104]\n\t" + "ldr r6, [%[a], #108]\n\t" + "ldr r7, [%[b], #96]\n\t" + "ldr r8, [%[b], #100]\n\t" + "ldr r9, [%[b], #104]\n\t" + "ldr r10, [%[b], #108]\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "str r3, [%[r], #96]\n\t" + "str r4, [%[r], #100]\n\t" + "str r5, [%[r], #104]\n\t" + "str r6, [%[r], #108]\n\t" + "ldr r3, [%[a], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[a], #120]\n\t" + "ldr r6, [%[a], #124]\n\t" + "ldr r7, [%[b], #112]\n\t" + "ldr r8, [%[b], #116]\n\t" + "ldr r9, [%[b], #120]\n\t" + "ldr r10, [%[b], #124]\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "str r3, [%[r], #112]\n\t" + "str r4, [%[r], #116]\n\t" + "str r5, [%[r], #120]\n\t" + "str r6, [%[r], #124]\n\t" + "sbc %[c], %[c], #0\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10" + ); + + return c; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_3072_add_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r12, #0\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[a], #4]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #12]\n\t" + "ldr r8, [%[b], #0]\n\t" + "ldr r9, [%[b], #4]\n\t" + "ldr r10, [%[b], #8]\n\t" + "ldr r14, [%[b], #12]\n\t" + "adds r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #0]\n\t" + "str r5, [%[r], #4]\n\t" + "str r6, [%[r], #8]\n\t" + "str r7, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[a], #20]\n\t" + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[a], #28]\n\t" + "ldr r8, [%[b], #16]\n\t" + "ldr r9, [%[b], #20]\n\t" + "ldr r10, [%[b], #24]\n\t" + "ldr r14, [%[b], #28]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #16]\n\t" + "str r5, [%[r], #20]\n\t" + "str r6, [%[r], #24]\n\t" + "str r7, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[a], #36]\n\t" + "ldr r6, [%[a], #40]\n\t" + "ldr r7, [%[a], #44]\n\t" + "ldr r8, [%[b], #32]\n\t" + "ldr r9, [%[b], #36]\n\t" + "ldr r10, [%[b], #40]\n\t" + "ldr r14, [%[b], #44]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #32]\n\t" + "str r5, [%[r], #36]\n\t" + "str r6, [%[r], #40]\n\t" + "str r7, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[a], #52]\n\t" + "ldr r6, [%[a], #56]\n\t" + "ldr r7, [%[a], #60]\n\t" + "ldr r8, [%[b], #48]\n\t" + "ldr r9, [%[b], #52]\n\t" + "ldr r10, [%[b], #56]\n\t" + "ldr r14, [%[b], #60]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #48]\n\t" + "str r5, [%[r], #52]\n\t" + "str r6, [%[r], #56]\n\t" + "str r7, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[a], #68]\n\t" + "ldr r6, [%[a], #72]\n\t" + "ldr r7, [%[a], #76]\n\t" + "ldr r8, [%[b], #64]\n\t" + "ldr r9, [%[b], #68]\n\t" + "ldr r10, [%[b], #72]\n\t" + "ldr r14, [%[b], #76]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #64]\n\t" + "str r5, [%[r], #68]\n\t" + "str r6, [%[r], #72]\n\t" + "str r7, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[a], #84]\n\t" + "ldr r6, [%[a], #88]\n\t" + "ldr r7, [%[a], #92]\n\t" + "ldr r8, [%[b], #80]\n\t" + "ldr r9, [%[b], #84]\n\t" + "ldr r10, [%[b], #88]\n\t" + "ldr r14, [%[b], #92]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #80]\n\t" + "str r5, [%[r], #84]\n\t" + "str r6, [%[r], #88]\n\t" + "str r7, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[a], #100]\n\t" + "ldr r6, [%[a], #104]\n\t" + "ldr r7, [%[a], #108]\n\t" + "ldr r8, [%[b], #96]\n\t" + "ldr r9, [%[b], #100]\n\t" + "ldr r10, [%[b], #104]\n\t" + "ldr r14, [%[b], #108]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #96]\n\t" + "str r5, [%[r], #100]\n\t" + "str r6, [%[r], #104]\n\t" + "str r7, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[a], #116]\n\t" + "ldr r6, [%[a], #120]\n\t" + "ldr r7, [%[a], #124]\n\t" + "ldr r8, [%[b], #112]\n\t" + "ldr r9, [%[b], #116]\n\t" + "ldr r10, [%[b], #120]\n\t" + "ldr r14, [%[b], #124]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #112]\n\t" + "str r5, [%[r], #116]\n\t" + "str r6, [%[r], #120]\n\t" + "str r7, [%[r], #124]\n\t" + "adc %[c], r12, r12\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + return c; +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_3072_mul_48(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit p0[32]; + sp_digit p1[32]; + sp_digit p2[32]; + sp_digit p3[32]; + sp_digit p4[32]; + sp_digit p5[32]; + sp_digit t0[32]; + sp_digit t1[32]; + sp_digit t2[32]; + sp_digit a0[16]; + sp_digit a1[16]; + sp_digit a2[16]; + sp_digit b0[16]; + sp_digit b1[16]; + sp_digit b2[16]; + sp_3072_add_16(a0, a, &a[16]); + sp_3072_add_16(b0, b, &b[16]); + sp_3072_add_16(a1, &a[16], &a[32]); + sp_3072_add_16(b1, &b[16], &b[32]); + sp_3072_add_16(a2, a0, &a[32]); + sp_3072_add_16(b2, b0, &b[32]); + sp_3072_mul_16(p0, a, b); + sp_3072_mul_16(p2, &a[16], &b[16]); + sp_3072_mul_16(p4, &a[32], &b[32]); + sp_3072_mul_16(p1, a0, b0); + sp_3072_mul_16(p3, a1, b1); + sp_3072_mul_16(p5, a2, b2); + XMEMSET(r, 0, sizeof(*r)*2*48); + sp_3072_sub_32(t0, p3, p2); + sp_3072_sub_32(t1, p1, p2); + sp_3072_sub_32(t2, p5, t0); + sp_3072_sub_32(t2, t2, t1); + sp_3072_sub_32(t0, t0, p4); + sp_3072_sub_32(t1, t1, p0); + sp_3072_add_32(r, r, p0); + sp_3072_add_32(&r[16], &r[16], t1); + sp_3072_add_32(&r[32], &r[32], t2); + sp_3072_add_32(&r[48], &r[48], t0); + sp_3072_add_32(&r[64], &r[64], p4); +} + +/* Square a into r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_3072_sqr_48(sp_digit* r, const sp_digit* a) +{ + sp_digit p0[32]; + sp_digit p1[32]; + sp_digit p2[32]; + sp_digit p3[32]; + sp_digit p4[32]; + sp_digit p5[32]; + sp_digit t0[32]; + sp_digit t1[32]; + sp_digit t2[32]; + sp_digit a0[16]; + sp_digit a1[16]; + sp_digit a2[16]; + sp_3072_add_16(a0, a, &a[16]); + sp_3072_add_16(a1, &a[16], &a[32]); + sp_3072_add_16(a2, a0, &a[32]); + sp_3072_sqr_16(p0, a); + sp_3072_sqr_16(p2, &a[16]); + sp_3072_sqr_16(p4, &a[32]); + sp_3072_sqr_16(p1, a0); + sp_3072_sqr_16(p3, a1); + sp_3072_sqr_16(p5, a2); + XMEMSET(r, 0, sizeof(*r)*2*48); + sp_3072_sub_32(t0, p3, p2); + sp_3072_sub_32(t1, p1, p2); + sp_3072_sub_32(t2, p5, t0); + sp_3072_sub_32(t2, t2, t1); + sp_3072_sub_32(t0, t0, p4); + sp_3072_sub_32(t1, t1, p0); + sp_3072_add_32(r, r, p0); + sp_3072_add_32(&r[16], &r[16], t1); + sp_3072_add_32(&r[32], &r[32], t2); + sp_3072_add_32(&r[48], &r[48], t0); + sp_3072_add_32(&r[64], &r[64], p4); +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_3072_add_48(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r12, #0\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[a], #4]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #12]\n\t" + "ldr r8, [%[b], #0]\n\t" + "ldr r9, [%[b], #4]\n\t" + "ldr r10, [%[b], #8]\n\t" + "ldr r14, [%[b], #12]\n\t" + "adds r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #0]\n\t" + "str r5, [%[r], #4]\n\t" + "str r6, [%[r], #8]\n\t" + "str r7, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[a], #20]\n\t" + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[a], #28]\n\t" + "ldr r8, [%[b], #16]\n\t" + "ldr r9, [%[b], #20]\n\t" + "ldr r10, [%[b], #24]\n\t" + "ldr r14, [%[b], #28]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #16]\n\t" + "str r5, [%[r], #20]\n\t" + "str r6, [%[r], #24]\n\t" + "str r7, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[a], #36]\n\t" + "ldr r6, [%[a], #40]\n\t" + "ldr r7, [%[a], #44]\n\t" + "ldr r8, [%[b], #32]\n\t" + "ldr r9, [%[b], #36]\n\t" + "ldr r10, [%[b], #40]\n\t" + "ldr r14, [%[b], #44]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #32]\n\t" + "str r5, [%[r], #36]\n\t" + "str r6, [%[r], #40]\n\t" + "str r7, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[a], #52]\n\t" + "ldr r6, [%[a], #56]\n\t" + "ldr r7, [%[a], #60]\n\t" + "ldr r8, [%[b], #48]\n\t" + "ldr r9, [%[b], #52]\n\t" + "ldr r10, [%[b], #56]\n\t" + "ldr r14, [%[b], #60]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #48]\n\t" + "str r5, [%[r], #52]\n\t" + "str r6, [%[r], #56]\n\t" + "str r7, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[a], #68]\n\t" + "ldr r6, [%[a], #72]\n\t" + "ldr r7, [%[a], #76]\n\t" + "ldr r8, [%[b], #64]\n\t" + "ldr r9, [%[b], #68]\n\t" + "ldr r10, [%[b], #72]\n\t" + "ldr r14, [%[b], #76]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #64]\n\t" + "str r5, [%[r], #68]\n\t" + "str r6, [%[r], #72]\n\t" + "str r7, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[a], #84]\n\t" + "ldr r6, [%[a], #88]\n\t" + "ldr r7, [%[a], #92]\n\t" + "ldr r8, [%[b], #80]\n\t" + "ldr r9, [%[b], #84]\n\t" + "ldr r10, [%[b], #88]\n\t" + "ldr r14, [%[b], #92]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #80]\n\t" + "str r5, [%[r], #84]\n\t" + "str r6, [%[r], #88]\n\t" + "str r7, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[a], #100]\n\t" + "ldr r6, [%[a], #104]\n\t" + "ldr r7, [%[a], #108]\n\t" + "ldr r8, [%[b], #96]\n\t" + "ldr r9, [%[b], #100]\n\t" + "ldr r10, [%[b], #104]\n\t" + "ldr r14, [%[b], #108]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #96]\n\t" + "str r5, [%[r], #100]\n\t" + "str r6, [%[r], #104]\n\t" + "str r7, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[a], #116]\n\t" + "ldr r6, [%[a], #120]\n\t" + "ldr r7, [%[a], #124]\n\t" + "ldr r8, [%[b], #112]\n\t" + "ldr r9, [%[b], #116]\n\t" + "ldr r10, [%[b], #120]\n\t" + "ldr r14, [%[b], #124]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #112]\n\t" + "str r5, [%[r], #116]\n\t" + "str r6, [%[r], #120]\n\t" + "str r7, [%[r], #124]\n\t" + "ldr r4, [%[a], #128]\n\t" + "ldr r5, [%[a], #132]\n\t" + "ldr r6, [%[a], #136]\n\t" + "ldr r7, [%[a], #140]\n\t" + "ldr r8, [%[b], #128]\n\t" + "ldr r9, [%[b], #132]\n\t" + "ldr r10, [%[b], #136]\n\t" + "ldr r14, [%[b], #140]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #128]\n\t" + "str r5, [%[r], #132]\n\t" + "str r6, [%[r], #136]\n\t" + "str r7, [%[r], #140]\n\t" + "ldr r4, [%[a], #144]\n\t" + "ldr r5, [%[a], #148]\n\t" + "ldr r6, [%[a], #152]\n\t" + "ldr r7, [%[a], #156]\n\t" + "ldr r8, [%[b], #144]\n\t" + "ldr r9, [%[b], #148]\n\t" + "ldr r10, [%[b], #152]\n\t" + "ldr r14, [%[b], #156]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #144]\n\t" + "str r5, [%[r], #148]\n\t" + "str r6, [%[r], #152]\n\t" + "str r7, [%[r], #156]\n\t" + "ldr r4, [%[a], #160]\n\t" + "ldr r5, [%[a], #164]\n\t" + "ldr r6, [%[a], #168]\n\t" + "ldr r7, [%[a], #172]\n\t" + "ldr r8, [%[b], #160]\n\t" + "ldr r9, [%[b], #164]\n\t" + "ldr r10, [%[b], #168]\n\t" + "ldr r14, [%[b], #172]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #160]\n\t" + "str r5, [%[r], #164]\n\t" + "str r6, [%[r], #168]\n\t" + "str r7, [%[r], #172]\n\t" + "ldr r4, [%[a], #176]\n\t" + "ldr r5, [%[a], #180]\n\t" + "ldr r6, [%[a], #184]\n\t" + "ldr r7, [%[a], #188]\n\t" + "ldr r8, [%[b], #176]\n\t" + "ldr r9, [%[b], #180]\n\t" + "ldr r10, [%[b], #184]\n\t" + "ldr r14, [%[b], #188]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #176]\n\t" + "str r5, [%[r], #180]\n\t" + "str r6, [%[r], #184]\n\t" + "str r7, [%[r], #188]\n\t" + "adc %[c], r12, r12\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + return c; +} + +/* Sub b from a into a. (a -= b) + * + * a A single precision integer and result. + * b A single precision integer. + */ +static sp_digit sp_3072_sub_in_place_96(sp_digit* a, const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r2, [%[a], #0]\n\t" + "ldr r3, [%[a], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[a], #12]\n\t" + "ldr r6, [%[b], #0]\n\t" + "ldr r7, [%[b], #4]\n\t" + "ldr r8, [%[b], #8]\n\t" + "ldr r9, [%[b], #12]\n\t" + "subs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #0]\n\t" + "str r3, [%[a], #4]\n\t" + "str r4, [%[a], #8]\n\t" + "str r5, [%[a], #12]\n\t" + "ldr r2, [%[a], #16]\n\t" + "ldr r3, [%[a], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[a], #28]\n\t" + "ldr r6, [%[b], #16]\n\t" + "ldr r7, [%[b], #20]\n\t" + "ldr r8, [%[b], #24]\n\t" + "ldr r9, [%[b], #28]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #16]\n\t" + "str r3, [%[a], #20]\n\t" + "str r4, [%[a], #24]\n\t" + "str r5, [%[a], #28]\n\t" + "ldr r2, [%[a], #32]\n\t" + "ldr r3, [%[a], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[a], #44]\n\t" + "ldr r6, [%[b], #32]\n\t" + "ldr r7, [%[b], #36]\n\t" + "ldr r8, [%[b], #40]\n\t" + "ldr r9, [%[b], #44]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #32]\n\t" + "str r3, [%[a], #36]\n\t" + "str r4, [%[a], #40]\n\t" + "str r5, [%[a], #44]\n\t" + "ldr r2, [%[a], #48]\n\t" + "ldr r3, [%[a], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[a], #60]\n\t" + "ldr r6, [%[b], #48]\n\t" + "ldr r7, [%[b], #52]\n\t" + "ldr r8, [%[b], #56]\n\t" + "ldr r9, [%[b], #60]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #48]\n\t" + "str r3, [%[a], #52]\n\t" + "str r4, [%[a], #56]\n\t" + "str r5, [%[a], #60]\n\t" + "ldr r2, [%[a], #64]\n\t" + "ldr r3, [%[a], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[a], #76]\n\t" + "ldr r6, [%[b], #64]\n\t" + "ldr r7, [%[b], #68]\n\t" + "ldr r8, [%[b], #72]\n\t" + "ldr r9, [%[b], #76]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #64]\n\t" + "str r3, [%[a], #68]\n\t" + "str r4, [%[a], #72]\n\t" + "str r5, [%[a], #76]\n\t" + "ldr r2, [%[a], #80]\n\t" + "ldr r3, [%[a], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[a], #92]\n\t" + "ldr r6, [%[b], #80]\n\t" + "ldr r7, [%[b], #84]\n\t" + "ldr r8, [%[b], #88]\n\t" + "ldr r9, [%[b], #92]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #80]\n\t" + "str r3, [%[a], #84]\n\t" + "str r4, [%[a], #88]\n\t" + "str r5, [%[a], #92]\n\t" + "ldr r2, [%[a], #96]\n\t" + "ldr r3, [%[a], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[a], #108]\n\t" + "ldr r6, [%[b], #96]\n\t" + "ldr r7, [%[b], #100]\n\t" + "ldr r8, [%[b], #104]\n\t" + "ldr r9, [%[b], #108]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #96]\n\t" + "str r3, [%[a], #100]\n\t" + "str r4, [%[a], #104]\n\t" + "str r5, [%[a], #108]\n\t" + "ldr r2, [%[a], #112]\n\t" + "ldr r3, [%[a], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[a], #124]\n\t" + "ldr r6, [%[b], #112]\n\t" + "ldr r7, [%[b], #116]\n\t" + "ldr r8, [%[b], #120]\n\t" + "ldr r9, [%[b], #124]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #112]\n\t" + "str r3, [%[a], #116]\n\t" + "str r4, [%[a], #120]\n\t" + "str r5, [%[a], #124]\n\t" + "ldr r2, [%[a], #128]\n\t" + "ldr r3, [%[a], #132]\n\t" + "ldr r4, [%[a], #136]\n\t" + "ldr r5, [%[a], #140]\n\t" + "ldr r6, [%[b], #128]\n\t" + "ldr r7, [%[b], #132]\n\t" + "ldr r8, [%[b], #136]\n\t" + "ldr r9, [%[b], #140]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #128]\n\t" + "str r3, [%[a], #132]\n\t" + "str r4, [%[a], #136]\n\t" + "str r5, [%[a], #140]\n\t" + "ldr r2, [%[a], #144]\n\t" + "ldr r3, [%[a], #148]\n\t" + "ldr r4, [%[a], #152]\n\t" + "ldr r5, [%[a], #156]\n\t" + "ldr r6, [%[b], #144]\n\t" + "ldr r7, [%[b], #148]\n\t" + "ldr r8, [%[b], #152]\n\t" + "ldr r9, [%[b], #156]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #144]\n\t" + "str r3, [%[a], #148]\n\t" + "str r4, [%[a], #152]\n\t" + "str r5, [%[a], #156]\n\t" + "ldr r2, [%[a], #160]\n\t" + "ldr r3, [%[a], #164]\n\t" + "ldr r4, [%[a], #168]\n\t" + "ldr r5, [%[a], #172]\n\t" + "ldr r6, [%[b], #160]\n\t" + "ldr r7, [%[b], #164]\n\t" + "ldr r8, [%[b], #168]\n\t" + "ldr r9, [%[b], #172]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #160]\n\t" + "str r3, [%[a], #164]\n\t" + "str r4, [%[a], #168]\n\t" + "str r5, [%[a], #172]\n\t" + "ldr r2, [%[a], #176]\n\t" + "ldr r3, [%[a], #180]\n\t" + "ldr r4, [%[a], #184]\n\t" + "ldr r5, [%[a], #188]\n\t" + "ldr r6, [%[b], #176]\n\t" + "ldr r7, [%[b], #180]\n\t" + "ldr r8, [%[b], #184]\n\t" + "ldr r9, [%[b], #188]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #176]\n\t" + "str r3, [%[a], #180]\n\t" + "str r4, [%[a], #184]\n\t" + "str r5, [%[a], #188]\n\t" + "ldr r2, [%[a], #192]\n\t" + "ldr r3, [%[a], #196]\n\t" + "ldr r4, [%[a], #200]\n\t" + "ldr r5, [%[a], #204]\n\t" + "ldr r6, [%[b], #192]\n\t" + "ldr r7, [%[b], #196]\n\t" + "ldr r8, [%[b], #200]\n\t" + "ldr r9, [%[b], #204]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #192]\n\t" + "str r3, [%[a], #196]\n\t" + "str r4, [%[a], #200]\n\t" + "str r5, [%[a], #204]\n\t" + "ldr r2, [%[a], #208]\n\t" + "ldr r3, [%[a], #212]\n\t" + "ldr r4, [%[a], #216]\n\t" + "ldr r5, [%[a], #220]\n\t" + "ldr r6, [%[b], #208]\n\t" + "ldr r7, [%[b], #212]\n\t" + "ldr r8, [%[b], #216]\n\t" + "ldr r9, [%[b], #220]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #208]\n\t" + "str r3, [%[a], #212]\n\t" + "str r4, [%[a], #216]\n\t" + "str r5, [%[a], #220]\n\t" + "ldr r2, [%[a], #224]\n\t" + "ldr r3, [%[a], #228]\n\t" + "ldr r4, [%[a], #232]\n\t" + "ldr r5, [%[a], #236]\n\t" + "ldr r6, [%[b], #224]\n\t" + "ldr r7, [%[b], #228]\n\t" + "ldr r8, [%[b], #232]\n\t" + "ldr r9, [%[b], #236]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #224]\n\t" + "str r3, [%[a], #228]\n\t" + "str r4, [%[a], #232]\n\t" + "str r5, [%[a], #236]\n\t" + "ldr r2, [%[a], #240]\n\t" + "ldr r3, [%[a], #244]\n\t" + "ldr r4, [%[a], #248]\n\t" + "ldr r5, [%[a], #252]\n\t" + "ldr r6, [%[b], #240]\n\t" + "ldr r7, [%[b], #244]\n\t" + "ldr r8, [%[b], #248]\n\t" + "ldr r9, [%[b], #252]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #240]\n\t" + "str r3, [%[a], #244]\n\t" + "str r4, [%[a], #248]\n\t" + "str r5, [%[a], #252]\n\t" + "ldr r2, [%[a], #256]\n\t" + "ldr r3, [%[a], #260]\n\t" + "ldr r4, [%[a], #264]\n\t" + "ldr r5, [%[a], #268]\n\t" + "ldr r6, [%[b], #256]\n\t" + "ldr r7, [%[b], #260]\n\t" + "ldr r8, [%[b], #264]\n\t" + "ldr r9, [%[b], #268]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #256]\n\t" + "str r3, [%[a], #260]\n\t" + "str r4, [%[a], #264]\n\t" + "str r5, [%[a], #268]\n\t" + "ldr r2, [%[a], #272]\n\t" + "ldr r3, [%[a], #276]\n\t" + "ldr r4, [%[a], #280]\n\t" + "ldr r5, [%[a], #284]\n\t" + "ldr r6, [%[b], #272]\n\t" + "ldr r7, [%[b], #276]\n\t" + "ldr r8, [%[b], #280]\n\t" + "ldr r9, [%[b], #284]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #272]\n\t" + "str r3, [%[a], #276]\n\t" + "str r4, [%[a], #280]\n\t" + "str r5, [%[a], #284]\n\t" + "ldr r2, [%[a], #288]\n\t" + "ldr r3, [%[a], #292]\n\t" + "ldr r4, [%[a], #296]\n\t" + "ldr r5, [%[a], #300]\n\t" + "ldr r6, [%[b], #288]\n\t" + "ldr r7, [%[b], #292]\n\t" + "ldr r8, [%[b], #296]\n\t" + "ldr r9, [%[b], #300]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #288]\n\t" + "str r3, [%[a], #292]\n\t" + "str r4, [%[a], #296]\n\t" + "str r5, [%[a], #300]\n\t" + "ldr r2, [%[a], #304]\n\t" + "ldr r3, [%[a], #308]\n\t" + "ldr r4, [%[a], #312]\n\t" + "ldr r5, [%[a], #316]\n\t" + "ldr r6, [%[b], #304]\n\t" + "ldr r7, [%[b], #308]\n\t" + "ldr r8, [%[b], #312]\n\t" + "ldr r9, [%[b], #316]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #304]\n\t" + "str r3, [%[a], #308]\n\t" + "str r4, [%[a], #312]\n\t" + "str r5, [%[a], #316]\n\t" + "ldr r2, [%[a], #320]\n\t" + "ldr r3, [%[a], #324]\n\t" + "ldr r4, [%[a], #328]\n\t" + "ldr r5, [%[a], #332]\n\t" + "ldr r6, [%[b], #320]\n\t" + "ldr r7, [%[b], #324]\n\t" + "ldr r8, [%[b], #328]\n\t" + "ldr r9, [%[b], #332]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #320]\n\t" + "str r3, [%[a], #324]\n\t" + "str r4, [%[a], #328]\n\t" + "str r5, [%[a], #332]\n\t" + "ldr r2, [%[a], #336]\n\t" + "ldr r3, [%[a], #340]\n\t" + "ldr r4, [%[a], #344]\n\t" + "ldr r5, [%[a], #348]\n\t" + "ldr r6, [%[b], #336]\n\t" + "ldr r7, [%[b], #340]\n\t" + "ldr r8, [%[b], #344]\n\t" + "ldr r9, [%[b], #348]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #336]\n\t" + "str r3, [%[a], #340]\n\t" + "str r4, [%[a], #344]\n\t" + "str r5, [%[a], #348]\n\t" + "ldr r2, [%[a], #352]\n\t" + "ldr r3, [%[a], #356]\n\t" + "ldr r4, [%[a], #360]\n\t" + "ldr r5, [%[a], #364]\n\t" + "ldr r6, [%[b], #352]\n\t" + "ldr r7, [%[b], #356]\n\t" + "ldr r8, [%[b], #360]\n\t" + "ldr r9, [%[b], #364]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #352]\n\t" + "str r3, [%[a], #356]\n\t" + "str r4, [%[a], #360]\n\t" + "str r5, [%[a], #364]\n\t" + "ldr r2, [%[a], #368]\n\t" + "ldr r3, [%[a], #372]\n\t" + "ldr r4, [%[a], #376]\n\t" + "ldr r5, [%[a], #380]\n\t" + "ldr r6, [%[b], #368]\n\t" + "ldr r7, [%[b], #372]\n\t" + "ldr r8, [%[b], #376]\n\t" + "ldr r9, [%[b], #380]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #368]\n\t" + "str r3, [%[a], #372]\n\t" + "str r4, [%[a], #376]\n\t" + "str r5, [%[a], #380]\n\t" + "sbc %[c], r9, r9\n\t" + : [c] "+r" (c) + : [a] "r" (a), [b] "r" (b) + : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9" + ); + + return c; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_3072_add_96(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r12, #0\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[a], #4]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #12]\n\t" + "ldr r8, [%[b], #0]\n\t" + "ldr r9, [%[b], #4]\n\t" + "ldr r10, [%[b], #8]\n\t" + "ldr r14, [%[b], #12]\n\t" + "adds r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #0]\n\t" + "str r5, [%[r], #4]\n\t" + "str r6, [%[r], #8]\n\t" + "str r7, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[a], #20]\n\t" + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[a], #28]\n\t" + "ldr r8, [%[b], #16]\n\t" + "ldr r9, [%[b], #20]\n\t" + "ldr r10, [%[b], #24]\n\t" + "ldr r14, [%[b], #28]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #16]\n\t" + "str r5, [%[r], #20]\n\t" + "str r6, [%[r], #24]\n\t" + "str r7, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[a], #36]\n\t" + "ldr r6, [%[a], #40]\n\t" + "ldr r7, [%[a], #44]\n\t" + "ldr r8, [%[b], #32]\n\t" + "ldr r9, [%[b], #36]\n\t" + "ldr r10, [%[b], #40]\n\t" + "ldr r14, [%[b], #44]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #32]\n\t" + "str r5, [%[r], #36]\n\t" + "str r6, [%[r], #40]\n\t" + "str r7, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[a], #52]\n\t" + "ldr r6, [%[a], #56]\n\t" + "ldr r7, [%[a], #60]\n\t" + "ldr r8, [%[b], #48]\n\t" + "ldr r9, [%[b], #52]\n\t" + "ldr r10, [%[b], #56]\n\t" + "ldr r14, [%[b], #60]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #48]\n\t" + "str r5, [%[r], #52]\n\t" + "str r6, [%[r], #56]\n\t" + "str r7, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[a], #68]\n\t" + "ldr r6, [%[a], #72]\n\t" + "ldr r7, [%[a], #76]\n\t" + "ldr r8, [%[b], #64]\n\t" + "ldr r9, [%[b], #68]\n\t" + "ldr r10, [%[b], #72]\n\t" + "ldr r14, [%[b], #76]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #64]\n\t" + "str r5, [%[r], #68]\n\t" + "str r6, [%[r], #72]\n\t" + "str r7, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[a], #84]\n\t" + "ldr r6, [%[a], #88]\n\t" + "ldr r7, [%[a], #92]\n\t" + "ldr r8, [%[b], #80]\n\t" + "ldr r9, [%[b], #84]\n\t" + "ldr r10, [%[b], #88]\n\t" + "ldr r14, [%[b], #92]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #80]\n\t" + "str r5, [%[r], #84]\n\t" + "str r6, [%[r], #88]\n\t" + "str r7, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[a], #100]\n\t" + "ldr r6, [%[a], #104]\n\t" + "ldr r7, [%[a], #108]\n\t" + "ldr r8, [%[b], #96]\n\t" + "ldr r9, [%[b], #100]\n\t" + "ldr r10, [%[b], #104]\n\t" + "ldr r14, [%[b], #108]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #96]\n\t" + "str r5, [%[r], #100]\n\t" + "str r6, [%[r], #104]\n\t" + "str r7, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[a], #116]\n\t" + "ldr r6, [%[a], #120]\n\t" + "ldr r7, [%[a], #124]\n\t" + "ldr r8, [%[b], #112]\n\t" + "ldr r9, [%[b], #116]\n\t" + "ldr r10, [%[b], #120]\n\t" + "ldr r14, [%[b], #124]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #112]\n\t" + "str r5, [%[r], #116]\n\t" + "str r6, [%[r], #120]\n\t" + "str r7, [%[r], #124]\n\t" + "ldr r4, [%[a], #128]\n\t" + "ldr r5, [%[a], #132]\n\t" + "ldr r6, [%[a], #136]\n\t" + "ldr r7, [%[a], #140]\n\t" + "ldr r8, [%[b], #128]\n\t" + "ldr r9, [%[b], #132]\n\t" + "ldr r10, [%[b], #136]\n\t" + "ldr r14, [%[b], #140]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #128]\n\t" + "str r5, [%[r], #132]\n\t" + "str r6, [%[r], #136]\n\t" + "str r7, [%[r], #140]\n\t" + "ldr r4, [%[a], #144]\n\t" + "ldr r5, [%[a], #148]\n\t" + "ldr r6, [%[a], #152]\n\t" + "ldr r7, [%[a], #156]\n\t" + "ldr r8, [%[b], #144]\n\t" + "ldr r9, [%[b], #148]\n\t" + "ldr r10, [%[b], #152]\n\t" + "ldr r14, [%[b], #156]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #144]\n\t" + "str r5, [%[r], #148]\n\t" + "str r6, [%[r], #152]\n\t" + "str r7, [%[r], #156]\n\t" + "ldr r4, [%[a], #160]\n\t" + "ldr r5, [%[a], #164]\n\t" + "ldr r6, [%[a], #168]\n\t" + "ldr r7, [%[a], #172]\n\t" + "ldr r8, [%[b], #160]\n\t" + "ldr r9, [%[b], #164]\n\t" + "ldr r10, [%[b], #168]\n\t" + "ldr r14, [%[b], #172]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #160]\n\t" + "str r5, [%[r], #164]\n\t" + "str r6, [%[r], #168]\n\t" + "str r7, [%[r], #172]\n\t" + "ldr r4, [%[a], #176]\n\t" + "ldr r5, [%[a], #180]\n\t" + "ldr r6, [%[a], #184]\n\t" + "ldr r7, [%[a], #188]\n\t" + "ldr r8, [%[b], #176]\n\t" + "ldr r9, [%[b], #180]\n\t" + "ldr r10, [%[b], #184]\n\t" + "ldr r14, [%[b], #188]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #176]\n\t" + "str r5, [%[r], #180]\n\t" + "str r6, [%[r], #184]\n\t" + "str r7, [%[r], #188]\n\t" + "ldr r4, [%[a], #192]\n\t" + "ldr r5, [%[a], #196]\n\t" + "ldr r6, [%[a], #200]\n\t" + "ldr r7, [%[a], #204]\n\t" + "ldr r8, [%[b], #192]\n\t" + "ldr r9, [%[b], #196]\n\t" + "ldr r10, [%[b], #200]\n\t" + "ldr r14, [%[b], #204]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #192]\n\t" + "str r5, [%[r], #196]\n\t" + "str r6, [%[r], #200]\n\t" + "str r7, [%[r], #204]\n\t" + "ldr r4, [%[a], #208]\n\t" + "ldr r5, [%[a], #212]\n\t" + "ldr r6, [%[a], #216]\n\t" + "ldr r7, [%[a], #220]\n\t" + "ldr r8, [%[b], #208]\n\t" + "ldr r9, [%[b], #212]\n\t" + "ldr r10, [%[b], #216]\n\t" + "ldr r14, [%[b], #220]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #208]\n\t" + "str r5, [%[r], #212]\n\t" + "str r6, [%[r], #216]\n\t" + "str r7, [%[r], #220]\n\t" + "ldr r4, [%[a], #224]\n\t" + "ldr r5, [%[a], #228]\n\t" + "ldr r6, [%[a], #232]\n\t" + "ldr r7, [%[a], #236]\n\t" + "ldr r8, [%[b], #224]\n\t" + "ldr r9, [%[b], #228]\n\t" + "ldr r10, [%[b], #232]\n\t" + "ldr r14, [%[b], #236]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #224]\n\t" + "str r5, [%[r], #228]\n\t" + "str r6, [%[r], #232]\n\t" + "str r7, [%[r], #236]\n\t" + "ldr r4, [%[a], #240]\n\t" + "ldr r5, [%[a], #244]\n\t" + "ldr r6, [%[a], #248]\n\t" + "ldr r7, [%[a], #252]\n\t" + "ldr r8, [%[b], #240]\n\t" + "ldr r9, [%[b], #244]\n\t" + "ldr r10, [%[b], #248]\n\t" + "ldr r14, [%[b], #252]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #240]\n\t" + "str r5, [%[r], #244]\n\t" + "str r6, [%[r], #248]\n\t" + "str r7, [%[r], #252]\n\t" + "ldr r4, [%[a], #256]\n\t" + "ldr r5, [%[a], #260]\n\t" + "ldr r6, [%[a], #264]\n\t" + "ldr r7, [%[a], #268]\n\t" + "ldr r8, [%[b], #256]\n\t" + "ldr r9, [%[b], #260]\n\t" + "ldr r10, [%[b], #264]\n\t" + "ldr r14, [%[b], #268]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #256]\n\t" + "str r5, [%[r], #260]\n\t" + "str r6, [%[r], #264]\n\t" + "str r7, [%[r], #268]\n\t" + "ldr r4, [%[a], #272]\n\t" + "ldr r5, [%[a], #276]\n\t" + "ldr r6, [%[a], #280]\n\t" + "ldr r7, [%[a], #284]\n\t" + "ldr r8, [%[b], #272]\n\t" + "ldr r9, [%[b], #276]\n\t" + "ldr r10, [%[b], #280]\n\t" + "ldr r14, [%[b], #284]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #272]\n\t" + "str r5, [%[r], #276]\n\t" + "str r6, [%[r], #280]\n\t" + "str r7, [%[r], #284]\n\t" + "ldr r4, [%[a], #288]\n\t" + "ldr r5, [%[a], #292]\n\t" + "ldr r6, [%[a], #296]\n\t" + "ldr r7, [%[a], #300]\n\t" + "ldr r8, [%[b], #288]\n\t" + "ldr r9, [%[b], #292]\n\t" + "ldr r10, [%[b], #296]\n\t" + "ldr r14, [%[b], #300]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #288]\n\t" + "str r5, [%[r], #292]\n\t" + "str r6, [%[r], #296]\n\t" + "str r7, [%[r], #300]\n\t" + "ldr r4, [%[a], #304]\n\t" + "ldr r5, [%[a], #308]\n\t" + "ldr r6, [%[a], #312]\n\t" + "ldr r7, [%[a], #316]\n\t" + "ldr r8, [%[b], #304]\n\t" + "ldr r9, [%[b], #308]\n\t" + "ldr r10, [%[b], #312]\n\t" + "ldr r14, [%[b], #316]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #304]\n\t" + "str r5, [%[r], #308]\n\t" + "str r6, [%[r], #312]\n\t" + "str r7, [%[r], #316]\n\t" + "ldr r4, [%[a], #320]\n\t" + "ldr r5, [%[a], #324]\n\t" + "ldr r6, [%[a], #328]\n\t" + "ldr r7, [%[a], #332]\n\t" + "ldr r8, [%[b], #320]\n\t" + "ldr r9, [%[b], #324]\n\t" + "ldr r10, [%[b], #328]\n\t" + "ldr r14, [%[b], #332]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #320]\n\t" + "str r5, [%[r], #324]\n\t" + "str r6, [%[r], #328]\n\t" + "str r7, [%[r], #332]\n\t" + "ldr r4, [%[a], #336]\n\t" + "ldr r5, [%[a], #340]\n\t" + "ldr r6, [%[a], #344]\n\t" + "ldr r7, [%[a], #348]\n\t" + "ldr r8, [%[b], #336]\n\t" + "ldr r9, [%[b], #340]\n\t" + "ldr r10, [%[b], #344]\n\t" + "ldr r14, [%[b], #348]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #336]\n\t" + "str r5, [%[r], #340]\n\t" + "str r6, [%[r], #344]\n\t" + "str r7, [%[r], #348]\n\t" + "ldr r4, [%[a], #352]\n\t" + "ldr r5, [%[a], #356]\n\t" + "ldr r6, [%[a], #360]\n\t" + "ldr r7, [%[a], #364]\n\t" + "ldr r8, [%[b], #352]\n\t" + "ldr r9, [%[b], #356]\n\t" + "ldr r10, [%[b], #360]\n\t" + "ldr r14, [%[b], #364]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #352]\n\t" + "str r5, [%[r], #356]\n\t" + "str r6, [%[r], #360]\n\t" + "str r7, [%[r], #364]\n\t" + "ldr r4, [%[a], #368]\n\t" + "ldr r5, [%[a], #372]\n\t" + "ldr r6, [%[a], #376]\n\t" + "ldr r7, [%[a], #380]\n\t" + "ldr r8, [%[b], #368]\n\t" + "ldr r9, [%[b], #372]\n\t" + "ldr r10, [%[b], #376]\n\t" + "ldr r14, [%[b], #380]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #368]\n\t" + "str r5, [%[r], #372]\n\t" + "str r6, [%[r], #376]\n\t" + "str r7, [%[r], #380]\n\t" + "adc %[c], r12, r12\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + return c; +} + +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_3072_mask_48(sp_digit* r, sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<48; i++) + r[i] = a[i] & m; +#else + int i; + + for (i = 0; i < 48; i += 8) { + r[i+0] = a[i+0] & m; + r[i+1] = a[i+1] & m; + r[i+2] = a[i+2] & m; + r[i+3] = a[i+3] & m; + r[i+4] = a[i+4] & m; + r[i+5] = a[i+5] & m; + r[i+6] = a[i+6] & m; + r[i+7] = a[i+7] & m; + } +#endif +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_3072_mul_96(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[96]; + sp_digit a1[48]; + sp_digit b1[48]; + sp_digit z2[96]; + sp_digit u, ca, cb; + + ca = sp_3072_add_48(a1, a, &a[48]); + cb = sp_3072_add_48(b1, b, &b[48]); + u = ca & cb; + sp_3072_mul_48(z1, a1, b1); + sp_3072_mul_48(z2, &a[48], &b[48]); + sp_3072_mul_48(z0, a, b); + sp_3072_mask_48(r + 96, a1, 0 - cb); + sp_3072_mask_48(b1, b1, 0 - ca); + u += sp_3072_add_48(r + 96, r + 96, b1); + u += sp_3072_sub_in_place_96(z1, z2); + u += sp_3072_sub_in_place_96(z1, z0); + u += sp_3072_add_96(r + 48, r + 48, z1); + r[144] = u; + XMEMSET(r + 144 + 1, 0, sizeof(sp_digit) * (48 - 1)); + sp_3072_add_96(r + 96, r + 96, z2); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_3072_sqr_96(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z2[96]; + sp_digit z1[96]; + sp_digit a1[48]; + sp_digit u; + + u = sp_3072_add_48(a1, a, &a[48]); + sp_3072_sqr_48(z1, a1); + sp_3072_sqr_48(z2, &a[48]); + sp_3072_sqr_48(z0, a); + sp_3072_mask_48(r + 96, a1, 0 - u); + u += sp_3072_add_48(r + 96, r + 96, r + 96); + u += sp_3072_sub_in_place_96(z1, z2); + u += sp_3072_sub_in_place_96(z1, z0); + u += sp_3072_add_96(r + 48, r + 48, z1); + r[144] = u; + XMEMSET(r + 144 + 1, 0, sizeof(sp_digit) * (48 - 1)); + sp_3072_add_96(r + 96, r + 96, z2); +} + +#endif /* !WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_3072_add_96(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "add r12, %[a], #384\n\t" + "\n1:\n\t" + "adds %[c], %[c], #-1\n\t" + "ldr r4, [%[a]], #4\n\t" + "ldr r5, [%[a]], #4\n\t" + "ldr r6, [%[a]], #4\n\t" + "ldr r7, [%[a]], #4\n\t" + "ldr r8, [%[b]], #4\n\t" + "ldr r9, [%[b]], #4\n\t" + "ldr r10, [%[b]], #4\n\t" + "ldr r14, [%[b]], #4\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r]], #4\n\t" + "str r5, [%[r]], #4\n\t" + "str r6, [%[r]], #4\n\t" + "str r7, [%[r]], #4\n\t" + "mov r4, #0\n\t" + "adc %[c], r4, #0\n\t" + "cmp %[a], r12\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into a. (a -= b) + * + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_3072_sub_in_place_96(sp_digit* a, const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r14, #0\n\t" + "add r12, %[a], #384\n\t" + "\n1:\n\t" + "subs %[c], r14, %[c]\n\t" + "ldr r3, [%[a]]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[a], #8]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b]], #4\n\t" + "ldr r8, [%[b]], #4\n\t" + "ldr r9, [%[b]], #4\n\t" + "ldr r10, [%[b]], #4\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "str r3, [%[a]], #4\n\t" + "str r4, [%[a]], #4\n\t" + "str r5, [%[a]], #4\n\t" + "str r6, [%[a]], #4\n\t" + "sbc %[c], r14, r14\n\t" + "cmp %[a], r12\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r12", "r14" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_3072_mul_96(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + __asm__ __volatile__ ( + "sub sp, sp, #768\n\t" + "mov r5, #0\n\t" + "mov r6, #0\n\t" + "mov r7, #0\n\t" + "mov r8, #0\n\t" + "\n1:\n\t" + "subs r3, r5, #380\n\t" + "movcc r3, #0\n\t" + "sub r4, r5, r3\n\t" + "\n2:\n\t" + "ldr r14, [%[a], r3]\n\t" + "ldr r12, [%[b], r4]\n\t" + "umull r9, r10, r14, r12\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, #0\n\t" + "add r3, r3, #4\n\t" + "sub r4, r4, #4\n\t" + "cmp r3, #384\n\t" + "beq 3f\n\t" + "cmp r3, r5\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "str r6, [sp, r5]\n\t" + "mov r6, r7\n\t" + "mov r7, r8\n\t" + "mov r8, #0\n\t" + "add r5, r5, #4\n\t" + "cmp r5, #760\n\t" + "ble 1b\n\t" + "str r6, [sp, r5]\n\t" + "\n4:\n\t" + "ldr r6, [sp, #0]\n\t" + "ldr r7, [sp, #4]\n\t" + "ldr r8, [sp, #8]\n\t" + "ldr r3, [sp, #12]\n\t" + "str r6, [%[r], #0]\n\t" + "str r7, [%[r], #4]\n\t" + "str r8, [%[r], #8]\n\t" + "str r3, [%[r], #12]\n\t" + "add sp, sp, #16\n\t" + "add %[r], %[r], #16\n\t" + "subs r5, r5, #16\n\t" + "bgt 4b\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_3072_sqr_96(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "sub sp, sp, #768\n\t" + "mov r12, #0\n\t" + "mov r6, #0\n\t" + "mov r7, #0\n\t" + "mov r8, #0\n\t" + "mov r5, #0\n\t" + "\n1:\n\t" + "subs r3, r5, #380\n\t" + "movcc r3, r12\n\t" + "sub r4, r5, r3\n\t" + "\n2:\n\t" + "cmp r4, r3\n\t" + "beq 4f\n\t" + "ldr r14, [%[a], r3]\n\t" + "ldr r9, [%[a], r4]\n\t" + "umull r9, r10, r14, r9\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, r12\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, r12\n\t" + "bal 5f\n\t" + "\n4:\n\t" + "ldr r14, [%[a], r3]\n\t" + "umull r9, r10, r14, r14\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, r12\n\t" + "\n5:\n\t" + "add r3, r3, #4\n\t" + "sub r4, r4, #4\n\t" + "cmp r3, #384\n\t" + "beq 3f\n\t" + "cmp r3, r4\n\t" + "bgt 3f\n\t" + "cmp r3, r5\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "str r6, [sp, r5]\n\t" + "mov r6, r7\n\t" + "mov r7, r8\n\t" + "mov r8, #0\n\t" + "add r5, r5, #4\n\t" + "cmp r5, #760\n\t" + "ble 1b\n\t" + "str r6, [sp, r5]\n\t" + "\n4:\n\t" + "ldr r6, [sp, #0]\n\t" + "ldr r7, [sp, #4]\n\t" + "ldr r8, [sp, #8]\n\t" + "ldr r3, [sp, #12]\n\t" + "str r6, [%[r], #0]\n\t" + "str r7, [%[r], #4]\n\t" + "str r8, [%[r], #8]\n\t" + "str r3, [%[r], #12]\n\t" + "add sp, sp, #16\n\t" + "add %[r], %[r], #16\n\t" + "subs r5, r5, #16\n\t" + "bgt 4b\n\t" + : [r] "+r" (r) + : [a] "r" (a) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r9", "r12" + ); +} + +#endif /* WOLFSSL_SP_SMALL */ +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +#ifdef WOLFSSL_SP_SMALL +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_3072_mask_48(sp_digit* r, sp_digit* a, sp_digit m) +{ + int i; + + for (i=0; i<48; i++) + r[i] = a[i] & m; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_3072_add_48(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "add r12, %[a], #192\n\t" + "\n1:\n\t" + "adds %[c], %[c], #-1\n\t" + "ldr r4, [%[a]], #4\n\t" + "ldr r5, [%[a]], #4\n\t" + "ldr r6, [%[a]], #4\n\t" + "ldr r7, [%[a]], #4\n\t" + "ldr r8, [%[b]], #4\n\t" + "ldr r9, [%[b]], #4\n\t" + "ldr r10, [%[b]], #4\n\t" + "ldr r14, [%[b]], #4\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r]], #4\n\t" + "str r5, [%[r]], #4\n\t" + "str r6, [%[r]], #4\n\t" + "str r7, [%[r]], #4\n\t" + "mov r4, #0\n\t" + "adc %[c], r4, #0\n\t" + "cmp %[a], r12\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_3072_mul_48(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + __asm__ __volatile__ ( + "sub sp, sp, #384\n\t" + "mov r5, #0\n\t" + "mov r6, #0\n\t" + "mov r7, #0\n\t" + "mov r8, #0\n\t" + "\n1:\n\t" + "subs r3, r5, #188\n\t" + "movcc r3, #0\n\t" + "sub r4, r5, r3\n\t" + "\n2:\n\t" + "ldr r14, [%[a], r3]\n\t" + "ldr r12, [%[b], r4]\n\t" + "umull r9, r10, r14, r12\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, #0\n\t" + "add r3, r3, #4\n\t" + "sub r4, r4, #4\n\t" + "cmp r3, #192\n\t" + "beq 3f\n\t" + "cmp r3, r5\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "str r6, [sp, r5]\n\t" + "mov r6, r7\n\t" + "mov r7, r8\n\t" + "mov r8, #0\n\t" + "add r5, r5, #4\n\t" + "cmp r5, #376\n\t" + "ble 1b\n\t" + "str r6, [sp, r5]\n\t" + "\n4:\n\t" + "ldr r6, [sp, #0]\n\t" + "ldr r7, [sp, #4]\n\t" + "ldr r8, [sp, #8]\n\t" + "ldr r3, [sp, #12]\n\t" + "str r6, [%[r], #0]\n\t" + "str r7, [%[r], #4]\n\t" + "str r8, [%[r], #8]\n\t" + "str r3, [%[r], #12]\n\t" + "add sp, sp, #16\n\t" + "add %[r], %[r], #16\n\t" + "subs r5, r5, #16\n\t" + "bgt 4b\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_3072_sqr_48(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "sub sp, sp, #384\n\t" + "mov r12, #0\n\t" + "mov r6, #0\n\t" + "mov r7, #0\n\t" + "mov r8, #0\n\t" + "mov r5, #0\n\t" + "\n1:\n\t" + "subs r3, r5, #188\n\t" + "movcc r3, r12\n\t" + "sub r4, r5, r3\n\t" + "\n2:\n\t" + "cmp r4, r3\n\t" + "beq 4f\n\t" + "ldr r14, [%[a], r3]\n\t" + "ldr r9, [%[a], r4]\n\t" + "umull r9, r10, r14, r9\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, r12\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, r12\n\t" + "bal 5f\n\t" + "\n4:\n\t" + "ldr r14, [%[a], r3]\n\t" + "umull r9, r10, r14, r14\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, r12\n\t" + "\n5:\n\t" + "add r3, r3, #4\n\t" + "sub r4, r4, #4\n\t" + "cmp r3, #192\n\t" + "beq 3f\n\t" + "cmp r3, r4\n\t" + "bgt 3f\n\t" + "cmp r3, r5\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "str r6, [sp, r5]\n\t" + "mov r6, r7\n\t" + "mov r7, r8\n\t" + "mov r8, #0\n\t" + "add r5, r5, #4\n\t" + "cmp r5, #376\n\t" + "ble 1b\n\t" + "str r6, [sp, r5]\n\t" + "\n4:\n\t" + "ldr r6, [sp, #0]\n\t" + "ldr r7, [sp, #4]\n\t" + "ldr r8, [sp, #8]\n\t" + "ldr r3, [sp, #12]\n\t" + "str r6, [%[r], #0]\n\t" + "str r7, [%[r], #4]\n\t" + "str r8, [%[r], #8]\n\t" + "str r3, [%[r], #12]\n\t" + "add sp, sp, #16\n\t" + "add %[r], %[r], #16\n\t" + "subs r5, r5, #16\n\t" + "bgt 4b\n\t" + : [r] "+r" (r) + : [a] "r" (a) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r9", "r12" + ); +} + +#endif /* WOLFSSL_SP_SMALL */ +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +/* Caclulate the bottom digit of -1/a mod 2^n. + * + * a A single precision number. + * rho Bottom word of inverse. + */ +static void sp_3072_mont_setup(sp_digit* a, sp_digit* rho) +{ + sp_digit x, b; + + b = a[0]; + x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ + x *= 2 - b * x; /* here x*a==1 mod 2**8 */ + x *= 2 - b * x; /* here x*a==1 mod 2**16 */ + x *= 2 - b * x; /* here x*a==1 mod 2**32 */ + + /* rho = -1/m mod b */ + *rho = -x; +} + +/* Mul a by digit b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision digit. + */ +static void sp_3072_mul_d_96(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov r10, #0\n\t" + "# A[0] * B\n\t" + "ldr r8, [%[a]]\n\t" + "umull r5, r3, %[b], r8\n\t" + "mov r4, #0\n\t" + "str r5, [%[r]]\n\t" + "mov r5, #0\n\t" + "mov r9, #4\n\t" + "1:\n\t" + "ldr r8, [%[a], r9]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], r9]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "add r9, r9, #4\n\t" + "cmp r9, #384\n\t" + "blt 1b\n\t" + "str r3, [%[r], #384]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10" + ); +#else + __asm__ __volatile__ ( + "mov r10, #0\n\t" + "# A[0] * B\n\t" + "ldr r8, [%[a]]\n\t" + "umull r3, r4, %[b], r8\n\t" + "mov r5, #0\n\t" + "str r3, [%[r]]\n\t" + "# A[1] * B\n\t" + "ldr r8, [%[a], #4]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #4]\n\t" + "# A[2] * B\n\t" + "ldr r8, [%[a], #8]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #8]\n\t" + "# A[3] * B\n\t" + "ldr r8, [%[a], #12]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #12]\n\t" + "# A[4] * B\n\t" + "ldr r8, [%[a], #16]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #16]\n\t" + "# A[5] * B\n\t" + "ldr r8, [%[a], #20]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #20]\n\t" + "# A[6] * B\n\t" + "ldr r8, [%[a], #24]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #24]\n\t" + "# A[7] * B\n\t" + "ldr r8, [%[a], #28]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #28]\n\t" + "# A[8] * B\n\t" + "ldr r8, [%[a], #32]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #32]\n\t" + "# A[9] * B\n\t" + "ldr r8, [%[a], #36]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #36]\n\t" + "# A[10] * B\n\t" + "ldr r8, [%[a], #40]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #40]\n\t" + "# A[11] * B\n\t" + "ldr r8, [%[a], #44]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #44]\n\t" + "# A[12] * B\n\t" + "ldr r8, [%[a], #48]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #48]\n\t" + "# A[13] * B\n\t" + "ldr r8, [%[a], #52]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #52]\n\t" + "# A[14] * B\n\t" + "ldr r8, [%[a], #56]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #56]\n\t" + "# A[15] * B\n\t" + "ldr r8, [%[a], #60]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #60]\n\t" + "# A[16] * B\n\t" + "ldr r8, [%[a], #64]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #64]\n\t" + "# A[17] * B\n\t" + "ldr r8, [%[a], #68]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #68]\n\t" + "# A[18] * B\n\t" + "ldr r8, [%[a], #72]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #72]\n\t" + "# A[19] * B\n\t" + "ldr r8, [%[a], #76]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #76]\n\t" + "# A[20] * B\n\t" + "ldr r8, [%[a], #80]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #80]\n\t" + "# A[21] * B\n\t" + "ldr r8, [%[a], #84]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #84]\n\t" + "# A[22] * B\n\t" + "ldr r8, [%[a], #88]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #88]\n\t" + "# A[23] * B\n\t" + "ldr r8, [%[a], #92]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #92]\n\t" + "# A[24] * B\n\t" + "ldr r8, [%[a], #96]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #96]\n\t" + "# A[25] * B\n\t" + "ldr r8, [%[a], #100]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #100]\n\t" + "# A[26] * B\n\t" + "ldr r8, [%[a], #104]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #104]\n\t" + "# A[27] * B\n\t" + "ldr r8, [%[a], #108]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #108]\n\t" + "# A[28] * B\n\t" + "ldr r8, [%[a], #112]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #112]\n\t" + "# A[29] * B\n\t" + "ldr r8, [%[a], #116]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #116]\n\t" + "# A[30] * B\n\t" + "ldr r8, [%[a], #120]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #120]\n\t" + "# A[31] * B\n\t" + "ldr r8, [%[a], #124]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #124]\n\t" + "# A[32] * B\n\t" + "ldr r8, [%[a], #128]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #128]\n\t" + "# A[33] * B\n\t" + "ldr r8, [%[a], #132]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #132]\n\t" + "# A[34] * B\n\t" + "ldr r8, [%[a], #136]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #136]\n\t" + "# A[35] * B\n\t" + "ldr r8, [%[a], #140]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #140]\n\t" + "# A[36] * B\n\t" + "ldr r8, [%[a], #144]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #144]\n\t" + "# A[37] * B\n\t" + "ldr r8, [%[a], #148]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #148]\n\t" + "# A[38] * B\n\t" + "ldr r8, [%[a], #152]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #152]\n\t" + "# A[39] * B\n\t" + "ldr r8, [%[a], #156]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #156]\n\t" + "# A[40] * B\n\t" + "ldr r8, [%[a], #160]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #160]\n\t" + "# A[41] * B\n\t" + "ldr r8, [%[a], #164]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #164]\n\t" + "# A[42] * B\n\t" + "ldr r8, [%[a], #168]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #168]\n\t" + "# A[43] * B\n\t" + "ldr r8, [%[a], #172]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #172]\n\t" + "# A[44] * B\n\t" + "ldr r8, [%[a], #176]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #176]\n\t" + "# A[45] * B\n\t" + "ldr r8, [%[a], #180]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #180]\n\t" + "# A[46] * B\n\t" + "ldr r8, [%[a], #184]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #184]\n\t" + "# A[47] * B\n\t" + "ldr r8, [%[a], #188]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #188]\n\t" + "# A[48] * B\n\t" + "ldr r8, [%[a], #192]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #192]\n\t" + "# A[49] * B\n\t" + "ldr r8, [%[a], #196]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #196]\n\t" + "# A[50] * B\n\t" + "ldr r8, [%[a], #200]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #200]\n\t" + "# A[51] * B\n\t" + "ldr r8, [%[a], #204]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #204]\n\t" + "# A[52] * B\n\t" + "ldr r8, [%[a], #208]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #208]\n\t" + "# A[53] * B\n\t" + "ldr r8, [%[a], #212]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #212]\n\t" + "# A[54] * B\n\t" + "ldr r8, [%[a], #216]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #216]\n\t" + "# A[55] * B\n\t" + "ldr r8, [%[a], #220]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #220]\n\t" + "# A[56] * B\n\t" + "ldr r8, [%[a], #224]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #224]\n\t" + "# A[57] * B\n\t" + "ldr r8, [%[a], #228]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #228]\n\t" + "# A[58] * B\n\t" + "ldr r8, [%[a], #232]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #232]\n\t" + "# A[59] * B\n\t" + "ldr r8, [%[a], #236]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #236]\n\t" + "# A[60] * B\n\t" + "ldr r8, [%[a], #240]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #240]\n\t" + "# A[61] * B\n\t" + "ldr r8, [%[a], #244]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #244]\n\t" + "# A[62] * B\n\t" + "ldr r8, [%[a], #248]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #248]\n\t" + "# A[63] * B\n\t" + "ldr r8, [%[a], #252]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #252]\n\t" + "# A[64] * B\n\t" + "ldr r8, [%[a], #256]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #256]\n\t" + "# A[65] * B\n\t" + "ldr r8, [%[a], #260]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #260]\n\t" + "# A[66] * B\n\t" + "ldr r8, [%[a], #264]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #264]\n\t" + "# A[67] * B\n\t" + "ldr r8, [%[a], #268]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #268]\n\t" + "# A[68] * B\n\t" + "ldr r8, [%[a], #272]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #272]\n\t" + "# A[69] * B\n\t" + "ldr r8, [%[a], #276]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #276]\n\t" + "# A[70] * B\n\t" + "ldr r8, [%[a], #280]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #280]\n\t" + "# A[71] * B\n\t" + "ldr r8, [%[a], #284]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #284]\n\t" + "# A[72] * B\n\t" + "ldr r8, [%[a], #288]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #288]\n\t" + "# A[73] * B\n\t" + "ldr r8, [%[a], #292]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #292]\n\t" + "# A[74] * B\n\t" + "ldr r8, [%[a], #296]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #296]\n\t" + "# A[75] * B\n\t" + "ldr r8, [%[a], #300]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #300]\n\t" + "# A[76] * B\n\t" + "ldr r8, [%[a], #304]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #304]\n\t" + "# A[77] * B\n\t" + "ldr r8, [%[a], #308]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #308]\n\t" + "# A[78] * B\n\t" + "ldr r8, [%[a], #312]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #312]\n\t" + "# A[79] * B\n\t" + "ldr r8, [%[a], #316]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #316]\n\t" + "# A[80] * B\n\t" + "ldr r8, [%[a], #320]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #320]\n\t" + "# A[81] * B\n\t" + "ldr r8, [%[a], #324]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #324]\n\t" + "# A[82] * B\n\t" + "ldr r8, [%[a], #328]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #328]\n\t" + "# A[83] * B\n\t" + "ldr r8, [%[a], #332]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #332]\n\t" + "# A[84] * B\n\t" + "ldr r8, [%[a], #336]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #336]\n\t" + "# A[85] * B\n\t" + "ldr r8, [%[a], #340]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #340]\n\t" + "# A[86] * B\n\t" + "ldr r8, [%[a], #344]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #344]\n\t" + "# A[87] * B\n\t" + "ldr r8, [%[a], #348]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #348]\n\t" + "# A[88] * B\n\t" + "ldr r8, [%[a], #352]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #352]\n\t" + "# A[89] * B\n\t" + "ldr r8, [%[a], #356]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #356]\n\t" + "# A[90] * B\n\t" + "ldr r8, [%[a], #360]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #360]\n\t" + "# A[91] * B\n\t" + "ldr r8, [%[a], #364]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #364]\n\t" + "# A[92] * B\n\t" + "ldr r8, [%[a], #368]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #368]\n\t" + "# A[93] * B\n\t" + "ldr r8, [%[a], #372]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #372]\n\t" + "# A[94] * B\n\t" + "ldr r8, [%[a], #376]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #376]\n\t" + "# A[95] * B\n\t" + "ldr r8, [%[a], #380]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adc r3, r3, r7\n\t" + "str r5, [%[r], #380]\n\t" + "str r3, [%[r], #384]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10" + ); +#endif +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into a. (a -= b) + * + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_3072_sub_in_place_48(sp_digit* a, const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r14, #0\n\t" + "add r12, %[a], #192\n\t" + "\n1:\n\t" + "subs %[c], r14, %[c]\n\t" + "ldr r3, [%[a]]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[a], #8]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b]], #4\n\t" + "ldr r8, [%[b]], #4\n\t" + "ldr r9, [%[b]], #4\n\t" + "ldr r10, [%[b]], #4\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "str r3, [%[a]], #4\n\t" + "str r4, [%[a]], #4\n\t" + "str r5, [%[a]], #4\n\t" + "str r6, [%[a]], #4\n\t" + "sbc %[c], r14, r14\n\t" + "cmp %[a], r12\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r12", "r14" + ); + + return c; +} + +#else +/* Sub b from a into a. (a -= b) + * + * a A single precision integer and result. + * b A single precision integer. + */ +static sp_digit sp_3072_sub_in_place_48(sp_digit* a, const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r2, [%[a], #0]\n\t" + "ldr r3, [%[a], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[a], #12]\n\t" + "ldr r6, [%[b], #0]\n\t" + "ldr r7, [%[b], #4]\n\t" + "ldr r8, [%[b], #8]\n\t" + "ldr r9, [%[b], #12]\n\t" + "subs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #0]\n\t" + "str r3, [%[a], #4]\n\t" + "str r4, [%[a], #8]\n\t" + "str r5, [%[a], #12]\n\t" + "ldr r2, [%[a], #16]\n\t" + "ldr r3, [%[a], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[a], #28]\n\t" + "ldr r6, [%[b], #16]\n\t" + "ldr r7, [%[b], #20]\n\t" + "ldr r8, [%[b], #24]\n\t" + "ldr r9, [%[b], #28]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #16]\n\t" + "str r3, [%[a], #20]\n\t" + "str r4, [%[a], #24]\n\t" + "str r5, [%[a], #28]\n\t" + "ldr r2, [%[a], #32]\n\t" + "ldr r3, [%[a], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[a], #44]\n\t" + "ldr r6, [%[b], #32]\n\t" + "ldr r7, [%[b], #36]\n\t" + "ldr r8, [%[b], #40]\n\t" + "ldr r9, [%[b], #44]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #32]\n\t" + "str r3, [%[a], #36]\n\t" + "str r4, [%[a], #40]\n\t" + "str r5, [%[a], #44]\n\t" + "ldr r2, [%[a], #48]\n\t" + "ldr r3, [%[a], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[a], #60]\n\t" + "ldr r6, [%[b], #48]\n\t" + "ldr r7, [%[b], #52]\n\t" + "ldr r8, [%[b], #56]\n\t" + "ldr r9, [%[b], #60]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #48]\n\t" + "str r3, [%[a], #52]\n\t" + "str r4, [%[a], #56]\n\t" + "str r5, [%[a], #60]\n\t" + "ldr r2, [%[a], #64]\n\t" + "ldr r3, [%[a], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[a], #76]\n\t" + "ldr r6, [%[b], #64]\n\t" + "ldr r7, [%[b], #68]\n\t" + "ldr r8, [%[b], #72]\n\t" + "ldr r9, [%[b], #76]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #64]\n\t" + "str r3, [%[a], #68]\n\t" + "str r4, [%[a], #72]\n\t" + "str r5, [%[a], #76]\n\t" + "ldr r2, [%[a], #80]\n\t" + "ldr r3, [%[a], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[a], #92]\n\t" + "ldr r6, [%[b], #80]\n\t" + "ldr r7, [%[b], #84]\n\t" + "ldr r8, [%[b], #88]\n\t" + "ldr r9, [%[b], #92]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #80]\n\t" + "str r3, [%[a], #84]\n\t" + "str r4, [%[a], #88]\n\t" + "str r5, [%[a], #92]\n\t" + "ldr r2, [%[a], #96]\n\t" + "ldr r3, [%[a], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[a], #108]\n\t" + "ldr r6, [%[b], #96]\n\t" + "ldr r7, [%[b], #100]\n\t" + "ldr r8, [%[b], #104]\n\t" + "ldr r9, [%[b], #108]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #96]\n\t" + "str r3, [%[a], #100]\n\t" + "str r4, [%[a], #104]\n\t" + "str r5, [%[a], #108]\n\t" + "ldr r2, [%[a], #112]\n\t" + "ldr r3, [%[a], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[a], #124]\n\t" + "ldr r6, [%[b], #112]\n\t" + "ldr r7, [%[b], #116]\n\t" + "ldr r8, [%[b], #120]\n\t" + "ldr r9, [%[b], #124]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #112]\n\t" + "str r3, [%[a], #116]\n\t" + "str r4, [%[a], #120]\n\t" + "str r5, [%[a], #124]\n\t" + "ldr r2, [%[a], #128]\n\t" + "ldr r3, [%[a], #132]\n\t" + "ldr r4, [%[a], #136]\n\t" + "ldr r5, [%[a], #140]\n\t" + "ldr r6, [%[b], #128]\n\t" + "ldr r7, [%[b], #132]\n\t" + "ldr r8, [%[b], #136]\n\t" + "ldr r9, [%[b], #140]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #128]\n\t" + "str r3, [%[a], #132]\n\t" + "str r4, [%[a], #136]\n\t" + "str r5, [%[a], #140]\n\t" + "ldr r2, [%[a], #144]\n\t" + "ldr r3, [%[a], #148]\n\t" + "ldr r4, [%[a], #152]\n\t" + "ldr r5, [%[a], #156]\n\t" + "ldr r6, [%[b], #144]\n\t" + "ldr r7, [%[b], #148]\n\t" + "ldr r8, [%[b], #152]\n\t" + "ldr r9, [%[b], #156]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #144]\n\t" + "str r3, [%[a], #148]\n\t" + "str r4, [%[a], #152]\n\t" + "str r5, [%[a], #156]\n\t" + "ldr r2, [%[a], #160]\n\t" + "ldr r3, [%[a], #164]\n\t" + "ldr r4, [%[a], #168]\n\t" + "ldr r5, [%[a], #172]\n\t" + "ldr r6, [%[b], #160]\n\t" + "ldr r7, [%[b], #164]\n\t" + "ldr r8, [%[b], #168]\n\t" + "ldr r9, [%[b], #172]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #160]\n\t" + "str r3, [%[a], #164]\n\t" + "str r4, [%[a], #168]\n\t" + "str r5, [%[a], #172]\n\t" + "ldr r2, [%[a], #176]\n\t" + "ldr r3, [%[a], #180]\n\t" + "ldr r4, [%[a], #184]\n\t" + "ldr r5, [%[a], #188]\n\t" + "ldr r6, [%[b], #176]\n\t" + "ldr r7, [%[b], #180]\n\t" + "ldr r8, [%[b], #184]\n\t" + "ldr r9, [%[b], #188]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #176]\n\t" + "str r3, [%[a], #180]\n\t" + "str r4, [%[a], #184]\n\t" + "str r5, [%[a], #188]\n\t" + "sbc %[c], r9, r9\n\t" + : [c] "+r" (c) + : [a] "r" (a), [b] "r" (b) + : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* r = 2^n mod m where n is the number of bits to reduce by. + * Given m must be 3072 bits, just need to subtract. + * + * r A single precision number. + * m A signle precision number. + */ +static void sp_3072_mont_norm_48(sp_digit* r, sp_digit* m) +{ + XMEMSET(r, 0, sizeof(sp_digit) * 48); + + /* r = 2^n mod m */ + sp_3072_sub_in_place_48(r, m); +} + +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not copying. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +static sp_digit sp_3072_cond_sub_48(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit m) +{ + sp_digit c = 0; + +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov r9, #0\n\t" + "mov r8, #0\n\t" + "1:\n\t" + "subs %[c], r9, %[c]\n\t" + "ldr r4, [%[a], r8]\n\t" + "ldr r5, [%[b], r8]\n\t" + "and r5, r5, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbc %[c], r9, r9\n\t" + "str r4, [%[r], r8]\n\t" + "add r8, r8, #4\n\t" + "cmp r8, #192\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r4", "r6", "r5", "r7", "r8", "r9" + ); +#else + __asm__ __volatile__ ( + + "mov r9, #0\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r6, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r7, [%[b], #4]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "subs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #0]\n\t" + "str r6, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r7, [%[b], #12]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #8]\n\t" + "str r6, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r6, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r7, [%[b], #20]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #16]\n\t" + "str r6, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r6, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r7, [%[b], #28]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #24]\n\t" + "str r6, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r6, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r7, [%[b], #36]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #32]\n\t" + "str r6, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r6, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r7, [%[b], #44]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #40]\n\t" + "str r6, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r6, [%[a], #52]\n\t" + "ldr r5, [%[b], #48]\n\t" + "ldr r7, [%[b], #52]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #48]\n\t" + "str r6, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r6, [%[a], #60]\n\t" + "ldr r5, [%[b], #56]\n\t" + "ldr r7, [%[b], #60]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #56]\n\t" + "str r6, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r6, [%[a], #68]\n\t" + "ldr r5, [%[b], #64]\n\t" + "ldr r7, [%[b], #68]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #64]\n\t" + "str r6, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r6, [%[a], #76]\n\t" + "ldr r5, [%[b], #72]\n\t" + "ldr r7, [%[b], #76]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #72]\n\t" + "str r6, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r6, [%[a], #84]\n\t" + "ldr r5, [%[b], #80]\n\t" + "ldr r7, [%[b], #84]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #80]\n\t" + "str r6, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r6, [%[a], #92]\n\t" + "ldr r5, [%[b], #88]\n\t" + "ldr r7, [%[b], #92]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #88]\n\t" + "str r6, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r6, [%[a], #100]\n\t" + "ldr r5, [%[b], #96]\n\t" + "ldr r7, [%[b], #100]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #96]\n\t" + "str r6, [%[r], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r6, [%[a], #108]\n\t" + "ldr r5, [%[b], #104]\n\t" + "ldr r7, [%[b], #108]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #104]\n\t" + "str r6, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r6, [%[a], #116]\n\t" + "ldr r5, [%[b], #112]\n\t" + "ldr r7, [%[b], #116]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #112]\n\t" + "str r6, [%[r], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r6, [%[a], #124]\n\t" + "ldr r5, [%[b], #120]\n\t" + "ldr r7, [%[b], #124]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #120]\n\t" + "str r6, [%[r], #124]\n\t" + "ldr r4, [%[a], #128]\n\t" + "ldr r6, [%[a], #132]\n\t" + "ldr r5, [%[b], #128]\n\t" + "ldr r7, [%[b], #132]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #128]\n\t" + "str r6, [%[r], #132]\n\t" + "ldr r4, [%[a], #136]\n\t" + "ldr r6, [%[a], #140]\n\t" + "ldr r5, [%[b], #136]\n\t" + "ldr r7, [%[b], #140]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #136]\n\t" + "str r6, [%[r], #140]\n\t" + "ldr r4, [%[a], #144]\n\t" + "ldr r6, [%[a], #148]\n\t" + "ldr r5, [%[b], #144]\n\t" + "ldr r7, [%[b], #148]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #144]\n\t" + "str r6, [%[r], #148]\n\t" + "ldr r4, [%[a], #152]\n\t" + "ldr r6, [%[a], #156]\n\t" + "ldr r5, [%[b], #152]\n\t" + "ldr r7, [%[b], #156]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #152]\n\t" + "str r6, [%[r], #156]\n\t" + "ldr r4, [%[a], #160]\n\t" + "ldr r6, [%[a], #164]\n\t" + "ldr r5, [%[b], #160]\n\t" + "ldr r7, [%[b], #164]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #160]\n\t" + "str r6, [%[r], #164]\n\t" + "ldr r4, [%[a], #168]\n\t" + "ldr r6, [%[a], #172]\n\t" + "ldr r5, [%[b], #168]\n\t" + "ldr r7, [%[b], #172]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #168]\n\t" + "str r6, [%[r], #172]\n\t" + "ldr r4, [%[a], #176]\n\t" + "ldr r6, [%[a], #180]\n\t" + "ldr r5, [%[b], #176]\n\t" + "ldr r7, [%[b], #180]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #176]\n\t" + "str r6, [%[r], #180]\n\t" + "ldr r4, [%[a], #184]\n\t" + "ldr r6, [%[a], #188]\n\t" + "ldr r5, [%[b], #184]\n\t" + "ldr r7, [%[b], #188]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #184]\n\t" + "str r6, [%[r], #188]\n\t" + "sbc %[c], r9, r9\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r4", "r6", "r5", "r7", "r8", "r9" + ); +#endif /* WOLFSSL_SP_SMALL */ + + return c; +} + +/* Reduce the number back to 3072 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "# i = 0\n\t" + "mov r12, #0\n\t" + "ldr r10, [%[a], #0]\n\t" + "ldr r14, [%[a], #4]\n\t" + "\n1:\n\t" + "# mu = a[i] * mp\n\t" + "mul r8, %[mp], r10\n\t" + "# a[i+0] += m[0] * mu\n\t" + "ldr r7, [%[m], #0]\n\t" + "ldr r9, [%[a], #0]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r10, r10, r6\n\t" + "adc r5, r7, #0\n\t" + "# a[i+1] += m[1] * mu\n\t" + "ldr r7, [%[m], #4]\n\t" + "ldr r9, [%[a], #4]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r10, r14, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r10, r10, r5\n\t" + "adc r4, r4, #0\n\t" + "# a[i+2] += m[2] * mu\n\t" + "ldr r7, [%[m], #8]\n\t" + "ldr r14, [%[a], #8]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r14, r14, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r14, r14, r4\n\t" + "adc r5, r5, #0\n\t" + "# a[i+3] += m[3] * mu\n\t" + "ldr r7, [%[m], #12]\n\t" + "ldr r9, [%[a], #12]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #12]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+4] += m[4] * mu\n\t" + "ldr r7, [%[m], #16]\n\t" + "ldr r9, [%[a], #16]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #16]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+5] += m[5] * mu\n\t" + "ldr r7, [%[m], #20]\n\t" + "ldr r9, [%[a], #20]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #20]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+6] += m[6] * mu\n\t" + "ldr r7, [%[m], #24]\n\t" + "ldr r9, [%[a], #24]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #24]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+7] += m[7] * mu\n\t" + "ldr r7, [%[m], #28]\n\t" + "ldr r9, [%[a], #28]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #28]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+8] += m[8] * mu\n\t" + "ldr r7, [%[m], #32]\n\t" + "ldr r9, [%[a], #32]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #32]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+9] += m[9] * mu\n\t" + "ldr r7, [%[m], #36]\n\t" + "ldr r9, [%[a], #36]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #36]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+10] += m[10] * mu\n\t" + "ldr r7, [%[m], #40]\n\t" + "ldr r9, [%[a], #40]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #40]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+11] += m[11] * mu\n\t" + "ldr r7, [%[m], #44]\n\t" + "ldr r9, [%[a], #44]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #44]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+12] += m[12] * mu\n\t" + "ldr r7, [%[m], #48]\n\t" + "ldr r9, [%[a], #48]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #48]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+13] += m[13] * mu\n\t" + "ldr r7, [%[m], #52]\n\t" + "ldr r9, [%[a], #52]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #52]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+14] += m[14] * mu\n\t" + "ldr r7, [%[m], #56]\n\t" + "ldr r9, [%[a], #56]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #56]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+15] += m[15] * mu\n\t" + "ldr r7, [%[m], #60]\n\t" + "ldr r9, [%[a], #60]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #60]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+16] += m[16] * mu\n\t" + "ldr r7, [%[m], #64]\n\t" + "ldr r9, [%[a], #64]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #64]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+17] += m[17] * mu\n\t" + "ldr r7, [%[m], #68]\n\t" + "ldr r9, [%[a], #68]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #68]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+18] += m[18] * mu\n\t" + "ldr r7, [%[m], #72]\n\t" + "ldr r9, [%[a], #72]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #72]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+19] += m[19] * mu\n\t" + "ldr r7, [%[m], #76]\n\t" + "ldr r9, [%[a], #76]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #76]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+20] += m[20] * mu\n\t" + "ldr r7, [%[m], #80]\n\t" + "ldr r9, [%[a], #80]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #80]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+21] += m[21] * mu\n\t" + "ldr r7, [%[m], #84]\n\t" + "ldr r9, [%[a], #84]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #84]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+22] += m[22] * mu\n\t" + "ldr r7, [%[m], #88]\n\t" + "ldr r9, [%[a], #88]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #88]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+23] += m[23] * mu\n\t" + "ldr r7, [%[m], #92]\n\t" + "ldr r9, [%[a], #92]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #92]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+24] += m[24] * mu\n\t" + "ldr r7, [%[m], #96]\n\t" + "ldr r9, [%[a], #96]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #96]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+25] += m[25] * mu\n\t" + "ldr r7, [%[m], #100]\n\t" + "ldr r9, [%[a], #100]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #100]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+26] += m[26] * mu\n\t" + "ldr r7, [%[m], #104]\n\t" + "ldr r9, [%[a], #104]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #104]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+27] += m[27] * mu\n\t" + "ldr r7, [%[m], #108]\n\t" + "ldr r9, [%[a], #108]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #108]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+28] += m[28] * mu\n\t" + "ldr r7, [%[m], #112]\n\t" + "ldr r9, [%[a], #112]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #112]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+29] += m[29] * mu\n\t" + "ldr r7, [%[m], #116]\n\t" + "ldr r9, [%[a], #116]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #116]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+30] += m[30] * mu\n\t" + "ldr r7, [%[m], #120]\n\t" + "ldr r9, [%[a], #120]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #120]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+31] += m[31] * mu\n\t" + "ldr r7, [%[m], #124]\n\t" + "ldr r9, [%[a], #124]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #124]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+32] += m[32] * mu\n\t" + "ldr r7, [%[m], #128]\n\t" + "ldr r9, [%[a], #128]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #128]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+33] += m[33] * mu\n\t" + "ldr r7, [%[m], #132]\n\t" + "ldr r9, [%[a], #132]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #132]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+34] += m[34] * mu\n\t" + "ldr r7, [%[m], #136]\n\t" + "ldr r9, [%[a], #136]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #136]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+35] += m[35] * mu\n\t" + "ldr r7, [%[m], #140]\n\t" + "ldr r9, [%[a], #140]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #140]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+36] += m[36] * mu\n\t" + "ldr r7, [%[m], #144]\n\t" + "ldr r9, [%[a], #144]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #144]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+37] += m[37] * mu\n\t" + "ldr r7, [%[m], #148]\n\t" + "ldr r9, [%[a], #148]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #148]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+38] += m[38] * mu\n\t" + "ldr r7, [%[m], #152]\n\t" + "ldr r9, [%[a], #152]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #152]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+39] += m[39] * mu\n\t" + "ldr r7, [%[m], #156]\n\t" + "ldr r9, [%[a], #156]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #156]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+40] += m[40] * mu\n\t" + "ldr r7, [%[m], #160]\n\t" + "ldr r9, [%[a], #160]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #160]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+41] += m[41] * mu\n\t" + "ldr r7, [%[m], #164]\n\t" + "ldr r9, [%[a], #164]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #164]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+42] += m[42] * mu\n\t" + "ldr r7, [%[m], #168]\n\t" + "ldr r9, [%[a], #168]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #168]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+43] += m[43] * mu\n\t" + "ldr r7, [%[m], #172]\n\t" + "ldr r9, [%[a], #172]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #172]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+44] += m[44] * mu\n\t" + "ldr r7, [%[m], #176]\n\t" + "ldr r9, [%[a], #176]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #176]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+45] += m[45] * mu\n\t" + "ldr r7, [%[m], #180]\n\t" + "ldr r9, [%[a], #180]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #180]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+46] += m[46] * mu\n\t" + "ldr r7, [%[m], #184]\n\t" + "ldr r9, [%[a], #184]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #184]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+47] += m[47] * mu\n\t" + "ldr r7, [%[m], #188]\n\t" + "ldr r9, [%[a], #188]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r7, r7, %[ca]\n\t" + "mov %[ca], #0\n\t" + "adc %[ca], %[ca], %[ca]\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #188]\n\t" + "ldr r9, [%[a], #192]\n\t" + "adcs r9, r9, r7\n\t" + "str r9, [%[a], #192]\n\t" + "adc %[ca], %[ca], #0\n\t" + "# i += 1\n\t" + "add %[a], %[a], #4\n\t" + "add r12, r12, #4\n\t" + "cmp r12, #192\n\t" + "blt 1b\n\t" + "str r10, [%[a], #0]\n\t" + "str r14, [%[a], #4]\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + sp_3072_cond_sub_48(a - 48, a, m, (sp_digit)0 - ca); +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_3072_mont_mul_48(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_3072_mul_48(r, a, b); + sp_3072_mont_reduce_48(r, m, mp); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_3072_mont_sqr_48(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_3072_sqr_48(r, a); + sp_3072_mont_reduce_48(r, m, mp); +} + +/* Mul a by digit b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision digit. + */ +static void sp_3072_mul_d_48(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov r10, #0\n\t" + "# A[0] * B\n\t" + "ldr r8, [%[a]]\n\t" + "umull r5, r3, %[b], r8\n\t" + "mov r4, #0\n\t" + "str r5, [%[r]]\n\t" + "mov r5, #0\n\t" + "mov r9, #4\n\t" + "1:\n\t" + "ldr r8, [%[a], r9]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], r9]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "add r9, r9, #4\n\t" + "cmp r9, #192\n\t" + "blt 1b\n\t" + "str r3, [%[r], #192]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10" + ); +#else + __asm__ __volatile__ ( + "mov r10, #0\n\t" + "# A[0] * B\n\t" + "ldr r8, [%[a]]\n\t" + "umull r3, r4, %[b], r8\n\t" + "mov r5, #0\n\t" + "str r3, [%[r]]\n\t" + "# A[1] * B\n\t" + "ldr r8, [%[a], #4]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #4]\n\t" + "# A[2] * B\n\t" + "ldr r8, [%[a], #8]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #8]\n\t" + "# A[3] * B\n\t" + "ldr r8, [%[a], #12]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #12]\n\t" + "# A[4] * B\n\t" + "ldr r8, [%[a], #16]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #16]\n\t" + "# A[5] * B\n\t" + "ldr r8, [%[a], #20]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #20]\n\t" + "# A[6] * B\n\t" + "ldr r8, [%[a], #24]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #24]\n\t" + "# A[7] * B\n\t" + "ldr r8, [%[a], #28]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #28]\n\t" + "# A[8] * B\n\t" + "ldr r8, [%[a], #32]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #32]\n\t" + "# A[9] * B\n\t" + "ldr r8, [%[a], #36]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #36]\n\t" + "# A[10] * B\n\t" + "ldr r8, [%[a], #40]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #40]\n\t" + "# A[11] * B\n\t" + "ldr r8, [%[a], #44]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #44]\n\t" + "# A[12] * B\n\t" + "ldr r8, [%[a], #48]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #48]\n\t" + "# A[13] * B\n\t" + "ldr r8, [%[a], #52]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #52]\n\t" + "# A[14] * B\n\t" + "ldr r8, [%[a], #56]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #56]\n\t" + "# A[15] * B\n\t" + "ldr r8, [%[a], #60]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #60]\n\t" + "# A[16] * B\n\t" + "ldr r8, [%[a], #64]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #64]\n\t" + "# A[17] * B\n\t" + "ldr r8, [%[a], #68]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #68]\n\t" + "# A[18] * B\n\t" + "ldr r8, [%[a], #72]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #72]\n\t" + "# A[19] * B\n\t" + "ldr r8, [%[a], #76]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #76]\n\t" + "# A[20] * B\n\t" + "ldr r8, [%[a], #80]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #80]\n\t" + "# A[21] * B\n\t" + "ldr r8, [%[a], #84]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #84]\n\t" + "# A[22] * B\n\t" + "ldr r8, [%[a], #88]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #88]\n\t" + "# A[23] * B\n\t" + "ldr r8, [%[a], #92]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #92]\n\t" + "# A[24] * B\n\t" + "ldr r8, [%[a], #96]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #96]\n\t" + "# A[25] * B\n\t" + "ldr r8, [%[a], #100]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #100]\n\t" + "# A[26] * B\n\t" + "ldr r8, [%[a], #104]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #104]\n\t" + "# A[27] * B\n\t" + "ldr r8, [%[a], #108]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #108]\n\t" + "# A[28] * B\n\t" + "ldr r8, [%[a], #112]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #112]\n\t" + "# A[29] * B\n\t" + "ldr r8, [%[a], #116]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #116]\n\t" + "# A[30] * B\n\t" + "ldr r8, [%[a], #120]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #120]\n\t" + "# A[31] * B\n\t" + "ldr r8, [%[a], #124]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #124]\n\t" + "# A[32] * B\n\t" + "ldr r8, [%[a], #128]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #128]\n\t" + "# A[33] * B\n\t" + "ldr r8, [%[a], #132]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #132]\n\t" + "# A[34] * B\n\t" + "ldr r8, [%[a], #136]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #136]\n\t" + "# A[35] * B\n\t" + "ldr r8, [%[a], #140]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #140]\n\t" + "# A[36] * B\n\t" + "ldr r8, [%[a], #144]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #144]\n\t" + "# A[37] * B\n\t" + "ldr r8, [%[a], #148]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #148]\n\t" + "# A[38] * B\n\t" + "ldr r8, [%[a], #152]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #152]\n\t" + "# A[39] * B\n\t" + "ldr r8, [%[a], #156]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #156]\n\t" + "# A[40] * B\n\t" + "ldr r8, [%[a], #160]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #160]\n\t" + "# A[41] * B\n\t" + "ldr r8, [%[a], #164]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #164]\n\t" + "# A[42] * B\n\t" + "ldr r8, [%[a], #168]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #168]\n\t" + "# A[43] * B\n\t" + "ldr r8, [%[a], #172]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #172]\n\t" + "# A[44] * B\n\t" + "ldr r8, [%[a], #176]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #176]\n\t" + "# A[45] * B\n\t" + "ldr r8, [%[a], #180]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #180]\n\t" + "# A[46] * B\n\t" + "ldr r8, [%[a], #184]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #184]\n\t" + "# A[47] * B\n\t" + "ldr r8, [%[a], #188]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adc r3, r3, r7\n\t" + "str r5, [%[r], #188]\n\t" + "str r3, [%[r], #192]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10" + ); +#endif +} + +/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) + * + * d1 The high order half of the number to divide. + * d0 The low order half of the number to divide. + * div The dividend. + * returns the result of the division. + * + * Note that this is an approximate div. It may give an answer 1 larger. + */ +static sp_digit div_3072_word_48(sp_digit d1, sp_digit d0, sp_digit div) +{ + sp_digit r = 0; + + __asm__ __volatile__ ( + "lsr r5, %[div], #1\n\t" + "add r5, r5, #1\n\t" + "mov r6, %[d0]\n\t" + "mov r7, %[d1]\n\t" + "# Do top 32\n\t" + "subs r8, r5, r7\n\t" + "sbc r8, r8, r8\n\t" + "add %[r], %[r], %[r]\n\t" + "sub %[r], %[r], r8\n\t" + "and r8, r8, r5\n\t" + "subs r7, r7, r8\n\t" + "# Next 30 bits\n\t" + "mov r4, #29\n\t" + "1:\n\t" + "movs r6, r6, lsl #1\n\t" + "adc r7, r7, r7\n\t" + "subs r8, r5, r7\n\t" + "sbc r8, r8, r8\n\t" + "add %[r], %[r], %[r]\n\t" + "sub %[r], %[r], r8\n\t" + "and r8, r8, r5\n\t" + "subs r7, r7, r8\n\t" + "subs r4, r4, #1\n\t" + "bpl 1b\n\t" + "add %[r], %[r], %[r]\n\t" + "add %[r], %[r], #1\n\t" + "umull r4, r5, %[r], %[div]\n\t" + "subs r4, %[d0], r4\n\t" + "sbc r5, %[d1], r5\n\t" + "add %[r], %[r], r5\n\t" + "umull r4, r5, %[r], %[div]\n\t" + "subs r4, %[d0], r4\n\t" + "sbc r5, %[d1], r5\n\t" + "add %[r], %[r], r5\n\t" + "subs r8, %[div], r4\n\t" + "sbc r8, r8, r8\n\t" + "sub %[r], %[r], r8\n\t" + : [r] "+r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "r4", "r5", "r6", "r7", "r8" + ); + return r; +} + +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +static int32_t sp_3072_cmp_48(sp_digit* a, sp_digit* b) +{ + sp_digit r = -1; + sp_digit one = 1; + + +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov r7, #0\n\t" + "mov r3, #-1\n\t" + "mov r6, #188\n\t" + "1:\n\t" + "ldr r4, [%[a], r6]\n\t" + "ldr r5, [%[b], r6]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "sub r6, r6, #4\n\t" + "bcc 1b\n\t" + "eor %[r], %[r], r3\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [one] "r" (one) + : "r3", "r4", "r5", "r6", "r7" + ); +#else + __asm__ __volatile__ ( + "mov r7, #0\n\t" + "mov r3, #-1\n\t" + "ldr r4, [%[a], #188]\n\t" + "ldr r5, [%[b], #188]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #184]\n\t" + "ldr r5, [%[b], #184]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #180]\n\t" + "ldr r5, [%[b], #180]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #176]\n\t" + "ldr r5, [%[b], #176]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #172]\n\t" + "ldr r5, [%[b], #172]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #168]\n\t" + "ldr r5, [%[b], #168]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #164]\n\t" + "ldr r5, [%[b], #164]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #160]\n\t" + "ldr r5, [%[b], #160]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #156]\n\t" + "ldr r5, [%[b], #156]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #152]\n\t" + "ldr r5, [%[b], #152]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #148]\n\t" + "ldr r5, [%[b], #148]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #144]\n\t" + "ldr r5, [%[b], #144]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #140]\n\t" + "ldr r5, [%[b], #140]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #136]\n\t" + "ldr r5, [%[b], #136]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #132]\n\t" + "ldr r5, [%[b], #132]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #128]\n\t" + "ldr r5, [%[b], #128]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #124]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[b], #120]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #116]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[b], #112]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #108]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[b], #104]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #100]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[b], #96]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #92]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[b], #88]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #84]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[b], #80]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #76]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[b], #72]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #68]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[b], #64]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #60]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[b], #56]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #52]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[b], #48]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "eor %[r], %[r], r3\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [one] "r" (one) + : "r3", "r4", "r5", "r6", "r7" + ); +#endif + + return r; +} + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_3072_div_48(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[96], t2[49]; + sp_digit div, r1; + int i; + + (void)m; + + div = d[47]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 48); + for (i=47; i>=0; i--) { + r1 = div_3072_word_48(t1[48 + i], t1[48 + i - 1], div); + + sp_3072_mul_d_48(t2, d, r1); + t1[48 + i] += sp_3072_sub_in_place_48(&t1[i], t2); + t1[48 + i] -= t2[48]; + sp_3072_mask_48(t2, d, t1[48 + i]); + t1[48 + i] += sp_3072_add_48(&t1[i], &t1[i], t2); + sp_3072_mask_48(t2, d, t1[48 + i]); + t1[48 + i] += sp_3072_add_48(&t1[i], &t1[i], t2); + } + + r1 = sp_3072_cmp_48(t1, d) >= 0; + sp_3072_cond_sub_48(r, t1, d, (sp_digit)0 - r1); + + return MP_OKAY; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_3072_mod_48(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_3072_div_48(a, m, NULL, r); +} + +#ifdef WOLFSSL_SP_SMALL +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_3072_mod_exp_48(sp_digit* r, sp_digit* a, sp_digit* e, + int bits, sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[16][96]; +#else + sp_digit* t[16]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 96, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<16; i++) + t[i] = td + i * 96; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_48(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 48); + if (reduceA) { + err = sp_3072_mod_48(t[1] + 48, a, m); + if (err == MP_OKAY) + err = sp_3072_mod_48(t[1], t[1], m); + } + else { + XMEMCPY(t[1] + 48, a, sizeof(sp_digit) * 48); + err = sp_3072_mod_48(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_3072_mont_sqr_48(t[ 2], t[ 1], m, mp); + sp_3072_mont_mul_48(t[ 3], t[ 2], t[ 1], m, mp); + sp_3072_mont_sqr_48(t[ 4], t[ 2], m, mp); + sp_3072_mont_mul_48(t[ 5], t[ 3], t[ 2], m, mp); + sp_3072_mont_sqr_48(t[ 6], t[ 3], m, mp); + sp_3072_mont_mul_48(t[ 7], t[ 4], t[ 3], m, mp); + sp_3072_mont_sqr_48(t[ 8], t[ 4], m, mp); + sp_3072_mont_mul_48(t[ 9], t[ 5], t[ 4], m, mp); + sp_3072_mont_sqr_48(t[10], t[ 5], m, mp); + sp_3072_mont_mul_48(t[11], t[ 6], t[ 5], m, mp); + sp_3072_mont_sqr_48(t[12], t[ 6], m, mp); + sp_3072_mont_mul_48(t[13], t[ 7], t[ 6], m, mp); + sp_3072_mont_sqr_48(t[14], t[ 7], m, mp); + sp_3072_mont_mul_48(t[15], t[ 8], t[ 7], m, mp); + + i = (bits - 1) / 32; + n = e[i--]; + y = n >> 28; + n <<= 4; + c = 28; + XMEMCPY(r, t[y], sizeof(sp_digit) * 48); + for (; i>=0 || c>=4; ) { + if (c == 0) { + n = e[i--]; + y = n >> 28; + n <<= 4; + c = 28; + } + else if (c < 4) { + y = n >> 28; + n = e[i--]; + c = 4 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 28) & 0xf; + n <<= 4; + c -= 4; + } + + sp_3072_mont_sqr_48(r, r, m, mp); + sp_3072_mont_sqr_48(r, r, m, mp); + sp_3072_mont_sqr_48(r, r, m, mp); + sp_3072_mont_sqr_48(r, r, m, mp); + + sp_3072_mont_mul_48(r, r, t[y], m, mp); + } + y = e[0] & ((1 << c) - 1); + for (; c > 0; c--) + sp_3072_mont_sqr_48(r, r, m, mp); + sp_3072_mont_mul_48(r, r, t[y], m, mp); + + XMEMSET(&r[48], 0, sizeof(sp_digit) * 48); + sp_3072_mont_reduce_48(r, m, mp); + + mask = 0 - (sp_3072_cmp_48(r, m) >= 0); + sp_3072_cond_sub_48(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#else +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_3072_mod_exp_48(sp_digit* r, sp_digit* a, sp_digit* e, + int bits, sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][96]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 96, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<32; i++) + t[i] = td + i * 96; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_48(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 48); + if (reduceA) { + err = sp_3072_mod_48(t[1] + 48, a, m); + if (err == MP_OKAY) + err = sp_3072_mod_48(t[1], t[1], m); + } + else { + XMEMCPY(t[1] + 48, a, sizeof(sp_digit) * 48); + err = sp_3072_mod_48(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_3072_mont_sqr_48(t[ 2], t[ 1], m, mp); + sp_3072_mont_mul_48(t[ 3], t[ 2], t[ 1], m, mp); + sp_3072_mont_sqr_48(t[ 4], t[ 2], m, mp); + sp_3072_mont_mul_48(t[ 5], t[ 3], t[ 2], m, mp); + sp_3072_mont_sqr_48(t[ 6], t[ 3], m, mp); + sp_3072_mont_mul_48(t[ 7], t[ 4], t[ 3], m, mp); + sp_3072_mont_sqr_48(t[ 8], t[ 4], m, mp); + sp_3072_mont_mul_48(t[ 9], t[ 5], t[ 4], m, mp); + sp_3072_mont_sqr_48(t[10], t[ 5], m, mp); + sp_3072_mont_mul_48(t[11], t[ 6], t[ 5], m, mp); + sp_3072_mont_sqr_48(t[12], t[ 6], m, mp); + sp_3072_mont_mul_48(t[13], t[ 7], t[ 6], m, mp); + sp_3072_mont_sqr_48(t[14], t[ 7], m, mp); + sp_3072_mont_mul_48(t[15], t[ 8], t[ 7], m, mp); + sp_3072_mont_sqr_48(t[16], t[ 8], m, mp); + sp_3072_mont_mul_48(t[17], t[ 9], t[ 8], m, mp); + sp_3072_mont_sqr_48(t[18], t[ 9], m, mp); + sp_3072_mont_mul_48(t[19], t[10], t[ 9], m, mp); + sp_3072_mont_sqr_48(t[20], t[10], m, mp); + sp_3072_mont_mul_48(t[21], t[11], t[10], m, mp); + sp_3072_mont_sqr_48(t[22], t[11], m, mp); + sp_3072_mont_mul_48(t[23], t[12], t[11], m, mp); + sp_3072_mont_sqr_48(t[24], t[12], m, mp); + sp_3072_mont_mul_48(t[25], t[13], t[12], m, mp); + sp_3072_mont_sqr_48(t[26], t[13], m, mp); + sp_3072_mont_mul_48(t[27], t[14], t[13], m, mp); + sp_3072_mont_sqr_48(t[28], t[14], m, mp); + sp_3072_mont_mul_48(t[29], t[15], t[14], m, mp); + sp_3072_mont_sqr_48(t[30], t[15], m, mp); + sp_3072_mont_mul_48(t[31], t[16], t[15], m, mp); + + i = (bits - 1) / 32; + n = e[i--]; + y = n >> 27; + n <<= 5; + c = 27; + XMEMCPY(r, t[y], sizeof(sp_digit) * 48); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 27; + n <<= 5; + c = 27; + } + else if (c < 5) { + y = n >> 27; + n = e[i--]; + c = 5 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 27) & 0x1f; + n <<= 5; + c -= 5; + } + + sp_3072_mont_sqr_48(r, r, m, mp); + sp_3072_mont_sqr_48(r, r, m, mp); + sp_3072_mont_sqr_48(r, r, m, mp); + sp_3072_mont_sqr_48(r, r, m, mp); + sp_3072_mont_sqr_48(r, r, m, mp); + + sp_3072_mont_mul_48(r, r, t[y], m, mp); + } + y = e[0] & ((1 << c) - 1); + for (; c > 0; c--) + sp_3072_mont_sqr_48(r, r, m, mp); + sp_3072_mont_mul_48(r, r, t[y], m, mp); + + XMEMSET(&r[48], 0, sizeof(sp_digit) * 48); + sp_3072_mont_reduce_48(r, m, mp); + + mask = 0 - (sp_3072_cmp_48(r, m) >= 0); + sp_3072_cond_sub_48(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#endif /* WOLFSSL_SP_SMALL */ + +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) +/* r = 2^n mod m where n is the number of bits to reduce by. + * Given m must be 3072 bits, just need to subtract. + * + * r A single precision number. + * m A signle precision number. + */ +static void sp_3072_mont_norm_96(sp_digit* r, sp_digit* m) +{ + XMEMSET(r, 0, sizeof(sp_digit) * 96); + + /* r = 2^n mod m */ + sp_3072_sub_in_place_96(r, m); +} + +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not copying. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +static sp_digit sp_3072_cond_sub_96(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit m) +{ + sp_digit c = 0; + +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov r9, #0\n\t" + "mov r8, #0\n\t" + "1:\n\t" + "subs %[c], r9, %[c]\n\t" + "ldr r4, [%[a], r8]\n\t" + "ldr r5, [%[b], r8]\n\t" + "and r5, r5, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbc %[c], r9, r9\n\t" + "str r4, [%[r], r8]\n\t" + "add r8, r8, #4\n\t" + "cmp r8, #384\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r4", "r6", "r5", "r7", "r8", "r9" + ); +#else + __asm__ __volatile__ ( + + "mov r9, #0\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r6, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r7, [%[b], #4]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "subs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #0]\n\t" + "str r6, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r7, [%[b], #12]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #8]\n\t" + "str r6, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r6, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r7, [%[b], #20]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #16]\n\t" + "str r6, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r6, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r7, [%[b], #28]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #24]\n\t" + "str r6, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r6, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r7, [%[b], #36]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #32]\n\t" + "str r6, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r6, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r7, [%[b], #44]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #40]\n\t" + "str r6, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r6, [%[a], #52]\n\t" + "ldr r5, [%[b], #48]\n\t" + "ldr r7, [%[b], #52]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #48]\n\t" + "str r6, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r6, [%[a], #60]\n\t" + "ldr r5, [%[b], #56]\n\t" + "ldr r7, [%[b], #60]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #56]\n\t" + "str r6, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r6, [%[a], #68]\n\t" + "ldr r5, [%[b], #64]\n\t" + "ldr r7, [%[b], #68]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #64]\n\t" + "str r6, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r6, [%[a], #76]\n\t" + "ldr r5, [%[b], #72]\n\t" + "ldr r7, [%[b], #76]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #72]\n\t" + "str r6, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r6, [%[a], #84]\n\t" + "ldr r5, [%[b], #80]\n\t" + "ldr r7, [%[b], #84]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #80]\n\t" + "str r6, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r6, [%[a], #92]\n\t" + "ldr r5, [%[b], #88]\n\t" + "ldr r7, [%[b], #92]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #88]\n\t" + "str r6, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r6, [%[a], #100]\n\t" + "ldr r5, [%[b], #96]\n\t" + "ldr r7, [%[b], #100]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #96]\n\t" + "str r6, [%[r], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r6, [%[a], #108]\n\t" + "ldr r5, [%[b], #104]\n\t" + "ldr r7, [%[b], #108]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #104]\n\t" + "str r6, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r6, [%[a], #116]\n\t" + "ldr r5, [%[b], #112]\n\t" + "ldr r7, [%[b], #116]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #112]\n\t" + "str r6, [%[r], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r6, [%[a], #124]\n\t" + "ldr r5, [%[b], #120]\n\t" + "ldr r7, [%[b], #124]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #120]\n\t" + "str r6, [%[r], #124]\n\t" + "ldr r4, [%[a], #128]\n\t" + "ldr r6, [%[a], #132]\n\t" + "ldr r5, [%[b], #128]\n\t" + "ldr r7, [%[b], #132]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #128]\n\t" + "str r6, [%[r], #132]\n\t" + "ldr r4, [%[a], #136]\n\t" + "ldr r6, [%[a], #140]\n\t" + "ldr r5, [%[b], #136]\n\t" + "ldr r7, [%[b], #140]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #136]\n\t" + "str r6, [%[r], #140]\n\t" + "ldr r4, [%[a], #144]\n\t" + "ldr r6, [%[a], #148]\n\t" + "ldr r5, [%[b], #144]\n\t" + "ldr r7, [%[b], #148]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #144]\n\t" + "str r6, [%[r], #148]\n\t" + "ldr r4, [%[a], #152]\n\t" + "ldr r6, [%[a], #156]\n\t" + "ldr r5, [%[b], #152]\n\t" + "ldr r7, [%[b], #156]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #152]\n\t" + "str r6, [%[r], #156]\n\t" + "ldr r4, [%[a], #160]\n\t" + "ldr r6, [%[a], #164]\n\t" + "ldr r5, [%[b], #160]\n\t" + "ldr r7, [%[b], #164]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #160]\n\t" + "str r6, [%[r], #164]\n\t" + "ldr r4, [%[a], #168]\n\t" + "ldr r6, [%[a], #172]\n\t" + "ldr r5, [%[b], #168]\n\t" + "ldr r7, [%[b], #172]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #168]\n\t" + "str r6, [%[r], #172]\n\t" + "ldr r4, [%[a], #176]\n\t" + "ldr r6, [%[a], #180]\n\t" + "ldr r5, [%[b], #176]\n\t" + "ldr r7, [%[b], #180]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #176]\n\t" + "str r6, [%[r], #180]\n\t" + "ldr r4, [%[a], #184]\n\t" + "ldr r6, [%[a], #188]\n\t" + "ldr r5, [%[b], #184]\n\t" + "ldr r7, [%[b], #188]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #184]\n\t" + "str r6, [%[r], #188]\n\t" + "ldr r4, [%[a], #192]\n\t" + "ldr r6, [%[a], #196]\n\t" + "ldr r5, [%[b], #192]\n\t" + "ldr r7, [%[b], #196]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #192]\n\t" + "str r6, [%[r], #196]\n\t" + "ldr r4, [%[a], #200]\n\t" + "ldr r6, [%[a], #204]\n\t" + "ldr r5, [%[b], #200]\n\t" + "ldr r7, [%[b], #204]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #200]\n\t" + "str r6, [%[r], #204]\n\t" + "ldr r4, [%[a], #208]\n\t" + "ldr r6, [%[a], #212]\n\t" + "ldr r5, [%[b], #208]\n\t" + "ldr r7, [%[b], #212]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #208]\n\t" + "str r6, [%[r], #212]\n\t" + "ldr r4, [%[a], #216]\n\t" + "ldr r6, [%[a], #220]\n\t" + "ldr r5, [%[b], #216]\n\t" + "ldr r7, [%[b], #220]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #216]\n\t" + "str r6, [%[r], #220]\n\t" + "ldr r4, [%[a], #224]\n\t" + "ldr r6, [%[a], #228]\n\t" + "ldr r5, [%[b], #224]\n\t" + "ldr r7, [%[b], #228]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #224]\n\t" + "str r6, [%[r], #228]\n\t" + "ldr r4, [%[a], #232]\n\t" + "ldr r6, [%[a], #236]\n\t" + "ldr r5, [%[b], #232]\n\t" + "ldr r7, [%[b], #236]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #232]\n\t" + "str r6, [%[r], #236]\n\t" + "ldr r4, [%[a], #240]\n\t" + "ldr r6, [%[a], #244]\n\t" + "ldr r5, [%[b], #240]\n\t" + "ldr r7, [%[b], #244]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #240]\n\t" + "str r6, [%[r], #244]\n\t" + "ldr r4, [%[a], #248]\n\t" + "ldr r6, [%[a], #252]\n\t" + "ldr r5, [%[b], #248]\n\t" + "ldr r7, [%[b], #252]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #248]\n\t" + "str r6, [%[r], #252]\n\t" + "ldr r4, [%[a], #256]\n\t" + "ldr r6, [%[a], #260]\n\t" + "ldr r5, [%[b], #256]\n\t" + "ldr r7, [%[b], #260]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #256]\n\t" + "str r6, [%[r], #260]\n\t" + "ldr r4, [%[a], #264]\n\t" + "ldr r6, [%[a], #268]\n\t" + "ldr r5, [%[b], #264]\n\t" + "ldr r7, [%[b], #268]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #264]\n\t" + "str r6, [%[r], #268]\n\t" + "ldr r4, [%[a], #272]\n\t" + "ldr r6, [%[a], #276]\n\t" + "ldr r5, [%[b], #272]\n\t" + "ldr r7, [%[b], #276]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #272]\n\t" + "str r6, [%[r], #276]\n\t" + "ldr r4, [%[a], #280]\n\t" + "ldr r6, [%[a], #284]\n\t" + "ldr r5, [%[b], #280]\n\t" + "ldr r7, [%[b], #284]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #280]\n\t" + "str r6, [%[r], #284]\n\t" + "ldr r4, [%[a], #288]\n\t" + "ldr r6, [%[a], #292]\n\t" + "ldr r5, [%[b], #288]\n\t" + "ldr r7, [%[b], #292]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #288]\n\t" + "str r6, [%[r], #292]\n\t" + "ldr r4, [%[a], #296]\n\t" + "ldr r6, [%[a], #300]\n\t" + "ldr r5, [%[b], #296]\n\t" + "ldr r7, [%[b], #300]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #296]\n\t" + "str r6, [%[r], #300]\n\t" + "ldr r4, [%[a], #304]\n\t" + "ldr r6, [%[a], #308]\n\t" + "ldr r5, [%[b], #304]\n\t" + "ldr r7, [%[b], #308]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #304]\n\t" + "str r6, [%[r], #308]\n\t" + "ldr r4, [%[a], #312]\n\t" + "ldr r6, [%[a], #316]\n\t" + "ldr r5, [%[b], #312]\n\t" + "ldr r7, [%[b], #316]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #312]\n\t" + "str r6, [%[r], #316]\n\t" + "ldr r4, [%[a], #320]\n\t" + "ldr r6, [%[a], #324]\n\t" + "ldr r5, [%[b], #320]\n\t" + "ldr r7, [%[b], #324]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #320]\n\t" + "str r6, [%[r], #324]\n\t" + "ldr r4, [%[a], #328]\n\t" + "ldr r6, [%[a], #332]\n\t" + "ldr r5, [%[b], #328]\n\t" + "ldr r7, [%[b], #332]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #328]\n\t" + "str r6, [%[r], #332]\n\t" + "ldr r4, [%[a], #336]\n\t" + "ldr r6, [%[a], #340]\n\t" + "ldr r5, [%[b], #336]\n\t" + "ldr r7, [%[b], #340]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #336]\n\t" + "str r6, [%[r], #340]\n\t" + "ldr r4, [%[a], #344]\n\t" + "ldr r6, [%[a], #348]\n\t" + "ldr r5, [%[b], #344]\n\t" + "ldr r7, [%[b], #348]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #344]\n\t" + "str r6, [%[r], #348]\n\t" + "ldr r4, [%[a], #352]\n\t" + "ldr r6, [%[a], #356]\n\t" + "ldr r5, [%[b], #352]\n\t" + "ldr r7, [%[b], #356]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #352]\n\t" + "str r6, [%[r], #356]\n\t" + "ldr r4, [%[a], #360]\n\t" + "ldr r6, [%[a], #364]\n\t" + "ldr r5, [%[b], #360]\n\t" + "ldr r7, [%[b], #364]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #360]\n\t" + "str r6, [%[r], #364]\n\t" + "ldr r4, [%[a], #368]\n\t" + "ldr r6, [%[a], #372]\n\t" + "ldr r5, [%[b], #368]\n\t" + "ldr r7, [%[b], #372]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #368]\n\t" + "str r6, [%[r], #372]\n\t" + "ldr r4, [%[a], #376]\n\t" + "ldr r6, [%[a], #380]\n\t" + "ldr r5, [%[b], #376]\n\t" + "ldr r7, [%[b], #380]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #376]\n\t" + "str r6, [%[r], #380]\n\t" + "sbc %[c], r9, r9\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r4", "r6", "r5", "r7", "r8", "r9" + ); +#endif /* WOLFSSL_SP_SMALL */ + + return c; +} + +/* Reduce the number back to 3072 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "# i = 0\n\t" + "mov r12, #0\n\t" + "ldr r10, [%[a], #0]\n\t" + "ldr r14, [%[a], #4]\n\t" + "\n1:\n\t" + "# mu = a[i] * mp\n\t" + "mul r8, %[mp], r10\n\t" + "# a[i+0] += m[0] * mu\n\t" + "ldr r7, [%[m], #0]\n\t" + "ldr r9, [%[a], #0]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r10, r10, r6\n\t" + "adc r5, r7, #0\n\t" + "# a[i+1] += m[1] * mu\n\t" + "ldr r7, [%[m], #4]\n\t" + "ldr r9, [%[a], #4]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r10, r14, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r10, r10, r5\n\t" + "adc r4, r4, #0\n\t" + "# a[i+2] += m[2] * mu\n\t" + "ldr r7, [%[m], #8]\n\t" + "ldr r14, [%[a], #8]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r14, r14, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r14, r14, r4\n\t" + "adc r5, r5, #0\n\t" + "# a[i+3] += m[3] * mu\n\t" + "ldr r7, [%[m], #12]\n\t" + "ldr r9, [%[a], #12]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #12]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+4] += m[4] * mu\n\t" + "ldr r7, [%[m], #16]\n\t" + "ldr r9, [%[a], #16]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #16]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+5] += m[5] * mu\n\t" + "ldr r7, [%[m], #20]\n\t" + "ldr r9, [%[a], #20]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #20]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+6] += m[6] * mu\n\t" + "ldr r7, [%[m], #24]\n\t" + "ldr r9, [%[a], #24]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #24]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+7] += m[7] * mu\n\t" + "ldr r7, [%[m], #28]\n\t" + "ldr r9, [%[a], #28]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #28]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+8] += m[8] * mu\n\t" + "ldr r7, [%[m], #32]\n\t" + "ldr r9, [%[a], #32]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #32]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+9] += m[9] * mu\n\t" + "ldr r7, [%[m], #36]\n\t" + "ldr r9, [%[a], #36]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #36]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+10] += m[10] * mu\n\t" + "ldr r7, [%[m], #40]\n\t" + "ldr r9, [%[a], #40]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #40]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+11] += m[11] * mu\n\t" + "ldr r7, [%[m], #44]\n\t" + "ldr r9, [%[a], #44]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #44]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+12] += m[12] * mu\n\t" + "ldr r7, [%[m], #48]\n\t" + "ldr r9, [%[a], #48]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #48]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+13] += m[13] * mu\n\t" + "ldr r7, [%[m], #52]\n\t" + "ldr r9, [%[a], #52]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #52]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+14] += m[14] * mu\n\t" + "ldr r7, [%[m], #56]\n\t" + "ldr r9, [%[a], #56]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #56]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+15] += m[15] * mu\n\t" + "ldr r7, [%[m], #60]\n\t" + "ldr r9, [%[a], #60]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #60]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+16] += m[16] * mu\n\t" + "ldr r7, [%[m], #64]\n\t" + "ldr r9, [%[a], #64]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #64]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+17] += m[17] * mu\n\t" + "ldr r7, [%[m], #68]\n\t" + "ldr r9, [%[a], #68]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #68]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+18] += m[18] * mu\n\t" + "ldr r7, [%[m], #72]\n\t" + "ldr r9, [%[a], #72]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #72]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+19] += m[19] * mu\n\t" + "ldr r7, [%[m], #76]\n\t" + "ldr r9, [%[a], #76]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #76]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+20] += m[20] * mu\n\t" + "ldr r7, [%[m], #80]\n\t" + "ldr r9, [%[a], #80]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #80]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+21] += m[21] * mu\n\t" + "ldr r7, [%[m], #84]\n\t" + "ldr r9, [%[a], #84]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #84]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+22] += m[22] * mu\n\t" + "ldr r7, [%[m], #88]\n\t" + "ldr r9, [%[a], #88]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #88]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+23] += m[23] * mu\n\t" + "ldr r7, [%[m], #92]\n\t" + "ldr r9, [%[a], #92]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #92]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+24] += m[24] * mu\n\t" + "ldr r7, [%[m], #96]\n\t" + "ldr r9, [%[a], #96]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #96]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+25] += m[25] * mu\n\t" + "ldr r7, [%[m], #100]\n\t" + "ldr r9, [%[a], #100]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #100]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+26] += m[26] * mu\n\t" + "ldr r7, [%[m], #104]\n\t" + "ldr r9, [%[a], #104]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #104]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+27] += m[27] * mu\n\t" + "ldr r7, [%[m], #108]\n\t" + "ldr r9, [%[a], #108]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #108]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+28] += m[28] * mu\n\t" + "ldr r7, [%[m], #112]\n\t" + "ldr r9, [%[a], #112]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #112]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+29] += m[29] * mu\n\t" + "ldr r7, [%[m], #116]\n\t" + "ldr r9, [%[a], #116]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #116]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+30] += m[30] * mu\n\t" + "ldr r7, [%[m], #120]\n\t" + "ldr r9, [%[a], #120]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #120]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+31] += m[31] * mu\n\t" + "ldr r7, [%[m], #124]\n\t" + "ldr r9, [%[a], #124]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #124]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+32] += m[32] * mu\n\t" + "ldr r7, [%[m], #128]\n\t" + "ldr r9, [%[a], #128]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #128]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+33] += m[33] * mu\n\t" + "ldr r7, [%[m], #132]\n\t" + "ldr r9, [%[a], #132]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #132]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+34] += m[34] * mu\n\t" + "ldr r7, [%[m], #136]\n\t" + "ldr r9, [%[a], #136]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #136]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+35] += m[35] * mu\n\t" + "ldr r7, [%[m], #140]\n\t" + "ldr r9, [%[a], #140]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #140]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+36] += m[36] * mu\n\t" + "ldr r7, [%[m], #144]\n\t" + "ldr r9, [%[a], #144]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #144]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+37] += m[37] * mu\n\t" + "ldr r7, [%[m], #148]\n\t" + "ldr r9, [%[a], #148]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #148]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+38] += m[38] * mu\n\t" + "ldr r7, [%[m], #152]\n\t" + "ldr r9, [%[a], #152]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #152]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+39] += m[39] * mu\n\t" + "ldr r7, [%[m], #156]\n\t" + "ldr r9, [%[a], #156]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #156]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+40] += m[40] * mu\n\t" + "ldr r7, [%[m], #160]\n\t" + "ldr r9, [%[a], #160]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #160]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+41] += m[41] * mu\n\t" + "ldr r7, [%[m], #164]\n\t" + "ldr r9, [%[a], #164]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #164]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+42] += m[42] * mu\n\t" + "ldr r7, [%[m], #168]\n\t" + "ldr r9, [%[a], #168]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #168]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+43] += m[43] * mu\n\t" + "ldr r7, [%[m], #172]\n\t" + "ldr r9, [%[a], #172]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #172]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+44] += m[44] * mu\n\t" + "ldr r7, [%[m], #176]\n\t" + "ldr r9, [%[a], #176]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #176]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+45] += m[45] * mu\n\t" + "ldr r7, [%[m], #180]\n\t" + "ldr r9, [%[a], #180]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #180]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+46] += m[46] * mu\n\t" + "ldr r7, [%[m], #184]\n\t" + "ldr r9, [%[a], #184]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #184]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+47] += m[47] * mu\n\t" + "ldr r7, [%[m], #188]\n\t" + "ldr r9, [%[a], #188]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #188]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+48] += m[48] * mu\n\t" + "ldr r7, [%[m], #192]\n\t" + "ldr r9, [%[a], #192]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #192]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+49] += m[49] * mu\n\t" + "ldr r7, [%[m], #196]\n\t" + "ldr r9, [%[a], #196]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #196]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+50] += m[50] * mu\n\t" + "ldr r7, [%[m], #200]\n\t" + "ldr r9, [%[a], #200]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #200]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+51] += m[51] * mu\n\t" + "ldr r7, [%[m], #204]\n\t" + "ldr r9, [%[a], #204]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #204]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+52] += m[52] * mu\n\t" + "ldr r7, [%[m], #208]\n\t" + "ldr r9, [%[a], #208]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #208]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+53] += m[53] * mu\n\t" + "ldr r7, [%[m], #212]\n\t" + "ldr r9, [%[a], #212]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #212]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+54] += m[54] * mu\n\t" + "ldr r7, [%[m], #216]\n\t" + "ldr r9, [%[a], #216]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #216]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+55] += m[55] * mu\n\t" + "ldr r7, [%[m], #220]\n\t" + "ldr r9, [%[a], #220]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #220]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+56] += m[56] * mu\n\t" + "ldr r7, [%[m], #224]\n\t" + "ldr r9, [%[a], #224]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #224]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+57] += m[57] * mu\n\t" + "ldr r7, [%[m], #228]\n\t" + "ldr r9, [%[a], #228]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #228]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+58] += m[58] * mu\n\t" + "ldr r7, [%[m], #232]\n\t" + "ldr r9, [%[a], #232]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #232]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+59] += m[59] * mu\n\t" + "ldr r7, [%[m], #236]\n\t" + "ldr r9, [%[a], #236]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #236]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+60] += m[60] * mu\n\t" + "ldr r7, [%[m], #240]\n\t" + "ldr r9, [%[a], #240]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #240]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+61] += m[61] * mu\n\t" + "ldr r7, [%[m], #244]\n\t" + "ldr r9, [%[a], #244]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #244]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+62] += m[62] * mu\n\t" + "ldr r7, [%[m], #248]\n\t" + "ldr r9, [%[a], #248]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #248]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+63] += m[63] * mu\n\t" + "ldr r7, [%[m], #252]\n\t" + "ldr r9, [%[a], #252]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #252]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+64] += m[64] * mu\n\t" + "ldr r7, [%[m], #256]\n\t" + "ldr r9, [%[a], #256]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #256]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+65] += m[65] * mu\n\t" + "ldr r7, [%[m], #260]\n\t" + "ldr r9, [%[a], #260]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #260]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+66] += m[66] * mu\n\t" + "ldr r7, [%[m], #264]\n\t" + "ldr r9, [%[a], #264]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #264]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+67] += m[67] * mu\n\t" + "ldr r7, [%[m], #268]\n\t" + "ldr r9, [%[a], #268]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #268]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+68] += m[68] * mu\n\t" + "ldr r7, [%[m], #272]\n\t" + "ldr r9, [%[a], #272]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #272]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+69] += m[69] * mu\n\t" + "ldr r7, [%[m], #276]\n\t" + "ldr r9, [%[a], #276]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #276]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+70] += m[70] * mu\n\t" + "ldr r7, [%[m], #280]\n\t" + "ldr r9, [%[a], #280]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #280]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+71] += m[71] * mu\n\t" + "ldr r7, [%[m], #284]\n\t" + "ldr r9, [%[a], #284]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #284]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+72] += m[72] * mu\n\t" + "ldr r7, [%[m], #288]\n\t" + "ldr r9, [%[a], #288]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #288]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+73] += m[73] * mu\n\t" + "ldr r7, [%[m], #292]\n\t" + "ldr r9, [%[a], #292]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #292]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+74] += m[74] * mu\n\t" + "ldr r7, [%[m], #296]\n\t" + "ldr r9, [%[a], #296]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #296]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+75] += m[75] * mu\n\t" + "ldr r7, [%[m], #300]\n\t" + "ldr r9, [%[a], #300]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #300]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+76] += m[76] * mu\n\t" + "ldr r7, [%[m], #304]\n\t" + "ldr r9, [%[a], #304]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #304]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+77] += m[77] * mu\n\t" + "ldr r7, [%[m], #308]\n\t" + "ldr r9, [%[a], #308]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #308]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+78] += m[78] * mu\n\t" + "ldr r7, [%[m], #312]\n\t" + "ldr r9, [%[a], #312]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #312]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+79] += m[79] * mu\n\t" + "ldr r7, [%[m], #316]\n\t" + "ldr r9, [%[a], #316]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #316]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+80] += m[80] * mu\n\t" + "ldr r7, [%[m], #320]\n\t" + "ldr r9, [%[a], #320]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #320]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+81] += m[81] * mu\n\t" + "ldr r7, [%[m], #324]\n\t" + "ldr r9, [%[a], #324]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #324]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+82] += m[82] * mu\n\t" + "ldr r7, [%[m], #328]\n\t" + "ldr r9, [%[a], #328]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #328]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+83] += m[83] * mu\n\t" + "ldr r7, [%[m], #332]\n\t" + "ldr r9, [%[a], #332]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #332]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+84] += m[84] * mu\n\t" + "ldr r7, [%[m], #336]\n\t" + "ldr r9, [%[a], #336]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #336]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+85] += m[85] * mu\n\t" + "ldr r7, [%[m], #340]\n\t" + "ldr r9, [%[a], #340]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #340]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+86] += m[86] * mu\n\t" + "ldr r7, [%[m], #344]\n\t" + "ldr r9, [%[a], #344]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #344]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+87] += m[87] * mu\n\t" + "ldr r7, [%[m], #348]\n\t" + "ldr r9, [%[a], #348]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #348]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+88] += m[88] * mu\n\t" + "ldr r7, [%[m], #352]\n\t" + "ldr r9, [%[a], #352]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #352]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+89] += m[89] * mu\n\t" + "ldr r7, [%[m], #356]\n\t" + "ldr r9, [%[a], #356]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #356]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+90] += m[90] * mu\n\t" + "ldr r7, [%[m], #360]\n\t" + "ldr r9, [%[a], #360]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #360]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+91] += m[91] * mu\n\t" + "ldr r7, [%[m], #364]\n\t" + "ldr r9, [%[a], #364]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #364]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+92] += m[92] * mu\n\t" + "ldr r7, [%[m], #368]\n\t" + "ldr r9, [%[a], #368]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #368]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+93] += m[93] * mu\n\t" + "ldr r7, [%[m], #372]\n\t" + "ldr r9, [%[a], #372]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #372]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+94] += m[94] * mu\n\t" + "ldr r7, [%[m], #376]\n\t" + "ldr r9, [%[a], #376]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #376]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+95] += m[95] * mu\n\t" + "ldr r7, [%[m], #380]\n\t" + "ldr r9, [%[a], #380]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r7, r7, %[ca]\n\t" + "mov %[ca], #0\n\t" + "adc %[ca], %[ca], %[ca]\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #380]\n\t" + "ldr r9, [%[a], #384]\n\t" + "adcs r9, r9, r7\n\t" + "str r9, [%[a], #384]\n\t" + "adc %[ca], %[ca], #0\n\t" + "# i += 1\n\t" + "add %[a], %[a], #4\n\t" + "add r12, r12, #4\n\t" + "cmp r12, #384\n\t" + "blt 1b\n\t" + "str r10, [%[a], #0]\n\t" + "str r14, [%[a], #4]\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + sp_3072_cond_sub_96(a - 96, a, m, (sp_digit)0 - ca); +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_3072_mont_mul_96(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_3072_mul_96(r, a, b); + sp_3072_mont_reduce_96(r, m, mp); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_3072_mont_sqr_96(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_3072_sqr_96(r, a); + sp_3072_mont_reduce_96(r, m, mp); +} + +#ifndef WOLFSSL_RSA_PUBLIC_ONLY +/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) + * + * d1 The high order half of the number to divide. + * d0 The low order half of the number to divide. + * div The dividend. + * returns the result of the division. + * + * Note that this is an approximate div. It may give an answer 1 larger. + */ +static sp_digit div_3072_word_96(sp_digit d1, sp_digit d0, sp_digit div) +{ + sp_digit r = 0; + + __asm__ __volatile__ ( + "lsr r5, %[div], #1\n\t" + "add r5, r5, #1\n\t" + "mov r6, %[d0]\n\t" + "mov r7, %[d1]\n\t" + "# Do top 32\n\t" + "subs r8, r5, r7\n\t" + "sbc r8, r8, r8\n\t" + "add %[r], %[r], %[r]\n\t" + "sub %[r], %[r], r8\n\t" + "and r8, r8, r5\n\t" + "subs r7, r7, r8\n\t" + "# Next 30 bits\n\t" + "mov r4, #29\n\t" + "1:\n\t" + "movs r6, r6, lsl #1\n\t" + "adc r7, r7, r7\n\t" + "subs r8, r5, r7\n\t" + "sbc r8, r8, r8\n\t" + "add %[r], %[r], %[r]\n\t" + "sub %[r], %[r], r8\n\t" + "and r8, r8, r5\n\t" + "subs r7, r7, r8\n\t" + "subs r4, r4, #1\n\t" + "bpl 1b\n\t" + "add %[r], %[r], %[r]\n\t" + "add %[r], %[r], #1\n\t" + "umull r4, r5, %[r], %[div]\n\t" + "subs r4, %[d0], r4\n\t" + "sbc r5, %[d1], r5\n\t" + "add %[r], %[r], r5\n\t" + "umull r4, r5, %[r], %[div]\n\t" + "subs r4, %[d0], r4\n\t" + "sbc r5, %[d1], r5\n\t" + "add %[r], %[r], r5\n\t" + "subs r8, %[div], r4\n\t" + "sbc r8, r8, r8\n\t" + "sub %[r], %[r], r8\n\t" + : [r] "+r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "r4", "r5", "r6", "r7", "r8" + ); + return r; +} + +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_3072_mask_96(sp_digit* r, sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<96; i++) + r[i] = a[i] & m; +#else + int i; + + for (i = 0; i < 96; i += 8) { + r[i+0] = a[i+0] & m; + r[i+1] = a[i+1] & m; + r[i+2] = a[i+2] & m; + r[i+3] = a[i+3] & m; + r[i+4] = a[i+4] & m; + r[i+5] = a[i+5] & m; + r[i+6] = a[i+6] & m; + r[i+7] = a[i+7] & m; + } +#endif +} + +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +static int32_t sp_3072_cmp_96(sp_digit* a, sp_digit* b) +{ + sp_digit r = -1; + sp_digit one = 1; + + +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov r7, #0\n\t" + "mov r3, #-1\n\t" + "mov r6, #380\n\t" + "1:\n\t" + "ldr r4, [%[a], r6]\n\t" + "ldr r5, [%[b], r6]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "sub r6, r6, #4\n\t" + "bcc 1b\n\t" + "eor %[r], %[r], r3\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [one] "r" (one) + : "r3", "r4", "r5", "r6", "r7" + ); +#else + __asm__ __volatile__ ( + "mov r7, #0\n\t" + "mov r3, #-1\n\t" + "ldr r4, [%[a], #380]\n\t" + "ldr r5, [%[b], #380]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #376]\n\t" + "ldr r5, [%[b], #376]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #372]\n\t" + "ldr r5, [%[b], #372]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #368]\n\t" + "ldr r5, [%[b], #368]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #364]\n\t" + "ldr r5, [%[b], #364]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #360]\n\t" + "ldr r5, [%[b], #360]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #356]\n\t" + "ldr r5, [%[b], #356]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #352]\n\t" + "ldr r5, [%[b], #352]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #348]\n\t" + "ldr r5, [%[b], #348]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #344]\n\t" + "ldr r5, [%[b], #344]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #340]\n\t" + "ldr r5, [%[b], #340]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #336]\n\t" + "ldr r5, [%[b], #336]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #332]\n\t" + "ldr r5, [%[b], #332]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #328]\n\t" + "ldr r5, [%[b], #328]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #324]\n\t" + "ldr r5, [%[b], #324]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #320]\n\t" + "ldr r5, [%[b], #320]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #316]\n\t" + "ldr r5, [%[b], #316]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #312]\n\t" + "ldr r5, [%[b], #312]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #308]\n\t" + "ldr r5, [%[b], #308]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #304]\n\t" + "ldr r5, [%[b], #304]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #300]\n\t" + "ldr r5, [%[b], #300]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #296]\n\t" + "ldr r5, [%[b], #296]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #292]\n\t" + "ldr r5, [%[b], #292]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #288]\n\t" + "ldr r5, [%[b], #288]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #284]\n\t" + "ldr r5, [%[b], #284]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #280]\n\t" + "ldr r5, [%[b], #280]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #276]\n\t" + "ldr r5, [%[b], #276]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #272]\n\t" + "ldr r5, [%[b], #272]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #268]\n\t" + "ldr r5, [%[b], #268]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #264]\n\t" + "ldr r5, [%[b], #264]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #260]\n\t" + "ldr r5, [%[b], #260]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #256]\n\t" + "ldr r5, [%[b], #256]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #252]\n\t" + "ldr r5, [%[b], #252]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #248]\n\t" + "ldr r5, [%[b], #248]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #244]\n\t" + "ldr r5, [%[b], #244]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #240]\n\t" + "ldr r5, [%[b], #240]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #236]\n\t" + "ldr r5, [%[b], #236]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #232]\n\t" + "ldr r5, [%[b], #232]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #228]\n\t" + "ldr r5, [%[b], #228]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #224]\n\t" + "ldr r5, [%[b], #224]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #220]\n\t" + "ldr r5, [%[b], #220]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #216]\n\t" + "ldr r5, [%[b], #216]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #212]\n\t" + "ldr r5, [%[b], #212]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #208]\n\t" + "ldr r5, [%[b], #208]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #204]\n\t" + "ldr r5, [%[b], #204]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #200]\n\t" + "ldr r5, [%[b], #200]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #196]\n\t" + "ldr r5, [%[b], #196]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #192]\n\t" + "ldr r5, [%[b], #192]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #188]\n\t" + "ldr r5, [%[b], #188]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #184]\n\t" + "ldr r5, [%[b], #184]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #180]\n\t" + "ldr r5, [%[b], #180]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #176]\n\t" + "ldr r5, [%[b], #176]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #172]\n\t" + "ldr r5, [%[b], #172]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #168]\n\t" + "ldr r5, [%[b], #168]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #164]\n\t" + "ldr r5, [%[b], #164]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #160]\n\t" + "ldr r5, [%[b], #160]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #156]\n\t" + "ldr r5, [%[b], #156]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #152]\n\t" + "ldr r5, [%[b], #152]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #148]\n\t" + "ldr r5, [%[b], #148]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #144]\n\t" + "ldr r5, [%[b], #144]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #140]\n\t" + "ldr r5, [%[b], #140]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #136]\n\t" + "ldr r5, [%[b], #136]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #132]\n\t" + "ldr r5, [%[b], #132]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #128]\n\t" + "ldr r5, [%[b], #128]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #124]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[b], #120]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #116]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[b], #112]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #108]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[b], #104]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #100]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[b], #96]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #92]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[b], #88]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #84]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[b], #80]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #76]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[b], #72]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #68]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[b], #64]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #60]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[b], #56]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #52]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[b], #48]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "eor %[r], %[r], r3\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [one] "r" (one) + : "r3", "r4", "r5", "r6", "r7" + ); +#endif + + return r; +} + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_3072_div_96(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[192], t2[97]; + sp_digit div, r1; + int i; + + (void)m; + + div = d[95]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 96); + for (i=95; i>=0; i--) { + r1 = div_3072_word_96(t1[96 + i], t1[96 + i - 1], div); + + sp_3072_mul_d_96(t2, d, r1); + t1[96 + i] += sp_3072_sub_in_place_96(&t1[i], t2); + t1[96 + i] -= t2[96]; + sp_3072_mask_96(t2, d, t1[96 + i]); + t1[96 + i] += sp_3072_add_96(&t1[i], &t1[i], t2); + sp_3072_mask_96(t2, d, t1[96 + i]); + t1[96 + i] += sp_3072_add_96(&t1[i], &t1[i], t2); + } + + r1 = sp_3072_cmp_96(t1, d) >= 0; + sp_3072_cond_sub_96(r, t1, d, (sp_digit)0 - r1); + + return MP_OKAY; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_3072_mod_96(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_3072_div_96(a, m, NULL, r); +} + +#endif /* WOLFSSL_RSA_PUBLIC_ONLY */ +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_3072_div_96_cond(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[192], t2[97]; + sp_digit div, r1; + int i; + + (void)m; + + div = d[95]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 96); + for (i=95; i>=0; i--) { + r1 = div_3072_word_96(t1[96 + i], t1[96 + i - 1], div); + + sp_3072_mul_d_96(t2, d, r1); + t1[96 + i] += sp_3072_sub_in_place_96(&t1[i], t2); + t1[96 + i] -= t2[96]; + if (t1[96 + i] != 0) { + t1[96 + i] += sp_3072_add_96(&t1[i], &t1[i], d); + if (t1[96 + i] != 0) + t1[96 + i] += sp_3072_add_96(&t1[i], &t1[i], d); + } + } + + r1 = sp_3072_cmp_96(t1, d) >= 0; + sp_3072_cond_sub_96(r, t1, d, (sp_digit)0 - r1); + + return MP_OKAY; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_3072_mod_96_cond(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_3072_div_96_cond(a, m, NULL, r); +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \ + defined(WOLFSSL_HAVE_SP_DH) +#ifdef WOLFSSL_SP_SMALL +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_3072_mod_exp_96(sp_digit* r, sp_digit* a, sp_digit* e, + int bits, sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[16][192]; +#else + sp_digit* t[16]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 192, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<16; i++) + t[i] = td + i * 192; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_96(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 96); + if (reduceA) { + err = sp_3072_mod_96(t[1] + 96, a, m); + if (err == MP_OKAY) + err = sp_3072_mod_96(t[1], t[1], m); + } + else { + XMEMCPY(t[1] + 96, a, sizeof(sp_digit) * 96); + err = sp_3072_mod_96(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_3072_mont_sqr_96(t[ 2], t[ 1], m, mp); + sp_3072_mont_mul_96(t[ 3], t[ 2], t[ 1], m, mp); + sp_3072_mont_sqr_96(t[ 4], t[ 2], m, mp); + sp_3072_mont_mul_96(t[ 5], t[ 3], t[ 2], m, mp); + sp_3072_mont_sqr_96(t[ 6], t[ 3], m, mp); + sp_3072_mont_mul_96(t[ 7], t[ 4], t[ 3], m, mp); + sp_3072_mont_sqr_96(t[ 8], t[ 4], m, mp); + sp_3072_mont_mul_96(t[ 9], t[ 5], t[ 4], m, mp); + sp_3072_mont_sqr_96(t[10], t[ 5], m, mp); + sp_3072_mont_mul_96(t[11], t[ 6], t[ 5], m, mp); + sp_3072_mont_sqr_96(t[12], t[ 6], m, mp); + sp_3072_mont_mul_96(t[13], t[ 7], t[ 6], m, mp); + sp_3072_mont_sqr_96(t[14], t[ 7], m, mp); + sp_3072_mont_mul_96(t[15], t[ 8], t[ 7], m, mp); + + i = (bits - 1) / 32; + n = e[i--]; + y = n >> 28; + n <<= 4; + c = 28; + XMEMCPY(r, t[y], sizeof(sp_digit) * 96); + for (; i>=0 || c>=4; ) { + if (c == 0) { + n = e[i--]; + y = n >> 28; + n <<= 4; + c = 28; + } + else if (c < 4) { + y = n >> 28; + n = e[i--]; + c = 4 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 28) & 0xf; + n <<= 4; + c -= 4; + } + + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + + sp_3072_mont_mul_96(r, r, t[y], m, mp); + } + y = e[0] & ((1 << c) - 1); + for (; c > 0; c--) + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_mul_96(r, r, t[y], m, mp); + + XMEMSET(&r[96], 0, sizeof(sp_digit) * 96); + sp_3072_mont_reduce_96(r, m, mp); + + mask = 0 - (sp_3072_cmp_96(r, m) >= 0); + sp_3072_cond_sub_96(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#else +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_3072_mod_exp_96(sp_digit* r, sp_digit* a, sp_digit* e, + int bits, sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][192]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 192, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<32; i++) + t[i] = td + i * 192; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_96(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 96); + if (reduceA) { + err = sp_3072_mod_96(t[1] + 96, a, m); + if (err == MP_OKAY) + err = sp_3072_mod_96(t[1], t[1], m); + } + else { + XMEMCPY(t[1] + 96, a, sizeof(sp_digit) * 96); + err = sp_3072_mod_96(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_3072_mont_sqr_96(t[ 2], t[ 1], m, mp); + sp_3072_mont_mul_96(t[ 3], t[ 2], t[ 1], m, mp); + sp_3072_mont_sqr_96(t[ 4], t[ 2], m, mp); + sp_3072_mont_mul_96(t[ 5], t[ 3], t[ 2], m, mp); + sp_3072_mont_sqr_96(t[ 6], t[ 3], m, mp); + sp_3072_mont_mul_96(t[ 7], t[ 4], t[ 3], m, mp); + sp_3072_mont_sqr_96(t[ 8], t[ 4], m, mp); + sp_3072_mont_mul_96(t[ 9], t[ 5], t[ 4], m, mp); + sp_3072_mont_sqr_96(t[10], t[ 5], m, mp); + sp_3072_mont_mul_96(t[11], t[ 6], t[ 5], m, mp); + sp_3072_mont_sqr_96(t[12], t[ 6], m, mp); + sp_3072_mont_mul_96(t[13], t[ 7], t[ 6], m, mp); + sp_3072_mont_sqr_96(t[14], t[ 7], m, mp); + sp_3072_mont_mul_96(t[15], t[ 8], t[ 7], m, mp); + sp_3072_mont_sqr_96(t[16], t[ 8], m, mp); + sp_3072_mont_mul_96(t[17], t[ 9], t[ 8], m, mp); + sp_3072_mont_sqr_96(t[18], t[ 9], m, mp); + sp_3072_mont_mul_96(t[19], t[10], t[ 9], m, mp); + sp_3072_mont_sqr_96(t[20], t[10], m, mp); + sp_3072_mont_mul_96(t[21], t[11], t[10], m, mp); + sp_3072_mont_sqr_96(t[22], t[11], m, mp); + sp_3072_mont_mul_96(t[23], t[12], t[11], m, mp); + sp_3072_mont_sqr_96(t[24], t[12], m, mp); + sp_3072_mont_mul_96(t[25], t[13], t[12], m, mp); + sp_3072_mont_sqr_96(t[26], t[13], m, mp); + sp_3072_mont_mul_96(t[27], t[14], t[13], m, mp); + sp_3072_mont_sqr_96(t[28], t[14], m, mp); + sp_3072_mont_mul_96(t[29], t[15], t[14], m, mp); + sp_3072_mont_sqr_96(t[30], t[15], m, mp); + sp_3072_mont_mul_96(t[31], t[16], t[15], m, mp); + + i = (bits - 1) / 32; + n = e[i--]; + y = n >> 27; + n <<= 5; + c = 27; + XMEMCPY(r, t[y], sizeof(sp_digit) * 96); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 27; + n <<= 5; + c = 27; + } + else if (c < 5) { + y = n >> 27; + n = e[i--]; + c = 5 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 27) & 0x1f; + n <<= 5; + c -= 5; + } + + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + + sp_3072_mont_mul_96(r, r, t[y], m, mp); + } + y = e[0] & ((1 << c) - 1); + for (; c > 0; c--) + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_mul_96(r, r, t[y], m, mp); + + XMEMSET(&r[96], 0, sizeof(sp_digit) * 96); + sp_3072_mont_reduce_96(r, m, mp); + + mask = 0 - (sp_3072_cmp_96(r, m) >= 0); + sp_3072_cond_sub_96(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#endif /* WOLFSSL_SP_SMALL */ +#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ + +#ifdef WOLFSSL_HAVE_SP_RSA +/* RSA public key operation. + * + * in Array of bytes representing the number to exponentiate, base. + * inLen Number of bytes in base. + * em Public exponent. + * mm Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 384 bytes long. + * outLen Number of bytes in result. + * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when + * an array is too long and MEMORY_E when dynamic memory allocation fails. + */ +int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm, + byte* out, word32* outLen) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit ad[192], md[96], rd[192]; +#else + sp_digit* d = NULL; +#endif + sp_digit* a; + sp_digit *ah; + sp_digit* m; + sp_digit* r; + sp_digit e[1]; + int err = MP_OKAY; + + if (*outLen < 384) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(em) > 32 || inLen > 384 || + mp_count_bits(mm) != 3072)) + err = MP_READ_E; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 96 * 5, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + a = d; + r = a + 96 * 2; + m = r + 96 * 2; + ah = a + 96; + } +#else + a = ad; + m = md; + r = rd; + ah = a + 96; +#endif + + if (err == MP_OKAY) { + sp_3072_from_bin(ah, 96, in, inLen); +#if DIGIT_BIT >= 32 + e[0] = em->dp[0]; +#else + e[0] = em->dp[0]; + if (em->used > 1) + e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT; +#endif + if (e[0] == 0) + err = MP_EXPTMOD_E; + } + if (err == MP_OKAY) { + sp_3072_from_mp(m, 96, mm); + + if (e[0] == 0x3) { + if (err == MP_OKAY) { + sp_3072_sqr_96(r, ah); + err = sp_3072_mod_96_cond(r, r, m); + } + if (err == MP_OKAY) { + sp_3072_mul_96(r, ah, r); + err = sp_3072_mod_96_cond(r, r, m); + } + } + else { + int i; + sp_digit mp; + + sp_3072_mont_setup(m, &mp); + + /* Convert to Montgomery form. */ + XMEMSET(a, 0, sizeof(sp_digit) * 96); + err = sp_3072_mod_96_cond(a, a, m); + + if (err == MP_OKAY) { + for (i=31; i>=0; i--) + if (e[0] >> i) + break; + + XMEMCPY(r, a, sizeof(sp_digit) * 96); + for (i--; i>=0; i--) { + sp_3072_mont_sqr_96(r, r, m, mp); + if (((e[0] >> i) & 1) == 1) + sp_3072_mont_mul_96(r, r, a, m, mp); + } + XMEMSET(&r[96], 0, sizeof(sp_digit) * 96); + sp_3072_mont_reduce_96(r, m, mp); + + for (i = 95; i > 0; i--) { + if (r[i] != m[i]) + break; + } + if (r[i] >= m[i]) + sp_3072_sub_in_place_96(r, m); + } + } + } + + if (err == MP_OKAY) { + sp_3072_to_bin(r, out); + *outLen = 384; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_RSA); +#endif + + return err; +} + +#ifndef WOLFSSL_RSA_PUBLIC_ONLY +/* RSA private key operation. + * + * in Array of bytes representing the number to exponentiate, base. + * inLen Number of bytes in base. + * dm Private exponent. + * pm First prime. + * qm Second prime. + * dpm First prime's CRT exponent. + * dqm Second prime's CRT exponent. + * qim Inverse of second prime mod p. + * mm Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 384 bytes long. + * outLen Number of bytes in result. + * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when + * an array is too long and MEMORY_E when dynamic memory allocation fails. + */ +int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, + mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm, + byte* out, word32* outLen) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit ad[96 * 2]; + sp_digit pd[48], qd[48], dpd[48]; + sp_digit tmpad[96], tmpbd[96]; +#else + sp_digit* t = NULL; +#endif + sp_digit* a; + sp_digit* p; + sp_digit* q; + sp_digit* dp; + sp_digit* dq; + sp_digit* qi; + sp_digit* tmp; + sp_digit* tmpa; + sp_digit* tmpb; + sp_digit* r; + sp_digit c; + int err = MP_OKAY; + + (void)dm; + (void)mm; + + if (*outLen < 384) + err = MP_TO_E; + if (err == MP_OKAY && (inLen > 384 || mp_count_bits(mm) != 3072)) + err = MP_READ_E; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 48 * 11, NULL, + DYNAMIC_TYPE_RSA); + if (t == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + a = t; + p = a + 96 * 2; + q = p + 48; + qi = dq = dp = q + 48; + tmpa = qi + 48; + tmpb = tmpa + 96; + + tmp = t; + r = tmp + 96; + } +#else + r = a = ad; + p = pd; + q = qd; + qi = dq = dp = dpd; + tmpa = tmpad; + tmpb = tmpbd; + tmp = a + 96; +#endif + + if (err == MP_OKAY) { + sp_3072_from_bin(a, 96, in, inLen); + sp_3072_from_mp(p, 48, pm); + sp_3072_from_mp(q, 48, qm); + sp_3072_from_mp(dp, 48, dpm); + + err = sp_3072_mod_exp_48(tmpa, a, dp, 1536, p, 1); + } + if (err == MP_OKAY) { + sp_3072_from_mp(dq, 48, dqm); + err = sp_3072_mod_exp_48(tmpb, a, dq, 1536, q, 1); + } + + if (err == MP_OKAY) { + c = sp_3072_sub_in_place_48(tmpa, tmpb); + sp_3072_mask_48(tmp, p, c); + sp_3072_add_48(tmpa, tmpa, tmp); + + sp_3072_from_mp(qi, 48, qim); + sp_3072_mul_48(tmpa, tmpa, qi); + err = sp_3072_mod_48(tmpa, tmpa, p); + } + + if (err == MP_OKAY) { + sp_3072_mul_48(tmpa, q, tmpa); + XMEMSET(&tmpb[48], 0, sizeof(sp_digit) * 48); + sp_3072_add_96(r, tmpb, tmpa); + + sp_3072_to_bin(r, out); + *outLen = 384; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_digit) * 48 * 11); + XFREE(t, NULL, DYNAMIC_TYPE_RSA); + } +#else + XMEMSET(tmpad, 0, sizeof(tmpad)); + XMEMSET(tmpbd, 0, sizeof(tmpbd)); + XMEMSET(pd, 0, sizeof(pd)); + XMEMSET(qd, 0, sizeof(qd)); + XMEMSET(dpd, 0, sizeof(dpd)); +#endif + + return err; +} +#endif +#endif /* WOLFSSL_HAVE_SP_RSA */ +#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \ + !defined(WOLFSSL_RSA_PUBLIC_ONLY)) +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_3072_to_mp(sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (3072 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { +#if DIGIT_BIT == 32 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 96); + r->used = 96; + mp_clamp(r); +#elif DIGIT_BIT < 32 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 96; i++) { + r->dp[j] |= a[i] << s; + r->dp[j] &= (1l << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + while (s + DIGIT_BIT <= 32) { + s += DIGIT_BIT; + r->dp[j] &= (1l << DIGIT_BIT) - 1; + r->dp[++j] = a[i] >> s; + } + s = 32 - s; + } + r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 96; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 32 >= DIGIT_BIT) { + #if DIGIT_BIT < 32 + r->dp[j] &= (1l << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 32 - s; + } + else + s += 32; + } + r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returs 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ + int err = MP_OKAY; + sp_digit b[192], e[96], m[96]; + sp_digit* r = b; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 3072 || expBits > 3072 || + mp_count_bits(mod) != 3072) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + sp_3072_from_mp(b, 96, base); + sp_3072_from_mp(e, 96, exp); + sp_3072_from_mp(m, 96, mod); + + err = sp_3072_mod_exp_96(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + err = sp_3072_to_mp(r, res); + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} + +#ifdef WOLFSSL_HAVE_SP_DH +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. + * exp Array of bytes that is the exponent. + * expLen Length of data, in bytes, in exponent. + * mod Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 384 bytes long. + * outLen Length, in bytes, of exponentiation result. + * returs 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen, + mp_int* mod, byte* out, word32* outLen) +{ + int err = MP_OKAY; + sp_digit b[192], e[96], m[96]; + sp_digit* r = b; + word32 i; + + if (mp_count_bits(base) > 3072 || expLen > 384 || + mp_count_bits(mod) != 3072) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + sp_3072_from_mp(b, 96, base); + sp_3072_from_bin(e, 96, exp, expLen); + sp_3072_from_mp(m, 96, mod); + + err = sp_3072_mod_exp_96(r, b, e, expLen * 8, m, 0); + } + + if (err == MP_OKAY) { + sp_3072_to_bin(r, out); + *outLen = 384; + for (i=0; i<384 && out[i] == 0; i++) { + } + *outLen -= i; + XMEMMOVE(out, out + i, *outLen); + + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} +#endif /* WOLFSSL_HAVE_SP_DH */ + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returs 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ + int err = MP_OKAY; + sp_digit b[96], e[48], m[48]; + sp_digit* r = b; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 1536 || expBits > 1536 || + mp_count_bits(mod) != 1536) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + sp_3072_from_mp(b, 48, base); + sp_3072_from_mp(e, 48, exp); + sp_3072_from_mp(m, 48, mod); + + err = sp_3072_mod_exp_48(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + XMEMSET(r + 48, 0, sizeof(*r) * 48); + err = sp_3072_to_mp(r, res); + res->used = mod->used; + mp_clamp(res); + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} + +#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ + +#endif /* !WOLFSSL_SP_NO_3072 */ + +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +#ifdef WOLFSSL_HAVE_SP_ECC +#ifndef WOLFSSL_SP_NO_256 + +/* Point structure to use. */ +typedef struct sp_point { + sp_digit x[2 * 8]; + sp_digit y[2 * 8]; + sp_digit z[2 * 8]; + int infinity; +} sp_point; + +/* The modulus (prime) of the curve P256. */ +static sp_digit p256_mod[8] = { + 0xffffffff,0xffffffff,0xffffffff,0x00000000,0x00000000,0x00000000, + 0x00000001,0xffffffff +}; +/* The Montogmery normalizer for modulus of the curve P256. */ +static sp_digit p256_norm_mod[8] = { + 0x00000001,0x00000000,0x00000000,0xffffffff,0xffffffff,0xffffffff, + 0xfffffffe,0x00000000 +}; +/* The Montogmery multiplier for modulus of the curve P256. */ +static sp_digit p256_mp_mod = 0x00000001; +#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ + defined(HAVE_ECC_VERIFY) +/* The order of the curve P256. */ +static sp_digit p256_order[8] = { + 0xfc632551,0xf3b9cac2,0xa7179e84,0xbce6faad,0xffffffff,0xffffffff, + 0x00000000,0xffffffff +}; +#endif +/* The order of the curve P256 minus 2. */ +static sp_digit p256_order2[8] = { + 0xfc63254f,0xf3b9cac2,0xa7179e84,0xbce6faad,0xffffffff,0xffffffff, + 0x00000000,0xffffffff +}; +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +/* The Montogmery normalizer for order of the curve P256. */ +static sp_digit p256_norm_order[8] = { + 0x039cdaaf,0x0c46353d,0x58e8617b,0x43190552,0x00000000,0x00000000, + 0xffffffff,0x00000000 +}; +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +/* The Montogmery multiplier for order of the curve P256. */ +static sp_digit p256_mp_order = 0xee00bc4f; +#endif +/* The base point of curve P256. */ +static sp_point p256_base = { + /* X ordinate */ + { + 0xd898c296,0xf4a13945,0x2deb33a0,0x77037d81,0x63a440f2,0xf8bce6e5, + 0xe12c4247,0x6b17d1f2 + }, + /* Y ordinate */ + { + 0x37bf51f5,0xcbb64068,0x6b315ece,0x2bce3357,0x7c0f9e16,0x8ee7eb4a, + 0xfe1a7f9b,0x4fe342e2 + }, + /* Z ordinate */ + { + 0x00000001,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000 + }, + /* infinity */ + 0 +}; +#if defined(HAVE_ECC_CHECK_KEY) || defined(HAVE_COMP_KEY) +static sp_digit p256_b[8] = { + 0x27d2604b,0x3bce3c3e,0xcc53b0f6,0x651d06b0,0x769886bc,0xb3ebbd55, + 0xaa3a93e7,0x5ac635d8 +}; +#endif + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) +/* Allocate memory for point and return error. */ +#define sp_ecc_point_new(heap, sp, p) \ + ((p = (sp_point*)XMALLOC(sizeof(sp_point), heap, DYNAMIC_TYPE_ECC)) \ + == NULL) ? MEMORY_E : MP_OKAY +#else +/* Set pointer to data and return no error. */ +#define sp_ecc_point_new(heap, sp, p) ((p = &sp) == NULL) ? MEMORY_E : MP_OKAY +#endif + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) +/* If valid pointer then clear point data if requested and free data. */ +#define sp_ecc_point_free(p, clear, heap) \ + do { \ + if (p != NULL) { \ + if (clear) \ + XMEMSET(p, 0, sizeof(*p)); \ + XFREE(p, heap, DYNAMIC_TYPE_ECC); \ + } \ + } \ + while (0) +#else +/* Clear point data if requested. */ +#define sp_ecc_point_free(p, clear, heap) \ + do { \ + if (clear) \ + XMEMSET(p, 0, sizeof(*p)); \ + } \ + while (0) +#endif + +/* Multiply a number by Montogmery normalizer mod modulus (prime). + * + * r The resulting Montgomery form number. + * a The number to convert. + * m The modulus (prime). + */ +static int sp_256_mod_mul_norm_8(sp_digit* r, sp_digit* a, sp_digit* m) +{ + (void)m; + + __asm__ __volatile__ ( + "sub sp, sp, #24\n\t" + "ldr r2, [%[a], #0]\n\t" + "ldr r3, [%[a], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[a], #12]\n\t" + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[a], #20]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[a], #28]\n\t" + "# Clear overflow and underflow\n\t" + "mov r14, #0\n\t" + "mov r12, #0\n\t" + "# t[0] = 1 1 0 -1 -1 -1 -1 0\n\t" + "adds r10, r2, r3\n\t" + "adc r14, r14, #0\n\t" + "subs r10, r10, r5\n\t" + "sbc r12, r12, #0\n\t" + "subs r10, r10, r6\n\t" + "sbc r12, r12, #0\n\t" + "subs r10, r10, r7\n\t" + "sbc r12, r12, #0\n\t" + "subs r10, r10, r8\n\t" + "sbc r12, r12, #0\n\t" + "# Store t[0]\n\t" + "str r10, [sp, #0]\n\t" + "neg r12, r12\n\t" + "mov r10, #0\n\t" + "# t[1] = 0 1 1 0 -1 -1 -1 -1\n\t" + "adds r14, r14, r3\n\t" + "adc r10, r10, #0\n\t" + "adds r14, r14, r4\n\t" + "adc r10, r10, #0\n\t" + "subs r14, r14, r12\n\t" + "mov r12, #0\n\t" + "sbc r12, r12, #0\n\t" + "subs r14, r14, r6\n\t" + "sbc r12, r12, #0\n\t" + "subs r14, r14, r7\n\t" + "sbc r12, r12, #0\n\t" + "subs r14, r14, r8\n\t" + "sbc r12, r12, #0\n\t" + "subs r14, r14, r9\n\t" + "sbc r12, r12, #0\n\t" + "# Store t[1]\n\t" + "str r14, [sp, #4]\n\t" + "neg r12, r12\n\t" + "mov r14, #0\n\t" + "# t[2] = 0 0 1 1 0 -1 -1 -1\n\t" + "adds r10, r10, r4\n\t" + "adc r14, r14, #0\n\t" + "adds r10, r10, r5\n\t" + "adc r14, r14, #0\n\t" + "subs r10, r10, r12\n\t" + "mov r12, #0\n\t" + "sbc r12, r12, #0\n\t" + "subs r10, r10, r7\n\t" + "sbc r12, r12, #0\n\t" + "subs r10, r10, r8\n\t" + "sbc r12, r12, #0\n\t" + "subs r10, r10, r9\n\t" + "sbc r12, r12, #0\n\t" + "# Store t[2]\n\t" + "str r10, [sp, #8]\n\t" + "neg r12, r12\n\t" + "mov r10, #0\n\t" + "# t[3] = -1 -1 0 2 2 1 0 -1\n\t" + "adds r14, r14, r5\n\t" + "adc r10, r10, #0\n\t" + "adds r14, r14, r5\n\t" + "adc r10, r10, #0\n\t" + "adds r14, r14, r6\n\t" + "adc r10, r10, #0\n\t" + "adds r14, r14, r6\n\t" + "adc r10, r10, #0\n\t" + "adds r14, r14, r7\n\t" + "adc r10, r10, #0\n\t" + "subs r14, r14, r12\n\t" + "mov r12, #0\n\t" + "sbc r12, r12, #0\n\t" + "subs r14, r14, r2\n\t" + "sbc r12, r12, #0\n\t" + "subs r14, r14, r3\n\t" + "sbc r12, r12, #0\n\t" + "subs r14, r14, r9\n\t" + "sbc r12, r12, #0\n\t" + "# Store t[3]\n\t" + "str r14, [sp, #12]\n\t" + "neg r12, r12\n\t" + "mov r14, #0\n\t" + "# t[4] = 0 -1 -1 0 2 2 1 0\n\t" + "adds r10, r10, r6\n\t" + "adc r14, r14, #0\n\t" + "adds r10, r10, r6\n\t" + "adc r14, r14, #0\n\t" + "adds r10, r10, r7\n\t" + "adc r14, r14, #0\n\t" + "adds r10, r10, r7\n\t" + "adc r14, r14, #0\n\t" + "adds r10, r10, r8\n\t" + "adc r14, r14, #0\n\t" + "subs r10, r10, r12\n\t" + "mov r12, #0\n\t" + "sbc r12, r12, #0\n\t" + "subs r10, r10, r3\n\t" + "sbc r12, r12, #0\n\t" + "subs r10, r10, r4\n\t" + "sbc r12, r12, #0\n\t" + "# Store t[4]\n\t" + "str r10, [sp, #16]\n\t" + "neg r12, r12\n\t" + "mov r10, #0\n\t" + "# t[5] = 0 0 -1 -1 0 2 2 1\n\t" + "adds r14, r14, r7\n\t" + "adc r10, r10, #0\n\t" + "adds r14, r14, r7\n\t" + "adc r10, r10, #0\n\t" + "adds r14, r14, r8\n\t" + "adc r10, r10, #0\n\t" + "adds r14, r14, r8\n\t" + "adc r10, r10, #0\n\t" + "adds r14, r14, r9\n\t" + "adc r10, r10, #0\n\t" + "subs r14, r14, r12\n\t" + "mov r12, #0\n\t" + "sbc r12, r12, #0\n\t" + "subs r14, r14, r4\n\t" + "sbc r12, r12, #0\n\t" + "subs r14, r14, r5\n\t" + "sbc r12, r12, #0\n\t" + "# Store t[5]\n\t" + "str r14, [sp, #20]\n\t" + "neg r12, r12\n\t" + "mov r14, #0\n\t" + "# t[6] = -1 -1 0 0 0 1 3 2\n\t" + "adds r10, r10, r7\n\t" + "adc r14, r14, #0\n\t" + "adds r10, r10, r8\n\t" + "adc r14, r14, #0\n\t" + "adds r10, r10, r8\n\t" + "adc r14, r14, #0\n\t" + "adds r10, r10, r8\n\t" + "adc r14, r14, #0\n\t" + "adds r10, r10, r9\n\t" + "adc r14, r14, #0\n\t" + "adds r10, r10, r9\n\t" + "adc r14, r14, #0\n\t" + "subs r10, r10, r12\n\t" + "mov r12, #0\n\t" + "sbc r12, r12, #0\n\t" + "subs r10, r10, r2\n\t" + "sbc r12, r12, #0\n\t" + "subs r10, r10, r3\n\t" + "sbc r12, r12, #0\n\t" + "# Store t[6]\n\t" + "mov r8, r10\n\t" + "neg r12, r12\n\t" + "mov r10, #0\n\t" + "# t[7] = 1 0 -1 -1 -1 -1 0 3\n\t" + "adds r14, r14, r2\n\t" + "adc r10, r10, #0\n\t" + "adds r14, r14, r9\n\t" + "adc r10, r10, #0\n\t" + "adds r14, r14, r9\n\t" + "adc r10, r10, #0\n\t" + "adds r14, r14, r9\n\t" + "adc r10, r10, #0\n\t" + "subs r14, r14, r12\n\t" + "mov r12, #0\n\t" + "sbc r12, r12, #0\n\t" + "subs r14, r14, r4\n\t" + "sbc r12, r12, #0\n\t" + "subs r14, r14, r5\n\t" + "sbc r12, r12, #0\n\t" + "subs r14, r14, r6\n\t" + "sbc r12, r12, #0\n\t" + "subs r14, r14, r7\n\t" + "sbc r12, r12, #0\n\t" + "# Store t[7]\n\t" + "# Load intermediate\n\t" + "ldr r2, [sp, #0]\n\t" + "ldr r3, [sp, #4]\n\t" + "ldr r4, [sp, #8]\n\t" + "ldr r5, [sp, #12]\n\t" + "ldr r6, [sp, #16]\n\t" + "ldr r7, [sp, #20]\n\t" + "neg r12, r12\n\t" + "# Add overflow\n\t" + "# Subtract underflow - add neg underflow\n\t" + "adds r2, r2, r10\n\t" + "adcs r3, r3, #0\n\t" + "adcs r4, r4, #0\n\t" + "adds r5, r5, r12\n\t" + "adcs r6, r6, #0\n\t" + "adcs r7, r7, #0\n\t" + "adcs r8, r8, r12\n\t" + "adc r14, r14, r10\n\t" + "# Subtract overflow\n\t" + "# Add underflow - subtract neg underflow\n\t" + "subs r2, r2, r12\n\t" + "sbcs r3, r3, #0\n\t" + "sbcs r4, r4, #0\n\t" + "subs r5, r5, r10\n\t" + "sbcs r6, r6, #0\n\t" + "sbcs r7, r7, #0\n\t" + "sbcs r8, r8, r10\n\t" + "sbc r14, r14, r12\n\t" + "# Store result\n\t" + "str r2, [%[r], #0]\n\t" + "str r3, [%[r], #4]\n\t" + "str r4, [%[r], #8]\n\t" + "str r5, [%[r], #12]\n\t" + "str r6, [%[r], #16]\n\t" + "str r7, [%[r], #20]\n\t" + "str r8, [%[r], #24]\n\t" + "str r14, [%[r], #28]\n\t" + "add sp, sp, #24\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + return MP_OKAY; +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * a A multi-precision integer. + */ +static void sp_256_from_mp(sp_digit* r, int max, mp_int* a) +{ +#if DIGIT_BIT == 32 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < max; j++) + r[j] = 0; +#elif DIGIT_BIT > 32 + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= a->dp[i] << s; + r[j] &= 0xffffffff; + s = 32 - s; + if (j + 1 >= max) + break; + r[++j] = a->dp[i] >> s; + while (s + 32 <= DIGIT_BIT) { + s += 32; + r[j] &= 0xffffffff; + if (j + 1 >= max) + break; + if (s < DIGIT_BIT) + r[++j] = a->dp[i] >> s; + else + r[++j] = 0; + } + s = DIGIT_BIT - s; + } + + for (j++; j < max; j++) + r[j] = 0; +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 32) { + r[j] &= 0xffffffff; + if (j + 1 >= max) + break; + s = 32 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else + s += DIGIT_BIT; + } + + for (j++; j < max; j++) + r[j] = 0; +#endif +} + +/* Convert a point of type ecc_point to type sp_point. + * + * p Point of type sp_point (result). + * pm Point of type ecc_point. + */ +static void sp_256_point_from_ecc_point_8(sp_point* p, ecc_point* pm) +{ + XMEMSET(p->x, 0, sizeof(p->x)); + XMEMSET(p->y, 0, sizeof(p->y)); + XMEMSET(p->z, 0, sizeof(p->z)); + sp_256_from_mp(p->x, 8, pm->x); + sp_256_from_mp(p->y, 8, pm->y); + sp_256_from_mp(p->z, 8, pm->z); + p->infinity = 0; +} + +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_256_to_mp(sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (256 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { +#if DIGIT_BIT == 32 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 8); + r->used = 8; + mp_clamp(r); +#elif DIGIT_BIT < 32 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 8; i++) { + r->dp[j] |= a[i] << s; + r->dp[j] &= (1l << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + while (s + DIGIT_BIT <= 32) { + s += DIGIT_BIT; + r->dp[j] &= (1l << DIGIT_BIT) - 1; + r->dp[++j] = a[i] >> s; + } + s = 32 - s; + } + r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 8; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 32 >= DIGIT_BIT) { + #if DIGIT_BIT < 32 + r->dp[j] &= (1l << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 32 - s; + } + else + s += 32; + } + r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Convert a point of type sp_point to type ecc_point. + * + * p Point of type sp_point. + * pm Point of type ecc_point (result). + * returns MEMORY_E when allocation of memory in ecc_point fails otherwise + * MP_OKAY. + */ +static int sp_256_point_to_ecc_point_8(sp_point* p, ecc_point* pm) +{ + int err; + + err = sp_256_to_mp(p->x, pm->x); + if (err == MP_OKAY) + err = sp_256_to_mp(p->y, pm->y); + if (err == MP_OKAY) + err = sp_256_to_mp(p->z, pm->z); + + return err; +} + +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +static int32_t sp_256_cmp_8(sp_digit* a, sp_digit* b) +{ + sp_digit r = -1; + sp_digit one = 1; + + +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov r7, #0\n\t" + "mov r3, #-1\n\t" + "mov r6, #28\n\t" + "1:\n\t" + "ldr r4, [%[a], r6]\n\t" + "ldr r5, [%[b], r6]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "sub r6, r6, #4\n\t" + "bcc 1b\n\t" + "eor %[r], %[r], r3\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [one] "r" (one) + : "r3", "r4", "r5", "r6", "r7" + ); +#else + __asm__ __volatile__ ( + "mov r7, #0\n\t" + "mov r3, #-1\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "and r4, r4, r3\n\t" + "and r5, r5, r3\n\t" + "subs r4, r4, r5\n\t" + "movhi %[r], %[one]\n\t" + "movlo %[r], r3\n\t" + "movne r3, r7\n\t" + "eor %[r], %[r], r3\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [one] "r" (one) + : "r3", "r4", "r5", "r6", "r7" + ); +#endif + + return r; +} + +/* Normalize the values in each word to 32. + * + * a Array of sp_digit to normalize. + */ +#define sp_256_norm_8(a) + +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not copying. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +static sp_digit sp_256_cond_sub_8(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit m) +{ + sp_digit c = 0; + +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov r9, #0\n\t" + "mov r8, #0\n\t" + "1:\n\t" + "subs %[c], r9, %[c]\n\t" + "ldr r4, [%[a], r8]\n\t" + "ldr r5, [%[b], r8]\n\t" + "and r5, r5, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbc %[c], r9, r9\n\t" + "str r4, [%[r], r8]\n\t" + "add r8, r8, #4\n\t" + "cmp r8, #32\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r4", "r6", "r5", "r7", "r8", "r9" + ); +#else + __asm__ __volatile__ ( + + "mov r9, #0\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r6, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r7, [%[b], #4]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "subs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #0]\n\t" + "str r6, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r7, [%[b], #12]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #8]\n\t" + "str r6, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r6, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r7, [%[b], #20]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #16]\n\t" + "str r6, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r6, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r7, [%[b], #28]\n\t" + "and r5, r5, %[m]\n\t" + "and r7, r7, %[m]\n\t" + "sbcs r4, r4, r5\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r], #24]\n\t" + "str r6, [%[r], #28]\n\t" + "sbc %[c], r9, r9\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r4", "r6", "r5", "r7", "r8", "r9" + ); +#endif /* WOLFSSL_SP_SMALL */ + + return c; +} + +#define sp_256_mont_reduce_order_8 sp_256_mont_reduce_8 + +/* Reduce the number back to 256 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +SP_NOINLINE static void sp_256_mont_reduce_8(sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "# i = 0\n\t" + "mov r12, #0\n\t" + "ldr r10, [%[a], #0]\n\t" + "ldr r14, [%[a], #4]\n\t" + "\n1:\n\t" + "# mu = a[i] * mp\n\t" + "mul r8, %[mp], r10\n\t" + "# a[i+0] += m[0] * mu\n\t" + "ldr r7, [%[m], #0]\n\t" + "ldr r9, [%[a], #0]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r10, r10, r6\n\t" + "adc r5, r7, #0\n\t" + "# a[i+1] += m[1] * mu\n\t" + "ldr r7, [%[m], #4]\n\t" + "ldr r9, [%[a], #4]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r10, r14, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r10, r10, r5\n\t" + "adc r4, r4, #0\n\t" + "# a[i+2] += m[2] * mu\n\t" + "ldr r7, [%[m], #8]\n\t" + "ldr r14, [%[a], #8]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r14, r14, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r14, r14, r4\n\t" + "adc r5, r5, #0\n\t" + "# a[i+3] += m[3] * mu\n\t" + "ldr r7, [%[m], #12]\n\t" + "ldr r9, [%[a], #12]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #12]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+4] += m[4] * mu\n\t" + "ldr r7, [%[m], #16]\n\t" + "ldr r9, [%[a], #16]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #16]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+5] += m[5] * mu\n\t" + "ldr r7, [%[m], #20]\n\t" + "ldr r9, [%[a], #20]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r4, r7, #0\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #20]\n\t" + "adc r4, r4, #0\n\t" + "# a[i+6] += m[6] * mu\n\t" + "ldr r7, [%[m], #24]\n\t" + "ldr r9, [%[a], #24]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r9, r9, r6\n\t" + "adc r5, r7, #0\n\t" + "adds r9, r9, r4\n\t" + "str r9, [%[a], #24]\n\t" + "adc r5, r5, #0\n\t" + "# a[i+7] += m[7] * mu\n\t" + "ldr r7, [%[m], #28]\n\t" + "ldr r9, [%[a], #28]\n\t" + "umull r6, r7, r8, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r7, r7, %[ca]\n\t" + "mov %[ca], #0\n\t" + "adc %[ca], %[ca], %[ca]\n\t" + "adds r9, r9, r5\n\t" + "str r9, [%[a], #28]\n\t" + "ldr r9, [%[a], #32]\n\t" + "adcs r9, r9, r7\n\t" + "str r9, [%[a], #32]\n\t" + "adc %[ca], %[ca], #0\n\t" + "# i += 1\n\t" + "add %[a], %[a], #4\n\t" + "add r12, r12, #4\n\t" + "cmp r12, #32\n\t" + "blt 1b\n\t" + "str r10, [%[a], #0]\n\t" + "str r14, [%[a], #4]\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + sp_256_cond_sub_8(a - 8, a, m, (sp_digit)0 - ca); +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +SP_NOINLINE static void sp_256_mont_mul_8(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + (void)mp; + (void)m; + + __asm__ __volatile__ ( + "sub sp, sp, #68\n\t" + "mov r5, #0\n\t" + "# A[0] * B[0]\n\t" + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[b], #0]\n\t" + "umull r8, r9, r6, r7\n\t" + "str r8, [sp, #0]\n\t" + "# A[0] * B[1]\n\t" + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[b], #4]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r9, r3, r9\n\t" + "adc r10, r4, #0\n\t" + "# A[1] * B[0]\n\t" + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[b], #0]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r9, r3, r9\n\t" + "adcs r10, r4, r10\n\t" + "adc r14, r5, #0\n\t" + "str r9, [sp, #4]\n\t" + "# A[0] * B[2]\n\t" + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[b], #8]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r10, r3, r10\n\t" + "adc r14, r4, r14\n\t" + "# A[1] * B[1]\n\t" + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[b], #4]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r10, r3, r10\n\t" + "adcs r14, r4, r14\n\t" + "adc r8, r5, #0\n\t" + "# A[2] * B[0]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[b], #0]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r10, r3, r10\n\t" + "adcs r14, r4, r14\n\t" + "adc r8, r5, r8\n\t" + "str r10, [sp, #8]\n\t" + "# A[0] * B[3]\n\t" + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[b], #12]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r14, r3, r14\n\t" + "adcs r8, r4, r8\n\t" + "adc r9, r5, #0\n\t" + "# A[1] * B[2]\n\t" + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[b], #8]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r14, r3, r14\n\t" + "adcs r8, r4, r8\n\t" + "adc r9, r5, r9\n\t" + "# A[2] * B[1]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[b], #4]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r14, r3, r14\n\t" + "adcs r8, r4, r8\n\t" + "adc r9, r5, r9\n\t" + "# A[3] * B[0]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b], #0]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r14, r3, r14\n\t" + "adcs r8, r4, r8\n\t" + "adc r9, r5, r9\n\t" + "str r14, [sp, #12]\n\t" + "# A[0] * B[4]\n\t" + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[b], #16]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r8, r3, r8\n\t" + "adcs r9, r4, r9\n\t" + "adc r10, r5, #0\n\t" + "# A[1] * B[3]\n\t" + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[b], #12]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r8, r3, r8\n\t" + "adcs r9, r4, r9\n\t" + "adc r10, r5, r10\n\t" + "# A[2] * B[2]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[b], #8]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r8, r3, r8\n\t" + "adcs r9, r4, r9\n\t" + "adc r10, r5, r10\n\t" + "# A[3] * B[1]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b], #4]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r8, r3, r8\n\t" + "adcs r9, r4, r9\n\t" + "adc r10, r5, r10\n\t" + "# A[4] * B[0]\n\t" + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[b], #0]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r8, r3, r8\n\t" + "adcs r9, r4, r9\n\t" + "adc r10, r5, r10\n\t" + "str r8, [sp, #16]\n\t" + "# A[0] * B[5]\n\t" + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[b], #20]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r9, r3, r9\n\t" + "adcs r10, r4, r10\n\t" + "adc r14, r5, #0\n\t" + "# A[1] * B[4]\n\t" + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[b], #16]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r9, r3, r9\n\t" + "adcs r10, r4, r10\n\t" + "adc r14, r5, r14\n\t" + "# A[2] * B[3]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[b], #12]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r9, r3, r9\n\t" + "adcs r10, r4, r10\n\t" + "adc r14, r5, r14\n\t" + "# A[3] * B[2]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b], #8]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r9, r3, r9\n\t" + "adcs r10, r4, r10\n\t" + "adc r14, r5, r14\n\t" + "# A[4] * B[1]\n\t" + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[b], #4]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r9, r3, r9\n\t" + "adcs r10, r4, r10\n\t" + "adc r14, r5, r14\n\t" + "# A[5] * B[0]\n\t" + "ldr r6, [%[a], #20]\n\t" + "ldr r7, [%[b], #0]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r9, r3, r9\n\t" + "adcs r10, r4, r10\n\t" + "adc r14, r5, r14\n\t" + "str r9, [sp, #20]\n\t" + "# A[0] * B[6]\n\t" + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[b], #24]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r10, r3, r10\n\t" + "adcs r14, r4, r14\n\t" + "adc r8, r5, #0\n\t" + "# A[1] * B[5]\n\t" + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[b], #20]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r10, r3, r10\n\t" + "adcs r14, r4, r14\n\t" + "adc r8, r5, r8\n\t" + "# A[2] * B[4]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[b], #16]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r10, r3, r10\n\t" + "adcs r14, r4, r14\n\t" + "adc r8, r5, r8\n\t" + "# A[3] * B[3]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b], #12]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r10, r3, r10\n\t" + "adcs r14, r4, r14\n\t" + "adc r8, r5, r8\n\t" + "# A[4] * B[2]\n\t" + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[b], #8]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r10, r3, r10\n\t" + "adcs r14, r4, r14\n\t" + "adc r8, r5, r8\n\t" + "# A[5] * B[1]\n\t" + "ldr r6, [%[a], #20]\n\t" + "ldr r7, [%[b], #4]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r10, r3, r10\n\t" + "adcs r14, r4, r14\n\t" + "adc r8, r5, r8\n\t" + "# A[6] * B[0]\n\t" + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[b], #0]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r10, r3, r10\n\t" + "adcs r14, r4, r14\n\t" + "adc r8, r5, r8\n\t" + "str r10, [sp, #24]\n\t" + "# A[0] * B[7]\n\t" + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[b], #28]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r14, r3, r14\n\t" + "adcs r8, r4, r8\n\t" + "adc r9, r5, #0\n\t" + "# A[1] * B[6]\n\t" + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[b], #24]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r14, r3, r14\n\t" + "adcs r8, r4, r8\n\t" + "adc r9, r5, r9\n\t" + "# A[2] * B[5]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[b], #20]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r14, r3, r14\n\t" + "adcs r8, r4, r8\n\t" + "adc r9, r5, r9\n\t" + "# A[3] * B[4]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b], #16]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r14, r3, r14\n\t" + "adcs r8, r4, r8\n\t" + "adc r9, r5, r9\n\t" + "# A[4] * B[3]\n\t" + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[b], #12]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r14, r3, r14\n\t" + "adcs r8, r4, r8\n\t" + "adc r9, r5, r9\n\t" + "# A[5] * B[2]\n\t" + "ldr r6, [%[a], #20]\n\t" + "ldr r7, [%[b], #8]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r14, r3, r14\n\t" + "adcs r8, r4, r8\n\t" + "adc r9, r5, r9\n\t" + "# A[6] * B[1]\n\t" + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[b], #4]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r14, r3, r14\n\t" + "adcs r8, r4, r8\n\t" + "adc r9, r5, r9\n\t" + "# A[7] * B[0]\n\t" + "ldr r6, [%[a], #28]\n\t" + "ldr r7, [%[b], #0]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r14, r3, r14\n\t" + "adcs r8, r4, r8\n\t" + "adc r9, r5, r9\n\t" + "str r14, [sp, #28]\n\t" + "# A[1] * B[7]\n\t" + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[b], #28]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r8, r3, r8\n\t" + "adcs r9, r4, r9\n\t" + "adc r10, r5, #0\n\t" + "# A[2] * B[6]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[b], #24]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r8, r3, r8\n\t" + "adcs r9, r4, r9\n\t" + "adc r10, r5, r10\n\t" + "# A[3] * B[5]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b], #20]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r8, r3, r8\n\t" + "adcs r9, r4, r9\n\t" + "adc r10, r5, r10\n\t" + "# A[4] * B[4]\n\t" + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[b], #16]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r8, r3, r8\n\t" + "adcs r9, r4, r9\n\t" + "adc r10, r5, r10\n\t" + "# A[5] * B[3]\n\t" + "ldr r6, [%[a], #20]\n\t" + "ldr r7, [%[b], #12]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r8, r3, r8\n\t" + "adcs r9, r4, r9\n\t" + "adc r10, r5, r10\n\t" + "# A[6] * B[2]\n\t" + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[b], #8]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r8, r3, r8\n\t" + "adcs r9, r4, r9\n\t" + "adc r10, r5, r10\n\t" + "# A[7] * B[1]\n\t" + "ldr r6, [%[a], #28]\n\t" + "ldr r7, [%[b], #4]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r8, r3, r8\n\t" + "adcs r9, r4, r9\n\t" + "adc r10, r5, r10\n\t" + "str r8, [sp, #32]\n\t" + "# A[2] * B[7]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[b], #28]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r9, r3, r9\n\t" + "adcs r10, r4, r10\n\t" + "adc r14, r5, #0\n\t" + "# A[3] * B[6]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b], #24]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r9, r3, r9\n\t" + "adcs r10, r4, r10\n\t" + "adc r14, r5, r14\n\t" + "# A[4] * B[5]\n\t" + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[b], #20]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r9, r3, r9\n\t" + "adcs r10, r4, r10\n\t" + "adc r14, r5, r14\n\t" + "# A[5] * B[4]\n\t" + "ldr r6, [%[a], #20]\n\t" + "ldr r7, [%[b], #16]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r9, r3, r9\n\t" + "adcs r10, r4, r10\n\t" + "adc r14, r5, r14\n\t" + "# A[6] * B[3]\n\t" + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[b], #12]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r9, r3, r9\n\t" + "adcs r10, r4, r10\n\t" + "adc r14, r5, r14\n\t" + "# A[7] * B[2]\n\t" + "ldr r6, [%[a], #28]\n\t" + "ldr r7, [%[b], #8]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r9, r3, r9\n\t" + "adcs r10, r4, r10\n\t" + "adc r14, r5, r14\n\t" + "str r9, [sp, #36]\n\t" + "# A[3] * B[7]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b], #28]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r10, r3, r10\n\t" + "adcs r14, r4, r14\n\t" + "adc r8, r5, #0\n\t" + "# A[4] * B[6]\n\t" + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[b], #24]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r10, r3, r10\n\t" + "adcs r14, r4, r14\n\t" + "adc r8, r5, r8\n\t" + "# A[5] * B[5]\n\t" + "ldr r6, [%[a], #20]\n\t" + "ldr r7, [%[b], #20]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r10, r3, r10\n\t" + "adcs r14, r4, r14\n\t" + "adc r8, r5, r8\n\t" + "# A[6] * B[4]\n\t" + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[b], #16]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r10, r3, r10\n\t" + "adcs r14, r4, r14\n\t" + "adc r8, r5, r8\n\t" + "# A[7] * B[3]\n\t" + "ldr r6, [%[a], #28]\n\t" + "ldr r7, [%[b], #12]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r10, r3, r10\n\t" + "adcs r14, r4, r14\n\t" + "adc r8, r5, r8\n\t" + "str r10, [sp, #40]\n\t" + "# A[4] * B[7]\n\t" + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[b], #28]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r14, r3, r14\n\t" + "adcs r8, r4, r8\n\t" + "adc r9, r5, #0\n\t" + "# A[5] * B[6]\n\t" + "ldr r6, [%[a], #20]\n\t" + "ldr r7, [%[b], #24]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r14, r3, r14\n\t" + "adcs r8, r4, r8\n\t" + "adc r9, r5, r9\n\t" + "# A[6] * B[5]\n\t" + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[b], #20]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r14, r3, r14\n\t" + "adcs r8, r4, r8\n\t" + "adc r9, r5, r9\n\t" + "# A[7] * B[4]\n\t" + "ldr r6, [%[a], #28]\n\t" + "ldr r7, [%[b], #16]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r14, r3, r14\n\t" + "adcs r8, r4, r8\n\t" + "adc r9, r5, r9\n\t" + "str r14, [sp, #44]\n\t" + "# A[5] * B[7]\n\t" + "ldr r6, [%[a], #20]\n\t" + "ldr r7, [%[b], #28]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r8, r3, r8\n\t" + "adcs r9, r4, r9\n\t" + "adc r10, r5, #0\n\t" + "# A[6] * B[6]\n\t" + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[b], #24]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r8, r3, r8\n\t" + "adcs r9, r4, r9\n\t" + "adc r10, r5, r10\n\t" + "# A[7] * B[5]\n\t" + "ldr r6, [%[a], #28]\n\t" + "ldr r7, [%[b], #20]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r8, r3, r8\n\t" + "adcs r9, r4, r9\n\t" + "adc r10, r5, r10\n\t" + "# A[6] * B[7]\n\t" + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[b], #28]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r9, r3, r9\n\t" + "adcs r10, r4, r10\n\t" + "adc r14, r5, #0\n\t" + "# A[7] * B[6]\n\t" + "ldr r6, [%[a], #28]\n\t" + "ldr r7, [%[b], #24]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r9, r3, r9\n\t" + "adcs r10, r4, r10\n\t" + "adc r14, r5, r14\n\t" + "# A[7] * B[7]\n\t" + "ldr r6, [%[a], #28]\n\t" + "ldr r7, [%[b], #28]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r10, r3, r10\n\t" + "adc r14, r4, r14\n\t" + "str r8, [sp, #48]\n\t" + "str r9, [sp, #52]\n\t" + "str r10, [sp, #56]\n\t" + "str r14, [sp, #60]\n\t" + "# Start Reduction\n\t" + "ldr r4, [sp, #0]\n\t" + "ldr r5, [sp, #4]\n\t" + "ldr r6, [sp, #8]\n\t" + "ldr r7, [sp, #12]\n\t" + "ldr r8, [sp, #16]\n\t" + "ldr r9, [sp, #20]\n\t" + "ldr r10, [sp, #24]\n\t" + "ldr r14, [sp, #28]\n\t" + "# mu = a[0]-a[7] + a[0]-a[4] << 96 + (a[0]-a[1] * 2) << 192\n\t" + "# - a[0] << 224\n\t" + "# + (a[0]-a[1] * 2) << (6 * 32)\n\t" + "adds r10, r10, r4\n\t" + "adc r14, r14, r5\n\t" + "adds r10, r10, r4\n\t" + "adc r14, r14, r5\n\t" + "# - a[0] << (7 * 32)\n\t" + "sub r14, r14, r4\n\t" + "# + a[0]-a[4] << (3 * 32)\n\t" + "mov %[a], r7\n\t" + "mov %[b], r8\n\t" + "adds r7, r7, r4\n\t" + "adcs r8, r8, r5\n\t" + "adcs r9, r9, r6\n\t" + "adcs r10, r10, %[a]\n\t" + "adc r14, r14, %[b]\n\t" + "str r4, [sp, #0]\n\t" + "str r5, [sp, #4]\n\t" + "str r6, [sp, #8]\n\t" + "str r7, [sp, #12]\n\t" + "str r8, [sp, #16]\n\t" + "str r9, [sp, #20]\n\t" + "# a += mu * m\n\t" + "# += mu * ((1 << 256) - (1 << 224) + (1 << 192) + (1 << 96) - 1)\n\t" + "mov %[a], #0\n\t" + "# a[6] += t[0] + t[3]\n\t" + "ldr r3, [sp, #24]\n\t" + "adds r3, r3, r4\n\t" + "adc %[b], %[a], #0\n\t" + "adds r3, r3, r7\n\t" + "adc %[b], %[b], #0\n\t" + "str r10, [sp, #24]\n\t" + "# a[7] += t[1] + t[4]\n\t" + "ldr r3, [sp, #28]\n\t" + "adds r3, r3, %[b]\n\t" + "adc %[b], %[a], #0\n\t" + "adds r3, r3, r5\n\t" + "adc %[b], %[b], #0\n\t" + "adds r3, r3, r8\n\t" + "adc %[b], %[b], #0\n\t" + "str r14, [sp, #28]\n\t" + "str r3, [sp, #64]\n\t" + "# a[8] += t[0] + t[2] + t[5]\n\t" + "ldr r3, [sp, #32]\n\t" + "adds r3, r3, %[b]\n\t" + "adc %[b], %[a], #0\n\t" + "adds r3, r3, r4\n\t" + "adc %[b], %[b], #0\n\t" + "adds r3, r3, r6\n\t" + "adc %[b], %[b], #0\n\t" + "adds r3, r3, r9\n\t" + "adc %[b], %[b], #0\n\t" + "str r3, [sp, #32]\n\t" + "# a[9] += t[1] + t[3] + t[6]\n\t" + "# a[10] += t[2] + t[4] + t[7]\n\t" + "ldr r3, [sp, #36]\n\t" + "ldr r4, [sp, #40]\n\t" + "adds r3, r3, %[b]\n\t" + "adcs r4, r4, #0\n\t" + "adc %[b], %[a], #0\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc %[b], %[b], #0\n\t" + "adds r3, r3, r7\n\t" + "adcs r4, r4, r8\n\t" + "adc %[b], %[b], #0\n\t" + "adds r3, r3, r10\n\t" + "adcs r4, r4, r14\n\t" + "adc %[b], %[b], #0\n\t" + "str r3, [sp, #36]\n\t" + "str r4, [sp, #40]\n\t" + "# a[11] += t[3] + t[5]\n\t" + "# a[12] += t[4] + t[6]\n\t" + "# a[13] += t[5] + t[7]\n\t" + "# a[14] += t[6]\n\t" + "ldr r3, [sp, #44]\n\t" + "ldr r4, [sp, #48]\n\t" + "ldr r5, [sp, #52]\n\t" + "ldr r6, [sp, #56]\n\t" + "adds r3, r3, %[b]\n\t" + "adcs r4, r4, #0\n\t" + "adcs r5, r5, #0\n\t" + "adcs r6, r6, #0\n\t" + "adc %[b], %[a], #0\n\t" + "adds r3, r3, r7\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adc %[b], %[b], #0\n\t" + "adds r3, r3, r9\n\t" + "adcs r4, r4, r10\n\t" + "adcs r5, r5, r14\n\t" + "adcs r6, r6, #0\n\t" + "adc %[b], %[b], #0\n\t" + "str r3, [sp, #44]\n\t" + "str r4, [sp, #48]\n\t" + "str r5, [sp, #52]\n\t" + "str r6, [sp, #56]\n\t" + "# a[15] += t[7]\n\t" + "ldr r3, [sp, #60]\n\t" + "adds r3, r3, %[b]\n\t" + "adc %[b], %[a], #0\n\t" + "adds r3, r3, r14\n\t" + "adc %[b], %[b], #0\n\t" + "str r3, [sp, #60]\n\t" + "ldr r3, [sp, #64]\n\t" + "ldr r4, [sp, #32]\n\t" + "ldr r5, [sp, #36]\n\t" + "ldr r6, [sp, #40]\n\t" + "ldr r8, [sp, #0]\n\t" + "ldr r9, [sp, #4]\n\t" + "ldr r10, [sp, #8]\n\t" + "ldr r14, [sp, #12]\n\t" + "subs r3, r3, r8\n\t" + "sbcs r4, r4, r9\n\t" + "sbcs r5, r5, r10\n\t" + "sbcs r6, r6, r14\n\t" + "str r4, [sp, #32]\n\t" + "str r5, [sp, #36]\n\t" + "str r6, [sp, #40]\n\t" + "ldr r3, [sp, #44]\n\t" + "ldr r4, [sp, #48]\n\t" + "ldr r5, [sp, #52]\n\t" + "ldr r6, [sp, #56]\n\t" + "ldr r7, [sp, #60]\n\t" + "ldr r8, [sp, #16]\n\t" + "ldr r9, [sp, #20]\n\t" + "ldr r10, [sp, #24]\n\t" + "ldr r14, [sp, #28]\n\t" + "sbcs r3, r3, r8\n\t" + "sbcs r4, r4, r9\n\t" + "sbcs r5, r5, r10\n\t" + "sbcs r6, r6, r14\n\t" + "sbc r7, r7, #0\n\t" + "str r3, [sp, #44]\n\t" + "str r4, [sp, #48]\n\t" + "str r5, [sp, #52]\n\t" + "str r6, [sp, #56]\n\t" + "str r7, [sp, #60]\n\t" + "# mask m and sub from result if overflow\n\t" + "sub %[b], %[a], %[b]\n\t" + "and %[a], %[b], #1\n\t" + "ldr r3, [sp, #32]\n\t" + "ldr r4, [sp, #36]\n\t" + "ldr r5, [sp, #40]\n\t" + "ldr r6, [sp, #44]\n\t" + "ldr r7, [sp, #48]\n\t" + "ldr r8, [sp, #52]\n\t" + "ldr r9, [sp, #56]\n\t" + "ldr r10, [sp, #60]\n\t" + "subs r3, r3, %[b]\n\t" + "sbcs r4, r4, %[b]\n\t" + "sbcs r5, r5, %[b]\n\t" + "sbcs r6, r6, #0\n\t" + "sbcs r7, r7, #0\n\t" + "sbcs r8, r8, #0\n\t" + "sbcs r9, r9, %[a]\n\t" + "sbc r10, r10, %[b]\n\t" + "str r3, [%[r], #0]\n\t" + "str r4, [%[r], #4]\n\t" + "str r5, [%[r], #8]\n\t" + "str r6, [%[r], #12]\n\t" + "str r7, [%[r], #16]\n\t" + "str r8, [%[r], #20]\n\t" + "str r9, [%[r], #24]\n\t" + "str r10, [%[r], #28]\n\t" + "add sp, sp, #68\n\t" + : [a] "+r" (a), [b] "+r" (b) + : [r] "r" (r) + : "memory", "r8", "r9", "r10", "r14", "r3", "r4", "r5", "r6", "r7" + ); +} + +/* Square the Montgomery form number mod the modulus (prime). (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +SP_NOINLINE static void sp_256_mont_sqr_8(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + (void)mp; + (void)m; + + __asm__ __volatile__ ( + "sub sp, sp, #68\n\t" + "mov r5, #0\n\t" + "# A[0] * A[1]\n\t" + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[a], #4]\n\t" + "umull r9, r10, r6, r7\n\t" + "str r9, [sp, #4]\n\t" + "# A[0] * A[2]\n\t" + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[a], #8]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r10, r3, r10\n\t" + "adc r14, r4, #0\n\t" + "str r10, [sp, #8]\n\t" + "# A[0] * A[3]\n\t" + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[a], #12]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r14, r3, r14\n\t" + "adc r8, r4, #0\n\t" + "# A[1] * A[2]\n\t" + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[a], #8]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r14, r3, r14\n\t" + "adcs r8, r4, r8\n\t" + "adc r9, r5, #0\n\t" + "str r14, [sp, #12]\n\t" + "# A[0] * A[4]\n\t" + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[a], #16]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r8, r3, r8\n\t" + "adc r9, r4, r9\n\t" + "# A[1] * A[3]\n\t" + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[a], #12]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r8, r3, r8\n\t" + "adcs r9, r4, r9\n\t" + "adc r10, r5, #0\n\t" + "str r8, [sp, #16]\n\t" + "# A[0] * A[5]\n\t" + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[a], #20]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r9, r3, r9\n\t" + "adc r10, r4, r10\n\t" + "# A[1] * A[4]\n\t" + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[a], #16]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r9, r3, r9\n\t" + "adcs r10, r4, r10\n\t" + "adc r14, r5, #0\n\t" + "# A[2] * A[3]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #12]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r9, r3, r9\n\t" + "adcs r10, r4, r10\n\t" + "adc r14, r5, r14\n\t" + "str r9, [sp, #20]\n\t" + "# A[0] * A[6]\n\t" + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[a], #24]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r10, r3, r10\n\t" + "adcs r14, r4, r14\n\t" + "adc r8, r5, #0\n\t" + "# A[1] * A[5]\n\t" + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[a], #20]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r10, r3, r10\n\t" + "adcs r14, r4, r14\n\t" + "adc r8, r5, r8\n\t" + "# A[2] * A[4]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #16]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r10, r3, r10\n\t" + "adcs r14, r4, r14\n\t" + "adc r8, r5, r8\n\t" + "str r10, [sp, #24]\n\t" + "# A[0] * A[7]\n\t" + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[a], #28]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r14, r3, r14\n\t" + "adcs r8, r4, r8\n\t" + "adc r9, r5, #0\n\t" + "# A[1] * A[6]\n\t" + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[a], #24]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r14, r3, r14\n\t" + "adcs r8, r4, r8\n\t" + "adc r9, r5, r9\n\t" + "# A[2] * A[5]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #20]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r14, r3, r14\n\t" + "adcs r8, r4, r8\n\t" + "adc r9, r5, r9\n\t" + "# A[3] * A[4]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[a], #16]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r14, r3, r14\n\t" + "adcs r8, r4, r8\n\t" + "adc r9, r5, r9\n\t" + "str r14, [sp, #28]\n\t" + "# A[1] * A[7]\n\t" + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[a], #28]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r8, r3, r8\n\t" + "adcs r9, r4, r9\n\t" + "adc r10, r5, #0\n\t" + "# A[2] * A[6]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #24]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r8, r3, r8\n\t" + "adcs r9, r4, r9\n\t" + "adc r10, r5, r10\n\t" + "# A[3] * A[5]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[a], #20]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r8, r3, r8\n\t" + "adcs r9, r4, r9\n\t" + "adc r10, r5, r10\n\t" + "str r8, [sp, #32]\n\t" + "# A[2] * A[7]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #28]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r9, r3, r9\n\t" + "adcs r10, r4, r10\n\t" + "adc r14, r5, #0\n\t" + "# A[3] * A[6]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[a], #24]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r9, r3, r9\n\t" + "adcs r10, r4, r10\n\t" + "adc r14, r5, r14\n\t" + "# A[4] * A[5]\n\t" + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[a], #20]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r9, r3, r9\n\t" + "adcs r10, r4, r10\n\t" + "adc r14, r5, r14\n\t" + "str r9, [sp, #36]\n\t" + "# A[3] * A[7]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[a], #28]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r10, r3, r10\n\t" + "adcs r14, r4, r14\n\t" + "adc r8, r5, #0\n\t" + "# A[4] * A[6]\n\t" + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[a], #24]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r10, r3, r10\n\t" + "adcs r14, r4, r14\n\t" + "adc r8, r5, r8\n\t" + "str r10, [sp, #40]\n\t" + "# A[4] * A[7]\n\t" + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[a], #28]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r14, r3, r14\n\t" + "adcs r8, r4, r8\n\t" + "adc r9, r5, #0\n\t" + "# A[5] * A[6]\n\t" + "ldr r6, [%[a], #20]\n\t" + "ldr r7, [%[a], #24]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r14, r3, r14\n\t" + "adcs r8, r4, r8\n\t" + "adc r9, r5, r9\n\t" + "str r14, [sp, #44]\n\t" + "# A[5] * A[7]\n\t" + "ldr r6, [%[a], #20]\n\t" + "ldr r7, [%[a], #28]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r8, r3, r8\n\t" + "adcs r9, r4, r9\n\t" + "adc r10, r5, #0\n\t" + "str r8, [sp, #48]\n\t" + "# A[6] * A[7]\n\t" + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[a], #28]\n\t" + "umull r3, r4, r6, r7\n\t" + "adds r9, r3, r9\n\t" + "adc r10, r4, r10\n\t" + "str r9, [sp, #52]\n\t" + "str r10, [sp, #56]\n\t" + "# Double\n\t" + "ldr r4, [sp, #4]\n\t" + "ldr r6, [sp, #8]\n\t" + "ldr r7, [sp, #12]\n\t" + "ldr r8, [sp, #16]\n\t" + "ldr r9, [sp, #20]\n\t" + "ldr r10, [sp, #24]\n\t" + "ldr r14, [sp, #28]\n\t" + "ldr r12, [sp, #32]\n\t" + "ldr r3, [sp, #36]\n\t" + "adds r4, r4, r4\n\t" + "adcs r6, r6, r6\n\t" + "adcs r7, r7, r7\n\t" + "adcs r8, r8, r8\n\t" + "adcs r9, r9, r9\n\t" + "adcs r10, r10, r10\n\t" + "adcs r14, r14, r14\n\t" + "adcs r12, r12, r12\n\t" + "adcs r3, r3, r3\n\t" + "str r4, [sp, #4]\n\t" + "str r6, [sp, #8]\n\t" + "str r7, [sp, #12]\n\t" + "str r8, [sp, #16]\n\t" + "str r9, [sp, #20]\n\t" + "str r10, [sp, #24]\n\t" + "str r14, [sp, #28]\n\t" + "str r12, [sp, #32]\n\t" + "str r3, [sp, #36]\n\t" + "ldr r4, [sp, #40]\n\t" + "ldr r6, [sp, #44]\n\t" + "ldr r7, [sp, #48]\n\t" + "ldr r8, [sp, #52]\n\t" + "ldr r9, [sp, #56]\n\t" + "adcs r4, r4, r4\n\t" + "adcs r6, r6, r6\n\t" + "adcs r7, r7, r7\n\t" + "adcs r8, r8, r8\n\t" + "adcs r9, r9, r9\n\t" + "str r4, [sp, #40]\n\t" + "str r6, [sp, #44]\n\t" + "str r7, [sp, #48]\n\t" + "str r8, [sp, #52]\n\t" + "str r9, [sp, #56]\n\t" + "adc r10, r5, #0\n\t" + "str r10, [sp, #60]\n\t" + "ldr r4, [sp, #4]\n\t" + "ldr r5, [sp, #8]\n\t" + "ldr r12, [sp, #12]\n\t" + "# A[0] * A[0]\n\t" + "ldr r6, [%[a], #0]\n\t" + "umull r8, r9, r6, r6\n\t" + "# A[1] * A[1]\n\t" + "ldr r6, [%[a], #4]\n\t" + "umull r10, r14, r6, r6\n\t" + "adds r9, r9, r4\n\t" + "adcs r10, r10, r5\n\t" + "adcs r14, r14, r12\n\t" + "str r8, [sp, #0]\n\t" + "str r9, [sp, #4]\n\t" + "str r10, [sp, #8]\n\t" + "str r14, [sp, #12]\n\t" + "ldr r3, [sp, #16]\n\t" + "ldr r4, [sp, #20]\n\t" + "ldr r5, [sp, #24]\n\t" + "ldr r12, [sp, #28]\n\t" + "# A[2] * A[2]\n\t" + "ldr r6, [%[a], #8]\n\t" + "umull r8, r9, r6, r6\n\t" + "# A[3] * A[3]\n\t" + "ldr r6, [%[a], #12]\n\t" + "umull r10, r14, r6, r6\n\t" + "adcs r8, r8, r3\n\t" + "adcs r9, r9, r4\n\t" + "adcs r10, r10, r5\n\t" + "adcs r14, r14, r12\n\t" + "str r8, [sp, #16]\n\t" + "str r9, [sp, #20]\n\t" + "str r10, [sp, #24]\n\t" + "str r14, [sp, #28]\n\t" + "ldr r3, [sp, #32]\n\t" + "ldr r4, [sp, #36]\n\t" + "ldr r5, [sp, #40]\n\t" + "ldr r12, [sp, #44]\n\t" + "# A[4] * A[4]\n\t" + "ldr r6, [%[a], #16]\n\t" + "umull r8, r9, r6, r6\n\t" + "# A[5] * A[5]\n\t" + "ldr r6, [%[a], #20]\n\t" + "umull r10, r14, r6, r6\n\t" + "adcs r8, r8, r3\n\t" + "adcs r9, r9, r4\n\t" + "adcs r10, r10, r5\n\t" + "adcs r14, r14, r12\n\t" + "str r8, [sp, #32]\n\t" + "str r9, [sp, #36]\n\t" + "str r10, [sp, #40]\n\t" + "str r14, [sp, #44]\n\t" + "ldr r3, [sp, #48]\n\t" + "ldr r4, [sp, #52]\n\t" + "ldr r5, [sp, #56]\n\t" + "ldr r12, [sp, #60]\n\t" + "# A[6] * A[6]\n\t" + "ldr r6, [%[a], #24]\n\t" + "umull r8, r9, r6, r6\n\t" + "# A[7] * A[7]\n\t" + "ldr r6, [%[a], #28]\n\t" + "umull r10, r14, r6, r6\n\t" + "adcs r8, r8, r3\n\t" + "adcs r9, r9, r4\n\t" + "adcs r10, r10, r5\n\t" + "adc r14, r14, r12\n\t" + "str r8, [sp, #48]\n\t" + "str r9, [sp, #52]\n\t" + "str r10, [sp, #56]\n\t" + "str r14, [sp, #60]\n\t" + "# Start Reduction\n\t" + "ldr r4, [sp, #0]\n\t" + "ldr r5, [sp, #4]\n\t" + "ldr r6, [sp, #8]\n\t" + "ldr r7, [sp, #12]\n\t" + "ldr r8, [sp, #16]\n\t" + "ldr r9, [sp, #20]\n\t" + "ldr r10, [sp, #24]\n\t" + "ldr r14, [sp, #28]\n\t" + "# mu = a[0]-a[7] + a[0]-a[4] << 96 + (a[0]-a[1] * 2) << 192\n\t" + "# - a[0] << 224\n\t" + "# + (a[0]-a[1] * 2) << (6 * 32)\n\t" + "adds r10, r10, r4\n\t" + "adc r14, r14, r5\n\t" + "adds r10, r10, r4\n\t" + "adc r14, r14, r5\n\t" + "# - a[0] << (7 * 32)\n\t" + "sub r14, r14, r4\n\t" + "# + a[0]-a[4] << (3 * 32)\n\t" + "mov %[a], r7\n\t" + "mov r12, r8\n\t" + "adds r7, r7, r4\n\t" + "adcs r8, r8, r5\n\t" + "adcs r9, r9, r6\n\t" + "adcs r10, r10, %[a]\n\t" + "adc r14, r14, r12\n\t" + "str r4, [sp, #0]\n\t" + "str r5, [sp, #4]\n\t" + "str r6, [sp, #8]\n\t" + "str r7, [sp, #12]\n\t" + "str r8, [sp, #16]\n\t" + "str r9, [sp, #20]\n\t" + "# a += mu * m\n\t" + "# += mu * ((1 << 256) - (1 << 224) + (1 << 192) + (1 << 96) - 1)\n\t" + "mov %[a], #0\n\t" + "# a[6] += t[0] + t[3]\n\t" + "ldr r3, [sp, #24]\n\t" + "adds r3, r3, r4\n\t" + "adc r12, %[a], #0\n\t" + "adds r3, r3, r7\n\t" + "adc r12, r12, #0\n\t" + "str r10, [sp, #24]\n\t" + "# a[7] += t[1] + t[4]\n\t" + "ldr r3, [sp, #28]\n\t" + "adds r3, r3, r12\n\t" + "adc r12, %[a], #0\n\t" + "adds r3, r3, r5\n\t" + "adc r12, r12, #0\n\t" + "adds r3, r3, r8\n\t" + "adc r12, r12, #0\n\t" + "str r14, [sp, #28]\n\t" + "str r3, [sp, #64]\n\t" + "# a[8] += t[0] + t[2] + t[5]\n\t" + "ldr r3, [sp, #32]\n\t" + "adds r3, r3, r12\n\t" + "adc r12, %[a], #0\n\t" + "adds r3, r3, r4\n\t" + "adc r12, r12, #0\n\t" + "adds r3, r3, r6\n\t" + "adc r12, r12, #0\n\t" + "adds r3, r3, r9\n\t" + "adc r12, r12, #0\n\t" + "str r3, [sp, #32]\n\t" + "# a[9] += t[1] + t[3] + t[6]\n\t" + "# a[10] += t[2] + t[4] + t[7]\n\t" + "ldr r3, [sp, #36]\n\t" + "ldr r4, [sp, #40]\n\t" + "adds r3, r3, r12\n\t" + "adcs r4, r4, #0\n\t" + "adc r12, %[a], #0\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r12, r12, #0\n\t" + "adds r3, r3, r7\n\t" + "adcs r4, r4, r8\n\t" + "adc r12, r12, #0\n\t" + "adds r3, r3, r10\n\t" + "adcs r4, r4, r14\n\t" + "adc r12, r12, #0\n\t" + "str r3, [sp, #36]\n\t" + "str r4, [sp, #40]\n\t" + "# a[11] += t[3] + t[5]\n\t" + "# a[12] += t[4] + t[6]\n\t" + "# a[13] += t[5] + t[7]\n\t" + "# a[14] += t[6]\n\t" + "ldr r3, [sp, #44]\n\t" + "ldr r4, [sp, #48]\n\t" + "ldr r5, [sp, #52]\n\t" + "ldr r6, [sp, #56]\n\t" + "adds r3, r3, r12\n\t" + "adcs r4, r4, #0\n\t" + "adcs r5, r5, #0\n\t" + "adcs r6, r6, #0\n\t" + "adc r12, %[a], #0\n\t" + "adds r3, r3, r7\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adc r12, r12, #0\n\t" + "adds r3, r3, r9\n\t" + "adcs r4, r4, r10\n\t" + "adcs r5, r5, r14\n\t" + "adcs r6, r6, #0\n\t" + "adc r12, r12, #0\n\t" + "str r3, [sp, #44]\n\t" + "str r4, [sp, #48]\n\t" + "str r5, [sp, #52]\n\t" + "str r6, [sp, #56]\n\t" + "# a[15] += t[7]\n\t" + "ldr r3, [sp, #60]\n\t" + "adds r3, r3, r12\n\t" + "adc r12, %[a], #0\n\t" + "adds r3, r3, r14\n\t" + "adc r12, r12, #0\n\t" + "str r3, [sp, #60]\n\t" + "ldr r3, [sp, #64]\n\t" + "ldr r4, [sp, #32]\n\t" + "ldr r5, [sp, #36]\n\t" + "ldr r6, [sp, #40]\n\t" + "ldr r8, [sp, #0]\n\t" + "ldr r9, [sp, #4]\n\t" + "ldr r10, [sp, #8]\n\t" + "ldr r14, [sp, #12]\n\t" + "subs r3, r3, r8\n\t" + "sbcs r4, r4, r9\n\t" + "sbcs r5, r5, r10\n\t" + "sbcs r6, r6, r14\n\t" + "str r4, [sp, #32]\n\t" + "str r5, [sp, #36]\n\t" + "str r6, [sp, #40]\n\t" + "ldr r3, [sp, #44]\n\t" + "ldr r4, [sp, #48]\n\t" + "ldr r5, [sp, #52]\n\t" + "ldr r6, [sp, #56]\n\t" + "ldr r7, [sp, #60]\n\t" + "ldr r8, [sp, #16]\n\t" + "ldr r9, [sp, #20]\n\t" + "ldr r10, [sp, #24]\n\t" + "ldr r14, [sp, #28]\n\t" + "sbcs r3, r3, r8\n\t" + "sbcs r4, r4, r9\n\t" + "sbcs r5, r5, r10\n\t" + "sbcs r6, r6, r14\n\t" + "sbc r7, r7, #0\n\t" + "str r3, [sp, #44]\n\t" + "str r4, [sp, #48]\n\t" + "str r5, [sp, #52]\n\t" + "str r6, [sp, #56]\n\t" + "str r7, [sp, #60]\n\t" + "# mask m and sub from result if overflow\n\t" + "sub r12, %[a], r12\n\t" + "and %[a], r12, #1\n\t" + "ldr r3, [sp, #32]\n\t" + "ldr r4, [sp, #36]\n\t" + "ldr r5, [sp, #40]\n\t" + "ldr r6, [sp, #44]\n\t" + "ldr r7, [sp, #48]\n\t" + "ldr r8, [sp, #52]\n\t" + "ldr r9, [sp, #56]\n\t" + "ldr r10, [sp, #60]\n\t" + "subs r3, r3, r12\n\t" + "sbcs r4, r4, r12\n\t" + "sbcs r5, r5, r12\n\t" + "sbcs r6, r6, #0\n\t" + "sbcs r7, r7, #0\n\t" + "sbcs r8, r8, #0\n\t" + "sbcs r9, r9, %[a]\n\t" + "sbc r10, r10, r12\n\t" + "str r3, [%[r], #0]\n\t" + "str r4, [%[r], #4]\n\t" + "str r5, [%[r], #8]\n\t" + "str r6, [%[r], #12]\n\t" + "str r7, [%[r], #16]\n\t" + "str r8, [%[r], #20]\n\t" + "str r9, [%[r], #24]\n\t" + "str r10, [%[r], #28]\n\t" + "add sp, sp, #68\n\t" + : [a] "+r" (a) + : [r] "r" (r) + : "memory", "r8", "r9", "r10", "r14", "r3", "r4", "r5", "r6", "r7", "r12" + ); +} + +#if !defined(WOLFSSL_SP_SMALL) || defined(HAVE_COMP_KEY) +/* Square the Montgomery form number a number of times. (r = a ^ n mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * n Number of times to square. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_256_mont_sqr_n_8(sp_digit* r, sp_digit* a, int n, + sp_digit* m, sp_digit mp) +{ + sp_256_mont_sqr_8(r, a, m, mp); + for (; n > 1; n--) + sp_256_mont_sqr_8(r, r, m, mp); +} + +#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */ +#ifdef WOLFSSL_SP_SMALL +/* Mod-2 for the P256 curve. */ +static const uint32_t p256_mod_2[8] = { + 0xfffffffd,0xffffffff,0xffffffff,0x00000000,0x00000000,0x00000000, + 0x00000001,0xffffffff +}; +#endif /* !WOLFSSL_SP_SMALL */ + +/* Invert the number, in Montgomery form, modulo the modulus (prime) of the + * P256 curve. (r = 1 / a mod m) + * + * r Inverse result. + * a Number to invert. + * td Temporary data. + */ +static void sp_256_mont_inv_8(sp_digit* r, sp_digit* a, sp_digit* td) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* t = td; + int i; + + XMEMCPY(t, a, sizeof(sp_digit) * 8); + for (i=254; i>=0; i--) { + sp_256_mont_sqr_8(t, t, p256_mod, p256_mp_mod); + if (p256_mod_2[i / 32] & ((sp_digit)1 << (i % 32))) + sp_256_mont_mul_8(t, t, a, p256_mod, p256_mp_mod); + } + XMEMCPY(r, t, sizeof(sp_digit) * 8); +#else + sp_digit* t = td; + sp_digit* t2 = td + 2 * 8; + sp_digit* t3 = td + 4 * 8; + + /* t = a^2 */ + sp_256_mont_sqr_8(t, a, p256_mod, p256_mp_mod); + /* t = a^3 = t * a */ + sp_256_mont_mul_8(t, t, a, p256_mod, p256_mp_mod); + /* t2= a^c = t ^ 2 ^ 2 */ + sp_256_mont_sqr_n_8(t2, t, 2, p256_mod, p256_mp_mod); + /* t3= a^d = t2 * a */ + sp_256_mont_mul_8(t3, t2, a, p256_mod, p256_mp_mod); + /* t = a^f = t2 * t */ + sp_256_mont_mul_8(t, t2, t, p256_mod, p256_mp_mod); + /* t2= a^f0 = t ^ 2 ^ 4 */ + sp_256_mont_sqr_n_8(t2, t, 4, p256_mod, p256_mp_mod); + /* t3= a^fd = t2 * t3 */ + sp_256_mont_mul_8(t3, t2, t3, p256_mod, p256_mp_mod); + /* t = a^ff = t2 * t */ + sp_256_mont_mul_8(t, t2, t, p256_mod, p256_mp_mod); + /* t2= a^ff00 = t ^ 2 ^ 8 */ + sp_256_mont_sqr_n_8(t2, t, 8, p256_mod, p256_mp_mod); + /* t3= a^fffd = t2 * t3 */ + sp_256_mont_mul_8(t3, t2, t3, p256_mod, p256_mp_mod); + /* t = a^ffff = t2 * t */ + sp_256_mont_mul_8(t, t2, t, p256_mod, p256_mp_mod); + /* t2= a^ffff0000 = t ^ 2 ^ 16 */ + sp_256_mont_sqr_n_8(t2, t, 16, p256_mod, p256_mp_mod); + /* t3= a^fffffffd = t2 * t3 */ + sp_256_mont_mul_8(t3, t2, t3, p256_mod, p256_mp_mod); + /* t = a^ffffffff = t2 * t */ + sp_256_mont_mul_8(t, t2, t, p256_mod, p256_mp_mod); + /* t = a^ffffffff00000000 = t ^ 2 ^ 32 */ + sp_256_mont_sqr_n_8(t2, t, 32, p256_mod, p256_mp_mod); + /* t2= a^ffffffffffffffff = t2 * t */ + sp_256_mont_mul_8(t, t2, t, p256_mod, p256_mp_mod); + /* t2= a^ffffffff00000001 = t2 * a */ + sp_256_mont_mul_8(t2, t2, a, p256_mod, p256_mp_mod); + /* t2= a^ffffffff000000010000000000000000000000000000000000000000 + * = t2 ^ 2 ^ 160 */ + sp_256_mont_sqr_n_8(t2, t2, 160, p256_mod, p256_mp_mod); + /* t2= a^ffffffff00000001000000000000000000000000ffffffffffffffff + * = t2 * t */ + sp_256_mont_mul_8(t2, t2, t, p256_mod, p256_mp_mod); + /* t2= a^ffffffff00000001000000000000000000000000ffffffffffffffff00000000 + * = t2 ^ 2 ^ 32 */ + sp_256_mont_sqr_n_8(t2, t2, 32, p256_mod, p256_mp_mod); + /* r = a^ffffffff00000001000000000000000000000000fffffffffffffffffffffffd + * = t2 * t3 */ + sp_256_mont_mul_8(r, t2, t3, p256_mod, p256_mp_mod); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Map the Montgomery form projective co-ordinate point to an affine point. + * + * r Resulting affine co-ordinate point. + * p Montgomery form projective co-ordinate point. + * t Temporary ordinate data. + */ +static void sp_256_map_8(sp_point* r, sp_point* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*8; + int32_t n; + + sp_256_mont_inv_8(t1, p->z, t + 2*8); + + sp_256_mont_sqr_8(t2, t1, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t1, t2, t1, p256_mod, p256_mp_mod); + + /* x /= z^2 */ + sp_256_mont_mul_8(r->x, p->x, t2, p256_mod, p256_mp_mod); + XMEMSET(r->x + 8, 0, sizeof(r->x) / 2); + sp_256_mont_reduce_8(r->x, p256_mod, p256_mp_mod); + /* Reduce x to less than modulus */ + n = sp_256_cmp_8(r->x, p256_mod); + sp_256_cond_sub_8(r->x, r->x, p256_mod, 0 - (n >= 0)); + sp_256_norm_8(r->x); + + /* y /= z^3 */ + sp_256_mont_mul_8(r->y, p->y, t1, p256_mod, p256_mp_mod); + XMEMSET(r->y + 8, 0, sizeof(r->y) / 2); + sp_256_mont_reduce_8(r->y, p256_mod, p256_mp_mod); + /* Reduce y to less than modulus */ + n = sp_256_cmp_8(r->y, p256_mod); + sp_256_cond_sub_8(r->y, r->y, p256_mod, 0 - (n >= 0)); + sp_256_norm_8(r->y); + + XMEMSET(r->z, 0, sizeof(r->z)); + r->z[0] = 1; + +} + +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_256_add_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "add r12, %[a], #32\n\t" + "\n1:\n\t" + "adds %[c], %[c], #-1\n\t" + "ldr r4, [%[a]], #4\n\t" + "ldr r5, [%[a]], #4\n\t" + "ldr r6, [%[a]], #4\n\t" + "ldr r7, [%[a]], #4\n\t" + "ldr r8, [%[b]], #4\n\t" + "ldr r9, [%[b]], #4\n\t" + "ldr r10, [%[b]], #4\n\t" + "ldr r14, [%[b]], #4\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r]], #4\n\t" + "str r5, [%[r]], #4\n\t" + "str r6, [%[r]], #4\n\t" + "str r7, [%[r]], #4\n\t" + "mov r4, #0\n\t" + "adc %[c], r4, #0\n\t" + "cmp %[a], r12\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + return c; +} + +#else +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_256_add_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r12, #0\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[a], #4]\n\t" + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #12]\n\t" + "ldr r8, [%[b], #0]\n\t" + "ldr r9, [%[b], #4]\n\t" + "ldr r10, [%[b], #8]\n\t" + "ldr r14, [%[b], #12]\n\t" + "adds r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #0]\n\t" + "str r5, [%[r], #4]\n\t" + "str r6, [%[r], #8]\n\t" + "str r7, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[a], #20]\n\t" + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[a], #28]\n\t" + "ldr r8, [%[b], #16]\n\t" + "ldr r9, [%[b], #20]\n\t" + "ldr r10, [%[b], #24]\n\t" + "ldr r14, [%[b], #28]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r], #16]\n\t" + "str r5, [%[r], #20]\n\t" + "str r6, [%[r], #24]\n\t" + "str r7, [%[r], #28]\n\t" + "adc %[c], r12, r12\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Add two Montgomery form numbers (r = a + b % m). + * + * r Result of addition. + * a First number to add in Montogmery form. + * b Second number to add in Montogmery form. + * m Modulus (prime). + */ +static void sp_256_mont_add_8(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m) +{ + (void)m; + + __asm__ __volatile__ ( + "mov r12, #0\n\t" + "ldr r4, [%[a],#0]\n\t" + "ldr r5, [%[a],#4]\n\t" + "ldr r6, [%[a],#8]\n\t" + "ldr r7, [%[a],#12]\n\t" + "ldr r8, [%[b],#0]\n\t" + "ldr r9, [%[b],#4]\n\t" + "ldr r10, [%[b],#8]\n\t" + "ldr r14, [%[b],#12]\n\t" + "adds r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "str r4, [%[r],#0]\n\t" + "str r5, [%[r],#4]\n\t" + "str r6, [%[r],#8]\n\t" + "str r7, [%[r],#12]\n\t" + "ldr r4, [%[a],#16]\n\t" + "ldr r5, [%[a],#20]\n\t" + "ldr r6, [%[a],#24]\n\t" + "ldr r7, [%[a],#28]\n\t" + "ldr r8, [%[b],#16]\n\t" + "ldr r9, [%[b],#20]\n\t" + "ldr r10, [%[b],#24]\n\t" + "ldr r14, [%[b],#28]\n\t" + "adcs r4, r4, r8\n\t" + "adcs r5, r5, r9\n\t" + "adcs r6, r6, r10\n\t" + "adcs r7, r7, r14\n\t" + "adc r3, r12, #0\n\t" + "sub r3, r12, r3\n\t" + "and r12, r3, #1\n\t" + "ldr r8, [%[r],#0]\n\t" + "ldr r9, [%[r],#4]\n\t" + "ldr r10, [%[r],#8]\n\t" + "ldr r14, [%[r],#12]\n\t" + "subs r8, r8, r3\n\t" + "sbcs r9, r9, r3\n\t" + "sbcs r10, r10, r3\n\t" + "sbcs r14, r14, #0\n\t" + "sbcs r4, r4, #0\n\t" + "sbcs r5, r5, #0\n\t" + "sbcs r6, r6, r12\n\t" + "sbc r7, r7, r3\n\t" + "str r8, [%[r],#0]\n\t" + "str r9, [%[r],#4]\n\t" + "str r10, [%[r],#8]\n\t" + "str r14, [%[r],#12]\n\t" + "str r4, [%[r],#16]\n\t" + "str r5, [%[r],#20]\n\t" + "str r6, [%[r],#24]\n\t" + "str r7, [%[r],#28]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r3", "r12" + ); +} + +/* Double a Montgomery form number (r = a + a % m). + * + * r Result of doubling. + * a Number to double in Montogmery form. + * m Modulus (prime). + */ +static void sp_256_mont_dbl_8(sp_digit* r, sp_digit* a, sp_digit* m) +{ + (void)m; + + __asm__ __volatile__ ( + "mov r12, #0\n\t" + "ldr r4, [%[a],#0]\n\t" + "ldr r5, [%[a],#4]\n\t" + "ldr r6, [%[a],#8]\n\t" + "ldr r7, [%[a],#12]\n\t" + "ldr r8, [%[a],#16]\n\t" + "ldr r9, [%[a],#20]\n\t" + "ldr r10, [%[a],#24]\n\t" + "ldr r14, [%[a],#28]\n\t" + "adds r4, r4, r4\n\t" + "adcs r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adcs r7, r7, r7\n\t" + "adcs r8, r8, r8\n\t" + "adcs r9, r9, r9\n\t" + "adcs r10, r10, r10\n\t" + "adcs r14, r14, r14\n\t" + "adc r3, r12, #0\n\t" + "sub r3, r12, r3\n\t" + "and r12, r3, #1\n\t" + "subs r4, r4, r3\n\t" + "sbcs r5, r5, r3\n\t" + "sbcs r6, r6, r3\n\t" + "sbcs r7, r7, #0\n\t" + "sbcs r8, r8, #0\n\t" + "sbcs r9, r9, #0\n\t" + "sbcs r10, r10, r12\n\t" + "sbc r14, r14, r3\n\t" + "str r4, [%[r],#0]\n\t" + "str r5, [%[r],#4]\n\t" + "str r6, [%[r],#8]\n\t" + "str r7, [%[r],#12]\n\t" + "str r8, [%[r],#16]\n\t" + "str r9, [%[r],#20]\n\t" + "str r10, [%[r],#24]\n\t" + "str r14, [%[r],#28]\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r3", "r12" + ); +} + +/* Triple a Montgomery form number (r = a + a + a % m). + * + * r Result of Tripling. + * a Number to triple in Montogmery form. + * m Modulus (prime). + */ +static void sp_256_mont_tpl_8(sp_digit* r, sp_digit* a, sp_digit* m) +{ + (void)m; + + __asm__ __volatile__ ( + "mov r12, #0\n\t" + "ldr r4, [%[a],#0]\n\t" + "ldr r5, [%[a],#4]\n\t" + "ldr r6, [%[a],#8]\n\t" + "ldr r7, [%[a],#12]\n\t" + "ldr r8, [%[a],#16]\n\t" + "ldr r9, [%[a],#20]\n\t" + "ldr r10, [%[a],#24]\n\t" + "ldr r14, [%[a],#28]\n\t" + "adds r4, r4, r4\n\t" + "adcs r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adcs r7, r7, r7\n\t" + "adcs r8, r8, r8\n\t" + "adcs r9, r9, r9\n\t" + "adcs r10, r10, r10\n\t" + "adcs r14, r14, r14\n\t" + "adc r3, r12, #0\n\t" + "sub r3, r12, r3\n\t" + "and r12, r3, #1\n\t" + "subs r4, r4, r3\n\t" + "sbcs r5, r5, r3\n\t" + "sbcs r6, r6, r3\n\t" + "sbcs r7, r7, #0\n\t" + "sbcs r8, r8, #0\n\t" + "sbcs r9, r9, #0\n\t" + "sbcs r10, r10, r12\n\t" + "sbc r14, r14, r3\n\t" + "str r8, [%[r],#16]\n\t" + "str r9, [%[r],#20]\n\t" + "str r10, [%[r],#24]\n\t" + "str r14, [%[r],#28]\n\t" + "mov r12, #0\n\t" + "ldr r8, [%[a],#0]\n\t" + "ldr r9, [%[a],#4]\n\t" + "ldr r10, [%[a],#8]\n\t" + "ldr r14, [%[a],#12]\n\t" + "adds r8, r8, r4\n\t" + "adcs r9, r9, r5\n\t" + "adcs r10, r10, r6\n\t" + "adcs r14, r14, r7\n\t" + "str r8, [%[r],#0]\n\t" + "str r9, [%[r],#4]\n\t" + "str r10, [%[r],#8]\n\t" + "str r14, [%[r],#12]\n\t" + "ldr r8, [%[a],#16]\n\t" + "ldr r9, [%[a],#20]\n\t" + "ldr r10, [%[a],#24]\n\t" + "ldr r14, [%[a],#28]\n\t" + "ldr r4, [%[r],#16]\n\t" + "ldr r5, [%[r],#20]\n\t" + "ldr r6, [%[r],#24]\n\t" + "ldr r7, [%[r],#28]\n\t" + "adcs r8, r8, r4\n\t" + "adcs r9, r9, r5\n\t" + "adcs r10, r10, r6\n\t" + "adcs r14, r14, r7\n\t" + "adc r3, r12, #0\n\t" + "sub r3, r12, r3\n\t" + "and r12, r3, #1\n\t" + "ldr r4, [%[r],#0]\n\t" + "ldr r5, [%[r],#4]\n\t" + "ldr r6, [%[r],#8]\n\t" + "ldr r7, [%[r],#12]\n\t" + "subs r4, r4, r3\n\t" + "sbcs r5, r5, r3\n\t" + "sbcs r6, r6, r3\n\t" + "sbcs r7, r7, #0\n\t" + "sbcs r8, r8, #0\n\t" + "sbcs r9, r9, #0\n\t" + "sbcs r10, r10, r12\n\t" + "sbc r14, r14, r3\n\t" + "str r4, [%[r],#0]\n\t" + "str r5, [%[r],#4]\n\t" + "str r6, [%[r],#8]\n\t" + "str r7, [%[r],#12]\n\t" + "str r8, [%[r],#16]\n\t" + "str r9, [%[r],#20]\n\t" + "str r10, [%[r],#24]\n\t" + "str r14, [%[r],#28]\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r3", "r12" + ); +} + +/* Subtract two Montgomery form numbers (r = a - b % m). + * + * r Result of subtration. + * a Number to subtract from in Montogmery form. + * b Number to subtract with in Montogmery form. + * m Modulus (prime). + */ +static void sp_256_mont_sub_8(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m) +{ + (void)m; + + __asm__ __volatile__ ( + "mov r12, #0\n\t" + "ldr r4, [%[a],#0]\n\t" + "ldr r5, [%[a],#4]\n\t" + "ldr r6, [%[a],#8]\n\t" + "ldr r7, [%[a],#12]\n\t" + "ldr r8, [%[b],#0]\n\t" + "ldr r9, [%[b],#4]\n\t" + "ldr r10, [%[b],#8]\n\t" + "ldr r14, [%[b],#12]\n\t" + "subs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "str r4, [%[r],#0]\n\t" + "str r5, [%[r],#4]\n\t" + "str r6, [%[r],#8]\n\t" + "str r7, [%[r],#12]\n\t" + "ldr r4, [%[a],#16]\n\t" + "ldr r5, [%[a],#20]\n\t" + "ldr r6, [%[a],#24]\n\t" + "ldr r7, [%[a],#28]\n\t" + "ldr r8, [%[b],#16]\n\t" + "ldr r9, [%[b],#20]\n\t" + "ldr r10, [%[b],#24]\n\t" + "ldr r14, [%[b],#28]\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "sbc r3, r12, #0\n\t" + "and r12, r3, #1\n\t" + "ldr r8, [%[r],#0]\n\t" + "ldr r9, [%[r],#4]\n\t" + "ldr r10, [%[r],#8]\n\t" + "ldr r14, [%[r],#12]\n\t" + "adds r8, r8, r3\n\t" + "adcs r9, r9, r3\n\t" + "adcs r10, r10, r3\n\t" + "adcs r14, r14, #0\n\t" + "adcs r4, r4, #0\n\t" + "adcs r5, r5, #0\n\t" + "adcs r6, r6, r12\n\t" + "adc r7, r7, r3\n\t" + "str r8, [%[r],#0]\n\t" + "str r9, [%[r],#4]\n\t" + "str r10, [%[r],#8]\n\t" + "str r14, [%[r],#12]\n\t" + "str r4, [%[r],#16]\n\t" + "str r5, [%[r],#20]\n\t" + "str r6, [%[r],#24]\n\t" + "str r7, [%[r],#28]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r3", "r12" + ); +} + +/* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m) + * + * r Result of division by 2. + * a Number to divide. + * m Modulus (prime). + */ +static void sp_256_div2_8(sp_digit* r, sp_digit* a, sp_digit* m) +{ + __asm__ __volatile__ ( + "mov r10, #0\n\t" + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[a], #8]\n\t" + "ldr r6, [%[a], #12]\n\t" + "and r9, r3, #1\n\t" + "sub r7, r10, r9\n\t" + "and r8, r7, #1\n\t" + "adds r3, r3, r7\n\t" + "adcs r4, r4, r7\n\t" + "adcs r5, r5, r7\n\t" + "adcs r6, r6, r10\n\t" + "str r3, [%[r], #0]\n\t" + "str r4, [%[r], #4]\n\t" + "str r5, [%[r], #8]\n\t" + "str r6, [%[r], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[a], #24]\n\t" + "ldr r6, [%[a], #28]\n\t" + "adcs r3, r3, r10\n\t" + "adcs r4, r4, r10\n\t" + "adcs r5, r5, r8\n\t" + "adcs r6, r6, r7\n\t" + "adc r9, r10, r10\n\t" + "lsr r7, r3, #1\n\t" + "and r3, r3, #1\n\t" + "lsr r8, r4, #1\n\t" + "lsr r10, r5, #1\n\t" + "lsr r14, r6, #1\n\t" + "orr r7, r7, r4, lsl #31\n\t" + "orr r8, r8, r5, lsl #31\n\t" + "orr r10, r10, r6, lsl #31\n\t" + "orr r14, r14, r9, lsl #31\n\t" + "mov r9, r3\n\t" + "str r7, [%[r], #16]\n\t" + "str r8, [%[r], #20]\n\t" + "str r10, [%[r], #24]\n\t" + "str r14, [%[r], #28]\n\t" + "ldr r3, [%[r], #0]\n\t" + "ldr r4, [%[r], #4]\n\t" + "ldr r5, [%[r], #8]\n\t" + "ldr r6, [%[r], #12]\n\t" + "lsr r7, r3, #1\n\t" + "lsr r8, r4, #1\n\t" + "lsr r10, r5, #1\n\t" + "lsr r14, r6, #1\n\t" + "orr r7, r7, r4, lsl #31\n\t" + "orr r8, r8, r5, lsl #31\n\t" + "orr r10, r10, r6, lsl #31\n\t" + "orr r14, r14, r9, lsl #31\n\t" + "str r7, [%[r], #0]\n\t" + "str r8, [%[r], #4]\n\t" + "str r10, [%[r], #8]\n\t" + "str r14, [%[r], #12]\n\t" + : + : [r] "r" (r), [a] "r" (a), [m] "r" (m) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r10", "r14", "r9" + ); + +} + +/* Double the Montgomery form projective point p. + * + * r Result of doubling point. + * p Point to double. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_dbl_8(sp_point* r, sp_point* p, sp_digit* t) +{ + sp_point* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*8; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* When infinity don't double point passed in - constant time. */ + rp[0] = r; + rp[1] = (sp_point*)t; + XMEMSET(rp[1], 0, sizeof(sp_point)); + x = rp[p->infinity]->x; + y = rp[p->infinity]->y; + z = rp[p->infinity]->z; + /* Put point to double into result - good for infinty. */ + if (r != p) { + for (i=0; i<8; i++) + r->x[i] = p->x[i]; + for (i=0; i<8; i++) + r->y[i] = p->y[i]; + for (i=0; i<8; i++) + r->z[i] = p->z[i]; + r->infinity = p->infinity; + } + + /* T1 = Z * Z */ + sp_256_mont_sqr_8(t1, z, p256_mod, p256_mp_mod); + /* Z = Y * Z */ + sp_256_mont_mul_8(z, y, z, p256_mod, p256_mp_mod); + /* Z = 2Z */ + sp_256_mont_dbl_8(z, z, p256_mod); + /* T2 = X - T1 */ + sp_256_mont_sub_8(t2, x, t1, p256_mod); + /* T1 = X + T1 */ + sp_256_mont_add_8(t1, x, t1, p256_mod); + /* T2 = T1 * T2 */ + sp_256_mont_mul_8(t2, t1, t2, p256_mod, p256_mp_mod); + /* T1 = 3T2 */ + sp_256_mont_tpl_8(t1, t2, p256_mod); + /* Y = 2Y */ + sp_256_mont_dbl_8(y, y, p256_mod); + /* Y = Y * Y */ + sp_256_mont_sqr_8(y, y, p256_mod, p256_mp_mod); + /* T2 = Y * Y */ + sp_256_mont_sqr_8(t2, y, p256_mod, p256_mp_mod); + /* T2 = T2/2 */ + sp_256_div2_8(t2, t2, p256_mod); + /* Y = Y * X */ + sp_256_mont_mul_8(y, y, x, p256_mod, p256_mp_mod); + /* X = T1 * T1 */ + sp_256_mont_mul_8(x, t1, t1, p256_mod, p256_mp_mod); + /* X = X - Y */ + sp_256_mont_sub_8(x, x, y, p256_mod); + /* X = X - Y */ + sp_256_mont_sub_8(x, x, y, p256_mod); + /* Y = Y - X */ + sp_256_mont_sub_8(y, y, x, p256_mod); + /* Y = Y * T1 */ + sp_256_mont_mul_8(y, y, t1, p256_mod, p256_mp_mod); + /* Y = Y - T2 */ + sp_256_mont_sub_8(y, y, t2, p256_mod); + +} + +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_256_sub_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "add r12, %[a], #32\n\t" + "\n1:\n\t" + "rsbs %[c], %[c], #0\n\t" + "ldr r4, [%[a]], #4\n\t" + "ldr r5, [%[a]], #4\n\t" + "ldr r6, [%[a]], #4\n\t" + "ldr r7, [%[a]], #4\n\t" + "ldr r8, [%[b]], #4\n\t" + "ldr r9, [%[b]], #4\n\t" + "ldr r10, [%[b]], #4\n\t" + "ldr r14, [%[b]], #4\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "sbcs r7, r7, r14\n\t" + "str r4, [%[r]], #4\n\t" + "str r5, [%[r]], #4\n\t" + "str r6, [%[r]], #4\n\t" + "str r7, [%[r]], #4\n\t" + "sbc %[c], r4, r4\n\t" + "cmp %[a], r12\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); + + return c; +} + +#else +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_256_sub_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[a], #8]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b], #0]\n\t" + "ldr r8, [%[b], #4]\n\t" + "ldr r9, [%[b], #8]\n\t" + "ldr r10, [%[b], #12]\n\t" + "subs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "str r3, [%[r], #0]\n\t" + "str r4, [%[r], #4]\n\t" + "str r5, [%[r], #8]\n\t" + "str r6, [%[r], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[a], #24]\n\t" + "ldr r6, [%[a], #28]\n\t" + "ldr r7, [%[b], #16]\n\t" + "ldr r8, [%[b], #20]\n\t" + "ldr r9, [%[b], #24]\n\t" + "ldr r10, [%[b], #28]\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "str r3, [%[r], #16]\n\t" + "str r4, [%[r], #20]\n\t" + "str r5, [%[r], #24]\n\t" + "str r6, [%[r], #28]\n\t" + "sbc %[c], %[c], #0\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Compare two numbers to determine if they are equal. + * Constant time implementation. + * + * a First number to compare. + * b Second number to compare. + * returns 1 when equal and 0 otherwise. + */ +static int sp_256_cmp_equal_8(const sp_digit* a, const sp_digit* b) +{ + return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]) | (a[3] ^ b[3]) | + (a[4] ^ b[4]) | (a[5] ^ b[5]) | (a[6] ^ b[6]) | (a[7] ^ b[7])) == 0; +} + +/* Add two Montgomery form projective points. + * + * r Result of addition. + * p Frist point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_add_8(sp_point* r, sp_point* p, sp_point* q, + sp_digit* t) +{ + sp_point* ap[2]; + sp_point* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*8; + sp_digit* t3 = t + 4*8; + sp_digit* t4 = t + 6*8; + sp_digit* t5 = t + 8*8; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + sp_point* a = p; + p = q; + q = a; + } + + /* Check double */ + sp_256_sub_8(t1, p256_mod, q->y); + sp_256_norm_8(t1); + if (sp_256_cmp_equal_8(p->x, q->x) & sp_256_cmp_equal_8(p->z, q->z) & + (sp_256_cmp_equal_8(p->y, q->y) | sp_256_cmp_equal_8(p->y, t1))) { + sp_256_proj_point_dbl_8(r, p, t); + } + else { + rp[0] = r; + rp[1] = (sp_point*)t; + XMEMSET(rp[1], 0, sizeof(sp_point)); + x = rp[p->infinity | q->infinity]->x; + y = rp[p->infinity | q->infinity]->y; + z = rp[p->infinity | q->infinity]->z; + + ap[0] = p; + ap[1] = q; + for (i=0; i<8; i++) + r->x[i] = ap[p->infinity]->x[i]; + for (i=0; i<8; i++) + r->y[i] = ap[p->infinity]->y[i]; + for (i=0; i<8; i++) + r->z[i] = ap[p->infinity]->z[i]; + r->infinity = ap[p->infinity]->infinity; + + /* U1 = X1*Z2^2 */ + sp_256_mont_sqr_8(t1, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t3, t1, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t1, t1, x, p256_mod, p256_mp_mod); + /* U2 = X2*Z1^2 */ + sp_256_mont_sqr_8(t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t4, t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t2, t2, q->x, p256_mod, p256_mp_mod); + /* S1 = Y1*Z2^3 */ + sp_256_mont_mul_8(t3, t3, y, p256_mod, p256_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_256_mont_mul_8(t4, t4, q->y, p256_mod, p256_mp_mod); + /* H = U2 - U1 */ + sp_256_mont_sub_8(t2, t2, t1, p256_mod); + /* R = S2 - S1 */ + sp_256_mont_sub_8(t4, t4, t3, p256_mod); + /* Z3 = H*Z1*Z2 */ + sp_256_mont_mul_8(z, z, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(z, z, t2, p256_mod, p256_mp_mod); + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_256_mont_sqr_8(x, t4, p256_mod, p256_mp_mod); + sp_256_mont_sqr_8(t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(y, t1, t5, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t5, t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_sub_8(x, x, t5, p256_mod); + sp_256_mont_dbl_8(t1, y, p256_mod); + sp_256_mont_sub_8(x, x, t1, p256_mod); + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_256_mont_sub_8(y, y, x, p256_mod); + sp_256_mont_mul_8(y, y, t4, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t5, t5, t3, p256_mod, p256_mp_mod); + sp_256_mont_sub_8(y, y, t5, p256_mod); + } +} + +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_fast_8(sp_point* r, sp_point* g, sp_digit* k, + int map, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point td[16]; + sp_point rtd; + sp_digit tmpd[2 * 8 * 5]; +#endif + sp_point* t; + sp_point* rt; + sp_digit* tmp; + sp_digit n; + int i; + int c, y; + int err; + + (void)heap; + + err = sp_ecc_point_new(heap, rtd, rt); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + t = (sp_point*)XMALLOC(sizeof(sp_point) * 16, heap, DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 5, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; +#else + t = td; + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + /* t[0] = {0, 0, 1} * norm */ + XMEMSET(&t[0], 0, sizeof(t[0])); + t[0].infinity = 1; + /* t[1] = {g->x, g->y, g->z} * norm */ + sp_256_mod_mul_norm_8(t[1].x, g->x, p256_mod); + sp_256_mod_mul_norm_8(t[1].y, g->y, p256_mod); + sp_256_mod_mul_norm_8(t[1].z, g->z, p256_mod); + t[1].infinity = 0; + sp_256_proj_point_dbl_8(&t[ 2], &t[ 1], tmp); + t[ 2].infinity = 0; + sp_256_proj_point_add_8(&t[ 3], &t[ 2], &t[ 1], tmp); + t[ 3].infinity = 0; + sp_256_proj_point_dbl_8(&t[ 4], &t[ 2], tmp); + t[ 4].infinity = 0; + sp_256_proj_point_add_8(&t[ 5], &t[ 3], &t[ 2], tmp); + t[ 5].infinity = 0; + sp_256_proj_point_dbl_8(&t[ 6], &t[ 3], tmp); + t[ 6].infinity = 0; + sp_256_proj_point_add_8(&t[ 7], &t[ 4], &t[ 3], tmp); + t[ 7].infinity = 0; + sp_256_proj_point_dbl_8(&t[ 8], &t[ 4], tmp); + t[ 8].infinity = 0; + sp_256_proj_point_add_8(&t[ 9], &t[ 5], &t[ 4], tmp); + t[ 9].infinity = 0; + sp_256_proj_point_dbl_8(&t[10], &t[ 5], tmp); + t[10].infinity = 0; + sp_256_proj_point_add_8(&t[11], &t[ 6], &t[ 5], tmp); + t[11].infinity = 0; + sp_256_proj_point_dbl_8(&t[12], &t[ 6], tmp); + t[12].infinity = 0; + sp_256_proj_point_add_8(&t[13], &t[ 7], &t[ 6], tmp); + t[13].infinity = 0; + sp_256_proj_point_dbl_8(&t[14], &t[ 7], tmp); + t[14].infinity = 0; + sp_256_proj_point_add_8(&t[15], &t[ 8], &t[ 7], tmp); + t[15].infinity = 0; + + i = 6; + n = k[i+1] << 0; + c = 28; + y = n >> 28; + XMEMCPY(rt, &t[y], sizeof(sp_point)); + n <<= 4; + for (; i>=0 || c>=4; ) { + if (c < 4) { + n |= k[i--] << (0 - c); + c += 32; + } + y = (n >> 28) & 0xf; + n <<= 4; + c -= 4; + + sp_256_proj_point_dbl_8(rt, rt, tmp); + sp_256_proj_point_dbl_8(rt, rt, tmp); + sp_256_proj_point_dbl_8(rt, rt, tmp); + sp_256_proj_point_dbl_8(rt, rt, tmp); + + sp_256_proj_point_add_8(rt, rt, &t[y], tmp); + } + + if (map) + sp_256_map_8(r, rt, tmp); + else + XMEMCPY(r, rt, sizeof(sp_point)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (tmp != NULL) { + XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 8 * 5); + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + } + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_point) * 16); + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } +#else + ForceZero(tmpd, sizeof(tmpd)); + ForceZero(td, sizeof(td)); +#endif + sp_ecc_point_free(rt, 1, heap); + + return err; +} + +/* A table entry for pre-computed points. */ +typedef struct sp_table_entry { + sp_digit x[8]; + sp_digit y[8]; + byte infinity; +} sp_table_entry; + +#ifdef FP_ECC +/* Double the Montgomery form projective point p a number of times. + * + * r Result of repeated doubling of point. + * p Point to double. + * n Number of times to double + * t Temporary ordinate data. + */ +static void sp_256_proj_point_dbl_n_8(sp_point* r, sp_point* p, int n, + sp_digit* t) +{ + sp_point* rp[2]; + sp_digit* w = t; + sp_digit* a = t + 2*8; + sp_digit* b = t + 4*8; + sp_digit* t1 = t + 6*8; + sp_digit* t2 = t + 8*8; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + rp[0] = r; + rp[1] = (sp_point*)t; + XMEMSET(rp[1], 0, sizeof(sp_point)); + x = rp[p->infinity]->x; + y = rp[p->infinity]->y; + z = rp[p->infinity]->z; + if (r != p) { + for (i=0; i<8; i++) + r->x[i] = p->x[i]; + for (i=0; i<8; i++) + r->y[i] = p->y[i]; + for (i=0; i<8; i++) + r->z[i] = p->z[i]; + r->infinity = p->infinity; + } + + /* Y = 2*Y */ + sp_256_mont_dbl_8(y, y, p256_mod); + /* W = Z^4 */ + sp_256_mont_sqr_8(w, z, p256_mod, p256_mp_mod); + sp_256_mont_sqr_8(w, w, p256_mod, p256_mp_mod); + while (n--) { + /* A = 3*(X^2 - W) */ + sp_256_mont_sqr_8(t1, x, p256_mod, p256_mp_mod); + sp_256_mont_sub_8(t1, t1, w, p256_mod); + sp_256_mont_tpl_8(a, t1, p256_mod); + /* B = X*Y^2 */ + sp_256_mont_sqr_8(t2, y, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(b, t2, x, p256_mod, p256_mp_mod); + /* X = A^2 - 2B */ + sp_256_mont_sqr_8(x, a, p256_mod, p256_mp_mod); + sp_256_mont_dbl_8(t1, b, p256_mod); + sp_256_mont_sub_8(x, x, t1, p256_mod); + /* Z = Z*Y */ + sp_256_mont_mul_8(z, z, y, p256_mod, p256_mp_mod); + /* t2 = Y^4 */ + sp_256_mont_sqr_8(t2, t2, p256_mod, p256_mp_mod); + if (n) { + /* W = W*Y^4 */ + sp_256_mont_mul_8(w, w, t2, p256_mod, p256_mp_mod); + } + /* y = 2*A*(B - X) - Y^4 */ + sp_256_mont_sub_8(y, b, x, p256_mod); + sp_256_mont_mul_8(y, y, a, p256_mod, p256_mp_mod); + sp_256_mont_dbl_8(y, y, p256_mod); + sp_256_mont_sub_8(y, y, t2, p256_mod); + } + /* Y = Y/2 */ + sp_256_div2_8(y, y, p256_mod); +} + +#endif /* FP_ECC */ +/* Add two Montgomery form projective points. The second point has a q value of + * one. + * Only the first point can be the same pointer as the result point. + * + * r Result of addition. + * p Frist point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_add_qz1_8(sp_point* r, sp_point* p, + sp_point* q, sp_digit* t) +{ + sp_point* ap[2]; + sp_point* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*8; + sp_digit* t3 = t + 4*8; + sp_digit* t4 = t + 6*8; + sp_digit* t5 = t + 8*8; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* Check double */ + sp_256_sub_8(t1, p256_mod, q->y); + sp_256_norm_8(t1); + if (sp_256_cmp_equal_8(p->x, q->x) & sp_256_cmp_equal_8(p->z, q->z) & + (sp_256_cmp_equal_8(p->y, q->y) | sp_256_cmp_equal_8(p->y, t1))) { + sp_256_proj_point_dbl_8(r, p, t); + } + else { + rp[0] = r; + rp[1] = (sp_point*)t; + XMEMSET(rp[1], 0, sizeof(sp_point)); + x = rp[p->infinity | q->infinity]->x; + y = rp[p->infinity | q->infinity]->y; + z = rp[p->infinity | q->infinity]->z; + + ap[0] = p; + ap[1] = q; + for (i=0; i<8; i++) + r->x[i] = ap[p->infinity]->x[i]; + for (i=0; i<8; i++) + r->y[i] = ap[p->infinity]->y[i]; + for (i=0; i<8; i++) + r->z[i] = ap[p->infinity]->z[i]; + r->infinity = ap[p->infinity]->infinity; + + /* U2 = X2*Z1^2 */ + sp_256_mont_sqr_8(t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t4, t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t2, t2, q->x, p256_mod, p256_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_256_mont_mul_8(t4, t4, q->y, p256_mod, p256_mp_mod); + /* H = U2 - X1 */ + sp_256_mont_sub_8(t2, t2, x, p256_mod); + /* R = S2 - Y1 */ + sp_256_mont_sub_8(t4, t4, y, p256_mod); + /* Z3 = H*Z1 */ + sp_256_mont_mul_8(z, z, t2, p256_mod, p256_mp_mod); + /* X3 = R^2 - H^3 - 2*X1*H^2 */ + sp_256_mont_sqr_8(t1, t4, p256_mod, p256_mp_mod); + sp_256_mont_sqr_8(t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t3, x, t5, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t5, t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_sub_8(x, t1, t5, p256_mod); + sp_256_mont_dbl_8(t1, t3, p256_mod); + sp_256_mont_sub_8(x, x, t1, p256_mod); + /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */ + sp_256_mont_sub_8(t3, t3, x, p256_mod); + sp_256_mont_mul_8(t3, t3, t4, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t5, t5, y, p256_mod, p256_mp_mod); + sp_256_mont_sub_8(y, t3, t5, p256_mod); + } +} + +#ifdef WOLFSSL_SP_SMALL +#ifdef FP_ECC +/* Convert the projective point to affine. + * Ordinates are in Montgomery form. + * + * a Point to convert. + * t Temprorary data. + */ +static void sp_256_proj_to_affine_8(sp_point* a, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 8; + sp_digit* tmp = t + 4 * 8; + + sp_256_mont_inv_8(t1, a->z, tmp); + + sp_256_mont_sqr_8(t2, t1, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t1, t2, t1, p256_mod, p256_mp_mod); + + sp_256_mont_mul_8(a->x, a->x, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(a->y, a->y, t1, p256_mod, p256_mp_mod); + XMEMCPY(a->z, p256_norm_mod, sizeof(p256_norm_mod)); +} + +/* Generate the pre-computed table of points for the base point. + * + * a The base point. + * table Place to store generated point data. + * tmp Temprorary data. + * heap Heap to use for allocation. + */ +static int sp_256_gen_stripe_table_8(sp_point* a, + sp_table_entry* table, sp_digit* tmp, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point td, s1d, s2d; +#endif + sp_point* t; + sp_point* s1 = NULL; + sp_point* s2 = NULL; + int i, j; + int err; + + (void)heap; + + err = sp_ecc_point_new(heap, td, t); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, s1d, s1); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, s2d, s2); + + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_8(t->x, a->x, p256_mod); + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_8(t->y, a->y, p256_mod); + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_8(t->z, a->z, p256_mod); + if (err == MP_OKAY) { + t->infinity = 0; + sp_256_proj_to_affine_8(t, tmp); + + XMEMCPY(s1->z, p256_norm_mod, sizeof(p256_norm_mod)); + s1->infinity = 0; + XMEMCPY(s2->z, p256_norm_mod, sizeof(p256_norm_mod)); + s2->infinity = 0; + + /* table[0] = {0, 0, infinity} */ + XMEMSET(&table[0], 0, sizeof(sp_table_entry)); + table[0].infinity = 1; + /* table[1] = Affine version of 'a' in Montgomery form */ + XMEMCPY(table[1].x, t->x, sizeof(table->x)); + XMEMCPY(table[1].y, t->y, sizeof(table->y)); + table[1].infinity = 0; + + for (i=1; i<4; i++) { + sp_256_proj_point_dbl_n_8(t, t, 64, tmp); + sp_256_proj_to_affine_8(t, tmp); + XMEMCPY(table[1<x, sizeof(table->x)); + XMEMCPY(table[1<y, sizeof(table->y)); + table[1<x, table[1<x)); + XMEMCPY(s1->y, table[1<y)); + for (j=(1<x, table[j-(1<x)); + XMEMCPY(s2->y, table[j-(1<y)); + sp_256_proj_point_add_qz1_8(t, s1, s2, tmp); + sp_256_proj_to_affine_8(t, tmp); + XMEMCPY(table[j].x, t->x, sizeof(table->x)); + XMEMCPY(table[j].y, t->y, sizeof(table->y)); + table[j].infinity = 0; + } + } + } + + sp_ecc_point_free(s2, 0, heap); + sp_ecc_point_free(s1, 0, heap); + sp_ecc_point_free( t, 0, heap); + + return err; +} + +#endif /* FP_ECC */ +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_stripe_8(sp_point* r, sp_point* g, + sp_table_entry* table, sp_digit* k, int map, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point rtd; + sp_point pd; + sp_digit td[2 * 8 * 5]; +#endif + sp_point* rt; + sp_point* p = NULL; + sp_digit* t; + int i, j; + int y, x; + int err; + + (void)g; + (void)heap; + + err = sp_ecc_point_new(heap, rtd, rt); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 5, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#else + t = td; +#endif + + if (err == MP_OKAY) { + XMEMCPY(p->z, p256_norm_mod, sizeof(p256_norm_mod)); + XMEMCPY(rt->z, p256_norm_mod, sizeof(p256_norm_mod)); + + y = 0; + for (j=0,x=63; j<4; j++,x+=64) + y |= ((k[x / 32] >> (x % 32)) & 1) << j; + XMEMCPY(rt->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(rt->y, table[y].y, sizeof(table[y].y)); + rt->infinity = table[y].infinity; + for (i=62; i>=0; i--) { + y = 0; + for (j=0,x=i; j<4; j++,x+=64) + y |= ((k[x / 32] >> (x % 32)) & 1) << j; + + sp_256_proj_point_dbl_8(rt, rt, t); + XMEMCPY(p->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(p->y, table[y].y, sizeof(table[y].y)); + p->infinity = table[y].infinity; + sp_256_proj_point_add_qz1_8(rt, rt, p, t); + } + + if (map) + sp_256_map_8(r, rt, t); + else + XMEMCPY(r, rt, sizeof(sp_point)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p, 0, heap); + sp_ecc_point_free(rt, 0, heap); + + return err; +} + +#ifdef FP_ECC +#ifndef FP_ENTRIES + #define FP_ENTRIES 16 +#endif + +typedef struct sp_cache_t { + sp_digit x[8]; + sp_digit y[8]; + sp_table_entry table[16]; + uint32_t cnt; + int set; +} sp_cache_t; + +static THREAD_LS_T sp_cache_t sp_cache[FP_ENTRIES]; +static THREAD_LS_T int sp_cache_last = -1; +static THREAD_LS_T int sp_cache_inited = 0; + +#ifndef HAVE_THREAD_LS + static volatile int initCacheMutex = 0; + static wolfSSL_Mutex sp_cache_lock; +#endif + +static void sp_ecc_get_cache(sp_point* g, sp_cache_t** cache) +{ + int i, j; + uint32_t least; + + if (sp_cache_inited == 0) { + for (i=0; ix, sp_cache[i].x) & + sp_256_cmp_equal_8(g->y, sp_cache[i].y)) { + sp_cache[i].cnt++; + break; + } + } + + /* No match. */ + if (i == FP_ENTRIES) { + /* Find empty entry. */ + i = (sp_cache_last + 1) % FP_ENTRIES; + for (; i != sp_cache_last; i=(i+1)%FP_ENTRIES) { + if (!sp_cache[i].set) { + break; + } + } + + /* Evict least used. */ + if (i == sp_cache_last) { + least = sp_cache[0].cnt; + for (j=1; jx, sizeof(sp_cache[i].x)); + XMEMCPY(sp_cache[i].y, g->y, sizeof(sp_cache[i].y)); + sp_cache[i].set = 1; + sp_cache[i].cnt = 1; + } + + *cache = &sp_cache[i]; + sp_cache_last = i; +} +#endif /* FP_ECC */ + +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_8(sp_point* r, sp_point* g, sp_digit* k, + int map, void* heap) +{ +#ifndef FP_ECC + return sp_256_ecc_mulmod_fast_8(r, g, k, map, heap); +#else + sp_digit tmp[2 * 8 * 5]; + sp_cache_t* cache; + int err = MP_OKAY; + +#ifndef HAVE_THREAD_LS + if (initCacheMutex == 0) { + wc_InitMutex(&sp_cache_lock); + initCacheMutex = 1; + } + if (wc_LockMutex(&sp_cache_lock) != 0) + err = BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + if (err == MP_OKAY) { + sp_ecc_get_cache(g, &cache); + if (cache->cnt == 2) + sp_256_gen_stripe_table_8(g, cache->table, tmp, heap); + +#ifndef HAVE_THREAD_LS + wc_UnLockMutex(&sp_cache_lock); +#endif /* HAVE_THREAD_LS */ + + if (cache->cnt < 2) { + err = sp_256_ecc_mulmod_fast_8(r, g, k, map, heap); + } + else { + err = sp_256_ecc_mulmod_stripe_8(r, g, cache->table, k, + map, heap); + } + } + + return err; +#endif +} + +#else +#ifdef FP_ECC +/* Generate the pre-computed table of points for the base point. + * + * a The base point. + * table Place to store generated point data. + * tmp Temprorary data. + * heap Heap to use for allocation. + */ +static int sp_256_gen_stripe_table_8(sp_point* a, + sp_table_entry* table, sp_digit* tmp, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point td, s1d, s2d; +#endif + sp_point* t; + sp_point* s1 = NULL; + sp_point* s2 = NULL; + int i, j; + int err; + + (void)heap; + + err = sp_ecc_point_new(heap, td, t); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, s1d, s1); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, s2d, s2); + + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_8(t->x, a->x, p256_mod); + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_8(t->y, a->y, p256_mod); + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_8(t->z, a->z, p256_mod); + if (err == MP_OKAY) { + t->infinity = 0; + sp_256_proj_to_affine_8(t, tmp); + + XMEMCPY(s1->z, p256_norm_mod, sizeof(p256_norm_mod)); + s1->infinity = 0; + XMEMCPY(s2->z, p256_norm_mod, sizeof(p256_norm_mod)); + s2->infinity = 0; + + /* table[0] = {0, 0, infinity} */ + XMEMSET(&table[0], 0, sizeof(sp_table_entry)); + table[0].infinity = 1; + /* table[1] = Affine version of 'a' in Montgomery form */ + XMEMCPY(table[1].x, t->x, sizeof(table->x)); + XMEMCPY(table[1].y, t->y, sizeof(table->y)); + table[1].infinity = 0; + + for (i=1; i<8; i++) { + sp_256_proj_point_dbl_n_8(t, t, 32, tmp); + sp_256_proj_to_affine_8(t, tmp); + XMEMCPY(table[1<x, sizeof(table->x)); + XMEMCPY(table[1<y, sizeof(table->y)); + table[1<x, table[1<x)); + XMEMCPY(s1->y, table[1<y)); + for (j=(1<x, table[j-(1<x)); + XMEMCPY(s2->y, table[j-(1<y)); + sp_256_proj_point_add_qz1_8(t, s1, s2, tmp); + sp_256_proj_to_affine_8(t, tmp); + XMEMCPY(table[j].x, t->x, sizeof(table->x)); + XMEMCPY(table[j].y, t->y, sizeof(table->y)); + table[j].infinity = 0; + } + } + } + + sp_ecc_point_free(s2, 0, heap); + sp_ecc_point_free(s1, 0, heap); + sp_ecc_point_free( t, 0, heap); + + return err; +} + +#endif /* FP_ECC */ +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_stripe_8(sp_point* r, sp_point* g, + sp_table_entry* table, sp_digit* k, int map, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point rtd; + sp_point pd; + sp_digit td[2 * 8 * 5]; +#endif + sp_point* rt; + sp_point* p = NULL; + sp_digit* t; + int i, j; + int y, x; + int err; + + (void)g; + (void)heap; + + err = sp_ecc_point_new(heap, rtd, rt); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 5, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#else + t = td; +#endif + + if (err == MP_OKAY) { + XMEMCPY(p->z, p256_norm_mod, sizeof(p256_norm_mod)); + XMEMCPY(rt->z, p256_norm_mod, sizeof(p256_norm_mod)); + + y = 0; + for (j=0,x=31; j<8; j++,x+=32) + y |= ((k[x / 32] >> (x % 32)) & 1) << j; + XMEMCPY(rt->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(rt->y, table[y].y, sizeof(table[y].y)); + rt->infinity = table[y].infinity; + for (i=30; i>=0; i--) { + y = 0; + for (j=0,x=i; j<8; j++,x+=32) + y |= ((k[x / 32] >> (x % 32)) & 1) << j; + + sp_256_proj_point_dbl_8(rt, rt, t); + XMEMCPY(p->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(p->y, table[y].y, sizeof(table[y].y)); + p->infinity = table[y].infinity; + sp_256_proj_point_add_qz1_8(rt, rt, p, t); + } + + if (map) + sp_256_map_8(r, rt, t); + else + XMEMCPY(r, rt, sizeof(sp_point)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p, 0, heap); + sp_ecc_point_free(rt, 0, heap); + + return err; +} + +#ifdef FP_ECC +#ifndef FP_ENTRIES + #define FP_ENTRIES 16 +#endif + +typedef struct sp_cache_t { + sp_digit x[8]; + sp_digit y[8]; + sp_table_entry table[256]; + uint32_t cnt; + int set; +} sp_cache_t; + +static THREAD_LS_T sp_cache_t sp_cache[FP_ENTRIES]; +static THREAD_LS_T int sp_cache_last = -1; +static THREAD_LS_T int sp_cache_inited = 0; + +#ifndef HAVE_THREAD_LS + static volatile int initCacheMutex = 0; + static wolfSSL_Mutex sp_cache_lock; +#endif + +static void sp_ecc_get_cache(sp_point* g, sp_cache_t** cache) +{ + int i, j; + uint32_t least; + + if (sp_cache_inited == 0) { + for (i=0; ix, sp_cache[i].x) & + sp_256_cmp_equal_8(g->y, sp_cache[i].y)) { + sp_cache[i].cnt++; + break; + } + } + + /* No match. */ + if (i == FP_ENTRIES) { + /* Find empty entry. */ + i = (sp_cache_last + 1) % FP_ENTRIES; + for (; i != sp_cache_last; i=(i+1)%FP_ENTRIES) { + if (!sp_cache[i].set) { + break; + } + } + + /* Evict least used. */ + if (i == sp_cache_last) { + least = sp_cache[0].cnt; + for (j=1; jx, sizeof(sp_cache[i].x)); + XMEMCPY(sp_cache[i].y, g->y, sizeof(sp_cache[i].y)); + sp_cache[i].set = 1; + sp_cache[i].cnt = 1; + } + + *cache = &sp_cache[i]; + sp_cache_last = i; +} +#endif /* FP_ECC */ + +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_8(sp_point* r, sp_point* g, sp_digit* k, + int map, void* heap) +{ +#ifndef FP_ECC + return sp_256_ecc_mulmod_fast_8(r, g, k, map, heap); +#else + sp_digit tmp[2 * 8 * 5]; + sp_cache_t* cache; + int err = MP_OKAY; + +#ifndef HAVE_THREAD_LS + if (initCacheMutex == 0) { + wc_InitMutex(&sp_cache_lock); + initCacheMutex = 1; + } + if (wc_LockMutex(&sp_cache_lock) != 0) + err = BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + if (err == MP_OKAY) { + sp_ecc_get_cache(g, &cache); + if (cache->cnt == 2) + sp_256_gen_stripe_table_8(g, cache->table, tmp, heap); + +#ifndef HAVE_THREAD_LS + wc_UnLockMutex(&sp_cache_lock); +#endif /* HAVE_THREAD_LS */ + + if (cache->cnt < 2) { + err = sp_256_ecc_mulmod_fast_8(r, g, k, map, heap); + } + else { + err = sp_256_ecc_mulmod_stripe_8(r, g, cache->table, k, + map, heap); + } + } + + return err; +#endif +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * km Scalar to multiply by. + * p Point to multiply. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_256(mp_int* km, ecc_point* gm, ecc_point* r, int map, + void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point p; + sp_digit kd[8]; +#endif + sp_point* point; + sp_digit* k = NULL; + int err = MP_OKAY; + + err = sp_ecc_point_new(heap, p, point); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + if (err == MP_OKAY) { + sp_256_from_mp(k, 8, km); + sp_256_point_from_ecc_point_8(point, gm); + + err = sp_256_ecc_mulmod_8(point, point, k, map, heap); + } + if (err == MP_OKAY) + err = sp_256_point_to_ecc_point_8(point, r); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(point, 0, heap); + + return err; +} + +#ifdef WOLFSSL_SP_SMALL +static sp_table_entry p256_table[16] = { + /* 0 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 */ + { { 0x18a9143c,0x79e730d4,0x5fedb601,0x75ba95fc,0x77622510,0x79fb732b, + 0xa53755c6,0x18905f76 }, + { 0xce95560a,0xddf25357,0xba19e45c,0x8b4ab8e4,0xdd21f325,0xd2e88688, + 0x25885d85,0x8571ff18 }, + 0 }, + /* 2 */ + { { 0x16a0d2bb,0x4f922fc5,0x1a623499,0x0d5cc16c,0x57c62c8b,0x9241cf3a, + 0xfd1b667f,0x2f5e6961 }, + { 0xf5a01797,0x5c15c70b,0x60956192,0x3d20b44d,0x071fdb52,0x04911b37, + 0x8d6f0f7b,0xf648f916 }, + 0 }, + /* 3 */ + { { 0xe137bbbc,0x9e566847,0x8a6a0bec,0xe434469e,0x79d73463,0xb1c42761, + 0x133d0015,0x5abe0285 }, + { 0xc04c7dab,0x92aa837c,0x43260c07,0x573d9f4c,0x78e6cc37,0x0c931562, + 0x6b6f7383,0x94bb725b }, + 0 }, + /* 4 */ + { { 0xbfe20925,0x62a8c244,0x8fdce867,0x91c19ac3,0xdd387063,0x5a96a5d5, + 0x21d324f6,0x61d587d4 }, + { 0xa37173ea,0xe87673a2,0x53778b65,0x23848008,0x05bab43e,0x10f8441e, + 0x4621efbe,0xfa11fe12 }, + 0 }, + /* 5 */ + { { 0x2cb19ffd,0x1c891f2b,0xb1923c23,0x01ba8d5b,0x8ac5ca8e,0xb6d03d67, + 0x1f13bedc,0x586eb04c }, + { 0x27e8ed09,0x0c35c6e5,0x1819ede2,0x1e81a33c,0x56c652fa,0x278fd6c0, + 0x70864f11,0x19d5ac08 }, + 0 }, + /* 6 */ + { { 0xd2b533d5,0x62577734,0xa1bdddc0,0x673b8af6,0xa79ec293,0x577e7c9a, + 0xc3b266b1,0xbb6de651 }, + { 0xb65259b3,0xe7e9303a,0xd03a7480,0xd6a0afd3,0x9b3cfc27,0xc5ac83d1, + 0x5d18b99b,0x60b4619a }, + 0 }, + /* 7 */ + { { 0x1ae5aa1c,0xbd6a38e1,0x49e73658,0xb8b7652b,0xee5f87ed,0x0b130014, + 0xaeebffcd,0x9d0f27b2 }, + { 0x7a730a55,0xca924631,0xddbbc83a,0x9c955b2f,0xac019a71,0x07c1dfe0, + 0x356ec48d,0x244a566d }, + 0 }, + /* 8 */ + { { 0xf4f8b16a,0x56f8410e,0xc47b266a,0x97241afe,0x6d9c87c1,0x0a406b8e, + 0xcd42ab1b,0x803f3e02 }, + { 0x04dbec69,0x7f0309a8,0x3bbad05f,0xa83b85f7,0xad8e197f,0xc6097273, + 0x5067adc1,0xc097440e }, + 0 }, + /* 9 */ + { { 0xc379ab34,0x846a56f2,0x841df8d1,0xa8ee068b,0x176c68ef,0x20314459, + 0x915f1f30,0xf1af32d5 }, + { 0x5d75bd50,0x99c37531,0xf72f67bc,0x837cffba,0x48d7723f,0x0613a418, + 0xe2d41c8b,0x23d0f130 }, + 0 }, + /* 10 */ + { { 0xd5be5a2b,0xed93e225,0x5934f3c6,0x6fe79983,0x22626ffc,0x43140926, + 0x7990216a,0x50bbb4d9 }, + { 0xe57ec63e,0x378191c6,0x181dcdb2,0x65422c40,0x0236e0f6,0x41a8099b, + 0x01fe49c3,0x2b100118 }, + 0 }, + /* 11 */ + { { 0x9b391593,0xfc68b5c5,0x598270fc,0xc385f5a2,0xd19adcbb,0x7144f3aa, + 0x83fbae0c,0xdd558999 }, + { 0x74b82ff4,0x93b88b8e,0x71e734c9,0xd2e03c40,0x43c0322a,0x9a7a9eaf, + 0x149d6041,0xe6e4c551 }, + 0 }, + /* 12 */ + { { 0x80ec21fe,0x5fe14bfe,0xc255be82,0xf6ce116a,0x2f4a5d67,0x98bc5a07, + 0xdb7e63af,0xfad27148 }, + { 0x29ab05b3,0x90c0b6ac,0x4e251ae6,0x37a9a83c,0xc2aade7d,0x0a7dc875, + 0x9f0e1a84,0x77387de3 }, + 0 }, + /* 13 */ + { { 0xa56c0dd7,0x1e9ecc49,0x46086c74,0xa5cffcd8,0xf505aece,0x8f7a1408, + 0xbef0c47e,0xb37b85c0 }, + { 0xcc0e6a8f,0x3596b6e4,0x6b388f23,0xfd6d4bbf,0xc39cef4e,0xaba453fa, + 0xf9f628d5,0x9c135ac8 }, + 0 }, + /* 14 */ + { { 0x95c8f8be,0x0a1c7294,0x3bf362bf,0x2961c480,0xdf63d4ac,0x9e418403, + 0x91ece900,0xc109f9cb }, + { 0x58945705,0xc2d095d0,0xddeb85c0,0xb9083d96,0x7a40449b,0x84692b8d, + 0x2eee1ee1,0x9bc3344f }, + 0 }, + /* 15 */ + { { 0x42913074,0x0d5ae356,0x48a542b1,0x55491b27,0xb310732a,0x469ca665, + 0x5f1a4cc1,0x29591d52 }, + { 0xb84f983f,0xe76f5b6b,0x9f5f84e1,0xbe7eef41,0x80baa189,0x1200d496, + 0x18ef332c,0x6376551f }, + 0 }, +}; + +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_base_8(sp_point* r, sp_digit* k, + int map, void* heap) +{ + return sp_256_ecc_mulmod_stripe_8(r, &p256_base, p256_table, + k, map, heap); +} + +#else +static sp_table_entry p256_table[256] = { + /* 0 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 */ + { { 0x18a9143c,0x79e730d4,0x5fedb601,0x75ba95fc,0x77622510,0x79fb732b, + 0xa53755c6,0x18905f76 }, + { 0xce95560a,0xddf25357,0xba19e45c,0x8b4ab8e4,0xdd21f325,0xd2e88688, + 0x25885d85,0x8571ff18 }, + 0 }, + /* 2 */ + { { 0x4147519a,0x20288602,0x26b372f0,0xd0981eac,0xa785ebc8,0xa9d4a7ca, + 0xdbdf58e9,0xd953c50d }, + { 0xfd590f8f,0x9d6361cc,0x44e6c917,0x72e9626b,0x22eb64cf,0x7fd96110, + 0x9eb288f3,0x863ebb7e }, + 0 }, + /* 3 */ + { { 0x5cdb6485,0x7856b623,0x2f0a2f97,0x808f0ea2,0x4f7e300b,0x3e68d954, + 0xb5ff80a0,0x00076055 }, + { 0x838d2010,0x7634eb9b,0x3243708a,0x54014fbb,0x842a6606,0xe0e47d39, + 0x34373ee0,0x83087761 }, + 0 }, + /* 4 */ + { { 0x16a0d2bb,0x4f922fc5,0x1a623499,0x0d5cc16c,0x57c62c8b,0x9241cf3a, + 0xfd1b667f,0x2f5e6961 }, + { 0xf5a01797,0x5c15c70b,0x60956192,0x3d20b44d,0x071fdb52,0x04911b37, + 0x8d6f0f7b,0xf648f916 }, + 0 }, + /* 5 */ + { { 0xe137bbbc,0x9e566847,0x8a6a0bec,0xe434469e,0x79d73463,0xb1c42761, + 0x133d0015,0x5abe0285 }, + { 0xc04c7dab,0x92aa837c,0x43260c07,0x573d9f4c,0x78e6cc37,0x0c931562, + 0x6b6f7383,0x94bb725b }, + 0 }, + /* 6 */ + { { 0x720f141c,0xbbf9b48f,0x2df5bc74,0x6199b3cd,0x411045c4,0xdc3f6129, + 0x2f7dc4ef,0xcdd6bbcb }, + { 0xeaf436fd,0xcca6700b,0xb99326be,0x6f647f6d,0x014f2522,0x0c0fa792, + 0x4bdae5f6,0xa361bebd }, + 0 }, + /* 7 */ + { { 0x597c13c7,0x28aa2558,0x50b7c3e1,0xc38d635f,0xf3c09d1d,0x07039aec, + 0xc4b5292c,0xba12ca09 }, + { 0x59f91dfd,0x9e408fa4,0xceea07fb,0x3af43b66,0x9d780b29,0x1eceb089, + 0x701fef4b,0x53ebb99d }, + 0 }, + /* 8 */ + { { 0xb0e63d34,0x4fe7ee31,0xa9e54fab,0xf4600572,0xd5e7b5a4,0xc0493334, + 0x06d54831,0x8589fb92 }, + { 0x6583553a,0xaa70f5cc,0xe25649e5,0x0879094a,0x10044652,0xcc904507, + 0x02541c4f,0xebb0696d }, + 0 }, + /* 9 */ + { { 0xac1647c5,0x4616ca15,0xc4cf5799,0xb8127d47,0x764dfbac,0xdc666aa3, + 0xd1b27da3,0xeb2820cb }, + { 0x6a87e008,0x9406f8d8,0x922378f3,0xd87dfa9d,0x80ccecb2,0x56ed2e42, + 0x55a7da1d,0x1f28289b }, + 0 }, + /* 10 */ + { { 0x3b89da99,0xabbaa0c0,0xb8284022,0xa6f2d79e,0xb81c05e8,0x27847862, + 0x05e54d63,0x337a4b59 }, + { 0x21f7794a,0x3c67500d,0x7d6d7f61,0x207005b7,0x04cfd6e8,0x0a5a3781, + 0xf4c2fbd6,0x0d65e0d5 }, + 0 }, + /* 11 */ + { { 0xb5275d38,0xd9d09bbe,0x0be0a358,0x4268a745,0x973eb265,0xf0762ff4, + 0x52f4a232,0xc23da242 }, + { 0x0b94520c,0x5da1b84f,0xb05bd78e,0x09666763,0x94d29ea1,0x3a4dcb86, + 0xc790cff1,0x19de3b8c }, + 0 }, + /* 12 */ + { { 0x26c5fe04,0x183a716c,0x3bba1bdb,0x3b28de0b,0xa4cb712c,0x7432c586, + 0x91fccbfd,0xe34dcbd4 }, + { 0xaaa58403,0xb408d46b,0x82e97a53,0x9a697486,0x36aaa8af,0x9e390127, + 0x7b4e0f7f,0xe7641f44 }, + 0 }, + /* 13 */ + { { 0xdf64ba59,0x7d753941,0x0b0242fc,0xd33f10ec,0xa1581859,0x4f06dfc6, + 0x052a57bf,0x4a12df57 }, + { 0x9439dbd0,0xbfa6338f,0xbde53e1f,0xd3c24bd4,0x21f1b314,0xfd5e4ffa, + 0xbb5bea46,0x6af5aa93 }, + 0 }, + /* 14 */ + { { 0x10c91999,0xda10b699,0x2a580491,0x0a24b440,0xb8cc2090,0x3e0094b4, + 0x66a44013,0x5fe3475a }, + { 0xf93e7b4b,0xb0f8cabd,0x7c23f91a,0x292b501a,0xcd1e6263,0x42e889ae, + 0xecfea916,0xb544e308 }, + 0 }, + /* 15 */ + { { 0x16ddfdce,0x6478c6e9,0xf89179e6,0x2c329166,0x4d4e67e1,0x4e8d6e76, + 0xa6b0c20b,0xe0b6b2bd }, + { 0xbb7efb57,0x0d312df2,0x790c4007,0x1aac0dde,0x679bc944,0xf90336ad, + 0x25a63774,0x71c023de }, + 0 }, + /* 16 */ + { { 0xbfe20925,0x62a8c244,0x8fdce867,0x91c19ac3,0xdd387063,0x5a96a5d5, + 0x21d324f6,0x61d587d4 }, + { 0xa37173ea,0xe87673a2,0x53778b65,0x23848008,0x05bab43e,0x10f8441e, + 0x4621efbe,0xfa11fe12 }, + 0 }, + /* 17 */ + { { 0x2cb19ffd,0x1c891f2b,0xb1923c23,0x01ba8d5b,0x8ac5ca8e,0xb6d03d67, + 0x1f13bedc,0x586eb04c }, + { 0x27e8ed09,0x0c35c6e5,0x1819ede2,0x1e81a33c,0x56c652fa,0x278fd6c0, + 0x70864f11,0x19d5ac08 }, + 0 }, + /* 18 */ + { { 0x309a4e1f,0x1e99f581,0xe9270074,0xab7de71b,0xefd28d20,0x26a5ef0b, + 0x7f9c563f,0xe7c0073f }, + { 0x0ef59f76,0x1f6d663a,0x20fcb050,0x669b3b54,0x7a6602d4,0xc08c1f7a, + 0xc65b3c0a,0xe08504fe }, + 0 }, + /* 19 */ + { { 0xa031b3ca,0xf098f68d,0xe6da6d66,0x6d1cab9e,0x94f246e8,0x5bfd81fa, + 0x5b0996b4,0x78f01882 }, + { 0x3a25787f,0xb7eefde4,0x1dccac9b,0x8016f80d,0xb35bfc36,0x0cea4877, + 0x7e94747a,0x43a773b8 }, + 0 }, + /* 20 */ + { { 0xd2b533d5,0x62577734,0xa1bdddc0,0x673b8af6,0xa79ec293,0x577e7c9a, + 0xc3b266b1,0xbb6de651 }, + { 0xb65259b3,0xe7e9303a,0xd03a7480,0xd6a0afd3,0x9b3cfc27,0xc5ac83d1, + 0x5d18b99b,0x60b4619a }, + 0 }, + /* 21 */ + { { 0x1ae5aa1c,0xbd6a38e1,0x49e73658,0xb8b7652b,0xee5f87ed,0x0b130014, + 0xaeebffcd,0x9d0f27b2 }, + { 0x7a730a55,0xca924631,0xddbbc83a,0x9c955b2f,0xac019a71,0x07c1dfe0, + 0x356ec48d,0x244a566d }, + 0 }, + /* 22 */ + { { 0xeacf1f96,0x6db0394a,0x024c271c,0x9f2122a9,0x82cbd3b9,0x2626ac1b, + 0x3581ef69,0x45e58c87 }, + { 0xa38f9dbc,0xd3ff479d,0xe888a040,0xa8aaf146,0x46e0bed7,0x945adfb2, + 0xc1e4b7a4,0xc040e21c }, + 0 }, + /* 23 */ + { { 0x6f8117b6,0x847af000,0x73a35433,0x651969ff,0x1d9475eb,0x482b3576, + 0x682c6ec7,0x1cdf5c97 }, + { 0x11f04839,0x7db775b4,0x48de1698,0x7dbeacf4,0xb70b3219,0xb2921dd1, + 0xa92dff3d,0x046755f8 }, + 0 }, + /* 24 */ + { { 0xbce8ffcd,0xcc8ac5d2,0x2fe61a82,0x0d53c48b,0x7202d6c7,0xf6f16172, + 0x3b83a5f3,0x046e5e11 }, + { 0xd8007f01,0xe7b8ff64,0x5af43183,0x7fb1ef12,0x35e1a03c,0x045c5ea6, + 0x303d005b,0x6e0106c3 }, + 0 }, + /* 25 */ + { { 0x88dd73b1,0x48c73584,0x995ed0d9,0x7670708f,0xc56a2ab7,0x38385ea8, + 0xe901cf1f,0x442594ed }, + { 0x12d4b65b,0xf8faa2c9,0x96c90c37,0x94c2343b,0x5e978d1f,0xd326e4a1, + 0x4c2ee68e,0xa796fa51 }, + 0 }, + /* 26 */ + { { 0x823addd7,0x359fb604,0xe56693b3,0x9e2a6183,0x3cbf3c80,0xf885b78e, + 0xc69766e9,0xe4ad2da9 }, + { 0x8e048a61,0x357f7f42,0xc092d9a0,0x082d198c,0xc03ed8ef,0xfc3a1af4, + 0xc37b5143,0xc5e94046 }, + 0 }, + /* 27 */ + { { 0x2be75f9e,0x476a538c,0xcb123a78,0x6fd1a9e8,0xb109c04b,0xd85e4df0, + 0xdb464747,0x63283daf }, + { 0xbaf2df15,0xce728cf7,0x0ad9a7f4,0xe592c455,0xe834bcc3,0xfab226ad, + 0x1981a938,0x68bd19ab }, + 0 }, + /* 28 */ + { { 0x1887d659,0xc08ead51,0xb359305a,0x3374d5f4,0xcfe74fe3,0x96986981, + 0x3c6fdfd6,0x495292f5 }, + { 0x1acec896,0x4a878c9e,0xec5b4484,0xd964b210,0x664d60a7,0x6696f7e2, + 0x26036837,0x0ec7530d }, + 0 }, + /* 29 */ + { { 0xad2687bb,0x2da13a05,0xf32e21fa,0xa1f83b6a,0x1dd4607b,0x390f5ef5, + 0x64863f0b,0x0f6207a6 }, + { 0x0f138233,0xbd67e3bb,0x272aa718,0xdd66b96c,0x26ec88ae,0x8ed00407, + 0x08ed6dcf,0xff0db072 }, + 0 }, + /* 30 */ + { { 0x4c95d553,0x749fa101,0x5d680a8a,0xa44052fd,0xff3b566f,0x183b4317, + 0x88740ea3,0x313b513c }, + { 0x08d11549,0xb402e2ac,0xb4dee21c,0x071ee10b,0x47f2320e,0x26b987dd, + 0x86f19f81,0x2d3abcf9 }, + 0 }, + /* 31 */ + { { 0x815581a2,0x4c288501,0x632211af,0x9a0a6d56,0x0cab2e99,0x19ba7a0f, + 0xded98cdf,0xc036fa10 }, + { 0xc1fbd009,0x29ae08ba,0x06d15816,0x0b68b190,0x9b9e0d8f,0xc2eb3277, + 0xb6d40194,0xa6b2a2c4 }, + 0 }, + /* 32 */ + { { 0x6d3549cf,0xd433e50f,0xfacd665e,0x6f33696f,0xce11fcb4,0x695bfdac, + 0xaf7c9860,0x810ee252 }, + { 0x7159bb2c,0x65450fe1,0x758b357b,0xf7dfbebe,0xd69fea72,0x2b057e74, + 0x92731745,0xd485717a }, + 0 }, + /* 33 */ + { { 0xf0cb5a98,0x11741a8a,0x1f3110bf,0xd3da8f93,0xab382adf,0x1994e2cb, + 0x2f9a604e,0x6a6045a7 }, + { 0xa2b2411d,0x170c0d3f,0x510e96e0,0xbe0eb83e,0x8865b3cc,0x3bcc9f73, + 0xf9e15790,0xd3e45cfa }, + 0 }, + /* 34 */ + { { 0xe83f7669,0xce1f69bb,0x72877d6b,0x09f8ae82,0x3244278d,0x9548ae54, + 0xe3c2c19c,0x207755de }, + { 0x6fef1945,0x87bd61d9,0xb12d28c3,0x18813cef,0x72df64aa,0x9fbcd1d6, + 0x7154b00d,0x48dc5ee5 }, + 0 }, + /* 35 */ + { { 0xf7e5a199,0x123790bf,0x989ccbb7,0xe0efb8cf,0x0a519c79,0xc27a2bfe, + 0xdff6f445,0xf2fb0aed }, + { 0xf0b5025f,0x41c09575,0x40fa9f22,0x550543d7,0x380bfbd0,0x8fa3c8ad, + 0xdb28d525,0xa13e9015 }, + 0 }, + /* 36 */ + { { 0xa2b65cbc,0xf9f7a350,0x2a464226,0x0b04b972,0xe23f07a1,0x265ce241, + 0x1497526f,0x2bf0d6b0 }, + { 0x4b216fb7,0xd3d4dd3f,0xfbdda26a,0xf7d7b867,0x6708505c,0xaeb7b83f, + 0x162fe89f,0x42a94a5a }, + 0 }, + /* 37 */ + { { 0xeaadf191,0x5846ad0b,0x25a268d7,0x0f8a4890,0x494dc1f6,0xe8603050, + 0xc65ede3d,0x2c2dd969 }, + { 0x93849c17,0x6d02171d,0x1da250dd,0x460488ba,0x3c3a5485,0x4810c706, + 0x42c56dbc,0xf437fa1f }, + 0 }, + /* 38 */ + { { 0x4a0f7dab,0x6aa0d714,0x1776e9ac,0x0f049793,0xf5f39786,0x52c0a050, + 0x54707aa8,0xaaf45b33 }, + { 0xc18d364a,0x85e37c33,0x3e497165,0xd40b9b06,0x15ec5444,0xf4171681, + 0xf4f272bc,0xcdf6310d }, + 0 }, + /* 39 */ + { { 0x8ea8b7ef,0x7473c623,0x85bc2287,0x08e93518,0x2bda8e34,0x41956772, + 0xda9e2ff2,0xf0d008ba }, + { 0x2414d3b1,0x2912671d,0xb019ea76,0xb3754985,0x453bcbdb,0x5c61b96d, + 0xca887b8b,0x5bd5c2f5 }, + 0 }, + /* 40 */ + { { 0xf49a3154,0xef0f469e,0x6e2b2e9a,0x3e85a595,0xaa924a9c,0x45aaec1e, + 0xa09e4719,0xaa12dfc8 }, + { 0x4df69f1d,0x26f27227,0xa2ff5e73,0xe0e4c82c,0xb7a9dd44,0xb9d8ce73, + 0xe48ca901,0x6c036e73 }, + 0 }, + /* 41 */ + { { 0x0f6e3138,0x5cfae12a,0x25ad345a,0x6966ef00,0x45672bc5,0x8993c64b, + 0x96afbe24,0x292ff658 }, + { 0x5e213402,0xd5250d44,0x4392c9fe,0xf6580e27,0xda1c72e8,0x097b397f, + 0x311b7276,0x644e0c90 }, + 0 }, + /* 42 */ + { { 0xa47153f0,0xe1e421e1,0x920418c9,0xb86c3b79,0x705d7672,0x93bdce87, + 0xcab79a77,0xf25ae793 }, + { 0x6d869d0c,0x1f3194a3,0x4986c264,0x9d55c882,0x096e945e,0x49fb5ea3, + 0x13db0a3e,0x39b8e653 }, + 0 }, + /* 43 */ + { { 0xb6fd2e59,0x37754200,0x9255c98f,0x35e2c066,0x0e2a5739,0xd9dab21a, + 0x0f19db06,0x39122f2f }, + { 0x03cad53c,0xcfbce1e0,0xe65c17e3,0x225b2c0f,0x9aa13877,0x72baf1d2, + 0xce80ff8d,0x8de80af8 }, + 0 }, + /* 44 */ + { { 0x207bbb76,0xafbea8d9,0x21782758,0x921c7e7c,0x1c0436b1,0xdfa2b74b, + 0x2e368c04,0x87194906 }, + { 0xa3993df5,0xb5f928bb,0xf3b3d26a,0x639d75b5,0x85b55050,0x011aa78a, + 0x5b74fde1,0xfc315e6a }, + 0 }, + /* 45 */ + { { 0xe8d6ecfa,0x561fd41a,0x1aec7f86,0x5f8c44f6,0x4924741d,0x98452a7b, + 0xee389088,0xe6d4a7ad }, + { 0x4593c75d,0x60552ed1,0xdd271162,0x70a70da4,0x7ba2c7db,0xd2aede93, + 0x9be2ae57,0x35dfaf9a }, + 0 }, + /* 46 */ + { { 0xaa736636,0x6b956fcd,0xae2cab7e,0x09f51d97,0x0f349966,0xfb10bf41, + 0x1c830d2b,0x1da5c7d7 }, + { 0x3cce6825,0x5c41e483,0xf9573c3b,0x15ad118f,0xf23036b8,0xa28552c7, + 0xdbf4b9d6,0x7077c0fd }, + 0 }, + /* 47 */ + { { 0x46b9661c,0xbf63ff8d,0x0d2cfd71,0xa1dfd36b,0xa847f8f7,0x0373e140, + 0xe50efe44,0x53a8632e }, + { 0x696d8051,0x0976ff68,0xc74f468a,0xdaec0c95,0x5e4e26bd,0x62994dc3, + 0x34e1fcc1,0x028ca76d }, + 0 }, + /* 48 */ + { { 0xfc9877ee,0xd11d47dc,0x801d0002,0xc8b36210,0x54c260b6,0xd002c117, + 0x6962f046,0x04c17cd8 }, + { 0xb0daddf5,0x6d9bd094,0x24ce55c0,0xbea23575,0x72da03b5,0x663356e6, + 0xfed97474,0xf7ba4de9 }, + 0 }, + /* 49 */ + { { 0xebe1263f,0xd0dbfa34,0x71ae7ce6,0x55763735,0x82a6f523,0xd2440553, + 0x52131c41,0xe31f9600 }, + { 0xea6b6ec6,0xd1bb9216,0x73c2fc44,0x37a1d12e,0x89d0a294,0xc10e7eac, + 0xce34d47b,0xaa3a6259 }, + 0 }, + /* 50 */ + { { 0x36f3dcd3,0xfbcf9df5,0xd2bf7360,0x6ceded50,0xdf504f5b,0x491710fa, + 0x7e79daee,0x2398dd62 }, + { 0x6d09569e,0xcf4705a3,0x5149f769,0xea0619bb,0x35f6034c,0xff9c0377, + 0x1c046210,0x5717f5b2 }, + 0 }, + /* 51 */ + { { 0x21dd895e,0x9fe229c9,0x40c28451,0x8e518500,0x1d637ecd,0xfa13d239, + 0x0e3c28de,0x660a2c56 }, + { 0xd67fcbd0,0x9cca88ae,0x0ea9f096,0xc8472478,0x72e92b4d,0x32b2f481, + 0x4f522453,0x624ee54c }, + 0 }, + /* 52 */ + { { 0xd897eccc,0x09549ce4,0x3f9880aa,0x4d49d1d9,0x043a7c20,0x723c2423, + 0x92bdfbc0,0x4f392afb }, + { 0x7de44fd9,0x6969f8fa,0x57b32156,0xb66cfbe4,0x368ebc3c,0xdb2fa803, + 0xccdb399c,0x8a3e7977 }, + 0 }, + /* 53 */ + { { 0x06c4b125,0xdde1881f,0xf6e3ca8c,0xae34e300,0x5c7a13e9,0xef6999de, + 0x70c24404,0x3888d023 }, + { 0x44f91081,0x76280356,0x5f015504,0x3d9fcf61,0x632cd36e,0x1827edc8, + 0x18102336,0xa5e62e47 }, + 0 }, + /* 54 */ + { { 0x2facd6c8,0x1a825ee3,0x54bcbc66,0x699c6354,0x98df9931,0x0ce3edf7, + 0x466a5adc,0x2c4768e6 }, + { 0x90a64bc9,0xb346ff8c,0xe4779f5c,0x630a6020,0xbc05e884,0xd949d064, + 0xf9e652a0,0x7b5e6441 }, + 0 }, + /* 55 */ + { { 0x1d28444a,0x2169422c,0xbe136a39,0xe996c5d8,0xfb0c7fce,0x2387afe5, + 0x0c8d744a,0xb8af73cb }, + { 0x338b86fd,0x5fde83aa,0xa58a5cff,0xfee3f158,0x20ac9433,0xc9ee8f6f, + 0x7f3f0895,0xa036395f }, + 0 }, + /* 56 */ + { { 0xa10f7770,0x8c73c6bb,0xa12a0e24,0xa6f16d81,0x51bc2b9f,0x100df682, + 0x875fb533,0x4be36b01 }, + { 0x9fb56dbb,0x9226086e,0x07e7a4f8,0x306fef8b,0x66d52f20,0xeeaccc05, + 0x1bdc00c0,0x8cbc9a87 }, + 0 }, + /* 57 */ + { { 0xc0dac4ab,0xe131895c,0x712ff112,0xa874a440,0x6a1cee57,0x6332ae7c, + 0x0c0835f8,0x44e7553e }, + { 0x7734002d,0x6d503fff,0x0b34425c,0x9d35cb8b,0x0e8738b5,0x95f70276, + 0x5eb8fc18,0x470a683a }, + 0 }, + /* 58 */ + { { 0x90513482,0x81b761dc,0x01e9276a,0x0287202a,0x0ce73083,0xcda441ee, + 0xc63dc6ef,0x16410690 }, + { 0x6d06a2ed,0xf5034a06,0x189b100b,0xdd4d7745,0xab8218c9,0xd914ae72, + 0x7abcbb4f,0xd73479fd }, + 0 }, + /* 59 */ + { { 0x5ad4c6e5,0x7edefb16,0x5b06d04d,0x262cf08f,0x8575cb14,0x12ed5bb1, + 0x0771666b,0x816469e3 }, + { 0x561e291e,0xd7ab9d79,0xc1de1661,0xeb9daf22,0x135e0513,0xf49827eb, + 0xf0dd3f9c,0x0a36dd23 }, + 0 }, + /* 60 */ + { { 0x41d5533c,0x098d32c7,0x8684628f,0x7c5f5a9e,0xe349bd11,0x39a228ad, + 0xfdbab118,0xe331dfd6 }, + { 0x6bcc6ed8,0x5100ab68,0xef7a260e,0x7160c3bd,0xbce850d7,0x9063d9a7, + 0x492e3389,0xd3b4782a }, + 0 }, + /* 61 */ + { { 0xf3821f90,0xa149b6e8,0x66eb7aad,0x92edd9ed,0x1a013116,0x0bb66953, + 0x4c86a5bd,0x7281275a }, + { 0xd3ff47e5,0x503858f7,0x61016441,0x5e1616bc,0x7dfd9bb1,0x62b0f11a, + 0xce145059,0x2c062e7e }, + 0 }, + /* 62 */ + { { 0x0159ac2e,0xa76f996f,0xcbdb2713,0x281e7736,0x08e46047,0x2ad6d288, + 0x2c4e7ef1,0x282a35f9 }, + { 0xc0ce5cd2,0x9c354b1e,0x1379c229,0xcf99efc9,0x3e82c11e,0x992caf38, + 0x554d2abd,0xc71cd513 }, + 0 }, + /* 63 */ + { { 0x09b578f4,0x4885de9c,0xe3affa7a,0x1884e258,0x59182f1f,0x8f76b1b7, + 0xcf47f3a3,0xc50f6740 }, + { 0x374b68ea,0xa9c4adf3,0x69965fe2,0xa406f323,0x85a53050,0x2f86a222, + 0x212958dc,0xb9ecb3a7 }, + 0 }, + /* 64 */ + { { 0xf4f8b16a,0x56f8410e,0xc47b266a,0x97241afe,0x6d9c87c1,0x0a406b8e, + 0xcd42ab1b,0x803f3e02 }, + { 0x04dbec69,0x7f0309a8,0x3bbad05f,0xa83b85f7,0xad8e197f,0xc6097273, + 0x5067adc1,0xc097440e }, + 0 }, + /* 65 */ + { { 0xc379ab34,0x846a56f2,0x841df8d1,0xa8ee068b,0x176c68ef,0x20314459, + 0x915f1f30,0xf1af32d5 }, + { 0x5d75bd50,0x99c37531,0xf72f67bc,0x837cffba,0x48d7723f,0x0613a418, + 0xe2d41c8b,0x23d0f130 }, + 0 }, + /* 66 */ + { { 0xf41500d9,0x857ab6ed,0xfcbeada8,0x0d890ae5,0x89725951,0x52fe8648, + 0xc0a3fadd,0xb0288dd6 }, + { 0x650bcb08,0x85320f30,0x695d6e16,0x71af6313,0xb989aa76,0x31f520a7, + 0xf408c8d2,0xffd3724f }, + 0 }, + /* 67 */ + { { 0xb458e6cb,0x53968e64,0x317a5d28,0x992dad20,0x7aa75f56,0x3814ae0b, + 0xd78c26df,0xf5590f4a }, + { 0xcf0ba55a,0x0fc24bd3,0x0c778bae,0x0fc4724a,0x683b674a,0x1ce9864f, + 0xf6f74a20,0x18d6da54 }, + 0 }, + /* 68 */ + { { 0xd5be5a2b,0xed93e225,0x5934f3c6,0x6fe79983,0x22626ffc,0x43140926, + 0x7990216a,0x50bbb4d9 }, + { 0xe57ec63e,0x378191c6,0x181dcdb2,0x65422c40,0x0236e0f6,0x41a8099b, + 0x01fe49c3,0x2b100118 }, + 0 }, + /* 69 */ + { { 0x9b391593,0xfc68b5c5,0x598270fc,0xc385f5a2,0xd19adcbb,0x7144f3aa, + 0x83fbae0c,0xdd558999 }, + { 0x74b82ff4,0x93b88b8e,0x71e734c9,0xd2e03c40,0x43c0322a,0x9a7a9eaf, + 0x149d6041,0xe6e4c551 }, + 0 }, + /* 70 */ + { { 0x1e9af288,0x55f655bb,0xf7ada931,0x647e1a64,0xcb2820e5,0x43697e4b, + 0x07ed56ff,0x51e00db1 }, + { 0x771c327e,0x43d169b8,0x4a96c2ad,0x29cdb20b,0x3deb4779,0xc07d51f5, + 0x49829177,0xe22f4241 }, + 0 }, + /* 71 */ + { { 0x635f1abb,0xcd45e8f4,0x68538874,0x7edc0cb5,0xb5a8034d,0xc9472c1f, + 0x52dc48c9,0xf709373d }, + { 0xa8af30d6,0x401966bb,0xf137b69c,0x95bf5f4a,0x9361c47e,0x3966162a, + 0xe7275b11,0xbd52d288 }, + 0 }, + /* 72 */ + { { 0x9c5fa877,0xab155c7a,0x7d3a3d48,0x17dad672,0x73d189d8,0x43f43f9e, + 0xc8aa77a6,0xa0d0f8e4 }, + { 0xcc94f92d,0x0bbeafd8,0x0c4ddb3a,0xd818c8be,0xb82eba14,0x22cc65f8, + 0x946d6a00,0xa56c78c7 }, + 0 }, + /* 73 */ + { { 0x0dd09529,0x2962391b,0x3daddfcf,0x803e0ea6,0x5b5bf481,0x2c77351f, + 0x731a367a,0xd8befdf8 }, + { 0xfc0157f4,0xab919d42,0xfec8e650,0xf51caed7,0x02d48b0a,0xcdf9cb40, + 0xce9f6478,0x854a68a5 }, + 0 }, + /* 74 */ + { { 0x63506ea5,0xdc35f67b,0xa4fe0d66,0x9286c489,0xfe95cd4d,0x3f101d3b, + 0x98846a95,0x5cacea0b }, + { 0x9ceac44d,0xa90df60c,0x354d1c3a,0x3db29af4,0xad5dbabe,0x08dd3de8, + 0x35e4efa9,0xe4982d12 }, + 0 }, + /* 75 */ + { { 0xc34cd55e,0x23104a22,0x2680d132,0x58695bb3,0x1fa1d943,0xfb345afa, + 0x16b20499,0x8046b7f6 }, + { 0x38e7d098,0xb533581e,0xf46f0b70,0xd7f61e8d,0x44cb78c4,0x30dea9ea, + 0x9082af55,0xeb17ca7b }, + 0 }, + /* 76 */ + { { 0x76a145b9,0x1751b598,0xc1bc71ec,0xa5cf6b0f,0x392715bb,0xd3e03565, + 0xfab5e131,0x097b00ba }, + { 0x565f69e1,0xaa66c8e9,0xb5be5199,0x77e8f75a,0xda4fd984,0x6033ba11, + 0xafdbcc9e,0xf95c747b }, + 0 }, + /* 77 */ + { { 0xbebae45e,0x558f01d3,0xc4bc6955,0xa8ebe9f0,0xdbc64fc6,0xaeb705b1, + 0x566ed837,0x3512601e }, + { 0xfa1161cd,0x9336f1e1,0x4c65ef87,0x328ab8d5,0x724f21e5,0x4757eee2, + 0x6068ab6b,0x0ef97123 }, + 0 }, + /* 78 */ + { { 0x54ca4226,0x02598cf7,0xf8642c8e,0x5eede138,0x468e1790,0x48963f74, + 0x3b4fbc95,0xfc16d933 }, + { 0xe7c800ca,0xbe96fb31,0x2678adaa,0x13806331,0x6ff3e8b5,0x3d624497, + 0xb95d7a17,0x14ca4af1 }, + 0 }, + /* 79 */ + { { 0xbd2f81d5,0x7a4771ba,0x01f7d196,0x1a5f9d69,0xcad9c907,0xd898bef7, + 0xf59c231d,0x4057b063 }, + { 0x89c05c0a,0xbffd82fe,0x1dc0df85,0xe4911c6f,0xa35a16db,0x3befccae, + 0xf1330b13,0x1c3b5d64 }, + 0 }, + /* 80 */ + { { 0x80ec21fe,0x5fe14bfe,0xc255be82,0xf6ce116a,0x2f4a5d67,0x98bc5a07, + 0xdb7e63af,0xfad27148 }, + { 0x29ab05b3,0x90c0b6ac,0x4e251ae6,0x37a9a83c,0xc2aade7d,0x0a7dc875, + 0x9f0e1a84,0x77387de3 }, + 0 }, + /* 81 */ + { { 0xa56c0dd7,0x1e9ecc49,0x46086c74,0xa5cffcd8,0xf505aece,0x8f7a1408, + 0xbef0c47e,0xb37b85c0 }, + { 0xcc0e6a8f,0x3596b6e4,0x6b388f23,0xfd6d4bbf,0xc39cef4e,0xaba453fa, + 0xf9f628d5,0x9c135ac8 }, + 0 }, + /* 82 */ + { { 0x84e35743,0x32aa3202,0x85a3cdef,0x320d6ab1,0x1df19819,0xb821b176, + 0xc433851f,0x5721361f }, + { 0x71fc9168,0x1f0db36a,0x5e5c403c,0x5f98ba73,0x37bcd8f5,0xf64ca87e, + 0xe6bb11bd,0xdcbac3c9 }, + 0 }, + /* 83 */ + { { 0x4518cbe2,0xf01d9968,0x9c9eb04e,0xd242fc18,0xe47feebf,0x727663c7, + 0x2d626862,0xb8c1c89e }, + { 0xc8e1d569,0x51a58bdd,0xb7d88cd0,0x563809c8,0xf11f31eb,0x26c27fd9, + 0x2f9422d4,0x5d23bbda }, + 0 }, + /* 84 */ + { { 0x95c8f8be,0x0a1c7294,0x3bf362bf,0x2961c480,0xdf63d4ac,0x9e418403, + 0x91ece900,0xc109f9cb }, + { 0x58945705,0xc2d095d0,0xddeb85c0,0xb9083d96,0x7a40449b,0x84692b8d, + 0x2eee1ee1,0x9bc3344f }, + 0 }, + /* 85 */ + { { 0x42913074,0x0d5ae356,0x48a542b1,0x55491b27,0xb310732a,0x469ca665, + 0x5f1a4cc1,0x29591d52 }, + { 0xb84f983f,0xe76f5b6b,0x9f5f84e1,0xbe7eef41,0x80baa189,0x1200d496, + 0x18ef332c,0x6376551f }, + 0 }, + /* 86 */ + { { 0x562976cc,0xbda5f14e,0x0ef12c38,0x22bca3e6,0x6cca9852,0xbbfa3064, + 0x08e2987a,0xbdb79dc8 }, + { 0xcb06a772,0xfd2cb5c9,0xfe536dce,0x38f475aa,0x7c2b5db8,0xc2a3e022, + 0xadd3c14a,0x8ee86001 }, + 0 }, + /* 87 */ + { { 0xa4ade873,0xcbe96981,0xc4fba48c,0x7ee9aa4d,0x5a054ba5,0x2cee2899, + 0x6f77aa4b,0x92e51d7a }, + { 0x7190a34d,0x948bafa8,0xf6bd1ed1,0xd698f75b,0x0caf1144,0xd00ee6e3, + 0x0a56aaaa,0x5182f86f }, + 0 }, + /* 88 */ + { { 0x7a4cc99c,0xfba6212c,0x3e6d9ca1,0xff609b68,0x5ac98c5a,0x5dbb27cb, + 0x4073a6f2,0x91dcab5d }, + { 0x5f575a70,0x01b6cc3d,0x6f8d87fa,0x0cb36139,0x89981736,0x165d4e8c, + 0x97974f2b,0x17a0cedb }, + 0 }, + /* 89 */ + { { 0x076c8d3a,0x38861e2a,0x210f924b,0x701aad39,0x13a835d9,0x94d0eae4, + 0x7f4cdf41,0x2e8ce36c }, + { 0x037a862b,0x91273dab,0x60e4c8fa,0x01ba9bb7,0x33baf2dd,0xf9645388, + 0x34f668f3,0xf4ccc6cb }, + 0 }, + /* 90 */ + { { 0xf1f79687,0x44ef525c,0x92efa815,0x7c595495,0xa5c78d29,0xe1231741, + 0x9a0df3c9,0xac0db488 }, + { 0xdf01747f,0x86bfc711,0xef17df13,0x592b9358,0x5ccb6bb5,0xe5880e4f, + 0x94c974a2,0x95a64a61 }, + 0 }, + /* 91 */ + { { 0xc15a4c93,0x72c1efda,0x82585141,0x40269b73,0x16cb0bad,0x6a8dfb1c, + 0x29210677,0x231e54ba }, + { 0x8ae6d2dc,0xa70df917,0x39112918,0x4d6aa63f,0x5e5b7223,0xf627726b, + 0xd8a731e1,0xab0be032 }, + 0 }, + /* 92 */ + { { 0x8d131f2d,0x097ad0e9,0x3b04f101,0x637f09e3,0xd5e9a748,0x1ac86196, + 0x2cf6a679,0xf1bcc880 }, + { 0xe8daacb4,0x25c69140,0x60f65009,0x3c4e4055,0x477937a6,0x591cc8fc, + 0x5aebb271,0x85169469 }, + 0 }, + /* 93 */ + { { 0xf1dcf593,0xde35c143,0xb018be3b,0x78202b29,0x9bdd9d3d,0xe9cdadc2, + 0xdaad55d8,0x8f67d9d2 }, + { 0x7481ea5f,0x84111656,0xe34c590c,0xe7d2dde9,0x05053fa8,0xffdd43f4, + 0xc0728b5d,0xf84572b9 }, + 0 }, + /* 94 */ + { { 0x97af71c9,0x5e1a7a71,0x7a736565,0xa1449444,0x0e1d5063,0xa1b4ae07, + 0x616b2c19,0xedee2710 }, + { 0x11734121,0xb2f034f5,0x4a25e9f0,0x1cac6e55,0xa40c2ecf,0x8dc148f3, + 0x44ebd7f4,0x9fd27e9b }, + 0 }, + /* 95 */ + { { 0xf6e2cb16,0x3cc7658a,0xfe5919b6,0xe3eb7d2c,0x168d5583,0x5a8c5816, + 0x958ff387,0xa40c2fb6 }, + { 0xfedcc158,0x8c9ec560,0x55f23056,0x7ad804c6,0x9a307e12,0xd9396704, + 0x7dc6decf,0x99bc9bb8 }, + 0 }, + /* 96 */ + { { 0x927dafc6,0x84a9521d,0x5c09cd19,0x52c1fb69,0xf9366dde,0x9d9581a0, + 0xa16d7e64,0x9abe210b }, + { 0x48915220,0x480af84a,0x4dd816c6,0xfa73176a,0x1681ca5a,0xc7d53987, + 0x87f344b0,0x7881c257 }, + 0 }, + /* 97 */ + { { 0xe0bcf3ff,0x93399b51,0x127f74f6,0x0d02cbc5,0xdd01d968,0x8fb465a2, + 0xa30e8940,0x15e6e319 }, + { 0x3e0e05f4,0x646d6e0d,0x43588404,0xfad7bddc,0xc4f850d3,0xbe61c7d1, + 0x191172ce,0x0e55facf }, + 0 }, + /* 98 */ + { { 0xf8787564,0x7e9d9806,0x31e85ce6,0x1a331721,0xb819e8d6,0x6b0158ca, + 0x6fe96577,0xd73d0976 }, + { 0x1eb7206e,0x42483425,0xc618bb42,0xa519290f,0x5e30a520,0x5dcbb859, + 0x8f15a50b,0x9250a374 }, + 0 }, + /* 99 */ + { { 0xbe577410,0xcaff08f8,0x5077a8c6,0xfd408a03,0xec0a63a4,0xf1f63289, + 0xc1cc8c0b,0x77414082 }, + { 0xeb0991cd,0x05a40fa6,0x49fdc296,0xc1ca0866,0xb324fd40,0x3a68a3c7, + 0x12eb20b9,0x8cb04f4d }, + 0 }, + /* 100 */ + { { 0x6906171c,0xb1c2d055,0xb0240c3f,0x9073e9cd,0xd8906841,0xdb8e6b4f, + 0x47123b51,0xe4e429ef }, + { 0x38ec36f4,0x0b8dd53c,0xff4b6a27,0xf9d2dc01,0x879a9a48,0x5d066e07, + 0x3c6e6552,0x37bca2ff }, + 0 }, + /* 101 */ + { { 0xdf562470,0x4cd2e3c7,0xc0964ac9,0x44f272a2,0x80c793be,0x7c6d5df9, + 0x3002b22a,0x59913edc }, + { 0x5750592a,0x7a139a83,0xe783de02,0x99e01d80,0xea05d64f,0xcf8c0375, + 0xb013e226,0x43786e4a }, + 0 }, + /* 102 */ + { { 0x9e56b5a6,0xff32b0ed,0xd9fc68f9,0x0750d9a6,0x597846a7,0xec15e845, + 0xb7e79e7a,0x8638ca98 }, + { 0x0afc24b2,0x2f5ae096,0x4dace8f2,0x05398eaf,0xaecba78f,0x3b765dd0, + 0x7b3aa6f0,0x1ecdd36a }, + 0 }, + /* 103 */ + { { 0x6c5ff2f3,0x5d3acd62,0x2873a978,0xa2d516c0,0xd2110d54,0xad94c9fa, + 0xd459f32d,0xd85d0f85 }, + { 0x10b11da3,0x9f700b8d,0xa78318c4,0xd2c22c30,0x9208decd,0x556988f4, + 0xb4ed3c62,0xa04f19c3 }, + 0 }, + /* 104 */ + { { 0xed7f93bd,0x087924c8,0x392f51f6,0xcb64ac5d,0x821b71af,0x7cae330a, + 0x5c0950b0,0x92b2eeea }, + { 0x85b6e235,0x85ac4c94,0x2936c0f0,0xab2ca4a9,0xe0508891,0x80faa6b3, + 0x5834276c,0x1ee78221 }, + 0 }, + /* 105 */ + { { 0xe63e79f7,0xa60a2e00,0xf399d906,0xf590e7b2,0x6607c09d,0x9021054a, + 0x57a6e150,0xf3f2ced8 }, + { 0xf10d9b55,0x200510f3,0xd8642648,0x9d2fcfac,0xe8bd0e7c,0xe5631aa7, + 0x3da3e210,0x0f56a454 }, + 0 }, + /* 106 */ + { { 0x1043e0df,0x5b21bffa,0x9c007e6d,0x6c74b6cc,0xd4a8517a,0x1a656ec0, + 0x1969e263,0xbd8f1741 }, + { 0xbeb7494a,0x8a9bbb86,0x45f3b838,0x1567d46f,0xa4e5a79a,0xdf7a12a7, + 0x30ccfa09,0x2d1a1c35 }, + 0 }, + /* 107 */ + { { 0x506508da,0x192e3813,0xa1d795a7,0x336180c4,0x7a9944b3,0xcddb5949, + 0xb91fba46,0xa107a65e }, + { 0x0f94d639,0xe6d1d1c5,0x8a58b7d7,0x8b4af375,0xbd37ca1c,0x1a7c5584, + 0xf87a9af2,0x183d760a }, + 0 }, + /* 108 */ + { { 0x0dde59a4,0x29d69711,0x0e8bef87,0xf1ad8d07,0x4f2ebe78,0x229b4963, + 0xc269d754,0x1d44179d }, + { 0x8390d30e,0xb32dc0cf,0x0de8110c,0x0a3b2753,0x2bc0339a,0x31af1dc5, + 0x9606d262,0x771f9cc2 }, + 0 }, + /* 109 */ + { { 0x85040739,0x99993e77,0x8026a939,0x44539db9,0xf5f8fc26,0xcf40f6f2, + 0x0362718e,0x64427a31 }, + { 0x85428aa8,0x4f4f2d87,0xebfb49a8,0x7b7adc3f,0xf23d01ac,0x201b2c6d, + 0x6ae90d6d,0x49d9b749 }, + 0 }, + /* 110 */ + { { 0x435d1099,0xcc78d8bc,0x8e8d1a08,0x2adbcd4e,0x2cb68a41,0x02c2e2a0, + 0x3f605445,0x9037d81b }, + { 0x074c7b61,0x7cdbac27,0x57bfd72e,0xfe2031ab,0x596d5352,0x61ccec96, + 0x7cc0639c,0x08c3de6a }, + 0 }, + /* 111 */ + { { 0xf6d552ab,0x20fdd020,0x05cd81f1,0x56baff98,0x91351291,0x06fb7c3e, + 0x45796b2f,0xc6909442 }, + { 0x41231bd1,0x17b3ae9c,0x5cc58205,0x1eac6e87,0xf9d6a122,0x208837ab, + 0xcafe3ac0,0x3fa3db02 }, + 0 }, + /* 112 */ + { { 0x05058880,0xd75a3e65,0x643943f2,0x7da365ef,0xfab24925,0x4147861c, + 0xfdb808ff,0xc5c4bdb0 }, + { 0xb272b56b,0x73513e34,0x11b9043a,0xc8327e95,0xf8844969,0xfd8ce37d, + 0x46c2b6b5,0x2d56db94 }, + 0 }, + /* 113 */ + { { 0xff46ac6b,0x2461782f,0x07a2e425,0xd19f7926,0x09a48de1,0xfafea3c4, + 0xe503ba42,0x0f56bd9d }, + { 0x345cda49,0x137d4ed1,0x816f299d,0x821158fc,0xaeb43402,0xe7c6a54a, + 0x1173b5f1,0x4003bb9d }, + 0 }, + /* 114 */ + { { 0xa0803387,0x3b8e8189,0x39cbd404,0xece115f5,0xd2877f21,0x4297208d, + 0xa07f2f9e,0x53765522 }, + { 0xa8a4182d,0xa4980a21,0x3219df79,0xa2bbd07a,0x1a19a2d4,0x674d0a2e, + 0x6c5d4549,0x7a056f58 }, + 0 }, + /* 115 */ + { { 0x9d8a2a47,0x646b2558,0xc3df2773,0x5b582948,0xabf0d539,0x51ec000e, + 0x7a1a2675,0x77d482f1 }, + { 0x87853948,0xb8a1bd95,0x6cfbffee,0xa6f817bd,0x80681e47,0xab6ec057, + 0x2b38b0e4,0x4115012b }, + 0 }, + /* 116 */ + { { 0x6de28ced,0x3c73f0f4,0x9b13ec47,0x1d5da760,0x6e5c6392,0x61b8ce9e, + 0xfbea0946,0xcdf04572 }, + { 0x6c53c3b0,0x1cb3c58b,0x447b843c,0x97fe3c10,0x2cb9780e,0xfb2b8ae1, + 0x97383109,0xee703dda }, + 0 }, + /* 117 */ + { { 0xff57e43a,0x34515140,0xb1b811b8,0xd44660d3,0x8f42b986,0x2b3b5dff, + 0xa162ce21,0x2a0ad89d }, + { 0x6bc277ba,0x64e4a694,0xc141c276,0xc788c954,0xcabf6274,0x141aa64c, + 0xac2b4659,0xd62d0b67 }, + 0 }, + /* 118 */ + { { 0x2c054ac4,0x39c5d87b,0xf27df788,0x57005859,0xb18128d6,0xedf7cbf3, + 0x991c2426,0xb39a23f2 }, + { 0xf0b16ae5,0x95284a15,0xa136f51b,0x0c6a05b1,0xf2700783,0x1d63c137, + 0xc0674cc5,0x04ed0092 }, + 0 }, + /* 119 */ + { { 0x9ae90393,0x1f4185d1,0x4a3d64e6,0x3047b429,0x9854fc14,0xae0001a6, + 0x0177c387,0xa0a91fc1 }, + { 0xae2c831e,0xff0a3f01,0x2b727e16,0xbb76ae82,0x5a3075b4,0x8f12c8a1, + 0x9ed20c41,0x084cf988 }, + 0 }, + /* 120 */ + { { 0xfca6becf,0xd98509de,0x7dffb328,0x2fceae80,0x4778e8b9,0x5d8a15c4, + 0x73abf77e,0xd57955b2 }, + { 0x31b5d4f1,0x210da79e,0x3cfa7a1c,0xaa52f04b,0xdc27c20b,0xd4d12089, + 0x02d141f1,0x8e14ea42 }, + 0 }, + /* 121 */ + { { 0xf2897042,0xeed50345,0x43402c4a,0x8d05331f,0xc8bdfb21,0xc8d9c194, + 0x2aa4d158,0x597e1a37 }, + { 0xcf0bd68c,0x0327ec1a,0xab024945,0x6d4be0dc,0xc9fe3e84,0x5b9c8d7a, + 0x199b4dea,0xca3f0236 }, + 0 }, + /* 122 */ + { { 0x6170bd20,0x592a10b5,0x6d3f5de7,0x0ea897f1,0x44b2ade2,0xa3363ff1, + 0x309c07e4,0xbde7fd7e }, + { 0xb8f5432c,0x516bb6d2,0xe043444b,0x210dc1cb,0xf8f95b5a,0x3db01e6f, + 0x0a7dd198,0xb623ad0e }, + 0 }, + /* 123 */ + { { 0x60c7b65b,0xa75bd675,0x23a4a289,0xab8c5590,0xd7b26795,0xf8220fd0, + 0x58ec137b,0xd6aa2e46 }, + { 0x5138bb85,0x10abc00b,0xd833a95c,0x8c31d121,0x1702a32e,0xb24ff00b, + 0x2dcc513a,0x111662e0 }, + 0 }, + /* 124 */ + { { 0xefb42b87,0x78114015,0x1b6c4dff,0xbd9f5d70,0xa7d7c129,0x66ecccd7, + 0x94b750f8,0xdb3ee1cb }, + { 0xf34837cf,0xb26f3db0,0xb9578d4f,0xe7eed18b,0x7c56657d,0x5d2cdf93, + 0x52206a59,0x886a6442 }, + 0 }, + /* 125 */ + { { 0x65b569ea,0x3c234cfb,0xf72119c1,0x20011141,0xa15a619e,0x8badc85d, + 0x018a17bc,0xa70cf4eb }, + { 0x8c4a6a65,0x224f97ae,0x0134378f,0x36e5cf27,0x4f7e0960,0xbe3a609e, + 0xd1747b77,0xaa4772ab }, + 0 }, + /* 126 */ + { { 0x7aa60cc0,0x67676131,0x0368115f,0xc7916361,0xbbc1bb5a,0xded98bb4, + 0x30faf974,0x611a6ddc }, + { 0xc15ee47a,0x30e78cbc,0x4e0d96a5,0x2e896282,0x3dd9ed88,0x36f35adf, + 0x16429c88,0x5cfffaf8 }, + 0 }, + /* 127 */ + { { 0x9b7a99cd,0xc0d54cff,0x843c45a1,0x7bf3b99d,0x62c739e1,0x038a908f, + 0x7dc1994c,0x6e5a6b23 }, + { 0x0ba5db77,0xef8b454e,0xacf60d63,0xb7b8807f,0x76608378,0xe591c0c6, + 0x242dabcc,0x481a238d }, + 0 }, + /* 128 */ + { { 0x35d0b34a,0xe3417bc0,0x8327c0a7,0x440b386b,0xac0362d1,0x8fb7262d, + 0xe0cdf943,0x2c41114c }, + { 0xad95a0b1,0x2ba5cef1,0x67d54362,0xc09b37a8,0x01e486c9,0x26d6cdd2, + 0x42ff9297,0x20477abf }, + 0 }, + /* 129 */ + { { 0x18d65dbf,0x2f75173c,0x339edad8,0x77bf940e,0xdcf1001c,0x7022d26b, + 0xc77396b6,0xac66409a }, + { 0xc6261cc3,0x8b0bb36f,0x190e7e90,0x213f7bc9,0xa45e6c10,0x6541ceba, + 0xcc122f85,0xce8e6975 }, + 0 }, + /* 130 */ + { { 0xbc0a67d2,0x0f121b41,0x444d248a,0x62d4760a,0x659b4737,0x0e044f1d, + 0x250bb4a8,0x08fde365 }, + { 0x848bf287,0xaceec3da,0xd3369d6e,0xc2a62182,0x92449482,0x3582dfdc, + 0x565d6cd7,0x2f7e2fd2 }, + 0 }, + /* 131 */ + { { 0xc3770fa7,0xae4b92db,0x379043f9,0x095e8d5c,0x17761171,0x54f34e9d, + 0x907702ae,0xc65be92e }, + { 0xf6fd0a40,0x2758a303,0xbcce784b,0xe7d822e3,0x4f9767bf,0x7ae4f585, + 0xd1193b3a,0x4bff8e47 }, + 0 }, + /* 132 */ + { { 0x00ff1480,0xcd41d21f,0x0754db16,0x2ab8fb7d,0xbbe0f3ea,0xac81d2ef, + 0x5772967d,0x3e4e4ae6 }, + { 0x3c5303e6,0x7e18f36d,0x92262397,0x3bd9994b,0x1324c3c0,0x9ed70e26, + 0x58ec6028,0x5388aefd }, + 0 }, + /* 133 */ + { { 0x5e5d7713,0xad1317eb,0x75de49da,0x09b985ee,0xc74fb261,0x32f5bc4f, + 0x4f75be0e,0x5cf908d1 }, + { 0x8e657b12,0x76043510,0xb96ed9e6,0xbfd421a5,0x8970ccc2,0x0e29f51f, + 0x60f00ce2,0xa698ba40 }, + 0 }, + /* 134 */ + { { 0xef748fec,0x73db1686,0x7e9d2cf9,0xe6e755a2,0xce265eff,0x630b6544, + 0x7aebad8d,0xb142ef8a }, + { 0x17d5770a,0xad31af9f,0x2cb3412f,0x66af3b67,0xdf3359de,0x6bd60d1b, + 0x58515075,0xd1896a96 }, + 0 }, + /* 135 */ + { { 0x33c41c08,0xec5957ab,0x5468e2e1,0x87de94ac,0xac472f6c,0x18816b73, + 0x7981da39,0x267b0e0b }, + { 0x8e62b988,0x6e554e5d,0x116d21e7,0xd8ddc755,0x3d2a6f99,0x4610faf0, + 0xa1119393,0xb54e287a }, + 0 }, + /* 136 */ + { { 0x178a876b,0x0a0122b5,0x085104b4,0x51ff96ff,0x14f29f76,0x050b31ab, + 0x5f87d4e6,0x84abb28b }, + { 0x8270790a,0xd5ed439f,0x85e3f46b,0x2d6cb59d,0x6c1e2212,0x75f55c1b, + 0x17655640,0xe5436f67 }, + 0 }, + /* 137 */ + { { 0x2286e8d5,0x53f9025e,0x864453be,0x353c95b4,0xe408e3a0,0xd832f5bd, + 0x5b9ce99e,0x0404f68b }, + { 0xa781e8e5,0xcad33bde,0x163c2f5b,0x3cdf5018,0x0119caa3,0x57576960, + 0x0ac1c701,0x3a4263df }, + 0 }, + /* 138 */ + { { 0x9aeb596d,0xc2965ecc,0x023c92b4,0x01ea03e7,0x2e013961,0x4704b4b6, + 0x905ea367,0x0ca8fd3f }, + { 0x551b2b61,0x92523a42,0x390fcd06,0x1eb7a89c,0x0392a63e,0xe7f1d2be, + 0x4ddb0c33,0x96dca264 }, + 0 }, + /* 139 */ + { { 0x387510af,0x203bb43a,0xa9a36a01,0x846feaa8,0x2f950378,0xd23a5770, + 0x3aad59dc,0x4363e212 }, + { 0x40246a47,0xca43a1c7,0xe55dd24d,0xb362b8d2,0x5d8faf96,0xf9b08604, + 0xd8bb98c4,0x840e115c }, + 0 }, + /* 140 */ + { { 0x1023e8a7,0xf12205e2,0xd8dc7a0b,0xc808a8cd,0x163a5ddf,0xe292a272, + 0x30ded6d4,0x5e0d6abd }, + { 0x7cfc0f64,0x07a721c2,0x0e55ed88,0x42eec01d,0x1d1f9db2,0x26a7bef9, + 0x2945a25a,0x7dea48f4 }, + 0 }, + /* 141 */ + { { 0xe5060a81,0xabdf6f1c,0xf8f95615,0xe79f9c72,0x06ac268b,0xcfd36c54, + 0xebfd16d1,0xabc2a2be }, + { 0xd3e2eac7,0x8ac66f91,0xd2dd0466,0x6f10ba63,0x0282d31b,0x6790e377, + 0x6c7eefc1,0x4ea35394 }, + 0 }, + /* 142 */ + { { 0x5266309d,0xed8a2f8d,0x81945a3e,0x0a51c6c0,0x578c5dc1,0xcecaf45a, + 0x1c94ffc3,0x3a76e689 }, + { 0x7d7b0d0f,0x9aace8a4,0x8f584a5f,0x963ace96,0x4e697fbe,0x51a30c72, + 0x465e6464,0x8212a10a }, + 0 }, + /* 143 */ + { { 0xcfab8caa,0xef7c61c3,0x0e142390,0x18eb8e84,0x7e9733ca,0xcd1dff67, + 0x599cb164,0xaa7cab71 }, + { 0xbc837bd1,0x02fc9273,0xc36af5d7,0xc06407d0,0xf423da49,0x17621292, + 0xfe0617c3,0x40e38073 }, + 0 }, + /* 144 */ + { { 0xa7bf9b7c,0xf4f80824,0x3fbe30d0,0x365d2320,0x97cf9ce3,0xbfbe5320, + 0xb3055526,0xe3604700 }, + { 0x6cc6c2c7,0x4dcb9911,0xba4cbee6,0x72683708,0x637ad9ec,0xdcded434, + 0xa3dee15f,0x6542d677 }, + 0 }, + /* 145 */ + { { 0x7b6c377a,0x3f32b6d0,0x903448be,0x6cb03847,0x20da8af7,0xd6fdd3a8, + 0x09bb6f21,0xa6534aee }, + { 0x1035facf,0x30a1780d,0x9dcb47e6,0x35e55a33,0xc447f393,0x6ea50fe1, + 0xdc9aef22,0xf3cb672f }, + 0 }, + /* 146 */ + { { 0x3b55fd83,0xeb3719fe,0x875ddd10,0xe0d7a46c,0x05cea784,0x33ac9fa9, + 0xaae870e7,0x7cafaa2e }, + { 0x1d53b338,0x9b814d04,0xef87e6c6,0xe0acc0a0,0x11672b0f,0xfb93d108, + 0xb9bd522e,0x0aab13c1 }, + 0 }, + /* 147 */ + { { 0xd2681297,0xddcce278,0xb509546a,0xcb350eb1,0x7661aaf2,0x2dc43173, + 0x847012e9,0x4b91a602 }, + { 0x72f8ddcf,0xdcff1095,0x9a911af4,0x08ebf61e,0xc372430e,0x48f4360a, + 0x72321cab,0x49534c53 }, + 0 }, + /* 148 */ + { { 0xf07b7e9d,0x83df7d71,0x13cd516f,0xa478efa3,0x6c047ee3,0x78ef264b, + 0xd65ac5ee,0xcaf46c4f }, + { 0x92aa8266,0xa04d0c77,0x913684bb,0xedf45466,0xae4b16b0,0x56e65168, + 0x04c6770f,0x14ce9e57 }, + 0 }, + /* 149 */ + { { 0x965e8f91,0x99445e3e,0xcb0f2492,0xd3aca1ba,0x90c8a0a0,0xd31cc70f, + 0x3e4c9a71,0x1bb708a5 }, + { 0x558bdd7a,0xd5ca9e69,0x018a26b1,0x734a0508,0x4c9cf1ec,0xb093aa71, + 0xda300102,0xf9d126f2 }, + 0 }, + /* 150 */ + { { 0xaff9563e,0x749bca7a,0xb49914a0,0xdd077afe,0xbf5f1671,0xe27a0311, + 0x729ecc69,0x807afcb9 }, + { 0xc9b08b77,0x7f8a9337,0x443c7e38,0x86c3a785,0x476fd8ba,0x85fafa59, + 0x6568cd8c,0x751adcd1 }, + 0 }, + /* 151 */ + { { 0x10715c0d,0x8aea38b4,0x8f7697f7,0xd113ea71,0x93fbf06d,0x665eab14, + 0x2537743f,0x29ec4468 }, + { 0xb50bebbc,0x3d94719c,0xe4505422,0x399ee5bf,0x8d2dedb1,0x90cd5b3a, + 0x92a4077d,0xff9370e3 }, + 0 }, + /* 152 */ + { { 0xc6b75b65,0x59a2d69b,0x266651c5,0x4188f8d5,0x3de9d7d2,0x28a9f33e, + 0xa2a9d01a,0x9776478b }, + { 0x929af2c7,0x8852622d,0x4e690923,0x334f5d6d,0xa89a51e9,0xce6cc7e5, + 0xac2f82fa,0x74a6313f }, + 0 }, + /* 153 */ + { { 0xb75f079c,0xb2f4dfdd,0x18e36fbb,0x85b07c95,0xe7cd36dd,0x1b6cfcf0, + 0x0ff4863d,0xab75be15 }, + { 0x173fc9b7,0x81b367c0,0xd2594fd0,0xb90a7420,0xc4091236,0x15fdbf03, + 0x0b4459f6,0x4ebeac2e }, + 0 }, + /* 154 */ + { { 0x5c9f2c53,0xeb6c5fe7,0x8eae9411,0xd2522011,0xf95ac5d8,0xc8887633, + 0x2c1baffc,0xdf99887b }, + { 0x850aaecb,0xbb78eed2,0x01d6a272,0x9d49181b,0xb1cdbcac,0x978dd511, + 0x779f4058,0x27b040a7 }, + 0 }, + /* 155 */ + { { 0xf73b2eb2,0x90405db7,0x8e1b2118,0xe0df8508,0x5962327e,0x501b7152, + 0xe4cfa3f5,0xb393dd37 }, + { 0x3fd75165,0xa1230e7b,0xbcd33554,0xd66344c2,0x0f7b5022,0x6c36f1be, + 0xd0463419,0x09588c12 }, + 0 }, + /* 156 */ + { { 0x02601c3b,0xe086093f,0xcf5c335f,0xfb0252f8,0x894aff28,0x955cf280, + 0xdb9f648b,0x81c879a9 }, + { 0xc6f56c51,0x040e687c,0x3f17618c,0xfed47169,0x9059353b,0x44f88a41, + 0x5fc11bc4,0xfa0d48f5 }, + 0 }, + /* 157 */ + { { 0xe1608e4d,0xbc6e1c9d,0x3582822c,0x010dda11,0x157ec2d7,0xf6b7ddc1, + 0xb6a367d6,0x8ea0e156 }, + { 0x2383b3b4,0xa354e02f,0x3f01f53c,0x69966b94,0x2de03ca5,0x4ff6632b, + 0xfa00b5ac,0x3f5ab924 }, + 0 }, + /* 158 */ + { { 0x59739efb,0x337bb0d9,0xe7ebec0d,0xc751b0f4,0x411a67d1,0x2da52dd6, + 0x2b74256e,0x8bc76887 }, + { 0x82d3d253,0xa5be3b72,0xf58d779f,0xa9f679a1,0xe16767bb,0xa1cac168, + 0x60fcf34f,0xb386f190 }, + 0 }, + /* 159 */ + { { 0x2fedcfc2,0x31f3c135,0x62f8af0d,0x5396bf62,0xe57288c2,0x9a02b4ea, + 0x1b069c4d,0x4cb460f7 }, + { 0x5b8095ea,0xae67b4d3,0x6fc07603,0x92bbf859,0xb614a165,0xe1475f66, + 0x95ef5223,0x52c0d508 }, + 0 }, + /* 160 */ + { { 0x15339848,0x231c210e,0x70778c8d,0xe87a28e8,0x6956e170,0x9d1de661, + 0x2bb09c0b,0x4ac3c938 }, + { 0x6998987d,0x19be0551,0xae09f4d6,0x8b2376c4,0x1a3f933d,0x1de0b765, + 0xe39705f4,0x380d94c7 }, + 0 }, + /* 161 */ + { { 0x81542e75,0x01a355aa,0xee01b9b7,0x96c724a1,0x624d7087,0x6b3a2977, + 0xde2637af,0x2ce3e171 }, + { 0xf5d5bc1a,0xcfefeb49,0x2777e2b5,0xa655607e,0x9513756c,0x4feaac2f, + 0x0b624e4d,0x2e6cd852 }, + 0 }, + /* 162 */ + { { 0x8c31c31d,0x3685954b,0x5bf21a0c,0x68533d00,0x75c79ec9,0x0bd7626e, + 0x42c69d54,0xca177547 }, + { 0xf6d2dbb2,0xcc6edaff,0x174a9d18,0xfd0d8cbd,0xaa4578e8,0x875e8793, + 0x9cab2ce6,0xa976a713 }, + 0 }, + /* 163 */ + { { 0x93fb353d,0x0a651f1b,0x57fcfa72,0xd75cab8b,0x31b15281,0xaa88cfa7, + 0x0a1f4999,0x8720a717 }, + { 0x693e1b90,0x8c3e8d37,0x16f6dfc3,0xd345dc0b,0xb52a8742,0x8ea8d00a, + 0xc769893c,0x9719ef29 }, + 0 }, + /* 164 */ + { { 0x58e35909,0x820eed8d,0x33ddc116,0x9366d8dc,0x6e205026,0xd7f999d0, + 0xe15704c1,0xa5072976 }, + { 0xc4e70b2e,0x002a37ea,0x6890aa8a,0x84dcf657,0x645b2a5c,0xcd71bf18, + 0xf7b77725,0x99389c9d }, + 0 }, + /* 165 */ + { { 0x7ada7a4b,0x238c08f2,0xfd389366,0x3abe9d03,0x766f512c,0x6b672e89, + 0x202c82e4,0xa88806aa }, + { 0xd380184e,0x6602044a,0x126a8b85,0xa8cb78c4,0xad844f17,0x79d670c0, + 0x4738dcfe,0x0043bffb }, + 0 }, + /* 166 */ + { { 0x36d5192e,0x8d59b5dc,0x4590b2af,0xacf885d3,0x11601781,0x83566d0a, + 0xba6c4866,0x52f3ef01 }, + { 0x0edcb64d,0x3986732a,0x8068379f,0x0a482c23,0x7040f309,0x16cbe5fa, + 0x9ef27e75,0x3296bd89 }, + 0 }, + /* 167 */ + { { 0x454d81d7,0x476aba89,0x51eb9b3c,0x9eade7ef,0x81c57986,0x619a21cd, + 0xaee571e9,0x3b90febf }, + { 0x5496f7cb,0x9393023e,0x7fb51bc4,0x55be41d8,0x99beb5ce,0x03f1dd48, + 0x9f810b18,0x6e88069d }, + 0 }, + /* 168 */ + { { 0xb43ea1db,0xce37ab11,0x5259d292,0x0a7ff1a9,0x8f84f186,0x851b0221, + 0xdefaad13,0xa7222bea }, + { 0x2b0a9144,0xa2ac78ec,0xf2fa59c5,0x5a024051,0x6147ce38,0x91d1eca5, + 0xbc2ac690,0xbe94d523 }, + 0 }, + /* 169 */ + { { 0x0b226ce7,0x72f4945e,0x967e8b70,0xb8afd747,0x85a6c63e,0xedea46f1, + 0x9be8c766,0x7782defe }, + { 0x3db38626,0x760d2aa4,0x76f67ad1,0x460ae787,0x54499cdb,0x341b86fc, + 0xa2892e4b,0x03838567 }, + 0 }, + /* 170 */ + { { 0x79ec1a0f,0x2d8daefd,0xceb39c97,0x3bbcd6fd,0x58f61a95,0xf5575ffc, + 0xadf7b420,0xdbd986c4 }, + { 0x15f39eb7,0x81aa8814,0xb98d976c,0x6ee2fcf5,0xcf2f717d,0x5465475d, + 0x6860bbd0,0x8e24d3c4 }, + 0 }, + /* 171 */ + { { 0x9a587390,0x749d8e54,0x0cbec588,0x12bb194f,0xb25983c6,0x46e07da4, + 0x407bafc8,0x541a99c4 }, + { 0x624c8842,0xdb241692,0xd86c05ff,0x6044c12a,0x4f7fcf62,0xc59d14b4, + 0xf57d35d1,0xc0092c49 }, + 0 }, + /* 172 */ + { { 0xdf2e61ef,0xd3cc75c3,0x2e1b35ca,0x7e8841c8,0x909f29f4,0xc62d30d1, + 0x7286944d,0x75e40634 }, + { 0xbbc237d0,0xe7d41fc5,0xec4f01c9,0xc9537bf0,0x282bd534,0x91c51a16, + 0xc7848586,0x5b7cb658 }, + 0 }, + /* 173 */ + { { 0x8a28ead1,0x964a7084,0xfd3b47f6,0x802dc508,0x767e5b39,0x9ae4bfd1, + 0x8df097a1,0x7ae13eba }, + { 0xeadd384e,0xfd216ef8,0xb6b2ff06,0x0361a2d9,0x4bcdb5f3,0x204b9878, + 0xe2a8e3fd,0x787d8074 }, + 0 }, + /* 174 */ + { { 0x757fbb1c,0xc5e25d6b,0xca201deb,0xe47bddb2,0x6d2233ff,0x4a55e9a3, + 0x9ef28484,0x5c222819 }, + { 0x88315250,0x773d4a85,0x827097c1,0x21b21a2b,0xdef5d33f,0xab7c4ea1, + 0xbaf0f2b0,0xe45d37ab }, + 0 }, + /* 175 */ + { { 0x28511c8a,0xd2df1e34,0xbdca6cd3,0xebb229c8,0x627c39a7,0x578a71a7, + 0x84dfb9d3,0xed7bc122 }, + { 0x93dea561,0xcf22a6df,0xd48f0ed1,0x5443f18d,0x5bad23e8,0xd8b86140, + 0x45ca6d27,0xaac97cc9 }, + 0 }, + /* 176 */ + { { 0xa16bd00a,0xeb54ea74,0xf5c0bcc1,0xd839e9ad,0x1f9bfc06,0x092bb7f1, + 0x1163dc4e,0x318f97b3 }, + { 0xc30d7138,0xecc0c5be,0xabc30220,0x44e8df23,0xb0223606,0x2bb7972f, + 0x9a84ff4d,0xfa41faa1 }, + 0 }, + /* 177 */ + { { 0xa6642269,0x4402d974,0x9bb783bd,0xc81814ce,0x7941e60b,0x398d38e4, + 0x1d26e9e2,0x38bb6b2c }, + { 0x6a577f87,0xc64e4a25,0xdc11fe1c,0x8b52d253,0x62280728,0xff336abf, + 0xce7601a5,0x94dd0905 }, + 0 }, + /* 178 */ + { { 0xde93f92a,0x156cf7dc,0x89b5f315,0xa01333cb,0xc995e750,0x02404df9, + 0xd25c2ae9,0x92077867 }, + { 0x0bf39d44,0xe2471e01,0x96bb53d7,0x5f2c9020,0x5c9c3d8f,0x4c44b7b3, + 0xd29beb51,0x81e8428b }, + 0 }, + /* 179 */ + { { 0xc477199f,0x6dd9c2ba,0x6b5ecdd9,0x8cb8eeee,0xee40fd0e,0x8af7db3f, + 0xdbbfa4b1,0x1b94ab62 }, + { 0xce47f143,0x44f0d8b3,0x63f46163,0x51e623fc,0xcc599383,0xf18f270f, + 0x055590ee,0x06a38e28 }, + 0 }, + /* 180 */ + { { 0xb3355b49,0x2e5b0139,0xb4ebf99b,0x20e26560,0xd269f3dc,0xc08ffa6b, + 0x83d9d4f8,0xa7b36c20 }, + { 0x1b3e8830,0x64d15c3a,0xa89f9c0b,0xd5fceae1,0xe2d16930,0xcfeee4a2, + 0xa2822a20,0xbe54c6b4 }, + 0 }, + /* 181 */ + { { 0x8d91167c,0xd6cdb3df,0xe7a6625e,0x517c3f79,0x346ac7f4,0x7105648f, + 0xeae022bb,0xbf30a5ab }, + { 0x93828a68,0x8e7785be,0x7f3ef036,0x5161c332,0x592146b2,0xe11b5feb, + 0x2732d13a,0xd1c820de }, + 0 }, + /* 182 */ + { { 0x9038b363,0x043e1347,0x6b05e519,0x58c11f54,0x6026cad1,0x4fe57abe, + 0x68a18da3,0xb7d17bed }, + { 0xe29c2559,0x44ca5891,0x5bfffd84,0x4f7a0376,0x74e46948,0x498de4af, + 0x6412cc64,0x3997fd5e }, + 0 }, + /* 183 */ + { { 0x8bd61507,0xf2074682,0x34a64d2a,0x29e132d5,0x8a8a15e3,0xffeddfb0, + 0x3c6c13e8,0x0eeb8929 }, + { 0xa7e259f8,0xe9b69a3e,0xd13e7e67,0xce1db7e6,0xad1fa685,0x277318f6, + 0xc922b6ef,0x228916f8 }, + 0 }, + /* 184 */ + { { 0x0a12ab5b,0x959ae25b,0x957bc136,0xcc11171f,0xd16e2b0c,0x8058429e, + 0x6e93097e,0xec05ad1d }, + { 0xac3f3708,0x157ba5be,0x30b59d77,0x31baf935,0x118234e5,0x47b55237, + 0x7ff11b37,0x7d314156 }, + 0 }, + /* 185 */ + { { 0xf6dfefab,0x7bd9c05c,0xdcb37707,0xbe2f2268,0x3a38bb95,0xe53ead97, + 0x9bc1d7a3,0xe9ce66fc }, + { 0x6f6a02a1,0x75aa1576,0x60e600ed,0x38c087df,0x68cdc1b9,0xf8947f34, + 0x72280651,0xd9650b01 }, + 0 }, + /* 186 */ + { { 0x5a057e60,0x504b4c4a,0x8def25e4,0xcbccc3be,0x17c1ccbd,0xa6353208, + 0x804eb7a2,0x14d6699a }, + { 0xdb1f411a,0x2c8a8415,0xf80d769c,0x09fbaf0b,0x1c2f77ad,0xb4deef90, + 0x0d43598a,0x6f4c6841 }, + 0 }, + /* 187 */ + { { 0x96c24a96,0x8726df4e,0xfcbd99a3,0x534dbc85,0x8b2ae30a,0x3c466ef2, + 0x61189abb,0x4c4350fd }, + { 0xf855b8da,0x2967f716,0x463c38a1,0x41a42394,0xeae93343,0xc37e1413, + 0x5a3118b5,0xa726d242 }, + 0 }, + /* 188 */ + { { 0x948c1086,0xdae6b3ee,0xcbd3a2e1,0xf1de503d,0x03d022f3,0x3f35ed3f, + 0xcc6cf392,0x13639e82 }, + { 0xcdafaa86,0x9ac938fb,0x2654a258,0xf45bc5fb,0x45051329,0x1963b26e, + 0xc1a335a3,0xca9365e1 }, + 0 }, + /* 189 */ + { { 0x4c3b2d20,0x3615ac75,0x904e241b,0x742a5417,0xcc9d071d,0xb08521c4, + 0x970b72a5,0x9ce29c34 }, + { 0x6d3e0ad6,0x8cc81f73,0xf2f8434c,0x8060da9e,0x6ce862d9,0x35ed1d1a, + 0xab42af98,0x48c4abd7 }, + 0 }, + /* 190 */ + { { 0x40c7485a,0xd221b0cc,0xe5274dbf,0xead455bb,0x9263d2e8,0x493c7698, + 0xf67b33cb,0x78017c32 }, + { 0x930cb5ee,0xb9d35769,0x0c408ed2,0xc0d14e94,0x272f1a4d,0xf8b7bf55, + 0xde5c1c04,0x53cd0454 }, + 0 }, + /* 191 */ + { { 0x5d28ccac,0xbcd585fa,0x005b746e,0x5f823e56,0xcd0123aa,0x7c79f0a1, + 0xd3d7fa8f,0xeea465c1 }, + { 0x0551803b,0x7810659f,0x7ce6af70,0x6c0b599f,0x29288e70,0x4195a770, + 0x7ae69193,0x1b6e42a4 }, + 0 }, + /* 192 */ + { { 0xf67d04c3,0x2e80937c,0x89eeb811,0x1e312be2,0x92594d60,0x56b5d887, + 0x187fbd3d,0x0224da14 }, + { 0x0c5fe36f,0x87abb863,0x4ef51f5f,0x580f3c60,0xb3b429ec,0x964fb1bf, + 0x42bfff33,0x60838ef0 }, + 0 }, + /* 193 */ + { { 0x7e0bbe99,0x432cb2f2,0x04aa39ee,0x7bda44f3,0x9fa93903,0x5f497c7a, + 0x2d331643,0x636eb202 }, + { 0x93ae00aa,0xfcfd0e61,0x31ae6d2f,0x875a00fe,0x9f93901c,0xf43658a2, + 0x39218bac,0x8844eeb6 }, + 0 }, + /* 194 */ + { { 0x6b3bae58,0x114171d2,0x17e39f3e,0x7db3df71,0x81a8eada,0xcd37bc7f, + 0x51fb789e,0x27ba83dc }, + { 0xfbf54de5,0xa7df439f,0xb5fe1a71,0x7277030b,0xdb297a48,0x42ee8e35, + 0x87f3a4ab,0xadb62d34 }, + 0 }, + /* 195 */ + { { 0xa175df2a,0x9b1168a2,0x618c32e9,0x082aa04f,0x146b0916,0xc9e4f2e7, + 0x75e7c8b2,0xb990fd76 }, + { 0x4df37313,0x0829d96b,0xd0b40789,0x1c205579,0x78087711,0x66c9ae4a, + 0x4d10d18d,0x81707ef9 }, + 0 }, + /* 196 */ + { { 0x03d6ff96,0x97d7cab2,0x0d843360,0x5b851bfc,0xd042db4b,0x268823c4, + 0xd5a8aa5c,0x3792daea }, + { 0x941afa0b,0x52818865,0x42d83671,0xf3e9e741,0x5be4e0a7,0x17c82527, + 0x94b001ba,0x5abd635e }, + 0 }, + /* 197 */ + { { 0x0ac4927c,0x727fa84e,0xa7c8cf23,0xe3886035,0x4adca0df,0xa4bcd5ea, + 0x846ab610,0x5995bf21 }, + { 0x829dfa33,0xe90f860b,0x958fc18b,0xcaafe2ae,0x78630366,0x9b3baf44, + 0xd483411e,0x44c32ca2 }, + 0 }, + /* 198 */ + { { 0xe40ed80c,0xa74a97f1,0x31d2ca82,0x5f938cb1,0x7c2d6ad9,0x53f2124b, + 0x8082a54c,0x1f2162fb }, + { 0x720b173e,0x7e467cc5,0x085f12f9,0x40e8a666,0x4c9d65dc,0x8cebc20e, + 0xc3e907c9,0x8f1d402b }, + 0 }, + /* 199 */ + { { 0xfbc4058a,0x4f592f9c,0x292f5670,0xb15e14b6,0xbc1d8c57,0xc55cfe37, + 0x926edbf9,0xb1980f43 }, + { 0x32c76b09,0x98c33e09,0x33b07f78,0x1df5279d,0x863bb461,0x6f08ead4, + 0x37448e45,0x2828ad9b }, + 0 }, + /* 200 */ + { { 0xc4cf4ac5,0x696722c4,0xdde64afb,0xf5ac1a3f,0xe0890832,0x0551baa2, + 0x5a14b390,0x4973f127 }, + { 0x322eac5d,0xe59d8335,0x0bd9b568,0x5e07eef5,0xa2588393,0xab36720f, + 0xdb168ac7,0x6dac8ed0 }, + 0 }, + /* 201 */ + { { 0xeda835ef,0xf7b545ae,0x1d10ed51,0x4aa113d2,0x13741b09,0x035a65e0, + 0x20b9de4c,0x4b23ef59 }, + { 0x3c4c7341,0xe82bb680,0x3f58bc37,0xd457706d,0xa51e3ee8,0x73527863, + 0xddf49a4e,0x4dd71534 }, + 0 }, + /* 202 */ + { { 0x95476cd9,0xbf944672,0xe31a725b,0x648d072f,0xfc4b67e0,0x1441c8b8, + 0x2f4a4dbb,0xfd317000 }, + { 0x8995d0e1,0x1cb43ff4,0x0ef729aa,0x76e695d1,0x41798982,0xe0d5f976, + 0x9569f365,0x14fac58c }, + 0 }, + /* 203 */ + { { 0xf312ae18,0xad9a0065,0xfcc93fc9,0x51958dc0,0x8a7d2846,0xd9a14240, + 0x36abda50,0xed7c7651 }, + { 0x25d4abbc,0x46270f1a,0xf1a113ea,0x9b5dd8f3,0x5b51952f,0xc609b075, + 0x4d2e9f53,0xfefcb7f7 }, + 0 }, + /* 204 */ + { { 0xba119185,0xbd09497a,0xaac45ba4,0xd54e8c30,0xaa521179,0x492479de, + 0x87e0d80b,0x1801a57e }, + { 0xfcafffb0,0x073d3f8d,0xae255240,0x6cf33c0b,0x5b5fdfbc,0x781d763b, + 0x1ead1064,0x9f8fc11e }, + 0 }, + /* 205 */ + { { 0x5e69544c,0x1583a171,0xf04b7813,0x0eaf8567,0x278a4c32,0x1e22a8fd, + 0x3d3a69a9,0xa9d3809d }, + { 0x59a2da3b,0x936c2c2c,0x1895c847,0x38ccbcf6,0x63d50869,0x5e65244e, + 0xe1178ef7,0x3006b9ae }, + 0 }, + /* 206 */ + { { 0xc9eead28,0x0bb1f2b0,0x89f4dfbc,0x7eef635d,0xb2ce8939,0x074757fd, + 0x45f8f761,0x0ab85fd7 }, + { 0x3e5b4549,0xecda7c93,0x97922f21,0x4be2bb5c,0xb43b8040,0x261a1274, + 0x11e942c2,0xb122d675 }, + 0 }, + /* 207 */ + { { 0x66a5ae7a,0x3be607be,0x76adcbe3,0x01e703fa,0x4eb6e5c5,0xaf904301, + 0x097dbaec,0x9f599dc1 }, + { 0x0ff250ed,0x6d75b718,0x349a20dc,0x8eb91574,0x10b227a3,0x425605a4, + 0x8a294b78,0x7d5528e0 }, + 0 }, + /* 208 */ + { { 0x20c26def,0xf0f58f66,0x582b2d1e,0x025585ea,0x01ce3881,0xfbe7d79b, + 0x303f1730,0x28ccea01 }, + { 0x79644ba5,0xd1dabcd1,0x06fff0b8,0x1fc643e8,0x66b3e17b,0xa60a76fc, + 0xa1d013bf,0xc18baf48 }, + 0 }, + /* 209 */ + { { 0x5dc4216d,0x34e638c8,0x206142ac,0x00c01067,0x95f5064a,0xd453a171, + 0xb7a9596b,0x9def809d }, + { 0x67ab8d2c,0x41e8642e,0x6237a2b6,0xb4240433,0x64c4218b,0x7d506a6d, + 0x68808ce5,0x0357f8b0 }, + 0 }, + /* 210 */ + { { 0x4cd2cc88,0x8e9dbe64,0xf0b8f39d,0xcc61c28d,0xcd30a0c8,0x4a309874, + 0x1b489887,0xe4a01add }, + { 0xf57cd8f9,0x2ed1eeac,0xbd594c48,0x1b767d3e,0x7bd2f787,0xa7295c71, + 0xce10cc30,0x466d7d79 }, + 0 }, + /* 211 */ + { { 0x9dada2c7,0x47d31892,0x8f9aa27d,0x4fa0a6c3,0x820a59e1,0x90e4fd28, + 0x451ead1a,0xc672a522 }, + { 0x5d86b655,0x30607cc8,0xf9ad4af1,0xf0235d3b,0x571172a6,0x99a08680, + 0xf2a67513,0x5e3d64fa }, + 0 }, + /* 212 */ + { { 0x9b3b4416,0xaa6410c7,0xeab26d99,0xcd8fcf85,0xdb656a74,0x5ebff74a, + 0xeb8e42fc,0x6c8a7a95 }, + { 0xb02a63bd,0x10c60ba7,0x8b8f0047,0x6b2f2303,0x312d90b0,0x8c6c3738, + 0xad82ca91,0x348ae422 }, + 0 }, + /* 213 */ + { { 0x5ccda2fb,0x7f474663,0x8e0726d2,0x22accaa1,0x492b1f20,0x85adf782, + 0xd9ef2d2e,0xc1074de0 }, + { 0xae9a65b3,0xfcf3ce44,0x05d7151b,0xfd71e4ac,0xce6a9788,0xd4711f50, + 0xc9e54ffc,0xfbadfbdb }, + 0 }, + /* 214 */ + { { 0x20a99363,0x1713f1cd,0x6cf22775,0xb915658f,0x24d359b2,0x968175cd, + 0x83716fcd,0xb7f976b4 }, + { 0x5d6dbf74,0x5758e24d,0x71c3af36,0x8d23bafd,0x0243dfe3,0x48f47760, + 0xcafcc805,0xf4d41b2e }, + 0 }, + /* 215 */ + { { 0xfdabd48d,0x51f1cf28,0x32c078a4,0xce81be36,0x117146e9,0x6ace2974, + 0xe0160f10,0x180824ea }, + { 0x66e58358,0x0387698b,0xce6ca358,0x63568752,0x5e41e6c5,0x82380e34, + 0x83cf6d25,0x67e5f639 }, + 0 }, + /* 216 */ + { { 0xcf4899ef,0xf89ccb8d,0x9ebb44c0,0x949015f0,0xb2598ec9,0x546f9276, + 0x04c11fc6,0x9fef789a }, + { 0x53d2a071,0x6d367ecf,0xa4519b09,0xb10e1a7f,0x611e2eef,0xca6b3fb0, + 0xa99c4e20,0xbc80c181 }, + 0 }, + /* 217 */ + { { 0xe5eb82e6,0x972536f8,0xf56cb920,0x1a484fc7,0x50b5da5e,0xc78e2171, + 0x9f8cdf10,0x49270e62 }, + { 0xea6b50ad,0x1a39b7bb,0xa2388ffc,0x9a0284c1,0x8107197b,0x5403eb17, + 0x61372f7f,0xd2ee52f9 }, + 0 }, + /* 218 */ + { { 0x88e0362a,0xd37cd285,0x8fa5d94d,0x442fa8a7,0xa434a526,0xaff836e5, + 0xe5abb733,0xdfb478be }, + { 0x673eede6,0xa91f1ce7,0x2b5b2f04,0xa5390ad4,0x5530da2f,0x5e66f7bf, + 0x08df473a,0xd9a140b4 }, + 0 }, + /* 219 */ + { { 0x6e8ea498,0x0e0221b5,0x3563ee09,0x62347829,0x335d2ade,0xe06b8391, + 0x623f4b1a,0x760c058d }, + { 0xc198aa79,0x0b89b58c,0xf07aba7f,0xf74890d2,0xfde2556a,0x4e204110, + 0x8f190409,0x7141982d }, + 0 }, + /* 220 */ + { { 0x4d4b0f45,0x6f0a0e33,0x392a94e1,0xd9280b38,0xb3c61d5e,0x3af324c6, + 0x89d54e47,0x3af9d1ce }, + { 0x20930371,0xfd8f7981,0x21c17097,0xeda2664c,0xdc42309b,0x0e9545dc, + 0x73957dd6,0xb1f815c3 }, + 0 }, + /* 221 */ + { { 0x89fec44a,0x84faa78e,0x3caa4caf,0xc8c2ae47,0xc1b6a624,0x691c807d, + 0x1543f052,0xa41aed14 }, + { 0x7d5ffe04,0x42435399,0x625b6e20,0x8bacb2df,0x87817775,0x85d660be, + 0x86fb60ef,0xd6e9c1dd }, + 0 }, + /* 222 */ + { { 0xc6853264,0x3aa2e97e,0xe2304a0b,0x771533b7,0xb8eae9be,0x1b912bb7, + 0xae9bf8c2,0x9c9c6e10 }, + { 0xe030b74c,0xa2309a59,0x6a631e90,0x4ed7494d,0xa49b79f2,0x89f44b23, + 0x40fa61b6,0x566bd596 }, + 0 }, + /* 223 */ + { { 0xc18061f3,0x066c0118,0x7c83fc70,0x190b25d3,0x27273245,0xf05fc8e0, + 0xf525345e,0xcf2c7390 }, + { 0x10eb30cf,0xa09bceb4,0x0d77703a,0xcfd2ebba,0x150ff255,0xe842c43a, + 0x8aa20979,0x02f51755 }, + 0 }, + /* 224 */ + { { 0xaddb7d07,0x396ef794,0x24455500,0x0b4fc742,0xc78aa3ce,0xfaff8eac, + 0xe8d4d97d,0x14e9ada5 }, + { 0x2f7079e2,0xdaa480a1,0xe4b0800e,0x45baa3cd,0x7838157d,0x01765e2d, + 0x8e9d9ae8,0xa0ad4fab }, + 0 }, + /* 225 */ + { { 0x4a653618,0x0bfb7621,0x31eaaa5f,0x1872813c,0x44949d5e,0x1553e737, + 0x6e56ed1e,0xbcd530b8 }, + { 0x32e9c47b,0x169be853,0xb50059ab,0xdc2776fe,0x192bfbb4,0xcdba9761, + 0x6979341d,0x909283cf }, + 0 }, + /* 226 */ + { { 0x76e81a13,0x67b00324,0x62171239,0x9bee1a99,0xd32e19d6,0x08ed361b, + 0xace1549a,0x35eeb7c9 }, + { 0x7e4e5bdc,0x1280ae5a,0xb6ceec6e,0x2dcd2cd3,0x6e266bc1,0x52e4224c, + 0x448ae864,0x9a8b2cf4 }, + 0 }, + /* 227 */ + { { 0x09d03b59,0xf6471bf2,0xb65af2ab,0xc90e62a3,0xebd5eec9,0xff7ff168, + 0xd4491379,0x6bdb60f4 }, + { 0x8a55bc30,0xdadafebc,0x10097fe0,0xc79ead16,0x4c1e3bdd,0x42e19741, + 0x94ba08a9,0x01ec3cfd }, + 0 }, + /* 228 */ + { { 0xdc9485c2,0xba6277eb,0x22fb10c7,0x48cc9a79,0x70a28d8a,0x4f61d60f, + 0x475464f6,0xd1acb1c0 }, + { 0x26f36612,0xd26902b1,0xe0618d8b,0x59c3a44e,0x308357ee,0x4df8a813, + 0x405626c2,0x7dcd079d }, + 0 }, + /* 229 */ + { { 0xf05a4b48,0x5ce7d4d3,0x37230772,0xadcd2952,0x812a915a,0xd18f7971, + 0x377d19b8,0x0bf53589 }, + { 0x6c68ea73,0x35ecd95a,0x823a584d,0xc7f3bbca,0xf473a723,0x9fb674c6, + 0xe16686fc,0xd28be4d9 }, + 0 }, + /* 230 */ + { { 0x38fa8e4b,0x5d2b9906,0x893fd8fc,0x559f186e,0x436fb6fc,0x3a6de2aa, + 0x510f88ce,0xd76007aa }, + { 0x523a4988,0x2d10aab6,0x74dd0273,0xb455cf44,0xa3407278,0x7f467082, + 0xb303bb01,0xf2b52f68 }, + 0 }, + /* 231 */ + { { 0x9835b4ca,0x0d57eafa,0xbb669cbc,0x2d2232fc,0xc6643198,0x8eeeb680, + 0xcc5aed3a,0xd8dbe98e }, + { 0xc5a02709,0xcba9be3f,0xf5ba1fa8,0x30be68e5,0xf10ea852,0xfebd43cd, + 0xee559705,0xe01593a3 }, + 0 }, + /* 232 */ + { { 0xea75a0a6,0xd3e5af50,0x57858033,0x512226ac,0xd0176406,0x6fe6d50f, + 0xaeb8ef06,0xafec07b1 }, + { 0x80bb0a31,0x7fb99567,0x37309aae,0x6f1af3cc,0x01abf389,0x9153a15a, + 0x6e2dbfdd,0xa71b9354 }, + 0 }, + /* 233 */ + { { 0x18f593d2,0xbf8e12e0,0xa078122b,0xd1a90428,0x0ba4f2ad,0x150505db, + 0x628523d9,0x53a2005c }, + { 0xe7f2b935,0x07c8b639,0xc182961a,0x2bff975a,0x7518ca2c,0x86bceea7, + 0x3d588e3d,0xbf47d19b }, + 0 }, + /* 234 */ + { { 0xdd7665d5,0x672967a7,0x2f2f4de5,0x4e303057,0x80d4903f,0x144005ae, + 0x39c9a1b6,0x001c2c7f }, + { 0x69efc6d6,0x143a8014,0x7bc7a724,0xc810bdaa,0xa78150a4,0x5f65670b, + 0x86ffb99b,0xfdadf8e7 }, + 0 }, + /* 235 */ + { { 0xffc00785,0xfd38cb88,0x3b48eb67,0x77fa7591,0xbf368fbc,0x0454d055, + 0x5aa43c94,0x3a838e4d }, + { 0x3e97bb9a,0x56166329,0x441d94d9,0x9eb93363,0x0adb2a83,0x515591a6, + 0x873e1da3,0x3cdb8257 }, + 0 }, + /* 236 */ + { { 0x7de77eab,0x137140a9,0x41648109,0xf7e1c50d,0xceb1d0df,0x762dcad2, + 0xf1f57fba,0x5a60cc89 }, + { 0x40d45673,0x80b36382,0x5913c655,0x1b82be19,0xdd64b741,0x057284b8, + 0xdbfd8fc0,0x922ff56f }, + 0 }, + /* 237 */ + { { 0xc9a129a1,0x1b265dee,0xcc284e04,0xa5b1ce57,0xcebfbe3c,0x04380c46, + 0xf6c5cd62,0x72919a7d }, + { 0x8fb90f9a,0x298f453a,0x88e4031b,0xd719c00b,0x796f1856,0xe32c0e77, + 0x3624089a,0x5e791780 }, + 0 }, + /* 238 */ + { { 0x7f63cdfb,0x5c16ec55,0xf1cae4fd,0x8e6a3571,0x560597ca,0xfce26bea, + 0xe24c2fab,0x4e0a5371 }, + { 0xa5765357,0x276a40d3,0x0d73a2b4,0x3c89af44,0x41d11a32,0xb8f370ae, + 0xd56604ee,0xf5ff7818 }, + 0 }, + /* 239 */ + { { 0x1a09df21,0xfbf3e3fe,0xe66e8e47,0x26d5d28e,0x29c89015,0x2096bd0a, + 0x533f5e64,0xe41df0e9 }, + { 0xb3ba9e3f,0x305fda40,0x2604d895,0xf2340ceb,0x7f0367c7,0x0866e192, + 0xac4f155f,0x8edd7d6e }, + 0 }, + /* 240 */ + { { 0x0bfc8ff3,0xc9a1dc0e,0xe936f42f,0x14efd82b,0xcca381ef,0x67016f7c, + 0xed8aee96,0x1432c1ca }, + { 0x70b23c26,0xec684829,0x0735b273,0xa64fe873,0xeaef0f5a,0xe389f6e5, + 0x5ac8d2c6,0xcaef480b }, + 0 }, + /* 241 */ + { { 0x75315922,0x5245c978,0x3063cca5,0xd8295171,0xb64ef2cb,0xf3ce60d0, + 0x8efae236,0xd0ba177e }, + { 0xb1b3af60,0x53a9ae8f,0x3d2da20e,0x1a796ae5,0xdf9eef28,0x01d63605, + 0x1c54ae16,0xf31c957c }, + 0 }, + /* 242 */ + { { 0x49cc4597,0xc0f58d52,0xbae0a028,0xdc5015b0,0x734a814a,0xefc5fc55, + 0x96e17c3a,0x013404cb }, + { 0xc9a824bf,0xb29e2585,0x001eaed7,0xd593185e,0x61ef68ac,0x8d6ee682, + 0x91933e6c,0x6f377c4b }, + 0 }, + /* 243 */ + { { 0xa8333fd2,0x9f93bad1,0x5a2a95b8,0xa8930202,0xeaf75ace,0x211e5037, + 0xd2d09506,0x6dba3e4e }, + { 0xd04399cd,0xa48ef98c,0xe6b73ade,0x1811c66e,0xc17ecaf3,0x72f60752, + 0x3becf4a7,0xf13cf342 }, + 0 }, + /* 244 */ + { { 0xa919e2eb,0xceeb9ec0,0xf62c0f68,0x83a9a195,0x7aba2299,0xcfba3bb6, + 0x274bbad3,0xc83fa9a9 }, + { 0x62fa1ce0,0x0d7d1b0b,0x3418efbf,0xe58b60f5,0x52706f04,0xbfa8ef9e, + 0x5d702683,0xb49d70f4 }, + 0 }, + /* 245 */ + { { 0xfad5513b,0x914c7510,0xb1751e2d,0x05f32eec,0xd9fb9d59,0x6d850418, + 0x0c30f1cf,0x59cfadbb }, + { 0x55cb7fd6,0xe167ac23,0x820426a3,0x249367b8,0x90a78864,0xeaeec58c, + 0x354a4b67,0x5babf362 }, + 0 }, + /* 246 */ + { { 0xee424865,0x37c981d1,0xf2e5577f,0x8b002878,0xb9e0c058,0x702970f1, + 0x9026c8f0,0x6188c6a7 }, + { 0xd0f244da,0x06f9a19b,0xfb080873,0x1ecced5c,0x9f213637,0x35470f9b, + 0xdf50b9d9,0x993fe475 }, + 0 }, + /* 247 */ + { { 0x9b2c3609,0x68e31cdf,0x2c46d4ea,0x84eb19c0,0x9a775101,0x7ac9ec1a, + 0x4c80616b,0x81f76466 }, + { 0x75fbe978,0x1d7c2a5a,0xf183b356,0x6743fed3,0x501dd2bf,0x838d1f04, + 0x5fe9060d,0x564a812a }, + 0 }, + /* 248 */ + { { 0xfa817d1d,0x7a5a64f4,0xbea82e0f,0x55f96844,0xcd57f9aa,0xb5ff5a0f, + 0x00e51d6c,0x226bf3cf }, + { 0x2f2833cf,0xd6d1a9f9,0x4f4f89a8,0x20a0a35a,0x8f3f7f77,0x11536c49, + 0xff257836,0x68779f47 }, + 0 }, + /* 249 */ + { { 0x73043d08,0x79b0c1c1,0x1fc020fa,0xa5446774,0x9a6d26d0,0xd3767e28, + 0xeb092e0b,0x97bcb0d1 }, + { 0xf32ed3c3,0x2ab6eaa8,0xb281bc48,0xc8a4f151,0xbfa178f3,0x4d1bf4f3, + 0x0a784655,0xa872ffe8 }, + 0 }, + /* 250 */ + { { 0xa32b2086,0xb1ab7935,0x8160f486,0xe1eb710e,0x3b6ae6be,0x9bd0cd91, + 0xb732a36a,0x02812bfc }, + { 0xcf605318,0xa63fd7ca,0xfdfd6d1d,0x646e5d50,0x2102d619,0xa1d68398, + 0xfe5396af,0x07391cc9 }, + 0 }, + /* 251 */ + { { 0x8b80d02b,0xc50157f0,0x62877f7f,0x6b8333d1,0x78d542ae,0x7aca1af8, + 0x7e6d2a08,0x355d2adc }, + { 0x287386e1,0xb41f335a,0xf8e43275,0xfd272a94,0xe79989ea,0x286ca2cd, + 0x7c2a3a79,0x3dc2b1e3 }, + 0 }, + /* 252 */ + { { 0x04581352,0xd689d21c,0x376782be,0x0a00c825,0x9fed701f,0x203bd590, + 0x3ccd846b,0xc4786910 }, + { 0x24c768ed,0x5dba7708,0x6841f657,0x72feea02,0x6accce0e,0x73313ed5, + 0xd5bb4d32,0xccc42968 }, + 0 }, + /* 253 */ + { { 0x3d7620b9,0x94e50de1,0x5992a56a,0xd89a5c8a,0x675487c9,0xdc007640, + 0xaa4871cf,0xe147eb42 }, + { 0xacf3ae46,0x274ab4ee,0x50350fbe,0xfd4936fb,0x48c840ea,0xdf2afe47, + 0x080e96e3,0x239ac047 }, + 0 }, + /* 254 */ + { { 0x2bfee8d4,0x481d1f35,0xfa7b0fec,0xce80b5cf,0x2ce9af3c,0x105c4c9e, + 0xf5f7e59d,0xc55fa1a3 }, + { 0x8257c227,0x3186f14e,0x342be00b,0xc5b1653f,0xaa904fb2,0x09afc998, + 0xd4f4b699,0x094cd99c }, + 0 }, + /* 255 */ + { { 0xd703beba,0x8a981c84,0x32ceb291,0x8631d150,0xe3bd49ec,0xa445f2c9, + 0x42abad33,0xb90a30b6 }, + { 0xb4a5abf9,0xb465404f,0x75db7603,0x004750c3,0xca35d89f,0x6f9a42cc, + 0x1b7924f7,0x019f8b9a }, + 0 }, +}; + +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_base_8(sp_point* r, sp_digit* k, + int map, void* heap) +{ + return sp_256_ecc_mulmod_stripe_8(r, &p256_base, p256_table, + k, map, heap); +} + +#endif + +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * km Scalar to multiply by. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_base_256(mp_int* km, ecc_point* r, int map, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point p; + sp_digit kd[8]; +#endif + sp_point* point; + sp_digit* k = NULL; + int err = MP_OKAY; + + err = sp_ecc_point_new(heap, p, point); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + if (err == MP_OKAY) { + sp_256_from_mp(k, 8, km); + + err = sp_256_ecc_mulmod_base_8(point, k, map, heap); + } + if (err == MP_OKAY) + err = sp_256_point_to_ecc_point_8(point, r); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(point, 0, heap); + + return err; +} + +#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ + defined(HAVE_ECC_VERIFY) +/* Returns 1 if the number of zero. + * Implementation is constant time. + * + * a Number to check. + * returns 1 if the number is zero and 0 otherwise. + */ +static int sp_256_iszero_8(const sp_digit* a) +{ + return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6] | a[7]) == 0; +} + +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN || HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +/* Add 1 to a. (a = a + 1) + * + * a A single precision integer. + */ +static void sp_256_add_one_8(sp_digit* a) +{ + __asm__ __volatile__ ( + "ldr r1, [%[a], #0]\n\t" + "ldr r2, [%[a], #4]\n\t" + "ldr r3, [%[a], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "adds r1, r1, #1\n\t" + "adcs r2, r2, #0\n\t" + "adcs r3, r3, #0\n\t" + "adcs r4, r4, #0\n\t" + "str r1, [%[a], #0]\n\t" + "str r2, [%[a], #4]\n\t" + "str r3, [%[a], #8]\n\t" + "str r4, [%[a], #12]\n\t" + "ldr r1, [%[a], #16]\n\t" + "ldr r2, [%[a], #20]\n\t" + "ldr r3, [%[a], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "adcs r1, r1, #0\n\t" + "adcs r2, r2, #0\n\t" + "adcs r3, r3, #0\n\t" + "adcs r4, r4, #0\n\t" + "str r1, [%[a], #16]\n\t" + "str r2, [%[a], #20]\n\t" + "str r3, [%[a], #24]\n\t" + "str r4, [%[a], #28]\n\t" + : + : [a] "r" (a) + : "memory", "r1", "r2", "r3", "r4" + ); +} + +/* Read big endian unsigned byte aray into r. + * + * r A single precision integer. + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_256_from_bin(sp_digit* r, int max, const byte* a, int n) +{ + int i, j = 0, s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= ((sp_digit)a[i]) << s; + if (s >= 24) { + r[j] &= 0xffffffff; + s = 32 - s; + if (j + 1 >= max) + break; + r[++j] = a[i] >> s; + s = 8 - s; + } + else + s += 8; + } + + for (j++; j < max; j++) + r[j] = 0; +} + +/* Generates a scalar that is in the range 1..order-1. + * + * rng Random number generator. + * k Scalar value. + * returns RNG failures, MEMORY_E when memory allocation fails and + * MP_OKAY on success. + */ +static int sp_256_ecc_gen_k_8(WC_RNG* rng, sp_digit* k) +{ + int err; + byte buf[32]; + + do { + err = wc_RNG_GenerateBlock(rng, buf, sizeof(buf)); + if (err == 0) { + sp_256_from_bin(k, 8, buf, sizeof(buf)); + if (sp_256_cmp_8(k, p256_order2) < 0) { + sp_256_add_one_8(k); + break; + } + } + } + while (err == 0); + + return err; +} + +/* Makes a random EC key pair. + * + * rng Random number generator. + * priv Generated private value. + * pub Generated public point. + * heap Heap to use for allocation. + * returns ECC_INF_E when the point does not have the correct order, RNG + * failures, MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point p; + sp_digit kd[8]; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point inf; +#endif +#endif + sp_point* point; + sp_digit* k = NULL; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point* infinity; +#endif + int err; + + (void)heap; + + err = sp_ecc_point_new(heap, p, point); +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, inf, infinity); +#endif +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + + if (err == MP_OKAY) + err = sp_256_ecc_gen_k_8(rng, k); + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_base_8(point, k, 1, NULL); + } + +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_8(infinity, point, p256_order, 1, NULL); + } + if (err == MP_OKAY) { + if (!sp_256_iszero_8(point->x) || !sp_256_iszero_8(point->y)) + err = ECC_INF_E; + } +#endif + + if (err == MP_OKAY) + err = sp_256_to_mp(k, priv); + if (err == MP_OKAY) + err = sp_256_point_to_ecc_point_8(point, pub); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); +#endif +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_ecc_point_free(infinity, 1, heap); +#endif + sp_ecc_point_free(point, 1, heap); + + return err; +} + +#ifdef HAVE_ECC_DHE +/* Write r as big endian to byte aray. + * Fixed length number of bytes written: 32 + * + * r A single precision integer. + * a Byte array. + */ +static void sp_256_to_bin(sp_digit* r, byte* a) +{ + int i, j, s = 0, b; + + j = 256 / 8 - 1; + a[j] = 0; + for (i=0; i<8 && j>=0; i++) { + b = 0; + a[j--] |= r[i] << s; b += 8 - s; + if (j < 0) + break; + while (b < 32) { + a[j--] = r[i] >> b; b += 8; + if (j < 0) + break; + } + s = 8 - (b - 32); + if (j >= 0) + a[j] = 0; + if (s != 0) + j++; + } +} + +/* Multiply the point by the scalar and serialize the X ordinate. + * The number is 0 padded to maximum size on output. + * + * priv Scalar to multiply the point by. + * pub Point to multiply. + * out Buffer to hold X ordinate. + * outLen On entry, size of the buffer in bytes. + * On exit, length of data in buffer in bytes. + * heap Heap to use for allocation. + * returns BUFFER_E if the buffer is to small for output size, + * MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_secret_gen_256(mp_int* priv, ecc_point* pub, byte* out, + word32* outLen, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point p; + sp_digit kd[8]; +#endif + sp_point* point = NULL; + sp_digit* k = NULL; + int err = MP_OKAY; + + if (*outLen < 32) + err = BUFFER_E; + + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, p, point); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(k, 8, priv); + sp_256_point_from_ecc_point_8(point, pub); + err = sp_256_ecc_mulmod_8(point, point, k, 1, heap); + } + if (err == MP_OKAY) { + sp_256_to_bin(point->x, out); + *outLen = 32; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(point, 0, heap); + + return err; +} +#endif /* HAVE_ECC_DHE */ + +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +#ifdef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_256_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + __asm__ __volatile__ ( + "sub sp, sp, #64\n\t" + "mov r5, #0\n\t" + "mov r6, #0\n\t" + "mov r7, #0\n\t" + "mov r8, #0\n\t" + "\n1:\n\t" + "subs r3, r5, #28\n\t" + "movcc r3, #0\n\t" + "sub r4, r5, r3\n\t" + "\n2:\n\t" + "ldr r14, [%[a], r3]\n\t" + "ldr r12, [%[b], r4]\n\t" + "umull r9, r10, r14, r12\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, #0\n\t" + "add r3, r3, #4\n\t" + "sub r4, r4, #4\n\t" + "cmp r3, #32\n\t" + "beq 3f\n\t" + "cmp r3, r5\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "str r6, [sp, r5]\n\t" + "mov r6, r7\n\t" + "mov r7, r8\n\t" + "mov r8, #0\n\t" + "add r5, r5, #4\n\t" + "cmp r5, #56\n\t" + "ble 1b\n\t" + "str r6, [sp, r5]\n\t" + "\n4:\n\t" + "ldr r6, [sp, #0]\n\t" + "ldr r7, [sp, #4]\n\t" + "ldr r8, [sp, #8]\n\t" + "ldr r3, [sp, #12]\n\t" + "str r6, [%[r], #0]\n\t" + "str r7, [%[r], #4]\n\t" + "str r8, [%[r], #8]\n\t" + "str r3, [%[r], #12]\n\t" + "add sp, sp, #16\n\t" + "add %[r], %[r], #16\n\t" + "subs r5, r5, #16\n\t" + "bgt 4b\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r12" + ); +} + +#else +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_256_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + __asm__ __volatile__ ( + "sub sp, sp, #32\n\t" + "mov r10, #0\n\t" + "# A[0] * B[0]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r3, r4, r8, r9\n\t" + "mov r5, #0\n\t" + "str r3, [sp]\n\t" + "# A[0] * B[1]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[1] * B[0]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #4]\n\t" + "# A[0] * B[2]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[1] * B[1]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[2] * B[0]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [sp, #8]\n\t" + "# A[0] * B[3]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[1] * B[2]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[2] * B[1]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[0]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [sp, #12]\n\t" + "# A[0] * B[4]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[1] * B[3]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[2] * B[2]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[3] * B[1]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[4] * B[0]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #16]\n\t" + "# A[0] * B[5]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[1] * B[4]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[2] * B[3]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[3] * B[2]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[4] * B[1]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[5] * B[0]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [sp, #20]\n\t" + "# A[0] * B[6]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[1] * B[5]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[2] * B[4]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[3] * B[3]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[4] * B[2]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[5] * B[1]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[6] * B[0]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [sp, #24]\n\t" + "# A[0] * B[7]\n\t" + "ldr r8, [%[a], #0]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[1] * B[6]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[2] * B[5]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[3] * B[4]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[4] * B[3]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[5] * B[2]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[6] * B[1]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[7] * B[0]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #0]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [sp, #28]\n\t" + "# A[1] * B[7]\n\t" + "ldr r8, [%[a], #4]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[2] * B[6]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[3] * B[5]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[4] * B[4]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[5] * B[3]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[6] * B[2]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[7] * B[1]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #4]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #32]\n\t" + "# A[2] * B[7]\n\t" + "ldr r8, [%[a], #8]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[3] * B[6]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[4] * B[5]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[5] * B[4]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[6] * B[3]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[7] * B[2]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #8]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #36]\n\t" + "# A[3] * B[7]\n\t" + "ldr r8, [%[a], #12]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[4] * B[6]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[5] * B[5]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[6] * B[4]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "# A[7] * B[3]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #12]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #40]\n\t" + "# A[4] * B[7]\n\t" + "ldr r8, [%[a], #16]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r10, r10\n\t" + "# A[5] * B[6]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[6] * B[5]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "# A[7] * B[4]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #16]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #44]\n\t" + "# A[5] * B[7]\n\t" + "ldr r8, [%[a], #20]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r10, r10\n\t" + "# A[6] * B[6]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "# A[7] * B[5]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #20]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #48]\n\t" + "# A[6] * B[7]\n\t" + "ldr r8, [%[a], #24]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r10, r10\n\t" + "# A[7] * B[6]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #24]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #52]\n\t" + "# A[7] * B[7]\n\t" + "ldr r8, [%[a], #28]\n\t" + "ldr r9, [%[b], #28]\n\t" + "umull r6, r7, r8, r9\n\t" + "adds r5, r5, r6\n\t" + "adc r3, r3, r7\n\t" + "str r5, [%[r], #56]\n\t" + "str r3, [%[r], #60]\n\t" + "ldr r3, [sp, #0]\n\t" + "ldr r4, [sp, #4]\n\t" + "ldr r5, [sp, #8]\n\t" + "ldr r6, [sp, #12]\n\t" + "str r3, [%[r], #0]\n\t" + "str r4, [%[r], #4]\n\t" + "str r5, [%[r], #8]\n\t" + "str r6, [%[r], #12]\n\t" + "ldr r3, [sp, #16]\n\t" + "ldr r4, [sp, #20]\n\t" + "ldr r5, [sp, #24]\n\t" + "ldr r6, [sp, #28]\n\t" + "str r3, [%[r], #16]\n\t" + "str r4, [%[r], #20]\n\t" + "str r5, [%[r], #24]\n\t" + "str r6, [%[r], #28]\n\t" + "add sp, sp, #32\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10" + ); +} + +#endif /* WOLFSSL_SP_SMALL */ +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into a. (a -= b) + * + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_256_sub_in_place_8(sp_digit* a, const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r14, #0\n\t" + "add r12, %[a], #32\n\t" + "\n1:\n\t" + "subs %[c], r14, %[c]\n\t" + "ldr r3, [%[a]]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[a], #8]\n\t" + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b]], #4\n\t" + "ldr r8, [%[b]], #4\n\t" + "ldr r9, [%[b]], #4\n\t" + "ldr r10, [%[b]], #4\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "sbcs r6, r6, r10\n\t" + "str r3, [%[a]], #4\n\t" + "str r4, [%[a]], #4\n\t" + "str r5, [%[a]], #4\n\t" + "str r6, [%[a]], #4\n\t" + "sbc %[c], r14, r14\n\t" + "cmp %[a], r12\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r12", "r14" + ); + + return c; +} + +#else +/* Sub b from a into a. (a -= b) + * + * a A single precision integer and result. + * b A single precision integer. + */ +static sp_digit sp_256_sub_in_place_8(sp_digit* a, const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r2, [%[a], #0]\n\t" + "ldr r3, [%[a], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[a], #12]\n\t" + "ldr r6, [%[b], #0]\n\t" + "ldr r7, [%[b], #4]\n\t" + "ldr r8, [%[b], #8]\n\t" + "ldr r9, [%[b], #12]\n\t" + "subs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #0]\n\t" + "str r3, [%[a], #4]\n\t" + "str r4, [%[a], #8]\n\t" + "str r5, [%[a], #12]\n\t" + "ldr r2, [%[a], #16]\n\t" + "ldr r3, [%[a], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[a], #28]\n\t" + "ldr r6, [%[b], #16]\n\t" + "ldr r7, [%[b], #20]\n\t" + "ldr r8, [%[b], #24]\n\t" + "ldr r9, [%[b], #28]\n\t" + "sbcs r2, r2, r6\n\t" + "sbcs r3, r3, r7\n\t" + "sbcs r4, r4, r8\n\t" + "sbcs r5, r5, r9\n\t" + "str r2, [%[a], #16]\n\t" + "str r3, [%[a], #20]\n\t" + "str r4, [%[a], #24]\n\t" + "str r5, [%[a], #28]\n\t" + "sbc %[c], r9, r9\n\t" + : [c] "+r" (c) + : [a] "r" (a), [b] "r" (b) + : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Mul a by digit b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision digit. + */ +static void sp_256_mul_d_8(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov r10, #0\n\t" + "# A[0] * B\n\t" + "ldr r8, [%[a]]\n\t" + "umull r5, r3, %[b], r8\n\t" + "mov r4, #0\n\t" + "str r5, [%[r]]\n\t" + "mov r5, #0\n\t" + "mov r9, #4\n\t" + "1:\n\t" + "ldr r8, [%[a], r9]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], r9]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "add r9, r9, #4\n\t" + "cmp r9, #32\n\t" + "blt 1b\n\t" + "str r3, [%[r], #32]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10" + ); +#else + __asm__ __volatile__ ( + "mov r10, #0\n\t" + "# A[0] * B\n\t" + "ldr r8, [%[a]]\n\t" + "umull r3, r4, %[b], r8\n\t" + "mov r5, #0\n\t" + "str r3, [%[r]]\n\t" + "# A[1] * B\n\t" + "ldr r8, [%[a], #4]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #4]\n\t" + "# A[2] * B\n\t" + "ldr r8, [%[a], #8]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #8]\n\t" + "# A[3] * B\n\t" + "ldr r8, [%[a], #12]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #12]\n\t" + "# A[4] * B\n\t" + "ldr r8, [%[a], #16]\n\t" + "mov r3, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, r10\n\t" + "str r4, [%[r], #16]\n\t" + "# A[5] * B\n\t" + "ldr r8, [%[a], #20]\n\t" + "mov r4, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, r10\n\t" + "str r5, [%[r], #20]\n\t" + "# A[6] * B\n\t" + "ldr r8, [%[a], #24]\n\t" + "mov r5, #0\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r10\n\t" + "str r3, [%[r], #24]\n\t" + "# A[7] * B\n\t" + "ldr r8, [%[a], #28]\n\t" + "umull r6, r7, %[b], r8\n\t" + "adds r4, r4, r6\n\t" + "adc r5, r5, r7\n\t" + "str r4, [%[r], #28]\n\t" + "str r5, [%[r], #32]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10" + ); +#endif +} + +/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) + * + * d1 The high order half of the number to divide. + * d0 The low order half of the number to divide. + * div The dividend. + * returns the result of the division. + * + * Note that this is an approximate div. It may give an answer 1 larger. + */ +static sp_digit div_256_word_8(sp_digit d1, sp_digit d0, sp_digit div) +{ + sp_digit r = 0; + + __asm__ __volatile__ ( + "lsr r5, %[div], #1\n\t" + "add r5, r5, #1\n\t" + "mov r6, %[d0]\n\t" + "mov r7, %[d1]\n\t" + "# Do top 32\n\t" + "subs r8, r5, r7\n\t" + "sbc r8, r8, r8\n\t" + "add %[r], %[r], %[r]\n\t" + "sub %[r], %[r], r8\n\t" + "and r8, r8, r5\n\t" + "subs r7, r7, r8\n\t" + "# Next 30 bits\n\t" + "mov r4, #29\n\t" + "1:\n\t" + "movs r6, r6, lsl #1\n\t" + "adc r7, r7, r7\n\t" + "subs r8, r5, r7\n\t" + "sbc r8, r8, r8\n\t" + "add %[r], %[r], %[r]\n\t" + "sub %[r], %[r], r8\n\t" + "and r8, r8, r5\n\t" + "subs r7, r7, r8\n\t" + "subs r4, r4, #1\n\t" + "bpl 1b\n\t" + "add %[r], %[r], %[r]\n\t" + "add %[r], %[r], #1\n\t" + "umull r4, r5, %[r], %[div]\n\t" + "subs r4, %[d0], r4\n\t" + "sbc r5, %[d1], r5\n\t" + "add %[r], %[r], r5\n\t" + "umull r4, r5, %[r], %[div]\n\t" + "subs r4, %[d0], r4\n\t" + "sbc r5, %[d1], r5\n\t" + "add %[r], %[r], r5\n\t" + "subs r8, %[div], r4\n\t" + "sbc r8, r8, r8\n\t" + "sub %[r], %[r], r8\n\t" + : [r] "+r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "r4", "r5", "r6", "r7", "r8" + ); + return r; +} + +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_256_mask_8(sp_digit* r, sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<8; i++) + r[i] = a[i] & m; +#else + r[0] = a[0] & m; + r[1] = a[1] & m; + r[2] = a[2] & m; + r[3] = a[3] & m; + r[4] = a[4] & m; + r[5] = a[5] & m; + r[6] = a[6] & m; + r[7] = a[7] & m; +#endif +} + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_256_div_8(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[16], t2[9]; + sp_digit div, r1; + int i; + + (void)m; + + div = d[7]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 8); + for (i=7; i>=0; i--) { + r1 = div_256_word_8(t1[8 + i], t1[8 + i - 1], div); + + sp_256_mul_d_8(t2, d, r1); + t1[8 + i] += sp_256_sub_in_place_8(&t1[i], t2); + t1[8 + i] -= t2[8]; + sp_256_mask_8(t2, d, t1[8 + i]); + t1[8 + i] += sp_256_add_8(&t1[i], &t1[i], t2); + sp_256_mask_8(t2, d, t1[8 + i]); + t1[8 + i] += sp_256_add_8(&t1[i], &t1[i], t2); + } + + r1 = sp_256_cmp_8(t1, d) >= 0; + sp_256_cond_sub_8(r, t1, d, (sp_digit)0 - r1); + + return MP_OKAY; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_256_mod_8(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_256_div_8(a, m, NULL, r); +} + +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +#ifdef WOLFSSL_SP_SMALL +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_256_sqr_8(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "sub sp, sp, #64\n\t" + "mov r12, #0\n\t" + "mov r6, #0\n\t" + "mov r7, #0\n\t" + "mov r8, #0\n\t" + "mov r5, #0\n\t" + "\n1:\n\t" + "subs r3, r5, #28\n\t" + "movcc r3, r12\n\t" + "sub r4, r5, r3\n\t" + "\n2:\n\t" + "cmp r4, r3\n\t" + "beq 4f\n\t" + "ldr r14, [%[a], r3]\n\t" + "ldr r9, [%[a], r4]\n\t" + "umull r9, r10, r14, r9\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, r12\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, r12\n\t" + "bal 5f\n\t" + "\n4:\n\t" + "ldr r14, [%[a], r3]\n\t" + "umull r9, r10, r14, r14\n\t" + "adds r6, r6, r9\n\t" + "adcs r7, r7, r10\n\t" + "adc r8, r8, r12\n\t" + "\n5:\n\t" + "add r3, r3, #4\n\t" + "sub r4, r4, #4\n\t" + "cmp r3, #32\n\t" + "beq 3f\n\t" + "cmp r3, r4\n\t" + "bgt 3f\n\t" + "cmp r3, r5\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "str r6, [sp, r5]\n\t" + "mov r6, r7\n\t" + "mov r7, r8\n\t" + "mov r8, #0\n\t" + "add r5, r5, #4\n\t" + "cmp r5, #56\n\t" + "ble 1b\n\t" + "str r6, [sp, r5]\n\t" + "\n4:\n\t" + "ldr r6, [sp, #0]\n\t" + "ldr r7, [sp, #4]\n\t" + "ldr r8, [sp, #8]\n\t" + "ldr r3, [sp, #12]\n\t" + "str r6, [%[r], #0]\n\t" + "str r7, [%[r], #4]\n\t" + "str r8, [%[r], #8]\n\t" + "str r3, [%[r], #12]\n\t" + "add sp, sp, #16\n\t" + "add %[r], %[r], #16\n\t" + "subs r5, r5, #16\n\t" + "bgt 4b\n\t" + : [r] "+r" (r) + : [a] "r" (a) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r14", "r9", "r12" + ); +} + +#else +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_256_sqr_8(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "sub sp, sp, #32\n\t" + "mov r14, #0\n\t" + "# A[0] * A[0]\n\t" + "ldr r10, [%[a], #0]\n\t" + "umull r8, r3, r10, r10\n\t" + "mov r4, #0\n\t" + "str r8, [sp]\n\t" + "# A[0] * A[1]\n\t" + "ldr r10, [%[a], #4]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r14, r14\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "str r3, [sp, #4]\n\t" + "# A[0] * A[2]\n\t" + "ldr r10, [%[a], #8]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r14, r14\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r14\n\t" + "# A[1] * A[1]\n\t" + "ldr r10, [%[a], #4]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r14\n\t" + "str r4, [sp, #8]\n\t" + "# A[0] * A[3]\n\t" + "ldr r10, [%[a], #12]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r14, r14\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r14\n\t" + "# A[1] * A[2]\n\t" + "ldr r10, [%[a], #8]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r14\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r14\n\t" + "str r2, [sp, #12]\n\t" + "# A[0] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r14, r14\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "# A[1] * A[3]\n\t" + "ldr r10, [%[a], #12]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "# A[2] * A[2]\n\t" + "ldr r10, [%[a], #8]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "str r3, [sp, #16]\n\t" + "# A[0] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[3]\n\t" + "ldr r10, [%[a], #12]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [sp, #20]\n\t" + "# A[0] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[3]\n\t" + "ldr r10, [%[a], #12]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [sp, #24]\n\t" + "# A[0] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #0]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r2, #0\n\t" + "mov r7, #0\n\t" + "# A[1] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[2] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r6\n\t" + "adc r2, r2, r7\n\t" + "str r3, [sp, #28]\n\t" + "# A[1] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #4]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "# A[2] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[3] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[4]\n\t" + "ldr r10, [%[a], #16]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r4, r4, r5\n\t" + "adcs r2, r2, r6\n\t" + "adc r3, r3, r7\n\t" + "str r4, [%[r], #32]\n\t" + "# A[2] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #8]\n\t" + "umull r5, r6, r10, r8\n\t" + "mov r4, #0\n\t" + "mov r7, #0\n\t" + "# A[3] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "# A[4] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r5, r5, r8\n\t" + "adcs r6, r6, r9\n\t" + "adc r7, r7, r14\n\t" + "adds r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adc r7, r7, r7\n\t" + "adds r2, r2, r5\n\t" + "adcs r3, r3, r6\n\t" + "adc r4, r4, r7\n\t" + "str r2, [%[r], #36]\n\t" + "# A[3] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #12]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r14, r14\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "# A[4] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "# A[5] * A[5]\n\t" + "ldr r10, [%[a], #20]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "str r3, [%[r], #40]\n\t" + "# A[4] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #16]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r14, r14\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r14\n\t" + "# A[5] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r14\n\t" + "adds r4, r4, r8\n\t" + "adcs r2, r2, r9\n\t" + "adc r3, r3, r14\n\t" + "str r4, [%[r], #44]\n\t" + "# A[5] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #20]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r14, r14\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r14\n\t" + "# A[6] * A[6]\n\t" + "ldr r10, [%[a], #24]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r2, r2, r8\n\t" + "adcs r3, r3, r9\n\t" + "adc r4, r4, r14\n\t" + "str r2, [%[r], #48]\n\t" + "# A[6] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "ldr r8, [%[a], #24]\n\t" + "umull r8, r9, r10, r8\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r14, r14\n\t" + "adds r3, r3, r8\n\t" + "adcs r4, r4, r9\n\t" + "adc r2, r2, r14\n\t" + "str r3, [%[r], #52]\n\t" + "# A[7] * A[7]\n\t" + "ldr r10, [%[a], #28]\n\t" + "umull r8, r9, r10, r10\n\t" + "adds r4, r4, r8\n\t" + "adc r2, r2, r9\n\t" + "str r4, [%[r], #56]\n\t" + "str r2, [%[r], #60]\n\t" + "ldr r2, [sp, #0]\n\t" + "ldr r3, [sp, #4]\n\t" + "ldr r4, [sp, #8]\n\t" + "ldr r8, [sp, #12]\n\t" + "str r2, [%[r], #0]\n\t" + "str r3, [%[r], #4]\n\t" + "str r4, [%[r], #8]\n\t" + "str r8, [%[r], #12]\n\t" + "ldr r2, [sp, #16]\n\t" + "ldr r3, [sp, #20]\n\t" + "ldr r4, [sp, #24]\n\t" + "ldr r8, [sp, #28]\n\t" + "str r2, [%[r], #16]\n\t" + "str r3, [%[r], #20]\n\t" + "str r4, [%[r], #24]\n\t" + "str r8, [%[r], #28]\n\t" + "add sp, sp, #32\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r8", "r9", "r10", "r8", "r5", "r6", "r7", "r14" + ); +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Order-2 for the P256 curve. */ +static const uint32_t p256_order_2[8] = { + 0xfc63254f,0xf3b9cac2,0xa7179e84,0xbce6faad,0xffffffff,0xffffffff, + 0x00000000,0xffffffff +}; +#else +/* The low half of the order-2 of the P256 curve. */ +static const uint32_t p256_order_low[4] = { + 0xfc63254f,0xf3b9cac2,0xa7179e84,0xbce6faad +}; +#endif /* WOLFSSL_SP_SMALL */ + +/* Multiply two number mod the order of P256 curve. (r = a * b mod order) + * + * r Result of the multiplication. + * a First operand of the multiplication. + * b Second operand of the multiplication. + */ +static void sp_256_mont_mul_order_8(sp_digit* r, sp_digit* a, sp_digit* b) +{ + sp_256_mul_8(r, a, b); + sp_256_mont_reduce_order_8(r, p256_order, p256_mp_order); +} + +/* Square number mod the order of P256 curve. (r = a * a mod order) + * + * r Result of the squaring. + * a Number to square. + */ +static void sp_256_mont_sqr_order_8(sp_digit* r, sp_digit* a) +{ + sp_256_sqr_8(r, a); + sp_256_mont_reduce_order_8(r, p256_order, p256_mp_order); +} + +#ifndef WOLFSSL_SP_SMALL +/* Square number mod the order of P256 curve a number of times. + * (r = a ^ n mod order) + * + * r Result of the squaring. + * a Number to square. + */ +static void sp_256_mont_sqr_n_order_8(sp_digit* r, sp_digit* a, int n) +{ + int i; + + sp_256_mont_sqr_order_8(r, a); + for (i=1; i=0; i--) { + sp_256_mont_sqr_order_8(t, t); + if (p256_order_2[i / 32] & ((sp_digit)1 << (i % 32))) + sp_256_mont_mul_order_8(t, t, a); + } + XMEMCPY(r, t, sizeof(sp_digit) * 8); +#else + sp_digit* t = td; + sp_digit* t2 = td + 2 * 8; + sp_digit* t3 = td + 4 * 8; + int i; + + /* t = a^2 */ + sp_256_mont_sqr_order_8(t, a); + /* t = a^3 = t * a */ + sp_256_mont_mul_order_8(t, t, a); + /* t2= a^c = t ^ 2 ^ 2 */ + sp_256_mont_sqr_n_order_8(t2, t, 2); + /* t3= a^f = t2 * t */ + sp_256_mont_mul_order_8(t3, t2, t); + /* t2= a^f0 = t3 ^ 2 ^ 4 */ + sp_256_mont_sqr_n_order_8(t2, t3, 4); + /* t = a^ff = t2 * t3 */ + sp_256_mont_mul_order_8(t, t2, t3); + /* t3= a^ff00 = t ^ 2 ^ 8 */ + sp_256_mont_sqr_n_order_8(t2, t, 8); + /* t = a^ffff = t2 * t */ + sp_256_mont_mul_order_8(t, t2, t); + /* t2= a^ffff0000 = t ^ 2 ^ 16 */ + sp_256_mont_sqr_n_order_8(t2, t, 16); + /* t = a^ffffffff = t2 * t */ + sp_256_mont_mul_order_8(t, t2, t); + /* t2= a^ffffffff0000000000000000 = t ^ 2 ^ 64 */ + sp_256_mont_sqr_n_order_8(t2, t, 64); + /* t2= a^ffffffff00000000ffffffff = t2 * t */ + sp_256_mont_mul_order_8(t2, t2, t); + /* t2= a^ffffffff00000000ffffffff00000000 = t2 ^ 2 ^ 32 */ + sp_256_mont_sqr_n_order_8(t2, t2, 32); + /* t2= a^ffffffff00000000ffffffffffffffff = t2 * t */ + sp_256_mont_mul_order_8(t2, t2, t); + /* t2= a^ffffffff00000000ffffffffffffffffbce6 */ + for (i=127; i>=112; i--) { + sp_256_mont_sqr_order_8(t2, t2); + if (p256_order_low[i / 32] & ((sp_digit)1 << (i % 32))) + sp_256_mont_mul_order_8(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6f */ + sp_256_mont_sqr_n_order_8(t2, t2, 4); + sp_256_mont_mul_order_8(t2, t2, t3); + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84 */ + for (i=107; i>=64; i--) { + sp_256_mont_sqr_order_8(t2, t2); + if (p256_order_low[i / 32] & ((sp_digit)1 << (i % 32))) + sp_256_mont_mul_order_8(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f */ + sp_256_mont_sqr_n_order_8(t2, t2, 4); + sp_256_mont_mul_order_8(t2, t2, t3); + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2 */ + for (i=59; i>=32; i--) { + sp_256_mont_sqr_order_8(t2, t2); + if (p256_order_low[i / 32] & ((sp_digit)1 << (i % 32))) + sp_256_mont_mul_order_8(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2f */ + sp_256_mont_sqr_n_order_8(t2, t2, 4); + sp_256_mont_mul_order_8(t2, t2, t3); + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254 */ + for (i=27; i>=0; i--) { + sp_256_mont_sqr_order_8(t2, t2); + if (p256_order_low[i / 32] & ((sp_digit)1 << (i % 32))) + sp_256_mont_mul_order_8(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632540 */ + sp_256_mont_sqr_n_order_8(t2, t2, 4); + /* r = a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f */ + sp_256_mont_mul_order_8(r, t2, t3); +#endif /* WOLFSSL_SP_SMALL */ +} + +#endif /* HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +#ifdef HAVE_ECC_SIGN +#ifndef SP_ECC_MAX_SIG_GEN +#define SP_ECC_MAX_SIG_GEN 64 +#endif + +/* Sign the hash using the private key. + * e = [hash, 256 bits] from binary + * r = (k.G)->x mod order + * s = (r * x + e) / k mod order + * The hash is truncated to the first 256 bits. + * + * hash Hash to sign. + * hashLen Length of the hash data. + * rng Random number generator. + * priv Private part of key - scalar. + * rm First part of result as an mp_int. + * sm Sirst part of result as an mp_int. + * heap Heap to use for allocation. + * returns RNG failures, MEMORY_E when memory allocation fails and + * MP_OKAY on success. + */ +int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, + mp_int* rm, mp_int* sm, void* heap) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d = NULL; +#else + sp_digit ed[2*8]; + sp_digit xd[2*8]; + sp_digit kd[2*8]; + sp_digit rd[2*8]; + sp_digit td[3 * 2*8]; + sp_point p; +#endif + sp_digit* e = NULL; + sp_digit* x = NULL; + sp_digit* k = NULL; + sp_digit* r = NULL; + sp_digit* tmp = NULL; + sp_point* point = NULL; + sp_digit carry; + sp_digit* s; + sp_digit* kInv; + int err = MP_OKAY; + int32_t c; + int i; + + (void)heap; + + err = sp_ecc_point_new(heap, p, point); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 8, heap, + DYNAMIC_TYPE_ECC); + if (d != NULL) { + e = d + 0 * 8; + x = d + 2 * 8; + k = d + 4 * 8; + r = d + 6 * 8; + tmp = d + 8 * 8; + } + else + err = MEMORY_E; + } +#else + e = ed; + x = xd; + k = kd; + r = rd; + tmp = td; +#endif + s = e; + kInv = k; + + if (err == MP_OKAY) { + if (hashLen > 32) + hashLen = 32; + + sp_256_from_bin(e, 8, hash, hashLen); + } + + for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { + sp_256_from_mp(x, 8, priv); + + /* New random point. */ + err = sp_256_ecc_gen_k_8(rng, k); + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_base_8(point, k, 1, NULL); + } + + if (err == MP_OKAY) { + /* r = point->x mod order */ + XMEMCPY(r, point->x, sizeof(sp_digit) * 8); + sp_256_norm_8(r); + c = sp_256_cmp_8(r, p256_order); + sp_256_cond_sub_8(r, r, p256_order, 0 - (c >= 0)); + sp_256_norm_8(r); + + /* Conv k to Montgomery form (mod order) */ + sp_256_mul_8(k, k, p256_norm_order); + err = sp_256_mod_8(k, k, p256_order); + } + if (err == MP_OKAY) { + sp_256_norm_8(k); + /* kInv = 1/k mod order */ + sp_256_mont_inv_order_8(kInv, k, tmp); + sp_256_norm_8(kInv); + + /* s = r * x + e */ + sp_256_mul_8(x, x, r); + err = sp_256_mod_8(x, x, p256_order); + } + if (err == MP_OKAY) { + sp_256_norm_8(x); + carry = sp_256_add_8(s, e, x); + sp_256_cond_sub_8(s, s, p256_order, 0 - carry); + sp_256_norm_8(s); + c = sp_256_cmp_8(s, p256_order); + sp_256_cond_sub_8(s, s, p256_order, 0 - (c >= 0)); + sp_256_norm_8(s); + + /* s = s * k^-1 mod order */ + sp_256_mont_mul_order_8(s, s, kInv); + sp_256_norm_8(s); + + /* Check that signature is usable. */ + if (!sp_256_iszero_8(s)) + break; + } + } + + if (i == 0) + err = RNG_FAILURE_E; + + if (err == MP_OKAY) + err = sp_256_to_mp(r, rm); + if (err == MP_OKAY) + err = sp_256_to_mp(s, sm); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) { + XMEMSET(d, 0, sizeof(sp_digit) * 8 * 8); + XFREE(d, heap, DYNAMIC_TYPE_ECC); + } +#else + XMEMSET(e, 0, sizeof(sp_digit) * 2 * 8); + XMEMSET(x, 0, sizeof(sp_digit) * 2 * 8); + XMEMSET(k, 0, sizeof(sp_digit) * 2 * 8); + XMEMSET(r, 0, sizeof(sp_digit) * 2 * 8); + XMEMSET(r, 0, sizeof(sp_digit) * 2 * 8); + XMEMSET(tmp, 0, sizeof(sp_digit) * 3 * 2*8); +#endif + sp_ecc_point_free(point, 1, heap); + + return err; +} +#endif /* HAVE_ECC_SIGN */ + +#ifdef HAVE_ECC_VERIFY +/* Verify the signature values with the hash and public key. + * e = Truncate(hash, 256) + * u1 = e/s mod order + * u2 = r/s mod order + * r == (u1.G + u2.Q)->x mod order + * Optimization: Leave point in projective form. + * (x, y, 1) == (x' / z'*z', y' / z'*z'*z', z' / z') + * (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' + * The hash is truncated to the first 256 bits. + * + * hash Hash to sign. + * hashLen Length of the hash data. + * rng Random number generator. + * priv Private part of key - scalar. + * rm First part of result as an mp_int. + * sm Sirst part of result as an mp_int. + * heap Heap to use for allocation. + * returns RNG failures, MEMORY_E when memory allocation fails and + * MP_OKAY on success. + */ +int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, + mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d = NULL; +#else + sp_digit u1d[2*8]; + sp_digit u2d[2*8]; + sp_digit sd[2*8]; + sp_digit tmpd[2*8 * 5]; + sp_point p1d; + sp_point p2d; +#endif + sp_digit* u1; + sp_digit* u2; + sp_digit* s; + sp_digit* tmp; + sp_point* p1; + sp_point* p2 = NULL; + sp_digit carry; + int32_t c; + int err; + + err = sp_ecc_point_new(heap, p1d, p1); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, p2d, p2); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 8, heap, + DYNAMIC_TYPE_ECC); + if (d != NULL) { + u1 = d + 0 * 8; + u2 = d + 2 * 8; + s = d + 4 * 8; + tmp = d + 6 * 8; + } + else + err = MEMORY_E; + } +#else + u1 = u1d; + u2 = u2d; + s = sd; + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + if (hashLen > 32) + hashLen = 32; + + sp_256_from_bin(u1, 8, hash, hashLen); + sp_256_from_mp(u2, 8, r); + sp_256_from_mp(s, 8, sm); + sp_256_from_mp(p2->x, 8, pX); + sp_256_from_mp(p2->y, 8, pY); + sp_256_from_mp(p2->z, 8, pZ); + + sp_256_mul_8(s, s, p256_norm_order); + err = sp_256_mod_8(s, s, p256_order); + } + if (err == MP_OKAY) { + sp_256_norm_8(s); + { + sp_256_mont_inv_order_8(s, s, tmp); + sp_256_mont_mul_order_8(u1, u1, s); + sp_256_mont_mul_order_8(u2, u2, s); + } + + err = sp_256_ecc_mulmod_base_8(p1, u1, 0, heap); + } + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_8(p2, p2, u2, 0, heap); + } + + if (err == MP_OKAY) { + sp_256_proj_point_add_8(p1, p1, p2, tmp); + + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_256_from_mp(u2, 8, r); + err = sp_256_mod_mul_norm_8(u2, u2, p256_mod); + } + + if (err == MP_OKAY) { + /* u1 = r.z'.z' mod prime */ + sp_256_mont_sqr_8(p1->z, p1->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(u1, u2, p1->z, p256_mod, p256_mp_mod); + *res = sp_256_cmp_8(p1->x, u1) == 0; + if (*res == 0) { + /* Reload r and add order. */ + sp_256_from_mp(u2, 8, r); + carry = sp_256_add_8(u2, u2, p256_order); + /* Carry means result is greater than mod and is not valid. */ + if (!carry) { + sp_256_norm_8(u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_256_cmp_8(u2, p256_mod); + if (c < 0) { + /* Convert to Montogomery form */ + err = sp_256_mod_mul_norm_8(u2, u2, p256_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_256_mont_mul_8(u1, u2, p1->z, p256_mod, + p256_mp_mod); + *res = sp_256_cmp_8(p1->x, u2) == 0; + } + } + } + } + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p1, 0, heap); + sp_ecc_point_free(p2, 0, heap); + + return err; +} +#endif /* HAVE_ECC_VERIFY */ + +#ifdef HAVE_ECC_CHECK_KEY +/* Check that the x and y oridinates are a valid point on the curve. + * + * point EC point. + * heap Heap to use if dynamically allocating. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +static int sp_256_ecc_is_point_8(sp_point* point, void* heap) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d = NULL; +#else + sp_digit t1d[2*8]; + sp_digit t2d[2*8]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8 * 4, heap, + DYNAMIC_TYPE_ECC); + if (d != NULL) { + t1 = d + 0 * 8; + t2 = d + 2 * 8; + } + else + err = MEMORY_E; +#else + (void)heap; + + t1 = t1d; + t2 = t2d; +#endif + + if (err == MP_OKAY) { + sp_256_sqr_8(t1, point->y); + sp_256_mod_8(t1, t1, p256_mod); + sp_256_sqr_8(t2, point->x); + sp_256_mod_8(t2, t2, p256_mod); + sp_256_mul_8(t2, t2, point->x); + sp_256_mod_8(t2, t2, p256_mod); + sp_256_sub_8(t2, p256_mod, t2); + sp_256_mont_add_8(t1, t1, t2, p256_mod); + + sp_256_mont_add_8(t1, t1, point->x, p256_mod); + sp_256_mont_add_8(t1, t1, point->x, p256_mod); + sp_256_mont_add_8(t1, t1, point->x, p256_mod); + + if (sp_256_cmp_8(t1, p256_b) != 0) + err = MP_VAL; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Check that the x and y oridinates are a valid point on the curve. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +int sp_ecc_is_point_256(mp_int* pX, mp_int* pY) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point pubd; +#endif + sp_point* pub; + byte one[1] = { 1 }; + int err; + + err = sp_ecc_point_new(NULL, pubd, pub); + if (err == MP_OKAY) { + sp_256_from_mp(pub->x, 8, pX); + sp_256_from_mp(pub->y, 8, pY); + sp_256_from_bin(pub->z, 8, one, sizeof(one)); + + err = sp_256_ecc_is_point_8(pub, NULL); + } + + sp_ecc_point_free(pub, 0, NULL); + + return err; +} + +/* Check that the private scalar generates the EC point (px, py), the point is + * on the curve and the point has the correct order. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * privm Private scalar that generates EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve, ECC_INF_E if the point does not have the correct order, + * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and + * MP_OKAY otherwise. + */ +int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit privd[8]; + sp_point pubd; + sp_point pd; +#endif + sp_digit* priv = NULL; + sp_point* pub; + sp_point* p = NULL; + byte one[1] = { 1 }; + int err; + + err = sp_ecc_point_new(heap, pubd, pub); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap, + DYNAMIC_TYPE_ECC); + if (priv == NULL) + err = MEMORY_E; + } +#else + priv = privd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(pub->x, 8, pX); + sp_256_from_mp(pub->y, 8, pY); + sp_256_from_bin(pub->z, 8, one, sizeof(one)); + sp_256_from_mp(priv, 8, privm); + + /* Check point at infinitiy. */ + if (sp_256_iszero_8(pub->x) && + sp_256_iszero_8(pub->y)) + err = ECC_INF_E; + } + + if (err == MP_OKAY) { + /* Check range of X and Y */ + if (sp_256_cmp_8(pub->x, p256_mod) >= 0 || + sp_256_cmp_8(pub->y, p256_mod) >= 0) + err = ECC_OUT_OF_RANGE_E; + } + + if (err == MP_OKAY) { + /* Check point is on curve */ + err = sp_256_ecc_is_point_8(pub, heap); + } + + if (err == MP_OKAY) { + /* Point * order = infinity */ + err = sp_256_ecc_mulmod_8(p, pub, p256_order, 1, heap); + } + if (err == MP_OKAY) { + /* Check result is infinity */ + if (!sp_256_iszero_8(p->x) || + !sp_256_iszero_8(p->y)) { + err = ECC_INF_E; + } + } + + if (err == MP_OKAY) { + /* Base * private = point */ + err = sp_256_ecc_mulmod_base_8(p, priv, 1, heap); + } + if (err == MP_OKAY) { + /* Check result is public key */ + if (sp_256_cmp_8(p->x, pub->x) != 0 || + sp_256_cmp_8(p->y, pub->y) != 0) { + err = ECC_PRIV_KEY_E; + } + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (priv != NULL) + XFREE(priv, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p, 0, heap); + sp_ecc_point_free(pub, 0, heap); + + return err; +} +#endif +#ifdef WOLFSSL_PUBLIC_ECC_ADD_DBL +/* Add two projective EC points together. + * (pX, pY, pZ) + (qX, qY, qZ) = (rX, rY, rZ) + * + * pX First EC point's X ordinate. + * pY First EC point's Y ordinate. + * pZ First EC point's Z ordinate. + * qX Second EC point's X ordinate. + * qY Second EC point's Y ordinate. + * qZ Second EC point's Z ordinate. + * rX Resultant EC point's X ordinate. + * rY Resultant EC point's Y ordinate. + * rZ Resultant EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* qX, mp_int* qY, mp_int* qZ, + mp_int* rX, mp_int* rY, mp_int* rZ) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit tmpd[2 * 8 * 5]; + sp_point pd; + sp_point qd; +#endif + sp_digit* tmp; + sp_point* p; + sp_point* q = NULL; + int err; + + err = sp_ecc_point_new(NULL, pd, p); + if (err == MP_OKAY) + err = sp_ecc_point_new(NULL, qd, q); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 5, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } +#else + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 8, pX); + sp_256_from_mp(p->y, 8, pY); + sp_256_from_mp(p->z, 8, pZ); + sp_256_from_mp(q->x, 8, qX); + sp_256_from_mp(q->y, 8, qY); + sp_256_from_mp(q->z, 8, qZ); + + sp_256_proj_point_add_8(p, p, q, tmp); + } + + if (err == MP_OKAY) + err = sp_256_to_mp(p->x, rX); + if (err == MP_OKAY) + err = sp_256_to_mp(p->y, rY); + if (err == MP_OKAY) + err = sp_256_to_mp(p->z, rZ); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (tmp != NULL) + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(q, 0, NULL); + sp_ecc_point_free(p, 0, NULL); + + return err; +} + +/* Double a projective EC point. + * (pX, pY, pZ) + (pX, pY, pZ) = (rX, rY, rZ) + * + * pX EC point's X ordinate. + * pY EC point's Y ordinate. + * pZ EC point's Z ordinate. + * rX Resultant EC point's X ordinate. + * rY Resultant EC point's Y ordinate. + * rZ Resultant EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* rX, mp_int* rY, mp_int* rZ) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit tmpd[2 * 8 * 2]; + sp_point pd; +#endif + sp_digit* tmp; + sp_point* p; + int err; + + err = sp_ecc_point_new(NULL, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 2, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } +#else + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 8, pX); + sp_256_from_mp(p->y, 8, pY); + sp_256_from_mp(p->z, 8, pZ); + + sp_256_proj_point_dbl_8(p, p, tmp); + } + + if (err == MP_OKAY) + err = sp_256_to_mp(p->x, rX); + if (err == MP_OKAY) + err = sp_256_to_mp(p->y, rY); + if (err == MP_OKAY) + err = sp_256_to_mp(p->z, rZ); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (tmp != NULL) + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p, 0, NULL); + + return err; +} + +/* Map a projective EC point to affine in place. + * pZ will be one. + * + * pX EC point's X ordinate. + * pY EC point's Y ordinate. + * pZ EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit tmpd[2 * 8 * 4]; + sp_point pd; +#endif + sp_digit* tmp; + sp_point* p; + int err; + + err = sp_ecc_point_new(NULL, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 4, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } +#else + tmp = tmpd; +#endif + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 8, pX); + sp_256_from_mp(p->y, 8, pY); + sp_256_from_mp(p->z, 8, pZ); + + sp_256_map_8(p, p, tmp); + } + + if (err == MP_OKAY) + err = sp_256_to_mp(p->x, pX); + if (err == MP_OKAY) + err = sp_256_to_mp(p->y, pY); + if (err == MP_OKAY) + err = sp_256_to_mp(p->z, pZ); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (tmp != NULL) + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p, 0, NULL); + + return err; +} +#endif /* WOLFSSL_PUBLIC_ECC_ADD_DBL */ +#ifdef HAVE_COMP_KEY +/* Find the square root of a number mod the prime of the curve. + * + * y The number to operate on and the result. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +static int sp_256_mont_sqrt_8(sp_digit* y) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d; +#else + sp_digit t1d[2 * 8]; + sp_digit t2d[2 * 8]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 8, NULL, DYNAMIC_TYPE_ECC); + if (d != NULL) { + t1 = d + 0 * 8; + t2 = d + 2 * 8; + } + else + err = MEMORY_E; +#else + t1 = t1d; + t2 = t2d; +#endif + + if (err == MP_OKAY) { + { + /* t2 = y ^ 0x2 */ + sp_256_mont_sqr_8(t2, y, p256_mod, p256_mp_mod); + /* t1 = y ^ 0x3 */ + sp_256_mont_mul_8(t1, t2, y, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xc */ + sp_256_mont_sqr_n_8(t2, t1, 2, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xf */ + sp_256_mont_mul_8(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xf0 */ + sp_256_mont_sqr_n_8(t2, t1, 4, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xff */ + sp_256_mont_mul_8(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xff00 */ + sp_256_mont_sqr_n_8(t2, t1, 8, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffff */ + sp_256_mont_mul_8(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xffff0000 */ + sp_256_mont_sqr_n_8(t2, t1, 16, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff */ + sp_256_mont_mul_8(t1, t1, t2, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000000 */ + sp_256_mont_sqr_n_8(t1, t1, 32, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001 */ + sp_256_mont_mul_8(t1, t1, y, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001000000000000000000000000 */ + sp_256_mont_sqr_n_8(t1, t1, 96, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001000000000000000000000001 */ + sp_256_mont_mul_8(t1, t1, y, p256_mod, p256_mp_mod); + sp_256_mont_sqr_n_8(y, t1, 94, p256_mod, p256_mp_mod); + } + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Uncompress the point given the X ordinate. + * + * xm X ordinate. + * odd Whether the Y ordinate is odd. + * ym Calculated Y ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d; +#else + sp_digit xd[2 * 8]; + sp_digit yd[2 * 8]; +#endif + sp_digit* x; + sp_digit* y; + int err = MP_OKAY; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 8, NULL, DYNAMIC_TYPE_ECC); + if (d != NULL) { + x = d + 0 * 8; + y = d + 2 * 8; + } + else + err = MEMORY_E; +#else + x = xd; + y = yd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(x, 8, xm); + + err = sp_256_mod_mul_norm_8(x, x, p256_mod); + } + + if (err == MP_OKAY) { + /* y = x^3 */ + { + sp_256_mont_sqr_8(y, x, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(y, y, x, p256_mod, p256_mp_mod); + } + /* y = x^3 - 3x */ + sp_256_mont_sub_8(y, y, x, p256_mod); + sp_256_mont_sub_8(y, y, x, p256_mod); + sp_256_mont_sub_8(y, y, x, p256_mod); + /* y = x^3 - 3x + b */ + err = sp_256_mod_mul_norm_8(x, p256_b, p256_mod); + } + if (err == MP_OKAY) { + sp_256_mont_add_8(y, y, x, p256_mod); + /* y = sqrt(x^3 - 3x + b) */ + err = sp_256_mont_sqrt_8(y); + } + if (err == MP_OKAY) { + XMEMSET(y + 8, 0, 8 * sizeof(sp_digit)); + sp_256_mont_reduce_8(y, p256_mod, p256_mp_mod); + if (((y[0] ^ odd) & 1) != 0) + sp_256_mont_sub_8(y, p256_mod, y, p256_mod); + + err = sp_256_to_mp(y, ym); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_ECC); +#endif + + return err; +} +#endif +#endif /* !WOLFSSL_SP_NO_256 */ +#endif /* WOLFSSL_HAVE_SP_ECC */ +#endif /* WOLFSSL_SP_ARM32_ASM */ +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH || WOLFSSL_HAVE_SP_ECC */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/sp_arm64.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/sp_arm64.c new file mode 100755 index 0000000..94bbd94 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/sp_arm64.c @@ -0,0 +1,29650 @@ +/* sp.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/* Implementation by Sean Parkinson. */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include +#include +#include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) || \ + defined(WOLFSSL_HAVE_SP_ECC) + +#ifdef RSA_LOW_MEM +#ifndef WOLFSSL_SP_SMALL +#define WOLFSSL_SP_SMALL +#endif +#endif + +#include + +#ifdef WOLFSSL_SP_ARM64_ASM +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) +#ifndef WOLFSSL_SP_NO_2048 +/* Read big endian unsigned byte aray into r. + * + * r A single precision integer. + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_2048_from_bin(sp_digit* r, int max, const byte* a, int n) +{ + int i, j = 0, s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= ((sp_digit)a[i]) << s; + if (s >= 56) { + r[j] &= 0xffffffffffffffffl; + s = 64 - s; + if (j + 1 >= max) + break; + r[++j] = a[i] >> s; + s = 8 - s; + } + else + s += 8; + } + + for (j++; j < max; j++) + r[j] = 0; +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * a A multi-precision integer. + */ +static void sp_2048_from_mp(sp_digit* r, int max, mp_int* a) +{ +#if DIGIT_BIT == 64 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < max; j++) + r[j] = 0; +#elif DIGIT_BIT > 64 + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= a->dp[i] << s; + r[j] &= 0xffffffffffffffffl; + s = 64 - s; + if (j + 1 >= max) + break; + r[++j] = a->dp[i] >> s; + while (s + 64 <= DIGIT_BIT) { + s += 64; + r[j] &= 0xffffffffffffffffl; + if (j + 1 >= max) + break; + if (s < DIGIT_BIT) + r[++j] = a->dp[i] >> s; + else + r[++j] = 0; + } + s = DIGIT_BIT - s; + } + + for (j++; j < max; j++) + r[j] = 0; +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 64) { + r[j] &= 0xffffffffffffffffl; + if (j + 1 >= max) + break; + s = 64 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else + s += DIGIT_BIT; + } + + for (j++; j < max; j++) + r[j] = 0; +#endif +} + +/* Write r as big endian to byte aray. + * Fixed length number of bytes written: 256 + * + * r A single precision integer. + * a Byte array. + */ +static void sp_2048_to_bin(sp_digit* r, byte* a) +{ + int i, j, s = 0, b; + + j = 2048 / 8 - 1; + a[j] = 0; + for (i=0; i<32 && j>=0; i++) { + b = 0; + a[j--] |= r[i] << s; b += 8 - s; + if (j < 0) + break; + while (b < 64) { + a[j--] = r[i] >> b; b += 8; + if (j < 0) + break; + } + s = 8 - (b - 64); + if (j >= 0) + a[j] = 0; + if (s != 0) + j++; + } +} + +#ifndef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_2048_mul_8(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + sp_digit tmp[8]; + + __asm__ __volatile__ ( + "ldp x8, x9, [%[a], 0]\n\t" + "ldp x10, x11, [%[a], 16]\n\t" + "ldp x12, x13, [%[a], 32]\n\t" + "ldp x14, x15, [%[a], 48]\n\t" + "ldp x16, x17, [%[b], 0]\n\t" + "ldp x18, x19, [%[b], 16]\n\t" + "ldp x20, x21, [%[b], 32]\n\t" + "ldp x22, x23, [%[b], 48]\n\t" + "# A[0] * B[0]\n\t" + "mul x3, x8, x16\n\t" + "umulh x4, x8, x16\n\t" + "str x3, [%[tmp]]\n\t" + "# A[0] * B[1]\n\t" + "mul x6, x8, x17\n\t" + "umulh x7, x8, x17\n\t" + "adds x4, x4, x6\n\t" + "adc x5, xzr, x7\n\t" + "# A[1] * B[0]\n\t" + "mul x6, x9, x16\n\t" + "umulh x7, x9, x16\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "str x4, [%[tmp], 8]\n\t" + "# A[0] * B[2]\n\t" + "mul x6, x8, x18\n\t" + "umulh x7, x8, x18\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, xzr, xzr\n\t" + "# A[1] * B[1]\n\t" + "mul x6, x9, x17\n\t" + "umulh x7, x9, x17\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "# A[2] * B[0]\n\t" + "mul x6, x10, x16\n\t" + "umulh x7, x10, x16\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "str x5, [%[tmp], 16]\n\t" + "# A[0] * B[3]\n\t" + "mul x6, x8, x19\n\t" + "umulh x7, x8, x19\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "# A[1] * B[2]\n\t" + "mul x6, x9, x18\n\t" + "umulh x7, x9, x18\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "# A[2] * B[1]\n\t" + "mul x6, x10, x17\n\t" + "umulh x7, x10, x17\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "# A[3] * B[0]\n\t" + "mul x6, x11, x16\n\t" + "umulh x7, x11, x16\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "str x3, [%[tmp], 24]\n\t" + "# A[0] * B[4]\n\t" + "mul x6, x8, x20\n\t" + "umulh x7, x8, x20\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "# A[1] * B[3]\n\t" + "mul x6, x9, x19\n\t" + "umulh x7, x9, x19\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "# A[2] * B[2]\n\t" + "mul x6, x10, x18\n\t" + "umulh x7, x10, x18\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "# A[3] * B[1]\n\t" + "mul x6, x11, x17\n\t" + "umulh x7, x11, x17\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "# A[4] * B[0]\n\t" + "mul x6, x12, x16\n\t" + "umulh x7, x12, x16\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "str x4, [%[tmp], 32]\n\t" + "# A[0] * B[5]\n\t" + "mul x6, x8, x21\n\t" + "umulh x7, x8, x21\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, xzr, xzr\n\t" + "# A[1] * B[4]\n\t" + "mul x6, x9, x20\n\t" + "umulh x7, x9, x20\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "# A[2] * B[3]\n\t" + "mul x6, x10, x19\n\t" + "umulh x7, x10, x19\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "# A[3] * B[2]\n\t" + "mul x6, x11, x18\n\t" + "umulh x7, x11, x18\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "# A[4] * B[1]\n\t" + "mul x6, x12, x17\n\t" + "umulh x7, x12, x17\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "# A[5] * B[0]\n\t" + "mul x6, x13, x16\n\t" + "umulh x7, x13, x16\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "str x5, [%[tmp], 40]\n\t" + "# A[0] * B[6]\n\t" + "mul x6, x8, x22\n\t" + "umulh x7, x8, x22\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "# A[1] * B[5]\n\t" + "mul x6, x9, x21\n\t" + "umulh x7, x9, x21\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "# A[2] * B[4]\n\t" + "mul x6, x10, x20\n\t" + "umulh x7, x10, x20\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "# A[3] * B[3]\n\t" + "mul x6, x11, x19\n\t" + "umulh x7, x11, x19\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "# A[4] * B[2]\n\t" + "mul x6, x12, x18\n\t" + "umulh x7, x12, x18\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "# A[5] * B[1]\n\t" + "mul x6, x13, x17\n\t" + "umulh x7, x13, x17\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "# A[6] * B[0]\n\t" + "mul x6, x14, x16\n\t" + "umulh x7, x14, x16\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "str x3, [%[tmp], 48]\n\t" + "# A[0] * B[7]\n\t" + "mul x6, x8, x23\n\t" + "umulh x7, x8, x23\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "# A[1] * B[6]\n\t" + "mul x6, x9, x22\n\t" + "umulh x7, x9, x22\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "# A[2] * B[5]\n\t" + "mul x6, x10, x21\n\t" + "umulh x7, x10, x21\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "# A[3] * B[4]\n\t" + "mul x6, x11, x20\n\t" + "umulh x7, x11, x20\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "# A[4] * B[3]\n\t" + "mul x6, x12, x19\n\t" + "umulh x7, x12, x19\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "# A[5] * B[2]\n\t" + "mul x6, x13, x18\n\t" + "umulh x7, x13, x18\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "# A[6] * B[1]\n\t" + "mul x6, x14, x17\n\t" + "umulh x7, x14, x17\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "# A[7] * B[0]\n\t" + "mul x6, x15, x16\n\t" + "umulh x7, x15, x16\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "str x4, [%[tmp], 56]\n\t" + "# A[1] * B[7]\n\t" + "mul x6, x9, x23\n\t" + "umulh x7, x9, x23\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, xzr, xzr\n\t" + "# A[2] * B[6]\n\t" + "mul x6, x10, x22\n\t" + "umulh x7, x10, x22\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "# A[3] * B[5]\n\t" + "mul x6, x11, x21\n\t" + "umulh x7, x11, x21\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "# A[4] * B[4]\n\t" + "mul x6, x12, x20\n\t" + "umulh x7, x12, x20\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "# A[5] * B[3]\n\t" + "mul x6, x13, x19\n\t" + "umulh x7, x13, x19\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "# A[6] * B[2]\n\t" + "mul x6, x14, x18\n\t" + "umulh x7, x14, x18\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "# A[7] * B[1]\n\t" + "mul x6, x15, x17\n\t" + "umulh x7, x15, x17\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "str x5, [%[r], 64]\n\t" + "# A[2] * B[7]\n\t" + "mul x6, x10, x23\n\t" + "umulh x7, x10, x23\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "# A[3] * B[6]\n\t" + "mul x6, x11, x22\n\t" + "umulh x7, x11, x22\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "# A[4] * B[5]\n\t" + "mul x6, x12, x21\n\t" + "umulh x7, x12, x21\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "# A[5] * B[4]\n\t" + "mul x6, x13, x20\n\t" + "umulh x7, x13, x20\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "# A[6] * B[3]\n\t" + "mul x6, x14, x19\n\t" + "umulh x7, x14, x19\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "# A[7] * B[2]\n\t" + "mul x6, x15, x18\n\t" + "umulh x7, x15, x18\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "str x3, [%[r], 72]\n\t" + "# A[3] * B[7]\n\t" + "mul x6, x11, x23\n\t" + "umulh x7, x11, x23\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "# A[4] * B[6]\n\t" + "mul x6, x12, x22\n\t" + "umulh x7, x12, x22\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "# A[5] * B[5]\n\t" + "mul x6, x13, x21\n\t" + "umulh x7, x13, x21\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "# A[6] * B[4]\n\t" + "mul x6, x14, x20\n\t" + "umulh x7, x14, x20\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "# A[7] * B[3]\n\t" + "mul x6, x15, x19\n\t" + "umulh x7, x15, x19\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "str x4, [%[r], 80]\n\t" + "# A[4] * B[7]\n\t" + "mul x6, x12, x23\n\t" + "umulh x7, x12, x23\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, xzr, xzr\n\t" + "# A[5] * B[6]\n\t" + "mul x6, x13, x22\n\t" + "umulh x7, x13, x22\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "# A[6] * B[5]\n\t" + "mul x6, x14, x21\n\t" + "umulh x7, x14, x21\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "# A[7] * B[4]\n\t" + "mul x6, x15, x20\n\t" + "umulh x7, x15, x20\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "str x5, [%[r], 88]\n\t" + "# A[5] * B[7]\n\t" + "mul x6, x13, x23\n\t" + "umulh x7, x13, x23\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "# A[6] * B[6]\n\t" + "mul x6, x14, x22\n\t" + "umulh x7, x14, x22\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "# A[7] * B[5]\n\t" + "mul x6, x15, x21\n\t" + "umulh x7, x15, x21\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "str x3, [%[r], 96]\n\t" + "# A[6] * B[7]\n\t" + "mul x6, x14, x23\n\t" + "umulh x7, x14, x23\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "# A[7] * B[6]\n\t" + "mul x6, x15, x22\n\t" + "umulh x7, x15, x22\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "str x4, [%[r], 104]\n\t" + "# A[7] * B[7]\n\t" + "mul x6, x15, x23\n\t" + "umulh x7, x15, x23\n\t" + "adds x5, x5, x6\n\t" + "adc x3, x3, x7\n\t" + "stp x5, x3, [%[r], 112]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [tmp] "r" (tmp) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_2048_sqr_8(sp_digit* r, const sp_digit* a) +{ + sp_digit tmp[8]; + + __asm__ __volatile__ ( + "ldp x10, x11, [%[a], 0]\n\t" + "ldp x12, x13, [%[a], 16]\n\t" + "ldp x14, x15, [%[a], 32]\n\t" + "ldp x16, x17, [%[a], 48]\n\t" + "# A[0] * A[0]\n\t" + "mul x2, x10, x10\n\t" + "umulh x3, x10, x10\n\t" + "str x2, [%[tmp]]\n\t" + "mov x4, 0\n\t" + "# A[0] * A[1]\n\t" + "mul x8, x10, x11\n\t" + "umulh x9, x10, x11\n\t" + "adds x3, x3, x8\n\t" + "adcs x4, x4, x9\n\t" + "adc x2, xzr, xzr\n\t" + "adds x3, x3, x8\n\t" + "adcs x4, x4, x9\n\t" + "adc x2, x2, xzr\n\t" + "str x3, [%[tmp], 8]\n\t" + "# A[0] * A[2]\n\t" + "mul x8, x10, x12\n\t" + "umulh x9, x10, x12\n\t" + "adds x4, x4, x8\n\t" + "adcs x2, x2, x9\n\t" + "adc x3, xzr, xzr\n\t" + "adds x4, x4, x8\n\t" + "adcs x2, x2, x9\n\t" + "adc x3, x3, xzr\n\t" + "# A[1] * A[1]\n\t" + "mul x8, x11, x11\n\t" + "umulh x9, x11, x11\n\t" + "adds x4, x4, x8\n\t" + "adcs x2, x2, x9\n\t" + "adc x3, x3, xzr\n\t" + "str x4, [%[tmp], 16]\n\t" + "# A[0] * A[3]\n\t" + "mul x8, x10, x13\n\t" + "umulh x9, x10, x13\n\t" + "adds x2, x2, x8\n\t" + "adcs x3, x3, x9\n\t" + "adc x4, xzr, xzr\n\t" + "adds x2, x2, x8\n\t" + "adcs x3, x3, x9\n\t" + "adc x4, x4, xzr\n\t" + "# A[1] * A[2]\n\t" + "mul x8, x11, x12\n\t" + "umulh x9, x11, x12\n\t" + "adds x2, x2, x8\n\t" + "adcs x3, x3, x9\n\t" + "adc x4, x4, xzr\n\t" + "adds x2, x2, x8\n\t" + "adcs x3, x3, x9\n\t" + "adc x4, x4, xzr\n\t" + "str x2, [%[tmp], 24]\n\t" + "# A[0] * A[4]\n\t" + "mul x8, x10, x14\n\t" + "umulh x9, x10, x14\n\t" + "adds x3, x3, x8\n\t" + "adcs x4, x4, x9\n\t" + "adc x2, xzr, xzr\n\t" + "adds x3, x3, x8\n\t" + "adcs x4, x4, x9\n\t" + "adc x2, x2, xzr\n\t" + "# A[1] * A[3]\n\t" + "mul x8, x11, x13\n\t" + "umulh x9, x11, x13\n\t" + "adds x3, x3, x8\n\t" + "adcs x4, x4, x9\n\t" + "adc x2, x2, xzr\n\t" + "adds x3, x3, x8\n\t" + "adcs x4, x4, x9\n\t" + "adc x2, x2, xzr\n\t" + "# A[2] * A[2]\n\t" + "mul x8, x12, x12\n\t" + "umulh x9, x12, x12\n\t" + "adds x3, x3, x8\n\t" + "adcs x4, x4, x9\n\t" + "adc x2, x2, xzr\n\t" + "str x3, [%[tmp], 32]\n\t" + "# A[0] * A[5]\n\t" + "mul x5, x10, x15\n\t" + "umulh x6, x10, x15\n\t" + "mov x3, 0\n\t" + "mov x7, 0\n\t" + "# A[1] * A[4]\n\t" + "mul x8, x11, x14\n\t" + "umulh x9, x11, x14\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "# A[2] * A[3]\n\t" + "mul x8, x12, x13\n\t" + "umulh x9, x12, x13\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "adds x5, x5, x5\n\t" + "adcs x6, x6, x6\n\t" + "adc x7, x7, x7\n\t" + "adds x4, x4, x5\n\t" + "adcs x2, x2, x6\n\t" + "adc x3, x3, x7\n\t" + "str x4, [%[tmp], 40]\n\t" + "# A[0] * A[6]\n\t" + "mul x5, x10, x16\n\t" + "umulh x6, x10, x16\n\t" + "mov x4, 0\n\t" + "mov x7, 0\n\t" + "# A[1] * A[5]\n\t" + "mul x8, x11, x15\n\t" + "umulh x9, x11, x15\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "# A[2] * A[4]\n\t" + "mul x8, x12, x14\n\t" + "umulh x9, x12, x14\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "# A[3] * A[3]\n\t" + "mul x8, x13, x13\n\t" + "umulh x9, x13, x13\n\t" + "adds x5, x5, x5\n\t" + "adcs x6, x6, x6\n\t" + "adc x7, x7, x7\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "adds x2, x2, x5\n\t" + "adcs x3, x3, x6\n\t" + "adc x4, x4, x7\n\t" + "str x2, [%[tmp], 48]\n\t" + "# A[0] * A[7]\n\t" + "mul x5, x10, x17\n\t" + "umulh x6, x10, x17\n\t" + "mov x2, 0\n\t" + "mov x7, 0\n\t" + "# A[1] * A[6]\n\t" + "mul x8, x11, x16\n\t" + "umulh x9, x11, x16\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "# A[2] * A[5]\n\t" + "mul x8, x12, x15\n\t" + "umulh x9, x12, x15\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "# A[3] * A[4]\n\t" + "mul x8, x13, x14\n\t" + "umulh x9, x13, x14\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "adds x5, x5, x5\n\t" + "adcs x6, x6, x6\n\t" + "adc x7, x7, x7\n\t" + "adds x3, x3, x5\n\t" + "adcs x4, x4, x6\n\t" + "adc x2, x2, x7\n\t" + "str x3, [%[tmp], 56]\n\t" + "# A[1] * A[7]\n\t" + "mul x5, x11, x17\n\t" + "umulh x6, x11, x17\n\t" + "mov x3, 0\n\t" + "mov x7, 0\n\t" + "# A[2] * A[6]\n\t" + "mul x8, x12, x16\n\t" + "umulh x9, x12, x16\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "# A[3] * A[5]\n\t" + "mul x8, x13, x15\n\t" + "umulh x9, x13, x15\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "# A[4] * A[4]\n\t" + "mul x8, x14, x14\n\t" + "umulh x9, x14, x14\n\t" + "adds x5, x5, x5\n\t" + "adcs x6, x6, x6\n\t" + "adc x7, x7, x7\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "adds x4, x4, x5\n\t" + "adcs x2, x2, x6\n\t" + "adc x3, x3, x7\n\t" + "str x4, [%[r], 64]\n\t" + "# A[2] * A[7]\n\t" + "mul x5, x12, x17\n\t" + "umulh x6, x12, x17\n\t" + "mov x4, 0\n\t" + "mov x7, 0\n\t" + "# A[3] * A[6]\n\t" + "mul x8, x13, x16\n\t" + "umulh x9, x13, x16\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "# A[4] * A[5]\n\t" + "mul x8, x14, x15\n\t" + "umulh x9, x14, x15\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "adds x5, x5, x5\n\t" + "adcs x6, x6, x6\n\t" + "adc x7, x7, x7\n\t" + "adds x2, x2, x5\n\t" + "adcs x3, x3, x6\n\t" + "adc x4, x4, x7\n\t" + "str x2, [%[r], 72]\n\t" + "# A[3] * A[7]\n\t" + "mul x8, x13, x17\n\t" + "umulh x9, x13, x17\n\t" + "adds x3, x3, x8\n\t" + "adcs x4, x4, x9\n\t" + "adc x2, xzr, xzr\n\t" + "adds x3, x3, x8\n\t" + "adcs x4, x4, x9\n\t" + "adc x2, x2, xzr\n\t" + "# A[4] * A[6]\n\t" + "mul x8, x14, x16\n\t" + "umulh x9, x14, x16\n\t" + "adds x3, x3, x8\n\t" + "adcs x4, x4, x9\n\t" + "adc x2, x2, xzr\n\t" + "adds x3, x3, x8\n\t" + "adcs x4, x4, x9\n\t" + "adc x2, x2, xzr\n\t" + "# A[5] * A[5]\n\t" + "mul x8, x15, x15\n\t" + "umulh x9, x15, x15\n\t" + "adds x3, x3, x8\n\t" + "adcs x4, x4, x9\n\t" + "adc x2, x2, xzr\n\t" + "str x3, [%[r], 80]\n\t" + "# A[4] * A[7]\n\t" + "mul x8, x14, x17\n\t" + "umulh x9, x14, x17\n\t" + "adds x4, x4, x8\n\t" + "adcs x2, x2, x9\n\t" + "adc x3, xzr, xzr\n\t" + "adds x4, x4, x8\n\t" + "adcs x2, x2, x9\n\t" + "adc x3, x3, xzr\n\t" + "# A[5] * A[6]\n\t" + "mul x8, x15, x16\n\t" + "umulh x9, x15, x16\n\t" + "adds x4, x4, x8\n\t" + "adcs x2, x2, x9\n\t" + "adc x3, x3, xzr\n\t" + "adds x4, x4, x8\n\t" + "adcs x2, x2, x9\n\t" + "adc x3, x3, xzr\n\t" + "str x4, [%[r], 88]\n\t" + "# A[5] * A[7]\n\t" + "mul x8, x15, x17\n\t" + "umulh x9, x15, x17\n\t" + "adds x2, x2, x8\n\t" + "adcs x3, x3, x9\n\t" + "adc x4, xzr, xzr\n\t" + "adds x2, x2, x8\n\t" + "adcs x3, x3, x9\n\t" + "adc x4, x4, xzr\n\t" + "# A[6] * A[6]\n\t" + "mul x8, x16, x16\n\t" + "umulh x9, x16, x16\n\t" + "adds x2, x2, x8\n\t" + "adcs x3, x3, x9\n\t" + "adc x4, x4, xzr\n\t" + "str x2, [%[r], 96]\n\t" + "# A[6] * A[7]\n\t" + "mul x8, x16, x17\n\t" + "umulh x9, x16, x17\n\t" + "adds x3, x3, x8\n\t" + "adcs x4, x4, x9\n\t" + "adc x2, xzr, xzr\n\t" + "adds x3, x3, x8\n\t" + "adcs x4, x4, x9\n\t" + "adc x2, x2, xzr\n\t" + "str x3, [%[r], 104]\n\t" + "# A[7] * A[7]\n\t" + "mul x8, x17, x17\n\t" + "umulh x9, x17, x17\n\t" + "adds x4, x4, x8\n\t" + "adc x2, x2, x9\n\t" + "stp x4, x2, [%[r], 112]\n\t" + : + : [r] "r" (r), [a] "r" (a), [tmp] "r" (tmp) + : "memory", "x2", "x3", "x4", "x8", "x9", "x10", "x5", "x6", "x7", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_2048_add_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldp x3, x4, [%[a], 0]\n\t" + "ldp x5, x6, [%[a], 16]\n\t" + "ldp x7, x8, [%[b], 0]\n\t" + "ldp x9, x10, [%[b], 16]\n\t" + "adds x3, x3, x7\n\t" + "adcs x4, x4, x8\n\t" + "adcs x5, x5, x9\n\t" + "adcs x6, x6, x10\n\t" + "stp x3, x4, [%[r], 0]\n\t" + "stp x5, x6, [%[r], 16]\n\t" + "ldp x3, x4, [%[a], 32]\n\t" + "ldp x5, x6, [%[a], 48]\n\t" + "ldp x7, x8, [%[b], 32]\n\t" + "ldp x9, x10, [%[b], 48]\n\t" + "adcs x3, x3, x7\n\t" + "adcs x4, x4, x8\n\t" + "adcs x5, x5, x9\n\t" + "adcs x6, x6, x10\n\t" + "stp x3, x4, [%[r], 32]\n\t" + "stp x5, x6, [%[r], 48]\n\t" + "cset %[c], cs\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10" + ); + + return c; +} + +/* Sub b from a into a. (a -= b) + * + * a A single precision integer and result. + * b A single precision integer. + */ +static sp_digit sp_2048_sub_in_place_16(sp_digit* a, const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldp x2, x3, [%[a], 0]\n\t" + "ldp x4, x5, [%[a], 16]\n\t" + "ldp x6, x7, [%[b], 0]\n\t" + "ldp x8, x9, [%[b], 16]\n\t" + "subs x2, x2, x6\n\t" + "sbcs x3, x3, x7\n\t" + "sbcs x4, x4, x8\n\t" + "sbcs x5, x5, x9\n\t" + "stp x2, x3, [%[a], 0]\n\t" + "stp x4, x5, [%[a], 16]\n\t" + "ldp x2, x3, [%[a], 32]\n\t" + "ldp x4, x5, [%[a], 48]\n\t" + "ldp x6, x7, [%[b], 32]\n\t" + "ldp x8, x9, [%[b], 48]\n\t" + "sbcs x2, x2, x6\n\t" + "sbcs x3, x3, x7\n\t" + "sbcs x4, x4, x8\n\t" + "sbcs x5, x5, x9\n\t" + "stp x2, x3, [%[a], 32]\n\t" + "stp x4, x5, [%[a], 48]\n\t" + "ldp x2, x3, [%[a], 64]\n\t" + "ldp x4, x5, [%[a], 80]\n\t" + "ldp x6, x7, [%[b], 64]\n\t" + "ldp x8, x9, [%[b], 80]\n\t" + "sbcs x2, x2, x6\n\t" + "sbcs x3, x3, x7\n\t" + "sbcs x4, x4, x8\n\t" + "sbcs x5, x5, x9\n\t" + "stp x2, x3, [%[a], 64]\n\t" + "stp x4, x5, [%[a], 80]\n\t" + "ldp x2, x3, [%[a], 96]\n\t" + "ldp x4, x5, [%[a], 112]\n\t" + "ldp x6, x7, [%[b], 96]\n\t" + "ldp x8, x9, [%[b], 112]\n\t" + "sbcs x2, x2, x6\n\t" + "sbcs x3, x3, x7\n\t" + "sbcs x4, x4, x8\n\t" + "sbcs x5, x5, x9\n\t" + "stp x2, x3, [%[a], 96]\n\t" + "stp x4, x5, [%[a], 112]\n\t" + "csetm %[c], cc\n\t" + : [c] "+r" (c) + : [a] "r" (a), [b] "r" (b) + : "memory", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9" + ); + + return c; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_2048_add_16(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldp x3, x4, [%[a], 0]\n\t" + "ldp x5, x6, [%[a], 16]\n\t" + "ldp x7, x8, [%[b], 0]\n\t" + "ldp x9, x10, [%[b], 16]\n\t" + "adds x3, x3, x7\n\t" + "adcs x4, x4, x8\n\t" + "adcs x5, x5, x9\n\t" + "adcs x6, x6, x10\n\t" + "stp x3, x4, [%[r], 0]\n\t" + "stp x5, x6, [%[r], 16]\n\t" + "ldp x3, x4, [%[a], 32]\n\t" + "ldp x5, x6, [%[a], 48]\n\t" + "ldp x7, x8, [%[b], 32]\n\t" + "ldp x9, x10, [%[b], 48]\n\t" + "adcs x3, x3, x7\n\t" + "adcs x4, x4, x8\n\t" + "adcs x5, x5, x9\n\t" + "adcs x6, x6, x10\n\t" + "stp x3, x4, [%[r], 32]\n\t" + "stp x5, x6, [%[r], 48]\n\t" + "ldp x3, x4, [%[a], 64]\n\t" + "ldp x5, x6, [%[a], 80]\n\t" + "ldp x7, x8, [%[b], 64]\n\t" + "ldp x9, x10, [%[b], 80]\n\t" + "adcs x3, x3, x7\n\t" + "adcs x4, x4, x8\n\t" + "adcs x5, x5, x9\n\t" + "adcs x6, x6, x10\n\t" + "stp x3, x4, [%[r], 64]\n\t" + "stp x5, x6, [%[r], 80]\n\t" + "ldp x3, x4, [%[a], 96]\n\t" + "ldp x5, x6, [%[a], 112]\n\t" + "ldp x7, x8, [%[b], 96]\n\t" + "ldp x9, x10, [%[b], 112]\n\t" + "adcs x3, x3, x7\n\t" + "adcs x4, x4, x8\n\t" + "adcs x5, x5, x9\n\t" + "adcs x6, x6, x10\n\t" + "stp x3, x4, [%[r], 96]\n\t" + "stp x5, x6, [%[r], 112]\n\t" + "cset %[c], cs\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10" + ); + + return c; +} + +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_2048_mask_8(sp_digit* r, sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<8; i++) + r[i] = a[i] & m; +#else + r[0] = a[0] & m; + r[1] = a[1] & m; + r[2] = a[2] & m; + r[3] = a[3] & m; + r[4] = a[4] & m; + r[5] = a[5] & m; + r[6] = a[6] & m; + r[7] = a[7] & m; +#endif +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_2048_mul_16(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[16]; + sp_digit a1[8]; + sp_digit b1[8]; + sp_digit z2[16]; + sp_digit u, ca, cb; + + ca = sp_2048_add_8(a1, a, &a[8]); + cb = sp_2048_add_8(b1, b, &b[8]); + u = ca & cb; + sp_2048_mul_8(z1, a1, b1); + sp_2048_mul_8(z2, &a[8], &b[8]); + sp_2048_mul_8(z0, a, b); + sp_2048_mask_8(r + 16, a1, 0 - cb); + sp_2048_mask_8(b1, b1, 0 - ca); + u += sp_2048_add_8(r + 16, r + 16, b1); + u += sp_2048_sub_in_place_16(z1, z2); + u += sp_2048_sub_in_place_16(z1, z0); + u += sp_2048_add_16(r + 8, r + 8, z1); + r[24] = u; + XMEMSET(r + 24 + 1, 0, sizeof(sp_digit) * (8 - 1)); + sp_2048_add_16(r + 16, r + 16, z2); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_2048_sqr_16(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z2[16]; + sp_digit z1[16]; + sp_digit a1[8]; + sp_digit u; + + u = sp_2048_add_8(a1, a, &a[8]); + sp_2048_sqr_8(z1, a1); + sp_2048_sqr_8(z2, &a[8]); + sp_2048_sqr_8(z0, a); + sp_2048_mask_8(r + 16, a1, 0 - u); + u += sp_2048_add_8(r + 16, r + 16, r + 16); + u += sp_2048_sub_in_place_16(z1, z2); + u += sp_2048_sub_in_place_16(z1, z0); + u += sp_2048_add_16(r + 8, r + 8, z1); + r[24] = u; + XMEMSET(r + 24 + 1, 0, sizeof(sp_digit) * (8 - 1)); + sp_2048_add_16(r + 16, r + 16, z2); +} + +/* Sub b from a into a. (a -= b) + * + * a A single precision integer and result. + * b A single precision integer. + */ +static sp_digit sp_2048_sub_in_place_32(sp_digit* a, const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldp x2, x3, [%[a], 0]\n\t" + "ldp x4, x5, [%[a], 16]\n\t" + "ldp x6, x7, [%[b], 0]\n\t" + "ldp x8, x9, [%[b], 16]\n\t" + "subs x2, x2, x6\n\t" + "sbcs x3, x3, x7\n\t" + "sbcs x4, x4, x8\n\t" + "sbcs x5, x5, x9\n\t" + "stp x2, x3, [%[a], 0]\n\t" + "stp x4, x5, [%[a], 16]\n\t" + "ldp x2, x3, [%[a], 32]\n\t" + "ldp x4, x5, [%[a], 48]\n\t" + "ldp x6, x7, [%[b], 32]\n\t" + "ldp x8, x9, [%[b], 48]\n\t" + "sbcs x2, x2, x6\n\t" + "sbcs x3, x3, x7\n\t" + "sbcs x4, x4, x8\n\t" + "sbcs x5, x5, x9\n\t" + "stp x2, x3, [%[a], 32]\n\t" + "stp x4, x5, [%[a], 48]\n\t" + "ldp x2, x3, [%[a], 64]\n\t" + "ldp x4, x5, [%[a], 80]\n\t" + "ldp x6, x7, [%[b], 64]\n\t" + "ldp x8, x9, [%[b], 80]\n\t" + "sbcs x2, x2, x6\n\t" + "sbcs x3, x3, x7\n\t" + "sbcs x4, x4, x8\n\t" + "sbcs x5, x5, x9\n\t" + "stp x2, x3, [%[a], 64]\n\t" + "stp x4, x5, [%[a], 80]\n\t" + "ldp x2, x3, [%[a], 96]\n\t" + "ldp x4, x5, [%[a], 112]\n\t" + "ldp x6, x7, [%[b], 96]\n\t" + "ldp x8, x9, [%[b], 112]\n\t" + "sbcs x2, x2, x6\n\t" + "sbcs x3, x3, x7\n\t" + "sbcs x4, x4, x8\n\t" + "sbcs x5, x5, x9\n\t" + "stp x2, x3, [%[a], 96]\n\t" + "stp x4, x5, [%[a], 112]\n\t" + "ldp x2, x3, [%[a], 128]\n\t" + "ldp x4, x5, [%[a], 144]\n\t" + "ldp x6, x7, [%[b], 128]\n\t" + "ldp x8, x9, [%[b], 144]\n\t" + "sbcs x2, x2, x6\n\t" + "sbcs x3, x3, x7\n\t" + "sbcs x4, x4, x8\n\t" + "sbcs x5, x5, x9\n\t" + "stp x2, x3, [%[a], 128]\n\t" + "stp x4, x5, [%[a], 144]\n\t" + "ldp x2, x3, [%[a], 160]\n\t" + "ldp x4, x5, [%[a], 176]\n\t" + "ldp x6, x7, [%[b], 160]\n\t" + "ldp x8, x9, [%[b], 176]\n\t" + "sbcs x2, x2, x6\n\t" + "sbcs x3, x3, x7\n\t" + "sbcs x4, x4, x8\n\t" + "sbcs x5, x5, x9\n\t" + "stp x2, x3, [%[a], 160]\n\t" + "stp x4, x5, [%[a], 176]\n\t" + "ldp x2, x3, [%[a], 192]\n\t" + "ldp x4, x5, [%[a], 208]\n\t" + "ldp x6, x7, [%[b], 192]\n\t" + "ldp x8, x9, [%[b], 208]\n\t" + "sbcs x2, x2, x6\n\t" + "sbcs x3, x3, x7\n\t" + "sbcs x4, x4, x8\n\t" + "sbcs x5, x5, x9\n\t" + "stp x2, x3, [%[a], 192]\n\t" + "stp x4, x5, [%[a], 208]\n\t" + "ldp x2, x3, [%[a], 224]\n\t" + "ldp x4, x5, [%[a], 240]\n\t" + "ldp x6, x7, [%[b], 224]\n\t" + "ldp x8, x9, [%[b], 240]\n\t" + "sbcs x2, x2, x6\n\t" + "sbcs x3, x3, x7\n\t" + "sbcs x4, x4, x8\n\t" + "sbcs x5, x5, x9\n\t" + "stp x2, x3, [%[a], 224]\n\t" + "stp x4, x5, [%[a], 240]\n\t" + "csetm %[c], cc\n\t" + : [c] "+r" (c) + : [a] "r" (a), [b] "r" (b) + : "memory", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9" + ); + + return c; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_2048_add_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldp x3, x4, [%[a], 0]\n\t" + "ldp x5, x6, [%[a], 16]\n\t" + "ldp x7, x8, [%[b], 0]\n\t" + "ldp x9, x10, [%[b], 16]\n\t" + "adds x3, x3, x7\n\t" + "adcs x4, x4, x8\n\t" + "adcs x5, x5, x9\n\t" + "adcs x6, x6, x10\n\t" + "stp x3, x4, [%[r], 0]\n\t" + "stp x5, x6, [%[r], 16]\n\t" + "ldp x3, x4, [%[a], 32]\n\t" + "ldp x5, x6, [%[a], 48]\n\t" + "ldp x7, x8, [%[b], 32]\n\t" + "ldp x9, x10, [%[b], 48]\n\t" + "adcs x3, x3, x7\n\t" + "adcs x4, x4, x8\n\t" + "adcs x5, x5, x9\n\t" + "adcs x6, x6, x10\n\t" + "stp x3, x4, [%[r], 32]\n\t" + "stp x5, x6, [%[r], 48]\n\t" + "ldp x3, x4, [%[a], 64]\n\t" + "ldp x5, x6, [%[a], 80]\n\t" + "ldp x7, x8, [%[b], 64]\n\t" + "ldp x9, x10, [%[b], 80]\n\t" + "adcs x3, x3, x7\n\t" + "adcs x4, x4, x8\n\t" + "adcs x5, x5, x9\n\t" + "adcs x6, x6, x10\n\t" + "stp x3, x4, [%[r], 64]\n\t" + "stp x5, x6, [%[r], 80]\n\t" + "ldp x3, x4, [%[a], 96]\n\t" + "ldp x5, x6, [%[a], 112]\n\t" + "ldp x7, x8, [%[b], 96]\n\t" + "ldp x9, x10, [%[b], 112]\n\t" + "adcs x3, x3, x7\n\t" + "adcs x4, x4, x8\n\t" + "adcs x5, x5, x9\n\t" + "adcs x6, x6, x10\n\t" + "stp x3, x4, [%[r], 96]\n\t" + "stp x5, x6, [%[r], 112]\n\t" + "ldp x3, x4, [%[a], 128]\n\t" + "ldp x5, x6, [%[a], 144]\n\t" + "ldp x7, x8, [%[b], 128]\n\t" + "ldp x9, x10, [%[b], 144]\n\t" + "adcs x3, x3, x7\n\t" + "adcs x4, x4, x8\n\t" + "adcs x5, x5, x9\n\t" + "adcs x6, x6, x10\n\t" + "stp x3, x4, [%[r], 128]\n\t" + "stp x5, x6, [%[r], 144]\n\t" + "ldp x3, x4, [%[a], 160]\n\t" + "ldp x5, x6, [%[a], 176]\n\t" + "ldp x7, x8, [%[b], 160]\n\t" + "ldp x9, x10, [%[b], 176]\n\t" + "adcs x3, x3, x7\n\t" + "adcs x4, x4, x8\n\t" + "adcs x5, x5, x9\n\t" + "adcs x6, x6, x10\n\t" + "stp x3, x4, [%[r], 160]\n\t" + "stp x5, x6, [%[r], 176]\n\t" + "ldp x3, x4, [%[a], 192]\n\t" + "ldp x5, x6, [%[a], 208]\n\t" + "ldp x7, x8, [%[b], 192]\n\t" + "ldp x9, x10, [%[b], 208]\n\t" + "adcs x3, x3, x7\n\t" + "adcs x4, x4, x8\n\t" + "adcs x5, x5, x9\n\t" + "adcs x6, x6, x10\n\t" + "stp x3, x4, [%[r], 192]\n\t" + "stp x5, x6, [%[r], 208]\n\t" + "ldp x3, x4, [%[a], 224]\n\t" + "ldp x5, x6, [%[a], 240]\n\t" + "ldp x7, x8, [%[b], 224]\n\t" + "ldp x9, x10, [%[b], 240]\n\t" + "adcs x3, x3, x7\n\t" + "adcs x4, x4, x8\n\t" + "adcs x5, x5, x9\n\t" + "adcs x6, x6, x10\n\t" + "stp x3, x4, [%[r], 224]\n\t" + "stp x5, x6, [%[r], 240]\n\t" + "cset %[c], cs\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10" + ); + + return c; +} + +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_2048_mask_16(sp_digit* r, sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<16; i++) + r[i] = a[i] & m; +#else + int i; + + for (i = 0; i < 16; i += 8) { + r[i+0] = a[i+0] & m; + r[i+1] = a[i+1] & m; + r[i+2] = a[i+2] & m; + r[i+3] = a[i+3] & m; + r[i+4] = a[i+4] & m; + r[i+5] = a[i+5] & m; + r[i+6] = a[i+6] & m; + r[i+7] = a[i+7] & m; + } +#endif +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_2048_mul_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[32]; + sp_digit a1[16]; + sp_digit b1[16]; + sp_digit z2[32]; + sp_digit u, ca, cb; + + ca = sp_2048_add_16(a1, a, &a[16]); + cb = sp_2048_add_16(b1, b, &b[16]); + u = ca & cb; + sp_2048_mul_16(z1, a1, b1); + sp_2048_mul_16(z2, &a[16], &b[16]); + sp_2048_mul_16(z0, a, b); + sp_2048_mask_16(r + 32, a1, 0 - cb); + sp_2048_mask_16(b1, b1, 0 - ca); + u += sp_2048_add_16(r + 32, r + 32, b1); + u += sp_2048_sub_in_place_32(z1, z2); + u += sp_2048_sub_in_place_32(z1, z0); + u += sp_2048_add_32(r + 16, r + 16, z1); + r[48] = u; + XMEMSET(r + 48 + 1, 0, sizeof(sp_digit) * (16 - 1)); + sp_2048_add_32(r + 32, r + 32, z2); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_2048_sqr_32(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z2[32]; + sp_digit z1[32]; + sp_digit a1[16]; + sp_digit u; + + u = sp_2048_add_16(a1, a, &a[16]); + sp_2048_sqr_16(z1, a1); + sp_2048_sqr_16(z2, &a[16]); + sp_2048_sqr_16(z0, a); + sp_2048_mask_16(r + 32, a1, 0 - u); + u += sp_2048_add_16(r + 32, r + 32, r + 32); + u += sp_2048_sub_in_place_32(z1, z2); + u += sp_2048_sub_in_place_32(z1, z0); + u += sp_2048_add_32(r + 16, r + 16, z1); + r[48] = u; + XMEMSET(r + 48 + 1, 0, sizeof(sp_digit) * (16 - 1)); + sp_2048_add_32(r + 32, r + 32, z2); +} + +#endif /* !WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_2048_add_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "add x11, %[a], 256\n\t" + "\n1:\n\t" + "adds %[c], %[c], #-1\n\t" + "ldp x3, x4, [%[a]], #16\n\t" + "ldp x5, x6, [%[a]], #16\n\t" + "ldp x7, x8, [%[b]], #16\n\t" + "ldp x9, x10, [%[b]], #16\n\t" + "adcs x3, x3, x7\n\t" + "adcs x4, x4, x8\n\t" + "adcs x5, x5, x9\n\t" + "adcs x6, x6, x10\n\t" + "stp x3, x4, [%[r]], #16\n\t" + "stp x5, x6, [%[r]], #16\n\t" + "cset %[c], cs\n\t" + "cmp %[a], x11\n\t" + "b.ne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into a. (a -= b) + * + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_2048_sub_in_place_32(sp_digit* a, const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "add x10, %[a], 256\n\t" + "\n1:\n\t" + "subs %[c], xzr, %[c]\n\t" + "ldp x2, x3, [%[a]]\n\t" + "ldp x4, x5, [%[a], #16]\n\t" + "ldp x6, x7, [%[b]], #16\n\t" + "ldp x8, x9, [%[b]], #16\n\t" + "sbcs x2, x2, x6\n\t" + "sbcs x3, x3, x7\n\t" + "sbcs x4, x4, x8\n\t" + "sbcs x5, x5, x9\n\t" + "stp x2, x3, [%[a]], #16\n\t" + "stp x4, x5, [%[a]], #16\n\t" + "csetm %[c], cc\n\t" + "cmp %[a], x10\n\t" + "b.ne 1b\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_2048_mul_32(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + sp_digit tmp[64]; + + __asm__ __volatile__ ( + "mov x5, 0\n\t" + "mov x6, 0\n\t" + "mov x7, 0\n\t" + "mov x8, 0\n\t" + "\n1:\n\t" + "subs x3, x5, 248\n\t" + "csel x3, xzr, x3, cc\n\t" + "sub x4, x5, x3\n\t" + "\n2:\n\t" + "ldr x10, [%[a], x3]\n\t" + "ldr x11, [%[b], x4]\n\t" + "mul x9, x10, x11\n\t" + "umulh x10, x10, x11\n\t" + "adds x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x8, x8, xzr\n\t" + "add x3, x3, #8\n\t" + "sub x4, x4, #8\n\t" + "cmp x3, 256\n\t" + "b.eq 3f\n\t" + "cmp x3, x5\n\t" + "b.le 2b\n\t" + "\n3:\n\t" + "str x6, [%[r], x5]\n\t" + "mov x6, x7\n\t" + "mov x7, x8\n\t" + "mov x8, #0\n\t" + "add x5, x5, #8\n\t" + "cmp x5, 496\n\t" + "b.le 1b\n\t" + "str x6, [%[r], x5]\n\t" + : + : [r] "r" (tmp), [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_2048_sqr_32(sp_digit* r, const sp_digit* a) +{ + sp_digit tmp[64]; + + __asm__ __volatile__ ( + "mov x6, 0\n\t" + "mov x7, 0\n\t" + "mov x8, 0\n\t" + "mov x5, 0\n\t" + "\n1:\n\t" + "subs x3, x5, 248\n\t" + "csel x3, xzr, x3, cc\n\t" + "sub x4, x5, x3\n\t" + "\n2:\n\t" + "cmp x4, x3\n\t" + "b.eq 4f\n\t" + "ldr x10, [%[a], x3]\n\t" + "ldr x11, [%[a], x4]\n\t" + "mul x9, x10, x11\n\t" + "umulh x10, x10, x11\n\t" + "adds x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x8, x8, xzr\n\t" + "adds x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x8, x8, xzr\n\t" + "b.al 5f\n\t" + "\n4:\n\t" + "ldr x10, [%[a], x3]\n\t" + "mul x9, x10, x10\n\t" + "umulh x10, x10, x10\n\t" + "adds x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x8, x8, xzr\n\t" + "\n5:\n\t" + "add x3, x3, #8\n\t" + "sub x4, x4, #8\n\t" + "cmp x3, 256\n\t" + "b.eq 3f\n\t" + "cmp x3, x4\n\t" + "b.gt 3f\n\t" + "cmp x3, x5\n\t" + "b.le 2b\n\t" + "\n3:\n\t" + "str x6, [%[r], x5]\n\t" + "mov x6, x7\n\t" + "mov x7, x8\n\t" + "mov x8, #0\n\t" + "add x5, x5, #8\n\t" + "cmp x5, 496\n\t" + "b.le 1b\n\t" + "str x6, [%[r], x5]\n\t" + : + : [r] "r" (tmp), [a] "r" (a) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +#endif /* WOLFSSL_SP_SMALL */ +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +#ifdef WOLFSSL_SP_SMALL +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_2048_mask_16(sp_digit* r, sp_digit* a, sp_digit m) +{ + int i; + + for (i=0; i<16; i++) + r[i] = a[i] & m; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_2048_add_16(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "add x11, %[a], 128\n\t" + "\n1:\n\t" + "adds %[c], %[c], #-1\n\t" + "ldp x3, x4, [%[a]], #16\n\t" + "ldp x5, x6, [%[a]], #16\n\t" + "ldp x7, x8, [%[b]], #16\n\t" + "ldp x9, x10, [%[b]], #16\n\t" + "adcs x3, x3, x7\n\t" + "adcs x4, x4, x8\n\t" + "adcs x5, x5, x9\n\t" + "adcs x6, x6, x10\n\t" + "stp x3, x4, [%[r]], #16\n\t" + "stp x5, x6, [%[r]], #16\n\t" + "cset %[c], cs\n\t" + "cmp %[a], x11\n\t" + "b.ne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into a. (a -= b) + * + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_2048_sub_in_place_16(sp_digit* a, const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "add x10, %[a], 128\n\t" + "\n1:\n\t" + "subs %[c], xzr, %[c]\n\t" + "ldp x2, x3, [%[a]]\n\t" + "ldp x4, x5, [%[a], #16]\n\t" + "ldp x6, x7, [%[b]], #16\n\t" + "ldp x8, x9, [%[b]], #16\n\t" + "sbcs x2, x2, x6\n\t" + "sbcs x3, x3, x7\n\t" + "sbcs x4, x4, x8\n\t" + "sbcs x5, x5, x9\n\t" + "stp x2, x3, [%[a]], #16\n\t" + "stp x4, x5, [%[a]], #16\n\t" + "csetm %[c], cc\n\t" + "cmp %[a], x10\n\t" + "b.ne 1b\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_2048_mul_16(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + sp_digit tmp[32]; + + __asm__ __volatile__ ( + "mov x5, 0\n\t" + "mov x6, 0\n\t" + "mov x7, 0\n\t" + "mov x8, 0\n\t" + "\n1:\n\t" + "subs x3, x5, 120\n\t" + "csel x3, xzr, x3, cc\n\t" + "sub x4, x5, x3\n\t" + "\n2:\n\t" + "ldr x10, [%[a], x3]\n\t" + "ldr x11, [%[b], x4]\n\t" + "mul x9, x10, x11\n\t" + "umulh x10, x10, x11\n\t" + "adds x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x8, x8, xzr\n\t" + "add x3, x3, #8\n\t" + "sub x4, x4, #8\n\t" + "cmp x3, 128\n\t" + "b.eq 3f\n\t" + "cmp x3, x5\n\t" + "b.le 2b\n\t" + "\n3:\n\t" + "str x6, [%[r], x5]\n\t" + "mov x6, x7\n\t" + "mov x7, x8\n\t" + "mov x8, #0\n\t" + "add x5, x5, #8\n\t" + "cmp x5, 240\n\t" + "b.le 1b\n\t" + "str x6, [%[r], x5]\n\t" + : + : [r] "r" (tmp), [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_2048_sqr_16(sp_digit* r, const sp_digit* a) +{ + sp_digit tmp[32]; + + __asm__ __volatile__ ( + "mov x6, 0\n\t" + "mov x7, 0\n\t" + "mov x8, 0\n\t" + "mov x5, 0\n\t" + "\n1:\n\t" + "subs x3, x5, 120\n\t" + "csel x3, xzr, x3, cc\n\t" + "sub x4, x5, x3\n\t" + "\n2:\n\t" + "cmp x4, x3\n\t" + "b.eq 4f\n\t" + "ldr x10, [%[a], x3]\n\t" + "ldr x11, [%[a], x4]\n\t" + "mul x9, x10, x11\n\t" + "umulh x10, x10, x11\n\t" + "adds x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x8, x8, xzr\n\t" + "adds x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x8, x8, xzr\n\t" + "b.al 5f\n\t" + "\n4:\n\t" + "ldr x10, [%[a], x3]\n\t" + "mul x9, x10, x10\n\t" + "umulh x10, x10, x10\n\t" + "adds x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x8, x8, xzr\n\t" + "\n5:\n\t" + "add x3, x3, #8\n\t" + "sub x4, x4, #8\n\t" + "cmp x3, 128\n\t" + "b.eq 3f\n\t" + "cmp x3, x4\n\t" + "b.gt 3f\n\t" + "cmp x3, x5\n\t" + "b.le 2b\n\t" + "\n3:\n\t" + "str x6, [%[r], x5]\n\t" + "mov x6, x7\n\t" + "mov x7, x8\n\t" + "mov x8, #0\n\t" + "add x5, x5, #8\n\t" + "cmp x5, 240\n\t" + "b.le 1b\n\t" + "str x6, [%[r], x5]\n\t" + : + : [r] "r" (tmp), [a] "r" (a) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +#endif /* WOLFSSL_SP_SMALL */ +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +/* Caclulate the bottom digit of -1/a mod 2^n. + * + * a A single precision number. + * rho Bottom word of inverse. + */ +static void sp_2048_mont_setup(sp_digit* a, sp_digit* rho) +{ + sp_digit x, b; + + b = a[0]; + x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ + x *= 2 - b * x; /* here x*a==1 mod 2**8 */ + x *= 2 - b * x; /* here x*a==1 mod 2**16 */ + x *= 2 - b * x; /* here x*a==1 mod 2**32 */ + x *= 2 - b * x; /* here x*a==1 mod 2**64 */ + + /* rho = -1/m mod b */ + *rho = -x; +} + +/* Mul a by digit b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision digit. + */ +static void sp_2048_mul_d_32(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "# A[0] * B\n\t" + "ldr x8, [%[a]]\n\t" + "mul x5, %[b], x8\n\t" + "umulh x3, %[b], x8\n\t" + "mov x4, 0\n\t" + "str x5, [%[r]]\n\t" + "mov x5, 0\n\t" + "mov x9, #8\n\t" + "1:\n\t" + "ldr x8, [%[a], x9]\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "str x3, [%[r], x9]\n\t" + "mov x3, x4\n\t" + "mov x4, x5\n\t" + "mov x5, #0\n\t" + "add x9, x9, #8\n\t" + "cmp x9, 256\n\t" + "b.lt 1b\n\t" + "str x3, [%[r], 256]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8" + ); +#else + __asm__ __volatile__ ( + "# A[0] * B\n\t" + "ldr x8, [%[a]]\n\t" + "mul x3, %[b], x8\n\t" + "umulh x4, %[b], x8\n\t" + "mov x5, 0\n\t" + "str x3, [%[r]]\n\t" + "# A[1] * B\n\t" + "ldr x8, [%[a], 8]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "str x4, [%[r], 8]\n\t" + "# A[2] * B\n\t" + "ldr x8, [%[a], 16]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, xzr, xzr\n\t" + "str x5, [%[r], 16]\n\t" + "# A[3] * B\n\t" + "ldr x8, [%[a], 24]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "str x3, [%[r], 24]\n\t" + "# A[4] * B\n\t" + "ldr x8, [%[a], 32]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "str x4, [%[r], 32]\n\t" + "# A[5] * B\n\t" + "ldr x8, [%[a], 40]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, xzr, xzr\n\t" + "str x5, [%[r], 40]\n\t" + "# A[6] * B\n\t" + "ldr x8, [%[a], 48]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "str x3, [%[r], 48]\n\t" + "# A[7] * B\n\t" + "ldr x8, [%[a], 56]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "str x4, [%[r], 56]\n\t" + "# A[8] * B\n\t" + "ldr x8, [%[a], 64]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, xzr, xzr\n\t" + "str x5, [%[r], 64]\n\t" + "# A[9] * B\n\t" + "ldr x8, [%[a], 72]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "str x3, [%[r], 72]\n\t" + "# A[10] * B\n\t" + "ldr x8, [%[a], 80]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "str x4, [%[r], 80]\n\t" + "# A[11] * B\n\t" + "ldr x8, [%[a], 88]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, xzr, xzr\n\t" + "str x5, [%[r], 88]\n\t" + "# A[12] * B\n\t" + "ldr x8, [%[a], 96]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "str x3, [%[r], 96]\n\t" + "# A[13] * B\n\t" + "ldr x8, [%[a], 104]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "str x4, [%[r], 104]\n\t" + "# A[14] * B\n\t" + "ldr x8, [%[a], 112]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, xzr, xzr\n\t" + "str x5, [%[r], 112]\n\t" + "# A[15] * B\n\t" + "ldr x8, [%[a], 120]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "str x3, [%[r], 120]\n\t" + "# A[16] * B\n\t" + "ldr x8, [%[a], 128]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "str x4, [%[r], 128]\n\t" + "# A[17] * B\n\t" + "ldr x8, [%[a], 136]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, xzr, xzr\n\t" + "str x5, [%[r], 136]\n\t" + "# A[18] * B\n\t" + "ldr x8, [%[a], 144]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "str x3, [%[r], 144]\n\t" + "# A[19] * B\n\t" + "ldr x8, [%[a], 152]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "str x4, [%[r], 152]\n\t" + "# A[20] * B\n\t" + "ldr x8, [%[a], 160]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, xzr, xzr\n\t" + "str x5, [%[r], 160]\n\t" + "# A[21] * B\n\t" + "ldr x8, [%[a], 168]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "str x3, [%[r], 168]\n\t" + "# A[22] * B\n\t" + "ldr x8, [%[a], 176]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "str x4, [%[r], 176]\n\t" + "# A[23] * B\n\t" + "ldr x8, [%[a], 184]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, xzr, xzr\n\t" + "str x5, [%[r], 184]\n\t" + "# A[24] * B\n\t" + "ldr x8, [%[a], 192]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "str x3, [%[r], 192]\n\t" + "# A[25] * B\n\t" + "ldr x8, [%[a], 200]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "str x4, [%[r], 200]\n\t" + "# A[26] * B\n\t" + "ldr x8, [%[a], 208]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, xzr, xzr\n\t" + "str x5, [%[r], 208]\n\t" + "# A[27] * B\n\t" + "ldr x8, [%[a], 216]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "str x3, [%[r], 216]\n\t" + "# A[28] * B\n\t" + "ldr x8, [%[a], 224]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "str x4, [%[r], 224]\n\t" + "# A[29] * B\n\t" + "ldr x8, [%[a], 232]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, xzr, xzr\n\t" + "str x5, [%[r], 232]\n\t" + "# A[30] * B\n\t" + "ldr x8, [%[a], 240]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "str x3, [%[r], 240]\n\t" + "# A[31] * B\n\t" + "ldr x8, [%[a], 248]\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x4, x4, x6\n\t" + "adc x5, x5, x7\n\t" + "str x4, [%[r], 248]\n\t" + "str x5, [%[r], 256]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8" + ); +#endif +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +/* r = 2^n mod m where n is the number of bits to reduce by. + * Given m must be 2048 bits, just need to subtract. + * + * r A single precision number. + * m A signle precision number. + */ +static void sp_2048_mont_norm_16(sp_digit* r, sp_digit* m) +{ + XMEMSET(r, 0, sizeof(sp_digit) * 16); + + /* r = 2^n mod m */ + sp_2048_sub_in_place_16(r, m); +} + +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not copying. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +static sp_digit sp_2048_cond_sub_16(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit m) +{ + sp_digit c = 0; + +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov x8, #0\n\t" + "1:\n\t" + "subs %[c], xzr, %[c]\n\t" + "ldr x4, [%[a], x8]\n\t" + "ldr x5, [%[b], x8]\n\t" + "and x5, x5, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "csetm %[c], cc\n\t" + "str x4, [%[r], x8]\n\t" + "add x8, x8, #8\n\t" + "cmp x8, 128\n\t" + "b.lt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "x4", "x6", "x5", "x7", "x8" + ); +#else + __asm__ __volatile__ ( + + "ldr x4, [%[a], 0]\n\t" + "ldr x6, [%[a], 8]\n\t" + "ldr x5, [%[b], 0]\n\t" + "ldr x7, [%[b], 8]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "subs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 0]\n\t" + "str x6, [%[r], 8]\n\t" + "ldr x4, [%[a], 16]\n\t" + "ldr x6, [%[a], 24]\n\t" + "ldr x5, [%[b], 16]\n\t" + "ldr x7, [%[b], 24]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 16]\n\t" + "str x6, [%[r], 24]\n\t" + "ldr x4, [%[a], 32]\n\t" + "ldr x6, [%[a], 40]\n\t" + "ldr x5, [%[b], 32]\n\t" + "ldr x7, [%[b], 40]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 32]\n\t" + "str x6, [%[r], 40]\n\t" + "ldr x4, [%[a], 48]\n\t" + "ldr x6, [%[a], 56]\n\t" + "ldr x5, [%[b], 48]\n\t" + "ldr x7, [%[b], 56]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 48]\n\t" + "str x6, [%[r], 56]\n\t" + "ldr x4, [%[a], 64]\n\t" + "ldr x6, [%[a], 72]\n\t" + "ldr x5, [%[b], 64]\n\t" + "ldr x7, [%[b], 72]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 64]\n\t" + "str x6, [%[r], 72]\n\t" + "ldr x4, [%[a], 80]\n\t" + "ldr x6, [%[a], 88]\n\t" + "ldr x5, [%[b], 80]\n\t" + "ldr x7, [%[b], 88]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 80]\n\t" + "str x6, [%[r], 88]\n\t" + "ldr x4, [%[a], 96]\n\t" + "ldr x6, [%[a], 104]\n\t" + "ldr x5, [%[b], 96]\n\t" + "ldr x7, [%[b], 104]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 96]\n\t" + "str x6, [%[r], 104]\n\t" + "ldr x4, [%[a], 112]\n\t" + "ldr x6, [%[a], 120]\n\t" + "ldr x5, [%[b], 112]\n\t" + "ldr x7, [%[b], 120]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 112]\n\t" + "str x6, [%[r], 120]\n\t" + "csetm %[c], cc\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "x4", "x6", "x5", "x7", "x8" + ); +#endif /* WOLFSSL_SP_SMALL */ + + return c; +} + +/* Reduce the number back to 2048 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +SP_NOINLINE static void sp_2048_mont_reduce_16(sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "ldp x12, x13, [%[m], 0]\n\t" + "ldp x14, x15, [%[m], 16]\n\t" + "ldp x16, x17, [%[m], 32]\n\t" + "ldp x18, x19, [%[m], 48]\n\t" + "ldp x20, x21, [%[m], 64]\n\t" + "ldp x22, x23, [%[m], 80]\n\t" + "ldp x24, x25, [%[m], 96]\n\t" + "ldp x26, x27, [%[m], 112]\n\t" + "# i = 0\n\t" + "mov x3, 0\n\t" + "ldp x10, x11, [%[a], 0]\n\t" + "\n1:\n\t" + "# mu = a[i] * mp\n\t" + "mul x8, %[mp], x10\n\t" + "# a[i+0] += m[0] * mu\n\t" + "ldr x9, [%[a], 0]\n\t" + "mul x6, x12, x8\n\t" + "umulh x7, x12, x8\n\t" + "adds x10, x10, x6\n\t" + "adc x5, x7, xzr\n\t" + "# a[i+1] += m[1] * mu\n\t" + "ldr x9, [%[a], 8]\n\t" + "mul x6, x13, x8\n\t" + "umulh x7, x13, x8\n\t" + "adds x10, x11, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x10, x10, x5\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+2] += m[2] * mu\n\t" + "ldr x11, [%[a], 16]\n\t" + "mul x6, x14, x8\n\t" + "umulh x7, x14, x8\n\t" + "adds x11, x11, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x11, x11, x4\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+3] += m[3] * mu\n\t" + "ldr x9, [%[a], 24]\n\t" + "mul x6, x15, x8\n\t" + "umulh x7, x15, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 24]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+4] += m[4] * mu\n\t" + "ldr x9, [%[a], 32]\n\t" + "mul x6, x16, x8\n\t" + "umulh x7, x16, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 32]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+5] += m[5] * mu\n\t" + "ldr x9, [%[a], 40]\n\t" + "mul x6, x17, x8\n\t" + "umulh x7, x17, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 40]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+6] += m[6] * mu\n\t" + "ldr x9, [%[a], 48]\n\t" + "mul x6, x18, x8\n\t" + "umulh x7, x18, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 48]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+7] += m[7] * mu\n\t" + "ldr x9, [%[a], 56]\n\t" + "mul x6, x19, x8\n\t" + "umulh x7, x19, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 56]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+8] += m[8] * mu\n\t" + "ldr x9, [%[a], 64]\n\t" + "mul x6, x20, x8\n\t" + "umulh x7, x20, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 64]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+9] += m[9] * mu\n\t" + "ldr x9, [%[a], 72]\n\t" + "mul x6, x21, x8\n\t" + "umulh x7, x21, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 72]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+10] += m[10] * mu\n\t" + "ldr x9, [%[a], 80]\n\t" + "mul x6, x22, x8\n\t" + "umulh x7, x22, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 80]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+11] += m[11] * mu\n\t" + "ldr x9, [%[a], 88]\n\t" + "mul x6, x23, x8\n\t" + "umulh x7, x23, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 88]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+12] += m[12] * mu\n\t" + "ldr x9, [%[a], 96]\n\t" + "mul x6, x24, x8\n\t" + "umulh x7, x24, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 96]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+13] += m[13] * mu\n\t" + "ldr x9, [%[a], 104]\n\t" + "mul x6, x25, x8\n\t" + "umulh x7, x25, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 104]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+14] += m[14] * mu\n\t" + "ldr x9, [%[a], 112]\n\t" + "mul x6, x26, x8\n\t" + "umulh x7, x26, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 112]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+15] += m[15] * mu\n\t" + "ldr x9, [%[a], 120]\n\t" + "mul x6, x27, x8\n\t" + "umulh x7, x27, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x7, x7, %[ca]\n\t" + "cset %[ca], cs\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 120]\n\t" + "ldr x9, [%[a], 128]\n\t" + "adcs x9, x9, x7\n\t" + "str x9, [%[a], 128]\n\t" + "adc %[ca], %[ca], xzr\n\t" + "# i += 1\n\t" + "add %[a], %[a], 8\n\t" + "add x3, x3, 8\n\t" + "cmp x3, 128\n\t" + "blt 1b\n\t" + "str x10, [%[a], 0]\n\t" + "str x11, [%[a], 8]\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27" + ); + + sp_2048_cond_sub_16(a - 16, a, m, (sp_digit)0 - ca); +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_2048_mont_mul_16(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_2048_mul_16(r, a, b); + sp_2048_mont_reduce_16(r, m, mp); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_2048_mont_sqr_16(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_2048_sqr_16(r, a); + sp_2048_mont_reduce_16(r, m, mp); +} + +/* Mul a by digit b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision digit. + */ +static void sp_2048_mul_d_16(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "# A[0] * B\n\t" + "ldr x8, [%[a]]\n\t" + "mul x5, %[b], x8\n\t" + "umulh x3, %[b], x8\n\t" + "mov x4, 0\n\t" + "str x5, [%[r]]\n\t" + "mov x5, 0\n\t" + "mov x9, #8\n\t" + "1:\n\t" + "ldr x8, [%[a], x9]\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "str x3, [%[r], x9]\n\t" + "mov x3, x4\n\t" + "mov x4, x5\n\t" + "mov x5, #0\n\t" + "add x9, x9, #8\n\t" + "cmp x9, 128\n\t" + "b.lt 1b\n\t" + "str x3, [%[r], 128]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8" + ); +#else + __asm__ __volatile__ ( + "# A[0] * B\n\t" + "ldr x8, [%[a]]\n\t" + "mul x3, %[b], x8\n\t" + "umulh x4, %[b], x8\n\t" + "mov x5, 0\n\t" + "str x3, [%[r]]\n\t" + "# A[1] * B\n\t" + "ldr x8, [%[a], 8]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "str x4, [%[r], 8]\n\t" + "# A[2] * B\n\t" + "ldr x8, [%[a], 16]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, xzr, xzr\n\t" + "str x5, [%[r], 16]\n\t" + "# A[3] * B\n\t" + "ldr x8, [%[a], 24]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "str x3, [%[r], 24]\n\t" + "# A[4] * B\n\t" + "ldr x8, [%[a], 32]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "str x4, [%[r], 32]\n\t" + "# A[5] * B\n\t" + "ldr x8, [%[a], 40]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, xzr, xzr\n\t" + "str x5, [%[r], 40]\n\t" + "# A[6] * B\n\t" + "ldr x8, [%[a], 48]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "str x3, [%[r], 48]\n\t" + "# A[7] * B\n\t" + "ldr x8, [%[a], 56]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "str x4, [%[r], 56]\n\t" + "# A[8] * B\n\t" + "ldr x8, [%[a], 64]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, xzr, xzr\n\t" + "str x5, [%[r], 64]\n\t" + "# A[9] * B\n\t" + "ldr x8, [%[a], 72]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "str x3, [%[r], 72]\n\t" + "# A[10] * B\n\t" + "ldr x8, [%[a], 80]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "str x4, [%[r], 80]\n\t" + "# A[11] * B\n\t" + "ldr x8, [%[a], 88]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, xzr, xzr\n\t" + "str x5, [%[r], 88]\n\t" + "# A[12] * B\n\t" + "ldr x8, [%[a], 96]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "str x3, [%[r], 96]\n\t" + "# A[13] * B\n\t" + "ldr x8, [%[a], 104]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "str x4, [%[r], 104]\n\t" + "# A[14] * B\n\t" + "ldr x8, [%[a], 112]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, xzr, xzr\n\t" + "str x5, [%[r], 112]\n\t" + "# A[15] * B\n\t" + "ldr x8, [%[a], 120]\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x3, x3, x6\n\t" + "adc x4, x4, x7\n\t" + "str x3, [%[r], 120]\n\t" + "str x4, [%[r], 128]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8" + ); +#endif +} + +/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) + * + * d1 The high order half of the number to divide. + * d0 The low order half of the number to divide. + * div The dividend. + * returns the result of the division. + */ +static sp_digit div_2048_word_16(sp_digit d1, sp_digit d0, sp_digit div) +{ + sp_digit r; + + __asm__ __volatile__ ( + "lsr x5, %[div], 32\n\t" + "add x5, x5, 1\n\t" + + "udiv x3, %[d1], x5\n\t" + "lsl x6, x3, 32\n\t" + "mul x4, %[div], x6\n\t" + "umulh x3, %[div], x6\n\t" + "subs %[d0], %[d0], x4\n\t" + "sbc %[d1], %[d1], x3\n\t" + + "udiv x3, %[d1], x5\n\t" + "lsl x3, x3, 32\n\t" + "add x6, x6, x3\n\t" + "mul x4, %[div], x3\n\t" + "umulh x3, %[div], x3\n\t" + "subs %[d0], %[d0], x4\n\t" + "sbc %[d1], %[d1], x3\n\t" + + "lsl x3, %[d1], 32\n\t" + "orr x3, x3, %[d0], lsr 32\n\t" + + "udiv x3, x3, x5\n\t" + "add x6, x6, x3\n\t" + "mul x4, %[div], x3\n\t" + "umulh x3, %[div], x3\n\t" + "subs %[d0], %[d0], x4\n\t" + "sbc %[d1], %[d1], x3\n\t" + + "lsl x3, %[d1], 32\n\t" + "orr x3, x3, %[d0], lsr 32\n\t" + + "udiv x3, x3, x5\n\t" + "add x6, x6, x3\n\t" + "mul x4, %[div], x3\n\t" + "umulh x3, %[div], x3\n\t" + "subs %[d0], %[d0], x4\n\t" + "sbc %[d1], %[d1], x3\n\t" + + "udiv x3, %[d0], %[div]\n\t" + "add x6, x6, x3\n\t" + "mul x3, %[div], x3\n\t" + "sub %[d0], %[d0], x3\n\t" + "mov %[r], x6\n\t" + + : [r] "=r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "x3", "x4", "x5", "x6" + ); + + return r; +} + +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +static int64_t sp_2048_cmp_16(sp_digit* a, sp_digit* b) +{ + sp_digit r = -1; + sp_digit one = 1; + +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov x3, -1\n\t" + "mov x6, 120\n\t" + "1:\n\t" + "ldr x4, [%[a], x6]\n\t" + "ldr x5, [%[b], x6]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "sub x6, x6, #8\n\t" + "b.cc 1b\n\t" + "eor %[r], %[r], x3\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [one] "r" (one) + : "x2", "x3", "x4", "x5", "x6" + ); +#else + __asm__ __volatile__ ( + "mov x3, -1\n\t" + "ldr x4, [%[a], 120]\n\t" + "ldr x5, [%[b], 120]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 112]\n\t" + "ldr x5, [%[b], 112]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 104]\n\t" + "ldr x5, [%[b], 104]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 96]\n\t" + "ldr x5, [%[b], 96]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 88]\n\t" + "ldr x5, [%[b], 88]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 80]\n\t" + "ldr x5, [%[b], 80]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 72]\n\t" + "ldr x5, [%[b], 72]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 64]\n\t" + "ldr x5, [%[b], 64]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 56]\n\t" + "ldr x5, [%[b], 56]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 48]\n\t" + "ldr x5, [%[b], 48]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 40]\n\t" + "ldr x5, [%[b], 40]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 32]\n\t" + "ldr x5, [%[b], 32]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 24]\n\t" + "ldr x5, [%[b], 24]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 16]\n\t" + "ldr x5, [%[b], 16]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 8]\n\t" + "ldr x5, [%[b], 8]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 0]\n\t" + "ldr x5, [%[b], 0]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "eor %[r], %[r], x3\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [one] "r" (one) + : "x2", "x3", "x4", "x5", "x6" + ); +#endif + + return r; +} + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_2048_div_16(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[32], t2[17]; + sp_digit div, r1; + int i; + + (void)m; + + div = d[15]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 16); + for (i=15; i>=0; i--) { + r1 = div_2048_word_16(t1[16 + i], t1[16 + i - 1], div); + + sp_2048_mul_d_16(t2, d, r1); + t1[16 + i] += sp_2048_sub_in_place_16(&t1[i], t2); + t1[16 + i] -= t2[16]; + sp_2048_mask_16(t2, d, t1[16 + i]); + t1[16 + i] += sp_2048_add_16(&t1[i], &t1[i], t2); + sp_2048_mask_16(t2, d, t1[16 + i]); + t1[16 + i] += sp_2048_add_16(&t1[i], &t1[i], t2); + } + + r1 = sp_2048_cmp_16(t1, d) >= 0; + sp_2048_cond_sub_16(r, t1, d, (sp_digit)0 - r1); + + return MP_OKAY; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_2048_mod_16(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_2048_div_16(a, m, NULL, r); +} + +#ifdef WOLFSSL_SP_SMALL +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_2048_mod_exp_16(sp_digit* r, sp_digit* a, sp_digit* e, + int bits, sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[16][32]; +#else + sp_digit* t[16]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 32, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<16; i++) + t[i] = td + i * 32; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_16(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 16); + if (reduceA) { + err = sp_2048_mod_16(t[1] + 16, a, m); + if (err == MP_OKAY) + err = sp_2048_mod_16(t[1], t[1], m); + } + else { + XMEMCPY(t[1] + 16, a, sizeof(sp_digit) * 16); + err = sp_2048_mod_16(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_2048_mont_sqr_16(t[ 2], t[ 1], m, mp); + sp_2048_mont_mul_16(t[ 3], t[ 2], t[ 1], m, mp); + sp_2048_mont_sqr_16(t[ 4], t[ 2], m, mp); + sp_2048_mont_mul_16(t[ 5], t[ 3], t[ 2], m, mp); + sp_2048_mont_sqr_16(t[ 6], t[ 3], m, mp); + sp_2048_mont_mul_16(t[ 7], t[ 4], t[ 3], m, mp); + sp_2048_mont_sqr_16(t[ 8], t[ 4], m, mp); + sp_2048_mont_mul_16(t[ 9], t[ 5], t[ 4], m, mp); + sp_2048_mont_sqr_16(t[10], t[ 5], m, mp); + sp_2048_mont_mul_16(t[11], t[ 6], t[ 5], m, mp); + sp_2048_mont_sqr_16(t[12], t[ 6], m, mp); + sp_2048_mont_mul_16(t[13], t[ 7], t[ 6], m, mp); + sp_2048_mont_sqr_16(t[14], t[ 7], m, mp); + sp_2048_mont_mul_16(t[15], t[ 8], t[ 7], m, mp); + + i = (bits - 1) / 64; + n = e[i--]; + y = n >> 60; + n <<= 4; + c = 60; + XMEMCPY(r, t[y], sizeof(sp_digit) * 16); + for (; i>=0 || c>=4; ) { + if (c == 0) { + n = e[i--]; + y = n >> 60; + n <<= 4; + c = 60; + } + else if (c < 4) { + y = n >> 60; + n = e[i--]; + c = 4 - c; + y |= n >> (64 - c); + n <<= c; + c = 64 - c; + } + else { + y = (n >> 60) & 0xf; + n <<= 4; + c -= 4; + } + + sp_2048_mont_sqr_16(r, r, m, mp); + sp_2048_mont_sqr_16(r, r, m, mp); + sp_2048_mont_sqr_16(r, r, m, mp); + sp_2048_mont_sqr_16(r, r, m, mp); + + sp_2048_mont_mul_16(r, r, t[y], m, mp); + } + y = e[0] & ((1 << c) - 1); + for (; c > 0; c--) + sp_2048_mont_sqr_16(r, r, m, mp); + sp_2048_mont_mul_16(r, r, t[y], m, mp); + + XMEMSET(&r[16], 0, sizeof(sp_digit) * 16); + sp_2048_mont_reduce_16(r, m, mp); + + mask = 0 - (sp_2048_cmp_16(r, m) >= 0); + sp_2048_cond_sub_16(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#else +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_2048_mod_exp_16(sp_digit* r, sp_digit* a, sp_digit* e, + int bits, sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][32]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 32, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<32; i++) + t[i] = td + i * 32; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_16(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 16); + if (reduceA) { + err = sp_2048_mod_16(t[1] + 16, a, m); + if (err == MP_OKAY) + err = sp_2048_mod_16(t[1], t[1], m); + } + else { + XMEMCPY(t[1] + 16, a, sizeof(sp_digit) * 16); + err = sp_2048_mod_16(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_2048_mont_sqr_16(t[ 2], t[ 1], m, mp); + sp_2048_mont_mul_16(t[ 3], t[ 2], t[ 1], m, mp); + sp_2048_mont_sqr_16(t[ 4], t[ 2], m, mp); + sp_2048_mont_mul_16(t[ 5], t[ 3], t[ 2], m, mp); + sp_2048_mont_sqr_16(t[ 6], t[ 3], m, mp); + sp_2048_mont_mul_16(t[ 7], t[ 4], t[ 3], m, mp); + sp_2048_mont_sqr_16(t[ 8], t[ 4], m, mp); + sp_2048_mont_mul_16(t[ 9], t[ 5], t[ 4], m, mp); + sp_2048_mont_sqr_16(t[10], t[ 5], m, mp); + sp_2048_mont_mul_16(t[11], t[ 6], t[ 5], m, mp); + sp_2048_mont_sqr_16(t[12], t[ 6], m, mp); + sp_2048_mont_mul_16(t[13], t[ 7], t[ 6], m, mp); + sp_2048_mont_sqr_16(t[14], t[ 7], m, mp); + sp_2048_mont_mul_16(t[15], t[ 8], t[ 7], m, mp); + sp_2048_mont_sqr_16(t[16], t[ 8], m, mp); + sp_2048_mont_mul_16(t[17], t[ 9], t[ 8], m, mp); + sp_2048_mont_sqr_16(t[18], t[ 9], m, mp); + sp_2048_mont_mul_16(t[19], t[10], t[ 9], m, mp); + sp_2048_mont_sqr_16(t[20], t[10], m, mp); + sp_2048_mont_mul_16(t[21], t[11], t[10], m, mp); + sp_2048_mont_sqr_16(t[22], t[11], m, mp); + sp_2048_mont_mul_16(t[23], t[12], t[11], m, mp); + sp_2048_mont_sqr_16(t[24], t[12], m, mp); + sp_2048_mont_mul_16(t[25], t[13], t[12], m, mp); + sp_2048_mont_sqr_16(t[26], t[13], m, mp); + sp_2048_mont_mul_16(t[27], t[14], t[13], m, mp); + sp_2048_mont_sqr_16(t[28], t[14], m, mp); + sp_2048_mont_mul_16(t[29], t[15], t[14], m, mp); + sp_2048_mont_sqr_16(t[30], t[15], m, mp); + sp_2048_mont_mul_16(t[31], t[16], t[15], m, mp); + + i = (bits - 1) / 64; + n = e[i--]; + y = n >> 59; + n <<= 5; + c = 59; + XMEMCPY(r, t[y], sizeof(sp_digit) * 16); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 59; + n <<= 5; + c = 59; + } + else if (c < 5) { + y = n >> 59; + n = e[i--]; + c = 5 - c; + y |= n >> (64 - c); + n <<= c; + c = 64 - c; + } + else { + y = (n >> 59) & 0x1f; + n <<= 5; + c -= 5; + } + + sp_2048_mont_sqr_16(r, r, m, mp); + sp_2048_mont_sqr_16(r, r, m, mp); + sp_2048_mont_sqr_16(r, r, m, mp); + sp_2048_mont_sqr_16(r, r, m, mp); + sp_2048_mont_sqr_16(r, r, m, mp); + + sp_2048_mont_mul_16(r, r, t[y], m, mp); + } + y = e[0] & ((1 << c) - 1); + for (; c > 0; c--) + sp_2048_mont_sqr_16(r, r, m, mp); + sp_2048_mont_mul_16(r, r, t[y], m, mp); + + XMEMSET(&r[16], 0, sizeof(sp_digit) * 16); + sp_2048_mont_reduce_16(r, m, mp); + + mask = 0 - (sp_2048_cmp_16(r, m) >= 0); + sp_2048_cond_sub_16(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#endif /* WOLFSSL_SP_SMALL */ + +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) +/* r = 2^n mod m where n is the number of bits to reduce by. + * Given m must be 2048 bits, just need to subtract. + * + * r A single precision number. + * m A signle precision number. + */ +static void sp_2048_mont_norm_32(sp_digit* r, sp_digit* m) +{ + XMEMSET(r, 0, sizeof(sp_digit) * 32); + + /* r = 2^n mod m */ + sp_2048_sub_in_place_32(r, m); +} + +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not copying. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +static sp_digit sp_2048_cond_sub_32(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit m) +{ + sp_digit c = 0; + +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov x8, #0\n\t" + "1:\n\t" + "subs %[c], xzr, %[c]\n\t" + "ldr x4, [%[a], x8]\n\t" + "ldr x5, [%[b], x8]\n\t" + "and x5, x5, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "csetm %[c], cc\n\t" + "str x4, [%[r], x8]\n\t" + "add x8, x8, #8\n\t" + "cmp x8, 256\n\t" + "b.lt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "x4", "x6", "x5", "x7", "x8" + ); +#else + __asm__ __volatile__ ( + + "ldr x4, [%[a], 0]\n\t" + "ldr x6, [%[a], 8]\n\t" + "ldr x5, [%[b], 0]\n\t" + "ldr x7, [%[b], 8]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "subs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 0]\n\t" + "str x6, [%[r], 8]\n\t" + "ldr x4, [%[a], 16]\n\t" + "ldr x6, [%[a], 24]\n\t" + "ldr x5, [%[b], 16]\n\t" + "ldr x7, [%[b], 24]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 16]\n\t" + "str x6, [%[r], 24]\n\t" + "ldr x4, [%[a], 32]\n\t" + "ldr x6, [%[a], 40]\n\t" + "ldr x5, [%[b], 32]\n\t" + "ldr x7, [%[b], 40]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 32]\n\t" + "str x6, [%[r], 40]\n\t" + "ldr x4, [%[a], 48]\n\t" + "ldr x6, [%[a], 56]\n\t" + "ldr x5, [%[b], 48]\n\t" + "ldr x7, [%[b], 56]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 48]\n\t" + "str x6, [%[r], 56]\n\t" + "ldr x4, [%[a], 64]\n\t" + "ldr x6, [%[a], 72]\n\t" + "ldr x5, [%[b], 64]\n\t" + "ldr x7, [%[b], 72]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 64]\n\t" + "str x6, [%[r], 72]\n\t" + "ldr x4, [%[a], 80]\n\t" + "ldr x6, [%[a], 88]\n\t" + "ldr x5, [%[b], 80]\n\t" + "ldr x7, [%[b], 88]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 80]\n\t" + "str x6, [%[r], 88]\n\t" + "ldr x4, [%[a], 96]\n\t" + "ldr x6, [%[a], 104]\n\t" + "ldr x5, [%[b], 96]\n\t" + "ldr x7, [%[b], 104]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 96]\n\t" + "str x6, [%[r], 104]\n\t" + "ldr x4, [%[a], 112]\n\t" + "ldr x6, [%[a], 120]\n\t" + "ldr x5, [%[b], 112]\n\t" + "ldr x7, [%[b], 120]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 112]\n\t" + "str x6, [%[r], 120]\n\t" + "ldr x4, [%[a], 128]\n\t" + "ldr x6, [%[a], 136]\n\t" + "ldr x5, [%[b], 128]\n\t" + "ldr x7, [%[b], 136]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 128]\n\t" + "str x6, [%[r], 136]\n\t" + "ldr x4, [%[a], 144]\n\t" + "ldr x6, [%[a], 152]\n\t" + "ldr x5, [%[b], 144]\n\t" + "ldr x7, [%[b], 152]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 144]\n\t" + "str x6, [%[r], 152]\n\t" + "ldr x4, [%[a], 160]\n\t" + "ldr x6, [%[a], 168]\n\t" + "ldr x5, [%[b], 160]\n\t" + "ldr x7, [%[b], 168]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 160]\n\t" + "str x6, [%[r], 168]\n\t" + "ldr x4, [%[a], 176]\n\t" + "ldr x6, [%[a], 184]\n\t" + "ldr x5, [%[b], 176]\n\t" + "ldr x7, [%[b], 184]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 176]\n\t" + "str x6, [%[r], 184]\n\t" + "ldr x4, [%[a], 192]\n\t" + "ldr x6, [%[a], 200]\n\t" + "ldr x5, [%[b], 192]\n\t" + "ldr x7, [%[b], 200]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 192]\n\t" + "str x6, [%[r], 200]\n\t" + "ldr x4, [%[a], 208]\n\t" + "ldr x6, [%[a], 216]\n\t" + "ldr x5, [%[b], 208]\n\t" + "ldr x7, [%[b], 216]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 208]\n\t" + "str x6, [%[r], 216]\n\t" + "ldr x4, [%[a], 224]\n\t" + "ldr x6, [%[a], 232]\n\t" + "ldr x5, [%[b], 224]\n\t" + "ldr x7, [%[b], 232]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 224]\n\t" + "str x6, [%[r], 232]\n\t" + "ldr x4, [%[a], 240]\n\t" + "ldr x6, [%[a], 248]\n\t" + "ldr x5, [%[b], 240]\n\t" + "ldr x7, [%[b], 248]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 240]\n\t" + "str x6, [%[r], 248]\n\t" + "csetm %[c], cc\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "x4", "x6", "x5", "x7", "x8" + ); +#endif /* WOLFSSL_SP_SMALL */ + + return c; +} + +/* Reduce the number back to 2048 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "ldp x12, x13, [%[m], 0]\n\t" + "ldp x14, x15, [%[m], 16]\n\t" + "ldp x16, x17, [%[m], 32]\n\t" + "ldp x18, x19, [%[m], 48]\n\t" + "ldp x20, x21, [%[m], 64]\n\t" + "ldp x22, x23, [%[m], 80]\n\t" + "ldp x24, x25, [%[m], 96]\n\t" + "ldp x26, x27, [%[m], 112]\n\t" + "# i = 0\n\t" + "mov x3, 0\n\t" + "ldp x10, x11, [%[a], 0]\n\t" + "\n1:\n\t" + "# mu = a[i] * mp\n\t" + "mul x8, %[mp], x10\n\t" + "# a[i+0] += m[0] * mu\n\t" + "ldr x9, [%[a], 0]\n\t" + "mul x6, x12, x8\n\t" + "umulh x7, x12, x8\n\t" + "adds x10, x10, x6\n\t" + "adc x5, x7, xzr\n\t" + "# a[i+1] += m[1] * mu\n\t" + "ldr x9, [%[a], 8]\n\t" + "mul x6, x13, x8\n\t" + "umulh x7, x13, x8\n\t" + "adds x10, x11, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x10, x10, x5\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+2] += m[2] * mu\n\t" + "ldr x11, [%[a], 16]\n\t" + "mul x6, x14, x8\n\t" + "umulh x7, x14, x8\n\t" + "adds x11, x11, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x11, x11, x4\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+3] += m[3] * mu\n\t" + "ldr x9, [%[a], 24]\n\t" + "mul x6, x15, x8\n\t" + "umulh x7, x15, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 24]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+4] += m[4] * mu\n\t" + "ldr x9, [%[a], 32]\n\t" + "mul x6, x16, x8\n\t" + "umulh x7, x16, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 32]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+5] += m[5] * mu\n\t" + "ldr x9, [%[a], 40]\n\t" + "mul x6, x17, x8\n\t" + "umulh x7, x17, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 40]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+6] += m[6] * mu\n\t" + "ldr x9, [%[a], 48]\n\t" + "mul x6, x18, x8\n\t" + "umulh x7, x18, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 48]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+7] += m[7] * mu\n\t" + "ldr x9, [%[a], 56]\n\t" + "mul x6, x19, x8\n\t" + "umulh x7, x19, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 56]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+8] += m[8] * mu\n\t" + "ldr x9, [%[a], 64]\n\t" + "mul x6, x20, x8\n\t" + "umulh x7, x20, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 64]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+9] += m[9] * mu\n\t" + "ldr x9, [%[a], 72]\n\t" + "mul x6, x21, x8\n\t" + "umulh x7, x21, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 72]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+10] += m[10] * mu\n\t" + "ldr x9, [%[a], 80]\n\t" + "mul x6, x22, x8\n\t" + "umulh x7, x22, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 80]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+11] += m[11] * mu\n\t" + "ldr x9, [%[a], 88]\n\t" + "mul x6, x23, x8\n\t" + "umulh x7, x23, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 88]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+12] += m[12] * mu\n\t" + "ldr x9, [%[a], 96]\n\t" + "mul x6, x24, x8\n\t" + "umulh x7, x24, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 96]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+13] += m[13] * mu\n\t" + "ldr x9, [%[a], 104]\n\t" + "mul x6, x25, x8\n\t" + "umulh x7, x25, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 104]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+14] += m[14] * mu\n\t" + "ldr x9, [%[a], 112]\n\t" + "mul x6, x26, x8\n\t" + "umulh x7, x26, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 112]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+15] += m[15] * mu\n\t" + "ldr x9, [%[a], 120]\n\t" + "mul x6, x27, x8\n\t" + "umulh x7, x27, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 120]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+16] += m[16] * mu\n\t" + "ldr x7, [%[m], 128]\n\t" + "ldr x9, [%[a], 128]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 128]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+17] += m[17] * mu\n\t" + "ldr x7, [%[m], 136]\n\t" + "ldr x9, [%[a], 136]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 136]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+18] += m[18] * mu\n\t" + "ldr x7, [%[m], 144]\n\t" + "ldr x9, [%[a], 144]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 144]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+19] += m[19] * mu\n\t" + "ldr x7, [%[m], 152]\n\t" + "ldr x9, [%[a], 152]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 152]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+20] += m[20] * mu\n\t" + "ldr x7, [%[m], 160]\n\t" + "ldr x9, [%[a], 160]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 160]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+21] += m[21] * mu\n\t" + "ldr x7, [%[m], 168]\n\t" + "ldr x9, [%[a], 168]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 168]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+22] += m[22] * mu\n\t" + "ldr x7, [%[m], 176]\n\t" + "ldr x9, [%[a], 176]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 176]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+23] += m[23] * mu\n\t" + "ldr x7, [%[m], 184]\n\t" + "ldr x9, [%[a], 184]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 184]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+24] += m[24] * mu\n\t" + "ldr x7, [%[m], 192]\n\t" + "ldr x9, [%[a], 192]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 192]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+25] += m[25] * mu\n\t" + "ldr x7, [%[m], 200]\n\t" + "ldr x9, [%[a], 200]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 200]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+26] += m[26] * mu\n\t" + "ldr x7, [%[m], 208]\n\t" + "ldr x9, [%[a], 208]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 208]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+27] += m[27] * mu\n\t" + "ldr x7, [%[m], 216]\n\t" + "ldr x9, [%[a], 216]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 216]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+28] += m[28] * mu\n\t" + "ldr x7, [%[m], 224]\n\t" + "ldr x9, [%[a], 224]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 224]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+29] += m[29] * mu\n\t" + "ldr x7, [%[m], 232]\n\t" + "ldr x9, [%[a], 232]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 232]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+30] += m[30] * mu\n\t" + "ldr x7, [%[m], 240]\n\t" + "ldr x9, [%[a], 240]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 240]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+31] += m[31] * mu\n\t" + "ldr x7, [%[m], 248]\n\t" + "ldr x9, [%[a], 248]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x7, x7, %[ca]\n\t" + "cset %[ca], cs\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 248]\n\t" + "ldr x9, [%[a], 256]\n\t" + "adcs x9, x9, x7\n\t" + "str x9, [%[a], 256]\n\t" + "adc %[ca], %[ca], xzr\n\t" + "# i += 1\n\t" + "add %[a], %[a], 8\n\t" + "add x3, x3, 8\n\t" + "cmp x3, 256\n\t" + "blt 1b\n\t" + "str x10, [%[a], 0]\n\t" + "str x11, [%[a], 8]\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27" + ); + + sp_2048_cond_sub_32(a - 32, a, m, (sp_digit)0 - ca); +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_2048_mont_mul_32(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_2048_mul_32(r, a, b); + sp_2048_mont_reduce_32(r, m, mp); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_2048_mont_sqr_32(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_2048_sqr_32(r, a); + sp_2048_mont_reduce_32(r, m, mp); +} + +/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) + * + * d1 The high order half of the number to divide. + * d0 The low order half of the number to divide. + * div The dividend. + * returns the result of the division. + */ +static sp_digit div_2048_word_32(sp_digit d1, sp_digit d0, sp_digit div) +{ + sp_digit r; + + __asm__ __volatile__ ( + "lsr x5, %[div], 32\n\t" + "add x5, x5, 1\n\t" + + "udiv x3, %[d1], x5\n\t" + "lsl x6, x3, 32\n\t" + "mul x4, %[div], x6\n\t" + "umulh x3, %[div], x6\n\t" + "subs %[d0], %[d0], x4\n\t" + "sbc %[d1], %[d1], x3\n\t" + + "udiv x3, %[d1], x5\n\t" + "lsl x3, x3, 32\n\t" + "add x6, x6, x3\n\t" + "mul x4, %[div], x3\n\t" + "umulh x3, %[div], x3\n\t" + "subs %[d0], %[d0], x4\n\t" + "sbc %[d1], %[d1], x3\n\t" + + "lsl x3, %[d1], 32\n\t" + "orr x3, x3, %[d0], lsr 32\n\t" + + "udiv x3, x3, x5\n\t" + "add x6, x6, x3\n\t" + "mul x4, %[div], x3\n\t" + "umulh x3, %[div], x3\n\t" + "subs %[d0], %[d0], x4\n\t" + "sbc %[d1], %[d1], x3\n\t" + + "lsl x3, %[d1], 32\n\t" + "orr x3, x3, %[d0], lsr 32\n\t" + + "udiv x3, x3, x5\n\t" + "add x6, x6, x3\n\t" + "mul x4, %[div], x3\n\t" + "umulh x3, %[div], x3\n\t" + "subs %[d0], %[d0], x4\n\t" + "sbc %[d1], %[d1], x3\n\t" + + "udiv x3, %[d0], %[div]\n\t" + "add x6, x6, x3\n\t" + "mul x3, %[div], x3\n\t" + "sub %[d0], %[d0], x3\n\t" + "mov %[r], x6\n\t" + + : [r] "=r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "x3", "x4", "x5", "x6" + ); + + return r; +} + +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_2048_mask_32(sp_digit* r, sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<32; i++) + r[i] = a[i] & m; +#else + int i; + + for (i = 0; i < 32; i += 8) { + r[i+0] = a[i+0] & m; + r[i+1] = a[i+1] & m; + r[i+2] = a[i+2] & m; + r[i+3] = a[i+3] & m; + r[i+4] = a[i+4] & m; + r[i+5] = a[i+5] & m; + r[i+6] = a[i+6] & m; + r[i+7] = a[i+7] & m; + } +#endif +} + +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +static int64_t sp_2048_cmp_32(sp_digit* a, sp_digit* b) +{ + sp_digit r = -1; + sp_digit one = 1; + +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov x3, -1\n\t" + "mov x6, 248\n\t" + "1:\n\t" + "ldr x4, [%[a], x6]\n\t" + "ldr x5, [%[b], x6]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "sub x6, x6, #8\n\t" + "b.cc 1b\n\t" + "eor %[r], %[r], x3\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [one] "r" (one) + : "x2", "x3", "x4", "x5", "x6" + ); +#else + __asm__ __volatile__ ( + "mov x3, -1\n\t" + "ldr x4, [%[a], 248]\n\t" + "ldr x5, [%[b], 248]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 240]\n\t" + "ldr x5, [%[b], 240]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 232]\n\t" + "ldr x5, [%[b], 232]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 224]\n\t" + "ldr x5, [%[b], 224]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 216]\n\t" + "ldr x5, [%[b], 216]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 208]\n\t" + "ldr x5, [%[b], 208]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 200]\n\t" + "ldr x5, [%[b], 200]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 192]\n\t" + "ldr x5, [%[b], 192]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 184]\n\t" + "ldr x5, [%[b], 184]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 176]\n\t" + "ldr x5, [%[b], 176]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 168]\n\t" + "ldr x5, [%[b], 168]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 160]\n\t" + "ldr x5, [%[b], 160]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 152]\n\t" + "ldr x5, [%[b], 152]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 144]\n\t" + "ldr x5, [%[b], 144]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 136]\n\t" + "ldr x5, [%[b], 136]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 128]\n\t" + "ldr x5, [%[b], 128]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 120]\n\t" + "ldr x5, [%[b], 120]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 112]\n\t" + "ldr x5, [%[b], 112]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 104]\n\t" + "ldr x5, [%[b], 104]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 96]\n\t" + "ldr x5, [%[b], 96]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 88]\n\t" + "ldr x5, [%[b], 88]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 80]\n\t" + "ldr x5, [%[b], 80]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 72]\n\t" + "ldr x5, [%[b], 72]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 64]\n\t" + "ldr x5, [%[b], 64]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 56]\n\t" + "ldr x5, [%[b], 56]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 48]\n\t" + "ldr x5, [%[b], 48]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 40]\n\t" + "ldr x5, [%[b], 40]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 32]\n\t" + "ldr x5, [%[b], 32]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 24]\n\t" + "ldr x5, [%[b], 24]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 16]\n\t" + "ldr x5, [%[b], 16]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 8]\n\t" + "ldr x5, [%[b], 8]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 0]\n\t" + "ldr x5, [%[b], 0]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "eor %[r], %[r], x3\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [one] "r" (one) + : "x2", "x3", "x4", "x5", "x6" + ); +#endif + + return r; +} + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_2048_div_32(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[64], t2[33]; + sp_digit div, r1; + int i; + + (void)m; + + div = d[31]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 32); + for (i=31; i>=0; i--) { + r1 = div_2048_word_32(t1[32 + i], t1[32 + i - 1], div); + + sp_2048_mul_d_32(t2, d, r1); + t1[32 + i] += sp_2048_sub_in_place_32(&t1[i], t2); + t1[32 + i] -= t2[32]; + sp_2048_mask_32(t2, d, t1[32 + i]); + t1[32 + i] += sp_2048_add_32(&t1[i], &t1[i], t2); + sp_2048_mask_32(t2, d, t1[32 + i]); + t1[32 + i] += sp_2048_add_32(&t1[i], &t1[i], t2); + } + + r1 = sp_2048_cmp_32(t1, d) >= 0; + sp_2048_cond_sub_32(r, t1, d, (sp_digit)0 - r1); + + return MP_OKAY; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_2048_mod_32(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_2048_div_32(a, m, NULL, r); +} + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_2048_div_32_cond(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[64], t2[33]; + sp_digit div, r1; + int i; + + (void)m; + + div = d[31]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 32); + for (i=31; i>=0; i--) { + r1 = div_2048_word_32(t1[32 + i], t1[32 + i - 1], div); + + sp_2048_mul_d_32(t2, d, r1); + t1[32 + i] += sp_2048_sub_in_place_32(&t1[i], t2); + t1[32 + i] -= t2[32]; + if (t1[32 + i] != 0) { + t1[32 + i] += sp_2048_add_32(&t1[i], &t1[i], d); + if (t1[32 + i] != 0) + t1[32 + i] += sp_2048_add_32(&t1[i], &t1[i], d); + } + } + + r1 = sp_2048_cmp_32(t1, d) >= 0; + sp_2048_cond_sub_32(r, t1, d, (sp_digit)0 - r1); + + return MP_OKAY; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_2048_mod_32_cond(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_2048_div_32_cond(a, m, NULL, r); +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \ + defined(WOLFSSL_HAVE_SP_DH) +#ifdef WOLFSSL_SP_SMALL +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_2048_mod_exp_32(sp_digit* r, sp_digit* a, sp_digit* e, + int bits, sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[16][64]; +#else + sp_digit* t[16]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 64, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<16; i++) + t[i] = td + i * 64; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_32(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 32); + if (reduceA) { + err = sp_2048_mod_32(t[1] + 32, a, m); + if (err == MP_OKAY) + err = sp_2048_mod_32(t[1], t[1], m); + } + else { + XMEMCPY(t[1] + 32, a, sizeof(sp_digit) * 32); + err = sp_2048_mod_32(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_2048_mont_sqr_32(t[ 2], t[ 1], m, mp); + sp_2048_mont_mul_32(t[ 3], t[ 2], t[ 1], m, mp); + sp_2048_mont_sqr_32(t[ 4], t[ 2], m, mp); + sp_2048_mont_mul_32(t[ 5], t[ 3], t[ 2], m, mp); + sp_2048_mont_sqr_32(t[ 6], t[ 3], m, mp); + sp_2048_mont_mul_32(t[ 7], t[ 4], t[ 3], m, mp); + sp_2048_mont_sqr_32(t[ 8], t[ 4], m, mp); + sp_2048_mont_mul_32(t[ 9], t[ 5], t[ 4], m, mp); + sp_2048_mont_sqr_32(t[10], t[ 5], m, mp); + sp_2048_mont_mul_32(t[11], t[ 6], t[ 5], m, mp); + sp_2048_mont_sqr_32(t[12], t[ 6], m, mp); + sp_2048_mont_mul_32(t[13], t[ 7], t[ 6], m, mp); + sp_2048_mont_sqr_32(t[14], t[ 7], m, mp); + sp_2048_mont_mul_32(t[15], t[ 8], t[ 7], m, mp); + + i = (bits - 1) / 64; + n = e[i--]; + y = n >> 60; + n <<= 4; + c = 60; + XMEMCPY(r, t[y], sizeof(sp_digit) * 32); + for (; i>=0 || c>=4; ) { + if (c == 0) { + n = e[i--]; + y = n >> 60; + n <<= 4; + c = 60; + } + else if (c < 4) { + y = n >> 60; + n = e[i--]; + c = 4 - c; + y |= n >> (64 - c); + n <<= c; + c = 64 - c; + } + else { + y = (n >> 60) & 0xf; + n <<= 4; + c -= 4; + } + + sp_2048_mont_sqr_32(r, r, m, mp); + sp_2048_mont_sqr_32(r, r, m, mp); + sp_2048_mont_sqr_32(r, r, m, mp); + sp_2048_mont_sqr_32(r, r, m, mp); + + sp_2048_mont_mul_32(r, r, t[y], m, mp); + } + y = e[0] & ((1 << c) - 1); + for (; c > 0; c--) + sp_2048_mont_sqr_32(r, r, m, mp); + sp_2048_mont_mul_32(r, r, t[y], m, mp); + + XMEMSET(&r[32], 0, sizeof(sp_digit) * 32); + sp_2048_mont_reduce_32(r, m, mp); + + mask = 0 - (sp_2048_cmp_32(r, m) >= 0); + sp_2048_cond_sub_32(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#else +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_2048_mod_exp_32(sp_digit* r, sp_digit* a, sp_digit* e, + int bits, sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][64]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 64, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<32; i++) + t[i] = td + i * 64; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_32(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 32); + if (reduceA) { + err = sp_2048_mod_32(t[1] + 32, a, m); + if (err == MP_OKAY) + err = sp_2048_mod_32(t[1], t[1], m); + } + else { + XMEMCPY(t[1] + 32, a, sizeof(sp_digit) * 32); + err = sp_2048_mod_32(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_2048_mont_sqr_32(t[ 2], t[ 1], m, mp); + sp_2048_mont_mul_32(t[ 3], t[ 2], t[ 1], m, mp); + sp_2048_mont_sqr_32(t[ 4], t[ 2], m, mp); + sp_2048_mont_mul_32(t[ 5], t[ 3], t[ 2], m, mp); + sp_2048_mont_sqr_32(t[ 6], t[ 3], m, mp); + sp_2048_mont_mul_32(t[ 7], t[ 4], t[ 3], m, mp); + sp_2048_mont_sqr_32(t[ 8], t[ 4], m, mp); + sp_2048_mont_mul_32(t[ 9], t[ 5], t[ 4], m, mp); + sp_2048_mont_sqr_32(t[10], t[ 5], m, mp); + sp_2048_mont_mul_32(t[11], t[ 6], t[ 5], m, mp); + sp_2048_mont_sqr_32(t[12], t[ 6], m, mp); + sp_2048_mont_mul_32(t[13], t[ 7], t[ 6], m, mp); + sp_2048_mont_sqr_32(t[14], t[ 7], m, mp); + sp_2048_mont_mul_32(t[15], t[ 8], t[ 7], m, mp); + sp_2048_mont_sqr_32(t[16], t[ 8], m, mp); + sp_2048_mont_mul_32(t[17], t[ 9], t[ 8], m, mp); + sp_2048_mont_sqr_32(t[18], t[ 9], m, mp); + sp_2048_mont_mul_32(t[19], t[10], t[ 9], m, mp); + sp_2048_mont_sqr_32(t[20], t[10], m, mp); + sp_2048_mont_mul_32(t[21], t[11], t[10], m, mp); + sp_2048_mont_sqr_32(t[22], t[11], m, mp); + sp_2048_mont_mul_32(t[23], t[12], t[11], m, mp); + sp_2048_mont_sqr_32(t[24], t[12], m, mp); + sp_2048_mont_mul_32(t[25], t[13], t[12], m, mp); + sp_2048_mont_sqr_32(t[26], t[13], m, mp); + sp_2048_mont_mul_32(t[27], t[14], t[13], m, mp); + sp_2048_mont_sqr_32(t[28], t[14], m, mp); + sp_2048_mont_mul_32(t[29], t[15], t[14], m, mp); + sp_2048_mont_sqr_32(t[30], t[15], m, mp); + sp_2048_mont_mul_32(t[31], t[16], t[15], m, mp); + + i = (bits - 1) / 64; + n = e[i--]; + y = n >> 59; + n <<= 5; + c = 59; + XMEMCPY(r, t[y], sizeof(sp_digit) * 32); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 59; + n <<= 5; + c = 59; + } + else if (c < 5) { + y = n >> 59; + n = e[i--]; + c = 5 - c; + y |= n >> (64 - c); + n <<= c; + c = 64 - c; + } + else { + y = (n >> 59) & 0x1f; + n <<= 5; + c -= 5; + } + + sp_2048_mont_sqr_32(r, r, m, mp); + sp_2048_mont_sqr_32(r, r, m, mp); + sp_2048_mont_sqr_32(r, r, m, mp); + sp_2048_mont_sqr_32(r, r, m, mp); + sp_2048_mont_sqr_32(r, r, m, mp); + + sp_2048_mont_mul_32(r, r, t[y], m, mp); + } + y = e[0] & ((1 << c) - 1); + for (; c > 0; c--) + sp_2048_mont_sqr_32(r, r, m, mp); + sp_2048_mont_mul_32(r, r, t[y], m, mp); + + XMEMSET(&r[32], 0, sizeof(sp_digit) * 32); + sp_2048_mont_reduce_32(r, m, mp); + + mask = 0 - (sp_2048_cmp_32(r, m) >= 0); + sp_2048_cond_sub_32(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#endif /* WOLFSSL_SP_SMALL */ +#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ + +#ifdef WOLFSSL_HAVE_SP_RSA +/* RSA public key operation. + * + * in Array of bytes representing the number to exponentiate, base. + * inLen Number of bytes in base. + * em Public exponent. + * mm Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 256 bytes long. + * outLen Number of bytes in result. + * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when + * an array is too long and MEMORY_E when dynamic memory allocation fails. + */ +int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm, + byte* out, word32* outLen) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit ad[64], md[32], rd[64]; +#else + sp_digit* d = NULL; +#endif + sp_digit* a; + sp_digit *ah; + sp_digit* m; + sp_digit* r; + sp_digit e[1]; + int err = MP_OKAY; + + if (*outLen < 256) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(em) > 64 || inLen > 256 || + mp_count_bits(mm) != 2048)) + err = MP_READ_E; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 5, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + a = d; + r = a + 32 * 2; + m = r + 32 * 2; + ah = a + 32; + } +#else + a = ad; + m = md; + r = rd; + ah = a + 32; +#endif + + if (err == MP_OKAY) { + sp_2048_from_bin(ah, 32, in, inLen); +#if DIGIT_BIT >= 64 + e[0] = em->dp[0]; +#else + e[0] = em->dp[0]; + if (em->used > 1) + e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT; +#endif + if (e[0] == 0) + err = MP_EXPTMOD_E; + } + if (err == MP_OKAY) { + sp_2048_from_mp(m, 32, mm); + + if (e[0] == 0x3) { + if (err == MP_OKAY) { + sp_2048_sqr_32(r, ah); + err = sp_2048_mod_32_cond(r, r, m); + } + if (err == MP_OKAY) { + sp_2048_mul_32(r, ah, r); + err = sp_2048_mod_32_cond(r, r, m); + } + } + else { + int i; + sp_digit mp; + + sp_2048_mont_setup(m, &mp); + + /* Convert to Montgomery form. */ + XMEMSET(a, 0, sizeof(sp_digit) * 32); + err = sp_2048_mod_32_cond(a, a, m); + + if (err == MP_OKAY) { + for (i=63; i>=0; i--) + if (e[0] >> i) + break; + + XMEMCPY(r, a, sizeof(sp_digit) * 32); + for (i--; i>=0; i--) { + sp_2048_mont_sqr_32(r, r, m, mp); + if (((e[0] >> i) & 1) == 1) + sp_2048_mont_mul_32(r, r, a, m, mp); + } + XMEMSET(&r[32], 0, sizeof(sp_digit) * 32); + sp_2048_mont_reduce_32(r, m, mp); + + for (i = 31; i > 0; i--) { + if (r[i] != m[i]) + break; + } + if (r[i] >= m[i]) + sp_2048_sub_in_place_32(r, m); + } + } + } + + if (err == MP_OKAY) { + sp_2048_to_bin(r, out); + *outLen = 256; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_RSA); +#endif + + return err; +} + +/* RSA private key operation. + * + * in Array of bytes representing the number to exponentiate, base. + * inLen Number of bytes in base. + * dm Private exponent. + * pm First prime. + * qm Second prime. + * dpm First prime's CRT exponent. + * dqm Second prime's CRT exponent. + * qim Inverse of second prime mod p. + * mm Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 256 bytes long. + * outLen Number of bytes in result. + * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when + * an array is too long and MEMORY_E when dynamic memory allocation fails. + */ +int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, + mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm, + byte* out, word32* outLen) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit ad[32 * 2]; + sp_digit pd[16], qd[16], dpd[16]; + sp_digit tmpad[32], tmpbd[32]; +#else + sp_digit* t = NULL; +#endif + sp_digit* a; + sp_digit* p; + sp_digit* q; + sp_digit* dp; + sp_digit* dq; + sp_digit* qi; + sp_digit* tmp; + sp_digit* tmpa; + sp_digit* tmpb; + sp_digit* r; + sp_digit c; + int err = MP_OKAY; + + (void)dm; + (void)mm; + + if (*outLen < 256) + err = MP_TO_E; + if (err == MP_OKAY && (inLen > 256 || mp_count_bits(mm) != 2048)) + err = MP_READ_E; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 11, NULL, + DYNAMIC_TYPE_RSA); + if (t == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + a = t; + p = a + 32 * 2; + q = p + 16; + qi = dq = dp = q + 16; + tmpa = qi + 16; + tmpb = tmpa + 32; + + tmp = t; + r = tmp + 32; + } +#else + r = a = ad; + p = pd; + q = qd; + qi = dq = dp = dpd; + tmpa = tmpad; + tmpb = tmpbd; + tmp = a + 32; +#endif + + if (err == MP_OKAY) { + sp_2048_from_bin(a, 32, in, inLen); + sp_2048_from_mp(p, 16, pm); + sp_2048_from_mp(q, 16, qm); + sp_2048_from_mp(dp, 16, dpm); + + err = sp_2048_mod_exp_16(tmpa, a, dp, 1024, p, 1); + } + if (err == MP_OKAY) { + sp_2048_from_mp(dq, 16, dqm); + err = sp_2048_mod_exp_16(tmpb, a, dq, 1024, q, 1); + } + + if (err == MP_OKAY) { + c = sp_2048_sub_in_place_16(tmpa, tmpb); + sp_2048_mask_16(tmp, p, c); + sp_2048_add_16(tmpa, tmpa, tmp); + + sp_2048_from_mp(qi, 16, qim); + sp_2048_mul_16(tmpa, tmpa, qi); + err = sp_2048_mod_16(tmpa, tmpa, p); + } + + if (err == MP_OKAY) { + sp_2048_mul_16(tmpa, q, tmpa); + XMEMSET(&tmpb[16], 0, sizeof(sp_digit) * 16); + sp_2048_add_32(r, tmpb, tmpa); + + sp_2048_to_bin(r, out); + *outLen = 256; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_digit) * 16 * 11); + XFREE(t, NULL, DYNAMIC_TYPE_RSA); + } +#else + XMEMSET(tmpad, 0, sizeof(tmpad)); + XMEMSET(tmpbd, 0, sizeof(tmpbd)); + XMEMSET(pd, 0, sizeof(pd)); + XMEMSET(qd, 0, sizeof(qd)); + XMEMSET(dpd, 0, sizeof(dpd)); +#endif + + return err; +} +#endif /* WOLFSSL_HAVE_SP_RSA */ +#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \ + !defined(WOLFSSL_RSA_PUBLIC_ONLY)) +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_2048_to_mp(sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (2048 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { +#if DIGIT_BIT == 64 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 32); + r->used = 32; + mp_clamp(r); +#elif DIGIT_BIT < 64 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 32; i++) { + r->dp[j] |= a[i] << s; + r->dp[j] &= (1l << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + while (s + DIGIT_BIT <= 64) { + s += DIGIT_BIT; + r->dp[j] &= (1l << DIGIT_BIT) - 1; + r->dp[++j] = a[i] >> s; + } + s = 64 - s; + } + r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 32; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 64 >= DIGIT_BIT) { + #if DIGIT_BIT < 64 + r->dp[j] &= (1l << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 64 - s; + } + else + s += 64; + } + r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returs 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ + int err = MP_OKAY; + sp_digit b[64], e[32], m[32]; + sp_digit* r = b; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 2048 || expBits > 2048 || + mp_count_bits(mod) != 2048) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + sp_2048_from_mp(b, 32, base); + sp_2048_from_mp(e, 32, exp); + sp_2048_from_mp(m, 32, mod); + + err = sp_2048_mod_exp_32(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + err = sp_2048_to_mp(r, res); + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} + +#ifdef WOLFSSL_HAVE_SP_DH +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. + * exp Array of bytes that is the exponent. + * expLen Length of data, in bytes, in exponent. + * mod Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 256 bytes long. + * outLen Length, in bytes, of exponentiation result. + * returs 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen, + mp_int* mod, byte* out, word32* outLen) +{ + int err = MP_OKAY; + sp_digit b[64], e[32], m[32]; + sp_digit* r = b; + word32 i; + + if (mp_count_bits(base) > 2048 || expLen > 256 || + mp_count_bits(mod) != 2048) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + sp_2048_from_mp(b, 32, base); + sp_2048_from_bin(e, 32, exp, expLen); + sp_2048_from_mp(m, 32, mod); + + err = sp_2048_mod_exp_32(r, b, e, expLen * 8, m, 0); + } + + if (err == MP_OKAY) { + sp_2048_to_bin(r, out); + *outLen = 256; + for (i=0; i<256 && out[i] == 0; i++) { + } + *outLen -= i; + XMEMMOVE(out, out + i, *outLen); + + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} +#endif /* WOLFSSL_HAVE_SP_DH */ + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returs 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ + int err = MP_OKAY; + sp_digit b[32], e[16], m[16]; + sp_digit* r = b; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 1024 || expBits > 1024 || + mp_count_bits(mod) != 1024) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + sp_2048_from_mp(b, 16, base); + sp_2048_from_mp(e, 16, exp); + sp_2048_from_mp(m, 16, mod); + + err = sp_2048_mod_exp_16(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + XMEMSET(r + 16, 0, sizeof(*r) * 16); + err = sp_2048_to_mp(r, res); + res->used = mod->used; + mp_clamp(res); + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} + +#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ + +#endif /* !WOLFSSL_SP_NO_2048 */ + +#ifndef WOLFSSL_SP_NO_3072 +/* Read big endian unsigned byte aray into r. + * + * r A single precision integer. + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_3072_from_bin(sp_digit* r, int max, const byte* a, int n) +{ + int i, j = 0, s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= ((sp_digit)a[i]) << s; + if (s >= 56) { + r[j] &= 0xffffffffffffffffl; + s = 64 - s; + if (j + 1 >= max) + break; + r[++j] = a[i] >> s; + s = 8 - s; + } + else + s += 8; + } + + for (j++; j < max; j++) + r[j] = 0; +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * a A multi-precision integer. + */ +static void sp_3072_from_mp(sp_digit* r, int max, mp_int* a) +{ +#if DIGIT_BIT == 64 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < max; j++) + r[j] = 0; +#elif DIGIT_BIT > 64 + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= a->dp[i] << s; + r[j] &= 0xffffffffffffffffl; + s = 64 - s; + if (j + 1 >= max) + break; + r[++j] = a->dp[i] >> s; + while (s + 64 <= DIGIT_BIT) { + s += 64; + r[j] &= 0xffffffffffffffffl; + if (j + 1 >= max) + break; + if (s < DIGIT_BIT) + r[++j] = a->dp[i] >> s; + else + r[++j] = 0; + } + s = DIGIT_BIT - s; + } + + for (j++; j < max; j++) + r[j] = 0; +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 64) { + r[j] &= 0xffffffffffffffffl; + if (j + 1 >= max) + break; + s = 64 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else + s += DIGIT_BIT; + } + + for (j++; j < max; j++) + r[j] = 0; +#endif +} + +/* Write r as big endian to byte aray. + * Fixed length number of bytes written: 384 + * + * r A single precision integer. + * a Byte array. + */ +static void sp_3072_to_bin(sp_digit* r, byte* a) +{ + int i, j, s = 0, b; + + j = 3072 / 8 - 1; + a[j] = 0; + for (i=0; i<48 && j>=0; i++) { + b = 0; + a[j--] |= r[i] << s; b += 8 - s; + if (j < 0) + break; + while (b < 64) { + a[j--] = r[i] >> b; b += 8; + if (j < 0) + break; + } + s = 8 - (b - 64); + if (j >= 0) + a[j] = 0; + if (s != 0) + j++; + } +} + +#ifndef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_3072_mul_12(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + sp_digit tmp[12]; + + __asm__ __volatile__ ( + "# A[0] * B[0]\n\t" + "ldr x7, [%[a], 0]\n\t" + "ldr x8, [%[b], 0]\n\t" + "mul x3, x7, x8\n\t" + "umulh x4, x7, x8\n\t" + "mov x5, 0\n\t" + "str x3, [%[tmp]]\n\t" + "# A[0] * B[1]\n\t" + "ldr x7, [%[a], 0]\n\t" + "ldr x8, [%[b], 8]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "# A[1] * B[0]\n\t" + "ldr x7, [%[a], 8]\n\t" + "ldr x8, [%[b], 0]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "str x4, [%[tmp], 8]\n\t" + "# A[0] * B[2]\n\t" + "ldr x7, [%[a], 0]\n\t" + "ldr x8, [%[b], 16]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, xzr, xzr\n\t" + "# A[1] * B[1]\n\t" + "ldr x7, [%[a], 8]\n\t" + "ldr x8, [%[b], 8]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "# A[2] * B[0]\n\t" + "ldr x7, [%[a], 16]\n\t" + "ldr x8, [%[b], 0]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "str x5, [%[tmp], 16]\n\t" + "# A[0] * B[3]\n\t" + "ldr x7, [%[a], 0]\n\t" + "ldr x8, [%[b], 24]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "# A[1] * B[2]\n\t" + "ldr x7, [%[a], 8]\n\t" + "ldr x8, [%[b], 16]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "# A[2] * B[1]\n\t" + "ldr x7, [%[a], 16]\n\t" + "ldr x8, [%[b], 8]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "# A[3] * B[0]\n\t" + "ldr x7, [%[a], 24]\n\t" + "ldr x8, [%[b], 0]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "str x3, [%[tmp], 24]\n\t" + "# A[0] * B[4]\n\t" + "ldr x7, [%[a], 0]\n\t" + "ldr x8, [%[b], 32]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "# A[1] * B[3]\n\t" + "ldr x7, [%[a], 8]\n\t" + "ldr x8, [%[b], 24]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "# A[2] * B[2]\n\t" + "ldr x7, [%[a], 16]\n\t" + "ldr x8, [%[b], 16]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "# A[3] * B[1]\n\t" + "ldr x7, [%[a], 24]\n\t" + "ldr x8, [%[b], 8]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "# A[4] * B[0]\n\t" + "ldr x7, [%[a], 32]\n\t" + "ldr x8, [%[b], 0]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "str x4, [%[tmp], 32]\n\t" + "# A[0] * B[5]\n\t" + "ldr x7, [%[a], 0]\n\t" + "ldr x8, [%[b], 40]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, xzr, xzr\n\t" + "# A[1] * B[4]\n\t" + "ldr x7, [%[a], 8]\n\t" + "ldr x8, [%[b], 32]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "# A[2] * B[3]\n\t" + "ldr x7, [%[a], 16]\n\t" + "ldr x8, [%[b], 24]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "# A[3] * B[2]\n\t" + "ldr x7, [%[a], 24]\n\t" + "ldr x8, [%[b], 16]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "# A[4] * B[1]\n\t" + "ldr x7, [%[a], 32]\n\t" + "ldr x8, [%[b], 8]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "# A[5] * B[0]\n\t" + "ldr x7, [%[a], 40]\n\t" + "ldr x8, [%[b], 0]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "str x5, [%[tmp], 40]\n\t" + "# A[0] * B[6]\n\t" + "ldr x7, [%[a], 0]\n\t" + "ldr x8, [%[b], 48]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "# A[1] * B[5]\n\t" + "ldr x7, [%[a], 8]\n\t" + "ldr x8, [%[b], 40]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "# A[2] * B[4]\n\t" + "ldr x7, [%[a], 16]\n\t" + "ldr x8, [%[b], 32]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "# A[3] * B[3]\n\t" + "ldr x7, [%[a], 24]\n\t" + "ldr x8, [%[b], 24]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "# A[4] * B[2]\n\t" + "ldr x7, [%[a], 32]\n\t" + "ldr x8, [%[b], 16]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "# A[5] * B[1]\n\t" + "ldr x7, [%[a], 40]\n\t" + "ldr x8, [%[b], 8]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "# A[6] * B[0]\n\t" + "ldr x7, [%[a], 48]\n\t" + "ldr x8, [%[b], 0]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "str x3, [%[tmp], 48]\n\t" + "# A[0] * B[7]\n\t" + "ldr x7, [%[a], 0]\n\t" + "ldr x8, [%[b], 56]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "# A[1] * B[6]\n\t" + "ldr x7, [%[a], 8]\n\t" + "ldr x8, [%[b], 48]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "# A[2] * B[5]\n\t" + "ldr x7, [%[a], 16]\n\t" + "ldr x8, [%[b], 40]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "# A[3] * B[4]\n\t" + "ldr x7, [%[a], 24]\n\t" + "ldr x8, [%[b], 32]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "# A[4] * B[3]\n\t" + "ldr x7, [%[a], 32]\n\t" + "ldr x8, [%[b], 24]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "# A[5] * B[2]\n\t" + "ldr x7, [%[a], 40]\n\t" + "ldr x8, [%[b], 16]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "# A[6] * B[1]\n\t" + "ldr x7, [%[a], 48]\n\t" + "ldr x8, [%[b], 8]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "# A[7] * B[0]\n\t" + "ldr x7, [%[a], 56]\n\t" + "ldr x8, [%[b], 0]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "str x4, [%[tmp], 56]\n\t" + "# A[0] * B[8]\n\t" + "ldr x7, [%[a], 0]\n\t" + "ldr x8, [%[b], 64]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, xzr, xzr\n\t" + "# A[1] * B[7]\n\t" + "ldr x7, [%[a], 8]\n\t" + "ldr x8, [%[b], 56]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "# A[2] * B[6]\n\t" + "ldr x7, [%[a], 16]\n\t" + "ldr x8, [%[b], 48]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "# A[3] * B[5]\n\t" + "ldr x7, [%[a], 24]\n\t" + "ldr x8, [%[b], 40]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "# A[4] * B[4]\n\t" + "ldr x7, [%[a], 32]\n\t" + "ldr x8, [%[b], 32]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "# A[5] * B[3]\n\t" + "ldr x7, [%[a], 40]\n\t" + "ldr x8, [%[b], 24]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "# A[6] * B[2]\n\t" + "ldr x7, [%[a], 48]\n\t" + "ldr x8, [%[b], 16]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "# A[7] * B[1]\n\t" + "ldr x7, [%[a], 56]\n\t" + "ldr x8, [%[b], 8]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "# A[8] * B[0]\n\t" + "ldr x7, [%[a], 64]\n\t" + "ldr x8, [%[b], 0]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "str x5, [%[tmp], 64]\n\t" + "# A[0] * B[9]\n\t" + "ldr x7, [%[a], 0]\n\t" + "ldr x8, [%[b], 72]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "# A[1] * B[8]\n\t" + "ldr x7, [%[a], 8]\n\t" + "ldr x8, [%[b], 64]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "# A[2] * B[7]\n\t" + "ldr x7, [%[a], 16]\n\t" + "ldr x8, [%[b], 56]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "# A[3] * B[6]\n\t" + "ldr x7, [%[a], 24]\n\t" + "ldr x8, [%[b], 48]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "# A[4] * B[5]\n\t" + "ldr x7, [%[a], 32]\n\t" + "ldr x8, [%[b], 40]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "# A[5] * B[4]\n\t" + "ldr x7, [%[a], 40]\n\t" + "ldr x8, [%[b], 32]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "# A[6] * B[3]\n\t" + "ldr x7, [%[a], 48]\n\t" + "ldr x8, [%[b], 24]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "# A[7] * B[2]\n\t" + "ldr x7, [%[a], 56]\n\t" + "ldr x8, [%[b], 16]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "# A[8] * B[1]\n\t" + "ldr x7, [%[a], 64]\n\t" + "ldr x8, [%[b], 8]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "# A[9] * B[0]\n\t" + "ldr x7, [%[a], 72]\n\t" + "ldr x8, [%[b], 0]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "str x3, [%[tmp], 72]\n\t" + "# A[0] * B[10]\n\t" + "ldr x7, [%[a], 0]\n\t" + "ldr x8, [%[b], 80]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "# A[1] * B[9]\n\t" + "ldr x7, [%[a], 8]\n\t" + "ldr x8, [%[b], 72]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "# A[2] * B[8]\n\t" + "ldr x7, [%[a], 16]\n\t" + "ldr x8, [%[b], 64]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "# A[3] * B[7]\n\t" + "ldr x7, [%[a], 24]\n\t" + "ldr x8, [%[b], 56]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "# A[4] * B[6]\n\t" + "ldr x7, [%[a], 32]\n\t" + "ldr x8, [%[b], 48]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "# A[5] * B[5]\n\t" + "ldr x7, [%[a], 40]\n\t" + "ldr x8, [%[b], 40]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "# A[6] * B[4]\n\t" + "ldr x7, [%[a], 48]\n\t" + "ldr x8, [%[b], 32]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "# A[7] * B[3]\n\t" + "ldr x7, [%[a], 56]\n\t" + "ldr x8, [%[b], 24]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "# A[8] * B[2]\n\t" + "ldr x7, [%[a], 64]\n\t" + "ldr x8, [%[b], 16]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "# A[9] * B[1]\n\t" + "ldr x7, [%[a], 72]\n\t" + "ldr x8, [%[b], 8]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "# A[10] * B[0]\n\t" + "ldr x7, [%[a], 80]\n\t" + "ldr x8, [%[b], 0]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "str x4, [%[tmp], 80]\n\t" + "# A[0] * B[11]\n\t" + "ldr x7, [%[a], 0]\n\t" + "ldr x8, [%[b], 88]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, xzr, xzr\n\t" + "# A[1] * B[10]\n\t" + "ldr x7, [%[a], 8]\n\t" + "ldr x8, [%[b], 80]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "# A[2] * B[9]\n\t" + "ldr x7, [%[a], 16]\n\t" + "ldr x8, [%[b], 72]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "# A[3] * B[8]\n\t" + "ldr x7, [%[a], 24]\n\t" + "ldr x8, [%[b], 64]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "# A[4] * B[7]\n\t" + "ldr x7, [%[a], 32]\n\t" + "ldr x8, [%[b], 56]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "# A[5] * B[6]\n\t" + "ldr x7, [%[a], 40]\n\t" + "ldr x8, [%[b], 48]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "# A[6] * B[5]\n\t" + "ldr x7, [%[a], 48]\n\t" + "ldr x8, [%[b], 40]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "# A[7] * B[4]\n\t" + "ldr x7, [%[a], 56]\n\t" + "ldr x8, [%[b], 32]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "# A[8] * B[3]\n\t" + "ldr x7, [%[a], 64]\n\t" + "ldr x8, [%[b], 24]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "# A[9] * B[2]\n\t" + "ldr x7, [%[a], 72]\n\t" + "ldr x8, [%[b], 16]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "# A[10] * B[1]\n\t" + "ldr x7, [%[a], 80]\n\t" + "ldr x8, [%[b], 8]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "# A[11] * B[0]\n\t" + "ldr x7, [%[a], 88]\n\t" + "ldr x8, [%[b], 0]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "str x5, [%[tmp], 88]\n\t" + "# A[1] * B[11]\n\t" + "ldr x7, [%[a], 8]\n\t" + "ldr x8, [%[b], 88]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "# A[2] * B[10]\n\t" + "ldr x7, [%[a], 16]\n\t" + "ldr x8, [%[b], 80]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "# A[3] * B[9]\n\t" + "ldr x7, [%[a], 24]\n\t" + "ldr x8, [%[b], 72]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "# A[4] * B[8]\n\t" + "ldr x7, [%[a], 32]\n\t" + "ldr x8, [%[b], 64]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "# A[5] * B[7]\n\t" + "ldr x7, [%[a], 40]\n\t" + "ldr x8, [%[b], 56]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "# A[6] * B[6]\n\t" + "ldr x7, [%[a], 48]\n\t" + "ldr x8, [%[b], 48]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "# A[7] * B[5]\n\t" + "ldr x7, [%[a], 56]\n\t" + "ldr x8, [%[b], 40]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "# A[8] * B[4]\n\t" + "ldr x7, [%[a], 64]\n\t" + "ldr x8, [%[b], 32]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "# A[9] * B[3]\n\t" + "ldr x7, [%[a], 72]\n\t" + "ldr x8, [%[b], 24]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "# A[10] * B[2]\n\t" + "ldr x7, [%[a], 80]\n\t" + "ldr x8, [%[b], 16]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "# A[11] * B[1]\n\t" + "ldr x7, [%[a], 88]\n\t" + "ldr x8, [%[b], 8]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "str x3, [%[r], 96]\n\t" + "# A[2] * B[11]\n\t" + "ldr x7, [%[a], 16]\n\t" + "ldr x8, [%[b], 88]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "# A[3] * B[10]\n\t" + "ldr x7, [%[a], 24]\n\t" + "ldr x8, [%[b], 80]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "# A[4] * B[9]\n\t" + "ldr x7, [%[a], 32]\n\t" + "ldr x8, [%[b], 72]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "# A[5] * B[8]\n\t" + "ldr x7, [%[a], 40]\n\t" + "ldr x8, [%[b], 64]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "# A[6] * B[7]\n\t" + "ldr x7, [%[a], 48]\n\t" + "ldr x8, [%[b], 56]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "# A[7] * B[6]\n\t" + "ldr x7, [%[a], 56]\n\t" + "ldr x8, [%[b], 48]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "# A[8] * B[5]\n\t" + "ldr x7, [%[a], 64]\n\t" + "ldr x8, [%[b], 40]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "# A[9] * B[4]\n\t" + "ldr x7, [%[a], 72]\n\t" + "ldr x8, [%[b], 32]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "# A[10] * B[3]\n\t" + "ldr x7, [%[a], 80]\n\t" + "ldr x8, [%[b], 24]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "# A[11] * B[2]\n\t" + "ldr x7, [%[a], 88]\n\t" + "ldr x8, [%[b], 16]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "str x4, [%[r], 104]\n\t" + "# A[3] * B[11]\n\t" + "ldr x7, [%[a], 24]\n\t" + "ldr x8, [%[b], 88]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, xzr, xzr\n\t" + "# A[4] * B[10]\n\t" + "ldr x7, [%[a], 32]\n\t" + "ldr x8, [%[b], 80]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "# A[5] * B[9]\n\t" + "ldr x7, [%[a], 40]\n\t" + "ldr x8, [%[b], 72]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "# A[6] * B[8]\n\t" + "ldr x7, [%[a], 48]\n\t" + "ldr x8, [%[b], 64]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "# A[7] * B[7]\n\t" + "ldr x7, [%[a], 56]\n\t" + "ldr x8, [%[b], 56]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "# A[8] * B[6]\n\t" + "ldr x7, [%[a], 64]\n\t" + "ldr x8, [%[b], 48]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "# A[9] * B[5]\n\t" + "ldr x7, [%[a], 72]\n\t" + "ldr x8, [%[b], 40]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "# A[10] * B[4]\n\t" + "ldr x7, [%[a], 80]\n\t" + "ldr x8, [%[b], 32]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "# A[11] * B[3]\n\t" + "ldr x7, [%[a], 88]\n\t" + "ldr x8, [%[b], 24]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "str x5, [%[r], 112]\n\t" + "# A[4] * B[11]\n\t" + "ldr x7, [%[a], 32]\n\t" + "ldr x8, [%[b], 88]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "# A[5] * B[10]\n\t" + "ldr x7, [%[a], 40]\n\t" + "ldr x8, [%[b], 80]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "# A[6] * B[9]\n\t" + "ldr x7, [%[a], 48]\n\t" + "ldr x8, [%[b], 72]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "# A[7] * B[8]\n\t" + "ldr x7, [%[a], 56]\n\t" + "ldr x8, [%[b], 64]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "# A[8] * B[7]\n\t" + "ldr x7, [%[a], 64]\n\t" + "ldr x8, [%[b], 56]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "# A[9] * B[6]\n\t" + "ldr x7, [%[a], 72]\n\t" + "ldr x8, [%[b], 48]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "# A[10] * B[5]\n\t" + "ldr x7, [%[a], 80]\n\t" + "ldr x8, [%[b], 40]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "# A[11] * B[4]\n\t" + "ldr x7, [%[a], 88]\n\t" + "ldr x8, [%[b], 32]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "str x3, [%[r], 120]\n\t" + "# A[5] * B[11]\n\t" + "ldr x7, [%[a], 40]\n\t" + "ldr x8, [%[b], 88]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "# A[6] * B[10]\n\t" + "ldr x7, [%[a], 48]\n\t" + "ldr x8, [%[b], 80]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "# A[7] * B[9]\n\t" + "ldr x7, [%[a], 56]\n\t" + "ldr x8, [%[b], 72]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "# A[8] * B[8]\n\t" + "ldr x7, [%[a], 64]\n\t" + "ldr x8, [%[b], 64]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "# A[9] * B[7]\n\t" + "ldr x7, [%[a], 72]\n\t" + "ldr x8, [%[b], 56]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "# A[10] * B[6]\n\t" + "ldr x7, [%[a], 80]\n\t" + "ldr x8, [%[b], 48]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "# A[11] * B[5]\n\t" + "ldr x7, [%[a], 88]\n\t" + "ldr x8, [%[b], 40]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "str x4, [%[r], 128]\n\t" + "# A[6] * B[11]\n\t" + "ldr x7, [%[a], 48]\n\t" + "ldr x8, [%[b], 88]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, xzr, xzr\n\t" + "# A[7] * B[10]\n\t" + "ldr x7, [%[a], 56]\n\t" + "ldr x8, [%[b], 80]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "# A[8] * B[9]\n\t" + "ldr x7, [%[a], 64]\n\t" + "ldr x8, [%[b], 72]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "# A[9] * B[8]\n\t" + "ldr x7, [%[a], 72]\n\t" + "ldr x8, [%[b], 64]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "# A[10] * B[7]\n\t" + "ldr x7, [%[a], 80]\n\t" + "ldr x8, [%[b], 56]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "# A[11] * B[6]\n\t" + "ldr x7, [%[a], 88]\n\t" + "ldr x8, [%[b], 48]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "str x5, [%[r], 136]\n\t" + "# A[7] * B[11]\n\t" + "ldr x7, [%[a], 56]\n\t" + "ldr x8, [%[b], 88]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "# A[8] * B[10]\n\t" + "ldr x7, [%[a], 64]\n\t" + "ldr x8, [%[b], 80]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "# A[9] * B[9]\n\t" + "ldr x7, [%[a], 72]\n\t" + "ldr x8, [%[b], 72]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "# A[10] * B[8]\n\t" + "ldr x7, [%[a], 80]\n\t" + "ldr x8, [%[b], 64]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "# A[11] * B[7]\n\t" + "ldr x7, [%[a], 88]\n\t" + "ldr x8, [%[b], 56]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "str x3, [%[r], 144]\n\t" + "# A[8] * B[11]\n\t" + "ldr x7, [%[a], 64]\n\t" + "ldr x8, [%[b], 88]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "# A[9] * B[10]\n\t" + "ldr x7, [%[a], 72]\n\t" + "ldr x8, [%[b], 80]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "# A[10] * B[9]\n\t" + "ldr x7, [%[a], 80]\n\t" + "ldr x8, [%[b], 72]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "# A[11] * B[8]\n\t" + "ldr x7, [%[a], 88]\n\t" + "ldr x8, [%[b], 64]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "str x4, [%[r], 152]\n\t" + "# A[9] * B[11]\n\t" + "ldr x7, [%[a], 72]\n\t" + "ldr x8, [%[b], 88]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, xzr, xzr\n\t" + "# A[10] * B[10]\n\t" + "ldr x7, [%[a], 80]\n\t" + "ldr x8, [%[b], 80]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "# A[11] * B[9]\n\t" + "ldr x7, [%[a], 88]\n\t" + "ldr x8, [%[b], 72]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "str x5, [%[r], 160]\n\t" + "# A[10] * B[11]\n\t" + "ldr x7, [%[a], 80]\n\t" + "ldr x8, [%[b], 88]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "# A[11] * B[10]\n\t" + "ldr x7, [%[a], 88]\n\t" + "ldr x8, [%[b], 80]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "str x3, [%[r], 168]\n\t" + "# A[11] * B[11]\n\t" + "ldr x7, [%[a], 88]\n\t" + "ldr x8, [%[b], 88]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x4, x4, x6\n\t" + "adc x5, x5, x7\n\t" + "stp x4, x5, [%[r], 176]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [tmp] "r" (tmp) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_3072_sqr_12(sp_digit* r, const sp_digit* a) +{ + sp_digit tmp[12]; + + __asm__ __volatile__ ( + "ldp x10, x11, [%[a], 0]\n\t" + "ldp x12, x13, [%[a], 16]\n\t" + "ldp x14, x15, [%[a], 32]\n\t" + "ldp x16, x17, [%[a], 48]\n\t" + "ldp x18, x19, [%[a], 64]\n\t" + "ldp x20, x21, [%[a], 80]\n\t" + "# A[0] * A[0]\n\t" + "mul x2, x10, x10\n\t" + "umulh x3, x10, x10\n\t" + "str x2, [%[tmp]]\n\t" + "mov x4, 0\n\t" + "# A[0] * A[1]\n\t" + "mul x8, x10, x11\n\t" + "umulh x9, x10, x11\n\t" + "adds x3, x3, x8\n\t" + "adcs x4, x4, x9\n\t" + "adc x2, xzr, xzr\n\t" + "adds x3, x3, x8\n\t" + "adcs x4, x4, x9\n\t" + "adc x2, x2, xzr\n\t" + "str x3, [%[tmp], 8]\n\t" + "# A[0] * A[2]\n\t" + "mul x8, x10, x12\n\t" + "umulh x9, x10, x12\n\t" + "adds x4, x4, x8\n\t" + "adcs x2, x2, x9\n\t" + "adc x3, xzr, xzr\n\t" + "adds x4, x4, x8\n\t" + "adcs x2, x2, x9\n\t" + "adc x3, x3, xzr\n\t" + "# A[1] * A[1]\n\t" + "mul x8, x11, x11\n\t" + "umulh x9, x11, x11\n\t" + "adds x4, x4, x8\n\t" + "adcs x2, x2, x9\n\t" + "adc x3, x3, xzr\n\t" + "str x4, [%[tmp], 16]\n\t" + "# A[0] * A[3]\n\t" + "mul x8, x10, x13\n\t" + "umulh x9, x10, x13\n\t" + "adds x2, x2, x8\n\t" + "adcs x3, x3, x9\n\t" + "adc x4, xzr, xzr\n\t" + "adds x2, x2, x8\n\t" + "adcs x3, x3, x9\n\t" + "adc x4, x4, xzr\n\t" + "# A[1] * A[2]\n\t" + "mul x8, x11, x12\n\t" + "umulh x9, x11, x12\n\t" + "adds x2, x2, x8\n\t" + "adcs x3, x3, x9\n\t" + "adc x4, x4, xzr\n\t" + "adds x2, x2, x8\n\t" + "adcs x3, x3, x9\n\t" + "adc x4, x4, xzr\n\t" + "str x2, [%[tmp], 24]\n\t" + "# A[0] * A[4]\n\t" + "mul x8, x10, x14\n\t" + "umulh x9, x10, x14\n\t" + "adds x3, x3, x8\n\t" + "adcs x4, x4, x9\n\t" + "adc x2, xzr, xzr\n\t" + "adds x3, x3, x8\n\t" + "adcs x4, x4, x9\n\t" + "adc x2, x2, xzr\n\t" + "# A[1] * A[3]\n\t" + "mul x8, x11, x13\n\t" + "umulh x9, x11, x13\n\t" + "adds x3, x3, x8\n\t" + "adcs x4, x4, x9\n\t" + "adc x2, x2, xzr\n\t" + "adds x3, x3, x8\n\t" + "adcs x4, x4, x9\n\t" + "adc x2, x2, xzr\n\t" + "# A[2] * A[2]\n\t" + "mul x8, x12, x12\n\t" + "umulh x9, x12, x12\n\t" + "adds x3, x3, x8\n\t" + "adcs x4, x4, x9\n\t" + "adc x2, x2, xzr\n\t" + "str x3, [%[tmp], 32]\n\t" + "# A[0] * A[5]\n\t" + "mul x5, x10, x15\n\t" + "umulh x6, x10, x15\n\t" + "mov x3, 0\n\t" + "mov x7, 0\n\t" + "# A[1] * A[4]\n\t" + "mul x8, x11, x14\n\t" + "umulh x9, x11, x14\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "# A[2] * A[3]\n\t" + "mul x8, x12, x13\n\t" + "umulh x9, x12, x13\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "adds x5, x5, x5\n\t" + "adcs x6, x6, x6\n\t" + "adc x7, x7, x7\n\t" + "adds x4, x4, x5\n\t" + "adcs x2, x2, x6\n\t" + "adc x3, x3, x7\n\t" + "str x4, [%[tmp], 40]\n\t" + "# A[0] * A[6]\n\t" + "mul x5, x10, x16\n\t" + "umulh x6, x10, x16\n\t" + "mov x4, 0\n\t" + "mov x7, 0\n\t" + "# A[1] * A[5]\n\t" + "mul x8, x11, x15\n\t" + "umulh x9, x11, x15\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "# A[2] * A[4]\n\t" + "mul x8, x12, x14\n\t" + "umulh x9, x12, x14\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "# A[3] * A[3]\n\t" + "mul x8, x13, x13\n\t" + "umulh x9, x13, x13\n\t" + "adds x5, x5, x5\n\t" + "adcs x6, x6, x6\n\t" + "adc x7, x7, x7\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "adds x2, x2, x5\n\t" + "adcs x3, x3, x6\n\t" + "adc x4, x4, x7\n\t" + "str x2, [%[tmp], 48]\n\t" + "# A[0] * A[7]\n\t" + "mul x5, x10, x17\n\t" + "umulh x6, x10, x17\n\t" + "mov x2, 0\n\t" + "mov x7, 0\n\t" + "# A[1] * A[6]\n\t" + "mul x8, x11, x16\n\t" + "umulh x9, x11, x16\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "# A[2] * A[5]\n\t" + "mul x8, x12, x15\n\t" + "umulh x9, x12, x15\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "# A[3] * A[4]\n\t" + "mul x8, x13, x14\n\t" + "umulh x9, x13, x14\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "adds x5, x5, x5\n\t" + "adcs x6, x6, x6\n\t" + "adc x7, x7, x7\n\t" + "adds x3, x3, x5\n\t" + "adcs x4, x4, x6\n\t" + "adc x2, x2, x7\n\t" + "str x3, [%[tmp], 56]\n\t" + "# A[0] * A[8]\n\t" + "mul x5, x10, x18\n\t" + "umulh x6, x10, x18\n\t" + "mov x3, 0\n\t" + "mov x7, 0\n\t" + "# A[1] * A[7]\n\t" + "mul x8, x11, x17\n\t" + "umulh x9, x11, x17\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "# A[2] * A[6]\n\t" + "mul x8, x12, x16\n\t" + "umulh x9, x12, x16\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "# A[3] * A[5]\n\t" + "mul x8, x13, x15\n\t" + "umulh x9, x13, x15\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "# A[4] * A[4]\n\t" + "mul x8, x14, x14\n\t" + "umulh x9, x14, x14\n\t" + "adds x5, x5, x5\n\t" + "adcs x6, x6, x6\n\t" + "adc x7, x7, x7\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "adds x4, x4, x5\n\t" + "adcs x2, x2, x6\n\t" + "adc x3, x3, x7\n\t" + "str x4, [%[tmp], 64]\n\t" + "# A[0] * A[9]\n\t" + "mul x5, x10, x19\n\t" + "umulh x6, x10, x19\n\t" + "mov x4, 0\n\t" + "mov x7, 0\n\t" + "# A[1] * A[8]\n\t" + "mul x8, x11, x18\n\t" + "umulh x9, x11, x18\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "# A[2] * A[7]\n\t" + "mul x8, x12, x17\n\t" + "umulh x9, x12, x17\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "# A[3] * A[6]\n\t" + "mul x8, x13, x16\n\t" + "umulh x9, x13, x16\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "# A[4] * A[5]\n\t" + "mul x8, x14, x15\n\t" + "umulh x9, x14, x15\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "adds x5, x5, x5\n\t" + "adcs x6, x6, x6\n\t" + "adc x7, x7, x7\n\t" + "adds x2, x2, x5\n\t" + "adcs x3, x3, x6\n\t" + "adc x4, x4, x7\n\t" + "str x2, [%[tmp], 72]\n\t" + "# A[0] * A[10]\n\t" + "mul x5, x10, x20\n\t" + "umulh x6, x10, x20\n\t" + "mov x2, 0\n\t" + "mov x7, 0\n\t" + "# A[1] * A[9]\n\t" + "mul x8, x11, x19\n\t" + "umulh x9, x11, x19\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "# A[2] * A[8]\n\t" + "mul x8, x12, x18\n\t" + "umulh x9, x12, x18\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "# A[3] * A[7]\n\t" + "mul x8, x13, x17\n\t" + "umulh x9, x13, x17\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "# A[4] * A[6]\n\t" + "mul x8, x14, x16\n\t" + "umulh x9, x14, x16\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "# A[5] * A[5]\n\t" + "mul x8, x15, x15\n\t" + "umulh x9, x15, x15\n\t" + "adds x5, x5, x5\n\t" + "adcs x6, x6, x6\n\t" + "adc x7, x7, x7\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "adds x3, x3, x5\n\t" + "adcs x4, x4, x6\n\t" + "adc x2, x2, x7\n\t" + "str x3, [%[tmp], 80]\n\t" + "# A[0] * A[11]\n\t" + "mul x5, x10, x21\n\t" + "umulh x6, x10, x21\n\t" + "mov x3, 0\n\t" + "mov x7, 0\n\t" + "# A[1] * A[10]\n\t" + "mul x8, x11, x20\n\t" + "umulh x9, x11, x20\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "# A[2] * A[9]\n\t" + "mul x8, x12, x19\n\t" + "umulh x9, x12, x19\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "# A[3] * A[8]\n\t" + "mul x8, x13, x18\n\t" + "umulh x9, x13, x18\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "# A[4] * A[7]\n\t" + "mul x8, x14, x17\n\t" + "umulh x9, x14, x17\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "# A[5] * A[6]\n\t" + "mul x8, x15, x16\n\t" + "umulh x9, x15, x16\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "adds x5, x5, x5\n\t" + "adcs x6, x6, x6\n\t" + "adc x7, x7, x7\n\t" + "adds x4, x4, x5\n\t" + "adcs x2, x2, x6\n\t" + "adc x3, x3, x7\n\t" + "str x4, [%[tmp], 88]\n\t" + "# A[1] * A[11]\n\t" + "mul x5, x11, x21\n\t" + "umulh x6, x11, x21\n\t" + "mov x4, 0\n\t" + "mov x7, 0\n\t" + "# A[2] * A[10]\n\t" + "mul x8, x12, x20\n\t" + "umulh x9, x12, x20\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "# A[3] * A[9]\n\t" + "mul x8, x13, x19\n\t" + "umulh x9, x13, x19\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "# A[4] * A[8]\n\t" + "mul x8, x14, x18\n\t" + "umulh x9, x14, x18\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "# A[5] * A[7]\n\t" + "mul x8, x15, x17\n\t" + "umulh x9, x15, x17\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "# A[6] * A[6]\n\t" + "mul x8, x16, x16\n\t" + "umulh x9, x16, x16\n\t" + "adds x5, x5, x5\n\t" + "adcs x6, x6, x6\n\t" + "adc x7, x7, x7\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "adds x2, x2, x5\n\t" + "adcs x3, x3, x6\n\t" + "adc x4, x4, x7\n\t" + "str x2, [%[r], 96]\n\t" + "# A[2] * A[11]\n\t" + "mul x5, x12, x21\n\t" + "umulh x6, x12, x21\n\t" + "mov x2, 0\n\t" + "mov x7, 0\n\t" + "# A[3] * A[10]\n\t" + "mul x8, x13, x20\n\t" + "umulh x9, x13, x20\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "# A[4] * A[9]\n\t" + "mul x8, x14, x19\n\t" + "umulh x9, x14, x19\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "# A[5] * A[8]\n\t" + "mul x8, x15, x18\n\t" + "umulh x9, x15, x18\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "# A[6] * A[7]\n\t" + "mul x8, x16, x17\n\t" + "umulh x9, x16, x17\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "adds x5, x5, x5\n\t" + "adcs x6, x6, x6\n\t" + "adc x7, x7, x7\n\t" + "adds x3, x3, x5\n\t" + "adcs x4, x4, x6\n\t" + "adc x2, x2, x7\n\t" + "str x3, [%[r], 104]\n\t" + "# A[3] * A[11]\n\t" + "mul x5, x13, x21\n\t" + "umulh x6, x13, x21\n\t" + "mov x3, 0\n\t" + "mov x7, 0\n\t" + "# A[4] * A[10]\n\t" + "mul x8, x14, x20\n\t" + "umulh x9, x14, x20\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "# A[5] * A[9]\n\t" + "mul x8, x15, x19\n\t" + "umulh x9, x15, x19\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "# A[6] * A[8]\n\t" + "mul x8, x16, x18\n\t" + "umulh x9, x16, x18\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "# A[7] * A[7]\n\t" + "mul x8, x17, x17\n\t" + "umulh x9, x17, x17\n\t" + "adds x5, x5, x5\n\t" + "adcs x6, x6, x6\n\t" + "adc x7, x7, x7\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "adds x4, x4, x5\n\t" + "adcs x2, x2, x6\n\t" + "adc x3, x3, x7\n\t" + "str x4, [%[r], 112]\n\t" + "# A[4] * A[11]\n\t" + "mul x5, x14, x21\n\t" + "umulh x6, x14, x21\n\t" + "mov x4, 0\n\t" + "mov x7, 0\n\t" + "# A[5] * A[10]\n\t" + "mul x8, x15, x20\n\t" + "umulh x9, x15, x20\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "# A[6] * A[9]\n\t" + "mul x8, x16, x19\n\t" + "umulh x9, x16, x19\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "# A[7] * A[8]\n\t" + "mul x8, x17, x18\n\t" + "umulh x9, x17, x18\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "adds x5, x5, x5\n\t" + "adcs x6, x6, x6\n\t" + "adc x7, x7, x7\n\t" + "adds x2, x2, x5\n\t" + "adcs x3, x3, x6\n\t" + "adc x4, x4, x7\n\t" + "str x2, [%[r], 120]\n\t" + "# A[5] * A[11]\n\t" + "mul x5, x15, x21\n\t" + "umulh x6, x15, x21\n\t" + "mov x2, 0\n\t" + "mov x7, 0\n\t" + "# A[6] * A[10]\n\t" + "mul x8, x16, x20\n\t" + "umulh x9, x16, x20\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "# A[7] * A[9]\n\t" + "mul x8, x17, x19\n\t" + "umulh x9, x17, x19\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "# A[8] * A[8]\n\t" + "mul x8, x18, x18\n\t" + "umulh x9, x18, x18\n\t" + "adds x5, x5, x5\n\t" + "adcs x6, x6, x6\n\t" + "adc x7, x7, x7\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "adds x3, x3, x5\n\t" + "adcs x4, x4, x6\n\t" + "adc x2, x2, x7\n\t" + "str x3, [%[r], 128]\n\t" + "# A[6] * A[11]\n\t" + "mul x5, x16, x21\n\t" + "umulh x6, x16, x21\n\t" + "mov x3, 0\n\t" + "mov x7, 0\n\t" + "# A[7] * A[10]\n\t" + "mul x8, x17, x20\n\t" + "umulh x9, x17, x20\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "# A[8] * A[9]\n\t" + "mul x8, x18, x19\n\t" + "umulh x9, x18, x19\n\t" + "adds x5, x5, x8\n\t" + "adcs x6, x6, x9\n\t" + "adc x7, x7, xzr\n\t" + "adds x5, x5, x5\n\t" + "adcs x6, x6, x6\n\t" + "adc x7, x7, x7\n\t" + "adds x4, x4, x5\n\t" + "adcs x2, x2, x6\n\t" + "adc x3, x3, x7\n\t" + "str x4, [%[r], 136]\n\t" + "# A[7] * A[11]\n\t" + "mul x8, x17, x21\n\t" + "umulh x9, x17, x21\n\t" + "adds x2, x2, x8\n\t" + "adcs x3, x3, x9\n\t" + "adc x4, xzr, xzr\n\t" + "adds x2, x2, x8\n\t" + "adcs x3, x3, x9\n\t" + "adc x4, x4, xzr\n\t" + "# A[8] * A[10]\n\t" + "mul x8, x18, x20\n\t" + "umulh x9, x18, x20\n\t" + "adds x2, x2, x8\n\t" + "adcs x3, x3, x9\n\t" + "adc x4, x4, xzr\n\t" + "adds x2, x2, x8\n\t" + "adcs x3, x3, x9\n\t" + "adc x4, x4, xzr\n\t" + "# A[9] * A[9]\n\t" + "mul x8, x19, x19\n\t" + "umulh x9, x19, x19\n\t" + "adds x2, x2, x8\n\t" + "adcs x3, x3, x9\n\t" + "adc x4, x4, xzr\n\t" + "str x2, [%[r], 144]\n\t" + "# A[8] * A[11]\n\t" + "mul x8, x18, x21\n\t" + "umulh x9, x18, x21\n\t" + "adds x3, x3, x8\n\t" + "adcs x4, x4, x9\n\t" + "adc x2, xzr, xzr\n\t" + "adds x3, x3, x8\n\t" + "adcs x4, x4, x9\n\t" + "adc x2, x2, xzr\n\t" + "# A[9] * A[10]\n\t" + "mul x8, x19, x20\n\t" + "umulh x9, x19, x20\n\t" + "adds x3, x3, x8\n\t" + "adcs x4, x4, x9\n\t" + "adc x2, x2, xzr\n\t" + "adds x3, x3, x8\n\t" + "adcs x4, x4, x9\n\t" + "adc x2, x2, xzr\n\t" + "str x3, [%[r], 152]\n\t" + "# A[9] * A[11]\n\t" + "mul x8, x19, x21\n\t" + "umulh x9, x19, x21\n\t" + "adds x4, x4, x8\n\t" + "adcs x2, x2, x9\n\t" + "adc x3, xzr, xzr\n\t" + "adds x4, x4, x8\n\t" + "adcs x2, x2, x9\n\t" + "adc x3, x3, xzr\n\t" + "# A[10] * A[10]\n\t" + "mul x8, x20, x20\n\t" + "umulh x9, x20, x20\n\t" + "adds x4, x4, x8\n\t" + "adcs x2, x2, x9\n\t" + "adc x3, x3, xzr\n\t" + "str x4, [%[r], 160]\n\t" + "# A[10] * A[11]\n\t" + "mul x8, x20, x21\n\t" + "umulh x9, x20, x21\n\t" + "adds x2, x2, x8\n\t" + "adcs x3, x3, x9\n\t" + "adc x4, xzr, xzr\n\t" + "adds x2, x2, x8\n\t" + "adcs x3, x3, x9\n\t" + "adc x4, x4, xzr\n\t" + "str x2, [%[r], 168]\n\t" + "# A[11] * A[11]\n\t" + "mul x8, x21, x21\n\t" + "umulh x9, x21, x21\n\t" + "adds x3, x3, x8\n\t" + "adc x4, x4, x9\n\t" + "stp x3, x4, [%[r], 176]\n\t" + : + : [r] "r" (r), [a] "r" (a), [tmp] "r" (tmp) + : "memory", "x2", "x3", "x4", "x8", "x9", "x10", "x5", "x6", "x7", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_3072_add_12(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldp x3, x4, [%[a], 0]\n\t" + "ldp x5, x6, [%[a], 16]\n\t" + "ldp x7, x8, [%[b], 0]\n\t" + "ldp x9, x10, [%[b], 16]\n\t" + "adds x3, x3, x7\n\t" + "adcs x4, x4, x8\n\t" + "adcs x5, x5, x9\n\t" + "adcs x6, x6, x10\n\t" + "stp x3, x4, [%[r], 0]\n\t" + "stp x5, x6, [%[r], 16]\n\t" + "ldp x3, x4, [%[a], 32]\n\t" + "ldp x5, x6, [%[a], 48]\n\t" + "ldp x7, x8, [%[b], 32]\n\t" + "ldp x9, x10, [%[b], 48]\n\t" + "adcs x3, x3, x7\n\t" + "adcs x4, x4, x8\n\t" + "adcs x5, x5, x9\n\t" + "adcs x6, x6, x10\n\t" + "stp x3, x4, [%[r], 32]\n\t" + "stp x5, x6, [%[r], 48]\n\t" + "ldp x3, x4, [%[a], 64]\n\t" + "ldp x5, x6, [%[a], 80]\n\t" + "ldp x7, x8, [%[b], 64]\n\t" + "ldp x9, x10, [%[b], 80]\n\t" + "adcs x3, x3, x7\n\t" + "adcs x4, x4, x8\n\t" + "adcs x5, x5, x9\n\t" + "adcs x6, x6, x10\n\t" + "stp x3, x4, [%[r], 64]\n\t" + "stp x5, x6, [%[r], 80]\n\t" + "cset %[c], cs\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10" + ); + + return c; +} + +/* Sub b from a into a. (a -= b) + * + * a A single precision integer and result. + * b A single precision integer. + */ +static sp_digit sp_3072_sub_in_place_24(sp_digit* a, const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldp x2, x3, [%[a], 0]\n\t" + "ldp x4, x5, [%[a], 16]\n\t" + "ldp x6, x7, [%[b], 0]\n\t" + "ldp x8, x9, [%[b], 16]\n\t" + "subs x2, x2, x6\n\t" + "sbcs x3, x3, x7\n\t" + "sbcs x4, x4, x8\n\t" + "sbcs x5, x5, x9\n\t" + "stp x2, x3, [%[a], 0]\n\t" + "stp x4, x5, [%[a], 16]\n\t" + "ldp x2, x3, [%[a], 32]\n\t" + "ldp x4, x5, [%[a], 48]\n\t" + "ldp x6, x7, [%[b], 32]\n\t" + "ldp x8, x9, [%[b], 48]\n\t" + "sbcs x2, x2, x6\n\t" + "sbcs x3, x3, x7\n\t" + "sbcs x4, x4, x8\n\t" + "sbcs x5, x5, x9\n\t" + "stp x2, x3, [%[a], 32]\n\t" + "stp x4, x5, [%[a], 48]\n\t" + "ldp x2, x3, [%[a], 64]\n\t" + "ldp x4, x5, [%[a], 80]\n\t" + "ldp x6, x7, [%[b], 64]\n\t" + "ldp x8, x9, [%[b], 80]\n\t" + "sbcs x2, x2, x6\n\t" + "sbcs x3, x3, x7\n\t" + "sbcs x4, x4, x8\n\t" + "sbcs x5, x5, x9\n\t" + "stp x2, x3, [%[a], 64]\n\t" + "stp x4, x5, [%[a], 80]\n\t" + "ldp x2, x3, [%[a], 96]\n\t" + "ldp x4, x5, [%[a], 112]\n\t" + "ldp x6, x7, [%[b], 96]\n\t" + "ldp x8, x9, [%[b], 112]\n\t" + "sbcs x2, x2, x6\n\t" + "sbcs x3, x3, x7\n\t" + "sbcs x4, x4, x8\n\t" + "sbcs x5, x5, x9\n\t" + "stp x2, x3, [%[a], 96]\n\t" + "stp x4, x5, [%[a], 112]\n\t" + "ldp x2, x3, [%[a], 128]\n\t" + "ldp x4, x5, [%[a], 144]\n\t" + "ldp x6, x7, [%[b], 128]\n\t" + "ldp x8, x9, [%[b], 144]\n\t" + "sbcs x2, x2, x6\n\t" + "sbcs x3, x3, x7\n\t" + "sbcs x4, x4, x8\n\t" + "sbcs x5, x5, x9\n\t" + "stp x2, x3, [%[a], 128]\n\t" + "stp x4, x5, [%[a], 144]\n\t" + "ldp x2, x3, [%[a], 160]\n\t" + "ldp x4, x5, [%[a], 176]\n\t" + "ldp x6, x7, [%[b], 160]\n\t" + "ldp x8, x9, [%[b], 176]\n\t" + "sbcs x2, x2, x6\n\t" + "sbcs x3, x3, x7\n\t" + "sbcs x4, x4, x8\n\t" + "sbcs x5, x5, x9\n\t" + "stp x2, x3, [%[a], 160]\n\t" + "stp x4, x5, [%[a], 176]\n\t" + "csetm %[c], cc\n\t" + : [c] "+r" (c) + : [a] "r" (a), [b] "r" (b) + : "memory", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9" + ); + + return c; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_3072_add_24(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldp x3, x4, [%[a], 0]\n\t" + "ldp x5, x6, [%[a], 16]\n\t" + "ldp x7, x8, [%[b], 0]\n\t" + "ldp x9, x10, [%[b], 16]\n\t" + "adds x3, x3, x7\n\t" + "adcs x4, x4, x8\n\t" + "adcs x5, x5, x9\n\t" + "adcs x6, x6, x10\n\t" + "stp x3, x4, [%[r], 0]\n\t" + "stp x5, x6, [%[r], 16]\n\t" + "ldp x3, x4, [%[a], 32]\n\t" + "ldp x5, x6, [%[a], 48]\n\t" + "ldp x7, x8, [%[b], 32]\n\t" + "ldp x9, x10, [%[b], 48]\n\t" + "adcs x3, x3, x7\n\t" + "adcs x4, x4, x8\n\t" + "adcs x5, x5, x9\n\t" + "adcs x6, x6, x10\n\t" + "stp x3, x4, [%[r], 32]\n\t" + "stp x5, x6, [%[r], 48]\n\t" + "ldp x3, x4, [%[a], 64]\n\t" + "ldp x5, x6, [%[a], 80]\n\t" + "ldp x7, x8, [%[b], 64]\n\t" + "ldp x9, x10, [%[b], 80]\n\t" + "adcs x3, x3, x7\n\t" + "adcs x4, x4, x8\n\t" + "adcs x5, x5, x9\n\t" + "adcs x6, x6, x10\n\t" + "stp x3, x4, [%[r], 64]\n\t" + "stp x5, x6, [%[r], 80]\n\t" + "ldp x3, x4, [%[a], 96]\n\t" + "ldp x5, x6, [%[a], 112]\n\t" + "ldp x7, x8, [%[b], 96]\n\t" + "ldp x9, x10, [%[b], 112]\n\t" + "adcs x3, x3, x7\n\t" + "adcs x4, x4, x8\n\t" + "adcs x5, x5, x9\n\t" + "adcs x6, x6, x10\n\t" + "stp x3, x4, [%[r], 96]\n\t" + "stp x5, x6, [%[r], 112]\n\t" + "ldp x3, x4, [%[a], 128]\n\t" + "ldp x5, x6, [%[a], 144]\n\t" + "ldp x7, x8, [%[b], 128]\n\t" + "ldp x9, x10, [%[b], 144]\n\t" + "adcs x3, x3, x7\n\t" + "adcs x4, x4, x8\n\t" + "adcs x5, x5, x9\n\t" + "adcs x6, x6, x10\n\t" + "stp x3, x4, [%[r], 128]\n\t" + "stp x5, x6, [%[r], 144]\n\t" + "ldp x3, x4, [%[a], 160]\n\t" + "ldp x5, x6, [%[a], 176]\n\t" + "ldp x7, x8, [%[b], 160]\n\t" + "ldp x9, x10, [%[b], 176]\n\t" + "adcs x3, x3, x7\n\t" + "adcs x4, x4, x8\n\t" + "adcs x5, x5, x9\n\t" + "adcs x6, x6, x10\n\t" + "stp x3, x4, [%[r], 160]\n\t" + "stp x5, x6, [%[r], 176]\n\t" + "cset %[c], cs\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10" + ); + + return c; +} + +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_3072_mask_12(sp_digit* r, sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<12; i++) + r[i] = a[i] & m; +#else + r[0] = a[0] & m; + r[1] = a[1] & m; + r[2] = a[2] & m; + r[3] = a[3] & m; + r[4] = a[4] & m; + r[5] = a[5] & m; + r[6] = a[6] & m; + r[7] = a[7] & m; + r[8] = a[8] & m; + r[9] = a[9] & m; + r[10] = a[10] & m; + r[11] = a[11] & m; +#endif +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_3072_mul_24(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[24]; + sp_digit a1[12]; + sp_digit b1[12]; + sp_digit z2[24]; + sp_digit u, ca, cb; + + ca = sp_3072_add_12(a1, a, &a[12]); + cb = sp_3072_add_12(b1, b, &b[12]); + u = ca & cb; + sp_3072_mul_12(z1, a1, b1); + sp_3072_mul_12(z2, &a[12], &b[12]); + sp_3072_mul_12(z0, a, b); + sp_3072_mask_12(r + 24, a1, 0 - cb); + sp_3072_mask_12(b1, b1, 0 - ca); + u += sp_3072_add_12(r + 24, r + 24, b1); + u += sp_3072_sub_in_place_24(z1, z2); + u += sp_3072_sub_in_place_24(z1, z0); + u += sp_3072_add_24(r + 12, r + 12, z1); + r[36] = u; + XMEMSET(r + 36 + 1, 0, sizeof(sp_digit) * (12 - 1)); + sp_3072_add_24(r + 24, r + 24, z2); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_3072_sqr_24(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z2[24]; + sp_digit z1[24]; + sp_digit a1[12]; + sp_digit u; + + u = sp_3072_add_12(a1, a, &a[12]); + sp_3072_sqr_12(z1, a1); + sp_3072_sqr_12(z2, &a[12]); + sp_3072_sqr_12(z0, a); + sp_3072_mask_12(r + 24, a1, 0 - u); + u += sp_3072_add_12(r + 24, r + 24, r + 24); + u += sp_3072_sub_in_place_24(z1, z2); + u += sp_3072_sub_in_place_24(z1, z0); + u += sp_3072_add_24(r + 12, r + 12, z1); + r[36] = u; + XMEMSET(r + 36 + 1, 0, sizeof(sp_digit) * (12 - 1)); + sp_3072_add_24(r + 24, r + 24, z2); +} + +/* Sub b from a into a. (a -= b) + * + * a A single precision integer and result. + * b A single precision integer. + */ +static sp_digit sp_3072_sub_in_place_48(sp_digit* a, const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldp x2, x3, [%[a], 0]\n\t" + "ldp x4, x5, [%[a], 16]\n\t" + "ldp x6, x7, [%[b], 0]\n\t" + "ldp x8, x9, [%[b], 16]\n\t" + "subs x2, x2, x6\n\t" + "sbcs x3, x3, x7\n\t" + "sbcs x4, x4, x8\n\t" + "sbcs x5, x5, x9\n\t" + "stp x2, x3, [%[a], 0]\n\t" + "stp x4, x5, [%[a], 16]\n\t" + "ldp x2, x3, [%[a], 32]\n\t" + "ldp x4, x5, [%[a], 48]\n\t" + "ldp x6, x7, [%[b], 32]\n\t" + "ldp x8, x9, [%[b], 48]\n\t" + "sbcs x2, x2, x6\n\t" + "sbcs x3, x3, x7\n\t" + "sbcs x4, x4, x8\n\t" + "sbcs x5, x5, x9\n\t" + "stp x2, x3, [%[a], 32]\n\t" + "stp x4, x5, [%[a], 48]\n\t" + "ldp x2, x3, [%[a], 64]\n\t" + "ldp x4, x5, [%[a], 80]\n\t" + "ldp x6, x7, [%[b], 64]\n\t" + "ldp x8, x9, [%[b], 80]\n\t" + "sbcs x2, x2, x6\n\t" + "sbcs x3, x3, x7\n\t" + "sbcs x4, x4, x8\n\t" + "sbcs x5, x5, x9\n\t" + "stp x2, x3, [%[a], 64]\n\t" + "stp x4, x5, [%[a], 80]\n\t" + "ldp x2, x3, [%[a], 96]\n\t" + "ldp x4, x5, [%[a], 112]\n\t" + "ldp x6, x7, [%[b], 96]\n\t" + "ldp x8, x9, [%[b], 112]\n\t" + "sbcs x2, x2, x6\n\t" + "sbcs x3, x3, x7\n\t" + "sbcs x4, x4, x8\n\t" + "sbcs x5, x5, x9\n\t" + "stp x2, x3, [%[a], 96]\n\t" + "stp x4, x5, [%[a], 112]\n\t" + "ldp x2, x3, [%[a], 128]\n\t" + "ldp x4, x5, [%[a], 144]\n\t" + "ldp x6, x7, [%[b], 128]\n\t" + "ldp x8, x9, [%[b], 144]\n\t" + "sbcs x2, x2, x6\n\t" + "sbcs x3, x3, x7\n\t" + "sbcs x4, x4, x8\n\t" + "sbcs x5, x5, x9\n\t" + "stp x2, x3, [%[a], 128]\n\t" + "stp x4, x5, [%[a], 144]\n\t" + "ldp x2, x3, [%[a], 160]\n\t" + "ldp x4, x5, [%[a], 176]\n\t" + "ldp x6, x7, [%[b], 160]\n\t" + "ldp x8, x9, [%[b], 176]\n\t" + "sbcs x2, x2, x6\n\t" + "sbcs x3, x3, x7\n\t" + "sbcs x4, x4, x8\n\t" + "sbcs x5, x5, x9\n\t" + "stp x2, x3, [%[a], 160]\n\t" + "stp x4, x5, [%[a], 176]\n\t" + "ldp x2, x3, [%[a], 192]\n\t" + "ldp x4, x5, [%[a], 208]\n\t" + "ldp x6, x7, [%[b], 192]\n\t" + "ldp x8, x9, [%[b], 208]\n\t" + "sbcs x2, x2, x6\n\t" + "sbcs x3, x3, x7\n\t" + "sbcs x4, x4, x8\n\t" + "sbcs x5, x5, x9\n\t" + "stp x2, x3, [%[a], 192]\n\t" + "stp x4, x5, [%[a], 208]\n\t" + "ldp x2, x3, [%[a], 224]\n\t" + "ldp x4, x5, [%[a], 240]\n\t" + "ldp x6, x7, [%[b], 224]\n\t" + "ldp x8, x9, [%[b], 240]\n\t" + "sbcs x2, x2, x6\n\t" + "sbcs x3, x3, x7\n\t" + "sbcs x4, x4, x8\n\t" + "sbcs x5, x5, x9\n\t" + "stp x2, x3, [%[a], 224]\n\t" + "stp x4, x5, [%[a], 240]\n\t" + "ldp x2, x3, [%[a], 256]\n\t" + "ldp x4, x5, [%[a], 272]\n\t" + "ldp x6, x7, [%[b], 256]\n\t" + "ldp x8, x9, [%[b], 272]\n\t" + "sbcs x2, x2, x6\n\t" + "sbcs x3, x3, x7\n\t" + "sbcs x4, x4, x8\n\t" + "sbcs x5, x5, x9\n\t" + "stp x2, x3, [%[a], 256]\n\t" + "stp x4, x5, [%[a], 272]\n\t" + "ldp x2, x3, [%[a], 288]\n\t" + "ldp x4, x5, [%[a], 304]\n\t" + "ldp x6, x7, [%[b], 288]\n\t" + "ldp x8, x9, [%[b], 304]\n\t" + "sbcs x2, x2, x6\n\t" + "sbcs x3, x3, x7\n\t" + "sbcs x4, x4, x8\n\t" + "sbcs x5, x5, x9\n\t" + "stp x2, x3, [%[a], 288]\n\t" + "stp x4, x5, [%[a], 304]\n\t" + "ldp x2, x3, [%[a], 320]\n\t" + "ldp x4, x5, [%[a], 336]\n\t" + "ldp x6, x7, [%[b], 320]\n\t" + "ldp x8, x9, [%[b], 336]\n\t" + "sbcs x2, x2, x6\n\t" + "sbcs x3, x3, x7\n\t" + "sbcs x4, x4, x8\n\t" + "sbcs x5, x5, x9\n\t" + "stp x2, x3, [%[a], 320]\n\t" + "stp x4, x5, [%[a], 336]\n\t" + "ldp x2, x3, [%[a], 352]\n\t" + "ldp x4, x5, [%[a], 368]\n\t" + "ldp x6, x7, [%[b], 352]\n\t" + "ldp x8, x9, [%[b], 368]\n\t" + "sbcs x2, x2, x6\n\t" + "sbcs x3, x3, x7\n\t" + "sbcs x4, x4, x8\n\t" + "sbcs x5, x5, x9\n\t" + "stp x2, x3, [%[a], 352]\n\t" + "stp x4, x5, [%[a], 368]\n\t" + "csetm %[c], cc\n\t" + : [c] "+r" (c) + : [a] "r" (a), [b] "r" (b) + : "memory", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9" + ); + + return c; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_3072_add_48(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldp x3, x4, [%[a], 0]\n\t" + "ldp x5, x6, [%[a], 16]\n\t" + "ldp x7, x8, [%[b], 0]\n\t" + "ldp x9, x10, [%[b], 16]\n\t" + "adds x3, x3, x7\n\t" + "adcs x4, x4, x8\n\t" + "adcs x5, x5, x9\n\t" + "adcs x6, x6, x10\n\t" + "stp x3, x4, [%[r], 0]\n\t" + "stp x5, x6, [%[r], 16]\n\t" + "ldp x3, x4, [%[a], 32]\n\t" + "ldp x5, x6, [%[a], 48]\n\t" + "ldp x7, x8, [%[b], 32]\n\t" + "ldp x9, x10, [%[b], 48]\n\t" + "adcs x3, x3, x7\n\t" + "adcs x4, x4, x8\n\t" + "adcs x5, x5, x9\n\t" + "adcs x6, x6, x10\n\t" + "stp x3, x4, [%[r], 32]\n\t" + "stp x5, x6, [%[r], 48]\n\t" + "ldp x3, x4, [%[a], 64]\n\t" + "ldp x5, x6, [%[a], 80]\n\t" + "ldp x7, x8, [%[b], 64]\n\t" + "ldp x9, x10, [%[b], 80]\n\t" + "adcs x3, x3, x7\n\t" + "adcs x4, x4, x8\n\t" + "adcs x5, x5, x9\n\t" + "adcs x6, x6, x10\n\t" + "stp x3, x4, [%[r], 64]\n\t" + "stp x5, x6, [%[r], 80]\n\t" + "ldp x3, x4, [%[a], 96]\n\t" + "ldp x5, x6, [%[a], 112]\n\t" + "ldp x7, x8, [%[b], 96]\n\t" + "ldp x9, x10, [%[b], 112]\n\t" + "adcs x3, x3, x7\n\t" + "adcs x4, x4, x8\n\t" + "adcs x5, x5, x9\n\t" + "adcs x6, x6, x10\n\t" + "stp x3, x4, [%[r], 96]\n\t" + "stp x5, x6, [%[r], 112]\n\t" + "ldp x3, x4, [%[a], 128]\n\t" + "ldp x5, x6, [%[a], 144]\n\t" + "ldp x7, x8, [%[b], 128]\n\t" + "ldp x9, x10, [%[b], 144]\n\t" + "adcs x3, x3, x7\n\t" + "adcs x4, x4, x8\n\t" + "adcs x5, x5, x9\n\t" + "adcs x6, x6, x10\n\t" + "stp x3, x4, [%[r], 128]\n\t" + "stp x5, x6, [%[r], 144]\n\t" + "ldp x3, x4, [%[a], 160]\n\t" + "ldp x5, x6, [%[a], 176]\n\t" + "ldp x7, x8, [%[b], 160]\n\t" + "ldp x9, x10, [%[b], 176]\n\t" + "adcs x3, x3, x7\n\t" + "adcs x4, x4, x8\n\t" + "adcs x5, x5, x9\n\t" + "adcs x6, x6, x10\n\t" + "stp x3, x4, [%[r], 160]\n\t" + "stp x5, x6, [%[r], 176]\n\t" + "ldp x3, x4, [%[a], 192]\n\t" + "ldp x5, x6, [%[a], 208]\n\t" + "ldp x7, x8, [%[b], 192]\n\t" + "ldp x9, x10, [%[b], 208]\n\t" + "adcs x3, x3, x7\n\t" + "adcs x4, x4, x8\n\t" + "adcs x5, x5, x9\n\t" + "adcs x6, x6, x10\n\t" + "stp x3, x4, [%[r], 192]\n\t" + "stp x5, x6, [%[r], 208]\n\t" + "ldp x3, x4, [%[a], 224]\n\t" + "ldp x5, x6, [%[a], 240]\n\t" + "ldp x7, x8, [%[b], 224]\n\t" + "ldp x9, x10, [%[b], 240]\n\t" + "adcs x3, x3, x7\n\t" + "adcs x4, x4, x8\n\t" + "adcs x5, x5, x9\n\t" + "adcs x6, x6, x10\n\t" + "stp x3, x4, [%[r], 224]\n\t" + "stp x5, x6, [%[r], 240]\n\t" + "ldp x3, x4, [%[a], 256]\n\t" + "ldp x5, x6, [%[a], 272]\n\t" + "ldp x7, x8, [%[b], 256]\n\t" + "ldp x9, x10, [%[b], 272]\n\t" + "adcs x3, x3, x7\n\t" + "adcs x4, x4, x8\n\t" + "adcs x5, x5, x9\n\t" + "adcs x6, x6, x10\n\t" + "stp x3, x4, [%[r], 256]\n\t" + "stp x5, x6, [%[r], 272]\n\t" + "ldp x3, x4, [%[a], 288]\n\t" + "ldp x5, x6, [%[a], 304]\n\t" + "ldp x7, x8, [%[b], 288]\n\t" + "ldp x9, x10, [%[b], 304]\n\t" + "adcs x3, x3, x7\n\t" + "adcs x4, x4, x8\n\t" + "adcs x5, x5, x9\n\t" + "adcs x6, x6, x10\n\t" + "stp x3, x4, [%[r], 288]\n\t" + "stp x5, x6, [%[r], 304]\n\t" + "ldp x3, x4, [%[a], 320]\n\t" + "ldp x5, x6, [%[a], 336]\n\t" + "ldp x7, x8, [%[b], 320]\n\t" + "ldp x9, x10, [%[b], 336]\n\t" + "adcs x3, x3, x7\n\t" + "adcs x4, x4, x8\n\t" + "adcs x5, x5, x9\n\t" + "adcs x6, x6, x10\n\t" + "stp x3, x4, [%[r], 320]\n\t" + "stp x5, x6, [%[r], 336]\n\t" + "ldp x3, x4, [%[a], 352]\n\t" + "ldp x5, x6, [%[a], 368]\n\t" + "ldp x7, x8, [%[b], 352]\n\t" + "ldp x9, x10, [%[b], 368]\n\t" + "adcs x3, x3, x7\n\t" + "adcs x4, x4, x8\n\t" + "adcs x5, x5, x9\n\t" + "adcs x6, x6, x10\n\t" + "stp x3, x4, [%[r], 352]\n\t" + "stp x5, x6, [%[r], 368]\n\t" + "cset %[c], cs\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10" + ); + + return c; +} + +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_3072_mask_24(sp_digit* r, sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<24; i++) + r[i] = a[i] & m; +#else + int i; + + for (i = 0; i < 24; i += 8) { + r[i+0] = a[i+0] & m; + r[i+1] = a[i+1] & m; + r[i+2] = a[i+2] & m; + r[i+3] = a[i+3] & m; + r[i+4] = a[i+4] & m; + r[i+5] = a[i+5] & m; + r[i+6] = a[i+6] & m; + r[i+7] = a[i+7] & m; + } +#endif +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_3072_mul_48(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[48]; + sp_digit a1[24]; + sp_digit b1[24]; + sp_digit z2[48]; + sp_digit u, ca, cb; + + ca = sp_3072_add_24(a1, a, &a[24]); + cb = sp_3072_add_24(b1, b, &b[24]); + u = ca & cb; + sp_3072_mul_24(z1, a1, b1); + sp_3072_mul_24(z2, &a[24], &b[24]); + sp_3072_mul_24(z0, a, b); + sp_3072_mask_24(r + 48, a1, 0 - cb); + sp_3072_mask_24(b1, b1, 0 - ca); + u += sp_3072_add_24(r + 48, r + 48, b1); + u += sp_3072_sub_in_place_48(z1, z2); + u += sp_3072_sub_in_place_48(z1, z0); + u += sp_3072_add_48(r + 24, r + 24, z1); + r[72] = u; + XMEMSET(r + 72 + 1, 0, sizeof(sp_digit) * (24 - 1)); + sp_3072_add_48(r + 48, r + 48, z2); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_3072_sqr_48(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z2[48]; + sp_digit z1[48]; + sp_digit a1[24]; + sp_digit u; + + u = sp_3072_add_24(a1, a, &a[24]); + sp_3072_sqr_24(z1, a1); + sp_3072_sqr_24(z2, &a[24]); + sp_3072_sqr_24(z0, a); + sp_3072_mask_24(r + 48, a1, 0 - u); + u += sp_3072_add_24(r + 48, r + 48, r + 48); + u += sp_3072_sub_in_place_48(z1, z2); + u += sp_3072_sub_in_place_48(z1, z0); + u += sp_3072_add_48(r + 24, r + 24, z1); + r[72] = u; + XMEMSET(r + 72 + 1, 0, sizeof(sp_digit) * (24 - 1)); + sp_3072_add_48(r + 48, r + 48, z2); +} + +#endif /* !WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_3072_add_48(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "add x11, %[a], 384\n\t" + "\n1:\n\t" + "adds %[c], %[c], #-1\n\t" + "ldp x3, x4, [%[a]], #16\n\t" + "ldp x5, x6, [%[a]], #16\n\t" + "ldp x7, x8, [%[b]], #16\n\t" + "ldp x9, x10, [%[b]], #16\n\t" + "adcs x3, x3, x7\n\t" + "adcs x4, x4, x8\n\t" + "adcs x5, x5, x9\n\t" + "adcs x6, x6, x10\n\t" + "stp x3, x4, [%[r]], #16\n\t" + "stp x5, x6, [%[r]], #16\n\t" + "cset %[c], cs\n\t" + "cmp %[a], x11\n\t" + "b.ne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into a. (a -= b) + * + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_3072_sub_in_place_48(sp_digit* a, const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "add x10, %[a], 384\n\t" + "\n1:\n\t" + "subs %[c], xzr, %[c]\n\t" + "ldp x2, x3, [%[a]]\n\t" + "ldp x4, x5, [%[a], #16]\n\t" + "ldp x6, x7, [%[b]], #16\n\t" + "ldp x8, x9, [%[b]], #16\n\t" + "sbcs x2, x2, x6\n\t" + "sbcs x3, x3, x7\n\t" + "sbcs x4, x4, x8\n\t" + "sbcs x5, x5, x9\n\t" + "stp x2, x3, [%[a]], #16\n\t" + "stp x4, x5, [%[a]], #16\n\t" + "csetm %[c], cc\n\t" + "cmp %[a], x10\n\t" + "b.ne 1b\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_3072_mul_48(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + sp_digit tmp[96]; + + __asm__ __volatile__ ( + "mov x5, 0\n\t" + "mov x6, 0\n\t" + "mov x7, 0\n\t" + "mov x8, 0\n\t" + "\n1:\n\t" + "subs x3, x5, 376\n\t" + "csel x3, xzr, x3, cc\n\t" + "sub x4, x5, x3\n\t" + "\n2:\n\t" + "ldr x10, [%[a], x3]\n\t" + "ldr x11, [%[b], x4]\n\t" + "mul x9, x10, x11\n\t" + "umulh x10, x10, x11\n\t" + "adds x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x8, x8, xzr\n\t" + "add x3, x3, #8\n\t" + "sub x4, x4, #8\n\t" + "cmp x3, 384\n\t" + "b.eq 3f\n\t" + "cmp x3, x5\n\t" + "b.le 2b\n\t" + "\n3:\n\t" + "str x6, [%[r], x5]\n\t" + "mov x6, x7\n\t" + "mov x7, x8\n\t" + "mov x8, #0\n\t" + "add x5, x5, #8\n\t" + "cmp x5, 752\n\t" + "b.le 1b\n\t" + "str x6, [%[r], x5]\n\t" + : + : [r] "r" (tmp), [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_3072_sqr_48(sp_digit* r, const sp_digit* a) +{ + sp_digit tmp[96]; + + __asm__ __volatile__ ( + "mov x6, 0\n\t" + "mov x7, 0\n\t" + "mov x8, 0\n\t" + "mov x5, 0\n\t" + "\n1:\n\t" + "subs x3, x5, 376\n\t" + "csel x3, xzr, x3, cc\n\t" + "sub x4, x5, x3\n\t" + "\n2:\n\t" + "cmp x4, x3\n\t" + "b.eq 4f\n\t" + "ldr x10, [%[a], x3]\n\t" + "ldr x11, [%[a], x4]\n\t" + "mul x9, x10, x11\n\t" + "umulh x10, x10, x11\n\t" + "adds x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x8, x8, xzr\n\t" + "adds x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x8, x8, xzr\n\t" + "b.al 5f\n\t" + "\n4:\n\t" + "ldr x10, [%[a], x3]\n\t" + "mul x9, x10, x10\n\t" + "umulh x10, x10, x10\n\t" + "adds x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x8, x8, xzr\n\t" + "\n5:\n\t" + "add x3, x3, #8\n\t" + "sub x4, x4, #8\n\t" + "cmp x3, 384\n\t" + "b.eq 3f\n\t" + "cmp x3, x4\n\t" + "b.gt 3f\n\t" + "cmp x3, x5\n\t" + "b.le 2b\n\t" + "\n3:\n\t" + "str x6, [%[r], x5]\n\t" + "mov x6, x7\n\t" + "mov x7, x8\n\t" + "mov x8, #0\n\t" + "add x5, x5, #8\n\t" + "cmp x5, 752\n\t" + "b.le 1b\n\t" + "str x6, [%[r], x5]\n\t" + : + : [r] "r" (tmp), [a] "r" (a) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +#endif /* WOLFSSL_SP_SMALL */ +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +#ifdef WOLFSSL_SP_SMALL +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_3072_mask_24(sp_digit* r, sp_digit* a, sp_digit m) +{ + int i; + + for (i=0; i<24; i++) + r[i] = a[i] & m; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_3072_add_24(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "add x11, %[a], 192\n\t" + "\n1:\n\t" + "adds %[c], %[c], #-1\n\t" + "ldp x3, x4, [%[a]], #16\n\t" + "ldp x5, x6, [%[a]], #16\n\t" + "ldp x7, x8, [%[b]], #16\n\t" + "ldp x9, x10, [%[b]], #16\n\t" + "adcs x3, x3, x7\n\t" + "adcs x4, x4, x8\n\t" + "adcs x5, x5, x9\n\t" + "adcs x6, x6, x10\n\t" + "stp x3, x4, [%[r]], #16\n\t" + "stp x5, x6, [%[r]], #16\n\t" + "cset %[c], cs\n\t" + "cmp %[a], x11\n\t" + "b.ne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into a. (a -= b) + * + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_3072_sub_in_place_24(sp_digit* a, const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "add x10, %[a], 192\n\t" + "\n1:\n\t" + "subs %[c], xzr, %[c]\n\t" + "ldp x2, x3, [%[a]]\n\t" + "ldp x4, x5, [%[a], #16]\n\t" + "ldp x6, x7, [%[b]], #16\n\t" + "ldp x8, x9, [%[b]], #16\n\t" + "sbcs x2, x2, x6\n\t" + "sbcs x3, x3, x7\n\t" + "sbcs x4, x4, x8\n\t" + "sbcs x5, x5, x9\n\t" + "stp x2, x3, [%[a]], #16\n\t" + "stp x4, x5, [%[a]], #16\n\t" + "csetm %[c], cc\n\t" + "cmp %[a], x10\n\t" + "b.ne 1b\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_3072_mul_24(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + sp_digit tmp[48]; + + __asm__ __volatile__ ( + "mov x5, 0\n\t" + "mov x6, 0\n\t" + "mov x7, 0\n\t" + "mov x8, 0\n\t" + "\n1:\n\t" + "subs x3, x5, 184\n\t" + "csel x3, xzr, x3, cc\n\t" + "sub x4, x5, x3\n\t" + "\n2:\n\t" + "ldr x10, [%[a], x3]\n\t" + "ldr x11, [%[b], x4]\n\t" + "mul x9, x10, x11\n\t" + "umulh x10, x10, x11\n\t" + "adds x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x8, x8, xzr\n\t" + "add x3, x3, #8\n\t" + "sub x4, x4, #8\n\t" + "cmp x3, 192\n\t" + "b.eq 3f\n\t" + "cmp x3, x5\n\t" + "b.le 2b\n\t" + "\n3:\n\t" + "str x6, [%[r], x5]\n\t" + "mov x6, x7\n\t" + "mov x7, x8\n\t" + "mov x8, #0\n\t" + "add x5, x5, #8\n\t" + "cmp x5, 368\n\t" + "b.le 1b\n\t" + "str x6, [%[r], x5]\n\t" + : + : [r] "r" (tmp), [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_3072_sqr_24(sp_digit* r, const sp_digit* a) +{ + sp_digit tmp[48]; + + __asm__ __volatile__ ( + "mov x6, 0\n\t" + "mov x7, 0\n\t" + "mov x8, 0\n\t" + "mov x5, 0\n\t" + "\n1:\n\t" + "subs x3, x5, 184\n\t" + "csel x3, xzr, x3, cc\n\t" + "sub x4, x5, x3\n\t" + "\n2:\n\t" + "cmp x4, x3\n\t" + "b.eq 4f\n\t" + "ldr x10, [%[a], x3]\n\t" + "ldr x11, [%[a], x4]\n\t" + "mul x9, x10, x11\n\t" + "umulh x10, x10, x11\n\t" + "adds x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x8, x8, xzr\n\t" + "adds x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x8, x8, xzr\n\t" + "b.al 5f\n\t" + "\n4:\n\t" + "ldr x10, [%[a], x3]\n\t" + "mul x9, x10, x10\n\t" + "umulh x10, x10, x10\n\t" + "adds x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x8, x8, xzr\n\t" + "\n5:\n\t" + "add x3, x3, #8\n\t" + "sub x4, x4, #8\n\t" + "cmp x3, 192\n\t" + "b.eq 3f\n\t" + "cmp x3, x4\n\t" + "b.gt 3f\n\t" + "cmp x3, x5\n\t" + "b.le 2b\n\t" + "\n3:\n\t" + "str x6, [%[r], x5]\n\t" + "mov x6, x7\n\t" + "mov x7, x8\n\t" + "mov x8, #0\n\t" + "add x5, x5, #8\n\t" + "cmp x5, 368\n\t" + "b.le 1b\n\t" + "str x6, [%[r], x5]\n\t" + : + : [r] "r" (tmp), [a] "r" (a) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +#endif /* WOLFSSL_SP_SMALL */ +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +/* Caclulate the bottom digit of -1/a mod 2^n. + * + * a A single precision number. + * rho Bottom word of inverse. + */ +static void sp_3072_mont_setup(sp_digit* a, sp_digit* rho) +{ + sp_digit x, b; + + b = a[0]; + x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ + x *= 2 - b * x; /* here x*a==1 mod 2**8 */ + x *= 2 - b * x; /* here x*a==1 mod 2**16 */ + x *= 2 - b * x; /* here x*a==1 mod 2**32 */ + x *= 2 - b * x; /* here x*a==1 mod 2**64 */ + + /* rho = -1/m mod b */ + *rho = -x; +} + +/* Mul a by digit b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision digit. + */ +static void sp_3072_mul_d_48(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "# A[0] * B\n\t" + "ldr x8, [%[a]]\n\t" + "mul x5, %[b], x8\n\t" + "umulh x3, %[b], x8\n\t" + "mov x4, 0\n\t" + "str x5, [%[r]]\n\t" + "mov x5, 0\n\t" + "mov x9, #8\n\t" + "1:\n\t" + "ldr x8, [%[a], x9]\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "str x3, [%[r], x9]\n\t" + "mov x3, x4\n\t" + "mov x4, x5\n\t" + "mov x5, #0\n\t" + "add x9, x9, #8\n\t" + "cmp x9, 384\n\t" + "b.lt 1b\n\t" + "str x3, [%[r], 384]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8" + ); +#else + __asm__ __volatile__ ( + "# A[0] * B\n\t" + "ldr x8, [%[a]]\n\t" + "mul x3, %[b], x8\n\t" + "umulh x4, %[b], x8\n\t" + "mov x5, 0\n\t" + "str x3, [%[r]]\n\t" + "# A[1] * B\n\t" + "ldr x8, [%[a], 8]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "str x4, [%[r], 8]\n\t" + "# A[2] * B\n\t" + "ldr x8, [%[a], 16]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, xzr, xzr\n\t" + "str x5, [%[r], 16]\n\t" + "# A[3] * B\n\t" + "ldr x8, [%[a], 24]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "str x3, [%[r], 24]\n\t" + "# A[4] * B\n\t" + "ldr x8, [%[a], 32]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "str x4, [%[r], 32]\n\t" + "# A[5] * B\n\t" + "ldr x8, [%[a], 40]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, xzr, xzr\n\t" + "str x5, [%[r], 40]\n\t" + "# A[6] * B\n\t" + "ldr x8, [%[a], 48]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "str x3, [%[r], 48]\n\t" + "# A[7] * B\n\t" + "ldr x8, [%[a], 56]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "str x4, [%[r], 56]\n\t" + "# A[8] * B\n\t" + "ldr x8, [%[a], 64]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, xzr, xzr\n\t" + "str x5, [%[r], 64]\n\t" + "# A[9] * B\n\t" + "ldr x8, [%[a], 72]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "str x3, [%[r], 72]\n\t" + "# A[10] * B\n\t" + "ldr x8, [%[a], 80]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "str x4, [%[r], 80]\n\t" + "# A[11] * B\n\t" + "ldr x8, [%[a], 88]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, xzr, xzr\n\t" + "str x5, [%[r], 88]\n\t" + "# A[12] * B\n\t" + "ldr x8, [%[a], 96]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "str x3, [%[r], 96]\n\t" + "# A[13] * B\n\t" + "ldr x8, [%[a], 104]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "str x4, [%[r], 104]\n\t" + "# A[14] * B\n\t" + "ldr x8, [%[a], 112]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, xzr, xzr\n\t" + "str x5, [%[r], 112]\n\t" + "# A[15] * B\n\t" + "ldr x8, [%[a], 120]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "str x3, [%[r], 120]\n\t" + "# A[16] * B\n\t" + "ldr x8, [%[a], 128]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "str x4, [%[r], 128]\n\t" + "# A[17] * B\n\t" + "ldr x8, [%[a], 136]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, xzr, xzr\n\t" + "str x5, [%[r], 136]\n\t" + "# A[18] * B\n\t" + "ldr x8, [%[a], 144]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "str x3, [%[r], 144]\n\t" + "# A[19] * B\n\t" + "ldr x8, [%[a], 152]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "str x4, [%[r], 152]\n\t" + "# A[20] * B\n\t" + "ldr x8, [%[a], 160]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, xzr, xzr\n\t" + "str x5, [%[r], 160]\n\t" + "# A[21] * B\n\t" + "ldr x8, [%[a], 168]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "str x3, [%[r], 168]\n\t" + "# A[22] * B\n\t" + "ldr x8, [%[a], 176]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "str x4, [%[r], 176]\n\t" + "# A[23] * B\n\t" + "ldr x8, [%[a], 184]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, xzr, xzr\n\t" + "str x5, [%[r], 184]\n\t" + "# A[24] * B\n\t" + "ldr x8, [%[a], 192]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "str x3, [%[r], 192]\n\t" + "# A[25] * B\n\t" + "ldr x8, [%[a], 200]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "str x4, [%[r], 200]\n\t" + "# A[26] * B\n\t" + "ldr x8, [%[a], 208]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, xzr, xzr\n\t" + "str x5, [%[r], 208]\n\t" + "# A[27] * B\n\t" + "ldr x8, [%[a], 216]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "str x3, [%[r], 216]\n\t" + "# A[28] * B\n\t" + "ldr x8, [%[a], 224]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "str x4, [%[r], 224]\n\t" + "# A[29] * B\n\t" + "ldr x8, [%[a], 232]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, xzr, xzr\n\t" + "str x5, [%[r], 232]\n\t" + "# A[30] * B\n\t" + "ldr x8, [%[a], 240]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "str x3, [%[r], 240]\n\t" + "# A[31] * B\n\t" + "ldr x8, [%[a], 248]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "str x4, [%[r], 248]\n\t" + "# A[32] * B\n\t" + "ldr x8, [%[a], 256]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, xzr, xzr\n\t" + "str x5, [%[r], 256]\n\t" + "# A[33] * B\n\t" + "ldr x8, [%[a], 264]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "str x3, [%[r], 264]\n\t" + "# A[34] * B\n\t" + "ldr x8, [%[a], 272]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "str x4, [%[r], 272]\n\t" + "# A[35] * B\n\t" + "ldr x8, [%[a], 280]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, xzr, xzr\n\t" + "str x5, [%[r], 280]\n\t" + "# A[36] * B\n\t" + "ldr x8, [%[a], 288]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "str x3, [%[r], 288]\n\t" + "# A[37] * B\n\t" + "ldr x8, [%[a], 296]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "str x4, [%[r], 296]\n\t" + "# A[38] * B\n\t" + "ldr x8, [%[a], 304]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, xzr, xzr\n\t" + "str x5, [%[r], 304]\n\t" + "# A[39] * B\n\t" + "ldr x8, [%[a], 312]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "str x3, [%[r], 312]\n\t" + "# A[40] * B\n\t" + "ldr x8, [%[a], 320]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "str x4, [%[r], 320]\n\t" + "# A[41] * B\n\t" + "ldr x8, [%[a], 328]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, xzr, xzr\n\t" + "str x5, [%[r], 328]\n\t" + "# A[42] * B\n\t" + "ldr x8, [%[a], 336]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "str x3, [%[r], 336]\n\t" + "# A[43] * B\n\t" + "ldr x8, [%[a], 344]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "str x4, [%[r], 344]\n\t" + "# A[44] * B\n\t" + "ldr x8, [%[a], 352]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, xzr, xzr\n\t" + "str x5, [%[r], 352]\n\t" + "# A[45] * B\n\t" + "ldr x8, [%[a], 360]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "str x3, [%[r], 360]\n\t" + "# A[46] * B\n\t" + "ldr x8, [%[a], 368]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "str x4, [%[r], 368]\n\t" + "# A[47] * B\n\t" + "ldr x8, [%[a], 376]\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x5, x5, x6\n\t" + "adc x3, x3, x7\n\t" + "str x5, [%[r], 376]\n\t" + "str x3, [%[r], 384]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8" + ); +#endif +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +/* r = 2^n mod m where n is the number of bits to reduce by. + * Given m must be 3072 bits, just need to subtract. + * + * r A single precision number. + * m A signle precision number. + */ +static void sp_3072_mont_norm_24(sp_digit* r, sp_digit* m) +{ + XMEMSET(r, 0, sizeof(sp_digit) * 24); + + /* r = 2^n mod m */ + sp_3072_sub_in_place_24(r, m); +} + +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not copying. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +static sp_digit sp_3072_cond_sub_24(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit m) +{ + sp_digit c = 0; + +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov x8, #0\n\t" + "1:\n\t" + "subs %[c], xzr, %[c]\n\t" + "ldr x4, [%[a], x8]\n\t" + "ldr x5, [%[b], x8]\n\t" + "and x5, x5, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "csetm %[c], cc\n\t" + "str x4, [%[r], x8]\n\t" + "add x8, x8, #8\n\t" + "cmp x8, 192\n\t" + "b.lt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "x4", "x6", "x5", "x7", "x8" + ); +#else + __asm__ __volatile__ ( + + "ldr x4, [%[a], 0]\n\t" + "ldr x6, [%[a], 8]\n\t" + "ldr x5, [%[b], 0]\n\t" + "ldr x7, [%[b], 8]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "subs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 0]\n\t" + "str x6, [%[r], 8]\n\t" + "ldr x4, [%[a], 16]\n\t" + "ldr x6, [%[a], 24]\n\t" + "ldr x5, [%[b], 16]\n\t" + "ldr x7, [%[b], 24]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 16]\n\t" + "str x6, [%[r], 24]\n\t" + "ldr x4, [%[a], 32]\n\t" + "ldr x6, [%[a], 40]\n\t" + "ldr x5, [%[b], 32]\n\t" + "ldr x7, [%[b], 40]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 32]\n\t" + "str x6, [%[r], 40]\n\t" + "ldr x4, [%[a], 48]\n\t" + "ldr x6, [%[a], 56]\n\t" + "ldr x5, [%[b], 48]\n\t" + "ldr x7, [%[b], 56]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 48]\n\t" + "str x6, [%[r], 56]\n\t" + "ldr x4, [%[a], 64]\n\t" + "ldr x6, [%[a], 72]\n\t" + "ldr x5, [%[b], 64]\n\t" + "ldr x7, [%[b], 72]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 64]\n\t" + "str x6, [%[r], 72]\n\t" + "ldr x4, [%[a], 80]\n\t" + "ldr x6, [%[a], 88]\n\t" + "ldr x5, [%[b], 80]\n\t" + "ldr x7, [%[b], 88]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 80]\n\t" + "str x6, [%[r], 88]\n\t" + "ldr x4, [%[a], 96]\n\t" + "ldr x6, [%[a], 104]\n\t" + "ldr x5, [%[b], 96]\n\t" + "ldr x7, [%[b], 104]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 96]\n\t" + "str x6, [%[r], 104]\n\t" + "ldr x4, [%[a], 112]\n\t" + "ldr x6, [%[a], 120]\n\t" + "ldr x5, [%[b], 112]\n\t" + "ldr x7, [%[b], 120]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 112]\n\t" + "str x6, [%[r], 120]\n\t" + "ldr x4, [%[a], 128]\n\t" + "ldr x6, [%[a], 136]\n\t" + "ldr x5, [%[b], 128]\n\t" + "ldr x7, [%[b], 136]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 128]\n\t" + "str x6, [%[r], 136]\n\t" + "ldr x4, [%[a], 144]\n\t" + "ldr x6, [%[a], 152]\n\t" + "ldr x5, [%[b], 144]\n\t" + "ldr x7, [%[b], 152]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 144]\n\t" + "str x6, [%[r], 152]\n\t" + "ldr x4, [%[a], 160]\n\t" + "ldr x6, [%[a], 168]\n\t" + "ldr x5, [%[b], 160]\n\t" + "ldr x7, [%[b], 168]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 160]\n\t" + "str x6, [%[r], 168]\n\t" + "ldr x4, [%[a], 176]\n\t" + "ldr x6, [%[a], 184]\n\t" + "ldr x5, [%[b], 176]\n\t" + "ldr x7, [%[b], 184]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 176]\n\t" + "str x6, [%[r], 184]\n\t" + "csetm %[c], cc\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "x4", "x6", "x5", "x7", "x8" + ); +#endif /* WOLFSSL_SP_SMALL */ + + return c; +} + +/* Reduce the number back to 3072 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +SP_NOINLINE static void sp_3072_mont_reduce_24(sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "ldp x12, x13, [%[m], 0]\n\t" + "ldp x14, x15, [%[m], 16]\n\t" + "ldp x16, x17, [%[m], 32]\n\t" + "ldp x18, x19, [%[m], 48]\n\t" + "ldp x20, x21, [%[m], 64]\n\t" + "ldp x22, x23, [%[m], 80]\n\t" + "ldp x24, x25, [%[m], 96]\n\t" + "ldp x26, x27, [%[m], 112]\n\t" + "# i = 0\n\t" + "mov x3, 0\n\t" + "ldp x10, x11, [%[a], 0]\n\t" + "\n1:\n\t" + "# mu = a[i] * mp\n\t" + "mul x8, %[mp], x10\n\t" + "# a[i+0] += m[0] * mu\n\t" + "ldr x9, [%[a], 0]\n\t" + "mul x6, x12, x8\n\t" + "umulh x7, x12, x8\n\t" + "adds x10, x10, x6\n\t" + "adc x5, x7, xzr\n\t" + "# a[i+1] += m[1] * mu\n\t" + "ldr x9, [%[a], 8]\n\t" + "mul x6, x13, x8\n\t" + "umulh x7, x13, x8\n\t" + "adds x10, x11, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x10, x10, x5\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+2] += m[2] * mu\n\t" + "ldr x11, [%[a], 16]\n\t" + "mul x6, x14, x8\n\t" + "umulh x7, x14, x8\n\t" + "adds x11, x11, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x11, x11, x4\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+3] += m[3] * mu\n\t" + "ldr x9, [%[a], 24]\n\t" + "mul x6, x15, x8\n\t" + "umulh x7, x15, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 24]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+4] += m[4] * mu\n\t" + "ldr x9, [%[a], 32]\n\t" + "mul x6, x16, x8\n\t" + "umulh x7, x16, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 32]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+5] += m[5] * mu\n\t" + "ldr x9, [%[a], 40]\n\t" + "mul x6, x17, x8\n\t" + "umulh x7, x17, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 40]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+6] += m[6] * mu\n\t" + "ldr x9, [%[a], 48]\n\t" + "mul x6, x18, x8\n\t" + "umulh x7, x18, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 48]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+7] += m[7] * mu\n\t" + "ldr x9, [%[a], 56]\n\t" + "mul x6, x19, x8\n\t" + "umulh x7, x19, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 56]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+8] += m[8] * mu\n\t" + "ldr x9, [%[a], 64]\n\t" + "mul x6, x20, x8\n\t" + "umulh x7, x20, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 64]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+9] += m[9] * mu\n\t" + "ldr x9, [%[a], 72]\n\t" + "mul x6, x21, x8\n\t" + "umulh x7, x21, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 72]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+10] += m[10] * mu\n\t" + "ldr x9, [%[a], 80]\n\t" + "mul x6, x22, x8\n\t" + "umulh x7, x22, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 80]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+11] += m[11] * mu\n\t" + "ldr x9, [%[a], 88]\n\t" + "mul x6, x23, x8\n\t" + "umulh x7, x23, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 88]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+12] += m[12] * mu\n\t" + "ldr x9, [%[a], 96]\n\t" + "mul x6, x24, x8\n\t" + "umulh x7, x24, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 96]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+13] += m[13] * mu\n\t" + "ldr x9, [%[a], 104]\n\t" + "mul x6, x25, x8\n\t" + "umulh x7, x25, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 104]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+14] += m[14] * mu\n\t" + "ldr x9, [%[a], 112]\n\t" + "mul x6, x26, x8\n\t" + "umulh x7, x26, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 112]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+15] += m[15] * mu\n\t" + "ldr x9, [%[a], 120]\n\t" + "mul x6, x27, x8\n\t" + "umulh x7, x27, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 120]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+16] += m[16] * mu\n\t" + "ldr x7, [%[m], 128]\n\t" + "ldr x9, [%[a], 128]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 128]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+17] += m[17] * mu\n\t" + "ldr x7, [%[m], 136]\n\t" + "ldr x9, [%[a], 136]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 136]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+18] += m[18] * mu\n\t" + "ldr x7, [%[m], 144]\n\t" + "ldr x9, [%[a], 144]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 144]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+19] += m[19] * mu\n\t" + "ldr x7, [%[m], 152]\n\t" + "ldr x9, [%[a], 152]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 152]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+20] += m[20] * mu\n\t" + "ldr x7, [%[m], 160]\n\t" + "ldr x9, [%[a], 160]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 160]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+21] += m[21] * mu\n\t" + "ldr x7, [%[m], 168]\n\t" + "ldr x9, [%[a], 168]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 168]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+22] += m[22] * mu\n\t" + "ldr x7, [%[m], 176]\n\t" + "ldr x9, [%[a], 176]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 176]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+23] += m[23] * mu\n\t" + "ldr x7, [%[m], 184]\n\t" + "ldr x9, [%[a], 184]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x7, x7, %[ca]\n\t" + "cset %[ca], cs\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 184]\n\t" + "ldr x9, [%[a], 192]\n\t" + "adcs x9, x9, x7\n\t" + "str x9, [%[a], 192]\n\t" + "adc %[ca], %[ca], xzr\n\t" + "# i += 1\n\t" + "add %[a], %[a], 8\n\t" + "add x3, x3, 8\n\t" + "cmp x3, 192\n\t" + "blt 1b\n\t" + "str x10, [%[a], 0]\n\t" + "str x11, [%[a], 8]\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27" + ); + + sp_3072_cond_sub_24(a - 24, a, m, (sp_digit)0 - ca); +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_3072_mont_mul_24(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_3072_mul_24(r, a, b); + sp_3072_mont_reduce_24(r, m, mp); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_3072_mont_sqr_24(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_3072_sqr_24(r, a); + sp_3072_mont_reduce_24(r, m, mp); +} + +/* Mul a by digit b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision digit. + */ +static void sp_3072_mul_d_24(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "# A[0] * B\n\t" + "ldr x8, [%[a]]\n\t" + "mul x5, %[b], x8\n\t" + "umulh x3, %[b], x8\n\t" + "mov x4, 0\n\t" + "str x5, [%[r]]\n\t" + "mov x5, 0\n\t" + "mov x9, #8\n\t" + "1:\n\t" + "ldr x8, [%[a], x9]\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "str x3, [%[r], x9]\n\t" + "mov x3, x4\n\t" + "mov x4, x5\n\t" + "mov x5, #0\n\t" + "add x9, x9, #8\n\t" + "cmp x9, 192\n\t" + "b.lt 1b\n\t" + "str x3, [%[r], 192]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8" + ); +#else + __asm__ __volatile__ ( + "# A[0] * B\n\t" + "ldr x8, [%[a]]\n\t" + "mul x3, %[b], x8\n\t" + "umulh x4, %[b], x8\n\t" + "mov x5, 0\n\t" + "str x3, [%[r]]\n\t" + "# A[1] * B\n\t" + "ldr x8, [%[a], 8]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "str x4, [%[r], 8]\n\t" + "# A[2] * B\n\t" + "ldr x8, [%[a], 16]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, xzr, xzr\n\t" + "str x5, [%[r], 16]\n\t" + "# A[3] * B\n\t" + "ldr x8, [%[a], 24]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "str x3, [%[r], 24]\n\t" + "# A[4] * B\n\t" + "ldr x8, [%[a], 32]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "str x4, [%[r], 32]\n\t" + "# A[5] * B\n\t" + "ldr x8, [%[a], 40]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, xzr, xzr\n\t" + "str x5, [%[r], 40]\n\t" + "# A[6] * B\n\t" + "ldr x8, [%[a], 48]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "str x3, [%[r], 48]\n\t" + "# A[7] * B\n\t" + "ldr x8, [%[a], 56]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "str x4, [%[r], 56]\n\t" + "# A[8] * B\n\t" + "ldr x8, [%[a], 64]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, xzr, xzr\n\t" + "str x5, [%[r], 64]\n\t" + "# A[9] * B\n\t" + "ldr x8, [%[a], 72]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "str x3, [%[r], 72]\n\t" + "# A[10] * B\n\t" + "ldr x8, [%[a], 80]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "str x4, [%[r], 80]\n\t" + "# A[11] * B\n\t" + "ldr x8, [%[a], 88]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, xzr, xzr\n\t" + "str x5, [%[r], 88]\n\t" + "# A[12] * B\n\t" + "ldr x8, [%[a], 96]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "str x3, [%[r], 96]\n\t" + "# A[13] * B\n\t" + "ldr x8, [%[a], 104]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "str x4, [%[r], 104]\n\t" + "# A[14] * B\n\t" + "ldr x8, [%[a], 112]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, xzr, xzr\n\t" + "str x5, [%[r], 112]\n\t" + "# A[15] * B\n\t" + "ldr x8, [%[a], 120]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "str x3, [%[r], 120]\n\t" + "# A[16] * B\n\t" + "ldr x8, [%[a], 128]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "str x4, [%[r], 128]\n\t" + "# A[17] * B\n\t" + "ldr x8, [%[a], 136]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, xzr, xzr\n\t" + "str x5, [%[r], 136]\n\t" + "# A[18] * B\n\t" + "ldr x8, [%[a], 144]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "str x3, [%[r], 144]\n\t" + "# A[19] * B\n\t" + "ldr x8, [%[a], 152]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "str x4, [%[r], 152]\n\t" + "# A[20] * B\n\t" + "ldr x8, [%[a], 160]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, xzr, xzr\n\t" + "str x5, [%[r], 160]\n\t" + "# A[21] * B\n\t" + "ldr x8, [%[a], 168]\n\t" + "mov x5, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "str x3, [%[r], 168]\n\t" + "# A[22] * B\n\t" + "ldr x8, [%[a], 176]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "str x4, [%[r], 176]\n\t" + "# A[23] * B\n\t" + "ldr x8, [%[a], 184]\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x5, x5, x6\n\t" + "adc x3, x3, x7\n\t" + "str x5, [%[r], 184]\n\t" + "str x3, [%[r], 192]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8" + ); +#endif +} + +/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) + * + * d1 The high order half of the number to divide. + * d0 The low order half of the number to divide. + * div The dividend. + * returns the result of the division. + */ +static sp_digit div_3072_word_24(sp_digit d1, sp_digit d0, sp_digit div) +{ + sp_digit r; + + __asm__ __volatile__ ( + "lsr x5, %[div], 32\n\t" + "add x5, x5, 1\n\t" + + "udiv x3, %[d1], x5\n\t" + "lsl x6, x3, 32\n\t" + "mul x4, %[div], x6\n\t" + "umulh x3, %[div], x6\n\t" + "subs %[d0], %[d0], x4\n\t" + "sbc %[d1], %[d1], x3\n\t" + + "udiv x3, %[d1], x5\n\t" + "lsl x3, x3, 32\n\t" + "add x6, x6, x3\n\t" + "mul x4, %[div], x3\n\t" + "umulh x3, %[div], x3\n\t" + "subs %[d0], %[d0], x4\n\t" + "sbc %[d1], %[d1], x3\n\t" + + "lsl x3, %[d1], 32\n\t" + "orr x3, x3, %[d0], lsr 32\n\t" + + "udiv x3, x3, x5\n\t" + "add x6, x6, x3\n\t" + "mul x4, %[div], x3\n\t" + "umulh x3, %[div], x3\n\t" + "subs %[d0], %[d0], x4\n\t" + "sbc %[d1], %[d1], x3\n\t" + + "lsl x3, %[d1], 32\n\t" + "orr x3, x3, %[d0], lsr 32\n\t" + + "udiv x3, x3, x5\n\t" + "add x6, x6, x3\n\t" + "mul x4, %[div], x3\n\t" + "umulh x3, %[div], x3\n\t" + "subs %[d0], %[d0], x4\n\t" + "sbc %[d1], %[d1], x3\n\t" + + "udiv x3, %[d0], %[div]\n\t" + "add x6, x6, x3\n\t" + "mul x3, %[div], x3\n\t" + "sub %[d0], %[d0], x3\n\t" + "mov %[r], x6\n\t" + + : [r] "=r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "x3", "x4", "x5", "x6" + ); + + return r; +} + +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +static int64_t sp_3072_cmp_24(sp_digit* a, sp_digit* b) +{ + sp_digit r = -1; + sp_digit one = 1; + +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov x3, -1\n\t" + "mov x6, 184\n\t" + "1:\n\t" + "ldr x4, [%[a], x6]\n\t" + "ldr x5, [%[b], x6]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "sub x6, x6, #8\n\t" + "b.cc 1b\n\t" + "eor %[r], %[r], x3\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [one] "r" (one) + : "x2", "x3", "x4", "x5", "x6" + ); +#else + __asm__ __volatile__ ( + "mov x3, -1\n\t" + "ldr x4, [%[a], 184]\n\t" + "ldr x5, [%[b], 184]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 176]\n\t" + "ldr x5, [%[b], 176]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 168]\n\t" + "ldr x5, [%[b], 168]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 160]\n\t" + "ldr x5, [%[b], 160]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 152]\n\t" + "ldr x5, [%[b], 152]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 144]\n\t" + "ldr x5, [%[b], 144]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 136]\n\t" + "ldr x5, [%[b], 136]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 128]\n\t" + "ldr x5, [%[b], 128]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 120]\n\t" + "ldr x5, [%[b], 120]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 112]\n\t" + "ldr x5, [%[b], 112]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 104]\n\t" + "ldr x5, [%[b], 104]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 96]\n\t" + "ldr x5, [%[b], 96]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 88]\n\t" + "ldr x5, [%[b], 88]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 80]\n\t" + "ldr x5, [%[b], 80]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 72]\n\t" + "ldr x5, [%[b], 72]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 64]\n\t" + "ldr x5, [%[b], 64]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 56]\n\t" + "ldr x5, [%[b], 56]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 48]\n\t" + "ldr x5, [%[b], 48]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 40]\n\t" + "ldr x5, [%[b], 40]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 32]\n\t" + "ldr x5, [%[b], 32]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 24]\n\t" + "ldr x5, [%[b], 24]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 16]\n\t" + "ldr x5, [%[b], 16]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 8]\n\t" + "ldr x5, [%[b], 8]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 0]\n\t" + "ldr x5, [%[b], 0]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "eor %[r], %[r], x3\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [one] "r" (one) + : "x2", "x3", "x4", "x5", "x6" + ); +#endif + + return r; +} + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_3072_div_24(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[48], t2[25]; + sp_digit div, r1; + int i; + + (void)m; + + div = d[23]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 24); + for (i=23; i>=0; i--) { + r1 = div_3072_word_24(t1[24 + i], t1[24 + i - 1], div); + + sp_3072_mul_d_24(t2, d, r1); + t1[24 + i] += sp_3072_sub_in_place_24(&t1[i], t2); + t1[24 + i] -= t2[24]; + sp_3072_mask_24(t2, d, t1[24 + i]); + t1[24 + i] += sp_3072_add_24(&t1[i], &t1[i], t2); + sp_3072_mask_24(t2, d, t1[24 + i]); + t1[24 + i] += sp_3072_add_24(&t1[i], &t1[i], t2); + } + + r1 = sp_3072_cmp_24(t1, d) >= 0; + sp_3072_cond_sub_24(r, t1, d, (sp_digit)0 - r1); + + return MP_OKAY; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_3072_mod_24(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_3072_div_24(a, m, NULL, r); +} + +#ifdef WOLFSSL_SP_SMALL +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_3072_mod_exp_24(sp_digit* r, sp_digit* a, sp_digit* e, + int bits, sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[16][48]; +#else + sp_digit* t[16]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 48, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<16; i++) + t[i] = td + i * 48; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_24(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 24); + if (reduceA) { + err = sp_3072_mod_24(t[1] + 24, a, m); + if (err == MP_OKAY) + err = sp_3072_mod_24(t[1], t[1], m); + } + else { + XMEMCPY(t[1] + 24, a, sizeof(sp_digit) * 24); + err = sp_3072_mod_24(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_3072_mont_sqr_24(t[ 2], t[ 1], m, mp); + sp_3072_mont_mul_24(t[ 3], t[ 2], t[ 1], m, mp); + sp_3072_mont_sqr_24(t[ 4], t[ 2], m, mp); + sp_3072_mont_mul_24(t[ 5], t[ 3], t[ 2], m, mp); + sp_3072_mont_sqr_24(t[ 6], t[ 3], m, mp); + sp_3072_mont_mul_24(t[ 7], t[ 4], t[ 3], m, mp); + sp_3072_mont_sqr_24(t[ 8], t[ 4], m, mp); + sp_3072_mont_mul_24(t[ 9], t[ 5], t[ 4], m, mp); + sp_3072_mont_sqr_24(t[10], t[ 5], m, mp); + sp_3072_mont_mul_24(t[11], t[ 6], t[ 5], m, mp); + sp_3072_mont_sqr_24(t[12], t[ 6], m, mp); + sp_3072_mont_mul_24(t[13], t[ 7], t[ 6], m, mp); + sp_3072_mont_sqr_24(t[14], t[ 7], m, mp); + sp_3072_mont_mul_24(t[15], t[ 8], t[ 7], m, mp); + + i = (bits - 1) / 64; + n = e[i--]; + y = n >> 60; + n <<= 4; + c = 60; + XMEMCPY(r, t[y], sizeof(sp_digit) * 24); + for (; i>=0 || c>=4; ) { + if (c == 0) { + n = e[i--]; + y = n >> 60; + n <<= 4; + c = 60; + } + else if (c < 4) { + y = n >> 60; + n = e[i--]; + c = 4 - c; + y |= n >> (64 - c); + n <<= c; + c = 64 - c; + } + else { + y = (n >> 60) & 0xf; + n <<= 4; + c -= 4; + } + + sp_3072_mont_sqr_24(r, r, m, mp); + sp_3072_mont_sqr_24(r, r, m, mp); + sp_3072_mont_sqr_24(r, r, m, mp); + sp_3072_mont_sqr_24(r, r, m, mp); + + sp_3072_mont_mul_24(r, r, t[y], m, mp); + } + y = e[0] & ((1 << c) - 1); + for (; c > 0; c--) + sp_3072_mont_sqr_24(r, r, m, mp); + sp_3072_mont_mul_24(r, r, t[y], m, mp); + + XMEMSET(&r[24], 0, sizeof(sp_digit) * 24); + sp_3072_mont_reduce_24(r, m, mp); + + mask = 0 - (sp_3072_cmp_24(r, m) >= 0); + sp_3072_cond_sub_24(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#else +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_3072_mod_exp_24(sp_digit* r, sp_digit* a, sp_digit* e, + int bits, sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][48]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 48, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<32; i++) + t[i] = td + i * 48; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_24(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 24); + if (reduceA) { + err = sp_3072_mod_24(t[1] + 24, a, m); + if (err == MP_OKAY) + err = sp_3072_mod_24(t[1], t[1], m); + } + else { + XMEMCPY(t[1] + 24, a, sizeof(sp_digit) * 24); + err = sp_3072_mod_24(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_3072_mont_sqr_24(t[ 2], t[ 1], m, mp); + sp_3072_mont_mul_24(t[ 3], t[ 2], t[ 1], m, mp); + sp_3072_mont_sqr_24(t[ 4], t[ 2], m, mp); + sp_3072_mont_mul_24(t[ 5], t[ 3], t[ 2], m, mp); + sp_3072_mont_sqr_24(t[ 6], t[ 3], m, mp); + sp_3072_mont_mul_24(t[ 7], t[ 4], t[ 3], m, mp); + sp_3072_mont_sqr_24(t[ 8], t[ 4], m, mp); + sp_3072_mont_mul_24(t[ 9], t[ 5], t[ 4], m, mp); + sp_3072_mont_sqr_24(t[10], t[ 5], m, mp); + sp_3072_mont_mul_24(t[11], t[ 6], t[ 5], m, mp); + sp_3072_mont_sqr_24(t[12], t[ 6], m, mp); + sp_3072_mont_mul_24(t[13], t[ 7], t[ 6], m, mp); + sp_3072_mont_sqr_24(t[14], t[ 7], m, mp); + sp_3072_mont_mul_24(t[15], t[ 8], t[ 7], m, mp); + sp_3072_mont_sqr_24(t[16], t[ 8], m, mp); + sp_3072_mont_mul_24(t[17], t[ 9], t[ 8], m, mp); + sp_3072_mont_sqr_24(t[18], t[ 9], m, mp); + sp_3072_mont_mul_24(t[19], t[10], t[ 9], m, mp); + sp_3072_mont_sqr_24(t[20], t[10], m, mp); + sp_3072_mont_mul_24(t[21], t[11], t[10], m, mp); + sp_3072_mont_sqr_24(t[22], t[11], m, mp); + sp_3072_mont_mul_24(t[23], t[12], t[11], m, mp); + sp_3072_mont_sqr_24(t[24], t[12], m, mp); + sp_3072_mont_mul_24(t[25], t[13], t[12], m, mp); + sp_3072_mont_sqr_24(t[26], t[13], m, mp); + sp_3072_mont_mul_24(t[27], t[14], t[13], m, mp); + sp_3072_mont_sqr_24(t[28], t[14], m, mp); + sp_3072_mont_mul_24(t[29], t[15], t[14], m, mp); + sp_3072_mont_sqr_24(t[30], t[15], m, mp); + sp_3072_mont_mul_24(t[31], t[16], t[15], m, mp); + + i = (bits - 1) / 64; + n = e[i--]; + y = n >> 59; + n <<= 5; + c = 59; + XMEMCPY(r, t[y], sizeof(sp_digit) * 24); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 59; + n <<= 5; + c = 59; + } + else if (c < 5) { + y = n >> 59; + n = e[i--]; + c = 5 - c; + y |= n >> (64 - c); + n <<= c; + c = 64 - c; + } + else { + y = (n >> 59) & 0x1f; + n <<= 5; + c -= 5; + } + + sp_3072_mont_sqr_24(r, r, m, mp); + sp_3072_mont_sqr_24(r, r, m, mp); + sp_3072_mont_sqr_24(r, r, m, mp); + sp_3072_mont_sqr_24(r, r, m, mp); + sp_3072_mont_sqr_24(r, r, m, mp); + + sp_3072_mont_mul_24(r, r, t[y], m, mp); + } + y = e[0] & ((1 << c) - 1); + for (; c > 0; c--) + sp_3072_mont_sqr_24(r, r, m, mp); + sp_3072_mont_mul_24(r, r, t[y], m, mp); + + XMEMSET(&r[24], 0, sizeof(sp_digit) * 24); + sp_3072_mont_reduce_24(r, m, mp); + + mask = 0 - (sp_3072_cmp_24(r, m) >= 0); + sp_3072_cond_sub_24(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#endif /* WOLFSSL_SP_SMALL */ + +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) +/* r = 2^n mod m where n is the number of bits to reduce by. + * Given m must be 3072 bits, just need to subtract. + * + * r A single precision number. + * m A signle precision number. + */ +static void sp_3072_mont_norm_48(sp_digit* r, sp_digit* m) +{ + XMEMSET(r, 0, sizeof(sp_digit) * 48); + + /* r = 2^n mod m */ + sp_3072_sub_in_place_48(r, m); +} + +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not copying. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +static sp_digit sp_3072_cond_sub_48(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit m) +{ + sp_digit c = 0; + +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov x8, #0\n\t" + "1:\n\t" + "subs %[c], xzr, %[c]\n\t" + "ldr x4, [%[a], x8]\n\t" + "ldr x5, [%[b], x8]\n\t" + "and x5, x5, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "csetm %[c], cc\n\t" + "str x4, [%[r], x8]\n\t" + "add x8, x8, #8\n\t" + "cmp x8, 384\n\t" + "b.lt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "x4", "x6", "x5", "x7", "x8" + ); +#else + __asm__ __volatile__ ( + + "ldr x4, [%[a], 0]\n\t" + "ldr x6, [%[a], 8]\n\t" + "ldr x5, [%[b], 0]\n\t" + "ldr x7, [%[b], 8]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "subs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 0]\n\t" + "str x6, [%[r], 8]\n\t" + "ldr x4, [%[a], 16]\n\t" + "ldr x6, [%[a], 24]\n\t" + "ldr x5, [%[b], 16]\n\t" + "ldr x7, [%[b], 24]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 16]\n\t" + "str x6, [%[r], 24]\n\t" + "ldr x4, [%[a], 32]\n\t" + "ldr x6, [%[a], 40]\n\t" + "ldr x5, [%[b], 32]\n\t" + "ldr x7, [%[b], 40]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 32]\n\t" + "str x6, [%[r], 40]\n\t" + "ldr x4, [%[a], 48]\n\t" + "ldr x6, [%[a], 56]\n\t" + "ldr x5, [%[b], 48]\n\t" + "ldr x7, [%[b], 56]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 48]\n\t" + "str x6, [%[r], 56]\n\t" + "ldr x4, [%[a], 64]\n\t" + "ldr x6, [%[a], 72]\n\t" + "ldr x5, [%[b], 64]\n\t" + "ldr x7, [%[b], 72]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 64]\n\t" + "str x6, [%[r], 72]\n\t" + "ldr x4, [%[a], 80]\n\t" + "ldr x6, [%[a], 88]\n\t" + "ldr x5, [%[b], 80]\n\t" + "ldr x7, [%[b], 88]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 80]\n\t" + "str x6, [%[r], 88]\n\t" + "ldr x4, [%[a], 96]\n\t" + "ldr x6, [%[a], 104]\n\t" + "ldr x5, [%[b], 96]\n\t" + "ldr x7, [%[b], 104]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 96]\n\t" + "str x6, [%[r], 104]\n\t" + "ldr x4, [%[a], 112]\n\t" + "ldr x6, [%[a], 120]\n\t" + "ldr x5, [%[b], 112]\n\t" + "ldr x7, [%[b], 120]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 112]\n\t" + "str x6, [%[r], 120]\n\t" + "ldr x4, [%[a], 128]\n\t" + "ldr x6, [%[a], 136]\n\t" + "ldr x5, [%[b], 128]\n\t" + "ldr x7, [%[b], 136]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 128]\n\t" + "str x6, [%[r], 136]\n\t" + "ldr x4, [%[a], 144]\n\t" + "ldr x6, [%[a], 152]\n\t" + "ldr x5, [%[b], 144]\n\t" + "ldr x7, [%[b], 152]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 144]\n\t" + "str x6, [%[r], 152]\n\t" + "ldr x4, [%[a], 160]\n\t" + "ldr x6, [%[a], 168]\n\t" + "ldr x5, [%[b], 160]\n\t" + "ldr x7, [%[b], 168]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 160]\n\t" + "str x6, [%[r], 168]\n\t" + "ldr x4, [%[a], 176]\n\t" + "ldr x6, [%[a], 184]\n\t" + "ldr x5, [%[b], 176]\n\t" + "ldr x7, [%[b], 184]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 176]\n\t" + "str x6, [%[r], 184]\n\t" + "ldr x4, [%[a], 192]\n\t" + "ldr x6, [%[a], 200]\n\t" + "ldr x5, [%[b], 192]\n\t" + "ldr x7, [%[b], 200]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 192]\n\t" + "str x6, [%[r], 200]\n\t" + "ldr x4, [%[a], 208]\n\t" + "ldr x6, [%[a], 216]\n\t" + "ldr x5, [%[b], 208]\n\t" + "ldr x7, [%[b], 216]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 208]\n\t" + "str x6, [%[r], 216]\n\t" + "ldr x4, [%[a], 224]\n\t" + "ldr x6, [%[a], 232]\n\t" + "ldr x5, [%[b], 224]\n\t" + "ldr x7, [%[b], 232]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 224]\n\t" + "str x6, [%[r], 232]\n\t" + "ldr x4, [%[a], 240]\n\t" + "ldr x6, [%[a], 248]\n\t" + "ldr x5, [%[b], 240]\n\t" + "ldr x7, [%[b], 248]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 240]\n\t" + "str x6, [%[r], 248]\n\t" + "ldr x4, [%[a], 256]\n\t" + "ldr x6, [%[a], 264]\n\t" + "ldr x5, [%[b], 256]\n\t" + "ldr x7, [%[b], 264]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 256]\n\t" + "str x6, [%[r], 264]\n\t" + "ldr x4, [%[a], 272]\n\t" + "ldr x6, [%[a], 280]\n\t" + "ldr x5, [%[b], 272]\n\t" + "ldr x7, [%[b], 280]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 272]\n\t" + "str x6, [%[r], 280]\n\t" + "ldr x4, [%[a], 288]\n\t" + "ldr x6, [%[a], 296]\n\t" + "ldr x5, [%[b], 288]\n\t" + "ldr x7, [%[b], 296]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 288]\n\t" + "str x6, [%[r], 296]\n\t" + "ldr x4, [%[a], 304]\n\t" + "ldr x6, [%[a], 312]\n\t" + "ldr x5, [%[b], 304]\n\t" + "ldr x7, [%[b], 312]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 304]\n\t" + "str x6, [%[r], 312]\n\t" + "ldr x4, [%[a], 320]\n\t" + "ldr x6, [%[a], 328]\n\t" + "ldr x5, [%[b], 320]\n\t" + "ldr x7, [%[b], 328]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 320]\n\t" + "str x6, [%[r], 328]\n\t" + "ldr x4, [%[a], 336]\n\t" + "ldr x6, [%[a], 344]\n\t" + "ldr x5, [%[b], 336]\n\t" + "ldr x7, [%[b], 344]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 336]\n\t" + "str x6, [%[r], 344]\n\t" + "ldr x4, [%[a], 352]\n\t" + "ldr x6, [%[a], 360]\n\t" + "ldr x5, [%[b], 352]\n\t" + "ldr x7, [%[b], 360]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 352]\n\t" + "str x6, [%[r], 360]\n\t" + "ldr x4, [%[a], 368]\n\t" + "ldr x6, [%[a], 376]\n\t" + "ldr x5, [%[b], 368]\n\t" + "ldr x7, [%[b], 376]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 368]\n\t" + "str x6, [%[r], 376]\n\t" + "csetm %[c], cc\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "x4", "x6", "x5", "x7", "x8" + ); +#endif /* WOLFSSL_SP_SMALL */ + + return c; +} + +/* Reduce the number back to 3072 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "ldp x12, x13, [%[m], 0]\n\t" + "ldp x14, x15, [%[m], 16]\n\t" + "ldp x16, x17, [%[m], 32]\n\t" + "ldp x18, x19, [%[m], 48]\n\t" + "ldp x20, x21, [%[m], 64]\n\t" + "ldp x22, x23, [%[m], 80]\n\t" + "ldp x24, x25, [%[m], 96]\n\t" + "ldp x26, x27, [%[m], 112]\n\t" + "# i = 0\n\t" + "mov x3, 0\n\t" + "ldp x10, x11, [%[a], 0]\n\t" + "\n1:\n\t" + "# mu = a[i] * mp\n\t" + "mul x8, %[mp], x10\n\t" + "# a[i+0] += m[0] * mu\n\t" + "ldr x9, [%[a], 0]\n\t" + "mul x6, x12, x8\n\t" + "umulh x7, x12, x8\n\t" + "adds x10, x10, x6\n\t" + "adc x5, x7, xzr\n\t" + "# a[i+1] += m[1] * mu\n\t" + "ldr x9, [%[a], 8]\n\t" + "mul x6, x13, x8\n\t" + "umulh x7, x13, x8\n\t" + "adds x10, x11, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x10, x10, x5\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+2] += m[2] * mu\n\t" + "ldr x11, [%[a], 16]\n\t" + "mul x6, x14, x8\n\t" + "umulh x7, x14, x8\n\t" + "adds x11, x11, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x11, x11, x4\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+3] += m[3] * mu\n\t" + "ldr x9, [%[a], 24]\n\t" + "mul x6, x15, x8\n\t" + "umulh x7, x15, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 24]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+4] += m[4] * mu\n\t" + "ldr x9, [%[a], 32]\n\t" + "mul x6, x16, x8\n\t" + "umulh x7, x16, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 32]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+5] += m[5] * mu\n\t" + "ldr x9, [%[a], 40]\n\t" + "mul x6, x17, x8\n\t" + "umulh x7, x17, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 40]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+6] += m[6] * mu\n\t" + "ldr x9, [%[a], 48]\n\t" + "mul x6, x18, x8\n\t" + "umulh x7, x18, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 48]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+7] += m[7] * mu\n\t" + "ldr x9, [%[a], 56]\n\t" + "mul x6, x19, x8\n\t" + "umulh x7, x19, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 56]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+8] += m[8] * mu\n\t" + "ldr x9, [%[a], 64]\n\t" + "mul x6, x20, x8\n\t" + "umulh x7, x20, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 64]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+9] += m[9] * mu\n\t" + "ldr x9, [%[a], 72]\n\t" + "mul x6, x21, x8\n\t" + "umulh x7, x21, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 72]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+10] += m[10] * mu\n\t" + "ldr x9, [%[a], 80]\n\t" + "mul x6, x22, x8\n\t" + "umulh x7, x22, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 80]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+11] += m[11] * mu\n\t" + "ldr x9, [%[a], 88]\n\t" + "mul x6, x23, x8\n\t" + "umulh x7, x23, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 88]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+12] += m[12] * mu\n\t" + "ldr x9, [%[a], 96]\n\t" + "mul x6, x24, x8\n\t" + "umulh x7, x24, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 96]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+13] += m[13] * mu\n\t" + "ldr x9, [%[a], 104]\n\t" + "mul x6, x25, x8\n\t" + "umulh x7, x25, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 104]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+14] += m[14] * mu\n\t" + "ldr x9, [%[a], 112]\n\t" + "mul x6, x26, x8\n\t" + "umulh x7, x26, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 112]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+15] += m[15] * mu\n\t" + "ldr x9, [%[a], 120]\n\t" + "mul x6, x27, x8\n\t" + "umulh x7, x27, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 120]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+16] += m[16] * mu\n\t" + "ldr x7, [%[m], 128]\n\t" + "ldr x9, [%[a], 128]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 128]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+17] += m[17] * mu\n\t" + "ldr x7, [%[m], 136]\n\t" + "ldr x9, [%[a], 136]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 136]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+18] += m[18] * mu\n\t" + "ldr x7, [%[m], 144]\n\t" + "ldr x9, [%[a], 144]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 144]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+19] += m[19] * mu\n\t" + "ldr x7, [%[m], 152]\n\t" + "ldr x9, [%[a], 152]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 152]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+20] += m[20] * mu\n\t" + "ldr x7, [%[m], 160]\n\t" + "ldr x9, [%[a], 160]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 160]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+21] += m[21] * mu\n\t" + "ldr x7, [%[m], 168]\n\t" + "ldr x9, [%[a], 168]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 168]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+22] += m[22] * mu\n\t" + "ldr x7, [%[m], 176]\n\t" + "ldr x9, [%[a], 176]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 176]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+23] += m[23] * mu\n\t" + "ldr x7, [%[m], 184]\n\t" + "ldr x9, [%[a], 184]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 184]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+24] += m[24] * mu\n\t" + "ldr x7, [%[m], 192]\n\t" + "ldr x9, [%[a], 192]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 192]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+25] += m[25] * mu\n\t" + "ldr x7, [%[m], 200]\n\t" + "ldr x9, [%[a], 200]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 200]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+26] += m[26] * mu\n\t" + "ldr x7, [%[m], 208]\n\t" + "ldr x9, [%[a], 208]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 208]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+27] += m[27] * mu\n\t" + "ldr x7, [%[m], 216]\n\t" + "ldr x9, [%[a], 216]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 216]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+28] += m[28] * mu\n\t" + "ldr x7, [%[m], 224]\n\t" + "ldr x9, [%[a], 224]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 224]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+29] += m[29] * mu\n\t" + "ldr x7, [%[m], 232]\n\t" + "ldr x9, [%[a], 232]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 232]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+30] += m[30] * mu\n\t" + "ldr x7, [%[m], 240]\n\t" + "ldr x9, [%[a], 240]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 240]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+31] += m[31] * mu\n\t" + "ldr x7, [%[m], 248]\n\t" + "ldr x9, [%[a], 248]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 248]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+32] += m[32] * mu\n\t" + "ldr x7, [%[m], 256]\n\t" + "ldr x9, [%[a], 256]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 256]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+33] += m[33] * mu\n\t" + "ldr x7, [%[m], 264]\n\t" + "ldr x9, [%[a], 264]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 264]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+34] += m[34] * mu\n\t" + "ldr x7, [%[m], 272]\n\t" + "ldr x9, [%[a], 272]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 272]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+35] += m[35] * mu\n\t" + "ldr x7, [%[m], 280]\n\t" + "ldr x9, [%[a], 280]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 280]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+36] += m[36] * mu\n\t" + "ldr x7, [%[m], 288]\n\t" + "ldr x9, [%[a], 288]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 288]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+37] += m[37] * mu\n\t" + "ldr x7, [%[m], 296]\n\t" + "ldr x9, [%[a], 296]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 296]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+38] += m[38] * mu\n\t" + "ldr x7, [%[m], 304]\n\t" + "ldr x9, [%[a], 304]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 304]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+39] += m[39] * mu\n\t" + "ldr x7, [%[m], 312]\n\t" + "ldr x9, [%[a], 312]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 312]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+40] += m[40] * mu\n\t" + "ldr x7, [%[m], 320]\n\t" + "ldr x9, [%[a], 320]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 320]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+41] += m[41] * mu\n\t" + "ldr x7, [%[m], 328]\n\t" + "ldr x9, [%[a], 328]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 328]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+42] += m[42] * mu\n\t" + "ldr x7, [%[m], 336]\n\t" + "ldr x9, [%[a], 336]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 336]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+43] += m[43] * mu\n\t" + "ldr x7, [%[m], 344]\n\t" + "ldr x9, [%[a], 344]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 344]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+44] += m[44] * mu\n\t" + "ldr x7, [%[m], 352]\n\t" + "ldr x9, [%[a], 352]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 352]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+45] += m[45] * mu\n\t" + "ldr x7, [%[m], 360]\n\t" + "ldr x9, [%[a], 360]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x4, x7, xzr\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 360]\n\t" + "adc x4, x4, xzr\n\t" + "# a[i+46] += m[46] * mu\n\t" + "ldr x7, [%[m], 368]\n\t" + "ldr x9, [%[a], 368]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x9, x9, x6\n\t" + "adc x5, x7, xzr\n\t" + "adds x9, x9, x4\n\t" + "str x9, [%[a], 368]\n\t" + "adc x5, x5, xzr\n\t" + "# a[i+47] += m[47] * mu\n\t" + "ldr x7, [%[m], 376]\n\t" + "ldr x9, [%[a], 376]\n\t" + "mul x6, x7, x8\n\t" + "umulh x7, x7, x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x7, x7, %[ca]\n\t" + "cset %[ca], cs\n\t" + "adds x9, x9, x5\n\t" + "str x9, [%[a], 376]\n\t" + "ldr x9, [%[a], 384]\n\t" + "adcs x9, x9, x7\n\t" + "str x9, [%[a], 384]\n\t" + "adc %[ca], %[ca], xzr\n\t" + "# i += 1\n\t" + "add %[a], %[a], 8\n\t" + "add x3, x3, 8\n\t" + "cmp x3, 384\n\t" + "blt 1b\n\t" + "str x10, [%[a], 0]\n\t" + "str x11, [%[a], 8]\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27" + ); + + sp_3072_cond_sub_48(a - 48, a, m, (sp_digit)0 - ca); +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_3072_mont_mul_48(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_3072_mul_48(r, a, b); + sp_3072_mont_reduce_48(r, m, mp); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_3072_mont_sqr_48(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_3072_sqr_48(r, a); + sp_3072_mont_reduce_48(r, m, mp); +} + +/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) + * + * d1 The high order half of the number to divide. + * d0 The low order half of the number to divide. + * div The dividend. + * returns the result of the division. + */ +static sp_digit div_3072_word_48(sp_digit d1, sp_digit d0, sp_digit div) +{ + sp_digit r; + + __asm__ __volatile__ ( + "lsr x5, %[div], 32\n\t" + "add x5, x5, 1\n\t" + + "udiv x3, %[d1], x5\n\t" + "lsl x6, x3, 32\n\t" + "mul x4, %[div], x6\n\t" + "umulh x3, %[div], x6\n\t" + "subs %[d0], %[d0], x4\n\t" + "sbc %[d1], %[d1], x3\n\t" + + "udiv x3, %[d1], x5\n\t" + "lsl x3, x3, 32\n\t" + "add x6, x6, x3\n\t" + "mul x4, %[div], x3\n\t" + "umulh x3, %[div], x3\n\t" + "subs %[d0], %[d0], x4\n\t" + "sbc %[d1], %[d1], x3\n\t" + + "lsl x3, %[d1], 32\n\t" + "orr x3, x3, %[d0], lsr 32\n\t" + + "udiv x3, x3, x5\n\t" + "add x6, x6, x3\n\t" + "mul x4, %[div], x3\n\t" + "umulh x3, %[div], x3\n\t" + "subs %[d0], %[d0], x4\n\t" + "sbc %[d1], %[d1], x3\n\t" + + "lsl x3, %[d1], 32\n\t" + "orr x3, x3, %[d0], lsr 32\n\t" + + "udiv x3, x3, x5\n\t" + "add x6, x6, x3\n\t" + "mul x4, %[div], x3\n\t" + "umulh x3, %[div], x3\n\t" + "subs %[d0], %[d0], x4\n\t" + "sbc %[d1], %[d1], x3\n\t" + + "udiv x3, %[d0], %[div]\n\t" + "add x6, x6, x3\n\t" + "mul x3, %[div], x3\n\t" + "sub %[d0], %[d0], x3\n\t" + "mov %[r], x6\n\t" + + : [r] "=r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "x3", "x4", "x5", "x6" + ); + + return r; +} + +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_3072_mask_48(sp_digit* r, sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<48; i++) + r[i] = a[i] & m; +#else + int i; + + for (i = 0; i < 48; i += 8) { + r[i+0] = a[i+0] & m; + r[i+1] = a[i+1] & m; + r[i+2] = a[i+2] & m; + r[i+3] = a[i+3] & m; + r[i+4] = a[i+4] & m; + r[i+5] = a[i+5] & m; + r[i+6] = a[i+6] & m; + r[i+7] = a[i+7] & m; + } +#endif +} + +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +static int64_t sp_3072_cmp_48(sp_digit* a, sp_digit* b) +{ + sp_digit r = -1; + sp_digit one = 1; + +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov x3, -1\n\t" + "mov x6, 376\n\t" + "1:\n\t" + "ldr x4, [%[a], x6]\n\t" + "ldr x5, [%[b], x6]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "sub x6, x6, #8\n\t" + "b.cc 1b\n\t" + "eor %[r], %[r], x3\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [one] "r" (one) + : "x2", "x3", "x4", "x5", "x6" + ); +#else + __asm__ __volatile__ ( + "mov x3, -1\n\t" + "ldr x4, [%[a], 376]\n\t" + "ldr x5, [%[b], 376]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 368]\n\t" + "ldr x5, [%[b], 368]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 360]\n\t" + "ldr x5, [%[b], 360]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 352]\n\t" + "ldr x5, [%[b], 352]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 344]\n\t" + "ldr x5, [%[b], 344]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 336]\n\t" + "ldr x5, [%[b], 336]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 328]\n\t" + "ldr x5, [%[b], 328]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 320]\n\t" + "ldr x5, [%[b], 320]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 312]\n\t" + "ldr x5, [%[b], 312]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 304]\n\t" + "ldr x5, [%[b], 304]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 296]\n\t" + "ldr x5, [%[b], 296]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 288]\n\t" + "ldr x5, [%[b], 288]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 280]\n\t" + "ldr x5, [%[b], 280]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 272]\n\t" + "ldr x5, [%[b], 272]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 264]\n\t" + "ldr x5, [%[b], 264]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 256]\n\t" + "ldr x5, [%[b], 256]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 248]\n\t" + "ldr x5, [%[b], 248]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 240]\n\t" + "ldr x5, [%[b], 240]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 232]\n\t" + "ldr x5, [%[b], 232]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 224]\n\t" + "ldr x5, [%[b], 224]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 216]\n\t" + "ldr x5, [%[b], 216]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 208]\n\t" + "ldr x5, [%[b], 208]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 200]\n\t" + "ldr x5, [%[b], 200]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 192]\n\t" + "ldr x5, [%[b], 192]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 184]\n\t" + "ldr x5, [%[b], 184]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 176]\n\t" + "ldr x5, [%[b], 176]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 168]\n\t" + "ldr x5, [%[b], 168]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 160]\n\t" + "ldr x5, [%[b], 160]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 152]\n\t" + "ldr x5, [%[b], 152]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 144]\n\t" + "ldr x5, [%[b], 144]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 136]\n\t" + "ldr x5, [%[b], 136]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 128]\n\t" + "ldr x5, [%[b], 128]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 120]\n\t" + "ldr x5, [%[b], 120]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 112]\n\t" + "ldr x5, [%[b], 112]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 104]\n\t" + "ldr x5, [%[b], 104]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 96]\n\t" + "ldr x5, [%[b], 96]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 88]\n\t" + "ldr x5, [%[b], 88]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 80]\n\t" + "ldr x5, [%[b], 80]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 72]\n\t" + "ldr x5, [%[b], 72]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 64]\n\t" + "ldr x5, [%[b], 64]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 56]\n\t" + "ldr x5, [%[b], 56]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 48]\n\t" + "ldr x5, [%[b], 48]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 40]\n\t" + "ldr x5, [%[b], 40]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 32]\n\t" + "ldr x5, [%[b], 32]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 24]\n\t" + "ldr x5, [%[b], 24]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 16]\n\t" + "ldr x5, [%[b], 16]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 8]\n\t" + "ldr x5, [%[b], 8]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 0]\n\t" + "ldr x5, [%[b], 0]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "eor %[r], %[r], x3\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [one] "r" (one) + : "x2", "x3", "x4", "x5", "x6" + ); +#endif + + return r; +} + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_3072_div_48(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[96], t2[49]; + sp_digit div, r1; + int i; + + (void)m; + + div = d[47]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 48); + for (i=47; i>=0; i--) { + r1 = div_3072_word_48(t1[48 + i], t1[48 + i - 1], div); + + sp_3072_mul_d_48(t2, d, r1); + t1[48 + i] += sp_3072_sub_in_place_48(&t1[i], t2); + t1[48 + i] -= t2[48]; + sp_3072_mask_48(t2, d, t1[48 + i]); + t1[48 + i] += sp_3072_add_48(&t1[i], &t1[i], t2); + sp_3072_mask_48(t2, d, t1[48 + i]); + t1[48 + i] += sp_3072_add_48(&t1[i], &t1[i], t2); + } + + r1 = sp_3072_cmp_48(t1, d) >= 0; + sp_3072_cond_sub_48(r, t1, d, (sp_digit)0 - r1); + + return MP_OKAY; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_3072_mod_48(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_3072_div_48(a, m, NULL, r); +} + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_3072_div_48_cond(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[96], t2[49]; + sp_digit div, r1; + int i; + + (void)m; + + div = d[47]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 48); + for (i=47; i>=0; i--) { + r1 = div_3072_word_48(t1[48 + i], t1[48 + i - 1], div); + + sp_3072_mul_d_48(t2, d, r1); + t1[48 + i] += sp_3072_sub_in_place_48(&t1[i], t2); + t1[48 + i] -= t2[48]; + if (t1[48 + i] != 0) { + t1[48 + i] += sp_3072_add_48(&t1[i], &t1[i], d); + if (t1[48 + i] != 0) + t1[48 + i] += sp_3072_add_48(&t1[i], &t1[i], d); + } + } + + r1 = sp_3072_cmp_48(t1, d) >= 0; + sp_3072_cond_sub_48(r, t1, d, (sp_digit)0 - r1); + + return MP_OKAY; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_3072_mod_48_cond(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_3072_div_48_cond(a, m, NULL, r); +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \ + defined(WOLFSSL_HAVE_SP_DH) +#ifdef WOLFSSL_SP_SMALL +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_3072_mod_exp_48(sp_digit* r, sp_digit* a, sp_digit* e, + int bits, sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[16][96]; +#else + sp_digit* t[16]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 96, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<16; i++) + t[i] = td + i * 96; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_48(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 48); + if (reduceA) { + err = sp_3072_mod_48(t[1] + 48, a, m); + if (err == MP_OKAY) + err = sp_3072_mod_48(t[1], t[1], m); + } + else { + XMEMCPY(t[1] + 48, a, sizeof(sp_digit) * 48); + err = sp_3072_mod_48(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_3072_mont_sqr_48(t[ 2], t[ 1], m, mp); + sp_3072_mont_mul_48(t[ 3], t[ 2], t[ 1], m, mp); + sp_3072_mont_sqr_48(t[ 4], t[ 2], m, mp); + sp_3072_mont_mul_48(t[ 5], t[ 3], t[ 2], m, mp); + sp_3072_mont_sqr_48(t[ 6], t[ 3], m, mp); + sp_3072_mont_mul_48(t[ 7], t[ 4], t[ 3], m, mp); + sp_3072_mont_sqr_48(t[ 8], t[ 4], m, mp); + sp_3072_mont_mul_48(t[ 9], t[ 5], t[ 4], m, mp); + sp_3072_mont_sqr_48(t[10], t[ 5], m, mp); + sp_3072_mont_mul_48(t[11], t[ 6], t[ 5], m, mp); + sp_3072_mont_sqr_48(t[12], t[ 6], m, mp); + sp_3072_mont_mul_48(t[13], t[ 7], t[ 6], m, mp); + sp_3072_mont_sqr_48(t[14], t[ 7], m, mp); + sp_3072_mont_mul_48(t[15], t[ 8], t[ 7], m, mp); + + i = (bits - 1) / 64; + n = e[i--]; + y = n >> 60; + n <<= 4; + c = 60; + XMEMCPY(r, t[y], sizeof(sp_digit) * 48); + for (; i>=0 || c>=4; ) { + if (c == 0) { + n = e[i--]; + y = n >> 60; + n <<= 4; + c = 60; + } + else if (c < 4) { + y = n >> 60; + n = e[i--]; + c = 4 - c; + y |= n >> (64 - c); + n <<= c; + c = 64 - c; + } + else { + y = (n >> 60) & 0xf; + n <<= 4; + c -= 4; + } + + sp_3072_mont_sqr_48(r, r, m, mp); + sp_3072_mont_sqr_48(r, r, m, mp); + sp_3072_mont_sqr_48(r, r, m, mp); + sp_3072_mont_sqr_48(r, r, m, mp); + + sp_3072_mont_mul_48(r, r, t[y], m, mp); + } + y = e[0] & ((1 << c) - 1); + for (; c > 0; c--) + sp_3072_mont_sqr_48(r, r, m, mp); + sp_3072_mont_mul_48(r, r, t[y], m, mp); + + XMEMSET(&r[48], 0, sizeof(sp_digit) * 48); + sp_3072_mont_reduce_48(r, m, mp); + + mask = 0 - (sp_3072_cmp_48(r, m) >= 0); + sp_3072_cond_sub_48(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#else +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_3072_mod_exp_48(sp_digit* r, sp_digit* a, sp_digit* e, + int bits, sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][96]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 96, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<32; i++) + t[i] = td + i * 96; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_48(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 48); + if (reduceA) { + err = sp_3072_mod_48(t[1] + 48, a, m); + if (err == MP_OKAY) + err = sp_3072_mod_48(t[1], t[1], m); + } + else { + XMEMCPY(t[1] + 48, a, sizeof(sp_digit) * 48); + err = sp_3072_mod_48(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_3072_mont_sqr_48(t[ 2], t[ 1], m, mp); + sp_3072_mont_mul_48(t[ 3], t[ 2], t[ 1], m, mp); + sp_3072_mont_sqr_48(t[ 4], t[ 2], m, mp); + sp_3072_mont_mul_48(t[ 5], t[ 3], t[ 2], m, mp); + sp_3072_mont_sqr_48(t[ 6], t[ 3], m, mp); + sp_3072_mont_mul_48(t[ 7], t[ 4], t[ 3], m, mp); + sp_3072_mont_sqr_48(t[ 8], t[ 4], m, mp); + sp_3072_mont_mul_48(t[ 9], t[ 5], t[ 4], m, mp); + sp_3072_mont_sqr_48(t[10], t[ 5], m, mp); + sp_3072_mont_mul_48(t[11], t[ 6], t[ 5], m, mp); + sp_3072_mont_sqr_48(t[12], t[ 6], m, mp); + sp_3072_mont_mul_48(t[13], t[ 7], t[ 6], m, mp); + sp_3072_mont_sqr_48(t[14], t[ 7], m, mp); + sp_3072_mont_mul_48(t[15], t[ 8], t[ 7], m, mp); + sp_3072_mont_sqr_48(t[16], t[ 8], m, mp); + sp_3072_mont_mul_48(t[17], t[ 9], t[ 8], m, mp); + sp_3072_mont_sqr_48(t[18], t[ 9], m, mp); + sp_3072_mont_mul_48(t[19], t[10], t[ 9], m, mp); + sp_3072_mont_sqr_48(t[20], t[10], m, mp); + sp_3072_mont_mul_48(t[21], t[11], t[10], m, mp); + sp_3072_mont_sqr_48(t[22], t[11], m, mp); + sp_3072_mont_mul_48(t[23], t[12], t[11], m, mp); + sp_3072_mont_sqr_48(t[24], t[12], m, mp); + sp_3072_mont_mul_48(t[25], t[13], t[12], m, mp); + sp_3072_mont_sqr_48(t[26], t[13], m, mp); + sp_3072_mont_mul_48(t[27], t[14], t[13], m, mp); + sp_3072_mont_sqr_48(t[28], t[14], m, mp); + sp_3072_mont_mul_48(t[29], t[15], t[14], m, mp); + sp_3072_mont_sqr_48(t[30], t[15], m, mp); + sp_3072_mont_mul_48(t[31], t[16], t[15], m, mp); + + i = (bits - 1) / 64; + n = e[i--]; + y = n >> 59; + n <<= 5; + c = 59; + XMEMCPY(r, t[y], sizeof(sp_digit) * 48); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 59; + n <<= 5; + c = 59; + } + else if (c < 5) { + y = n >> 59; + n = e[i--]; + c = 5 - c; + y |= n >> (64 - c); + n <<= c; + c = 64 - c; + } + else { + y = (n >> 59) & 0x1f; + n <<= 5; + c -= 5; + } + + sp_3072_mont_sqr_48(r, r, m, mp); + sp_3072_mont_sqr_48(r, r, m, mp); + sp_3072_mont_sqr_48(r, r, m, mp); + sp_3072_mont_sqr_48(r, r, m, mp); + sp_3072_mont_sqr_48(r, r, m, mp); + + sp_3072_mont_mul_48(r, r, t[y], m, mp); + } + y = e[0] & ((1 << c) - 1); + for (; c > 0; c--) + sp_3072_mont_sqr_48(r, r, m, mp); + sp_3072_mont_mul_48(r, r, t[y], m, mp); + + XMEMSET(&r[48], 0, sizeof(sp_digit) * 48); + sp_3072_mont_reduce_48(r, m, mp); + + mask = 0 - (sp_3072_cmp_48(r, m) >= 0); + sp_3072_cond_sub_48(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#endif /* WOLFSSL_SP_SMALL */ +#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ + +#ifdef WOLFSSL_HAVE_SP_RSA +/* RSA public key operation. + * + * in Array of bytes representing the number to exponentiate, base. + * inLen Number of bytes in base. + * em Public exponent. + * mm Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 384 bytes long. + * outLen Number of bytes in result. + * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when + * an array is too long and MEMORY_E when dynamic memory allocation fails. + */ +int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm, + byte* out, word32* outLen) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit ad[96], md[48], rd[96]; +#else + sp_digit* d = NULL; +#endif + sp_digit* a; + sp_digit *ah; + sp_digit* m; + sp_digit* r; + sp_digit e[1]; + int err = MP_OKAY; + + if (*outLen < 384) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(em) > 64 || inLen > 384 || + mp_count_bits(mm) != 3072)) + err = MP_READ_E; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 48 * 5, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + a = d; + r = a + 48 * 2; + m = r + 48 * 2; + ah = a + 48; + } +#else + a = ad; + m = md; + r = rd; + ah = a + 48; +#endif + + if (err == MP_OKAY) { + sp_3072_from_bin(ah, 48, in, inLen); +#if DIGIT_BIT >= 64 + e[0] = em->dp[0]; +#else + e[0] = em->dp[0]; + if (em->used > 1) + e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT; +#endif + if (e[0] == 0) + err = MP_EXPTMOD_E; + } + if (err == MP_OKAY) { + sp_3072_from_mp(m, 48, mm); + + if (e[0] == 0x3) { + if (err == MP_OKAY) { + sp_3072_sqr_48(r, ah); + err = sp_3072_mod_48_cond(r, r, m); + } + if (err == MP_OKAY) { + sp_3072_mul_48(r, ah, r); + err = sp_3072_mod_48_cond(r, r, m); + } + } + else { + int i; + sp_digit mp; + + sp_3072_mont_setup(m, &mp); + + /* Convert to Montgomery form. */ + XMEMSET(a, 0, sizeof(sp_digit) * 48); + err = sp_3072_mod_48_cond(a, a, m); + + if (err == MP_OKAY) { + for (i=63; i>=0; i--) + if (e[0] >> i) + break; + + XMEMCPY(r, a, sizeof(sp_digit) * 48); + for (i--; i>=0; i--) { + sp_3072_mont_sqr_48(r, r, m, mp); + if (((e[0] >> i) & 1) == 1) + sp_3072_mont_mul_48(r, r, a, m, mp); + } + XMEMSET(&r[48], 0, sizeof(sp_digit) * 48); + sp_3072_mont_reduce_48(r, m, mp); + + for (i = 47; i > 0; i--) { + if (r[i] != m[i]) + break; + } + if (r[i] >= m[i]) + sp_3072_sub_in_place_48(r, m); + } + } + } + + if (err == MP_OKAY) { + sp_3072_to_bin(r, out); + *outLen = 384; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_RSA); +#endif + + return err; +} + +/* RSA private key operation. + * + * in Array of bytes representing the number to exponentiate, base. + * inLen Number of bytes in base. + * dm Private exponent. + * pm First prime. + * qm Second prime. + * dpm First prime's CRT exponent. + * dqm Second prime's CRT exponent. + * qim Inverse of second prime mod p. + * mm Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 384 bytes long. + * outLen Number of bytes in result. + * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when + * an array is too long and MEMORY_E when dynamic memory allocation fails. + */ +int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, + mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm, + byte* out, word32* outLen) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit ad[48 * 2]; + sp_digit pd[24], qd[24], dpd[24]; + sp_digit tmpad[48], tmpbd[48]; +#else + sp_digit* t = NULL; +#endif + sp_digit* a; + sp_digit* p; + sp_digit* q; + sp_digit* dp; + sp_digit* dq; + sp_digit* qi; + sp_digit* tmp; + sp_digit* tmpa; + sp_digit* tmpb; + sp_digit* r; + sp_digit c; + int err = MP_OKAY; + + (void)dm; + (void)mm; + + if (*outLen < 384) + err = MP_TO_E; + if (err == MP_OKAY && (inLen > 384 || mp_count_bits(mm) != 3072)) + err = MP_READ_E; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 24 * 11, NULL, + DYNAMIC_TYPE_RSA); + if (t == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + a = t; + p = a + 48 * 2; + q = p + 24; + qi = dq = dp = q + 24; + tmpa = qi + 24; + tmpb = tmpa + 48; + + tmp = t; + r = tmp + 48; + } +#else + r = a = ad; + p = pd; + q = qd; + qi = dq = dp = dpd; + tmpa = tmpad; + tmpb = tmpbd; + tmp = a + 48; +#endif + + if (err == MP_OKAY) { + sp_3072_from_bin(a, 48, in, inLen); + sp_3072_from_mp(p, 24, pm); + sp_3072_from_mp(q, 24, qm); + sp_3072_from_mp(dp, 24, dpm); + + err = sp_3072_mod_exp_24(tmpa, a, dp, 1536, p, 1); + } + if (err == MP_OKAY) { + sp_3072_from_mp(dq, 24, dqm); + err = sp_3072_mod_exp_24(tmpb, a, dq, 1536, q, 1); + } + + if (err == MP_OKAY) { + c = sp_3072_sub_in_place_24(tmpa, tmpb); + sp_3072_mask_24(tmp, p, c); + sp_3072_add_24(tmpa, tmpa, tmp); + + sp_3072_from_mp(qi, 24, qim); + sp_3072_mul_24(tmpa, tmpa, qi); + err = sp_3072_mod_24(tmpa, tmpa, p); + } + + if (err == MP_OKAY) { + sp_3072_mul_24(tmpa, q, tmpa); + XMEMSET(&tmpb[24], 0, sizeof(sp_digit) * 24); + sp_3072_add_48(r, tmpb, tmpa); + + sp_3072_to_bin(r, out); + *outLen = 384; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_digit) * 24 * 11); + XFREE(t, NULL, DYNAMIC_TYPE_RSA); + } +#else + XMEMSET(tmpad, 0, sizeof(tmpad)); + XMEMSET(tmpbd, 0, sizeof(tmpbd)); + XMEMSET(pd, 0, sizeof(pd)); + XMEMSET(qd, 0, sizeof(qd)); + XMEMSET(dpd, 0, sizeof(dpd)); +#endif + + return err; +} +#endif /* WOLFSSL_HAVE_SP_RSA */ +#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \ + !defined(WOLFSSL_RSA_PUBLIC_ONLY)) +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_3072_to_mp(sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (3072 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { +#if DIGIT_BIT == 64 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 48); + r->used = 48; + mp_clamp(r); +#elif DIGIT_BIT < 64 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 48; i++) { + r->dp[j] |= a[i] << s; + r->dp[j] &= (1l << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + while (s + DIGIT_BIT <= 64) { + s += DIGIT_BIT; + r->dp[j] &= (1l << DIGIT_BIT) - 1; + r->dp[++j] = a[i] >> s; + } + s = 64 - s; + } + r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 48; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 64 >= DIGIT_BIT) { + #if DIGIT_BIT < 64 + r->dp[j] &= (1l << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 64 - s; + } + else + s += 64; + } + r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returs 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ + int err = MP_OKAY; + sp_digit b[96], e[48], m[48]; + sp_digit* r = b; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 3072 || expBits > 3072 || + mp_count_bits(mod) != 3072) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + sp_3072_from_mp(b, 48, base); + sp_3072_from_mp(e, 48, exp); + sp_3072_from_mp(m, 48, mod); + + err = sp_3072_mod_exp_48(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + err = sp_3072_to_mp(r, res); + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} + +#ifdef WOLFSSL_HAVE_SP_DH +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. + * exp Array of bytes that is the exponent. + * expLen Length of data, in bytes, in exponent. + * mod Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 384 bytes long. + * outLen Length, in bytes, of exponentiation result. + * returs 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen, + mp_int* mod, byte* out, word32* outLen) +{ + int err = MP_OKAY; + sp_digit b[96], e[48], m[48]; + sp_digit* r = b; + word32 i; + + if (mp_count_bits(base) > 3072 || expLen > 384 || + mp_count_bits(mod) != 3072) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + sp_3072_from_mp(b, 48, base); + sp_3072_from_bin(e, 48, exp, expLen); + sp_3072_from_mp(m, 48, mod); + + err = sp_3072_mod_exp_48(r, b, e, expLen * 8, m, 0); + } + + if (err == MP_OKAY) { + sp_3072_to_bin(r, out); + *outLen = 384; + for (i=0; i<384 && out[i] == 0; i++) { + } + *outLen -= i; + XMEMMOVE(out, out + i, *outLen); + + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} +#endif /* WOLFSSL_HAVE_SP_DH */ + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returs 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ + int err = MP_OKAY; + sp_digit b[48], e[24], m[24]; + sp_digit* r = b; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 1536 || expBits > 1536 || + mp_count_bits(mod) != 1536) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + sp_3072_from_mp(b, 24, base); + sp_3072_from_mp(e, 24, exp); + sp_3072_from_mp(m, 24, mod); + + err = sp_3072_mod_exp_24(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + XMEMSET(r + 24, 0, sizeof(*r) * 24); + err = sp_3072_to_mp(r, res); + res->used = mod->used; + mp_clamp(res); + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} + +#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ + +#endif /* !WOLFSSL_SP_NO_3072 */ + +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +#ifdef WOLFSSL_HAVE_SP_ECC +#ifndef WOLFSSL_SP_NO_256 + +/* Point structure to use. */ +typedef struct sp_point { + sp_digit x[2 * 4]; + sp_digit y[2 * 4]; + sp_digit z[2 * 4]; + int infinity; +} sp_point; + +/* The modulus (prime) of the curve P256. */ +static sp_digit p256_mod[4] = { + 0xffffffffffffffffl,0x00000000ffffffffl,0x0000000000000000l, + 0xffffffff00000001l +}; +/* The Montogmery normalizer for modulus of the curve P256. */ +static sp_digit p256_norm_mod[4] = { + 0x0000000000000001l,0xffffffff00000000l,0xffffffffffffffffl, + 0x00000000fffffffel +}; +/* The Montogmery multiplier for modulus of the curve P256. */ +static sp_digit p256_mp_mod = 0x0000000000000001; +#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ + defined(HAVE_ECC_VERIFY) +/* The order of the curve P256. */ +static sp_digit p256_order[4] = { + 0xf3b9cac2fc632551l,0xbce6faada7179e84l,0xffffffffffffffffl, + 0xffffffff00000000l +}; +#endif +/* The order of the curve P256 minus 2. */ +static sp_digit p256_order2[4] = { + 0xf3b9cac2fc63254fl,0xbce6faada7179e84l,0xffffffffffffffffl, + 0xffffffff00000000l +}; +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +/* The Montogmery normalizer for order of the curve P256. */ +static sp_digit p256_norm_order[4] = { + 0x0c46353d039cdaafl,0x4319055258e8617bl,0x0000000000000000l, + 0x00000000ffffffffl +}; +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +/* The Montogmery multiplier for order of the curve P256. */ +static sp_digit p256_mp_order = 0xccd1c8aaee00bc4fl; +#endif +#ifdef WOLFSSL_SP_SMALL +/* The base point of curve P256. */ +static sp_point p256_base = { + /* X ordinate */ + { + 0xf4a13945d898c296l,0x77037d812deb33a0l,0xf8bce6e563a440f2l, + 0x6b17d1f2e12c4247l + }, + /* Y ordinate */ + { + 0xcbb6406837bf51f5l,0x2bce33576b315ecel,0x8ee7eb4a7c0f9e16l, + 0x4fe342e2fe1a7f9bl + }, + /* Z ordinate */ + { + 0x0000000000000001l,0x0000000000000000l,0x0000000000000000l, + 0x0000000000000000l + }, + /* infinity */ + 0 +}; +#endif /* WOLFSSL_SP_SMALL */ +#if defined(HAVE_ECC_CHECK_KEY) || defined(HAVE_COMP_KEY) +static sp_digit p256_b[4] = { + 0x3bce3c3e27d2604bl,0x651d06b0cc53b0f6l,0xb3ebbd55769886bcl, + 0x5ac635d8aa3a93e7l +}; +#endif + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) +/* Allocate memory for point and return error. */ +#define sp_ecc_point_new(heap, sp, p) \ + ((p = (sp_point*)XMALLOC(sizeof(sp_point), heap, DYNAMIC_TYPE_ECC)) \ + == NULL) ? MEMORY_E : MP_OKAY +#else +/* Set pointer to data and return no error. */ +#define sp_ecc_point_new(heap, sp, p) ((p = &sp) == NULL) ? MEMORY_E : MP_OKAY +#endif + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) +/* If valid pointer then clear point data if requested and free data. */ +#define sp_ecc_point_free(p, clear, heap) \ + do { \ + if (p != NULL) { \ + if (clear) \ + XMEMSET(p, 0, sizeof(*p)); \ + XFREE(p, heap, DYNAMIC_TYPE_ECC); \ + } \ + } \ + while (0) +#else +/* Clear point data if requested. */ +#define sp_ecc_point_free(p, clear, heap) \ + do { \ + if (clear) \ + XMEMSET(p, 0, sizeof(*p)); \ + } \ + while (0) +#endif + +/* Multiply a number by Montogmery normalizer mod modulus (prime). + * + * r The resulting Montgomery form number. + * a The number to convert. + * m The modulus (prime). + */ +static int sp_256_mod_mul_norm_4(sp_digit* r, sp_digit* a, sp_digit* m) +{ + int64_t t[8]; + int64_t a32[8]; + int64_t o; + + (void)m; + + a32[0] = a[0] & 0xffffffff; + a32[1] = a[0] >> 32; + a32[2] = a[1] & 0xffffffff; + a32[3] = a[1] >> 32; + a32[4] = a[2] & 0xffffffff; + a32[5] = a[2] >> 32; + a32[6] = a[3] & 0xffffffff; + a32[7] = a[3] >> 32; + + /* 1 1 0 -1 -1 -1 -1 0 */ + t[0] = 0 + a32[0] + a32[1] - a32[3] - a32[4] - a32[5] - a32[6]; + /* 0 1 1 0 -1 -1 -1 -1 */ + t[1] = 0 + a32[1] + a32[2] - a32[4] - a32[5] - a32[6] - a32[7]; + /* 0 0 1 1 0 -1 -1 -1 */ + t[2] = 0 + a32[2] + a32[3] - a32[5] - a32[6] - a32[7]; + /* -1 -1 0 2 2 1 0 -1 */ + t[3] = 0 - a32[0] - a32[1] + 2 * a32[3] + 2 * a32[4] + a32[5] - a32[7]; + /* 0 -1 -1 0 2 2 1 0 */ + t[4] = 0 - a32[1] - a32[2] + 2 * a32[4] + 2 * a32[5] + a32[6]; + /* 0 0 -1 -1 0 2 2 1 */ + t[5] = 0 - a32[2] - a32[3] + 2 * a32[5] + 2 * a32[6] + a32[7]; + /* -1 -1 0 0 0 1 3 2 */ + t[6] = 0 - a32[0] - a32[1] + a32[5] + 3 * a32[6] + 2 * a32[7]; + /* 1 0 -1 -1 -1 -1 0 3 */ + t[7] = 0 + a32[0] - a32[2] - a32[3] - a32[4] - a32[5] + 3 * a32[7]; + + t[1] += t[0] >> 32; t[0] &= 0xffffffff; + t[2] += t[1] >> 32; t[1] &= 0xffffffff; + t[3] += t[2] >> 32; t[2] &= 0xffffffff; + t[4] += t[3] >> 32; t[3] &= 0xffffffff; + t[5] += t[4] >> 32; t[4] &= 0xffffffff; + t[6] += t[5] >> 32; t[5] &= 0xffffffff; + t[7] += t[6] >> 32; t[6] &= 0xffffffff; + o = t[7] >> 32; t[7] &= 0xffffffff; + t[0] += o; + t[3] -= o; + t[6] -= o; + t[7] += o; + t[1] += t[0] >> 32; t[0] &= 0xffffffff; + t[2] += t[1] >> 32; t[1] &= 0xffffffff; + t[3] += t[2] >> 32; t[2] &= 0xffffffff; + t[4] += t[3] >> 32; t[3] &= 0xffffffff; + t[5] += t[4] >> 32; t[4] &= 0xffffffff; + t[6] += t[5] >> 32; t[5] &= 0xffffffff; + t[7] += t[6] >> 32; t[6] &= 0xffffffff; + r[0] = (t[1] << 32) | t[0]; + r[1] = (t[3] << 32) | t[2]; + r[2] = (t[5] << 32) | t[4]; + r[3] = (t[7] << 32) | t[6]; + + return MP_OKAY; +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * a A multi-precision integer. + */ +static void sp_256_from_mp(sp_digit* r, int max, mp_int* a) +{ +#if DIGIT_BIT == 64 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < max; j++) + r[j] = 0; +#elif DIGIT_BIT > 64 + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= a->dp[i] << s; + r[j] &= 0xffffffffffffffffl; + s = 64 - s; + if (j + 1 >= max) + break; + r[++j] = a->dp[i] >> s; + while (s + 64 <= DIGIT_BIT) { + s += 64; + r[j] &= 0xffffffffffffffffl; + if (j + 1 >= max) + break; + if (s < DIGIT_BIT) + r[++j] = a->dp[i] >> s; + else + r[++j] = 0; + } + s = DIGIT_BIT - s; + } + + for (j++; j < max; j++) + r[j] = 0; +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 64) { + r[j] &= 0xffffffffffffffffl; + if (j + 1 >= max) + break; + s = 64 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else + s += DIGIT_BIT; + } + + for (j++; j < max; j++) + r[j] = 0; +#endif +} + +/* Convert a point of type ecc_point to type sp_point. + * + * p Point of type sp_point (result). + * pm Point of type ecc_point. + */ +static void sp_256_point_from_ecc_point_4(sp_point* p, ecc_point* pm) +{ + XMEMSET(p->x, 0, sizeof(p->x)); + XMEMSET(p->y, 0, sizeof(p->y)); + XMEMSET(p->z, 0, sizeof(p->z)); + sp_256_from_mp(p->x, 4, pm->x); + sp_256_from_mp(p->y, 4, pm->y); + sp_256_from_mp(p->z, 4, pm->z); + p->infinity = 0; +} + +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_256_to_mp(sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (256 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { +#if DIGIT_BIT == 64 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 4); + r->used = 4; + mp_clamp(r); +#elif DIGIT_BIT < 64 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 4; i++) { + r->dp[j] |= a[i] << s; + r->dp[j] &= (1l << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + while (s + DIGIT_BIT <= 64) { + s += DIGIT_BIT; + r->dp[j] &= (1l << DIGIT_BIT) - 1; + r->dp[++j] = a[i] >> s; + } + s = 64 - s; + } + r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 4; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 64 >= DIGIT_BIT) { + #if DIGIT_BIT < 64 + r->dp[j] &= (1l << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 64 - s; + } + else + s += 64; + } + r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Convert a point of type sp_point to type ecc_point. + * + * p Point of type sp_point. + * pm Point of type ecc_point (result). + * returns MEMORY_E when allocation of memory in ecc_point fails otherwise + * MP_OKAY. + */ +static int sp_256_point_to_ecc_point_4(sp_point* p, ecc_point* pm) +{ + int err; + + err = sp_256_to_mp(p->x, pm->x); + if (err == MP_OKAY) + err = sp_256_to_mp(p->y, pm->y); + if (err == MP_OKAY) + err = sp_256_to_mp(p->z, pm->z); + + return err; +} + +/* Conditionally copy a into r using the mask m. + * m is -1 to copy and 0 when not. + * + * r A single precision number to copy over. + * a A single precision number to copy. + * m Mask value to apply. + */ +static void sp_256_cond_copy_4(sp_digit* r, const sp_digit* a, const sp_digit m) +{ + __asm__ __volatile__ ( + "ldp x3, x4, [%[r], 0]\n\t" + "ldp x5, x6, [%[r], 16]\n\t" + "ldp x7, x8, [%[a], 0]\n\t" + "ldp x9, x10, [%[a], 16]\n\t" + "eor x7, x7, x3\n\t" + "eor x8, x8, x4\n\t" + "eor x9, x9, x5\n\t" + "eor x10, x10, x6\n\t" + "and x7, x7, %[m]\n\t" + "and x8, x8, %[m]\n\t" + "and x9, x9, %[m]\n\t" + "and x10, x10, %[m]\n\t" + "eor x3, x3, x7\n\t" + "eor x4, x4, x8\n\t" + "eor x5, x5, x9\n\t" + "eor x6, x6, x10\n\t" + "stp x3, x4, [%[r], 0]\n\t" + "stp x5, x6, [%[r], 16]\n\t" + : + : [r] "r" (r), [a] "r" (a), [m] "r" (m) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10" + ); +} + +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +static int64_t sp_256_cmp_4(sp_digit* a, sp_digit* b) +{ + sp_digit r = -1; + sp_digit one = 1; + +#ifdef WOLFSSL_SP_SMALL + __asm__ __volatile__ ( + "mov x3, -1\n\t" + "mov x6, 24\n\t" + "1:\n\t" + "ldr x4, [%[a], x6]\n\t" + "ldr x5, [%[b], x6]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "sub x6, x6, #8\n\t" + "b.cc 1b\n\t" + "eor %[r], %[r], x3\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [one] "r" (one) + : "x2", "x3", "x4", "x5", "x6" + ); +#else + __asm__ __volatile__ ( + "mov x3, -1\n\t" + "ldr x4, [%[a], 24]\n\t" + "ldr x5, [%[b], 24]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 16]\n\t" + "ldr x5, [%[b], 16]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 8]\n\t" + "ldr x5, [%[b], 8]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "ldr x4, [%[a], 0]\n\t" + "ldr x5, [%[b], 0]\n\t" + "and x4, x4, x3\n\t" + "and x5, x5, x3\n\t" + "subs x4, x4, x5\n\t" + "csel %[r], %[one], %[r], hi\n\t" + "csel %[r], x3, %[r], lo\n\t" + "csel x3, x3, xzr, eq\n\t" + "eor %[r], %[r], x3\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b), [one] "r" (one) + : "x2", "x3", "x4", "x5", "x6" + ); +#endif + + return r; +} + +/* Normalize the values in each word to 64. + * + * a Array of sp_digit to normalize. + */ +#define sp_256_norm_4(a) + +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not copying. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +static sp_digit sp_256_cond_sub_4(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit m) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + + "ldr x4, [%[a], 0]\n\t" + "ldr x6, [%[a], 8]\n\t" + "ldr x5, [%[b], 0]\n\t" + "ldr x7, [%[b], 8]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "subs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 0]\n\t" + "str x6, [%[r], 8]\n\t" + "ldr x4, [%[a], 16]\n\t" + "ldr x6, [%[a], 24]\n\t" + "ldr x5, [%[b], 16]\n\t" + "ldr x7, [%[b], 24]\n\t" + "and x5, x5, %[m]\n\t" + "and x7, x7, %[m]\n\t" + "sbcs x4, x4, x5\n\t" + "sbcs x6, x6, x7\n\t" + "str x4, [%[r], 16]\n\t" + "str x6, [%[r], 24]\n\t" + "csetm %[c], cc\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "x4", "x6", "x5", "x7", "x8" + ); + + return c; +} + +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_256_sub_4(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldp x3, x4, [%[a], 0]\n\t" + "ldp x5, x6, [%[a], 16]\n\t" + "ldp x7, x8, [%[b], 0]\n\t" + "ldp x9, x10, [%[b], 16]\n\t" + "subs x3, x3, x7\n\t" + "sbcs x4, x4, x8\n\t" + "sbcs x5, x5, x9\n\t" + "sbcs x6, x6, x10\n\t" + "stp x3, x4, [%[r], 0]\n\t" + "stp x5, x6, [%[r], 16]\n\t" + "csetm %[c], cc\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10" + ); + + return c; +} + +#define sp_256_mont_reduce_order_4 sp_256_mont_reduce_4 + +/* Reduce the number back to 256 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +SP_NOINLINE static void sp_256_mont_reduce_4(sp_digit* a, sp_digit* m, + sp_digit mp) +{ + __asm__ __volatile__ ( + "# i = 0\n\t" + "mov x9, xzr\n\t" + "mov x8, xzr\n\t" + "mov x6, %[a]\n\t" + "\n1:\n\t" + "# mu = a[i] * mp\n\t" + "ldr x5, [x6, 0]\n\t" + "mov x7, x5\n\t" + "mul x5, %[mp], x5\n\t" + "# a[i+0] += m[0] * mu\n\t" + "ldr x4, [%[m], 0]\n\t" + "ldr x11, [%[m], 8]\n\t" + "mul x3, x4, x5\n\t" + "umulh x10, x4, x5\n\t" + "adds x7, x7, x3\n\t" + "str x7, [x6, 0]\n\t" + "adc x10, x10, xzr\n\t" + "# a[i+1] += m[1] * mu\n\t" + "mul x3, x11, x5\n\t" + "umulh x12, x11, x5\n\t" + "ldr x11, [%[m], 16]\n\t" + "ldr x7, [x6, 8]\n\t" + "adds x3, x3, x10\n\t" + "adc x12, x12, xzr\n\t" + "adds x7, x7, x3\n\t" + "str x7, [x6, 8]\n\t" + "adc x12, x12, xzr\n\t" + "# a[i+2] += m[2] * mu\n\t" + "mul x3, x11, x5\n\t" + "umulh x10, x11, x5\n\t" + "ldr x11, [%[m], 24]\n\t" + "ldr x7, [x6, 16]\n\t" + "adds x3, x3, x12\n\t" + "adc x10, x10, xzr\n\t" + "adds x7, x7, x3\n\t" + "str x7, [x6, 16]\n\t" + "adc x10, x10, xzr\n\t" + "# a[i+3] += m[3] * mu\n\t" + "mul x3, x11, x5\n\t" + "umulh x4, x11, x5\n\t" + "ldr x7, [x6, 24]\n\t" + "ldr x12, [x6, 32]\n\t" + "adds x3, x3, x10\n\t" + "adcs x4, x4, x9\n\t" + "cset x9, cs\n\t" + "adds x7, x7, x3\n\t" + "str x7, [x6, 24]\n\t" + "adcs x12, x12, x4\n\t" + "str x12, [x6, 32]\n\t" + "adc x9, x9, xzr\n\t" + "# i += 1\n\t" + "add x6, x6, 8\n\t" + "add x8, x8, 8\n\t" + "cmp x8, 32\n\t" + "b.lt 1b\n\t" + "ldr x5, [%[a], 32]\n\t" + "ldr x6, [%[a], 40]\n\t" + "ldr x7, [%[a], 48]\n\t" + "ldr x8, [%[a], 56]\n\t" + "sub x3, xzr, x9\n\t" + "ldr x9, [%[m], 0]\n\t" + "ldr x10, [%[m], 8]\n\t" + "ldr x11, [%[m], 16]\n\t" + "ldr x12, [%[m], 24]\n\t" + "and x9, x9, x3\n\t" + "and x10, x10, x3\n\t" + "and x11, x11, x3\n\t" + "and x12, x12, x3\n\t" + "subs x5, x5, x9\n\t" + "sbcs x6, x6, x10\n\t" + "sbcs x7, x7, x11\n\t" + "sbc x8, x8, x12\n\t" + "str x5, [%[a], 0]\n\t" + "str x6, [%[a], 8]\n\t" + "str x7, [%[a], 16]\n\t" + "str x8, [%[a], 24]\n\t" + : + : [a] "r" (a), [m] "r" (m), [mp] "r" (mp) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", + "x12" + ); +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +SP_NOINLINE static void sp_256_mont_mul_4(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + (void)mp; + + __asm__ __volatile__ ( + "ldr x18, [%[a], 0]\n\t" + "ldr x19, [%[a], 8]\n\t" + "ldr x20, [%[a], 16]\n\t" + "ldr x21, [%[a], 24]\n\t" + "ldr x22, [%[b], 0]\n\t" + "ldr x23, [%[b], 8]\n\t" + "ldr x24, [%[b], 16]\n\t" + "ldr x25, [%[b], 24]\n\t" + "# A[0] * B[0]\n\t" + "mul x10, x18, x22\n\t" + "umulh x11, x18, x22\n\t" + "# A[0] * B[1]\n\t" + "mul x5, x18, x23\n\t" + "umulh x6, x18, x23\n\t" + "adds x11, x11, x5\n\t" + "adc x12, xzr, x6\n\t" + "# A[1] * B[0]\n\t" + "mul x5, x19, x22\n\t" + "umulh x6, x19, x22\n\t" + "adds x11, x11, x5\n\t" + "adcs x12, x12, x6\n\t" + "adc x13, xzr, xzr\n\t" + "# A[0] * B[2]\n\t" + "mul x5, x18, x24\n\t" + "umulh x6, x18, x24\n\t" + "adds x12, x12, x5\n\t" + "adc x13, x13, x6\n\t" + "# A[1] * B[1]\n\t" + "mul x5, x19, x23\n\t" + "umulh x6, x19, x23\n\t" + "adds x12, x12, x5\n\t" + "adcs x13, x13, x6\n\t" + "adc x14, xzr, xzr\n\t" + "# A[2] * B[0]\n\t" + "mul x5, x20, x22\n\t" + "umulh x6, x20, x22\n\t" + "adds x12, x12, x5\n\t" + "adcs x13, x13, x6\n\t" + "adc x14, x14, xzr\n\t" + "# A[0] * B[3]\n\t" + "mul x5, x18, x25\n\t" + "umulh x6, x18, x25\n\t" + "adds x13, x13, x5\n\t" + "adcs x14, x14, x6\n\t" + "adc x15, xzr, xzr\n\t" + "# A[1] * B[2]\n\t" + "mul x5, x19, x24\n\t" + "umulh x6, x19, x24\n\t" + "adds x13, x13, x5\n\t" + "adcs x14, x14, x6\n\t" + "adc x15, x15, xzr\n\t" + "# A[2] * B[1]\n\t" + "mul x5, x20, x23\n\t" + "umulh x6, x20, x23\n\t" + "adds x13, x13, x5\n\t" + "adcs x14, x14, x6\n\t" + "adc x15, x15, xzr\n\t" + "# A[3] * B[0]\n\t" + "mul x5, x21, x22\n\t" + "umulh x6, x21, x22\n\t" + "adds x13, x13, x5\n\t" + "adcs x14, x14, x6\n\t" + "adc x15, x15, xzr\n\t" + "# A[1] * B[3]\n\t" + "mul x5, x19, x25\n\t" + "umulh x6, x19, x25\n\t" + "adds x14, x14, x5\n\t" + "adcs x15, x15, x6\n\t" + "adc x16, xzr, xzr\n\t" + "# A[2] * B[2]\n\t" + "mul x5, x20, x24\n\t" + "umulh x6, x20, x24\n\t" + "adds x14, x14, x5\n\t" + "adcs x15, x15, x6\n\t" + "adc x16, x16, xzr\n\t" + "# A[3] * B[1]\n\t" + "mul x5, x21, x23\n\t" + "umulh x6, x21, x23\n\t" + "adds x14, x14, x5\n\t" + "adcs x15, x15, x6\n\t" + "adc x16, x16, xzr\n\t" + "# A[2] * B[3]\n\t" + "mul x5, x20, x25\n\t" + "umulh x6, x20, x25\n\t" + "adds x15, x15, x5\n\t" + "adcs x16, x16, x6\n\t" + "adc x17, xzr, xzr\n\t" + "# A[3] * B[2]\n\t" + "mul x5, x21, x24\n\t" + "umulh x6, x21, x24\n\t" + "adds x15, x15, x5\n\t" + "adcs x16, x16, x6\n\t" + "adc x17, x17, xzr\n\t" + "# A[3] * B[3]\n\t" + "mul x5, x21, x25\n\t" + "umulh x6, x21, x25\n\t" + "adds x16, x16, x5\n\t" + "adc x17, x17, x6\n\t" + "# Start Reduction\n\t" + "mov x5, x10\n\t" + "mov x6, x11\n\t" + "mov x7, x12\n\t" + "mov x8, x13\n\t" + "# mu = a[0]-a[3] + a[0]-a[2] << 32 << 64 + (a[0] * 2) << 192\n\t" + "# - a[0] << 32 << 192\n\t" + "# + (a[0] * 2) << 192\n\t" + "add x8, x8, x10\n\t" + "add x8, x8, x10\n\t" + "# a[0]-a[2] << 32\n\t" + "lsl x10, x10, 32\n\t" + "lsr x18, x5, 32\n\t" + "lsl x11, x6, 32\n\t" + "lsr x19, x6, 32\n\t" + "lsl x12, x7, 32\n\t" + "eor x11, x11, x18\n\t" + "eor x12, x12, x19\n\t" + "# - a[0] << 32 << 192\n\t" + "sub x8, x8, x10\n\t" + "# + a[0]-a[2] << 32 << 64\n\t" + "adds x6, x6, x10\n\t" + "adcs x7, x7, x11\n\t" + "adc x8, x8, x12\n\t" + "# a += (mu << 256) - (mu << 224) + (mu << 192) + (mu << 96) - mu\n\t" + "# a += mu << 256\n\t" + "adds x14, x14, x5\n\t" + "adcs x15, x15, x6\n\t" + "adcs x16, x16, x7\n\t" + "adcs x17, x17, x8\n\t" + "csetm x10, cs\n\t" + "# a += mu << 192\n\t" + "adds x13, x13, x5\n\t" + "adcs x14, x14, x6\n\t" + "adcs x15, x15, x7\n\t" + "adcs x16, x16, x8\n\t" + "adcs x17, x17, xzr\n\t" + "csetm x20, cs\n\t" + "add x10, x10, x20\n\t" + "# mu <<= 32\n\t" + "lsr x9, x8, 32\n\t" + "lsr x18, x5, 32\n\t" + "lsl x5, x5, 32\n\t" + "lsr x19, x6, 32\n\t" + "lsl x6, x6, 32\n\t" + "lsr x20, x7, 32\n\t" + "lsl x7, x7, 32\n\t" + "lsl x8, x8, 32\n\t" + "eor x6, x6, x18\n\t" + "eor x7, x7, x19\n\t" + "eor x8, x8, x20\n\t" + "# a += (mu << 32) << 64\n\t" + "adds x13, x13, x7\n\t" + "adcs x14, x14, x8\n\t" + "adcs x15, x15, x9\n\t" + "adcs x16, x16, xzr\n\t" + "adcs x17, x17, xzr\n\t" + "csetm x20, cs\n\t" + "add x10, x10, x20\n\t" + "# a -= (mu << 32) << 192\n\t" + "subs x13, x13, x5\n\t" + "mov x18, 0xffffffff\n\t" + "sbcs x14, x14, x6\n\t" + "mov x19, 0xffffffff00000001\n\t" + "sbcs x15, x15, x7\n\t" + "sbcs x16, x16, x8\n\t" + "sbcs x17, x17, x9\n\t" + "cset x20, cc\n\t" + "add x10, x10, x20\n\t" + "# mask m and sub from result if overflow\n\t" + "# m[0] = -1 & mask = mask\n\t" + "and x18, x18, x10\n\t" + "# m[2] = 0 & mask = 0\n\t" + "and x19, x19, x10\n\t" + "subs x14, x14, x10\n\t" + "sbcs x15, x15, x18\n\t" + "sbcs x16, x16, xzr\n\t" + "sbc x17, x17, x19\n\t" + "str x14, [%[r], 0]\n\t" + "str x15, [%[r], 8]\n\t" + "str x16, [%[r], 16]\n\t" + "str x17, [%[r], 24]\n\t" + : [m] "+r" (m), [a] "+r" (a), [b] "+r" (b) + : [r] "r" (r) + : "memory", "x5", "x6", "x7", "x8", "x9", + "x18", "x19", "x20", "x21", + "x22", "x23", "x24", "x25", + "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17" + ); +} + +/* Square the Montgomery form number mod the modulus (prime). (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +SP_NOINLINE static void sp_256_mont_sqr_4(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + __asm__ __volatile__ ( + "ldr x18, [%[a], 0]\n\t" + "ldr x19, [%[a], 8]\n\t" + "ldr x20, [%[a], 16]\n\t" + "ldr x21, [%[a], 24]\n\t" + "# A[0] * A[1]\n\t" + "mul x11, x18, x19\n\t" + "umulh x12, x18, x19\n\t" + "# A[0] * A[2]\n\t" + "mul x5, x18, x20\n\t" + "umulh x6, x18, x20\n\t" + "adds x12, x12, x5\n\t" + "adc x13, xzr, x6\n\t" + "# A[0] * A[3]\n\t" + "mul x5, x18, x21\n\t" + "umulh x6, x18, x21\n\t" + "adds x13, x13, x5\n\t" + "adc x14, xzr, x6\n\t" + "# A[1] * A[2]\n\t" + "mul x5, x19, x20\n\t" + "umulh x6, x19, x20\n\t" + "adds x13, x13, x5\n\t" + "adcs x14, x14, x6\n\t" + "adc x15, xzr, xzr\n\t" + "# A[1] * A[3]\n\t" + "mul x5, x19, x21\n\t" + "umulh x6, x19, x21\n\t" + "adds x14, x14, x5\n\t" + "adc x15, x15, x6\n\t" + "# A[2] * A[3]\n\t" + "mul x5, x20, x21\n\t" + "umulh x6, x20, x21\n\t" + "adds x15, x15, x5\n\t" + "adc x16, xzr, x6\n\t" + "# Double\n\t" + "adds x11, x11, x11\n\t" + "adcs x12, x12, x12\n\t" + "adcs x13, x13, x13\n\t" + "adcs x14, x14, x14\n\t" + "adcs x15, x15, x15\n\t" + "adcs x16, x16, x16\n\t" + "cset x17, cs\n\t" + "# A[0] * A[0]\n\t" + "mul x10, x18, x18\n\t" + "umulh x4, x18, x18\n\t" + "# A[1] * A[1]\n\t" + "mul x5, x19, x19\n\t" + "umulh x6, x19, x19\n\t" + "# A[2] * A[2]\n\t" + "mul x7, x20, x20\n\t" + "umulh x8, x20, x20\n\t" + "# A[3] * A[3]\n\t" + "mul x9, x21, x21\n\t" + "umulh x18, x21, x21\n\t" + "adds x11, x11, x4\n\t" + "adcs x12, x12, x5\n\t" + "adcs x13, x13, x6\n\t" + "adcs x14, x14, x7\n\t" + "adcs x15, x15, x8\n\t" + "adcs x16, x16, x9\n\t" + "adc x17, x17, x18\n\t" + "# Start Reduction\n\t" + "mov x5, x10\n\t" + "mov x6, x11\n\t" + "mov x7, x12\n\t" + "mov x8, x13\n\t" + "# mu = a[0]-a[3] + a[0]-a[2] << 32 << 64 + (a[0] * 2) << 192\n\t" + "# - a[0] << 32 << 192\n\t" + "# + (a[0] * 2) << 192\n\t" + "add x8, x8, x10\n\t" + "add x8, x8, x10\n\t" + "# a[0]-a[2] << 32\n\t" + "lsl x10, x10, 32\n\t" + "lsr x18, x5, 32\n\t" + "lsl x11, x6, 32\n\t" + "lsr x19, x6, 32\n\t" + "lsl x12, x7, 32\n\t" + "eor x11, x11, x18\n\t" + "eor x12, x12, x19\n\t" + "# - a[0] << 32 << 192\n\t" + "sub x8, x8, x10\n\t" + "# + a[0]-a[2] << 32 << 64\n\t" + "adds x6, x6, x10\n\t" + "adcs x7, x7, x11\n\t" + "adc x8, x8, x12\n\t" + "# a += (mu << 256) - (mu << 224) + (mu << 192) + (mu << 96) - mu\n\t" + "# a += mu << 256\n\t" + "adds x14, x14, x5\n\t" + "adcs x15, x15, x6\n\t" + "adcs x16, x16, x7\n\t" + "adcs x17, x17, x8\n\t" + "csetm x10, cs\n\t" + "# a += mu << 192\n\t" + "adds x13, x13, x5\n\t" + "adcs x14, x14, x6\n\t" + "adcs x15, x15, x7\n\t" + "adcs x16, x16, x8\n\t" + "adcs x17, x17, xzr\n\t" + "csetm x20, cs\n\t" + "add x10, x10, x20\n\t" + "# mu <<= 32\n\t" + "lsr x9, x8, 32\n\t" + "lsr x18, x5, 32\n\t" + "lsl x5, x5, 32\n\t" + "lsr x19, x6, 32\n\t" + "lsl x6, x6, 32\n\t" + "lsr x20, x7, 32\n\t" + "lsl x7, x7, 32\n\t" + "lsl x8, x8, 32\n\t" + "eor x6, x6, x18\n\t" + "eor x7, x7, x19\n\t" + "eor x8, x8, x20\n\t" + "# a += (mu << 32) << 64\n\t" + "adds x13, x13, x7\n\t" + "adcs x14, x14, x8\n\t" + "adcs x15, x15, x9\n\t" + "adcs x16, x16, xzr\n\t" + "adcs x17, x17, xzr\n\t" + "csetm x20, cs\n\t" + "add x10, x10, x20\n\t" + "# a -= (mu << 32) << 192\n\t" + "subs x13, x13, x5\n\t" + "mov x18, 0xffffffff\n\t" + "sbcs x14, x14, x6\n\t" + "mov x19, 0xffffffff00000001\n\t" + "sbcs x15, x15, x7\n\t" + "sbcs x16, x16, x8\n\t" + "sbcs x17, x17, x9\n\t" + "cset x20, cc\n\t" + "add x10, x10, x20\n\t" + "# mask m and sub from result if overflow\n\t" + "# m[0] = -1 & mask = mask\n\t" + "and x18, x18, x10\n\t" + "# m[2] = 0 & mask = 0\n\t" + "and x19, x19, x10\n\t" + "subs x14, x14, x10\n\t" + "sbcs x15, x15, x18\n\t" + "sbcs x16, x16, xzr\n\t" + "sbc x17, x17, x19\n\t" + "str x14, [%[r], 0]\n\t" + "str x15, [%[r], 8]\n\t" + "str x16, [%[r], 16]\n\t" + "str x17, [%[r], 24]\n\t" + : [m] "+r" (m), [a] "+r" (a), [mp] "+r" (mp) + : [r] "r" (r) + : "memory", "x4", "x5", "x6", "x7", "x8", "x9", + "x18", "x19", "x20", "x21", + "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17" + ); +} + +#if !defined(WOLFSSL_SP_SMALL) || defined(HAVE_COMP_KEY) +/* Square the Montgomery form number a number of times. (r = a ^ n mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * n Number of times to square. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_256_mont_sqr_n_4(sp_digit* r, sp_digit* a, int n, + sp_digit* m, sp_digit mp) +{ + sp_256_mont_sqr_4(r, a, m, mp); + for (; n > 1; n--) + sp_256_mont_sqr_4(r, r, m, mp); +} + +#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */ +#ifdef WOLFSSL_SP_SMALL +/* Mod-2 for the P256 curve. */ +static const uint64_t p256_mod_2[4] = { + 0xfffffffffffffffd,0x00000000ffffffff,0x0000000000000000, + 0xffffffff00000001 +}; +#endif /* !WOLFSSL_SP_SMALL */ + +/* Invert the number, in Montgomery form, modulo the modulus (prime) of the + * P256 curve. (r = 1 / a mod m) + * + * r Inverse result. + * a Number to invert. + * td Temporary data. + */ +static void sp_256_mont_inv_4(sp_digit* r, sp_digit* a, sp_digit* td) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* t = td; + int i; + + XMEMCPY(t, a, sizeof(sp_digit) * 4); + for (i=254; i>=0; i--) { + sp_256_mont_sqr_4(t, t, p256_mod, p256_mp_mod); + if (p256_mod_2[i / 64] & ((sp_digit)1 << (i % 64))) + sp_256_mont_mul_4(t, t, a, p256_mod, p256_mp_mod); + } + XMEMCPY(r, t, sizeof(sp_digit) * 4); +#else + sp_digit* t = td; + sp_digit* t2 = td + 2 * 4; + sp_digit* t3 = td + 4 * 4; + + /* t = a^2 */ + sp_256_mont_sqr_4(t, a, p256_mod, p256_mp_mod); + /* t = a^3 = t * a */ + sp_256_mont_mul_4(t, t, a, p256_mod, p256_mp_mod); + /* t2= a^c = t ^ 2 ^ 2 */ + sp_256_mont_sqr_n_4(t2, t, 2, p256_mod, p256_mp_mod); + /* t3= a^d = t2 * a */ + sp_256_mont_mul_4(t3, t2, a, p256_mod, p256_mp_mod); + /* t = a^f = t2 * t */ + sp_256_mont_mul_4(t, t2, t, p256_mod, p256_mp_mod); + /* t2= a^f0 = t ^ 2 ^ 4 */ + sp_256_mont_sqr_n_4(t2, t, 4, p256_mod, p256_mp_mod); + /* t3= a^fd = t2 * t3 */ + sp_256_mont_mul_4(t3, t2, t3, p256_mod, p256_mp_mod); + /* t = a^ff = t2 * t */ + sp_256_mont_mul_4(t, t2, t, p256_mod, p256_mp_mod); + /* t2= a^ff00 = t ^ 2 ^ 8 */ + sp_256_mont_sqr_n_4(t2, t, 8, p256_mod, p256_mp_mod); + /* t3= a^fffd = t2 * t3 */ + sp_256_mont_mul_4(t3, t2, t3, p256_mod, p256_mp_mod); + /* t = a^ffff = t2 * t */ + sp_256_mont_mul_4(t, t2, t, p256_mod, p256_mp_mod); + /* t2= a^ffff0000 = t ^ 2 ^ 16 */ + sp_256_mont_sqr_n_4(t2, t, 16, p256_mod, p256_mp_mod); + /* t3= a^fffffffd = t2 * t3 */ + sp_256_mont_mul_4(t3, t2, t3, p256_mod, p256_mp_mod); + /* t = a^ffffffff = t2 * t */ + sp_256_mont_mul_4(t, t2, t, p256_mod, p256_mp_mod); + /* t = a^ffffffff00000000 = t ^ 2 ^ 32 */ + sp_256_mont_sqr_n_4(t2, t, 32, p256_mod, p256_mp_mod); + /* t2= a^ffffffffffffffff = t2 * t */ + sp_256_mont_mul_4(t, t2, t, p256_mod, p256_mp_mod); + /* t2= a^ffffffff00000001 = t2 * a */ + sp_256_mont_mul_4(t2, t2, a, p256_mod, p256_mp_mod); + /* t2= a^ffffffff000000010000000000000000000000000000000000000000 + * = t2 ^ 2 ^ 160 */ + sp_256_mont_sqr_n_4(t2, t2, 160, p256_mod, p256_mp_mod); + /* t2= a^ffffffff00000001000000000000000000000000ffffffffffffffff + * = t2 * t */ + sp_256_mont_mul_4(t2, t2, t, p256_mod, p256_mp_mod); + /* t2= a^ffffffff00000001000000000000000000000000ffffffffffffffff00000000 + * = t2 ^ 2 ^ 32 */ + sp_256_mont_sqr_n_4(t2, t2, 32, p256_mod, p256_mp_mod); + /* r = a^ffffffff00000001000000000000000000000000fffffffffffffffffffffffd + * = t2 * t3 */ + sp_256_mont_mul_4(r, t2, t3, p256_mod, p256_mp_mod); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Map the Montgomery form projective co-ordinate point to an affine point. + * + * r Resulting affine co-ordinate point. + * p Montgomery form projective co-ordinate point. + * t Temporary ordinate data. + */ +static void sp_256_map_4(sp_point* r, sp_point* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*4; + int64_t n; + + sp_256_mont_inv_4(t1, p->z, t + 2*4); + + sp_256_mont_sqr_4(t2, t1, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t1, t2, t1, p256_mod, p256_mp_mod); + + /* x /= z^2 */ + sp_256_mont_mul_4(r->x, p->x, t2, p256_mod, p256_mp_mod); + XMEMSET(r->x + 4, 0, sizeof(r->x) / 2); + sp_256_mont_reduce_4(r->x, p256_mod, p256_mp_mod); + /* Reduce x to less than modulus */ + n = sp_256_cmp_4(r->x, p256_mod); + sp_256_cond_sub_4(r->x, r->x, p256_mod, 0 - (n >= 0)); + sp_256_norm_4(r->x); + + /* y /= z^3 */ + sp_256_mont_mul_4(r->y, p->y, t1, p256_mod, p256_mp_mod); + XMEMSET(r->y + 4, 0, sizeof(r->y) / 2); + sp_256_mont_reduce_4(r->y, p256_mod, p256_mp_mod); + /* Reduce y to less than modulus */ + n = sp_256_cmp_4(r->y, p256_mod); + sp_256_cond_sub_4(r->y, r->y, p256_mod, 0 - (n >= 0)); + sp_256_norm_4(r->y); + + XMEMSET(r->z, 0, sizeof(r->z)); + r->z[0] = 1; + +} + +/* Add two Montgomery form numbers (r = a + b % m). + * + * r Result of addition. + * a First number to add in Montogmery form. + * b Second number to add in Montogmery form. + * m Modulus (prime). + */ +static void sp_256_mont_add_4(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m) +{ + __asm__ __volatile__ ( + "ldr x4, [%[a],0]\n\t" + "ldr x5, [%[a],8]\n\t" + "ldr x6, [%[a],16]\n\t" + "ldr x7, [%[a],24]\n\t" + "ldr x8, [%[b],0]\n\t" + "ldr x9, [%[b],8]\n\t" + "ldr x10, [%[b],16]\n\t" + "ldr x11, [%[b],24]\n\t" + "adds x4, x4, x8\n\t" + "adcs x5, x5, x9\n\t" + "mov x12, 0xffffffff\n\t" + "adcs x6, x6, x10\n\t" + "adcs x7, x7, x11\n\t" + "mov x13, 0xffffffff00000001\n\t" + "csetm x14, cs\n\t" + "and x12, x12, x14\n\t" + "and x13, x13, x14\n\t" + "subs x4, x4, x14\n\t" + "sbcs x5, x5, x12\n\t" + "str x4, [%[r],0]\n\t" + "sbcs x6, x6, xzr\n\t" + "str x5, [%[r],8]\n\t" + "sbc x7, x7, x13\n\t" + "str x6, [%[r],16]\n\t" + "str x7, [%[r],24]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14" + ); +} + +/* Double a Montgomery form number (r = a + a % m). + * + * r Result of doubling. + * a Number to double in Montogmery form. + * m Modulus (prime). + */ +static void sp_256_mont_dbl_4(sp_digit* r, sp_digit* a, sp_digit* m) +{ + __asm__ __volatile__ ( + "ldr x3, [%[a]]\n\t" + "ldr x4, [%[a],8]\n\t" + "ldr x5, [%[a],16]\n\t" + "ldr x6, [%[a],24]\n\t" + "adds x3, x3, x3\n\t" + "adcs x4, x4, x4\n\t" + "mov x7, 0xffffffff\n\t" + "adcs x5, x5, x5\n\t" + "mov x8, 0xffffffff00000001\n\t" + "adcs x6, x6, x6\n\t" + "csetm x9, cs\n\t" + "and x7, x7, x9\n\t" + "and x8, x8, x9\n\t" + "subs x3, x3, x9\n\t" + "sbcs x4, x4, x7\n\t" + "str x3, [%[r],0]\n\t" + "sbcs x5, x5, xzr\n\t" + "str x4, [%[r],8]\n\t" + "sbc x6, x6, x8\n\t" + "str x5, [%[r],16]\n\t" + "str x6, [%[r],24]\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9" + ); + + (void)m; +} + +/* Triple a Montgomery form number (r = a + a + a % m). + * + * r Result of Tripling. + * a Number to triple in Montogmery form. + * m Modulus (prime). + */ +static void sp_256_mont_tpl_4(sp_digit* r, sp_digit* a, sp_digit* m) +{ + __asm__ __volatile__ ( + "ldr x10, [%[a]]\n\t" + "ldr x11, [%[a],8]\n\t" + "ldr x12, [%[a],16]\n\t" + "ldr x13, [%[a],24]\n\t" + "adds x3, x10, x10\n\t" + "adcs x4, x11, x11\n\t" + "mov x7, 0xffffffff\n\t" + "adcs x5, x12, x12\n\t" + "mov x8, 0xffffffff00000001\n\t" + "adcs x6, x13, x13\n\t" + "csetm x9, cs\n\t" + "and x7, x7, x9\n\t" + "and x8, x8, x9\n\t" + "subs x3, x3, x9\n\t" + "sbcs x4, x4, x7\n\t" + "sbcs x5, x5, xzr\n\t" + "sbc x6, x6, x8\n\t" + "adds x3, x3, x10\n\t" + "adcs x4, x4, x11\n\t" + "mov x7, 0xffffffff\n\t" + "adcs x5, x5, x12\n\t" + "mov x8, 0xffffffff00000001\n\t" + "adcs x6, x6, x13\n\t" + "csetm x9, cs\n\t" + "and x7, x7, x9\n\t" + "and x8, x8, x9\n\t" + "subs x3, x3, x9\n\t" + "sbcs x4, x4, x7\n\t" + "sbcs x5, x5, xzr\n\t" + "sbc x6, x6, x8\n\t" + "str x3, [%[r], 0]\n\t" + "str x4, [%[r], 8]\n\t" + "str x5, [%[r], 16]\n\t" + "str x6, [%[r], 24]\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "x10", "x11", "x12", "x13", "x3", "x4", "x5", "x6", "x7", "x8", "x9" + ); + + (void)m; +} + +/* Subtract two Montgomery form numbers (r = a - b % m). + * + * r Result of subtration. + * a Number to subtract from in Montogmery form. + * b Number to subtract with in Montogmery form. + * m Modulus (prime). + */ +static void sp_256_mont_sub_4(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m) +{ + __asm__ __volatile__ ( + "ldr x4, [%[a],0]\n\t" + "ldr x5, [%[a],8]\n\t" + "ldr x6, [%[a],16]\n\t" + "ldr x7, [%[a],24]\n\t" + "ldr x8, [%[b],0]\n\t" + "ldr x9, [%[b],8]\n\t" + "ldr x10, [%[b],16]\n\t" + "ldr x11, [%[b],24]\n\t" + "subs x4, x4, x8\n\t" + "sbcs x5, x5, x9\n\t" + "mov x12, 0xffffffff\n\t" + "sbcs x6, x6, x10\n\t" + "sbcs x7, x7, x11\n\t" + "mov x13, 0xffffffff00000001\n\t" + "csetm x14, cc\n\t" + "and x12, x12, x14\n\t" + "and x13, x13, x14\n\t" + "adds x4, x4, x14\n\t" + "adcs x5, x5, x12\n\t" + "str x4, [%[r],0]\n\t" + "adcs x6, x6, xzr\n\t" + "str x5, [%[r],8]\n\t" + "adc x7, x7, x13\n\t" + "str x6, [%[r],16]\n\t" + "str x7, [%[r],24]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14" + ); +} + +/* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m) + * + * r Result of division by 2. + * a Number to divide. + * m Modulus (prime). + */ +static void sp_256_div2_4(sp_digit* r, sp_digit* a, sp_digit* m) +{ + __asm__ __volatile__ ( + "ldr x3, [%[a], 0]\n\t" + "ldr x4, [%[a], 8]\n\t" + "ldr x5, [%[a], 16]\n\t" + "ldr x6, [%[a], 24]\n\t" + "and x9, x3, 1\n\t" + "sub x10, xzr, x9\n\t" + "and x7, x10, 0xffffffff\n\t" + "and x8, x10, 0xffffffff00000001\n\t" + "adds x3, x3, x10\n\t" + "adcs x4, x4, x7\n\t" + "adcs x5, x5, xzr\n\t" + "adcs x6, x6, x8\n\t" + "cset x9, cs\n\t" + "lsr x3, x3, 1\n\t" + "lsr x7, x4, 1\n\t" + "lsr x8, x5, 1\n\t" + "lsr x10, x6, 1\n\t" + "orr x3, x3, x4, lsl 63\n\t" + "orr x4, x7, x5, lsl 63\n\t" + "orr x5, x8, x6, lsl 63\n\t" + "orr x6, x10, x9, lsl 63\n\t" + "str x3, [%[r], 0]\n\t" + "str x4, [%[r], 8]\n\t" + "str x5, [%[r], 16]\n\t" + "str x6, [%[r], 24]\n\t" + : + : [r] "r" (r), [a] "r" (a), [m] "r" (m) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10" + ); + +} + +/* Double the Montgomery form projective point p. + * + * r Result of doubling point. + * p Point to double. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_dbl_4(sp_point* r, sp_point* p, sp_digit* t) +{ + sp_point* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*4; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* When infinity don't double point passed in - constant time. */ + rp[0] = r; + rp[1] = (sp_point*)t; + XMEMSET(rp[1], 0, sizeof(sp_point)); + x = rp[p->infinity]->x; + y = rp[p->infinity]->y; + z = rp[p->infinity]->z; + /* Put point to double into result - good for infinty. */ + if (r != p) { + for (i=0; i<4; i++) + r->x[i] = p->x[i]; + for (i=0; i<4; i++) + r->y[i] = p->y[i]; + for (i=0; i<4; i++) + r->z[i] = p->z[i]; + r->infinity = p->infinity; + } + + /* T1 = Z * Z */ + sp_256_mont_sqr_4(t1, z, p256_mod, p256_mp_mod); + /* Z = Y * Z */ + sp_256_mont_mul_4(z, y, z, p256_mod, p256_mp_mod); + /* Z = 2Z */ + sp_256_mont_dbl_4(z, z, p256_mod); + /* T2 = X - T1 */ + sp_256_mont_sub_4(t2, x, t1, p256_mod); + /* T1 = X + T1 */ + sp_256_mont_add_4(t1, x, t1, p256_mod); + /* T2 = T1 * T2 */ + sp_256_mont_mul_4(t2, t1, t2, p256_mod, p256_mp_mod); + /* T1 = 3T2 */ + sp_256_mont_tpl_4(t1, t2, p256_mod); + /* Y = 2Y */ + sp_256_mont_dbl_4(y, y, p256_mod); + /* Y = Y * Y */ + sp_256_mont_sqr_4(y, y, p256_mod, p256_mp_mod); + /* T2 = Y * Y */ + sp_256_mont_sqr_4(t2, y, p256_mod, p256_mp_mod); + /* T2 = T2/2 */ + sp_256_div2_4(t2, t2, p256_mod); + /* Y = Y * X */ + sp_256_mont_mul_4(y, y, x, p256_mod, p256_mp_mod); + /* X = T1 * T1 */ + sp_256_mont_mul_4(x, t1, t1, p256_mod, p256_mp_mod); + /* X = X - Y */ + sp_256_mont_sub_4(x, x, y, p256_mod); + /* X = X - Y */ + sp_256_mont_sub_4(x, x, y, p256_mod); + /* Y = Y - X */ + sp_256_mont_sub_4(y, y, x, p256_mod); + /* Y = Y * T1 */ + sp_256_mont_mul_4(y, y, t1, p256_mod, p256_mp_mod); + /* Y = Y - T2 */ + sp_256_mont_sub_4(y, y, t2, p256_mod); + +} + +/* Double the Montgomery form projective point p a number of times. + * + * r Result of repeated doubling of point. + * p Point to double. + * n Number of times to double + * t Temporary ordinate data. + */ +static void sp_256_proj_point_dbl_n_4(sp_point* r, sp_point* p, int n, + sp_digit* t) +{ + sp_point* rp[2]; + sp_digit* w = t; + sp_digit* a = t + 2*4; + sp_digit* b = t + 4*4; + sp_digit* t1 = t + 6*4; + sp_digit* t2 = t + 8*4; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + rp[0] = r; + rp[1] = (sp_point*)t; + XMEMSET(rp[1], 0, sizeof(sp_point)); + x = rp[p->infinity]->x; + y = rp[p->infinity]->y; + z = rp[p->infinity]->z; + if (r != p) { + for (i=0; i<4; i++) + r->x[i] = p->x[i]; + for (i=0; i<4; i++) + r->y[i] = p->y[i]; + for (i=0; i<4; i++) + r->z[i] = p->z[i]; + r->infinity = p->infinity; + } + + /* Y = 2*Y */ + sp_256_mont_dbl_4(y, y, p256_mod); + /* W = Z^4 */ + sp_256_mont_sqr_4(w, z, p256_mod, p256_mp_mod); + sp_256_mont_sqr_4(w, w, p256_mod, p256_mp_mod); + while (n--) { + /* A = 3*(X^2 - W) */ + sp_256_mont_sqr_4(t1, x, p256_mod, p256_mp_mod); + sp_256_mont_sub_4(t1, t1, w, p256_mod); + sp_256_mont_tpl_4(a, t1, p256_mod); + /* B = X*Y^2 */ + sp_256_mont_sqr_4(t2, y, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(b, t2, x, p256_mod, p256_mp_mod); + /* X = A^2 - 2B */ + sp_256_mont_sqr_4(x, a, p256_mod, p256_mp_mod); + sp_256_mont_dbl_4(t1, b, p256_mod); + sp_256_mont_sub_4(x, x, t1, p256_mod); + /* Z = Z*Y */ + sp_256_mont_mul_4(z, z, y, p256_mod, p256_mp_mod); + /* t2 = Y^4 */ + sp_256_mont_sqr_4(t2, t2, p256_mod, p256_mp_mod); + if (n) { + /* W = W*Y^4 */ + sp_256_mont_mul_4(w, w, t2, p256_mod, p256_mp_mod); + } + /* y = 2*A*(B - X) - Y^4 */ + sp_256_mont_sub_4(y, b, x, p256_mod); + sp_256_mont_mul_4(y, y, a, p256_mod, p256_mp_mod); + sp_256_mont_dbl_4(y, y, p256_mod); + sp_256_mont_sub_4(y, y, t2, p256_mod); + } + /* Y = Y/2 */ + sp_256_div2_4(y, y, p256_mod); +} + +/* Compare two numbers to determine if they are equal. + * Constant time implementation. + * + * a First number to compare. + * b Second number to compare. + * returns 1 when equal and 0 otherwise. + */ +static int sp_256_cmp_equal_4(const sp_digit* a, const sp_digit* b) +{ + return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]) | (a[3] ^ b[3])) == 0; +} + +/* Add two Montgomery form projective points. + * + * r Result of addition. + * p Frist point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_add_4(sp_point* r, sp_point* p, sp_point* q, + sp_digit* t) +{ + sp_point* ap[2]; + sp_point* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*4; + sp_digit* t3 = t + 4*4; + sp_digit* t4 = t + 6*4; + sp_digit* t5 = t + 8*4; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + sp_point* a = p; + p = q; + q = a; + } + + /* Check double */ + sp_256_sub_4(t1, p256_mod, q->y); + sp_256_norm_4(t1); + if (sp_256_cmp_equal_4(p->x, q->x) & sp_256_cmp_equal_4(p->z, q->z) & + (sp_256_cmp_equal_4(p->y, q->y) | sp_256_cmp_equal_4(p->y, t1))) { + sp_256_proj_point_dbl_4(r, p, t); + } + else { + rp[0] = r; + rp[1] = (sp_point*)t; + XMEMSET(rp[1], 0, sizeof(sp_point)); + x = rp[p->infinity | q->infinity]->x; + y = rp[p->infinity | q->infinity]->y; + z = rp[p->infinity | q->infinity]->z; + + ap[0] = p; + ap[1] = q; + for (i=0; i<4; i++) + r->x[i] = ap[p->infinity]->x[i]; + for (i=0; i<4; i++) + r->y[i] = ap[p->infinity]->y[i]; + for (i=0; i<4; i++) + r->z[i] = ap[p->infinity]->z[i]; + r->infinity = ap[p->infinity]->infinity; + + /* U1 = X1*Z2^2 */ + sp_256_mont_sqr_4(t1, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t3, t1, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t1, t1, x, p256_mod, p256_mp_mod); + /* U2 = X2*Z1^2 */ + sp_256_mont_sqr_4(t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t4, t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t2, t2, q->x, p256_mod, p256_mp_mod); + /* S1 = Y1*Z2^3 */ + sp_256_mont_mul_4(t3, t3, y, p256_mod, p256_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_256_mont_mul_4(t4, t4, q->y, p256_mod, p256_mp_mod); + /* H = U2 - U1 */ + sp_256_mont_sub_4(t2, t2, t1, p256_mod); + /* R = S2 - S1 */ + sp_256_mont_sub_4(t4, t4, t3, p256_mod); + /* Z3 = H*Z1*Z2 */ + sp_256_mont_mul_4(z, z, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(z, z, t2, p256_mod, p256_mp_mod); + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_256_mont_sqr_4(x, t4, p256_mod, p256_mp_mod); + sp_256_mont_sqr_4(t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(y, t1, t5, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t5, t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_sub_4(x, x, t5, p256_mod); + sp_256_mont_dbl_4(t1, y, p256_mod); + sp_256_mont_sub_4(x, x, t1, p256_mod); + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_256_mont_sub_4(y, y, x, p256_mod); + sp_256_mont_mul_4(y, y, t4, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t5, t5, t3, p256_mod, p256_mp_mod); + sp_256_mont_sub_4(y, y, t5, p256_mod); + } +} + +/* Double the Montgomery form projective point p a number of times. + * + * r Result of repeated doubling of point. + * p Point to double. + * n Number of times to double + * t Temporary ordinate data. + */ +static void sp_256_proj_point_dbl_n_store_4(sp_point* r, sp_point* p, + int n, int m, sp_digit* t) +{ + sp_digit* w = t; + sp_digit* a = t + 2*4; + sp_digit* b = t + 4*4; + sp_digit* t1 = t + 6*4; + sp_digit* t2 = t + 8*4; + sp_digit* x = r[2*m].x; + sp_digit* y = r[(1<x[i]; + for (i=0; i<4; i++) + y[i] = p->y[i]; + for (i=0; i<4; i++) + z[i] = p->z[i]; + + /* Y = 2*Y */ + sp_256_mont_dbl_4(y, y, p256_mod); + /* W = Z^4 */ + sp_256_mont_sqr_4(w, z, p256_mod, p256_mp_mod); + sp_256_mont_sqr_4(w, w, p256_mod, p256_mp_mod); + for (i=1; i<=n; i++) { + /* A = 3*(X^2 - W) */ + sp_256_mont_sqr_4(t1, x, p256_mod, p256_mp_mod); + sp_256_mont_sub_4(t1, t1, w, p256_mod); + sp_256_mont_tpl_4(a, t1, p256_mod); + /* B = X*Y^2 */ + sp_256_mont_sqr_4(t2, y, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(b, t2, x, p256_mod, p256_mp_mod); + x = r[(1<x; + sp_digit* y = ra->y; + sp_digit* z = ra->z; + sp_digit* xs = rs->x; + sp_digit* ys = rs->y; + sp_digit* zs = rs->z; + + + XMEMCPY(x, p->x, sizeof(p->x) / 2); + XMEMCPY(y, p->y, sizeof(p->y) / 2); + XMEMCPY(z, p->z, sizeof(p->z) / 2); + ra->infinity = 0; + rs->infinity = 0; + + /* U1 = X1*Z2^2 */ + sp_256_mont_sqr_4(t1, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t3, t1, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t1, t1, x, p256_mod, p256_mp_mod); + /* U2 = X2*Z1^2 */ + sp_256_mont_sqr_4(t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t4, t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t2, t2, q->x, p256_mod, p256_mp_mod); + /* S1 = Y1*Z2^3 */ + sp_256_mont_mul_4(t3, t3, y, p256_mod, p256_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_256_mont_mul_4(t4, t4, q->y, p256_mod, p256_mp_mod); + /* H = U2 - U1 */ + sp_256_mont_sub_4(t2, t2, t1, p256_mod); + /* RS = S2 + S1 */ + sp_256_mont_add_4(t6, t4, t3, p256_mod); + /* R = S2 - S1 */ + sp_256_mont_sub_4(t4, t4, t3, p256_mod); + /* Z3 = H*Z1*Z2 */ + /* ZS = H*Z1*Z2 */ + sp_256_mont_mul_4(z, z, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(z, z, t2, p256_mod, p256_mp_mod); + XMEMCPY(zs, z, sizeof(p->z)/2); + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + /* XS = RS^2 - H^3 - 2*U1*H^2 */ + sp_256_mont_sqr_4(x, t4, p256_mod, p256_mp_mod); + sp_256_mont_sqr_4(xs, t6, p256_mod, p256_mp_mod); + sp_256_mont_sqr_4(t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(y, t1, t5, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t5, t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_sub_4(x, x, t5, p256_mod); + sp_256_mont_sub_4(xs, xs, t5, p256_mod); + sp_256_mont_dbl_4(t1, y, p256_mod); + sp_256_mont_sub_4(x, x, t1, p256_mod); + sp_256_mont_sub_4(xs, xs, t1, p256_mod); + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + /* YS = -RS*(U1*H^2 - XS) - S1*H^3 */ + sp_256_mont_sub_4(ys, y, xs, p256_mod); + sp_256_mont_sub_4(y, y, x, p256_mod); + sp_256_mont_mul_4(y, y, t4, p256_mod, p256_mp_mod); + sp_256_sub_4(t6, p256_mod, t6); + sp_256_mont_mul_4(ys, ys, t6, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t5, t5, t3, p256_mod, p256_mp_mod); + sp_256_mont_sub_4(y, y, t5, p256_mod); + sp_256_mont_sub_4(ys, ys, t5, p256_mod); +} + +/* Structure used to describe recoding of scalar multiplication. */ +typedef struct ecc_recode { + /* Index into pre-computation table. */ + uint8_t i; + /* Use the negative of the point. */ + uint8_t neg; +} ecc_recode; + +/* The index into pre-computation table to use. */ +static uint8_t recode_index_4_6[66] = { + 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, 26, 27, 28, 29, 30, 31, + 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, + 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, + 0, 1, +}; + +/* Whether to negate y-ordinate. */ +static uint8_t recode_neg_4_6[66] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, +}; + +/* Recode the scalar for multiplication using pre-computed values and + * subtraction. + * + * k Scalar to multiply by. + * v Vector of operations to peform. + */ +static void sp_256_ecc_recode_6_4(sp_digit* k, ecc_recode* v) +{ + int i, j; + uint8_t y; + int carry = 0; + int o; + sp_digit n; + + j = 0; + n = k[j]; + o = 0; + for (i=0; i<43; i++) { + y = n; + if (o + 6 < 64) { + y &= 0x3f; + n >>= 6; + o += 6; + } + else if (o + 6 == 64) { + n >>= 6; + if (++j < 4) + n = k[j]; + o = 0; + } + else if (++j < 4) { + n = k[j]; + y |= (n << (64 - o)) & 0x3f; + o -= 58; + n >>= o; + } + + y += carry; + v[i].i = recode_index_4_6[y]; + v[i].neg = recode_neg_4_6[y]; + carry = (y >> 6) + v[i].neg; + } +} + +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_win_add_sub_4(sp_point* r, sp_point* g, + sp_digit* k, int map, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point td[33]; + sp_point rtd, pd; + sp_digit tmpd[2 * 4 * 6]; +#endif + sp_point* t; + sp_point* rt; + sp_point* p = NULL; + sp_digit* tmp; + sp_digit* negy; + int i; + ecc_recode v[43]; + int err; + + (void)heap; + + err = sp_ecc_point_new(heap, rtd, rt); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + t = (sp_point*)XMALLOC(sizeof(sp_point) * 33, heap, DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 6, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; +#else + t = td; + tmp = tmpd; +#endif + + + if (err == MP_OKAY) { + /* t[0] = {0, 0, 1} * norm */ + XMEMSET(&t[0], 0, sizeof(t[0])); + t[0].infinity = 1; + /* t[1] = {g->x, g->y, g->z} * norm */ + err = sp_256_mod_mul_norm_4(t[1].x, g->x, p256_mod); + } + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_4(t[1].y, g->y, p256_mod); + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_4(t[1].z, g->z, p256_mod); + + if (err == MP_OKAY) { + t[1].infinity = 0; + /* t[2] ... t[32] */ + sp_256_proj_point_dbl_n_store_4(t, &t[ 1], 5, 1, tmp); + sp_256_proj_point_add_4(&t[ 3], &t[ 2], &t[ 1], tmp); + sp_256_proj_point_dbl_4(&t[ 6], &t[ 3], tmp); + sp_256_proj_point_add_sub_4(&t[ 7], &t[ 5], &t[ 6], &t[ 1], tmp); + sp_256_proj_point_dbl_4(&t[10], &t[ 5], tmp); + sp_256_proj_point_add_sub_4(&t[11], &t[ 9], &t[10], &t[ 1], tmp); + sp_256_proj_point_dbl_4(&t[12], &t[ 6], tmp); + sp_256_proj_point_dbl_4(&t[14], &t[ 7], tmp); + sp_256_proj_point_add_sub_4(&t[15], &t[13], &t[14], &t[ 1], tmp); + sp_256_proj_point_dbl_4(&t[18], &t[ 9], tmp); + sp_256_proj_point_add_sub_4(&t[19], &t[17], &t[18], &t[ 1], tmp); + sp_256_proj_point_dbl_4(&t[20], &t[10], tmp); + sp_256_proj_point_dbl_4(&t[22], &t[11], tmp); + sp_256_proj_point_add_sub_4(&t[23], &t[21], &t[22], &t[ 1], tmp); + sp_256_proj_point_dbl_4(&t[24], &t[12], tmp); + sp_256_proj_point_dbl_4(&t[26], &t[13], tmp); + sp_256_proj_point_add_sub_4(&t[27], &t[25], &t[26], &t[ 1], tmp); + sp_256_proj_point_dbl_4(&t[28], &t[14], tmp); + sp_256_proj_point_dbl_4(&t[30], &t[15], tmp); + sp_256_proj_point_add_sub_4(&t[31], &t[29], &t[30], &t[ 1], tmp); + + negy = t[0].y; + + sp_256_ecc_recode_6_4(k, v); + + i = 42; + XMEMCPY(rt, &t[v[i].i], sizeof(sp_point)); + for (--i; i>=0; i--) { + sp_256_proj_point_dbl_n_4(rt, rt, 6, tmp); + + XMEMCPY(p, &t[v[i].i], sizeof(sp_point)); + sp_256_sub_4(negy, p256_mod, p->y); + sp_256_cond_copy_4(p->y, negy, (sp_digit)0 - v[i].neg); + sp_256_proj_point_add_4(rt, rt, p, tmp); + } + + if (map) + sp_256_map_4(r, rt, tmp); + else + XMEMCPY(r, rt, sizeof(sp_point)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + if (tmp != NULL) + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p, 0, heap); + sp_ecc_point_free(rt, 0, heap); + + return err; +} + +/* A table entry for pre-computed points. */ +typedef struct sp_table_entry { + sp_digit x[4]; + sp_digit y[4]; + byte infinity; +} sp_table_entry; + +#if defined(FP_ECC) || defined(WOLFSSL_SP_SMALL) +#endif /* FP_ECC || WOLFSSL_SP_SMALL */ +/* Add two Montgomery form projective points. The second point has a q value of + * one. + * Only the first point can be the same pointer as the result point. + * + * r Result of addition. + * p Frist point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_add_qz1_4(sp_point* r, sp_point* p, + sp_point* q, sp_digit* t) +{ + sp_point* ap[2]; + sp_point* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*4; + sp_digit* t3 = t + 4*4; + sp_digit* t4 = t + 6*4; + sp_digit* t5 = t + 8*4; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* Check double */ + sp_256_sub_4(t1, p256_mod, q->y); + sp_256_norm_4(t1); + if (sp_256_cmp_equal_4(p->x, q->x) & sp_256_cmp_equal_4(p->z, q->z) & + (sp_256_cmp_equal_4(p->y, q->y) | sp_256_cmp_equal_4(p->y, t1))) { + sp_256_proj_point_dbl_4(r, p, t); + } + else { + rp[0] = r; + rp[1] = (sp_point*)t; + XMEMSET(rp[1], 0, sizeof(sp_point)); + x = rp[p->infinity | q->infinity]->x; + y = rp[p->infinity | q->infinity]->y; + z = rp[p->infinity | q->infinity]->z; + + ap[0] = p; + ap[1] = q; + for (i=0; i<4; i++) + r->x[i] = ap[p->infinity]->x[i]; + for (i=0; i<4; i++) + r->y[i] = ap[p->infinity]->y[i]; + for (i=0; i<4; i++) + r->z[i] = ap[p->infinity]->z[i]; + r->infinity = ap[p->infinity]->infinity; + + /* U2 = X2*Z1^2 */ + sp_256_mont_sqr_4(t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t4, t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t2, t2, q->x, p256_mod, p256_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_256_mont_mul_4(t4, t4, q->y, p256_mod, p256_mp_mod); + /* H = U2 - X1 */ + sp_256_mont_sub_4(t2, t2, x, p256_mod); + /* R = S2 - Y1 */ + sp_256_mont_sub_4(t4, t4, y, p256_mod); + /* Z3 = H*Z1 */ + sp_256_mont_mul_4(z, z, t2, p256_mod, p256_mp_mod); + /* X3 = R^2 - H^3 - 2*X1*H^2 */ + sp_256_mont_sqr_4(t1, t4, p256_mod, p256_mp_mod); + sp_256_mont_sqr_4(t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t3, x, t5, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t5, t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_sub_4(x, t1, t5, p256_mod); + sp_256_mont_dbl_4(t1, t3, p256_mod); + sp_256_mont_sub_4(x, x, t1, p256_mod); + /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */ + sp_256_mont_sub_4(t3, t3, x, p256_mod); + sp_256_mont_mul_4(t3, t3, t4, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t5, t5, y, p256_mod, p256_mp_mod); + sp_256_mont_sub_4(y, t3, t5, p256_mod); + } +} + +#ifdef FP_ECC +/* Convert the projective point to affine. + * Ordinates are in Montgomery form. + * + * a Point to convert. + * t Temprorary data. + */ +static void sp_256_proj_to_affine_4(sp_point* a, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 4; + sp_digit* tmp = t + 4 * 4; + + sp_256_mont_inv_4(t1, a->z, tmp); + + sp_256_mont_sqr_4(t2, t1, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t1, t2, t1, p256_mod, p256_mp_mod); + + sp_256_mont_mul_4(a->x, a->x, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(a->y, a->y, t1, p256_mod, p256_mp_mod); + XMEMCPY(a->z, p256_norm_mod, sizeof(p256_norm_mod)); +} + +/* Generate the pre-computed table of points for the base point. + * + * a The base point. + * table Place to store generated point data. + * tmp Temprorary data. + * heap Heap to use for allocation. + */ +static int sp_256_gen_stripe_table_4(sp_point* a, + sp_table_entry* table, sp_digit* tmp, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point td, s1d, s2d; +#endif + sp_point* t; + sp_point* s1 = NULL; + sp_point* s2 = NULL; + int i, j; + int err; + + (void)heap; + + err = sp_ecc_point_new(heap, td, t); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, s1d, s1); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, s2d, s2); + + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_4(t->x, a->x, p256_mod); + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_4(t->y, a->y, p256_mod); + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_4(t->z, a->z, p256_mod); + if (err == MP_OKAY) { + t->infinity = 0; + sp_256_proj_to_affine_4(t, tmp); + + XMEMCPY(s1->z, p256_norm_mod, sizeof(p256_norm_mod)); + s1->infinity = 0; + XMEMCPY(s2->z, p256_norm_mod, sizeof(p256_norm_mod)); + s2->infinity = 0; + + /* table[0] = {0, 0, infinity} */ + XMEMSET(&table[0], 0, sizeof(sp_table_entry)); + table[0].infinity = 1; + /* table[1] = Affine version of 'a' in Montgomery form */ + XMEMCPY(table[1].x, t->x, sizeof(table->x)); + XMEMCPY(table[1].y, t->y, sizeof(table->y)); + table[1].infinity = 0; + + for (i=1; i<8; i++) { + sp_256_proj_point_dbl_n_4(t, t, 32, tmp); + sp_256_proj_to_affine_4(t, tmp); + XMEMCPY(table[1<x, sizeof(table->x)); + XMEMCPY(table[1<y, sizeof(table->y)); + table[1<x, table[1<x)); + XMEMCPY(s1->y, table[1<y)); + for (j=(1<x, table[j-(1<x)); + XMEMCPY(s2->y, table[j-(1<y)); + sp_256_proj_point_add_qz1_4(t, s1, s2, tmp); + sp_256_proj_to_affine_4(t, tmp); + XMEMCPY(table[j].x, t->x, sizeof(table->x)); + XMEMCPY(table[j].y, t->y, sizeof(table->y)); + table[j].infinity = 0; + } + } + } + + sp_ecc_point_free(s2, 0, heap); + sp_ecc_point_free(s1, 0, heap); + sp_ecc_point_free( t, 0, heap); + + return err; +} + +#endif /* FP_ECC */ +#if defined(FP_ECC) || defined(WOLFSSL_SP_SMALL) +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_stripe_4(sp_point* r, sp_point* g, + sp_table_entry* table, sp_digit* k, int map, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point rtd; + sp_point pd; + sp_digit td[2 * 4 * 5]; +#endif + sp_point* rt; + sp_point* p = NULL; + sp_digit* t; + int i, j; + int y, x; + int err; + + (void)g; + (void)heap; + + err = sp_ecc_point_new(heap, rtd, rt); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 5, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#else + t = td; +#endif + + if (err == MP_OKAY) { + XMEMCPY(p->z, p256_norm_mod, sizeof(p256_norm_mod)); + XMEMCPY(rt->z, p256_norm_mod, sizeof(p256_norm_mod)); + + y = 0; + for (j=0,x=31; j<8; j++,x+=32) + y |= ((k[x / 64] >> (x % 64)) & 1) << j; + XMEMCPY(rt->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(rt->y, table[y].y, sizeof(table[y].y)); + rt->infinity = table[y].infinity; + for (i=30; i>=0; i--) { + y = 0; + for (j=0,x=i; j<8; j++,x+=32) + y |= ((k[x / 64] >> (x % 64)) & 1) << j; + + sp_256_proj_point_dbl_4(rt, rt, t); + XMEMCPY(p->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(p->y, table[y].y, sizeof(table[y].y)); + p->infinity = table[y].infinity; + sp_256_proj_point_add_qz1_4(rt, rt, p, t); + } + + if (map) + sp_256_map_4(r, rt, t); + else + XMEMCPY(r, rt, sizeof(sp_point)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p, 0, heap); + sp_ecc_point_free(rt, 0, heap); + + return err; +} + +#endif /* FP_ECC || WOLFSSL_SP_SMALL */ +#ifdef FP_ECC +#ifndef FP_ENTRIES + #define FP_ENTRIES 16 +#endif + +typedef struct sp_cache_t { + sp_digit x[4]; + sp_digit y[4]; + sp_table_entry table[256]; + uint32_t cnt; + int set; +} sp_cache_t; + +static THREAD_LS_T sp_cache_t sp_cache[FP_ENTRIES]; +static THREAD_LS_T int sp_cache_last = -1; +static THREAD_LS_T int sp_cache_inited = 0; + +#ifndef HAVE_THREAD_LS + static volatile int initCacheMutex = 0; + static wolfSSL_Mutex sp_cache_lock; +#endif + +static void sp_ecc_get_cache(sp_point* g, sp_cache_t** cache) +{ + int i, j; + uint32_t least; + + if (sp_cache_inited == 0) { + for (i=0; ix, sp_cache[i].x) & + sp_256_cmp_equal_4(g->y, sp_cache[i].y)) { + sp_cache[i].cnt++; + break; + } + } + + /* No match. */ + if (i == FP_ENTRIES) { + /* Find empty entry. */ + i = (sp_cache_last + 1) % FP_ENTRIES; + for (; i != sp_cache_last; i=(i+1)%FP_ENTRIES) { + if (!sp_cache[i].set) { + break; + } + } + + /* Evict least used. */ + if (i == sp_cache_last) { + least = sp_cache[0].cnt; + for (j=1; jx, sizeof(sp_cache[i].x)); + XMEMCPY(sp_cache[i].y, g->y, sizeof(sp_cache[i].y)); + sp_cache[i].set = 1; + sp_cache[i].cnt = 1; + } + + *cache = &sp_cache[i]; + sp_cache_last = i; +} +#endif /* FP_ECC */ + +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_4(sp_point* r, sp_point* g, sp_digit* k, + int map, void* heap) +{ +#ifndef FP_ECC + return sp_256_ecc_mulmod_win_add_sub_4(r, g, k, map, heap); +#else + sp_digit tmp[2 * 4 * 5]; + sp_cache_t* cache; + int err = MP_OKAY; + +#ifndef HAVE_THREAD_LS + if (initCacheMutex == 0) { + wc_InitMutex(&sp_cache_lock); + initCacheMutex = 1; + } + if (wc_LockMutex(&sp_cache_lock) != 0) + err = BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + if (err == MP_OKAY) { + sp_ecc_get_cache(g, &cache); + if (cache->cnt == 2) + sp_256_gen_stripe_table_4(g, cache->table, tmp, heap); + +#ifndef HAVE_THREAD_LS + wc_UnLockMutex(&sp_cache_lock); +#endif /* HAVE_THREAD_LS */ + + if (cache->cnt < 2) { + err = sp_256_ecc_mulmod_win_add_sub_4(r, g, k, map, heap); + } + else { + err = sp_256_ecc_mulmod_stripe_4(r, g, cache->table, k, + map, heap); + } + } + + return err; +#endif +} + +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * km Scalar to multiply by. + * p Point to multiply. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_256(mp_int* km, ecc_point* gm, ecc_point* r, int map, + void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point p; + sp_digit kd[4]; +#endif + sp_point* point; + sp_digit* k = NULL; + int err = MP_OKAY; + + err = sp_ecc_point_new(heap, p, point); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + if (err == MP_OKAY) { + sp_256_from_mp(k, 4, km); + sp_256_point_from_ecc_point_4(point, gm); + + err = sp_256_ecc_mulmod_4(point, point, k, map, heap); + } + if (err == MP_OKAY) + err = sp_256_point_to_ecc_point_4(point, r); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(point, 0, heap); + + return err; +} + +#ifdef WOLFSSL_SP_SMALL +static sp_table_entry p256_table[256] = { + /* 0 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 */ + { { 0x79e730d418a9143cl,0x75ba95fc5fedb601l,0x79fb732b77622510l, + 0x18905f76a53755c6l }, + { 0xddf25357ce95560al,0x8b4ab8e4ba19e45cl,0xd2e88688dd21f325l, + 0x8571ff1825885d85l }, + 0 }, + /* 2 */ + { { 0x202886024147519al,0xd0981eac26b372f0l,0xa9d4a7caa785ebc8l, + 0xd953c50ddbdf58e9l }, + { 0x9d6361ccfd590f8fl,0x72e9626b44e6c917l,0x7fd9611022eb64cfl, + 0x863ebb7e9eb288f3l }, + 0 }, + /* 3 */ + { { 0x7856b6235cdb6485l,0x808f0ea22f0a2f97l,0x3e68d9544f7e300bl, + 0x00076055b5ff80a0l }, + { 0x7634eb9b838d2010l,0x54014fbb3243708al,0xe0e47d39842a6606l, + 0x8308776134373ee0l }, + 0 }, + /* 4 */ + { { 0x4f922fc516a0d2bbl,0x0d5cc16c1a623499l,0x9241cf3a57c62c8bl, + 0x2f5e6961fd1b667fl }, + { 0x5c15c70bf5a01797l,0x3d20b44d60956192l,0x04911b37071fdb52l, + 0xf648f9168d6f0f7bl }, + 0 }, + /* 5 */ + { { 0x9e566847e137bbbcl,0xe434469e8a6a0becl,0xb1c4276179d73463l, + 0x5abe0285133d0015l }, + { 0x92aa837cc04c7dabl,0x573d9f4c43260c07l,0x0c93156278e6cc37l, + 0x94bb725b6b6f7383l }, + 0 }, + /* 6 */ + { { 0xbbf9b48f720f141cl,0x6199b3cd2df5bc74l,0xdc3f6129411045c4l, + 0xcdd6bbcb2f7dc4efl }, + { 0xcca6700beaf436fdl,0x6f647f6db99326bel,0x0c0fa792014f2522l, + 0xa361bebd4bdae5f6l }, + 0 }, + /* 7 */ + { { 0x28aa2558597c13c7l,0xc38d635f50b7c3e1l,0x07039aecf3c09d1dl, + 0xba12ca09c4b5292cl }, + { 0x9e408fa459f91dfdl,0x3af43b66ceea07fbl,0x1eceb0899d780b29l, + 0x53ebb99d701fef4bl }, + 0 }, + /* 8 */ + { { 0x4fe7ee31b0e63d34l,0xf4600572a9e54fabl,0xc0493334d5e7b5a4l, + 0x8589fb9206d54831l }, + { 0xaa70f5cc6583553al,0x0879094ae25649e5l,0xcc90450710044652l, + 0xebb0696d02541c4fl }, + 0 }, + /* 9 */ + { { 0x4616ca15ac1647c5l,0xb8127d47c4cf5799l,0xdc666aa3764dfbacl, + 0xeb2820cbd1b27da3l }, + { 0x9406f8d86a87e008l,0xd87dfa9d922378f3l,0x56ed2e4280ccecb2l, + 0x1f28289b55a7da1dl }, + 0 }, + /* 10 */ + { { 0xabbaa0c03b89da99l,0xa6f2d79eb8284022l,0x27847862b81c05e8l, + 0x337a4b5905e54d63l }, + { 0x3c67500d21f7794al,0x207005b77d6d7f61l,0x0a5a378104cfd6e8l, + 0x0d65e0d5f4c2fbd6l }, + 0 }, + /* 11 */ + { { 0xd9d09bbeb5275d38l,0x4268a7450be0a358l,0xf0762ff4973eb265l, + 0xc23da24252f4a232l }, + { 0x5da1b84f0b94520cl,0x09666763b05bd78el,0x3a4dcb8694d29ea1l, + 0x19de3b8cc790cff1l }, + 0 }, + /* 12 */ + { { 0x183a716c26c5fe04l,0x3b28de0b3bba1bdbl,0x7432c586a4cb712cl, + 0xe34dcbd491fccbfdl }, + { 0xb408d46baaa58403l,0x9a69748682e97a53l,0x9e39012736aaa8afl, + 0xe7641f447b4e0f7fl }, + 0 }, + /* 13 */ + { { 0x7d753941df64ba59l,0xd33f10ec0b0242fcl,0x4f06dfc6a1581859l, + 0x4a12df57052a57bfl }, + { 0xbfa6338f9439dbd0l,0xd3c24bd4bde53e1fl,0xfd5e4ffa21f1b314l, + 0x6af5aa93bb5bea46l }, + 0 }, + /* 14 */ + { { 0xda10b69910c91999l,0x0a24b4402a580491l,0x3e0094b4b8cc2090l, + 0x5fe3475a66a44013l }, + { 0xb0f8cabdf93e7b4bl,0x292b501a7c23f91al,0x42e889aecd1e6263l, + 0xb544e308ecfea916l }, + 0 }, + /* 15 */ + { { 0x6478c6e916ddfdcel,0x2c329166f89179e6l,0x4e8d6e764d4e67e1l, + 0xe0b6b2bda6b0c20bl }, + { 0x0d312df2bb7efb57l,0x1aac0dde790c4007l,0xf90336ad679bc944l, + 0x71c023de25a63774l }, + 0 }, + /* 16 */ + { { 0x62a8c244bfe20925l,0x91c19ac38fdce867l,0x5a96a5d5dd387063l, + 0x61d587d421d324f6l }, + { 0xe87673a2a37173eal,0x2384800853778b65l,0x10f8441e05bab43el, + 0xfa11fe124621efbel }, + 0 }, + /* 17 */ + { { 0x1c891f2b2cb19ffdl,0x01ba8d5bb1923c23l,0xb6d03d678ac5ca8el, + 0x586eb04c1f13bedcl }, + { 0x0c35c6e527e8ed09l,0x1e81a33c1819ede2l,0x278fd6c056c652fal, + 0x19d5ac0870864f11l }, + 0 }, + /* 18 */ + { { 0x1e99f581309a4e1fl,0xab7de71be9270074l,0x26a5ef0befd28d20l, + 0xe7c0073f7f9c563fl }, + { 0x1f6d663a0ef59f76l,0x669b3b5420fcb050l,0xc08c1f7a7a6602d4l, + 0xe08504fec65b3c0al }, + 0 }, + /* 19 */ + { { 0xf098f68da031b3cal,0x6d1cab9ee6da6d66l,0x5bfd81fa94f246e8l, + 0x78f018825b0996b4l }, + { 0xb7eefde43a25787fl,0x8016f80d1dccac9bl,0x0cea4877b35bfc36l, + 0x43a773b87e94747al }, + 0 }, + /* 20 */ + { { 0x62577734d2b533d5l,0x673b8af6a1bdddc0l,0x577e7c9aa79ec293l, + 0xbb6de651c3b266b1l }, + { 0xe7e9303ab65259b3l,0xd6a0afd3d03a7480l,0xc5ac83d19b3cfc27l, + 0x60b4619a5d18b99bl }, + 0 }, + /* 21 */ + { { 0xbd6a38e11ae5aa1cl,0xb8b7652b49e73658l,0x0b130014ee5f87edl, + 0x9d0f27b2aeebffcdl }, + { 0xca9246317a730a55l,0x9c955b2fddbbc83al,0x07c1dfe0ac019a71l, + 0x244a566d356ec48dl }, + 0 }, + /* 22 */ + { { 0x6db0394aeacf1f96l,0x9f2122a9024c271cl,0x2626ac1b82cbd3b9l, + 0x45e58c873581ef69l }, + { 0xd3ff479da38f9dbcl,0xa8aaf146e888a040l,0x945adfb246e0bed7l, + 0xc040e21cc1e4b7a4l }, + 0 }, + /* 23 */ + { { 0x847af0006f8117b6l,0x651969ff73a35433l,0x482b35761d9475ebl, + 0x1cdf5c97682c6ec7l }, + { 0x7db775b411f04839l,0x7dbeacf448de1698l,0xb2921dd1b70b3219l, + 0x046755f8a92dff3dl }, + 0 }, + /* 24 */ + { { 0xcc8ac5d2bce8ffcdl,0x0d53c48b2fe61a82l,0xf6f161727202d6c7l, + 0x046e5e113b83a5f3l }, + { 0xe7b8ff64d8007f01l,0x7fb1ef125af43183l,0x045c5ea635e1a03cl, + 0x6e0106c3303d005bl }, + 0 }, + /* 25 */ + { { 0x48c7358488dd73b1l,0x7670708f995ed0d9l,0x38385ea8c56a2ab7l, + 0x442594ede901cf1fl }, + { 0xf8faa2c912d4b65bl,0x94c2343b96c90c37l,0xd326e4a15e978d1fl, + 0xa796fa514c2ee68el }, + 0 }, + /* 26 */ + { { 0x359fb604823addd7l,0x9e2a6183e56693b3l,0xf885b78e3cbf3c80l, + 0xe4ad2da9c69766e9l }, + { 0x357f7f428e048a61l,0x082d198cc092d9a0l,0xfc3a1af4c03ed8efl, + 0xc5e94046c37b5143l }, + 0 }, + /* 27 */ + { { 0x476a538c2be75f9el,0x6fd1a9e8cb123a78l,0xd85e4df0b109c04bl, + 0x63283dafdb464747l }, + { 0xce728cf7baf2df15l,0xe592c4550ad9a7f4l,0xfab226ade834bcc3l, + 0x68bd19ab1981a938l }, + 0 }, + /* 28 */ + { { 0xc08ead511887d659l,0x3374d5f4b359305al,0x96986981cfe74fe3l, + 0x495292f53c6fdfd6l }, + { 0x4a878c9e1acec896l,0xd964b210ec5b4484l,0x6696f7e2664d60a7l, + 0x0ec7530d26036837l }, + 0 }, + /* 29 */ + { { 0x2da13a05ad2687bbl,0xa1f83b6af32e21fal,0x390f5ef51dd4607bl, + 0x0f6207a664863f0bl }, + { 0xbd67e3bb0f138233l,0xdd66b96c272aa718l,0x8ed0040726ec88ael, + 0xff0db07208ed6dcfl }, + 0 }, + /* 30 */ + { { 0x749fa1014c95d553l,0xa44052fd5d680a8al,0x183b4317ff3b566fl, + 0x313b513c88740ea3l }, + { 0xb402e2ac08d11549l,0x071ee10bb4dee21cl,0x26b987dd47f2320el, + 0x2d3abcf986f19f81l }, + 0 }, + /* 31 */ + { { 0x4c288501815581a2l,0x9a0a6d56632211afl,0x19ba7a0f0cab2e99l, + 0xc036fa10ded98cdfl }, + { 0x29ae08bac1fbd009l,0x0b68b19006d15816l,0xc2eb32779b9e0d8fl, + 0xa6b2a2c4b6d40194l }, + 0 }, + /* 32 */ + { { 0xd433e50f6d3549cfl,0x6f33696ffacd665el,0x695bfdacce11fcb4l, + 0x810ee252af7c9860l }, + { 0x65450fe17159bb2cl,0xf7dfbebe758b357bl,0x2b057e74d69fea72l, + 0xd485717a92731745l }, + 0 }, + /* 33 */ + { { 0x11741a8af0cb5a98l,0xd3da8f931f3110bfl,0x1994e2cbab382adfl, + 0x6a6045a72f9a604el }, + { 0x170c0d3fa2b2411dl,0xbe0eb83e510e96e0l,0x3bcc9f738865b3ccl, + 0xd3e45cfaf9e15790l }, + 0 }, + /* 34 */ + { { 0xce1f69bbe83f7669l,0x09f8ae8272877d6bl,0x9548ae543244278dl, + 0x207755dee3c2c19cl }, + { 0x87bd61d96fef1945l,0x18813cefb12d28c3l,0x9fbcd1d672df64aal, + 0x48dc5ee57154b00dl }, + 0 }, + /* 35 */ + { { 0x123790bff7e5a199l,0xe0efb8cf989ccbb7l,0xc27a2bfe0a519c79l, + 0xf2fb0aeddff6f445l }, + { 0x41c09575f0b5025fl,0x550543d740fa9f22l,0x8fa3c8ad380bfbd0l, + 0xa13e9015db28d525l }, + 0 }, + /* 36 */ + { { 0xf9f7a350a2b65cbcl,0x0b04b9722a464226l,0x265ce241e23f07a1l, + 0x2bf0d6b01497526fl }, + { 0xd3d4dd3f4b216fb7l,0xf7d7b867fbdda26al,0xaeb7b83f6708505cl, + 0x42a94a5a162fe89fl }, + 0 }, + /* 37 */ + { { 0x5846ad0beaadf191l,0x0f8a489025a268d7l,0xe8603050494dc1f6l, + 0x2c2dd969c65ede3dl }, + { 0x6d02171d93849c17l,0x460488ba1da250ddl,0x4810c7063c3a5485l, + 0xf437fa1f42c56dbcl }, + 0 }, + /* 38 */ + { { 0x6aa0d7144a0f7dabl,0x0f0497931776e9acl,0x52c0a050f5f39786l, + 0xaaf45b3354707aa8l }, + { 0x85e37c33c18d364al,0xd40b9b063e497165l,0xf417168115ec5444l, + 0xcdf6310df4f272bcl }, + 0 }, + /* 39 */ + { { 0x7473c6238ea8b7efl,0x08e9351885bc2287l,0x419567722bda8e34l, + 0xf0d008bada9e2ff2l }, + { 0x2912671d2414d3b1l,0xb3754985b019ea76l,0x5c61b96d453bcbdbl, + 0x5bd5c2f5ca887b8bl }, + 0 }, + /* 40 */ + { { 0xef0f469ef49a3154l,0x3e85a5956e2b2e9al,0x45aaec1eaa924a9cl, + 0xaa12dfc8a09e4719l }, + { 0x26f272274df69f1dl,0xe0e4c82ca2ff5e73l,0xb9d8ce73b7a9dd44l, + 0x6c036e73e48ca901l }, + 0 }, + /* 41 */ + { { 0x5cfae12a0f6e3138l,0x6966ef0025ad345al,0x8993c64b45672bc5l, + 0x292ff65896afbe24l }, + { 0xd5250d445e213402l,0xf6580e274392c9fel,0x097b397fda1c72e8l, + 0x644e0c90311b7276l }, + 0 }, + /* 42 */ + { { 0xe1e421e1a47153f0l,0xb86c3b79920418c9l,0x93bdce87705d7672l, + 0xf25ae793cab79a77l }, + { 0x1f3194a36d869d0cl,0x9d55c8824986c264l,0x49fb5ea3096e945el, + 0x39b8e65313db0a3el }, + 0 }, + /* 43 */ + { { 0x37754200b6fd2e59l,0x35e2c0669255c98fl,0xd9dab21a0e2a5739l, + 0x39122f2f0f19db06l }, + { 0xcfbce1e003cad53cl,0x225b2c0fe65c17e3l,0x72baf1d29aa13877l, + 0x8de80af8ce80ff8dl }, + 0 }, + /* 44 */ + { { 0xafbea8d9207bbb76l,0x921c7e7c21782758l,0xdfa2b74b1c0436b1l, + 0x871949062e368c04l }, + { 0xb5f928bba3993df5l,0x639d75b5f3b3d26al,0x011aa78a85b55050l, + 0xfc315e6a5b74fde1l }, + 0 }, + /* 45 */ + { { 0x561fd41ae8d6ecfal,0x5f8c44f61aec7f86l,0x98452a7b4924741dl, + 0xe6d4a7adee389088l }, + { 0x60552ed14593c75dl,0x70a70da4dd271162l,0xd2aede937ba2c7dbl, + 0x35dfaf9a9be2ae57l }, + 0 }, + /* 46 */ + { { 0x6b956fcdaa736636l,0x09f51d97ae2cab7el,0xfb10bf410f349966l, + 0x1da5c7d71c830d2bl }, + { 0x5c41e4833cce6825l,0x15ad118ff9573c3bl,0xa28552c7f23036b8l, + 0x7077c0fddbf4b9d6l }, + 0 }, + /* 47 */ + { { 0xbf63ff8d46b9661cl,0xa1dfd36b0d2cfd71l,0x0373e140a847f8f7l, + 0x53a8632ee50efe44l }, + { 0x0976ff68696d8051l,0xdaec0c95c74f468al,0x62994dc35e4e26bdl, + 0x028ca76d34e1fcc1l }, + 0 }, + /* 48 */ + { { 0xd11d47dcfc9877eel,0xc8b36210801d0002l,0xd002c11754c260b6l, + 0x04c17cd86962f046l }, + { 0x6d9bd094b0daddf5l,0xbea2357524ce55c0l,0x663356e672da03b5l, + 0xf7ba4de9fed97474l }, + 0 }, + /* 49 */ + { { 0xd0dbfa34ebe1263fl,0x5576373571ae7ce6l,0xd244055382a6f523l, + 0xe31f960052131c41l }, + { 0xd1bb9216ea6b6ec6l,0x37a1d12e73c2fc44l,0xc10e7eac89d0a294l, + 0xaa3a6259ce34d47bl }, + 0 }, + /* 50 */ + { { 0xfbcf9df536f3dcd3l,0x6ceded50d2bf7360l,0x491710fadf504f5bl, + 0x2398dd627e79daeel }, + { 0xcf4705a36d09569el,0xea0619bb5149f769l,0xff9c037735f6034cl, + 0x5717f5b21c046210l }, + 0 }, + /* 51 */ + { { 0x9fe229c921dd895el,0x8e51850040c28451l,0xfa13d2391d637ecdl, + 0x660a2c560e3c28del }, + { 0x9cca88aed67fcbd0l,0xc84724780ea9f096l,0x32b2f48172e92b4dl, + 0x624ee54c4f522453l }, + 0 }, + /* 52 */ + { { 0x09549ce4d897ecccl,0x4d49d1d93f9880aal,0x723c2423043a7c20l, + 0x4f392afb92bdfbc0l }, + { 0x6969f8fa7de44fd9l,0xb66cfbe457b32156l,0xdb2fa803368ebc3cl, + 0x8a3e7977ccdb399cl }, + 0 }, + /* 53 */ + { { 0xdde1881f06c4b125l,0xae34e300f6e3ca8cl,0xef6999de5c7a13e9l, + 0x3888d02370c24404l }, + { 0x7628035644f91081l,0x3d9fcf615f015504l,0x1827edc8632cd36el, + 0xa5e62e4718102336l }, + 0 }, + /* 54 */ + { { 0x1a825ee32facd6c8l,0x699c635454bcbc66l,0x0ce3edf798df9931l, + 0x2c4768e6466a5adcl }, + { 0xb346ff8c90a64bc9l,0x630a6020e4779f5cl,0xd949d064bc05e884l, + 0x7b5e6441f9e652a0l }, + 0 }, + /* 55 */ + { { 0x2169422c1d28444al,0xe996c5d8be136a39l,0x2387afe5fb0c7fcel, + 0xb8af73cb0c8d744al }, + { 0x5fde83aa338b86fdl,0xfee3f158a58a5cffl,0xc9ee8f6f20ac9433l, + 0xa036395f7f3f0895l }, + 0 }, + /* 56 */ + { { 0x8c73c6bba10f7770l,0xa6f16d81a12a0e24l,0x100df68251bc2b9fl, + 0x4be36b01875fb533l }, + { 0x9226086e9fb56dbbl,0x306fef8b07e7a4f8l,0xeeaccc0566d52f20l, + 0x8cbc9a871bdc00c0l }, + 0 }, + /* 57 */ + { { 0xe131895cc0dac4abl,0xa874a440712ff112l,0x6332ae7c6a1cee57l, + 0x44e7553e0c0835f8l }, + { 0x6d503fff7734002dl,0x9d35cb8b0b34425cl,0x95f702760e8738b5l, + 0x470a683a5eb8fc18l }, + 0 }, + /* 58 */ + { { 0x81b761dc90513482l,0x0287202a01e9276al,0xcda441ee0ce73083l, + 0x16410690c63dc6efl }, + { 0xf5034a066d06a2edl,0xdd4d7745189b100bl,0xd914ae72ab8218c9l, + 0xd73479fd7abcbb4fl }, + 0 }, + /* 59 */ + { { 0x7edefb165ad4c6e5l,0x262cf08f5b06d04dl,0x12ed5bb18575cb14l, + 0x816469e30771666bl }, + { 0xd7ab9d79561e291el,0xeb9daf22c1de1661l,0xf49827eb135e0513l, + 0x0a36dd23f0dd3f9cl }, + 0 }, + /* 60 */ + { { 0x098d32c741d5533cl,0x7c5f5a9e8684628fl,0x39a228ade349bd11l, + 0xe331dfd6fdbab118l }, + { 0x5100ab686bcc6ed8l,0x7160c3bdef7a260el,0x9063d9a7bce850d7l, + 0xd3b4782a492e3389l }, + 0 }, + /* 61 */ + { { 0xa149b6e8f3821f90l,0x92edd9ed66eb7aadl,0x0bb669531a013116l, + 0x7281275a4c86a5bdl }, + { 0x503858f7d3ff47e5l,0x5e1616bc61016441l,0x62b0f11a7dfd9bb1l, + 0x2c062e7ece145059l }, + 0 }, + /* 62 */ + { { 0xa76f996f0159ac2el,0x281e7736cbdb2713l,0x2ad6d28808e46047l, + 0x282a35f92c4e7ef1l }, + { 0x9c354b1ec0ce5cd2l,0xcf99efc91379c229l,0x992caf383e82c11el, + 0xc71cd513554d2abdl }, + 0 }, + /* 63 */ + { { 0x4885de9c09b578f4l,0x1884e258e3affa7al,0x8f76b1b759182f1fl, + 0xc50f6740cf47f3a3l }, + { 0xa9c4adf3374b68eal,0xa406f32369965fe2l,0x2f86a22285a53050l, + 0xb9ecb3a7212958dcl }, + 0 }, + /* 64 */ + { { 0x56f8410ef4f8b16al,0x97241afec47b266al,0x0a406b8e6d9c87c1l, + 0x803f3e02cd42ab1bl }, + { 0x7f0309a804dbec69l,0xa83b85f73bbad05fl,0xc6097273ad8e197fl, + 0xc097440e5067adc1l }, + 0 }, + /* 65 */ + { { 0x846a56f2c379ab34l,0xa8ee068b841df8d1l,0x20314459176c68efl, + 0xf1af32d5915f1f30l }, + { 0x99c375315d75bd50l,0x837cffbaf72f67bcl,0x0613a41848d7723fl, + 0x23d0f130e2d41c8bl }, + 0 }, + /* 66 */ + { { 0x857ab6edf41500d9l,0x0d890ae5fcbeada8l,0x52fe864889725951l, + 0xb0288dd6c0a3faddl }, + { 0x85320f30650bcb08l,0x71af6313695d6e16l,0x31f520a7b989aa76l, + 0xffd3724ff408c8d2l }, + 0 }, + /* 67 */ + { { 0x53968e64b458e6cbl,0x992dad20317a5d28l,0x3814ae0b7aa75f56l, + 0xf5590f4ad78c26dfl }, + { 0x0fc24bd3cf0ba55al,0x0fc4724a0c778bael,0x1ce9864f683b674al, + 0x18d6da54f6f74a20l }, + 0 }, + /* 68 */ + { { 0xed93e225d5be5a2bl,0x6fe799835934f3c6l,0x4314092622626ffcl, + 0x50bbb4d97990216al }, + { 0x378191c6e57ec63el,0x65422c40181dcdb2l,0x41a8099b0236e0f6l, + 0x2b10011801fe49c3l }, + 0 }, + /* 69 */ + { { 0xfc68b5c59b391593l,0xc385f5a2598270fcl,0x7144f3aad19adcbbl, + 0xdd55899983fbae0cl }, + { 0x93b88b8e74b82ff4l,0xd2e03c4071e734c9l,0x9a7a9eaf43c0322al, + 0xe6e4c551149d6041l }, + 0 }, + /* 70 */ + { { 0x55f655bb1e9af288l,0x647e1a64f7ada931l,0x43697e4bcb2820e5l, + 0x51e00db107ed56ffl }, + { 0x43d169b8771c327el,0x29cdb20b4a96c2adl,0xc07d51f53deb4779l, + 0xe22f424149829177l }, + 0 }, + /* 71 */ + { { 0xcd45e8f4635f1abbl,0x7edc0cb568538874l,0xc9472c1fb5a8034dl, + 0xf709373d52dc48c9l }, + { 0x401966bba8af30d6l,0x95bf5f4af137b69cl,0x3966162a9361c47el, + 0xbd52d288e7275b11l }, + 0 }, + /* 72 */ + { { 0xab155c7a9c5fa877l,0x17dad6727d3a3d48l,0x43f43f9e73d189d8l, + 0xa0d0f8e4c8aa77a6l }, + { 0x0bbeafd8cc94f92dl,0xd818c8be0c4ddb3al,0x22cc65f8b82eba14l, + 0xa56c78c7946d6a00l }, + 0 }, + /* 73 */ + { { 0x2962391b0dd09529l,0x803e0ea63daddfcfl,0x2c77351f5b5bf481l, + 0xd8befdf8731a367al }, + { 0xab919d42fc0157f4l,0xf51caed7fec8e650l,0xcdf9cb4002d48b0al, + 0x854a68a5ce9f6478l }, + 0 }, + /* 74 */ + { { 0xdc35f67b63506ea5l,0x9286c489a4fe0d66l,0x3f101d3bfe95cd4dl, + 0x5cacea0b98846a95l }, + { 0xa90df60c9ceac44dl,0x3db29af4354d1c3al,0x08dd3de8ad5dbabel, + 0xe4982d1235e4efa9l }, + 0 }, + /* 75 */ + { { 0x23104a22c34cd55el,0x58695bb32680d132l,0xfb345afa1fa1d943l, + 0x8046b7f616b20499l }, + { 0xb533581e38e7d098l,0xd7f61e8df46f0b70l,0x30dea9ea44cb78c4l, + 0xeb17ca7b9082af55l }, + 0 }, + /* 76 */ + { { 0x1751b59876a145b9l,0xa5cf6b0fc1bc71ecl,0xd3e03565392715bbl, + 0x097b00bafab5e131l }, + { 0xaa66c8e9565f69e1l,0x77e8f75ab5be5199l,0x6033ba11da4fd984l, + 0xf95c747bafdbcc9el }, + 0 }, + /* 77 */ + { { 0x558f01d3bebae45el,0xa8ebe9f0c4bc6955l,0xaeb705b1dbc64fc6l, + 0x3512601e566ed837l }, + { 0x9336f1e1fa1161cdl,0x328ab8d54c65ef87l,0x4757eee2724f21e5l, + 0x0ef971236068ab6bl }, + 0 }, + /* 78 */ + { { 0x02598cf754ca4226l,0x5eede138f8642c8el,0x48963f74468e1790l, + 0xfc16d9333b4fbc95l }, + { 0xbe96fb31e7c800cal,0x138063312678adaal,0x3d6244976ff3e8b5l, + 0x14ca4af1b95d7a17l }, + 0 }, + /* 79 */ + { { 0x7a4771babd2f81d5l,0x1a5f9d6901f7d196l,0xd898bef7cad9c907l, + 0x4057b063f59c231dl }, + { 0xbffd82fe89c05c0al,0xe4911c6f1dc0df85l,0x3befccaea35a16dbl, + 0x1c3b5d64f1330b13l }, + 0 }, + /* 80 */ + { { 0x5fe14bfe80ec21fel,0xf6ce116ac255be82l,0x98bc5a072f4a5d67l, + 0xfad27148db7e63afl }, + { 0x90c0b6ac29ab05b3l,0x37a9a83c4e251ae6l,0x0a7dc875c2aade7dl, + 0x77387de39f0e1a84l }, + 0 }, + /* 81 */ + { { 0x1e9ecc49a56c0dd7l,0xa5cffcd846086c74l,0x8f7a1408f505aecel, + 0xb37b85c0bef0c47el }, + { 0x3596b6e4cc0e6a8fl,0xfd6d4bbf6b388f23l,0xaba453fac39cef4el, + 0x9c135ac8f9f628d5l }, + 0 }, + /* 82 */ + { { 0x32aa320284e35743l,0x320d6ab185a3cdefl,0xb821b1761df19819l, + 0x5721361fc433851fl }, + { 0x1f0db36a71fc9168l,0x5f98ba735e5c403cl,0xf64ca87e37bcd8f5l, + 0xdcbac3c9e6bb11bdl }, + 0 }, + /* 83 */ + { { 0xf01d99684518cbe2l,0xd242fc189c9eb04el,0x727663c7e47feebfl, + 0xb8c1c89e2d626862l }, + { 0x51a58bddc8e1d569l,0x563809c8b7d88cd0l,0x26c27fd9f11f31ebl, + 0x5d23bbda2f9422d4l }, + 0 }, + /* 84 */ + { { 0x0a1c729495c8f8bel,0x2961c4803bf362bfl,0x9e418403df63d4acl, + 0xc109f9cb91ece900l }, + { 0xc2d095d058945705l,0xb9083d96ddeb85c0l,0x84692b8d7a40449bl, + 0x9bc3344f2eee1ee1l }, + 0 }, + /* 85 */ + { { 0x0d5ae35642913074l,0x55491b2748a542b1l,0x469ca665b310732al, + 0x29591d525f1a4cc1l }, + { 0xe76f5b6bb84f983fl,0xbe7eef419f5f84e1l,0x1200d49680baa189l, + 0x6376551f18ef332cl }, + 0 }, + /* 86 */ + { { 0xbda5f14e562976ccl,0x22bca3e60ef12c38l,0xbbfa30646cca9852l, + 0xbdb79dc808e2987al }, + { 0xfd2cb5c9cb06a772l,0x38f475aafe536dcel,0xc2a3e0227c2b5db8l, + 0x8ee86001add3c14al }, + 0 }, + /* 87 */ + { { 0xcbe96981a4ade873l,0x7ee9aa4dc4fba48cl,0x2cee28995a054ba5l, + 0x92e51d7a6f77aa4bl }, + { 0x948bafa87190a34dl,0xd698f75bf6bd1ed1l,0xd00ee6e30caf1144l, + 0x5182f86f0a56aaaal }, + 0 }, + /* 88 */ + { { 0xfba6212c7a4cc99cl,0xff609b683e6d9ca1l,0x5dbb27cb5ac98c5al, + 0x91dcab5d4073a6f2l }, + { 0x01b6cc3d5f575a70l,0x0cb361396f8d87fal,0x165d4e8c89981736l, + 0x17a0cedb97974f2bl }, + 0 }, + /* 89 */ + { { 0x38861e2a076c8d3al,0x701aad39210f924bl,0x94d0eae413a835d9l, + 0x2e8ce36c7f4cdf41l }, + { 0x91273dab037a862bl,0x01ba9bb760e4c8fal,0xf964538833baf2ddl, + 0xf4ccc6cb34f668f3l }, + 0 }, + /* 90 */ + { { 0x44ef525cf1f79687l,0x7c59549592efa815l,0xe1231741a5c78d29l, + 0xac0db4889a0df3c9l }, + { 0x86bfc711df01747fl,0x592b9358ef17df13l,0xe5880e4f5ccb6bb5l, + 0x95a64a6194c974a2l }, + 0 }, + /* 91 */ + { { 0x72c1efdac15a4c93l,0x40269b7382585141l,0x6a8dfb1c16cb0badl, + 0x231e54ba29210677l }, + { 0xa70df9178ae6d2dcl,0x4d6aa63f39112918l,0xf627726b5e5b7223l, + 0xab0be032d8a731e1l }, + 0 }, + /* 92 */ + { { 0x097ad0e98d131f2dl,0x637f09e33b04f101l,0x1ac86196d5e9a748l, + 0xf1bcc8802cf6a679l }, + { 0x25c69140e8daacb4l,0x3c4e405560f65009l,0x591cc8fc477937a6l, + 0x851694695aebb271l }, + 0 }, + /* 93 */ + { { 0xde35c143f1dcf593l,0x78202b29b018be3bl,0xe9cdadc29bdd9d3dl, + 0x8f67d9d2daad55d8l }, + { 0x841116567481ea5fl,0xe7d2dde9e34c590cl,0xffdd43f405053fa8l, + 0xf84572b9c0728b5dl }, + 0 }, + /* 94 */ + { { 0x5e1a7a7197af71c9l,0xa14494447a736565l,0xa1b4ae070e1d5063l, + 0xedee2710616b2c19l }, + { 0xb2f034f511734121l,0x1cac6e554a25e9f0l,0x8dc148f3a40c2ecfl, + 0x9fd27e9b44ebd7f4l }, + 0 }, + /* 95 */ + { { 0x3cc7658af6e2cb16l,0xe3eb7d2cfe5919b6l,0x5a8c5816168d5583l, + 0xa40c2fb6958ff387l }, + { 0x8c9ec560fedcc158l,0x7ad804c655f23056l,0xd93967049a307e12l, + 0x99bc9bb87dc6decfl }, + 0 }, + /* 96 */ + { { 0x84a9521d927dafc6l,0x52c1fb695c09cd19l,0x9d9581a0f9366ddel, + 0x9abe210ba16d7e64l }, + { 0x480af84a48915220l,0xfa73176a4dd816c6l,0xc7d539871681ca5al, + 0x7881c25787f344b0l }, + 0 }, + /* 97 */ + { { 0x93399b51e0bcf3ffl,0x0d02cbc5127f74f6l,0x8fb465a2dd01d968l, + 0x15e6e319a30e8940l }, + { 0x646d6e0d3e0e05f4l,0xfad7bddc43588404l,0xbe61c7d1c4f850d3l, + 0x0e55facf191172cel }, + 0 }, + /* 98 */ + { { 0x7e9d9806f8787564l,0x1a33172131e85ce6l,0x6b0158cab819e8d6l, + 0xd73d09766fe96577l }, + { 0x424834251eb7206el,0xa519290fc618bb42l,0x5dcbb8595e30a520l, + 0x9250a3748f15a50bl }, + 0 }, + /* 99 */ + { { 0xcaff08f8be577410l,0xfd408a035077a8c6l,0xf1f63289ec0a63a4l, + 0x77414082c1cc8c0bl }, + { 0x05a40fa6eb0991cdl,0xc1ca086649fdc296l,0x3a68a3c7b324fd40l, + 0x8cb04f4d12eb20b9l }, + 0 }, + /* 100 */ + { { 0xb1c2d0556906171cl,0x9073e9cdb0240c3fl,0xdb8e6b4fd8906841l, + 0xe4e429ef47123b51l }, + { 0x0b8dd53c38ec36f4l,0xf9d2dc01ff4b6a27l,0x5d066e07879a9a48l, + 0x37bca2ff3c6e6552l }, + 0 }, + /* 101 */ + { { 0x4cd2e3c7df562470l,0x44f272a2c0964ac9l,0x7c6d5df980c793bel, + 0x59913edc3002b22al }, + { 0x7a139a835750592al,0x99e01d80e783de02l,0xcf8c0375ea05d64fl, + 0x43786e4ab013e226l }, + 0 }, + /* 102 */ + { { 0xff32b0ed9e56b5a6l,0x0750d9a6d9fc68f9l,0xec15e845597846a7l, + 0x8638ca98b7e79e7al }, + { 0x2f5ae0960afc24b2l,0x05398eaf4dace8f2l,0x3b765dd0aecba78fl, + 0x1ecdd36a7b3aa6f0l }, + 0 }, + /* 103 */ + { { 0x5d3acd626c5ff2f3l,0xa2d516c02873a978l,0xad94c9fad2110d54l, + 0xd85d0f85d459f32dl }, + { 0x9f700b8d10b11da3l,0xd2c22c30a78318c4l,0x556988f49208decdl, + 0xa04f19c3b4ed3c62l }, + 0 }, + /* 104 */ + { { 0x087924c8ed7f93bdl,0xcb64ac5d392f51f6l,0x7cae330a821b71afl, + 0x92b2eeea5c0950b0l }, + { 0x85ac4c9485b6e235l,0xab2ca4a92936c0f0l,0x80faa6b3e0508891l, + 0x1ee782215834276cl }, + 0 }, + /* 105 */ + { { 0xa60a2e00e63e79f7l,0xf590e7b2f399d906l,0x9021054a6607c09dl, + 0xf3f2ced857a6e150l }, + { 0x200510f3f10d9b55l,0x9d2fcfacd8642648l,0xe5631aa7e8bd0e7cl, + 0x0f56a4543da3e210l }, + 0 }, + /* 106 */ + { { 0x5b21bffa1043e0dfl,0x6c74b6cc9c007e6dl,0x1a656ec0d4a8517al, + 0xbd8f17411969e263l }, + { 0x8a9bbb86beb7494al,0x1567d46f45f3b838l,0xdf7a12a7a4e5a79al, + 0x2d1a1c3530ccfa09l }, + 0 }, + /* 107 */ + { { 0x192e3813506508dal,0x336180c4a1d795a7l,0xcddb59497a9944b3l, + 0xa107a65eb91fba46l }, + { 0xe6d1d1c50f94d639l,0x8b4af3758a58b7d7l,0x1a7c5584bd37ca1cl, + 0x183d760af87a9af2l }, + 0 }, + /* 108 */ + { { 0x29d697110dde59a4l,0xf1ad8d070e8bef87l,0x229b49634f2ebe78l, + 0x1d44179dc269d754l }, + { 0xb32dc0cf8390d30el,0x0a3b27530de8110cl,0x31af1dc52bc0339al, + 0x771f9cc29606d262l }, + 0 }, + /* 109 */ + { { 0x99993e7785040739l,0x44539db98026a939l,0xcf40f6f2f5f8fc26l, + 0x64427a310362718el }, + { 0x4f4f2d8785428aa8l,0x7b7adc3febfb49a8l,0x201b2c6df23d01acl, + 0x49d9b7496ae90d6dl }, + 0 }, + /* 110 */ + { { 0xcc78d8bc435d1099l,0x2adbcd4e8e8d1a08l,0x02c2e2a02cb68a41l, + 0x9037d81b3f605445l }, + { 0x7cdbac27074c7b61l,0xfe2031ab57bfd72el,0x61ccec96596d5352l, + 0x08c3de6a7cc0639cl }, + 0 }, + /* 111 */ + { { 0x20fdd020f6d552abl,0x56baff9805cd81f1l,0x06fb7c3e91351291l, + 0xc690944245796b2fl }, + { 0x17b3ae9c41231bd1l,0x1eac6e875cc58205l,0x208837abf9d6a122l, + 0x3fa3db02cafe3ac0l }, + 0 }, + /* 112 */ + { { 0xd75a3e6505058880l,0x7da365ef643943f2l,0x4147861cfab24925l, + 0xc5c4bdb0fdb808ffl }, + { 0x73513e34b272b56bl,0xc8327e9511b9043al,0xfd8ce37df8844969l, + 0x2d56db9446c2b6b5l }, + 0 }, + /* 113 */ + { { 0x2461782fff46ac6bl,0xd19f792607a2e425l,0xfafea3c409a48de1l, + 0x0f56bd9de503ba42l }, + { 0x137d4ed1345cda49l,0x821158fc816f299dl,0xe7c6a54aaeb43402l, + 0x4003bb9d1173b5f1l }, + 0 }, + /* 114 */ + { { 0x3b8e8189a0803387l,0xece115f539cbd404l,0x4297208dd2877f21l, + 0x53765522a07f2f9el }, + { 0xa4980a21a8a4182dl,0xa2bbd07a3219df79l,0x674d0a2e1a19a2d4l, + 0x7a056f586c5d4549l }, + 0 }, + /* 115 */ + { { 0x646b25589d8a2a47l,0x5b582948c3df2773l,0x51ec000eabf0d539l, + 0x77d482f17a1a2675l }, + { 0xb8a1bd9587853948l,0xa6f817bd6cfbffeel,0xab6ec05780681e47l, + 0x4115012b2b38b0e4l }, + 0 }, + /* 116 */ + { { 0x3c73f0f46de28cedl,0x1d5da7609b13ec47l,0x61b8ce9e6e5c6392l, + 0xcdf04572fbea0946l }, + { 0x1cb3c58b6c53c3b0l,0x97fe3c10447b843cl,0xfb2b8ae12cb9780el, + 0xee703dda97383109l }, + 0 }, + /* 117 */ + { { 0x34515140ff57e43al,0xd44660d3b1b811b8l,0x2b3b5dff8f42b986l, + 0x2a0ad89da162ce21l }, + { 0x64e4a6946bc277bal,0xc788c954c141c276l,0x141aa64ccabf6274l, + 0xd62d0b67ac2b4659l }, + 0 }, + /* 118 */ + { { 0x39c5d87b2c054ac4l,0x57005859f27df788l,0xedf7cbf3b18128d6l, + 0xb39a23f2991c2426l }, + { 0x95284a15f0b16ae5l,0x0c6a05b1a136f51bl,0x1d63c137f2700783l, + 0x04ed0092c0674cc5l }, + 0 }, + /* 119 */ + { { 0x1f4185d19ae90393l,0x3047b4294a3d64e6l,0xae0001a69854fc14l, + 0xa0a91fc10177c387l }, + { 0xff0a3f01ae2c831el,0xbb76ae822b727e16l,0x8f12c8a15a3075b4l, + 0x084cf9889ed20c41l }, + 0 }, + /* 120 */ + { { 0xd98509defca6becfl,0x2fceae807dffb328l,0x5d8a15c44778e8b9l, + 0xd57955b273abf77el }, + { 0x210da79e31b5d4f1l,0xaa52f04b3cfa7a1cl,0xd4d12089dc27c20bl, + 0x8e14ea4202d141f1l }, + 0 }, + /* 121 */ + { { 0xeed50345f2897042l,0x8d05331f43402c4al,0xc8d9c194c8bdfb21l, + 0x597e1a372aa4d158l }, + { 0x0327ec1acf0bd68cl,0x6d4be0dcab024945l,0x5b9c8d7ac9fe3e84l, + 0xca3f0236199b4deal }, + 0 }, + /* 122 */ + { { 0x592a10b56170bd20l,0x0ea897f16d3f5de7l,0xa3363ff144b2ade2l, + 0xbde7fd7e309c07e4l }, + { 0x516bb6d2b8f5432cl,0x210dc1cbe043444bl,0x3db01e6ff8f95b5al, + 0xb623ad0e0a7dd198l }, + 0 }, + /* 123 */ + { { 0xa75bd67560c7b65bl,0xab8c559023a4a289l,0xf8220fd0d7b26795l, + 0xd6aa2e4658ec137bl }, + { 0x10abc00b5138bb85l,0x8c31d121d833a95cl,0xb24ff00b1702a32el, + 0x111662e02dcc513al }, + 0 }, + /* 124 */ + { { 0x78114015efb42b87l,0xbd9f5d701b6c4dffl,0x66ecccd7a7d7c129l, + 0xdb3ee1cb94b750f8l }, + { 0xb26f3db0f34837cfl,0xe7eed18bb9578d4fl,0x5d2cdf937c56657dl, + 0x886a644252206a59l }, + 0 }, + /* 125 */ + { { 0x3c234cfb65b569eal,0x20011141f72119c1l,0x8badc85da15a619el, + 0xa70cf4eb018a17bcl }, + { 0x224f97ae8c4a6a65l,0x36e5cf270134378fl,0xbe3a609e4f7e0960l, + 0xaa4772abd1747b77l }, + 0 }, + /* 126 */ + { { 0x676761317aa60cc0l,0xc79163610368115fl,0xded98bb4bbc1bb5al, + 0x611a6ddc30faf974l }, + { 0x30e78cbcc15ee47al,0x2e8962824e0d96a5l,0x36f35adf3dd9ed88l, + 0x5cfffaf816429c88l }, + 0 }, + /* 127 */ + { { 0xc0d54cff9b7a99cdl,0x7bf3b99d843c45a1l,0x038a908f62c739e1l, + 0x6e5a6b237dc1994cl }, + { 0xef8b454e0ba5db77l,0xb7b8807facf60d63l,0xe591c0c676608378l, + 0x481a238d242dabccl }, + 0 }, + /* 128 */ + { { 0xe3417bc035d0b34al,0x440b386b8327c0a7l,0x8fb7262dac0362d1l, + 0x2c41114ce0cdf943l }, + { 0x2ba5cef1ad95a0b1l,0xc09b37a867d54362l,0x26d6cdd201e486c9l, + 0x20477abf42ff9297l }, + 0 }, + /* 129 */ + { { 0x2f75173c18d65dbfl,0x77bf940e339edad8l,0x7022d26bdcf1001cl, + 0xac66409ac77396b6l }, + { 0x8b0bb36fc6261cc3l,0x213f7bc9190e7e90l,0x6541cebaa45e6c10l, + 0xce8e6975cc122f85l }, + 0 }, + /* 130 */ + { { 0x0f121b41bc0a67d2l,0x62d4760a444d248al,0x0e044f1d659b4737l, + 0x08fde365250bb4a8l }, + { 0xaceec3da848bf287l,0xc2a62182d3369d6el,0x3582dfdc92449482l, + 0x2f7e2fd2565d6cd7l }, + 0 }, + /* 131 */ + { { 0xae4b92dbc3770fa7l,0x095e8d5c379043f9l,0x54f34e9d17761171l, + 0xc65be92e907702ael }, + { 0x2758a303f6fd0a40l,0xe7d822e3bcce784bl,0x7ae4f5854f9767bfl, + 0x4bff8e47d1193b3al }, + 0 }, + /* 132 */ + { { 0xcd41d21f00ff1480l,0x2ab8fb7d0754db16l,0xac81d2efbbe0f3eal, + 0x3e4e4ae65772967dl }, + { 0x7e18f36d3c5303e6l,0x3bd9994b92262397l,0x9ed70e261324c3c0l, + 0x5388aefd58ec6028l }, + 0 }, + /* 133 */ + { { 0xad1317eb5e5d7713l,0x09b985ee75de49dal,0x32f5bc4fc74fb261l, + 0x5cf908d14f75be0el }, + { 0x760435108e657b12l,0xbfd421a5b96ed9e6l,0x0e29f51f8970ccc2l, + 0xa698ba4060f00ce2l }, + 0 }, + /* 134 */ + { { 0x73db1686ef748fecl,0xe6e755a27e9d2cf9l,0x630b6544ce265effl, + 0xb142ef8a7aebad8dl }, + { 0xad31af9f17d5770al,0x66af3b672cb3412fl,0x6bd60d1bdf3359del, + 0xd1896a9658515075l }, + 0 }, + /* 135 */ + { { 0xec5957ab33c41c08l,0x87de94ac5468e2e1l,0x18816b73ac472f6cl, + 0x267b0e0b7981da39l }, + { 0x6e554e5d8e62b988l,0xd8ddc755116d21e7l,0x4610faf03d2a6f99l, + 0xb54e287aa1119393l }, + 0 }, + /* 136 */ + { { 0x0a0122b5178a876bl,0x51ff96ff085104b4l,0x050b31ab14f29f76l, + 0x84abb28b5f87d4e6l }, + { 0xd5ed439f8270790al,0x2d6cb59d85e3f46bl,0x75f55c1b6c1e2212l, + 0xe5436f6717655640l }, + 0 }, + /* 137 */ + { { 0x53f9025e2286e8d5l,0x353c95b4864453bel,0xd832f5bde408e3a0l, + 0x0404f68b5b9ce99el }, + { 0xcad33bdea781e8e5l,0x3cdf5018163c2f5bl,0x575769600119caa3l, + 0x3a4263df0ac1c701l }, + 0 }, + /* 138 */ + { { 0xc2965ecc9aeb596dl,0x01ea03e7023c92b4l,0x4704b4b62e013961l, + 0x0ca8fd3f905ea367l }, + { 0x92523a42551b2b61l,0x1eb7a89c390fcd06l,0xe7f1d2be0392a63el, + 0x96dca2644ddb0c33l }, + 0 }, + /* 139 */ + { { 0x203bb43a387510afl,0x846feaa8a9a36a01l,0xd23a57702f950378l, + 0x4363e2123aad59dcl }, + { 0xca43a1c740246a47l,0xb362b8d2e55dd24dl,0xf9b086045d8faf96l, + 0x840e115cd8bb98c4l }, + 0 }, + /* 140 */ + { { 0xf12205e21023e8a7l,0xc808a8cdd8dc7a0bl,0xe292a272163a5ddfl, + 0x5e0d6abd30ded6d4l }, + { 0x07a721c27cfc0f64l,0x42eec01d0e55ed88l,0x26a7bef91d1f9db2l, + 0x7dea48f42945a25al }, + 0 }, + /* 141 */ + { { 0xabdf6f1ce5060a81l,0xe79f9c72f8f95615l,0xcfd36c5406ac268bl, + 0xabc2a2beebfd16d1l }, + { 0x8ac66f91d3e2eac7l,0x6f10ba63d2dd0466l,0x6790e3770282d31bl, + 0x4ea353946c7eefc1l }, + 0 }, + /* 142 */ + { { 0xed8a2f8d5266309dl,0x0a51c6c081945a3el,0xcecaf45a578c5dc1l, + 0x3a76e6891c94ffc3l }, + { 0x9aace8a47d7b0d0fl,0x963ace968f584a5fl,0x51a30c724e697fbel, + 0x8212a10a465e6464l }, + 0 }, + /* 143 */ + { { 0xef7c61c3cfab8caal,0x18eb8e840e142390l,0xcd1dff677e9733cal, + 0xaa7cab71599cb164l }, + { 0x02fc9273bc837bd1l,0xc06407d0c36af5d7l,0x17621292f423da49l, + 0x40e38073fe0617c3l }, + 0 }, + /* 144 */ + { { 0xf4f80824a7bf9b7cl,0x365d23203fbe30d0l,0xbfbe532097cf9ce3l, + 0xe3604700b3055526l }, + { 0x4dcb99116cc6c2c7l,0x72683708ba4cbee6l,0xdcded434637ad9ecl, + 0x6542d677a3dee15fl }, + 0 }, + /* 145 */ + { { 0x3f32b6d07b6c377al,0x6cb03847903448bel,0xd6fdd3a820da8af7l, + 0xa6534aee09bb6f21l }, + { 0x30a1780d1035facfl,0x35e55a339dcb47e6l,0x6ea50fe1c447f393l, + 0xf3cb672fdc9aef22l }, + 0 }, + /* 146 */ + { { 0xeb3719fe3b55fd83l,0xe0d7a46c875ddd10l,0x33ac9fa905cea784l, + 0x7cafaa2eaae870e7l }, + { 0x9b814d041d53b338l,0xe0acc0a0ef87e6c6l,0xfb93d10811672b0fl, + 0x0aab13c1b9bd522el }, + 0 }, + /* 147 */ + { { 0xddcce278d2681297l,0xcb350eb1b509546al,0x2dc431737661aaf2l, + 0x4b91a602847012e9l }, + { 0xdcff109572f8ddcfl,0x08ebf61e9a911af4l,0x48f4360ac372430el, + 0x49534c5372321cabl }, + 0 }, + /* 148 */ + { { 0x83df7d71f07b7e9dl,0xa478efa313cd516fl,0x78ef264b6c047ee3l, + 0xcaf46c4fd65ac5eel }, + { 0xa04d0c7792aa8266l,0xedf45466913684bbl,0x56e65168ae4b16b0l, + 0x14ce9e5704c6770fl }, + 0 }, + /* 149 */ + { { 0x99445e3e965e8f91l,0xd3aca1bacb0f2492l,0xd31cc70f90c8a0a0l, + 0x1bb708a53e4c9a71l }, + { 0xd5ca9e69558bdd7al,0x734a0508018a26b1l,0xb093aa714c9cf1ecl, + 0xf9d126f2da300102l }, + 0 }, + /* 150 */ + { { 0x749bca7aaff9563el,0xdd077afeb49914a0l,0xe27a0311bf5f1671l, + 0x807afcb9729ecc69l }, + { 0x7f8a9337c9b08b77l,0x86c3a785443c7e38l,0x85fafa59476fd8bal, + 0x751adcd16568cd8cl }, + 0 }, + /* 151 */ + { { 0x8aea38b410715c0dl,0xd113ea718f7697f7l,0x665eab1493fbf06dl, + 0x29ec44682537743fl }, + { 0x3d94719cb50bebbcl,0x399ee5bfe4505422l,0x90cd5b3a8d2dedb1l, + 0xff9370e392a4077dl }, + 0 }, + /* 152 */ + { { 0x59a2d69bc6b75b65l,0x4188f8d5266651c5l,0x28a9f33e3de9d7d2l, + 0x9776478ba2a9d01al }, + { 0x8852622d929af2c7l,0x334f5d6d4e690923l,0xce6cc7e5a89a51e9l, + 0x74a6313fac2f82fal }, + 0 }, + /* 153 */ + { { 0xb2f4dfddb75f079cl,0x85b07c9518e36fbbl,0x1b6cfcf0e7cd36ddl, + 0xab75be150ff4863dl }, + { 0x81b367c0173fc9b7l,0xb90a7420d2594fd0l,0x15fdbf03c4091236l, + 0x4ebeac2e0b4459f6l }, + 0 }, + /* 154 */ + { { 0xeb6c5fe75c9f2c53l,0xd25220118eae9411l,0xc8887633f95ac5d8l, + 0xdf99887b2c1baffcl }, + { 0xbb78eed2850aaecbl,0x9d49181b01d6a272l,0x978dd511b1cdbcacl, + 0x27b040a7779f4058l }, + 0 }, + /* 155 */ + { { 0x90405db7f73b2eb2l,0xe0df85088e1b2118l,0x501b71525962327el, + 0xb393dd37e4cfa3f5l }, + { 0xa1230e7b3fd75165l,0xd66344c2bcd33554l,0x6c36f1be0f7b5022l, + 0x09588c12d0463419l }, + 0 }, + /* 156 */ + { { 0xe086093f02601c3bl,0xfb0252f8cf5c335fl,0x955cf280894aff28l, + 0x81c879a9db9f648bl }, + { 0x040e687cc6f56c51l,0xfed471693f17618cl,0x44f88a419059353bl, + 0xfa0d48f55fc11bc4l }, + 0 }, + /* 157 */ + { { 0xbc6e1c9de1608e4dl,0x010dda113582822cl,0xf6b7ddc1157ec2d7l, + 0x8ea0e156b6a367d6l }, + { 0xa354e02f2383b3b4l,0x69966b943f01f53cl,0x4ff6632b2de03ca5l, + 0x3f5ab924fa00b5acl }, + 0 }, + /* 158 */ + { { 0x337bb0d959739efbl,0xc751b0f4e7ebec0dl,0x2da52dd6411a67d1l, + 0x8bc768872b74256el }, + { 0xa5be3b7282d3d253l,0xa9f679a1f58d779fl,0xa1cac168e16767bbl, + 0xb386f19060fcf34fl }, + 0 }, + /* 159 */ + { { 0x31f3c1352fedcfc2l,0x5396bf6262f8af0dl,0x9a02b4eae57288c2l, + 0x4cb460f71b069c4dl }, + { 0xae67b4d35b8095eal,0x92bbf8596fc07603l,0xe1475f66b614a165l, + 0x52c0d50895ef5223l }, + 0 }, + /* 160 */ + { { 0x231c210e15339848l,0xe87a28e870778c8dl,0x9d1de6616956e170l, + 0x4ac3c9382bb09c0bl }, + { 0x19be05516998987dl,0x8b2376c4ae09f4d6l,0x1de0b7651a3f933dl, + 0x380d94c7e39705f4l }, + 0 }, + /* 161 */ + { { 0x01a355aa81542e75l,0x96c724a1ee01b9b7l,0x6b3a2977624d7087l, + 0x2ce3e171de2637afl }, + { 0xcfefeb49f5d5bc1al,0xa655607e2777e2b5l,0x4feaac2f9513756cl, + 0x2e6cd8520b624e4dl }, + 0 }, + /* 162 */ + { { 0x3685954b8c31c31dl,0x68533d005bf21a0cl,0x0bd7626e75c79ec9l, + 0xca17754742c69d54l }, + { 0xcc6edafff6d2dbb2l,0xfd0d8cbd174a9d18l,0x875e8793aa4578e8l, + 0xa976a7139cab2ce6l }, + 0 }, + /* 163 */ + { { 0x0a651f1b93fb353dl,0xd75cab8b57fcfa72l,0xaa88cfa731b15281l, + 0x8720a7170a1f4999l }, + { 0x8c3e8d37693e1b90l,0xd345dc0b16f6dfc3l,0x8ea8d00ab52a8742l, + 0x9719ef29c769893cl }, + 0 }, + /* 164 */ + { { 0x820eed8d58e35909l,0x9366d8dc33ddc116l,0xd7f999d06e205026l, + 0xa5072976e15704c1l }, + { 0x002a37eac4e70b2el,0x84dcf6576890aa8al,0xcd71bf18645b2a5cl, + 0x99389c9df7b77725l }, + 0 }, + /* 165 */ + { { 0x238c08f27ada7a4bl,0x3abe9d03fd389366l,0x6b672e89766f512cl, + 0xa88806aa202c82e4l }, + { 0x6602044ad380184el,0xa8cb78c4126a8b85l,0x79d670c0ad844f17l, + 0x0043bffb4738dcfel }, + 0 }, + /* 166 */ + { { 0x8d59b5dc36d5192el,0xacf885d34590b2afl,0x83566d0a11601781l, + 0x52f3ef01ba6c4866l }, + { 0x3986732a0edcb64dl,0x0a482c238068379fl,0x16cbe5fa7040f309l, + 0x3296bd899ef27e75l }, + 0 }, + /* 167 */ + { { 0x476aba89454d81d7l,0x9eade7ef51eb9b3cl,0x619a21cd81c57986l, + 0x3b90febfaee571e9l }, + { 0x9393023e5496f7cbl,0x55be41d87fb51bc4l,0x03f1dd4899beb5cel, + 0x6e88069d9f810b18l }, + 0 }, + /* 168 */ + { { 0xce37ab11b43ea1dbl,0x0a7ff1a95259d292l,0x851b02218f84f186l, + 0xa7222beadefaad13l }, + { 0xa2ac78ec2b0a9144l,0x5a024051f2fa59c5l,0x91d1eca56147ce38l, + 0xbe94d523bc2ac690l }, + 0 }, + /* 169 */ + { { 0x72f4945e0b226ce7l,0xb8afd747967e8b70l,0xedea46f185a6c63el, + 0x7782defe9be8c766l }, + { 0x760d2aa43db38626l,0x460ae78776f67ad1l,0x341b86fc54499cdbl, + 0x03838567a2892e4bl }, + 0 }, + /* 170 */ + { { 0x2d8daefd79ec1a0fl,0x3bbcd6fdceb39c97l,0xf5575ffc58f61a95l, + 0xdbd986c4adf7b420l }, + { 0x81aa881415f39eb7l,0x6ee2fcf5b98d976cl,0x5465475dcf2f717dl, + 0x8e24d3c46860bbd0l }, + 0 }, + /* 171 */ + { { 0x749d8e549a587390l,0x12bb194f0cbec588l,0x46e07da4b25983c6l, + 0x541a99c4407bafc8l }, + { 0xdb241692624c8842l,0x6044c12ad86c05ffl,0xc59d14b44f7fcf62l, + 0xc0092c49f57d35d1l }, + 0 }, + /* 172 */ + { { 0xd3cc75c3df2e61efl,0x7e8841c82e1b35cal,0xc62d30d1909f29f4l, + 0x75e406347286944dl }, + { 0xe7d41fc5bbc237d0l,0xc9537bf0ec4f01c9l,0x91c51a16282bd534l, + 0x5b7cb658c7848586l }, + 0 }, + /* 173 */ + { { 0x964a70848a28ead1l,0x802dc508fd3b47f6l,0x9ae4bfd1767e5b39l, + 0x7ae13eba8df097a1l }, + { 0xfd216ef8eadd384el,0x0361a2d9b6b2ff06l,0x204b98784bcdb5f3l, + 0x787d8074e2a8e3fdl }, + 0 }, + /* 174 */ + { { 0xc5e25d6b757fbb1cl,0xe47bddb2ca201debl,0x4a55e9a36d2233ffl, + 0x5c2228199ef28484l }, + { 0x773d4a8588315250l,0x21b21a2b827097c1l,0xab7c4ea1def5d33fl, + 0xe45d37abbaf0f2b0l }, + 0 }, + /* 175 */ + { { 0xd2df1e3428511c8al,0xebb229c8bdca6cd3l,0x578a71a7627c39a7l, + 0xed7bc12284dfb9d3l }, + { 0xcf22a6df93dea561l,0x5443f18dd48f0ed1l,0xd8b861405bad23e8l, + 0xaac97cc945ca6d27l }, + 0 }, + /* 176 */ + { { 0xeb54ea74a16bd00al,0xd839e9adf5c0bcc1l,0x092bb7f11f9bfc06l, + 0x318f97b31163dc4el }, + { 0xecc0c5bec30d7138l,0x44e8df23abc30220l,0x2bb7972fb0223606l, + 0xfa41faa19a84ff4dl }, + 0 }, + /* 177 */ + { { 0x4402d974a6642269l,0xc81814ce9bb783bdl,0x398d38e47941e60bl, + 0x38bb6b2c1d26e9e2l }, + { 0xc64e4a256a577f87l,0x8b52d253dc11fe1cl,0xff336abf62280728l, + 0x94dd0905ce7601a5l }, + 0 }, + /* 178 */ + { { 0x156cf7dcde93f92al,0xa01333cb89b5f315l,0x02404df9c995e750l, + 0x92077867d25c2ae9l }, + { 0xe2471e010bf39d44l,0x5f2c902096bb53d7l,0x4c44b7b35c9c3d8fl, + 0x81e8428bd29beb51l }, + 0 }, + /* 179 */ + { { 0x6dd9c2bac477199fl,0x8cb8eeee6b5ecdd9l,0x8af7db3fee40fd0el, + 0x1b94ab62dbbfa4b1l }, + { 0x44f0d8b3ce47f143l,0x51e623fc63f46163l,0xf18f270fcc599383l, + 0x06a38e28055590eel }, + 0 }, + /* 180 */ + { { 0x2e5b0139b3355b49l,0x20e26560b4ebf99bl,0xc08ffa6bd269f3dcl, + 0xa7b36c2083d9d4f8l }, + { 0x64d15c3a1b3e8830l,0xd5fceae1a89f9c0bl,0xcfeee4a2e2d16930l, + 0xbe54c6b4a2822a20l }, + 0 }, + /* 181 */ + { { 0xd6cdb3df8d91167cl,0x517c3f79e7a6625el,0x7105648f346ac7f4l, + 0xbf30a5abeae022bbl }, + { 0x8e7785be93828a68l,0x5161c3327f3ef036l,0xe11b5feb592146b2l, + 0xd1c820de2732d13al }, + 0 }, + /* 182 */ + { { 0x043e13479038b363l,0x58c11f546b05e519l,0x4fe57abe6026cad1l, + 0xb7d17bed68a18da3l }, + { 0x44ca5891e29c2559l,0x4f7a03765bfffd84l,0x498de4af74e46948l, + 0x3997fd5e6412cc64l }, + 0 }, + /* 183 */ + { { 0xf20746828bd61507l,0x29e132d534a64d2al,0xffeddfb08a8a15e3l, + 0x0eeb89293c6c13e8l }, + { 0xe9b69a3ea7e259f8l,0xce1db7e6d13e7e67l,0x277318f6ad1fa685l, + 0x228916f8c922b6efl }, + 0 }, + /* 184 */ + { { 0x959ae25b0a12ab5bl,0xcc11171f957bc136l,0x8058429ed16e2b0cl, + 0xec05ad1d6e93097el }, + { 0x157ba5beac3f3708l,0x31baf93530b59d77l,0x47b55237118234e5l, + 0x7d3141567ff11b37l }, + 0 }, + /* 185 */ + { { 0x7bd9c05cf6dfefabl,0xbe2f2268dcb37707l,0xe53ead973a38bb95l, + 0xe9ce66fc9bc1d7a3l }, + { 0x75aa15766f6a02a1l,0x38c087df60e600edl,0xf8947f3468cdc1b9l, + 0xd9650b0172280651l }, + 0 }, + /* 186 */ + { { 0x504b4c4a5a057e60l,0xcbccc3be8def25e4l,0xa635320817c1ccbdl, + 0x14d6699a804eb7a2l }, + { 0x2c8a8415db1f411al,0x09fbaf0bf80d769cl,0xb4deef901c2f77adl, + 0x6f4c68410d43598al }, + 0 }, + /* 187 */ + { { 0x8726df4e96c24a96l,0x534dbc85fcbd99a3l,0x3c466ef28b2ae30al, + 0x4c4350fd61189abbl }, + { 0x2967f716f855b8dal,0x41a42394463c38a1l,0xc37e1413eae93343l, + 0xa726d2425a3118b5l }, + 0 }, + /* 188 */ + { { 0xdae6b3ee948c1086l,0xf1de503dcbd3a2e1l,0x3f35ed3f03d022f3l, + 0x13639e82cc6cf392l }, + { 0x9ac938fbcdafaa86l,0xf45bc5fb2654a258l,0x1963b26e45051329l, + 0xca9365e1c1a335a3l }, + 0 }, + /* 189 */ + { { 0x3615ac754c3b2d20l,0x742a5417904e241bl,0xb08521c4cc9d071dl, + 0x9ce29c34970b72a5l }, + { 0x8cc81f736d3e0ad6l,0x8060da9ef2f8434cl,0x35ed1d1a6ce862d9l, + 0x48c4abd7ab42af98l }, + 0 }, + /* 190 */ + { { 0xd221b0cc40c7485al,0xead455bbe5274dbfl,0x493c76989263d2e8l, + 0x78017c32f67b33cbl }, + { 0xb9d35769930cb5eel,0xc0d14e940c408ed2l,0xf8b7bf55272f1a4dl, + 0x53cd0454de5c1c04l }, + 0 }, + /* 191 */ + { { 0xbcd585fa5d28ccacl,0x5f823e56005b746el,0x7c79f0a1cd0123aal, + 0xeea465c1d3d7fa8fl }, + { 0x7810659f0551803bl,0x6c0b599f7ce6af70l,0x4195a77029288e70l, + 0x1b6e42a47ae69193l }, + 0 }, + /* 192 */ + { { 0x2e80937cf67d04c3l,0x1e312be289eeb811l,0x56b5d88792594d60l, + 0x0224da14187fbd3dl }, + { 0x87abb8630c5fe36fl,0x580f3c604ef51f5fl,0x964fb1bfb3b429ecl, + 0x60838ef042bfff33l }, + 0 }, + /* 193 */ + { { 0x432cb2f27e0bbe99l,0x7bda44f304aa39eel,0x5f497c7a9fa93903l, + 0x636eb2022d331643l }, + { 0xfcfd0e6193ae00aal,0x875a00fe31ae6d2fl,0xf43658a29f93901cl, + 0x8844eeb639218bacl }, + 0 }, + /* 194 */ + { { 0x114171d26b3bae58l,0x7db3df7117e39f3el,0xcd37bc7f81a8eadal, + 0x27ba83dc51fb789el }, + { 0xa7df439ffbf54de5l,0x7277030bb5fe1a71l,0x42ee8e35db297a48l, + 0xadb62d3487f3a4abl }, + 0 }, + /* 195 */ + { { 0x9b1168a2a175df2al,0x082aa04f618c32e9l,0xc9e4f2e7146b0916l, + 0xb990fd7675e7c8b2l }, + { 0x0829d96b4df37313l,0x1c205579d0b40789l,0x66c9ae4a78087711l, + 0x81707ef94d10d18dl }, + 0 }, + /* 196 */ + { { 0x97d7cab203d6ff96l,0x5b851bfc0d843360l,0x268823c4d042db4bl, + 0x3792daead5a8aa5cl }, + { 0x52818865941afa0bl,0xf3e9e74142d83671l,0x17c825275be4e0a7l, + 0x5abd635e94b001bal }, + 0 }, + /* 197 */ + { { 0x727fa84e0ac4927cl,0xe3886035a7c8cf23l,0xa4bcd5ea4adca0dfl, + 0x5995bf21846ab610l }, + { 0xe90f860b829dfa33l,0xcaafe2ae958fc18bl,0x9b3baf4478630366l, + 0x44c32ca2d483411el }, + 0 }, + /* 198 */ + { { 0xa74a97f1e40ed80cl,0x5f938cb131d2ca82l,0x53f2124b7c2d6ad9l, + 0x1f2162fb8082a54cl }, + { 0x7e467cc5720b173el,0x40e8a666085f12f9l,0x8cebc20e4c9d65dcl, + 0x8f1d402bc3e907c9l }, + 0 }, + /* 199 */ + { { 0x4f592f9cfbc4058al,0xb15e14b6292f5670l,0xc55cfe37bc1d8c57l, + 0xb1980f43926edbf9l }, + { 0x98c33e0932c76b09l,0x1df5279d33b07f78l,0x6f08ead4863bb461l, + 0x2828ad9b37448e45l }, + 0 }, + /* 200 */ + { { 0x696722c4c4cf4ac5l,0xf5ac1a3fdde64afbl,0x0551baa2e0890832l, + 0x4973f1275a14b390l }, + { 0xe59d8335322eac5dl,0x5e07eef50bd9b568l,0xab36720fa2588393l, + 0x6dac8ed0db168ac7l }, + 0 }, + /* 201 */ + { { 0xf7b545aeeda835efl,0x4aa113d21d10ed51l,0x035a65e013741b09l, + 0x4b23ef5920b9de4cl }, + { 0xe82bb6803c4c7341l,0xd457706d3f58bc37l,0x73527863a51e3ee8l, + 0x4dd71534ddf49a4el }, + 0 }, + /* 202 */ + { { 0xbf94467295476cd9l,0x648d072fe31a725bl,0x1441c8b8fc4b67e0l, + 0xfd3170002f4a4dbbl }, + { 0x1cb43ff48995d0e1l,0x76e695d10ef729aal,0xe0d5f97641798982l, + 0x14fac58c9569f365l }, + 0 }, + /* 203 */ + { { 0xad9a0065f312ae18l,0x51958dc0fcc93fc9l,0xd9a142408a7d2846l, + 0xed7c765136abda50l }, + { 0x46270f1a25d4abbcl,0x9b5dd8f3f1a113eal,0xc609b0755b51952fl, + 0xfefcb7f74d2e9f53l }, + 0 }, + /* 204 */ + { { 0xbd09497aba119185l,0xd54e8c30aac45ba4l,0x492479deaa521179l, + 0x1801a57e87e0d80bl }, + { 0x073d3f8dfcafffb0l,0x6cf33c0bae255240l,0x781d763b5b5fdfbcl, + 0x9f8fc11e1ead1064l }, + 0 }, + /* 205 */ + { { 0x1583a1715e69544cl,0x0eaf8567f04b7813l,0x1e22a8fd278a4c32l, + 0xa9d3809d3d3a69a9l }, + { 0x936c2c2c59a2da3bl,0x38ccbcf61895c847l,0x5e65244e63d50869l, + 0x3006b9aee1178ef7l }, + 0 }, + /* 206 */ + { { 0x0bb1f2b0c9eead28l,0x7eef635d89f4dfbcl,0x074757fdb2ce8939l, + 0x0ab85fd745f8f761l }, + { 0xecda7c933e5b4549l,0x4be2bb5c97922f21l,0x261a1274b43b8040l, + 0xb122d67511e942c2l }, + 0 }, + /* 207 */ + { { 0x3be607be66a5ae7al,0x01e703fa76adcbe3l,0xaf9043014eb6e5c5l, + 0x9f599dc1097dbaecl }, + { 0x6d75b7180ff250edl,0x8eb91574349a20dcl,0x425605a410b227a3l, + 0x7d5528e08a294b78l }, + 0 }, + /* 208 */ + { { 0xf0f58f6620c26defl,0x025585ea582b2d1el,0xfbe7d79b01ce3881l, + 0x28ccea01303f1730l }, + { 0xd1dabcd179644ba5l,0x1fc643e806fff0b8l,0xa60a76fc66b3e17bl, + 0xc18baf48a1d013bfl }, + 0 }, + /* 209 */ + { { 0x34e638c85dc4216dl,0x00c01067206142acl,0xd453a17195f5064al, + 0x9def809db7a9596bl }, + { 0x41e8642e67ab8d2cl,0xb42404336237a2b6l,0x7d506a6d64c4218bl, + 0x0357f8b068808ce5l }, + 0 }, + /* 210 */ + { { 0x8e9dbe644cd2cc88l,0xcc61c28df0b8f39dl,0x4a309874cd30a0c8l, + 0xe4a01add1b489887l }, + { 0x2ed1eeacf57cd8f9l,0x1b767d3ebd594c48l,0xa7295c717bd2f787l, + 0x466d7d79ce10cc30l }, + 0 }, + /* 211 */ + { { 0x47d318929dada2c7l,0x4fa0a6c38f9aa27dl,0x90e4fd28820a59e1l, + 0xc672a522451ead1al }, + { 0x30607cc85d86b655l,0xf0235d3bf9ad4af1l,0x99a08680571172a6l, + 0x5e3d64faf2a67513l }, + 0 }, + /* 212 */ + { { 0xaa6410c79b3b4416l,0xcd8fcf85eab26d99l,0x5ebff74adb656a74l, + 0x6c8a7a95eb8e42fcl }, + { 0x10c60ba7b02a63bdl,0x6b2f23038b8f0047l,0x8c6c3738312d90b0l, + 0x348ae422ad82ca91l }, + 0 }, + /* 213 */ + { { 0x7f4746635ccda2fbl,0x22accaa18e0726d2l,0x85adf782492b1f20l, + 0xc1074de0d9ef2d2el }, + { 0xfcf3ce44ae9a65b3l,0xfd71e4ac05d7151bl,0xd4711f50ce6a9788l, + 0xfbadfbdbc9e54ffcl }, + 0 }, + /* 214 */ + { { 0x1713f1cd20a99363l,0xb915658f6cf22775l,0x968175cd24d359b2l, + 0xb7f976b483716fcdl }, + { 0x5758e24d5d6dbf74l,0x8d23bafd71c3af36l,0x48f477600243dfe3l, + 0xf4d41b2ecafcc805l }, + 0 }, + /* 215 */ + { { 0x51f1cf28fdabd48dl,0xce81be3632c078a4l,0x6ace2974117146e9l, + 0x180824eae0160f10l }, + { 0x0387698b66e58358l,0x63568752ce6ca358l,0x82380e345e41e6c5l, + 0x67e5f63983cf6d25l }, + 0 }, + /* 216 */ + { { 0xf89ccb8dcf4899efl,0x949015f09ebb44c0l,0x546f9276b2598ec9l, + 0x9fef789a04c11fc6l }, + { 0x6d367ecf53d2a071l,0xb10e1a7fa4519b09l,0xca6b3fb0611e2eefl, + 0xbc80c181a99c4e20l }, + 0 }, + /* 217 */ + { { 0x972536f8e5eb82e6l,0x1a484fc7f56cb920l,0xc78e217150b5da5el, + 0x49270e629f8cdf10l }, + { 0x1a39b7bbea6b50adl,0x9a0284c1a2388ffcl,0x5403eb178107197bl, + 0xd2ee52f961372f7fl }, + 0 }, + /* 218 */ + { { 0xd37cd28588e0362al,0x442fa8a78fa5d94dl,0xaff836e5a434a526l, + 0xdfb478bee5abb733l }, + { 0xa91f1ce7673eede6l,0xa5390ad42b5b2f04l,0x5e66f7bf5530da2fl, + 0xd9a140b408df473al }, + 0 }, + /* 219 */ + { { 0x0e0221b56e8ea498l,0x623478293563ee09l,0xe06b8391335d2adel, + 0x760c058d623f4b1al }, + { 0x0b89b58cc198aa79l,0xf74890d2f07aba7fl,0x4e204110fde2556al, + 0x7141982d8f190409l }, + 0 }, + /* 220 */ + { { 0x6f0a0e334d4b0f45l,0xd9280b38392a94e1l,0x3af324c6b3c61d5el, + 0x3af9d1ce89d54e47l }, + { 0xfd8f798120930371l,0xeda2664c21c17097l,0x0e9545dcdc42309bl, + 0xb1f815c373957dd6l }, + 0 }, + /* 221 */ + { { 0x84faa78e89fec44al,0xc8c2ae473caa4cafl,0x691c807dc1b6a624l, + 0xa41aed141543f052l }, + { 0x424353997d5ffe04l,0x8bacb2df625b6e20l,0x85d660be87817775l, + 0xd6e9c1dd86fb60efl }, + 0 }, + /* 222 */ + { { 0x3aa2e97ec6853264l,0x771533b7e2304a0bl,0x1b912bb7b8eae9bel, + 0x9c9c6e10ae9bf8c2l }, + { 0xa2309a59e030b74cl,0x4ed7494d6a631e90l,0x89f44b23a49b79f2l, + 0x566bd59640fa61b6l }, + 0 }, + /* 223 */ + { { 0x066c0118c18061f3l,0x190b25d37c83fc70l,0xf05fc8e027273245l, + 0xcf2c7390f525345el }, + { 0xa09bceb410eb30cfl,0xcfd2ebba0d77703al,0xe842c43a150ff255l, + 0x02f517558aa20979l }, + 0 }, + /* 224 */ + { { 0x396ef794addb7d07l,0x0b4fc74224455500l,0xfaff8eacc78aa3cel, + 0x14e9ada5e8d4d97dl }, + { 0xdaa480a12f7079e2l,0x45baa3cde4b0800el,0x01765e2d7838157dl, + 0xa0ad4fab8e9d9ae8l }, + 0 }, + /* 225 */ + { { 0x0bfb76214a653618l,0x1872813c31eaaa5fl,0x1553e73744949d5el, + 0xbcd530b86e56ed1el }, + { 0x169be85332e9c47bl,0xdc2776feb50059abl,0xcdba9761192bfbb4l, + 0x909283cf6979341dl }, + 0 }, + /* 226 */ + { { 0x67b0032476e81a13l,0x9bee1a9962171239l,0x08ed361bd32e19d6l, + 0x35eeb7c9ace1549al }, + { 0x1280ae5a7e4e5bdcl,0x2dcd2cd3b6ceec6el,0x52e4224c6e266bc1l, + 0x9a8b2cf4448ae864l }, + 0 }, + /* 227 */ + { { 0xf6471bf209d03b59l,0xc90e62a3b65af2abl,0xff7ff168ebd5eec9l, + 0x6bdb60f4d4491379l }, + { 0xdadafebc8a55bc30l,0xc79ead1610097fe0l,0x42e197414c1e3bddl, + 0x01ec3cfd94ba08a9l }, + 0 }, + /* 228 */ + { { 0xba6277ebdc9485c2l,0x48cc9a7922fb10c7l,0x4f61d60f70a28d8al, + 0xd1acb1c0475464f6l }, + { 0xd26902b126f36612l,0x59c3a44ee0618d8bl,0x4df8a813308357eel, + 0x7dcd079d405626c2l }, + 0 }, + /* 229 */ + { { 0x5ce7d4d3f05a4b48l,0xadcd295237230772l,0xd18f7971812a915al, + 0x0bf53589377d19b8l }, + { 0x35ecd95a6c68ea73l,0xc7f3bbca823a584dl,0x9fb674c6f473a723l, + 0xd28be4d9e16686fcl }, + 0 }, + /* 230 */ + { { 0x5d2b990638fa8e4bl,0x559f186e893fd8fcl,0x3a6de2aa436fb6fcl, + 0xd76007aa510f88cel }, + { 0x2d10aab6523a4988l,0xb455cf4474dd0273l,0x7f467082a3407278l, + 0xf2b52f68b303bb01l }, + 0 }, + /* 231 */ + { { 0x0d57eafa9835b4cal,0x2d2232fcbb669cbcl,0x8eeeb680c6643198l, + 0xd8dbe98ecc5aed3al }, + { 0xcba9be3fc5a02709l,0x30be68e5f5ba1fa8l,0xfebd43cdf10ea852l, + 0xe01593a3ee559705l }, + 0 }, + /* 232 */ + { { 0xd3e5af50ea75a0a6l,0x512226ac57858033l,0x6fe6d50fd0176406l, + 0xafec07b1aeb8ef06l }, + { 0x7fb9956780bb0a31l,0x6f1af3cc37309aael,0x9153a15a01abf389l, + 0xa71b93546e2dbfddl }, + 0 }, + /* 233 */ + { { 0xbf8e12e018f593d2l,0xd1a90428a078122bl,0x150505db0ba4f2adl, + 0x53a2005c628523d9l }, + { 0x07c8b639e7f2b935l,0x2bff975ac182961al,0x86bceea77518ca2cl, + 0xbf47d19b3d588e3dl }, + 0 }, + /* 234 */ + { { 0x672967a7dd7665d5l,0x4e3030572f2f4de5l,0x144005ae80d4903fl, + 0x001c2c7f39c9a1b6l }, + { 0x143a801469efc6d6l,0xc810bdaa7bc7a724l,0x5f65670ba78150a4l, + 0xfdadf8e786ffb99bl }, + 0 }, + /* 235 */ + { { 0xfd38cb88ffc00785l,0x77fa75913b48eb67l,0x0454d055bf368fbcl, + 0x3a838e4d5aa43c94l }, + { 0x561663293e97bb9al,0x9eb93363441d94d9l,0x515591a60adb2a83l, + 0x3cdb8257873e1da3l }, + 0 }, + /* 236 */ + { { 0x137140a97de77eabl,0xf7e1c50d41648109l,0x762dcad2ceb1d0dfl, + 0x5a60cc89f1f57fbal }, + { 0x80b3638240d45673l,0x1b82be195913c655l,0x057284b8dd64b741l, + 0x922ff56fdbfd8fc0l }, + 0 }, + /* 237 */ + { { 0x1b265deec9a129a1l,0xa5b1ce57cc284e04l,0x04380c46cebfbe3cl, + 0x72919a7df6c5cd62l }, + { 0x298f453a8fb90f9al,0xd719c00b88e4031bl,0xe32c0e77796f1856l, + 0x5e7917803624089al }, + 0 }, + /* 238 */ + { { 0x5c16ec557f63cdfbl,0x8e6a3571f1cae4fdl,0xfce26bea560597cal, + 0x4e0a5371e24c2fabl }, + { 0x276a40d3a5765357l,0x3c89af440d73a2b4l,0xb8f370ae41d11a32l, + 0xf5ff7818d56604eel }, + 0 }, + /* 239 */ + { { 0xfbf3e3fe1a09df21l,0x26d5d28ee66e8e47l,0x2096bd0a29c89015l, + 0xe41df0e9533f5e64l }, + { 0x305fda40b3ba9e3fl,0xf2340ceb2604d895l,0x0866e1927f0367c7l, + 0x8edd7d6eac4f155fl }, + 0 }, + /* 240 */ + { { 0xc9a1dc0e0bfc8ff3l,0x14efd82be936f42fl,0x67016f7ccca381efl, + 0x1432c1caed8aee96l }, + { 0xec68482970b23c26l,0xa64fe8730735b273l,0xe389f6e5eaef0f5al, + 0xcaef480b5ac8d2c6l }, + 0 }, + /* 241 */ + { { 0x5245c97875315922l,0xd82951713063cca5l,0xf3ce60d0b64ef2cbl, + 0xd0ba177e8efae236l }, + { 0x53a9ae8fb1b3af60l,0x1a796ae53d2da20el,0x01d63605df9eef28l, + 0xf31c957c1c54ae16l }, + 0 }, + /* 242 */ + { { 0xc0f58d5249cc4597l,0xdc5015b0bae0a028l,0xefc5fc55734a814al, + 0x013404cb96e17c3al }, + { 0xb29e2585c9a824bfl,0xd593185e001eaed7l,0x8d6ee68261ef68acl, + 0x6f377c4b91933e6cl }, + 0 }, + /* 243 */ + { { 0x9f93bad1a8333fd2l,0xa89302025a2a95b8l,0x211e5037eaf75acel, + 0x6dba3e4ed2d09506l }, + { 0xa48ef98cd04399cdl,0x1811c66ee6b73adel,0x72f60752c17ecaf3l, + 0xf13cf3423becf4a7l }, + 0 }, + /* 244 */ + { { 0xceeb9ec0a919e2ebl,0x83a9a195f62c0f68l,0xcfba3bb67aba2299l, + 0xc83fa9a9274bbad3l }, + { 0x0d7d1b0b62fa1ce0l,0xe58b60f53418efbfl,0xbfa8ef9e52706f04l, + 0xb49d70f45d702683l }, + 0 }, + /* 245 */ + { { 0x914c7510fad5513bl,0x05f32eecb1751e2dl,0x6d850418d9fb9d59l, + 0x59cfadbb0c30f1cfl }, + { 0xe167ac2355cb7fd6l,0x249367b8820426a3l,0xeaeec58c90a78864l, + 0x5babf362354a4b67l }, + 0 }, + /* 246 */ + { { 0x37c981d1ee424865l,0x8b002878f2e5577fl,0x702970f1b9e0c058l, + 0x6188c6a79026c8f0l }, + { 0x06f9a19bd0f244dal,0x1ecced5cfb080873l,0x35470f9b9f213637l, + 0x993fe475df50b9d9l }, + 0 }, + /* 247 */ + { { 0x68e31cdf9b2c3609l,0x84eb19c02c46d4eal,0x7ac9ec1a9a775101l, + 0x81f764664c80616bl }, + { 0x1d7c2a5a75fbe978l,0x6743fed3f183b356l,0x838d1f04501dd2bfl, + 0x564a812a5fe9060dl }, + 0 }, + /* 248 */ + { { 0x7a5a64f4fa817d1dl,0x55f96844bea82e0fl,0xb5ff5a0fcd57f9aal, + 0x226bf3cf00e51d6cl }, + { 0xd6d1a9f92f2833cfl,0x20a0a35a4f4f89a8l,0x11536c498f3f7f77l, + 0x68779f47ff257836l }, + 0 }, + /* 249 */ + { { 0x79b0c1c173043d08l,0xa54467741fc020fal,0xd3767e289a6d26d0l, + 0x97bcb0d1eb092e0bl }, + { 0x2ab6eaa8f32ed3c3l,0xc8a4f151b281bc48l,0x4d1bf4f3bfa178f3l, + 0xa872ffe80a784655l }, + 0 }, + /* 250 */ + { { 0xb1ab7935a32b2086l,0xe1eb710e8160f486l,0x9bd0cd913b6ae6bel, + 0x02812bfcb732a36al }, + { 0xa63fd7cacf605318l,0x646e5d50fdfd6d1dl,0xa1d683982102d619l, + 0x07391cc9fe5396afl }, + 0 }, + /* 251 */ + { { 0xc50157f08b80d02bl,0x6b8333d162877f7fl,0x7aca1af878d542ael, + 0x355d2adc7e6d2a08l }, + { 0xb41f335a287386e1l,0xfd272a94f8e43275l,0x286ca2cde79989eal, + 0x3dc2b1e37c2a3a79l }, + 0 }, + /* 252 */ + { { 0xd689d21c04581352l,0x0a00c825376782bel,0x203bd5909fed701fl, + 0xc47869103ccd846bl }, + { 0x5dba770824c768edl,0x72feea026841f657l,0x73313ed56accce0el, + 0xccc42968d5bb4d32l }, + 0 }, + /* 253 */ + { { 0x94e50de13d7620b9l,0xd89a5c8a5992a56al,0xdc007640675487c9l, + 0xe147eb42aa4871cfl }, + { 0x274ab4eeacf3ae46l,0xfd4936fb50350fbel,0xdf2afe4748c840eal, + 0x239ac047080e96e3l }, + 0 }, + /* 254 */ + { { 0x481d1f352bfee8d4l,0xce80b5cffa7b0fecl,0x105c4c9e2ce9af3cl, + 0xc55fa1a3f5f7e59dl }, + { 0x3186f14e8257c227l,0xc5b1653f342be00bl,0x09afc998aa904fb2l, + 0x094cd99cd4f4b699l }, + 0 }, + /* 255 */ + { { 0x8a981c84d703bebal,0x8631d15032ceb291l,0xa445f2c9e3bd49ecl, + 0xb90a30b642abad33l }, + { 0xb465404fb4a5abf9l,0x004750c375db7603l,0x6f9a42ccca35d89fl, + 0x019f8b9a1b7924f7l }, + 0 }, +}; + +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_base_4(sp_point* r, sp_digit* k, + int map, void* heap) +{ + return sp_256_ecc_mulmod_stripe_4(r, &p256_base, p256_table, + k, map, heap); +} + +#else +/* A table entry for pre-computed points. */ +typedef struct sp_table_entry_sum { + sp_digit x[4]; + sp_digit y[4]; + byte infinity; +} sp_table_entry_sum; + +/* Table of pre-computed values for P256 with 3 multiples and width of 8 bits. + */ +static sp_table_entry_sum p256_table[33][58] = { + { + /* 0 << 0 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 0 */ + { { 0x79e730d418a9143cl,0x75ba95fc5fedb601l,0x79fb732b77622510l, + 0x18905f76a53755c6l }, + { 0xddf25357ce95560al,0x8b4ab8e4ba19e45cl,0xd2e88688dd21f325l, + 0x8571ff1825885d85l }, + 0 }, + /* 3 << 0 */ + { { 0xffac3f904eebc127l,0xb027f84a087d81fbl,0x66ad77dd87cbbc98l, + 0x26936a3fb6ff747el }, + { 0xb04c5c1fc983a7ebl,0x583e47ad0861fe1al,0x788208311a2ee98el, + 0xd5f06a29e587cc07l }, + 0 }, + /* 4 << 0 */ + { { 0x74b0b50d46918dccl,0x4650a6edc623c173l,0x0cdaacace8100af2l, + 0x577362f541b0176bl }, + { 0x2d96f24ce4cbaba6l,0x17628471fad6f447l,0x6b6c36dee5ddd22el, + 0x84b14c394c5ab863l }, + 0 }, + /* 5 << 0 */ + { { 0xbe1b8aaec45c61f5l,0x90ec649a94b9537dl,0x941cb5aad076c20cl, + 0xc9079605890523c8l }, + { 0xeb309b4ae7ba4f10l,0x73c568efe5eb882bl,0x3540a9877e7a1f68l, + 0x73a076bb2dd1e916l }, + 0 }, + /* 7 << 0 */ + { { 0x0746354ea0173b4fl,0x2bd20213d23c00f7l,0xf43eaab50c23bb08l, + 0x13ba5119c3123e03l }, + { 0x2847d0303f5b9d4dl,0x6742f2f25da67bddl,0xef933bdc77c94195l, + 0xeaedd9156e240867l }, + 0 }, + /* 9 << 0 */ + { { 0x75c96e8f264e20e8l,0xabe6bfed59a7a841l,0x2cc09c0444c8eb00l, + 0xe05b3080f0c4e16bl }, + { 0x1eb7777aa45f3314l,0x56af7bedce5d45e3l,0x2b6e019a88b12f1al, + 0x086659cdfd835f9bl }, + 0 }, + /* 10 << 0 */ + { { 0x2c18dbd19dc21ec8l,0x98f9868a0fcf8139l,0x737d2cd648250b49l, + 0xcc61c94724b3428fl }, + { 0x0c2b407880dd9e76l,0xc43a8991383fbe08l,0x5f7d2d65779be5d2l, + 0x78719a54eb3b4ab5l }, + 0 }, + /* 11 << 0 */ + { { 0xea7d260a6245e404l,0x9de407956e7fdfe0l,0x1ff3a4158dac1ab5l, + 0x3e7090f1649c9073l }, + { 0x1a7685612b944e88l,0x250f939ee57f61c8l,0x0c0daa891ead643dl, + 0x68930023e125b88el }, + 0 }, + /* 13 << 0 */ + { { 0xccc425634b2ed709l,0x0e356769856fd30dl,0xbcbcd43f559e9811l, + 0x738477ac5395b759l }, + { 0x35752b90c00ee17fl,0x68748390742ed2e3l,0x7cd06422bd1f5bc1l, + 0xfbc08769c9e7b797l }, + 0 }, + /* 15 << 0 */ + { { 0x72bcd8b7bc60055bl,0x03cc23ee56e27e4bl,0xee337424e4819370l, + 0xe2aa0e430ad3da09l }, + { 0x40b8524f6383c45dl,0xd766355442a41b25l,0x64efa6de778a4797l, + 0x2042170a7079adf4l }, + 0 }, + /* 16 << 0 */ + { { 0x808b0b650bc6fb80l,0x5882e0753ffe2e6bl,0xd5ef2f7c2c83f549l, + 0x54d63c809103b723l }, + { 0xf2f11bd652a23f9bl,0x3670c3194b0b6587l,0x55c4623bb1580e9el, + 0x64edf7b201efe220l }, + 0 }, + /* 17 << 0 */ + { { 0x97091dcbd53c5c9dl,0xf17624b6ac0a177bl,0xb0f139752cfe2dffl, + 0xc1a35c0a6c7a574el }, + { 0x227d314693e79987l,0x0575bf30e89cb80el,0x2f4e247f0d1883bbl, + 0xebd512263274c3d0l }, + 0 }, + /* 19 << 0 */ + { { 0xfea912baa5659ae8l,0x68363aba25e1a16el,0xb8842277752c41acl, + 0xfe545c282897c3fcl }, + { 0x2d36e9e7dc4c696bl,0x5806244afba977c5l,0x85665e9be39508c1l, + 0xf720ee256d12597bl }, + 0 }, + /* 21 << 0 */ + { { 0x562e4cecc135b208l,0x74e1b2654783f47dl,0x6d2a506c5a3f3b30l, + 0xecead9f4c16762fcl }, + { 0xf29dd4b2e286e5b9l,0x1b0fadc083bb3c61l,0x7a75023e7fac29a4l, + 0xc086d5f1c9477fa3l }, + 0 }, + /* 23 << 0 */ + { { 0xf4f876532de45068l,0x37c7a7e89e2e1f6el,0xd0825fa2a3584069l, + 0xaf2cea7c1727bf42l }, + { 0x0360a4fb9e4785a9l,0xe5fda49c27299f4al,0x48068e1371ac2f71l, + 0x83d0687b9077666fl }, + 0 }, + /* 25 << 0 */ + { { 0xa4a319acd837879fl,0x6fc1b49eed6b67b0l,0xe395993332f1f3afl, + 0x966742eb65432a2el }, + { 0x4b8dc9feb4966228l,0x96cc631243f43950l,0x12068859c9b731eel, + 0x7b948dc356f79968l }, + 0 }, + /* 27 << 0 */ + { { 0x042c2af497e2feb4l,0xd36a42d7aebf7313l,0x49d2c9eb084ffdd7l, + 0x9f8aa54b2ef7c76al }, + { 0x9200b7ba09895e70l,0x3bd0c66fddb7fb58l,0x2d97d10878eb4cbbl, + 0x2d431068d84bde31l }, + 0 }, + /* 28 << 0 */ + { { 0x4b523eb7172ccd1fl,0x7323cb2830a6a892l,0x97082ec0cfe153ebl, + 0xe97f6b6af2aadb97l }, + { 0x1d3d393ed1a83da1l,0xa6a7f9c7804b2a68l,0x4a688b482d0cb71el, + 0xa9b4cc5f40585278l }, + 0 }, + /* 29 << 0 */ + { { 0x5e5db46acb66e132l,0xf1be963a0d925880l,0x944a70270317b9e2l, + 0xe266f95948603d48l }, + { 0x98db66735c208899l,0x90472447a2fb18a3l,0x8a966939777c619fl, + 0x3798142a2a3be21bl }, + 0 }, + /* 31 << 0 */ + { { 0xe2f73c696755ff89l,0xdd3cf7e7473017e6l,0x8ef5689d3cf7600dl, + 0x948dc4f8b1fc87b4l }, + { 0xd9e9fe814ea53299l,0x2d921ca298eb6028l,0xfaecedfd0c9803fcl, + 0xf38ae8914d7b4745l }, + 0 }, + /* 33 << 0 */ + { { 0x871514560f664534l,0x85ceae7c4b68f103l,0xac09c4ae65578ab9l, + 0x33ec6868f044b10cl }, + { 0x6ac4832b3a8ec1f1l,0x5509d1285847d5efl,0xf909604f763f1574l, + 0xb16c4303c32f63c4l }, + 0 }, + /* 34 << 0 */ + { { 0xb6ab20147ca23cd3l,0xcaa7a5c6a391849dl,0x5b0673a375678d94l, + 0xc982ddd4dd303e64l }, + { 0xfd7b000b5db6f971l,0xbba2cb1f6f876f92l,0xc77332a33c569426l, + 0xa159100c570d74f8l }, + 0 }, + /* 35 << 0 */ + { { 0xfd16847fdec67ef5l,0x742ee464233e76b7l,0x0b8e4134efc2b4c8l, + 0xca640b8642a3e521l }, + { 0x653a01908ceb6aa9l,0x313c300c547852d5l,0x24e4ab126b237af7l, + 0x2ba901628bb47af8l }, + 0 }, + /* 36 << 0 */ + { { 0x3d5e58d6a8219bb7l,0xc691d0bd1b06c57fl,0x0ae4cb10d257576el, + 0x3569656cd54a3dc3l }, + { 0xe5ebaebd94cda03al,0x934e82d3162bfe13l,0x450ac0bae251a0c6l, + 0x480b9e11dd6da526l }, + 0 }, + /* 37 << 0 */ + { { 0x00467bc58cce08b5l,0xb636458c7f178d55l,0xc5748baea677d806l, + 0x2763a387dfa394ebl }, + { 0xa12b448a7d3cebb6l,0xe7adda3e6f20d850l,0xf63ebce51558462cl, + 0x58b36143620088a8l }, + 0 }, + /* 39 << 0 */ + { { 0xa9d89488a059c142l,0x6f5ae714ff0b9346l,0x068f237d16fb3664l, + 0x5853e4c4363186acl }, + { 0xe2d87d2363c52f98l,0x2ec4a76681828876l,0x47b864fae14e7b1cl, + 0x0c0bc0e569192408l }, + 0 }, + /* 40 << 0 */ + { { 0xe4d7681db82e9f3el,0x83200f0bdf25e13cl,0x8909984c66f27280l, + 0x462d7b0075f73227l }, + { 0xd90ba188f2651798l,0x74c6e18c36ab1c34l,0xab256ea35ef54359l, + 0x03466612d1aa702fl }, + 0 }, + /* 41 << 0 */ + { { 0x624d60492ed22e91l,0x6fdfe0b56f072822l,0xeeca111539ce2271l, + 0x98100a4fdb01614fl }, + { 0xb6b0daa2a35c628fl,0xb6f94d2ec87e9a47l,0xc67732591d57d9cel, + 0xf70bfeec03884a7bl }, + 0 }, + /* 43 << 0 */ + { { 0x4ff23ffd248a7d06l,0x80c5bfb4878873fal,0xb7d9ad9005745981l, + 0x179c85db3db01994l }, + { 0xba41b06261a6966cl,0x4d82d052eadce5a8l,0x9e91cd3ba5e6a318l, + 0x47795f4f95b2dda0l }, + 0 }, + /* 44 << 0 */ + { { 0xecfd7c1fd55a897cl,0x009194abb29110fbl,0x5f0e2046e381d3b0l, + 0x5f3425f6a98dd291l }, + { 0xbfa06687730d50dal,0x0423446c4b083b7fl,0x397a247dd69d3417l, + 0xeb629f90387ba42al }, + 0 }, + /* 45 << 0 */ + { { 0x1ee426ccd5cd79bfl,0x0032940b946c6e18l,0x1b1e8ae057477f58l, + 0xe94f7d346d823278l }, + { 0xc747cb96782ba21al,0xc5254469f72b33a5l,0x772ef6dec7f80c81l, + 0xd73acbfe2cd9e6b5l }, + 0 }, + /* 46 << 0 */ + { { 0x4075b5b149ee90d9l,0x785c339aa06e9ebal,0xa1030d5babf825e0l, + 0xcec684c3a42931dcl }, + { 0x42ab62c9c1586e63l,0x45431d665ab43f2bl,0x57c8b2c055f7835dl, + 0x033da338c1b7f865l }, + 0 }, + /* 47 << 0 */ + { { 0x283c7513caa76097l,0x0a624fa936c83906l,0x6b20afec715af2c7l, + 0x4b969974eba78bfdl }, + { 0x220755ccd921d60el,0x9b944e107baeca13l,0x04819d515ded93d4l, + 0x9bbff86e6dddfd27l }, + 0 }, + /* 48 << 0 */ + { { 0x6b34413077adc612l,0xa7496529bbd803a0l,0x1a1baaa76d8805bdl, + 0xc8403902470343adl }, + { 0x39f59f66175adff1l,0x0b26d7fbb7d8c5b7l,0xa875f5ce529d75e3l, + 0x85efc7e941325cc2l }, + 0 }, + /* 49 << 0 */ + { { 0x21950b421ff6acd3l,0xffe7048453dc6909l,0xff4cd0b228766127l, + 0xabdbe6084fb7db2bl }, + { 0x837c92285e1109e8l,0x26147d27f4645b5al,0x4d78f592f7818ed8l, + 0xd394077ef247fa36l }, + 0 }, + /* 51 << 0 */ + { { 0x508cec1c3b3f64c9l,0xe20bc0ba1e5edf3fl,0xda1deb852f4318d4l, + 0xd20ebe0d5c3fa443l }, + { 0x370b4ea773241ea3l,0x61f1511c5e1a5f65l,0x99a5e23d82681c62l, + 0xd731e383a2f54c2dl }, + 0 }, + /* 52 << 0 */ + { { 0x2692f36e83445904l,0x2e0ec469af45f9c0l,0x905a3201c67528b7l, + 0x88f77f34d0e5e542l }, + { 0xf67a8d295864687cl,0x23b92eae22df3562l,0x5c27014b9bbec39el, + 0x7ef2f2269c0f0f8dl }, + 0 }, + /* 53 << 0 */ + { { 0x97359638546c4d8dl,0x5f9c3fc492f24679l,0x912e8beda8c8acd9l, + 0xec3a318d306634b0l }, + { 0x80167f41c31cb264l,0x3db82f6f522113f2l,0xb155bcd2dcafe197l, + 0xfba1da5943465283l }, + 0 }, + /* 55 << 0 */ + { { 0x258bbbf9e7305683l,0x31eea5bf07ef5be6l,0x0deb0e4a46c814c1l, + 0x5cee8449a7b730ddl }, + { 0xeab495c5a0182bdel,0xee759f879e27a6b4l,0xc2cf6a6880e518cal, + 0x25e8013ff14cf3f4l }, + 0 }, + /* 57 << 0 */ + { { 0x3ec832e77acaca28l,0x1bfeea57c7385b29l,0x068212e3fd1eaf38l, + 0xc13298306acf8cccl }, + { 0xb909f2db2aac9e59l,0x5748060db661782al,0xc5ab2632c79b7a01l, + 0xda44c6c600017626l }, + 0 }, + /* 59 << 0 */ + { { 0x69d44ed65c46aa8el,0x2100d5d3a8d063d1l,0xcb9727eaa2d17c36l, + 0x4c2bab1b8add53b7l }, + { 0xa084e90c15426704l,0x778afcd3a837ebeal,0x6651f7017ce477f8l, + 0xa062499846fb7a8bl }, + 0 }, + /* 60 << 0 */ + { { 0xdc1e6828ed8a6e19l,0x33fc23364189d9c7l,0x026f8fe2671c39bcl, + 0xd40c4ccdbc6f9915l }, + { 0xafa135bbf80e75cal,0x12c651a022adff2cl,0xc40a04bd4f51ad96l, + 0x04820109bbe4e832l }, + 0 }, + /* 61 << 0 */ + { { 0x3667eb1a7f4c04ccl,0x59556621a9404f84l,0x71cdf6537eceb50al, + 0x994a44a69b8335fal }, + { 0xd7faf819dbeb9b69l,0x473c5680eed4350dl,0xb6658466da44bba2l, + 0x0d1bc780872bdbf3l }, + 0 }, + /* 63 << 0 */ + { { 0xb8d3d9319ff91fe5l,0x039c4800f0518eedl,0x95c376329182cb26l, + 0x0763a43482fc568dl }, + { 0x707c04d5383e76bal,0xac98b930824e8197l,0x92bf7c8f91230de0l, + 0x90876a0140959b70l }, + 0 }, + /* 64 << 0 */ + { { 0xdb6d96f305968b80l,0x380a0913089f73b9l,0x7da70b83c2c61e01l, + 0x95fb8394569b38c7l }, + { 0x9a3c651280edfe2fl,0x8f726bb98faeaf82l,0x8010a4a078424bf8l, + 0x296720440e844970l }, + 0 }, + /* 65 << 0 */ + { { 0xdc2306ebfcdbb2b2l,0x79527db7ba66f4b9l,0xbf639ed67765765el, + 0x01628c4706b6090al }, + { 0x66eb62f1b957b4a1l,0x33cb7691ba659f46l,0x2c90d98cf3e055d6l, + 0x7d096ac42f174750l }, + 0 }, + /* 71 << 0 */ + { { 0xf19f382e92aa7864l,0x49c7cb94fc05804bl,0xf94aa89b40750d01l, + 0xdd421b5d4a210364l }, + { 0x56cd001e39df3672l,0x030a119fdd4af1ecl,0x11f947e696cd0572l, + 0x574cc7b293786791l }, + 0 }, + /* 77 << 0 */ + { { 0x0a2193bfc266f85cl,0x719a87be5a0ec9cel,0x9c30c6422b2f9c49l, + 0xdb15e4963d5baeb1l }, + { 0x83c3139be0d37321l,0x4788522b2e9fdbb2l,0x2b4f0c7877eb94eal, + 0x854dc9d595105f9el }, + 0 }, + /* 83 << 0 */ + { { 0x2c9ee62dc3363a22l,0x125d4714ec67199al,0xf87abebf2ab80485l, + 0xcf3086e87a243ca4l }, + { 0x5c52b051c64e09ddl,0x5e9b16125625aad7l,0x0536a39db19c6126l, + 0x97f0013247b64be5l }, + 0 }, + /* 89 << 0 */ + { { 0xc1ee6264a7eabe67l,0x62d51e29fd54487dl,0x3ea123446310eb5al, + 0xbd88aca74765b805l }, + { 0xb7b284be14fb691al,0x640388f83b9fffefl,0x7ab49dd209f98f9al, + 0x7150f87e7211e445l }, + 0 }, + /* 95 << 0 */ + { { 0x263e039bb308cc40l,0x6684ad762b346fd2l,0x9a127f2bcaa12d0dl, + 0x76a8f9fea974291fl }, + { 0xc802049b68aa19e4l,0x65499c990c5dbba0l,0xee1b1cb5344455a1l, + 0x3f293fda2cd6f439l }, + 0 }, + /* 101 << 0 */ + { { 0xb7a96e0a4ea6fdf7l,0xbbe914d3b99cd026l,0x6a610374c569a602l, + 0xe9b1c23914da499el }, + { 0xb5f6f0feadc19a99l,0x731251826f21687cl,0x5a8a14644be77793l, + 0x94ce9e0adba8bfc7l }, + 0 }, + /* 107 << 0 */ + { { 0x2ca0ba9c3796f4c7l,0x3571e4d1592ce334l,0x28f9cdebe9f6e877l, + 0xee206023efce1a70l }, + { 0xb2159e08b76369dcl,0x2754e4260a7f687cl,0xe008039e02de2ff1l, + 0xccd7e9418ea700c1l }, + 0 }, + /* 113 << 0 */ + { { 0xa125e6c1b7ebcb88l,0x3289e86e10ec0d40l,0xcc3a5ecb98353869l, + 0x734e0d078a2b0d3al }, + { 0xe0d92e9a51933360l,0xfa6bcdb1786076b9l,0xd13cca90747f19ecl, + 0x61d8209d49f3a53dl }, + 0 }, + /* 116 << 0 */ + { { 0x87f9793bc9826344l,0x4b3de89bb2f5f79cl,0xc9f08a5659cb1b6el, + 0xd8f1fc5f6a92b9aal }, + { 0x86357f9eb412595el,0x53c30bbe65b80f16l,0xf06c2c8c70549a57l, + 0xa9c8a4b42b9157dal }, + 0 }, + /* 119 << 0 */ + { { 0x87af199e6cc47305l,0x062afb7c1e314ddel,0x2be22ba0f3a49fb4l, + 0x6ed0b988157b7f56l }, + { 0x8162cf502d653fd9l,0x17d29c64877b7497l,0xd7e814380f67b514l, + 0xfedf1014fe6ee703l }, + 0 }, + /* 125 << 0 */ + { { 0xaab54cfc93740130l,0xf72dab6d225733fal,0x04b76d2d1ed32559l, + 0xa9fe2396bb85b9cbl }, + { 0x128b0d24bf2219f0l,0x2292393b579f3ce2l,0x51dc5fac145ff0d5l, + 0xb16d6af8c3febbc1l }, + 0 }, + }, + { + /* 0 << 8 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 8 */ + { { 0x486d8ffa696946fcl,0x50fbc6d8b9cba56dl,0x7e3d423e90f35a15l, + 0x7c3da195c0dd962cl }, + { 0xe673fdb03cfd5d8bl,0x0704b7c2889dfca5l,0xf6ce581ff52305aal, + 0x399d49eb914d5e53l }, + 0 }, + /* 3 << 8 */ + { { 0x35d6a53eed4c3717l,0x9f8240cf3d0ed2a3l,0x8c0d4d05e5543aa5l, + 0x45d5bbfbdd33b4b4l }, + { 0xfa04cc73137fd28el,0x862ac6efc73b3ffdl,0x403ff9f531f51ef2l, + 0x34d5e0fcbc73f5a2l }, + 0 }, + /* 4 << 8 */ + { { 0x4f7081e144cc3addl,0xd5ffa1d687be82cfl,0x89890b6c0edd6472l, + 0xada26e1a3ed17863l }, + { 0x276f271563483caal,0xe6924cd92f6077fdl,0x05a7fe980a466e3cl, + 0xf1c794b0b1902d1fl }, + 0 }, + /* 5 << 8 */ + { { 0x33b2385c08369a90l,0x2990c59b190eb4f8l,0x819a6145c68eac80l, + 0x7a786d622ec4a014l }, + { 0x33faadbe20ac3a8dl,0x31a217815aba2d30l,0x209d2742dba4f565l, + 0xdb2ce9e355aa0fbbl }, + 0 }, + /* 7 << 8 */ + { { 0x0c4a58d474a86108l,0xf8048a8fee4c5d90l,0xe3c7c924e86d4c80l, + 0x28c889de056a1e60l }, + { 0x57e2662eb214a040l,0xe8c48e9837e10347l,0x8774286280ac748al, + 0xf1c24022186b06f2l }, + 0 }, + /* 9 << 8 */ + { { 0xe8cbf1e5d5923359l,0xdb0cea9d539b9fb0l,0x0c5b34cf49859b98l, + 0x5e583c56a4403cc6l }, + { 0x11fc1a2dd48185b7l,0xc93fbc7e6e521787l,0x47e7a05805105b8bl, + 0x7b4d4d58db8260c8l }, + 0 }, + /* 10 << 8 */ + { { 0xb31bd6136339c083l,0x39ff8155dfb64701l,0x7c3388d2e29604abl, + 0x1e19084ba6b10442l }, + { 0x17cf54c0eccd47efl,0x896933854a5dfb30l,0x69d023fb47daf9f6l, + 0x9222840b7d91d959l }, + 0 }, + /* 11 << 8 */ + { { 0xc510610939842194l,0xb7e2353e49d05295l,0xfc8c1d5cefb42ee0l, + 0xe04884eb08ce811cl }, + { 0xf1f75d817419f40el,0x5b0ac162a995c241l,0x120921bbc4c55646l, + 0x713520c28d33cf97l }, + 0 }, + /* 13 << 8 */ + { { 0x41d04ee21726931al,0x0bbbb2c83660ecfdl,0xa6ef6de524818e18l, + 0xe421cc51e7d57887l }, + { 0xf127d208bea87be6l,0x16a475d3b1cdd682l,0x9db1b684439b63f7l, + 0x5359b3dbf0f113b6l }, + 0 }, + /* 15 << 8 */ + { { 0x3a5c752edcc18770l,0x4baf1f2f8825c3a5l,0xebd63f7421b153edl, + 0xa2383e47b2f64723l }, + { 0xe7bf620a2646d19al,0x56cb44ec03c83ffdl,0xaf7267c94f6be9f1l, + 0x8b2dfd7bc06bb5e9l }, + 0 }, + /* 16 << 8 */ + { { 0x6772b0e5ab4b35a2l,0x1d8b6001f5eeaacfl,0x728f7ce4795b9580l, + 0x4a20ed2a41fb81dal }, + { 0x9f685cd44fec01e6l,0x3ed7ddcca7ff50adl,0x460fd2640c2d97fdl, + 0x3a241426eb82f4f9l }, + 0 }, + /* 17 << 8 */ + { { 0xc503cd33bccd9617l,0x365dede4ba7730a3l,0x798c63555ddb0786l, + 0xa6c3200efc9cd3bcl }, + { 0x060ffb2ce5e35efdl,0x99a4e25b5555a1c1l,0x11d95375f70b3751l, + 0x0a57354a160e1bf6l }, + 0 }, + /* 19 << 8 */ + { { 0xc033bdc719803511l,0xa9f97b3b8888c3bel,0x3d68aebc85c6d05el, + 0xc3b88a9d193919ebl }, + { 0x2d300748c48b0ee3l,0x7506bc7c07a746c1l,0xfc48437c6e6d57f3l, + 0x5bd71587cfeaa91al }, + 0 }, + /* 21 << 8 */ + { { 0xe40736d3df61bc76l,0x13a619c03f778cdbl,0x6dd921a4c56ea28fl, + 0x76a524332fa647b4l }, + { 0x23591891ac5bdc5dl,0xff4a1a72bac7dc01l,0x9905e26162df8453l, + 0x3ac045dfe63b265fl }, + 0 }, + /* 23 << 8 */ + { { 0x8435bd6994b03ed1l,0xd9ad1de3634cc546l,0x2cf423fc00e420cal, + 0xeed26d80a03096ddl }, + { 0xd7f60be7a4db09d2l,0xf47f569d960622f7l,0xe5925fd77296c729l, + 0xeff2db2626ca2715l }, + 0 }, + /* 25 << 8 */ + { { 0x5dfee80f83774bddl,0x6313160285734485l,0xa1b524ae914a69a9l, + 0xebc2ffafd4e300d7l }, + { 0x52c93db77cfa46a5l,0x71e6161f21653b50l,0x3574fc57a4bc580al, + 0xc09015dde1bc1253l }, + 0 }, + /* 27 << 8 */ + { { 0x9c38ddcceb5b76c1l,0x746f528526fc0ab4l,0x52a63a50d62c269fl, + 0x60049c5599458621l }, + { 0xe7f48f823c2f7c9el,0x6bd99043917d5cf3l,0xeb1317a88701f469l, + 0xbd3fe2ed9a449fe0l }, + 0 }, + /* 28 << 8 */ + { { 0xe652533b3cef0d7dl,0xd94f7b182bbb4381l,0x838752be0e80f500l, + 0x8e6e24889e9c9bfbl }, + { 0xc975169716caca6al,0x866c49d838531ad9l,0xc917e2397151ade1l, + 0x2d016ec16037c407l }, + 0 }, + /* 29 << 8 */ + { { 0x202f6a9c31c71f7bl,0x01f95aa3296ffe5cl,0x5fc0601453cec3a3l, + 0xeb9912375f498a45l }, + { 0xae9a935e5d91ba87l,0xc6ac62810b564a19l,0x8a8fe81c3bd44e69l, + 0x7c8b467f9dd11d45l }, + 0 }, + /* 31 << 8 */ + { { 0x21d3634d39eedbbal,0x35cd2e680455a46dl,0xc8cafe65f9d7eb0cl, + 0xbda3ce9e00cefb3el }, + { 0xddc17a602c9cf7a4l,0x01572ee47bcb8773l,0xa92b2b018c7548dfl, + 0x732fd309a84600e3l }, + 0 }, + /* 33 << 8 */ + { { 0x65cf89a2e0600afal,0xcf51482f753c5ceal,0x4f2b2d25a5c2bfc5l, + 0x9381f57187098256l }, + { 0x89210f676e976e4bl,0xe2cf12f489f47a7bl,0xc21a1658e8484050l, + 0xa224dbf82f0fff01l }, + 0 }, + /* 34 << 8 */ + { { 0xc28961087282513dl,0x9a78c4296a3f8fb8l,0xddfa56f9a31e24b7l, + 0xb1e14f84fb72611fl }, + { 0x1d0f70ab45078d65l,0xb247aef3819924d8l,0x8d519f9dbb9877c1l, + 0x495c2ece8368c7c9l }, + 0 }, + /* 35 << 8 */ + { { 0xca9129a0bdb69d12l,0xbe3e319978f39adfl,0xa88506df5fe49438l, + 0x17ddb7a7aafe894cl }, + { 0x28d1456f6d1d742fl,0xeec09651917d1268l,0xdecb1c700fd5b4c0l, + 0x32d14f6acf2861dbl }, + 0 }, + /* 36 << 8 */ + { { 0x903f6e3960e913afl,0xb2b58bee98bf140dl,0x9deff025354890b8l, + 0x155810068d2e924el }, + { 0xb5755db493c95e5bl,0x3fac42f0dae20eb8l,0x9377c8c109b6d8e0l, + 0xa43e2b46ab47ceffl }, + 0 }, + /* 37 << 8 */ + { { 0x6c3f5a51cb61e7e7l,0x264aebc80d9c73b2l,0xc404b2114a0d9288l, + 0x5178d3cf8b3a79e9l }, + { 0x4080be5372a420d7l,0xa39396adef026429l,0x22fbb92e8dde4728l, + 0x19e42d8874d949fcl }, + 0 }, + /* 39 << 8 */ + { { 0xde352d78387f5557l,0x6770149969367413l,0x255bb8c00b0cc102l, + 0x63cad1be1f4d262el }, + { 0xf34f9a8a3f8f4fb6l,0x32bc13aae03a969fl,0xb29d4336218371cdl, + 0x799d76ab285bd210l }, + 0 }, + /* 40 << 8 */ + { { 0x5f57b2fbfacfa459l,0x874b1498c1b5aa6bl,0xb9e89acac4db2092l, + 0x1362bf8ddf4381dal }, + { 0x25d76830b76328a0l,0x38188b7098572ae4l,0xb43e941429132f7dl, + 0x7895a29f22dd42c9l }, + 0 }, + /* 41 << 8 */ + { { 0x85bded619e808c05l,0x6e0fc2bcc7ef83bbl,0xed70e0b499bedf77l, + 0x300e777dc1aaffc0l }, + { 0xe2da2359c43e6d2cl,0xacf6d60a275226e0l,0x18ca38f7f82558bdl, + 0xd7b017d475ae2591l }, + 0 }, + /* 43 << 8 */ + { { 0xed299e2d7cd92ee2l,0x2c08eb37ad847153l,0x7b372aa712acfd81l, + 0x574d27f5fabda29cl }, + { 0xbd8247f0f2ee6ebcl,0x8bf76710d06be261l,0x26e95b4bcb186d4cl, + 0x4fa3ac1d1ebb4a46l }, + 0 }, + /* 44 << 8 */ + { { 0xcbde78dd5e22cbb2l,0xf449c85b76bb4391l,0x4289f357b6a4273bl, + 0x9fce23fd48e84a19l }, + { 0xcfc32730939eb3b4l,0x8b3d982c16c32280l,0x5ac234bad5f1346cl, + 0x781954b470769fc9l }, + 0 }, + /* 45 << 8 */ + { { 0xff0d4d30062c7dbdl,0x2c483081e6f9fcf0l,0x22f96316d67e070fl, + 0xdd9be459c0e68c44l }, + { 0xb9c1edffce2edd4dl,0x1a54782021fc538cl,0x93849be49979aee1l, + 0x3f313629a590949el }, + 0 }, + /* 46 << 8 */ + { { 0x160b836b266be332l,0x49de38215f340575l,0x782e8f6701edce66l, + 0x83ae008b5df1a93el }, + { 0x85d33a263ed9ffebl,0xae2f9f961e79db97l,0xf64f209b95ae9e34l, + 0x2b6b03455e957d49l }, + 0 }, + /* 47 << 8 */ + { { 0x7a24a21a331d6bdal,0xfdba302f6328f742l,0x37a36dd47744dca4l, + 0xda2832ce6fef500fl }, + { 0x23da304a7b49d73al,0xeede2cebc6ad834fl,0xf21a81248dec3c78l, + 0x4bc9469b19b721e3l }, + 0 }, + /* 48 << 8 */ + { { 0x6faf68feaae6ee70l,0x78f4cc155602b0c9l,0x7e3321a86e94052al, + 0x2fb3a0d6734d5d80l }, + { 0xf3b98f3bb25a43bal,0x30bf803119ee2951l,0x7ffee43321b0612al, + 0x12f775e42eb821d0l }, + 0 }, + /* 49 << 8 */ + { { 0x31cc342913e5c1d6l,0x05deaa3cee54e334l,0x21ea2b61cd5087d8l, + 0x73a1841e70d1b8bcl }, + { 0xd44e2b41b078bf14l,0xc295732fcea2a30el,0x30cdab42954939f7l, + 0xc1b4e43a2dba0b7cl }, + 0 }, + /* 51 << 8 */ + { { 0x5f33f618b6a20132l,0xc8d73e3cfbbf3022l,0xf3b9844d47ed4320l, + 0xab5868aa927f00cal }, + { 0x06cb1113077f6e1cl,0x1417b43a5c94faaal,0x7666cb90cf4cd1e9l, + 0x99e009f210900566l }, + 0 }, + /* 52 << 8 */ + { { 0x4fdff805f57209b5l,0x9bd65ac3f952ac8dl,0x02a3abd3c7969a6fl, + 0x1359927ef523775fl }, + { 0xe09b463f88d2e861l,0x661d2199623287c3l,0x821e64495a70eb7al, + 0x0afbbb1dd67dc684l }, + 0 }, + /* 53 << 8 */ + { { 0x2c5a2b2d55750eb2l,0x54d756c29dc28d9fl,0x798c8d113af97f71l, + 0x54e21ee21f6d1853l }, + { 0x34e0c8bceffc3f8al,0xed3cc4dda96f193fl,0x86436a84fad97110l, + 0x8530ca522c97205el }, + 0 }, + /* 55 << 8 */ + { { 0x9b6c8452f7236867l,0x21cf260c777b44fdl,0x659fc99dceb00c52l, + 0xda97098e2439e8dbl }, + { 0x647efe510ed6e14fl,0x37c8ca122a6600f3l,0x53e89b0badf6f4a7l, + 0xd9fc8c716645618al }, + 0 }, + /* 57 << 8 */ + { { 0x9cecfb8eee6ebd31l,0x4603994b1ff25529l,0x707bc80af4b141c4l, + 0x3a83d56c07524d3al }, + { 0x7035c746613a3020l,0x7aa766b286626a1cl,0x3af656095ac76c78l, + 0x4039c655171e47d6l }, + 0 }, + /* 59 << 8 */ + { { 0x79cb147f0ce33b63l,0xa1328a622d160c61l,0xf99538f3cf7eb87el, + 0x0334d4958e2241d5l }, + { 0x3ad97e02f3e49e48l,0xdcfcc754037c3679l,0x76078ba61a8ff67cl, + 0x8054aa55c2a64964l }, + 0 }, + /* 60 << 8 */ + { { 0x5852104b87453b28l,0x073e8128b387344dl,0x300e78e4817cfc08l, + 0x3a82ed4799362088l }, + { 0xe222304c88de46a4l,0x666c94fd57fadf4al,0x40b2d08ea0c8e108l, + 0x4b2955b909e050fal }, + 0 }, + /* 61 << 8 */ + { { 0x656078565f814881l,0x0fc3d1ce58466117l,0x0ae377d3c6c1e68al, + 0xe3dd8d5cba566c48l }, + { 0x9404849ec4b63be6l,0x1e22b03ba5be9c92l,0x08145122a8b03e63l, + 0x71248243771fe153l }, + 0 }, + /* 63 << 8 */ + { { 0xa80a0e83b41ac541l,0xa77570ea533e5f9bl,0x416a14c0216dc452l, + 0x2a8d728a19f7ee59l }, + { 0x58494c8cd6552eaal,0x4d635acd60145722l,0xa8e9b127327b1cbcl, + 0xb429a62e9f8235f0l }, + 0 }, + /* 64 << 8 */ + { { 0xf8d112e76e6485b3l,0x4d3e24db771c52f8l,0x48e3ee41684a2f6dl, + 0x7161957d21d95551l }, + { 0x19631283cdb12a6cl,0xbf3fa8822e50e164l,0xf6254b633166cc73l, + 0x3aefa7aeaee8cc38l }, + 0 }, + /* 65 << 8 */ + { { 0xd52d2cb746ef1c7el,0xebd4f7c4d8fb6e07l,0x16f77a48cf6dd2b4l, + 0x6e8f0431e77e4d51l }, + { 0x59d94cc4e9177bf2l,0xb58a578f7a7181a1l,0xeefbc4cde8f6d330l, + 0xa66c85560fe05490l }, + 0 }, + /* 71 << 8 */ + { { 0x0e6db7a35d9649dal,0x4d2f25193be3d362l,0xcd891fd5a6b137b5l, + 0xa4b7e4ddacd377a9l }, + { 0x20ccd6f24355f258l,0x842c08673aafb413l,0xdd55db99d6873b88l, + 0x04d15f4fea5a2a55l }, + 0 }, + /* 77 << 8 */ + { { 0x679cd93dfae289c2l,0x84cadd61ff92ba1bl,0x548b5a6f2cd734aal, + 0x1827507db8267082l }, + { 0xa903a6010c6d5b4cl,0xde0d96befdfb952bl,0x2fc9419c6a2e24f9l, + 0x27333e3936bb3203l }, + 0 }, + /* 83 << 8 */ + { { 0x3eb7f062dde4aa6al,0x40effae07f354cc0l,0xe9a14bc2a066c05el, + 0x7817b11356afc543l }, + { 0x5f0ed1f28bdda262l,0x001e23d2e007ec13l,0x435878a59c57de6al, + 0x84d0e20895ac263cl }, + 0 }, + /* 89 << 8 */ + { { 0xedf24aec97a66678l,0xd1f93cf8ccf55671l,0x4ed2ce8a9379a49dl, + 0x64991862c39b0ac9l }, + { 0xc15b24e31ff67e04l,0x4ee8fc76c3c084fel,0x262012b4f64bcd46l, + 0x3b5086732425c622l }, + 0 }, + /* 95 << 8 */ + { { 0xaa3e451fe65002f7l,0xf5ff2617eb46d253l,0x918d146e572afca2l, + 0x0a9333b7e56a8553l }, + { 0x9b7e232d94127dc0l,0xcd0687d6831014e6l,0x725ce5baf08e1c71l, + 0x56e26f48cde0e4edl }, + 0 }, + /* 101 << 8 */ + { { 0xae78dde8db833460l,0xaf1736fe762cb78al,0x5cd85742eae5ac60l, + 0x7b6c52fe955e981al }, + { 0x9f823e8555599f97l,0xb9ce70d21a4b46b3l,0xb6076175d7d09829l, + 0x21e77d22abf390a4l }, + 0 }, + /* 107 << 8 */ + { { 0xf704f09da142ad7el,0xb60ec2e1bab9f5d2l,0x4180314681e54d0dl, + 0x0de50506309335e6l }, + { 0x4135374e05aec64fl,0xb5d31041b556808al,0x0092eb86049033a8l, + 0x5b7a2fa0bde0d737l }, + 0 }, + /* 113 << 8 */ + { { 0xc0dfa6bbefb40cfal,0x86a6fe279c5037f3l,0xf153cd37f71155f4l, + 0xf16d6029767664f9l }, + { 0x7441aa54c635aa57l,0x547f82e9e8186b2el,0x330b464bfbf7c7fel, + 0xb5556770a1f6fddel }, + 0 }, + /* 116 << 8 */ + { { 0xa0a9c5d1e8f9edf1l,0x9814c26b6946cea3l,0xcbb47a37d8e6a08dl, + 0x517a3d9b2cba11b1l }, + { 0x94edc73dab43c540l,0x4fd0b82a753e552cl,0x419aab8bd14ae853l, + 0x94955f9ca68abad8l }, + 0 }, + /* 119 << 8 */ + { { 0x3a162e06ed169150l,0x8c9683a6ba1194a8l,0x53fead66ccc28d04l, + 0xdbb2a85bef09809al }, + { 0x58e677439d3ab018l,0xff9a2046b6e56bd0l,0xf4b8215eb28061e9l, + 0xcf16d9f7b10e358fl }, + 0 }, + /* 125 << 8 */ + { { 0x265ceae9a55abe39l,0x9e3783f796a98f84l,0xb799628af0757d99l, + 0xebb5f12665472fb3l }, + { 0xd83619f52ba517d8l,0x5672105f50382bdfl,0x32c5681c4a12ee9fl, + 0x31e6f60d834a9fedl }, + 0 }, + }, + { + /* 0 << 16 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 16 */ + { { 0x0f0165fce3779ee3l,0xe00e7f9dbd495d9el,0x1fa4efa220284e7al, + 0x4564bade47ac6219l }, + { 0x90e6312ac4708e8el,0x4f5725fba71e9adfl,0xe95f55ae3d684b9fl, + 0x47f7ccb11e94b415l }, + 0 }, + /* 3 << 16 */ + { { 0xbd9b8b1dbe7a2af3l,0xec51caa94fb74a72l,0xb9937a4b63879697l, + 0x7c9a9d20ec2687d5l }, + { 0x1773e44f6ef5f014l,0x8abcf412e90c6900l,0x387bd0228142161el, + 0x50393755fcb6ff2al }, + 0 }, + /* 4 << 16 */ + { { 0xfabf770977f7195al,0x8ec86167adeb838fl,0xea1285a8bb4f012dl, + 0xd68835039a3eab3fl }, + { 0xee5d24f8309004c2l,0xa96e4b7613ffe95el,0x0cdffe12bd223ea4l, + 0x8f5c2ee5b6739a53l }, + 0 }, + /* 5 << 16 */ + { { 0x3d61333959145a65l,0xcd9bc368fa406337l,0x82d11be32d8a52a0l, + 0xf6877b2797a1c590l }, + { 0x837a819bf5cbdb25l,0x2a4fd1d8de090249l,0x622a7de774990e5fl, + 0x840fa5a07945511bl }, + 0 }, + /* 7 << 16 */ + { { 0x26e08c07e3533d77l,0xd7222e6a2e341c99l,0x9d60ec3d8d2dc4edl, + 0xbdfe0d8f7c476cf8l }, + { 0x1fe59ab61d056605l,0xa9ea9df686a8551fl,0x8489941e47fb8d8cl, + 0xfeb874eb4a7f1b10l }, + 0 }, + /* 9 << 16 */ + { { 0x9164088d977eab40l,0x51f4c5b62760b390l,0xd238238f340dd553l, + 0x358566c3db1d31c9l }, + { 0x3a5ad69e5068f5ffl,0xf31435fcdaff6b06l,0xae549a5bd6debff0l, + 0x59e5f0b775e01331l }, + 0 }, + /* 10 << 16 */ + { { 0x2cc5226138634818l,0x501814f4b44c2e0bl,0xf7e181aa54dfdba3l, + 0xcfd58ff0e759718cl }, + { 0xf90cdb14d3b507a8l,0x57bd478ec50bdad8l,0x29c197e250e5f9aal, + 0x4db6eef8e40bc855l }, + 0 }, + /* 11 << 16 */ + { { 0xd5d5cdd35958cd79l,0x3580a1b51d373114l,0xa36e4c91fa935726l, + 0xa38c534def20d760l }, + { 0x7088e40a2ff5845bl,0xe5bb40bdbd78177fl,0x4f06a7a8857f9920l, + 0xe3cc3e50e968f05dl }, + 0 }, + /* 13 << 16 */ + { { 0x10595b5696a71cbal,0x944938b2fdcadeb7l,0xa282da4cfccd8471l, + 0x98ec05f30d37bfe1l }, + { 0xe171ce1b0698304al,0x2d69144421bdf79bl,0xd0cd3b741b21dec1l, + 0x712ecd8b16a15f71l }, + 0 }, + /* 15 << 16 */ + { { 0xe89f48c85963a46el,0x658ab875a99e61c7l,0x6e296f874b8517b4l, + 0x36c4fcdcfc1bc656l }, + { 0xde5227a1a3906defl,0x9fe95f5762418945l,0x20c91e81fdd96cdel, + 0x5adbe47eda4480del }, + 0 }, + /* 16 << 16 */ + { { 0xa7a8746a584c5e20l,0x267e4ea1b9dc7035l,0x593a15cfb9548c9bl, + 0x5e6e21354bd012f3l }, + { 0xdf31cc6a8c8f936el,0x8af84d04b5c241dcl,0x63990a6f345efb86l, + 0x6fef4e61b9b962cbl }, + 0 }, + /* 17 << 16 */ + { { 0xaa35809ddfe6e2a0l,0xebb4d7d4356a2222l,0x7d500a6a319f33b7l, + 0x4895a47d4ac99011l }, + { 0x300ab40bdf3812b2l,0xd0764ec88aec8b9fl,0x86b61d95e591b2a7l, + 0xc1b2a0b72ed74603l }, + 0 }, + /* 19 << 16 */ + { { 0x6001bf5d3849c680l,0xd7a1a4e4c1d3faccl,0xa0f2776418c5e351l, + 0x0849c0736c29c623l }, + { 0x3317e143ac751c0cl,0x9bcb1f3eda06200bl,0x40a63a75541419b5l, + 0x8fad9c983f62c513l }, + 0 }, + /* 21 << 16 */ + { { 0xacff0828d03b2242l,0x5a9375c43abb7389l,0x41b1a318d0192baal, + 0x105bd3100458e97bl }, + { 0x71582dc7ed496315l,0x8ab2884a4d4bda18l,0xb8b638b494bc5bb8l, + 0xb42ed1309500bb04l }, + 0 }, + /* 23 << 16 */ + { { 0x73e04f02ad1ed952l,0x680051cadfa5bdb7l,0xbe0bef3c0c7437b9l, + 0x45d6f3a40e65e627l }, + { 0x5295e060c9436a75l,0xbe84ba78d289ba9el,0x350887fd69c09364l, + 0xf27bfd17671c64a7l }, + 0 }, + /* 25 << 16 */ + { { 0xc8afbdc3adf6ffc5l,0x4a4fb35876385891l,0xc7fa86424d41453fl, + 0x19490b7672eedd06l }, + { 0xc883e45337d22d6al,0x8e6e38e4a9009f96l,0x44e2811eb1c560c6l, + 0x8a0021bf4439cfcfl }, + 0 }, + /* 27 << 16 */ + { { 0xba768f8b7615a327l,0x6c8b320d7b15bbe7l,0x5d8d5bcbaaa9ca64l, + 0x19a2b99f3d13cdfdl }, + { 0x858288a26f172e10l,0x2412a4da37a00f94l,0xfc67fd2edaa7f6c6l, + 0x4aea0eadafa2a5c5l }, + 0 }, + /* 28 << 16 */ + { { 0x5c80ccef6cd77b30l,0x49978299ec99b6d0l,0x6bf4485eb939d335l, + 0xc53e61ab86d7c147l }, + { 0xdd948052fb601dddl,0x34c5eb393511dd48l,0x91f5c67600e6f61cl, + 0x33f1b525b1e71f34l }, + 0 }, + /* 29 << 16 */ + { { 0xb4cb4a151d2dad36l,0x709a61631e60b60dl,0x2f18f3bd932ece4fl, + 0x70f495a8e92368bel }, + { 0x6e88be2bb7aeaa6fl,0x4efebd9ae1bf1d6el,0x49925e6e44e94993l, + 0x33b7aba0ef0517dcl }, + 0 }, + /* 31 << 16 */ + { { 0x69ce1f207afe6c37l,0xe1148ba984f68db5l,0x32668bdc2c594a8al, + 0x2cb60d3063ac4fb3l }, + { 0x5e6efe1dd9e036f8l,0x917cb2a27db4739fl,0x70ea601ded4e0b5el, + 0x5928f068ae7ac8a6l }, + 0 }, + /* 33 << 16 */ + { { 0x9e4ad0073f2d96abl,0x51a9697f2d058c03l,0xcd5c0a7522d1e795l, + 0xaa1a121c2ac4f019l }, + { 0xa837c14c3e3631f4l,0x6a997381236a5576l,0xb305e7db2753782bl, + 0xae561b0237243afbl }, + 0 }, + /* 34 << 16 */ + { { 0x20176baca787897bl,0x057b8b979a9f67d9l,0xe7d5c4f761e14e09l, + 0x8e4856901e6cd6d0l }, + { 0x3eeffbba9b925d52l,0xe651a5383046927bl,0x02326d1fe92d4352l, + 0xad2d6493d697369fl }, + 0 }, + /* 35 << 16 */ + { { 0xe9de299c548c4ca5l,0x66f64ef54be3bde3l,0xcf6d39ebf2d5ebc9l, + 0x665ca727898953e1l }, + { 0x521ec435e33ac1b4l,0x8418fa7534ab2b82l,0x94d6c0c4771a3a87l, + 0x21feb6054859ee22l }, + 0 }, + /* 36 << 16 */ + { { 0xde7153f8eed9dd1dl,0xba09ad1152ebcb2el,0xaa41b015e1843fb6l, + 0xf933a2abdd4ce6f0l }, + { 0x777f834313f6b83fl,0x28df7da4db113a75l,0x6d7d1b3c72a5d143l, + 0x6f789698966c6ddfl }, + 0 }, + /* 37 << 16 */ + { { 0x57d11ed7a95e704el,0x7d5ac6dc380ad582l,0xb175421d5ab6e377l, + 0x4e383b0ba760dd4dl }, + { 0xde07b81a352b6cb3l,0x342abe825c2e1704l,0x90988de20dd48537l, + 0x4a7fec0544821591l }, + 0 }, + /* 39 << 16 */ + { { 0xb0e4d17c90a94eb7l,0x27555067aceb0176l,0x587576e15c38c4e2l, + 0xe647d9dd445f2880l }, + { 0x00beb2f5ca502f83l,0x4e89e638c44767c7l,0xbef361da154a5757l, + 0x2dc632a2dc0675f2l }, + 0 }, + /* 40 << 16 */ + { { 0xed439a33a72ba054l,0xa3170a15ead265bal,0xcf7eb903fe99a58el, + 0xcf6db0c633d80c26l }, + { 0xd031255ef613e71al,0x12ccbe5718ca255cl,0xdd21d0537808c40dl, + 0xf5488ebc3af2be6bl }, + 0 }, + /* 41 << 16 */ + { { 0x589a125ac10f8157l,0x3c8a15bde1353e49l,0x7d9bbd0c22ce2dd0l, + 0xdfcd019211ac7bb1l }, + { 0x0e1d67151193c5b1l,0xd4de115ab0e8c285l,0x0b3e94c2272c29fel, + 0xea640843c8213581l }, + 0 }, + /* 43 << 16 */ + { { 0x7a01aeed6aca2231l,0x8135cf2ace80abbel,0xdc1a41b2ae5fdec9l, + 0xde34ea4da0174364l }, + { 0xa5104e453cf8b845l,0x4b6fd986675ba557l,0x4bc750af29c8cb4al, + 0x8bebb266583f9391l }, + 0 }, + /* 44 << 16 */ + { { 0x47110d7c1be3f9c5l,0x12b9e4485eadb4ddl,0x6e8c09870b713d41l, + 0xe1e20356733d56ael }, + { 0xe68d6bab445ea727l,0x9ef4f6eac934a1a4l,0xe0155547f8cef1c3l, + 0xdb5c3909159bdcbfl }, + 0 }, + /* 45 << 16 */ + { { 0xef0449cb32fa8a37l,0x95071f5dcd246405l,0x1c56ad776c598891l, + 0x981781de0fa9cd42l }, + { 0x0f93d456d29c0500l,0x43aa7bc1483f52c4l,0xd7c8736666c8abadl, + 0x47552530ea5050efl }, + 0 }, + /* 46 << 16 */ + { { 0x40dd9ca9fa9b8d3dl,0xf27b7bc056da41d9l,0x87967f4b66db8845l, + 0xf6918c9444de6bc7l }, + { 0x4d76d51135568d4dl,0x7ab18f9a40e7fa5al,0x069a44bba5bbbdc6l, + 0x19e6c04bb4c8f808l }, + 0 }, + /* 47 << 16 */ + { { 0x5fd2501108b2b6c7l,0xcce85a3ec41cad21l,0x90857daffdd70387l, + 0x7a679062c63789f4l }, + { 0x9c462134ef8666e2l,0xcb7dba108c8505bdl,0x7c4a7e2fc610f2e7l, + 0x22906f65d68315f9l }, + 0 }, + /* 48 << 16 */ + { { 0xf2efe23d442a8ad1l,0xc3816a7d06b9c164l,0xa9df2d8bdc0aa5e5l, + 0x191ae46f120a8e65l }, + { 0x83667f8700611c5bl,0x83171ed7ff109948l,0x33a2ecf8ca695952l, + 0xfa4a73eef48d1a13l }, + 0 }, + /* 49 << 16 */ + { { 0x41dd38c1118de9a0l,0x3485cb3be2d8f6f5l,0xd4bac751b1dcc577l, + 0x2148d93fed12ea6bl }, + { 0xde3504729da8cb18l,0x6046daf89eb85925l,0xddbc357b942b1044l, + 0x248e7afe815b8b7cl }, + 0 }, + /* 51 << 16 */ + { { 0xd4bb77b3acb21004l,0xe9f236cf83392035l,0xa9894c5c52133743l, + 0x4d6112749a7b054al }, + { 0xa61675ea4ba2a553l,0x59c199681da6aa78l,0x3988c36590f474del, + 0x73e751bbd001be43l }, + 0 }, + /* 52 << 16 */ + { { 0x97cacf846604007dl,0x1e92b4b22d47a9f1l,0x858ae0d6374ed165l, + 0x4c973e6f307aefb8l }, + { 0x6f524a238a10eb72l,0x7b4a92a9eb2849d6l,0x3678bda42fe91eddl, + 0x56092acd7c0fc35cl }, + 0 }, + /* 53 << 16 */ + { { 0x93bea99b1b9b43c4l,0x2f6af6f3e145fda2l,0x862f0607278adf0dl, + 0x647be08398456ccal }, + { 0xce79ba1487250c28l,0x1c1c4fc8efedab42l,0x966f612af90caa8dl, + 0xb1a2cf6e72c440f8l }, + 0 }, + /* 55 << 16 */ + { { 0x2fca1be45b3b7dd5l,0x453c19853c211bcal,0x313cb21969a46484l, + 0x66082837414bd5dfl }, + { 0xab7a97bf2ac1cdf7l,0x45cd1792676d778fl,0x42fb6c4f6a5b560al, + 0x45747fe30b8f17e9l }, + 0 }, + /* 57 << 16 */ + { { 0x38b6db6235db6218l,0xa10cdfe1bb54bacal,0x56fd4a1d610f7f6bl, + 0xc4bea78b76d183d7l }, + { 0xc0e6ca9fbf730d26l,0x1b1e271aed6cf535l,0x6fef275faadbe375l, + 0xfa2e8da903e489bal }, + 0 }, + /* 59 << 16 */ + { { 0x6f79d25c7c4626ecl,0xfe27690232d55d6cl,0x3f5c5768afa19ce3l, + 0xa1373777f8834739l }, + { 0x761d67a8a4ce960al,0xb34de1ea459e656al,0x8725b0f09db6f269l, + 0x75316f250dbfe22el }, + 0 }, + /* 60 << 16 */ + { { 0x091d5b631a093b40l,0xb85c1c075862f24al,0xc5d74eb53e8f85bfl, + 0xf51c7746cab22456l }, + { 0xc25cb8d9e761da89l,0x2670ec2fc0f028b5l,0x873fd30d2db9af5cl, + 0x3d0f1ea18262565el }, + 0 }, + /* 61 << 16 */ + { { 0x8f9492c261c23b3cl,0xd366baeb631688a4l,0x55e759e78093bb07l, + 0xf6d0eaf47218f765l }, + { 0xb8a174ff54ca583bl,0x790f10e0b23d14cel,0xfebe7333be83cbbal, + 0xfeb6dcc5eed67536l }, + 0 }, + /* 63 << 16 */ + { { 0x175b3bacce027e5bl,0xe0728a99c48252c4l,0x0be25d4507a39c7cl, + 0xcb9c2d3aba8e8c72l }, + { 0x6185a48d1abd459al,0x27207feadff9a27bl,0xfd92e8231d34393fl, + 0x738511534351d965l }, + 0 }, + /* 64 << 16 */ + { { 0xfcde7cc8f43a730fl,0xe89b6f3c33ab590el,0xc823f529ad03240bl, + 0x82b79afe98bea5dbl }, + { 0x568f2856962fe5del,0x0c590adb60c591f3l,0x1fc74a144a28a858l, + 0x3b662498b3203f4cl }, + 0 }, + /* 65 << 16 */ + { { 0x8ede0fcdc11682eel,0x41e3faa1b2ab5664l,0x58b2a7dc26a35ff5l, + 0x939bcd6b701b89e9l }, + { 0x55f66fd188e0838fl,0x99d1a77b4ff1f975l,0x103abbf72e060cc5l, + 0x91c77beb6bc4bdbbl }, + 0 }, + /* 71 << 16 */ + { { 0xcd048abca380cc72l,0x91cab1bbd0e13662l,0x68115b18686de4cel, + 0x484724e63deccbf5l }, + { 0xf164ba54f176137el,0x5189793662ab2728l,0x6afdecf9b60a5458l, + 0xca40472d0aabafd2l }, + 0 }, + /* 77 << 16 */ + { { 0x7a9439183b98d725l,0x1c1763e8ece1ea3cl,0x45c44ef639840476l, + 0x689271e69c009133l }, + { 0xa017405f56a51fe1l,0xd54cc7253e0d0970l,0x212ad075cfe09e8bl, + 0x999f21c37af7bf30l }, + 0 }, + /* 83 << 16 */ + { { 0xdc2a2af12bf95f73l,0xb88b4ca76de82cbel,0xa31a21aaecb8e84el, + 0x86d19a601b74f5bel }, + { 0xc68bf64406008019l,0xe52ab50e9431c694l,0x6375463d627ab11cl, + 0xdd3eeaa03c0ef241l }, + 0 }, + /* 89 << 16 */ + { { 0x608d9cb323f1caf8l,0x95069450b1700741l,0xe3132bd2bc2fa7aal, + 0xc4f363e7f64e4f06l }, + { 0xb059c4191ca888c2l,0x1004cb1f8d17bf5dl,0x6b6ba6f934ea5711l, + 0x071d94abd79b2c8al }, + 0 }, + /* 95 << 16 */ + { { 0xc7ef9b42d147a39dl,0x36dd5d770a10cd5bl,0x3bf6cc77d0eea34bl, + 0x60c84591197479c7l }, + { 0xf95860ac50ba50edl,0xe1c94a8dc4cdc8fal,0x780818d685e24a23l, + 0x1950e3c0c8abbd27l }, + 0 }, + /* 101 << 16 */ + { { 0x9908c694ae04778el,0x2e37a6790a0d36ffl,0x212a340f52b067bdl, + 0xec89c9fad080b914l }, + { 0x920dc2f005ab8a23l,0xecff5c78655e8984l,0x80eedd34f66211acl, + 0xa7a56366ef58d4d8l }, + 0 }, + /* 107 << 16 */ + { { 0x4f95debe2bca42f0l,0xf0346307844334d2l,0x7003a60521d600aal, + 0x1eb98c6365c5248al }, + { 0x6757b3822fa202cal,0x32765d399fb12f36l,0xe851b476d7b44c9al, + 0x27cd7d1b4e0bab4cl }, + 0 }, + /* 113 << 16 */ + { { 0xd0c1f7c9c43ea1a3l,0x73d944f49f42907dl,0xd113f34619352c92l, + 0x86a1ad53b149cdc1l }, + { 0x32c34e8f848d1be4l,0xba8afda7c3d9360bl,0x17e8bc32eea8bf96l, + 0x3174cae499c87febl }, + 0 }, + /* 116 << 16 */ + { { 0x4b215f016671b47el,0xb67633ca4a8dae2al,0x2915120f79fd3cdbl, + 0xc1f8a06fb064e6del }, + { 0xf4d5368cc1d57420l,0x6ada51a8e18de475l,0xa0f0d47cc749d4b0l, + 0xabfa2c0074526aa5l }, + 0 }, + /* 119 << 16 */ + { { 0xf752f6659e5ce44fl,0x7b97ebfa189d35ecl,0x9540cbb90fc609abl, + 0x19c1dc6999632cc8l }, + { 0x0a957700e08ca9a8l,0xb0cd0ab7a3246a4el,0xca687cfcc8d6a544l, + 0xb6281f0035f82a77l }, + 0 }, + /* 125 << 16 */ + { { 0x547027012b818036l,0xf72315f729c8f14cl,0x95f1bc15230e74bel, + 0x2e7c492f1abe20d4l }, + { 0xe1ea8b1cd7e78ab1l,0xc3f6ba59043585adl,0xac404ea9477ac053l, + 0xaa6872914ec6d0e3l }, + 0 }, + }, + { + /* 0 << 24 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 24 */ + { { 0xd9d0c8c4868af75dl,0xd7325cff45c8c7eal,0xab471996cc81ecb0l, + 0xff5d55f3611824edl }, + { 0xbe3145411977a0eel,0x5085c4c5722038c6l,0x2d5335bff94bb495l, + 0x894ad8a6c8e2a082l }, + 0 }, + /* 3 << 24 */ + { { 0xd1e059b21994ef20l,0x2a653b69638ae318l,0x70d5eb582f699010l, + 0x279739f709f5f84al }, + { 0x5da4663c8b799336l,0xfdfdf14d203c37ebl,0x32d8a9dca1dbfb2dl, + 0xab40cff077d48f9bl }, + 0 }, + /* 4 << 24 */ + { { 0xf2369f0b879fbbedl,0x0ff0ae86da9d1869l,0x5251d75956766f45l, + 0x4984d8c02be8d0fcl }, + { 0x7ecc95a6d21008f0l,0x29bd54a03a1a1c49l,0xab9828c5d26c50f3l, + 0x32c0087c51d0d251l }, + 0 }, + /* 5 << 24 */ + { { 0xf61790abfbaf50a5l,0xdf55e76b684e0750l,0xec516da7f176b005l, + 0x575553bb7a2dddc7l }, + { 0x37c87ca3553afa73l,0x315f3ffc4d55c251l,0xe846442aaf3e5d35l, + 0x61b911496495ff28l }, + 0 }, + /* 7 << 24 */ + { { 0x4bdf3a4956f90823l,0xba0f5080741d777bl,0x091d71c3f38bf760l, + 0x9633d50f9b625b02l }, + { 0x03ecb743b8c9de61l,0xb47512545de74720l,0x9f9defc974ce1cb2l, + 0x774a4f6a00bd32efl }, + 0 }, + /* 9 << 24 */ + { { 0x327bc002b0131e5bl,0x1739e6d5cb2514d9l,0xc8cbdafe55a81543l, + 0x5bb1a36ce1137243l }, + { 0x205da3c517325327l,0xc35c1a36515a057el,0xf00f64c942925f9bl, + 0xbd14633cb7d59f7al }, + 0 }, + /* 10 << 24 */ + { { 0xae2ad171656e8c3al,0xc0e2a4631acd0705l,0x006f6a8aa0b6055cl, + 0xaf4513d72b65a26el }, + { 0x3f549e14d616d5bcl,0x64ee395571253b1fl,0xe8b10bc1b8ce243al, + 0xbcbeace5913a4e77l }, + 0 }, + /* 11 << 24 */ + { { 0x47c1004341f37dbdl,0x96eccae36168ecf6l,0x65bde59d1ca46aa3l, + 0x38a7027ab8698ffal }, + { 0xa2b89dc86dc34437l,0x5a0a118d43a4153fl,0x9e330a861ce22fd8l, + 0x28382af6b3bbd3bcl }, + 0 }, + /* 13 << 24 */ + { { 0x0b2e27c0d81e0271l,0xa67a7596117a317cl,0x17f08928a6723d99l, + 0x71a75681485310a3l }, + { 0x90465462afb66ca9l,0x185e97ccfbbe229dl,0x6a1a606addad8fc2l, + 0x2431f316b3c797cfl }, + 0 }, + /* 15 << 24 */ + { { 0x4703401193529432l,0x1f106bdd30743462l,0xabfb9964cd66d8cal, + 0x934d9d5ae9bdadd5l }, + { 0x5976d815908e3d22l,0x344a362f28e057bdl,0xf92cdadc5443dfb3l, + 0x001297adf089603bl }, + 0 }, + /* 16 << 24 */ + { { 0x7f99824f20151427l,0x206828b692430206l,0xaa9097d7e1112357l, + 0xacf9a2f209e414ecl }, + { 0xdbdac9da27915356l,0x7e0734b7001efee3l,0x54fab5bbd2b288e2l, + 0x4c630fc4f62dd09cl }, + 0 }, + /* 17 << 24 */ + { { 0x4a2fce605044066bl,0x904a019cfa3a47f4l,0xba81ea9c0c5c0a60l, + 0xd7e4ea0d96c098bdl }, + { 0xefe700419cd50a02l,0xc0c839d42d7f048cl,0xe2daf264e09b561fl, + 0x0cbc13185034b18bl }, + 0 }, + /* 19 << 24 */ + { { 0x11e5f2e388323f7al,0xe07a74c2927584cdl,0x1e774b3495613d2dl, + 0x9c9b52c52c787488l }, + { 0x3cdd3c3ebe421f08l,0x5ff7819e223e3d5fl,0xba8739b2c1da09b9l, + 0x6b7263164e8b491bl }, + 0 }, + /* 21 << 24 */ + { { 0xb5afd13ca0943befl,0xd651772957abb1ccl,0x9d5a52dc9b61b5bcl, + 0x85cefaa6806e31cdl }, + { 0xab84257a720a1deal,0x6a60261bced70d35l,0xc023f94db9d6da61l, + 0x947f7eec54a0ae0el }, + 0 }, + /* 23 << 24 */ + { { 0xc3b787569f83b787l,0xd6d249263694ddd7l,0x58d248945d70a02el, + 0xac16670e8c278c6al }, + { 0x71a94d58e370b6e6l,0xe4d763840253db05l,0x99b1c98814b32cfel, + 0x4e6bd870cc78cc95l }, + 0 }, + /* 25 << 24 */ + { { 0xf5f7ca79c8b63614l,0xf3bfb2158af4903cl,0x2bdb9f5496d47bd3l, + 0xd6e715300e8a63bal }, + { 0x67e90a497a93bec4l,0x8613478b8c1e63eel,0xe36bd9c8f2dde561l, + 0x681486518a768689l }, + 0 }, + /* 27 << 24 */ + { { 0xef617a9494aa531cl,0x9ac35e2fd6f4ad87l,0xbcd2a047122468fbl, + 0xbd7a423fef7c5ca6l }, + { 0xab58cb52064c8040l,0x93ef4ed54a644716l,0xf7d17097c32cd48dl, + 0xb249a173d17fcf42l }, + 0 }, + /* 28 << 24 */ + { { 0x66fe0fffe298cdf5l,0x3f61bea47b2e51b6l,0x7d372117bad3afa4l, + 0x6521a09cef656e2fl }, + { 0xb3b8c966e8a58fe7l,0x25203a115a47ebc7l,0xfe81588d5c4be573l, + 0x6132e2f31f49a03cl }, + 0 }, + /* 29 << 24 */ + { { 0xbbe5c108b7a7ecc4l,0x62a5a78ebfd22e4cl,0xb7974033df188bd2l, + 0xcf11deea4df7d1ael }, + { 0x99cc774a53ace3eal,0xe0373a71105cc1f6l,0xd751987f133d7a20l, + 0xab86ee04ae215871l }, + 0 }, + /* 31 << 24 */ + { { 0x2094f9a280cd10e6l,0x045232aa7b8a0da7l,0x969a81b69c03244el, + 0x1293b4ca7e98d955l }, + { 0x1631421dd68f3ab0l,0xa0106422c3738c82l,0xc5f43845f82c4ff9l, + 0xb479acbe1aa0f58fl }, + 0 }, + /* 33 << 24 */ + { { 0xf1db0267f67683cfl,0xa6b13c9e44ce009dl,0x04b4eed505884a69l, + 0xf2ff9c16d9087a0bl }, + { 0x2c53699b3e35b4a6l,0x5020c0142369afb8l,0xf83bfe0095be37f1l, + 0xd300d8c553b29d80l }, + 0 }, + /* 34 << 24 */ + { { 0x16893055811cf4bbl,0x580dd1e55aeb5027l,0xcaf47fba5ae3c71cl, + 0xde79698129ebbb07l }, + { 0xbed1db33d262cdd3l,0x78315e3748c7313bl,0xfc9561f02fe1368dl, + 0xe0209698ccacacc7l }, + 0 }, + /* 35 << 24 */ + { { 0xd61af89a781ece24l,0xf3b90626008f41e9l,0xd715dbf7c5693191l, + 0x8d6c05de6f299edel }, + { 0xf18d62637ca50aacl,0x7987bf5cb0dd5fdcl,0x424136bd2cfa702bl, + 0xaa7e237ded859db2l }, + 0 }, + /* 36 << 24 */ + { { 0xde7169e4e5d41796l,0x6700333e33c0a380l,0xe20b95780343a994l, + 0xa745455e1fb3a1c3l }, + { 0x97e0ff88ce029a7fl,0x3b3481c976e384bcl,0x028b339dddad5951l, + 0xa1fdcdbae4b95cfcl }, + 0 }, + /* 37 << 24 */ + { { 0xcc9221baed20c6adl,0xf2619a51fa9c73aal,0xfc2cff847d7f55a5l, + 0xd56c23d65f01d4dal }, + { 0x6d20f88cb3d84d5fl,0x048825f75dcc615dl,0x73634d3f85631a6el, + 0xa57a02e3ad7b2e2dl }, + 0 }, + /* 39 << 24 */ + { { 0x067a8dcf08aa81ffl,0x62948258c23f3d16l,0xb61bd04316f2fe7bl, + 0xf250f769b6a766b1l }, + { 0x32df97246d0b241el,0xb736e4bb714e5f88l,0x50da15022c1d40d7l, + 0x013e0edebdd285a4l }, + 0 }, + /* 40 << 24 */ + { { 0x1b92c3a0181a5d8fl,0x6429531d9adb77c7l,0x629152b53af710eel, + 0x4e3f27370bd5647el }, + { 0xfb7c392b77553c7dl,0xa930abacefe78c87l,0xf80c8cd6a05a6991l, + 0x751469b71be5f6f5l }, + 0 }, + /* 41 << 24 */ + { { 0xf89f2b0b3e2f2af0l,0x52f634099eefc39al,0x505005c679906cb6l, + 0x820c2216b2de0b1el }, + { 0x96f0f2831f20ad7al,0xcd33125c718ffcb0l,0xf6130ef278f0c578l, + 0x4cda2471d0b76b95l }, + 0 }, + /* 43 << 24 */ + { { 0x611dd83f39485581l,0x96c47051803e1b20l,0xefacc736830f44c7l, + 0x5588d8ce688b12bal }, + { 0x44f4edf3eee70fadl,0x1026dfd8869539f7l,0xa4c146ee8ddb0e00l, + 0x9f4f55816efb41c8l }, + 0 }, + /* 44 << 24 */ + { { 0x6036ed0236cbace7l,0x5a70e4abada837ddl,0xf06918aff10b2fefl, + 0x08a8a9f69fd31590l }, + { 0x6c4a1ba6916af88dl,0x4868bc1466016037l,0x06d345af164228a9l, + 0x2c1961d19b550dd9l }, + 0 }, + /* 45 << 24 */ + { { 0x8b72775c6851f0acl,0x7827242bd70f5975l,0x2de91f1e34db4a6fl, + 0x586bf3d58538f5eel }, + { 0xf0a15aed25d9a09bl,0x43018e56f74deb46l,0xc2af1ad0f50e0e67l, + 0x49cc9528b10cff6fl }, + 0 }, + /* 46 << 24 */ + { { 0x05eb146c9d55c425l,0xe2b557ccbc62261fl,0x2a716301bd077089l, + 0x83a63c81e0527d02l }, + { 0x055ff7f8a0d9203bl,0x05d09f0525bf5a04l,0x2e44545fb3eb0b30l, + 0xed7c57c4d279a1adl }, + 0 }, + /* 47 << 24 */ + { { 0x6928f6e45e0ebdd5l,0xd7e44ddf092d233bl,0xe7148066d1b7026fl, + 0xf645a2e53d5f25c3l }, + { 0x6eeb25ee58ff9eb4l,0x60f1fcf737f87ebfl,0x9eaaf1e5c4679c70l, + 0x4609fb13b7b7dc7el }, + 0 }, + /* 48 << 24 */ + { { 0xae915f5d5fa067d1l,0x4134b57f9668960cl,0xbd3656d6a48edaacl, + 0xdac1e3e4fc1d7436l }, + { 0x674ff869d81fbb26l,0x449ed3ecb26c33d4l,0x85138705d94203e8l, + 0xccde538bbeeb6f4al }, + 0 }, + /* 49 << 24 */ + { { 0x27f317af2b33987fl,0xd2d3cf5d51e59588l,0x333999bd031f27c9l, + 0x6ddfa3f22e0a3306l }, + { 0x23e0e651990041b0l,0xf028aba1585837acl,0x1c6ad72b25226f53l, + 0xf243c991d1fca64al }, + 0 }, + /* 51 << 24 */ + { { 0x72b8a13272cbae1fl,0xfe0b1c4fbfdbd64al,0x98bc7876c5e76921l, + 0x51c726bfdb1f5af7l }, + { 0x97e88a842c186e8bl,0x9ed99516ed8eb7b4l,0x3e54a17dafc818ebl, + 0xfcfbf25a1e8f77d8l }, + 0 }, + /* 52 << 24 */ + { { 0x7780d7d68f7d5c6el,0x6725b49a454101e6l,0xceddc26586b0770cl, + 0xc26624615666f504l }, + { 0x16b77477ce040f75l,0x13f9113c293f8b45l,0xff0cfa07e2dcc91el, + 0x1948d8bd41c202f5l }, + 0 }, + /* 53 << 24 */ + { { 0x4c6ae39a1dfbe13al,0xafb1e5c46be9c200l,0x39e728d168bb08c3l, + 0xc794b905acc9166fl }, + { 0x1cb0dec2d9c7c3e4l,0xc4c3053289f14d65l,0x4af80801a6a9d609l, + 0x79d7e82de0d6ab24l }, + 0 }, + /* 55 << 24 */ + { { 0xb905c6af8ad4cf6el,0x785590b0f6d1be13l,0x78f402c2a0ef76bel, + 0x739b22ea5c19a40bl }, + { 0xd4d3262553d596b6l,0x01598eb4d571666bl,0xf8dc150b8173486al, + 0xd8aa43af15e94f09l }, + 0 }, + /* 57 << 24 */ + { { 0xcfa387cd984393b5l,0x1645659e21a1bf92l,0xb4ab3966dd46c7eel, + 0xcf8c296d89482623l }, + { 0x72e4d01cf976b4c0l,0x44ad07e8fa0fa5ebl,0xd6c82681b486fdd2l, + 0x2d9074f89b8845b4l }, + 0 }, + /* 59 << 24 */ + { { 0x96e4fc08d96862dbl,0xf9e29bb6c50c14b2l,0xfedaad64f8f9be75l, + 0xab6b2d79ae9e1274l }, + { 0x033e3eb58d84dec0l,0xc136904ccbd113e7l,0xb82b0aed6061f289l, + 0x3476d9247b699e25l }, + 0 }, + /* 60 << 24 */ + { { 0x8fb5ceeb969231dcl,0xaed13be1686ff6cdl,0x71d7c67bdd69db87l, + 0x49613e08fb53f33al }, + { 0x2899729ead8e802fl,0x83bfde49d1982a1dl,0x675c45ea878239d2l, + 0xb7bf59cd0d8240d3l }, + 0 }, + /* 61 << 24 */ + { { 0x853d8cd1baf53b8bl,0x9c73d04cff95fc18l,0xae8a94412d1d6aacl, + 0xd8a15ce901500b70l }, + { 0xaef813499aacba59l,0x2cd2ba0ac493cd8dl,0x01c37ee1f398f034l, + 0xed72d51d0f7299fcl }, + 0 }, + /* 63 << 24 */ + { { 0x2c204940e7592fb1l,0xcc1bb19b49366f08l,0x31855e8a7c927935l, + 0x16f7e9a2c590b81dl }, + { 0xa5fbb7c1ed8df240l,0x7b5204122de2d7f5l,0x7eb1eb989a637588l, + 0x5ef4eca89540d2e8l }, + 0 }, + /* 64 << 24 */ + { { 0x55d5c68da61a76fal,0x598b441dca1554dcl,0xd39923b9773b279cl, + 0x33331d3c36bf9efcl }, + { 0x2d4c848e298de399l,0xcfdb8e77a1a27f56l,0x94c855ea57b8ab70l, + 0xdcdb9dae6f7879bal }, + 0 }, + /* 65 << 24 */ + { { 0x811e14dd9594afb8l,0xaf6c1b10d349124al,0x8488021b6528a642l, + 0xecf6834341cf1447l }, + { 0x7a40acb756924446l,0xd9c11bbed98ec4cfl,0x0cef00bfb2bff163l, + 0xfaaad8015432803bl }, + 0 }, + /* 71 << 24 */ + { { 0x5a217d5e6b075cbel,0x7ef88d1dc89b513bl,0xb6d015da0531c93bl, + 0x477b502a6333834al }, + { 0x4655e48b2fb458d5l,0x93f21a7cb7674ca8l,0xa0616786502d1f3al, + 0x82d16d17f26bb6ccl }, + 0 }, + /* 77 << 24 */ + { { 0x3d995aa9183c1688l,0xa125906c3766d2e8l,0x23ed7871c5f10d5bl, + 0xdfe1e1cc6df80368l }, + { 0x8bfcb54271eaae2cl,0xe94e6f910945a7bbl,0xd543ef90862f650al, + 0x0dc043b803eed66bl }, + 0 }, + /* 83 << 24 */ + { { 0x0c6a5620060d2ccdl,0xcd8200e37a8a03a4l,0x6018d304793867e6l, + 0xad23dd61a74d054dl }, + { 0x5a856faeebc21eb4l,0x66be16714b5cd7dbl,0xe0d0441ec75f8c9dl, + 0xb80ca9ecf90dbc6dl }, + 0 }, + /* 89 << 24 */ + { { 0xbd6902ccd24692cbl,0xbcce6bbc21920408l,0x40f120ca55dec4c5l, + 0xd9f1f5ef5361c8b3l }, + { 0x535d368226935dffl,0x9635447b01a9998al,0x8c4ec40d99e36d12l, + 0xbaeef8912b793369l }, + 0 }, + /* 95 << 24 */ + { { 0xded3a51c1cd887ebl,0xd43225568376515cl,0xdaf3a2271ca7c097l, + 0x089156fdecd4d90cl }, + { 0x2b354810ca0727c9l,0xb7257c1966c19d8cl,0x5e68a379432d5072l, + 0x75c04c2443e585c7l }, + 0 }, + /* 101 << 24 */ + { { 0xb5ba2a8fe5e0952fl,0x2c2d086811040b4el,0x27448bd5f818e253l, + 0x720f677987a92c85l }, + { 0x2c9b2367b9d035fal,0xf18ad8ce16c15ab9l,0xd65a360841bd57eel, + 0xeb4b07c9ff6ae897l }, + 0 }, + /* 107 << 24 */ + { { 0xcffb6d71d38589acl,0x812372920fa509d3l,0x94db5ba6e54725e8l, + 0x1ad2b4206cfbb825l }, + { 0x8592c1f238cfb9f2l,0xbe8e917e0eec6a27l,0x53921bfe9d93d42fl, + 0x1aa95e6269454a35l }, + 0 }, + /* 113 << 24 */ + { { 0xc25e8934d898049dl,0xeeaf4e6d3bb3d459l,0xc3ac44447d29ad10l, + 0xccdf9fcbcef8fa04l }, + { 0x1d995a3fb9679cb9l,0x3d6c5eab46fabc14l,0xd3849ff066385d4dl, + 0xc0eb21bacff08be2l }, + 0 }, + /* 116 << 24 */ + { { 0x8213c71e90d13fd6l,0x114321149bb6b733l,0xaaf8037880ac4902l, + 0xb24e046b555f7557l }, + { 0x5f6ed2881db79832l,0xd493a758ac760e5dl,0xbc30a2a7a1c0f570l, + 0xa5009807161174e3l }, + 0 }, + /* 119 << 24 */ + { { 0x9e9b864a6889e952l,0xee908932f352f31al,0xe421f2423166b932l, + 0x6dd4aa3b7ddbdb35l }, + { 0x553cc5639e8b88a4l,0x05457f171f04704dl,0x1dcc3004c9554e6bl, + 0x3a4a3a253f1b61e7l }, + 0 }, + /* 125 << 24 */ + { { 0x7ac0a5e7c56e303al,0x7c7bab64037b0a19l,0x11f103fcc8d29a2bl, + 0x7d99dc46cf0b1340l }, + { 0x0481588ceffba92el,0x8a817356b04e77bcl,0x19edf4dbce1b708dl, + 0xa2a1f7a6e6f9d52cl }, + 0 }, + }, + { + /* 0 << 32 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 32 */ + { { 0x202886024147519al,0xd0981eac26b372f0l,0xa9d4a7caa785ebc8l, + 0xd953c50ddbdf58e9l }, + { 0x9d6361ccfd590f8fl,0x72e9626b44e6c917l,0x7fd9611022eb64cfl, + 0x863ebb7e9eb288f3l }, + 0 }, + /* 3 << 32 */ + { { 0xa18f07e0e90fb21el,0x00fd2b80bba7fca1l,0x20387f2795cd67b5l, + 0x5b89a4e7d39707f7l }, + { 0x8f83ad3f894407cel,0xa0025b946c226132l,0xc79563c7f906c13bl, + 0x5f548f314e7bb025l }, + 0 }, + /* 4 << 32 */ + { { 0x0ee6d3a7c35d8794l,0x042e65580356bae5l,0x9f59698d643322fdl, + 0x9379ae1550a61967l }, + { 0x64b9ae62fcc9981el,0xaed3d6316d2934c6l,0x2454b3025e4e65ebl, + 0xab09f647f9950428l }, + 0 }, + /* 5 << 32 */ + { { 0xc1b3d3d331b85f09l,0x0f45354aa88ae64al,0xa8b626d32fec50fdl, + 0x1bdcfbd4e828834fl }, + { 0xe45a2866cd522539l,0xfa9d4732810f7ab3l,0xd8c1d6b4c905f293l, + 0x10ac80473461b597l }, + 0 }, + /* 7 << 32 */ + { { 0xbbb175146fc627e2l,0xa0569bc591573a51l,0xa7016d9e358243d5l, + 0x0dac0c56ac1d6692l }, + { 0x993833b5da590d5fl,0xa8067803de817491l,0x65b4f2124dbf75d0l, + 0xcc960232ccf80cfbl }, + 0 }, + /* 9 << 32 */ + { { 0x35d742806cf3d65bl,0x4b7c790678b28dd9l,0xc4fcdd2f95e1f85fl, + 0xcf6fb7ba591350b6l }, + { 0x9f8e3287edfc26afl,0xe2dd9e73c2d0ed9al,0xeab5d67f24cbb703l, + 0x60c293999a759a5al }, + 0 }, + /* 10 << 32 */ + { { 0xcf8625d7708f97cdl,0xfb6c5119ea419de4l,0xe8cb234dc03f9b06l, + 0x5a7822c335e23972l }, + { 0x9b876319a284ff10l,0xefcc49977093fdcel,0xdddfd62a878fe39al, + 0x44bfbe53910aa059l }, + 0 }, + /* 11 << 32 */ + { { 0xfb93ca3d7ca53d5fl,0x432649f004379cbfl,0xf506113acba2ff75l, + 0x4594ae2103718b35l }, + { 0x1aa6cee50d044627l,0xc0e0d2b7f5c94aa2l,0x0bf33d3dee4dd3f5l, + 0xaca96e288477c97al }, + 0 }, + /* 13 << 32 */ + { { 0x995c068e6861a713l,0xa9ba339463de88dcl,0xab954344689a964fl, + 0x58195aec0f5a0d6cl }, + { 0xc5f207d5c98f8b50l,0x6600cd280c98ccf6l,0x1a680fe339c3e6c2l, + 0xa23f3931660e87c0l }, + 0 }, + /* 15 << 32 */ + { { 0x43bc1b42c78440a1l,0x9a07e22632ac6c3fl,0xaf3d7ba10f4bcd15l, + 0x3ad43c9da36814c6l }, + { 0xca11f742a0c9c162l,0xd3e06fc6c90b96ecl,0xeace6e766bf2d03fl, + 0x8bcd98e8f8032795l }, + 0 }, + /* 16 << 32 */ + { { 0xe27a6dbe305406ddl,0x8eb7dc7fdd5d1957l,0xf54a6876387d4d8fl, + 0x9c479409c7762de4l }, + { 0xbe4d5b5d99b30778l,0x25380c566e793682l,0x602d37f3dac740e3l, + 0x140deabe1566e4ael }, + 0 }, + /* 17 << 32 */ + { { 0x7be3ddb77099ae96l,0x83d6157306e0da6al,0x31bcac5f74bf9870l, + 0x7f7aa3b422b256f1l }, + { 0xff84d63caa212e20l,0x7d636556decdc8b5l,0x8fed824dbf909d62l, + 0x62d70186e5fb1445l }, + 0 }, + /* 19 << 32 */ + { { 0x8796989f67d8ab8al,0xa46282253700b772l,0xa353cadf05f799abl, + 0x7a8be2741eeb06bbl }, + { 0xf74a367e4653b134l,0x4e43449660c70340l,0xc99b6d6b72e10b18l, + 0xcf1adf0f1ba636e1l }, + 0 }, + /* 21 << 32 */ + { { 0xb0260fb57c6a0958l,0xae791b9c2fc2731el,0xb339f2bf8ce6e575l, + 0x769214a816e2639fl }, + { 0xbaf422e1346da10el,0xc7805fdf7a56f463l,0xf47b6b766f845428l, + 0x8f21369e38492948l }, + 0 }, + /* 23 << 32 */ + { { 0x2bac716a17931a90l,0x42a5e27cc8267236l,0xfd4b367c0bafeb78l, + 0x5856e69c6173db02l }, + { 0xfaac7358973d73c4l,0xbfbffcc36768d285l,0x05444ff2be3eb243l, + 0x9f8d3692f3c323fel }, + 0 }, + /* 25 << 32 */ + { { 0xac296863221c31a9l,0x46f3a24ef1ca99a9l,0xd927648a7535a864l, + 0xd7e3c47d5848e497l }, + { 0xc19595b782a98ac7l,0x9a9bf627273ff554l,0xe29aa48fb62298a1l, + 0xed3f068ee797e9e3l }, + 0 }, + /* 27 << 32 */ + { { 0x8d16a1660eb9227bl,0xe04c6bc58c37c74bl,0xd1be9585cc1ef78cl, + 0xa5cfe1962e929d9bl }, + { 0xc9b0ea21417c1cc6l,0x316352d345b79599l,0xc1502c4dc2d54af7l, + 0xe7f4412990f83445l }, + 0 }, + /* 28 << 32 */ + { { 0x0f6704abd95917e8l,0x168dafaeaec6e899l,0xd2833e8cde710027l, + 0x34ea277e68ee3c59l }, + { 0x3689e2350054d4e5l,0x6f3a568d11013943l,0xb5ce1ff69bc2b144l, + 0x705bfe7e72b33a59l }, + 0 }, + /* 29 << 32 */ + { { 0x1baa4f02c8e93284l,0xec6b93ea3c97d3e8l,0xb656c149034f8b32l, + 0x3cab9063cd4cc69fl }, + { 0xd8de5989d61031ccl,0xcf85329fc1b1de1dl,0xf18b78b323d8cb9al, + 0x6dc04bc61a6b69eal }, + 0 }, + /* 31 << 32 */ + { { 0x79cf86314a1d4f8fl,0xda5ba331aa47394el,0x36f9c0be8ff20527l, + 0xccdc719bbc7097f6l }, + { 0x2304a3ba5cb052bbl,0xab80cdea392f0ab5l,0x0ac1858bf38de03bl, + 0xd6e2119878a8f55dl }, + 0 }, + /* 33 << 32 */ + { { 0x6bdebc26584bc618l,0x499f0f1894591499l,0xd35ed50bf4a573dal, + 0x5a622e73ff2792d0l }, + { 0x8510cbce68d41a3bl,0x6610f43c94e919afl,0x4527373dc163c8a1l, + 0x50afb46f280a8a7dl }, + 0 }, + /* 34 << 32 */ + { { 0x33e779cd8de7707al,0xf94bbd94438f535bl,0x61159864be144878l, + 0xb6623235f098ce4al }, + { 0x6813b71ba65568d8l,0x6603dd4c2f796451l,0x9a97d88c8b9ee5b2l, + 0xaaa4593549d5926cl }, + 0 }, + /* 35 << 32 */ + { { 0x2e01fc75ebe75bf2l,0x8270318d6cbdd09cl,0x534e4f21d3f1a196l, + 0x6c9eaeca9459173el }, + { 0xda454fe0b642a1d4l,0xe45b69bfc4664c4al,0x4724bd423e078dc8l, + 0x39ac8fe603336b81l }, + 0 }, + /* 36 << 32 */ + { { 0x0a2e53dd302e9485l,0x75882a19deaa9ff4l,0xe283242eac8de4ddl, + 0x2742105cc678dba7l }, + { 0x9f6f0a88cdb3a8a2l,0x5c9d3338f722e894l,0xf1fa3143c38c31c1l, + 0x22137e2db18c77acl }, + 0 }, + /* 37 << 32 */ + { { 0xd821665e368d7835l,0x3300c012b596c6ecl,0xb60da7353557b2ddl, + 0x6c3d9db6fb8cf9ael }, + { 0x092d8b0b8b4b0d34l,0x900a0bf4b3d4107dl,0x75371a245e813ec3l, + 0x91125a17f2ad56d5l }, + 0 }, + /* 39 << 32 */ + { { 0x5e6594e2fe0073e6l,0x908a93778be13cb7l,0xa2c3d5c8ac26617cl, + 0xa0bab085c317c6b9l }, + { 0x0bdc183b83664109l,0x6bbba2b468f9dcd9l,0x697a50785814be41l, + 0x12a59b183a5e5f98l }, + 0 }, + /* 40 << 32 */ + { { 0xbd9802e6c30fa92bl,0x5a70d96d9a552784l,0x9085c4ea3f83169bl, + 0xfa9423bb06908228l }, + { 0x2ffebe12fe97a5b9l,0x85da604971b99118l,0x9cbc2f7f63178846l, + 0xfd96bc709153218el }, + 0 }, + /* 41 << 32 */ + { { 0xb5a85c61bfa70ca6l,0x4edc7f2d4c1f745fl,0x05aea9aa3ded1eb5l, + 0x750385efb82e5918l }, + { 0xdcbc53221fdc5164l,0x32a5721f6794184el,0x5c5b2269ff09c90bl, + 0x96d009115323ca42l }, + 0 }, + /* 43 << 32 */ + { { 0x12c73403f43f1440l,0xc94813eb66cc1f50l,0x04d5957b9b035151l, + 0x76011bca4bfaafa8l }, + { 0x56806c13574f1f0al,0x98f63a4697652a62l,0x17c63ef4a3178de9l, + 0xf7ce961a65009a52l }, + 0 }, + /* 44 << 32 */ + { { 0x58f92aebe4173516l,0xdc37d99275e42d44l,0x76dcec5b4d48e1bal, + 0x07e0608e25676448l }, + { 0xa1877bcd1d4af36al,0x38b62b3c5a8ccf0cl,0x60522e88aeab7f75l, + 0xbef213ed5e03547al }, + 0 }, + /* 45 << 32 */ + { { 0x8acd5ba4e6ed0282l,0x792328f06a04531dl,0xe95de8aa80297e50l, + 0x79d33ce07d60e05cl }, + { 0xcb84646dd827d602l,0xd3421521302a608cl,0x867970a4524f9751l, + 0x05e2f7e347a75734l }, + 0 }, + /* 46 << 32 */ + { { 0x64e4de4a01c66263l,0xbcfe16a4d0033d4cl,0x359e23d4817de1dcl, + 0xb01e812ec259449cl }, + { 0x90c9ade2df53499fl,0xabbeaa27288c6862l,0x5a655db4cd1b896fl, + 0x416f10a5a022a3d6l }, + 0 }, + /* 47 << 32 */ + { { 0x0d17e1ef98601fd5l,0x9a3f85e0eab76a6fl,0x0b9eaed1510b80a1l, + 0x3282fd747ec30422l }, + { 0xaca5815a70a4a402l,0xfad3121cf2439cb2l,0xba251af81fccabd6l, + 0xb382843fa5c127d5l }, + 0 }, + /* 48 << 32 */ + { { 0x958381db1782269bl,0xae34bf792597e550l,0xbb5c60645f385153l, + 0x6f0e96afe3088048l }, + { 0xbf6a021577884456l,0xb3b5688c69310ea7l,0x17c9429504fad2del, + 0xe020f0e517896d4dl }, + 0 }, + /* 49 << 32 */ + { { 0x442fdfe920cd1ebel,0xa8317dfa6a250d62l,0x5214576d082d5a2dl, + 0xc1a5d31930803c33l }, + { 0x33eee5b25e4a2cd0l,0x7df181b3b4db8011l,0x249285145b5c6b0bl, + 0x464c1c5828bf8837l }, + 0 }, + /* 51 << 32 */ + { { 0x5464da65d55babd1l,0x50eaad2a0048d80fl,0x782ca3dd2b9bce90l, + 0x41107164ab526844l }, + { 0xad3f0602d56e0a5fl,0xc1f0248018455114l,0xe05d8dcab1527931l, + 0x87818cf5bb1295d7l }, + 0 }, + /* 52 << 32 */ + { { 0x95aeb5bd483e333al,0x003af31effeaededl,0xfc5532e87efb1e4fl, + 0xb37e0fb52dfa24a5l }, + { 0x485d4cecdc140b08l,0xb81a0d23983bd787l,0xd19928dae8d489fdl, + 0x3fa0312c177b9dbdl }, + 0 }, + /* 53 << 32 */ + { { 0xade391470c6d7e88l,0x4fd1e8cd47072c45l,0x145760fed5a65c56l, + 0x198960c7be4887del }, + { 0xfe7974a82640257al,0xf838a19b774febefl,0xb2aecad11b6e988el, + 0x643f44fa448e4a8fl }, + 0 }, + /* 55 << 32 */ + { { 0xc35ceffdee756e71l,0x2c1364d88ea932c4l,0xbd594d8d837d2d9fl, + 0x5b334bdac9d74d48l }, + { 0x72dc3e03b8fac08bl,0x38f01de006fdf70fl,0x4bde74b31d298ba4l, + 0x2598d183ad5f42a9l }, + 0 }, + /* 57 << 32 */ + { { 0x02c6ba15f62befa2l,0x6399ceb55c8ccee9l,0x3638bd6e08d3473el, + 0xb8f1f13d2f8f4a9cl }, + { 0x50d7560655827a74l,0x8d6e65f33fb4f32cl,0x40a5d21189ee621al, + 0x6d3f9e11c4474716l }, + 0 }, + /* 59 << 32 */ + { { 0xcb633a4ce9b2bb8fl,0x0475703f8c529253l,0x61e007b5a8878873l, + 0x342d77ba14504159l }, + { 0x2925175c313578dfl,0x4e631897b6b097f1l,0xe64d138929350e41l, + 0x2fb20608ec7adccdl }, + 0 }, + /* 60 << 32 */ + { { 0xa560c234d5c0f5d1l,0x74f84bf62bdef0efl,0x61ed00005cbd3d0bl, + 0xc74262d087fb408bl }, + { 0xad30a6496cc64128l,0x708e3a31a4a8b154l,0xaf21ce2637f82074l, + 0x31d33b38204c9a74l }, + 0 }, + /* 61 << 32 */ + { { 0x8f609fe04cc2f575l,0xe44f9784b35488c4l,0x0d464bb6180fa375l, + 0x4f44d5d2de2247b8l }, + { 0xf538eb38141ef077l,0x781f8f6e8fa456a4l,0x67e9a46429b4f39dl, + 0x245d21e8b704c3e9l }, + 0 }, + /* 63 << 32 */ + { { 0x45a94ee858ffa7cdl,0x4d38bc6818053549l,0x0b4bc65a499d79f3l, + 0xa81e3ab09159cab7l }, + { 0xf13716efb47898cel,0xb7ee597c2e2d9044l,0x09396b90e6158276l, + 0x5c644dc36a533fcel }, + 0 }, + /* 64 << 32 */ + { { 0xcca4428dbbe5a1a9l,0x8187fd5f3126bd67l,0x0036973a48105826l, + 0xa39b6663b8bd61a0l }, + { 0x6d42deef2d65a808l,0x4969044f94636b19l,0xf611ee47dd5d564cl, + 0x7b2f3a49d2873077l }, + 0 }, + /* 65 << 32 */ + { { 0xbe4c16c3bf429668l,0xd32f56f0ef35db3bl,0xae8355de9ea4e3f1l, + 0x8f66c4a2a450944el }, + { 0xafab94c8b798fbe2l,0x18c57baff7f3d5cfl,0x692d191c5cfa5c7dl, + 0xc0c25f69a689daebl }, + 0 }, + /* 71 << 32 */ + { { 0x15fb3ae398340d4cl,0xa8b9233a7de82134l,0x44971a545fc0dbc6l, + 0xb2b4f0f3a1d3f094l }, + { 0x8d9eaba1b6242bd4l,0xd8aad777787cc557l,0xb1ab8b7870d1a2bbl, + 0x5d20f48cead3bfe3l }, + 0 }, + /* 77 << 32 */ + { { 0x4dacbf09a2bf9772l,0x969a4c4357aa8457l,0xadbe673b273ebfc5l, + 0xb85582bb927778c9l }, + { 0x748371855c03752cl,0xc337bc6bc2f60d11l,0x2c3838e4ad456a09l, + 0xaf479c897e381842l }, + 0 }, + /* 83 << 32 */ + { { 0x8530ae751b1aea77l,0xf43b923ba8310cb9l,0x9c1a60c6bf4dd6c5l, + 0x11885b863e3aaaa5l }, + { 0x594a8fa90f69821el,0x1eece3d66bc37998l,0x1fd718f518df32bfl, + 0x1c00c7d461d84082l }, + 0 }, + /* 89 << 32 */ + { { 0xd67ee3a4c763c3cfl,0x760b128305969234l,0x1a5ff331ec17f2d1l, + 0x25f0392a84fecfefl }, + { 0xb1bc004a3a80d47el,0xf450bf08182fee3bl,0xf11117681e19751el, + 0x5b4127dae28ed23fl }, + 0 }, + /* 95 << 32 */ + { { 0x91e00defdaf08f09l,0x7ef41724f4738a07l,0x990fbbceaf1263fcl, + 0x779121e3e6eeb5aal }, + { 0x3e162c7a5a3ecf52l,0x73ae568a51be5faal,0x8bea1bfa451be8a9l, + 0x3e8cd5db90e11097l }, + 0 }, + /* 101 << 32 */ + { { 0x90390f7224d27159l,0x685c139efd07e5d4l,0x4e21e44a3bc234a8l, + 0x61b50f34eeb14dacl }, + { 0x7beb0aa087555d58l,0x781326bcc806f0d2l,0xc289537a1eb7199fl, + 0x44a31a037b42766el }, + 0 }, + /* 107 << 32 */ + { { 0x7d778206edde4b40l,0x34539fa18eb92fcdl,0x5a0bdd79bf52a552l, + 0x066d3672fdcca75el }, + { 0xd73fa893e28b5a5bl,0xb495135876c38698l,0x44469b0114ae16cfl, + 0xb428c763691d6618l }, + 0 }, + /* 113 << 32 */ + { { 0x9022db8b69196353l,0x152ebb7dd7a4afd0l,0xea36fae57fcf1765l, + 0xa8fc00ba0decea8al }, + { 0x1047206a0c0b0414l,0x6607d8ade076df28l,0xf343e19966b8aba1l, + 0x7f03c1ad311e208dl }, + 0 }, + /* 116 << 32 */ + { { 0xe6b4c96e888f3870l,0xa21bb618fe544042l,0x7122ee88bd817699l, + 0xcb38ecebfa66e173l }, + { 0x6ed5b3482c9cc05fl,0x591affc84ae0fd9el,0x7cf325ac6e7aaac0l, + 0x2397c053d05e5be0l }, + 0 }, + /* 119 << 32 */ + { { 0x95363f61eaa96552l,0xe03bc6b38fb15b73l,0xa5c5808f2c389053l, + 0xcd021e6c11b2030cl }, + { 0x349ca9bdc038e30al,0x0a3368d4165afa2cl,0x043630debbfa1cc6l, + 0xb8c4456ba7cdbf69l }, + 0 }, + /* 125 << 32 */ + { { 0x63aa3315fd7d2983l,0xaf4c96afa6a04bedl,0x3a5c0b5410814a74l, + 0x9906f5e30f9b0770l }, + { 0x622be6523676986fl,0x09ac5bc0173e7cb5l,0x1c40e56a502c8b3cl, + 0xabb9a0f7253ce8f6l }, + 0 }, + }, + { + /* 0 << 40 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 40 */ + { { 0x889f6d65533ef217l,0x7158c7e4c3ca2e87l,0xfb670dfbdc2b4167l, + 0x75910a01844c257fl }, + { 0xf336bf07cf88577dl,0x22245250e45e2acel,0x2ed92e8d7ca23d85l, + 0x29f8be4c2b812f58l }, + 0 }, + /* 3 << 40 */ + { { 0xc51e414351facc61l,0xbaf2647de68a25bcl,0x8f5271a00ff872edl, + 0x8f32ef993d2d9659l }, + { 0xca12488c7593cbd4l,0xed266c5d02b82fabl,0x0a2f78ad14eb3f16l, + 0xc34049484d47afe3l }, + 0 }, + /* 4 << 40 */ + { { 0xa6f3d574c005979dl,0xc2072b426a40e350l,0xfca5c1568de2ecf9l, + 0xa8c8bf5ba515344el }, + { 0x97aee555114df14al,0xd4374a4dfdc5ec6bl,0x754cc28f2ca85418l, + 0x71cb9e27d3c41f78l }, + 0 }, + /* 5 << 40 */ + { { 0x09c1670209470496l,0xa489a5edebd23815l,0xc4dde4648edd4398l, + 0x3ca7b94a80111696l }, + { 0x3c385d682ad636a4l,0x6702702508dc5f1el,0x0c1965deafa21943l, + 0x18666e16610be69el }, + 0 }, + /* 7 << 40 */ + { { 0x45beb4ca2a604b3bl,0x56f651843a616762l,0xf52f5a70978b806el, + 0x7aa3978711dc4480l }, + { 0xe13fac2a0e01fabcl,0x7c6ee8a5237d99f9l,0x251384ee05211ffel, + 0x4ff6976d1bc9d3ebl }, + 0 }, + /* 9 << 40 */ + { { 0xdde0492316e043a2l,0x98a452611dd3d209l,0xeaf9f61bd431ebe8l, + 0x00919f4dbaf56abdl }, + { 0xe42417db6d8774b1l,0x5fc5279c58e0e309l,0x64aa40613adf81eal, + 0xef419edabc627c7fl }, + 0 }, + /* 10 << 40 */ + { { 0x3919759239ef620fl,0x9d47284074fa29c4l,0x4e428fa39d416d83l, + 0xd1a7c25129f30269l }, + { 0x46076e1cd746218fl,0xf3ad6ee8110d967el,0xfbb5f434a00ae61fl, + 0x3cd2c01980d4c929l }, + 0 }, + /* 11 << 40 */ + { { 0xfa24d0537a4af00fl,0x3f938926ca294614l,0x0d700c183982182el, + 0x801334434cc59947l }, + { 0xf0397106ec87c925l,0x62bd59fc0ed6665cl,0xe8414348c7cca8b5l, + 0x574c76209f9f0a30l }, + 0 }, + /* 13 << 40 */ + { { 0x95be42e2bb8b6a07l,0x64be74eeca23f86al,0xa73d74fd154ce470l, + 0x1c2d2857d8dc076al }, + { 0xb1fa1c575a887868l,0x38df8e0b3de64818l,0xd88e52f9c34e8967l, + 0x274b4f018b4cc76cl }, + 0 }, + /* 15 << 40 */ + { { 0x3f5c05b4f8b7559dl,0x0be4c7acfae29200l,0xdd6d3ef756532accl, + 0xf6c3ed87eea7a285l }, + { 0xe463b0a8f46ec59bl,0x531d9b14ecea6c83l,0x3d6bdbafc2dc836bl, + 0x3ee501e92ab27f0bl }, + 0 }, + /* 16 << 40 */ + { { 0x8df275455922ac1cl,0xa7b3ef5ca52b3f63l,0x8e77b21471de57c4l, + 0x31682c10834c008bl }, + { 0xc76824f04bd55d31l,0xb6d1c08617b61c71l,0x31db0903c2a5089dl, + 0x9c092172184e5d3fl }, + 0 }, + /* 17 << 40 */ + { { 0x7b1a921ea6b3340bl,0x6d7c4d7d7438a53el,0x2b9ef73c5bf71d8fl, + 0xb5f6e0182b167a7cl }, + { 0x5ada98ab0ce536a3l,0xee0f16f9e1fea850l,0xf6424e9d74f1c0c5l, + 0x4d00de0cd3d10b41l }, + 0 }, + /* 19 << 40 */ + { { 0xd542f522a6533610l,0xfdde15a734ec439al,0x696560fedc87dd0dl, + 0x69eab421e01fd05fl }, + { 0xca4febdc95cc5988l,0x839be396c44d92fbl,0x7bedff6daffe543bl, + 0xd2bb97296f6da43al }, + 0 }, + /* 21 << 40 */ + { { 0x5bc6dea80b8d0077l,0xb2adf5d1ea9c49efl,0x7104c20eaafe8659l, + 0x1e3604f37866ee7el }, + { 0x0cfc7e7b3075c8c5l,0x5281d9bb639c5a2bl,0xcbdf42494bc44ee3l, + 0x835ab066655e9209l }, + 0 }, + /* 23 << 40 */ + { { 0x78fbda4b90b94ffal,0x447e52eb7beb993cl,0x920011bc92620d15l, + 0x7bad6ecf481fd396l }, + { 0xad3bd28ba989a09el,0x20491784a3e62b78l,0xcdcd7096b07bd9efl, + 0x9bf5bb7337d780adl }, + 0 }, + /* 25 << 40 */ + { { 0xbe911a71a976c8d4l,0xba0346743fdd778el,0x2359e7434cf87ea1l, + 0x8dccf65f07ebb691l }, + { 0x6c2c18eb09746d87l,0x6a19945fd2ecc8fal,0xc67121ff2ffa0339l, + 0x408c95ba9bd9fc31l }, + 0 }, + /* 27 << 40 */ + { { 0xa317204bcaa5da39l,0xd390df7468bf53d7l,0x56de18b2dbd71c0dl, + 0xcb4d3bee75184779l }, + { 0x815a219499d920a5l,0x9e10fb4ecf3d3a64l,0x7fd4901dfe92e1eel, + 0x5d86d10d3ab87b2el }, + 0 }, + /* 28 << 40 */ + { { 0x24f2a692840bb336l,0x7c353bdca669fa7bl,0xda20d6fcdec9c300l, + 0x625fbe2fa13a4f17l }, + { 0xa2b1b61adbc17328l,0x008965bfa9515621l,0x49690939c620ff46l, + 0x182dd27d8717e91cl }, + 0 }, + /* 29 << 40 */ + { { 0x98e9136c878303e4l,0x2769e74fd1e65efdl,0x6154c545809da56el, + 0x8c5d50a04301638cl }, + { 0x10f3d2068214b763l,0x2da9a2fc44df0644l,0xca912bab588a6fcdl, + 0xe9e82d9b227e1932l }, + 0 }, + /* 31 << 40 */ + { { 0xcbdc4d66d080e55bl,0xad3f11e5b8f98d6bl,0x31bea68e18a32480l, + 0xdf1c6fd52c1bcf6el }, + { 0xadcda7ee118a3f39l,0xbd02f857ac060d5fl,0xd2d0265d86631997l, + 0xb866a7d33818f2d4l }, + 0 }, + /* 33 << 40 */ + { { 0xfbcce2d31892d98dl,0x2e34bc9507de73dcl,0x3a48d1a94891eec1l, + 0xe64499c24d31060bl }, + { 0xe9674b7149745520l,0xf126ccaca6594a2cl,0x33e5c1a079945342l, + 0x02aa0629066e061fl }, + 0 }, + /* 34 << 40 */ + { { 0xdfd7c0ae7af3191el,0x923ec111d68c70d9l,0xb6f1380bb675f013l, + 0x9192a224f23d45bal }, + { 0xbe7890f9524891e3l,0x45b24c47eba996bbl,0x59331e48320447e9l, + 0x0e4d8753ac9afad4l }, + 0 }, + /* 35 << 40 */ + { { 0x49e49c38c9f5a6c3l,0x3f5eea44d8ee2a65l,0x02bf3e761c74bbb4l, + 0x50d291cdef565571l }, + { 0xf4edc290a36dd5fal,0x3015df9556dd6b85l,0x4494926aa5549a16l, + 0x5de6c59390399e4al }, + 0 }, + /* 36 << 40 */ + { { 0x29be11c6ce800998l,0x72bb1752b90360d9l,0x2c1931975a4ad590l, + 0x2ba2f5489fc1dbc0l }, + { 0x7fe4eebbe490ebe0l,0x12a0a4cd7fae11c0l,0x7197cf81e903ba37l, + 0xcf7d4aa8de1c6dd8l }, + 0 }, + /* 37 << 40 */ + { { 0x961fa6317e249e7bl,0x5c4f707796caed50l,0x6b176e62d7e50885l, + 0x4dd5de72f390cbecl }, + { 0x91fa29954b2bd762l,0x80427e6395b8dadel,0xd565bf1de2c34743l, + 0x911da39d16e6c841l }, + 0 }, + /* 39 << 40 */ + { { 0x48365465802ff016l,0x6d2a561f71beece6l,0xdd299ce6f9707052l, + 0x62a32698a23407bbl }, + { 0x1d55bdb147004afbl,0xfadec124369b1084l,0x1ce78adf291c89f7l, + 0x9f2eaf03278bc529l }, + 0 }, + /* 40 << 40 */ + { { 0x92af6bf43fd5684cl,0x2b26eecf80360aa1l,0xbd960f3000546a82l, + 0x407b3c43f59ad8fel }, + { 0x86cae5fe249c82bal,0x9e0faec72463744cl,0x87f551e894916272l, + 0x033f93446ceb0615l }, + 0 }, + /* 41 << 40 */ + { { 0x04658ad212dba0cel,0x9e600624068822f0l,0x84661f11b26d368bl, + 0xbca867d894ebb87al }, + { 0x79506dc42f1bad89l,0x1a8322d3ebcbe7a1l,0xb4f1e102ac197178l, + 0x29a950b779f7198cl }, + 0 }, + /* 43 << 40 */ + { { 0x19a6fb0984a3d1d5l,0x6c75c3a2ba5f5307l,0x7983485bf9698447l, + 0x689f41b88b1cdc1el }, + { 0x18f6fbd74c1979d0l,0x3e6be9a27a0b6708l,0x06acb615f63d5a8al, + 0x8a817c098d0f64b1l }, + 0 }, + /* 44 << 40 */ + { { 0x1e5eb0d18be82e84l,0x89967f0e7a582fefl,0xbcf687d5a6e921fal, + 0xdfee4cf3d37a09bal }, + { 0x94f06965b493c465l,0x638b9a1c7635c030l,0x7666786466f05e9fl, + 0xccaf6808c04da725l }, + 0 }, + /* 45 << 40 */ + { { 0xa9b3479b1b53a173l,0xc041eda3392eddc0l,0xdb8f804755edd7eel, + 0xaf1f7a37ab60683cl }, + { 0x9318603a72c0accbl,0xab1bb9fe401cbf3cl,0xc40e991e88afe245l, + 0x9298a4580d06ac35l }, + 0 }, + /* 46 << 40 */ + { { 0x58e127d5036c2fe7l,0x5fe5020555b93361l,0xc1373d850f74a045l, + 0x28cd79dbe8228e4bl }, + { 0x0ae82320c2018d9al,0xf6d0049c78f8016al,0x381b6fe2149b31fbl, + 0x33a0e8adec3cfbcfl }, + 0 }, + /* 47 << 40 */ + { { 0x23a6612e9eab5da7l,0xb645fe29d94d6431l,0xe3d74594ca1210c4l, + 0xdc1376bceeca0674l }, + { 0xfd40dfef657f0154l,0x7952a548d52cbac5l,0x0ee189583685ad28l, + 0xd13639409ba9ca46l }, + 0 }, + /* 48 << 40 */ + { { 0xca2eb690768fccfcl,0xf402d37db835b362l,0x0efac0d0e2fdfccel, + 0xefc9cdefb638d990l }, + { 0x2af12b72d1669a8bl,0x33c536bc5774ccbdl,0x30b21909fb34870el, + 0xc38fa2f77df25acal }, + 0 }, + /* 49 << 40 */ + { { 0x1337902f1c982cd6l,0x222e08fe14ec53eal,0x6c8abd0d330ef3e5l, + 0xeb59e01531f6fd9dl }, + { 0xd74ae554a8532df4l,0xbc010db1ab44c83el,0xe98016561b8f9285l, + 0x65a9612783acc546l }, + 0 }, + /* 51 << 40 */ + { { 0x36a8b0a76770cfb1l,0x3338d52f9bb578fcl,0x5136c785f5ed12a4l, + 0x652d47ed87bf129el }, + { 0x9c6c827e6067c2d0l,0x61fc2f410345533al,0x2d7fb182130cea19l, + 0x71a0186330b3ef85l }, + 0 }, + /* 52 << 40 */ + { { 0x74c5f02bbf81f3f5l,0x0525a5aeaf7e4581l,0x88d2aaba433c54ael, + 0xed9775db806a56c5l }, + { 0xd320738ac0edb37dl,0x25fdb6ee66cc1f51l,0xac661d1710600d76l, + 0x931ec1f3bdd1ed76l }, + 0 }, + /* 53 << 40 */ + { { 0xb81e239161faa569l,0xb379f759bb40eebfl,0x9f2fd1b2a2c54549l, + 0x0a968f4b0d6ba0ael }, + { 0xaa869e6eedfe8c75l,0x0e36b298645ab173l,0x5a76282b0bcdefd7l, + 0x9e949331d05293f2l }, + 0 }, + /* 55 << 40 */ + { { 0xc1cfa9a1c59fac6el,0x2648bffcb72747cel,0x5f8a39805f2e2637l, + 0x8bd3a8eb73e65758l }, + { 0xd9c43f1df14381a7l,0xecc1c3b0d6a86c10l,0xffcf4fa8a4a6dc74l, + 0x7304fa834cea0a46l }, + 0 }, + /* 57 << 40 */ + { { 0x4460760c34dca952l,0xeac9cf2444c70444l,0xb879297b8493c87el, + 0x295941a54b2dccb7l }, + { 0x1e5cecede58721cdl,0xc8b58db74ca0d12bl,0x1927965c6da1d034l, + 0x7220b02839ed1369l }, + 0 }, + /* 59 << 40 */ + { { 0xc38746c83c2e34b6l,0x9f27362e38a51042l,0x26febec02067afebl, + 0xd9c4e15544e7371fl }, + { 0x6035f469f92930d1l,0xe6ed7c08b4431b8bl,0xa25bf5903e16410dl, + 0x147d83368adf4c18l }, + 0 }, + /* 60 << 40 */ + { { 0x7f01c9ecaa80ba59l,0x3083411a68538e51l,0x970370f1e88128afl, + 0x625cc3db91dec14bl }, + { 0xfef9666c01ac3107l,0xb2a8d577d5057ac3l,0xb0f2629992be5df7l, + 0xf579c8e500353924l }, + 0 }, + /* 61 << 40 */ + { { 0xbd9398d6ca02669fl,0x896e053bf9ad11a1l,0xe024b699a3556f9fl, + 0x23b4b96ad53cbca3l }, + { 0x549d2d6c89733dd6l,0x3dae193f394f3179l,0x8bf7ec1cdfeda825l, + 0xf6a1db7a8a4844b4l }, + 0 }, + /* 63 << 40 */ + { { 0x3b5403d56437a027l,0xda32bbd233ed30aal,0xd2ad3baa906de0cal, + 0x3b6df514533f736el }, + { 0x986f1cab5df9b9c4l,0x41cd2088970d330el,0xaae7c2238c20a923l, + 0x52760a6e1e951dc0l }, + 0 }, + /* 64 << 40 */ + { { 0xb8fa3d931341ed7al,0x4223272ca7b59d49l,0x3dcb194783b8c4a4l, + 0x4e413c01ed1302e4l }, + { 0x6d999127e17e44cel,0xee86bf7533b3adfbl,0xf6902fe625aa96cal, + 0xb73540e4e5aae47dl }, + 0 }, + /* 65 << 40 */ + { { 0x55318a525e34036cl,0xc3acafaaf9884e3fl,0xe5ba15cea042ba04l, + 0x56a1d8960ada550el }, + { 0xa5198cae87b76764l,0xd079d1f0b6fd84fbl,0xb22b637bcbe363edl, + 0xbe8ab7d64499deaal }, + 0 }, + /* 71 << 40 */ + { { 0xbe8eba5eb4925f25l,0x00f8bf582e3159d6l,0xb1aa24fa18856070l, + 0x22ea8b74e4c30b22l }, + { 0x512f633e55bbe4e8l,0x82ba62318678aee9l,0xea05da90fdf72b7el, + 0x616b9bc7a4fc65eel }, + 0 }, + /* 77 << 40 */ + { { 0xe31ee3b3b7c221e7l,0x10353824e353fa43l,0x9d2f3df69dd2a86fl, + 0x8a12ab9322ccffecl }, + { 0x25c8e326d666f9e5l,0x33ea98a0598da7fbl,0x2fc1de0917f74e17l, + 0x0d0b6c7a35efb211l }, + 0 }, + /* 83 << 40 */ + { { 0x22a82c6c804e6ecel,0x824a170b1d8fce9el,0x621802becee65ed0l, + 0x4a4e9e7895ec4285l }, + { 0x8da0988fa8940b7al,0xaff89c5b86445aa5l,0x386fdbdad689cde9l, + 0x3aeaae7d9f5caaccl }, + 0 }, + /* 89 << 40 */ + { { 0xe9cb9e68a7b62f4cl,0x515cae0ec3b7092el,0xb8abec354b491f52l, + 0x672673fd01eeabc1l }, + { 0x65e5739f7ad6e8a1l,0xc2da8e003d91b2f9l,0xcc43229cced84319l, + 0x0f8cbf9574ccf2d1l }, + 0 }, + /* 95 << 40 */ + { { 0xb03d1cfb1b2f872al,0x88aef4670872b6f7l,0xaafe55e48ea9170cl, + 0xd5cc4875f24aa689l }, + { 0x7e5732908458ce84l,0xef4e143d58bfc16dl,0xc58626efaa222836l, + 0x01c60ec0ca5e0cb8l }, + 0 }, + /* 101 << 40 */ + { { 0x123901aa36337c09l,0x1697acadd2f5e675l,0xc0a1ddd022fe2bael, + 0xf68ea88cff0210ddl }, + { 0x665d11e014168709l,0x912a575f45f25321l,0x7e7ed38070c78934l, + 0x663d692cb0a46322l }, + 0 }, + /* 107 << 40 */ + { { 0x912ab8bd8642cba4l,0x97fab1a3b6b50b73l,0x76666b3cb86ef354l, + 0x16d41330fa5ecce9l }, + { 0x77c7c138c7da404bl,0xc6508cb78c983fb0l,0xe5881733f9004984l, + 0x76dea7794182c7abl }, + 0 }, + /* 113 << 40 */ + { { 0x16db18583556b765l,0x39c18c200263755al,0x7b6691f591c15201l, + 0x4e4c17b168514ea9l }, + { 0xacbe449e06f5f20al,0xeb9119d2541ddfb6l,0x2f6e687bf2eac86fl, + 0xb161471ec14ac508l }, + 0 }, + /* 116 << 40 */ + { { 0x58846d32c4744733l,0x40517c71379f9e34l,0x2f65655f130ef6cal, + 0x526e4488f1f3503fl }, + { 0x8467bd177ee4a976l,0x1d9dc913921363d1l,0xd8d24c33b069e041l, + 0x5eb5da0a2cdf7f51l }, + 0 }, + /* 119 << 40 */ + { { 0x81c2cc32951ab3e7l,0xc86d9a109b0c7e87l,0x0b7a18bd606ef408l, + 0x099b5bbfe6c2251el }, + { 0x46d627d0bfce880fl,0xbfaddcbbe1c6865al,0xa9ab6183d2bb9a00l, + 0x23cb9a2720ad9789l }, + 0 }, + /* 125 << 40 */ + { { 0x1592d0630c25fbebl,0x13869ec24995a3fal,0x6413f494861d0a73l, + 0xa3b782342f9f1b89l }, + { 0x113689e2b6cad351l,0x53be2014a873dcc1l,0xccf405e0c6bb1be7l, + 0x4fff7b4ca9061ca9l }, + 0 }, + }, + { + /* 0 << 48 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 48 */ + { { 0xcc7a64880a750c0fl,0x39bacfe34e548e83l,0x3d418c760c110f05l, + 0x3e4daa4cb1f11588l }, + { 0x2733e7b55ffc69ffl,0x46f147bc92053127l,0x885b2434d722df94l, + 0x6a444f65e6fc6b7cl }, + 0 }, + /* 3 << 48 */ + { { 0x6d0b16f4bdaedfbdl,0x23fd326086746cedl,0x8bfb1d2fff4b3e17l, + 0xc7f2ec2d019c14c8l }, + { 0x3e0832f245104b0dl,0x5f00dafbadea2b7el,0x29e5cf6699fbfb0fl, + 0x264f972361827cdal }, + 0 }, + /* 4 << 48 */ + { { 0x97b14f7ea90567e6l,0x513257b7b6ae5cb7l,0x85454a3c9f10903dl, + 0xd8d2c9ad69bc3724l }, + { 0x38da93246b29cb44l,0xb540a21d77c8cbacl,0x9bbfe43501918e42l, + 0xfffa707a56c3614el }, + 0 }, + /* 5 << 48 */ + { { 0x6eb1a2f3e30bc27fl,0xe5f0c05ab0836511l,0x4d741bbf4965ab0el, + 0xfeec41ca83464bbdl }, + { 0x1aca705f99d0b09fl,0xc5d6cc56f42da5fal,0x49964eddcc52b931l, + 0x8ae59615c884d8d8l }, + 0 }, + /* 7 << 48 */ + { { 0xf634b57b39f8868al,0xe27f4fd475cc69afl,0xa47e58cbd0d5496el, + 0x8a26793fd323e07fl }, + { 0xc61a9b72fa30f349l,0x94c9d9c9b696d134l,0x792beca85880a6d1l, + 0xbdcc4645af039995l }, + 0 }, + /* 9 << 48 */ + { { 0xce7ef8e58c796c3cl,0x9adaae84dd66e57al,0x784ae13e45227f33l, + 0xb046c5b82a85e757l }, + { 0xb7aa50aeec37631fl,0xbedc4fca3b300758l,0x0f82567e0ac9700bl, + 0x1071d9d44ff5f8d2l }, + 0 }, + /* 10 << 48 */ + { { 0x61360ee99e240d18l,0x057cdcacb4b94466l,0xe7667cd12fe5325cl, + 0x1fa297b521974e3bl }, + { 0xfa4081e7db083d76l,0x31993be6f206bd15l,0x8949269b14c19f8cl, + 0x21468d72a9d92357l }, + 0 }, + /* 11 << 48 */ + { { 0xd09ef6c4e51a2811l,0x39f6862bb8fb66b9l,0x64e77f8d22dfaa99l, + 0x7b10504461b08aacl }, + { 0x71704e4c4a7df332l,0xd09734342ffe015bl,0xab0eaf4408d3020el, + 0x28b1909eed63b97al }, + 0 }, + /* 13 << 48 */ + { { 0x2f3fa882cdadcd4fl,0xa4ef68595f631995l,0xe52ca2f9e531766fl, + 0x20af5c3057e2c1d3l }, + { 0x1e4828f6e51e94b8l,0xf900a1751a2f5d4fl,0xe831adb3392c58a0l, + 0x4c5a90ca1b6e5866l }, + 0 }, + /* 15 << 48 */ + { { 0x5f3dcba86182827cl,0xd1a448ddbd7e7252l,0x2d8f96fcf493b815l, + 0xba0a4c263b0aa95fl }, + { 0x88a1514063a0007fl,0x9564c25e6a9c5846l,0x5a4d7b0fdc0fcbcal, + 0x2275daa33f8a740el }, + 0 }, + /* 16 << 48 */ + { { 0x83f49167ceca9754l,0x426d2cf64b7939a0l,0x2555e355723fd0bfl, + 0xa96e6d06c4f144e2l }, + { 0x4768a8dd87880e61l,0x15543815e508e4d5l,0x09d7e772b1b65e15l, + 0x63439dd6ac302fa0l }, + 0 }, + /* 17 << 48 */ + { { 0x159591cc0461086bl,0xb695aa9495e66e51l,0x2d4c946779ded531l, + 0xbd2482ba89c2be79l }, + { 0x8ee2658aa20bbf19l,0xc000528a32247917l,0xd924be4affeae845l, + 0x51312bebed992c8bl }, + 0 }, + /* 19 << 48 */ + { { 0x3a01b958dc752bd9l,0x2babdbc20c215d45l,0xe689d79a131641c1l, + 0x48e8f0da80e05ed4l }, + { 0x4b505feb77bb70c4l,0xefbd3e2bb6057ef7l,0x7583e22dce603ca5l, + 0xfbe3b1f22c5c70c7l }, + 0 }, + /* 21 << 48 */ + { { 0x8ec1ecf029e5e35al,0x2f3168e58645c2b3l,0xe9297362c7f94cb2l, + 0x4fbf1466d1c90b39l }, + { 0x3e4f7656920bae2al,0x805d04b9f1beb172l,0x729a7208dbdbd4b4l, + 0x1aade45687aeca53l }, + 0 }, + /* 23 << 48 */ + { { 0xb0ff1f541934a508l,0x19e1397604bbf31al,0xb2a8e6033717a6b4l, + 0xd601e45d0ef12cb9l }, + { 0x563f0af5b515e98el,0x9b129db633984f9bl,0xe34aba2fa47e4a65l, + 0xb56f82d19e3f9d82l }, + 0 }, + /* 25 << 48 */ + { { 0x0203effdb1209b86l,0x21f063edb19d6cbfl,0x59f53476980f275bl, + 0x202456d7b7ac5e80l }, + { 0xe5a8c05f4900edc9l,0x04c08eb470f01e86l,0xf74ac2241dcd98cel, + 0x7e77cc0ce2e830dbl }, + 0 }, + /* 27 << 48 */ + { { 0x74e37234a9747edel,0x4fc9fbb1361b1013l,0xe7b533733cf357efl, + 0x6aa2dd2c991c4193l }, + { 0x7887e4d2a770917al,0xdd1809b4c20d24cbl,0x004cd7c38e9c2d3el, + 0xc77c5baba9970abel }, + 0 }, + /* 28 << 48 */ + { { 0x20ac0351d598d710l,0x272c4166cb3a4da4l,0xdb82fe1aca71de1fl, + 0x746e79f2d8f54b0fl }, + { 0x6e7fc7364b573e9bl,0x75d03f46fd4b5040l,0x5c1cc36d0b98d87bl, + 0x513ba3f11f472da1l }, + 0 }, + /* 29 << 48 */ + { { 0x52927eaac3af237fl,0xfaa06065d7398767l,0x042e72b497c6ce0bl, + 0xdaed0cc40a9f2361l }, + { 0xddc2e11c2fc1bb4al,0x631da5770c1a9ef8l,0x8a4cfe44680272bfl, + 0xc76b9f7262fb5cc3l }, + 0 }, + /* 31 << 48 */ + { { 0x248f814538b3aae3l,0xb5345864bc204334l,0x66d6b5bc1d127524l, + 0xe312080d14f572d3l }, + { 0x13ed15a716abafebl,0x6f18ce27dba967bel,0x96c9e826ef08552dl, + 0x2c191b06be2b63e0l }, + 0 }, + /* 33 << 48 */ + { { 0xde4be45dc115ca51l,0xa028cafe934dabd6l,0x7e875663d1c0f8c5l, + 0xa8e32ab063d17473l }, + { 0x33f55bd5543199aal,0x79d2c937a2071d6el,0xa6a6758ceff16f28l, + 0x9c5f93ef87d85201l }, + 0 }, + /* 34 << 48 */ + { { 0x7f2e440381e9ede3l,0x243c3894caf6df0al,0x7c605bb11c073b11l, + 0xcd06a541ba6a4a62l }, + { 0x2916894949d4e2e5l,0x33649d074af66880l,0xbfc0c885e9a85035l, + 0xb4e52113fc410f4bl }, + 0 }, + /* 35 << 48 */ + { { 0xe86f21bc3ad4c81el,0x53b408403a37dcebl,0xaa606087383402cdl, + 0xc248caf185452b1dl }, + { 0x38853772576b57cdl,0xe2798e5441b7a6edl,0x7c2f1eed95ef4a33l, + 0xccd7e776adb1873cl }, + 0 }, + /* 36 << 48 */ + { { 0xdca3b70678a6513bl,0x92ea4a2a9edb1943l,0x02642216db6e2dd8l, + 0x9b45d0b49fd57894l }, + { 0x114e70dbc69d11ael,0x1477dd194c57595fl,0xbc2208b4ec77c272l, + 0x95c5b4d7db68f59cl }, + 0 }, + /* 37 << 48 */ + { { 0xd978bb791c61030al,0xa47325d2218222f3l,0x65ad4d4832e67d97l, + 0x31e4ed632e0d162al }, + { 0x7308ea317f76da37l,0xcfdffe87d93f35d8l,0xf4b2d60ee6f96cc4l, + 0x8028f3bd0117c421l }, + 0 }, + /* 39 << 48 */ + { { 0x7df80cbb9543edb6l,0xa07a54df40b0b3bcl,0xacbd067cc1888488l, + 0x61ad61318a00c721l }, + { 0x67e7599ebe2e6fe6l,0x8349d568f7270e06l,0x5630aabc307bc0c7l, + 0x97210b3f71af442fl }, + 0 }, + /* 40 << 48 */ + { { 0xfe541fa47ea67c77l,0x952bd2afe3ea810cl,0x791fef568d01d374l, + 0xa3a1c6210f11336el }, + { 0x5ad0d5a9c7ec6d79l,0xff7038af3225c342l,0x003c6689bc69601bl, + 0x25059bc745e8747dl }, + 0 }, + /* 41 << 48 */ + { { 0x58bdabb7ef701b5fl,0x64f987aee00c3a96l,0x533b391e2d585679l, + 0x30ad79d97a862e03l }, + { 0xd941471e8177b261l,0x33f65cb856a9018el,0x985ce9f607759fc4l, + 0x9b085f33aefdbd9el }, + 0 }, + /* 43 << 48 */ + { { 0xab2fa51a9c43ee15l,0x457f338263f30575l,0xce8dcd863e75a6e0l, + 0x67a03ab86e70421al }, + { 0xe72c37893e174230l,0x45ffff6c066f4816l,0x3a3dd84879a2d4a7l, + 0xefa4b7e68b76c24cl }, + 0 }, + /* 44 << 48 */ + { { 0x9a75c80676cb2566l,0x8f76acb1b24892d9l,0x7ae7b9cc1f08fe45l, + 0x19ef73296a4907d8l }, + { 0x2db4ab715f228bf0l,0xf3cdea39817032d7l,0x0b1f482edcabe3c0l, + 0x3baf76b4bb86325cl }, + 0 }, + /* 45 << 48 */ + { { 0xd6be8f00e39e056al,0xb58f87a6232fa3bcl,0xd5cb09dc6b18c772l, + 0x3177256da8e7e17bl }, + { 0x1877fd34230bf92cl,0x6f9031175a36f632l,0x526a288728e2c9d9l, + 0xc373fc94415ec45cl }, + 0 }, + /* 46 << 48 */ + { { 0xd49065e010089465l,0x3bab5d298e77c596l,0x7636c3a6193dbd95l, + 0xdef5d294b246e499l }, + { 0xb22c58b9286b2475l,0xa0b93939cd80862bl,0x3002c83af0992388l, + 0x6de01f9beacbe14cl }, + 0 }, + /* 47 << 48 */ + { { 0x70fa6e2a2bf5e373l,0x501691739271694cl,0xd6ebb98c5d2ed9f1l, + 0x11fd0b3f225bf92dl }, + { 0x51ffbcea1e3d5520l,0xa7c549875513ad47l,0xe9689750b431d46dl, + 0x6e69fecbb620cb9al }, + 0 }, + /* 48 << 48 */ + { { 0x6aac688eadd70482l,0x708de92a7b4a4e8al,0x75b6dd73758a6eefl, + 0xea4bf352725b3c43l }, + { 0x10041f2c87912868l,0xb1b1be95ef09297al,0x19ae23c5a9f3860al, + 0xc4f0f839515dcf4bl }, + 0 }, + /* 49 << 48 */ + { { 0xf3c22398e04b5734l,0x4fba59b275f2579dl,0xbf95182d691901b3l, + 0x4c139534eb599496l }, + { 0xf3f821de33b77e8bl,0x66e580743785d42fl,0xe3ba3d5abdc89c2dl, + 0x7ee988bdd19f37b9l }, + 0 }, + /* 51 << 48 */ + { { 0xe9ba62ca2ee53eb0l,0x64295ae23401d7dal,0x70ed8be24e493580l, + 0x702caa624502732fl }, + { 0xb1f4e21278d0cedfl,0x130b114bdc97057bl,0x9c5d0bd3c38c77b5l, + 0xd9d641e18bad68e7l }, + 0 }, + /* 52 << 48 */ + { { 0xc71e27bf8538a5c6l,0x195c63dd89abff17l,0xfd3152851b71e3dal, + 0x9cbdfda7fa680fa0l }, + { 0x9db876ca849d7eabl,0xebe2764b3c273271l,0x663357e3f208dceal, + 0x8c5bd833565b1b70l }, + 0 }, + /* 53 << 48 */ + { { 0x7c2dea1d122aebd4l,0x090bee4a138c1e4dl,0x94a9ffe59e4aca6cl, + 0x8f3212ba5d405c7fl }, + { 0x6618185f180b5e85l,0x76298d46f455ab9fl,0x0c804076476b2d88l, + 0x45ea9d03d5a40b39l }, + 0 }, + /* 55 << 48 */ + { { 0xdf325ac76a2ed772l,0x35da47ccb0da2765l,0x94ce6f460bc9b166l, + 0xe0fc82fb5f7f3628l }, + { 0x2b26d588c055f576l,0xb9d37c97ec2bae98l,0xffbbead856908806l, + 0xa8c2df87437f4c84l }, + 0 }, + /* 57 << 48 */ + { { 0x47d11c3528430994l,0x0183df71cf13d9d3l,0x98604c89aa138fe5l, + 0xb1432e1c32c09aa1l }, + { 0xf19bc45d99bd5e34l,0xb198be72108e9b89l,0xee500ae9dacde648l, + 0x5936cf98746870a9l }, + 0 }, + /* 59 << 48 */ + { { 0x6d8efb98ed1d5a9bl,0x2e0b08e697f778fal,0xda728454dc5e0835l, + 0x2c28a45f8e3651c4l }, + { 0x667fab6f7ee77088l,0xd94429c8f29a94b4l,0xd83d594d9deea5b2l, + 0x2dc08ccbbea58080l }, + 0 }, + /* 60 << 48 */ + { { 0xba5514df3fd165e8l,0x499fd6a9061f8811l,0x72cd1fe0bfef9f00l, + 0x120a4bb979ad7e8al }, + { 0xf2ffd0955f4a5ac5l,0xcfd174f195a7a2f0l,0xd42301ba9d17baf1l, + 0xd2fa487a77f22089l }, + 0 }, + /* 61 << 48 */ + { { 0xfb5f53ba20a9a01el,0x3adb174fd20d6a9cl,0x6db8bb6d80e0f64fl, + 0x596e428df6a26f76l }, + { 0xbab1f846e6a4e362l,0x8bdb22af9b1becbdl,0x62b48335f31352adl, + 0xd72c26409634f727l }, + 0 }, + /* 63 << 48 */ + { { 0xaaa61cb22b1ec1c3l,0x3b5156722cb6f00el,0x67d1be0a8bf83f60l, + 0x88f1627aa4b804bcl }, + { 0xc52b11a7cdade2abl,0xa6a8b71a606a4e9dl,0x04e0e6697b900551l, + 0x35cfa33c8d5ad0d2l }, + 0 }, + /* 64 << 48 */ + { { 0xb93452381d531696l,0x57201c0088cdde69l,0xdde922519a86afc7l, + 0xe3043895bd35cea8l }, + { 0x7608c1e18555970dl,0x8267dfa92535935el,0xd4c60a57322ea38bl, + 0xe0bf7977804ef8b5l }, + 0 }, + /* 65 << 48 */ + { { 0x375ca189b60f0d5al,0xc9458cf949a78362l,0x61c1c5024262c03al, + 0x299353db4363d5bel }, + { 0xe3565124dac407fel,0x16ea66cd5b93c532l,0xe5c6aec2749df8e3l, + 0x59181317ce3ee4bfl }, + 0 }, + /* 71 << 48 */ + { { 0xd46ea34af41c2a3cl,0x9936184916545c98l,0xd7cb800ccf2498b4l, + 0xe71d088d9353fe87l }, + { 0x43443cbeae2e172cl,0x77131656ca905cb3l,0x76471fd1dce63594l, + 0x346b1d1738f5e264l }, + 0 }, + /* 77 << 48 */ + { { 0x22b1e639f6d0a419l,0x8bbb1fad7cea278cl,0xf07f6c01370cc86al, + 0x661bd027d39b837fl }, + { 0x042c7a69de606098l,0x93433b154e44eb12l,0x20f44ada88d8bfe8l, + 0xb44f66e64ccbfab6l }, + 0 }, + /* 83 << 48 */ + { { 0x1cc32158583d9745l,0x9306223cad1c2201l,0x76aa8d0995748039l, + 0x29425391707e9b59l }, + { 0x8501c0d4487cdf9el,0xbe08e89c205c5611l,0xa950400b04ccc48bl, + 0xb614b69b637e966bl }, + 0 }, + /* 89 << 48 */ + { { 0xd9c3c1238ffa5c4bl,0xc65765f7f3593988l,0x9a7e5d2728242119l, + 0x0ad27b5097ad7620l }, + { 0x154cc5eb413a8b23l,0xae93d8de7afa8254l,0x9ce5116cab9907b5l, + 0x9a163d78063103b9l }, + 0 }, + /* 95 << 48 */ + { { 0x5c4c299291086d2al,0x42c6ca9de8e2d951l,0xe67ecf93dd353f30l, + 0xba54557fe7167c2el }, + { 0x04a7eb2db734c779l,0x8f345605e300711al,0x4811c1ad67b27de6l, + 0xb7ac8e842731d5f0l }, + 0 }, + /* 101 << 48 */ + { { 0xee33a1d8e449ac46l,0x2500ba0aaaebfa2dl,0x8fb914ebc424eff4l, + 0x3a36545d3989255el }, + { 0xd24f2484761235e6l,0x2fc5d5ddd9b2c04bl,0x73660f86070ab0dbl, + 0x2e266d0479d20c7bl }, + 0 }, + /* 107 << 48 */ + { { 0x143752d5316d19a3l,0x56a55e01915497b8l,0x44ba4b2609a5fd15l, + 0xe4fc3e7fd9bee4eel }, + { 0x6f9d8609878a9f26l,0xdf36b5bd2ede7a20l,0x8e03e712a9a3e435l, + 0x4ced555b56546d33l }, + 0 }, + /* 113 << 48 */ + { { 0x89a6aaab0882717el,0x56a9736b43fa5153l,0xdb07dcc9d0e1fb1al, + 0xe7c986d34145e227l }, + { 0x57be66abb10dad51l,0xa47b964e4aa01ea7l,0xd851d9f36bb837cbl, + 0x9851ab3d652e13f7l }, + 0 }, + /* 116 << 48 */ + { { 0x22b88a805616ee30l,0xfb09548fe7ab1083l,0x8ad6ab0d511270cdl, + 0x61f6c57a6924d9abl }, + { 0xa0f7bf7290aecb08l,0x849f87c90df784a4l,0x27c79c15cfaf1d03l, + 0xbbf9f675c463facel }, + 0 }, + /* 119 << 48 */ + { { 0x65512fb716dd6ce1l,0xfa76ebc960d53b35l,0x31e5322e19ada3bel, + 0x7e259b75d0ccc3cdl }, + { 0xd36d03f0e025fd69l,0xbefab782eea9e5f3l,0x1569969dd09ce6a7l, + 0x2df5396178c385b0l }, + 0 }, + /* 125 << 48 */ + { { 0x4201652fce0ccac7l,0x12f8e93df1d29d2dl,0x6c2ac9b2220f00c1l, + 0x4ee6a685a850baa9l }, + { 0x2c2371f163ee8829l,0xddff16488f464433l,0xeab6cd8869a2c413l, + 0xcae34beb85e4c2a8l }, + 0 }, + }, + { + /* 0 << 56 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 56 */ + { { 0xc7913e91991724f3l,0x5eda799c39cbd686l,0xddb595c763d4fc1el, + 0x6b63b80bac4fed54l }, + { 0x6ea0fc697e5fb516l,0x737708bad0f1c964l,0x9628745f11a92ca5l, + 0x61f379589a86967al }, + 0 }, + /* 3 << 56 */ + { { 0x46a8c4180d738dedl,0x6f1a5bb0e0de5729l,0xf10230b98ba81675l, + 0x32c6f30c112b33d4l }, + { 0x7559129dd8fffb62l,0x6a281b47b459bf05l,0x77c1bd3afa3b6776l, + 0x0709b3807829973al }, + 0 }, + /* 4 << 56 */ + { { 0x8c26b232a3326505l,0x38d69272ee1d41bfl,0x0459453effe32afal, + 0xce8143ad7cb3ea87l }, + { 0x932ec1fa7e6ab666l,0x6cd2d23022286264l,0x459a46fe6736f8edl, + 0x50bf0d009eca85bbl }, + 0 }, + /* 5 << 56 */ + { { 0x0b825852877a21ecl,0x300414a70f537a94l,0x3f1cba4021a9a6a2l, + 0x50824eee76943c00l }, + { 0xa0dbfcecf83cba5dl,0xf953814893b4f3c0l,0x6174416248f24dd7l, + 0x5322d64de4fb09ddl }, + 0 }, + /* 7 << 56 */ + { { 0xa337c447f1f0ced1l,0x800cc7939492dd2bl,0x4b93151dbea08efal, + 0x820cf3f8de0a741el }, + { 0xff1982dc1c0f7d13l,0xef92196084dde6cal,0x1ad7d97245f96ee3l, + 0x319c8dbe29dea0c7l }, + 0 }, + /* 9 << 56 */ + { { 0x0ae1d63b0eb919b0l,0xd74ee51da74b9620l,0x395458d0a674290cl, + 0x324c930f4620a510l }, + { 0x2d1f4d19fbac27d4l,0x4086e8ca9bedeeacl,0x0cdd211b9b679ab8l, + 0x5970167d7090fec4l }, + 0 }, + /* 10 << 56 */ + { { 0x3420f2c9faf1fc63l,0x616d333a328c8bb4l,0x7d65364c57f1fe4al, + 0x9343e87755e5c73al }, + { 0x5795176be970e78cl,0xa36ccebf60533627l,0xfc7c738009cdfc1bl, + 0xb39a2afeb3fec326l }, + 0 }, + /* 11 << 56 */ + { { 0xb7ff1ba16224408al,0xcc856e92247cfc5el,0x01f102e7c18bc493l, + 0x4613ab742091c727l }, + { 0xaa25e89cc420bf2bl,0x00a5317690337ec2l,0xd2be9f437d025fc7l, + 0x3316fb856e6fe3dcl }, + 0 }, + /* 13 << 56 */ + { { 0x67332cfc2064cfd1l,0x339c31deb0651934l,0x719b28d52a3bcbeal, + 0xee74c82b9d6ae5c6l }, + { 0x0927d05ebaf28ee6l,0x82cecf2c9d719028l,0x0b0d353eddb30289l, + 0xfe4bb977fddb2e29l }, + 0 }, + /* 15 << 56 */ + { { 0xe10b2ab817a91cael,0xb89aab6508e27f63l,0x7b3074a7dba3ddf9l, + 0x1c20ce09330c2972l }, + { 0x6b9917b45fcf7e33l,0xe6793743945ceb42l,0x18fc22155c633d19l, + 0xad1adb3cc7485474l }, + 0 }, + /* 16 << 56 */ + { { 0x646f96796424c49bl,0xf888dfe867c241c9l,0xe12d4b9324f68b49l, + 0x9a6b62d8a571df20l }, + { 0x81b4b26d179483cbl,0x666f96329511fae2l,0xd281b3e4d53aa51fl, + 0x7f96a7657f3dbd16l }, + 0 }, + /* 17 << 56 */ + { { 0xa7f8b5bf074a30cel,0xd7f52107005a32e6l,0x6f9e090750237ed4l, + 0x2f21da478096fa2bl }, + { 0xf3e19cb4eec863a0l,0xd18f77fd9527620al,0x9505c81c407c1cf8l, + 0x9998db4e1b6ec284l }, + 0 }, + /* 19 << 56 */ + { { 0x794e2d5984ac066cl,0xf5954a92e68c69a0l,0x28c524584fd99dccl, + 0x60e639fcb1012517l }, + { 0xc2e601257de79248l,0xe9ef6404f12fc6d7l,0x4c4f28082a3b5d32l, + 0x865ad32ec768eb8al }, + 0 }, + /* 21 << 56 */ + { { 0x4f4ddf91b2f1ac7al,0xf99eaabb760fee27l,0x57f4008a49c228e5l, + 0x090be4401cf713bbl }, + { 0xac91fbe45004f022l,0xd838c2c2569e1af6l,0xd6c7d20b0f1daaa5l, + 0xaa063ac11bbb02c0l }, + 0 }, + /* 23 << 56 */ + { { 0x54935fcb81d73c9el,0x6d07e9790a5e97abl,0x4dc7b30acf3a6babl, + 0x147ab1f3170bee11l }, + { 0x0aaf8e3d9fafdee4l,0xfab3dbcb538a8b95l,0x405df4b36ef13871l, + 0xf1f4e9cb088d5a49l }, + 0 }, + /* 25 << 56 */ + { { 0x43c01b87459afccdl,0x6bd45143b7432652l,0x8473453055b5d78el, + 0x81088fdb1554ba7dl }, + { 0xada0a52c1e269375l,0xf9f037c42dc5ec10l,0xc066060794bfbc11l, + 0xc0a630bbc9c40d2fl }, + 0 }, + /* 27 << 56 */ + { { 0x9a730ed44763eb50l,0x24a0e221c1ab0d66l,0x643b6393648748f3l, + 0x1982daa16d3c6291l }, + { 0x6f00a9f78bbc5549l,0x7a1783e17f36384el,0xe8346323de977f50l, + 0x91ab688db245502al }, + 0 }, + /* 28 << 56 */ + { { 0x331ab6b56d0bdd66l,0x0a6ef32e64b71229l,0x1028150efe7c352fl, + 0x27e04350ce7b39d3l }, + { 0x2a3c8acdc1070c82l,0xfb2034d380c9feefl,0x2d729621709f3729l, + 0x8df290bf62cb4549l }, + 0 }, + /* 29 << 56 */ + { { 0x02f99f33fc2e4326l,0x3b30076d5eddf032l,0xbb21f8cf0c652fb5l, + 0x314fb49eed91cf7bl }, + { 0xa013eca52f700750l,0x2b9e3c23712a4575l,0xe5355557af30fbb0l, + 0x1ada35167c77e771l }, + 0 }, + /* 31 << 56 */ + { { 0xdc9f46fc609e4a74l,0x2a44a143ba667f91l,0xbc3d8b95b4d83436l, + 0xa01e4bd0c7bd2958l }, + { 0x7b18293273483c90l,0xa79c6aa1a7c7b598l,0xbf3983c6eaaac07el, + 0x8f18181e96e0d4e6l }, + 0 }, + /* 33 << 56 */ + { { 0x0bfc27eeacee5043l,0xae419e732eb10f02l,0x19c028d18943fb05l, + 0x71f01cf7ff13aa2al }, + { 0x7790737e8887a132l,0x6751330966318410l,0x9819e8a37ddb795el, + 0xfecb8ef5dad100b2l }, + 0 }, + /* 34 << 56 */ + { { 0x59f74a223021926al,0xb7c28a496f9b4c1cl,0xed1a733f912ad0abl, + 0x42a910af01a5659cl }, + { 0x3842c6e07bd68cabl,0x2b57fa3876d70ac8l,0x8a6707a83c53aaebl, + 0x62c1c51065b4db18l }, + 0 }, + /* 35 << 56 */ + { { 0x8de2c1fbb2d09dc7l,0xc3dfed12266bd23bl,0x927d039bd5b27db6l, + 0x2fb2f0f1103243dal }, + { 0xf855a07b80be7399l,0xed9327ce1f9f27a8l,0xa0bd99c7729bdef7l, + 0x2b67125e28250d88l }, + 0 }, + /* 36 << 56 */ + { { 0x784b26e88670ced7l,0xe3dfe41fc31bd3b4l,0x9e353a06bcc85cbcl, + 0x302e290960178a9dl }, + { 0x860abf11a6eac16el,0x76447000aa2b3aacl,0x46ff9d19850afdabl, + 0x35bdd6a5fdb2d4c1l }, + 0 }, + /* 37 << 56 */ + { { 0xe82594b07e5c9ce9l,0x0f379e5320af346el,0x608b31e3bc65ad4al, + 0x710c6b12267c4826l }, + { 0x51c966f971954cf1l,0xb1cec7930d0aa215l,0x1f15598986bd23a8l, + 0xae2ff99cf9452e86l }, + 0 }, + /* 39 << 56 */ + { { 0xb5a741a76b2515cfl,0x71c416019585c749l,0x78350d4fe683de97l, + 0x31d6152463d0b5f5l }, + { 0x7a0cc5e1fbce090bl,0xaac927edfbcb2a5bl,0xe920de4920d84c35l, + 0x8c06a0b622b4de26l }, + 0 }, + /* 40 << 56 */ + { { 0xd34dd58bafe7ddf3l,0x55851fedc1e6e55bl,0xd1395616960696e7l, + 0x940304b25f22705fl }, + { 0x6f43f861b0a2a860l,0xcf1212820e7cc981l,0x121862120ab64a96l, + 0x09215b9ab789383cl }, + 0 }, + /* 41 << 56 */ + { { 0x311eb30537387c09l,0xc5832fcef03ee760l,0x30358f5832f7ea19l, + 0xe01d3c3491d53551l }, + { 0x1ca5ee41da48ea80l,0x34e71e8ecf4fa4c1l,0x312abd257af1e1c7l, + 0xe3afcdeb2153f4a5l }, + 0 }, + /* 43 << 56 */ + { { 0x2a17747fa6d74081l,0x60ea4c0555a26214l,0x53514bb41f88c5fel, + 0xedd645677e83426cl }, + { 0xd5d6cbec96460b25l,0xa12fd0ce68dc115el,0xc5bc3ed2697840eal, + 0x969876a8a6331e31l }, + 0 }, + /* 44 << 56 */ + { { 0x60c36217472ff580l,0xf42297054ad41393l,0x4bd99ef0a03b8b92l, + 0x501c7317c144f4f6l }, + { 0x159009b318464945l,0x6d5e594c74c5c6bel,0x2d587011321a3660l, + 0xd1e184b13898d022l }, + 0 }, + /* 45 << 56 */ + { { 0x5ba047524c6a7e04l,0x47fa1e2b45550b65l,0x9419daf048c0a9a5l, + 0x663629537c243236l }, + { 0xcd0744b15cb12a88l,0x561b6f9a2b646188l,0x599415a566c2c0c0l, + 0xbe3f08590f83f09al }, + 0 }, + /* 46 << 56 */ + { { 0x9141c5beb92041b8l,0x01ae38c726477d0dl,0xca8b71f3d12c7a94l, + 0xfab5b31f765c70dbl }, + { 0x76ae7492487443e9l,0x8595a310990d1349l,0xf8dbeda87d460a37l, + 0x7f7ad0821e45a38fl }, + 0 }, + /* 47 << 56 */ + { { 0xed1d4db61059705al,0xa3dd492ae6b9c697l,0x4b92ee3a6eb38bd5l, + 0xbab2609d67cc0bb7l }, + { 0x7fc4fe896e70ee82l,0xeff2c56e13e6b7e3l,0x9b18959e34d26fcal, + 0x2517ab66889d6b45l }, + 0 }, + /* 48 << 56 */ + { { 0xf167b4e0bdefdd4fl,0x69958465f366e401l,0x5aa368aba73bbec0l, + 0x121487097b240c21l }, + { 0x378c323318969006l,0xcb4d73cee1fe53d1l,0x5f50a80e130c4361l, + 0xd67f59517ef5212bl }, + 0 }, + /* 49 << 56 */ + { { 0xf145e21e9e70c72el,0xb2e52e295566d2fbl,0x44eaba4a032397f5l, + 0x5e56937b7e31a7del }, + { 0x68dcf517456c61e1l,0xbc2e954aa8b0a388l,0xe3552fa760a8b755l, + 0x03442dae73ad0cdel }, + 0 }, + /* 51 << 56 */ + { { 0x3fcbdbce478e2135l,0x7547b5cfbda35342l,0xa97e81f18a677af6l, + 0xc8c2bf8328817987l }, + { 0xdf07eaaf45580985l,0xc68d1f05c93b45cbl,0x106aa2fec77b4cacl, + 0x4c1d8afc04a7ae86l }, + 0 }, + /* 52 << 56 */ + { { 0xdb41c3fd9eb45ab2l,0x5b234b5bd4b22e74l,0xda253decf215958al, + 0x67e0606ea04edfa0l }, + { 0xabbbf070ef751b11l,0xf352f175f6f06dcel,0xdfc4b6af6839f6b4l, + 0x53ddf9a89959848el }, + 0 }, + /* 53 << 56 */ + { { 0xda49c379c21520b0l,0x90864ff0dbd5d1b6l,0x2f055d235f49c7f7l, + 0xe51e4e6aa796b2d8l }, + { 0xc361a67f5c9dc340l,0x5ad53c37bca7c620l,0xda1d658832c756d0l, + 0xad60d9118bb67e13l }, + 0 }, + /* 55 << 56 */ + { { 0xd1183316fd6f7140l,0xf9fadb5bbd8e81f7l,0x701d5e0c5a02d962l, + 0xfdee4dbf1b601324l }, + { 0xbed1740735d7620el,0x04e3c2c3f48c0012l,0x9ee29da73455449al, + 0x562cdef491a836c4l }, + 0 }, + /* 57 << 56 */ + { { 0x147ebf01fad097a5l,0x49883ea8610e815dl,0xe44d60ba8a11de56l, + 0xa970de6e827a7a6dl }, + { 0x2be414245e17fc19l,0xd833c65701214057l,0x1375813b363e723fl, + 0x6820bb88e6a52e9bl }, + 0 }, + /* 59 << 56 */ + { { 0xe1b6f60c08191224l,0xc4126ebbde4ec091l,0xe1dff4dc4ae38d84l, + 0xde3f57db4f2ef985l }, + { 0x34964337d446a1ddl,0x7bf217a0859e77f6l,0x8ff105278e1d13f5l, + 0xa304ef0374eeae27l }, + 0 }, + /* 60 << 56 */ + { { 0xfc6f5e47d19dfa5al,0xdb007de37fad982bl,0x28205ad1613715f5l, + 0x251e67297889529el }, + { 0x727051841ae98e78l,0xf818537d271cac32l,0xc8a15b7eb7f410f5l, + 0xc474356f81f62393l }, + 0 }, + /* 61 << 56 */ + { { 0x92dbdc5ac242316bl,0xabe060acdbf4aff5l,0x6e8c38fe909a8ec6l, + 0x43e514e56116cb94l }, + { 0x2078fa3807d784f9l,0x1161a880f4b5b357l,0x5283ce7913adea3dl, + 0x0756c3e6cc6a910bl }, + 0 }, + /* 63 << 56 */ + { { 0xa573a4966d17fbc7l,0x0cd1a70a73d2b24el,0x34e2c5cab2676937l, + 0xe7050b06bf669f21l }, + { 0xfbe948b61ede9046l,0xa053005197662659l,0x58cbd4edf10124c5l, + 0xde2646e4dd6c06c8l }, + 0 }, + /* 64 << 56 */ + { { 0x332f81088cad38c0l,0x471b7e906bd68ae2l,0x56ac3fb20d8e27a3l, + 0xb54660db136b4b0dl }, + { 0x123a1e11a6fd8de4l,0x44dbffeaa37799efl,0x4540b977ce6ac17cl, + 0x495173a8af60acefl }, + 0 }, + /* 65 << 56 */ + { { 0xc48b1478db447d0bl,0xe1b85f5d46104fbbl,0x4ab31e7d991c60b9l, + 0xaa674a9258a0cfd0l }, + { 0x179fc2cd316f4297l,0x90c18642dcccbc82l,0x65d4309e56a4c163l, + 0xf211a9c7145a33ecl }, + 0 }, + /* 71 << 56 */ + { { 0x9669170cdc32717fl,0x52d69b5138133e34l,0xaed24e5fb079c3b2l, + 0xaba44a91a21ea3d2l }, + { 0xd6814f1938d40105l,0x38289fe463462e7al,0x1793eefa3a80cbf5l, + 0x05816a0795f29bacl }, + 0 }, + /* 77 << 56 */ + { { 0xdca88ad98f850641l,0x8c1152c447999b0dl,0x509f654e654aff33l, + 0x2228550f08a12f14l }, + { 0x60fe99dbb6a0ccdbl,0x80d6829bfc2cddccl,0x190f454dd5617aa4l, + 0x0aea05fe36295d2dl }, + 0 }, + /* 83 << 56 */ + { { 0x1de06c8af9bef9a5l,0xe24d85d3fb2d3164l,0x3dbe455e8d203d3el, + 0x439bee4735ea47a9l }, + { 0xcc143432784893d7l,0x9b71073bd9bebd00l,0x6c106b343aa2fe88l, + 0x9df2a42734746f7al }, + 0 }, + /* 89 << 56 */ + { { 0x1ad0b3725a8c2168l,0x64e52d6d143f0402l,0xd933c783e320f31fl, + 0x1ccf90a80ff14f52l }, + { 0xd3a3133ee1e6d0c0l,0xfd75a2d5b4acc8cal,0x62659b8e5559d171l, + 0x5087d6e9f13ad52al }, + 0 }, + /* 95 << 56 */ + { { 0xb4d647a5deef31a4l,0x95bf4ab180975ea9l,0x2f92d15adf57b03el, + 0x5ee808ab746b26d6l }, + { 0x4341597c1082f261l,0x027795eb40c45e95l,0xcb77744b3b690c30l, + 0xdd87c084af3f88d1l }, + 0 }, + /* 101 << 56 */ + { { 0x469f177572109785l,0xf365e55123f84d6cl,0x8006a9c28a046dbbl, + 0x1b9fbe892fa09f52l }, + { 0xac18a88016075e9el,0x4a3069bc1e3fd628l,0x20c61eaa60c61c14l, + 0x315b59daf61f004bl }, + 0 }, + /* 107 << 56 */ + { { 0x0a94387f26d04857l,0x952a4ebc43d6de95l,0xb422e15cf14abdfal, + 0x5b7a0153324ef90cl }, + { 0x6aefa20e9826ec5bl,0x0e529886ad2fe161l,0xb710a74ec0d416e8l, + 0x6cf4b0a5fb6c90bcl }, + 0 }, + /* 113 << 56 */ + { { 0x822aea4031979d3bl,0xb504eafde215a109l,0xa8761ead84bf2377l, + 0xb55c1e55efb3d942l }, + { 0xd01f9b0212b7f17bl,0x41b62c2a891bfbbfl,0x50800e6b08938149l, + 0x527b50a9b0a55d82l }, + 0 }, + /* 116 << 56 */ + { { 0x6bc84d8d1d9ce3c4l,0x53b465072a308df0l,0x6c3da9bfca79c88al, + 0x9636ad9c36372acfl }, + { 0x8840e92c425ef14cl,0x863191f96af3225bl,0xd56d82d0d369b857l, + 0x2053a2527a4c41f9l }, + 0 }, + /* 119 << 56 */ + { { 0x20aecd6609ca8805l,0x945d9b31dc818ee6l,0x1424647c2119b44bl, + 0xbe934d7e5a6641f9l }, + { 0xe91d53184559e55el,0xc2fb8e0b4dfbc3d4l,0x9e92e20676cb937fl, + 0x0f5582e4f2932429l }, + 0 }, + /* 125 << 56 */ + { { 0xb5fc22a42d31809fl,0x6d582d2b0e35b7b4l,0x5fac415158c5f576l, + 0xdff239371e4cd7c9l }, + { 0x0f62b329ed4d1925l,0x00994a2e6010fb16l,0xb4b91076bd754837l, + 0xfde219463345103al }, + 0 }, + }, + { + /* 0 << 64 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 64 */ + { { 0x4f922fc516a0d2bbl,0x0d5cc16c1a623499l,0x9241cf3a57c62c8bl, + 0x2f5e6961fd1b667fl }, + { 0x5c15c70bf5a01797l,0x3d20b44d60956192l,0x04911b37071fdb52l, + 0xf648f9168d6f0f7bl }, + 0 }, + /* 3 << 64 */ + { { 0x4090914bb5def996l,0x1cb69c83233dd1e7l,0xc1e9c1d39b3d5e76l, + 0x1f3338edfccf6012l }, + { 0xb1e95d0d2f5378a8l,0xacf4c2c72f00cd21l,0x6e984240eb5fe290l, + 0xd66c038d248088ael }, + 0 }, + /* 4 << 64 */ + { { 0x9ad5462bb4d8bc50l,0x181c0b16a9195770l,0xebd4fe1c78412a68l, + 0xae0341bcc0dff48cl }, + { 0xb6bc45cf7003e866l,0xf11a6dea8a24a41bl,0x5407151ad04c24c2l, + 0x62c9d27dda5b7b68l }, + 0 }, + /* 5 << 64 */ + { { 0xd4992b30614c0900l,0xda98d121bd00c24bl,0x7f534dc87ec4bfa1l, + 0x4a5ff67437dc34bcl }, + { 0x68c196b81d7ea1d7l,0x38cf289380a6d208l,0xfd56cd09e3cbbd6el, + 0xec72e27e4205a5b6l }, + 0 }, + /* 7 << 64 */ + { { 0xe8b97932b88756ddl,0xed4e8652f17e3e61l,0xc2dd14993ee1c4a4l, + 0xc0aaee17597f8c0el }, + { 0x15c4edb96c168af3l,0x6563c7bfb39ae875l,0xadfadb6f20adb436l, + 0xad55e8c99a042ac0l }, + 0 }, + /* 9 << 64 */ + { { 0x65c29219909523c8l,0xa62f648fa3a1c741l,0x88598d4f60c9e55al, + 0xbce9141b0e4f347al }, + { 0x9af97d8435f9b988l,0x0210da62320475b6l,0x3c076e229191476cl, + 0x7520dbd944fc7834l }, + 0 }, + /* 10 << 64 */ + { { 0x87a7ebd1e0a1b12al,0x1e4ef88d770ba95fl,0x8c33345cdc2ae9cbl, + 0xcecf127601cc8403l }, + { 0x687c012e1b39b80fl,0xfd90d0ad35c33ba4l,0xa3ef5a675c9661c2l, + 0x368fc88ee017429el }, + 0 }, + /* 11 << 64 */ + { { 0x664300b07850ec06l,0xac5a38b97d3a10cfl,0x9233188de34ab39dl, + 0xe77057e45072cbb9l }, + { 0xbcf0c042b59e78dfl,0x4cfc91e81d97de52l,0x4661a26c3ee0ca4al, + 0x5620a4c1fb8507bcl }, + 0 }, + /* 13 << 64 */ + { { 0x84b9ca1504b6c5a0l,0x35216f3918f0e3a3l,0x3ec2d2bcbd986c00l, + 0x8bf546d9d19228fel }, + { 0xd1c655a44cd623c3l,0x366ce718502b8e5al,0x2cfc84b4eea0bfe7l, + 0xe01d5ceecf443e8el }, + 0 }, + /* 15 << 64 */ + { { 0xa75feacabe063f64l,0x9b392f43bce47a09l,0xd42415091ad07acal, + 0x4b0c591b8d26cd0fl }, + { 0x2d42ddfd92f1169al,0x63aeb1ac4cbf2392l,0x1de9e8770691a2afl, + 0xebe79af7d98021dal }, + 0 }, + /* 16 << 64 */ + { { 0x58af2010f5b343bcl,0x0f2e400af2f142fel,0x3483bfdea85f4bdfl, + 0xf0b1d09303bfeaa9l }, + { 0x2ea01b95c7081603l,0xe943e4c93dba1097l,0x47be92adb438f3a6l, + 0x00bb7742e5bf6636l }, + 0 }, + /* 17 << 64 */ + { { 0x66917ce63b5f1cc4l,0x37ae52eace872e62l,0xbb087b722905f244l, + 0x120770861e6af74fl }, + { 0x4b644e491058edeal,0x827510e3b638ca1dl,0x8cf2b7046038591cl, + 0xffc8b47afe635063l }, + 0 }, + /* 19 << 64 */ + { { 0x7677408d6dfafed3l,0x33a0165339661588l,0x3c9c15ec0b726fa0l, + 0x090cfd936c9b56dal }, + { 0xe34f4baea3c40af5l,0x3469eadbd21129f1l,0xcc51674a1e207ce8l, + 0x1e293b24c83b1ef9l }, + 0 }, + /* 21 << 64 */ + { { 0x796d3a85825808bdl,0x51dc3cb73fd6e902l,0x643c768a916219d1l, + 0x36cd7685a2ad7d32l }, + { 0xe3db9d05b22922a4l,0x6494c87edba29660l,0xf0ac91dfbcd2ebc7l, + 0x4deb57a045107f8dl }, + 0 }, + /* 23 << 64 */ + { { 0xb6c69ac82094cec3l,0x9976fb88403b770cl,0x1dea026c4859590dl, + 0xb6acbb468562d1fdl }, + { 0x7cd6c46144569d85l,0xc3190a3697f0891dl,0xc6f5319548d5a17dl, + 0x7d919966d749abc8l }, + 0 }, + /* 25 << 64 */ + { { 0xb53b7de561906373l,0x858dbadeeb999595l,0x8cbb47b2a59e5c36l, + 0x660318b3dcf4e842l }, + { 0xbd161ccd12ba4b7al,0xf399daabf8c8282al,0x1587633aeeb2130dl, + 0xa465311ada38dd7dl }, + 0 }, + /* 27 << 64 */ + { { 0x2dae9082be7cf3a6l,0xcc86ba92bc967274l,0xf28a2ce8aea0a8a9l, + 0x404ca6d96ee988b3l }, + { 0xfd7e9c5d005921b8l,0xf56297f144e79bf9l,0xa163b4600d75ddc2l, + 0x30b23616a1f2be87l }, + 0 }, + /* 28 << 64 */ + { { 0x19e6125dec3f1decl,0x07b1f040911178dal,0xd93ededa904a6738l, + 0x55187a5a0bebedcdl }, + { 0xf7d04722eb329d41l,0xf449099ef170b391l,0xfd317a69ca99f828l, + 0x50c3db2b34a4976dl }, + 0 }, + /* 29 << 64 */ + { { 0x0064d8585499fb32l,0x7b67bad977a8aeb7l,0x1d3eb9772d08eec5l, + 0x5fc047a6cbabae1dl }, + { 0x0577d159e54a64bbl,0x8862201bc43497e4l,0xad6b4e282ce0608dl, + 0x8b687b7d0b167aacl }, + 0 }, + /* 31 << 64 */ + { { 0xe9f9669cda94951el,0x4b6af58d66b8d418l,0xfa32107417d426a4l, + 0xc78e66a99dde6027l }, + { 0x0516c0834a53b964l,0xfc659d38ff602330l,0x0ab55e5c58c5c897l, + 0x985099b2838bc5dfl }, + 0 }, + /* 33 << 64 */ + { { 0xe7a935fa1684cb3bl,0x571650b5a7d7e69dl,0x6ba9ffa40328c168l, + 0xac43f6bc7e46f358l }, + { 0x54f75e567cb6a779l,0x4e4e2cc8c61320del,0xb94258bc2b8903d0l, + 0xc7f32d57ceecabe0l }, + 0 }, + /* 34 << 64 */ + { { 0x34739f16cd7d9d89l,0x6daab4267ca080b5l,0x772086ff40e19f45l, + 0x43caa56118c61b42l }, + { 0x0ba3d4a8dbf365f1l,0xa0db435ee760ad97l,0xfd6f30d56916c59bl, + 0xab34cb5dafe12f5dl }, + 0 }, + /* 35 << 64 */ + { { 0x445b86ea02a3260al,0x8c51d6428d689babl,0x183334d65588904cl, + 0xf8a3b84d479d6422l }, + { 0x581acfa0f0833d00l,0xc50827bc3b567d2dl,0x2c935e6daddcf73el, + 0x2a645f7704dd19f2l }, + 0 }, + /* 36 << 64 */ + { { 0x78d2e8dfcb564473l,0x4349a97357d5621al,0x9d835d89218f8b24l, + 0x01fe7bc5079b6ee2l }, + { 0xe57f2a2b5b3b5dcel,0x5a8637b75fe55565l,0x83ff34aea41dbae7l, + 0xfce1199c950a7a8fl }, + 0 }, + /* 37 << 64 */ + { { 0x0ca5d25bf8e71ce2l,0x204edc4a062685dal,0x06fe407d87678ec2l, + 0xd16936a07defa39al }, + { 0x3b108d84af3d16d0l,0xf2e9616d0305cad0l,0xbc9537e6f27bed97l, + 0x71c2d699ebc9f45cl }, + 0 }, + /* 39 << 64 */ + { { 0x203bdd84cdcd3a85l,0x1107b901ade3ccfal,0xa7da89e95533159dl, + 0x8d834005860e8c64l }, + { 0x914bc0eb2a7638f7l,0xc66ce0a6620e8606l,0x11ef98c2e6c12dc0l, + 0x25666b1d7780fc0el }, + 0 }, + /* 40 << 64 */ + { { 0x374f541f3e707706l,0x9a4d3638a831d0cfl,0x4ab4f4831518ca04l, + 0x54e3ee5dfe38c318l }, + { 0x383ae36403c8819bl,0xa9d1daa12e17864cl,0x245a97b350eeaa5bl, + 0x5362d00999bf4e83l }, + 0 }, + /* 41 << 64 */ + { { 0x6667e89f4ded8a4fl,0xa59161abc36a7795l,0x1c96f6f9331ccf94l, + 0xf2727e879a686d49l }, + { 0x0f94894bb841295fl,0xb0fe8f744a0503d1l,0x60c581c7ef407926l, + 0x1980c8e13edb7e1cl }, + 0 }, + /* 43 << 64 */ + { { 0x47948c84c5de1a41l,0xd595d14a48959688l,0x3bfca4be86ff21c9l, + 0xb5ff59b86a4191cal }, + { 0xced1dd1d65094c86l,0xd57b86559dc9d001l,0xbcac6fa3486e51d7l, + 0x8e97e2637b774c1bl }, + 0 }, + /* 44 << 64 */ + { { 0xfc0313c29bd43980l,0x9c954b70f172db29l,0x679bdcb7f954a21al, + 0x6b48170954e2e4fcl }, + { 0x318af5f530baf1d0l,0x26ea8a3ccbf92060l,0xc3c69d7ccd5ae258l, + 0xa73ba0470ead07c9l }, + 0 }, + /* 45 << 64 */ + { { 0xe82eb003e35dca85l,0xfd0000fa31e39180l,0xbca90f746735f378l, + 0xe6aa783158c943edl }, + { 0x0e94ecd5b6a438d7l,0xc02b60faf9a5f114l,0x4063568b8b1611ebl, + 0x1398bdc1272509ecl }, + 0 }, + /* 46 << 64 */ + { { 0xc2ef6a01be3e92d1l,0x1bce9c27282bd5ddl,0xf7e488f3adda0568l, + 0xd4f15fdb1af9bb8bl }, + { 0x8c490ade4da846efl,0x76229da17f0b825el,0xc8b812082a6711c6l, + 0x511f5e23b4c523aal }, + 0 }, + /* 47 << 64 */ + { { 0xbdf4e7049970f46el,0x70e220288dadbd1al,0x2b86c97fb1223d26l, + 0x042ad22ecf62f51al }, + { 0x72944339ba2ed2e9l,0x0ba0d10ef94fa61dl,0x3f86164194e68f15l, + 0x1312a74acb86c545l }, + 0 }, + /* 48 << 64 */ + { { 0x3a63c39731815e69l,0x6df9cbd6dcdd2802l,0x4c47ed4a15b4f6afl, + 0x62009d826ac0f978l }, + { 0x664d80d28b898fc7l,0x72f1eeda2c17c91fl,0x9e84d3bc7aae6609l, + 0x58c7c19528376895l }, + 0 }, + /* 49 << 64 */ + { { 0x640ebf5d5b8d354al,0xa5f3a8fdb396ff64l,0xd53f041d8378ed81l, + 0x1969d61bc1234ad2l }, + { 0x16d7acffeb68bde2l,0x63767a68f23e9368l,0x937a533c38928d95l, + 0xee2190bbbeb0f1f2l }, + 0 }, + /* 51 << 64 */ + { { 0xb6860c9a73a4aafbl,0xb2f996290488870dl,0x16ef6232572d9e25l, + 0x5b9eb1bad1383389l }, + { 0xabf713a7ed8d77f8l,0xd2b4a2e9e2b69e64l,0xa1a22cfd6d6f17c2l, + 0x4bfd6f992d604511l }, + 0 }, + /* 52 << 64 */ + { { 0xdcff7630d9294f07l,0x89b765d68dba8fd0l,0x553e55de8dbcaccdl, + 0x9b4a009eed702bf8l }, + { 0xf6e534dd27b8ca0dl,0xc4496b346177fd52l,0x378ce6f6c87bb7b7l, + 0x68633d4844cc19f0l }, + 0 }, + /* 53 << 64 */ + { { 0xfe550021bc84c625l,0x8d7169986d45e4a3l,0xa09c6ded4c0c66b7l, + 0xe32313aeb9e1d547l }, + { 0x8ce775b4d1e8e0b9l,0xa899f9102654dd15l,0x7c38aa066cc8b2a9l, + 0xe6ebb291d6ce6cc0l }, + 0 }, + /* 55 << 64 */ + { { 0x5963df62a6991216l,0x4c17f72246996010l,0x131dc2b840477722l, + 0x78bf50b0d1765a75l }, + { 0x360afd587ceaca12l,0xebc55dbb139cd470l,0x9083e27e4c05541cl, + 0xc10057a3b873d757l }, + 0 }, + /* 57 << 64 */ + { { 0x440009c3deed7769l,0xde2fa58a14fd8a44l,0x509e7df35b627596l, + 0x3d76a87cc3bb07a7l }, + { 0x8018fee5b8ef000al,0x71ce33e9823fd4b6l,0x3a1cac37469c0bb1l, + 0x92fe7aeaf3eec8eel }, + 0 }, + /* 59 << 64 */ + { { 0x37ad0eb8de64e568l,0x4ac669bca1e3e20el,0x240d0ac22ce944edl, + 0xd532039a3c1b28fbl }, + { 0xa2bb899a23acba6cl,0xd472af671af937e1l,0x04478f7b8851e753l, + 0x74030eef5ea05307l }, + 0 }, + /* 60 << 64 */ + { { 0x3559e7b67dc17874l,0xd0caf0ef8195cc2al,0x07c067880cd24dd9l, + 0x01a99ea002857c41l }, + { 0xd86579e490f82f63l,0xb1e0658ae41c9237l,0x075ffafd93fd1e79l, + 0x6e70403547f60b8fl }, + 0 }, + /* 61 << 64 */ + { { 0x2246ad76c1d68c31l,0x9126202b0d5c4677l,0x5f40de81638882dcl, + 0xb131988ca3253a7fl }, + { 0x766f1897ba9ae0a8l,0xf0e01dd41d8b5fefl,0x03e28ce3ed7b12c8l, + 0x44b3a2be1fd20e1el }, + 0 }, + /* 63 << 64 */ + { { 0xd4c8e8e5f2a5f247l,0x42ffd816c2c7c979l,0x89e1485211093d1al, + 0x98f44a4613871ebbl }, + { 0x374849964b032e2dl,0x28a430f445995a61l,0xf2f9acbad5be16b6l, + 0xac98a5402d8e02aal }, + 0 }, + /* 64 << 64 */ + { { 0x0d53f5c7a3e6fcedl,0xe8cbbdd5f45fbdebl,0xf85c01df13339a70l, + 0x0ff71880142ceb81l }, + { 0x4c4e8774bd70437al,0x5fb32891ba0bda6al,0x1cdbebd2f18bd26el, + 0x2f9526f103a9d522l }, + 0 }, + /* 65 << 64 */ + { { 0x48334fdcc20b8d30l,0x25f887d749414fddl,0x9ccd513311a2cf0dl, + 0x7e7799e4d08975a4l }, + { 0xb5993a53729b951cl,0x0cf14a5a62dbc6a8l,0xb39ed36efe4d16eel, + 0xb75f3fb681bda63al }, + 0 }, + /* 71 << 64 */ + { { 0xac7db8706d4f68b5l,0x819a13c7be49b3a4l,0x646ae2b1418bf1e9l, + 0x25b53a5f69b3a5ccl }, + { 0xd23d94d37de26578l,0x8bb581caecdd138al,0x9e053f67f857b0dal, + 0xe679cc7a255ff474l }, + 0 }, + /* 77 << 64 */ + { { 0x4a4b8d990df097f9l,0x0ae1227a0b4173cal,0x0d401778adb72178l, + 0xd29848b43f421e0cl }, + { 0xc5eec6096eb0722dl,0x527d72877e12c028l,0xed12a9e71b5dcc0cl, + 0x26b27344dcf4b4dal }, + 0 }, + /* 83 << 64 */ + { { 0x695c502565e4408al,0x2d23768fcbce94e6l,0x1505fa1e5080b88dl, + 0x5c8fbab6855f7cc1l }, + { 0x70d876f275fb125dl,0x456421330a252007l,0xfe99249a8ee05be1l, + 0x0893b620f4bf5490l }, + 0 }, + /* 89 << 64 */ + { { 0x2a59df1ed9fe6bdfl,0x96a9c791785e057fl,0x4b0d795f86a1d751l, + 0x196c8e0aec642886l }, + { 0x6df67899bc0e055cl,0x4173204a63007433l,0xb5ee4efec21c9245l, + 0x2f7d4c75c1451bael }, + 0 }, + /* 95 << 64 */ + { { 0x2ad7f836b1047b7fl,0x368d431a71f6bfe1l,0xfcd933b103db4667l, + 0xfff77ed3ecb81330l }, + { 0x3677935b44958bd4l,0xa6cfcda8a1d5a9e7l,0xb2b73bc699ff9fael, + 0x1c2cd628f866d3c4l }, + 0 }, + /* 101 << 64 */ + { { 0x2756873495031ceel,0xebed373d51091c1bl,0x398fef0819aa2f27l, + 0x2f26174e2c0a9feal }, + { 0xedca72b6b219be3fl,0x001a8fdc80503df8l,0x9a2fadbb6b93f643l, + 0xd48e552cd44cebc3l }, + 0 }, + /* 107 << 64 */ + { { 0x6c0dbb68667a7ab6l,0x00490ce757630e91l,0x04976cd57eb2f382l, + 0x9ee486b655dda4a3l }, + { 0x4ea5c9c9cca0d01cl,0xa6e054b639f69c6dl,0xb3b7ac992ecab239l, + 0x80c9f6d17597512el }, + 0 }, + /* 113 << 64 */ + { { 0x64dfdd68b942fad9l,0xe7d8e88da5eb3d14l,0xb7281dc2382f6301l, + 0xcfa2ee6dbfe00a7fl }, + { 0x6e617657dc7be39fl,0x22d58dd6591c6e3al,0xd3a4003918318c13l, + 0xcac6c830981b6b72l }, + 0 }, + /* 116 << 64 */ + { { 0x009690ffb4fbfaa0l,0x8bbbdab73619c6dbl,0xc6d44273728356e8l, + 0xfd76f0d8e453ec35l }, + { 0x775c2554aac28a29l,0x28f7af9d5c55e4f0l,0xbacf54a688e8ad4dl, + 0x85b018e80aa76ddfl }, + 0 }, + /* 119 << 64 */ + { { 0x27893f7983ce88e4l,0x9556c9977785f13dl,0x83d3c38d3a35831el, + 0x3856c829d12f0a1dl }, + { 0xb308d84c93259c1al,0x4ef87ab4691ffd28l,0x76a18d5321a88c58l, + 0xf13cd5d53503cb4dl }, + 0 }, + /* 125 << 64 */ + { { 0x669d93dba8cc0db3l,0x403cb9200dfcfcf4l,0x5def4a03e77c3979l, + 0x2a05c9423e2e2522l }, + { 0xd86dca52b5f48bf0l,0x174766de5828a135l,0x116290b40d3a96d0l, + 0xe1999457aeea1193l }, + 0 }, + }, + { + /* 0 << 72 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 72 */ + { { 0x0db2fb5ed005832al,0x5f5efd3b91042e4fl,0x8c4ffdc6ed70f8cal, + 0xe4645d0bb52da9ccl }, + { 0x9596f58bc9001d1fl,0x52c8f0bc4e117205l,0xfd4aa0d2e398a084l, + 0x815bfe3a104f49del }, + 0 }, + /* 3 << 72 */ + { { 0x524d226ad7ab9a2dl,0x9c00090d7dfae958l,0x0ba5f5398751d8c2l, + 0x8afcbcdd3ab8262dl }, + { 0x57392729e99d043bl,0xef51263baebc943al,0x9feace9320862935l, + 0x639efc03b06c817bl }, + 0 }, + /* 4 << 72 */ + { { 0xe839be7d341d81dcl,0xcddb688932148379l,0xda6211a1f7026eadl, + 0xf3b2575ff4d1cc5el }, + { 0x40cfc8f6a7a73ae6l,0x83879a5e61d5b483l,0xc5acb1ed41a50ebcl, + 0x59a60cc83c07d8fal }, + 0 }, + /* 5 << 72 */ + { { 0xdec98d4ac3b81990l,0x1cb837229e0cc8fel,0xfe0b0491d2b427b9l, + 0x0f2386ace983a66cl }, + { 0x930c4d1eb3291213l,0xa2f82b2e59a62ae4l,0x77233853f93e89e3l, + 0x7f8063ac11777c7fl }, + 0 }, + /* 7 << 72 */ + { { 0x36e607cf02ff6072l,0xa47d2ca98ad98cdcl,0xbf471d1ef5f56609l, + 0xbcf86623f264ada0l }, + { 0xb70c0687aa9e5cb6l,0xc98124f217401c6cl,0x8189635fd4a61435l, + 0xd28fb8afa9d98ea6l }, + 0 }, + /* 9 << 72 */ + { { 0x3d4da8c3017025f3l,0xefcf628cfb9579b4l,0x5c4d00161f3716ecl, + 0x9c27ebc46801116el }, + { 0x5eba0ea11da1767el,0xfe15145247004c57l,0x3ace6df68c2373b7l, + 0x75c3dffe5dbc37acl }, + 0 }, + /* 10 << 72 */ + { { 0xa2a147dba28a0749l,0x246c20d6ee519165l,0x5068d1b1d3810715l, + 0xb1e7018c748160b9l }, + { 0x03f5b1faf380ff62l,0xef7fb1ddf3cb2c1el,0xeab539a8fc91a7dal, + 0x83ddb707f3f9b561l }, + 0 }, + /* 11 << 72 */ + { { 0xb57276d980101b98l,0x760883fdb82f0f66l,0x89d7de754bc3eff3l, + 0x03b606435dc2ab40l }, + { 0xcd6e53dfe05beeacl,0xf2f1e862bc3325cdl,0xdd0f7921774f03c3l, + 0x97ca72214552cc1bl }, + 0 }, + /* 13 << 72 */ + { { 0x760cb3b5e224c5d7l,0xfa3baf8c68616919l,0x9fbca1138d142552l, + 0x1ab18bf17669ebf5l }, + { 0x55e6f53e9bdf25ddl,0x04cc0bf3cb6cd154l,0x595bef4995e89080l, + 0xfe9459a8104a9ac1l }, + 0 }, + /* 15 << 72 */ + { { 0x694b64c5abb020e8l,0x3d18c18419c4eec7l,0x9c4673ef1c4793e5l, + 0xc7b8aeb5056092e6l }, + { 0x3aa1ca43f0f8c16bl,0x224ed5ecd679b2f6l,0x0d56eeaf55a205c9l, + 0xbfe115ba4b8e028bl }, + 0 }, + /* 16 << 72 */ + { { 0x3e22a7b397acf4ecl,0x0426c4005ea8b640l,0x5e3295a64e969285l, + 0x22aabc59a6a45670l }, + { 0xb929714c5f5942bcl,0x9a6168bdfa3182edl,0x2216a665104152bal, + 0x46908d03b6926368l }, + 0 }, + /* 17 << 72 */ + { { 0x9b8be0247fcba850l,0x81eb5797820a181el,0xa0f2812230a01211l, + 0x7e9cdc3cae7b8821l }, + { 0x202332cc72ce15e7l,0xcd3cb2bbcb8238d7l,0xe4ab63dfc6e82c43l, + 0x58bd00283183d717l }, + 0 }, + /* 19 << 72 */ + { { 0x02d57b7e717ed7b5l,0xd22e5b244dbce1a2l,0x174bd7712a4cdcf5l, + 0xa6fdb801408205bbl }, + { 0x67b4b0695e1387e9l,0x332b19a10591a442l,0x24edd916ccacf366l, + 0xbe34cc4534958a50l }, + 0 }, + /* 21 << 72 */ + { { 0xa3f46e1e3e66d391l,0xb4a732cd7d6369b2l,0x99c3b85d402c1022l, + 0x7dccfcbe2b54932el }, + { 0xa6ddaa7b56b1dfe2l,0x31dc78a5e34a82c9l,0x8abeb3da704f3941l, + 0xdf11a36cca55fa98l }, + 0 }, + /* 23 << 72 */ + { { 0x6c01f77a16e00c1bl,0x82515490839eaaacl,0x62f3a4ef3470d334l, + 0x5a29a6491c1dcd6cl }, + { 0x46b6782ece997a25l,0x9978fb35d3579953l,0x98f5a9df0960e0cel, + 0x547dc8391f527a4cl }, + 0 }, + /* 25 << 72 */ + { { 0x395b15835d9dc24fl,0xa4256932c73ae680l,0x0542960efaa2c8e9l, + 0x2bb3adee71068c6al }, + { 0xa706099b570b4554l,0x85d12bb5f4e278d6l,0xd78af6f664296843l, + 0xc7d3b3888428c633l }, + 0 }, + /* 27 << 72 */ + { { 0x34d44f9343b7e597l,0xdde440a7c2530f42l,0x7270a0817856bdb9l, + 0x86a945eb5353032fl }, + { 0x6c2f8e9966d39810l,0x0642a31b9b8b4b6bl,0x51679e62d1509d82l, + 0x0120001c90f8ff16l }, + 0 }, + /* 28 << 72 */ + { { 0x50a1c1062e36e34al,0x74e8f58ce024ed1al,0x3f0f1dfa1300d726l, + 0x6680df267b4a2d18l }, + { 0x12b5979d8235b3b7l,0x1d2fafcb8a611493l,0x73ebda968848ece5l, + 0xe996c275a413e399l }, + 0 }, + /* 29 << 72 */ + { { 0x46b7d7c7495ff000l,0xe60ed097baed95d1l,0xaa8804ac6e38f9c0l, + 0x92990c0645c6f9bbl }, + { 0xcae6a439c0919851l,0x713dff151bf5e1f2l,0x5d262c302eb38cdbl, + 0xb73d505190df31dfl }, + 0 }, + /* 31 << 72 */ + { { 0x921e7b1c32d9268cl,0x34db2b964276fad4l,0x0ec56d34cc44e730l, + 0x59be3a46096545b7l }, + { 0xe9fdbc9766cf3a6al,0x7b2f83edd04e9b53l,0x6d99b3cc8fbae3e7l, + 0x8eb5646c7ada3a40l }, + 0 }, + /* 33 << 72 */ + { { 0xa69ab906fc3302bfl,0x49ae6ba7d0872e90l,0xc9e2d6d1f3a1bfc3l, + 0x11dfe85f1a033500l }, + { 0x45189c2998666dbdl,0xba6aab88bbfd13cel,0xcf9c8b43dbd38cd4l, + 0xa0cb581b68009236l }, + 0 }, + /* 34 << 72 */ + { { 0xff18c42a16288a7al,0x6363ace430699163l,0x8546d6332a2ce353l, + 0x5e0379ef7b6b3418l }, + { 0x2df2bb463e941bb2l,0xae7c091888e1aacel,0x6bc0982d83f5a37al, + 0x8521bd02676d09e0l }, + 0 }, + /* 35 << 72 */ + { { 0x6531dff33d361aacl,0x59b954477c8cac2el,0xcc104df6c5cb7363l, + 0x68b571c519364acdl }, + { 0x7521e962979c3bc0l,0xbe0544c9c4aa1f92l,0x59127fe92a31eabbl, + 0x760ac28593d8b55bl }, + 0 }, + /* 36 << 72 */ + { { 0x62ed534c6115164bl,0xaebe9e4cdce84ceal,0xd81c91a1c83f64c3l, + 0x325a8ca8ecacd09al }, + { 0x7ea57ad968b45df1l,0xa555636fd530c5d2l,0x23aff510591cfe32l, + 0x46ff147637bedab9l }, + 0 }, + /* 37 << 72 */ + { { 0xa5a7e81ecb2edb3bl,0x9b0dc5f4f8fbe238l,0xc6f258087c66dd34l, + 0xb4a57503a3f8f38al }, + { 0x195b433513571b5bl,0xa32840763ccbc30bl,0x64ae1ffccf99ddd5l, + 0x0dfc8772aa844e76l }, + 0 }, + /* 39 << 72 */ + { { 0x8b471afbfb22341dl,0xbf448b43397afdd2l,0x4cb08409682c37edl, + 0xc3acfae6a948f1f6l }, + { 0xf58462549e634707l,0x50161a78bd949f52l,0xf0529e752fe73566l, + 0xe7e3fdef6fda53e0l }, + 0 }, + /* 40 << 72 */ + { { 0x56dab1c8321a518cl,0xfd4439a68bce226fl,0xe0b30d194facb9fal, + 0xb5052f307583571bl }, + { 0x1442641012afd476l,0xd02e417203fe624al,0xfc394f65531c92e6l, + 0x16d4bf5ad4bc0b52l }, + 0 }, + /* 41 << 72 */ + { { 0xa38ac25eb4ec4f0fl,0x5399c024de72b27dl,0x08318aafd81a3d65l, + 0x1af227a70c20e5d9l }, + { 0x6389cc9a26c54e25l,0x438298bba47dc27fl,0x75386cca1a63fa0el, + 0xc941e84cdf7bc1b0l }, + 0 }, + /* 43 << 72 */ + { { 0x81cad748fdfe3faal,0x752107b453ff1988l,0x8d8bb7001a8fd829l, + 0x69838e15ca821d8el }, + { 0x24371ede3b9f6b34l,0x19b4bb24d91e1495l,0x90899ca1e598ded1l, + 0xbbb78b167c14e9e3l }, + 0 }, + /* 44 << 72 */ + { { 0xa577e84cbef239aal,0x656d2b6f8904b4d4l,0x2f6defe6ca4007edl, + 0xca6e517737770796l }, + { 0x4c62fcba298b6448l,0x046849660f62e00dl,0x806c2f0390b07d82l, + 0x730855795e8d1e60l }, + 0 }, + /* 45 << 72 */ + { { 0x24488802f4703b78l,0x6c9323bee9eaa1e0l,0x242990e2aa94c170l, + 0x3292bc42a15b5886l }, + { 0x60ccb5bc908af203l,0x8fd63583713b09bdl,0x40791ecad693fa28l, + 0xea80abf2941af8a1l }, + 0 }, + /* 46 << 72 */ + { { 0xf9c0315071145fe3l,0x80a71b55d7873a7dl,0xd134244b5e10bac7l, + 0x303f7e12ded3a4b4l }, + { 0x58e6f17e803b7a3bl,0xcd6f64130b1ca6b4l,0x25e744ce2ce65aa2l, + 0xf2bbc66b952efa51l }, + 0 }, + /* 47 << 72 */ + { { 0xc8b212e75913e1f3l,0xf018ab208d416886l,0x28249e15b617cac4l, + 0x837fcba1693ed09al }, + { 0x9c457e511c15a1bcl,0x9354758756c7f3f1l,0x1afd80348be18306l, + 0xa43d56982256ab14l }, + 0 }, + /* 48 << 72 */ + { { 0xce06b88210395755l,0x117ce6345ec1df80l,0xfefae513eff55e96l, + 0xcf36cba6fd7fed1el }, + { 0x7340eca9a40ebf88l,0xe6ec1bcfb3d37e12l,0xca51b64e86bbf9ffl, + 0x4e0dbb588b40e05el }, + 0 }, + /* 49 << 72 */ + { { 0xf9c063f62f2be34bl,0x9ca32fa99c20f16bl,0xe02e350d0125a01al, + 0x62d66c54e6516c25l }, + { 0x21b154ad5120bedbl,0xb1077f4e8d6ff9d8l,0xd01a46c300bb4941l, + 0x9d381847d1460588l }, + 0 }, + /* 51 << 72 */ + { { 0xf3a9b311581cb57bl,0x65fb3fb649727d13l,0xb8496e3d35131142l, + 0xf7642f554d0cdab9l }, + { 0xe2f66f0e9f6d7e45l,0xbae14cedaa22fcd4l,0x1f769f0e49b2e05al, + 0x08c4d7784ac5191el }, + 0 }, + /* 52 << 72 */ + { { 0x86f9108ece4aa825l,0xbe5b2f317e5a5fbfl,0x2772c1b49254bb78l, + 0xae6cdf5f4ff8ac5cl }, + { 0x106cd94bf6b7a12el,0xbe0915d6d1c7a1a5l,0x8bf6bc8d3b40ac5el, + 0xbb89180423ee3acal }, + 0 }, + /* 53 << 72 */ + { { 0x76f15eaa618b5ea1l,0xec1ea62e6d4ad0c8l,0x301b60c8168d57fal, + 0x454d5f771edbfb05l }, + { 0xea888e29a936031al,0x01303d3f0174dd17l,0x8b5e06b4244254e7l, + 0x00ebf03509724acfl }, + 0 }, + /* 55 << 72 */ + { { 0x66ce3ded8e66d509l,0x368e38d05a488586l,0x7b9ae220c7eedf5el, + 0x67e9ea52bfbf9d62l }, + { 0xe9cbf53d99b7ecb3l,0xfde3e8c0908bf072l,0x288400ab1107e21fl, + 0x24c8856256532667l }, + 0 }, + /* 57 << 72 */ + { { 0x0d5f9955ca9d3ad1l,0x545feba13a1daec0l,0xd22972016cb30f23l, + 0x9660175ccef6cf6el }, + { 0xbf3e341a395738dcl,0x74a5efbc80f7cca4l,0xc4f9a07bbebc6a60l, + 0x2f1e3dad4b1f915al }, + 0 }, + /* 59 << 72 */ + { { 0xada4423f0d5e2e34l,0x2d31f4920b372358l,0xd7f469370e2d6a8cl, + 0xf5e7ccfe0028e4ael }, + { 0x20fcb1f3928854b2l,0x2a8973c507271bf6l,0xe87de33e5fa88fe1l, + 0xe9af2dce7bd3c2a6l }, + 0 }, + /* 60 << 72 */ + { { 0x185a19d959d097b2l,0xb1c72a3a0dea2875l,0x3b371628f9021f08l, + 0x45f1255bfa9d6ac1l }, + { 0x9ff36a90cfd72c0dl,0x8c7315db24fe2376l,0x9aebcde04b34d42cl, + 0x2129ab16923025f3l }, + 0 }, + /* 61 << 72 */ + { { 0x341b9dd714b4cf50l,0x7c6e4634d619d00el,0x571d6e2fdf2165ael, + 0xdedf9cd18dbe9db5l }, + { 0x52a152777c5f3dc3l,0x7d27c97ef2901cf7l,0x5e098b54d02a85dfl, + 0x6fce3e13088e3640l }, + 0 }, + /* 63 << 72 */ + { { 0xfa95be147a939904l,0xdfcf5b9bb56365ccl,0xdbb546bdd2d66922l, + 0xf26a8b9cda03ca7fl }, + { 0x96a8042d16821c0cl,0xe6729970e88ede60l,0xd028130d1285e303l, + 0x1678b01688b7de75l }, + 0 }, + /* 64 << 72 */ + { { 0x96649933aed1d1f7l,0x566eaff350563090l,0x345057f0ad2e39cfl, + 0x148ff65b1f832124l }, + { 0x042e89d4cf94cf0dl,0x319bec84520c58b3l,0x2a2676265361aa0dl, + 0xc86fa3028fbc87adl }, + 0 }, + /* 65 << 72 */ + { { 0x5db4884124627d04l,0xf92740766f7e3febl,0xd09eb11773496240l, + 0xd48e51419a6b9ec9l }, + { 0xcbb2ac97b7336e27l,0xe794fb760640bf6cl,0xc0b7f78dc7c7fa3fl, + 0x1355d071fd2edbb9l }, + 0 }, + /* 71 << 72 */ + { { 0x575d9724e84e25a3l,0x068690a13d4d8708l,0x8a7b1c6c54dd62d0l, + 0x8c45e1b37f88e231l }, + { 0x38c665466d85afe2l,0x65231642e1d69f1bl,0xb71c53a090687ec1l, + 0xdf8469d777fb5981l }, + 0 }, + /* 77 << 72 */ + { { 0xb920b503144fe6bcl,0x54b0f0593914c130l,0x63188d5a8269b650l, + 0x8d7780962fc7064dl }, + { 0xbf7b0eec5e50839al,0xaf8a7ddbe242cd06l,0x93df850809cecdb9l, + 0x4db58a72410659e9l }, + 0 }, + /* 83 << 72 */ + { { 0x460d9b383baba3cdl,0x52386e4d2cf860b8l,0xd224fe5da3924b9al, + 0xe4a4be7bcf14d813l }, + { 0xb0759e82ed3774fdl,0x57c064b38d9b6c59l,0x301ab902aee183d0l, + 0xf1c873495ba207c3l }, + 0 }, + /* 89 << 72 */ + { { 0xe8245b0a6dd58696l,0x0714eedb61091043l,0x7d9874459101129bl, + 0x4a7f1f03a0b27a21l }, + { 0x282e5cff71ee2045l,0x25c694a3da5c6b41l,0xb3d8e21f5542ca55l, + 0x57d64170e3601af0l }, + 0 }, + /* 95 << 72 */ + { { 0x9c8e86c6c6c4fee6l,0x70194db5a596119bl,0xfc6271d30e06050cl, + 0x17d94c89b15f18d2l }, + { 0x76c9e9bd49817224l,0x42621638b989c5bcl,0x1e9c4cbeb769d70cl, + 0x85e227c3b87f2783l }, + 0 }, + /* 101 << 72 */ + { { 0x146185d2117e73c5l,0xbf6214696dc38116l,0x9af9d9b5459e72cbl, + 0x7512882fb3930b85l }, + { 0xfe935379d36583b8l,0xb83ad35e7c7fdcdel,0x093ca0ab2658ae4bl, + 0xc9b16d60a756681bl }, + 0 }, + /* 107 << 72 */ + { { 0x12c24d9195d3519bl,0x1fc6db1bdb43fd06l,0x1ae49fed25bbde51l, + 0x27072e0b76d2827bl }, + { 0xdcb92e05aeb8c47fl,0x601d414056145f67l,0xcb7002652a39e8f7l, + 0x6ce9facc35620d8cl }, + 0 }, + /* 113 << 72 */ + { { 0x5c428a5ebd702c22l,0xcb6863291616129dl,0xe6278994eabcb9a1l, + 0xb409a10b9327e540l }, + { 0x6899f7cb66cf96aal,0xa9225f051c64b545l,0x00c5522ee3feec21l, + 0x35503728e083315cl }, + 0 }, + /* 116 << 72 */ + { { 0x1916d88cf1600077l,0x1ac9c238e3a58b2bl,0x3080df8535f3508dl, + 0x86cc18712744912bl }, + { 0x56aec9d5ccd15044l,0x8dd9061a5db0ab17l,0x84d6bc4e2c84171dl, + 0xd569c7d70989a5bdl }, + 0 }, + /* 119 << 72 */ + { { 0x24446b2702af35abl,0x071710478eea4565l,0xba4989db728306e6l, + 0x2cd692a85954a558l }, + { 0x644e02763576b32el,0x7efdb65c1f9fe65dl,0x04b2828e8796c048l, + 0xcfd22481187b979bl }, + 0 }, + /* 125 << 72 */ + { { 0xa10d104084ea9701l,0x27dd0dcb415e187dl,0xf667c5e939bfe45cl, + 0x3995e4ae55b67506l }, + { 0xb25117d9b5a14801l,0xeee58525fe142e92l,0x100b856a6dbae9f1l, + 0xada7057629586658l }, + 0 }, + }, + { + /* 0 << 80 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 80 */ + { { 0xe4050f1cf1c367cal,0x9bc85a9bc90fbc7dl,0xa373c4a2e1a11032l, + 0xb64232b7ad0393a9l }, + { 0xf5577eb0167dad29l,0x1604f30194b78ab2l,0x0baa94afe829348bl, + 0x77fbd8dd41654342l }, + 0 }, + /* 3 << 80 */ + { { 0xa2f7932c68af43eel,0x5502468e703d00bdl,0xe5dc978f2fb061f5l, + 0xc9a1904a28c815adl }, + { 0xd3af538d470c56a4l,0x159abc5f193d8cedl,0x2a37245f20108ef3l, + 0xfa17081e223f7178l }, + 0 }, + /* 4 << 80 */ + { { 0x1fe2a9b2b4b4b67cl,0xc1d10df0e8020604l,0x9d64abfcbc8058d8l, + 0x8943b9b2712a0fbbl }, + { 0x90eed9143b3def04l,0x85ab3aa24ce775ffl,0x605fd4ca7bbc9040l, + 0x8b34a564e2c75dfbl }, + 0 }, + /* 5 << 80 */ + { { 0x5c18acf88e2f7d90l,0xfdbf33d777be32cdl,0x0a085cd7d2eb5ee9l, + 0x2d702cfbb3201115l }, + { 0xb6e0ebdb85c88ce8l,0x23a3ce3c1e01d617l,0x3041618e567333acl, + 0x9dd0fd8f157edb6bl }, + 0 }, + /* 7 << 80 */ + { { 0x516ff3a36fa6110cl,0x74fb1eb1fb93561fl,0x6c0c90478457522bl, + 0xcfd321046bb8bdc6l }, + { 0x2d6884a2cc80ad57l,0x7c27fc3586a9b637l,0x3461baedadf4e8cdl, + 0x1d56251a617242f0l }, + 0 }, + /* 9 << 80 */ + { { 0x892c81a321175ec1l,0x9159a505ee018109l,0xc70130532d8be316l, + 0x76060c21426fa2e5l }, + { 0x074d2dfc6b6f0f22l,0x9725fc64ca01a671l,0x3f6679b92770bd8el, + 0x8fe6604fd7c9b3fel }, + 0 }, + /* 10 << 80 */ + { { 0xce711154b6e00a84l,0xd9fe7e4224890e60l,0xd10bc6c34560988fl, + 0xbdc2ef526859b004l }, + { 0xdcf0d868d5c890eel,0x893115e6119c47dcl,0xe97966fbee714567l, + 0x117813355c85aa53l }, + 0 }, + /* 11 << 80 */ + { { 0x71d530cc73204349l,0xc9df473d94a0679cl,0xc572f0014261e031l, + 0x9786b71f22f135fel }, + { 0xed6505fa6b64e56fl,0xe2fb48e905219c46l,0x0dbec45bedf53d71l, + 0xd7d782f2c589f406l }, + 0 }, + /* 13 << 80 */ + { { 0x06513c8a446cd7f4l,0x158c423b906d52a6l,0x71503261c423866cl, + 0x4b96f57093c148eel }, + { 0x5daf9cc7239a8523l,0x611b597695ac4b8bl,0xde3981db724bf7f6l, + 0x7e7d0f7867afc443l }, + 0 }, + /* 15 << 80 */ + { { 0x3d1ab80c8ce59954l,0x742c5a9478222ac0l,0x3ddacbf894f878ddl, + 0xfc085117e7d54a99l }, + { 0xfb0f1dfa21e38ec2l,0x1c7b59cb16f4ff7fl,0x988752397ea888fel, + 0x705d270cb10dc889l }, + 0 }, + /* 16 << 80 */ + { { 0xe5aa692a87dec0e1l,0x010ded8df7b39d00l,0x7b1b80c854cfa0b5l, + 0x66beb876a0f8ea28l }, + { 0x50d7f5313476cd0el,0xa63d0e65b08d3949l,0x1a09eea953479fc6l, + 0x82ae9891f499e742l }, + 0 }, + /* 17 << 80 */ + { { 0xd7c89ba1e7d1cefdl,0xcb33553a9a91e03dl,0xa01caaff59f01e54l, + 0x4a71c141de07def7l }, + { 0xe1616a4034d467d1l,0x6f395ab2e8ba8817l,0xf781ea64e45869abl, + 0x8b9513bb7134f484l }, + 0 }, + /* 19 << 80 */ + { { 0x0b0ec9035948c135l,0xaee219539a990127l,0x9d15ba0eb185dda1l, + 0xd87bc2fb2c7d6802l }, + { 0x05a480307a82d7f8l,0x7b591ce4e7e11ec3l,0x14d4cc22a0e15fdbl, + 0xf2d4213576def955l }, + 0 }, + /* 21 << 80 */ + { { 0xd56d69e4117a5f59l,0xcae6008a01286e97l,0x716a0a282dab13b0l, + 0xc821da99b3a8d2d0l }, + { 0x6898b66239c305e6l,0xe42d3394c8b61142l,0x54c1d2b253b16712l, + 0x3cec3953a01f4be6l }, + 0 }, + /* 23 << 80 */ + { { 0x5bd1e3036951b85el,0x1a73f1fb164d79a4l,0x6e77abd39fb22bc3l, + 0x8ae4c181b3d18dfdl }, + { 0xdd4226f5a6a14ed1l,0x620e111feb4e1d92l,0xffce6e59edca4fe8l, + 0x39f5fc053d0a717dl }, + 0 }, + /* 25 << 80 */ + { { 0xef8fa78cd91aff44l,0x6f3f9749bdc03be7l,0x171545f8b8596075l, + 0xbe31a73e2af132cel }, + { 0x5b4e174123884e1dl,0x4373357ea9fa75f0l,0x8dba2731bc06f49el, + 0xa09aebc877fa6de8l }, + 0 }, + /* 27 << 80 */ + { { 0xd4974e518293e18cl,0x1e4cfc5331ec0e8fl,0x80b4258325d40b1el, + 0x5cfb73a2a85f7588l }, + { 0xe553efd204c0e00bl,0xdaa6750e9a48ac39l,0xf20936b00abda06al, + 0xbfd3c7e4bf85771cl }, + 0 }, + /* 28 << 80 */ + { { 0x72669c3c7292495cl,0xa627e2dd82786572l,0xbdbfce5cd39c3e3dl, + 0xba6164927feed3d6l }, + { 0x4eb5f513e77b7318l,0x133f2e834337c2e0l,0xdea20f07f408bec6l, + 0x848a8396e3c87655l }, + 0 }, + /* 29 << 80 */ + { { 0x3086643551138f2bl,0x1176d8e6108a36bal,0xd78b3b400d4d4b66l, + 0x99ddd9bd956dbff1l }, + { 0x91dfe72822f08e5fl,0x7fd8cfe6a081ac4el,0x8ebb278ed75285c2l, + 0x2335fe00ef457ac0l }, + 0 }, + /* 31 << 80 */ + { { 0xe9d79c50f058191al,0x6749c3b05d3183f8l,0x5edc2708dbfeb1ecl, + 0x2c18f93621275986l }, + { 0x3a093e1f0703389fl,0xdf065e4a3ef60f44l,0x6860e4df87e7c458l, + 0xdb22d96e8bfe4c7dl }, + 0 }, + /* 33 << 80 */ + { { 0xb7193811b48dad42l,0x23b9dca320ad0f0cl,0x55511ffb54efb61bl, + 0xac8ed94626f9ce42l }, + { 0xa42b4bc73fc4cbd9l,0x2a4670905c6f8e39l,0xb50040f87eb592del, + 0x6633f81bdc2541f3l }, + 0 }, + /* 34 << 80 */ + { { 0xc104e02ed2d6d9c2l,0xa4876e870302517al,0x0263c9b2912f5005l, + 0x902f364a3d89d268l }, + { 0x76070565bb20a5a8l,0xa3a8977452109e98l,0x51fbffec463aa476l, + 0xfa8519625daa1503l }, + 0 }, + /* 35 << 80 */ + { { 0xe449dd8f82a9a4f3l,0xa1a2f405797e6b36l,0x76913537787785e8l, + 0x0315a3cfe064481el }, + { 0xc02291ee83df11e2l,0x5b59a0e9bcd178f0l,0xd5e8d10ce6b4c63al, + 0x9eee599f3fc60a82l }, + 0 }, + /* 36 << 80 */ + { { 0x051e589759621468l,0xb92c06327293621el,0xee17ea647762e4f2l, + 0x412107a771abd28cl }, + { 0xa083d87bf02d65ebl,0xbd4a3f165594395el,0x1d5694337c8882f3l, + 0xc5eb10c55f9c63cfl }, + 0 }, + /* 37 << 80 */ + { { 0x4b196728c8e62c4el,0x03dbd04cb74a757cl,0xe960a65b8520f044l, + 0x9eda0f33f7937337l }, + { 0x06ff0b86b6dc7dfbl,0x3bd276c11fc1ac35l,0x0e67055b1b255c27l, + 0xe43ae552eff899f8l }, + 0 }, + /* 39 << 80 */ + { { 0xc64c914d3b156d76l,0x784c1f61d794345dl,0xcda0c77c365d7a50l, + 0xcc5a1e205b32dbd0l }, + { 0x2f4e78bff90b6ac0l,0xbead62f9a2d4862dl,0xa8f67e7dcc346b53l, + 0xa38d7ae947e59dbdl }, + 0 }, + /* 40 << 80 */ + { { 0x7dc1605d480aca4dl,0x08c37750ef263aabl,0xd5c6b7c93f166725l, + 0xf99982f30ff2853bl }, + { 0xc61b9583a8ecb64al,0x041211a91b771741l,0x50ba64154e156f97l, + 0xb6595ea871b8954el }, + 0 }, + /* 41 << 80 */ + { { 0x4ae760845eb3b4eel,0xcafefdc6c62ed274l,0x4eabeacf113f790bl, + 0x10c2cc88a5ff64c9l }, + { 0xe7b59f8a49965d80l,0xd04884b50df07712l,0x6316ac5ba5f7bab1l, + 0x388111d99e78a075l }, + 0 }, + /* 43 << 80 */ + { { 0x8d437128f24804efl,0x12a687dd7b71dd53l,0x8b8f71d96139a60el, + 0xb047fed42a095ec7l }, + { 0xef238041fba59ee8l,0x61b17fac64045514l,0x45b1cf4857afa184l, + 0x8592c50a4bff5fc5l }, + 0 }, + /* 44 << 80 */ + { { 0x2830592394b745dcl,0x53e9ec16b09cb993l,0x59d0b57f9a134ed1l, + 0x89d7b439c56ee0ebl }, + { 0xc3656539991e22a2l,0xd27a89372a345043l,0x55dd5341064038eel, + 0xc9ee3f0348cb42efl }, + 0 }, + /* 45 << 80 */ + { { 0x08518c631d56c1cbl,0x5650f79f31235521l,0x33fc08d648911017l, + 0xbb8b58538a0a33c8l }, + { 0xb54554f2f869a62al,0x67f8cf48222457e5l,0x46e13911f276cc0dl, + 0x4b3a2ad6943b389el }, + 0 }, + /* 46 << 80 */ + { { 0x0e72b816b11a4c9dl,0x919b2738e9028fa4l,0xab80e1117698a5d6l, + 0xcd7950f56cd49adal }, + { 0x0db75c908dfb13a5l,0x2178578770f12cebl,0xfab72d5243486ff6l, + 0x66d55d726a0673ebl }, + 0 }, + /* 47 << 80 */ + { { 0xe98014b922667519l,0x7fcab2b3a95da9c0l,0x9bdbccd8438d5060l, + 0xa72fff5455a726b6l }, + { 0x7ae032943a5e769bl,0xf7291e9b559a0734l,0x18ae4f182ce18eeel, + 0x88e49f7328b7b4f0l }, + 0 }, + /* 48 << 80 */ + { { 0x90fe7a1d214aeb18l,0x1506af3c741432f7l,0xbb5565f9e591a0c4l, + 0x10d41a77b44f1bc3l }, + { 0xa09d65e4a84bde96l,0x42f060d8f20a6a1cl,0x652a3bfdf27f9ce7l, + 0xb6bdb65c3b3d739fl }, + 0 }, + /* 49 << 80 */ + { { 0xc6a2923e60ef9d87l,0xac66cdd8c3a64f1cl,0x069292d26e0bb0ccl, + 0x9e491414451e52a0l }, + { 0x2e76cedf0e0d35b3l,0x311b7ae9af682b84l,0xaa1017a02f90b176l, + 0xac0b43a794feb6e8l }, + 0 }, + /* 51 << 80 */ + { { 0x7ddb42f9214e82f5l,0x91c88566f67269d7l,0x1763ed8cdd0ff422l, + 0x045dd690ad284ddfl }, + { 0x5713bbb141e48fe7l,0xdc5bef28f8eb580fl,0x4bd0b288ed2992c2l, + 0x436587faaf5ef2b3l }, + 0 }, + /* 52 << 80 */ + { { 0xbbc1a48d6e5822c4l,0x16c3135daacebd02l,0xd0c6c543b56157dfl, + 0xae249a0ef49f44a1l }, + { 0x1f2c23ce72c47341l,0x8f52dc2a25974313l,0x2c99bc0a958e0e6bl, + 0xe57eab6b950cd492l }, + 0 }, + /* 53 << 80 */ + { { 0xea66db638934efc0l,0x7bfe479193c6f7c7l,0x78438d535ef90d99l, + 0xe63b87c9c665736dl }, + { 0x6de32d82db49e1bbl,0xbfa877dcd0ad1648l,0xdb2e85de1197806dl, + 0x74e9dbd3cfee7854l }, + 0 }, + /* 55 << 80 */ + { { 0xd2c26e2edb6d7e0al,0x9103119a531009cdl,0xb5dc49869a8b9d54l, + 0x4781b83bb408b427l }, + { 0x70d98b2ccb4ba2f7l,0x112ed5d7fa8a36b8l,0x97257bc6fdde1675l, + 0xd2a9c711db211cb7l }, + 0 }, + /* 57 << 80 */ + { { 0xe4aa6a06ee79fe8cl,0x06e210233dff8a54l,0x63e11ac5bf50731al, + 0xb8b9944f544125b8l }, + { 0xcba92c41d359aeb0l,0xd201c893249bca36l,0xfe79bd77cb501216l, + 0x694b21488d525ba4l }, + 0 }, + /* 59 << 80 */ + { { 0x60c90e11ee3dde2al,0x7df08e17bb36c4a2l,0xb6c3210dcc5b3c17l, + 0xa814180955cec91cl }, + { 0xf4ecbc05a8193dffl,0xf43cdef8da5744fal,0x4895a6c6f12f8a2el, + 0x44282692eb7b910al }, + 0 }, + /* 60 << 80 */ + { { 0x1a405e1886d6e13al,0x6a18c91827a7c67cl,0xc34877ebe127bfd7l, + 0x3c9fab08c098e692l }, + { 0xfe2dc65bc2066586l,0xb107603a8f68a0a9l,0x74ef0ef8127cd340l, + 0xfe577b5b86788d87l }, + 0 }, + /* 61 << 80 */ + { { 0xdc7ff83c71234c81l,0xee48d9c6d868c82fl,0xb80bac5e37e4f365l, + 0x2bfbe94efcb951c2l }, + { 0x55829049a374d0b0l,0x2a502cada87a5fb4l,0x0742ac9d9ee840bal, + 0x7689bf53eecd05b1l }, + 0 }, + /* 63 << 80 */ + { { 0x0e7f459320059c22l,0x47c273e0e49368a2l,0x5ccb960ac6946ee2l, + 0xd8209ec48b3271b6l }, + { 0x7fd5142cdfb9e947l,0x46a89c83ff737ab1l,0xa45f6b0282d875ecl, + 0x19a16e0e34c296d6l }, + 0 }, + /* 64 << 80 */ + { { 0xeb5ddcb6ec7fae9fl,0x995f2714efb66e5al,0xdee95d8e69445d52l, + 0x1b6c2d4609e27620l }, + { 0x32621c318129d716l,0xb03909f10958c1aal,0x8c468ef91af4af63l, + 0x162c429ffba5cdf6l }, + 0 }, + /* 65 << 80 */ + { { 0x65c93be33607927bl,0x86feaaecdae5411dl,0x4a1686c6dd2e2c3dl, + 0xf78200068acdf51dl }, + { 0xf82c4d0239ed3e50l,0x5ac04047b4c3a4a4l,0xbdd14d7ec34b07a7l, + 0x9911d7027cc12db5l }, + 0 }, + /* 71 << 80 */ + { { 0x4ed5dbbd1751abc9l,0xaf374229a23cc54al,0x9b5fa66ea4ed3f9al, + 0xc56dd9613d380643l }, + { 0x7d77897144b38021l,0xdf4712d0d3584508l,0x0018e2eecd7ab168l, + 0xc8a3a166293d29a7l }, + 0 }, + /* 77 << 80 */ + { { 0x34681bdb3a5a0214l,0xe188d6f1f718797el,0xaa751de7db761c5fl, + 0x347c50324959a5cel }, + { 0x108705fc338be49cl,0x1dc5eada95abf7a8l,0xb863808f0fc3f0b7l, + 0x529c27c1a05c4d43l }, + 0 }, + /* 83 << 80 */ + { { 0xa75f90677f699f79l,0xd01cf9c866356f99l,0xf90f9b73fdfbaae7l, + 0xe0b5f4412c304d2fl }, + { 0x17cbfb11807f3f57l,0xe902d542af8a9eb4l,0x3335285461f89b4al, + 0x3a51c54d3628c0ael }, + 0 }, + /* 89 << 80 */ + { { 0xae5fd487c704212dl,0x82dd07a565e2e32cl,0x46d4c9646c19c199l, + 0xe7f428593778eedcl }, + { 0x084a4e9b6dcc5ec9l,0x757e04ba2d0538b7l,0x4ec0a573a3fba4cdl, + 0x2432a4e5c627c2fcl }, + 0 }, + /* 95 << 80 */ + { { 0xfde00b3094c8a424l,0x20a57d8cd224c232l,0xd6ace1a170019992l, + 0x1a648d40697e67a3l }, + { 0xed1fb10691338d84l,0x828004a08372bfc8l,0xb93030fefad3bfedl, + 0x883dea23f27369ecl }, + 0 }, + /* 101 << 80 */ + { { 0xfbbf36a62a710d73l,0x8db834024b3cc6bbl,0xa60c47cf16d7b1fcl, + 0xf9778fa6cd16ce8fl }, + { 0xd77023086d14a1a6l,0x01f139cb06e8247cl,0xd89af2979770b9c1l, + 0x94bf1ca97d9fb550l }, + 0 }, + /* 107 << 80 */ + { { 0xe17e2e6dc2d45f34l,0x5969d8ee26efc6cbl,0x6f175231b9219cfbl, + 0x027f333c189f1175l }, + { 0x5bc60fad54f6da49l,0xc52e09af8ae5c3f3l,0x6c0e3927ed07f46dl, + 0xbfd9e598f39cf16bl }, + 0 }, + /* 113 << 80 */ + { { 0x9dffd95b090aefb9l,0x26db7b73637224fel,0xb78a679e92e2aa0cl, + 0xfc7c824ffc8f895dl }, + { 0xdc8287e8e636b3a8l,0x6b3ccc0f28b7a639l,0x38e6e2cc653de56al, + 0x998cf6985392c3cal }, + 0 }, + /* 116 << 80 */ + { { 0xe68de79e57f0d6fal,0xe707b252ff9c06f7l,0x5613698a4a061697l, + 0xd83d6453b5390352l }, + { 0x59b007599867c708l,0xcfe24fd7b41ea7adl,0x4692abf3da5b7de6l, + 0xd99a6f3bf0c54e8fl }, + 0 }, + /* 119 << 80 */ + { { 0xe8ee870dea4addc3l,0x0d1fb29559841f3el,0xdc05b5581dba2f14l, + 0xb8bf38324e3f4600l }, + { 0x1a909e66fd57c48al,0xb65ca4c24e2d76dfl,0x0b27755ae7c60d89l, + 0x9fcfa75acb9003f6l }, + 0 }, + /* 125 << 80 */ + { { 0xbbbdf4c49e5325aal,0x6879fe11d0d1f281l,0x7a400f890633002el, + 0xc3633c779bb79ac9l }, + { 0x15a4cfae93ab9bc3l,0x379bbdea42594603l,0x7c61dfa257d2af3fl, + 0x20190537b51bfb62l }, + 0 }, + }, + { + /* 0 << 88 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 88 */ + { { 0xa80d1db6f79588c0l,0xfa52fc69b55768ccl,0x0b4df1ae7f54438al, + 0x0cadd1a7f9b46a4fl }, + { 0xb40ea6b31803dd6fl,0x488e4fa555eaae35l,0x9f047d55382e4e16l, + 0xc9b5b7e02f6e0c98l }, + 0 }, + /* 3 << 88 */ + { { 0x4b7d0e0683a7337bl,0x1e3416d4ffecf249l,0x24840eff66a2b71fl, + 0xd0d9a50ab37cc26dl }, + { 0xe21981506fe28ef7l,0x3cc5ef1623324c7fl,0x220f3455769b5263l, + 0xe2ade2f1a10bf475l }, + 0 }, + /* 4 << 88 */ + { { 0x9894344f3a29467al,0xde81e949c51eba6dl,0xdaea066ba5e5c2f2l, + 0x3fc8a61408c8c7b3l }, + { 0x7adff88f06d0de9fl,0xbbc11cf53b75ce0al,0x9fbb7accfbbc87d5l, + 0xa1458e267badfde2l }, + 0 }, + /* 5 << 88 */ + { { 0x03b6c8c7dacddb7dl,0x92ed50047e1edcadl,0xa0e46c2f54080633l, + 0xcd37663d46dec1cel }, + { 0x396984c5f365b7ccl,0x294e3a2ae79bb95dl,0x9aa17d7727b1d3c1l, + 0x3ffd3cfae49440f5l }, + 0 }, + /* 7 << 88 */ + { { 0x26679d11399f9cf3l,0x78e7a48e1e3c4394l,0x08722dea0d98daf1l, + 0x37e7ed5880030ea3l }, + { 0xf3731ad43c8aae72l,0x7878be95ac729695l,0x6a643affbbc28352l, + 0xef8b801b78759b61l }, + 0 }, + /* 9 << 88 */ + { { 0xdcdd3709b63afe75l,0xad9d7f0b3f1af8ffl,0xdd6a8045194f4beel, + 0x867724cc2f7d998cl }, + { 0xd51d0aa5837751bel,0x21d6754a959a0658l,0xd2212611695f7e58l, + 0xec4b93c2297363efl }, + 0 }, + /* 10 << 88 */ + { { 0x0ac1c5fab6ef26cfl,0xcd8ba0c5a39de8eel,0x11ba7537dd7796e0l, + 0x1215933476d58d6dl }, + { 0xf51eb76f529fda4cl,0x2fd9209ddedaa8a3l,0x555a675615efac65l, + 0xb784c9ca7fd42fe9l }, + 0 }, + /* 11 << 88 */ + { { 0x8165ec11b9d1a70fl,0x01347efc384f6cael,0xe95c01a0ab7aeca9l, + 0x459ba1c5c6c99530l }, + { 0x38967a635cf3416bl,0x5c3761fd1e5457e2l,0x43e6077af03e9df6l, + 0xb15d34628bd1c7f6l }, + 0 }, + /* 13 << 88 */ + { { 0xad87d3db35a75c49l,0xc69d800961af03c5l,0x31aef61a3a6a6c4cl, + 0xb3292640aa10a993l }, + { 0x959aae80aaee340fl,0xf900528e7f381a3bl,0x44ecf76e853691a3l, + 0xa081663ce749e68el }, + 0 }, + /* 15 << 88 */ + { { 0x4f2782136283e34al,0x6f9fcf60fbfa315fl,0x224a2ab99b701364l, + 0xb4b1b418f9fecadcl }, + { 0xbf7280fe50ba1b9al,0x7e68259c33f36db9l,0x8ccb754e154c9fb0l, + 0xf281adb1db2328f1l }, + 0 }, + /* 16 << 88 */ + { { 0xf92dda31be24319al,0x03f7d28be095a8e7l,0xa52fe84098782185l, + 0x276ddafe29c24dbcl }, + { 0x80cd54961d7a64ebl,0xe43608897f1dbe42l,0x2f81a8778438d2d5l, + 0x7e4d52a885169036l }, + 0 }, + /* 17 << 88 */ + { { 0xc2a950ad2d6608bel,0xab415e2a51c3c2b6l,0xffbd2a65f5c803e7l, + 0x3f81dc3eca908532l }, + { 0x0ec47397c28c04f4l,0xf6c632e8153f58e8l,0xccac35f8efb4a6d8l, + 0x22a1b677ee6d7407l }, + 0 }, + /* 19 << 88 */ + { { 0x276662435243c119l,0x79cb8580e707363el,0x5bf5ebf4d01682d6l, + 0x8a980173762811e0l }, + { 0xe2f2be1fc7547d77l,0x21a50fffb925fec6l,0x5e6cf2ef40115509l, + 0xb69beae18faa0fc0l }, + 0 }, + /* 21 << 88 */ + { { 0xfa147da8cec36e75l,0xba184e5a42860484l,0xe8ec25df222fb1e6l, + 0xce91dcb18ff8403cl }, + { 0xf1b0e27ead7faa32l,0x097d881d42a3a205l,0xa8865dd43f8f56d4l, + 0x624d7a451aef929dl }, + 0 }, + /* 23 << 88 */ + { { 0x3db0238ad01698e8l,0xbb7186dc00306082l,0x542f4377250f830el, + 0x34b8a67dae438c50l }, + { 0xada528a0858d8048l,0x561aa3336b57afc1l,0x8d9188e0fda35f7al, + 0x5838d1211dcad0c5l }, + 0 }, + /* 25 << 88 */ + { { 0x4f97d1529f17511dl,0x8b9f012776fdb9ebl,0x53a0a72d4056e6a7l, + 0x5ff937d64e262eeel }, + { 0xaa64a8dc489fbe6dl,0xc19947dfea02bc69l,0x76f0bbb91492c9bel, + 0xe53881098d89cd01l }, + 0 }, + /* 27 << 88 */ + { { 0x16083309456057b7l,0x2810c08040a331f6l,0x0561656c3c166929l, + 0x16f0d8d6ed1c3999l }, + { 0x37b6da7294697927l,0xd821c2cc23ca6c9cl,0x42ef1bdb8ca4351cl, + 0x7ca32bad5edfa682l }, + 0 }, + /* 28 << 88 */ + { { 0xdc1de17d98119f10l,0x74353c5d488c36a6l,0x14aaf33a3d8e23dfl, + 0x31e075c078baf593l }, + { 0x0f7ca03a46d1ca3cl,0x99c5e3ac47b660c7l,0x70d0241388fe2e59l, + 0x2e9a6be12a7ec005l }, + 0 }, + /* 29 << 88 */ + { { 0x4d1f087f184252b1l,0xfd3ace273f5b49c6l,0x6e874447bbb04da2l, + 0x2347e3a1b3767ff0l }, + { 0x990d4010f868966al,0x35320090dd658b5el,0x1105bfb974fe972al, + 0x3961f7dc8e7ad2c6l }, + 0 }, + /* 31 << 88 */ + { { 0x100d8b54741e3286l,0x65d9108ef3abc7afl,0x172b450620ef8fbcl, + 0x11bd7db2d81b8a2el }, + { 0xf89210e1e8e41de5l,0x910613f3d98a868bl,0xbfc85241849aa909l, + 0x68a43e21c7d3a7cal }, + 0 }, + /* 33 << 88 */ + { { 0x68f891479a4f8293l,0x48262328a5eb9101l,0x7eca2a178fe218b5l, + 0xde6c22dbc733f768l }, + { 0xde7171d108d6084dl,0xd153827a0f0f8092l,0xc7b52d8f85a9252fl, + 0xfa29ca3a5708b31fl }, + 0 }, + /* 34 << 88 */ + { { 0x20518ddf9e0ad7e7l,0x33d5d079e8d28b9bl,0x1149b393d13058b0l, + 0x708cc65586d4651dl }, + { 0xd7fefaa694207435l,0xce882c0d96312f8fl,0x2fd5cb2059d091a7l, + 0x4533a88a0e1ece94l }, + 0 }, + /* 35 << 88 */ + { { 0xceddd9b5a59c28bcl,0xaa4808f9572e2a5dl,0x38bc191999014a1el, + 0x1aacefdaa6d85686l }, + { 0xa59283d42a573fddl,0x84359db29c387594l,0x79994773dca3acc8l, + 0xe4323e7654cf7653l }, + 0 }, + /* 36 << 88 */ + { { 0xac449695241fbd6fl,0x67c9b170081c1223l,0x16868f21b56aac6fl, + 0x34bd8fa3f8bcb721l }, + { 0x06b6bd33b6691c76l,0x6c924766381a7973l,0x6a12444ca54078dbl, + 0xd02e91a96d1051ccl }, + 0 }, + /* 37 << 88 */ + { { 0x512f5fb35f30b344l,0xb13ade169d516885l,0x18812e9b2b468802l, + 0xf15d730e6b28979al }, + { 0x5015616f6889348bl,0xe0b02a0a96af0401l,0x3b02007b61204c89l, + 0x9ece2aa7432742a4l }, + 0 }, + /* 39 << 88 */ + { { 0xd5f7e09c7c1cc4a1l,0x313ac04218b2d854l,0xbc4fe2a04c253b10l, + 0x25a696a3c7080b5cl }, + { 0x6de3cb6aef811877l,0x4d242fecd15f9644l,0xb9bfa2480ee6a136l, + 0x8122679e9c8d181el }, + 0 }, + /* 40 << 88 */ + { { 0x37e5684744ddfa35l,0x9ccfc5c5dab3f747l,0x9ac1df3f1ee96cf4l, + 0x0c0571a13b480b8fl }, + { 0x2fbeb3d54b3a7b3cl,0x35c036695dcdbb99l,0x52a0f5dcb2415b3al, + 0xd57759b44413ed9al }, + 0 }, + /* 41 << 88 */ + { { 0xc2c7daec96a8d727l,0x8a11631a17f3abf9l,0x06aba65c0ae8940al, + 0xfca280c7873d3635l }, + { 0x57496889ddb72b87l,0xaa9a3359320793d4l,0x11b6864d43120741l, + 0x1877cd4e51527639l }, + 0 }, + /* 43 << 88 */ + { { 0x8b35ce4e6f43dfc6l,0x4114b2fe9a19f3bfl,0x8c4af8024ffa45cal, + 0xa3ab5f869328b847l }, + { 0x0986de3e555f30f0l,0xaae6e3eac8cb84c4l,0x2a7dcdbaa4ba01f7l, + 0xfa32efa729f5dc6cl }, + 0 }, + /* 44 << 88 */ + { { 0x077379c00b33d3f8l,0x421883c67064e409l,0x2d0873d76c29c8f6l, + 0xbfa433a3d274c0c8l }, + { 0x56dc778f23a5891el,0xd663bf6535e2de04l,0x488fdb485db517cel, + 0x00bba55e19b226c2l }, + 0 }, + /* 45 << 88 */ + { { 0x879b30ead7260d78l,0x04954ba2eac5201fl,0x3210c0e3ff2529d1l, + 0x0743823488b470b3l }, + { 0x8b618de48854cc0dl,0x98270d5e35b795eel,0x0e47d651aa33ca37l, + 0x77d75fda1e87d0cfl }, + 0 }, + /* 46 << 88 */ + { { 0x789dbe987803fbf9l,0x940589aa17ede316l,0x032902bd85a1988cl, + 0x43cbc0031c47f7f0l }, + { 0xc6ff73714709148fl,0x769957122d9b8a5el,0xb4520e462597b70el, + 0x00d19f39f67ff3b8l }, + 0 }, + /* 47 << 88 */ + { { 0xe2dfcef9b159f403l,0xe8e9e8d8855644afl,0x2796247163fa1068l, + 0x400e992a968a5400l }, + { 0xe2b9d29f56e563c1l,0xed66759c2885fabfl,0x788b6263750abdffl, + 0x30adb00d6cbbdcacl }, + 0 }, + /* 48 << 88 */ + { { 0x1fe647d83d30a2c5l,0x0857f77ef78a81dcl,0x11d5a334131a4a9bl, + 0xc0a94af929d393f5l }, + { 0xbc3a5c0bdaa6ec1al,0xba9fe49388d2d7edl,0xbb4335b4bb614797l, + 0x991c4d6872f83533l }, + 0 }, + /* 49 << 88 */ + { { 0x5548d3423fa17b28l,0x38587952823ee731l,0x8ee9b90a0a28bcd1l, + 0xcfc029bf6676917el }, + { 0x7e08306d2a212358l,0x66a9488dc88a66bcl,0x7a09db327d7c9e65l, + 0x20eaf4e72cbc1790l }, + 0 }, + /* 51 << 88 */ + { { 0xb3095b491f2a9605l,0x7cfc4205f72691c7l,0x1544bf964d889b90l, + 0xdc44d20ba0bbae7al }, + { 0xee369b670b1f0b23l,0xf3ec25e818a7bdcbl,0xf614ab5df47ecf65l, + 0x4869762f80a4a09dl }, + 0 }, + /* 52 << 88 */ + { { 0xedbbeee78a058fb6l,0xb9d19ddcfb09121al,0xa41bb45bd34dddcel, + 0x2dbc80b900964bc4l }, + { 0x4ed9137d1d6cb654l,0x1b9016db483d01c5l,0x5fc501bc6528e22el, + 0xb2d2f8816cad646bl }, + 0 }, + /* 53 << 88 */ + { { 0xb57aa72a89043e56l,0x8fbca2435c5319fdl,0xe66aef43b13ce900l, + 0x2c7c3927c3382934l }, + { 0x434d9104a835fdf5l,0x419470b81b3b85bel,0xeaec374abeb4d448l, + 0x26a53b51f33cda51l }, + 0 }, + /* 55 << 88 */ + { { 0x421f1725bb1db793l,0x20214d4f558c94a9l,0x3371233b7696092cl, + 0x774d3fcb1902ab0el }, + { 0x4ce223ded149aecel,0x174b260e33057bc7l,0xdf70cfa3f6effee4l, + 0x3d8cd01f80880678l }, + 0 }, + /* 57 << 88 */ + { { 0x32db21862e59985cl,0x448865abaa1b39e1l,0x250ce79cd89fe98dl, + 0x962710e763e3fb10l }, + { 0xa8fc70561ac10e3el,0x9eed208fa3b132fbl,0xf499d638937051f5l, + 0x27acf7ec21a9f78fl }, + 0 }, + /* 59 << 88 */ + { { 0x148e572a4c7b445el,0xdc10a0214dc95a4fl,0xe60e9c2e02237869l, + 0xbfdfcb3aa393c3a4l }, + { 0x8b799db211a64cf0l,0x1ca865ea2e16f59fl,0x865441fbd3a17e46l, + 0x23315b9753409692l }, + 0 }, + /* 60 << 88 */ + { { 0x5e76fb2f286bad39l,0xbad9efe39dcad1e2l,0x60e75190edc7e904l, + 0x6a6f063e0fecb5a5l }, + { 0x5150ed85aed8acc3l,0xb56ccfbc6d20af6cl,0x7e0d1e982c69dbfal, + 0xabf5628a7c7e10a9l }, + 0 }, + /* 61 << 88 */ + { { 0xb84af2c00df6d61fl,0x02c651c52acbaf4bl,0xfb605754afaaa0bfl, + 0xa03f5257dff61017l }, + { 0x9e3ffb1672762093l,0x4f9a5da0c4f40bd3l,0x37dce5220d26f8e1l, + 0x260f736fc06a1a07l }, + 0 }, + /* 63 << 88 */ + { { 0xb92aba79b1077d55l,0xc52f81081a42f5f5l,0x9913f04f86e5aa99l, + 0x6814b0b1f3c7f504l }, + { 0xb7d61fd34d354bdal,0xf27926e39581d25el,0x97724001c2dc21adl, + 0x835778231d5c4788l }, + 0 }, + /* 64 << 88 */ + { { 0x77b868cee978a1d3l,0xe3a68b337ab92d04l,0x5102979487a5b862l, + 0x5f0606c33a61d41dl }, + { 0x2814be276f9326f1l,0x2f521c14c6fe3c2el,0x17464d7dacdf7351l, + 0x10f5f9d3777f7e44l }, + 0 }, + /* 65 << 88 */ + { { 0x53857462ff9727a2l,0xe6870e7dc68488e7l,0x276da72808c79656l, + 0x1308eb61d86c24ebl }, + { 0x34c43a84db0a3e56l,0x03961b5525335a59l,0xf9bc2d5805689d86l, + 0xfa4d3c01eb29d6d6l }, + 0 }, + /* 71 << 88 */ + { { 0xd07dac3037d10ffal,0xb2b0a0fd8bef0a79l,0xa2e804510ec02505l, + 0xf256c18962f55f5fl }, + { 0x0ca3f9b10b39f4f0l,0x7bf4e1cf3bb7c8e9l,0x7a8a43f8ee11f227l, + 0x2ad8431a3e4056ebl }, + 0 }, + /* 77 << 88 */ + { { 0xb8cf71ed031c1871l,0x702431806f703102l,0x9a87e1c24ec6f1b0l, + 0xf7e6e5b4664f275dl }, + { 0xc70a8b4e8c76b505l,0x6ba69bf2a002e9cfl,0x33ed74f7a0d8c9bfl, + 0x17f5f4b18d9989del }, + 0 }, + /* 83 << 88 */ + { { 0xcd116dcb1b13a4a1l,0x591adb831c369877l,0x697be1aca6b8e80bl, + 0xb2d4baa1b975d781l }, + { 0xd4a9a496b16b48e7l,0x64de2d7af293997dl,0x039ae039af09a492l, + 0x66e31a2665f3a485l }, + 0 }, + /* 89 << 88 */ + { { 0x110a8a42fec01a53l,0x1f5fcc1b38affab8l,0x757310ca9941a19el, + 0x11ef95f76c29d6cbl }, + { 0x0756bdb22dd427bal,0x8de8d44af3e16c33l,0xf9d28355e25aec52l, + 0xeb761efc02f36465l }, + 0 }, + /* 95 << 88 */ + { { 0xfc83bf7454bfcd7al,0x51d861794837b6bel,0x8165b3f9801a324dl, + 0x3a5972bc634cfd61l }, + { 0xeecfe6d825258ed6l,0x51d968df1451ced0l,0x3010cdb8316aa0ael, + 0xc295b8522900eaf2l }, + 0 }, + /* 101 << 88 */ + { { 0x5ad434a3890cc798l,0x4c17ff5e1531bce4l,0x825b5b5a5ea8e26fl, + 0xacca9d5dd66fd7b3l }, + { 0xb647dbde37ae6f92l,0xa5594868f3600416l,0x7b90ac53ab0c5d63l, + 0x4b66ad7ceb43e1d0l }, + 0 }, + /* 107 << 88 */ + { { 0x04a211fac09ccbffl,0x9c96ad9ee873d898l,0x9eb1deb69c481f86l, + 0xb3616ce8b2d70298l }, + { 0x67a6fe9b9073726dl,0x5b8aa37d4c9bf744l,0xf558603ebb6aa0efl, + 0x72767f5103d304fbl }, + 0 }, + /* 113 << 88 */ + { { 0x787cb8b8d6e9b7e3l,0x8bb30222e079fc68l,0x651a2ea6e3145a0bl, + 0x0254c5da9ab18fa8l }, + { 0x83722ffc12e1611fl,0xb0ddf1ffa7cc61bel,0x7c9c7e10ac0ac8d7l, + 0x8241a8191da12218l }, + 0 }, + /* 116 << 88 */ + { { 0x70bb7719bc407e6el,0x231328efd84ceb41l,0x8bca6a1fc104bb20l, + 0xd6f4e425280b9071l }, + { 0xb41b95a292896a82l,0x735cf435fa34df67l,0xbc331a08d9d6d769l, + 0x579786052682747el }, + 0 }, + /* 119 << 88 */ + { { 0x048ba499eb3af9a9l,0x43a8c367d50b82cel,0xedf9e2b21e0724d9l, + 0x3098aab3d607140bl }, + { 0xd1f18f1e5ed49eb9l,0xf9c6bb6ae0bb02a2l,0x204f96aa0cd245ddl, + 0xdaadaf4afb011ed5l }, + 0 }, + /* 125 << 88 */ + { { 0xb298ce2de50404b1l,0x04dd38c45bf9b581l,0x229deabdfada51e8l, + 0x74bd233f8788a132l }, + { 0x951ba5ecf03e6c30l,0x9da2f5aa45bf1a41l,0x6bec7fea7e52b860l, + 0x76e3778964b0a9ddl }, + 0 }, + }, + { + /* 0 << 96 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 96 */ + { { 0x4fe7ee31b0e63d34l,0xf4600572a9e54fabl,0xc0493334d5e7b5a4l, + 0x8589fb9206d54831l }, + { 0xaa70f5cc6583553al,0x0879094ae25649e5l,0xcc90450710044652l, + 0xebb0696d02541c4fl }, + 0 }, + /* 3 << 96 */ + { { 0xb99f0e0399375235l,0x7614c847b9917970l,0xfec93ce9524ec067l, + 0xe40e7bf89b122520l }, + { 0xb5670631ee4c4774l,0x6f03847a3b04914cl,0xc96e9429dc9dd226l, + 0x43489b6c8c57c1f8l }, + 0 }, + /* 4 << 96 */ + { { 0x0e299d23fe67ba66l,0x9145076093cf2f34l,0xf45b5ea997fcf913l, + 0x5be008438bd7dddal }, + { 0x358c3e05d53ff04dl,0xbf7ccdc35de91ef7l,0xad684dbfb69ec1a0l, + 0x367e7cf2801fd997l }, + 0 }, + /* 5 << 96 */ + { { 0x46ffd227cc2338fbl,0x89ff6fa990e26153l,0xbe570779331a0076l, + 0x43d241c506e1f3afl }, + { 0xfdcdb97dde9b62a3l,0x6a06e984a0ae30eal,0xc9bf16804fbddf7dl, + 0x170471a2d36163c4l }, + 0 }, + /* 7 << 96 */ + { { 0x361619e455950cc3l,0xc71d665c56b66bb8l,0xea034b34afac6d84l, + 0xa987f832e5e4c7e3l }, + { 0xa07427727a79a6a7l,0x56e5d017e26d6c23l,0x7e50b97638167e10l, + 0xaa6c81efe88aa84el }, + 0 }, + /* 9 << 96 */ + { { 0x473959d74d325bbfl,0x2a61beec8d6114b9l,0x25672a94924be2eel, + 0xa48595dbf2c23d0cl }, + { 0xe476848b6a221838l,0xe743e69a35c1b673l,0x2ab42499d8468503l, + 0x62aa0054e9e90ba7l }, + 0 }, + /* 10 << 96 */ + { { 0x358d13f1bc482911l,0x685d1971b7fa7f26l,0x3e67a51d2be1aee4l, + 0xe041850998d114a9l }, + { 0x59639f604e052561l,0x32075c49155d0818l,0x2aa2343b67b64b1cl, + 0x1b445e2967f53e6al }, + 0 }, + /* 11 << 96 */ + { { 0xbdfb271773a904e0l,0x7ce1e40b28888d73l,0x2e7e35f6eaa97d1bl, + 0xd061772aa9afa097l }, + { 0x434ac7c47a1f7c59l,0x6e21124ae79b7b9al,0x055acff3bb22ecc7l, + 0x8bfd7ac984c858d3l }, + 0 }, + /* 13 << 96 */ + { { 0x2fd57df59f1f68adl,0x5ddcc6dbb06470c8l,0x801b6451a9b47307l, + 0x6b51c8e376551bf4l }, + { 0xef0bd1f7d44e1da9l,0x714bcb1d4d4e600cl,0xc57bb9e40c6540c7l, + 0x71bd1ec2327cc644l }, + 0 }, + /* 15 << 96 */ + { { 0x9a52cf7e7f4dd81fl,0xa0132be15e69c05el,0x90dab7472a0f4d72l, + 0xc142f911312d6706l }, + { 0xe8d3631f8261998bl,0xf0f42fae615c1c94l,0x2f4e948caec3fa5dl, + 0x242ae7a8a374101el }, + 0 }, + /* 16 << 96 */ + { { 0x0f893a5dc8de610bl,0xe8c515fb67e223cel,0x7774bfa64ead6dc5l, + 0x89d20f95925c728fl }, + { 0x7a1e0966098583cel,0xa2eedb9493f2a7d7l,0x1b2820974c304d4al, + 0x0842e3dac077282dl }, + 0 }, + /* 17 << 96 */ + { { 0x1fa878cad088be52l,0x89c2cb07a9e1e656l,0x385bc5c3219d62dbl, + 0xd82b676b5fda2752l }, + { 0x2449dc9ee304eafcl,0x1e9e7991632f4ea2l,0x3036e061cdd5e0b9l, + 0x75a6f6ff830825bcl }, + 0 }, + /* 19 << 96 */ + { { 0xb10fcddc449dedb4l,0x2c890042d1244acfl,0x9b3072cac7fc7017l, + 0x1acda6859ce8063fl }, + { 0xd243313c7f51e2f5l,0x52a3f1a4d73d9578l,0xda785b7a64f0ce6el, + 0x2e766315442a4c2dl }, + 0 }, + /* 21 << 96 */ + { { 0x94f9b004151f111al,0xc7a5035b07dbc5fal,0x53958ea7609e49d7l, + 0x0526b4d79013f4c0l }, + { 0x66de5ebb593e2fbdl,0x6e7cf8b44c2e0c37l,0x6f72fc8b8c983e78l, + 0x6fab9b632348f9d7l }, + 0 }, + /* 23 << 96 */ + { { 0xc748a3526a3d8468l,0x3fab479927e38032l,0x91ad3629fa430ce7l, + 0xc5af0b2c71614c44l }, + { 0xcede3fa50c211611l,0x6e6889ba02338083l,0xee0a195977f0fe32l, + 0x01ea905d0f4bbc5al }, + 0 }, + /* 25 << 96 */ + { { 0x12cfb25e8193db48l,0xddb4ae633bea708cl,0xdaae102ef181f821l, + 0x9d9d923024a089d9l }, + { 0x71c4122da0876aeal,0x1a63ea3bbbe19c09l,0x3b898076016f8d0cl, + 0xa5cccc5daea6b713l }, + 0 }, + /* 27 << 96 */ + { { 0xc3f22baf4a8e2f61l,0x77d29ede176da6a6l,0x40a55f211607da63l, + 0x858b38561452e391l }, + { 0x0dd3c267fe1b3c56l,0x66c04bdd7d55227al,0xfbd2fe55e6404e09l, + 0x5981cf49ea9cfcbcl }, + 0 }, + /* 28 << 96 */ + { { 0xe549237f78890732l,0xc443bef953fcb4d9l,0x9884d8a6eb3480d6l, + 0x8a35b6a13048b186l }, + { 0xb4e4471665e9a90al,0x45bf380d653006c0l,0x8f3f820d4fe9ae3bl, + 0x244a35a0979a3b71l }, + 0 }, + /* 29 << 96 */ + { { 0xae46a902aea870afl,0xa9b9fcf57cbedc99l,0x74f2ca3f79b7e793l, + 0xadb8f2231dbeeb28l }, + { 0x6302060e6764df85l,0x363320d257ebd554l,0xd9fd573e798d22e1l, + 0x285f85f5ebb67dedl }, + 0 }, + /* 31 << 96 */ + { { 0xd86b329211caa2b5l,0x2a26258e39337bd1l,0x4dc5a9b579c8c291l, + 0x16443d87741942e6l }, + { 0x6bc9a2f8f811400cl,0x819c69359eeb4e0el,0xe1be7273ce0c214bl, + 0x429afb8184b61581l }, + 0 }, + /* 33 << 96 */ + { { 0xb37e188756af5812l,0xd662bdb485aff83el,0xc89742d07bc63de7l, + 0xea103f9d0279f487l }, + { 0x4d26916a3a6cc639l,0x4eea3a3c7c743b94l,0x6a3e0dc7007376d9l, + 0xdb6ef3cf573f904el }, + 0 }, + /* 34 << 96 */ + { { 0x9b1058ecb0b0fb53l,0x8955f5f75f8a9a9fl,0xf5f92e7f9f6f9e6dl, + 0x03f5df6c50ec198bl }, + { 0x6c8741f2b8aedbcel,0x8f4e60cfed8018f7l,0x6ca5297c9fa01f89l, + 0x8591cf7a864995dbl }, + 0 }, + /* 35 << 96 */ + { { 0xa126147eb0a11b9bl,0xeedcc9e198900232l,0x15d94f8c2bead119l, + 0x042423cfefc38691l }, + { 0x6ce86fbe77165d91l,0xa07732126b3fd565l,0x8cdc409150b1f9c7l, + 0x7f5ad1af064595acl }, + 0 }, + /* 36 << 96 */ + { { 0xed374a6658926dddl,0x138b2d49908015b8l,0x886c6579de1f7ab8l, + 0x888b9aa0c3020b7al }, + { 0xd3ec034e3a96e355l,0xba65b0b8f30fbe9al,0x064c8e50ff21367al, + 0x1f508ea40b04b46el }, + 0 }, + /* 37 << 96 */ + { { 0x73644c158f8402a0l,0x0d9b5354f4730eb9l,0x78542af4e94cc278l, + 0xf4dbede3e395f33al }, + { 0x8fe8cbc590c70b00l,0x9c35bb2d7db197f6l,0x229b4973e6599746l, + 0x0817d04e1a84b986l }, + 0 }, + /* 39 << 96 */ + { { 0x8ffe34e95ecd09b3l,0x6a7c3de4153b7cael,0xf02713e4a81044b7l, + 0x85ca6158c70545c8l }, + { 0xd3ff392845d88bffl,0x3a251a07f0bafe89l,0x61290e1287cea7f4l, + 0xa360a17efa4808adl }, + 0 }, + /* 40 << 96 */ + { { 0x98561a49747c866cl,0xbbb1e5fe0518a062l,0x20ff4e8becdc3608l, + 0x7f55cded20184027l }, + { 0x8d73ec95f38c85f0l,0x5b589fdf8bc3b8c3l,0xbe95dd980f12b66fl, + 0xf5bd1a090e338e01l }, + 0 }, + /* 41 << 96 */ + { { 0x2d1751083edf4e2bl,0x30e6e90fa29c10d0l,0xfee1eb14c9c6ccd2l, + 0x244670c756a81453l }, + { 0x90b33eefc5185c22l,0xd77ae4b63db82d28l,0xce5ee034f228f940l, + 0x5d7660847bb47be5l }, + 0 }, + /* 43 << 96 */ + { { 0x88b7eec499b9a8c6l,0x56048d9e14e8ef0cl,0xa18f93215c89cf78l, + 0xbd2087616d327e66l }, + { 0x5b187225d9e53e27l,0xa57ca6c7bf4d0317l,0x187731d2e9557736l, + 0xd4ce2f78a874982el }, + 0 }, + /* 44 << 96 */ + { { 0x65163ae55e915918l,0x6158d6d986f8a46bl,0x8466b538eeebf99cl, + 0xca8761f6bca477efl }, + { 0xaf3449c29ebbc601l,0xef3b0f41e0c3ae2fl,0xaa6c577d5de63752l, + 0xe916660164682a51l }, + 0 }, + /* 45 << 96 */ + { { 0xf5b602bb29f47deal,0x42853c9659ddd679l,0x5c25be4041d7c001l, + 0x8e069399d4a3b307l }, + { 0x1782152e736ce467l,0x2e264109c9cb4f08l,0xf900cb11ab124698l, + 0x1bbed1d02d6e05b1l }, + 0 }, + /* 46 << 96 */ + { { 0x9cc3fedc7da08b1fl,0x0f44949361d5ed38l,0xc8cbc4209b991b6bl, + 0xee62a342891c42e1l }, + { 0x11c496bb1a179139l,0x94ece2892eac4d8el,0x35f303a5a98d5570l, + 0x69d4340514a31552l }, + 0 }, + /* 47 << 96 */ + { { 0x29d45e50892dfcbal,0x653e613e5c30cee3l,0x7b8c1ae61868a348l, + 0x40ab51654f2c612al }, + { 0x56e977f9891cdc8cl,0xee1ca12a34ca7cd1l,0xa4e283ee17b5ddf8l, + 0x4e36f2fb6f536205l }, + 0 }, + /* 48 << 96 */ + { { 0x5a3097befc15aa1el,0x40d12548b54b0745l,0x5bad4706519a5f12l, + 0xed03f717a439dee6l }, + { 0x0794bb6c4a02c499l,0xf725083dcffe71d2l,0x2cad75190f3adcafl, + 0x7f68ea1c43729310l }, + 0 }, + /* 49 << 96 */ + { { 0xa3834d85e89ea13fl,0x2ca00f942db803bbl,0x0f378681400ed3dal, + 0x1028af6b54854da3l }, + { 0x3928c2da06400c7fl,0x21119785d82aac92l,0x06618c17724e4af0l, + 0x22b42b161470736bl }, + 0 }, + /* 51 << 96 */ + { { 0x7d0cfd48f7f2ac65l,0x46e1ac705f641b60l,0x0ab9566a0fcf0137l, + 0xbd4380e0db460fb8l }, + { 0x4550efbf6db99b55l,0x33846e669764b744l,0xacffa0cae34ca007l, + 0xce642d6a077e646cl }, + 0 }, + /* 52 << 96 */ + { { 0xe747c8c7b7ffd977l,0xec104c3580761a22l,0x8395ebaf5a3ffb83l, + 0xfb3261f4e4b63db7l }, + { 0x53544960d883e544l,0x13520d708cc2eeb8l,0x08f6337bd3d65f99l, + 0x83997db2781cf95bl }, + 0 }, + /* 53 << 96 */ + { { 0xd89112c47d8037a3l,0xcba48ad3464c2025l,0x3afea8399814a09dl, + 0x69e52260269030b5l }, + { 0x5b7067365c674805l,0x8c3fd33d87343f56l,0xc572c858b1c61edfl, + 0x43d8f4ded06749cbl }, + 0 }, + /* 55 << 96 */ + { { 0x04da1f06b4066003l,0xf7d4e52f372749e8l,0x56cd667114b38747l, + 0x1943a22a22eb6d9el }, + { 0xc2c5391990714b0al,0xb6e3abb7d13cf3ael,0xfcd8d671676115cbl, + 0x178ce1a0c06a0d3al }, + 0 }, + /* 57 << 96 */ + { { 0x94485b36913508f8l,0x92f87fe36de83b42l,0xedd476f0ed77e666l, + 0xee90fbc68da2cf53l }, + { 0x6f4afc53fc6cf3d9l,0x231bceb9f21f6ecfl,0x6504a11d494c6e9cl, + 0xd3728f032c211461l }, + 0 }, + /* 59 << 96 */ + { { 0x09a9b93799562ca2l,0xb7d5c5cf6a5a5aa8l,0x52f5d7b9987b219dl, + 0x33849f9ec38014d4l }, + { 0x299adaf628f23880l,0x738ecc8874875588l,0x39d707adca2af665l, + 0xc8c11f688f4c5f73l }, + 0 }, + /* 60 << 96 */ + { { 0x68e4f15e9afdfb3cl,0x49a561435bdfb6dfl,0xa9bc1bd45f823d97l, + 0xbceb5970ea111c2al }, + { 0x366b455fb269bbc4l,0x7cd85e1ee9bc5d62l,0xc743c41c4f18b086l, + 0xa4b4099095294fb9l }, + 0 }, + /* 61 << 96 */ + { { 0x2ae046d66aa34757l,0x34db1addaa6d7e9dl,0x2b4b7e017ccf432bl, + 0xfbe0bfa590d319c6l }, + { 0xfb2981687ec7a7f2l,0x346cc46004f5132el,0x782b2e53b40aceddl, + 0x402e1d64e3f0b8b9l }, + 0 }, + /* 63 << 96 */ + { { 0x2aa3b21d25a56088l,0xae6ee57543d08962l,0x669e42bff1e22297l, + 0x7b4c635732e3a47al }, + { 0x22b16260ea464a25l,0xad8ca59072d5cd7al,0x7c244266104eb96al, + 0x1def95e28e7c11d2l }, + 0 }, + /* 64 << 96 */ + { { 0x9c7c581d26ee8382l,0xcf17dcc5359d638el,0xee8273abb728ae3dl, + 0x1d112926f821f047l }, + { 0x1149847750491a74l,0x687fa761fde0dfb9l,0x2c2580227ea435abl, + 0x6b8bdb9491ce7e3fl }, + 0 }, + /* 65 << 96 */ + { { 0x1f04524cdc27e1f7l,0xa0c74f61572eab14l,0xdd5d0cfced272074l, + 0x95533c1d5bfe4f65l }, + { 0x3039d57ecce817cal,0x029967d73b822082l,0x9fca43866c4a10d3l, + 0xf8b2a7f0bb4968ebl }, + 0 }, + /* 71 << 96 */ + { { 0x933cd6dcbfbf6407l,0xd08f21504be673f8l,0x0e1c4d0db1140a2el, + 0x0502a092431b270al }, + { 0x5d99f9508768c00al,0xda3ce5079b3ff3c7l,0x1c648b75031c11abl, + 0x5e3de47bf2776305l }, + 0 }, + /* 77 << 96 */ + { { 0xe22af9274d2b9de4l,0xf3690f55a69609ecl,0x20260a6e453fbe18l, + 0x8edcb46b42d0b085l }, + { 0xd4ef250b7d9c7f58l,0x5e8578dfc83c3433l,0x9751d9b9e46e320al, + 0xb02bd03cf3c58af6l }, + 0 }, + /* 83 << 96 */ + { { 0x0ab299ede1b4d1ccl,0x22e7301cec4d18d2l,0xf2380f2a7b86d4ffl, + 0xca19ef9e40753713l }, + { 0x52bb0d24678c38a1l,0xcc9d6fd499001c02l,0xa2dd6b00bc5876e4l, + 0xfe04b402409fe2b3l }, + 0 }, + /* 89 << 96 */ + { { 0x7db986b1ff69f8d3l,0x648865e59d6266b9l,0x7ccfe96183f7dae5l, + 0x0f59a8bd6828379bl }, + { 0xad97e5ef0ac7c4e8l,0xa75914be784e9c18l,0x053e015bb18c1bb8l, + 0x18f6cefcb347043el }, + 0 }, + /* 95 << 96 */ + { { 0xb4d641bdf257c38al,0xadcea4d0c1372574l,0x7f8d20be71c8f0d0l, + 0x14a1d24c41dc6344l }, + { 0xe446054e41f35526l,0x4664213823c952ddl,0xfbde483401f6b0acl, + 0xc89eee66d75b6318l }, + 0 }, + /* 101 << 96 */ + { { 0x700242937a087392l,0xd42bd3aad5da04del,0xee64cb5b1f803414l, + 0xd6341ecbbab52988l }, + { 0x7ad522f343170a74l,0x5fba22536d61d9del,0x230304c1e845a6e5l, + 0xd69feabfbc9e326bl }, + 0 }, + /* 107 << 96 */ + { { 0xef7e49412e8a11d7l,0x4cb8963662c8bae1l,0xecc741198aad5816l, + 0x13490782c7af5175l }, + { 0x10c701f73e91a604l,0xcb8c6c7124cc30c1l,0xce0d479c071eb382l, + 0xa3dc71fb058087d4l }, + 0 }, + /* 113 << 96 */ + { { 0xec368492541eb6d1l,0x567735d6e09a94abl,0xb8039ec172350329l, + 0x3bd83a8f4894ddafl }, + { 0x740ef2a39c07063dl,0xba25e72277da7b59l,0xb09e248e3bf42e82l, + 0x7ff36da0b017d037l }, + 0 }, + /* 116 << 96 */ + { { 0xca80416651b8d9a3l,0x42531bc90ffb0db1l,0x72ce4718aa82e7cel, + 0x6e199913df574741l }, + { 0xd5f1b13dd5d36946l,0x8255dc65f68f0194l,0xdc9df4cd8710d230l, + 0x3453c20f138c1988l }, + 0 }, + /* 119 << 96 */ + { { 0x913f23b9ed08ac04l,0x18e336643590d098l,0xd3f72934e67536dcl, + 0xf949a757ec7ecde9l }, + { 0x37fc6583cf9cbd37l,0xcbe62cc043b1228el,0x777124948a743274l, + 0x3ea3668c716ce6f1l }, + 0 }, + /* 125 << 96 */ + { { 0xc89ce010a90d375bl,0x39ac669340503fe3l,0x9036f782d33ecb0el, + 0x5190656841fdc7d1l }, + { 0xbefd136e917d94cdl,0x05fea2f22a511b24l,0x80e62d76f9076e0cl, + 0x8c57635e418ba653l }, + 0 }, + }, + { + /* 0 << 104 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 104 */ + { { 0x20d3c982cf7d62d2l,0x1f36e29d23ba8150l,0x48ae0bf092763f9el, + 0x7a527e6b1d3a7007l }, + { 0xb4a89097581a85e3l,0x1f1a520fdc158be5l,0xf98db37d167d726el, + 0x8802786e1113e862l }, + 0 }, + /* 3 << 104 */ + { { 0xf6e894d1f4c6b6ecl,0x526b082718b3cd9bl,0x73f952a812117fbfl, + 0x2be864b011945bf5l }, + { 0x86f18ea542099b64l,0x2770b28a07548ce2l,0x97390f28295c1c9cl, + 0x672e6a43cb5206c3l }, + 0 }, + /* 4 << 104 */ + { { 0xc37c7dd0c55c4496l,0xa6a9635725bbabd2l,0x5b7e63f2add7f363l, + 0x9dce37822e73f1dfl }, + { 0xe1e5a16ab2b91f71l,0xe44898235ba0163cl,0xf2759c32f6e515adl, + 0xa5e2f1f88615eecfl }, + 0 }, + /* 5 << 104 */ + { { 0xcacce2c847c64367l,0x6a496b9f45af4ec0l,0x2a0836f36034042cl, + 0x14a1f3900b6c62eal }, + { 0xe7fa93633ef1f540l,0xd323b30a72a76d93l,0xffeec8b50feae451l, + 0x4eafc172bd04ef87l }, + 0 }, + /* 7 << 104 */ + { { 0xe4435a51b3e59b89l,0x136139554133a1c9l,0x87f46973440bee59l, + 0x714710f800c401e4l }, + { 0xc0cf4bced6c446c9l,0xe0aa7fd66c4d5368l,0xde5d811afc68fc37l, + 0x61febd72b7c2a057l }, + 0 }, + /* 9 << 104 */ + { { 0x27375fe665f837e2l,0x93f8c68bd882179fl,0x584feadc59b16187l, + 0xe5b50be9483bc162l }, + { 0x7ad9d6f1a2776625l,0xe9d1008004ff457bl,0x5b56d322677618a6l, + 0x036694eae3e68673l }, + 0 }, + /* 10 << 104 */ + { { 0x6ca4f87e822e37bel,0x73f237b4253bda4el,0xf747f3a241190aebl, + 0xf06fa36f804cf284l }, + { 0x0a6bbb6efc621c12l,0x5d624b6440b80ec6l,0x4b0724257ba556f3l, + 0x7fa0c3543e2d20a8l }, + 0 }, + /* 11 << 104 */ + { { 0x6feaffc51d8a4fd1l,0x59663b205f1ad208l,0xefc93cef24acb46al, + 0x54929de05967118cl }, + { 0x885708009acffb1cl,0x492bbf2b145639ecl,0x71f495a638f0018el, + 0xe24365dbc2792847l }, + 0 }, + /* 13 << 104 */ + { { 0x4bedae86a6f29002l,0x7abedb56e034457al,0x8bf3eec6179bff2al, + 0x9d626d57390f4e6bl }, + { 0x653fe0e914dd6ea3l,0x7483715989bd6d08l,0x85fb05b4ebd9b03dl, + 0x7dc3f2214a768bbcl }, + 0 }, + /* 15 << 104 */ + { { 0xaacc63f132b0ed8fl,0x041237242bafefd2l,0x0df9a7987e2d2a13l, + 0x09bd13cf9c27591fl }, + { 0xaa5f5e476e1afb50l,0xcd146a42b66eb646l,0x3f07561d1442ec3cl, + 0x7e5471738ae8ec47l }, + 0 }, + /* 16 << 104 */ + { { 0x8de2b7bc453cadd6l,0x203900a7bc0bc1f8l,0xbcd86e47a6abd3afl, + 0x911cac128502effbl }, + { 0x2d550242ec965469l,0x0e9f769229e0017el,0x633f078f65979885l, + 0xfb87d4494cf751efl }, + 0 }, + /* 17 << 104 */ + { { 0x2c3e61196c0c6cd5l,0x5e01a49a99f4aac8l,0xfa518fc92ef1565el, + 0xf64ff8714f772366l }, + { 0x52fcbc2b726420d0l,0x30fbf6eb76cfa9eel,0x0bd17139fa618268l, + 0x23ed6e122087535dl }, + 0 }, + /* 19 << 104 */ + { { 0x76098e38bb4ccb2cl,0x44e88aeeafbad6d1l,0x5c4d286771928778l, + 0xb1df868138534c94l }, + { 0x67eb8f4d77ce9debl,0x2a86d0461a77c55dl,0xc327181e46a6a3e7l, + 0x68fd611b8710e206l }, + 0 }, + /* 21 << 104 */ + { { 0xc093f3fc0c82bdf1l,0x21db25894f76c4a6l,0xf3dcb22ee410a7ael, + 0x1db37114f3c22ffel }, + { 0x9bd0a1fb58f6801dl,0x2cab103bd1b55cc8l,0x2ae1a7f5077ba4b2l, + 0x82b46642ce5ab2b3l }, + 0 }, + /* 23 << 104 */ + { { 0xc8477ec52546684cl,0xe3f9387702ff02b5l,0xefb72133ae5d04cdl, + 0x644905c339f10d02l }, + { 0x1750c87c13d8d356l,0x0e9b8063b41e7640l,0xc7ece04f5647b05bl, + 0x89a43da7ca9df9c4l }, + 0 }, + /* 25 << 104 */ + { { 0x02610ef1920eb7d9l,0x34bd2fc2e1ea1dc0l,0xcb89da255170b890l, + 0xaaa2796461cff827l }, + { 0xc308c9d37103ed6al,0xe82d63d5a467564al,0x94c897c4a0fa7732l, + 0x75eb52fa64c7aa5fl }, + 0 }, + /* 27 << 104 */ + { { 0x52582f9cb985fcb6l,0xaaef8d9f8508a691l,0x494c2c346e505131l, + 0x6d062362d55f30f6l }, + { 0x70059e9122e1e32fl,0x1507c3fe9e51abb0l,0xd8aba31b2b7bda72l, + 0x5acbc5f77b753f13l }, + 0 }, + /* 28 << 104 */ + { { 0x15bfb8bf5116f937l,0x7c64a586c1268943l,0x71e25cc38419a2c8l, + 0x9fd6b0c48335f463l }, + { 0x4bf0ba3ce8ee0e0el,0x6f6fba60298c21fal,0x57d57b39ae66bee0l, + 0x292d513022672544l }, + 0 }, + /* 29 << 104 */ + { { 0x075dc81953952ff6l,0xd4d9eeda20b7384dl,0x8a81c1bfd2d6c6a5l, + 0x319368a0db050f3bl }, + { 0x91f476de31f1cee2l,0x1b38604500d0e17fl,0xed2081889a820384l, + 0x8d00c411a0f1a637l }, + 0 }, + /* 31 << 104 */ + { { 0xb029b687a47fd8f0l,0xa531360696371a05l,0x7b84e88c5ab09140l, + 0x87dad7c85eeb1d14l }, + { 0xef0749b9d0edf6f3l,0x29fc7310e2ef198bl,0x01e05df5069ed399l, + 0x121db4ecdf4e2fcal }, + 0 }, + /* 33 << 104 */ + { { 0xe730f3f62826bee0l,0xb9bdbe3fce332a8fl,0x1ecad11766ec00aal, + 0x7503d835617a62d1l }, + { 0x9f34e161b862b139l,0xde42194cf30f6a67l,0x5037a953c1e879fel, + 0x62f321f89bda45dbl }, + 0 }, + /* 34 << 104 */ + { { 0xe87771d8033f2876l,0xb0186ec67d5cc3dbl,0x58e8bb803bc9bc1dl, + 0x4d1395cc6f6ef60el }, + { 0xa73c62d6186244a0l,0x918e5f23110a5b53l,0xed4878ca741b7eabl, + 0x3038d71adbe03e51l }, + 0 }, + /* 35 << 104 */ + { { 0xcbdba27c40234d55l,0x24352b6cb3eb56c9l,0xae681b85a8e9295al, + 0x2a6cfba1f1171664l }, + { 0x49f045838ca40c3cl,0xe56da25c6eb0f8eal,0x8e62f86fc4341a4el, + 0x7f68bdc64c3f947fl }, + 0 }, + /* 36 << 104 */ + { { 0x840204b7a93c3246l,0x21ab6069a0b9b4cdl,0xf5fa6e2bb1d64218l, + 0x1de6ad0ef3d56191l }, + { 0x570aaa88ff1929c7l,0xc6df4c6b640e87b5l,0xde8a74f2c65f0cccl, + 0x8b972fd5e6f6cc01l }, + 0 }, + /* 37 << 104 */ + { { 0x862013c00bf22173l,0xfd004c834acd8e23l,0x50e422ca310b1649l, + 0xe6d04de65bbe1854l }, + { 0x651f646385761ef3l,0x3b17d38652cf85c9l,0xbdce284a5f54ecc7l, + 0x72efcd3ec7c2106cl }, + 0 }, + /* 39 << 104 */ + { { 0x34324b182ff07e3el,0x29938f38f50bcb71l,0xd0e3d7b977e2bcc3l, + 0x8e78f007c0a3292bl }, + { 0xfa28c530005c2c00l,0x6f9c21d51faa0c5al,0x3df01abd7b9c78f3l, + 0x0e5618c1ccaaeb7el }, + 0 }, + /* 40 << 104 */ + { { 0xaa6778fce7560b90l,0xb4073e61a7e824cel,0xff0d693cd642eba8l, + 0x7ce2e57a5dccef38l }, + { 0x89c2c7891df1ad46l,0x83a06922098346fdl,0x2d715d72da2fc177l, + 0x7b6dd71d85b6cf1dl }, + 0 }, + /* 41 << 104 */ + { { 0x4601a6a492ad3889l,0xdc8e3364d9a0709fl,0x0c687f2b2c260327l, + 0xe882af62e1a79573l }, + { 0x0cfd00ab945d9017l,0xe6df7505d0e3c188l,0xb389a66dbde825a2l, + 0x126d77b6bcd8e14fl }, + 0 }, + /* 43 << 104 */ + { { 0xc800acc7db18ec73l,0x0ebecc78d86e99efl,0x675796cdbd05bc5fl, + 0x254498126afd7c7fl }, + { 0x96293b695969b165l,0xd8514d83c162c8dal,0xe174f8b674a15a5cl, + 0x880d687389a2f73cl }, + 0 }, + /* 44 << 104 */ + { { 0x53703a328300129fl,0x1f63766268c43bfdl,0xbcbd191300e54051l, + 0x812fcc627bf5a8c5l }, + { 0x3f969d5f29fb85dal,0x72f4e00a694759e8l,0x426b6e52790726b7l, + 0x617bbc873bdbb209l }, + 0 }, + /* 45 << 104 */ + { { 0xf536f07cad1deb2el,0x2a13a11ea87a710el,0x0ce2ccab64f4dc96l, + 0x16178694f5a55464l }, + { 0x1496168da2cb3986l,0xb079a5b9d56a93a9l,0x97005e99092893d3l, + 0x55df5ed6e8fcc6c3l }, + 0 }, + /* 46 << 104 */ + { { 0x511f8bb997aee317l,0x812a4096e81536a8l,0x137dfe593ac09b9bl, + 0x0682238fba8c9a7al }, + { 0x7072ead6aeccb4bdl,0x6a34e9aa692ba633l,0xc82eaec26fff9d33l, + 0xfb7535121d4d2b62l }, + 0 }, + /* 47 << 104 */ + { { 0x821dca8bbf328b1cl,0x24596ddd5a3d6830l,0x061c4c15635b5b4cl, + 0x0e2b3bef4fa3560al }, + { 0xffced37498906c43l,0x10ebd174e26b3784l,0x7cd068c470039bb5l, + 0xc47dda0f88404e59l }, + 0 }, + /* 48 << 104 */ + { { 0x1a0445ff1d7aadabl,0x65d38260d5f6a67cl,0x6e62fb0891cfb26fl, + 0xef1e0fa55c7d91d6l }, + { 0x47e7c7ba33db72cdl,0x017cbc09fa7c74b2l,0x3c931590f50a503cl, + 0xcac54f60616baa42l }, + 0 }, + /* 49 << 104 */ + { { 0x7ad7d13569185235l,0x19771949fb69e030l,0xd4de9717bc45fb4fl, + 0x5657b076167e5739l }, + { 0x9503a71fdd27449el,0xfa2fabf73cc01347l,0xf8ecef24c83fb301l, + 0x527012bd5a8d5078l }, + 0 }, + /* 51 << 104 */ + { { 0x70a550d7e6fc3a32l,0x8e5875841951fe57l,0x5e6d43eaaab9788bl, + 0x1e406fed80599794l }, + { 0xd8164ace9ed2557cl,0xf9648f30ff593e10l,0x53af2fd80c2ff879l, + 0x6705993cc9409bf4l }, + 0 }, + /* 52 << 104 */ + { { 0x04b005b6c6458293l,0x36bb5276e8d10af7l,0xacf2dc138ee617b8l, + 0x470d2d35b004b3d4l }, + { 0x06790832feeb1b77l,0x2bb75c3985657f9cl,0xd70bd4edc0f60004l, + 0xfe797ecc219b018bl }, + 0 }, + /* 53 << 104 */ + { { 0xeca02ebf0ef19ceel,0xac691fbe2de090a4l,0x1f3866641b374547l, + 0xbd8018c6a12ee85fl }, + { 0x3e851318ee63e0f1l,0x45b0c37a161987d3l,0x67fe36056eb567c4l, + 0x07c291b563200c5bl }, + 0 }, + /* 55 << 104 */ + { { 0xc85535ac1a956a8al,0x7bf4d70bc0ade321l,0xaf2efc48237bc56fl, + 0xf9bfe13e31ba97e7l }, + { 0x2ca5fac4cf7c6c65l,0xc23b14ff03ec3e35l,0xc5109923217bcfd2l, + 0xf02f96a1c58f32f3l }, + 0 }, + /* 57 << 104 */ + { { 0x3b1f715b0d0aeff4l,0xbe406d62f0d44536l,0xe413843d567bcb38l, + 0x75b7fb43791e705al }, + { 0x5b831d4b224f85e5l,0x3fea6659d9a35eael,0xd6f8bd097c85480bl, + 0x2a9561a34a959267l }, + 0 }, + /* 59 << 104 */ + { { 0x4a96a3535a303c10l,0x9aa3ad71c37c8d7el,0x4e2d077fde52014fl, + 0x4d8bec5df8e3964dl }, + { 0xda88ab94e865e142l,0x52df506d10a88091l,0x9aebff0092fc38a2l, + 0xdfc034395608b0a2l }, + 0 }, + /* 60 << 104 */ + { { 0xee23fa819966e7eel,0x64ec4aa805b7920dl,0x2d44462d2d90aad4l, + 0xf44dd195df277ad5l }, + { 0x8d6471f1bb46b6a1l,0x1e65d313fd885090l,0x33a800f513a977b4l, + 0xaca9d7210797e1efl }, + 0 }, + /* 61 << 104 */ + { { 0xb1557be2a4ea787el,0x59324973019f667fl,0x262ceced5595367cl, + 0x8a676897ec598640l }, + { 0x2df6cebfc7f06f4fl,0xb255723138078f9al,0xad553c46524a0dd1l, + 0xe20bb20a5a68d62al }, + 0 }, + /* 63 << 104 */ + { { 0x6f47e3779589e263l,0x7cb83e3d35106bb8l,0x2642d87bcc632fc2l, + 0x4d18f34d8b77eb36l }, + { 0x7de6bf6d19ca4d1cl,0x438e8f02f7e926aal,0xb539021250ac930al, + 0xe34ddfc15b219a9fl }, + 0 }, + /* 64 << 104 */ + { { 0x98857ceb1bf4581cl,0xe635e186aca7b166l,0x278ddd22659722acl, + 0xa0903c4c1db68007l }, + { 0x366e458948f21402l,0x31b49c14b96abda2l,0x329c4b09e0403190l, + 0x97197ca3d29f43fel }, + 0 }, + /* 65 << 104 */ + { { 0xfe4de13781479db4l,0x307331f012f08ea5l,0x7f59a64758c04c13l, + 0x6b41189abdc9b3c9l }, + { 0xb10f11e5a6f8c5edl,0x757fb7a3f5b0579el,0x456d0a873c90d027l, + 0x7e8bb6bf32361796l }, + 0 }, + /* 71 << 104 */ + { { 0x6aa1dc6c9e689d8dl,0xaa5fa015479cdd09l,0x7eb4dbb582fc000al, + 0x4a57b689eff4e701l }, + { 0x7bfe8d2a8e15cd8cl,0xab109b1cc9074e1al,0x5716715fee1619a5l, + 0xf29a51eccdcb40bcl }, + 0 }, + /* 77 << 104 */ + { { 0x14c76234ddf03c6el,0xdfb5d388baeb2eddl,0x4bd85da26d413d2dl, + 0x5b0dd9be3ae38469l }, + { 0xe4d8a9d89ab3ae61l,0xb9e37b880ee63951l,0x17f08e9b21a7f30fl, + 0x173db1e8119af788l }, + 0 }, + /* 83 << 104 */ + { { 0x2352ad4a170d43f6l,0x098d74f65a0ae4b0l,0x290f5236c3a46c2al, + 0xea9266102dd87e7fl }, + { 0xd7ee90f6848e6911l,0xebe8f4cce0d8886fl,0xa2038320558ff6a0l, + 0x1f716534f37c38cfl }, + 0 }, + /* 89 << 104 */ + { { 0x9754209439a4a159l,0xe6135412fed24278l,0xbba62254d70e2cabl, + 0x4ac6a8ac85895130l }, + { 0xc01614fee1a45363l,0x720ad3f8b67294f2l,0x724ea95cb420ea51l, + 0x1f40ab2d712b856cl }, + 0 }, + /* 95 << 104 */ + { { 0x708e1c7975f3d30cl,0x423f1535e2172da3l,0x7a29be342a06a0b1l, + 0x9de5c9eb32c68ba2l }, + { 0x70217b0232d48793l,0x3cf3855bac1471cfl,0x6762d03f8321e179l, + 0x06ee12ea236fa7cfl }, + 0 }, + /* 101 << 104 */ + { { 0x1718e7428779109bl,0x6188008d0aca350bl,0xbbe227e00594bc15l, + 0x4a7b6423ddbdea35l }, + { 0x06ad632dfa44e1bfl,0xaf9c163d1e97b409l,0x64dafec3c61f2b2fl, + 0xc6759d905525c0c9l }, + 0 }, + /* 107 << 104 */ + { { 0x76d6294787517149l,0x2bda339baa77d325l,0x04b1bec067ad1fd1l, + 0x49f63fcc0aec7c73l }, + { 0x005cb459ec1bf494l,0x8fa99c1b1ec6f8bbl,0x70a4e6d78b59dd43l, + 0xfd70bcb313d6594dl }, + 0 }, + /* 113 << 104 */ + { { 0x2987a7cb13966c11l,0x74ad0a26a783f283l,0xf011200ae54d27f0l, + 0xbd8632963fb38396l }, + { 0x7ec7fe8c9b86d059l,0xfa94ca76d0cd33a7l,0xf6ad741cdc646993l, + 0x83054a427ebc34e9l }, + 0 }, + /* 116 << 104 */ + { { 0xadef8c5a192ef710l,0x88afbd4b3b7431f9l,0x7e1f740764250c9el, + 0x6e31318db58bec07l }, + { 0xfd4fc4b824f89b4el,0x65a5dd8848c36a2al,0x4f1eccfff024baa7l, + 0x22a21cf2cba94650l }, + 0 }, + /* 119 << 104 */ + { { 0x7b45865478f39754l,0xcbb8b96c4564e003l,0xb492d2bf69b35752l, + 0x4e6287e065ee5ad3l }, + { 0x07906c14eb1ffe62l,0xf350390c681fcdf8l,0xc351386f6be3eec3l, + 0x8480d00ee5df919dl }, + 0 }, + /* 125 << 104 */ + { { 0x399861ecf8a2d5aal,0xb179adeb046f78cbl,0x056a6cd88792f647l, + 0xd3dfc91c3d411820l }, + { 0x4ccf92d179693be1l,0x12ecd9a3f65cb250l,0x58e5d2102538b9e7l, + 0x4e655882ff977ccal }, + 0 }, + }, + { + /* 0 << 112 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 112 */ + { { 0x8ce9b6bfc360e25al,0xe6425195075a1a78l,0x9dc756a8481732f4l, + 0x83c0440f5432b57al }, + { 0xc670b3f1d720281fl,0x2205910ed135e051l,0xded14b0edb052be7l, + 0x697b3d27c568ea39l }, + 0 }, + /* 3 << 112 */ + { { 0x0b89de9314092ebbl,0xf17256bd428e240cl,0xcf89a7f393d2f064l, + 0x4f57841ee1ed3b14l }, + { 0x4ee14405e708d855l,0x856aae7203f1c3d0l,0xc8e5424fbdd7eed5l, + 0x3333e4ef73ab4270l }, + 0 }, + /* 4 << 112 */ + { { 0x3bc77adedda492f8l,0xc11a3aea78297205l,0x5e89a3e734931b4cl, + 0x17512e2e9f5694bbl }, + { 0x5dc349f3177bf8b6l,0x232ea4ba08c7ff3el,0x9c4f9d16f511145dl, + 0xccf109a333b379c3l }, + 0 }, + /* 5 << 112 */ + { { 0xe75e7a88a1f25897l,0x7ac6961fa1b5d4d8l,0xe3e1077308f3ed5cl, + 0x208a54ec0a892dfbl }, + { 0xbe826e1978660710l,0x0cf70a97237df2c8l,0x418a7340ed704da5l, + 0xa3eeb9a908ca33fdl }, + 0 }, + /* 7 << 112 */ + { { 0xb4323d588434a920l,0xc0af8e93622103c5l,0x667518ef938dbf9al, + 0xa184307383a9cdf2l }, + { 0x350a94aa5447ab80l,0xe5e5a325c75a3d61l,0x74ba507f68411a9el, + 0x10581fc1594f70c5l }, + 0 }, + /* 9 << 112 */ + { { 0x5aaa98a7cb0c9c8cl,0x75105f3081c4375cl,0xceee50575ef1c90fl, + 0xb31e065fc23a17bfl }, + { 0x5364d275d4b6d45al,0xd363f3ad62ec8996l,0xb5d212394391c65bl, + 0x84564765ebb41b47l }, + 0 }, + /* 10 << 112 */ + { { 0x20d18ecc37107c78l,0xacff3b6b570c2a66l,0x22f975d99bd0d845l, + 0xef0a0c46ba178fa0l }, + { 0x1a41965176b6028el,0xc49ec674248612d4l,0x5b6ac4f27338af55l, + 0x06145e627bee5a36l }, + 0 }, + /* 11 << 112 */ + { { 0x33e95d07e75746b5l,0x1c1e1f6dc40c78bel,0x967833ef222ff8e2l, + 0x4bedcf6ab49180adl }, + { 0x6b37e9c13d7a4c8al,0x2748887c6ddfe760l,0xf7055123aa3a5bbcl, + 0x954ff2257bbb8e74l }, + 0 }, + /* 13 << 112 */ + { { 0x4e23ca446d3fea55l,0xb4ae9c86f4810568l,0x47bfb91b2a62f27dl, + 0x60deb4c9d9bac28cl }, + { 0xa892d8947de6c34cl,0x4ee682594494587dl,0x914ee14e1a3f8a5bl, + 0xbb113eaa28700385l }, + 0 }, + /* 15 << 112 */ + { { 0xef9dc899a7b56eafl,0x00c0e52c34ef7316l,0x5b1e4e24fe818a86l, + 0x9d31e20dc538be47l }, + { 0x22eb932d3ed68974l,0xe44bbc087c4e87c4l,0x4121086e0dde9aefl, + 0x8e6b9cff134f4345l }, + 0 }, + /* 16 << 112 */ + { { 0x96892c1f711b0eb9l,0xb905f2c8780ab954l,0xace26309a20792dbl, + 0xec8ac9b30684e126l }, + { 0x486ad8b6b40a2447l,0x60121fc19fe3fb24l,0x5626fccf1a8e3b3fl, + 0x4e5686226ad1f394l }, + 0 }, + /* 17 << 112 */ + { { 0xda7aae0d196aa5a1l,0xe0df8c771041b5fbl,0x451465d926b318b7l, + 0xc29b6e557ab136e9l }, + { 0x2c2ab48b71148463l,0xb5738de364454a76l,0x54ccf9a05a03abe4l, + 0x377c02960427d58el }, + 0 }, + /* 19 << 112 */ + { { 0x90e4f7c92d7d1413l,0x67e2d6b59834f597l,0x4fd4f4f9a808c3e8l, + 0xaf8237e0d5281ec1l }, + { 0x25ab5fdc84687ceel,0xc5ded6b1a5b26c09l,0x8e4a5aecc8ea7650l, + 0x23b73e5c14cc417fl }, + 0 }, + /* 21 << 112 */ + { { 0xb4293fdcf50225f9l,0xc52e175cb0e12b03l,0xf649c3bad0a8bf64l, + 0x745a8fefeb8ae3c6l }, + { 0x30d7e5a358321bc3l,0xb1732be70bc4df48l,0x1f217993e9ea5058l, + 0xf7a71cde3e4fd745l }, + 0 }, + /* 23 << 112 */ + { { 0xa188b2502d0f39aal,0x622118bb15a85947l,0x2ebf520ffde0f4fal, + 0xa40e9f294860e539l }, + { 0x7b6a51eb22b57f0fl,0x849a33b97e80644al,0x50e5d16f1cf095fel, + 0xd754b54eec55f002l }, + 0 }, + /* 25 << 112 */ + { { 0xcd821dfb988baf01l,0xe6331a7ddbb16647l,0x1eb8ad33094cb960l, + 0x593cca38c91bbca5l }, + { 0x384aac8d26567456l,0x40fa0309c04b6490l,0x97834cd6dab6c8f6l, + 0x68a7318d3f91e55fl }, + 0 }, + /* 27 << 112 */ + { { 0xc7bfd486605daaa6l,0x46fd72b7bb9a6c9el,0xe4847fb1a124fb89l, + 0x75959cbda2d8ffbcl }, + { 0x42579f65c8a588eel,0x368c92e6b80b499dl,0xea4ef6cd999a5df1l, + 0xaa73bb7f936fe604l }, + 0 }, + /* 28 << 112 */ + { { 0xf347a70d6457d188l,0x86eda86b8b7a388bl,0xb7cdff060ccd6013l, + 0xbeb1b6c7d0053fb2l }, + { 0x0b02238799240a9fl,0x1bbb384f776189b2l,0x8695e71e9066193al, + 0x2eb5009706ffac7el }, + 0 }, + /* 29 << 112 */ + { { 0x0654a9c04a7d2caal,0x6f3fb3d1a5aaa290l,0x835db041ff476e8fl, + 0x540b8b0bc42295e4l }, + { 0xa5c73ac905e214f5l,0x9a74075a56a0b638l,0x2e4b1090ce9e680bl, + 0x57a5b4796b8d9afal }, + 0 }, + /* 31 << 112 */ + { { 0x2a2bfa7f650006f0l,0xdfd7dad350c0fbb2l,0x92452495ccf9ad96l, + 0x183bf494d95635f9l }, + { 0x02d5df434a7bd989l,0x505385cca5431095l,0xdd98e67dfd43f53el, + 0xd61e1a6c500c34a9l }, + 0 }, + /* 33 << 112 */ + { { 0x41d85ea1ef74c45bl,0x2cfbfa66ae328506l,0x98b078f53ada7da9l, + 0xd985fe37ec752fbbl }, + { 0xeece68fe5a0148b4l,0x6f9a55c72d78136dl,0x232dccc4d2b729cel, + 0xa27e0dfd90aafbc4l }, + 0 }, + /* 34 << 112 */ + { { 0x9647445212b4603el,0xa876c5516b706d14l,0xdf145fcf69a9d412l, + 0xe2ab75b72d479c34l }, + { 0x12df9a761a23ff97l,0xc61389925d359d10l,0x6e51c7aefa835f22l, + 0x69a79cb1c0fcc4d9l }, + 0 }, + /* 35 << 112 */ + { { 0xf57f350d594cc7e1l,0x3079ca633350ab79l,0x226fb6149aff594al, + 0x35afec026d59a62bl }, + { 0x9bee46f406ed2c6el,0x58da17357d939a57l,0x44c504028fd1797el, + 0xd8853e7c5ccea6cal }, + 0 }, + /* 36 << 112 */ + { { 0x4065508da35fcd5fl,0x8965df8c495ccaebl,0x0f2da85012e1a962l, + 0xee471b94c1cf1cc4l }, + { 0xcef19bc80a08fb75l,0x704958f581de3591l,0x2867f8b23aef4f88l, + 0x8d749384ea9f9a5fl }, + 0 }, + /* 37 << 112 */ + { { 0x1b3855378c9049f4l,0x5be948f37b92d8b6l,0xd96f725db6e2bd6bl, + 0x37a222bc958c454dl }, + { 0xe7c61abb8809bf61l,0x46f07fbc1346f18dl,0xfb567a7ae87c0d1cl, + 0x84a461c87ef3d07al }, + 0 }, + /* 39 << 112 */ + { { 0x3ab3d5afbd76e195l,0x478dd1ad6938a810l,0x6ffab3936ee3d5cbl, + 0xdfb693db22b361e4l }, + { 0xf969449651dbf1a7l,0xcab4b4ef08a2e762l,0xe8c92f25d39bba9al, + 0x850e61bcf1464d96l }, + 0 }, + /* 40 << 112 */ + { { 0xb7e830e3dc09508bl,0xfaf6d2cf74317655l,0x72606cebdf690355l, + 0x48bb92b3d0c3ded6l }, + { 0x65b754845c7cf892l,0xf6cd7ac9d5d5f01fl,0xc2c30a5996401d69l, + 0x91268650ed921878l }, + 0 }, + /* 41 << 112 */ + { { 0x380bf913b78c558fl,0x43c0baebc8afdaa9l,0x377f61d554f169d3l, + 0xf8da07e3ae5ff20bl }, + { 0xb676c49da8a90ea8l,0x81c1ff2b83a29b21l,0x383297ac2ad8d276l, + 0x3001122fba89f982l }, + 0 }, + /* 43 << 112 */ + { { 0xbbe1e6a6c93f72d6l,0xd5f75d12cad800eal,0xfa40a09fe7acf117l, + 0x32c8cdd57581a355l }, + { 0x742219927023c499l,0xa8afe5d738ec3901l,0x5691afcba90e83f0l, + 0x41bcaa030b8f8eacl }, + 0 }, + /* 44 << 112 */ + { { 0xe38b5ff98d2668d5l,0x0715281a7ad81965l,0x1bc8fc7c03c6ce11l, + 0xcbbee6e28b650436l }, + { 0x06b00fe80cdb9808l,0x17d6e066fe3ed315l,0x2e9d38c64d0b5018l, + 0xab8bfd56844dcaefl }, + 0 }, + /* 45 << 112 */ + { { 0x42894a59513aed8bl,0xf77f3b6d314bd07al,0xbbdecb8f8e42b582l, + 0xf10e2fa8d2390fe6l }, + { 0xefb9502262a2f201l,0x4d59ea5050ee32b0l,0xd87f77286da789a8l, + 0xcf98a2cff79492c4l }, + 0 }, + /* 46 << 112 */ + { { 0xf9577239720943c2l,0xba044cf53990b9d0l,0x5aa8e82395f2884al, + 0x834de6ed0278a0afl }, + { 0xc8e1ee9a5f25bd12l,0x9259ceaa6f7ab271l,0x7e6d97a277d00b76l, + 0x5c0c6eeaa437832al }, + 0 }, + /* 47 << 112 */ + { { 0x5232c20f5606b81dl,0xabd7b3750d991ee5l,0x4d2bfe358632d951l, + 0x78f8514698ed9364l }, + { 0x951873f0f30c3282l,0x0da8ac80a789230bl,0x3ac7789c5398967fl, + 0xa69b8f7fbdda0fb5l }, + 0 }, + /* 48 << 112 */ + { { 0xe5db77176add8545l,0x1b71cb6672c49b66l,0xd856073968421d77l, + 0x03840fe883e3afeal }, + { 0xb391dad51ec69977l,0xae243fb9307f6726l,0xc88ac87be8ca160cl, + 0x5174cced4ce355f4l }, + 0 }, + /* 49 << 112 */ + { { 0x98a35966e58ba37dl,0xfdcc8da27817335dl,0x5b75283083fbc7bfl, + 0x68e419d4d9c96984l }, + { 0x409a39f402a40380l,0x88940faf1fe977bcl,0xc640a94b8f8edea6l, + 0x1e22cd17ed11547dl }, + 0 }, + /* 51 << 112 */ + { { 0x17ba93b1a20ef103l,0xad8591306ba6577bl,0x65c91cf66fa214a0l, + 0xd7d49c6c27990da5l }, + { 0xecd9ec8d20bb569dl,0xbd4b2502eeffbc33l,0x2056ca5a6bed0467l, + 0x7916a1f75b63728cl }, + 0 }, + /* 52 << 112 */ + { { 0xd4f9497d53a4f566l,0x8973466497b56810l,0xf8e1da740494a621l, + 0x82546a938d011c68l }, + { 0x1f3acb19c61ac162l,0x52f8fa9cabad0d3el,0x15356523b4b7ea43l, + 0x5a16ad61ae608125l }, + 0 }, + /* 53 << 112 */ + { { 0xb0bcb87f4faed184l,0x5f236b1d5029f45fl,0xd42c76070bc6b1fcl, + 0xc644324e68aefce3l }, + { 0x8e191d595c5d8446l,0xc020807713ae1979l,0xadcaee553ba59cc7l, + 0x20ed6d6ba2cb81bal }, + 0 }, + /* 55 << 112 */ + { { 0x7392b41a530ccbbdl,0x87c82146ea823525l,0xa52f984c05d98d0cl, + 0x2ae57d735ef6974cl }, + { 0x9377f7bf3042a6ddl,0xb1a007c019647a64l,0xfaa9079a0cca9767l, + 0x3d81a25bf68f72d5l }, + 0 }, + /* 57 << 112 */ + { { 0xc110d830b0f2ac95l,0x48d0995aab20e64el,0x0f3e00e17729cd9al, + 0x2a570c20dd556946l }, + { 0x912dbcfd4e86214dl,0x2d014ee2cf615498l,0x55e2b1e63530d76el, + 0xc5135ae4fd0fd6d1l }, + 0 }, + /* 59 << 112 */ + { { 0x1854daa5061f1658l,0xc0016df1df0cd2b3l,0xc2a3f23e833d50del, + 0x73b681d2bbbd3017l }, + { 0x2f046dc43ac343c0l,0x9c847e7d85716421l,0xe1e13c910917eed4l, + 0x3fc9eebd63a1b9c6l }, + 0 }, + /* 60 << 112 */ + { { 0x0f816a727fe02299l,0x6335ccc2294f3319l,0x3820179f4745c5bel, + 0xe647b782922f066el }, + { 0xc22e49de02cafb8al,0x299bc2fffcc2ecccl,0x9a8feea26e0e8282l, + 0xa627278bfe893205l }, + 0 }, + /* 61 << 112 */ + { { 0xa7e197337933e47bl,0xf4ff6b132e766402l,0xa4d8be0a98440d9fl, + 0x658f5c2f38938808l }, + { 0x90b75677c95b3b3el,0xfa0442693137b6ffl,0x077b039b43c47c29l, + 0xcca95dd38a6445b2l }, + 0 }, + /* 63 << 112 */ + { { 0x583f3703f9374ab6l,0x864f91956e564145l,0x33bc3f4822526d50l, + 0x9f323c801262a496l }, + { 0xaa97a7ae3f046a9al,0x70da183edf8a039al,0x5b68f71c52aa0ba6l, + 0x9be0fe5121459c2dl }, + 0 }, + /* 64 << 112 */ + { { 0xc1e17eb6cbc613e5l,0x33131d55497ea61cl,0x2f69d39eaf7eded5l, + 0x73c2f434de6af11bl }, + { 0x4ca52493a4a375fal,0x5f06787cb833c5c2l,0x814e091f3e6e71cfl, + 0x76451f578b746666l }, + 0 }, + /* 65 << 112 */ + { { 0xa700767eabd0cc76l,0xa14ae98015889273l,0x5acf2cc466ea6380l, + 0xb942cc40d08d18b9l }, + { 0x9b5daa763ae45782l,0x61a25e0fb72f0ce0l,0xf94c0e80435fefe3l, + 0x73d552cf1620e1c9l }, + 0 }, + /* 71 << 112 */ + { { 0x57130582727185c1l,0x8f2b8ebc163897ecl,0x4a059cc7a04e4a6bl, + 0x4b1de9fe0908a366l }, + { 0xa4f7738688d0fef0l,0x55e3bb1d9ebfc138l,0x9022bbef005ae362l, + 0xf5669edc8741d349l }, + 0 }, + /* 77 << 112 */ + { { 0xf192c0f7ede937a4l,0xd2e91d62810c1b1el,0xf2b40b64dcc39c69l, + 0xe125fbd028f03b0el }, + { 0x52966dd78da708f9l,0x92d400a3cc0e7f32l,0x4e35aae36b0842b8l, + 0x0b4fe66ded3ad3cfl }, + 0 }, + /* 83 << 112 */ + { { 0x14b81d951f1ff6b5l,0x1d82f132ed9b03b8l,0x52f6f029b4fa4047l, + 0xea653682601e5913l }, + { 0x4e900375edeee046l,0xd22ed267f9428714l,0xb004fb3b1753e873l, + 0xfef061ba245b2c09l }, + 0 }, + /* 89 << 112 */ + { { 0x5e2376eaf9deba2bl,0x1ed1e9e5269a18cfl,0x8dffd66dcb1cada8l, + 0xb13239f068369c77l }, + { 0x2fede3a67f25426fl,0xc885cf0c6f90a2a6l,0xd950162d4eeac543l, + 0x53011aa09abc201bl }, + 0 }, + /* 95 << 112 */ + { { 0x7a63925d432b798al,0x92e762cfc9bd6da9l,0xf22fb9706a190382l, + 0x19919b847b18a9b3l }, + { 0x16793b803adfde86l,0xf9ce15ace8b1d44cl,0x4bf74144c0a140b8l, + 0x680468616f853f6cl }, + 0 }, + /* 101 << 112 */ + { { 0xd4e0d8460db84ba2l,0x9a162a3a360b68bbl,0x7297f3939233146cl, + 0xbc93c2f4ec77412dl }, + { 0x13ddf0a7e07e1065l,0x000a8d45fb5e5131l,0xb4373078cf61d467l, + 0xa4a1fd67bf3bb6f9l }, + 0 }, + /* 107 << 112 */ + { { 0x6f2473f9d7585098l,0x45a29448d4f23c1al,0x47fe40f1c22bdc25l, + 0x4e46ed1f31347673l }, + { 0x5e43a8624148898cl,0x4a02ededa993954el,0x83d830b52f8a1847l, + 0x007e3156a7f6a378l }, + 0 }, + /* 113 << 112 */ + { { 0x01a39fe7e847ca18l,0xaf2722418fed2772l,0x3104ef891fbb1748l, + 0x5b55331b2b9dd5ffl }, + { 0xe7806e31cec6a787l,0x9f49ed881e9c0af2l,0xf5a66373a3905b36l, + 0x77b5bca9efab75f3l }, + 0 }, + /* 116 << 112 */ + { { 0xd4d75f4bf0831932l,0x5e770ac477fe8cc9l,0x52b5e748862e72a2l, + 0xe9a45482501d35fel }, + { 0x8a93e7424a9ab187l,0x5a72506de88ca017l,0xe680dcb201eb2defl, + 0xdc5aa4e6ba68209dl }, + 0 }, + /* 119 << 112 */ + { { 0x2defa3dc3d01a344l,0x11fd939b162e459al,0x928453b97313d720l, + 0x08696dc053184a65l }, + { 0xd9f8a69c721f7415l,0x304eb0e079539019l,0xc9b0ca6dbb0c6313l, + 0xa10133eba93dc74el }, + 0 }, + /* 125 << 112 */ + { { 0xee0b164004393f1el,0x511547dfe1301979l,0xc00dfc3516d26d87l, + 0x06227c8aab847494l }, + { 0x178ca86748b2fdc7l,0xb51296f01a8ba1dcl,0xf252787731e1dd14l, + 0x7ecb5456c0ba2a1fl }, + 0 }, + }, + { + /* 0 << 120 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 120 */ + { { 0x3e0e5c9dd111f8ecl,0xbcc33f8db7c4e760l,0x702f9a91bd392a51l, + 0x7da4a795c132e92dl }, + { 0x1a0b0ae30bb1151bl,0x54febac802e32251l,0xea3a5082694e9e78l, + 0xe58ffec1e4fe40b8l }, + 0 }, + /* 3 << 120 */ + { { 0x7b23c513516e19e4l,0x56e2e847c5c4d593l,0x9f727d735ce71ef6l, + 0x5b6304a6f79a44c5l }, + { 0x6638a7363ab7e433l,0x1adea470fe742f83l,0xe054b8545b7fc19fl, + 0xf935381aba1d0698l }, + 0 }, + /* 4 << 120 */ + { { 0xb5504f9d918e4936l,0x65035ef6b2513982l,0x0553a0c26f4d9cb9l, + 0x6cb10d56bea85509l }, + { 0x48d957b7a242da11l,0x16a4d3dd672b7268l,0x3d7e637c8502a96bl, + 0x27c7032b730d463bl }, + 0 }, + /* 5 << 120 */ + { { 0x55366b7d5846426fl,0xe7d09e89247d441dl,0x510b404d736fbf48l, + 0x7fa003d0e784bd7dl }, + { 0x25f7614f17fd9596l,0x49e0e0a135cb98dbl,0x2c65957b2e83a76al, + 0x5d40da8dcddbe0f8l }, + 0 }, + /* 7 << 120 */ + { { 0x9fb3bba354530bb2l,0xbde3ef77cb0869eal,0x89bc90460b431163l, + 0x4d03d7d2e4819a35l }, + { 0x33ae4f9e43b6a782l,0x216db3079c88a686l,0x91dd88e000ffedd9l, + 0xb280da9f12bd4840l }, + 0 }, + /* 9 << 120 */ + { { 0xa37f3573f37f5937l,0xeb0f6c7dd1e4fca5l,0x2965a554ac8ab0fcl, + 0x17fbf56c274676acl }, + { 0x2e2f6bd9acf7d720l,0x41fc8f8810224766l,0x517a14b385d53befl, + 0xdae327a57d76a7d1l }, + 0 }, + /* 10 << 120 */ + { { 0x515d5c891f5f82dcl,0x9a7f67d76361079el,0xa8da81e311a35330l, + 0xe44990c44b18be1bl }, + { 0xc7d5ed95af103e59l,0xece8aba78dac9261l,0xbe82b0999394b8d3l, + 0x6830f09a16adfe83l }, + 0 }, + /* 11 << 120 */ + { { 0x43c41ac194d7d9b1l,0x5bafdd82c82e7f17l,0xdf0614c15fda0fcal, + 0x74b043a7a8ae37adl }, + { 0x3ba6afa19e71734cl,0x15d5437e9c450f2el,0x4a5883fe67e242b1l, + 0x5143bdc22c1953c2l }, + 0 }, + /* 13 << 120 */ + { { 0xc676d7f2b1f3390bl,0x9f7a1b8ca5b61272l,0x4ebebfc9c2e127a9l, + 0x4602500c5dd997bfl }, + { 0x7f09771c4711230fl,0x058eb37c020f09c1l,0xab693d4bfee5e38bl, + 0x9289eb1f4653cbc0l }, + 0 }, + /* 15 << 120 */ + { { 0x54da9dc7ab952578l,0xb5423df226e84d0bl,0xa8b64eeb9b872042l, + 0xac2057825990f6dfl }, + { 0x4ff696eb21f4c77al,0x1a79c3e4aab273afl,0x29bc922e9436b3f1l, + 0xff807ef8d6d9a27al }, + 0 }, + /* 16 << 120 */ + { { 0xc7f3a8f833f6746cl,0x21e46f65fea990cal,0x915fd5c5caddb0a9l, + 0xbd41f01678614555l }, + { 0x346f4434426ffb58l,0x8055943614dbc204l,0xf3dd20fe5a969b7fl, + 0x9d59e956e899a39al }, + 0 }, + /* 17 << 120 */ + { { 0xe4ca688fd06f56c0l,0xa48af70ddf027972l,0x691f0f045e9a609dl, + 0xa9dd82cdee61270el }, + { 0x8903ca63a0ef18d3l,0x9fb7ee353d6ca3bdl,0xa7b4a09cabf47d03l, + 0x4cdada011c67de8el }, + 0 }, + /* 19 << 120 */ + { { 0xac127dc1e038a675l,0x729deff38c5c6320l,0xb7df8fd4a90d2c53l, + 0x9b74b0ec681e7cd3l }, + { 0x5cb5a623dab407e5l,0xcdbd361576b340c6l,0xa184415a7d28392cl, + 0xc184c1d8e96f7830l }, + 0 }, + /* 21 << 120 */ + { { 0x86a9303b2f7e85c3l,0x5fce462171988f9bl,0x5b935bf6c138acb5l, + 0x30ea7d6725661212l }, + { 0xef1eb5f4e51ab9a2l,0x0587c98aae067c78l,0xb3ce1b3c77ca9ca6l, + 0x2a553d4d54b5f057l }, + 0 }, + /* 23 << 120 */ + { { 0x2c7156e10b1894a0l,0x92034001d81c68c0l,0xed225d00c8b115b5l, + 0x237f9c2283b907f2l }, + { 0x0ea2f32f4470e2c0l,0xb725f7c158be4e95l,0x0f1dcafab1ae5463l, + 0x59ed51871ba2fc04l }, + 0 }, + /* 25 << 120 */ + { { 0xd1b0ccdec9520711l,0x55a9e4ed3c8b84bfl,0x9426bd39a1fef314l, + 0x4f5f638e6eb93f2bl }, + { 0xba2a1ed32bf9341bl,0xd63c13214d42d5a9l,0xd2964a89316dc7c5l, + 0xd1759606ca511851l }, + 0 }, + /* 27 << 120 */ + { { 0xedf69feaf8c51187l,0x05bb67ec741e4da7l,0x47df0f3208114345l, + 0x56facb07bb9792b1l }, + { 0xf3e007e98f6229e4l,0x62d103f4526fba0fl,0x4f33bef7b0339d79l, + 0x9841357bb59bfec1l }, + 0 }, + /* 28 << 120 */ + { { 0xae1e0b67e28ef5bal,0x2c9a4699cb18e169l,0x0ecd0e331e6bbd20l, + 0x571b360eaf5e81d2l }, + { 0xcd9fea58101c1d45l,0x6651788e18880452l,0xa99726351f8dd446l, + 0x44bed022e37281d0l }, + 0 }, + /* 29 << 120 */ + { { 0x830e6eea60dbac1fl,0x23d8c484da06a2f7l,0x896714b050ca535bl, + 0xdc8d3644ebd97a9bl }, + { 0x106ef9fab12177b4l,0xf79bf464534d5d9cl,0x2537a349a6ab360bl, + 0xc7c54253a00c744fl }, + 0 }, + /* 31 << 120 */ + { { 0x24d661d168754ab0l,0x801fce1d6f429a76l,0xc068a85fa58ce769l, + 0xedc35c545d5eca2bl }, + { 0xea31276fa3f660d1l,0xa0184ebeb8fc7167l,0x0f20f21a1d8db0ael, + 0xd96d095f56c35e12l }, + 0 }, + /* 33 << 120 */ + { { 0x57d2046b59da06ebl,0x3c076d5fa49f6d74l,0x6b4c96e616f82ea0l, + 0xaf7b0f1f90536c0bl }, + { 0x7999f86d204a9b2dl,0x7e420264126c9f87l,0x4c967a1f262ac4e5l, + 0xe8174a09900e79adl }, + 0 }, + /* 34 << 120 */ + { { 0xd51687f2cb82516bl,0x8a440cfc040e4670l,0xeafd2bcfe7738d32l, + 0x7071e9162a1e911al }, + { 0xbd3abd44cfea57bbl,0x9c3add16085b19e2l,0xb194c01d6baa5aa6l, + 0x6f3d3faf92f85c64l }, + 0 }, + /* 35 << 120 */ + { { 0xe23e0769488a280el,0x8e55a728e63a5904l,0x01690716ab84cccfl, + 0xfe796130b78b3c98l }, + { 0x15cc475b9117f211l,0xbdc178761d1b9d56l,0x8df5594a3e37b9b9l, + 0x97747e341e37e494l }, + 0 }, + /* 36 << 120 */ + { { 0xf2a6370ed2f896e1l,0x27100e63802987afl,0xb4db1cff4678ebc7l, + 0x6e5f28d937b4b263l }, + { 0xd29030009711ebc4l,0xf14dcb9ff8712484l,0x7a46ec3eea449146l, + 0x200155e9c1c51179l }, + 0 }, + /* 37 << 120 */ + { { 0x8130f007f1968d55l,0x18823e7097ed9803l,0xdc9fec559402762dl, + 0x9e0bd57e278f5abbl }, + { 0xaa41b913c9ebf303l,0x1105ec43a76b9353l,0xf8e4ee4cf4e6c6b5l, + 0x3a630972bd7be696l }, + 0 }, + /* 39 << 120 */ + { { 0x5c7da7e16356b3eel,0x951bfe458ccf9b48l,0x6f2c6e91d0555d0cl, + 0x47d7f7b58efd38eel }, + { 0x957256c8af6fd630l,0xa690c65bdc01774cl,0xad52b27c7c8dafdal, + 0x81fbc16af44a145fl }, + 0 }, + /* 40 << 120 */ + { { 0x497c3a3481b0493al,0x2b3ab20d71bc8408l,0x0c60226aa03769d1l, + 0x4ac89c7ad10708b0l }, + { 0x62398ea5092f7e6al,0x7f408f54de96d526l,0x025bde6f85bf102cl, + 0xcc2f85120a4aa72el }, + 0 }, + /* 41 << 120 */ + { { 0x8a65e0386884a9c3l,0xd2e6ac047bf8c794l,0xc9c5d3d3f7bcdfb9l, + 0x0000ce42a33f2c12l }, + { 0xea1c0a9a7dd13b2bl,0xbfd97d7f0c35c3b1l,0x0ba75cf3347fcefel, + 0xc3c5f28f1333460dl }, + 0 }, + /* 43 << 120 */ + { { 0x7810ebf575baa708l,0xe7fa7a0dd7440549l,0x25b813baf0667e4al, + 0x30a46740d15838a8l }, + { 0x13207b1ad04b22f7l,0x09e601ffd1419699l,0xb1038fc77f687b27l, + 0xa4547dc9a127f95bl }, + 0 }, + /* 44 << 120 */ + { { 0x83b2e3b3056ecd2cl,0xd17dcdaaf03dfd36l,0xee24a5f81dcef956l, + 0xb6746cd0b7239f16l }, + { 0xed6cb311c8458c48l,0xe8c0fc9805d27da4l,0x4610e9a0a1bf0970l, + 0x1947f01d9906c19el }, + 0 }, + /* 45 << 120 */ + { { 0x8b979126217c7cd7l,0x65c57a378050067el,0x6a50c6383f34838cl, + 0x3de617c29b7bc81fl }, + { 0x58488d24253a0ac7l,0x3fe53ec75520ba0bl,0x9156dca763f0607el, + 0xdd08c5705d1fe134l }, + 0 }, + /* 46 << 120 */ + { { 0xbfb1d9e1e33ba77fl,0x0985311ccaef6c01l,0xc8b59e9accca8948l, + 0x1256280945416f25l }, + { 0xc90edbc257f53218l,0xcaa08c05125d8fb5l,0x33ea3fd49a1aad3bl, + 0x2aa8bd83d005e8bel }, + 0 }, + /* 47 << 120 */ + { { 0xcbd2f1a3c2b22963l,0x0f7bd29c0c8ac2b3l,0xddb932432d405bfdl, + 0xeabd4805328413b5l }, + { 0xcc79d31748ebb6b9l,0x09604f831f521aael,0xd3487fdf4c7d188cl, + 0xd219c318d1552ea9l }, + 0 }, + /* 48 << 120 */ + { { 0xef4f115c775d6ecel,0x69d2e3bbe8c0e78dl,0xb0264ef1145cfc81l, + 0x0a41e9fa1b69788bl }, + { 0x0d9233be909a1f0bl,0x150a84520ae76b30l,0xea3375370632bb69l, + 0x15f7b3cfaa25584al }, + 0 }, + /* 49 << 120 */ + { { 0xfc4c623e321f7b11l,0xd36c1066f9cbc693l,0x8165235835dc0c0al, + 0xa3ce2e18c824e97el }, + { 0x59ea7cbcc6ff405el,0xced5a94a1e56a1e2l,0x88d744c53ab64b39l, + 0x8963d029073a36e7l }, + 0 }, + /* 51 << 120 */ + { { 0x97aa902cb19f3edbl,0x8e605ff9bbf2975bl,0x0536fa8ba6eb299bl, + 0xfd96da4f7cd03ac0l }, + { 0x29c5b5b578f9a265l,0x1f025a6d5fd0bc1bl,0x440486ee58e0f8e1l, + 0x8f191f7d593e49e9l }, + 0 }, + /* 52 << 120 */ + { { 0xbddf656baea9c13fl,0x083c5d514c678b37l,0x975431b630878ed4l, + 0x6de13d4608d9cf1cl }, + { 0xfbb639cc02427c45l,0x6190ca0c5a6cd989l,0x35a6aa26c53f11b7l, + 0x73f9e17dddfd86f6l }, + 0 }, + /* 53 << 120 */ + { { 0xd30478a317be7689l,0x6fc3f634e358f7a7l,0x4057ece515688d9fl, + 0xb5397495d3d91eefl }, + { 0x62fac49e2f49bde4l,0xeb4a3e1860125c73l,0x15f38be8dabdac55l, + 0x18bf29f7d334d52al }, + 0 }, + /* 55 << 120 */ + { { 0xf684162b68777538l,0x3e2a770bbb3381f4l,0x1b7562c1b374577cl, + 0x9eec22dc5cf21688l }, + { 0xc35014b1d472be2cl,0xafe2317035f086fbl,0xb9c9c4c9a1491ce1l, + 0x2df1e669b56792ddl }, + 0 }, + /* 57 << 120 */ + { { 0xcf7d36fe1830f624l,0x176c3c12ed0474bdl,0x25b802c8f82b493dl, + 0x683c2a744c78147el }, + { 0x0db99444f8f3e446l,0x437bcac6800a56c7l,0xb4e592264d08b25fl, + 0xcaf1b4142e691ca7l }, + 0 }, + /* 59 << 120 */ + { { 0x378bd47b9d231cafl,0xde3aa2f01f4db832l,0xf609d16ab29bd7d5l, + 0x13feab54bdfb54dfl }, + { 0x274abbbc22fc1a12l,0x267febb47d30ef1bl,0xeffa996d80717cd8l, + 0x065a86d1118d0812l }, + 0 }, + /* 60 << 120 */ + { { 0xc681a8656a3cb3afl,0x528f25a981751414l,0x6669f07cc7eac946l, + 0x9fb3a53f3cc6cc6bl }, + { 0x2919d92a11ae224al,0xa59141110b170a19l,0xdc16c611e2042f16l, + 0x58ace12decd4180bl }, + 0 }, + /* 61 << 120 */ + { { 0x689bb1ec107bb59fl,0x8129702adad2b385l,0x10bd3baeb1630603l, + 0xaadec5d15f23e7cfl }, + { 0x572f234f4586f7fbl,0x13abdec95ec11b32l,0xa462a7ec6191c26al, + 0x4a7d92a06685c8d3l }, + 0 }, + /* 63 << 120 */ + { { 0xdd4e2b63b16628eal,0xdf0c8fc8eefa5e86l,0xb0ec710205662720l, + 0x3f4c6956fe81e9dal }, + { 0x5732ad8f52e356f7l,0x045a103968a658f0l,0x9c40b0b6506ba33al, + 0x0a426010cb54258dl }, + 0 }, + /* 64 << 120 */ + { { 0x09891641d4c5105fl,0x1ae80f8e6d7fbd65l,0x9d67225fbee6bdb0l, + 0x3b433b597fc4d860l }, + { 0x44e66db693e85638l,0xf7b59252e3e9862fl,0xdb785157665c32ecl, + 0x702fefd7ae362f50l }, + 0 }, + /* 65 << 120 */ + { { 0x3902ab14c3254641l,0xa63cfd9fd8c001c8l,0x597d155c52d0af3cl, + 0xc5a2cbc4a0dbe688l }, + { 0xac8a841b249195aal,0xc98f01aaed14426fl,0xeb4a8ce8353905f1l, + 0x4d6668171ecee1b7l }, + 0 }, + /* 71 << 120 */ + { { 0xbd66e7d9a94da8cdl,0x7bc04735801ef314l,0x90f3eba1c5cc2904l, + 0x3c7dfed6f71bb36dl }, + { 0x89a50c8da75e3086l,0x88b8b4746f8e3418l,0x26fe17f4a44a5dbdl, + 0x98bf74c16a1e24fel }, + 0 }, + /* 77 << 120 */ + { { 0xca7b470679e0db85l,0x7f46c7716fc897fdl,0x9537e7918edfc0f3l, + 0xa46d4b4405e91ddfl }, + { 0x97d21061ee5575e7l,0x1f4f32da59650429l,0x2d1d6af878995129l, + 0x41d6fc228a0e4260l }, + 0 }, + /* 83 << 120 */ + { { 0xb30a1a89107d2282l,0x5433d7673a5e1323l,0xb9eeab822abdfeafl, + 0x9579cb46df3e0dbfl }, + { 0x6fc3ff2c7e088e79l,0x94b32360d7314326l,0xd2e82b59e5ad82e4l, + 0x7372dc4a55bc24e3l }, + 0 }, + /* 89 << 120 */ + { { 0x355697215f3c03cbl,0x4150adf2a146edcdl,0x16ec1a421a252e1cl, + 0xdf4d0f94424984eal }, + { 0x15142b5f5fabe961l,0xe6a73c29567ec13al,0xe6d370795d12070al, + 0x437743d0206fd7c6l }, + 0 }, + /* 95 << 120 */ + { { 0x483b7a95d66bc594l,0xf6a7064e8a6113bbl,0x373ce20f4ed34f72l, + 0x6aa876ab24f429b2l }, + { 0x378d5c25412c3102l,0xe4219a97b493199cl,0x01c7cafaa0b37332l, + 0x9305cc85f7633f7dl }, + 0 }, + /* 101 << 120 */ + { { 0x0259b43aaadf2273l,0x869c5bd3cf9dc1c2l,0x4f18a6e4068d6628l, + 0xd110637fec2d4547l }, + { 0x1ae88a791e94aaddl,0xe8b4be39de64f5f9l,0x85cbd9b24dc6b2bbl, + 0xb65091fa1bc352b2l }, + 0 }, + /* 107 << 120 */ + { { 0x7c5cea5d20f6a354l,0xe936ff1582f3ed39l,0x54e7a775b779368el, + 0x8ca8a46e3cb17c9el }, + { 0x753ca1fa0138974dl,0x9ce311eba72902ffl,0xcb727e56973f72b6l, + 0xde72538d91685710l }, + 0 }, + /* 113 << 120 */ + { { 0xf423569f1bec8f85l,0x23376da5ca844ac4l,0xce7b407a111523f4l, + 0x736fb92dde7aa46dl }, + { 0xd9139edcc7662640l,0x520fbf0656a85e24l,0x14e3b5857e5284b5l, + 0xcbae4e8321d56ef3l }, + 0 }, + /* 116 << 120 */ + { { 0x69830a05564470a1l,0x1a1e26cf5b702e8el,0xe5fdf7d9d8fae645l, + 0xe4774f74a9950c66l }, + { 0x18bdda7cd1466825l,0xe6ab4ce6d115218al,0xfcb8c50064528629l, + 0xd705f429e70deed9l }, + 0 }, + /* 119 << 120 */ + { { 0x3f992d7ba99df096l,0x08993b4125e78725l,0x79eaad13117c4cafl, + 0x7230594c9fa87285l }, + { 0xac23d7edf2673e27l,0xc9d76fb53b9eb111l,0x7a0a036a9e9db78al, + 0x7c6ec39df9565cffl }, + 0 }, + /* 125 << 120 */ + { { 0x956ad1441fd4f7a1l,0x6c511ffecb7546cal,0x11becdaef5ae6ddbl, + 0x67587741946168b2l }, + { 0x99cd45edf54379a7l,0x687f8462e2748decl,0x2b2be1e1837bd066l, + 0x3862659c0c45a5a9l }, + 0 }, + }, + { + /* 0 << 128 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 128 */ + { { 0x62a8c244bfe20925l,0x91c19ac38fdce867l,0x5a96a5d5dd387063l, + 0x61d587d421d324f6l }, + { 0xe87673a2a37173eal,0x2384800853778b65l,0x10f8441e05bab43el, + 0xfa11fe124621efbel }, + 0 }, + /* 3 << 128 */ + { { 0xc0f734a3b2335834l,0x9526205a90ef6860l,0xcb8be71704e2bb0dl, + 0x2418871e02f383fal }, + { 0xd71776814082c157l,0xcc914ad029c20073l,0xf186c1ebe587e728l, + 0x6fdb3c2261bcd5fdl }, + 0 }, + /* 4 << 128 */ + { { 0xb4480f0441c23fa3l,0xb4712eb0c1989a2el,0x3ccbba0f93a29ca7l, + 0x6e205c14d619428cl }, + { 0x90db7957b3641686l,0x0432691d45ac8b4el,0x07a759acf64e0350l, + 0x0514d89c9c972517l }, + 0 }, + /* 5 << 128 */ + { { 0xcc7c4c1c2cf9d7c1l,0x1320886aee95e5abl,0xbb7b9056beae170cl, + 0xc8a5b250dbc0d662l }, + { 0x4ed81432c11d2303l,0x7da669121f03769fl,0x3ac7a5fd84539828l, + 0x14dada943bccdd02l }, + 0 }, + /* 7 << 128 */ + { { 0x51b90651cbae2f70l,0xefc4bc0593aaa8ebl,0x8ecd8689dd1df499l, + 0x1aee99a822f367a5l }, + { 0x95d485b9ae8274c5l,0x6c14d4457d30b39cl,0xbafea90bbcc1ef81l, + 0x7c5f317aa459a2edl }, + 0 }, + /* 9 << 128 */ + { { 0x410dc6a90deeaf52l,0xb003fb024c641c15l,0x1384978c5bc504c4l, + 0x37640487864a6a77l }, + { 0x05991bc6222a77dal,0x62260a575e47eb11l,0xc7af6613f21b432cl, + 0x22f3acc9ab4953e9l }, + 0 }, + /* 10 << 128 */ + { { 0x27c8919240be34e8l,0xc7162b3791907f35l,0x90188ec1a956702bl, + 0xca132f7ddf93769cl }, + { 0x3ece44f90e2025b4l,0x67aaec690c62f14cl,0xad74141822e3cc11l, + 0xcf9b75c37ff9a50el }, + 0 }, + /* 11 << 128 */ + { { 0x0d0942770c24efc8l,0x0349fd04bef737a4l,0x6d1c9dd2514cdd28l, + 0x29c135ff30da9521l }, + { 0xea6e4508f78b0b6fl,0x176f5dd2678c143cl,0x081484184be21e65l, + 0x27f7525ce7df38c4l }, + 0 }, + /* 13 << 128 */ + { { 0x9faaccf5e4652f1dl,0xbd6fdd2ad56157b2l,0xa4f4fb1f6261ec50l, + 0x244e55ad476bcd52l }, + { 0x881c9305047d320bl,0x1ca983d56181263fl,0x354e9a44278fb8eel, + 0xad2dbc0f396e4964l }, + 0 }, + /* 15 << 128 */ + { { 0xfce0176788a2ffe4l,0xdc506a3528e169a5l,0x0ea108617af9c93al, + 0x1ed2436103fa0e08l }, + { 0x96eaaa92a3d694e7l,0xc0f43b4def50bc74l,0xce6aa58c64114db4l, + 0x8218e8ea7c000fd4l }, + 0 }, + /* 16 << 128 */ + { { 0x6a7091c2e48fb889l,0x26882c137b8a9d06l,0xa24986631b82a0e2l, + 0x844ed7363518152dl }, + { 0x282f476fd86e27c7l,0xa04edaca04afefdcl,0x8b256ebc6119e34dl, + 0x56a413e90787d78bl }, + 0 }, + /* 17 << 128 */ + { { 0xd1ffd160deb58b9bl,0x78492428c007273cl,0x47c908048ef06073l, + 0x746cd0dfe48c659el }, + { 0xbd7e8e109d47055bl,0xe070967e39711c04l,0x3d8869c99c9444f6l, + 0x6c67ccc834ac85fcl }, + 0 }, + /* 19 << 128 */ + { { 0x8a42d8b087b05be1l,0xef00df8d3e4e1456l,0x148cc8e8fbfc8cd2l, + 0x0288ae4c4878804fl }, + { 0x44e669a73b4f6872l,0xa4a8dbd4aab53c5bl,0x843fa963c9660052l, + 0x128e2d2571c05dd2l }, + 0 }, + /* 21 << 128 */ + { { 0x3ea86174a9f1b59bl,0xc747ea076a9a8845l,0x733710b5ab242123l, + 0x6381b546d386a60cl }, + { 0xba0e286366a44904l,0x770f618de9db556cl,0x39e567f828fb198dl, + 0xb5f1bef040147ee8l }, + 0 }, + /* 23 << 128 */ + { { 0x1adee1d516391617l,0x962d9184a3315fd9l,0x91c229750c805d59l, + 0x4575eaf2cd9a1877l }, + { 0x83fef163451831b9l,0x829d6bdd6f09e30fl,0x9379272dcc6b4e6al, + 0xd7a049bd95fbee4al }, + 0 }, + /* 25 << 128 */ + { { 0x695f70da44ae09c6l,0x79793892bb99de1dl,0xde269352f696b429l, + 0xe37ea97f8104c825l }, + { 0x3166cac6b0e72e63l,0xa82e633ca03ba670l,0x1106e3843e505667l, + 0xc2994f3dffb788b6l }, + 0 }, + /* 27 << 128 */ + { { 0xd36a5ab37c53073bl,0xc44a9940ebdc7e35l,0x7dd86c8bf3ded136l, + 0x9fe9879fd5a0eb14l }, + { 0xa210726c9b99bf9cl,0x3faf4456861036afl,0x1661f1c9615d091al, + 0x2c63f630911551bcl }, + 0 }, + /* 28 << 128 */ + { { 0x1554d46da670ff1dl,0x24833d88cb97a1ccl,0x8fa6ab3cded97493l, + 0x215e037189926498l }, + { 0x549bd592e56d74ffl,0x58a8caf543b5e1ecl,0x3c6087a323e93cb9l, + 0x8b0549875648b83cl }, + 0 }, + /* 29 << 128 */ + { { 0x232974230554f94fl,0x4f445a380f3a7618l,0xb9fb40bee4abefd6l, + 0xfbf3eaf9c15eb07cl }, + { 0xed469c23aca0c8b3l,0xc5209f68846e3f8fl,0x33d51d13d75da468l, + 0x9406e10a3d5c6e29l }, + 0 }, + /* 31 << 128 */ + { { 0xb9a44b1f5c6cad21l,0xaa9947751ee60a83l,0xc89af3858c390401l, + 0xef1e450b8dd51056l }, + { 0x5f5f069879ac84d1l,0x68d82982ef57b1afl,0x31f1d90f50849555l, + 0xff9577e57d9fc8f6l }, + 0 }, + /* 33 << 128 */ + { { 0xaeebc5c0b430d6a1l,0x39b87a13dc3a9c04l,0xf0c445252db4a631l, + 0xe32d95482c66fcf6l }, + { 0x16f11bafb17849c4l,0xdd1c76615eca71f7l,0x4389ad2e32e6c944l, + 0x727c11a5889a06bbl }, + 0 }, + /* 34 << 128 */ + { { 0x38dd1ac021e5781al,0x578318dbfd019ee2l,0x096b677d5f88e574l, + 0xdbec82b216ad9f4fl }, + { 0x348debe23260e8d9l,0x9334126064dfcda1l,0xdc5fb34cefc8faael, + 0x5fa048beb4a6fc25l }, + 0 }, + /* 35 << 128 */ + { { 0xe18806fd60b3258cl,0xb7d2926b1364df47l,0xe208300fa107ce99l, + 0x8d2f29fe7918df0el }, + { 0x0b012d77a1244f4cl,0xf01076f4213a11cfl,0x8e623223181c559dl, + 0x9df196ee995a281dl }, + 0 }, + /* 36 << 128 */ + { { 0xc431a238013ff83bl,0x7c0018b2fad69d08l,0x99aeb52a4c9589eal, + 0x121f41ab9b1cf19fl }, + { 0x0cfbbcbaef0f5958l,0x8deb3aeb7be8fbdcl,0x12b954081f15aa31l, + 0x5acc09b34c0c06fdl }, + 0 }, + /* 37 << 128 */ + { { 0xfaa821383a721940l,0xdd70f54dd0008b83l,0x00decb507d32a52dl, + 0x04563529cdd87deal }, + { 0xb0e7e2a2db81643dl,0x445f4c383a6fef50l,0x5c0ef211df694ae1l, + 0xa5a8fead923d0f1cl }, + 0 }, + /* 39 << 128 */ + { { 0xbc0e08b0325b2601l,0xae9e4c6105815b7al,0x07f664faf944a4a1l, + 0x0ad19d29288f83b3l }, + { 0x8615cd677232c458l,0x98edff6e9038e7d1l,0x082e0c4395a4dfccl, + 0x336267afeceee00el }, + 0 }, + /* 40 << 128 */ + { { 0x775cbfa86d518ffbl,0xdecee1f6930f124bl,0x9a402804f5e81d0fl, + 0x0e8225c52a0eeb2fl }, + { 0x884a5d39fee9e867l,0x9540428ffb505454l,0xb2bf2e20107a70d1l, + 0xd9917c3ba010b2aal }, + 0 }, + /* 41 << 128 */ + { { 0xc88ad4452a29bfdel,0x3072ebfa998368b7l,0xa754cbf7f5384692l, + 0x85f7e16906b13146l }, + { 0x42a7095f6a549fbel,0xef44edf91f7f1f42l,0xbea2989737b0c863l, + 0x13b096d87a1e7fc3l }, + 0 }, + /* 43 << 128 */ + { { 0x51add77ce2a3a251l,0x840ca1384d8476adl,0x08d01d26f6096478l, + 0x10d501a532f1662bl }, + { 0xc8d63f811165a955l,0x587aa2e34095046al,0x759506c617af9000l, + 0xd6201fe4a32ab8d2l }, + 0 }, + /* 44 << 128 */ + { { 0xa98f42fa3d843d53l,0x33777cc613ef927al,0xc440cdbecb84ca74l, + 0x8c22f9631dc7c5ddl }, + { 0x4bc82b70c8d94708l,0x7e0b43fcc814364fl,0x286d4e2486f59b7el, + 0x1abc895e4d6bf4c4l }, + 0 }, + /* 45 << 128 */ + { { 0x7c52500cfc8c9bbdl,0x635563381534d9f7l,0xf55f38cbfd52c990l, + 0xc585ae85058f52e7l }, + { 0xb710a28bf9f19a01l,0x891861bdf0273ca4l,0x38a7aa2b034b0b7cl, + 0xa2ecead52a809fb1l }, + 0 }, + /* 46 << 128 */ + { { 0x3df614f1ec3ca8eal,0x6bb24e9f9505bc08l,0x23ba1afbf37ace22l, + 0x2e51b03b3463c261l }, + { 0x59a0fca9c39e6558l,0x819f271ca342ccd9l,0x0c913d54df7ac033l, + 0xba0f83de573257d3l }, + 0 }, + /* 47 << 128 */ + { { 0xdf62817ab3b32fbcl,0x616d74b0964670d4l,0xa37bc6270e26020bl, + 0xda46d655b7d40bdal }, + { 0x2840f155b5773f84l,0xbb633777897774b6l,0x59ff1df79a1ed3fal, + 0xf7011ee2bac571f9l }, + 0 }, + /* 48 << 128 */ + { { 0x38151e274d559d96l,0x4f18c0d3b8db6c01l,0x49a3aa836f9921afl, + 0xdbeab27b8c046029l }, + { 0x242b9eaa7040bf3bl,0x39c479e51614b091l,0x338ede2b0e4baf5dl, + 0x5bb192b7f0a53945l }, + 0 }, + /* 49 << 128 */ + { { 0xd612951861535bb0l,0xbf14364016f6a954l,0x3e0931eedde18024l, + 0x79d791c8139441c0l }, + { 0xba4fe7ecb67b8269l,0x7f30d848224b96c1l,0xa7e0a6abf0341068l, + 0x78db42c37198ea2dl }, + 0 }, + /* 51 << 128 */ + { { 0x13354044185ce776l,0x109a6e059ff0100cl,0xafa3b61b03144cb1l, + 0x4e4c814585265586l }, + { 0xa8dafd33edb35364l,0x6691781bfd2606bel,0x2e06a9786182f5ccl, + 0x588784ebe77faeecl }, + 0 }, + /* 52 << 128 */ + { { 0x896d572337e440d7l,0x685c5fd9ade23f68l,0xb5b1a26dc2c64918l, + 0xb9390e30dad6580cl }, + { 0x87911c4e7dee5b9bl,0xb90c5053deb04f6el,0x37b942a18f065aa6l, + 0x34acdf2a1ca0928dl }, + 0 }, + /* 53 << 128 */ + { { 0xc773f525606f8f04l,0x75ae4a4b41b0a5bbl,0xb2aa058eaf7df93cl, + 0xf15bea4feafed676l }, + { 0xd2967b236a3c4fd7l,0xa698628090e30e7fl,0xf1b5166d316418bdl, + 0x5748682e1c13cb29l }, + 0 }, + /* 55 << 128 */ + { { 0xe7b11babfff3605bl,0xdbce1b74cbac080fl,0xa0be39bd6535f082l, + 0x2b6501805f826684l }, + { 0xf90cea2400f5244fl,0xe279f2fadd244a1cl,0xd3fca77c9421c3ael, + 0xe66bc7ee81a5210al }, + 0 }, + /* 57 << 128 */ + { { 0x114085dac40c6461l,0xaf78cb47f47d41b8l,0x7a9ae851755b0adbl, + 0x8d2e8c66a0600b6dl }, + { 0x5fb19045389758c0l,0xfa6e2cdabe7c91b2l,0x6472a432663983a2l, + 0xc9370829e0e19363l }, + 0 }, + /* 59 << 128 */ + { { 0xd335856ec50bf2ffl,0x89b42295dfa708c2l,0x5dfb42241b201b4el, + 0x6c94d6b94eecbf9cl }, + { 0xabe5a47a7a634097l,0xf3d53b1643febecfl,0xff18619faca9846el, + 0x80ad8629a4066177l }, + 0 }, + /* 60 << 128 */ + { { 0x7872e34b3390ff23l,0x968ce4abde7d18efl,0x9b4a745e627fe7b1l, + 0x9607b0a0caff3e2al }, + { 0x1b05818eeb40e3a5l,0x6ac62204c0fa8d7al,0xb5b9058571ed4809l, + 0xb2432ef0f7cb65f2l }, + 0 }, + /* 61 << 128 */ + { { 0xc1203418f8a144b7l,0xb3413f808378f901l,0xf6badea161857095l, + 0xcd2816c2b2e93efel }, + { 0x6a8303ea174a0ee6l,0x98b62f29150b28b6l,0x68071bbc9c2a05b6l, + 0xcfcf41a39f00e36el }, + 0 }, + /* 63 << 128 */ + { { 0xcaf564f234d6bc29l,0x9e9a6507f3c8edb0l,0x2fb889edd4e5502el, + 0xb70d4ceb6cc9d8edl }, + { 0x0de25356b020f740l,0xa68d9263d11fe5e6l,0xe86400679d85dd77l, + 0xa95dfa7dec2c8c8dl }, + 0 }, + /* 64 << 128 */ + { { 0x715c9f973112795fl,0xe8244437984e6ee1l,0x55cb4858ecb66bcdl, + 0x7c136735abaffbeel }, + { 0x546615955dbec38el,0x51c0782c388ad153l,0x9ba4c53ac6e0952fl, + 0x27e6782a1b21dfa8l }, + 0 }, + /* 65 << 128 */ + { { 0x3f9bc63ece59397dl,0x3f0f98a93eaa6104l,0x2f82c37c002d9271l, + 0x6ac0495d4985353cl }, + { 0xbde52f629191527bl,0xa3a13fce475aa640l,0x1d71ae17ce673f89l, + 0x2b5cc61529120ec1l }, + 0 }, + /* 71 << 128 */ + { { 0xa0ab0f9924318c1cl,0x0cc5ca7da80ca60bl,0x24e27598abb965bal, + 0xc4863198b44d1351l }, + { 0x4d913783a28f04bel,0x404e78088cce8960l,0x2973b4e46286873el, + 0x7b6e0f3219f42b50l }, + 0 }, + /* 77 << 128 */ + { { 0x0091a786306a6349l,0x4640ceab2098622dl,0x9928022be8182233l, + 0xf261bee4514d0bedl }, + { 0x70cdcc44c5f64fedl,0x4e19fec4f9eb2dfel,0xd05bdc09058b0b69l, + 0x16f3007ed3bc6190l }, + 0 }, + /* 83 << 128 */ + { { 0x8f7f16957f136df1l,0x6d7547019b4f4215l,0xfb22d55eb4cc46a6l, + 0x0b53ef53a8563034l }, + { 0x8b105acc42bc9353l,0xe44c0a396079d59dl,0x78441fee35ee38ddl, + 0x87ad93e43dcc0119l }, + 0 }, + /* 89 << 128 */ + { { 0x98a1c55358d9f73al,0xaa0843f0540e2b91l,0x701f8831d0647459l, + 0xc4ae9d0484673005l }, + { 0x9c37bc9f30b3ea20l,0x24cb4e2dbcbfb2b2l,0x8513e6f313cbf070l, + 0x0c4db4334e76c79el }, + 0 }, + /* 95 << 128 */ + { { 0x882a2b9cbc8320b8l,0x16e9c11e3ad9e222l,0x24399ac19b23cb1dl, + 0x334c5496799a89c7l }, + { 0x72b6f9b8df3d774cl,0x42955bcbb11b6704l,0x3c4d6021ad2d4eafl, + 0x5416b309afe2b671l }, + 0 }, + /* 101 << 128 */ + { { 0x1bbe9e662bf7c2a6l,0x22a3a10ca4acfddbl,0x2424eaab46bae581l, + 0xebec1bbf40d6bdadl }, + { 0xd7e3fa1a5b012aedl,0xc0f82c23f1dc6204l,0x42787c82e319477dl, + 0xca1ae7a14cf57573l }, + 0 }, + /* 107 << 128 */ + { { 0x44b7d589d51bbde9l,0x15de755fd6a4cc98l,0x9b6ea8e582fb8e2el, + 0x9d9294f04332bc22l }, + { 0x53c6b2b7d1fa239al,0x286bf536693ca4f1l,0xc3fa754603c00f65l, + 0xc046713af49cdb48l }, + 0 }, + /* 113 << 128 */ + { { 0xe356f5f11d82d5d6l,0xa0346a73d035ca0cl,0x14c76adee1884448l, + 0xd8369bdd1c23dde9l }, + { 0x13017862fe025eafl,0x6b5ac5e9a76be1d7l,0x52d621a94933bb6el, + 0xb045b53baa8c1d3fl }, + 0 }, + /* 116 << 128 */ + { { 0x242da39e4e40466al,0xc03cb184ac322b07l,0x776b744f9aaa10bfl, + 0xb80d9f14fe7d4beal }, + { 0x75cd14308f9c4908l,0xa4e59ce9087b3d7al,0x3bbdce598cdca614l, + 0x58c57113bc1a5df1l }, + 0 }, + /* 119 << 128 */ + { { 0x2a70af1abd79d467l,0x68dc4f23f63e2b73l,0x4345572f1f67b23dl, + 0xc012b08f3a340718l }, + { 0x9458585cc963dbe2l,0x21d84032223a495cl,0x0d54a4ea0dc28159l, + 0xd9549e2c9b927dafl }, + 0 }, + /* 125 << 128 */ + { { 0xcd54ebd2d43c8cd2l,0x5ff4ded6a817b9f9l,0x6f59bc31245386d3l, + 0x65b67cb0a2077821l }, + { 0x36407956405ffa07l,0x723e0252d589f27al,0x052004b888e1239el, + 0x8e6d188d69fdf94dl }, + 0 }, + }, + { + /* 0 << 136 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 136 */ + { { 0xc16c236e846e364fl,0x7f33527cdea50ca0l,0xc48107750926b86dl, + 0x6c2a36090598e70cl }, + { 0xa6755e52f024e924l,0xe0fa07a49db4afcal,0x15c3ce7d66831790l, + 0x5b4ef350a6cbb0d6l }, + 0 }, + /* 3 << 136 */ + { { 0xe2a37598a9d82abfl,0x5f188ccbe6c170f5l,0x816822005066b087l, + 0xda22c212c7155adal }, + { 0x151e5d3afbddb479l,0x4b606b846d715b99l,0x4a73b54bf997cb2el, + 0x9a1bfe433ecd8b66l }, + 0 }, + /* 4 << 136 */ + { { 0xe13122f3dbfb894el,0xbe9b79f6ce274b18l,0x85a49de5ca58aadfl, + 0x2495775811487351l }, + { 0x111def61bb939099l,0x1d6a974a26d13694l,0x4474b4ced3fc253bl, + 0x3a1485e64c5db15el }, + 0 }, + /* 5 << 136 */ + { { 0x5afddab61430c9abl,0x0bdd41d32238e997l,0xf0947430418042ael, + 0x71f9addacdddc4cbl }, + { 0x7090c016c52dd907l,0xd9bdf44d29e2047fl,0xe6f1fe801b1011a6l, + 0xb63accbcd9acdc78l }, + 0 }, + /* 7 << 136 */ + { { 0x0ad7337ac0b7eff3l,0x8552225ec5e48b3cl,0xe6f78b0c73f13a5fl, + 0x5e70062e82349cbel }, + { 0x6b8d5048e7073969l,0x392d2a29c33cb3d2l,0xee4f727c4ecaa20fl, + 0xa068c99e2ccde707l }, + 0 }, + /* 9 << 136 */ + { { 0x5b826fcb1b3ec67bl,0xece1b4b041356616l,0x7d5ce77e56a3ab4fl, + 0xf6087f13aa212da0l }, + { 0xe63015054db92129l,0xb8ae4c9940407d11l,0x2b6de222dfab8385l, + 0x9b323022b7d6c3b4l }, + 0 }, + /* 10 << 136 */ + { { 0x057ef17a5ae6ad84l,0x9feae00b293a6ae0l,0xd18bb6c154266408l, + 0xd3d3e1209c8e8e48l }, + { 0xba8d4ca80e94fc8fl,0x80262ffc8a8ea0fel,0xac5b2855f71655fdl, + 0xa348f8fae9aced89l }, + 0 }, + /* 11 << 136 */ + { { 0x60684b69a5660af3l,0x69aad23b9066d14bl,0x4d9f9b49fa4d020al, + 0xafb54ec1b5cd6a4al }, + { 0x2b25fe1832fd864dl,0xee6945062b6b64d0l,0x954a2a515001d8aal, + 0x5e1008557082b5b3l }, + 0 }, + /* 13 << 136 */ + { { 0x20ecf71cbc90eb1bl,0x4234facf651c1df4l,0xc720fce9e681f678l, + 0x680becdda7c007f4l }, + { 0x7c08dc063181afeal,0x75c1b050a34eca91l,0x7d3479d54b9e2333l, + 0xed16640af3951aa3l }, + 0 }, + /* 15 << 136 */ + { { 0x911b596264723e54l,0x34384f8c004b327cl,0x06ca5c61b85435f2l, + 0x12e0cd25e2c1075cl }, + { 0xa4b84cb8ac727394l,0x50bd720492b352c1l,0xe85524a49cbd0fb4l, + 0x10b9274be7876024l }, + 0 }, + /* 16 << 136 */ + { { 0xef0a3fecfa181e69l,0x9ea02f8130d69a98l,0xb2e9cf8e66eab95dl, + 0x520f2beb24720021l }, + { 0x621c540a1df84361l,0x1203772171fa6d5dl,0x6e3c7b510ff5f6ffl, + 0x817a069babb2bef3l }, + 0 }, + /* 17 << 136 */ + { { 0xb7cf93c3aace2c6al,0x017a96e658ff1bbfl,0x3b401301624a8250l, + 0xf5ef158529266518l }, + { 0x3c968bef7585838dl,0x8e97d023853191abl,0x175022e4f6823389l, + 0xb6a3bfc2f6a9b4c1l }, + 0 }, + /* 19 << 136 */ + { { 0x515acf174591d77el,0xb393c89e3c3b25b6l,0x291e068e9c95abd7l, + 0x256b72c046c02544l }, + { 0x8172af03915ea92fl,0xc1b324ae4fcd0f03l,0x8abc779215108993l, + 0xe05fe6867ab815ael }, + 0 }, + /* 21 << 136 */ + { { 0xca08d4095bc42740l,0xdd2c19d3e26e2e60l,0x27afdeded7c091fal, + 0x3b943b0faf25cb22l }, + { 0x400af8be026047e9l,0x3149b35f772b8ff9l,0x3ddb2c06f17229d9l, + 0xcd604aeadac152fcl }, + 0 }, + /* 23 << 136 */ + { { 0xea2275311c0f6803l,0x9ae82d5ea394cc08l,0xc107a2cfbe32080cl, + 0x550f35a76429f6d7l }, + { 0x483c94dacfb70c0cl,0xf26f8e5d90190c94l,0x8574b3cf86bf2620l, + 0xe7258e45df9f482fl }, + 0 }, + /* 25 << 136 */ + { { 0x8f8dc582da46f1cfl,0x61d76cf91e1e7427l,0x8aceb48b306c84aal, + 0xecaa142f28ebff98l }, + { 0xac5bd940401d80fel,0x0caacb8fe800cf9el,0x99068da9b3359af5l, + 0x92fdd5795225b8c0l }, + 0 }, + /* 27 << 136 */ + { { 0x5a29d1c5ab56a3fbl,0x4e46ffc0a9aab4afl,0xa210472624d83080l, + 0xb5820998007f08b6l }, + { 0x9ce1188e4bc07b3el,0xbf6d0dbe32a19898l,0x5d5c68ea5b2350bal, + 0xd6c794eb3aa20b45l }, + 0 }, + /* 28 << 136 */ + { { 0x3de605ba9ec598cfl,0x1933d3ae4d3029ael,0x6bf2fabd9b140516l, + 0x712dfc5559a7d01cl }, + { 0xff3eaae0d2576366l,0x36e407f948701cf8l,0xede21d89b41f4bd4l, + 0xc5292f5c666eefa9l }, + 0 }, + /* 29 << 136 */ + { { 0x30045782c3ebcd77l,0xaa0cf3c73fdbe72el,0x719ec58ef8f43b39l, + 0x9716fb9972574d3al }, + { 0x300afc2b0d03ccd6l,0xb60016a34f3fac41l,0x8898910ea3a439f6l, + 0xdc00a99707ca11f5l }, + 0 }, + /* 31 << 136 */ + { { 0x291b15ee8ed34662l,0xb780d54b2ee422a7l,0x5b9e3788fcfe4ccbl, + 0x4554cb8cbe8b7c3al }, + { 0xfdaccc2209a85a7fl,0x51f4a8ec555497edl,0x07dc69037da33505l, + 0xa3bc8bfcbc1fc1dbl }, + 0 }, + /* 33 << 136 */ + { { 0x661638c151e25257l,0x0a6fd99c53304974l,0x29d8ae165078eec6l, + 0xed7512ad447b73del }, + { 0x0e21de607a4d0e9bl,0x842abd422462be01l,0x3be82afa5cddc709l, + 0x25bb9da99b52797dl }, + 0 }, + /* 34 << 136 */ + { { 0x80613af28adc986al,0x4602284935776a41l,0x17d33e0f4665d03cl, + 0xeb12eb6c0df12b50l }, + { 0x0f0effa0ee41527fl,0x8ca2edb680531563l,0x4c354679f28c52c3l, + 0x67f1ba5c2f6df66dl }, + 0 }, + /* 35 << 136 */ + { { 0x9c27207a2479fb3fl,0xef6e0f13515fb902l,0x3f7ad9e9d0d9436el, + 0x36eb4ea5893bbcf5l }, + { 0x5c53a2ac02b316b7l,0x10c75ee1f54f7585l,0x29e5879c3c7a4c1bl, + 0x77da3c82f29c67d6l }, + 0 }, + /* 36 << 136 */ + { { 0xf2b75d21ef78a852l,0xba38cd34dd31a900l,0x72b3a68658ffe18al, + 0x7464190cbfd95745l }, + { 0x406e532177ed6e81l,0x1af0975bde535eabl,0x66ba22c760c54c82l, + 0x88e3b1ceb00a2fe0l }, + 0 }, + /* 37 << 136 */ + { { 0xb6099b7df7e5c69bl,0x84aa1e26ba34ee2fl,0x5952600405c338bbl, + 0xe9a134374951a539l }, + { 0xb12276526ec196bdl,0x26a7be264b6dce36l,0x052e10a4e2a68458l, + 0x475fc74c1f38898bl }, + 0 }, + /* 39 << 136 */ + { { 0x120167fc0a3eb4e1l,0xaa94bc70c0c21204l,0x313cd835e1243b75l, + 0x3bb63fb20bfd6a4al }, + { 0xa615dcae21ef05cfl,0x63774c2ec23c3ee5l,0x39365b1fed0dfd65l, + 0xb610e6ff5d2a2d7dl }, + 0 }, + /* 40 << 136 */ + { { 0x55b7f977f0337b15l,0x3bc872a30e94973al,0x624ad983770deea0l, + 0xcaab336413a5efdbl }, + { 0x391dd0027a0d4247l,0x39590d5df312aed5l,0x532802c9351365acl, + 0xdd2e824578a2e22al }, + 0 }, + /* 41 << 136 */ + { { 0x81b0d7be7f774fb8l,0x62f32bb3aa412425l,0xbe7afe26bbcd2162l, + 0xa6ce167c53c7fa7dl }, + { 0x8deca64fc5c4fc5bl,0x70e546aba6efd2fel,0xf2d8495987ff672al, + 0x2ca551f249c3059el }, + 0 }, + /* 43 << 136 */ + { { 0x40b62d528eb99155l,0xe6b048947420a7e0l,0x9ebecb2bc685e58al, + 0x3ea642d8d3c8d2cbl }, + { 0x5340ac6ed489d0dfl,0xf3846d08c2b7588el,0x4cecd8a0611c289bl, + 0xdddc39c50dd71421l }, + 0 }, + /* 44 << 136 */ + { { 0x98c6a6a52ebee687l,0xcdf65bfa56c1c731l,0x48e8132772def210l, + 0x4ea119418083b5a5l }, + { 0x3fdcea4fffebb525l,0x55aaea19fb50bf72l,0x5fbedc0a2a85b40cl, + 0x0d6fd954bf44f29fl }, + 0 }, + /* 45 << 136 */ + { { 0x83a8302a9db4071el,0x52f104436f8ae934l,0x96de829d175b800al, + 0x20ff5035373e97cel }, + { 0xf58660185f65356al,0x992c15054c8cd782l,0x0b962c8eb57d727fl, + 0xe8a9abc92bba8bc7l }, + 0 }, + /* 46 << 136 */ + { { 0x81a85ddd7cf2b565l,0x5e51e6afc34a0305l,0xa8d94ccefbc89faal, + 0x2bfd97c1e68cd288l }, + { 0x16d79c21af2958b8l,0x5e5d989defda7df8l,0x6d2f0ca6ff734c8al, + 0xfa5b8dd32cc9bafel }, + 0 }, + /* 47 << 136 */ + { { 0x5787a9934e6ed688l,0x6815f3b5aab42f46l,0x7960f45b093c6c66l, + 0xb2b9829728be10cfl }, + { 0x1d4c7790296568cdl,0xa279a877f048e194l,0xcf7c20f4c6a58b4el, + 0xf0c717afa1f9c00fl }, + 0 }, + /* 48 << 136 */ + { { 0x8a10b53189e800cal,0x50fe0c17145208fdl,0x9e43c0d3b714ba37l, + 0x427d200e34189accl }, + { 0x05dee24fe616e2c0l,0x9c25f4c8ee1854c1l,0x4d3222a58f342a73l, + 0x0807804fa027c952l }, + 0 }, + /* 49 << 136 */ + { { 0x79730084ba196afcl,0x17d38e98054bd539l,0xc5cfff3918583239l, + 0x4b0db5a2d9adbee6l }, + { 0x9bc9f1e3c2a304e8l,0xbaa61de7de406fa8l,0x8e921ca9e4bec498l, + 0xd9f4e5ae6604ab02l }, + 0 }, + /* 51 << 136 */ + { { 0xdf6b97b5b37f2097l,0x7576c3f9b4a5d2b9l,0x6eb697ed3588cabbl, + 0x4d75b38622598d8fl }, + { 0x4e6d93b522ff55e8l,0x4620ec635b8f7edal,0xd5006209f97b7749l, + 0x9e22e3a84da8b464l }, + 0 }, + /* 52 << 136 */ + { { 0xbabfb7f82e8f326fl,0xed9cac225625a519l,0xf1109c1a0edae0a9l, + 0x45f80a9858521259l }, + { 0x37a44b075ab71f44l,0x21699eb64a21161bl,0xb523fddf56fe67eel, + 0x9f5c3a2120b9f72el }, + 0 }, + /* 53 << 136 */ + { { 0x12c1131508b75673l,0xfa20121823b096d6l,0x839f01aeeacd6537l, + 0x0e592be787df32cal }, + { 0xfe3f65ff8b7dd0fcl,0xed09b4875c1d9a80l,0x8c09dd97b79786d8l, + 0x74eba2806c5bc983l }, + 0 }, + /* 55 << 136 */ + { { 0xf917704862987b50l,0xcc84cdc6bc4ac456l,0x8bd2c922ae08fe12l, + 0x09d5f661fc2d06c7l }, + { 0xd10ac6dd9457d47fl,0x65aa30a23668060cl,0x33cddac6745161fcl, + 0xf4c18b5ea51e540fl }, + 0 }, + /* 57 << 136 */ + { { 0x591c064ede723c1fl,0x92e5d4e601a4adael,0x3d7ee8a3145716ecl, + 0x0ef4c62061727816l }, + { 0x0e17c576f1bf6d6el,0x173104015ae18045l,0xdad620aae9589b75l, + 0xb10c7e2d0eda4905l }, + 0 }, + /* 59 << 136 */ + { { 0xb8020f16aa08df6fl,0x03cf58ffd67054e9l,0x302e003c11fe3d1al, + 0x9c194bc1c638a3ecl }, + { 0x8ed3cb3adefd3f1el,0xc4115e079bf39de4l,0x8dece48bdf46fdf6l, + 0xebd1dbcf30eafeafl }, + 0 }, + /* 60 << 136 */ + { { 0x058eb276fba319c5l,0xd33a91127f7fa54al,0xf060c1b4932a2dabl, + 0xce3a224e79c7d9bfl }, + { 0x6fb0388c0ba92823l,0x8d31738a69787881l,0x2d86eb0203cd00b7l, + 0x4e6e44512b69911bl }, + 0 }, + /* 61 << 136 */ + { { 0xff2efe1cfdcca1cfl,0x08f22c69b5bb71e3l,0xc63f4a9f7023076el, + 0x88fb2aa0ce0c490el }, + { 0xcc7c97f91f77783cl,0x360026d942ab36b7l,0x547c34ecefd68f70l, + 0xebe7f99efbabfdabl }, + 0 }, + /* 63 << 136 */ + { { 0xe7c1c1788613e87al,0xb035d65e60b82654l,0x055a82d03583a254l, + 0x27ce1ffc9b3b22fal }, + { 0x0cf904917ec83cd5l,0xfc6c21805604aa40l,0x1330604099357428l, + 0x9b0982f9ad4818b7l }, + 0 }, + /* 64 << 136 */ + { { 0xc222653a4f0d56f3l,0x961e4047ca28b805l,0x2c03f8b04a73434bl, + 0x4c966787ab712a19l }, + { 0xcc196c42864fee42l,0xc1be93da5b0ece5cl,0xa87d9f22c131c159l, + 0x2bb6d593dce45655l }, + 0 }, + /* 65 << 136 */ + { { 0x3a6080d9fb56bc3al,0xf1552dcad6212d7el,0x977ac5b59420f4f6l, + 0xef914d370e3cd97fl }, + { 0x807bd6e69c04f768l,0x743a7b552bb803f6l,0x7f5c20804215f4b0l, + 0x41e331288fc6ce42l }, + 0 }, + /* 71 << 136 */ + { { 0x5a31c9ac61e6a460l,0x55102e4093e7eeddl,0x969fe0612da6adcel, + 0xe8cddc2f3ffea1d9l }, + { 0xaa26c6b1f0f327c5l,0x9e5b63743544f5e1l,0x5159fa1ddbaa685bl, + 0x9892d03aa7f44b99l }, + 0 }, + /* 77 << 136 */ + { { 0x4dfcbf12e2c6fc1fl,0x703f2f5b7535ac29l,0x78f8617e82f7dc0fl, + 0x54b835ff853e792dl }, + { 0x3cc7f000df9f7353l,0x0d7ffd68db5a157al,0x2c1c33691672b21cl, + 0x694b4904ac970ef8l }, + 0 }, + /* 83 << 136 */ + { { 0xd655bc42c1d2c45cl,0x572f603cbd22b05fl,0xa7fbf09388e4531al, + 0x8d38bbd91fdde98dl }, + { 0x16cc2aaa73b0fa01l,0x515019a25e8ffb04l,0xb075990611e792ccl, + 0x89df06f399112c90l }, + 0 }, + /* 89 << 136 */ + { { 0x26d435c2481b46dal,0x73ab7e96266e9b3al,0x22d5b1db3c613c40l, + 0x9de4021c6727e399l }, + { 0x451ebba56051f8c9l,0xa37f6ec52c281a58l,0x3d7a28fe0e9f4cc5l, + 0x0f45bcd655b64df7l }, + 0 }, + /* 95 << 136 */ + { { 0xba2a718c66616fbel,0x4b27810b3369a9acl,0x50b8391a2b426d5fl, + 0x420c88efa626fa05l }, + { 0xe39cef97b9c39a30l,0xcae7cde85e67e5d0l,0x3821f8319a58e521l, + 0xbf474d1941479509l }, + 0 }, + /* 101 << 136 */ + { { 0x401bbab58fb15118l,0xb0376892dbf38b39l,0x10e4b9dd3a3ca42al, + 0xa69c2693f8063ffel }, + { 0xe10facdde07cb761l,0x96f4dde831d7759al,0xd702fdecc2cc7f9fl, + 0x9e87e46e1ac0162cl }, + 0 }, + /* 107 << 136 */ + { { 0xb6cd60518479ca8fl,0xcca345e60968f6c7l,0x7b57248a64a9afe7l, + 0x5552e3511d0d4db9l }, + { 0x8f749b199dc68aabl,0x0fb86f06db1f7819l,0x23b300963143ac09l, + 0x61c166d8abfbcb9bl }, + 0 }, + /* 113 << 136 */ + { { 0x4c96e85a43101165l,0x393a882fcf39bd19l,0xef9e1d42c2df6f33l, + 0xe1775c990278f088l }, + { 0xb1581929a9250d4al,0x582b0608c4168873l,0x0b3ffba3a1e68cd8l, + 0x3f78147ef9490897l }, + 0 }, + /* 116 << 136 */ + { { 0x277b5177eb18ff20l,0x48002e9828f06d62l,0xece8d6c30e506d8dl, + 0x5cde0a58cd9ff963l }, + { 0x3b97cdb74e3baa0el,0x50560c0b631238f9l,0xe1c31b35cf79793dl, + 0x95d12f14355e2178l }, + 0 }, + /* 119 << 136 */ + { { 0x0143f695bcc31b77l,0x3627aed14c49b65al,0x6e4f7a9ce441c183l, + 0xb708c79de1bfa0a3l }, + { 0xdbf0fc313a0726b8l,0xe04d82a8852d78bbl,0xb859001e3be5d398l, + 0x92dcc20c8e89bd11l }, + 0 }, + /* 125 << 136 */ + { { 0x5f2416a3df9026b4l,0xffc01f3afcb29a1bl,0x18d02c9f1d94b20fl, + 0xd93b0f2f81cfdef3l }, + { 0xe6b0fd4713adf5f2l,0xcc9067b7ba06dff3l,0xb48c0cbb2256f842l, + 0xc2ae741dfd34df2fl }, + 0 }, + }, + { + /* 0 << 144 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 144 */ + { { 0x80531fe1c63c4962l,0x50541e89981fdb25l,0xdc1291a1fd4c2b6bl, + 0xc0693a17a6df4fcal }, + { 0xb2c4604e0117f203l,0x245f19630a99b8d0l,0xaedc20aac6212c44l, + 0xb1ed4e56520f52a8l }, + 0 }, + /* 3 << 144 */ + { { 0x18f37a9c6bdf22dal,0xefbc432f90dc82dfl,0xc52cef8e5d703651l, + 0x82887ba0d99881a5l }, + { 0x7cec9ddab920ec1dl,0xd0d7e8c3ec3e8d3bl,0x445bc3954ca88747l, + 0xedeaa2e09fd53535l }, + 0 }, + /* 4 << 144 */ + { { 0xa12b384ece53c2d0l,0x779d897d5e4606dal,0xa53e47b073ec12b0l, + 0x462dbbba5756f1adl }, + { 0x69fe09f2cafe37b6l,0x273d1ebfecce2e17l,0x8ac1d5383cf607fdl, + 0x8035f7ff12e10c25l }, + 0 }, + /* 5 << 144 */ + { { 0xb7d4cc0f296c9005l,0x4b9094fa7b0aebdbl,0xe1bf10f1c00ec8d4l, + 0xd807b1c4d667c101l }, + { 0xa9412cdfbe713383l,0x435e063e81142ba1l,0x984c15ecaf0a6bdcl, + 0x592c246092a3dab9l }, + 0 }, + /* 7 << 144 */ + { { 0x9365690016e23e9dl,0xcb220c6ba7cc41e1l,0xb36b20c369d6245cl, + 0x2d63c348b62e9a6al }, + { 0xa3473e19cdc0bcb5l,0x70f18b3f8f601b98l,0x8ad7a2c7cde346e4l, + 0xae9f6ec3bd3aaa64l }, + 0 }, + /* 9 << 144 */ + { { 0x030223503274c7e1l,0x61ee8c934c4b6c26l,0x3c4397e3199389cel, + 0xe0082600488757cel }, + { 0xaac3a2df06b4dafbl,0x45af0700ddff5b6al,0x0a5974248c1d9fa0l, + 0x1640087d391fc68bl }, + 0 }, + /* 10 << 144 */ + { { 0x26a43e41d07fa53dl,0x3154a78a74e35bc5l,0x7b768924e0da2f8cl, + 0xba964a2b23613f9al }, + { 0x5a548d35ba1d16c4l,0x2e1bfed1fb54d057l,0xff992136bc640205l, + 0xf39cb9148156df29l }, + 0 }, + /* 11 << 144 */ + { { 0xf4873fcf4e5548bdl,0x8725da3f03ce57f0l,0xd82f5c95ca953258l, + 0xac647f127cf0747el }, + { 0xff2038b02d570bd5l,0xb0c2a767a13ae03fl,0xebaa27cde9932d16l, + 0xa686e3fc1234e901l }, + 0 }, + /* 13 << 144 */ + { { 0x9f80435e63261eccl,0x6302a62e4337d6c9l,0x91916a49ca4958a0l, + 0x554958993149d5d3l }, + { 0x378d020b9f91de3cl,0x47b839a34dd25170l,0x2825854138b7f258l, + 0xea5b14f7437e7decl }, + 0 }, + /* 15 << 144 */ + { { 0x74f08736b0018f44l,0xf4a03417b446d0f5l,0x66a4aa2fa40ca6b2l, + 0x215679f0badb60edl }, + { 0x3871195a323e4eefl,0x8f0940c320952b16l,0xfe8dac62879d5f7dl, + 0x649cb623c1a6e875l }, + 0 }, + /* 16 << 144 */ + { { 0xecaff541338d6e43l,0x56f7dd734541d5ccl,0xb5d426de96bc88cal, + 0x48d94f6b9ed3a2c3l }, + { 0x6354a3bb2ef8279cl,0xd575465b0b1867f2l,0xef99b0ff95225151l, + 0xf3e19d88f94500d8l }, + 0 }, + /* 17 << 144 */ + { { 0xa26a9087133ec108l,0x5dc5699f2712bdc0l,0x96903f4dd14224a9l, + 0x3da5992429e47b80l }, + { 0xb717712ff9dbba5al,0x9e52004b756391c9l,0xe669a11dcc9d219cl, + 0x3b6e6b84d1d6c07dl }, + 0 }, + /* 19 << 144 */ + { { 0x5feec06a676feadbl,0xfc449bc59d69f322l,0x1d8d7b5e7cda8895l, + 0x5ed54dc11a3314a7l }, + { 0x1a11d2ae6de889c0l,0xb2a979724ced2bd9l,0x6ecf6989306a5ef6l, + 0x1611d57b8cc8a249l }, + 0 }, + /* 21 << 144 */ + { { 0x2d9942ba007cbf87l,0x4e62bce6df3fc926l,0xe7eee5b0e4560affl, + 0xe51963bb7cb009b7l }, + { 0xaa5118cee29b37ddl,0x5cd84a4747263903l,0x3050caa6620055d8l, + 0x7ef576a76c4b1e3dl }, + 0 }, + /* 23 << 144 */ + { { 0x9026a4dde6008ff1l,0x49e995ad1c8cd96cl,0x80722e73503e589bl, + 0x05bcbce184c2bc26l }, + { 0x255f9abbd4682c2cl,0xc42bcfc2f084d456l,0xa0eae9b0641c0767l, + 0x1b45632d864c9a2dl }, + 0 }, + /* 25 << 144 */ + { { 0xcf25793b6ae024e0l,0x1b6607b484b5c4b0l,0x9579fa903f1624c8l, + 0x37fb65be68bd57e8l }, + { 0xd693a55efc39c203l,0x4e267ac4c87252e9l,0xb8d78bb09f899413l, + 0xe4c014070b3b8508l }, + 0 }, + /* 27 << 144 */ + { { 0x662906e5bc3f3553l,0xde38d53531459684l,0x8f46a8c634f7280dl, + 0xaaf91b873d24198el }, + { 0xecd5ee115f9b117el,0xce00ffbe50ae8ddal,0x263a3d4e7710a9ael, + 0x0ff3f721f26ba74fl }, + 0 }, + /* 28 << 144 */ + { { 0x4a8a4f47f0cefa69l,0xdc8e4cbaa4546866l,0x359ba69b23f603c1l, + 0xdab4d601187b7ac5l }, + { 0xa6ca4337c1ebc8d9l,0x9fa6585452b4074bl,0x1a4b4f81902fb733l, + 0xd2bb5d7aa525deaal }, + 0 }, + /* 29 << 144 */ + { { 0xcc287ac2e6b3577al,0xd7528ca7f612003bl,0x8afdb6f12c1400b8l, + 0x103a2ed346a2dd8dl }, + { 0xc8f8c54d2ee21339l,0x8f011b92355a2d20l,0x81c6fc9f1346f2acl, + 0xdb6042f005a6d24bl }, + 0 }, + /* 31 << 144 */ + { { 0xfc90e3630da4f996l,0x8ceca49daa6d6fe4l,0x1084affdbdfc619bl, + 0x2029f672c1140b04l }, + { 0x606ec25f136f3e5el,0x6d24149b02224c4al,0xabb0f142cfdfcf4cl, + 0xe40d0419fab1a0edl }, + 0 }, + /* 33 << 144 */ + { { 0xcfdd08265cbccb84l,0x2258a16e88ad93c4l,0xb3ac365e728c5ad3l, + 0x0bbf97808560df1fl }, + { 0x42d08a39bad8c7b8l,0x1e3960106d3e8b91l,0xc332b39910274f58l, + 0xe0a84dacce2ea778l }, + 0 }, + /* 34 << 144 */ + { { 0x113e1189ff432945l,0x4a0d2c3d04e1106cl,0xcde487744f3597b1l, + 0x853b029174fa26eal }, + { 0x2149e0ff02662e26l,0xb3181eaa5e6a030fl,0x086fc2159b006340l, + 0xa1df84a694a4e0bbl }, + 0 }, + /* 35 << 144 */ + { { 0xc2cbd80ac99f8d3dl,0xe24b9d8f50ecf4f4l,0xf18d34728ecb126al, + 0x83966662e1670aael }, + { 0x1cece80fda5f594el,0x545e94ae65f391e0l,0xf3286dff93f98bb7l, + 0xf945e6cdf5abf176l }, + 0 }, + /* 36 << 144 */ + { { 0x00ba5995dd95ac33l,0xa4957a40738f3bf4l,0x073539f599438a85l, + 0xcc9c43acc2eb1411l }, + { 0xe27501b5be2ec3d2l,0xa88d4ed057a85458l,0x870ae236755c8777l, + 0x0933c5af89216cbal }, + 0 }, + /* 37 << 144 */ + { { 0xb5feea219e40e37fl,0x8c5ccb159e20fd60l,0xaeddc502ce8209a1l, + 0xbdf873cc11e793b3l }, + { 0xbc938103f0de8db5l,0x619fb72fb0e9d3d5l,0x800147cb588ed2adl, + 0x260f92bb7901ced8l }, + 0 }, + /* 39 << 144 */ + { { 0x72dd9b089848c699l,0xc6086381185dacc1l,0x9489f11ff7d5a4c8l, + 0xedb41d5628dee90fl }, + { 0x1091db6b09af693cl,0xc7587551ae4b6413l,0x806aefb0768227adl, + 0x4214b83eafb3c88el }, + 0 }, + /* 40 << 144 */ + { { 0xddfb02c4c753c45fl,0x18ca81b6f9c840fel,0x846fd09ab0f8a3e6l, + 0xb1162adde7733dbcl }, + { 0x7070ad20236e3ab6l,0xf88cdaf5b2a56326l,0x05fc8719997cbc7al, + 0x442cd4524b665272l }, + 0 }, + /* 41 << 144 */ + { { 0x748819f9aa9c0ef5l,0xd7227d8ba458ad48l,0x8d67399f27aef626l, + 0xc6241a1859bf0a4cl }, + { 0xed9b0bfcc31cb9bbl,0x591254f896142555l,0x80e4bab461134151l, + 0x7c5e680243efbd83l }, + 0 }, + /* 43 << 144 */ + { { 0x7f3f5a1706b9b7ddl,0x392132e75faeb417l,0x508ac4788fae38a2l, + 0x2b854ead0d3499c3l }, + { 0x26a687d8ef18bf0fl,0x62ff0c4a8ae00b61l,0x84111011f48578f2l, + 0xa879f383cd0fcd3al }, + 0 }, + /* 44 << 144 */ + { { 0xeb7615aa202992f0l,0xde0562b38361d0b3l,0x789a302862027ee0l, + 0xe3e3e9921048f899l }, + { 0x07945c246deadab4l,0xeb06a15ec77d894el,0xb825af36bab1416bl, + 0x99083c4df4b4e04fl }, + 0 }, + /* 45 << 144 */ + { { 0x4684a8f27b3ad6c3l,0x58238dbd928d9b6bl,0x31865b998da2c495l, + 0xc1ca784fb8e7cda1l }, + { 0xc9605dc71e081572l,0x8f560bcdef8ed104l,0x51f73981bd3feaedl, + 0xc778aa4e4251c88dl }, + 0 }, + /* 46 << 144 */ + { { 0x9c0daa63aa502800l,0x73c7959a1e15b9bdl,0xd0447bcb7ab10f6cl, + 0x05b8fbc8b8311bdel }, + { 0xa8a74be1915d5c4el,0x38d41c1e0b7c0351l,0x5bb2d49ff52d6568l, + 0x6c48d8eed5e43593l }, + 0 }, + /* 47 << 144 */ + { { 0x387b26d554159498l,0x92e92fad1ec34eb4l,0x0f88705e7a51b635l, + 0x66bcbf4dedca735fl }, + { 0x0a4c6112dcb896ccl,0x148e1dfe6fc72ad9l,0x3de977fd2b4c9585l, + 0x0cd6e65f741e62cal }, + 0 }, + /* 48 << 144 */ + { { 0x7807f364b71698f5l,0x6ba418d29f7b605el,0xfd20b00fa03b2cbbl, + 0x883eca37da54386fl }, + { 0xff0be43ff3437f24l,0xe910b432a48bb33cl,0x4963a128329df765l, + 0xac1dd556be2fe6f7l }, + 0 }, + /* 49 << 144 */ + { { 0x98ae40d53ce533bal,0x10342e1931fdd9c2l,0x54a255c8abf8b2bfl, + 0x8facc41b15f6fef7l }, + { 0x2e195565bc65b38bl,0xb9f3abaaeaea63cbl,0xede2ab9bf2b7518bl, + 0x5e84102ce9ea3d81l }, + 0 }, + /* 51 << 144 */ + { { 0x162abc35113bc262l,0x8012f06829eb3fd4l,0x0e2727eb2c1ccf9cl, + 0x89561ff44b455b20l }, + { 0xc48db835ee3b1fd4l,0x4075ca86095bbfa7l,0x0c498d7d98745182l, + 0x828fb93c5dfb5205l }, + 0 }, + /* 52 << 144 */ + { { 0xf95c7a5f0a76333bl,0x07603929cd607927l,0xabde328591028d3el, + 0x55765e8fa032a400l }, + { 0x3041f2cabed17cd7l,0x018a5b7b9a9e5923l,0xca4867975bb9bae3l, + 0x741c802ecc382cb5l }, + 0 }, + /* 53 << 144 */ + { { 0x182a10311e5a3d8el,0xc352b8c8986c4d10l,0x7c50a172434c02ebl, + 0x121d728c4420c41cl }, + { 0x0f8eca2a8a51812fl,0xdb6c4a4ea5158430l,0x67944e0b8d8f4144l, + 0x387cc2052405c77al }, + 0 }, + /* 55 << 144 */ + { { 0x98b36eb47e95ad76l,0x1973fa7d5f7e5ff7l,0xc4827abc6cc8a25cl, + 0x4263a0d3ec822ae4l }, + { 0x49f113f35217a6f4l,0xf27cc9bb81748aa6l,0x9cb81d97d822e08el, + 0x698d2826b5c360bcl }, + 0 }, + /* 57 << 144 */ + { { 0x895f81514eb6d0b8l,0x32ef71df9f786536l,0x032a449430379a79l, + 0xa8c1076218bdb83fl }, + { 0x7a3b0b8fe53a4064l,0x0e724a54e2ce89b7l,0x565baeba7a31f6bcl, + 0x12b9fa6387d18a7bl }, + 0 }, + /* 59 << 144 */ + { { 0x027231a3585bcfbdl,0x8690e977dca24269l,0x229c021afc6f1422l, + 0xd98050d044084cabl }, + { 0x6add95d79d4fd09al,0x12484c68c15b24ddl,0xa79a8f4facf4f551l, + 0xf53204e27a83cbecl }, + 0 }, + /* 60 << 144 */ + { { 0xbc006413a906f7aal,0x9c8cd648bbeaf464l,0xaf5c7c64fb78cdf2l, + 0xe45839eafabc2375l }, + { 0x1eb89bd150012172l,0x9d0d76194488518cl,0xd55a7238bd534d32l, + 0x48f35d5e95b4fe55l }, + 0 }, + /* 61 << 144 */ + { { 0xa6c5574f3e70a35al,0x35c11b5a8df97d97l,0x8f629f6cda85dd27l, + 0x94dab294c218452el }, + { 0xa2e1882e8916c731l,0xc02ce77c8929e350l,0xa7ed351fe4eff8afl, + 0xeb76ef0654c3e1c1l }, + 0 }, + /* 63 << 144 */ + { { 0xc31d7cf87e3f5be5l,0x1472af0d3ce7f3a0l,0x226414f8f962e1afl, + 0xd318e3df16f54295l }, + { 0x9a3f6aaf41477cd3l,0x7034172f66ec6b2el,0xbea54eb537413a62l, + 0x79f81262dc515e73l }, + 0 }, + /* 64 << 144 */ + { { 0x994f523a626332d5l,0x7bc388335561bb44l,0x005ed4b03d845ea2l, + 0xd39d3ee1c2a1f08al }, + { 0x6561fdd3e7676b0dl,0x620e35fffb706017l,0x36ce424ff264f9a8l, + 0xc4c3419fda2681f7l }, + 0 }, + /* 65 << 144 */ + { { 0xb71a52b8b6bf8719l,0x0c7701f73196db36l,0xff1b936f53141cf4l, + 0x684d8a3c1b94a31cl }, + { 0xe555633ab52386e1l,0x9353a2af91450578l,0xc53db6fab99b14bcl, + 0x1f2d42adcf619d36l }, + 0 }, + /* 71 << 144 */ + { { 0xbeb535ef3851c573l,0x3105fff585589843l,0xbe9f62a1d47aaf06l, + 0x6bb2ee5d107e1131l }, + { 0x82530247a4a7699fl,0x3fb475e144872afbl,0x8ad43fd73c4c49f2l, + 0x3f7632882e045fc4l }, + 0 }, + /* 77 << 144 */ + { { 0x48440beb2924d7b2l,0x234163809c88fc57l,0xdc1d23d54ab08c2bl, + 0x576400b6e70feab0l }, + { 0x3b8afb8ba66da779l,0x7a7e3bf445468f16l,0x1976ddf3231f79dfl, + 0xbe61c170b8531a9el }, + 0 }, + /* 83 << 144 */ + { { 0xf8d2dc768bf191b2l,0x3269e68813a39eb9l,0x104bb84be755eccfl, + 0xb8d1330f2868f807l }, + { 0x2b29c74cb06c6059l,0x3648baa1a6440a26l,0x5dfae323f1e6b2c9l, + 0x9d0319b79330ac0al }, + 0 }, + /* 89 << 144 */ + { { 0x526ba3770e708bb2l,0x95c21ba327565dd9l,0x7071f46d48a0a873l, + 0xe4b9959efed6cc74l }, + { 0x1b16bfd1e08a5afal,0xc87fec98d1789782l,0x200186e946cfd068l, + 0x88ea35a7280bf3ebl }, + 0 }, + /* 95 << 144 */ + { { 0x9e31943d42ac0e6cl,0xe61374cf1db8e40fl,0xbe27ea35a27db609l, + 0x7c5b91d67bf192e9l }, + { 0xc2af846defd0a24bl,0x1b2efc37669b647al,0xbfc3c38e5e58ef8al, + 0xb6afb167e13ab5a2l }, + 0 }, + /* 101 << 144 */ + { { 0x08612d29b9f2aad4l,0x43c41330ad09dd17l,0xa45cb84a9f740519l, + 0x0a9ea9a7512ec031l }, + { 0x6e90dccaee747f35l,0xe4388bd1f0a1479bl,0x966140c4e20a9029l, + 0x1bb1f65d7dd956abl }, + 0 }, + /* 107 << 144 */ + { { 0x066d206ea8f12bb3l,0xc9023b1b4325ec13l,0x1f56c72c96ead8ddl, + 0x454050fd8003e4c2l }, + { 0x9ca258a58917aa9dl,0xfe24b282d94593cfl,0xea66c203752741cfl, + 0x5714268c295a895el }, + 0 }, + /* 113 << 144 */ + { { 0x72a9fbecc177d694l,0x38bb9387d68454d3l,0xa3d347bf590bc7d2l, + 0xcb6e292605ccc234l }, + { 0x588abfcf0d393c01l,0xf053dadf539e5568l,0xad7480fef2a8b157l, + 0xff28c8bb018cac8fl }, + 0 }, + /* 116 << 144 */ + { { 0x12f1a00e7f5b8821l,0x0afa44e489b4b0cel,0x2dcaad8f6006338el, + 0x79c022cdba41242bl }, + { 0x7f6ef7e17871d350l,0x946c2a91674253adl,0xf686d137a9cbbdd9l, + 0xa47ce2eaf7d4f9f2l }, + 0 }, + /* 119 << 144 */ + { { 0x1824991b205d40d6l,0x49cca1c085046a90l,0x7e23c1acd005e3c2l, + 0x093a9ae6d102c8ffl }, + { 0xf4791082d2f40843l,0xe456021811645483l,0x8a59c3b0fd3a6b39l, + 0x39130e7f820de158l }, + 0 }, + /* 125 << 144 */ + { { 0xf7eef88d83b90783l,0xff60762af336d581l,0xf64f2d5dd801f5a0l, + 0x672b6ee7d6b3b8b9l }, + { 0xa2a2dceb08034d69l,0x3eca27f635638218l,0xe7065986fa17fefdl, + 0xf1b74445f5803af1l }, + 0 }, + }, + { + /* 0 << 152 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 152 */ + { { 0x32670d2f7189e71fl,0xc64387485ecf91e7l,0x15758e57db757a21l, + 0x427d09f8290a9ce5l }, + { 0x846a308f38384a7al,0xaac3acb4b0732b99l,0x9e94100917845819l, + 0x95cba111a7ce5e03l }, + 0 }, + /* 3 << 152 */ + { { 0x37a01e48a105fc8el,0x769d754a289ba48cl,0xc08c6fe1d51c2180l, + 0xb032dd33b7bd1387l }, + { 0x953826db020b0aa6l,0x05137e800664c73cl,0xc66302c4660cf95dl, + 0x99004e11b2cef28al }, + 0 }, + /* 4 << 152 */ + { { 0x214bc9a7d298c241l,0xe3b697ba56807cfdl,0xef1c78024564eadbl, + 0xdde8cdcfb48149c5l }, + { 0x946bf0a75a4d2604l,0x27154d7f6c1538afl,0x95cc9230de5b1fccl, + 0xd88519e966864f82l }, + 0 }, + /* 5 << 152 */ + { { 0x1013e4f796ea6ca1l,0x567cdc2a1f792871l,0xadb728705c658d45l, + 0xf7c1ff4ace600e98l }, + { 0xa1ba86574b6cad39l,0x3d58d634ba20b428l,0xc0011cdea2e6fdfbl, + 0xa832367a7b18960dl }, + 0 }, + /* 7 << 152 */ + { { 0x1ecc032af416448dl,0x4a7e8c10ec76d971l,0x854f9805b90b6eael, + 0xfd0b15324bed0594l }, + { 0x89f71848d98b5ca3l,0xd01fe5fcf039b3efl,0x4481332e627bda2el, + 0xe67cecd7a5073e41l }, + 0 }, + /* 9 << 152 */ + { { 0x2ab0bce94595a859l,0x4d8c2da082084ee7l,0x21ff8be5acca3d3cl, + 0xd8b805337827f633l }, + { 0xf74e8c026becabbfl,0x9fae4dbefede4828l,0xd3885a5b3cc46bcfl, + 0x2d535e2b6e6ad144l }, + 0 }, + /* 10 << 152 */ + { { 0x63d3444507d9e240l,0x6fbadf4338cff7e6l,0x8717624a959c9461l, + 0xd7d951c411fb775bl }, + { 0x4049161af6fc3a2bl,0x0dfa2547a1a8e98dl,0xeca780d439c2139cl, + 0xd8c2d8cbd73ea8efl }, + 0 }, + /* 11 << 152 */ + { { 0x3aa1974f07605b28l,0x4f3d82a71e296255l,0xbbe5ea03b4e23f16l, + 0x8f5c6c6b4e654193l }, + { 0x27181182d3e8ab01l,0xc68bb231f3ba6bc2l,0x90a244d820af1fd7l, + 0x605abc055b713f4fl }, + 0 }, + /* 13 << 152 */ + { { 0xca5fe19bd221991al,0x271ff066f05f400el,0x9d46ec4c9cf09896l, + 0xdcaa8dfdec4febc3l }, + { 0xaa3995a0adf19d04l,0xc98634239da573a6l,0x378058b2f2465b2bl, + 0x20d389f9b4c31612l }, + 0 }, + /* 15 << 152 */ + { { 0xd7d199c7b7631c9dl,0x1322c2b8bb123942l,0xe662b68fbe8b6848l, + 0xc970faf2cde99b14l }, + { 0x61b27134b06655e5l,0xadcef8f781365d89l,0x917b5ab521b851aal, + 0x4f4472121cf694a7l }, + 0 }, + /* 16 << 152 */ + { { 0x488f1185ca8d9d1al,0xadf2c77dd987ded2l,0x5f3039f060c46124l, + 0xe5d70b7571e095f4l }, + { 0x82d586506260e70fl,0x39d75ea7f750d105l,0x8cf3d0b175bac364l, + 0xf3a7564d21d01329l }, + 0 }, + /* 17 << 152 */ + { { 0x241e3907fe44e547l,0x42d464c36b992187l,0xeaa8fa989ba72f28l, + 0x965a8b8f6afbb81fl }, + { 0x69356a7a8b375ea5l,0x22501ec741bdcc83l,0xf80f4e1445fb180cl, + 0xc0b12e95f5e1b822l }, + 0 }, + /* 19 << 152 */ + { { 0x977234e05483dc02l,0x0167430c13d8dcb2l,0xa9971278049912edl, + 0xab044b18ca40fa39l }, + { 0xac9587449ff3896cl,0x75bb32eb860d1240l,0xf807071f6b958654l, + 0x67d2d3dc7121b4b6l }, + 0 }, + /* 21 << 152 */ + { { 0x3b61e67722f9f017l,0x9c593eb1a8541696l,0xbeba950050eda653l, + 0x07b5a48f5e673f6al }, + { 0x748dca0013257aa3l,0x6bbddf9a7372e942l,0xc012f4badde83977l, + 0x6e59b327392ddb53l }, + 0 }, + /* 23 << 152 */ + { { 0xb2f3fff641356603l,0x50e63537545f042bl,0x55e5149770eb530dl, + 0x5a7383c310860c3bl }, + { 0x7be30382ea669a09l,0xfdf735d289cc1c7fl,0x6e51ed844e0607cfl, + 0xdab566df4893795el }, + 0 }, + /* 25 << 152 */ + { { 0x20e3be0f8920690dl,0x98db80eaac279c05l,0x4cd5c60a44b8a4f8l, + 0xeda7e91c7b0335f4l }, + { 0x45c1302a41ee5713l,0x1f6455fe588508d0l,0x82cb7311163d2fc3l, + 0xe866b90322f10b71l }, + 0 }, + /* 27 << 152 */ + { { 0xc217a2e259b4041el,0x85b96ce274526cbfl,0xcbfc4f5473f12687l, + 0x097caa5fd40225e7l }, + { 0x0871ad406e91293fl,0x5f2ea207033b98ecl,0x0b3b8fac1f27d37al, + 0x7d72dd4c7f03876cl }, + 0 }, + /* 28 << 152 */ + { { 0xb51a40a51e6a75c1l,0x24327c760ea7d817l,0x0663018207774597l, + 0xd6fdbec397fa7164l }, + { 0x20c99dfb13c90f48l,0xd6ac5273686ef263l,0xc6a50bdcfef64eebl, + 0xcd87b28186fdfc32l }, + 0 }, + /* 29 << 152 */ + { { 0x2f0c49ac95861439l,0xcdcb051b2e36e38al,0x459474080ae20c0cl, + 0x374baad2dddf0aabl }, + { 0x291abc85d5d104a4l,0x0758001958a0657cl,0xd0f428e1a905ea13l, + 0x12599ddcf7241dbfl }, + 0 }, + /* 31 << 152 */ + { { 0x16222ce81bc3c403l,0xbacc1508fc13ca02l,0xfa98db4d920ee8e9l, + 0xe5fc39c4df12a359l }, + { 0x4e8c9b90188733e8l,0x04283dd81394936cl,0x93b3db51cd130432l, + 0x33bfe3163c93ce31l }, + 0 }, + /* 33 << 152 */ + { { 0xb48591e9840b1724l,0x1009559f5885ec6fl,0x45ee51121b077620l, + 0x848f9800f1f4cc8al }, + { 0x6ec1e0f74e97bceal,0x953bc23a98e80642l,0x9f0d1e8194ce7181l, + 0xeb3e6b9700eec596l }, + 0 }, + /* 34 << 152 */ + { { 0x6d34b39bff7514dal,0x29ffe49825be3634l,0x63e56598f28c8b82l, + 0x78b99133aab41bcel }, + { 0x11febd5a52563180l,0xa3be94c5c356a8c0l,0x5e9b422e0d61f864l, + 0x2bf4ca1278fd259el }, + 0 }, + /* 35 << 152 */ + { { 0x8f60e40266914514l,0x6d9e280fef178167l,0x2ff7aec9e2949a48l, + 0x422389ce72d37511l }, + { 0xe9b156f3307ac1d2l,0x1cb581a78518e79fl,0x56d43f302185cf82l, + 0x8d46c5aade59562cl }, + 0 }, + /* 36 << 152 */ + { { 0x50fc0711745edc11l,0x9dd9ad7d3dc87558l,0xce6931fbb49d1e64l, + 0x6c77a0a2c98bd0f9l }, + { 0x62b9a6296baf7cb1l,0xcf065f91ccf72d22l,0x7203cce979639071l, + 0x09ae4885f9cb732fl }, + 0 }, + /* 37 << 152 */ + { { 0xd007d682e4b35428l,0x80c162315bcdc0d6l,0xe55a86bd36fce9b2l, + 0x16772edb969a87cfl }, + { 0xff323a2d3f370c94l,0x8d3c8028bf3c1afcl,0x4e1591e73b0c3fafl, + 0xfbd6475cb981ce83l }, + 0 }, + /* 39 << 152 */ + { { 0xcf414ae3315b2471l,0xf54abf8033168de6l,0x6883efc5df5cdb24l, + 0x3eca788c8efe81acl }, + { 0xdb58c6c778eeccadl,0x3c77939082fecfb7l,0x5736cdd9c9b513f3l, + 0xab7e6ea57b02aaf2l }, + 0 }, + /* 40 << 152 */ + { { 0x5e7c3becee8314f3l,0x1c068aeddbea298fl,0x08d381f17c80acecl, + 0x03b56be8e330495bl }, + { 0xaeffb8f29222882dl,0x95ff38f6c4af8bf7l,0x50e32d351fc57d8cl, + 0x6635be5217b444f0l }, + 0 }, + /* 41 << 152 */ + { { 0x2cec7ba64805d895l,0x4c8399870ac78e7cl,0x031ad6c7f79416c5l, + 0x1b2f2621f1838d2fl }, + { 0x60835eac91447f90l,0x59147af1f9bab5d9l,0x7a3005d6f393f175l, + 0x8cf3c468c4120ba2l }, + 0 }, + /* 43 << 152 */ + { { 0xeccffc7d8a2c1f08l,0x308916d37e384bd4l,0x6b8c2ff55e366384l, + 0xf4b2850d03e4747cl }, + { 0xe839c569e96c1488l,0xa46ff7f956c9cb10l,0xd968c74c362fd172l, + 0x2aa7fe4cad6bb601l }, + 0 }, + /* 44 << 152 */ + { { 0x04d15276a5177900l,0x4e1dbb47f6858752l,0x5b475622c615796cl, + 0xa6fa0387691867bfl }, + { 0xed7f5d562844c6d0l,0xc633cf9b03a2477dl,0xf6be5c402d3721d6l, + 0xaf312eb7e9fd68e6l }, + 0 }, + /* 45 << 152 */ + { { 0xf3b8164eec04c847l,0xa305ca93fe65816cl,0xa65f9963c7e2ce52l, + 0xc448005198882cfcl }, + { 0x46a998df05c165bbl,0xc38f4edf9dfe1e98l,0xb96ec43f8739f77al, + 0x10a23af9313b40bfl }, + 0 }, + /* 46 << 152 */ + { { 0xe476c3e3ee668e0cl,0xcec6a984478197c2l,0xc9fa1d68897147c1l, + 0x4e6aec0ea6465793l }, + { 0xedca9db76b219c3bl,0xa2cd57942e508d3bl,0x38b384663936e02al, + 0x0b8d3b4ca54ce90fl }, + 0 }, + /* 47 << 152 */ + { { 0x66e06537af08e0fcl,0x70fe0f2a907f1a93l,0x8c25245285ec1647l, + 0x0b8b2964d5560eddl }, + { 0xda45a326f3ef8e14l,0xf3adf9a6abc3494bl,0xbbdd93c11eda0d92l, + 0x1b5e12c609912773l }, + 0 }, + /* 48 << 152 */ + { { 0x242792d2e7417ce1l,0xff42bc71970ee7f5l,0x1ff4dc6d5c67a41el, + 0x77709b7b20882a58l }, + { 0x3554731dbe217f2cl,0x2af2a8cd5bb72177l,0x58eee769591dd059l, + 0xbb2930c94bba6477l }, + 0 }, + /* 49 << 152 */ + { { 0x5d9d507551d01848l,0x53dadb405b600d1el,0x7ba5b4dc5cb0a9a3l, + 0xdb85b04c6795e547l }, + { 0x480e7443f0354843l,0xc7efe6e813012322l,0x479b674a2aeee1e6l, + 0xf5481f19704f4ea3l }, + 0 }, + /* 51 << 152 */ + { { 0x76a38d6978c7816el,0xe020c87df84ec554l,0x99af2f78f9818010l, + 0x31cf103d988136eal }, + { 0x6b095a114816a5aal,0x5a4cd2a4eff0a4afl,0x543041a5892e5e04l, + 0x460f94c30aab9ee1l }, + 0 }, + /* 52 << 152 */ + { { 0x863ee0477d930cfcl,0x4c262ad1396fd1f4l,0xf4765bc8039af7e1l, + 0x2519834b5ba104f6l }, + { 0x7cd61b4cd105f961l,0xa5415da5d63bca54l,0x778280a088a1f17cl, + 0xc49689492329512cl }, + 0 }, + /* 53 << 152 */ + { { 0x282d92b48cd3948al,0x95d219dfe168205bl,0xf6111a6f87bf3abcl, + 0x910f8ce655fee9f2l }, + { 0xb6c806f74f71ac89l,0xd0cc300fb7235f73l,0xfe37ccb47d0d45bbl, + 0x5b2445f6952f0eaal }, + 0 }, + /* 55 << 152 */ + { { 0x03870be447141962l,0x8b79033f4a2b3f7fl,0xb6983b5ed2e5e274l, + 0x2a2f8018501ed99cl }, + { 0x07a92eb9feb49656l,0x063f0a9e482e2972l,0x413be27a57435832l, + 0x56363c5f6f9d3de1l }, + 0 }, + /* 57 << 152 */ + { { 0xd247153163b50214l,0x32b435eeb2b897del,0xc49f0b01b05df4del, + 0x97b6aa40b7df9b91l }, + { 0x58ff34ec8ec39d78l,0xab0889005e0114a3l,0x6872b4de4822b7b8l, + 0x7614c0d0ab239073l }, + 0 }, + /* 59 << 152 */ + { { 0x81891d378aa5d80al,0xf48ca24292e45f2cl,0xba711b6c0d04904cl, + 0x5992cda349f16ed6l }, + { 0x18b9a739790593eel,0x8b98e84dc4ba16d1l,0xac55701cb7b81615l, + 0xadb4533b15822291l }, + 0 }, + /* 60 << 152 */ + { { 0x6210db7181236c97l,0x74f7685b3ee0781fl,0x4df7da7ba3e41372l, + 0x2aae38b1b1a1553el }, + { 0x1688e222f6dd9d1bl,0x576954485b8b6487l,0x478d21274b2edeaal, + 0xb2818fa51e85956al }, + 0 }, + /* 61 << 152 */ + { { 0xc0677533f255ba8el,0x2bdae2a1efa2aabel,0xf7aebbd4b086c8a6l, + 0x148455d992cb1147l }, + { 0xa084e8d715402565l,0x33f111a8fa41bf23l,0x4bc990d627ac189bl, + 0x48dbe6569d505f76l }, + 0 }, + /* 63 << 152 */ + { { 0x59df7fab596766f3l,0x4cadcbfe604f26e4l,0x0cf199338a6af592l, + 0x3af1ace287b826c1l }, + { 0xf09a5b38ee60684el,0xa04cbeda4ed7c711l,0xdb28c42eb1731040l, + 0x75fcc0ec2e6e6523l }, + 0 }, + /* 64 << 152 */ + { { 0x1e6adddaf176f2c0l,0x01ca4604e2572658l,0x0a404ded85342ffbl, + 0x8cf60f96441838d6l }, + { 0x9bbc691cc9071c4al,0xfd58874434442803l,0x97101c85809c0d81l, + 0xa7fb754c8c456f7fl }, + 0 }, + /* 65 << 152 */ + { { 0x4374020072196f30l,0x59ed0dc0dcd6c935l,0x17d4ed8e5034161bl, + 0x8abe3e13009e7170l }, + { 0xe51c41c96c791456l,0xc671807704d72bb6l,0xd4309cf56bba424al, + 0x6122b951d0ca4ceal }, + 0 }, + /* 71 << 152 */ + { { 0xdfdb2e9c4278982bl,0xf3a282b32d6a2a61l,0x5611650cd2f2b03cl, + 0xa62c177f43f7f83al }, + { 0x372310ab4c593d32l,0x2bb6903a2b570f9cl,0x2930da3df43af904l, + 0x2bbd04aa2c8a5a7dl }, + 0 }, + /* 77 << 152 */ + { { 0x10c324c007e536del,0xc456836d377be1b4l,0x9a627d75d785af3fl, + 0xde74559118b58b31l }, + { 0xeac83ea60c47239al,0x35da24abbc02f670l,0x2d4abde0c3af6e63l, + 0xac53acba5a7ebf1bl }, + 0 }, + /* 83 << 152 */ + { { 0x2b03ec2efd9a9f3el,0xc967cd2b9d898a09l,0xb24bcba8039dc4f6l, + 0x0ea1d297061ada1el }, + { 0x3a7a25fbc134b8bcl,0x846282d6f61cd312l,0xfa1de0d2e0d778d9l, + 0xf75fad4ef09be264l }, + 0 }, + /* 89 << 152 */ + { { 0x7d35695bcf74afb3l,0x34d43d9f15bb36fbl,0x15f0b43960b45fbel, + 0xb15db8d84f38ec06l }, + { 0x93ce7d50f7da1406l,0x2db97edd9f076aaal,0x27ebb9aa354429dcl, + 0xf97eb5c446ace469l }, + 0 }, + /* 95 << 152 */ + { { 0x758fa2312dcf498fl,0xaa8c14d15cf3853al,0x416f5dab097d786al, + 0xceec00ef38f242a0l }, + { 0x2f8b10b9d8b75ef2l,0xee64912b2281be6al,0xa883481aa382a51el, + 0x9442300f61b16b8al }, + 0 }, + /* 101 << 152 */ + { { 0x80e7fbc4f4b171e1l,0xdd2246f5661564a4l,0xcf08d73cd00d4e54l, + 0xf725f5389fca9a30l }, + { 0xd9607358af20debel,0xa97c81e16f7d1cf2l,0x72794ae70dedfb2al, + 0xc328cb93159ff29dl }, + 0 }, + /* 107 << 152 */ + { { 0xaf9491d6252f6d59l,0x6744d7518feda60dl,0xa485f8aa34c5c048l, + 0x2ed794b4b50ea53bl }, + { 0x0da82650db26c289l,0xed3ab4c50904af55l,0x425eda1176544463l, + 0x917be5f48939b29bl }, + 0 }, + /* 113 << 152 */ + { { 0xa2e72d0f8e208e5dl,0x5a5e4344234a5fedl,0x6dcc56535005bee8l, + 0x09d0c254854e2e04l }, + { 0xade4bcdba82f0789l,0x5a3e3cd4ec460a91l,0x6b1a867be76695b2l, + 0xd1eb9df0a28b9331l }, + 0 }, + /* 116 << 152 */ + { { 0x3f5cf5f678e62ddcl,0x2267c45407fd752bl,0x5e361b6b5e437bbel, + 0x95c595018354e075l }, + { 0xec725f85f2b254d9l,0x844b617d2cb52b4el,0xed8554f5cf425fb5l, + 0xab67703e2af9f312l }, + 0 }, + /* 119 << 152 */ + { { 0x8dcc920005fb96bbl,0x29d2442470f84705l,0x540bb6e63f09628fl, + 0x07f8b4de2a9c2359l }, + { 0xb8e002d1957e41dcl,0x9a0fe82b9e683a3fl,0x996b1a5250e633fdl, + 0x748a11e500c669cal }, + 0 }, + /* 125 << 152 */ + { { 0x0593a788581dfd6el,0x99f1164f64e1b329l,0x1142c44b1defddbbl, + 0xbc95c9c7660b9036l }, + { 0xf24b5a47079179ccl,0x6175b52c21f7033bl,0x8b5d84183bc2eec0l, + 0xc1332c8272d12670l }, + 0 }, + }, + { + /* 0 << 160 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 160 */ + { { 0xd433e50f6d3549cfl,0x6f33696ffacd665el,0x695bfdacce11fcb4l, + 0x810ee252af7c9860l }, + { 0x65450fe17159bb2cl,0xf7dfbebe758b357bl,0x2b057e74d69fea72l, + 0xd485717a92731745l }, + 0 }, + /* 3 << 160 */ + { { 0x6c8d0aa9b898fd52l,0x2fb38a57be9af1a7l,0xe1f2b9a93b4f03f8l, + 0x2b1aad44c3f0cc6fl }, + { 0x58b5332e7cf2c084l,0x1c57d96f0367d26dl,0x2297eabdfa6e4a8dl, + 0x65a947ee4a0e2b6al }, + 0 }, + /* 4 << 160 */ + { { 0xaaafafb0285b9491l,0x01a0be881e4c705el,0xff1d4f5d2ad9caabl, + 0x6e349a4ac37a233fl }, + { 0xcf1c12464a1c6a16l,0xd99e6b6629383260l,0xea3d43665f6d5471l, + 0x36974d04ff8cc89bl }, + 0 }, + /* 5 << 160 */ + { { 0xf535b616fdd5b854l,0x592549c85728719fl,0xe231468606921cadl, + 0x98c8ce34311b1ef8l }, + { 0x28b937e7e9090b36l,0x67fc3ab90bf7bbb7l,0x12337097a9d87974l, + 0x3e5adca1f970e3fel }, + 0 }, + /* 7 << 160 */ + { { 0xcdcc68a7b3f85ff0l,0xacd21cdd1a888044l,0xb6719b2e05dbe894l, + 0xfae1d3d88b8260d4l }, + { 0xedfedece8a1c5d92l,0xbca01a94dc52077el,0xc085549c16dd13edl, + 0xdc5c3bae495ebaadl }, + 0 }, + /* 9 << 160 */ + { { 0xcc17063fbe7b643al,0x7872e1c846085760l,0x86b0fffbb4214c9el, + 0xb18bbc0e72bf3638l }, + { 0x8b17de0c722591c9l,0x1edeab1948c29e0cl,0x9fbfd98ef4304f20l, + 0x2d1dbb6b9c77ffb6l }, + 0 }, + /* 10 << 160 */ + { { 0xf53f2c658ead09f7l,0x1335e1d59780d14dl,0x69cc20e0cd1b66bcl, + 0x9b670a37bbe0bfc8l }, + { 0xce53dc8128efbeedl,0x0c74e77c8326a6e5l,0x3604e0d2b88e9a63l, + 0xbab38fca13dc2248l }, + 0 }, + /* 11 << 160 */ + { { 0x255616d3c7141771l,0xa86691ab2f226b66l,0xda19fea4b3ca63a9l, + 0xfc05dc42ae672f2bl }, + { 0xa9c6e786718ba28fl,0x07b7995b9c66b984l,0x0f434f551b3702f2l, + 0xd6f6212fda84eeffl }, + 0 }, + /* 13 << 160 */ + { { 0x4b0e7987b5b41d78l,0xea7df9074bf0c4f8l,0xb4d03560fab80ecdl, + 0x6cf306f6fb1db7e5l }, + { 0x0d59fb5689fd4773l,0xab254f4000f9be33l,0x18a09a9277352da4l, + 0xf81862f5641ea3efl }, + 0 }, + /* 15 << 160 */ + { { 0xb59b01579f759d01l,0xa2923d2f7eae4fdel,0x18327757690ba8c0l, + 0x4bf7e38b44f51443l }, + { 0xb6812563b413fc26l,0xedb7d36379e53b36l,0x4fa585c4c389f66dl, + 0x8e1adc3154bd3416l }, + 0 }, + /* 16 << 160 */ + { { 0xd3b3a13f1402b9d0l,0x573441c32c7bc863l,0x4b301ec4578c3e6el, + 0xc26fc9c40adaf57el }, + { 0x96e71bfd7493cea3l,0xd05d4b3f1af81456l,0xdaca2a8a6a8c608fl, + 0x53ef07f60725b276l }, + 0 }, + /* 17 << 160 */ + { { 0x971e9eedd5098497l,0x97692be63077d8a7l,0xb57e02ad79625a8al, + 0x5e3d20f6a688ecd5l }, + { 0xa4431a28188f964dl,0xd4eb23bd5a11c1dbl,0xfcda853eadc7446fl, + 0x9e2e98b593c94046l }, + 0 }, + /* 19 << 160 */ + { { 0x4a649b66eddaa4f1l,0x35a04f185e690c50l,0x1639bdcff908bc53l, + 0xce6d525c121726e8l }, + { 0x70f34948902b402cl,0x3a40c6950e290579l,0x7b0ed90f469a0085l, + 0xecb979c60189c501l }, + 0 }, + /* 21 << 160 */ + { { 0x847e2bde5cee8d07l,0x1bed198cd3340037l,0x439ffb3ce41586e3l, + 0x594980f1856f15b0l }, + { 0x22c3b86c6e9307c6l,0xf8b3ee08876382dbl,0x850c628e628f3f30l, + 0x22ec0acb51ee3659l }, + 0 }, + /* 23 << 160 */ + { { 0xa4052591efcef5a0l,0x82692a47106d55afl,0xdac3ea88e6ead453l, + 0xaa1368fcf3dfd875l }, + { 0x87bc688aa0c539eal,0x905e206040b1de3el,0x072240b8f1d52452l, + 0x3ebf0644d57b6580l }, + 0 }, + /* 25 << 160 */ + { { 0x12109bcc07a0b2f8l,0x336f87d2ca23f14cl,0xb39ae282452a2ea2l, + 0x8e085f5bab59a500l }, + { 0xf7daeb69b63f015cl,0x44c555bcacb47b38l,0x96190454b623910al, + 0x4b666e2255b41b70l }, + 0 }, + /* 27 << 160 */ + { { 0xf146914eb53419fdl,0xd2109b07493e88bfl,0x30bf9cbccc54bcd5l, + 0xcf9ea59750e34a1fl }, + { 0x70ade8a59588591dl,0xf668be676b41c269l,0x3497c58f78df2e6bl, + 0x0fad05cc71042b56l }, + 0 }, + /* 28 << 160 */ + { { 0x27f536e049ce89e7l,0x18908539cc890cb5l,0x308909abd83c2aa1l, + 0xecd3142b1ab73bd3l }, + { 0x6a85bf59b3f5ab84l,0x3c320a68f2bea4c6l,0xad8dc5386da4541fl, + 0xeaf34eb0b7c41186l }, + 0 }, + /* 29 << 160 */ + { { 0x709da836093aa5f6l,0x567a9becb4644edel,0xae02a46044466b0cl, + 0xc80b237a407f1b3bl }, + { 0x451df45ab4168a98l,0xdc9b40ef24a3f7c9l,0x23593ef32671341dl, + 0x40f4533190b90faal }, + 0 }, + /* 31 << 160 */ + { { 0x7f97768e922f36e3l,0x936943f8491034a2l,0x72f6c17f21483753l, + 0x5489fa0cb2918619l }, + { 0x55b31aa59cc21a46l,0xde4cc71a8e54ab14l,0x942cb8be9eaff8b0l, + 0xe38f6116d1755231l }, + 0 }, + /* 33 << 160 */ + { { 0xf0c0606a395b39abl,0x0efcbc699b5166a5l,0x85995e6895453d85l, + 0xadc9a2920806ee5cl }, + { 0xc3662e804928fe09l,0x2a2ddcc6969c87e7l,0xa02d7947111d319dl, + 0xde23bcf12d20f66dl }, + 0 }, + /* 34 << 160 */ + { { 0xc47cb3395f6d4a09l,0x6b4f355cee52b826l,0x3d100f5df51b930al, + 0xf4512fac9f668f69l }, + { 0x546781d5206c4c74l,0xd021d4d4cb4d2e48l,0x494a54c2ca085c2dl, + 0xf1dbaca4520850a8l }, + 0 }, + /* 35 << 160 */ + { { 0xb2d15b14a911cc2bl,0xab2dfaf7643e28eal,0xfccc9ed1f52c4c2dl, + 0xfb4b1d4a09d8faa3l }, + { 0x6fd72a9b7f5ce767l,0x0233c856a287e2b5l,0xd42135e05775ebb9l, + 0xb3c9dada7376568bl }, + 0 }, + /* 36 << 160 */ + { { 0x63c79326490a1acal,0xcb64dd9c41526b02l,0xbb772591a2979258l, + 0x3f58297048d97846l }, + { 0xd66b70d17c213ba7l,0xc28febb5e8a0ced4l,0x6b911831c10338c1l, + 0x0d54e389bf0126f3l }, + 0 }, + /* 37 << 160 */ + { { 0x5952996b5306af1bl,0x99f444f4354b67bel,0x6f670181633a2928l, + 0x289023f0e9bdc4a6l }, + { 0xcbed12148f7455a2l,0x501ace2f659a4858l,0x83ee678d5f8e1784l, + 0x95c984587335c5bdl }, + 0 }, + /* 39 << 160 */ + { { 0x2e25a1f3e0233000l,0xed0028cd44fe8ba9l,0x447501a6021d43b3l, + 0x4ec203906b4dffccl }, + { 0x50642f9ad0169740l,0x9360003373cc58adl,0x825f1a82fe9cf9acl, + 0x456194c653242bd6l }, + 0 }, + /* 40 << 160 */ + { { 0x40242efeb483689bl,0x2575d3f6513ac262l,0xf30037c80ca6db72l, + 0xc9fcce8298864be2l }, + { 0x84a112ff0149362dl,0x95e575821c4ae971l,0x1fa4b1a8945cf86cl, + 0x4525a7340b024a2fl }, + 0 }, + /* 41 << 160 */ + { { 0x83205e8f5db5e2b1l,0x94e7a2621e311c12l,0xe1cac7333e37068fl, + 0xe3f43f6d39965acfl }, + { 0xd28db9e854d905bal,0x686f372a101f2162l,0x409cfe5d3d1b46d4l, + 0x17648f1cbd0bb63al }, + 0 }, + /* 43 << 160 */ + { { 0xef83315b821f4ee4l,0xb90766998ba78b4dl,0xee6a15880fce5260l, + 0x828f4a72d754affbl }, + { 0x4650ec7daaae54d2l,0x3174301f1057efe9l,0x174e0683eb7704cel, + 0xb7e6aeb357eb0b14l }, + 0 }, + /* 44 << 160 */ + { { 0xcaead1c2c905d85fl,0xe9d7f7900733ae57l,0x24c9a65cf07cdd94l, + 0x7389359ca4b55931l }, + { 0xf58709b7367e45f7l,0x1f203067cb7e7adcl,0x82444bffc7b72818l, + 0x07303b35baac8033l }, + 0 }, + /* 45 << 160 */ + { { 0xd59528fb38a0dc96l,0x8179dc9088d0e857l,0x55e9ba039ed4b1afl, + 0x8a2c0dc787b74cacl }, + { 0xe8ca91aeef1c0006l,0x67f59ab2de0e15d4l,0xba0cddf86e6634d2l, + 0x352803657b7ba591l }, + 0 }, + /* 46 << 160 */ + { { 0x1e1ee4e4d13b7ea1l,0xe6489b24e0e74180l,0xa5f2c6107e70ef70l, + 0xa1655412bdd10894l }, + { 0x555ebefb7af4194el,0x533c1c3c8e89bd9cl,0x735b9b5789895856l, + 0x15fb3cd2567f5c15l }, + 0 }, + /* 47 << 160 */ + { { 0xef07bfedfb0986c7l,0xde138afe47c1659al,0x8b79c159a555e907l, + 0x21d572f1125518bbl }, + { 0x2005999ad320410cl,0x4167dc469484414bl,0x0cd965c34c6aaefdl, + 0x2a1abc9a0e1d5e9dl }, + 0 }, + /* 48 << 160 */ + { { 0x057fed45526f09fdl,0xe8a4f10c8128240al,0x9332efc4ff2bfd8dl, + 0x214e77a0bd35aa31l }, + { 0x32896d7314faa40el,0x767867ec01e5f186l,0xc9adf8f117a1813el, + 0xcb6cda7854741795l }, + 0 }, + /* 49 << 160 */ + { { 0xadfaf39b888dedf1l,0x4f8b178aab1750b9l,0x26418617ffe6b0eal, + 0x01d1be82af04a59fl }, + { 0x41584147e652db64l,0xf7775ac5727f9ea7l,0x58052a20e72ad8bbl, + 0x5badf0dc6021160el }, + 0 }, + /* 51 << 160 */ + { { 0x8490ea99183de59dl,0xc95f72146f5c6f8cl,0x89b55d15df00c334l, + 0x84386ad8a0ec36f7l }, + { 0x24dadaefe4dc1ed1l,0xc606ba4c1e717227l,0x7e4756c0bbfa62eal, + 0x3916cf14afc29cf3l }, + 0 }, + /* 52 << 160 */ + { { 0xb7b4d00101dae185l,0x45434e0b9b7a94bcl,0xf54339affbd8cb0bl, + 0xdcc4569ee98ef49el }, + { 0x7789318a09a51299l,0x81b4d206b2b025d8l,0xf64aa418fae85792l, + 0x3e50258facd7baf7l }, + 0 }, + /* 53 << 160 */ + { { 0x4152c508492d91f3l,0x59d6cf9c678f9db4l,0xb0a8c966404608d1l, + 0xdced55d0e3fed558l }, + { 0x0914a3cb33a76188l,0x79df212423d35d46l,0x2322507fca13b364l, + 0x0aed41d60078ab93l }, + 0 }, + /* 55 << 160 */ + { { 0x7acdaa7f6b2ebfc2l,0xb5ab1a9a80d9f67fl,0x53ba8173ff8aa8b0l, + 0x9cd85cf874ca56a6l }, + { 0xabac57f49c4fad81l,0x2325bb8521078995l,0xbac5e3a1b928a054l, + 0x7219047a2394cc2al }, + 0 }, + /* 57 << 160 */ + { { 0xa33410d2aa75fd37l,0x821093affc0f1192l,0xe45e85ed155e39a9l, + 0xd0e87cd12de67188l }, + { 0xdeca97d965d43d87l,0x8c73826f9d2c99ecl,0x1bfe111e33237ddbl, + 0xda32e865587bfb28l }, + 0 }, + /* 59 << 160 */ + { { 0xde456d92c89e9e4el,0xe45688a98e47f3cdl,0x3deacfca3bacbde0l, + 0xdf9b32efc9683a70l }, + { 0x749bc007e1691106l,0x788a05342a5154d7l,0x1a06baecf7c7b70dl, + 0xb5b608eeae6ffc4cl }, + 0 }, + /* 60 << 160 */ + { { 0x4cd296df5579bea4l,0x10e35ac85ceedaf1l,0x04c4c5fde3bcc5b1l, + 0x95f9ee8a89412cf9l }, + { 0x2c9459ee82b6eb0fl,0x2e84576595c2aaddl,0x774a84aed327fcfel, + 0xd8c937220368d476l }, + 0 }, + /* 61 << 160 */ + { { 0x39ebf947ccd25abbl,0x74e7a868cb49ebael,0x576ea108332e6147l, + 0xcf3ba166150c1e5dl }, + { 0xb5411fc3515c0e93l,0x51b15761f15c8a34l,0x362a4a3a0d213f38l, + 0xf6f63c2e24e93aeal }, + 0 }, + /* 63 << 160 */ + { { 0x0cb3a2dcb78528d5l,0xa1888c18d585bb41l,0x210cca40de402a6el, + 0x10c6339d9ed7c381l }, + { 0xcd3558d561fe2a0cl,0xc97db05dad5140b1l,0x3366b028b21f8d11l, + 0x878b09033e38be13l }, + 0 }, + /* 64 << 160 */ + { { 0x211cde10296c36efl,0x7ee8967282c4da77l,0xb617d270a57836dal, + 0xf0cd9c319cb7560bl }, + { 0x01fdcbf7e455fe90l,0x3fb53cbb7e7334f3l,0x781e2ea44e7de4ecl, + 0x8adab3ad0b384fd0l }, + 0 }, + /* 65 << 160 */ + { { 0x081e505aa353ba05l,0x244ab34a288b86b1l,0x1155f06214e3a829l, + 0x383300daf2118a6bl }, + { 0xe8fc17cef27032b9l,0xed7f05c9c7bd2389l,0x78f70d14202f8a88l, + 0x8a8310c0647b3f20l }, + 0 }, + /* 71 << 160 */ + { { 0xc80786e1a3633369l,0x496d55de9073f5b9l,0x10deeb6a89ae93cel, + 0x6a2dd5c8b12e00c6l }, + { 0xc25cd2f90c68e26dl,0x29d7ad8b53f0bb64l,0x2dd0d027d7fc9b00l, + 0xad21e1f7ca9c4d5dl }, + 0 }, + /* 77 << 160 */ + { { 0xd45cb932d83465f3l,0x95830c0faf22fdbdl,0x41d830e007cd2a0al, + 0x4a08500e3616e716l }, + { 0x5931fc9f277755a5l,0x7d11680731006764l,0xa409a0ad1b3999aal, + 0xec70368c9939d566l }, + 0 }, + /* 83 << 160 */ + { { 0x3905cb59f2030370l,0x7e9bdee56dcc8fd7l,0xb1b7b04e9806e06fl, + 0xfbdadce22c73eb57l }, + { 0xfb1ab2e98d5b2eb3l,0x58fbf2df7699338bl,0x81b1c54a63b5a032l, + 0xefd1a1896a5d7ff4l }, + 0 }, + /* 89 << 160 */ + { { 0x0265189da1f769eal,0x22fa0bbbfdb5a502l,0xf69f0d1b21027534l, + 0x64302b81f6066b99l }, + { 0xdef85fc98a717e80l,0xe066166386879a3bl,0xe5489b347f95b22cl, + 0x106dca9aa054a563l }, + 0 }, + /* 95 << 160 */ + { { 0xd624b4f4b4be9a77l,0x21a11ed77d50acb1l,0x707181f43d406e11l, + 0x3f324d203ef158bcl }, + { 0xb29a2a34aa8cc8del,0x482f4a15315db969l,0x42ce4fc7d9af272el, + 0x784665b1f8f4cdc4l }, + 0 }, + /* 101 << 160 */ + { { 0x66ff7f73ab43a863l,0xa90be2cba77fd07el,0x84843997f76e5288l, + 0x288c197f3cee129bl }, + { 0x39acc080c0a060a6l,0x4c8e574bd24e27cal,0x1dd6170ffcd3d5e9l, + 0x9736bb51f75e5150l }, + 0 }, + /* 107 << 160 */ + { { 0x2133810e6ba75716l,0x4debf728712886a8l,0x351e46a1f527d1f3l, + 0x29709ae8e9591564l }, + { 0x696163d3a3dc1780l,0xd5b7825ae02aadf3l,0x23579d7cd565ae68l, + 0x105380124fa42cecl }, + 0 }, + /* 113 << 160 */ + { { 0x04eb554d13ffa704l,0x7441a62f2ed33d20l,0xaa926fa0b5b81324l, + 0xb981bcb829836f61l }, + { 0x313a78d4cc9a7a15l,0xff1242d11b3921d2l,0xc0053fd36a209d4dl, + 0x95ac85caf7e92ca9l }, + 0 }, + /* 116 << 160 */ + { { 0x6d2a483d6f73c51el,0xa4cb2412ea0dc2ddl,0x50663c411eb917ffl, + 0x3d3a74cfeade299el }, + { 0x29b3990f4a7a9202l,0xa9bccf59a7b15c3dl,0x66a3ccdca5df9208l, + 0x48027c1443f2f929l }, + 0 }, + /* 119 << 160 */ + { { 0xdf8a6f9673c3f6fbl,0xe4b1f0d98cc03220l,0x5ddacd618350480cl, + 0x485c4fababdfb016l }, + { 0xdc840628b4d424b7l,0x07d3a99c215b2359l,0xad3dc5af56dff52el, + 0x5a3a6754973b6825l }, + 0 }, + /* 125 << 160 */ + { { 0xcfe231b83539a06dl,0xb36d1f72f46770ddl,0x126049747bb900d6l, + 0x8d0990973fc31661l }, + { 0x03b2749c920bc39el,0xf933d510b0486e23l,0x09cc958f0e9b0bb5l, + 0x0b254dd1aa1e23abl }, + 0 }, + }, + { + /* 0 << 168 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 168 */ + { { 0x263a2cfb9db3b381l,0x9c3a2deed4df0a4bl,0x728d06e97d04e61fl, + 0x8b1adfbc42449325l }, + { 0x6ec1d9397e053a1bl,0xee2be5c766daf707l,0x80ba1e14810ac7abl, + 0xdd2ae778f530f174l }, + 0 }, + /* 3 << 168 */ + { { 0xadbaeb79b6828f36l,0x9d7a025801bd5b9el,0xeda01e0d1e844b0cl, + 0x4b625175887edfc9l }, + { 0x14109fdd9669b621l,0x88a2ca56f6f87b98l,0xfe2eb788170df6bcl, + 0x0cea06f4ffa473f9l }, + 0 }, + /* 4 << 168 */ + { { 0x43ed81b5c4e83d33l,0xd9f358795efd488bl,0x164a620f9deb4d0fl, + 0xc6927bdbac6a7394l }, + { 0x45c28df79f9e0f03l,0x2868661efcd7e1a9l,0x7cf4e8d0ffa348f1l, + 0x6bd4c284398538e0l }, + 0 }, + /* 5 << 168 */ + { { 0x2618a091289a8619l,0xef796e606671b173l,0x664e46e59090c632l, + 0xa38062d41e66f8fbl }, + { 0x6c744a200573274el,0xd07b67e4a9271394l,0x391223b26bdc0e20l, + 0xbe2d93f1eb0a05a7l }, + 0 }, + /* 7 << 168 */ + { { 0x7efa14b84444896bl,0x64974d2ff94027fbl,0xefdcd0e8de84487dl, + 0x8c45b2602b48989bl }, + { 0xa8fcbbc2d8463487l,0xd1b2b3f73fbc476cl,0x21d005b7c8f443c0l, + 0x518f2e6740c0139cl }, + 0 }, + /* 9 << 168 */ + { { 0xae51dca2a91f6791l,0x2abe41909baa9efcl,0xd9d2e2f4559c7ac1l, + 0xe82f4b51fc9f773al }, + { 0xa77130274073e81cl,0xc0276facfbb596fcl,0x1d819fc9a684f70cl, + 0x29b47fddc9f7b1e0l }, + 0 }, + /* 10 << 168 */ + { { 0x358de103459b1940l,0xec881c595b013e93l,0x51574c9349532ad3l, + 0x2db1d445b37b46del }, + { 0xc6445b87df239fd8l,0xc718af75151d24eel,0xaea1c4a4f43c6259l, + 0x40c0e5d770be02f7l }, + 0 }, + /* 11 << 168 */ + { { 0x6a4590f4721b33f2l,0x2124f1fbfedf04eal,0xf8e53cde9745efe7l, + 0xe7e1043265f046d9l }, + { 0xc3fca28ee4d0c7e6l,0x847e339a87253b1bl,0x9b5953483743e643l, + 0xcb6a0a0b4fd12fc5l }, + 0 }, + /* 13 << 168 */ + { { 0xec1214eda714181dl,0x609ac13b6067b341l,0xff4b4c97a545df1fl, + 0xa124050134d2076bl }, + { 0x6efa0c231409ca97l,0x254cc1a820638c43l,0xd4e363afdcfb46cdl, + 0x62c2adc303942a27l }, + 0 }, + /* 15 << 168 */ + { { 0x27b6a8ab3fd40e09l,0xe455842e77313ea9l,0x8b51d1e21f55988bl, + 0x5716dd73062bbbfcl }, + { 0x633c11e54e8bf3del,0x9a0e77b61b85be3bl,0x565107290911cca6l, + 0x27e76495efa6590fl }, + 0 }, + /* 16 << 168 */ + { { 0xe4ac8b33070d3aabl,0x2643672b9a2cd5e5l,0x52eff79b1cfc9173l, + 0x665ca49b90a7c13fl }, + { 0x5a8dda59b3efb998l,0x8a5b922d052f1341l,0xae9ebbab3cf9a530l, + 0x35986e7bf56da4d7l }, + 0 }, + /* 17 << 168 */ + { { 0x3a636b5cff3513ccl,0xbb0cf8ba3198f7ddl,0xb8d4052241f16f86l, + 0x760575d8de13a7bfl }, + { 0x36f74e169f7aa181l,0x163a3ecff509ed1cl,0x6aead61f3c40a491l, + 0x158c95fcdfe8fcaal }, + 0 }, + /* 19 << 168 */ + { { 0x6b47accdd9eee96cl,0x0ca277fbe58cec37l,0x113fe413e702c42al, + 0xdd1764eec47cbe51l }, + { 0x041e7cde7b3ed739l,0x50cb74595ce9e1c0l,0x355685132925b212l, + 0x7cff95c4001b081cl }, + 0 }, + /* 21 << 168 */ + { { 0x726f0973da50c991l,0x48afcd5b822d6ee2l,0xe5fc718b20fd7771l, + 0xb9e8e77dfd0807a1l }, + { 0x7f5e0f4499a7703dl,0x6972930e618e36f3l,0x2b7c77b823807bbel, + 0xe5b82405cb27ff50l }, + 0 }, + /* 23 << 168 */ + { { 0x98cb1ae9255c0980l,0x4bd863812b4a739fl,0x5a5c31e11e4a45a1l, + 0x1e5d55fe9cb0db2fl }, + { 0x74661b068ff5cc29l,0x026b389f0eb8a4f4l,0x536b21a458848c24l, + 0x2e5bf8ec81dc72b0l }, + 0 }, + /* 25 << 168 */ + { { 0x9f0af483d309cbe6l,0x5b020d8ae0bced4fl,0x606e986db38023e3l, + 0xad8f2c9d1abc6933l }, + { 0x19292e1de7400e93l,0xfe3e18a952be5e4dl,0xe8e9771d2e0680bfl, + 0x8c5bec98c54db063l }, + 0 }, + /* 27 << 168 */ + { { 0x4c23f62a2c160dcdl,0x34e6c5e38f90eaefl,0x35865519a9a65d5al, + 0x07c48aae8fd38a3dl }, + { 0xb7e7aeda50068527l,0x2c09ef231c90936al,0x31ecfeb6e879324cl, + 0xa0871f6bfb0ec938l }, + 0 }, + /* 28 << 168 */ + { { 0xb1f0fb68d84d835dl,0xc90caf39861dc1e6l,0x12e5b0467594f8d7l, + 0x26897ae265012b92l }, + { 0xbcf68a08a4d6755dl,0x403ee41c0991fbdal,0x733e343e3bbf17e8l, + 0xd2c7980d679b3d65l }, + 0 }, + /* 29 << 168 */ + { { 0x33056232d2e11305l,0x966be492f3c07a6fl,0x6a8878ffbb15509dl, + 0xff2211010a9b59a4l }, + { 0x6c9f564aabe30129l,0xc6f2c940336e64cfl,0x0fe752628b0c8022l, + 0xbe0267e96ae8db87l }, + 0 }, + /* 31 << 168 */ + { { 0x9d031369a5e829e5l,0xcbb4c6fc1607aa41l,0x75ac59a6241d84c1l, + 0xc043f2bf8829e0eel }, + { 0x82a38f758ea5e185l,0x8bda40b9d87cbd9fl,0x9e65e75e2d8fc601l, + 0x3d515f74a35690b3l }, + 0 }, + /* 33 << 168 */ + { { 0xf6b5b2d0bc8fa5bcl,0x8a5ead67500c277bl,0x214625e6dfa08a5dl, + 0x51fdfedc959cf047l }, + { 0x6bc9430b289fca32l,0xe36ff0cf9d9bdc3fl,0x2fe187cb58ea0edel, + 0xed66af205a900b3fl }, + 0 }, + /* 34 << 168 */ + { { 0x00e0968b5fa9f4d6l,0x2d4066ce37a362e7l,0xa99a9748bd07e772l, + 0x710989c006a4f1d0l }, + { 0xd5dedf35ce40cbd8l,0xab55c5f01743293dl,0x766f11448aa24e2cl, + 0x94d874f8605fbcb4l }, + 0 }, + /* 35 << 168 */ + { { 0xa365f0e8a518001bl,0xee605eb69d04ef0fl,0x5a3915cdba8d4d25l, + 0x44c0e1b8b5113472l }, + { 0xcbb024e88b6740dcl,0x89087a53ee1d4f0cl,0xa88fa05c1fc4e372l, + 0x8bf395cbaf8b3af2l }, + 0 }, + /* 36 << 168 */ + { { 0x1e71c9a1deb8568bl,0xa35daea080fb3d32l,0xe8b6f2662cf8fb81l, + 0x6d51afe89490696al }, + { 0x81beac6e51803a19l,0xe3d24b7f86219080l,0x727cfd9ddf6f463cl, + 0x8c6865ca72284ee8l }, + 0 }, + /* 37 << 168 */ + { { 0x32c88b7db743f4efl,0x3793909be7d11dcel,0xd398f9222ff2ebe8l, + 0x2c70ca44e5e49796l }, + { 0xdf4d9929cb1131b1l,0x7826f29825888e79l,0x4d3a112cf1d8740al, + 0x00384cb6270afa8bl }, + 0 }, + /* 39 << 168 */ + { { 0xbe7e990ff0d796a0l,0x5fc62478df0e8b02l,0x8aae8bf4030c00adl, + 0x3d2db93b9004ba0fl }, + { 0xe48c8a79d85d5ddcl,0xe907caa76bb07f34l,0x58db343aa39eaed5l, + 0x0ea6e007adaf5724l }, + 0 }, + /* 40 << 168 */ + { { 0xe00df169d23233f3l,0x3e32279677cb637fl,0x1f897c0e1da0cf6cl, + 0xa651f5d831d6bbddl }, + { 0xdd61af191a230c76l,0xbd527272cdaa5e4al,0xca753636d0abcd7el, + 0x78bdd37c370bd8dcl }, + 0 }, + /* 41 << 168 */ + { { 0xc23916c217cd93fel,0x65b97a4ddadce6e2l,0xe04ed4eb174e42f8l, + 0x1491ccaabb21480al }, + { 0x145a828023196332l,0x3c3862d7587b479al,0x9f4a88a301dcd0edl, + 0x4da2b7ef3ea12f1fl }, + 0 }, + /* 43 << 168 */ + { { 0x71965cbfc3dd9b4dl,0xce23edbffc068a87l,0xb78d4725745b029bl, + 0x74610713cefdd9bdl }, + { 0x7116f75f1266bf52l,0x0204672218e49bb6l,0xdf43df9f3d6f19e3l, + 0xef1bc7d0e685cb2fl }, + 0 }, + /* 44 << 168 */ + { { 0xcddb27c17078c432l,0xe1961b9cb77fedb7l,0x1edc2f5cc2290570l, + 0x2c3fefca19cbd886l }, + { 0xcf880a36c2af389al,0x96c610fdbda71ceal,0xf03977a932aa8463l, + 0x8eb7763f8586d90al }, + 0 }, + /* 45 << 168 */ + { { 0x3f3424542a296e77l,0xc871868342837a35l,0x7dc710906a09c731l, + 0x54778ffb51b816dbl }, + { 0x6b33bfecaf06defdl,0xfe3c105f8592b70bl,0xf937fda461da6114l, + 0x3c13e6514c266ad7l }, + 0 }, + /* 46 << 168 */ + { { 0xe363a829855938e8l,0x2eeb5d9e9de54b72l,0xbeb93b0e20ccfab9l, + 0x3dffbb5f25e61a25l }, + { 0x7f655e431acc093dl,0x0cb6cc3d3964ce61l,0x6ab283a1e5e9b460l, + 0x55d787c5a1c7e72dl }, + 0 }, + /* 47 << 168 */ + { { 0x4d2efd47deadbf02l,0x11e80219ac459068l,0x810c762671f311f0l, + 0xfa17ef8d4ab6ef53l }, + { 0xaf47fd2593e43bffl,0x5cb5ff3f0be40632l,0x546871068ee61da3l, + 0x7764196eb08afd0fl }, + 0 }, + /* 48 << 168 */ + { { 0x831ab3edf0290a8fl,0xcae81966cb47c387l,0xaad7dece184efb4fl, + 0xdcfc53b34749110el }, + { 0x6698f23c4cb632f9l,0xc42a1ad6b91f8067l,0xb116a81d6284180al, + 0xebedf5f8e901326fl }, + 0 }, + /* 49 << 168 */ + { { 0xf2274c9f97e3e044l,0x4201852011d09fc9l,0x56a65f17d18e6e23l, + 0x2ea61e2a352b683cl }, + { 0x27d291bc575eaa94l,0x9e7bc721b8ff522dl,0x5f7268bfa7f04d6fl, + 0x5868c73faba41748l }, + 0 }, + /* 51 << 168 */ + { { 0x1c52e63596e78cc4l,0x5385c8b20c06b4a8l,0xd84ddfdbb0e87d03l, + 0xc49dfb66934bafadl }, + { 0x7071e17059f70772l,0x3a073a843a1db56bl,0x034949033b8af190l, + 0x7d882de3d32920f0l }, + 0 }, + /* 52 << 168 */ + { { 0x91633f0ab2cf8940l,0x72b0b1786f948f51l,0x2d28dc30782653c8l, + 0x88829849db903a05l }, + { 0xb8095d0c6a19d2bbl,0x4b9e7f0c86f782cbl,0x7af739882d907064l, + 0xd12be0fe8b32643cl }, + 0 }, + /* 53 << 168 */ + { { 0x358ed23d0e165dc3l,0x3d47ce624e2378cel,0x7e2bb0b9feb8a087l, + 0x3246e8aee29e10b9l }, + { 0x459f4ec703ce2b4dl,0xe9b4ca1bbbc077cfl,0x2613b4f20e9940c1l, + 0xfc598bb9047d1eb1l }, + 0 }, + /* 55 << 168 */ + { { 0x52fb0c9d7fc63668l,0x6886c9dd0c039cdel,0x602bd59955b22351l, + 0xb00cab02360c7c13l }, + { 0x8cb616bc81b69442l,0x41486700b55c3ceel,0x71093281f49ba278l, + 0xad956d9c64a50710l }, + 0 }, + /* 57 << 168 */ + { { 0xbaca6591d4b66947l,0xb452ce9804460a8cl,0x6830d24643768f55l, + 0xf4197ed87dff12dfl }, + { 0x6521b472400dd0f7l,0x59f5ca8f4b1e7093l,0x6feff11b080338ael, + 0x0ada31f6a29ca3c6l }, + 0 }, + /* 59 << 168 */ + { { 0x04e5dfe0d809c7bdl,0xd7b2580c8f1050abl,0x6d91ad78d8a4176fl, + 0x0af556ee4e2e897cl }, + { 0x162a8b73921de0acl,0x52ac9c227ea78400l,0xee2a4eeaefce2174l, + 0xbe61844e6d637f79l }, + 0 }, + /* 60 << 168 */ + { { 0x0491f1bc789a283bl,0x72d3ac3d880836f4l,0xaa1c5ea388e5402dl, + 0x1b192421d5cc473dl }, + { 0x5c0b99989dc84cacl,0xb0a8482d9c6e75b8l,0x639961d03a191ce2l, + 0xda3bc8656d837930l }, + 0 }, + /* 61 << 168 */ + { { 0xca990653056e6f8fl,0x84861c4164d133a7l,0x8b403276746abe40l, + 0xb7b4d51aebf8e303l }, + { 0x05b43211220a255dl,0xc997152c02419e6el,0x76ff47b6630c2feal, + 0x50518677281fdadel }, + 0 }, + /* 63 << 168 */ + { { 0x6d2d99b7ea7b979bl,0xcd78cd74e6fb3bcdl,0x11e45a9e86cffbfel, + 0x78a61cf4637024f6l }, + { 0xd06bc8723d502295l,0xf1376854458cb288l,0xb9db26a1342f8586l, + 0xf33effcf4beee09el }, + 0 }, + /* 64 << 168 */ + { { 0xd7e0c4cdb30cfb3al,0x6d09b8c16c9db4c8l,0x40ba1a4207c8d9dfl, + 0x6fd495f71c52c66dl }, + { 0xfb0e169f275264dal,0x80c2b746e57d8362l,0xedd987f749ad7222l, + 0xfdc229af4398ec7bl }, + 0 }, + /* 65 << 168 */ + { { 0xfe81af4609418a51l,0xdbb60b836f18e3a5l,0x5e7a86ea4566ec9cl, + 0xb76ff40f25093925l }, + { 0x5fe6662c429c5554l,0xfc9ec35384e478cfl,0x73dbb5f3e8cfa761l, + 0x031e506592f82709l }, + 0 }, + /* 71 << 168 */ + { { 0x108c736abd49f2e0l,0xe230f2417487dcc8l,0x073fc4f8f74d939cl, + 0x98532487e9745bbel }, + { 0x5208eb981714b10bl,0xec35d0510458725dl,0x35dbb60bf203f4b6l, + 0x064299b27781ab38l }, + 0 }, + /* 77 << 168 */ + { { 0x43cc7bbc02d26929l,0xeb00a683162d9607l,0x2af152b8ed9fa224l, + 0xf24e8bee12257f0cl }, + { 0xdf065dd5d004b1cbl,0x6aa20bcf9f9908c6l,0x8e5e86b6941c593dl, + 0x0e0034b398969717l }, + 0 }, + /* 83 << 168 */ + { { 0x5be62e155c43b8fcl,0xd9e0adfc3c445636l,0xc5141df0e0d78f48l, + 0xd134bbed2c277716l }, + { 0x79033a84598fe069l,0x6c704367b081614cl,0x55c45d66bf5bf772l, + 0xf08744c57a444730l }, + 0 }, + /* 89 << 168 */ + { { 0x866752091422b528l,0xdb297411c3e028eel,0x1f5575b040e1c3ccl, + 0x85367b84d333b04fl }, + { 0x57864c86e9804aa9l,0xf13fa8e3439156dfl,0xa3b337e0464e0aecl, + 0x0018dfd7f2ae382bl }, + 0 }, + /* 95 << 168 */ + { { 0xe93cece9cea132fcl,0x985542d8f74e867al,0x2a3d18a5cc8fcf87l, + 0xa0561055479d0039l }, + { 0x3513c7eaac4b3f9dl,0xc095967256477606l,0xa63960f330df8ad6l, + 0x59ca8d53cc9ddcb3l }, + 0 }, + /* 101 << 168 */ + { { 0x6d8e942b2f208191l,0xd49a6d9453fe5457l,0x2b55e391003010bal, + 0x3dd1fd9fdf4605ebl }, + { 0xdc006a3358682886l,0x60a5e86c1bd9ac88l,0xc4bd320ed0cab8f2l, + 0x7281e7cb7751855bl }, + 0 }, + /* 107 << 168 */ + { { 0x7d564222e1881e7al,0x59061a89db0673c2l,0x1f9d607213f27313l, + 0x5b3b29368ff3aeb7l }, + { 0x6cf2304ccf969f43l,0x8eff4a25e7f69ae5l,0xbaeb6411d17da4ffl, + 0x666af0af9eea17ecl }, + 0 }, + /* 113 << 168 */ + { { 0x6c0b811697f4cd0bl,0xcd7825d40e4ea852l,0x80158fb0677fef3dl, + 0x5bb1a3aaa10ee693l }, + { 0xc5df66678066fc9bl,0x3200dc11f404d4a6l,0x58868950a8686d8el, + 0xbdaaffb53770fabal }, + 0 }, + /* 116 << 168 */ + { { 0xba6a9f84660326f5l,0x61c1e44161bc3e88l,0xfbf992a0bde85cf8l, + 0xe704dd1e6f8c8f5fl }, + { 0x231caa0ab1d7d486l,0xd10616d8891cd571l,0x2ddada75c008833cl, + 0x44337d6dad514c94l }, + 0 }, + /* 119 << 168 */ + { { 0xd48678b8f6933cf0l,0x7b4d623e0b739471l,0x4ad620287b216238l, + 0xb4d4918959c4fabel }, + { 0x8c2a1bdc296d42d5l,0x9235d0ec2fd3eb96l,0xfe271972f81c135bl, + 0x82b5181741471e16l }, + 0 }, + /* 125 << 168 */ + { { 0xe9aa8ce4051f8e81l,0x14484af67cd1391fl,0x53a361dcafb1656el, + 0x6ad8ba02f4d9d0cbl }, + { 0xfb4385466c50a722l,0x2f1c5bbc7edb37f4l,0x8dc90ccb16e4b795l, + 0xbcb32e1508127094l }, + 0 }, + }, + { + /* 0 << 176 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 176 */ + { { 0xb81d783e979f3925l,0x1efd130aaf4c89a7l,0x525c2144fd1bf7fal, + 0x4b2969041b265a9el }, + { 0xed8e9634b9db65b6l,0x35c82e3203599d8al,0xdaa7a54f403563f3l, + 0x9df088ad022c38abl }, + 0 }, + /* 3 << 176 */ + { { 0x9e93ba24f111661el,0xedced484b105eb04l,0x96dc9ba1f424b578l, + 0xbf8f66b7e83e9069l }, + { 0x872d4df4d7ed8216l,0xbf07f3778e2cbecfl,0x4281d89998e73754l, + 0xfec85fbb8aab8708l }, + 0 }, + /* 4 << 176 */ + { { 0x13b5bf22765fa7d0l,0x59805bf01d6a5370l,0x67a5e29d4280db98l, + 0x4f53916f776b1ce3l }, + { 0x714ff61f33ddf626l,0x4206238ea085d103l,0x1c50d4b7e5809ee3l, + 0x999f450d85f8eb1dl }, + 0 }, + /* 5 << 176 */ + { { 0x82eebe731a3a93bcl,0x42bbf465a21adc1al,0xc10b6fa4ef030efdl, + 0x247aa4c787b097bbl }, + { 0x8b8dc632f60c77dal,0x6ffbc26ac223523el,0xa4f6ff11344579cfl, + 0x5825653c980250f6l }, + 0 }, + /* 7 << 176 */ + { { 0xeda6c595d314e7bcl,0x2ee7464b467899edl,0x1cef423c0a1ed5d3l, + 0x217e76ea69cc7613l }, + { 0x27ccce1fe7cda917l,0x12d8016b8a893f16l,0xbcd6de849fc74f6bl, + 0xfa5817e2f3144e61l }, + 0 }, + /* 9 << 176 */ + { { 0xc0b48d4e49ccd6d7l,0xff8fb02c88bd5580l,0xc75235e907d473b2l, + 0x4fab1ac5a2188af3l }, + { 0x030fa3bc97576ec0l,0xe8c946e80b7e7d2fl,0x40a5c9cc70305600l, + 0x6d8260a9c8b013b4l }, + 0 }, + /* 10 << 176 */ + { { 0xe6c51073615cd9e4l,0x498ec047f1243c06l,0x3e5a8809b17b3d8cl, + 0x5cd99e610cc565f1l }, + { 0x81e312df7851dafel,0xf156f5baa79061e2l,0x80d62b71880c590el, + 0xbec9746f0a39faa1l }, + 0 }, + /* 11 << 176 */ + { { 0x2b09d2c3cfdcf7ddl,0x41a9fce3723fcab4l,0x73d905f707f57ca3l, + 0x080f9fb1ac8e1555l }, + { 0x7c088e849ba7a531l,0x07d35586ed9a147fl,0x602846abaf48c336l, + 0x7320fd320ccf0e79l }, + 0 }, + /* 13 << 176 */ + { { 0x92eb40907f8f875dl,0x9c9d754e56c26bbfl,0x158cea618110bbe7l, + 0x62a6b802745f91eal }, + { 0xa79c41aac6e7394bl,0x445b6a83ad57ef10l,0x0c5277eb6ea6f40cl, + 0x319fe96b88633365l }, + 0 }, + /* 15 << 176 */ + { { 0x77f84203d39b8c34l,0xed8b1be63125eddbl,0x5bbf2441f6e39dc5l, + 0xb00f6ee66a5d678al }, + { 0xba456ecf57d0ea99l,0xdcae0f5817e06c43l,0x01643de40f5b4baal, + 0x2c324341d161b9bel }, + 0 }, + /* 16 << 176 */ + { { 0x949c9976e1337c26l,0x6faadebdd73d68e5l,0x9e158614f1b768d9l, + 0x22dfa5579cc4f069l }, + { 0xccd6da17be93c6d6l,0x24866c61a504f5b9l,0x2121353c8d694da1l, + 0x1c6ca5800140b8c6l }, + 0 }, + /* 17 << 176 */ + { { 0x4e77c5575b45afb4l,0xe9ded649efb8912dl,0x7ec9bbf542f6e557l, + 0x2570dfff62671f00l }, + { 0x2b3bfb7888e084bdl,0xa024b238f37fe5b4l,0x44e7dc0495649aeel, + 0x498ca2555e7ec1d8l }, + 0 }, + /* 19 << 176 */ + { { 0x2e44d22526a1fc90l,0x0d6d10d24d70705dl,0xd94b6b10d70c45f4l, + 0x0f201022b216c079l }, + { 0xcec966c5658fde41l,0xa8d2bc7d7e27601dl,0xbfcce3e1ff230be7l, + 0x3394ff6b0033ffb5l }, + 0 }, + /* 21 << 176 */ + { { 0x05d99be8b9c20cdal,0x89f7aad5d5cd0c98l,0x7ef936fe5bb94183l, + 0x92ca0753b05cd7f2l }, + { 0x9d65db1174a1e035l,0x02628cc813eaea92l,0xf2d9e24249e4fbf2l, + 0x94fdfd9be384f8b7l }, + 0 }, + /* 23 << 176 */ + { { 0x29882d7c98379d44l,0xd000bdfb509edc8al,0xc6f95979e66fe464l, + 0x504a6115fa61bde0l }, + { 0x56b3b871effea31al,0x2d3de26df0c21a54l,0x21dbff31834753bfl, + 0xe67ecf4969269d86l }, + 0 }, + /* 25 << 176 */ + { { 0xed29a56da16d4b34l,0x7fba9d09dca21c4fl,0x66d7ac006d8de486l, + 0x6006198773a2a5e1l }, + { 0x8b400f869da28ff0l,0x3133f70843c4599cl,0x9911c9b8ee28cb0dl, + 0xcd7e28748e0af61dl }, + 0 }, + /* 27 << 176 */ + { { 0x6a7bb6a93b5bdb83l,0x08da65c0a4a72318l,0xc58d22aa63eb065fl, + 0x1717596c1b15d685l }, + { 0x112df0d0b266d88bl,0xf688ae975941945al,0x487386e37c292cacl, + 0x42f3b50d57d6985cl }, + 0 }, + /* 28 << 176 */ + { { 0x69e3be0427596893l,0xb6bb02a645bf452bl,0x0875c11af4c698c8l, + 0x6652b5c7bece3794l }, + { 0x7b3755fd4f5c0499l,0x6ea16558b5532b38l,0xd1c69889a2e96ef7l, + 0x9c773c3a61ed8f48l }, + 0 }, + /* 29 << 176 */ + { { 0x5a304ada8545d185l,0x82ae44ea738bb8cbl,0x628a35e3df87e10el, + 0xd3624f3da15b9fe3l }, + { 0xcc44209b14be4254l,0x7d0efcbcbdbc2ea5l,0x1f60336204c37bbel, + 0x21f363f556a5852cl }, + 0 }, + /* 31 << 176 */ + { { 0x81262e4225346689l,0x716da290b07c7004l,0x35f911eab7950ee3l, + 0x6fd72969261d21b5l }, + { 0x5238980308b640d3l,0x5b0026ee887f12a1l,0x20e21660742e9311l, + 0x0ef6d5415ff77ff7l }, + 0 }, + /* 33 << 176 */ + { { 0x64aa0874925dd0b0l,0x5ffd503851c474c6l,0x4478c72c8ebd4157l, + 0xb98694cb8c8375e2l }, + { 0xeda4edeecd8e208cl,0xf98a053d2c0670a6l,0x564bd3057f346b9dl, + 0xafbbf3e94c318fddl }, + 0 }, + /* 34 << 176 */ + { { 0x8a03410aa96c4685l,0xef1b6b16a978a31bl,0x44738a3b629df6cfl, + 0xa1dc65da807713e9l }, + { 0x569cc7884c373442l,0x1f30a2464965fb52l,0x56822f1677ff5e2el, + 0x63f18812e303748bl }, + 0 }, + /* 35 << 176 */ + { { 0x2abdc403dd0983ecl,0xec0c08c7f365c6f5l,0xe555083fbdb66b8bl, + 0x593685bc4e8973ffl }, + { 0x737df3f920e9c705l,0x00c7bcc309c31a5al,0x5f1d23e2efdcb34dl, + 0x79d9b382470f7949l }, + 0 }, + /* 36 << 176 */ + { { 0x44a315645fd2eb1dl,0x4e7397263fdd1356l,0x9b96735463200efel, + 0xcb70402e520bbb6al }, + { 0xcbc90d7e693d2642l,0x6fb00064bc9b4002l,0x95f2eab3d96f7150l, + 0xb1619e3fe035f47al }, + 0 }, + /* 37 << 176 */ + { { 0xd22d6073d1561bb7l,0x40666e4ba9928683l,0x90654dab8ab3f9b1l, + 0x7625c507b8773421l }, + { 0x288f28220ca88cd2l,0xbb88114ed8d005c1l,0xbeec2b0af603a11bl, + 0x8fdda60325f7949el }, + 0 }, + /* 39 << 176 */ + { { 0x6503632d6ee4f1d0l,0xd5449747ea394840l,0xd696167a8abe13a1l, + 0xc080f76e609ebaa9l }, + { 0x181acf0c10aa70d6l,0x70614461291e5e50l,0x7ade8e84b9f0c0a3l, + 0xef1de9f2cb11b41el }, + 0 }, + /* 40 << 176 */ + { { 0x2d5c3c848e592413l,0x727022961832ba2cl,0x22979b51596c6321l, + 0x738f31cb5a04db64l }, + { 0x0bdaa6ca98f84ee5l,0x4e9e827c15e21eeel,0x4c59dbcc3ea632e0l, + 0xed3404db5bc6f027l }, + 0 }, + /* 41 << 176 */ + { { 0x2841f05cfbaf8b26l,0xac9830db5b243770l,0xde3ab1707787f324l, + 0x1ee12efe079209bcl }, + { 0x2d3fd62d5bcf6e3cl,0x8a680655d60b0582l,0xdafc5061bc2b64a1l, + 0xe0d91e7526a88788l }, + 0 }, + /* 43 << 176 */ + { { 0x2d49c685426b1b1el,0x6c2149caeabb02f7l,0xa4697d7fde11984fl, + 0xa0e32fb3ed3c8707l }, + { 0xb783e825f4ca12dal,0xb2666e2448770a50l,0x82d47f478660e923l, + 0x6e36cd71fb4a984fl }, + 0 }, + /* 44 << 176 */ + { { 0x3295a8ea43c66b92l,0x99387af6ac5d19d4l,0x545f9b1b8e9d2090l, + 0x138b1c4c2660f530l }, + { 0xbfb05fd2ff872627l,0xb6614b0f4c3bc45cl,0x13defece62ca0fb0l, + 0x82ddae134fededd8l }, + 0 }, + /* 45 << 176 */ + { { 0x5a34499b871c4cbbl,0x3ab0e69a2eb6084bl,0xa8d0160025ef7755l, + 0x5db8f611d9e70f5dl }, + { 0x63f9eb9a7afa95d7l,0x328b97f9706d7964l,0x8bcf9a0f4b71dfcal, + 0x53d4c3042a5c7934l }, + 0 }, + /* 46 << 176 */ + { { 0x0c87dd3a8768d9aal,0x201ce5a082f6a55fl,0xa3de6f3049ca4602l, + 0x36f421422aeb5f17l }, + { 0x5c9962399817b77al,0x2584a10ae8d165acl,0x80f683d0c726f4aal, + 0x524307502dcdfa48l }, + 0 }, + /* 47 << 176 */ + { { 0x0c04399f94683df2l,0x0978e9d4e954838dl,0x01faa5e8cf4a7a7bl, + 0x92f6e6a90dae61cfl }, + { 0x0c0f1293373dc957l,0x8320178fd8cc6b67l,0x4af977ed4b6444f2l, + 0xd8c9a401ad8e5f84l }, + 0 }, + /* 48 << 176 */ + { { 0xbd5660ed9aed9f40l,0x70ca6ad1532a8c99l,0xc4978bfb95c371eal, + 0xe5464d0d7003109dl }, + { 0x1af32fdfd9e535efl,0xabf57ea798c9185bl,0xed7a741712b42488l, + 0x8e0296a7e97286fal }, + 0 }, + /* 49 << 176 */ + { { 0x79ee35ac16fca804l,0x8f16e6165f59782el,0x8fbef1011737694el, + 0xb34b7625462be08bl }, + { 0x7e63e1b016e75c91l,0xb6a18edd2d23728dl,0xcf761a1e7f299ab6l, + 0x796dcdebf16c770el }, + 0 }, + /* 51 << 176 */ + { { 0x47354f22308ee4afl,0x96959a538ecd6f4bl,0xf60b5f104055cbd2l, + 0x04b1c9599bd86095l }, + { 0x26accd8486008564l,0x46b2fe0478f31ea7l,0x5500dbf72dd76f23l, + 0x36bcdf584c496c6fl }, + 0 }, + /* 52 << 176 */ + { { 0x8836cd431527d7cel,0x1f236623187a50eal,0x6470c0ae847221f0l, + 0xc61f86b47e449110l }, + { 0x7cc9cc20fa9fcec1l,0xa394903019134349l,0xafe5a08ff53ab467l, + 0x9caba02301ed2919l }, + 0 }, + /* 53 << 176 */ + { { 0xffecbdce406abf1el,0x0ef4bcd73ae340d4l,0x7e37bae0e19d5613l, + 0xe191669be4c6e97al }, + { 0x9fafe59797292db7l,0xab7ef3713172d716l,0x9f0fff330ce3b533l, + 0xca94ff8f932dd8cfl }, + 0 }, + /* 55 << 176 */ + { { 0x659c8b5d78aea69el,0xdde7ab46476a8fb9l,0x26bfe303bd01b5e6l, + 0xf3dfb08a726a937cl }, + { 0xe7a591fa0a263670l,0xe872c3f8f97434a0l,0x4881a82e2e0f2c21l, + 0x17624e48788ef958l }, + 0 }, + /* 57 << 176 */ + { { 0xd526d66da7222e5bl,0xd33bb78efeb00e25l,0x9a7d670b932c8d08l, + 0xea31e5273cee093fl }, + { 0x55cc091bd04b7a43l,0x12b08d6dd01a123dl,0x1d98a6467fb0e7bal, + 0xdabb09483535fd0dl }, + 0 }, + /* 59 << 176 */ + { { 0x2862314d08b69b19l,0x9cf302e191effcfal,0x43bdc8462ead917al, + 0x21b238bbf94b3d8fl }, + { 0xa3736160e2f465d3l,0x4d7fb6818541e255l,0x46fa089a23551edcl, + 0xf7c41d17c1fefa8cl }, + 0 }, + /* 60 << 176 */ + { { 0x8ed0807fed113000l,0x8e1672d04c691484l,0x33a13ab31ee86ca0l, + 0x9df0d9573bcaee4fl }, + { 0x0cf0c638ef0dfb71l,0x1e0fe22ac2c9510al,0x43f506716fcc6a21l, + 0xccb58404cec03a94l }, + 0 }, + /* 61 << 176 */ + { { 0x59547e37fd0936c1l,0x81e0517df45140b1l,0xcc6ccd89ed49e3fcl, + 0xc2fa23eff3b897del }, + { 0x149511ef2050c80al,0xf66bea6b3140b833l,0xbbe1401e2786d723l, + 0x0aeb549c887509bcl }, + 0 }, + /* 63 << 176 */ + { { 0xf938e85060f5867al,0x806e1fff72429adcl,0x5ff7962a45f43b52l, + 0xd8375ab6b2bbb403l }, + { 0x00d5819b21b287fcl,0x15c7190ebae37d58l,0x075ce5ce05fcfb07l, + 0x76368d06dbc003cbl }, + 0 }, + /* 64 << 176 */ + { { 0x01079383171b445fl,0x9bcf21e38131ad4cl,0x8cdfe205c93987e8l, + 0xe63f4152c92e8c8fl }, + { 0x729462a930add43dl,0x62ebb143c980f05al,0x4f3954e53b06e968l, + 0xfe1d75ad242cf6b1l }, + 0 }, + /* 65 << 176 */ + { { 0x1cf508197630655el,0x9b4685c408d417f5l,0x6ea942619b049259l, + 0x31c29b54fe73b755l }, + { 0x3d2872a1f1f2af17l,0xbcd1139956bcbc4bl,0x4d14f59890d7a85cl, + 0xd2c46040dbcbe998l }, + 0 }, + /* 71 << 176 */ + { { 0x3c8a06ca9792c42al,0x92535628602460ddl,0xa95e13f2ddd4c676l, + 0xe823841d3b20d463l }, + { 0x0248605bbfad6051l,0x82985dd61af51233l,0x3d243a5cdef7d742l, + 0x0a88ce55ff6aa911l }, + 0 }, + /* 77 << 176 */ + { { 0xcf5b5962449aec98l,0x40322a6531a41389l,0xcd15606fd72c0527l, + 0xfe91eac7b90d65a0l }, + { 0xcd32415487636360l,0x82f2c7bdfc653a6fl,0xd04d138ae315ce7cl, + 0x40ebfd5e78118dbcl }, + 0 }, + /* 83 << 176 */ + { { 0x0f9ea6ae4144660fl,0x02345c6513279b25l,0x139497b65c7671cbl, + 0x7259f14b2ebed1d5l }, + { 0xa1e5d98ce9b29988l,0xaed0efcd8df73ac8l,0x88339f073b81a77cl, + 0x28f2bbca7109c8a6l }, + 0 }, + /* 89 << 176 */ + { { 0xa264f99d811472ddl,0x0e7eae0afc07a80cl,0x77f264d4a683cdc6l, + 0x0512df49d053c668l }, + { 0x2b4dfbade61dea15l,0x83de61acfd74890al,0xd2552bab32d41182l, + 0x1fb9411435924e6al }, + 0 }, + /* 95 << 176 */ + { { 0x85efe53ade23c988l,0x89d41dbbf897f91bl,0x1357f91e7873fa8dl, + 0x7a6ec2e3718d911cl }, + { 0xf9e4f92e8f209a01l,0x4ffb96a70fdd67f3l,0x4c81a787f83dde1cl, + 0x0d68fce15e163b60l }, + 0 }, + /* 101 << 176 */ + { { 0xbc79b4b26ab6da9dl,0xb4be5c278bb005f1l,0x63624530cd3b280bl, + 0x543142f04e880026l }, + { 0xbf7fb14cad90ddbfl,0xfe456e8a3966732dl,0x85499fb987ce35e9l, + 0x8af09e6b24f1305dl }, + 0 }, + /* 107 << 176 */ + { { 0x5fc563ec16dc2b4bl,0xfe5631b25d0e535fl,0xbf4c489f9a93e36cl, + 0x56badff1da2a07c4l }, + { 0x72ac6b77fb7c5595l,0x4b25b9428e6645d9l,0xeeae127251f0657el, + 0x30779ca51abeb76bl }, + 0 }, + /* 113 << 176 */ + { { 0x3d602ef5d909f43dl,0x2b2951a6bb347c79l,0x44903bfaa0d88896l, + 0xd4ab20e8684c104fl }, + { 0x55f70b4dd9b7e626l,0x084b3ee646a5f9ecl,0x1799cbe3da4ae81al, + 0xc7cfac937fd6b80fl }, + 0 }, + /* 116 << 176 */ + { { 0x45647911ca20c525l,0x78f83186004706abl,0x5596377d97510538l, + 0x047863defe041f8cl }, + { 0xaea784896ec82367l,0x9d4eac2601eee8fcl,0xb32728f19b57d9dbl, + 0x60a158f5313c0f65l }, + 0 }, + /* 119 << 176 */ + { { 0xf78caf129754377bl,0xa7fce16b6966f0c4l,0xfea937555a54a2b7l, + 0x52d7f79b7cdfe951l }, + { 0x3e14b92e94b1dac0l,0x363f2e5af168b73bl,0xcc0e9dcb6436a8c2l, + 0x2dbece4bb52cbd27l }, + 0 }, + /* 125 << 176 */ + { { 0x7e7907ed8df38ffel,0xa68ec827e24e8a24l,0x5093a97e5f168732l, + 0xa9ffea2f39ebb6dbl }, + { 0x89e02c12284276d4l,0xc1179e3b3f9502d6l,0x01becb51d8f69eb6l, + 0x86eee2935eb1c73cl }, + 0 }, + }, + { + /* 0 << 184 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 184 */ + { { 0xf3b7963f4c830320l,0x842c7aa0903203e3l,0xaf22ca0ae7327afbl, + 0x38e13092967609b6l }, + { 0x73b8fb62757558f1l,0x3cc3e831f7eca8c1l,0xe4174474f6331627l, + 0xa77989cac3c40234l }, + 0 }, + /* 3 << 184 */ + { { 0xb32cb8b0b796d219l,0xc3e95f4f34741dd9l,0x8721212568edf6f5l, + 0x7a03aee4a2b9cb8el }, + { 0x0cd3c376f53a89aal,0x0d8af9b1948a28dcl,0xcf86a3f4902ab04fl, + 0x8aacb62a7f42002dl }, + 0 }, + /* 4 << 184 */ + { { 0xfd8e139f8f5fcda8l,0xf3e558c4bdee5bfdl,0xd76cbaf4e33f9f77l, + 0x3a4c97a471771969l }, + { 0xda27e84bf6dce6a7l,0xff373d9613e6c2d1l,0xf115193cd759a6e9l, + 0x3f9b702563d2262cl }, + 0 }, + /* 5 << 184 */ + { { 0x9cb0ae6c252bd479l,0x05e0f88a12b5848fl,0x78f6d2b2a5c97663l, + 0x6f6e149bc162225cl }, + { 0xe602235cde601a89l,0xd17bbe98f373be1fl,0xcaf49a5ba8471827l, + 0x7e1a0a8518aaa116l }, + 0 }, + /* 7 << 184 */ + { { 0x8b1e572235e6fc06l,0x3477728f0b3e13d5l,0x150c294daa8a7372l, + 0xc0291d433bfa528al }, + { 0xc6c8bc67cec5a196l,0xdeeb31e45c2e8a7cl,0xba93e244fb6e1c51l, + 0xb9f8b71b2e28e156l }, + 0 }, + /* 9 << 184 */ + { { 0x343ac0a3ee9523f0l,0xbb75eab2975ea978l,0x1bccf332107387f4l, + 0x790f92599ab0062el }, + { 0xf1a363ad1e4f6a5fl,0x06e08b8462519a50l,0x609151877265f1eel, + 0x6a80ca3493ae985el }, + 0 }, + /* 10 << 184 */ + { { 0xa3f4f521e447f2c4l,0x81b8da7a604291f0l,0xd680bc467d5926del, + 0x84f21fd534a1202fl }, + { 0x1d1e31814e9df3d8l,0x1ca4861a39ab8d34l,0x809ddeec5b19aa4al, + 0x59f72f7e4d329366l }, + 0 }, + /* 11 << 184 */ + { { 0x2dfb9e08be0f4492l,0x3ff0da03e9d5e517l,0x03dbe9a1f79466a8l, + 0x0b87bcd015ea9932l }, + { 0xeb64fc83ab1f58abl,0x6d9598da817edc8al,0x699cff661d3b67e5l, + 0x645c0f2992635853l }, + 0 }, + /* 13 << 184 */ + { { 0xd50e57c7d7fe71f3l,0x15342190bc97ce38l,0x51bda2de4df07b63l, + 0xba12aeae200eb87dl }, + { 0xabe135d2a9b4f8f6l,0x04619d65fad6d99cl,0x4a6683a77994937cl, + 0x7a778c8b6f94f09al }, + 0 }, + /* 15 << 184 */ + { { 0x8dd1fb83425c6559l,0x7fc00ee60af06fdal,0xe98c922533d956dfl, + 0x0f1ef3354fbdc8a2l }, + { 0x2abb5145b79b8ea2l,0x40fd2945bdbff288l,0x6a814ac4d7185db7l, + 0xc4329d6fc084609al }, + 0 }, + /* 16 << 184 */ + { { 0x511053e453544774l,0x834d0ecc3adba2bcl,0x4215d7f7bae371f5l, + 0xfcfd57bf6c8663bcl }, + { 0xded2383dd6901b1dl,0x3b49fbb4b5587dc3l,0xfd44a08d07625f62l, + 0x3ee4d65b9de9b762l }, + 0 }, + /* 17 << 184 */ + { { 0x55ef9d3dcc26e8b0l,0xf869c827729b707al,0xdbbf450d8c47e00cl, + 0x73d546ea60972ed7l }, + { 0x9563e11f0dcd6821l,0xe48e1af57d80de7fl,0xbe7139b49057838dl, + 0xf3f0ad4d7e5ca535l }, + 0 }, + /* 19 << 184 */ + { { 0xac66d1d49f8f8cc2l,0x43fe5c154ef18941l,0xbae77b6ddc30fcbfl, + 0xdb95ea7d945723b7l }, + { 0x43298e2bda8097e2l,0x8004167baf22ea9bl,0x9cf5974196a83d57l, + 0xb35c9aba3cf67d5el }, + 0 }, + /* 21 << 184 */ + { { 0x0569a48df766f793l,0x6b4c7b16706b3442l,0xcc97754416ff41e0l, + 0x800c56e31fee2e86l }, + { 0xce0c3d0fcdf93450l,0x6ec3703582f35916l,0x902520d5bbc11e68l, + 0x7e2b988505078223l }, + 0 }, + /* 23 << 184 */ + { { 0xb30d1769101da00bl,0xb26872d5113cfdb6l,0x7b0491da44e48db5l, + 0x810e73bb2013f8c9l }, + { 0xc86e579a570f0b59l,0xf34107e37a918f34l,0x49286d00277473f1l, + 0x74423f5abc85905dl }, + 0 }, + /* 25 << 184 */ + { { 0x90d7417879de6b48l,0xe762caf0d14fa75bl,0xa309dcf3bd91ec5dl, + 0x7aafe1ddf526d04fl }, + { 0x76911342d39e36ffl,0xe28994d2fabb34b8l,0xac23a92c863110cbl, + 0x9f0f69673aabd166l }, + 0 }, + /* 27 << 184 */ + { { 0x7436bdf47e333f98l,0x879cf31f2455af64l,0x07933a9cf6cfde92l, + 0xfcac38a5b6e3203fl }, + { 0xa39b6a8098e5a6e0l,0x1d600b5da4837528l,0x54718de7c32d412bl, + 0x02870f46317937ccl }, + 0 }, + /* 28 << 184 */ + { { 0x1f13756db1761ec8l,0xe53c8b98a4b97e55l,0xb2aee3f84096cc28l, + 0x48c361a0920f1a8dl }, + { 0xa98b672d8c31190al,0x7bc1e7d1001855d4l,0x242cfb07bf3f4b2al, + 0x9bf44a3f32a28bc4l }, + 0 }, + /* 29 << 184 */ + { { 0x96d4b271e36eeccdl,0x2d8c01b859237e23l,0x24f7a6eb8adf2653l, + 0xc08ac4ab41183d80l }, + { 0xc35e5bb7036367c3l,0xd8c97cbc0ba59f61l,0x296b1f4c5aafe986l, + 0xa519c7a17d179c37l }, + 0 }, + /* 31 << 184 */ + { { 0x4043490790ae5f49l,0x8ac8f73649556b81l,0xb57a89b0f4e77a16l, + 0xe1a1565d071020eal }, + { 0x4a27f34d3dda8450l,0x65af18b9bc395814l,0xaf21939f9ff49991l, + 0x47e00639b4af7691l }, + 0 }, + /* 33 << 184 */ + { { 0x4b3e263246b1f9b2l,0x6457d838efde99d3l,0x77d5142325e56171l, + 0xb45de3df7d54996cl }, + { 0x1ee2dd3194098d98l,0x986896141f3ebdc5l,0x2704a107997efb47l, + 0x96b502eecb11e520l }, + 0 }, + /* 34 << 184 */ + { { 0x58c8039ec19f866el,0xc84c053e386c2644l,0xb3708ab049435704l, + 0x1b70c3c86fc47b24l }, + { 0x235582a27f095649l,0x0d344b66673c9a9el,0x777c9e71e2b00efdl, + 0x91691d6e5b877856l }, + 0 }, + /* 35 << 184 */ + { { 0x11c663c49cd31e22l,0x46ae0bd95fb943d7l,0x6e36bca6a392fc01l, + 0x4f8cc3a77948716fl }, + { 0x10ae9d6b3aa4bbb0l,0xcc9b6cb5d8001a86l,0x012c8e3aa0a4ceedl, + 0xe462971e52274942l }, + 0 }, + /* 36 << 184 */ + { { 0x9982e2ac42e176a5l,0x324eba46e2782b64l,0x3d8caaafe18350f5l, + 0xf3d82af2f5d674cal }, + { 0xc2090fed56600d1el,0x4548e0ef5950de07l,0xb2f0023f765a4febl, + 0xb303103339f16790l }, + 0 }, + /* 37 << 184 */ + { { 0xb94095dc7bdacf7al,0x0e73db39509b310al,0x76e99a6b41b5f772l, + 0xef40e9c596f3dbd7l }, + { 0xd0d644f980f2179el,0xe0db831d5a89807el,0xa0188493c2a2d6c6l, + 0xf2d9a85e5ba9faa9l }, + 0 }, + /* 39 << 184 */ + { { 0x598b7876cdd95b93l,0x5f7cc827336966e8l,0x01887109e797f102l, + 0x665671c446c7c296l }, + { 0xb314793c6e019c72l,0x5a6c81580e0329acl,0x4faf2f1b44281b98l, + 0x825884072e1fc97el }, + 0 }, + /* 40 << 184 */ + { { 0xa692781d61a3c8b3l,0x08bc385432876d0el,0xbecf05fb28027b03l, + 0x636c687da4b1e12fl }, + { 0x00e3003d07217c58l,0x613ba9375e01b2a3l,0xa58c8405881de16el, + 0xc653c43014f8f48bl }, + 0 }, + /* 41 << 184 */ + { { 0x68e53c7c89c0c7c2l,0xf2e680b23c423272l,0xacd47fae60f50133l, + 0x4c484c6534f05605l }, + { 0x663bdcf9ebffbb7dl,0xb49cff3be42421c6l,0x0549f7b13f53f261l, + 0xc516aeda7c374766l }, + 0 }, + /* 43 << 184 */ + { { 0xa515fe0f76a0ec26l,0xf727c0797b0b8b21l,0xaeed4c671993651el, + 0x1465a7f828ac7c87l }, + { 0x776bd5131f0ef90bl,0x57515d2cd9773e61l,0x235455e95564c50bl, + 0xf44daef80bf06a24l }, + 0 }, + /* 44 << 184 */ + { { 0xbc1c6897d6a0d0f9l,0xd8e0ea0e3b0d7f55l,0xb35baa92b85b7aadl, + 0x2becd1b7674e48f4l }, + { 0xe2d7f78d6d7a9ac2l,0xf5074262f99c95d0l,0x4852470a89f611e9l, + 0xf7aa911992869decl }, + 0 }, + /* 45 << 184 */ + { { 0x0bd1755b0ac4840fl,0x0f4c6c2aa22eef10l,0x3f72fe2d78d16dd9l, + 0xb2d49200ff7096a4l }, + { 0xa5dead555ffca031l,0x1d013c320b65f4cfl,0x67e498582a23f441l, + 0x55bae166d02412c0l }, + 0 }, + /* 46 << 184 */ + { { 0x546dd4545739a62al,0x353dc1422a30b836l,0x1462449d99cbd704l, + 0xda02d0772da69411l }, + { 0xcb115fe565b1a1adl,0x395235f501230a22l,0x8ae630eed164d970l, + 0x60b679f0074e3a7el }, + 0 }, + /* 47 << 184 */ + { { 0x2e64695245d231e1l,0xc96663ac00d8a0fbl,0xc1fbaa0cd07e1f41l, + 0x4b31484488758781l }, + { 0xd6971a835183e72el,0xd1d01f174cbe99b7l,0xe90b438c5a2f7512l, + 0xf858fa452957c620l }, + 0 }, + /* 48 << 184 */ + { { 0xed7f2e774e6daae2l,0x7b3ae0e39e0a19bcl,0xd3293f8a91ae677el, + 0xd363b0cb45c8611fl }, + { 0xbe1d1ccf309ae93bl,0xa3f80be73920cae1l,0xaaacba74498edf01l, + 0x1e6d2a4ab2f5ac90l }, + 0 }, + /* 49 << 184 */ + { { 0xb5c5bb67b972a778l,0xc2423a4a190f9b5al,0x4e693cf365247948l, + 0xc37d129ea94a65a3l }, + { 0xbea4736b6e9cd47bl,0xf3d1bd212338f524l,0xa2a0278e067a45dal, + 0xc86d631b5b5dce9bl }, + 0 }, + /* 51 << 184 */ + { { 0xc2d75f46116952cel,0xd2b66269b75e40dal,0x024f670f921c4111l, + 0x37ffd854c91fd490l }, + { 0x6be44d0385b2f613l,0x040cd7d9ba11c4f9l,0x04c1cb762c0efb1fl, + 0xd905ff4f505e4698l }, + 0 }, + /* 52 << 184 */ + { { 0x60c5f03f233550f1l,0xd4d09411925afd2el,0xa95b65c3d258e5a6l, + 0x1a19cfb59f902c6al }, + { 0xb486013af5ad5c68l,0xa2506776979638f3l,0x1232b4d0a38e0b28l, + 0xa64784b8d36a7b4fl }, + 0 }, + /* 53 << 184 */ + { { 0x22c75830a13dcb47l,0xd6e81258efd7a08fl,0x6db703b6e4fc49b8l, + 0x8a5ac636f01817e9l }, + { 0x8d27b6e1b3f24514l,0x40edc3bc708c51d7l,0x9a1eec7765bb086dl, + 0x812ccb42b10800f8l }, + 0 }, + /* 55 << 184 */ + { { 0x1a39c6acd4338453l,0x3d93822954b1295dl,0x7bf0bf45e0d81165l, + 0x83d58ca5972804d2l }, + { 0x105d3ddb00524b94l,0x65d516e7920378ecl,0x1d28f5f1aea33926l, + 0xa0b354313901c906l }, + 0 }, + /* 57 << 184 */ + { { 0x000442a1e4f354del,0x165b44d9d1d112f5l,0x67fd9ced0d05c0a9l, + 0xd6ce074360bd5d60l }, + { 0x9ac80c931522af2al,0x8232d522fa07d449l,0x287b5534c3fdb652l, + 0x9f0548b3abd2ab98l }, + 0 }, + /* 59 << 184 */ + { { 0xde8d7086b9aea1d4l,0x692180d98a7dc3fcl,0xd64ffb53bad3e6f3l, + 0x84628acf36ce3f91l }, + { 0xf76e470b6d498ac5l,0xa16945547abad602l,0x5b8fd6a5a255c1f6l, + 0xffe24e4a8576ae2al }, + 0 }, + /* 60 << 184 */ + { { 0x5655179de7d70e03l,0x3e780c5c72a84570l,0xc102b4cb1d50029cl, + 0x3e71bdd5f075e839l }, + { 0x6460f4f0b498b822l,0x2682e06c6d4b8da5l,0x4eae53c996a740d4l, + 0xc19d8bef6389702cl }, + 0 }, + /* 61 << 184 */ + { { 0x711be2081025fe1dl,0x2e562c89f0bc6a99l,0xcfd2be3a28bf4150l, + 0x33037b4a38e5bc91l }, + { 0x10c6da9df52fea02l,0x511f62444f0ea410l,0x19d37ca81a294c3fl, + 0x7e40f444618e6fd3l }, + 0 }, + /* 63 << 184 */ + { { 0x4095f5ddbedb8734l,0x9c16027c4432f51al,0xced8179d873d0f11l, + 0x70c2bc9f6ebe6e61l }, + { 0x5c31035d616cf2f4l,0xf92e0fbd00a4af3dl,0xe6048a03511893c4l, + 0x639a804b52e2f462l }, + 0 }, + /* 64 << 184 */ + { { 0x8735728dc2c6ff70l,0x79d6122fc5dc2235l,0x23f5d00319e277f9l, + 0x7ee84e25dded8cc7l }, + { 0x91a8afb063cd880al,0x3f3ea7c63574af60l,0x0cfcdc8402de7f42l, + 0x62d0792fb31aa152l }, + 0 }, + /* 65 << 184 */ + { { 0x0f4bcefd9da373e4l,0x7278f44d119271a3l,0xb2dff94449e111c0l, + 0xb0a3abf8e5d2b2d4l }, + { 0x01baabb48ea80631l,0x27517ed3da305f85l,0x0a1ca6fc3f56aa86l, + 0x183d9c7694c22839l }, + 0 }, + /* 71 << 184 */ + { { 0xe9a0dfbf22e238d7l,0x8690dfd97e8d8d31l,0xb3cb2a0d4006c59cl, + 0xe4d297caa1850d74l }, + { 0x066f10517842d14cl,0x68dd32737d43602bl,0x1f9f5cf931345f39l, + 0x44f18c2b10593890l }, + 0 }, + /* 77 << 184 */ + { { 0x8d8c0233a7c3f60bl,0xfb59fe2d2bcbbd4cl,0xfa311680dc3e5b44l, + 0xb3cba9f3fbea5eedl }, + { 0xcb353b2f61e0e690l,0x06edf0c1b6e0efe0l,0xa29578cb1d0c02a2l, + 0xaeb2d677937fec07l }, + 0 }, + /* 83 << 184 */ + { { 0xa19a81c5cdd0cac9l,0x5c10b942ec9cf85bl,0x0843ef4639e8c298l, + 0xcfd45d0e6c043258l }, + { 0x1011bcb9fb7e4b58l,0xae6362a544402bbdl,0x9ecc8c68ec15d751l, + 0xbc05998869d1a00bl }, + 0 }, + /* 89 << 184 */ + { { 0xe9a43619460147e3l,0x881a6af423067448l,0x94f93ae6cee17a6bl, + 0x469e692f10782558l }, + { 0x01e244a1289bdb32l,0x240645779dddf970l,0x664cbd92d8f521ecl, + 0xadaf8ffb600222d0l }, + 0 }, + /* 95 << 184 */ + { { 0x68314c740dbec437l,0x2095e1295ec75e2cl,0x8e88a3ddf0e6c606l, + 0x40ac647d1230f6b2l }, + { 0x09d124aaa2e6b991l,0xa22f9e2bcc81037cl,0xc842b64d15c3a1c2l, + 0x4d822becce808c65l }, + 0 }, + /* 101 << 184 */ + { { 0xb02204d06ffb396bl,0x82eb6ecc881bead6l,0xf58432cebd6896c8l, + 0xc243468da38f4b9dl }, + { 0x8486402df8e628bdl,0x5dd338a1a4df2401l,0x748a41ab0daac953l, + 0xaa121d13e51e6235l }, + 0 }, + /* 107 << 184 */ + { { 0x6daa0a4e50abc6aal,0x99fcc5bdeafb7cf2l,0xc705f64c4b8dbd2al, + 0x7deff836e7b51e90l }, + { 0xd92f42b859a8180fl,0x3bb298f8618d24acl,0x2433aa7357a56438l, + 0xcf29895b48a6a238l }, + 0 }, + /* 113 << 184 */ + { { 0x74079dc59ed25aafl,0x7988245c023d5143l,0x7edfc6a6feb79c24l, + 0x7ed03c50a6baa70fl }, + { 0x71d3413596a753b4l,0x59efbafcef976246l,0xed050260a4a6947fl, + 0xabbc1f8066254247l }, + 0 }, + /* 116 << 184 */ + { { 0x1f804e00caa4646fl,0x8643dc8870944924l,0xa37f1ca273f86de9l, + 0xa3199f9228889898l }, + { 0xc273ba580c1e4adfl,0x0f0d38af65bc82f0l,0xd8b28ab5f8a6cd3bl, + 0xeea6e08575894d8el }, + 0 }, + /* 119 << 184 */ + { { 0x398f39132c1620f7l,0x9046d2dea921f3a3l,0x40a25a2785b50bb0l, + 0xb9adeca0d32e95f3l }, + { 0xa4199b1bdede5cbfl,0x9068aee084f5410bl,0x6665e4f5730f0397l, + 0x2e9ba18c8ae20659l }, + 0 }, + /* 125 << 184 */ + { { 0xd76e9b2351835897l,0x72a0e000012deda6l,0x5bf08922bfec23e4l, + 0x8c2fcf1385cf2b7bl }, + { 0x6c42f935c63332c6l,0x8736c58395eccce9l,0x2d2abbb10721afc8l, + 0x1f7a76cc42d4e029l }, + 0 }, + }, + { + /* 0 << 192 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 192 */ + { { 0x56f8410ef4f8b16al,0x97241afec47b266al,0x0a406b8e6d9c87c1l, + 0x803f3e02cd42ab1bl }, + { 0x7f0309a804dbec69l,0xa83b85f73bbad05fl,0xc6097273ad8e197fl, + 0xc097440e5067adc1l }, + 0 }, + /* 3 << 192 */ + { { 0x266344a43794f8dcl,0xdcca923a483c5c36l,0x2d6b6bbf3f9d10a0l, + 0xb320c5ca81d9bdf3l }, + { 0x620e28ff47b50a95l,0x933e3b01cef03371l,0xf081bf8599100153l, + 0x183be9a0c3a8c8d6l }, + 0 }, + /* 4 << 192 */ + { { 0xb6c185c341dca566l,0x7de7fedad8622aa3l,0x99e84d92901b6dfbl, + 0x30a02b0e7c4ad288l }, + { 0xc7c81daa2fd3cf36l,0xd1319547df89e59fl,0xb2be8184cd496733l, + 0xd5f449eb93d3412bl }, + 0 }, + /* 5 << 192 */ + { { 0x25470fabe085116bl,0x04a4337587285310l,0x4e39187ee2bfd52fl, + 0x36166b447d9ebc74l }, + { 0x92ad433cfd4b322cl,0x726aa817ba79ab51l,0xf96eacd8c1db15ebl, + 0xfaf71e910476be63l }, + 0 }, + /* 7 << 192 */ + { { 0x72cfd2e949dee168l,0x1ae052233e2af239l,0x009e75be1d94066al, + 0x6cca31c738abf413l }, + { 0xb50bd61d9bc49908l,0x4a9b4a8cf5e2bc1el,0xeb6cc5f7946f83acl, + 0x27da93fcebffab28l }, + 0 }, + /* 9 << 192 */ + { { 0x3ce519ef76257c51l,0x6f5818d318d477e7l,0xab022e037963edc0l, + 0xf0403a898bd1f5f3l }, + { 0xe43b8da0496033cal,0x0994e10ea1cfdd72l,0xb1ec6d20ba73c0e2l, + 0x0329c9ecb6bcfad1l }, + 0 }, + /* 10 << 192 */ + { { 0xf1ff42a12c84bd9dl,0x751f3ec4390c674al,0x27bb36f701e5e0cal, + 0x65dfff515caf6692l }, + { 0x5df579c4cd7bbd3fl,0xef8fb29785591205l,0x1ded7203e47ac732l, + 0xa93dc45ccd1c331al }, + 0 }, + /* 11 << 192 */ + { { 0xbdec338e3318d2d4l,0x733dd7bbbe8de963l,0x61bcc3baa2c47ebdl, + 0xa821ad1935efcbdel }, + { 0x91ac668c024cdd5cl,0x7ba558e4c1cdfa49l,0x491d4ce0908fb4dal, + 0x7ba869f9f685bde8l }, + 0 }, + /* 13 << 192 */ + { { 0xed1b5ec279f464bal,0x2d65e42c47d72e26l,0x8198e5749e67f926l, + 0x4106673834747e44l }, + { 0x4637acc1e37e5447l,0x02cbc9ecf3e15822l,0x58a8e98e805aa83cl, + 0x73facd6e5595e800l }, + 0 }, + /* 15 << 192 */ + { { 0x468ff80338330507l,0x06f34ddf4037a53el,0x70cd1a408d6993a4l, + 0xf85a159743e5c022l }, + { 0x396fc9c2c125a67dl,0x03b7bebf1064bfcbl,0x7c444592a9806dcbl, + 0x1b02614b4487cd54l }, + 0 }, + /* 16 << 192 */ + { { 0x8303604f692ac542l,0xf079ffe1227b91d3l,0x19f63e6315aaf9bdl, + 0xf99ee565f1f344fbl }, + { 0x8a1d661fd6219199l,0x8c883bc6d48ce41cl,0x1065118f3c74d904l, + 0x713889ee0faf8b1bl }, + 0 }, + /* 17 << 192 */ + { { 0xb47b60f70de21bb6l,0x64acae4fdcd836cal,0x3375ea6dc744ce63l, + 0xb764265fb047955bl }, + { 0xc68a5d4c9841c2c3l,0x60e98fd7cf454f60l,0xc701fbe2756aea0cl, + 0x09c8885eaab21c79l }, + 0 }, + /* 19 << 192 */ + { { 0x45bb810869d2d46cl,0xe47c8b3968c8365al,0xf3b87663267551bdl, + 0x1590768f5b67547al }, + { 0x371c1db2fb2ed3ffl,0xe316691917a59440l,0x03c0d178df242c14l, + 0x40c93fceed862ac1l }, + 0 }, + /* 21 << 192 */ + { { 0x1286da692bc982d6l,0x5f6d80f27bdae7e3l,0x3d9c5647a6f064fbl, + 0xfdc8e6a1d74c1540l }, + { 0x97da48c6d68b135al,0xc2097979d66dbfffl,0x0296adb9ea20531dl, + 0xa333730d4ab2c8f0l }, + 0 }, + /* 23 << 192 */ + { { 0x0eb3565429847fedl,0xfdc142860a673dd0l,0x721b36278b62dd0bl, + 0x105a293e711a5771l }, + { 0xdf001cce7f761927l,0xf7b681b011d04c7dl,0x16dff792a3ac1996l, + 0x580c120b0fc4ae30l }, + 0 }, + /* 25 << 192 */ + { { 0x31ea3d4f7ee8d0bcl,0x3832f22a0f42c3dcl,0xc661061a1a87a2f4l, + 0x0978c9f64b45576bl }, + { 0xb7abac3c6dfb5fd2l,0x27f36a00b7e01b90l,0x68f733cde9429e36l, + 0x953a4681dcbfe8cbl }, + 0 }, + /* 27 << 192 */ + { { 0xbfb7c41067fe1eafl,0xa2073c6a6929a785l,0x6f2536f4a75fdb79l, + 0x859ad26d809bca69l }, + { 0x06f2c0693b197e7bl,0x656ad9f48ec0a573l,0xe7c7901f9a4d0262l, + 0xbec29443b938602bl }, + 0 }, + /* 28 << 192 */ + { { 0xd00397fc0f0073a4l,0x5b668fa46f8d675fl,0x14374ac91522108cl, + 0x92efa7d10283e42el }, + { 0x673e6df90b6d024al,0x05f914d457581f26l,0xf5c8516267df8c12l, + 0x1197f1b4e06c2462l }, + 0 }, + /* 29 << 192 */ + { { 0x6e2d1cb3dd9c90c1l,0x28f82d5a7990579el,0x90e189cd06226195l, + 0xbd2939df19b0dc74l }, + { 0x18b18505c0917177l,0xeed5470d3117d9c4l,0x39ef92eb6c893ca0l, + 0x4533ef8244a41940l }, + 0 }, + /* 31 << 192 */ + { { 0xcaee9dec34943ddal,0x8e50e98e8b4b6782l,0x24358ea591ea3a1fl, + 0x71c4c827a9e1c194l }, + { 0xa38baa5d09bb7a94l,0xfb4ab4c057b58f9cl,0x4a01065e24e0ee19l, + 0xb9cf805107b877bfl }, + 0 }, + /* 33 << 192 */ + { { 0xd38c1ce0a2980d5el,0x8b84cca4541face7l,0x93298136dbd8d05dl, + 0x582708d03f85c85al }, + { 0x6545eec7282960e4l,0x92e184aebaadec07l,0x05452564fd27a20fl, + 0x79d4668abddce6ebl }, + 0 }, + /* 34 << 192 */ + { { 0xf5cc5cccf5191707l,0xe800328bd5d01f67l,0x0572012ebd9b1599l, + 0xf5be11a6863d0125l }, + { 0x4da7ca876ea441e0l,0x47dbf83b321b134al,0x5cbadcdac1acfb4al, + 0x19ac798a734f8e25l }, + 0 }, + /* 35 << 192 */ + { { 0xe312623a7002114fl,0xb888b637e047686bl,0x23b2c270cbac91bdl, + 0xb50b31884dbfe02dl }, + { 0x8335ce43de97eef6l,0x6a4e65502bac193al,0xf2b35aac3101f720l, + 0x5b2c88d5379a2015l }, + 0 }, + /* 36 << 192 */ + { { 0xf445e77131547128l,0x22761665e27811cal,0x9b944e91a37c6681l, + 0xc0aa06a536899860l }, + { 0x8c2b5816cfcd557el,0xf2734a19945aa357l,0x536ca07ca55a0049l, + 0x8328fdccc636d967l }, + 0 }, + /* 37 << 192 */ + { { 0x52b513616aca06bdl,0x8d19b893cdf16560l,0x06b28179c3b438cdl, + 0xde1ef747cd1819e4l }, + { 0xbc6cc43b5f557985l,0xa277e11f61e0142al,0x58890f1e429cc392l, + 0x28d17dbfe5fc8f5el }, + 0 }, + /* 39 << 192 */ + { { 0x556df61a29a8f7cbl,0x5cf554dfd14ab27al,0x243f933ba755b886l, + 0xa4d0b06ff2d4ce87l }, + { 0xa745eb8d2c0f1d39l,0xc228747aea3047a5l,0xced774c41d2cecc0l, + 0x54a55c3a774fb01al }, + 0 }, + /* 40 << 192 */ + { { 0xa691398a4a9eb3f0l,0x56c1dbff3b99a48fl,0x9a87e1b91b4b5b32l, + 0xad6396145378b5fel }, + { 0x437a243ec26b5302l,0x0275878c3ccb4c10l,0x0e81e4a21de07015l, + 0x0c6265c9850df3c0l }, + 0 }, + /* 41 << 192 */ + { { 0x182c3f0e6be95db0l,0x8c5ab38cae065c62l,0xcce8294ebe23abacl, + 0xed5b65c47d0add6dl }, + { 0xbce57d78cc9494cal,0x76f75c717f435877l,0xb3084b2eb06560a9l, + 0x67216bc850b55981l }, + 0 }, + /* 43 << 192 */ + { { 0x49c9fd92557de68bl,0x357aa44fc3151b7al,0xd36286d11e4aebd0l, + 0x84562cd736a51203l }, + { 0x42a57e7c3cacc002l,0x794a47751b1e25a3l,0x2c2ab68cac0d4356l, + 0xececb6addb31afdcl }, + 0 }, + /* 44 << 192 */ + { { 0x47a5f010b4c21bfel,0x45c5610f0ac3dc20l,0x20e689fcea3bf4dcl, + 0xf244ea49fb5f46e4l }, + { 0xd918e59e8ca38e45l,0x7d6c601d96189a6fl,0x1a40f03854138471l, + 0xfe867d7308a9d034l }, + 0 }, + /* 45 << 192 */ + { { 0x3b49e489100c0410l,0x8831d3992adc2b29l,0xb6726cd1247a8116l, + 0x83a71a59d1d56d8el }, + { 0x82ade2fe5cd333e9l,0x3b087ef83ea11f1al,0x17b96ca66ce879cel, + 0xc2f74a971871dc43l }, + 0 }, + /* 46 << 192 */ + { { 0xa11a1e3680b576cel,0xf91278bbce2683e8l,0xc3bab95fbae8bc5bl, + 0x642ca26397351715l }, + { 0x5ffc14726fecbbc1l,0x2465e996a23f36d4l,0x06fc53bf5187d428l, + 0x54b4014351fbce91l }, + 0 }, + /* 47 << 192 */ + { { 0x081ca6f0eafc7b2cl,0x1ba047a38c48703fl,0xe84865046663accfl, + 0xde1f97568d43689cl }, + { 0xf5373e1d5bc19f75l,0x4e48c493d64b0a54l,0x0c43f4e25807dbf6l, + 0x73bef15167778c36l }, + 0 }, + /* 48 << 192 */ + { { 0xca6c0937b1b76ba6l,0x1a2eab854d2026dcl,0xb1715e1519d9ae0al, + 0xf1ad9199bac4a026l }, + { 0x35b3dfb807ea7b0el,0xedf5496f3ed9eb89l,0x8932e5ff2d6d08abl, + 0xf314874e25bd2731l }, + 0 }, + /* 49 << 192 */ + { { 0x9d5322e89e9bba53l,0xdd7c9ceb989ff350l,0xd76147eadab0d7b3l, + 0x8e45b1c6d7a9a9a1l }, + { 0x8f896a91d4f10c10l,0x999a73c54068de06l,0x84a9d0839cf0a779l, + 0x4d7cc7689f608ab2l }, + 0 }, + /* 51 << 192 */ + { { 0x1833ccddaee93c82l,0x6a05ef7b9f35f20fl,0xc538dac9ae413bc2l, + 0x1e74f4658b4784bdl }, + { 0xccb2bc4a49ffd544l,0x9b88183d2b17ae88l,0x96037a136e43824fl, + 0xbbb61441480bf3dfl }, + 0 }, + /* 52 << 192 */ + { { 0x13319d20e090ad42l,0x4ff3186e12cbb719l,0xf38e504913fc0a46l, + 0x83185a1254e60378l }, + { 0x08c4057797ea8935l,0x7b2212a946b614f9l,0xedcdfa520634cfb3l, + 0xdbc60eed9e7d5726l }, + 0 }, + /* 53 << 192 */ + { { 0x9b0785c6c7e1070fl,0xec112f53cbf561e5l,0xc93511e37fab3464l, + 0x9e6dc4da9de8e0c2l }, + { 0x7733c425e206b4eel,0xb8b254ef50cedf29l,0xfaee4bbbd50ad285l, + 0x216e76d58c4eb6cfl }, + 0 }, + /* 55 << 192 */ + { { 0x9d6a28641d51f254l,0x26c5062a0c2822c3l,0xd74ebba8334bf4eel, + 0x6e5446eb0b8f7305l }, + { 0x5988ae8eb629beccl,0x71e576d0a1de7d1dl,0x15e39592a8873970l, + 0x2b1f9a9342ecc74el }, + 0 }, + /* 57 << 192 */ + { { 0xcbdb70727c519bf9l,0x112986bbcaaf48e6l,0x64d4c6d1a13baf3cl, + 0x85ccf6f7a065e77el }, + { 0x183be337749beaedl,0xb3703096cba6c9b1l,0x1edf81f0e42b8afel, + 0xf04ed594ccb73ad7l }, + 0 }, + /* 59 << 192 */ + { { 0xfa954ebc38491e9fl,0xf75a5808d32f0b03l,0x196d4a828083b9d3l, + 0x92d5a0be5e8dc9fel }, + { 0x4a507ae9aea628bal,0xeea5861e11a02fb5l,0xa033b84fd23ec8f7l, + 0x1a68c36ec60f11d5l }, + 0 }, + /* 60 << 192 */ + { { 0x3dfb55bdab920ef2l,0xe0090971e6244484l,0xdc39fd08f7c6e1a3l, + 0x1ca765356ee79e72l }, + { 0x472c8985287d590cl,0x67635e35ad6daeb4l,0x06ec4e7980f9fee3l, + 0x0aceb39921dc5fdbl }, + 0 }, + /* 61 << 192 */ + { { 0xdb2478fd9410a756l,0xd106aefe3a53a1e6l,0x1f4c940d14286333l, + 0x6a98659d04950958l }, + { 0x3232a1c6a6bbe060l,0x19ad132ca5e7ca9bl,0x3c9c13ef800fae29l, + 0x9b0d9068b8660f49l }, + 0 }, + /* 63 << 192 */ + { { 0x1e7f043795c53027l,0x5221e5c0da9a3806l,0xf297d8e379d9385fl, + 0x4d69e95f78ba697el }, + { 0xdda936cee76d13c1l,0xd9a5790a485b12f5l,0xeab84add51efbfd0l, + 0xc9a3ee9ca9f44aa4l }, + 0 }, + /* 64 << 192 */ + { { 0xefb26a753f73f449l,0x1d1c94f88d44fc79l,0x49f0fbc53bc0dc4dl, + 0xb747ea0b3698a0d0l }, + { 0x5218c3fe228d291el,0x35b804b543c129d6l,0xfac859b8d1acc516l, + 0x6c10697d95d6e668l }, + 0 }, + /* 65 << 192 */ + { { 0x8c12e87a15454db4l,0xbc1fc546908e8fbcl,0xc35d83c7e4cf1636l, + 0xcb2f5ac820641524l }, + { 0x2400aae2e644ecd0l,0x9b01e2d14be37119l,0x6cffd52831b54857l, + 0xb3fd5d864b5cbf81l }, + 0 }, + /* 71 << 192 */ + { { 0x2e999a4739709fb9l,0x4cb4bbdb62c2b30fl,0x4c7259ac09de0c92l, + 0x73c1e34f8c59a0ffl }, + { 0x0a9e5f2e48cb0a12l,0x5e07449fcf499bb0l,0x0527a8b4b02c4a54l, + 0x7381287159da01e4l }, + 0 }, + /* 77 << 192 */ + { { 0xe0b876ca0548ff87l,0x74b5a9b25e03bae3l,0xd5564cc5dd0642d2l, + 0x29ed211b668c4977l }, + { 0xf29d3b7aa7422b11l,0x17f2d3586d29b8bal,0x2e35cdda2bb887del, + 0x650f148078e4444bl }, + 0 }, + /* 83 << 192 */ + { { 0x8c75532fb47435ebl,0x2234e2c5a113f905l,0x27b75fea31508ae9l, + 0x09733e40d489ad0bl }, + { 0x73b38464a1b06da1l,0x0aed522dc5b7ccf2l,0xcc04783e78d7e5afl, + 0xa81c8a8ff23eaab7l }, + 0 }, + /* 89 << 192 */ + { { 0x6bb5eca73c149ffal,0x4593d851c536487al,0x3675daaad85eb9edl, + 0xbf65d0f9b8a58ffbl }, + { 0x1dc6ddddc22e83eel,0xb673397ee10d3c17l,0x6bdc20600ca62c93l, + 0x260389c30b821f6dl }, + 0 }, + /* 95 << 192 */ + { { 0x45f5cf07b417be10l,0x0acb1a44e5d561d8l,0x54b7baeafb1dfbe9l, + 0x0e6e66219044672el }, + { 0xa9b6db6d9a793601l,0xd70eadb8a4a0ba4al,0xaedace846098b89el, + 0x970f2c23ac39d40fl }, + 0 }, + /* 101 << 192 */ + { { 0x9dff8d289c7eaaa8l,0x38bcd076db0cc361l,0x25760147cdea9db8l, + 0x44c89dd40163f343l }, + { 0x18815d7544db8365l,0xa186d57b37f3e4b3l,0xa71de7806e84a7fal, + 0xf1c08989e56646b3l }, + 0 }, + /* 107 << 192 */ + { { 0xad73e1448fb56a43l,0x078c14fb715543c9l,0xa57770fd64b92d54l, + 0xf0420a9277e9b919l }, + { 0xc660d0cb588ccc1dl,0x069baa1471415c2el,0x747438dc32982740l, + 0x4782ce08767381eel }, + 0 }, + /* 113 << 192 */ + { { 0xc2a1ee5fdb3b6b5dl,0x08ce544820e1339fl,0x3cb954b77073955fl, + 0xb9ed2ee7f32d0832l }, + { 0xc0a998b1b4aac98el,0x4912273dbca4bac7l,0xac0f5014c3f92c4al, + 0xbf3dc27f9e916e78l }, + 0 }, + /* 116 << 192 */ + { { 0x222c7bae28833944l,0xbb78a867f5e3cf67l,0x590cbd96faf6cfd6l, + 0x1c50aecb3b0d842el }, + { 0x8f2c5df1dbade9a5l,0x60923fb7e3840cecl,0xe8f2db6b03a67512l, + 0x90af187be0d7c628l }, + 0 }, + /* 119 << 192 */ + { { 0xb4162b615fee3ccbl,0xe9786e7d7327e651l,0x6c85bd938812d9c1l, + 0xfe4905083dc9e838l }, + { 0xe66f25178a6765dfl,0x72fd294edeee184cl,0x07608bd27b6ec227l, + 0x9df7b664dfdaa5e6l }, + 0 }, + /* 125 << 192 */ + { { 0x4aea16602d53a155l,0x7285069a32ab07fdl,0xf6f3000d8b6fcd19l, + 0x010b1f246e98953fl }, + { 0xe180bc559f9aa221l,0x7717ee383cba4534l,0x5997f3aa36cbda06l, + 0x54c6090064a04b05l }, + 0 }, + }, + { + /* 0 << 200 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 200 */ + { { 0x25914f7881fdad90l,0xcf638f560d2cf6abl,0xb90bc03fcc054de5l, + 0x932811a718b06350l }, + { 0x2f00b3309bbd11ffl,0x76108a6fb4044974l,0x801bb9e0a851d266l, + 0x0dd099bebf8990c1l }, + 0 }, + /* 3 << 200 */ + { { 0xebd6a6777b0ac93dl,0xa6e37b0d78f5e0d7l,0x2516c09676f5492bl, + 0x1e4bf8889ac05f3al }, + { 0xcdb42ce04df0ba2bl,0x935d5cfd5062341bl,0x8a30333382acac20l, + 0x429438c45198b00el }, + 0 }, + /* 4 << 200 */ + { { 0xfb2838be67e573e0l,0x05891db94084c44bl,0x9131137396c1c2c5l, + 0x6aebfa3fd958444bl }, + { 0xac9cdce9e56e55c1l,0x7148ced32caa46d0l,0x2e10c7efb61fe8ebl, + 0x9fd835daff97cf4dl }, + 0 }, + /* 5 << 200 */ + { { 0x6c626f56c1770616l,0x5351909e09da9a2dl,0xe58e6825a3730e45l, + 0x9d8c8bc003ef0a79l }, + { 0x543f78b6056becfdl,0x33f13253a090b36dl,0x82ad4997794432f9l, + 0x1386493c4721f502l }, + 0 }, + /* 7 << 200 */ + { { 0xe566f400b008733al,0xcba0697d512e1f57l,0x9537c2b240509cd0l, + 0x5f989c6957353d8cl }, + { 0x7dbec9724c3c2b2fl,0x90e02fa8ff031fa8l,0xf4d15c53cfd5d11fl, + 0xb3404fae48314dfcl }, + 0 }, + /* 9 << 200 */ + { { 0xf02cc3a9f327a07fl,0xefb27a9b4490937dl,0x81451e96b1b3afa5l, + 0x67e24de891883be4l }, + { 0x1ad65d4770869e54l,0xd36291a464a3856al,0x070a1abf7132e880l, + 0x9511d0a30e28dfdfl }, + 0 }, + /* 10 << 200 */ + { { 0xfdeed650f8d1cac4l,0xeb99194b6d16bda5l,0xb53b19f71cabbe46l, + 0x5f45af5039b9276cl }, + { 0xd0784c6126ee9d77l,0xf7a1558b0c02ca5dl,0xb61d6c59f032e720l, + 0xae3ffb95470cf3f7l }, + 0 }, + /* 11 << 200 */ + { { 0x9b185facc72a4be5l,0xf66de2364d848089l,0xba14d07c717afea9l, + 0x25bfbfc02d551c1cl }, + { 0x2cef0ecd4cdf3d88l,0x8cee2aa3647f73c4l,0xc10a7d3d722d67f7l, + 0x090037a294564a21l }, + 0 }, + /* 13 << 200 */ + { { 0x6ac07bb84f3815c4l,0xddb9f6241aa9017el,0x31e30228ca85720al, + 0xe59d63f57cb75838l }, + { 0x69e18e777baad2d0l,0x2cfdb784d42f5d73l,0x025dd53df5774983l, + 0x2f80e7cee042cd52l }, + 0 }, + /* 15 << 200 */ + { { 0x43f18d7f4d6ee4abl,0xd3ac8cde9570c3dcl,0x527e49070b8c9b2al, + 0x716709a7c5a4c0f1l }, + { 0x930852b0916a26b1l,0x3cc17fcf4e071177l,0x34f5e3d459694868l, + 0xee0341aba28f655dl }, + 0 }, + /* 16 << 200 */ + { { 0xf431f462060b5f61l,0xa56f46b47bd057c2l,0x348dca6c47e1bf65l, + 0x9a38783e41bcf1ffl }, + { 0x7a5d33a9da710718l,0x5a7799872e0aeaf6l,0xca87314d2d29d187l, + 0xfa0edc3ec687d733l }, + 0 }, + /* 17 << 200 */ + { { 0x4b764317aa365220l,0x7a24affe68cc0355l,0x76732ed0ceb3df5el, + 0x2ce1332aae096ed0l }, + { 0x89ce70a7b8adac9dl,0xfdddcf05b3fc85c8l,0xbd7b29c6f2ee8bfel, + 0xa1effcb9457d50f3l }, + 0 }, + /* 19 << 200 */ + { { 0x6053972dac953207l,0xc2ca9a8408ad12f6l,0x9ed6cd386ba36190l, + 0xa5b50a48539d18a4l }, + { 0xd9491347dbf18c2al,0x2cdce4662e9697cfl,0x4e97db5ca9e31819l, + 0x0fb02e2d4c044b74l }, + 0 }, + /* 21 << 200 */ + { { 0x66a4dd414aa5e9ddl,0x6ec7576e64f6aeb9l,0x3f08ce06c7e980b5l, + 0x52fe9fd6c1a2aa7el }, + { 0xfe46e6d95074326al,0xd570ed734c126c1dl,0x86c7ec257217d55al, + 0x3cb434057c3de2b2l }, + 0 }, + /* 23 << 200 */ + { { 0x48e0295dcc9e79bfl,0x2419485693eb403dl,0x9386fb7709dd8194l, + 0xb6e89bb101a242f6l }, + { 0xc7994f3924d308d7l,0xf0fbc392de673d88l,0x43eed52ea11abb62l, + 0xc900f9d0c83e7fbel }, + 0 }, + /* 25 << 200 */ + { { 0x214a10dca8152891l,0xe6787b4c64f1abb2l,0x276333d9fa1a10edl, + 0xc0e1c88e47dbccbcl }, + { 0x8a3c37c4849dd12el,0x2144a8c8d86e109fl,0xbb6891f7286c140cl, + 0xb0b8c5e29cce5e6fl }, + 0 }, + /* 27 << 200 */ + { { 0x3f9e0e3499753288l,0x6b26f1ebe559d93al,0x647fe21d9841faf1l, + 0x48a4b6efa786ea02l }, + { 0x6e09cd22665a882dl,0x95390d81b63ccda6l,0x5b014db4b026a44al, + 0x5b96efb22ad30ff1l }, + 0 }, + /* 28 << 200 */ + { { 0x64c50c8b4a3b99e9l,0x2489a675d0a26f4fl,0xe2aacaeed85bc6fdl, + 0x556882038a6019bal }, + { 0x7ceb9da645cfac07l,0xe1ad3d25652dbd09l,0x086adf348d3b5d2bl, + 0xf9256d8aec3654a0l }, + 0 }, + /* 29 << 200 */ + { { 0x571c246bf009a690l,0x8fe54231ccd90d3al,0x8adde6adfe173b79l, + 0x75d9a392b05a5e3bl }, + { 0x607f47b0d1bb3a84l,0xe4e3b472058e691al,0xfc0f793bf3d956e3l, + 0x6a6730b605de54dal }, + 0 }, + /* 31 << 200 */ + { { 0x4daf7f540d80aaa1l,0xc571d04c229c4574l,0x469e2da5fffca53dl, + 0x9fffe29513ff7f59l }, + { 0x2075da5a33a254f7l,0x769f33acd35e575dl,0x7b940d2c3d35001al, + 0x2d606b57e34c95b7l }, + 0 }, + /* 33 << 200 */ + { { 0xc7e4f8b899365f86l,0x8f6f959faae69527l,0x749ffedffdfaeeeal, + 0x2b91f0221b54c2a0l }, + { 0xe75c2352addbdf83l,0xe7329922fff2694cl,0xbb65ae06badadeacl, + 0x16cbb9d1f56be3b5l }, + 0 }, + /* 34 << 200 */ + { { 0xb100a4c67a07bd70l,0x222fee7634787efel,0xa4dafc14f1e79d1bl, + 0x0d3a82dad18b8be4l }, + { 0xe0181445fc06922fl,0x0873d99b714a90b6l,0xdf43082fa5087a0el, + 0x195e49367399e0dbl }, + 0 }, + /* 35 << 200 */ + { { 0x7e83545aae6fcc9cl,0x1a24fce819e15ce2l,0x4a3465c536d8c6a8l, + 0xd1e5f24109436ae0l }, + { 0xed334bfc6be463d5l,0xc46a600b934fbdcfl,0xbd2fd65b920321ffl, + 0x953fa91767fa154el }, + 0 }, + /* 36 << 200 */ + { { 0x5dca4995f93ddad1l,0x061efcabf72470c2l,0xad78d54d5e7e0741l, + 0xa91f4e839c4e0ab4l }, + { 0xdd4403af5c75aa0dl,0x4308c8ee13c69113l,0x3a3b66f51ebc36adl, + 0xc07cc3f0f4bf777al }, + 0 }, + /* 37 << 200 */ + { { 0x3fd1963e37a86b32l,0x22e236d60bd0880el,0xb87467cf89f0fa5cl, + 0x85b9c6c0310e0265l }, + { 0x82979a96783459ael,0xd19b0919bd529ed3l,0xa21f771808434f94l, + 0x3dd130a9195369c6l }, + 0 }, + /* 39 << 200 */ + { { 0xc61e62767915d157l,0xc48244279e07fb0el,0x8980c1cc8420ea49l, + 0x10d82e4a588d4e2bl }, + { 0xdddecd52b17eff2dl,0xe44c7b2ded8492a4l,0x96ca89ebb9bea6afl, + 0x724166fe1b03ed03l }, + 0 }, + /* 40 << 200 */ + { { 0xfc87975f8fb54738l,0x3516078827c3ead3l,0x834116d2b74a085al, + 0x53c99a73a62fe996l }, + { 0x87585be05b81c51bl,0x925bafa8be0852b7l,0x76a4fafda84d19a7l, + 0x39a45982585206d4l }, + 0 }, + /* 41 << 200 */ + { { 0x8bbc484ed551f3e1l,0x6e058a90b7eb06d2l,0xfaccd9a0e5cd281al, + 0xe7661b78d5b44900l }, + { 0x03afe115725fde22l,0xbe929230c7229fd1l,0x5cd0d16a0000035el, + 0x1f6a9df0c8f5a910l }, + 0 }, + /* 43 << 200 */ + { { 0xe54bbcfd535dfc82l,0x89be0b89a9012196l,0xa67831ee71011beal, + 0x2ea7a8292db43878l }, + { 0xff7c144378ffe871l,0xa67dc3d4c63f65eal,0xbbfc7fc2a1527419l, + 0x6440380bf6c36b8fl }, + 0 }, + /* 44 << 200 */ + { { 0x71ab9f69d812d7e6l,0x2847c5516e142126l,0x9e27755bb31e7753l, + 0xb89533e2943b8c7fl }, + { 0xbe7f0c6e14fa7dc6l,0x782a06388cee1f7al,0x7069292938e13a6bl, + 0x1e1221f0c63f4d28l }, + 0 }, + /* 45 << 200 */ + { { 0x9030aa9a63a431f4l,0x0fa7b5d45039a318l,0x6a0cf40af083687dl, + 0x46689cec659fa752l }, + { 0x8259727a456fa97el,0x4f618a355b08d7fcl,0x2c44217b72028d15l, + 0x8083b09935111e32l }, + 0 }, + /* 46 << 200 */ + { { 0xaa5976523b5b29f1l,0xb07f10ab37432a54l,0x16e3e2236e36556fl, + 0xf1c7c9bd47cd4586l }, + { 0xa4eef99d3f87216dl,0x4e54d3c52e1eaa79l,0x534c5901d2540d91l, + 0x718df7c9b6f0fcfcl }, + 0 }, + /* 47 << 200 */ + { { 0x99497f8a2eb0ee3bl,0x87e550c1caeb3a20l,0xd23e053dfb91627cl, + 0xb971c043873124e6l }, + { 0x3581ab853b16e467l,0x24541c926145187bl,0x4423ec5c010c2527l, + 0x775f13029fa82a68l }, + 0 }, + /* 48 << 200 */ + { { 0x499b6ab65eb03c0el,0xf19b795472bc3fdel,0xa86b5b9c6e3a80d2l, + 0xe43775086d42819fl }, + { 0xc1663650bb3ee8a3l,0x75eb14fcb132075fl,0xa8ccc9067ad834f6l, + 0xea6a2474e6e92ffdl }, + 0 }, + /* 49 << 200 */ + { { 0xbaebdd8a0c40aec4l,0x5eccafb563e8cfd0l,0x1c204c0eb5159938l, + 0x607109d34b996aa9l }, + { 0x024c6c4b9cef59fel,0xbc846e216ed4b6f1l,0xf6a50ff3ff652c0al, + 0x368af2c72d95220cl }, + 0 }, + /* 51 << 200 */ + { { 0xec9c2e35cbd3ccafl,0xb9eeff3ddcda8f30l,0x82012e191062d02el, + 0xed964cc94efc6b6el }, + { 0x8853ea0a6bf54c22l,0xea40fcc0f3cbe264l,0x21f9c01ddecf114el, + 0x05e754c63da71e59l }, + 0 }, + /* 52 << 200 */ + { { 0xe6a26d38046dfc72l,0x70409579c2175175l,0x2a575ac5d44e0c1dl, + 0xb35395e01479ab5al }, + { 0x1550a5d4f7bfbd8el,0x01daeb680778807bl,0xe0aa940321294dbal, + 0x84bcdc8c5b5a93b7l }, + 0 }, + /* 53 << 200 */ + { { 0x876cc4d2520f04abl,0x6e320f5da85ff6a8l,0x7c504720ce17bc80l, + 0xe7907079a62089f9l }, + { 0xa45c4ac7bca45feel,0xd8f3facd5bd54b0cl,0xc0b036277b3e4a24l, + 0xaabe96dfe4cd4b57l }, + 0 }, + /* 55 << 200 */ + { { 0xdc85a54773862ce4l,0x169051a3cc6f5d85l,0x8e3d3be0355f4df7l, + 0xa139d6fac72bac76l }, + { 0xddc95d0dfeb0a6f0l,0xd53f70e545cd6955l,0x18eede5e47e54112l, + 0x4a135dc9cbc6a52el }, + 0 }, + /* 57 << 200 */ + { { 0x705a08ba90a58fb4l,0x10eef880fb3f8a64l,0x4ced9ba2f8e585ffl, + 0xb4f0f955fc6ebef5l }, + { 0x152c1a338d8b739el,0xb2be701db495bee5l,0xd27141a8d3540a74l, + 0x20c8a00247f9e9d7l }, + 0 }, + /* 59 << 200 */ + { { 0x6d5ae921f5adcb3fl,0xaed1047003a3b610l,0x7c75e36f22256df9l, + 0xe664b36fb97dae99l }, + { 0x138b5eca91e746ael,0xb3e01ef5648674a7l,0xa3f256da9e375c74l, + 0xa00e82bc6a82d6f3l }, + 0 }, + /* 60 << 200 */ + { { 0xe7a01eae6e28b4a8l,0xb3bf8224782166c9l,0x0b7ba2a06a244510l, + 0x9751a69c2abbb4dbl }, + { 0xb611adc1b3f9fcbcl,0x1d08eb3b436c4675l,0x1c71e98a20f96a64l, + 0x33d9b58c7ffd3f08l }, + 0 }, + /* 61 << 200 */ + { { 0x7c7b03c1affa2d6cl,0x5f189bb9aec6e624l,0xe77a1eedadeff5e7l, + 0xfc58b90f4280b467l }, + { 0x561e5d579b71cb4el,0x8ed767aa36d6a17el,0x38d8671e8aa9e188l, + 0x7bc68f07a95350c0l }, + 0 }, + /* 63 << 200 */ + { { 0xe0cd38cf98c01384l,0xc6741123a4226d9fl,0xdd1d42dbf877a0b8l, + 0xc5986ef0110b3cbal }, + { 0xeba949f809c8cebel,0x96b47bc4bd39f1dcl,0xbad140b6e07a2a3cl, + 0x2a8d80999ac5ca8al }, + 0 }, + /* 64 << 200 */ + { { 0x39d934abd3c095f1l,0x04b261bee4b76d71l,0x1d2e6970e73e6984l, + 0x879fb23b5e5fcb11l }, + { 0x11506c72dfd75490l,0x3a97d08561bcf1c1l,0x43201d82bf5e7007l, + 0x7f0ac52f798232a7l }, + 0 }, + /* 65 << 200 */ + { { 0x8cf27618590ca850l,0x58134f6f44bb94f2l,0x0a147562b78b4eecl, + 0x2e5986e39f1ed647l }, + { 0x9becf893348393b0l,0xaea21b92c31c2a86l,0x3d69859e5ff1b9a6l, + 0x6fcd19f4cd805691l }, + 0 }, + /* 71 << 200 */ + { { 0x81619bd4841f43c3l,0x3a3325538e5c61f0l,0x2b68921eda862151l, + 0x97f5c8a741a491f8l }, + { 0x8b452094d3b9afa0l,0x93b2b7b4f2124dbcl,0x53285e7d26e0e26dl, + 0x3f003fc5c8a24edel }, + 0 }, + /* 77 << 200 */ + { { 0x4cdabb586c025824l,0x5935ad1586bfcd7dl,0x8ce2c3101b7c5533l, + 0x761c9fe96cae8808l }, + { 0x8a0723f5d9e66d70l,0xb640b323dcced11dl,0x5768528051ae548cl, + 0x83576f75d53f3f2cl }, + 0 }, + /* 83 << 200 */ + { { 0xc715edc47b532ec3l,0x159765e6c4a6e14bl,0x4a74f15228cd2d45l, + 0xbfd309edae8c753bl }, + { 0xf56bb5315d6d5245l,0x2c89c21833b30a55l,0xe436141acd4ed5fal, + 0x7eb7a5c707868ee6l }, + 0 }, + /* 89 << 200 */ + { { 0x9a3ad3ffb0c7c48cl,0x25e8d977738e3638l,0xbb6c6c9d1c024074l, + 0xeda1ac0f8cfdf416l }, + { 0x93059ba538de49e2l,0xdb199cfc1b9ce741l,0x49b05e9446f3b494l, + 0x717cafc606480902l }, + 0 }, + /* 95 << 200 */ + { { 0x8d27421052885708l,0x9d2297fd74e5b9b5l,0xe7cb6a68dc4d7318l, + 0x0b60b0d276357b31l }, + { 0x57301994532c2095l,0xfbae2ba203373452l,0xe8020b20ba700583l, + 0x1ca7772c2988919cl }, + 0 }, + /* 101 << 200 */ + { { 0x723296eb918f3eecl,0x358c9ff0b79901c6l,0x64a1934c8d5e814cl, + 0x7e5a9afced165177l }, + { 0xd783840168733e7al,0xfcf3c0b6f61ede6dl,0x94ec0bf08434e804l, + 0xa5a70153c192c1cdl }, + 0 }, + /* 107 << 200 */ + { { 0x03cdf976c23e49d4l,0x51e5cfa5a2ae72d5l,0x7716faa3100f7a51l, + 0xc53153a2c14dc015l }, + { 0xe7c69b052b47ec18l,0xff4756907ea93b01l,0x55fde3c540a2f205l, + 0x0263d0b12f85aed6l }, + 0 }, + /* 113 << 200 */ + { { 0x668c56619686fe30l,0x382a8ccd8f73a476l,0xda012cbfb40a85e7l, + 0x55ea1e72e9e88b91l }, + { 0x8312556088cc5afcl,0x44ae54cbc45b19c7l,0xc91fffa8f86a02cdl, + 0xc79f573752d7e89bl }, + 0 }, + /* 116 << 200 */ + { { 0x652b50523e357579l,0x08ce7d3a2afe5746l,0x9dc1cca6f71a12efl, + 0x80a221c24f6c4196l }, + { 0xdde40eff0f49f508l,0x7995bb46913b0dc3l,0x4adbdeb385e44f6el, + 0x6816bb3ab222e4bbl }, + 0 }, + /* 119 << 200 */ + { { 0xce1ee518579a1a4dl,0x5d86e8912bc3870al,0x230878d18da907c4l, + 0xc648392777ae7ea8l }, + { 0x64319653016c0ad7l,0x7cbfa0b0b71f20dal,0xbf087dc3395ed4d8l, + 0x59512add307d218dl }, + 0 }, + /* 125 << 200 */ + { { 0x7378a969d8ae335el,0x11c69965506d3a42l,0x212539769949468al, + 0x570cf87e64995050l }, + { 0xf300ad2e30b94e22l,0xbc159cf8f36dad32l,0xdff3b3767ca8aa6al, + 0xa5de93b5627fb9e7l }, + 0 }, + }, + { + /* 0 << 208 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 208 */ + { { 0x75d9bc15adf7cccfl,0x81a3e5d6dfa1e1b0l,0x8c39e444249bc17el, + 0xf37dccb28ea7fd43l }, + { 0xda654873907fba12l,0x35daa6da4a372904l,0x0564cfc66283a6c5l, + 0xd09fa4f64a9395bfl }, + 0 }, + /* 3 << 208 */ + { { 0xc51aa29e5cfe5c48l,0x82c020ae815ee096l,0x7848ad827549a68al, + 0x7933d48960471355l }, + { 0x04998d2e67c51e57l,0x0f64020ad9944afcl,0x7a299fe1a7fadac6l, + 0x40c73ff45aefe92cl }, + 0 }, + /* 4 << 208 */ + { { 0xe5f649be9d8e68fdl,0xdb0f05331b044320l,0xf6fde9b3e0c33398l, + 0x92f4209b66c8cfael }, + { 0xe9d1afcc1a739d4bl,0x09aea75fa28ab8del,0x14375fb5eac6f1d0l, + 0x6420b560708f7aa5l }, + 0 }, + /* 5 << 208 */ + { { 0xbf44ffc75488771al,0xcb76e3f17f2f2191l,0x4197bde394f86a42l, + 0x45c25bb970641d9al }, + { 0xd8a29e31f88ce6dcl,0xbe2becfd4bb7ac7dl,0x13094214b5670cc7l, + 0xe90a8fd560af8433l }, + 0 }, + /* 7 << 208 */ + { { 0x0ecf9b8b4ebd3f02l,0xa47acd9d86b770eal,0x93b84a6a2da213cel, + 0xd760871b53e7c8cfl }, + { 0x7a5f58e536e530d7l,0x7abc52a51912ad51l,0x7ad43db02ea0252al, + 0x498b00ecc176b742l }, + 0 }, + /* 9 << 208 */ + { { 0x9ff713ef888ae17fl,0x6007f68fb34b7bebl,0x5d2b18983b653d64l, + 0xcbf73e91d3ca4b1bl }, + { 0x4b050ad56cdfb3a1l,0x41bd3ec3d1f833a4l,0x78d7e2ee719d7bf5l, + 0xea4604672a27412el }, + 0 }, + /* 10 << 208 */ + { { 0x7dad6d1b42cd7900l,0xb6e6b439e058f8a4l,0x8836f1e662aa3bbcl, + 0xd45bf2c811142b0al }, + { 0xae324bac3c045ed1l,0x372be24d270a8333l,0xeeda7a3a6b7c73b6l, + 0xf6675402db49562al }, + 0 }, + /* 11 << 208 */ + { { 0xc312ba68441e760dl,0x84d0d061a50e512el,0xfe764f4e4bbdd849l, + 0xa924adcf9dadd5c0l }, + { 0x08685961debfe976l,0xd3d846c529fba601l,0x43bf8227dc3f4040l, + 0x05e767b8a49e9ff5l }, + 0 }, + /* 13 << 208 */ + { { 0xc4689c309953e453l,0x5e355a2e1712dca5l,0x1ff83c81f1cd96f7l, + 0xb06b89fb44cf56dbl }, + { 0x1827705365f16e0dl,0x6403b91de5618672l,0xba3f9475be384bc6l, + 0x7f691cbe303ce5f3l }, + 0 }, + /* 15 << 208 */ + { { 0x4589ba03210f4045l,0xd5e7366301e8012al,0x1c26052d74462ffal, + 0xe78f600c4f989519l }, + { 0xc63ca0c97cee0b2fl,0xbe588573af760b5fl,0x05906fc4593773cdl, + 0xd5970fb0e322d5afl }, + 0 }, + /* 16 << 208 */ + { { 0x103c46e60ebcf726l,0x4482b8316231470el,0x6f6dfaca487c2109l, + 0x2e0ace9762e666efl }, + { 0x3246a9d31f8d1f42l,0x1b1e83f1574944d2l,0x13dfa63aa57f334bl, + 0x0cf8daed9f025d81l }, + 0 }, + /* 17 << 208 */ + { { 0xf67c098aae0690aal,0x1a4656422b7bc62bl,0xaffc6b917220dea2l, + 0xd97ac543d2552deel }, + { 0x1f84514a7e816b8el,0xe9887e81a8f38552l,0x2e6358e6847ad46bl, + 0x1f67871e6bc9895el }, + 0 }, + /* 19 << 208 */ + { { 0x2462b6e0d47f43fal,0x71db3610d8a245e5l,0x0c26b0e734208974l, + 0x0cd6d49d2029bd2el }, + { 0xf207c9f6091922b8l,0x0c476c5c7f0fbf66l,0x6de7efb2295d6da8l, + 0xea054ee10ced6cfel }, + 0 }, + /* 21 << 208 */ + { { 0xd21496e3e9bd795cl,0xf293f617c6a557del,0x9d041b7239a45642l, + 0xe8353dab4ac87f80l }, + { 0x21e9f35620d8d019l,0x1f4adca9d2fb2668l,0xe5f68227dfecd64al, + 0x10d71b79d7f09ec0l }, + 0 }, + /* 23 << 208 */ + { { 0xca3f068999f87118l,0x99a933911b2417f0l,0xa383481a3d1f70e5l, + 0x7a31a6c833b14414l }, + { 0x9d60f4368b2a9931l,0xd4c97ded80588534l,0x7cb29e82ab6a8bdal, + 0x3799bdad97b4c45al }, + 0 }, + /* 25 << 208 */ + { { 0x51da0ff629011af3l,0xcbb03c809a4f0855l,0xea3536725555b10bl, + 0x4bf94e025c7da97el }, + { 0x384352f5ff713300l,0xb2c2b675192d41e6l,0x4ff66861625ca046l, + 0xf0f5e472013dddc4l }, + 0 }, + /* 27 << 208 */ + { { 0x38c44cdc59987914l,0xad7f2829757fb853l,0x9aabf1c8688e3342l, + 0xbe0f1e4ef534c850l }, + { 0x732cac652ec24ecal,0x9328b657933bb5e4l,0xe2747ff60bb31033l, + 0xdbaab72cfcdc36acl }, + 0 }, + /* 28 << 208 */ + { { 0x0e5e3049a639fc6bl,0xe75c35d986003625l,0x0cf35bd85dcc1646l, + 0x8bcaced26c26273al }, + { 0xe22ecf1db5536742l,0x013dd8971a9e068bl,0x17f411cb8a7909c5l, + 0x5757ac98861dd506l }, + 0 }, + /* 29 << 208 */ + { { 0xaf410d5aac66a3e8l,0x39fcbffb2031f658l,0xd29e58c947ce11fbl, + 0x7f0b874965f73e49l }, + { 0xedc30f4b27fea6c6l,0xe03b9103d2baa340l,0xa7bb3f17ae680612l, + 0xe06656a8197af6f0l }, + 0 }, + /* 31 << 208 */ + { { 0x84562095bff86165l,0x994194e916bc7589l,0xb1320c7ec14c6710l, + 0x508a8d7f766e978fl }, + { 0xd04adc9ec7e1f6fel,0x7bafaff68398cecfl,0x906df2fccef3b934l, + 0xc65afe18f3008c38l }, + 0 }, + /* 33 << 208 */ + { { 0x477ffeeeab983130l,0x5426363a96e83d55l,0xcf0370a15204af42l, + 0x99834414b5a6ea8fl }, + { 0xf475ba711ab4ee8al,0x8486da5d0102d8f2l,0x55082e713839c821l, + 0xa57e58395b65defal }, + 0 }, + /* 34 << 208 */ + { { 0x34b2185bbbb33a76l,0x189038b7d48158c2l,0xfa32eb90e9e90217l, + 0x79271771730e74dfl }, + { 0x315ed8c2a5d01ffdl,0x9799dae723e6a95el,0x40070aa016f5715al, + 0x40e6c0ca5ea51f8cl }, + 0 }, + /* 35 << 208 */ + { { 0x099c0570d8132163l,0xcd5508a3023dbbf3l,0x18162ff526bfe6a6l, + 0xf39e071144bbb455l }, + { 0x49664996eaa3cf96l,0x1c6442d5e2649be9l,0x6199f740c01d269dl, + 0x4be605ee37542c11l }, + 0 }, + /* 36 << 208 */ + { { 0xc7313e9cf36658f0l,0xc433ef1c71f8057el,0x853262461b6a835al, + 0xc8f053987c86394cl }, + { 0xff398cdfe983c4a1l,0xbf5e816203b7b931l,0x93193c46b7b9045bl, + 0x1e4ebf5da4a6e46bl }, + 0 }, + /* 37 << 208 */ + { { 0xd032fbfd0dbf82b4l,0x707181f668e58969l,0xef434381e7be2d5el, + 0x290669176f2c64ddl }, + { 0xf66cffc3772769abl,0x68d8a76a17aad01cl,0xdd3991c590f6e078l, + 0xdb74db06ea4ac7dcl }, + 0 }, + /* 39 << 208 */ + { { 0x9f34a7c11c78be71l,0x7bf2f2d149ca6987l,0xb528a514dcd34afcl, + 0x4dddb3f1183a68b1l }, + { 0x54d2626660b83883l,0x9073e4e0e0cd8dadl,0xbd2b837d9eb818b2l, + 0x5fa5f9086ae2e32dl }, + 0 }, + /* 40 << 208 */ + { { 0xf9942a6043a24fe7l,0x29c1191effb3492bl,0x9f662449902fde05l, + 0xc792a7ac6713c32dl }, + { 0x2fd88ad8b737982cl,0x7e3a0319a21e60e3l,0x09b0de447383591al, + 0x6df141ee8310a456l }, + 0 }, + /* 41 << 208 */ + { { 0xcd02ba1e0df98a64l,0x301b6bfa03f5676el,0x41e1a8d4a2fe4090l, + 0x489c1cbf47f0e1dcl }, + { 0x4171a98c20760847l,0xdcb21cee77af4796l,0x5fb0f0c9d0b7e981l, + 0x4c2791dff33b9f8dl }, + 0 }, + /* 43 << 208 */ + { { 0x95d7ec0c50420a50l,0x5794665c2a6756d5l,0x73558c6e9101e7f5l, + 0xa3fa0f8c1642af0el }, + { 0xa11b309b4ee43551l,0x3939de30cb8fc712l,0x9710f2320fde8921l, + 0x2a4db2d5cae8b41cl }, + 0 }, + /* 44 << 208 */ + { { 0xaec1a039e6d6f471l,0x14b2ba0f1198d12el,0xebc1a1603aeee5acl, + 0x401f4836e0b964cel }, + { 0x2ee437964fd03f66l,0x3fdb4e49dd8f3f12l,0x6ef267f629380f18l, + 0x3e8e96708da64d16l }, + 0 }, + /* 45 << 208 */ + { { 0xdf6cdac0bc4c78adl,0xbe9e32182e97376el,0xa37f9d8b1a139274l, + 0x7640c3982807128el }, + { 0xe9735166c05b5f85l,0xbccd3675100e5716l,0x51376a293e5c9682l, + 0x95efe088848f6aeal }, + 0 }, + /* 46 << 208 */ + { { 0xfac2d7dd23d14105l,0xdda17149a9136f52l,0xb9f3a9c672d1a99bl, + 0x2fcf532a142c3b20l }, + { 0xc2731f1e61190c1bl,0x26dbe810a76509e4l,0xc96cc431908bb92fl, + 0x5661a84d80e3e694l }, + 0 }, + /* 47 << 208 */ + { { 0x5194d144150ba121l,0x8de57c48b6b11561l,0x803228da96c156d9l, + 0x2112e4250a8f6376l }, + { 0x15436294643449ffl,0xfc3880add4118cd0l,0x16ed90731e3f7413l, + 0xa400699901d38d6dl }, + 0 }, + /* 48 << 208 */ + { { 0xbc19180c207674f1l,0x112e09a733ae8fdbl,0x996675546aaeb71el, + 0x79432af1e101b1c7l }, + { 0xd5eb558fde2ddec6l,0x81392d1f5357753fl,0xa7a76b973ae1158al, + 0x416fbbff4a899991l }, + 0 }, + /* 49 << 208 */ + { { 0xf84c9147c52d7384l,0x86391accec01efa6l,0xffd68616f9c6f3f4l, + 0xc7536461b17c2de6l }, + { 0xa81f4ba10121abdfl,0xa068a2e26f6eae27l,0xe0ee90350eb159f0l, + 0x4c48f761fd8c4b9cl }, + 0 }, + /* 51 << 208 */ + { { 0x4b6d71e87790000cl,0xced195744ce9293el,0xc25626a3747585e8l, + 0xb8307d22d7044270l }, + { 0xf08e7ef6117c24cbl,0xae6403162f660d04l,0xbc3ffdcff224a2fdl, + 0x1ebc0328d0586c7el }, + 0 }, + /* 52 << 208 */ + { { 0x9e65fdfd0d4a9dcfl,0x7bc29e48944ddf12l,0xbc1a92d93c856866l, + 0x273c69056e98dfe2l }, + { 0x69fce418cdfaa6b8l,0x606bd8235061c69fl,0x42d495a06af75e27l, + 0x8ed3d5056d873a1fl }, + 0 }, + /* 53 << 208 */ + { { 0x46b160e5a6022278l,0x86b1d50cc30a51fcl,0xe898ac0e684b81b7l, + 0x04d591e277b93597l }, + { 0xd20cac347626e18al,0xb49c941f0a968733l,0x054e6e7e21631627l, + 0xd6d33db9d4c716b1l }, + 0 }, + /* 55 << 208 */ + { { 0xaa79ab4bf91e9b75l,0x7df3235bd34d961dl,0x9f3954e6534a40e1l, + 0x80f88d2c790b4456l }, + { 0x98f7711b21e9fb2al,0x0a04c318877d27e6l,0x499b7c2412338848l, + 0x0b1dbe9ccd5e7ec3l }, + 0 }, + /* 57 << 208 */ + { { 0xb430ff44e04715ffl,0x671358d565d076d0l,0x3946d38f22c3aa06l, + 0x80919ea363b2d627l }, + { 0x14ffa219e8790922l,0xfe1d895ae8d89c48l,0x717e9e51748e806el, + 0xb91e1ddf550d711dl }, + 0 }, + /* 59 << 208 */ + { { 0x8aac26225f540127l,0x57cd5d7cba25f742l,0x87006a6b1df7a0fcl, + 0x88e9ab863ecbf26cl }, + { 0xe1b8155f9143b314l,0xc00196130b679bddl,0x819e7b61a1871d07l, + 0xc36e7892cc2c9cc9l }, + 0 }, + /* 60 << 208 */ + { { 0x4b03c55b8e33787fl,0xef42f975a6384673l,0xff7304f75051b9f0l, + 0x18aca1dc741c87c2l }, + { 0x56f120a72d4bfe80l,0xfd823b3d053e732cl,0x11bccfe47537ca16l, + 0xdf6c9c741b5a996bl }, + 0 }, + /* 61 << 208 */ + { { 0x65729b05301ee370l,0x3ed09a2a24c2824cl,0x781ef66a33481977l, + 0xf2ccdeec193506d0l }, + { 0x92b4f70d703422d6l,0x7f004a43f80a1b99l,0x47db23607a856445l, + 0x783a8dd1ce5b0622l }, + 0 }, + /* 63 << 208 */ + { { 0x7febefd34e9aac5al,0x601c89e2bdd6173el,0x79b08930c257431el, + 0x915d601d399ee099l }, + { 0xfa48347eca02acd2l,0xc33249baeeb7ccedl,0xd76e408755704722l, + 0xd3709c600dcf4878l }, + 0 }, + /* 64 << 208 */ + { { 0xee7332c7904fc3fal,0x14a23f45c7e3636al,0xc38659c3f091d9aal, + 0x4a995e5db12d8540l }, + { 0x20a53becf3a5598al,0x56534b17b1eaa995l,0x9ed3dca4bf04e03cl, + 0x716c563ad8d56268l }, + 0 }, + /* 65 << 208 */ + { { 0x963353201580f3adl,0x6c495304b0cd50d4l,0xd035cdc7555ff981l, + 0xe65cd063c6b6bdfbl }, + { 0x7deb3cbb437e749cl,0xa9de9f3db5dc24a1l,0xe2e76a2b35c29ffal, + 0x4d35e261323ba650l }, + 0 }, + /* 71 << 208 */ + { { 0x52c46fc8c89e2766l,0x7330b02bb945e5f2l,0xc77ef75c2673ebbcl, + 0x1740e72657c33783l }, + { 0xf0312d29623565fbl,0xff9f707af0ca1ed9l,0xb98609ca5ea51a4al, + 0xde86b9a87b5cc91fl }, + 0 }, + /* 77 << 208 */ + { { 0x0dece4badca158b7l,0x5e39baf6a3e9f837l,0xcf14e6dc4d57b640l, + 0x0548aaa4b67bcbe7l }, + { 0xb6cf5b393c90e434l,0xf8b3c5645006f3abl,0xa74e92859bf04bd9l, + 0xf59a3a6bf99c8977l }, + 0 }, + /* 83 << 208 */ + { { 0x652ca66ac5b072d5l,0x2102b55993ad4928l,0x1b5f192d88210f9bl, + 0xb18710144c6ad7e5l }, + { 0x3979fde3bc0abf13l,0xb5cb4c7dac3fd631l,0x4aedffa6c200ec7bl, + 0x8aed81ceaddf3610l }, + 0 }, + /* 89 << 208 */ + { { 0x72b48105abeefbael,0x0e9e6e41827bb22bl,0xf45ada151e52a848l, + 0xb8e94579534867a2l }, + { 0x3a08773b7adb0fdcl,0xe7133a28b83316dfl,0xc8b7b08c5bb41470l, + 0x28719eb4aaf140c7l }, + 0 }, + /* 95 << 208 */ + { { 0x398996cd430007cel,0x20d8c0e07642d616l,0x81566639a7eb2397l, + 0x74aa0b692e133732l }, + { 0x326745907ba80aa7l,0x56a491c39bd69d64l,0xc8c8b040e54dcce0l, + 0x3f991872d571d037l }, + 0 }, + /* 101 << 208 */ + { { 0x70e681fa4fb595c9l,0xf0635d6386b4d97bl,0xfc029284c1347081l, + 0x5a4e9cbe4fee0303l }, + { 0xd43da8609c31094fl,0x0412cfed6515b4aal,0x10fc06da8d53be86l, + 0x4b7b380b4bccc94dl }, + 0 }, + /* 107 << 208 */ + { { 0x560d57408e7d6738l,0xa82268a8937f12a2l,0x87787b2d3d95b463l, + 0xb36539b2030e23bfl }, + { 0x60d16b8fd61e761dl,0x96ba2949fe8efccdl,0x8c170eda667fa7ebl, + 0xc880d74cf800d7c3l }, + 0 }, + /* 113 << 208 */ + { { 0x7c05d6c1efcbfea0l,0xae7ba3291a2f6dd8l,0x521598ed5bd42ecfl, + 0x58e07842ef0ab40cl }, + { 0xae65105f66c752a5l,0x4910fba45f99d499l,0xbfdaf5fce9e44357l, + 0x6aaf4053796ee5b6l }, + 0 }, + /* 116 << 208 */ + { { 0xf58fecb16f640f62l,0xe274b92b39f51946l,0x7f4dfc046288af44l, + 0x0a91f32aeac329e5l }, + { 0x43ad274bd6aaba31l,0x719a16400f6884f9l,0x685d29f6daf91e20l, + 0x5ec1cc3327e49d52l }, + 0 }, + /* 119 << 208 */ + { { 0x615ac02527ba93edl,0x0d43915d3556ef47l,0x8c739fd1cb0cda89l, + 0xa2318169625f7a16l }, + { 0x17d486113e0479cel,0x814beb6038ee541el,0x09c9807fb98ef355l, + 0x4ad3668752d07af6l }, + 0 }, + /* 125 << 208 */ + { { 0x5c1f42e444f3f568l,0xd743b7c078fb409bl,0xe09edccb6224362cl, + 0x7f13d140c5fe872cl }, + { 0x85e8cb88f403c0ebl,0x918a231b688d20a0l,0xc65b7ab9f246c73fl, + 0xda743fbf76dbd6adl }, + 0 }, + }, + { + /* 0 << 216 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 216 */ + { { 0xa0158eeae457a477l,0xd19857dbee6ddc05l,0xb326522418c41671l, + 0x3ffdfc7e3c2c0d58l }, + { 0x3a3a525426ee7cdal,0x341b0869df02c3a8l,0xa023bf42723bbfc8l, + 0x3d15002a14452691l }, + 0 }, + /* 3 << 216 */ + { { 0xf3cae7e9262a3539l,0x78a49d1d6670d59el,0x37de0f63c1c5e1b9l, + 0x3072c30c69cb7c1cl }, + { 0x1d278a5277c850e6l,0x84f15f8f1f6a3de6l,0x46a8bb45592ca7adl, + 0x1912e3eee4d424b8l }, + 0 }, + /* 4 << 216 */ + { { 0x6ba7a92079e5fb67l,0xe1331feb70aa725el,0x5080ccf57df5d837l, + 0xe4cae01d7ff72e21l }, + { 0xd9243ee60412a77dl,0x06ff7cacdf449025l,0xbe75f7cd23ef5a31l, + 0xbc9578220ddef7a8l }, + 0 }, + /* 5 << 216 */ + { { 0xdc988086365e668bl,0xada8dcdaaabda5fbl,0xbc146b4c255f1fbel, + 0x9cfcde29cf34cfc3l }, + { 0xacbb453e7e85d1e4l,0x9ca09679f92358b5l,0x15fc2d96240823ffl, + 0x8d65adf70c11d11el }, + 0 }, + /* 7 << 216 */ + { { 0x775557f10296f4fdl,0x1dca76a3ea51b436l,0xf3e98f60fb950805l, + 0x31ff32ea831cf7f1l }, + { 0x643e7bf18d2c714bl,0x64b5c3392e9d2acal,0xa9fd9ccc6adc2d23l, + 0xfc2397eccc721b9bl }, + 0 }, + /* 9 << 216 */ + { { 0xf031182db48ec57dl,0x515d32f804b233b9l,0x06bbb1d4093aad26l, + 0x88a142fe0d83d1ecl }, + { 0x3b95c099245c73f8l,0xb126d4af52edcd32l,0xf8022c1e8fcb52e6l, + 0x5a51ac4c0106d339l }, + 0 }, + /* 10 << 216 */ + { { 0xc589e1ce44ace150l,0xe0f8d3d94381e97cl,0x59e99b1162c5a4b8l, + 0x90d262f7fd0ec9f9l }, + { 0xfbc854c9283e13c9l,0x2d04fde7aedc7085l,0x057d776547dcbecbl, + 0x8dbdf5919a76fa5fl }, + 0 }, + /* 11 << 216 */ + { { 0xb7f70a1a7c64a054l,0x0dc1c0df9db43e79l,0x6d0a4ae251fe63d6l, + 0xe0d5e3327f0c8abfl }, + { 0xff5500362b7ecee8l,0x3ea0e6f75d055008l,0x30deb62ff24ac84fl, + 0x936969fd5d7116b7l }, + 0 }, + /* 13 << 216 */ + { { 0x02da76122617cf7fl,0xd6e25d4eeee35260l,0xb2fa5b0afd3533e9l, + 0xe76bb7b0b9126f88l }, + { 0x692e6a9988856866l,0x3fdf394f49db65cal,0x2529699122d8d606l, + 0xe815bfbf3dd7c4cfl }, + 0 }, + /* 15 << 216 */ + { { 0x69c984ed4d844e7fl,0xd354b2174a2e8a82l,0x25bd4addfb2c4136l, + 0xf72df4de144b26e1l }, + { 0xd0aa9db0e6101afdl,0x4445efaae49bd1b8l,0x5dc54eee331593b2l, + 0xfa35e3b9094bf10bl }, + 0 }, + /* 16 << 216 */ + { { 0xdb567d6ac42bd6d2l,0x6df86468bb1f96ael,0x0efe5b1a4843b28el, + 0x961bbb056379b240l }, + { 0xb6caf5f070a6a26bl,0x70686c0d328e6e39l,0x80da06cf895fc8d3l, + 0x804d8810b363fdc9l }, + 0 }, + /* 17 << 216 */ + { { 0x660a0f893ea089c3l,0xa25823aac9009b09l,0xb2262d7ba681f5e5l, + 0x4fc30c8c3413863al }, + { 0x691544b7c32059f7l,0xf65cf276b21c6134l,0xe3a96b2a5104dabal, + 0xbb08d109a43ee42fl }, + 0 }, + /* 19 << 216 */ + { { 0x85a52d69f9916861l,0x595469a4da4fa813l,0x1dd7786e3338502fl, + 0x34b8ef2853963ac5l }, + { 0xc0f019f81a891b25l,0xb619970c4f4bd775l,0x8c2a5af3be19f681l, + 0x9463db0498ec1728l }, + 0 }, + /* 21 << 216 */ + { { 0xeb62c27801f39eabl,0x27de39340ab3a4aal,0xfbd17520a982ca8dl, + 0x58817ec2e4bdc6edl }, + { 0x312d78de31c6ac13l,0x9483bf7609202ea6l,0xf64ab8b622c6d8e1l, + 0xdddf589ce580de74l }, + 0 }, + /* 23 << 216 */ + { { 0xe0fa3336ee98a92al,0x7d80eeef66a4d745l,0xb612531bba0119d3l, + 0x86e770c1b351fe15l }, + { 0xafbad6f882d5a397l,0x1e5f1cb80dbf0110l,0x25138ac09f79063dl, + 0x089ed22f2746a156l }, + 0 }, + /* 25 << 216 */ + { { 0x198d1b5d7d8b8ddel,0xf32c11078dab37fbl,0xf15fcb6d42b93874l, + 0x91ddb74f41f94f84l }, + { 0x6a64540a271524b2l,0x950a0c12758b5a64l,0xf9f237933dce9580l, + 0xc8edd0ab2cf8ce32l }, + 0 }, + /* 27 << 216 */ + { { 0xefc6357eae1046b7l,0xe6704929612932e4l,0xa20305d4b1355b17l, + 0x88a9136a58b4a156l }, + { 0xbc379985b4d275ecl,0x718b91316eaf338bl,0x61229a7ad152a509l, + 0x1109f7c445157ae9l }, + 0 }, + /* 28 << 216 */ + { { 0xcf197ca7fb8088fal,0x014272474ddc96c5l,0xa2d2550a30777176l, + 0x534698984d0cf71dl }, + { 0x6ce937b83a2aaac6l,0xe9f91dc35af38d9bl,0x2598ad83c8bf2899l, + 0x8e706ac9b5536c16l }, + 0 }, + /* 29 << 216 */ + { { 0x2bde42140df85c2cl,0x4fb839f4058a7a63l,0x7c10572a47f51231l, + 0x878826231989824el }, + { 0xa8293d2016e1564al,0xcb11c0f818c04576l,0x83b91e7d9740c631l, + 0xbdcb23d0cbffcea0l }, + 0 }, + /* 31 << 216 */ + { { 0x64bdfd2a9094bfc8l,0x8558acc60fc54d1el,0x3992848faf27721el, + 0x7a8fcbdaa14cd009l }, + { 0x6de6120900a4b9c2l,0xbd192b1b20cf8f28l,0x2356b90168d9be83l, + 0xce1e7a944a49a48al }, + 0 }, + /* 33 << 216 */ + { { 0x7630103b6ac189b9l,0x15d35edc6f1f5549l,0x9051799d31cb58edl, + 0xb4f32694a7a8579el }, + { 0x6f037435f2abe306l,0xf0595696410fb2f7l,0x2a0d347a5cc98f59l, + 0x9c19a9a87e3bbd69l }, + 0 }, + /* 34 << 216 */ + { { 0x87f8df7c0e58d493l,0xb1ae5ed058b73f12l,0xc368f784dea0c34dl, + 0x9bd0a120859a91a0l }, + { 0xb00d88b7cc863c68l,0x3a1cc11e3d1f4d65l,0xea38e0e70aa85593l, + 0x37f13e987dc4aee8l }, + 0 }, + /* 35 << 216 */ + { { 0x91dbe00e49430cd2l,0xcc67c0b17aa8ef6bl,0x769985b8a273f1a5l, + 0x358371dc360e5dafl }, + { 0xbf9b9127d6d8b5e8l,0x748ae12cb45588c1l,0x9c609eb556076c58l, + 0xf287489109733e89l }, + 0 }, + /* 36 << 216 */ + { { 0x10d38667bc947badl,0x738e07ce2a36ee2el,0xc93470cdc577fcacl, + 0xdee1b6162782470dl }, + { 0x36a25e672e793d12l,0xd6aa6caee0f186dal,0x474d0fd980e07af7l, + 0xf7cdc47dba8a5cd4l }, + 0 }, + /* 37 << 216 */ + { { 0xceb6aa80f8a08fddl,0xd98fc56f46fead7bl,0xe26bd3f8b07b3f1fl, + 0x3547e9b99d361c3el }, + { 0x1a89f802e94b8eccl,0x2210a590c0a40ef2l,0xe7e5b965afc01bf2l, + 0xca3d57fe234b936bl }, + 0 }, + /* 39 << 216 */ + { { 0x9230a70db9f9e8cdl,0xa63cebfcb81ba2ecl,0x8482ca87a8f664d6l, + 0xa8ae78e00b137064l }, + { 0xb787bd558384c687l,0xfde1d1bdb29ae830l,0xc4a9b2e39f0b7535l, + 0x7e6c9a15efde2d01l }, + 0 }, + /* 40 << 216 */ + { { 0x7d2e5c054f7269b1l,0xfcf30777e287c385l,0x10edc84ff2a46f21l, + 0x354417574f43fa36l }, + { 0xf1327899fd703431l,0xa438d7a616dd587al,0x65c34c57e9c8352dl, + 0xa728edab5cc5a24el }, + 0 }, + /* 41 << 216 */ + { { 0xcd6e6db872896d4fl,0x324afa99896c4640l,0x37d18c3d33a292bdl, + 0x98dba3b44143421fl }, + { 0x2406f3c949c61b84l,0x402d974754899588l,0xc73b7fd634a485e5l, + 0x75c9bae08587f0c3l }, + 0 }, + /* 43 << 216 */ + { { 0x6c32fa8cb0b4a04dl,0xeb58d0d875fda587l,0x61d8a157c4b86563l, + 0x92191bf01006b8afl }, + { 0xd04d3eff32d3478bl,0x3cc52eab2a684fc8l,0xb19a0f1625de54ccl, + 0x5c5295973620db2dl }, + 0 }, + /* 44 << 216 */ + { { 0xa97b51265c3427b0l,0x6401405cd282c9bdl,0x3629f8d7222c5c45l, + 0xb1c02c16e8d50aedl }, + { 0xbea2ed75d9635bc9l,0x226790c76e24552fl,0x3c33f2a365f1d066l, + 0x2a43463e6dfccc2el }, + 0 }, + /* 45 << 216 */ + { { 0x09b2e0d3b8da1e01l,0xa3a1a8fee9c0eb04l,0x59af5afe8bf653bal, + 0xba979f8bd0a54836l }, + { 0xa0d8194b51ee6ffbl,0x451c29e2f4b0586cl,0x7eb5fddb7471ee3dl, + 0x84b627d4bcb3afd8l }, + 0 }, + /* 46 << 216 */ + { { 0x8cc3453adb483761l,0xe7cc608565d5672bl,0x277ed6cbde3efc87l, + 0x19f2f36869234eafl }, + { 0x9aaf43175c0b800bl,0x1f1e7c898b6da6e2l,0x6cfb4715b94ec75el, + 0xd590dd5f453118c2l }, + 0 }, + /* 47 << 216 */ + { { 0xa70e9b0afb54e812l,0x092a0d7d8d86819bl,0x5421ff042e669090l, + 0x8af770c6b133c952l }, + { 0xc8e8dd596c8b1426l,0x1c92eb0e9523b483l,0x5a7c88f2cf3d40edl, + 0x4cc0c04bf5dd98f8l }, + 0 }, + /* 48 << 216 */ + { { 0x14e49da11f17a34cl,0x5420ab39235a1456l,0xb76372412f50363bl, + 0x7b15d623c3fabb6el }, + { 0xa0ef40b1e274e49cl,0x5cf5074496b1860al,0xd6583fbf66afe5a4l, + 0x44240510f47e3e9al }, + 0 }, + /* 49 << 216 */ + { { 0xb3939a8ffd617288l,0x3d37e5c2d68c2636l,0x4a595fac9d666c0el, + 0xfebcad9edb3a4978l }, + { 0x6d284a49c125016fl,0x05a7b9c80ee246a2l,0xe8b351739436c6e9l, + 0xffb89032d4be40b7l }, + 0 }, + /* 51 << 216 */ + { { 0xba1387a5436ebf33l,0xc351a400e8d05267l,0x18645dde4259dbe8l, + 0x5fc32895c10fd676l }, + { 0x1ef7a944807f040el,0x9486b5c625738e5fl,0xc9e56cf4a7e3e96cl, + 0x34c7dc87a20be832l }, + 0 }, + /* 52 << 216 */ + { { 0xe10d49996fe8393fl,0x0f809a3fe91f3a32l,0x61096d1c802f63c8l, + 0x289e146257750d3dl }, + { 0xed06167e9889feeal,0xd5c9c0e2e0993909l,0x46fca0d856508ac6l, + 0x918260474f1b8e83l }, + 0 }, + /* 53 << 216 */ + { { 0x1d5f2ad7a9bf79cbl,0x228fb24fca9c2f98l,0x5f7c3883701c4b71l, + 0x18cf76c4ec42d686l }, + { 0x3680d2e94dcdec8dl,0x6d58e87ba0d60cb6l,0x72fbf086a0e513cfl, + 0xb922d3c5346ed99al }, + 0 }, + /* 55 << 216 */ + { { 0x1678d658c2b9b874l,0x0e0b2c47f6360d4dl,0x01a45c02a0c9b9acl, + 0x05e82e9d0da69afbl }, + { 0x50be4001f28b8018l,0x503d967b667d8241l,0x6cd816534981da04l, + 0x9b18c3117f09c35fl }, + 0 }, + /* 57 << 216 */ + { { 0xdfdfd5b409d22331l,0xf445126817f0c6a2l,0xe51d1aa8a5cde27bl, + 0xb61a12a37aaf9513l }, + { 0xe43a241d3b3ea114l,0x5c62b624366ae28dl,0x085a530db5f237eal, + 0x7c4ed375651205afl }, + 0 }, + /* 59 << 216 */ + { { 0xf9de879dce842decl,0xe505320a94cedb89l,0xee55dae7f05ad888l, + 0x44ffbfa7f028b4efl }, + { 0xa3c1b32e63b2cd31l,0x201a058910c5ab29l,0x20f930afcd4085d6l, + 0xda79ed169f6ff24bl }, + 0 }, + /* 60 << 216 */ + { { 0x7e8cfbcf704e23c6l,0xc71b7d2228aaa65bl,0xa041b2bd245e3c83l, + 0x69b98834d21854ffl }, + { 0x89d227a3963bfeecl,0x99947aaade7da7cbl,0x1d9ee9dbee68a9b1l, + 0x0a08f003698ec368l }, + 0 }, + /* 61 << 216 */ + { { 0x04c64f33b0959be5l,0x182332ba396a7fe2l,0x4c5401e302e15b97l, + 0x92880f9877db104bl }, + { 0x0bf0b9cc21726a33l,0x780264741acc7b6dl,0x9721f621a26f08e3l, + 0xe3935b434197fed1l }, + 0 }, + /* 63 << 216 */ + { { 0x0bffae503652be69l,0x395a9c6afb3fd5d8l,0x17f66adaa4fadfbfl, + 0x1ee92a35f9268f8cl }, + { 0x40ded34d6827781al,0xcd36224e34e63dccl,0xec90cf571cd1ef7al, + 0xf6067d578f72a3bfl }, + 0 }, + /* 64 << 216 */ + { { 0x142b55021a93507al,0xb4cd11878d3c06cfl,0xdf70e76a91ec3f40l, + 0x484e81ad4e7553c2l }, + { 0x830f87b5272e9d6el,0xea1c93e5c6ff514al,0x67cc2adcc4192a8el, + 0xc77e27e242f4535al }, + 0 }, + /* 65 << 216 */ + { { 0x537388d299e2f9d2l,0x15ead88612cd6d08l,0x33dfe3a769082d86l, + 0x0ef25f4266d79d40l }, + { 0x8035b4e546ba5cf1l,0x4e48f53711eec591l,0x40b56cda122a7aael, + 0x78e270211dbb79a7l }, + 0 }, + /* 71 << 216 */ + { { 0x520b655355b4a5b1l,0xeee835cafb4f5fdel,0xb2ae86e59a823d7fl, + 0x24325f4fc084497fl }, + { 0x542bed4e6f0eefa4l,0x2909233b141792fdl,0x74bfc3bfc847a946l, + 0x8ec1d009e212cb44l }, + 0 }, + /* 77 << 216 */ + { { 0xc2082b6d5cedd516l,0xaf148eadeafa3a10l,0x104cd5855ad63aa6l, + 0xe3fdbf8c78c11e1el }, + { 0x78651c493c25c24el,0x8064c4f37b7cce0el,0xa55441d4a6d8a928l, + 0x4525c40eb0db3adcl }, + 0 }, + /* 83 << 216 */ + { { 0x5f69e49cfde6001el,0xc61e753aee59b47el,0xd0d4559971b0db5bl, + 0x7f76f7b45ad4acc3l }, + { 0xb0318a9c39830897l,0x2b15da22feef3822l,0x34049400acfb0753l, + 0x16f4fb51a5114ed4l }, + 0 }, + /* 89 << 216 */ + { { 0x0b5c76928defbf10l,0xb9f1795cb79cdb6el,0xba17e7759a90317cl, + 0x3cb69cf950cf514bl }, + { 0x076cc4c1e5b892ffl,0x75724e8fb548b73cl,0x2ebcdb33248ff2e6l, + 0x1f12967be109b08fl }, + 0 }, + /* 95 << 216 */ + { { 0x3f514c63461b7bb3l,0x3bdca5aa70afbad7l,0x368ce251eab3e38bl, + 0xdc0fb3300d101049l }, + { 0x7ce09abdff5013eel,0x926dd7dd7d10729dl,0xe6fe47ab6f486197l, + 0xd23964eaa6eb6903l }, + 0 }, + /* 101 << 216 */ + { { 0x537ceb74eca30797l,0xf171bba557b0f338l,0x220a31fee831f1f8l, + 0xabbc2c7c5ae6bbbcl }, + { 0xaf7609f27eadfb60l,0x22cff1d58f28b51bl,0x63c3d76d6d1863bdl, + 0x3a6a2fb489e8a4c8l }, + 0 }, + /* 107 << 216 */ + { { 0x9e74f8beb26e38f0l,0xc4c73fc4ea8bd55bl,0x086f688e1429e1fcl, + 0x91438ff40f78159fl }, + { 0x3571ae5f20810acbl,0x305edafe7451eb00l,0x8443c96d5704385cl, + 0xc03b234e542605b5l }, + 0 }, + /* 113 << 216 */ + { { 0x2e5ff4fed85567c2l,0x136f49c7e4abd0c6l,0x5a68730cfb8a62d1l, + 0x101ebfd030bcb848l }, + { 0x634b0618fee950bbl,0xfa748d21c8aa65bal,0xc1d67c3e699f5560l, + 0x6fb0546cb22889d2l }, + 0 }, + /* 116 << 216 */ + { { 0xa9784ebd9c95f0f9l,0x5ed9deb224640771l,0x31244af7035561c4l, + 0x87332f3a7ee857del }, + { 0x09e16e9e2b9e0d88l,0x52d910f456a06049l,0x507ed477a9592f48l, + 0x85cb917b2365d678l }, + 0 }, + /* 119 << 216 */ + { { 0x6108f2b458a9d40dl,0xb036034838e15a52l,0xcc5610a3fd5625d6l, + 0x79825dd083b0418el }, + { 0xf83a95fc6324b6e5l,0x2463114deedfc4ebl,0x58b177e32250707fl, + 0x778dcd454af8d942l }, + 0 }, + /* 125 << 216 */ + { { 0x1ecf2670eb816bf8l,0xa2d6e73aaa6d59c6l,0xf9a11434156852ebl, + 0x9bc9bb70f6f82c83l }, + { 0xd23a018d9c874836l,0xd26bf8bc6db5a8b5l,0x1d648846bec0c624l, + 0x39f15d97ef90302fl }, + 0 }, + }, + { + /* 0 << 224 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 224 */ + { { 0xe3417bc035d0b34al,0x440b386b8327c0a7l,0x8fb7262dac0362d1l, + 0x2c41114ce0cdf943l }, + { 0x2ba5cef1ad95a0b1l,0xc09b37a867d54362l,0x26d6cdd201e486c9l, + 0x20477abf42ff9297l }, + 0 }, + /* 3 << 224 */ + { { 0x126f35b51e706ad9l,0xb99cebb4c3a9ebdfl,0xa75389afbf608d90l, + 0x76113c4fc6c89858l }, + { 0x80de8eb097e2b5aal,0x7e1022cc63b91304l,0x3bdab6056ccc066cl, + 0x33cbb144b2edf900l }, + 0 }, + /* 4 << 224 */ + { { 0xc41764717af715d2l,0xe2f7f594d0134a96l,0x2c1873efa41ec956l, + 0xe4e7b4f677821304l }, + { 0xe5c8ff9788d5374al,0x2b915e6380823d5bl,0xea6bc755b2ee8fe2l, + 0x6657624ce7112651l }, + 0 }, + /* 5 << 224 */ + { { 0x157af101dace5acal,0xc4fdbcf211a6a267l,0xdaddf340c49c8609l, + 0x97e49f52e9604a65l }, + { 0x9be8e790937e2ad5l,0x846e2508326e17f1l,0x3f38007a0bbbc0dcl, + 0xcf03603fb11e16d6l }, + 0 }, + /* 7 << 224 */ + { { 0x5ed0c007f8ae7c38l,0x6db07a5c3d740192l,0xbe5e9c2a5fe36db3l, + 0xd5b9d57a76e95046l }, + { 0x54ac32e78eba20f2l,0xef11ca8f71b9a352l,0x305e373eff98a658l, + 0xffe5a100823eb667l }, + 0 }, + /* 9 << 224 */ + { { 0x5c8ed8d5da64309dl,0x61a6de5691b30704l,0xd6b52f6a2f9b5808l, + 0x0eee419498c958a7l }, + { 0xcddd9aab771e4caal,0x83965dfd78bc21bel,0x02affce3b3b504f5l, + 0x30847a21561c8291l }, + 0 }, + /* 10 << 224 */ + { { 0xd2eb2cf152bfda05l,0xe0e4c4e96197b98cl,0x1d35076cf8a1726fl, + 0x6c06085b2db11e3dl }, + { 0x15c0c4d74463ba14l,0x9d292f830030238cl,0x1311ee8b3727536dl, + 0xfeea86efbeaedc1el }, + 0 }, + /* 11 << 224 */ + { { 0xb9d18cd366131e2el,0xf31d974f80fe2682l,0xb6e49e0fe4160289l, + 0x7c48ec0b08e92799l }, + { 0x818111d8d1989aa7l,0xb34fa0aaebf926f9l,0xdb5fe2f5a245474al, + 0xf80a6ebb3c7ca756l }, + 0 }, + /* 13 << 224 */ + { { 0x8ea610593de9abe3l,0x404348819cdc03bel,0x9b261245cfedce8cl, + 0x78c318b4cf5234a1l }, + { 0x510bcf16fde24c99l,0x2a77cb75a2c2ff5dl,0x9c895c2b27960fb4l, + 0xd30ce975b0eda42bl }, + 0 }, + /* 15 << 224 */ + { { 0x09521177ff57d051l,0x2ff38037fb6a1961l,0xfc0aba74a3d76ad4l, + 0x7c76480325a7ec17l }, + { 0x7532d75f48879bc8l,0xea7eacc058ce6bc1l,0xc82176b48e896c16l, + 0x9a30e0b22c750fedl }, + 0 }, + /* 16 << 224 */ + { { 0xc37e2c2e421d3aa4l,0xf926407ce84fa840l,0x18abc03d1454e41cl, + 0x26605ecd3f7af644l }, + { 0x242341a6d6a5eabfl,0x1edb84f4216b668el,0xd836edb804010102l, + 0x5b337ce7945e1d8cl }, + 0 }, + /* 17 << 224 */ + { { 0xd2075c77c055dc14l,0x2a0ffa2581d89cdfl,0x8ce815ea6ffdcbafl, + 0xa3428878fb648867l }, + { 0x277699cf884655fbl,0xfa5b5bd6364d3e41l,0x01f680c6441e1cb7l, + 0x3fd61e66b70a7d67l }, + 0 }, + /* 19 << 224 */ + { { 0xfd5bb657b1fa70fbl,0xfa07f50fd8073a00l,0xf72e3aa7bca02500l, + 0xf68f895d9975740dl }, + { 0x301120605cae2a6al,0x01bd721802874842l,0x3d4238917ce47bd3l, + 0xa66663c1789544f6l }, + 0 }, + /* 21 << 224 */ + { { 0xb4b9a39b36194d40l,0xe857a7c577612601l,0xf4209dd24ecf2f58l, + 0x82b9e66d5a033487l }, + { 0xc1e36934e4e8b9ddl,0xd2372c9da42377d7l,0x51dc94c70e3ae43bl, + 0x4c57761e04474f6fl }, + 0 }, + /* 23 << 224 */ + { { 0xa39114e24415503bl,0xc08ff7c64cbb17e9l,0x1eff674dd7dec966l, + 0x6d4690af53376f63l }, + { 0xff6fe32eea74237bl,0xc436d17ecd57508el,0x15aa28e1edcc40fel, + 0x0d769c04581bbb44l }, + 0 }, + /* 25 << 224 */ + { { 0xfe51d0296ae55043l,0x8931e98f44a87de1l,0xe57f1cc609e4fee2l, + 0x0d063b674e072d92l }, + { 0x70a998b9ed0e4316l,0xe74a736b306aca46l,0xecf0fbf24fda97c7l, + 0xa40f65cb3e178d93l }, + 0 }, + /* 27 << 224 */ + { { 0x8667e981c27253c9l,0x05a6aefb92b36a45l,0xa62c4b369cb7bb46l, + 0x8394f37511f7027bl }, + { 0x747bc79c5f109d0fl,0xcad88a765b8cc60al,0x80c5a66b58f09e68l, + 0xe753d451f6127eacl }, + 0 }, + /* 28 << 224 */ + { { 0xc44b74a15b0ec6f5l,0x47989fe45289b2b8l,0x745f848458d6fc73l, + 0xec362a6ff61c70abl }, + { 0x070c98a7b3a8ad41l,0x73a20fc07b63db51l,0xed2c2173f44c35f4l, + 0x8a56149d9acc9dcal }, + 0 }, + /* 29 << 224 */ + { { 0x98f178819ac6e0f4l,0x360fdeafa413b5edl,0x0625b8f4a300b0fdl, + 0xf1f4d76a5b3222d3l }, + { 0x9d6f5109587f76b8l,0x8b4ee08d2317fdb5l,0x88089bb78c68b095l, + 0x95570e9a5808d9b9l }, + 0 }, + /* 31 << 224 */ + { { 0x2e1284943fb42622l,0x3b2700ac500907d5l,0xf370fb091a95ec63l, + 0xf8f30be231b6dfbdl }, + { 0xf2b2f8d269e55f15l,0x1fead851cc1323e9l,0xfa366010d9e5eef6l, + 0x64d487b0e316107el }, + 0 }, + /* 33 << 224 */ + { { 0xc9a9513929607745l,0x0ca07420a26f2b28l,0xcb2790e74bc6f9ddl, + 0x345bbb58adcaffc0l }, + { 0xc65ea38cbe0f27a2l,0x67c24d7c641fcb56l,0x2c25f0a7a9e2c757l, + 0x93f5cdb016f16c49l }, + 0 }, + /* 34 << 224 */ + { { 0x2ca5a9d7c5ee30a1l,0xd1593635b909b729l,0x804ce9f3dadeff48l, + 0xec464751b07c30c3l }, + { 0x89d65ff39e49af6al,0xf2d6238a6f3d01bcl,0x1095561e0bced843l, + 0x51789e12c8a13fd8l }, + 0 }, + /* 35 << 224 */ + { { 0xd633f929763231dfl,0x46df9f7de7cbddefl,0x01c889c0cb265da8l, + 0xfce1ad10af4336d2l }, + { 0x8d110df6fc6a0a7el,0xdd431b986da425dcl,0xcdc4aeab1834aabel, + 0x84deb1248439b7fcl }, + 0 }, + /* 36 << 224 */ + { { 0x8796f1693c2a5998l,0x9b9247b47947190dl,0x55b9d9a511597014l, + 0x7e9dd70d7b1566eel }, + { 0x94ad78f7cbcd5e64l,0x0359ac179bd4c032l,0x3b11baaf7cc222ael, + 0xa6a6e284ba78e812l }, + 0 }, + /* 37 << 224 */ + { { 0x8392053f24cea1a0l,0xc97bce4a33621491l,0x7eb1db3435399ee9l, + 0x473f78efece81ad1l }, + { 0x41d72fe0f63d3d0dl,0xe620b880afab62fcl,0x92096bc993158383l, + 0x41a213578f896f6cl }, + 0 }, + /* 39 << 224 */ + { { 0x6fb4d4e42bad4d5fl,0xfa4c3590fef0059bl,0x6a10218af5122294l, + 0x9a78a81aa85751d1l }, + { 0x04f20579a98e84e7l,0xfe1242c04997e5b5l,0xe77a273bca21e1e4l, + 0xfcc8b1ef9411939dl }, + 0 }, + /* 40 << 224 */ + { { 0xe20ea30292d0487al,0x1442dbec294b91fel,0x1f7a4afebb6b0e8fl, + 0x1700ef746889c318l }, + { 0xf5bbffc370f1fc62l,0x3b31d4b669c79ccal,0xe8bc2aaba7f6340dl, + 0xb0b08ab4a725e10al }, + 0 }, + /* 41 << 224 */ + { { 0x44f05701ae340050l,0xba4b30161cf0c569l,0x5aa29f83fbe19a51l, + 0x1b9ed428b71d752el }, + { 0x1666e54eeb4819f5l,0x616cdfed9e18b75bl,0x112ed5be3ee27b0bl, + 0xfbf2831944c7de4dl }, + 0 }, + /* 43 << 224 */ + { { 0x722eb104e2b4e075l,0x49987295437c4926l,0xb1e4c0e446a9b82dl, + 0xd0cb319757a006f5l }, + { 0xf3de0f7dd7808c56l,0xb5c54d8f51f89772l,0x500a114aadbd31aal, + 0x9afaaaa6295f6cabl }, + 0 }, + /* 44 << 224 */ + { { 0x94705e2104cf667al,0xfc2a811b9d3935d7l,0x560b02806d09267cl, + 0xf19ed119f780e53bl }, + { 0xf0227c09067b6269l,0x967b85335caef599l,0x155b924368efeebcl, + 0xcd6d34f5c497bae6l }, + 0 }, + /* 45 << 224 */ + { { 0x1dd8d5d36cceb370l,0x2aeac579a78d7bf9l,0x5d65017d70b67a62l, + 0x70c8e44f17c53f67l }, + { 0xd1fc095086a34d09l,0xe0fca256e7134907l,0xe24fa29c80fdd315l, + 0x2c4acd03d87499adl }, + 0 }, + /* 46 << 224 */ + { { 0xbaaf75173b5a9ba6l,0xb9cbe1f612e51a51l,0xd88edae35e154897l, + 0xe4309c3c77b66ca0l }, + { 0xf5555805f67f3746l,0x85fc37baa36401ffl,0xdf86e2cad9499a53l, + 0x6270b2a3ecbc955bl }, + 0 }, + /* 47 << 224 */ + { { 0xafae64f5974ad33bl,0x04d85977fe7b2df1l,0x2a3db3ff4ab03f73l, + 0x0b87878a8702740al }, + { 0x6d263f015a061732l,0xc25430cea32a1901l,0xf7ebab3ddb155018l, + 0x3a86f69363a9b78el }, + 0 }, + /* 48 << 224 */ + { { 0x349ae368da9f3804l,0x470f07fea164349cl,0xd52f4cc98562baa5l, + 0xc74a9e862b290df3l }, + { 0xd3a1aa3543471a24l,0x239446beb8194511l,0xbec2dd0081dcd44dl, + 0xca3d7f0fc42ac82dl }, + 0 }, + /* 49 << 224 */ + { { 0x1f3db085fdaf4520l,0xbb6d3e804549daf2l,0xf5969d8a19ad5c42l, + 0x7052b13ddbfd1511l }, + { 0x11890d1b682b9060l,0xa71d3883ac34452cl,0xa438055b783805b4l, + 0x432412774725b23el }, + 0 }, + /* 51 << 224 */ + { { 0x40b08f7443b30ca8l,0xe10b5bbad9934583l,0xe8a546d6b51110adl, + 0x1dd50e6628e0b6c5l }, + { 0x292e9d54cff2b821l,0x3882555d47281760l,0x134838f83724d6e3l, + 0xf2c679e022ddcda1l }, + 0 }, + /* 52 << 224 */ + { { 0x40ee88156d2a5768l,0x7f227bd21c1e7e2dl,0x487ba134d04ff443l, + 0x76e2ff3dc614e54bl }, + { 0x36b88d6fa3177ec7l,0xbf731d512328fff5l,0x758caea249ba158el, + 0x5ab8ff4c02938188l }, + 0 }, + /* 53 << 224 */ + { { 0x33e1605635edc56dl,0x5a69d3497e940d79l,0x6c4fd00103866dcbl, + 0x20a38f574893cdefl }, + { 0xfbf3e790fac3a15bl,0x6ed7ea2e7a4f8e6bl,0xa663eb4fbc3aca86l, + 0x22061ea5080d53f7l }, + 0 }, + /* 55 << 224 */ + { { 0x635a8e5ec3a0ee43l,0x70aaebca679898ffl,0x9ee9f5475dc63d56l, + 0xce987966ffb34d00l }, + { 0xf9f86b195e26310al,0x9e435484382a8ca8l,0x253bcb81c2352fe4l, + 0xa4eac8b04474b571l }, + 0 }, + /* 57 << 224 */ + { { 0x2617f91c93aa96b8l,0x0fc8716b7fca2e13l,0xa7106f5e95328723l, + 0xd1c9c40b262e6522l }, + { 0xb9bafe8642b7c094l,0x1873439d1543c021l,0xe1baa5de5cbefd5dl, + 0xa363fc5e521e8affl }, + 0 }, + /* 59 << 224 */ + { { 0xbc00fc2f2f8ba2c7l,0x0966eb2f7c67aa28l,0x13f7b5165a786972l, + 0x3bfb75578a2fbba0l }, + { 0x131c4f235a2b9620l,0xbff3ed276faf46bel,0x9b4473d17e172323l, + 0x421e8878339f6246l }, + 0 }, + /* 60 << 224 */ + { { 0x0fa8587a25a41632l,0xc0814124a35b6c93l,0x2b18a9f559ebb8dbl, + 0x264e335776edb29cl }, + { 0xaf245ccdc87c51e2l,0x16b3015b501e6214l,0xbb31c5600a3882cel, + 0x6961bb94fec11e04l }, + 0 }, + /* 61 << 224 */ + { { 0x3b825b8deff7a3a0l,0xbec33738b1df7326l,0x68ad747c99604a1fl, + 0xd154c9349a3bd499l }, + { 0xac33506f1cc7a906l,0x73bb53926c560e8fl,0x6428fcbe263e3944l, + 0xc11828d51c387434l }, + 0 }, + /* 63 << 224 */ + { { 0x659b17c8d8ceb147l,0x9b649eeeb70a5554l,0x6b7fa0b5ac6bc634l, + 0xd99fe2c71d6e732fl }, + { 0x30e6e7628d3abba2l,0x18fee6e7a797b799l,0x5c9d360dc696464dl, + 0xe3baeb4827bfde12l }, + 0 }, + /* 64 << 224 */ + { { 0x2bf5db47f23206d5l,0x2f6d34201d260152l,0x17b876533f8ff89al, + 0x5157c30c378fa458l }, + { 0x7517c5c52d4fb936l,0xef22f7ace6518cdcl,0xdeb483e6bf847a64l, + 0xf508455892e0fa89l }, + 0 }, + /* 65 << 224 */ + { { 0xf77bb113a74ed3bel,0x89e4eb8f074f2637l,0x7fbfa84df7ce2aebl, + 0xe7c6ecd5baaefe4cl }, + { 0x176bba7df6319542l,0x70098120f6080799l,0x2e2118339054d9aal, + 0x1be4c6a78295a912l }, + 0 }, + /* 71 << 224 */ + { { 0x6bb4d8c35df1455fl,0xb839f08f0384b033l,0x718868af11f95d50l, + 0xae256a92e07a8801l }, + { 0xa5bafaf24d71a273l,0x18ff04ea2a30e68fl,0x364c193287ba727el, + 0x4bb8cf99befcaf73l }, + 0 }, + /* 77 << 224 */ + { { 0xc79f5b1f4e9fb3d7l,0x52854970a51cccddl,0xa4e27e97f00054a3l, + 0x26a79792240e1232l }, + { 0xb15579fecb5ff465l,0x6ef54c3bd1722a84l,0xee211bfa5239a4d8l, + 0x36c7db27270b7059l }, + 0 }, + /* 83 << 224 */ + { { 0x5e7da0a9f9858cd3l,0x67459de5b633de49l,0x2db0d54b2e73892el, + 0x37f50877adae399al }, + { 0x83c28b83b65e6179l,0xae5a915ca39faf17l,0x6ab8f3fbe841b53cl, + 0x7c30997b0df7d004l }, + 0 }, + /* 89 << 224 */ + { { 0x87904ca7b3b862bdl,0x7593db93cf9ea671l,0x8a2670f8739aa783l, + 0x3921d779f5154ca6l }, + { 0xe81ca56468f65ebbl,0x0c600603bc4e64d4l,0xdf170049cb83b2d1l, + 0x373893b863487064l }, + 0 }, + /* 95 << 224 */ + { { 0x7c3c52b9c0c4e88el,0x0f0484d06f0c2446l,0xeb876827000fe87bl, + 0xa749b3136d20f94al }, + { 0x0876dae9d55abda6l,0xe6e4367620726911l,0xf85e8a8c4a2676b4l, + 0x4e8c97f1b4a890ebl }, + 0 }, + /* 101 << 224 */ + { { 0xa992f482a3c0a4f4l,0xe1536f3f7a8d961al,0x26fc79ae000752b0l, + 0xdbfb706b76ad8508l }, + { 0x2642b2ed6f4cf9e4l,0xa013db54557fa7e2l,0x2ef711821d326116l, + 0x8dc3f5bcbafc83ecl }, + 0 }, + /* 107 << 224 */ + { { 0x9671258578e5a201l,0xc71aca1de9125569l,0x360c45c0e2231379l, + 0x2d71783512e82369l }, + { 0x392432d3d84b2153l,0x502fd3f6d6939ffel,0x33c440ae6e766cacl, + 0x99f1fbee28062416l }, + 0 }, + /* 113 << 224 */ + { { 0xe51ad841861604cbl,0x1ec9c54f630283a7l,0xcc42cad582a39473l, + 0xa2eb053709929c4al }, + { 0xe374459767f655a3l,0x9f54c2451d7f2674l,0xd85e9163fbc8aba5l, + 0x12fd0b55866bc892l }, + 0 }, + /* 116 << 224 */ + { { 0x4f2c3063d7bd4661l,0xe533798d57a974ccl,0x44860d503ea02d85l, + 0xf2a7f4e5acaa0521l }, + { 0x05593061abb108f0l,0x56d1056044528309l,0x1f674df9c88b6d1el, + 0x19fdc4cbd8744c4dl }, + 0 }, + /* 119 << 224 */ + { { 0xfd1488ec00f2f1d5l,0x24fcc67b44a825ddl,0xc7bfae2ea925a0f4l, + 0x5e03249cad59cf48l }, + { 0x1dc5a8e11af4844cl,0x89b2fbc58a598c20l,0xb0f56afff2078121l, + 0x8194012d4878bb0dl }, + 0 }, + /* 125 << 224 */ + { { 0xc1cbe9d3a5ae1031l,0x38da74435706b987l,0x01844b55b353f188l, + 0x390c59ca87a807c5l }, + { 0x55ac7b1fb13b780cl,0x060970bff375c1cbl,0x8dd1f378c7ab4e5cl, + 0xcca782e5cf726645l }, + 0 }, + }, + { + /* 0 << 232 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 232 */ + { { 0x91213462f23f2d92l,0x6cab71bd60b94078l,0x6bdd0a63176cde20l, + 0x54c9b20cee4d54bcl }, + { 0x3cd2d8aa9f2ac02fl,0x03f8e617206eedb0l,0xc7f68e1693086434l, + 0x831469c592dd3db9l }, + 0 }, + /* 3 << 232 */ + { { 0x4a9090cde36d0757l,0xf722d7b1d9a29382l,0xfb7fb04c04b48ddfl, + 0x628ad2a7ebe16f43l }, + { 0xcd3fbfb520226040l,0x6c34ecb15104b6c4l,0x30c0754ec903c188l, + 0xec336b082d23cab0l }, + 0 }, + /* 4 << 232 */ + { { 0x9f51439e558df019l,0x230da4baac712b27l,0x518919e355185a24l, + 0x4dcefcdd84b78f50l }, + { 0xa7d90fb2a47d4c5al,0x55ac9abfb30e009el,0xfd2fc35974eed273l, + 0xb72d824cdbea8fafl }, + 0 }, + /* 5 << 232 */ + { { 0xd213f923cbb13d1bl,0x98799f425bfb9bfel,0x1ae8ddc9701144a9l, + 0x0b8b3bb64c5595eel }, + { 0x0ea9ef2e3ecebb21l,0x17cb6c4b3671f9a7l,0x47ef464f726f1d1fl, + 0x171b94846943a276l }, + 0 }, + /* 7 << 232 */ + { { 0xc9941109a607419dl,0xfaa71e62bb6bca80l,0x34158c1307c431f3l, + 0x594abebc992bc47al }, + { 0x6dfea691eb78399fl,0x48aafb353f42cba4l,0xedcd65af077c04f0l, + 0x1a29a366e884491al }, + 0 }, + /* 9 << 232 */ + { { 0x7bf6a5c1f7ea25aal,0xd165e6bffbb07d5fl,0xe353936189e78671l, + 0xa3fcac892bac4219l }, + { 0xdfab6fd4f0baa8abl,0x5a4adac1e2c1c2e5l,0x6cd75e3140d85849l, + 0xce263fea19b39181l }, + 0 }, + /* 10 << 232 */ + { { 0xb8d804a3315980cdl,0x693bc492fa3bebf7l,0x3578aeee2253c504l, + 0x158de498cd2474a2l }, + { 0x1331f5c7cfda8368l,0xd2d7bbb378d7177el,0xdf61133af3c1e46el, + 0x5836ce7dd30e7be8l }, + 0 }, + /* 11 << 232 */ + { { 0xe042ece59a29a5c5l,0xb19b3c073b6c8402l,0xc97667c719d92684l, + 0xb5624622ebc66372l }, + { 0x0cb96e653c04fa02l,0x83a7176c8eaa39aal,0x2033561deaa1633fl, + 0x45a9d0864533df73l }, + 0 }, + /* 13 << 232 */ + { { 0xa29ae9df5ece6e7cl,0x0603ac8f0facfb55l,0xcfe85b7adda233a5l, + 0xe618919fbd75f0b8l }, + { 0xf555a3d299bf1603l,0x1f43afc9f184255al,0xdcdaf341319a3e02l, + 0xd3b117ef03903a39l }, + 0 }, + /* 15 << 232 */ + { { 0xb6b82fa74d82f4c2l,0x90725a606804efb3l,0xbc82ec46adc3425el, + 0xb7b805812787843el }, + { 0xdf46d91cdd1fc74cl,0xdc1c62cbe783a6c4l,0x59d1b9f31a04cbbal, + 0xd87f6f7295e40764l }, + 0 }, + /* 16 << 232 */ + { { 0x196860411e84e0e5l,0xa5db84d3aea34c93l,0xf9d5bb197073a732l, + 0xb8d2fe566bcfd7c0l }, + { 0x45775f36f3eb82fal,0x8cb20cccfdff8b58l,0x1659b65f8374c110l, + 0xb8b4a422330c789al }, + 0 }, + /* 17 << 232 */ + { { 0xa6312c9e8977d99bl,0xbe94433183f531e7l,0x8232c0c218d3b1d4l, + 0x617aae8be1247b73l }, + { 0x40153fc4282aec3bl,0xc6063d2ff7b8f823l,0x68f10e583304f94cl, + 0x31efae74ee676346l }, + 0 }, + /* 19 << 232 */ + { { 0xd98bf2a43734e520l,0x5e3abbe3209bdcbal,0x77c76553bc945b35l, + 0x5331c093c6ef14aal }, + { 0x518ffe2976b60c80l,0x2285593b7ace16f8l,0xab1f64ccbe2b9784l, + 0xe8f2c0d9ab2421b6l }, + 0 }, + /* 21 << 232 */ + { { 0x481dae5fd5ecfefcl,0x07084fd8c2bff8fcl,0x8040a01aea324596l, + 0x4c646980d4de4036l }, + { 0x9eb8ab4ed65abfc3l,0xe01cb91f13541ec7l,0x8f029adbfd695012l, + 0x9ae284833c7569ecl }, + 0 }, + /* 23 << 232 */ + { { 0xc83605f6f10ff927l,0xd387145123739fc6l,0x6d163450cac1c2ccl, + 0x6b521296a2ec1ac5l }, + { 0x0606c4f96e3cb4a5l,0xe47d3f41778abff7l,0x425a8d5ebe8e3a45l, + 0x53ea9e97a6102160l }, + 0 }, + /* 25 << 232 */ + { { 0x6b72fab526bc2797l,0x13670d1699f16771l,0x001700521e3e48d1l, + 0x978fe401b7adf678l }, + { 0x55ecfb92d41c5dd4l,0x5ff8e247c7b27da5l,0xe7518272013fb606l, + 0x5768d7e52f547a3cl }, + 0 }, + /* 27 << 232 */ + { { 0x0e966e64c73b2383l,0x49eb3447d17d8762l,0xde1078218da05dabl, + 0x443d8baa016b7236l }, + { 0x163b63a5ea7610d6l,0xe47e4185ce1ca979l,0xae648b6580baa132l, + 0xebf53de20e0d5b64l }, + 0 }, + /* 28 << 232 */ + { { 0x6ba535da9a85788bl,0xd21f03aebd0626d4l,0x099f8c47e873dc64l, + 0xcda8564d018ec97el }, + { 0x3e8d7a5cde92c68cl,0x78e035a173323cc4l,0x3ef26275f880ff7cl, + 0xa4ee3dff273eedaal }, + 0 }, + /* 29 << 232 */ + { { 0x8bbaec49571d92acl,0x569e85fe4692517fl,0x8333b014a14ea4afl, + 0x32f2a62f12e5c5adl }, + { 0x98c2ce3a06d89b85l,0xb90741aa2ff77a08l,0x2530defc01f795a2l, + 0xd6e5ba0b84b3c199l }, + 0 }, + /* 31 << 232 */ + { { 0x3d1b24cb28c682c6l,0x27f252288612575bl,0xb587c779e8e66e98l, + 0x7b0c03e9405eb1fel }, + { 0xfdf0d03015b548e7l,0xa8be76e038b36af7l,0x4cdab04a4f310c40l, + 0x6287223ef47ecaecl }, + 0 }, + /* 33 << 232 */ + { { 0x0a4c6f3670ad54aal,0xc24cfd0d2a543909l,0xe1b0bc5b745c1a97l, + 0xb8431cfd68f0ddbfl }, + { 0x326357989ed8cb06l,0xa00a80ff759d2b7dl,0x81f335c190570e02l, + 0xbfccd89849c4e4d9l }, + 0 }, + /* 34 << 232 */ + { { 0x4dcb646bfd16d8c4l,0x76a6b640e38ba57bl,0xd92de1f79d8ae7e2l, + 0x126f48f13f77f23bl }, + { 0xb7b53ca977e8abc2l,0x3faa17112c0787ffl,0xf8f9308c8e5762f8l, + 0x600a8a7f6b83aea8l }, + 0 }, + /* 35 << 232 */ + { { 0xa2aed4a799aa03c0l,0x1f93b93da18b79c5l,0x7b4550b7314192c3l, + 0x9da00676272bb08el }, + { 0xe42f0d7e23e072edl,0x7ce76494888b5783l,0x4c7900203680b63bl, + 0x6040c83f662a8718l }, + 0 }, + /* 36 << 232 */ + { { 0xba9e5c88a56d73edl,0x6c24f7712ca054d3l,0x4a37c235083beae1l, + 0x04a883b26483e9fdl }, + { 0x0c63f3aee27c2c5dl,0x0e1da88dae4671f1l,0xa577e8e25995e1dbl, + 0xbfc4b1b16ed6066al }, + 0 }, + /* 37 << 232 */ + { { 0x8b398541f53d9e63l,0x4ab045bb019395cbl,0x69a1b90371dd70c7l, + 0xdedf284b38aaa431l }, + { 0xb45e245aaed3efe7l,0x49460905079f2facl,0xde4dee470845bd78l, + 0x0540524039d02ec3l }, + 0 }, + /* 39 << 232 */ + { { 0x300cf051675cc986l,0x758afea99324219fl,0xf524c3fad5a93b5fl, + 0xb73385abc3864a8al }, + { 0xbde19289f6be9050l,0xbb9018558205a3f3l,0x99a9d14d229f6b89l, + 0x4c3a802f4336e68fl }, + 0 }, + /* 40 << 232 */ + { { 0xdd4a12d8e12b31f8l,0x577e29bc177736e6l,0x2353722ba88935e8l, + 0xca1d3729015f286dl }, + { 0x86c7b6a239a3e035l,0x6e5250bfd3b03a9fl,0x79d98930fd0d536el, + 0x8c4cbbabfa0c3832l }, + 0 }, + /* 41 << 232 */ + { { 0x92ecff374f8e6163l,0x171cc8830f35faeal,0xc5434242bcd36142l, + 0x707049adb28b63bbl }, + { 0xa1f4d1dbf6443da9l,0x002bb062dabc108bl,0x17287f171a272b08l, + 0x2a3aac8c884cf6bbl }, + 0 }, + /* 43 << 232 */ + { { 0x55524645651c0a5al,0x14624a9703cf0d12l,0xca9315a8f884a9e2l, + 0x9840c6e2df7c9d59l }, + { 0xd96bd10a7438e8d5l,0x12be73d2b2f887del,0x5e47445dca2493efl, + 0x85aef555e9fff03el }, + 0 }, + /* 44 << 232 */ + { { 0x169b38c9a43b2339l,0x884308d91732bfabl,0xe4b593a28ff202ddl, + 0xaf51d11f1e65376cl }, + { 0x6ec648de741525ffl,0xf93cbd369ff4c628l,0xc76df9efb1129c79l, + 0x31a5f2e2b7a67294l }, + 0 }, + /* 45 << 232 */ + { { 0x0661bc02801d0e38l,0x4a37dc0e71fc46b7l,0x0b224cfc80c3e311l, + 0x2dd3d2779646a957l }, + { 0xfa45aa18ef524012l,0x5d2a2d0916185a09l,0x34d5c630b5313dcel, + 0xd9581ed151e4cf84l }, + 0 }, + /* 46 << 232 */ + { { 0x5845aa4a8ebd2af8l,0x141404ecd3df43ccl,0xff3fc7681ffd48d9l, + 0x8a096e72e0cefb65l }, + { 0xc9c81cfdffc3a5cdl,0x7550aa3029b27cf9l,0x34dca72b65fa0380l, + 0xe8c5f6059ddd032bl }, + 0 }, + /* 47 << 232 */ + { { 0xe53da8a46bfbadb3l,0x4a9dfa55afaeeb5el,0x076245ea6644b1d4l, + 0xc19be4012307bbcbl }, + { 0x097774c19d77318bl,0xacc8a1519cfd51c4l,0x736ef6b3ecaa7b08l, + 0x107479132d643a80l }, + 0 }, + /* 48 << 232 */ + { { 0x2d500910cab91f1el,0xbedd9e444d1cd216l,0xd634b74fedd02252l, + 0xbd60f8e11258617al }, + { 0xd8c7537b9e05614al,0xfd26c766e7af5fc5l,0x0660b581582bd926l, + 0x87019244acf07fc8l }, + 0 }, + /* 49 << 232 */ + { { 0xd4889fdf6220ae8el,0x745d67ec1abf1549l,0x957b2e3d2fb89c36l, + 0x9768c90edc62ada9l }, + { 0x90332fd748e6c46el,0x5aa5a4e54e90ef0dl,0x58838fd3ddcc8571l, + 0xd12f6c6f9a721126l }, + 0 }, + /* 51 << 232 */ + { { 0x2f0fd0b2cec757bal,0x46a7a9c63032cd1dl,0x9af3a600547d7a77l, + 0x828e16eca43da1bal }, + { 0x0b303a66092a8d92l,0x78ba0389c23d08bal,0x52aed08d4616bd29l, + 0x4c0ff1210539c9fal }, + 0 }, + /* 52 << 232 */ + { { 0x2c3b7322badcfe8el,0x6e0616fac5e25a04l,0x0a3c12753da6e4a2l, + 0xe46c957e077bca01l }, + { 0xb46ca4e3da4be64bl,0xa59bda668e75ee78l,0x41835184a4de98f2l, + 0x6efb1f924ed6a568l }, + 0 }, + /* 53 << 232 */ + { { 0xbb8cdc094af1dd72l,0x93c0aa38a2460633l,0xf66f5d238a7ebc93l, + 0x43ecda843e8e37a6l }, + { 0x399da8265fd5139el,0x8b39930fd446f38el,0x114414135d2b68efl, + 0x8be163b8d1637c38l }, + 0 }, + /* 55 << 232 */ + { { 0x488e2a35b70ddbd3l,0xb4aa5f718da50077l,0xb38b74b1d8752bbdl, + 0x7007f328416106a3l }, + { 0xe6a62e4fcec4ea68l,0x9fdfb79741ef920bl,0x1a19d7dfe3c337a6l, + 0x08f643558be0f586l }, + 0 }, + /* 57 << 232 */ + { { 0x91a5d8ff60343a1fl,0x921e442173ef8cdfl,0x4358f27b975138cdl, + 0x36fd8577a4992b08l }, + { 0xc07c8ca1f8d044c6l,0xcf42903687747b6bl,0x0932ffb0867c8632l, + 0x7e565213250e5a89l }, + 0 }, + /* 59 << 232 */ + { { 0xae7c3b9b06255feal,0x2eb1d9a78a6fe229l,0xf81548e77601e6f8l, + 0x777394eb7bd96d6cl }, + { 0x54734187000a3509l,0xaeec146492d43c04l,0xc9b7f0d7c428b4acl, + 0x9d4bcedccd7f7018l }, + 0 }, + /* 60 << 232 */ + { { 0x4741b9b311370605l,0x47fa72f75d09b355l,0x391a71ac7a144c6al, + 0x0808c0f498b6e3cal }, + { 0x7eaed9ef7fe53900l,0xf157a2a5e5a830bal,0xd13ec09127974afcl, + 0x78d710a70b87997dl }, + 0 }, + /* 61 << 232 */ + { { 0xcbb96ecb4e263f81l,0x093e0d1509084351l,0x7af3232629220a81l, + 0xd721b415c60f36dcl }, + { 0xe3340a87fe9387a1l,0x6088bf482ff2b126l,0xd31028f1d2bc982cl, + 0x9794e106630d52cbl }, + 0 }, + /* 63 << 232 */ + { { 0x1dac76780b11e972l,0x46e814c62698dafel,0x553f7370c37640d6l, + 0xdcf588cc51cede93l }, + { 0x4d6b56d3c3f6215bl,0x07edc6621b8f8f03l,0xdfef9d60b9a5dfbcl, + 0x377edf4d10af7a5bl }, + 0 }, + /* 64 << 232 */ + { { 0x8928e99aeeaf8c49l,0xee7aa73d6e24d728l,0x4c5007c2e72b156cl, + 0x5fcf57c5ed408a1dl }, + { 0x9f719e39b6057604l,0x7d343c01c2868bbfl,0x2cca254b7e103e2dl, + 0xe6eb38a9f131bea2l }, + 0 }, + /* 65 << 232 */ + { { 0x26ae28bede7a4b7el,0xd2f07569d2664163l,0x798690d4ff69266al, + 0x77093d356ef3695dl }, + { 0xaca9903d567dd3dfl,0x259c59a3a274c67bl,0x9f34bc0bfc1198b0l, + 0x51a7726290b1521cl }, + 0 }, + /* 71 << 232 */ + { { 0xa20644bc80ca5391l,0xf9cdb4f7e5b36ea3l,0xe7936c0641426e22l, + 0x39bc23033eef8a52l }, + { 0x31253f43e5d8f896l,0xb0e5a588dc3df499l,0x1d03519a2d7e66d5l, + 0x923de91f6d7da5e3l }, + 0 }, + /* 77 << 232 */ + { { 0x17a833ffedf861e4l,0x0ee3d0af4ebec965l,0xd0fac1c1ea66870el, + 0x325756d0ae810cf4l }, + { 0x4ed78d2c78e9a415l,0x6cc65685192046e4l,0x03e4243d8498a91el, + 0x56a02dd25ab97794l }, + 0 }, + /* 83 << 232 */ + { { 0xc2fd373748e2b156l,0x259e9a98139645bel,0xe90106fb9877b4f1l, + 0x49e5bac5889ce002l }, + { 0x936a7dd18cf14e0bl,0x70bf6d304e3a8a01l,0x99d3e8bfeb748b62l, + 0xa52a27c99b31c55cl }, + 0 }, + /* 89 << 232 */ + { { 0x9db1d41d300637d5l,0xe38744397c2dd836l,0x36179baf0d04ceb3l, + 0xe9ccd17b251b3f2dl }, + { 0xd8228073442b6d1dl,0x59a038363eed2971l,0xb443732046979f5cl, + 0x54ad4113ae63937cl }, + 0 }, + /* 95 << 232 */ + { { 0x092c34e6d9246e9fl,0xb4b3b63d3eeb18a7l,0x8b3778beed9d1383l, + 0xe4cb7be9d70d5d80l }, + { 0xcff12e9b3d059203l,0x277af117ba86699fl,0x9bd4e8e363603585l, + 0x0750b0f28e89c8d5l }, + 0 }, + /* 101 << 232 */ + { { 0x38b77e5958f7187bl,0x31c7068de0cb618el,0xa0f8e0d6c11ebe62l, + 0x07adc8010473d7ebl }, + { 0x36161a2c5c3e9510l,0xb2ec90d64ad04815l,0x01e2dd1f917d8166l, + 0x549bcbdd6aa0f794l }, + 0 }, + /* 107 << 232 */ + { { 0x4ab27c3a8e4e45e5l,0xf6bd9d82f2bb99e7l,0xcab48c735e9da59fl, + 0xdeb09eb2b9727353l }, + { 0xc4a7954bafb8fa3el,0x34af2a49abf6803dl,0xc1ee1416d63e13bbl, + 0xd49bf42d7a949193l }, + 0 }, + /* 113 << 232 */ + { { 0x504823ea9c9c07c6l,0x9dbec902bee2288cl,0x018d7875f0ceb6bbl, + 0x678b997304f7022cl }, + { 0x74d658238c5fb369l,0x7d4e1f114ca89ee8l,0x148316399905abc0l, + 0xc107324e2c4deff4l }, + 0 }, + /* 116 << 232 */ + { { 0x1bc4fa8bdadc4404l,0x0edb9534daa12ee3l,0x084481b6a5f7289cl, + 0x7f42461d9d8fb3d2l }, + { 0xf93f1d3212293c70l,0xc14706596bb73ea3l,0xf80834afde339cadl, + 0x99dcfc0081f22953l }, + 0 }, + /* 119 << 232 */ + { { 0x497e544f9fca737el,0x7f6342210e91e1afl,0x638e500c78d7b20bl, + 0xb1ffed3f7ebaa947l }, + { 0x751aa54871086f83l,0x8100bb703cf97848l,0xc32f91ace19ad68fl, + 0x7dffb6851fb9157el }, + 0 }, + /* 125 << 232 */ + { { 0x5108589778e25060l,0x33e3cb7316cfe6cbl,0x0884cb8d410c0822l, + 0xaa806ecc0be3fc94l }, + { 0x9f9121f5f692353el,0xb9ab0310f8ee3349l,0x390032ce2561973el, + 0xc07b6c6c8856b766l }, + 0 }, + }, + { + /* 0 << 240 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 240 */ + { { 0x1083e2ea1f095615l,0x0a28ad7714e68c33l,0x6bfc02523d8818bel, + 0xb585113af35850cdl }, + { 0x7d935f0b30df8aa1l,0xaddda07c4ab7e3acl,0x92c34299552f00cbl, + 0xc33ed1de2909df6cl }, + 0 }, + /* 3 << 240 */ + { { 0xabe7905a83cdd60el,0x50602fb5a1170184l,0x689886cdb023642al, + 0xd568d090a6e1fb00l }, + { 0x5b1922c70259217fl,0x93831cd9c43141e4l,0xdfca35870c95f86el, + 0xdec2057a568ae828l }, + 0 }, + /* 4 << 240 */ + { { 0x568f8925913cc16dl,0x18bc5b6de1a26f5al,0xdfa413bef5f499ael, + 0xf8835decc3f0ae84l }, + { 0xb6e60bd865a40ab0l,0x65596439194b377el,0xbcd8562592084a69l, + 0x5ce433b94f23ede0l }, + 0 }, + /* 5 << 240 */ + { { 0x860d523d42e06189l,0xbf0779414e3aff13l,0x0b616dcac1b20650l, + 0xe66dd6d12131300dl }, + { 0xd4a0fd67ff99abdel,0xc9903550c7aac50dl,0x022ecf8b7c46b2d7l, + 0x3333b1e83abf92afl }, + 0 }, + /* 7 << 240 */ + { { 0xefecdef7be42a582l,0xd3fc608065046be6l,0xc9af13c809e8dba9l, + 0x1e6c9847641491ffl }, + { 0x3b574925d30c31f7l,0xb7eb72baac2a2122l,0x776a0dacef0859e7l, + 0x06fec31421900942l }, + 0 }, + /* 9 << 240 */ + { { 0x7ec62fbbf4737f21l,0xd8dba5ab6209f5acl,0x24b5d7a9a5f9adbel, + 0x707d28f7a61dc768l }, + { 0x7711460bcaa999eal,0xba7b174d1c92e4ccl,0x3c4bab6618d4bf2dl, + 0xb8f0c980eb8bd279l }, + 0 }, + /* 10 << 240 */ + { { 0x9d658932790691bfl,0xed61058906b736ael,0x712c2f04c0d63b6el, + 0x5cf06fd5c63d488fl }, + { 0x97363facd9588e41l,0x1f9bf7622b93257el,0xa9d1ffc4667acacel, + 0x1cf4a1aa0a061ecfl }, + 0 }, + /* 11 << 240 */ + { { 0x28d675b2c0519a23l,0x9ebf94fe4f6952e3l,0xf28bb767a2294a8al, + 0x85512b4dfe0af3f5l }, + { 0x18958ba899b16a0dl,0x95c2430cba7548a7l,0xb30d1b10a16be615l, + 0xe3ebbb9785bfb74cl }, + 0 }, + /* 13 << 240 */ + { { 0x81eeb865d2fdca23l,0x5a15ee08cc8ef895l,0x768fa10a01905614l, + 0xeff5b8ef880ee19bl }, + { 0xf0c0cabbcb1c8a0el,0x2e1ee9cdb8c838f9l,0x0587d8b88a4a14c0l, + 0xf6f278962ff698e5l }, + 0 }, + /* 15 << 240 */ + { { 0x9c4b646e9e2fce99l,0x68a210811e80857fl,0x06d54e443643b52al, + 0xde8d6d630d8eb843l }, + { 0x7032156342146a0al,0x8ba826f25eaa3622l,0x227a58bd86138787l, + 0x43b6c03c10281d37l }, + 0 }, + /* 16 << 240 */ + { { 0x02b37a952f41deffl,0x0e44a59ae63b89b7l,0x673257dc143ff951l, + 0x19c02205d752baf4l }, + { 0x46c23069c4b7d692l,0x2e6392c3fd1502acl,0x6057b1a21b220846l, + 0xe51ff9460c1b5b63l }, + 0 }, + /* 17 << 240 */ + { { 0x7aca2632f02fc0f0l,0xb92b337dc7f01c86l,0x624bc4bf5afbdc7dl, + 0x812b07bc4de21a5el }, + { 0x29d137240b2090ccl,0x0403c5095a1b2132l,0x1dca34d50e35e015l, + 0xf085ed7d3bbbb66fl }, + 0 }, + /* 19 << 240 */ + { { 0xc27b98f9f781e865l,0x51e1f692994e1345l,0x0807d516e19361eel, + 0x13885ceffb998aefl }, + { 0xd223d5e92f0f8a17l,0x48672010e8d20280l,0x6f02fd60237eac98l, + 0xcc51bfad9ada7ee7l }, + 0 }, + /* 21 << 240 */ + { { 0x2756bcdd1e09701dl,0x94e31db990d45c80l,0xb9e856a98566e584l, + 0x4f87d9deab10e3f3l }, + { 0x166ecb373ded9cb2l,0xfd14c7073f653d3el,0x105d049b92aec425l, + 0x7f657e4909a42e11l }, + 0 }, + /* 23 << 240 */ + { { 0xea6490076a159594l,0x3e424d6b1f97ce52l,0xac6df30a185e8ccbl, + 0xad56ec80517747bfl }, + { 0xf0935ccf4391fe93l,0x866b260f03811d40l,0x792047b99f7b9abel, + 0xb1600bc88ee42d84l }, + 0 }, + /* 25 << 240 */ + { { 0x2d97b3db7768a85fl,0x2b78f6334287e038l,0x86c947676f892bb1l, + 0x920bfb1ac0a9c200l }, + { 0x4292f6ec332041b2l,0xa30bb937c9989d54l,0x39f941ebc6d5879el, + 0x76a450fcdfdbb187l }, + 0 }, + /* 27 << 240 */ + { { 0x31256089ee430db6l,0xaece9bd8f6836f56l,0x484cfc4bfb85a046l, + 0xee1e3e2c1599b2b9l }, + { 0x7e3c38903d122eafl,0xaa940ce0c770556cl,0x4802d6631b08fae8l, + 0xb08a85807f69f8bal }, + 0 }, + /* 28 << 240 */ + { { 0x70ed0a0405411eael,0x60deb08f16494c66l,0x8cf20fc6133797bbl, + 0x3e30f4f50c6bc310l }, + { 0x1a677c29749c46c7l,0xfe1d93f4f11e981cl,0x937303d82e3e688bl, + 0x01aef5a7a6aa9e85l }, + 0 }, + /* 29 << 240 */ + { { 0x4902f495b959b920l,0x13b0fdbdfca2d885l,0x41cbd9e7b6a2f0fal, + 0xf9bdf11056430b87l }, + { 0xd705a223954d19b9l,0x74d0fc5c972a4fdel,0xcbcbfed6912977eal, + 0x870611fdcc59a5afl }, + 0 }, + /* 31 << 240 */ + { { 0xf4f19bd04089236al,0x3b206c12313d0e0bl,0x73e70df303feaeb2l, + 0x09dba0eb9bd1efe0l }, + { 0x4c7fd532fc4e5305l,0xd792ffede93d787al,0xc72dc4e2e4245010l, + 0xe7e0d47d0466bbbdl }, + 0 }, + /* 33 << 240 */ + { { 0x549c861983e4f8bbl,0xf70133fbd8e06829l,0xc962b8e28c64e849l, + 0xad87f5b1901e4c25l }, + { 0xd005bde568a1cab5l,0x6a591acf0d2a95bal,0x728f14ce30ebcae4l, + 0x303cec99a3459b0fl }, + 0 }, + /* 34 << 240 */ + { { 0x62e62f258350e6bcl,0x5a5ea94d96adba1fl,0x36c2a2844a23c7b3l, + 0x32f50a72992f5c8bl }, + { 0x55d685204136c6afl,0x1aafd32992794f20l,0x69f5d820b59aa9bfl, + 0x218966a8570e209al }, + 0 }, + /* 35 << 240 */ + { { 0xf3204feb2f9a31fcl,0x77f33a360429f463l,0xfb9f3a5a59a1d6a7l, + 0x4445a2e93b1a78e0l }, + { 0xc77a9b6fd58e32d3l,0xa44e23c8302e6390l,0x7d8e00b4c0f7bcb0l, + 0xd2e2237b0ffa46f4l }, + 0 }, + /* 36 << 240 */ + { { 0xb3046cb13c8ea6d3l,0xf0151b5efce2f445l,0xa968e60b55e5715el, + 0x39e52662587dce61l }, + { 0xfde176e0b7de2862l,0x298d83e68e8db497l,0x1042136773641bfbl, + 0xd72ac78d36e0bb0dl }, + 0 }, + /* 37 << 240 */ + { { 0x2cabb94fff6b8340l,0xf425a35a21771acbl,0x564fec3d12c4a758l, + 0x57a61af39ba8f281l }, + { 0x5807e78c97e9a71dl,0x991d9be75b8314e6l,0x1cd90b16ec4133b9l, + 0xff043efa0f1ac621l }, + 0 }, + /* 39 << 240 */ + { { 0xea6e5527d7e58321l,0xfb95c13c04056ff1l,0x9447361f2fc4e732l, + 0x63cbc655786d0154l }, + { 0x302c0d668610fb71l,0xbf692d6920d06613l,0x8465b74b4be8355al, + 0xcc883c95c31356b7l }, + 0 }, + /* 40 << 240 */ + { { 0x4ab6e919b33eabcal,0xb58f0998a1acacbfl,0xa747e5782ddbc28fl, + 0xf9dd04ca59866cbcl }, + { 0x084c062ff7a0073fl,0x6d22acdfb577fc38l,0x0870ee08eacd907cl, + 0x710b4b266c9fcf95l }, + 0 }, + /* 41 << 240 */ + { { 0xa99546faf1c835a7l,0x1514a5a30d59f933l,0x1f6ad0f81bedd730l, + 0x24de76287b528aaal }, + { 0x4d9e7845c02fff87l,0xba74f8a942c79e67l,0x5bf5015f476e285bl, + 0x0b1a5d8b1b93b364l }, + 0 }, + /* 43 << 240 */ + { { 0x8c7c0d7ff839819fl,0xc82b819827a95965l,0xce7294d377270519l, + 0xfb508d6cad47aff7l }, + { 0xf6de15431035076al,0x697d60ac5dd465c6l,0x88d771b8a76dcd26l, + 0x8c7ce11ab10c9c44l }, + 0 }, + /* 44 << 240 */ + { { 0x215ea44a08216060l,0xccfa18a187996cf6l,0xccfb2483f7eccdd2l, + 0x07aa601ad453c66al }, + { 0xd43cf263cffee9e2l,0x230bc099718f69bfl,0xc43de21300c193e8l, + 0x94cf251799c8746fl }, + 0 }, + /* 45 << 240 */ + { { 0x4785d7f87d1320c5l,0x84bed8c3d0771dcbl,0xff28044d22254edbl, + 0x2e5992a445f71504l }, + { 0xcb92695b72bbf5cdl,0x9bcbde35c42422e5l,0x856594fd1d07ed86l, + 0x3aaf0b717716b4ffl }, + 0 }, + /* 46 << 240 */ + { { 0x3edf24f9eebed405l,0x9e3141360eccb503l,0xf7704c25b85c2bc2l, + 0x4cb7c1de9a3247eel }, + { 0x798ac8f2f0b507c5l,0x6e6217206851bbf1l,0xc0b89398c0d9ed16l, + 0xf7d5d2a09f20728fl }, + 0 }, + /* 47 << 240 */ + { { 0x7358a94a19f0ededl,0x5e08c4c3e32ccfbbl,0x84a8eeeb0089f071l, + 0xdaf0514c41fc436el }, + { 0x30fe216f310309afl,0xe72f77bd564e6fc9l,0xe7ef3bddfdc59fd5l, + 0xd199b1c9a8e1169cl }, + 0 }, + /* 48 << 240 */ + { { 0xb9dc857c5b0f7bd4l,0x6990c2c9108ea1cdl,0x84730b83b984c7a9l, + 0x552723d2eab18a78l }, + { 0x9752c2e2919ba0f9l,0x075a3bd94bf40890l,0x71e52a04a6d98212l, + 0x3fb6607a9f18a4c8l }, + 0 }, + /* 49 << 240 */ + { { 0xa0305d01e8c3214dl,0x025b3cae8d51cea3l,0xeeaf7ab239923274l, + 0x51179407c876b72cl }, + { 0xcf0241c7d4549a68l,0xffae7f4c793dab3dl,0xdfb5917b4bdf2280l, + 0xcf25c870a652e391l }, + 0 }, + /* 51 << 240 */ + { { 0xb1345466b922e1c8l,0xae42f46ab5bf8a34l,0x1e1ab6053310e604l, + 0x64093cd9b4d7a658l }, + { 0x5d3b385ab3d9242cl,0x2225b99ae56f8ec7l,0x19a8cbfc9a916e11l, + 0x11c5df831f957c03l }, + 0 }, + /* 52 << 240 */ + { { 0x09f1d04af381147bl,0x7be13628b26b345fl,0xd8371966d1c60b78l, + 0xf1743c2c5d91808fl }, + { 0x8a2966acafc71cc3l,0x0ba9702efdfc24c3l,0x60c80158e6fbb539l, + 0x58eaee49812c32f4l }, + 0 }, + /* 53 << 240 */ + { { 0x31af7f5ee89d0b84l,0xa776dada6caa110bl,0xd67b7891df6d54ddl, + 0x831613cab82b8a5cl }, + { 0x7a4eb86ef020af6dl,0x2914fd11bd795a7bl,0xc038a273fcb54a17l, + 0x6b2dc8e18219cc75l }, + 0 }, + /* 55 << 240 */ + { { 0x031fc875464ba9b5l,0xe268cf45bd812dd3l,0x443f57defbfb664al, + 0xfd1a38544e28c2fal }, + { 0xb8799782cb96515bl,0xa12d3e3f1138c95dl,0x0cc5ee117748ee57l, + 0x6ab167cf955a7dfcl }, + 0 }, + /* 57 << 240 */ + { { 0x0d54aaca4dc1c74fl,0x74af1807bf2e0d61l,0x151254f87aebe0f1l, + 0x4072f38bf6376095l }, + { 0x31ebe17a26646abfl,0xdc8cb6b40ecc1282l,0x4f6326bbbc095a66l, + 0x37dad65a0363636dl }, + 0 }, + /* 59 << 240 */ + { { 0xc851860a70f8c15al,0xb2d4555488368381l,0xbfd46e197019c7b6l, + 0xa1a9b12f6bb6f33bl }, + { 0xecfd5fe6f170c82bl,0x6d58bb52d601afc3l,0xb8b3de15fe6eb102l, + 0xad07336886a47964l }, + 0 }, + /* 60 << 240 */ + { { 0x89f514c91911840fl,0xc9fa6b504cc106bcl,0x70a97f0dfe55b4f1l, + 0xada6306be5888609l }, + { 0xa9437881c6dc8d15l,0x0fc0f5368411f3dfl,0xd26162087a913dd2l, + 0x4fe1c7c4e92848cdl }, + 0 }, + /* 61 << 240 */ + { { 0xaa18eb262e07383dl,0xb948c35c34e90f3dl,0x95e97f81d3653565l, + 0x4a821a2687b5b75dl }, + { 0x87b4d81c892db882l,0xa69e65d689f3bfadl,0xe475f532eb371cacl, + 0xd8cc23fa17194d5dl }, + 0 }, + /* 63 << 240 */ + { { 0x3fc0052ad789d484l,0xe8c67aac29324323l,0x133fd07cf54c43d3l, + 0xd4a0848fb91d4faal }, + { 0xf683ce065ea5098fl,0xe84348f9887c8a76l,0x38f8c2cf79b224b6l, + 0x327e4c534a818cb1l }, + 0 }, + /* 64 << 240 */ + { { 0xb6d92a7f3e5f9f11l,0x9afe153ad6cb3b8el,0x4d1a6dd7ddf800bdl, + 0xf6c13cc0caf17e19l }, + { 0x15f6c58e325fc3eel,0x71095400a31dc3b2l,0x168e7c07afa3d3e7l, + 0x3f8417a194c7ae2dl }, + 0 }, + /* 65 << 240 */ + { { 0x0c9e9237d5f812bcl,0xdae5b7e9595f02e5l,0x5ec1dece42b1e9a8l, + 0x506a6ef8e527a685l }, + { 0xe3049290236af251l,0x6322dd1bf81970acl,0x1459d39c516d5e61l, + 0x672f502d9455b694l }, + 0 }, + /* 71 << 240 */ + { { 0xf83788e06b228af2l,0xaafc823911f596fal,0x6d47fa592f0fcb13l, + 0x0b7af65f1c99c5d4l }, + { 0xbc4c185dca961e6fl,0xec02b09f158481a4l,0x4bbfd9f31423fdd4l, + 0x0ff44a53b619644bl }, + 0 }, + /* 77 << 240 */ + { { 0x23e255a3ea3f59d8l,0x1f4a47a8261ac30bl,0x346bf409c8faf0b3l, + 0xd13e73fbc03a226bl }, + { 0x670ddc792fe8a79bl,0x335fa172f1aac412l,0xe2347de1a5ceff20l, + 0x66e02c73381130f2l }, + 0 }, + /* 83 << 240 */ + { { 0xa6b874c51db717cdl,0x027d318ab00f160bl,0x578f89f49be791afl, + 0x659ef2f01f3b5e9bl }, + { 0xa0c593033835d84cl,0xb71e261fdb6f9a60l,0x65837c7f44b7813fl, + 0xea776163ea4bcc96l }, + 0 }, + /* 89 << 240 */ + { { 0x208234118df3f15fl,0xe0514d4694f341acl,0xdc66282d6486d704l, + 0xd5fb354ad2548389l }, + { 0xf3e98d72df273295l,0x27ded7fa50cd09fcl,0x4f486af3c5c1c169l, + 0xe51044150aa41ba3l }, + 0 }, + /* 95 << 240 */ + { { 0x66b14d296fce0aecl,0x35fe5e60c8915ceal,0x06a023b736c5da39l, + 0x0977c9f0404e932fl }, + { 0x1dd6f95db54866del,0xe5ec79359387430cl,0x98dee57b5ef42e67l, + 0x1707f01912ed3ad0l }, + 0 }, + /* 101 << 240 */ + { { 0xeb3abdedeec82495l,0x587a696e764a41c7l,0x13fdcce2add1a6a3l, + 0x299a0d43286b2162l }, + { 0x2c4e71e18131f1b4l,0x48f0e806ada3d04fl,0x91d2de80c57491b2l, + 0x1b1266236cc355cbl }, + 0 }, + /* 107 << 240 */ + { { 0xdc28afe5a6d44444l,0xb5ad8d3cfe0b947bl,0x50c6126c96ce9fb9l, + 0x5384a998d1fc7d39l }, + { 0xa43ff8898788f51cl,0x30359593a6bc7b87l,0x3e1691dccc0d019al, + 0xda0ef5ad7943abcdl }, + 0 }, + /* 113 << 240 */ + { { 0x5bc58b6f020b5cd7l,0x9098e202e103ff4el,0xc1f1a3d9f6fce7c7l, + 0xf9dc32a856090ccel }, + { 0x4c7d2520a9cc3b09l,0x98d47b5dd8c4dfcel,0xdcee788297e689b4l, + 0xe5eec71815f982b9l }, + 0 }, + /* 116 << 240 */ + { { 0xff154bb8a1e1538cl,0xb9883276f7dcfae9l,0x1ac0a4d2c1c8cba4l, + 0x511a54cc76e6b284l }, + { 0xe2da436f00011f6dl,0x4d357a190f43a8adl,0xf36899c95458655bl, + 0xe5f75c768d613ed9l }, + 0 }, + /* 119 << 240 */ + { { 0x15b4af1d93f12ef8l,0x3f4c5868fd032f88l,0x39f67a08f27d86bdl, + 0x2f551820da32db6bl }, + { 0x72fe295ac2c16214l,0x39927c381a2cf9afl,0x8dda23d6b1dc1ae7l, + 0x1209ff3ed32071d4l }, + 0 }, + /* 125 << 240 */ + { { 0x861fdceb9a3c6c6fl,0x76d7a01386778453l,0xbf8d147cd5e422cbl, + 0xd16f532e51772d19l }, + { 0x72025ee2570d02cdl,0xe8e7737be80c7664l,0x81b7d56c334a8d8fl, + 0x42477a0ff1b79308l }, + 0 }, + }, + { + /* 0 << 248 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 248 */ + { { 0xf306a3c8ee3c76cbl,0x3cf11623d32a1f6el,0xe6d5ab646863e956l, + 0x3b8a4cbe5c005c26l }, + { 0xdcd529a59ce6bb27l,0xc4afaa5204d4b16fl,0xb0624a267923798dl, + 0x85e56df66b307fabl }, + 0 }, + /* 3 << 248 */ + { { 0x896895959884aaf7l,0xb1959be307b348a6l,0x96250e573c147c87l, + 0xae0efb3add0c61f8l }, + { 0xed00745eca8c325el,0x3c911696ecff3f70l,0x73acbc65319ad41dl, + 0x7b01a020f0b1c7efl }, + 0 }, + /* 4 << 248 */ + { { 0x9910ba6b23a5d896l,0x1fe19e357fe4364el,0x6e1da8c39a33c677l, + 0x15b4488b29fd9fd0l }, + { 0x1f4392541a1f22bfl,0x920a8a70ab8163e8l,0x3fd1b24907e5658el, + 0xf2c4f79cb6ec839bl }, + 0 }, + /* 5 << 248 */ + { { 0x262143b5224c08dcl,0x2bbb09b481b50c91l,0xc16ed709aca8c84fl, + 0xa6210d9db2850ca8l }, + { 0x6d8df67a09cb54d6l,0x91eef6e0500919a4l,0x90f613810f132857l, + 0x9acede47f8d5028bl }, + 0 }, + /* 7 << 248 */ + { { 0x45e21446de673629l,0x57f7aa1e703c2d21l,0xa0e99b7f98c868c7l, + 0x4e42f66d8b641676l }, + { 0x602884dc91077896l,0xa0d690cfc2c9885bl,0xfeb4da333b9a5187l, + 0x5f789598153c87eel }, + 0 }, + /* 9 << 248 */ + { { 0xb19b1c4fca66eca8l,0xf04a20b55663de54l,0x42a29a33c223b617l, + 0x86c68d0d44827e11l }, + { 0x71f90ddeadba1206l,0xeeffb4167a6ceeeal,0x9e302fbac543e8afl, + 0xcf07f7471aa77b96l }, + 0 }, + /* 10 << 248 */ + { { 0xcf57fca29849e95bl,0x96e9793ed510053cl,0x89fa443d07d3e75el, + 0xfe2bc235e52800a0l }, + { 0x1c208b8c0ac7e740l,0xb5852a49e7222263l,0x217e4005e541e592l, + 0xee52747dc960b0e1l }, + 0 }, + /* 11 << 248 */ + { { 0x5fd7cafb475952afl,0x23a6d71954a43337l,0xa83a7523b1617941l, + 0x0b7f35d412b37dd4l }, + { 0x81ec51292ae27eafl,0x7ca92fb3318169dfl,0xc01bfd6078d0875al, + 0xcc6074e3c99c436el }, + 0 }, + /* 13 << 248 */ + { { 0x4ca6bdebf57912b8l,0x9a17577e98507b5al,0x8ed4ab7759e51dfcl, + 0x103b7b2a470f5a36l }, + { 0x0c8545ac12553321l,0xab5861a760482817l,0xf4b5f602b9b856cfl, + 0x609955787adf2e5fl }, + 0 }, + /* 15 << 248 */ + { { 0x60ce25b1ee5cb44fl,0xddcc7d182c2d7598l,0x1765a1b301847b5cl, + 0xf5d9c3635d0d23b7l }, + { 0x42ff1ba7928b65d0l,0x587ac69d6148e043l,0x3099be0dd320390bl, + 0xa7b88dfc4278329fl }, + 0 }, + /* 16 << 248 */ + { { 0x80802dc91ec34f9el,0xd8772d3533810603l,0x3f06d66c530cb4f3l, + 0x7be5ed0dc475c129l }, + { 0xcb9e3c1931e82b10l,0xc63d2857c9ff6b4cl,0xb92118c692a1b45el, + 0x0aec44147285bbcal }, + 0 }, + /* 17 << 248 */ + { { 0x7685bb9e0ba4e0b7l,0x330a7ebc5e58c29bl,0xbc1d9173e8a3797al, + 0x7c506a16ea60f86cl }, + { 0x9defb9248c099445l,0xcf1ddcc0256df210l,0x4844ce293d07e990l, + 0x92318e37e2628503l }, + 0 }, + /* 19 << 248 */ + { { 0x61acd597fdf968d7l,0x7321a8b26598c381l,0xcb86a2809f448a0cl, + 0x38534a01855df66al }, + { 0xc119ec141e29037fl,0xe23c20ad0b42ba67l,0xefb1c4e033fb4f22l, + 0xf088358f445a5032l }, + 0 }, + /* 21 << 248 */ + { { 0x2d73f5d1b8475744l,0xcc297e0a9d399b06l,0xa8c61d4038d3df06l, + 0xacc6e8651a2d27a0l }, + { 0x63dd6f6230153bf2l,0x6b23ad7bd73b83b7l,0x25382bf767ff7dcdl, + 0x7e268c8fcf7ce2d1l }, + 0 }, + /* 23 << 248 */ + { { 0x4b9161c3cb2ebef1l,0x6009716b669ed801l,0x97c65219aacefe44l, + 0xde13597d71aae4b5l }, + { 0x3a077a816141d651l,0xe1b4e80129f876eal,0x729aed6d5c00c96cl, + 0x0c6f404374cc645el }, + 0 }, + /* 25 << 248 */ + { { 0x22c51812df5a66e1l,0x1c8069c9ae7dedeal,0xcff9d86f0eea5180l, + 0x676dbd6f44235ddal }, + { 0xa53f01383db1ad42l,0xd079e571bcf19029l,0x1e37b9ecfab0cf82l, + 0x93ae35ed4844e9c4l }, + 0 }, + /* 27 << 248 */ + { { 0xdaee55a543756358l,0x0ace18d41b2d3f89l,0x3391fa36824dd7d4l, + 0x7b9963d1770e5f3fl }, + { 0xc1fb9a78c94f724dl,0x94ff86fe76c4da6bl,0xb5d928c64170609bl, + 0xc9372becfb015a9fl }, + 0 }, + /* 28 << 248 */ + { { 0x9c34b650e16e05e9l,0x965a774094e74640l,0xa3fd22fbcea3f029l, + 0x1eb6a9688f95277cl }, + { 0x2520a63d7bad84f6l,0xad917201f58f2feel,0xea92c1669b840d48l, + 0x12109c4aacef5cbdl }, + 0 }, + /* 29 << 248 */ + { { 0xd85850d0d407a252l,0x6fa3b14de63909d4l,0x2ff9f6593e0fba69l, + 0x7f9fd2a2d1b2cd0bl }, + { 0x611233d745ad896al,0xfe4211648df850f9l,0x7808832399e32983l, + 0x4b040859dee6741dl }, + 0 }, + /* 31 << 248 */ + { { 0x7dd2afd456e1ed5cl,0xd48429ec41ba4992l,0x97a02188968bab27l, + 0x09ecf813e63c4168l }, + { 0xf4ac65e77288b10cl,0x10630ab2afac7410l,0x4e3e59c3bb049e56l, + 0x25972fff40fea0b1l }, + 0 }, + /* 33 << 248 */ + { { 0xfd8363da98365c18l,0x8aa57b1a8d47bf91l,0x423dce57695f4dd6l, + 0xfccf54d4cc17f034l }, + { 0x8fdba27c3610ea51l,0xcc0a06d654306b06l,0xb97a121c389b9dfdl, + 0x7dbb90eb1ed0ca42l }, + 0 }, + /* 34 << 248 */ + { { 0xd32d7cec0094e84cl,0x862ae25e2ece8f72l,0x8644ef1cdfceb8abl, + 0x68a9969c8e225628l }, + { 0xdf209e27b3117876l,0x308a6e1882ba242bl,0xcbd09a659bf0cdb6l, + 0x79f2826cc85b9705l }, + 0 }, + /* 35 << 248 */ + { { 0x3b36b6bf8f011496l,0xea6acc1a9bcf6ef8l,0x6db132263b101f12l, + 0x4fc4e35e3b7585c3l }, + { 0x641de27556eb64c6l,0x9b2834d3f3b08519l,0xebb76a2ba1f44b40l, + 0x1b545ccd3cd31677l }, + 0 }, + /* 36 << 248 */ + { { 0xab293027aad991c1l,0x598d0bf8849be4b7l,0x8c94a21ab972da90l, + 0xada4cfdd7ecfa840l }, + { 0x93d4b9c0fbcec63al,0x7ca617a203219a34l,0x900424eb6a652a55l, + 0xaf9346e9eb8562e0l }, + 0 }, + /* 37 << 248 */ + { { 0x9681a73d2d8bc904l,0x8b5f9b317b1553bel,0xfb03b874f6bc852fl, + 0x8e658fb8cbbec8b0l }, + { 0x9b2ff17bb9e9f9d1l,0xf46e9bf3e8679854l,0x7fbb1323618ed3aal, + 0x064a1c5d714ebc3dl }, + 0 }, + /* 39 << 248 */ + { { 0xac0bdfc39f0e69dcl,0x71957386ae12f132l,0xa263ef2e6aa90b5bl, + 0xa94b152390d42976l }, + { 0xfb2d17741bcdbf7bl,0xba77b77c3a04f72fl,0xa6818ed8ec3e25a1l, + 0x2e0e01743733e251l }, + 0 }, + /* 40 << 248 */ + { { 0xc3e04d7902381461l,0xb1643ab5911bc478l,0xc92becfa390b3ef2l, + 0x54476778acd2f1b6l }, + { 0x8daa0c4d66bf3aafl,0x2bc1287b2c21c65al,0xee182910b5a13ac3l, + 0xbb04730090b0790al }, + 0 }, + /* 41 << 248 */ + { { 0x8bdd6f35a8540489l,0x788c03e5ee390d4el,0x203323c18f653017l, + 0x39953308c4bc0094l }, + { 0x6ee0857118308d0bl,0x70e9f90b450b0002l,0x191662aa8139f145l, + 0xd7c5415b62d71124l }, + 0 }, + /* 43 << 248 */ + { { 0x41b37d72b927231cl,0xca17b5429e4de13al,0x7bc03469cded2ce3l, + 0x961b0ecb4f4560f9l }, + { 0x7c5bd41b43d31fa1l,0x3ed047f643f44dc3l,0x5b02083efe1a4d14l, + 0xcc2c66ac18b330bcl }, + 0 }, + /* 44 << 248 */ + { { 0x83766947d17d4e0bl,0xc5772beefdc3a47bl,0x765a50db1a6fd0ffl, + 0x17f904ba45b0995el }, + { 0xcee643832883487el,0xf56db7f3c270aaedl,0x6738d94f46cb1fd9l, + 0xc8fa426a142fd4d5l }, + 0 }, + /* 45 << 248 */ + { { 0xc85bef5b5a78efcel,0xaf380c6b0580e41el,0x6c093256a43b8d9bl, + 0xed9d07bbea670933l }, + { 0xfdb9a295f1682c6el,0x4cc29a63532b6bb7l,0x21a918f9f8e42dd0l, + 0x9ac935ce0edacca0l }, + 0 }, + /* 46 << 248 */ + { { 0xbfe48a8ff43daf9dl,0xd7799b31b313c052l,0x46d480d77119c60el, + 0x5090d91f0b80bcb9l }, + { 0xc94c4c1e873bd7bfl,0x16e69b4f9915aa0al,0x769be02bb1d5928cl, + 0x3fdaf62162e1d85al }, + 0 }, + /* 47 << 248 */ + { { 0x03497a57371c1b5cl,0x11e4c0b3552ab6abl,0xf857061f0a169ee7l, + 0xc21c6c43e6d1bc66l }, + { 0x706283a82832be7al,0xd35b143299aba62cl,0x7f4da83de9aef62dl, + 0x2b7e5fc8723fa4e5l }, + 0 }, + /* 48 << 248 */ + { { 0xae485bb72b724759l,0x945353e1b2d4c63al,0x82159d07de7d6f2cl, + 0x389caef34ec5b109l }, + { 0x4a8ebb53db65ef14l,0x2dc2cb7edd99de43l,0x816fa3ed83f2405fl, + 0x73429bb9c14208a3l }, + 0 }, + /* 49 << 248 */ + { { 0xc086e737eb4cfa54l,0x9400e1ad3c44aad9l,0x210bba94336959b4l, + 0x08621a809106f0cal }, + { 0x2ae66096c510ee9cl,0x2ba21617fc76a895l,0xc0707f8b0c186f1el, + 0x1fe170a3ed0bfe25l }, + 0 }, + /* 51 << 248 */ + { { 0x3780fe2084759c5cl,0x716ec626b7050aa7l,0x6a43fb8b84b63bd1l, + 0xb01098a039bc449fl }, + { 0x96b3ff8ebb7daa4dl,0x2d146882654a7f01l,0x2500f701dcae6143l, + 0xc13d51d01626fd3bl }, + 0 }, + /* 52 << 248 */ + { { 0x08ed8febd56daf06l,0x8d98277b4a837f69l,0x9947c636a9b6e05al, + 0x58c8a77ac0d58abdl }, + { 0xf45496a45f121e4fl,0x16cd67c71076d3d3l,0xecbd1958e3fb0c5dl, + 0xfbe185ec38e1eb47l }, + 0 }, + /* 53 << 248 */ + { { 0x65b067eb740216e3l,0x1e19a71479db8760l,0x8d30dca18878de5al, + 0x627d03e8aa47c005l }, + { 0x096d58c0d2536c96l,0x232e6a4d69b12c2al,0x850eb8c0e7044bcel, + 0xd9cf923bef2ee9a1l }, + 0 }, + /* 55 << 248 */ + { { 0x8b301094c8eaee90l,0x9a96950b8330928fl,0x472ba105faccc3bal, + 0x00f8620e9153172al }, + { 0x019b8164303fcdf5l,0x614d5c3c41fb4c73l,0x632d98f2c5992f89l, + 0xfbeb29d790e2dea5l }, + 0 }, + /* 57 << 248 */ + { { 0xefd48b577f91d6e0l,0x8575605595bcf5d4l,0x7677b4a7bb9d891bl, + 0xdc9931e9685912c9l }, + { 0x69bca306f31a07c8l,0x3dd729534962a7f0l,0xdcea49cc9d366c2al, + 0xce664ba7dc79a57dl }, + 0 }, + /* 59 << 248 */ + { { 0x7842d547013ec3b5l,0xa2785ceb433cf990l,0x9d667e5f700ab14al, + 0x4b46f362a0f46d55l }, + { 0x152c0e80cc7a3487l,0x7f3a88cef86f5e68l,0x6f950a73f1b2a75fl, + 0x9be5b1aa51d24f3bl }, + 0 }, + /* 60 << 248 */ + { { 0xaea68626dc4ad4f4l,0x5dc516824ddbc0b6l,0xa76697bd602e9065l, + 0xbeeb3ea58c37888el }, + { 0x1ec4a2f214569113l,0xe48b820ca35f4484l,0x9fb560949ae44df2l, + 0x6ca1346292cc09fdl }, + 0 }, + /* 61 << 248 */ + { { 0x887e0b87bcdc3a36l,0x6b0d617d503dee65l,0x96bda1f6cebcb893l, + 0xdc0dd17341e20b3el }, + { 0x812fbacfa6657c11l,0x32492fcbc94a6f4bl,0x854a0bcb6a772123l, + 0x1ed573f65d463f31l }, + 0 }, + /* 63 << 248 */ + { { 0x22c7ef7bd022cc4dl,0xeec383d61e63b4bcl,0x52e0aaa06502b46fl, + 0x9224187ded5e41bfl }, + { 0x3a01f53dd26faf1cl,0x9bc4ee2e4e591d10l,0x10b7a98eea7e4c88l, + 0xe521c150e2c1beccl }, + 0 }, + /* 64 << 248 */ + { { 0xb618d590b01e6e27l,0x047e2ccde180b2dcl,0xd1b299b504aea4a9l, + 0x412c9e1e9fa403a4l }, + { 0x88d28a3679407552l,0x49c50136f332b8e3l,0x3a1b6fcce668de19l, + 0x178851bc75122b97l }, + 0 }, + /* 65 << 248 */ + { { 0x26f9b9322ed53a71l,0x0bac7348c72ef2e0l,0x7e96001da5c6faf1l, + 0x5d43f76dea00eb2dl }, + { 0x1327370f44f1c478l,0x1c83a9ac6bb964c8l,0xa3a9769f76ffbd25l, + 0xdf045fb6b04f1bddl }, + 0 }, + /* 71 << 248 */ + { { 0x4283898d556b975el,0x6e2301ffe3880361l,0xc6d3b2bbe9198077l, + 0xc4799578d21cac02l }, + { 0x11448ff8f784eb7cl,0xb775973fbb81898dl,0x4e51f061519c76b9l, + 0xaba1f3ef3cad0393l }, + 0 }, + /* 77 << 248 */ + { { 0x59d60c1c9b339830l,0x5af60a44ac32746dl,0x5ac006bc9dea8d80l, + 0x4a2a56d97f2b1180l }, + { 0x2032845a46946fc4l,0xe25b911226a3b503l,0xfed89db9a28827d3l, + 0xdd2d7e90c6b74593l }, + 0 }, + /* 83 << 248 */ + { { 0x9b047a26cda38ecfl,0x6889284f5f6cb442l,0x4d128bcb14753820l, + 0x8f9937c160eedd78l }, + { 0xe333bad751ab9127l,0xd31b01c67ace3b19l,0x0732de39d7c0b4bel, + 0xad04fa4c649e2b9bl }, + 0 }, + /* 89 << 248 */ + { { 0x02e042689d1495bal,0x95dca5a85591b5f8l,0xb10488d856f46c71l, + 0x97829baf3590000al }, + { 0xaeda5cb378c9e78al,0x3615873a7ba1c71cl,0x7c9f9f4d4333aa12l, + 0x893fab42cea8e6d3l }, + 0 }, + /* 95 << 248 */ + { { 0x9eb09fff69aaa09fl,0xf36678a926731322l,0x8be61ee1cafcabafl, + 0x77a172f558ddb763l }, + { 0x7e09dfc66471130el,0x7f8909791039771el,0x0e44071d37800b9bl, + 0x09123d27fe762d10l }, + 0 }, + /* 101 << 248 */ + { { 0xffd455a7a1b7fdd6l,0xb6162cb4dabdffael,0xf859519ec89c0e56l, + 0x07406c1b421f2846l }, + { 0x42db24ed9e96ddbbl,0x03bcae092dc5da85l,0x75099cd217aa7493l, + 0x8cd1aa4266b8740dl }, + 0 }, + /* 107 << 248 */ + { { 0xe94333d5dde7fec3l,0x894fd673745a9be3l,0xaf3d97c725683748l, + 0xeaa469a2c9ec165fl }, + { 0xc9a18decdc7abd3bl,0xf059008082717b02l,0x9816374a4fdf4300l, + 0x449d3eb74fb5a6cel }, + 0 }, + /* 113 << 248 */ + { { 0x7fc983ebd28001a6l,0xeabf5276dae74b6bl,0x50adb67d742ed0a5l, + 0x1d2ad363650e1446l }, + { 0x5a564253d122f5d0l,0x7e5aefc7e30471del,0xdc64cbb3e5dc2f2cl, + 0xe645b9fa9437be4el }, + 0 }, + /* 116 << 248 */ + { { 0x0f58cec54e27d357l,0x08dcf2b70004539el,0xb1ead64104f96709l, + 0x350fed185a914c72l }, + { 0x44f43523c5147854l,0x45f8b46f46d04ac7l,0x62c306869a449d51l, + 0xaacc0f0d9e66d9a3l }, + 0 }, + /* 119 << 248 */ + { { 0x94cb62e5bdd61b63l,0xe6ce5b5104a0ec57l,0x0461cb95f0bda8a4l, + 0xca2d6220cbadfe8fl }, + { 0x6c19bdf03c1ad65el,0x774a49bae04239d5l,0xf78cb7404a2fd59dl, + 0xaebf90ed66a09130l }, + 0 }, + /* 125 << 248 */ + { { 0x10e4074857cc8d54l,0x29985831918e3cf9l,0x3d87def9f2e344eel, + 0x8899992c68977860l }, + { 0xbdc8d73b210f3c50l,0x98aa042fa9857f46l,0x76a34daf6c71357fl, + 0x086289d3200bcb6dl }, + 0 }, + }, + { + /* 0 << 256 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 256 */ + { { 0xb4e370af3aeac968l,0xe4f7fee9c4b63266l,0xb4acd4c2e3ac5664l, + 0xf8910bd2ceb38cbfl }, + { 0x1c3ae50cc9c0726el,0x15309569d97b40bfl,0x70884b7ffd5a5a1bl, + 0x3890896aef8314cdl }, + 0 }, + /* 3 << 256 */ + { { 0x996884f5903fa271l,0xe6da0fd2b9da921el,0xa6f2f2695db01e54l, + 0x1ee3e9bd6876214el }, + { 0xa26e181ce27a9497l,0x36d254e48e215e04l,0x42f32a6c252cabcal, + 0x9948148780b57614l }, + 0 }, + /* 4 << 256 */ + { { 0xab41b43a43228d83l,0x24ae1c304ad63f99l,0x8e525f1a46a51229l, + 0x14af860fcd26d2b4l }, + { 0xd6baef613f714aa1l,0xf51865adeb78795el,0xd3e21fcee6a9d694l, + 0x82ceb1dd8a37b527l }, + 0 }, + /* 5 << 256 */ + { { 0x4a665bfd2f9fd51al,0x7f2f1fe2481b97f7l,0xcad05d69ad36ce50l, + 0x314fc2a4844f4dedl }, + { 0xd5593d8cb55fc5c6l,0xe3510ce8bfb1e23dl,0xf9b7be6937453ccel, + 0xd3541b7969fae631l }, + 0 }, + /* 7 << 256 */ + { { 0x711b8a4176a9f05dl,0x06ca4e4b9011d488l,0x543bc62ba248a65el, + 0x017535ffc9290894l }, + { 0x840b84ce406851d7l,0xafa3acdf90e960b4l,0xac3394af7128fd34l, + 0x54eb4d5b2ac0f92cl }, + 0 }, + /* 9 << 256 */ + { { 0x3549a0f14df48fecl,0x6ae7b1eec239f83al,0x001dcf253eb90ff3l, + 0x02ff0f02581e90edl }, + { 0x72921d8ca103dcefl,0x2c513c3c5876293el,0xc07064ca6b68875el, + 0x7198d44653b9537cl }, + 0 }, + /* 10 << 256 */ + { { 0x58349b77685e089bl,0x1c678441219b7b8cl,0xba8da91f61e2e20dl, + 0xf9c50b8c309fd4e6l }, + { 0x99b0164996d0ef64l,0xac334ded60cdb63al,0x6b9ada19fb0bce4fl, + 0x39dc9375c7896377l }, + 0 }, + /* 11 << 256 */ + { { 0x068dda8b7e1bc126l,0x77c7c58176243a21l,0xcc8ba55c875f9dael, + 0xdde7afe2ce469f95l }, + { 0xde2a15f5e9523b85l,0x447512c6d85674ael,0x5691f89e12c6c20cl, + 0xd64ef40e0fae4513l }, + 0 }, + /* 13 << 256 */ + { { 0x10db2041c4d9eb40l,0x420eccb724f03f8al,0x64470fd17d29080el, + 0xf66c5b4416e52414l }, + { 0xa32cc70e4ca94031l,0xa67931592c8401bal,0x34f2dc29abfcc58dl, + 0x6f340f9a07325d7dl }, + 0 }, + /* 15 << 256 */ + { { 0xf55d446b060a52bbl,0x2f33cb9f02939f24l,0x0f27a01bc8953718l, + 0x362882917fcd3932l }, + { 0x7485613488ed4436l,0xcfe69e27195f089el,0xd6ab040a8ff10bd8l, + 0x9741c5472e4a1623l }, + 0 }, + /* 16 << 256 */ + { { 0xc52d8d8b6d55d6a4l,0xc4130fb3be58e8f9l,0x5f55c345e1275627l, + 0xb881a03c117042d3l }, + { 0x00a970a53238d301l,0x40d7cf2412a2c4f1l,0xace4a2f5d770ea74l, + 0x36a2e587e96940b2l }, + 0 }, + /* 17 << 256 */ + { { 0x84793d9fef12d4c8l,0x04b89b152d8a163cl,0x0fdb566fb4a87740l, + 0xf7e6e5cf9e595680l }, + { 0xbcb973e41c5cd74el,0xafcb439fe4ed49d8l,0xd5c0820aebbae8eel, + 0x23483d836f56e2a2l }, + 0 }, + /* 19 << 256 */ + { { 0x91f9b8be5e8ad115l,0xf1fd6a2e225db496l,0xf362d2cf4a444085l, + 0x033d9201eea043ebl }, + { 0x1e50c0989951a150l,0x4814fca5cfcf1f94l,0xaf3e8ef41bf82de5l, + 0xba0e2991038cff53l }, + 0 }, + /* 21 << 256 */ + { { 0x904a41ae5fc373fal,0x235556d61a6a3fc4l,0xe44eb3ea36eeb570l, + 0xa4e1b34a26ba5ca6l }, + { 0x210e7c9131180257l,0x2c28669622158b0cl,0xc78b69c783ddd341l, + 0xfc05941b294e1750l }, + 0 }, + /* 23 << 256 */ + { { 0x70666f51fc167dedl,0x47e9e289fe75b8d1l,0x8a5f59739605a03el, + 0x19876a58dd579094l }, + { 0x69a5c8cca964e426l,0xed74a652ccf20306l,0x5c93ae3cf06d31d5l, + 0x51922fa2127a8a12l }, + 0 }, + /* 25 << 256 */ + { { 0xa18e26f99e3d509el,0xbc296dd2c10814fal,0x5dadd6eeaa24e147l, + 0xdba2121a8340f12el }, + { 0xd348e7f3e245ca21l,0x1e45a42978e3eb5bl,0x252bf89c169677bbl, + 0xfb33a2564021ac55l }, + 0 }, + /* 27 << 256 */ + { { 0x30dc46586e7d72b8l,0x38df46fb0d81c3d6l,0x901bab6e10e84162l, + 0x25d7303ff7932801l }, + { 0xe781d5f37500be42l,0x9a7104c3380ff208l,0xfa801181652121a1l, + 0xef89f4f18d3bed43l }, + 0 }, + /* 28 << 256 */ + { { 0xbe4ae5683594917al,0xef7c1c47a04bf81el,0xa1dc3612046d91a0l, + 0x3eee37affb11b338l }, + { 0x7e90278fd03d8f51l,0x3045a6da4fa183c6l,0xb39e573391cd16a9l, + 0xc748a504e54e9411l }, + 0 }, + /* 29 << 256 */ + { { 0x07804331a1c6ec56l,0x25358e795b347123l,0x1ab9b39acf9432a4l, + 0x9628501d0a7881cel }, + { 0x749d58988a46d98el,0x01ea43346a17c321l,0xe2b197f9b1f9160fl, + 0x2052c7c07815f2a2l }, + 0 }, + /* 31 << 256 */ + { { 0xaa691bfbc57a1a6dl,0x06cae127d737d525l,0x5be04b2f963c7c98l, + 0x936b1f5bfc00bc4al }, + { 0x3fed4ac77eda6a34l,0xba6ca7aa2500a438l,0x1e979fa6786c2a75l, + 0xa3db26bec13f37d4l }, + 0 }, + /* 33 << 256 */ + { { 0x20afae333d7006d1l,0xdcbca6fbbda467d1l,0x2714b3827df4006cl, + 0x9abc0510c8e94549l }, + { 0x5b30a6d464c14915l,0xba91d0c35752b44fl,0x7ad9b19bbb389f1fl, + 0xe4c7aa04ef7c6e13l }, + 0 }, + /* 34 << 256 */ + { { 0x1e24a3f23d12e2b6l,0xf99df403febd6db3l,0x61e580a6b0c8e12fl, + 0x819341b7c2bfe085l }, + { 0xd53002d640828921l,0x31e1eb65cea010efl,0xc48d0cfe85b3279fl, + 0xb90de69089f35fa5l }, + 0 }, + /* 35 << 256 */ + { { 0xa3f6fd3c88ed748fl,0x6d72613af48127b9l,0xe85ed703d1e6f7e5l, + 0xbb563db449636f40l }, + { 0x23bae3c9708497bal,0x89dbff163aa65cf4l,0x70861847e6c0850al, + 0x5ef19d5d48b2e90cl }, + 0 }, + /* 36 << 256 */ + { { 0xab6a1e13107f7bacl,0x83a8bc57972091f5l,0x3c65b454f6dcba41l, + 0xd7606ff96abc431dl }, + { 0xa3af9c189bd09971l,0x6ddd3bbf276bad63l,0xd2aba9beab4f0816l, + 0x8f13063c151581edl }, + 0 }, + /* 37 << 256 */ + { { 0xf9c02364f5761b15l,0x3cfa250afd478139l,0x67d51e7416e26191l, + 0x0281bbf65eda396cl }, + { 0xbd38d4d70d1f4510l,0x2032a930edff593el,0x0ab74a0cf2ea4ad7l, + 0xb95aa9c3302498d6l }, + 0 }, + /* 39 << 256 */ + { { 0x2995495dd7da3c7cl,0x28d579d0a0bb703el,0xabec6afec8288837l, + 0x93c34dfd05ab989bl }, + { 0xcc94f05dde5ea3dfl,0xc3e3d4ef90f436e6l,0x32b3dee1cf59dc4el, + 0x5eab01635447d9d9l }, + 0 }, + /* 40 << 256 */ + { { 0xd31c5e8e2c23464el,0x5bcc382f50cfbde7l,0x6cee3d8da93c3d9bl, + 0xbee2948909ee62acl }, + { 0x4848d59c10742b84l,0x2486796fe35e9c84l,0x1a1d9570cd8f391al, + 0x839aa0913eedb743l }, + 0 }, + /* 41 << 256 */ + { { 0xae02a7ce0f83f369l,0x3b67c56097994835l,0x715def441ae4bbeal, + 0x11e764ee59f6b9eel }, + { 0x70c775051c962c3al,0x42811507d937a258l,0x06dbdceed03e6e86l, + 0x39a3a7ed48cae79el }, + 0 }, + /* 43 << 256 */ + { { 0xa32e729fb220eef8l,0x12d876baf37ac5d7l,0x9376ab45105a7f34l, + 0xb422331a4deb7275l }, + { 0x6ea07fb7686dea5el,0xba67ed3e1d8e32c9l,0x5ae52632bbc6bb9cl, + 0xdca55b86d1397575l }, + 0 }, + /* 44 << 256 */ + { { 0xd9183f74378200b1l,0xe5ea1645762f5605l,0x78b42e2f7bd6290fl, + 0xa0bdfccc07fa0899l }, + { 0x2f92ea52dacda629l,0x810b4e6c48de27e2l,0x013d8587d9d1250dl, + 0xc153d519dd5141d5l }, + 0 }, + /* 45 << 256 */ + { { 0x8f1f6cb5b8f1d719l,0xa9abc27b04e15a4el,0xc0d944a92ad42296l, + 0x69ecc877f3d2b0e5l }, + { 0xec60dbea16a5581al,0x2a0ead5fb85130d6l,0x7b3d2ebb6fddac23l, + 0x06213269ac448663l }, + 0 }, + /* 46 << 256 */ + { { 0xe1074008ac11e180l,0xdff3339c14b8f830l,0x136e22be636504f3l, + 0xb07ae98aa09c5c4cl }, + { 0x9b0a0517192168e9l,0x39e09fac86ad0865l,0x24f90705adb08d41l, + 0x9c699cc759d3be24l }, + 0 }, + /* 47 << 256 */ + { { 0xd9e16551907e36b0l,0x57f24b6caf91cb5al,0xbdb7dfdb062edae4l, + 0x99e3bffe4b85f424l }, + { 0x250774f4b2961ba7l,0xe7c0f2386d993c51l,0xcd0aae29f559b4bdl, + 0x3b12893a09a6859bl }, + 0 }, + /* 48 << 256 */ + { { 0xac177eb985ae12c3l,0x8e6cb5cc6cf76537l,0x134abb19f265f9e3l, + 0xc37309b71ba3f55dl }, + { 0x570833b4392d564bl,0xaa273a27d8c22f00l,0x9ba6b6276006773al, + 0x2156c94f0a16c092l }, + 0 }, + /* 49 << 256 */ + { { 0x2be0436b408e1258l,0xb179a2e34f47f121l,0x140b948fa42d3cfcl, + 0x96649c6700d2b4e6l }, + { 0x2bf934c7d08a4b34l,0x371c770136b472ddl,0x36297876e06adc73l, + 0x59e0d8251c3e6558l }, + 0 }, + /* 51 << 256 */ + { { 0x9368cfd304a8bc81l,0x145249d4c49e58c7l,0x8c7ac1891392be01l, + 0x58cbcb5fbc7b0903l }, + { 0x502218a1a0377b0al,0x5c17eb8afb625836l,0x845c09ef349f4d26l, + 0x15fdeb2554ddce85l }, + 0 }, + /* 52 << 256 */ + { { 0xf773535a64e8344dl,0xb8486a33d0dbabe6l,0x43c2df99b578862dl, + 0xcead29a11a39820el }, + { 0x3e5466fe63134d63l,0xc37ea88fdf43a104l,0x3b34ac34bbaacb5al, + 0x8281c240bc20be5al }, + 0 }, + /* 53 << 256 */ + { { 0x55113d5e0f8dec77l,0xdfe59f251d7e1543l,0x3b2837e0a63a849al, + 0xdfbdb8b67a5691afl }, + { 0x8dd6faf0bd4cf444l,0x28b2bdfaab128b6cl,0x44af3ee24b1098ebl, + 0xbbf328ebe50b2d02l }, + 0 }, + /* 55 << 256 */ + { { 0xf231b1f4e4e6151al,0x6ac7130413258c6al,0x6f9cb1c1a09b9f86l, + 0xbfc9291ee52ed880l }, + { 0x2a7d8230bea258a2l,0xd52a0da6baf386acl,0x5166764b3af00b7el, + 0x84792b043c985be2l }, + 0 }, + /* 57 << 256 */ + { { 0x914ca588a906d9e4l,0xb4e4e86abc27a876l,0x97e6ed27724324f2l, + 0xda7e9aa5c0b87d2cl }, + { 0xafccbe6b33a56f84l,0x69e8fd4ac892d90al,0xb47512910bb5457fl, + 0xad65e4d05cb136fal }, + 0 }, + /* 59 << 256 */ + { { 0xb09974d2fd679a1bl,0x17abc2a54578faf0l,0xe7da92828c830388l, + 0x7e455d8b0edf6146l }, + { 0xdff3b2f0c324bdb6l,0xe7a1718769f4a4f9l,0xfb4e0b3129c500a4l, + 0x1ed50799a09c5a07l }, + 0 }, + /* 60 << 256 */ + { { 0x6b669496c679d9f9l,0x3b741f36e78f0830l,0xf99d4857eb3f9e53l, + 0x41be594276f7d4ael }, + { 0x75f44d57c09a112bl,0xa5139fd68475eeb7l,0xa4560cd5c6bc9df6l, + 0x8ce2c4cf50845434l }, + 0 }, + /* 61 << 256 */ + { { 0x96b515c32b3cb0a6l,0x65836de3930d5344l,0xfb032d5b00e6d403l, + 0x2648301843c93bd1l }, + { 0xfc4525dd4b572363l,0x12b7923e7b28ab5cl,0xf376b633e22ac5e6l, + 0xd6ff6582e30b4707l }, + 0 }, + /* 63 << 256 */ + { { 0x8bdce75c83b09e07l,0x64228b19227717c4l,0xeae8f8a2dc6a1f02l, + 0x1081031be72f3b6dl }, + { 0xba0f876072c3f736l,0xde38a0c5246a28adl,0x0b116fe08596c412l, + 0xb9e37be3fa135d11l }, + 0 }, + /* 64 << 256 */ + { { 0x09800dc1b48d4168l,0xa740b282bfee87a2l,0x80c6b75dc94a547al, + 0x8cb622f0099c1985l }, + { 0xe6c789631467e05dl,0x027b658822fd3064l,0xe14735e2c2fdb68cl, + 0xfd2869947d853158l }, + 0 }, + /* 65 << 256 */ + { { 0x301916a5bbd7caf1l,0xef563fda4e2076c2l,0xccbc56088467f279l, + 0xd7de3088b8d0f1bfl }, + { 0x3d9adcce8586910dl,0x3fa3b8b9d775e0e9l,0x4b7a4a1d88136503l, + 0xc748656de4994fcel }, + 0 }, + /* 71 << 256 */ + { { 0x18cc605c2d9f8646l,0x3764f1c29e441b64l,0xb0ea7f7fc4b64ee3l, + 0xb5c22d0c042f8678l }, + { 0x3761f7f89b3057fdl,0xc85b8de64a207ce4l,0x11da715bc5c04cf7l, + 0x0cb1fa77c8e99c1fl }, + 0 }, + /* 77 << 256 */ + { { 0x35f9cfc8045dab4el,0x08a65c6771a7d720l,0xf076767b8eef1351l, + 0x5351dbff8638fbe5l }, + { 0x5aead6f7772ad54cl,0x5f6b441fafe93e69l,0xb7b83d1aeeb876b5l, + 0xbe1ba4a7cdc094d9l }, + 0 }, + /* 83 << 256 */ + { { 0x005d8f04ec0377bal,0x036b8e1ace58f05dl,0xdd6ffc6f1b28cf58l, + 0xc3d95a58e206189fl }, + { 0xcb2873c1f52e8b8cl,0xcffdb18d80142af1l,0x7cf88eb64c77ed78l, + 0xb3a3141981ef2c12l }, + 0 }, + /* 89 << 256 */ + { { 0xbb17e6f957c175b1l,0xf33abc63260a6f6dl,0x9435f2de620ddd6bl, + 0x90bdde59ff3e99eal }, + { 0x3d7875e0567b520fl,0xdd6954aa813b4978l,0x1af3dc24de7b631cl, + 0x82ddcd08934d3c97l }, + 0 }, + /* 95 << 256 */ + { { 0x7a9d60affc5ce598l,0xc6f507597c37abfdl,0xaa1b32f3a79355d0l, + 0xac581b94d7e4fcf3l }, + { 0x2669cefd139f6466l,0x560a98bb26f97570l,0x32e1c1db2837b908l, + 0x7823d7922d252781l }, + 0 }, + /* 101 << 256 */ + { { 0xea018b4cdedf9af0l,0x4b64c0a380c1d2f9l,0x527a0b1c36992c44l, + 0x72a2408142b7adffl }, + { 0x0023d10f97a502eel,0xc0f9ed067b401ac4l,0xabd1bd03d6d3b516l, + 0xc320e3e478c5d0bel }, + 0 }, + /* 107 << 256 */ + { { 0x9f5d2a6a37dd009cl,0x88c0f42ac2c3cbacl,0x3155636977552a1el, + 0xe78ec89d02f8098fl }, + { 0x276c2ad71b6eeff9l,0xf4c49a28f7f91856l,0x698a2368dc795124l, + 0x5502810de92a6c0fl }, + 0 }, + /* 113 << 256 */ + { { 0x82a5042e9f5e5192l,0x64da65fac0965a88l,0xf4c80dd56668399el, + 0x635323757e33c233l }, + { 0x5e5339b1a0048616l,0x4a17b1931c91741fl,0x65fdc7c213dcf3d0l, + 0x230181426d10c410l }, + 0 }, + /* 116 << 256 */ + { { 0x090a04220f46c635l,0xc7eac842a04de3f5l,0x45b69d4c8990d4b2l, + 0x032aeb50b8e0cdc6l }, + { 0x02ce332a4ee3f307l,0x3c80c1545043980fl,0xc774838bcbd5287cl, + 0x052661074a37d0ael }, + 0 }, + /* 119 << 256 */ + { { 0xc401b9c0f4d70fbfl,0xf82bbfde98ee47fel,0x94965118c84d91afl, + 0xdd9a67c4d3b6ad1dl }, + { 0x85c9cf1eb66a3ad4l,0x05580a0fbf5f514cl,0xf3ef0fd00218536el, + 0x1dc2cf2bd14a7ca9l }, + 0 }, + /* 125 << 256 */ + { { 0x18c83e337c1e24d4l,0x30911165563657c6l,0xf9be1af679e53083l, + 0x9b058059637753cel }, + { 0x6a37fa24e54522b9l,0xc11d38b426dbf4c4l,0xbc6738655ebd4d9al, + 0x2b40e9427fd4e2ecl }, + 0 }, + }, +}; + +/* Structure used to describe recoding of scalar multiplication. */ +typedef struct ecc_recode_sum { + /* Index into pre-computation table. */ + uint8_t i; + /* Multiplier to add point into. */ + uint8_t mul; + /* Use the negative of the point. */ + uint8_t neg; +} ecc_recode_sum; + +/* The index into pre-computation table to use. */ +static uint8_t recode_index_4_8[258] = { + 0, 1, 1, 1, 3, 4, 2, 5, 3, 2, 4, 8, 3, 9, 5, 4, + 11, 12, 6, 13, 7, 5, 8, 15, 55, 16, 9, 6, 18, 19, 7, 20, + 11, 8, 12, 23, 24, 25, 13, 9, 27, 28, 14, 29, 30, 10, 15, 33, + 11, 35, 16, 12, 37, 38, 17, 39, 18, 13, 19, 41, 42, 43, 20, 14, + 45, 46, 21, 44, 22, 15, 23, 47, 24, 43, 25, 16, 42, 48, 26, 41, + 27, 17, 28, 49, 18, 40, 29, 19, 30, 50, 31, 39, 32, 20, 33, 51, + 34, 38, 35, 21, 37, 52, 22, 36, 37, 23, 38, 53, 24, 35, 39, 25, + 34, 54, 40, 33, 55, 26, 32, 56, 27, 31, 43, 28, 30, 57, 44, 29, + 45, 29, 44, 57, 30, 28, 43, 31, 27, 56, 32, 26, 55, 33, 40, 54, + 34, 25, 39, 35, 24, 53, 38, 23, 37, 36, 22, 52, 37, 21, 35, 38, + 34, 51, 33, 20, 32, 39, 31, 50, 30, 19, 29, 40, 18, 49, 28, 17, + 27, 41, 26, 48, 42, 16, 25, 43, 24, 47, 23, 15, 22, 44, 21, 46, + 45, 14, 20, 43, 42, 41, 19, 13, 18, 39, 17, 38, 37, 12, 16, 35, + 11, 33, 15, 10, 30, 29, 14, 28, 27, 9, 13, 25, 24, 23, 12, 8, + 11, 20, 7, 19, 18, 6, 9, 16, 55, 15, 8, 5, 7, 13, 6, 12, + 11, 4, 5, 9, 3, 8, 4, 2, 3, 5, 2, 4, 3, 1, 1, 1, + 0, 1, +}; + +/* Multiple to add point into. */ +static uint8_t recode_mul_4_8[258] = { + 0, 1, 2, 3, 1, 1, 2, 1, 2, 3, 2, 1, 3, 1, 2, 3, + 1, 1, 2, 1, 2, 3, 2, 1, 2, 1, 2, 3, 1, 1, 3, 1, + 2, 3, 2, 1, 1, 1, 2, 3, 1, 1, 2, 1, 1, 3, 2, 1, + 3, 1, 2, 3, 1, 1, 2, 1, 2, 3, 2, 1, 1, 1, 2, 3, + 1, 1, 2, 3, 2, 3, 2, 1, 2, 3, 2, 3, 3, 1, 2, 3, + 2, 3, 2, 1, 3, 3, 2, 3, 2, 1, 2, 3, 2, 3, 2, 1, + 2, 3, 2, 3, 3, 1, 3, 3, 2, 3, 2, 1, 3, 3, 2, 3, + 3, 1, 2, 3, 1, 3, 3, 1, 3, 3, 2, 3, 3, 1, 2, 3, + 2, 3, 2, 1, 3, 3, 2, 3, 3, 1, 3, 3, 1, 3, 2, 1, + 3, 3, 2, 3, 3, 1, 2, 3, 2, 3, 3, 1, 3, 3, 2, 3, + 2, 1, 2, 3, 2, 3, 2, 1, 2, 3, 2, 3, 3, 1, 2, 3, + 2, 3, 2, 1, 3, 3, 2, 3, 2, 1, 2, 3, 2, 3, 2, 1, + 1, 3, 2, 1, 1, 1, 2, 3, 2, 1, 2, 1, 1, 3, 2, 1, + 3, 1, 2, 3, 1, 1, 2, 1, 1, 3, 2, 1, 1, 1, 2, 3, + 2, 1, 3, 1, 1, 3, 2, 1, 2, 1, 2, 3, 2, 1, 2, 1, + 1, 3, 2, 1, 3, 1, 2, 3, 2, 1, 2, 1, 1, 3, 2, 1, + 0, 1, +}; + +/* Whether to negate y-ordinate. */ +static uint8_t recode_neg_4_8[258] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, + 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, + 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, + 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, + 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, +}; + +/* Recode the scalar for multiplication using pre-computed values, multipliers + * and subtraction. + * + * k Scalar to multiply by. + * v Vector of operations to peform. + */ +static void sp_256_ecc_recode_sum_8_4(sp_digit* k, ecc_recode_sum* v) +{ + int i, j; + uint16_t y; + int carry = 0; + int o; + sp_digit n; + + j = 0; + n = k[j]; + o = 0; + for (i=0; i<33; i++) { + y = n; + if (o + 8 < 64) { + y &= 0xff; + n >>= 8; + o += 8; + } + else if (o + 8 == 64) { + n >>= 8; + if (++j < 4) + n = k[j]; + o = 0; + } + else if (++j < 4) { + n = k[j]; + y |= (n << (64 - o)) & 0xff; + o -= 56; + n >>= o; + } + + y += carry; + v[i].i = recode_index_4_8[y]; + v[i].mul = recode_mul_4_8[y]; + v[i].neg = recode_neg_4_8[y]; + carry = (y >> 8) + v[i].neg; + } +} + +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_base_4(sp_point* r, sp_digit* k, int map, + void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point td[4]; + sp_point pd; + sp_digit tmpd[2 * 4 * 5]; +#endif + sp_point* t; + sp_point* p; + sp_digit* tmp; + sp_digit* negy; + int i; + ecc_recode_sum v[33]; + int err; + + (void)heap; + + err = sp_ecc_point_new(heap, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + t = (sp_point*)XMALLOC(sizeof(sp_point) * 4, heap, DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 5, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; +#else + t = td; + tmp = tmpd; +#endif + negy = tmp; + + if (err == MP_OKAY) { + sp_256_ecc_recode_sum_8_4(k, v); + + XMEMCPY(p->z, p256_norm_mod, sizeof(p256_norm_mod)); + XMEMSET(t, 0, sizeof(sp_point) * 4); + for (i=0; i<4; i++) { + XMEMCPY(t[i].z, p256_norm_mod, sizeof(p256_norm_mod)); + t[i].infinity = 1; + } + + i = 32; + XMEMCPY(t[v[i].mul].x, p256_table[i][v[i].i].x, + sizeof(p256_table[i]->x)); + XMEMCPY(t[v[i].mul].y, p256_table[i][v[i].i].y, + sizeof(p256_table[i]->y)); + t[v[i].mul].infinity = p256_table[i][v[i].i].infinity; + for (--i; i>=0; i--) { + XMEMCPY(p->x, p256_table[i][v[i].i].x, sizeof(p256_table[i]->x)); + XMEMCPY(p->y, p256_table[i][v[i].i].y, sizeof(p256_table[i]->y)); + p->infinity = p256_table[i][v[i].i].infinity; + sp_256_sub_4(negy, p256_mod, p->y); + sp_256_cond_copy_4(p->y, negy, (sp_digit)0 - v[i].neg); + sp_256_proj_point_add_qz1_4(&t[v[i].mul], &t[v[i].mul], p, + tmp); + } + sp_256_proj_point_add_4(&t[2], &t[2], &t[3], tmp); + sp_256_proj_point_add_4(&t[1], &t[1], &t[3], tmp); + sp_256_proj_point_dbl_4(&t[2], &t[2], tmp); + sp_256_proj_point_add_4(&t[1], &t[1], &t[2], tmp); + + if (map) + sp_256_map_4(r, &t[1], tmp); + else + XMEMCPY(r, &t[1], sizeof(sp_point)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_point) * 4); + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } + if (tmp != NULL) { + XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 4 * 5); + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + } +#else + ForceZero(tmpd, sizeof(tmpd)); + ForceZero(td, sizeof(td)); +#endif + sp_ecc_point_free(p, 0, heap); + + return MP_OKAY; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * km Scalar to multiply by. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_base_256(mp_int* km, ecc_point* r, int map, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point p; + sp_digit kd[4]; +#endif + sp_point* point; + sp_digit* k = NULL; + int err = MP_OKAY; + + err = sp_ecc_point_new(heap, p, point); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + if (err == MP_OKAY) { + sp_256_from_mp(k, 4, km); + + err = sp_256_ecc_mulmod_base_4(point, k, map, heap); + } + if (err == MP_OKAY) + err = sp_256_point_to_ecc_point_4(point, r); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(point, 0, heap); + + return err; +} + +#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ + defined(HAVE_ECC_VERIFY) +/* Returns 1 if the number of zero. + * Implementation is constant time. + * + * a Number to check. + * returns 1 if the number is zero and 0 otherwise. + */ +static int sp_256_iszero_4(const sp_digit* a) +{ + return (a[0] | a[1] | a[2] | a[3]) == 0; +} + +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN || HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +/* Add 1 to a. (a = a + 1) + * + * a A single precision integer. + */ +static void sp_256_add_one_4(sp_digit* a) +{ + __asm__ __volatile__ ( + "ldp x1, x2, [%[a], 0]\n\t" + "ldp x3, x4, [%[a], 16]\n\t" + "adds x1, x1, #1\n\t" + "adcs x2, x2, xzr\n\t" + "adcs x3, x3, xzr\n\t" + "adcs x4, x4, xzr\n\t" + "stp x1, x2, [%[a], 0]\n\t" + "stp x3, x4, [%[a], 16]\n\t" + : + : [a] "r" (a) + : "memory", "x1", "x2", "x3", "x4" + ); +} + +/* Read big endian unsigned byte aray into r. + * + * r A single precision integer. + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_256_from_bin(sp_digit* r, int max, const byte* a, int n) +{ + int i, j = 0, s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= ((sp_digit)a[i]) << s; + if (s >= 56) { + r[j] &= 0xffffffffffffffffl; + s = 64 - s; + if (j + 1 >= max) + break; + r[++j] = a[i] >> s; + s = 8 - s; + } + else + s += 8; + } + + for (j++; j < max; j++) + r[j] = 0; +} + +/* Generates a scalar that is in the range 1..order-1. + * + * rng Random number generator. + * k Scalar value. + * returns RNG failures, MEMORY_E when memory allocation fails and + * MP_OKAY on success. + */ +static int sp_256_ecc_gen_k_4(WC_RNG* rng, sp_digit* k) +{ + int err; + byte buf[32]; + + do { + err = wc_RNG_GenerateBlock(rng, buf, sizeof(buf)); + if (err == 0) { + sp_256_from_bin(k, 4, buf, sizeof(buf)); + if (sp_256_cmp_4(k, p256_order2) < 0) { + sp_256_add_one_4(k); + break; + } + } + } + while (err == 0); + + return err; +} + +/* Makes a random EC key pair. + * + * rng Random number generator. + * priv Generated private value. + * pub Generated public point. + * heap Heap to use for allocation. + * returns ECC_INF_E when the point does not have the correct order, RNG + * failures, MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point p; + sp_digit kd[4]; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point inf; +#endif +#endif + sp_point* point; + sp_digit* k = NULL; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point* infinity; +#endif + int err; + + (void)heap; + + err = sp_ecc_point_new(heap, p, point); +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, inf, infinity); +#endif +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + + if (err == MP_OKAY) + err = sp_256_ecc_gen_k_4(rng, k); + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_base_4(point, k, 1, NULL); + } + +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_4(infinity, point, p256_order, 1, NULL); + } + if (err == MP_OKAY) { + if (!sp_256_iszero_4(point->x) || !sp_256_iszero_4(point->y)) + err = ECC_INF_E; + } +#endif + + if (err == MP_OKAY) + err = sp_256_to_mp(k, priv); + if (err == MP_OKAY) + err = sp_256_point_to_ecc_point_4(point, pub); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); +#endif +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_ecc_point_free(infinity, 1, heap); +#endif + sp_ecc_point_free(point, 1, heap); + + return err; +} + +#ifdef HAVE_ECC_DHE +/* Write r as big endian to byte aray. + * Fixed length number of bytes written: 32 + * + * r A single precision integer. + * a Byte array. + */ +static void sp_256_to_bin(sp_digit* r, byte* a) +{ + int i, j, s = 0, b; + + j = 256 / 8 - 1; + a[j] = 0; + for (i=0; i<4 && j>=0; i++) { + b = 0; + a[j--] |= r[i] << s; b += 8 - s; + if (j < 0) + break; + while (b < 64) { + a[j--] = r[i] >> b; b += 8; + if (j < 0) + break; + } + s = 8 - (b - 64); + if (j >= 0) + a[j] = 0; + if (s != 0) + j++; + } +} + +/* Multiply the point by the scalar and serialize the X ordinate. + * The number is 0 padded to maximum size on output. + * + * priv Scalar to multiply the point by. + * pub Point to multiply. + * out Buffer to hold X ordinate. + * outLen On entry, size of the buffer in bytes. + * On exit, length of data in buffer in bytes. + * heap Heap to use for allocation. + * returns BUFFER_E if the buffer is to small for output size, + * MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_secret_gen_256(mp_int* priv, ecc_point* pub, byte* out, + word32* outLen, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point p; + sp_digit kd[4]; +#endif + sp_point* point = NULL; + sp_digit* k = NULL; + int err = MP_OKAY; + + if (*outLen < 32) + err = BUFFER_E; + + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, p, point); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(k, 4, priv); + sp_256_point_from_ecc_point_4(point, pub); + err = sp_256_ecc_mulmod_4(point, point, k, 1, heap); + } + if (err == MP_OKAY) { + sp_256_to_bin(point->x, out); + *outLen = 32; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(point, 0, heap); + + return err; +} +#endif /* HAVE_ECC_DHE */ + +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static sp_digit sp_256_add_4(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldp x3, x4, [%[a], 0]\n\t" + "ldp x5, x6, [%[a], 16]\n\t" + "ldp x7, x8, [%[b], 0]\n\t" + "ldp x9, x10, [%[b], 16]\n\t" + "adds x3, x3, x7\n\t" + "adcs x4, x4, x8\n\t" + "adcs x5, x5, x9\n\t" + "adcs x6, x6, x10\n\t" + "stp x3, x4, [%[r], 0]\n\t" + "stp x5, x6, [%[r], 16]\n\t" + "cset %[c], cs\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10" + ); + + return c; +} + +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +#ifdef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_256_mul_4(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + sp_digit tmp[8]; + + __asm__ __volatile__ ( + "mov x5, 0\n\t" + "mov x6, 0\n\t" + "mov x7, 0\n\t" + "mov x8, 0\n\t" + "\n1:\n\t" + "subs x3, x5, 24\n\t" + "csel x3, xzr, x3, cc\n\t" + "sub x4, x5, x3\n\t" + "\n2:\n\t" + "ldr x10, [%[a], x3]\n\t" + "ldr x11, [%[b], x4]\n\t" + "mul x9, x10, x11\n\t" + "umulh x10, x10, x11\n\t" + "adds x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x8, x8, xzr\n\t" + "add x3, x3, #8\n\t" + "sub x4, x4, #8\n\t" + "cmp x3, 32\n\t" + "b.eq 3f\n\t" + "cmp x3, x5\n\t" + "b.le 2b\n\t" + "\n3:\n\t" + "str x6, [%[r], x5]\n\t" + "mov x6, x7\n\t" + "mov x7, x8\n\t" + "mov x8, #0\n\t" + "add x5, x5, #8\n\t" + "cmp x5, 48\n\t" + "b.le 1b\n\t" + "str x6, [%[r], x5]\n\t" + : + : [r] "r" (tmp), [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +#else +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +static void sp_256_mul_4(sp_digit* r, const sp_digit* a, const sp_digit* b) +{ + sp_digit tmp[4]; + + __asm__ __volatile__ ( + "ldp x8, x9, [%[a], 0]\n\t" + "ldp x10, x11, [%[a], 16]\n\t" + "ldp x12, x13, [%[b], 0]\n\t" + "ldp x14, x15, [%[b], 16]\n\t" + "# A[0] * B[0]\n\t" + "mul x3, x8, x12\n\t" + "umulh x4, x8, x12\n\t" + "str x3, [%[tmp]]\n\t" + "# A[0] * B[1]\n\t" + "mul x6, x8, x13\n\t" + "umulh x7, x8, x13\n\t" + "adds x4, x4, x6\n\t" + "adc x5, xzr, x7\n\t" + "# A[1] * B[0]\n\t" + "mul x6, x9, x12\n\t" + "umulh x7, x9, x12\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "str x4, [%[tmp], 8]\n\t" + "# A[0] * B[2]\n\t" + "mul x6, x8, x14\n\t" + "umulh x7, x8, x14\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, xzr, xzr\n\t" + "# A[1] * B[1]\n\t" + "mul x6, x9, x13\n\t" + "umulh x7, x9, x13\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "# A[2] * B[0]\n\t" + "mul x6, x10, x12\n\t" + "umulh x7, x10, x12\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "str x5, [%[tmp], 16]\n\t" + "# A[0] * B[3]\n\t" + "mul x6, x8, x15\n\t" + "umulh x7, x8, x15\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, xzr, xzr\n\t" + "# A[1] * B[2]\n\t" + "mul x6, x9, x14\n\t" + "umulh x7, x9, x14\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "# A[2] * B[1]\n\t" + "mul x6, x10, x13\n\t" + "umulh x7, x10, x13\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "# A[3] * B[0]\n\t" + "mul x6, x11, x12\n\t" + "umulh x7, x11, x12\n\t" + "adds x3, x3, x6\n\t" + "adcs x4, x4, x7\n\t" + "adc x5, x5, xzr\n\t" + "str x3, [%[tmp], 24]\n\t" + "# A[1] * B[3]\n\t" + "mul x6, x9, x15\n\t" + "umulh x7, x9, x15\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "# A[2] * B[2]\n\t" + "mul x6, x10, x14\n\t" + "umulh x7, x10, x14\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "# A[3] * B[1]\n\t" + "mul x6, x11, x13\n\t" + "umulh x7, x11, x13\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, x3, xzr\n\t" + "str x4, [%[r], 32]\n\t" + "# A[2] * B[3]\n\t" + "mul x6, x10, x15\n\t" + "umulh x7, x10, x15\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, xzr, xzr\n\t" + "# A[3] * B[2]\n\t" + "mul x6, x11, x14\n\t" + "umulh x7, x11, x14\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, x4, xzr\n\t" + "str x5, [%[r], 40]\n\t" + "# A[3] * B[3]\n\t" + "mul x6, x11, x15\n\t" + "umulh x7, x11, x15\n\t" + "adds x3, x3, x6\n\t" + "adc x4, x4, x7\n\t" + "stp x3, x4, [%[r], 48]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [tmp] "r" (tmp) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +#endif /* WOLFSSL_SP_SMALL */ +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +/* Sub b from a into a. (a -= b) + * + * a A single precision integer and result. + * b A single precision integer. + */ +static sp_digit sp_256_sub_in_place_4(sp_digit* a, const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldp x2, x3, [%[a], 0]\n\t" + "ldp x4, x5, [%[a], 16]\n\t" + "ldp x6, x7, [%[b], 0]\n\t" + "ldp x8, x9, [%[b], 16]\n\t" + "subs x2, x2, x6\n\t" + "sbcs x3, x3, x7\n\t" + "sbcs x4, x4, x8\n\t" + "sbcs x5, x5, x9\n\t" + "stp x2, x3, [%[a], 0]\n\t" + "stp x4, x5, [%[a], 16]\n\t" + "csetm %[c], cc\n\t" + : [c] "+r" (c) + : [a] "r" (a), [b] "r" (b) + : "memory", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9" + ); + + return c; +} + +/* Mul a by digit b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision digit. + */ +static void sp_256_mul_d_4(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ + __asm__ __volatile__ ( + "# A[0] * B\n\t" + "ldr x8, [%[a]]\n\t" + "mul x3, %[b], x8\n\t" + "umulh x4, %[b], x8\n\t" + "mov x5, 0\n\t" + "str x3, [%[r]]\n\t" + "# A[1] * B\n\t" + "ldr x8, [%[a], 8]\n\t" + "mov x3, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x4, x4, x6\n\t" + "adcs x5, x5, x7\n\t" + "adc x3, xzr, xzr\n\t" + "str x4, [%[r], 8]\n\t" + "# A[2] * B\n\t" + "ldr x8, [%[a], 16]\n\t" + "mov x4, 0\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x5, x5, x6\n\t" + "adcs x3, x3, x7\n\t" + "adc x4, xzr, xzr\n\t" + "str x5, [%[r], 16]\n\t" + "# A[3] * B\n\t" + "ldr x8, [%[a], 24]\n\t" + "mul x6, %[b], x8\n\t" + "umulh x7, %[b], x8\n\t" + "adds x3, x3, x6\n\t" + "adc x4, x4, x7\n\t" + "str x3, [%[r], 24]\n\t" + "str x4, [%[r], 32]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8" + ); +} + +/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) + * + * d1 The high order half of the number to divide. + * d0 The low order half of the number to divide. + * div The dividend. + * returns the result of the division. + */ +static sp_digit div_256_word_4(sp_digit d1, sp_digit d0, sp_digit div) +{ + sp_digit r; + + __asm__ __volatile__ ( + "lsr x5, %[div], 32\n\t" + "add x5, x5, 1\n\t" + + "udiv x3, %[d1], x5\n\t" + "lsl x6, x3, 32\n\t" + "mul x4, %[div], x6\n\t" + "umulh x3, %[div], x6\n\t" + "subs %[d0], %[d0], x4\n\t" + "sbc %[d1], %[d1], x3\n\t" + + "udiv x3, %[d1], x5\n\t" + "lsl x3, x3, 32\n\t" + "add x6, x6, x3\n\t" + "mul x4, %[div], x3\n\t" + "umulh x3, %[div], x3\n\t" + "subs %[d0], %[d0], x4\n\t" + "sbc %[d1], %[d1], x3\n\t" + + "lsl x3, %[d1], 32\n\t" + "orr x3, x3, %[d0], lsr 32\n\t" + + "udiv x3, x3, x5\n\t" + "add x6, x6, x3\n\t" + "mul x4, %[div], x3\n\t" + "umulh x3, %[div], x3\n\t" + "subs %[d0], %[d0], x4\n\t" + "sbc %[d1], %[d1], x3\n\t" + + "lsl x3, %[d1], 32\n\t" + "orr x3, x3, %[d0], lsr 32\n\t" + + "udiv x3, x3, x5\n\t" + "add x6, x6, x3\n\t" + "mul x4, %[div], x3\n\t" + "umulh x3, %[div], x3\n\t" + "subs %[d0], %[d0], x4\n\t" + "sbc %[d1], %[d1], x3\n\t" + + "udiv x3, %[d0], %[div]\n\t" + "add x6, x6, x3\n\t" + "mul x3, %[div], x3\n\t" + "sub %[d0], %[d0], x3\n\t" + "mov %[r], x6\n\t" + + : [r] "=r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "x3", "x4", "x5", "x6" + ); + + return r; +} + +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_256_mask_4(sp_digit* r, sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<4; i++) + r[i] = a[i] & m; +#else + r[0] = a[0] & m; + r[1] = a[1] & m; + r[2] = a[2] & m; + r[3] = a[3] & m; +#endif +} + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_256_div_4(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[8], t2[5]; + sp_digit div, r1; + int i; + + (void)m; + + div = d[3]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 4); + for (i=3; i>=0; i--) { + r1 = div_256_word_4(t1[4 + i], t1[4 + i - 1], div); + + sp_256_mul_d_4(t2, d, r1); + t1[4 + i] += sp_256_sub_in_place_4(&t1[i], t2); + t1[4 + i] -= t2[4]; + sp_256_mask_4(t2, d, t1[4 + i]); + t1[4 + i] += sp_256_add_4(&t1[i], &t1[i], t2); + sp_256_mask_4(t2, d, t1[4 + i]); + t1[4 + i] += sp_256_add_4(&t1[i], &t1[i], t2); + } + + r1 = sp_256_cmp_4(t1, d) >= 0; + sp_256_cond_sub_4(r, t1, d, (sp_digit)0 - r1); + + return MP_OKAY; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_256_mod_4(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_256_div_4(a, m, NULL, r); +} + +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +#ifdef WOLFSSL_SP_SMALL +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_256_sqr_4(sp_digit* r, const sp_digit* a) +{ + sp_digit tmp[8]; + + __asm__ __volatile__ ( + "mov x6, 0\n\t" + "mov x7, 0\n\t" + "mov x8, 0\n\t" + "mov x5, 0\n\t" + "\n1:\n\t" + "subs x3, x5, 24\n\t" + "csel x3, xzr, x3, cc\n\t" + "sub x4, x5, x3\n\t" + "\n2:\n\t" + "cmp x4, x3\n\t" + "b.eq 4f\n\t" + "ldr x10, [%[a], x3]\n\t" + "ldr x11, [%[a], x4]\n\t" + "mul x9, x10, x11\n\t" + "umulh x10, x10, x11\n\t" + "adds x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x8, x8, xzr\n\t" + "adds x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x8, x8, xzr\n\t" + "b.al 5f\n\t" + "\n4:\n\t" + "ldr x10, [%[a], x3]\n\t" + "mul x9, x10, x10\n\t" + "umulh x10, x10, x10\n\t" + "adds x6, x6, x9\n\t" + "adcs x7, x7, x10\n\t" + "adc x8, x8, xzr\n\t" + "\n5:\n\t" + "add x3, x3, #8\n\t" + "sub x4, x4, #8\n\t" + "cmp x3, 32\n\t" + "b.eq 3f\n\t" + "cmp x3, x4\n\t" + "b.gt 3f\n\t" + "cmp x3, x5\n\t" + "b.le 2b\n\t" + "\n3:\n\t" + "str x6, [%[r], x5]\n\t" + "mov x6, x7\n\t" + "mov x7, x8\n\t" + "mov x8, #0\n\t" + "add x5, x5, #8\n\t" + "cmp x5, 48\n\t" + "b.le 1b\n\t" + "str x6, [%[r], x5]\n\t" + : + : [r] "r" (tmp), [a] "r" (a) + : "memory", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +#else +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +static void sp_256_sqr_4(sp_digit* r, const sp_digit* a) +{ + sp_digit tmp[4]; + + __asm__ __volatile__ ( + "ldp x10, x11, [%[a], 0]\n\t" + "ldp x12, x13, [%[a], 16]\n\t" + "# A[0] * A[0]\n\t" + "mul x2, x10, x10\n\t" + "umulh x3, x10, x10\n\t" + "str x2, [%[tmp]]\n\t" + "mov x4, 0\n\t" + "# A[0] * A[1]\n\t" + "mul x8, x10, x11\n\t" + "umulh x9, x10, x11\n\t" + "adds x3, x3, x8\n\t" + "adcs x4, x4, x9\n\t" + "adc x2, xzr, xzr\n\t" + "adds x3, x3, x8\n\t" + "adcs x4, x4, x9\n\t" + "adc x2, x2, xzr\n\t" + "str x3, [%[tmp], 8]\n\t" + "# A[0] * A[2]\n\t" + "mul x8, x10, x12\n\t" + "umulh x9, x10, x12\n\t" + "adds x4, x4, x8\n\t" + "adcs x2, x2, x9\n\t" + "adc x3, xzr, xzr\n\t" + "adds x4, x4, x8\n\t" + "adcs x2, x2, x9\n\t" + "adc x3, x3, xzr\n\t" + "# A[1] * A[1]\n\t" + "mul x8, x11, x11\n\t" + "umulh x9, x11, x11\n\t" + "adds x4, x4, x8\n\t" + "adcs x2, x2, x9\n\t" + "adc x3, x3, xzr\n\t" + "str x4, [%[tmp], 16]\n\t" + "# A[0] * A[3]\n\t" + "mul x8, x10, x13\n\t" + "umulh x9, x10, x13\n\t" + "adds x2, x2, x8\n\t" + "adcs x3, x3, x9\n\t" + "adc x4, xzr, xzr\n\t" + "adds x2, x2, x8\n\t" + "adcs x3, x3, x9\n\t" + "adc x4, x4, xzr\n\t" + "# A[1] * A[2]\n\t" + "mul x8, x11, x12\n\t" + "umulh x9, x11, x12\n\t" + "adds x2, x2, x8\n\t" + "adcs x3, x3, x9\n\t" + "adc x4, x4, xzr\n\t" + "adds x2, x2, x8\n\t" + "adcs x3, x3, x9\n\t" + "adc x4, x4, xzr\n\t" + "str x2, [%[tmp], 24]\n\t" + "# A[1] * A[3]\n\t" + "mul x8, x11, x13\n\t" + "umulh x9, x11, x13\n\t" + "adds x3, x3, x8\n\t" + "adcs x4, x4, x9\n\t" + "adc x2, xzr, xzr\n\t" + "adds x3, x3, x8\n\t" + "adcs x4, x4, x9\n\t" + "adc x2, x2, xzr\n\t" + "# A[2] * A[2]\n\t" + "mul x8, x12, x12\n\t" + "umulh x9, x12, x12\n\t" + "adds x3, x3, x8\n\t" + "adcs x4, x4, x9\n\t" + "adc x2, x2, xzr\n\t" + "str x3, [%[r], 32]\n\t" + "# A[2] * A[3]\n\t" + "mul x8, x12, x13\n\t" + "umulh x9, x12, x13\n\t" + "adds x4, x4, x8\n\t" + "adcs x2, x2, x9\n\t" + "adc x3, xzr, xzr\n\t" + "adds x4, x4, x8\n\t" + "adcs x2, x2, x9\n\t" + "adc x3, x3, xzr\n\t" + "str x4, [%[r], 40]\n\t" + "# A[3] * A[3]\n\t" + "mul x8, x13, x13\n\t" + "umulh x9, x13, x13\n\t" + "adds x2, x2, x8\n\t" + "adc x3, x3, x9\n\t" + "stp x2, x3, [%[r], 48]\n\t" + : + : [r] "r" (r), [a] "r" (a), [tmp] "r" (tmp) + : "memory", "x2", "x3", "x4", "x8", "x9", "x10", "x5", "x6", "x7", "x10", "x11", "x12", "x13" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Order-2 for the P256 curve. */ +static const uint64_t p256_order_2[4] = { + 0xf3b9cac2fc63254f,0xbce6faada7179e84,0xffffffffffffffff, + 0xffffffff00000000 +}; +#else +/* The low half of the order-2 of the P256 curve. */ +static const uint64_t p256_order_low[2] = { + 0xf3b9cac2fc63254f,0xbce6faada7179e84 +}; +#endif /* WOLFSSL_SP_SMALL */ + +/* Multiply two number mod the order of P256 curve. (r = a * b mod order) + * + * r Result of the multiplication. + * a First operand of the multiplication. + * b Second operand of the multiplication. + */ +static void sp_256_mont_mul_order_4(sp_digit* r, sp_digit* a, sp_digit* b) +{ + sp_256_mul_4(r, a, b); + sp_256_mont_reduce_order_4(r, p256_order, p256_mp_order); +} + +/* Square number mod the order of P256 curve. (r = a * a mod order) + * + * r Result of the squaring. + * a Number to square. + */ +static void sp_256_mont_sqr_order_4(sp_digit* r, sp_digit* a) +{ + sp_256_sqr_4(r, a); + sp_256_mont_reduce_order_4(r, p256_order, p256_mp_order); +} + +#ifndef WOLFSSL_SP_SMALL +/* Square number mod the order of P256 curve a number of times. + * (r = a ^ n mod order) + * + * r Result of the squaring. + * a Number to square. + */ +static void sp_256_mont_sqr_n_order_4(sp_digit* r, sp_digit* a, int n) +{ + int i; + + sp_256_mont_sqr_order_4(r, a); + for (i=1; i=0; i--) { + sp_256_mont_sqr_order_4(t, t); + if (p256_order_2[i / 64] & ((sp_digit)1 << (i % 64))) + sp_256_mont_mul_order_4(t, t, a); + } + XMEMCPY(r, t, sizeof(sp_digit) * 4); +#else + sp_digit* t = td; + sp_digit* t2 = td + 2 * 4; + sp_digit* t3 = td + 4 * 4; + int i; + + /* t = a^2 */ + sp_256_mont_sqr_order_4(t, a); + /* t = a^3 = t * a */ + sp_256_mont_mul_order_4(t, t, a); + /* t2= a^c = t ^ 2 ^ 2 */ + sp_256_mont_sqr_n_order_4(t2, t, 2); + /* t3= a^f = t2 * t */ + sp_256_mont_mul_order_4(t3, t2, t); + /* t2= a^f0 = t3 ^ 2 ^ 4 */ + sp_256_mont_sqr_n_order_4(t2, t3, 4); + /* t = a^ff = t2 * t3 */ + sp_256_mont_mul_order_4(t, t2, t3); + /* t3= a^ff00 = t ^ 2 ^ 8 */ + sp_256_mont_sqr_n_order_4(t2, t, 8); + /* t = a^ffff = t2 * t */ + sp_256_mont_mul_order_4(t, t2, t); + /* t2= a^ffff0000 = t ^ 2 ^ 16 */ + sp_256_mont_sqr_n_order_4(t2, t, 16); + /* t = a^ffffffff = t2 * t */ + sp_256_mont_mul_order_4(t, t2, t); + /* t2= a^ffffffff0000000000000000 = t ^ 2 ^ 64 */ + sp_256_mont_sqr_n_order_4(t2, t, 64); + /* t2= a^ffffffff00000000ffffffff = t2 * t */ + sp_256_mont_mul_order_4(t2, t2, t); + /* t2= a^ffffffff00000000ffffffff00000000 = t2 ^ 2 ^ 32 */ + sp_256_mont_sqr_n_order_4(t2, t2, 32); + /* t2= a^ffffffff00000000ffffffffffffffff = t2 * t */ + sp_256_mont_mul_order_4(t2, t2, t); + /* t2= a^ffffffff00000000ffffffffffffffffbce6 */ + for (i=127; i>=112; i--) { + sp_256_mont_sqr_order_4(t2, t2); + if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64))) + sp_256_mont_mul_order_4(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6f */ + sp_256_mont_sqr_n_order_4(t2, t2, 4); + sp_256_mont_mul_order_4(t2, t2, t3); + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84 */ + for (i=107; i>=64; i--) { + sp_256_mont_sqr_order_4(t2, t2); + if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64))) + sp_256_mont_mul_order_4(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f */ + sp_256_mont_sqr_n_order_4(t2, t2, 4); + sp_256_mont_mul_order_4(t2, t2, t3); + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2 */ + for (i=59; i>=32; i--) { + sp_256_mont_sqr_order_4(t2, t2); + if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64))) + sp_256_mont_mul_order_4(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2f */ + sp_256_mont_sqr_n_order_4(t2, t2, 4); + sp_256_mont_mul_order_4(t2, t2, t3); + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254 */ + for (i=27; i>=0; i--) { + sp_256_mont_sqr_order_4(t2, t2); + if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64))) + sp_256_mont_mul_order_4(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632540 */ + sp_256_mont_sqr_n_order_4(t2, t2, 4); + /* r = a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f */ + sp_256_mont_mul_order_4(r, t2, t3); +#endif /* WOLFSSL_SP_SMALL */ +} + +#endif /* HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +#ifdef HAVE_ECC_SIGN +#ifndef SP_ECC_MAX_SIG_GEN +#define SP_ECC_MAX_SIG_GEN 64 +#endif + +/* Sign the hash using the private key. + * e = [hash, 256 bits] from binary + * r = (k.G)->x mod order + * s = (r * x + e) / k mod order + * The hash is truncated to the first 256 bits. + * + * hash Hash to sign. + * hashLen Length of the hash data. + * rng Random number generator. + * priv Private part of key - scalar. + * rm First part of result as an mp_int. + * sm Sirst part of result as an mp_int. + * heap Heap to use for allocation. + * returns RNG failures, MEMORY_E when memory allocation fails and + * MP_OKAY on success. + */ +int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, + mp_int* rm, mp_int* sm, void* heap) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d = NULL; +#else + sp_digit ed[2*4]; + sp_digit xd[2*4]; + sp_digit kd[2*4]; + sp_digit rd[2*4]; + sp_digit td[3 * 2*4]; + sp_point p; +#endif + sp_digit* e = NULL; + sp_digit* x = NULL; + sp_digit* k = NULL; + sp_digit* r = NULL; + sp_digit* tmp = NULL; + sp_point* point = NULL; + sp_digit carry; + sp_digit* s; + sp_digit* kInv; + int err = MP_OKAY; + int64_t c; + int i; + + (void)heap; + + err = sp_ecc_point_new(heap, p, point); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 4, heap, + DYNAMIC_TYPE_ECC); + if (d != NULL) { + e = d + 0 * 4; + x = d + 2 * 4; + k = d + 4 * 4; + r = d + 6 * 4; + tmp = d + 8 * 4; + } + else + err = MEMORY_E; + } +#else + e = ed; + x = xd; + k = kd; + r = rd; + tmp = td; +#endif + s = e; + kInv = k; + + if (err == MP_OKAY) { + if (hashLen > 32) + hashLen = 32; + + sp_256_from_bin(e, 4, hash, hashLen); + } + + for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { + sp_256_from_mp(x, 4, priv); + + /* New random point. */ + err = sp_256_ecc_gen_k_4(rng, k); + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_base_4(point, k, 1, NULL); + } + + if (err == MP_OKAY) { + /* r = point->x mod order */ + XMEMCPY(r, point->x, sizeof(sp_digit) * 4); + sp_256_norm_4(r); + c = sp_256_cmp_4(r, p256_order); + sp_256_cond_sub_4(r, r, p256_order, 0 - (c >= 0)); + sp_256_norm_4(r); + + /* Conv k to Montgomery form (mod order) */ + sp_256_mul_4(k, k, p256_norm_order); + err = sp_256_mod_4(k, k, p256_order); + } + if (err == MP_OKAY) { + sp_256_norm_4(k); + /* kInv = 1/k mod order */ + sp_256_mont_inv_order_4(kInv, k, tmp); + sp_256_norm_4(kInv); + + /* s = r * x + e */ + sp_256_mul_4(x, x, r); + err = sp_256_mod_4(x, x, p256_order); + } + if (err == MP_OKAY) { + sp_256_norm_4(x); + carry = sp_256_add_4(s, e, x); + sp_256_cond_sub_4(s, s, p256_order, 0 - carry); + sp_256_norm_4(s); + c = sp_256_cmp_4(s, p256_order); + sp_256_cond_sub_4(s, s, p256_order, 0 - (c >= 0)); + sp_256_norm_4(s); + + /* s = s * k^-1 mod order */ + sp_256_mont_mul_order_4(s, s, kInv); + sp_256_norm_4(s); + + /* Check that signature is usable. */ + if (!sp_256_iszero_4(s)) + break; + } + } + + if (i == 0) + err = RNG_FAILURE_E; + + if (err == MP_OKAY) + err = sp_256_to_mp(r, rm); + if (err == MP_OKAY) + err = sp_256_to_mp(s, sm); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) { + XMEMSET(d, 0, sizeof(sp_digit) * 8 * 4); + XFREE(d, heap, DYNAMIC_TYPE_ECC); + } +#else + XMEMSET(e, 0, sizeof(sp_digit) * 2 * 4); + XMEMSET(x, 0, sizeof(sp_digit) * 2 * 4); + XMEMSET(k, 0, sizeof(sp_digit) * 2 * 4); + XMEMSET(r, 0, sizeof(sp_digit) * 2 * 4); + XMEMSET(r, 0, sizeof(sp_digit) * 2 * 4); + XMEMSET(tmp, 0, sizeof(sp_digit) * 3 * 2*4); +#endif + sp_ecc_point_free(point, 1, heap); + + return err; +} +#endif /* HAVE_ECC_SIGN */ + +#ifdef HAVE_ECC_VERIFY +/* Verify the signature values with the hash and public key. + * e = Truncate(hash, 256) + * u1 = e/s mod order + * u2 = r/s mod order + * r == (u1.G + u2.Q)->x mod order + * Optimization: Leave point in projective form. + * (x, y, 1) == (x' / z'*z', y' / z'*z'*z', z' / z') + * (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' + * The hash is truncated to the first 256 bits. + * + * hash Hash to sign. + * hashLen Length of the hash data. + * rng Random number generator. + * priv Private part of key - scalar. + * rm First part of result as an mp_int. + * sm Sirst part of result as an mp_int. + * heap Heap to use for allocation. + * returns RNG failures, MEMORY_E when memory allocation fails and + * MP_OKAY on success. + */ +int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, + mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d = NULL; +#else + sp_digit u1d[2*4]; + sp_digit u2d[2*4]; + sp_digit sd[2*4]; + sp_digit tmpd[2*4 * 5]; + sp_point p1d; + sp_point p2d; +#endif + sp_digit* u1; + sp_digit* u2; + sp_digit* s; + sp_digit* tmp; + sp_point* p1; + sp_point* p2 = NULL; + sp_digit carry; + int64_t c; + int err; + + err = sp_ecc_point_new(heap, p1d, p1); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, p2d, p2); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 4, heap, + DYNAMIC_TYPE_ECC); + if (d != NULL) { + u1 = d + 0 * 4; + u2 = d + 2 * 4; + s = d + 4 * 4; + tmp = d + 6 * 4; + } + else + err = MEMORY_E; + } +#else + u1 = u1d; + u2 = u2d; + s = sd; + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + if (hashLen > 32) + hashLen = 32; + + sp_256_from_bin(u1, 4, hash, hashLen); + sp_256_from_mp(u2, 4, r); + sp_256_from_mp(s, 4, sm); + sp_256_from_mp(p2->x, 4, pX); + sp_256_from_mp(p2->y, 4, pY); + sp_256_from_mp(p2->z, 4, pZ); + + sp_256_mul_4(s, s, p256_norm_order); + err = sp_256_mod_4(s, s, p256_order); + } + if (err == MP_OKAY) { + sp_256_norm_4(s); + { + sp_256_mont_inv_order_4(s, s, tmp); + sp_256_mont_mul_order_4(u1, u1, s); + sp_256_mont_mul_order_4(u2, u2, s); + } + + err = sp_256_ecc_mulmod_base_4(p1, u1, 0, heap); + } + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_4(p2, p2, u2, 0, heap); + } + + if (err == MP_OKAY) { + sp_256_proj_point_add_4(p1, p1, p2, tmp); + + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_256_from_mp(u2, 4, r); + err = sp_256_mod_mul_norm_4(u2, u2, p256_mod); + } + + if (err == MP_OKAY) { + /* u1 = r.z'.z' mod prime */ + sp_256_mont_sqr_4(p1->z, p1->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(u1, u2, p1->z, p256_mod, p256_mp_mod); + *res = sp_256_cmp_4(p1->x, u1) == 0; + if (*res == 0) { + /* Reload r and add order. */ + sp_256_from_mp(u2, 4, r); + carry = sp_256_add_4(u2, u2, p256_order); + /* Carry means result is greater than mod and is not valid. */ + if (!carry) { + sp_256_norm_4(u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_256_cmp_4(u2, p256_mod); + if (c < 0) { + /* Convert to Montogomery form */ + err = sp_256_mod_mul_norm_4(u2, u2, p256_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_256_mont_mul_4(u1, u2, p1->z, p256_mod, + p256_mp_mod); + *res = sp_256_cmp_4(p1->x, u2) == 0; + } + } + } + } + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p1, 0, heap); + sp_ecc_point_free(p2, 0, heap); + + return err; +} +#endif /* HAVE_ECC_VERIFY */ + +#ifdef HAVE_ECC_CHECK_KEY +/* Check that the x and y oridinates are a valid point on the curve. + * + * point EC point. + * heap Heap to use if dynamically allocating. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +static int sp_256_ecc_is_point_4(sp_point* point, void* heap) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d = NULL; +#else + sp_digit t1d[2*4]; + sp_digit t2d[2*4]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 4, heap, + DYNAMIC_TYPE_ECC); + if (d != NULL) { + t1 = d + 0 * 4; + t2 = d + 2 * 4; + } + else + err = MEMORY_E; +#else + (void)heap; + + t1 = t1d; + t2 = t2d; +#endif + + if (err == MP_OKAY) { + sp_256_sqr_4(t1, point->y); + sp_256_mod_4(t1, t1, p256_mod); + sp_256_sqr_4(t2, point->x); + sp_256_mod_4(t2, t2, p256_mod); + sp_256_mul_4(t2, t2, point->x); + sp_256_mod_4(t2, t2, p256_mod); + sp_256_sub_4(t2, p256_mod, t2); + sp_256_mont_add_4(t1, t1, t2, p256_mod); + + sp_256_mont_add_4(t1, t1, point->x, p256_mod); + sp_256_mont_add_4(t1, t1, point->x, p256_mod); + sp_256_mont_add_4(t1, t1, point->x, p256_mod); + + if (sp_256_cmp_4(t1, p256_b) != 0) + err = MP_VAL; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Check that the x and y oridinates are a valid point on the curve. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +int sp_ecc_is_point_256(mp_int* pX, mp_int* pY) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point pubd; +#endif + sp_point* pub; + byte one[1] = { 1 }; + int err; + + err = sp_ecc_point_new(NULL, pubd, pub); + if (err == MP_OKAY) { + sp_256_from_mp(pub->x, 4, pX); + sp_256_from_mp(pub->y, 4, pY); + sp_256_from_bin(pub->z, 4, one, sizeof(one)); + + err = sp_256_ecc_is_point_4(pub, NULL); + } + + sp_ecc_point_free(pub, 0, NULL); + + return err; +} + +/* Check that the private scalar generates the EC point (px, py), the point is + * on the curve and the point has the correct order. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * privm Private scalar that generates EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve, ECC_INF_E if the point does not have the correct order, + * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and + * MP_OKAY otherwise. + */ +int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit privd[4]; + sp_point pubd; + sp_point pd; +#endif + sp_digit* priv = NULL; + sp_point* pub; + sp_point* p = NULL; + byte one[1] = { 1 }; + int err; + + err = sp_ecc_point_new(heap, pubd, pub); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4, heap, + DYNAMIC_TYPE_ECC); + if (priv == NULL) + err = MEMORY_E; + } +#else + priv = privd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(pub->x, 4, pX); + sp_256_from_mp(pub->y, 4, pY); + sp_256_from_bin(pub->z, 4, one, sizeof(one)); + sp_256_from_mp(priv, 4, privm); + + /* Check point at infinitiy. */ + if (sp_256_iszero_4(pub->x) && + sp_256_iszero_4(pub->y)) + err = ECC_INF_E; + } + + if (err == MP_OKAY) { + /* Check range of X and Y */ + if (sp_256_cmp_4(pub->x, p256_mod) >= 0 || + sp_256_cmp_4(pub->y, p256_mod) >= 0) + err = ECC_OUT_OF_RANGE_E; + } + + if (err == MP_OKAY) { + /* Check point is on curve */ + err = sp_256_ecc_is_point_4(pub, heap); + } + + if (err == MP_OKAY) { + /* Point * order = infinity */ + err = sp_256_ecc_mulmod_4(p, pub, p256_order, 1, heap); + } + if (err == MP_OKAY) { + /* Check result is infinity */ + if (!sp_256_iszero_4(p->x) || + !sp_256_iszero_4(p->y)) { + err = ECC_INF_E; + } + } + + if (err == MP_OKAY) { + /* Base * private = point */ + err = sp_256_ecc_mulmod_base_4(p, priv, 1, heap); + } + if (err == MP_OKAY) { + /* Check result is public key */ + if (sp_256_cmp_4(p->x, pub->x) != 0 || + sp_256_cmp_4(p->y, pub->y) != 0) { + err = ECC_PRIV_KEY_E; + } + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (priv != NULL) + XFREE(priv, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p, 0, heap); + sp_ecc_point_free(pub, 0, heap); + + return err; +} +#endif +#ifdef WOLFSSL_PUBLIC_ECC_ADD_DBL +/* Add two projective EC points together. + * (pX, pY, pZ) + (qX, qY, qZ) = (rX, rY, rZ) + * + * pX First EC point's X ordinate. + * pY First EC point's Y ordinate. + * pZ First EC point's Z ordinate. + * qX Second EC point's X ordinate. + * qY Second EC point's Y ordinate. + * qZ Second EC point's Z ordinate. + * rX Resultant EC point's X ordinate. + * rY Resultant EC point's Y ordinate. + * rZ Resultant EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* qX, mp_int* qY, mp_int* qZ, + mp_int* rX, mp_int* rY, mp_int* rZ) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit tmpd[2 * 4 * 5]; + sp_point pd; + sp_point qd; +#endif + sp_digit* tmp; + sp_point* p; + sp_point* q = NULL; + int err; + + err = sp_ecc_point_new(NULL, pd, p); + if (err == MP_OKAY) + err = sp_ecc_point_new(NULL, qd, q); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 5, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } +#else + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 4, pX); + sp_256_from_mp(p->y, 4, pY); + sp_256_from_mp(p->z, 4, pZ); + sp_256_from_mp(q->x, 4, qX); + sp_256_from_mp(q->y, 4, qY); + sp_256_from_mp(q->z, 4, qZ); + + sp_256_proj_point_add_4(p, p, q, tmp); + } + + if (err == MP_OKAY) + err = sp_256_to_mp(p->x, rX); + if (err == MP_OKAY) + err = sp_256_to_mp(p->y, rY); + if (err == MP_OKAY) + err = sp_256_to_mp(p->z, rZ); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (tmp != NULL) + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(q, 0, NULL); + sp_ecc_point_free(p, 0, NULL); + + return err; +} + +/* Double a projective EC point. + * (pX, pY, pZ) + (pX, pY, pZ) = (rX, rY, rZ) + * + * pX EC point's X ordinate. + * pY EC point's Y ordinate. + * pZ EC point's Z ordinate. + * rX Resultant EC point's X ordinate. + * rY Resultant EC point's Y ordinate. + * rZ Resultant EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* rX, mp_int* rY, mp_int* rZ) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit tmpd[2 * 4 * 2]; + sp_point pd; +#endif + sp_digit* tmp; + sp_point* p; + int err; + + err = sp_ecc_point_new(NULL, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 2, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } +#else + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 4, pX); + sp_256_from_mp(p->y, 4, pY); + sp_256_from_mp(p->z, 4, pZ); + + sp_256_proj_point_dbl_4(p, p, tmp); + } + + if (err == MP_OKAY) + err = sp_256_to_mp(p->x, rX); + if (err == MP_OKAY) + err = sp_256_to_mp(p->y, rY); + if (err == MP_OKAY) + err = sp_256_to_mp(p->z, rZ); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (tmp != NULL) + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p, 0, NULL); + + return err; +} + +/* Map a projective EC point to affine in place. + * pZ will be one. + * + * pX EC point's X ordinate. + * pY EC point's Y ordinate. + * pZ EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit tmpd[2 * 4 * 4]; + sp_point pd; +#endif + sp_digit* tmp; + sp_point* p; + int err; + + err = sp_ecc_point_new(NULL, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 4, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } +#else + tmp = tmpd; +#endif + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 4, pX); + sp_256_from_mp(p->y, 4, pY); + sp_256_from_mp(p->z, 4, pZ); + + sp_256_map_4(p, p, tmp); + } + + if (err == MP_OKAY) + err = sp_256_to_mp(p->x, pX); + if (err == MP_OKAY) + err = sp_256_to_mp(p->y, pY); + if (err == MP_OKAY) + err = sp_256_to_mp(p->z, pZ); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (tmp != NULL) + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p, 0, NULL); + + return err; +} +#endif /* WOLFSSL_PUBLIC_ECC_ADD_DBL */ +#ifdef HAVE_COMP_KEY +/* Find the square root of a number mod the prime of the curve. + * + * y The number to operate on and the result. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +static int sp_256_mont_sqrt_4(sp_digit* y) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d; +#else + sp_digit t1d[2 * 4]; + sp_digit t2d[2 * 4]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 4, NULL, DYNAMIC_TYPE_ECC); + if (d != NULL) { + t1 = d + 0 * 4; + t2 = d + 2 * 4; + } + else + err = MEMORY_E; +#else + t1 = t1d; + t2 = t2d; +#endif + + if (err == MP_OKAY) { + { + /* t2 = y ^ 0x2 */ + sp_256_mont_sqr_4(t2, y, p256_mod, p256_mp_mod); + /* t1 = y ^ 0x3 */ + sp_256_mont_mul_4(t1, t2, y, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xc */ + sp_256_mont_sqr_n_4(t2, t1, 2, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xf */ + sp_256_mont_mul_4(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xf0 */ + sp_256_mont_sqr_n_4(t2, t1, 4, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xff */ + sp_256_mont_mul_4(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xff00 */ + sp_256_mont_sqr_n_4(t2, t1, 8, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffff */ + sp_256_mont_mul_4(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xffff0000 */ + sp_256_mont_sqr_n_4(t2, t1, 16, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff */ + sp_256_mont_mul_4(t1, t1, t2, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000000 */ + sp_256_mont_sqr_n_4(t1, t1, 32, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001 */ + sp_256_mont_mul_4(t1, t1, y, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001000000000000000000000000 */ + sp_256_mont_sqr_n_4(t1, t1, 96, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001000000000000000000000001 */ + sp_256_mont_mul_4(t1, t1, y, p256_mod, p256_mp_mod); + sp_256_mont_sqr_n_4(y, t1, 94, p256_mod, p256_mp_mod); + } + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Uncompress the point given the X ordinate. + * + * xm X ordinate. + * odd Whether the Y ordinate is odd. + * ym Calculated Y ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d; +#else + sp_digit xd[2 * 4]; + sp_digit yd[2 * 4]; +#endif + sp_digit* x; + sp_digit* y; + int err = MP_OKAY; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 4, NULL, DYNAMIC_TYPE_ECC); + if (d != NULL) { + x = d + 0 * 4; + y = d + 2 * 4; + } + else + err = MEMORY_E; +#else + x = xd; + y = yd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(x, 4, xm); + + err = sp_256_mod_mul_norm_4(x, x, p256_mod); + } + + if (err == MP_OKAY) { + /* y = x^3 */ + { + sp_256_mont_sqr_4(y, x, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(y, y, x, p256_mod, p256_mp_mod); + } + /* y = x^3 - 3x */ + sp_256_mont_sub_4(y, y, x, p256_mod); + sp_256_mont_sub_4(y, y, x, p256_mod); + sp_256_mont_sub_4(y, y, x, p256_mod); + /* y = x^3 - 3x + b */ + err = sp_256_mod_mul_norm_4(x, p256_b, p256_mod); + } + if (err == MP_OKAY) { + sp_256_mont_add_4(y, y, x, p256_mod); + /* y = sqrt(x^3 - 3x + b) */ + err = sp_256_mont_sqrt_4(y); + } + if (err == MP_OKAY) { + XMEMSET(y + 4, 0, 4 * sizeof(sp_digit)); + sp_256_mont_reduce_4(y, p256_mod, p256_mp_mod); + if (((y[0] ^ odd) & 1) != 0) + sp_256_mont_sub_4(y, p256_mod, y, p256_mod); + + err = sp_256_to_mp(y, ym); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_ECC); +#endif + + return err; +} +#endif +#endif /* !WOLFSSL_SP_NO_256 */ +#endif /* WOLFSSL_HAVE_SP_ECC */ +#endif /* WOLFSSL_SP_ARM64_ASM */ +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH || WOLFSSL_HAVE_SP_ECC */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/sp_armthumb.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/sp_armthumb.c new file mode 100755 index 0000000..d313975 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/sp_armthumb.c @@ -0,0 +1,16131 @@ +/* sp.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/* Implementation by Sean Parkinson. */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include +#include +#include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) || \ + defined(WOLFSSL_HAVE_SP_ECC) + +#ifdef RSA_LOW_MEM +#ifndef WOLFSSL_SP_SMALL +#define WOLFSSL_SP_SMALL +#endif +#endif + +#include + +#ifdef WOLFSSL_SP_ARM_THUMB_ASM +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) +#ifndef WOLFSSL_SP_NO_2048 +/* Read big endian unsigned byte aray into r. + * + * r A single precision integer. + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_2048_from_bin(sp_digit* r, int max, const byte* a, int n) +{ + int i, j = 0, s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= ((sp_digit)a[i]) << s; + if (s >= 24) { + r[j] &= 0xffffffff; + s = 32 - s; + if (j + 1 >= max) + break; + r[++j] = a[i] >> s; + s = 8 - s; + } + else + s += 8; + } + + for (j++; j < max; j++) + r[j] = 0; +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * a A multi-precision integer. + */ +static void sp_2048_from_mp(sp_digit* r, int max, mp_int* a) +{ +#if DIGIT_BIT == 32 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < max; j++) + r[j] = 0; +#elif DIGIT_BIT > 32 + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= a->dp[i] << s; + r[j] &= 0xffffffff; + s = 32 - s; + if (j + 1 >= max) + break; + r[++j] = a->dp[i] >> s; + while (s + 32 <= DIGIT_BIT) { + s += 32; + r[j] &= 0xffffffff; + if (j + 1 >= max) + break; + if (s < DIGIT_BIT) + r[++j] = a->dp[i] >> s; + else + r[++j] = 0; + } + s = DIGIT_BIT - s; + } + + for (j++; j < max; j++) + r[j] = 0; +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 32) { + r[j] &= 0xffffffff; + if (j + 1 >= max) + break; + s = 32 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else + s += DIGIT_BIT; + } + + for (j++; j < max; j++) + r[j] = 0; +#endif +} + +/* Write r as big endian to byte aray. + * Fixed length number of bytes written: 256 + * + * r A single precision integer. + * a Byte array. + */ +static void sp_2048_to_bin(sp_digit* r, byte* a) +{ + int i, j, s = 0, b; + + j = 2048 / 8 - 1; + a[j] = 0; + for (i=0; i<64 && j>=0; i++) { + b = 0; + a[j--] |= r[i] << s; b += 8 - s; + if (j < 0) + break; + while (b < 32) { + a[j--] = r[i] >> b; b += 8; + if (j < 0) + break; + } + s = 8 - (b - 32); + if (j >= 0) + a[j] = 0; + if (s != 0) + j++; + } +} + +#ifndef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_2048_mul_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit tmp[8 * 2]; + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r8, r3\n\t" + "mov r11, %[r]\n\t" + "mov r9, %[a]\n\t" + "mov r10, %[b]\n\t" + "mov r6, #32\n\t" + "add r6, r9\n\t" + "mov r12, r6\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r5, #0\n\t" + "mov r6, #28\n\t" + "mov %[a], r8\n\t" + "sub %[a], r6\n\t" + "sbc r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], r6\n\t" + "mov %[b], r8\n\t" + "sub %[b], %[a]\n\t" + "add %[a], r9\n\t" + "add %[b], r10\n\t" + "\n2:\n\t" + "# Multiply Start\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [%[b]]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [%[b]]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [%[b]]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [%[b]]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Multiply Done\n\t" + "add %[a], #4\n\t" + "sub %[b], #4\n\t" + "cmp %[a], r12\n\t" + "beq 3f\n\t" + "mov r6, r8\n\t" + "add r6, r9\n\t" + "cmp %[a], r6\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r11\n\t" + "mov r7, r8\n\t" + "str r3, [%[r], r7]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "add r7, #4\n\t" + "mov r8, r7\n\t" + "mov r6, #56\n\t" + "cmp r7, r6\n\t" + "ble 1b\n\t" + "str r3, [%[r], r7]\n\t" + "mov %[a], r9\n\t" + "mov %[b], r10\n\t" + : + : [r] "r" (tmp), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_2048_sqr_8(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r5, #0\n\t" + "mov r8, r3\n\t" + "mov r11, %[r]\n\t" + "mov r6, #64\n\t" + "neg r6, r6\n\t" + "add sp, r6\n\t" + "mov r10, sp\n\t" + "mov r9, %[a]\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r6, #28\n\t" + "mov %[a], r8\n\t" + "sub %[a], r6\n\t" + "sbc r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], r6\n\t" + "mov r2, r8\n\t" + "sub r2, %[a]\n\t" + "add %[a], r9\n\t" + "add r2, r9\n\t" + "\n2:\n\t" + "cmp r2, %[a]\n\t" + "beq 4f\n\t" + "# Multiply * 2: Start\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [r2]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [r2]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [r2]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [r2]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Multiply * 2: Done\n\t" + "bal 5f\n\t" + "\n4:\n\t" + "# Square: Start\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "lsr r6, r6, #16\n\t" + "mul r6, r6\n\t" + "add r3, r6\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "mul r7, r7\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "lsr r6, r6, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #15\n\t" + "lsl r6, r6, #17\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Square: Done\n\t" + "\n5:\n\t" + "add %[a], #4\n\t" + "sub r2, #4\n\t" + "mov r6, #32\n\t" + "add r6, r9\n\t" + "cmp %[a], r6\n\t" + "beq 3f\n\t" + "cmp %[a], r2\n\t" + "bgt 3f\n\t" + "mov r7, r8\n\t" + "add r7, r9\n\t" + "cmp %[a], r7\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r10\n\t" + "mov r7, r8\n\t" + "str r3, [%[r], r7]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "add r7, #4\n\t" + "mov r8, r7\n\t" + "mov r6, #56\n\t" + "cmp r7, r6\n\t" + "ble 1b\n\t" + "mov %[a], r9\n\t" + "str r3, [%[r], r7]\n\t" + "mov %[r], r11\n\t" + "mov %[a], r10\n\t" + "mov r3, #60\n\t" + "\n4:\n\t" + "ldr r6, [%[a], r3]\n\t" + "str r6, [%[r], r3]\n\t" + "sub r3, #4\n\t" + "bge 4b\n\t" + "mov r6, #64\n\t" + "add sp, r6\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11" + ); +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_2048_add_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "add r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5" + ); + + return c; +} + +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_2048_sub_in_place_16(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sub r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #0]\n\t" + "str r4, [%[a], #4]\n\t" + "ldr r3, [%[a], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r6, [%[b], #12]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #8]\n\t" + "str r4, [%[a], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r6, [%[b], #20]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #16]\n\t" + "str r4, [%[a], #20]\n\t" + "ldr r3, [%[a], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r6, [%[b], #28]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #24]\n\t" + "str r4, [%[a], #28]\n\t" + "ldr r3, [%[a], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r6, [%[b], #36]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #32]\n\t" + "str r4, [%[a], #36]\n\t" + "ldr r3, [%[a], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r6, [%[b], #44]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #40]\n\t" + "str r4, [%[a], #44]\n\t" + "ldr r3, [%[a], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #48]\n\t" + "ldr r6, [%[b], #52]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #48]\n\t" + "str r4, [%[a], #52]\n\t" + "ldr r3, [%[a], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #56]\n\t" + "ldr r6, [%[b], #60]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #56]\n\t" + "str r4, [%[a], #60]\n\t" + "sbc %[c], %[c]\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6" + ); + + return c; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_2048_add_16(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "add r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[b], #48]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #52]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[b], #56]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #60]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #60]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5" + ); + + return c; +} + +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_2048_mask_8(sp_digit* r, sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<8; i++) + r[i] = a[i] & m; +#else + r[0] = a[0] & m; + r[1] = a[1] & m; + r[2] = a[2] & m; + r[3] = a[3] & m; + r[4] = a[4] & m; + r[5] = a[5] & m; + r[6] = a[6] & m; + r[7] = a[7] & m; +#endif +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_2048_mul_16(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[16]; + sp_digit a1[8]; + sp_digit b1[8]; + sp_digit z2[16]; + sp_digit u, ca, cb; + + ca = sp_2048_add_8(a1, a, &a[8]); + cb = sp_2048_add_8(b1, b, &b[8]); + u = ca & cb; + sp_2048_mul_8(z1, a1, b1); + sp_2048_mul_8(z2, &a[8], &b[8]); + sp_2048_mul_8(z0, a, b); + sp_2048_mask_8(r + 16, a1, 0 - cb); + sp_2048_mask_8(b1, b1, 0 - ca); + u += sp_2048_add_8(r + 16, r + 16, b1); + u += sp_2048_sub_in_place_16(z1, z2); + u += sp_2048_sub_in_place_16(z1, z0); + u += sp_2048_add_16(r + 8, r + 8, z1); + r[24] = u; + XMEMSET(r + 24 + 1, 0, sizeof(sp_digit) * (8 - 1)); + sp_2048_add_16(r + 16, r + 16, z2); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_2048_sqr_16(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z2[16]; + sp_digit z1[16]; + sp_digit a1[8]; + sp_digit u; + + u = sp_2048_add_8(a1, a, &a[8]); + sp_2048_sqr_8(z1, a1); + sp_2048_sqr_8(z2, &a[8]); + sp_2048_sqr_8(z0, a); + sp_2048_mask_8(r + 16, a1, 0 - u); + u += sp_2048_add_8(r + 16, r + 16, r + 16); + u += sp_2048_sub_in_place_16(z1, z2); + u += sp_2048_sub_in_place_16(z1, z0); + u += sp_2048_add_16(r + 8, r + 8, z1); + r[24] = u; + XMEMSET(r + 24 + 1, 0, sizeof(sp_digit) * (8 - 1)); + sp_2048_add_16(r + 16, r + 16, z2); +} + +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_2048_sub_in_place_32(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sub r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #0]\n\t" + "str r4, [%[a], #4]\n\t" + "ldr r3, [%[a], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r6, [%[b], #12]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #8]\n\t" + "str r4, [%[a], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r6, [%[b], #20]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #16]\n\t" + "str r4, [%[a], #20]\n\t" + "ldr r3, [%[a], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r6, [%[b], #28]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #24]\n\t" + "str r4, [%[a], #28]\n\t" + "ldr r3, [%[a], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r6, [%[b], #36]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #32]\n\t" + "str r4, [%[a], #36]\n\t" + "ldr r3, [%[a], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r6, [%[b], #44]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #40]\n\t" + "str r4, [%[a], #44]\n\t" + "ldr r3, [%[a], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #48]\n\t" + "ldr r6, [%[b], #52]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #48]\n\t" + "str r4, [%[a], #52]\n\t" + "ldr r3, [%[a], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #56]\n\t" + "ldr r6, [%[b], #60]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #56]\n\t" + "str r4, [%[a], #60]\n\t" + "ldr r3, [%[a], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #64]\n\t" + "ldr r6, [%[b], #68]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #64]\n\t" + "str r4, [%[a], #68]\n\t" + "ldr r3, [%[a], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #72]\n\t" + "ldr r6, [%[b], #76]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #72]\n\t" + "str r4, [%[a], #76]\n\t" + "ldr r3, [%[a], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #80]\n\t" + "ldr r6, [%[b], #84]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #80]\n\t" + "str r4, [%[a], #84]\n\t" + "ldr r3, [%[a], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #88]\n\t" + "ldr r6, [%[b], #92]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #88]\n\t" + "str r4, [%[a], #92]\n\t" + "ldr r3, [%[a], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #96]\n\t" + "ldr r6, [%[b], #100]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #96]\n\t" + "str r4, [%[a], #100]\n\t" + "ldr r3, [%[a], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #104]\n\t" + "ldr r6, [%[b], #108]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #104]\n\t" + "str r4, [%[a], #108]\n\t" + "ldr r3, [%[a], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #112]\n\t" + "ldr r6, [%[b], #116]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #112]\n\t" + "str r4, [%[a], #116]\n\t" + "ldr r3, [%[a], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #120]\n\t" + "ldr r6, [%[b], #124]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #120]\n\t" + "str r4, [%[a], #124]\n\t" + "sbc %[c], %[c]\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6" + ); + + return c; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_2048_add_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "add r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[b], #48]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #52]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[b], #56]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #60]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[b], #64]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #68]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[b], #72]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #76]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[b], #80]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #84]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[b], #88]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #92]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[b], #96]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #100]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[b], #104]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #108]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[b], #112]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #116]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[b], #120]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #124]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #124]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5" + ); + + return c; +} + +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_2048_mask_16(sp_digit* r, sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<16; i++) + r[i] = a[i] & m; +#else + int i; + + for (i = 0; i < 16; i += 8) { + r[i+0] = a[i+0] & m; + r[i+1] = a[i+1] & m; + r[i+2] = a[i+2] & m; + r[i+3] = a[i+3] & m; + r[i+4] = a[i+4] & m; + r[i+5] = a[i+5] & m; + r[i+6] = a[i+6] & m; + r[i+7] = a[i+7] & m; + } +#endif +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_2048_mul_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[32]; + sp_digit a1[16]; + sp_digit b1[16]; + sp_digit z2[32]; + sp_digit u, ca, cb; + + ca = sp_2048_add_16(a1, a, &a[16]); + cb = sp_2048_add_16(b1, b, &b[16]); + u = ca & cb; + sp_2048_mul_16(z1, a1, b1); + sp_2048_mul_16(z2, &a[16], &b[16]); + sp_2048_mul_16(z0, a, b); + sp_2048_mask_16(r + 32, a1, 0 - cb); + sp_2048_mask_16(b1, b1, 0 - ca); + u += sp_2048_add_16(r + 32, r + 32, b1); + u += sp_2048_sub_in_place_32(z1, z2); + u += sp_2048_sub_in_place_32(z1, z0); + u += sp_2048_add_32(r + 16, r + 16, z1); + r[48] = u; + XMEMSET(r + 48 + 1, 0, sizeof(sp_digit) * (16 - 1)); + sp_2048_add_32(r + 32, r + 32, z2); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_2048_sqr_32(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z2[32]; + sp_digit z1[32]; + sp_digit a1[16]; + sp_digit u; + + u = sp_2048_add_16(a1, a, &a[16]); + sp_2048_sqr_16(z1, a1); + sp_2048_sqr_16(z2, &a[16]); + sp_2048_sqr_16(z0, a); + sp_2048_mask_16(r + 32, a1, 0 - u); + u += sp_2048_add_16(r + 32, r + 32, r + 32); + u += sp_2048_sub_in_place_32(z1, z2); + u += sp_2048_sub_in_place_32(z1, z0); + u += sp_2048_add_32(r + 16, r + 16, z1); + r[48] = u; + XMEMSET(r + 48 + 1, 0, sizeof(sp_digit) * (16 - 1)); + sp_2048_add_32(r + 32, r + 32, z2); +} + +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_2048_sub_in_place_64(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sub r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #0]\n\t" + "str r4, [%[a], #4]\n\t" + "ldr r3, [%[a], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r6, [%[b], #12]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #8]\n\t" + "str r4, [%[a], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r6, [%[b], #20]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #16]\n\t" + "str r4, [%[a], #20]\n\t" + "ldr r3, [%[a], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r6, [%[b], #28]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #24]\n\t" + "str r4, [%[a], #28]\n\t" + "ldr r3, [%[a], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r6, [%[b], #36]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #32]\n\t" + "str r4, [%[a], #36]\n\t" + "ldr r3, [%[a], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r6, [%[b], #44]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #40]\n\t" + "str r4, [%[a], #44]\n\t" + "ldr r3, [%[a], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #48]\n\t" + "ldr r6, [%[b], #52]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #48]\n\t" + "str r4, [%[a], #52]\n\t" + "ldr r3, [%[a], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #56]\n\t" + "ldr r6, [%[b], #60]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #56]\n\t" + "str r4, [%[a], #60]\n\t" + "ldr r3, [%[a], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #64]\n\t" + "ldr r6, [%[b], #68]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #64]\n\t" + "str r4, [%[a], #68]\n\t" + "ldr r3, [%[a], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #72]\n\t" + "ldr r6, [%[b], #76]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #72]\n\t" + "str r4, [%[a], #76]\n\t" + "ldr r3, [%[a], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #80]\n\t" + "ldr r6, [%[b], #84]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #80]\n\t" + "str r4, [%[a], #84]\n\t" + "ldr r3, [%[a], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #88]\n\t" + "ldr r6, [%[b], #92]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #88]\n\t" + "str r4, [%[a], #92]\n\t" + "ldr r3, [%[a], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #96]\n\t" + "ldr r6, [%[b], #100]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #96]\n\t" + "str r4, [%[a], #100]\n\t" + "ldr r3, [%[a], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #104]\n\t" + "ldr r6, [%[b], #108]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #104]\n\t" + "str r4, [%[a], #108]\n\t" + "ldr r3, [%[a], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #112]\n\t" + "ldr r6, [%[b], #116]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #112]\n\t" + "str r4, [%[a], #116]\n\t" + "ldr r3, [%[a], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #120]\n\t" + "ldr r6, [%[b], #124]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #120]\n\t" + "str r4, [%[a], #124]\n\t" + "sbc %[c], %[c]\n\t" + "add %[a], #0x80\n\t" + "add %[b], #0x80\n\t" + "mov r5, #0\n\t" + "sub r5, %[c]\n\t" + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #0]\n\t" + "str r4, [%[a], #4]\n\t" + "ldr r3, [%[a], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r6, [%[b], #12]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #8]\n\t" + "str r4, [%[a], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r6, [%[b], #20]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #16]\n\t" + "str r4, [%[a], #20]\n\t" + "ldr r3, [%[a], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r6, [%[b], #28]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #24]\n\t" + "str r4, [%[a], #28]\n\t" + "ldr r3, [%[a], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r6, [%[b], #36]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #32]\n\t" + "str r4, [%[a], #36]\n\t" + "ldr r3, [%[a], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r6, [%[b], #44]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #40]\n\t" + "str r4, [%[a], #44]\n\t" + "ldr r3, [%[a], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #48]\n\t" + "ldr r6, [%[b], #52]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #48]\n\t" + "str r4, [%[a], #52]\n\t" + "ldr r3, [%[a], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #56]\n\t" + "ldr r6, [%[b], #60]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #56]\n\t" + "str r4, [%[a], #60]\n\t" + "ldr r3, [%[a], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #64]\n\t" + "ldr r6, [%[b], #68]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #64]\n\t" + "str r4, [%[a], #68]\n\t" + "ldr r3, [%[a], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #72]\n\t" + "ldr r6, [%[b], #76]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #72]\n\t" + "str r4, [%[a], #76]\n\t" + "ldr r3, [%[a], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #80]\n\t" + "ldr r6, [%[b], #84]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #80]\n\t" + "str r4, [%[a], #84]\n\t" + "ldr r3, [%[a], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #88]\n\t" + "ldr r6, [%[b], #92]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #88]\n\t" + "str r4, [%[a], #92]\n\t" + "ldr r3, [%[a], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #96]\n\t" + "ldr r6, [%[b], #100]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #96]\n\t" + "str r4, [%[a], #100]\n\t" + "ldr r3, [%[a], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #104]\n\t" + "ldr r6, [%[b], #108]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #104]\n\t" + "str r4, [%[a], #108]\n\t" + "ldr r3, [%[a], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #112]\n\t" + "ldr r6, [%[b], #116]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #112]\n\t" + "str r4, [%[a], #116]\n\t" + "ldr r3, [%[a], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #120]\n\t" + "ldr r6, [%[b], #124]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #120]\n\t" + "str r4, [%[a], #124]\n\t" + "sbc %[c], %[c]\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6" + ); + + return c; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_2048_add_64(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r7, #0\n\t" + "mvn r7, r7\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "add r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[b], #48]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #52]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[b], #56]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #60]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[b], #64]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #68]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[b], #72]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #76]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[b], #80]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #84]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[b], #88]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #92]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[b], #96]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #100]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[b], #104]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #108]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[b], #112]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #116]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[b], #120]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #124]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #124]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + "add %[a], #0x80\n\t" + "add %[b], #0x80\n\t" + "add %[r], #0x80\n\t" + "add %[c], r7\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[b], #48]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #52]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[b], #56]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #60]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[b], #64]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #68]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[b], #72]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #76]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[b], #80]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #84]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[b], #88]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #92]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[b], #96]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #100]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[b], #104]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #108]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[b], #112]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #116]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[b], #120]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #124]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #124]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r7" + ); + + return c; +} + +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_2048_mask_32(sp_digit* r, sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<32; i++) + r[i] = a[i] & m; +#else + int i; + + for (i = 0; i < 32; i += 8) { + r[i+0] = a[i+0] & m; + r[i+1] = a[i+1] & m; + r[i+2] = a[i+2] & m; + r[i+3] = a[i+3] & m; + r[i+4] = a[i+4] & m; + r[i+5] = a[i+5] & m; + r[i+6] = a[i+6] & m; + r[i+7] = a[i+7] & m; + } +#endif +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_2048_mul_64(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[64]; + sp_digit a1[32]; + sp_digit b1[32]; + sp_digit z2[64]; + sp_digit u, ca, cb; + + ca = sp_2048_add_32(a1, a, &a[32]); + cb = sp_2048_add_32(b1, b, &b[32]); + u = ca & cb; + sp_2048_mul_32(z1, a1, b1); + sp_2048_mul_32(z2, &a[32], &b[32]); + sp_2048_mul_32(z0, a, b); + sp_2048_mask_32(r + 64, a1, 0 - cb); + sp_2048_mask_32(b1, b1, 0 - ca); + u += sp_2048_add_32(r + 64, r + 64, b1); + u += sp_2048_sub_in_place_64(z1, z2); + u += sp_2048_sub_in_place_64(z1, z0); + u += sp_2048_add_64(r + 32, r + 32, z1); + r[96] = u; + XMEMSET(r + 96 + 1, 0, sizeof(sp_digit) * (32 - 1)); + sp_2048_add_64(r + 64, r + 64, z2); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_2048_sqr_64(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z2[64]; + sp_digit z1[64]; + sp_digit a1[32]; + sp_digit u; + + u = sp_2048_add_32(a1, a, &a[32]); + sp_2048_sqr_32(z1, a1); + sp_2048_sqr_32(z2, &a[32]); + sp_2048_sqr_32(z0, a); + sp_2048_mask_32(r + 64, a1, 0 - u); + u += sp_2048_add_32(r + 64, r + 64, r + 64); + u += sp_2048_sub_in_place_64(z1, z2); + u += sp_2048_sub_in_place_64(z1, z0); + u += sp_2048_add_64(r + 32, r + 32, z1); + r[96] = u; + XMEMSET(r + 96 + 1, 0, sizeof(sp_digit) * (32 - 1)); + sp_2048_add_64(r + 64, r + 64, z2); +} + +#endif /* !WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_2048_add_64(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r6, %[a]\n\t" + "mov r7, #0\n\t" + "mov r4, #1\n\t" + "lsl r4, #8\n\t" + "sub r7, #1\n\t" + "add r6, r4\n\t" + "\n1:\n\t" + "add %[c], r7\n\t" + "ldr r4, [%[a]]\n\t" + "ldr r5, [%[b]]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r]]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + "add %[a], #4\n\t" + "add %[b], #4\n\t" + "add %[r], #4\n\t" + "cmp %[a], r6\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r7" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into a. (a -= b) + * + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_2048_sub_in_place_64(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + __asm__ __volatile__ ( + "mov r7, %[a]\n\t" + "mov r5, #1\n\t" + "lsl r5, #8\n\t" + "add r7, r5\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "sub r5, %[c]\n\t" + "ldr r3, [%[a]]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b]]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a]]\n\t" + "str r4, [%[a], #4]\n\t" + "sbc %[c], %[c]\n\t" + "add %[a], #8\n\t" + "add %[b], #8\n\t" + "cmp %[a], r7\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6", "r7" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_2048_mul_64(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit tmp[64 * 2]; + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r8, r3\n\t" + "mov r11, %[r]\n\t" + "mov r9, %[a]\n\t" + "mov r10, %[b]\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, r9\n\t" + "mov r12, r6\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r5, #0\n\t" + "mov r6, #252\n\t" + "mov %[a], r8\n\t" + "sub %[a], r6\n\t" + "sbc r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], r6\n\t" + "mov %[b], r8\n\t" + "sub %[b], %[a]\n\t" + "add %[a], r9\n\t" + "add %[b], r10\n\t" + "\n2:\n\t" + "# Multiply Start\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [%[b]]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [%[b]]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [%[b]]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [%[b]]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Multiply Done\n\t" + "add %[a], #4\n\t" + "sub %[b], #4\n\t" + "cmp %[a], r12\n\t" + "beq 3f\n\t" + "mov r6, r8\n\t" + "add r6, r9\n\t" + "cmp %[a], r6\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r11\n\t" + "mov r7, r8\n\t" + "str r3, [%[r], r7]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "add r7, #4\n\t" + "mov r8, r7\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, #248\n\t" + "cmp r7, r6\n\t" + "ble 1b\n\t" + "str r3, [%[r], r7]\n\t" + "mov %[a], r9\n\t" + "mov %[b], r10\n\t" + : + : [r] "r" (tmp), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_2048_sqr_64(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r5, #0\n\t" + "mov r8, r3\n\t" + "mov r11, %[r]\n\t" + "mov r6, #2\n\t" + "lsl r6, r6, #8\n\t" + "neg r6, r6\n\t" + "add sp, r6\n\t" + "mov r10, sp\n\t" + "mov r9, %[a]\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r6, #252\n\t" + "mov %[a], r8\n\t" + "sub %[a], r6\n\t" + "sbc r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], r6\n\t" + "mov r2, r8\n\t" + "sub r2, %[a]\n\t" + "add %[a], r9\n\t" + "add r2, r9\n\t" + "\n2:\n\t" + "cmp r2, %[a]\n\t" + "beq 4f\n\t" + "# Multiply * 2: Start\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [r2]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [r2]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [r2]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [r2]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Multiply * 2: Done\n\t" + "bal 5f\n\t" + "\n4:\n\t" + "# Square: Start\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "lsr r6, r6, #16\n\t" + "mul r6, r6\n\t" + "add r3, r6\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "mul r7, r7\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "lsr r6, r6, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #15\n\t" + "lsl r6, r6, #17\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Square: Done\n\t" + "\n5:\n\t" + "add %[a], #4\n\t" + "sub r2, #4\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, r9\n\t" + "cmp %[a], r6\n\t" + "beq 3f\n\t" + "cmp %[a], r2\n\t" + "bgt 3f\n\t" + "mov r7, r8\n\t" + "add r7, r9\n\t" + "cmp %[a], r7\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r10\n\t" + "mov r7, r8\n\t" + "str r3, [%[r], r7]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "add r7, #4\n\t" + "mov r8, r7\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, #248\n\t" + "cmp r7, r6\n\t" + "ble 1b\n\t" + "mov %[a], r9\n\t" + "str r3, [%[r], r7]\n\t" + "mov %[r], r11\n\t" + "mov %[a], r10\n\t" + "mov r3, #1\n\t" + "lsl r3, r3, #8\n\t" + "add r3, #252\n\t" + "\n4:\n\t" + "ldr r6, [%[a], r3]\n\t" + "str r6, [%[r], r3]\n\t" + "sub r3, #4\n\t" + "bge 4b\n\t" + "mov r6, #2\n\t" + "lsl r6, r6, #8\n\t" + "add sp, r6\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11" + ); +} + +#endif /* WOLFSSL_SP_SMALL */ +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +#ifdef WOLFSSL_SP_SMALL +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_2048_mask_32(sp_digit* r, sp_digit* a, sp_digit m) +{ + int i; + + for (i=0; i<32; i++) + r[i] = a[i] & m; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_2048_add_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r6, %[a]\n\t" + "mov r7, #0\n\t" + "add r6, #128\n\t" + "sub r7, #1\n\t" + "\n1:\n\t" + "add %[c], r7\n\t" + "ldr r4, [%[a]]\n\t" + "ldr r5, [%[b]]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r]]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + "add %[a], #4\n\t" + "add %[b], #4\n\t" + "add %[r], #4\n\t" + "cmp %[a], r6\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r7" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into a. (a -= b) + * + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_2048_sub_in_place_32(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + __asm__ __volatile__ ( + "mov r7, %[a]\n\t" + "add r7, #128\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "sub r5, %[c]\n\t" + "ldr r3, [%[a]]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b]]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a]]\n\t" + "str r4, [%[a], #4]\n\t" + "sbc %[c], %[c]\n\t" + "add %[a], #8\n\t" + "add %[b], #8\n\t" + "cmp %[a], r7\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6", "r7" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_2048_mul_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit tmp[32 * 2]; + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r8, r3\n\t" + "mov r11, %[r]\n\t" + "mov r9, %[a]\n\t" + "mov r10, %[b]\n\t" + "mov r6, #128\n\t" + "add r6, r9\n\t" + "mov r12, r6\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r5, #0\n\t" + "mov r6, #124\n\t" + "mov %[a], r8\n\t" + "sub %[a], r6\n\t" + "sbc r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], r6\n\t" + "mov %[b], r8\n\t" + "sub %[b], %[a]\n\t" + "add %[a], r9\n\t" + "add %[b], r10\n\t" + "\n2:\n\t" + "# Multiply Start\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [%[b]]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [%[b]]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [%[b]]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [%[b]]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Multiply Done\n\t" + "add %[a], #4\n\t" + "sub %[b], #4\n\t" + "cmp %[a], r12\n\t" + "beq 3f\n\t" + "mov r6, r8\n\t" + "add r6, r9\n\t" + "cmp %[a], r6\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r11\n\t" + "mov r7, r8\n\t" + "str r3, [%[r], r7]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "add r7, #4\n\t" + "mov r8, r7\n\t" + "mov r6, #248\n\t" + "cmp r7, r6\n\t" + "ble 1b\n\t" + "str r3, [%[r], r7]\n\t" + "mov %[a], r9\n\t" + "mov %[b], r10\n\t" + : + : [r] "r" (tmp), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_2048_sqr_32(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r5, #0\n\t" + "mov r8, r3\n\t" + "mov r11, %[r]\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "neg r6, r6\n\t" + "add sp, r6\n\t" + "mov r10, sp\n\t" + "mov r9, %[a]\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r6, #124\n\t" + "mov %[a], r8\n\t" + "sub %[a], r6\n\t" + "sbc r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], r6\n\t" + "mov r2, r8\n\t" + "sub r2, %[a]\n\t" + "add %[a], r9\n\t" + "add r2, r9\n\t" + "\n2:\n\t" + "cmp r2, %[a]\n\t" + "beq 4f\n\t" + "# Multiply * 2: Start\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [r2]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [r2]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [r2]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [r2]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Multiply * 2: Done\n\t" + "bal 5f\n\t" + "\n4:\n\t" + "# Square: Start\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "lsr r6, r6, #16\n\t" + "mul r6, r6\n\t" + "add r3, r6\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "mul r7, r7\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "lsr r6, r6, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #15\n\t" + "lsl r6, r6, #17\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Square: Done\n\t" + "\n5:\n\t" + "add %[a], #4\n\t" + "sub r2, #4\n\t" + "mov r6, #128\n\t" + "add r6, r9\n\t" + "cmp %[a], r6\n\t" + "beq 3f\n\t" + "cmp %[a], r2\n\t" + "bgt 3f\n\t" + "mov r7, r8\n\t" + "add r7, r9\n\t" + "cmp %[a], r7\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r10\n\t" + "mov r7, r8\n\t" + "str r3, [%[r], r7]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "add r7, #4\n\t" + "mov r8, r7\n\t" + "mov r6, #248\n\t" + "cmp r7, r6\n\t" + "ble 1b\n\t" + "mov %[a], r9\n\t" + "str r3, [%[r], r7]\n\t" + "mov %[r], r11\n\t" + "mov %[a], r10\n\t" + "mov r3, #252\n\t" + "\n4:\n\t" + "ldr r6, [%[a], r3]\n\t" + "str r6, [%[r], r3]\n\t" + "sub r3, #4\n\t" + "bge 4b\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add sp, r6\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11" + ); +} + +#endif /* WOLFSSL_SP_SMALL */ +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +/* Caclulate the bottom digit of -1/a mod 2^n. + * + * a A single precision number. + * rho Bottom word of inverse. + */ +static void sp_2048_mont_setup(sp_digit* a, sp_digit* rho) +{ + sp_digit x, b; + + b = a[0]; + x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ + x *= 2 - b * x; /* here x*a==1 mod 2**8 */ + x *= 2 - b * x; /* here x*a==1 mod 2**16 */ + x *= 2 - b * x; /* here x*a==1 mod 2**32 */ + + /* rho = -1/m mod b */ + *rho = -x; +} + +/* Mul a by digit b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision digit. + */ +SP_NOINLINE static void sp_2048_mul_d_64(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ + __asm__ __volatile__ ( + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, %[a]\n\t" + "mov r8, %[r]\n\t" + "mov r9, r6\n\t" + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "1:\n\t" + "mov %[r], #0\n\t" + "mov r5, #0\n\t" + "# A[] * B\n\t" + "ldr r6, [%[a]]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, %[b], #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "lsr r7, %[b], #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, %[b], #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "lsl r7, %[b], #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# A[] * B - Done\n\t" + "mov %[r], r8\n\t" + "str r3, [%[r]]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "add %[r], #4\n\t" + "add %[a], #4\n\t" + "mov r8, %[r]\n\t" + "cmp %[a], r9\n\t" + "blt 1b\n\t" + "str r3, [%[r]]\n\t" + : [r] "+r" (r), [a] "+r" (a) + : [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9" + ); +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +/* r = 2^n mod m where n is the number of bits to reduce by. + * Given m must be 2048 bits, just need to subtract. + * + * r A single precision number. + * m A signle precision number. + */ +static void sp_2048_mont_norm_32(sp_digit* r, sp_digit* m) +{ + XMEMSET(r, 0, sizeof(sp_digit) * 32); + + /* r = 2^n mod m */ + sp_2048_sub_in_place_32(r, m); +} + +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not copying. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +SP_NOINLINE static sp_digit sp_2048_cond_sub_32(sp_digit* r, sp_digit* a, + sp_digit* b, sp_digit m) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r5, #128\n\t" + "mov r8, r5\n\t" + "mov r7, #0\n\t" + "1:\n\t" + "ldr r6, [%[b], r7]\n\t" + "and r6, %[m]\n\t" + "mov r5, #0\n\t" + "sub r5, %[c]\n\t" + "ldr r5, [%[a], r7]\n\t" + "sbc r5, r6\n\t" + "sbc %[c], %[c]\n\t" + "str r5, [%[r], r7]\n\t" + "add r7, #4\n\t" + "cmp r7, r8\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r5", "r6", "r7", "r8" + ); + + return c; +} + +/* Reduce the number back to 2048 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "mov r8, %[mp]\n\t" + "mov r12, %[ca]\n\t" + "mov r14, %[m]\n\t" + "mov r9, %[a]\n\t" + "mov r4, #0\n\t" + "# i = 0\n\t" + "mov r11, r4\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "mov %[ca], #0\n\t" + "# mu = a[i] * mp\n\t" + "mov %[mp], r8\n\t" + "ldr %[a], [%[a]]\n\t" + "mul %[mp], %[a]\n\t" + "mov %[m], r14\n\t" + "mov r10, r9\n\t" + "\n2:\n\t" + "# a[i+j] += m[j] * mu\n\t" + "mov %[a], r10\n\t" + "ldr %[a], [%[a]]\n\t" + "mov %[ca], #0\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "# Multiply m[j] and mu - Start\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r6, %[mp], #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add %[a], r7\n\t" + "adc r5, %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add %[a], r6\n\t" + "adc r5, r7\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r6, %[mp], #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r5, r7\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add %[a], r6\n\t" + "adc r5, r7\n\t" + "# Multiply m[j] and mu - Done\n\t" + "add r4, %[a]\n\t" + "adc r5, %[ca]\n\t" + "mov %[a], r10\n\t" + "str r4, [%[a]]\n\t" + "mov r6, #4\n\t" + "add %[m], #4\n\t" + "add r10, r6\n\t" + "mov r4, #124\n\t" + "add r4, r9\n\t" + "cmp r10, r4\n\t" + "blt 2b\n\t" + "# a[i+31] += m[31] * mu\n\t" + "mov %[ca], #0\n\t" + "mov r4, r12\n\t" + "mov %[a], #0\n\t" + "# Multiply m[31] and mu - Start\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r6, %[mp], #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r5, r7\n\t" + "adc r4, %[ca]\n\t" + "adc %[a], %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r5, r6\n\t" + "adc r4, r7\n\t" + "adc %[a], %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r6, %[mp], #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc %[a], %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r5, r6\n\t" + "adc r4, r7\n\t" + "adc %[a], %[ca]\n\t" + "# Multiply m[31] and mu - Done\n\t" + "mov %[ca], %[a]\n\t" + "mov %[a], r10\n\t" + "ldr r7, [%[a], #4]\n\t" + "ldr %[a], [%[a]]\n\t" + "mov r6, #0\n\t" + "add r5, %[a]\n\t" + "adc r7, r4\n\t" + "adc %[ca], r6\n\t" + "mov %[a], r10\n\t" + "str r5, [%[a]]\n\t" + "str r7, [%[a], #4]\n\t" + "# i += 1\n\t" + "mov r6, #4\n\t" + "add r9, r6\n\t" + "add r11, r6\n\t" + "mov r12, %[ca]\n\t" + "mov %[a], r9\n\t" + "mov r4, #128\n\t" + "cmp r11, r4\n\t" + "blt 1b\n\t" + "mov %[m], r14\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14" + ); + + sp_2048_cond_sub_32(a - 32, a, m, (sp_digit)0 - ca); +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_2048_mont_mul_32(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_2048_mul_32(r, a, b); + sp_2048_mont_reduce_32(r, m, mp); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_2048_mont_sqr_32(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_2048_sqr_32(r, a); + sp_2048_mont_reduce_32(r, m, mp); +} + +/* Mul a by digit b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision digit. + */ +SP_NOINLINE static void sp_2048_mul_d_32(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ + __asm__ __volatile__ ( + "mov r6, #128\n\t" + "add r6, %[a]\n\t" + "mov r8, %[r]\n\t" + "mov r9, r6\n\t" + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "1:\n\t" + "mov %[r], #0\n\t" + "mov r5, #0\n\t" + "# A[] * B\n\t" + "ldr r6, [%[a]]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, %[b], #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "lsr r7, %[b], #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, %[b], #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "lsl r7, %[b], #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# A[] * B - Done\n\t" + "mov %[r], r8\n\t" + "str r3, [%[r]]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "add %[r], #4\n\t" + "add %[a], #4\n\t" + "mov r8, %[r]\n\t" + "cmp %[a], r9\n\t" + "blt 1b\n\t" + "str r3, [%[r]]\n\t" + : [r] "+r" (r), [a] "+r" (a) + : [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9" + ); +} + +/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) + * + * d1 The high order half of the number to divide. + * d0 The low order half of the number to divide. + * div The dividend. + * returns the result of the division. + * + * Note that this is an approximate div. It may give an answer 1 larger. + */ +SP_NOINLINE static sp_digit div_2048_word_32(sp_digit d1, sp_digit d0, + sp_digit div) +{ + sp_digit r = 0; + + __asm__ __volatile__ ( + "lsr r5, %[div], #1\n\t" + "add r5, #1\n\t" + "mov r8, %[d0]\n\t" + "mov r9, %[d1]\n\t" + "# Do top 32\n\t" + "mov r6, r5\n\t" + "sub r6, %[d1]\n\t" + "sbc r6, r6\n\t" + "add %[r], %[r]\n\t" + "sub %[r], r6\n\t" + "and r6, r5\n\t" + "sub %[d1], r6\n\t" + "# Next 30 bits\n\t" + "mov r4, #29\n\t" + "1:\n\t" + "lsl %[d0], %[d0], #1\n\t" + "adc %[d1], %[d1]\n\t" + "mov r6, r5\n\t" + "sub r6, %[d1]\n\t" + "sbc r6, r6\n\t" + "add %[r], %[r]\n\t" + "sub %[r], r6\n\t" + "and r6, r5\n\t" + "sub %[d1], r6\n\t" + "sub r4, #1\n\t" + "bpl 1b\n\t" + "mov r7, #0\n\t" + "add %[r], %[r]\n\t" + "add %[r], #1\n\t" + "# r * div - Start\n\t" + "lsl %[d1], %[r], #16\n\t" + "lsl r4, %[div], #16\n\t" + "lsr %[d1], %[d1], #16\n\t" + "lsr r4, r4, #16\n\t" + "mul r4, %[d1]\n\t" + "lsr r6, %[div], #16\n\t" + "mul %[d1], r6\n\t" + "lsr r5, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r7\n\t" + "lsr %[d1], %[r], #16\n\t" + "mul r6, %[d1]\n\t" + "add r5, r6\n\t" + "lsl r6, %[div], #16\n\t" + "lsr r6, r6, #16\n\t" + "mul %[d1], r6\n\t" + "lsr r6, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r6\n\t" + "# r * div - Done\n\t" + "mov %[d1], r8\n\t" + "sub %[d1], r4\n\t" + "mov r4, %[d1]\n\t" + "mov %[d1], r9\n\t" + "sbc %[d1], r5\n\t" + "mov r5, %[d1]\n\t" + "add %[r], r5\n\t" + "# r * div - Start\n\t" + "lsl %[d1], %[r], #16\n\t" + "lsl r4, %[div], #16\n\t" + "lsr %[d1], %[d1], #16\n\t" + "lsr r4, r4, #16\n\t" + "mul r4, %[d1]\n\t" + "lsr r6, %[div], #16\n\t" + "mul %[d1], r6\n\t" + "lsr r5, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r7\n\t" + "lsr %[d1], %[r], #16\n\t" + "mul r6, %[d1]\n\t" + "add r5, r6\n\t" + "lsl r6, %[div], #16\n\t" + "lsr r6, r6, #16\n\t" + "mul %[d1], r6\n\t" + "lsr r6, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r6\n\t" + "# r * div - Done\n\t" + "mov %[d1], r8\n\t" + "mov r6, r9\n\t" + "sub r4, %[d1], r4\n\t" + "sbc r6, r5\n\t" + "mov r5, r6\n\t" + "add %[r], r5\n\t" + "# r * div - Start\n\t" + "lsl %[d1], %[r], #16\n\t" + "lsl r4, %[div], #16\n\t" + "lsr %[d1], %[d1], #16\n\t" + "lsr r4, r4, #16\n\t" + "mul r4, %[d1]\n\t" + "lsr r6, %[div], #16\n\t" + "mul %[d1], r6\n\t" + "lsr r5, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r7\n\t" + "lsr %[d1], %[r], #16\n\t" + "mul r6, %[d1]\n\t" + "add r5, r6\n\t" + "lsl r6, %[div], #16\n\t" + "lsr r6, r6, #16\n\t" + "mul %[d1], r6\n\t" + "lsr r6, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r6\n\t" + "# r * div - Done\n\t" + "mov %[d1], r8\n\t" + "mov r6, r9\n\t" + "sub r4, %[d1], r4\n\t" + "sbc r6, r5\n\t" + "mov r5, r6\n\t" + "add %[r], r5\n\t" + "mov r6, %[div]\n\t" + "sub r6, r4\n\t" + "sbc r6, r6\n\t" + "sub %[r], r6\n\t" + : [r] "+r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "r4", "r5", "r7", "r6", "r8", "r9" + ); + return r; +} + +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +SP_NOINLINE static int32_t sp_2048_cmp_32(sp_digit* a, sp_digit* b) +{ + sp_digit r = 0; + + + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mvn r3, r3\n\t" + "mov r6, #124\n\t" + "1:\n\t" + "ldr r7, [%[a], r6]\n\t" + "ldr r5, [%[b], r6]\n\t" + "and r7, r3\n\t" + "and r5, r3\n\t" + "mov r4, r7\n\t" + "sub r7, r5\n\t" + "sbc r7, r7\n\t" + "add %[r], r7\n\t" + "mvn r7, r7\n\t" + "and r3, r7\n\t" + "sub r5, r4\n\t" + "sbc r7, r7\n\t" + "sub %[r], r7\n\t" + "mvn r7, r7\n\t" + "and r3, r7\n\t" + "sub r6, #4\n\t" + "cmp r6, #0\n\t" + "bge 1b\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "r3", "r4", "r5", "r6", "r7" + ); + + return r; +} + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_2048_div_32(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[64], t2[33]; + sp_digit div, r1; + int i; + + (void)m; + + div = d[31]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 32); + for (i=31; i>=0; i--) { + r1 = div_2048_word_32(t1[32 + i], t1[32 + i - 1], div); + + sp_2048_mul_d_32(t2, d, r1); + t1[32 + i] += sp_2048_sub_in_place_32(&t1[i], t2); + t1[32 + i] -= t2[32]; + sp_2048_mask_32(t2, d, t1[32 + i]); + t1[32 + i] += sp_2048_add_32(&t1[i], &t1[i], t2); + sp_2048_mask_32(t2, d, t1[32 + i]); + t1[32 + i] += sp_2048_add_32(&t1[i], &t1[i], t2); + } + + r1 = sp_2048_cmp_32(t1, d) >= 0; + sp_2048_cond_sub_32(r, t1, d, (sp_digit)0 - r1); + + return MP_OKAY; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_2048_mod_32(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_2048_div_32(a, m, NULL, r); +} + +#ifdef WOLFSSL_SP_SMALL +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_2048_mod_exp_32(sp_digit* r, sp_digit* a, sp_digit* e, + int bits, sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[16][64]; +#else + sp_digit* t[16]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 64, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<16; i++) + t[i] = td + i * 64; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_32(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 32); + if (reduceA) { + err = sp_2048_mod_32(t[1] + 32, a, m); + if (err == MP_OKAY) + err = sp_2048_mod_32(t[1], t[1], m); + } + else { + XMEMCPY(t[1] + 32, a, sizeof(sp_digit) * 32); + err = sp_2048_mod_32(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_2048_mont_sqr_32(t[ 2], t[ 1], m, mp); + sp_2048_mont_mul_32(t[ 3], t[ 2], t[ 1], m, mp); + sp_2048_mont_sqr_32(t[ 4], t[ 2], m, mp); + sp_2048_mont_mul_32(t[ 5], t[ 3], t[ 2], m, mp); + sp_2048_mont_sqr_32(t[ 6], t[ 3], m, mp); + sp_2048_mont_mul_32(t[ 7], t[ 4], t[ 3], m, mp); + sp_2048_mont_sqr_32(t[ 8], t[ 4], m, mp); + sp_2048_mont_mul_32(t[ 9], t[ 5], t[ 4], m, mp); + sp_2048_mont_sqr_32(t[10], t[ 5], m, mp); + sp_2048_mont_mul_32(t[11], t[ 6], t[ 5], m, mp); + sp_2048_mont_sqr_32(t[12], t[ 6], m, mp); + sp_2048_mont_mul_32(t[13], t[ 7], t[ 6], m, mp); + sp_2048_mont_sqr_32(t[14], t[ 7], m, mp); + sp_2048_mont_mul_32(t[15], t[ 8], t[ 7], m, mp); + + i = (bits - 1) / 32; + n = e[i--]; + y = n >> 28; + n <<= 4; + c = 28; + XMEMCPY(r, t[y], sizeof(sp_digit) * 32); + for (; i>=0 || c>=4; ) { + if (c == 0) { + n = e[i--]; + y = n >> 28; + n <<= 4; + c = 28; + } + else if (c < 4) { + y = n >> 28; + n = e[i--]; + c = 4 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 28) & 0xf; + n <<= 4; + c -= 4; + } + + sp_2048_mont_sqr_32(r, r, m, mp); + sp_2048_mont_sqr_32(r, r, m, mp); + sp_2048_mont_sqr_32(r, r, m, mp); + sp_2048_mont_sqr_32(r, r, m, mp); + + sp_2048_mont_mul_32(r, r, t[y], m, mp); + } + y = e[0] & ((1 << c) - 1); + for (; c > 0; c--) + sp_2048_mont_sqr_32(r, r, m, mp); + sp_2048_mont_mul_32(r, r, t[y], m, mp); + + XMEMSET(&r[32], 0, sizeof(sp_digit) * 32); + sp_2048_mont_reduce_32(r, m, mp); + + mask = 0 - (sp_2048_cmp_32(r, m) >= 0); + sp_2048_cond_sub_32(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#else +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_2048_mod_exp_32(sp_digit* r, sp_digit* a, sp_digit* e, + int bits, sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][64]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 64, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<32; i++) + t[i] = td + i * 64; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_32(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 32); + if (reduceA) { + err = sp_2048_mod_32(t[1] + 32, a, m); + if (err == MP_OKAY) + err = sp_2048_mod_32(t[1], t[1], m); + } + else { + XMEMCPY(t[1] + 32, a, sizeof(sp_digit) * 32); + err = sp_2048_mod_32(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_2048_mont_sqr_32(t[ 2], t[ 1], m, mp); + sp_2048_mont_mul_32(t[ 3], t[ 2], t[ 1], m, mp); + sp_2048_mont_sqr_32(t[ 4], t[ 2], m, mp); + sp_2048_mont_mul_32(t[ 5], t[ 3], t[ 2], m, mp); + sp_2048_mont_sqr_32(t[ 6], t[ 3], m, mp); + sp_2048_mont_mul_32(t[ 7], t[ 4], t[ 3], m, mp); + sp_2048_mont_sqr_32(t[ 8], t[ 4], m, mp); + sp_2048_mont_mul_32(t[ 9], t[ 5], t[ 4], m, mp); + sp_2048_mont_sqr_32(t[10], t[ 5], m, mp); + sp_2048_mont_mul_32(t[11], t[ 6], t[ 5], m, mp); + sp_2048_mont_sqr_32(t[12], t[ 6], m, mp); + sp_2048_mont_mul_32(t[13], t[ 7], t[ 6], m, mp); + sp_2048_mont_sqr_32(t[14], t[ 7], m, mp); + sp_2048_mont_mul_32(t[15], t[ 8], t[ 7], m, mp); + sp_2048_mont_sqr_32(t[16], t[ 8], m, mp); + sp_2048_mont_mul_32(t[17], t[ 9], t[ 8], m, mp); + sp_2048_mont_sqr_32(t[18], t[ 9], m, mp); + sp_2048_mont_mul_32(t[19], t[10], t[ 9], m, mp); + sp_2048_mont_sqr_32(t[20], t[10], m, mp); + sp_2048_mont_mul_32(t[21], t[11], t[10], m, mp); + sp_2048_mont_sqr_32(t[22], t[11], m, mp); + sp_2048_mont_mul_32(t[23], t[12], t[11], m, mp); + sp_2048_mont_sqr_32(t[24], t[12], m, mp); + sp_2048_mont_mul_32(t[25], t[13], t[12], m, mp); + sp_2048_mont_sqr_32(t[26], t[13], m, mp); + sp_2048_mont_mul_32(t[27], t[14], t[13], m, mp); + sp_2048_mont_sqr_32(t[28], t[14], m, mp); + sp_2048_mont_mul_32(t[29], t[15], t[14], m, mp); + sp_2048_mont_sqr_32(t[30], t[15], m, mp); + sp_2048_mont_mul_32(t[31], t[16], t[15], m, mp); + + i = (bits - 1) / 32; + n = e[i--]; + y = n >> 27; + n <<= 5; + c = 27; + XMEMCPY(r, t[y], sizeof(sp_digit) * 32); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 27; + n <<= 5; + c = 27; + } + else if (c < 5) { + y = n >> 27; + n = e[i--]; + c = 5 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 27) & 0x1f; + n <<= 5; + c -= 5; + } + + sp_2048_mont_sqr_32(r, r, m, mp); + sp_2048_mont_sqr_32(r, r, m, mp); + sp_2048_mont_sqr_32(r, r, m, mp); + sp_2048_mont_sqr_32(r, r, m, mp); + sp_2048_mont_sqr_32(r, r, m, mp); + + sp_2048_mont_mul_32(r, r, t[y], m, mp); + } + y = e[0] & ((1 << c) - 1); + for (; c > 0; c--) + sp_2048_mont_sqr_32(r, r, m, mp); + sp_2048_mont_mul_32(r, r, t[y], m, mp); + + XMEMSET(&r[32], 0, sizeof(sp_digit) * 32); + sp_2048_mont_reduce_32(r, m, mp); + + mask = 0 - (sp_2048_cmp_32(r, m) >= 0); + sp_2048_cond_sub_32(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#endif /* WOLFSSL_SP_SMALL */ + +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) +/* r = 2^n mod m where n is the number of bits to reduce by. + * Given m must be 2048 bits, just need to subtract. + * + * r A single precision number. + * m A signle precision number. + */ +static void sp_2048_mont_norm_64(sp_digit* r, sp_digit* m) +{ + XMEMSET(r, 0, sizeof(sp_digit) * 64); + + /* r = 2^n mod m */ + sp_2048_sub_in_place_64(r, m); +} + +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not copying. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +SP_NOINLINE static sp_digit sp_2048_cond_sub_64(sp_digit* r, sp_digit* a, + sp_digit* b, sp_digit m) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r5, #1\n\t" + "lsl r5, r5, #8\n\t" + "mov r8, r5\n\t" + "mov r7, #0\n\t" + "1:\n\t" + "ldr r6, [%[b], r7]\n\t" + "and r6, %[m]\n\t" + "mov r5, #0\n\t" + "sub r5, %[c]\n\t" + "ldr r5, [%[a], r7]\n\t" + "sbc r5, r6\n\t" + "sbc %[c], %[c]\n\t" + "str r5, [%[r], r7]\n\t" + "add r7, #4\n\t" + "cmp r7, r8\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r5", "r6", "r7", "r8" + ); + + return c; +} + +/* Reduce the number back to 2048 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "mov r8, %[mp]\n\t" + "mov r12, %[ca]\n\t" + "mov r14, %[m]\n\t" + "mov r9, %[a]\n\t" + "mov r4, #0\n\t" + "# i = 0\n\t" + "mov r11, r4\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "mov %[ca], #0\n\t" + "# mu = a[i] * mp\n\t" + "mov %[mp], r8\n\t" + "ldr %[a], [%[a]]\n\t" + "mul %[mp], %[a]\n\t" + "mov %[m], r14\n\t" + "mov r10, r9\n\t" + "\n2:\n\t" + "# a[i+j] += m[j] * mu\n\t" + "mov %[a], r10\n\t" + "ldr %[a], [%[a]]\n\t" + "mov %[ca], #0\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "# Multiply m[j] and mu - Start\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r6, %[mp], #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add %[a], r7\n\t" + "adc r5, %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add %[a], r6\n\t" + "adc r5, r7\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r6, %[mp], #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r5, r7\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add %[a], r6\n\t" + "adc r5, r7\n\t" + "# Multiply m[j] and mu - Done\n\t" + "add r4, %[a]\n\t" + "adc r5, %[ca]\n\t" + "mov %[a], r10\n\t" + "str r4, [%[a]]\n\t" + "mov r6, #4\n\t" + "add %[m], #4\n\t" + "add r10, r6\n\t" + "mov r4, #252\n\t" + "add r4, r9\n\t" + "cmp r10, r4\n\t" + "blt 2b\n\t" + "# a[i+63] += m[63] * mu\n\t" + "mov %[ca], #0\n\t" + "mov r4, r12\n\t" + "mov %[a], #0\n\t" + "# Multiply m[63] and mu - Start\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r6, %[mp], #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r5, r7\n\t" + "adc r4, %[ca]\n\t" + "adc %[a], %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r5, r6\n\t" + "adc r4, r7\n\t" + "adc %[a], %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r6, %[mp], #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc %[a], %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r5, r6\n\t" + "adc r4, r7\n\t" + "adc %[a], %[ca]\n\t" + "# Multiply m[63] and mu - Done\n\t" + "mov %[ca], %[a]\n\t" + "mov %[a], r10\n\t" + "ldr r7, [%[a], #4]\n\t" + "ldr %[a], [%[a]]\n\t" + "mov r6, #0\n\t" + "add r5, %[a]\n\t" + "adc r7, r4\n\t" + "adc %[ca], r6\n\t" + "mov %[a], r10\n\t" + "str r5, [%[a]]\n\t" + "str r7, [%[a], #4]\n\t" + "# i += 1\n\t" + "mov r6, #4\n\t" + "add r9, r6\n\t" + "add r11, r6\n\t" + "mov r12, %[ca]\n\t" + "mov %[a], r9\n\t" + "mov r4, #1\n\t" + "lsl r4, r4, #8\n\t" + "cmp r11, r4\n\t" + "blt 1b\n\t" + "mov %[m], r14\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14" + ); + + sp_2048_cond_sub_64(a - 64, a, m, (sp_digit)0 - ca); +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_2048_mont_mul_64(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_2048_mul_64(r, a, b); + sp_2048_mont_reduce_64(r, m, mp); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_2048_mont_sqr_64(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_2048_sqr_64(r, a); + sp_2048_mont_reduce_64(r, m, mp); +} + +/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) + * + * d1 The high order half of the number to divide. + * d0 The low order half of the number to divide. + * div The dividend. + * returns the result of the division. + * + * Note that this is an approximate div. It may give an answer 1 larger. + */ +SP_NOINLINE static sp_digit div_2048_word_64(sp_digit d1, sp_digit d0, + sp_digit div) +{ + sp_digit r = 0; + + __asm__ __volatile__ ( + "lsr r5, %[div], #1\n\t" + "add r5, #1\n\t" + "mov r8, %[d0]\n\t" + "mov r9, %[d1]\n\t" + "# Do top 32\n\t" + "mov r6, r5\n\t" + "sub r6, %[d1]\n\t" + "sbc r6, r6\n\t" + "add %[r], %[r]\n\t" + "sub %[r], r6\n\t" + "and r6, r5\n\t" + "sub %[d1], r6\n\t" + "# Next 30 bits\n\t" + "mov r4, #29\n\t" + "1:\n\t" + "lsl %[d0], %[d0], #1\n\t" + "adc %[d1], %[d1]\n\t" + "mov r6, r5\n\t" + "sub r6, %[d1]\n\t" + "sbc r6, r6\n\t" + "add %[r], %[r]\n\t" + "sub %[r], r6\n\t" + "and r6, r5\n\t" + "sub %[d1], r6\n\t" + "sub r4, #1\n\t" + "bpl 1b\n\t" + "mov r7, #0\n\t" + "add %[r], %[r]\n\t" + "add %[r], #1\n\t" + "# r * div - Start\n\t" + "lsl %[d1], %[r], #16\n\t" + "lsl r4, %[div], #16\n\t" + "lsr %[d1], %[d1], #16\n\t" + "lsr r4, r4, #16\n\t" + "mul r4, %[d1]\n\t" + "lsr r6, %[div], #16\n\t" + "mul %[d1], r6\n\t" + "lsr r5, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r7\n\t" + "lsr %[d1], %[r], #16\n\t" + "mul r6, %[d1]\n\t" + "add r5, r6\n\t" + "lsl r6, %[div], #16\n\t" + "lsr r6, r6, #16\n\t" + "mul %[d1], r6\n\t" + "lsr r6, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r6\n\t" + "# r * div - Done\n\t" + "mov %[d1], r8\n\t" + "sub %[d1], r4\n\t" + "mov r4, %[d1]\n\t" + "mov %[d1], r9\n\t" + "sbc %[d1], r5\n\t" + "mov r5, %[d1]\n\t" + "add %[r], r5\n\t" + "# r * div - Start\n\t" + "lsl %[d1], %[r], #16\n\t" + "lsl r4, %[div], #16\n\t" + "lsr %[d1], %[d1], #16\n\t" + "lsr r4, r4, #16\n\t" + "mul r4, %[d1]\n\t" + "lsr r6, %[div], #16\n\t" + "mul %[d1], r6\n\t" + "lsr r5, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r7\n\t" + "lsr %[d1], %[r], #16\n\t" + "mul r6, %[d1]\n\t" + "add r5, r6\n\t" + "lsl r6, %[div], #16\n\t" + "lsr r6, r6, #16\n\t" + "mul %[d1], r6\n\t" + "lsr r6, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r6\n\t" + "# r * div - Done\n\t" + "mov %[d1], r8\n\t" + "mov r6, r9\n\t" + "sub r4, %[d1], r4\n\t" + "sbc r6, r5\n\t" + "mov r5, r6\n\t" + "add %[r], r5\n\t" + "# r * div - Start\n\t" + "lsl %[d1], %[r], #16\n\t" + "lsl r4, %[div], #16\n\t" + "lsr %[d1], %[d1], #16\n\t" + "lsr r4, r4, #16\n\t" + "mul r4, %[d1]\n\t" + "lsr r6, %[div], #16\n\t" + "mul %[d1], r6\n\t" + "lsr r5, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r7\n\t" + "lsr %[d1], %[r], #16\n\t" + "mul r6, %[d1]\n\t" + "add r5, r6\n\t" + "lsl r6, %[div], #16\n\t" + "lsr r6, r6, #16\n\t" + "mul %[d1], r6\n\t" + "lsr r6, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r6\n\t" + "# r * div - Done\n\t" + "mov %[d1], r8\n\t" + "mov r6, r9\n\t" + "sub r4, %[d1], r4\n\t" + "sbc r6, r5\n\t" + "mov r5, r6\n\t" + "add %[r], r5\n\t" + "mov r6, %[div]\n\t" + "sub r6, r4\n\t" + "sbc r6, r6\n\t" + "sub %[r], r6\n\t" + : [r] "+r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "r4", "r5", "r7", "r6", "r8", "r9" + ); + return r; +} + +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_2048_mask_64(sp_digit* r, sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<64; i++) + r[i] = a[i] & m; +#else + int i; + + for (i = 0; i < 64; i += 8) { + r[i+0] = a[i+0] & m; + r[i+1] = a[i+1] & m; + r[i+2] = a[i+2] & m; + r[i+3] = a[i+3] & m; + r[i+4] = a[i+4] & m; + r[i+5] = a[i+5] & m; + r[i+6] = a[i+6] & m; + r[i+7] = a[i+7] & m; + } +#endif +} + +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +SP_NOINLINE static int32_t sp_2048_cmp_64(sp_digit* a, sp_digit* b) +{ + sp_digit r = 0; + + + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mvn r3, r3\n\t" + "mov r6, #252\n\t" + "1:\n\t" + "ldr r7, [%[a], r6]\n\t" + "ldr r5, [%[b], r6]\n\t" + "and r7, r3\n\t" + "and r5, r3\n\t" + "mov r4, r7\n\t" + "sub r7, r5\n\t" + "sbc r7, r7\n\t" + "add %[r], r7\n\t" + "mvn r7, r7\n\t" + "and r3, r7\n\t" + "sub r5, r4\n\t" + "sbc r7, r7\n\t" + "sub %[r], r7\n\t" + "mvn r7, r7\n\t" + "and r3, r7\n\t" + "sub r6, #4\n\t" + "cmp r6, #0\n\t" + "bge 1b\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "r3", "r4", "r5", "r6", "r7" + ); + + return r; +} + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_2048_div_64(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[128], t2[65]; + sp_digit div, r1; + int i; + + (void)m; + + div = d[63]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 64); + for (i=63; i>=0; i--) { + r1 = div_2048_word_64(t1[64 + i], t1[64 + i - 1], div); + + sp_2048_mul_d_64(t2, d, r1); + t1[64 + i] += sp_2048_sub_in_place_64(&t1[i], t2); + t1[64 + i] -= t2[64]; + sp_2048_mask_64(t2, d, t1[64 + i]); + t1[64 + i] += sp_2048_add_64(&t1[i], &t1[i], t2); + sp_2048_mask_64(t2, d, t1[64 + i]); + t1[64 + i] += sp_2048_add_64(&t1[i], &t1[i], t2); + } + + r1 = sp_2048_cmp_64(t1, d) >= 0; + sp_2048_cond_sub_64(r, t1, d, (sp_digit)0 - r1); + + return MP_OKAY; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_2048_mod_64(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_2048_div_64(a, m, NULL, r); +} + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_2048_div_64_cond(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[128], t2[65]; + sp_digit div, r1; + int i; + + (void)m; + + div = d[63]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 64); + for (i=63; i>=0; i--) { + r1 = div_2048_word_64(t1[64 + i], t1[64 + i - 1], div); + + sp_2048_mul_d_64(t2, d, r1); + t1[64 + i] += sp_2048_sub_in_place_64(&t1[i], t2); + t1[64 + i] -= t2[64]; + if (t1[64 + i] != 0) { + t1[64 + i] += sp_2048_add_64(&t1[i], &t1[i], d); + if (t1[64 + i] != 0) + t1[64 + i] += sp_2048_add_64(&t1[i], &t1[i], d); + } + } + + r1 = sp_2048_cmp_64(t1, d) >= 0; + sp_2048_cond_sub_64(r, t1, d, (sp_digit)0 - r1); + + return MP_OKAY; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_2048_mod_64_cond(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_2048_div_64_cond(a, m, NULL, r); +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \ + defined(WOLFSSL_HAVE_SP_DH) +#ifdef WOLFSSL_SP_SMALL +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_2048_mod_exp_64(sp_digit* r, sp_digit* a, sp_digit* e, + int bits, sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[16][128]; +#else + sp_digit* t[16]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 128, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<16; i++) + t[i] = td + i * 128; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_64(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 64); + if (reduceA) { + err = sp_2048_mod_64(t[1] + 64, a, m); + if (err == MP_OKAY) + err = sp_2048_mod_64(t[1], t[1], m); + } + else { + XMEMCPY(t[1] + 64, a, sizeof(sp_digit) * 64); + err = sp_2048_mod_64(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_2048_mont_sqr_64(t[ 2], t[ 1], m, mp); + sp_2048_mont_mul_64(t[ 3], t[ 2], t[ 1], m, mp); + sp_2048_mont_sqr_64(t[ 4], t[ 2], m, mp); + sp_2048_mont_mul_64(t[ 5], t[ 3], t[ 2], m, mp); + sp_2048_mont_sqr_64(t[ 6], t[ 3], m, mp); + sp_2048_mont_mul_64(t[ 7], t[ 4], t[ 3], m, mp); + sp_2048_mont_sqr_64(t[ 8], t[ 4], m, mp); + sp_2048_mont_mul_64(t[ 9], t[ 5], t[ 4], m, mp); + sp_2048_mont_sqr_64(t[10], t[ 5], m, mp); + sp_2048_mont_mul_64(t[11], t[ 6], t[ 5], m, mp); + sp_2048_mont_sqr_64(t[12], t[ 6], m, mp); + sp_2048_mont_mul_64(t[13], t[ 7], t[ 6], m, mp); + sp_2048_mont_sqr_64(t[14], t[ 7], m, mp); + sp_2048_mont_mul_64(t[15], t[ 8], t[ 7], m, mp); + + i = (bits - 1) / 32; + n = e[i--]; + y = n >> 28; + n <<= 4; + c = 28; + XMEMCPY(r, t[y], sizeof(sp_digit) * 64); + for (; i>=0 || c>=4; ) { + if (c == 0) { + n = e[i--]; + y = n >> 28; + n <<= 4; + c = 28; + } + else if (c < 4) { + y = n >> 28; + n = e[i--]; + c = 4 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 28) & 0xf; + n <<= 4; + c -= 4; + } + + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + + sp_2048_mont_mul_64(r, r, t[y], m, mp); + } + y = e[0] & ((1 << c) - 1); + for (; c > 0; c--) + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_mul_64(r, r, t[y], m, mp); + + XMEMSET(&r[64], 0, sizeof(sp_digit) * 64); + sp_2048_mont_reduce_64(r, m, mp); + + mask = 0 - (sp_2048_cmp_64(r, m) >= 0); + sp_2048_cond_sub_64(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#else +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_2048_mod_exp_64(sp_digit* r, sp_digit* a, sp_digit* e, + int bits, sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][128]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 128, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<32; i++) + t[i] = td + i * 128; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_64(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 64); + if (reduceA) { + err = sp_2048_mod_64(t[1] + 64, a, m); + if (err == MP_OKAY) + err = sp_2048_mod_64(t[1], t[1], m); + } + else { + XMEMCPY(t[1] + 64, a, sizeof(sp_digit) * 64); + err = sp_2048_mod_64(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_2048_mont_sqr_64(t[ 2], t[ 1], m, mp); + sp_2048_mont_mul_64(t[ 3], t[ 2], t[ 1], m, mp); + sp_2048_mont_sqr_64(t[ 4], t[ 2], m, mp); + sp_2048_mont_mul_64(t[ 5], t[ 3], t[ 2], m, mp); + sp_2048_mont_sqr_64(t[ 6], t[ 3], m, mp); + sp_2048_mont_mul_64(t[ 7], t[ 4], t[ 3], m, mp); + sp_2048_mont_sqr_64(t[ 8], t[ 4], m, mp); + sp_2048_mont_mul_64(t[ 9], t[ 5], t[ 4], m, mp); + sp_2048_mont_sqr_64(t[10], t[ 5], m, mp); + sp_2048_mont_mul_64(t[11], t[ 6], t[ 5], m, mp); + sp_2048_mont_sqr_64(t[12], t[ 6], m, mp); + sp_2048_mont_mul_64(t[13], t[ 7], t[ 6], m, mp); + sp_2048_mont_sqr_64(t[14], t[ 7], m, mp); + sp_2048_mont_mul_64(t[15], t[ 8], t[ 7], m, mp); + sp_2048_mont_sqr_64(t[16], t[ 8], m, mp); + sp_2048_mont_mul_64(t[17], t[ 9], t[ 8], m, mp); + sp_2048_mont_sqr_64(t[18], t[ 9], m, mp); + sp_2048_mont_mul_64(t[19], t[10], t[ 9], m, mp); + sp_2048_mont_sqr_64(t[20], t[10], m, mp); + sp_2048_mont_mul_64(t[21], t[11], t[10], m, mp); + sp_2048_mont_sqr_64(t[22], t[11], m, mp); + sp_2048_mont_mul_64(t[23], t[12], t[11], m, mp); + sp_2048_mont_sqr_64(t[24], t[12], m, mp); + sp_2048_mont_mul_64(t[25], t[13], t[12], m, mp); + sp_2048_mont_sqr_64(t[26], t[13], m, mp); + sp_2048_mont_mul_64(t[27], t[14], t[13], m, mp); + sp_2048_mont_sqr_64(t[28], t[14], m, mp); + sp_2048_mont_mul_64(t[29], t[15], t[14], m, mp); + sp_2048_mont_sqr_64(t[30], t[15], m, mp); + sp_2048_mont_mul_64(t[31], t[16], t[15], m, mp); + + i = (bits - 1) / 32; + n = e[i--]; + y = n >> 27; + n <<= 5; + c = 27; + XMEMCPY(r, t[y], sizeof(sp_digit) * 64); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 27; + n <<= 5; + c = 27; + } + else if (c < 5) { + y = n >> 27; + n = e[i--]; + c = 5 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 27) & 0x1f; + n <<= 5; + c -= 5; + } + + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + + sp_2048_mont_mul_64(r, r, t[y], m, mp); + } + y = e[0] & ((1 << c) - 1); + for (; c > 0; c--) + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_mul_64(r, r, t[y], m, mp); + + XMEMSET(&r[64], 0, sizeof(sp_digit) * 64); + sp_2048_mont_reduce_64(r, m, mp); + + mask = 0 - (sp_2048_cmp_64(r, m) >= 0); + sp_2048_cond_sub_64(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#endif /* WOLFSSL_SP_SMALL */ +#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ + +#ifdef WOLFSSL_HAVE_SP_RSA +/* RSA public key operation. + * + * in Array of bytes representing the number to exponentiate, base. + * inLen Number of bytes in base. + * em Public exponent. + * mm Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 256 bytes long. + * outLen Number of bytes in result. + * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when + * an array is too long and MEMORY_E when dynamic memory allocation fails. + */ +int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm, + byte* out, word32* outLen) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit ad[128], md[64], rd[128]; +#else + sp_digit* d = NULL; +#endif + sp_digit* a; + sp_digit *ah; + sp_digit* m; + sp_digit* r; + sp_digit e[1]; + int err = MP_OKAY; + + if (*outLen < 256) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(em) > 32 || inLen > 256 || + mp_count_bits(mm) != 2048)) + err = MP_READ_E; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 64 * 5, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + a = d; + r = a + 64 * 2; + m = r + 64 * 2; + ah = a + 64; + } +#else + a = ad; + m = md; + r = rd; + ah = a + 64; +#endif + + if (err == MP_OKAY) { + sp_2048_from_bin(ah, 64, in, inLen); +#if DIGIT_BIT >= 32 + e[0] = em->dp[0]; +#else + e[0] = em->dp[0]; + if (em->used > 1) + e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT; +#endif + if (e[0] == 0) + err = MP_EXPTMOD_E; + } + if (err == MP_OKAY) { + sp_2048_from_mp(m, 64, mm); + + if (e[0] == 0x3) { + if (err == MP_OKAY) { + sp_2048_sqr_64(r, ah); + err = sp_2048_mod_64_cond(r, r, m); + } + if (err == MP_OKAY) { + sp_2048_mul_64(r, ah, r); + err = sp_2048_mod_64_cond(r, r, m); + } + } + else { + int i; + sp_digit mp; + + sp_2048_mont_setup(m, &mp); + + /* Convert to Montgomery form. */ + XMEMSET(a, 0, sizeof(sp_digit) * 64); + err = sp_2048_mod_64_cond(a, a, m); + + if (err == MP_OKAY) { + for (i=31; i>=0; i--) + if (e[0] >> i) + break; + + XMEMCPY(r, a, sizeof(sp_digit) * 64); + for (i--; i>=0; i--) { + sp_2048_mont_sqr_64(r, r, m, mp); + if (((e[0] >> i) & 1) == 1) + sp_2048_mont_mul_64(r, r, a, m, mp); + } + XMEMSET(&r[64], 0, sizeof(sp_digit) * 64); + sp_2048_mont_reduce_64(r, m, mp); + + for (i = 63; i > 0; i--) { + if (r[i] != m[i]) + break; + } + if (r[i] >= m[i]) + sp_2048_sub_in_place_64(r, m); + } + } + } + + if (err == MP_OKAY) { + sp_2048_to_bin(r, out); + *outLen = 256; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_RSA); +#endif + + return err; +} + +/* RSA private key operation. + * + * in Array of bytes representing the number to exponentiate, base. + * inLen Number of bytes in base. + * dm Private exponent. + * pm First prime. + * qm Second prime. + * dpm First prime's CRT exponent. + * dqm Second prime's CRT exponent. + * qim Inverse of second prime mod p. + * mm Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 256 bytes long. + * outLen Number of bytes in result. + * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when + * an array is too long and MEMORY_E when dynamic memory allocation fails. + */ +int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, + mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm, + byte* out, word32* outLen) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit ad[64 * 2]; + sp_digit pd[32], qd[32], dpd[32]; + sp_digit tmpad[64], tmpbd[64]; +#else + sp_digit* t = NULL; +#endif + sp_digit* a; + sp_digit* p; + sp_digit* q; + sp_digit* dp; + sp_digit* dq; + sp_digit* qi; + sp_digit* tmp; + sp_digit* tmpa; + sp_digit* tmpb; + sp_digit* r; + sp_digit c; + int err = MP_OKAY; + + (void)dm; + (void)mm; + + if (*outLen < 256) + err = MP_TO_E; + if (err == MP_OKAY && (inLen > 256 || mp_count_bits(mm) != 2048)) + err = MP_READ_E; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 11, NULL, + DYNAMIC_TYPE_RSA); + if (t == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + a = t; + p = a + 64 * 2; + q = p + 32; + qi = dq = dp = q + 32; + tmpa = qi + 32; + tmpb = tmpa + 64; + + tmp = t; + r = tmp + 64; + } +#else + r = a = ad; + p = pd; + q = qd; + qi = dq = dp = dpd; + tmpa = tmpad; + tmpb = tmpbd; + tmp = a + 64; +#endif + + if (err == MP_OKAY) { + sp_2048_from_bin(a, 64, in, inLen); + sp_2048_from_mp(p, 32, pm); + sp_2048_from_mp(q, 32, qm); + sp_2048_from_mp(dp, 32, dpm); + + err = sp_2048_mod_exp_32(tmpa, a, dp, 1024, p, 1); + } + if (err == MP_OKAY) { + sp_2048_from_mp(dq, 32, dqm); + err = sp_2048_mod_exp_32(tmpb, a, dq, 1024, q, 1); + } + + if (err == MP_OKAY) { + c = sp_2048_sub_in_place_32(tmpa, tmpb); + sp_2048_mask_32(tmp, p, c); + sp_2048_add_32(tmpa, tmpa, tmp); + + sp_2048_from_mp(qi, 32, qim); + sp_2048_mul_32(tmpa, tmpa, qi); + err = sp_2048_mod_32(tmpa, tmpa, p); + } + + if (err == MP_OKAY) { + sp_2048_mul_32(tmpa, q, tmpa); + XMEMSET(&tmpb[32], 0, sizeof(sp_digit) * 32); + sp_2048_add_64(r, tmpb, tmpa); + + sp_2048_to_bin(r, out); + *outLen = 256; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_digit) * 32 * 11); + XFREE(t, NULL, DYNAMIC_TYPE_RSA); + } +#else + XMEMSET(tmpad, 0, sizeof(tmpad)); + XMEMSET(tmpbd, 0, sizeof(tmpbd)); + XMEMSET(pd, 0, sizeof(pd)); + XMEMSET(qd, 0, sizeof(qd)); + XMEMSET(dpd, 0, sizeof(dpd)); +#endif + + return err; +} +#endif /* WOLFSSL_HAVE_SP_RSA */ +#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \ + !defined(WOLFSSL_RSA_PUBLIC_ONLY)) +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_2048_to_mp(sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (2048 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { +#if DIGIT_BIT == 32 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 64); + r->used = 64; + mp_clamp(r); +#elif DIGIT_BIT < 32 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 64; i++) { + r->dp[j] |= a[i] << s; + r->dp[j] &= (1l << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + while (s + DIGIT_BIT <= 32) { + s += DIGIT_BIT; + r->dp[j] &= (1l << DIGIT_BIT) - 1; + r->dp[++j] = a[i] >> s; + } + s = 32 - s; + } + r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 64; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 32 >= DIGIT_BIT) { + #if DIGIT_BIT < 32 + r->dp[j] &= (1l << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 32 - s; + } + else + s += 32; + } + r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returs 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ + int err = MP_OKAY; + sp_digit b[128], e[64], m[64]; + sp_digit* r = b; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 2048 || expBits > 2048 || + mp_count_bits(mod) != 2048) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + sp_2048_from_mp(b, 64, base); + sp_2048_from_mp(e, 64, exp); + sp_2048_from_mp(m, 64, mod); + + err = sp_2048_mod_exp_64(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + err = sp_2048_to_mp(r, res); + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} + +#ifdef WOLFSSL_HAVE_SP_DH +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. + * exp Array of bytes that is the exponent. + * expLen Length of data, in bytes, in exponent. + * mod Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 256 bytes long. + * outLen Length, in bytes, of exponentiation result. + * returs 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen, + mp_int* mod, byte* out, word32* outLen) +{ + int err = MP_OKAY; + sp_digit b[128], e[64], m[64]; + sp_digit* r = b; + word32 i; + + if (mp_count_bits(base) > 2048 || expLen > 256 || + mp_count_bits(mod) != 2048) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + sp_2048_from_mp(b, 64, base); + sp_2048_from_bin(e, 64, exp, expLen); + sp_2048_from_mp(m, 64, mod); + + err = sp_2048_mod_exp_64(r, b, e, expLen * 8, m, 0); + } + + if (err == MP_OKAY) { + sp_2048_to_bin(r, out); + *outLen = 256; + for (i=0; i<256 && out[i] == 0; i++) { + } + *outLen -= i; + XMEMMOVE(out, out + i, *outLen); + + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} +#endif /* WOLFSSL_HAVE_SP_DH */ + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returs 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ + int err = MP_OKAY; + sp_digit b[64], e[32], m[32]; + sp_digit* r = b; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 1024 || expBits > 1024 || + mp_count_bits(mod) != 1024) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + sp_2048_from_mp(b, 32, base); + sp_2048_from_mp(e, 32, exp); + sp_2048_from_mp(m, 32, mod); + + err = sp_2048_mod_exp_32(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + XMEMSET(r + 32, 0, sizeof(*r) * 32); + err = sp_2048_to_mp(r, res); + res->used = mod->used; + mp_clamp(res); + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} + +#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ + +#endif /* !WOLFSSL_SP_NO_2048 */ + +#ifndef WOLFSSL_SP_NO_3072 +/* Read big endian unsigned byte aray into r. + * + * r A single precision integer. + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_3072_from_bin(sp_digit* r, int max, const byte* a, int n) +{ + int i, j = 0, s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= ((sp_digit)a[i]) << s; + if (s >= 24) { + r[j] &= 0xffffffff; + s = 32 - s; + if (j + 1 >= max) + break; + r[++j] = a[i] >> s; + s = 8 - s; + } + else + s += 8; + } + + for (j++; j < max; j++) + r[j] = 0; +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * a A multi-precision integer. + */ +static void sp_3072_from_mp(sp_digit* r, int max, mp_int* a) +{ +#if DIGIT_BIT == 32 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < max; j++) + r[j] = 0; +#elif DIGIT_BIT > 32 + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= a->dp[i] << s; + r[j] &= 0xffffffff; + s = 32 - s; + if (j + 1 >= max) + break; + r[++j] = a->dp[i] >> s; + while (s + 32 <= DIGIT_BIT) { + s += 32; + r[j] &= 0xffffffff; + if (j + 1 >= max) + break; + if (s < DIGIT_BIT) + r[++j] = a->dp[i] >> s; + else + r[++j] = 0; + } + s = DIGIT_BIT - s; + } + + for (j++; j < max; j++) + r[j] = 0; +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 32) { + r[j] &= 0xffffffff; + if (j + 1 >= max) + break; + s = 32 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else + s += DIGIT_BIT; + } + + for (j++; j < max; j++) + r[j] = 0; +#endif +} + +/* Write r as big endian to byte aray. + * Fixed length number of bytes written: 384 + * + * r A single precision integer. + * a Byte array. + */ +static void sp_3072_to_bin(sp_digit* r, byte* a) +{ + int i, j, s = 0, b; + + j = 3072 / 8 - 1; + a[j] = 0; + for (i=0; i<96 && j>=0; i++) { + b = 0; + a[j--] |= r[i] << s; b += 8 - s; + if (j < 0) + break; + while (b < 32) { + a[j--] = r[i] >> b; b += 8; + if (j < 0) + break; + } + s = 8 - (b - 32); + if (j >= 0) + a[j] = 0; + if (s != 0) + j++; + } +} + +#ifndef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_3072_mul_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit tmp[8 * 2]; + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r8, r3\n\t" + "mov r11, %[r]\n\t" + "mov r9, %[a]\n\t" + "mov r10, %[b]\n\t" + "mov r6, #32\n\t" + "add r6, r9\n\t" + "mov r12, r6\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r5, #0\n\t" + "mov r6, #28\n\t" + "mov %[a], r8\n\t" + "sub %[a], r6\n\t" + "sbc r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], r6\n\t" + "mov %[b], r8\n\t" + "sub %[b], %[a]\n\t" + "add %[a], r9\n\t" + "add %[b], r10\n\t" + "\n2:\n\t" + "# Multiply Start\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [%[b]]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [%[b]]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [%[b]]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [%[b]]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Multiply Done\n\t" + "add %[a], #4\n\t" + "sub %[b], #4\n\t" + "cmp %[a], r12\n\t" + "beq 3f\n\t" + "mov r6, r8\n\t" + "add r6, r9\n\t" + "cmp %[a], r6\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r11\n\t" + "mov r7, r8\n\t" + "str r3, [%[r], r7]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "add r7, #4\n\t" + "mov r8, r7\n\t" + "mov r6, #56\n\t" + "cmp r7, r6\n\t" + "ble 1b\n\t" + "str r3, [%[r], r7]\n\t" + "mov %[a], r9\n\t" + "mov %[b], r10\n\t" + : + : [r] "r" (tmp), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_3072_sqr_8(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r5, #0\n\t" + "mov r8, r3\n\t" + "mov r11, %[r]\n\t" + "mov r6, #64\n\t" + "neg r6, r6\n\t" + "add sp, r6\n\t" + "mov r10, sp\n\t" + "mov r9, %[a]\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r6, #28\n\t" + "mov %[a], r8\n\t" + "sub %[a], r6\n\t" + "sbc r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], r6\n\t" + "mov r2, r8\n\t" + "sub r2, %[a]\n\t" + "add %[a], r9\n\t" + "add r2, r9\n\t" + "\n2:\n\t" + "cmp r2, %[a]\n\t" + "beq 4f\n\t" + "# Multiply * 2: Start\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [r2]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [r2]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [r2]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [r2]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Multiply * 2: Done\n\t" + "bal 5f\n\t" + "\n4:\n\t" + "# Square: Start\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "lsr r6, r6, #16\n\t" + "mul r6, r6\n\t" + "add r3, r6\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "mul r7, r7\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "lsr r6, r6, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #15\n\t" + "lsl r6, r6, #17\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Square: Done\n\t" + "\n5:\n\t" + "add %[a], #4\n\t" + "sub r2, #4\n\t" + "mov r6, #32\n\t" + "add r6, r9\n\t" + "cmp %[a], r6\n\t" + "beq 3f\n\t" + "cmp %[a], r2\n\t" + "bgt 3f\n\t" + "mov r7, r8\n\t" + "add r7, r9\n\t" + "cmp %[a], r7\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r10\n\t" + "mov r7, r8\n\t" + "str r3, [%[r], r7]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "add r7, #4\n\t" + "mov r8, r7\n\t" + "mov r6, #56\n\t" + "cmp r7, r6\n\t" + "ble 1b\n\t" + "mov %[a], r9\n\t" + "str r3, [%[r], r7]\n\t" + "mov %[r], r11\n\t" + "mov %[a], r10\n\t" + "mov r3, #60\n\t" + "\n4:\n\t" + "ldr r6, [%[a], r3]\n\t" + "str r6, [%[r], r3]\n\t" + "sub r3, #4\n\t" + "bge 4b\n\t" + "mov r6, #64\n\t" + "add sp, r6\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11" + ); +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_3072_add_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "add r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5" + ); + + return c; +} + +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_3072_sub_in_place_16(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sub r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #0]\n\t" + "str r4, [%[a], #4]\n\t" + "ldr r3, [%[a], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r6, [%[b], #12]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #8]\n\t" + "str r4, [%[a], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r6, [%[b], #20]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #16]\n\t" + "str r4, [%[a], #20]\n\t" + "ldr r3, [%[a], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r6, [%[b], #28]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #24]\n\t" + "str r4, [%[a], #28]\n\t" + "ldr r3, [%[a], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r6, [%[b], #36]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #32]\n\t" + "str r4, [%[a], #36]\n\t" + "ldr r3, [%[a], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r6, [%[b], #44]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #40]\n\t" + "str r4, [%[a], #44]\n\t" + "ldr r3, [%[a], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #48]\n\t" + "ldr r6, [%[b], #52]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #48]\n\t" + "str r4, [%[a], #52]\n\t" + "ldr r3, [%[a], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #56]\n\t" + "ldr r6, [%[b], #60]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #56]\n\t" + "str r4, [%[a], #60]\n\t" + "sbc %[c], %[c]\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6" + ); + + return c; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_3072_add_16(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "add r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[b], #48]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #52]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[b], #56]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #60]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #60]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5" + ); + + return c; +} + +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_3072_mask_8(sp_digit* r, sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<8; i++) + r[i] = a[i] & m; +#else + r[0] = a[0] & m; + r[1] = a[1] & m; + r[2] = a[2] & m; + r[3] = a[3] & m; + r[4] = a[4] & m; + r[5] = a[5] & m; + r[6] = a[6] & m; + r[7] = a[7] & m; +#endif +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_3072_mul_16(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[16]; + sp_digit a1[8]; + sp_digit b1[8]; + sp_digit z2[16]; + sp_digit u, ca, cb; + + ca = sp_3072_add_8(a1, a, &a[8]); + cb = sp_3072_add_8(b1, b, &b[8]); + u = ca & cb; + sp_3072_mul_8(z1, a1, b1); + sp_3072_mul_8(z2, &a[8], &b[8]); + sp_3072_mul_8(z0, a, b); + sp_3072_mask_8(r + 16, a1, 0 - cb); + sp_3072_mask_8(b1, b1, 0 - ca); + u += sp_3072_add_8(r + 16, r + 16, b1); + u += sp_3072_sub_in_place_16(z1, z2); + u += sp_3072_sub_in_place_16(z1, z0); + u += sp_3072_add_16(r + 8, r + 8, z1); + r[24] = u; + XMEMSET(r + 24 + 1, 0, sizeof(sp_digit) * (8 - 1)); + sp_3072_add_16(r + 16, r + 16, z2); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_3072_sqr_16(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z2[16]; + sp_digit z1[16]; + sp_digit a1[8]; + sp_digit u; + + u = sp_3072_add_8(a1, a, &a[8]); + sp_3072_sqr_8(z1, a1); + sp_3072_sqr_8(z2, &a[8]); + sp_3072_sqr_8(z0, a); + sp_3072_mask_8(r + 16, a1, 0 - u); + u += sp_3072_add_8(r + 16, r + 16, r + 16); + u += sp_3072_sub_in_place_16(z1, z2); + u += sp_3072_sub_in_place_16(z1, z0); + u += sp_3072_add_16(r + 8, r + 8, z1); + r[24] = u; + XMEMSET(r + 24 + 1, 0, sizeof(sp_digit) * (8 - 1)); + sp_3072_add_16(r + 16, r + 16, z2); +} + +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_3072_sub_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[a], #4]\n\t" + "ldr r6, [%[b], #0]\n\t" + "ldr r7, [%[b], #4]\n\t" + "sub r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #0]\n\t" + "str r5, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[a], #12]\n\t" + "ldr r6, [%[b], #8]\n\t" + "ldr r7, [%[b], #12]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #8]\n\t" + "str r5, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[a], #20]\n\t" + "ldr r6, [%[b], #16]\n\t" + "ldr r7, [%[b], #20]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #16]\n\t" + "str r5, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[a], #28]\n\t" + "ldr r6, [%[b], #24]\n\t" + "ldr r7, [%[b], #28]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #24]\n\t" + "str r5, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[a], #36]\n\t" + "ldr r6, [%[b], #32]\n\t" + "ldr r7, [%[b], #36]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #32]\n\t" + "str r5, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[a], #44]\n\t" + "ldr r6, [%[b], #40]\n\t" + "ldr r7, [%[b], #44]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #40]\n\t" + "str r5, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[a], #52]\n\t" + "ldr r6, [%[b], #48]\n\t" + "ldr r7, [%[b], #52]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #48]\n\t" + "str r5, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[a], #60]\n\t" + "ldr r6, [%[b], #56]\n\t" + "ldr r7, [%[b], #60]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #56]\n\t" + "str r5, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[a], #68]\n\t" + "ldr r6, [%[b], #64]\n\t" + "ldr r7, [%[b], #68]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #64]\n\t" + "str r5, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[a], #76]\n\t" + "ldr r6, [%[b], #72]\n\t" + "ldr r7, [%[b], #76]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #72]\n\t" + "str r5, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[a], #84]\n\t" + "ldr r6, [%[b], #80]\n\t" + "ldr r7, [%[b], #84]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #80]\n\t" + "str r5, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[a], #92]\n\t" + "ldr r6, [%[b], #88]\n\t" + "ldr r7, [%[b], #92]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #88]\n\t" + "str r5, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[a], #100]\n\t" + "ldr r6, [%[b], #96]\n\t" + "ldr r7, [%[b], #100]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #96]\n\t" + "str r5, [%[r], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[a], #108]\n\t" + "ldr r6, [%[b], #104]\n\t" + "ldr r7, [%[b], #108]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #104]\n\t" + "str r5, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[a], #116]\n\t" + "ldr r6, [%[b], #112]\n\t" + "ldr r7, [%[b], #116]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #112]\n\t" + "str r5, [%[r], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[a], #124]\n\t" + "ldr r6, [%[b], #120]\n\t" + "ldr r7, [%[b], #124]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #120]\n\t" + "str r5, [%[r], #124]\n\t" + "sbc %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r7" + ); + + return c; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_3072_add_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "add r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[b], #48]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #52]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[b], #56]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #60]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[b], #64]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #68]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[b], #72]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #76]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[b], #80]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #84]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[b], #88]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #92]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[b], #96]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #100]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[b], #104]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #108]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[b], #112]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #116]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[b], #120]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #124]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #124]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5" + ); + + return c; +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_3072_mul_48(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit p0[32]; + sp_digit p1[32]; + sp_digit p2[32]; + sp_digit p3[32]; + sp_digit p4[32]; + sp_digit p5[32]; + sp_digit t0[32]; + sp_digit t1[32]; + sp_digit t2[32]; + sp_digit a0[16]; + sp_digit a1[16]; + sp_digit a2[16]; + sp_digit b0[16]; + sp_digit b1[16]; + sp_digit b2[16]; + sp_3072_add_16(a0, a, &a[16]); + sp_3072_add_16(b0, b, &b[16]); + sp_3072_add_16(a1, &a[16], &a[32]); + sp_3072_add_16(b1, &b[16], &b[32]); + sp_3072_add_16(a2, a0, &a[32]); + sp_3072_add_16(b2, b0, &b[32]); + sp_3072_mul_16(p0, a, b); + sp_3072_mul_16(p2, &a[16], &b[16]); + sp_3072_mul_16(p4, &a[32], &b[32]); + sp_3072_mul_16(p1, a0, b0); + sp_3072_mul_16(p3, a1, b1); + sp_3072_mul_16(p5, a2, b2); + XMEMSET(r, 0, sizeof(*r)*2*48); + sp_3072_sub_32(t0, p3, p2); + sp_3072_sub_32(t1, p1, p2); + sp_3072_sub_32(t2, p5, t0); + sp_3072_sub_32(t2, t2, t1); + sp_3072_sub_32(t0, t0, p4); + sp_3072_sub_32(t1, t1, p0); + sp_3072_add_32(r, r, p0); + sp_3072_add_32(&r[16], &r[16], t1); + sp_3072_add_32(&r[32], &r[32], t2); + sp_3072_add_32(&r[48], &r[48], t0); + sp_3072_add_32(&r[64], &r[64], p4); +} + +/* Square a into r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_3072_sqr_48(sp_digit* r, const sp_digit* a) +{ + sp_digit p0[32]; + sp_digit p1[32]; + sp_digit p2[32]; + sp_digit p3[32]; + sp_digit p4[32]; + sp_digit p5[32]; + sp_digit t0[32]; + sp_digit t1[32]; + sp_digit t2[32]; + sp_digit a0[16]; + sp_digit a1[16]; + sp_digit a2[16]; + sp_3072_add_16(a0, a, &a[16]); + sp_3072_add_16(a1, &a[16], &a[32]); + sp_3072_add_16(a2, a0, &a[32]); + sp_3072_sqr_16(p0, a); + sp_3072_sqr_16(p2, &a[16]); + sp_3072_sqr_16(p4, &a[32]); + sp_3072_sqr_16(p1, a0); + sp_3072_sqr_16(p3, a1); + sp_3072_sqr_16(p5, a2); + XMEMSET(r, 0, sizeof(*r)*2*48); + sp_3072_sub_32(t0, p3, p2); + sp_3072_sub_32(t1, p1, p2); + sp_3072_sub_32(t2, p5, t0); + sp_3072_sub_32(t2, t2, t1); + sp_3072_sub_32(t0, t0, p4); + sp_3072_sub_32(t1, t1, p0); + sp_3072_add_32(r, r, p0); + sp_3072_add_32(&r[16], &r[16], t1); + sp_3072_add_32(&r[32], &r[32], t2); + sp_3072_add_32(&r[48], &r[48], t0); + sp_3072_add_32(&r[64], &r[64], p4); +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_3072_add_48(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r7, #0\n\t" + "mvn r7, r7\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "add r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[b], #48]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #52]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[b], #56]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #60]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[b], #64]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #68]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[b], #72]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #76]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[b], #80]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #84]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[b], #88]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #92]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[b], #96]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #100]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[b], #104]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #108]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[b], #112]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #116]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[b], #120]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #124]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #124]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + "add %[a], #0x80\n\t" + "add %[b], #0x80\n\t" + "add %[r], #0x80\n\t" + "add %[c], r7\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[b], #48]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #52]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[b], #56]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #60]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #60]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r7" + ); + + return c; +} + +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_3072_sub_in_place_96(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sub r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #0]\n\t" + "str r4, [%[a], #4]\n\t" + "ldr r3, [%[a], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r6, [%[b], #12]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #8]\n\t" + "str r4, [%[a], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r6, [%[b], #20]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #16]\n\t" + "str r4, [%[a], #20]\n\t" + "ldr r3, [%[a], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r6, [%[b], #28]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #24]\n\t" + "str r4, [%[a], #28]\n\t" + "ldr r3, [%[a], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r6, [%[b], #36]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #32]\n\t" + "str r4, [%[a], #36]\n\t" + "ldr r3, [%[a], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r6, [%[b], #44]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #40]\n\t" + "str r4, [%[a], #44]\n\t" + "ldr r3, [%[a], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #48]\n\t" + "ldr r6, [%[b], #52]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #48]\n\t" + "str r4, [%[a], #52]\n\t" + "ldr r3, [%[a], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #56]\n\t" + "ldr r6, [%[b], #60]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #56]\n\t" + "str r4, [%[a], #60]\n\t" + "ldr r3, [%[a], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #64]\n\t" + "ldr r6, [%[b], #68]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #64]\n\t" + "str r4, [%[a], #68]\n\t" + "ldr r3, [%[a], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #72]\n\t" + "ldr r6, [%[b], #76]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #72]\n\t" + "str r4, [%[a], #76]\n\t" + "ldr r3, [%[a], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #80]\n\t" + "ldr r6, [%[b], #84]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #80]\n\t" + "str r4, [%[a], #84]\n\t" + "ldr r3, [%[a], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #88]\n\t" + "ldr r6, [%[b], #92]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #88]\n\t" + "str r4, [%[a], #92]\n\t" + "ldr r3, [%[a], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #96]\n\t" + "ldr r6, [%[b], #100]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #96]\n\t" + "str r4, [%[a], #100]\n\t" + "ldr r3, [%[a], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #104]\n\t" + "ldr r6, [%[b], #108]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #104]\n\t" + "str r4, [%[a], #108]\n\t" + "ldr r3, [%[a], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #112]\n\t" + "ldr r6, [%[b], #116]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #112]\n\t" + "str r4, [%[a], #116]\n\t" + "ldr r3, [%[a], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #120]\n\t" + "ldr r6, [%[b], #124]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #120]\n\t" + "str r4, [%[a], #124]\n\t" + "sbc %[c], %[c]\n\t" + "add %[a], #0x80\n\t" + "add %[b], #0x80\n\t" + "mov r5, #0\n\t" + "sub r5, %[c]\n\t" + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #0]\n\t" + "str r4, [%[a], #4]\n\t" + "ldr r3, [%[a], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r6, [%[b], #12]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #8]\n\t" + "str r4, [%[a], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r6, [%[b], #20]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #16]\n\t" + "str r4, [%[a], #20]\n\t" + "ldr r3, [%[a], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r6, [%[b], #28]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #24]\n\t" + "str r4, [%[a], #28]\n\t" + "ldr r3, [%[a], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r6, [%[b], #36]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #32]\n\t" + "str r4, [%[a], #36]\n\t" + "ldr r3, [%[a], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r6, [%[b], #44]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #40]\n\t" + "str r4, [%[a], #44]\n\t" + "ldr r3, [%[a], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #48]\n\t" + "ldr r6, [%[b], #52]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #48]\n\t" + "str r4, [%[a], #52]\n\t" + "ldr r3, [%[a], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #56]\n\t" + "ldr r6, [%[b], #60]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #56]\n\t" + "str r4, [%[a], #60]\n\t" + "ldr r3, [%[a], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #64]\n\t" + "ldr r6, [%[b], #68]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #64]\n\t" + "str r4, [%[a], #68]\n\t" + "ldr r3, [%[a], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #72]\n\t" + "ldr r6, [%[b], #76]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #72]\n\t" + "str r4, [%[a], #76]\n\t" + "ldr r3, [%[a], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #80]\n\t" + "ldr r6, [%[b], #84]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #80]\n\t" + "str r4, [%[a], #84]\n\t" + "ldr r3, [%[a], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #88]\n\t" + "ldr r6, [%[b], #92]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #88]\n\t" + "str r4, [%[a], #92]\n\t" + "ldr r3, [%[a], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #96]\n\t" + "ldr r6, [%[b], #100]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #96]\n\t" + "str r4, [%[a], #100]\n\t" + "ldr r3, [%[a], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #104]\n\t" + "ldr r6, [%[b], #108]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #104]\n\t" + "str r4, [%[a], #108]\n\t" + "ldr r3, [%[a], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #112]\n\t" + "ldr r6, [%[b], #116]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #112]\n\t" + "str r4, [%[a], #116]\n\t" + "ldr r3, [%[a], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #120]\n\t" + "ldr r6, [%[b], #124]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #120]\n\t" + "str r4, [%[a], #124]\n\t" + "sbc %[c], %[c]\n\t" + "add %[a], #0x80\n\t" + "add %[b], #0x80\n\t" + "mov r5, #0\n\t" + "sub r5, %[c]\n\t" + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #0]\n\t" + "str r4, [%[a], #4]\n\t" + "ldr r3, [%[a], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r6, [%[b], #12]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #8]\n\t" + "str r4, [%[a], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r6, [%[b], #20]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #16]\n\t" + "str r4, [%[a], #20]\n\t" + "ldr r3, [%[a], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r6, [%[b], #28]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #24]\n\t" + "str r4, [%[a], #28]\n\t" + "ldr r3, [%[a], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r6, [%[b], #36]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #32]\n\t" + "str r4, [%[a], #36]\n\t" + "ldr r3, [%[a], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r6, [%[b], #44]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #40]\n\t" + "str r4, [%[a], #44]\n\t" + "ldr r3, [%[a], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #48]\n\t" + "ldr r6, [%[b], #52]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #48]\n\t" + "str r4, [%[a], #52]\n\t" + "ldr r3, [%[a], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #56]\n\t" + "ldr r6, [%[b], #60]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #56]\n\t" + "str r4, [%[a], #60]\n\t" + "ldr r3, [%[a], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #64]\n\t" + "ldr r6, [%[b], #68]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #64]\n\t" + "str r4, [%[a], #68]\n\t" + "ldr r3, [%[a], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #72]\n\t" + "ldr r6, [%[b], #76]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #72]\n\t" + "str r4, [%[a], #76]\n\t" + "ldr r3, [%[a], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #80]\n\t" + "ldr r6, [%[b], #84]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #80]\n\t" + "str r4, [%[a], #84]\n\t" + "ldr r3, [%[a], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #88]\n\t" + "ldr r6, [%[b], #92]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #88]\n\t" + "str r4, [%[a], #92]\n\t" + "ldr r3, [%[a], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #96]\n\t" + "ldr r6, [%[b], #100]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #96]\n\t" + "str r4, [%[a], #100]\n\t" + "ldr r3, [%[a], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #104]\n\t" + "ldr r6, [%[b], #108]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #104]\n\t" + "str r4, [%[a], #108]\n\t" + "ldr r3, [%[a], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #112]\n\t" + "ldr r6, [%[b], #116]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #112]\n\t" + "str r4, [%[a], #116]\n\t" + "ldr r3, [%[a], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #120]\n\t" + "ldr r6, [%[b], #124]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #120]\n\t" + "str r4, [%[a], #124]\n\t" + "sbc %[c], %[c]\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6" + ); + + return c; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_3072_add_96(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r7, #0\n\t" + "mvn r7, r7\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "add r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[b], #48]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #52]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[b], #56]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #60]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[b], #64]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #68]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[b], #72]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #76]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[b], #80]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #84]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[b], #88]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #92]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[b], #96]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #100]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[b], #104]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #108]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[b], #112]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #116]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[b], #120]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #124]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #124]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + "add %[a], #0x80\n\t" + "add %[b], #0x80\n\t" + "add %[r], #0x80\n\t" + "add %[c], r7\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[b], #48]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #52]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[b], #56]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #60]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[b], #64]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #68]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[b], #72]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #76]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[b], #80]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #84]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[b], #88]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #92]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[b], #96]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #100]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[b], #104]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #108]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[b], #112]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #116]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[b], #120]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #124]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #124]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + "add %[a], #0x80\n\t" + "add %[b], #0x80\n\t" + "add %[r], #0x80\n\t" + "add %[c], r7\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[b], #48]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #52]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[b], #56]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #60]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[b], #64]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #68]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[b], #72]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #76]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[b], #80]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #84]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[b], #88]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #92]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[b], #96]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #100]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[b], #104]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #108]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[b], #112]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #116]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[b], #120]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #124]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #124]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r7" + ); + + return c; +} + +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_3072_mask_48(sp_digit* r, sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<48; i++) + r[i] = a[i] & m; +#else + int i; + + for (i = 0; i < 48; i += 8) { + r[i+0] = a[i+0] & m; + r[i+1] = a[i+1] & m; + r[i+2] = a[i+2] & m; + r[i+3] = a[i+3] & m; + r[i+4] = a[i+4] & m; + r[i+5] = a[i+5] & m; + r[i+6] = a[i+6] & m; + r[i+7] = a[i+7] & m; + } +#endif +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_3072_mul_96(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[96]; + sp_digit a1[48]; + sp_digit b1[48]; + sp_digit z2[96]; + sp_digit u, ca, cb; + + ca = sp_3072_add_48(a1, a, &a[48]); + cb = sp_3072_add_48(b1, b, &b[48]); + u = ca & cb; + sp_3072_mul_48(z1, a1, b1); + sp_3072_mul_48(z2, &a[48], &b[48]); + sp_3072_mul_48(z0, a, b); + sp_3072_mask_48(r + 96, a1, 0 - cb); + sp_3072_mask_48(b1, b1, 0 - ca); + u += sp_3072_add_48(r + 96, r + 96, b1); + u += sp_3072_sub_in_place_96(z1, z2); + u += sp_3072_sub_in_place_96(z1, z0); + u += sp_3072_add_96(r + 48, r + 48, z1); + r[144] = u; + XMEMSET(r + 144 + 1, 0, sizeof(sp_digit) * (48 - 1)); + sp_3072_add_96(r + 96, r + 96, z2); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_3072_sqr_96(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z2[96]; + sp_digit z1[96]; + sp_digit a1[48]; + sp_digit u; + + u = sp_3072_add_48(a1, a, &a[48]); + sp_3072_sqr_48(z1, a1); + sp_3072_sqr_48(z2, &a[48]); + sp_3072_sqr_48(z0, a); + sp_3072_mask_48(r + 96, a1, 0 - u); + u += sp_3072_add_48(r + 96, r + 96, r + 96); + u += sp_3072_sub_in_place_96(z1, z2); + u += sp_3072_sub_in_place_96(z1, z0); + u += sp_3072_add_96(r + 48, r + 48, z1); + r[144] = u; + XMEMSET(r + 144 + 1, 0, sizeof(sp_digit) * (48 - 1)); + sp_3072_add_96(r + 96, r + 96, z2); +} + +#endif /* !WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_3072_add_96(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r6, %[a]\n\t" + "mov r7, #0\n\t" + "mov r4, #1\n\t" + "lsl r4, #8\n\t" + "add r4, #128\n\t" + "sub r7, #1\n\t" + "add r6, r4\n\t" + "\n1:\n\t" + "add %[c], r7\n\t" + "ldr r4, [%[a]]\n\t" + "ldr r5, [%[b]]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r]]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + "add %[a], #4\n\t" + "add %[b], #4\n\t" + "add %[r], #4\n\t" + "cmp %[a], r6\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r7" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into a. (a -= b) + * + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_3072_sub_in_place_96(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + __asm__ __volatile__ ( + "mov r7, %[a]\n\t" + "mov r5, #1\n\t" + "lsl r5, #8\n\t" + "add r5, #128\n\t" + "add r7, r5\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "sub r5, %[c]\n\t" + "ldr r3, [%[a]]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b]]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a]]\n\t" + "str r4, [%[a], #4]\n\t" + "sbc %[c], %[c]\n\t" + "add %[a], #8\n\t" + "add %[b], #8\n\t" + "cmp %[a], r7\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6", "r7" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_3072_mul_96(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit tmp[96 * 2]; + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r8, r3\n\t" + "mov r11, %[r]\n\t" + "mov r9, %[a]\n\t" + "mov r10, %[b]\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, #128\n\t" + "add r6, r9\n\t" + "mov r12, r6\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r5, #0\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, #124\n\t" + "mov %[a], r8\n\t" + "sub %[a], r6\n\t" + "sbc r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], r6\n\t" + "mov %[b], r8\n\t" + "sub %[b], %[a]\n\t" + "add %[a], r9\n\t" + "add %[b], r10\n\t" + "\n2:\n\t" + "# Multiply Start\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [%[b]]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [%[b]]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [%[b]]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [%[b]]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Multiply Done\n\t" + "add %[a], #4\n\t" + "sub %[b], #4\n\t" + "cmp %[a], r12\n\t" + "beq 3f\n\t" + "mov r6, r8\n\t" + "add r6, r9\n\t" + "cmp %[a], r6\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r11\n\t" + "mov r7, r8\n\t" + "str r3, [%[r], r7]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "add r7, #4\n\t" + "mov r8, r7\n\t" + "mov r6, #2\n\t" + "lsl r6, r6, #8\n\t" + "add r6, #248\n\t" + "cmp r7, r6\n\t" + "ble 1b\n\t" + "str r3, [%[r], r7]\n\t" + "mov %[a], r9\n\t" + "mov %[b], r10\n\t" + : + : [r] "r" (tmp), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_3072_sqr_96(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r5, #0\n\t" + "mov r8, r3\n\t" + "mov r11, %[r]\n\t" + "mov r6, #3\n\t" + "lsl r6, r6, #8\n\t" + "neg r6, r6\n\t" + "add sp, r6\n\t" + "mov r10, sp\n\t" + "mov r9, %[a]\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, #124\n\t" + "mov %[a], r8\n\t" + "sub %[a], r6\n\t" + "sbc r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], r6\n\t" + "mov r2, r8\n\t" + "sub r2, %[a]\n\t" + "add %[a], r9\n\t" + "add r2, r9\n\t" + "\n2:\n\t" + "cmp r2, %[a]\n\t" + "beq 4f\n\t" + "# Multiply * 2: Start\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [r2]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [r2]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [r2]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [r2]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Multiply * 2: Done\n\t" + "bal 5f\n\t" + "\n4:\n\t" + "# Square: Start\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "lsr r6, r6, #16\n\t" + "mul r6, r6\n\t" + "add r3, r6\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "mul r7, r7\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "lsr r6, r6, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #15\n\t" + "lsl r6, r6, #17\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Square: Done\n\t" + "\n5:\n\t" + "add %[a], #4\n\t" + "sub r2, #4\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, #128\n\t" + "add r6, r9\n\t" + "cmp %[a], r6\n\t" + "beq 3f\n\t" + "cmp %[a], r2\n\t" + "bgt 3f\n\t" + "mov r7, r8\n\t" + "add r7, r9\n\t" + "cmp %[a], r7\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r10\n\t" + "mov r7, r8\n\t" + "str r3, [%[r], r7]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "add r7, #4\n\t" + "mov r8, r7\n\t" + "mov r6, #2\n\t" + "lsl r6, r6, #8\n\t" + "add r6, #248\n\t" + "cmp r7, r6\n\t" + "ble 1b\n\t" + "mov %[a], r9\n\t" + "str r3, [%[r], r7]\n\t" + "mov %[r], r11\n\t" + "mov %[a], r10\n\t" + "mov r3, #2\n\t" + "lsl r3, r3, #8\n\t" + "add r3, #252\n\t" + "\n4:\n\t" + "ldr r6, [%[a], r3]\n\t" + "str r6, [%[r], r3]\n\t" + "sub r3, #4\n\t" + "bge 4b\n\t" + "mov r6, #3\n\t" + "lsl r6, r6, #8\n\t" + "add sp, r6\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11" + ); +} + +#endif /* WOLFSSL_SP_SMALL */ +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +#ifdef WOLFSSL_SP_SMALL +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_3072_mask_48(sp_digit* r, sp_digit* a, sp_digit m) +{ + int i; + + for (i=0; i<48; i++) + r[i] = a[i] & m; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_3072_add_48(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r6, %[a]\n\t" + "mov r7, #0\n\t" + "add r6, #192\n\t" + "sub r7, #1\n\t" + "\n1:\n\t" + "add %[c], r7\n\t" + "ldr r4, [%[a]]\n\t" + "ldr r5, [%[b]]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r]]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + "add %[a], #4\n\t" + "add %[b], #4\n\t" + "add %[r], #4\n\t" + "cmp %[a], r6\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r7" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_3072_mul_48(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit tmp[48 * 2]; + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r8, r3\n\t" + "mov r11, %[r]\n\t" + "mov r9, %[a]\n\t" + "mov r10, %[b]\n\t" + "mov r6, #192\n\t" + "add r6, r9\n\t" + "mov r12, r6\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r5, #0\n\t" + "mov r6, #188\n\t" + "mov %[a], r8\n\t" + "sub %[a], r6\n\t" + "sbc r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], r6\n\t" + "mov %[b], r8\n\t" + "sub %[b], %[a]\n\t" + "add %[a], r9\n\t" + "add %[b], r10\n\t" + "\n2:\n\t" + "# Multiply Start\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [%[b]]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [%[b]]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [%[b]]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [%[b]]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Multiply Done\n\t" + "add %[a], #4\n\t" + "sub %[b], #4\n\t" + "cmp %[a], r12\n\t" + "beq 3f\n\t" + "mov r6, r8\n\t" + "add r6, r9\n\t" + "cmp %[a], r6\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r11\n\t" + "mov r7, r8\n\t" + "str r3, [%[r], r7]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "add r7, #4\n\t" + "mov r8, r7\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, #120\n\t" + "cmp r7, r6\n\t" + "ble 1b\n\t" + "str r3, [%[r], r7]\n\t" + "mov %[a], r9\n\t" + "mov %[b], r10\n\t" + : + : [r] "r" (tmp), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_3072_sqr_48(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r5, #0\n\t" + "mov r8, r3\n\t" + "mov r11, %[r]\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, #128\n\t" + "neg r6, r6\n\t" + "add sp, r6\n\t" + "mov r10, sp\n\t" + "mov r9, %[a]\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r6, #188\n\t" + "mov %[a], r8\n\t" + "sub %[a], r6\n\t" + "sbc r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], r6\n\t" + "mov r2, r8\n\t" + "sub r2, %[a]\n\t" + "add %[a], r9\n\t" + "add r2, r9\n\t" + "\n2:\n\t" + "cmp r2, %[a]\n\t" + "beq 4f\n\t" + "# Multiply * 2: Start\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [r2]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [r2]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [r2]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [r2]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Multiply * 2: Done\n\t" + "bal 5f\n\t" + "\n4:\n\t" + "# Square: Start\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "lsr r6, r6, #16\n\t" + "mul r6, r6\n\t" + "add r3, r6\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "mul r7, r7\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "lsr r6, r6, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #15\n\t" + "lsl r6, r6, #17\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Square: Done\n\t" + "\n5:\n\t" + "add %[a], #4\n\t" + "sub r2, #4\n\t" + "mov r6, #192\n\t" + "add r6, r9\n\t" + "cmp %[a], r6\n\t" + "beq 3f\n\t" + "cmp %[a], r2\n\t" + "bgt 3f\n\t" + "mov r7, r8\n\t" + "add r7, r9\n\t" + "cmp %[a], r7\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r10\n\t" + "mov r7, r8\n\t" + "str r3, [%[r], r7]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "add r7, #4\n\t" + "mov r8, r7\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, #120\n\t" + "cmp r7, r6\n\t" + "ble 1b\n\t" + "mov %[a], r9\n\t" + "str r3, [%[r], r7]\n\t" + "mov %[r], r11\n\t" + "mov %[a], r10\n\t" + "mov r3, #1\n\t" + "lsl r3, r3, #8\n\t" + "add r3, #124\n\t" + "\n4:\n\t" + "ldr r6, [%[a], r3]\n\t" + "str r6, [%[r], r3]\n\t" + "sub r3, #4\n\t" + "bge 4b\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, #128\n\t" + "add sp, r6\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11" + ); +} + +#endif /* WOLFSSL_SP_SMALL */ +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +/* Caclulate the bottom digit of -1/a mod 2^n. + * + * a A single precision number. + * rho Bottom word of inverse. + */ +static void sp_3072_mont_setup(sp_digit* a, sp_digit* rho) +{ + sp_digit x, b; + + b = a[0]; + x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ + x *= 2 - b * x; /* here x*a==1 mod 2**8 */ + x *= 2 - b * x; /* here x*a==1 mod 2**16 */ + x *= 2 - b * x; /* here x*a==1 mod 2**32 */ + + /* rho = -1/m mod b */ + *rho = -x; +} + +/* Mul a by digit b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision digit. + */ +SP_NOINLINE static void sp_3072_mul_d_96(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ + __asm__ __volatile__ ( + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, #128\n\t" + "add r6, %[a]\n\t" + "mov r8, %[r]\n\t" + "mov r9, r6\n\t" + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "1:\n\t" + "mov %[r], #0\n\t" + "mov r5, #0\n\t" + "# A[] * B\n\t" + "ldr r6, [%[a]]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, %[b], #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "lsr r7, %[b], #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, %[b], #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "lsl r7, %[b], #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# A[] * B - Done\n\t" + "mov %[r], r8\n\t" + "str r3, [%[r]]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "add %[r], #4\n\t" + "add %[a], #4\n\t" + "mov r8, %[r]\n\t" + "cmp %[a], r9\n\t" + "blt 1b\n\t" + "str r3, [%[r]]\n\t" + : [r] "+r" (r), [a] "+r" (a) + : [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9" + ); +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into a. (a -= b) + * + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_3072_sub_in_place_48(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + __asm__ __volatile__ ( + "mov r7, %[a]\n\t" + "add r7, #192\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "sub r5, %[c]\n\t" + "ldr r3, [%[a]]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b]]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a]]\n\t" + "str r4, [%[a], #4]\n\t" + "sbc %[c], %[c]\n\t" + "add %[a], #8\n\t" + "add %[b], #8\n\t" + "cmp %[a], r7\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6", "r7" + ); + + return c; +} + +#else +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_3072_sub_in_place_48(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sub r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #0]\n\t" + "str r4, [%[a], #4]\n\t" + "ldr r3, [%[a], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r6, [%[b], #12]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #8]\n\t" + "str r4, [%[a], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r6, [%[b], #20]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #16]\n\t" + "str r4, [%[a], #20]\n\t" + "ldr r3, [%[a], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r6, [%[b], #28]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #24]\n\t" + "str r4, [%[a], #28]\n\t" + "ldr r3, [%[a], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r6, [%[b], #36]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #32]\n\t" + "str r4, [%[a], #36]\n\t" + "ldr r3, [%[a], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r6, [%[b], #44]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #40]\n\t" + "str r4, [%[a], #44]\n\t" + "ldr r3, [%[a], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #48]\n\t" + "ldr r6, [%[b], #52]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #48]\n\t" + "str r4, [%[a], #52]\n\t" + "ldr r3, [%[a], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #56]\n\t" + "ldr r6, [%[b], #60]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #56]\n\t" + "str r4, [%[a], #60]\n\t" + "ldr r3, [%[a], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #64]\n\t" + "ldr r6, [%[b], #68]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #64]\n\t" + "str r4, [%[a], #68]\n\t" + "ldr r3, [%[a], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #72]\n\t" + "ldr r6, [%[b], #76]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #72]\n\t" + "str r4, [%[a], #76]\n\t" + "ldr r3, [%[a], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #80]\n\t" + "ldr r6, [%[b], #84]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #80]\n\t" + "str r4, [%[a], #84]\n\t" + "ldr r3, [%[a], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #88]\n\t" + "ldr r6, [%[b], #92]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #88]\n\t" + "str r4, [%[a], #92]\n\t" + "ldr r3, [%[a], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #96]\n\t" + "ldr r6, [%[b], #100]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #96]\n\t" + "str r4, [%[a], #100]\n\t" + "ldr r3, [%[a], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #104]\n\t" + "ldr r6, [%[b], #108]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #104]\n\t" + "str r4, [%[a], #108]\n\t" + "ldr r3, [%[a], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #112]\n\t" + "ldr r6, [%[b], #116]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #112]\n\t" + "str r4, [%[a], #116]\n\t" + "ldr r3, [%[a], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #120]\n\t" + "ldr r6, [%[b], #124]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #120]\n\t" + "str r4, [%[a], #124]\n\t" + "sbc %[c], %[c]\n\t" + "add %[a], #0x80\n\t" + "add %[b], #0x80\n\t" + "mov r5, #0\n\t" + "sub r5, %[c]\n\t" + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #0]\n\t" + "str r4, [%[a], #4]\n\t" + "ldr r3, [%[a], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r6, [%[b], #12]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #8]\n\t" + "str r4, [%[a], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r6, [%[b], #20]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #16]\n\t" + "str r4, [%[a], #20]\n\t" + "ldr r3, [%[a], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r6, [%[b], #28]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #24]\n\t" + "str r4, [%[a], #28]\n\t" + "ldr r3, [%[a], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r6, [%[b], #36]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #32]\n\t" + "str r4, [%[a], #36]\n\t" + "ldr r3, [%[a], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r6, [%[b], #44]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #40]\n\t" + "str r4, [%[a], #44]\n\t" + "ldr r3, [%[a], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #48]\n\t" + "ldr r6, [%[b], #52]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #48]\n\t" + "str r4, [%[a], #52]\n\t" + "ldr r3, [%[a], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #56]\n\t" + "ldr r6, [%[b], #60]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #56]\n\t" + "str r4, [%[a], #60]\n\t" + "sbc %[c], %[c]\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* r = 2^n mod m where n is the number of bits to reduce by. + * Given m must be 3072 bits, just need to subtract. + * + * r A single precision number. + * m A signle precision number. + */ +static void sp_3072_mont_norm_48(sp_digit* r, sp_digit* m) +{ + XMEMSET(r, 0, sizeof(sp_digit) * 48); + + /* r = 2^n mod m */ + sp_3072_sub_in_place_48(r, m); +} + +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not copying. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +SP_NOINLINE static sp_digit sp_3072_cond_sub_48(sp_digit* r, sp_digit* a, + sp_digit* b, sp_digit m) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r5, #192\n\t" + "mov r8, r5\n\t" + "mov r7, #0\n\t" + "1:\n\t" + "ldr r6, [%[b], r7]\n\t" + "and r6, %[m]\n\t" + "mov r5, #0\n\t" + "sub r5, %[c]\n\t" + "ldr r5, [%[a], r7]\n\t" + "sbc r5, r6\n\t" + "sbc %[c], %[c]\n\t" + "str r5, [%[r], r7]\n\t" + "add r7, #4\n\t" + "cmp r7, r8\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r5", "r6", "r7", "r8" + ); + + return c; +} + +/* Reduce the number back to 3072 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "mov r8, %[mp]\n\t" + "mov r12, %[ca]\n\t" + "mov r14, %[m]\n\t" + "mov r9, %[a]\n\t" + "mov r4, #0\n\t" + "# i = 0\n\t" + "mov r11, r4\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "mov %[ca], #0\n\t" + "# mu = a[i] * mp\n\t" + "mov %[mp], r8\n\t" + "ldr %[a], [%[a]]\n\t" + "mul %[mp], %[a]\n\t" + "mov %[m], r14\n\t" + "mov r10, r9\n\t" + "\n2:\n\t" + "# a[i+j] += m[j] * mu\n\t" + "mov %[a], r10\n\t" + "ldr %[a], [%[a]]\n\t" + "mov %[ca], #0\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "# Multiply m[j] and mu - Start\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r6, %[mp], #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add %[a], r7\n\t" + "adc r5, %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add %[a], r6\n\t" + "adc r5, r7\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r6, %[mp], #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r5, r7\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add %[a], r6\n\t" + "adc r5, r7\n\t" + "# Multiply m[j] and mu - Done\n\t" + "add r4, %[a]\n\t" + "adc r5, %[ca]\n\t" + "mov %[a], r10\n\t" + "str r4, [%[a]]\n\t" + "mov r6, #4\n\t" + "add %[m], #4\n\t" + "add r10, r6\n\t" + "mov r4, #188\n\t" + "add r4, r9\n\t" + "cmp r10, r4\n\t" + "blt 2b\n\t" + "# a[i+47] += m[47] * mu\n\t" + "mov %[ca], #0\n\t" + "mov r4, r12\n\t" + "mov %[a], #0\n\t" + "# Multiply m[47] and mu - Start\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r6, %[mp], #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r5, r7\n\t" + "adc r4, %[ca]\n\t" + "adc %[a], %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r5, r6\n\t" + "adc r4, r7\n\t" + "adc %[a], %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r6, %[mp], #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc %[a], %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r5, r6\n\t" + "adc r4, r7\n\t" + "adc %[a], %[ca]\n\t" + "# Multiply m[47] and mu - Done\n\t" + "mov %[ca], %[a]\n\t" + "mov %[a], r10\n\t" + "ldr r7, [%[a], #4]\n\t" + "ldr %[a], [%[a]]\n\t" + "mov r6, #0\n\t" + "add r5, %[a]\n\t" + "adc r7, r4\n\t" + "adc %[ca], r6\n\t" + "mov %[a], r10\n\t" + "str r5, [%[a]]\n\t" + "str r7, [%[a], #4]\n\t" + "# i += 1\n\t" + "mov r6, #4\n\t" + "add r9, r6\n\t" + "add r11, r6\n\t" + "mov r12, %[ca]\n\t" + "mov %[a], r9\n\t" + "mov r4, #192\n\t" + "cmp r11, r4\n\t" + "blt 1b\n\t" + "mov %[m], r14\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14" + ); + + sp_3072_cond_sub_48(a - 48, a, m, (sp_digit)0 - ca); +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_3072_mont_mul_48(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_3072_mul_48(r, a, b); + sp_3072_mont_reduce_48(r, m, mp); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_3072_mont_sqr_48(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_3072_sqr_48(r, a); + sp_3072_mont_reduce_48(r, m, mp); +} + +/* Mul a by digit b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision digit. + */ +SP_NOINLINE static void sp_3072_mul_d_48(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ + __asm__ __volatile__ ( + "mov r6, #192\n\t" + "add r6, %[a]\n\t" + "mov r8, %[r]\n\t" + "mov r9, r6\n\t" + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "1:\n\t" + "mov %[r], #0\n\t" + "mov r5, #0\n\t" + "# A[] * B\n\t" + "ldr r6, [%[a]]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, %[b], #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "lsr r7, %[b], #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, %[b], #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "lsl r7, %[b], #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# A[] * B - Done\n\t" + "mov %[r], r8\n\t" + "str r3, [%[r]]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "add %[r], #4\n\t" + "add %[a], #4\n\t" + "mov r8, %[r]\n\t" + "cmp %[a], r9\n\t" + "blt 1b\n\t" + "str r3, [%[r]]\n\t" + : [r] "+r" (r), [a] "+r" (a) + : [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9" + ); +} + +/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) + * + * d1 The high order half of the number to divide. + * d0 The low order half of the number to divide. + * div The dividend. + * returns the result of the division. + * + * Note that this is an approximate div. It may give an answer 1 larger. + */ +SP_NOINLINE static sp_digit div_3072_word_48(sp_digit d1, sp_digit d0, + sp_digit div) +{ + sp_digit r = 0; + + __asm__ __volatile__ ( + "lsr r5, %[div], #1\n\t" + "add r5, #1\n\t" + "mov r8, %[d0]\n\t" + "mov r9, %[d1]\n\t" + "# Do top 32\n\t" + "mov r6, r5\n\t" + "sub r6, %[d1]\n\t" + "sbc r6, r6\n\t" + "add %[r], %[r]\n\t" + "sub %[r], r6\n\t" + "and r6, r5\n\t" + "sub %[d1], r6\n\t" + "# Next 30 bits\n\t" + "mov r4, #29\n\t" + "1:\n\t" + "lsl %[d0], %[d0], #1\n\t" + "adc %[d1], %[d1]\n\t" + "mov r6, r5\n\t" + "sub r6, %[d1]\n\t" + "sbc r6, r6\n\t" + "add %[r], %[r]\n\t" + "sub %[r], r6\n\t" + "and r6, r5\n\t" + "sub %[d1], r6\n\t" + "sub r4, #1\n\t" + "bpl 1b\n\t" + "mov r7, #0\n\t" + "add %[r], %[r]\n\t" + "add %[r], #1\n\t" + "# r * div - Start\n\t" + "lsl %[d1], %[r], #16\n\t" + "lsl r4, %[div], #16\n\t" + "lsr %[d1], %[d1], #16\n\t" + "lsr r4, r4, #16\n\t" + "mul r4, %[d1]\n\t" + "lsr r6, %[div], #16\n\t" + "mul %[d1], r6\n\t" + "lsr r5, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r7\n\t" + "lsr %[d1], %[r], #16\n\t" + "mul r6, %[d1]\n\t" + "add r5, r6\n\t" + "lsl r6, %[div], #16\n\t" + "lsr r6, r6, #16\n\t" + "mul %[d1], r6\n\t" + "lsr r6, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r6\n\t" + "# r * div - Done\n\t" + "mov %[d1], r8\n\t" + "sub %[d1], r4\n\t" + "mov r4, %[d1]\n\t" + "mov %[d1], r9\n\t" + "sbc %[d1], r5\n\t" + "mov r5, %[d1]\n\t" + "add %[r], r5\n\t" + "# r * div - Start\n\t" + "lsl %[d1], %[r], #16\n\t" + "lsl r4, %[div], #16\n\t" + "lsr %[d1], %[d1], #16\n\t" + "lsr r4, r4, #16\n\t" + "mul r4, %[d1]\n\t" + "lsr r6, %[div], #16\n\t" + "mul %[d1], r6\n\t" + "lsr r5, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r7\n\t" + "lsr %[d1], %[r], #16\n\t" + "mul r6, %[d1]\n\t" + "add r5, r6\n\t" + "lsl r6, %[div], #16\n\t" + "lsr r6, r6, #16\n\t" + "mul %[d1], r6\n\t" + "lsr r6, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r6\n\t" + "# r * div - Done\n\t" + "mov %[d1], r8\n\t" + "mov r6, r9\n\t" + "sub r4, %[d1], r4\n\t" + "sbc r6, r5\n\t" + "mov r5, r6\n\t" + "add %[r], r5\n\t" + "# r * div - Start\n\t" + "lsl %[d1], %[r], #16\n\t" + "lsl r4, %[div], #16\n\t" + "lsr %[d1], %[d1], #16\n\t" + "lsr r4, r4, #16\n\t" + "mul r4, %[d1]\n\t" + "lsr r6, %[div], #16\n\t" + "mul %[d1], r6\n\t" + "lsr r5, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r7\n\t" + "lsr %[d1], %[r], #16\n\t" + "mul r6, %[d1]\n\t" + "add r5, r6\n\t" + "lsl r6, %[div], #16\n\t" + "lsr r6, r6, #16\n\t" + "mul %[d1], r6\n\t" + "lsr r6, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r6\n\t" + "# r * div - Done\n\t" + "mov %[d1], r8\n\t" + "mov r6, r9\n\t" + "sub r4, %[d1], r4\n\t" + "sbc r6, r5\n\t" + "mov r5, r6\n\t" + "add %[r], r5\n\t" + "mov r6, %[div]\n\t" + "sub r6, r4\n\t" + "sbc r6, r6\n\t" + "sub %[r], r6\n\t" + : [r] "+r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "r4", "r5", "r7", "r6", "r8", "r9" + ); + return r; +} + +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +SP_NOINLINE static int32_t sp_3072_cmp_48(sp_digit* a, sp_digit* b) +{ + sp_digit r = 0; + + + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mvn r3, r3\n\t" + "mov r6, #188\n\t" + "1:\n\t" + "ldr r7, [%[a], r6]\n\t" + "ldr r5, [%[b], r6]\n\t" + "and r7, r3\n\t" + "and r5, r3\n\t" + "mov r4, r7\n\t" + "sub r7, r5\n\t" + "sbc r7, r7\n\t" + "add %[r], r7\n\t" + "mvn r7, r7\n\t" + "and r3, r7\n\t" + "sub r5, r4\n\t" + "sbc r7, r7\n\t" + "sub %[r], r7\n\t" + "mvn r7, r7\n\t" + "and r3, r7\n\t" + "sub r6, #4\n\t" + "cmp r6, #0\n\t" + "bge 1b\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "r3", "r4", "r5", "r6", "r7" + ); + + return r; +} + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_3072_div_48(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[96], t2[49]; + sp_digit div, r1; + int i; + + (void)m; + + div = d[47]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 48); + for (i=47; i>=0; i--) { + r1 = div_3072_word_48(t1[48 + i], t1[48 + i - 1], div); + + sp_3072_mul_d_48(t2, d, r1); + t1[48 + i] += sp_3072_sub_in_place_48(&t1[i], t2); + t1[48 + i] -= t2[48]; + sp_3072_mask_48(t2, d, t1[48 + i]); + t1[48 + i] += sp_3072_add_48(&t1[i], &t1[i], t2); + sp_3072_mask_48(t2, d, t1[48 + i]); + t1[48 + i] += sp_3072_add_48(&t1[i], &t1[i], t2); + } + + r1 = sp_3072_cmp_48(t1, d) >= 0; + sp_3072_cond_sub_48(r, t1, d, (sp_digit)0 - r1); + + return MP_OKAY; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_3072_mod_48(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_3072_div_48(a, m, NULL, r); +} + +#ifdef WOLFSSL_SP_SMALL +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_3072_mod_exp_48(sp_digit* r, sp_digit* a, sp_digit* e, + int bits, sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[16][96]; +#else + sp_digit* t[16]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 96, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<16; i++) + t[i] = td + i * 96; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_48(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 48); + if (reduceA) { + err = sp_3072_mod_48(t[1] + 48, a, m); + if (err == MP_OKAY) + err = sp_3072_mod_48(t[1], t[1], m); + } + else { + XMEMCPY(t[1] + 48, a, sizeof(sp_digit) * 48); + err = sp_3072_mod_48(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_3072_mont_sqr_48(t[ 2], t[ 1], m, mp); + sp_3072_mont_mul_48(t[ 3], t[ 2], t[ 1], m, mp); + sp_3072_mont_sqr_48(t[ 4], t[ 2], m, mp); + sp_3072_mont_mul_48(t[ 5], t[ 3], t[ 2], m, mp); + sp_3072_mont_sqr_48(t[ 6], t[ 3], m, mp); + sp_3072_mont_mul_48(t[ 7], t[ 4], t[ 3], m, mp); + sp_3072_mont_sqr_48(t[ 8], t[ 4], m, mp); + sp_3072_mont_mul_48(t[ 9], t[ 5], t[ 4], m, mp); + sp_3072_mont_sqr_48(t[10], t[ 5], m, mp); + sp_3072_mont_mul_48(t[11], t[ 6], t[ 5], m, mp); + sp_3072_mont_sqr_48(t[12], t[ 6], m, mp); + sp_3072_mont_mul_48(t[13], t[ 7], t[ 6], m, mp); + sp_3072_mont_sqr_48(t[14], t[ 7], m, mp); + sp_3072_mont_mul_48(t[15], t[ 8], t[ 7], m, mp); + + i = (bits - 1) / 32; + n = e[i--]; + y = n >> 28; + n <<= 4; + c = 28; + XMEMCPY(r, t[y], sizeof(sp_digit) * 48); + for (; i>=0 || c>=4; ) { + if (c == 0) { + n = e[i--]; + y = n >> 28; + n <<= 4; + c = 28; + } + else if (c < 4) { + y = n >> 28; + n = e[i--]; + c = 4 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 28) & 0xf; + n <<= 4; + c -= 4; + } + + sp_3072_mont_sqr_48(r, r, m, mp); + sp_3072_mont_sqr_48(r, r, m, mp); + sp_3072_mont_sqr_48(r, r, m, mp); + sp_3072_mont_sqr_48(r, r, m, mp); + + sp_3072_mont_mul_48(r, r, t[y], m, mp); + } + y = e[0] & ((1 << c) - 1); + for (; c > 0; c--) + sp_3072_mont_sqr_48(r, r, m, mp); + sp_3072_mont_mul_48(r, r, t[y], m, mp); + + XMEMSET(&r[48], 0, sizeof(sp_digit) * 48); + sp_3072_mont_reduce_48(r, m, mp); + + mask = 0 - (sp_3072_cmp_48(r, m) >= 0); + sp_3072_cond_sub_48(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#else +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_3072_mod_exp_48(sp_digit* r, sp_digit* a, sp_digit* e, + int bits, sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][96]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 96, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<32; i++) + t[i] = td + i * 96; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_48(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 48); + if (reduceA) { + err = sp_3072_mod_48(t[1] + 48, a, m); + if (err == MP_OKAY) + err = sp_3072_mod_48(t[1], t[1], m); + } + else { + XMEMCPY(t[1] + 48, a, sizeof(sp_digit) * 48); + err = sp_3072_mod_48(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_3072_mont_sqr_48(t[ 2], t[ 1], m, mp); + sp_3072_mont_mul_48(t[ 3], t[ 2], t[ 1], m, mp); + sp_3072_mont_sqr_48(t[ 4], t[ 2], m, mp); + sp_3072_mont_mul_48(t[ 5], t[ 3], t[ 2], m, mp); + sp_3072_mont_sqr_48(t[ 6], t[ 3], m, mp); + sp_3072_mont_mul_48(t[ 7], t[ 4], t[ 3], m, mp); + sp_3072_mont_sqr_48(t[ 8], t[ 4], m, mp); + sp_3072_mont_mul_48(t[ 9], t[ 5], t[ 4], m, mp); + sp_3072_mont_sqr_48(t[10], t[ 5], m, mp); + sp_3072_mont_mul_48(t[11], t[ 6], t[ 5], m, mp); + sp_3072_mont_sqr_48(t[12], t[ 6], m, mp); + sp_3072_mont_mul_48(t[13], t[ 7], t[ 6], m, mp); + sp_3072_mont_sqr_48(t[14], t[ 7], m, mp); + sp_3072_mont_mul_48(t[15], t[ 8], t[ 7], m, mp); + sp_3072_mont_sqr_48(t[16], t[ 8], m, mp); + sp_3072_mont_mul_48(t[17], t[ 9], t[ 8], m, mp); + sp_3072_mont_sqr_48(t[18], t[ 9], m, mp); + sp_3072_mont_mul_48(t[19], t[10], t[ 9], m, mp); + sp_3072_mont_sqr_48(t[20], t[10], m, mp); + sp_3072_mont_mul_48(t[21], t[11], t[10], m, mp); + sp_3072_mont_sqr_48(t[22], t[11], m, mp); + sp_3072_mont_mul_48(t[23], t[12], t[11], m, mp); + sp_3072_mont_sqr_48(t[24], t[12], m, mp); + sp_3072_mont_mul_48(t[25], t[13], t[12], m, mp); + sp_3072_mont_sqr_48(t[26], t[13], m, mp); + sp_3072_mont_mul_48(t[27], t[14], t[13], m, mp); + sp_3072_mont_sqr_48(t[28], t[14], m, mp); + sp_3072_mont_mul_48(t[29], t[15], t[14], m, mp); + sp_3072_mont_sqr_48(t[30], t[15], m, mp); + sp_3072_mont_mul_48(t[31], t[16], t[15], m, mp); + + i = (bits - 1) / 32; + n = e[i--]; + y = n >> 27; + n <<= 5; + c = 27; + XMEMCPY(r, t[y], sizeof(sp_digit) * 48); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 27; + n <<= 5; + c = 27; + } + else if (c < 5) { + y = n >> 27; + n = e[i--]; + c = 5 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 27) & 0x1f; + n <<= 5; + c -= 5; + } + + sp_3072_mont_sqr_48(r, r, m, mp); + sp_3072_mont_sqr_48(r, r, m, mp); + sp_3072_mont_sqr_48(r, r, m, mp); + sp_3072_mont_sqr_48(r, r, m, mp); + sp_3072_mont_sqr_48(r, r, m, mp); + + sp_3072_mont_mul_48(r, r, t[y], m, mp); + } + y = e[0] & ((1 << c) - 1); + for (; c > 0; c--) + sp_3072_mont_sqr_48(r, r, m, mp); + sp_3072_mont_mul_48(r, r, t[y], m, mp); + + XMEMSET(&r[48], 0, sizeof(sp_digit) * 48); + sp_3072_mont_reduce_48(r, m, mp); + + mask = 0 - (sp_3072_cmp_48(r, m) >= 0); + sp_3072_cond_sub_48(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#endif /* WOLFSSL_SP_SMALL */ + +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) +/* r = 2^n mod m where n is the number of bits to reduce by. + * Given m must be 3072 bits, just need to subtract. + * + * r A single precision number. + * m A signle precision number. + */ +static void sp_3072_mont_norm_96(sp_digit* r, sp_digit* m) +{ + XMEMSET(r, 0, sizeof(sp_digit) * 96); + + /* r = 2^n mod m */ + sp_3072_sub_in_place_96(r, m); +} + +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not copying. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +SP_NOINLINE static sp_digit sp_3072_cond_sub_96(sp_digit* r, sp_digit* a, + sp_digit* b, sp_digit m) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r5, #1\n\t" + "lsl r5, r5, #8\n\t" + "add r5, #128\n\t" + "mov r8, r5\n\t" + "mov r7, #0\n\t" + "1:\n\t" + "ldr r6, [%[b], r7]\n\t" + "and r6, %[m]\n\t" + "mov r5, #0\n\t" + "sub r5, %[c]\n\t" + "ldr r5, [%[a], r7]\n\t" + "sbc r5, r6\n\t" + "sbc %[c], %[c]\n\t" + "str r5, [%[r], r7]\n\t" + "add r7, #4\n\t" + "cmp r7, r8\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r5", "r6", "r7", "r8" + ); + + return c; +} + +/* Reduce the number back to 3072 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "mov r8, %[mp]\n\t" + "mov r12, %[ca]\n\t" + "mov r14, %[m]\n\t" + "mov r9, %[a]\n\t" + "mov r4, #0\n\t" + "# i = 0\n\t" + "mov r11, r4\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "mov %[ca], #0\n\t" + "# mu = a[i] * mp\n\t" + "mov %[mp], r8\n\t" + "ldr %[a], [%[a]]\n\t" + "mul %[mp], %[a]\n\t" + "mov %[m], r14\n\t" + "mov r10, r9\n\t" + "\n2:\n\t" + "# a[i+j] += m[j] * mu\n\t" + "mov %[a], r10\n\t" + "ldr %[a], [%[a]]\n\t" + "mov %[ca], #0\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "# Multiply m[j] and mu - Start\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r6, %[mp], #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add %[a], r7\n\t" + "adc r5, %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add %[a], r6\n\t" + "adc r5, r7\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r6, %[mp], #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r5, r7\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add %[a], r6\n\t" + "adc r5, r7\n\t" + "# Multiply m[j] and mu - Done\n\t" + "add r4, %[a]\n\t" + "adc r5, %[ca]\n\t" + "mov %[a], r10\n\t" + "str r4, [%[a]]\n\t" + "mov r6, #4\n\t" + "add %[m], #4\n\t" + "add r10, r6\n\t" + "mov r4, #1\n\t" + "lsl r4, r4, #8\n\t" + "add r4, #124\n\t" + "add r4, r9\n\t" + "cmp r10, r4\n\t" + "blt 2b\n\t" + "# a[i+95] += m[95] * mu\n\t" + "mov %[ca], #0\n\t" + "mov r4, r12\n\t" + "mov %[a], #0\n\t" + "# Multiply m[95] and mu - Start\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r6, %[mp], #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r5, r7\n\t" + "adc r4, %[ca]\n\t" + "adc %[a], %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r5, r6\n\t" + "adc r4, r7\n\t" + "adc %[a], %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r6, %[mp], #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc %[a], %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r5, r6\n\t" + "adc r4, r7\n\t" + "adc %[a], %[ca]\n\t" + "# Multiply m[95] and mu - Done\n\t" + "mov %[ca], %[a]\n\t" + "mov %[a], r10\n\t" + "ldr r7, [%[a], #4]\n\t" + "ldr %[a], [%[a]]\n\t" + "mov r6, #0\n\t" + "add r5, %[a]\n\t" + "adc r7, r4\n\t" + "adc %[ca], r6\n\t" + "mov %[a], r10\n\t" + "str r5, [%[a]]\n\t" + "str r7, [%[a], #4]\n\t" + "# i += 1\n\t" + "mov r6, #4\n\t" + "add r9, r6\n\t" + "add r11, r6\n\t" + "mov r12, %[ca]\n\t" + "mov %[a], r9\n\t" + "mov r4, #1\n\t" + "lsl r4, r4, #8\n\t" + "add r4, #128\n\t" + "cmp r11, r4\n\t" + "blt 1b\n\t" + "mov %[m], r14\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14" + ); + + sp_3072_cond_sub_96(a - 96, a, m, (sp_digit)0 - ca); +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_3072_mont_mul_96(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_3072_mul_96(r, a, b); + sp_3072_mont_reduce_96(r, m, mp); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_3072_mont_sqr_96(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_3072_sqr_96(r, a); + sp_3072_mont_reduce_96(r, m, mp); +} + +/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) + * + * d1 The high order half of the number to divide. + * d0 The low order half of the number to divide. + * div The dividend. + * returns the result of the division. + * + * Note that this is an approximate div. It may give an answer 1 larger. + */ +SP_NOINLINE static sp_digit div_3072_word_96(sp_digit d1, sp_digit d0, + sp_digit div) +{ + sp_digit r = 0; + + __asm__ __volatile__ ( + "lsr r5, %[div], #1\n\t" + "add r5, #1\n\t" + "mov r8, %[d0]\n\t" + "mov r9, %[d1]\n\t" + "# Do top 32\n\t" + "mov r6, r5\n\t" + "sub r6, %[d1]\n\t" + "sbc r6, r6\n\t" + "add %[r], %[r]\n\t" + "sub %[r], r6\n\t" + "and r6, r5\n\t" + "sub %[d1], r6\n\t" + "# Next 30 bits\n\t" + "mov r4, #29\n\t" + "1:\n\t" + "lsl %[d0], %[d0], #1\n\t" + "adc %[d1], %[d1]\n\t" + "mov r6, r5\n\t" + "sub r6, %[d1]\n\t" + "sbc r6, r6\n\t" + "add %[r], %[r]\n\t" + "sub %[r], r6\n\t" + "and r6, r5\n\t" + "sub %[d1], r6\n\t" + "sub r4, #1\n\t" + "bpl 1b\n\t" + "mov r7, #0\n\t" + "add %[r], %[r]\n\t" + "add %[r], #1\n\t" + "# r * div - Start\n\t" + "lsl %[d1], %[r], #16\n\t" + "lsl r4, %[div], #16\n\t" + "lsr %[d1], %[d1], #16\n\t" + "lsr r4, r4, #16\n\t" + "mul r4, %[d1]\n\t" + "lsr r6, %[div], #16\n\t" + "mul %[d1], r6\n\t" + "lsr r5, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r7\n\t" + "lsr %[d1], %[r], #16\n\t" + "mul r6, %[d1]\n\t" + "add r5, r6\n\t" + "lsl r6, %[div], #16\n\t" + "lsr r6, r6, #16\n\t" + "mul %[d1], r6\n\t" + "lsr r6, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r6\n\t" + "# r * div - Done\n\t" + "mov %[d1], r8\n\t" + "sub %[d1], r4\n\t" + "mov r4, %[d1]\n\t" + "mov %[d1], r9\n\t" + "sbc %[d1], r5\n\t" + "mov r5, %[d1]\n\t" + "add %[r], r5\n\t" + "# r * div - Start\n\t" + "lsl %[d1], %[r], #16\n\t" + "lsl r4, %[div], #16\n\t" + "lsr %[d1], %[d1], #16\n\t" + "lsr r4, r4, #16\n\t" + "mul r4, %[d1]\n\t" + "lsr r6, %[div], #16\n\t" + "mul %[d1], r6\n\t" + "lsr r5, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r7\n\t" + "lsr %[d1], %[r], #16\n\t" + "mul r6, %[d1]\n\t" + "add r5, r6\n\t" + "lsl r6, %[div], #16\n\t" + "lsr r6, r6, #16\n\t" + "mul %[d1], r6\n\t" + "lsr r6, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r6\n\t" + "# r * div - Done\n\t" + "mov %[d1], r8\n\t" + "mov r6, r9\n\t" + "sub r4, %[d1], r4\n\t" + "sbc r6, r5\n\t" + "mov r5, r6\n\t" + "add %[r], r5\n\t" + "# r * div - Start\n\t" + "lsl %[d1], %[r], #16\n\t" + "lsl r4, %[div], #16\n\t" + "lsr %[d1], %[d1], #16\n\t" + "lsr r4, r4, #16\n\t" + "mul r4, %[d1]\n\t" + "lsr r6, %[div], #16\n\t" + "mul %[d1], r6\n\t" + "lsr r5, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r7\n\t" + "lsr %[d1], %[r], #16\n\t" + "mul r6, %[d1]\n\t" + "add r5, r6\n\t" + "lsl r6, %[div], #16\n\t" + "lsr r6, r6, #16\n\t" + "mul %[d1], r6\n\t" + "lsr r6, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r6\n\t" + "# r * div - Done\n\t" + "mov %[d1], r8\n\t" + "mov r6, r9\n\t" + "sub r4, %[d1], r4\n\t" + "sbc r6, r5\n\t" + "mov r5, r6\n\t" + "add %[r], r5\n\t" + "mov r6, %[div]\n\t" + "sub r6, r4\n\t" + "sbc r6, r6\n\t" + "sub %[r], r6\n\t" + : [r] "+r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "r4", "r5", "r7", "r6", "r8", "r9" + ); + return r; +} + +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_3072_mask_96(sp_digit* r, sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<96; i++) + r[i] = a[i] & m; +#else + int i; + + for (i = 0; i < 96; i += 8) { + r[i+0] = a[i+0] & m; + r[i+1] = a[i+1] & m; + r[i+2] = a[i+2] & m; + r[i+3] = a[i+3] & m; + r[i+4] = a[i+4] & m; + r[i+5] = a[i+5] & m; + r[i+6] = a[i+6] & m; + r[i+7] = a[i+7] & m; + } +#endif +} + +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +SP_NOINLINE static int32_t sp_3072_cmp_96(sp_digit* a, sp_digit* b) +{ + sp_digit r = 0; + + + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mvn r3, r3\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, #124\n\t" + "1:\n\t" + "ldr r7, [%[a], r6]\n\t" + "ldr r5, [%[b], r6]\n\t" + "and r7, r3\n\t" + "and r5, r3\n\t" + "mov r4, r7\n\t" + "sub r7, r5\n\t" + "sbc r7, r7\n\t" + "add %[r], r7\n\t" + "mvn r7, r7\n\t" + "and r3, r7\n\t" + "sub r5, r4\n\t" + "sbc r7, r7\n\t" + "sub %[r], r7\n\t" + "mvn r7, r7\n\t" + "and r3, r7\n\t" + "sub r6, #4\n\t" + "cmp r6, #0\n\t" + "bge 1b\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "r3", "r4", "r5", "r6", "r7" + ); + + return r; +} + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_3072_div_96(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[192], t2[97]; + sp_digit div, r1; + int i; + + (void)m; + + div = d[95]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 96); + for (i=95; i>=0; i--) { + r1 = div_3072_word_96(t1[96 + i], t1[96 + i - 1], div); + + sp_3072_mul_d_96(t2, d, r1); + t1[96 + i] += sp_3072_sub_in_place_96(&t1[i], t2); + t1[96 + i] -= t2[96]; + sp_3072_mask_96(t2, d, t1[96 + i]); + t1[96 + i] += sp_3072_add_96(&t1[i], &t1[i], t2); + sp_3072_mask_96(t2, d, t1[96 + i]); + t1[96 + i] += sp_3072_add_96(&t1[i], &t1[i], t2); + } + + r1 = sp_3072_cmp_96(t1, d) >= 0; + sp_3072_cond_sub_96(r, t1, d, (sp_digit)0 - r1); + + return MP_OKAY; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_3072_mod_96(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_3072_div_96(a, m, NULL, r); +} + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_3072_div_96_cond(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[192], t2[97]; + sp_digit div, r1; + int i; + + (void)m; + + div = d[95]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 96); + for (i=95; i>=0; i--) { + r1 = div_3072_word_96(t1[96 + i], t1[96 + i - 1], div); + + sp_3072_mul_d_96(t2, d, r1); + t1[96 + i] += sp_3072_sub_in_place_96(&t1[i], t2); + t1[96 + i] -= t2[96]; + if (t1[96 + i] != 0) { + t1[96 + i] += sp_3072_add_96(&t1[i], &t1[i], d); + if (t1[96 + i] != 0) + t1[96 + i] += sp_3072_add_96(&t1[i], &t1[i], d); + } + } + + r1 = sp_3072_cmp_96(t1, d) >= 0; + sp_3072_cond_sub_96(r, t1, d, (sp_digit)0 - r1); + + return MP_OKAY; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_3072_mod_96_cond(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_3072_div_96_cond(a, m, NULL, r); +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \ + defined(WOLFSSL_HAVE_SP_DH) +#ifdef WOLFSSL_SP_SMALL +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_3072_mod_exp_96(sp_digit* r, sp_digit* a, sp_digit* e, + int bits, sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[16][192]; +#else + sp_digit* t[16]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 192, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<16; i++) + t[i] = td + i * 192; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_96(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 96); + if (reduceA) { + err = sp_3072_mod_96(t[1] + 96, a, m); + if (err == MP_OKAY) + err = sp_3072_mod_96(t[1], t[1], m); + } + else { + XMEMCPY(t[1] + 96, a, sizeof(sp_digit) * 96); + err = sp_3072_mod_96(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_3072_mont_sqr_96(t[ 2], t[ 1], m, mp); + sp_3072_mont_mul_96(t[ 3], t[ 2], t[ 1], m, mp); + sp_3072_mont_sqr_96(t[ 4], t[ 2], m, mp); + sp_3072_mont_mul_96(t[ 5], t[ 3], t[ 2], m, mp); + sp_3072_mont_sqr_96(t[ 6], t[ 3], m, mp); + sp_3072_mont_mul_96(t[ 7], t[ 4], t[ 3], m, mp); + sp_3072_mont_sqr_96(t[ 8], t[ 4], m, mp); + sp_3072_mont_mul_96(t[ 9], t[ 5], t[ 4], m, mp); + sp_3072_mont_sqr_96(t[10], t[ 5], m, mp); + sp_3072_mont_mul_96(t[11], t[ 6], t[ 5], m, mp); + sp_3072_mont_sqr_96(t[12], t[ 6], m, mp); + sp_3072_mont_mul_96(t[13], t[ 7], t[ 6], m, mp); + sp_3072_mont_sqr_96(t[14], t[ 7], m, mp); + sp_3072_mont_mul_96(t[15], t[ 8], t[ 7], m, mp); + + i = (bits - 1) / 32; + n = e[i--]; + y = n >> 28; + n <<= 4; + c = 28; + XMEMCPY(r, t[y], sizeof(sp_digit) * 96); + for (; i>=0 || c>=4; ) { + if (c == 0) { + n = e[i--]; + y = n >> 28; + n <<= 4; + c = 28; + } + else if (c < 4) { + y = n >> 28; + n = e[i--]; + c = 4 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 28) & 0xf; + n <<= 4; + c -= 4; + } + + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + + sp_3072_mont_mul_96(r, r, t[y], m, mp); + } + y = e[0] & ((1 << c) - 1); + for (; c > 0; c--) + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_mul_96(r, r, t[y], m, mp); + + XMEMSET(&r[96], 0, sizeof(sp_digit) * 96); + sp_3072_mont_reduce_96(r, m, mp); + + mask = 0 - (sp_3072_cmp_96(r, m) >= 0); + sp_3072_cond_sub_96(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#else +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_3072_mod_exp_96(sp_digit* r, sp_digit* a, sp_digit* e, + int bits, sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][192]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 192, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<32; i++) + t[i] = td + i * 192; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_96(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 96); + if (reduceA) { + err = sp_3072_mod_96(t[1] + 96, a, m); + if (err == MP_OKAY) + err = sp_3072_mod_96(t[1], t[1], m); + } + else { + XMEMCPY(t[1] + 96, a, sizeof(sp_digit) * 96); + err = sp_3072_mod_96(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_3072_mont_sqr_96(t[ 2], t[ 1], m, mp); + sp_3072_mont_mul_96(t[ 3], t[ 2], t[ 1], m, mp); + sp_3072_mont_sqr_96(t[ 4], t[ 2], m, mp); + sp_3072_mont_mul_96(t[ 5], t[ 3], t[ 2], m, mp); + sp_3072_mont_sqr_96(t[ 6], t[ 3], m, mp); + sp_3072_mont_mul_96(t[ 7], t[ 4], t[ 3], m, mp); + sp_3072_mont_sqr_96(t[ 8], t[ 4], m, mp); + sp_3072_mont_mul_96(t[ 9], t[ 5], t[ 4], m, mp); + sp_3072_mont_sqr_96(t[10], t[ 5], m, mp); + sp_3072_mont_mul_96(t[11], t[ 6], t[ 5], m, mp); + sp_3072_mont_sqr_96(t[12], t[ 6], m, mp); + sp_3072_mont_mul_96(t[13], t[ 7], t[ 6], m, mp); + sp_3072_mont_sqr_96(t[14], t[ 7], m, mp); + sp_3072_mont_mul_96(t[15], t[ 8], t[ 7], m, mp); + sp_3072_mont_sqr_96(t[16], t[ 8], m, mp); + sp_3072_mont_mul_96(t[17], t[ 9], t[ 8], m, mp); + sp_3072_mont_sqr_96(t[18], t[ 9], m, mp); + sp_3072_mont_mul_96(t[19], t[10], t[ 9], m, mp); + sp_3072_mont_sqr_96(t[20], t[10], m, mp); + sp_3072_mont_mul_96(t[21], t[11], t[10], m, mp); + sp_3072_mont_sqr_96(t[22], t[11], m, mp); + sp_3072_mont_mul_96(t[23], t[12], t[11], m, mp); + sp_3072_mont_sqr_96(t[24], t[12], m, mp); + sp_3072_mont_mul_96(t[25], t[13], t[12], m, mp); + sp_3072_mont_sqr_96(t[26], t[13], m, mp); + sp_3072_mont_mul_96(t[27], t[14], t[13], m, mp); + sp_3072_mont_sqr_96(t[28], t[14], m, mp); + sp_3072_mont_mul_96(t[29], t[15], t[14], m, mp); + sp_3072_mont_sqr_96(t[30], t[15], m, mp); + sp_3072_mont_mul_96(t[31], t[16], t[15], m, mp); + + i = (bits - 1) / 32; + n = e[i--]; + y = n >> 27; + n <<= 5; + c = 27; + XMEMCPY(r, t[y], sizeof(sp_digit) * 96); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 27; + n <<= 5; + c = 27; + } + else if (c < 5) { + y = n >> 27; + n = e[i--]; + c = 5 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 27) & 0x1f; + n <<= 5; + c -= 5; + } + + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + + sp_3072_mont_mul_96(r, r, t[y], m, mp); + } + y = e[0] & ((1 << c) - 1); + for (; c > 0; c--) + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_mul_96(r, r, t[y], m, mp); + + XMEMSET(&r[96], 0, sizeof(sp_digit) * 96); + sp_3072_mont_reduce_96(r, m, mp); + + mask = 0 - (sp_3072_cmp_96(r, m) >= 0); + sp_3072_cond_sub_96(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#endif /* WOLFSSL_SP_SMALL */ +#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ + +#ifdef WOLFSSL_HAVE_SP_RSA +/* RSA public key operation. + * + * in Array of bytes representing the number to exponentiate, base. + * inLen Number of bytes in base. + * em Public exponent. + * mm Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 384 bytes long. + * outLen Number of bytes in result. + * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when + * an array is too long and MEMORY_E when dynamic memory allocation fails. + */ +int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm, + byte* out, word32* outLen) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit ad[192], md[96], rd[192]; +#else + sp_digit* d = NULL; +#endif + sp_digit* a; + sp_digit *ah; + sp_digit* m; + sp_digit* r; + sp_digit e[1]; + int err = MP_OKAY; + + if (*outLen < 384) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(em) > 32 || inLen > 384 || + mp_count_bits(mm) != 3072)) + err = MP_READ_E; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 96 * 5, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + a = d; + r = a + 96 * 2; + m = r + 96 * 2; + ah = a + 96; + } +#else + a = ad; + m = md; + r = rd; + ah = a + 96; +#endif + + if (err == MP_OKAY) { + sp_3072_from_bin(ah, 96, in, inLen); +#if DIGIT_BIT >= 32 + e[0] = em->dp[0]; +#else + e[0] = em->dp[0]; + if (em->used > 1) + e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT; +#endif + if (e[0] == 0) + err = MP_EXPTMOD_E; + } + if (err == MP_OKAY) { + sp_3072_from_mp(m, 96, mm); + + if (e[0] == 0x3) { + if (err == MP_OKAY) { + sp_3072_sqr_96(r, ah); + err = sp_3072_mod_96_cond(r, r, m); + } + if (err == MP_OKAY) { + sp_3072_mul_96(r, ah, r); + err = sp_3072_mod_96_cond(r, r, m); + } + } + else { + int i; + sp_digit mp; + + sp_3072_mont_setup(m, &mp); + + /* Convert to Montgomery form. */ + XMEMSET(a, 0, sizeof(sp_digit) * 96); + err = sp_3072_mod_96_cond(a, a, m); + + if (err == MP_OKAY) { + for (i=31; i>=0; i--) + if (e[0] >> i) + break; + + XMEMCPY(r, a, sizeof(sp_digit) * 96); + for (i--; i>=0; i--) { + sp_3072_mont_sqr_96(r, r, m, mp); + if (((e[0] >> i) & 1) == 1) + sp_3072_mont_mul_96(r, r, a, m, mp); + } + XMEMSET(&r[96], 0, sizeof(sp_digit) * 96); + sp_3072_mont_reduce_96(r, m, mp); + + for (i = 95; i > 0; i--) { + if (r[i] != m[i]) + break; + } + if (r[i] >= m[i]) + sp_3072_sub_in_place_96(r, m); + } + } + } + + if (err == MP_OKAY) { + sp_3072_to_bin(r, out); + *outLen = 384; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_RSA); +#endif + + return err; +} + +/* RSA private key operation. + * + * in Array of bytes representing the number to exponentiate, base. + * inLen Number of bytes in base. + * dm Private exponent. + * pm First prime. + * qm Second prime. + * dpm First prime's CRT exponent. + * dqm Second prime's CRT exponent. + * qim Inverse of second prime mod p. + * mm Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 384 bytes long. + * outLen Number of bytes in result. + * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when + * an array is too long and MEMORY_E when dynamic memory allocation fails. + */ +int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, + mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm, + byte* out, word32* outLen) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit ad[96 * 2]; + sp_digit pd[48], qd[48], dpd[48]; + sp_digit tmpad[96], tmpbd[96]; +#else + sp_digit* t = NULL; +#endif + sp_digit* a; + sp_digit* p; + sp_digit* q; + sp_digit* dp; + sp_digit* dq; + sp_digit* qi; + sp_digit* tmp; + sp_digit* tmpa; + sp_digit* tmpb; + sp_digit* r; + sp_digit c; + int err = MP_OKAY; + + (void)dm; + (void)mm; + + if (*outLen < 384) + err = MP_TO_E; + if (err == MP_OKAY && (inLen > 384 || mp_count_bits(mm) != 3072)) + err = MP_READ_E; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 48 * 11, NULL, + DYNAMIC_TYPE_RSA); + if (t == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + a = t; + p = a + 96 * 2; + q = p + 48; + qi = dq = dp = q + 48; + tmpa = qi + 48; + tmpb = tmpa + 96; + + tmp = t; + r = tmp + 96; + } +#else + r = a = ad; + p = pd; + q = qd; + qi = dq = dp = dpd; + tmpa = tmpad; + tmpb = tmpbd; + tmp = a + 96; +#endif + + if (err == MP_OKAY) { + sp_3072_from_bin(a, 96, in, inLen); + sp_3072_from_mp(p, 48, pm); + sp_3072_from_mp(q, 48, qm); + sp_3072_from_mp(dp, 48, dpm); + + err = sp_3072_mod_exp_48(tmpa, a, dp, 1536, p, 1); + } + if (err == MP_OKAY) { + sp_3072_from_mp(dq, 48, dqm); + err = sp_3072_mod_exp_48(tmpb, a, dq, 1536, q, 1); + } + + if (err == MP_OKAY) { + c = sp_3072_sub_in_place_48(tmpa, tmpb); + sp_3072_mask_48(tmp, p, c); + sp_3072_add_48(tmpa, tmpa, tmp); + + sp_3072_from_mp(qi, 48, qim); + sp_3072_mul_48(tmpa, tmpa, qi); + err = sp_3072_mod_48(tmpa, tmpa, p); + } + + if (err == MP_OKAY) { + sp_3072_mul_48(tmpa, q, tmpa); + XMEMSET(&tmpb[48], 0, sizeof(sp_digit) * 48); + sp_3072_add_96(r, tmpb, tmpa); + + sp_3072_to_bin(r, out); + *outLen = 384; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_digit) * 48 * 11); + XFREE(t, NULL, DYNAMIC_TYPE_RSA); + } +#else + XMEMSET(tmpad, 0, sizeof(tmpad)); + XMEMSET(tmpbd, 0, sizeof(tmpbd)); + XMEMSET(pd, 0, sizeof(pd)); + XMEMSET(qd, 0, sizeof(qd)); + XMEMSET(dpd, 0, sizeof(dpd)); +#endif + + return err; +} +#endif /* WOLFSSL_HAVE_SP_RSA */ +#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \ + !defined(WOLFSSL_RSA_PUBLIC_ONLY)) +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_3072_to_mp(sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (3072 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { +#if DIGIT_BIT == 32 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 96); + r->used = 96; + mp_clamp(r); +#elif DIGIT_BIT < 32 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 96; i++) { + r->dp[j] |= a[i] << s; + r->dp[j] &= (1l << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + while (s + DIGIT_BIT <= 32) { + s += DIGIT_BIT; + r->dp[j] &= (1l << DIGIT_BIT) - 1; + r->dp[++j] = a[i] >> s; + } + s = 32 - s; + } + r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 96; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 32 >= DIGIT_BIT) { + #if DIGIT_BIT < 32 + r->dp[j] &= (1l << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 32 - s; + } + else + s += 32; + } + r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returs 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ + int err = MP_OKAY; + sp_digit b[192], e[96], m[96]; + sp_digit* r = b; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 3072 || expBits > 3072 || + mp_count_bits(mod) != 3072) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + sp_3072_from_mp(b, 96, base); + sp_3072_from_mp(e, 96, exp); + sp_3072_from_mp(m, 96, mod); + + err = sp_3072_mod_exp_96(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + err = sp_3072_to_mp(r, res); + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} + +#ifdef WOLFSSL_HAVE_SP_DH +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. + * exp Array of bytes that is the exponent. + * expLen Length of data, in bytes, in exponent. + * mod Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 384 bytes long. + * outLen Length, in bytes, of exponentiation result. + * returs 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen, + mp_int* mod, byte* out, word32* outLen) +{ + int err = MP_OKAY; + sp_digit b[192], e[96], m[96]; + sp_digit* r = b; + word32 i; + + if (mp_count_bits(base) > 3072 || expLen > 384 || + mp_count_bits(mod) != 3072) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + sp_3072_from_mp(b, 96, base); + sp_3072_from_bin(e, 96, exp, expLen); + sp_3072_from_mp(m, 96, mod); + + err = sp_3072_mod_exp_96(r, b, e, expLen * 8, m, 0); + } + + if (err == MP_OKAY) { + sp_3072_to_bin(r, out); + *outLen = 384; + for (i=0; i<384 && out[i] == 0; i++) { + } + *outLen -= i; + XMEMMOVE(out, out + i, *outLen); + + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} +#endif /* WOLFSSL_HAVE_SP_DH */ + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returs 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ + int err = MP_OKAY; + sp_digit b[96], e[48], m[48]; + sp_digit* r = b; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 1536 || expBits > 1536 || + mp_count_bits(mod) != 1536) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + sp_3072_from_mp(b, 48, base); + sp_3072_from_mp(e, 48, exp); + sp_3072_from_mp(m, 48, mod); + + err = sp_3072_mod_exp_48(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + XMEMSET(r + 48, 0, sizeof(*r) * 48); + err = sp_3072_to_mp(r, res); + res->used = mod->used; + mp_clamp(res); + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} + +#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ + +#endif /* !WOLFSSL_SP_NO_3072 */ + +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +#ifdef WOLFSSL_HAVE_SP_ECC +#ifndef WOLFSSL_SP_NO_256 + +/* Point structure to use. */ +typedef struct sp_point { + sp_digit x[2 * 8]; + sp_digit y[2 * 8]; + sp_digit z[2 * 8]; + int infinity; +} sp_point; + +/* The modulus (prime) of the curve P256. */ +static sp_digit p256_mod[8] = { + 0xffffffff,0xffffffff,0xffffffff,0x00000000,0x00000000,0x00000000, + 0x00000001,0xffffffff +}; +/* The Montogmery normalizer for modulus of the curve P256. */ +static sp_digit p256_norm_mod[8] = { + 0x00000001,0x00000000,0x00000000,0xffffffff,0xffffffff,0xffffffff, + 0xfffffffe,0x00000000 +}; +/* The Montogmery multiplier for modulus of the curve P256. */ +static sp_digit p256_mp_mod = 0x00000001; +#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ + defined(HAVE_ECC_VERIFY) +/* The order of the curve P256. */ +static sp_digit p256_order[8] = { + 0xfc632551,0xf3b9cac2,0xa7179e84,0xbce6faad,0xffffffff,0xffffffff, + 0x00000000,0xffffffff +}; +#endif +/* The order of the curve P256 minus 2. */ +static sp_digit p256_order2[8] = { + 0xfc63254f,0xf3b9cac2,0xa7179e84,0xbce6faad,0xffffffff,0xffffffff, + 0x00000000,0xffffffff +}; +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +/* The Montogmery normalizer for order of the curve P256. */ +static sp_digit p256_norm_order[8] = { + 0x039cdaaf,0x0c46353d,0x58e8617b,0x43190552,0x00000000,0x00000000, + 0xffffffff,0x00000000 +}; +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +/* The Montogmery multiplier for order of the curve P256. */ +static sp_digit p256_mp_order = 0xee00bc4f; +#endif +/* The base point of curve P256. */ +static sp_point p256_base = { + /* X ordinate */ + { + 0xd898c296,0xf4a13945,0x2deb33a0,0x77037d81,0x63a440f2,0xf8bce6e5, + 0xe12c4247,0x6b17d1f2 + }, + /* Y ordinate */ + { + 0x37bf51f5,0xcbb64068,0x6b315ece,0x2bce3357,0x7c0f9e16,0x8ee7eb4a, + 0xfe1a7f9b,0x4fe342e2 + }, + /* Z ordinate */ + { + 0x00000001,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000 + }, + /* infinity */ + 0 +}; +#if defined(HAVE_ECC_CHECK_KEY) || defined(HAVE_COMP_KEY) +static sp_digit p256_b[8] = { + 0x27d2604b,0x3bce3c3e,0xcc53b0f6,0x651d06b0,0x769886bc,0xb3ebbd55, + 0xaa3a93e7,0x5ac635d8 +}; +#endif + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) +/* Allocate memory for point and return error. */ +#define sp_ecc_point_new(heap, sp, p) \ + ((p = (sp_point*)XMALLOC(sizeof(sp_point), heap, DYNAMIC_TYPE_ECC)) \ + == NULL) ? MEMORY_E : MP_OKAY +#else +/* Set pointer to data and return no error. */ +#define sp_ecc_point_new(heap, sp, p) ((p = &sp) == NULL) ? MEMORY_E : MP_OKAY +#endif + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) +/* If valid pointer then clear point data if requested and free data. */ +#define sp_ecc_point_free(p, clear, heap) \ + do { \ + if (p != NULL) { \ + if (clear) \ + XMEMSET(p, 0, sizeof(*p)); \ + XFREE(p, heap, DYNAMIC_TYPE_ECC); \ + } \ + } \ + while (0) +#else +/* Clear point data if requested. */ +#define sp_ecc_point_free(p, clear, heap) \ + do { \ + if (clear) \ + XMEMSET(p, 0, sizeof(*p)); \ + } \ + while (0) +#endif + +/* Multiply a number by Montogmery normalizer mod modulus (prime). + * + * r The resulting Montgomery form number. + * a The number to convert. + * m The modulus (prime). + */ +static int sp_256_mod_mul_norm_8(sp_digit* r, sp_digit* a, sp_digit* m) +{ + int64_t t[8]; + int64_t a64[8]; + int64_t o; + + (void)m; + + a64[0] = a[0]; + a64[1] = a[1]; + a64[2] = a[2]; + a64[3] = a[3]; + a64[4] = a[4]; + a64[5] = a[5]; + a64[6] = a[6]; + a64[7] = a[7]; + + /* 1 1 0 -1 -1 -1 -1 0 */ + t[0] = 0 + a64[0] + a64[1] - a64[3] - a64[4] - a64[5] - a64[6]; + /* 0 1 1 0 -1 -1 -1 -1 */ + t[1] = 0 + a64[1] + a64[2] - a64[4] - a64[5] - a64[6] - a64[7]; + /* 0 0 1 1 0 -1 -1 -1 */ + t[2] = 0 + a64[2] + a64[3] - a64[5] - a64[6] - a64[7]; + /* -1 -1 0 2 2 1 0 -1 */ + t[3] = 0 - a64[0] - a64[1] + 2 * a64[3] + 2 * a64[4] + a64[5] - a64[7]; + /* 0 -1 -1 0 2 2 1 0 */ + t[4] = 0 - a64[1] - a64[2] + 2 * a64[4] + 2 * a64[5] + a64[6]; + /* 0 0 -1 -1 0 2 2 1 */ + t[5] = 0 - a64[2] - a64[3] + 2 * a64[5] + 2 * a64[6] + a64[7]; + /* -1 -1 0 0 0 1 3 2 */ + t[6] = 0 - a64[0] - a64[1] + a64[5] + 3 * a64[6] + 2 * a64[7]; + /* 1 0 -1 -1 -1 -1 0 3 */ + t[7] = 0 + a64[0] - a64[2] - a64[3] - a64[4] - a64[5] + 3 * a64[7]; + + t[1] += t[0] >> 32; t[0] &= 0xffffffff; + t[2] += t[1] >> 32; t[1] &= 0xffffffff; + t[3] += t[2] >> 32; t[2] &= 0xffffffff; + t[4] += t[3] >> 32; t[3] &= 0xffffffff; + t[5] += t[4] >> 32; t[4] &= 0xffffffff; + t[6] += t[5] >> 32; t[5] &= 0xffffffff; + t[7] += t[6] >> 32; t[6] &= 0xffffffff; + o = t[7] >> 32; t[7] &= 0xffffffff; + t[0] += o; + t[3] -= o; + t[6] -= o; + t[7] += o; + t[1] += t[0] >> 32; t[0] &= 0xffffffff; + t[2] += t[1] >> 32; t[1] &= 0xffffffff; + t[3] += t[2] >> 32; t[2] &= 0xffffffff; + t[4] += t[3] >> 32; t[3] &= 0xffffffff; + t[5] += t[4] >> 32; t[4] &= 0xffffffff; + t[6] += t[5] >> 32; t[5] &= 0xffffffff; + t[7] += t[6] >> 32; t[6] &= 0xffffffff; + r[0] = t[0]; + r[1] = t[1]; + r[2] = t[2]; + r[3] = t[3]; + r[4] = t[4]; + r[5] = t[5]; + r[6] = t[6]; + r[7] = t[7]; + + return MP_OKAY; +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * a A multi-precision integer. + */ +static void sp_256_from_mp(sp_digit* r, int max, mp_int* a) +{ +#if DIGIT_BIT == 32 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < max; j++) + r[j] = 0; +#elif DIGIT_BIT > 32 + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= a->dp[i] << s; + r[j] &= 0xffffffff; + s = 32 - s; + if (j + 1 >= max) + break; + r[++j] = a->dp[i] >> s; + while (s + 32 <= DIGIT_BIT) { + s += 32; + r[j] &= 0xffffffff; + if (j + 1 >= max) + break; + if (s < DIGIT_BIT) + r[++j] = a->dp[i] >> s; + else + r[++j] = 0; + } + s = DIGIT_BIT - s; + } + + for (j++; j < max; j++) + r[j] = 0; +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 32) { + r[j] &= 0xffffffff; + if (j + 1 >= max) + break; + s = 32 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else + s += DIGIT_BIT; + } + + for (j++; j < max; j++) + r[j] = 0; +#endif +} + +/* Convert a point of type ecc_point to type sp_point. + * + * p Point of type sp_point (result). + * pm Point of type ecc_point. + */ +static void sp_256_point_from_ecc_point_8(sp_point* p, ecc_point* pm) +{ + XMEMSET(p->x, 0, sizeof(p->x)); + XMEMSET(p->y, 0, sizeof(p->y)); + XMEMSET(p->z, 0, sizeof(p->z)); + sp_256_from_mp(p->x, 8, pm->x); + sp_256_from_mp(p->y, 8, pm->y); + sp_256_from_mp(p->z, 8, pm->z); + p->infinity = 0; +} + +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_256_to_mp(sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (256 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { +#if DIGIT_BIT == 32 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 8); + r->used = 8; + mp_clamp(r); +#elif DIGIT_BIT < 32 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 8; i++) { + r->dp[j] |= a[i] << s; + r->dp[j] &= (1l << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + while (s + DIGIT_BIT <= 32) { + s += DIGIT_BIT; + r->dp[j] &= (1l << DIGIT_BIT) - 1; + r->dp[++j] = a[i] >> s; + } + s = 32 - s; + } + r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 8; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 32 >= DIGIT_BIT) { + #if DIGIT_BIT < 32 + r->dp[j] &= (1l << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 32 - s; + } + else + s += 32; + } + r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Convert a point of type sp_point to type ecc_point. + * + * p Point of type sp_point. + * pm Point of type ecc_point (result). + * returns MEMORY_E when allocation of memory in ecc_point fails otherwise + * MP_OKAY. + */ +static int sp_256_point_to_ecc_point_8(sp_point* p, ecc_point* pm) +{ + int err; + + err = sp_256_to_mp(p->x, pm->x); + if (err == MP_OKAY) + err = sp_256_to_mp(p->y, pm->y); + if (err == MP_OKAY) + err = sp_256_to_mp(p->z, pm->z); + + return err; +} + +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +SP_NOINLINE static int32_t sp_256_cmp_8(sp_digit* a, sp_digit* b) +{ + sp_digit r = 0; + + + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mvn r3, r3\n\t" + "mov r6, #28\n\t" + "1:\n\t" + "ldr r7, [%[a], r6]\n\t" + "ldr r5, [%[b], r6]\n\t" + "and r7, r3\n\t" + "and r5, r3\n\t" + "mov r4, r7\n\t" + "sub r7, r5\n\t" + "sbc r7, r7\n\t" + "add %[r], r7\n\t" + "mvn r7, r7\n\t" + "and r3, r7\n\t" + "sub r5, r4\n\t" + "sbc r7, r7\n\t" + "sub %[r], r7\n\t" + "mvn r7, r7\n\t" + "and r3, r7\n\t" + "sub r6, #4\n\t" + "cmp r6, #0\n\t" + "bge 1b\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "r3", "r4", "r5", "r6", "r7" + ); + + return r; +} + +/* Normalize the values in each word to 32. + * + * a Array of sp_digit to normalize. + */ +#define sp_256_norm_8(a) + +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not copying. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +SP_NOINLINE static sp_digit sp_256_cond_sub_8(sp_digit* r, sp_digit* a, + sp_digit* b, sp_digit m) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r5, #32\n\t" + "mov r8, r5\n\t" + "mov r7, #0\n\t" + "1:\n\t" + "ldr r6, [%[b], r7]\n\t" + "and r6, %[m]\n\t" + "mov r5, #0\n\t" + "sub r5, %[c]\n\t" + "ldr r5, [%[a], r7]\n\t" + "sbc r5, r6\n\t" + "sbc %[c], %[c]\n\t" + "str r5, [%[r], r7]\n\t" + "add r7, #4\n\t" + "cmp r7, r8\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r5", "r6", "r7", "r8" + ); + + return c; +} + +/* Reduce the number back to 256 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +SP_NOINLINE static void sp_256_mont_reduce_8(sp_digit* a, sp_digit* m, + sp_digit mp) +{ + (void)mp; + (void)m; + + __asm__ __volatile__ ( + "mov r2, #0\n\t" + "mov r1, #0\n\t" + "# i = 0\n\t" + "mov r8, r2\n\t" + "\n1:\n\t" + "mov r4, #0\n\t" + "# mu = a[i] * 1 (mp) = a[i]\n\t" + "ldr r3, [%[a]]\n\t" + "# a[i+0] += -1 * mu\n\t" + "mov r5, r3\n\t" + "str r4, [%[a], #0]\n\t" + "# a[i+1] += -1 * mu\n\t" + "ldr r6, [%[a], #4]\n\t" + "mov r4, r3\n\t" + "sub r5, r3\n\t" + "sbc r4, r2\n\t" + "add r5, r6\n\t" + "adc r4, r2\n\t" + "str r5, [%[a], #4]\n\t" + "# a[i+2] += -1 * mu\n\t" + "ldr r6, [%[a], #8]\n\t" + "mov r5, r3\n\t" + "sub r4, r3\n\t" + "sbc r5, r2\n\t" + "add r4, r6\n\t" + "adc r5, r2\n\t" + "str r4, [%[a], #8]\n\t" + "# a[i+3] += 0 * mu\n\t" + "ldr r6, [%[a], #12]\n\t" + "mov r4, #0\n\t" + "add r5, r6\n\t" + "adc r4, r2\n\t" + "str r5, [%[a], #12]\n\t" + "# a[i+4] += 0 * mu\n\t" + "ldr r6, [%[a], #16]\n\t" + "mov r5, #0\n\t" + "add r4, r6\n\t" + "adc r5, r2\n\t" + "str r4, [%[a], #16]\n\t" + "# a[i+5] += 0 * mu\n\t" + "ldr r6, [%[a], #20]\n\t" + "mov r4, #0\n\t" + "add r5, r6\n\t" + "adc r4, r2\n\t" + "str r5, [%[a], #20]\n\t" + "# a[i+6] += 1 * mu\n\t" + "ldr r6, [%[a], #24]\n\t" + "mov r5, #0\n\t" + "add r4, r3\n\t" + "adc r5, r2\n\t" + "add r4, r6\n\t" + "adc r5, r2\n\t" + "str r4, [%[a], #24]\n\t" + "# a[i+7] += -1 * mu\n\t" + "ldr r6, [%[a], #28]\n\t" + "ldr r7, [%[a], #32]\n\t" + "add r4, r1, r3\n\t" + "mov r1, #0\n\t" + "adc r1, r2\n\t" + "sub r5, r3\n\t" + "sbc r4, r2\n\t" + "sbc r1, r2\n\t" + "add r5, r6\n\t" + "adc r4, r7\n\t" + "adc r1, r2\n\t" + "str r5, [%[a], #28]\n\t" + "str r4, [%[a], #32]\n\t" + "# i += 1\n\t" + "mov r6, #4\n\t" + "add r8, r6\n\t" + "add %[a], #4\n\t" + "mov r6, #32\n\t" + "cmp r8, r6\n\t" + "blt 1b\n\t" + "sub %[a], #32\n\t" + "mov r3, r1\n\t" + "sub r1, #1\n\t" + "mvn r1, r1\n\t" + "ldr r5, [%[a],#32]\n\t" + "ldr r4, [%[a],#36]\n\t" + "ldr r6, [%[a],#40]\n\t" + "ldr r7, [%[a],#44]\n\t" + "sub r5, r1\n\t" + "sbc r4, r1\n\t" + "sbc r6, r1\n\t" + "sbc r7, r2\n\t" + "str r5, [%[a],#0]\n\t" + "str r4, [%[a],#4]\n\t" + "str r6, [%[a],#8]\n\t" + "str r7, [%[a],#12]\n\t" + "ldr r5, [%[a],#48]\n\t" + "ldr r4, [%[a],#52]\n\t" + "ldr r6, [%[a],#56]\n\t" + "ldr r7, [%[a],#60]\n\t" + "sbc r5, r2\n\t" + "sbc r4, r2\n\t" + "sbc r6, r3\n\t" + "sbc r7, r1\n\t" + "str r5, [%[a],#16]\n\t" + "str r4, [%[a],#20]\n\t" + "str r6, [%[a],#24]\n\t" + "str r7, [%[a],#28]\n\t" + : [a] "+r" (a) + : + : "memory", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8" + ); + + + (void)m; + (void)mp; +} + +/* Reduce the number back to 256 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +SP_NOINLINE static void sp_256_mont_reduce_order_8(sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "mov r8, %[mp]\n\t" + "mov r12, %[ca]\n\t" + "mov r14, %[m]\n\t" + "mov r9, %[a]\n\t" + "mov r4, #0\n\t" + "# i = 0\n\t" + "mov r11, r4\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "mov %[ca], #0\n\t" + "# mu = a[i] * mp\n\t" + "mov %[mp], r8\n\t" + "ldr %[a], [%[a]]\n\t" + "mul %[mp], %[a]\n\t" + "mov %[m], r14\n\t" + "mov r10, r9\n\t" + "\n2:\n\t" + "# a[i+j] += m[j] * mu\n\t" + "mov %[a], r10\n\t" + "ldr %[a], [%[a]]\n\t" + "mov %[ca], #0\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "# Multiply m[j] and mu - Start\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r6, %[mp], #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add %[a], r7\n\t" + "adc r5, %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add %[a], r6\n\t" + "adc r5, r7\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r6, %[mp], #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r5, r7\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add %[a], r6\n\t" + "adc r5, r7\n\t" + "# Multiply m[j] and mu - Done\n\t" + "add r4, %[a]\n\t" + "adc r5, %[ca]\n\t" + "mov %[a], r10\n\t" + "str r4, [%[a]]\n\t" + "mov r6, #4\n\t" + "add %[m], #4\n\t" + "add r10, r6\n\t" + "mov r4, #28\n\t" + "add r4, r9\n\t" + "cmp r10, r4\n\t" + "blt 2b\n\t" + "# a[i+7] += m[7] * mu\n\t" + "mov %[ca], #0\n\t" + "mov r4, r12\n\t" + "mov %[a], #0\n\t" + "# Multiply m[7] and mu - Start\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r6, %[mp], #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r5, r7\n\t" + "adc r4, %[ca]\n\t" + "adc %[a], %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r5, r6\n\t" + "adc r4, r7\n\t" + "adc %[a], %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsr r6, %[mp], #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc %[a], %[ca]\n\t" + "ldr r7, [%[m]]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r5, r6\n\t" + "adc r4, r7\n\t" + "adc %[a], %[ca]\n\t" + "# Multiply m[7] and mu - Done\n\t" + "mov %[ca], %[a]\n\t" + "mov %[a], r10\n\t" + "ldr r7, [%[a], #4]\n\t" + "ldr %[a], [%[a]]\n\t" + "mov r6, #0\n\t" + "add r5, %[a]\n\t" + "adc r7, r4\n\t" + "adc %[ca], r6\n\t" + "mov %[a], r10\n\t" + "str r5, [%[a]]\n\t" + "str r7, [%[a], #4]\n\t" + "# i += 1\n\t" + "mov r6, #4\n\t" + "add r9, r6\n\t" + "add r11, r6\n\t" + "mov r12, %[ca]\n\t" + "mov %[a], r9\n\t" + "mov r4, #32\n\t" + "cmp r11, r4\n\t" + "blt 1b\n\t" + "mov %[m], r14\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14" + ); + + sp_256_cond_sub_8(a - 8, a, m, (sp_digit)0 - ca); +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_256_mul_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit tmp[8 * 2]; + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r8, r3\n\t" + "mov r11, %[r]\n\t" + "mov r9, %[a]\n\t" + "mov r10, %[b]\n\t" + "mov r6, #32\n\t" + "add r6, r9\n\t" + "mov r12, r6\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r5, #0\n\t" + "mov r6, #28\n\t" + "mov %[a], r8\n\t" + "sub %[a], r6\n\t" + "sbc r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], r6\n\t" + "mov %[b], r8\n\t" + "sub %[b], %[a]\n\t" + "add %[a], r9\n\t" + "add %[b], r10\n\t" + "\n2:\n\t" + "# Multiply Start\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [%[b]]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [%[b]]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [%[b]]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [%[b]]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Multiply Done\n\t" + "add %[a], #4\n\t" + "sub %[b], #4\n\t" + "cmp %[a], r12\n\t" + "beq 3f\n\t" + "mov r6, r8\n\t" + "add r6, r9\n\t" + "cmp %[a], r6\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r11\n\t" + "mov r7, r8\n\t" + "str r3, [%[r], r7]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "add r7, #4\n\t" + "mov r8, r7\n\t" + "mov r6, #56\n\t" + "cmp r7, r6\n\t" + "ble 1b\n\t" + "str r3, [%[r], r7]\n\t" + "mov %[a], r9\n\t" + "mov %[b], r10\n\t" + : + : [r] "r" (tmp), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_256_mont_mul_8(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_256_mul_8(r, a, b); + sp_256_mont_reduce_8(r, m, mp); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_256_sqr_8(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r5, #0\n\t" + "mov r8, r3\n\t" + "mov r11, %[r]\n\t" + "mov r6, #64\n\t" + "neg r6, r6\n\t" + "add sp, r6\n\t" + "mov r10, sp\n\t" + "mov r9, %[a]\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r6, #28\n\t" + "mov %[a], r8\n\t" + "sub %[a], r6\n\t" + "sbc r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], r6\n\t" + "mov r2, r8\n\t" + "sub r2, %[a]\n\t" + "add %[a], r9\n\t" + "add r2, r9\n\t" + "\n2:\n\t" + "cmp r2, %[a]\n\t" + "beq 4f\n\t" + "# Multiply * 2: Start\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [r2]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, r7, #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [r2]\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "ldr r7, [r2]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r7, [r2]\n\t" + "lsl r7, r7, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Multiply * 2: Done\n\t" + "bal 5f\n\t" + "\n4:\n\t" + "# Square: Start\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "lsr r6, r6, #16\n\t" + "mul r6, r6\n\t" + "add r3, r6\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "mul r7, r7\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "lsr r6, r6, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #15\n\t" + "lsl r6, r6, #17\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# Square: Done\n\t" + "\n5:\n\t" + "add %[a], #4\n\t" + "sub r2, #4\n\t" + "mov r6, #32\n\t" + "add r6, r9\n\t" + "cmp %[a], r6\n\t" + "beq 3f\n\t" + "cmp %[a], r2\n\t" + "bgt 3f\n\t" + "mov r7, r8\n\t" + "add r7, r9\n\t" + "cmp %[a], r7\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r10\n\t" + "mov r7, r8\n\t" + "str r3, [%[r], r7]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "add r7, #4\n\t" + "mov r8, r7\n\t" + "mov r6, #56\n\t" + "cmp r7, r6\n\t" + "ble 1b\n\t" + "mov %[a], r9\n\t" + "str r3, [%[r], r7]\n\t" + "mov %[r], r11\n\t" + "mov %[a], r10\n\t" + "mov r3, #60\n\t" + "\n4:\n\t" + "ldr r6, [%[a], r3]\n\t" + "str r6, [%[r], r3]\n\t" + "sub r3, #4\n\t" + "bge 4b\n\t" + "mov r6, #64\n\t" + "add sp, r6\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11" + ); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_256_mont_sqr_8(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_256_sqr_8(r, a); + sp_256_mont_reduce_8(r, m, mp); +} + +#if !defined(WOLFSSL_SP_SMALL) || defined(HAVE_COMP_KEY) +/* Square the Montgomery form number a number of times. (r = a ^ n mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * n Number of times to square. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_256_mont_sqr_n_8(sp_digit* r, sp_digit* a, int n, + sp_digit* m, sp_digit mp) +{ + sp_256_mont_sqr_8(r, a, m, mp); + for (; n > 1; n--) + sp_256_mont_sqr_8(r, r, m, mp); +} + +#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */ +#ifdef WOLFSSL_SP_SMALL +/* Mod-2 for the P256 curve. */ +static const uint32_t p256_mod_2[8] = { + 0xfffffffd,0xffffffff,0xffffffff,0x00000000,0x00000000,0x00000000, + 0x00000001,0xffffffff +}; +#endif /* !WOLFSSL_SP_SMALL */ + +/* Invert the number, in Montgomery form, modulo the modulus (prime) of the + * P256 curve. (r = 1 / a mod m) + * + * r Inverse result. + * a Number to invert. + * td Temporary data. + */ +static void sp_256_mont_inv_8(sp_digit* r, sp_digit* a, sp_digit* td) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* t = td; + int i; + + XMEMCPY(t, a, sizeof(sp_digit) * 8); + for (i=254; i>=0; i--) { + sp_256_mont_sqr_8(t, t, p256_mod, p256_mp_mod); + if (p256_mod_2[i / 32] & ((sp_digit)1 << (i % 32))) + sp_256_mont_mul_8(t, t, a, p256_mod, p256_mp_mod); + } + XMEMCPY(r, t, sizeof(sp_digit) * 8); +#else + sp_digit* t = td; + sp_digit* t2 = td + 2 * 8; + sp_digit* t3 = td + 4 * 8; + + /* t = a^2 */ + sp_256_mont_sqr_8(t, a, p256_mod, p256_mp_mod); + /* t = a^3 = t * a */ + sp_256_mont_mul_8(t, t, a, p256_mod, p256_mp_mod); + /* t2= a^c = t ^ 2 ^ 2 */ + sp_256_mont_sqr_n_8(t2, t, 2, p256_mod, p256_mp_mod); + /* t3= a^d = t2 * a */ + sp_256_mont_mul_8(t3, t2, a, p256_mod, p256_mp_mod); + /* t = a^f = t2 * t */ + sp_256_mont_mul_8(t, t2, t, p256_mod, p256_mp_mod); + /* t2= a^f0 = t ^ 2 ^ 4 */ + sp_256_mont_sqr_n_8(t2, t, 4, p256_mod, p256_mp_mod); + /* t3= a^fd = t2 * t3 */ + sp_256_mont_mul_8(t3, t2, t3, p256_mod, p256_mp_mod); + /* t = a^ff = t2 * t */ + sp_256_mont_mul_8(t, t2, t, p256_mod, p256_mp_mod); + /* t2= a^ff00 = t ^ 2 ^ 8 */ + sp_256_mont_sqr_n_8(t2, t, 8, p256_mod, p256_mp_mod); + /* t3= a^fffd = t2 * t3 */ + sp_256_mont_mul_8(t3, t2, t3, p256_mod, p256_mp_mod); + /* t = a^ffff = t2 * t */ + sp_256_mont_mul_8(t, t2, t, p256_mod, p256_mp_mod); + /* t2= a^ffff0000 = t ^ 2 ^ 16 */ + sp_256_mont_sqr_n_8(t2, t, 16, p256_mod, p256_mp_mod); + /* t3= a^fffffffd = t2 * t3 */ + sp_256_mont_mul_8(t3, t2, t3, p256_mod, p256_mp_mod); + /* t = a^ffffffff = t2 * t */ + sp_256_mont_mul_8(t, t2, t, p256_mod, p256_mp_mod); + /* t = a^ffffffff00000000 = t ^ 2 ^ 32 */ + sp_256_mont_sqr_n_8(t2, t, 32, p256_mod, p256_mp_mod); + /* t2= a^ffffffffffffffff = t2 * t */ + sp_256_mont_mul_8(t, t2, t, p256_mod, p256_mp_mod); + /* t2= a^ffffffff00000001 = t2 * a */ + sp_256_mont_mul_8(t2, t2, a, p256_mod, p256_mp_mod); + /* t2= a^ffffffff000000010000000000000000000000000000000000000000 + * = t2 ^ 2 ^ 160 */ + sp_256_mont_sqr_n_8(t2, t2, 160, p256_mod, p256_mp_mod); + /* t2= a^ffffffff00000001000000000000000000000000ffffffffffffffff + * = t2 * t */ + sp_256_mont_mul_8(t2, t2, t, p256_mod, p256_mp_mod); + /* t2= a^ffffffff00000001000000000000000000000000ffffffffffffffff00000000 + * = t2 ^ 2 ^ 32 */ + sp_256_mont_sqr_n_8(t2, t2, 32, p256_mod, p256_mp_mod); + /* r = a^ffffffff00000001000000000000000000000000fffffffffffffffffffffffd + * = t2 * t3 */ + sp_256_mont_mul_8(r, t2, t3, p256_mod, p256_mp_mod); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Map the Montgomery form projective co-ordinate point to an affine point. + * + * r Resulting affine co-ordinate point. + * p Montgomery form projective co-ordinate point. + * t Temporary ordinate data. + */ +static void sp_256_map_8(sp_point* r, sp_point* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*8; + int32_t n; + + sp_256_mont_inv_8(t1, p->z, t + 2*8); + + sp_256_mont_sqr_8(t2, t1, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t1, t2, t1, p256_mod, p256_mp_mod); + + /* x /= z^2 */ + sp_256_mont_mul_8(r->x, p->x, t2, p256_mod, p256_mp_mod); + XMEMSET(r->x + 8, 0, sizeof(r->x) / 2); + sp_256_mont_reduce_8(r->x, p256_mod, p256_mp_mod); + /* Reduce x to less than modulus */ + n = sp_256_cmp_8(r->x, p256_mod); + sp_256_cond_sub_8(r->x, r->x, p256_mod, 0 - (n >= 0)); + sp_256_norm_8(r->x); + + /* y /= z^3 */ + sp_256_mont_mul_8(r->y, p->y, t1, p256_mod, p256_mp_mod); + XMEMSET(r->y + 8, 0, sizeof(r->y) / 2); + sp_256_mont_reduce_8(r->y, p256_mod, p256_mp_mod); + /* Reduce y to less than modulus */ + n = sp_256_cmp_8(r->y, p256_mod); + sp_256_cond_sub_8(r->y, r->y, p256_mod, 0 - (n >= 0)); + sp_256_norm_8(r->y); + + XMEMSET(r->z, 0, sizeof(r->z)); + r->z[0] = 1; + +} + +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_256_add_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r6, %[a]\n\t" + "mov r7, #0\n\t" + "add r6, #32\n\t" + "sub r7, #1\n\t" + "\n1:\n\t" + "add %[c], r7\n\t" + "ldr r4, [%[a]]\n\t" + "ldr r5, [%[b]]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r]]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + "add %[a], #4\n\t" + "add %[b], #4\n\t" + "add %[r], #4\n\t" + "cmp %[a], r6\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r7" + ); + + return c; +} + +#else +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_256_add_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "add r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adc r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Add two Montgomery form numbers (r = a + b % m). + * + * r Result of addition. + * a First number to add in Montogmery form. + * b Second number to add in Montogmery form. + * m Modulus (prime). + */ +SP_NOINLINE static void sp_256_mont_add_8(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m) +{ + (void)m; + + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "ldr r4, [%[a],#0]\n\t" + "ldr r5, [%[a],#4]\n\t" + "ldr r6, [%[b],#0]\n\t" + "ldr r7, [%[b],#4]\n\t" + "add r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r],#0]\n\t" + "str r5, [%[r],#4]\n\t" + "ldr r4, [%[a],#8]\n\t" + "ldr r5, [%[a],#12]\n\t" + "ldr r6, [%[b],#8]\n\t" + "ldr r7, [%[b],#12]\n\t" + "adc r4, r6\n\t" + "adc r5, r7\n\t" + "str r4, [%[r],#8]\n\t" + "str r5, [%[r],#12]\n\t" + "ldr r4, [%[a],#16]\n\t" + "ldr r5, [%[a],#20]\n\t" + "ldr r6, [%[b],#16]\n\t" + "ldr r7, [%[b],#20]\n\t" + "adc r4, r6\n\t" + "adc r5, r7\n\t" + "mov r8, r4\n\t" + "mov r9, r5\n\t" + "ldr r4, [%[a],#24]\n\t" + "ldr r5, [%[a],#28]\n\t" + "ldr r6, [%[b],#24]\n\t" + "ldr r7, [%[b],#28]\n\t" + "adc r4, r6\n\t" + "adc r5, r7\n\t" + "mov r10, r4\n\t" + "mov r11, r5\n\t" + "adc r3, r3\n\t" + "mov r6, r3\n\t" + "sub r3, #1\n\t" + "mvn r3, r3\n\t" + "mov r7, #0\n\t" + "ldr r4, [%[r],#0]\n\t" + "ldr r5, [%[r],#4]\n\t" + "sub r4, r3\n\t" + "sbc r5, r3\n\t" + "str r4, [%[r],#0]\n\t" + "str r5, [%[r],#4]\n\t" + "ldr r4, [%[r],#8]\n\t" + "ldr r5, [%[r],#12]\n\t" + "sbc r4, r3\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r],#8]\n\t" + "str r5, [%[r],#12]\n\t" + "mov r4, r8\n\t" + "mov r5, r9\n\t" + "sbc r4, r7\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r],#16]\n\t" + "str r5, [%[r],#20]\n\t" + "mov r4, r10\n\t" + "mov r5, r11\n\t" + "sbc r4, r6\n\t" + "sbc r5, r3\n\t" + "str r4, [%[r],#24]\n\t" + "str r5, [%[r],#28]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11" + ); +} + +/* Double a Montgomery form number (r = a + a % m). + * + * r Result of doubling. + * a Number to double in Montogmery form. + * m Modulus (prime). + */ +SP_NOINLINE static void sp_256_mont_dbl_8(sp_digit* r, sp_digit* a, sp_digit* m) +{ + (void)m; + + __asm__ __volatile__ ( + "ldr r4, [%[a],#0]\n\t" + "ldr r5, [%[a],#4]\n\t" + "ldr r6, [%[a],#8]\n\t" + "ldr r7, [%[a],#12]\n\t" + "add r4, r4\n\t" + "adc r5, r5\n\t" + "adc r6, r6\n\t" + "adc r7, r7\n\t" + "str r4, [%[r],#0]\n\t" + "str r5, [%[r],#4]\n\t" + "str r6, [%[r],#8]\n\t" + "str r7, [%[r],#12]\n\t" + "ldr r4, [%[a],#16]\n\t" + "ldr r5, [%[a],#20]\n\t" + "ldr r6, [%[a],#24]\n\t" + "ldr r7, [%[a],#28]\n\t" + "adc r4, r4\n\t" + "adc r5, r5\n\t" + "adc r6, r6\n\t" + "adc r7, r7\n\t" + "mov r8, r4\n\t" + "mov r9, r5\n\t" + "mov r10, r6\n\t" + "mov r11, r7\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "adc r3, r3\n\t" + "mov r2, r3\n\t" + "sub r3, #1\n\t" + "mvn r3, r3\n\t" + "ldr r4, [%[r],#0]\n\t" + "ldr r5, [%[r],#4]\n\t" + "ldr r6, [%[r],#8]\n\t" + "sub r4, r3\n\t" + "sbc r5, r3\n\t" + "sbc r6, r3\n\t" + "str r4, [%[r],#0]\n\t" + "str r5, [%[r],#4]\n\t" + "str r6, [%[r],#8]\n\t" + "ldr r4, [%[r],#12]\n\t" + "mov r5, r8\n\t" + "mov r6, r9\n\t" + "sbc r4, r7\n\t" + "sbc r5, r7\n\t" + "sbc r6, r7\n\t" + "str r4, [%[r],#12]\n\t" + "str r5, [%[r],#16]\n\t" + "str r6, [%[r],#20]\n\t" + "mov r4, r10\n\t" + "mov r5, r11\n\t" + "sbc r4, r2\n\t" + "sbc r5, r3\n\t" + "str r4, [%[r],#24]\n\t" + "str r5, [%[r],#28]\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r3", "r2", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11" + ); +} + +/* Triple a Montgomery form number (r = a + a + a % m). + * + * r Result of Tripling. + * a Number to triple in Montogmery form. + * m Modulus (prime). + */ +SP_NOINLINE static void sp_256_mont_tpl_8(sp_digit* r, sp_digit* a, sp_digit* m) +{ + (void)m; + + __asm__ __volatile__ ( + "ldr r6, [%[a],#0]\n\t" + "ldr r7, [%[a],#4]\n\t" + "ldr r4, [%[a],#8]\n\t" + "ldr r5, [%[a],#12]\n\t" + "add r6, r6\n\t" + "adc r7, r7\n\t" + "adc r4, r4\n\t" + "adc r5, r5\n\t" + "mov r8, r4\n\t" + "mov r9, r5\n\t" + "ldr r2, [%[a],#16]\n\t" + "ldr r3, [%[a],#20]\n\t" + "ldr r4, [%[a],#24]\n\t" + "ldr r5, [%[a],#28]\n\t" + "adc r2, r2\n\t" + "adc r3, r3\n\t" + "adc r4, r4\n\t" + "adc r5, r5\n\t" + "mov r10, r2\n\t" + "mov r11, r3\n\t" + "mov r12, r4\n\t" + "mov r14, r5\n\t" + "mov r3, #0\n\t" + "mov r5, #0\n\t" + "adc r3, r3\n\t" + "mov r4, r3\n\t" + "sub r3, #1\n\t" + "mvn r3, r3\n\t" + "sub r6, r3\n\t" + "sbc r7, r3\n\t" + "mov r2, r8\n\t" + "sbc r2, r3\n\t" + "mov r8, r2\n\t" + "mov r2, r9\n\t" + "sbc r2, r5\n\t" + "mov r9, r2\n\t" + "mov r2, r10\n\t" + "sbc r2, r5\n\t" + "mov r10, r2\n\t" + "mov r2, r11\n\t" + "sbc r2, r5\n\t" + "mov r11, r2\n\t" + "mov r2, r12\n\t" + "sbc r2, r4\n\t" + "mov r12, r2\n\t" + "mov r2, r14\n\t" + "sbc r2, r3\n\t" + "mov r14, r2\n\t" + "ldr r2, [%[a],#0]\n\t" + "ldr r3, [%[a],#4]\n\t" + "add r6, r2\n\t" + "adc r7, r3\n\t" + "ldr r2, [%[a],#8]\n\t" + "ldr r3, [%[a],#12]\n\t" + "mov r4, r8\n\t" + "mov r5, r9\n\t" + "adc r2, r4\n\t" + "adc r3, r5\n\t" + "mov r8, r2\n\t" + "mov r9, r3\n\t" + "ldr r2, [%[a],#16]\n\t" + "ldr r3, [%[a],#20]\n\t" + "mov r4, r10\n\t" + "mov r5, r11\n\t" + "adc r2, r4\n\t" + "adc r3, r5\n\t" + "mov r10, r2\n\t" + "mov r11, r3\n\t" + "ldr r2, [%[a],#24]\n\t" + "ldr r3, [%[a],#28]\n\t" + "mov r4, r12\n\t" + "mov r5, r14\n\t" + "adc r2, r4\n\t" + "adc r3, r5\n\t" + "mov r12, r2\n\t" + "mov r14, r3\n\t" + "mov r3, #0\n\t" + "mov r5, #0\n\t" + "adc r3, r3\n\t" + "mov r4, r3\n\t" + "sub r3, #1\n\t" + "mvn r3, r3\n\t" + "sub r6, r3\n\t" + "str r6, [%[r],#0]\n\t" + "sbc r7, r3\n\t" + "str r7, [%[r],#4]\n\t" + "mov r2, r8\n\t" + "sbc r2, r3\n\t" + "str r2, [%[r],#8]\n\t" + "mov r2, r9\n\t" + "sbc r2, r5\n\t" + "str r2, [%[r],#12]\n\t" + "mov r2, r10\n\t" + "sbc r2, r5\n\t" + "str r2, [%[r],#16]\n\t" + "mov r2, r11\n\t" + "sbc r2, r5\n\t" + "str r2, [%[r],#20]\n\t" + "mov r2, r12\n\t" + "sbc r2, r4\n\t" + "str r2, [%[r],#24]\n\t" + "mov r2, r14\n\t" + "sbc r2, r3\n\t" + "str r2, [%[r],#28]\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14" + ); +} + +/* Subtract two Montgomery form numbers (r = a - b % m). + * + * r Result of subtration. + * a Number to subtract from in Montogmery form. + * b Number to subtract with in Montogmery form. + * m Modulus (prime). + */ +SP_NOINLINE static void sp_256_mont_sub_8(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m) +{ + (void)m; + + __asm__ __volatile__ ( + "ldr r4, [%[a],#0]\n\t" + "ldr r5, [%[a],#4]\n\t" + "ldr r6, [%[b],#0]\n\t" + "ldr r7, [%[b],#4]\n\t" + "sub r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r],#0]\n\t" + "str r5, [%[r],#4]\n\t" + "ldr r4, [%[a],#8]\n\t" + "ldr r5, [%[a],#12]\n\t" + "ldr r6, [%[b],#8]\n\t" + "ldr r7, [%[b],#12]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r],#8]\n\t" + "str r5, [%[r],#12]\n\t" + "ldr r4, [%[a],#16]\n\t" + "ldr r5, [%[a],#20]\n\t" + "ldr r6, [%[b],#16]\n\t" + "ldr r7, [%[b],#20]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "mov r8, r4\n\t" + "mov r9, r5\n\t" + "ldr r4, [%[a],#24]\n\t" + "ldr r5, [%[a],#28]\n\t" + "ldr r6, [%[b],#24]\n\t" + "ldr r7, [%[b],#28]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "mov r10, r4\n\t" + "mov r11, r5\n\t" + "sbc r3, r3\n\t" + "lsr r7, r3, #31\n\t" + "mov r6, #0\n\t" + "ldr r4, [%[r],#0]\n\t" + "ldr r5, [%[r],#4]\n\t" + "add r4, r3\n\t" + "adc r5, r3\n\t" + "str r4, [%[r],#0]\n\t" + "str r5, [%[r],#4]\n\t" + "ldr r4, [%[r],#8]\n\t" + "ldr r5, [%[r],#12]\n\t" + "adc r4, r3\n\t" + "adc r5, r6\n\t" + "str r4, [%[r],#8]\n\t" + "str r5, [%[r],#12]\n\t" + "mov r4, r8\n\t" + "mov r5, r9\n\t" + "adc r4, r6\n\t" + "adc r5, r6\n\t" + "str r4, [%[r],#16]\n\t" + "str r5, [%[r],#20]\n\t" + "mov r4, r10\n\t" + "mov r5, r11\n\t" + "adc r4, r7\n\t" + "adc r5, r3\n\t" + "str r4, [%[r],#24]\n\t" + "str r5, [%[r],#28]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11" + ); +} + +/* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m) + * + * r Result of division by 2. + * a Number to divide. + * m Modulus (prime). + */ +SP_NOINLINE static void sp_256_div2_8(sp_digit* r, sp_digit* a, sp_digit* m) +{ + __asm__ __volatile__ ( + "ldr r7, [%[a], #0]\n\t" + "lsl r7, r7, #31\n\t" + "lsr r7, r7, #31\n\t" + "mov r5, #0\n\t" + "sub r5, r7\n\t" + "mov r7, #0\n\t" + "lsl r6, r5, #31\n\t" + "lsr r6, r6, #31\n\t" + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "add r3, r5\n\t" + "adc r4, r5\n\t" + "str r3, [%[r], #0]\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r3, [%[a], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "adc r3, r5\n\t" + "adc r4, r7\n\t" + "str r3, [%[r], #8]\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "adc r3, r7\n\t" + "adc r4, r7\n\t" + "str r3, [%[r], #16]\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r3, [%[a], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "adc r3, r6\n\t" + "adc r4, r5\n\t" + "adc r7, r7\n\t" + "lsl r7, r7, #31\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, #31\n\t" + "lsr r6, r4, #1\n\t" + "lsl r4, r4, #31\n\t" + "orr r5, r4\n\t" + "orr r6, r7\n\t" + "mov r7, r3\n\t" + "str r5, [%[r], #24]\n\t" + "str r6, [%[r], #28]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, #31\n\t" + "lsr r6, r4, #1\n\t" + "lsl r4, r4, #31\n\t" + "orr r5, r4\n\t" + "orr r6, r7\n\t" + "mov r7, r3\n\t" + "str r5, [%[r], #16]\n\t" + "str r6, [%[r], #20]\n\t" + "ldr r3, [%[a], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, #31\n\t" + "lsr r6, r4, #1\n\t" + "lsl r4, r4, #31\n\t" + "orr r5, r4\n\t" + "orr r6, r7\n\t" + "mov r7, r3\n\t" + "str r5, [%[r], #8]\n\t" + "str r6, [%[r], #12]\n\t" + "ldr r3, [%[r], #0]\n\t" + "ldr r4, [%[r], #4]\n\t" + "lsr r5, r3, #1\n\t" + "lsr r6, r4, #1\n\t" + "lsl r4, r4, #31\n\t" + "orr r5, r4\n\t" + "orr r6, r7\n\t" + "str r5, [%[r], #0]\n\t" + "str r6, [%[r], #4]\n\t" + : + : [r] "r" (r), [a] "r" (a), [m] "r" (m) + : "memory", "r3", "r4", "r5", "r6", "r7" + ); +} + +/* Double the Montgomery form projective point p. + * + * r Result of doubling point. + * p Point to double. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_dbl_8(sp_point* r, sp_point* p, sp_digit* t) +{ + sp_point* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*8; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* When infinity don't double point passed in - constant time. */ + rp[0] = r; + rp[1] = (sp_point*)t; + XMEMSET(rp[1], 0, sizeof(sp_point)); + x = rp[p->infinity]->x; + y = rp[p->infinity]->y; + z = rp[p->infinity]->z; + /* Put point to double into result - good for infinty. */ + if (r != p) { + for (i=0; i<8; i++) + r->x[i] = p->x[i]; + for (i=0; i<8; i++) + r->y[i] = p->y[i]; + for (i=0; i<8; i++) + r->z[i] = p->z[i]; + r->infinity = p->infinity; + } + + /* T1 = Z * Z */ + sp_256_mont_sqr_8(t1, z, p256_mod, p256_mp_mod); + /* Z = Y * Z */ + sp_256_mont_mul_8(z, y, z, p256_mod, p256_mp_mod); + /* Z = 2Z */ + sp_256_mont_dbl_8(z, z, p256_mod); + /* T2 = X - T1 */ + sp_256_mont_sub_8(t2, x, t1, p256_mod); + /* T1 = X + T1 */ + sp_256_mont_add_8(t1, x, t1, p256_mod); + /* T2 = T1 * T2 */ + sp_256_mont_mul_8(t2, t1, t2, p256_mod, p256_mp_mod); + /* T1 = 3T2 */ + sp_256_mont_tpl_8(t1, t2, p256_mod); + /* Y = 2Y */ + sp_256_mont_dbl_8(y, y, p256_mod); + /* Y = Y * Y */ + sp_256_mont_sqr_8(y, y, p256_mod, p256_mp_mod); + /* T2 = Y * Y */ + sp_256_mont_sqr_8(t2, y, p256_mod, p256_mp_mod); + /* T2 = T2/2 */ + sp_256_div2_8(t2, t2, p256_mod); + /* Y = Y * X */ + sp_256_mont_mul_8(y, y, x, p256_mod, p256_mp_mod); + /* X = T1 * T1 */ + sp_256_mont_mul_8(x, t1, t1, p256_mod, p256_mp_mod); + /* X = X - Y */ + sp_256_mont_sub_8(x, x, y, p256_mod); + /* X = X - Y */ + sp_256_mont_sub_8(x, x, y, p256_mod); + /* Y = Y - X */ + sp_256_mont_sub_8(y, y, x, p256_mod); + /* Y = Y * T1 */ + sp_256_mont_mul_8(y, y, t1, p256_mod, p256_mp_mod); + /* Y = Y - T2 */ + sp_256_mont_sub_8(y, y, t2, p256_mod); + +} + +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_256_sub_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r6, %[a]\n\t" + "add r6, #32\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "sub r5, %[c]\n\t" + "ldr r4, [%[a]]\n\t" + "ldr r5, [%[b]]\n\t" + "sbc r4, r5\n\t" + "str r4, [%[r]]\n\t" + "sbc %[c], %[c]\n\t" + "add %[a], #4\n\t" + "add %[b], #4\n\t" + "add %[r], #4\n\t" + "cmp %[a], r6\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6" + ); + + return c; +} + +#else +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_256_sub_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[a], #4]\n\t" + "ldr r6, [%[b], #0]\n\t" + "ldr r7, [%[b], #4]\n\t" + "sub r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #0]\n\t" + "str r5, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[a], #12]\n\t" + "ldr r6, [%[b], #8]\n\t" + "ldr r7, [%[b], #12]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #8]\n\t" + "str r5, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[a], #20]\n\t" + "ldr r6, [%[b], #16]\n\t" + "ldr r7, [%[b], #20]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #16]\n\t" + "str r5, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[a], #28]\n\t" + "ldr r6, [%[b], #24]\n\t" + "ldr r7, [%[b], #28]\n\t" + "sbc r4, r6\n\t" + "sbc r5, r7\n\t" + "str r4, [%[r], #24]\n\t" + "str r5, [%[r], #28]\n\t" + "sbc %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r7" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Compare two numbers to determine if they are equal. + * Constant time implementation. + * + * a First number to compare. + * b Second number to compare. + * returns 1 when equal and 0 otherwise. + */ +static int sp_256_cmp_equal_8(const sp_digit* a, const sp_digit* b) +{ + return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]) | (a[3] ^ b[3]) | + (a[4] ^ b[4]) | (a[5] ^ b[5]) | (a[6] ^ b[6]) | (a[7] ^ b[7])) == 0; +} + +/* Add two Montgomery form projective points. + * + * r Result of addition. + * p Frist point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_add_8(sp_point* r, sp_point* p, sp_point* q, + sp_digit* t) +{ + sp_point* ap[2]; + sp_point* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*8; + sp_digit* t3 = t + 4*8; + sp_digit* t4 = t + 6*8; + sp_digit* t5 = t + 8*8; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + sp_point* a = p; + p = q; + q = a; + } + + /* Check double */ + sp_256_sub_8(t1, p256_mod, q->y); + sp_256_norm_8(t1); + if (sp_256_cmp_equal_8(p->x, q->x) & sp_256_cmp_equal_8(p->z, q->z) & + (sp_256_cmp_equal_8(p->y, q->y) | sp_256_cmp_equal_8(p->y, t1))) { + sp_256_proj_point_dbl_8(r, p, t); + } + else { + rp[0] = r; + rp[1] = (sp_point*)t; + XMEMSET(rp[1], 0, sizeof(sp_point)); + x = rp[p->infinity | q->infinity]->x; + y = rp[p->infinity | q->infinity]->y; + z = rp[p->infinity | q->infinity]->z; + + ap[0] = p; + ap[1] = q; + for (i=0; i<8; i++) + r->x[i] = ap[p->infinity]->x[i]; + for (i=0; i<8; i++) + r->y[i] = ap[p->infinity]->y[i]; + for (i=0; i<8; i++) + r->z[i] = ap[p->infinity]->z[i]; + r->infinity = ap[p->infinity]->infinity; + + /* U1 = X1*Z2^2 */ + sp_256_mont_sqr_8(t1, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t3, t1, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t1, t1, x, p256_mod, p256_mp_mod); + /* U2 = X2*Z1^2 */ + sp_256_mont_sqr_8(t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t4, t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t2, t2, q->x, p256_mod, p256_mp_mod); + /* S1 = Y1*Z2^3 */ + sp_256_mont_mul_8(t3, t3, y, p256_mod, p256_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_256_mont_mul_8(t4, t4, q->y, p256_mod, p256_mp_mod); + /* H = U2 - U1 */ + sp_256_mont_sub_8(t2, t2, t1, p256_mod); + /* R = S2 - S1 */ + sp_256_mont_sub_8(t4, t4, t3, p256_mod); + /* Z3 = H*Z1*Z2 */ + sp_256_mont_mul_8(z, z, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(z, z, t2, p256_mod, p256_mp_mod); + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_256_mont_sqr_8(x, t4, p256_mod, p256_mp_mod); + sp_256_mont_sqr_8(t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(y, t1, t5, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t5, t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_sub_8(x, x, t5, p256_mod); + sp_256_mont_dbl_8(t1, y, p256_mod); + sp_256_mont_sub_8(x, x, t1, p256_mod); + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_256_mont_sub_8(y, y, x, p256_mod); + sp_256_mont_mul_8(y, y, t4, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t5, t5, t3, p256_mod, p256_mp_mod); + sp_256_mont_sub_8(y, y, t5, p256_mod); + } +} + +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_fast_8(sp_point* r, sp_point* g, sp_digit* k, + int map, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point td[16]; + sp_point rtd; + sp_digit tmpd[2 * 8 * 5]; +#endif + sp_point* t; + sp_point* rt; + sp_digit* tmp; + sp_digit n; + int i; + int c, y; + int err; + + (void)heap; + + err = sp_ecc_point_new(heap, rtd, rt); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + t = (sp_point*)XMALLOC(sizeof(sp_point) * 16, heap, DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 5, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; +#else + t = td; + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + /* t[0] = {0, 0, 1} * norm */ + XMEMSET(&t[0], 0, sizeof(t[0])); + t[0].infinity = 1; + /* t[1] = {g->x, g->y, g->z} * norm */ + sp_256_mod_mul_norm_8(t[1].x, g->x, p256_mod); + sp_256_mod_mul_norm_8(t[1].y, g->y, p256_mod); + sp_256_mod_mul_norm_8(t[1].z, g->z, p256_mod); + t[1].infinity = 0; + sp_256_proj_point_dbl_8(&t[ 2], &t[ 1], tmp); + t[ 2].infinity = 0; + sp_256_proj_point_add_8(&t[ 3], &t[ 2], &t[ 1], tmp); + t[ 3].infinity = 0; + sp_256_proj_point_dbl_8(&t[ 4], &t[ 2], tmp); + t[ 4].infinity = 0; + sp_256_proj_point_add_8(&t[ 5], &t[ 3], &t[ 2], tmp); + t[ 5].infinity = 0; + sp_256_proj_point_dbl_8(&t[ 6], &t[ 3], tmp); + t[ 6].infinity = 0; + sp_256_proj_point_add_8(&t[ 7], &t[ 4], &t[ 3], tmp); + t[ 7].infinity = 0; + sp_256_proj_point_dbl_8(&t[ 8], &t[ 4], tmp); + t[ 8].infinity = 0; + sp_256_proj_point_add_8(&t[ 9], &t[ 5], &t[ 4], tmp); + t[ 9].infinity = 0; + sp_256_proj_point_dbl_8(&t[10], &t[ 5], tmp); + t[10].infinity = 0; + sp_256_proj_point_add_8(&t[11], &t[ 6], &t[ 5], tmp); + t[11].infinity = 0; + sp_256_proj_point_dbl_8(&t[12], &t[ 6], tmp); + t[12].infinity = 0; + sp_256_proj_point_add_8(&t[13], &t[ 7], &t[ 6], tmp); + t[13].infinity = 0; + sp_256_proj_point_dbl_8(&t[14], &t[ 7], tmp); + t[14].infinity = 0; + sp_256_proj_point_add_8(&t[15], &t[ 8], &t[ 7], tmp); + t[15].infinity = 0; + + i = 6; + n = k[i+1] << 0; + c = 28; + y = n >> 28; + XMEMCPY(rt, &t[y], sizeof(sp_point)); + n <<= 4; + for (; i>=0 || c>=4; ) { + if (c < 4) { + n |= k[i--] << (0 - c); + c += 32; + } + y = (n >> 28) & 0xf; + n <<= 4; + c -= 4; + + sp_256_proj_point_dbl_8(rt, rt, tmp); + sp_256_proj_point_dbl_8(rt, rt, tmp); + sp_256_proj_point_dbl_8(rt, rt, tmp); + sp_256_proj_point_dbl_8(rt, rt, tmp); + + sp_256_proj_point_add_8(rt, rt, &t[y], tmp); + } + + if (map) + sp_256_map_8(r, rt, tmp); + else + XMEMCPY(r, rt, sizeof(sp_point)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (tmp != NULL) { + XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 8 * 5); + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + } + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_point) * 16); + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } +#else + ForceZero(tmpd, sizeof(tmpd)); + ForceZero(td, sizeof(td)); +#endif + sp_ecc_point_free(rt, 1, heap); + + return err; +} + +/* A table entry for pre-computed points. */ +typedef struct sp_table_entry { + sp_digit x[8]; + sp_digit y[8]; + byte infinity; +} sp_table_entry; + +#ifdef FP_ECC +/* Double the Montgomery form projective point p a number of times. + * + * r Result of repeated doubling of point. + * p Point to double. + * n Number of times to double + * t Temporary ordinate data. + */ +static void sp_256_proj_point_dbl_n_8(sp_point* r, sp_point* p, int n, + sp_digit* t) +{ + sp_point* rp[2]; + sp_digit* w = t; + sp_digit* a = t + 2*8; + sp_digit* b = t + 4*8; + sp_digit* t1 = t + 6*8; + sp_digit* t2 = t + 8*8; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + rp[0] = r; + rp[1] = (sp_point*)t; + XMEMSET(rp[1], 0, sizeof(sp_point)); + x = rp[p->infinity]->x; + y = rp[p->infinity]->y; + z = rp[p->infinity]->z; + if (r != p) { + for (i=0; i<8; i++) + r->x[i] = p->x[i]; + for (i=0; i<8; i++) + r->y[i] = p->y[i]; + for (i=0; i<8; i++) + r->z[i] = p->z[i]; + r->infinity = p->infinity; + } + + /* Y = 2*Y */ + sp_256_mont_dbl_8(y, y, p256_mod); + /* W = Z^4 */ + sp_256_mont_sqr_8(w, z, p256_mod, p256_mp_mod); + sp_256_mont_sqr_8(w, w, p256_mod, p256_mp_mod); + while (n--) { + /* A = 3*(X^2 - W) */ + sp_256_mont_sqr_8(t1, x, p256_mod, p256_mp_mod); + sp_256_mont_sub_8(t1, t1, w, p256_mod); + sp_256_mont_tpl_8(a, t1, p256_mod); + /* B = X*Y^2 */ + sp_256_mont_sqr_8(t2, y, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(b, t2, x, p256_mod, p256_mp_mod); + /* X = A^2 - 2B */ + sp_256_mont_sqr_8(x, a, p256_mod, p256_mp_mod); + sp_256_mont_dbl_8(t1, b, p256_mod); + sp_256_mont_sub_8(x, x, t1, p256_mod); + /* Z = Z*Y */ + sp_256_mont_mul_8(z, z, y, p256_mod, p256_mp_mod); + /* t2 = Y^4 */ + sp_256_mont_sqr_8(t2, t2, p256_mod, p256_mp_mod); + if (n) { + /* W = W*Y^4 */ + sp_256_mont_mul_8(w, w, t2, p256_mod, p256_mp_mod); + } + /* y = 2*A*(B - X) - Y^4 */ + sp_256_mont_sub_8(y, b, x, p256_mod); + sp_256_mont_mul_8(y, y, a, p256_mod, p256_mp_mod); + sp_256_mont_dbl_8(y, y, p256_mod); + sp_256_mont_sub_8(y, y, t2, p256_mod); + } + /* Y = Y/2 */ + sp_256_div2_8(y, y, p256_mod); +} + +#endif /* FP_ECC */ +/* Add two Montgomery form projective points. The second point has a q value of + * one. + * Only the first point can be the same pointer as the result point. + * + * r Result of addition. + * p Frist point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_add_qz1_8(sp_point* r, sp_point* p, + sp_point* q, sp_digit* t) +{ + sp_point* ap[2]; + sp_point* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*8; + sp_digit* t3 = t + 4*8; + sp_digit* t4 = t + 6*8; + sp_digit* t5 = t + 8*8; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* Check double */ + sp_256_sub_8(t1, p256_mod, q->y); + sp_256_norm_8(t1); + if (sp_256_cmp_equal_8(p->x, q->x) & sp_256_cmp_equal_8(p->z, q->z) & + (sp_256_cmp_equal_8(p->y, q->y) | sp_256_cmp_equal_8(p->y, t1))) { + sp_256_proj_point_dbl_8(r, p, t); + } + else { + rp[0] = r; + rp[1] = (sp_point*)t; + XMEMSET(rp[1], 0, sizeof(sp_point)); + x = rp[p->infinity | q->infinity]->x; + y = rp[p->infinity | q->infinity]->y; + z = rp[p->infinity | q->infinity]->z; + + ap[0] = p; + ap[1] = q; + for (i=0; i<8; i++) + r->x[i] = ap[p->infinity]->x[i]; + for (i=0; i<8; i++) + r->y[i] = ap[p->infinity]->y[i]; + for (i=0; i<8; i++) + r->z[i] = ap[p->infinity]->z[i]; + r->infinity = ap[p->infinity]->infinity; + + /* U2 = X2*Z1^2 */ + sp_256_mont_sqr_8(t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t4, t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t2, t2, q->x, p256_mod, p256_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_256_mont_mul_8(t4, t4, q->y, p256_mod, p256_mp_mod); + /* H = U2 - X1 */ + sp_256_mont_sub_8(t2, t2, x, p256_mod); + /* R = S2 - Y1 */ + sp_256_mont_sub_8(t4, t4, y, p256_mod); + /* Z3 = H*Z1 */ + sp_256_mont_mul_8(z, z, t2, p256_mod, p256_mp_mod); + /* X3 = R^2 - H^3 - 2*X1*H^2 */ + sp_256_mont_sqr_8(t1, t4, p256_mod, p256_mp_mod); + sp_256_mont_sqr_8(t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t3, x, t5, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t5, t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_sub_8(x, t1, t5, p256_mod); + sp_256_mont_dbl_8(t1, t3, p256_mod); + sp_256_mont_sub_8(x, x, t1, p256_mod); + /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */ + sp_256_mont_sub_8(t3, t3, x, p256_mod); + sp_256_mont_mul_8(t3, t3, t4, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t5, t5, y, p256_mod, p256_mp_mod); + sp_256_mont_sub_8(y, t3, t5, p256_mod); + } +} + +#ifdef WOLFSSL_SP_SMALL +#ifdef FP_ECC +/* Convert the projective point to affine. + * Ordinates are in Montgomery form. + * + * a Point to convert. + * t Temprorary data. + */ +static void sp_256_proj_to_affine_8(sp_point* a, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 8; + sp_digit* tmp = t + 4 * 8; + + sp_256_mont_inv_8(t1, a->z, tmp); + + sp_256_mont_sqr_8(t2, t1, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t1, t2, t1, p256_mod, p256_mp_mod); + + sp_256_mont_mul_8(a->x, a->x, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(a->y, a->y, t1, p256_mod, p256_mp_mod); + XMEMCPY(a->z, p256_norm_mod, sizeof(p256_norm_mod)); +} + +/* Generate the pre-computed table of points for the base point. + * + * a The base point. + * table Place to store generated point data. + * tmp Temprorary data. + * heap Heap to use for allocation. + */ +static int sp_256_gen_stripe_table_8(sp_point* a, + sp_table_entry* table, sp_digit* tmp, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point td, s1d, s2d; +#endif + sp_point* t; + sp_point* s1 = NULL; + sp_point* s2 = NULL; + int i, j; + int err; + + (void)heap; + + err = sp_ecc_point_new(heap, td, t); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, s1d, s1); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, s2d, s2); + + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_8(t->x, a->x, p256_mod); + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_8(t->y, a->y, p256_mod); + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_8(t->z, a->z, p256_mod); + if (err == MP_OKAY) { + t->infinity = 0; + sp_256_proj_to_affine_8(t, tmp); + + XMEMCPY(s1->z, p256_norm_mod, sizeof(p256_norm_mod)); + s1->infinity = 0; + XMEMCPY(s2->z, p256_norm_mod, sizeof(p256_norm_mod)); + s2->infinity = 0; + + /* table[0] = {0, 0, infinity} */ + XMEMSET(&table[0], 0, sizeof(sp_table_entry)); + table[0].infinity = 1; + /* table[1] = Affine version of 'a' in Montgomery form */ + XMEMCPY(table[1].x, t->x, sizeof(table->x)); + XMEMCPY(table[1].y, t->y, sizeof(table->y)); + table[1].infinity = 0; + + for (i=1; i<4; i++) { + sp_256_proj_point_dbl_n_8(t, t, 64, tmp); + sp_256_proj_to_affine_8(t, tmp); + XMEMCPY(table[1<x, sizeof(table->x)); + XMEMCPY(table[1<y, sizeof(table->y)); + table[1<x, table[1<x)); + XMEMCPY(s1->y, table[1<y)); + for (j=(1<x, table[j-(1<x)); + XMEMCPY(s2->y, table[j-(1<y)); + sp_256_proj_point_add_qz1_8(t, s1, s2, tmp); + sp_256_proj_to_affine_8(t, tmp); + XMEMCPY(table[j].x, t->x, sizeof(table->x)); + XMEMCPY(table[j].y, t->y, sizeof(table->y)); + table[j].infinity = 0; + } + } + } + + sp_ecc_point_free(s2, 0, heap); + sp_ecc_point_free(s1, 0, heap); + sp_ecc_point_free( t, 0, heap); + + return err; +} + +#endif /* FP_ECC */ +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_stripe_8(sp_point* r, sp_point* g, + sp_table_entry* table, sp_digit* k, int map, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point rtd; + sp_point pd; + sp_digit td[2 * 8 * 5]; +#endif + sp_point* rt; + sp_point* p = NULL; + sp_digit* t; + int i, j; + int y, x; + int err; + + (void)g; + (void)heap; + + err = sp_ecc_point_new(heap, rtd, rt); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 5, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#else + t = td; +#endif + + if (err == MP_OKAY) { + XMEMCPY(p->z, p256_norm_mod, sizeof(p256_norm_mod)); + XMEMCPY(rt->z, p256_norm_mod, sizeof(p256_norm_mod)); + + y = 0; + for (j=0,x=63; j<4; j++,x+=64) + y |= ((k[x / 32] >> (x % 32)) & 1) << j; + XMEMCPY(rt->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(rt->y, table[y].y, sizeof(table[y].y)); + rt->infinity = table[y].infinity; + for (i=62; i>=0; i--) { + y = 0; + for (j=0,x=i; j<4; j++,x+=64) + y |= ((k[x / 32] >> (x % 32)) & 1) << j; + + sp_256_proj_point_dbl_8(rt, rt, t); + XMEMCPY(p->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(p->y, table[y].y, sizeof(table[y].y)); + p->infinity = table[y].infinity; + sp_256_proj_point_add_qz1_8(rt, rt, p, t); + } + + if (map) + sp_256_map_8(r, rt, t); + else + XMEMCPY(r, rt, sizeof(sp_point)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p, 0, heap); + sp_ecc_point_free(rt, 0, heap); + + return err; +} + +#ifdef FP_ECC +#ifndef FP_ENTRIES + #define FP_ENTRIES 16 +#endif + +typedef struct sp_cache_t { + sp_digit x[8]; + sp_digit y[8]; + sp_table_entry table[16]; + uint32_t cnt; + int set; +} sp_cache_t; + +static THREAD_LS_T sp_cache_t sp_cache[FP_ENTRIES]; +static THREAD_LS_T int sp_cache_last = -1; +static THREAD_LS_T int sp_cache_inited = 0; + +#ifndef HAVE_THREAD_LS + static volatile int initCacheMutex = 0; + static wolfSSL_Mutex sp_cache_lock; +#endif + +static void sp_ecc_get_cache(sp_point* g, sp_cache_t** cache) +{ + int i, j; + uint32_t least; + + if (sp_cache_inited == 0) { + for (i=0; ix, sp_cache[i].x) & + sp_256_cmp_equal_8(g->y, sp_cache[i].y)) { + sp_cache[i].cnt++; + break; + } + } + + /* No match. */ + if (i == FP_ENTRIES) { + /* Find empty entry. */ + i = (sp_cache_last + 1) % FP_ENTRIES; + for (; i != sp_cache_last; i=(i+1)%FP_ENTRIES) { + if (!sp_cache[i].set) { + break; + } + } + + /* Evict least used. */ + if (i == sp_cache_last) { + least = sp_cache[0].cnt; + for (j=1; jx, sizeof(sp_cache[i].x)); + XMEMCPY(sp_cache[i].y, g->y, sizeof(sp_cache[i].y)); + sp_cache[i].set = 1; + sp_cache[i].cnt = 1; + } + + *cache = &sp_cache[i]; + sp_cache_last = i; +} +#endif /* FP_ECC */ + +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_8(sp_point* r, sp_point* g, sp_digit* k, + int map, void* heap) +{ +#ifndef FP_ECC + return sp_256_ecc_mulmod_fast_8(r, g, k, map, heap); +#else + sp_digit tmp[2 * 8 * 5]; + sp_cache_t* cache; + int err = MP_OKAY; + +#ifndef HAVE_THREAD_LS + if (initCacheMutex == 0) { + wc_InitMutex(&sp_cache_lock); + initCacheMutex = 1; + } + if (wc_LockMutex(&sp_cache_lock) != 0) + err = BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + if (err == MP_OKAY) { + sp_ecc_get_cache(g, &cache); + if (cache->cnt == 2) + sp_256_gen_stripe_table_8(g, cache->table, tmp, heap); + +#ifndef HAVE_THREAD_LS + wc_UnLockMutex(&sp_cache_lock); +#endif /* HAVE_THREAD_LS */ + + if (cache->cnt < 2) { + err = sp_256_ecc_mulmod_fast_8(r, g, k, map, heap); + } + else { + err = sp_256_ecc_mulmod_stripe_8(r, g, cache->table, k, + map, heap); + } + } + + return err; +#endif +} + +#else +#ifdef FP_ECC +/* Generate the pre-computed table of points for the base point. + * + * a The base point. + * table Place to store generated point data. + * tmp Temprorary data. + * heap Heap to use for allocation. + */ +static int sp_256_gen_stripe_table_8(sp_point* a, + sp_table_entry* table, sp_digit* tmp, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point td, s1d, s2d; +#endif + sp_point* t; + sp_point* s1 = NULL; + sp_point* s2 = NULL; + int i, j; + int err; + + (void)heap; + + err = sp_ecc_point_new(heap, td, t); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, s1d, s1); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, s2d, s2); + + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_8(t->x, a->x, p256_mod); + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_8(t->y, a->y, p256_mod); + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_8(t->z, a->z, p256_mod); + if (err == MP_OKAY) { + t->infinity = 0; + sp_256_proj_to_affine_8(t, tmp); + + XMEMCPY(s1->z, p256_norm_mod, sizeof(p256_norm_mod)); + s1->infinity = 0; + XMEMCPY(s2->z, p256_norm_mod, sizeof(p256_norm_mod)); + s2->infinity = 0; + + /* table[0] = {0, 0, infinity} */ + XMEMSET(&table[0], 0, sizeof(sp_table_entry)); + table[0].infinity = 1; + /* table[1] = Affine version of 'a' in Montgomery form */ + XMEMCPY(table[1].x, t->x, sizeof(table->x)); + XMEMCPY(table[1].y, t->y, sizeof(table->y)); + table[1].infinity = 0; + + for (i=1; i<8; i++) { + sp_256_proj_point_dbl_n_8(t, t, 32, tmp); + sp_256_proj_to_affine_8(t, tmp); + XMEMCPY(table[1<x, sizeof(table->x)); + XMEMCPY(table[1<y, sizeof(table->y)); + table[1<x, table[1<x)); + XMEMCPY(s1->y, table[1<y)); + for (j=(1<x, table[j-(1<x)); + XMEMCPY(s2->y, table[j-(1<y)); + sp_256_proj_point_add_qz1_8(t, s1, s2, tmp); + sp_256_proj_to_affine_8(t, tmp); + XMEMCPY(table[j].x, t->x, sizeof(table->x)); + XMEMCPY(table[j].y, t->y, sizeof(table->y)); + table[j].infinity = 0; + } + } + } + + sp_ecc_point_free(s2, 0, heap); + sp_ecc_point_free(s1, 0, heap); + sp_ecc_point_free( t, 0, heap); + + return err; +} + +#endif /* FP_ECC */ +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_stripe_8(sp_point* r, sp_point* g, + sp_table_entry* table, sp_digit* k, int map, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point rtd; + sp_point pd; + sp_digit td[2 * 8 * 5]; +#endif + sp_point* rt; + sp_point* p = NULL; + sp_digit* t; + int i, j; + int y, x; + int err; + + (void)g; + (void)heap; + + err = sp_ecc_point_new(heap, rtd, rt); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 5, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#else + t = td; +#endif + + if (err == MP_OKAY) { + XMEMCPY(p->z, p256_norm_mod, sizeof(p256_norm_mod)); + XMEMCPY(rt->z, p256_norm_mod, sizeof(p256_norm_mod)); + + y = 0; + for (j=0,x=31; j<8; j++,x+=32) + y |= ((k[x / 32] >> (x % 32)) & 1) << j; + XMEMCPY(rt->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(rt->y, table[y].y, sizeof(table[y].y)); + rt->infinity = table[y].infinity; + for (i=30; i>=0; i--) { + y = 0; + for (j=0,x=i; j<8; j++,x+=32) + y |= ((k[x / 32] >> (x % 32)) & 1) << j; + + sp_256_proj_point_dbl_8(rt, rt, t); + XMEMCPY(p->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(p->y, table[y].y, sizeof(table[y].y)); + p->infinity = table[y].infinity; + sp_256_proj_point_add_qz1_8(rt, rt, p, t); + } + + if (map) + sp_256_map_8(r, rt, t); + else + XMEMCPY(r, rt, sizeof(sp_point)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p, 0, heap); + sp_ecc_point_free(rt, 0, heap); + + return err; +} + +#ifdef FP_ECC +#ifndef FP_ENTRIES + #define FP_ENTRIES 16 +#endif + +typedef struct sp_cache_t { + sp_digit x[8]; + sp_digit y[8]; + sp_table_entry table[256]; + uint32_t cnt; + int set; +} sp_cache_t; + +static THREAD_LS_T sp_cache_t sp_cache[FP_ENTRIES]; +static THREAD_LS_T int sp_cache_last = -1; +static THREAD_LS_T int sp_cache_inited = 0; + +#ifndef HAVE_THREAD_LS + static volatile int initCacheMutex = 0; + static wolfSSL_Mutex sp_cache_lock; +#endif + +static void sp_ecc_get_cache(sp_point* g, sp_cache_t** cache) +{ + int i, j; + uint32_t least; + + if (sp_cache_inited == 0) { + for (i=0; ix, sp_cache[i].x) & + sp_256_cmp_equal_8(g->y, sp_cache[i].y)) { + sp_cache[i].cnt++; + break; + } + } + + /* No match. */ + if (i == FP_ENTRIES) { + /* Find empty entry. */ + i = (sp_cache_last + 1) % FP_ENTRIES; + for (; i != sp_cache_last; i=(i+1)%FP_ENTRIES) { + if (!sp_cache[i].set) { + break; + } + } + + /* Evict least used. */ + if (i == sp_cache_last) { + least = sp_cache[0].cnt; + for (j=1; jx, sizeof(sp_cache[i].x)); + XMEMCPY(sp_cache[i].y, g->y, sizeof(sp_cache[i].y)); + sp_cache[i].set = 1; + sp_cache[i].cnt = 1; + } + + *cache = &sp_cache[i]; + sp_cache_last = i; +} +#endif /* FP_ECC */ + +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_8(sp_point* r, sp_point* g, sp_digit* k, + int map, void* heap) +{ +#ifndef FP_ECC + return sp_256_ecc_mulmod_fast_8(r, g, k, map, heap); +#else + sp_digit tmp[2 * 8 * 5]; + sp_cache_t* cache; + int err = MP_OKAY; + +#ifndef HAVE_THREAD_LS + if (initCacheMutex == 0) { + wc_InitMutex(&sp_cache_lock); + initCacheMutex = 1; + } + if (wc_LockMutex(&sp_cache_lock) != 0) + err = BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + if (err == MP_OKAY) { + sp_ecc_get_cache(g, &cache); + if (cache->cnt == 2) + sp_256_gen_stripe_table_8(g, cache->table, tmp, heap); + +#ifndef HAVE_THREAD_LS + wc_UnLockMutex(&sp_cache_lock); +#endif /* HAVE_THREAD_LS */ + + if (cache->cnt < 2) { + err = sp_256_ecc_mulmod_fast_8(r, g, k, map, heap); + } + else { + err = sp_256_ecc_mulmod_stripe_8(r, g, cache->table, k, + map, heap); + } + } + + return err; +#endif +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * km Scalar to multiply by. + * p Point to multiply. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_256(mp_int* km, ecc_point* gm, ecc_point* r, int map, + void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point p; + sp_digit kd[8]; +#endif + sp_point* point; + sp_digit* k = NULL; + int err = MP_OKAY; + + err = sp_ecc_point_new(heap, p, point); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + if (err == MP_OKAY) { + sp_256_from_mp(k, 8, km); + sp_256_point_from_ecc_point_8(point, gm); + + err = sp_256_ecc_mulmod_8(point, point, k, map, heap); + } + if (err == MP_OKAY) + err = sp_256_point_to_ecc_point_8(point, r); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(point, 0, heap); + + return err; +} + +#ifdef WOLFSSL_SP_SMALL +static sp_table_entry p256_table[16] = { + /* 0 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 */ + { { 0x18a9143c,0x79e730d4,0x5fedb601,0x75ba95fc,0x77622510,0x79fb732b, + 0xa53755c6,0x18905f76 }, + { 0xce95560a,0xddf25357,0xba19e45c,0x8b4ab8e4,0xdd21f325,0xd2e88688, + 0x25885d85,0x8571ff18 }, + 0 }, + /* 2 */ + { { 0x16a0d2bb,0x4f922fc5,0x1a623499,0x0d5cc16c,0x57c62c8b,0x9241cf3a, + 0xfd1b667f,0x2f5e6961 }, + { 0xf5a01797,0x5c15c70b,0x60956192,0x3d20b44d,0x071fdb52,0x04911b37, + 0x8d6f0f7b,0xf648f916 }, + 0 }, + /* 3 */ + { { 0xe137bbbc,0x9e566847,0x8a6a0bec,0xe434469e,0x79d73463,0xb1c42761, + 0x133d0015,0x5abe0285 }, + { 0xc04c7dab,0x92aa837c,0x43260c07,0x573d9f4c,0x78e6cc37,0x0c931562, + 0x6b6f7383,0x94bb725b }, + 0 }, + /* 4 */ + { { 0xbfe20925,0x62a8c244,0x8fdce867,0x91c19ac3,0xdd387063,0x5a96a5d5, + 0x21d324f6,0x61d587d4 }, + { 0xa37173ea,0xe87673a2,0x53778b65,0x23848008,0x05bab43e,0x10f8441e, + 0x4621efbe,0xfa11fe12 }, + 0 }, + /* 5 */ + { { 0x2cb19ffd,0x1c891f2b,0xb1923c23,0x01ba8d5b,0x8ac5ca8e,0xb6d03d67, + 0x1f13bedc,0x586eb04c }, + { 0x27e8ed09,0x0c35c6e5,0x1819ede2,0x1e81a33c,0x56c652fa,0x278fd6c0, + 0x70864f11,0x19d5ac08 }, + 0 }, + /* 6 */ + { { 0xd2b533d5,0x62577734,0xa1bdddc0,0x673b8af6,0xa79ec293,0x577e7c9a, + 0xc3b266b1,0xbb6de651 }, + { 0xb65259b3,0xe7e9303a,0xd03a7480,0xd6a0afd3,0x9b3cfc27,0xc5ac83d1, + 0x5d18b99b,0x60b4619a }, + 0 }, + /* 7 */ + { { 0x1ae5aa1c,0xbd6a38e1,0x49e73658,0xb8b7652b,0xee5f87ed,0x0b130014, + 0xaeebffcd,0x9d0f27b2 }, + { 0x7a730a55,0xca924631,0xddbbc83a,0x9c955b2f,0xac019a71,0x07c1dfe0, + 0x356ec48d,0x244a566d }, + 0 }, + /* 8 */ + { { 0xf4f8b16a,0x56f8410e,0xc47b266a,0x97241afe,0x6d9c87c1,0x0a406b8e, + 0xcd42ab1b,0x803f3e02 }, + { 0x04dbec69,0x7f0309a8,0x3bbad05f,0xa83b85f7,0xad8e197f,0xc6097273, + 0x5067adc1,0xc097440e }, + 0 }, + /* 9 */ + { { 0xc379ab34,0x846a56f2,0x841df8d1,0xa8ee068b,0x176c68ef,0x20314459, + 0x915f1f30,0xf1af32d5 }, + { 0x5d75bd50,0x99c37531,0xf72f67bc,0x837cffba,0x48d7723f,0x0613a418, + 0xe2d41c8b,0x23d0f130 }, + 0 }, + /* 10 */ + { { 0xd5be5a2b,0xed93e225,0x5934f3c6,0x6fe79983,0x22626ffc,0x43140926, + 0x7990216a,0x50bbb4d9 }, + { 0xe57ec63e,0x378191c6,0x181dcdb2,0x65422c40,0x0236e0f6,0x41a8099b, + 0x01fe49c3,0x2b100118 }, + 0 }, + /* 11 */ + { { 0x9b391593,0xfc68b5c5,0x598270fc,0xc385f5a2,0xd19adcbb,0x7144f3aa, + 0x83fbae0c,0xdd558999 }, + { 0x74b82ff4,0x93b88b8e,0x71e734c9,0xd2e03c40,0x43c0322a,0x9a7a9eaf, + 0x149d6041,0xe6e4c551 }, + 0 }, + /* 12 */ + { { 0x80ec21fe,0x5fe14bfe,0xc255be82,0xf6ce116a,0x2f4a5d67,0x98bc5a07, + 0xdb7e63af,0xfad27148 }, + { 0x29ab05b3,0x90c0b6ac,0x4e251ae6,0x37a9a83c,0xc2aade7d,0x0a7dc875, + 0x9f0e1a84,0x77387de3 }, + 0 }, + /* 13 */ + { { 0xa56c0dd7,0x1e9ecc49,0x46086c74,0xa5cffcd8,0xf505aece,0x8f7a1408, + 0xbef0c47e,0xb37b85c0 }, + { 0xcc0e6a8f,0x3596b6e4,0x6b388f23,0xfd6d4bbf,0xc39cef4e,0xaba453fa, + 0xf9f628d5,0x9c135ac8 }, + 0 }, + /* 14 */ + { { 0x95c8f8be,0x0a1c7294,0x3bf362bf,0x2961c480,0xdf63d4ac,0x9e418403, + 0x91ece900,0xc109f9cb }, + { 0x58945705,0xc2d095d0,0xddeb85c0,0xb9083d96,0x7a40449b,0x84692b8d, + 0x2eee1ee1,0x9bc3344f }, + 0 }, + /* 15 */ + { { 0x42913074,0x0d5ae356,0x48a542b1,0x55491b27,0xb310732a,0x469ca665, + 0x5f1a4cc1,0x29591d52 }, + { 0xb84f983f,0xe76f5b6b,0x9f5f84e1,0xbe7eef41,0x80baa189,0x1200d496, + 0x18ef332c,0x6376551f }, + 0 }, +}; + +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_base_8(sp_point* r, sp_digit* k, + int map, void* heap) +{ + return sp_256_ecc_mulmod_stripe_8(r, &p256_base, p256_table, + k, map, heap); +} + +#else +static sp_table_entry p256_table[256] = { + /* 0 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 */ + { { 0x18a9143c,0x79e730d4,0x5fedb601,0x75ba95fc,0x77622510,0x79fb732b, + 0xa53755c6,0x18905f76 }, + { 0xce95560a,0xddf25357,0xba19e45c,0x8b4ab8e4,0xdd21f325,0xd2e88688, + 0x25885d85,0x8571ff18 }, + 0 }, + /* 2 */ + { { 0x4147519a,0x20288602,0x26b372f0,0xd0981eac,0xa785ebc8,0xa9d4a7ca, + 0xdbdf58e9,0xd953c50d }, + { 0xfd590f8f,0x9d6361cc,0x44e6c917,0x72e9626b,0x22eb64cf,0x7fd96110, + 0x9eb288f3,0x863ebb7e }, + 0 }, + /* 3 */ + { { 0x5cdb6485,0x7856b623,0x2f0a2f97,0x808f0ea2,0x4f7e300b,0x3e68d954, + 0xb5ff80a0,0x00076055 }, + { 0x838d2010,0x7634eb9b,0x3243708a,0x54014fbb,0x842a6606,0xe0e47d39, + 0x34373ee0,0x83087761 }, + 0 }, + /* 4 */ + { { 0x16a0d2bb,0x4f922fc5,0x1a623499,0x0d5cc16c,0x57c62c8b,0x9241cf3a, + 0xfd1b667f,0x2f5e6961 }, + { 0xf5a01797,0x5c15c70b,0x60956192,0x3d20b44d,0x071fdb52,0x04911b37, + 0x8d6f0f7b,0xf648f916 }, + 0 }, + /* 5 */ + { { 0xe137bbbc,0x9e566847,0x8a6a0bec,0xe434469e,0x79d73463,0xb1c42761, + 0x133d0015,0x5abe0285 }, + { 0xc04c7dab,0x92aa837c,0x43260c07,0x573d9f4c,0x78e6cc37,0x0c931562, + 0x6b6f7383,0x94bb725b }, + 0 }, + /* 6 */ + { { 0x720f141c,0xbbf9b48f,0x2df5bc74,0x6199b3cd,0x411045c4,0xdc3f6129, + 0x2f7dc4ef,0xcdd6bbcb }, + { 0xeaf436fd,0xcca6700b,0xb99326be,0x6f647f6d,0x014f2522,0x0c0fa792, + 0x4bdae5f6,0xa361bebd }, + 0 }, + /* 7 */ + { { 0x597c13c7,0x28aa2558,0x50b7c3e1,0xc38d635f,0xf3c09d1d,0x07039aec, + 0xc4b5292c,0xba12ca09 }, + { 0x59f91dfd,0x9e408fa4,0xceea07fb,0x3af43b66,0x9d780b29,0x1eceb089, + 0x701fef4b,0x53ebb99d }, + 0 }, + /* 8 */ + { { 0xb0e63d34,0x4fe7ee31,0xa9e54fab,0xf4600572,0xd5e7b5a4,0xc0493334, + 0x06d54831,0x8589fb92 }, + { 0x6583553a,0xaa70f5cc,0xe25649e5,0x0879094a,0x10044652,0xcc904507, + 0x02541c4f,0xebb0696d }, + 0 }, + /* 9 */ + { { 0xac1647c5,0x4616ca15,0xc4cf5799,0xb8127d47,0x764dfbac,0xdc666aa3, + 0xd1b27da3,0xeb2820cb }, + { 0x6a87e008,0x9406f8d8,0x922378f3,0xd87dfa9d,0x80ccecb2,0x56ed2e42, + 0x55a7da1d,0x1f28289b }, + 0 }, + /* 10 */ + { { 0x3b89da99,0xabbaa0c0,0xb8284022,0xa6f2d79e,0xb81c05e8,0x27847862, + 0x05e54d63,0x337a4b59 }, + { 0x21f7794a,0x3c67500d,0x7d6d7f61,0x207005b7,0x04cfd6e8,0x0a5a3781, + 0xf4c2fbd6,0x0d65e0d5 }, + 0 }, + /* 11 */ + { { 0xb5275d38,0xd9d09bbe,0x0be0a358,0x4268a745,0x973eb265,0xf0762ff4, + 0x52f4a232,0xc23da242 }, + { 0x0b94520c,0x5da1b84f,0xb05bd78e,0x09666763,0x94d29ea1,0x3a4dcb86, + 0xc790cff1,0x19de3b8c }, + 0 }, + /* 12 */ + { { 0x26c5fe04,0x183a716c,0x3bba1bdb,0x3b28de0b,0xa4cb712c,0x7432c586, + 0x91fccbfd,0xe34dcbd4 }, + { 0xaaa58403,0xb408d46b,0x82e97a53,0x9a697486,0x36aaa8af,0x9e390127, + 0x7b4e0f7f,0xe7641f44 }, + 0 }, + /* 13 */ + { { 0xdf64ba59,0x7d753941,0x0b0242fc,0xd33f10ec,0xa1581859,0x4f06dfc6, + 0x052a57bf,0x4a12df57 }, + { 0x9439dbd0,0xbfa6338f,0xbde53e1f,0xd3c24bd4,0x21f1b314,0xfd5e4ffa, + 0xbb5bea46,0x6af5aa93 }, + 0 }, + /* 14 */ + { { 0x10c91999,0xda10b699,0x2a580491,0x0a24b440,0xb8cc2090,0x3e0094b4, + 0x66a44013,0x5fe3475a }, + { 0xf93e7b4b,0xb0f8cabd,0x7c23f91a,0x292b501a,0xcd1e6263,0x42e889ae, + 0xecfea916,0xb544e308 }, + 0 }, + /* 15 */ + { { 0x16ddfdce,0x6478c6e9,0xf89179e6,0x2c329166,0x4d4e67e1,0x4e8d6e76, + 0xa6b0c20b,0xe0b6b2bd }, + { 0xbb7efb57,0x0d312df2,0x790c4007,0x1aac0dde,0x679bc944,0xf90336ad, + 0x25a63774,0x71c023de }, + 0 }, + /* 16 */ + { { 0xbfe20925,0x62a8c244,0x8fdce867,0x91c19ac3,0xdd387063,0x5a96a5d5, + 0x21d324f6,0x61d587d4 }, + { 0xa37173ea,0xe87673a2,0x53778b65,0x23848008,0x05bab43e,0x10f8441e, + 0x4621efbe,0xfa11fe12 }, + 0 }, + /* 17 */ + { { 0x2cb19ffd,0x1c891f2b,0xb1923c23,0x01ba8d5b,0x8ac5ca8e,0xb6d03d67, + 0x1f13bedc,0x586eb04c }, + { 0x27e8ed09,0x0c35c6e5,0x1819ede2,0x1e81a33c,0x56c652fa,0x278fd6c0, + 0x70864f11,0x19d5ac08 }, + 0 }, + /* 18 */ + { { 0x309a4e1f,0x1e99f581,0xe9270074,0xab7de71b,0xefd28d20,0x26a5ef0b, + 0x7f9c563f,0xe7c0073f }, + { 0x0ef59f76,0x1f6d663a,0x20fcb050,0x669b3b54,0x7a6602d4,0xc08c1f7a, + 0xc65b3c0a,0xe08504fe }, + 0 }, + /* 19 */ + { { 0xa031b3ca,0xf098f68d,0xe6da6d66,0x6d1cab9e,0x94f246e8,0x5bfd81fa, + 0x5b0996b4,0x78f01882 }, + { 0x3a25787f,0xb7eefde4,0x1dccac9b,0x8016f80d,0xb35bfc36,0x0cea4877, + 0x7e94747a,0x43a773b8 }, + 0 }, + /* 20 */ + { { 0xd2b533d5,0x62577734,0xa1bdddc0,0x673b8af6,0xa79ec293,0x577e7c9a, + 0xc3b266b1,0xbb6de651 }, + { 0xb65259b3,0xe7e9303a,0xd03a7480,0xd6a0afd3,0x9b3cfc27,0xc5ac83d1, + 0x5d18b99b,0x60b4619a }, + 0 }, + /* 21 */ + { { 0x1ae5aa1c,0xbd6a38e1,0x49e73658,0xb8b7652b,0xee5f87ed,0x0b130014, + 0xaeebffcd,0x9d0f27b2 }, + { 0x7a730a55,0xca924631,0xddbbc83a,0x9c955b2f,0xac019a71,0x07c1dfe0, + 0x356ec48d,0x244a566d }, + 0 }, + /* 22 */ + { { 0xeacf1f96,0x6db0394a,0x024c271c,0x9f2122a9,0x82cbd3b9,0x2626ac1b, + 0x3581ef69,0x45e58c87 }, + { 0xa38f9dbc,0xd3ff479d,0xe888a040,0xa8aaf146,0x46e0bed7,0x945adfb2, + 0xc1e4b7a4,0xc040e21c }, + 0 }, + /* 23 */ + { { 0x6f8117b6,0x847af000,0x73a35433,0x651969ff,0x1d9475eb,0x482b3576, + 0x682c6ec7,0x1cdf5c97 }, + { 0x11f04839,0x7db775b4,0x48de1698,0x7dbeacf4,0xb70b3219,0xb2921dd1, + 0xa92dff3d,0x046755f8 }, + 0 }, + /* 24 */ + { { 0xbce8ffcd,0xcc8ac5d2,0x2fe61a82,0x0d53c48b,0x7202d6c7,0xf6f16172, + 0x3b83a5f3,0x046e5e11 }, + { 0xd8007f01,0xe7b8ff64,0x5af43183,0x7fb1ef12,0x35e1a03c,0x045c5ea6, + 0x303d005b,0x6e0106c3 }, + 0 }, + /* 25 */ + { { 0x88dd73b1,0x48c73584,0x995ed0d9,0x7670708f,0xc56a2ab7,0x38385ea8, + 0xe901cf1f,0x442594ed }, + { 0x12d4b65b,0xf8faa2c9,0x96c90c37,0x94c2343b,0x5e978d1f,0xd326e4a1, + 0x4c2ee68e,0xa796fa51 }, + 0 }, + /* 26 */ + { { 0x823addd7,0x359fb604,0xe56693b3,0x9e2a6183,0x3cbf3c80,0xf885b78e, + 0xc69766e9,0xe4ad2da9 }, + { 0x8e048a61,0x357f7f42,0xc092d9a0,0x082d198c,0xc03ed8ef,0xfc3a1af4, + 0xc37b5143,0xc5e94046 }, + 0 }, + /* 27 */ + { { 0x2be75f9e,0x476a538c,0xcb123a78,0x6fd1a9e8,0xb109c04b,0xd85e4df0, + 0xdb464747,0x63283daf }, + { 0xbaf2df15,0xce728cf7,0x0ad9a7f4,0xe592c455,0xe834bcc3,0xfab226ad, + 0x1981a938,0x68bd19ab }, + 0 }, + /* 28 */ + { { 0x1887d659,0xc08ead51,0xb359305a,0x3374d5f4,0xcfe74fe3,0x96986981, + 0x3c6fdfd6,0x495292f5 }, + { 0x1acec896,0x4a878c9e,0xec5b4484,0xd964b210,0x664d60a7,0x6696f7e2, + 0x26036837,0x0ec7530d }, + 0 }, + /* 29 */ + { { 0xad2687bb,0x2da13a05,0xf32e21fa,0xa1f83b6a,0x1dd4607b,0x390f5ef5, + 0x64863f0b,0x0f6207a6 }, + { 0x0f138233,0xbd67e3bb,0x272aa718,0xdd66b96c,0x26ec88ae,0x8ed00407, + 0x08ed6dcf,0xff0db072 }, + 0 }, + /* 30 */ + { { 0x4c95d553,0x749fa101,0x5d680a8a,0xa44052fd,0xff3b566f,0x183b4317, + 0x88740ea3,0x313b513c }, + { 0x08d11549,0xb402e2ac,0xb4dee21c,0x071ee10b,0x47f2320e,0x26b987dd, + 0x86f19f81,0x2d3abcf9 }, + 0 }, + /* 31 */ + { { 0x815581a2,0x4c288501,0x632211af,0x9a0a6d56,0x0cab2e99,0x19ba7a0f, + 0xded98cdf,0xc036fa10 }, + { 0xc1fbd009,0x29ae08ba,0x06d15816,0x0b68b190,0x9b9e0d8f,0xc2eb3277, + 0xb6d40194,0xa6b2a2c4 }, + 0 }, + /* 32 */ + { { 0x6d3549cf,0xd433e50f,0xfacd665e,0x6f33696f,0xce11fcb4,0x695bfdac, + 0xaf7c9860,0x810ee252 }, + { 0x7159bb2c,0x65450fe1,0x758b357b,0xf7dfbebe,0xd69fea72,0x2b057e74, + 0x92731745,0xd485717a }, + 0 }, + /* 33 */ + { { 0xf0cb5a98,0x11741a8a,0x1f3110bf,0xd3da8f93,0xab382adf,0x1994e2cb, + 0x2f9a604e,0x6a6045a7 }, + { 0xa2b2411d,0x170c0d3f,0x510e96e0,0xbe0eb83e,0x8865b3cc,0x3bcc9f73, + 0xf9e15790,0xd3e45cfa }, + 0 }, + /* 34 */ + { { 0xe83f7669,0xce1f69bb,0x72877d6b,0x09f8ae82,0x3244278d,0x9548ae54, + 0xe3c2c19c,0x207755de }, + { 0x6fef1945,0x87bd61d9,0xb12d28c3,0x18813cef,0x72df64aa,0x9fbcd1d6, + 0x7154b00d,0x48dc5ee5 }, + 0 }, + /* 35 */ + { { 0xf7e5a199,0x123790bf,0x989ccbb7,0xe0efb8cf,0x0a519c79,0xc27a2bfe, + 0xdff6f445,0xf2fb0aed }, + { 0xf0b5025f,0x41c09575,0x40fa9f22,0x550543d7,0x380bfbd0,0x8fa3c8ad, + 0xdb28d525,0xa13e9015 }, + 0 }, + /* 36 */ + { { 0xa2b65cbc,0xf9f7a350,0x2a464226,0x0b04b972,0xe23f07a1,0x265ce241, + 0x1497526f,0x2bf0d6b0 }, + { 0x4b216fb7,0xd3d4dd3f,0xfbdda26a,0xf7d7b867,0x6708505c,0xaeb7b83f, + 0x162fe89f,0x42a94a5a }, + 0 }, + /* 37 */ + { { 0xeaadf191,0x5846ad0b,0x25a268d7,0x0f8a4890,0x494dc1f6,0xe8603050, + 0xc65ede3d,0x2c2dd969 }, + { 0x93849c17,0x6d02171d,0x1da250dd,0x460488ba,0x3c3a5485,0x4810c706, + 0x42c56dbc,0xf437fa1f }, + 0 }, + /* 38 */ + { { 0x4a0f7dab,0x6aa0d714,0x1776e9ac,0x0f049793,0xf5f39786,0x52c0a050, + 0x54707aa8,0xaaf45b33 }, + { 0xc18d364a,0x85e37c33,0x3e497165,0xd40b9b06,0x15ec5444,0xf4171681, + 0xf4f272bc,0xcdf6310d }, + 0 }, + /* 39 */ + { { 0x8ea8b7ef,0x7473c623,0x85bc2287,0x08e93518,0x2bda8e34,0x41956772, + 0xda9e2ff2,0xf0d008ba }, + { 0x2414d3b1,0x2912671d,0xb019ea76,0xb3754985,0x453bcbdb,0x5c61b96d, + 0xca887b8b,0x5bd5c2f5 }, + 0 }, + /* 40 */ + { { 0xf49a3154,0xef0f469e,0x6e2b2e9a,0x3e85a595,0xaa924a9c,0x45aaec1e, + 0xa09e4719,0xaa12dfc8 }, + { 0x4df69f1d,0x26f27227,0xa2ff5e73,0xe0e4c82c,0xb7a9dd44,0xb9d8ce73, + 0xe48ca901,0x6c036e73 }, + 0 }, + /* 41 */ + { { 0x0f6e3138,0x5cfae12a,0x25ad345a,0x6966ef00,0x45672bc5,0x8993c64b, + 0x96afbe24,0x292ff658 }, + { 0x5e213402,0xd5250d44,0x4392c9fe,0xf6580e27,0xda1c72e8,0x097b397f, + 0x311b7276,0x644e0c90 }, + 0 }, + /* 42 */ + { { 0xa47153f0,0xe1e421e1,0x920418c9,0xb86c3b79,0x705d7672,0x93bdce87, + 0xcab79a77,0xf25ae793 }, + { 0x6d869d0c,0x1f3194a3,0x4986c264,0x9d55c882,0x096e945e,0x49fb5ea3, + 0x13db0a3e,0x39b8e653 }, + 0 }, + /* 43 */ + { { 0xb6fd2e59,0x37754200,0x9255c98f,0x35e2c066,0x0e2a5739,0xd9dab21a, + 0x0f19db06,0x39122f2f }, + { 0x03cad53c,0xcfbce1e0,0xe65c17e3,0x225b2c0f,0x9aa13877,0x72baf1d2, + 0xce80ff8d,0x8de80af8 }, + 0 }, + /* 44 */ + { { 0x207bbb76,0xafbea8d9,0x21782758,0x921c7e7c,0x1c0436b1,0xdfa2b74b, + 0x2e368c04,0x87194906 }, + { 0xa3993df5,0xb5f928bb,0xf3b3d26a,0x639d75b5,0x85b55050,0x011aa78a, + 0x5b74fde1,0xfc315e6a }, + 0 }, + /* 45 */ + { { 0xe8d6ecfa,0x561fd41a,0x1aec7f86,0x5f8c44f6,0x4924741d,0x98452a7b, + 0xee389088,0xe6d4a7ad }, + { 0x4593c75d,0x60552ed1,0xdd271162,0x70a70da4,0x7ba2c7db,0xd2aede93, + 0x9be2ae57,0x35dfaf9a }, + 0 }, + /* 46 */ + { { 0xaa736636,0x6b956fcd,0xae2cab7e,0x09f51d97,0x0f349966,0xfb10bf41, + 0x1c830d2b,0x1da5c7d7 }, + { 0x3cce6825,0x5c41e483,0xf9573c3b,0x15ad118f,0xf23036b8,0xa28552c7, + 0xdbf4b9d6,0x7077c0fd }, + 0 }, + /* 47 */ + { { 0x46b9661c,0xbf63ff8d,0x0d2cfd71,0xa1dfd36b,0xa847f8f7,0x0373e140, + 0xe50efe44,0x53a8632e }, + { 0x696d8051,0x0976ff68,0xc74f468a,0xdaec0c95,0x5e4e26bd,0x62994dc3, + 0x34e1fcc1,0x028ca76d }, + 0 }, + /* 48 */ + { { 0xfc9877ee,0xd11d47dc,0x801d0002,0xc8b36210,0x54c260b6,0xd002c117, + 0x6962f046,0x04c17cd8 }, + { 0xb0daddf5,0x6d9bd094,0x24ce55c0,0xbea23575,0x72da03b5,0x663356e6, + 0xfed97474,0xf7ba4de9 }, + 0 }, + /* 49 */ + { { 0xebe1263f,0xd0dbfa34,0x71ae7ce6,0x55763735,0x82a6f523,0xd2440553, + 0x52131c41,0xe31f9600 }, + { 0xea6b6ec6,0xd1bb9216,0x73c2fc44,0x37a1d12e,0x89d0a294,0xc10e7eac, + 0xce34d47b,0xaa3a6259 }, + 0 }, + /* 50 */ + { { 0x36f3dcd3,0xfbcf9df5,0xd2bf7360,0x6ceded50,0xdf504f5b,0x491710fa, + 0x7e79daee,0x2398dd62 }, + { 0x6d09569e,0xcf4705a3,0x5149f769,0xea0619bb,0x35f6034c,0xff9c0377, + 0x1c046210,0x5717f5b2 }, + 0 }, + /* 51 */ + { { 0x21dd895e,0x9fe229c9,0x40c28451,0x8e518500,0x1d637ecd,0xfa13d239, + 0x0e3c28de,0x660a2c56 }, + { 0xd67fcbd0,0x9cca88ae,0x0ea9f096,0xc8472478,0x72e92b4d,0x32b2f481, + 0x4f522453,0x624ee54c }, + 0 }, + /* 52 */ + { { 0xd897eccc,0x09549ce4,0x3f9880aa,0x4d49d1d9,0x043a7c20,0x723c2423, + 0x92bdfbc0,0x4f392afb }, + { 0x7de44fd9,0x6969f8fa,0x57b32156,0xb66cfbe4,0x368ebc3c,0xdb2fa803, + 0xccdb399c,0x8a3e7977 }, + 0 }, + /* 53 */ + { { 0x06c4b125,0xdde1881f,0xf6e3ca8c,0xae34e300,0x5c7a13e9,0xef6999de, + 0x70c24404,0x3888d023 }, + { 0x44f91081,0x76280356,0x5f015504,0x3d9fcf61,0x632cd36e,0x1827edc8, + 0x18102336,0xa5e62e47 }, + 0 }, + /* 54 */ + { { 0x2facd6c8,0x1a825ee3,0x54bcbc66,0x699c6354,0x98df9931,0x0ce3edf7, + 0x466a5adc,0x2c4768e6 }, + { 0x90a64bc9,0xb346ff8c,0xe4779f5c,0x630a6020,0xbc05e884,0xd949d064, + 0xf9e652a0,0x7b5e6441 }, + 0 }, + /* 55 */ + { { 0x1d28444a,0x2169422c,0xbe136a39,0xe996c5d8,0xfb0c7fce,0x2387afe5, + 0x0c8d744a,0xb8af73cb }, + { 0x338b86fd,0x5fde83aa,0xa58a5cff,0xfee3f158,0x20ac9433,0xc9ee8f6f, + 0x7f3f0895,0xa036395f }, + 0 }, + /* 56 */ + { { 0xa10f7770,0x8c73c6bb,0xa12a0e24,0xa6f16d81,0x51bc2b9f,0x100df682, + 0x875fb533,0x4be36b01 }, + { 0x9fb56dbb,0x9226086e,0x07e7a4f8,0x306fef8b,0x66d52f20,0xeeaccc05, + 0x1bdc00c0,0x8cbc9a87 }, + 0 }, + /* 57 */ + { { 0xc0dac4ab,0xe131895c,0x712ff112,0xa874a440,0x6a1cee57,0x6332ae7c, + 0x0c0835f8,0x44e7553e }, + { 0x7734002d,0x6d503fff,0x0b34425c,0x9d35cb8b,0x0e8738b5,0x95f70276, + 0x5eb8fc18,0x470a683a }, + 0 }, + /* 58 */ + { { 0x90513482,0x81b761dc,0x01e9276a,0x0287202a,0x0ce73083,0xcda441ee, + 0xc63dc6ef,0x16410690 }, + { 0x6d06a2ed,0xf5034a06,0x189b100b,0xdd4d7745,0xab8218c9,0xd914ae72, + 0x7abcbb4f,0xd73479fd }, + 0 }, + /* 59 */ + { { 0x5ad4c6e5,0x7edefb16,0x5b06d04d,0x262cf08f,0x8575cb14,0x12ed5bb1, + 0x0771666b,0x816469e3 }, + { 0x561e291e,0xd7ab9d79,0xc1de1661,0xeb9daf22,0x135e0513,0xf49827eb, + 0xf0dd3f9c,0x0a36dd23 }, + 0 }, + /* 60 */ + { { 0x41d5533c,0x098d32c7,0x8684628f,0x7c5f5a9e,0xe349bd11,0x39a228ad, + 0xfdbab118,0xe331dfd6 }, + { 0x6bcc6ed8,0x5100ab68,0xef7a260e,0x7160c3bd,0xbce850d7,0x9063d9a7, + 0x492e3389,0xd3b4782a }, + 0 }, + /* 61 */ + { { 0xf3821f90,0xa149b6e8,0x66eb7aad,0x92edd9ed,0x1a013116,0x0bb66953, + 0x4c86a5bd,0x7281275a }, + { 0xd3ff47e5,0x503858f7,0x61016441,0x5e1616bc,0x7dfd9bb1,0x62b0f11a, + 0xce145059,0x2c062e7e }, + 0 }, + /* 62 */ + { { 0x0159ac2e,0xa76f996f,0xcbdb2713,0x281e7736,0x08e46047,0x2ad6d288, + 0x2c4e7ef1,0x282a35f9 }, + { 0xc0ce5cd2,0x9c354b1e,0x1379c229,0xcf99efc9,0x3e82c11e,0x992caf38, + 0x554d2abd,0xc71cd513 }, + 0 }, + /* 63 */ + { { 0x09b578f4,0x4885de9c,0xe3affa7a,0x1884e258,0x59182f1f,0x8f76b1b7, + 0xcf47f3a3,0xc50f6740 }, + { 0x374b68ea,0xa9c4adf3,0x69965fe2,0xa406f323,0x85a53050,0x2f86a222, + 0x212958dc,0xb9ecb3a7 }, + 0 }, + /* 64 */ + { { 0xf4f8b16a,0x56f8410e,0xc47b266a,0x97241afe,0x6d9c87c1,0x0a406b8e, + 0xcd42ab1b,0x803f3e02 }, + { 0x04dbec69,0x7f0309a8,0x3bbad05f,0xa83b85f7,0xad8e197f,0xc6097273, + 0x5067adc1,0xc097440e }, + 0 }, + /* 65 */ + { { 0xc379ab34,0x846a56f2,0x841df8d1,0xa8ee068b,0x176c68ef,0x20314459, + 0x915f1f30,0xf1af32d5 }, + { 0x5d75bd50,0x99c37531,0xf72f67bc,0x837cffba,0x48d7723f,0x0613a418, + 0xe2d41c8b,0x23d0f130 }, + 0 }, + /* 66 */ + { { 0xf41500d9,0x857ab6ed,0xfcbeada8,0x0d890ae5,0x89725951,0x52fe8648, + 0xc0a3fadd,0xb0288dd6 }, + { 0x650bcb08,0x85320f30,0x695d6e16,0x71af6313,0xb989aa76,0x31f520a7, + 0xf408c8d2,0xffd3724f }, + 0 }, + /* 67 */ + { { 0xb458e6cb,0x53968e64,0x317a5d28,0x992dad20,0x7aa75f56,0x3814ae0b, + 0xd78c26df,0xf5590f4a }, + { 0xcf0ba55a,0x0fc24bd3,0x0c778bae,0x0fc4724a,0x683b674a,0x1ce9864f, + 0xf6f74a20,0x18d6da54 }, + 0 }, + /* 68 */ + { { 0xd5be5a2b,0xed93e225,0x5934f3c6,0x6fe79983,0x22626ffc,0x43140926, + 0x7990216a,0x50bbb4d9 }, + { 0xe57ec63e,0x378191c6,0x181dcdb2,0x65422c40,0x0236e0f6,0x41a8099b, + 0x01fe49c3,0x2b100118 }, + 0 }, + /* 69 */ + { { 0x9b391593,0xfc68b5c5,0x598270fc,0xc385f5a2,0xd19adcbb,0x7144f3aa, + 0x83fbae0c,0xdd558999 }, + { 0x74b82ff4,0x93b88b8e,0x71e734c9,0xd2e03c40,0x43c0322a,0x9a7a9eaf, + 0x149d6041,0xe6e4c551 }, + 0 }, + /* 70 */ + { { 0x1e9af288,0x55f655bb,0xf7ada931,0x647e1a64,0xcb2820e5,0x43697e4b, + 0x07ed56ff,0x51e00db1 }, + { 0x771c327e,0x43d169b8,0x4a96c2ad,0x29cdb20b,0x3deb4779,0xc07d51f5, + 0x49829177,0xe22f4241 }, + 0 }, + /* 71 */ + { { 0x635f1abb,0xcd45e8f4,0x68538874,0x7edc0cb5,0xb5a8034d,0xc9472c1f, + 0x52dc48c9,0xf709373d }, + { 0xa8af30d6,0x401966bb,0xf137b69c,0x95bf5f4a,0x9361c47e,0x3966162a, + 0xe7275b11,0xbd52d288 }, + 0 }, + /* 72 */ + { { 0x9c5fa877,0xab155c7a,0x7d3a3d48,0x17dad672,0x73d189d8,0x43f43f9e, + 0xc8aa77a6,0xa0d0f8e4 }, + { 0xcc94f92d,0x0bbeafd8,0x0c4ddb3a,0xd818c8be,0xb82eba14,0x22cc65f8, + 0x946d6a00,0xa56c78c7 }, + 0 }, + /* 73 */ + { { 0x0dd09529,0x2962391b,0x3daddfcf,0x803e0ea6,0x5b5bf481,0x2c77351f, + 0x731a367a,0xd8befdf8 }, + { 0xfc0157f4,0xab919d42,0xfec8e650,0xf51caed7,0x02d48b0a,0xcdf9cb40, + 0xce9f6478,0x854a68a5 }, + 0 }, + /* 74 */ + { { 0x63506ea5,0xdc35f67b,0xa4fe0d66,0x9286c489,0xfe95cd4d,0x3f101d3b, + 0x98846a95,0x5cacea0b }, + { 0x9ceac44d,0xa90df60c,0x354d1c3a,0x3db29af4,0xad5dbabe,0x08dd3de8, + 0x35e4efa9,0xe4982d12 }, + 0 }, + /* 75 */ + { { 0xc34cd55e,0x23104a22,0x2680d132,0x58695bb3,0x1fa1d943,0xfb345afa, + 0x16b20499,0x8046b7f6 }, + { 0x38e7d098,0xb533581e,0xf46f0b70,0xd7f61e8d,0x44cb78c4,0x30dea9ea, + 0x9082af55,0xeb17ca7b }, + 0 }, + /* 76 */ + { { 0x76a145b9,0x1751b598,0xc1bc71ec,0xa5cf6b0f,0x392715bb,0xd3e03565, + 0xfab5e131,0x097b00ba }, + { 0x565f69e1,0xaa66c8e9,0xb5be5199,0x77e8f75a,0xda4fd984,0x6033ba11, + 0xafdbcc9e,0xf95c747b }, + 0 }, + /* 77 */ + { { 0xbebae45e,0x558f01d3,0xc4bc6955,0xa8ebe9f0,0xdbc64fc6,0xaeb705b1, + 0x566ed837,0x3512601e }, + { 0xfa1161cd,0x9336f1e1,0x4c65ef87,0x328ab8d5,0x724f21e5,0x4757eee2, + 0x6068ab6b,0x0ef97123 }, + 0 }, + /* 78 */ + { { 0x54ca4226,0x02598cf7,0xf8642c8e,0x5eede138,0x468e1790,0x48963f74, + 0x3b4fbc95,0xfc16d933 }, + { 0xe7c800ca,0xbe96fb31,0x2678adaa,0x13806331,0x6ff3e8b5,0x3d624497, + 0xb95d7a17,0x14ca4af1 }, + 0 }, + /* 79 */ + { { 0xbd2f81d5,0x7a4771ba,0x01f7d196,0x1a5f9d69,0xcad9c907,0xd898bef7, + 0xf59c231d,0x4057b063 }, + { 0x89c05c0a,0xbffd82fe,0x1dc0df85,0xe4911c6f,0xa35a16db,0x3befccae, + 0xf1330b13,0x1c3b5d64 }, + 0 }, + /* 80 */ + { { 0x80ec21fe,0x5fe14bfe,0xc255be82,0xf6ce116a,0x2f4a5d67,0x98bc5a07, + 0xdb7e63af,0xfad27148 }, + { 0x29ab05b3,0x90c0b6ac,0x4e251ae6,0x37a9a83c,0xc2aade7d,0x0a7dc875, + 0x9f0e1a84,0x77387de3 }, + 0 }, + /* 81 */ + { { 0xa56c0dd7,0x1e9ecc49,0x46086c74,0xa5cffcd8,0xf505aece,0x8f7a1408, + 0xbef0c47e,0xb37b85c0 }, + { 0xcc0e6a8f,0x3596b6e4,0x6b388f23,0xfd6d4bbf,0xc39cef4e,0xaba453fa, + 0xf9f628d5,0x9c135ac8 }, + 0 }, + /* 82 */ + { { 0x84e35743,0x32aa3202,0x85a3cdef,0x320d6ab1,0x1df19819,0xb821b176, + 0xc433851f,0x5721361f }, + { 0x71fc9168,0x1f0db36a,0x5e5c403c,0x5f98ba73,0x37bcd8f5,0xf64ca87e, + 0xe6bb11bd,0xdcbac3c9 }, + 0 }, + /* 83 */ + { { 0x4518cbe2,0xf01d9968,0x9c9eb04e,0xd242fc18,0xe47feebf,0x727663c7, + 0x2d626862,0xb8c1c89e }, + { 0xc8e1d569,0x51a58bdd,0xb7d88cd0,0x563809c8,0xf11f31eb,0x26c27fd9, + 0x2f9422d4,0x5d23bbda }, + 0 }, + /* 84 */ + { { 0x95c8f8be,0x0a1c7294,0x3bf362bf,0x2961c480,0xdf63d4ac,0x9e418403, + 0x91ece900,0xc109f9cb }, + { 0x58945705,0xc2d095d0,0xddeb85c0,0xb9083d96,0x7a40449b,0x84692b8d, + 0x2eee1ee1,0x9bc3344f }, + 0 }, + /* 85 */ + { { 0x42913074,0x0d5ae356,0x48a542b1,0x55491b27,0xb310732a,0x469ca665, + 0x5f1a4cc1,0x29591d52 }, + { 0xb84f983f,0xe76f5b6b,0x9f5f84e1,0xbe7eef41,0x80baa189,0x1200d496, + 0x18ef332c,0x6376551f }, + 0 }, + /* 86 */ + { { 0x562976cc,0xbda5f14e,0x0ef12c38,0x22bca3e6,0x6cca9852,0xbbfa3064, + 0x08e2987a,0xbdb79dc8 }, + { 0xcb06a772,0xfd2cb5c9,0xfe536dce,0x38f475aa,0x7c2b5db8,0xc2a3e022, + 0xadd3c14a,0x8ee86001 }, + 0 }, + /* 87 */ + { { 0xa4ade873,0xcbe96981,0xc4fba48c,0x7ee9aa4d,0x5a054ba5,0x2cee2899, + 0x6f77aa4b,0x92e51d7a }, + { 0x7190a34d,0x948bafa8,0xf6bd1ed1,0xd698f75b,0x0caf1144,0xd00ee6e3, + 0x0a56aaaa,0x5182f86f }, + 0 }, + /* 88 */ + { { 0x7a4cc99c,0xfba6212c,0x3e6d9ca1,0xff609b68,0x5ac98c5a,0x5dbb27cb, + 0x4073a6f2,0x91dcab5d }, + { 0x5f575a70,0x01b6cc3d,0x6f8d87fa,0x0cb36139,0x89981736,0x165d4e8c, + 0x97974f2b,0x17a0cedb }, + 0 }, + /* 89 */ + { { 0x076c8d3a,0x38861e2a,0x210f924b,0x701aad39,0x13a835d9,0x94d0eae4, + 0x7f4cdf41,0x2e8ce36c }, + { 0x037a862b,0x91273dab,0x60e4c8fa,0x01ba9bb7,0x33baf2dd,0xf9645388, + 0x34f668f3,0xf4ccc6cb }, + 0 }, + /* 90 */ + { { 0xf1f79687,0x44ef525c,0x92efa815,0x7c595495,0xa5c78d29,0xe1231741, + 0x9a0df3c9,0xac0db488 }, + { 0xdf01747f,0x86bfc711,0xef17df13,0x592b9358,0x5ccb6bb5,0xe5880e4f, + 0x94c974a2,0x95a64a61 }, + 0 }, + /* 91 */ + { { 0xc15a4c93,0x72c1efda,0x82585141,0x40269b73,0x16cb0bad,0x6a8dfb1c, + 0x29210677,0x231e54ba }, + { 0x8ae6d2dc,0xa70df917,0x39112918,0x4d6aa63f,0x5e5b7223,0xf627726b, + 0xd8a731e1,0xab0be032 }, + 0 }, + /* 92 */ + { { 0x8d131f2d,0x097ad0e9,0x3b04f101,0x637f09e3,0xd5e9a748,0x1ac86196, + 0x2cf6a679,0xf1bcc880 }, + { 0xe8daacb4,0x25c69140,0x60f65009,0x3c4e4055,0x477937a6,0x591cc8fc, + 0x5aebb271,0x85169469 }, + 0 }, + /* 93 */ + { { 0xf1dcf593,0xde35c143,0xb018be3b,0x78202b29,0x9bdd9d3d,0xe9cdadc2, + 0xdaad55d8,0x8f67d9d2 }, + { 0x7481ea5f,0x84111656,0xe34c590c,0xe7d2dde9,0x05053fa8,0xffdd43f4, + 0xc0728b5d,0xf84572b9 }, + 0 }, + /* 94 */ + { { 0x97af71c9,0x5e1a7a71,0x7a736565,0xa1449444,0x0e1d5063,0xa1b4ae07, + 0x616b2c19,0xedee2710 }, + { 0x11734121,0xb2f034f5,0x4a25e9f0,0x1cac6e55,0xa40c2ecf,0x8dc148f3, + 0x44ebd7f4,0x9fd27e9b }, + 0 }, + /* 95 */ + { { 0xf6e2cb16,0x3cc7658a,0xfe5919b6,0xe3eb7d2c,0x168d5583,0x5a8c5816, + 0x958ff387,0xa40c2fb6 }, + { 0xfedcc158,0x8c9ec560,0x55f23056,0x7ad804c6,0x9a307e12,0xd9396704, + 0x7dc6decf,0x99bc9bb8 }, + 0 }, + /* 96 */ + { { 0x927dafc6,0x84a9521d,0x5c09cd19,0x52c1fb69,0xf9366dde,0x9d9581a0, + 0xa16d7e64,0x9abe210b }, + { 0x48915220,0x480af84a,0x4dd816c6,0xfa73176a,0x1681ca5a,0xc7d53987, + 0x87f344b0,0x7881c257 }, + 0 }, + /* 97 */ + { { 0xe0bcf3ff,0x93399b51,0x127f74f6,0x0d02cbc5,0xdd01d968,0x8fb465a2, + 0xa30e8940,0x15e6e319 }, + { 0x3e0e05f4,0x646d6e0d,0x43588404,0xfad7bddc,0xc4f850d3,0xbe61c7d1, + 0x191172ce,0x0e55facf }, + 0 }, + /* 98 */ + { { 0xf8787564,0x7e9d9806,0x31e85ce6,0x1a331721,0xb819e8d6,0x6b0158ca, + 0x6fe96577,0xd73d0976 }, + { 0x1eb7206e,0x42483425,0xc618bb42,0xa519290f,0x5e30a520,0x5dcbb859, + 0x8f15a50b,0x9250a374 }, + 0 }, + /* 99 */ + { { 0xbe577410,0xcaff08f8,0x5077a8c6,0xfd408a03,0xec0a63a4,0xf1f63289, + 0xc1cc8c0b,0x77414082 }, + { 0xeb0991cd,0x05a40fa6,0x49fdc296,0xc1ca0866,0xb324fd40,0x3a68a3c7, + 0x12eb20b9,0x8cb04f4d }, + 0 }, + /* 100 */ + { { 0x6906171c,0xb1c2d055,0xb0240c3f,0x9073e9cd,0xd8906841,0xdb8e6b4f, + 0x47123b51,0xe4e429ef }, + { 0x38ec36f4,0x0b8dd53c,0xff4b6a27,0xf9d2dc01,0x879a9a48,0x5d066e07, + 0x3c6e6552,0x37bca2ff }, + 0 }, + /* 101 */ + { { 0xdf562470,0x4cd2e3c7,0xc0964ac9,0x44f272a2,0x80c793be,0x7c6d5df9, + 0x3002b22a,0x59913edc }, + { 0x5750592a,0x7a139a83,0xe783de02,0x99e01d80,0xea05d64f,0xcf8c0375, + 0xb013e226,0x43786e4a }, + 0 }, + /* 102 */ + { { 0x9e56b5a6,0xff32b0ed,0xd9fc68f9,0x0750d9a6,0x597846a7,0xec15e845, + 0xb7e79e7a,0x8638ca98 }, + { 0x0afc24b2,0x2f5ae096,0x4dace8f2,0x05398eaf,0xaecba78f,0x3b765dd0, + 0x7b3aa6f0,0x1ecdd36a }, + 0 }, + /* 103 */ + { { 0x6c5ff2f3,0x5d3acd62,0x2873a978,0xa2d516c0,0xd2110d54,0xad94c9fa, + 0xd459f32d,0xd85d0f85 }, + { 0x10b11da3,0x9f700b8d,0xa78318c4,0xd2c22c30,0x9208decd,0x556988f4, + 0xb4ed3c62,0xa04f19c3 }, + 0 }, + /* 104 */ + { { 0xed7f93bd,0x087924c8,0x392f51f6,0xcb64ac5d,0x821b71af,0x7cae330a, + 0x5c0950b0,0x92b2eeea }, + { 0x85b6e235,0x85ac4c94,0x2936c0f0,0xab2ca4a9,0xe0508891,0x80faa6b3, + 0x5834276c,0x1ee78221 }, + 0 }, + /* 105 */ + { { 0xe63e79f7,0xa60a2e00,0xf399d906,0xf590e7b2,0x6607c09d,0x9021054a, + 0x57a6e150,0xf3f2ced8 }, + { 0xf10d9b55,0x200510f3,0xd8642648,0x9d2fcfac,0xe8bd0e7c,0xe5631aa7, + 0x3da3e210,0x0f56a454 }, + 0 }, + /* 106 */ + { { 0x1043e0df,0x5b21bffa,0x9c007e6d,0x6c74b6cc,0xd4a8517a,0x1a656ec0, + 0x1969e263,0xbd8f1741 }, + { 0xbeb7494a,0x8a9bbb86,0x45f3b838,0x1567d46f,0xa4e5a79a,0xdf7a12a7, + 0x30ccfa09,0x2d1a1c35 }, + 0 }, + /* 107 */ + { { 0x506508da,0x192e3813,0xa1d795a7,0x336180c4,0x7a9944b3,0xcddb5949, + 0xb91fba46,0xa107a65e }, + { 0x0f94d639,0xe6d1d1c5,0x8a58b7d7,0x8b4af375,0xbd37ca1c,0x1a7c5584, + 0xf87a9af2,0x183d760a }, + 0 }, + /* 108 */ + { { 0x0dde59a4,0x29d69711,0x0e8bef87,0xf1ad8d07,0x4f2ebe78,0x229b4963, + 0xc269d754,0x1d44179d }, + { 0x8390d30e,0xb32dc0cf,0x0de8110c,0x0a3b2753,0x2bc0339a,0x31af1dc5, + 0x9606d262,0x771f9cc2 }, + 0 }, + /* 109 */ + { { 0x85040739,0x99993e77,0x8026a939,0x44539db9,0xf5f8fc26,0xcf40f6f2, + 0x0362718e,0x64427a31 }, + { 0x85428aa8,0x4f4f2d87,0xebfb49a8,0x7b7adc3f,0xf23d01ac,0x201b2c6d, + 0x6ae90d6d,0x49d9b749 }, + 0 }, + /* 110 */ + { { 0x435d1099,0xcc78d8bc,0x8e8d1a08,0x2adbcd4e,0x2cb68a41,0x02c2e2a0, + 0x3f605445,0x9037d81b }, + { 0x074c7b61,0x7cdbac27,0x57bfd72e,0xfe2031ab,0x596d5352,0x61ccec96, + 0x7cc0639c,0x08c3de6a }, + 0 }, + /* 111 */ + { { 0xf6d552ab,0x20fdd020,0x05cd81f1,0x56baff98,0x91351291,0x06fb7c3e, + 0x45796b2f,0xc6909442 }, + { 0x41231bd1,0x17b3ae9c,0x5cc58205,0x1eac6e87,0xf9d6a122,0x208837ab, + 0xcafe3ac0,0x3fa3db02 }, + 0 }, + /* 112 */ + { { 0x05058880,0xd75a3e65,0x643943f2,0x7da365ef,0xfab24925,0x4147861c, + 0xfdb808ff,0xc5c4bdb0 }, + { 0xb272b56b,0x73513e34,0x11b9043a,0xc8327e95,0xf8844969,0xfd8ce37d, + 0x46c2b6b5,0x2d56db94 }, + 0 }, + /* 113 */ + { { 0xff46ac6b,0x2461782f,0x07a2e425,0xd19f7926,0x09a48de1,0xfafea3c4, + 0xe503ba42,0x0f56bd9d }, + { 0x345cda49,0x137d4ed1,0x816f299d,0x821158fc,0xaeb43402,0xe7c6a54a, + 0x1173b5f1,0x4003bb9d }, + 0 }, + /* 114 */ + { { 0xa0803387,0x3b8e8189,0x39cbd404,0xece115f5,0xd2877f21,0x4297208d, + 0xa07f2f9e,0x53765522 }, + { 0xa8a4182d,0xa4980a21,0x3219df79,0xa2bbd07a,0x1a19a2d4,0x674d0a2e, + 0x6c5d4549,0x7a056f58 }, + 0 }, + /* 115 */ + { { 0x9d8a2a47,0x646b2558,0xc3df2773,0x5b582948,0xabf0d539,0x51ec000e, + 0x7a1a2675,0x77d482f1 }, + { 0x87853948,0xb8a1bd95,0x6cfbffee,0xa6f817bd,0x80681e47,0xab6ec057, + 0x2b38b0e4,0x4115012b }, + 0 }, + /* 116 */ + { { 0x6de28ced,0x3c73f0f4,0x9b13ec47,0x1d5da760,0x6e5c6392,0x61b8ce9e, + 0xfbea0946,0xcdf04572 }, + { 0x6c53c3b0,0x1cb3c58b,0x447b843c,0x97fe3c10,0x2cb9780e,0xfb2b8ae1, + 0x97383109,0xee703dda }, + 0 }, + /* 117 */ + { { 0xff57e43a,0x34515140,0xb1b811b8,0xd44660d3,0x8f42b986,0x2b3b5dff, + 0xa162ce21,0x2a0ad89d }, + { 0x6bc277ba,0x64e4a694,0xc141c276,0xc788c954,0xcabf6274,0x141aa64c, + 0xac2b4659,0xd62d0b67 }, + 0 }, + /* 118 */ + { { 0x2c054ac4,0x39c5d87b,0xf27df788,0x57005859,0xb18128d6,0xedf7cbf3, + 0x991c2426,0xb39a23f2 }, + { 0xf0b16ae5,0x95284a15,0xa136f51b,0x0c6a05b1,0xf2700783,0x1d63c137, + 0xc0674cc5,0x04ed0092 }, + 0 }, + /* 119 */ + { { 0x9ae90393,0x1f4185d1,0x4a3d64e6,0x3047b429,0x9854fc14,0xae0001a6, + 0x0177c387,0xa0a91fc1 }, + { 0xae2c831e,0xff0a3f01,0x2b727e16,0xbb76ae82,0x5a3075b4,0x8f12c8a1, + 0x9ed20c41,0x084cf988 }, + 0 }, + /* 120 */ + { { 0xfca6becf,0xd98509de,0x7dffb328,0x2fceae80,0x4778e8b9,0x5d8a15c4, + 0x73abf77e,0xd57955b2 }, + { 0x31b5d4f1,0x210da79e,0x3cfa7a1c,0xaa52f04b,0xdc27c20b,0xd4d12089, + 0x02d141f1,0x8e14ea42 }, + 0 }, + /* 121 */ + { { 0xf2897042,0xeed50345,0x43402c4a,0x8d05331f,0xc8bdfb21,0xc8d9c194, + 0x2aa4d158,0x597e1a37 }, + { 0xcf0bd68c,0x0327ec1a,0xab024945,0x6d4be0dc,0xc9fe3e84,0x5b9c8d7a, + 0x199b4dea,0xca3f0236 }, + 0 }, + /* 122 */ + { { 0x6170bd20,0x592a10b5,0x6d3f5de7,0x0ea897f1,0x44b2ade2,0xa3363ff1, + 0x309c07e4,0xbde7fd7e }, + { 0xb8f5432c,0x516bb6d2,0xe043444b,0x210dc1cb,0xf8f95b5a,0x3db01e6f, + 0x0a7dd198,0xb623ad0e }, + 0 }, + /* 123 */ + { { 0x60c7b65b,0xa75bd675,0x23a4a289,0xab8c5590,0xd7b26795,0xf8220fd0, + 0x58ec137b,0xd6aa2e46 }, + { 0x5138bb85,0x10abc00b,0xd833a95c,0x8c31d121,0x1702a32e,0xb24ff00b, + 0x2dcc513a,0x111662e0 }, + 0 }, + /* 124 */ + { { 0xefb42b87,0x78114015,0x1b6c4dff,0xbd9f5d70,0xa7d7c129,0x66ecccd7, + 0x94b750f8,0xdb3ee1cb }, + { 0xf34837cf,0xb26f3db0,0xb9578d4f,0xe7eed18b,0x7c56657d,0x5d2cdf93, + 0x52206a59,0x886a6442 }, + 0 }, + /* 125 */ + { { 0x65b569ea,0x3c234cfb,0xf72119c1,0x20011141,0xa15a619e,0x8badc85d, + 0x018a17bc,0xa70cf4eb }, + { 0x8c4a6a65,0x224f97ae,0x0134378f,0x36e5cf27,0x4f7e0960,0xbe3a609e, + 0xd1747b77,0xaa4772ab }, + 0 }, + /* 126 */ + { { 0x7aa60cc0,0x67676131,0x0368115f,0xc7916361,0xbbc1bb5a,0xded98bb4, + 0x30faf974,0x611a6ddc }, + { 0xc15ee47a,0x30e78cbc,0x4e0d96a5,0x2e896282,0x3dd9ed88,0x36f35adf, + 0x16429c88,0x5cfffaf8 }, + 0 }, + /* 127 */ + { { 0x9b7a99cd,0xc0d54cff,0x843c45a1,0x7bf3b99d,0x62c739e1,0x038a908f, + 0x7dc1994c,0x6e5a6b23 }, + { 0x0ba5db77,0xef8b454e,0xacf60d63,0xb7b8807f,0x76608378,0xe591c0c6, + 0x242dabcc,0x481a238d }, + 0 }, + /* 128 */ + { { 0x35d0b34a,0xe3417bc0,0x8327c0a7,0x440b386b,0xac0362d1,0x8fb7262d, + 0xe0cdf943,0x2c41114c }, + { 0xad95a0b1,0x2ba5cef1,0x67d54362,0xc09b37a8,0x01e486c9,0x26d6cdd2, + 0x42ff9297,0x20477abf }, + 0 }, + /* 129 */ + { { 0x18d65dbf,0x2f75173c,0x339edad8,0x77bf940e,0xdcf1001c,0x7022d26b, + 0xc77396b6,0xac66409a }, + { 0xc6261cc3,0x8b0bb36f,0x190e7e90,0x213f7bc9,0xa45e6c10,0x6541ceba, + 0xcc122f85,0xce8e6975 }, + 0 }, + /* 130 */ + { { 0xbc0a67d2,0x0f121b41,0x444d248a,0x62d4760a,0x659b4737,0x0e044f1d, + 0x250bb4a8,0x08fde365 }, + { 0x848bf287,0xaceec3da,0xd3369d6e,0xc2a62182,0x92449482,0x3582dfdc, + 0x565d6cd7,0x2f7e2fd2 }, + 0 }, + /* 131 */ + { { 0xc3770fa7,0xae4b92db,0x379043f9,0x095e8d5c,0x17761171,0x54f34e9d, + 0x907702ae,0xc65be92e }, + { 0xf6fd0a40,0x2758a303,0xbcce784b,0xe7d822e3,0x4f9767bf,0x7ae4f585, + 0xd1193b3a,0x4bff8e47 }, + 0 }, + /* 132 */ + { { 0x00ff1480,0xcd41d21f,0x0754db16,0x2ab8fb7d,0xbbe0f3ea,0xac81d2ef, + 0x5772967d,0x3e4e4ae6 }, + { 0x3c5303e6,0x7e18f36d,0x92262397,0x3bd9994b,0x1324c3c0,0x9ed70e26, + 0x58ec6028,0x5388aefd }, + 0 }, + /* 133 */ + { { 0x5e5d7713,0xad1317eb,0x75de49da,0x09b985ee,0xc74fb261,0x32f5bc4f, + 0x4f75be0e,0x5cf908d1 }, + { 0x8e657b12,0x76043510,0xb96ed9e6,0xbfd421a5,0x8970ccc2,0x0e29f51f, + 0x60f00ce2,0xa698ba40 }, + 0 }, + /* 134 */ + { { 0xef748fec,0x73db1686,0x7e9d2cf9,0xe6e755a2,0xce265eff,0x630b6544, + 0x7aebad8d,0xb142ef8a }, + { 0x17d5770a,0xad31af9f,0x2cb3412f,0x66af3b67,0xdf3359de,0x6bd60d1b, + 0x58515075,0xd1896a96 }, + 0 }, + /* 135 */ + { { 0x33c41c08,0xec5957ab,0x5468e2e1,0x87de94ac,0xac472f6c,0x18816b73, + 0x7981da39,0x267b0e0b }, + { 0x8e62b988,0x6e554e5d,0x116d21e7,0xd8ddc755,0x3d2a6f99,0x4610faf0, + 0xa1119393,0xb54e287a }, + 0 }, + /* 136 */ + { { 0x178a876b,0x0a0122b5,0x085104b4,0x51ff96ff,0x14f29f76,0x050b31ab, + 0x5f87d4e6,0x84abb28b }, + { 0x8270790a,0xd5ed439f,0x85e3f46b,0x2d6cb59d,0x6c1e2212,0x75f55c1b, + 0x17655640,0xe5436f67 }, + 0 }, + /* 137 */ + { { 0x2286e8d5,0x53f9025e,0x864453be,0x353c95b4,0xe408e3a0,0xd832f5bd, + 0x5b9ce99e,0x0404f68b }, + { 0xa781e8e5,0xcad33bde,0x163c2f5b,0x3cdf5018,0x0119caa3,0x57576960, + 0x0ac1c701,0x3a4263df }, + 0 }, + /* 138 */ + { { 0x9aeb596d,0xc2965ecc,0x023c92b4,0x01ea03e7,0x2e013961,0x4704b4b6, + 0x905ea367,0x0ca8fd3f }, + { 0x551b2b61,0x92523a42,0x390fcd06,0x1eb7a89c,0x0392a63e,0xe7f1d2be, + 0x4ddb0c33,0x96dca264 }, + 0 }, + /* 139 */ + { { 0x387510af,0x203bb43a,0xa9a36a01,0x846feaa8,0x2f950378,0xd23a5770, + 0x3aad59dc,0x4363e212 }, + { 0x40246a47,0xca43a1c7,0xe55dd24d,0xb362b8d2,0x5d8faf96,0xf9b08604, + 0xd8bb98c4,0x840e115c }, + 0 }, + /* 140 */ + { { 0x1023e8a7,0xf12205e2,0xd8dc7a0b,0xc808a8cd,0x163a5ddf,0xe292a272, + 0x30ded6d4,0x5e0d6abd }, + { 0x7cfc0f64,0x07a721c2,0x0e55ed88,0x42eec01d,0x1d1f9db2,0x26a7bef9, + 0x2945a25a,0x7dea48f4 }, + 0 }, + /* 141 */ + { { 0xe5060a81,0xabdf6f1c,0xf8f95615,0xe79f9c72,0x06ac268b,0xcfd36c54, + 0xebfd16d1,0xabc2a2be }, + { 0xd3e2eac7,0x8ac66f91,0xd2dd0466,0x6f10ba63,0x0282d31b,0x6790e377, + 0x6c7eefc1,0x4ea35394 }, + 0 }, + /* 142 */ + { { 0x5266309d,0xed8a2f8d,0x81945a3e,0x0a51c6c0,0x578c5dc1,0xcecaf45a, + 0x1c94ffc3,0x3a76e689 }, + { 0x7d7b0d0f,0x9aace8a4,0x8f584a5f,0x963ace96,0x4e697fbe,0x51a30c72, + 0x465e6464,0x8212a10a }, + 0 }, + /* 143 */ + { { 0xcfab8caa,0xef7c61c3,0x0e142390,0x18eb8e84,0x7e9733ca,0xcd1dff67, + 0x599cb164,0xaa7cab71 }, + { 0xbc837bd1,0x02fc9273,0xc36af5d7,0xc06407d0,0xf423da49,0x17621292, + 0xfe0617c3,0x40e38073 }, + 0 }, + /* 144 */ + { { 0xa7bf9b7c,0xf4f80824,0x3fbe30d0,0x365d2320,0x97cf9ce3,0xbfbe5320, + 0xb3055526,0xe3604700 }, + { 0x6cc6c2c7,0x4dcb9911,0xba4cbee6,0x72683708,0x637ad9ec,0xdcded434, + 0xa3dee15f,0x6542d677 }, + 0 }, + /* 145 */ + { { 0x7b6c377a,0x3f32b6d0,0x903448be,0x6cb03847,0x20da8af7,0xd6fdd3a8, + 0x09bb6f21,0xa6534aee }, + { 0x1035facf,0x30a1780d,0x9dcb47e6,0x35e55a33,0xc447f393,0x6ea50fe1, + 0xdc9aef22,0xf3cb672f }, + 0 }, + /* 146 */ + { { 0x3b55fd83,0xeb3719fe,0x875ddd10,0xe0d7a46c,0x05cea784,0x33ac9fa9, + 0xaae870e7,0x7cafaa2e }, + { 0x1d53b338,0x9b814d04,0xef87e6c6,0xe0acc0a0,0x11672b0f,0xfb93d108, + 0xb9bd522e,0x0aab13c1 }, + 0 }, + /* 147 */ + { { 0xd2681297,0xddcce278,0xb509546a,0xcb350eb1,0x7661aaf2,0x2dc43173, + 0x847012e9,0x4b91a602 }, + { 0x72f8ddcf,0xdcff1095,0x9a911af4,0x08ebf61e,0xc372430e,0x48f4360a, + 0x72321cab,0x49534c53 }, + 0 }, + /* 148 */ + { { 0xf07b7e9d,0x83df7d71,0x13cd516f,0xa478efa3,0x6c047ee3,0x78ef264b, + 0xd65ac5ee,0xcaf46c4f }, + { 0x92aa8266,0xa04d0c77,0x913684bb,0xedf45466,0xae4b16b0,0x56e65168, + 0x04c6770f,0x14ce9e57 }, + 0 }, + /* 149 */ + { { 0x965e8f91,0x99445e3e,0xcb0f2492,0xd3aca1ba,0x90c8a0a0,0xd31cc70f, + 0x3e4c9a71,0x1bb708a5 }, + { 0x558bdd7a,0xd5ca9e69,0x018a26b1,0x734a0508,0x4c9cf1ec,0xb093aa71, + 0xda300102,0xf9d126f2 }, + 0 }, + /* 150 */ + { { 0xaff9563e,0x749bca7a,0xb49914a0,0xdd077afe,0xbf5f1671,0xe27a0311, + 0x729ecc69,0x807afcb9 }, + { 0xc9b08b77,0x7f8a9337,0x443c7e38,0x86c3a785,0x476fd8ba,0x85fafa59, + 0x6568cd8c,0x751adcd1 }, + 0 }, + /* 151 */ + { { 0x10715c0d,0x8aea38b4,0x8f7697f7,0xd113ea71,0x93fbf06d,0x665eab14, + 0x2537743f,0x29ec4468 }, + { 0xb50bebbc,0x3d94719c,0xe4505422,0x399ee5bf,0x8d2dedb1,0x90cd5b3a, + 0x92a4077d,0xff9370e3 }, + 0 }, + /* 152 */ + { { 0xc6b75b65,0x59a2d69b,0x266651c5,0x4188f8d5,0x3de9d7d2,0x28a9f33e, + 0xa2a9d01a,0x9776478b }, + { 0x929af2c7,0x8852622d,0x4e690923,0x334f5d6d,0xa89a51e9,0xce6cc7e5, + 0xac2f82fa,0x74a6313f }, + 0 }, + /* 153 */ + { { 0xb75f079c,0xb2f4dfdd,0x18e36fbb,0x85b07c95,0xe7cd36dd,0x1b6cfcf0, + 0x0ff4863d,0xab75be15 }, + { 0x173fc9b7,0x81b367c0,0xd2594fd0,0xb90a7420,0xc4091236,0x15fdbf03, + 0x0b4459f6,0x4ebeac2e }, + 0 }, + /* 154 */ + { { 0x5c9f2c53,0xeb6c5fe7,0x8eae9411,0xd2522011,0xf95ac5d8,0xc8887633, + 0x2c1baffc,0xdf99887b }, + { 0x850aaecb,0xbb78eed2,0x01d6a272,0x9d49181b,0xb1cdbcac,0x978dd511, + 0x779f4058,0x27b040a7 }, + 0 }, + /* 155 */ + { { 0xf73b2eb2,0x90405db7,0x8e1b2118,0xe0df8508,0x5962327e,0x501b7152, + 0xe4cfa3f5,0xb393dd37 }, + { 0x3fd75165,0xa1230e7b,0xbcd33554,0xd66344c2,0x0f7b5022,0x6c36f1be, + 0xd0463419,0x09588c12 }, + 0 }, + /* 156 */ + { { 0x02601c3b,0xe086093f,0xcf5c335f,0xfb0252f8,0x894aff28,0x955cf280, + 0xdb9f648b,0x81c879a9 }, + { 0xc6f56c51,0x040e687c,0x3f17618c,0xfed47169,0x9059353b,0x44f88a41, + 0x5fc11bc4,0xfa0d48f5 }, + 0 }, + /* 157 */ + { { 0xe1608e4d,0xbc6e1c9d,0x3582822c,0x010dda11,0x157ec2d7,0xf6b7ddc1, + 0xb6a367d6,0x8ea0e156 }, + { 0x2383b3b4,0xa354e02f,0x3f01f53c,0x69966b94,0x2de03ca5,0x4ff6632b, + 0xfa00b5ac,0x3f5ab924 }, + 0 }, + /* 158 */ + { { 0x59739efb,0x337bb0d9,0xe7ebec0d,0xc751b0f4,0x411a67d1,0x2da52dd6, + 0x2b74256e,0x8bc76887 }, + { 0x82d3d253,0xa5be3b72,0xf58d779f,0xa9f679a1,0xe16767bb,0xa1cac168, + 0x60fcf34f,0xb386f190 }, + 0 }, + /* 159 */ + { { 0x2fedcfc2,0x31f3c135,0x62f8af0d,0x5396bf62,0xe57288c2,0x9a02b4ea, + 0x1b069c4d,0x4cb460f7 }, + { 0x5b8095ea,0xae67b4d3,0x6fc07603,0x92bbf859,0xb614a165,0xe1475f66, + 0x95ef5223,0x52c0d508 }, + 0 }, + /* 160 */ + { { 0x15339848,0x231c210e,0x70778c8d,0xe87a28e8,0x6956e170,0x9d1de661, + 0x2bb09c0b,0x4ac3c938 }, + { 0x6998987d,0x19be0551,0xae09f4d6,0x8b2376c4,0x1a3f933d,0x1de0b765, + 0xe39705f4,0x380d94c7 }, + 0 }, + /* 161 */ + { { 0x81542e75,0x01a355aa,0xee01b9b7,0x96c724a1,0x624d7087,0x6b3a2977, + 0xde2637af,0x2ce3e171 }, + { 0xf5d5bc1a,0xcfefeb49,0x2777e2b5,0xa655607e,0x9513756c,0x4feaac2f, + 0x0b624e4d,0x2e6cd852 }, + 0 }, + /* 162 */ + { { 0x8c31c31d,0x3685954b,0x5bf21a0c,0x68533d00,0x75c79ec9,0x0bd7626e, + 0x42c69d54,0xca177547 }, + { 0xf6d2dbb2,0xcc6edaff,0x174a9d18,0xfd0d8cbd,0xaa4578e8,0x875e8793, + 0x9cab2ce6,0xa976a713 }, + 0 }, + /* 163 */ + { { 0x93fb353d,0x0a651f1b,0x57fcfa72,0xd75cab8b,0x31b15281,0xaa88cfa7, + 0x0a1f4999,0x8720a717 }, + { 0x693e1b90,0x8c3e8d37,0x16f6dfc3,0xd345dc0b,0xb52a8742,0x8ea8d00a, + 0xc769893c,0x9719ef29 }, + 0 }, + /* 164 */ + { { 0x58e35909,0x820eed8d,0x33ddc116,0x9366d8dc,0x6e205026,0xd7f999d0, + 0xe15704c1,0xa5072976 }, + { 0xc4e70b2e,0x002a37ea,0x6890aa8a,0x84dcf657,0x645b2a5c,0xcd71bf18, + 0xf7b77725,0x99389c9d }, + 0 }, + /* 165 */ + { { 0x7ada7a4b,0x238c08f2,0xfd389366,0x3abe9d03,0x766f512c,0x6b672e89, + 0x202c82e4,0xa88806aa }, + { 0xd380184e,0x6602044a,0x126a8b85,0xa8cb78c4,0xad844f17,0x79d670c0, + 0x4738dcfe,0x0043bffb }, + 0 }, + /* 166 */ + { { 0x36d5192e,0x8d59b5dc,0x4590b2af,0xacf885d3,0x11601781,0x83566d0a, + 0xba6c4866,0x52f3ef01 }, + { 0x0edcb64d,0x3986732a,0x8068379f,0x0a482c23,0x7040f309,0x16cbe5fa, + 0x9ef27e75,0x3296bd89 }, + 0 }, + /* 167 */ + { { 0x454d81d7,0x476aba89,0x51eb9b3c,0x9eade7ef,0x81c57986,0x619a21cd, + 0xaee571e9,0x3b90febf }, + { 0x5496f7cb,0x9393023e,0x7fb51bc4,0x55be41d8,0x99beb5ce,0x03f1dd48, + 0x9f810b18,0x6e88069d }, + 0 }, + /* 168 */ + { { 0xb43ea1db,0xce37ab11,0x5259d292,0x0a7ff1a9,0x8f84f186,0x851b0221, + 0xdefaad13,0xa7222bea }, + { 0x2b0a9144,0xa2ac78ec,0xf2fa59c5,0x5a024051,0x6147ce38,0x91d1eca5, + 0xbc2ac690,0xbe94d523 }, + 0 }, + /* 169 */ + { { 0x0b226ce7,0x72f4945e,0x967e8b70,0xb8afd747,0x85a6c63e,0xedea46f1, + 0x9be8c766,0x7782defe }, + { 0x3db38626,0x760d2aa4,0x76f67ad1,0x460ae787,0x54499cdb,0x341b86fc, + 0xa2892e4b,0x03838567 }, + 0 }, + /* 170 */ + { { 0x79ec1a0f,0x2d8daefd,0xceb39c97,0x3bbcd6fd,0x58f61a95,0xf5575ffc, + 0xadf7b420,0xdbd986c4 }, + { 0x15f39eb7,0x81aa8814,0xb98d976c,0x6ee2fcf5,0xcf2f717d,0x5465475d, + 0x6860bbd0,0x8e24d3c4 }, + 0 }, + /* 171 */ + { { 0x9a587390,0x749d8e54,0x0cbec588,0x12bb194f,0xb25983c6,0x46e07da4, + 0x407bafc8,0x541a99c4 }, + { 0x624c8842,0xdb241692,0xd86c05ff,0x6044c12a,0x4f7fcf62,0xc59d14b4, + 0xf57d35d1,0xc0092c49 }, + 0 }, + /* 172 */ + { { 0xdf2e61ef,0xd3cc75c3,0x2e1b35ca,0x7e8841c8,0x909f29f4,0xc62d30d1, + 0x7286944d,0x75e40634 }, + { 0xbbc237d0,0xe7d41fc5,0xec4f01c9,0xc9537bf0,0x282bd534,0x91c51a16, + 0xc7848586,0x5b7cb658 }, + 0 }, + /* 173 */ + { { 0x8a28ead1,0x964a7084,0xfd3b47f6,0x802dc508,0x767e5b39,0x9ae4bfd1, + 0x8df097a1,0x7ae13eba }, + { 0xeadd384e,0xfd216ef8,0xb6b2ff06,0x0361a2d9,0x4bcdb5f3,0x204b9878, + 0xe2a8e3fd,0x787d8074 }, + 0 }, + /* 174 */ + { { 0x757fbb1c,0xc5e25d6b,0xca201deb,0xe47bddb2,0x6d2233ff,0x4a55e9a3, + 0x9ef28484,0x5c222819 }, + { 0x88315250,0x773d4a85,0x827097c1,0x21b21a2b,0xdef5d33f,0xab7c4ea1, + 0xbaf0f2b0,0xe45d37ab }, + 0 }, + /* 175 */ + { { 0x28511c8a,0xd2df1e34,0xbdca6cd3,0xebb229c8,0x627c39a7,0x578a71a7, + 0x84dfb9d3,0xed7bc122 }, + { 0x93dea561,0xcf22a6df,0xd48f0ed1,0x5443f18d,0x5bad23e8,0xd8b86140, + 0x45ca6d27,0xaac97cc9 }, + 0 }, + /* 176 */ + { { 0xa16bd00a,0xeb54ea74,0xf5c0bcc1,0xd839e9ad,0x1f9bfc06,0x092bb7f1, + 0x1163dc4e,0x318f97b3 }, + { 0xc30d7138,0xecc0c5be,0xabc30220,0x44e8df23,0xb0223606,0x2bb7972f, + 0x9a84ff4d,0xfa41faa1 }, + 0 }, + /* 177 */ + { { 0xa6642269,0x4402d974,0x9bb783bd,0xc81814ce,0x7941e60b,0x398d38e4, + 0x1d26e9e2,0x38bb6b2c }, + { 0x6a577f87,0xc64e4a25,0xdc11fe1c,0x8b52d253,0x62280728,0xff336abf, + 0xce7601a5,0x94dd0905 }, + 0 }, + /* 178 */ + { { 0xde93f92a,0x156cf7dc,0x89b5f315,0xa01333cb,0xc995e750,0x02404df9, + 0xd25c2ae9,0x92077867 }, + { 0x0bf39d44,0xe2471e01,0x96bb53d7,0x5f2c9020,0x5c9c3d8f,0x4c44b7b3, + 0xd29beb51,0x81e8428b }, + 0 }, + /* 179 */ + { { 0xc477199f,0x6dd9c2ba,0x6b5ecdd9,0x8cb8eeee,0xee40fd0e,0x8af7db3f, + 0xdbbfa4b1,0x1b94ab62 }, + { 0xce47f143,0x44f0d8b3,0x63f46163,0x51e623fc,0xcc599383,0xf18f270f, + 0x055590ee,0x06a38e28 }, + 0 }, + /* 180 */ + { { 0xb3355b49,0x2e5b0139,0xb4ebf99b,0x20e26560,0xd269f3dc,0xc08ffa6b, + 0x83d9d4f8,0xa7b36c20 }, + { 0x1b3e8830,0x64d15c3a,0xa89f9c0b,0xd5fceae1,0xe2d16930,0xcfeee4a2, + 0xa2822a20,0xbe54c6b4 }, + 0 }, + /* 181 */ + { { 0x8d91167c,0xd6cdb3df,0xe7a6625e,0x517c3f79,0x346ac7f4,0x7105648f, + 0xeae022bb,0xbf30a5ab }, + { 0x93828a68,0x8e7785be,0x7f3ef036,0x5161c332,0x592146b2,0xe11b5feb, + 0x2732d13a,0xd1c820de }, + 0 }, + /* 182 */ + { { 0x9038b363,0x043e1347,0x6b05e519,0x58c11f54,0x6026cad1,0x4fe57abe, + 0x68a18da3,0xb7d17bed }, + { 0xe29c2559,0x44ca5891,0x5bfffd84,0x4f7a0376,0x74e46948,0x498de4af, + 0x6412cc64,0x3997fd5e }, + 0 }, + /* 183 */ + { { 0x8bd61507,0xf2074682,0x34a64d2a,0x29e132d5,0x8a8a15e3,0xffeddfb0, + 0x3c6c13e8,0x0eeb8929 }, + { 0xa7e259f8,0xe9b69a3e,0xd13e7e67,0xce1db7e6,0xad1fa685,0x277318f6, + 0xc922b6ef,0x228916f8 }, + 0 }, + /* 184 */ + { { 0x0a12ab5b,0x959ae25b,0x957bc136,0xcc11171f,0xd16e2b0c,0x8058429e, + 0x6e93097e,0xec05ad1d }, + { 0xac3f3708,0x157ba5be,0x30b59d77,0x31baf935,0x118234e5,0x47b55237, + 0x7ff11b37,0x7d314156 }, + 0 }, + /* 185 */ + { { 0xf6dfefab,0x7bd9c05c,0xdcb37707,0xbe2f2268,0x3a38bb95,0xe53ead97, + 0x9bc1d7a3,0xe9ce66fc }, + { 0x6f6a02a1,0x75aa1576,0x60e600ed,0x38c087df,0x68cdc1b9,0xf8947f34, + 0x72280651,0xd9650b01 }, + 0 }, + /* 186 */ + { { 0x5a057e60,0x504b4c4a,0x8def25e4,0xcbccc3be,0x17c1ccbd,0xa6353208, + 0x804eb7a2,0x14d6699a }, + { 0xdb1f411a,0x2c8a8415,0xf80d769c,0x09fbaf0b,0x1c2f77ad,0xb4deef90, + 0x0d43598a,0x6f4c6841 }, + 0 }, + /* 187 */ + { { 0x96c24a96,0x8726df4e,0xfcbd99a3,0x534dbc85,0x8b2ae30a,0x3c466ef2, + 0x61189abb,0x4c4350fd }, + { 0xf855b8da,0x2967f716,0x463c38a1,0x41a42394,0xeae93343,0xc37e1413, + 0x5a3118b5,0xa726d242 }, + 0 }, + /* 188 */ + { { 0x948c1086,0xdae6b3ee,0xcbd3a2e1,0xf1de503d,0x03d022f3,0x3f35ed3f, + 0xcc6cf392,0x13639e82 }, + { 0xcdafaa86,0x9ac938fb,0x2654a258,0xf45bc5fb,0x45051329,0x1963b26e, + 0xc1a335a3,0xca9365e1 }, + 0 }, + /* 189 */ + { { 0x4c3b2d20,0x3615ac75,0x904e241b,0x742a5417,0xcc9d071d,0xb08521c4, + 0x970b72a5,0x9ce29c34 }, + { 0x6d3e0ad6,0x8cc81f73,0xf2f8434c,0x8060da9e,0x6ce862d9,0x35ed1d1a, + 0xab42af98,0x48c4abd7 }, + 0 }, + /* 190 */ + { { 0x40c7485a,0xd221b0cc,0xe5274dbf,0xead455bb,0x9263d2e8,0x493c7698, + 0xf67b33cb,0x78017c32 }, + { 0x930cb5ee,0xb9d35769,0x0c408ed2,0xc0d14e94,0x272f1a4d,0xf8b7bf55, + 0xde5c1c04,0x53cd0454 }, + 0 }, + /* 191 */ + { { 0x5d28ccac,0xbcd585fa,0x005b746e,0x5f823e56,0xcd0123aa,0x7c79f0a1, + 0xd3d7fa8f,0xeea465c1 }, + { 0x0551803b,0x7810659f,0x7ce6af70,0x6c0b599f,0x29288e70,0x4195a770, + 0x7ae69193,0x1b6e42a4 }, + 0 }, + /* 192 */ + { { 0xf67d04c3,0x2e80937c,0x89eeb811,0x1e312be2,0x92594d60,0x56b5d887, + 0x187fbd3d,0x0224da14 }, + { 0x0c5fe36f,0x87abb863,0x4ef51f5f,0x580f3c60,0xb3b429ec,0x964fb1bf, + 0x42bfff33,0x60838ef0 }, + 0 }, + /* 193 */ + { { 0x7e0bbe99,0x432cb2f2,0x04aa39ee,0x7bda44f3,0x9fa93903,0x5f497c7a, + 0x2d331643,0x636eb202 }, + { 0x93ae00aa,0xfcfd0e61,0x31ae6d2f,0x875a00fe,0x9f93901c,0xf43658a2, + 0x39218bac,0x8844eeb6 }, + 0 }, + /* 194 */ + { { 0x6b3bae58,0x114171d2,0x17e39f3e,0x7db3df71,0x81a8eada,0xcd37bc7f, + 0x51fb789e,0x27ba83dc }, + { 0xfbf54de5,0xa7df439f,0xb5fe1a71,0x7277030b,0xdb297a48,0x42ee8e35, + 0x87f3a4ab,0xadb62d34 }, + 0 }, + /* 195 */ + { { 0xa175df2a,0x9b1168a2,0x618c32e9,0x082aa04f,0x146b0916,0xc9e4f2e7, + 0x75e7c8b2,0xb990fd76 }, + { 0x4df37313,0x0829d96b,0xd0b40789,0x1c205579,0x78087711,0x66c9ae4a, + 0x4d10d18d,0x81707ef9 }, + 0 }, + /* 196 */ + { { 0x03d6ff96,0x97d7cab2,0x0d843360,0x5b851bfc,0xd042db4b,0x268823c4, + 0xd5a8aa5c,0x3792daea }, + { 0x941afa0b,0x52818865,0x42d83671,0xf3e9e741,0x5be4e0a7,0x17c82527, + 0x94b001ba,0x5abd635e }, + 0 }, + /* 197 */ + { { 0x0ac4927c,0x727fa84e,0xa7c8cf23,0xe3886035,0x4adca0df,0xa4bcd5ea, + 0x846ab610,0x5995bf21 }, + { 0x829dfa33,0xe90f860b,0x958fc18b,0xcaafe2ae,0x78630366,0x9b3baf44, + 0xd483411e,0x44c32ca2 }, + 0 }, + /* 198 */ + { { 0xe40ed80c,0xa74a97f1,0x31d2ca82,0x5f938cb1,0x7c2d6ad9,0x53f2124b, + 0x8082a54c,0x1f2162fb }, + { 0x720b173e,0x7e467cc5,0x085f12f9,0x40e8a666,0x4c9d65dc,0x8cebc20e, + 0xc3e907c9,0x8f1d402b }, + 0 }, + /* 199 */ + { { 0xfbc4058a,0x4f592f9c,0x292f5670,0xb15e14b6,0xbc1d8c57,0xc55cfe37, + 0x926edbf9,0xb1980f43 }, + { 0x32c76b09,0x98c33e09,0x33b07f78,0x1df5279d,0x863bb461,0x6f08ead4, + 0x37448e45,0x2828ad9b }, + 0 }, + /* 200 */ + { { 0xc4cf4ac5,0x696722c4,0xdde64afb,0xf5ac1a3f,0xe0890832,0x0551baa2, + 0x5a14b390,0x4973f127 }, + { 0x322eac5d,0xe59d8335,0x0bd9b568,0x5e07eef5,0xa2588393,0xab36720f, + 0xdb168ac7,0x6dac8ed0 }, + 0 }, + /* 201 */ + { { 0xeda835ef,0xf7b545ae,0x1d10ed51,0x4aa113d2,0x13741b09,0x035a65e0, + 0x20b9de4c,0x4b23ef59 }, + { 0x3c4c7341,0xe82bb680,0x3f58bc37,0xd457706d,0xa51e3ee8,0x73527863, + 0xddf49a4e,0x4dd71534 }, + 0 }, + /* 202 */ + { { 0x95476cd9,0xbf944672,0xe31a725b,0x648d072f,0xfc4b67e0,0x1441c8b8, + 0x2f4a4dbb,0xfd317000 }, + { 0x8995d0e1,0x1cb43ff4,0x0ef729aa,0x76e695d1,0x41798982,0xe0d5f976, + 0x9569f365,0x14fac58c }, + 0 }, + /* 203 */ + { { 0xf312ae18,0xad9a0065,0xfcc93fc9,0x51958dc0,0x8a7d2846,0xd9a14240, + 0x36abda50,0xed7c7651 }, + { 0x25d4abbc,0x46270f1a,0xf1a113ea,0x9b5dd8f3,0x5b51952f,0xc609b075, + 0x4d2e9f53,0xfefcb7f7 }, + 0 }, + /* 204 */ + { { 0xba119185,0xbd09497a,0xaac45ba4,0xd54e8c30,0xaa521179,0x492479de, + 0x87e0d80b,0x1801a57e }, + { 0xfcafffb0,0x073d3f8d,0xae255240,0x6cf33c0b,0x5b5fdfbc,0x781d763b, + 0x1ead1064,0x9f8fc11e }, + 0 }, + /* 205 */ + { { 0x5e69544c,0x1583a171,0xf04b7813,0x0eaf8567,0x278a4c32,0x1e22a8fd, + 0x3d3a69a9,0xa9d3809d }, + { 0x59a2da3b,0x936c2c2c,0x1895c847,0x38ccbcf6,0x63d50869,0x5e65244e, + 0xe1178ef7,0x3006b9ae }, + 0 }, + /* 206 */ + { { 0xc9eead28,0x0bb1f2b0,0x89f4dfbc,0x7eef635d,0xb2ce8939,0x074757fd, + 0x45f8f761,0x0ab85fd7 }, + { 0x3e5b4549,0xecda7c93,0x97922f21,0x4be2bb5c,0xb43b8040,0x261a1274, + 0x11e942c2,0xb122d675 }, + 0 }, + /* 207 */ + { { 0x66a5ae7a,0x3be607be,0x76adcbe3,0x01e703fa,0x4eb6e5c5,0xaf904301, + 0x097dbaec,0x9f599dc1 }, + { 0x0ff250ed,0x6d75b718,0x349a20dc,0x8eb91574,0x10b227a3,0x425605a4, + 0x8a294b78,0x7d5528e0 }, + 0 }, + /* 208 */ + { { 0x20c26def,0xf0f58f66,0x582b2d1e,0x025585ea,0x01ce3881,0xfbe7d79b, + 0x303f1730,0x28ccea01 }, + { 0x79644ba5,0xd1dabcd1,0x06fff0b8,0x1fc643e8,0x66b3e17b,0xa60a76fc, + 0xa1d013bf,0xc18baf48 }, + 0 }, + /* 209 */ + { { 0x5dc4216d,0x34e638c8,0x206142ac,0x00c01067,0x95f5064a,0xd453a171, + 0xb7a9596b,0x9def809d }, + { 0x67ab8d2c,0x41e8642e,0x6237a2b6,0xb4240433,0x64c4218b,0x7d506a6d, + 0x68808ce5,0x0357f8b0 }, + 0 }, + /* 210 */ + { { 0x4cd2cc88,0x8e9dbe64,0xf0b8f39d,0xcc61c28d,0xcd30a0c8,0x4a309874, + 0x1b489887,0xe4a01add }, + { 0xf57cd8f9,0x2ed1eeac,0xbd594c48,0x1b767d3e,0x7bd2f787,0xa7295c71, + 0xce10cc30,0x466d7d79 }, + 0 }, + /* 211 */ + { { 0x9dada2c7,0x47d31892,0x8f9aa27d,0x4fa0a6c3,0x820a59e1,0x90e4fd28, + 0x451ead1a,0xc672a522 }, + { 0x5d86b655,0x30607cc8,0xf9ad4af1,0xf0235d3b,0x571172a6,0x99a08680, + 0xf2a67513,0x5e3d64fa }, + 0 }, + /* 212 */ + { { 0x9b3b4416,0xaa6410c7,0xeab26d99,0xcd8fcf85,0xdb656a74,0x5ebff74a, + 0xeb8e42fc,0x6c8a7a95 }, + { 0xb02a63bd,0x10c60ba7,0x8b8f0047,0x6b2f2303,0x312d90b0,0x8c6c3738, + 0xad82ca91,0x348ae422 }, + 0 }, + /* 213 */ + { { 0x5ccda2fb,0x7f474663,0x8e0726d2,0x22accaa1,0x492b1f20,0x85adf782, + 0xd9ef2d2e,0xc1074de0 }, + { 0xae9a65b3,0xfcf3ce44,0x05d7151b,0xfd71e4ac,0xce6a9788,0xd4711f50, + 0xc9e54ffc,0xfbadfbdb }, + 0 }, + /* 214 */ + { { 0x20a99363,0x1713f1cd,0x6cf22775,0xb915658f,0x24d359b2,0x968175cd, + 0x83716fcd,0xb7f976b4 }, + { 0x5d6dbf74,0x5758e24d,0x71c3af36,0x8d23bafd,0x0243dfe3,0x48f47760, + 0xcafcc805,0xf4d41b2e }, + 0 }, + /* 215 */ + { { 0xfdabd48d,0x51f1cf28,0x32c078a4,0xce81be36,0x117146e9,0x6ace2974, + 0xe0160f10,0x180824ea }, + { 0x66e58358,0x0387698b,0xce6ca358,0x63568752,0x5e41e6c5,0x82380e34, + 0x83cf6d25,0x67e5f639 }, + 0 }, + /* 216 */ + { { 0xcf4899ef,0xf89ccb8d,0x9ebb44c0,0x949015f0,0xb2598ec9,0x546f9276, + 0x04c11fc6,0x9fef789a }, + { 0x53d2a071,0x6d367ecf,0xa4519b09,0xb10e1a7f,0x611e2eef,0xca6b3fb0, + 0xa99c4e20,0xbc80c181 }, + 0 }, + /* 217 */ + { { 0xe5eb82e6,0x972536f8,0xf56cb920,0x1a484fc7,0x50b5da5e,0xc78e2171, + 0x9f8cdf10,0x49270e62 }, + { 0xea6b50ad,0x1a39b7bb,0xa2388ffc,0x9a0284c1,0x8107197b,0x5403eb17, + 0x61372f7f,0xd2ee52f9 }, + 0 }, + /* 218 */ + { { 0x88e0362a,0xd37cd285,0x8fa5d94d,0x442fa8a7,0xa434a526,0xaff836e5, + 0xe5abb733,0xdfb478be }, + { 0x673eede6,0xa91f1ce7,0x2b5b2f04,0xa5390ad4,0x5530da2f,0x5e66f7bf, + 0x08df473a,0xd9a140b4 }, + 0 }, + /* 219 */ + { { 0x6e8ea498,0x0e0221b5,0x3563ee09,0x62347829,0x335d2ade,0xe06b8391, + 0x623f4b1a,0x760c058d }, + { 0xc198aa79,0x0b89b58c,0xf07aba7f,0xf74890d2,0xfde2556a,0x4e204110, + 0x8f190409,0x7141982d }, + 0 }, + /* 220 */ + { { 0x4d4b0f45,0x6f0a0e33,0x392a94e1,0xd9280b38,0xb3c61d5e,0x3af324c6, + 0x89d54e47,0x3af9d1ce }, + { 0x20930371,0xfd8f7981,0x21c17097,0xeda2664c,0xdc42309b,0x0e9545dc, + 0x73957dd6,0xb1f815c3 }, + 0 }, + /* 221 */ + { { 0x89fec44a,0x84faa78e,0x3caa4caf,0xc8c2ae47,0xc1b6a624,0x691c807d, + 0x1543f052,0xa41aed14 }, + { 0x7d5ffe04,0x42435399,0x625b6e20,0x8bacb2df,0x87817775,0x85d660be, + 0x86fb60ef,0xd6e9c1dd }, + 0 }, + /* 222 */ + { { 0xc6853264,0x3aa2e97e,0xe2304a0b,0x771533b7,0xb8eae9be,0x1b912bb7, + 0xae9bf8c2,0x9c9c6e10 }, + { 0xe030b74c,0xa2309a59,0x6a631e90,0x4ed7494d,0xa49b79f2,0x89f44b23, + 0x40fa61b6,0x566bd596 }, + 0 }, + /* 223 */ + { { 0xc18061f3,0x066c0118,0x7c83fc70,0x190b25d3,0x27273245,0xf05fc8e0, + 0xf525345e,0xcf2c7390 }, + { 0x10eb30cf,0xa09bceb4,0x0d77703a,0xcfd2ebba,0x150ff255,0xe842c43a, + 0x8aa20979,0x02f51755 }, + 0 }, + /* 224 */ + { { 0xaddb7d07,0x396ef794,0x24455500,0x0b4fc742,0xc78aa3ce,0xfaff8eac, + 0xe8d4d97d,0x14e9ada5 }, + { 0x2f7079e2,0xdaa480a1,0xe4b0800e,0x45baa3cd,0x7838157d,0x01765e2d, + 0x8e9d9ae8,0xa0ad4fab }, + 0 }, + /* 225 */ + { { 0x4a653618,0x0bfb7621,0x31eaaa5f,0x1872813c,0x44949d5e,0x1553e737, + 0x6e56ed1e,0xbcd530b8 }, + { 0x32e9c47b,0x169be853,0xb50059ab,0xdc2776fe,0x192bfbb4,0xcdba9761, + 0x6979341d,0x909283cf }, + 0 }, + /* 226 */ + { { 0x76e81a13,0x67b00324,0x62171239,0x9bee1a99,0xd32e19d6,0x08ed361b, + 0xace1549a,0x35eeb7c9 }, + { 0x7e4e5bdc,0x1280ae5a,0xb6ceec6e,0x2dcd2cd3,0x6e266bc1,0x52e4224c, + 0x448ae864,0x9a8b2cf4 }, + 0 }, + /* 227 */ + { { 0x09d03b59,0xf6471bf2,0xb65af2ab,0xc90e62a3,0xebd5eec9,0xff7ff168, + 0xd4491379,0x6bdb60f4 }, + { 0x8a55bc30,0xdadafebc,0x10097fe0,0xc79ead16,0x4c1e3bdd,0x42e19741, + 0x94ba08a9,0x01ec3cfd }, + 0 }, + /* 228 */ + { { 0xdc9485c2,0xba6277eb,0x22fb10c7,0x48cc9a79,0x70a28d8a,0x4f61d60f, + 0x475464f6,0xd1acb1c0 }, + { 0x26f36612,0xd26902b1,0xe0618d8b,0x59c3a44e,0x308357ee,0x4df8a813, + 0x405626c2,0x7dcd079d }, + 0 }, + /* 229 */ + { { 0xf05a4b48,0x5ce7d4d3,0x37230772,0xadcd2952,0x812a915a,0xd18f7971, + 0x377d19b8,0x0bf53589 }, + { 0x6c68ea73,0x35ecd95a,0x823a584d,0xc7f3bbca,0xf473a723,0x9fb674c6, + 0xe16686fc,0xd28be4d9 }, + 0 }, + /* 230 */ + { { 0x38fa8e4b,0x5d2b9906,0x893fd8fc,0x559f186e,0x436fb6fc,0x3a6de2aa, + 0x510f88ce,0xd76007aa }, + { 0x523a4988,0x2d10aab6,0x74dd0273,0xb455cf44,0xa3407278,0x7f467082, + 0xb303bb01,0xf2b52f68 }, + 0 }, + /* 231 */ + { { 0x9835b4ca,0x0d57eafa,0xbb669cbc,0x2d2232fc,0xc6643198,0x8eeeb680, + 0xcc5aed3a,0xd8dbe98e }, + { 0xc5a02709,0xcba9be3f,0xf5ba1fa8,0x30be68e5,0xf10ea852,0xfebd43cd, + 0xee559705,0xe01593a3 }, + 0 }, + /* 232 */ + { { 0xea75a0a6,0xd3e5af50,0x57858033,0x512226ac,0xd0176406,0x6fe6d50f, + 0xaeb8ef06,0xafec07b1 }, + { 0x80bb0a31,0x7fb99567,0x37309aae,0x6f1af3cc,0x01abf389,0x9153a15a, + 0x6e2dbfdd,0xa71b9354 }, + 0 }, + /* 233 */ + { { 0x18f593d2,0xbf8e12e0,0xa078122b,0xd1a90428,0x0ba4f2ad,0x150505db, + 0x628523d9,0x53a2005c }, + { 0xe7f2b935,0x07c8b639,0xc182961a,0x2bff975a,0x7518ca2c,0x86bceea7, + 0x3d588e3d,0xbf47d19b }, + 0 }, + /* 234 */ + { { 0xdd7665d5,0x672967a7,0x2f2f4de5,0x4e303057,0x80d4903f,0x144005ae, + 0x39c9a1b6,0x001c2c7f }, + { 0x69efc6d6,0x143a8014,0x7bc7a724,0xc810bdaa,0xa78150a4,0x5f65670b, + 0x86ffb99b,0xfdadf8e7 }, + 0 }, + /* 235 */ + { { 0xffc00785,0xfd38cb88,0x3b48eb67,0x77fa7591,0xbf368fbc,0x0454d055, + 0x5aa43c94,0x3a838e4d }, + { 0x3e97bb9a,0x56166329,0x441d94d9,0x9eb93363,0x0adb2a83,0x515591a6, + 0x873e1da3,0x3cdb8257 }, + 0 }, + /* 236 */ + { { 0x7de77eab,0x137140a9,0x41648109,0xf7e1c50d,0xceb1d0df,0x762dcad2, + 0xf1f57fba,0x5a60cc89 }, + { 0x40d45673,0x80b36382,0x5913c655,0x1b82be19,0xdd64b741,0x057284b8, + 0xdbfd8fc0,0x922ff56f }, + 0 }, + /* 237 */ + { { 0xc9a129a1,0x1b265dee,0xcc284e04,0xa5b1ce57,0xcebfbe3c,0x04380c46, + 0xf6c5cd62,0x72919a7d }, + { 0x8fb90f9a,0x298f453a,0x88e4031b,0xd719c00b,0x796f1856,0xe32c0e77, + 0x3624089a,0x5e791780 }, + 0 }, + /* 238 */ + { { 0x7f63cdfb,0x5c16ec55,0xf1cae4fd,0x8e6a3571,0x560597ca,0xfce26bea, + 0xe24c2fab,0x4e0a5371 }, + { 0xa5765357,0x276a40d3,0x0d73a2b4,0x3c89af44,0x41d11a32,0xb8f370ae, + 0xd56604ee,0xf5ff7818 }, + 0 }, + /* 239 */ + { { 0x1a09df21,0xfbf3e3fe,0xe66e8e47,0x26d5d28e,0x29c89015,0x2096bd0a, + 0x533f5e64,0xe41df0e9 }, + { 0xb3ba9e3f,0x305fda40,0x2604d895,0xf2340ceb,0x7f0367c7,0x0866e192, + 0xac4f155f,0x8edd7d6e }, + 0 }, + /* 240 */ + { { 0x0bfc8ff3,0xc9a1dc0e,0xe936f42f,0x14efd82b,0xcca381ef,0x67016f7c, + 0xed8aee96,0x1432c1ca }, + { 0x70b23c26,0xec684829,0x0735b273,0xa64fe873,0xeaef0f5a,0xe389f6e5, + 0x5ac8d2c6,0xcaef480b }, + 0 }, + /* 241 */ + { { 0x75315922,0x5245c978,0x3063cca5,0xd8295171,0xb64ef2cb,0xf3ce60d0, + 0x8efae236,0xd0ba177e }, + { 0xb1b3af60,0x53a9ae8f,0x3d2da20e,0x1a796ae5,0xdf9eef28,0x01d63605, + 0x1c54ae16,0xf31c957c }, + 0 }, + /* 242 */ + { { 0x49cc4597,0xc0f58d52,0xbae0a028,0xdc5015b0,0x734a814a,0xefc5fc55, + 0x96e17c3a,0x013404cb }, + { 0xc9a824bf,0xb29e2585,0x001eaed7,0xd593185e,0x61ef68ac,0x8d6ee682, + 0x91933e6c,0x6f377c4b }, + 0 }, + /* 243 */ + { { 0xa8333fd2,0x9f93bad1,0x5a2a95b8,0xa8930202,0xeaf75ace,0x211e5037, + 0xd2d09506,0x6dba3e4e }, + { 0xd04399cd,0xa48ef98c,0xe6b73ade,0x1811c66e,0xc17ecaf3,0x72f60752, + 0x3becf4a7,0xf13cf342 }, + 0 }, + /* 244 */ + { { 0xa919e2eb,0xceeb9ec0,0xf62c0f68,0x83a9a195,0x7aba2299,0xcfba3bb6, + 0x274bbad3,0xc83fa9a9 }, + { 0x62fa1ce0,0x0d7d1b0b,0x3418efbf,0xe58b60f5,0x52706f04,0xbfa8ef9e, + 0x5d702683,0xb49d70f4 }, + 0 }, + /* 245 */ + { { 0xfad5513b,0x914c7510,0xb1751e2d,0x05f32eec,0xd9fb9d59,0x6d850418, + 0x0c30f1cf,0x59cfadbb }, + { 0x55cb7fd6,0xe167ac23,0x820426a3,0x249367b8,0x90a78864,0xeaeec58c, + 0x354a4b67,0x5babf362 }, + 0 }, + /* 246 */ + { { 0xee424865,0x37c981d1,0xf2e5577f,0x8b002878,0xb9e0c058,0x702970f1, + 0x9026c8f0,0x6188c6a7 }, + { 0xd0f244da,0x06f9a19b,0xfb080873,0x1ecced5c,0x9f213637,0x35470f9b, + 0xdf50b9d9,0x993fe475 }, + 0 }, + /* 247 */ + { { 0x9b2c3609,0x68e31cdf,0x2c46d4ea,0x84eb19c0,0x9a775101,0x7ac9ec1a, + 0x4c80616b,0x81f76466 }, + { 0x75fbe978,0x1d7c2a5a,0xf183b356,0x6743fed3,0x501dd2bf,0x838d1f04, + 0x5fe9060d,0x564a812a }, + 0 }, + /* 248 */ + { { 0xfa817d1d,0x7a5a64f4,0xbea82e0f,0x55f96844,0xcd57f9aa,0xb5ff5a0f, + 0x00e51d6c,0x226bf3cf }, + { 0x2f2833cf,0xd6d1a9f9,0x4f4f89a8,0x20a0a35a,0x8f3f7f77,0x11536c49, + 0xff257836,0x68779f47 }, + 0 }, + /* 249 */ + { { 0x73043d08,0x79b0c1c1,0x1fc020fa,0xa5446774,0x9a6d26d0,0xd3767e28, + 0xeb092e0b,0x97bcb0d1 }, + { 0xf32ed3c3,0x2ab6eaa8,0xb281bc48,0xc8a4f151,0xbfa178f3,0x4d1bf4f3, + 0x0a784655,0xa872ffe8 }, + 0 }, + /* 250 */ + { { 0xa32b2086,0xb1ab7935,0x8160f486,0xe1eb710e,0x3b6ae6be,0x9bd0cd91, + 0xb732a36a,0x02812bfc }, + { 0xcf605318,0xa63fd7ca,0xfdfd6d1d,0x646e5d50,0x2102d619,0xa1d68398, + 0xfe5396af,0x07391cc9 }, + 0 }, + /* 251 */ + { { 0x8b80d02b,0xc50157f0,0x62877f7f,0x6b8333d1,0x78d542ae,0x7aca1af8, + 0x7e6d2a08,0x355d2adc }, + { 0x287386e1,0xb41f335a,0xf8e43275,0xfd272a94,0xe79989ea,0x286ca2cd, + 0x7c2a3a79,0x3dc2b1e3 }, + 0 }, + /* 252 */ + { { 0x04581352,0xd689d21c,0x376782be,0x0a00c825,0x9fed701f,0x203bd590, + 0x3ccd846b,0xc4786910 }, + { 0x24c768ed,0x5dba7708,0x6841f657,0x72feea02,0x6accce0e,0x73313ed5, + 0xd5bb4d32,0xccc42968 }, + 0 }, + /* 253 */ + { { 0x3d7620b9,0x94e50de1,0x5992a56a,0xd89a5c8a,0x675487c9,0xdc007640, + 0xaa4871cf,0xe147eb42 }, + { 0xacf3ae46,0x274ab4ee,0x50350fbe,0xfd4936fb,0x48c840ea,0xdf2afe47, + 0x080e96e3,0x239ac047 }, + 0 }, + /* 254 */ + { { 0x2bfee8d4,0x481d1f35,0xfa7b0fec,0xce80b5cf,0x2ce9af3c,0x105c4c9e, + 0xf5f7e59d,0xc55fa1a3 }, + { 0x8257c227,0x3186f14e,0x342be00b,0xc5b1653f,0xaa904fb2,0x09afc998, + 0xd4f4b699,0x094cd99c }, + 0 }, + /* 255 */ + { { 0xd703beba,0x8a981c84,0x32ceb291,0x8631d150,0xe3bd49ec,0xa445f2c9, + 0x42abad33,0xb90a30b6 }, + { 0xb4a5abf9,0xb465404f,0x75db7603,0x004750c3,0xca35d89f,0x6f9a42cc, + 0x1b7924f7,0x019f8b9a }, + 0 }, +}; + +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_base_8(sp_point* r, sp_digit* k, + int map, void* heap) +{ + return sp_256_ecc_mulmod_stripe_8(r, &p256_base, p256_table, + k, map, heap); +} + +#endif + +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * km Scalar to multiply by. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_base_256(mp_int* km, ecc_point* r, int map, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point p; + sp_digit kd[8]; +#endif + sp_point* point; + sp_digit* k = NULL; + int err = MP_OKAY; + + err = sp_ecc_point_new(heap, p, point); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + if (err == MP_OKAY) { + sp_256_from_mp(k, 8, km); + + err = sp_256_ecc_mulmod_base_8(point, k, map, heap); + } + if (err == MP_OKAY) + err = sp_256_point_to_ecc_point_8(point, r); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(point, 0, heap); + + return err; +} + +#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ + defined(HAVE_ECC_VERIFY) +/* Returns 1 if the number of zero. + * Implementation is constant time. + * + * a Number to check. + * returns 1 if the number is zero and 0 otherwise. + */ +static int sp_256_iszero_8(const sp_digit* a) +{ + return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6] | a[7]) == 0; +} + +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN || HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +/* Add 1 to a. (a = a + 1) + * + * a A single precision integer. + */ +SP_NOINLINE static void sp_256_add_one_8(sp_digit* a) +{ + __asm__ __volatile__ ( + "mov r2, #1\n\t" + "ldr r1, [%[a], #0]\n\t" + "add r1, r2\n\t" + "mov r2, #0\n\t" + "str r1, [%[a], #0]\n\t" + "ldr r1, [%[a], #4]\n\t" + "adc r1, r2\n\t" + "str r1, [%[a], #4]\n\t" + "ldr r1, [%[a], #8]\n\t" + "adc r1, r2\n\t" + "str r1, [%[a], #8]\n\t" + "ldr r1, [%[a], #12]\n\t" + "adc r1, r2\n\t" + "str r1, [%[a], #12]\n\t" + "ldr r1, [%[a], #16]\n\t" + "adc r1, r2\n\t" + "str r1, [%[a], #16]\n\t" + "ldr r1, [%[a], #20]\n\t" + "adc r1, r2\n\t" + "str r1, [%[a], #20]\n\t" + "ldr r1, [%[a], #24]\n\t" + "adc r1, r2\n\t" + "str r1, [%[a], #24]\n\t" + "ldr r1, [%[a], #28]\n\t" + "adc r1, r2\n\t" + "str r1, [%[a], #28]\n\t" + : + : [a] "r" (a) + : "memory", "r1", "r2" + ); +} + +/* Read big endian unsigned byte aray into r. + * + * r A single precision integer. + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_256_from_bin(sp_digit* r, int max, const byte* a, int n) +{ + int i, j = 0, s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= ((sp_digit)a[i]) << s; + if (s >= 24) { + r[j] &= 0xffffffff; + s = 32 - s; + if (j + 1 >= max) + break; + r[++j] = a[i] >> s; + s = 8 - s; + } + else + s += 8; + } + + for (j++; j < max; j++) + r[j] = 0; +} + +/* Generates a scalar that is in the range 1..order-1. + * + * rng Random number generator. + * k Scalar value. + * returns RNG failures, MEMORY_E when memory allocation fails and + * MP_OKAY on success. + */ +static int sp_256_ecc_gen_k_8(WC_RNG* rng, sp_digit* k) +{ + int err; + byte buf[32]; + + do { + err = wc_RNG_GenerateBlock(rng, buf, sizeof(buf)); + if (err == 0) { + sp_256_from_bin(k, 8, buf, sizeof(buf)); + if (sp_256_cmp_8(k, p256_order2) < 0) { + sp_256_add_one_8(k); + break; + } + } + } + while (err == 0); + + return err; +} + +/* Makes a random EC key pair. + * + * rng Random number generator. + * priv Generated private value. + * pub Generated public point. + * heap Heap to use for allocation. + * returns ECC_INF_E when the point does not have the correct order, RNG + * failures, MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point p; + sp_digit kd[8]; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point inf; +#endif +#endif + sp_point* point; + sp_digit* k = NULL; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point* infinity; +#endif + int err; + + (void)heap; + + err = sp_ecc_point_new(heap, p, point); +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, inf, infinity); +#endif +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + + if (err == MP_OKAY) + err = sp_256_ecc_gen_k_8(rng, k); + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_base_8(point, k, 1, NULL); + } + +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_8(infinity, point, p256_order, 1, NULL); + } + if (err == MP_OKAY) { + if (!sp_256_iszero_8(point->x) || !sp_256_iszero_8(point->y)) + err = ECC_INF_E; + } +#endif + + if (err == MP_OKAY) + err = sp_256_to_mp(k, priv); + if (err == MP_OKAY) + err = sp_256_point_to_ecc_point_8(point, pub); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); +#endif +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_ecc_point_free(infinity, 1, heap); +#endif + sp_ecc_point_free(point, 1, heap); + + return err; +} + +#ifdef HAVE_ECC_DHE +/* Write r as big endian to byte aray. + * Fixed length number of bytes written: 32 + * + * r A single precision integer. + * a Byte array. + */ +static void sp_256_to_bin(sp_digit* r, byte* a) +{ + int i, j, s = 0, b; + + j = 256 / 8 - 1; + a[j] = 0; + for (i=0; i<8 && j>=0; i++) { + b = 0; + a[j--] |= r[i] << s; b += 8 - s; + if (j < 0) + break; + while (b < 32) { + a[j--] = r[i] >> b; b += 8; + if (j < 0) + break; + } + s = 8 - (b - 32); + if (j >= 0) + a[j] = 0; + if (s != 0) + j++; + } +} + +/* Multiply the point by the scalar and serialize the X ordinate. + * The number is 0 padded to maximum size on output. + * + * priv Scalar to multiply the point by. + * pub Point to multiply. + * out Buffer to hold X ordinate. + * outLen On entry, size of the buffer in bytes. + * On exit, length of data in buffer in bytes. + * heap Heap to use for allocation. + * returns BUFFER_E if the buffer is to small for output size, + * MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_secret_gen_256(mp_int* priv, ecc_point* pub, byte* out, + word32* outLen, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point p; + sp_digit kd[8]; +#endif + sp_point* point = NULL; + sp_digit* k = NULL; + int err = MP_OKAY; + + if (*outLen < 32) + err = BUFFER_E; + + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, p, point); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(k, 8, priv); + sp_256_point_from_ecc_point_8(point, pub); + err = sp_256_ecc_mulmod_8(point, point, k, 1, heap); + } + if (err == MP_OKAY) { + sp_256_to_bin(point->x, out); + *outLen = 32; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(point, 0, heap); + + return err; +} +#endif /* HAVE_ECC_DHE */ + +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into a. (a -= b) + * + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_256_sub_in_place_8(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + __asm__ __volatile__ ( + "mov r7, %[a]\n\t" + "add r7, #32\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "sub r5, %[c]\n\t" + "ldr r3, [%[a]]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b]]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a]]\n\t" + "str r4, [%[a], #4]\n\t" + "sbc %[c], %[c]\n\t" + "add %[a], #8\n\t" + "add %[b], #8\n\t" + "cmp %[a], r7\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6", "r7" + ); + + return c; +} + +#else +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_256_sub_in_place_8(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sub r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #0]\n\t" + "str r4, [%[a], #4]\n\t" + "ldr r3, [%[a], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r6, [%[b], #12]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #8]\n\t" + "str r4, [%[a], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r6, [%[b], #20]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #16]\n\t" + "str r4, [%[a], #20]\n\t" + "ldr r3, [%[a], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r6, [%[b], #28]\n\t" + "sbc r3, r5\n\t" + "sbc r4, r6\n\t" + "str r3, [%[a], #24]\n\t" + "str r4, [%[a], #28]\n\t" + "sbc %[c], %[c]\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Mul a by digit b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision digit. + */ +SP_NOINLINE static void sp_256_mul_d_8(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ + __asm__ __volatile__ ( + "mov r6, #32\n\t" + "add r6, %[a]\n\t" + "mov r8, %[r]\n\t" + "mov r9, r6\n\t" + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "1:\n\t" + "mov %[r], #0\n\t" + "mov r5, #0\n\t" + "# A[] * B\n\t" + "ldr r6, [%[a]]\n\t" + "lsl r6, r6, #16\n\t" + "lsl r7, %[b], #16\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r7, r6\n\t" + "add r3, r7\n\t" + "adc r4, %[r]\n\t" + "adc r5, %[r]\n\t" + "lsr r7, %[b], #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "ldr r6, [%[a]]\n\t" + "lsr r6, r6, #16\n\t" + "lsr r7, %[b], #16\n\t" + "mul r7, r6\n\t" + "add r4, r7\n\t" + "adc r5, %[r]\n\t" + "lsl r7, %[b], #16\n\t" + "lsr r7, r7, #16\n\t" + "mul r6, r7\n\t" + "lsr r7, r6, #16\n\t" + "lsl r6, r6, #16\n\t" + "add r3, r6\n\t" + "adc r4, r7\n\t" + "adc r5, %[r]\n\t" + "# A[] * B - Done\n\t" + "mov %[r], r8\n\t" + "str r3, [%[r]]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "add %[r], #4\n\t" + "add %[a], #4\n\t" + "mov r8, %[r]\n\t" + "cmp %[a], r9\n\t" + "blt 1b\n\t" + "str r3, [%[r]]\n\t" + : [r] "+r" (r), [a] "+r" (a) + : [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9" + ); +} + +/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) + * + * d1 The high order half of the number to divide. + * d0 The low order half of the number to divide. + * div The dividend. + * returns the result of the division. + * + * Note that this is an approximate div. It may give an answer 1 larger. + */ +SP_NOINLINE static sp_digit div_256_word_8(sp_digit d1, sp_digit d0, + sp_digit div) +{ + sp_digit r = 0; + + __asm__ __volatile__ ( + "lsr r5, %[div], #1\n\t" + "add r5, #1\n\t" + "mov r8, %[d0]\n\t" + "mov r9, %[d1]\n\t" + "# Do top 32\n\t" + "mov r6, r5\n\t" + "sub r6, %[d1]\n\t" + "sbc r6, r6\n\t" + "add %[r], %[r]\n\t" + "sub %[r], r6\n\t" + "and r6, r5\n\t" + "sub %[d1], r6\n\t" + "# Next 30 bits\n\t" + "mov r4, #29\n\t" + "1:\n\t" + "lsl %[d0], %[d0], #1\n\t" + "adc %[d1], %[d1]\n\t" + "mov r6, r5\n\t" + "sub r6, %[d1]\n\t" + "sbc r6, r6\n\t" + "add %[r], %[r]\n\t" + "sub %[r], r6\n\t" + "and r6, r5\n\t" + "sub %[d1], r6\n\t" + "sub r4, #1\n\t" + "bpl 1b\n\t" + "mov r7, #0\n\t" + "add %[r], %[r]\n\t" + "add %[r], #1\n\t" + "# r * div - Start\n\t" + "lsl %[d1], %[r], #16\n\t" + "lsl r4, %[div], #16\n\t" + "lsr %[d1], %[d1], #16\n\t" + "lsr r4, r4, #16\n\t" + "mul r4, %[d1]\n\t" + "lsr r6, %[div], #16\n\t" + "mul %[d1], r6\n\t" + "lsr r5, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r7\n\t" + "lsr %[d1], %[r], #16\n\t" + "mul r6, %[d1]\n\t" + "add r5, r6\n\t" + "lsl r6, %[div], #16\n\t" + "lsr r6, r6, #16\n\t" + "mul %[d1], r6\n\t" + "lsr r6, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r6\n\t" + "# r * div - Done\n\t" + "mov %[d1], r8\n\t" + "sub %[d1], r4\n\t" + "mov r4, %[d1]\n\t" + "mov %[d1], r9\n\t" + "sbc %[d1], r5\n\t" + "mov r5, %[d1]\n\t" + "add %[r], r5\n\t" + "# r * div - Start\n\t" + "lsl %[d1], %[r], #16\n\t" + "lsl r4, %[div], #16\n\t" + "lsr %[d1], %[d1], #16\n\t" + "lsr r4, r4, #16\n\t" + "mul r4, %[d1]\n\t" + "lsr r6, %[div], #16\n\t" + "mul %[d1], r6\n\t" + "lsr r5, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r7\n\t" + "lsr %[d1], %[r], #16\n\t" + "mul r6, %[d1]\n\t" + "add r5, r6\n\t" + "lsl r6, %[div], #16\n\t" + "lsr r6, r6, #16\n\t" + "mul %[d1], r6\n\t" + "lsr r6, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r6\n\t" + "# r * div - Done\n\t" + "mov %[d1], r8\n\t" + "mov r6, r9\n\t" + "sub r4, %[d1], r4\n\t" + "sbc r6, r5\n\t" + "mov r5, r6\n\t" + "add %[r], r5\n\t" + "# r * div - Start\n\t" + "lsl %[d1], %[r], #16\n\t" + "lsl r4, %[div], #16\n\t" + "lsr %[d1], %[d1], #16\n\t" + "lsr r4, r4, #16\n\t" + "mul r4, %[d1]\n\t" + "lsr r6, %[div], #16\n\t" + "mul %[d1], r6\n\t" + "lsr r5, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r7\n\t" + "lsr %[d1], %[r], #16\n\t" + "mul r6, %[d1]\n\t" + "add r5, r6\n\t" + "lsl r6, %[div], #16\n\t" + "lsr r6, r6, #16\n\t" + "mul %[d1], r6\n\t" + "lsr r6, %[d1], #16\n\t" + "lsl %[d1], %[d1], #16\n\t" + "add r4, %[d1]\n\t" + "adc r5, r6\n\t" + "# r * div - Done\n\t" + "mov %[d1], r8\n\t" + "mov r6, r9\n\t" + "sub r4, %[d1], r4\n\t" + "sbc r6, r5\n\t" + "mov r5, r6\n\t" + "add %[r], r5\n\t" + "mov r6, %[div]\n\t" + "sub r6, r4\n\t" + "sbc r6, r6\n\t" + "sub %[r], r6\n\t" + : [r] "+r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "r4", "r5", "r7", "r6", "r8", "r9" + ); + return r; +} + +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_256_mask_8(sp_digit* r, sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<8; i++) + r[i] = a[i] & m; +#else + r[0] = a[0] & m; + r[1] = a[1] & m; + r[2] = a[2] & m; + r[3] = a[3] & m; + r[4] = a[4] & m; + r[5] = a[5] & m; + r[6] = a[6] & m; + r[7] = a[7] & m; +#endif +} + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_256_div_8(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[16], t2[9]; + sp_digit div, r1; + int i; + + (void)m; + + div = d[7]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 8); + for (i=7; i>=0; i--) { + r1 = div_256_word_8(t1[8 + i], t1[8 + i - 1], div); + + sp_256_mul_d_8(t2, d, r1); + t1[8 + i] += sp_256_sub_in_place_8(&t1[i], t2); + t1[8 + i] -= t2[8]; + sp_256_mask_8(t2, d, t1[8 + i]); + t1[8 + i] += sp_256_add_8(&t1[i], &t1[i], t2); + sp_256_mask_8(t2, d, t1[8 + i]); + t1[8 + i] += sp_256_add_8(&t1[i], &t1[i], t2); + } + + r1 = sp_256_cmp_8(t1, d) >= 0; + sp_256_cond_sub_8(r, t1, d, (sp_digit)0 - r1); + + return MP_OKAY; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_256_mod_8(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_256_div_8(a, m, NULL, r); +} + +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +#ifdef WOLFSSL_SP_SMALL +/* Order-2 for the P256 curve. */ +static const uint32_t p256_order_2[8] = { + 0xfc63254f,0xf3b9cac2,0xa7179e84,0xbce6faad,0xffffffff,0xffffffff, + 0x00000000,0xffffffff +}; +#else +/* The low half of the order-2 of the P256 curve. */ +static const uint32_t p256_order_low[4] = { + 0xfc63254f,0xf3b9cac2,0xa7179e84,0xbce6faad +}; +#endif /* WOLFSSL_SP_SMALL */ + +/* Multiply two number mod the order of P256 curve. (r = a * b mod order) + * + * r Result of the multiplication. + * a First operand of the multiplication. + * b Second operand of the multiplication. + */ +static void sp_256_mont_mul_order_8(sp_digit* r, sp_digit* a, sp_digit* b) +{ + sp_256_mul_8(r, a, b); + sp_256_mont_reduce_order_8(r, p256_order, p256_mp_order); +} + +/* Square number mod the order of P256 curve. (r = a * a mod order) + * + * r Result of the squaring. + * a Number to square. + */ +static void sp_256_mont_sqr_order_8(sp_digit* r, sp_digit* a) +{ + sp_256_sqr_8(r, a); + sp_256_mont_reduce_order_8(r, p256_order, p256_mp_order); +} + +#ifndef WOLFSSL_SP_SMALL +/* Square number mod the order of P256 curve a number of times. + * (r = a ^ n mod order) + * + * r Result of the squaring. + * a Number to square. + */ +static void sp_256_mont_sqr_n_order_8(sp_digit* r, sp_digit* a, int n) +{ + int i; + + sp_256_mont_sqr_order_8(r, a); + for (i=1; i=0; i--) { + sp_256_mont_sqr_order_8(t, t); + if (p256_order_2[i / 32] & ((sp_digit)1 << (i % 32))) + sp_256_mont_mul_order_8(t, t, a); + } + XMEMCPY(r, t, sizeof(sp_digit) * 8); +#else + sp_digit* t = td; + sp_digit* t2 = td + 2 * 8; + sp_digit* t3 = td + 4 * 8; + int i; + + /* t = a^2 */ + sp_256_mont_sqr_order_8(t, a); + /* t = a^3 = t * a */ + sp_256_mont_mul_order_8(t, t, a); + /* t2= a^c = t ^ 2 ^ 2 */ + sp_256_mont_sqr_n_order_8(t2, t, 2); + /* t3= a^f = t2 * t */ + sp_256_mont_mul_order_8(t3, t2, t); + /* t2= a^f0 = t3 ^ 2 ^ 4 */ + sp_256_mont_sqr_n_order_8(t2, t3, 4); + /* t = a^ff = t2 * t3 */ + sp_256_mont_mul_order_8(t, t2, t3); + /* t3= a^ff00 = t ^ 2 ^ 8 */ + sp_256_mont_sqr_n_order_8(t2, t, 8); + /* t = a^ffff = t2 * t */ + sp_256_mont_mul_order_8(t, t2, t); + /* t2= a^ffff0000 = t ^ 2 ^ 16 */ + sp_256_mont_sqr_n_order_8(t2, t, 16); + /* t = a^ffffffff = t2 * t */ + sp_256_mont_mul_order_8(t, t2, t); + /* t2= a^ffffffff0000000000000000 = t ^ 2 ^ 64 */ + sp_256_mont_sqr_n_order_8(t2, t, 64); + /* t2= a^ffffffff00000000ffffffff = t2 * t */ + sp_256_mont_mul_order_8(t2, t2, t); + /* t2= a^ffffffff00000000ffffffff00000000 = t2 ^ 2 ^ 32 */ + sp_256_mont_sqr_n_order_8(t2, t2, 32); + /* t2= a^ffffffff00000000ffffffffffffffff = t2 * t */ + sp_256_mont_mul_order_8(t2, t2, t); + /* t2= a^ffffffff00000000ffffffffffffffffbce6 */ + for (i=127; i>=112; i--) { + sp_256_mont_sqr_order_8(t2, t2); + if (p256_order_low[i / 32] & ((sp_digit)1 << (i % 32))) + sp_256_mont_mul_order_8(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6f */ + sp_256_mont_sqr_n_order_8(t2, t2, 4); + sp_256_mont_mul_order_8(t2, t2, t3); + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84 */ + for (i=107; i>=64; i--) { + sp_256_mont_sqr_order_8(t2, t2); + if (p256_order_low[i / 32] & ((sp_digit)1 << (i % 32))) + sp_256_mont_mul_order_8(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f */ + sp_256_mont_sqr_n_order_8(t2, t2, 4); + sp_256_mont_mul_order_8(t2, t2, t3); + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2 */ + for (i=59; i>=32; i--) { + sp_256_mont_sqr_order_8(t2, t2); + if (p256_order_low[i / 32] & ((sp_digit)1 << (i % 32))) + sp_256_mont_mul_order_8(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2f */ + sp_256_mont_sqr_n_order_8(t2, t2, 4); + sp_256_mont_mul_order_8(t2, t2, t3); + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254 */ + for (i=27; i>=0; i--) { + sp_256_mont_sqr_order_8(t2, t2); + if (p256_order_low[i / 32] & ((sp_digit)1 << (i % 32))) + sp_256_mont_mul_order_8(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632540 */ + sp_256_mont_sqr_n_order_8(t2, t2, 4); + /* r = a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f */ + sp_256_mont_mul_order_8(r, t2, t3); +#endif /* WOLFSSL_SP_SMALL */ +} + +#endif /* HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +#ifdef HAVE_ECC_SIGN +#ifndef SP_ECC_MAX_SIG_GEN +#define SP_ECC_MAX_SIG_GEN 64 +#endif + +/* Sign the hash using the private key. + * e = [hash, 256 bits] from binary + * r = (k.G)->x mod order + * s = (r * x + e) / k mod order + * The hash is truncated to the first 256 bits. + * + * hash Hash to sign. + * hashLen Length of the hash data. + * rng Random number generator. + * priv Private part of key - scalar. + * rm First part of result as an mp_int. + * sm Sirst part of result as an mp_int. + * heap Heap to use for allocation. + * returns RNG failures, MEMORY_E when memory allocation fails and + * MP_OKAY on success. + */ +int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, + mp_int* rm, mp_int* sm, void* heap) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d = NULL; +#else + sp_digit ed[2*8]; + sp_digit xd[2*8]; + sp_digit kd[2*8]; + sp_digit rd[2*8]; + sp_digit td[3 * 2*8]; + sp_point p; +#endif + sp_digit* e = NULL; + sp_digit* x = NULL; + sp_digit* k = NULL; + sp_digit* r = NULL; + sp_digit* tmp = NULL; + sp_point* point = NULL; + sp_digit carry; + sp_digit* s; + sp_digit* kInv; + int err = MP_OKAY; + int32_t c; + int i; + + (void)heap; + + err = sp_ecc_point_new(heap, p, point); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 8, heap, + DYNAMIC_TYPE_ECC); + if (d != NULL) { + e = d + 0 * 8; + x = d + 2 * 8; + k = d + 4 * 8; + r = d + 6 * 8; + tmp = d + 8 * 8; + } + else + err = MEMORY_E; + } +#else + e = ed; + x = xd; + k = kd; + r = rd; + tmp = td; +#endif + s = e; + kInv = k; + + if (err == MP_OKAY) { + if (hashLen > 32) + hashLen = 32; + + sp_256_from_bin(e, 8, hash, hashLen); + } + + for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { + sp_256_from_mp(x, 8, priv); + + /* New random point. */ + err = sp_256_ecc_gen_k_8(rng, k); + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_base_8(point, k, 1, NULL); + } + + if (err == MP_OKAY) { + /* r = point->x mod order */ + XMEMCPY(r, point->x, sizeof(sp_digit) * 8); + sp_256_norm_8(r); + c = sp_256_cmp_8(r, p256_order); + sp_256_cond_sub_8(r, r, p256_order, 0 - (c >= 0)); + sp_256_norm_8(r); + + /* Conv k to Montgomery form (mod order) */ + sp_256_mul_8(k, k, p256_norm_order); + err = sp_256_mod_8(k, k, p256_order); + } + if (err == MP_OKAY) { + sp_256_norm_8(k); + /* kInv = 1/k mod order */ + sp_256_mont_inv_order_8(kInv, k, tmp); + sp_256_norm_8(kInv); + + /* s = r * x + e */ + sp_256_mul_8(x, x, r); + err = sp_256_mod_8(x, x, p256_order); + } + if (err == MP_OKAY) { + sp_256_norm_8(x); + carry = sp_256_add_8(s, e, x); + sp_256_cond_sub_8(s, s, p256_order, 0 - carry); + sp_256_norm_8(s); + c = sp_256_cmp_8(s, p256_order); + sp_256_cond_sub_8(s, s, p256_order, 0 - (c >= 0)); + sp_256_norm_8(s); + + /* s = s * k^-1 mod order */ + sp_256_mont_mul_order_8(s, s, kInv); + sp_256_norm_8(s); + + /* Check that signature is usable. */ + if (!sp_256_iszero_8(s)) + break; + } + } + + if (i == 0) + err = RNG_FAILURE_E; + + if (err == MP_OKAY) + err = sp_256_to_mp(r, rm); + if (err == MP_OKAY) + err = sp_256_to_mp(s, sm); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) { + XMEMSET(d, 0, sizeof(sp_digit) * 8 * 8); + XFREE(d, heap, DYNAMIC_TYPE_ECC); + } +#else + XMEMSET(e, 0, sizeof(sp_digit) * 2 * 8); + XMEMSET(x, 0, sizeof(sp_digit) * 2 * 8); + XMEMSET(k, 0, sizeof(sp_digit) * 2 * 8); + XMEMSET(r, 0, sizeof(sp_digit) * 2 * 8); + XMEMSET(r, 0, sizeof(sp_digit) * 2 * 8); + XMEMSET(tmp, 0, sizeof(sp_digit) * 3 * 2*8); +#endif + sp_ecc_point_free(point, 1, heap); + + return err; +} +#endif /* HAVE_ECC_SIGN */ + +#ifdef HAVE_ECC_VERIFY +/* Verify the signature values with the hash and public key. + * e = Truncate(hash, 256) + * u1 = e/s mod order + * u2 = r/s mod order + * r == (u1.G + u2.Q)->x mod order + * Optimization: Leave point in projective form. + * (x, y, 1) == (x' / z'*z', y' / z'*z'*z', z' / z') + * (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' + * The hash is truncated to the first 256 bits. + * + * hash Hash to sign. + * hashLen Length of the hash data. + * rng Random number generator. + * priv Private part of key - scalar. + * rm First part of result as an mp_int. + * sm Sirst part of result as an mp_int. + * heap Heap to use for allocation. + * returns RNG failures, MEMORY_E when memory allocation fails and + * MP_OKAY on success. + */ +int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, + mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d = NULL; +#else + sp_digit u1d[2*8]; + sp_digit u2d[2*8]; + sp_digit sd[2*8]; + sp_digit tmpd[2*8 * 5]; + sp_point p1d; + sp_point p2d; +#endif + sp_digit* u1; + sp_digit* u2; + sp_digit* s; + sp_digit* tmp; + sp_point* p1; + sp_point* p2 = NULL; + sp_digit carry; + int32_t c; + int err; + + err = sp_ecc_point_new(heap, p1d, p1); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, p2d, p2); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 8, heap, + DYNAMIC_TYPE_ECC); + if (d != NULL) { + u1 = d + 0 * 8; + u2 = d + 2 * 8; + s = d + 4 * 8; + tmp = d + 6 * 8; + } + else + err = MEMORY_E; + } +#else + u1 = u1d; + u2 = u2d; + s = sd; + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + if (hashLen > 32) + hashLen = 32; + + sp_256_from_bin(u1, 8, hash, hashLen); + sp_256_from_mp(u2, 8, r); + sp_256_from_mp(s, 8, sm); + sp_256_from_mp(p2->x, 8, pX); + sp_256_from_mp(p2->y, 8, pY); + sp_256_from_mp(p2->z, 8, pZ); + + sp_256_mul_8(s, s, p256_norm_order); + err = sp_256_mod_8(s, s, p256_order); + } + if (err == MP_OKAY) { + sp_256_norm_8(s); + { + sp_256_mont_inv_order_8(s, s, tmp); + sp_256_mont_mul_order_8(u1, u1, s); + sp_256_mont_mul_order_8(u2, u2, s); + } + + err = sp_256_ecc_mulmod_base_8(p1, u1, 0, heap); + } + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_8(p2, p2, u2, 0, heap); + } + + if (err == MP_OKAY) { + sp_256_proj_point_add_8(p1, p1, p2, tmp); + + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_256_from_mp(u2, 8, r); + err = sp_256_mod_mul_norm_8(u2, u2, p256_mod); + } + + if (err == MP_OKAY) { + /* u1 = r.z'.z' mod prime */ + sp_256_mont_sqr_8(p1->z, p1->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(u1, u2, p1->z, p256_mod, p256_mp_mod); + *res = sp_256_cmp_8(p1->x, u1) == 0; + if (*res == 0) { + /* Reload r and add order. */ + sp_256_from_mp(u2, 8, r); + carry = sp_256_add_8(u2, u2, p256_order); + /* Carry means result is greater than mod and is not valid. */ + if (!carry) { + sp_256_norm_8(u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_256_cmp_8(u2, p256_mod); + if (c < 0) { + /* Convert to Montogomery form */ + err = sp_256_mod_mul_norm_8(u2, u2, p256_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_256_mont_mul_8(u1, u2, p1->z, p256_mod, + p256_mp_mod); + *res = sp_256_cmp_8(p1->x, u2) == 0; + } + } + } + } + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p1, 0, heap); + sp_ecc_point_free(p2, 0, heap); + + return err; +} +#endif /* HAVE_ECC_VERIFY */ + +#ifdef HAVE_ECC_CHECK_KEY +/* Check that the x and y oridinates are a valid point on the curve. + * + * point EC point. + * heap Heap to use if dynamically allocating. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +static int sp_256_ecc_is_point_8(sp_point* point, void* heap) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d = NULL; +#else + sp_digit t1d[2*8]; + sp_digit t2d[2*8]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8 * 4, heap, + DYNAMIC_TYPE_ECC); + if (d != NULL) { + t1 = d + 0 * 8; + t2 = d + 2 * 8; + } + else + err = MEMORY_E; +#else + (void)heap; + + t1 = t1d; + t2 = t2d; +#endif + + if (err == MP_OKAY) { + sp_256_sqr_8(t1, point->y); + sp_256_mod_8(t1, t1, p256_mod); + sp_256_sqr_8(t2, point->x); + sp_256_mod_8(t2, t2, p256_mod); + sp_256_mul_8(t2, t2, point->x); + sp_256_mod_8(t2, t2, p256_mod); + sp_256_sub_8(t2, p256_mod, t2); + sp_256_mont_add_8(t1, t1, t2, p256_mod); + + sp_256_mont_add_8(t1, t1, point->x, p256_mod); + sp_256_mont_add_8(t1, t1, point->x, p256_mod); + sp_256_mont_add_8(t1, t1, point->x, p256_mod); + + if (sp_256_cmp_8(t1, p256_b) != 0) + err = MP_VAL; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Check that the x and y oridinates are a valid point on the curve. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +int sp_ecc_is_point_256(mp_int* pX, mp_int* pY) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point pubd; +#endif + sp_point* pub; + byte one[1] = { 1 }; + int err; + + err = sp_ecc_point_new(NULL, pubd, pub); + if (err == MP_OKAY) { + sp_256_from_mp(pub->x, 8, pX); + sp_256_from_mp(pub->y, 8, pY); + sp_256_from_bin(pub->z, 8, one, sizeof(one)); + + err = sp_256_ecc_is_point_8(pub, NULL); + } + + sp_ecc_point_free(pub, 0, NULL); + + return err; +} + +/* Check that the private scalar generates the EC point (px, py), the point is + * on the curve and the point has the correct order. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * privm Private scalar that generates EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve, ECC_INF_E if the point does not have the correct order, + * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and + * MP_OKAY otherwise. + */ +int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit privd[8]; + sp_point pubd; + sp_point pd; +#endif + sp_digit* priv = NULL; + sp_point* pub; + sp_point* p = NULL; + byte one[1] = { 1 }; + int err; + + err = sp_ecc_point_new(heap, pubd, pub); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap, + DYNAMIC_TYPE_ECC); + if (priv == NULL) + err = MEMORY_E; + } +#else + priv = privd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(pub->x, 8, pX); + sp_256_from_mp(pub->y, 8, pY); + sp_256_from_bin(pub->z, 8, one, sizeof(one)); + sp_256_from_mp(priv, 8, privm); + + /* Check point at infinitiy. */ + if (sp_256_iszero_8(pub->x) && + sp_256_iszero_8(pub->y)) + err = ECC_INF_E; + } + + if (err == MP_OKAY) { + /* Check range of X and Y */ + if (sp_256_cmp_8(pub->x, p256_mod) >= 0 || + sp_256_cmp_8(pub->y, p256_mod) >= 0) + err = ECC_OUT_OF_RANGE_E; + } + + if (err == MP_OKAY) { + /* Check point is on curve */ + err = sp_256_ecc_is_point_8(pub, heap); + } + + if (err == MP_OKAY) { + /* Point * order = infinity */ + err = sp_256_ecc_mulmod_8(p, pub, p256_order, 1, heap); + } + if (err == MP_OKAY) { + /* Check result is infinity */ + if (!sp_256_iszero_8(p->x) || + !sp_256_iszero_8(p->y)) { + err = ECC_INF_E; + } + } + + if (err == MP_OKAY) { + /* Base * private = point */ + err = sp_256_ecc_mulmod_base_8(p, priv, 1, heap); + } + if (err == MP_OKAY) { + /* Check result is public key */ + if (sp_256_cmp_8(p->x, pub->x) != 0 || + sp_256_cmp_8(p->y, pub->y) != 0) { + err = ECC_PRIV_KEY_E; + } + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (priv != NULL) + XFREE(priv, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p, 0, heap); + sp_ecc_point_free(pub, 0, heap); + + return err; +} +#endif +#ifdef WOLFSSL_PUBLIC_ECC_ADD_DBL +/* Add two projective EC points together. + * (pX, pY, pZ) + (qX, qY, qZ) = (rX, rY, rZ) + * + * pX First EC point's X ordinate. + * pY First EC point's Y ordinate. + * pZ First EC point's Z ordinate. + * qX Second EC point's X ordinate. + * qY Second EC point's Y ordinate. + * qZ Second EC point's Z ordinate. + * rX Resultant EC point's X ordinate. + * rY Resultant EC point's Y ordinate. + * rZ Resultant EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* qX, mp_int* qY, mp_int* qZ, + mp_int* rX, mp_int* rY, mp_int* rZ) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit tmpd[2 * 8 * 5]; + sp_point pd; + sp_point qd; +#endif + sp_digit* tmp; + sp_point* p; + sp_point* q = NULL; + int err; + + err = sp_ecc_point_new(NULL, pd, p); + if (err == MP_OKAY) + err = sp_ecc_point_new(NULL, qd, q); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 5, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } +#else + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 8, pX); + sp_256_from_mp(p->y, 8, pY); + sp_256_from_mp(p->z, 8, pZ); + sp_256_from_mp(q->x, 8, qX); + sp_256_from_mp(q->y, 8, qY); + sp_256_from_mp(q->z, 8, qZ); + + sp_256_proj_point_add_8(p, p, q, tmp); + } + + if (err == MP_OKAY) + err = sp_256_to_mp(p->x, rX); + if (err == MP_OKAY) + err = sp_256_to_mp(p->y, rY); + if (err == MP_OKAY) + err = sp_256_to_mp(p->z, rZ); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (tmp != NULL) + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(q, 0, NULL); + sp_ecc_point_free(p, 0, NULL); + + return err; +} + +/* Double a projective EC point. + * (pX, pY, pZ) + (pX, pY, pZ) = (rX, rY, rZ) + * + * pX EC point's X ordinate. + * pY EC point's Y ordinate. + * pZ EC point's Z ordinate. + * rX Resultant EC point's X ordinate. + * rY Resultant EC point's Y ordinate. + * rZ Resultant EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* rX, mp_int* rY, mp_int* rZ) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit tmpd[2 * 8 * 2]; + sp_point pd; +#endif + sp_digit* tmp; + sp_point* p; + int err; + + err = sp_ecc_point_new(NULL, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 2, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } +#else + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 8, pX); + sp_256_from_mp(p->y, 8, pY); + sp_256_from_mp(p->z, 8, pZ); + + sp_256_proj_point_dbl_8(p, p, tmp); + } + + if (err == MP_OKAY) + err = sp_256_to_mp(p->x, rX); + if (err == MP_OKAY) + err = sp_256_to_mp(p->y, rY); + if (err == MP_OKAY) + err = sp_256_to_mp(p->z, rZ); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (tmp != NULL) + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p, 0, NULL); + + return err; +} + +/* Map a projective EC point to affine in place. + * pZ will be one. + * + * pX EC point's X ordinate. + * pY EC point's Y ordinate. + * pZ EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit tmpd[2 * 8 * 4]; + sp_point pd; +#endif + sp_digit* tmp; + sp_point* p; + int err; + + err = sp_ecc_point_new(NULL, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 4, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } +#else + tmp = tmpd; +#endif + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 8, pX); + sp_256_from_mp(p->y, 8, pY); + sp_256_from_mp(p->z, 8, pZ); + + sp_256_map_8(p, p, tmp); + } + + if (err == MP_OKAY) + err = sp_256_to_mp(p->x, pX); + if (err == MP_OKAY) + err = sp_256_to_mp(p->y, pY); + if (err == MP_OKAY) + err = sp_256_to_mp(p->z, pZ); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (tmp != NULL) + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p, 0, NULL); + + return err; +} +#endif /* WOLFSSL_PUBLIC_ECC_ADD_DBL */ +#ifdef HAVE_COMP_KEY +/* Find the square root of a number mod the prime of the curve. + * + * y The number to operate on and the result. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +static int sp_256_mont_sqrt_8(sp_digit* y) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d; +#else + sp_digit t1d[2 * 8]; + sp_digit t2d[2 * 8]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 8, NULL, DYNAMIC_TYPE_ECC); + if (d != NULL) { + t1 = d + 0 * 8; + t2 = d + 2 * 8; + } + else + err = MEMORY_E; +#else + t1 = t1d; + t2 = t2d; +#endif + + if (err == MP_OKAY) { + { + /* t2 = y ^ 0x2 */ + sp_256_mont_sqr_8(t2, y, p256_mod, p256_mp_mod); + /* t1 = y ^ 0x3 */ + sp_256_mont_mul_8(t1, t2, y, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xc */ + sp_256_mont_sqr_n_8(t2, t1, 2, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xf */ + sp_256_mont_mul_8(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xf0 */ + sp_256_mont_sqr_n_8(t2, t1, 4, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xff */ + sp_256_mont_mul_8(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xff00 */ + sp_256_mont_sqr_n_8(t2, t1, 8, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffff */ + sp_256_mont_mul_8(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xffff0000 */ + sp_256_mont_sqr_n_8(t2, t1, 16, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff */ + sp_256_mont_mul_8(t1, t1, t2, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000000 */ + sp_256_mont_sqr_n_8(t1, t1, 32, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001 */ + sp_256_mont_mul_8(t1, t1, y, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001000000000000000000000000 */ + sp_256_mont_sqr_n_8(t1, t1, 96, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001000000000000000000000001 */ + sp_256_mont_mul_8(t1, t1, y, p256_mod, p256_mp_mod); + sp_256_mont_sqr_n_8(y, t1, 94, p256_mod, p256_mp_mod); + } + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Uncompress the point given the X ordinate. + * + * xm X ordinate. + * odd Whether the Y ordinate is odd. + * ym Calculated Y ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d; +#else + sp_digit xd[2 * 8]; + sp_digit yd[2 * 8]; +#endif + sp_digit* x; + sp_digit* y; + int err = MP_OKAY; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 8, NULL, DYNAMIC_TYPE_ECC); + if (d != NULL) { + x = d + 0 * 8; + y = d + 2 * 8; + } + else + err = MEMORY_E; +#else + x = xd; + y = yd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(x, 8, xm); + + err = sp_256_mod_mul_norm_8(x, x, p256_mod); + } + + if (err == MP_OKAY) { + /* y = x^3 */ + { + sp_256_mont_sqr_8(y, x, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(y, y, x, p256_mod, p256_mp_mod); + } + /* y = x^3 - 3x */ + sp_256_mont_sub_8(y, y, x, p256_mod); + sp_256_mont_sub_8(y, y, x, p256_mod); + sp_256_mont_sub_8(y, y, x, p256_mod); + /* y = x^3 - 3x + b */ + err = sp_256_mod_mul_norm_8(x, p256_b, p256_mod); + } + if (err == MP_OKAY) { + sp_256_mont_add_8(y, y, x, p256_mod); + /* y = sqrt(x^3 - 3x + b) */ + err = sp_256_mont_sqrt_8(y); + } + if (err == MP_OKAY) { + XMEMSET(y + 8, 0, 8 * sizeof(sp_digit)); + sp_256_mont_reduce_8(y, p256_mod, p256_mp_mod); + if (((y[0] ^ odd) & 1) != 0) + sp_256_mont_sub_8(y, p256_mod, y, p256_mod); + + err = sp_256_to_mp(y, ym); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_ECC); +#endif + + return err; +} +#endif +#endif /* !WOLFSSL_SP_NO_256 */ +#endif /* WOLFSSL_HAVE_SP_ECC */ +#endif /* WOLFSSL_SP_ARM_THUMB_ASM */ +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH || WOLFSSL_HAVE_SP_ECC */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/sp_c32.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/sp_c32.c new file mode 100755 index 0000000..444f537 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/sp_c32.c @@ -0,0 +1,12678 @@ +/* sp.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/* Implementation by Sean Parkinson. */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include +#include +#include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) || \ + defined(WOLFSSL_HAVE_SP_ECC) + +#ifdef RSA_LOW_MEM +#ifndef SP_RSA_PRIVATE_EXP_D +#define SP_RSA_PRIVATE_EXP_D +#endif + +#ifndef WOLFSSL_SP_SMALL +#define WOLFSSL_SP_SMALL +#endif +#endif + +#include + +#ifndef WOLFSSL_SP_ASM +#if SP_WORD_SIZE == 32 +#if (defined(WOLFSSL_SP_CACHE_RESISTANT) || defined(WOLFSSL_SP_SMALL)) && (defined(WOLFSSL_HAVE_SP_ECC) || !defined(WOLFSSL_RSA_PUBLIC_ONLY)) +/* Mask for address to obfuscate which of the two address will be used. */ +static const size_t addr_mask[2] = { 0, (size_t)-1 }; +#endif + +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) +#ifndef WOLFSSL_SP_NO_2048 +/* Read big endian unsigned byte aray into r. + * + * r A single precision integer. + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_2048_from_bin(sp_digit* r, int max, const byte* a, int n) +{ + int i, j = 0, s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= ((sp_digit)a[i]) << s; + if (s >= 15) { + r[j] &= 0x7fffff; + s = 23 - s; + if (j + 1 >= max) + break; + r[++j] = a[i] >> s; + s = 8 - s; + } + else + s += 8; + } + + for (j++; j < max; j++) + r[j] = 0; +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * a A multi-precision integer. + */ +static void sp_2048_from_mp(sp_digit* r, int max, mp_int* a) +{ +#if DIGIT_BIT == 23 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < max; j++) + r[j] = 0; +#elif DIGIT_BIT > 23 + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= a->dp[i] << s; + r[j] &= 0x7fffff; + s = 23 - s; + if (j + 1 >= max) + break; + r[++j] = (sp_digit)(a->dp[i] >> s); + while (s + 23 <= DIGIT_BIT) { + s += 23; + r[j] &= 0x7fffff; + if (j + 1 >= max) + break; + if (s < DIGIT_BIT) + r[++j] = (sp_digit)(a->dp[i] >> s); + else + r[++j] = 0; + } + s = DIGIT_BIT - s; + } + + for (j++; j < max; j++) + r[j] = 0; +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 23) { + r[j] &= 0x7fffff; + if (j + 1 >= max) + break; + s = 23 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else + s += DIGIT_BIT; + } + + for (j++; j < max; j++) + r[j] = 0; +#endif +} + +/* Write r as big endian to byte aray. + * Fixed length number of bytes written: 256 + * + * r A single precision integer. + * a Byte array. + */ +static void sp_2048_to_bin(sp_digit* r, byte* a) +{ + int i, j, s = 0, b; + + for (i=0; i<89; i++) { + r[i+1] += r[i] >> 23; + r[i] &= 0x7fffff; + } + j = 2048 / 8 - 1; + a[j] = 0; + for (i=0; i<90 && j>=0; i++) { + b = 0; + a[j--] |= r[i] << s; b += 8 - s; + if (j < 0) + break; + while (b < 23) { + a[j--] = r[i] >> b; b += 8; + if (j < 0) + break; + } + s = 8 - (b - 23); + if (j >= 0) + a[j] = 0; + if (s != 0) + j++; + } +} + +#ifndef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_2048_mul_15(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int64_t t0 = ((int64_t)a[ 0]) * b[ 0]; + int64_t t1 = ((int64_t)a[ 0]) * b[ 1] + + ((int64_t)a[ 1]) * b[ 0]; + int64_t t2 = ((int64_t)a[ 0]) * b[ 2] + + ((int64_t)a[ 1]) * b[ 1] + + ((int64_t)a[ 2]) * b[ 0]; + int64_t t3 = ((int64_t)a[ 0]) * b[ 3] + + ((int64_t)a[ 1]) * b[ 2] + + ((int64_t)a[ 2]) * b[ 1] + + ((int64_t)a[ 3]) * b[ 0]; + int64_t t4 = ((int64_t)a[ 0]) * b[ 4] + + ((int64_t)a[ 1]) * b[ 3] + + ((int64_t)a[ 2]) * b[ 2] + + ((int64_t)a[ 3]) * b[ 1] + + ((int64_t)a[ 4]) * b[ 0]; + int64_t t5 = ((int64_t)a[ 0]) * b[ 5] + + ((int64_t)a[ 1]) * b[ 4] + + ((int64_t)a[ 2]) * b[ 3] + + ((int64_t)a[ 3]) * b[ 2] + + ((int64_t)a[ 4]) * b[ 1] + + ((int64_t)a[ 5]) * b[ 0]; + int64_t t6 = ((int64_t)a[ 0]) * b[ 6] + + ((int64_t)a[ 1]) * b[ 5] + + ((int64_t)a[ 2]) * b[ 4] + + ((int64_t)a[ 3]) * b[ 3] + + ((int64_t)a[ 4]) * b[ 2] + + ((int64_t)a[ 5]) * b[ 1] + + ((int64_t)a[ 6]) * b[ 0]; + int64_t t7 = ((int64_t)a[ 0]) * b[ 7] + + ((int64_t)a[ 1]) * b[ 6] + + ((int64_t)a[ 2]) * b[ 5] + + ((int64_t)a[ 3]) * b[ 4] + + ((int64_t)a[ 4]) * b[ 3] + + ((int64_t)a[ 5]) * b[ 2] + + ((int64_t)a[ 6]) * b[ 1] + + ((int64_t)a[ 7]) * b[ 0]; + int64_t t8 = ((int64_t)a[ 0]) * b[ 8] + + ((int64_t)a[ 1]) * b[ 7] + + ((int64_t)a[ 2]) * b[ 6] + + ((int64_t)a[ 3]) * b[ 5] + + ((int64_t)a[ 4]) * b[ 4] + + ((int64_t)a[ 5]) * b[ 3] + + ((int64_t)a[ 6]) * b[ 2] + + ((int64_t)a[ 7]) * b[ 1] + + ((int64_t)a[ 8]) * b[ 0]; + int64_t t9 = ((int64_t)a[ 0]) * b[ 9] + + ((int64_t)a[ 1]) * b[ 8] + + ((int64_t)a[ 2]) * b[ 7] + + ((int64_t)a[ 3]) * b[ 6] + + ((int64_t)a[ 4]) * b[ 5] + + ((int64_t)a[ 5]) * b[ 4] + + ((int64_t)a[ 6]) * b[ 3] + + ((int64_t)a[ 7]) * b[ 2] + + ((int64_t)a[ 8]) * b[ 1] + + ((int64_t)a[ 9]) * b[ 0]; + int64_t t10 = ((int64_t)a[ 0]) * b[10] + + ((int64_t)a[ 1]) * b[ 9] + + ((int64_t)a[ 2]) * b[ 8] + + ((int64_t)a[ 3]) * b[ 7] + + ((int64_t)a[ 4]) * b[ 6] + + ((int64_t)a[ 5]) * b[ 5] + + ((int64_t)a[ 6]) * b[ 4] + + ((int64_t)a[ 7]) * b[ 3] + + ((int64_t)a[ 8]) * b[ 2] + + ((int64_t)a[ 9]) * b[ 1] + + ((int64_t)a[10]) * b[ 0]; + int64_t t11 = ((int64_t)a[ 0]) * b[11] + + ((int64_t)a[ 1]) * b[10] + + ((int64_t)a[ 2]) * b[ 9] + + ((int64_t)a[ 3]) * b[ 8] + + ((int64_t)a[ 4]) * b[ 7] + + ((int64_t)a[ 5]) * b[ 6] + + ((int64_t)a[ 6]) * b[ 5] + + ((int64_t)a[ 7]) * b[ 4] + + ((int64_t)a[ 8]) * b[ 3] + + ((int64_t)a[ 9]) * b[ 2] + + ((int64_t)a[10]) * b[ 1] + + ((int64_t)a[11]) * b[ 0]; + int64_t t12 = ((int64_t)a[ 0]) * b[12] + + ((int64_t)a[ 1]) * b[11] + + ((int64_t)a[ 2]) * b[10] + + ((int64_t)a[ 3]) * b[ 9] + + ((int64_t)a[ 4]) * b[ 8] + + ((int64_t)a[ 5]) * b[ 7] + + ((int64_t)a[ 6]) * b[ 6] + + ((int64_t)a[ 7]) * b[ 5] + + ((int64_t)a[ 8]) * b[ 4] + + ((int64_t)a[ 9]) * b[ 3] + + ((int64_t)a[10]) * b[ 2] + + ((int64_t)a[11]) * b[ 1] + + ((int64_t)a[12]) * b[ 0]; + int64_t t13 = ((int64_t)a[ 0]) * b[13] + + ((int64_t)a[ 1]) * b[12] + + ((int64_t)a[ 2]) * b[11] + + ((int64_t)a[ 3]) * b[10] + + ((int64_t)a[ 4]) * b[ 9] + + ((int64_t)a[ 5]) * b[ 8] + + ((int64_t)a[ 6]) * b[ 7] + + ((int64_t)a[ 7]) * b[ 6] + + ((int64_t)a[ 8]) * b[ 5] + + ((int64_t)a[ 9]) * b[ 4] + + ((int64_t)a[10]) * b[ 3] + + ((int64_t)a[11]) * b[ 2] + + ((int64_t)a[12]) * b[ 1] + + ((int64_t)a[13]) * b[ 0]; + int64_t t14 = ((int64_t)a[ 0]) * b[14] + + ((int64_t)a[ 1]) * b[13] + + ((int64_t)a[ 2]) * b[12] + + ((int64_t)a[ 3]) * b[11] + + ((int64_t)a[ 4]) * b[10] + + ((int64_t)a[ 5]) * b[ 9] + + ((int64_t)a[ 6]) * b[ 8] + + ((int64_t)a[ 7]) * b[ 7] + + ((int64_t)a[ 8]) * b[ 6] + + ((int64_t)a[ 9]) * b[ 5] + + ((int64_t)a[10]) * b[ 4] + + ((int64_t)a[11]) * b[ 3] + + ((int64_t)a[12]) * b[ 2] + + ((int64_t)a[13]) * b[ 1] + + ((int64_t)a[14]) * b[ 0]; + int64_t t15 = ((int64_t)a[ 1]) * b[14] + + ((int64_t)a[ 2]) * b[13] + + ((int64_t)a[ 3]) * b[12] + + ((int64_t)a[ 4]) * b[11] + + ((int64_t)a[ 5]) * b[10] + + ((int64_t)a[ 6]) * b[ 9] + + ((int64_t)a[ 7]) * b[ 8] + + ((int64_t)a[ 8]) * b[ 7] + + ((int64_t)a[ 9]) * b[ 6] + + ((int64_t)a[10]) * b[ 5] + + ((int64_t)a[11]) * b[ 4] + + ((int64_t)a[12]) * b[ 3] + + ((int64_t)a[13]) * b[ 2] + + ((int64_t)a[14]) * b[ 1]; + int64_t t16 = ((int64_t)a[ 2]) * b[14] + + ((int64_t)a[ 3]) * b[13] + + ((int64_t)a[ 4]) * b[12] + + ((int64_t)a[ 5]) * b[11] + + ((int64_t)a[ 6]) * b[10] + + ((int64_t)a[ 7]) * b[ 9] + + ((int64_t)a[ 8]) * b[ 8] + + ((int64_t)a[ 9]) * b[ 7] + + ((int64_t)a[10]) * b[ 6] + + ((int64_t)a[11]) * b[ 5] + + ((int64_t)a[12]) * b[ 4] + + ((int64_t)a[13]) * b[ 3] + + ((int64_t)a[14]) * b[ 2]; + int64_t t17 = ((int64_t)a[ 3]) * b[14] + + ((int64_t)a[ 4]) * b[13] + + ((int64_t)a[ 5]) * b[12] + + ((int64_t)a[ 6]) * b[11] + + ((int64_t)a[ 7]) * b[10] + + ((int64_t)a[ 8]) * b[ 9] + + ((int64_t)a[ 9]) * b[ 8] + + ((int64_t)a[10]) * b[ 7] + + ((int64_t)a[11]) * b[ 6] + + ((int64_t)a[12]) * b[ 5] + + ((int64_t)a[13]) * b[ 4] + + ((int64_t)a[14]) * b[ 3]; + int64_t t18 = ((int64_t)a[ 4]) * b[14] + + ((int64_t)a[ 5]) * b[13] + + ((int64_t)a[ 6]) * b[12] + + ((int64_t)a[ 7]) * b[11] + + ((int64_t)a[ 8]) * b[10] + + ((int64_t)a[ 9]) * b[ 9] + + ((int64_t)a[10]) * b[ 8] + + ((int64_t)a[11]) * b[ 7] + + ((int64_t)a[12]) * b[ 6] + + ((int64_t)a[13]) * b[ 5] + + ((int64_t)a[14]) * b[ 4]; + int64_t t19 = ((int64_t)a[ 5]) * b[14] + + ((int64_t)a[ 6]) * b[13] + + ((int64_t)a[ 7]) * b[12] + + ((int64_t)a[ 8]) * b[11] + + ((int64_t)a[ 9]) * b[10] + + ((int64_t)a[10]) * b[ 9] + + ((int64_t)a[11]) * b[ 8] + + ((int64_t)a[12]) * b[ 7] + + ((int64_t)a[13]) * b[ 6] + + ((int64_t)a[14]) * b[ 5]; + int64_t t20 = ((int64_t)a[ 6]) * b[14] + + ((int64_t)a[ 7]) * b[13] + + ((int64_t)a[ 8]) * b[12] + + ((int64_t)a[ 9]) * b[11] + + ((int64_t)a[10]) * b[10] + + ((int64_t)a[11]) * b[ 9] + + ((int64_t)a[12]) * b[ 8] + + ((int64_t)a[13]) * b[ 7] + + ((int64_t)a[14]) * b[ 6]; + int64_t t21 = ((int64_t)a[ 7]) * b[14] + + ((int64_t)a[ 8]) * b[13] + + ((int64_t)a[ 9]) * b[12] + + ((int64_t)a[10]) * b[11] + + ((int64_t)a[11]) * b[10] + + ((int64_t)a[12]) * b[ 9] + + ((int64_t)a[13]) * b[ 8] + + ((int64_t)a[14]) * b[ 7]; + int64_t t22 = ((int64_t)a[ 8]) * b[14] + + ((int64_t)a[ 9]) * b[13] + + ((int64_t)a[10]) * b[12] + + ((int64_t)a[11]) * b[11] + + ((int64_t)a[12]) * b[10] + + ((int64_t)a[13]) * b[ 9] + + ((int64_t)a[14]) * b[ 8]; + int64_t t23 = ((int64_t)a[ 9]) * b[14] + + ((int64_t)a[10]) * b[13] + + ((int64_t)a[11]) * b[12] + + ((int64_t)a[12]) * b[11] + + ((int64_t)a[13]) * b[10] + + ((int64_t)a[14]) * b[ 9]; + int64_t t24 = ((int64_t)a[10]) * b[14] + + ((int64_t)a[11]) * b[13] + + ((int64_t)a[12]) * b[12] + + ((int64_t)a[13]) * b[11] + + ((int64_t)a[14]) * b[10]; + int64_t t25 = ((int64_t)a[11]) * b[14] + + ((int64_t)a[12]) * b[13] + + ((int64_t)a[13]) * b[12] + + ((int64_t)a[14]) * b[11]; + int64_t t26 = ((int64_t)a[12]) * b[14] + + ((int64_t)a[13]) * b[13] + + ((int64_t)a[14]) * b[12]; + int64_t t27 = ((int64_t)a[13]) * b[14] + + ((int64_t)a[14]) * b[13]; + int64_t t28 = ((int64_t)a[14]) * b[14]; + + t1 += t0 >> 23; r[ 0] = t0 & 0x7fffff; + t2 += t1 >> 23; r[ 1] = t1 & 0x7fffff; + t3 += t2 >> 23; r[ 2] = t2 & 0x7fffff; + t4 += t3 >> 23; r[ 3] = t3 & 0x7fffff; + t5 += t4 >> 23; r[ 4] = t4 & 0x7fffff; + t6 += t5 >> 23; r[ 5] = t5 & 0x7fffff; + t7 += t6 >> 23; r[ 6] = t6 & 0x7fffff; + t8 += t7 >> 23; r[ 7] = t7 & 0x7fffff; + t9 += t8 >> 23; r[ 8] = t8 & 0x7fffff; + t10 += t9 >> 23; r[ 9] = t9 & 0x7fffff; + t11 += t10 >> 23; r[10] = t10 & 0x7fffff; + t12 += t11 >> 23; r[11] = t11 & 0x7fffff; + t13 += t12 >> 23; r[12] = t12 & 0x7fffff; + t14 += t13 >> 23; r[13] = t13 & 0x7fffff; + t15 += t14 >> 23; r[14] = t14 & 0x7fffff; + t16 += t15 >> 23; r[15] = t15 & 0x7fffff; + t17 += t16 >> 23; r[16] = t16 & 0x7fffff; + t18 += t17 >> 23; r[17] = t17 & 0x7fffff; + t19 += t18 >> 23; r[18] = t18 & 0x7fffff; + t20 += t19 >> 23; r[19] = t19 & 0x7fffff; + t21 += t20 >> 23; r[20] = t20 & 0x7fffff; + t22 += t21 >> 23; r[21] = t21 & 0x7fffff; + t23 += t22 >> 23; r[22] = t22 & 0x7fffff; + t24 += t23 >> 23; r[23] = t23 & 0x7fffff; + t25 += t24 >> 23; r[24] = t24 & 0x7fffff; + t26 += t25 >> 23; r[25] = t25 & 0x7fffff; + t27 += t26 >> 23; r[26] = t26 & 0x7fffff; + t28 += t27 >> 23; r[27] = t27 & 0x7fffff; + r[29] = (sp_digit)(t28 >> 23); + r[28] = t28 & 0x7fffff; +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_2048_sqr_15(sp_digit* r, const sp_digit* a) +{ + int64_t t0 = ((int64_t)a[ 0]) * a[ 0]; + int64_t t1 = (((int64_t)a[ 0]) * a[ 1]) * 2; + int64_t t2 = (((int64_t)a[ 0]) * a[ 2]) * 2 + + ((int64_t)a[ 1]) * a[ 1]; + int64_t t3 = (((int64_t)a[ 0]) * a[ 3] + + ((int64_t)a[ 1]) * a[ 2]) * 2; + int64_t t4 = (((int64_t)a[ 0]) * a[ 4] + + ((int64_t)a[ 1]) * a[ 3]) * 2 + + ((int64_t)a[ 2]) * a[ 2]; + int64_t t5 = (((int64_t)a[ 0]) * a[ 5] + + ((int64_t)a[ 1]) * a[ 4] + + ((int64_t)a[ 2]) * a[ 3]) * 2; + int64_t t6 = (((int64_t)a[ 0]) * a[ 6] + + ((int64_t)a[ 1]) * a[ 5] + + ((int64_t)a[ 2]) * a[ 4]) * 2 + + ((int64_t)a[ 3]) * a[ 3]; + int64_t t7 = (((int64_t)a[ 0]) * a[ 7] + + ((int64_t)a[ 1]) * a[ 6] + + ((int64_t)a[ 2]) * a[ 5] + + ((int64_t)a[ 3]) * a[ 4]) * 2; + int64_t t8 = (((int64_t)a[ 0]) * a[ 8] + + ((int64_t)a[ 1]) * a[ 7] + + ((int64_t)a[ 2]) * a[ 6] + + ((int64_t)a[ 3]) * a[ 5]) * 2 + + ((int64_t)a[ 4]) * a[ 4]; + int64_t t9 = (((int64_t)a[ 0]) * a[ 9] + + ((int64_t)a[ 1]) * a[ 8] + + ((int64_t)a[ 2]) * a[ 7] + + ((int64_t)a[ 3]) * a[ 6] + + ((int64_t)a[ 4]) * a[ 5]) * 2; + int64_t t10 = (((int64_t)a[ 0]) * a[10] + + ((int64_t)a[ 1]) * a[ 9] + + ((int64_t)a[ 2]) * a[ 8] + + ((int64_t)a[ 3]) * a[ 7] + + ((int64_t)a[ 4]) * a[ 6]) * 2 + + ((int64_t)a[ 5]) * a[ 5]; + int64_t t11 = (((int64_t)a[ 0]) * a[11] + + ((int64_t)a[ 1]) * a[10] + + ((int64_t)a[ 2]) * a[ 9] + + ((int64_t)a[ 3]) * a[ 8] + + ((int64_t)a[ 4]) * a[ 7] + + ((int64_t)a[ 5]) * a[ 6]) * 2; + int64_t t12 = (((int64_t)a[ 0]) * a[12] + + ((int64_t)a[ 1]) * a[11] + + ((int64_t)a[ 2]) * a[10] + + ((int64_t)a[ 3]) * a[ 9] + + ((int64_t)a[ 4]) * a[ 8] + + ((int64_t)a[ 5]) * a[ 7]) * 2 + + ((int64_t)a[ 6]) * a[ 6]; + int64_t t13 = (((int64_t)a[ 0]) * a[13] + + ((int64_t)a[ 1]) * a[12] + + ((int64_t)a[ 2]) * a[11] + + ((int64_t)a[ 3]) * a[10] + + ((int64_t)a[ 4]) * a[ 9] + + ((int64_t)a[ 5]) * a[ 8] + + ((int64_t)a[ 6]) * a[ 7]) * 2; + int64_t t14 = (((int64_t)a[ 0]) * a[14] + + ((int64_t)a[ 1]) * a[13] + + ((int64_t)a[ 2]) * a[12] + + ((int64_t)a[ 3]) * a[11] + + ((int64_t)a[ 4]) * a[10] + + ((int64_t)a[ 5]) * a[ 9] + + ((int64_t)a[ 6]) * a[ 8]) * 2 + + ((int64_t)a[ 7]) * a[ 7]; + int64_t t15 = (((int64_t)a[ 1]) * a[14] + + ((int64_t)a[ 2]) * a[13] + + ((int64_t)a[ 3]) * a[12] + + ((int64_t)a[ 4]) * a[11] + + ((int64_t)a[ 5]) * a[10] + + ((int64_t)a[ 6]) * a[ 9] + + ((int64_t)a[ 7]) * a[ 8]) * 2; + int64_t t16 = (((int64_t)a[ 2]) * a[14] + + ((int64_t)a[ 3]) * a[13] + + ((int64_t)a[ 4]) * a[12] + + ((int64_t)a[ 5]) * a[11] + + ((int64_t)a[ 6]) * a[10] + + ((int64_t)a[ 7]) * a[ 9]) * 2 + + ((int64_t)a[ 8]) * a[ 8]; + int64_t t17 = (((int64_t)a[ 3]) * a[14] + + ((int64_t)a[ 4]) * a[13] + + ((int64_t)a[ 5]) * a[12] + + ((int64_t)a[ 6]) * a[11] + + ((int64_t)a[ 7]) * a[10] + + ((int64_t)a[ 8]) * a[ 9]) * 2; + int64_t t18 = (((int64_t)a[ 4]) * a[14] + + ((int64_t)a[ 5]) * a[13] + + ((int64_t)a[ 6]) * a[12] + + ((int64_t)a[ 7]) * a[11] + + ((int64_t)a[ 8]) * a[10]) * 2 + + ((int64_t)a[ 9]) * a[ 9]; + int64_t t19 = (((int64_t)a[ 5]) * a[14] + + ((int64_t)a[ 6]) * a[13] + + ((int64_t)a[ 7]) * a[12] + + ((int64_t)a[ 8]) * a[11] + + ((int64_t)a[ 9]) * a[10]) * 2; + int64_t t20 = (((int64_t)a[ 6]) * a[14] + + ((int64_t)a[ 7]) * a[13] + + ((int64_t)a[ 8]) * a[12] + + ((int64_t)a[ 9]) * a[11]) * 2 + + ((int64_t)a[10]) * a[10]; + int64_t t21 = (((int64_t)a[ 7]) * a[14] + + ((int64_t)a[ 8]) * a[13] + + ((int64_t)a[ 9]) * a[12] + + ((int64_t)a[10]) * a[11]) * 2; + int64_t t22 = (((int64_t)a[ 8]) * a[14] + + ((int64_t)a[ 9]) * a[13] + + ((int64_t)a[10]) * a[12]) * 2 + + ((int64_t)a[11]) * a[11]; + int64_t t23 = (((int64_t)a[ 9]) * a[14] + + ((int64_t)a[10]) * a[13] + + ((int64_t)a[11]) * a[12]) * 2; + int64_t t24 = (((int64_t)a[10]) * a[14] + + ((int64_t)a[11]) * a[13]) * 2 + + ((int64_t)a[12]) * a[12]; + int64_t t25 = (((int64_t)a[11]) * a[14] + + ((int64_t)a[12]) * a[13]) * 2; + int64_t t26 = (((int64_t)a[12]) * a[14]) * 2 + + ((int64_t)a[13]) * a[13]; + int64_t t27 = (((int64_t)a[13]) * a[14]) * 2; + int64_t t28 = ((int64_t)a[14]) * a[14]; + + t1 += t0 >> 23; r[ 0] = t0 & 0x7fffff; + t2 += t1 >> 23; r[ 1] = t1 & 0x7fffff; + t3 += t2 >> 23; r[ 2] = t2 & 0x7fffff; + t4 += t3 >> 23; r[ 3] = t3 & 0x7fffff; + t5 += t4 >> 23; r[ 4] = t4 & 0x7fffff; + t6 += t5 >> 23; r[ 5] = t5 & 0x7fffff; + t7 += t6 >> 23; r[ 6] = t6 & 0x7fffff; + t8 += t7 >> 23; r[ 7] = t7 & 0x7fffff; + t9 += t8 >> 23; r[ 8] = t8 & 0x7fffff; + t10 += t9 >> 23; r[ 9] = t9 & 0x7fffff; + t11 += t10 >> 23; r[10] = t10 & 0x7fffff; + t12 += t11 >> 23; r[11] = t11 & 0x7fffff; + t13 += t12 >> 23; r[12] = t12 & 0x7fffff; + t14 += t13 >> 23; r[13] = t13 & 0x7fffff; + t15 += t14 >> 23; r[14] = t14 & 0x7fffff; + t16 += t15 >> 23; r[15] = t15 & 0x7fffff; + t17 += t16 >> 23; r[16] = t16 & 0x7fffff; + t18 += t17 >> 23; r[17] = t17 & 0x7fffff; + t19 += t18 >> 23; r[18] = t18 & 0x7fffff; + t20 += t19 >> 23; r[19] = t19 & 0x7fffff; + t21 += t20 >> 23; r[20] = t20 & 0x7fffff; + t22 += t21 >> 23; r[21] = t21 & 0x7fffff; + t23 += t22 >> 23; r[22] = t22 & 0x7fffff; + t24 += t23 >> 23; r[23] = t23 & 0x7fffff; + t25 += t24 >> 23; r[24] = t24 & 0x7fffff; + t26 += t25 >> 23; r[25] = t25 & 0x7fffff; + t27 += t26 >> 23; r[26] = t26 & 0x7fffff; + t28 += t27 >> 23; r[27] = t27 & 0x7fffff; + r[29] = (sp_digit)(t28 >> 23); + r[28] = t28 & 0x7fffff; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_2048_add_15(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + r[ 0] = a[ 0] + b[ 0]; + r[ 1] = a[ 1] + b[ 1]; + r[ 2] = a[ 2] + b[ 2]; + r[ 3] = a[ 3] + b[ 3]; + r[ 4] = a[ 4] + b[ 4]; + r[ 5] = a[ 5] + b[ 5]; + r[ 6] = a[ 6] + b[ 6]; + r[ 7] = a[ 7] + b[ 7]; + r[ 8] = a[ 8] + b[ 8]; + r[ 9] = a[ 9] + b[ 9]; + r[10] = a[10] + b[10]; + r[11] = a[11] + b[11]; + r[12] = a[12] + b[12]; + r[13] = a[13] + b[13]; + r[14] = a[14] + b[14]; + + return 0; +} + +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_2048_sub_30(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 24; i += 8) { + r[i + 0] = a[i + 0] - b[i + 0]; + r[i + 1] = a[i + 1] - b[i + 1]; + r[i + 2] = a[i + 2] - b[i + 2]; + r[i + 3] = a[i + 3] - b[i + 3]; + r[i + 4] = a[i + 4] - b[i + 4]; + r[i + 5] = a[i + 5] - b[i + 5]; + r[i + 6] = a[i + 6] - b[i + 6]; + r[i + 7] = a[i + 7] - b[i + 7]; + } + r[24] = a[24] - b[24]; + r[25] = a[25] - b[25]; + r[26] = a[26] - b[26]; + r[27] = a[27] - b[27]; + r[28] = a[28] - b[28]; + r[29] = a[29] - b[29]; + + return 0; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_2048_add_30(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 24; i += 8) { + r[i + 0] = a[i + 0] + b[i + 0]; + r[i + 1] = a[i + 1] + b[i + 1]; + r[i + 2] = a[i + 2] + b[i + 2]; + r[i + 3] = a[i + 3] + b[i + 3]; + r[i + 4] = a[i + 4] + b[i + 4]; + r[i + 5] = a[i + 5] + b[i + 5]; + r[i + 6] = a[i + 6] + b[i + 6]; + r[i + 7] = a[i + 7] + b[i + 7]; + } + r[24] = a[24] + b[24]; + r[25] = a[25] + b[25]; + r[26] = a[26] + b[26]; + r[27] = a[27] + b[27]; + r[28] = a[28] + b[28]; + r[29] = a[29] + b[29]; + + return 0; +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_2048_mul_45(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit p0[30]; + sp_digit p1[30]; + sp_digit p2[30]; + sp_digit p3[30]; + sp_digit p4[30]; + sp_digit p5[30]; + sp_digit t0[30]; + sp_digit t1[30]; + sp_digit t2[30]; + sp_digit a0[15]; + sp_digit a1[15]; + sp_digit a2[15]; + sp_digit b0[15]; + sp_digit b1[15]; + sp_digit b2[15]; + sp_2048_add_15(a0, a, &a[15]); + sp_2048_add_15(b0, b, &b[15]); + sp_2048_add_15(a1, &a[15], &a[30]); + sp_2048_add_15(b1, &b[15], &b[30]); + sp_2048_add_15(a2, a0, &a[30]); + sp_2048_add_15(b2, b0, &b[30]); + sp_2048_mul_15(p0, a, b); + sp_2048_mul_15(p2, &a[15], &b[15]); + sp_2048_mul_15(p4, &a[30], &b[30]); + sp_2048_mul_15(p1, a0, b0); + sp_2048_mul_15(p3, a1, b1); + sp_2048_mul_15(p5, a2, b2); + XMEMSET(r, 0, sizeof(*r)*2*45); + sp_2048_sub_30(t0, p3, p2); + sp_2048_sub_30(t1, p1, p2); + sp_2048_sub_30(t2, p5, t0); + sp_2048_sub_30(t2, t2, t1); + sp_2048_sub_30(t0, t0, p4); + sp_2048_sub_30(t1, t1, p0); + sp_2048_add_30(r, r, p0); + sp_2048_add_30(&r[15], &r[15], t1); + sp_2048_add_30(&r[30], &r[30], t2); + sp_2048_add_30(&r[45], &r[45], t0); + sp_2048_add_30(&r[60], &r[60], p4); +} + +/* Square a into r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_2048_sqr_45(sp_digit* r, const sp_digit* a) +{ + sp_digit p0[30]; + sp_digit p1[30]; + sp_digit p2[30]; + sp_digit p3[30]; + sp_digit p4[30]; + sp_digit p5[30]; + sp_digit t0[30]; + sp_digit t1[30]; + sp_digit t2[30]; + sp_digit a0[15]; + sp_digit a1[15]; + sp_digit a2[15]; + sp_2048_add_15(a0, a, &a[15]); + sp_2048_add_15(a1, &a[15], &a[30]); + sp_2048_add_15(a2, a0, &a[30]); + sp_2048_sqr_15(p0, a); + sp_2048_sqr_15(p2, &a[15]); + sp_2048_sqr_15(p4, &a[30]); + sp_2048_sqr_15(p1, a0); + sp_2048_sqr_15(p3, a1); + sp_2048_sqr_15(p5, a2); + XMEMSET(r, 0, sizeof(*r)*2*45); + sp_2048_sub_30(t0, p3, p2); + sp_2048_sub_30(t1, p1, p2); + sp_2048_sub_30(t2, p5, t0); + sp_2048_sub_30(t2, t2, t1); + sp_2048_sub_30(t0, t0, p4); + sp_2048_sub_30(t1, t1, p0); + sp_2048_add_30(r, r, p0); + sp_2048_add_30(&r[15], &r[15], t1); + sp_2048_add_30(&r[30], &r[30], t2); + sp_2048_add_30(&r[45], &r[45], t0); + sp_2048_add_30(&r[60], &r[60], p4); +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_2048_add_45(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 40; i += 8) { + r[i + 0] = a[i + 0] + b[i + 0]; + r[i + 1] = a[i + 1] + b[i + 1]; + r[i + 2] = a[i + 2] + b[i + 2]; + r[i + 3] = a[i + 3] + b[i + 3]; + r[i + 4] = a[i + 4] + b[i + 4]; + r[i + 5] = a[i + 5] + b[i + 5]; + r[i + 6] = a[i + 6] + b[i + 6]; + r[i + 7] = a[i + 7] + b[i + 7]; + } + r[40] = a[40] + b[40]; + r[41] = a[41] + b[41]; + r[42] = a[42] + b[42]; + r[43] = a[43] + b[43]; + r[44] = a[44] + b[44]; + + return 0; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_2048_add_90(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 88; i += 8) { + r[i + 0] = a[i + 0] + b[i + 0]; + r[i + 1] = a[i + 1] + b[i + 1]; + r[i + 2] = a[i + 2] + b[i + 2]; + r[i + 3] = a[i + 3] + b[i + 3]; + r[i + 4] = a[i + 4] + b[i + 4]; + r[i + 5] = a[i + 5] + b[i + 5]; + r[i + 6] = a[i + 6] + b[i + 6]; + r[i + 7] = a[i + 7] + b[i + 7]; + } + r[88] = a[88] + b[88]; + r[89] = a[89] + b[89]; + + return 0; +} + +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_2048_sub_90(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 88; i += 8) { + r[i + 0] = a[i + 0] - b[i + 0]; + r[i + 1] = a[i + 1] - b[i + 1]; + r[i + 2] = a[i + 2] - b[i + 2]; + r[i + 3] = a[i + 3] - b[i + 3]; + r[i + 4] = a[i + 4] - b[i + 4]; + r[i + 5] = a[i + 5] - b[i + 5]; + r[i + 6] = a[i + 6] - b[i + 6]; + r[i + 7] = a[i + 7] - b[i + 7]; + } + r[88] = a[88] - b[88]; + r[89] = a[89] - b[89]; + + return 0; +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_2048_mul_90(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[90]; + sp_digit* a1 = z1; + sp_digit b1[45]; + sp_digit* z2 = r + 90; + sp_2048_add_45(a1, a, &a[45]); + sp_2048_add_45(b1, b, &b[45]); + sp_2048_mul_45(z2, &a[45], &b[45]); + sp_2048_mul_45(z0, a, b); + sp_2048_mul_45(z1, a1, b1); + sp_2048_sub_90(z1, z1, z2); + sp_2048_sub_90(z1, z1, z0); + sp_2048_add_90(r + 45, r + 45, z1); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_2048_sqr_90(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z1[90]; + sp_digit* a1 = z1; + sp_digit* z2 = r + 90; + sp_2048_add_45(a1, a, &a[45]); + sp_2048_sqr_45(z2, &a[45]); + sp_2048_sqr_45(z0, a); + sp_2048_sqr_45(z1, a1); + sp_2048_sub_90(z1, z1, z2); + sp_2048_sub_90(z1, z1, z0); + sp_2048_add_90(r + 45, r + 45, z1); +} + +#endif /* !WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_2048_add_90(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 90; i++) + r[i] = a[i] + b[i]; + + return 0; +} +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_2048_sub_90(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 90; i++) + r[i] = a[i] - b[i]; + + return 0; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_2048_mul_90(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i, j, k; + int64_t c; + + c = ((int64_t)a[89]) * b[89]; + r[179] = (sp_digit)(c >> 23); + c = (c & 0x7fffff) << 23; + for (k = 177; k >= 0; k--) { + for (i = 89; i >= 0; i--) { + j = k - i; + if (j >= 90) + break; + if (j < 0) + continue; + + c += ((int64_t)a[i]) * b[j]; + } + r[k + 2] += c >> 46; + r[k + 1] = (c >> 23) & 0x7fffff; + c = (c & 0x7fffff) << 23; + } + r[0] = (sp_digit)(c >> 23); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_2048_sqr_90(sp_digit* r, const sp_digit* a) +{ + int i, j, k; + int64_t c; + + c = ((int64_t)a[89]) * a[89]; + r[179] = (sp_digit)(c >> 23); + c = (c & 0x7fffff) << 23; + for (k = 177; k >= 0; k--) { + for (i = 89; i >= 0; i--) { + j = k - i; + if (j >= 90 || i <= j) + break; + if (j < 0) + continue; + + c += ((int64_t)a[i]) * a[j] * 2; + } + if (i == j) + c += ((int64_t)a[i]) * a[i]; + + r[k + 2] += c >> 46; + r[k + 1] = (c >> 23) & 0x7fffff; + c = (c & 0x7fffff) << 23; + } + r[0] = (sp_digit)(c >> 23); +} + +#endif /* WOLFSSL_SP_SMALL */ +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_2048_add_45(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 45; i++) + r[i] = a[i] + b[i]; + + return 0; +} +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_2048_sub_45(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 45; i++) + r[i] = a[i] - b[i]; + + return 0; +} + +#else +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_2048_sub_45(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 40; i += 8) { + r[i + 0] = a[i + 0] - b[i + 0]; + r[i + 1] = a[i + 1] - b[i + 1]; + r[i + 2] = a[i + 2] - b[i + 2]; + r[i + 3] = a[i + 3] - b[i + 3]; + r[i + 4] = a[i + 4] - b[i + 4]; + r[i + 5] = a[i + 5] - b[i + 5]; + r[i + 6] = a[i + 6] - b[i + 6]; + r[i + 7] = a[i + 7] - b[i + 7]; + } + r[40] = a[40] - b[40]; + r[41] = a[41] - b[41]; + r[42] = a[42] - b[42]; + r[43] = a[43] - b[43]; + r[44] = a[44] - b[44]; + + return 0; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_2048_mul_45(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i, j, k; + int64_t c; + + c = ((int64_t)a[44]) * b[44]; + r[89] = (sp_digit)(c >> 23); + c = (c & 0x7fffff) << 23; + for (k = 87; k >= 0; k--) { + for (i = 44; i >= 0; i--) { + j = k - i; + if (j >= 45) + break; + if (j < 0) + continue; + + c += ((int64_t)a[i]) * b[j]; + } + r[k + 2] += c >> 46; + r[k + 1] = (c >> 23) & 0x7fffff; + c = (c & 0x7fffff) << 23; + } + r[0] = (sp_digit)(c >> 23); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_2048_sqr_45(sp_digit* r, const sp_digit* a) +{ + int i, j, k; + int64_t c; + + c = ((int64_t)a[44]) * a[44]; + r[89] = (sp_digit)(c >> 23); + c = (c & 0x7fffff) << 23; + for (k = 87; k >= 0; k--) { + for (i = 44; i >= 0; i--) { + j = k - i; + if (j >= 45 || i <= j) + break; + if (j < 0) + continue; + + c += ((int64_t)a[i]) * a[j] * 2; + } + if (i == j) + c += ((int64_t)a[i]) * a[i]; + + r[k + 2] += c >> 46; + r[k + 1] = (c >> 23) & 0x7fffff; + c = (c & 0x7fffff) << 23; + } + r[0] = (sp_digit)(c >> 23); +} + +#endif /* WOLFSSL_SP_SMALL */ +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +/* Caclulate the bottom digit of -1/a mod 2^n. + * + * a A single precision number. + * rho Bottom word of inverse. + */ +static void sp_2048_mont_setup(sp_digit* a, sp_digit* rho) +{ + sp_digit x, b; + + b = a[0]; + x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ + x *= 2 - b * x; /* here x*a==1 mod 2**8 */ + x *= 2 - b * x; /* here x*a==1 mod 2**16 */ + x *= 2 - b * x; /* here x*a==1 mod 2**32 */ + x &= 0x7fffff; + + /* rho = -1/m mod b */ + *rho = (1L << 23) - x; +} + +/* Multiply a by scalar b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +SP_NOINLINE static void sp_2048_mul_d_90(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int64_t tb = b; + int64_t t = 0; + int i; + + for (i = 0; i < 90; i++) { + t += tb * a[i]; + r[i] = t & 0x7fffff; + t >>= 23; + } + r[90] = (sp_digit)t; +#else + int64_t tb = b; + int64_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] = t[0] & 0x7fffff; + for (i = 0; i < 88; i += 8) { + t[1] = tb * a[i+1]; + r[i+1] = (sp_digit)(t[0] >> 23) + (t[1] & 0x7fffff); + t[2] = tb * a[i+2]; + r[i+2] = (sp_digit)(t[1] >> 23) + (t[2] & 0x7fffff); + t[3] = tb * a[i+3]; + r[i+3] = (sp_digit)(t[2] >> 23) + (t[3] & 0x7fffff); + t[4] = tb * a[i+4]; + r[i+4] = (sp_digit)(t[3] >> 23) + (t[4] & 0x7fffff); + t[5] = tb * a[i+5]; + r[i+5] = (sp_digit)(t[4] >> 23) + (t[5] & 0x7fffff); + t[6] = tb * a[i+6]; + r[i+6] = (sp_digit)(t[5] >> 23) + (t[6] & 0x7fffff); + t[7] = tb * a[i+7]; + r[i+7] = (sp_digit)(t[6] >> 23) + (t[7] & 0x7fffff); + t[0] = tb * a[i+8]; + r[i+8] = (sp_digit)(t[7] >> 23) + (t[0] & 0x7fffff); + } + t[1] = tb * a[89]; + r[89] = (sp_digit)(t[0] >> 23) + (t[1] & 0x7fffff); + r[90] = (sp_digit)(t[1] >> 23); +#endif /* WOLFSSL_SP_SMALL */ +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +/* r = 2^n mod m where n is the number of bits to reduce by. + * Given m must be 2048 bits, just need to subtract. + * + * r A single precision number. + * m A signle precision number. + */ +static void sp_2048_mont_norm_45(sp_digit* r, sp_digit* m) +{ + /* Set r = 2^n - 1. */ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<44; i++) + r[i] = 0x7fffff; +#else + int i; + + for (i = 0; i < 40; i += 8) { + r[i + 0] = 0x7fffff; + r[i + 1] = 0x7fffff; + r[i + 2] = 0x7fffff; + r[i + 3] = 0x7fffff; + r[i + 4] = 0x7fffff; + r[i + 5] = 0x7fffff; + r[i + 6] = 0x7fffff; + r[i + 7] = 0x7fffff; + } + r[40] = 0x7fffff; + r[41] = 0x7fffff; + r[42] = 0x7fffff; + r[43] = 0x7fffff; +#endif + r[44] = 0xfffl; + + /* r = (2^n - 1) mod n */ + sp_2048_sub_45(r, r, m); + + /* Add one so r = 2^n mod m */ + r[0] += 1; +} + +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +static sp_digit sp_2048_cmp_45(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = 0; +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=44; i>=0; i--) + r |= (a[i] - b[i]) & (0 - !r); +#else + int i; + + r |= (a[44] - b[44]) & (0 - !r); + r |= (a[43] - b[43]) & (0 - !r); + r |= (a[42] - b[42]) & (0 - !r); + r |= (a[41] - b[41]) & (0 - !r); + r |= (a[40] - b[40]) & (0 - !r); + for (i = 32; i >= 0; i -= 8) { + r |= (a[i + 7] - b[i + 7]) & (0 - !r); + r |= (a[i + 6] - b[i + 6]) & (0 - !r); + r |= (a[i + 5] - b[i + 5]) & (0 - !r); + r |= (a[i + 4] - b[i + 4]) & (0 - !r); + r |= (a[i + 3] - b[i + 3]) & (0 - !r); + r |= (a[i + 2] - b[i + 2]) & (0 - !r); + r |= (a[i + 1] - b[i + 1]) & (0 - !r); + r |= (a[i + 0] - b[i + 0]) & (0 - !r); + } +#endif /* WOLFSSL_SP_SMALL */ + + return r; +} + +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +static void sp_2048_cond_sub_45(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i = 0; i < 45; i++) + r[i] = a[i] - (b[i] & m); +#else + int i; + + for (i = 0; i < 40; i += 8) { + r[i + 0] = a[i + 0] - (b[i + 0] & m); + r[i + 1] = a[i + 1] - (b[i + 1] & m); + r[i + 2] = a[i + 2] - (b[i + 2] & m); + r[i + 3] = a[i + 3] - (b[i + 3] & m); + r[i + 4] = a[i + 4] - (b[i + 4] & m); + r[i + 5] = a[i + 5] - (b[i + 5] & m); + r[i + 6] = a[i + 6] - (b[i + 6] & m); + r[i + 7] = a[i + 7] - (b[i + 7] & m); + } + r[40] = a[40] - (b[40] & m); + r[41] = a[41] - (b[41] & m); + r[42] = a[42] - (b[42] & m); + r[43] = a[43] - (b[43] & m); + r[44] = a[44] - (b[44] & m); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Mul a by scalar b and add into r. (r += a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +SP_NOINLINE static void sp_2048_mul_add_45(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int64_t tb = b; + int64_t t = 0; + int i; + + for (i = 0; i < 45; i++) { + t += (tb * a[i]) + r[i]; + r[i] = t & 0x7fffff; + t >>= 23; + } + r[45] += t; +#else + int64_t tb = b; + int64_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] += t[0] & 0x7fffff; + for (i = 0; i < 40; i += 8) { + t[1] = tb * a[i+1]; + r[i+1] += (t[0] >> 23) + (t[1] & 0x7fffff); + t[2] = tb * a[i+2]; + r[i+2] += (t[1] >> 23) + (t[2] & 0x7fffff); + t[3] = tb * a[i+3]; + r[i+3] += (t[2] >> 23) + (t[3] & 0x7fffff); + t[4] = tb * a[i+4]; + r[i+4] += (t[3] >> 23) + (t[4] & 0x7fffff); + t[5] = tb * a[i+5]; + r[i+5] += (t[4] >> 23) + (t[5] & 0x7fffff); + t[6] = tb * a[i+6]; + r[i+6] += (t[5] >> 23) + (t[6] & 0x7fffff); + t[7] = tb * a[i+7]; + r[i+7] += (t[6] >> 23) + (t[7] & 0x7fffff); + t[0] = tb * a[i+8]; + r[i+8] += (t[7] >> 23) + (t[0] & 0x7fffff); + } + t[1] = tb * a[41]; r[41] += (t[0] >> 23) + (t[1] & 0x7fffff); + t[2] = tb * a[42]; r[42] += (t[1] >> 23) + (t[2] & 0x7fffff); + t[3] = tb * a[43]; r[43] += (t[2] >> 23) + (t[3] & 0x7fffff); + t[4] = tb * a[44]; r[44] += (t[3] >> 23) + (t[4] & 0x7fffff); + r[45] += t[4] >> 23; +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Normalize the values in each word to 23. + * + * a Array of sp_digit to normalize. + */ +static void sp_2048_norm_45(sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + for (i = 0; i < 44; i++) { + a[i+1] += a[i] >> 23; + a[i] &= 0x7fffff; + } +#else + int i; + for (i = 0; i < 40; i += 8) { + a[i+1] += a[i+0] >> 23; a[i+0] &= 0x7fffff; + a[i+2] += a[i+1] >> 23; a[i+1] &= 0x7fffff; + a[i+3] += a[i+2] >> 23; a[i+2] &= 0x7fffff; + a[i+4] += a[i+3] >> 23; a[i+3] &= 0x7fffff; + a[i+5] += a[i+4] >> 23; a[i+4] &= 0x7fffff; + a[i+6] += a[i+5] >> 23; a[i+5] &= 0x7fffff; + a[i+7] += a[i+6] >> 23; a[i+6] &= 0x7fffff; + a[i+8] += a[i+7] >> 23; a[i+7] &= 0x7fffff; + a[i+9] += a[i+8] >> 23; a[i+8] &= 0x7fffff; + } + a[40+1] += a[40] >> 23; + a[40] &= 0x7fffff; + a[41+1] += a[41] >> 23; + a[41] &= 0x7fffff; + a[42+1] += a[42] >> 23; + a[42] &= 0x7fffff; + a[43+1] += a[43] >> 23; + a[43] &= 0x7fffff; +#endif +} + +/* Shift the result in the high 1024 bits down to the bottom. + * + * r A single precision number. + * a A single precision number. + */ +static void sp_2048_mont_shift_45(sp_digit* r, const sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + int64_t n = a[44] >> 12; + n += ((int64_t)a[45]) << 11; + + for (i = 0; i < 44; i++) { + r[i] = n & 0x7fffff; + n >>= 23; + n += ((int64_t)a[46 + i]) << 11; + } + r[44] = (sp_digit)n; +#else + int i; + int64_t n = a[44] >> 12; + n += ((int64_t)a[45]) << 11; + for (i = 0; i < 40; i += 8) { + r[i + 0] = n & 0x7fffff; + n >>= 23; n += ((int64_t)a[i + 46]) << 11; + r[i + 1] = n & 0x7fffff; + n >>= 23; n += ((int64_t)a[i + 47]) << 11; + r[i + 2] = n & 0x7fffff; + n >>= 23; n += ((int64_t)a[i + 48]) << 11; + r[i + 3] = n & 0x7fffff; + n >>= 23; n += ((int64_t)a[i + 49]) << 11; + r[i + 4] = n & 0x7fffff; + n >>= 23; n += ((int64_t)a[i + 50]) << 11; + r[i + 5] = n & 0x7fffff; + n >>= 23; n += ((int64_t)a[i + 51]) << 11; + r[i + 6] = n & 0x7fffff; + n >>= 23; n += ((int64_t)a[i + 52]) << 11; + r[i + 7] = n & 0x7fffff; + n >>= 23; n += ((int64_t)a[i + 53]) << 11; + } + r[40] = n & 0x7fffff; n >>= 23; n += ((int64_t)a[86]) << 11; + r[41] = n & 0x7fffff; n >>= 23; n += ((int64_t)a[87]) << 11; + r[42] = n & 0x7fffff; n >>= 23; n += ((int64_t)a[88]) << 11; + r[43] = n & 0x7fffff; n >>= 23; n += ((int64_t)a[89]) << 11; + r[44] = (sp_digit)n; +#endif /* WOLFSSL_SP_SMALL */ + XMEMSET(&r[45], 0, sizeof(*r) * 45); +} + +/* Reduce the number back to 2048 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +static void sp_2048_mont_reduce_45(sp_digit* a, sp_digit* m, sp_digit mp) +{ + int i; + sp_digit mu; + + for (i=0; i<44; i++) { + mu = (a[i] * mp) & 0x7fffff; + sp_2048_mul_add_45(a+i, m, mu); + a[i+1] += a[i] >> 23; + } + mu = (a[i] * mp) & 0xfffl; + sp_2048_mul_add_45(a+i, m, mu); + a[i+1] += a[i] >> 23; + a[i] &= 0x7fffff; + + sp_2048_mont_shift_45(a, a); + sp_2048_cond_sub_45(a, a, m, 0 - ((a[44] >> 12) > 0)); + sp_2048_norm_45(a); +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_2048_mont_mul_45(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_2048_mul_45(r, a, b); + sp_2048_mont_reduce_45(r, m, mp); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_2048_mont_sqr_45(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_2048_sqr_45(r, a); + sp_2048_mont_reduce_45(r, m, mp); +} + +/* Multiply a by scalar b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +SP_NOINLINE static void sp_2048_mul_d_45(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int64_t tb = b; + int64_t t = 0; + int i; + + for (i = 0; i < 45; i++) { + t += tb * a[i]; + r[i] = t & 0x7fffff; + t >>= 23; + } + r[45] = (sp_digit)t; +#else + int64_t tb = b; + int64_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] = t[0] & 0x7fffff; + for (i = 0; i < 40; i += 8) { + t[1] = tb * a[i+1]; + r[i+1] = (sp_digit)(t[0] >> 23) + (t[1] & 0x7fffff); + t[2] = tb * a[i+2]; + r[i+2] = (sp_digit)(t[1] >> 23) + (t[2] & 0x7fffff); + t[3] = tb * a[i+3]; + r[i+3] = (sp_digit)(t[2] >> 23) + (t[3] & 0x7fffff); + t[4] = tb * a[i+4]; + r[i+4] = (sp_digit)(t[3] >> 23) + (t[4] & 0x7fffff); + t[5] = tb * a[i+5]; + r[i+5] = (sp_digit)(t[4] >> 23) + (t[5] & 0x7fffff); + t[6] = tb * a[i+6]; + r[i+6] = (sp_digit)(t[5] >> 23) + (t[6] & 0x7fffff); + t[7] = tb * a[i+7]; + r[i+7] = (sp_digit)(t[6] >> 23) + (t[7] & 0x7fffff); + t[0] = tb * a[i+8]; + r[i+8] = (sp_digit)(t[7] >> 23) + (t[0] & 0x7fffff); + } + t[1] = tb * a[41]; + r[41] = (sp_digit)(t[0] >> 23) + (t[1] & 0x7fffff); + t[2] = tb * a[42]; + r[42] = (sp_digit)(t[1] >> 23) + (t[2] & 0x7fffff); + t[3] = tb * a[43]; + r[43] = (sp_digit)(t[2] >> 23) + (t[3] & 0x7fffff); + t[4] = tb * a[44]; + r[44] = (sp_digit)(t[3] >> 23) + (t[4] & 0x7fffff); + r[45] = (sp_digit)(t[4] >> 23); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Conditionally add a and b using the mask m. + * m is -1 to add and 0 when not. + * + * r A single precision number representing conditional add result. + * a A single precision number to add with. + * b A single precision number to add. + * m Mask value to apply. + */ +static void sp_2048_cond_add_45(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i = 0; i < 45; i++) + r[i] = a[i] + (b[i] & m); +#else + int i; + + for (i = 0; i < 40; i += 8) { + r[i + 0] = a[i + 0] + (b[i + 0] & m); + r[i + 1] = a[i + 1] + (b[i + 1] & m); + r[i + 2] = a[i + 2] + (b[i + 2] & m); + r[i + 3] = a[i + 3] + (b[i + 3] & m); + r[i + 4] = a[i + 4] + (b[i + 4] & m); + r[i + 5] = a[i + 5] + (b[i + 5] & m); + r[i + 6] = a[i + 6] + (b[i + 6] & m); + r[i + 7] = a[i + 7] + (b[i + 7] & m); + } + r[40] = a[40] + (b[40] & m); + r[41] = a[41] + (b[41] & m); + r[42] = a[42] + (b[42] & m); + r[43] = a[43] + (b[43] & m); + r[44] = a[44] + (b[44] & m); +#endif /* WOLFSSL_SP_SMALL */ +} + +#ifdef WOLFSSL_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_2048_add_45(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 45; i++) + r[i] = a[i] + b[i]; + + return 0; +} +#endif +SP_NOINLINE static void sp_2048_rshift_45(sp_digit* r, sp_digit* a, byte n) +{ + int i; + +#ifdef WOLFSSL_SP_SMALL + for (i=0; i<44; i++) + r[i] = ((a[i] >> n) | (a[i + 1] << (23 - n))) & 0x7fffff; +#else + for (i=0; i<40; i += 8) { + r[i+0] = ((a[i+0] >> n) | (a[i+1] << (23 - n))) & 0x7fffff; + r[i+1] = ((a[i+1] >> n) | (a[i+2] << (23 - n))) & 0x7fffff; + r[i+2] = ((a[i+2] >> n) | (a[i+3] << (23 - n))) & 0x7fffff; + r[i+3] = ((a[i+3] >> n) | (a[i+4] << (23 - n))) & 0x7fffff; + r[i+4] = ((a[i+4] >> n) | (a[i+5] << (23 - n))) & 0x7fffff; + r[i+5] = ((a[i+5] >> n) | (a[i+6] << (23 - n))) & 0x7fffff; + r[i+6] = ((a[i+6] >> n) | (a[i+7] << (23 - n))) & 0x7fffff; + r[i+7] = ((a[i+7] >> n) | (a[i+8] << (23 - n))) & 0x7fffff; + } + r[40] = ((a[40] >> n) | (a[41] << (23 - n))) & 0x7fffff; + r[41] = ((a[41] >> n) | (a[42] << (23 - n))) & 0x7fffff; + r[42] = ((a[42] >> n) | (a[43] << (23 - n))) & 0x7fffff; + r[43] = ((a[43] >> n) | (a[44] << (23 - n))) & 0x7fffff; +#endif + r[44] = a[44] >> n; +} + +#ifdef WOLFSSL_SP_DIV_32 +static WC_INLINE sp_digit sp_2048_div_word_45(sp_digit d1, sp_digit d0, + sp_digit div) +{ + sp_digit d, r, t; + + /* All 23 bits from d1 and top 8 bits from d0. */ + d = (d1 << 8) | (d0 >> 15); + r = d / div; + d -= r * div; + /* Up to 9 bits in r */ + /* Next 8 bits from d0. */ + r <<= 8; + d <<= 8; + d |= (d0 >> 7) & ((1 << 8) - 1); + t = d / div; + d -= t * div; + r += t; + /* Up to 17 bits in r */ + /* Remaining 7 bits from d0. */ + r <<= 7; + d <<= 7; + d |= d0 & ((1 << 7) - 1); + t = d / div; + r += t; + + return r; +} +#endif /* WOLFSSL_SP_DIV_32 */ + +/* Normalize the values in each word to 23. + * + * a Array of sp_digit to normalize. + */ +static void sp_2048_norm_90(sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + for (i = 0; i < 89; i++) { + a[i+1] += a[i] >> 23; + a[i] &= 0x7fffff; + } +#else + int i; + for (i = 0; i < 88; i += 8) { + a[i+1] += a[i+0] >> 23; a[i+0] &= 0x7fffff; + a[i+2] += a[i+1] >> 23; a[i+1] &= 0x7fffff; + a[i+3] += a[i+2] >> 23; a[i+2] &= 0x7fffff; + a[i+4] += a[i+3] >> 23; a[i+3] &= 0x7fffff; + a[i+5] += a[i+4] >> 23; a[i+4] &= 0x7fffff; + a[i+6] += a[i+5] >> 23; a[i+5] &= 0x7fffff; + a[i+7] += a[i+6] >> 23; a[i+6] &= 0x7fffff; + a[i+8] += a[i+7] >> 23; a[i+7] &= 0x7fffff; + a[i+9] += a[i+8] >> 23; a[i+8] &= 0x7fffff; + } + a[88+1] += a[88] >> 23; + a[88] &= 0x7fffff; +#endif +} + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. + */ +static int sp_2048_div_45(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + int i; +#ifndef WOLFSSL_SP_DIV_32 + int64_t d1; +#endif + sp_digit div, r1; +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* td; +#else + sp_digit t1d[90 + 1], t2d[45 + 1], sdd[45 + 1]; +#endif + sp_digit* t1; + sp_digit* t2; + sp_digit* sd; + int err = MP_OKAY; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 45 + 3), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td != NULL) { + t1 = td; + t2 = td + 90 + 1; + sd = t2 + 45 + 1; + } + else + err = MEMORY_E; +#else + t1 = t1d; + t2 = t2d; + sd = sdd; +#endif + + (void)m; + + if (err == MP_OKAY) { + sp_2048_mul_d_45(sd, d, 1 << 11); + sp_2048_norm_90(a); + sp_2048_mul_d_90(t1, a, 1 << 11); + div = sd[44]; + for (i=45; i>=0; i--) { + t1[45 + i] += t1[45 + i - 1] >> 23; + t1[45 + i - 1] &= 0x7fffff; +#ifndef WOLFSSL_SP_DIV_32 + d1 = t1[45 + i]; + d1 <<= 23; + d1 += t1[45 + i - 1]; + r1 = (sp_digit)(d1 / div); +#else + r1 = sp_2048_div_word_45(t1[45 + i], t1[45 + i - 1], div); +#endif + + sp_2048_mul_d_45(t2, sd, r1); + sp_2048_sub_45(&t1[i], &t1[i], t2); + t1[45 + i] -= t2[45]; + t1[45 + i] += t1[45 + i - 1] >> 23; + t1[45 + i - 1] &= 0x7fffff; + r1 = (((-t1[45 + i]) << 23) - t1[45 + i - 1]) / div; + r1 -= t1[45 + i]; + sp_2048_mul_d_45(t2, sd, r1); + sp_2048_add_45(&t1[i], &t1[i], t2); + t1[45 + i] += t1[45 + i - 1] >> 23; + t1[45 + i - 1] &= 0x7fffff; + } + t1[45 - 1] += t1[45 - 2] >> 23; + t1[45 - 2] &= 0x7fffff; + r1 = t1[45 - 1] / div; + + sp_2048_mul_d_45(t2, sd, r1); + sp_2048_sub_45(t1, t1, t2); + XMEMCPY(r, t1, sizeof(*r) * 2 * 45); + for (i=0; i<43; i++) { + r[i+1] += r[i] >> 23; + r[i] &= 0x7fffff; + } + sp_2048_cond_add_45(r, r, sd, 0 - (r[44] < 0)); + } + + sp_2048_norm_45(r); + sp_2048_rshift_45(r, r, 11); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. + */ +static int sp_2048_mod_45(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_2048_div_45(a, m, NULL, r); +} + +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_2048_mod_exp_45(sp_digit* r, sp_digit* a, sp_digit* e, int bits, + sp_digit* m, int reduceA) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* td; + sp_digit* t[3]; + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + + td = (sp_digit*)XMALLOC(sizeof(*td) * 3 * 45 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + XMEMSET(td, 0, sizeof(*td) * 3 * 45 * 2); + + norm = t[0] = td; + t[1] = &td[45 * 2]; + t[2] = &td[2 * 45 * 2]; + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_45(norm, m); + + if (reduceA) + err = sp_2048_mod_45(t[1], a, m); + else + XMEMCPY(t[1], a, sizeof(sp_digit) * 45); + } + if (err == MP_OKAY) { + sp_2048_mul_45(t[1], t[1], norm); + err = sp_2048_mod_45(t[1], t[1], m); + } + + if (err == MP_OKAY) { + i = bits / 23; + c = bits % 23; + n = e[i--] << (23 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = e[i--]; + c = 23; + } + + y = (n >> 22) & 1; + n <<= 1; + + sp_2048_mont_mul_45(t[y^1], t[0], t[1], m, mp); + + XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), + sizeof(*t[2]) * 45 * 2); + sp_2048_mont_sqr_45(t[2], t[2], m, mp); + XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), t[2], + sizeof(*t[2]) * 45 * 2); + } + + sp_2048_mont_reduce_45(t[0], m, mp); + n = sp_2048_cmp_45(t[0], m); + sp_2048_cond_sub_45(t[0], t[0], m, (n < 0) - 1); + XMEMCPY(r, t[0], sizeof(*r) * 45 * 2); + + } + + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return err; +#elif defined(WOLFSSL_SP_CACHE_RESISTANT) +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[3][90]; +#else + sp_digit* td; + sp_digit* t[3]; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(*td) * 3 * 45 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + t[0] = td; + t[1] = &td[45 * 2]; + t[2] = &td[2 * 45 * 2]; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_45(norm, m); + + if (reduceA) { + err = sp_2048_mod_45(t[1], a, m); + if (err == MP_OKAY) { + sp_2048_mul_45(t[1], t[1], norm); + err = sp_2048_mod_45(t[1], t[1], m); + } + } + else { + sp_2048_mul_45(t[1], a, norm); + err = sp_2048_mod_45(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + i = bits / 23; + c = bits % 23; + n = e[i--] << (23 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = e[i--]; + c = 23; + } + + y = (n >> 22) & 1; + n <<= 1; + + sp_2048_mont_mul_45(t[y^1], t[0], t[1], m, mp); + + XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), sizeof(t[2])); + sp_2048_mont_sqr_45(t[2], t[2], m, mp); + XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), t[2], sizeof(t[2])); + } + + sp_2048_mont_reduce_45(t[0], m, mp); + n = sp_2048_cmp_45(t[0], m); + sp_2048_cond_sub_45(t[0], t[0], m, (n < 0) - 1); + XMEMCPY(r, t[0], sizeof(t[0])); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +#else +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][90]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit rt[90]; + sp_digit mp = 1; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 90, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<32; i++) + t[i] = td + i * 90; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_45(norm, m); + + if (reduceA) { + err = sp_2048_mod_45(t[1], a, m); + if (err == MP_OKAY) { + sp_2048_mul_45(t[1], t[1], norm); + err = sp_2048_mod_45(t[1], t[1], m); + } + } + else { + sp_2048_mul_45(t[1], a, norm); + err = sp_2048_mod_45(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_2048_mont_sqr_45(t[ 2], t[ 1], m, mp); + sp_2048_mont_mul_45(t[ 3], t[ 2], t[ 1], m, mp); + sp_2048_mont_sqr_45(t[ 4], t[ 2], m, mp); + sp_2048_mont_mul_45(t[ 5], t[ 3], t[ 2], m, mp); + sp_2048_mont_sqr_45(t[ 6], t[ 3], m, mp); + sp_2048_mont_mul_45(t[ 7], t[ 4], t[ 3], m, mp); + sp_2048_mont_sqr_45(t[ 8], t[ 4], m, mp); + sp_2048_mont_mul_45(t[ 9], t[ 5], t[ 4], m, mp); + sp_2048_mont_sqr_45(t[10], t[ 5], m, mp); + sp_2048_mont_mul_45(t[11], t[ 6], t[ 5], m, mp); + sp_2048_mont_sqr_45(t[12], t[ 6], m, mp); + sp_2048_mont_mul_45(t[13], t[ 7], t[ 6], m, mp); + sp_2048_mont_sqr_45(t[14], t[ 7], m, mp); + sp_2048_mont_mul_45(t[15], t[ 8], t[ 7], m, mp); + sp_2048_mont_sqr_45(t[16], t[ 8], m, mp); + sp_2048_mont_mul_45(t[17], t[ 9], t[ 8], m, mp); + sp_2048_mont_sqr_45(t[18], t[ 9], m, mp); + sp_2048_mont_mul_45(t[19], t[10], t[ 9], m, mp); + sp_2048_mont_sqr_45(t[20], t[10], m, mp); + sp_2048_mont_mul_45(t[21], t[11], t[10], m, mp); + sp_2048_mont_sqr_45(t[22], t[11], m, mp); + sp_2048_mont_mul_45(t[23], t[12], t[11], m, mp); + sp_2048_mont_sqr_45(t[24], t[12], m, mp); + sp_2048_mont_mul_45(t[25], t[13], t[12], m, mp); + sp_2048_mont_sqr_45(t[26], t[13], m, mp); + sp_2048_mont_mul_45(t[27], t[14], t[13], m, mp); + sp_2048_mont_sqr_45(t[28], t[14], m, mp); + sp_2048_mont_mul_45(t[29], t[15], t[14], m, mp); + sp_2048_mont_sqr_45(t[30], t[15], m, mp); + sp_2048_mont_mul_45(t[31], t[16], t[15], m, mp); + + bits = ((bits + 4) / 5) * 5; + i = ((bits + 22) / 23) - 1; + c = bits % 23; + if (c == 0) + c = 23; + if (i < 45) + n = e[i--] << (32 - c); + else { + n = 0; + i--; + } + if (c < 5) { + n |= e[i--] << (9 - c); + c += 23; + } + y = (n >> 27) & 0x1f; + n <<= 5; + c -= 5; + XMEMCPY(rt, t[y], sizeof(rt)); + for (; i>=0 || c>=5; ) { + if (c < 5) { + n |= e[i--] << (9 - c); + c += 23; + } + y = (n >> 27) & 0x1f; + n <<= 5; + c -= 5; + + sp_2048_mont_sqr_45(rt, rt, m, mp); + sp_2048_mont_sqr_45(rt, rt, m, mp); + sp_2048_mont_sqr_45(rt, rt, m, mp); + sp_2048_mont_sqr_45(rt, rt, m, mp); + sp_2048_mont_sqr_45(rt, rt, m, mp); + + sp_2048_mont_mul_45(rt, rt, t[y], m, mp); + } + + sp_2048_mont_reduce_45(rt, m, mp); + n = sp_2048_cmp_45(rt, m); + sp_2048_cond_sub_45(rt, rt, m, (n < 0) - 1); + XMEMCPY(r, rt, sizeof(rt)); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +#endif +} + +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +/* r = 2^n mod m where n is the number of bits to reduce by. + * Given m must be 2048 bits, just need to subtract. + * + * r A single precision number. + * m A signle precision number. + */ +static void sp_2048_mont_norm_90(sp_digit* r, sp_digit* m) +{ + /* Set r = 2^n - 1. */ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<89; i++) + r[i] = 0x7fffff; +#else + int i; + + for (i = 0; i < 88; i += 8) { + r[i + 0] = 0x7fffff; + r[i + 1] = 0x7fffff; + r[i + 2] = 0x7fffff; + r[i + 3] = 0x7fffff; + r[i + 4] = 0x7fffff; + r[i + 5] = 0x7fffff; + r[i + 6] = 0x7fffff; + r[i + 7] = 0x7fffff; + } + r[88] = 0x7fffff; +#endif + r[89] = 0x1l; + + /* r = (2^n - 1) mod n */ + sp_2048_sub_90(r, r, m); + + /* Add one so r = 2^n mod m */ + r[0] += 1; +} + +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +static sp_digit sp_2048_cmp_90(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = 0; +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=89; i>=0; i--) + r |= (a[i] - b[i]) & (0 - !r); +#else + int i; + + r |= (a[89] - b[89]) & (0 - !r); + r |= (a[88] - b[88]) & (0 - !r); + for (i = 80; i >= 0; i -= 8) { + r |= (a[i + 7] - b[i + 7]) & (0 - !r); + r |= (a[i + 6] - b[i + 6]) & (0 - !r); + r |= (a[i + 5] - b[i + 5]) & (0 - !r); + r |= (a[i + 4] - b[i + 4]) & (0 - !r); + r |= (a[i + 3] - b[i + 3]) & (0 - !r); + r |= (a[i + 2] - b[i + 2]) & (0 - !r); + r |= (a[i + 1] - b[i + 1]) & (0 - !r); + r |= (a[i + 0] - b[i + 0]) & (0 - !r); + } +#endif /* WOLFSSL_SP_SMALL */ + + return r; +} + +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +static void sp_2048_cond_sub_90(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i = 0; i < 90; i++) + r[i] = a[i] - (b[i] & m); +#else + int i; + + for (i = 0; i < 88; i += 8) { + r[i + 0] = a[i + 0] - (b[i + 0] & m); + r[i + 1] = a[i + 1] - (b[i + 1] & m); + r[i + 2] = a[i + 2] - (b[i + 2] & m); + r[i + 3] = a[i + 3] - (b[i + 3] & m); + r[i + 4] = a[i + 4] - (b[i + 4] & m); + r[i + 5] = a[i + 5] - (b[i + 5] & m); + r[i + 6] = a[i + 6] - (b[i + 6] & m); + r[i + 7] = a[i + 7] - (b[i + 7] & m); + } + r[88] = a[88] - (b[88] & m); + r[89] = a[89] - (b[89] & m); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Mul a by scalar b and add into r. (r += a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +SP_NOINLINE static void sp_2048_mul_add_90(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int64_t tb = b; + int64_t t = 0; + int i; + + for (i = 0; i < 90; i++) { + t += (tb * a[i]) + r[i]; + r[i] = t & 0x7fffff; + t >>= 23; + } + r[90] += t; +#else + int64_t tb = b; + int64_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] += t[0] & 0x7fffff; + for (i = 0; i < 88; i += 8) { + t[1] = tb * a[i+1]; + r[i+1] += (t[0] >> 23) + (t[1] & 0x7fffff); + t[2] = tb * a[i+2]; + r[i+2] += (t[1] >> 23) + (t[2] & 0x7fffff); + t[3] = tb * a[i+3]; + r[i+3] += (t[2] >> 23) + (t[3] & 0x7fffff); + t[4] = tb * a[i+4]; + r[i+4] += (t[3] >> 23) + (t[4] & 0x7fffff); + t[5] = tb * a[i+5]; + r[i+5] += (t[4] >> 23) + (t[5] & 0x7fffff); + t[6] = tb * a[i+6]; + r[i+6] += (t[5] >> 23) + (t[6] & 0x7fffff); + t[7] = tb * a[i+7]; + r[i+7] += (t[6] >> 23) + (t[7] & 0x7fffff); + t[0] = tb * a[i+8]; + r[i+8] += (t[7] >> 23) + (t[0] & 0x7fffff); + } + t[1] = tb * a[89]; r[89] += (t[0] >> 23) + (t[1] & 0x7fffff); + r[90] += t[1] >> 23; +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Shift the result in the high 2048 bits down to the bottom. + * + * r A single precision number. + * a A single precision number. + */ +static void sp_2048_mont_shift_90(sp_digit* r, const sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + int64_t n = a[89] >> 1; + n += ((int64_t)a[90]) << 22; + + for (i = 0; i < 89; i++) { + r[i] = n & 0x7fffff; + n >>= 23; + n += ((int64_t)a[91 + i]) << 22; + } + r[89] = (sp_digit)n; +#else + int i; + int64_t n = a[89] >> 1; + n += ((int64_t)a[90]) << 22; + for (i = 0; i < 88; i += 8) { + r[i + 0] = n & 0x7fffff; + n >>= 23; n += ((int64_t)a[i + 91]) << 22; + r[i + 1] = n & 0x7fffff; + n >>= 23; n += ((int64_t)a[i + 92]) << 22; + r[i + 2] = n & 0x7fffff; + n >>= 23; n += ((int64_t)a[i + 93]) << 22; + r[i + 3] = n & 0x7fffff; + n >>= 23; n += ((int64_t)a[i + 94]) << 22; + r[i + 4] = n & 0x7fffff; + n >>= 23; n += ((int64_t)a[i + 95]) << 22; + r[i + 5] = n & 0x7fffff; + n >>= 23; n += ((int64_t)a[i + 96]) << 22; + r[i + 6] = n & 0x7fffff; + n >>= 23; n += ((int64_t)a[i + 97]) << 22; + r[i + 7] = n & 0x7fffff; + n >>= 23; n += ((int64_t)a[i + 98]) << 22; + } + r[88] = n & 0x7fffff; n >>= 23; n += ((int64_t)a[179]) << 22; + r[89] = (sp_digit)n; +#endif /* WOLFSSL_SP_SMALL */ + XMEMSET(&r[90], 0, sizeof(*r) * 90); +} + +/* Reduce the number back to 2048 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +static void sp_2048_mont_reduce_90(sp_digit* a, sp_digit* m, sp_digit mp) +{ + int i; + sp_digit mu; + +#ifdef WOLFSSL_SP_DH + if (mp != 1) { + for (i=0; i<89; i++) { + mu = (a[i] * mp) & 0x7fffff; + sp_2048_mul_add_90(a+i, m, mu); + a[i+1] += a[i] >> 23; + } + mu = (a[i] * mp) & 0x1l; + sp_2048_mul_add_90(a+i, m, mu); + a[i+1] += a[i] >> 23; + a[i] &= 0x7fffff; + } + else { + for (i=0; i<89; i++) { + mu = a[i] & 0x7fffff; + sp_2048_mul_add_90(a+i, m, mu); + a[i+1] += a[i] >> 23; + } + mu = a[i] & 0x1l; + sp_2048_mul_add_90(a+i, m, mu); + a[i+1] += a[i] >> 23; + a[i] &= 0x7fffff; + } +#else + for (i=0; i<89; i++) { + mu = (a[i] * mp) & 0x7fffff; + sp_2048_mul_add_90(a+i, m, mu); + a[i+1] += a[i] >> 23; + } + mu = (a[i] * mp) & 0x1l; + sp_2048_mul_add_90(a+i, m, mu); + a[i+1] += a[i] >> 23; + a[i] &= 0x7fffff; +#endif + + sp_2048_mont_shift_90(a, a); + sp_2048_cond_sub_90(a, a, m, 0 - ((a[89] >> 1) > 0)); + sp_2048_norm_90(a); +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_2048_mont_mul_90(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_2048_mul_90(r, a, b); + sp_2048_mont_reduce_90(r, m, mp); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_2048_mont_sqr_90(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_2048_sqr_90(r, a); + sp_2048_mont_reduce_90(r, m, mp); +} + +/* Multiply a by scalar b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +SP_NOINLINE static void sp_2048_mul_d_180(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int64_t tb = b; + int64_t t = 0; + int i; + + for (i = 0; i < 180; i++) { + t += tb * a[i]; + r[i] = t & 0x7fffff; + t >>= 23; + } + r[180] = (sp_digit)t; +#else + int64_t tb = b; + int64_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] = t[0] & 0x7fffff; + for (i = 0; i < 176; i += 8) { + t[1] = tb * a[i+1]; + r[i+1] = (sp_digit)(t[0] >> 23) + (t[1] & 0x7fffff); + t[2] = tb * a[i+2]; + r[i+2] = (sp_digit)(t[1] >> 23) + (t[2] & 0x7fffff); + t[3] = tb * a[i+3]; + r[i+3] = (sp_digit)(t[2] >> 23) + (t[3] & 0x7fffff); + t[4] = tb * a[i+4]; + r[i+4] = (sp_digit)(t[3] >> 23) + (t[4] & 0x7fffff); + t[5] = tb * a[i+5]; + r[i+5] = (sp_digit)(t[4] >> 23) + (t[5] & 0x7fffff); + t[6] = tb * a[i+6]; + r[i+6] = (sp_digit)(t[5] >> 23) + (t[6] & 0x7fffff); + t[7] = tb * a[i+7]; + r[i+7] = (sp_digit)(t[6] >> 23) + (t[7] & 0x7fffff); + t[0] = tb * a[i+8]; + r[i+8] = (sp_digit)(t[7] >> 23) + (t[0] & 0x7fffff); + } + t[1] = tb * a[177]; + r[177] = (sp_digit)(t[0] >> 23) + (t[1] & 0x7fffff); + t[2] = tb * a[178]; + r[178] = (sp_digit)(t[1] >> 23) + (t[2] & 0x7fffff); + t[3] = tb * a[179]; + r[179] = (sp_digit)(t[2] >> 23) + (t[3] & 0x7fffff); + r[180] = (sp_digit)(t[3] >> 23); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Conditionally add a and b using the mask m. + * m is -1 to add and 0 when not. + * + * r A single precision number representing conditional add result. + * a A single precision number to add with. + * b A single precision number to add. + * m Mask value to apply. + */ +static void sp_2048_cond_add_90(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i = 0; i < 90; i++) + r[i] = a[i] + (b[i] & m); +#else + int i; + + for (i = 0; i < 88; i += 8) { + r[i + 0] = a[i + 0] + (b[i + 0] & m); + r[i + 1] = a[i + 1] + (b[i + 1] & m); + r[i + 2] = a[i + 2] + (b[i + 2] & m); + r[i + 3] = a[i + 3] + (b[i + 3] & m); + r[i + 4] = a[i + 4] + (b[i + 4] & m); + r[i + 5] = a[i + 5] + (b[i + 5] & m); + r[i + 6] = a[i + 6] + (b[i + 6] & m); + r[i + 7] = a[i + 7] + (b[i + 7] & m); + } + r[88] = a[88] + (b[88] & m); + r[89] = a[89] + (b[89] & m); +#endif /* WOLFSSL_SP_SMALL */ +} + +#ifdef WOLFSSL_SMALL +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_2048_sub_90(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 90; i++) + r[i] = a[i] - b[i]; + + return 0; +} + +#endif +#ifdef WOLFSSL_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_2048_add_90(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 90; i++) + r[i] = a[i] + b[i]; + + return 0; +} +#endif +SP_NOINLINE static void sp_2048_rshift_90(sp_digit* r, sp_digit* a, byte n) +{ + int i; + +#ifdef WOLFSSL_SP_SMALL + for (i=0; i<89; i++) + r[i] = ((a[i] >> n) | (a[i + 1] << (23 - n))) & 0x7fffff; +#else + for (i=0; i<88; i += 8) { + r[i+0] = ((a[i+0] >> n) | (a[i+1] << (23 - n))) & 0x7fffff; + r[i+1] = ((a[i+1] >> n) | (a[i+2] << (23 - n))) & 0x7fffff; + r[i+2] = ((a[i+2] >> n) | (a[i+3] << (23 - n))) & 0x7fffff; + r[i+3] = ((a[i+3] >> n) | (a[i+4] << (23 - n))) & 0x7fffff; + r[i+4] = ((a[i+4] >> n) | (a[i+5] << (23 - n))) & 0x7fffff; + r[i+5] = ((a[i+5] >> n) | (a[i+6] << (23 - n))) & 0x7fffff; + r[i+6] = ((a[i+6] >> n) | (a[i+7] << (23 - n))) & 0x7fffff; + r[i+7] = ((a[i+7] >> n) | (a[i+8] << (23 - n))) & 0x7fffff; + } + r[88] = ((a[88] >> n) | (a[89] << (23 - n))) & 0x7fffff; +#endif + r[89] = a[89] >> n; +} + +#ifdef WOLFSSL_SP_DIV_32 +static WC_INLINE sp_digit sp_2048_div_word_90(sp_digit d1, sp_digit d0, + sp_digit div) +{ + sp_digit d, r, t; + + /* All 23 bits from d1 and top 8 bits from d0. */ + d = (d1 << 8) | (d0 >> 15); + r = d / div; + d -= r * div; + /* Up to 9 bits in r */ + /* Next 8 bits from d0. */ + r <<= 8; + d <<= 8; + d |= (d0 >> 7) & ((1 << 8) - 1); + t = d / div; + d -= t * div; + r += t; + /* Up to 17 bits in r */ + /* Remaining 7 bits from d0. */ + r <<= 7; + d <<= 7; + d |= d0 & ((1 << 7) - 1); + t = d / div; + r += t; + + return r; +} +#endif /* WOLFSSL_SP_DIV_32 */ + +/* Normalize the values in each word to 23. + * + * a Array of sp_digit to normalize. + */ +static void sp_2048_norm_180(sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + for (i = 0; i < 179; i++) { + a[i+1] += a[i] >> 23; + a[i] &= 0x7fffff; + } +#else + int i; + for (i = 0; i < 176; i += 8) { + a[i+1] += a[i+0] >> 23; a[i+0] &= 0x7fffff; + a[i+2] += a[i+1] >> 23; a[i+1] &= 0x7fffff; + a[i+3] += a[i+2] >> 23; a[i+2] &= 0x7fffff; + a[i+4] += a[i+3] >> 23; a[i+3] &= 0x7fffff; + a[i+5] += a[i+4] >> 23; a[i+4] &= 0x7fffff; + a[i+6] += a[i+5] >> 23; a[i+5] &= 0x7fffff; + a[i+7] += a[i+6] >> 23; a[i+6] &= 0x7fffff; + a[i+8] += a[i+7] >> 23; a[i+7] &= 0x7fffff; + a[i+9] += a[i+8] >> 23; a[i+8] &= 0x7fffff; + } + a[176+1] += a[176] >> 23; + a[176] &= 0x7fffff; + a[177+1] += a[177] >> 23; + a[177] &= 0x7fffff; + a[178+1] += a[178] >> 23; + a[178] &= 0x7fffff; +#endif +} + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. + */ +static int sp_2048_div_90(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + int i; +#ifndef WOLFSSL_SP_DIV_32 + int64_t d1; +#endif + sp_digit div, r1; +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* td; +#else + sp_digit t1d[180 + 1], t2d[90 + 1], sdd[90 + 1]; +#endif + sp_digit* t1; + sp_digit* t2; + sp_digit* sd; + int err = MP_OKAY; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 90 + 3), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td != NULL) { + t1 = td; + t2 = td + 180 + 1; + sd = t2 + 90 + 1; + } + else + err = MEMORY_E; +#else + t1 = t1d; + t2 = t2d; + sd = sdd; +#endif + + (void)m; + + if (err == MP_OKAY) { + sp_2048_mul_d_90(sd, d, 1 << 22); + sp_2048_norm_180(a); + sp_2048_mul_d_180(t1, a, 1 << 22); + div = sd[89]; + for (i=90; i>=0; i--) { + t1[90 + i] += t1[90 + i - 1] >> 23; + t1[90 + i - 1] &= 0x7fffff; +#ifndef WOLFSSL_SP_DIV_32 + d1 = t1[90 + i]; + d1 <<= 23; + d1 += t1[90 + i - 1]; + r1 = (sp_digit)(d1 / div); +#else + r1 = sp_2048_div_word_90(t1[90 + i], t1[90 + i - 1], div); +#endif + + sp_2048_mul_d_90(t2, sd, r1); + sp_2048_sub_90(&t1[i], &t1[i], t2); + t1[90 + i] -= t2[90]; + t1[90 + i] += t1[90 + i - 1] >> 23; + t1[90 + i - 1] &= 0x7fffff; + r1 = (((-t1[90 + i]) << 23) - t1[90 + i - 1]) / div; + r1 -= t1[90 + i]; + sp_2048_mul_d_90(t2, sd, r1); + sp_2048_add_90(&t1[i], &t1[i], t2); + t1[90 + i] += t1[90 + i - 1] >> 23; + t1[90 + i - 1] &= 0x7fffff; + } + t1[90 - 1] += t1[90 - 2] >> 23; + t1[90 - 2] &= 0x7fffff; + r1 = t1[90 - 1] / div; + + sp_2048_mul_d_90(t2, sd, r1); + sp_2048_sub_90(t1, t1, t2); + XMEMCPY(r, t1, sizeof(*r) * 2 * 90); + for (i=0; i<88; i++) { + r[i+1] += r[i] >> 23; + r[i] &= 0x7fffff; + } + sp_2048_cond_add_90(r, r, sd, 0 - (r[89] < 0)); + } + + sp_2048_norm_90(r); + sp_2048_rshift_90(r, r, 22); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. + */ +static int sp_2048_mod_90(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_2048_div_90(a, m, NULL, r); +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \ + defined(WOLFSSL_HAVE_SP_DH) +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_2048_mod_exp_90(sp_digit* r, sp_digit* a, sp_digit* e, int bits, + sp_digit* m, int reduceA) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* td; + sp_digit* t[3]; + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + + td = (sp_digit*)XMALLOC(sizeof(*td) * 3 * 90 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + XMEMSET(td, 0, sizeof(*td) * 3 * 90 * 2); + + norm = t[0] = td; + t[1] = &td[90 * 2]; + t[2] = &td[2 * 90 * 2]; + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_90(norm, m); + + if (reduceA) + err = sp_2048_mod_90(t[1], a, m); + else + XMEMCPY(t[1], a, sizeof(sp_digit) * 90); + } + if (err == MP_OKAY) { + sp_2048_mul_90(t[1], t[1], norm); + err = sp_2048_mod_90(t[1], t[1], m); + } + + if (err == MP_OKAY) { + i = bits / 23; + c = bits % 23; + n = e[i--] << (23 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = e[i--]; + c = 23; + } + + y = (n >> 22) & 1; + n <<= 1; + + sp_2048_mont_mul_90(t[y^1], t[0], t[1], m, mp); + + XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), + sizeof(*t[2]) * 90 * 2); + sp_2048_mont_sqr_90(t[2], t[2], m, mp); + XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), t[2], + sizeof(*t[2]) * 90 * 2); + } + + sp_2048_mont_reduce_90(t[0], m, mp); + n = sp_2048_cmp_90(t[0], m); + sp_2048_cond_sub_90(t[0], t[0], m, (n < 0) - 1); + XMEMCPY(r, t[0], sizeof(*r) * 90 * 2); + + } + + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return err; +#elif defined(WOLFSSL_SP_CACHE_RESISTANT) +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[3][180]; +#else + sp_digit* td; + sp_digit* t[3]; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(*td) * 3 * 90 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + t[0] = td; + t[1] = &td[90 * 2]; + t[2] = &td[2 * 90 * 2]; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_90(norm, m); + + if (reduceA) { + err = sp_2048_mod_90(t[1], a, m); + if (err == MP_OKAY) { + sp_2048_mul_90(t[1], t[1], norm); + err = sp_2048_mod_90(t[1], t[1], m); + } + } + else { + sp_2048_mul_90(t[1], a, norm); + err = sp_2048_mod_90(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + i = bits / 23; + c = bits % 23; + n = e[i--] << (23 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = e[i--]; + c = 23; + } + + y = (n >> 22) & 1; + n <<= 1; + + sp_2048_mont_mul_90(t[y^1], t[0], t[1], m, mp); + + XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), sizeof(t[2])); + sp_2048_mont_sqr_90(t[2], t[2], m, mp); + XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), t[2], sizeof(t[2])); + } + + sp_2048_mont_reduce_90(t[0], m, mp); + n = sp_2048_cmp_90(t[0], m); + sp_2048_cond_sub_90(t[0], t[0], m, (n < 0) - 1); + XMEMCPY(r, t[0], sizeof(t[0])); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +#else +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][180]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit rt[180]; + sp_digit mp = 1; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 180, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<32; i++) + t[i] = td + i * 180; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_90(norm, m); + + if (reduceA) { + err = sp_2048_mod_90(t[1], a, m); + if (err == MP_OKAY) { + sp_2048_mul_90(t[1], t[1], norm); + err = sp_2048_mod_90(t[1], t[1], m); + } + } + else { + sp_2048_mul_90(t[1], a, norm); + err = sp_2048_mod_90(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_2048_mont_sqr_90(t[ 2], t[ 1], m, mp); + sp_2048_mont_mul_90(t[ 3], t[ 2], t[ 1], m, mp); + sp_2048_mont_sqr_90(t[ 4], t[ 2], m, mp); + sp_2048_mont_mul_90(t[ 5], t[ 3], t[ 2], m, mp); + sp_2048_mont_sqr_90(t[ 6], t[ 3], m, mp); + sp_2048_mont_mul_90(t[ 7], t[ 4], t[ 3], m, mp); + sp_2048_mont_sqr_90(t[ 8], t[ 4], m, mp); + sp_2048_mont_mul_90(t[ 9], t[ 5], t[ 4], m, mp); + sp_2048_mont_sqr_90(t[10], t[ 5], m, mp); + sp_2048_mont_mul_90(t[11], t[ 6], t[ 5], m, mp); + sp_2048_mont_sqr_90(t[12], t[ 6], m, mp); + sp_2048_mont_mul_90(t[13], t[ 7], t[ 6], m, mp); + sp_2048_mont_sqr_90(t[14], t[ 7], m, mp); + sp_2048_mont_mul_90(t[15], t[ 8], t[ 7], m, mp); + sp_2048_mont_sqr_90(t[16], t[ 8], m, mp); + sp_2048_mont_mul_90(t[17], t[ 9], t[ 8], m, mp); + sp_2048_mont_sqr_90(t[18], t[ 9], m, mp); + sp_2048_mont_mul_90(t[19], t[10], t[ 9], m, mp); + sp_2048_mont_sqr_90(t[20], t[10], m, mp); + sp_2048_mont_mul_90(t[21], t[11], t[10], m, mp); + sp_2048_mont_sqr_90(t[22], t[11], m, mp); + sp_2048_mont_mul_90(t[23], t[12], t[11], m, mp); + sp_2048_mont_sqr_90(t[24], t[12], m, mp); + sp_2048_mont_mul_90(t[25], t[13], t[12], m, mp); + sp_2048_mont_sqr_90(t[26], t[13], m, mp); + sp_2048_mont_mul_90(t[27], t[14], t[13], m, mp); + sp_2048_mont_sqr_90(t[28], t[14], m, mp); + sp_2048_mont_mul_90(t[29], t[15], t[14], m, mp); + sp_2048_mont_sqr_90(t[30], t[15], m, mp); + sp_2048_mont_mul_90(t[31], t[16], t[15], m, mp); + + bits = ((bits + 4) / 5) * 5; + i = ((bits + 22) / 23) - 1; + c = bits % 23; + if (c == 0) + c = 23; + if (i < 90) + n = e[i--] << (32 - c); + else { + n = 0; + i--; + } + if (c < 5) { + n |= e[i--] << (9 - c); + c += 23; + } + y = (n >> 27) & 0x1f; + n <<= 5; + c -= 5; + XMEMCPY(rt, t[y], sizeof(rt)); + for (; i>=0 || c>=5; ) { + if (c < 5) { + n |= e[i--] << (9 - c); + c += 23; + } + y = (n >> 27) & 0x1f; + n <<= 5; + c -= 5; + + sp_2048_mont_sqr_90(rt, rt, m, mp); + sp_2048_mont_sqr_90(rt, rt, m, mp); + sp_2048_mont_sqr_90(rt, rt, m, mp); + sp_2048_mont_sqr_90(rt, rt, m, mp); + sp_2048_mont_sqr_90(rt, rt, m, mp); + + sp_2048_mont_mul_90(rt, rt, t[y], m, mp); + } + + sp_2048_mont_reduce_90(rt, m, mp); + n = sp_2048_cmp_90(rt, m); + sp_2048_cond_sub_90(rt, rt, m, (n < 0) - 1); + XMEMCPY(r, rt, sizeof(rt)); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +#endif +} +#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || */ + /* WOLFSSL_HAVE_SP_DH */ + +#if defined(WOLFSSL_HAVE_SP_RSA) && !defined(SP_RSA_PRIVATE_EXP_D) && \ + !defined(RSA_LOW_MEM) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_2048_mask_45(sp_digit* r, sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<45; i++) + r[i] = a[i] & m; +#else + int i; + + for (i = 0; i < 40; i += 8) { + r[i+0] = a[i+0] & m; + r[i+1] = a[i+1] & m; + r[i+2] = a[i+2] & m; + r[i+3] = a[i+3] & m; + r[i+4] = a[i+4] & m; + r[i+5] = a[i+5] & m; + r[i+6] = a[i+6] & m; + r[i+7] = a[i+7] & m; + } + r[40] = a[40] & m; + r[41] = a[41] & m; + r[42] = a[42] & m; + r[43] = a[43] & m; + r[44] = a[44] & m; +#endif +} + +#endif +#ifdef WOLFSSL_HAVE_SP_RSA +/* RSA public key operation. + * + * in Array of bytes representing the number to exponentiate, base. + * inLen Number of bytes in base. + * em Public exponent. + * mm Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 256 bytes long. + * outLen Number of bytes in result. + * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when + * an array is too long and MEMORY_E when dynamic memory allocation fails. + */ +int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm, + byte* out, word32* outLen) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* d = NULL; + sp_digit* a; + sp_digit* m; + sp_digit* r; + sp_digit* norm; + sp_digit e[1]; + sp_digit mp; + int i; + int err = MP_OKAY; + + if (*outLen < 256) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(em) > 23 || inLen > 256 || + mp_count_bits(mm) != 2048)) + err = MP_READ_E; + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 90 * 5, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + a = d; + r = a + 90 * 2; + m = r + 90 * 2; + norm = r; + + sp_2048_from_bin(a, 90, in, inLen); +#if DIGIT_BIT >= 23 + e[0] = (sp_digit)em->dp[0]; +#else + e[0] = (sp_digit)em->dp[0]; + if (em->used > 1) + e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT; +#endif + if (e[0] == 0) + err = MP_EXPTMOD_E; + } + + if (err == MP_OKAY) { + sp_2048_from_mp(m, 90, mm); + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_90(norm, m); + } + if (err == MP_OKAY) { + sp_2048_mul_90(a, a, norm); + err = sp_2048_mod_90(a, a, m); + } + if (err == MP_OKAY) { + for (i=22; i>=0; i--) + if (e[0] >> i) + break; + + XMEMCPY(r, a, sizeof(sp_digit) * 90 * 2); + for (i--; i>=0; i--) { + sp_2048_mont_sqr_90(r, r, m, mp); + + if (((e[0] >> i) & 1) == 1) + sp_2048_mont_mul_90(r, r, a, m, mp); + } + sp_2048_mont_reduce_90(r, m, mp); + mp = sp_2048_cmp_90(r, m); + sp_2048_cond_sub_90(r, r, m, (mp < 0) - 1); + + sp_2048_to_bin(r, out); + *outLen = 256; + } + + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + + return err; +#else +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit ad[180], md[90], rd[180]; +#else + sp_digit* d = NULL; +#endif + sp_digit* a; + sp_digit* m; + sp_digit* r; + sp_digit e[1]; + int err = MP_OKAY; + + if (*outLen < 256) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(em) > 23 || inLen > 256 || + mp_count_bits(mm) != 2048)) + err = MP_READ_E; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 90 * 5, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + a = d; + r = a + 90 * 2; + m = r + 90 * 2; + } +#else + a = ad; + m = md; + r = rd; +#endif + + if (err == MP_OKAY) { + sp_2048_from_bin(a, 90, in, inLen); +#if DIGIT_BIT >= 23 + e[0] = (sp_digit)em->dp[0]; +#else + e[0] = (sp_digit)em->dp[0]; + if (em->used > 1) + e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT; +#endif + if (e[0] == 0) + err = MP_EXPTMOD_E; + } + if (err == MP_OKAY) { + sp_2048_from_mp(m, 90, mm); + + if (e[0] == 0x3) { + if (err == MP_OKAY) { + sp_2048_sqr_90(r, a); + err = sp_2048_mod_90(r, r, m); + } + if (err == MP_OKAY) { + sp_2048_mul_90(r, a, r); + err = sp_2048_mod_90(r, r, m); + } + } + else { + sp_digit* norm = r; + int i; + sp_digit mp; + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_90(norm, m); + + if (err == MP_OKAY) { + sp_2048_mul_90(a, a, norm); + err = sp_2048_mod_90(a, a, m); + } + + if (err == MP_OKAY) { + for (i=22; i>=0; i--) + if (e[0] >> i) + break; + + XMEMCPY(r, a, sizeof(sp_digit) * 180); + for (i--; i>=0; i--) { + sp_2048_mont_sqr_90(r, r, m, mp); + + if (((e[0] >> i) & 1) == 1) + sp_2048_mont_mul_90(r, r, a, m, mp); + } + sp_2048_mont_reduce_90(r, m, mp); + mp = sp_2048_cmp_90(r, m); + sp_2048_cond_sub_90(r, r, m, (mp < 0) - 1); + } + } + } + + if (err == MP_OKAY) { + sp_2048_to_bin(r, out); + *outLen = 256; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_RSA); +#endif + + return err; +#endif /* WOLFSSL_SP_SMALL */ +} + +#ifndef WOLFSSL_RSA_PUBLIC_ONLY +/* RSA private key operation. + * + * in Array of bytes representing the number to exponentiate, base. + * inLen Number of bytes in base. + * dm Private exponent. + * pm First prime. + * qm Second prime. + * dpm First prime's CRT exponent. + * dqm Second prime's CRT exponent. + * qim Inverse of second prime mod p. + * mm Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 256 bytes long. + * outLen Number of bytes in result. + * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when + * an array is too long and MEMORY_E when dynamic memory allocation fails. + */ +int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, + mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm, + byte* out, word32* outLen) +{ +#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* a; + sp_digit* d = NULL; + sp_digit* m; + sp_digit* r; + int err = MP_OKAY; + + (void)pm; + (void)qm; + (void)dpm; + (void)dqm; + (void)qim; + + if (*outLen < 256) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(dm) > 2048 || inLen > 256 || + mp_count_bits(mm) != 2048)) + err = MP_READ_E; + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 90 * 4, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + a = d + 90; + m = a + 90; + r = a; + + sp_2048_from_bin(a, 90, in, inLen); + sp_2048_from_mp(d, 90, dm); + sp_2048_from_mp(m, 90, mm); + err = sp_2048_mod_exp_90(r, a, d, 2048, m, 0); + } + if (err == MP_OKAY) { + sp_2048_to_bin(r, out); + *outLen = 256; + } + + if (d != NULL) { + XMEMSET(d, 0, sizeof(sp_digit) * 90); + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + } + + return err; +#else + sp_digit a[180], d[90], m[90]; + sp_digit* r = a; + int err = MP_OKAY; + + (void)pm; + (void)qm; + (void)dpm; + (void)dqm; + (void)qim; + + if (*outLen < 256) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(dm) > 2048 || inLen > 256 || + mp_count_bits(mm) != 2048)) + err = MP_READ_E; + + if (err == MP_OKAY) { + sp_2048_from_bin(a, 90, in, inLen); + sp_2048_from_mp(d, 90, dm); + sp_2048_from_mp(m, 90, mm); + err = sp_2048_mod_exp_90(r, a, d, 2048, m, 0); + } + + if (err == MP_OKAY) { + sp_2048_to_bin(r, out); + *outLen = 256; + } + + XMEMSET(d, 0, sizeof(sp_digit) * 90); + + return err; +#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */ +#else +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* t = NULL; + sp_digit* a; + sp_digit* p; + sp_digit* q; + sp_digit* dp; + sp_digit* dq; + sp_digit* qi; + sp_digit* tmp; + sp_digit* tmpa; + sp_digit* tmpb; + sp_digit* r; + int err = MP_OKAY; + + (void)dm; + (void)mm; + + if (*outLen < 256) + err = MP_TO_E; + if (err == MP_OKAY && (inLen > 256 || mp_count_bits(mm) != 2048)) + err = MP_READ_E; + + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 45 * 11, NULL, + DYNAMIC_TYPE_RSA); + if (t == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + a = t; + p = a + 90 * 2; + q = p + 45; + qi = dq = dp = q + 45; + tmpa = qi + 45; + tmpb = tmpa + 90; + + tmp = t; + r = tmp + 90; + + sp_2048_from_bin(a, 90, in, inLen); + sp_2048_from_mp(p, 45, pm); + sp_2048_from_mp(q, 45, qm); + sp_2048_from_mp(dp, 45, dpm); + err = sp_2048_mod_exp_45(tmpa, a, dp, 1024, p, 1); + } + if (err == MP_OKAY) { + sp_2048_from_mp(dq, 45, dqm); + err = sp_2048_mod_exp_45(tmpb, a, dq, 1024, q, 1); + } + if (err == MP_OKAY) { + sp_2048_sub_45(tmpa, tmpa, tmpb); + sp_2048_mask_45(tmp, p, tmpa[44] >> 31); + sp_2048_add_45(tmpa, tmpa, tmp); + + sp_2048_from_mp(qi, 45, qim); + sp_2048_mul_45(tmpa, tmpa, qi); + err = sp_2048_mod_45(tmpa, tmpa, p); + } + + if (err == MP_OKAY) { + sp_2048_mul_45(tmpa, q, tmpa); + sp_2048_add_90(r, tmpb, tmpa); + sp_2048_norm_90(r); + + sp_2048_to_bin(r, out); + *outLen = 256; + } + + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_digit) * 45 * 11); + XFREE(t, NULL, DYNAMIC_TYPE_RSA); + } + + return err; +#else + sp_digit a[90 * 2]; + sp_digit p[45], q[45], dp[45], dq[45], qi[45]; + sp_digit tmp[90], tmpa[90], tmpb[90]; + sp_digit* r = a; + int err = MP_OKAY; + + (void)dm; + (void)mm; + + if (*outLen < 256) + err = MP_TO_E; + if (err == MP_OKAY && (inLen > 256 || mp_count_bits(mm) != 2048)) + err = MP_READ_E; + + if (err == MP_OKAY) { + sp_2048_from_bin(a, 90, in, inLen); + sp_2048_from_mp(p, 45, pm); + sp_2048_from_mp(q, 45, qm); + sp_2048_from_mp(dp, 45, dpm); + sp_2048_from_mp(dq, 45, dqm); + sp_2048_from_mp(qi, 45, qim); + + err = sp_2048_mod_exp_45(tmpa, a, dp, 1024, p, 1); + } + if (err == MP_OKAY) + err = sp_2048_mod_exp_45(tmpb, a, dq, 1024, q, 1); + + if (err == MP_OKAY) { + sp_2048_sub_45(tmpa, tmpa, tmpb); + sp_2048_mask_45(tmp, p, tmpa[44] >> 31); + sp_2048_add_45(tmpa, tmpa, tmp); + sp_2048_mul_45(tmpa, tmpa, qi); + err = sp_2048_mod_45(tmpa, tmpa, p); + } + + if (err == MP_OKAY) { + sp_2048_mul_45(tmpa, tmpa, q); + sp_2048_add_90(r, tmpb, tmpa); + sp_2048_norm_90(r); + + sp_2048_to_bin(r, out); + *outLen = 256; + } + + XMEMSET(tmpa, 0, sizeof(tmpa)); + XMEMSET(tmpb, 0, sizeof(tmpb)); + XMEMSET(p, 0, sizeof(p)); + XMEMSET(q, 0, sizeof(q)); + XMEMSET(dp, 0, sizeof(dp)); + XMEMSET(dq, 0, sizeof(dq)); + XMEMSET(qi, 0, sizeof(qi)); + + return err; +#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */ +#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ +} + +#endif /* !WOLFSSL_RSA_PUBLIC_ONLY */ +#endif /* WOLFSSL_HAVE_SP_RSA */ +#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \ + !defined(WOLFSSL_RSA_PUBLIC_ONLY)) +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_2048_to_mp(sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (2048 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { +#if DIGIT_BIT == 23 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 90); + r->used = 90; + mp_clamp(r); +#elif DIGIT_BIT < 23 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 90; i++) { + r->dp[j] |= a[i] << s; + r->dp[j] &= (1l << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + while (s + DIGIT_BIT <= 23) { + s += DIGIT_BIT; + r->dp[j] &= (1l << DIGIT_BIT) - 1; + r->dp[++j] = a[i] >> s; + } + s = 23 - s; + } + r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 90; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 23 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && DIGIT_BIT != 64 + r->dp[j] &= (1l << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 23 - s; + } + else + s += 23; + } + r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returs 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ +#ifdef WOLFSSL_SP_SMALL + int err = MP_OKAY; + sp_digit* d = NULL; + sp_digit* b; + sp_digit* e; + sp_digit* m; + sp_digit* r; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 2048 || expBits > 2048 || + mp_count_bits(mod) != 2048) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 90 * 4, NULL, DYNAMIC_TYPE_DH); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + b = d; + e = b + 90 * 2; + m = e + 90; + r = b; + + sp_2048_from_mp(b, 90, base); + sp_2048_from_mp(e, 90, exp); + sp_2048_from_mp(m, 90, mod); + + err = sp_2048_mod_exp_90(r, b, e, mp_count_bits(exp), m, 0); + } + + if (err == MP_OKAY) { + err = sp_2048_to_mp(r, res); + } + + if (d != NULL) { + XMEMSET(e, 0, sizeof(sp_digit) * 90); + XFREE(d, NULL, DYNAMIC_TYPE_DH); + } + return err; +#else +#ifndef WOLFSSL_SMALL_STACK + sp_digit bd[180], ed[90], md[90]; +#else + sp_digit* d = NULL; +#endif + sp_digit* b; + sp_digit* e; + sp_digit* m; + sp_digit* r; + int err = MP_OKAY; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 2048 || expBits > 2048 || + mp_count_bits(mod) != 2048) { + err = MP_READ_E; + } + +#ifdef WOLFSSL_SMALL_STACK + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 90 * 4, NULL, DYNAMIC_TYPE_DH); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + b = d; + e = b + 90 * 2; + m = e + 90; + r = b; + } +#else + r = b = bd; + e = ed; + m = md; +#endif + + if (err == MP_OKAY) { + sp_2048_from_mp(b, 90, base); + sp_2048_from_mp(e, 90, exp); + sp_2048_from_mp(m, 90, mod); + + err = sp_2048_mod_exp_90(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + err = sp_2048_to_mp(r, res); + } + + XMEMSET(e, 0, sizeof(sp_digit) * 90); + +#ifdef WOLFSSL_SMALL_STACK + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_DH); +#endif + + return err; +#endif +} + +#ifdef WOLFSSL_HAVE_SP_DH +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. + * exp Array of bytes that is the exponent. + * expLen Length of data, in bytes, in exponent. + * mod Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 256 bytes long. + * outLen Length, in bytes, of exponentiation result. + * returs 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen, + mp_int* mod, byte* out, word32* outLen) +{ +#ifdef WOLFSSL_SP_SMALL + int err = MP_OKAY; + sp_digit* d = NULL; + sp_digit* b; + sp_digit* e; + sp_digit* m; + sp_digit* r; + word32 i; + + if (mp_count_bits(base) > 2048 || expLen > 256 || + mp_count_bits(mod) != 2048) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 90 * 4, NULL, DYNAMIC_TYPE_DH); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + b = d; + e = b + 90 * 2; + m = e + 90; + r = b; + + sp_2048_from_mp(b, 90, base); + sp_2048_from_bin(e, 90, exp, expLen); + sp_2048_from_mp(m, 90, mod); + + err = sp_2048_mod_exp_90(r, b, e, expLen * 8, m, 0); + } + + if (err == MP_OKAY) { + sp_2048_to_bin(r, out); + *outLen = 256; + for (i=0; i<256 && out[i] == 0; i++) { + } + *outLen -= i; + XMEMMOVE(out, out + i, *outLen); + } + + if (d != NULL) { + XMEMSET(e, 0, sizeof(sp_digit) * 90); + XFREE(d, NULL, DYNAMIC_TYPE_DH); + } + return err; +#else +#ifndef WOLFSSL_SMALL_STACK + sp_digit bd[180], ed[90], md[90]; +#else + sp_digit* d = NULL; +#endif + sp_digit* b; + sp_digit* e; + sp_digit* m; + sp_digit* r; + word32 i; + int err = MP_OKAY; + + if (mp_count_bits(base) > 2048 || expLen > 256 || + mp_count_bits(mod) != 2048) { + err = MP_READ_E; + } + +#ifdef WOLFSSL_SMALL_STACK + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 90 * 4, NULL, DYNAMIC_TYPE_DH); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + b = d; + e = b + 90 * 2; + m = e + 90; + r = b; + } +#else + r = b = bd; + e = ed; + m = md; +#endif + + if (err == MP_OKAY) { + sp_2048_from_mp(b, 90, base); + sp_2048_from_bin(e, 90, exp, expLen); + sp_2048_from_mp(m, 90, mod); + + err = sp_2048_mod_exp_90(r, b, e, expLen * 8, m, 0); + } + + if (err == MP_OKAY) { + sp_2048_to_bin(r, out); + *outLen = 256; + for (i=0; i<256 && out[i] == 0; i++) { + } + *outLen -= i; + XMEMMOVE(out, out + i, *outLen); + } + + XMEMSET(e, 0, sizeof(sp_digit) * 90); + +#ifdef WOLFSSL_SMALL_STACK + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_DH); +#endif + + return err; +#endif +} +#endif /* WOLFSSL_HAVE_SP_DH */ + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returs 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ +#ifdef WOLFSSL_SP_SMALL + int err = MP_OKAY; + sp_digit* d = NULL; + sp_digit* b; + sp_digit* e; + sp_digit* m; + sp_digit* r; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 1024 || expBits > 1024 || + mp_count_bits(mod) != 1024) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 45 * 4, NULL, DYNAMIC_TYPE_DH); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + b = d; + e = b + 45 * 2; + m = e + 45; + r = b; + + sp_2048_from_mp(b, 45, base); + sp_2048_from_mp(e, 45, exp); + sp_2048_from_mp(m, 45, mod); + + err = sp_2048_mod_exp_45(r, b, e, mp_count_bits(exp), m, 0); + } + + if (err == MP_OKAY) { + XMEMSET(r + 45, 0, sizeof(*r) * 45); + err = sp_2048_to_mp(r, res); + } + + if (d != NULL) { + XMEMSET(e, 0, sizeof(sp_digit) * 45); + XFREE(d, NULL, DYNAMIC_TYPE_DH); + } + return err; +#else +#ifndef WOLFSSL_SMALL_STACK + sp_digit bd[90], ed[45], md[45]; +#else + sp_digit* d = NULL; +#endif + sp_digit* b; + sp_digit* e; + sp_digit* m; + sp_digit* r; + int err = MP_OKAY; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 1024 || expBits > 1024 || + mp_count_bits(mod) != 1024) { + err = MP_READ_E; + } + +#ifdef WOLFSSL_SMALL_STACK + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 45 * 4, NULL, DYNAMIC_TYPE_DH); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + b = d; + e = b + 45 * 2; + m = e + 45; + r = b; + } +#else + r = b = bd; + e = ed; + m = md; +#endif + + if (err == MP_OKAY) { + sp_2048_from_mp(b, 45, base); + sp_2048_from_mp(e, 45, exp); + sp_2048_from_mp(m, 45, mod); + + err = sp_2048_mod_exp_45(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + XMEMSET(r + 45, 0, sizeof(*r) * 45); + err = sp_2048_to_mp(r, res); + } + + XMEMSET(e, 0, sizeof(sp_digit) * 45); + +#ifdef WOLFSSL_SMALL_STACK + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_DH); +#endif + + return err; +#endif +} + +#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ + +#endif /* !WOLFSSL_SP_NO_2048 */ + +#ifndef WOLFSSL_SP_NO_3072 +/* Read big endian unsigned byte aray into r. + * + * r A single precision integer. + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_3072_from_bin(sp_digit* r, int max, const byte* a, int n) +{ + int i, j = 0, s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= ((sp_digit)a[i]) << s; + if (s >= 15) { + r[j] &= 0x7fffff; + s = 23 - s; + if (j + 1 >= max) + break; + r[++j] = a[i] >> s; + s = 8 - s; + } + else + s += 8; + } + + for (j++; j < max; j++) + r[j] = 0; +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * a A multi-precision integer. + */ +static void sp_3072_from_mp(sp_digit* r, int max, mp_int* a) +{ +#if DIGIT_BIT == 23 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < max; j++) + r[j] = 0; +#elif DIGIT_BIT > 23 + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= a->dp[i] << s; + r[j] &= 0x7fffff; + s = 23 - s; + if (j + 1 >= max) + break; + r[++j] = (sp_digit)(a->dp[i] >> s); + while (s + 23 <= DIGIT_BIT) { + s += 23; + r[j] &= 0x7fffff; + if (j + 1 >= max) + break; + if (s < DIGIT_BIT) + r[++j] = (sp_digit)(a->dp[i] >> s); + else + r[++j] = 0; + } + s = DIGIT_BIT - s; + } + + for (j++; j < max; j++) + r[j] = 0; +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 23) { + r[j] &= 0x7fffff; + if (j + 1 >= max) + break; + s = 23 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else + s += DIGIT_BIT; + } + + for (j++; j < max; j++) + r[j] = 0; +#endif +} + +/* Write r as big endian to byte aray. + * Fixed length number of bytes written: 384 + * + * r A single precision integer. + * a Byte array. + */ +static void sp_3072_to_bin(sp_digit* r, byte* a) +{ + int i, j, s = 0, b; + + for (i=0; i<133; i++) { + r[i+1] += r[i] >> 23; + r[i] &= 0x7fffff; + } + j = 3072 / 8 - 1; + a[j] = 0; + for (i=0; i<134 && j>=0; i++) { + b = 0; + a[j--] |= r[i] << s; b += 8 - s; + if (j < 0) + break; + while (b < 23) { + a[j--] = r[i] >> b; b += 8; + if (j < 0) + break; + } + s = 8 - (b - 23); + if (j >= 0) + a[j] = 0; + if (s != 0) + j++; + } +} + +#ifndef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_3072_mul_67(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i, j; + int64_t t[134]; + + XMEMSET(t, 0, sizeof(t)); + for (i=0; i<67; i++) { + for (j=0; j<67; j++) + t[i+j] += ((int64_t)a[i]) * b[j]; + } + for (i=0; i<133; i++) { + r[i] = t[i] & 0x7fffff; + t[i+1] += t[i] >> 23; + } + r[133] = (sp_digit)t[133]; +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_3072_sqr_67(sp_digit* r, const sp_digit* a) +{ + int i, j; + int64_t t[134]; + + XMEMSET(t, 0, sizeof(t)); + for (i=0; i<67; i++) { + for (j=0; j> 23; + } + r[133] = (sp_digit)t[133]; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_3072_add_67(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 64; i += 8) { + r[i + 0] = a[i + 0] + b[i + 0]; + r[i + 1] = a[i + 1] + b[i + 1]; + r[i + 2] = a[i + 2] + b[i + 2]; + r[i + 3] = a[i + 3] + b[i + 3]; + r[i + 4] = a[i + 4] + b[i + 4]; + r[i + 5] = a[i + 5] + b[i + 5]; + r[i + 6] = a[i + 6] + b[i + 6]; + r[i + 7] = a[i + 7] + b[i + 7]; + } + r[64] = a[64] + b[64]; + r[65] = a[65] + b[65]; + r[66] = a[66] + b[66]; + + return 0; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_3072_add_134(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 128; i += 8) { + r[i + 0] = a[i + 0] + b[i + 0]; + r[i + 1] = a[i + 1] + b[i + 1]; + r[i + 2] = a[i + 2] + b[i + 2]; + r[i + 3] = a[i + 3] + b[i + 3]; + r[i + 4] = a[i + 4] + b[i + 4]; + r[i + 5] = a[i + 5] + b[i + 5]; + r[i + 6] = a[i + 6] + b[i + 6]; + r[i + 7] = a[i + 7] + b[i + 7]; + } + r[128] = a[128] + b[128]; + r[129] = a[129] + b[129]; + r[130] = a[130] + b[130]; + r[131] = a[131] + b[131]; + r[132] = a[132] + b[132]; + r[133] = a[133] + b[133]; + + return 0; +} + +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_3072_sub_134(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 128; i += 8) { + r[i + 0] = a[i + 0] - b[i + 0]; + r[i + 1] = a[i + 1] - b[i + 1]; + r[i + 2] = a[i + 2] - b[i + 2]; + r[i + 3] = a[i + 3] - b[i + 3]; + r[i + 4] = a[i + 4] - b[i + 4]; + r[i + 5] = a[i + 5] - b[i + 5]; + r[i + 6] = a[i + 6] - b[i + 6]; + r[i + 7] = a[i + 7] - b[i + 7]; + } + r[128] = a[128] - b[128]; + r[129] = a[129] - b[129]; + r[130] = a[130] - b[130]; + r[131] = a[131] - b[131]; + r[132] = a[132] - b[132]; + r[133] = a[133] - b[133]; + + return 0; +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_3072_mul_134(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[134]; + sp_digit* a1 = z1; + sp_digit b1[67]; + sp_digit* z2 = r + 134; + sp_3072_add_67(a1, a, &a[67]); + sp_3072_add_67(b1, b, &b[67]); + sp_3072_mul_67(z2, &a[67], &b[67]); + sp_3072_mul_67(z0, a, b); + sp_3072_mul_67(z1, a1, b1); + sp_3072_sub_134(z1, z1, z2); + sp_3072_sub_134(z1, z1, z0); + sp_3072_add_134(r + 67, r + 67, z1); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_3072_sqr_134(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z1[134]; + sp_digit* a1 = z1; + sp_digit* z2 = r + 134; + sp_3072_add_67(a1, a, &a[67]); + sp_3072_sqr_67(z2, &a[67]); + sp_3072_sqr_67(z0, a); + sp_3072_sqr_67(z1, a1); + sp_3072_sub_134(z1, z1, z2); + sp_3072_sub_134(z1, z1, z0); + sp_3072_add_134(r + 67, r + 67, z1); +} + +#endif /* !WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_3072_add_134(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 134; i++) + r[i] = a[i] + b[i]; + + return 0; +} +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_3072_sub_134(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 134; i++) + r[i] = a[i] - b[i]; + + return 0; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_3072_mul_134(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i, j, k; + int64_t c; + + c = ((int64_t)a[133]) * b[133]; + r[267] = (sp_digit)(c >> 23); + c = (c & 0x7fffff) << 23; + for (k = 265; k >= 0; k--) { + for (i = 133; i >= 0; i--) { + j = k - i; + if (j >= 134) + break; + if (j < 0) + continue; + + c += ((int64_t)a[i]) * b[j]; + } + r[k + 2] += c >> 46; + r[k + 1] = (c >> 23) & 0x7fffff; + c = (c & 0x7fffff) << 23; + } + r[0] = (sp_digit)(c >> 23); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_3072_sqr_134(sp_digit* r, const sp_digit* a) +{ + int i, j, k; + int64_t c; + + c = ((int64_t)a[133]) * a[133]; + r[267] = (sp_digit)(c >> 23); + c = (c & 0x7fffff) << 23; + for (k = 265; k >= 0; k--) { + for (i = 133; i >= 0; i--) { + j = k - i; + if (j >= 134 || i <= j) + break; + if (j < 0) + continue; + + c += ((int64_t)a[i]) * a[j] * 2; + } + if (i == j) + c += ((int64_t)a[i]) * a[i]; + + r[k + 2] += c >> 46; + r[k + 1] = (c >> 23) & 0x7fffff; + c = (c & 0x7fffff) << 23; + } + r[0] = (sp_digit)(c >> 23); +} + +#endif /* WOLFSSL_SP_SMALL */ +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_3072_add_67(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 67; i++) + r[i] = a[i] + b[i]; + + return 0; +} +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_3072_sub_67(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 67; i++) + r[i] = a[i] - b[i]; + + return 0; +} + +#else +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_3072_sub_67(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 64; i += 8) { + r[i + 0] = a[i + 0] - b[i + 0]; + r[i + 1] = a[i + 1] - b[i + 1]; + r[i + 2] = a[i + 2] - b[i + 2]; + r[i + 3] = a[i + 3] - b[i + 3]; + r[i + 4] = a[i + 4] - b[i + 4]; + r[i + 5] = a[i + 5] - b[i + 5]; + r[i + 6] = a[i + 6] - b[i + 6]; + r[i + 7] = a[i + 7] - b[i + 7]; + } + r[64] = a[64] - b[64]; + r[65] = a[65] - b[65]; + r[66] = a[66] - b[66]; + + return 0; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_3072_mul_67(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i, j, k; + int64_t c; + + c = ((int64_t)a[66]) * b[66]; + r[133] = (sp_digit)(c >> 23); + c = (c & 0x7fffff) << 23; + for (k = 131; k >= 0; k--) { + for (i = 66; i >= 0; i--) { + j = k - i; + if (j >= 67) + break; + if (j < 0) + continue; + + c += ((int64_t)a[i]) * b[j]; + } + r[k + 2] += c >> 46; + r[k + 1] = (c >> 23) & 0x7fffff; + c = (c & 0x7fffff) << 23; + } + r[0] = (sp_digit)(c >> 23); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_3072_sqr_67(sp_digit* r, const sp_digit* a) +{ + int i, j, k; + int64_t c; + + c = ((int64_t)a[66]) * a[66]; + r[133] = (sp_digit)(c >> 23); + c = (c & 0x7fffff) << 23; + for (k = 131; k >= 0; k--) { + for (i = 66; i >= 0; i--) { + j = k - i; + if (j >= 67 || i <= j) + break; + if (j < 0) + continue; + + c += ((int64_t)a[i]) * a[j] * 2; + } + if (i == j) + c += ((int64_t)a[i]) * a[i]; + + r[k + 2] += c >> 46; + r[k + 1] = (c >> 23) & 0x7fffff; + c = (c & 0x7fffff) << 23; + } + r[0] = (sp_digit)(c >> 23); +} + +#endif /* WOLFSSL_SP_SMALL */ +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +/* Caclulate the bottom digit of -1/a mod 2^n. + * + * a A single precision number. + * rho Bottom word of inverse. + */ +static void sp_3072_mont_setup(sp_digit* a, sp_digit* rho) +{ + sp_digit x, b; + + b = a[0]; + x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ + x *= 2 - b * x; /* here x*a==1 mod 2**8 */ + x *= 2 - b * x; /* here x*a==1 mod 2**16 */ + x *= 2 - b * x; /* here x*a==1 mod 2**32 */ + x &= 0x7fffff; + + /* rho = -1/m mod b */ + *rho = (1L << 23) - x; +} + +/* Multiply a by scalar b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +SP_NOINLINE static void sp_3072_mul_d_134(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int64_t tb = b; + int64_t t = 0; + int i; + + for (i = 0; i < 134; i++) { + t += tb * a[i]; + r[i] = t & 0x7fffff; + t >>= 23; + } + r[134] = (sp_digit)t; +#else + int64_t tb = b; + int64_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] = t[0] & 0x7fffff; + for (i = 0; i < 128; i += 8) { + t[1] = tb * a[i+1]; + r[i+1] = (sp_digit)(t[0] >> 23) + (t[1] & 0x7fffff); + t[2] = tb * a[i+2]; + r[i+2] = (sp_digit)(t[1] >> 23) + (t[2] & 0x7fffff); + t[3] = tb * a[i+3]; + r[i+3] = (sp_digit)(t[2] >> 23) + (t[3] & 0x7fffff); + t[4] = tb * a[i+4]; + r[i+4] = (sp_digit)(t[3] >> 23) + (t[4] & 0x7fffff); + t[5] = tb * a[i+5]; + r[i+5] = (sp_digit)(t[4] >> 23) + (t[5] & 0x7fffff); + t[6] = tb * a[i+6]; + r[i+6] = (sp_digit)(t[5] >> 23) + (t[6] & 0x7fffff); + t[7] = tb * a[i+7]; + r[i+7] = (sp_digit)(t[6] >> 23) + (t[7] & 0x7fffff); + t[0] = tb * a[i+8]; + r[i+8] = (sp_digit)(t[7] >> 23) + (t[0] & 0x7fffff); + } + t[1] = tb * a[129]; + r[129] = (sp_digit)(t[0] >> 23) + (t[1] & 0x7fffff); + t[2] = tb * a[130]; + r[130] = (sp_digit)(t[1] >> 23) + (t[2] & 0x7fffff); + t[3] = tb * a[131]; + r[131] = (sp_digit)(t[2] >> 23) + (t[3] & 0x7fffff); + t[4] = tb * a[132]; + r[132] = (sp_digit)(t[3] >> 23) + (t[4] & 0x7fffff); + t[5] = tb * a[133]; + r[133] = (sp_digit)(t[4] >> 23) + (t[5] & 0x7fffff); + r[134] = (sp_digit)(t[5] >> 23); +#endif /* WOLFSSL_SP_SMALL */ +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +/* r = 2^n mod m where n is the number of bits to reduce by. + * Given m must be 3072 bits, just need to subtract. + * + * r A single precision number. + * m A signle precision number. + */ +static void sp_3072_mont_norm_67(sp_digit* r, sp_digit* m) +{ + /* Set r = 2^n - 1. */ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<66; i++) + r[i] = 0x7fffff; +#else + int i; + + for (i = 0; i < 64; i += 8) { + r[i + 0] = 0x7fffff; + r[i + 1] = 0x7fffff; + r[i + 2] = 0x7fffff; + r[i + 3] = 0x7fffff; + r[i + 4] = 0x7fffff; + r[i + 5] = 0x7fffff; + r[i + 6] = 0x7fffff; + r[i + 7] = 0x7fffff; + } + r[64] = 0x7fffff; + r[65] = 0x7fffff; +#endif + r[66] = 0x3ffffl; + + /* r = (2^n - 1) mod n */ + sp_3072_sub_67(r, r, m); + + /* Add one so r = 2^n mod m */ + r[0] += 1; +} + +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +static sp_digit sp_3072_cmp_67(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = 0; +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=66; i>=0; i--) + r |= (a[i] - b[i]) & (0 - !r); +#else + int i; + + r |= (a[66] - b[66]) & (0 - !r); + r |= (a[65] - b[65]) & (0 - !r); + r |= (a[64] - b[64]) & (0 - !r); + for (i = 56; i >= 0; i -= 8) { + r |= (a[i + 7] - b[i + 7]) & (0 - !r); + r |= (a[i + 6] - b[i + 6]) & (0 - !r); + r |= (a[i + 5] - b[i + 5]) & (0 - !r); + r |= (a[i + 4] - b[i + 4]) & (0 - !r); + r |= (a[i + 3] - b[i + 3]) & (0 - !r); + r |= (a[i + 2] - b[i + 2]) & (0 - !r); + r |= (a[i + 1] - b[i + 1]) & (0 - !r); + r |= (a[i + 0] - b[i + 0]) & (0 - !r); + } +#endif /* WOLFSSL_SP_SMALL */ + + return r; +} + +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +static void sp_3072_cond_sub_67(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i = 0; i < 67; i++) + r[i] = a[i] - (b[i] & m); +#else + int i; + + for (i = 0; i < 64; i += 8) { + r[i + 0] = a[i + 0] - (b[i + 0] & m); + r[i + 1] = a[i + 1] - (b[i + 1] & m); + r[i + 2] = a[i + 2] - (b[i + 2] & m); + r[i + 3] = a[i + 3] - (b[i + 3] & m); + r[i + 4] = a[i + 4] - (b[i + 4] & m); + r[i + 5] = a[i + 5] - (b[i + 5] & m); + r[i + 6] = a[i + 6] - (b[i + 6] & m); + r[i + 7] = a[i + 7] - (b[i + 7] & m); + } + r[64] = a[64] - (b[64] & m); + r[65] = a[65] - (b[65] & m); + r[66] = a[66] - (b[66] & m); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Mul a by scalar b and add into r. (r += a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +SP_NOINLINE static void sp_3072_mul_add_67(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int64_t tb = b; + int64_t t = 0; + int i; + + for (i = 0; i < 67; i++) { + t += (tb * a[i]) + r[i]; + r[i] = t & 0x7fffff; + t >>= 23; + } + r[67] += t; +#else + int64_t tb = b; + int64_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] += t[0] & 0x7fffff; + for (i = 0; i < 64; i += 8) { + t[1] = tb * a[i+1]; + r[i+1] += (t[0] >> 23) + (t[1] & 0x7fffff); + t[2] = tb * a[i+2]; + r[i+2] += (t[1] >> 23) + (t[2] & 0x7fffff); + t[3] = tb * a[i+3]; + r[i+3] += (t[2] >> 23) + (t[3] & 0x7fffff); + t[4] = tb * a[i+4]; + r[i+4] += (t[3] >> 23) + (t[4] & 0x7fffff); + t[5] = tb * a[i+5]; + r[i+5] += (t[4] >> 23) + (t[5] & 0x7fffff); + t[6] = tb * a[i+6]; + r[i+6] += (t[5] >> 23) + (t[6] & 0x7fffff); + t[7] = tb * a[i+7]; + r[i+7] += (t[6] >> 23) + (t[7] & 0x7fffff); + t[0] = tb * a[i+8]; + r[i+8] += (t[7] >> 23) + (t[0] & 0x7fffff); + } + t[1] = tb * a[65]; r[65] += (t[0] >> 23) + (t[1] & 0x7fffff); + t[2] = tb * a[66]; r[66] += (t[1] >> 23) + (t[2] & 0x7fffff); + r[67] += t[2] >> 23; +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Normalize the values in each word to 23. + * + * a Array of sp_digit to normalize. + */ +static void sp_3072_norm_67(sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + for (i = 0; i < 66; i++) { + a[i+1] += a[i] >> 23; + a[i] &= 0x7fffff; + } +#else + int i; + for (i = 0; i < 64; i += 8) { + a[i+1] += a[i+0] >> 23; a[i+0] &= 0x7fffff; + a[i+2] += a[i+1] >> 23; a[i+1] &= 0x7fffff; + a[i+3] += a[i+2] >> 23; a[i+2] &= 0x7fffff; + a[i+4] += a[i+3] >> 23; a[i+3] &= 0x7fffff; + a[i+5] += a[i+4] >> 23; a[i+4] &= 0x7fffff; + a[i+6] += a[i+5] >> 23; a[i+5] &= 0x7fffff; + a[i+7] += a[i+6] >> 23; a[i+6] &= 0x7fffff; + a[i+8] += a[i+7] >> 23; a[i+7] &= 0x7fffff; + a[i+9] += a[i+8] >> 23; a[i+8] &= 0x7fffff; + } + a[64+1] += a[64] >> 23; + a[64] &= 0x7fffff; + a[65+1] += a[65] >> 23; + a[65] &= 0x7fffff; +#endif +} + +/* Shift the result in the high 1536 bits down to the bottom. + * + * r A single precision number. + * a A single precision number. + */ +static void sp_3072_mont_shift_67(sp_digit* r, const sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + sp_digit n, s; + + s = a[67]; + n = a[66] >> 18; + for (i = 0; i < 66; i++) { + n += (s & 0x7fffff) << 5; + r[i] = n & 0x7fffff; + n >>= 23; + s = a[68 + i] + (s >> 23); + } + n += s << 5; + r[66] = n; +#else + sp_digit n, s; + int i; + + s = a[67]; n = a[66] >> 18; + for (i = 0; i < 64; i += 8) { + n += (s & 0x7fffff) << 5; r[i+0] = n & 0x7fffff; + n >>= 23; s = a[i+68] + (s >> 23); + n += (s & 0x7fffff) << 5; r[i+1] = n & 0x7fffff; + n >>= 23; s = a[i+69] + (s >> 23); + n += (s & 0x7fffff) << 5; r[i+2] = n & 0x7fffff; + n >>= 23; s = a[i+70] + (s >> 23); + n += (s & 0x7fffff) << 5; r[i+3] = n & 0x7fffff; + n >>= 23; s = a[i+71] + (s >> 23); + n += (s & 0x7fffff) << 5; r[i+4] = n & 0x7fffff; + n >>= 23; s = a[i+72] + (s >> 23); + n += (s & 0x7fffff) << 5; r[i+5] = n & 0x7fffff; + n >>= 23; s = a[i+73] + (s >> 23); + n += (s & 0x7fffff) << 5; r[i+6] = n & 0x7fffff; + n >>= 23; s = a[i+74] + (s >> 23); + n += (s & 0x7fffff) << 5; r[i+7] = n & 0x7fffff; + n >>= 23; s = a[i+75] + (s >> 23); + } + n += (s & 0x7fffff) << 5; r[64] = n & 0x7fffff; + n >>= 23; s = a[132] + (s >> 23); + n += (s & 0x7fffff) << 5; r[65] = n & 0x7fffff; + n >>= 23; s = a[133] + (s >> 23); + n += s << 5; r[66] = n; +#endif /* WOLFSSL_SP_SMALL */ + XMEMSET(&r[67], 0, sizeof(*r) * 67); +} + +/* Reduce the number back to 3072 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +static void sp_3072_mont_reduce_67(sp_digit* a, sp_digit* m, sp_digit mp) +{ + int i; + sp_digit mu; + + for (i=0; i<66; i++) { + mu = (a[i] * mp) & 0x7fffff; + sp_3072_mul_add_67(a+i, m, mu); + a[i+1] += a[i] >> 23; + } + mu = (a[i] * mp) & 0x3ffffl; + sp_3072_mul_add_67(a+i, m, mu); + a[i+1] += a[i] >> 23; + a[i] &= 0x7fffff; + + sp_3072_mont_shift_67(a, a); + sp_3072_cond_sub_67(a, a, m, 0 - ((a[66] >> 18) > 0)); + sp_3072_norm_67(a); +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_3072_mont_mul_67(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_3072_mul_67(r, a, b); + sp_3072_mont_reduce_67(r, m, mp); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_3072_mont_sqr_67(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_3072_sqr_67(r, a); + sp_3072_mont_reduce_67(r, m, mp); +} + +/* Multiply a by scalar b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +SP_NOINLINE static void sp_3072_mul_d_67(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int64_t tb = b; + int64_t t = 0; + int i; + + for (i = 0; i < 67; i++) { + t += tb * a[i]; + r[i] = t & 0x7fffff; + t >>= 23; + } + r[67] = (sp_digit)t; +#else + int64_t tb = b; + int64_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] = t[0] & 0x7fffff; + for (i = 0; i < 64; i += 8) { + t[1] = tb * a[i+1]; + r[i+1] = (sp_digit)(t[0] >> 23) + (t[1] & 0x7fffff); + t[2] = tb * a[i+2]; + r[i+2] = (sp_digit)(t[1] >> 23) + (t[2] & 0x7fffff); + t[3] = tb * a[i+3]; + r[i+3] = (sp_digit)(t[2] >> 23) + (t[3] & 0x7fffff); + t[4] = tb * a[i+4]; + r[i+4] = (sp_digit)(t[3] >> 23) + (t[4] & 0x7fffff); + t[5] = tb * a[i+5]; + r[i+5] = (sp_digit)(t[4] >> 23) + (t[5] & 0x7fffff); + t[6] = tb * a[i+6]; + r[i+6] = (sp_digit)(t[5] >> 23) + (t[6] & 0x7fffff); + t[7] = tb * a[i+7]; + r[i+7] = (sp_digit)(t[6] >> 23) + (t[7] & 0x7fffff); + t[0] = tb * a[i+8]; + r[i+8] = (sp_digit)(t[7] >> 23) + (t[0] & 0x7fffff); + } + t[1] = tb * a[65]; + r[65] = (sp_digit)(t[0] >> 23) + (t[1] & 0x7fffff); + t[2] = tb * a[66]; + r[66] = (sp_digit)(t[1] >> 23) + (t[2] & 0x7fffff); + r[67] = (sp_digit)(t[2] >> 23); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Conditionally add a and b using the mask m. + * m is -1 to add and 0 when not. + * + * r A single precision number representing conditional add result. + * a A single precision number to add with. + * b A single precision number to add. + * m Mask value to apply. + */ +static void sp_3072_cond_add_67(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i = 0; i < 67; i++) + r[i] = a[i] + (b[i] & m); +#else + int i; + + for (i = 0; i < 64; i += 8) { + r[i + 0] = a[i + 0] + (b[i + 0] & m); + r[i + 1] = a[i + 1] + (b[i + 1] & m); + r[i + 2] = a[i + 2] + (b[i + 2] & m); + r[i + 3] = a[i + 3] + (b[i + 3] & m); + r[i + 4] = a[i + 4] + (b[i + 4] & m); + r[i + 5] = a[i + 5] + (b[i + 5] & m); + r[i + 6] = a[i + 6] + (b[i + 6] & m); + r[i + 7] = a[i + 7] + (b[i + 7] & m); + } + r[64] = a[64] + (b[64] & m); + r[65] = a[65] + (b[65] & m); + r[66] = a[66] + (b[66] & m); +#endif /* WOLFSSL_SP_SMALL */ +} + +#ifdef WOLFSSL_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_3072_add_67(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 67; i++) + r[i] = a[i] + b[i]; + + return 0; +} +#endif +#ifdef WOLFSSL_SP_DIV_32 +static WC_INLINE sp_digit sp_3072_div_word_67(sp_digit d1, sp_digit d0, + sp_digit div) +{ + sp_digit d, r, t; + + /* All 23 bits from d1 and top 8 bits from d0. */ + d = (d1 << 8) | (d0 >> 15); + r = d / div; + d -= r * div; + /* Up to 9 bits in r */ + /* Next 8 bits from d0. */ + r <<= 8; + d <<= 8; + d |= (d0 >> 7) & ((1 << 8) - 1); + t = d / div; + d -= t * div; + r += t; + /* Up to 17 bits in r */ + /* Remaining 7 bits from d0. */ + r <<= 7; + d <<= 7; + d |= d0 & ((1 << 7) - 1); + t = d / div; + r += t; + + return r; +} +#endif /* WOLFSSL_SP_DIV_32 */ + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. + */ +static int sp_3072_div_67(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + int i; +#ifndef WOLFSSL_SP_DIV_32 + int64_t d1; +#endif + sp_digit div, r1; +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* td; +#else + sp_digit t1d[134], t2d[67 + 1]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (3 * 67 + 1), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td != NULL) { + t1 = td; + t2 = td + 2 * 67; + } + else + err = MEMORY_E; +#else + t1 = t1d; + t2 = t2d; +#endif + + (void)m; + + if (err == MP_OKAY) { + div = d[66]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 67); + for (i=66; i>=0; i--) { + t1[67 + i] += t1[67 + i - 1] >> 23; + t1[67 + i - 1] &= 0x7fffff; +#ifndef WOLFSSL_SP_DIV_32 + d1 = t1[67 + i]; + d1 <<= 23; + d1 += t1[67 + i - 1]; + r1 = (sp_digit)(d1 / div); +#else + r1 = sp_3072_div_word_67(t1[67 + i], t1[67 + i - 1], div); +#endif + + sp_3072_mul_d_67(t2, d, r1); + sp_3072_sub_67(&t1[i], &t1[i], t2); + t1[67 + i] -= t2[67]; + t1[67 + i] += t1[67 + i - 1] >> 23; + t1[67 + i - 1] &= 0x7fffff; + r1 = (((-t1[67 + i]) << 23) - t1[67 + i - 1]) / div; + r1++; + sp_3072_mul_d_67(t2, d, r1); + sp_3072_add_67(&t1[i], &t1[i], t2); + t1[67 + i] += t1[67 + i - 1] >> 23; + t1[67 + i - 1] &= 0x7fffff; + } + t1[67 - 1] += t1[67 - 2] >> 23; + t1[67 - 2] &= 0x7fffff; + r1 = t1[67 - 1] / div; + + sp_3072_mul_d_67(t2, d, r1); + sp_3072_sub_67(t1, t1, t2); + XMEMCPY(r, t1, sizeof(*r) * 2 * 67); + for (i=0; i<65; i++) { + r[i+1] += r[i] >> 23; + r[i] &= 0x7fffff; + } + sp_3072_cond_add_67(r, r, d, 0 - (r[66] < 0)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. + */ +static int sp_3072_mod_67(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_3072_div_67(a, m, NULL, r); +} + +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_3072_mod_exp_67(sp_digit* r, sp_digit* a, sp_digit* e, int bits, + sp_digit* m, int reduceA) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* td; + sp_digit* t[3]; + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + + td = (sp_digit*)XMALLOC(sizeof(*td) * 3 * 67 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + XMEMSET(td, 0, sizeof(*td) * 3 * 67 * 2); + + norm = t[0] = td; + t[1] = &td[67 * 2]; + t[2] = &td[2 * 67 * 2]; + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_67(norm, m); + + if (reduceA) + err = sp_3072_mod_67(t[1], a, m); + else + XMEMCPY(t[1], a, sizeof(sp_digit) * 67); + } + if (err == MP_OKAY) { + sp_3072_mul_67(t[1], t[1], norm); + err = sp_3072_mod_67(t[1], t[1], m); + } + + if (err == MP_OKAY) { + i = bits / 23; + c = bits % 23; + n = e[i--] << (23 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = e[i--]; + c = 23; + } + + y = (n >> 22) & 1; + n <<= 1; + + sp_3072_mont_mul_67(t[y^1], t[0], t[1], m, mp); + + XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), + sizeof(*t[2]) * 67 * 2); + sp_3072_mont_sqr_67(t[2], t[2], m, mp); + XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), t[2], + sizeof(*t[2]) * 67 * 2); + } + + sp_3072_mont_reduce_67(t[0], m, mp); + n = sp_3072_cmp_67(t[0], m); + sp_3072_cond_sub_67(t[0], t[0], m, (n < 0) - 1); + XMEMCPY(r, t[0], sizeof(*r) * 67 * 2); + + } + + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return err; +#elif defined(WOLFSSL_SP_CACHE_RESISTANT) +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[3][134]; +#else + sp_digit* td; + sp_digit* t[3]; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(*td) * 3 * 67 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + t[0] = td; + t[1] = &td[67 * 2]; + t[2] = &td[2 * 67 * 2]; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_67(norm, m); + + if (reduceA) { + err = sp_3072_mod_67(t[1], a, m); + if (err == MP_OKAY) { + sp_3072_mul_67(t[1], t[1], norm); + err = sp_3072_mod_67(t[1], t[1], m); + } + } + else { + sp_3072_mul_67(t[1], a, norm); + err = sp_3072_mod_67(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + i = bits / 23; + c = bits % 23; + n = e[i--] << (23 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = e[i--]; + c = 23; + } + + y = (n >> 22) & 1; + n <<= 1; + + sp_3072_mont_mul_67(t[y^1], t[0], t[1], m, mp); + + XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), sizeof(t[2])); + sp_3072_mont_sqr_67(t[2], t[2], m, mp); + XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), t[2], sizeof(t[2])); + } + + sp_3072_mont_reduce_67(t[0], m, mp); + n = sp_3072_cmp_67(t[0], m); + sp_3072_cond_sub_67(t[0], t[0], m, (n < 0) - 1); + XMEMCPY(r, t[0], sizeof(t[0])); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +#else +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][134]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit rt[134]; + sp_digit mp = 1; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 134, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<32; i++) + t[i] = td + i * 134; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_67(norm, m); + + if (reduceA) { + err = sp_3072_mod_67(t[1], a, m); + if (err == MP_OKAY) { + sp_3072_mul_67(t[1], t[1], norm); + err = sp_3072_mod_67(t[1], t[1], m); + } + } + else { + sp_3072_mul_67(t[1], a, norm); + err = sp_3072_mod_67(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_3072_mont_sqr_67(t[ 2], t[ 1], m, mp); + sp_3072_mont_mul_67(t[ 3], t[ 2], t[ 1], m, mp); + sp_3072_mont_sqr_67(t[ 4], t[ 2], m, mp); + sp_3072_mont_mul_67(t[ 5], t[ 3], t[ 2], m, mp); + sp_3072_mont_sqr_67(t[ 6], t[ 3], m, mp); + sp_3072_mont_mul_67(t[ 7], t[ 4], t[ 3], m, mp); + sp_3072_mont_sqr_67(t[ 8], t[ 4], m, mp); + sp_3072_mont_mul_67(t[ 9], t[ 5], t[ 4], m, mp); + sp_3072_mont_sqr_67(t[10], t[ 5], m, mp); + sp_3072_mont_mul_67(t[11], t[ 6], t[ 5], m, mp); + sp_3072_mont_sqr_67(t[12], t[ 6], m, mp); + sp_3072_mont_mul_67(t[13], t[ 7], t[ 6], m, mp); + sp_3072_mont_sqr_67(t[14], t[ 7], m, mp); + sp_3072_mont_mul_67(t[15], t[ 8], t[ 7], m, mp); + sp_3072_mont_sqr_67(t[16], t[ 8], m, mp); + sp_3072_mont_mul_67(t[17], t[ 9], t[ 8], m, mp); + sp_3072_mont_sqr_67(t[18], t[ 9], m, mp); + sp_3072_mont_mul_67(t[19], t[10], t[ 9], m, mp); + sp_3072_mont_sqr_67(t[20], t[10], m, mp); + sp_3072_mont_mul_67(t[21], t[11], t[10], m, mp); + sp_3072_mont_sqr_67(t[22], t[11], m, mp); + sp_3072_mont_mul_67(t[23], t[12], t[11], m, mp); + sp_3072_mont_sqr_67(t[24], t[12], m, mp); + sp_3072_mont_mul_67(t[25], t[13], t[12], m, mp); + sp_3072_mont_sqr_67(t[26], t[13], m, mp); + sp_3072_mont_mul_67(t[27], t[14], t[13], m, mp); + sp_3072_mont_sqr_67(t[28], t[14], m, mp); + sp_3072_mont_mul_67(t[29], t[15], t[14], m, mp); + sp_3072_mont_sqr_67(t[30], t[15], m, mp); + sp_3072_mont_mul_67(t[31], t[16], t[15], m, mp); + + bits = ((bits + 4) / 5) * 5; + i = ((bits + 22) / 23) - 1; + c = bits % 23; + if (c == 0) + c = 23; + if (i < 67) + n = e[i--] << (32 - c); + else { + n = 0; + i--; + } + if (c < 5) { + n |= e[i--] << (9 - c); + c += 23; + } + y = (n >> 27) & 0x1f; + n <<= 5; + c -= 5; + XMEMCPY(rt, t[y], sizeof(rt)); + for (; i>=0 || c>=5; ) { + if (c < 5) { + n |= e[i--] << (9 - c); + c += 23; + } + y = (n >> 27) & 0x1f; + n <<= 5; + c -= 5; + + sp_3072_mont_sqr_67(rt, rt, m, mp); + sp_3072_mont_sqr_67(rt, rt, m, mp); + sp_3072_mont_sqr_67(rt, rt, m, mp); + sp_3072_mont_sqr_67(rt, rt, m, mp); + sp_3072_mont_sqr_67(rt, rt, m, mp); + + sp_3072_mont_mul_67(rt, rt, t[y], m, mp); + } + + sp_3072_mont_reduce_67(rt, m, mp); + n = sp_3072_cmp_67(rt, m); + sp_3072_cond_sub_67(rt, rt, m, (n < 0) - 1); + XMEMCPY(r, rt, sizeof(rt)); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +#endif +} + +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +/* r = 2^n mod m where n is the number of bits to reduce by. + * Given m must be 3072 bits, just need to subtract. + * + * r A single precision number. + * m A signle precision number. + */ +static void sp_3072_mont_norm_134(sp_digit* r, sp_digit* m) +{ + /* Set r = 2^n - 1. */ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<133; i++) + r[i] = 0x7fffff; +#else + int i; + + for (i = 0; i < 128; i += 8) { + r[i + 0] = 0x7fffff; + r[i + 1] = 0x7fffff; + r[i + 2] = 0x7fffff; + r[i + 3] = 0x7fffff; + r[i + 4] = 0x7fffff; + r[i + 5] = 0x7fffff; + r[i + 6] = 0x7fffff; + r[i + 7] = 0x7fffff; + } + r[128] = 0x7fffff; + r[129] = 0x7fffff; + r[130] = 0x7fffff; + r[131] = 0x7fffff; + r[132] = 0x7fffff; +#endif + r[133] = 0x1fffl; + + /* r = (2^n - 1) mod n */ + sp_3072_sub_134(r, r, m); + + /* Add one so r = 2^n mod m */ + r[0] += 1; +} + +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +static sp_digit sp_3072_cmp_134(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = 0; +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=133; i>=0; i--) + r |= (a[i] - b[i]) & (0 - !r); +#else + int i; + + r |= (a[133] - b[133]) & (0 - !r); + r |= (a[132] - b[132]) & (0 - !r); + r |= (a[131] - b[131]) & (0 - !r); + r |= (a[130] - b[130]) & (0 - !r); + r |= (a[129] - b[129]) & (0 - !r); + r |= (a[128] - b[128]) & (0 - !r); + for (i = 120; i >= 0; i -= 8) { + r |= (a[i + 7] - b[i + 7]) & (0 - !r); + r |= (a[i + 6] - b[i + 6]) & (0 - !r); + r |= (a[i + 5] - b[i + 5]) & (0 - !r); + r |= (a[i + 4] - b[i + 4]) & (0 - !r); + r |= (a[i + 3] - b[i + 3]) & (0 - !r); + r |= (a[i + 2] - b[i + 2]) & (0 - !r); + r |= (a[i + 1] - b[i + 1]) & (0 - !r); + r |= (a[i + 0] - b[i + 0]) & (0 - !r); + } +#endif /* WOLFSSL_SP_SMALL */ + + return r; +} + +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +static void sp_3072_cond_sub_134(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i = 0; i < 134; i++) + r[i] = a[i] - (b[i] & m); +#else + int i; + + for (i = 0; i < 128; i += 8) { + r[i + 0] = a[i + 0] - (b[i + 0] & m); + r[i + 1] = a[i + 1] - (b[i + 1] & m); + r[i + 2] = a[i + 2] - (b[i + 2] & m); + r[i + 3] = a[i + 3] - (b[i + 3] & m); + r[i + 4] = a[i + 4] - (b[i + 4] & m); + r[i + 5] = a[i + 5] - (b[i + 5] & m); + r[i + 6] = a[i + 6] - (b[i + 6] & m); + r[i + 7] = a[i + 7] - (b[i + 7] & m); + } + r[128] = a[128] - (b[128] & m); + r[129] = a[129] - (b[129] & m); + r[130] = a[130] - (b[130] & m); + r[131] = a[131] - (b[131] & m); + r[132] = a[132] - (b[132] & m); + r[133] = a[133] - (b[133] & m); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Mul a by scalar b and add into r. (r += a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +SP_NOINLINE static void sp_3072_mul_add_134(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int64_t tb = b; + int64_t t = 0; + int i; + + for (i = 0; i < 134; i++) { + t += (tb * a[i]) + r[i]; + r[i] = t & 0x7fffff; + t >>= 23; + } + r[134] += t; +#else + int64_t tb = b; + int64_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] += t[0] & 0x7fffff; + for (i = 0; i < 128; i += 8) { + t[1] = tb * a[i+1]; + r[i+1] += (t[0] >> 23) + (t[1] & 0x7fffff); + t[2] = tb * a[i+2]; + r[i+2] += (t[1] >> 23) + (t[2] & 0x7fffff); + t[3] = tb * a[i+3]; + r[i+3] += (t[2] >> 23) + (t[3] & 0x7fffff); + t[4] = tb * a[i+4]; + r[i+4] += (t[3] >> 23) + (t[4] & 0x7fffff); + t[5] = tb * a[i+5]; + r[i+5] += (t[4] >> 23) + (t[5] & 0x7fffff); + t[6] = tb * a[i+6]; + r[i+6] += (t[5] >> 23) + (t[6] & 0x7fffff); + t[7] = tb * a[i+7]; + r[i+7] += (t[6] >> 23) + (t[7] & 0x7fffff); + t[0] = tb * a[i+8]; + r[i+8] += (t[7] >> 23) + (t[0] & 0x7fffff); + } + t[1] = tb * a[129]; r[129] += (t[0] >> 23) + (t[1] & 0x7fffff); + t[2] = tb * a[130]; r[130] += (t[1] >> 23) + (t[2] & 0x7fffff); + t[3] = tb * a[131]; r[131] += (t[2] >> 23) + (t[3] & 0x7fffff); + t[4] = tb * a[132]; r[132] += (t[3] >> 23) + (t[4] & 0x7fffff); + t[5] = tb * a[133]; r[133] += (t[4] >> 23) + (t[5] & 0x7fffff); + r[134] += t[5] >> 23; +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Normalize the values in each word to 23. + * + * a Array of sp_digit to normalize. + */ +static void sp_3072_norm_134(sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + for (i = 0; i < 133; i++) { + a[i+1] += a[i] >> 23; + a[i] &= 0x7fffff; + } +#else + int i; + for (i = 0; i < 128; i += 8) { + a[i+1] += a[i+0] >> 23; a[i+0] &= 0x7fffff; + a[i+2] += a[i+1] >> 23; a[i+1] &= 0x7fffff; + a[i+3] += a[i+2] >> 23; a[i+2] &= 0x7fffff; + a[i+4] += a[i+3] >> 23; a[i+3] &= 0x7fffff; + a[i+5] += a[i+4] >> 23; a[i+4] &= 0x7fffff; + a[i+6] += a[i+5] >> 23; a[i+5] &= 0x7fffff; + a[i+7] += a[i+6] >> 23; a[i+6] &= 0x7fffff; + a[i+8] += a[i+7] >> 23; a[i+7] &= 0x7fffff; + a[i+9] += a[i+8] >> 23; a[i+8] &= 0x7fffff; + } + a[128+1] += a[128] >> 23; + a[128] &= 0x7fffff; + a[129+1] += a[129] >> 23; + a[129] &= 0x7fffff; + a[130+1] += a[130] >> 23; + a[130] &= 0x7fffff; + a[131+1] += a[131] >> 23; + a[131] &= 0x7fffff; + a[132+1] += a[132] >> 23; + a[132] &= 0x7fffff; +#endif +} + +/* Shift the result in the high 3072 bits down to the bottom. + * + * r A single precision number. + * a A single precision number. + */ +static void sp_3072_mont_shift_134(sp_digit* r, const sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + int64_t n = a[133] >> 13; + n += ((int64_t)a[134]) << 10; + + for (i = 0; i < 133; i++) { + r[i] = n & 0x7fffff; + n >>= 23; + n += ((int64_t)a[135 + i]) << 10; + } + r[133] = (sp_digit)n; +#else + int i; + int64_t n = a[133] >> 13; + n += ((int64_t)a[134]) << 10; + for (i = 0; i < 128; i += 8) { + r[i + 0] = n & 0x7fffff; + n >>= 23; n += ((int64_t)a[i + 135]) << 10; + r[i + 1] = n & 0x7fffff; + n >>= 23; n += ((int64_t)a[i + 136]) << 10; + r[i + 2] = n & 0x7fffff; + n >>= 23; n += ((int64_t)a[i + 137]) << 10; + r[i + 3] = n & 0x7fffff; + n >>= 23; n += ((int64_t)a[i + 138]) << 10; + r[i + 4] = n & 0x7fffff; + n >>= 23; n += ((int64_t)a[i + 139]) << 10; + r[i + 5] = n & 0x7fffff; + n >>= 23; n += ((int64_t)a[i + 140]) << 10; + r[i + 6] = n & 0x7fffff; + n >>= 23; n += ((int64_t)a[i + 141]) << 10; + r[i + 7] = n & 0x7fffff; + n >>= 23; n += ((int64_t)a[i + 142]) << 10; + } + r[128] = n & 0x7fffff; n >>= 23; n += ((int64_t)a[263]) << 10; + r[129] = n & 0x7fffff; n >>= 23; n += ((int64_t)a[264]) << 10; + r[130] = n & 0x7fffff; n >>= 23; n += ((int64_t)a[265]) << 10; + r[131] = n & 0x7fffff; n >>= 23; n += ((int64_t)a[266]) << 10; + r[132] = n & 0x7fffff; n >>= 23; n += ((int64_t)a[267]) << 10; + r[133] = (sp_digit)n; +#endif /* WOLFSSL_SP_SMALL */ + XMEMSET(&r[134], 0, sizeof(*r) * 134); +} + +/* Reduce the number back to 3072 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +static void sp_3072_mont_reduce_134(sp_digit* a, sp_digit* m, sp_digit mp) +{ + int i; + sp_digit mu; + +#ifdef WOLFSSL_SP_DH + if (mp != 1) { + for (i=0; i<133; i++) { + mu = (a[i] * mp) & 0x7fffff; + sp_3072_mul_add_134(a+i, m, mu); + a[i+1] += a[i] >> 23; + } + mu = (a[i] * mp) & 0x1fffl; + sp_3072_mul_add_134(a+i, m, mu); + a[i+1] += a[i] >> 23; + a[i] &= 0x7fffff; + } + else { + for (i=0; i<133; i++) { + mu = a[i] & 0x7fffff; + sp_3072_mul_add_134(a+i, m, mu); + a[i+1] += a[i] >> 23; + } + mu = a[i] & 0x1fffl; + sp_3072_mul_add_134(a+i, m, mu); + a[i+1] += a[i] >> 23; + a[i] &= 0x7fffff; + } +#else + for (i=0; i<133; i++) { + mu = (a[i] * mp) & 0x7fffff; + sp_3072_mul_add_134(a+i, m, mu); + a[i+1] += a[i] >> 23; + } + mu = (a[i] * mp) & 0x1fffl; + sp_3072_mul_add_134(a+i, m, mu); + a[i+1] += a[i] >> 23; + a[i] &= 0x7fffff; +#endif + + sp_3072_mont_shift_134(a, a); + sp_3072_cond_sub_134(a, a, m, 0 - ((a[133] >> 13) > 0)); + sp_3072_norm_134(a); +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_3072_mont_mul_134(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_3072_mul_134(r, a, b); + sp_3072_mont_reduce_134(r, m, mp); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_3072_mont_sqr_134(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_3072_sqr_134(r, a); + sp_3072_mont_reduce_134(r, m, mp); +} + +/* Multiply a by scalar b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +SP_NOINLINE static void sp_3072_mul_d_268(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int64_t tb = b; + int64_t t = 0; + int i; + + for (i = 0; i < 268; i++) { + t += tb * a[i]; + r[i] = t & 0x7fffff; + t >>= 23; + } + r[268] = (sp_digit)t; +#else + int64_t tb = b; + int64_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] = t[0] & 0x7fffff; + for (i = 0; i < 264; i += 8) { + t[1] = tb * a[i+1]; + r[i+1] = (sp_digit)(t[0] >> 23) + (t[1] & 0x7fffff); + t[2] = tb * a[i+2]; + r[i+2] = (sp_digit)(t[1] >> 23) + (t[2] & 0x7fffff); + t[3] = tb * a[i+3]; + r[i+3] = (sp_digit)(t[2] >> 23) + (t[3] & 0x7fffff); + t[4] = tb * a[i+4]; + r[i+4] = (sp_digit)(t[3] >> 23) + (t[4] & 0x7fffff); + t[5] = tb * a[i+5]; + r[i+5] = (sp_digit)(t[4] >> 23) + (t[5] & 0x7fffff); + t[6] = tb * a[i+6]; + r[i+6] = (sp_digit)(t[5] >> 23) + (t[6] & 0x7fffff); + t[7] = tb * a[i+7]; + r[i+7] = (sp_digit)(t[6] >> 23) + (t[7] & 0x7fffff); + t[0] = tb * a[i+8]; + r[i+8] = (sp_digit)(t[7] >> 23) + (t[0] & 0x7fffff); + } + t[1] = tb * a[265]; + r[265] = (sp_digit)(t[0] >> 23) + (t[1] & 0x7fffff); + t[2] = tb * a[266]; + r[266] = (sp_digit)(t[1] >> 23) + (t[2] & 0x7fffff); + t[3] = tb * a[267]; + r[267] = (sp_digit)(t[2] >> 23) + (t[3] & 0x7fffff); + r[268] = (sp_digit)(t[3] >> 23); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Conditionally add a and b using the mask m. + * m is -1 to add and 0 when not. + * + * r A single precision number representing conditional add result. + * a A single precision number to add with. + * b A single precision number to add. + * m Mask value to apply. + */ +static void sp_3072_cond_add_134(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i = 0; i < 134; i++) + r[i] = a[i] + (b[i] & m); +#else + int i; + + for (i = 0; i < 128; i += 8) { + r[i + 0] = a[i + 0] + (b[i + 0] & m); + r[i + 1] = a[i + 1] + (b[i + 1] & m); + r[i + 2] = a[i + 2] + (b[i + 2] & m); + r[i + 3] = a[i + 3] + (b[i + 3] & m); + r[i + 4] = a[i + 4] + (b[i + 4] & m); + r[i + 5] = a[i + 5] + (b[i + 5] & m); + r[i + 6] = a[i + 6] + (b[i + 6] & m); + r[i + 7] = a[i + 7] + (b[i + 7] & m); + } + r[128] = a[128] + (b[128] & m); + r[129] = a[129] + (b[129] & m); + r[130] = a[130] + (b[130] & m); + r[131] = a[131] + (b[131] & m); + r[132] = a[132] + (b[132] & m); + r[133] = a[133] + (b[133] & m); +#endif /* WOLFSSL_SP_SMALL */ +} + +#ifdef WOLFSSL_SMALL +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_3072_sub_134(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 134; i++) + r[i] = a[i] - b[i]; + + return 0; +} + +#endif +#ifdef WOLFSSL_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_3072_add_134(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 134; i++) + r[i] = a[i] + b[i]; + + return 0; +} +#endif +SP_NOINLINE static void sp_3072_rshift_134(sp_digit* r, sp_digit* a, byte n) +{ + int i; + +#ifdef WOLFSSL_SP_SMALL + for (i=0; i<133; i++) + r[i] = ((a[i] >> n) | (a[i + 1] << (23 - n))) & 0x7fffff; +#else + for (i=0; i<128; i += 8) { + r[i+0] = ((a[i+0] >> n) | (a[i+1] << (23 - n))) & 0x7fffff; + r[i+1] = ((a[i+1] >> n) | (a[i+2] << (23 - n))) & 0x7fffff; + r[i+2] = ((a[i+2] >> n) | (a[i+3] << (23 - n))) & 0x7fffff; + r[i+3] = ((a[i+3] >> n) | (a[i+4] << (23 - n))) & 0x7fffff; + r[i+4] = ((a[i+4] >> n) | (a[i+5] << (23 - n))) & 0x7fffff; + r[i+5] = ((a[i+5] >> n) | (a[i+6] << (23 - n))) & 0x7fffff; + r[i+6] = ((a[i+6] >> n) | (a[i+7] << (23 - n))) & 0x7fffff; + r[i+7] = ((a[i+7] >> n) | (a[i+8] << (23 - n))) & 0x7fffff; + } + r[128] = ((a[128] >> n) | (a[129] << (23 - n))) & 0x7fffff; + r[129] = ((a[129] >> n) | (a[130] << (23 - n))) & 0x7fffff; + r[130] = ((a[130] >> n) | (a[131] << (23 - n))) & 0x7fffff; + r[131] = ((a[131] >> n) | (a[132] << (23 - n))) & 0x7fffff; + r[132] = ((a[132] >> n) | (a[133] << (23 - n))) & 0x7fffff; +#endif + r[133] = a[133] >> n; +} + +#ifdef WOLFSSL_SP_DIV_32 +static WC_INLINE sp_digit sp_3072_div_word_134(sp_digit d1, sp_digit d0, + sp_digit div) +{ + sp_digit d, r, t; + + /* All 23 bits from d1 and top 8 bits from d0. */ + d = (d1 << 8) | (d0 >> 15); + r = d / div; + d -= r * div; + /* Up to 9 bits in r */ + /* Next 8 bits from d0. */ + r <<= 8; + d <<= 8; + d |= (d0 >> 7) & ((1 << 8) - 1); + t = d / div; + d -= t * div; + r += t; + /* Up to 17 bits in r */ + /* Remaining 7 bits from d0. */ + r <<= 7; + d <<= 7; + d |= d0 & ((1 << 7) - 1); + t = d / div; + r += t; + + return r; +} +#endif /* WOLFSSL_SP_DIV_32 */ + +/* Normalize the values in each word to 23. + * + * a Array of sp_digit to normalize. + */ +static void sp_3072_norm_268(sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + for (i = 0; i < 267; i++) { + a[i+1] += a[i] >> 23; + a[i] &= 0x7fffff; + } +#else + int i; + for (i = 0; i < 264; i += 8) { + a[i+1] += a[i+0] >> 23; a[i+0] &= 0x7fffff; + a[i+2] += a[i+1] >> 23; a[i+1] &= 0x7fffff; + a[i+3] += a[i+2] >> 23; a[i+2] &= 0x7fffff; + a[i+4] += a[i+3] >> 23; a[i+3] &= 0x7fffff; + a[i+5] += a[i+4] >> 23; a[i+4] &= 0x7fffff; + a[i+6] += a[i+5] >> 23; a[i+5] &= 0x7fffff; + a[i+7] += a[i+6] >> 23; a[i+6] &= 0x7fffff; + a[i+8] += a[i+7] >> 23; a[i+7] &= 0x7fffff; + a[i+9] += a[i+8] >> 23; a[i+8] &= 0x7fffff; + } + a[264+1] += a[264] >> 23; + a[264] &= 0x7fffff; + a[265+1] += a[265] >> 23; + a[265] &= 0x7fffff; + a[266+1] += a[266] >> 23; + a[266] &= 0x7fffff; +#endif +} + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. + */ +static int sp_3072_div_134(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + int i; +#ifndef WOLFSSL_SP_DIV_32 + int64_t d1; +#endif + sp_digit div, r1; +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* td; +#else + sp_digit t1d[268 + 1], t2d[134 + 1], sdd[134 + 1]; +#endif + sp_digit* t1; + sp_digit* t2; + sp_digit* sd; + int err = MP_OKAY; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (4 * 134 + 3), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td != NULL) { + t1 = td; + t2 = td + 268 + 1; + sd = t2 + 134 + 1; + } + else + err = MEMORY_E; +#else + t1 = t1d; + t2 = t2d; + sd = sdd; +#endif + + (void)m; + + if (err == MP_OKAY) { + sp_3072_mul_d_134(sd, d, 1 << 10); + sp_3072_norm_268(a); + sp_3072_mul_d_268(t1, a, 1 << 10); + div = sd[133]; + for (i=134; i>=0; i--) { + t1[134 + i] += t1[134 + i - 1] >> 23; + t1[134 + i - 1] &= 0x7fffff; +#ifndef WOLFSSL_SP_DIV_32 + d1 = t1[134 + i]; + d1 <<= 23; + d1 += t1[134 + i - 1]; + r1 = (sp_digit)(d1 / div); +#else + r1 = sp_3072_div_word_134(t1[134 + i], t1[134 + i - 1], div); +#endif + + sp_3072_mul_d_134(t2, sd, r1); + sp_3072_sub_134(&t1[i], &t1[i], t2); + t1[134 + i] -= t2[134]; + t1[134 + i] += t1[134 + i - 1] >> 23; + t1[134 + i - 1] &= 0x7fffff; + r1 = (((-t1[134 + i]) << 23) - t1[134 + i - 1]) / div; + r1 -= t1[134 + i]; + sp_3072_mul_d_134(t2, sd, r1); + sp_3072_add_134(&t1[i], &t1[i], t2); + t1[134 + i] += t1[134 + i - 1] >> 23; + t1[134 + i - 1] &= 0x7fffff; + } + t1[134 - 1] += t1[134 - 2] >> 23; + t1[134 - 2] &= 0x7fffff; + r1 = t1[134 - 1] / div; + + sp_3072_mul_d_134(t2, sd, r1); + sp_3072_sub_134(t1, t1, t2); + XMEMCPY(r, t1, sizeof(*r) * 2 * 134); + for (i=0; i<132; i++) { + r[i+1] += r[i] >> 23; + r[i] &= 0x7fffff; + } + sp_3072_cond_add_134(r, r, sd, 0 - (r[133] < 0)); + } + + sp_3072_norm_134(r); + sp_3072_rshift_134(r, r, 10); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. + */ +static int sp_3072_mod_134(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_3072_div_134(a, m, NULL, r); +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \ + defined(WOLFSSL_HAVE_SP_DH) +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_3072_mod_exp_134(sp_digit* r, sp_digit* a, sp_digit* e, int bits, + sp_digit* m, int reduceA) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* td; + sp_digit* t[3]; + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + + td = (sp_digit*)XMALLOC(sizeof(*td) * 3 * 134 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + XMEMSET(td, 0, sizeof(*td) * 3 * 134 * 2); + + norm = t[0] = td; + t[1] = &td[134 * 2]; + t[2] = &td[2 * 134 * 2]; + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_134(norm, m); + + if (reduceA) + err = sp_3072_mod_134(t[1], a, m); + else + XMEMCPY(t[1], a, sizeof(sp_digit) * 134); + } + if (err == MP_OKAY) { + sp_3072_mul_134(t[1], t[1], norm); + err = sp_3072_mod_134(t[1], t[1], m); + } + + if (err == MP_OKAY) { + i = bits / 23; + c = bits % 23; + n = e[i--] << (23 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = e[i--]; + c = 23; + } + + y = (n >> 22) & 1; + n <<= 1; + + sp_3072_mont_mul_134(t[y^1], t[0], t[1], m, mp); + + XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), + sizeof(*t[2]) * 134 * 2); + sp_3072_mont_sqr_134(t[2], t[2], m, mp); + XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), t[2], + sizeof(*t[2]) * 134 * 2); + } + + sp_3072_mont_reduce_134(t[0], m, mp); + n = sp_3072_cmp_134(t[0], m); + sp_3072_cond_sub_134(t[0], t[0], m, (n < 0) - 1); + XMEMCPY(r, t[0], sizeof(*r) * 134 * 2); + + } + + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return err; +#elif defined(WOLFSSL_SP_CACHE_RESISTANT) +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[3][268]; +#else + sp_digit* td; + sp_digit* t[3]; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(*td) * 3 * 134 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + t[0] = td; + t[1] = &td[134 * 2]; + t[2] = &td[2 * 134 * 2]; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_134(norm, m); + + if (reduceA) { + err = sp_3072_mod_134(t[1], a, m); + if (err == MP_OKAY) { + sp_3072_mul_134(t[1], t[1], norm); + err = sp_3072_mod_134(t[1], t[1], m); + } + } + else { + sp_3072_mul_134(t[1], a, norm); + err = sp_3072_mod_134(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + i = bits / 23; + c = bits % 23; + n = e[i--] << (23 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = e[i--]; + c = 23; + } + + y = (n >> 22) & 1; + n <<= 1; + + sp_3072_mont_mul_134(t[y^1], t[0], t[1], m, mp); + + XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), sizeof(t[2])); + sp_3072_mont_sqr_134(t[2], t[2], m, mp); + XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), t[2], sizeof(t[2])); + } + + sp_3072_mont_reduce_134(t[0], m, mp); + n = sp_3072_cmp_134(t[0], m); + sp_3072_cond_sub_134(t[0], t[0], m, (n < 0) - 1); + XMEMCPY(r, t[0], sizeof(t[0])); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +#else +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][268]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit rt[268]; + sp_digit mp = 1; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 268, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<32; i++) + t[i] = td + i * 268; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_134(norm, m); + + if (reduceA) { + err = sp_3072_mod_134(t[1], a, m); + if (err == MP_OKAY) { + sp_3072_mul_134(t[1], t[1], norm); + err = sp_3072_mod_134(t[1], t[1], m); + } + } + else { + sp_3072_mul_134(t[1], a, norm); + err = sp_3072_mod_134(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_3072_mont_sqr_134(t[ 2], t[ 1], m, mp); + sp_3072_mont_mul_134(t[ 3], t[ 2], t[ 1], m, mp); + sp_3072_mont_sqr_134(t[ 4], t[ 2], m, mp); + sp_3072_mont_mul_134(t[ 5], t[ 3], t[ 2], m, mp); + sp_3072_mont_sqr_134(t[ 6], t[ 3], m, mp); + sp_3072_mont_mul_134(t[ 7], t[ 4], t[ 3], m, mp); + sp_3072_mont_sqr_134(t[ 8], t[ 4], m, mp); + sp_3072_mont_mul_134(t[ 9], t[ 5], t[ 4], m, mp); + sp_3072_mont_sqr_134(t[10], t[ 5], m, mp); + sp_3072_mont_mul_134(t[11], t[ 6], t[ 5], m, mp); + sp_3072_mont_sqr_134(t[12], t[ 6], m, mp); + sp_3072_mont_mul_134(t[13], t[ 7], t[ 6], m, mp); + sp_3072_mont_sqr_134(t[14], t[ 7], m, mp); + sp_3072_mont_mul_134(t[15], t[ 8], t[ 7], m, mp); + sp_3072_mont_sqr_134(t[16], t[ 8], m, mp); + sp_3072_mont_mul_134(t[17], t[ 9], t[ 8], m, mp); + sp_3072_mont_sqr_134(t[18], t[ 9], m, mp); + sp_3072_mont_mul_134(t[19], t[10], t[ 9], m, mp); + sp_3072_mont_sqr_134(t[20], t[10], m, mp); + sp_3072_mont_mul_134(t[21], t[11], t[10], m, mp); + sp_3072_mont_sqr_134(t[22], t[11], m, mp); + sp_3072_mont_mul_134(t[23], t[12], t[11], m, mp); + sp_3072_mont_sqr_134(t[24], t[12], m, mp); + sp_3072_mont_mul_134(t[25], t[13], t[12], m, mp); + sp_3072_mont_sqr_134(t[26], t[13], m, mp); + sp_3072_mont_mul_134(t[27], t[14], t[13], m, mp); + sp_3072_mont_sqr_134(t[28], t[14], m, mp); + sp_3072_mont_mul_134(t[29], t[15], t[14], m, mp); + sp_3072_mont_sqr_134(t[30], t[15], m, mp); + sp_3072_mont_mul_134(t[31], t[16], t[15], m, mp); + + bits = ((bits + 4) / 5) * 5; + i = ((bits + 22) / 23) - 1; + c = bits % 23; + if (c == 0) + c = 23; + if (i < 134) + n = e[i--] << (32 - c); + else { + n = 0; + i--; + } + if (c < 5) { + n |= e[i--] << (9 - c); + c += 23; + } + y = (n >> 27) & 0x1f; + n <<= 5; + c -= 5; + XMEMCPY(rt, t[y], sizeof(rt)); + for (; i>=0 || c>=5; ) { + if (c < 5) { + n |= e[i--] << (9 - c); + c += 23; + } + y = (n >> 27) & 0x1f; + n <<= 5; + c -= 5; + + sp_3072_mont_sqr_134(rt, rt, m, mp); + sp_3072_mont_sqr_134(rt, rt, m, mp); + sp_3072_mont_sqr_134(rt, rt, m, mp); + sp_3072_mont_sqr_134(rt, rt, m, mp); + sp_3072_mont_sqr_134(rt, rt, m, mp); + + sp_3072_mont_mul_134(rt, rt, t[y], m, mp); + } + + sp_3072_mont_reduce_134(rt, m, mp); + n = sp_3072_cmp_134(rt, m); + sp_3072_cond_sub_134(rt, rt, m, (n < 0) - 1); + XMEMCPY(r, rt, sizeof(rt)); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +#endif +} +#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || */ + /* WOLFSSL_HAVE_SP_DH */ + +#if defined(WOLFSSL_HAVE_SP_RSA) && !defined(SP_RSA_PRIVATE_EXP_D) && \ + !defined(RSA_LOW_MEM) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_3072_mask_67(sp_digit* r, sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<67; i++) + r[i] = a[i] & m; +#else + int i; + + for (i = 0; i < 64; i += 8) { + r[i+0] = a[i+0] & m; + r[i+1] = a[i+1] & m; + r[i+2] = a[i+2] & m; + r[i+3] = a[i+3] & m; + r[i+4] = a[i+4] & m; + r[i+5] = a[i+5] & m; + r[i+6] = a[i+6] & m; + r[i+7] = a[i+7] & m; + } + r[64] = a[64] & m; + r[65] = a[65] & m; + r[66] = a[66] & m; +#endif +} + +#endif +#ifdef WOLFSSL_HAVE_SP_RSA +/* RSA public key operation. + * + * in Array of bytes representing the number to exponentiate, base. + * inLen Number of bytes in base. + * em Public exponent. + * mm Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 384 bytes long. + * outLen Number of bytes in result. + * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when + * an array is too long and MEMORY_E when dynamic memory allocation fails. + */ +int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm, + byte* out, word32* outLen) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* d = NULL; + sp_digit* a; + sp_digit* m; + sp_digit* r; + sp_digit* norm; + sp_digit e[1]; + sp_digit mp; + int i; + int err = MP_OKAY; + + if (*outLen < 384) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(em) > 23 || inLen > 384 || + mp_count_bits(mm) != 3072)) + err = MP_READ_E; + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 134 * 5, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + a = d; + r = a + 134 * 2; + m = r + 134 * 2; + norm = r; + + sp_3072_from_bin(a, 134, in, inLen); +#if DIGIT_BIT >= 23 + e[0] = (sp_digit)em->dp[0]; +#else + e[0] = (sp_digit)em->dp[0]; + if (em->used > 1) + e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT; +#endif + if (e[0] == 0) + err = MP_EXPTMOD_E; + } + + if (err == MP_OKAY) { + sp_3072_from_mp(m, 134, mm); + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_134(norm, m); + } + if (err == MP_OKAY) { + sp_3072_mul_134(a, a, norm); + err = sp_3072_mod_134(a, a, m); + } + if (err == MP_OKAY) { + for (i=22; i>=0; i--) + if (e[0] >> i) + break; + + XMEMCPY(r, a, sizeof(sp_digit) * 134 * 2); + for (i--; i>=0; i--) { + sp_3072_mont_sqr_134(r, r, m, mp); + + if (((e[0] >> i) & 1) == 1) + sp_3072_mont_mul_134(r, r, a, m, mp); + } + sp_3072_mont_reduce_134(r, m, mp); + mp = sp_3072_cmp_134(r, m); + sp_3072_cond_sub_134(r, r, m, (mp < 0) - 1); + + sp_3072_to_bin(r, out); + *outLen = 384; + } + + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + + return err; +#else +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit ad[268], md[134], rd[268]; +#else + sp_digit* d = NULL; +#endif + sp_digit* a; + sp_digit* m; + sp_digit* r; + sp_digit e[1]; + int err = MP_OKAY; + + if (*outLen < 384) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(em) > 23 || inLen > 384 || + mp_count_bits(mm) != 3072)) + err = MP_READ_E; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 134 * 5, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + a = d; + r = a + 134 * 2; + m = r + 134 * 2; + } +#else + a = ad; + m = md; + r = rd; +#endif + + if (err == MP_OKAY) { + sp_3072_from_bin(a, 134, in, inLen); +#if DIGIT_BIT >= 23 + e[0] = (sp_digit)em->dp[0]; +#else + e[0] = (sp_digit)em->dp[0]; + if (em->used > 1) + e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT; +#endif + if (e[0] == 0) + err = MP_EXPTMOD_E; + } + if (err == MP_OKAY) { + sp_3072_from_mp(m, 134, mm); + + if (e[0] == 0x3) { + if (err == MP_OKAY) { + sp_3072_sqr_134(r, a); + err = sp_3072_mod_134(r, r, m); + } + if (err == MP_OKAY) { + sp_3072_mul_134(r, a, r); + err = sp_3072_mod_134(r, r, m); + } + } + else { + sp_digit* norm = r; + int i; + sp_digit mp; + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_134(norm, m); + + if (err == MP_OKAY) { + sp_3072_mul_134(a, a, norm); + err = sp_3072_mod_134(a, a, m); + } + + if (err == MP_OKAY) { + for (i=22; i>=0; i--) + if (e[0] >> i) + break; + + XMEMCPY(r, a, sizeof(sp_digit) * 268); + for (i--; i>=0; i--) { + sp_3072_mont_sqr_134(r, r, m, mp); + + if (((e[0] >> i) & 1) == 1) + sp_3072_mont_mul_134(r, r, a, m, mp); + } + sp_3072_mont_reduce_134(r, m, mp); + mp = sp_3072_cmp_134(r, m); + sp_3072_cond_sub_134(r, r, m, (mp < 0) - 1); + } + } + } + + if (err == MP_OKAY) { + sp_3072_to_bin(r, out); + *outLen = 384; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_RSA); +#endif + + return err; +#endif /* WOLFSSL_SP_SMALL */ +} + +#ifndef WOLFSSL_RSA_PUBLIC_ONLY +/* RSA private key operation. + * + * in Array of bytes representing the number to exponentiate, base. + * inLen Number of bytes in base. + * dm Private exponent. + * pm First prime. + * qm Second prime. + * dpm First prime's CRT exponent. + * dqm Second prime's CRT exponent. + * qim Inverse of second prime mod p. + * mm Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 384 bytes long. + * outLen Number of bytes in result. + * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when + * an array is too long and MEMORY_E when dynamic memory allocation fails. + */ +int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, + mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm, + byte* out, word32* outLen) +{ +#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* a; + sp_digit* d = NULL; + sp_digit* m; + sp_digit* r; + int err = MP_OKAY; + + (void)pm; + (void)qm; + (void)dpm; + (void)dqm; + (void)qim; + + if (*outLen < 384) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(dm) > 3072 || inLen > 384 || + mp_count_bits(mm) != 3072)) + err = MP_READ_E; + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 134 * 4, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + a = d + 134; + m = a + 134; + r = a; + + sp_3072_from_bin(a, 134, in, inLen); + sp_3072_from_mp(d, 134, dm); + sp_3072_from_mp(m, 134, mm); + err = sp_3072_mod_exp_134(r, a, d, 3072, m, 0); + } + if (err == MP_OKAY) { + sp_3072_to_bin(r, out); + *outLen = 384; + } + + if (d != NULL) { + XMEMSET(d, 0, sizeof(sp_digit) * 134); + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + } + + return err; +#else + sp_digit a[268], d[134], m[134]; + sp_digit* r = a; + int err = MP_OKAY; + + (void)pm; + (void)qm; + (void)dpm; + (void)dqm; + (void)qim; + + if (*outLen < 384) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(dm) > 3072 || inLen > 384 || + mp_count_bits(mm) != 3072)) + err = MP_READ_E; + + if (err == MP_OKAY) { + sp_3072_from_bin(a, 134, in, inLen); + sp_3072_from_mp(d, 134, dm); + sp_3072_from_mp(m, 134, mm); + err = sp_3072_mod_exp_134(r, a, d, 3072, m, 0); + } + + if (err == MP_OKAY) { + sp_3072_to_bin(r, out); + *outLen = 384; + } + + XMEMSET(d, 0, sizeof(sp_digit) * 134); + + return err; +#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */ +#else +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* t = NULL; + sp_digit* a; + sp_digit* p; + sp_digit* q; + sp_digit* dp; + sp_digit* dq; + sp_digit* qi; + sp_digit* tmp; + sp_digit* tmpa; + sp_digit* tmpb; + sp_digit* r; + int err = MP_OKAY; + + (void)dm; + (void)mm; + + if (*outLen < 384) + err = MP_TO_E; + if (err == MP_OKAY && (inLen > 384 || mp_count_bits(mm) != 3072)) + err = MP_READ_E; + + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 67 * 11, NULL, + DYNAMIC_TYPE_RSA); + if (t == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + a = t; + p = a + 134 * 2; + q = p + 67; + qi = dq = dp = q + 67; + tmpa = qi + 67; + tmpb = tmpa + 134; + + tmp = t; + r = tmp + 134; + + sp_3072_from_bin(a, 134, in, inLen); + sp_3072_from_mp(p, 67, pm); + sp_3072_from_mp(q, 67, qm); + sp_3072_from_mp(dp, 67, dpm); + err = sp_3072_mod_exp_67(tmpa, a, dp, 1536, p, 1); + } + if (err == MP_OKAY) { + sp_3072_from_mp(dq, 67, dqm); + err = sp_3072_mod_exp_67(tmpb, a, dq, 1536, q, 1); + } + if (err == MP_OKAY) { + sp_3072_sub_67(tmpa, tmpa, tmpb); + sp_3072_mask_67(tmp, p, tmpa[66] >> 31); + sp_3072_add_67(tmpa, tmpa, tmp); + + sp_3072_from_mp(qi, 67, qim); + sp_3072_mul_67(tmpa, tmpa, qi); + err = sp_3072_mod_67(tmpa, tmpa, p); + } + + if (err == MP_OKAY) { + sp_3072_mul_67(tmpa, q, tmpa); + sp_3072_add_134(r, tmpb, tmpa); + sp_3072_norm_134(r); + + sp_3072_to_bin(r, out); + *outLen = 384; + } + + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_digit) * 67 * 11); + XFREE(t, NULL, DYNAMIC_TYPE_RSA); + } + + return err; +#else + sp_digit a[134 * 2]; + sp_digit p[67], q[67], dp[67], dq[67], qi[67]; + sp_digit tmp[134], tmpa[134], tmpb[134]; + sp_digit* r = a; + int err = MP_OKAY; + + (void)dm; + (void)mm; + + if (*outLen < 384) + err = MP_TO_E; + if (err == MP_OKAY && (inLen > 384 || mp_count_bits(mm) != 3072)) + err = MP_READ_E; + + if (err == MP_OKAY) { + sp_3072_from_bin(a, 134, in, inLen); + sp_3072_from_mp(p, 67, pm); + sp_3072_from_mp(q, 67, qm); + sp_3072_from_mp(dp, 67, dpm); + sp_3072_from_mp(dq, 67, dqm); + sp_3072_from_mp(qi, 67, qim); + + err = sp_3072_mod_exp_67(tmpa, a, dp, 1536, p, 1); + } + if (err == MP_OKAY) + err = sp_3072_mod_exp_67(tmpb, a, dq, 1536, q, 1); + + if (err == MP_OKAY) { + sp_3072_sub_67(tmpa, tmpa, tmpb); + sp_3072_mask_67(tmp, p, tmpa[66] >> 31); + sp_3072_add_67(tmpa, tmpa, tmp); + sp_3072_mul_67(tmpa, tmpa, qi); + err = sp_3072_mod_67(tmpa, tmpa, p); + } + + if (err == MP_OKAY) { + sp_3072_mul_67(tmpa, tmpa, q); + sp_3072_add_134(r, tmpb, tmpa); + sp_3072_norm_134(r); + + sp_3072_to_bin(r, out); + *outLen = 384; + } + + XMEMSET(tmpa, 0, sizeof(tmpa)); + XMEMSET(tmpb, 0, sizeof(tmpb)); + XMEMSET(p, 0, sizeof(p)); + XMEMSET(q, 0, sizeof(q)); + XMEMSET(dp, 0, sizeof(dp)); + XMEMSET(dq, 0, sizeof(dq)); + XMEMSET(qi, 0, sizeof(qi)); + + return err; +#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */ +#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ +} + +#endif /* !WOLFSSL_RSA_PUBLIC_ONLY */ +#endif /* WOLFSSL_HAVE_SP_RSA */ +#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \ + !defined(WOLFSSL_RSA_PUBLIC_ONLY)) +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_3072_to_mp(sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (3072 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { +#if DIGIT_BIT == 23 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 134); + r->used = 134; + mp_clamp(r); +#elif DIGIT_BIT < 23 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 134; i++) { + r->dp[j] |= a[i] << s; + r->dp[j] &= (1l << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + while (s + DIGIT_BIT <= 23) { + s += DIGIT_BIT; + r->dp[j] &= (1l << DIGIT_BIT) - 1; + r->dp[++j] = a[i] >> s; + } + s = 23 - s; + } + r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 134; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 23 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && DIGIT_BIT != 64 + r->dp[j] &= (1l << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 23 - s; + } + else + s += 23; + } + r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returs 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ +#ifdef WOLFSSL_SP_SMALL + int err = MP_OKAY; + sp_digit* d = NULL; + sp_digit* b; + sp_digit* e; + sp_digit* m; + sp_digit* r; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 3072 || expBits > 3072 || + mp_count_bits(mod) != 3072) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 134 * 4, NULL, DYNAMIC_TYPE_DH); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + b = d; + e = b + 134 * 2; + m = e + 134; + r = b; + + sp_3072_from_mp(b, 134, base); + sp_3072_from_mp(e, 134, exp); + sp_3072_from_mp(m, 134, mod); + + err = sp_3072_mod_exp_134(r, b, e, mp_count_bits(exp), m, 0); + } + + if (err == MP_OKAY) { + err = sp_3072_to_mp(r, res); + } + + if (d != NULL) { + XMEMSET(e, 0, sizeof(sp_digit) * 134); + XFREE(d, NULL, DYNAMIC_TYPE_DH); + } + return err; +#else +#ifndef WOLFSSL_SMALL_STACK + sp_digit bd[268], ed[134], md[134]; +#else + sp_digit* d = NULL; +#endif + sp_digit* b; + sp_digit* e; + sp_digit* m; + sp_digit* r; + int err = MP_OKAY; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 3072 || expBits > 3072 || + mp_count_bits(mod) != 3072) { + err = MP_READ_E; + } + +#ifdef WOLFSSL_SMALL_STACK + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 134 * 4, NULL, DYNAMIC_TYPE_DH); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + b = d; + e = b + 134 * 2; + m = e + 134; + r = b; + } +#else + r = b = bd; + e = ed; + m = md; +#endif + + if (err == MP_OKAY) { + sp_3072_from_mp(b, 134, base); + sp_3072_from_mp(e, 134, exp); + sp_3072_from_mp(m, 134, mod); + + err = sp_3072_mod_exp_134(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + err = sp_3072_to_mp(r, res); + } + + XMEMSET(e, 0, sizeof(sp_digit) * 134); + +#ifdef WOLFSSL_SMALL_STACK + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_DH); +#endif + + return err; +#endif +} + +#ifdef WOLFSSL_HAVE_SP_DH +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. + * exp Array of bytes that is the exponent. + * expLen Length of data, in bytes, in exponent. + * mod Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 384 bytes long. + * outLen Length, in bytes, of exponentiation result. + * returs 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen, + mp_int* mod, byte* out, word32* outLen) +{ +#ifdef WOLFSSL_SP_SMALL + int err = MP_OKAY; + sp_digit* d = NULL; + sp_digit* b; + sp_digit* e; + sp_digit* m; + sp_digit* r; + word32 i; + + if (mp_count_bits(base) > 3072 || expLen > 384 || + mp_count_bits(mod) != 3072) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 134 * 4, NULL, DYNAMIC_TYPE_DH); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + b = d; + e = b + 134 * 2; + m = e + 134; + r = b; + + sp_3072_from_mp(b, 134, base); + sp_3072_from_bin(e, 134, exp, expLen); + sp_3072_from_mp(m, 134, mod); + + err = sp_3072_mod_exp_134(r, b, e, expLen * 8, m, 0); + } + + if (err == MP_OKAY) { + sp_3072_to_bin(r, out); + *outLen = 384; + for (i=0; i<384 && out[i] == 0; i++) { + } + *outLen -= i; + XMEMMOVE(out, out + i, *outLen); + } + + if (d != NULL) { + XMEMSET(e, 0, sizeof(sp_digit) * 134); + XFREE(d, NULL, DYNAMIC_TYPE_DH); + } + return err; +#else +#ifndef WOLFSSL_SMALL_STACK + sp_digit bd[268], ed[134], md[134]; +#else + sp_digit* d = NULL; +#endif + sp_digit* b; + sp_digit* e; + sp_digit* m; + sp_digit* r; + word32 i; + int err = MP_OKAY; + + if (mp_count_bits(base) > 3072 || expLen > 384 || + mp_count_bits(mod) != 3072) { + err = MP_READ_E; + } + +#ifdef WOLFSSL_SMALL_STACK + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 134 * 4, NULL, DYNAMIC_TYPE_DH); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + b = d; + e = b + 134 * 2; + m = e + 134; + r = b; + } +#else + r = b = bd; + e = ed; + m = md; +#endif + + if (err == MP_OKAY) { + sp_3072_from_mp(b, 134, base); + sp_3072_from_bin(e, 134, exp, expLen); + sp_3072_from_mp(m, 134, mod); + + err = sp_3072_mod_exp_134(r, b, e, expLen * 8, m, 0); + } + + if (err == MP_OKAY) { + sp_3072_to_bin(r, out); + *outLen = 384; + for (i=0; i<384 && out[i] == 0; i++) { + } + *outLen -= i; + XMEMMOVE(out, out + i, *outLen); + } + + XMEMSET(e, 0, sizeof(sp_digit) * 134); + +#ifdef WOLFSSL_SMALL_STACK + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_DH); +#endif + + return err; +#endif +} +#endif /* WOLFSSL_HAVE_SP_DH */ + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returs 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ +#ifdef WOLFSSL_SP_SMALL + int err = MP_OKAY; + sp_digit* d = NULL; + sp_digit* b; + sp_digit* e; + sp_digit* m; + sp_digit* r; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 1536 || expBits > 1536 || + mp_count_bits(mod) != 1536) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 67 * 4, NULL, DYNAMIC_TYPE_DH); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + b = d; + e = b + 67 * 2; + m = e + 67; + r = b; + + sp_3072_from_mp(b, 67, base); + sp_3072_from_mp(e, 67, exp); + sp_3072_from_mp(m, 67, mod); + + err = sp_3072_mod_exp_67(r, b, e, mp_count_bits(exp), m, 0); + } + + if (err == MP_OKAY) { + XMEMSET(r + 67, 0, sizeof(*r) * 67); + err = sp_3072_to_mp(r, res); + } + + if (d != NULL) { + XMEMSET(e, 0, sizeof(sp_digit) * 67); + XFREE(d, NULL, DYNAMIC_TYPE_DH); + } + return err; +#else +#ifndef WOLFSSL_SMALL_STACK + sp_digit bd[134], ed[67], md[67]; +#else + sp_digit* d = NULL; +#endif + sp_digit* b; + sp_digit* e; + sp_digit* m; + sp_digit* r; + int err = MP_OKAY; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 1536 || expBits > 1536 || + mp_count_bits(mod) != 1536) { + err = MP_READ_E; + } + +#ifdef WOLFSSL_SMALL_STACK + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 67 * 4, NULL, DYNAMIC_TYPE_DH); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + b = d; + e = b + 67 * 2; + m = e + 67; + r = b; + } +#else + r = b = bd; + e = ed; + m = md; +#endif + + if (err == MP_OKAY) { + sp_3072_from_mp(b, 67, base); + sp_3072_from_mp(e, 67, exp); + sp_3072_from_mp(m, 67, mod); + + err = sp_3072_mod_exp_67(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + XMEMSET(r + 67, 0, sizeof(*r) * 67); + err = sp_3072_to_mp(r, res); + } + + XMEMSET(e, 0, sizeof(sp_digit) * 67); + +#ifdef WOLFSSL_SMALL_STACK + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_DH); +#endif + + return err; +#endif +} + +#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ + +#endif /* !WOLFSSL_SP_NO_3072 */ + +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +#ifdef WOLFSSL_HAVE_SP_ECC +#ifndef WOLFSSL_SP_NO_256 + +/* Point structure to use. */ +typedef struct sp_point { + sp_digit x[2 * 10]; + sp_digit y[2 * 10]; + sp_digit z[2 * 10]; + int infinity; +} sp_point; + +/* The modulus (prime) of the curve P256. */ +static sp_digit p256_mod[10] = { + 0x3ffffff,0x3ffffff,0x3ffffff,0x003ffff,0x0000000,0x0000000,0x0000000, + 0x0000400,0x3ff0000,0x03fffff +}; +#ifndef WOLFSSL_SP_SMALL +/* The Montogmery normalizer for modulus of the curve P256. */ +static sp_digit p256_norm_mod[10] = { + 0x0000001,0x0000000,0x0000000,0x3fc0000,0x3ffffff,0x3ffffff,0x3ffffff, + 0x3fffbff,0x000ffff,0x0000000 +}; +#endif /* WOLFSSL_SP_SMALL */ +/* The Montogmery multiplier for modulus of the curve P256. */ +static sp_digit p256_mp_mod = 0x000001; +#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ + defined(HAVE_ECC_VERIFY) +/* The order of the curve P256. */ +static sp_digit p256_order[10] = { + 0x0632551,0x272b0bf,0x1e84f3b,0x2b69c5e,0x3bce6fa,0x3ffffff,0x3ffffff, + 0x00003ff,0x3ff0000,0x03fffff +}; +#endif +/* The order of the curve P256 minus 2. */ +static sp_digit p256_order2[10] = { + 0x063254f,0x272b0bf,0x1e84f3b,0x2b69c5e,0x3bce6fa,0x3ffffff,0x3ffffff, + 0x00003ff,0x3ff0000,0x03fffff +}; +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +/* The Montogmery normalizer for order of the curve P256. */ +static sp_digit p256_norm_order[10] = { + 0x39cdaaf,0x18d4f40,0x217b0c4,0x14963a1,0x0431905,0x0000000,0x0000000, + 0x3fffc00,0x000ffff,0x0000000 +}; +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +/* The Montogmery multiplier for order of the curve P256. */ +static sp_digit p256_mp_order = 0x200bc4f; +#endif +/* The base point of curve P256. */ +static sp_point p256_base = { + /* X ordinate */ + { + 0x098c296,0x04e5176,0x33a0f4a,0x204b7ac,0x277037d,0x0e9103c,0x3ce6e56, + 0x1091fe2,0x1f2e12c,0x01ac5f4 + }, + /* Y ordinate */ + { + 0x3bf51f5,0x1901a0d,0x1ececbb,0x15dacc5,0x22bce33,0x303e785,0x27eb4a7, + 0x1fe6e3b,0x2e2fe1a,0x013f8d0 + }, + /* Z ordinate */ + { + 0x0000001,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000,0x0000000, + 0x0000000,0x0000000,0x0000000 + }, + /* infinity */ + 0 +}; +#if defined(HAVE_ECC_CHECK_KEY) || defined(HAVE_COMP_KEY) +static sp_digit p256_b[10] = { + 0x3d2604b,0x38f0f89,0x30f63bc,0x2c3314e,0x0651d06,0x1a621af,0x2bbd557, + 0x24f9ecf,0x1d8aa3a,0x016b18d +}; +#endif + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) +/* Allocate memory for point and return error. */ +#define sp_ecc_point_new(heap, sp, p) \ + ((p = (sp_point*)XMALLOC(sizeof(sp_point), heap, DYNAMIC_TYPE_ECC)) \ + == NULL) ? MEMORY_E : MP_OKAY +#else +/* Set pointer to data and return no error. */ +#define sp_ecc_point_new(heap, sp, p) ((p = &sp) == NULL) ? MEMORY_E : MP_OKAY +#endif + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) +/* If valid pointer then clear point data if requested and free data. */ +#define sp_ecc_point_free(p, clear, heap) \ + do { \ + if (p != NULL) { \ + if (clear) \ + XMEMSET(p, 0, sizeof(*p)); \ + XFREE(p, heap, DYNAMIC_TYPE_ECC); \ + } \ + } \ + while (0) +#else +/* Clear point data if requested. */ +#define sp_ecc_point_free(p, clear, heap) \ + do { \ + if (clear) \ + XMEMSET(p, 0, sizeof(*p)); \ + } \ + while (0) +#endif + +/* Multiply a number by Montogmery normalizer mod modulus (prime). + * + * r The resulting Montgomery form number. + * a The number to convert. + * m The modulus (prime). + * returns MEMORY_E when memory allocation fails and MP_OKAY otherwise. + */ +static int sp_256_mod_mul_norm_10(sp_digit* r, sp_digit* a, sp_digit* m) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + int64_t* td; +#else + int64_t td[8]; + int64_t a32d[8]; +#endif + int64_t* t; + int64_t* a32; + int64_t o; + int err = MP_OKAY; + + (void)m; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + td = (int64_t*)XMALLOC(sizeof(int64_t) * 2 * 8, NULL, DYNAMIC_TYPE_ECC); + if (td != NULL) { + t = td; + a32 = td + 8; + } + else + err = MEMORY_E; +#else + t = td; + a32 = a32d; +#endif + + if (err == MP_OKAY) { + a32[0] = a[0]; + a32[0] |= a[1] << 26; + a32[0] &= 0xffffffff; + a32[1] = (sp_digit)(a[1] >> 6); + a32[1] |= a[2] << 20; + a32[1] &= 0xffffffff; + a32[2] = (sp_digit)(a[2] >> 12); + a32[2] |= a[3] << 14; + a32[2] &= 0xffffffff; + a32[3] = (sp_digit)(a[3] >> 18); + a32[3] |= a[4] << 8; + a32[3] &= 0xffffffff; + a32[4] = (sp_digit)(a[4] >> 24); + a32[4] |= a[5] << 2; + a32[4] |= a[6] << 28; + a32[4] &= 0xffffffff; + a32[5] = (sp_digit)(a[6] >> 4); + a32[5] |= a[7] << 22; + a32[5] &= 0xffffffff; + a32[6] = (sp_digit)(a[7] >> 10); + a32[6] |= a[8] << 16; + a32[6] &= 0xffffffff; + a32[7] = (sp_digit)(a[8] >> 16); + a32[7] |= a[9] << 10; + a32[7] &= 0xffffffff; + + /* 1 1 0 -1 -1 -1 -1 0 */ + t[0] = 0 + a32[0] + a32[1] - a32[3] - a32[4] - a32[5] - a32[6]; + /* 0 1 1 0 -1 -1 -1 -1 */ + t[1] = 0 + a32[1] + a32[2] - a32[4] - a32[5] - a32[6] - a32[7]; + /* 0 0 1 1 0 -1 -1 -1 */ + t[2] = 0 + a32[2] + a32[3] - a32[5] - a32[6] - a32[7]; + /* -1 -1 0 2 2 1 0 -1 */ + t[3] = 0 - a32[0] - a32[1] + 2 * a32[3] + 2 * a32[4] + a32[5] - a32[7]; + /* 0 -1 -1 0 2 2 1 0 */ + t[4] = 0 - a32[1] - a32[2] + 2 * a32[4] + 2 * a32[5] + a32[6]; + /* 0 0 -1 -1 0 2 2 1 */ + t[5] = 0 - a32[2] - a32[3] + 2 * a32[5] + 2 * a32[6] + a32[7]; + /* -1 -1 0 0 0 1 3 2 */ + t[6] = 0 - a32[0] - a32[1] + a32[5] + 3 * a32[6] + 2 * a32[7]; + /* 1 0 -1 -1 -1 -1 0 3 */ + t[7] = 0 + a32[0] - a32[2] - a32[3] - a32[4] - a32[5] + 3 * a32[7]; + + t[1] += t[0] >> 32; t[0] &= 0xffffffff; + t[2] += t[1] >> 32; t[1] &= 0xffffffff; + t[3] += t[2] >> 32; t[2] &= 0xffffffff; + t[4] += t[3] >> 32; t[3] &= 0xffffffff; + t[5] += t[4] >> 32; t[4] &= 0xffffffff; + t[6] += t[5] >> 32; t[5] &= 0xffffffff; + t[7] += t[6] >> 32; t[6] &= 0xffffffff; + o = t[7] >> 32; t[7] &= 0xffffffff; + t[0] += o; + t[3] -= o; + t[6] -= o; + t[7] += o; + t[1] += t[0] >> 32; t[0] &= 0xffffffff; + t[2] += t[1] >> 32; t[1] &= 0xffffffff; + t[3] += t[2] >> 32; t[2] &= 0xffffffff; + t[4] += t[3] >> 32; t[3] &= 0xffffffff; + t[5] += t[4] >> 32; t[4] &= 0xffffffff; + t[6] += t[5] >> 32; t[5] &= 0xffffffff; + t[7] += t[6] >> 32; t[6] &= 0xffffffff; + + r[0] = (sp_digit)(t[0]) & 0x3ffffff; + r[1] = (sp_digit)(t[0] >> 26); + r[1] |= t[1] << 6; + r[1] &= 0x3ffffff; + r[2] = (sp_digit)(t[1] >> 20); + r[2] |= t[2] << 12; + r[2] &= 0x3ffffff; + r[3] = (sp_digit)(t[2] >> 14); + r[3] |= t[3] << 18; + r[3] &= 0x3ffffff; + r[4] = (sp_digit)(t[3] >> 8); + r[4] |= t[4] << 24; + r[4] &= 0x3ffffff; + r[5] = (sp_digit)(t[4] >> 2) & 0x3ffffff; + r[6] = (sp_digit)(t[4] >> 28); + r[6] |= t[5] << 4; + r[6] &= 0x3ffffff; + r[7] = (sp_digit)(t[5] >> 22); + r[7] |= t[6] << 10; + r[7] &= 0x3ffffff; + r[8] = (sp_digit)(t[6] >> 16); + r[8] |= t[7] << 16; + r[8] &= 0x3ffffff; + r[9] = (sp_digit)(t[7] >> 10); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * a A multi-precision integer. + */ +static void sp_256_from_mp(sp_digit* r, int max, mp_int* a) +{ +#if DIGIT_BIT == 26 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < max; j++) + r[j] = 0; +#elif DIGIT_BIT > 26 + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= a->dp[i] << s; + r[j] &= 0x3ffffff; + s = 26 - s; + if (j + 1 >= max) + break; + r[++j] = (sp_digit)(a->dp[i] >> s); + while (s + 26 <= DIGIT_BIT) { + s += 26; + r[j] &= 0x3ffffff; + if (j + 1 >= max) + break; + if (s < DIGIT_BIT) + r[++j] = (sp_digit)(a->dp[i] >> s); + else + r[++j] = 0; + } + s = DIGIT_BIT - s; + } + + for (j++; j < max; j++) + r[j] = 0; +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 26) { + r[j] &= 0x3ffffff; + if (j + 1 >= max) + break; + s = 26 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else + s += DIGIT_BIT; + } + + for (j++; j < max; j++) + r[j] = 0; +#endif +} + +/* Convert a point of type ecc_point to type sp_point. + * + * p Point of type sp_point (result). + * pm Point of type ecc_point. + */ +static void sp_256_point_from_ecc_point_10(sp_point* p, ecc_point* pm) +{ + XMEMSET(p->x, 0, sizeof(p->x)); + XMEMSET(p->y, 0, sizeof(p->y)); + XMEMSET(p->z, 0, sizeof(p->z)); + sp_256_from_mp(p->x, 10, pm->x); + sp_256_from_mp(p->y, 10, pm->y); + sp_256_from_mp(p->z, 10, pm->z); + p->infinity = 0; +} + +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_256_to_mp(sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (256 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { +#if DIGIT_BIT == 26 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 10); + r->used = 10; + mp_clamp(r); +#elif DIGIT_BIT < 26 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 10; i++) { + r->dp[j] |= a[i] << s; + r->dp[j] &= (1l << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + while (s + DIGIT_BIT <= 26) { + s += DIGIT_BIT; + r->dp[j] &= (1l << DIGIT_BIT) - 1; + r->dp[++j] = a[i] >> s; + } + s = 26 - s; + } + r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 10; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 26 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && DIGIT_BIT != 64 + r->dp[j] &= (1l << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 26 - s; + } + else + s += 26; + } + r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Convert a point of type sp_point to type ecc_point. + * + * p Point of type sp_point. + * pm Point of type ecc_point (result). + * returns MEMORY_E when allocation of memory in ecc_point fails otherwise + * MP_OKAY. + */ +static int sp_256_point_to_ecc_point_10(sp_point* p, ecc_point* pm) +{ + int err; + + err = sp_256_to_mp(p->x, pm->x); + if (err == MP_OKAY) + err = sp_256_to_mp(p->y, pm->y); + if (err == MP_OKAY) + err = sp_256_to_mp(p->z, pm->z); + + return err; +} + +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +static sp_digit sp_256_cmp_10(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = 0; +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=9; i>=0; i--) + r |= (a[i] - b[i]) & (0 - !r); +#else + r |= (a[ 9] - b[ 9]) & (0 - !r); + r |= (a[ 8] - b[ 8]) & (0 - !r); + r |= (a[ 7] - b[ 7]) & (0 - !r); + r |= (a[ 6] - b[ 6]) & (0 - !r); + r |= (a[ 5] - b[ 5]) & (0 - !r); + r |= (a[ 4] - b[ 4]) & (0 - !r); + r |= (a[ 3] - b[ 3]) & (0 - !r); + r |= (a[ 2] - b[ 2]) & (0 - !r); + r |= (a[ 1] - b[ 1]) & (0 - !r); + r |= (a[ 0] - b[ 0]) & (0 - !r); +#endif /* WOLFSSL_SP_SMALL */ + + return r; +} + +/* Normalize the values in each word to 26. + * + * a Array of sp_digit to normalize. + */ +static void sp_256_norm_10(sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + for (i = 0; i < 9; i++) { + a[i+1] += a[i] >> 26; + a[i] &= 0x3ffffff; + } +#else + a[1] += a[0] >> 26; a[0] &= 0x3ffffff; + a[2] += a[1] >> 26; a[1] &= 0x3ffffff; + a[3] += a[2] >> 26; a[2] &= 0x3ffffff; + a[4] += a[3] >> 26; a[3] &= 0x3ffffff; + a[5] += a[4] >> 26; a[4] &= 0x3ffffff; + a[6] += a[5] >> 26; a[5] &= 0x3ffffff; + a[7] += a[6] >> 26; a[6] &= 0x3ffffff; + a[8] += a[7] >> 26; a[7] &= 0x3ffffff; + a[9] += a[8] >> 26; a[8] &= 0x3ffffff; +#endif +} + +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +static void sp_256_cond_sub_10(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i = 0; i < 10; i++) + r[i] = a[i] - (b[i] & m); +#else + r[ 0] = a[ 0] - (b[ 0] & m); + r[ 1] = a[ 1] - (b[ 1] & m); + r[ 2] = a[ 2] - (b[ 2] & m); + r[ 3] = a[ 3] - (b[ 3] & m); + r[ 4] = a[ 4] - (b[ 4] & m); + r[ 5] = a[ 5] - (b[ 5] & m); + r[ 6] = a[ 6] - (b[ 6] & m); + r[ 7] = a[ 7] - (b[ 7] & m); + r[ 8] = a[ 8] - (b[ 8] & m); + r[ 9] = a[ 9] - (b[ 9] & m); +#endif /* WOLFSSL_SP_SMALL */ +} + +#define sp_256_mont_reduce_order_10 sp_256_mont_reduce_10 + +/* Mul a by scalar b and add into r. (r += a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +SP_NOINLINE static void sp_256_mul_add_10(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int64_t tb = b; + int64_t t = 0; + int i; + + for (i = 0; i < 10; i++) { + t += (tb * a[i]) + r[i]; + r[i] = t & 0x3ffffff; + t >>= 26; + } + r[10] += t; +#else + int64_t tb = b; + int64_t t[10]; + + t[ 0] = tb * a[ 0]; + t[ 1] = tb * a[ 1]; + t[ 2] = tb * a[ 2]; + t[ 3] = tb * a[ 3]; + t[ 4] = tb * a[ 4]; + t[ 5] = tb * a[ 5]; + t[ 6] = tb * a[ 6]; + t[ 7] = tb * a[ 7]; + t[ 8] = tb * a[ 8]; + t[ 9] = tb * a[ 9]; + r[ 0] += (t[ 0] & 0x3ffffff); + r[ 1] += (t[ 0] >> 26) + (t[ 1] & 0x3ffffff); + r[ 2] += (t[ 1] >> 26) + (t[ 2] & 0x3ffffff); + r[ 3] += (t[ 2] >> 26) + (t[ 3] & 0x3ffffff); + r[ 4] += (t[ 3] >> 26) + (t[ 4] & 0x3ffffff); + r[ 5] += (t[ 4] >> 26) + (t[ 5] & 0x3ffffff); + r[ 6] += (t[ 5] >> 26) + (t[ 6] & 0x3ffffff); + r[ 7] += (t[ 6] >> 26) + (t[ 7] & 0x3ffffff); + r[ 8] += (t[ 7] >> 26) + (t[ 8] & 0x3ffffff); + r[ 9] += (t[ 8] >> 26) + (t[ 9] & 0x3ffffff); + r[10] += t[ 9] >> 26; +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Shift the result in the high 256 bits down to the bottom. + * + * r A single precision number. + * a A single precision number. + */ +static void sp_256_mont_shift_10(sp_digit* r, const sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + sp_digit n, s; + + s = a[10]; + n = a[9] >> 22; + for (i = 0; i < 9; i++) { + n += (s & 0x3ffffff) << 4; + r[i] = n & 0x3ffffff; + n >>= 26; + s = a[11 + i] + (s >> 26); + } + n += s << 4; + r[9] = n; +#else + sp_digit n, s; + + s = a[10]; n = a[9] >> 22; + n += (s & 0x3ffffff) << 4; r[ 0] = n & 0x3ffffff; + n >>= 26; s = a[11] + (s >> 26); + n += (s & 0x3ffffff) << 4; r[ 1] = n & 0x3ffffff; + n >>= 26; s = a[12] + (s >> 26); + n += (s & 0x3ffffff) << 4; r[ 2] = n & 0x3ffffff; + n >>= 26; s = a[13] + (s >> 26); + n += (s & 0x3ffffff) << 4; r[ 3] = n & 0x3ffffff; + n >>= 26; s = a[14] + (s >> 26); + n += (s & 0x3ffffff) << 4; r[ 4] = n & 0x3ffffff; + n >>= 26; s = a[15] + (s >> 26); + n += (s & 0x3ffffff) << 4; r[ 5] = n & 0x3ffffff; + n >>= 26; s = a[16] + (s >> 26); + n += (s & 0x3ffffff) << 4; r[ 6] = n & 0x3ffffff; + n >>= 26; s = a[17] + (s >> 26); + n += (s & 0x3ffffff) << 4; r[ 7] = n & 0x3ffffff; + n >>= 26; s = a[18] + (s >> 26); + n += (s & 0x3ffffff) << 4; r[ 8] = n & 0x3ffffff; + n >>= 26; s = a[19] + (s >> 26); + n += s << 4; r[ 9] = n; +#endif /* WOLFSSL_SP_SMALL */ + XMEMSET(&r[10], 0, sizeof(*r) * 10); +} + +/* Reduce the number back to 256 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +static void sp_256_mont_reduce_10(sp_digit* a, sp_digit* m, sp_digit mp) +{ + int i; + sp_digit mu; + + if (mp != 1) { + for (i=0; i<9; i++) { + mu = (a[i] * mp) & 0x3ffffff; + sp_256_mul_add_10(a+i, m, mu); + a[i+1] += a[i] >> 26; + } + mu = (a[i] * mp) & 0x3fffffl; + sp_256_mul_add_10(a+i, m, mu); + a[i+1] += a[i] >> 26; + a[i] &= 0x3ffffff; + } + else { + for (i=0; i<9; i++) { + mu = a[i] & 0x3ffffff; + sp_256_mul_add_10(a+i, p256_mod, mu); + a[i+1] += a[i] >> 26; + } + mu = a[i] & 0x3fffffl; + sp_256_mul_add_10(a+i, p256_mod, mu); + a[i+1] += a[i] >> 26; + a[i] &= 0x3ffffff; + } + + sp_256_mont_shift_10(a, a); + sp_256_cond_sub_10(a, a, m, 0 - ((a[9] >> 22) > 0)); + sp_256_norm_10(a); +} + +#ifdef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_256_mul_10(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i, j, k; + int64_t c; + + c = ((int64_t)a[9]) * b[9]; + r[19] = (sp_digit)(c >> 26); + c = (c & 0x3ffffff) << 26; + for (k = 17; k >= 0; k--) { + for (i = 9; i >= 0; i--) { + j = k - i; + if (j >= 10) + break; + if (j < 0) + continue; + + c += ((int64_t)a[i]) * b[j]; + } + r[k + 2] += c >> 52; + r[k + 1] = (c >> 26) & 0x3ffffff; + c = (c & 0x3ffffff) << 26; + } + r[0] = (sp_digit)(c >> 26); +} + +#else +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_256_mul_10(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int64_t t0 = ((int64_t)a[ 0]) * b[ 0]; + int64_t t1 = ((int64_t)a[ 0]) * b[ 1] + + ((int64_t)a[ 1]) * b[ 0]; + int64_t t2 = ((int64_t)a[ 0]) * b[ 2] + + ((int64_t)a[ 1]) * b[ 1] + + ((int64_t)a[ 2]) * b[ 0]; + int64_t t3 = ((int64_t)a[ 0]) * b[ 3] + + ((int64_t)a[ 1]) * b[ 2] + + ((int64_t)a[ 2]) * b[ 1] + + ((int64_t)a[ 3]) * b[ 0]; + int64_t t4 = ((int64_t)a[ 0]) * b[ 4] + + ((int64_t)a[ 1]) * b[ 3] + + ((int64_t)a[ 2]) * b[ 2] + + ((int64_t)a[ 3]) * b[ 1] + + ((int64_t)a[ 4]) * b[ 0]; + int64_t t5 = ((int64_t)a[ 0]) * b[ 5] + + ((int64_t)a[ 1]) * b[ 4] + + ((int64_t)a[ 2]) * b[ 3] + + ((int64_t)a[ 3]) * b[ 2] + + ((int64_t)a[ 4]) * b[ 1] + + ((int64_t)a[ 5]) * b[ 0]; + int64_t t6 = ((int64_t)a[ 0]) * b[ 6] + + ((int64_t)a[ 1]) * b[ 5] + + ((int64_t)a[ 2]) * b[ 4] + + ((int64_t)a[ 3]) * b[ 3] + + ((int64_t)a[ 4]) * b[ 2] + + ((int64_t)a[ 5]) * b[ 1] + + ((int64_t)a[ 6]) * b[ 0]; + int64_t t7 = ((int64_t)a[ 0]) * b[ 7] + + ((int64_t)a[ 1]) * b[ 6] + + ((int64_t)a[ 2]) * b[ 5] + + ((int64_t)a[ 3]) * b[ 4] + + ((int64_t)a[ 4]) * b[ 3] + + ((int64_t)a[ 5]) * b[ 2] + + ((int64_t)a[ 6]) * b[ 1] + + ((int64_t)a[ 7]) * b[ 0]; + int64_t t8 = ((int64_t)a[ 0]) * b[ 8] + + ((int64_t)a[ 1]) * b[ 7] + + ((int64_t)a[ 2]) * b[ 6] + + ((int64_t)a[ 3]) * b[ 5] + + ((int64_t)a[ 4]) * b[ 4] + + ((int64_t)a[ 5]) * b[ 3] + + ((int64_t)a[ 6]) * b[ 2] + + ((int64_t)a[ 7]) * b[ 1] + + ((int64_t)a[ 8]) * b[ 0]; + int64_t t9 = ((int64_t)a[ 0]) * b[ 9] + + ((int64_t)a[ 1]) * b[ 8] + + ((int64_t)a[ 2]) * b[ 7] + + ((int64_t)a[ 3]) * b[ 6] + + ((int64_t)a[ 4]) * b[ 5] + + ((int64_t)a[ 5]) * b[ 4] + + ((int64_t)a[ 6]) * b[ 3] + + ((int64_t)a[ 7]) * b[ 2] + + ((int64_t)a[ 8]) * b[ 1] + + ((int64_t)a[ 9]) * b[ 0]; + int64_t t10 = ((int64_t)a[ 1]) * b[ 9] + + ((int64_t)a[ 2]) * b[ 8] + + ((int64_t)a[ 3]) * b[ 7] + + ((int64_t)a[ 4]) * b[ 6] + + ((int64_t)a[ 5]) * b[ 5] + + ((int64_t)a[ 6]) * b[ 4] + + ((int64_t)a[ 7]) * b[ 3] + + ((int64_t)a[ 8]) * b[ 2] + + ((int64_t)a[ 9]) * b[ 1]; + int64_t t11 = ((int64_t)a[ 2]) * b[ 9] + + ((int64_t)a[ 3]) * b[ 8] + + ((int64_t)a[ 4]) * b[ 7] + + ((int64_t)a[ 5]) * b[ 6] + + ((int64_t)a[ 6]) * b[ 5] + + ((int64_t)a[ 7]) * b[ 4] + + ((int64_t)a[ 8]) * b[ 3] + + ((int64_t)a[ 9]) * b[ 2]; + int64_t t12 = ((int64_t)a[ 3]) * b[ 9] + + ((int64_t)a[ 4]) * b[ 8] + + ((int64_t)a[ 5]) * b[ 7] + + ((int64_t)a[ 6]) * b[ 6] + + ((int64_t)a[ 7]) * b[ 5] + + ((int64_t)a[ 8]) * b[ 4] + + ((int64_t)a[ 9]) * b[ 3]; + int64_t t13 = ((int64_t)a[ 4]) * b[ 9] + + ((int64_t)a[ 5]) * b[ 8] + + ((int64_t)a[ 6]) * b[ 7] + + ((int64_t)a[ 7]) * b[ 6] + + ((int64_t)a[ 8]) * b[ 5] + + ((int64_t)a[ 9]) * b[ 4]; + int64_t t14 = ((int64_t)a[ 5]) * b[ 9] + + ((int64_t)a[ 6]) * b[ 8] + + ((int64_t)a[ 7]) * b[ 7] + + ((int64_t)a[ 8]) * b[ 6] + + ((int64_t)a[ 9]) * b[ 5]; + int64_t t15 = ((int64_t)a[ 6]) * b[ 9] + + ((int64_t)a[ 7]) * b[ 8] + + ((int64_t)a[ 8]) * b[ 7] + + ((int64_t)a[ 9]) * b[ 6]; + int64_t t16 = ((int64_t)a[ 7]) * b[ 9] + + ((int64_t)a[ 8]) * b[ 8] + + ((int64_t)a[ 9]) * b[ 7]; + int64_t t17 = ((int64_t)a[ 8]) * b[ 9] + + ((int64_t)a[ 9]) * b[ 8]; + int64_t t18 = ((int64_t)a[ 9]) * b[ 9]; + + t1 += t0 >> 26; r[ 0] = t0 & 0x3ffffff; + t2 += t1 >> 26; r[ 1] = t1 & 0x3ffffff; + t3 += t2 >> 26; r[ 2] = t2 & 0x3ffffff; + t4 += t3 >> 26; r[ 3] = t3 & 0x3ffffff; + t5 += t4 >> 26; r[ 4] = t4 & 0x3ffffff; + t6 += t5 >> 26; r[ 5] = t5 & 0x3ffffff; + t7 += t6 >> 26; r[ 6] = t6 & 0x3ffffff; + t8 += t7 >> 26; r[ 7] = t7 & 0x3ffffff; + t9 += t8 >> 26; r[ 8] = t8 & 0x3ffffff; + t10 += t9 >> 26; r[ 9] = t9 & 0x3ffffff; + t11 += t10 >> 26; r[10] = t10 & 0x3ffffff; + t12 += t11 >> 26; r[11] = t11 & 0x3ffffff; + t13 += t12 >> 26; r[12] = t12 & 0x3ffffff; + t14 += t13 >> 26; r[13] = t13 & 0x3ffffff; + t15 += t14 >> 26; r[14] = t14 & 0x3ffffff; + t16 += t15 >> 26; r[15] = t15 & 0x3ffffff; + t17 += t16 >> 26; r[16] = t16 & 0x3ffffff; + t18 += t17 >> 26; r[17] = t17 & 0x3ffffff; + r[19] = (sp_digit)(t18 >> 26); + r[18] = t18 & 0x3ffffff; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_256_mont_mul_10(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_256_mul_10(r, a, b); + sp_256_mont_reduce_10(r, m, mp); +} + +#ifdef WOLFSSL_SP_SMALL +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_256_sqr_10(sp_digit* r, const sp_digit* a) +{ + int i, j, k; + int64_t c; + + c = ((int64_t)a[9]) * a[9]; + r[19] = (sp_digit)(c >> 26); + c = (c & 0x3ffffff) << 26; + for (k = 17; k >= 0; k--) { + for (i = 9; i >= 0; i--) { + j = k - i; + if (j >= 10 || i <= j) + break; + if (j < 0) + continue; + + c += ((int64_t)a[i]) * a[j] * 2; + } + if (i == j) + c += ((int64_t)a[i]) * a[i]; + + r[k + 2] += c >> 52; + r[k + 1] = (c >> 26) & 0x3ffffff; + c = (c & 0x3ffffff) << 26; + } + r[0] = (sp_digit)(c >> 26); +} + +#else +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_256_sqr_10(sp_digit* r, const sp_digit* a) +{ + int64_t t0 = ((int64_t)a[ 0]) * a[ 0]; + int64_t t1 = (((int64_t)a[ 0]) * a[ 1]) * 2; + int64_t t2 = (((int64_t)a[ 0]) * a[ 2]) * 2 + + ((int64_t)a[ 1]) * a[ 1]; + int64_t t3 = (((int64_t)a[ 0]) * a[ 3] + + ((int64_t)a[ 1]) * a[ 2]) * 2; + int64_t t4 = (((int64_t)a[ 0]) * a[ 4] + + ((int64_t)a[ 1]) * a[ 3]) * 2 + + ((int64_t)a[ 2]) * a[ 2]; + int64_t t5 = (((int64_t)a[ 0]) * a[ 5] + + ((int64_t)a[ 1]) * a[ 4] + + ((int64_t)a[ 2]) * a[ 3]) * 2; + int64_t t6 = (((int64_t)a[ 0]) * a[ 6] + + ((int64_t)a[ 1]) * a[ 5] + + ((int64_t)a[ 2]) * a[ 4]) * 2 + + ((int64_t)a[ 3]) * a[ 3]; + int64_t t7 = (((int64_t)a[ 0]) * a[ 7] + + ((int64_t)a[ 1]) * a[ 6] + + ((int64_t)a[ 2]) * a[ 5] + + ((int64_t)a[ 3]) * a[ 4]) * 2; + int64_t t8 = (((int64_t)a[ 0]) * a[ 8] + + ((int64_t)a[ 1]) * a[ 7] + + ((int64_t)a[ 2]) * a[ 6] + + ((int64_t)a[ 3]) * a[ 5]) * 2 + + ((int64_t)a[ 4]) * a[ 4]; + int64_t t9 = (((int64_t)a[ 0]) * a[ 9] + + ((int64_t)a[ 1]) * a[ 8] + + ((int64_t)a[ 2]) * a[ 7] + + ((int64_t)a[ 3]) * a[ 6] + + ((int64_t)a[ 4]) * a[ 5]) * 2; + int64_t t10 = (((int64_t)a[ 1]) * a[ 9] + + ((int64_t)a[ 2]) * a[ 8] + + ((int64_t)a[ 3]) * a[ 7] + + ((int64_t)a[ 4]) * a[ 6]) * 2 + + ((int64_t)a[ 5]) * a[ 5]; + int64_t t11 = (((int64_t)a[ 2]) * a[ 9] + + ((int64_t)a[ 3]) * a[ 8] + + ((int64_t)a[ 4]) * a[ 7] + + ((int64_t)a[ 5]) * a[ 6]) * 2; + int64_t t12 = (((int64_t)a[ 3]) * a[ 9] + + ((int64_t)a[ 4]) * a[ 8] + + ((int64_t)a[ 5]) * a[ 7]) * 2 + + ((int64_t)a[ 6]) * a[ 6]; + int64_t t13 = (((int64_t)a[ 4]) * a[ 9] + + ((int64_t)a[ 5]) * a[ 8] + + ((int64_t)a[ 6]) * a[ 7]) * 2; + int64_t t14 = (((int64_t)a[ 5]) * a[ 9] + + ((int64_t)a[ 6]) * a[ 8]) * 2 + + ((int64_t)a[ 7]) * a[ 7]; + int64_t t15 = (((int64_t)a[ 6]) * a[ 9] + + ((int64_t)a[ 7]) * a[ 8]) * 2; + int64_t t16 = (((int64_t)a[ 7]) * a[ 9]) * 2 + + ((int64_t)a[ 8]) * a[ 8]; + int64_t t17 = (((int64_t)a[ 8]) * a[ 9]) * 2; + int64_t t18 = ((int64_t)a[ 9]) * a[ 9]; + + t1 += t0 >> 26; r[ 0] = t0 & 0x3ffffff; + t2 += t1 >> 26; r[ 1] = t1 & 0x3ffffff; + t3 += t2 >> 26; r[ 2] = t2 & 0x3ffffff; + t4 += t3 >> 26; r[ 3] = t3 & 0x3ffffff; + t5 += t4 >> 26; r[ 4] = t4 & 0x3ffffff; + t6 += t5 >> 26; r[ 5] = t5 & 0x3ffffff; + t7 += t6 >> 26; r[ 6] = t6 & 0x3ffffff; + t8 += t7 >> 26; r[ 7] = t7 & 0x3ffffff; + t9 += t8 >> 26; r[ 8] = t8 & 0x3ffffff; + t10 += t9 >> 26; r[ 9] = t9 & 0x3ffffff; + t11 += t10 >> 26; r[10] = t10 & 0x3ffffff; + t12 += t11 >> 26; r[11] = t11 & 0x3ffffff; + t13 += t12 >> 26; r[12] = t12 & 0x3ffffff; + t14 += t13 >> 26; r[13] = t13 & 0x3ffffff; + t15 += t14 >> 26; r[14] = t14 & 0x3ffffff; + t16 += t15 >> 26; r[15] = t15 & 0x3ffffff; + t17 += t16 >> 26; r[16] = t16 & 0x3ffffff; + t18 += t17 >> 26; r[17] = t17 & 0x3ffffff; + r[19] = (sp_digit)(t18 >> 26); + r[18] = t18 & 0x3ffffff; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_256_mont_sqr_10(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_256_sqr_10(r, a); + sp_256_mont_reduce_10(r, m, mp); +} + +#if !defined(WOLFSSL_SP_SMALL) || defined(HAVE_COMP_KEY) +/* Square the Montgomery form number a number of times. (r = a ^ n mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * n Number of times to square. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_256_mont_sqr_n_10(sp_digit* r, sp_digit* a, int n, + sp_digit* m, sp_digit mp) +{ + sp_256_mont_sqr_10(r, a, m, mp); + for (; n > 1; n--) + sp_256_mont_sqr_10(r, r, m, mp); +} + +#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */ +#ifdef WOLFSSL_SP_SMALL +/* Mod-2 for the P256 curve. */ +static const uint32_t p256_mod_2[8] = { + 0xfffffffd,0xffffffff,0xffffffff,0x00000000,0x00000000,0x00000000, + 0x00000001,0xffffffff +}; +#endif /* !WOLFSSL_SP_SMALL */ + +/* Invert the number, in Montgomery form, modulo the modulus (prime) of the + * P256 curve. (r = 1 / a mod m) + * + * r Inverse result. + * a Number to invert. + * td Temporary data. + */ +static void sp_256_mont_inv_10(sp_digit* r, sp_digit* a, sp_digit* td) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* t = td; + int i; + + XMEMCPY(t, a, sizeof(sp_digit) * 10); + for (i=254; i>=0; i--) { + sp_256_mont_sqr_10(t, t, p256_mod, p256_mp_mod); + if (p256_mod_2[i / 32] & ((sp_digit)1 << (i % 32))) + sp_256_mont_mul_10(t, t, a, p256_mod, p256_mp_mod); + } + XMEMCPY(r, t, sizeof(sp_digit) * 10); +#else + sp_digit* t = td; + sp_digit* t2 = td + 2 * 10; + sp_digit* t3 = td + 4 * 10; + + /* t = a^2 */ + sp_256_mont_sqr_10(t, a, p256_mod, p256_mp_mod); + /* t = a^3 = t * a */ + sp_256_mont_mul_10(t, t, a, p256_mod, p256_mp_mod); + /* t2= a^c = t ^ 2 ^ 2 */ + sp_256_mont_sqr_n_10(t2, t, 2, p256_mod, p256_mp_mod); + /* t3= a^d = t2 * a */ + sp_256_mont_mul_10(t3, t2, a, p256_mod, p256_mp_mod); + /* t = a^f = t2 * t */ + sp_256_mont_mul_10(t, t2, t, p256_mod, p256_mp_mod); + /* t2= a^f0 = t ^ 2 ^ 4 */ + sp_256_mont_sqr_n_10(t2, t, 4, p256_mod, p256_mp_mod); + /* t3= a^fd = t2 * t3 */ + sp_256_mont_mul_10(t3, t2, t3, p256_mod, p256_mp_mod); + /* t = a^ff = t2 * t */ + sp_256_mont_mul_10(t, t2, t, p256_mod, p256_mp_mod); + /* t2= a^ff00 = t ^ 2 ^ 8 */ + sp_256_mont_sqr_n_10(t2, t, 8, p256_mod, p256_mp_mod); + /* t3= a^fffd = t2 * t3 */ + sp_256_mont_mul_10(t3, t2, t3, p256_mod, p256_mp_mod); + /* t = a^ffff = t2 * t */ + sp_256_mont_mul_10(t, t2, t, p256_mod, p256_mp_mod); + /* t2= a^ffff0000 = t ^ 2 ^ 16 */ + sp_256_mont_sqr_n_10(t2, t, 16, p256_mod, p256_mp_mod); + /* t3= a^fffffffd = t2 * t3 */ + sp_256_mont_mul_10(t3, t2, t3, p256_mod, p256_mp_mod); + /* t = a^ffffffff = t2 * t */ + sp_256_mont_mul_10(t, t2, t, p256_mod, p256_mp_mod); + /* t = a^ffffffff00000000 = t ^ 2 ^ 32 */ + sp_256_mont_sqr_n_10(t2, t, 32, p256_mod, p256_mp_mod); + /* t2= a^ffffffffffffffff = t2 * t */ + sp_256_mont_mul_10(t, t2, t, p256_mod, p256_mp_mod); + /* t2= a^ffffffff00000001 = t2 * a */ + sp_256_mont_mul_10(t2, t2, a, p256_mod, p256_mp_mod); + /* t2= a^ffffffff000000010000000000000000000000000000000000000000 + * = t2 ^ 2 ^ 160 */ + sp_256_mont_sqr_n_10(t2, t2, 160, p256_mod, p256_mp_mod); + /* t2= a^ffffffff00000001000000000000000000000000ffffffffffffffff + * = t2 * t */ + sp_256_mont_mul_10(t2, t2, t, p256_mod, p256_mp_mod); + /* t2= a^ffffffff00000001000000000000000000000000ffffffffffffffff00000000 + * = t2 ^ 2 ^ 32 */ + sp_256_mont_sqr_n_10(t2, t2, 32, p256_mod, p256_mp_mod); + /* r = a^ffffffff00000001000000000000000000000000fffffffffffffffffffffffd + * = t2 * t3 */ + sp_256_mont_mul_10(r, t2, t3, p256_mod, p256_mp_mod); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Map the Montgomery form projective co-ordinate point to an affine point. + * + * r Resulting affine co-ordinate point. + * p Montgomery form projective co-ordinate point. + * t Temporary ordinate data. + */ +static void sp_256_map_10(sp_point* r, sp_point* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*10; + int32_t n; + + sp_256_mont_inv_10(t1, p->z, t + 2*10); + + sp_256_mont_sqr_10(t2, t1, p256_mod, p256_mp_mod); + sp_256_mont_mul_10(t1, t2, t1, p256_mod, p256_mp_mod); + + /* x /= z^2 */ + sp_256_mont_mul_10(r->x, p->x, t2, p256_mod, p256_mp_mod); + XMEMSET(r->x + 10, 0, sizeof(r->x) / 2); + sp_256_mont_reduce_10(r->x, p256_mod, p256_mp_mod); + /* Reduce x to less than modulus */ + n = sp_256_cmp_10(r->x, p256_mod); + sp_256_cond_sub_10(r->x, r->x, p256_mod, 0 - (n >= 0)); + sp_256_norm_10(r->x); + + /* y /= z^3 */ + sp_256_mont_mul_10(r->y, p->y, t1, p256_mod, p256_mp_mod); + XMEMSET(r->y + 10, 0, sizeof(r->y) / 2); + sp_256_mont_reduce_10(r->y, p256_mod, p256_mp_mod); + /* Reduce y to less than modulus */ + n = sp_256_cmp_10(r->y, p256_mod); + sp_256_cond_sub_10(r->y, r->y, p256_mod, 0 - (n >= 0)); + sp_256_norm_10(r->y); + + XMEMSET(r->z, 0, sizeof(r->z)); + r->z[0] = 1; + +} + +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_256_add_10(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 10; i++) + r[i] = a[i] + b[i]; + + return 0; +} +#else +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_256_add_10(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + r[ 0] = a[ 0] + b[ 0]; + r[ 1] = a[ 1] + b[ 1]; + r[ 2] = a[ 2] + b[ 2]; + r[ 3] = a[ 3] + b[ 3]; + r[ 4] = a[ 4] + b[ 4]; + r[ 5] = a[ 5] + b[ 5]; + r[ 6] = a[ 6] + b[ 6]; + r[ 7] = a[ 7] + b[ 7]; + r[ 8] = a[ 8] + b[ 8]; + r[ 9] = a[ 9] + b[ 9]; + + return 0; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Add two Montgomery form numbers (r = a + b % m). + * + * r Result of addition. + * a First number to add in Montogmery form. + * b Second number to add in Montogmery form. + * m Modulus (prime). + */ +static void sp_256_mont_add_10(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m) +{ + sp_256_add_10(r, a, b); + sp_256_norm_10(r); + sp_256_cond_sub_10(r, r, m, 0 - ((r[9] >> 22) > 0)); + sp_256_norm_10(r); +} + +/* Double a Montgomery form number (r = a + a % m). + * + * r Result of doubling. + * a Number to double in Montogmery form. + * m Modulus (prime). + */ +static void sp_256_mont_dbl_10(sp_digit* r, sp_digit* a, sp_digit* m) +{ + sp_256_add_10(r, a, a); + sp_256_norm_10(r); + sp_256_cond_sub_10(r, r, m, 0 - ((r[9] >> 22) > 0)); + sp_256_norm_10(r); +} + +/* Triple a Montgomery form number (r = a + a + a % m). + * + * r Result of Tripling. + * a Number to triple in Montogmery form. + * m Modulus (prime). + */ +static void sp_256_mont_tpl_10(sp_digit* r, sp_digit* a, sp_digit* m) +{ + sp_256_add_10(r, a, a); + sp_256_norm_10(r); + sp_256_cond_sub_10(r, r, m, 0 - ((r[9] >> 22) > 0)); + sp_256_norm_10(r); + sp_256_add_10(r, r, a); + sp_256_norm_10(r); + sp_256_cond_sub_10(r, r, m, 0 - ((r[9] >> 22) > 0)); + sp_256_norm_10(r); +} + +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_256_sub_10(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 10; i++) + r[i] = a[i] - b[i]; + + return 0; +} + +#else +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_256_sub_10(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + r[ 0] = a[ 0] - b[ 0]; + r[ 1] = a[ 1] - b[ 1]; + r[ 2] = a[ 2] - b[ 2]; + r[ 3] = a[ 3] - b[ 3]; + r[ 4] = a[ 4] - b[ 4]; + r[ 5] = a[ 5] - b[ 5]; + r[ 6] = a[ 6] - b[ 6]; + r[ 7] = a[ 7] - b[ 7]; + r[ 8] = a[ 8] - b[ 8]; + r[ 9] = a[ 9] - b[ 9]; + + return 0; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Conditionally add a and b using the mask m. + * m is -1 to add and 0 when not. + * + * r A single precision number representing conditional add result. + * a A single precision number to add with. + * b A single precision number to add. + * m Mask value to apply. + */ +static void sp_256_cond_add_10(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i = 0; i < 10; i++) + r[i] = a[i] + (b[i] & m); +#else + r[ 0] = a[ 0] + (b[ 0] & m); + r[ 1] = a[ 1] + (b[ 1] & m); + r[ 2] = a[ 2] + (b[ 2] & m); + r[ 3] = a[ 3] + (b[ 3] & m); + r[ 4] = a[ 4] + (b[ 4] & m); + r[ 5] = a[ 5] + (b[ 5] & m); + r[ 6] = a[ 6] + (b[ 6] & m); + r[ 7] = a[ 7] + (b[ 7] & m); + r[ 8] = a[ 8] + (b[ 8] & m); + r[ 9] = a[ 9] + (b[ 9] & m); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Subtract two Montgomery form numbers (r = a - b % m). + * + * r Result of subtration. + * a Number to subtract from in Montogmery form. + * b Number to subtract with in Montogmery form. + * m Modulus (prime). + */ +static void sp_256_mont_sub_10(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m) +{ + sp_256_sub_10(r, a, b); + sp_256_cond_add_10(r, r, m, r[9] >> 22); + sp_256_norm_10(r); +} + +/* Shift number left one bit. + * Bottom bit is lost. + * + * r Result of shift. + * a Number to shift. + */ +SP_NOINLINE static void sp_256_rshift1_10(sp_digit* r, sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<9; i++) + r[i] = ((a[i] >> 1) | (a[i + 1] << 25)) & 0x3ffffff; +#else + r[0] = ((a[0] >> 1) | (a[1] << 25)) & 0x3ffffff; + r[1] = ((a[1] >> 1) | (a[2] << 25)) & 0x3ffffff; + r[2] = ((a[2] >> 1) | (a[3] << 25)) & 0x3ffffff; + r[3] = ((a[3] >> 1) | (a[4] << 25)) & 0x3ffffff; + r[4] = ((a[4] >> 1) | (a[5] << 25)) & 0x3ffffff; + r[5] = ((a[5] >> 1) | (a[6] << 25)) & 0x3ffffff; + r[6] = ((a[6] >> 1) | (a[7] << 25)) & 0x3ffffff; + r[7] = ((a[7] >> 1) | (a[8] << 25)) & 0x3ffffff; + r[8] = ((a[8] >> 1) | (a[9] << 25)) & 0x3ffffff; +#endif + r[9] = a[9] >> 1; +} + +/* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m) + * + * r Result of division by 2. + * a Number to divide. + * m Modulus (prime). + */ +static void sp_256_div2_10(sp_digit* r, sp_digit* a, sp_digit* m) +{ + sp_256_cond_add_10(r, a, m, 0 - (a[0] & 1)); + sp_256_norm_10(r); + sp_256_rshift1_10(r, r); +} + +/* Double the Montgomery form projective point p. + * + * r Result of doubling point. + * p Point to double. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_dbl_10(sp_point* r, sp_point* p, sp_digit* t) +{ + sp_point* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*10; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* When infinity don't double point passed in - constant time. */ + rp[0] = r; + rp[1] = (sp_point*)t; + XMEMSET(rp[1], 0, sizeof(sp_point)); + x = rp[p->infinity]->x; + y = rp[p->infinity]->y; + z = rp[p->infinity]->z; + /* Put point to double into result - good for infinty. */ + if (r != p) { + for (i=0; i<10; i++) + r->x[i] = p->x[i]; + for (i=0; i<10; i++) + r->y[i] = p->y[i]; + for (i=0; i<10; i++) + r->z[i] = p->z[i]; + r->infinity = p->infinity; + } + + /* T1 = Z * Z */ + sp_256_mont_sqr_10(t1, z, p256_mod, p256_mp_mod); + /* Z = Y * Z */ + sp_256_mont_mul_10(z, y, z, p256_mod, p256_mp_mod); + /* Z = 2Z */ + sp_256_mont_dbl_10(z, z, p256_mod); + /* T2 = X - T1 */ + sp_256_mont_sub_10(t2, x, t1, p256_mod); + /* T1 = X + T1 */ + sp_256_mont_add_10(t1, x, t1, p256_mod); + /* T2 = T1 * T2 */ + sp_256_mont_mul_10(t2, t1, t2, p256_mod, p256_mp_mod); + /* T1 = 3T2 */ + sp_256_mont_tpl_10(t1, t2, p256_mod); + /* Y = 2Y */ + sp_256_mont_dbl_10(y, y, p256_mod); + /* Y = Y * Y */ + sp_256_mont_sqr_10(y, y, p256_mod, p256_mp_mod); + /* T2 = Y * Y */ + sp_256_mont_sqr_10(t2, y, p256_mod, p256_mp_mod); + /* T2 = T2/2 */ + sp_256_div2_10(t2, t2, p256_mod); + /* Y = Y * X */ + sp_256_mont_mul_10(y, y, x, p256_mod, p256_mp_mod); + /* X = T1 * T1 */ + sp_256_mont_mul_10(x, t1, t1, p256_mod, p256_mp_mod); + /* X = X - Y */ + sp_256_mont_sub_10(x, x, y, p256_mod); + /* X = X - Y */ + sp_256_mont_sub_10(x, x, y, p256_mod); + /* Y = Y - X */ + sp_256_mont_sub_10(y, y, x, p256_mod); + /* Y = Y * T1 */ + sp_256_mont_mul_10(y, y, t1, p256_mod, p256_mp_mod); + /* Y = Y - T2 */ + sp_256_mont_sub_10(y, y, t2, p256_mod); + +} + +/* Compare two numbers to determine if they are equal. + * Constant time implementation. + * + * a First number to compare. + * b Second number to compare. + * returns 1 when equal and 0 otherwise. + */ +static int sp_256_cmp_equal_10(const sp_digit* a, const sp_digit* b) +{ + return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]) | (a[3] ^ b[3]) | + (a[4] ^ b[4]) | (a[5] ^ b[5]) | (a[6] ^ b[6]) | (a[7] ^ b[7]) | + (a[8] ^ b[8]) | (a[9] ^ b[9])) == 0; +} + +/* Add two Montgomery form projective points. + * + * r Result of addition. + * p Frist point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_add_10(sp_point* r, sp_point* p, sp_point* q, + sp_digit* t) +{ + sp_point* ap[2]; + sp_point* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*10; + sp_digit* t3 = t + 4*10; + sp_digit* t4 = t + 6*10; + sp_digit* t5 = t + 8*10; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + sp_point* a = p; + p = q; + q = a; + } + + /* Check double */ + sp_256_sub_10(t1, p256_mod, q->y); + sp_256_norm_10(t1); + if (sp_256_cmp_equal_10(p->x, q->x) & sp_256_cmp_equal_10(p->z, q->z) & + (sp_256_cmp_equal_10(p->y, q->y) | sp_256_cmp_equal_10(p->y, t1))) { + sp_256_proj_point_dbl_10(r, p, t); + } + else { + rp[0] = r; + rp[1] = (sp_point*)t; + XMEMSET(rp[1], 0, sizeof(sp_point)); + x = rp[p->infinity | q->infinity]->x; + y = rp[p->infinity | q->infinity]->y; + z = rp[p->infinity | q->infinity]->z; + + ap[0] = p; + ap[1] = q; + for (i=0; i<10; i++) + r->x[i] = ap[p->infinity]->x[i]; + for (i=0; i<10; i++) + r->y[i] = ap[p->infinity]->y[i]; + for (i=0; i<10; i++) + r->z[i] = ap[p->infinity]->z[i]; + r->infinity = ap[p->infinity]->infinity; + + /* U1 = X1*Z2^2 */ + sp_256_mont_sqr_10(t1, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_10(t3, t1, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_10(t1, t1, x, p256_mod, p256_mp_mod); + /* U2 = X2*Z1^2 */ + sp_256_mont_sqr_10(t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_10(t4, t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_10(t2, t2, q->x, p256_mod, p256_mp_mod); + /* S1 = Y1*Z2^3 */ + sp_256_mont_mul_10(t3, t3, y, p256_mod, p256_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_256_mont_mul_10(t4, t4, q->y, p256_mod, p256_mp_mod); + /* H = U2 - U1 */ + sp_256_mont_sub_10(t2, t2, t1, p256_mod); + /* R = S2 - S1 */ + sp_256_mont_sub_10(t4, t4, t3, p256_mod); + /* Z3 = H*Z1*Z2 */ + sp_256_mont_mul_10(z, z, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_10(z, z, t2, p256_mod, p256_mp_mod); + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_256_mont_sqr_10(x, t4, p256_mod, p256_mp_mod); + sp_256_mont_sqr_10(t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_10(y, t1, t5, p256_mod, p256_mp_mod); + sp_256_mont_mul_10(t5, t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_sub_10(x, x, t5, p256_mod); + sp_256_mont_dbl_10(t1, y, p256_mod); + sp_256_mont_sub_10(x, x, t1, p256_mod); + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_256_mont_sub_10(y, y, x, p256_mod); + sp_256_mont_mul_10(y, y, t4, p256_mod, p256_mp_mod); + sp_256_mont_mul_10(t5, t5, t3, p256_mod, p256_mp_mod); + sp_256_mont_sub_10(y, y, t5, p256_mod); + } +} + +#ifdef WOLFSSL_SP_SMALL +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_10(sp_point* r, sp_point* g, sp_digit* k, + int map, void* heap) +{ + sp_point* td; + sp_point* t[3]; + sp_digit* tmp; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + + (void)heap; + + td = (sp_point*)XMALLOC(sizeof(sp_point) * 3, heap, DYNAMIC_TYPE_ECC); + if (td == NULL) + err = MEMORY_E; + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 10 * 5, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + XMEMSET(td, 0, sizeof(*td) * 3); + + t[0] = &td[0]; + t[1] = &td[1]; + t[2] = &td[2]; + + /* t[0] = {0, 0, 1} * norm */ + t[0]->infinity = 1; + /* t[1] = {g->x, g->y, g->z} * norm */ + err = sp_256_mod_mul_norm_10(t[1]->x, g->x, p256_mod); + } + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_10(t[1]->y, g->y, p256_mod); + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_10(t[1]->z, g->z, p256_mod); + + if (err == MP_OKAY) { + i = 9; + c = 22; + n = k[i--] << (26 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = k[i--]; + c = 26; + } + + y = (n >> 25) & 1; + n <<= 1; + + sp_256_proj_point_add_10(t[y^1], t[0], t[1], tmp); + + XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), + sizeof(sp_point)); + sp_256_proj_point_dbl_10(t[2], t[2], tmp); + XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), t[2], + sizeof(sp_point)); + } + + if (map) + sp_256_map_10(r, t[0], tmp); + else + XMEMCPY(r, t[0], sizeof(sp_point)); + } + + if (tmp != NULL) { + XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 10 * 5); + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); + } + if (td != NULL) { + XMEMSET(td, 0, sizeof(sp_point) * 3); + XFREE(td, NULL, DYNAMIC_TYPE_ECC); + } + + return err; +} + +#elif defined(WOLFSSL_SP_CACHE_RESISTANT) +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_10(sp_point* r, sp_point* g, sp_digit* k, + int map, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point td[3]; + sp_digit tmpd[2 * 10 * 5]; +#endif + sp_point* t; + sp_digit* tmp; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + + (void)heap; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_point td[3]; + t = (sp_point*)XMALLOC(sizeof(*td) * 3, heap, DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 10 * 5, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; +#else + t = td; + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + t[0] = &td[0]; + t[1] = &td[1]; + t[2] = &td[2]; + + /* t[0] = {0, 0, 1} * norm */ + XMEMSET(&t[0], 0, sizeof(t[0])); + t[0].infinity = 1; + /* t[1] = {g->x, g->y, g->z} * norm */ + err = sp_256_mod_mul_norm_10(t[1].x, g->x, p256_mod); + } + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_10(t[1].y, g->y, p256_mod); + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_10(t[1].z, g->z, p256_mod); + + if (err == MP_OKAY) { + i = 9; + c = 22; + n = k[i--] << (26 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = k[i--]; + c = 26; + } + + y = (n >> 25) & 1; + n <<= 1; + + sp_256_proj_point_add_10(&t[y^1], &t[0], &t[1], tmp); + + XMEMCPY(&t[2], (void*)(((size_t)&t[0] & addr_mask[y^1]) + + ((size_t)&t[1] & addr_mask[y])), sizeof(t[2])); + sp_256_proj_point_dbl_10(&t[2], &t[2], tmp); + XMEMCPY((void*)(((size_t)&t[0] & addr_mask[y^1]) + + ((size_t)&t[1] & addr_mask[y])), &t[2], sizeof(t[2])); + } + + if (map) + sp_256_map_10(r, &t[0], tmp); + else + XMEMCPY(r, &t[0], sizeof(sp_point)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (tmp != NULL) { + XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 10 * 5); + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + } + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_point) * 3); + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } +#else + ForceZero(tmpd, sizeof(tmpd)); + ForceZero(td, sizeof(td)); +#endif + + return err; +} + +#else +/* A table entry for pre-computed points. */ +typedef struct sp_table_entry { + sp_digit x[10]; + sp_digit y[10]; + byte infinity; +} sp_table_entry; + +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_fast_10(sp_point* r, sp_point* g, sp_digit* k, + int map, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point td[16]; + sp_point rtd; + sp_digit tmpd[2 * 10 * 5]; +#endif + sp_point* t; + sp_point* rt; + sp_digit* tmp; + sp_digit n; + int i; + int c, y; + int err; + + (void)heap; + + err = sp_ecc_point_new(heap, rtd, rt); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + t = (sp_point*)XMALLOC(sizeof(sp_point) * 16, heap, DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 10 * 5, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; +#else + t = td; + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + /* t[0] = {0, 0, 1} * norm */ + XMEMSET(&t[0], 0, sizeof(t[0])); + t[0].infinity = 1; + /* t[1] = {g->x, g->y, g->z} * norm */ + sp_256_mod_mul_norm_10(t[1].x, g->x, p256_mod); + sp_256_mod_mul_norm_10(t[1].y, g->y, p256_mod); + sp_256_mod_mul_norm_10(t[1].z, g->z, p256_mod); + t[1].infinity = 0; + sp_256_proj_point_dbl_10(&t[ 2], &t[ 1], tmp); + t[ 2].infinity = 0; + sp_256_proj_point_add_10(&t[ 3], &t[ 2], &t[ 1], tmp); + t[ 3].infinity = 0; + sp_256_proj_point_dbl_10(&t[ 4], &t[ 2], tmp); + t[ 4].infinity = 0; + sp_256_proj_point_add_10(&t[ 5], &t[ 3], &t[ 2], tmp); + t[ 5].infinity = 0; + sp_256_proj_point_dbl_10(&t[ 6], &t[ 3], tmp); + t[ 6].infinity = 0; + sp_256_proj_point_add_10(&t[ 7], &t[ 4], &t[ 3], tmp); + t[ 7].infinity = 0; + sp_256_proj_point_dbl_10(&t[ 8], &t[ 4], tmp); + t[ 8].infinity = 0; + sp_256_proj_point_add_10(&t[ 9], &t[ 5], &t[ 4], tmp); + t[ 9].infinity = 0; + sp_256_proj_point_dbl_10(&t[10], &t[ 5], tmp); + t[10].infinity = 0; + sp_256_proj_point_add_10(&t[11], &t[ 6], &t[ 5], tmp); + t[11].infinity = 0; + sp_256_proj_point_dbl_10(&t[12], &t[ 6], tmp); + t[12].infinity = 0; + sp_256_proj_point_add_10(&t[13], &t[ 7], &t[ 6], tmp); + t[13].infinity = 0; + sp_256_proj_point_dbl_10(&t[14], &t[ 7], tmp); + t[14].infinity = 0; + sp_256_proj_point_add_10(&t[15], &t[ 8], &t[ 7], tmp); + t[15].infinity = 0; + + i = 8; + n = k[i+1] << 6; + c = 18; + y = n >> 24; + XMEMCPY(rt, &t[y], sizeof(sp_point)); + n <<= 8; + for (; i>=0 || c>=4; ) { + if (c < 4) { + n |= k[i--] << (6 - c); + c += 26; + } + y = (n >> 28) & 0xf; + n <<= 4; + c -= 4; + + sp_256_proj_point_dbl_10(rt, rt, tmp); + sp_256_proj_point_dbl_10(rt, rt, tmp); + sp_256_proj_point_dbl_10(rt, rt, tmp); + sp_256_proj_point_dbl_10(rt, rt, tmp); + + sp_256_proj_point_add_10(rt, rt, &t[y], tmp); + } + + if (map) + sp_256_map_10(r, rt, tmp); + else + XMEMCPY(r, rt, sizeof(sp_point)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (tmp != NULL) { + XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 10 * 5); + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + } + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_point) * 16); + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } +#else + ForceZero(tmpd, sizeof(tmpd)); + ForceZero(td, sizeof(td)); +#endif + sp_ecc_point_free(rt, 1, heap); + + return err; +} + +#ifdef FP_ECC +/* Double the Montgomery form projective point p a number of times. + * + * r Result of repeated doubling of point. + * p Point to double. + * n Number of times to double + * t Temporary ordinate data. + */ +static void sp_256_proj_point_dbl_n_10(sp_point* r, sp_point* p, int n, + sp_digit* t) +{ + sp_point* rp[2]; + sp_digit* w = t; + sp_digit* a = t + 2*10; + sp_digit* b = t + 4*10; + sp_digit* t1 = t + 6*10; + sp_digit* t2 = t + 8*10; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + rp[0] = r; + rp[1] = (sp_point*)t; + XMEMSET(rp[1], 0, sizeof(sp_point)); + x = rp[p->infinity]->x; + y = rp[p->infinity]->y; + z = rp[p->infinity]->z; + if (r != p) { + for (i=0; i<10; i++) + r->x[i] = p->x[i]; + for (i=0; i<10; i++) + r->y[i] = p->y[i]; + for (i=0; i<10; i++) + r->z[i] = p->z[i]; + r->infinity = p->infinity; + } + + /* Y = 2*Y */ + sp_256_mont_dbl_10(y, y, p256_mod); + /* W = Z^4 */ + sp_256_mont_sqr_10(w, z, p256_mod, p256_mp_mod); + sp_256_mont_sqr_10(w, w, p256_mod, p256_mp_mod); + while (n--) { + /* A = 3*(X^2 - W) */ + sp_256_mont_sqr_10(t1, x, p256_mod, p256_mp_mod); + sp_256_mont_sub_10(t1, t1, w, p256_mod); + sp_256_mont_tpl_10(a, t1, p256_mod); + /* B = X*Y^2 */ + sp_256_mont_sqr_10(t2, y, p256_mod, p256_mp_mod); + sp_256_mont_mul_10(b, t2, x, p256_mod, p256_mp_mod); + /* X = A^2 - 2B */ + sp_256_mont_sqr_10(x, a, p256_mod, p256_mp_mod); + sp_256_mont_dbl_10(t1, b, p256_mod); + sp_256_mont_sub_10(x, x, t1, p256_mod); + /* Z = Z*Y */ + sp_256_mont_mul_10(z, z, y, p256_mod, p256_mp_mod); + /* t2 = Y^4 */ + sp_256_mont_sqr_10(t2, t2, p256_mod, p256_mp_mod); + if (n) { + /* W = W*Y^4 */ + sp_256_mont_mul_10(w, w, t2, p256_mod, p256_mp_mod); + } + /* y = 2*A*(B - X) - Y^4 */ + sp_256_mont_sub_10(y, b, x, p256_mod); + sp_256_mont_mul_10(y, y, a, p256_mod, p256_mp_mod); + sp_256_mont_dbl_10(y, y, p256_mod); + sp_256_mont_sub_10(y, y, t2, p256_mod); + } + /* Y = Y/2 */ + sp_256_div2_10(y, y, p256_mod); +} + +#endif /* FP_ECC */ +/* Add two Montgomery form projective points. The second point has a q value of + * one. + * Only the first point can be the same pointer as the result point. + * + * r Result of addition. + * p Frist point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_add_qz1_10(sp_point* r, sp_point* p, + sp_point* q, sp_digit* t) +{ + sp_point* ap[2]; + sp_point* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*10; + sp_digit* t3 = t + 4*10; + sp_digit* t4 = t + 6*10; + sp_digit* t5 = t + 8*10; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* Check double */ + sp_256_sub_10(t1, p256_mod, q->y); + sp_256_norm_10(t1); + if (sp_256_cmp_equal_10(p->x, q->x) & sp_256_cmp_equal_10(p->z, q->z) & + (sp_256_cmp_equal_10(p->y, q->y) | sp_256_cmp_equal_10(p->y, t1))) { + sp_256_proj_point_dbl_10(r, p, t); + } + else { + rp[0] = r; + rp[1] = (sp_point*)t; + XMEMSET(rp[1], 0, sizeof(sp_point)); + x = rp[p->infinity | q->infinity]->x; + y = rp[p->infinity | q->infinity]->y; + z = rp[p->infinity | q->infinity]->z; + + ap[0] = p; + ap[1] = q; + for (i=0; i<10; i++) + r->x[i] = ap[p->infinity]->x[i]; + for (i=0; i<10; i++) + r->y[i] = ap[p->infinity]->y[i]; + for (i=0; i<10; i++) + r->z[i] = ap[p->infinity]->z[i]; + r->infinity = ap[p->infinity]->infinity; + + /* U2 = X2*Z1^2 */ + sp_256_mont_sqr_10(t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_10(t4, t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_10(t2, t2, q->x, p256_mod, p256_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_256_mont_mul_10(t4, t4, q->y, p256_mod, p256_mp_mod); + /* H = U2 - X1 */ + sp_256_mont_sub_10(t2, t2, x, p256_mod); + /* R = S2 - Y1 */ + sp_256_mont_sub_10(t4, t4, y, p256_mod); + /* Z3 = H*Z1 */ + sp_256_mont_mul_10(z, z, t2, p256_mod, p256_mp_mod); + /* X3 = R^2 - H^3 - 2*X1*H^2 */ + sp_256_mont_sqr_10(t1, t4, p256_mod, p256_mp_mod); + sp_256_mont_sqr_10(t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_10(t3, x, t5, p256_mod, p256_mp_mod); + sp_256_mont_mul_10(t5, t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_sub_10(x, t1, t5, p256_mod); + sp_256_mont_dbl_10(t1, t3, p256_mod); + sp_256_mont_sub_10(x, x, t1, p256_mod); + /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */ + sp_256_mont_sub_10(t3, t3, x, p256_mod); + sp_256_mont_mul_10(t3, t3, t4, p256_mod, p256_mp_mod); + sp_256_mont_mul_10(t5, t5, y, p256_mod, p256_mp_mod); + sp_256_mont_sub_10(y, t3, t5, p256_mod); + } +} + +#ifdef FP_ECC +/* Convert the projective point to affine. + * Ordinates are in Montgomery form. + * + * a Point to convert. + * t Temprorary data. + */ +static void sp_256_proj_to_affine_10(sp_point* a, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 10; + sp_digit* tmp = t + 4 * 10; + + sp_256_mont_inv_10(t1, a->z, tmp); + + sp_256_mont_sqr_10(t2, t1, p256_mod, p256_mp_mod); + sp_256_mont_mul_10(t1, t2, t1, p256_mod, p256_mp_mod); + + sp_256_mont_mul_10(a->x, a->x, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_10(a->y, a->y, t1, p256_mod, p256_mp_mod); + XMEMCPY(a->z, p256_norm_mod, sizeof(p256_norm_mod)); +} + +/* Generate the pre-computed table of points for the base point. + * + * a The base point. + * table Place to store generated point data. + * tmp Temprorary data. + * heap Heap to use for allocation. + */ +static int sp_256_gen_stripe_table_10(sp_point* a, + sp_table_entry* table, sp_digit* tmp, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point td, s1d, s2d; +#endif + sp_point* t; + sp_point* s1 = NULL; + sp_point* s2 = NULL; + int i, j; + int err; + + (void)heap; + + err = sp_ecc_point_new(heap, td, t); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, s1d, s1); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, s2d, s2); + + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_10(t->x, a->x, p256_mod); + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_10(t->y, a->y, p256_mod); + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_10(t->z, a->z, p256_mod); + if (err == MP_OKAY) { + t->infinity = 0; + sp_256_proj_to_affine_10(t, tmp); + + XMEMCPY(s1->z, p256_norm_mod, sizeof(p256_norm_mod)); + s1->infinity = 0; + XMEMCPY(s2->z, p256_norm_mod, sizeof(p256_norm_mod)); + s2->infinity = 0; + + /* table[0] = {0, 0, infinity} */ + XMEMSET(&table[0], 0, sizeof(sp_table_entry)); + table[0].infinity = 1; + /* table[1] = Affine version of 'a' in Montgomery form */ + XMEMCPY(table[1].x, t->x, sizeof(table->x)); + XMEMCPY(table[1].y, t->y, sizeof(table->y)); + table[1].infinity = 0; + + for (i=1; i<8; i++) { + sp_256_proj_point_dbl_n_10(t, t, 32, tmp); + sp_256_proj_to_affine_10(t, tmp); + XMEMCPY(table[1<x, sizeof(table->x)); + XMEMCPY(table[1<y, sizeof(table->y)); + table[1<x, table[1<x)); + XMEMCPY(s1->y, table[1<y)); + for (j=(1<x, table[j-(1<x)); + XMEMCPY(s2->y, table[j-(1<y)); + sp_256_proj_point_add_qz1_10(t, s1, s2, tmp); + sp_256_proj_to_affine_10(t, tmp); + XMEMCPY(table[j].x, t->x, sizeof(table->x)); + XMEMCPY(table[j].y, t->y, sizeof(table->y)); + table[j].infinity = 0; + } + } + } + + sp_ecc_point_free(s2, 0, heap); + sp_ecc_point_free(s1, 0, heap); + sp_ecc_point_free( t, 0, heap); + + return err; +} + +#endif /* FP_ECC */ +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_stripe_10(sp_point* r, sp_point* g, + sp_table_entry* table, sp_digit* k, int map, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point rtd; + sp_point pd; + sp_digit td[2 * 10 * 5]; +#endif + sp_point* rt; + sp_point* p = NULL; + sp_digit* t; + int i, j; + int y, x; + int err; + + (void)g; + (void)heap; + + err = sp_ecc_point_new(heap, rtd, rt); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 10 * 5, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#else + t = td; +#endif + + if (err == MP_OKAY) { + XMEMCPY(p->z, p256_norm_mod, sizeof(p256_norm_mod)); + XMEMCPY(rt->z, p256_norm_mod, sizeof(p256_norm_mod)); + + y = 0; + for (j=0,x=31; j<8; j++,x+=32) + y |= ((k[x / 26] >> (x % 26)) & 1) << j; + XMEMCPY(rt->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(rt->y, table[y].y, sizeof(table[y].y)); + rt->infinity = table[y].infinity; + for (i=30; i>=0; i--) { + y = 0; + for (j=0,x=i; j<8; j++,x+=32) + y |= ((k[x / 26] >> (x % 26)) & 1) << j; + + sp_256_proj_point_dbl_10(rt, rt, t); + XMEMCPY(p->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(p->y, table[y].y, sizeof(table[y].y)); + p->infinity = table[y].infinity; + sp_256_proj_point_add_qz1_10(rt, rt, p, t); + } + + if (map) + sp_256_map_10(r, rt, t); + else + XMEMCPY(r, rt, sizeof(sp_point)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p, 0, heap); + sp_ecc_point_free(rt, 0, heap); + + return err; +} + +#ifdef FP_ECC +#ifndef FP_ENTRIES + #define FP_ENTRIES 16 +#endif + +typedef struct sp_cache_t { + sp_digit x[10]; + sp_digit y[10]; + sp_table_entry table[256]; + uint32_t cnt; + int set; +} sp_cache_t; + +static THREAD_LS_T sp_cache_t sp_cache[FP_ENTRIES]; +static THREAD_LS_T int sp_cache_last = -1; +static THREAD_LS_T int sp_cache_inited = 0; + +#ifndef HAVE_THREAD_LS + static volatile int initCacheMutex = 0; + static wolfSSL_Mutex sp_cache_lock; +#endif + +static void sp_ecc_get_cache(sp_point* g, sp_cache_t** cache) +{ + int i, j; + uint32_t least; + + if (sp_cache_inited == 0) { + for (i=0; ix, sp_cache[i].x) & + sp_256_cmp_equal_10(g->y, sp_cache[i].y)) { + sp_cache[i].cnt++; + break; + } + } + + /* No match. */ + if (i == FP_ENTRIES) { + /* Find empty entry. */ + i = (sp_cache_last + 1) % FP_ENTRIES; + for (; i != sp_cache_last; i=(i+1)%FP_ENTRIES) { + if (!sp_cache[i].set) { + break; + } + } + + /* Evict least used. */ + if (i == sp_cache_last) { + least = sp_cache[0].cnt; + for (j=1; jx, sizeof(sp_cache[i].x)); + XMEMCPY(sp_cache[i].y, g->y, sizeof(sp_cache[i].y)); + sp_cache[i].set = 1; + sp_cache[i].cnt = 1; + } + + *cache = &sp_cache[i]; + sp_cache_last = i; +} +#endif /* FP_ECC */ + +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_10(sp_point* r, sp_point* g, sp_digit* k, + int map, void* heap) +{ +#ifndef FP_ECC + return sp_256_ecc_mulmod_fast_10(r, g, k, map, heap); +#else + sp_digit tmp[2 * 10 * 5]; + sp_cache_t* cache; + int err = MP_OKAY; + +#ifndef HAVE_THREAD_LS + if (initCacheMutex == 0) { + wc_InitMutex(&sp_cache_lock); + initCacheMutex = 1; + } + if (wc_LockMutex(&sp_cache_lock) != 0) + err = BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + if (err == MP_OKAY) { + sp_ecc_get_cache(g, &cache); + if (cache->cnt == 2) + sp_256_gen_stripe_table_10(g, cache->table, tmp, heap); + +#ifndef HAVE_THREAD_LS + wc_UnLockMutex(&sp_cache_lock); +#endif /* HAVE_THREAD_LS */ + + if (cache->cnt < 2) { + err = sp_256_ecc_mulmod_fast_10(r, g, k, map, heap); + } + else { + err = sp_256_ecc_mulmod_stripe_10(r, g, cache->table, k, + map, heap); + } + } + + return err; +#endif +} + +#endif +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * km Scalar to multiply by. + * p Point to multiply. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_256(mp_int* km, ecc_point* gm, ecc_point* r, int map, + void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point p; + sp_digit kd[10]; +#endif + sp_point* point; + sp_digit* k = NULL; + int err = MP_OKAY; + + err = sp_ecc_point_new(heap, p, point); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 10, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + if (err == MP_OKAY) { + sp_256_from_mp(k, 10, km); + sp_256_point_from_ecc_point_10(point, gm); + + err = sp_256_ecc_mulmod_10(point, point, k, map, heap); + } + if (err == MP_OKAY) + err = sp_256_point_to_ecc_point_10(point, r); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(point, 0, heap); + + return err; +} + +#ifdef WOLFSSL_SP_SMALL +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_base_10(sp_point* r, sp_digit* k, + int map, void* heap) +{ + /* No pre-computed values. */ + return sp_256_ecc_mulmod_10(r, &p256_base, k, map, heap); +} + +#else +static sp_table_entry p256_table[256] = { + /* 0 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 */ + { { 0x0a9143c,0x1cc3506,0x360179e,0x3f17fb6,0x075ba95,0x1d88944, + 0x3b732b7,0x15719e7,0x376a537,0x0062417 }, + { 0x295560a,0x094d5f3,0x245cddf,0x392e867,0x18b4ab8,0x3487cc9, + 0x288688d,0x176174b,0x3182588,0x0215c7f }, + 0 }, + /* 2 */ + { { 0x147519a,0x2218090,0x32f0202,0x2b09acd,0x0d0981e,0x1e17af2, + 0x14a7caa,0x163a6a7,0x10ddbdf,0x03654f1 }, + { 0x1590f8f,0x0d8733f,0x09179d6,0x1ad139b,0x372e962,0x0bad933, + 0x1961102,0x223cdff,0x37e9eb2,0x0218fae }, + 0 }, + /* 3 */ + { { 0x0db6485,0x1ad88d7,0x2f97785,0x288bc28,0x3808f0e,0x3df8c02, + 0x28d9544,0x20280f9,0x055b5ff,0x00001d8 }, + { 0x38d2010,0x13ae6e0,0x308a763,0x2ecc90d,0x254014f,0x10a9981, + 0x247d398,0x0fb8383,0x3613437,0x020c21d }, + 0 }, + /* 4 */ + { { 0x2a0d2bb,0x08bf145,0x34994f9,0x1b06988,0x30d5cc1,0x1f18b22, + 0x01cf3a5,0x199fe49,0x161fd1b,0x00bd79a }, + { 0x1a01797,0x171c2fd,0x21925c1,0x1358255,0x23d20b4,0x1c7f6d4, + 0x111b370,0x03dec12,0x1168d6f,0x03d923e }, + 0 }, + /* 5 */ + { { 0x137bbbc,0x19a11f8,0x0bec9e5,0x27a29a8,0x3e43446,0x275cd18, + 0x0427617,0x00056c7,0x285133d,0x016af80 }, + { 0x04c7dab,0x2a0df30,0x0c0792a,0x1310c98,0x3573d9f,0x239b30d, + 0x1315627,0x1ce0c32,0x25b6b6f,0x0252edc }, + 0 }, + /* 6 */ + { { 0x20f141c,0x26d23dc,0x3c74bbf,0x334b7d6,0x06199b3,0x0441171, + 0x3f61294,0x313bf70,0x3cb2f7d,0x03375ae }, + { 0x2f436fd,0x19c02fa,0x26becca,0x1b6e64c,0x26f647f,0x053c948, + 0x0fa7920,0x397d830,0x2bd4bda,0x028d86f }, + 0 }, + /* 7 */ + { { 0x17c13c7,0x2895616,0x03e128a,0x17d42df,0x1c38d63,0x0f02747, + 0x039aecf,0x0a4b01c,0x209c4b5,0x02e84b2 }, + { 0x1f91dfd,0x023e916,0x07fb9e4,0x19b3ba8,0x13af43b,0x35e02ca, + 0x0eb0899,0x3bd2c7b,0x19d701f,0x014faee }, + 0 }, + /* 8 */ + { { 0x0e63d34,0x1fb8c6c,0x0fab4fe,0x1caa795,0x0f46005,0x179ed69, + 0x093334d,0x120c701,0x39206d5,0x021627e }, + { 0x183553a,0x03d7319,0x09e5aa7,0x12b8959,0x2087909,0x0011194, + 0x1045071,0x0713f32,0x16d0254,0x03aec1a }, + 0 }, + /* 9 */ + { { 0x01647c5,0x1b2856b,0x1799461,0x11f133d,0x0b8127d,0x1937eeb, + 0x266aa37,0x1f68f71,0x0cbd1b2,0x03aca08 }, + { 0x287e008,0x1be361a,0x38f3940,0x276488d,0x2d87dfa,0x0333b2c, + 0x2d2e428,0x368755b,0x09b55a7,0x007ca0a }, + 0 }, + /* 10 */ + { { 0x389da99,0x2a8300e,0x0022abb,0x27ae0a1,0x0a6f2d7,0x207017a, + 0x047862b,0x1358c9e,0x35905e5,0x00cde92 }, + { 0x1f7794a,0x1d40348,0x3f613c6,0x2ddf5b5,0x0207005,0x133f5ba, + 0x1a37810,0x3ef5829,0x0d5f4c2,0x0035978 }, + 0 }, + /* 11 */ + { { 0x1275d38,0x026efad,0x2358d9d,0x1142f82,0x14268a7,0x1cfac99, + 0x362ff49,0x288cbc1,0x24252f4,0x0308f68 }, + { 0x394520c,0x06e13c2,0x178e5da,0x18ec16f,0x1096667,0x134a7a8, + 0x0dcb869,0x33fc4e9,0x38cc790,0x006778e }, + 0 }, + /* 12 */ + { { 0x2c5fe04,0x29c5b09,0x1bdb183,0x02ceee8,0x03b28de,0x132dc4b, + 0x32c586a,0x32ff5d0,0x3d491fc,0x038d372 }, + { 0x2a58403,0x2351aea,0x3a53b40,0x21a0ba5,0x39a6974,0x1aaaa2b, + 0x3901273,0x03dfe78,0x3447b4e,0x039d907 }, + 0 }, + /* 13 */ + { { 0x364ba59,0x14e5077,0x02fc7d7,0x3b02c09,0x1d33f10,0x0560616, + 0x06dfc6a,0x15efd3c,0x357052a,0x01284b7 }, + { 0x039dbd0,0x18ce3e5,0x3e1fbfa,0x352f794,0x0d3c24b,0x07c6cc5, + 0x1e4ffa2,0x3a91bf5,0x293bb5b,0x01abd6a }, + 0 }, + /* 14 */ + { { 0x0c91999,0x02da644,0x0491da1,0x100a960,0x00a24b4,0x2330824, + 0x0094b4b,0x1004cf8,0x35a66a4,0x017f8d1 }, + { 0x13e7b4b,0x232af7e,0x391ab0f,0x069f08f,0x3292b50,0x3479898, + 0x2889aec,0x2a4590b,0x308ecfe,0x02d5138 }, + 0 }, + /* 15 */ + { { 0x2ddfdce,0x231ba45,0x39e6647,0x19be245,0x12c3291,0x35399f8, + 0x0d6e764,0x3082d3a,0x2bda6b0,0x0382dac }, + { 0x37efb57,0x04b7cae,0x00070d3,0x379e431,0x01aac0d,0x1e6f251, + 0x0336ad6,0x0ddd3e4,0x3de25a6,0x01c7008 }, + 0 }, + /* 16 */ + { { 0x3e20925,0x230912f,0x286762a,0x30e3f73,0x391c19a,0x34e1c18, + 0x16a5d5d,0x093d96a,0x3d421d3,0x0187561 }, + { 0x37173ea,0x19ce8a8,0x0b65e87,0x0214dde,0x2238480,0x16ead0f, + 0x38441e0,0x3bef843,0x2124621,0x03e847f }, + 0 }, + /* 17 */ + { { 0x0b19ffd,0x247cacb,0x3c231c8,0x16ec648,0x201ba8d,0x2b172a3, + 0x103d678,0x2fb72db,0x04c1f13,0x0161bac }, + { 0x3e8ed09,0x171b949,0x2de20c3,0x0f06067,0x21e81a3,0x1b194be, + 0x0fd6c05,0x13c449e,0x0087086,0x006756b }, + 0 }, + /* 18 */ + { { 0x09a4e1f,0x27d604c,0x00741e9,0x06fa49c,0x0ab7de7,0x3f4a348, + 0x25ef0be,0x158fc9a,0x33f7f9c,0x039f001 }, + { 0x2f59f76,0x3598e83,0x30501f6,0x15083f2,0x0669b3b,0x29980b5, + 0x0c1f7a7,0x0f02b02,0x0fec65b,0x0382141 }, + 0 }, + /* 19 */ + { { 0x031b3ca,0x23da368,0x2d66f09,0x27b9b69,0x06d1cab,0x13c91ba, + 0x3d81fa9,0x25ad16f,0x0825b09,0x01e3c06 }, + { 0x225787f,0x3bf790e,0x2c9bb7e,0x0347732,0x28016f8,0x0d6ff0d, + 0x2a4877b,0x1d1e833,0x3b87e94,0x010e9dc }, + 0 }, + /* 20 */ + { { 0x2b533d5,0x1ddcd34,0x1dc0625,0x3da86f7,0x3673b8a,0x1e7b0a4, + 0x3e7c9aa,0x19ac55d,0x251c3b2,0x02edb79 }, + { 0x25259b3,0x24c0ead,0x3480e7e,0x34f40e9,0x3d6a0af,0x2cf3f09, + 0x2c83d19,0x2e66f16,0x19a5d18,0x0182d18 }, + 0 }, + /* 21 */ + { { 0x2e5aa1c,0x28e3846,0x3658bd6,0x0ad279c,0x1b8b765,0x397e1fb, + 0x130014e,0x3ff342c,0x3b2aeeb,0x02743c9 }, + { 0x2730a55,0x0918c5e,0x083aca9,0x0bf76ef,0x19c955b,0x300669c, + 0x01dfe0a,0x312341f,0x26d356e,0x0091295 }, + 0 }, + /* 22 */ + { { 0x2cf1f96,0x00e52ba,0x271c6db,0x2a40930,0x19f2122,0x0b2f4ee, + 0x26ac1b8,0x3bda498,0x0873581,0x0117963 }, + { 0x38f9dbc,0x3d1e768,0x2040d3f,0x11ba222,0x3a8aaf1,0x1b82fb5, + 0x1adfb24,0x2de9251,0x21cc1e4,0x0301038 }, + 0 }, + /* 23 */ + { { 0x38117b6,0x2bc001b,0x1433847,0x3fdce8d,0x3651969,0x3651d7a, + 0x2b35761,0x1bb1d20,0x097682c,0x00737d7 }, + { 0x1f04839,0x1dd6d04,0x16987db,0x3d12378,0x17dbeac,0x1c2cc86, + 0x121dd1b,0x3fcf6ca,0x1f8a92d,0x00119d5 }, + 0 }, + /* 24 */ + { { 0x0e8ffcd,0x2b174af,0x1a82cc8,0x22cbf98,0x30d53c4,0x080b5b1, + 0x3161727,0x297cfdb,0x2113b83,0x0011b97 }, + { 0x0007f01,0x23fd936,0x3183e7b,0x0496bd0,0x07fb1ef,0x178680f, + 0x1c5ea63,0x0016c11,0x2c3303d,0x01b8041 }, + 0 }, + /* 25 */ + { { 0x0dd73b1,0x1cd6122,0x10d948c,0x23e657b,0x3767070,0x15a8aad, + 0x385ea8c,0x33c7ce0,0x0ede901,0x0110965 }, + { 0x2d4b65b,0x2a8b244,0x0c37f8f,0x0ee5b24,0x394c234,0x3a5e347, + 0x26e4a15,0x39a3b4c,0x2514c2e,0x029e5be }, + 0 }, + /* 26 */ + { { 0x23addd7,0x3ed8120,0x13b3359,0x20f959a,0x09e2a61,0x32fcf20, + 0x05b78e3,0x19ba7e2,0x1a9c697,0x0392b4b }, + { 0x2048a61,0x3dfd0a3,0x19a0357,0x233024b,0x3082d19,0x00fb63b, + 0x3a1af4c,0x1450ff0,0x046c37b,0x0317a50 }, + 0 }, + /* 27 */ + { { 0x3e75f9e,0x294e30a,0x3a78476,0x3a32c48,0x36fd1a9,0x0427012, + 0x1e4df0b,0x11d1f61,0x1afdb46,0x018ca0f }, + { 0x2f2df15,0x0a33dee,0x27f4ce7,0x1542b66,0x3e592c4,0x20d2f30, + 0x3226ade,0x2a4e3ea,0x1ab1981,0x01a2f46 }, + 0 }, + /* 28 */ + { { 0x087d659,0x3ab5446,0x305ac08,0x3d2cd64,0x33374d5,0x3f9d3f8, + 0x186981c,0x37f5a5a,0x2f53c6f,0x01254a4 }, + { 0x2cec896,0x1e32786,0x04844a8,0x043b16d,0x3d964b2,0x1935829, + 0x16f7e26,0x1a0dd9a,0x30d2603,0x003b1d4 }, + 0 }, + /* 29 */ + { { 0x12687bb,0x04e816b,0x21fa2da,0x1abccb8,0x3a1f83b,0x375181e, + 0x0f5ef51,0x0fc2ce4,0x3a66486,0x003d881 }, + { 0x3138233,0x1f8eec3,0x2718bd6,0x1b09caa,0x2dd66b9,0x1bb222b, + 0x1004072,0x1b73e3b,0x07208ed,0x03fc36c }, + 0 }, + /* 30 */ + { { 0x095d553,0x3e84053,0x0a8a749,0x3f575a0,0x3a44052,0x3ced59b, + 0x3b4317f,0x03a8c60,0x13c8874,0x00c4ed4 }, + { 0x0d11549,0x0b8ab02,0x221cb40,0x02ed37b,0x2071ee1,0x1fc8c83, + 0x3987dd4,0x27e049a,0x0f986f1,0x00b4eaf }, + 0 }, + /* 31 */ + { { 0x15581a2,0x2214060,0x11af4c2,0x1598c88,0x19a0a6d,0x32acba6, + 0x3a7a0f0,0x2337c66,0x210ded9,0x0300dbe }, + { 0x1fbd009,0x3822eb0,0x181629a,0x2401b45,0x30b68b1,0x2e78363, + 0x2b32779,0x006530b,0x2c4b6d4,0x029aca8 }, + 0 }, + /* 32 */ + { { 0x13549cf,0x0f943db,0x265ed43,0x1bfeb35,0x06f3369,0x3847f2d, + 0x1bfdacc,0x26181a5,0x252af7c,0x02043b8 }, + { 0x159bb2c,0x143f85c,0x357b654,0x2f9d62c,0x2f7dfbe,0x1a7fa9c, + 0x057e74d,0x05d14ac,0x17a9273,0x035215c }, + 0 }, + /* 33 */ + { { 0x0cb5a98,0x106a2bc,0x10bf117,0x24c7cc4,0x3d3da8f,0x2ce0ab7, + 0x14e2cba,0x1813866,0x1a72f9a,0x01a9811 }, + { 0x2b2411d,0x3034fe8,0x16e0170,0x0f9443a,0x0be0eb8,0x2196cf3, + 0x0c9f738,0x15e40ef,0x0faf9e1,0x034f917 }, + 0 }, + /* 34 */ + { { 0x03f7669,0x3da6efa,0x3d6bce1,0x209ca1d,0x109f8ae,0x09109e3, + 0x08ae543,0x3067255,0x1dee3c2,0x0081dd5 }, + { 0x3ef1945,0x358765b,0x28c387b,0x3bec4b4,0x218813c,0x0b7d92a, + 0x3cd1d67,0x2c0367e,0x2e57154,0x0123717 }, + 0 }, + /* 35 */ + { { 0x3e5a199,0x1e42ffd,0x0bb7123,0x33e6273,0x1e0efb8,0x294671e, + 0x3a2bfe0,0x3d11709,0x2eddff6,0x03cbec2 }, + { 0x0b5025f,0x0255d7c,0x1f2241c,0x35d03ea,0x0550543,0x202fef4, + 0x23c8ad3,0x354963e,0x015db28,0x0284fa4 }, + 0 }, + /* 36 */ + { { 0x2b65cbc,0x1e8d428,0x0226f9f,0x1c8a919,0x10b04b9,0x08fc1e8, + 0x1ce241e,0x149bc99,0x2b01497,0x00afc35 }, + { 0x3216fb7,0x1374fd2,0x226ad3d,0x19fef76,0x0f7d7b8,0x1c21417, + 0x37b83f6,0x3a27eba,0x25a162f,0x010aa52 }, + 0 }, + /* 37 */ + { { 0x2adf191,0x1ab42fa,0x28d7584,0x2409689,0x20f8a48,0x253707d, + 0x2030504,0x378f7a1,0x169c65e,0x00b0b76 }, + { 0x3849c17,0x085c764,0x10dd6d0,0x2e87689,0x1460488,0x30e9521, + 0x10c7063,0x1b6f120,0x21f42c5,0x03d0dfe }, + 0 }, + /* 38 */ + { { 0x20f7dab,0x035c512,0x29ac6aa,0x24c5ddb,0x20f0497,0x17ce5e1, + 0x00a050f,0x1eaa14b,0x3335470,0x02abd16 }, + { 0x18d364a,0x0df0cf0,0x316585e,0x018f925,0x0d40b9b,0x17b1511, + 0x1716811,0x1caf3d0,0x10df4f2,0x0337d8c }, + 0 }, + /* 39 */ + { { 0x2a8b7ef,0x0f188e3,0x2287747,0x06216f0,0x008e935,0x2f6a38d, + 0x1567722,0x0bfc906,0x0bada9e,0x03c3402 }, + { 0x014d3b1,0x099c749,0x2a76291,0x216c067,0x3b37549,0x14ef2f6, + 0x21b96d4,0x1ee2d71,0x2f5ca88,0x016f570 }, + 0 }, + /* 40 */ + { { 0x09a3154,0x3d1a7bd,0x2e9aef0,0x255b8ac,0x03e85a5,0x2a492a7, + 0x2aec1ea,0x11c6516,0x3c8a09e,0x02a84b7 }, + { 0x1f69f1d,0x09c89d3,0x1e7326f,0x0b28bfd,0x0e0e4c8,0x1ea7751, + 0x18ce73b,0x2a406e7,0x273e48c,0x01b00db }, + 0 }, + /* 41 */ + { { 0x36e3138,0x2b84a83,0x345a5cf,0x00096b4,0x16966ef,0x159caf1, + 0x13c64b4,0x2f89226,0x25896af,0x00a4bfd }, + { 0x2213402,0x1435117,0x09fed52,0x09d0e4b,0x0f6580e,0x2871cba, + 0x3b397fd,0x1c9d825,0x090311b,0x0191383 }, + 0 }, + /* 42 */ + { { 0x07153f0,0x1087869,0x18c9e1e,0x1e64810,0x2b86c3b,0x0175d9c, + 0x3dce877,0x269de4e,0x393cab7,0x03c96b9 }, + { 0x1869d0c,0x06528db,0x02641f3,0x209261b,0x29d55c8,0x25ba517, + 0x3b5ea30,0x028f927,0x25313db,0x00e6e39 }, + 0 }, + /* 43 */ + { { 0x2fd2e59,0x150802d,0x098f377,0x19a4957,0x135e2c0,0x38a95ce, + 0x1ab21a0,0x36c1b67,0x32f0f19,0x00e448b }, + { 0x3cad53c,0x3387800,0x17e3cfb,0x03f9970,0x3225b2c,0x2a84e1d, + 0x3af1d29,0x3fe35ca,0x2f8ce80,0x0237a02 }, + 0 }, + /* 44 */ + { { 0x07bbb76,0x3aa3648,0x2758afb,0x1f085e0,0x1921c7e,0x3010dac, + 0x22b74b1,0x230137e,0x1062e36,0x021c652 }, + { 0x3993df5,0x24a2ee8,0x126ab5f,0x2d7cecf,0x0639d75,0x16d5414, + 0x1aa78a8,0x3f78404,0x26a5b74,0x03f0c57 }, + 0 }, + /* 45 */ + { { 0x0d6ecfa,0x3f506ba,0x3f86561,0x3d86bb1,0x15f8c44,0x2491d07, + 0x052a7b4,0x2422261,0x3adee38,0x039b529 }, + { 0x193c75d,0x14bb451,0x1162605,0x293749c,0x370a70d,0x2e8b1f6, + 0x2ede937,0x2b95f4a,0x39a9be2,0x00d77eb }, + 0 }, + /* 46 */ + { { 0x2736636,0x15bf36a,0x2b7e6b9,0x25eb8b2,0x209f51d,0x3cd2659, + 0x10bf410,0x034afec,0x3d71c83,0x0076971 }, + { 0x0ce6825,0x07920cf,0x3c3b5c4,0x23fe55c,0x015ad11,0x08c0dae, + 0x0552c7f,0x2e75a8a,0x0fddbf4,0x01c1df0 }, + 0 }, + /* 47 */ + { { 0x2b9661c,0x0ffe351,0x3d71bf6,0x1ac34b3,0x3a1dfd3,0x211fe3d, + 0x33e140a,0x3f9100d,0x32ee50e,0x014ea18 }, + { 0x16d8051,0x1bfda1a,0x068a097,0x2571d3d,0x1daec0c,0x39389af, + 0x194dc35,0x3f3058a,0x36d34e1,0x000a329 }, + 0 }, + /* 48 */ + { { 0x09877ee,0x351f73f,0x0002d11,0x0420074,0x2c8b362,0x130982d, + 0x02c1175,0x3c11b40,0x0d86962,0x001305f }, + { 0x0daddf5,0x2f4252c,0x15c06d9,0x1d49339,0x1bea235,0x0b680ed, + 0x3356e67,0x1d1d198,0x1e9fed9,0x03dee93 }, + 0 }, + /* 49 */ + { { 0x3e1263f,0x2fe8d3a,0x3ce6d0d,0x0d5c6b9,0x3557637,0x0a9bd48, + 0x0405538,0x0710749,0x2005213,0x038c7e5 }, + { 0x26b6ec6,0x2e485ba,0x3c44d1b,0x0b9cf0b,0x037a1d1,0x27428a5, + 0x0e7eac8,0x351ef04,0x259ce34,0x02a8e98 }, + 0 }, + /* 50 */ + { { 0x2f3dcd3,0x3e77d4d,0x3360fbc,0x1434afd,0x36ceded,0x3d413d6, + 0x1710fad,0x36bb924,0x1627e79,0x008e637 }, + { 0x109569e,0x1c168db,0x3769cf4,0x2ed4527,0x0ea0619,0x17d80d3, + 0x1c03773,0x18843fe,0x1b21c04,0x015c5fd }, + 0 }, + /* 51 */ + { { 0x1dd895e,0x08a7248,0x04519fe,0x001030a,0x18e5185,0x358dfb3, + 0x13d2391,0x0a37be8,0x0560e3c,0x019828b }, + { 0x27fcbd0,0x2a22bb5,0x30969cc,0x1e03aa7,0x1c84724,0x0ba4ad3, + 0x32f4817,0x0914cca,0x14c4f52,0x01893b9 }, + 0 }, + /* 52 */ + { { 0x097eccc,0x1273936,0x00aa095,0x364fe62,0x04d49d1,0x10e9f08, + 0x3c24230,0x3ef01c8,0x2fb92bd,0x013ce4a }, + { 0x1e44fd9,0x27e3e9f,0x2156696,0x3915ecc,0x0b66cfb,0x1a3af0f, + 0x2fa8033,0x0e6736c,0x177ccdb,0x0228f9e }, + 0 }, + /* 53 */ + { { 0x2c4b125,0x06207c1,0x0a8cdde,0x003db8f,0x1ae34e3,0x31e84fa, + 0x2999de5,0x11013bd,0x02370c2,0x00e2234 }, + { 0x0f91081,0x200d591,0x1504762,0x1857c05,0x23d9fcf,0x0cb34db, + 0x27edc86,0x08cd860,0x2471810,0x029798b }, + 0 }, + /* 54 */ + { { 0x3acd6c8,0x097b8cb,0x3c661a8,0x15152f2,0x1699c63,0x237e64c, + 0x23edf79,0x16b7033,0x0e6466a,0x00b11da }, + { 0x0a64bc9,0x1bfe324,0x1f5cb34,0x08391de,0x0630a60,0x3017a21, + 0x09d064b,0x14a8365,0x041f9e6,0x01ed799 }, + 0 }, + /* 55 */ + { { 0x128444a,0x2508b07,0x2a39216,0x362f84d,0x2e996c5,0x2c31ff3, + 0x07afe5f,0x1d1288e,0x3cb0c8d,0x02e2bdc }, + { 0x38b86fd,0x3a0ea8c,0x1cff5fd,0x1629629,0x3fee3f1,0x02b250c, + 0x2e8f6f2,0x0225727,0x15f7f3f,0x0280d8e }, + 0 }, + /* 56 */ + { { 0x10f7770,0x0f1aee8,0x0e248c7,0x20684a8,0x3a6f16d,0x06f0ae7, + 0x0df6825,0x2d4cc40,0x301875f,0x012f8da }, + { 0x3b56dbb,0x1821ba7,0x24f8922,0x22c1f9e,0x0306fef,0x1b54bc8, + 0x2ccc056,0x00303ba,0x2871bdc,0x0232f26 }, + 0 }, + /* 57 */ + { { 0x0dac4ab,0x0625730,0x3112e13,0x101c4bf,0x3a874a4,0x2873b95, + 0x32ae7c6,0x0d7e18c,0x13e0c08,0x01139d5 }, + { 0x334002d,0x00fffdd,0x025c6d5,0x22c2cd1,0x19d35cb,0x3a1ce2d, + 0x3702760,0x3f06257,0x03a5eb8,0x011c29a }, + 0 }, + /* 58 */ + { { 0x0513482,0x1d87724,0x276a81b,0x0a807a4,0x3028720,0x339cc20, + 0x2441ee0,0x31bbf36,0x290c63d,0x0059041 }, + { 0x106a2ed,0x0d2819b,0x100bf50,0x114626c,0x1dd4d77,0x2e08632, + 0x14ae72a,0x2ed3f64,0x1fd7abc,0x035cd1e }, + 0 }, + /* 59 */ + { { 0x2d4c6e5,0x3bec596,0x104d7ed,0x23d6c1b,0x0262cf0,0x15d72c5, + 0x2d5bb18,0x199ac4b,0x1e30771,0x020591a }, + { 0x21e291e,0x2e75e55,0x1661d7a,0x08b0778,0x3eb9daf,0x0d78144, + 0x1827eb1,0x0fe73d2,0x123f0dd,0x0028db7 }, + 0 }, + /* 60 */ + { { 0x1d5533c,0x34cb1d0,0x228f098,0x27a1a11,0x17c5f5a,0x0d26f44, + 0x2228ade,0x2c460e6,0x3d6fdba,0x038cc77 }, + { 0x3cc6ed8,0x02ada1a,0x260e510,0x2f7bde8,0x37160c3,0x33a1435, + 0x23d9a7b,0x0ce2641,0x02a492e,0x034ed1e }, + 0 }, + /* 61 */ + { { 0x3821f90,0x26dba3c,0x3aada14,0x3b59bad,0x292edd9,0x2804c45, + 0x3669531,0x296f42e,0x35a4c86,0x01ca049 }, + { 0x3ff47e5,0x2163df4,0x2441503,0x2f18405,0x15e1616,0x37f66ec, + 0x30f11a7,0x141658a,0x27ece14,0x00b018b }, + 0 }, + /* 62 */ + { { 0x159ac2e,0x3e65bc0,0x2713a76,0x0db2f6c,0x3281e77,0x2391811, + 0x16d2880,0x1fbc4ab,0x1f92c4e,0x00a0a8d }, + { 0x0ce5cd2,0x152c7b0,0x02299c3,0x3244de7,0x2cf99ef,0x3a0b047, + 0x2caf383,0x0aaf664,0x113554d,0x031c735 }, + 0 }, + /* 63 */ + { { 0x1b578f4,0x177a702,0x3a7a488,0x1638ebf,0x31884e2,0x2460bc7, + 0x36b1b75,0x3ce8e3d,0x340cf47,0x03143d9 }, + { 0x34b68ea,0x12b7ccd,0x1fe2a9c,0x08da659,0x0a406f3,0x1694c14, + 0x06a2228,0x16370be,0x3a72129,0x02e7b2c }, + 0 }, + /* 64 */ + { { 0x0f8b16a,0x21043bd,0x266a56f,0x3fb11ec,0x197241a,0x36721f0, + 0x006b8e6,0x2ac6c29,0x202cd42,0x0200fcf }, + { 0x0dbec69,0x0c26a01,0x105f7f0,0x3dceeeb,0x3a83b85,0x363865f, + 0x097273a,0x2b70718,0x00e5067,0x03025d1 }, + 0 }, + /* 65 */ + { { 0x379ab34,0x295bcb0,0x38d1846,0x22e1077,0x3a8ee06,0x1db1a3b, + 0x3144591,0x07cc080,0x2d5915f,0x03c6bcc }, + { 0x175bd50,0x0dd4c57,0x27bc99c,0x2ebdcbd,0x3837cff,0x235dc8f, + 0x13a4184,0x0722c18,0x130e2d4,0x008f43c }, + 0 }, + /* 66 */ + { { 0x01500d9,0x2adbb7d,0x2da8857,0x397f2fa,0x10d890a,0x25c9654, + 0x3e86488,0x3eb754b,0x1d6c0a3,0x02c0a23 }, + { 0x10bcb08,0x083cc19,0x2e16853,0x04da575,0x271af63,0x2626a9d, + 0x3520a7b,0x32348c7,0x24ff408,0x03ff4dc }, + 0 }, + /* 67 */ + { { 0x058e6cb,0x1a3992d,0x1d28539,0x080c5e9,0x2992dad,0x2a9d7d5, + 0x14ae0b7,0x09b7ce0,0x34ad78c,0x03d5643 }, + { 0x30ba55a,0x092f4f3,0x0bae0fc,0x12831de,0x20fc472,0x20ed9d2, + 0x29864f6,0x1288073,0x254f6f7,0x00635b6 }, + 0 }, + /* 68 */ + { { 0x1be5a2b,0x0f88975,0x33c6ed9,0x20d64d3,0x06fe799,0x0989bff, + 0x1409262,0x085a90c,0x0d97990,0x0142eed }, + { 0x17ec63e,0x06471b9,0x0db2378,0x1006077,0x265422c,0x08db83d, + 0x28099b0,0x1270d06,0x11801fe,0x00ac400 }, + 0 }, + /* 69 */ + { { 0x3391593,0x22d7166,0x30fcfc6,0x2896609,0x3c385f5,0x066b72e, + 0x04f3aad,0x2b831c5,0x19983fb,0x0375562 }, + { 0x0b82ff4,0x222e39d,0x34c993b,0x101c79c,0x2d2e03c,0x0f00c8a, + 0x3a9eaf4,0x1810669,0x151149d,0x039b931 }, + 0 }, + /* 70 */ + { { 0x29af288,0x1956ec7,0x293155f,0x193deb6,0x1647e1a,0x2ca0839, + 0x297e4bc,0x15bfd0d,0x1b107ed,0x0147803 }, + { 0x31c327e,0x05a6e1d,0x02ad43d,0x02d2a5b,0x129cdb2,0x37ad1de, + 0x3d51f53,0x245df01,0x2414982,0x0388bd0 }, + 0 }, + /* 71 */ + { { 0x35f1abb,0x17a3d18,0x0874cd4,0x2d5a14e,0x17edc0c,0x16a00d3, + 0x072c1fb,0x1232725,0x33d52dc,0x03dc24d }, + { 0x0af30d6,0x259aeea,0x369c401,0x12bc4de,0x295bf5f,0x0d8711f, + 0x26162a9,0x16c44e5,0x288e727,0x02f54b4 }, + 0 }, + /* 72 */ + { { 0x05fa877,0x1571ea7,0x3d48ab1,0x1c9f4e8,0x017dad6,0x0f46276, + 0x343f9e7,0x1de990f,0x0e4c8aa,0x028343e }, + { 0x094f92d,0x3abf633,0x1b3a0bb,0x2f83137,0x0d818c8,0x20bae85, + 0x0c65f8b,0x1a8008b,0x0c7946d,0x0295b1e }, + 0 }, + /* 73 */ + { { 0x1d09529,0x08e46c3,0x1fcf296,0x298f6b7,0x1803e0e,0x2d6fd20, + 0x37351f5,0x0d9e8b1,0x1f8731a,0x0362fbf }, + { 0x00157f4,0x06750bf,0x2650ab9,0x35ffb23,0x2f51cae,0x0b522c2, + 0x39cb400,0x191e337,0x0a5ce9f,0x021529a }, + 0 }, + /* 74 */ + { { 0x3506ea5,0x17d9ed8,0x0d66dc3,0x22693f8,0x19286c4,0x3a57353, + 0x101d3bf,0x1aa54fc,0x20b9884,0x0172b3a }, + { 0x0eac44d,0x37d8327,0x1c3aa90,0x3d0d534,0x23db29a,0x3576eaf, + 0x1d3de8a,0x3bea423,0x11235e4,0x039260b }, + 0 }, + /* 75 */ + { { 0x34cd55e,0x01288b0,0x1132231,0x2cc9a03,0x358695b,0x3e87650, + 0x345afa1,0x01267ec,0x3f616b2,0x02011ad }, + { 0x0e7d098,0x0d6078e,0x0b70b53,0x237d1bc,0x0d7f61e,0x132de31, + 0x1ea9ea4,0x2bd54c3,0x27b9082,0x03ac5f2 }, + 0 }, + /* 76 */ + { { 0x2a145b9,0x06d661d,0x31ec175,0x03f06f1,0x3a5cf6b,0x249c56e, + 0x2035653,0x384c74f,0x0bafab5,0x0025ec0 }, + { 0x25f69e1,0x1b23a55,0x1199aa6,0x16ad6f9,0x077e8f7,0x293f661, + 0x33ba11d,0x3327980,0x07bafdb,0x03e571d }, + 0 }, + /* 77 */ + { { 0x2bae45e,0x3c074ef,0x2955558,0x3c312f1,0x2a8ebe9,0x2f193f1, + 0x3705b1d,0x360deba,0x01e566e,0x00d4498 }, + { 0x21161cd,0x1bc787e,0x2f87933,0x3553197,0x1328ab8,0x093c879, + 0x17eee27,0x2adad1d,0x1236068,0x003be5c }, + 0 }, + /* 78 */ + { { 0x0ca4226,0x2633dd5,0x2c8e025,0x0e3e190,0x05eede1,0x1a385e4, + 0x163f744,0x2f25522,0x1333b4f,0x03f05b6 }, + { 0x3c800ca,0x1becc79,0x2daabe9,0x0c499e2,0x1138063,0x3fcfa2d, + 0x2244976,0x1e85cf5,0x2f1b95d,0x0053292 }, + 0 }, + /* 79 */ + { { 0x12f81d5,0x1dc6eaf,0x11967a4,0x1a407df,0x31a5f9d,0x2b67241, + 0x18bef7c,0x08c7762,0x063f59c,0x01015ec }, + { 0x1c05c0a,0x360bfa2,0x1f85bff,0x1bc7703,0x3e4911c,0x0d685b6, + 0x2fccaea,0x02c4cef,0x164f133,0x0070ed7 }, + 0 }, + /* 80 */ + { { 0x0ec21fe,0x052ffa0,0x3e825fe,0x1ab0956,0x3f6ce11,0x3d29759, + 0x3c5a072,0x18ebe62,0x148db7e,0x03eb49c }, + { 0x1ab05b3,0x02dab0a,0x1ae690c,0x0f13894,0x137a9a8,0x0aab79f, + 0x3dc875c,0x06a1029,0x1e39f0e,0x01dce1f }, + 0 }, + /* 81 */ + { { 0x16c0dd7,0x3b31269,0x2c741e9,0x3611821,0x2a5cffc,0x1416bb3, + 0x3a1408f,0x311fa3d,0x1c0bef0,0x02cdee1 }, + { 0x00e6a8f,0x1adb933,0x0f23359,0x2fdace2,0x2fd6d4b,0x0e73bd3, + 0x2453fac,0x0a356ae,0x2c8f9f6,0x02704d6 }, + 0 }, + /* 82 */ + { { 0x0e35743,0x28c80a1,0x0def32a,0x2c6168f,0x1320d6a,0x37c6606, + 0x21b1761,0x2147ee0,0x21fc433,0x015c84d }, + { 0x1fc9168,0x36cda9c,0x003c1f0,0x1cd7971,0x15f98ba,0x1ef363d, + 0x0ca87e3,0x046f7d9,0x3c9e6bb,0x0372eb0 }, + 0 }, + /* 83 */ + { { 0x118cbe2,0x3665a11,0x304ef01,0x062727a,0x3d242fc,0x11ffbaf, + 0x3663c7e,0x1a189c9,0x09e2d62,0x02e3072 }, + { 0x0e1d569,0x162f772,0x0cd051a,0x322df62,0x3563809,0x047cc7a, + 0x027fd9f,0x08b509b,0x3da2f94,0x01748ee }, + 0 }, + /* 84 */ + { { 0x1c8f8be,0x31ca525,0x22bf0a1,0x200efcd,0x02961c4,0x3d8f52b, + 0x018403d,0x3a40279,0x1cb91ec,0x030427e }, + { 0x0945705,0x0257416,0x05c0c2d,0x25b77ae,0x3b9083d,0x2901126, + 0x292b8d7,0x07b8611,0x04f2eee,0x026f0cd }, + 0 }, + /* 85 */ + { { 0x2913074,0x2b8d590,0x02b10d5,0x09d2295,0x255491b,0x0c41cca, + 0x1ca665b,0x133051a,0x1525f1a,0x00a5647 }, + { 0x04f983f,0x3d6daee,0x04e1e76,0x1067d7e,0x1be7eef,0x02ea862, + 0x00d4968,0x0ccb048,0x11f18ef,0x018dd95 }, + 0 }, + /* 86 */ + { { 0x22976cc,0x17c5395,0x2c38bda,0x3983bc4,0x222bca3,0x332a614, + 0x3a30646,0x261eaef,0x1c808e2,0x02f6de7 }, + { 0x306a772,0x32d7272,0x2dcefd2,0x2abf94d,0x038f475,0x30ad76e, + 0x23e0227,0x3052b0a,0x001add3,0x023ba18 }, + 0 }, + /* 87 */ + { { 0x0ade873,0x25a6069,0x248ccbe,0x13713ee,0x17ee9aa,0x28152e9, + 0x2e28995,0x2a92cb3,0x17a6f77,0x024b947 }, + { 0x190a34d,0x2ebea1c,0x1ed1948,0x16fdaf4,0x0d698f7,0x32bc451, + 0x0ee6e30,0x2aaab40,0x06f0a56,0x01460be }, + 0 }, + /* 88 */ + { { 0x24cc99c,0x1884b1e,0x1ca1fba,0x1a0f9b6,0x2ff609b,0x2b26316, + 0x3b27cb5,0x29bc976,0x35d4073,0x024772a }, + { 0x3575a70,0x1b30f57,0x07fa01b,0x0e5be36,0x20cb361,0x26605cd, + 0x1d4e8c8,0x13cac59,0x2db9797,0x005e833 }, + 0 }, + /* 89 */ + { { 0x36c8d3a,0x1878a81,0x124b388,0x0e4843e,0x1701aad,0x0ea0d76, + 0x10eae41,0x37d0653,0x36c7f4c,0x00ba338 }, + { 0x37a862b,0x1cf6ac0,0x08fa912,0x2dd8393,0x101ba9b,0x0eebcb7, + 0x2453883,0x1a3cfe5,0x2cb34f6,0x03d3331 }, + 0 }, + /* 90 */ + { { 0x1f79687,0x3d4973c,0x281544e,0x2564bbe,0x17c5954,0x171e34a, + 0x231741a,0x3cf2784,0x0889a0d,0x02b036d }, + { 0x301747f,0x3f1c477,0x1f1386b,0x163bc5f,0x1592b93,0x332daed, + 0x080e4f5,0x1d28b96,0x26194c9,0x0256992 }, + 0 }, + /* 91 */ + { { 0x15a4c93,0x07bf6b0,0x114172c,0x1ce0961,0x140269b,0x1b2c2eb, + 0x0dfb1c1,0x019ddaa,0x0ba2921,0x008c795 }, + { 0x2e6d2dc,0x37e45e2,0x2918a70,0x0fce444,0x34d6aa6,0x396dc88, + 0x27726b5,0x0c787d8,0x032d8a7,0x02ac2f8 }, + 0 }, + /* 92 */ + { { 0x1131f2d,0x2b43a63,0x3101097,0x38cec13,0x0637f09,0x17a69d2, + 0x086196d,0x299e46b,0x0802cf6,0x03c6f32 }, + { 0x0daacb4,0x1a4503a,0x100925c,0x15583d9,0x23c4e40,0x1de4de9, + 0x1cc8fc4,0x2c9c564,0x0695aeb,0x02145a5 }, + 0 }, + /* 93 */ + { { 0x1dcf593,0x17050fc,0x3e3bde3,0x0a6c062,0x178202b,0x2f7674f, + 0x0dadc29,0x15763a7,0x1d2daad,0x023d9f6 }, + { 0x081ea5f,0x045959d,0x190c841,0x3a78d31,0x0e7d2dd,0x1414fea, + 0x1d43f40,0x22d77ff,0x2b9c072,0x03e115c }, + 0 }, + /* 94 */ + { { 0x3af71c9,0x29e9c65,0x25655e1,0x111e9cd,0x3a14494,0x3875418, + 0x34ae070,0x0b06686,0x310616b,0x03b7b89 }, + { 0x1734121,0x00d3d44,0x29f0b2f,0x1552897,0x31cac6e,0x1030bb3, + 0x0148f3a,0x35fd237,0x29b44eb,0x027f49f }, + 0 }, + /* 95 */ + { { 0x2e2cb16,0x1d962bd,0x19b63cc,0x0b3f964,0x3e3eb7d,0x1a35560, + 0x0c58161,0x3ce1d6a,0x3b6958f,0x029030b }, + { 0x2dcc158,0x3b1583f,0x30568c9,0x31957c8,0x27ad804,0x28c1f84, + 0x3967049,0x37b3f64,0x3b87dc6,0x0266f26 }, + 0 }, + /* 96 */ + { { 0x27dafc6,0x2548764,0x0d1984a,0x1a57027,0x252c1fb,0x24d9b77, + 0x1581a0f,0x1f99276,0x10ba16d,0x026af88 }, + { 0x0915220,0x2be1292,0x16c6480,0x1a93760,0x2fa7317,0x1a07296, + 0x1539871,0x112c31f,0x25787f3,0x01e2070 }, + 0 }, + /* 97 */ + { { 0x0bcf3ff,0x266d478,0x34f6933,0x31449fd,0x00d02cb,0x340765a, + 0x3465a2d,0x225023e,0x319a30e,0x00579b8 }, + { 0x20e05f4,0x35b834f,0x0404646,0x3710d62,0x3fad7bd,0x13e1434, + 0x21c7d1c,0x1cb3af9,0x2cf1911,0x003957e }, + 0 }, + /* 98 */ + { { 0x0787564,0x36601be,0x1ce67e9,0x084c7a1,0x21a3317,0x2067a35, + 0x0158cab,0x195ddac,0x1766fe9,0x035cf42 }, + { 0x2b7206e,0x20d0947,0x3b42424,0x03f1862,0x0a51929,0x38c2948, + 0x0bb8595,0x2942d77,0x3748f15,0x0249428 }, + 0 }, + /* 99 */ + { { 0x2577410,0x3c23e2f,0x28c6caf,0x00d41de,0x0fd408a,0x30298e9, + 0x363289e,0x2302fc7,0x082c1cc,0x01dd050 }, + { 0x30991cd,0x103e9ba,0x029605a,0x19927f7,0x0c1ca08,0x0c93f50, + 0x28a3c7b,0x082e4e9,0x34d12eb,0x0232c13 }, + 0 }, + /* 100 */ + { { 0x106171c,0x0b4155a,0x0c3fb1c,0x336c090,0x19073e9,0x2241a10, + 0x0e6b4fd,0x0ed476e,0x1ef4712,0x039390a }, + { 0x0ec36f4,0x3754f0e,0x2a270b8,0x007fd2d,0x0f9d2dc,0x1e6a692, + 0x066e078,0x1954974,0x2ff3c6e,0x00def28 }, + 0 }, + /* 101 */ + { { 0x3562470,0x0b8f1f7,0x0ac94cd,0x28b0259,0x244f272,0x031e4ef, + 0x2d5df98,0x2c8a9f1,0x2dc3002,0x016644f }, + { 0x350592a,0x0e6a0d5,0x1e027a1,0x2039e0f,0x399e01d,0x2817593, + 0x0c0375e,0x3889b3e,0x24ab013,0x010de1b }, + 0 }, + /* 102 */ + { { 0x256b5a6,0x0ac3b67,0x28f9ff3,0x29b67f1,0x30750d9,0x25e11a9, + 0x15e8455,0x279ebb0,0x298b7e7,0x0218e32 }, + { 0x2fc24b2,0x2b82582,0x28f22f5,0x2bd36b3,0x305398e,0x3b2e9e3, + 0x365dd0a,0x29bc0ed,0x36a7b3a,0x007b374 }, + 0 }, + /* 103 */ + { { 0x05ff2f3,0x2b3589b,0x29785d3,0x300a1ce,0x0a2d516,0x0844355, + 0x14c9fad,0x3ccb6b6,0x385d459,0x0361743 }, + { 0x0b11da3,0x002e344,0x18c49f7,0x0c29e0c,0x1d2c22c,0x08237b3, + 0x2988f49,0x0f18955,0x1c3b4ed,0x02813c6 }, + 0 }, + /* 104 */ + { { 0x17f93bd,0x249323b,0x11f6087,0x174e4bd,0x3cb64ac,0x086dc6b, + 0x2e330a8,0x142c1f2,0x2ea5c09,0x024acbb }, + { 0x1b6e235,0x3132521,0x00f085a,0x2a4a4db,0x1ab2ca4,0x0142224, + 0x3aa6b3e,0x09db203,0x2215834,0x007b9e0 }, + 0 }, + /* 105 */ + { { 0x23e79f7,0x28b8039,0x1906a60,0x2cbce67,0x1f590e7,0x181f027, + 0x21054a6,0x3854240,0x2d857a6,0x03cfcb3 }, + { 0x10d9b55,0x1443cfc,0x2648200,0x2b36190,0x09d2fcf,0x22f439f, + 0x231aa7e,0x3884395,0x0543da3,0x003d5a9 }, + 0 }, + /* 106 */ + { { 0x043e0df,0x06ffe84,0x3e6d5b2,0x3327001,0x26c74b6,0x12a145e, + 0x256ec0d,0x3898c69,0x3411969,0x02f63c5 }, + { 0x2b7494a,0x2eee1af,0x38388a9,0x1bd17ce,0x21567d4,0x13969e6, + 0x3a12a7a,0x3e8277d,0x03530cc,0x00b4687 }, + 0 }, + /* 107 */ + { { 0x06508da,0x38e04d4,0x15a7192,0x312875e,0x3336180,0x2a6512c, + 0x1b59497,0x2e91b37,0x25eb91f,0x02841e9 }, + { 0x394d639,0x0747143,0x37d7e6d,0x1d62962,0x08b4af3,0x34df287, + 0x3c5584b,0x26bc869,0x20af87a,0x0060f5d }, + 0 }, + /* 108 */ + { { 0x1de59a4,0x1a5c443,0x2f8729d,0x01c3a2f,0x0f1ad8d,0x3cbaf9e, + 0x1b49634,0x35d508a,0x39dc269,0x0075105 }, + { 0x390d30e,0x37033e0,0x110cb32,0x14c37a0,0x20a3b27,0x2f00ce6, + 0x2f1dc52,0x34988c6,0x0c29606,0x01dc7e7 }, + 0 }, + /* 109 */ + { { 0x1040739,0x24f9de1,0x2939999,0x2e6009a,0x244539d,0x17e3f09, + 0x00f6f2f,0x1c63b3d,0x2310362,0x019109e }, + { 0x1428aa8,0x3cb61e1,0x09a84f4,0x0ffafed,0x07b7adc,0x08f406b, + 0x1b2c6df,0x035b480,0x3496ae9,0x012766d }, + 0 }, + /* 110 */ + { { 0x35d1099,0x2362f10,0x1a08cc7,0x13a3a34,0x12adbcd,0x32da290, + 0x02e2a02,0x151140b,0x01b3f60,0x0240df6 }, + { 0x34c7b61,0x2eb09c1,0x172e7cd,0x2ad5eff,0x2fe2031,0x25b54d4, + 0x0cec965,0x18e7187,0x26a7cc0,0x00230f7 }, + 0 }, + /* 111 */ + { { 0x2d552ab,0x374083d,0x01f120f,0x2601736,0x156baff,0x04d44a4, + 0x3b7c3e9,0x1acbc1b,0x0424579,0x031a425 }, + { 0x1231bd1,0x0eba710,0x020517b,0x21d7316,0x21eac6e,0x275a848, + 0x0837abf,0x0eb0082,0x302cafe,0x00fe8f6 }, + 0 }, + /* 112 */ + { { 0x1058880,0x28f9941,0x03f2d75,0x3bd90e5,0x17da365,0x2ac9249, + 0x07861cf,0x023fd05,0x1b0fdb8,0x031712f }, + { 0x272b56b,0x04f8d2c,0x043a735,0x25446e4,0x1c8327e,0x221125a, + 0x0ce37df,0x2dad7f6,0x39446c2,0x00b55b6 }, + 0 }, + /* 113 */ + { { 0x346ac6b,0x05e0bff,0x2425246,0x0981e8b,0x1d19f79,0x2692378, + 0x3ea3c40,0x2e90beb,0x19de503,0x003d5af }, + { 0x05cda49,0x353b44d,0x299d137,0x3f205bc,0x2821158,0x3ad0d00, + 0x06a54aa,0x2d7c79f,0x39d1173,0x01000ee }, + 0 }, + /* 114 */ + { { 0x0803387,0x3a06268,0x14043b8,0x3d4e72f,0x1ece115,0x0a1dfc8, + 0x17208dd,0x0be790a,0x122a07f,0x014dd95 }, + { 0x0a4182d,0x202886a,0x1f79a49,0x1e8c867,0x0a2bbd0,0x28668b5, + 0x0d0a2e1,0x115259d,0x3586c5d,0x01e815b }, + 0 }, + /* 115 */ + { { 0x18a2a47,0x2c95627,0x2773646,0x1230f7c,0x15b5829,0x2fc354e, + 0x2c000ea,0x099d547,0x2f17a1a,0x01df520 }, + { 0x3853948,0x06f6561,0x3feeb8a,0x2f5b3ef,0x3a6f817,0x01a0791, + 0x2ec0578,0x2c392ad,0x12b2b38,0x0104540 }, + 0 }, + /* 116 */ + { { 0x1e28ced,0x0fc3d1b,0x2c473c7,0x1826c4f,0x21d5da7,0x39718e4, + 0x38ce9e6,0x0251986,0x172fbea,0x0337c11 }, + { 0x053c3b0,0x0f162db,0x043c1cb,0x04111ee,0x297fe3c,0x32e5e03, + 0x2b8ae12,0x0c427ec,0x1da9738,0x03b9c0f }, + 0 }, + /* 117 */ + { { 0x357e43a,0x054503f,0x11b8345,0x34ec6e0,0x2d44660,0x3d0ae61, + 0x3b5dff8,0x33884ac,0x09da162,0x00a82b6 }, + { 0x3c277ba,0x129a51a,0x027664e,0x1530507,0x0c788c9,0x2afd89d, + 0x1aa64cc,0x1196450,0x367ac2b,0x0358b42 }, + 0 }, + /* 118 */ + { { 0x0054ac4,0x1761ecb,0x378839c,0x167c9f7,0x2570058,0x0604a35, + 0x37cbf3b,0x0909bb7,0x3f2991c,0x02ce688 }, + { 0x0b16ae5,0x212857c,0x351b952,0x2c684db,0x30c6a05,0x09c01e0, + 0x23c137f,0x1331475,0x092c067,0x0013b40 }, + 0 }, + /* 119 */ + { { 0x2e90393,0x0617466,0x24e61f4,0x0a528f5,0x03047b4,0x2153f05, + 0x0001a69,0x30e1eb8,0x3c10177,0x0282a47 }, + { 0x22c831e,0x28fc06b,0x3e16ff0,0x208adc9,0x0bb76ae,0x28c1d6d, + 0x12c8a15,0x031063c,0x1889ed2,0x002133e }, + 0 }, + /* 120 */ + { { 0x0a6becf,0x14277bf,0x3328d98,0x201f7fe,0x12fceae,0x1de3a2e, + 0x0a15c44,0x3ddf976,0x1b273ab,0x0355e55 }, + { 0x1b5d4f1,0x369e78c,0x3a1c210,0x12cf3e9,0x3aa52f0,0x309f082, + 0x112089d,0x107c753,0x24202d1,0x023853a }, + 0 }, + /* 121 */ + { { 0x2897042,0x140d17c,0x2c4aeed,0x07d0d00,0x18d0533,0x22f7ec8, + 0x19c194c,0x3456323,0x2372aa4,0x0165f86 }, + { 0x30bd68c,0x1fb06b3,0x0945032,0x372ac09,0x06d4be0,0x27f8fa1, + 0x1c8d7ac,0x137a96e,0x236199b,0x0328fc0 }, + 0 }, + /* 122 */ + { { 0x170bd20,0x2842d58,0x1de7592,0x3c5b4fd,0x20ea897,0x12cab78, + 0x363ff14,0x01f928c,0x17e309c,0x02f79ff }, + { 0x0f5432c,0x2edb4ae,0x044b516,0x32f810d,0x2210dc1,0x23e56d6, + 0x301e6ff,0x34660f6,0x10e0a7d,0x02d88eb }, + 0 }, + /* 123 */ + { { 0x0c7b65b,0x2f59d58,0x2289a75,0x2408e92,0x1ab8c55,0x1ec99e5, + 0x220fd0d,0x04defe0,0x24658ec,0x035aa8b }, + { 0x138bb85,0x2f002d4,0x295c10a,0x08760ce,0x28c31d1,0x1c0a8cb, + 0x0ff00b1,0x144eac9,0x2e02dcc,0x0044598 }, + 0 }, + /* 124 */ + { { 0x3b42b87,0x050057b,0x0dff781,0x1c06db1,0x1bd9f5d,0x1f5f04a, + 0x2cccd7a,0x143e19b,0x1cb94b7,0x036cfb8 }, + { 0x34837cf,0x3cf6c3c,0x0d4fb26,0x22ee55e,0x1e7eed1,0x315995f, + 0x2cdf937,0x1a96574,0x0425220,0x0221a99 }, + 0 }, + /* 125 */ + { { 0x1b569ea,0x0d33ed9,0x19c13c2,0x107dc84,0x2200111,0x0569867, + 0x2dc85da,0x05ef22e,0x0eb018a,0x029c33d }, + { 0x04a6a65,0x3e5eba3,0x378f224,0x09c04d0,0x036e5cf,0x3df8258, + 0x3a609e4,0x1eddef8,0x2abd174,0x02a91dc }, + 0 }, + /* 126 */ + { { 0x2a60cc0,0x1d84c5e,0x115f676,0x1840da0,0x2c79163,0x2f06ed6, + 0x198bb4b,0x3e5d37b,0x1dc30fa,0x018469b }, + { 0x15ee47a,0x1e32f30,0x16a530e,0x2093836,0x02e8962,0x3767b62, + 0x335adf3,0x27220db,0x2f81642,0x0173ffe }, + 0 }, + /* 127 */ + { { 0x37a99cd,0x1533fe6,0x05a1c0d,0x27610f1,0x17bf3b9,0x0b1ce78, + 0x0a908f6,0x265300e,0x3237dc1,0x01b969a }, + { 0x3a5db77,0x2d15382,0x0d63ef8,0x1feb3d8,0x0b7b880,0x19820de, + 0x11c0c67,0x2af3396,0x38d242d,0x0120688 }, + 0 }, + /* 128 */ + { { 0x1d0b34a,0x05ef00d,0x00a7e34,0x1ae0c9f,0x1440b38,0x300d8b4, + 0x37262da,0x3e50e3e,0x14ce0cd,0x00b1044 }, + { 0x195a0b1,0x173bc6b,0x03622ba,0x2a19f55,0x1c09b37,0x07921b2, + 0x16cdd20,0x24a5c9b,0x2bf42ff,0x00811de }, + 0 }, + /* 129 */ + { { 0x0d65dbf,0x145cf06,0x1ad82f7,0x038ce7b,0x077bf94,0x33c4007, + 0x22d26bd,0x25ad9c0,0x09ac773,0x02b1990 }, + { 0x2261cc3,0x2ecdbf1,0x3e908b0,0x3246439,0x0213f7b,0x1179b04, + 0x01cebaa,0x0be1595,0x175cc12,0x033a39a }, + 0 }, + /* 130 */ + { { 0x00a67d2,0x086d06f,0x248a0f1,0x0291134,0x362d476,0x166d1cd, + 0x044f1d6,0x2d2a038,0x365250b,0x0023f78 }, + { 0x08bf287,0x3b0f6a1,0x1d6eace,0x20b4cda,0x2c2a621,0x0912520, + 0x02dfdc9,0x1b35cd6,0x3d2565d,0x00bdf8b }, + 0 }, + /* 131 */ + { { 0x3770fa7,0x2e4b6f0,0x03f9ae4,0x170de41,0x1095e8d,0x1dd845c, + 0x334e9d1,0x00ab953,0x12e9077,0x03196fa }, + { 0x2fd0a40,0x228c0fd,0x384b275,0x38ef339,0x3e7d822,0x3e5d9ef, + 0x24f5854,0x0ece9eb,0x247d119,0x012ffe3 }, + 0 }, + /* 132 */ + { { 0x0ff1480,0x07487c0,0x1b16cd4,0x1f41d53,0x22ab8fb,0x2f83cfa, + 0x01d2efb,0x259f6b2,0x2e65772,0x00f9392 }, + { 0x05303e6,0x23cdb4f,0x23977e1,0x12e4898,0x03bd999,0x0c930f0, + 0x170e261,0x180a27b,0x2fd58ec,0x014e22b }, + 0 }, + /* 133 */ + { { 0x25d7713,0x0c5fad7,0x09daad1,0x3b9d779,0x109b985,0x1d3ec98, + 0x35bc4fc,0x2f838cb,0x0d14f75,0x0173e42 }, + { 0x2657b12,0x10d4423,0x19e6760,0x296e5bb,0x2bfd421,0x25c3330, + 0x29f51f8,0x0338838,0x24060f0,0x029a62e }, + 0 }, + /* 134 */ + { { 0x3748fec,0x2c5a1bb,0x2cf973d,0x289fa74,0x3e6e755,0x38997bf, + 0x0b6544c,0x2b6358c,0x38a7aeb,0x02c50bb }, + { 0x3d5770a,0x06be7c5,0x012fad3,0x19cb2cd,0x266af3b,0x3ccd677, + 0x160d1bd,0x141d5af,0x2965851,0x034625a }, + 0 }, + /* 135 */ + { { 0x3c41c08,0x255eacc,0x22e1ec5,0x2b151a3,0x087de94,0x311cbdb, + 0x016b73a,0x368e462,0x20b7981,0x0099ec3 }, + { 0x262b988,0x1539763,0x21e76e5,0x15445b4,0x1d8ddc7,0x34a9be6, + 0x10faf03,0x24e4d18,0x07aa111,0x02d538a }, + 0 }, + /* 136 */ + { { 0x38a876b,0x048ad45,0x04b40a0,0x3fc2144,0x251ff96,0x13ca7dd, + 0x0b31ab1,0x3539814,0x28b5f87,0x0212aec }, + { 0x270790a,0x350e7e0,0x346bd5e,0x276178f,0x22d6cb5,0x3078884, + 0x355c1b6,0x15901d7,0x3671765,0x03950db }, + 0 }, + /* 137 */ + { { 0x286e8d5,0x2409788,0x13be53f,0x2d21911,0x0353c95,0x10238e8, + 0x32f5bde,0x3a67b60,0x28b5b9c,0x001013d }, + { 0x381e8e5,0x0cef7a9,0x2f5bcad,0x06058f0,0x33cdf50,0x04672a8, + 0x1769600,0x31c055d,0x3df0ac1,0x00e9098 }, + 0 }, + /* 138 */ + { { 0x2eb596d,0x197b326,0x12b4c29,0x39c08f2,0x101ea03,0x3804e58, + 0x04b4b62,0x28d9d1c,0x13f905e,0x0032a3f }, + { 0x11b2b61,0x08e9095,0x0d06925,0x270e43f,0x21eb7a8,0x0e4a98f, + 0x31d2be0,0x030cf9f,0x2644ddb,0x025b728 }, + 0 }, + /* 139 */ + { { 0x07510af,0x2ed0e8e,0x2a01203,0x2a2a68d,0x0846fea,0x3e540de, + 0x3a57702,0x1677348,0x2123aad,0x010d8f8 }, + { 0x0246a47,0x0e871d0,0x124dca4,0x34b9577,0x2b362b8,0x363ebe5, + 0x3086045,0x26313e6,0x15cd8bb,0x0210384 }, + 0 }, + /* 140 */ + { { 0x023e8a7,0x0817884,0x3a0bf12,0x3376371,0x3c808a8,0x18e9777, + 0x12a2721,0x35b538a,0x2bd30de,0x017835a }, + { 0x0fc0f64,0x1c8709f,0x2d8807a,0x0743957,0x242eec0,0x347e76c, + 0x27bef91,0x289689a,0x0f42945,0x01f7a92 }, + 0 }, + /* 141 */ + { { 0x1060a81,0x3dbc739,0x1615abd,0x1cbe3e5,0x3e79f9c,0x1ab09a2, + 0x136c540,0x05b473f,0x2beebfd,0x02af0a8 }, + { 0x3e2eac7,0x19be474,0x04668ac,0x18f4b74,0x36f10ba,0x0a0b4c6, + 0x10e3770,0x3bf059e,0x3946c7e,0x013a8d4 }, + 0 }, + /* 142 */ + { { 0x266309d,0x28be354,0x1a3eed8,0x3020651,0x10a51c6,0x1e31770, + 0x0af45a5,0x3ff0f3b,0x2891c94,0x00e9db9 }, + { 0x17b0d0f,0x33a291f,0x0a5f9aa,0x25a3d61,0x2963ace,0x39a5fef, + 0x230c724,0x1919146,0x10a465e,0x02084a8 }, + 0 }, + /* 143 */ + { { 0x3ab8caa,0x31870f3,0x2390ef7,0x2103850,0x218eb8e,0x3a5ccf2, + 0x1dff677,0x2c59334,0x371599c,0x02a9f2a }, + { 0x0837bd1,0x3249cef,0x35d702f,0x3430dab,0x1c06407,0x108f692, + 0x221292f,0x05f0c5d,0x073fe06,0x01038e0 }, + 0 }, + /* 144 */ + { { 0x3bf9b7c,0x2020929,0x30d0f4f,0x080fef8,0x3365d23,0x1f3e738, + 0x3e53209,0x1549afe,0x300b305,0x038d811 }, + { 0x0c6c2c7,0x2e6445b,0x3ee64dc,0x022e932,0x0726837,0x0deb67b, + 0x1ed4346,0x3857f73,0x277a3de,0x01950b5 }, + 0 }, + /* 145 */ + { { 0x36c377a,0x0adb41e,0x08be3f3,0x11e40d1,0x36cb038,0x036a2bd, + 0x3dd3a82,0x1bc875b,0x2ee09bb,0x02994d2 }, + { 0x035facf,0x05e0344,0x07e630a,0x0ce772d,0x335e55a,0x111fce4, + 0x250fe1c,0x3bc89ba,0x32fdc9a,0x03cf2d9 }, + 0 }, + /* 146 */ + { { 0x355fd83,0x1c67f8e,0x1d10eb3,0x1b21d77,0x0e0d7a4,0x173a9e1, + 0x2c9fa90,0x1c39cce,0x22eaae8,0x01f2bea }, + { 0x153b338,0x0534107,0x26c69b8,0x283be1f,0x3e0acc0,0x059cac3, + 0x13d1081,0x148bbee,0x3c1b9bd,0x002aac4 }, + 0 }, + /* 147 */ + { { 0x2681297,0x3389e34,0x146addc,0x2c6d425,0x2cb350e,0x1986abc, + 0x0431737,0x04ba4b7,0x2028470,0x012e469 }, + { 0x2f8ddcf,0x3c4255c,0x1af4dcf,0x07a6a44,0x208ebf6,0x0dc90c3, + 0x34360ac,0x072ad23,0x0537232,0x01254d3 }, + 0 }, + /* 148 */ + { { 0x07b7e9d,0x3df5c7c,0x116f83d,0x28c4f35,0x3a478ef,0x3011fb8, + 0x2f264b6,0x317b9e3,0x04fd65a,0x032bd1b }, + { 0x2aa8266,0x3431de4,0x04bba04,0x19a44da,0x0edf454,0x392c5ac, + 0x265168a,0x1dc3d5b,0x25704c6,0x00533a7 }, + 0 }, + /* 149 */ + { { 0x25e8f91,0x1178fa5,0x2492994,0x2eb2c3c,0x0d3aca1,0x0322828, + 0x1cc70f9,0x269c74c,0x0a53e4c,0x006edc2 }, + { 0x18bdd7a,0x2a79a55,0x26b1d5c,0x0200628,0x0734a05,0x3273c7b, + 0x13aa714,0x0040ac2,0x2f2da30,0x03e7449 }, + 0 }, + /* 150 */ + { { 0x3f9563e,0x2f29eab,0x14a0749,0x3fad264,0x1dd077a,0x3d7c59c, + 0x3a0311b,0x331a789,0x0b9729e,0x0201ebf }, + { 0x1b08b77,0x2a4cdf2,0x3e387f8,0x21510f1,0x286c3a7,0x1dbf62e, + 0x3afa594,0x3363217,0x0d16568,0x01d46b7 }, + 0 }, + /* 151 */ + { { 0x0715c0d,0x28e2d04,0x17f78ae,0x1c63dda,0x1d113ea,0x0fefc1b, + 0x1eab149,0x1d0fd99,0x0682537,0x00a7b11 }, + { 0x10bebbc,0x11c672d,0x14223d9,0x2ff9141,0x1399ee5,0x34b7b6c, + 0x0d5b3a8,0x01df643,0x0e392a4,0x03fe4dc }, + 0 }, + /* 152 */ + { { 0x2b75b65,0x0b5a6f1,0x11c559a,0x3549999,0x24188f8,0x37a75f4, + 0x29f33e3,0x34068a2,0x38ba2a9,0x025dd91 }, + { 0x29af2c7,0x0988b64,0x0923885,0x1b539a4,0x1334f5d,0x226947a, + 0x2cc7e5a,0x20beb39,0x13fac2f,0x01d298c }, + 0 }, + /* 153 */ + { { 0x35f079c,0x137f76d,0x2fbbb2f,0x254638d,0x185b07c,0x1f34db7, + 0x2cfcf0e,0x218f46d,0x2150ff4,0x02add6f }, + { 0x33fc9b7,0x0d9f005,0x0fd081b,0x0834965,0x2b90a74,0x102448d, + 0x3dbf03c,0x167d857,0x02e0b44,0x013afab }, + 0 }, + /* 154 */ + { { 0x09f2c53,0x317f9d7,0x1411eb6,0x0463aba,0x0d25220,0x256b176, + 0x087633f,0x2bff322,0x07b2c1b,0x037e662 }, + { 0x10aaecb,0x23bb4a1,0x2272bb7,0x06c075a,0x09d4918,0x0736f2b, + 0x0dd511b,0x101625e,0x0a7779f,0x009ec10 }, + 0 }, + /* 155 */ + { { 0x33b2eb2,0x0176dfd,0x2118904,0x022386c,0x2e0df85,0x2588c9f, + 0x1b71525,0x28fd540,0x137e4cf,0x02ce4f7 }, + { 0x3d75165,0x0c39ecf,0x3554a12,0x30af34c,0x2d66344,0x3ded408, + 0x36f1be0,0x0d065b0,0x012d046,0x0025623 }, + 0 }, + /* 156 */ + { { 0x2601c3b,0x1824fc0,0x335fe08,0x3e33d70,0x0fb0252,0x252bfca, + 0x1cf2808,0x1922e55,0x1a9db9f,0x020721e }, + { 0x2f56c51,0x39a1f31,0x218c040,0x1a4fc5d,0x3fed471,0x0164d4e, + 0x388a419,0x06f1113,0x0f55fc1,0x03e8352 }, + 0 }, + /* 157 */ + { { 0x1608e4d,0x3872778,0x022cbc6,0x044d60a,0x3010dda,0x15fb0b5, + 0x37ddc11,0x19f5bda,0x156b6a3,0x023a838 }, + { 0x383b3b4,0x1380bc8,0x353ca35,0x250fc07,0x169966b,0x3780f29, + 0x36632b2,0x2d6b13f,0x124fa00,0x00fd6ae }, + 0 }, + /* 158 */ + { { 0x1739efb,0x2ec3656,0x2c0d337,0x3d39faf,0x1c751b0,0x04699f4, + 0x252dd64,0x095b8b6,0x0872b74,0x022f1da }, + { 0x2d3d253,0x38edca0,0x379fa5b,0x287d635,0x3a9f679,0x059d9ee, + 0x0ac168e,0x3cd3e87,0x19060fc,0x02ce1bc }, + 0 }, + /* 159 */ + { { 0x3edcfc2,0x0f04d4b,0x2f0d31f,0x1898be2,0x25396bf,0x15ca230, + 0x02b4eae,0x2713668,0x0f71b06,0x0132d18 }, + { 0x38095ea,0x1ed34d6,0x3603ae6,0x165bf01,0x192bbf8,0x1852859, + 0x075f66b,0x1488f85,0x10895ef,0x014b035 }, + 0 }, + /* 160 */ + { { 0x1339848,0x3084385,0x0c8d231,0x3a1c1de,0x0e87a28,0x255b85c, + 0x1de6616,0x2702e74,0x1382bb0,0x012b0f2 }, + { 0x198987d,0x381545a,0x34d619b,0x312b827,0x18b2376,0x28fe4cf, + 0x20b7651,0x017d077,0x0c7e397,0x00e0365 }, + 0 }, + /* 161 */ + { { 0x1542e75,0x0d56aa0,0x39b701a,0x287b806,0x396c724,0x0935c21, + 0x3a29776,0x0debdac,0x171de26,0x00b38f8 }, + { 0x1d5bc1a,0x3fad27d,0x22b5cfe,0x1f89ddf,0x0a65560,0x144dd5b, + 0x2aac2f9,0x139353f,0x0520b62,0x00b9b36 }, + 0 }, + /* 162 */ + { { 0x031c31d,0x16552e3,0x1a0c368,0x0016fc8,0x168533d,0x171e7b2, + 0x17626e7,0x275502f,0x14742c6,0x03285dd }, + { 0x2d2dbb2,0x3b6bffd,0x1d18cc6,0x2f45d2a,0x0fd0d8c,0x2915e3a, + 0x1e8793a,0x0b39a1d,0x3139cab,0x02a5da9 }, + 0 }, + /* 163 */ + { { 0x3fb353d,0x147c6e4,0x3a720a6,0x22d5ff3,0x1d75cab,0x06c54a0, + 0x08cfa73,0x12666aa,0x3170a1f,0x021c829 }, + { 0x13e1b90,0x3a34dda,0x1fc38c3,0x02c5bdb,0x2d345dc,0x14aa1d0, + 0x28d00ab,0x224f23a,0x329c769,0x025c67b }, + 0 }, + /* 164 */ + { { 0x0e35909,0x3bb6356,0x0116820,0x370cf77,0x29366d8,0x3881409, + 0x3999d06,0x013075f,0x176e157,0x02941ca }, + { 0x0e70b2e,0x28dfab1,0x2a8a002,0x15da242,0x084dcf6,0x116ca97, + 0x31bf186,0x1dc9735,0x09df7b7,0x0264e27 }, + 0 }, + /* 165 */ + { { 0x2da7a4b,0x3023c9e,0x1366238,0x00ff4e2,0x03abe9d,0x19bd44b, + 0x272e897,0x20b91ad,0x2aa202c,0x02a2201 }, + { 0x380184e,0x08112b4,0x0b85660,0x31049aa,0x3a8cb78,0x36113c5, + 0x1670c0a,0x373f9e7,0x3fb4738,0x00010ef }, + 0 }, + /* 166 */ + { { 0x2d5192e,0x26d770d,0x32af8d5,0x34d1642,0x1acf885,0x05805e0, + 0x166d0a1,0x1219a0d,0x301ba6c,0x014bcfb }, + { 0x2dcb64d,0x19cca83,0x379f398,0x08e01a0,0x10a482c,0x0103cc2, + 0x0be5fa7,0x1f9d45b,0x1899ef2,0x00ca5af }, + 0 }, + /* 167 */ + { { 0x14d81d7,0x2aea251,0x1b3c476,0x3bd47ae,0x29eade7,0x0715e61, + 0x1a21cd8,0x1c7a586,0x2bfaee5,0x00ee43f }, + { 0x096f7cb,0x0c08f95,0x1bc4939,0x361fed4,0x255be41,0x26fad73, + 0x31dd489,0x02c600f,0x29d9f81,0x01ba201 }, + 0 }, + /* 168 */ + { { 0x03ea1db,0x1eac46d,0x1292ce3,0x2a54967,0x20a7ff1,0x3e13c61, + 0x1b02218,0x2b44e14,0x3eadefa,0x029c88a }, + { 0x30a9144,0x31e3b0a,0x19c5a2a,0x147cbe9,0x05a0240,0x051f38e, + 0x11eca56,0x31a4247,0x123bc2a,0x02fa535 }, + 0 }, + /* 169 */ + { { 0x3226ce7,0x1251782,0x0b7072f,0x11e59fa,0x2b8afd7,0x169b18f, + 0x2a46f18,0x31d9bb7,0x2fe9be8,0x01de0b7 }, + { 0x1b38626,0x34aa90f,0x3ad1760,0x21ddbd9,0x3460ae7,0x1126736, + 0x1b86fc5,0x0b92cd0,0x167a289,0x000e0e1 }, + 0 }, + /* 170 */ + { { 0x1ec1a0f,0x36bbf5e,0x1c972d8,0x3f73ace,0x13bbcd6,0x23d86a5, + 0x175ffc5,0x2d083d5,0x2c4adf7,0x036f661 }, + { 0x1f39eb7,0x2a20505,0x176c81a,0x3d6e636,0x16ee2fc,0x3cbdc5f, + 0x25475dc,0x2ef4151,0x3c46860,0x0238934 }, + 0 }, + /* 171 */ + { { 0x2587390,0x3639526,0x0588749,0x13c32fb,0x212bb19,0x09660f1, + 0x207da4b,0x2bf211b,0x1c4407b,0x01506a6 }, + { 0x24c8842,0x105a498,0x05ffdb2,0x0ab61b0,0x26044c1,0x3dff3d8, + 0x1d14b44,0x0d74716,0x049f57d,0x030024b }, + 0 }, + /* 172 */ + { { 0x32e61ef,0x31d70f7,0x35cad3c,0x320b86c,0x07e8841,0x027ca7d, + 0x2d30d19,0x2513718,0x2347286,0x01d7901 }, + { 0x3c237d0,0x107f16e,0x01c9e7d,0x3c3b13c,0x0c9537b,0x20af54d, + 0x051a162,0x2161a47,0x258c784,0x016df2d }, + 0 }, + /* 173 */ + { { 0x228ead1,0x29c2122,0x07f6964,0x023f4ed,0x1802dc5,0x19f96ce, + 0x24bfd17,0x25e866b,0x2ba8df0,0x01eb84f }, + { 0x2dd384e,0x05bbe3a,0x3f06fd2,0x366dacb,0x30361a2,0x2f36d7c, + 0x0b98784,0x38ff481,0x074e2a8,0x01e1f60 }, + 0 }, + /* 174 */ + { { 0x17fbb1c,0x0975add,0x1debc5e,0x2cb2880,0x3e47bdd,0x3488cff, + 0x15e9a36,0x2121129,0x0199ef2,0x017088a }, + { 0x0315250,0x352a162,0x17c1773,0x0ae09c2,0x321b21a,0x3bd74cf, + 0x3c4ea1d,0x3cac2ad,0x3abbaf0,0x039174d }, + 0 }, + /* 175 */ + { { 0x0511c8a,0x3c78d0a,0x2cd3d2d,0x322f729,0x3ebb229,0x09f0e69, + 0x0a71a76,0x2e74d5e,0x12284df,0x03b5ef0 }, + { 0x3dea561,0x0a9b7e4,0x0ed1cf2,0x237523c,0x05443f1,0x2eb48fa, + 0x3861405,0x1b49f62,0x0c945ca,0x02ab25f }, + 0 }, + /* 176 */ + { { 0x16bd00a,0x13a9d28,0x3cc1eb5,0x2b7d702,0x2d839e9,0x3e6ff01, + 0x2bb7f11,0x3713824,0x3b31163,0x00c63e5 }, + { 0x30d7138,0x0316fb0,0x0220ecc,0x08eaf0c,0x244e8df,0x0088d81, + 0x37972fb,0x3fd34ae,0x2a19a84,0x03e907e }, + 0 }, + /* 177 */ + { { 0x2642269,0x0b65d29,0x03bd440,0x33a6ede,0x3c81814,0x2507982, + 0x0d38e47,0x3a788e6,0x32c1d26,0x00e2eda }, + { 0x2577f87,0x392895a,0x3e1cc64,0x14f7047,0x08b52d2,0x08a01ca, + 0x336abf6,0x00697fc,0x105ce76,0x0253742 }, + 0 }, + /* 178 */ + { { 0x293f92a,0x33df737,0x3315156,0x32e26d7,0x0a01333,0x26579d4, + 0x004df9c,0x0aba409,0x067d25c,0x02481de }, + { 0x3f39d44,0x1c78042,0x13d7e24,0x0825aed,0x35f2c90,0x3270f63, + 0x04b7b35,0x3ad4531,0x28bd29b,0x0207a10 }, + 0 }, + /* 179 */ + { { 0x077199f,0x270aeb1,0x0dd96dd,0x3b9ad7b,0x28cb8ee,0x3903f43, + 0x37db3fe,0x292c62b,0x362dbbf,0x006e52a }, + { 0x247f143,0x0362cf3,0x216344f,0x3f18fd1,0x351e623,0x31664e0, + 0x0f270fc,0x243bbc6,0x2280555,0x001a8e3 }, + 0 }, + /* 180 */ + { { 0x3355b49,0x2c04e6c,0x399b2e5,0x182d3af,0x020e265,0x09a7cf7, + 0x0ffa6bd,0x353e302,0x02083d9,0x029ecdb }, + { 0x33e8830,0x0570e86,0x1c0b64d,0x386a27e,0x0d5fcea,0x0b45a4c, + 0x2ee4a2e,0x0a8833f,0x2b4a282,0x02f9531 }, + 0 }, + /* 181 */ + { { 0x191167c,0x36cf7e3,0x225ed6c,0x1e79e99,0x0517c3f,0x11ab1fd, + 0x05648f3,0x08aedc4,0x1abeae0,0x02fcc29 }, + { 0x3828a68,0x1e16fa4,0x30368e7,0x0c9fcfb,0x25161c3,0x24851ac, + 0x1b5feb5,0x344eb84,0x0de2732,0x0347208 }, + 0 }, + /* 182 */ + { { 0x038b363,0x384d1e4,0x2519043,0x151ac17,0x158c11f,0x009b2b4, + 0x257abe6,0x2368d3f,0x3ed68a1,0x02df45e }, + { 0x29c2559,0x2962478,0x3d8444c,0x1d96fff,0x04f7a03,0x1391a52, + 0x0de4af7,0x3319126,0x15e6412,0x00e65ff }, + 0 }, + /* 183 */ + { { 0x3d61507,0x1d1a0a2,0x0d2af20,0x354d299,0x329e132,0x2a28578, + 0x2ddfb08,0x04fa3ff,0x1293c6c,0x003bae2 }, + { 0x3e259f8,0x1a68fa9,0x3e67e9b,0x39b44f9,0x1ce1db7,0x347e9a1, + 0x3318f6a,0x2dbbc9d,0x2f8c922,0x008a245 }, + 0 }, + /* 184 */ + { { 0x212ab5b,0x2b896c2,0x0136959,0x07e55ef,0x0cc1117,0x05b8ac3, + 0x18429ed,0x025fa01,0x11d6e93,0x03b016b }, + { 0x03f3708,0x2e96fab,0x1d77157,0x0d4c2d6,0x131baf9,0x0608d39, + 0x3552371,0x06cdd1e,0x1567ff1,0x01f4c50 }, + 0 }, + /* 185 */ + { { 0x2dfefab,0x270173d,0x37077bd,0x1a372cd,0x1be2f22,0x28e2ee5, + 0x3ead973,0x35e8f94,0x2fc9bc1,0x03a7399 }, + { 0x36a02a1,0x2855d9b,0x00ed75a,0x37d8398,0x138c087,0x233706e, + 0x147f346,0x01947e2,0x3017228,0x0365942 }, + 0 }, + /* 186 */ + { { 0x2057e60,0x2d31296,0x25e4504,0x2fa37bc,0x1cbccc3,0x1f0732f, + 0x3532081,0x2de8a98,0x19a804e,0x005359a }, + { 0x31f411a,0x2a10576,0x369c2c8,0x02fe035,0x109fbaf,0x30bddeb, + 0x1eef901,0x1662ad3,0x0410d43,0x01bd31a }, + 0 }, + /* 187 */ + { { 0x2c24a96,0x1b7d3a5,0x19a3872,0x217f2f6,0x2534dbc,0x2cab8c2, + 0x066ef28,0x26aecf1,0x0fd6118,0x01310d4 }, + { 0x055b8da,0x1fdc5be,0x38a1296,0x25118f0,0x341a423,0x2ba4cd0, + 0x3e1413e,0x062d70d,0x2425a31,0x029c9b4 }, + 0 }, + /* 188 */ + { { 0x08c1086,0x1acfba5,0x22e1dae,0x0f72f4e,0x3f1de50,0x0f408bc, + 0x35ed3f0,0x3ce48fc,0x282cc6c,0x004d8e7 }, + { 0x1afaa86,0x24e3ef3,0x22589ac,0x3ec9952,0x1f45bc5,0x14144ca, + 0x23b26e4,0x0d68c65,0x1e1c1a3,0x032a4d9 }, + 0 }, + /* 189 */ + { { 0x03b2d20,0x16b1d53,0x241b361,0x05e4138,0x1742a54,0x32741c7, + 0x0521c4c,0x1ca96c2,0x034970b,0x02738a7 }, + { 0x13e0ad6,0x207dcdb,0x034c8cc,0x27bcbe1,0x18060da,0x33a18b6, + 0x2d1d1a6,0x2be60d7,0x3d7ab42,0x012312a }, + 0 }, + /* 190 */ + { { 0x0c7485a,0x06c3310,0x0dbfd22,0x2ef949d,0x0ead455,0x098f4ba, + 0x3c76989,0x0cf2d24,0x032f67b,0x01e005f }, + { 0x30cb5ee,0x0d5da64,0x0ed2b9d,0x2503102,0x1c0d14e,0x1cbc693, + 0x37bf552,0x07013e2,0x054de5c,0x014f341 }, + 0 }, + /* 191 */ + { { 0x128ccac,0x1617e97,0x346ebcd,0x158016d,0x25f823e,0x34048ea, + 0x39f0a1c,0x3ea3df1,0x1c1d3d7,0x03ba919 }, + { 0x151803b,0x01967c1,0x2f70781,0x27df39a,0x06c0b59,0x24a239c, + 0x15a7702,0x2464d06,0x2a47ae6,0x006db90 }, + 0 }, + /* 192 */ + { { 0x27d04c3,0x024df3d,0x38112e8,0x38a27ba,0x01e312b,0x0965358, + 0x35d8879,0x2f4f55a,0x214187f,0x0008936 }, + { 0x05fe36f,0x2ee18c3,0x1f5f87a,0x1813bd4,0x0580f3c,0x0ed0a7b, + 0x0fb1bfb,0x3fcce59,0x2f042bf,0x01820e3 }, + 0 }, + /* 193 */ + { { 0x20bbe99,0x32cbc9f,0x39ee432,0x3cc12a8,0x37bda44,0x3ea4e40, + 0x097c7a9,0x0590d7d,0x2022d33,0x018dbac }, + { 0x3ae00aa,0x3439864,0x2d2ffcf,0x3f8c6b9,0x0875a00,0x3e4e407, + 0x3658a29,0x22eb3d0,0x2b63921,0x022113b }, + 0 }, + /* 194 */ + { { 0x33bae58,0x05c749a,0x1f3e114,0x1c45f8e,0x27db3df,0x06a3ab6, + 0x37bc7f8,0x1e27b34,0x3dc51fb,0x009eea0 }, + { 0x3f54de5,0x3d0e7fe,0x1a71a7d,0x02ed7f8,0x0727703,0x2ca5e92, + 0x2e8e35d,0x292ad0b,0x13487f3,0x02b6d8b }, + 0 }, + /* 195 */ + { { 0x175df2a,0x05a28a8,0x32e99b1,0x13d8630,0x2082aa0,0x11ac245, + 0x24f2e71,0x322cb27,0x17675e7,0x02e643f }, + { 0x1f37313,0x2765ad3,0x0789082,0x1e742d0,0x11c2055,0x2021dc4, + 0x09ae4a7,0x346359b,0x2f94d10,0x0205c1f }, + 0 }, + /* 196 */ + { { 0x3d6ff96,0x1f2ac80,0x336097d,0x3f03610,0x35b851b,0x010b6d2, + 0x0823c4d,0x2a9709a,0x2ead5a8,0x00de4b6 }, + { 0x01afa0b,0x0621965,0x3671528,0x1050b60,0x3f3e9e7,0x2f93829, + 0x0825275,0x006e85f,0x35e94b0,0x016af58 }, + 0 }, + /* 197 */ + { { 0x2c4927c,0x3ea1382,0x0f23727,0x0d69f23,0x3e38860,0x2b72837, + 0x3cd5ea4,0x2d84292,0x321846a,0x016656f }, + { 0x29dfa33,0x3e182e0,0x018be90,0x2ba563f,0x2caafe2,0x218c0d9, + 0x3baf447,0x1047a6c,0x0a2d483,0x01130cb }, + 0 }, + /* 198 */ + { { 0x00ed80c,0x2a5fc79,0x0a82a74,0x2c4c74b,0x15f938c,0x30b5ab6, + 0x32124b7,0x295314f,0x2fb8082,0x007c858 }, + { 0x20b173e,0x19f315c,0x12f97e4,0x198217c,0x040e8a6,0x3275977, + 0x2bc20e4,0x01f2633,0x02bc3e9,0x023c750 }, + 0 }, + /* 199 */ + { { 0x3c4058a,0x24be73e,0x16704f5,0x2d8a4bd,0x3b15e14,0x3076315, + 0x1cfe37b,0x36fe715,0x343926e,0x02c6603 }, + { 0x2c76b09,0x0cf824c,0x3f7898c,0x274cec1,0x11df527,0x18eed18, + 0x08ead48,0x23915bc,0x19b3744,0x00a0a2b }, + 0 }, + /* 200 */ + { { 0x0cf4ac5,0x1c8b131,0x0afb696,0x0ff7799,0x2f5ac1a,0x022420c, + 0x11baa2e,0x2ce4015,0x1275a14,0x0125cfc }, + { 0x22eac5d,0x360cd4c,0x3568e59,0x3d42f66,0x35e07ee,0x09620e4, + 0x36720fa,0x22b1eac,0x2d0db16,0x01b6b23 }, + 0 }, + /* 201 */ + { { 0x1a835ef,0x1516bbb,0x2d51f7b,0x3487443,0x14aa113,0x0dd06c2, + 0x1a65e01,0x379300d,0x35920b9,0x012c8fb }, + { 0x04c7341,0x2eda00f,0x3c37e82,0x1b4fd62,0x0d45770,0x1478fba, + 0x127863a,0x26939cd,0x134ddf4,0x01375c5 }, + 0 }, + /* 202 */ + { { 0x1476cd9,0x1119ca5,0x325bbf9,0x0bf8c69,0x0648d07,0x312d9f8, + 0x01c8b8f,0x136ec51,0x0002f4a,0x03f4c5c }, + { 0x195d0e1,0x10ffd22,0x29aa1cb,0x3443bdc,0x276e695,0x05e6260, + 0x15f9764,0x3cd9783,0x18c9569,0x0053eb1 }, + 0 }, + /* 203 */ + { { 0x312ae18,0x280197c,0x3fc9ad9,0x303f324,0x251958d,0x29f4a11, + 0x2142408,0x3694366,0x25136ab,0x03b5f1d }, + { 0x1d4abbc,0x1c3c689,0x13ea462,0x3cfc684,0x39b5dd8,0x2d4654b, + 0x09b0755,0x27d4f18,0x3f74d2e,0x03fbf2d }, + 0 }, + /* 204 */ + { { 0x2119185,0x2525eae,0x1ba4bd0,0x0c2ab11,0x1d54e8c,0x294845e, + 0x2479dea,0x3602d24,0x17e87e0,0x0060069 }, + { 0x0afffb0,0x34fe37f,0x1240073,0x02eb895,0x06cf33c,0x2d7f7ef, + 0x1d763b5,0x04191e0,0x11e1ead,0x027e3f0 }, + 0 }, + /* 205 */ + { { 0x269544c,0x0e85c57,0x3813158,0x19fc12d,0x20eaf85,0x1e2930c, + 0x22a8fd2,0x1a6a478,0x09d3d3a,0x02a74e0 }, + { 0x1a2da3b,0x30b0b16,0x0847936,0x3d86257,0x138ccbc,0x0f5421a, + 0x25244e6,0x23bdd79,0x1aee117,0x00c01ae }, + 0 }, + /* 206 */ + { { 0x1eead28,0x07cac32,0x1fbc0bb,0x17627d3,0x17eef63,0x0b3a24e, + 0x0757fdb,0x3dd841d,0x3d745f8,0x002ae17 }, + { 0x25b4549,0x29f24cf,0x2f21ecd,0x1725e48,0x04be2bb,0x10ee010, + 0x1a1274b,0x10b0898,0x27511e9,0x02c48b5 }, + 0 }, + /* 207 */ + { { 0x2a5ae7a,0x181ef99,0x0be33be,0x3e9dab7,0x101e703,0x3adb971, + 0x1043014,0x2ebb2be,0x1c1097d,0x027d667 }, + { 0x3f250ed,0x16dc603,0x20dc6d7,0x1d0d268,0x38eb915,0x02c89e8, + 0x1605a41,0x12de109,0x0e08a29,0x01f554a }, + 0 }, + /* 208 */ + { { 0x0c26def,0x163d988,0x2d1ef0f,0x3a960ac,0x1025585,0x0738e20, + 0x27d79b0,0x05cc3ef,0x201303f,0x00a333a }, + { 0x1644ba5,0x2af345e,0x30b8d1d,0x3a01bff,0x31fc643,0x1acf85e, + 0x0a76fc6,0x04efe98,0x348a1d0,0x03062eb }, + 0 }, + /* 209 */ + { { 0x1c4216d,0x18e3217,0x02ac34e,0x19c8185,0x200c010,0x17d4192, + 0x13a1719,0x165af51,0x09db7a9,0x0277be0 }, + { 0x3ab8d2c,0x2190b99,0x22b641e,0x0cd88de,0x3b42404,0x1310862, + 0x106a6d6,0x23395f5,0x0b06880,0x000d5fe }, + 0 }, + /* 210 */ + { { 0x0d2cc88,0x36f9913,0x339d8e9,0x237c2e3,0x0cc61c2,0x34c2832, + 0x309874c,0x2621d28,0x2dd1b48,0x0392806 }, + { 0x17cd8f9,0x07bab3d,0x0c482ed,0x0faf565,0x31b767d,0x2f4bde1, + 0x295c717,0x330c29c,0x179ce10,0x0119b5f }, + 0 }, + /* 211 */ + { { 0x1ada2c7,0x0c624a7,0x227d47d,0x30e3e6a,0x14fa0a6,0x0829678, + 0x24fd288,0x2b46a43,0x122451e,0x0319ca9 }, + { 0x186b655,0x01f3217,0x0af1306,0x0efe6b5,0x2f0235d,0x1c45ca9, + 0x2086805,0x1d44e66,0x0faf2a6,0x0178f59 }, + 0 }, + /* 212 */ + { { 0x33b4416,0x10431e6,0x2d99aa6,0x217aac9,0x0cd8fcf,0x2d95a9d, + 0x3ff74ad,0x10bf17a,0x295eb8e,0x01b229e }, + { 0x02a63bd,0x182e9ec,0x004710c,0x00e2e3c,0x06b2f23,0x04b642c, + 0x2c37383,0x32a4631,0x022ad82,0x00d22b9 }, + 0 }, + /* 213 */ + { { 0x0cda2fb,0x1d198d7,0x26d27f4,0x286381c,0x022acca,0x24ac7c8, + 0x2df7824,0x0b4ba16,0x1e0d9ef,0x03041d3 }, + { 0x29a65b3,0x0f3912b,0x151bfcf,0x2b0175c,0x0fd71e4,0x39aa5e2, + 0x311f50c,0x13ff351,0x3dbc9e5,0x03eeb7e }, + 0 }, + /* 214 */ + { { 0x0a99363,0x0fc7348,0x2775171,0x23db3c8,0x2b91565,0x134d66c, + 0x0175cd2,0x1bf365a,0x2b48371,0x02dfe5d }, + { 0x16dbf74,0x2389357,0x2f36575,0x3f5c70e,0x38d23ba,0x090f7f8, + 0x3477600,0x3201523,0x32ecafc,0x03d3506 }, + 0 }, + /* 215 */ + { { 0x1abd48d,0x073ca3f,0x38a451f,0x0d8cb01,0x1ce81be,0x05c51ba, + 0x0e29741,0x03c41ab,0x0eae016,0x0060209 }, + { 0x2e58358,0x1da62d9,0x2358038,0x14b39b2,0x1635687,0x39079b1, + 0x380e345,0x1b49608,0x23983cf,0x019f97d }, + 0 }, + /* 216 */ + { { 0x34899ef,0x332e373,0x04c0f89,0x3c27aed,0x1949015,0x09663b2, + 0x2f9276b,0x07f1951,0x09a04c1,0x027fbde }, + { 0x3d2a071,0x19fb3d4,0x1b096d3,0x1fe9146,0x3b10e1a,0x0478bbb, + 0x2b3fb06,0x1388329,0x181a99c,0x02f2030 }, + 0 }, + /* 217 */ + { { 0x1eb82e6,0x14dbe39,0x3920972,0x31fd5b2,0x21a484f,0x02d7697, + 0x0e21715,0x37c431e,0x2629f8c,0x01249c3 }, + { 0x26b50ad,0x26deefa,0x0ffc1a3,0x30688e2,0x39a0284,0x041c65e, + 0x03eb178,0x0bdfd50,0x2f96137,0x034bb94 }, + 0 }, + /* 218 */ + { { 0x0e0362a,0x334a162,0x194dd37,0x29e3e97,0x2442fa8,0x10d2949, + 0x3836e5a,0x2dccebf,0x0bee5ab,0x037ed1e }, + { 0x33eede6,0x3c739d9,0x2f04a91,0x350ad6c,0x3a5390a,0x14c368b, + 0x26f7bf5,0x11ce979,0x0b408df,0x0366850 }, + 0 }, + /* 219 */ + { { 0x28ea498,0x0886d5b,0x2e090e0,0x0a4d58f,0x2623478,0x0d74ab7, + 0x2b83913,0x12c6b81,0x18d623f,0x01d8301 }, + { 0x198aa79,0x26d6330,0x3a7f0b8,0x34bc1ea,0x2f74890,0x378955a, + 0x204110f,0x0102538,0x02d8f19,0x01c5066 }, + 0 }, + /* 220 */ + { { 0x14b0f45,0x2838cd3,0x14e16f0,0x0e0e4aa,0x2d9280b,0x0f18757, + 0x3324c6b,0x1391ceb,0x1ce89d5,0x00ebe74 }, + { 0x0930371,0x3de6048,0x3097fd8,0x1308705,0x3eda266,0x3108c26, + 0x1545dcd,0x1f7583a,0x1c37395,0x02c7e05 }, + 0 }, + /* 221 */ + { { 0x1fec44a,0x2a9e3a2,0x0caf84f,0x11cf2a9,0x0c8c2ae,0x06da989, + 0x1c807dc,0x3c149a4,0x1141543,0x02906bb }, + { 0x15ffe04,0x0d4e65f,0x2e20424,0x37d896d,0x18bacb2,0x1e05ddd, + 0x1660be8,0x183be17,0x1dd86fb,0x035ba70 }, + 0 }, + /* 222 */ + { { 0x2853264,0x0ba5fb1,0x0a0b3aa,0x2df88c1,0x2771533,0x23aba6f, + 0x112bb7b,0x3e3086e,0x210ae9b,0x027271b }, + { 0x030b74c,0x0269678,0x1e90a23,0x135a98c,0x24ed749,0x126de7c, + 0x344b23a,0x186da27,0x19640fa,0x0159af5 }, + 0 }, + /* 223 */ + { { 0x18061f3,0x3004630,0x3c70066,0x34df20f,0x1190b25,0x1c9cc91, + 0x1fc8e02,0x0d17bc1,0x390f525,0x033cb1c }, + { 0x0eb30cf,0x2f3ad04,0x303aa09,0x2e835dd,0x1cfd2eb,0x143fc95, + 0x02c43a1,0x025e7a1,0x3558aa2,0x000bd45 }, + 0 }, + /* 224 */ + { { 0x1db7d07,0x3bde52b,0x1500396,0x1089115,0x20b4fc7,0x1e2a8f3, + 0x3f8eacc,0x365f7eb,0x1a5e8d4,0x0053a6b }, + { 0x37079e2,0x120284b,0x000edaa,0x33792c2,0x145baa3,0x20e055f, + 0x365e2d7,0x26ba005,0x3ab8e9d,0x0282b53 }, + 0 }, + /* 225 */ + { { 0x2653618,0x2dd8852,0x2a5f0bf,0x0f0c7aa,0x2187281,0x1252757, + 0x13e7374,0x3b47855,0x0b86e56,0x02f354c }, + { 0x2e9c47b,0x2fa14cc,0x19ab169,0x3fad401,0x0dc2776,0x24afeed, + 0x3a97611,0x0d07736,0x3cf6979,0x02424a0 }, + 0 }, + /* 226 */ + { { 0x2e81a13,0x000c91d,0x123967b,0x265885c,0x29bee1a,0x0cb8675, + 0x2d361bd,0x1526823,0x3c9ace1,0x00d7bad }, + { 0x24e5bdc,0x02b969f,0x2c6e128,0x34edb3b,0x12dcd2c,0x3899af0, + 0x24224c6,0x3a1914b,0x0f4448a,0x026a2cb }, + 0 }, + /* 227 */ + { { 0x1d03b59,0x1c6fc82,0x32abf64,0x28ed96b,0x1c90e62,0x2f57bb2, + 0x3ff168e,0x04de7fd,0x0f4d449,0x01af6d8 }, + { 0x255bc30,0x2bfaf22,0x3fe0dad,0x0584025,0x1c79ead,0x3078ef7, + 0x2197414,0x022a50b,0x0fd94ba,0x0007b0f }, + 0 }, + /* 228 */ + { { 0x09485c2,0x09dfaf7,0x10c7ba6,0x1e48bec,0x248cc9a,0x028a362, + 0x21d60f7,0x193d93d,0x1c04754,0x0346b2c }, + { 0x2f36612,0x240ac49,0x0d8bd26,0x13b8186,0x259c3a4,0x020d5fb, + 0x38a8133,0x09b0937,0x39d4056,0x01f7341 }, + 0 }, + /* 229 */ + { { 0x05a4b48,0x1f534fc,0x07725ce,0x148dc8c,0x2adcd29,0x04aa456, + 0x0f79718,0x066e346,0x189377d,0x002fd4d }, + { 0x068ea73,0x336569b,0x184d35e,0x32a08e9,0x3c7f3bb,0x11ce9c8, + 0x3674c6f,0x21bf27e,0x0d9e166,0x034a2f9 }, + 0 }, + /* 230 */ + { { 0x0fa8e4b,0x2e6418e,0x18fc5d2,0x1ba24ff,0x0559f18,0x0dbedbf, + 0x2de2aa4,0x22338e9,0x3aa510f,0x035d801 }, + { 0x23a4988,0x02aad94,0x02732d1,0x111d374,0x0b455cf,0x0d01c9e, + 0x067082a,0x2ec05fd,0x368b303,0x03cad4b }, + 0 }, + /* 231 */ + { { 0x035b4ca,0x1fabea6,0x1cbc0d5,0x3f2ed9a,0x02d2232,0x1990c66, + 0x2eb680c,0x3b4ea3b,0x18ecc5a,0x03636fa }, + { 0x1a02709,0x26f8ff1,0x1fa8cba,0x397d6e8,0x230be68,0x043aa14, + 0x3d43cdf,0x25c17fa,0x3a3ee55,0x0380564 }, + 0 }, + /* 232 */ + { { 0x275a0a6,0x16bd43a,0x0033d3e,0x2b15e16,0x2512226,0x005d901, + 0x26d50fd,0x3bc19bf,0x3b1aeb8,0x02bfb01 }, + { 0x0bb0a31,0x26559e0,0x1aae7fb,0x330dcc2,0x16f1af3,0x06afce2, + 0x13a15a0,0x2ff7645,0x3546e2d,0x029c6e4 }, + 0 }, + /* 233 */ + { { 0x0f593d2,0x384b806,0x122bbf8,0x0a281e0,0x1d1a904,0x2e93cab, + 0x0505db0,0x08f6454,0x05c6285,0x014e880 }, + { 0x3f2b935,0x22d8e79,0x161a07c,0x16b060a,0x02bff97,0x146328b, + 0x3ceea77,0x238f61a,0x19b3d58,0x02fd1f4 }, + 0 }, + /* 234 */ + { { 0x17665d5,0x259e9f7,0x0de5672,0x15cbcbd,0x34e3030,0x035240f, + 0x0005ae8,0x286d851,0x07f39c9,0x000070b }, + { 0x1efc6d6,0x2a0051a,0x2724143,0x2a9ef1e,0x0c810bd,0x1e05429, + 0x25670ba,0x2e66d7d,0x0e786ff,0x03f6b7e }, + 0 }, + /* 235 */ + { { 0x3c00785,0x232e23f,0x2b67fd3,0x244ed23,0x077fa75,0x3cda3ef, + 0x14d055b,0x0f25011,0x24d5aa4,0x00ea0e3 }, + { 0x297bb9a,0x198ca4f,0x14d9561,0x18d1076,0x39eb933,0x2b6caa0, + 0x1591a60,0x0768d45,0x257873e,0x00f36e0 }, + 0 }, + /* 236 */ + { { 0x1e77eab,0x0502a5f,0x0109137,0x0350592,0x3f7e1c5,0x3ac7437, + 0x2dcad2c,0x1fee9d8,0x089f1f5,0x0169833 }, + { 0x0d45673,0x0d8e090,0x065580b,0x065644f,0x11b82be,0x3592dd0, + 0x3284b8d,0x23f0015,0x16fdbfd,0x0248bfd }, + 0 }, + /* 237 */ + { { 0x1a129a1,0x1977bb2,0x0e041b2,0x15f30a1,0x0a5b1ce,0x3afef8f, + 0x380c46c,0x3358810,0x27df6c5,0x01ca466 }, + { 0x3b90f9a,0x3d14ea3,0x031b298,0x02e2390,0x2d719c0,0x25bc615, + 0x2c0e777,0x0226b8c,0x3803624,0x0179e45 }, + 0 }, + /* 238 */ + { { 0x363cdfb,0x1bb155f,0x24fd5c1,0x1c7c72b,0x28e6a35,0x18165f2, + 0x226bea5,0x0beaff3,0x371e24c,0x0138294 }, + { 0x1765357,0x29034e9,0x22b4276,0x11035ce,0x23c89af,0x074468c, + 0x3370ae4,0x013bae3,0x018d566,0x03d7fde }, + 0 }, + /* 239 */ + { { 0x209df21,0x0f8ff86,0x0e47fbf,0x23b99ba,0x126d5d2,0x2722405, + 0x16bd0a2,0x1799082,0x0e9533f,0x039077c }, + { 0x3ba9e3f,0x3f6902c,0x1895305,0x3ac9813,0x3f2340c,0x3c0d9f1, + 0x26e1927,0x0557c21,0x16eac4f,0x023b75f }, + 0 }, + /* 240 */ + { { 0x3fc8ff3,0x0770382,0x342fc9a,0x0afa4db,0x314efd8,0x328e07b, + 0x016f7cc,0x3ba599c,0x1caed8a,0x0050cb0 }, + { 0x0b23c26,0x2120a5c,0x3273ec6,0x1cc1cd6,0x2a64fe8,0x2bbc3d6, + 0x09f6e5e,0x34b1b8e,0x00b5ac8,0x032bbd2 }, + 0 }, + /* 241 */ + { { 0x1315922,0x1725e1d,0x0ca5524,0x1c4c18f,0x3d82951,0x193bcb2, + 0x0e60d0b,0x388dbcf,0x37e8efa,0x0342e85 }, + { 0x1b3af60,0x26ba3ec,0x220e53a,0x394f4b6,0x01a796a,0x3e7bbca, + 0x163605d,0x2b85807,0x17c1c54,0x03cc725 }, + 0 }, + /* 242 */ + { { 0x1cc4597,0x1635492,0x2028c0f,0x2c2eb82,0x2dc5015,0x0d2a052, + 0x05fc557,0x1f0ebbf,0x0cb96e1,0x0004d01 }, + { 0x1a824bf,0x3896172,0x2ed7b29,0x178007a,0x0d59318,0x07bda2b, + 0x2ee6826,0x0f9b235,0x04b9193,0x01bcddf }, + 0 }, + /* 243 */ + { { 0x0333fd2,0x0eeb46a,0x15b89f9,0x00968aa,0x2a89302,0x2bdd6b3, + 0x1e5037e,0x2541884,0x24ed2d0,0x01b6e8f }, + { 0x04399cd,0x3be6334,0x3adea48,0x1bb9adc,0x31811c6,0x05fb2bc, + 0x360752c,0x3d29dcb,0x3423bec,0x03c4f3c }, + 0 }, + /* 244 */ + { { 0x119e2eb,0x2e7b02a,0x0f68cee,0x257d8b0,0x183a9a1,0x2ae88a6, + 0x3a3bb67,0x2eb4f3e,0x1a9274b,0x0320fea }, + { 0x2fa1ce0,0x346c2d8,0x2fbf0d7,0x3d4d063,0x0e58b60,0x09c1bc1, + 0x28ef9e5,0x09a0efe,0x0f45d70,0x02d275c }, + 0 }, + /* 245 */ + { { 0x2d5513b,0x31d443e,0x1e2d914,0x3b2c5d4,0x105f32e,0x27ee756, + 0x050418d,0x3c73db6,0x1bb0c30,0x01673eb }, + { 0x1cb7fd6,0x1eb08d5,0x26a3e16,0x2e20810,0x0249367,0x029e219, + 0x2ec58c9,0x12d9fab,0x362354a,0x016eafc }, + 0 }, + /* 246 */ + { { 0x2424865,0x260747b,0x177f37c,0x1e3cb95,0x08b0028,0x2783016, + 0x2970f1b,0x323c1c0,0x2a79026,0x0186231 }, + { 0x0f244da,0x26866f4,0x087306f,0x173ec20,0x31ecced,0x3c84d8d, + 0x070f9b9,0x2e764d5,0x075df50,0x0264ff9 }, + 0 }, + /* 247 */ + { { 0x32c3609,0x0c737e6,0x14ea68e,0x300b11b,0x184eb19,0x29dd440, + 0x09ec1a9,0x185adeb,0x0664c80,0x0207dd9 }, + { 0x1fbe978,0x30a969d,0x33561d7,0x34fc60e,0x36743fe,0x00774af, + 0x0d1f045,0x018360e,0x12a5fe9,0x01592a0 }, + 0 }, + /* 248 */ + { { 0x2817d1d,0x2993d3e,0x2e0f7a5,0x112faa0,0x255f968,0x355fe6a, + 0x3f5a0fc,0x075b2d7,0x3cf00e5,0x0089afc }, + { 0x32833cf,0x06a7e4b,0x09a8d6d,0x1693d3e,0x320a0a3,0x3cfdfdd, + 0x136c498,0x1e0d845,0x347ff25,0x01a1de7 }, + 0 }, + /* 249 */ + { { 0x3043d08,0x030705c,0x20fa79b,0x1d07f00,0x0a54467,0x29b49b4, + 0x367e289,0x0b82f4d,0x0d1eb09,0x025ef2c }, + { 0x32ed3c3,0x1baaa3c,0x3c482ab,0x146ca06,0x3c8a4f1,0x3e85e3c, + 0x1bf4f3b,0x1195534,0x3e80a78,0x02a1cbf }, + 0 }, + /* 250 */ + { { 0x32b2086,0x2de4d68,0x3486b1a,0x03a0583,0x2e1eb71,0x2dab9af, + 0x10cd913,0x28daa6f,0x3fcb732,0x000a04a }, + { 0x3605318,0x3f5f2b3,0x2d1da63,0x143f7f5,0x1646e5d,0x040b586, + 0x1683982,0x25abe87,0x0c9fe53,0x001ce47 }, + 0 }, + /* 251 */ + { { 0x380d02b,0x055fc22,0x3f7fc50,0x3458a1d,0x26b8333,0x23550ab, + 0x0a1af87,0x0a821eb,0x2dc7e6d,0x00d574a }, + { 0x07386e1,0x3ccd68a,0x3275b41,0x253e390,0x2fd272a,0x1e6627a, + 0x2ca2cde,0x0e9e4a1,0x1e37c2a,0x00f70ac }, + 0 }, + /* 252 */ + { { 0x0581352,0x2748701,0x02bed68,0x094dd9e,0x30a00c8,0x3fb5c07, + 0x3bd5909,0x211ac80,0x1103ccd,0x0311e1a }, + { 0x0c768ed,0x29dc209,0x36575db,0x009a107,0x272feea,0x2b33383, + 0x313ed56,0x134c9cc,0x168d5bb,0x033310a }, + 0 }, + /* 253 */ + { { 0x17620b9,0x143784f,0x256a94e,0x229664a,0x1d89a5c,0x1d521f2, + 0x0076406,0x1c73f70,0x342aa48,0x03851fa }, + { 0x0f3ae46,0x2ad3bab,0x0fbe274,0x3ed40d4,0x2fd4936,0x232103a, + 0x2afe474,0x25b8f7c,0x047080e,0x008e6b0 }, + 0 }, + /* 254 */ + { { 0x3fee8d4,0x347cd4a,0x0fec481,0x33fe9ec,0x0ce80b5,0x33a6bcf, + 0x1c4c9e2,0x3967441,0x1a3f5f7,0x03157e8 }, + { 0x257c227,0x1bc53a0,0x200b318,0x0fcd0af,0x2c5b165,0x2a413ec, + 0x2fc998a,0x2da6426,0x19cd4f4,0x0025336 }, + 0 }, + /* 255 */ + { { 0x303beba,0x2072135,0x32918a9,0x140cb3a,0x08631d1,0x0ef527b, + 0x05f2c9e,0x2b4ce91,0x0b642ab,0x02e428c }, + { 0x0a5abf9,0x15013ed,0x3603b46,0x30dd76d,0x3004750,0x28d7627, + 0x1a42ccc,0x093ddbe,0x39a1b79,0x00067e2 }, + 0 }, +}; + +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_base_10(sp_point* r, sp_digit* k, + int map, void* heap) +{ + return sp_256_ecc_mulmod_stripe_10(r, &p256_base, p256_table, + k, map, heap); +} + +#endif + +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * km Scalar to multiply by. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_base_256(mp_int* km, ecc_point* r, int map, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point p; + sp_digit kd[10]; +#endif + sp_point* point; + sp_digit* k = NULL; + int err = MP_OKAY; + + err = sp_ecc_point_new(heap, p, point); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 10, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + if (err == MP_OKAY) { + sp_256_from_mp(k, 10, km); + + err = sp_256_ecc_mulmod_base_10(point, k, map, heap); + } + if (err == MP_OKAY) + err = sp_256_point_to_ecc_point_10(point, r); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(point, 0, heap); + + return err; +} + +#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ + defined(HAVE_ECC_VERIFY) +/* Returns 1 if the number of zero. + * Implementation is constant time. + * + * a Number to check. + * returns 1 if the number is zero and 0 otherwise. + */ +static int sp_256_iszero_10(const sp_digit* a) +{ + return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6] | a[7] | + a[8] | a[9]) == 0; +} + +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN || HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +/* Add 1 to a. (a = a + 1) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_256_add_one_10(sp_digit* a) +{ + a[0]++; + sp_256_norm_10(a); +} + +/* Read big endian unsigned byte aray into r. + * + * r A single precision integer. + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_256_from_bin(sp_digit* r, int max, const byte* a, int n) +{ + int i, j = 0, s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= ((sp_digit)a[i]) << s; + if (s >= 18) { + r[j] &= 0x3ffffff; + s = 26 - s; + if (j + 1 >= max) + break; + r[++j] = a[i] >> s; + s = 8 - s; + } + else + s += 8; + } + + for (j++; j < max; j++) + r[j] = 0; +} + +/* Generates a scalar that is in the range 1..order-1. + * + * rng Random number generator. + * k Scalar value. + * returns RNG failures, MEMORY_E when memory allocation fails and + * MP_OKAY on success. + */ +static int sp_256_ecc_gen_k_10(WC_RNG* rng, sp_digit* k) +{ + int err; + byte buf[32]; + + do { + err = wc_RNG_GenerateBlock(rng, buf, sizeof(buf)); + if (err == 0) { + sp_256_from_bin(k, 10, buf, sizeof(buf)); + if (sp_256_cmp_10(k, p256_order2) < 0) { + sp_256_add_one_10(k); + break; + } + } + } + while (err == 0); + + return err; +} + +/* Makes a random EC key pair. + * + * rng Random number generator. + * priv Generated private value. + * pub Generated public point. + * heap Heap to use for allocation. + * returns ECC_INF_E when the point does not have the correct order, RNG + * failures, MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point p; + sp_digit kd[10]; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point inf; +#endif +#endif + sp_point* point; + sp_digit* k = NULL; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point* infinity; +#endif + int err; + + (void)heap; + + err = sp_ecc_point_new(heap, p, point); +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, inf, infinity); +#endif +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 10, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + + if (err == MP_OKAY) + err = sp_256_ecc_gen_k_10(rng, k); + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_base_10(point, k, 1, NULL); + } + +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_10(infinity, point, p256_order, 1, NULL); + } + if (err == MP_OKAY) { + if (!sp_256_iszero_10(point->x) || !sp_256_iszero_10(point->y)) + err = ECC_INF_E; + } +#endif + + if (err == MP_OKAY) + err = sp_256_to_mp(k, priv); + if (err == MP_OKAY) + err = sp_256_point_to_ecc_point_10(point, pub); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); +#endif +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_ecc_point_free(infinity, 1, heap); +#endif + sp_ecc_point_free(point, 1, heap); + + return err; +} + +#ifdef HAVE_ECC_DHE +/* Write r as big endian to byte aray. + * Fixed length number of bytes written: 32 + * + * r A single precision integer. + * a Byte array. + */ +static void sp_256_to_bin(sp_digit* r, byte* a) +{ + int i, j, s = 0, b; + + for (i=0; i<9; i++) { + r[i+1] += r[i] >> 26; + r[i] &= 0x3ffffff; + } + j = 256 / 8 - 1; + a[j] = 0; + for (i=0; i<10 && j>=0; i++) { + b = 0; + a[j--] |= r[i] << s; b += 8 - s; + if (j < 0) + break; + while (b < 26) { + a[j--] = r[i] >> b; b += 8; + if (j < 0) + break; + } + s = 8 - (b - 26); + if (j >= 0) + a[j] = 0; + if (s != 0) + j++; + } +} + +/* Multiply the point by the scalar and serialize the X ordinate. + * The number is 0 padded to maximum size on output. + * + * priv Scalar to multiply the point by. + * pub Point to multiply. + * out Buffer to hold X ordinate. + * outLen On entry, size of the buffer in bytes. + * On exit, length of data in buffer in bytes. + * heap Heap to use for allocation. + * returns BUFFER_E if the buffer is to small for output size, + * MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_secret_gen_256(mp_int* priv, ecc_point* pub, byte* out, + word32* outLen, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point p; + sp_digit kd[10]; +#endif + sp_point* point = NULL; + sp_digit* k = NULL; + int err = MP_OKAY; + + if (*outLen < 32) + err = BUFFER_E; + + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, p, point); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 10, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(k, 10, priv); + sp_256_point_from_ecc_point_10(point, pub); + err = sp_256_ecc_mulmod_10(point, point, k, 1, heap); + } + if (err == MP_OKAY) { + sp_256_to_bin(point->x, out); + *outLen = 32; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(point, 0, heap); + + return err; +} +#endif /* HAVE_ECC_DHE */ + +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +/* Multiply a by scalar b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +SP_NOINLINE static void sp_256_mul_d_10(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int64_t tb = b; + int64_t t = 0; + int i; + + for (i = 0; i < 10; i++) { + t += tb * a[i]; + r[i] = t & 0x3ffffff; + t >>= 26; + } + r[10] = (sp_digit)t; +#else + int64_t tb = b; + int64_t t[10]; + + t[ 0] = tb * a[ 0]; + t[ 1] = tb * a[ 1]; + t[ 2] = tb * a[ 2]; + t[ 3] = tb * a[ 3]; + t[ 4] = tb * a[ 4]; + t[ 5] = tb * a[ 5]; + t[ 6] = tb * a[ 6]; + t[ 7] = tb * a[ 7]; + t[ 8] = tb * a[ 8]; + t[ 9] = tb * a[ 9]; + r[ 0] = (t[ 0] & 0x3ffffff); + r[ 1] = (sp_digit)(t[ 0] >> 26) + (t[ 1] & 0x3ffffff); + r[ 2] = (sp_digit)(t[ 1] >> 26) + (t[ 2] & 0x3ffffff); + r[ 3] = (sp_digit)(t[ 2] >> 26) + (t[ 3] & 0x3ffffff); + r[ 4] = (sp_digit)(t[ 3] >> 26) + (t[ 4] & 0x3ffffff); + r[ 5] = (sp_digit)(t[ 4] >> 26) + (t[ 5] & 0x3ffffff); + r[ 6] = (sp_digit)(t[ 5] >> 26) + (t[ 6] & 0x3ffffff); + r[ 7] = (sp_digit)(t[ 6] >> 26) + (t[ 7] & 0x3ffffff); + r[ 8] = (sp_digit)(t[ 7] >> 26) + (t[ 8] & 0x3ffffff); + r[ 9] = (sp_digit)(t[ 8] >> 26) + (t[ 9] & 0x3ffffff); + r[10] = (sp_digit)(t[ 9] >> 26); +#endif /* WOLFSSL_SP_SMALL */ +} + +#ifdef WOLFSSL_SP_DIV_32 +static WC_INLINE sp_digit sp_256_div_word_10(sp_digit d1, sp_digit d0, + sp_digit div) +{ + sp_digit d, r, t, dv; + int64_t t0, t1; + + /* dv has 14 bits. */ + dv = (div >> 12) + 1; + /* All 26 bits from d1 and top 5 bits from d0. */ + d = (d1 << 5) | (d0 >> 21); + r = d / dv; + d -= r * dv; + /* Up to 17 bits in r */ + /* Next 9 bits from d0. */ + d <<= 9; + r <<= 9; + d |= (d0 >> 12) & ((1 << 9) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 26 bits in r */ + + /* Handle rounding error with dv - top part */ + t0 = ((int64_t)d1 << 26) + d0; + t1 = (int64_t)r * div; + t1 = t0 - t1; + t = (sp_digit)(t1 >> 12) / dv; + r += t; + + /* Handle rounding error with dv - bottom 32 bits */ + t1 = (sp_digit)t0 - (r * div); + t = (sp_digit)t1 / div; + r += t; + + return r; +} +#endif /* WOLFSSL_SP_DIV_32 */ + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. + */ +static int sp_256_div_10(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + int i; +#ifndef WOLFSSL_SP_DIV_32 + int64_t d1; +#endif + sp_digit div, r1; +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* td; +#else + sp_digit t1d[20], t2d[10 + 1]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (3 * 10 + 1), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td != NULL) { + t1 = td; + t2 = td + 2 * 10; + } + else + err = MEMORY_E; +#else + t1 = t1d; + t2 = t2d; +#endif + + (void)m; + + if (err == MP_OKAY) { + div = d[9]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 10); + for (i=9; i>=0; i--) { + t1[10 + i] += t1[10 + i - 1] >> 26; + t1[10 + i - 1] &= 0x3ffffff; +#ifndef WOLFSSL_SP_DIV_32 + d1 = t1[10 + i]; + d1 <<= 26; + d1 += t1[10 + i - 1]; + r1 = (sp_digit)(d1 / div); +#else + r1 = sp_256_div_word_10(t1[10 + i], t1[10 + i - 1], div); +#endif + + sp_256_mul_d_10(t2, d, r1); + sp_256_sub_10(&t1[i], &t1[i], t2); + t1[10 + i] -= t2[10]; + t1[10 + i] += t1[10 + i - 1] >> 26; + t1[10 + i - 1] &= 0x3ffffff; + r1 = (((-t1[10 + i]) << 26) - t1[10 + i - 1]) / div; + r1++; + sp_256_mul_d_10(t2, d, r1); + sp_256_add_10(&t1[i], &t1[i], t2); + t1[10 + i] += t1[10 + i - 1] >> 26; + t1[10 + i - 1] &= 0x3ffffff; + } + t1[10 - 1] += t1[10 - 2] >> 26; + t1[10 - 2] &= 0x3ffffff; + r1 = t1[10 - 1] / div; + + sp_256_mul_d_10(t2, d, r1); + sp_256_sub_10(t1, t1, t2); + XMEMCPY(r, t1, sizeof(*r) * 2 * 10); + for (i=0; i<8; i++) { + r[i+1] += r[i] >> 26; + r[i] &= 0x3ffffff; + } + sp_256_cond_add_10(r, r, d, 0 - (r[9] < 0)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. + */ +static int sp_256_mod_10(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_256_div_10(a, m, NULL, r); +} + +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +#ifdef WOLFSSL_SP_SMALL +/* Order-2 for the P256 curve. */ +static const uint32_t p256_order_2[8] = { + 0xfc63254f,0xf3b9cac2,0xa7179e84,0xbce6faad,0xffffffff,0xffffffff, + 0x00000000,0xffffffff +}; +#else +/* The low half of the order-2 of the P256 curve. */ +static const uint32_t p256_order_low[4] = { + 0xfc63254f,0xf3b9cac2,0xa7179e84,0xbce6faad +}; +#endif /* WOLFSSL_SP_SMALL */ + +/* Multiply two number mod the order of P256 curve. (r = a * b mod order) + * + * r Result of the multiplication. + * a First operand of the multiplication. + * b Second operand of the multiplication. + */ +static void sp_256_mont_mul_order_10(sp_digit* r, sp_digit* a, sp_digit* b) +{ + sp_256_mul_10(r, a, b); + sp_256_mont_reduce_order_10(r, p256_order, p256_mp_order); +} + +/* Square number mod the order of P256 curve. (r = a * a mod order) + * + * r Result of the squaring. + * a Number to square. + */ +static void sp_256_mont_sqr_order_10(sp_digit* r, sp_digit* a) +{ + sp_256_sqr_10(r, a); + sp_256_mont_reduce_order_10(r, p256_order, p256_mp_order); +} + +#ifndef WOLFSSL_SP_SMALL +/* Square number mod the order of P256 curve a number of times. + * (r = a ^ n mod order) + * + * r Result of the squaring. + * a Number to square. + */ +static void sp_256_mont_sqr_n_order_10(sp_digit* r, sp_digit* a, int n) +{ + int i; + + sp_256_mont_sqr_order_10(r, a); + for (i=1; i=0; i--) { + sp_256_mont_sqr_order_10(t, t); + if (p256_order_2[i / 32] & ((sp_digit)1 << (i % 32))) + sp_256_mont_mul_order_10(t, t, a); + } + XMEMCPY(r, t, sizeof(sp_digit) * 10); +#else + sp_digit* t = td; + sp_digit* t2 = td + 2 * 10; + sp_digit* t3 = td + 4 * 10; + int i; + + /* t = a^2 */ + sp_256_mont_sqr_order_10(t, a); + /* t = a^3 = t * a */ + sp_256_mont_mul_order_10(t, t, a); + /* t2= a^c = t ^ 2 ^ 2 */ + sp_256_mont_sqr_n_order_10(t2, t, 2); + /* t3= a^f = t2 * t */ + sp_256_mont_mul_order_10(t3, t2, t); + /* t2= a^f0 = t3 ^ 2 ^ 4 */ + sp_256_mont_sqr_n_order_10(t2, t3, 4); + /* t = a^ff = t2 * t3 */ + sp_256_mont_mul_order_10(t, t2, t3); + /* t3= a^ff00 = t ^ 2 ^ 8 */ + sp_256_mont_sqr_n_order_10(t2, t, 8); + /* t = a^ffff = t2 * t */ + sp_256_mont_mul_order_10(t, t2, t); + /* t2= a^ffff0000 = t ^ 2 ^ 16 */ + sp_256_mont_sqr_n_order_10(t2, t, 16); + /* t = a^ffffffff = t2 * t */ + sp_256_mont_mul_order_10(t, t2, t); + /* t2= a^ffffffff0000000000000000 = t ^ 2 ^ 64 */ + sp_256_mont_sqr_n_order_10(t2, t, 64); + /* t2= a^ffffffff00000000ffffffff = t2 * t */ + sp_256_mont_mul_order_10(t2, t2, t); + /* t2= a^ffffffff00000000ffffffff00000000 = t2 ^ 2 ^ 32 */ + sp_256_mont_sqr_n_order_10(t2, t2, 32); + /* t2= a^ffffffff00000000ffffffffffffffff = t2 * t */ + sp_256_mont_mul_order_10(t2, t2, t); + /* t2= a^ffffffff00000000ffffffffffffffffbce6 */ + for (i=127; i>=112; i--) { + sp_256_mont_sqr_order_10(t2, t2); + if (p256_order_low[i / 32] & ((sp_digit)1 << (i % 32))) + sp_256_mont_mul_order_10(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6f */ + sp_256_mont_sqr_n_order_10(t2, t2, 4); + sp_256_mont_mul_order_10(t2, t2, t3); + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84 */ + for (i=107; i>=64; i--) { + sp_256_mont_sqr_order_10(t2, t2); + if (p256_order_low[i / 32] & ((sp_digit)1 << (i % 32))) + sp_256_mont_mul_order_10(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f */ + sp_256_mont_sqr_n_order_10(t2, t2, 4); + sp_256_mont_mul_order_10(t2, t2, t3); + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2 */ + for (i=59; i>=32; i--) { + sp_256_mont_sqr_order_10(t2, t2); + if (p256_order_low[i / 32] & ((sp_digit)1 << (i % 32))) + sp_256_mont_mul_order_10(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2f */ + sp_256_mont_sqr_n_order_10(t2, t2, 4); + sp_256_mont_mul_order_10(t2, t2, t3); + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254 */ + for (i=27; i>=0; i--) { + sp_256_mont_sqr_order_10(t2, t2); + if (p256_order_low[i / 32] & ((sp_digit)1 << (i % 32))) + sp_256_mont_mul_order_10(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632540 */ + sp_256_mont_sqr_n_order_10(t2, t2, 4); + /* r = a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f */ + sp_256_mont_mul_order_10(r, t2, t3); +#endif /* WOLFSSL_SP_SMALL */ +} + +#endif /* HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +#ifdef HAVE_ECC_SIGN +#ifndef SP_ECC_MAX_SIG_GEN +#define SP_ECC_MAX_SIG_GEN 64 +#endif + +/* Sign the hash using the private key. + * e = [hash, 256 bits] from binary + * r = (k.G)->x mod order + * s = (r * x + e) / k mod order + * The hash is truncated to the first 256 bits. + * + * hash Hash to sign. + * hashLen Length of the hash data. + * rng Random number generator. + * priv Private part of key - scalar. + * rm First part of result as an mp_int. + * sm Sirst part of result as an mp_int. + * heap Heap to use for allocation. + * returns RNG failures, MEMORY_E when memory allocation fails and + * MP_OKAY on success. + */ +int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, + mp_int* rm, mp_int* sm, void* heap) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d = NULL; +#else + sp_digit ed[2*10]; + sp_digit xd[2*10]; + sp_digit kd[2*10]; + sp_digit rd[2*10]; + sp_digit td[3 * 2*10]; + sp_point p; +#endif + sp_digit* e = NULL; + sp_digit* x = NULL; + sp_digit* k = NULL; + sp_digit* r = NULL; + sp_digit* tmp = NULL; + sp_point* point = NULL; + sp_digit carry; + sp_digit* s; + sp_digit* kInv; + int err = MP_OKAY; + int32_t c; + int i; + + (void)heap; + + err = sp_ecc_point_new(heap, p, point); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 10, heap, + DYNAMIC_TYPE_ECC); + if (d != NULL) { + e = d + 0 * 10; + x = d + 2 * 10; + k = d + 4 * 10; + r = d + 6 * 10; + tmp = d + 8 * 10; + } + else + err = MEMORY_E; + } +#else + e = ed; + x = xd; + k = kd; + r = rd; + tmp = td; +#endif + s = e; + kInv = k; + + if (err == MP_OKAY) { + if (hashLen > 32) + hashLen = 32; + + sp_256_from_bin(e, 10, hash, hashLen); + } + + for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { + sp_256_from_mp(x, 10, priv); + + /* New random point. */ + err = sp_256_ecc_gen_k_10(rng, k); + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_base_10(point, k, 1, NULL); + } + + if (err == MP_OKAY) { + /* r = point->x mod order */ + XMEMCPY(r, point->x, sizeof(sp_digit) * 10); + sp_256_norm_10(r); + c = sp_256_cmp_10(r, p256_order); + sp_256_cond_sub_10(r, r, p256_order, 0 - (c >= 0)); + sp_256_norm_10(r); + + /* Conv k to Montgomery form (mod order) */ + sp_256_mul_10(k, k, p256_norm_order); + err = sp_256_mod_10(k, k, p256_order); + } + if (err == MP_OKAY) { + sp_256_norm_10(k); + /* kInv = 1/k mod order */ + sp_256_mont_inv_order_10(kInv, k, tmp); + sp_256_norm_10(kInv); + + /* s = r * x + e */ + sp_256_mul_10(x, x, r); + err = sp_256_mod_10(x, x, p256_order); + } + if (err == MP_OKAY) { + sp_256_norm_10(x); + carry = sp_256_add_10(s, e, x); + sp_256_cond_sub_10(s, s, p256_order, 0 - carry); + sp_256_norm_10(s); + c = sp_256_cmp_10(s, p256_order); + sp_256_cond_sub_10(s, s, p256_order, 0 - (c >= 0)); + sp_256_norm_10(s); + + /* s = s * k^-1 mod order */ + sp_256_mont_mul_order_10(s, s, kInv); + sp_256_norm_10(s); + + /* Check that signature is usable. */ + if (!sp_256_iszero_10(s)) + break; + } + } + + if (i == 0) + err = RNG_FAILURE_E; + + if (err == MP_OKAY) + err = sp_256_to_mp(r, rm); + if (err == MP_OKAY) + err = sp_256_to_mp(s, sm); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) { + XMEMSET(d, 0, sizeof(sp_digit) * 8 * 10); + XFREE(d, heap, DYNAMIC_TYPE_ECC); + } +#else + XMEMSET(e, 0, sizeof(sp_digit) * 2 * 10); + XMEMSET(x, 0, sizeof(sp_digit) * 2 * 10); + XMEMSET(k, 0, sizeof(sp_digit) * 2 * 10); + XMEMSET(r, 0, sizeof(sp_digit) * 2 * 10); + XMEMSET(r, 0, sizeof(sp_digit) * 2 * 10); + XMEMSET(tmp, 0, sizeof(sp_digit) * 3 * 2*10); +#endif + sp_ecc_point_free(point, 1, heap); + + return err; +} +#endif /* HAVE_ECC_SIGN */ + +#ifdef HAVE_ECC_VERIFY +/* Verify the signature values with the hash and public key. + * e = Truncate(hash, 256) + * u1 = e/s mod order + * u2 = r/s mod order + * r == (u1.G + u2.Q)->x mod order + * Optimization: Leave point in projective form. + * (x, y, 1) == (x' / z'*z', y' / z'*z'*z', z' / z') + * (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' + * The hash is truncated to the first 256 bits. + * + * hash Hash to sign. + * hashLen Length of the hash data. + * rng Random number generator. + * priv Private part of key - scalar. + * rm First part of result as an mp_int. + * sm Sirst part of result as an mp_int. + * heap Heap to use for allocation. + * returns RNG failures, MEMORY_E when memory allocation fails and + * MP_OKAY on success. + */ +int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, + mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d = NULL; +#else + sp_digit u1d[2*10]; + sp_digit u2d[2*10]; + sp_digit sd[2*10]; + sp_digit tmpd[2*10 * 5]; + sp_point p1d; + sp_point p2d; +#endif + sp_digit* u1; + sp_digit* u2; + sp_digit* s; + sp_digit* tmp; + sp_point* p1; + sp_point* p2 = NULL; + sp_digit carry; + int32_t c; + int err; + + err = sp_ecc_point_new(heap, p1d, p1); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, p2d, p2); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 10, heap, + DYNAMIC_TYPE_ECC); + if (d != NULL) { + u1 = d + 0 * 10; + u2 = d + 2 * 10; + s = d + 4 * 10; + tmp = d + 6 * 10; + } + else + err = MEMORY_E; + } +#else + u1 = u1d; + u2 = u2d; + s = sd; + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + if (hashLen > 32) + hashLen = 32; + + sp_256_from_bin(u1, 10, hash, hashLen); + sp_256_from_mp(u2, 10, r); + sp_256_from_mp(s, 10, sm); + sp_256_from_mp(p2->x, 10, pX); + sp_256_from_mp(p2->y, 10, pY); + sp_256_from_mp(p2->z, 10, pZ); + + sp_256_mul_10(s, s, p256_norm_order); + err = sp_256_mod_10(s, s, p256_order); + } + if (err == MP_OKAY) { + sp_256_norm_10(s); + { + sp_256_mont_inv_order_10(s, s, tmp); + sp_256_mont_mul_order_10(u1, u1, s); + sp_256_mont_mul_order_10(u2, u2, s); + } + + err = sp_256_ecc_mulmod_base_10(p1, u1, 0, heap); + } + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_10(p2, p2, u2, 0, heap); + } + + if (err == MP_OKAY) { + sp_256_proj_point_add_10(p1, p1, p2, tmp); + + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_256_from_mp(u2, 10, r); + err = sp_256_mod_mul_norm_10(u2, u2, p256_mod); + } + + if (err == MP_OKAY) { + /* u1 = r.z'.z' mod prime */ + sp_256_mont_sqr_10(p1->z, p1->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_10(u1, u2, p1->z, p256_mod, p256_mp_mod); + *res = sp_256_cmp_10(p1->x, u1) == 0; + if (*res == 0) { + /* Reload r and add order. */ + sp_256_from_mp(u2, 10, r); + carry = sp_256_add_10(u2, u2, p256_order); + /* Carry means result is greater than mod and is not valid. */ + if (!carry) { + sp_256_norm_10(u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_256_cmp_10(u2, p256_mod); + if (c < 0) { + /* Convert to Montogomery form */ + err = sp_256_mod_mul_norm_10(u2, u2, p256_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_256_mont_mul_10(u1, u2, p1->z, p256_mod, + p256_mp_mod); + *res = sp_256_cmp_10(p1->x, u2) == 0; + } + } + } + } + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p1, 0, heap); + sp_ecc_point_free(p2, 0, heap); + + return err; +} +#endif /* HAVE_ECC_VERIFY */ + +#ifdef HAVE_ECC_CHECK_KEY +/* Check that the x and y oridinates are a valid point on the curve. + * + * point EC point. + * heap Heap to use if dynamically allocating. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +static int sp_256_ecc_is_point_10(sp_point* point, void* heap) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d = NULL; +#else + sp_digit t1d[2*10]; + sp_digit t2d[2*10]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 10 * 4, heap, + DYNAMIC_TYPE_ECC); + if (d != NULL) { + t1 = d + 0 * 10; + t2 = d + 2 * 10; + } + else + err = MEMORY_E; +#else + (void)heap; + + t1 = t1d; + t2 = t2d; +#endif + + if (err == MP_OKAY) { + sp_256_sqr_10(t1, point->y); + sp_256_mod_10(t1, t1, p256_mod); + sp_256_sqr_10(t2, point->x); + sp_256_mod_10(t2, t2, p256_mod); + sp_256_mul_10(t2, t2, point->x); + sp_256_mod_10(t2, t2, p256_mod); + sp_256_sub_10(t2, p256_mod, t2); + sp_256_mont_add_10(t1, t1, t2, p256_mod); + + sp_256_mont_add_10(t1, t1, point->x, p256_mod); + sp_256_mont_add_10(t1, t1, point->x, p256_mod); + sp_256_mont_add_10(t1, t1, point->x, p256_mod); + + if (sp_256_cmp_10(t1, p256_b) != 0) + err = MP_VAL; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Check that the x and y oridinates are a valid point on the curve. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +int sp_ecc_is_point_256(mp_int* pX, mp_int* pY) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point pubd; +#endif + sp_point* pub; + byte one[1] = { 1 }; + int err; + + err = sp_ecc_point_new(NULL, pubd, pub); + if (err == MP_OKAY) { + sp_256_from_mp(pub->x, 10, pX); + sp_256_from_mp(pub->y, 10, pY); + sp_256_from_bin(pub->z, 10, one, sizeof(one)); + + err = sp_256_ecc_is_point_10(pub, NULL); + } + + sp_ecc_point_free(pub, 0, NULL); + + return err; +} + +/* Check that the private scalar generates the EC point (px, py), the point is + * on the curve and the point has the correct order. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * privm Private scalar that generates EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve, ECC_INF_E if the point does not have the correct order, + * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and + * MP_OKAY otherwise. + */ +int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit privd[10]; + sp_point pubd; + sp_point pd; +#endif + sp_digit* priv = NULL; + sp_point* pub; + sp_point* p = NULL; + byte one[1] = { 1 }; + int err; + + err = sp_ecc_point_new(heap, pubd, pub); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 10, heap, + DYNAMIC_TYPE_ECC); + if (priv == NULL) + err = MEMORY_E; + } +#else + priv = privd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(pub->x, 10, pX); + sp_256_from_mp(pub->y, 10, pY); + sp_256_from_bin(pub->z, 10, one, sizeof(one)); + sp_256_from_mp(priv, 10, privm); + + /* Check point at infinitiy. */ + if (sp_256_iszero_10(pub->x) && + sp_256_iszero_10(pub->y)) + err = ECC_INF_E; + } + + if (err == MP_OKAY) { + /* Check range of X and Y */ + if (sp_256_cmp_10(pub->x, p256_mod) >= 0 || + sp_256_cmp_10(pub->y, p256_mod) >= 0) + err = ECC_OUT_OF_RANGE_E; + } + + if (err == MP_OKAY) { + /* Check point is on curve */ + err = sp_256_ecc_is_point_10(pub, heap); + } + + if (err == MP_OKAY) { + /* Point * order = infinity */ + err = sp_256_ecc_mulmod_10(p, pub, p256_order, 1, heap); + } + if (err == MP_OKAY) { + /* Check result is infinity */ + if (!sp_256_iszero_10(p->x) || + !sp_256_iszero_10(p->y)) { + err = ECC_INF_E; + } + } + + if (err == MP_OKAY) { + /* Base * private = point */ + err = sp_256_ecc_mulmod_base_10(p, priv, 1, heap); + } + if (err == MP_OKAY) { + /* Check result is public key */ + if (sp_256_cmp_10(p->x, pub->x) != 0 || + sp_256_cmp_10(p->y, pub->y) != 0) { + err = ECC_PRIV_KEY_E; + } + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (priv != NULL) + XFREE(priv, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p, 0, heap); + sp_ecc_point_free(pub, 0, heap); + + return err; +} +#endif +#ifdef WOLFSSL_PUBLIC_ECC_ADD_DBL +/* Add two projective EC points together. + * (pX, pY, pZ) + (qX, qY, qZ) = (rX, rY, rZ) + * + * pX First EC point's X ordinate. + * pY First EC point's Y ordinate. + * pZ First EC point's Z ordinate. + * qX Second EC point's X ordinate. + * qY Second EC point's Y ordinate. + * qZ Second EC point's Z ordinate. + * rX Resultant EC point's X ordinate. + * rY Resultant EC point's Y ordinate. + * rZ Resultant EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* qX, mp_int* qY, mp_int* qZ, + mp_int* rX, mp_int* rY, mp_int* rZ) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit tmpd[2 * 10 * 5]; + sp_point pd; + sp_point qd; +#endif + sp_digit* tmp; + sp_point* p; + sp_point* q = NULL; + int err; + + err = sp_ecc_point_new(NULL, pd, p); + if (err == MP_OKAY) + err = sp_ecc_point_new(NULL, qd, q); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 10 * 5, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } +#else + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 10, pX); + sp_256_from_mp(p->y, 10, pY); + sp_256_from_mp(p->z, 10, pZ); + sp_256_from_mp(q->x, 10, qX); + sp_256_from_mp(q->y, 10, qY); + sp_256_from_mp(q->z, 10, qZ); + + sp_256_proj_point_add_10(p, p, q, tmp); + } + + if (err == MP_OKAY) + err = sp_256_to_mp(p->x, rX); + if (err == MP_OKAY) + err = sp_256_to_mp(p->y, rY); + if (err == MP_OKAY) + err = sp_256_to_mp(p->z, rZ); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (tmp != NULL) + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(q, 0, NULL); + sp_ecc_point_free(p, 0, NULL); + + return err; +} + +/* Double a projective EC point. + * (pX, pY, pZ) + (pX, pY, pZ) = (rX, rY, rZ) + * + * pX EC point's X ordinate. + * pY EC point's Y ordinate. + * pZ EC point's Z ordinate. + * rX Resultant EC point's X ordinate. + * rY Resultant EC point's Y ordinate. + * rZ Resultant EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* rX, mp_int* rY, mp_int* rZ) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit tmpd[2 * 10 * 2]; + sp_point pd; +#endif + sp_digit* tmp; + sp_point* p; + int err; + + err = sp_ecc_point_new(NULL, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 10 * 2, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } +#else + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 10, pX); + sp_256_from_mp(p->y, 10, pY); + sp_256_from_mp(p->z, 10, pZ); + + sp_256_proj_point_dbl_10(p, p, tmp); + } + + if (err == MP_OKAY) + err = sp_256_to_mp(p->x, rX); + if (err == MP_OKAY) + err = sp_256_to_mp(p->y, rY); + if (err == MP_OKAY) + err = sp_256_to_mp(p->z, rZ); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (tmp != NULL) + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p, 0, NULL); + + return err; +} + +/* Map a projective EC point to affine in place. + * pZ will be one. + * + * pX EC point's X ordinate. + * pY EC point's Y ordinate. + * pZ EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit tmpd[2 * 10 * 4]; + sp_point pd; +#endif + sp_digit* tmp; + sp_point* p; + int err; + + err = sp_ecc_point_new(NULL, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 10 * 4, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } +#else + tmp = tmpd; +#endif + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 10, pX); + sp_256_from_mp(p->y, 10, pY); + sp_256_from_mp(p->z, 10, pZ); + + sp_256_map_10(p, p, tmp); + } + + if (err == MP_OKAY) + err = sp_256_to_mp(p->x, pX); + if (err == MP_OKAY) + err = sp_256_to_mp(p->y, pY); + if (err == MP_OKAY) + err = sp_256_to_mp(p->z, pZ); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (tmp != NULL) + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p, 0, NULL); + + return err; +} +#endif /* WOLFSSL_PUBLIC_ECC_ADD_DBL */ +#ifdef HAVE_COMP_KEY +/* Find the square root of a number mod the prime of the curve. + * + * y The number to operate on and the result. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +static int sp_256_mont_sqrt_10(sp_digit* y) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d; +#else + sp_digit t1d[2 * 10]; + sp_digit t2d[2 * 10]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 10, NULL, DYNAMIC_TYPE_ECC); + if (d != NULL) { + t1 = d + 0 * 10; + t2 = d + 2 * 10; + } + else + err = MEMORY_E; +#else + t1 = t1d; + t2 = t2d; +#endif + + if (err == MP_OKAY) { + { + /* t2 = y ^ 0x2 */ + sp_256_mont_sqr_10(t2, y, p256_mod, p256_mp_mod); + /* t1 = y ^ 0x3 */ + sp_256_mont_mul_10(t1, t2, y, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xc */ + sp_256_mont_sqr_n_10(t2, t1, 2, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xf */ + sp_256_mont_mul_10(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xf0 */ + sp_256_mont_sqr_n_10(t2, t1, 4, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xff */ + sp_256_mont_mul_10(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xff00 */ + sp_256_mont_sqr_n_10(t2, t1, 8, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffff */ + sp_256_mont_mul_10(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xffff0000 */ + sp_256_mont_sqr_n_10(t2, t1, 16, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff */ + sp_256_mont_mul_10(t1, t1, t2, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000000 */ + sp_256_mont_sqr_n_10(t1, t1, 32, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001 */ + sp_256_mont_mul_10(t1, t1, y, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001000000000000000000000000 */ + sp_256_mont_sqr_n_10(t1, t1, 96, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001000000000000000000000001 */ + sp_256_mont_mul_10(t1, t1, y, p256_mod, p256_mp_mod); + sp_256_mont_sqr_n_10(y, t1, 94, p256_mod, p256_mp_mod); + } + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Uncompress the point given the X ordinate. + * + * xm X ordinate. + * odd Whether the Y ordinate is odd. + * ym Calculated Y ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d; +#else + sp_digit xd[2 * 10]; + sp_digit yd[2 * 10]; +#endif + sp_digit* x; + sp_digit* y; + int err = MP_OKAY; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 10, NULL, DYNAMIC_TYPE_ECC); + if (d != NULL) { + x = d + 0 * 10; + y = d + 2 * 10; + } + else + err = MEMORY_E; +#else + x = xd; + y = yd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(x, 10, xm); + + err = sp_256_mod_mul_norm_10(x, x, p256_mod); + } + + if (err == MP_OKAY) { + /* y = x^3 */ + { + sp_256_mont_sqr_10(y, x, p256_mod, p256_mp_mod); + sp_256_mont_mul_10(y, y, x, p256_mod, p256_mp_mod); + } + /* y = x^3 - 3x */ + sp_256_mont_sub_10(y, y, x, p256_mod); + sp_256_mont_sub_10(y, y, x, p256_mod); + sp_256_mont_sub_10(y, y, x, p256_mod); + /* y = x^3 - 3x + b */ + err = sp_256_mod_mul_norm_10(x, p256_b, p256_mod); + } + if (err == MP_OKAY) { + sp_256_mont_add_10(y, y, x, p256_mod); + /* y = sqrt(x^3 - 3x + b) */ + err = sp_256_mont_sqrt_10(y); + } + if (err == MP_OKAY) { + XMEMSET(y + 10, 0, 10 * sizeof(sp_digit)); + sp_256_mont_reduce_10(y, p256_mod, p256_mp_mod); + if (((y[0] ^ odd) & 1) != 0) + sp_256_mont_sub_10(y, p256_mod, y, p256_mod); + + err = sp_256_to_mp(y, ym); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_ECC); +#endif + + return err; +} +#endif +#endif /* !WOLFSSL_SP_NO_256 */ +#endif /* WOLFSSL_HAVE_SP_ECC */ +#endif /* SP_WORD_SIZE == 32 */ +#endif /* !WOLFSSL_SP_ASM */ +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH || WOLFSSL_HAVE_SP_ECC */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/sp_c64.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/sp_c64.c new file mode 100755 index 0000000..801a7c0 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/sp_c64.c @@ -0,0 +1,12222 @@ +/* sp.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/* Implementation by Sean Parkinson. */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include +#include +#include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) || \ + defined(WOLFSSL_HAVE_SP_ECC) + +#ifdef RSA_LOW_MEM +#ifndef SP_RSA_PRIVATE_EXP_D +#define SP_RSA_PRIVATE_EXP_D +#endif + +#ifndef WOLFSSL_SP_SMALL +#define WOLFSSL_SP_SMALL +#endif +#endif + +#include + +#ifndef WOLFSSL_SP_ASM +#if SP_WORD_SIZE == 64 +#if (defined(WOLFSSL_SP_CACHE_RESISTANT) || defined(WOLFSSL_SP_SMALL)) && (defined(WOLFSSL_HAVE_SP_ECC) || !defined(WOLFSSL_RSA_PUBLIC_ONLY)) +/* Mask for address to obfuscate which of the two address will be used. */ +static const size_t addr_mask[2] = { 0, (size_t)-1 }; +#endif + +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) +#ifndef WOLFSSL_SP_NO_2048 +/* Read big endian unsigned byte aray into r. + * + * r A single precision integer. + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_2048_from_bin(sp_digit* r, int max, const byte* a, int n) +{ + int i, j = 0, s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= ((sp_digit)a[i]) << s; + if (s >= 49) { + r[j] &= 0x1ffffffffffffffl; + s = 57 - s; + if (j + 1 >= max) + break; + r[++j] = a[i] >> s; + s = 8 - s; + } + else + s += 8; + } + + for (j++; j < max; j++) + r[j] = 0; +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * a A multi-precision integer. + */ +static void sp_2048_from_mp(sp_digit* r, int max, mp_int* a) +{ +#if DIGIT_BIT == 57 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < max; j++) + r[j] = 0; +#elif DIGIT_BIT > 57 + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= a->dp[i] << s; + r[j] &= 0x1ffffffffffffffl; + s = 57 - s; + if (j + 1 >= max) + break; + r[++j] = (sp_digit)(a->dp[i] >> s); + while (s + 57 <= DIGIT_BIT) { + s += 57; + r[j] &= 0x1ffffffffffffffl; + if (j + 1 >= max) + break; + if (s < DIGIT_BIT) + r[++j] = (sp_digit)(a->dp[i] >> s); + else + r[++j] = 0; + } + s = DIGIT_BIT - s; + } + + for (j++; j < max; j++) + r[j] = 0; +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 57) { + r[j] &= 0x1ffffffffffffffl; + if (j + 1 >= max) + break; + s = 57 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else + s += DIGIT_BIT; + } + + for (j++; j < max; j++) + r[j] = 0; +#endif +} + +/* Write r as big endian to byte aray. + * Fixed length number of bytes written: 256 + * + * r A single precision integer. + * a Byte array. + */ +static void sp_2048_to_bin(sp_digit* r, byte* a) +{ + int i, j, s = 0, b; + + for (i=0; i<35; i++) { + r[i+1] += r[i] >> 57; + r[i] &= 0x1ffffffffffffffl; + } + j = 2048 / 8 - 1; + a[j] = 0; + for (i=0; i<36 && j>=0; i++) { + b = 0; + a[j--] |= r[i] << s; b += 8 - s; + if (j < 0) + break; + while (b < 57) { + a[j--] = r[i] >> b; b += 8; + if (j < 0) + break; + } + s = 8 - (b - 57); + if (j >= 0) + a[j] = 0; + if (s != 0) + j++; + } +} + +#ifndef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_2048_mul_9(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int128_t t0 = ((int128_t)a[ 0]) * b[ 0]; + int128_t t1 = ((int128_t)a[ 0]) * b[ 1] + + ((int128_t)a[ 1]) * b[ 0]; + int128_t t2 = ((int128_t)a[ 0]) * b[ 2] + + ((int128_t)a[ 1]) * b[ 1] + + ((int128_t)a[ 2]) * b[ 0]; + int128_t t3 = ((int128_t)a[ 0]) * b[ 3] + + ((int128_t)a[ 1]) * b[ 2] + + ((int128_t)a[ 2]) * b[ 1] + + ((int128_t)a[ 3]) * b[ 0]; + int128_t t4 = ((int128_t)a[ 0]) * b[ 4] + + ((int128_t)a[ 1]) * b[ 3] + + ((int128_t)a[ 2]) * b[ 2] + + ((int128_t)a[ 3]) * b[ 1] + + ((int128_t)a[ 4]) * b[ 0]; + int128_t t5 = ((int128_t)a[ 0]) * b[ 5] + + ((int128_t)a[ 1]) * b[ 4] + + ((int128_t)a[ 2]) * b[ 3] + + ((int128_t)a[ 3]) * b[ 2] + + ((int128_t)a[ 4]) * b[ 1] + + ((int128_t)a[ 5]) * b[ 0]; + int128_t t6 = ((int128_t)a[ 0]) * b[ 6] + + ((int128_t)a[ 1]) * b[ 5] + + ((int128_t)a[ 2]) * b[ 4] + + ((int128_t)a[ 3]) * b[ 3] + + ((int128_t)a[ 4]) * b[ 2] + + ((int128_t)a[ 5]) * b[ 1] + + ((int128_t)a[ 6]) * b[ 0]; + int128_t t7 = ((int128_t)a[ 0]) * b[ 7] + + ((int128_t)a[ 1]) * b[ 6] + + ((int128_t)a[ 2]) * b[ 5] + + ((int128_t)a[ 3]) * b[ 4] + + ((int128_t)a[ 4]) * b[ 3] + + ((int128_t)a[ 5]) * b[ 2] + + ((int128_t)a[ 6]) * b[ 1] + + ((int128_t)a[ 7]) * b[ 0]; + int128_t t8 = ((int128_t)a[ 0]) * b[ 8] + + ((int128_t)a[ 1]) * b[ 7] + + ((int128_t)a[ 2]) * b[ 6] + + ((int128_t)a[ 3]) * b[ 5] + + ((int128_t)a[ 4]) * b[ 4] + + ((int128_t)a[ 5]) * b[ 3] + + ((int128_t)a[ 6]) * b[ 2] + + ((int128_t)a[ 7]) * b[ 1] + + ((int128_t)a[ 8]) * b[ 0]; + int128_t t9 = ((int128_t)a[ 1]) * b[ 8] + + ((int128_t)a[ 2]) * b[ 7] + + ((int128_t)a[ 3]) * b[ 6] + + ((int128_t)a[ 4]) * b[ 5] + + ((int128_t)a[ 5]) * b[ 4] + + ((int128_t)a[ 6]) * b[ 3] + + ((int128_t)a[ 7]) * b[ 2] + + ((int128_t)a[ 8]) * b[ 1]; + int128_t t10 = ((int128_t)a[ 2]) * b[ 8] + + ((int128_t)a[ 3]) * b[ 7] + + ((int128_t)a[ 4]) * b[ 6] + + ((int128_t)a[ 5]) * b[ 5] + + ((int128_t)a[ 6]) * b[ 4] + + ((int128_t)a[ 7]) * b[ 3] + + ((int128_t)a[ 8]) * b[ 2]; + int128_t t11 = ((int128_t)a[ 3]) * b[ 8] + + ((int128_t)a[ 4]) * b[ 7] + + ((int128_t)a[ 5]) * b[ 6] + + ((int128_t)a[ 6]) * b[ 5] + + ((int128_t)a[ 7]) * b[ 4] + + ((int128_t)a[ 8]) * b[ 3]; + int128_t t12 = ((int128_t)a[ 4]) * b[ 8] + + ((int128_t)a[ 5]) * b[ 7] + + ((int128_t)a[ 6]) * b[ 6] + + ((int128_t)a[ 7]) * b[ 5] + + ((int128_t)a[ 8]) * b[ 4]; + int128_t t13 = ((int128_t)a[ 5]) * b[ 8] + + ((int128_t)a[ 6]) * b[ 7] + + ((int128_t)a[ 7]) * b[ 6] + + ((int128_t)a[ 8]) * b[ 5]; + int128_t t14 = ((int128_t)a[ 6]) * b[ 8] + + ((int128_t)a[ 7]) * b[ 7] + + ((int128_t)a[ 8]) * b[ 6]; + int128_t t15 = ((int128_t)a[ 7]) * b[ 8] + + ((int128_t)a[ 8]) * b[ 7]; + int128_t t16 = ((int128_t)a[ 8]) * b[ 8]; + + t1 += t0 >> 57; r[ 0] = t0 & 0x1ffffffffffffffl; + t2 += t1 >> 57; r[ 1] = t1 & 0x1ffffffffffffffl; + t3 += t2 >> 57; r[ 2] = t2 & 0x1ffffffffffffffl; + t4 += t3 >> 57; r[ 3] = t3 & 0x1ffffffffffffffl; + t5 += t4 >> 57; r[ 4] = t4 & 0x1ffffffffffffffl; + t6 += t5 >> 57; r[ 5] = t5 & 0x1ffffffffffffffl; + t7 += t6 >> 57; r[ 6] = t6 & 0x1ffffffffffffffl; + t8 += t7 >> 57; r[ 7] = t7 & 0x1ffffffffffffffl; + t9 += t8 >> 57; r[ 8] = t8 & 0x1ffffffffffffffl; + t10 += t9 >> 57; r[ 9] = t9 & 0x1ffffffffffffffl; + t11 += t10 >> 57; r[10] = t10 & 0x1ffffffffffffffl; + t12 += t11 >> 57; r[11] = t11 & 0x1ffffffffffffffl; + t13 += t12 >> 57; r[12] = t12 & 0x1ffffffffffffffl; + t14 += t13 >> 57; r[13] = t13 & 0x1ffffffffffffffl; + t15 += t14 >> 57; r[14] = t14 & 0x1ffffffffffffffl; + t16 += t15 >> 57; r[15] = t15 & 0x1ffffffffffffffl; + r[17] = (sp_digit)(t16 >> 57); + r[16] = t16 & 0x1ffffffffffffffl; +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_2048_sqr_9(sp_digit* r, const sp_digit* a) +{ + int128_t t0 = ((int128_t)a[ 0]) * a[ 0]; + int128_t t1 = (((int128_t)a[ 0]) * a[ 1]) * 2; + int128_t t2 = (((int128_t)a[ 0]) * a[ 2]) * 2 + + ((int128_t)a[ 1]) * a[ 1]; + int128_t t3 = (((int128_t)a[ 0]) * a[ 3] + + ((int128_t)a[ 1]) * a[ 2]) * 2; + int128_t t4 = (((int128_t)a[ 0]) * a[ 4] + + ((int128_t)a[ 1]) * a[ 3]) * 2 + + ((int128_t)a[ 2]) * a[ 2]; + int128_t t5 = (((int128_t)a[ 0]) * a[ 5] + + ((int128_t)a[ 1]) * a[ 4] + + ((int128_t)a[ 2]) * a[ 3]) * 2; + int128_t t6 = (((int128_t)a[ 0]) * a[ 6] + + ((int128_t)a[ 1]) * a[ 5] + + ((int128_t)a[ 2]) * a[ 4]) * 2 + + ((int128_t)a[ 3]) * a[ 3]; + int128_t t7 = (((int128_t)a[ 0]) * a[ 7] + + ((int128_t)a[ 1]) * a[ 6] + + ((int128_t)a[ 2]) * a[ 5] + + ((int128_t)a[ 3]) * a[ 4]) * 2; + int128_t t8 = (((int128_t)a[ 0]) * a[ 8] + + ((int128_t)a[ 1]) * a[ 7] + + ((int128_t)a[ 2]) * a[ 6] + + ((int128_t)a[ 3]) * a[ 5]) * 2 + + ((int128_t)a[ 4]) * a[ 4]; + int128_t t9 = (((int128_t)a[ 1]) * a[ 8] + + ((int128_t)a[ 2]) * a[ 7] + + ((int128_t)a[ 3]) * a[ 6] + + ((int128_t)a[ 4]) * a[ 5]) * 2; + int128_t t10 = (((int128_t)a[ 2]) * a[ 8] + + ((int128_t)a[ 3]) * a[ 7] + + ((int128_t)a[ 4]) * a[ 6]) * 2 + + ((int128_t)a[ 5]) * a[ 5]; + int128_t t11 = (((int128_t)a[ 3]) * a[ 8] + + ((int128_t)a[ 4]) * a[ 7] + + ((int128_t)a[ 5]) * a[ 6]) * 2; + int128_t t12 = (((int128_t)a[ 4]) * a[ 8] + + ((int128_t)a[ 5]) * a[ 7]) * 2 + + ((int128_t)a[ 6]) * a[ 6]; + int128_t t13 = (((int128_t)a[ 5]) * a[ 8] + + ((int128_t)a[ 6]) * a[ 7]) * 2; + int128_t t14 = (((int128_t)a[ 6]) * a[ 8]) * 2 + + ((int128_t)a[ 7]) * a[ 7]; + int128_t t15 = (((int128_t)a[ 7]) * a[ 8]) * 2; + int128_t t16 = ((int128_t)a[ 8]) * a[ 8]; + + t1 += t0 >> 57; r[ 0] = t0 & 0x1ffffffffffffffl; + t2 += t1 >> 57; r[ 1] = t1 & 0x1ffffffffffffffl; + t3 += t2 >> 57; r[ 2] = t2 & 0x1ffffffffffffffl; + t4 += t3 >> 57; r[ 3] = t3 & 0x1ffffffffffffffl; + t5 += t4 >> 57; r[ 4] = t4 & 0x1ffffffffffffffl; + t6 += t5 >> 57; r[ 5] = t5 & 0x1ffffffffffffffl; + t7 += t6 >> 57; r[ 6] = t6 & 0x1ffffffffffffffl; + t8 += t7 >> 57; r[ 7] = t7 & 0x1ffffffffffffffl; + t9 += t8 >> 57; r[ 8] = t8 & 0x1ffffffffffffffl; + t10 += t9 >> 57; r[ 9] = t9 & 0x1ffffffffffffffl; + t11 += t10 >> 57; r[10] = t10 & 0x1ffffffffffffffl; + t12 += t11 >> 57; r[11] = t11 & 0x1ffffffffffffffl; + t13 += t12 >> 57; r[12] = t12 & 0x1ffffffffffffffl; + t14 += t13 >> 57; r[13] = t13 & 0x1ffffffffffffffl; + t15 += t14 >> 57; r[14] = t14 & 0x1ffffffffffffffl; + t16 += t15 >> 57; r[15] = t15 & 0x1ffffffffffffffl; + r[17] = (sp_digit)(t16 >> 57); + r[16] = t16 & 0x1ffffffffffffffl; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_2048_add_9(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + r[ 0] = a[ 0] + b[ 0]; + r[ 1] = a[ 1] + b[ 1]; + r[ 2] = a[ 2] + b[ 2]; + r[ 3] = a[ 3] + b[ 3]; + r[ 4] = a[ 4] + b[ 4]; + r[ 5] = a[ 5] + b[ 5]; + r[ 6] = a[ 6] + b[ 6]; + r[ 7] = a[ 7] + b[ 7]; + r[ 8] = a[ 8] + b[ 8]; + + return 0; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_2048_add_18(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 16; i += 8) { + r[i + 0] = a[i + 0] + b[i + 0]; + r[i + 1] = a[i + 1] + b[i + 1]; + r[i + 2] = a[i + 2] + b[i + 2]; + r[i + 3] = a[i + 3] + b[i + 3]; + r[i + 4] = a[i + 4] + b[i + 4]; + r[i + 5] = a[i + 5] + b[i + 5]; + r[i + 6] = a[i + 6] + b[i + 6]; + r[i + 7] = a[i + 7] + b[i + 7]; + } + r[16] = a[16] + b[16]; + r[17] = a[17] + b[17]; + + return 0; +} + +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_2048_sub_18(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 16; i += 8) { + r[i + 0] = a[i + 0] - b[i + 0]; + r[i + 1] = a[i + 1] - b[i + 1]; + r[i + 2] = a[i + 2] - b[i + 2]; + r[i + 3] = a[i + 3] - b[i + 3]; + r[i + 4] = a[i + 4] - b[i + 4]; + r[i + 5] = a[i + 5] - b[i + 5]; + r[i + 6] = a[i + 6] - b[i + 6]; + r[i + 7] = a[i + 7] - b[i + 7]; + } + r[16] = a[16] - b[16]; + r[17] = a[17] - b[17]; + + return 0; +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_2048_mul_18(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[18]; + sp_digit* a1 = z1; + sp_digit b1[9]; + sp_digit* z2 = r + 18; + sp_2048_add_9(a1, a, &a[9]); + sp_2048_add_9(b1, b, &b[9]); + sp_2048_mul_9(z2, &a[9], &b[9]); + sp_2048_mul_9(z0, a, b); + sp_2048_mul_9(z1, a1, b1); + sp_2048_sub_18(z1, z1, z2); + sp_2048_sub_18(z1, z1, z0); + sp_2048_add_18(r + 9, r + 9, z1); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_2048_sqr_18(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z1[18]; + sp_digit* a1 = z1; + sp_digit* z2 = r + 18; + sp_2048_add_9(a1, a, &a[9]); + sp_2048_sqr_9(z2, &a[9]); + sp_2048_sqr_9(z0, a); + sp_2048_sqr_9(z1, a1); + sp_2048_sub_18(z1, z1, z2); + sp_2048_sub_18(z1, z1, z0); + sp_2048_add_18(r + 9, r + 9, z1); +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_2048_add_36(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 32; i += 8) { + r[i + 0] = a[i + 0] + b[i + 0]; + r[i + 1] = a[i + 1] + b[i + 1]; + r[i + 2] = a[i + 2] + b[i + 2]; + r[i + 3] = a[i + 3] + b[i + 3]; + r[i + 4] = a[i + 4] + b[i + 4]; + r[i + 5] = a[i + 5] + b[i + 5]; + r[i + 6] = a[i + 6] + b[i + 6]; + r[i + 7] = a[i + 7] + b[i + 7]; + } + r[32] = a[32] + b[32]; + r[33] = a[33] + b[33]; + r[34] = a[34] + b[34]; + r[35] = a[35] + b[35]; + + return 0; +} + +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_2048_sub_36(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 32; i += 8) { + r[i + 0] = a[i + 0] - b[i + 0]; + r[i + 1] = a[i + 1] - b[i + 1]; + r[i + 2] = a[i + 2] - b[i + 2]; + r[i + 3] = a[i + 3] - b[i + 3]; + r[i + 4] = a[i + 4] - b[i + 4]; + r[i + 5] = a[i + 5] - b[i + 5]; + r[i + 6] = a[i + 6] - b[i + 6]; + r[i + 7] = a[i + 7] - b[i + 7]; + } + r[32] = a[32] - b[32]; + r[33] = a[33] - b[33]; + r[34] = a[34] - b[34]; + r[35] = a[35] - b[35]; + + return 0; +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_2048_mul_36(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[36]; + sp_digit* a1 = z1; + sp_digit b1[18]; + sp_digit* z2 = r + 36; + sp_2048_add_18(a1, a, &a[18]); + sp_2048_add_18(b1, b, &b[18]); + sp_2048_mul_18(z2, &a[18], &b[18]); + sp_2048_mul_18(z0, a, b); + sp_2048_mul_18(z1, a1, b1); + sp_2048_sub_36(z1, z1, z2); + sp_2048_sub_36(z1, z1, z0); + sp_2048_add_36(r + 18, r + 18, z1); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_2048_sqr_36(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z1[36]; + sp_digit* a1 = z1; + sp_digit* z2 = r + 36; + sp_2048_add_18(a1, a, &a[18]); + sp_2048_sqr_18(z2, &a[18]); + sp_2048_sqr_18(z0, a); + sp_2048_sqr_18(z1, a1); + sp_2048_sub_36(z1, z1, z2); + sp_2048_sub_36(z1, z1, z0); + sp_2048_add_36(r + 18, r + 18, z1); +} + +#endif /* !WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_2048_add_36(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 36; i++) + r[i] = a[i] + b[i]; + + return 0; +} +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_2048_sub_36(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 36; i++) + r[i] = a[i] - b[i]; + + return 0; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_2048_mul_36(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i, j, k; + int128_t c; + + c = ((int128_t)a[35]) * b[35]; + r[71] = (sp_digit)(c >> 57); + c = (c & 0x1ffffffffffffffl) << 57; + for (k = 69; k >= 0; k--) { + for (i = 35; i >= 0; i--) { + j = k - i; + if (j >= 36) + break; + if (j < 0) + continue; + + c += ((int128_t)a[i]) * b[j]; + } + r[k + 2] += c >> 114; + r[k + 1] = (c >> 57) & 0x1ffffffffffffffl; + c = (c & 0x1ffffffffffffffl) << 57; + } + r[0] = (sp_digit)(c >> 57); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_2048_sqr_36(sp_digit* r, const sp_digit* a) +{ + int i, j, k; + int128_t c; + + c = ((int128_t)a[35]) * a[35]; + r[71] = (sp_digit)(c >> 57); + c = (c & 0x1ffffffffffffffl) << 57; + for (k = 69; k >= 0; k--) { + for (i = 35; i >= 0; i--) { + j = k - i; + if (j >= 36 || i <= j) + break; + if (j < 0) + continue; + + c += ((int128_t)a[i]) * a[j] * 2; + } + if (i == j) + c += ((int128_t)a[i]) * a[i]; + + r[k + 2] += c >> 114; + r[k + 1] = (c >> 57) & 0x1ffffffffffffffl; + c = (c & 0x1ffffffffffffffl) << 57; + } + r[0] = (sp_digit)(c >> 57); +} + +#endif /* WOLFSSL_SP_SMALL */ +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_2048_add_18(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 18; i++) + r[i] = a[i] + b[i]; + + return 0; +} +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_2048_sub_18(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 18; i++) + r[i] = a[i] - b[i]; + + return 0; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_2048_mul_18(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i, j, k; + int128_t c; + + c = ((int128_t)a[17]) * b[17]; + r[35] = (sp_digit)(c >> 57); + c = (c & 0x1ffffffffffffffl) << 57; + for (k = 33; k >= 0; k--) { + for (i = 17; i >= 0; i--) { + j = k - i; + if (j >= 18) + break; + if (j < 0) + continue; + + c += ((int128_t)a[i]) * b[j]; + } + r[k + 2] += c >> 114; + r[k + 1] = (c >> 57) & 0x1ffffffffffffffl; + c = (c & 0x1ffffffffffffffl) << 57; + } + r[0] = (sp_digit)(c >> 57); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_2048_sqr_18(sp_digit* r, const sp_digit* a) +{ + int i, j, k; + int128_t c; + + c = ((int128_t)a[17]) * a[17]; + r[35] = (sp_digit)(c >> 57); + c = (c & 0x1ffffffffffffffl) << 57; + for (k = 33; k >= 0; k--) { + for (i = 17; i >= 0; i--) { + j = k - i; + if (j >= 18 || i <= j) + break; + if (j < 0) + continue; + + c += ((int128_t)a[i]) * a[j] * 2; + } + if (i == j) + c += ((int128_t)a[i]) * a[i]; + + r[k + 2] += c >> 114; + r[k + 1] = (c >> 57) & 0x1ffffffffffffffl; + c = (c & 0x1ffffffffffffffl) << 57; + } + r[0] = (sp_digit)(c >> 57); +} + +#endif /* WOLFSSL_SP_SMALL */ +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +/* Caclulate the bottom digit of -1/a mod 2^n. + * + * a A single precision number. + * rho Bottom word of inverse. + */ +static void sp_2048_mont_setup(sp_digit* a, sp_digit* rho) +{ + sp_digit x, b; + + b = a[0]; + x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ + x *= 2 - b * x; /* here x*a==1 mod 2**8 */ + x *= 2 - b * x; /* here x*a==1 mod 2**16 */ + x *= 2 - b * x; /* here x*a==1 mod 2**32 */ + x *= 2 - b * x; /* here x*a==1 mod 2**64 */ + x &= 0x1ffffffffffffffl; + + /* rho = -1/m mod b */ + *rho = (1L << 57) - x; +} + +/* Multiply a by scalar b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +SP_NOINLINE static void sp_2048_mul_d_36(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int128_t tb = b; + int128_t t = 0; + int i; + + for (i = 0; i < 36; i++) { + t += tb * a[i]; + r[i] = t & 0x1ffffffffffffffl; + t >>= 57; + } + r[36] = (sp_digit)t; +#else + int128_t tb = b; + int128_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] = t[0] & 0x1ffffffffffffffl; + for (i = 0; i < 32; i += 8) { + t[1] = tb * a[i+1]; + r[i+1] = (sp_digit)(t[0] >> 57) + (t[1] & 0x1ffffffffffffffl); + t[2] = tb * a[i+2]; + r[i+2] = (sp_digit)(t[1] >> 57) + (t[2] & 0x1ffffffffffffffl); + t[3] = tb * a[i+3]; + r[i+3] = (sp_digit)(t[2] >> 57) + (t[3] & 0x1ffffffffffffffl); + t[4] = tb * a[i+4]; + r[i+4] = (sp_digit)(t[3] >> 57) + (t[4] & 0x1ffffffffffffffl); + t[5] = tb * a[i+5]; + r[i+5] = (sp_digit)(t[4] >> 57) + (t[5] & 0x1ffffffffffffffl); + t[6] = tb * a[i+6]; + r[i+6] = (sp_digit)(t[5] >> 57) + (t[6] & 0x1ffffffffffffffl); + t[7] = tb * a[i+7]; + r[i+7] = (sp_digit)(t[6] >> 57) + (t[7] & 0x1ffffffffffffffl); + t[0] = tb * a[i+8]; + r[i+8] = (sp_digit)(t[7] >> 57) + (t[0] & 0x1ffffffffffffffl); + } + t[1] = tb * a[33]; + r[33] = (sp_digit)(t[0] >> 57) + (t[1] & 0x1ffffffffffffffl); + t[2] = tb * a[34]; + r[34] = (sp_digit)(t[1] >> 57) + (t[2] & 0x1ffffffffffffffl); + t[3] = tb * a[35]; + r[35] = (sp_digit)(t[2] >> 57) + (t[3] & 0x1ffffffffffffffl); + r[36] = (sp_digit)(t[3] >> 57); +#endif /* WOLFSSL_SP_SMALL */ +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +/* r = 2^n mod m where n is the number of bits to reduce by. + * Given m must be 2048 bits, just need to subtract. + * + * r A single precision number. + * m A signle precision number. + */ +static void sp_2048_mont_norm_18(sp_digit* r, sp_digit* m) +{ + /* Set r = 2^n - 1. */ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<17; i++) + r[i] = 0x1ffffffffffffffl; +#else + int i; + + for (i = 0; i < 16; i += 8) { + r[i + 0] = 0x1ffffffffffffffl; + r[i + 1] = 0x1ffffffffffffffl; + r[i + 2] = 0x1ffffffffffffffl; + r[i + 3] = 0x1ffffffffffffffl; + r[i + 4] = 0x1ffffffffffffffl; + r[i + 5] = 0x1ffffffffffffffl; + r[i + 6] = 0x1ffffffffffffffl; + r[i + 7] = 0x1ffffffffffffffl; + } + r[16] = 0x1ffffffffffffffl; +#endif + r[17] = 0x7fffffffffffffl; + + /* r = (2^n - 1) mod n */ + sp_2048_sub_18(r, r, m); + + /* Add one so r = 2^n mod m */ + r[0] += 1; +} + +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +static sp_digit sp_2048_cmp_18(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = 0; +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=17; i>=0; i--) + r |= (a[i] - b[i]) & (0 - !r); +#else + int i; + + r |= (a[17] - b[17]) & (0 - !r); + r |= (a[16] - b[16]) & (0 - !r); + for (i = 8; i >= 0; i -= 8) { + r |= (a[i + 7] - b[i + 7]) & (0 - !r); + r |= (a[i + 6] - b[i + 6]) & (0 - !r); + r |= (a[i + 5] - b[i + 5]) & (0 - !r); + r |= (a[i + 4] - b[i + 4]) & (0 - !r); + r |= (a[i + 3] - b[i + 3]) & (0 - !r); + r |= (a[i + 2] - b[i + 2]) & (0 - !r); + r |= (a[i + 1] - b[i + 1]) & (0 - !r); + r |= (a[i + 0] - b[i + 0]) & (0 - !r); + } +#endif /* WOLFSSL_SP_SMALL */ + + return r; +} + +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +static void sp_2048_cond_sub_18(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i = 0; i < 18; i++) + r[i] = a[i] - (b[i] & m); +#else + int i; + + for (i = 0; i < 16; i += 8) { + r[i + 0] = a[i + 0] - (b[i + 0] & m); + r[i + 1] = a[i + 1] - (b[i + 1] & m); + r[i + 2] = a[i + 2] - (b[i + 2] & m); + r[i + 3] = a[i + 3] - (b[i + 3] & m); + r[i + 4] = a[i + 4] - (b[i + 4] & m); + r[i + 5] = a[i + 5] - (b[i + 5] & m); + r[i + 6] = a[i + 6] - (b[i + 6] & m); + r[i + 7] = a[i + 7] - (b[i + 7] & m); + } + r[16] = a[16] - (b[16] & m); + r[17] = a[17] - (b[17] & m); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Mul a by scalar b and add into r. (r += a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +SP_NOINLINE static void sp_2048_mul_add_18(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int128_t tb = b; + int128_t t = 0; + int i; + + for (i = 0; i < 18; i++) { + t += (tb * a[i]) + r[i]; + r[i] = t & 0x1ffffffffffffffl; + t >>= 57; + } + r[18] += t; +#else + int128_t tb = b; + int128_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] += t[0] & 0x1ffffffffffffffl; + for (i = 0; i < 16; i += 8) { + t[1] = tb * a[i+1]; + r[i+1] += (t[0] >> 57) + (t[1] & 0x1ffffffffffffffl); + t[2] = tb * a[i+2]; + r[i+2] += (t[1] >> 57) + (t[2] & 0x1ffffffffffffffl); + t[3] = tb * a[i+3]; + r[i+3] += (t[2] >> 57) + (t[3] & 0x1ffffffffffffffl); + t[4] = tb * a[i+4]; + r[i+4] += (t[3] >> 57) + (t[4] & 0x1ffffffffffffffl); + t[5] = tb * a[i+5]; + r[i+5] += (t[4] >> 57) + (t[5] & 0x1ffffffffffffffl); + t[6] = tb * a[i+6]; + r[i+6] += (t[5] >> 57) + (t[6] & 0x1ffffffffffffffl); + t[7] = tb * a[i+7]; + r[i+7] += (t[6] >> 57) + (t[7] & 0x1ffffffffffffffl); + t[0] = tb * a[i+8]; + r[i+8] += (t[7] >> 57) + (t[0] & 0x1ffffffffffffffl); + } + t[1] = tb * a[17]; r[17] += (t[0] >> 57) + (t[1] & 0x1ffffffffffffffl); + r[18] += t[1] >> 57; +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Normalize the values in each word to 57. + * + * a Array of sp_digit to normalize. + */ +static void sp_2048_norm_18(sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + for (i = 0; i < 17; i++) { + a[i+1] += a[i] >> 57; + a[i] &= 0x1ffffffffffffffl; + } +#else + int i; + for (i = 0; i < 16; i += 8) { + a[i+1] += a[i+0] >> 57; a[i+0] &= 0x1ffffffffffffffl; + a[i+2] += a[i+1] >> 57; a[i+1] &= 0x1ffffffffffffffl; + a[i+3] += a[i+2] >> 57; a[i+2] &= 0x1ffffffffffffffl; + a[i+4] += a[i+3] >> 57; a[i+3] &= 0x1ffffffffffffffl; + a[i+5] += a[i+4] >> 57; a[i+4] &= 0x1ffffffffffffffl; + a[i+6] += a[i+5] >> 57; a[i+5] &= 0x1ffffffffffffffl; + a[i+7] += a[i+6] >> 57; a[i+6] &= 0x1ffffffffffffffl; + a[i+8] += a[i+7] >> 57; a[i+7] &= 0x1ffffffffffffffl; + a[i+9] += a[i+8] >> 57; a[i+8] &= 0x1ffffffffffffffl; + } + a[16+1] += a[16] >> 57; + a[16] &= 0x1ffffffffffffffl; +#endif +} + +/* Shift the result in the high 1024 bits down to the bottom. + * + * r A single precision number. + * a A single precision number. + */ +static void sp_2048_mont_shift_18(sp_digit* r, const sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + word64 n; + + n = a[17] >> 55; + for (i = 0; i < 17; i++) { + n += a[18 + i] << 2; + r[i] = n & 0x1ffffffffffffffl; + n >>= 57; + } + n += a[35] << 2; + r[17] = n; +#else + word64 n; + int i; + + n = a[17] >> 55; + for (i = 0; i < 16; i += 8) { + n += a[i+18] << 2; r[i+0] = n & 0x1ffffffffffffffl; n >>= 57; + n += a[i+19] << 2; r[i+1] = n & 0x1ffffffffffffffl; n >>= 57; + n += a[i+20] << 2; r[i+2] = n & 0x1ffffffffffffffl; n >>= 57; + n += a[i+21] << 2; r[i+3] = n & 0x1ffffffffffffffl; n >>= 57; + n += a[i+22] << 2; r[i+4] = n & 0x1ffffffffffffffl; n >>= 57; + n += a[i+23] << 2; r[i+5] = n & 0x1ffffffffffffffl; n >>= 57; + n += a[i+24] << 2; r[i+6] = n & 0x1ffffffffffffffl; n >>= 57; + n += a[i+25] << 2; r[i+7] = n & 0x1ffffffffffffffl; n >>= 57; + } + n += a[34] << 2; r[16] = n & 0x1ffffffffffffffl; n >>= 57; + n += a[35] << 2; r[17] = n; +#endif /* WOLFSSL_SP_SMALL */ + XMEMSET(&r[18], 0, sizeof(*r) * 18); +} + +/* Reduce the number back to 2048 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +static void sp_2048_mont_reduce_18(sp_digit* a, sp_digit* m, sp_digit mp) +{ + int i; + sp_digit mu; + + for (i=0; i<17; i++) { + mu = (a[i] * mp) & 0x1ffffffffffffffl; + sp_2048_mul_add_18(a+i, m, mu); + a[i+1] += a[i] >> 57; + } + mu = (a[i] * mp) & 0x7fffffffffffffl; + sp_2048_mul_add_18(a+i, m, mu); + a[i+1] += a[i] >> 57; + a[i] &= 0x1ffffffffffffffl; + + sp_2048_mont_shift_18(a, a); + sp_2048_cond_sub_18(a, a, m, 0 - ((a[17] >> 55) > 0)); + sp_2048_norm_18(a); +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_2048_mont_mul_18(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_2048_mul_18(r, a, b); + sp_2048_mont_reduce_18(r, m, mp); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_2048_mont_sqr_18(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_2048_sqr_18(r, a); + sp_2048_mont_reduce_18(r, m, mp); +} + +/* Multiply a by scalar b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +SP_NOINLINE static void sp_2048_mul_d_18(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int128_t tb = b; + int128_t t = 0; + int i; + + for (i = 0; i < 18; i++) { + t += tb * a[i]; + r[i] = t & 0x1ffffffffffffffl; + t >>= 57; + } + r[18] = (sp_digit)t; +#else + int128_t tb = b; + int128_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] = t[0] & 0x1ffffffffffffffl; + for (i = 0; i < 16; i += 8) { + t[1] = tb * a[i+1]; + r[i+1] = (sp_digit)(t[0] >> 57) + (t[1] & 0x1ffffffffffffffl); + t[2] = tb * a[i+2]; + r[i+2] = (sp_digit)(t[1] >> 57) + (t[2] & 0x1ffffffffffffffl); + t[3] = tb * a[i+3]; + r[i+3] = (sp_digit)(t[2] >> 57) + (t[3] & 0x1ffffffffffffffl); + t[4] = tb * a[i+4]; + r[i+4] = (sp_digit)(t[3] >> 57) + (t[4] & 0x1ffffffffffffffl); + t[5] = tb * a[i+5]; + r[i+5] = (sp_digit)(t[4] >> 57) + (t[5] & 0x1ffffffffffffffl); + t[6] = tb * a[i+6]; + r[i+6] = (sp_digit)(t[5] >> 57) + (t[6] & 0x1ffffffffffffffl); + t[7] = tb * a[i+7]; + r[i+7] = (sp_digit)(t[6] >> 57) + (t[7] & 0x1ffffffffffffffl); + t[0] = tb * a[i+8]; + r[i+8] = (sp_digit)(t[7] >> 57) + (t[0] & 0x1ffffffffffffffl); + } + t[1] = tb * a[17]; + r[17] = (sp_digit)(t[0] >> 57) + (t[1] & 0x1ffffffffffffffl); + r[18] = (sp_digit)(t[1] >> 57); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Conditionally add a and b using the mask m. + * m is -1 to add and 0 when not. + * + * r A single precision number representing conditional add result. + * a A single precision number to add with. + * b A single precision number to add. + * m Mask value to apply. + */ +static void sp_2048_cond_add_18(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i = 0; i < 18; i++) + r[i] = a[i] + (b[i] & m); +#else + int i; + + for (i = 0; i < 16; i += 8) { + r[i + 0] = a[i + 0] + (b[i + 0] & m); + r[i + 1] = a[i + 1] + (b[i + 1] & m); + r[i + 2] = a[i + 2] + (b[i + 2] & m); + r[i + 3] = a[i + 3] + (b[i + 3] & m); + r[i + 4] = a[i + 4] + (b[i + 4] & m); + r[i + 5] = a[i + 5] + (b[i + 5] & m); + r[i + 6] = a[i + 6] + (b[i + 6] & m); + r[i + 7] = a[i + 7] + (b[i + 7] & m); + } + r[16] = a[16] + (b[16] & m); + r[17] = a[17] + (b[17] & m); +#endif /* WOLFSSL_SP_SMALL */ +} + +#ifdef WOLFSSL_SMALL +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_2048_sub_18(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 18; i++) + r[i] = a[i] - b[i]; + + return 0; +} + +#endif +#ifdef WOLFSSL_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_2048_add_18(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 18; i++) + r[i] = a[i] + b[i]; + + return 0; +} +#endif +#ifdef WOLFSSL_SP_DIV_64 +static WC_INLINE sp_digit sp_2048_div_word_18(sp_digit d1, sp_digit d0, + sp_digit div) +{ + sp_digit d, r, t, dv; + int128_t t0, t1; + + /* dv has 29 bits. */ + dv = (div >> 28) + 1; + /* All 57 bits from d1 and top 6 bits from d0. */ + d = (d1 << 6) | (d0 >> 51); + r = d / dv; + d -= r * dv; + /* Up to 34 bits in r */ + /* Next 23 bits from d0. */ + d <<= 23; + r <<= 23; + d |= (d0 >> 28) & ((1 << 23) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 57 bits in r */ + + /* Handle rounding error with dv - top part */ + t0 = ((int128_t)d1 << 57) + d0; + t1 = (int128_t)r * div; + t1 = t0 - t1; + t = (sp_digit)(t1 >> 28) / dv; + r += t; + + /* Handle rounding error with dv - bottom 64 bits */ + t1 = (sp_digit)t0 - (r * div); + t = (sp_digit)t1 / div; + r += t; + + return r; +} +#endif /* WOLFSSL_SP_DIV_64 */ + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. + */ +static int sp_2048_div_18(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + int i; +#ifndef WOLFSSL_SP_DIV_64 + int128_t d1; +#endif + sp_digit div, r1; +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* td; +#else + sp_digit t1d[36], t2d[18 + 1]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (3 * 18 + 1), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td != NULL) { + t1 = td; + t2 = td + 2 * 18; + } + else + err = MEMORY_E; +#else + t1 = t1d; + t2 = t2d; +#endif + + (void)m; + + if (err == MP_OKAY) { + div = d[17]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 18); + for (i=17; i>=0; i--) { + t1[18 + i] += t1[18 + i - 1] >> 57; + t1[18 + i - 1] &= 0x1ffffffffffffffl; +#ifndef WOLFSSL_SP_DIV_64 + d1 = t1[18 + i]; + d1 <<= 57; + d1 += t1[18 + i - 1]; + r1 = (sp_digit)(d1 / div); +#else + r1 = sp_2048_div_word_18(t1[18 + i], t1[18 + i - 1], div); +#endif + + sp_2048_mul_d_18(t2, d, r1); + sp_2048_sub_18(&t1[i], &t1[i], t2); + t1[18 + i] -= t2[18]; + t1[18 + i] += t1[18 + i - 1] >> 57; + t1[18 + i - 1] &= 0x1ffffffffffffffl; + r1 = (((-t1[18 + i]) << 57) - t1[18 + i - 1]) / div; + r1++; + sp_2048_mul_d_18(t2, d, r1); + sp_2048_add_18(&t1[i], &t1[i], t2); + t1[18 + i] += t1[18 + i - 1] >> 57; + t1[18 + i - 1] &= 0x1ffffffffffffffl; + } + t1[18 - 1] += t1[18 - 2] >> 57; + t1[18 - 2] &= 0x1ffffffffffffffl; + r1 = t1[18 - 1] / div; + + sp_2048_mul_d_18(t2, d, r1); + sp_2048_sub_18(t1, t1, t2); + XMEMCPY(r, t1, sizeof(*r) * 2 * 18); + for (i=0; i<16; i++) { + r[i+1] += r[i] >> 57; + r[i] &= 0x1ffffffffffffffl; + } + sp_2048_cond_add_18(r, r, d, 0 - (r[17] < 0)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. + */ +static int sp_2048_mod_18(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_2048_div_18(a, m, NULL, r); +} + +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_2048_mod_exp_18(sp_digit* r, sp_digit* a, sp_digit* e, int bits, + sp_digit* m, int reduceA) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* td; + sp_digit* t[3]; + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + + td = (sp_digit*)XMALLOC(sizeof(*td) * 3 * 18 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + XMEMSET(td, 0, sizeof(*td) * 3 * 18 * 2); + + norm = t[0] = td; + t[1] = &td[18 * 2]; + t[2] = &td[2 * 18 * 2]; + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_18(norm, m); + + if (reduceA) + err = sp_2048_mod_18(t[1], a, m); + else + XMEMCPY(t[1], a, sizeof(sp_digit) * 18); + } + if (err == MP_OKAY) { + sp_2048_mul_18(t[1], t[1], norm); + err = sp_2048_mod_18(t[1], t[1], m); + } + + if (err == MP_OKAY) { + i = bits / 57; + c = bits % 57; + n = e[i--] << (57 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = e[i--]; + c = 57; + } + + y = (n >> 56) & 1; + n <<= 1; + + sp_2048_mont_mul_18(t[y^1], t[0], t[1], m, mp); + + XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), + sizeof(*t[2]) * 18 * 2); + sp_2048_mont_sqr_18(t[2], t[2], m, mp); + XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), t[2], + sizeof(*t[2]) * 18 * 2); + } + + sp_2048_mont_reduce_18(t[0], m, mp); + n = sp_2048_cmp_18(t[0], m); + sp_2048_cond_sub_18(t[0], t[0], m, (n < 0) - 1); + XMEMCPY(r, t[0], sizeof(*r) * 18 * 2); + + } + + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return err; +#elif defined(WOLFSSL_SP_CACHE_RESISTANT) +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[3][36]; +#else + sp_digit* td; + sp_digit* t[3]; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(*td) * 3 * 18 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + t[0] = td; + t[1] = &td[18 * 2]; + t[2] = &td[2 * 18 * 2]; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_18(norm, m); + + if (reduceA) { + err = sp_2048_mod_18(t[1], a, m); + if (err == MP_OKAY) { + sp_2048_mul_18(t[1], t[1], norm); + err = sp_2048_mod_18(t[1], t[1], m); + } + } + else { + sp_2048_mul_18(t[1], a, norm); + err = sp_2048_mod_18(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + i = bits / 57; + c = bits % 57; + n = e[i--] << (57 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = e[i--]; + c = 57; + } + + y = (n >> 56) & 1; + n <<= 1; + + sp_2048_mont_mul_18(t[y^1], t[0], t[1], m, mp); + + XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), sizeof(t[2])); + sp_2048_mont_sqr_18(t[2], t[2], m, mp); + XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), t[2], sizeof(t[2])); + } + + sp_2048_mont_reduce_18(t[0], m, mp); + n = sp_2048_cmp_18(t[0], m); + sp_2048_cond_sub_18(t[0], t[0], m, (n < 0) - 1); + XMEMCPY(r, t[0], sizeof(t[0])); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +#else +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][36]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit rt[36]; + sp_digit mp = 1; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 36, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<32; i++) + t[i] = td + i * 36; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_18(norm, m); + + if (reduceA) { + err = sp_2048_mod_18(t[1], a, m); + if (err == MP_OKAY) { + sp_2048_mul_18(t[1], t[1], norm); + err = sp_2048_mod_18(t[1], t[1], m); + } + } + else { + sp_2048_mul_18(t[1], a, norm); + err = sp_2048_mod_18(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_2048_mont_sqr_18(t[ 2], t[ 1], m, mp); + sp_2048_mont_mul_18(t[ 3], t[ 2], t[ 1], m, mp); + sp_2048_mont_sqr_18(t[ 4], t[ 2], m, mp); + sp_2048_mont_mul_18(t[ 5], t[ 3], t[ 2], m, mp); + sp_2048_mont_sqr_18(t[ 6], t[ 3], m, mp); + sp_2048_mont_mul_18(t[ 7], t[ 4], t[ 3], m, mp); + sp_2048_mont_sqr_18(t[ 8], t[ 4], m, mp); + sp_2048_mont_mul_18(t[ 9], t[ 5], t[ 4], m, mp); + sp_2048_mont_sqr_18(t[10], t[ 5], m, mp); + sp_2048_mont_mul_18(t[11], t[ 6], t[ 5], m, mp); + sp_2048_mont_sqr_18(t[12], t[ 6], m, mp); + sp_2048_mont_mul_18(t[13], t[ 7], t[ 6], m, mp); + sp_2048_mont_sqr_18(t[14], t[ 7], m, mp); + sp_2048_mont_mul_18(t[15], t[ 8], t[ 7], m, mp); + sp_2048_mont_sqr_18(t[16], t[ 8], m, mp); + sp_2048_mont_mul_18(t[17], t[ 9], t[ 8], m, mp); + sp_2048_mont_sqr_18(t[18], t[ 9], m, mp); + sp_2048_mont_mul_18(t[19], t[10], t[ 9], m, mp); + sp_2048_mont_sqr_18(t[20], t[10], m, mp); + sp_2048_mont_mul_18(t[21], t[11], t[10], m, mp); + sp_2048_mont_sqr_18(t[22], t[11], m, mp); + sp_2048_mont_mul_18(t[23], t[12], t[11], m, mp); + sp_2048_mont_sqr_18(t[24], t[12], m, mp); + sp_2048_mont_mul_18(t[25], t[13], t[12], m, mp); + sp_2048_mont_sqr_18(t[26], t[13], m, mp); + sp_2048_mont_mul_18(t[27], t[14], t[13], m, mp); + sp_2048_mont_sqr_18(t[28], t[14], m, mp); + sp_2048_mont_mul_18(t[29], t[15], t[14], m, mp); + sp_2048_mont_sqr_18(t[30], t[15], m, mp); + sp_2048_mont_mul_18(t[31], t[16], t[15], m, mp); + + bits = ((bits + 4) / 5) * 5; + i = ((bits + 56) / 57) - 1; + c = bits % 57; + if (c == 0) + c = 57; + if (i < 18) + n = e[i--] << (64 - c); + else { + n = 0; + i--; + } + if (c < 5) { + n |= e[i--] << (7 - c); + c += 57; + } + y = (n >> 59) & 0x1f; + n <<= 5; + c -= 5; + XMEMCPY(rt, t[y], sizeof(rt)); + for (; i>=0 || c>=5; ) { + if (c < 5) { + n |= e[i--] << (7 - c); + c += 57; + } + y = (n >> 59) & 0x1f; + n <<= 5; + c -= 5; + + sp_2048_mont_sqr_18(rt, rt, m, mp); + sp_2048_mont_sqr_18(rt, rt, m, mp); + sp_2048_mont_sqr_18(rt, rt, m, mp); + sp_2048_mont_sqr_18(rt, rt, m, mp); + sp_2048_mont_sqr_18(rt, rt, m, mp); + + sp_2048_mont_mul_18(rt, rt, t[y], m, mp); + } + + sp_2048_mont_reduce_18(rt, m, mp); + n = sp_2048_cmp_18(rt, m); + sp_2048_cond_sub_18(rt, rt, m, (n < 0) - 1); + XMEMCPY(r, rt, sizeof(rt)); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +#endif +} + +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +/* r = 2^n mod m where n is the number of bits to reduce by. + * Given m must be 2048 bits, just need to subtract. + * + * r A single precision number. + * m A signle precision number. + */ +static void sp_2048_mont_norm_36(sp_digit* r, sp_digit* m) +{ + /* Set r = 2^n - 1. */ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<35; i++) + r[i] = 0x1ffffffffffffffl; +#else + int i; + + for (i = 0; i < 32; i += 8) { + r[i + 0] = 0x1ffffffffffffffl; + r[i + 1] = 0x1ffffffffffffffl; + r[i + 2] = 0x1ffffffffffffffl; + r[i + 3] = 0x1ffffffffffffffl; + r[i + 4] = 0x1ffffffffffffffl; + r[i + 5] = 0x1ffffffffffffffl; + r[i + 6] = 0x1ffffffffffffffl; + r[i + 7] = 0x1ffffffffffffffl; + } + r[32] = 0x1ffffffffffffffl; + r[33] = 0x1ffffffffffffffl; + r[34] = 0x1ffffffffffffffl; +#endif + r[35] = 0x1fffffffffffffl; + + /* r = (2^n - 1) mod n */ + sp_2048_sub_36(r, r, m); + + /* Add one so r = 2^n mod m */ + r[0] += 1; +} + +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +static sp_digit sp_2048_cmp_36(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = 0; +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=35; i>=0; i--) + r |= (a[i] - b[i]) & (0 - !r); +#else + int i; + + r |= (a[35] - b[35]) & (0 - !r); + r |= (a[34] - b[34]) & (0 - !r); + r |= (a[33] - b[33]) & (0 - !r); + r |= (a[32] - b[32]) & (0 - !r); + for (i = 24; i >= 0; i -= 8) { + r |= (a[i + 7] - b[i + 7]) & (0 - !r); + r |= (a[i + 6] - b[i + 6]) & (0 - !r); + r |= (a[i + 5] - b[i + 5]) & (0 - !r); + r |= (a[i + 4] - b[i + 4]) & (0 - !r); + r |= (a[i + 3] - b[i + 3]) & (0 - !r); + r |= (a[i + 2] - b[i + 2]) & (0 - !r); + r |= (a[i + 1] - b[i + 1]) & (0 - !r); + r |= (a[i + 0] - b[i + 0]) & (0 - !r); + } +#endif /* WOLFSSL_SP_SMALL */ + + return r; +} + +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +static void sp_2048_cond_sub_36(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i = 0; i < 36; i++) + r[i] = a[i] - (b[i] & m); +#else + int i; + + for (i = 0; i < 32; i += 8) { + r[i + 0] = a[i + 0] - (b[i + 0] & m); + r[i + 1] = a[i + 1] - (b[i + 1] & m); + r[i + 2] = a[i + 2] - (b[i + 2] & m); + r[i + 3] = a[i + 3] - (b[i + 3] & m); + r[i + 4] = a[i + 4] - (b[i + 4] & m); + r[i + 5] = a[i + 5] - (b[i + 5] & m); + r[i + 6] = a[i + 6] - (b[i + 6] & m); + r[i + 7] = a[i + 7] - (b[i + 7] & m); + } + r[32] = a[32] - (b[32] & m); + r[33] = a[33] - (b[33] & m); + r[34] = a[34] - (b[34] & m); + r[35] = a[35] - (b[35] & m); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Mul a by scalar b and add into r. (r += a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +SP_NOINLINE static void sp_2048_mul_add_36(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int128_t tb = b; + int128_t t = 0; + int i; + + for (i = 0; i < 36; i++) { + t += (tb * a[i]) + r[i]; + r[i] = t & 0x1ffffffffffffffl; + t >>= 57; + } + r[36] += t; +#else + int128_t tb = b; + int128_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] += t[0] & 0x1ffffffffffffffl; + for (i = 0; i < 32; i += 8) { + t[1] = tb * a[i+1]; + r[i+1] += (t[0] >> 57) + (t[1] & 0x1ffffffffffffffl); + t[2] = tb * a[i+2]; + r[i+2] += (t[1] >> 57) + (t[2] & 0x1ffffffffffffffl); + t[3] = tb * a[i+3]; + r[i+3] += (t[2] >> 57) + (t[3] & 0x1ffffffffffffffl); + t[4] = tb * a[i+4]; + r[i+4] += (t[3] >> 57) + (t[4] & 0x1ffffffffffffffl); + t[5] = tb * a[i+5]; + r[i+5] += (t[4] >> 57) + (t[5] & 0x1ffffffffffffffl); + t[6] = tb * a[i+6]; + r[i+6] += (t[5] >> 57) + (t[6] & 0x1ffffffffffffffl); + t[7] = tb * a[i+7]; + r[i+7] += (t[6] >> 57) + (t[7] & 0x1ffffffffffffffl); + t[0] = tb * a[i+8]; + r[i+8] += (t[7] >> 57) + (t[0] & 0x1ffffffffffffffl); + } + t[1] = tb * a[33]; r[33] += (t[0] >> 57) + (t[1] & 0x1ffffffffffffffl); + t[2] = tb * a[34]; r[34] += (t[1] >> 57) + (t[2] & 0x1ffffffffffffffl); + t[3] = tb * a[35]; r[35] += (t[2] >> 57) + (t[3] & 0x1ffffffffffffffl); + r[36] += t[3] >> 57; +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Normalize the values in each word to 57. + * + * a Array of sp_digit to normalize. + */ +static void sp_2048_norm_36(sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + for (i = 0; i < 35; i++) { + a[i+1] += a[i] >> 57; + a[i] &= 0x1ffffffffffffffl; + } +#else + int i; + for (i = 0; i < 32; i += 8) { + a[i+1] += a[i+0] >> 57; a[i+0] &= 0x1ffffffffffffffl; + a[i+2] += a[i+1] >> 57; a[i+1] &= 0x1ffffffffffffffl; + a[i+3] += a[i+2] >> 57; a[i+2] &= 0x1ffffffffffffffl; + a[i+4] += a[i+3] >> 57; a[i+3] &= 0x1ffffffffffffffl; + a[i+5] += a[i+4] >> 57; a[i+4] &= 0x1ffffffffffffffl; + a[i+6] += a[i+5] >> 57; a[i+5] &= 0x1ffffffffffffffl; + a[i+7] += a[i+6] >> 57; a[i+6] &= 0x1ffffffffffffffl; + a[i+8] += a[i+7] >> 57; a[i+7] &= 0x1ffffffffffffffl; + a[i+9] += a[i+8] >> 57; a[i+8] &= 0x1ffffffffffffffl; + } + a[32+1] += a[32] >> 57; + a[32] &= 0x1ffffffffffffffl; + a[33+1] += a[33] >> 57; + a[33] &= 0x1ffffffffffffffl; + a[34+1] += a[34] >> 57; + a[34] &= 0x1ffffffffffffffl; +#endif +} + +/* Shift the result in the high 2048 bits down to the bottom. + * + * r A single precision number. + * a A single precision number. + */ +static void sp_2048_mont_shift_36(sp_digit* r, const sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + sp_digit n, s; + + s = a[36]; + n = a[35] >> 53; + for (i = 0; i < 35; i++) { + n += (s & 0x1ffffffffffffffl) << 4; + r[i] = n & 0x1ffffffffffffffl; + n >>= 57; + s = a[37 + i] + (s >> 57); + } + n += s << 4; + r[35] = n; +#else + sp_digit n, s; + int i; + + s = a[36]; n = a[35] >> 53; + for (i = 0; i < 32; i += 8) { + n += (s & 0x1ffffffffffffffl) << 4; r[i+0] = n & 0x1ffffffffffffffl; + n >>= 57; s = a[i+37] + (s >> 57); + n += (s & 0x1ffffffffffffffl) << 4; r[i+1] = n & 0x1ffffffffffffffl; + n >>= 57; s = a[i+38] + (s >> 57); + n += (s & 0x1ffffffffffffffl) << 4; r[i+2] = n & 0x1ffffffffffffffl; + n >>= 57; s = a[i+39] + (s >> 57); + n += (s & 0x1ffffffffffffffl) << 4; r[i+3] = n & 0x1ffffffffffffffl; + n >>= 57; s = a[i+40] + (s >> 57); + n += (s & 0x1ffffffffffffffl) << 4; r[i+4] = n & 0x1ffffffffffffffl; + n >>= 57; s = a[i+41] + (s >> 57); + n += (s & 0x1ffffffffffffffl) << 4; r[i+5] = n & 0x1ffffffffffffffl; + n >>= 57; s = a[i+42] + (s >> 57); + n += (s & 0x1ffffffffffffffl) << 4; r[i+6] = n & 0x1ffffffffffffffl; + n >>= 57; s = a[i+43] + (s >> 57); + n += (s & 0x1ffffffffffffffl) << 4; r[i+7] = n & 0x1ffffffffffffffl; + n >>= 57; s = a[i+44] + (s >> 57); + } + n += (s & 0x1ffffffffffffffl) << 4; r[32] = n & 0x1ffffffffffffffl; + n >>= 57; s = a[69] + (s >> 57); + n += (s & 0x1ffffffffffffffl) << 4; r[33] = n & 0x1ffffffffffffffl; + n >>= 57; s = a[70] + (s >> 57); + n += (s & 0x1ffffffffffffffl) << 4; r[34] = n & 0x1ffffffffffffffl; + n >>= 57; s = a[71] + (s >> 57); + n += s << 4; r[35] = n; +#endif /* WOLFSSL_SP_SMALL */ + XMEMSET(&r[36], 0, sizeof(*r) * 36); +} + +/* Reduce the number back to 2048 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +static void sp_2048_mont_reduce_36(sp_digit* a, sp_digit* m, sp_digit mp) +{ + int i; + sp_digit mu; + +#ifdef WOLFSSL_SP_DH + if (mp != 1) { + for (i=0; i<35; i++) { + mu = (a[i] * mp) & 0x1ffffffffffffffl; + sp_2048_mul_add_36(a+i, m, mu); + a[i+1] += a[i] >> 57; + } + mu = (a[i] * mp) & 0x1fffffffffffffl; + sp_2048_mul_add_36(a+i, m, mu); + a[i+1] += a[i] >> 57; + a[i] &= 0x1ffffffffffffffl; + } + else { + for (i=0; i<35; i++) { + mu = a[i] & 0x1ffffffffffffffl; + sp_2048_mul_add_36(a+i, m, mu); + a[i+1] += a[i] >> 57; + } + mu = a[i] & 0x1fffffffffffffl; + sp_2048_mul_add_36(a+i, m, mu); + a[i+1] += a[i] >> 57; + a[i] &= 0x1ffffffffffffffl; + } +#else + for (i=0; i<35; i++) { + mu = (a[i] * mp) & 0x1ffffffffffffffl; + sp_2048_mul_add_36(a+i, m, mu); + a[i+1] += a[i] >> 57; + } + mu = (a[i] * mp) & 0x1fffffffffffffl; + sp_2048_mul_add_36(a+i, m, mu); + a[i+1] += a[i] >> 57; + a[i] &= 0x1ffffffffffffffl; +#endif + + sp_2048_mont_shift_36(a, a); + sp_2048_cond_sub_36(a, a, m, 0 - ((a[35] >> 53) > 0)); + sp_2048_norm_36(a); +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_2048_mont_mul_36(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_2048_mul_36(r, a, b); + sp_2048_mont_reduce_36(r, m, mp); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_2048_mont_sqr_36(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_2048_sqr_36(r, a); + sp_2048_mont_reduce_36(r, m, mp); +} + +/* Conditionally add a and b using the mask m. + * m is -1 to add and 0 when not. + * + * r A single precision number representing conditional add result. + * a A single precision number to add with. + * b A single precision number to add. + * m Mask value to apply. + */ +static void sp_2048_cond_add_36(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i = 0; i < 36; i++) + r[i] = a[i] + (b[i] & m); +#else + int i; + + for (i = 0; i < 32; i += 8) { + r[i + 0] = a[i + 0] + (b[i + 0] & m); + r[i + 1] = a[i + 1] + (b[i + 1] & m); + r[i + 2] = a[i + 2] + (b[i + 2] & m); + r[i + 3] = a[i + 3] + (b[i + 3] & m); + r[i + 4] = a[i + 4] + (b[i + 4] & m); + r[i + 5] = a[i + 5] + (b[i + 5] & m); + r[i + 6] = a[i + 6] + (b[i + 6] & m); + r[i + 7] = a[i + 7] + (b[i + 7] & m); + } + r[32] = a[32] + (b[32] & m); + r[33] = a[33] + (b[33] & m); + r[34] = a[34] + (b[34] & m); + r[35] = a[35] + (b[35] & m); +#endif /* WOLFSSL_SP_SMALL */ +} + +#ifdef WOLFSSL_SMALL +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_2048_sub_36(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 36; i++) + r[i] = a[i] - b[i]; + + return 0; +} + +#endif +#ifdef WOLFSSL_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_2048_add_36(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 36; i++) + r[i] = a[i] + b[i]; + + return 0; +} +#endif +#ifdef WOLFSSL_SP_DIV_64 +static WC_INLINE sp_digit sp_2048_div_word_36(sp_digit d1, sp_digit d0, + sp_digit div) +{ + sp_digit d, r, t, dv; + int128_t t0, t1; + + /* dv has 29 bits. */ + dv = (div >> 28) + 1; + /* All 57 bits from d1 and top 6 bits from d0. */ + d = (d1 << 6) | (d0 >> 51); + r = d / dv; + d -= r * dv; + /* Up to 34 bits in r */ + /* Next 23 bits from d0. */ + d <<= 23; + r <<= 23; + d |= (d0 >> 28) & ((1 << 23) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 57 bits in r */ + + /* Handle rounding error with dv - top part */ + t0 = ((int128_t)d1 << 57) + d0; + t1 = (int128_t)r * div; + t1 = t0 - t1; + t = (sp_digit)(t1 >> 28) / dv; + r += t; + + /* Handle rounding error with dv - bottom 64 bits */ + t1 = (sp_digit)t0 - (r * div); + t = (sp_digit)t1 / div; + r += t; + + return r; +} +#endif /* WOLFSSL_SP_DIV_64 */ + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. + */ +static int sp_2048_div_36(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + int i; +#ifndef WOLFSSL_SP_DIV_64 + int128_t d1; +#endif + sp_digit div, r1; +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* td; +#else + sp_digit t1d[72], t2d[36 + 1]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (3 * 36 + 1), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td != NULL) { + t1 = td; + t2 = td + 2 * 36; + } + else + err = MEMORY_E; +#else + t1 = t1d; + t2 = t2d; +#endif + + (void)m; + + if (err == MP_OKAY) { + div = d[35]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 36); + for (i=35; i>=0; i--) { + t1[36 + i] += t1[36 + i - 1] >> 57; + t1[36 + i - 1] &= 0x1ffffffffffffffl; +#ifndef WOLFSSL_SP_DIV_64 + d1 = t1[36 + i]; + d1 <<= 57; + d1 += t1[36 + i - 1]; + r1 = (sp_digit)(d1 / div); +#else + r1 = sp_2048_div_word_36(t1[36 + i], t1[36 + i - 1], div); +#endif + + sp_2048_mul_d_36(t2, d, r1); + sp_2048_sub_36(&t1[i], &t1[i], t2); + t1[36 + i] -= t2[36]; + t1[36 + i] += t1[36 + i - 1] >> 57; + t1[36 + i - 1] &= 0x1ffffffffffffffl; + r1 = (((-t1[36 + i]) << 57) - t1[36 + i - 1]) / div; + r1++; + sp_2048_mul_d_36(t2, d, r1); + sp_2048_add_36(&t1[i], &t1[i], t2); + t1[36 + i] += t1[36 + i - 1] >> 57; + t1[36 + i - 1] &= 0x1ffffffffffffffl; + } + t1[36 - 1] += t1[36 - 2] >> 57; + t1[36 - 2] &= 0x1ffffffffffffffl; + r1 = t1[36 - 1] / div; + + sp_2048_mul_d_36(t2, d, r1); + sp_2048_sub_36(t1, t1, t2); + XMEMCPY(r, t1, sizeof(*r) * 2 * 36); + for (i=0; i<34; i++) { + r[i+1] += r[i] >> 57; + r[i] &= 0x1ffffffffffffffl; + } + sp_2048_cond_add_36(r, r, d, 0 - (r[35] < 0)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. + */ +static int sp_2048_mod_36(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_2048_div_36(a, m, NULL, r); +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \ + defined(WOLFSSL_HAVE_SP_DH) +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_2048_mod_exp_36(sp_digit* r, sp_digit* a, sp_digit* e, int bits, + sp_digit* m, int reduceA) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* td; + sp_digit* t[3]; + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + + td = (sp_digit*)XMALLOC(sizeof(*td) * 3 * 36 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + XMEMSET(td, 0, sizeof(*td) * 3 * 36 * 2); + + norm = t[0] = td; + t[1] = &td[36 * 2]; + t[2] = &td[2 * 36 * 2]; + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_36(norm, m); + + if (reduceA) + err = sp_2048_mod_36(t[1], a, m); + else + XMEMCPY(t[1], a, sizeof(sp_digit) * 36); + } + if (err == MP_OKAY) { + sp_2048_mul_36(t[1], t[1], norm); + err = sp_2048_mod_36(t[1], t[1], m); + } + + if (err == MP_OKAY) { + i = bits / 57; + c = bits % 57; + n = e[i--] << (57 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = e[i--]; + c = 57; + } + + y = (n >> 56) & 1; + n <<= 1; + + sp_2048_mont_mul_36(t[y^1], t[0], t[1], m, mp); + + XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), + sizeof(*t[2]) * 36 * 2); + sp_2048_mont_sqr_36(t[2], t[2], m, mp); + XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), t[2], + sizeof(*t[2]) * 36 * 2); + } + + sp_2048_mont_reduce_36(t[0], m, mp); + n = sp_2048_cmp_36(t[0], m); + sp_2048_cond_sub_36(t[0], t[0], m, (n < 0) - 1); + XMEMCPY(r, t[0], sizeof(*r) * 36 * 2); + + } + + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return err; +#elif defined(WOLFSSL_SP_CACHE_RESISTANT) +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[3][72]; +#else + sp_digit* td; + sp_digit* t[3]; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(*td) * 3 * 36 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + t[0] = td; + t[1] = &td[36 * 2]; + t[2] = &td[2 * 36 * 2]; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_36(norm, m); + + if (reduceA) { + err = sp_2048_mod_36(t[1], a, m); + if (err == MP_OKAY) { + sp_2048_mul_36(t[1], t[1], norm); + err = sp_2048_mod_36(t[1], t[1], m); + } + } + else { + sp_2048_mul_36(t[1], a, norm); + err = sp_2048_mod_36(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + i = bits / 57; + c = bits % 57; + n = e[i--] << (57 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = e[i--]; + c = 57; + } + + y = (n >> 56) & 1; + n <<= 1; + + sp_2048_mont_mul_36(t[y^1], t[0], t[1], m, mp); + + XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), sizeof(t[2])); + sp_2048_mont_sqr_36(t[2], t[2], m, mp); + XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), t[2], sizeof(t[2])); + } + + sp_2048_mont_reduce_36(t[0], m, mp); + n = sp_2048_cmp_36(t[0], m); + sp_2048_cond_sub_36(t[0], t[0], m, (n < 0) - 1); + XMEMCPY(r, t[0], sizeof(t[0])); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +#else +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][72]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit rt[72]; + sp_digit mp = 1; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 72, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<32; i++) + t[i] = td + i * 72; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_36(norm, m); + + if (reduceA) { + err = sp_2048_mod_36(t[1], a, m); + if (err == MP_OKAY) { + sp_2048_mul_36(t[1], t[1], norm); + err = sp_2048_mod_36(t[1], t[1], m); + } + } + else { + sp_2048_mul_36(t[1], a, norm); + err = sp_2048_mod_36(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_2048_mont_sqr_36(t[ 2], t[ 1], m, mp); + sp_2048_mont_mul_36(t[ 3], t[ 2], t[ 1], m, mp); + sp_2048_mont_sqr_36(t[ 4], t[ 2], m, mp); + sp_2048_mont_mul_36(t[ 5], t[ 3], t[ 2], m, mp); + sp_2048_mont_sqr_36(t[ 6], t[ 3], m, mp); + sp_2048_mont_mul_36(t[ 7], t[ 4], t[ 3], m, mp); + sp_2048_mont_sqr_36(t[ 8], t[ 4], m, mp); + sp_2048_mont_mul_36(t[ 9], t[ 5], t[ 4], m, mp); + sp_2048_mont_sqr_36(t[10], t[ 5], m, mp); + sp_2048_mont_mul_36(t[11], t[ 6], t[ 5], m, mp); + sp_2048_mont_sqr_36(t[12], t[ 6], m, mp); + sp_2048_mont_mul_36(t[13], t[ 7], t[ 6], m, mp); + sp_2048_mont_sqr_36(t[14], t[ 7], m, mp); + sp_2048_mont_mul_36(t[15], t[ 8], t[ 7], m, mp); + sp_2048_mont_sqr_36(t[16], t[ 8], m, mp); + sp_2048_mont_mul_36(t[17], t[ 9], t[ 8], m, mp); + sp_2048_mont_sqr_36(t[18], t[ 9], m, mp); + sp_2048_mont_mul_36(t[19], t[10], t[ 9], m, mp); + sp_2048_mont_sqr_36(t[20], t[10], m, mp); + sp_2048_mont_mul_36(t[21], t[11], t[10], m, mp); + sp_2048_mont_sqr_36(t[22], t[11], m, mp); + sp_2048_mont_mul_36(t[23], t[12], t[11], m, mp); + sp_2048_mont_sqr_36(t[24], t[12], m, mp); + sp_2048_mont_mul_36(t[25], t[13], t[12], m, mp); + sp_2048_mont_sqr_36(t[26], t[13], m, mp); + sp_2048_mont_mul_36(t[27], t[14], t[13], m, mp); + sp_2048_mont_sqr_36(t[28], t[14], m, mp); + sp_2048_mont_mul_36(t[29], t[15], t[14], m, mp); + sp_2048_mont_sqr_36(t[30], t[15], m, mp); + sp_2048_mont_mul_36(t[31], t[16], t[15], m, mp); + + bits = ((bits + 4) / 5) * 5; + i = ((bits + 56) / 57) - 1; + c = bits % 57; + if (c == 0) + c = 57; + if (i < 36) + n = e[i--] << (64 - c); + else { + n = 0; + i--; + } + if (c < 5) { + n |= e[i--] << (7 - c); + c += 57; + } + y = (n >> 59) & 0x1f; + n <<= 5; + c -= 5; + XMEMCPY(rt, t[y], sizeof(rt)); + for (; i>=0 || c>=5; ) { + if (c < 5) { + n |= e[i--] << (7 - c); + c += 57; + } + y = (n >> 59) & 0x1f; + n <<= 5; + c -= 5; + + sp_2048_mont_sqr_36(rt, rt, m, mp); + sp_2048_mont_sqr_36(rt, rt, m, mp); + sp_2048_mont_sqr_36(rt, rt, m, mp); + sp_2048_mont_sqr_36(rt, rt, m, mp); + sp_2048_mont_sqr_36(rt, rt, m, mp); + + sp_2048_mont_mul_36(rt, rt, t[y], m, mp); + } + + sp_2048_mont_reduce_36(rt, m, mp); + n = sp_2048_cmp_36(rt, m); + sp_2048_cond_sub_36(rt, rt, m, (n < 0) - 1); + XMEMCPY(r, rt, sizeof(rt)); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +#endif +} +#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || */ + /* WOLFSSL_HAVE_SP_DH */ + +#if defined(WOLFSSL_HAVE_SP_RSA) && !defined(SP_RSA_PRIVATE_EXP_D) && \ + !defined(RSA_LOW_MEM) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_2048_mask_18(sp_digit* r, sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<18; i++) + r[i] = a[i] & m; +#else + int i; + + for (i = 0; i < 16; i += 8) { + r[i+0] = a[i+0] & m; + r[i+1] = a[i+1] & m; + r[i+2] = a[i+2] & m; + r[i+3] = a[i+3] & m; + r[i+4] = a[i+4] & m; + r[i+5] = a[i+5] & m; + r[i+6] = a[i+6] & m; + r[i+7] = a[i+7] & m; + } + r[16] = a[16] & m; + r[17] = a[17] & m; +#endif +} + +#endif +#ifdef WOLFSSL_HAVE_SP_RSA +/* RSA public key operation. + * + * in Array of bytes representing the number to exponentiate, base. + * inLen Number of bytes in base. + * em Public exponent. + * mm Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 256 bytes long. + * outLen Number of bytes in result. + * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when + * an array is too long and MEMORY_E when dynamic memory allocation fails. + */ +int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm, + byte* out, word32* outLen) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* d = NULL; + sp_digit* a; + sp_digit* m; + sp_digit* r; + sp_digit* norm; + sp_digit e[1]; + sp_digit mp; + int i; + int err = MP_OKAY; + + if (*outLen < 256) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(em) > 57 || inLen > 256 || + mp_count_bits(mm) != 2048)) + err = MP_READ_E; + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 36 * 5, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + a = d; + r = a + 36 * 2; + m = r + 36 * 2; + norm = r; + + sp_2048_from_bin(a, 36, in, inLen); +#if DIGIT_BIT >= 57 + e[0] = (sp_digit)em->dp[0]; +#else + e[0] = (sp_digit)em->dp[0]; + if (em->used > 1) + e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT; +#endif + if (e[0] == 0) + err = MP_EXPTMOD_E; + } + + if (err == MP_OKAY) { + sp_2048_from_mp(m, 36, mm); + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_36(norm, m); + } + if (err == MP_OKAY) { + sp_2048_mul_36(a, a, norm); + err = sp_2048_mod_36(a, a, m); + } + if (err == MP_OKAY) { + for (i=56; i>=0; i--) + if (e[0] >> i) + break; + + XMEMCPY(r, a, sizeof(sp_digit) * 36 * 2); + for (i--; i>=0; i--) { + sp_2048_mont_sqr_36(r, r, m, mp); + + if (((e[0] >> i) & 1) == 1) + sp_2048_mont_mul_36(r, r, a, m, mp); + } + sp_2048_mont_reduce_36(r, m, mp); + mp = sp_2048_cmp_36(r, m); + sp_2048_cond_sub_36(r, r, m, (mp < 0) - 1); + + sp_2048_to_bin(r, out); + *outLen = 256; + } + + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + + return err; +#else +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit ad[72], md[36], rd[72]; +#else + sp_digit* d = NULL; +#endif + sp_digit* a; + sp_digit* m; + sp_digit* r; + sp_digit e[1]; + int err = MP_OKAY; + + if (*outLen < 256) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(em) > 57 || inLen > 256 || + mp_count_bits(mm) != 2048)) + err = MP_READ_E; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 36 * 5, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + a = d; + r = a + 36 * 2; + m = r + 36 * 2; + } +#else + a = ad; + m = md; + r = rd; +#endif + + if (err == MP_OKAY) { + sp_2048_from_bin(a, 36, in, inLen); +#if DIGIT_BIT >= 57 + e[0] = (sp_digit)em->dp[0]; +#else + e[0] = (sp_digit)em->dp[0]; + if (em->used > 1) + e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT; +#endif + if (e[0] == 0) + err = MP_EXPTMOD_E; + } + if (err == MP_OKAY) { + sp_2048_from_mp(m, 36, mm); + + if (e[0] == 0x3) { + if (err == MP_OKAY) { + sp_2048_sqr_36(r, a); + err = sp_2048_mod_36(r, r, m); + } + if (err == MP_OKAY) { + sp_2048_mul_36(r, a, r); + err = sp_2048_mod_36(r, r, m); + } + } + else { + sp_digit* norm = r; + int i; + sp_digit mp; + + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_36(norm, m); + + if (err == MP_OKAY) { + sp_2048_mul_36(a, a, norm); + err = sp_2048_mod_36(a, a, m); + } + + if (err == MP_OKAY) { + for (i=56; i>=0; i--) + if (e[0] >> i) + break; + + XMEMCPY(r, a, sizeof(sp_digit) * 72); + for (i--; i>=0; i--) { + sp_2048_mont_sqr_36(r, r, m, mp); + + if (((e[0] >> i) & 1) == 1) + sp_2048_mont_mul_36(r, r, a, m, mp); + } + sp_2048_mont_reduce_36(r, m, mp); + mp = sp_2048_cmp_36(r, m); + sp_2048_cond_sub_36(r, r, m, (mp < 0) - 1); + } + } + } + + if (err == MP_OKAY) { + sp_2048_to_bin(r, out); + *outLen = 256; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_RSA); +#endif + + return err; +#endif /* WOLFSSL_SP_SMALL */ +} + +#ifndef WOLFSSL_RSA_PUBLIC_ONLY +/* RSA private key operation. + * + * in Array of bytes representing the number to exponentiate, base. + * inLen Number of bytes in base. + * dm Private exponent. + * pm First prime. + * qm Second prime. + * dpm First prime's CRT exponent. + * dqm Second prime's CRT exponent. + * qim Inverse of second prime mod p. + * mm Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 256 bytes long. + * outLen Number of bytes in result. + * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when + * an array is too long and MEMORY_E when dynamic memory allocation fails. + */ +int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, + mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm, + byte* out, word32* outLen) +{ +#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* a; + sp_digit* d = NULL; + sp_digit* m; + sp_digit* r; + int err = MP_OKAY; + + (void)pm; + (void)qm; + (void)dpm; + (void)dqm; + (void)qim; + + if (*outLen < 256) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(dm) > 2048 || inLen > 256 || + mp_count_bits(mm) != 2048)) + err = MP_READ_E; + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 36 * 4, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + a = d + 36; + m = a + 36; + r = a; + + sp_2048_from_bin(a, 36, in, inLen); + sp_2048_from_mp(d, 36, dm); + sp_2048_from_mp(m, 36, mm); + err = sp_2048_mod_exp_36(r, a, d, 2048, m, 0); + } + if (err == MP_OKAY) { + sp_2048_to_bin(r, out); + *outLen = 256; + } + + if (d != NULL) { + XMEMSET(d, 0, sizeof(sp_digit) * 36); + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + } + + return err; +#else + sp_digit a[72], d[36], m[36]; + sp_digit* r = a; + int err = MP_OKAY; + + (void)pm; + (void)qm; + (void)dpm; + (void)dqm; + (void)qim; + + if (*outLen < 256) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(dm) > 2048 || inLen > 256 || + mp_count_bits(mm) != 2048)) + err = MP_READ_E; + + if (err == MP_OKAY) { + sp_2048_from_bin(a, 36, in, inLen); + sp_2048_from_mp(d, 36, dm); + sp_2048_from_mp(m, 36, mm); + err = sp_2048_mod_exp_36(r, a, d, 2048, m, 0); + } + + if (err == MP_OKAY) { + sp_2048_to_bin(r, out); + *outLen = 256; + } + + XMEMSET(d, 0, sizeof(sp_digit) * 36); + + return err; +#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */ +#else +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* t = NULL; + sp_digit* a; + sp_digit* p; + sp_digit* q; + sp_digit* dp; + sp_digit* dq; + sp_digit* qi; + sp_digit* tmp; + sp_digit* tmpa; + sp_digit* tmpb; + sp_digit* r; + int err = MP_OKAY; + + (void)dm; + (void)mm; + + if (*outLen < 256) + err = MP_TO_E; + if (err == MP_OKAY && (inLen > 256 || mp_count_bits(mm) != 2048)) + err = MP_READ_E; + + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 18 * 11, NULL, + DYNAMIC_TYPE_RSA); + if (t == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + a = t; + p = a + 36 * 2; + q = p + 18; + qi = dq = dp = q + 18; + tmpa = qi + 18; + tmpb = tmpa + 36; + + tmp = t; + r = tmp + 36; + + sp_2048_from_bin(a, 36, in, inLen); + sp_2048_from_mp(p, 18, pm); + sp_2048_from_mp(q, 18, qm); + sp_2048_from_mp(dp, 18, dpm); + err = sp_2048_mod_exp_18(tmpa, a, dp, 1024, p, 1); + } + if (err == MP_OKAY) { + sp_2048_from_mp(dq, 18, dqm); + err = sp_2048_mod_exp_18(tmpb, a, dq, 1024, q, 1); + } + if (err == MP_OKAY) { + sp_2048_sub_18(tmpa, tmpa, tmpb); + sp_2048_mask_18(tmp, p, tmpa[17] >> 63); + sp_2048_add_18(tmpa, tmpa, tmp); + + sp_2048_from_mp(qi, 18, qim); + sp_2048_mul_18(tmpa, tmpa, qi); + err = sp_2048_mod_18(tmpa, tmpa, p); + } + + if (err == MP_OKAY) { + sp_2048_mul_18(tmpa, q, tmpa); + sp_2048_add_36(r, tmpb, tmpa); + sp_2048_norm_36(r); + + sp_2048_to_bin(r, out); + *outLen = 256; + } + + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_digit) * 18 * 11); + XFREE(t, NULL, DYNAMIC_TYPE_RSA); + } + + return err; +#else + sp_digit a[36 * 2]; + sp_digit p[18], q[18], dp[18], dq[18], qi[18]; + sp_digit tmp[36], tmpa[36], tmpb[36]; + sp_digit* r = a; + int err = MP_OKAY; + + (void)dm; + (void)mm; + + if (*outLen < 256) + err = MP_TO_E; + if (err == MP_OKAY && (inLen > 256 || mp_count_bits(mm) != 2048)) + err = MP_READ_E; + + if (err == MP_OKAY) { + sp_2048_from_bin(a, 36, in, inLen); + sp_2048_from_mp(p, 18, pm); + sp_2048_from_mp(q, 18, qm); + sp_2048_from_mp(dp, 18, dpm); + sp_2048_from_mp(dq, 18, dqm); + sp_2048_from_mp(qi, 18, qim); + + err = sp_2048_mod_exp_18(tmpa, a, dp, 1024, p, 1); + } + if (err == MP_OKAY) + err = sp_2048_mod_exp_18(tmpb, a, dq, 1024, q, 1); + + if (err == MP_OKAY) { + sp_2048_sub_18(tmpa, tmpa, tmpb); + sp_2048_mask_18(tmp, p, tmpa[17] >> 63); + sp_2048_add_18(tmpa, tmpa, tmp); + sp_2048_mul_18(tmpa, tmpa, qi); + err = sp_2048_mod_18(tmpa, tmpa, p); + } + + if (err == MP_OKAY) { + sp_2048_mul_18(tmpa, tmpa, q); + sp_2048_add_36(r, tmpb, tmpa); + sp_2048_norm_36(r); + + sp_2048_to_bin(r, out); + *outLen = 256; + } + + XMEMSET(tmpa, 0, sizeof(tmpa)); + XMEMSET(tmpb, 0, sizeof(tmpb)); + XMEMSET(p, 0, sizeof(p)); + XMEMSET(q, 0, sizeof(q)); + XMEMSET(dp, 0, sizeof(dp)); + XMEMSET(dq, 0, sizeof(dq)); + XMEMSET(qi, 0, sizeof(qi)); + + return err; +#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */ +#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ +} + +#endif /* !WOLFSSL_RSA_PUBLIC_ONLY */ +#endif /* WOLFSSL_HAVE_SP_RSA */ +#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \ + !defined(WOLFSSL_RSA_PUBLIC_ONLY)) +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_2048_to_mp(sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (2048 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { +#if DIGIT_BIT == 57 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 36); + r->used = 36; + mp_clamp(r); +#elif DIGIT_BIT < 57 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 36; i++) { + r->dp[j] |= a[i] << s; + r->dp[j] &= (1l << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + while (s + DIGIT_BIT <= 57) { + s += DIGIT_BIT; + r->dp[j] &= (1l << DIGIT_BIT) - 1; + r->dp[++j] = a[i] >> s; + } + s = 57 - s; + } + r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 36; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 57 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && DIGIT_BIT != 64 + r->dp[j] &= (1l << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 57 - s; + } + else + s += 57; + } + r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returs 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ +#ifdef WOLFSSL_SP_SMALL + int err = MP_OKAY; + sp_digit* d = NULL; + sp_digit* b; + sp_digit* e; + sp_digit* m; + sp_digit* r; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 2048 || expBits > 2048 || + mp_count_bits(mod) != 2048) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 36 * 4, NULL, DYNAMIC_TYPE_DH); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + b = d; + e = b + 36 * 2; + m = e + 36; + r = b; + + sp_2048_from_mp(b, 36, base); + sp_2048_from_mp(e, 36, exp); + sp_2048_from_mp(m, 36, mod); + + err = sp_2048_mod_exp_36(r, b, e, mp_count_bits(exp), m, 0); + } + + if (err == MP_OKAY) { + err = sp_2048_to_mp(r, res); + } + + if (d != NULL) { + XMEMSET(e, 0, sizeof(sp_digit) * 36); + XFREE(d, NULL, DYNAMIC_TYPE_DH); + } + return err; +#else +#ifndef WOLFSSL_SMALL_STACK + sp_digit bd[72], ed[36], md[36]; +#else + sp_digit* d = NULL; +#endif + sp_digit* b; + sp_digit* e; + sp_digit* m; + sp_digit* r; + int err = MP_OKAY; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 2048 || expBits > 2048 || + mp_count_bits(mod) != 2048) { + err = MP_READ_E; + } + +#ifdef WOLFSSL_SMALL_STACK + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 36 * 4, NULL, DYNAMIC_TYPE_DH); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + b = d; + e = b + 36 * 2; + m = e + 36; + r = b; + } +#else + r = b = bd; + e = ed; + m = md; +#endif + + if (err == MP_OKAY) { + sp_2048_from_mp(b, 36, base); + sp_2048_from_mp(e, 36, exp); + sp_2048_from_mp(m, 36, mod); + + err = sp_2048_mod_exp_36(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + err = sp_2048_to_mp(r, res); + } + + XMEMSET(e, 0, sizeof(sp_digit) * 36); + +#ifdef WOLFSSL_SMALL_STACK + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_DH); +#endif + + return err; +#endif +} + +#ifdef WOLFSSL_HAVE_SP_DH +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. + * exp Array of bytes that is the exponent. + * expLen Length of data, in bytes, in exponent. + * mod Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 256 bytes long. + * outLen Length, in bytes, of exponentiation result. + * returs 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen, + mp_int* mod, byte* out, word32* outLen) +{ +#ifdef WOLFSSL_SP_SMALL + int err = MP_OKAY; + sp_digit* d = NULL; + sp_digit* b; + sp_digit* e; + sp_digit* m; + sp_digit* r; + word32 i; + + if (mp_count_bits(base) > 2048 || expLen > 256 || + mp_count_bits(mod) != 2048) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 36 * 4, NULL, DYNAMIC_TYPE_DH); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + b = d; + e = b + 36 * 2; + m = e + 36; + r = b; + + sp_2048_from_mp(b, 36, base); + sp_2048_from_bin(e, 36, exp, expLen); + sp_2048_from_mp(m, 36, mod); + + err = sp_2048_mod_exp_36(r, b, e, expLen * 8, m, 0); + } + + if (err == MP_OKAY) { + sp_2048_to_bin(r, out); + *outLen = 256; + for (i=0; i<256 && out[i] == 0; i++) { + } + *outLen -= i; + XMEMMOVE(out, out + i, *outLen); + } + + if (d != NULL) { + XMEMSET(e, 0, sizeof(sp_digit) * 36); + XFREE(d, NULL, DYNAMIC_TYPE_DH); + } + return err; +#else +#ifndef WOLFSSL_SMALL_STACK + sp_digit bd[72], ed[36], md[36]; +#else + sp_digit* d = NULL; +#endif + sp_digit* b; + sp_digit* e; + sp_digit* m; + sp_digit* r; + word32 i; + int err = MP_OKAY; + + if (mp_count_bits(base) > 2048 || expLen > 256 || + mp_count_bits(mod) != 2048) { + err = MP_READ_E; + } + +#ifdef WOLFSSL_SMALL_STACK + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 36 * 4, NULL, DYNAMIC_TYPE_DH); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + b = d; + e = b + 36 * 2; + m = e + 36; + r = b; + } +#else + r = b = bd; + e = ed; + m = md; +#endif + + if (err == MP_OKAY) { + sp_2048_from_mp(b, 36, base); + sp_2048_from_bin(e, 36, exp, expLen); + sp_2048_from_mp(m, 36, mod); + + err = sp_2048_mod_exp_36(r, b, e, expLen * 8, m, 0); + } + + if (err == MP_OKAY) { + sp_2048_to_bin(r, out); + *outLen = 256; + for (i=0; i<256 && out[i] == 0; i++) { + } + *outLen -= i; + XMEMMOVE(out, out + i, *outLen); + } + + XMEMSET(e, 0, sizeof(sp_digit) * 36); + +#ifdef WOLFSSL_SMALL_STACK + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_DH); +#endif + + return err; +#endif +} +#endif /* WOLFSSL_HAVE_SP_DH */ + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returs 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ +#ifdef WOLFSSL_SP_SMALL + int err = MP_OKAY; + sp_digit* d = NULL; + sp_digit* b; + sp_digit* e; + sp_digit* m; + sp_digit* r; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 1024 || expBits > 1024 || + mp_count_bits(mod) != 1024) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 18 * 4, NULL, DYNAMIC_TYPE_DH); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + b = d; + e = b + 18 * 2; + m = e + 18; + r = b; + + sp_2048_from_mp(b, 18, base); + sp_2048_from_mp(e, 18, exp); + sp_2048_from_mp(m, 18, mod); + + err = sp_2048_mod_exp_18(r, b, e, mp_count_bits(exp), m, 0); + } + + if (err == MP_OKAY) { + XMEMSET(r + 18, 0, sizeof(*r) * 18); + err = sp_2048_to_mp(r, res); + } + + if (d != NULL) { + XMEMSET(e, 0, sizeof(sp_digit) * 18); + XFREE(d, NULL, DYNAMIC_TYPE_DH); + } + return err; +#else +#ifndef WOLFSSL_SMALL_STACK + sp_digit bd[36], ed[18], md[18]; +#else + sp_digit* d = NULL; +#endif + sp_digit* b; + sp_digit* e; + sp_digit* m; + sp_digit* r; + int err = MP_OKAY; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 1024 || expBits > 1024 || + mp_count_bits(mod) != 1024) { + err = MP_READ_E; + } + +#ifdef WOLFSSL_SMALL_STACK + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 18 * 4, NULL, DYNAMIC_TYPE_DH); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + b = d; + e = b + 18 * 2; + m = e + 18; + r = b; + } +#else + r = b = bd; + e = ed; + m = md; +#endif + + if (err == MP_OKAY) { + sp_2048_from_mp(b, 18, base); + sp_2048_from_mp(e, 18, exp); + sp_2048_from_mp(m, 18, mod); + + err = sp_2048_mod_exp_18(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + XMEMSET(r + 18, 0, sizeof(*r) * 18); + err = sp_2048_to_mp(r, res); + } + + XMEMSET(e, 0, sizeof(sp_digit) * 18); + +#ifdef WOLFSSL_SMALL_STACK + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_DH); +#endif + + return err; +#endif +} + +#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ + +#endif /* !WOLFSSL_SP_NO_2048 */ + +#ifndef WOLFSSL_SP_NO_3072 +/* Read big endian unsigned byte aray into r. + * + * r A single precision integer. + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_3072_from_bin(sp_digit* r, int max, const byte* a, int n) +{ + int i, j = 0, s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= ((sp_digit)a[i]) << s; + if (s >= 49) { + r[j] &= 0x1ffffffffffffffl; + s = 57 - s; + if (j + 1 >= max) + break; + r[++j] = a[i] >> s; + s = 8 - s; + } + else + s += 8; + } + + for (j++; j < max; j++) + r[j] = 0; +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * a A multi-precision integer. + */ +static void sp_3072_from_mp(sp_digit* r, int max, mp_int* a) +{ +#if DIGIT_BIT == 57 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < max; j++) + r[j] = 0; +#elif DIGIT_BIT > 57 + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= a->dp[i] << s; + r[j] &= 0x1ffffffffffffffl; + s = 57 - s; + if (j + 1 >= max) + break; + r[++j] = (sp_digit)(a->dp[i] >> s); + while (s + 57 <= DIGIT_BIT) { + s += 57; + r[j] &= 0x1ffffffffffffffl; + if (j + 1 >= max) + break; + if (s < DIGIT_BIT) + r[++j] = (sp_digit)(a->dp[i] >> s); + else + r[++j] = 0; + } + s = DIGIT_BIT - s; + } + + for (j++; j < max; j++) + r[j] = 0; +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 57) { + r[j] &= 0x1ffffffffffffffl; + if (j + 1 >= max) + break; + s = 57 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else + s += DIGIT_BIT; + } + + for (j++; j < max; j++) + r[j] = 0; +#endif +} + +/* Write r as big endian to byte aray. + * Fixed length number of bytes written: 384 + * + * r A single precision integer. + * a Byte array. + */ +static void sp_3072_to_bin(sp_digit* r, byte* a) +{ + int i, j, s = 0, b; + + for (i=0; i<53; i++) { + r[i+1] += r[i] >> 57; + r[i] &= 0x1ffffffffffffffl; + } + j = 3072 / 8 - 1; + a[j] = 0; + for (i=0; i<54 && j>=0; i++) { + b = 0; + a[j--] |= r[i] << s; b += 8 - s; + if (j < 0) + break; + while (b < 57) { + a[j--] = r[i] >> b; b += 8; + if (j < 0) + break; + } + s = 8 - (b - 57); + if (j >= 0) + a[j] = 0; + if (s != 0) + j++; + } +} + +#ifndef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_3072_mul_9(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int128_t t0 = ((int128_t)a[ 0]) * b[ 0]; + int128_t t1 = ((int128_t)a[ 0]) * b[ 1] + + ((int128_t)a[ 1]) * b[ 0]; + int128_t t2 = ((int128_t)a[ 0]) * b[ 2] + + ((int128_t)a[ 1]) * b[ 1] + + ((int128_t)a[ 2]) * b[ 0]; + int128_t t3 = ((int128_t)a[ 0]) * b[ 3] + + ((int128_t)a[ 1]) * b[ 2] + + ((int128_t)a[ 2]) * b[ 1] + + ((int128_t)a[ 3]) * b[ 0]; + int128_t t4 = ((int128_t)a[ 0]) * b[ 4] + + ((int128_t)a[ 1]) * b[ 3] + + ((int128_t)a[ 2]) * b[ 2] + + ((int128_t)a[ 3]) * b[ 1] + + ((int128_t)a[ 4]) * b[ 0]; + int128_t t5 = ((int128_t)a[ 0]) * b[ 5] + + ((int128_t)a[ 1]) * b[ 4] + + ((int128_t)a[ 2]) * b[ 3] + + ((int128_t)a[ 3]) * b[ 2] + + ((int128_t)a[ 4]) * b[ 1] + + ((int128_t)a[ 5]) * b[ 0]; + int128_t t6 = ((int128_t)a[ 0]) * b[ 6] + + ((int128_t)a[ 1]) * b[ 5] + + ((int128_t)a[ 2]) * b[ 4] + + ((int128_t)a[ 3]) * b[ 3] + + ((int128_t)a[ 4]) * b[ 2] + + ((int128_t)a[ 5]) * b[ 1] + + ((int128_t)a[ 6]) * b[ 0]; + int128_t t7 = ((int128_t)a[ 0]) * b[ 7] + + ((int128_t)a[ 1]) * b[ 6] + + ((int128_t)a[ 2]) * b[ 5] + + ((int128_t)a[ 3]) * b[ 4] + + ((int128_t)a[ 4]) * b[ 3] + + ((int128_t)a[ 5]) * b[ 2] + + ((int128_t)a[ 6]) * b[ 1] + + ((int128_t)a[ 7]) * b[ 0]; + int128_t t8 = ((int128_t)a[ 0]) * b[ 8] + + ((int128_t)a[ 1]) * b[ 7] + + ((int128_t)a[ 2]) * b[ 6] + + ((int128_t)a[ 3]) * b[ 5] + + ((int128_t)a[ 4]) * b[ 4] + + ((int128_t)a[ 5]) * b[ 3] + + ((int128_t)a[ 6]) * b[ 2] + + ((int128_t)a[ 7]) * b[ 1] + + ((int128_t)a[ 8]) * b[ 0]; + int128_t t9 = ((int128_t)a[ 1]) * b[ 8] + + ((int128_t)a[ 2]) * b[ 7] + + ((int128_t)a[ 3]) * b[ 6] + + ((int128_t)a[ 4]) * b[ 5] + + ((int128_t)a[ 5]) * b[ 4] + + ((int128_t)a[ 6]) * b[ 3] + + ((int128_t)a[ 7]) * b[ 2] + + ((int128_t)a[ 8]) * b[ 1]; + int128_t t10 = ((int128_t)a[ 2]) * b[ 8] + + ((int128_t)a[ 3]) * b[ 7] + + ((int128_t)a[ 4]) * b[ 6] + + ((int128_t)a[ 5]) * b[ 5] + + ((int128_t)a[ 6]) * b[ 4] + + ((int128_t)a[ 7]) * b[ 3] + + ((int128_t)a[ 8]) * b[ 2]; + int128_t t11 = ((int128_t)a[ 3]) * b[ 8] + + ((int128_t)a[ 4]) * b[ 7] + + ((int128_t)a[ 5]) * b[ 6] + + ((int128_t)a[ 6]) * b[ 5] + + ((int128_t)a[ 7]) * b[ 4] + + ((int128_t)a[ 8]) * b[ 3]; + int128_t t12 = ((int128_t)a[ 4]) * b[ 8] + + ((int128_t)a[ 5]) * b[ 7] + + ((int128_t)a[ 6]) * b[ 6] + + ((int128_t)a[ 7]) * b[ 5] + + ((int128_t)a[ 8]) * b[ 4]; + int128_t t13 = ((int128_t)a[ 5]) * b[ 8] + + ((int128_t)a[ 6]) * b[ 7] + + ((int128_t)a[ 7]) * b[ 6] + + ((int128_t)a[ 8]) * b[ 5]; + int128_t t14 = ((int128_t)a[ 6]) * b[ 8] + + ((int128_t)a[ 7]) * b[ 7] + + ((int128_t)a[ 8]) * b[ 6]; + int128_t t15 = ((int128_t)a[ 7]) * b[ 8] + + ((int128_t)a[ 8]) * b[ 7]; + int128_t t16 = ((int128_t)a[ 8]) * b[ 8]; + + t1 += t0 >> 57; r[ 0] = t0 & 0x1ffffffffffffffl; + t2 += t1 >> 57; r[ 1] = t1 & 0x1ffffffffffffffl; + t3 += t2 >> 57; r[ 2] = t2 & 0x1ffffffffffffffl; + t4 += t3 >> 57; r[ 3] = t3 & 0x1ffffffffffffffl; + t5 += t4 >> 57; r[ 4] = t4 & 0x1ffffffffffffffl; + t6 += t5 >> 57; r[ 5] = t5 & 0x1ffffffffffffffl; + t7 += t6 >> 57; r[ 6] = t6 & 0x1ffffffffffffffl; + t8 += t7 >> 57; r[ 7] = t7 & 0x1ffffffffffffffl; + t9 += t8 >> 57; r[ 8] = t8 & 0x1ffffffffffffffl; + t10 += t9 >> 57; r[ 9] = t9 & 0x1ffffffffffffffl; + t11 += t10 >> 57; r[10] = t10 & 0x1ffffffffffffffl; + t12 += t11 >> 57; r[11] = t11 & 0x1ffffffffffffffl; + t13 += t12 >> 57; r[12] = t12 & 0x1ffffffffffffffl; + t14 += t13 >> 57; r[13] = t13 & 0x1ffffffffffffffl; + t15 += t14 >> 57; r[14] = t14 & 0x1ffffffffffffffl; + t16 += t15 >> 57; r[15] = t15 & 0x1ffffffffffffffl; + r[17] = (sp_digit)(t16 >> 57); + r[16] = t16 & 0x1ffffffffffffffl; +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_3072_sqr_9(sp_digit* r, const sp_digit* a) +{ + int128_t t0 = ((int128_t)a[ 0]) * a[ 0]; + int128_t t1 = (((int128_t)a[ 0]) * a[ 1]) * 2; + int128_t t2 = (((int128_t)a[ 0]) * a[ 2]) * 2 + + ((int128_t)a[ 1]) * a[ 1]; + int128_t t3 = (((int128_t)a[ 0]) * a[ 3] + + ((int128_t)a[ 1]) * a[ 2]) * 2; + int128_t t4 = (((int128_t)a[ 0]) * a[ 4] + + ((int128_t)a[ 1]) * a[ 3]) * 2 + + ((int128_t)a[ 2]) * a[ 2]; + int128_t t5 = (((int128_t)a[ 0]) * a[ 5] + + ((int128_t)a[ 1]) * a[ 4] + + ((int128_t)a[ 2]) * a[ 3]) * 2; + int128_t t6 = (((int128_t)a[ 0]) * a[ 6] + + ((int128_t)a[ 1]) * a[ 5] + + ((int128_t)a[ 2]) * a[ 4]) * 2 + + ((int128_t)a[ 3]) * a[ 3]; + int128_t t7 = (((int128_t)a[ 0]) * a[ 7] + + ((int128_t)a[ 1]) * a[ 6] + + ((int128_t)a[ 2]) * a[ 5] + + ((int128_t)a[ 3]) * a[ 4]) * 2; + int128_t t8 = (((int128_t)a[ 0]) * a[ 8] + + ((int128_t)a[ 1]) * a[ 7] + + ((int128_t)a[ 2]) * a[ 6] + + ((int128_t)a[ 3]) * a[ 5]) * 2 + + ((int128_t)a[ 4]) * a[ 4]; + int128_t t9 = (((int128_t)a[ 1]) * a[ 8] + + ((int128_t)a[ 2]) * a[ 7] + + ((int128_t)a[ 3]) * a[ 6] + + ((int128_t)a[ 4]) * a[ 5]) * 2; + int128_t t10 = (((int128_t)a[ 2]) * a[ 8] + + ((int128_t)a[ 3]) * a[ 7] + + ((int128_t)a[ 4]) * a[ 6]) * 2 + + ((int128_t)a[ 5]) * a[ 5]; + int128_t t11 = (((int128_t)a[ 3]) * a[ 8] + + ((int128_t)a[ 4]) * a[ 7] + + ((int128_t)a[ 5]) * a[ 6]) * 2; + int128_t t12 = (((int128_t)a[ 4]) * a[ 8] + + ((int128_t)a[ 5]) * a[ 7]) * 2 + + ((int128_t)a[ 6]) * a[ 6]; + int128_t t13 = (((int128_t)a[ 5]) * a[ 8] + + ((int128_t)a[ 6]) * a[ 7]) * 2; + int128_t t14 = (((int128_t)a[ 6]) * a[ 8]) * 2 + + ((int128_t)a[ 7]) * a[ 7]; + int128_t t15 = (((int128_t)a[ 7]) * a[ 8]) * 2; + int128_t t16 = ((int128_t)a[ 8]) * a[ 8]; + + t1 += t0 >> 57; r[ 0] = t0 & 0x1ffffffffffffffl; + t2 += t1 >> 57; r[ 1] = t1 & 0x1ffffffffffffffl; + t3 += t2 >> 57; r[ 2] = t2 & 0x1ffffffffffffffl; + t4 += t3 >> 57; r[ 3] = t3 & 0x1ffffffffffffffl; + t5 += t4 >> 57; r[ 4] = t4 & 0x1ffffffffffffffl; + t6 += t5 >> 57; r[ 5] = t5 & 0x1ffffffffffffffl; + t7 += t6 >> 57; r[ 6] = t6 & 0x1ffffffffffffffl; + t8 += t7 >> 57; r[ 7] = t7 & 0x1ffffffffffffffl; + t9 += t8 >> 57; r[ 8] = t8 & 0x1ffffffffffffffl; + t10 += t9 >> 57; r[ 9] = t9 & 0x1ffffffffffffffl; + t11 += t10 >> 57; r[10] = t10 & 0x1ffffffffffffffl; + t12 += t11 >> 57; r[11] = t11 & 0x1ffffffffffffffl; + t13 += t12 >> 57; r[12] = t12 & 0x1ffffffffffffffl; + t14 += t13 >> 57; r[13] = t13 & 0x1ffffffffffffffl; + t15 += t14 >> 57; r[14] = t14 & 0x1ffffffffffffffl; + t16 += t15 >> 57; r[15] = t15 & 0x1ffffffffffffffl; + r[17] = (sp_digit)(t16 >> 57); + r[16] = t16 & 0x1ffffffffffffffl; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_3072_add_9(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + r[ 0] = a[ 0] + b[ 0]; + r[ 1] = a[ 1] + b[ 1]; + r[ 2] = a[ 2] + b[ 2]; + r[ 3] = a[ 3] + b[ 3]; + r[ 4] = a[ 4] + b[ 4]; + r[ 5] = a[ 5] + b[ 5]; + r[ 6] = a[ 6] + b[ 6]; + r[ 7] = a[ 7] + b[ 7]; + r[ 8] = a[ 8] + b[ 8]; + + return 0; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_3072_add_18(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 16; i += 8) { + r[i + 0] = a[i + 0] + b[i + 0]; + r[i + 1] = a[i + 1] + b[i + 1]; + r[i + 2] = a[i + 2] + b[i + 2]; + r[i + 3] = a[i + 3] + b[i + 3]; + r[i + 4] = a[i + 4] + b[i + 4]; + r[i + 5] = a[i + 5] + b[i + 5]; + r[i + 6] = a[i + 6] + b[i + 6]; + r[i + 7] = a[i + 7] + b[i + 7]; + } + r[16] = a[16] + b[16]; + r[17] = a[17] + b[17]; + + return 0; +} + +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_3072_sub_18(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 16; i += 8) { + r[i + 0] = a[i + 0] - b[i + 0]; + r[i + 1] = a[i + 1] - b[i + 1]; + r[i + 2] = a[i + 2] - b[i + 2]; + r[i + 3] = a[i + 3] - b[i + 3]; + r[i + 4] = a[i + 4] - b[i + 4]; + r[i + 5] = a[i + 5] - b[i + 5]; + r[i + 6] = a[i + 6] - b[i + 6]; + r[i + 7] = a[i + 7] - b[i + 7]; + } + r[16] = a[16] - b[16]; + r[17] = a[17] - b[17]; + + return 0; +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_3072_mul_18(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[18]; + sp_digit* a1 = z1; + sp_digit b1[9]; + sp_digit* z2 = r + 18; + sp_3072_add_9(a1, a, &a[9]); + sp_3072_add_9(b1, b, &b[9]); + sp_3072_mul_9(z2, &a[9], &b[9]); + sp_3072_mul_9(z0, a, b); + sp_3072_mul_9(z1, a1, b1); + sp_3072_sub_18(z1, z1, z2); + sp_3072_sub_18(z1, z1, z0); + sp_3072_add_18(r + 9, r + 9, z1); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_3072_sqr_18(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z1[18]; + sp_digit* a1 = z1; + sp_digit* z2 = r + 18; + sp_3072_add_9(a1, a, &a[9]); + sp_3072_sqr_9(z2, &a[9]); + sp_3072_sqr_9(z0, a); + sp_3072_sqr_9(z1, a1); + sp_3072_sub_18(z1, z1, z2); + sp_3072_sub_18(z1, z1, z0); + sp_3072_add_18(r + 9, r + 9, z1); +} + +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_3072_sub_36(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 32; i += 8) { + r[i + 0] = a[i + 0] - b[i + 0]; + r[i + 1] = a[i + 1] - b[i + 1]; + r[i + 2] = a[i + 2] - b[i + 2]; + r[i + 3] = a[i + 3] - b[i + 3]; + r[i + 4] = a[i + 4] - b[i + 4]; + r[i + 5] = a[i + 5] - b[i + 5]; + r[i + 6] = a[i + 6] - b[i + 6]; + r[i + 7] = a[i + 7] - b[i + 7]; + } + r[32] = a[32] - b[32]; + r[33] = a[33] - b[33]; + r[34] = a[34] - b[34]; + r[35] = a[35] - b[35]; + + return 0; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_3072_add_36(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 32; i += 8) { + r[i + 0] = a[i + 0] + b[i + 0]; + r[i + 1] = a[i + 1] + b[i + 1]; + r[i + 2] = a[i + 2] + b[i + 2]; + r[i + 3] = a[i + 3] + b[i + 3]; + r[i + 4] = a[i + 4] + b[i + 4]; + r[i + 5] = a[i + 5] + b[i + 5]; + r[i + 6] = a[i + 6] + b[i + 6]; + r[i + 7] = a[i + 7] + b[i + 7]; + } + r[32] = a[32] + b[32]; + r[33] = a[33] + b[33]; + r[34] = a[34] + b[34]; + r[35] = a[35] + b[35]; + + return 0; +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_3072_mul_54(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit p0[36]; + sp_digit p1[36]; + sp_digit p2[36]; + sp_digit p3[36]; + sp_digit p4[36]; + sp_digit p5[36]; + sp_digit t0[36]; + sp_digit t1[36]; + sp_digit t2[36]; + sp_digit a0[18]; + sp_digit a1[18]; + sp_digit a2[18]; + sp_digit b0[18]; + sp_digit b1[18]; + sp_digit b2[18]; + sp_3072_add_18(a0, a, &a[18]); + sp_3072_add_18(b0, b, &b[18]); + sp_3072_add_18(a1, &a[18], &a[36]); + sp_3072_add_18(b1, &b[18], &b[36]); + sp_3072_add_18(a2, a0, &a[36]); + sp_3072_add_18(b2, b0, &b[36]); + sp_3072_mul_18(p0, a, b); + sp_3072_mul_18(p2, &a[18], &b[18]); + sp_3072_mul_18(p4, &a[36], &b[36]); + sp_3072_mul_18(p1, a0, b0); + sp_3072_mul_18(p3, a1, b1); + sp_3072_mul_18(p5, a2, b2); + XMEMSET(r, 0, sizeof(*r)*2*54); + sp_3072_sub_36(t0, p3, p2); + sp_3072_sub_36(t1, p1, p2); + sp_3072_sub_36(t2, p5, t0); + sp_3072_sub_36(t2, t2, t1); + sp_3072_sub_36(t0, t0, p4); + sp_3072_sub_36(t1, t1, p0); + sp_3072_add_36(r, r, p0); + sp_3072_add_36(&r[18], &r[18], t1); + sp_3072_add_36(&r[36], &r[36], t2); + sp_3072_add_36(&r[54], &r[54], t0); + sp_3072_add_36(&r[72], &r[72], p4); +} + +/* Square a into r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_3072_sqr_54(sp_digit* r, const sp_digit* a) +{ + sp_digit p0[36]; + sp_digit p1[36]; + sp_digit p2[36]; + sp_digit p3[36]; + sp_digit p4[36]; + sp_digit p5[36]; + sp_digit t0[36]; + sp_digit t1[36]; + sp_digit t2[36]; + sp_digit a0[18]; + sp_digit a1[18]; + sp_digit a2[18]; + sp_3072_add_18(a0, a, &a[18]); + sp_3072_add_18(a1, &a[18], &a[36]); + sp_3072_add_18(a2, a0, &a[36]); + sp_3072_sqr_18(p0, a); + sp_3072_sqr_18(p2, &a[18]); + sp_3072_sqr_18(p4, &a[36]); + sp_3072_sqr_18(p1, a0); + sp_3072_sqr_18(p3, a1); + sp_3072_sqr_18(p5, a2); + XMEMSET(r, 0, sizeof(*r)*2*54); + sp_3072_sub_36(t0, p3, p2); + sp_3072_sub_36(t1, p1, p2); + sp_3072_sub_36(t2, p5, t0); + sp_3072_sub_36(t2, t2, t1); + sp_3072_sub_36(t0, t0, p4); + sp_3072_sub_36(t1, t1, p0); + sp_3072_add_36(r, r, p0); + sp_3072_add_36(&r[18], &r[18], t1); + sp_3072_add_36(&r[36], &r[36], t2); + sp_3072_add_36(&r[54], &r[54], t0); + sp_3072_add_36(&r[72], &r[72], p4); +} + +#endif /* !WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_3072_add_54(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 54; i++) + r[i] = a[i] + b[i]; + + return 0; +} +#else +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_3072_add_54(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 48; i += 8) { + r[i + 0] = a[i + 0] + b[i + 0]; + r[i + 1] = a[i + 1] + b[i + 1]; + r[i + 2] = a[i + 2] + b[i + 2]; + r[i + 3] = a[i + 3] + b[i + 3]; + r[i + 4] = a[i + 4] + b[i + 4]; + r[i + 5] = a[i + 5] + b[i + 5]; + r[i + 6] = a[i + 6] + b[i + 6]; + r[i + 7] = a[i + 7] + b[i + 7]; + } + r[48] = a[48] + b[48]; + r[49] = a[49] + b[49]; + r[50] = a[50] + b[50]; + r[51] = a[51] + b[51]; + r[52] = a[52] + b[52]; + r[53] = a[53] + b[53]; + + return 0; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_3072_sub_54(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 54; i++) + r[i] = a[i] - b[i]; + + return 0; +} + +#else +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_3072_sub_54(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 48; i += 8) { + r[i + 0] = a[i + 0] - b[i + 0]; + r[i + 1] = a[i + 1] - b[i + 1]; + r[i + 2] = a[i + 2] - b[i + 2]; + r[i + 3] = a[i + 3] - b[i + 3]; + r[i + 4] = a[i + 4] - b[i + 4]; + r[i + 5] = a[i + 5] - b[i + 5]; + r[i + 6] = a[i + 6] - b[i + 6]; + r[i + 7] = a[i + 7] - b[i + 7]; + } + r[48] = a[48] - b[48]; + r[49] = a[49] - b[49]; + r[50] = a[50] - b[50]; + r[51] = a[51] - b[51]; + r[52] = a[52] - b[52]; + r[53] = a[53] - b[53]; + + return 0; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_3072_mul_54(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i, j, k; + int128_t c; + + c = ((int128_t)a[53]) * b[53]; + r[107] = (sp_digit)(c >> 57); + c = (c & 0x1ffffffffffffffl) << 57; + for (k = 105; k >= 0; k--) { + for (i = 53; i >= 0; i--) { + j = k - i; + if (j >= 54) + break; + if (j < 0) + continue; + + c += ((int128_t)a[i]) * b[j]; + } + r[k + 2] += c >> 114; + r[k + 1] = (c >> 57) & 0x1ffffffffffffffl; + c = (c & 0x1ffffffffffffffl) << 57; + } + r[0] = (sp_digit)(c >> 57); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_3072_sqr_54(sp_digit* r, const sp_digit* a) +{ + int i, j, k; + int128_t c; + + c = ((int128_t)a[53]) * a[53]; + r[107] = (sp_digit)(c >> 57); + c = (c & 0x1ffffffffffffffl) << 57; + for (k = 105; k >= 0; k--) { + for (i = 53; i >= 0; i--) { + j = k - i; + if (j >= 54 || i <= j) + break; + if (j < 0) + continue; + + c += ((int128_t)a[i]) * a[j] * 2; + } + if (i == j) + c += ((int128_t)a[i]) * a[i]; + + r[k + 2] += c >> 114; + r[k + 1] = (c >> 57) & 0x1ffffffffffffffl; + c = (c & 0x1ffffffffffffffl) << 57; + } + r[0] = (sp_digit)(c >> 57); +} + +#endif /* WOLFSSL_SP_SMALL */ +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_3072_add_27(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 27; i++) + r[i] = a[i] + b[i]; + + return 0; +} +#else +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_3072_add_27(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 24; i += 8) { + r[i + 0] = a[i + 0] + b[i + 0]; + r[i + 1] = a[i + 1] + b[i + 1]; + r[i + 2] = a[i + 2] + b[i + 2]; + r[i + 3] = a[i + 3] + b[i + 3]; + r[i + 4] = a[i + 4] + b[i + 4]; + r[i + 5] = a[i + 5] + b[i + 5]; + r[i + 6] = a[i + 6] + b[i + 6]; + r[i + 7] = a[i + 7] + b[i + 7]; + } + r[24] = a[24] + b[24]; + r[25] = a[25] + b[25]; + r[26] = a[26] + b[26]; + + return 0; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_3072_sub_27(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 27; i++) + r[i] = a[i] - b[i]; + + return 0; +} + +#else +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_3072_sub_27(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 24; i += 8) { + r[i + 0] = a[i + 0] - b[i + 0]; + r[i + 1] = a[i + 1] - b[i + 1]; + r[i + 2] = a[i + 2] - b[i + 2]; + r[i + 3] = a[i + 3] - b[i + 3]; + r[i + 4] = a[i + 4] - b[i + 4]; + r[i + 5] = a[i + 5] - b[i + 5]; + r[i + 6] = a[i + 6] - b[i + 6]; + r[i + 7] = a[i + 7] - b[i + 7]; + } + r[24] = a[24] - b[24]; + r[25] = a[25] - b[25]; + r[26] = a[26] - b[26]; + + return 0; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_3072_mul_27(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i, j, k; + int128_t c; + + c = ((int128_t)a[26]) * b[26]; + r[53] = (sp_digit)(c >> 57); + c = (c & 0x1ffffffffffffffl) << 57; + for (k = 51; k >= 0; k--) { + for (i = 26; i >= 0; i--) { + j = k - i; + if (j >= 27) + break; + if (j < 0) + continue; + + c += ((int128_t)a[i]) * b[j]; + } + r[k + 2] += c >> 114; + r[k + 1] = (c >> 57) & 0x1ffffffffffffffl; + c = (c & 0x1ffffffffffffffl) << 57; + } + r[0] = (sp_digit)(c >> 57); +} + +#else +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_3072_mul_27(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i, j; + int128_t t[54]; + + XMEMSET(t, 0, sizeof(t)); + for (i=0; i<27; i++) { + for (j=0; j<27; j++) + t[i+j] += ((int128_t)a[i]) * b[j]; + } + for (i=0; i<53; i++) { + r[i] = t[i] & 0x1ffffffffffffffl; + t[i+1] += t[i] >> 57; + } + r[53] = (sp_digit)t[53]; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_3072_sqr_27(sp_digit* r, const sp_digit* a) +{ + int i, j, k; + int128_t c; + + c = ((int128_t)a[26]) * a[26]; + r[53] = (sp_digit)(c >> 57); + c = (c & 0x1ffffffffffffffl) << 57; + for (k = 51; k >= 0; k--) { + for (i = 26; i >= 0; i--) { + j = k - i; + if (j >= 27 || i <= j) + break; + if (j < 0) + continue; + + c += ((int128_t)a[i]) * a[j] * 2; + } + if (i == j) + c += ((int128_t)a[i]) * a[i]; + + r[k + 2] += c >> 114; + r[k + 1] = (c >> 57) & 0x1ffffffffffffffl; + c = (c & 0x1ffffffffffffffl) << 57; + } + r[0] = (sp_digit)(c >> 57); +} + +#else +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_3072_sqr_27(sp_digit* r, const sp_digit* a) +{ + int i, j; + int128_t t[54]; + + XMEMSET(t, 0, sizeof(t)); + for (i=0; i<27; i++) { + for (j=0; j> 57; + } + r[53] = (sp_digit)t[53]; +} + +#endif /* WOLFSSL_SP_SMALL */ +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +/* Caclulate the bottom digit of -1/a mod 2^n. + * + * a A single precision number. + * rho Bottom word of inverse. + */ +static void sp_3072_mont_setup(sp_digit* a, sp_digit* rho) +{ + sp_digit x, b; + + b = a[0]; + x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ + x *= 2 - b * x; /* here x*a==1 mod 2**8 */ + x *= 2 - b * x; /* here x*a==1 mod 2**16 */ + x *= 2 - b * x; /* here x*a==1 mod 2**32 */ + x *= 2 - b * x; /* here x*a==1 mod 2**64 */ + x &= 0x1ffffffffffffffl; + + /* rho = -1/m mod b */ + *rho = (1L << 57) - x; +} + +/* Multiply a by scalar b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +SP_NOINLINE static void sp_3072_mul_d_54(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int128_t tb = b; + int128_t t = 0; + int i; + + for (i = 0; i < 54; i++) { + t += tb * a[i]; + r[i] = t & 0x1ffffffffffffffl; + t >>= 57; + } + r[54] = (sp_digit)t; +#else + int128_t tb = b; + int128_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] = t[0] & 0x1ffffffffffffffl; + for (i = 0; i < 48; i += 8) { + t[1] = tb * a[i+1]; + r[i+1] = (sp_digit)(t[0] >> 57) + (t[1] & 0x1ffffffffffffffl); + t[2] = tb * a[i+2]; + r[i+2] = (sp_digit)(t[1] >> 57) + (t[2] & 0x1ffffffffffffffl); + t[3] = tb * a[i+3]; + r[i+3] = (sp_digit)(t[2] >> 57) + (t[3] & 0x1ffffffffffffffl); + t[4] = tb * a[i+4]; + r[i+4] = (sp_digit)(t[3] >> 57) + (t[4] & 0x1ffffffffffffffl); + t[5] = tb * a[i+5]; + r[i+5] = (sp_digit)(t[4] >> 57) + (t[5] & 0x1ffffffffffffffl); + t[6] = tb * a[i+6]; + r[i+6] = (sp_digit)(t[5] >> 57) + (t[6] & 0x1ffffffffffffffl); + t[7] = tb * a[i+7]; + r[i+7] = (sp_digit)(t[6] >> 57) + (t[7] & 0x1ffffffffffffffl); + t[0] = tb * a[i+8]; + r[i+8] = (sp_digit)(t[7] >> 57) + (t[0] & 0x1ffffffffffffffl); + } + t[1] = tb * a[49]; + r[49] = (sp_digit)(t[0] >> 57) + (t[1] & 0x1ffffffffffffffl); + t[2] = tb * a[50]; + r[50] = (sp_digit)(t[1] >> 57) + (t[2] & 0x1ffffffffffffffl); + t[3] = tb * a[51]; + r[51] = (sp_digit)(t[2] >> 57) + (t[3] & 0x1ffffffffffffffl); + t[4] = tb * a[52]; + r[52] = (sp_digit)(t[3] >> 57) + (t[4] & 0x1ffffffffffffffl); + t[5] = tb * a[53]; + r[53] = (sp_digit)(t[4] >> 57) + (t[5] & 0x1ffffffffffffffl); + r[54] = (sp_digit)(t[5] >> 57); +#endif /* WOLFSSL_SP_SMALL */ +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +/* r = 2^n mod m where n is the number of bits to reduce by. + * Given m must be 3072 bits, just need to subtract. + * + * r A single precision number. + * m A signle precision number. + */ +static void sp_3072_mont_norm_27(sp_digit* r, sp_digit* m) +{ + /* Set r = 2^n - 1. */ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<26; i++) + r[i] = 0x1ffffffffffffffl; +#else + int i; + + for (i = 0; i < 24; i += 8) { + r[i + 0] = 0x1ffffffffffffffl; + r[i + 1] = 0x1ffffffffffffffl; + r[i + 2] = 0x1ffffffffffffffl; + r[i + 3] = 0x1ffffffffffffffl; + r[i + 4] = 0x1ffffffffffffffl; + r[i + 5] = 0x1ffffffffffffffl; + r[i + 6] = 0x1ffffffffffffffl; + r[i + 7] = 0x1ffffffffffffffl; + } + r[24] = 0x1ffffffffffffffl; + r[25] = 0x1ffffffffffffffl; +#endif + r[26] = 0x3fffffffffffffl; + + /* r = (2^n - 1) mod n */ + sp_3072_sub_27(r, r, m); + + /* Add one so r = 2^n mod m */ + r[0] += 1; +} + +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +static sp_digit sp_3072_cmp_27(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = 0; +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=26; i>=0; i--) + r |= (a[i] - b[i]) & (0 - !r); +#else + int i; + + r |= (a[26] - b[26]) & (0 - !r); + r |= (a[25] - b[25]) & (0 - !r); + r |= (a[24] - b[24]) & (0 - !r); + for (i = 16; i >= 0; i -= 8) { + r |= (a[i + 7] - b[i + 7]) & (0 - !r); + r |= (a[i + 6] - b[i + 6]) & (0 - !r); + r |= (a[i + 5] - b[i + 5]) & (0 - !r); + r |= (a[i + 4] - b[i + 4]) & (0 - !r); + r |= (a[i + 3] - b[i + 3]) & (0 - !r); + r |= (a[i + 2] - b[i + 2]) & (0 - !r); + r |= (a[i + 1] - b[i + 1]) & (0 - !r); + r |= (a[i + 0] - b[i + 0]) & (0 - !r); + } +#endif /* WOLFSSL_SP_SMALL */ + + return r; +} + +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +static void sp_3072_cond_sub_27(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i = 0; i < 27; i++) + r[i] = a[i] - (b[i] & m); +#else + int i; + + for (i = 0; i < 24; i += 8) { + r[i + 0] = a[i + 0] - (b[i + 0] & m); + r[i + 1] = a[i + 1] - (b[i + 1] & m); + r[i + 2] = a[i + 2] - (b[i + 2] & m); + r[i + 3] = a[i + 3] - (b[i + 3] & m); + r[i + 4] = a[i + 4] - (b[i + 4] & m); + r[i + 5] = a[i + 5] - (b[i + 5] & m); + r[i + 6] = a[i + 6] - (b[i + 6] & m); + r[i + 7] = a[i + 7] - (b[i + 7] & m); + } + r[24] = a[24] - (b[24] & m); + r[25] = a[25] - (b[25] & m); + r[26] = a[26] - (b[26] & m); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Mul a by scalar b and add into r. (r += a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +SP_NOINLINE static void sp_3072_mul_add_27(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int128_t tb = b; + int128_t t = 0; + int i; + + for (i = 0; i < 27; i++) { + t += (tb * a[i]) + r[i]; + r[i] = t & 0x1ffffffffffffffl; + t >>= 57; + } + r[27] += t; +#else + int128_t tb = b; + int128_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] += t[0] & 0x1ffffffffffffffl; + for (i = 0; i < 24; i += 8) { + t[1] = tb * a[i+1]; + r[i+1] += (t[0] >> 57) + (t[1] & 0x1ffffffffffffffl); + t[2] = tb * a[i+2]; + r[i+2] += (t[1] >> 57) + (t[2] & 0x1ffffffffffffffl); + t[3] = tb * a[i+3]; + r[i+3] += (t[2] >> 57) + (t[3] & 0x1ffffffffffffffl); + t[4] = tb * a[i+4]; + r[i+4] += (t[3] >> 57) + (t[4] & 0x1ffffffffffffffl); + t[5] = tb * a[i+5]; + r[i+5] += (t[4] >> 57) + (t[5] & 0x1ffffffffffffffl); + t[6] = tb * a[i+6]; + r[i+6] += (t[5] >> 57) + (t[6] & 0x1ffffffffffffffl); + t[7] = tb * a[i+7]; + r[i+7] += (t[6] >> 57) + (t[7] & 0x1ffffffffffffffl); + t[0] = tb * a[i+8]; + r[i+8] += (t[7] >> 57) + (t[0] & 0x1ffffffffffffffl); + } + t[1] = tb * a[25]; r[25] += (t[0] >> 57) + (t[1] & 0x1ffffffffffffffl); + t[2] = tb * a[26]; r[26] += (t[1] >> 57) + (t[2] & 0x1ffffffffffffffl); + r[27] += t[2] >> 57; +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Normalize the values in each word to 57. + * + * a Array of sp_digit to normalize. + */ +static void sp_3072_norm_27(sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + for (i = 0; i < 26; i++) { + a[i+1] += a[i] >> 57; + a[i] &= 0x1ffffffffffffffl; + } +#else + int i; + for (i = 0; i < 24; i += 8) { + a[i+1] += a[i+0] >> 57; a[i+0] &= 0x1ffffffffffffffl; + a[i+2] += a[i+1] >> 57; a[i+1] &= 0x1ffffffffffffffl; + a[i+3] += a[i+2] >> 57; a[i+2] &= 0x1ffffffffffffffl; + a[i+4] += a[i+3] >> 57; a[i+3] &= 0x1ffffffffffffffl; + a[i+5] += a[i+4] >> 57; a[i+4] &= 0x1ffffffffffffffl; + a[i+6] += a[i+5] >> 57; a[i+5] &= 0x1ffffffffffffffl; + a[i+7] += a[i+6] >> 57; a[i+6] &= 0x1ffffffffffffffl; + a[i+8] += a[i+7] >> 57; a[i+7] &= 0x1ffffffffffffffl; + a[i+9] += a[i+8] >> 57; a[i+8] &= 0x1ffffffffffffffl; + } + a[24+1] += a[24] >> 57; + a[24] &= 0x1ffffffffffffffl; + a[25+1] += a[25] >> 57; + a[25] &= 0x1ffffffffffffffl; +#endif +} + +/* Shift the result in the high 1536 bits down to the bottom. + * + * r A single precision number. + * a A single precision number. + */ +static void sp_3072_mont_shift_27(sp_digit* r, const sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + sp_digit n, s; + + s = a[27]; + n = a[26] >> 54; + for (i = 0; i < 26; i++) { + n += (s & 0x1ffffffffffffffl) << 3; + r[i] = n & 0x1ffffffffffffffl; + n >>= 57; + s = a[28 + i] + (s >> 57); + } + n += s << 3; + r[26] = n; +#else + sp_digit n, s; + int i; + + s = a[27]; n = a[26] >> 54; + for (i = 0; i < 24; i += 8) { + n += (s & 0x1ffffffffffffffl) << 3; r[i+0] = n & 0x1ffffffffffffffl; + n >>= 57; s = a[i+28] + (s >> 57); + n += (s & 0x1ffffffffffffffl) << 3; r[i+1] = n & 0x1ffffffffffffffl; + n >>= 57; s = a[i+29] + (s >> 57); + n += (s & 0x1ffffffffffffffl) << 3; r[i+2] = n & 0x1ffffffffffffffl; + n >>= 57; s = a[i+30] + (s >> 57); + n += (s & 0x1ffffffffffffffl) << 3; r[i+3] = n & 0x1ffffffffffffffl; + n >>= 57; s = a[i+31] + (s >> 57); + n += (s & 0x1ffffffffffffffl) << 3; r[i+4] = n & 0x1ffffffffffffffl; + n >>= 57; s = a[i+32] + (s >> 57); + n += (s & 0x1ffffffffffffffl) << 3; r[i+5] = n & 0x1ffffffffffffffl; + n >>= 57; s = a[i+33] + (s >> 57); + n += (s & 0x1ffffffffffffffl) << 3; r[i+6] = n & 0x1ffffffffffffffl; + n >>= 57; s = a[i+34] + (s >> 57); + n += (s & 0x1ffffffffffffffl) << 3; r[i+7] = n & 0x1ffffffffffffffl; + n >>= 57; s = a[i+35] + (s >> 57); + } + n += (s & 0x1ffffffffffffffl) << 3; r[24] = n & 0x1ffffffffffffffl; + n >>= 57; s = a[52] + (s >> 57); + n += (s & 0x1ffffffffffffffl) << 3; r[25] = n & 0x1ffffffffffffffl; + n >>= 57; s = a[53] + (s >> 57); + n += s << 3; r[26] = n; +#endif /* WOLFSSL_SP_SMALL */ + XMEMSET(&r[27], 0, sizeof(*r) * 27); +} + +/* Reduce the number back to 3072 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +static void sp_3072_mont_reduce_27(sp_digit* a, sp_digit* m, sp_digit mp) +{ + int i; + sp_digit mu; + + for (i=0; i<26; i++) { + mu = (a[i] * mp) & 0x1ffffffffffffffl; + sp_3072_mul_add_27(a+i, m, mu); + a[i+1] += a[i] >> 57; + } + mu = (a[i] * mp) & 0x3fffffffffffffl; + sp_3072_mul_add_27(a+i, m, mu); + a[i+1] += a[i] >> 57; + a[i] &= 0x1ffffffffffffffl; + + sp_3072_mont_shift_27(a, a); + sp_3072_cond_sub_27(a, a, m, 0 - ((a[26] >> 54) > 0)); + sp_3072_norm_27(a); +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_3072_mont_mul_27(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_3072_mul_27(r, a, b); + sp_3072_mont_reduce_27(r, m, mp); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_3072_mont_sqr_27(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_3072_sqr_27(r, a); + sp_3072_mont_reduce_27(r, m, mp); +} + +/* Multiply a by scalar b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +SP_NOINLINE static void sp_3072_mul_d_27(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int128_t tb = b; + int128_t t = 0; + int i; + + for (i = 0; i < 27; i++) { + t += tb * a[i]; + r[i] = t & 0x1ffffffffffffffl; + t >>= 57; + } + r[27] = (sp_digit)t; +#else + int128_t tb = b; + int128_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] = t[0] & 0x1ffffffffffffffl; + for (i = 0; i < 24; i += 8) { + t[1] = tb * a[i+1]; + r[i+1] = (sp_digit)(t[0] >> 57) + (t[1] & 0x1ffffffffffffffl); + t[2] = tb * a[i+2]; + r[i+2] = (sp_digit)(t[1] >> 57) + (t[2] & 0x1ffffffffffffffl); + t[3] = tb * a[i+3]; + r[i+3] = (sp_digit)(t[2] >> 57) + (t[3] & 0x1ffffffffffffffl); + t[4] = tb * a[i+4]; + r[i+4] = (sp_digit)(t[3] >> 57) + (t[4] & 0x1ffffffffffffffl); + t[5] = tb * a[i+5]; + r[i+5] = (sp_digit)(t[4] >> 57) + (t[5] & 0x1ffffffffffffffl); + t[6] = tb * a[i+6]; + r[i+6] = (sp_digit)(t[5] >> 57) + (t[6] & 0x1ffffffffffffffl); + t[7] = tb * a[i+7]; + r[i+7] = (sp_digit)(t[6] >> 57) + (t[7] & 0x1ffffffffffffffl); + t[0] = tb * a[i+8]; + r[i+8] = (sp_digit)(t[7] >> 57) + (t[0] & 0x1ffffffffffffffl); + } + t[1] = tb * a[25]; + r[25] = (sp_digit)(t[0] >> 57) + (t[1] & 0x1ffffffffffffffl); + t[2] = tb * a[26]; + r[26] = (sp_digit)(t[1] >> 57) + (t[2] & 0x1ffffffffffffffl); + r[27] = (sp_digit)(t[2] >> 57); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Conditionally add a and b using the mask m. + * m is -1 to add and 0 when not. + * + * r A single precision number representing conditional add result. + * a A single precision number to add with. + * b A single precision number to add. + * m Mask value to apply. + */ +static void sp_3072_cond_add_27(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i = 0; i < 27; i++) + r[i] = a[i] + (b[i] & m); +#else + int i; + + for (i = 0; i < 24; i += 8) { + r[i + 0] = a[i + 0] + (b[i + 0] & m); + r[i + 1] = a[i + 1] + (b[i + 1] & m); + r[i + 2] = a[i + 2] + (b[i + 2] & m); + r[i + 3] = a[i + 3] + (b[i + 3] & m); + r[i + 4] = a[i + 4] + (b[i + 4] & m); + r[i + 5] = a[i + 5] + (b[i + 5] & m); + r[i + 6] = a[i + 6] + (b[i + 6] & m); + r[i + 7] = a[i + 7] + (b[i + 7] & m); + } + r[24] = a[24] + (b[24] & m); + r[25] = a[25] + (b[25] & m); + r[26] = a[26] + (b[26] & m); +#endif /* WOLFSSL_SP_SMALL */ +} + +#ifdef WOLFSSL_SP_DIV_64 +static WC_INLINE sp_digit sp_3072_div_word_27(sp_digit d1, sp_digit d0, + sp_digit div) +{ + sp_digit d, r, t, dv; + int128_t t0, t1; + + /* dv has 29 bits. */ + dv = (div >> 28) + 1; + /* All 57 bits from d1 and top 6 bits from d0. */ + d = (d1 << 6) | (d0 >> 51); + r = d / dv; + d -= r * dv; + /* Up to 34 bits in r */ + /* Next 23 bits from d0. */ + d <<= 23; + r <<= 23; + d |= (d0 >> 28) & ((1 << 23) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 57 bits in r */ + + /* Handle rounding error with dv - top part */ + t0 = ((int128_t)d1 << 57) + d0; + t1 = (int128_t)r * div; + t1 = t0 - t1; + t = (sp_digit)(t1 >> 28) / dv; + r += t; + + /* Handle rounding error with dv - bottom 64 bits */ + t1 = (sp_digit)t0 - (r * div); + t = (sp_digit)t1 / div; + r += t; + + return r; +} +#endif /* WOLFSSL_SP_DIV_64 */ + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. + */ +static int sp_3072_div_27(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + int i; +#ifndef WOLFSSL_SP_DIV_64 + int128_t d1; +#endif + sp_digit div, r1; +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* td; +#else + sp_digit t1d[54], t2d[27 + 1]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (3 * 27 + 1), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td != NULL) { + t1 = td; + t2 = td + 2 * 27; + } + else + err = MEMORY_E; +#else + t1 = t1d; + t2 = t2d; +#endif + + (void)m; + + if (err == MP_OKAY) { + div = d[26]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 27); + for (i=26; i>=0; i--) { + t1[27 + i] += t1[27 + i - 1] >> 57; + t1[27 + i - 1] &= 0x1ffffffffffffffl; +#ifndef WOLFSSL_SP_DIV_64 + d1 = t1[27 + i]; + d1 <<= 57; + d1 += t1[27 + i - 1]; + r1 = (sp_digit)(d1 / div); +#else + r1 = sp_3072_div_word_27(t1[27 + i], t1[27 + i - 1], div); +#endif + + sp_3072_mul_d_27(t2, d, r1); + sp_3072_sub_27(&t1[i], &t1[i], t2); + t1[27 + i] -= t2[27]; + t1[27 + i] += t1[27 + i - 1] >> 57; + t1[27 + i - 1] &= 0x1ffffffffffffffl; + r1 = (((-t1[27 + i]) << 57) - t1[27 + i - 1]) / div; + r1++; + sp_3072_mul_d_27(t2, d, r1); + sp_3072_add_27(&t1[i], &t1[i], t2); + t1[27 + i] += t1[27 + i - 1] >> 57; + t1[27 + i - 1] &= 0x1ffffffffffffffl; + } + t1[27 - 1] += t1[27 - 2] >> 57; + t1[27 - 2] &= 0x1ffffffffffffffl; + r1 = t1[27 - 1] / div; + + sp_3072_mul_d_27(t2, d, r1); + sp_3072_sub_27(t1, t1, t2); + XMEMCPY(r, t1, sizeof(*r) * 2 * 27); + for (i=0; i<25; i++) { + r[i+1] += r[i] >> 57; + r[i] &= 0x1ffffffffffffffl; + } + sp_3072_cond_add_27(r, r, d, 0 - (r[26] < 0)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. + */ +static int sp_3072_mod_27(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_3072_div_27(a, m, NULL, r); +} + +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_3072_mod_exp_27(sp_digit* r, sp_digit* a, sp_digit* e, int bits, + sp_digit* m, int reduceA) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* td; + sp_digit* t[3]; + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + + td = (sp_digit*)XMALLOC(sizeof(*td) * 3 * 27 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + XMEMSET(td, 0, sizeof(*td) * 3 * 27 * 2); + + norm = t[0] = td; + t[1] = &td[27 * 2]; + t[2] = &td[2 * 27 * 2]; + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_27(norm, m); + + if (reduceA) + err = sp_3072_mod_27(t[1], a, m); + else + XMEMCPY(t[1], a, sizeof(sp_digit) * 27); + } + if (err == MP_OKAY) { + sp_3072_mul_27(t[1], t[1], norm); + err = sp_3072_mod_27(t[1], t[1], m); + } + + if (err == MP_OKAY) { + i = bits / 57; + c = bits % 57; + n = e[i--] << (57 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = e[i--]; + c = 57; + } + + y = (n >> 56) & 1; + n <<= 1; + + sp_3072_mont_mul_27(t[y^1], t[0], t[1], m, mp); + + XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), + sizeof(*t[2]) * 27 * 2); + sp_3072_mont_sqr_27(t[2], t[2], m, mp); + XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), t[2], + sizeof(*t[2]) * 27 * 2); + } + + sp_3072_mont_reduce_27(t[0], m, mp); + n = sp_3072_cmp_27(t[0], m); + sp_3072_cond_sub_27(t[0], t[0], m, (n < 0) - 1); + XMEMCPY(r, t[0], sizeof(*r) * 27 * 2); + + } + + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return err; +#elif defined(WOLFSSL_SP_CACHE_RESISTANT) +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[3][54]; +#else + sp_digit* td; + sp_digit* t[3]; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(*td) * 3 * 27 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + t[0] = td; + t[1] = &td[27 * 2]; + t[2] = &td[2 * 27 * 2]; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_27(norm, m); + + if (reduceA) { + err = sp_3072_mod_27(t[1], a, m); + if (err == MP_OKAY) { + sp_3072_mul_27(t[1], t[1], norm); + err = sp_3072_mod_27(t[1], t[1], m); + } + } + else { + sp_3072_mul_27(t[1], a, norm); + err = sp_3072_mod_27(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + i = bits / 57; + c = bits % 57; + n = e[i--] << (57 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = e[i--]; + c = 57; + } + + y = (n >> 56) & 1; + n <<= 1; + + sp_3072_mont_mul_27(t[y^1], t[0], t[1], m, mp); + + XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), sizeof(t[2])); + sp_3072_mont_sqr_27(t[2], t[2], m, mp); + XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), t[2], sizeof(t[2])); + } + + sp_3072_mont_reduce_27(t[0], m, mp); + n = sp_3072_cmp_27(t[0], m); + sp_3072_cond_sub_27(t[0], t[0], m, (n < 0) - 1); + XMEMCPY(r, t[0], sizeof(t[0])); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +#else +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][54]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit rt[54]; + sp_digit mp = 1; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 54, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<32; i++) + t[i] = td + i * 54; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_27(norm, m); + + if (reduceA) { + err = sp_3072_mod_27(t[1], a, m); + if (err == MP_OKAY) { + sp_3072_mul_27(t[1], t[1], norm); + err = sp_3072_mod_27(t[1], t[1], m); + } + } + else { + sp_3072_mul_27(t[1], a, norm); + err = sp_3072_mod_27(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_3072_mont_sqr_27(t[ 2], t[ 1], m, mp); + sp_3072_mont_mul_27(t[ 3], t[ 2], t[ 1], m, mp); + sp_3072_mont_sqr_27(t[ 4], t[ 2], m, mp); + sp_3072_mont_mul_27(t[ 5], t[ 3], t[ 2], m, mp); + sp_3072_mont_sqr_27(t[ 6], t[ 3], m, mp); + sp_3072_mont_mul_27(t[ 7], t[ 4], t[ 3], m, mp); + sp_3072_mont_sqr_27(t[ 8], t[ 4], m, mp); + sp_3072_mont_mul_27(t[ 9], t[ 5], t[ 4], m, mp); + sp_3072_mont_sqr_27(t[10], t[ 5], m, mp); + sp_3072_mont_mul_27(t[11], t[ 6], t[ 5], m, mp); + sp_3072_mont_sqr_27(t[12], t[ 6], m, mp); + sp_3072_mont_mul_27(t[13], t[ 7], t[ 6], m, mp); + sp_3072_mont_sqr_27(t[14], t[ 7], m, mp); + sp_3072_mont_mul_27(t[15], t[ 8], t[ 7], m, mp); + sp_3072_mont_sqr_27(t[16], t[ 8], m, mp); + sp_3072_mont_mul_27(t[17], t[ 9], t[ 8], m, mp); + sp_3072_mont_sqr_27(t[18], t[ 9], m, mp); + sp_3072_mont_mul_27(t[19], t[10], t[ 9], m, mp); + sp_3072_mont_sqr_27(t[20], t[10], m, mp); + sp_3072_mont_mul_27(t[21], t[11], t[10], m, mp); + sp_3072_mont_sqr_27(t[22], t[11], m, mp); + sp_3072_mont_mul_27(t[23], t[12], t[11], m, mp); + sp_3072_mont_sqr_27(t[24], t[12], m, mp); + sp_3072_mont_mul_27(t[25], t[13], t[12], m, mp); + sp_3072_mont_sqr_27(t[26], t[13], m, mp); + sp_3072_mont_mul_27(t[27], t[14], t[13], m, mp); + sp_3072_mont_sqr_27(t[28], t[14], m, mp); + sp_3072_mont_mul_27(t[29], t[15], t[14], m, mp); + sp_3072_mont_sqr_27(t[30], t[15], m, mp); + sp_3072_mont_mul_27(t[31], t[16], t[15], m, mp); + + bits = ((bits + 4) / 5) * 5; + i = ((bits + 56) / 57) - 1; + c = bits % 57; + if (c == 0) + c = 57; + if (i < 27) + n = e[i--] << (64 - c); + else { + n = 0; + i--; + } + if (c < 5) { + n |= e[i--] << (7 - c); + c += 57; + } + y = (n >> 59) & 0x1f; + n <<= 5; + c -= 5; + XMEMCPY(rt, t[y], sizeof(rt)); + for (; i>=0 || c>=5; ) { + if (c < 5) { + n |= e[i--] << (7 - c); + c += 57; + } + y = (n >> 59) & 0x1f; + n <<= 5; + c -= 5; + + sp_3072_mont_sqr_27(rt, rt, m, mp); + sp_3072_mont_sqr_27(rt, rt, m, mp); + sp_3072_mont_sqr_27(rt, rt, m, mp); + sp_3072_mont_sqr_27(rt, rt, m, mp); + sp_3072_mont_sqr_27(rt, rt, m, mp); + + sp_3072_mont_mul_27(rt, rt, t[y], m, mp); + } + + sp_3072_mont_reduce_27(rt, m, mp); + n = sp_3072_cmp_27(rt, m); + sp_3072_cond_sub_27(rt, rt, m, (n < 0) - 1); + XMEMCPY(r, rt, sizeof(rt)); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +#endif +} + +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +/* r = 2^n mod m where n is the number of bits to reduce by. + * Given m must be 3072 bits, just need to subtract. + * + * r A single precision number. + * m A signle precision number. + */ +static void sp_3072_mont_norm_54(sp_digit* r, sp_digit* m) +{ + /* Set r = 2^n - 1. */ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<53; i++) + r[i] = 0x1ffffffffffffffl; +#else + int i; + + for (i = 0; i < 48; i += 8) { + r[i + 0] = 0x1ffffffffffffffl; + r[i + 1] = 0x1ffffffffffffffl; + r[i + 2] = 0x1ffffffffffffffl; + r[i + 3] = 0x1ffffffffffffffl; + r[i + 4] = 0x1ffffffffffffffl; + r[i + 5] = 0x1ffffffffffffffl; + r[i + 6] = 0x1ffffffffffffffl; + r[i + 7] = 0x1ffffffffffffffl; + } + r[48] = 0x1ffffffffffffffl; + r[49] = 0x1ffffffffffffffl; + r[50] = 0x1ffffffffffffffl; + r[51] = 0x1ffffffffffffffl; + r[52] = 0x1ffffffffffffffl; +#endif + r[53] = 0x7ffffffffffffl; + + /* r = (2^n - 1) mod n */ + sp_3072_sub_54(r, r, m); + + /* Add one so r = 2^n mod m */ + r[0] += 1; +} + +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +static sp_digit sp_3072_cmp_54(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = 0; +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=53; i>=0; i--) + r |= (a[i] - b[i]) & (0 - !r); +#else + int i; + + r |= (a[53] - b[53]) & (0 - !r); + r |= (a[52] - b[52]) & (0 - !r); + r |= (a[51] - b[51]) & (0 - !r); + r |= (a[50] - b[50]) & (0 - !r); + r |= (a[49] - b[49]) & (0 - !r); + r |= (a[48] - b[48]) & (0 - !r); + for (i = 40; i >= 0; i -= 8) { + r |= (a[i + 7] - b[i + 7]) & (0 - !r); + r |= (a[i + 6] - b[i + 6]) & (0 - !r); + r |= (a[i + 5] - b[i + 5]) & (0 - !r); + r |= (a[i + 4] - b[i + 4]) & (0 - !r); + r |= (a[i + 3] - b[i + 3]) & (0 - !r); + r |= (a[i + 2] - b[i + 2]) & (0 - !r); + r |= (a[i + 1] - b[i + 1]) & (0 - !r); + r |= (a[i + 0] - b[i + 0]) & (0 - !r); + } +#endif /* WOLFSSL_SP_SMALL */ + + return r; +} + +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +static void sp_3072_cond_sub_54(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i = 0; i < 54; i++) + r[i] = a[i] - (b[i] & m); +#else + int i; + + for (i = 0; i < 48; i += 8) { + r[i + 0] = a[i + 0] - (b[i + 0] & m); + r[i + 1] = a[i + 1] - (b[i + 1] & m); + r[i + 2] = a[i + 2] - (b[i + 2] & m); + r[i + 3] = a[i + 3] - (b[i + 3] & m); + r[i + 4] = a[i + 4] - (b[i + 4] & m); + r[i + 5] = a[i + 5] - (b[i + 5] & m); + r[i + 6] = a[i + 6] - (b[i + 6] & m); + r[i + 7] = a[i + 7] - (b[i + 7] & m); + } + r[48] = a[48] - (b[48] & m); + r[49] = a[49] - (b[49] & m); + r[50] = a[50] - (b[50] & m); + r[51] = a[51] - (b[51] & m); + r[52] = a[52] - (b[52] & m); + r[53] = a[53] - (b[53] & m); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Mul a by scalar b and add into r. (r += a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +SP_NOINLINE static void sp_3072_mul_add_54(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int128_t tb = b; + int128_t t = 0; + int i; + + for (i = 0; i < 54; i++) { + t += (tb * a[i]) + r[i]; + r[i] = t & 0x1ffffffffffffffl; + t >>= 57; + } + r[54] += t; +#else + int128_t tb = b; + int128_t t[8]; + int i; + + t[0] = tb * a[0]; r[0] += t[0] & 0x1ffffffffffffffl; + for (i = 0; i < 48; i += 8) { + t[1] = tb * a[i+1]; + r[i+1] += (t[0] >> 57) + (t[1] & 0x1ffffffffffffffl); + t[2] = tb * a[i+2]; + r[i+2] += (t[1] >> 57) + (t[2] & 0x1ffffffffffffffl); + t[3] = tb * a[i+3]; + r[i+3] += (t[2] >> 57) + (t[3] & 0x1ffffffffffffffl); + t[4] = tb * a[i+4]; + r[i+4] += (t[3] >> 57) + (t[4] & 0x1ffffffffffffffl); + t[5] = tb * a[i+5]; + r[i+5] += (t[4] >> 57) + (t[5] & 0x1ffffffffffffffl); + t[6] = tb * a[i+6]; + r[i+6] += (t[5] >> 57) + (t[6] & 0x1ffffffffffffffl); + t[7] = tb * a[i+7]; + r[i+7] += (t[6] >> 57) + (t[7] & 0x1ffffffffffffffl); + t[0] = tb * a[i+8]; + r[i+8] += (t[7] >> 57) + (t[0] & 0x1ffffffffffffffl); + } + t[1] = tb * a[49]; r[49] += (t[0] >> 57) + (t[1] & 0x1ffffffffffffffl); + t[2] = tb * a[50]; r[50] += (t[1] >> 57) + (t[2] & 0x1ffffffffffffffl); + t[3] = tb * a[51]; r[51] += (t[2] >> 57) + (t[3] & 0x1ffffffffffffffl); + t[4] = tb * a[52]; r[52] += (t[3] >> 57) + (t[4] & 0x1ffffffffffffffl); + t[5] = tb * a[53]; r[53] += (t[4] >> 57) + (t[5] & 0x1ffffffffffffffl); + r[54] += t[5] >> 57; +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Normalize the values in each word to 57. + * + * a Array of sp_digit to normalize. + */ +static void sp_3072_norm_54(sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + for (i = 0; i < 53; i++) { + a[i+1] += a[i] >> 57; + a[i] &= 0x1ffffffffffffffl; + } +#else + int i; + for (i = 0; i < 48; i += 8) { + a[i+1] += a[i+0] >> 57; a[i+0] &= 0x1ffffffffffffffl; + a[i+2] += a[i+1] >> 57; a[i+1] &= 0x1ffffffffffffffl; + a[i+3] += a[i+2] >> 57; a[i+2] &= 0x1ffffffffffffffl; + a[i+4] += a[i+3] >> 57; a[i+3] &= 0x1ffffffffffffffl; + a[i+5] += a[i+4] >> 57; a[i+4] &= 0x1ffffffffffffffl; + a[i+6] += a[i+5] >> 57; a[i+5] &= 0x1ffffffffffffffl; + a[i+7] += a[i+6] >> 57; a[i+6] &= 0x1ffffffffffffffl; + a[i+8] += a[i+7] >> 57; a[i+7] &= 0x1ffffffffffffffl; + a[i+9] += a[i+8] >> 57; a[i+8] &= 0x1ffffffffffffffl; + } + a[48+1] += a[48] >> 57; + a[48] &= 0x1ffffffffffffffl; + a[49+1] += a[49] >> 57; + a[49] &= 0x1ffffffffffffffl; + a[50+1] += a[50] >> 57; + a[50] &= 0x1ffffffffffffffl; + a[51+1] += a[51] >> 57; + a[51] &= 0x1ffffffffffffffl; + a[52+1] += a[52] >> 57; + a[52] &= 0x1ffffffffffffffl; +#endif +} + +/* Shift the result in the high 3072 bits down to the bottom. + * + * r A single precision number. + * a A single precision number. + */ +static void sp_3072_mont_shift_54(sp_digit* r, const sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + int128_t n = a[53] >> 51; + n += ((int128_t)a[54]) << 6; + + for (i = 0; i < 53; i++) { + r[i] = n & 0x1ffffffffffffffl; + n >>= 57; + n += ((int128_t)a[55 + i]) << 6; + } + r[53] = (sp_digit)n; +#else + int i; + int128_t n = a[53] >> 51; + n += ((int128_t)a[54]) << 6; + for (i = 0; i < 48; i += 8) { + r[i + 0] = n & 0x1ffffffffffffffl; + n >>= 57; n += ((int128_t)a[i + 55]) << 6; + r[i + 1] = n & 0x1ffffffffffffffl; + n >>= 57; n += ((int128_t)a[i + 56]) << 6; + r[i + 2] = n & 0x1ffffffffffffffl; + n >>= 57; n += ((int128_t)a[i + 57]) << 6; + r[i + 3] = n & 0x1ffffffffffffffl; + n >>= 57; n += ((int128_t)a[i + 58]) << 6; + r[i + 4] = n & 0x1ffffffffffffffl; + n >>= 57; n += ((int128_t)a[i + 59]) << 6; + r[i + 5] = n & 0x1ffffffffffffffl; + n >>= 57; n += ((int128_t)a[i + 60]) << 6; + r[i + 6] = n & 0x1ffffffffffffffl; + n >>= 57; n += ((int128_t)a[i + 61]) << 6; + r[i + 7] = n & 0x1ffffffffffffffl; + n >>= 57; n += ((int128_t)a[i + 62]) << 6; + } + r[48] = n & 0x1ffffffffffffffl; n >>= 57; n += ((int128_t)a[103]) << 6; + r[49] = n & 0x1ffffffffffffffl; n >>= 57; n += ((int128_t)a[104]) << 6; + r[50] = n & 0x1ffffffffffffffl; n >>= 57; n += ((int128_t)a[105]) << 6; + r[51] = n & 0x1ffffffffffffffl; n >>= 57; n += ((int128_t)a[106]) << 6; + r[52] = n & 0x1ffffffffffffffl; n >>= 57; n += ((int128_t)a[107]) << 6; + r[53] = (sp_digit)n; +#endif /* WOLFSSL_SP_SMALL */ + XMEMSET(&r[54], 0, sizeof(*r) * 54); +} + +/* Reduce the number back to 3072 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +static void sp_3072_mont_reduce_54(sp_digit* a, sp_digit* m, sp_digit mp) +{ + int i; + sp_digit mu; + +#ifdef WOLFSSL_SP_DH + if (mp != 1) { + for (i=0; i<53; i++) { + mu = (a[i] * mp) & 0x1ffffffffffffffl; + sp_3072_mul_add_54(a+i, m, mu); + a[i+1] += a[i] >> 57; + } + mu = (a[i] * mp) & 0x7ffffffffffffl; + sp_3072_mul_add_54(a+i, m, mu); + a[i+1] += a[i] >> 57; + a[i] &= 0x1ffffffffffffffl; + } + else { + for (i=0; i<53; i++) { + mu = a[i] & 0x1ffffffffffffffl; + sp_3072_mul_add_54(a+i, m, mu); + a[i+1] += a[i] >> 57; + } + mu = a[i] & 0x7ffffffffffffl; + sp_3072_mul_add_54(a+i, m, mu); + a[i+1] += a[i] >> 57; + a[i] &= 0x1ffffffffffffffl; + } +#else + for (i=0; i<53; i++) { + mu = (a[i] * mp) & 0x1ffffffffffffffl; + sp_3072_mul_add_54(a+i, m, mu); + a[i+1] += a[i] >> 57; + } + mu = (a[i] * mp) & 0x7ffffffffffffl; + sp_3072_mul_add_54(a+i, m, mu); + a[i+1] += a[i] >> 57; + a[i] &= 0x1ffffffffffffffl; +#endif + + sp_3072_mont_shift_54(a, a); + sp_3072_cond_sub_54(a, a, m, 0 - ((a[53] >> 51) > 0)); + sp_3072_norm_54(a); +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_3072_mont_mul_54(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_3072_mul_54(r, a, b); + sp_3072_mont_reduce_54(r, m, mp); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_3072_mont_sqr_54(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_3072_sqr_54(r, a); + sp_3072_mont_reduce_54(r, m, mp); +} + +/* Conditionally add a and b using the mask m. + * m is -1 to add and 0 when not. + * + * r A single precision number representing conditional add result. + * a A single precision number to add with. + * b A single precision number to add. + * m Mask value to apply. + */ +static void sp_3072_cond_add_54(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i = 0; i < 54; i++) + r[i] = a[i] + (b[i] & m); +#else + int i; + + for (i = 0; i < 48; i += 8) { + r[i + 0] = a[i + 0] + (b[i + 0] & m); + r[i + 1] = a[i + 1] + (b[i + 1] & m); + r[i + 2] = a[i + 2] + (b[i + 2] & m); + r[i + 3] = a[i + 3] + (b[i + 3] & m); + r[i + 4] = a[i + 4] + (b[i + 4] & m); + r[i + 5] = a[i + 5] + (b[i + 5] & m); + r[i + 6] = a[i + 6] + (b[i + 6] & m); + r[i + 7] = a[i + 7] + (b[i + 7] & m); + } + r[48] = a[48] + (b[48] & m); + r[49] = a[49] + (b[49] & m); + r[50] = a[50] + (b[50] & m); + r[51] = a[51] + (b[51] & m); + r[52] = a[52] + (b[52] & m); + r[53] = a[53] + (b[53] & m); +#endif /* WOLFSSL_SP_SMALL */ +} + +#ifdef WOLFSSL_SP_DIV_64 +static WC_INLINE sp_digit sp_3072_div_word_54(sp_digit d1, sp_digit d0, + sp_digit div) +{ + sp_digit d, r, t, dv; + int128_t t0, t1; + + /* dv has 29 bits. */ + dv = (div >> 28) + 1; + /* All 57 bits from d1 and top 6 bits from d0. */ + d = (d1 << 6) | (d0 >> 51); + r = d / dv; + d -= r * dv; + /* Up to 34 bits in r */ + /* Next 23 bits from d0. */ + d <<= 23; + r <<= 23; + d |= (d0 >> 28) & ((1 << 23) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 57 bits in r */ + + /* Handle rounding error with dv - top part */ + t0 = ((int128_t)d1 << 57) + d0; + t1 = (int128_t)r * div; + t1 = t0 - t1; + t = (sp_digit)(t1 >> 28) / dv; + r += t; + + /* Handle rounding error with dv - bottom 64 bits */ + t1 = (sp_digit)t0 - (r * div); + t = (sp_digit)t1 / div; + r += t; + + return r; +} +#endif /* WOLFSSL_SP_DIV_64 */ + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. + */ +static int sp_3072_div_54(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + int i; +#ifndef WOLFSSL_SP_DIV_64 + int128_t d1; +#endif + sp_digit div, r1; +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* td; +#else + sp_digit t1d[108], t2d[54 + 1]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (3 * 54 + 1), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td != NULL) { + t1 = td; + t2 = td + 2 * 54; + } + else + err = MEMORY_E; +#else + t1 = t1d; + t2 = t2d; +#endif + + (void)m; + + if (err == MP_OKAY) { + div = d[53]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 54); + for (i=53; i>=0; i--) { + t1[54 + i] += t1[54 + i - 1] >> 57; + t1[54 + i - 1] &= 0x1ffffffffffffffl; +#ifndef WOLFSSL_SP_DIV_64 + d1 = t1[54 + i]; + d1 <<= 57; + d1 += t1[54 + i - 1]; + r1 = (sp_digit)(d1 / div); +#else + r1 = sp_3072_div_word_54(t1[54 + i], t1[54 + i - 1], div); +#endif + + sp_3072_mul_d_54(t2, d, r1); + sp_3072_sub_54(&t1[i], &t1[i], t2); + t1[54 + i] -= t2[54]; + t1[54 + i] += t1[54 + i - 1] >> 57; + t1[54 + i - 1] &= 0x1ffffffffffffffl; + r1 = (((-t1[54 + i]) << 57) - t1[54 + i - 1]) / div; + r1++; + sp_3072_mul_d_54(t2, d, r1); + sp_3072_add_54(&t1[i], &t1[i], t2); + t1[54 + i] += t1[54 + i - 1] >> 57; + t1[54 + i - 1] &= 0x1ffffffffffffffl; + } + t1[54 - 1] += t1[54 - 2] >> 57; + t1[54 - 2] &= 0x1ffffffffffffffl; + r1 = t1[54 - 1] / div; + + sp_3072_mul_d_54(t2, d, r1); + sp_3072_sub_54(t1, t1, t2); + XMEMCPY(r, t1, sizeof(*r) * 2 * 54); + for (i=0; i<52; i++) { + r[i+1] += r[i] >> 57; + r[i] &= 0x1ffffffffffffffl; + } + sp_3072_cond_add_54(r, r, d, 0 - (r[53] < 0)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. + */ +static int sp_3072_mod_54(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_3072_div_54(a, m, NULL, r); +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \ + defined(WOLFSSL_HAVE_SP_DH) +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_3072_mod_exp_54(sp_digit* r, sp_digit* a, sp_digit* e, int bits, + sp_digit* m, int reduceA) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* td; + sp_digit* t[3]; + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + + td = (sp_digit*)XMALLOC(sizeof(*td) * 3 * 54 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + XMEMSET(td, 0, sizeof(*td) * 3 * 54 * 2); + + norm = t[0] = td; + t[1] = &td[54 * 2]; + t[2] = &td[2 * 54 * 2]; + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_54(norm, m); + + if (reduceA) + err = sp_3072_mod_54(t[1], a, m); + else + XMEMCPY(t[1], a, sizeof(sp_digit) * 54); + } + if (err == MP_OKAY) { + sp_3072_mul_54(t[1], t[1], norm); + err = sp_3072_mod_54(t[1], t[1], m); + } + + if (err == MP_OKAY) { + i = bits / 57; + c = bits % 57; + n = e[i--] << (57 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = e[i--]; + c = 57; + } + + y = (n >> 56) & 1; + n <<= 1; + + sp_3072_mont_mul_54(t[y^1], t[0], t[1], m, mp); + + XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), + sizeof(*t[2]) * 54 * 2); + sp_3072_mont_sqr_54(t[2], t[2], m, mp); + XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), t[2], + sizeof(*t[2]) * 54 * 2); + } + + sp_3072_mont_reduce_54(t[0], m, mp); + n = sp_3072_cmp_54(t[0], m); + sp_3072_cond_sub_54(t[0], t[0], m, (n < 0) - 1); + XMEMCPY(r, t[0], sizeof(*r) * 54 * 2); + + } + + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); + + return err; +#elif defined(WOLFSSL_SP_CACHE_RESISTANT) +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[3][108]; +#else + sp_digit* td; + sp_digit* t[3]; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(*td) * 3 * 54 * 2, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + t[0] = td; + t[1] = &td[54 * 2]; + t[2] = &td[2 * 54 * 2]; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_54(norm, m); + + if (reduceA) { + err = sp_3072_mod_54(t[1], a, m); + if (err == MP_OKAY) { + sp_3072_mul_54(t[1], t[1], norm); + err = sp_3072_mod_54(t[1], t[1], m); + } + } + else { + sp_3072_mul_54(t[1], a, norm); + err = sp_3072_mod_54(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + i = bits / 57; + c = bits % 57; + n = e[i--] << (57 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = e[i--]; + c = 57; + } + + y = (n >> 56) & 1; + n <<= 1; + + sp_3072_mont_mul_54(t[y^1], t[0], t[1], m, mp); + + XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), sizeof(t[2])); + sp_3072_mont_sqr_54(t[2], t[2], m, mp); + XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), t[2], sizeof(t[2])); + } + + sp_3072_mont_reduce_54(t[0], m, mp); + n = sp_3072_cmp_54(t[0], m); + sp_3072_cond_sub_54(t[0], t[0], m, (n < 0) - 1); + XMEMCPY(r, t[0], sizeof(t[0])); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +#else +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][108]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit rt[108]; + sp_digit mp = 1; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 108, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<32; i++) + t[i] = td + i * 108; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_54(norm, m); + + if (reduceA) { + err = sp_3072_mod_54(t[1], a, m); + if (err == MP_OKAY) { + sp_3072_mul_54(t[1], t[1], norm); + err = sp_3072_mod_54(t[1], t[1], m); + } + } + else { + sp_3072_mul_54(t[1], a, norm); + err = sp_3072_mod_54(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_3072_mont_sqr_54(t[ 2], t[ 1], m, mp); + sp_3072_mont_mul_54(t[ 3], t[ 2], t[ 1], m, mp); + sp_3072_mont_sqr_54(t[ 4], t[ 2], m, mp); + sp_3072_mont_mul_54(t[ 5], t[ 3], t[ 2], m, mp); + sp_3072_mont_sqr_54(t[ 6], t[ 3], m, mp); + sp_3072_mont_mul_54(t[ 7], t[ 4], t[ 3], m, mp); + sp_3072_mont_sqr_54(t[ 8], t[ 4], m, mp); + sp_3072_mont_mul_54(t[ 9], t[ 5], t[ 4], m, mp); + sp_3072_mont_sqr_54(t[10], t[ 5], m, mp); + sp_3072_mont_mul_54(t[11], t[ 6], t[ 5], m, mp); + sp_3072_mont_sqr_54(t[12], t[ 6], m, mp); + sp_3072_mont_mul_54(t[13], t[ 7], t[ 6], m, mp); + sp_3072_mont_sqr_54(t[14], t[ 7], m, mp); + sp_3072_mont_mul_54(t[15], t[ 8], t[ 7], m, mp); + sp_3072_mont_sqr_54(t[16], t[ 8], m, mp); + sp_3072_mont_mul_54(t[17], t[ 9], t[ 8], m, mp); + sp_3072_mont_sqr_54(t[18], t[ 9], m, mp); + sp_3072_mont_mul_54(t[19], t[10], t[ 9], m, mp); + sp_3072_mont_sqr_54(t[20], t[10], m, mp); + sp_3072_mont_mul_54(t[21], t[11], t[10], m, mp); + sp_3072_mont_sqr_54(t[22], t[11], m, mp); + sp_3072_mont_mul_54(t[23], t[12], t[11], m, mp); + sp_3072_mont_sqr_54(t[24], t[12], m, mp); + sp_3072_mont_mul_54(t[25], t[13], t[12], m, mp); + sp_3072_mont_sqr_54(t[26], t[13], m, mp); + sp_3072_mont_mul_54(t[27], t[14], t[13], m, mp); + sp_3072_mont_sqr_54(t[28], t[14], m, mp); + sp_3072_mont_mul_54(t[29], t[15], t[14], m, mp); + sp_3072_mont_sqr_54(t[30], t[15], m, mp); + sp_3072_mont_mul_54(t[31], t[16], t[15], m, mp); + + bits = ((bits + 4) / 5) * 5; + i = ((bits + 56) / 57) - 1; + c = bits % 57; + if (c == 0) + c = 57; + if (i < 54) + n = e[i--] << (64 - c); + else { + n = 0; + i--; + } + if (c < 5) { + n |= e[i--] << (7 - c); + c += 57; + } + y = (n >> 59) & 0x1f; + n <<= 5; + c -= 5; + XMEMCPY(rt, t[y], sizeof(rt)); + for (; i>=0 || c>=5; ) { + if (c < 5) { + n |= e[i--] << (7 - c); + c += 57; + } + y = (n >> 59) & 0x1f; + n <<= 5; + c -= 5; + + sp_3072_mont_sqr_54(rt, rt, m, mp); + sp_3072_mont_sqr_54(rt, rt, m, mp); + sp_3072_mont_sqr_54(rt, rt, m, mp); + sp_3072_mont_sqr_54(rt, rt, m, mp); + sp_3072_mont_sqr_54(rt, rt, m, mp); + + sp_3072_mont_mul_54(rt, rt, t[y], m, mp); + } + + sp_3072_mont_reduce_54(rt, m, mp); + n = sp_3072_cmp_54(rt, m); + sp_3072_cond_sub_54(rt, rt, m, (n < 0) - 1); + XMEMCPY(r, rt, sizeof(rt)); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +#endif +} +#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || */ + /* WOLFSSL_HAVE_SP_DH */ + +#if defined(WOLFSSL_HAVE_SP_RSA) && !defined(SP_RSA_PRIVATE_EXP_D) && \ + !defined(RSA_LOW_MEM) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_3072_mask_27(sp_digit* r, sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<27; i++) + r[i] = a[i] & m; +#else + int i; + + for (i = 0; i < 24; i += 8) { + r[i+0] = a[i+0] & m; + r[i+1] = a[i+1] & m; + r[i+2] = a[i+2] & m; + r[i+3] = a[i+3] & m; + r[i+4] = a[i+4] & m; + r[i+5] = a[i+5] & m; + r[i+6] = a[i+6] & m; + r[i+7] = a[i+7] & m; + } + r[24] = a[24] & m; + r[25] = a[25] & m; + r[26] = a[26] & m; +#endif +} + +#endif +#ifdef WOLFSSL_HAVE_SP_RSA +/* RSA public key operation. + * + * in Array of bytes representing the number to exponentiate, base. + * inLen Number of bytes in base. + * em Public exponent. + * mm Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 384 bytes long. + * outLen Number of bytes in result. + * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when + * an array is too long and MEMORY_E when dynamic memory allocation fails. + */ +int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm, + byte* out, word32* outLen) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* d = NULL; + sp_digit* a; + sp_digit* m; + sp_digit* r; + sp_digit* norm; + sp_digit e[1]; + sp_digit mp; + int i; + int err = MP_OKAY; + + if (*outLen < 384) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(em) > 57 || inLen > 384 || + mp_count_bits(mm) != 3072)) + err = MP_READ_E; + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 54 * 5, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + a = d; + r = a + 54 * 2; + m = r + 54 * 2; + norm = r; + + sp_3072_from_bin(a, 54, in, inLen); +#if DIGIT_BIT >= 57 + e[0] = (sp_digit)em->dp[0]; +#else + e[0] = (sp_digit)em->dp[0]; + if (em->used > 1) + e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT; +#endif + if (e[0] == 0) + err = MP_EXPTMOD_E; + } + + if (err == MP_OKAY) { + sp_3072_from_mp(m, 54, mm); + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_54(norm, m); + } + if (err == MP_OKAY) { + sp_3072_mul_54(a, a, norm); + err = sp_3072_mod_54(a, a, m); + } + if (err == MP_OKAY) { + for (i=56; i>=0; i--) + if (e[0] >> i) + break; + + XMEMCPY(r, a, sizeof(sp_digit) * 54 * 2); + for (i--; i>=0; i--) { + sp_3072_mont_sqr_54(r, r, m, mp); + + if (((e[0] >> i) & 1) == 1) + sp_3072_mont_mul_54(r, r, a, m, mp); + } + sp_3072_mont_reduce_54(r, m, mp); + mp = sp_3072_cmp_54(r, m); + sp_3072_cond_sub_54(r, r, m, (mp < 0) - 1); + + sp_3072_to_bin(r, out); + *outLen = 384; + } + + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + + return err; +#else +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit ad[108], md[54], rd[108]; +#else + sp_digit* d = NULL; +#endif + sp_digit* a; + sp_digit* m; + sp_digit* r; + sp_digit e[1]; + int err = MP_OKAY; + + if (*outLen < 384) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(em) > 57 || inLen > 384 || + mp_count_bits(mm) != 3072)) + err = MP_READ_E; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 54 * 5, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + a = d; + r = a + 54 * 2; + m = r + 54 * 2; + } +#else + a = ad; + m = md; + r = rd; +#endif + + if (err == MP_OKAY) { + sp_3072_from_bin(a, 54, in, inLen); +#if DIGIT_BIT >= 57 + e[0] = (sp_digit)em->dp[0]; +#else + e[0] = (sp_digit)em->dp[0]; + if (em->used > 1) + e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT; +#endif + if (e[0] == 0) + err = MP_EXPTMOD_E; + } + if (err == MP_OKAY) { + sp_3072_from_mp(m, 54, mm); + + if (e[0] == 0x3) { + if (err == MP_OKAY) { + sp_3072_sqr_54(r, a); + err = sp_3072_mod_54(r, r, m); + } + if (err == MP_OKAY) { + sp_3072_mul_54(r, a, r); + err = sp_3072_mod_54(r, r, m); + } + } + else { + sp_digit* norm = r; + int i; + sp_digit mp; + + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_54(norm, m); + + if (err == MP_OKAY) { + sp_3072_mul_54(a, a, norm); + err = sp_3072_mod_54(a, a, m); + } + + if (err == MP_OKAY) { + for (i=56; i>=0; i--) + if (e[0] >> i) + break; + + XMEMCPY(r, a, sizeof(sp_digit) * 108); + for (i--; i>=0; i--) { + sp_3072_mont_sqr_54(r, r, m, mp); + + if (((e[0] >> i) & 1) == 1) + sp_3072_mont_mul_54(r, r, a, m, mp); + } + sp_3072_mont_reduce_54(r, m, mp); + mp = sp_3072_cmp_54(r, m); + sp_3072_cond_sub_54(r, r, m, (mp < 0) - 1); + } + } + } + + if (err == MP_OKAY) { + sp_3072_to_bin(r, out); + *outLen = 384; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_RSA); +#endif + + return err; +#endif /* WOLFSSL_SP_SMALL */ +} + +#ifndef WOLFSSL_RSA_PUBLIC_ONLY +/* RSA private key operation. + * + * in Array of bytes representing the number to exponentiate, base. + * inLen Number of bytes in base. + * dm Private exponent. + * pm First prime. + * qm Second prime. + * dpm First prime's CRT exponent. + * dqm Second prime's CRT exponent. + * qim Inverse of second prime mod p. + * mm Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 384 bytes long. + * outLen Number of bytes in result. + * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when + * an array is too long and MEMORY_E when dynamic memory allocation fails. + */ +int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, + mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm, + byte* out, word32* outLen) +{ +#if defined(SP_RSA_PRIVATE_EXP_D) || defined(RSA_LOW_MEM) +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* a; + sp_digit* d = NULL; + sp_digit* m; + sp_digit* r; + int err = MP_OKAY; + + (void)pm; + (void)qm; + (void)dpm; + (void)dqm; + (void)qim; + + if (*outLen < 384) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(dm) > 3072 || inLen > 384 || + mp_count_bits(mm) != 3072)) + err = MP_READ_E; + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 54 * 4, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + a = d + 54; + m = a + 54; + r = a; + + sp_3072_from_bin(a, 54, in, inLen); + sp_3072_from_mp(d, 54, dm); + sp_3072_from_mp(m, 54, mm); + err = sp_3072_mod_exp_54(r, a, d, 3072, m, 0); + } + if (err == MP_OKAY) { + sp_3072_to_bin(r, out); + *outLen = 384; + } + + if (d != NULL) { + XMEMSET(d, 0, sizeof(sp_digit) * 54); + XFREE(d, NULL, DYNAMIC_TYPE_RSA); + } + + return err; +#else + sp_digit a[108], d[54], m[54]; + sp_digit* r = a; + int err = MP_OKAY; + + (void)pm; + (void)qm; + (void)dpm; + (void)dqm; + (void)qim; + + if (*outLen < 384) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(dm) > 3072 || inLen > 384 || + mp_count_bits(mm) != 3072)) + err = MP_READ_E; + + if (err == MP_OKAY) { + sp_3072_from_bin(a, 54, in, inLen); + sp_3072_from_mp(d, 54, dm); + sp_3072_from_mp(m, 54, mm); + err = sp_3072_mod_exp_54(r, a, d, 3072, m, 0); + } + + if (err == MP_OKAY) { + sp_3072_to_bin(r, out); + *outLen = 384; + } + + XMEMSET(d, 0, sizeof(sp_digit) * 54); + + return err; +#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */ +#else +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* t = NULL; + sp_digit* a; + sp_digit* p; + sp_digit* q; + sp_digit* dp; + sp_digit* dq; + sp_digit* qi; + sp_digit* tmp; + sp_digit* tmpa; + sp_digit* tmpb; + sp_digit* r; + int err = MP_OKAY; + + (void)dm; + (void)mm; + + if (*outLen < 384) + err = MP_TO_E; + if (err == MP_OKAY && (inLen > 384 || mp_count_bits(mm) != 3072)) + err = MP_READ_E; + + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 27 * 11, NULL, + DYNAMIC_TYPE_RSA); + if (t == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + a = t; + p = a + 54 * 2; + q = p + 27; + qi = dq = dp = q + 27; + tmpa = qi + 27; + tmpb = tmpa + 54; + + tmp = t; + r = tmp + 54; + + sp_3072_from_bin(a, 54, in, inLen); + sp_3072_from_mp(p, 27, pm); + sp_3072_from_mp(q, 27, qm); + sp_3072_from_mp(dp, 27, dpm); + err = sp_3072_mod_exp_27(tmpa, a, dp, 1536, p, 1); + } + if (err == MP_OKAY) { + sp_3072_from_mp(dq, 27, dqm); + err = sp_3072_mod_exp_27(tmpb, a, dq, 1536, q, 1); + } + if (err == MP_OKAY) { + sp_3072_sub_27(tmpa, tmpa, tmpb); + sp_3072_mask_27(tmp, p, tmpa[26] >> 63); + sp_3072_add_27(tmpa, tmpa, tmp); + + sp_3072_from_mp(qi, 27, qim); + sp_3072_mul_27(tmpa, tmpa, qi); + err = sp_3072_mod_27(tmpa, tmpa, p); + } + + if (err == MP_OKAY) { + sp_3072_mul_27(tmpa, q, tmpa); + sp_3072_add_54(r, tmpb, tmpa); + sp_3072_norm_54(r); + + sp_3072_to_bin(r, out); + *outLen = 384; + } + + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_digit) * 27 * 11); + XFREE(t, NULL, DYNAMIC_TYPE_RSA); + } + + return err; +#else + sp_digit a[54 * 2]; + sp_digit p[27], q[27], dp[27], dq[27], qi[27]; + sp_digit tmp[54], tmpa[54], tmpb[54]; + sp_digit* r = a; + int err = MP_OKAY; + + (void)dm; + (void)mm; + + if (*outLen < 384) + err = MP_TO_E; + if (err == MP_OKAY && (inLen > 384 || mp_count_bits(mm) != 3072)) + err = MP_READ_E; + + if (err == MP_OKAY) { + sp_3072_from_bin(a, 54, in, inLen); + sp_3072_from_mp(p, 27, pm); + sp_3072_from_mp(q, 27, qm); + sp_3072_from_mp(dp, 27, dpm); + sp_3072_from_mp(dq, 27, dqm); + sp_3072_from_mp(qi, 27, qim); + + err = sp_3072_mod_exp_27(tmpa, a, dp, 1536, p, 1); + } + if (err == MP_OKAY) + err = sp_3072_mod_exp_27(tmpb, a, dq, 1536, q, 1); + + if (err == MP_OKAY) { + sp_3072_sub_27(tmpa, tmpa, tmpb); + sp_3072_mask_27(tmp, p, tmpa[26] >> 63); + sp_3072_add_27(tmpa, tmpa, tmp); + sp_3072_mul_27(tmpa, tmpa, qi); + err = sp_3072_mod_27(tmpa, tmpa, p); + } + + if (err == MP_OKAY) { + sp_3072_mul_27(tmpa, tmpa, q); + sp_3072_add_54(r, tmpb, tmpa); + sp_3072_norm_54(r); + + sp_3072_to_bin(r, out); + *outLen = 384; + } + + XMEMSET(tmpa, 0, sizeof(tmpa)); + XMEMSET(tmpb, 0, sizeof(tmpb)); + XMEMSET(p, 0, sizeof(p)); + XMEMSET(q, 0, sizeof(q)); + XMEMSET(dp, 0, sizeof(dp)); + XMEMSET(dq, 0, sizeof(dq)); + XMEMSET(qi, 0, sizeof(qi)); + + return err; +#endif /* WOLFSSL_SP_SMALL || defined(WOLFSSL_SMALL_STACK) */ +#endif /* SP_RSA_PRIVATE_EXP_D || RSA_LOW_MEM */ +} + +#endif /* !WOLFSSL_RSA_PUBLIC_ONLY */ +#endif /* WOLFSSL_HAVE_SP_RSA */ +#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \ + !defined(WOLFSSL_RSA_PUBLIC_ONLY)) +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_3072_to_mp(sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (3072 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { +#if DIGIT_BIT == 57 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 54); + r->used = 54; + mp_clamp(r); +#elif DIGIT_BIT < 57 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 54; i++) { + r->dp[j] |= a[i] << s; + r->dp[j] &= (1l << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + while (s + DIGIT_BIT <= 57) { + s += DIGIT_BIT; + r->dp[j] &= (1l << DIGIT_BIT) - 1; + r->dp[++j] = a[i] >> s; + } + s = 57 - s; + } + r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 54; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 57 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && DIGIT_BIT != 64 + r->dp[j] &= (1l << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 57 - s; + } + else + s += 57; + } + r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returs 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ +#ifdef WOLFSSL_SP_SMALL + int err = MP_OKAY; + sp_digit* d = NULL; + sp_digit* b; + sp_digit* e; + sp_digit* m; + sp_digit* r; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 3072 || expBits > 3072 || + mp_count_bits(mod) != 3072) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 54 * 4, NULL, DYNAMIC_TYPE_DH); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + b = d; + e = b + 54 * 2; + m = e + 54; + r = b; + + sp_3072_from_mp(b, 54, base); + sp_3072_from_mp(e, 54, exp); + sp_3072_from_mp(m, 54, mod); + + err = sp_3072_mod_exp_54(r, b, e, mp_count_bits(exp), m, 0); + } + + if (err == MP_OKAY) { + err = sp_3072_to_mp(r, res); + } + + if (d != NULL) { + XMEMSET(e, 0, sizeof(sp_digit) * 54); + XFREE(d, NULL, DYNAMIC_TYPE_DH); + } + return err; +#else +#ifndef WOLFSSL_SMALL_STACK + sp_digit bd[108], ed[54], md[54]; +#else + sp_digit* d = NULL; +#endif + sp_digit* b; + sp_digit* e; + sp_digit* m; + sp_digit* r; + int err = MP_OKAY; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 3072 || expBits > 3072 || + mp_count_bits(mod) != 3072) { + err = MP_READ_E; + } + +#ifdef WOLFSSL_SMALL_STACK + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 54 * 4, NULL, DYNAMIC_TYPE_DH); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + b = d; + e = b + 54 * 2; + m = e + 54; + r = b; + } +#else + r = b = bd; + e = ed; + m = md; +#endif + + if (err == MP_OKAY) { + sp_3072_from_mp(b, 54, base); + sp_3072_from_mp(e, 54, exp); + sp_3072_from_mp(m, 54, mod); + + err = sp_3072_mod_exp_54(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + err = sp_3072_to_mp(r, res); + } + + XMEMSET(e, 0, sizeof(sp_digit) * 54); + +#ifdef WOLFSSL_SMALL_STACK + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_DH); +#endif + + return err; +#endif +} + +#ifdef WOLFSSL_HAVE_SP_DH +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. + * exp Array of bytes that is the exponent. + * expLen Length of data, in bytes, in exponent. + * mod Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 384 bytes long. + * outLen Length, in bytes, of exponentiation result. + * returs 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen, + mp_int* mod, byte* out, word32* outLen) +{ +#ifdef WOLFSSL_SP_SMALL + int err = MP_OKAY; + sp_digit* d = NULL; + sp_digit* b; + sp_digit* e; + sp_digit* m; + sp_digit* r; + word32 i; + + if (mp_count_bits(base) > 3072 || expLen > 384 || + mp_count_bits(mod) != 3072) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 54 * 4, NULL, DYNAMIC_TYPE_DH); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + b = d; + e = b + 54 * 2; + m = e + 54; + r = b; + + sp_3072_from_mp(b, 54, base); + sp_3072_from_bin(e, 54, exp, expLen); + sp_3072_from_mp(m, 54, mod); + + err = sp_3072_mod_exp_54(r, b, e, expLen * 8, m, 0); + } + + if (err == MP_OKAY) { + sp_3072_to_bin(r, out); + *outLen = 384; + for (i=0; i<384 && out[i] == 0; i++) { + } + *outLen -= i; + XMEMMOVE(out, out + i, *outLen); + } + + if (d != NULL) { + XMEMSET(e, 0, sizeof(sp_digit) * 54); + XFREE(d, NULL, DYNAMIC_TYPE_DH); + } + return err; +#else +#ifndef WOLFSSL_SMALL_STACK + sp_digit bd[108], ed[54], md[54]; +#else + sp_digit* d = NULL; +#endif + sp_digit* b; + sp_digit* e; + sp_digit* m; + sp_digit* r; + word32 i; + int err = MP_OKAY; + + if (mp_count_bits(base) > 3072 || expLen > 384 || + mp_count_bits(mod) != 3072) { + err = MP_READ_E; + } + +#ifdef WOLFSSL_SMALL_STACK + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 54 * 4, NULL, DYNAMIC_TYPE_DH); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + b = d; + e = b + 54 * 2; + m = e + 54; + r = b; + } +#else + r = b = bd; + e = ed; + m = md; +#endif + + if (err == MP_OKAY) { + sp_3072_from_mp(b, 54, base); + sp_3072_from_bin(e, 54, exp, expLen); + sp_3072_from_mp(m, 54, mod); + + err = sp_3072_mod_exp_54(r, b, e, expLen * 8, m, 0); + } + + if (err == MP_OKAY) { + sp_3072_to_bin(r, out); + *outLen = 384; + for (i=0; i<384 && out[i] == 0; i++) { + } + *outLen -= i; + XMEMMOVE(out, out + i, *outLen); + } + + XMEMSET(e, 0, sizeof(sp_digit) * 54); + +#ifdef WOLFSSL_SMALL_STACK + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_DH); +#endif + + return err; +#endif +} +#endif /* WOLFSSL_HAVE_SP_DH */ + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returs 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ +#ifdef WOLFSSL_SP_SMALL + int err = MP_OKAY; + sp_digit* d = NULL; + sp_digit* b; + sp_digit* e; + sp_digit* m; + sp_digit* r; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 1536 || expBits > 1536 || + mp_count_bits(mod) != 1536) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 27 * 4, NULL, DYNAMIC_TYPE_DH); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + b = d; + e = b + 27 * 2; + m = e + 27; + r = b; + + sp_3072_from_mp(b, 27, base); + sp_3072_from_mp(e, 27, exp); + sp_3072_from_mp(m, 27, mod); + + err = sp_3072_mod_exp_27(r, b, e, mp_count_bits(exp), m, 0); + } + + if (err == MP_OKAY) { + XMEMSET(r + 27, 0, sizeof(*r) * 27); + err = sp_3072_to_mp(r, res); + } + + if (d != NULL) { + XMEMSET(e, 0, sizeof(sp_digit) * 27); + XFREE(d, NULL, DYNAMIC_TYPE_DH); + } + return err; +#else +#ifndef WOLFSSL_SMALL_STACK + sp_digit bd[54], ed[27], md[27]; +#else + sp_digit* d = NULL; +#endif + sp_digit* b; + sp_digit* e; + sp_digit* m; + sp_digit* r; + int err = MP_OKAY; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 1536 || expBits > 1536 || + mp_count_bits(mod) != 1536) { + err = MP_READ_E; + } + +#ifdef WOLFSSL_SMALL_STACK + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(*d) * 27 * 4, NULL, DYNAMIC_TYPE_DH); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + b = d; + e = b + 27 * 2; + m = e + 27; + r = b; + } +#else + r = b = bd; + e = ed; + m = md; +#endif + + if (err == MP_OKAY) { + sp_3072_from_mp(b, 27, base); + sp_3072_from_mp(e, 27, exp); + sp_3072_from_mp(m, 27, mod); + + err = sp_3072_mod_exp_27(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + XMEMSET(r + 27, 0, sizeof(*r) * 27); + err = sp_3072_to_mp(r, res); + } + + XMEMSET(e, 0, sizeof(sp_digit) * 27); + +#ifdef WOLFSSL_SMALL_STACK + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_DH); +#endif + + return err; +#endif +} + +#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ + +#endif /* !WOLFSSL_SP_NO_3072 */ + +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +#ifdef WOLFSSL_HAVE_SP_ECC +#ifndef WOLFSSL_SP_NO_256 + +/* Point structure to use. */ +typedef struct sp_point { + sp_digit x[2 * 5]; + sp_digit y[2 * 5]; + sp_digit z[2 * 5]; + int infinity; +} sp_point; + +/* The modulus (prime) of the curve P256. */ +static sp_digit p256_mod[5] = { + 0xfffffffffffffl,0x00fffffffffffl,0x0000000000000l,0x0001000000000l, + 0x0ffffffff0000l +}; +#ifndef WOLFSSL_SP_SMALL +/* The Montogmery normalizer for modulus of the curve P256. */ +static sp_digit p256_norm_mod[5] = { + 0x0000000000001l,0xff00000000000l,0xfffffffffffffl,0xfffefffffffffl, + 0x000000000ffffl +}; +#endif /* WOLFSSL_SP_SMALL */ +/* The Montogmery multiplier for modulus of the curve P256. */ +static sp_digit p256_mp_mod = 0x0000000000001; +#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ + defined(HAVE_ECC_VERIFY) +/* The order of the curve P256. */ +static sp_digit p256_order[5] = { + 0x9cac2fc632551l,0xada7179e84f3bl,0xfffffffbce6fal,0x0000fffffffffl, + 0x0ffffffff0000l +}; +#endif +/* The order of the curve P256 minus 2. */ +static sp_digit p256_order2[5] = { + 0x9cac2fc63254fl,0xada7179e84f3bl,0xfffffffbce6fal,0x0000fffffffffl, + 0x0ffffffff0000l +}; +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +/* The Montogmery normalizer for order of the curve P256. */ +static sp_digit p256_norm_order[5] = { + 0x6353d039cdaafl,0x5258e8617b0c4l,0x0000000431905l,0xffff000000000l, + 0x000000000ffffl +}; +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +/* The Montogmery multiplier for order of the curve P256. */ +static sp_digit p256_mp_order = 0x1c8aaee00bc4fl; +#endif +/* The base point of curve P256. */ +static sp_point p256_base = { + /* X ordinate */ + { + 0x13945d898c296l,0x812deb33a0f4al,0x3a440f277037dl,0x4247f8bce6e56l, + 0x06b17d1f2e12cl + }, + /* Y ordinate */ + { + 0x6406837bf51f5l,0x576b315ececbbl,0xc0f9e162bce33l,0x7f9b8ee7eb4a7l, + 0x04fe342e2fe1al + }, + /* Z ordinate */ + { + 0x0000000000001l,0x0000000000000l,0x0000000000000l,0x0000000000000l, + 0x0000000000000l + }, + /* infinity */ + 0 +}; +#if defined(HAVE_ECC_CHECK_KEY) || defined(HAVE_COMP_KEY) +static sp_digit p256_b[5] = { + 0xe3c3e27d2604bl,0xb0cc53b0f63bcl,0x69886bc651d06l,0x93e7b3ebbd557l, + 0x05ac635d8aa3al +}; +#endif + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) +/* Allocate memory for point and return error. */ +#define sp_ecc_point_new(heap, sp, p) \ + ((p = (sp_point*)XMALLOC(sizeof(sp_point), heap, DYNAMIC_TYPE_ECC)) \ + == NULL) ? MEMORY_E : MP_OKAY +#else +/* Set pointer to data and return no error. */ +#define sp_ecc_point_new(heap, sp, p) ((p = &sp) == NULL) ? MEMORY_E : MP_OKAY +#endif + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) +/* If valid pointer then clear point data if requested and free data. */ +#define sp_ecc_point_free(p, clear, heap) \ + do { \ + if (p != NULL) { \ + if (clear) \ + XMEMSET(p, 0, sizeof(*p)); \ + XFREE(p, heap, DYNAMIC_TYPE_ECC); \ + } \ + } \ + while (0) +#else +/* Clear point data if requested. */ +#define sp_ecc_point_free(p, clear, heap) \ + do { \ + if (clear) \ + XMEMSET(p, 0, sizeof(*p)); \ + } \ + while (0) +#endif + +/* Multiply a number by Montogmery normalizer mod modulus (prime). + * + * r The resulting Montgomery form number. + * a The number to convert. + * m The modulus (prime). + * returns MEMORY_E when memory allocation fails and MP_OKAY otherwise. + */ +static int sp_256_mod_mul_norm_5(sp_digit* r, sp_digit* a, sp_digit* m) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + int64_t* td; +#else + int64_t td[8]; + int64_t a32d[8]; +#endif + int64_t* t; + int64_t* a32; + int64_t o; + int err = MP_OKAY; + + (void)m; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + td = (int64_t*)XMALLOC(sizeof(int64_t) * 2 * 8, NULL, DYNAMIC_TYPE_ECC); + if (td != NULL) { + t = td; + a32 = td + 8; + } + else + err = MEMORY_E; +#else + t = td; + a32 = a32d; +#endif + + if (err == MP_OKAY) { + a32[0] = (sp_digit)(a[0]) & 0xffffffff; + a32[1] = (sp_digit)(a[0] >> 32); + a32[1] |= a[1] << 20; + a32[1] &= 0xffffffff; + a32[2] = (sp_digit)(a[1] >> 12) & 0xffffffff; + a32[3] = (sp_digit)(a[1] >> 44); + a32[3] |= a[2] << 8; + a32[3] &= 0xffffffff; + a32[4] = (sp_digit)(a[2] >> 24); + a32[4] |= a[3] << 28; + a32[4] &= 0xffffffff; + a32[5] = (sp_digit)(a[3] >> 4) & 0xffffffff; + a32[6] = (sp_digit)(a[3] >> 36); + a32[6] |= a[4] << 16; + a32[6] &= 0xffffffff; + a32[7] = (sp_digit)(a[4] >> 16) & 0xffffffff; + + /* 1 1 0 -1 -1 -1 -1 0 */ + t[0] = 0 + a32[0] + a32[1] - a32[3] - a32[4] - a32[5] - a32[6]; + /* 0 1 1 0 -1 -1 -1 -1 */ + t[1] = 0 + a32[1] + a32[2] - a32[4] - a32[5] - a32[6] - a32[7]; + /* 0 0 1 1 0 -1 -1 -1 */ + t[2] = 0 + a32[2] + a32[3] - a32[5] - a32[6] - a32[7]; + /* -1 -1 0 2 2 1 0 -1 */ + t[3] = 0 - a32[0] - a32[1] + 2 * a32[3] + 2 * a32[4] + a32[5] - a32[7]; + /* 0 -1 -1 0 2 2 1 0 */ + t[4] = 0 - a32[1] - a32[2] + 2 * a32[4] + 2 * a32[5] + a32[6]; + /* 0 0 -1 -1 0 2 2 1 */ + t[5] = 0 - a32[2] - a32[3] + 2 * a32[5] + 2 * a32[6] + a32[7]; + /* -1 -1 0 0 0 1 3 2 */ + t[6] = 0 - a32[0] - a32[1] + a32[5] + 3 * a32[6] + 2 * a32[7]; + /* 1 0 -1 -1 -1 -1 0 3 */ + t[7] = 0 + a32[0] - a32[2] - a32[3] - a32[4] - a32[5] + 3 * a32[7]; + + t[1] += t[0] >> 32; t[0] &= 0xffffffff; + t[2] += t[1] >> 32; t[1] &= 0xffffffff; + t[3] += t[2] >> 32; t[2] &= 0xffffffff; + t[4] += t[3] >> 32; t[3] &= 0xffffffff; + t[5] += t[4] >> 32; t[4] &= 0xffffffff; + t[6] += t[5] >> 32; t[5] &= 0xffffffff; + t[7] += t[6] >> 32; t[6] &= 0xffffffff; + o = t[7] >> 32; t[7] &= 0xffffffff; + t[0] += o; + t[3] -= o; + t[6] -= o; + t[7] += o; + t[1] += t[0] >> 32; t[0] &= 0xffffffff; + t[2] += t[1] >> 32; t[1] &= 0xffffffff; + t[3] += t[2] >> 32; t[2] &= 0xffffffff; + t[4] += t[3] >> 32; t[3] &= 0xffffffff; + t[5] += t[4] >> 32; t[4] &= 0xffffffff; + t[6] += t[5] >> 32; t[5] &= 0xffffffff; + t[7] += t[6] >> 32; t[6] &= 0xffffffff; + + r[0] = t[0]; + r[0] |= t[1] << 32; + r[0] &= 0xfffffffffffffl; + r[1] = (sp_digit)(t[1] >> 20); + r[1] |= t[2] << 12; + r[1] |= t[3] << 44; + r[1] &= 0xfffffffffffffl; + r[2] = (sp_digit)(t[3] >> 8); + r[2] |= t[4] << 24; + r[2] &= 0xfffffffffffffl; + r[3] = (sp_digit)(t[4] >> 28); + r[3] |= t[5] << 4; + r[3] |= t[6] << 36; + r[3] &= 0xfffffffffffffl; + r[4] = (sp_digit)(t[6] >> 16); + r[4] |= t[7] << 16; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * a A multi-precision integer. + */ +static void sp_256_from_mp(sp_digit* r, int max, mp_int* a) +{ +#if DIGIT_BIT == 52 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < max; j++) + r[j] = 0; +#elif DIGIT_BIT > 52 + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= a->dp[i] << s; + r[j] &= 0xfffffffffffffl; + s = 52 - s; + if (j + 1 >= max) + break; + r[++j] = (sp_digit)(a->dp[i] >> s); + while (s + 52 <= DIGIT_BIT) { + s += 52; + r[j] &= 0xfffffffffffffl; + if (j + 1 >= max) + break; + if (s < DIGIT_BIT) + r[++j] = (sp_digit)(a->dp[i] >> s); + else + r[++j] = 0; + } + s = DIGIT_BIT - s; + } + + for (j++; j < max; j++) + r[j] = 0; +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 52) { + r[j] &= 0xfffffffffffffl; + if (j + 1 >= max) + break; + s = 52 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else + s += DIGIT_BIT; + } + + for (j++; j < max; j++) + r[j] = 0; +#endif +} + +/* Convert a point of type ecc_point to type sp_point. + * + * p Point of type sp_point (result). + * pm Point of type ecc_point. + */ +static void sp_256_point_from_ecc_point_5(sp_point* p, ecc_point* pm) +{ + XMEMSET(p->x, 0, sizeof(p->x)); + XMEMSET(p->y, 0, sizeof(p->y)); + XMEMSET(p->z, 0, sizeof(p->z)); + sp_256_from_mp(p->x, 5, pm->x); + sp_256_from_mp(p->y, 5, pm->y); + sp_256_from_mp(p->z, 5, pm->z); + p->infinity = 0; +} + +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_256_to_mp(sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (256 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { +#if DIGIT_BIT == 52 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 5); + r->used = 5; + mp_clamp(r); +#elif DIGIT_BIT < 52 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 5; i++) { + r->dp[j] |= a[i] << s; + r->dp[j] &= (1l << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + while (s + DIGIT_BIT <= 52) { + s += DIGIT_BIT; + r->dp[j] &= (1l << DIGIT_BIT) - 1; + r->dp[++j] = a[i] >> s; + } + s = 52 - s; + } + r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 5; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 52 >= DIGIT_BIT) { + #if DIGIT_BIT != 32 && DIGIT_BIT != 64 + r->dp[j] &= (1l << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 52 - s; + } + else + s += 52; + } + r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Convert a point of type sp_point to type ecc_point. + * + * p Point of type sp_point. + * pm Point of type ecc_point (result). + * returns MEMORY_E when allocation of memory in ecc_point fails otherwise + * MP_OKAY. + */ +static int sp_256_point_to_ecc_point_5(sp_point* p, ecc_point* pm) +{ + int err; + + err = sp_256_to_mp(p->x, pm->x); + if (err == MP_OKAY) + err = sp_256_to_mp(p->y, pm->y); + if (err == MP_OKAY) + err = sp_256_to_mp(p->z, pm->z); + + return err; +} + +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +static sp_digit sp_256_cmp_5(const sp_digit* a, const sp_digit* b) +{ + sp_digit r = 0; +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=4; i>=0; i--) + r |= (a[i] - b[i]) & (0 - !r); +#else + r |= (a[ 4] - b[ 4]) & (0 - !r); + r |= (a[ 3] - b[ 3]) & (0 - !r); + r |= (a[ 2] - b[ 2]) & (0 - !r); + r |= (a[ 1] - b[ 1]) & (0 - !r); + r |= (a[ 0] - b[ 0]) & (0 - !r); +#endif /* WOLFSSL_SP_SMALL */ + + return r; +} + +/* Normalize the values in each word to 52. + * + * a Array of sp_digit to normalize. + */ +static void sp_256_norm_5(sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + for (i = 0; i < 4; i++) { + a[i+1] += a[i] >> 52; + a[i] &= 0xfffffffffffffl; + } +#else + a[1] += a[0] >> 52; a[0] &= 0xfffffffffffffl; + a[2] += a[1] >> 52; a[1] &= 0xfffffffffffffl; + a[3] += a[2] >> 52; a[2] &= 0xfffffffffffffl; + a[4] += a[3] >> 52; a[3] &= 0xfffffffffffffl; +#endif +} + +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +static void sp_256_cond_sub_5(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i = 0; i < 5; i++) + r[i] = a[i] - (b[i] & m); +#else + r[ 0] = a[ 0] - (b[ 0] & m); + r[ 1] = a[ 1] - (b[ 1] & m); + r[ 2] = a[ 2] - (b[ 2] & m); + r[ 3] = a[ 3] - (b[ 3] & m); + r[ 4] = a[ 4] - (b[ 4] & m); +#endif /* WOLFSSL_SP_SMALL */ +} + +#define sp_256_mont_reduce_order_5 sp_256_mont_reduce_5 + +/* Mul a by scalar b and add into r. (r += a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +SP_NOINLINE static void sp_256_mul_add_5(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int128_t tb = b; + int128_t t = 0; + int i; + + for (i = 0; i < 5; i++) { + t += (tb * a[i]) + r[i]; + r[i] = t & 0xfffffffffffffl; + t >>= 52; + } + r[5] += t; +#else + int128_t tb = b; + int128_t t[5]; + + t[ 0] = tb * a[ 0]; + t[ 1] = tb * a[ 1]; + t[ 2] = tb * a[ 2]; + t[ 3] = tb * a[ 3]; + t[ 4] = tb * a[ 4]; + r[ 0] += (t[ 0] & 0xfffffffffffffl); + r[ 1] += (t[ 0] >> 52) + (t[ 1] & 0xfffffffffffffl); + r[ 2] += (t[ 1] >> 52) + (t[ 2] & 0xfffffffffffffl); + r[ 3] += (t[ 2] >> 52) + (t[ 3] & 0xfffffffffffffl); + r[ 4] += (t[ 3] >> 52) + (t[ 4] & 0xfffffffffffffl); + r[ 5] += t[ 4] >> 52; +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Shift the result in the high 256 bits down to the bottom. + * + * r A single precision number. + * a A single precision number. + */ +static void sp_256_mont_shift_5(sp_digit* r, const sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + word64 n; + + n = a[4] >> 48; + for (i = 0; i < 4; i++) { + n += a[5 + i] << 4; + r[i] = n & 0xfffffffffffffl; + n >>= 52; + } + n += a[9] << 4; + r[4] = n; +#else + word64 n; + + n = a[4] >> 48; + n += a[ 5] << 4; r[ 0] = n & 0xfffffffffffffl; n >>= 52; + n += a[ 6] << 4; r[ 1] = n & 0xfffffffffffffl; n >>= 52; + n += a[ 7] << 4; r[ 2] = n & 0xfffffffffffffl; n >>= 52; + n += a[ 8] << 4; r[ 3] = n & 0xfffffffffffffl; n >>= 52; + n += a[ 9] << 4; r[ 4] = n; +#endif /* WOLFSSL_SP_SMALL */ + XMEMSET(&r[5], 0, sizeof(*r) * 5); +} + +/* Reduce the number back to 256 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +static void sp_256_mont_reduce_5(sp_digit* a, sp_digit* m, sp_digit mp) +{ + int i; + sp_digit mu; + + if (mp != 1) { + for (i=0; i<4; i++) { + mu = (a[i] * mp) & 0xfffffffffffffl; + sp_256_mul_add_5(a+i, m, mu); + a[i+1] += a[i] >> 52; + } + mu = (a[i] * mp) & 0xffffffffffffl; + sp_256_mul_add_5(a+i, m, mu); + a[i+1] += a[i] >> 52; + a[i] &= 0xfffffffffffffl; + } + else { + for (i=0; i<4; i++) { + mu = a[i] & 0xfffffffffffffl; + sp_256_mul_add_5(a+i, p256_mod, mu); + a[i+1] += a[i] >> 52; + } + mu = a[i] & 0xffffffffffffl; + sp_256_mul_add_5(a+i, p256_mod, mu); + a[i+1] += a[i] >> 52; + a[i] &= 0xfffffffffffffl; + } + + sp_256_mont_shift_5(a, a); + sp_256_cond_sub_5(a, a, m, 0 - ((a[4] >> 48) > 0)); + sp_256_norm_5(a); +} + +#ifdef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_256_mul_5(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i, j, k; + int128_t c; + + c = ((int128_t)a[4]) * b[4]; + r[9] = (sp_digit)(c >> 52); + c = (c & 0xfffffffffffffl) << 52; + for (k = 7; k >= 0; k--) { + for (i = 4; i >= 0; i--) { + j = k - i; + if (j >= 5) + break; + if (j < 0) + continue; + + c += ((int128_t)a[i]) * b[j]; + } + r[k + 2] += c >> 104; + r[k + 1] = (c >> 52) & 0xfffffffffffffl; + c = (c & 0xfffffffffffffl) << 52; + } + r[0] = (sp_digit)(c >> 52); +} + +#else +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_256_mul_5(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int128_t t0 = ((int128_t)a[ 0]) * b[ 0]; + int128_t t1 = ((int128_t)a[ 0]) * b[ 1] + + ((int128_t)a[ 1]) * b[ 0]; + int128_t t2 = ((int128_t)a[ 0]) * b[ 2] + + ((int128_t)a[ 1]) * b[ 1] + + ((int128_t)a[ 2]) * b[ 0]; + int128_t t3 = ((int128_t)a[ 0]) * b[ 3] + + ((int128_t)a[ 1]) * b[ 2] + + ((int128_t)a[ 2]) * b[ 1] + + ((int128_t)a[ 3]) * b[ 0]; + int128_t t4 = ((int128_t)a[ 0]) * b[ 4] + + ((int128_t)a[ 1]) * b[ 3] + + ((int128_t)a[ 2]) * b[ 2] + + ((int128_t)a[ 3]) * b[ 1] + + ((int128_t)a[ 4]) * b[ 0]; + int128_t t5 = ((int128_t)a[ 1]) * b[ 4] + + ((int128_t)a[ 2]) * b[ 3] + + ((int128_t)a[ 3]) * b[ 2] + + ((int128_t)a[ 4]) * b[ 1]; + int128_t t6 = ((int128_t)a[ 2]) * b[ 4] + + ((int128_t)a[ 3]) * b[ 3] + + ((int128_t)a[ 4]) * b[ 2]; + int128_t t7 = ((int128_t)a[ 3]) * b[ 4] + + ((int128_t)a[ 4]) * b[ 3]; + int128_t t8 = ((int128_t)a[ 4]) * b[ 4]; + + t1 += t0 >> 52; r[ 0] = t0 & 0xfffffffffffffl; + t2 += t1 >> 52; r[ 1] = t1 & 0xfffffffffffffl; + t3 += t2 >> 52; r[ 2] = t2 & 0xfffffffffffffl; + t4 += t3 >> 52; r[ 3] = t3 & 0xfffffffffffffl; + t5 += t4 >> 52; r[ 4] = t4 & 0xfffffffffffffl; + t6 += t5 >> 52; r[ 5] = t5 & 0xfffffffffffffl; + t7 += t6 >> 52; r[ 6] = t6 & 0xfffffffffffffl; + t8 += t7 >> 52; r[ 7] = t7 & 0xfffffffffffffl; + r[9] = (sp_digit)(t8 >> 52); + r[8] = t8 & 0xfffffffffffffl; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_256_mont_mul_5(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_256_mul_5(r, a, b); + sp_256_mont_reduce_5(r, m, mp); +} + +#ifdef WOLFSSL_SP_SMALL +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_256_sqr_5(sp_digit* r, const sp_digit* a) +{ + int i, j, k; + int128_t c; + + c = ((int128_t)a[4]) * a[4]; + r[9] = (sp_digit)(c >> 52); + c = (c & 0xfffffffffffffl) << 52; + for (k = 7; k >= 0; k--) { + for (i = 4; i >= 0; i--) { + j = k - i; + if (j >= 5 || i <= j) + break; + if (j < 0) + continue; + + c += ((int128_t)a[i]) * a[j] * 2; + } + if (i == j) + c += ((int128_t)a[i]) * a[i]; + + r[k + 2] += c >> 104; + r[k + 1] = (c >> 52) & 0xfffffffffffffl; + c = (c & 0xfffffffffffffl) << 52; + } + r[0] = (sp_digit)(c >> 52); +} + +#else +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_256_sqr_5(sp_digit* r, const sp_digit* a) +{ + int128_t t0 = ((int128_t)a[ 0]) * a[ 0]; + int128_t t1 = (((int128_t)a[ 0]) * a[ 1]) * 2; + int128_t t2 = (((int128_t)a[ 0]) * a[ 2]) * 2 + + ((int128_t)a[ 1]) * a[ 1]; + int128_t t3 = (((int128_t)a[ 0]) * a[ 3] + + ((int128_t)a[ 1]) * a[ 2]) * 2; + int128_t t4 = (((int128_t)a[ 0]) * a[ 4] + + ((int128_t)a[ 1]) * a[ 3]) * 2 + + ((int128_t)a[ 2]) * a[ 2]; + int128_t t5 = (((int128_t)a[ 1]) * a[ 4] + + ((int128_t)a[ 2]) * a[ 3]) * 2; + int128_t t6 = (((int128_t)a[ 2]) * a[ 4]) * 2 + + ((int128_t)a[ 3]) * a[ 3]; + int128_t t7 = (((int128_t)a[ 3]) * a[ 4]) * 2; + int128_t t8 = ((int128_t)a[ 4]) * a[ 4]; + + t1 += t0 >> 52; r[ 0] = t0 & 0xfffffffffffffl; + t2 += t1 >> 52; r[ 1] = t1 & 0xfffffffffffffl; + t3 += t2 >> 52; r[ 2] = t2 & 0xfffffffffffffl; + t4 += t3 >> 52; r[ 3] = t3 & 0xfffffffffffffl; + t5 += t4 >> 52; r[ 4] = t4 & 0xfffffffffffffl; + t6 += t5 >> 52; r[ 5] = t5 & 0xfffffffffffffl; + t7 += t6 >> 52; r[ 6] = t6 & 0xfffffffffffffl; + t8 += t7 >> 52; r[ 7] = t7 & 0xfffffffffffffl; + r[9] = (sp_digit)(t8 >> 52); + r[8] = t8 & 0xfffffffffffffl; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_256_mont_sqr_5(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_256_sqr_5(r, a); + sp_256_mont_reduce_5(r, m, mp); +} + +#if !defined(WOLFSSL_SP_SMALL) || defined(HAVE_COMP_KEY) +/* Square the Montgomery form number a number of times. (r = a ^ n mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * n Number of times to square. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_256_mont_sqr_n_5(sp_digit* r, sp_digit* a, int n, + sp_digit* m, sp_digit mp) +{ + sp_256_mont_sqr_5(r, a, m, mp); + for (; n > 1; n--) + sp_256_mont_sqr_5(r, r, m, mp); +} + +#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */ +#ifdef WOLFSSL_SP_SMALL +/* Mod-2 for the P256 curve. */ +static const uint64_t p256_mod_2[4] = { + 0xfffffffffffffffd,0x00000000ffffffff,0x0000000000000000, + 0xffffffff00000001 +}; +#endif /* !WOLFSSL_SP_SMALL */ + +/* Invert the number, in Montgomery form, modulo the modulus (prime) of the + * P256 curve. (r = 1 / a mod m) + * + * r Inverse result. + * a Number to invert. + * td Temporary data. + */ +static void sp_256_mont_inv_5(sp_digit* r, sp_digit* a, sp_digit* td) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* t = td; + int i; + + XMEMCPY(t, a, sizeof(sp_digit) * 5); + for (i=254; i>=0; i--) { + sp_256_mont_sqr_5(t, t, p256_mod, p256_mp_mod); + if (p256_mod_2[i / 64] & ((sp_digit)1 << (i % 64))) + sp_256_mont_mul_5(t, t, a, p256_mod, p256_mp_mod); + } + XMEMCPY(r, t, sizeof(sp_digit) * 5); +#else + sp_digit* t = td; + sp_digit* t2 = td + 2 * 5; + sp_digit* t3 = td + 4 * 5; + + /* t = a^2 */ + sp_256_mont_sqr_5(t, a, p256_mod, p256_mp_mod); + /* t = a^3 = t * a */ + sp_256_mont_mul_5(t, t, a, p256_mod, p256_mp_mod); + /* t2= a^c = t ^ 2 ^ 2 */ + sp_256_mont_sqr_n_5(t2, t, 2, p256_mod, p256_mp_mod); + /* t3= a^d = t2 * a */ + sp_256_mont_mul_5(t3, t2, a, p256_mod, p256_mp_mod); + /* t = a^f = t2 * t */ + sp_256_mont_mul_5(t, t2, t, p256_mod, p256_mp_mod); + /* t2= a^f0 = t ^ 2 ^ 4 */ + sp_256_mont_sqr_n_5(t2, t, 4, p256_mod, p256_mp_mod); + /* t3= a^fd = t2 * t3 */ + sp_256_mont_mul_5(t3, t2, t3, p256_mod, p256_mp_mod); + /* t = a^ff = t2 * t */ + sp_256_mont_mul_5(t, t2, t, p256_mod, p256_mp_mod); + /* t2= a^ff00 = t ^ 2 ^ 8 */ + sp_256_mont_sqr_n_5(t2, t, 8, p256_mod, p256_mp_mod); + /* t3= a^fffd = t2 * t3 */ + sp_256_mont_mul_5(t3, t2, t3, p256_mod, p256_mp_mod); + /* t = a^ffff = t2 * t */ + sp_256_mont_mul_5(t, t2, t, p256_mod, p256_mp_mod); + /* t2= a^ffff0000 = t ^ 2 ^ 16 */ + sp_256_mont_sqr_n_5(t2, t, 16, p256_mod, p256_mp_mod); + /* t3= a^fffffffd = t2 * t3 */ + sp_256_mont_mul_5(t3, t2, t3, p256_mod, p256_mp_mod); + /* t = a^ffffffff = t2 * t */ + sp_256_mont_mul_5(t, t2, t, p256_mod, p256_mp_mod); + /* t = a^ffffffff00000000 = t ^ 2 ^ 32 */ + sp_256_mont_sqr_n_5(t2, t, 32, p256_mod, p256_mp_mod); + /* t2= a^ffffffffffffffff = t2 * t */ + sp_256_mont_mul_5(t, t2, t, p256_mod, p256_mp_mod); + /* t2= a^ffffffff00000001 = t2 * a */ + sp_256_mont_mul_5(t2, t2, a, p256_mod, p256_mp_mod); + /* t2= a^ffffffff000000010000000000000000000000000000000000000000 + * = t2 ^ 2 ^ 160 */ + sp_256_mont_sqr_n_5(t2, t2, 160, p256_mod, p256_mp_mod); + /* t2= a^ffffffff00000001000000000000000000000000ffffffffffffffff + * = t2 * t */ + sp_256_mont_mul_5(t2, t2, t, p256_mod, p256_mp_mod); + /* t2= a^ffffffff00000001000000000000000000000000ffffffffffffffff00000000 + * = t2 ^ 2 ^ 32 */ + sp_256_mont_sqr_n_5(t2, t2, 32, p256_mod, p256_mp_mod); + /* r = a^ffffffff00000001000000000000000000000000fffffffffffffffffffffffd + * = t2 * t3 */ + sp_256_mont_mul_5(r, t2, t3, p256_mod, p256_mp_mod); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Map the Montgomery form projective co-ordinate point to an affine point. + * + * r Resulting affine co-ordinate point. + * p Montgomery form projective co-ordinate point. + * t Temporary ordinate data. + */ +static void sp_256_map_5(sp_point* r, sp_point* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*5; + int64_t n; + + sp_256_mont_inv_5(t1, p->z, t + 2*5); + + sp_256_mont_sqr_5(t2, t1, p256_mod, p256_mp_mod); + sp_256_mont_mul_5(t1, t2, t1, p256_mod, p256_mp_mod); + + /* x /= z^2 */ + sp_256_mont_mul_5(r->x, p->x, t2, p256_mod, p256_mp_mod); + XMEMSET(r->x + 5, 0, sizeof(r->x) / 2); + sp_256_mont_reduce_5(r->x, p256_mod, p256_mp_mod); + /* Reduce x to less than modulus */ + n = sp_256_cmp_5(r->x, p256_mod); + sp_256_cond_sub_5(r->x, r->x, p256_mod, 0 - (n >= 0)); + sp_256_norm_5(r->x); + + /* y /= z^3 */ + sp_256_mont_mul_5(r->y, p->y, t1, p256_mod, p256_mp_mod); + XMEMSET(r->y + 5, 0, sizeof(r->y) / 2); + sp_256_mont_reduce_5(r->y, p256_mod, p256_mp_mod); + /* Reduce y to less than modulus */ + n = sp_256_cmp_5(r->y, p256_mod); + sp_256_cond_sub_5(r->y, r->y, p256_mod, 0 - (n >= 0)); + sp_256_norm_5(r->y); + + XMEMSET(r->z, 0, sizeof(r->z)); + r->z[0] = 1; + +} + +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_256_add_5(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 5; i++) + r[i] = a[i] + b[i]; + + return 0; +} +#else +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_256_add_5(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + r[ 0] = a[ 0] + b[ 0]; + r[ 1] = a[ 1] + b[ 1]; + r[ 2] = a[ 2] + b[ 2]; + r[ 3] = a[ 3] + b[ 3]; + r[ 4] = a[ 4] + b[ 4]; + + return 0; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Add two Montgomery form numbers (r = a + b % m). + * + * r Result of addition. + * a First number to add in Montogmery form. + * b Second number to add in Montogmery form. + * m Modulus (prime). + */ +static void sp_256_mont_add_5(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m) +{ + sp_256_add_5(r, a, b); + sp_256_norm_5(r); + sp_256_cond_sub_5(r, r, m, 0 - ((r[4] >> 48) > 0)); + sp_256_norm_5(r); +} + +/* Double a Montgomery form number (r = a + a % m). + * + * r Result of doubling. + * a Number to double in Montogmery form. + * m Modulus (prime). + */ +static void sp_256_mont_dbl_5(sp_digit* r, sp_digit* a, sp_digit* m) +{ + sp_256_add_5(r, a, a); + sp_256_norm_5(r); + sp_256_cond_sub_5(r, r, m, 0 - ((r[4] >> 48) > 0)); + sp_256_norm_5(r); +} + +/* Triple a Montgomery form number (r = a + a + a % m). + * + * r Result of Tripling. + * a Number to triple in Montogmery form. + * m Modulus (prime). + */ +static void sp_256_mont_tpl_5(sp_digit* r, sp_digit* a, sp_digit* m) +{ + sp_256_add_5(r, a, a); + sp_256_norm_5(r); + sp_256_cond_sub_5(r, r, m, 0 - ((r[4] >> 48) > 0)); + sp_256_norm_5(r); + sp_256_add_5(r, r, a); + sp_256_norm_5(r); + sp_256_cond_sub_5(r, r, m, 0 - ((r[4] >> 48) > 0)); + sp_256_norm_5(r); +} + +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_256_sub_5(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + int i; + + for (i = 0; i < 5; i++) + r[i] = a[i] - b[i]; + + return 0; +} + +#else +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static int sp_256_sub_5(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + r[ 0] = a[ 0] - b[ 0]; + r[ 1] = a[ 1] - b[ 1]; + r[ 2] = a[ 2] - b[ 2]; + r[ 3] = a[ 3] - b[ 3]; + r[ 4] = a[ 4] - b[ 4]; + + return 0; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Conditionally add a and b using the mask m. + * m is -1 to add and 0 when not. + * + * r A single precision number representing conditional add result. + * a A single precision number to add with. + * b A single precision number to add. + * m Mask value to apply. + */ +static void sp_256_cond_add_5(sp_digit* r, const sp_digit* a, + const sp_digit* b, const sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i = 0; i < 5; i++) + r[i] = a[i] + (b[i] & m); +#else + r[ 0] = a[ 0] + (b[ 0] & m); + r[ 1] = a[ 1] + (b[ 1] & m); + r[ 2] = a[ 2] + (b[ 2] & m); + r[ 3] = a[ 3] + (b[ 3] & m); + r[ 4] = a[ 4] + (b[ 4] & m); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Subtract two Montgomery form numbers (r = a - b % m). + * + * r Result of subtration. + * a Number to subtract from in Montogmery form. + * b Number to subtract with in Montogmery form. + * m Modulus (prime). + */ +static void sp_256_mont_sub_5(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m) +{ + sp_256_sub_5(r, a, b); + sp_256_cond_add_5(r, r, m, r[4] >> 48); + sp_256_norm_5(r); +} + +/* Shift number left one bit. + * Bottom bit is lost. + * + * r Result of shift. + * a Number to shift. + */ +SP_NOINLINE static void sp_256_rshift1_5(sp_digit* r, sp_digit* a) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<4; i++) + r[i] = ((a[i] >> 1) | (a[i + 1] << 51)) & 0xfffffffffffffl; +#else + r[0] = ((a[0] >> 1) | (a[1] << 51)) & 0xfffffffffffffl; + r[1] = ((a[1] >> 1) | (a[2] << 51)) & 0xfffffffffffffl; + r[2] = ((a[2] >> 1) | (a[3] << 51)) & 0xfffffffffffffl; + r[3] = ((a[3] >> 1) | (a[4] << 51)) & 0xfffffffffffffl; +#endif + r[4] = a[4] >> 1; +} + +/* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m) + * + * r Result of division by 2. + * a Number to divide. + * m Modulus (prime). + */ +static void sp_256_div2_5(sp_digit* r, sp_digit* a, sp_digit* m) +{ + sp_256_cond_add_5(r, a, m, 0 - (a[0] & 1)); + sp_256_norm_5(r); + sp_256_rshift1_5(r, r); +} + +/* Double the Montgomery form projective point p. + * + * r Result of doubling point. + * p Point to double. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_dbl_5(sp_point* r, sp_point* p, sp_digit* t) +{ + sp_point* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*5; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* When infinity don't double point passed in - constant time. */ + rp[0] = r; + rp[1] = (sp_point*)t; + XMEMSET(rp[1], 0, sizeof(sp_point)); + x = rp[p->infinity]->x; + y = rp[p->infinity]->y; + z = rp[p->infinity]->z; + /* Put point to double into result - good for infinty. */ + if (r != p) { + for (i=0; i<5; i++) + r->x[i] = p->x[i]; + for (i=0; i<5; i++) + r->y[i] = p->y[i]; + for (i=0; i<5; i++) + r->z[i] = p->z[i]; + r->infinity = p->infinity; + } + + /* T1 = Z * Z */ + sp_256_mont_sqr_5(t1, z, p256_mod, p256_mp_mod); + /* Z = Y * Z */ + sp_256_mont_mul_5(z, y, z, p256_mod, p256_mp_mod); + /* Z = 2Z */ + sp_256_mont_dbl_5(z, z, p256_mod); + /* T2 = X - T1 */ + sp_256_mont_sub_5(t2, x, t1, p256_mod); + /* T1 = X + T1 */ + sp_256_mont_add_5(t1, x, t1, p256_mod); + /* T2 = T1 * T2 */ + sp_256_mont_mul_5(t2, t1, t2, p256_mod, p256_mp_mod); + /* T1 = 3T2 */ + sp_256_mont_tpl_5(t1, t2, p256_mod); + /* Y = 2Y */ + sp_256_mont_dbl_5(y, y, p256_mod); + /* Y = Y * Y */ + sp_256_mont_sqr_5(y, y, p256_mod, p256_mp_mod); + /* T2 = Y * Y */ + sp_256_mont_sqr_5(t2, y, p256_mod, p256_mp_mod); + /* T2 = T2/2 */ + sp_256_div2_5(t2, t2, p256_mod); + /* Y = Y * X */ + sp_256_mont_mul_5(y, y, x, p256_mod, p256_mp_mod); + /* X = T1 * T1 */ + sp_256_mont_mul_5(x, t1, t1, p256_mod, p256_mp_mod); + /* X = X - Y */ + sp_256_mont_sub_5(x, x, y, p256_mod); + /* X = X - Y */ + sp_256_mont_sub_5(x, x, y, p256_mod); + /* Y = Y - X */ + sp_256_mont_sub_5(y, y, x, p256_mod); + /* Y = Y * T1 */ + sp_256_mont_mul_5(y, y, t1, p256_mod, p256_mp_mod); + /* Y = Y - T2 */ + sp_256_mont_sub_5(y, y, t2, p256_mod); + +} + +/* Compare two numbers to determine if they are equal. + * Constant time implementation. + * + * a First number to compare. + * b Second number to compare. + * returns 1 when equal and 0 otherwise. + */ +static int sp_256_cmp_equal_5(const sp_digit* a, const sp_digit* b) +{ + return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]) | (a[3] ^ b[3]) | + (a[4] ^ b[4])) == 0; +} + +/* Add two Montgomery form projective points. + * + * r Result of addition. + * p Frist point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_add_5(sp_point* r, sp_point* p, sp_point* q, + sp_digit* t) +{ + sp_point* ap[2]; + sp_point* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*5; + sp_digit* t3 = t + 4*5; + sp_digit* t4 = t + 6*5; + sp_digit* t5 = t + 8*5; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + sp_point* a = p; + p = q; + q = a; + } + + /* Check double */ + sp_256_sub_5(t1, p256_mod, q->y); + sp_256_norm_5(t1); + if (sp_256_cmp_equal_5(p->x, q->x) & sp_256_cmp_equal_5(p->z, q->z) & + (sp_256_cmp_equal_5(p->y, q->y) | sp_256_cmp_equal_5(p->y, t1))) { + sp_256_proj_point_dbl_5(r, p, t); + } + else { + rp[0] = r; + rp[1] = (sp_point*)t; + XMEMSET(rp[1], 0, sizeof(sp_point)); + x = rp[p->infinity | q->infinity]->x; + y = rp[p->infinity | q->infinity]->y; + z = rp[p->infinity | q->infinity]->z; + + ap[0] = p; + ap[1] = q; + for (i=0; i<5; i++) + r->x[i] = ap[p->infinity]->x[i]; + for (i=0; i<5; i++) + r->y[i] = ap[p->infinity]->y[i]; + for (i=0; i<5; i++) + r->z[i] = ap[p->infinity]->z[i]; + r->infinity = ap[p->infinity]->infinity; + + /* U1 = X1*Z2^2 */ + sp_256_mont_sqr_5(t1, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_5(t3, t1, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_5(t1, t1, x, p256_mod, p256_mp_mod); + /* U2 = X2*Z1^2 */ + sp_256_mont_sqr_5(t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_5(t4, t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_5(t2, t2, q->x, p256_mod, p256_mp_mod); + /* S1 = Y1*Z2^3 */ + sp_256_mont_mul_5(t3, t3, y, p256_mod, p256_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_256_mont_mul_5(t4, t4, q->y, p256_mod, p256_mp_mod); + /* H = U2 - U1 */ + sp_256_mont_sub_5(t2, t2, t1, p256_mod); + /* R = S2 - S1 */ + sp_256_mont_sub_5(t4, t4, t3, p256_mod); + /* Z3 = H*Z1*Z2 */ + sp_256_mont_mul_5(z, z, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_5(z, z, t2, p256_mod, p256_mp_mod); + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_256_mont_sqr_5(x, t4, p256_mod, p256_mp_mod); + sp_256_mont_sqr_5(t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_5(y, t1, t5, p256_mod, p256_mp_mod); + sp_256_mont_mul_5(t5, t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_sub_5(x, x, t5, p256_mod); + sp_256_mont_dbl_5(t1, y, p256_mod); + sp_256_mont_sub_5(x, x, t1, p256_mod); + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_256_mont_sub_5(y, y, x, p256_mod); + sp_256_mont_mul_5(y, y, t4, p256_mod, p256_mp_mod); + sp_256_mont_mul_5(t5, t5, t3, p256_mod, p256_mp_mod); + sp_256_mont_sub_5(y, y, t5, p256_mod); + } +} + +#ifdef WOLFSSL_SP_SMALL +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_5(sp_point* r, sp_point* g, sp_digit* k, + int map, void* heap) +{ + sp_point* td; + sp_point* t[3]; + sp_digit* tmp; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + + (void)heap; + + td = (sp_point*)XMALLOC(sizeof(sp_point) * 3, heap, DYNAMIC_TYPE_ECC); + if (td == NULL) + err = MEMORY_E; + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 5 * 5, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + XMEMSET(td, 0, sizeof(*td) * 3); + + t[0] = &td[0]; + t[1] = &td[1]; + t[2] = &td[2]; + + /* t[0] = {0, 0, 1} * norm */ + t[0]->infinity = 1; + /* t[1] = {g->x, g->y, g->z} * norm */ + err = sp_256_mod_mul_norm_5(t[1]->x, g->x, p256_mod); + } + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_5(t[1]->y, g->y, p256_mod); + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_5(t[1]->z, g->z, p256_mod); + + if (err == MP_OKAY) { + i = 4; + c = 48; + n = k[i--] << (52 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = k[i--]; + c = 52; + } + + y = (n >> 51) & 1; + n <<= 1; + + sp_256_proj_point_add_5(t[y^1], t[0], t[1], tmp); + + XMEMCPY(t[2], (void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), + sizeof(sp_point)); + sp_256_proj_point_dbl_5(t[2], t[2], tmp); + XMEMCPY((void*)(((size_t)t[0] & addr_mask[y^1]) + + ((size_t)t[1] & addr_mask[y])), t[2], + sizeof(sp_point)); + } + + if (map) + sp_256_map_5(r, t[0], tmp); + else + XMEMCPY(r, t[0], sizeof(sp_point)); + } + + if (tmp != NULL) { + XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 5 * 5); + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); + } + if (td != NULL) { + XMEMSET(td, 0, sizeof(sp_point) * 3); + XFREE(td, NULL, DYNAMIC_TYPE_ECC); + } + + return err; +} + +#elif defined(WOLFSSL_SP_CACHE_RESISTANT) +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_5(sp_point* r, sp_point* g, sp_digit* k, + int map, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point td[3]; + sp_digit tmpd[2 * 5 * 5]; +#endif + sp_point* t; + sp_digit* tmp; + sp_digit n; + int i; + int c, y; + int err = MP_OKAY; + + (void)heap; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_point td[3]; + t = (sp_point*)XMALLOC(sizeof(*td) * 3, heap, DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 5 * 5, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; +#else + t = td; + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + t[0] = &td[0]; + t[1] = &td[1]; + t[2] = &td[2]; + + /* t[0] = {0, 0, 1} * norm */ + XMEMSET(&t[0], 0, sizeof(t[0])); + t[0].infinity = 1; + /* t[1] = {g->x, g->y, g->z} * norm */ + err = sp_256_mod_mul_norm_5(t[1].x, g->x, p256_mod); + } + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_5(t[1].y, g->y, p256_mod); + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_5(t[1].z, g->z, p256_mod); + + if (err == MP_OKAY) { + i = 4; + c = 48; + n = k[i--] << (52 - c); + for (; ; c--) { + if (c == 0) { + if (i == -1) + break; + + n = k[i--]; + c = 52; + } + + y = (n >> 51) & 1; + n <<= 1; + + sp_256_proj_point_add_5(&t[y^1], &t[0], &t[1], tmp); + + XMEMCPY(&t[2], (void*)(((size_t)&t[0] & addr_mask[y^1]) + + ((size_t)&t[1] & addr_mask[y])), sizeof(t[2])); + sp_256_proj_point_dbl_5(&t[2], &t[2], tmp); + XMEMCPY((void*)(((size_t)&t[0] & addr_mask[y^1]) + + ((size_t)&t[1] & addr_mask[y])), &t[2], sizeof(t[2])); + } + + if (map) + sp_256_map_5(r, &t[0], tmp); + else + XMEMCPY(r, &t[0], sizeof(sp_point)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (tmp != NULL) { + XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 5 * 5); + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + } + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_point) * 3); + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } +#else + ForceZero(tmpd, sizeof(tmpd)); + ForceZero(td, sizeof(td)); +#endif + + return err; +} + +#else +/* A table entry for pre-computed points. */ +typedef struct sp_table_entry { + sp_digit x[5]; + sp_digit y[5]; + byte infinity; +} sp_table_entry; + +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_fast_5(sp_point* r, sp_point* g, sp_digit* k, + int map, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point td[16]; + sp_point rtd; + sp_digit tmpd[2 * 5 * 5]; +#endif + sp_point* t; + sp_point* rt; + sp_digit* tmp; + sp_digit n; + int i; + int c, y; + int err; + + (void)heap; + + err = sp_ecc_point_new(heap, rtd, rt); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + t = (sp_point*)XMALLOC(sizeof(sp_point) * 16, heap, DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 5 * 5, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; +#else + t = td; + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + /* t[0] = {0, 0, 1} * norm */ + XMEMSET(&t[0], 0, sizeof(t[0])); + t[0].infinity = 1; + /* t[1] = {g->x, g->y, g->z} * norm */ + sp_256_mod_mul_norm_5(t[1].x, g->x, p256_mod); + sp_256_mod_mul_norm_5(t[1].y, g->y, p256_mod); + sp_256_mod_mul_norm_5(t[1].z, g->z, p256_mod); + t[1].infinity = 0; + sp_256_proj_point_dbl_5(&t[ 2], &t[ 1], tmp); + t[ 2].infinity = 0; + sp_256_proj_point_add_5(&t[ 3], &t[ 2], &t[ 1], tmp); + t[ 3].infinity = 0; + sp_256_proj_point_dbl_5(&t[ 4], &t[ 2], tmp); + t[ 4].infinity = 0; + sp_256_proj_point_add_5(&t[ 5], &t[ 3], &t[ 2], tmp); + t[ 5].infinity = 0; + sp_256_proj_point_dbl_5(&t[ 6], &t[ 3], tmp); + t[ 6].infinity = 0; + sp_256_proj_point_add_5(&t[ 7], &t[ 4], &t[ 3], tmp); + t[ 7].infinity = 0; + sp_256_proj_point_dbl_5(&t[ 8], &t[ 4], tmp); + t[ 8].infinity = 0; + sp_256_proj_point_add_5(&t[ 9], &t[ 5], &t[ 4], tmp); + t[ 9].infinity = 0; + sp_256_proj_point_dbl_5(&t[10], &t[ 5], tmp); + t[10].infinity = 0; + sp_256_proj_point_add_5(&t[11], &t[ 6], &t[ 5], tmp); + t[11].infinity = 0; + sp_256_proj_point_dbl_5(&t[12], &t[ 6], tmp); + t[12].infinity = 0; + sp_256_proj_point_add_5(&t[13], &t[ 7], &t[ 6], tmp); + t[13].infinity = 0; + sp_256_proj_point_dbl_5(&t[14], &t[ 7], tmp); + t[14].infinity = 0; + sp_256_proj_point_add_5(&t[15], &t[ 8], &t[ 7], tmp); + t[15].infinity = 0; + + i = 3; + n = k[i+1] << 12; + c = 44; + y = n >> 56; + XMEMCPY(rt, &t[y], sizeof(sp_point)); + n <<= 8; + for (; i>=0 || c>=4; ) { + if (c < 4) { + n |= k[i--] << (12 - c); + c += 52; + } + y = (n >> 60) & 0xf; + n <<= 4; + c -= 4; + + sp_256_proj_point_dbl_5(rt, rt, tmp); + sp_256_proj_point_dbl_5(rt, rt, tmp); + sp_256_proj_point_dbl_5(rt, rt, tmp); + sp_256_proj_point_dbl_5(rt, rt, tmp); + + sp_256_proj_point_add_5(rt, rt, &t[y], tmp); + } + + if (map) + sp_256_map_5(r, rt, tmp); + else + XMEMCPY(r, rt, sizeof(sp_point)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (tmp != NULL) { + XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 5 * 5); + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + } + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_point) * 16); + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } +#else + ForceZero(tmpd, sizeof(tmpd)); + ForceZero(td, sizeof(td)); +#endif + sp_ecc_point_free(rt, 1, heap); + + return err; +} + +#ifdef FP_ECC +/* Double the Montgomery form projective point p a number of times. + * + * r Result of repeated doubling of point. + * p Point to double. + * n Number of times to double + * t Temporary ordinate data. + */ +static void sp_256_proj_point_dbl_n_5(sp_point* r, sp_point* p, int n, + sp_digit* t) +{ + sp_point* rp[2]; + sp_digit* w = t; + sp_digit* a = t + 2*5; + sp_digit* b = t + 4*5; + sp_digit* t1 = t + 6*5; + sp_digit* t2 = t + 8*5; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + rp[0] = r; + rp[1] = (sp_point*)t; + XMEMSET(rp[1], 0, sizeof(sp_point)); + x = rp[p->infinity]->x; + y = rp[p->infinity]->y; + z = rp[p->infinity]->z; + if (r != p) { + for (i=0; i<5; i++) + r->x[i] = p->x[i]; + for (i=0; i<5; i++) + r->y[i] = p->y[i]; + for (i=0; i<5; i++) + r->z[i] = p->z[i]; + r->infinity = p->infinity; + } + + /* Y = 2*Y */ + sp_256_mont_dbl_5(y, y, p256_mod); + /* W = Z^4 */ + sp_256_mont_sqr_5(w, z, p256_mod, p256_mp_mod); + sp_256_mont_sqr_5(w, w, p256_mod, p256_mp_mod); + while (n--) { + /* A = 3*(X^2 - W) */ + sp_256_mont_sqr_5(t1, x, p256_mod, p256_mp_mod); + sp_256_mont_sub_5(t1, t1, w, p256_mod); + sp_256_mont_tpl_5(a, t1, p256_mod); + /* B = X*Y^2 */ + sp_256_mont_sqr_5(t2, y, p256_mod, p256_mp_mod); + sp_256_mont_mul_5(b, t2, x, p256_mod, p256_mp_mod); + /* X = A^2 - 2B */ + sp_256_mont_sqr_5(x, a, p256_mod, p256_mp_mod); + sp_256_mont_dbl_5(t1, b, p256_mod); + sp_256_mont_sub_5(x, x, t1, p256_mod); + /* Z = Z*Y */ + sp_256_mont_mul_5(z, z, y, p256_mod, p256_mp_mod); + /* t2 = Y^4 */ + sp_256_mont_sqr_5(t2, t2, p256_mod, p256_mp_mod); + if (n) { + /* W = W*Y^4 */ + sp_256_mont_mul_5(w, w, t2, p256_mod, p256_mp_mod); + } + /* y = 2*A*(B - X) - Y^4 */ + sp_256_mont_sub_5(y, b, x, p256_mod); + sp_256_mont_mul_5(y, y, a, p256_mod, p256_mp_mod); + sp_256_mont_dbl_5(y, y, p256_mod); + sp_256_mont_sub_5(y, y, t2, p256_mod); + } + /* Y = Y/2 */ + sp_256_div2_5(y, y, p256_mod); +} + +#endif /* FP_ECC */ +/* Add two Montgomery form projective points. The second point has a q value of + * one. + * Only the first point can be the same pointer as the result point. + * + * r Result of addition. + * p Frist point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_add_qz1_5(sp_point* r, sp_point* p, + sp_point* q, sp_digit* t) +{ + sp_point* ap[2]; + sp_point* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*5; + sp_digit* t3 = t + 4*5; + sp_digit* t4 = t + 6*5; + sp_digit* t5 = t + 8*5; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* Check double */ + sp_256_sub_5(t1, p256_mod, q->y); + sp_256_norm_5(t1); + if (sp_256_cmp_equal_5(p->x, q->x) & sp_256_cmp_equal_5(p->z, q->z) & + (sp_256_cmp_equal_5(p->y, q->y) | sp_256_cmp_equal_5(p->y, t1))) { + sp_256_proj_point_dbl_5(r, p, t); + } + else { + rp[0] = r; + rp[1] = (sp_point*)t; + XMEMSET(rp[1], 0, sizeof(sp_point)); + x = rp[p->infinity | q->infinity]->x; + y = rp[p->infinity | q->infinity]->y; + z = rp[p->infinity | q->infinity]->z; + + ap[0] = p; + ap[1] = q; + for (i=0; i<5; i++) + r->x[i] = ap[p->infinity]->x[i]; + for (i=0; i<5; i++) + r->y[i] = ap[p->infinity]->y[i]; + for (i=0; i<5; i++) + r->z[i] = ap[p->infinity]->z[i]; + r->infinity = ap[p->infinity]->infinity; + + /* U2 = X2*Z1^2 */ + sp_256_mont_sqr_5(t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_5(t4, t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_5(t2, t2, q->x, p256_mod, p256_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_256_mont_mul_5(t4, t4, q->y, p256_mod, p256_mp_mod); + /* H = U2 - X1 */ + sp_256_mont_sub_5(t2, t2, x, p256_mod); + /* R = S2 - Y1 */ + sp_256_mont_sub_5(t4, t4, y, p256_mod); + /* Z3 = H*Z1 */ + sp_256_mont_mul_5(z, z, t2, p256_mod, p256_mp_mod); + /* X3 = R^2 - H^3 - 2*X1*H^2 */ + sp_256_mont_sqr_5(t1, t4, p256_mod, p256_mp_mod); + sp_256_mont_sqr_5(t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_5(t3, x, t5, p256_mod, p256_mp_mod); + sp_256_mont_mul_5(t5, t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_sub_5(x, t1, t5, p256_mod); + sp_256_mont_dbl_5(t1, t3, p256_mod); + sp_256_mont_sub_5(x, x, t1, p256_mod); + /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */ + sp_256_mont_sub_5(t3, t3, x, p256_mod); + sp_256_mont_mul_5(t3, t3, t4, p256_mod, p256_mp_mod); + sp_256_mont_mul_5(t5, t5, y, p256_mod, p256_mp_mod); + sp_256_mont_sub_5(y, t3, t5, p256_mod); + } +} + +#ifdef FP_ECC +/* Convert the projective point to affine. + * Ordinates are in Montgomery form. + * + * a Point to convert. + * t Temprorary data. + */ +static void sp_256_proj_to_affine_5(sp_point* a, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 5; + sp_digit* tmp = t + 4 * 5; + + sp_256_mont_inv_5(t1, a->z, tmp); + + sp_256_mont_sqr_5(t2, t1, p256_mod, p256_mp_mod); + sp_256_mont_mul_5(t1, t2, t1, p256_mod, p256_mp_mod); + + sp_256_mont_mul_5(a->x, a->x, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_5(a->y, a->y, t1, p256_mod, p256_mp_mod); + XMEMCPY(a->z, p256_norm_mod, sizeof(p256_norm_mod)); +} + +/* Generate the pre-computed table of points for the base point. + * + * a The base point. + * table Place to store generated point data. + * tmp Temprorary data. + * heap Heap to use for allocation. + */ +static int sp_256_gen_stripe_table_5(sp_point* a, + sp_table_entry* table, sp_digit* tmp, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point td, s1d, s2d; +#endif + sp_point* t; + sp_point* s1 = NULL; + sp_point* s2 = NULL; + int i, j; + int err; + + (void)heap; + + err = sp_ecc_point_new(heap, td, t); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, s1d, s1); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, s2d, s2); + + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_5(t->x, a->x, p256_mod); + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_5(t->y, a->y, p256_mod); + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_5(t->z, a->z, p256_mod); + if (err == MP_OKAY) { + t->infinity = 0; + sp_256_proj_to_affine_5(t, tmp); + + XMEMCPY(s1->z, p256_norm_mod, sizeof(p256_norm_mod)); + s1->infinity = 0; + XMEMCPY(s2->z, p256_norm_mod, sizeof(p256_norm_mod)); + s2->infinity = 0; + + /* table[0] = {0, 0, infinity} */ + XMEMSET(&table[0], 0, sizeof(sp_table_entry)); + table[0].infinity = 1; + /* table[1] = Affine version of 'a' in Montgomery form */ + XMEMCPY(table[1].x, t->x, sizeof(table->x)); + XMEMCPY(table[1].y, t->y, sizeof(table->y)); + table[1].infinity = 0; + + for (i=1; i<8; i++) { + sp_256_proj_point_dbl_n_5(t, t, 32, tmp); + sp_256_proj_to_affine_5(t, tmp); + XMEMCPY(table[1<x, sizeof(table->x)); + XMEMCPY(table[1<y, sizeof(table->y)); + table[1<x, table[1<x)); + XMEMCPY(s1->y, table[1<y)); + for (j=(1<x, table[j-(1<x)); + XMEMCPY(s2->y, table[j-(1<y)); + sp_256_proj_point_add_qz1_5(t, s1, s2, tmp); + sp_256_proj_to_affine_5(t, tmp); + XMEMCPY(table[j].x, t->x, sizeof(table->x)); + XMEMCPY(table[j].y, t->y, sizeof(table->y)); + table[j].infinity = 0; + } + } + } + + sp_ecc_point_free(s2, 0, heap); + sp_ecc_point_free(s1, 0, heap); + sp_ecc_point_free( t, 0, heap); + + return err; +} + +#endif /* FP_ECC */ +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_stripe_5(sp_point* r, sp_point* g, + sp_table_entry* table, sp_digit* k, int map, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point rtd; + sp_point pd; + sp_digit td[2 * 5 * 5]; +#endif + sp_point* rt; + sp_point* p = NULL; + sp_digit* t; + int i, j; + int y, x; + int err; + + (void)g; + (void)heap; + + err = sp_ecc_point_new(heap, rtd, rt); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 5 * 5, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#else + t = td; +#endif + + if (err == MP_OKAY) { + XMEMCPY(p->z, p256_norm_mod, sizeof(p256_norm_mod)); + XMEMCPY(rt->z, p256_norm_mod, sizeof(p256_norm_mod)); + + y = 0; + for (j=0,x=31; j<8; j++,x+=32) + y |= ((k[x / 52] >> (x % 52)) & 1) << j; + XMEMCPY(rt->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(rt->y, table[y].y, sizeof(table[y].y)); + rt->infinity = table[y].infinity; + for (i=30; i>=0; i--) { + y = 0; + for (j=0,x=i; j<8; j++,x+=32) + y |= ((k[x / 52] >> (x % 52)) & 1) << j; + + sp_256_proj_point_dbl_5(rt, rt, t); + XMEMCPY(p->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(p->y, table[y].y, sizeof(table[y].y)); + p->infinity = table[y].infinity; + sp_256_proj_point_add_qz1_5(rt, rt, p, t); + } + + if (map) + sp_256_map_5(r, rt, t); + else + XMEMCPY(r, rt, sizeof(sp_point)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p, 0, heap); + sp_ecc_point_free(rt, 0, heap); + + return err; +} + +#ifdef FP_ECC +#ifndef FP_ENTRIES + #define FP_ENTRIES 16 +#endif + +typedef struct sp_cache_t { + sp_digit x[5]; + sp_digit y[5]; + sp_table_entry table[256]; + uint32_t cnt; + int set; +} sp_cache_t; + +static THREAD_LS_T sp_cache_t sp_cache[FP_ENTRIES]; +static THREAD_LS_T int sp_cache_last = -1; +static THREAD_LS_T int sp_cache_inited = 0; + +#ifndef HAVE_THREAD_LS + static volatile int initCacheMutex = 0; + static wolfSSL_Mutex sp_cache_lock; +#endif + +static void sp_ecc_get_cache(sp_point* g, sp_cache_t** cache) +{ + int i, j; + uint32_t least; + + if (sp_cache_inited == 0) { + for (i=0; ix, sp_cache[i].x) & + sp_256_cmp_equal_5(g->y, sp_cache[i].y)) { + sp_cache[i].cnt++; + break; + } + } + + /* No match. */ + if (i == FP_ENTRIES) { + /* Find empty entry. */ + i = (sp_cache_last + 1) % FP_ENTRIES; + for (; i != sp_cache_last; i=(i+1)%FP_ENTRIES) { + if (!sp_cache[i].set) { + break; + } + } + + /* Evict least used. */ + if (i == sp_cache_last) { + least = sp_cache[0].cnt; + for (j=1; jx, sizeof(sp_cache[i].x)); + XMEMCPY(sp_cache[i].y, g->y, sizeof(sp_cache[i].y)); + sp_cache[i].set = 1; + sp_cache[i].cnt = 1; + } + + *cache = &sp_cache[i]; + sp_cache_last = i; +} +#endif /* FP_ECC */ + +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_5(sp_point* r, sp_point* g, sp_digit* k, + int map, void* heap) +{ +#ifndef FP_ECC + return sp_256_ecc_mulmod_fast_5(r, g, k, map, heap); +#else + sp_digit tmp[2 * 5 * 5]; + sp_cache_t* cache; + int err = MP_OKAY; + +#ifndef HAVE_THREAD_LS + if (initCacheMutex == 0) { + wc_InitMutex(&sp_cache_lock); + initCacheMutex = 1; + } + if (wc_LockMutex(&sp_cache_lock) != 0) + err = BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + if (err == MP_OKAY) { + sp_ecc_get_cache(g, &cache); + if (cache->cnt == 2) + sp_256_gen_stripe_table_5(g, cache->table, tmp, heap); + +#ifndef HAVE_THREAD_LS + wc_UnLockMutex(&sp_cache_lock); +#endif /* HAVE_THREAD_LS */ + + if (cache->cnt < 2) { + err = sp_256_ecc_mulmod_fast_5(r, g, k, map, heap); + } + else { + err = sp_256_ecc_mulmod_stripe_5(r, g, cache->table, k, + map, heap); + } + } + + return err; +#endif +} + +#endif +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * km Scalar to multiply by. + * p Point to multiply. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_256(mp_int* km, ecc_point* gm, ecc_point* r, int map, + void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point p; + sp_digit kd[5]; +#endif + sp_point* point; + sp_digit* k = NULL; + int err = MP_OKAY; + + err = sp_ecc_point_new(heap, p, point); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 5, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + if (err == MP_OKAY) { + sp_256_from_mp(k, 5, km); + sp_256_point_from_ecc_point_5(point, gm); + + err = sp_256_ecc_mulmod_5(point, point, k, map, heap); + } + if (err == MP_OKAY) + err = sp_256_point_to_ecc_point_5(point, r); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(point, 0, heap); + + return err; +} + +#ifdef WOLFSSL_SP_SMALL +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_base_5(sp_point* r, sp_digit* k, + int map, void* heap) +{ + /* No pre-computed values. */ + return sp_256_ecc_mulmod_5(r, &p256_base, k, map, heap); +} + +#else +static sp_table_entry p256_table[256] = { + /* 0 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 */ + { { 0x730d418a9143cl,0xfc5fedb60179el,0x762251075ba95l,0x55c679fb732b7l, + 0x018905f76a537l }, + { 0x25357ce95560al,0xe4ba19e45cddfl,0xd21f3258b4ab8l,0x5d85d2e88688dl, + 0x08571ff182588l }, + 0 }, + /* 2 */ + { { 0x886024147519al,0xac26b372f0202l,0x785ebc8d0981el,0x58e9a9d4a7caal, + 0x0d953c50ddbdfl }, + { 0x361ccfd590f8fl,0x6b44e6c9179d6l,0x2eb64cf72e962l,0x88f37fd961102l, + 0x0863ebb7e9eb2l }, + 0 }, + /* 3 */ + { { 0x6b6235cdb6485l,0xa22f0a2f97785l,0xf7e300b808f0el,0x80a03e68d9544l, + 0x000076055b5ffl }, + { 0x4eb9b838d2010l,0xbb3243708a763l,0x42a660654014fl,0x3ee0e0e47d398l, + 0x0830877613437l }, + 0 }, + /* 4 */ + { { 0x22fc516a0d2bbl,0x6c1a6234994f9l,0x7c62c8b0d5cc1l,0x667f9241cf3a5l, + 0x02f5e6961fd1bl }, + { 0x5c70bf5a01797l,0x4d609561925c1l,0x71fdb523d20b4l,0x0f7b04911b370l, + 0x0f648f9168d6fl }, + 0 }, + /* 5 */ + { { 0x66847e137bbbcl,0x9e8a6a0bec9e5l,0x9d73463e43446l,0x0015b1c427617l, + 0x05abe0285133dl }, + { 0xa837cc04c7dabl,0x4c43260c0792al,0x8e6cc37573d9fl,0x73830c9315627l, + 0x094bb725b6b6fl }, + 0 }, + /* 6 */ + { { 0x9b48f720f141cl,0xcd2df5bc74bbfl,0x11045c46199b3l,0xc4efdc3f61294l, + 0x0cdd6bbcb2f7dl }, + { 0x6700beaf436fdl,0x6db99326beccal,0x14f25226f647fl,0xe5f60c0fa7920l, + 0x0a361bebd4bdal }, + 0 }, + /* 7 */ + { { 0xa2558597c13c7l,0x5f50b7c3e128al,0x3c09d1dc38d63l,0x292c07039aecfl, + 0x0ba12ca09c4b5l }, + { 0x08fa459f91dfdl,0x66ceea07fb9e4l,0xd780b293af43bl,0xef4b1eceb0899l, + 0x053ebb99d701fl }, + 0 }, + /* 8 */ + { { 0x7ee31b0e63d34l,0x72a9e54fab4fel,0x5e7b5a4f46005l,0x4831c0493334dl, + 0x08589fb9206d5l }, + { 0x0f5cc6583553al,0x4ae25649e5aa7l,0x0044652087909l,0x1c4fcc9045071l, + 0x0ebb0696d0254l }, + 0 }, + /* 9 */ + { { 0x6ca15ac1647c5l,0x47c4cf5799461l,0x64dfbacb8127dl,0x7da3dc666aa37l, + 0x0eb2820cbd1b2l }, + { 0x6f8d86a87e008l,0x9d922378f3940l,0x0ccecb2d87dfal,0xda1d56ed2e428l, + 0x01f28289b55a7l }, + 0 }, + /* 10 */ + { { 0xaa0c03b89da99l,0x9eb8284022abbl,0x81c05e8a6f2d7l,0x4d6327847862bl, + 0x0337a4b5905e5l }, + { 0x7500d21f7794al,0xb77d6d7f613c6l,0x4cfd6e8207005l,0xfbd60a5a37810l, + 0x00d65e0d5f4c2l }, + 0 }, + /* 11 */ + { { 0x09bbeb5275d38l,0x450be0a358d9dl,0x73eb2654268a7l,0xa232f0762ff49l, + 0x0c23da24252f4l }, + { 0x1b84f0b94520cl,0x63b05bd78e5dal,0x4d29ea1096667l,0xcff13a4dcb869l, + 0x019de3b8cc790l }, + 0 }, + /* 12 */ + { { 0xa716c26c5fe04l,0x0b3bba1bdb183l,0x4cb712c3b28del,0xcbfd7432c586al, + 0x0e34dcbd491fcl }, + { 0x8d46baaa58403l,0x8682e97a53b40l,0x6aaa8af9a6974l,0x0f7f9e3901273l, + 0x0e7641f447b4el }, + 0 }, + /* 13 */ + { { 0x53941df64ba59l,0xec0b0242fc7d7l,0x1581859d33f10l,0x57bf4f06dfc6al, + 0x04a12df57052al }, + { 0x6338f9439dbd0l,0xd4bde53e1fbfal,0x1f1b314d3c24bl,0xea46fd5e4ffa2l, + 0x06af5aa93bb5bl }, + 0 }, + /* 14 */ + { { 0x0b69910c91999l,0x402a580491da1l,0x8cc20900a24b4l,0x40133e0094b4bl, + 0x05fe3475a66a4l }, + { 0x8cabdf93e7b4bl,0x1a7c23f91ab0fl,0xd1e6263292b50l,0xa91642e889aecl, + 0x0b544e308ecfel }, + 0 }, + /* 15 */ + { { 0x8c6e916ddfdcel,0x66f89179e6647l,0xd4e67e12c3291l,0xc20b4e8d6e764l, + 0x0e0b6b2bda6b0l }, + { 0x12df2bb7efb57l,0xde790c40070d3l,0x79bc9441aac0dl,0x3774f90336ad6l, + 0x071c023de25a6l }, + 0 }, + /* 16 */ + { { 0x8c244bfe20925l,0xc38fdce86762al,0xd38706391c19al,0x24f65a96a5d5dl, + 0x061d587d421d3l }, + { 0x673a2a37173eal,0x0853778b65e87l,0x5bab43e238480l,0xefbe10f8441e0l, + 0x0fa11fe124621l }, + 0 }, + /* 17 */ + { { 0x91f2b2cb19ffdl,0x5bb1923c231c8l,0xac5ca8e01ba8dl,0xbedcb6d03d678l, + 0x0586eb04c1f13l }, + { 0x5c6e527e8ed09l,0x3c1819ede20c3l,0x6c652fa1e81a3l,0x4f11278fd6c05l, + 0x019d5ac087086l }, + 0 }, + /* 18 */ + { { 0x9f581309a4e1fl,0x1be92700741e9l,0xfd28d20ab7de7l,0x563f26a5ef0bel, + 0x0e7c0073f7f9cl }, + { 0xd663a0ef59f76l,0x5420fcb0501f6l,0xa6602d4669b3bl,0x3c0ac08c1f7a7l, + 0x0e08504fec65bl }, + 0 }, + /* 19 */ + { { 0x8f68da031b3cal,0x9ee6da6d66f09l,0x4f246e86d1cabl,0x96b45bfd81fa9l, + 0x078f018825b09l }, + { 0xefde43a25787fl,0x0d1dccac9bb7el,0x35bfc368016f8l,0x747a0cea4877bl, + 0x043a773b87e94l }, + 0 }, + /* 20 */ + { { 0x77734d2b533d5l,0xf6a1bdddc0625l,0x79ec293673b8al,0x66b1577e7c9aal, + 0x0bb6de651c3b2l }, + { 0x9303ab65259b3l,0xd3d03a7480e7el,0xb3cfc27d6a0afl,0xb99bc5ac83d19l, + 0x060b4619a5d18l }, + 0 }, + /* 21 */ + { { 0xa38e11ae5aa1cl,0x2b49e73658bd6l,0xe5f87edb8b765l,0xffcd0b130014el, + 0x09d0f27b2aeebl }, + { 0x246317a730a55l,0x2fddbbc83aca9l,0xc019a719c955bl,0xc48d07c1dfe0al, + 0x0244a566d356el }, + 0 }, + /* 22 */ + { { 0x0394aeacf1f96l,0xa9024c271c6dbl,0x2cbd3b99f2122l,0xef692626ac1b8l, + 0x045e58c873581l }, + { 0xf479da38f9dbcl,0x46e888a040d3fl,0x6e0bed7a8aaf1l,0xb7a4945adfb24l, + 0x0c040e21cc1e4l }, + 0 }, + /* 23 */ + { { 0xaf0006f8117b6l,0xff73a35433847l,0xd9475eb651969l,0x6ec7482b35761l, + 0x01cdf5c97682cl }, + { 0x775b411f04839l,0xf448de16987dbl,0x70b32197dbeacl,0xff3db2921dd1bl, + 0x0046755f8a92dl }, + 0 }, + /* 24 */ + { { 0xac5d2bce8ffcdl,0x8b2fe61a82cc8l,0x202d6c70d53c4l,0xa5f3f6f161727l, + 0x0046e5e113b83l }, + { 0x8ff64d8007f01l,0x125af43183e7bl,0x5e1a03c7fb1efl,0x005b045c5ea63l, + 0x06e0106c3303dl }, + 0 }, + /* 25 */ + { { 0x7358488dd73b1l,0x8f995ed0d948cl,0x56a2ab7767070l,0xcf1f38385ea8cl, + 0x0442594ede901l }, + { 0xaa2c912d4b65bl,0x3b96c90c37f8fl,0xe978d1f94c234l,0xe68ed326e4a15l, + 0x0a796fa514c2el }, + 0 }, + /* 26 */ + { { 0xfb604823addd7l,0x83e56693b3359l,0xcbf3c809e2a61l,0x66e9f885b78e3l, + 0x0e4ad2da9c697l }, + { 0xf7f428e048a61l,0x8cc092d9a0357l,0x03ed8ef082d19l,0x5143fc3a1af4cl, + 0x0c5e94046c37bl }, + 0 }, + /* 27 */ + { { 0xa538c2be75f9el,0xe8cb123a78476l,0x109c04b6fd1a9l,0x4747d85e4df0bl, + 0x063283dafdb46l }, + { 0x28cf7baf2df15l,0x550ad9a7f4ce7l,0x834bcc3e592c4l,0xa938fab226adel, + 0x068bd19ab1981l }, + 0 }, + /* 28 */ + { { 0xead511887d659l,0xf4b359305ac08l,0xfe74fe33374d5l,0xdfd696986981cl, + 0x0495292f53c6fl }, + { 0x78c9e1acec896l,0x10ec5b44844a8l,0x64d60a7d964b2l,0x68376696f7e26l, + 0x00ec7530d2603l }, + 0 }, + /* 29 */ + { { 0x13a05ad2687bbl,0x6af32e21fa2dal,0xdd4607ba1f83bl,0x3f0b390f5ef51l, + 0x00f6207a66486l }, + { 0x7e3bb0f138233l,0x6c272aa718bd6l,0x6ec88aedd66b9l,0x6dcf8ed004072l, + 0x0ff0db07208edl }, + 0 }, + /* 30 */ + { { 0xfa1014c95d553l,0xfd5d680a8a749l,0xf3b566fa44052l,0x0ea3183b4317fl, + 0x0313b513c8874l }, + { 0x2e2ac08d11549l,0x0bb4dee21cb40l,0x7f2320e071ee1l,0x9f8126b987dd4l, + 0x02d3abcf986f1l }, + 0 }, + /* 31 */ + { { 0x88501815581a2l,0x56632211af4c2l,0xcab2e999a0a6dl,0x8cdf19ba7a0f0l, + 0x0c036fa10ded9l }, + { 0xe08bac1fbd009l,0x9006d1581629al,0xb9e0d8f0b68b1l,0x0194c2eb32779l, + 0x0a6b2a2c4b6d4l }, + 0 }, + /* 32 */ + { { 0x3e50f6d3549cfl,0x6ffacd665ed43l,0xe11fcb46f3369l,0x9860695bfdaccl, + 0x0810ee252af7cl }, + { 0x50fe17159bb2cl,0xbe758b357b654l,0x69fea72f7dfbel,0x17452b057e74dl, + 0x0d485717a9273l }, + 0 }, + /* 33 */ + { { 0x41a8af0cb5a98l,0x931f3110bf117l,0xb382adfd3da8fl,0x604e1994e2cbal, + 0x06a6045a72f9al }, + { 0xc0d3fa2b2411dl,0x3e510e96e0170l,0x865b3ccbe0eb8l,0x57903bcc9f738l, + 0x0d3e45cfaf9e1l }, + 0 }, + /* 34 */ + { { 0xf69bbe83f7669l,0x8272877d6bce1l,0x244278d09f8ael,0xc19c9548ae543l, + 0x0207755dee3c2l }, + { 0xd61d96fef1945l,0xefb12d28c387bl,0x2df64aa18813cl,0xb00d9fbcd1d67l, + 0x048dc5ee57154l }, + 0 }, + /* 35 */ + { { 0x790bff7e5a199l,0xcf989ccbb7123l,0xa519c79e0efb8l,0xf445c27a2bfe0l, + 0x0f2fb0aeddff6l }, + { 0x09575f0b5025fl,0xd740fa9f2241cl,0x80bfbd0550543l,0xd5258fa3c8ad3l, + 0x0a13e9015db28l }, + 0 }, + /* 36 */ + { { 0x7a350a2b65cbcl,0x722a464226f9fl,0x23f07a10b04b9l,0x526f265ce241el, + 0x02bf0d6b01497l }, + { 0x4dd3f4b216fb7l,0x67fbdda26ad3dl,0x708505cf7d7b8l,0xe89faeb7b83f6l, + 0x042a94a5a162fl }, + 0 }, + /* 37 */ + { { 0x6ad0beaadf191l,0x9025a268d7584l,0x94dc1f60f8a48l,0xde3de86030504l, + 0x02c2dd969c65el }, + { 0x2171d93849c17l,0xba1da250dd6d0l,0xc3a5485460488l,0x6dbc4810c7063l, + 0x0f437fa1f42c5l }, + 0 }, + /* 38 */ + { { 0x0d7144a0f7dabl,0x931776e9ac6aal,0x5f397860f0497l,0x7aa852c0a050fl, + 0x0aaf45b335470l }, + { 0x37c33c18d364al,0x063e49716585el,0x5ec5444d40b9bl,0x72bcf41716811l, + 0x0cdf6310df4f2l }, + 0 }, + /* 39 */ + { { 0x3c6238ea8b7efl,0x1885bc2287747l,0xbda8e3408e935l,0x2ff2419567722l, + 0x0f0d008bada9el }, + { 0x2671d2414d3b1l,0x85b019ea76291l,0x53bcbdbb37549l,0x7b8b5c61b96d4l, + 0x05bd5c2f5ca88l }, + 0 }, + /* 40 */ + { { 0xf469ef49a3154l,0x956e2b2e9aef0l,0xa924a9c3e85a5l,0x471945aaec1eal, + 0x0aa12dfc8a09el }, + { 0x272274df69f1dl,0x2ca2ff5e7326fl,0x7a9dd44e0e4c8l,0xa901b9d8ce73bl, + 0x06c036e73e48cl }, + 0 }, + /* 41 */ + { { 0xae12a0f6e3138l,0x0025ad345a5cfl,0x5672bc56966efl,0xbe248993c64b4l, + 0x0292ff65896afl }, + { 0x50d445e213402l,0x274392c9fed52l,0xa1c72e8f6580el,0x7276097b397fdl, + 0x0644e0c90311bl }, + 0 }, + /* 42 */ + { { 0x421e1a47153f0l,0x79920418c9e1el,0x05d7672b86c3bl,0x9a7793bdce877l, + 0x0f25ae793cab7l }, + { 0x194a36d869d0cl,0x824986c2641f3l,0x96e945e9d55c8l,0x0a3e49fb5ea30l, + 0x039b8e65313dbl }, + 0 }, + /* 43 */ + { { 0x54200b6fd2e59l,0x669255c98f377l,0xe2a573935e2c0l,0xdb06d9dab21a0l, + 0x039122f2f0f19l }, + { 0xce1e003cad53cl,0x0fe65c17e3cfbl,0xaa13877225b2cl,0xff8d72baf1d29l, + 0x08de80af8ce80l }, + 0 }, + /* 44 */ + { { 0xea8d9207bbb76l,0x7c21782758afbl,0xc0436b1921c7el,0x8c04dfa2b74b1l, + 0x0871949062e36l }, + { 0x928bba3993df5l,0xb5f3b3d26ab5fl,0x5b55050639d75l,0xfde1011aa78a8l, + 0x0fc315e6a5b74l }, + 0 }, + /* 45 */ + { { 0xfd41ae8d6ecfal,0xf61aec7f86561l,0x924741d5f8c44l,0x908898452a7b4l, + 0x0e6d4a7adee38l }, + { 0x52ed14593c75dl,0xa4dd271162605l,0xba2c7db70a70dl,0xae57d2aede937l, + 0x035dfaf9a9be2l }, + 0 }, + /* 46 */ + { { 0x56fcdaa736636l,0x97ae2cab7e6b9l,0xf34996609f51dl,0x0d2bfb10bf410l, + 0x01da5c7d71c83l }, + { 0x1e4833cce6825l,0x8ff9573c3b5c4l,0x23036b815ad11l,0xb9d6a28552c7fl, + 0x07077c0fddbf4l }, + 0 }, + /* 47 */ + { { 0x3ff8d46b9661cl,0x6b0d2cfd71bf6l,0x847f8f7a1dfd3l,0xfe440373e140al, + 0x053a8632ee50el }, + { 0x6ff68696d8051l,0x95c74f468a097l,0xe4e26bddaec0cl,0xfcc162994dc35l, + 0x0028ca76d34e1l }, + 0 }, + /* 48 */ + { { 0xd47dcfc9877eel,0x10801d0002d11l,0x4c260b6c8b362l,0xf046d002c1175l, + 0x004c17cd86962l }, + { 0xbd094b0daddf5l,0x7524ce55c06d9l,0x2da03b5bea235l,0x7474663356e67l, + 0x0f7ba4de9fed9l }, + 0 }, + /* 49 */ + { { 0xbfa34ebe1263fl,0x3571ae7ce6d0dl,0x2a6f523557637l,0x1c41d24405538l, + 0x0e31f96005213l }, + { 0xb9216ea6b6ec6l,0x2e73c2fc44d1bl,0x9d0a29437a1d1l,0xd47bc10e7eac8l, + 0x0aa3a6259ce34l }, + 0 }, + /* 50 */ + { { 0xf9df536f3dcd3l,0x50d2bf7360fbcl,0xf504f5b6cededl,0xdaee491710fadl, + 0x02398dd627e79l }, + { 0x705a36d09569el,0xbb5149f769cf4l,0x5f6034cea0619l,0x6210ff9c03773l, + 0x05717f5b21c04l }, + 0 }, + /* 51 */ + { { 0x229c921dd895el,0x0040c284519fel,0xd637ecd8e5185l,0x28defa13d2391l, + 0x0660a2c560e3cl }, + { 0xa88aed67fcbd0l,0x780ea9f0969ccl,0x2e92b4dc84724l,0x245332b2f4817l, + 0x0624ee54c4f52l }, + 0 }, + /* 52 */ + { { 0x49ce4d897ecccl,0xd93f9880aa095l,0x43a7c204d49d1l,0xfbc0723c24230l, + 0x04f392afb92bdl }, + { 0x9f8fa7de44fd9l,0xe457b32156696l,0x68ebc3cb66cfbl,0x399cdb2fa8033l, + 0x08a3e7977ccdbl }, + 0 }, + /* 53 */ + { { 0x1881f06c4b125l,0x00f6e3ca8cddel,0xc7a13e9ae34e3l,0x4404ef6999de5l, + 0x03888d02370c2l }, + { 0x8035644f91081l,0x615f015504762l,0x32cd36e3d9fcfl,0x23361827edc86l, + 0x0a5e62e471810l }, + 0 }, + /* 54 */ + { { 0x25ee32facd6c8l,0x5454bcbc661a8l,0x8df9931699c63l,0x5adc0ce3edf79l, + 0x02c4768e6466al }, + { 0x6ff8c90a64bc9l,0x20e4779f5cb34l,0xc05e884630a60l,0x52a0d949d064bl, + 0x07b5e6441f9e6l }, + 0 }, + /* 55 */ + { { 0x9422c1d28444al,0xd8be136a39216l,0xb0c7fcee996c5l,0x744a2387afe5fl, + 0x0b8af73cb0c8dl }, + { 0xe83aa338b86fdl,0x58a58a5cff5fdl,0x0ac9433fee3f1l,0x0895c9ee8f6f2l, + 0x0a036395f7f3fl }, + 0 }, + /* 56 */ + { { 0x3c6bba10f7770l,0x81a12a0e248c7l,0x1bc2b9fa6f16dl,0xb533100df6825l, + 0x04be36b01875fl }, + { 0x6086e9fb56dbbl,0x8b07e7a4f8922l,0x6d52f20306fefl,0x00c0eeaccc056l, + 0x08cbc9a871bdcl }, + 0 }, + /* 57 */ + { { 0x1895cc0dac4abl,0x40712ff112e13l,0xa1cee57a874a4l,0x35f86332ae7c6l, + 0x044e7553e0c08l }, + { 0x03fff7734002dl,0x8b0b34425c6d5l,0xe8738b59d35cbl,0xfc1895f702760l, + 0x0470a683a5eb8l }, + 0 }, + /* 58 */ + { { 0x761dc90513482l,0x2a01e9276a81bl,0xce73083028720l,0xc6efcda441ee0l, + 0x016410690c63dl }, + { 0x34a066d06a2edl,0x45189b100bf50l,0xb8218c9dd4d77l,0xbb4fd914ae72al, + 0x0d73479fd7abcl }, + 0 }, + /* 59 */ + { { 0xefb165ad4c6e5l,0x8f5b06d04d7edl,0x575cb14262cf0l,0x666b12ed5bb18l, + 0x0816469e30771l }, + { 0xb9d79561e291el,0x22c1de1661d7al,0x35e0513eb9dafl,0x3f9cf49827eb1l, + 0x00a36dd23f0ddl }, + 0 }, + /* 60 */ + { { 0xd32c741d5533cl,0x9e8684628f098l,0x349bd117c5f5al,0xb11839a228adel, + 0x0e331dfd6fdbal }, + { 0x0ab686bcc6ed8l,0xbdef7a260e510l,0xce850d77160c3l,0x33899063d9a7bl, + 0x0d3b4782a492el }, + 0 }, + /* 61 */ + { { 0x9b6e8f3821f90l,0xed66eb7aada14l,0xa01311692edd9l,0xa5bd0bb669531l, + 0x07281275a4c86l }, + { 0x858f7d3ff47e5l,0xbc61016441503l,0xdfd9bb15e1616l,0x505962b0f11a7l, + 0x02c062e7ece14l }, + 0 }, + /* 62 */ + { { 0xf996f0159ac2el,0x36cbdb2713a76l,0x8e46047281e77l,0x7ef12ad6d2880l, + 0x0282a35f92c4el }, + { 0x54b1ec0ce5cd2l,0xc91379c2299c3l,0xe82c11ecf99efl,0x2abd992caf383l, + 0x0c71cd513554dl }, + 0 }, + /* 63 */ + { { 0x5de9c09b578f4l,0x58e3affa7a488l,0x9182f1f1884e2l,0xf3a38f76b1b75l, + 0x0c50f6740cf47l }, + { 0x4adf3374b68eal,0x2369965fe2a9cl,0x5a53050a406f3l,0x58dc2f86a2228l, + 0x0b9ecb3a72129l }, + 0 }, + /* 64 */ + { { 0x8410ef4f8b16al,0xfec47b266a56fl,0xd9c87c197241al,0xab1b0a406b8e6l, + 0x0803f3e02cd42l }, + { 0x309a804dbec69l,0xf73bbad05f7f0l,0xd8e197fa83b85l,0xadc1c6097273al, + 0x0c097440e5067l }, + 0 }, + /* 65 */ + { { 0xa56f2c379ab34l,0x8b841df8d1846l,0x76c68efa8ee06l,0x1f30203144591l, + 0x0f1af32d5915fl }, + { 0x375315d75bd50l,0xbaf72f67bc99cl,0x8d7723f837cffl,0x1c8b0613a4184l, + 0x023d0f130e2d4l }, + 0 }, + /* 66 */ + { { 0xab6edf41500d9l,0xe5fcbeada8857l,0x97259510d890al,0xfadd52fe86488l, + 0x0b0288dd6c0a3l }, + { 0x20f30650bcb08l,0x13695d6e16853l,0x989aa7671af63l,0xc8d231f520a7bl, + 0x0ffd3724ff408l }, + 0 }, + /* 67 */ + { { 0x68e64b458e6cbl,0x20317a5d28539l,0xaa75f56992dadl,0x26df3814ae0b7l, + 0x0f5590f4ad78cl }, + { 0x24bd3cf0ba55al,0x4a0c778bae0fcl,0x83b674a0fc472l,0x4a201ce9864f6l, + 0x018d6da54f6f7l }, + 0 }, + /* 68 */ + { { 0x3e225d5be5a2bl,0x835934f3c6ed9l,0x2626ffc6fe799l,0x216a431409262l, + 0x050bbb4d97990l }, + { 0x191c6e57ec63el,0x40181dcdb2378l,0x236e0f665422cl,0x49c341a8099b0l, + 0x02b10011801fel }, + 0 }, + /* 69 */ + { { 0x8b5c59b391593l,0xa2598270fcfc6l,0x19adcbbc385f5l,0xae0c7144f3aadl, + 0x0dd55899983fbl }, + { 0x88b8e74b82ff4l,0x4071e734c993bl,0x3c0322ad2e03cl,0x60419a7a9eaf4l, + 0x0e6e4c551149dl }, + 0 }, + /* 70 */ + { { 0x655bb1e9af288l,0x64f7ada93155fl,0xb2820e5647e1al,0x56ff43697e4bcl, + 0x051e00db107edl }, + { 0x169b8771c327el,0x0b4a96c2ad43dl,0xdeb477929cdb2l,0x9177c07d51f53l, + 0x0e22f42414982l }, + 0 }, + /* 71 */ + { { 0x5e8f4635f1abbl,0xb568538874cd4l,0x5a8034d7edc0cl,0x48c9c9472c1fbl, + 0x0f709373d52dcl }, + { 0x966bba8af30d6l,0x4af137b69c401l,0x361c47e95bf5fl,0x5b113966162a9l, + 0x0bd52d288e727l }, + 0 }, + /* 72 */ + { { 0x55c7a9c5fa877l,0x727d3a3d48ab1l,0x3d189d817dad6l,0x77a643f43f9e7l, + 0x0a0d0f8e4c8aal }, + { 0xeafd8cc94f92dl,0xbe0c4ddb3a0bbl,0x82eba14d818c8l,0x6a0022cc65f8bl, + 0x0a56c78c7946dl }, + 0 }, + /* 73 */ + { { 0x2391b0dd09529l,0xa63daddfcf296l,0xb5bf481803e0el,0x367a2c77351f5l, + 0x0d8befdf8731al }, + { 0x19d42fc0157f4l,0xd7fec8e650ab9l,0x2d48b0af51cael,0x6478cdf9cb400l, + 0x0854a68a5ce9fl }, + 0 }, + /* 74 */ + { { 0x5f67b63506ea5l,0x89a4fe0d66dc3l,0xe95cd4d9286c4l,0x6a953f101d3bfl, + 0x05cacea0b9884l }, + { 0xdf60c9ceac44dl,0xf4354d1c3aa90l,0xd5dbabe3db29al,0xefa908dd3de8al, + 0x0e4982d1235e4l }, + 0 }, + /* 75 */ + { { 0x04a22c34cd55el,0xb32680d132231l,0xfa1d94358695bl,0x0499fb345afa1l, + 0x08046b7f616b2l }, + { 0x3581e38e7d098l,0x8df46f0b70b53l,0x4cb78c4d7f61el,0xaf5530dea9ea4l, + 0x0eb17ca7b9082l }, + 0 }, + /* 76 */ + { { 0x1b59876a145b9l,0x0fc1bc71ec175l,0x92715bba5cf6bl,0xe131d3e035653l, + 0x0097b00bafab5l }, + { 0x6c8e9565f69e1l,0x5ab5be5199aa6l,0xa4fd98477e8f7l,0xcc9e6033ba11dl, + 0x0f95c747bafdbl }, + 0 }, + /* 77 */ + { { 0xf01d3bebae45el,0xf0c4bc6955558l,0xbc64fc6a8ebe9l,0xd837aeb705b1dl, + 0x03512601e566el }, + { 0x6f1e1fa1161cdl,0xd54c65ef87933l,0x24f21e5328ab8l,0xab6b4757eee27l, + 0x00ef971236068l }, + 0 }, + /* 78 */ + { { 0x98cf754ca4226l,0x38f8642c8e025l,0x68e17905eede1l,0xbc9548963f744l, + 0x0fc16d9333b4fl }, + { 0x6fb31e7c800cal,0x312678adaabe9l,0xff3e8b5138063l,0x7a173d6244976l, + 0x014ca4af1b95dl }, + 0 }, + /* 79 */ + { { 0x771babd2f81d5l,0x6901f7d1967a4l,0xad9c9071a5f9dl,0x231dd898bef7cl, + 0x04057b063f59cl }, + { 0xd82fe89c05c0al,0x6f1dc0df85bffl,0x35a16dbe4911cl,0x0b133befccaeal, + 0x01c3b5d64f133l }, + 0 }, + /* 80 */ + { { 0x14bfe80ec21fel,0x6ac255be825fel,0xf4a5d67f6ce11l,0x63af98bc5a072l, + 0x0fad27148db7el }, + { 0x0b6ac29ab05b3l,0x3c4e251ae690cl,0x2aade7d37a9a8l,0x1a840a7dc875cl, + 0x077387de39f0el }, + 0 }, + /* 81 */ + { { 0xecc49a56c0dd7l,0xd846086c741e9l,0x505aecea5cffcl,0xc47e8f7a1408fl, + 0x0b37b85c0bef0l }, + { 0x6b6e4cc0e6a8fl,0xbf6b388f23359l,0x39cef4efd6d4bl,0x28d5aba453facl, + 0x09c135ac8f9f6l }, + 0 }, + /* 82 */ + { { 0xa320284e35743l,0xb185a3cdef32al,0xdf19819320d6al,0x851fb821b1761l, + 0x05721361fc433l }, + { 0xdb36a71fc9168l,0x735e5c403c1f0l,0x7bcd8f55f98bal,0x11bdf64ca87e3l, + 0x0dcbac3c9e6bbl }, + 0 }, + /* 83 */ + { { 0xd99684518cbe2l,0x189c9eb04ef01l,0x47feebfd242fcl,0x6862727663c7el, + 0x0b8c1c89e2d62l }, + { 0x58bddc8e1d569l,0xc8b7d88cd051al,0x11f31eb563809l,0x22d426c27fd9fl, + 0x05d23bbda2f94l }, + 0 }, + /* 84 */ + { { 0xc729495c8f8bel,0x803bf362bf0a1l,0xf63d4ac2961c4l,0xe9009e418403dl, + 0x0c109f9cb91ecl }, + { 0x095d058945705l,0x96ddeb85c0c2dl,0xa40449bb9083dl,0x1ee184692b8d7l, + 0x09bc3344f2eeel }, + 0 }, + /* 85 */ + { { 0xae35642913074l,0x2748a542b10d5l,0x310732a55491bl,0x4cc1469ca665bl, + 0x029591d525f1al }, + { 0xf5b6bb84f983fl,0x419f5f84e1e76l,0x0baa189be7eefl,0x332c1200d4968l, + 0x06376551f18efl }, + 0 }, + /* 86 */ + { { 0x5f14e562976ccl,0xe60ef12c38bdal,0xcca985222bca3l,0x987abbfa30646l, + 0x0bdb79dc808e2l }, + { 0xcb5c9cb06a772l,0xaafe536dcefd2l,0xc2b5db838f475l,0xc14ac2a3e0227l, + 0x08ee86001add3l }, + 0 }, + /* 87 */ + { { 0x96981a4ade873l,0x4dc4fba48ccbel,0xa054ba57ee9aal,0xaa4b2cee28995l, + 0x092e51d7a6f77l }, + { 0xbafa87190a34dl,0x5bf6bd1ed1948l,0xcaf1144d698f7l,0xaaaad00ee6e30l, + 0x05182f86f0a56l }, + 0 }, + /* 88 */ + { { 0x6212c7a4cc99cl,0x683e6d9ca1fbal,0xac98c5aff609bl,0xa6f25dbb27cb5l, + 0x091dcab5d4073l }, + { 0x6cc3d5f575a70l,0x396f8d87fa01bl,0x99817360cb361l,0x4f2b165d4e8c8l, + 0x017a0cedb9797l }, + 0 }, + /* 89 */ + { { 0x61e2a076c8d3al,0x39210f924b388l,0x3a835d9701aadl,0xdf4194d0eae41l, + 0x02e8ce36c7f4cl }, + { 0x73dab037a862bl,0xb760e4c8fa912l,0x3baf2dd01ba9bl,0x68f3f96453883l, + 0x0f4ccc6cb34f6l }, + 0 }, + /* 90 */ + { { 0xf525cf1f79687l,0x9592efa81544el,0x5c78d297c5954l,0xf3c9e1231741al, + 0x0ac0db4889a0dl }, + { 0xfc711df01747fl,0x58ef17df1386bl,0xccb6bb5592b93l,0x74a2e5880e4f5l, + 0x095a64a6194c9l }, + 0 }, + /* 91 */ + { { 0x1efdac15a4c93l,0x738258514172cl,0x6cb0bad40269bl,0x06776a8dfb1c1l, + 0x0231e54ba2921l }, + { 0xdf9178ae6d2dcl,0x3f39112918a70l,0xe5b72234d6aa6l,0x31e1f627726b5l, + 0x0ab0be032d8a7l }, + 0 }, + /* 92 */ + { { 0xad0e98d131f2dl,0xe33b04f101097l,0x5e9a748637f09l,0xa6791ac86196dl, + 0x0f1bcc8802cf6l }, + { 0x69140e8daacb4l,0x5560f6500925cl,0x77937a63c4e40l,0xb271591cc8fc4l, + 0x0851694695aebl }, + 0 }, + /* 93 */ + { { 0x5c143f1dcf593l,0x29b018be3bde3l,0xbdd9d3d78202bl,0x55d8e9cdadc29l, + 0x08f67d9d2daadl }, + { 0x116567481ea5fl,0xe9e34c590c841l,0x5053fa8e7d2ddl,0x8b5dffdd43f40l, + 0x0f84572b9c072l }, + 0 }, + /* 94 */ + { { 0xa7a7197af71c9l,0x447a7365655e1l,0xe1d5063a14494l,0x2c19a1b4ae070l, + 0x0edee2710616bl }, + { 0x034f511734121l,0x554a25e9f0b2fl,0x40c2ecf1cac6el,0xd7f48dc148f3al, + 0x09fd27e9b44ebl }, + 0 }, + /* 95 */ + { { 0x7658af6e2cb16l,0x2cfe5919b63ccl,0x68d5583e3eb7dl,0xf3875a8c58161l, + 0x0a40c2fb6958fl }, + { 0xec560fedcc158l,0xc655f230568c9l,0xa307e127ad804l,0xdecfd93967049l, + 0x099bc9bb87dc6l }, + 0 }, + /* 96 */ + { { 0x9521d927dafc6l,0x695c09cd1984al,0x9366dde52c1fbl,0x7e649d9581a0fl, + 0x09abe210ba16dl }, + { 0xaf84a48915220l,0x6a4dd816c6480l,0x681ca5afa7317l,0x44b0c7d539871l, + 0x07881c25787f3l }, + 0 }, + /* 97 */ + { { 0x99b51e0bcf3ffl,0xc5127f74f6933l,0xd01d9680d02cbl,0x89408fb465a2dl, + 0x015e6e319a30el }, + { 0xd6e0d3e0e05f4l,0xdc43588404646l,0x4f850d3fad7bdl,0x72cebe61c7d1cl, + 0x00e55facf1911l }, + 0 }, + /* 98 */ + { { 0xd9806f8787564l,0x2131e85ce67e9l,0x819e8d61a3317l,0x65776b0158cabl, + 0x0d73d09766fe9l }, + { 0x834251eb7206el,0x0fc618bb42424l,0xe30a520a51929l,0xa50b5dcbb8595l, + 0x09250a3748f15l }, + 0 }, + /* 99 */ + { { 0xf08f8be577410l,0x035077a8c6cafl,0xc0a63a4fd408al,0x8c0bf1f63289el, + 0x077414082c1ccl }, + { 0x40fa6eb0991cdl,0x6649fdc29605al,0x324fd40c1ca08l,0x20b93a68a3c7bl, + 0x08cb04f4d12ebl }, + 0 }, + /* 100 */ + { { 0x2d0556906171cl,0xcdb0240c3fb1cl,0x89068419073e9l,0x3b51db8e6b4fdl, + 0x0e4e429ef4712l }, + { 0xdd53c38ec36f4l,0x01ff4b6a270b8l,0x79a9a48f9d2dcl,0x65525d066e078l, + 0x037bca2ff3c6el }, + 0 }, + /* 101 */ + { { 0x2e3c7df562470l,0xa2c0964ac94cdl,0x0c793be44f272l,0xb22a7c6d5df98l, + 0x059913edc3002l }, + { 0x39a835750592al,0x80e783de027a1l,0xa05d64f99e01dl,0xe226cf8c0375el, + 0x043786e4ab013l }, + 0 }, + /* 102 */ + { { 0x2b0ed9e56b5a6l,0xa6d9fc68f9ff3l,0x97846a70750d9l,0x9e7aec15e8455l, + 0x08638ca98b7e7l }, + { 0xae0960afc24b2l,0xaf4dace8f22f5l,0xecba78f05398el,0xa6f03b765dd0al, + 0x01ecdd36a7b3al }, + 0 }, + /* 103 */ + { { 0xacd626c5ff2f3l,0xc02873a9785d3l,0x2110d54a2d516l,0xf32dad94c9fadl, + 0x0d85d0f85d459l }, + { 0x00b8d10b11da3l,0x30a78318c49f7l,0x208decdd2c22cl,0x3c62556988f49l, + 0x0a04f19c3b4edl }, + 0 }, + /* 104 */ + { { 0x924c8ed7f93bdl,0x5d392f51f6087l,0x21b71afcb64acl,0x50b07cae330a8l, + 0x092b2eeea5c09l }, + { 0xc4c9485b6e235l,0xa92936c0f085al,0x0508891ab2ca4l,0x276c80faa6b3el, + 0x01ee782215834l }, + 0 }, + /* 105 */ + { { 0xa2e00e63e79f7l,0xb2f399d906a60l,0x607c09df590e7l,0xe1509021054a6l, + 0x0f3f2ced857a6l }, + { 0x510f3f10d9b55l,0xacd8642648200l,0x8bd0e7c9d2fcfl,0xe210e5631aa7el, + 0x00f56a4543da3l }, + 0 }, + /* 106 */ + { { 0x1bffa1043e0dfl,0xcc9c007e6d5b2l,0x4a8517a6c74b6l,0xe2631a656ec0dl, + 0x0bd8f17411969l }, + { 0xbbb86beb7494al,0x6f45f3b8388a9l,0x4e5a79a1567d4l,0xfa09df7a12a7al, + 0x02d1a1c3530ccl }, + 0 }, + /* 107 */ + { { 0xe3813506508dal,0xc4a1d795a7192l,0xa9944b3336180l,0xba46cddb59497l, + 0x0a107a65eb91fl }, + { 0x1d1c50f94d639l,0x758a58b7d7e6dl,0xd37ca1c8b4af3l,0x9af21a7c5584bl, + 0x0183d760af87al }, + 0 }, + /* 108 */ + { { 0x697110dde59a4l,0x070e8bef8729dl,0xf2ebe78f1ad8dl,0xd754229b49634l, + 0x01d44179dc269l }, + { 0xdc0cf8390d30el,0x530de8110cb32l,0xbc0339a0a3b27l,0xd26231af1dc52l, + 0x0771f9cc29606l }, + 0 }, + /* 109 */ + { { 0x93e7785040739l,0xb98026a939999l,0x5f8fc2644539dl,0x718ecf40f6f2fl, + 0x064427a310362l }, + { 0xf2d8785428aa8l,0x3febfb49a84f4l,0x23d01ac7b7adcl,0x0d6d201b2c6dfl, + 0x049d9b7496ae9l }, + 0 }, + /* 110 */ + { { 0x8d8bc435d1099l,0x4e8e8d1a08cc7l,0xcb68a412adbcdl,0x544502c2e2a02l, + 0x09037d81b3f60l }, + { 0xbac27074c7b61l,0xab57bfd72e7cdl,0x96d5352fe2031l,0x639c61ccec965l, + 0x008c3de6a7cc0l }, + 0 }, + /* 111 */ + { { 0xdd020f6d552abl,0x9805cd81f120fl,0x135129156baffl,0x6b2f06fb7c3e9l, + 0x0c69094424579l }, + { 0x3ae9c41231bd1l,0x875cc5820517bl,0x9d6a1221eac6el,0x3ac0208837abfl, + 0x03fa3db02cafel }, + 0 }, + /* 112 */ + { { 0xa3e6505058880l,0xef643943f2d75l,0xab249257da365l,0x08ff4147861cfl, + 0x0c5c4bdb0fdb8l }, + { 0x13e34b272b56bl,0x9511b9043a735l,0x8844969c8327el,0xb6b5fd8ce37dfl, + 0x02d56db9446c2l }, + 0 }, + /* 113 */ + { { 0x1782fff46ac6bl,0x2607a2e425246l,0x9a48de1d19f79l,0xba42fafea3c40l, + 0x00f56bd9de503l }, + { 0xd4ed1345cda49l,0xfc816f299d137l,0xeb43402821158l,0xb5f1e7c6a54aal, + 0x04003bb9d1173l }, + 0 }, + /* 114 */ + { { 0xe8189a0803387l,0xf539cbd4043b8l,0x2877f21ece115l,0x2f9e4297208ddl, + 0x053765522a07fl }, + { 0x80a21a8a4182dl,0x7a3219df79a49l,0xa19a2d4a2bbd0l,0x4549674d0a2e1l, + 0x07a056f586c5dl }, + 0 }, + /* 115 */ + { { 0xb25589d8a2a47l,0x48c3df2773646l,0xbf0d5395b5829l,0x267551ec000eal, + 0x077d482f17a1al }, + { 0x1bd9587853948l,0xbd6cfbffeeb8al,0x0681e47a6f817l,0xb0e4ab6ec0578l, + 0x04115012b2b38l }, + 0 }, + /* 116 */ + { { 0x3f0f46de28cedl,0x609b13ec473c7l,0xe5c63921d5da7l,0x094661b8ce9e6l, + 0x0cdf04572fbeal }, + { 0x3c58b6c53c3b0l,0x10447b843c1cbl,0xcb9780e97fe3cl,0x3109fb2b8ae12l, + 0x0ee703dda9738l }, + 0 }, + /* 117 */ + { { 0x15140ff57e43al,0xd3b1b811b8345l,0xf42b986d44660l,0xce212b3b5dff8l, + 0x02a0ad89da162l }, + { 0x4a6946bc277bal,0x54c141c27664el,0xabf6274c788c9l,0x4659141aa64ccl, + 0x0d62d0b67ac2bl }, + 0 }, + /* 118 */ + { { 0x5d87b2c054ac4l,0x59f27df78839cl,0x18128d6570058l,0x2426edf7cbf3bl, + 0x0b39a23f2991cl }, + { 0x84a15f0b16ae5l,0xb1a136f51b952l,0x27007830c6a05l,0x4cc51d63c137fl, + 0x004ed0092c067l }, + 0 }, + /* 119 */ + { { 0x185d19ae90393l,0x294a3d64e61f4l,0x854fc143047b4l,0xc387ae0001a69l, + 0x0a0a91fc10177l }, + { 0xa3f01ae2c831el,0x822b727e16ff0l,0xa3075b4bb76ael,0x0c418f12c8a15l, + 0x0084cf9889ed2l }, + 0 }, + /* 120 */ + { { 0x509defca6becfl,0x807dffb328d98l,0x778e8b92fceael,0xf77e5d8a15c44l, + 0x0d57955b273abl }, + { 0xda79e31b5d4f1l,0x4b3cfa7a1c210l,0xc27c20baa52f0l,0x41f1d4d12089dl, + 0x08e14ea4202d1l }, + 0 }, + /* 121 */ + { { 0x50345f2897042l,0x1f43402c4aeedl,0x8bdfb218d0533l,0xd158c8d9c194cl, + 0x0597e1a372aa4l }, + { 0x7ec1acf0bd68cl,0xdcab024945032l,0x9fe3e846d4be0l,0x4dea5b9c8d7acl, + 0x0ca3f0236199bl }, + 0 }, + /* 122 */ + { { 0xa10b56170bd20l,0xf16d3f5de7592l,0x4b2ade20ea897l,0x07e4a3363ff14l, + 0x0bde7fd7e309cl }, + { 0xbb6d2b8f5432cl,0xcbe043444b516l,0x8f95b5a210dc1l,0xd1983db01e6ffl, + 0x0b623ad0e0a7dl }, + 0 }, + /* 123 */ + { { 0xbd67560c7b65bl,0x9023a4a289a75l,0x7b26795ab8c55l,0x137bf8220fd0dl, + 0x0d6aa2e4658ecl }, + { 0xbc00b5138bb85l,0x21d833a95c10al,0x702a32e8c31d1l,0x513ab24ff00b1l, + 0x0111662e02dccl }, + 0 }, + /* 124 */ + { { 0x14015efb42b87l,0x701b6c4dff781l,0x7d7c129bd9f5dl,0x50f866ecccd7al, + 0x0db3ee1cb94b7l }, + { 0xf3db0f34837cfl,0x8bb9578d4fb26l,0xc56657de7eed1l,0x6a595d2cdf937l, + 0x0886a64425220l }, + 0 }, + /* 125 */ + { { 0x34cfb65b569eal,0x41f72119c13c2l,0x15a619e200111l,0x17bc8badc85dal, + 0x0a70cf4eb018al }, + { 0xf97ae8c4a6a65l,0x270134378f224l,0xf7e096036e5cfl,0x7b77be3a609e4l, + 0x0aa4772abd174l }, + 0 }, + /* 126 */ + { { 0x761317aa60cc0l,0x610368115f676l,0xbc1bb5ac79163l,0xf974ded98bb4bl, + 0x0611a6ddc30fal }, + { 0x78cbcc15ee47al,0x824e0d96a530el,0xdd9ed882e8962l,0x9c8836f35adf3l, + 0x05cfffaf81642l }, + 0 }, + /* 127 */ + { { 0x54cff9b7a99cdl,0x9d843c45a1c0dl,0x2c739e17bf3b9l,0x994c038a908f6l, + 0x06e5a6b237dc1l }, + { 0xb454e0ba5db77l,0x7facf60d63ef8l,0x6608378b7b880l,0xabcce591c0c67l, + 0x0481a238d242dl }, + 0 }, + /* 128 */ + { { 0x17bc035d0b34al,0x6b8327c0a7e34l,0xc0362d1440b38l,0xf9438fb7262dal, + 0x02c41114ce0cdl }, + { 0x5cef1ad95a0b1l,0xa867d543622bal,0x1e486c9c09b37l,0x929726d6cdd20l, + 0x020477abf42ffl }, + 0 }, + /* 129 */ + { { 0x5173c18d65dbfl,0x0e339edad82f7l,0xcf1001c77bf94l,0x96b67022d26bdl, + 0x0ac66409ac773l }, + { 0xbb36fc6261cc3l,0xc9190e7e908b0l,0x45e6c10213f7bl,0x2f856541cebaal, + 0x0ce8e6975cc12l }, + 0 }, + /* 130 */ + { { 0x21b41bc0a67d2l,0x0a444d248a0f1l,0x59b473762d476l,0xb4a80e044f1d6l, + 0x008fde365250bl }, + { 0xec3da848bf287l,0x82d3369d6eacel,0x2449482c2a621l,0x6cd73582dfdc9l, + 0x02f7e2fd2565dl }, + 0 }, + /* 131 */ + { { 0xb92dbc3770fa7l,0x5c379043f9ae4l,0x7761171095e8dl,0x02ae54f34e9d1l, + 0x0c65be92e9077l }, + { 0x8a303f6fd0a40l,0xe3bcce784b275l,0xf9767bfe7d822l,0x3b3a7ae4f5854l, + 0x04bff8e47d119l }, + 0 }, + /* 132 */ + { { 0x1d21f00ff1480l,0x7d0754db16cd4l,0xbe0f3ea2ab8fbl,0x967dac81d2efbl, + 0x03e4e4ae65772l }, + { 0x8f36d3c5303e6l,0x4b922623977e1l,0x324c3c03bd999l,0x60289ed70e261l, + 0x05388aefd58ecl }, + 0 }, + /* 133 */ + { { 0x317eb5e5d7713l,0xee75de49daad1l,0x74fb26109b985l,0xbe0e32f5bc4fcl, + 0x05cf908d14f75l }, + { 0x435108e657b12l,0xa5b96ed9e6760l,0x970ccc2bfd421l,0x0ce20e29f51f8l, + 0x0a698ba4060f0l }, + 0 }, + /* 134 */ + { { 0xb1686ef748fecl,0xa27e9d2cf973dl,0xe265effe6e755l,0xad8d630b6544cl, + 0x0b142ef8a7aebl }, + { 0x1af9f17d5770al,0x672cb3412fad3l,0xf3359de66af3bl,0x50756bd60d1bdl, + 0x0d1896a965851l }, + 0 }, + /* 135 */ + { { 0x957ab33c41c08l,0xac5468e2e1ec5l,0xc472f6c87de94l,0xda3918816b73al, + 0x0267b0e0b7981l }, + { 0x54e5d8e62b988l,0x55116d21e76e5l,0xd2a6f99d8ddc7l,0x93934610faf03l, + 0x0b54e287aa111l }, + 0 }, + /* 136 */ + { { 0x122b5178a876bl,0xff085104b40a0l,0x4f29f7651ff96l,0xd4e6050b31ab1l, + 0x084abb28b5f87l }, + { 0xd439f8270790al,0x9d85e3f46bd5el,0xc1e22122d6cb5l,0x564075f55c1b6l, + 0x0e5436f671765l }, + 0 }, + /* 137 */ + { { 0x9025e2286e8d5l,0xb4864453be53fl,0x408e3a0353c95l,0xe99ed832f5bdel, + 0x00404f68b5b9cl }, + { 0x33bdea781e8e5l,0x18163c2f5bcadl,0x119caa33cdf50l,0xc701575769600l, + 0x03a4263df0ac1l }, + 0 }, + /* 138 */ + { { 0x65ecc9aeb596dl,0xe7023c92b4c29l,0xe01396101ea03l,0xa3674704b4b62l, + 0x00ca8fd3f905el }, + { 0x23a42551b2b61l,0x9c390fcd06925l,0x392a63e1eb7a8l,0x0c33e7f1d2be0l, + 0x096dca2644ddbl }, + 0 }, + /* 139 */ + { { 0xbb43a387510afl,0xa8a9a36a01203l,0xf950378846feal,0x59dcd23a57702l, + 0x04363e2123aadl }, + { 0x3a1c740246a47l,0xd2e55dd24dca4l,0xd8faf96b362b8l,0x98c4f9b086045l, + 0x0840e115cd8bbl }, + 0 }, + /* 140 */ + { { 0x205e21023e8a7l,0xcdd8dc7a0bf12l,0x63a5ddfc808a8l,0xd6d4e292a2721l, + 0x05e0d6abd30del }, + { 0x721c27cfc0f64l,0x1d0e55ed8807al,0xd1f9db242eec0l,0xa25a26a7bef91l, + 0x07dea48f42945l }, + 0 }, + /* 141 */ + { { 0xf6f1ce5060a81l,0x72f8f95615abdl,0x6ac268be79f9cl,0x16d1cfd36c540l, + 0x0abc2a2beebfdl }, + { 0x66f91d3e2eac7l,0x63d2dd04668acl,0x282d31b6f10bal,0xefc16790e3770l, + 0x04ea353946c7el }, + 0 }, + /* 142 */ + { { 0xa2f8d5266309dl,0xc081945a3eed8l,0x78c5dc10a51c6l,0xffc3cecaf45a5l, + 0x03a76e6891c94l }, + { 0xce8a47d7b0d0fl,0x968f584a5f9aal,0xe697fbe963acel,0x646451a30c724l, + 0x08212a10a465el }, + 0 }, + /* 143 */ + { { 0xc61c3cfab8caal,0x840e142390ef7l,0xe9733ca18eb8el,0xb164cd1dff677l, + 0x0aa7cab71599cl }, + { 0xc9273bc837bd1l,0xd0c36af5d702fl,0x423da49c06407l,0x17c317621292fl, + 0x040e38073fe06l }, + 0 }, + /* 144 */ + { { 0x80824a7bf9b7cl,0x203fbe30d0f4fl,0x7cf9ce3365d23l,0x5526bfbe53209l, + 0x0e3604700b305l }, + { 0xb99116cc6c2c7l,0x08ba4cbee64dcl,0x37ad9ec726837l,0xe15fdcded4346l, + 0x06542d677a3del }, + 0 }, + /* 145 */ + { { 0x2b6d07b6c377al,0x47903448be3f3l,0x0da8af76cb038l,0x6f21d6fdd3a82l, + 0x0a6534aee09bbl }, + { 0x1780d1035facfl,0x339dcb47e630al,0x447f39335e55al,0xef226ea50fe1cl, + 0x0f3cb672fdc9al }, + 0 }, + /* 146 */ + { { 0x719fe3b55fd83l,0x6c875ddd10eb3l,0x5cea784e0d7a4l,0x70e733ac9fa90l, + 0x07cafaa2eaae8l }, + { 0x14d041d53b338l,0xa0ef87e6c69b8l,0x1672b0fe0acc0l,0x522efb93d1081l, + 0x00aab13c1b9bdl }, + 0 }, + /* 147 */ + { { 0xce278d2681297l,0xb1b509546addcl,0x661aaf2cb350el,0x12e92dc431737l, + 0x04b91a6028470l }, + { 0xf109572f8ddcfl,0x1e9a911af4dcfl,0x372430e08ebf6l,0x1cab48f4360acl, + 0x049534c537232l }, + 0 }, + /* 148 */ + { { 0xf7d71f07b7e9dl,0xa313cd516f83dl,0xc047ee3a478efl,0xc5ee78ef264b6l, + 0x0caf46c4fd65al }, + { 0xd0c7792aa8266l,0x66913684bba04l,0xe4b16b0edf454l,0x770f56e65168al, + 0x014ce9e5704c6l }, + 0 }, + /* 149 */ + { { 0x45e3e965e8f91l,0xbacb0f2492994l,0x0c8a0a0d3aca1l,0x9a71d31cc70f9l, + 0x01bb708a53e4cl }, + { 0xa9e69558bdd7al,0x08018a26b1d5cl,0xc9cf1ec734a05l,0x0102b093aa714l, + 0x0f9d126f2da30l }, + 0 }, + /* 150 */ + { { 0xbca7aaff9563el,0xfeb49914a0749l,0xf5f1671dd077al,0xcc69e27a0311bl, + 0x0807afcb9729el }, + { 0xa9337c9b08b77l,0x85443c7e387f8l,0x76fd8ba86c3a7l,0xcd8c85fafa594l, + 0x0751adcd16568l }, + 0 }, + /* 151 */ + { { 0xa38b410715c0dl,0x718f7697f78ael,0x3fbf06dd113eal,0x743f665eab149l, + 0x029ec44682537l }, + { 0x4719cb50bebbcl,0xbfe45054223d9l,0xd2dedb1399ee5l,0x077d90cd5b3a8l, + 0x0ff9370e392a4l }, + 0 }, + /* 152 */ + { { 0x2d69bc6b75b65l,0xd5266651c559al,0xde9d7d24188f8l,0xd01a28a9f33e3l, + 0x09776478ba2a9l }, + { 0x2622d929af2c7l,0x6d4e690923885l,0x89a51e9334f5dl,0x82face6cc7e5al, + 0x074a6313fac2fl }, + 0 }, + /* 153 */ + { { 0x4dfddb75f079cl,0x9518e36fbbb2fl,0x7cd36dd85b07cl,0x863d1b6cfcf0el, + 0x0ab75be150ff4l }, + { 0x367c0173fc9b7l,0x20d2594fd081bl,0x4091236b90a74l,0x59f615fdbf03cl, + 0x04ebeac2e0b44l }, + 0 }, + /* 154 */ + { { 0xc5fe75c9f2c53l,0x118eae9411eb6l,0x95ac5d8d25220l,0xaffcc8887633fl, + 0x0df99887b2c1bl }, + { 0x8eed2850aaecbl,0x1b01d6a272bb7l,0x1cdbcac9d4918l,0x4058978dd511bl, + 0x027b040a7779fl }, + 0 }, + /* 155 */ + { { 0x05db7f73b2eb2l,0x088e1b2118904l,0x962327ee0df85l,0xa3f5501b71525l, + 0x0b393dd37e4cfl }, + { 0x30e7b3fd75165l,0xc2bcd33554a12l,0xf7b5022d66344l,0x34196c36f1be0l, + 0x009588c12d046l }, + 0 }, + /* 156 */ + { { 0x6093f02601c3bl,0xf8cf5c335fe08l,0x94aff28fb0252l,0x648b955cf2808l, + 0x081c879a9db9fl }, + { 0xe687cc6f56c51l,0x693f17618c040l,0x059353bfed471l,0x1bc444f88a419l, + 0x0fa0d48f55fc1l }, + 0 }, + /* 157 */ + { { 0xe1c9de1608e4dl,0x113582822cbc6l,0x57ec2d7010ddal,0x67d6f6b7ddc11l, + 0x08ea0e156b6a3l }, + { 0x4e02f2383b3b4l,0x943f01f53ca35l,0xde03ca569966bl,0xb5ac4ff6632b2l, + 0x03f5ab924fa00l }, + 0 }, + /* 158 */ + { { 0xbb0d959739efbl,0xf4e7ebec0d337l,0x11a67d1c751b0l,0x256e2da52dd64l, + 0x08bc768872b74l }, + { 0xe3b7282d3d253l,0xa1f58d779fa5bl,0x16767bba9f679l,0xf34fa1cac168el, + 0x0b386f19060fcl }, + 0 }, + /* 159 */ + { { 0x3c1352fedcfc2l,0x6262f8af0d31fl,0x57288c25396bfl,0x9c4d9a02b4eael, + 0x04cb460f71b06l }, + { 0x7b4d35b8095eal,0x596fc07603ae6l,0x614a16592bbf8l,0x5223e1475f66bl, + 0x052c0d50895efl }, + 0 }, + /* 160 */ + { { 0xc210e15339848l,0xe870778c8d231l,0x956e170e87a28l,0x9c0b9d1de6616l, + 0x04ac3c9382bb0l }, + { 0xe05516998987dl,0xc4ae09f4d619bl,0xa3f933d8b2376l,0x05f41de0b7651l, + 0x0380d94c7e397l }, + 0 }, + /* 161 */ + { { 0x355aa81542e75l,0xa1ee01b9b701al,0x24d708796c724l,0x37af6b3a29776l, + 0x02ce3e171de26l }, + { 0xfeb49f5d5bc1al,0x7e2777e2b5cfel,0x513756ca65560l,0x4e4d4feaac2f9l, + 0x02e6cd8520b62l }, + 0 }, + /* 162 */ + { { 0x5954b8c31c31dl,0x005bf21a0c368l,0x5c79ec968533dl,0x9d540bd7626e7l, + 0x0ca17754742c6l }, + { 0xedafff6d2dbb2l,0xbd174a9d18cc6l,0xa4578e8fd0d8cl,0x2ce6875e8793al, + 0x0a976a7139cabl }, + 0 }, + /* 163 */ + { { 0x51f1b93fb353dl,0x8b57fcfa720a6l,0x1b15281d75cabl,0x4999aa88cfa73l, + 0x08720a7170a1fl }, + { 0xe8d37693e1b90l,0x0b16f6dfc38c3l,0x52a8742d345dcl,0x893c8ea8d00abl, + 0x09719ef29c769l }, + 0 }, + /* 164 */ + { { 0xeed8d58e35909l,0xdc33ddc116820l,0xe2050269366d8l,0x04c1d7f999d06l, + 0x0a5072976e157l }, + { 0xa37eac4e70b2el,0x576890aa8a002l,0x45b2a5c84dcf6l,0x7725cd71bf186l, + 0x099389c9df7b7l }, + 0 }, + /* 165 */ + { { 0xc08f27ada7a4bl,0x03fd389366238l,0x66f512c3abe9dl,0x82e46b672e897l, + 0x0a88806aa202cl }, + { 0x2044ad380184el,0xc4126a8b85660l,0xd844f17a8cb78l,0xdcfe79d670c0al, + 0x00043bffb4738l }, + 0 }, + /* 166 */ + { { 0x9b5dc36d5192el,0xd34590b2af8d5l,0x1601781acf885l,0x486683566d0a1l, + 0x052f3ef01ba6cl }, + { 0x6732a0edcb64dl,0x238068379f398l,0x040f3090a482cl,0x7e7516cbe5fa7l, + 0x03296bd899ef2l }, + 0 }, + /* 167 */ + { { 0xaba89454d81d7l,0xef51eb9b3c476l,0x1c579869eade7l,0x71e9619a21cd8l, + 0x03b90febfaee5l }, + { 0x3023e5496f7cbl,0xd87fb51bc4939l,0x9beb5ce55be41l,0x0b1803f1dd489l, + 0x06e88069d9f81l }, + 0 }, + /* 168 */ + { { 0x7ab11b43ea1dbl,0xa95259d292ce3l,0xf84f1860a7ff1l,0xad13851b02218l, + 0x0a7222beadefal }, + { 0xc78ec2b0a9144l,0x51f2fa59c5a2al,0x147ce385a0240l,0xc69091d1eca56l, + 0x0be94d523bc2al }, + 0 }, + /* 169 */ + { { 0x4945e0b226ce7l,0x47967e8b7072fl,0x5a6c63eb8afd7l,0xc766edea46f18l, + 0x07782defe9be8l }, + { 0xd2aa43db38626l,0x8776f67ad1760l,0x4499cdb460ae7l,0x2e4b341b86fc5l, + 0x003838567a289l }, + 0 }, + /* 170 */ + { { 0xdaefd79ec1a0fl,0xfdceb39c972d8l,0x8f61a953bbcd6l,0xb420f5575ffc5l, + 0x0dbd986c4adf7l }, + { 0xa881415f39eb7l,0xf5b98d976c81al,0xf2f717d6ee2fcl,0xbbd05465475dcl, + 0x08e24d3c46860l }, + 0 }, + /* 171 */ + { { 0xd8e549a587390l,0x4f0cbec588749l,0x25983c612bb19l,0xafc846e07da4bl, + 0x0541a99c4407bl }, + { 0x41692624c8842l,0x2ad86c05ffdb2l,0xf7fcf626044c1l,0x35d1c59d14b44l, + 0x0c0092c49f57dl }, + 0 }, + /* 172 */ + { { 0xc75c3df2e61efl,0xc82e1b35cad3cl,0x09f29f47e8841l,0x944dc62d30d19l, + 0x075e406347286l }, + { 0x41fc5bbc237d0l,0xf0ec4f01c9e7dl,0x82bd534c9537bl,0x858691c51a162l, + 0x05b7cb658c784l }, + 0 }, + /* 173 */ + { { 0xa70848a28ead1l,0x08fd3b47f6964l,0x67e5b39802dc5l,0x97a19ae4bfd17l, + 0x07ae13eba8df0l }, + { 0x16ef8eadd384el,0xd9b6b2ff06fd2l,0xbcdb5f30361a2l,0xe3fd204b98784l, + 0x0787d8074e2a8l }, + 0 }, + /* 174 */ + { { 0x25d6b757fbb1cl,0xb2ca201debc5el,0xd2233ffe47bddl,0x84844a55e9a36l, + 0x05c2228199ef2l }, + { 0xd4a8588315250l,0x2b827097c1773l,0xef5d33f21b21al,0xf2b0ab7c4ea1dl, + 0x0e45d37abbaf0l }, + 0 }, + /* 175 */ + { { 0xf1e3428511c8al,0xc8bdca6cd3d2dl,0x27c39a7ebb229l,0xb9d3578a71a76l, + 0x0ed7bc12284dfl }, + { 0x2a6df93dea561l,0x8dd48f0ed1cf2l,0xbad23e85443f1l,0x6d27d8b861405l, + 0x0aac97cc945cal }, + 0 }, + /* 176 */ + { { 0x4ea74a16bd00al,0xadf5c0bcc1eb5l,0xf9bfc06d839e9l,0xdc4e092bb7f11l, + 0x0318f97b31163l }, + { 0x0c5bec30d7138l,0x23abc30220eccl,0x022360644e8dfl,0xff4d2bb7972fbl, + 0x0fa41faa19a84l }, + 0 }, + /* 177 */ + { { 0x2d974a6642269l,0xce9bb783bd440l,0x941e60bc81814l,0xe9e2398d38e47l, + 0x038bb6b2c1d26l }, + { 0xe4a256a577f87l,0x53dc11fe1cc64l,0x22807288b52d2l,0x01a5ff336abf6l, + 0x094dd0905ce76l }, + 0 }, + /* 178 */ + { { 0xcf7dcde93f92al,0xcb89b5f315156l,0x995e750a01333l,0x2ae902404df9cl, + 0x092077867d25cl }, + { 0x71e010bf39d44l,0x2096bb53d7e24l,0xc9c3d8f5f2c90l,0xeb514c44b7b35l, + 0x081e8428bd29bl }, + 0 }, + /* 179 */ + { { 0x9c2bac477199fl,0xee6b5ecdd96ddl,0xe40fd0e8cb8eel,0xa4b18af7db3fel, + 0x01b94ab62dbbfl }, + { 0x0d8b3ce47f143l,0xfc63f4616344fl,0xc59938351e623l,0x90eef18f270fcl, + 0x006a38e280555l }, + 0 }, + /* 180 */ + { { 0xb0139b3355b49l,0x60b4ebf99b2e5l,0x269f3dc20e265l,0xd4f8c08ffa6bdl, + 0x0a7b36c2083d9l }, + { 0x15c3a1b3e8830l,0xe1a89f9c0b64dl,0x2d16930d5fceal,0x2a20cfeee4a2el, + 0x0be54c6b4a282l }, + 0 }, + /* 181 */ + { { 0xdb3df8d91167cl,0x79e7a6625ed6cl,0x46ac7f4517c3fl,0x22bb7105648f3l, + 0x0bf30a5abeae0l }, + { 0x785be93828a68l,0x327f3ef0368e7l,0x92146b25161c3l,0xd13ae11b5feb5l, + 0x0d1c820de2732l }, + 0 }, + /* 182 */ + { { 0xe13479038b363l,0x546b05e519043l,0x026cad158c11fl,0x8da34fe57abe6l, + 0x0b7d17bed68a1l }, + { 0xa5891e29c2559l,0x765bfffd8444cl,0x4e469484f7a03l,0xcc64498de4af7l, + 0x03997fd5e6412l }, + 0 }, + /* 183 */ + { { 0x746828bd61507l,0xd534a64d2af20l,0xa8a15e329e132l,0x13e8ffeddfb08l, + 0x00eeb89293c6cl }, + { 0x69a3ea7e259f8l,0xe6d13e7e67e9bl,0xd1fa685ce1db7l,0xb6ef277318f6al, + 0x0228916f8c922l }, + 0 }, + /* 184 */ + { { 0xae25b0a12ab5bl,0x1f957bc136959l,0x16e2b0ccc1117l,0x097e8058429edl, + 0x0ec05ad1d6e93l }, + { 0xba5beac3f3708l,0x3530b59d77157l,0x18234e531baf9l,0x1b3747b552371l, + 0x07d3141567ff1l }, + 0 }, + /* 185 */ + { { 0x9c05cf6dfefabl,0x68dcb377077bdl,0xa38bb95be2f22l,0xd7a3e53ead973l, + 0x0e9ce66fc9bc1l }, + { 0xa15766f6a02a1l,0xdf60e600ed75al,0x8cdc1b938c087l,0x0651f8947f346l, + 0x0d9650b017228l }, + 0 }, + /* 186 */ + { { 0xb4c4a5a057e60l,0xbe8def25e4504l,0x7c1ccbdcbccc3l,0xb7a2a63532081l, + 0x014d6699a804el }, + { 0xa8415db1f411al,0x0bf80d769c2c8l,0xc2f77ad09fbafl,0x598ab4deef901l, + 0x06f4c68410d43l }, + 0 }, + /* 187 */ + { { 0x6df4e96c24a96l,0x85fcbd99a3872l,0xb2ae30a534dbcl,0x9abb3c466ef28l, + 0x04c4350fd6118l }, + { 0x7f716f855b8dal,0x94463c38a1296l,0xae9334341a423l,0x18b5c37e1413el, + 0x0a726d2425a31l }, + 0 }, + /* 188 */ + { { 0x6b3ee948c1086l,0x3dcbd3a2e1dael,0x3d022f3f1de50l,0xf3923f35ed3f0l, + 0x013639e82cc6cl }, + { 0x938fbcdafaa86l,0xfb2654a2589acl,0x5051329f45bc5l,0x35a31963b26e4l, + 0x0ca9365e1c1a3l }, + 0 }, + /* 189 */ + { { 0x5ac754c3b2d20l,0x17904e241b361l,0xc9d071d742a54l,0x72a5b08521c4cl, + 0x09ce29c34970bl }, + { 0x81f736d3e0ad6l,0x9ef2f8434c8ccl,0xce862d98060dal,0xaf9835ed1d1a6l, + 0x048c4abd7ab42l }, + 0 }, + /* 190 */ + { { 0x1b0cc40c7485al,0xbbe5274dbfd22l,0x263d2e8ead455l,0x33cb493c76989l, + 0x078017c32f67bl }, + { 0x35769930cb5eel,0x940c408ed2b9dl,0x72f1a4dc0d14el,0x1c04f8b7bf552l, + 0x053cd0454de5cl }, + 0 }, + /* 191 */ + { { 0x585fa5d28ccacl,0x56005b746ebcdl,0xd0123aa5f823el,0xfa8f7c79f0a1cl, + 0x0eea465c1d3d7l }, + { 0x0659f0551803bl,0x9f7ce6af70781l,0x9288e706c0b59l,0x91934195a7702l, + 0x01b6e42a47ae6l }, + 0 }, + /* 192 */ + { { 0x0937cf67d04c3l,0xe289eeb8112e8l,0x2594d601e312bl,0xbd3d56b5d8879l, + 0x00224da14187fl }, + { 0xbb8630c5fe36fl,0x604ef51f5f87al,0x3b429ec580f3cl,0xff33964fb1bfbl, + 0x060838ef042bfl }, + 0 }, + /* 193 */ + { { 0xcb2f27e0bbe99l,0xf304aa39ee432l,0xfa939037bda44l,0x16435f497c7a9l, + 0x0636eb2022d33l }, + { 0xd0e6193ae00aal,0xfe31ae6d2ffcfl,0xf93901c875a00l,0x8bacf43658a29l, + 0x08844eeb63921l }, + 0 }, + /* 194 */ + { { 0x171d26b3bae58l,0x7117e39f3e114l,0x1a8eada7db3dfl,0x789ecd37bc7f8l, + 0x027ba83dc51fbl }, + { 0xf439ffbf54de5l,0x0bb5fe1a71a7dl,0xb297a48727703l,0xa4ab42ee8e35dl, + 0x0adb62d3487f3l }, + 0 }, + /* 195 */ + { { 0x168a2a175df2al,0x4f618c32e99b1l,0x46b0916082aa0l,0xc8b2c9e4f2e71l, + 0x0b990fd7675e7l }, + { 0x9d96b4df37313l,0x79d0b40789082l,0x80877111c2055l,0xd18d66c9ae4a7l, + 0x081707ef94d10l }, + 0 }, + /* 196 */ + { { 0x7cab203d6ff96l,0xfc0d84336097dl,0x042db4b5b851bl,0xaa5c268823c4dl, + 0x03792daead5a8l }, + { 0x18865941afa0bl,0x4142d83671528l,0xbe4e0a7f3e9e7l,0x01ba17c825275l, + 0x05abd635e94b0l }, + 0 }, + /* 197 */ + { { 0xfa84e0ac4927cl,0x35a7c8cf23727l,0xadca0dfe38860l,0xb610a4bcd5ea4l, + 0x05995bf21846al }, + { 0xf860b829dfa33l,0xae958fc18be90l,0x8630366caafe2l,0x411e9b3baf447l, + 0x044c32ca2d483l }, + 0 }, + /* 198 */ + { { 0xa97f1e40ed80cl,0xb131d2ca82a74l,0xc2d6ad95f938cl,0xa54c53f2124b7l, + 0x01f2162fb8082l }, + { 0x67cc5720b173el,0x66085f12f97e4l,0xc9d65dc40e8a6l,0x07c98cebc20e4l, + 0x08f1d402bc3e9l }, + 0 }, + /* 199 */ + { { 0x92f9cfbc4058al,0xb6292f56704f5l,0xc1d8c57b15e14l,0xdbf9c55cfe37bl, + 0x0b1980f43926el }, + { 0x33e0932c76b09l,0x9d33b07f7898cl,0x63bb4611df527l,0x8e456f08ead48l, + 0x02828ad9b3744l }, + 0 }, + /* 200 */ + { { 0x722c4c4cf4ac5l,0x3fdde64afb696l,0x0890832f5ac1al,0xb3900551baa2el, + 0x04973f1275a14l }, + { 0xd8335322eac5dl,0xf50bd9b568e59l,0x25883935e07eel,0x8ac7ab36720fal, + 0x06dac8ed0db16l }, + 0 }, + /* 201 */ + { { 0x545aeeda835efl,0xd21d10ed51f7bl,0x3741b094aa113l,0xde4c035a65e01l, + 0x04b23ef5920b9l }, + { 0xbb6803c4c7341l,0x6d3f58bc37e82l,0x51e3ee8d45770l,0x9a4e73527863al, + 0x04dd71534ddf4l }, + 0 }, + /* 202 */ + { { 0x4467295476cd9l,0x2fe31a725bbf9l,0xc4b67e0648d07l,0x4dbb1441c8b8fl, + 0x0fd3170002f4al }, + { 0x43ff48995d0e1l,0xd10ef729aa1cbl,0x179898276e695l,0xf365e0d5f9764l, + 0x014fac58c9569l }, + 0 }, + /* 203 */ + { { 0xa0065f312ae18l,0xc0fcc93fc9ad9l,0xa7d284651958dl,0xda50d9a142408l, + 0x0ed7c765136abl }, + { 0x70f1a25d4abbcl,0xf3f1a113ea462l,0xb51952f9b5dd8l,0x9f53c609b0755l, + 0x0fefcb7f74d2el }, + 0 }, + /* 204 */ + { { 0x9497aba119185l,0x30aac45ba4bd0l,0xa521179d54e8cl,0xd80b492479deal, + 0x01801a57e87e0l }, + { 0xd3f8dfcafffb0l,0x0bae255240073l,0xb5fdfbc6cf33cl,0x1064781d763b5l, + 0x09f8fc11e1eadl }, + 0 }, + /* 205 */ + { { 0x3a1715e69544cl,0x67f04b7813158l,0x78a4c320eaf85l,0x69a91e22a8fd2l, + 0x0a9d3809d3d3al }, + { 0xc2c2c59a2da3bl,0xf61895c847936l,0x3d5086938ccbcl,0x8ef75e65244e6l, + 0x03006b9aee117l }, + 0 }, + /* 206 */ + { { 0x1f2b0c9eead28l,0x5d89f4dfbc0bbl,0x2ce89397eef63l,0xf761074757fdbl, + 0x00ab85fd745f8l }, + { 0xa7c933e5b4549l,0x5c97922f21ecdl,0x43b80404be2bbl,0x42c2261a1274bl, + 0x0b122d67511e9l }, + 0 }, + /* 207 */ + { { 0x607be66a5ae7al,0xfa76adcbe33bel,0xeb6e5c501e703l,0xbaecaf9043014l, + 0x09f599dc1097dl }, + { 0x5b7180ff250edl,0x74349a20dc6d7l,0x0b227a38eb915l,0x4b78425605a41l, + 0x07d5528e08a29l }, + 0 }, + /* 208 */ + { { 0x58f6620c26defl,0xea582b2d1ef0fl,0x1ce3881025585l,0x1730fbe7d79b0l, + 0x028ccea01303fl }, + { 0xabcd179644ba5l,0xe806fff0b8d1dl,0x6b3e17b1fc643l,0x13bfa60a76fc6l, + 0x0c18baf48a1d0l }, + 0 }, + /* 209 */ + { { 0x638c85dc4216dl,0x67206142ac34el,0x5f5064a00c010l,0x596bd453a1719l, + 0x09def809db7a9l }, + { 0x8642e67ab8d2cl,0x336237a2b641el,0x4c4218bb42404l,0x8ce57d506a6d6l, + 0x00357f8b06880l }, + 0 }, + /* 210 */ + { { 0xdbe644cd2cc88l,0x8df0b8f39d8e9l,0xd30a0c8cc61c2l,0x98874a309874cl, + 0x0e4a01add1b48l }, + { 0x1eeacf57cd8f9l,0x3ebd594c482edl,0xbd2f7871b767dl,0xcc30a7295c717l, + 0x0466d7d79ce10l }, + 0 }, + /* 211 */ + { { 0x318929dada2c7l,0xc38f9aa27d47dl,0x20a59e14fa0a6l,0xad1a90e4fd288l, + 0x0c672a522451el }, + { 0x07cc85d86b655l,0x3bf9ad4af1306l,0x71172a6f0235dl,0x751399a086805l, + 0x05e3d64faf2a6l }, + 0 }, + /* 212 */ + { { 0x410c79b3b4416l,0x85eab26d99aa6l,0xb656a74cd8fcfl,0x42fc5ebff74adl, + 0x06c8a7a95eb8el }, + { 0x60ba7b02a63bdl,0x038b8f004710cl,0x12d90b06b2f23l,0xca918c6c37383l, + 0x0348ae422ad82l }, + 0 }, + /* 213 */ + { { 0x746635ccda2fbl,0xa18e0726d27f4l,0x92b1f2022accal,0x2d2e85adf7824l, + 0x0c1074de0d9efl }, + { 0x3ce44ae9a65b3l,0xac05d7151bfcfl,0xe6a9788fd71e4l,0x4ffcd4711f50cl, + 0x0fbadfbdbc9e5l }, + 0 }, + /* 214 */ + { { 0x3f1cd20a99363l,0x8f6cf22775171l,0x4d359b2b91565l,0x6fcd968175cd2l, + 0x0b7f976b48371l }, + { 0x8e24d5d6dbf74l,0xfd71c3af36575l,0x243dfe38d23bal,0xc80548f477600l, + 0x0f4d41b2ecafcl }, + 0 }, + /* 215 */ + { { 0x1cf28fdabd48dl,0x3632c078a451fl,0x17146e9ce81bel,0x0f106ace29741l, + 0x0180824eae016l }, + { 0x7698b66e58358l,0x52ce6ca358038l,0xe41e6c5635687l,0x6d2582380e345l, + 0x067e5f63983cfl }, + 0 }, + /* 216 */ + { { 0xccb8dcf4899efl,0xf09ebb44c0f89l,0x2598ec9949015l,0x1fc6546f9276bl, + 0x09fef789a04c1l }, + { 0x67ecf53d2a071l,0x7fa4519b096d3l,0x11e2eefb10e1al,0x4e20ca6b3fb06l, + 0x0bc80c181a99cl }, + 0 }, + /* 217 */ + { { 0x536f8e5eb82e6l,0xc7f56cb920972l,0x0b5da5e1a484fl,0xdf10c78e21715l, + 0x049270e629f8cl }, + { 0x9b7bbea6b50adl,0xc1a2388ffc1a3l,0x107197b9a0284l,0x2f7f5403eb178l, + 0x0d2ee52f96137l }, + 0 }, + /* 218 */ + { { 0xcd28588e0362al,0xa78fa5d94dd37l,0x434a526442fa8l,0xb733aff836e5al, + 0x0dfb478bee5abl }, + { 0xf1ce7673eede6l,0xd42b5b2f04a91l,0x530da2fa5390al,0x473a5e66f7bf5l, + 0x0d9a140b408dfl }, + 0 }, + /* 219 */ + { { 0x221b56e8ea498l,0x293563ee090e0l,0x35d2ade623478l,0x4b1ae06b83913l, + 0x0760c058d623fl }, + { 0x9b58cc198aa79l,0xd2f07aba7f0b8l,0xde2556af74890l,0x04094e204110fl, + 0x07141982d8f19l }, + 0 }, + /* 220 */ + { { 0xa0e334d4b0f45l,0x38392a94e16f0l,0x3c61d5ed9280bl,0x4e473af324c6bl, + 0x03af9d1ce89d5l }, + { 0xf798120930371l,0x4c21c17097fd8l,0xc42309beda266l,0x7dd60e9545dcdl, + 0x0b1f815c37395l }, + 0 }, + /* 221 */ + { { 0xaa78e89fec44al,0x473caa4caf84fl,0x1b6a624c8c2ael,0xf052691c807dcl, + 0x0a41aed141543l }, + { 0x353997d5ffe04l,0xdf625b6e20424l,0x78177758bacb2l,0x60ef85d660be8l, + 0x0d6e9c1dd86fbl }, + 0 }, + /* 222 */ + { { 0x2e97ec6853264l,0xb7e2304a0b3aal,0x8eae9be771533l,0xf8c21b912bb7bl, + 0x09c9c6e10ae9bl }, + { 0x09a59e030b74cl,0x4d6a631e90a23l,0x49b79f24ed749l,0x61b689f44b23al, + 0x0566bd59640fal }, + 0 }, + /* 223 */ + { { 0xc0118c18061f3l,0xd37c83fc70066l,0x7273245190b25l,0x345ef05fc8e02l, + 0x0cf2c7390f525l }, + { 0xbceb410eb30cfl,0xba0d77703aa09l,0x50ff255cfd2ebl,0x0979e842c43a1l, + 0x002f517558aa2l }, + 0 }, + /* 224 */ + { { 0xef794addb7d07l,0x4224455500396l,0x78aa3ce0b4fc7l,0xd97dfaff8eaccl, + 0x014e9ada5e8d4l }, + { 0x480a12f7079e2l,0xcde4b0800edaal,0x838157d45baa3l,0x9ae801765e2d7l, + 0x0a0ad4fab8e9dl }, + 0 }, + /* 225 */ + { { 0xb76214a653618l,0x3c31eaaa5f0bfl,0x4949d5e187281l,0xed1e1553e7374l, + 0x0bcd530b86e56l }, + { 0xbe85332e9c47bl,0xfeb50059ab169l,0x92bfbb4dc2776l,0x341dcdba97611l, + 0x0909283cf6979l }, + 0 }, + /* 226 */ + { { 0x0032476e81a13l,0x996217123967bl,0x32e19d69bee1al,0x549a08ed361bdl, + 0x035eeb7c9ace1l }, + { 0x0ae5a7e4e5bdcl,0xd3b6ceec6e128l,0xe266bc12dcd2cl,0xe86452e4224c6l, + 0x09a8b2cf4448al }, + 0 }, + /* 227 */ + { { 0x71bf209d03b59l,0xa3b65af2abf64l,0xbd5eec9c90e62l,0x1379ff7ff168el, + 0x06bdb60f4d449l }, + { 0xafebc8a55bc30l,0x1610097fe0dadl,0xc1e3bddc79eadl,0x08a942e197414l, + 0x001ec3cfd94bal }, + 0 }, + /* 228 */ + { { 0x277ebdc9485c2l,0x7922fb10c7ba6l,0x0a28d8a48cc9al,0x64f64f61d60f7l, + 0x0d1acb1c04754l }, + { 0x902b126f36612l,0x4ee0618d8bd26l,0x08357ee59c3a4l,0x26c24df8a8133l, + 0x07dcd079d4056l }, + 0 }, + /* 229 */ + { { 0x7d4d3f05a4b48l,0x52372307725cel,0x12a915aadcd29l,0x19b8d18f79718l, + 0x00bf53589377dl }, + { 0xcd95a6c68ea73l,0xca823a584d35el,0x473a723c7f3bbl,0x86fc9fb674c6fl, + 0x0d28be4d9e166l }, + 0 }, + /* 230 */ + { { 0xb990638fa8e4bl,0x6e893fd8fc5d2l,0x36fb6fc559f18l,0x88ce3a6de2aa4l, + 0x0d76007aa510fl }, + { 0x0aab6523a4988l,0x4474dd02732d1l,0x3407278b455cfl,0xbb017f467082al, + 0x0f2b52f68b303l }, + 0 }, + /* 231 */ + { { 0x7eafa9835b4cal,0xfcbb669cbc0d5l,0x66431982d2232l,0xed3a8eeeb680cl, + 0x0d8dbe98ecc5al }, + { 0x9be3fc5a02709l,0xe5f5ba1fa8cbal,0x10ea85230be68l,0x9705febd43cdfl, + 0x0e01593a3ee55l }, + 0 }, + /* 232 */ + { { 0x5af50ea75a0a6l,0xac57858033d3el,0x0176406512226l,0xef066fe6d50fdl, + 0x0afec07b1aeb8l }, + { 0x9956780bb0a31l,0xcc37309aae7fbl,0x1abf3896f1af3l,0xbfdd9153a15a0l, + 0x0a71b93546e2dl }, + 0 }, + /* 233 */ + { { 0xe12e018f593d2l,0x28a078122bbf8l,0xba4f2add1a904l,0x23d9150505db0l, + 0x053a2005c6285l }, + { 0x8b639e7f2b935l,0x5ac182961a07cl,0x518ca2c2bff97l,0x8e3d86bceea77l, + 0x0bf47d19b3d58l }, + 0 }, + /* 234 */ + { { 0x967a7dd7665d5l,0x572f2f4de5672l,0x0d4903f4e3030l,0xa1b6144005ae8l, + 0x0001c2c7f39c9l }, + { 0xa801469efc6d6l,0xaa7bc7a724143l,0x78150a4c810bdl,0xb99b5f65670bal, + 0x0fdadf8e786ffl }, + 0 }, + /* 235 */ + { { 0x8cb88ffc00785l,0x913b48eb67fd3l,0xf368fbc77fa75l,0x3c940454d055bl, + 0x03a838e4d5aa4l }, + { 0x663293e97bb9al,0x63441d94d9561l,0xadb2a839eb933l,0x1da3515591a60l, + 0x03cdb8257873el }, + 0 }, + /* 236 */ + { { 0x140a97de77eabl,0x0d41648109137l,0xeb1d0dff7e1c5l,0x7fba762dcad2cl, + 0x05a60cc89f1f5l }, + { 0x3638240d45673l,0x195913c65580bl,0xd64b7411b82bel,0x8fc0057284b8dl, + 0x0922ff56fdbfdl }, + 0 }, + /* 237 */ + { { 0x65deec9a129a1l,0x57cc284e041b2l,0xebfbe3ca5b1cel,0xcd6204380c46cl, + 0x072919a7df6c5l }, + { 0xf453a8fb90f9al,0x0b88e4031b298l,0x96f1856d719c0l,0x089ae32c0e777l, + 0x05e7917803624l }, + 0 }, + /* 238 */ + { { 0x6ec557f63cdfbl,0x71f1cae4fd5c1l,0x60597ca8e6a35l,0x2fabfce26bea5l, + 0x04e0a5371e24cl }, + { 0xa40d3a5765357l,0x440d73a2b4276l,0x1d11a323c89afl,0x04eeb8f370ae4l, + 0x0f5ff7818d566l }, + 0 }, + /* 239 */ + { { 0x3e3fe1a09df21l,0x8ee66e8e47fbfl,0x9c8901526d5d2l,0x5e642096bd0a2l, + 0x0e41df0e9533fl }, + { 0xfda40b3ba9e3fl,0xeb2604d895305l,0xf0367c7f2340cl,0x155f0866e1927l, + 0x08edd7d6eac4fl }, + 0 }, + /* 240 */ + { { 0x1dc0e0bfc8ff3l,0x2be936f42fc9al,0xca381ef14efd8l,0xee9667016f7ccl, + 0x01432c1caed8al }, + { 0x8482970b23c26l,0x730735b273ec6l,0xaef0f5aa64fe8l,0xd2c6e389f6e5el, + 0x0caef480b5ac8l }, + 0 }, + /* 241 */ + { { 0x5c97875315922l,0x713063cca5524l,0x64ef2cbd82951l,0xe236f3ce60d0bl, + 0x0d0ba177e8efal }, + { 0x9ae8fb1b3af60l,0xe53d2da20e53al,0xf9eef281a796al,0xae1601d63605dl, + 0x0f31c957c1c54l }, + 0 }, + /* 242 */ + { { 0x58d5249cc4597l,0xb0bae0a028c0fl,0x34a814adc5015l,0x7c3aefc5fc557l, + 0x0013404cb96e1l }, + { 0xe2585c9a824bfl,0x5e001eaed7b29l,0x1ef68acd59318l,0x3e6c8d6ee6826l, + 0x06f377c4b9193l }, + 0 }, + /* 243 */ + { { 0x3bad1a8333fd2l,0x025a2a95b89f9l,0xaf75acea89302l,0x9506211e5037el, + 0x06dba3e4ed2d0l }, + { 0xef98cd04399cdl,0x6ee6b73adea48l,0x17ecaf31811c6l,0xf4a772f60752cl, + 0x0f13cf3423becl }, + 0 }, + /* 244 */ + { { 0xb9ec0a919e2ebl,0x95f62c0f68ceel,0xaba229983a9a1l,0xbad3cfba3bb67l, + 0x0c83fa9a9274bl }, + { 0xd1b0b62fa1ce0l,0xf53418efbf0d7l,0x2706f04e58b60l,0x2683bfa8ef9e5l, + 0x0b49d70f45d70l }, + 0 }, + /* 245 */ + { { 0xc7510fad5513bl,0xecb1751e2d914l,0x9fb9d5905f32el,0xf1cf6d850418dl, + 0x059cfadbb0c30l }, + { 0x7ac2355cb7fd6l,0xb8820426a3e16l,0x0a78864249367l,0x4b67eaeec58c9l, + 0x05babf362354al }, + 0 }, + /* 246 */ + { { 0x981d1ee424865l,0x78f2e5577f37cl,0x9e0c0588b0028l,0xc8f0702970f1bl, + 0x06188c6a79026l }, + { 0x9a19bd0f244dal,0x5cfb08087306fl,0xf2136371eccedl,0xb9d935470f9b9l, + 0x0993fe475df50l }, + 0 }, + /* 247 */ + { { 0x31cdf9b2c3609l,0xc02c46d4ea68el,0xa77510184eb19l,0x616b7ac9ec1a9l, + 0x081f764664c80l }, + { 0xc2a5a75fbe978l,0xd3f183b3561d7l,0x01dd2bf6743fel,0x060d838d1f045l, + 0x0564a812a5fe9l }, + 0 }, + /* 248 */ + { { 0xa64f4fa817d1dl,0x44bea82e0f7a5l,0xd57f9aa55f968l,0x1d6cb5ff5a0fcl, + 0x0226bf3cf00e5l }, + { 0x1a9f92f2833cfl,0x5a4f4f89a8d6dl,0xf3f7f7720a0a3l,0x783611536c498l, + 0x068779f47ff25l }, + 0 }, + /* 249 */ + { { 0x0c1c173043d08l,0x741fc020fa79bl,0xa6d26d0a54467l,0x2e0bd3767e289l, + 0x097bcb0d1eb09l }, + { 0x6eaa8f32ed3c3l,0x51b281bc482abl,0xfa178f3c8a4f1l,0x46554d1bf4f3bl, + 0x0a872ffe80a78l }, + 0 }, + /* 250 */ + { { 0xb7935a32b2086l,0x0e8160f486b1al,0xb6ae6bee1eb71l,0xa36a9bd0cd913l, + 0x002812bfcb732l }, + { 0xfd7cacf605318l,0x50fdfd6d1da63l,0x102d619646e5dl,0x96afa1d683982l, + 0x007391cc9fe53l }, + 0 }, + /* 251 */ + { { 0x157f08b80d02bl,0xd162877f7fc50l,0x8d542ae6b8333l,0x2a087aca1af87l, + 0x0355d2adc7e6dl }, + { 0xf335a287386e1l,0x94f8e43275b41l,0x79989eafd272al,0x3a79286ca2cdel, + 0x03dc2b1e37c2al }, + 0 }, + /* 252 */ + { { 0x9d21c04581352l,0x25376782bed68l,0xfed701f0a00c8l,0x846b203bd5909l, + 0x0c47869103ccdl }, + { 0xa770824c768edl,0x026841f6575dbl,0xaccce0e72feeal,0x4d3273313ed56l, + 0x0ccc42968d5bbl }, + 0 }, + /* 253 */ + { { 0x50de13d7620b9l,0x8a5992a56a94el,0x75487c9d89a5cl,0x71cfdc0076406l, + 0x0e147eb42aa48l }, + { 0xab4eeacf3ae46l,0xfb50350fbe274l,0x8c840eafd4936l,0x96e3df2afe474l, + 0x0239ac047080el }, + 0 }, + /* 254 */ + { { 0xd1f352bfee8d4l,0xcffa7b0fec481l,0xce9af3cce80b5l,0xe59d105c4c9e2l, + 0x0c55fa1a3f5f7l }, + { 0x6f14e8257c227l,0x3f342be00b318l,0xa904fb2c5b165l,0xb69909afc998al, + 0x0094cd99cd4f4l }, + 0 }, + /* 255 */ + { { 0x81c84d703bebal,0x5032ceb2918a9l,0x3bd49ec8631d1l,0xad33a445f2c9el, + 0x0b90a30b642abl }, + { 0x5404fb4a5abf9l,0xc375db7603b46l,0xa35d89f004750l,0x24f76f9a42cccl, + 0x0019f8b9a1b79l }, + 0 }, +}; + +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_base_5(sp_point* r, sp_digit* k, + int map, void* heap) +{ + return sp_256_ecc_mulmod_stripe_5(r, &p256_base, p256_table, + k, map, heap); +} + +#endif + +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * km Scalar to multiply by. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_base_256(mp_int* km, ecc_point* r, int map, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point p; + sp_digit kd[5]; +#endif + sp_point* point; + sp_digit* k = NULL; + int err = MP_OKAY; + + err = sp_ecc_point_new(heap, p, point); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 5, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + if (err == MP_OKAY) { + sp_256_from_mp(k, 5, km); + + err = sp_256_ecc_mulmod_base_5(point, k, map, heap); + } + if (err == MP_OKAY) + err = sp_256_point_to_ecc_point_5(point, r); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(point, 0, heap); + + return err; +} + +#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ + defined(HAVE_ECC_VERIFY) +/* Returns 1 if the number of zero. + * Implementation is constant time. + * + * a Number to check. + * returns 1 if the number is zero and 0 otherwise. + */ +static int sp_256_iszero_5(const sp_digit* a) +{ + return (a[0] | a[1] | a[2] | a[3] | a[4]) == 0; +} + +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN || HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +/* Add 1 to a. (a = a + 1) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_256_add_one_5(sp_digit* a) +{ + a[0]++; + sp_256_norm_5(a); +} + +/* Read big endian unsigned byte aray into r. + * + * r A single precision integer. + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_256_from_bin(sp_digit* r, int max, const byte* a, int n) +{ + int i, j = 0, s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= ((sp_digit)a[i]) << s; + if (s >= 44) { + r[j] &= 0xfffffffffffffl; + s = 52 - s; + if (j + 1 >= max) + break; + r[++j] = a[i] >> s; + s = 8 - s; + } + else + s += 8; + } + + for (j++; j < max; j++) + r[j] = 0; +} + +/* Generates a scalar that is in the range 1..order-1. + * + * rng Random number generator. + * k Scalar value. + * returns RNG failures, MEMORY_E when memory allocation fails and + * MP_OKAY on success. + */ +static int sp_256_ecc_gen_k_5(WC_RNG* rng, sp_digit* k) +{ + int err; + byte buf[32]; + + do { + err = wc_RNG_GenerateBlock(rng, buf, sizeof(buf)); + if (err == 0) { + sp_256_from_bin(k, 5, buf, sizeof(buf)); + if (sp_256_cmp_5(k, p256_order2) < 0) { + sp_256_add_one_5(k); + break; + } + } + } + while (err == 0); + + return err; +} + +/* Makes a random EC key pair. + * + * rng Random number generator. + * priv Generated private value. + * pub Generated public point. + * heap Heap to use for allocation. + * returns ECC_INF_E when the point does not have the correct order, RNG + * failures, MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point p; + sp_digit kd[5]; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point inf; +#endif +#endif + sp_point* point; + sp_digit* k = NULL; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point* infinity; +#endif + int err; + + (void)heap; + + err = sp_ecc_point_new(heap, p, point); +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, inf, infinity); +#endif +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 5, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + + if (err == MP_OKAY) + err = sp_256_ecc_gen_k_5(rng, k); + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_base_5(point, k, 1, NULL); + } + +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_5(infinity, point, p256_order, 1, NULL); + } + if (err == MP_OKAY) { + if (!sp_256_iszero_5(point->x) || !sp_256_iszero_5(point->y)) + err = ECC_INF_E; + } +#endif + + if (err == MP_OKAY) + err = sp_256_to_mp(k, priv); + if (err == MP_OKAY) + err = sp_256_point_to_ecc_point_5(point, pub); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); +#endif +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_ecc_point_free(infinity, 1, heap); +#endif + sp_ecc_point_free(point, 1, heap); + + return err; +} + +#ifdef HAVE_ECC_DHE +/* Write r as big endian to byte aray. + * Fixed length number of bytes written: 32 + * + * r A single precision integer. + * a Byte array. + */ +static void sp_256_to_bin(sp_digit* r, byte* a) +{ + int i, j, s = 0, b; + + for (i=0; i<4; i++) { + r[i+1] += r[i] >> 52; + r[i] &= 0xfffffffffffffl; + } + j = 256 / 8 - 1; + a[j] = 0; + for (i=0; i<5 && j>=0; i++) { + b = 0; + a[j--] |= r[i] << s; b += 8 - s; + if (j < 0) + break; + while (b < 52) { + a[j--] = r[i] >> b; b += 8; + if (j < 0) + break; + } + s = 8 - (b - 52); + if (j >= 0) + a[j] = 0; + if (s != 0) + j++; + } +} + +/* Multiply the point by the scalar and serialize the X ordinate. + * The number is 0 padded to maximum size on output. + * + * priv Scalar to multiply the point by. + * pub Point to multiply. + * out Buffer to hold X ordinate. + * outLen On entry, size of the buffer in bytes. + * On exit, length of data in buffer in bytes. + * heap Heap to use for allocation. + * returns BUFFER_E if the buffer is to small for output size, + * MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_secret_gen_256(mp_int* priv, ecc_point* pub, byte* out, + word32* outLen, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point p; + sp_digit kd[5]; +#endif + sp_point* point = NULL; + sp_digit* k = NULL; + int err = MP_OKAY; + + if (*outLen < 32) + err = BUFFER_E; + + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, p, point); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 5, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(k, 5, priv); + sp_256_point_from_ecc_point_5(point, pub); + err = sp_256_ecc_mulmod_5(point, point, k, 1, heap); + } + if (err == MP_OKAY) { + sp_256_to_bin(point->x, out); + *outLen = 32; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(point, 0, heap); + + return err; +} +#endif /* HAVE_ECC_DHE */ + +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +/* Multiply a by scalar b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A scalar. + */ +SP_NOINLINE static void sp_256_mul_d_5(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ +#ifdef WOLFSSL_SP_SMALL + int128_t tb = b; + int128_t t = 0; + int i; + + for (i = 0; i < 5; i++) { + t += tb * a[i]; + r[i] = t & 0xfffffffffffffl; + t >>= 52; + } + r[5] = (sp_digit)t; +#else + int128_t tb = b; + int128_t t[5]; + + t[ 0] = tb * a[ 0]; + t[ 1] = tb * a[ 1]; + t[ 2] = tb * a[ 2]; + t[ 3] = tb * a[ 3]; + t[ 4] = tb * a[ 4]; + r[ 0] = (t[ 0] & 0xfffffffffffffl); + r[ 1] = (sp_digit)(t[ 0] >> 52) + (t[ 1] & 0xfffffffffffffl); + r[ 2] = (sp_digit)(t[ 1] >> 52) + (t[ 2] & 0xfffffffffffffl); + r[ 3] = (sp_digit)(t[ 2] >> 52) + (t[ 3] & 0xfffffffffffffl); + r[ 4] = (sp_digit)(t[ 3] >> 52) + (t[ 4] & 0xfffffffffffffl); + r[ 5] = (sp_digit)(t[ 4] >> 52); +#endif /* WOLFSSL_SP_SMALL */ +} + +#ifdef WOLFSSL_SP_DIV_64 +static WC_INLINE sp_digit sp_256_div_word_5(sp_digit d1, sp_digit d0, + sp_digit div) +{ + sp_digit d, r, t, dv; + int128_t t0, t1; + + /* dv has 27 bits. */ + dv = (div >> 25) + 1; + /* All 52 bits from d1 and top 11 bits from d0. */ + d = (d1 << 11) | (d0 >> 41); + r = d / dv; + d -= r * dv; + /* Up to 36 bits in r */ + /* Next 16 bits from d0. */ + d <<= 16; + r <<= 16; + d |= (d0 >> 25) & ((1 << 16) - 1); + t = d / dv; + d -= t * dv; + r += t; + /* Up to 52 bits in r */ + + /* Handle rounding error with dv - top part */ + t0 = ((int128_t)d1 << 52) + d0; + t1 = (int128_t)r * div; + t1 = t0 - t1; + t = (sp_digit)(t1 >> 25) / dv; + r += t; + + /* Handle rounding error with dv - bottom 64 bits */ + t1 = (sp_digit)t0 - (r * div); + t = (sp_digit)t1 / div; + r += t; + + return r; +} +#endif /* WOLFSSL_SP_DIV_64 */ + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. + */ +static int sp_256_div_5(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + int i; +#ifndef WOLFSSL_SP_DIV_64 + int128_t d1; +#endif + sp_digit div, r1; +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* td; +#else + sp_digit t1d[10], t2d[5 + 1]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * (3 * 5 + 1), NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td != NULL) { + t1 = td; + t2 = td + 2 * 5; + } + else + err = MEMORY_E; +#else + t1 = t1d; + t2 = t2d; +#endif + + (void)m; + + if (err == MP_OKAY) { + div = d[4]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 5); + for (i=4; i>=0; i--) { + t1[5 + i] += t1[5 + i - 1] >> 52; + t1[5 + i - 1] &= 0xfffffffffffffl; +#ifndef WOLFSSL_SP_DIV_64 + d1 = t1[5 + i]; + d1 <<= 52; + d1 += t1[5 + i - 1]; + r1 = (sp_digit)(d1 / div); +#else + r1 = sp_256_div_word_5(t1[5 + i], t1[5 + i - 1], div); +#endif + + sp_256_mul_d_5(t2, d, r1); + sp_256_sub_5(&t1[i], &t1[i], t2); + t1[5 + i] -= t2[5]; + t1[5 + i] += t1[5 + i - 1] >> 52; + t1[5 + i - 1] &= 0xfffffffffffffl; + r1 = (((-t1[5 + i]) << 52) - t1[5 + i - 1]) / div; + r1++; + sp_256_mul_d_5(t2, d, r1); + sp_256_add_5(&t1[i], &t1[i], t2); + t1[5 + i] += t1[5 + i - 1] >> 52; + t1[5 + i - 1] &= 0xfffffffffffffl; + } + t1[5 - 1] += t1[5 - 2] >> 52; + t1[5 - 2] &= 0xfffffffffffffl; + r1 = t1[5 - 1] / div; + + sp_256_mul_d_5(t2, d, r1); + sp_256_sub_5(t1, t1, t2); + XMEMCPY(r, t1, sizeof(*r) * 2 * 5); + for (i=0; i<3; i++) { + r[i+1] += r[i] >> 52; + r[i] &= 0xfffffffffffffl; + } + sp_256_cond_add_5(r, r, d, 0 - (r[4] < 0)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MEMORY_E when unable to allocate memory and MP_OKAY otherwise. + */ +static int sp_256_mod_5(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_256_div_5(a, m, NULL, r); +} + +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +#ifdef WOLFSSL_SP_SMALL +/* Order-2 for the P256 curve. */ +static const uint64_t p256_order_2[4] = { + 0xf3b9cac2fc63254f,0xbce6faada7179e84,0xffffffffffffffff, + 0xffffffff00000000 +}; +#else +/* The low half of the order-2 of the P256 curve. */ +static const uint64_t p256_order_low[2] = { + 0xf3b9cac2fc63254f,0xbce6faada7179e84 +}; +#endif /* WOLFSSL_SP_SMALL */ + +/* Multiply two number mod the order of P256 curve. (r = a * b mod order) + * + * r Result of the multiplication. + * a First operand of the multiplication. + * b Second operand of the multiplication. + */ +static void sp_256_mont_mul_order_5(sp_digit* r, sp_digit* a, sp_digit* b) +{ + sp_256_mul_5(r, a, b); + sp_256_mont_reduce_order_5(r, p256_order, p256_mp_order); +} + +/* Square number mod the order of P256 curve. (r = a * a mod order) + * + * r Result of the squaring. + * a Number to square. + */ +static void sp_256_mont_sqr_order_5(sp_digit* r, sp_digit* a) +{ + sp_256_sqr_5(r, a); + sp_256_mont_reduce_order_5(r, p256_order, p256_mp_order); +} + +#ifndef WOLFSSL_SP_SMALL +/* Square number mod the order of P256 curve a number of times. + * (r = a ^ n mod order) + * + * r Result of the squaring. + * a Number to square. + */ +static void sp_256_mont_sqr_n_order_5(sp_digit* r, sp_digit* a, int n) +{ + int i; + + sp_256_mont_sqr_order_5(r, a); + for (i=1; i=0; i--) { + sp_256_mont_sqr_order_5(t, t); + if (p256_order_2[i / 64] & ((sp_digit)1 << (i % 64))) + sp_256_mont_mul_order_5(t, t, a); + } + XMEMCPY(r, t, sizeof(sp_digit) * 5); +#else + sp_digit* t = td; + sp_digit* t2 = td + 2 * 5; + sp_digit* t3 = td + 4 * 5; + int i; + + /* t = a^2 */ + sp_256_mont_sqr_order_5(t, a); + /* t = a^3 = t * a */ + sp_256_mont_mul_order_5(t, t, a); + /* t2= a^c = t ^ 2 ^ 2 */ + sp_256_mont_sqr_n_order_5(t2, t, 2); + /* t3= a^f = t2 * t */ + sp_256_mont_mul_order_5(t3, t2, t); + /* t2= a^f0 = t3 ^ 2 ^ 4 */ + sp_256_mont_sqr_n_order_5(t2, t3, 4); + /* t = a^ff = t2 * t3 */ + sp_256_mont_mul_order_5(t, t2, t3); + /* t3= a^ff00 = t ^ 2 ^ 8 */ + sp_256_mont_sqr_n_order_5(t2, t, 8); + /* t = a^ffff = t2 * t */ + sp_256_mont_mul_order_5(t, t2, t); + /* t2= a^ffff0000 = t ^ 2 ^ 16 */ + sp_256_mont_sqr_n_order_5(t2, t, 16); + /* t = a^ffffffff = t2 * t */ + sp_256_mont_mul_order_5(t, t2, t); + /* t2= a^ffffffff0000000000000000 = t ^ 2 ^ 64 */ + sp_256_mont_sqr_n_order_5(t2, t, 64); + /* t2= a^ffffffff00000000ffffffff = t2 * t */ + sp_256_mont_mul_order_5(t2, t2, t); + /* t2= a^ffffffff00000000ffffffff00000000 = t2 ^ 2 ^ 32 */ + sp_256_mont_sqr_n_order_5(t2, t2, 32); + /* t2= a^ffffffff00000000ffffffffffffffff = t2 * t */ + sp_256_mont_mul_order_5(t2, t2, t); + /* t2= a^ffffffff00000000ffffffffffffffffbce6 */ + for (i=127; i>=112; i--) { + sp_256_mont_sqr_order_5(t2, t2); + if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64))) + sp_256_mont_mul_order_5(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6f */ + sp_256_mont_sqr_n_order_5(t2, t2, 4); + sp_256_mont_mul_order_5(t2, t2, t3); + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84 */ + for (i=107; i>=64; i--) { + sp_256_mont_sqr_order_5(t2, t2); + if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64))) + sp_256_mont_mul_order_5(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f */ + sp_256_mont_sqr_n_order_5(t2, t2, 4); + sp_256_mont_mul_order_5(t2, t2, t3); + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2 */ + for (i=59; i>=32; i--) { + sp_256_mont_sqr_order_5(t2, t2); + if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64))) + sp_256_mont_mul_order_5(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2f */ + sp_256_mont_sqr_n_order_5(t2, t2, 4); + sp_256_mont_mul_order_5(t2, t2, t3); + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254 */ + for (i=27; i>=0; i--) { + sp_256_mont_sqr_order_5(t2, t2); + if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64))) + sp_256_mont_mul_order_5(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632540 */ + sp_256_mont_sqr_n_order_5(t2, t2, 4); + /* r = a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f */ + sp_256_mont_mul_order_5(r, t2, t3); +#endif /* WOLFSSL_SP_SMALL */ +} + +#endif /* HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +#ifdef HAVE_ECC_SIGN +#ifndef SP_ECC_MAX_SIG_GEN +#define SP_ECC_MAX_SIG_GEN 64 +#endif + +/* Sign the hash using the private key. + * e = [hash, 256 bits] from binary + * r = (k.G)->x mod order + * s = (r * x + e) / k mod order + * The hash is truncated to the first 256 bits. + * + * hash Hash to sign. + * hashLen Length of the hash data. + * rng Random number generator. + * priv Private part of key - scalar. + * rm First part of result as an mp_int. + * sm Sirst part of result as an mp_int. + * heap Heap to use for allocation. + * returns RNG failures, MEMORY_E when memory allocation fails and + * MP_OKAY on success. + */ +int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, + mp_int* rm, mp_int* sm, void* heap) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d = NULL; +#else + sp_digit ed[2*5]; + sp_digit xd[2*5]; + sp_digit kd[2*5]; + sp_digit rd[2*5]; + sp_digit td[3 * 2*5]; + sp_point p; +#endif + sp_digit* e = NULL; + sp_digit* x = NULL; + sp_digit* k = NULL; + sp_digit* r = NULL; + sp_digit* tmp = NULL; + sp_point* point = NULL; + sp_digit carry; + sp_digit* s; + sp_digit* kInv; + int err = MP_OKAY; + int64_t c; + int i; + + (void)heap; + + err = sp_ecc_point_new(heap, p, point); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 5, heap, + DYNAMIC_TYPE_ECC); + if (d != NULL) { + e = d + 0 * 5; + x = d + 2 * 5; + k = d + 4 * 5; + r = d + 6 * 5; + tmp = d + 8 * 5; + } + else + err = MEMORY_E; + } +#else + e = ed; + x = xd; + k = kd; + r = rd; + tmp = td; +#endif + s = e; + kInv = k; + + if (err == MP_OKAY) { + if (hashLen > 32) + hashLen = 32; + + sp_256_from_bin(e, 5, hash, hashLen); + } + + for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { + sp_256_from_mp(x, 5, priv); + + /* New random point. */ + err = sp_256_ecc_gen_k_5(rng, k); + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_base_5(point, k, 1, NULL); + } + + if (err == MP_OKAY) { + /* r = point->x mod order */ + XMEMCPY(r, point->x, sizeof(sp_digit) * 5); + sp_256_norm_5(r); + c = sp_256_cmp_5(r, p256_order); + sp_256_cond_sub_5(r, r, p256_order, 0 - (c >= 0)); + sp_256_norm_5(r); + + /* Conv k to Montgomery form (mod order) */ + sp_256_mul_5(k, k, p256_norm_order); + err = sp_256_mod_5(k, k, p256_order); + } + if (err == MP_OKAY) { + sp_256_norm_5(k); + /* kInv = 1/k mod order */ + sp_256_mont_inv_order_5(kInv, k, tmp); + sp_256_norm_5(kInv); + + /* s = r * x + e */ + sp_256_mul_5(x, x, r); + err = sp_256_mod_5(x, x, p256_order); + } + if (err == MP_OKAY) { + sp_256_norm_5(x); + carry = sp_256_add_5(s, e, x); + sp_256_cond_sub_5(s, s, p256_order, 0 - carry); + sp_256_norm_5(s); + c = sp_256_cmp_5(s, p256_order); + sp_256_cond_sub_5(s, s, p256_order, 0 - (c >= 0)); + sp_256_norm_5(s); + + /* s = s * k^-1 mod order */ + sp_256_mont_mul_order_5(s, s, kInv); + sp_256_norm_5(s); + + /* Check that signature is usable. */ + if (!sp_256_iszero_5(s)) + break; + } + } + + if (i == 0) + err = RNG_FAILURE_E; + + if (err == MP_OKAY) + err = sp_256_to_mp(r, rm); + if (err == MP_OKAY) + err = sp_256_to_mp(s, sm); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) { + XMEMSET(d, 0, sizeof(sp_digit) * 8 * 5); + XFREE(d, heap, DYNAMIC_TYPE_ECC); + } +#else + XMEMSET(e, 0, sizeof(sp_digit) * 2 * 5); + XMEMSET(x, 0, sizeof(sp_digit) * 2 * 5); + XMEMSET(k, 0, sizeof(sp_digit) * 2 * 5); + XMEMSET(r, 0, sizeof(sp_digit) * 2 * 5); + XMEMSET(r, 0, sizeof(sp_digit) * 2 * 5); + XMEMSET(tmp, 0, sizeof(sp_digit) * 3 * 2*5); +#endif + sp_ecc_point_free(point, 1, heap); + + return err; +} +#endif /* HAVE_ECC_SIGN */ + +#ifdef HAVE_ECC_VERIFY +/* Verify the signature values with the hash and public key. + * e = Truncate(hash, 256) + * u1 = e/s mod order + * u2 = r/s mod order + * r == (u1.G + u2.Q)->x mod order + * Optimization: Leave point in projective form. + * (x, y, 1) == (x' / z'*z', y' / z'*z'*z', z' / z') + * (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' + * The hash is truncated to the first 256 bits. + * + * hash Hash to sign. + * hashLen Length of the hash data. + * rng Random number generator. + * priv Private part of key - scalar. + * rm First part of result as an mp_int. + * sm Sirst part of result as an mp_int. + * heap Heap to use for allocation. + * returns RNG failures, MEMORY_E when memory allocation fails and + * MP_OKAY on success. + */ +int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, + mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d = NULL; +#else + sp_digit u1d[2*5]; + sp_digit u2d[2*5]; + sp_digit sd[2*5]; + sp_digit tmpd[2*5 * 5]; + sp_point p1d; + sp_point p2d; +#endif + sp_digit* u1; + sp_digit* u2; + sp_digit* s; + sp_digit* tmp; + sp_point* p1; + sp_point* p2 = NULL; + sp_digit carry; + int64_t c; + int err; + + err = sp_ecc_point_new(heap, p1d, p1); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, p2d, p2); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 5, heap, + DYNAMIC_TYPE_ECC); + if (d != NULL) { + u1 = d + 0 * 5; + u2 = d + 2 * 5; + s = d + 4 * 5; + tmp = d + 6 * 5; + } + else + err = MEMORY_E; + } +#else + u1 = u1d; + u2 = u2d; + s = sd; + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + if (hashLen > 32) + hashLen = 32; + + sp_256_from_bin(u1, 5, hash, hashLen); + sp_256_from_mp(u2, 5, r); + sp_256_from_mp(s, 5, sm); + sp_256_from_mp(p2->x, 5, pX); + sp_256_from_mp(p2->y, 5, pY); + sp_256_from_mp(p2->z, 5, pZ); + + sp_256_mul_5(s, s, p256_norm_order); + err = sp_256_mod_5(s, s, p256_order); + } + if (err == MP_OKAY) { + sp_256_norm_5(s); + { + sp_256_mont_inv_order_5(s, s, tmp); + sp_256_mont_mul_order_5(u1, u1, s); + sp_256_mont_mul_order_5(u2, u2, s); + } + + err = sp_256_ecc_mulmod_base_5(p1, u1, 0, heap); + } + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_5(p2, p2, u2, 0, heap); + } + + if (err == MP_OKAY) { + sp_256_proj_point_add_5(p1, p1, p2, tmp); + + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_256_from_mp(u2, 5, r); + err = sp_256_mod_mul_norm_5(u2, u2, p256_mod); + } + + if (err == MP_OKAY) { + /* u1 = r.z'.z' mod prime */ + sp_256_mont_sqr_5(p1->z, p1->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_5(u1, u2, p1->z, p256_mod, p256_mp_mod); + *res = sp_256_cmp_5(p1->x, u1) == 0; + if (*res == 0) { + /* Reload r and add order. */ + sp_256_from_mp(u2, 5, r); + carry = sp_256_add_5(u2, u2, p256_order); + /* Carry means result is greater than mod and is not valid. */ + if (!carry) { + sp_256_norm_5(u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_256_cmp_5(u2, p256_mod); + if (c < 0) { + /* Convert to Montogomery form */ + err = sp_256_mod_mul_norm_5(u2, u2, p256_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_256_mont_mul_5(u1, u2, p1->z, p256_mod, + p256_mp_mod); + *res = sp_256_cmp_5(p1->x, u2) == 0; + } + } + } + } + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p1, 0, heap); + sp_ecc_point_free(p2, 0, heap); + + return err; +} +#endif /* HAVE_ECC_VERIFY */ + +#ifdef HAVE_ECC_CHECK_KEY +/* Check that the x and y oridinates are a valid point on the curve. + * + * point EC point. + * heap Heap to use if dynamically allocating. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +static int sp_256_ecc_is_point_5(sp_point* point, void* heap) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d = NULL; +#else + sp_digit t1d[2*5]; + sp_digit t2d[2*5]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 5 * 4, heap, + DYNAMIC_TYPE_ECC); + if (d != NULL) { + t1 = d + 0 * 5; + t2 = d + 2 * 5; + } + else + err = MEMORY_E; +#else + (void)heap; + + t1 = t1d; + t2 = t2d; +#endif + + if (err == MP_OKAY) { + sp_256_sqr_5(t1, point->y); + sp_256_mod_5(t1, t1, p256_mod); + sp_256_sqr_5(t2, point->x); + sp_256_mod_5(t2, t2, p256_mod); + sp_256_mul_5(t2, t2, point->x); + sp_256_mod_5(t2, t2, p256_mod); + sp_256_sub_5(t2, p256_mod, t2); + sp_256_mont_add_5(t1, t1, t2, p256_mod); + + sp_256_mont_add_5(t1, t1, point->x, p256_mod); + sp_256_mont_add_5(t1, t1, point->x, p256_mod); + sp_256_mont_add_5(t1, t1, point->x, p256_mod); + + if (sp_256_cmp_5(t1, p256_b) != 0) + err = MP_VAL; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Check that the x and y oridinates are a valid point on the curve. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +int sp_ecc_is_point_256(mp_int* pX, mp_int* pY) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point pubd; +#endif + sp_point* pub; + byte one[1] = { 1 }; + int err; + + err = sp_ecc_point_new(NULL, pubd, pub); + if (err == MP_OKAY) { + sp_256_from_mp(pub->x, 5, pX); + sp_256_from_mp(pub->y, 5, pY); + sp_256_from_bin(pub->z, 5, one, sizeof(one)); + + err = sp_256_ecc_is_point_5(pub, NULL); + } + + sp_ecc_point_free(pub, 0, NULL); + + return err; +} + +/* Check that the private scalar generates the EC point (px, py), the point is + * on the curve and the point has the correct order. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * privm Private scalar that generates EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve, ECC_INF_E if the point does not have the correct order, + * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and + * MP_OKAY otherwise. + */ +int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit privd[5]; + sp_point pubd; + sp_point pd; +#endif + sp_digit* priv = NULL; + sp_point* pub; + sp_point* p = NULL; + byte one[1] = { 1 }; + int err; + + err = sp_ecc_point_new(heap, pubd, pub); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 5, heap, + DYNAMIC_TYPE_ECC); + if (priv == NULL) + err = MEMORY_E; + } +#else + priv = privd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(pub->x, 5, pX); + sp_256_from_mp(pub->y, 5, pY); + sp_256_from_bin(pub->z, 5, one, sizeof(one)); + sp_256_from_mp(priv, 5, privm); + + /* Check point at infinitiy. */ + if (sp_256_iszero_5(pub->x) && + sp_256_iszero_5(pub->y)) + err = ECC_INF_E; + } + + if (err == MP_OKAY) { + /* Check range of X and Y */ + if (sp_256_cmp_5(pub->x, p256_mod) >= 0 || + sp_256_cmp_5(pub->y, p256_mod) >= 0) + err = ECC_OUT_OF_RANGE_E; + } + + if (err == MP_OKAY) { + /* Check point is on curve */ + err = sp_256_ecc_is_point_5(pub, heap); + } + + if (err == MP_OKAY) { + /* Point * order = infinity */ + err = sp_256_ecc_mulmod_5(p, pub, p256_order, 1, heap); + } + if (err == MP_OKAY) { + /* Check result is infinity */ + if (!sp_256_iszero_5(p->x) || + !sp_256_iszero_5(p->y)) { + err = ECC_INF_E; + } + } + + if (err == MP_OKAY) { + /* Base * private = point */ + err = sp_256_ecc_mulmod_base_5(p, priv, 1, heap); + } + if (err == MP_OKAY) { + /* Check result is public key */ + if (sp_256_cmp_5(p->x, pub->x) != 0 || + sp_256_cmp_5(p->y, pub->y) != 0) { + err = ECC_PRIV_KEY_E; + } + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (priv != NULL) + XFREE(priv, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p, 0, heap); + sp_ecc_point_free(pub, 0, heap); + + return err; +} +#endif +#ifdef WOLFSSL_PUBLIC_ECC_ADD_DBL +/* Add two projective EC points together. + * (pX, pY, pZ) + (qX, qY, qZ) = (rX, rY, rZ) + * + * pX First EC point's X ordinate. + * pY First EC point's Y ordinate. + * pZ First EC point's Z ordinate. + * qX Second EC point's X ordinate. + * qY Second EC point's Y ordinate. + * qZ Second EC point's Z ordinate. + * rX Resultant EC point's X ordinate. + * rY Resultant EC point's Y ordinate. + * rZ Resultant EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* qX, mp_int* qY, mp_int* qZ, + mp_int* rX, mp_int* rY, mp_int* rZ) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit tmpd[2 * 5 * 5]; + sp_point pd; + sp_point qd; +#endif + sp_digit* tmp; + sp_point* p; + sp_point* q = NULL; + int err; + + err = sp_ecc_point_new(NULL, pd, p); + if (err == MP_OKAY) + err = sp_ecc_point_new(NULL, qd, q); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 5 * 5, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } +#else + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 5, pX); + sp_256_from_mp(p->y, 5, pY); + sp_256_from_mp(p->z, 5, pZ); + sp_256_from_mp(q->x, 5, qX); + sp_256_from_mp(q->y, 5, qY); + sp_256_from_mp(q->z, 5, qZ); + + sp_256_proj_point_add_5(p, p, q, tmp); + } + + if (err == MP_OKAY) + err = sp_256_to_mp(p->x, rX); + if (err == MP_OKAY) + err = sp_256_to_mp(p->y, rY); + if (err == MP_OKAY) + err = sp_256_to_mp(p->z, rZ); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (tmp != NULL) + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(q, 0, NULL); + sp_ecc_point_free(p, 0, NULL); + + return err; +} + +/* Double a projective EC point. + * (pX, pY, pZ) + (pX, pY, pZ) = (rX, rY, rZ) + * + * pX EC point's X ordinate. + * pY EC point's Y ordinate. + * pZ EC point's Z ordinate. + * rX Resultant EC point's X ordinate. + * rY Resultant EC point's Y ordinate. + * rZ Resultant EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* rX, mp_int* rY, mp_int* rZ) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit tmpd[2 * 5 * 2]; + sp_point pd; +#endif + sp_digit* tmp; + sp_point* p; + int err; + + err = sp_ecc_point_new(NULL, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 5 * 2, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } +#else + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 5, pX); + sp_256_from_mp(p->y, 5, pY); + sp_256_from_mp(p->z, 5, pZ); + + sp_256_proj_point_dbl_5(p, p, tmp); + } + + if (err == MP_OKAY) + err = sp_256_to_mp(p->x, rX); + if (err == MP_OKAY) + err = sp_256_to_mp(p->y, rY); + if (err == MP_OKAY) + err = sp_256_to_mp(p->z, rZ); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (tmp != NULL) + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p, 0, NULL); + + return err; +} + +/* Map a projective EC point to affine in place. + * pZ will be one. + * + * pX EC point's X ordinate. + * pY EC point's Y ordinate. + * pZ EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit tmpd[2 * 5 * 4]; + sp_point pd; +#endif + sp_digit* tmp; + sp_point* p; + int err; + + err = sp_ecc_point_new(NULL, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 5 * 4, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } +#else + tmp = tmpd; +#endif + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 5, pX); + sp_256_from_mp(p->y, 5, pY); + sp_256_from_mp(p->z, 5, pZ); + + sp_256_map_5(p, p, tmp); + } + + if (err == MP_OKAY) + err = sp_256_to_mp(p->x, pX); + if (err == MP_OKAY) + err = sp_256_to_mp(p->y, pY); + if (err == MP_OKAY) + err = sp_256_to_mp(p->z, pZ); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (tmp != NULL) + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p, 0, NULL); + + return err; +} +#endif /* WOLFSSL_PUBLIC_ECC_ADD_DBL */ +#ifdef HAVE_COMP_KEY +/* Find the square root of a number mod the prime of the curve. + * + * y The number to operate on and the result. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +static int sp_256_mont_sqrt_5(sp_digit* y) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d; +#else + sp_digit t1d[2 * 5]; + sp_digit t2d[2 * 5]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 5, NULL, DYNAMIC_TYPE_ECC); + if (d != NULL) { + t1 = d + 0 * 5; + t2 = d + 2 * 5; + } + else + err = MEMORY_E; +#else + t1 = t1d; + t2 = t2d; +#endif + + if (err == MP_OKAY) { + { + /* t2 = y ^ 0x2 */ + sp_256_mont_sqr_5(t2, y, p256_mod, p256_mp_mod); + /* t1 = y ^ 0x3 */ + sp_256_mont_mul_5(t1, t2, y, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xc */ + sp_256_mont_sqr_n_5(t2, t1, 2, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xf */ + sp_256_mont_mul_5(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xf0 */ + sp_256_mont_sqr_n_5(t2, t1, 4, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xff */ + sp_256_mont_mul_5(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xff00 */ + sp_256_mont_sqr_n_5(t2, t1, 8, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffff */ + sp_256_mont_mul_5(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xffff0000 */ + sp_256_mont_sqr_n_5(t2, t1, 16, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff */ + sp_256_mont_mul_5(t1, t1, t2, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000000 */ + sp_256_mont_sqr_n_5(t1, t1, 32, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001 */ + sp_256_mont_mul_5(t1, t1, y, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001000000000000000000000000 */ + sp_256_mont_sqr_n_5(t1, t1, 96, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001000000000000000000000001 */ + sp_256_mont_mul_5(t1, t1, y, p256_mod, p256_mp_mod); + sp_256_mont_sqr_n_5(y, t1, 94, p256_mod, p256_mp_mod); + } + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Uncompress the point given the X ordinate. + * + * xm X ordinate. + * odd Whether the Y ordinate is odd. + * ym Calculated Y ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d; +#else + sp_digit xd[2 * 5]; + sp_digit yd[2 * 5]; +#endif + sp_digit* x; + sp_digit* y; + int err = MP_OKAY; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 5, NULL, DYNAMIC_TYPE_ECC); + if (d != NULL) { + x = d + 0 * 5; + y = d + 2 * 5; + } + else + err = MEMORY_E; +#else + x = xd; + y = yd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(x, 5, xm); + + err = sp_256_mod_mul_norm_5(x, x, p256_mod); + } + + if (err == MP_OKAY) { + /* y = x^3 */ + { + sp_256_mont_sqr_5(y, x, p256_mod, p256_mp_mod); + sp_256_mont_mul_5(y, y, x, p256_mod, p256_mp_mod); + } + /* y = x^3 - 3x */ + sp_256_mont_sub_5(y, y, x, p256_mod); + sp_256_mont_sub_5(y, y, x, p256_mod); + sp_256_mont_sub_5(y, y, x, p256_mod); + /* y = x^3 - 3x + b */ + err = sp_256_mod_mul_norm_5(x, p256_b, p256_mod); + } + if (err == MP_OKAY) { + sp_256_mont_add_5(y, y, x, p256_mod); + /* y = sqrt(x^3 - 3x + b) */ + err = sp_256_mont_sqrt_5(y); + } + if (err == MP_OKAY) { + XMEMSET(y + 5, 0, 5 * sizeof(sp_digit)); + sp_256_mont_reduce_5(y, p256_mod, p256_mp_mod); + if (((y[0] ^ odd) & 1) != 0) + sp_256_mont_sub_5(y, p256_mod, y, p256_mod); + + err = sp_256_to_mp(y, ym); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_ECC); +#endif + + return err; +} +#endif +#endif /* !WOLFSSL_SP_NO_256 */ +#endif /* WOLFSSL_HAVE_SP_ECC */ +#endif /* SP_WORD_SIZE == 64 */ +#endif /* !WOLFSSL_SP_ASM */ +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH || WOLFSSL_HAVE_SP_ECC */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/sp_cortexm.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/sp_cortexm.c new file mode 100755 index 0000000..e9952bf --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/sp_cortexm.c @@ -0,0 +1,16932 @@ +/* sp.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/* Implementation by Sean Parkinson. */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include +#include +#include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) || \ + defined(WOLFSSL_HAVE_SP_ECC) + +#ifdef RSA_LOW_MEM +#ifndef WOLFSSL_SP_SMALL +#define WOLFSSL_SP_SMALL +#endif +#endif + +#include + +#ifdef __IAR_SYSTEMS_ICC__ +#define __asm__ asm +#define __volatile__ volatile +#endif /* __IAR_SYSTEMS_ICC__ */ + +#ifdef WOLFSSL_SP_ARM_CORTEX_M_ASM +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) +#ifndef WOLFSSL_SP_NO_2048 +/* Read big endian unsigned byte aray into r. + * + * r A single precision integer. + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_2048_from_bin(sp_digit* r, int max, const byte* a, int n) +{ + int i, j = 0, s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= ((sp_digit)a[i]) << s; + if (s >= 24) { + r[j] &= 0xffffffff; + s = 32 - s; + if (j + 1 >= max) + break; + r[++j] = a[i] >> s; + s = 8 - s; + } + else + s += 8; + } + + for (j++; j < max; j++) + r[j] = 0; +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * a A multi-precision integer. + */ +static void sp_2048_from_mp(sp_digit* r, int max, mp_int* a) +{ +#if DIGIT_BIT == 32 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < max; j++) + r[j] = 0; +#elif DIGIT_BIT > 32 + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= a->dp[i] << s; + r[j] &= 0xffffffff; + s = 32 - s; + if (j + 1 >= max) + break; + r[++j] = a->dp[i] >> s; + while (s + 32 <= DIGIT_BIT) { + s += 32; + r[j] &= 0xffffffff; + if (j + 1 >= max) + break; + if (s < DIGIT_BIT) + r[++j] = a->dp[i] >> s; + else + r[++j] = 0; + } + s = DIGIT_BIT - s; + } + + for (j++; j < max; j++) + r[j] = 0; +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 32) { + r[j] &= 0xffffffff; + if (j + 1 >= max) + break; + s = 32 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else + s += DIGIT_BIT; + } + + for (j++; j < max; j++) + r[j] = 0; +#endif +} + +/* Write r as big endian to byte aray. + * Fixed length number of bytes written: 256 + * + * r A single precision integer. + * a Byte array. + */ +static void sp_2048_to_bin(sp_digit* r, byte* a) +{ + int i, j, s = 0, b; + + j = 2048 / 8 - 1; + a[j] = 0; + for (i=0; i<64 && j>=0; i++) { + b = 0; + a[j--] |= r[i] << s; b += 8 - s; + if (j < 0) + break; + while (b < 32) { + a[j--] = r[i] >> b; b += 8; + if (j < 0) + break; + } + s = 8 - (b - 32); + if (j >= 0) + a[j] = 0; + if (s != 0) + j++; + } +} + +#ifndef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_2048_mul_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit tmp[8]; + __asm__ __volatile__ ( + "mov r8, %[r]\n\t" + "mov %[r], #0\n\t" + /* A[0] * B[0] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[b], #0]\n\t" + "umull r3, r4, r6, r7\n\t" + "mov r5, #0\n\t" + "str r3, [%[tmp], #0]\n\t" + "mov r3, #0\n\t" + /* A[0] * B[1] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[b], #4]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[1] * B[0] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[b], #0]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "str r4, [%[tmp], #4]\n\t" + "mov r4, #0\n\t" + /* A[0] * B[2] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[b], #8]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[1] * B[1] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[b], #4]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[2] * B[0] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[b], #0]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + "str r5, [%[tmp], #8]\n\t" + "mov r5, #0\n\t" + /* A[0] * B[3] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[b], #12]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[1] * B[2] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[b], #8]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[2] * B[1] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[b], #4]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[3] * B[0] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b], #0]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "str r3, [%[tmp], #12]\n\t" + "mov r3, #0\n\t" + /* A[0] * B[4] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[b], #16]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[1] * B[3] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[b], #12]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[2] * B[2] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[b], #8]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[3] * B[1] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b], #4]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[4] * B[0] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[b], #0]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "str r4, [%[tmp], #16]\n\t" + "mov r4, #0\n\t" + /* A[0] * B[5] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[b], #20]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[1] * B[4] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[b], #16]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[2] * B[3] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[b], #12]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[3] * B[2] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b], #8]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[4] * B[1] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[b], #4]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[5] * B[0] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r7, [%[b], #0]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + "str r5, [%[tmp], #20]\n\t" + "mov r5, #0\n\t" + /* A[0] * B[6] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[b], #24]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[1] * B[5] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[b], #20]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[2] * B[4] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[b], #16]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[3] * B[3] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b], #12]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[4] * B[2] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[b], #8]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[5] * B[1] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r7, [%[b], #4]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[6] * B[0] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[b], #0]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "str r3, [%[tmp], #24]\n\t" + "mov r3, #0\n\t" + /* A[0] * B[7] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[b], #28]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[1] * B[6] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[b], #24]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[2] * B[5] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[b], #20]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[3] * B[4] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b], #16]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[4] * B[3] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[b], #12]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[5] * B[2] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r7, [%[b], #8]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[6] * B[1] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[b], #4]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[7] * B[0] */ + "ldr r6, [%[a], #28]\n\t" + "ldr r7, [%[b], #0]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "str r4, [%[tmp], #28]\n\t" + "mov r4, #0\n\t" + /* A[1] * B[7] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[b], #28]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[2] * B[6] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[b], #24]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[3] * B[5] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b], #20]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[4] * B[4] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[b], #16]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[5] * B[3] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r7, [%[b], #12]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[6] * B[2] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[b], #8]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[7] * B[1] */ + "ldr r6, [%[a], #28]\n\t" + "ldr r7, [%[b], #4]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + "str r5, [r8, #32]\n\t" + "mov r5, #0\n\t" + /* A[2] * B[7] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[b], #28]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[3] * B[6] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b], #24]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[4] * B[5] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[b], #20]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[5] * B[4] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r7, [%[b], #16]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[6] * B[3] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[b], #12]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[7] * B[2] */ + "ldr r6, [%[a], #28]\n\t" + "ldr r7, [%[b], #8]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "str r3, [r8, #36]\n\t" + "mov r3, #0\n\t" + /* A[3] * B[7] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b], #28]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[4] * B[6] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[b], #24]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[5] * B[5] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r7, [%[b], #20]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[6] * B[4] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[b], #16]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[7] * B[3] */ + "ldr r6, [%[a], #28]\n\t" + "ldr r7, [%[b], #12]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "str r4, [r8, #40]\n\t" + "mov r4, #0\n\t" + /* A[4] * B[7] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[b], #28]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[5] * B[6] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r7, [%[b], #24]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[6] * B[5] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[b], #20]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[7] * B[4] */ + "ldr r6, [%[a], #28]\n\t" + "ldr r7, [%[b], #16]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + "str r5, [r8, #44]\n\t" + "mov r5, #0\n\t" + /* A[5] * B[7] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r7, [%[b], #28]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[6] * B[6] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[b], #24]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[7] * B[5] */ + "ldr r6, [%[a], #28]\n\t" + "ldr r7, [%[b], #20]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "str r3, [r8, #48]\n\t" + "mov r3, #0\n\t" + /* A[6] * B[7] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[b], #28]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[7] * B[6] */ + "ldr r6, [%[a], #28]\n\t" + "ldr r7, [%[b], #24]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "str r4, [r8, #52]\n\t" + "mov r4, #0\n\t" + /* A[7] * B[7] */ + "ldr r6, [%[a], #28]\n\t" + "ldr r7, [%[b], #28]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "str r5, [r8, #56]\n\t" + "str r3, [r8, #60]\n\t" + "ldr r3, [%[tmp], #0]\n\t" + "ldr r4, [%[tmp], #4]\n\t" + "ldr r5, [%[tmp], #8]\n\t" + "ldr r6, [%[tmp], #12]\n\t" + "str r3, [r8, #0]\n\t" + "str r4, [r8, #4]\n\t" + "str r5, [r8, #8]\n\t" + "str r6, [r8, #12]\n\t" + "ldr r3, [%[tmp], #16]\n\t" + "ldr r4, [%[tmp], #20]\n\t" + "ldr r5, [%[tmp], #24]\n\t" + "ldr r6, [%[tmp], #28]\n\t" + "str r3, [r8, #16]\n\t" + "str r4, [r8, #20]\n\t" + "str r5, [r8, #24]\n\t" + "str r6, [r8, #28]\n\t" + "mov %[r], r8\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [tmp] "r" (tmp) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8" + ); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_2048_sqr_8(sp_digit* r, const sp_digit* a) +{ + sp_digit tmp[8]; + __asm__ __volatile__ ( + "mov r8, %[r]\n\t" + "mov %[r], #0\n\t" + /* A[0] * A[0] */ + "ldr r6, [%[a], #0]\n\t" + "umull r3, r4, r6, r6\n\t" + "mov r5, #0\n\t" + "str r3, [%[tmp], #0]\n\t" + "mov r3, #0\n\t" + /* A[0] * A[1] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[a], #4]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "str r4, [%[tmp], #4]\n\t" + "mov r4, #0\n\t" + /* A[0] * A[2] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[a], #8]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[1] * A[1] */ + "ldr r6, [%[a], #4]\n\t" + "umull r6, r7, r6, r6\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + "str r5, [%[tmp], #8]\n\t" + "mov r5, #0\n\t" + /* A[0] * A[3] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[a], #12]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[1] * A[2] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[a], #8]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "str r3, [%[tmp], #12]\n\t" + "mov r3, #0\n\t" + /* A[0] * A[4] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[a], #16]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[1] * A[3] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[a], #12]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[2] * A[2] */ + "ldr r6, [%[a], #8]\n\t" + "umull r6, r7, r6, r6\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "str r4, [%[tmp], #16]\n\t" + "mov r4, #0\n\t" + /* A[0] * A[5] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[a], #20]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[1] * A[4] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[a], #16]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[2] * A[3] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #12]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + "str r5, [%[tmp], #20]\n\t" + "mov r5, #0\n\t" + /* A[0] * A[6] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[a], #24]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[1] * A[5] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[a], #20]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[2] * A[4] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #16]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[3] * A[3] */ + "ldr r6, [%[a], #12]\n\t" + "umull r6, r7, r6, r6\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "str r3, [%[tmp], #24]\n\t" + "mov r3, #0\n\t" + /* A[0] * A[7] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[a], #28]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[1] * A[6] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[a], #24]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[2] * A[5] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #20]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[3] * A[4] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[a], #16]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "str r4, [%[tmp], #28]\n\t" + "mov r4, #0\n\t" + /* A[1] * A[7] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[a], #28]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[2] * A[6] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #24]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[3] * A[5] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[a], #20]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[4] * A[4] */ + "ldr r6, [%[a], #16]\n\t" + "umull r6, r7, r6, r6\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + "str r5, [r8, #32]\n\t" + "mov r5, #0\n\t" + /* A[2] * A[7] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #28]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[3] * A[6] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[a], #24]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[4] * A[5] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[a], #20]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "str r3, [r8, #36]\n\t" + "mov r3, #0\n\t" + /* A[3] * A[7] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[a], #28]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[4] * A[6] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[a], #24]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[5] * A[5] */ + "ldr r6, [%[a], #20]\n\t" + "umull r6, r7, r6, r6\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "str r4, [r8, #40]\n\t" + "mov r4, #0\n\t" + /* A[4] * A[7] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[a], #28]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[5] * A[6] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r7, [%[a], #24]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + "str r5, [r8, #44]\n\t" + "mov r5, #0\n\t" + /* A[5] * A[7] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r7, [%[a], #28]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[6] * A[6] */ + "ldr r6, [%[a], #24]\n\t" + "umull r6, r7, r6, r6\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "str r3, [r8, #48]\n\t" + "mov r3, #0\n\t" + /* A[6] * A[7] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[a], #28]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "str r4, [r8, #52]\n\t" + "mov r4, #0\n\t" + /* A[7] * A[7] */ + "ldr r6, [%[a], #28]\n\t" + "umull r6, r7, r6, r6\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "str r5, [r8, #56]\n\t" + "str r3, [r8, #60]\n\t" + "ldr r3, [%[tmp], #0]\n\t" + "ldr r4, [%[tmp], #4]\n\t" + "ldr r5, [%[tmp], #8]\n\t" + "ldr r6, [%[tmp], #12]\n\t" + "str r3, [r8, #0]\n\t" + "str r4, [r8, #4]\n\t" + "str r5, [r8, #8]\n\t" + "str r6, [r8, #12]\n\t" + "ldr r3, [%[tmp], #16]\n\t" + "ldr r4, [%[tmp], #20]\n\t" + "ldr r5, [%[tmp], #24]\n\t" + "ldr r6, [%[tmp], #28]\n\t" + "str r3, [r8, #16]\n\t" + "str r4, [r8, #20]\n\t" + "str r5, [r8, #24]\n\t" + "str r6, [r8, #28]\n\t" + "mov %[r], r8\n\t" + : + : [r] "r" (r), [a] "r" (a), [tmp] "r" (tmp) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8" + ); +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_2048_add_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "adds r4, r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5" + ); + + return c; +} + +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_2048_sub_in_place_16(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r6, [%[b], #4]\n\t" + "subs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #0]\n\t" + "str r4, [%[a], #4]\n\t" + "ldr r3, [%[a], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r6, [%[b], #12]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #8]\n\t" + "str r4, [%[a], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r6, [%[b], #20]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #16]\n\t" + "str r4, [%[a], #20]\n\t" + "ldr r3, [%[a], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r6, [%[b], #28]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #24]\n\t" + "str r4, [%[a], #28]\n\t" + "ldr r3, [%[a], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r6, [%[b], #36]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #32]\n\t" + "str r4, [%[a], #36]\n\t" + "ldr r3, [%[a], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r6, [%[b], #44]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #40]\n\t" + "str r4, [%[a], #44]\n\t" + "ldr r3, [%[a], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #48]\n\t" + "ldr r6, [%[b], #52]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #48]\n\t" + "str r4, [%[a], #52]\n\t" + "ldr r3, [%[a], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #56]\n\t" + "ldr r6, [%[b], #60]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #56]\n\t" + "str r4, [%[a], #60]\n\t" + "sbc %[c], %[c], %[c]\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6" + ); + + return c; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_2048_add_16(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "adds r4, r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[b], #48]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #52]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[b], #56]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #60]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #60]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5" + ); + + return c; +} + +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_2048_mask_8(sp_digit* r, sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<8; i++) + r[i] = a[i] & m; +#else + r[0] = a[0] & m; + r[1] = a[1] & m; + r[2] = a[2] & m; + r[3] = a[3] & m; + r[4] = a[4] & m; + r[5] = a[5] & m; + r[6] = a[6] & m; + r[7] = a[7] & m; +#endif +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_2048_mul_16(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[16]; + sp_digit a1[8]; + sp_digit b1[8]; + sp_digit z2[16]; + sp_digit u, ca, cb; + + ca = sp_2048_add_8(a1, a, &a[8]); + cb = sp_2048_add_8(b1, b, &b[8]); + u = ca & cb; + sp_2048_mul_8(z1, a1, b1); + sp_2048_mul_8(z2, &a[8], &b[8]); + sp_2048_mul_8(z0, a, b); + sp_2048_mask_8(r + 16, a1, 0 - cb); + sp_2048_mask_8(b1, b1, 0 - ca); + u += sp_2048_add_8(r + 16, r + 16, b1); + u += sp_2048_sub_in_place_16(z1, z2); + u += sp_2048_sub_in_place_16(z1, z0); + u += sp_2048_add_16(r + 8, r + 8, z1); + r[24] = u; + XMEMSET(r + 24 + 1, 0, sizeof(sp_digit) * (8 - 1)); + sp_2048_add_16(r + 16, r + 16, z2); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_2048_sqr_16(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z2[16]; + sp_digit z1[16]; + sp_digit a1[8]; + sp_digit u; + + u = sp_2048_add_8(a1, a, &a[8]); + sp_2048_sqr_8(z1, a1); + sp_2048_sqr_8(z2, &a[8]); + sp_2048_sqr_8(z0, a); + sp_2048_mask_8(r + 16, a1, 0 - u); + u += sp_2048_add_8(r + 16, r + 16, r + 16); + u += sp_2048_sub_in_place_16(z1, z2); + u += sp_2048_sub_in_place_16(z1, z0); + u += sp_2048_add_16(r + 8, r + 8, z1); + r[24] = u; + XMEMSET(r + 24 + 1, 0, sizeof(sp_digit) * (8 - 1)); + sp_2048_add_16(r + 16, r + 16, z2); +} + +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_2048_sub_in_place_32(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r6, [%[b], #4]\n\t" + "subs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #0]\n\t" + "str r4, [%[a], #4]\n\t" + "ldr r3, [%[a], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r6, [%[b], #12]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #8]\n\t" + "str r4, [%[a], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r6, [%[b], #20]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #16]\n\t" + "str r4, [%[a], #20]\n\t" + "ldr r3, [%[a], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r6, [%[b], #28]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #24]\n\t" + "str r4, [%[a], #28]\n\t" + "ldr r3, [%[a], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r6, [%[b], #36]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #32]\n\t" + "str r4, [%[a], #36]\n\t" + "ldr r3, [%[a], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r6, [%[b], #44]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #40]\n\t" + "str r4, [%[a], #44]\n\t" + "ldr r3, [%[a], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #48]\n\t" + "ldr r6, [%[b], #52]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #48]\n\t" + "str r4, [%[a], #52]\n\t" + "ldr r3, [%[a], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #56]\n\t" + "ldr r6, [%[b], #60]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #56]\n\t" + "str r4, [%[a], #60]\n\t" + "ldr r3, [%[a], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #64]\n\t" + "ldr r6, [%[b], #68]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #64]\n\t" + "str r4, [%[a], #68]\n\t" + "ldr r3, [%[a], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #72]\n\t" + "ldr r6, [%[b], #76]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #72]\n\t" + "str r4, [%[a], #76]\n\t" + "ldr r3, [%[a], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #80]\n\t" + "ldr r6, [%[b], #84]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #80]\n\t" + "str r4, [%[a], #84]\n\t" + "ldr r3, [%[a], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #88]\n\t" + "ldr r6, [%[b], #92]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #88]\n\t" + "str r4, [%[a], #92]\n\t" + "ldr r3, [%[a], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #96]\n\t" + "ldr r6, [%[b], #100]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #96]\n\t" + "str r4, [%[a], #100]\n\t" + "ldr r3, [%[a], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #104]\n\t" + "ldr r6, [%[b], #108]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #104]\n\t" + "str r4, [%[a], #108]\n\t" + "ldr r3, [%[a], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #112]\n\t" + "ldr r6, [%[b], #116]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #112]\n\t" + "str r4, [%[a], #116]\n\t" + "ldr r3, [%[a], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #120]\n\t" + "ldr r6, [%[b], #124]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #120]\n\t" + "str r4, [%[a], #124]\n\t" + "sbc %[c], %[c], %[c]\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6" + ); + + return c; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_2048_add_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "adds r4, r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[b], #48]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #52]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[b], #56]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #60]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[b], #64]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #68]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[b], #72]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #76]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[b], #80]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #84]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[b], #88]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #92]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[b], #96]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #100]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[b], #104]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #108]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[b], #112]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #116]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[b], #120]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #124]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #124]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5" + ); + + return c; +} + +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_2048_mask_16(sp_digit* r, sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<16; i++) + r[i] = a[i] & m; +#else + int i; + + for (i = 0; i < 16; i += 8) { + r[i+0] = a[i+0] & m; + r[i+1] = a[i+1] & m; + r[i+2] = a[i+2] & m; + r[i+3] = a[i+3] & m; + r[i+4] = a[i+4] & m; + r[i+5] = a[i+5] & m; + r[i+6] = a[i+6] & m; + r[i+7] = a[i+7] & m; + } +#endif +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_2048_mul_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[32]; + sp_digit a1[16]; + sp_digit b1[16]; + sp_digit z2[32]; + sp_digit u, ca, cb; + + ca = sp_2048_add_16(a1, a, &a[16]); + cb = sp_2048_add_16(b1, b, &b[16]); + u = ca & cb; + sp_2048_mul_16(z1, a1, b1); + sp_2048_mul_16(z2, &a[16], &b[16]); + sp_2048_mul_16(z0, a, b); + sp_2048_mask_16(r + 32, a1, 0 - cb); + sp_2048_mask_16(b1, b1, 0 - ca); + u += sp_2048_add_16(r + 32, r + 32, b1); + u += sp_2048_sub_in_place_32(z1, z2); + u += sp_2048_sub_in_place_32(z1, z0); + u += sp_2048_add_32(r + 16, r + 16, z1); + r[48] = u; + XMEMSET(r + 48 + 1, 0, sizeof(sp_digit) * (16 - 1)); + sp_2048_add_32(r + 32, r + 32, z2); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_2048_sqr_32(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z2[32]; + sp_digit z1[32]; + sp_digit a1[16]; + sp_digit u; + + u = sp_2048_add_16(a1, a, &a[16]); + sp_2048_sqr_16(z1, a1); + sp_2048_sqr_16(z2, &a[16]); + sp_2048_sqr_16(z0, a); + sp_2048_mask_16(r + 32, a1, 0 - u); + u += sp_2048_add_16(r + 32, r + 32, r + 32); + u += sp_2048_sub_in_place_32(z1, z2); + u += sp_2048_sub_in_place_32(z1, z0); + u += sp_2048_add_32(r + 16, r + 16, z1); + r[48] = u; + XMEMSET(r + 48 + 1, 0, sizeof(sp_digit) * (16 - 1)); + sp_2048_add_32(r + 32, r + 32, z2); +} + +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_2048_sub_in_place_64(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r6, [%[b], #4]\n\t" + "subs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #0]\n\t" + "str r4, [%[a], #4]\n\t" + "ldr r3, [%[a], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r6, [%[b], #12]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #8]\n\t" + "str r4, [%[a], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r6, [%[b], #20]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #16]\n\t" + "str r4, [%[a], #20]\n\t" + "ldr r3, [%[a], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r6, [%[b], #28]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #24]\n\t" + "str r4, [%[a], #28]\n\t" + "ldr r3, [%[a], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r6, [%[b], #36]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #32]\n\t" + "str r4, [%[a], #36]\n\t" + "ldr r3, [%[a], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r6, [%[b], #44]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #40]\n\t" + "str r4, [%[a], #44]\n\t" + "ldr r3, [%[a], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #48]\n\t" + "ldr r6, [%[b], #52]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #48]\n\t" + "str r4, [%[a], #52]\n\t" + "ldr r3, [%[a], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #56]\n\t" + "ldr r6, [%[b], #60]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #56]\n\t" + "str r4, [%[a], #60]\n\t" + "ldr r3, [%[a], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #64]\n\t" + "ldr r6, [%[b], #68]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #64]\n\t" + "str r4, [%[a], #68]\n\t" + "ldr r3, [%[a], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #72]\n\t" + "ldr r6, [%[b], #76]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #72]\n\t" + "str r4, [%[a], #76]\n\t" + "ldr r3, [%[a], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #80]\n\t" + "ldr r6, [%[b], #84]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #80]\n\t" + "str r4, [%[a], #84]\n\t" + "ldr r3, [%[a], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #88]\n\t" + "ldr r6, [%[b], #92]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #88]\n\t" + "str r4, [%[a], #92]\n\t" + "ldr r3, [%[a], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #96]\n\t" + "ldr r6, [%[b], #100]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #96]\n\t" + "str r4, [%[a], #100]\n\t" + "ldr r3, [%[a], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #104]\n\t" + "ldr r6, [%[b], #108]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #104]\n\t" + "str r4, [%[a], #108]\n\t" + "ldr r3, [%[a], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #112]\n\t" + "ldr r6, [%[b], #116]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #112]\n\t" + "str r4, [%[a], #116]\n\t" + "ldr r3, [%[a], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #120]\n\t" + "ldr r6, [%[b], #124]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #120]\n\t" + "str r4, [%[a], #124]\n\t" + "sbc %[c], %[c], %[c]\n\t" + "add %[a], %[a], #0x80\n\t" + "add %[b], %[b], #0x80\n\t" + "mov r5, #0\n\t" + "sub r5, r5, %[c]\n\t" + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #0]\n\t" + "str r4, [%[a], #4]\n\t" + "ldr r3, [%[a], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r6, [%[b], #12]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #8]\n\t" + "str r4, [%[a], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r6, [%[b], #20]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #16]\n\t" + "str r4, [%[a], #20]\n\t" + "ldr r3, [%[a], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r6, [%[b], #28]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #24]\n\t" + "str r4, [%[a], #28]\n\t" + "ldr r3, [%[a], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r6, [%[b], #36]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #32]\n\t" + "str r4, [%[a], #36]\n\t" + "ldr r3, [%[a], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r6, [%[b], #44]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #40]\n\t" + "str r4, [%[a], #44]\n\t" + "ldr r3, [%[a], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #48]\n\t" + "ldr r6, [%[b], #52]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #48]\n\t" + "str r4, [%[a], #52]\n\t" + "ldr r3, [%[a], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #56]\n\t" + "ldr r6, [%[b], #60]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #56]\n\t" + "str r4, [%[a], #60]\n\t" + "ldr r3, [%[a], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #64]\n\t" + "ldr r6, [%[b], #68]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #64]\n\t" + "str r4, [%[a], #68]\n\t" + "ldr r3, [%[a], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #72]\n\t" + "ldr r6, [%[b], #76]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #72]\n\t" + "str r4, [%[a], #76]\n\t" + "ldr r3, [%[a], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #80]\n\t" + "ldr r6, [%[b], #84]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #80]\n\t" + "str r4, [%[a], #84]\n\t" + "ldr r3, [%[a], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #88]\n\t" + "ldr r6, [%[b], #92]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #88]\n\t" + "str r4, [%[a], #92]\n\t" + "ldr r3, [%[a], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #96]\n\t" + "ldr r6, [%[b], #100]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #96]\n\t" + "str r4, [%[a], #100]\n\t" + "ldr r3, [%[a], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #104]\n\t" + "ldr r6, [%[b], #108]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #104]\n\t" + "str r4, [%[a], #108]\n\t" + "ldr r3, [%[a], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #112]\n\t" + "ldr r6, [%[b], #116]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #112]\n\t" + "str r4, [%[a], #116]\n\t" + "ldr r3, [%[a], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #120]\n\t" + "ldr r6, [%[b], #124]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #120]\n\t" + "str r4, [%[a], #124]\n\t" + "sbc %[c], %[c], %[c]\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6" + ); + + return c; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_2048_add_64(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r7, #0\n\t" + "mvn r7, r7\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "adds r4, r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[b], #48]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #52]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[b], #56]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #60]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[b], #64]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #68]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[b], #72]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #76]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[b], #80]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #84]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[b], #88]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #92]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[b], #96]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #100]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[b], #104]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #108]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[b], #112]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #116]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[b], #120]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #124]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #124]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c], %[c]\n\t" + "add %[a], %[a], #0x80\n\t" + "add %[b], %[b], #0x80\n\t" + "add %[r], %[r], #0x80\n\t" + "adds %[c], %[c], r7\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[b], #48]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #52]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[b], #56]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #60]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[b], #64]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #68]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[b], #72]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #76]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[b], #80]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #84]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[b], #88]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #92]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[b], #96]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #100]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[b], #104]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #108]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[b], #112]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #116]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[b], #120]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #124]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #124]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r7" + ); + + return c; +} + +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_2048_mask_32(sp_digit* r, sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<32; i++) + r[i] = a[i] & m; +#else + int i; + + for (i = 0; i < 32; i += 8) { + r[i+0] = a[i+0] & m; + r[i+1] = a[i+1] & m; + r[i+2] = a[i+2] & m; + r[i+3] = a[i+3] & m; + r[i+4] = a[i+4] & m; + r[i+5] = a[i+5] & m; + r[i+6] = a[i+6] & m; + r[i+7] = a[i+7] & m; + } +#endif +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_2048_mul_64(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[64]; + sp_digit a1[32]; + sp_digit b1[32]; + sp_digit z2[64]; + sp_digit u, ca, cb; + + ca = sp_2048_add_32(a1, a, &a[32]); + cb = sp_2048_add_32(b1, b, &b[32]); + u = ca & cb; + sp_2048_mul_32(z1, a1, b1); + sp_2048_mul_32(z2, &a[32], &b[32]); + sp_2048_mul_32(z0, a, b); + sp_2048_mask_32(r + 64, a1, 0 - cb); + sp_2048_mask_32(b1, b1, 0 - ca); + u += sp_2048_add_32(r + 64, r + 64, b1); + u += sp_2048_sub_in_place_64(z1, z2); + u += sp_2048_sub_in_place_64(z1, z0); + u += sp_2048_add_64(r + 32, r + 32, z1); + r[96] = u; + XMEMSET(r + 96 + 1, 0, sizeof(sp_digit) * (32 - 1)); + sp_2048_add_64(r + 64, r + 64, z2); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_2048_sqr_64(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z2[64]; + sp_digit z1[64]; + sp_digit a1[32]; + sp_digit u; + + u = sp_2048_add_32(a1, a, &a[32]); + sp_2048_sqr_32(z1, a1); + sp_2048_sqr_32(z2, &a[32]); + sp_2048_sqr_32(z0, a); + sp_2048_mask_32(r + 64, a1, 0 - u); + u += sp_2048_add_32(r + 64, r + 64, r + 64); + u += sp_2048_sub_in_place_64(z1, z2); + u += sp_2048_sub_in_place_64(z1, z0); + u += sp_2048_add_64(r + 32, r + 32, z1); + r[96] = u; + XMEMSET(r + 96 + 1, 0, sizeof(sp_digit) * (32 - 1)); + sp_2048_add_64(r + 64, r + 64, z2); +} + +#endif /* !WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_2048_add_64(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r6, %[a]\n\t" + "mov r7, #0\n\t" + "mov r4, #1\n\t" + "lsl r4, r4, #8\n\t" + "sub r7, r7, #1\n\t" + "add r6, r6, r4\n\t" + "\n1:\n\t" + "adds %[c], %[c], r7\n\t" + "ldr r4, [%[a]]\n\t" + "ldr r5, [%[b]]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r]]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c], %[c]\n\t" + "add %[a], %[a], #4\n\t" + "add %[b], %[b], #4\n\t" + "add %[r], %[r], #4\n\t" + "cmp %[a], r6\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r7" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into a. (a -= b) + * + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_2048_sub_in_place_64(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + __asm__ __volatile__ ( + "mov r7, %[a]\n\t" + "mov r5, #1\n\t" + "lsl r5, r5, #8\n\t" + "add r7, r7, r5\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "subs r5, r5, %[c]\n\t" + "ldr r3, [%[a]]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b]]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a]]\n\t" + "str r4, [%[a], #4]\n\t" + "sbc %[c], %[c], %[c]\n\t" + "add %[a], %[a], #8\n\t" + "add %[b], %[b], #8\n\t" + "cmp %[a], r7\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6", "r7" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_2048_mul_64(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit tmp[64 * 2]; + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r8, r3\n\t" + "mov r11, %[r]\n\t" + "mov r9, %[a]\n\t" + "mov r10, %[b]\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, r6, r9\n\t" + "mov r12, r6\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r5, #0\n\t" + "mov r6, #252\n\t" + "mov %[a], r8\n\t" + "subs %[a], %[a], r6\n\t" + "sbc r6, r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], %[a], r6\n\t" + "mov %[b], r8\n\t" + "sub %[b], %[b], %[a]\n\t" + "add %[a], %[a], r9\n\t" + "add %[b], %[b], r10\n\t" + "\n2:\n\t" + /* Multiply Start */ + "ldr r6, [%[a]]\n\t" + "ldr r7, [%[b]]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* Multiply Done */ + "add %[a], %[a], #4\n\t" + "sub %[b], %[b], #4\n\t" + "cmp %[a], r12\n\t" + "beq 3f\n\t" + "mov r6, r8\n\t" + "add r6, r6, r9\n\t" + "cmp %[a], r6\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r11\n\t" + "mov r7, r8\n\t" + "str r3, [%[r], r7]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "add r7, r7, #4\n\t" + "mov r8, r7\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, r6, #248\n\t" + "cmp r7, r6\n\t" + "ble 1b\n\t" + "str r3, [%[r], r7]\n\t" + "mov %[a], r9\n\t" + "mov %[b], r10\n\t" + : + : [r] "r" (tmp), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_2048_sqr_64(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r5, #0\n\t" + "mov r8, r3\n\t" + "mov r11, %[r]\n\t" + "mov r6, #2\n\t" + "lsl r6, r6, #8\n\t" + "neg r6, r6\n\t" + "add sp, sp, r6\n\t" + "mov r10, sp\n\t" + "mov r9, %[a]\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r6, #252\n\t" + "mov %[a], r8\n\t" + "subs %[a], %[a], r6\n\t" + "sbc r6, r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], %[a], r6\n\t" + "mov r2, r8\n\t" + "sub r2, r2, %[a]\n\t" + "add %[a], %[a], r9\n\t" + "add r2, r2, r9\n\t" + "\n2:\n\t" + "cmp r2, %[a]\n\t" + "beq 4f\n\t" + /* Multiply * 2: Start */ + "ldr r6, [%[a]]\n\t" + "ldr r7, [r2]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* Multiply * 2: Done */ + "bal 5f\n\t" + "\n4:\n\t" + /* Square: Start */ + "ldr r6, [%[a]]\n\t" + "umull r6, r7, r6, r6\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* Square: Done */ + "\n5:\n\t" + "add %[a], %[a], #4\n\t" + "sub r2, r2, #4\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, r6, r9\n\t" + "cmp %[a], r6\n\t" + "beq 3f\n\t" + "cmp %[a], r2\n\t" + "bgt 3f\n\t" + "mov r7, r8\n\t" + "add r7, r7, r9\n\t" + "cmp %[a], r7\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r10\n\t" + "mov r7, r8\n\t" + "str r3, [%[r], r7]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "add r7, r7, #4\n\t" + "mov r8, r7\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, r6, #248\n\t" + "cmp r7, r6\n\t" + "ble 1b\n\t" + "mov %[a], r9\n\t" + "str r3, [%[r], r7]\n\t" + "mov %[r], r11\n\t" + "mov %[a], r10\n\t" + "mov r3, #1\n\t" + "lsl r3, r3, #8\n\t" + "add r3, r3, #252\n\t" + "\n4:\n\t" + "ldr r6, [%[a], r3]\n\t" + "str r6, [%[r], r3]\n\t" + "subs r3, r3, #4\n\t" + "bge 4b\n\t" + "mov r6, #2\n\t" + "lsl r6, r6, #8\n\t" + "add sp, sp, r6\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11" + ); +} + +#endif /* WOLFSSL_SP_SMALL */ +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +#ifdef WOLFSSL_SP_SMALL +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_2048_mask_32(sp_digit* r, sp_digit* a, sp_digit m) +{ + int i; + + for (i=0; i<32; i++) + r[i] = a[i] & m; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_2048_add_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r6, %[a]\n\t" + "mov r7, #0\n\t" + "add r6, r6, #128\n\t" + "sub r7, r7, #1\n\t" + "\n1:\n\t" + "adds %[c], %[c], r7\n\t" + "ldr r4, [%[a]]\n\t" + "ldr r5, [%[b]]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r]]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c], %[c]\n\t" + "add %[a], %[a], #4\n\t" + "add %[b], %[b], #4\n\t" + "add %[r], %[r], #4\n\t" + "cmp %[a], r6\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r7" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into a. (a -= b) + * + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_2048_sub_in_place_32(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + __asm__ __volatile__ ( + "mov r7, %[a]\n\t" + "add r7, r7, #128\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "subs r5, r5, %[c]\n\t" + "ldr r3, [%[a]]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b]]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a]]\n\t" + "str r4, [%[a], #4]\n\t" + "sbc %[c], %[c], %[c]\n\t" + "add %[a], %[a], #8\n\t" + "add %[b], %[b], #8\n\t" + "cmp %[a], r7\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6", "r7" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_2048_mul_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit tmp[32 * 2]; + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r8, r3\n\t" + "mov r11, %[r]\n\t" + "mov r9, %[a]\n\t" + "mov r10, %[b]\n\t" + "mov r6, #128\n\t" + "add r6, r6, r9\n\t" + "mov r12, r6\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r5, #0\n\t" + "mov r6, #124\n\t" + "mov %[a], r8\n\t" + "subs %[a], %[a], r6\n\t" + "sbc r6, r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], %[a], r6\n\t" + "mov %[b], r8\n\t" + "sub %[b], %[b], %[a]\n\t" + "add %[a], %[a], r9\n\t" + "add %[b], %[b], r10\n\t" + "\n2:\n\t" + /* Multiply Start */ + "ldr r6, [%[a]]\n\t" + "ldr r7, [%[b]]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* Multiply Done */ + "add %[a], %[a], #4\n\t" + "sub %[b], %[b], #4\n\t" + "cmp %[a], r12\n\t" + "beq 3f\n\t" + "mov r6, r8\n\t" + "add r6, r6, r9\n\t" + "cmp %[a], r6\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r11\n\t" + "mov r7, r8\n\t" + "str r3, [%[r], r7]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "add r7, r7, #4\n\t" + "mov r8, r7\n\t" + "mov r6, #248\n\t" + "cmp r7, r6\n\t" + "ble 1b\n\t" + "str r3, [%[r], r7]\n\t" + "mov %[a], r9\n\t" + "mov %[b], r10\n\t" + : + : [r] "r" (tmp), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_2048_sqr_32(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r5, #0\n\t" + "mov r8, r3\n\t" + "mov r11, %[r]\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "neg r6, r6\n\t" + "add sp, sp, r6\n\t" + "mov r10, sp\n\t" + "mov r9, %[a]\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r6, #124\n\t" + "mov %[a], r8\n\t" + "subs %[a], %[a], r6\n\t" + "sbc r6, r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], %[a], r6\n\t" + "mov r2, r8\n\t" + "sub r2, r2, %[a]\n\t" + "add %[a], %[a], r9\n\t" + "add r2, r2, r9\n\t" + "\n2:\n\t" + "cmp r2, %[a]\n\t" + "beq 4f\n\t" + /* Multiply * 2: Start */ + "ldr r6, [%[a]]\n\t" + "ldr r7, [r2]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* Multiply * 2: Done */ + "bal 5f\n\t" + "\n4:\n\t" + /* Square: Start */ + "ldr r6, [%[a]]\n\t" + "umull r6, r7, r6, r6\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* Square: Done */ + "\n5:\n\t" + "add %[a], %[a], #4\n\t" + "sub r2, r2, #4\n\t" + "mov r6, #128\n\t" + "add r6, r6, r9\n\t" + "cmp %[a], r6\n\t" + "beq 3f\n\t" + "cmp %[a], r2\n\t" + "bgt 3f\n\t" + "mov r7, r8\n\t" + "add r7, r7, r9\n\t" + "cmp %[a], r7\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r10\n\t" + "mov r7, r8\n\t" + "str r3, [%[r], r7]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "add r7, r7, #4\n\t" + "mov r8, r7\n\t" + "mov r6, #248\n\t" + "cmp r7, r6\n\t" + "ble 1b\n\t" + "mov %[a], r9\n\t" + "str r3, [%[r], r7]\n\t" + "mov %[r], r11\n\t" + "mov %[a], r10\n\t" + "mov r3, #252\n\t" + "\n4:\n\t" + "ldr r6, [%[a], r3]\n\t" + "str r6, [%[r], r3]\n\t" + "subs r3, r3, #4\n\t" + "bge 4b\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add sp, sp, r6\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11" + ); +} + +#endif /* WOLFSSL_SP_SMALL */ +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +/* Caclulate the bottom digit of -1/a mod 2^n. + * + * a A single precision number. + * rho Bottom word of inverse. + */ +static void sp_2048_mont_setup(sp_digit* a, sp_digit* rho) +{ + sp_digit x, b; + + b = a[0]; + x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ + x *= 2 - b * x; /* here x*a==1 mod 2**8 */ + x *= 2 - b * x; /* here x*a==1 mod 2**16 */ + x *= 2 - b * x; /* here x*a==1 mod 2**32 */ + + /* rho = -1/m mod b */ + *rho = -x; +} + +/* Mul a by digit b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision digit. + */ +SP_NOINLINE static void sp_2048_mul_d_64(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ + __asm__ __volatile__ ( + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, r6, %[a]\n\t" + "mov r8, %[r]\n\t" + "mov r9, r6\n\t" + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r5, #0\n\t" + /* A[] * B */ + "ldr r6, [%[a]]\n\t" + "umull r6, r7, r6, %[b]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[] * B - Done */ + "mov %[r], r8\n\t" + "str r3, [%[r]]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "add %[r], %[r], #4\n\t" + "add %[a], %[a], #4\n\t" + "mov r8, %[r]\n\t" + "cmp %[a], r9\n\t" + "blt 1b\n\t" + "str r3, [%[r]]\n\t" + : [r] "+r" (r), [a] "+r" (a) + : [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9" + ); +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +/* r = 2^n mod m where n is the number of bits to reduce by. + * Given m must be 2048 bits, just need to subtract. + * + * r A single precision number. + * m A signle precision number. + */ +static void sp_2048_mont_norm_32(sp_digit* r, sp_digit* m) +{ + XMEMSET(r, 0, sizeof(sp_digit) * 32); + + /* r = 2^n mod m */ + sp_2048_sub_in_place_32(r, m); +} + +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not copying. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +SP_NOINLINE static sp_digit sp_2048_cond_sub_32(sp_digit* r, sp_digit* a, + sp_digit* b, sp_digit m) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r5, #128\n\t" + "mov r8, r5\n\t" + "mov r7, #0\n\t" + "\n1:\n\t" + "ldr r6, [%[b], r7]\n\t" + "and r6, r6, %[m]\n\t" + "mov r5, #0\n\t" + "subs r5, r5, %[c]\n\t" + "ldr r5, [%[a], r7]\n\t" + "sbcs r5, r5, r6\n\t" + "sbcs %[c], %[c], %[c]\n\t" + "str r5, [%[r], r7]\n\t" + "add r7, r7, #4\n\t" + "cmp r7, r8\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r5", "r6", "r7", "r8" + ); + + return c; +} + +/* Reduce the number back to 2048 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +SP_NOINLINE static void sp_2048_mont_reduce_32(sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "mov r8, %[mp]\n\t" + "mov r12, %[ca]\n\t" + "mov r14, %[m]\n\t" + "mov r9, %[a]\n\t" + "mov r4, #0\n\t" + /* i = 0 */ + "mov r11, r4\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "mov %[ca], #0\n\t" + /* mu = a[i] * mp */ + "mov %[mp], r8\n\t" + "ldr %[a], [%[a]]\n\t" + "mul %[mp], %[mp], %[a]\n\t" + "mov %[m], r14\n\t" + "mov r10, r9\n\t" + "\n2:\n\t" + /* a[i+j] += m[j] * mu */ + "mov %[a], r10\n\t" + "ldr %[a], [%[a]]\n\t" + "mov %[ca], #0\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + /* Multiply m[j] and mu - Start */ + "ldr r7, [%[m]]\n\t" + "umull r6, r7, %[mp], r7\n\t" + "adds %[a], %[a], r6\n\t" + "adcs r5, r5, r7\n\t" + /* Multiply m[j] and mu - Done */ + "adds r4, r4, %[a]\n\t" + "adc r5, r5, %[ca]\n\t" + "mov %[a], r10\n\t" + "str r4, [%[a]]\n\t" + "mov r6, #4\n\t" + "add %[m], %[m], #4\n\t" + "add r10, r10, r6\n\t" + "mov r4, #124\n\t" + "add r4, r4, r9\n\t" + "cmp r10, r4\n\t" + "blt 2b\n\t" + /* a[i+31] += m[31] * mu */ + "mov %[ca], #0\n\t" + "mov r4, r12\n\t" + "mov %[a], #0\n\t" + /* Multiply m[31] and mu - Start */ + "ldr r7, [%[m]]\n\t" + "umull r6, r7, %[mp], r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc %[a], %[a], %[ca]\n\t" + /* Multiply m[31] and mu - Done */ + "mov %[ca], %[a]\n\t" + "mov %[a], r10\n\t" + "ldr r7, [%[a], #4]\n\t" + "ldr %[a], [%[a]]\n\t" + "mov r6, #0\n\t" + "adds r5, r5, %[a]\n\t" + "adcs r7, r7, r4\n\t" + "adc %[ca], %[ca], r6\n\t" + "mov %[a], r10\n\t" + "str r5, [%[a]]\n\t" + "str r7, [%[a], #4]\n\t" + /* i += 1 */ + "mov r6, #4\n\t" + "add r9, r9, r6\n\t" + "add r11, r11, r6\n\t" + "mov r12, %[ca]\n\t" + "mov %[a], r9\n\t" + "mov r4, #128\n\t" + "cmp r11, r4\n\t" + "blt 1b\n\t" + "mov %[m], r14\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14" + ); + + sp_2048_cond_sub_32(a - 32, a, m, (sp_digit)0 - ca); +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_2048_mont_mul_32(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_2048_mul_32(r, a, b); + sp_2048_mont_reduce_32(r, m, mp); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_2048_mont_sqr_32(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_2048_sqr_32(r, a); + sp_2048_mont_reduce_32(r, m, mp); +} + +/* Mul a by digit b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision digit. + */ +SP_NOINLINE static void sp_2048_mul_d_32(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ + __asm__ __volatile__ ( + "mov r6, #128\n\t" + "add r6, r6, %[a]\n\t" + "mov r8, %[r]\n\t" + "mov r9, r6\n\t" + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r5, #0\n\t" + /* A[] * B */ + "ldr r6, [%[a]]\n\t" + "umull r6, r7, r6, %[b]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[] * B - Done */ + "mov %[r], r8\n\t" + "str r3, [%[r]]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "add %[r], %[r], #4\n\t" + "add %[a], %[a], #4\n\t" + "mov r8, %[r]\n\t" + "cmp %[a], r9\n\t" + "blt 1b\n\t" + "str r3, [%[r]]\n\t" + : [r] "+r" (r), [a] "+r" (a) + : [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9" + ); +} + +/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) + * + * d1 The high order half of the number to divide. + * d0 The low order half of the number to divide. + * div The dividend. + * returns the result of the division. + * + * Note that this is an approximate div. It may give an answer 1 larger. + */ +SP_NOINLINE static sp_digit div_2048_word_32(sp_digit d1, sp_digit d0, + sp_digit div) +{ + sp_digit r = 0; + + __asm__ __volatile__ ( + "lsr r6, %[div], #16\n\t" + "add r6, r6, #1\n\t" + "udiv r4, %[d1], r6\n\t" + "lsl r7, r4, #16\n\t" + "umull r4, r5, %[div], r7\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "udiv r5, %[d1], r6\n\t" + "lsl r4, r5, #16\n\t" + "add r7, r7, r4\n\t" + "umull r4, r5, %[div], r4\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "lsl r4, %[d1], #16\n\t" + "orr r4, r4, %[d0], lsr 16\n\t" + "udiv r4, r4, r6\n\t" + "add r7, r7, r4\n\t" + "umull r4, r5, %[div], r4\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "lsl r4, %[d1], #16\n\t" + "orr r4, r4, %[d0], lsr 16\n\t" + "udiv r4, r4, r6\n\t" + "add r7, r7, r4\n\t" + "umull r4, r5, %[div], r4\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "udiv r4, %[d0], %[div]\n\t" + "add r7, r7, r4\n\t" + "mov %[r], r7\n\t" + : [r] "+r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "r4", "r5", "r6", "r7" + ); + return r; +} + +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +SP_NOINLINE static int32_t sp_2048_cmp_32(sp_digit* a, sp_digit* b) +{ + sp_digit r = 0; + + + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mvn r3, r3\n\t" + "mov r6, #124\n\t" + "\n1:\n\t" + "ldr r7, [%[a], r6]\n\t" + "ldr r5, [%[b], r6]\n\t" + "and r7, r7, r3\n\t" + "and r5, r5, r3\n\t" + "mov r4, r7\n\t" + "subs r7, r7, r5\n\t" + "sbc r7, r7, r7\n\t" + "add %[r], %[r], r7\n\t" + "mvn r7, r7\n\t" + "and r3, r3, r7\n\t" + "subs r5, r5, r4\n\t" + "sbc r7, r7, r7\n\t" + "sub %[r], %[r], r7\n\t" + "mvn r7, r7\n\t" + "and r3, r3, r7\n\t" + "sub r6, r6, #4\n\t" + "cmp r6, #0\n\t" + "bge 1b\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "r3", "r4", "r5", "r6", "r7" + ); + + return r; +} + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_2048_div_32(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[64], t2[33]; + sp_digit div, r1; + int i; + + (void)m; + + div = d[31]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 32); + for (i=31; i>=0; i--) { + r1 = div_2048_word_32(t1[32 + i], t1[32 + i - 1], div); + + sp_2048_mul_d_32(t2, d, r1); + t1[32 + i] += sp_2048_sub_in_place_32(&t1[i], t2); + t1[32 + i] -= t2[32]; + sp_2048_mask_32(t2, d, t1[32 + i]); + t1[32 + i] += sp_2048_add_32(&t1[i], &t1[i], t2); + sp_2048_mask_32(t2, d, t1[32 + i]); + t1[32 + i] += sp_2048_add_32(&t1[i], &t1[i], t2); + } + + r1 = sp_2048_cmp_32(t1, d) >= 0; + sp_2048_cond_sub_32(r, t1, d, (sp_digit)0 - r1); + + return MP_OKAY; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_2048_mod_32(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_2048_div_32(a, m, NULL, r); +} + +#ifdef WOLFSSL_SP_SMALL +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_2048_mod_exp_32(sp_digit* r, sp_digit* a, sp_digit* e, + int bits, sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[16][64]; +#else + sp_digit* t[16]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 64, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<16; i++) + t[i] = td + i * 64; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_32(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 32); + if (reduceA) { + err = sp_2048_mod_32(t[1] + 32, a, m); + if (err == MP_OKAY) + err = sp_2048_mod_32(t[1], t[1], m); + } + else { + XMEMCPY(t[1] + 32, a, sizeof(sp_digit) * 32); + err = sp_2048_mod_32(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_2048_mont_sqr_32(t[ 2], t[ 1], m, mp); + sp_2048_mont_mul_32(t[ 3], t[ 2], t[ 1], m, mp); + sp_2048_mont_sqr_32(t[ 4], t[ 2], m, mp); + sp_2048_mont_mul_32(t[ 5], t[ 3], t[ 2], m, mp); + sp_2048_mont_sqr_32(t[ 6], t[ 3], m, mp); + sp_2048_mont_mul_32(t[ 7], t[ 4], t[ 3], m, mp); + sp_2048_mont_sqr_32(t[ 8], t[ 4], m, mp); + sp_2048_mont_mul_32(t[ 9], t[ 5], t[ 4], m, mp); + sp_2048_mont_sqr_32(t[10], t[ 5], m, mp); + sp_2048_mont_mul_32(t[11], t[ 6], t[ 5], m, mp); + sp_2048_mont_sqr_32(t[12], t[ 6], m, mp); + sp_2048_mont_mul_32(t[13], t[ 7], t[ 6], m, mp); + sp_2048_mont_sqr_32(t[14], t[ 7], m, mp); + sp_2048_mont_mul_32(t[15], t[ 8], t[ 7], m, mp); + + i = (bits - 1) / 32; + n = e[i--]; + y = n >> 28; + n <<= 4; + c = 28; + XMEMCPY(r, t[y], sizeof(sp_digit) * 32); + for (; i>=0 || c>=4; ) { + if (c == 0) { + n = e[i--]; + y = n >> 28; + n <<= 4; + c = 28; + } + else if (c < 4) { + y = n >> 28; + n = e[i--]; + c = 4 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 28) & 0xf; + n <<= 4; + c -= 4; + } + + sp_2048_mont_sqr_32(r, r, m, mp); + sp_2048_mont_sqr_32(r, r, m, mp); + sp_2048_mont_sqr_32(r, r, m, mp); + sp_2048_mont_sqr_32(r, r, m, mp); + + sp_2048_mont_mul_32(r, r, t[y], m, mp); + } + y = e[0] & ((1 << c) - 1); + for (; c > 0; c--) + sp_2048_mont_sqr_32(r, r, m, mp); + sp_2048_mont_mul_32(r, r, t[y], m, mp); + + XMEMSET(&r[32], 0, sizeof(sp_digit) * 32); + sp_2048_mont_reduce_32(r, m, mp); + + mask = 0 - (sp_2048_cmp_32(r, m) >= 0); + sp_2048_cond_sub_32(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#else +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_2048_mod_exp_32(sp_digit* r, sp_digit* a, sp_digit* e, + int bits, sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][64]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 64, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<32; i++) + t[i] = td + i * 64; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_32(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 32); + if (reduceA) { + err = sp_2048_mod_32(t[1] + 32, a, m); + if (err == MP_OKAY) + err = sp_2048_mod_32(t[1], t[1], m); + } + else { + XMEMCPY(t[1] + 32, a, sizeof(sp_digit) * 32); + err = sp_2048_mod_32(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_2048_mont_sqr_32(t[ 2], t[ 1], m, mp); + sp_2048_mont_mul_32(t[ 3], t[ 2], t[ 1], m, mp); + sp_2048_mont_sqr_32(t[ 4], t[ 2], m, mp); + sp_2048_mont_mul_32(t[ 5], t[ 3], t[ 2], m, mp); + sp_2048_mont_sqr_32(t[ 6], t[ 3], m, mp); + sp_2048_mont_mul_32(t[ 7], t[ 4], t[ 3], m, mp); + sp_2048_mont_sqr_32(t[ 8], t[ 4], m, mp); + sp_2048_mont_mul_32(t[ 9], t[ 5], t[ 4], m, mp); + sp_2048_mont_sqr_32(t[10], t[ 5], m, mp); + sp_2048_mont_mul_32(t[11], t[ 6], t[ 5], m, mp); + sp_2048_mont_sqr_32(t[12], t[ 6], m, mp); + sp_2048_mont_mul_32(t[13], t[ 7], t[ 6], m, mp); + sp_2048_mont_sqr_32(t[14], t[ 7], m, mp); + sp_2048_mont_mul_32(t[15], t[ 8], t[ 7], m, mp); + sp_2048_mont_sqr_32(t[16], t[ 8], m, mp); + sp_2048_mont_mul_32(t[17], t[ 9], t[ 8], m, mp); + sp_2048_mont_sqr_32(t[18], t[ 9], m, mp); + sp_2048_mont_mul_32(t[19], t[10], t[ 9], m, mp); + sp_2048_mont_sqr_32(t[20], t[10], m, mp); + sp_2048_mont_mul_32(t[21], t[11], t[10], m, mp); + sp_2048_mont_sqr_32(t[22], t[11], m, mp); + sp_2048_mont_mul_32(t[23], t[12], t[11], m, mp); + sp_2048_mont_sqr_32(t[24], t[12], m, mp); + sp_2048_mont_mul_32(t[25], t[13], t[12], m, mp); + sp_2048_mont_sqr_32(t[26], t[13], m, mp); + sp_2048_mont_mul_32(t[27], t[14], t[13], m, mp); + sp_2048_mont_sqr_32(t[28], t[14], m, mp); + sp_2048_mont_mul_32(t[29], t[15], t[14], m, mp); + sp_2048_mont_sqr_32(t[30], t[15], m, mp); + sp_2048_mont_mul_32(t[31], t[16], t[15], m, mp); + + i = (bits - 1) / 32; + n = e[i--]; + y = n >> 27; + n <<= 5; + c = 27; + XMEMCPY(r, t[y], sizeof(sp_digit) * 32); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 27; + n <<= 5; + c = 27; + } + else if (c < 5) { + y = n >> 27; + n = e[i--]; + c = 5 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 27) & 0x1f; + n <<= 5; + c -= 5; + } + + sp_2048_mont_sqr_32(r, r, m, mp); + sp_2048_mont_sqr_32(r, r, m, mp); + sp_2048_mont_sqr_32(r, r, m, mp); + sp_2048_mont_sqr_32(r, r, m, mp); + sp_2048_mont_sqr_32(r, r, m, mp); + + sp_2048_mont_mul_32(r, r, t[y], m, mp); + } + y = e[0] & ((1 << c) - 1); + for (; c > 0; c--) + sp_2048_mont_sqr_32(r, r, m, mp); + sp_2048_mont_mul_32(r, r, t[y], m, mp); + + XMEMSET(&r[32], 0, sizeof(sp_digit) * 32); + sp_2048_mont_reduce_32(r, m, mp); + + mask = 0 - (sp_2048_cmp_32(r, m) >= 0); + sp_2048_cond_sub_32(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#endif /* WOLFSSL_SP_SMALL */ + +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) +/* r = 2^n mod m where n is the number of bits to reduce by. + * Given m must be 2048 bits, just need to subtract. + * + * r A single precision number. + * m A signle precision number. + */ +static void sp_2048_mont_norm_64(sp_digit* r, sp_digit* m) +{ + XMEMSET(r, 0, sizeof(sp_digit) * 64); + + /* r = 2^n mod m */ + sp_2048_sub_in_place_64(r, m); +} + +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not copying. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +SP_NOINLINE static sp_digit sp_2048_cond_sub_64(sp_digit* r, sp_digit* a, + sp_digit* b, sp_digit m) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r5, #1\n\t" + "lsl r5, r5, #8\n\t" + "mov r8, r5\n\t" + "mov r7, #0\n\t" + "\n1:\n\t" + "ldr r6, [%[b], r7]\n\t" + "and r6, r6, %[m]\n\t" + "mov r5, #0\n\t" + "subs r5, r5, %[c]\n\t" + "ldr r5, [%[a], r7]\n\t" + "sbcs r5, r5, r6\n\t" + "sbcs %[c], %[c], %[c]\n\t" + "str r5, [%[r], r7]\n\t" + "add r7, r7, #4\n\t" + "cmp r7, r8\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r5", "r6", "r7", "r8" + ); + + return c; +} + +/* Reduce the number back to 2048 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +SP_NOINLINE static void sp_2048_mont_reduce_64(sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "mov r8, %[mp]\n\t" + "mov r12, %[ca]\n\t" + "mov r14, %[m]\n\t" + "mov r9, %[a]\n\t" + "mov r4, #0\n\t" + /* i = 0 */ + "mov r11, r4\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "mov %[ca], #0\n\t" + /* mu = a[i] * mp */ + "mov %[mp], r8\n\t" + "ldr %[a], [%[a]]\n\t" + "mul %[mp], %[mp], %[a]\n\t" + "mov %[m], r14\n\t" + "mov r10, r9\n\t" + "\n2:\n\t" + /* a[i+j] += m[j] * mu */ + "mov %[a], r10\n\t" + "ldr %[a], [%[a]]\n\t" + "mov %[ca], #0\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + /* Multiply m[j] and mu - Start */ + "ldr r7, [%[m]]\n\t" + "umull r6, r7, %[mp], r7\n\t" + "adds %[a], %[a], r6\n\t" + "adcs r5, r5, r7\n\t" + /* Multiply m[j] and mu - Done */ + "adds r4, r4, %[a]\n\t" + "adc r5, r5, %[ca]\n\t" + "mov %[a], r10\n\t" + "str r4, [%[a]]\n\t" + "mov r6, #4\n\t" + "add %[m], %[m], #4\n\t" + "add r10, r10, r6\n\t" + "mov r4, #252\n\t" + "add r4, r4, r9\n\t" + "cmp r10, r4\n\t" + "blt 2b\n\t" + /* a[i+63] += m[63] * mu */ + "mov %[ca], #0\n\t" + "mov r4, r12\n\t" + "mov %[a], #0\n\t" + /* Multiply m[63] and mu - Start */ + "ldr r7, [%[m]]\n\t" + "umull r6, r7, %[mp], r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc %[a], %[a], %[ca]\n\t" + /* Multiply m[63] and mu - Done */ + "mov %[ca], %[a]\n\t" + "mov %[a], r10\n\t" + "ldr r7, [%[a], #4]\n\t" + "ldr %[a], [%[a]]\n\t" + "mov r6, #0\n\t" + "adds r5, r5, %[a]\n\t" + "adcs r7, r7, r4\n\t" + "adc %[ca], %[ca], r6\n\t" + "mov %[a], r10\n\t" + "str r5, [%[a]]\n\t" + "str r7, [%[a], #4]\n\t" + /* i += 1 */ + "mov r6, #4\n\t" + "add r9, r9, r6\n\t" + "add r11, r11, r6\n\t" + "mov r12, %[ca]\n\t" + "mov %[a], r9\n\t" + "mov r4, #1\n\t" + "lsl r4, r4, #8\n\t" + "cmp r11, r4\n\t" + "blt 1b\n\t" + "mov %[m], r14\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14" + ); + + sp_2048_cond_sub_64(a - 64, a, m, (sp_digit)0 - ca); +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_2048_mont_mul_64(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_2048_mul_64(r, a, b); + sp_2048_mont_reduce_64(r, m, mp); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_2048_mont_sqr_64(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_2048_sqr_64(r, a); + sp_2048_mont_reduce_64(r, m, mp); +} + +/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) + * + * d1 The high order half of the number to divide. + * d0 The low order half of the number to divide. + * div The dividend. + * returns the result of the division. + * + * Note that this is an approximate div. It may give an answer 1 larger. + */ +SP_NOINLINE static sp_digit div_2048_word_64(sp_digit d1, sp_digit d0, + sp_digit div) +{ + sp_digit r = 0; + + __asm__ __volatile__ ( + "lsr r6, %[div], #16\n\t" + "add r6, r6, #1\n\t" + "udiv r4, %[d1], r6\n\t" + "lsl r7, r4, #16\n\t" + "umull r4, r5, %[div], r7\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "udiv r5, %[d1], r6\n\t" + "lsl r4, r5, #16\n\t" + "add r7, r7, r4\n\t" + "umull r4, r5, %[div], r4\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "lsl r4, %[d1], #16\n\t" + "orr r4, r4, %[d0], lsr 16\n\t" + "udiv r4, r4, r6\n\t" + "add r7, r7, r4\n\t" + "umull r4, r5, %[div], r4\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "lsl r4, %[d1], #16\n\t" + "orr r4, r4, %[d0], lsr 16\n\t" + "udiv r4, r4, r6\n\t" + "add r7, r7, r4\n\t" + "umull r4, r5, %[div], r4\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "udiv r4, %[d0], %[div]\n\t" + "add r7, r7, r4\n\t" + "mov %[r], r7\n\t" + : [r] "+r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "r4", "r5", "r6", "r7" + ); + return r; +} + +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_2048_mask_64(sp_digit* r, sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<64; i++) + r[i] = a[i] & m; +#else + int i; + + for (i = 0; i < 64; i += 8) { + r[i+0] = a[i+0] & m; + r[i+1] = a[i+1] & m; + r[i+2] = a[i+2] & m; + r[i+3] = a[i+3] & m; + r[i+4] = a[i+4] & m; + r[i+5] = a[i+5] & m; + r[i+6] = a[i+6] & m; + r[i+7] = a[i+7] & m; + } +#endif +} + +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +SP_NOINLINE static int32_t sp_2048_cmp_64(sp_digit* a, sp_digit* b) +{ + sp_digit r = 0; + + + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mvn r3, r3\n\t" + "mov r6, #252\n\t" + "\n1:\n\t" + "ldr r7, [%[a], r6]\n\t" + "ldr r5, [%[b], r6]\n\t" + "and r7, r7, r3\n\t" + "and r5, r5, r3\n\t" + "mov r4, r7\n\t" + "subs r7, r7, r5\n\t" + "sbc r7, r7, r7\n\t" + "add %[r], %[r], r7\n\t" + "mvn r7, r7\n\t" + "and r3, r3, r7\n\t" + "subs r5, r5, r4\n\t" + "sbc r7, r7, r7\n\t" + "sub %[r], %[r], r7\n\t" + "mvn r7, r7\n\t" + "and r3, r3, r7\n\t" + "sub r6, r6, #4\n\t" + "cmp r6, #0\n\t" + "bge 1b\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "r3", "r4", "r5", "r6", "r7" + ); + + return r; +} + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_2048_div_64(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[128], t2[65]; + sp_digit div, r1; + int i; + + (void)m; + + div = d[63]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 64); + for (i=63; i>=0; i--) { + r1 = div_2048_word_64(t1[64 + i], t1[64 + i - 1], div); + + sp_2048_mul_d_64(t2, d, r1); + t1[64 + i] += sp_2048_sub_in_place_64(&t1[i], t2); + t1[64 + i] -= t2[64]; + sp_2048_mask_64(t2, d, t1[64 + i]); + t1[64 + i] += sp_2048_add_64(&t1[i], &t1[i], t2); + sp_2048_mask_64(t2, d, t1[64 + i]); + t1[64 + i] += sp_2048_add_64(&t1[i], &t1[i], t2); + } + + r1 = sp_2048_cmp_64(t1, d) >= 0; + sp_2048_cond_sub_64(r, t1, d, (sp_digit)0 - r1); + + return MP_OKAY; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_2048_mod_64(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_2048_div_64(a, m, NULL, r); +} + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_2048_div_64_cond(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[128], t2[65]; + sp_digit div, r1; + int i; + + (void)m; + + div = d[63]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 64); + for (i=63; i>=0; i--) { + r1 = div_2048_word_64(t1[64 + i], t1[64 + i - 1], div); + + sp_2048_mul_d_64(t2, d, r1); + t1[64 + i] += sp_2048_sub_in_place_64(&t1[i], t2); + t1[64 + i] -= t2[64]; + if (t1[64 + i] != 0) { + t1[64 + i] += sp_2048_add_64(&t1[i], &t1[i], d); + if (t1[64 + i] != 0) + t1[64 + i] += sp_2048_add_64(&t1[i], &t1[i], d); + } + } + + r1 = sp_2048_cmp_64(t1, d) >= 0; + sp_2048_cond_sub_64(r, t1, d, (sp_digit)0 - r1); + + return MP_OKAY; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_2048_mod_64_cond(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_2048_div_64_cond(a, m, NULL, r); +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \ + defined(WOLFSSL_HAVE_SP_DH) +#ifdef WOLFSSL_SP_SMALL +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_2048_mod_exp_64(sp_digit* r, sp_digit* a, sp_digit* e, + int bits, sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[16][128]; +#else + sp_digit* t[16]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 128, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<16; i++) + t[i] = td + i * 128; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_64(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 64); + if (reduceA) { + err = sp_2048_mod_64(t[1] + 64, a, m); + if (err == MP_OKAY) + err = sp_2048_mod_64(t[1], t[1], m); + } + else { + XMEMCPY(t[1] + 64, a, sizeof(sp_digit) * 64); + err = sp_2048_mod_64(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_2048_mont_sqr_64(t[ 2], t[ 1], m, mp); + sp_2048_mont_mul_64(t[ 3], t[ 2], t[ 1], m, mp); + sp_2048_mont_sqr_64(t[ 4], t[ 2], m, mp); + sp_2048_mont_mul_64(t[ 5], t[ 3], t[ 2], m, mp); + sp_2048_mont_sqr_64(t[ 6], t[ 3], m, mp); + sp_2048_mont_mul_64(t[ 7], t[ 4], t[ 3], m, mp); + sp_2048_mont_sqr_64(t[ 8], t[ 4], m, mp); + sp_2048_mont_mul_64(t[ 9], t[ 5], t[ 4], m, mp); + sp_2048_mont_sqr_64(t[10], t[ 5], m, mp); + sp_2048_mont_mul_64(t[11], t[ 6], t[ 5], m, mp); + sp_2048_mont_sqr_64(t[12], t[ 6], m, mp); + sp_2048_mont_mul_64(t[13], t[ 7], t[ 6], m, mp); + sp_2048_mont_sqr_64(t[14], t[ 7], m, mp); + sp_2048_mont_mul_64(t[15], t[ 8], t[ 7], m, mp); + + i = (bits - 1) / 32; + n = e[i--]; + y = n >> 28; + n <<= 4; + c = 28; + XMEMCPY(r, t[y], sizeof(sp_digit) * 64); + for (; i>=0 || c>=4; ) { + if (c == 0) { + n = e[i--]; + y = n >> 28; + n <<= 4; + c = 28; + } + else if (c < 4) { + y = n >> 28; + n = e[i--]; + c = 4 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 28) & 0xf; + n <<= 4; + c -= 4; + } + + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + + sp_2048_mont_mul_64(r, r, t[y], m, mp); + } + y = e[0] & ((1 << c) - 1); + for (; c > 0; c--) + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_mul_64(r, r, t[y], m, mp); + + XMEMSET(&r[64], 0, sizeof(sp_digit) * 64); + sp_2048_mont_reduce_64(r, m, mp); + + mask = 0 - (sp_2048_cmp_64(r, m) >= 0); + sp_2048_cond_sub_64(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#else +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_2048_mod_exp_64(sp_digit* r, sp_digit* a, sp_digit* e, + int bits, sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][128]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 128, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<32; i++) + t[i] = td + i * 128; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_64(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 64); + if (reduceA) { + err = sp_2048_mod_64(t[1] + 64, a, m); + if (err == MP_OKAY) + err = sp_2048_mod_64(t[1], t[1], m); + } + else { + XMEMCPY(t[1] + 64, a, sizeof(sp_digit) * 64); + err = sp_2048_mod_64(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_2048_mont_sqr_64(t[ 2], t[ 1], m, mp); + sp_2048_mont_mul_64(t[ 3], t[ 2], t[ 1], m, mp); + sp_2048_mont_sqr_64(t[ 4], t[ 2], m, mp); + sp_2048_mont_mul_64(t[ 5], t[ 3], t[ 2], m, mp); + sp_2048_mont_sqr_64(t[ 6], t[ 3], m, mp); + sp_2048_mont_mul_64(t[ 7], t[ 4], t[ 3], m, mp); + sp_2048_mont_sqr_64(t[ 8], t[ 4], m, mp); + sp_2048_mont_mul_64(t[ 9], t[ 5], t[ 4], m, mp); + sp_2048_mont_sqr_64(t[10], t[ 5], m, mp); + sp_2048_mont_mul_64(t[11], t[ 6], t[ 5], m, mp); + sp_2048_mont_sqr_64(t[12], t[ 6], m, mp); + sp_2048_mont_mul_64(t[13], t[ 7], t[ 6], m, mp); + sp_2048_mont_sqr_64(t[14], t[ 7], m, mp); + sp_2048_mont_mul_64(t[15], t[ 8], t[ 7], m, mp); + sp_2048_mont_sqr_64(t[16], t[ 8], m, mp); + sp_2048_mont_mul_64(t[17], t[ 9], t[ 8], m, mp); + sp_2048_mont_sqr_64(t[18], t[ 9], m, mp); + sp_2048_mont_mul_64(t[19], t[10], t[ 9], m, mp); + sp_2048_mont_sqr_64(t[20], t[10], m, mp); + sp_2048_mont_mul_64(t[21], t[11], t[10], m, mp); + sp_2048_mont_sqr_64(t[22], t[11], m, mp); + sp_2048_mont_mul_64(t[23], t[12], t[11], m, mp); + sp_2048_mont_sqr_64(t[24], t[12], m, mp); + sp_2048_mont_mul_64(t[25], t[13], t[12], m, mp); + sp_2048_mont_sqr_64(t[26], t[13], m, mp); + sp_2048_mont_mul_64(t[27], t[14], t[13], m, mp); + sp_2048_mont_sqr_64(t[28], t[14], m, mp); + sp_2048_mont_mul_64(t[29], t[15], t[14], m, mp); + sp_2048_mont_sqr_64(t[30], t[15], m, mp); + sp_2048_mont_mul_64(t[31], t[16], t[15], m, mp); + + i = (bits - 1) / 32; + n = e[i--]; + y = n >> 27; + n <<= 5; + c = 27; + XMEMCPY(r, t[y], sizeof(sp_digit) * 64); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 27; + n <<= 5; + c = 27; + } + else if (c < 5) { + y = n >> 27; + n = e[i--]; + c = 5 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 27) & 0x1f; + n <<= 5; + c -= 5; + } + + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_sqr_64(r, r, m, mp); + + sp_2048_mont_mul_64(r, r, t[y], m, mp); + } + y = e[0] & ((1 << c) - 1); + for (; c > 0; c--) + sp_2048_mont_sqr_64(r, r, m, mp); + sp_2048_mont_mul_64(r, r, t[y], m, mp); + + XMEMSET(&r[64], 0, sizeof(sp_digit) * 64); + sp_2048_mont_reduce_64(r, m, mp); + + mask = 0 - (sp_2048_cmp_64(r, m) >= 0); + sp_2048_cond_sub_64(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#endif /* WOLFSSL_SP_SMALL */ +#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ + +#ifdef WOLFSSL_HAVE_SP_RSA +/* RSA public key operation. + * + * in Array of bytes representing the number to exponentiate, base. + * inLen Number of bytes in base. + * em Public exponent. + * mm Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 256 bytes long. + * outLen Number of bytes in result. + * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when + * an array is too long and MEMORY_E when dynamic memory allocation fails. + */ +int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm, + byte* out, word32* outLen) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit ad[128], md[64], rd[128]; +#else + sp_digit* d = NULL; +#endif + sp_digit* a; + sp_digit *ah; + sp_digit* m; + sp_digit* r; + sp_digit e[1]; + int err = MP_OKAY; + + if (*outLen < 256) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(em) > 32 || inLen > 256 || + mp_count_bits(mm) != 2048)) + err = MP_READ_E; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 64 * 5, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + a = d; + r = a + 64 * 2; + m = r + 64 * 2; + ah = a + 64; + } +#else + a = ad; + m = md; + r = rd; + ah = a + 64; +#endif + + if (err == MP_OKAY) { + sp_2048_from_bin(ah, 64, in, inLen); +#if DIGIT_BIT >= 32 + e[0] = em->dp[0]; +#else + e[0] = em->dp[0]; + if (em->used > 1) + e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT; +#endif + if (e[0] == 0) + err = MP_EXPTMOD_E; + } + if (err == MP_OKAY) { + sp_2048_from_mp(m, 64, mm); + + if (e[0] == 0x3) { + if (err == MP_OKAY) { + sp_2048_sqr_64(r, ah); + err = sp_2048_mod_64_cond(r, r, m); + } + if (err == MP_OKAY) { + sp_2048_mul_64(r, ah, r); + err = sp_2048_mod_64_cond(r, r, m); + } + } + else { + int i; + sp_digit mp; + + sp_2048_mont_setup(m, &mp); + + /* Convert to Montgomery form. */ + XMEMSET(a, 0, sizeof(sp_digit) * 64); + err = sp_2048_mod_64_cond(a, a, m); + + if (err == MP_OKAY) { + for (i=31; i>=0; i--) + if (e[0] >> i) + break; + + XMEMCPY(r, a, sizeof(sp_digit) * 64); + for (i--; i>=0; i--) { + sp_2048_mont_sqr_64(r, r, m, mp); + if (((e[0] >> i) & 1) == 1) + sp_2048_mont_mul_64(r, r, a, m, mp); + } + XMEMSET(&r[64], 0, sizeof(sp_digit) * 64); + sp_2048_mont_reduce_64(r, m, mp); + + for (i = 63; i > 0; i--) { + if (r[i] != m[i]) + break; + } + if (r[i] >= m[i]) + sp_2048_sub_in_place_64(r, m); + } + } + } + + if (err == MP_OKAY) { + sp_2048_to_bin(r, out); + *outLen = 256; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_RSA); +#endif + + return err; +} + +/* RSA private key operation. + * + * in Array of bytes representing the number to exponentiate, base. + * inLen Number of bytes in base. + * dm Private exponent. + * pm First prime. + * qm Second prime. + * dpm First prime's CRT exponent. + * dqm Second prime's CRT exponent. + * qim Inverse of second prime mod p. + * mm Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 256 bytes long. + * outLen Number of bytes in result. + * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when + * an array is too long and MEMORY_E when dynamic memory allocation fails. + */ +int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, + mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm, + byte* out, word32* outLen) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit ad[64 * 2]; + sp_digit pd[32], qd[32], dpd[32]; + sp_digit tmpad[64], tmpbd[64]; +#else + sp_digit* t = NULL; +#endif + sp_digit* a; + sp_digit* p; + sp_digit* q; + sp_digit* dp; + sp_digit* dq; + sp_digit* qi; + sp_digit* tmp; + sp_digit* tmpa; + sp_digit* tmpb; + sp_digit* r; + sp_digit c; + int err = MP_OKAY; + + (void)dm; + (void)mm; + + if (*outLen < 256) + err = MP_TO_E; + if (err == MP_OKAY && (inLen > 256 || mp_count_bits(mm) != 2048)) + err = MP_READ_E; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 11, NULL, + DYNAMIC_TYPE_RSA); + if (t == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + a = t; + p = a + 64 * 2; + q = p + 32; + qi = dq = dp = q + 32; + tmpa = qi + 32; + tmpb = tmpa + 64; + + tmp = t; + r = tmp + 64; + } +#else + r = a = ad; + p = pd; + q = qd; + qi = dq = dp = dpd; + tmpa = tmpad; + tmpb = tmpbd; + tmp = a + 64; +#endif + + if (err == MP_OKAY) { + sp_2048_from_bin(a, 64, in, inLen); + sp_2048_from_mp(p, 32, pm); + sp_2048_from_mp(q, 32, qm); + sp_2048_from_mp(dp, 32, dpm); + + err = sp_2048_mod_exp_32(tmpa, a, dp, 1024, p, 1); + } + if (err == MP_OKAY) { + sp_2048_from_mp(dq, 32, dqm); + err = sp_2048_mod_exp_32(tmpb, a, dq, 1024, q, 1); + } + + if (err == MP_OKAY) { + c = sp_2048_sub_in_place_32(tmpa, tmpb); + sp_2048_mask_32(tmp, p, c); + sp_2048_add_32(tmpa, tmpa, tmp); + + sp_2048_from_mp(qi, 32, qim); + sp_2048_mul_32(tmpa, tmpa, qi); + err = sp_2048_mod_32(tmpa, tmpa, p); + } + + if (err == MP_OKAY) { + sp_2048_mul_32(tmpa, q, tmpa); + XMEMSET(&tmpb[32], 0, sizeof(sp_digit) * 32); + sp_2048_add_64(r, tmpb, tmpa); + + sp_2048_to_bin(r, out); + *outLen = 256; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_digit) * 32 * 11); + XFREE(t, NULL, DYNAMIC_TYPE_RSA); + } +#else + XMEMSET(tmpad, 0, sizeof(tmpad)); + XMEMSET(tmpbd, 0, sizeof(tmpbd)); + XMEMSET(pd, 0, sizeof(pd)); + XMEMSET(qd, 0, sizeof(qd)); + XMEMSET(dpd, 0, sizeof(dpd)); +#endif + + return err; +} +#endif /* WOLFSSL_HAVE_SP_RSA */ +#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \ + !defined(WOLFSSL_RSA_PUBLIC_ONLY)) +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_2048_to_mp(sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (2048 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { +#if DIGIT_BIT == 32 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 64); + r->used = 64; + mp_clamp(r); +#elif DIGIT_BIT < 32 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 64; i++) { + r->dp[j] |= a[i] << s; + r->dp[j] &= (1l << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + while (s + DIGIT_BIT <= 32) { + s += DIGIT_BIT; + r->dp[j] &= (1l << DIGIT_BIT) - 1; + r->dp[++j] = a[i] >> s; + } + s = 32 - s; + } + r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 64; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 32 >= DIGIT_BIT) { + #if DIGIT_BIT < 32 + r->dp[j] &= (1l << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 32 - s; + } + else + s += 32; + } + r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returs 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ + int err = MP_OKAY; + sp_digit b[128], e[64], m[64]; + sp_digit* r = b; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 2048 || expBits > 2048 || + mp_count_bits(mod) != 2048) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + sp_2048_from_mp(b, 64, base); + sp_2048_from_mp(e, 64, exp); + sp_2048_from_mp(m, 64, mod); + + err = sp_2048_mod_exp_64(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + err = sp_2048_to_mp(r, res); + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} + +#ifdef WOLFSSL_HAVE_SP_DH +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. + * exp Array of bytes that is the exponent. + * expLen Length of data, in bytes, in exponent. + * mod Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 256 bytes long. + * outLen Length, in bytes, of exponentiation result. + * returs 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen, + mp_int* mod, byte* out, word32* outLen) +{ + int err = MP_OKAY; + sp_digit b[128], e[64], m[64]; + sp_digit* r = b; + word32 i; + + if (mp_count_bits(base) > 2048 || expLen > 256 || + mp_count_bits(mod) != 2048) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + sp_2048_from_mp(b, 64, base); + sp_2048_from_bin(e, 64, exp, expLen); + sp_2048_from_mp(m, 64, mod); + + err = sp_2048_mod_exp_64(r, b, e, expLen * 8, m, 0); + } + + if (err == MP_OKAY) { + sp_2048_to_bin(r, out); + *outLen = 256; + for (i=0; i<256 && out[i] == 0; i++) { + } + *outLen -= i; + XMEMMOVE(out, out + i, *outLen); + + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} +#endif /* WOLFSSL_HAVE_SP_DH */ + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returs 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ + int err = MP_OKAY; + sp_digit b[64], e[32], m[32]; + sp_digit* r = b; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 1024 || expBits > 1024 || + mp_count_bits(mod) != 1024) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + sp_2048_from_mp(b, 32, base); + sp_2048_from_mp(e, 32, exp); + sp_2048_from_mp(m, 32, mod); + + err = sp_2048_mod_exp_32(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + XMEMSET(r + 32, 0, sizeof(*r) * 32); + err = sp_2048_to_mp(r, res); + res->used = mod->used; + mp_clamp(res); + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} + +#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ + +#endif /* !WOLFSSL_SP_NO_2048 */ + +#ifndef WOLFSSL_SP_NO_3072 +/* Read big endian unsigned byte aray into r. + * + * r A single precision integer. + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_3072_from_bin(sp_digit* r, int max, const byte* a, int n) +{ + int i, j = 0, s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= ((sp_digit)a[i]) << s; + if (s >= 24) { + r[j] &= 0xffffffff; + s = 32 - s; + if (j + 1 >= max) + break; + r[++j] = a[i] >> s; + s = 8 - s; + } + else + s += 8; + } + + for (j++; j < max; j++) + r[j] = 0; +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * a A multi-precision integer. + */ +static void sp_3072_from_mp(sp_digit* r, int max, mp_int* a) +{ +#if DIGIT_BIT == 32 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < max; j++) + r[j] = 0; +#elif DIGIT_BIT > 32 + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= a->dp[i] << s; + r[j] &= 0xffffffff; + s = 32 - s; + if (j + 1 >= max) + break; + r[++j] = a->dp[i] >> s; + while (s + 32 <= DIGIT_BIT) { + s += 32; + r[j] &= 0xffffffff; + if (j + 1 >= max) + break; + if (s < DIGIT_BIT) + r[++j] = a->dp[i] >> s; + else + r[++j] = 0; + } + s = DIGIT_BIT - s; + } + + for (j++; j < max; j++) + r[j] = 0; +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 32) { + r[j] &= 0xffffffff; + if (j + 1 >= max) + break; + s = 32 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else + s += DIGIT_BIT; + } + + for (j++; j < max; j++) + r[j] = 0; +#endif +} + +/* Write r as big endian to byte aray. + * Fixed length number of bytes written: 384 + * + * r A single precision integer. + * a Byte array. + */ +static void sp_3072_to_bin(sp_digit* r, byte* a) +{ + int i, j, s = 0, b; + + j = 3072 / 8 - 1; + a[j] = 0; + for (i=0; i<96 && j>=0; i++) { + b = 0; + a[j--] |= r[i] << s; b += 8 - s; + if (j < 0) + break; + while (b < 32) { + a[j--] = r[i] >> b; b += 8; + if (j < 0) + break; + } + s = 8 - (b - 32); + if (j >= 0) + a[j] = 0; + if (s != 0) + j++; + } +} + +#ifndef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_3072_mul_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit tmp[8]; + __asm__ __volatile__ ( + "mov r8, %[r]\n\t" + "mov %[r], #0\n\t" + /* A[0] * B[0] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[b], #0]\n\t" + "umull r3, r4, r6, r7\n\t" + "mov r5, #0\n\t" + "str r3, [%[tmp], #0]\n\t" + "mov r3, #0\n\t" + /* A[0] * B[1] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[b], #4]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[1] * B[0] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[b], #0]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "str r4, [%[tmp], #4]\n\t" + "mov r4, #0\n\t" + /* A[0] * B[2] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[b], #8]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[1] * B[1] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[b], #4]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[2] * B[0] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[b], #0]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + "str r5, [%[tmp], #8]\n\t" + "mov r5, #0\n\t" + /* A[0] * B[3] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[b], #12]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[1] * B[2] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[b], #8]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[2] * B[1] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[b], #4]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[3] * B[0] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b], #0]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "str r3, [%[tmp], #12]\n\t" + "mov r3, #0\n\t" + /* A[0] * B[4] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[b], #16]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[1] * B[3] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[b], #12]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[2] * B[2] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[b], #8]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[3] * B[1] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b], #4]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[4] * B[0] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[b], #0]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "str r4, [%[tmp], #16]\n\t" + "mov r4, #0\n\t" + /* A[0] * B[5] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[b], #20]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[1] * B[4] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[b], #16]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[2] * B[3] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[b], #12]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[3] * B[2] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b], #8]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[4] * B[1] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[b], #4]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[5] * B[0] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r7, [%[b], #0]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + "str r5, [%[tmp], #20]\n\t" + "mov r5, #0\n\t" + /* A[0] * B[6] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[b], #24]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[1] * B[5] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[b], #20]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[2] * B[4] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[b], #16]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[3] * B[3] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b], #12]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[4] * B[2] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[b], #8]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[5] * B[1] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r7, [%[b], #4]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[6] * B[0] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[b], #0]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "str r3, [%[tmp], #24]\n\t" + "mov r3, #0\n\t" + /* A[0] * B[7] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[b], #28]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[1] * B[6] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[b], #24]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[2] * B[5] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[b], #20]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[3] * B[4] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b], #16]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[4] * B[3] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[b], #12]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[5] * B[2] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r7, [%[b], #8]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[6] * B[1] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[b], #4]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[7] * B[0] */ + "ldr r6, [%[a], #28]\n\t" + "ldr r7, [%[b], #0]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "str r4, [%[tmp], #28]\n\t" + "mov r4, #0\n\t" + /* A[1] * B[7] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[b], #28]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[2] * B[6] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[b], #24]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[3] * B[5] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b], #20]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[4] * B[4] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[b], #16]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[5] * B[3] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r7, [%[b], #12]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[6] * B[2] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[b], #8]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[7] * B[1] */ + "ldr r6, [%[a], #28]\n\t" + "ldr r7, [%[b], #4]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + "str r5, [r8, #32]\n\t" + "mov r5, #0\n\t" + /* A[2] * B[7] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[b], #28]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[3] * B[6] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b], #24]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[4] * B[5] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[b], #20]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[5] * B[4] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r7, [%[b], #16]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[6] * B[3] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[b], #12]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[7] * B[2] */ + "ldr r6, [%[a], #28]\n\t" + "ldr r7, [%[b], #8]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "str r3, [r8, #36]\n\t" + "mov r3, #0\n\t" + /* A[3] * B[7] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b], #28]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[4] * B[6] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[b], #24]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[5] * B[5] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r7, [%[b], #20]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[6] * B[4] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[b], #16]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[7] * B[3] */ + "ldr r6, [%[a], #28]\n\t" + "ldr r7, [%[b], #12]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "str r4, [r8, #40]\n\t" + "mov r4, #0\n\t" + /* A[4] * B[7] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[b], #28]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[5] * B[6] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r7, [%[b], #24]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[6] * B[5] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[b], #20]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[7] * B[4] */ + "ldr r6, [%[a], #28]\n\t" + "ldr r7, [%[b], #16]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + "str r5, [r8, #44]\n\t" + "mov r5, #0\n\t" + /* A[5] * B[7] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r7, [%[b], #28]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[6] * B[6] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[b], #24]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[7] * B[5] */ + "ldr r6, [%[a], #28]\n\t" + "ldr r7, [%[b], #20]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "str r3, [r8, #48]\n\t" + "mov r3, #0\n\t" + /* A[6] * B[7] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[b], #28]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[7] * B[6] */ + "ldr r6, [%[a], #28]\n\t" + "ldr r7, [%[b], #24]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "str r4, [r8, #52]\n\t" + "mov r4, #0\n\t" + /* A[7] * B[7] */ + "ldr r6, [%[a], #28]\n\t" + "ldr r7, [%[b], #28]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "str r5, [r8, #56]\n\t" + "str r3, [r8, #60]\n\t" + "ldr r3, [%[tmp], #0]\n\t" + "ldr r4, [%[tmp], #4]\n\t" + "ldr r5, [%[tmp], #8]\n\t" + "ldr r6, [%[tmp], #12]\n\t" + "str r3, [r8, #0]\n\t" + "str r4, [r8, #4]\n\t" + "str r5, [r8, #8]\n\t" + "str r6, [r8, #12]\n\t" + "ldr r3, [%[tmp], #16]\n\t" + "ldr r4, [%[tmp], #20]\n\t" + "ldr r5, [%[tmp], #24]\n\t" + "ldr r6, [%[tmp], #28]\n\t" + "str r3, [r8, #16]\n\t" + "str r4, [r8, #20]\n\t" + "str r5, [r8, #24]\n\t" + "str r6, [r8, #28]\n\t" + "mov %[r], r8\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [tmp] "r" (tmp) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8" + ); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_3072_sqr_8(sp_digit* r, const sp_digit* a) +{ + sp_digit tmp[8]; + __asm__ __volatile__ ( + "mov r8, %[r]\n\t" + "mov %[r], #0\n\t" + /* A[0] * A[0] */ + "ldr r6, [%[a], #0]\n\t" + "umull r3, r4, r6, r6\n\t" + "mov r5, #0\n\t" + "str r3, [%[tmp], #0]\n\t" + "mov r3, #0\n\t" + /* A[0] * A[1] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[a], #4]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "str r4, [%[tmp], #4]\n\t" + "mov r4, #0\n\t" + /* A[0] * A[2] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[a], #8]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[1] * A[1] */ + "ldr r6, [%[a], #4]\n\t" + "umull r6, r7, r6, r6\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + "str r5, [%[tmp], #8]\n\t" + "mov r5, #0\n\t" + /* A[0] * A[3] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[a], #12]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[1] * A[2] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[a], #8]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "str r3, [%[tmp], #12]\n\t" + "mov r3, #0\n\t" + /* A[0] * A[4] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[a], #16]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[1] * A[3] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[a], #12]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[2] * A[2] */ + "ldr r6, [%[a], #8]\n\t" + "umull r6, r7, r6, r6\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "str r4, [%[tmp], #16]\n\t" + "mov r4, #0\n\t" + /* A[0] * A[5] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[a], #20]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[1] * A[4] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[a], #16]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[2] * A[3] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #12]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + "str r5, [%[tmp], #20]\n\t" + "mov r5, #0\n\t" + /* A[0] * A[6] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[a], #24]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[1] * A[5] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[a], #20]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[2] * A[4] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #16]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[3] * A[3] */ + "ldr r6, [%[a], #12]\n\t" + "umull r6, r7, r6, r6\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "str r3, [%[tmp], #24]\n\t" + "mov r3, #0\n\t" + /* A[0] * A[7] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[a], #28]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[1] * A[6] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[a], #24]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[2] * A[5] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #20]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[3] * A[4] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[a], #16]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "str r4, [%[tmp], #28]\n\t" + "mov r4, #0\n\t" + /* A[1] * A[7] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[a], #28]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[2] * A[6] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #24]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[3] * A[5] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[a], #20]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[4] * A[4] */ + "ldr r6, [%[a], #16]\n\t" + "umull r6, r7, r6, r6\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + "str r5, [r8, #32]\n\t" + "mov r5, #0\n\t" + /* A[2] * A[7] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #28]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[3] * A[6] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[a], #24]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[4] * A[5] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[a], #20]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "str r3, [r8, #36]\n\t" + "mov r3, #0\n\t" + /* A[3] * A[7] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[a], #28]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[4] * A[6] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[a], #24]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[5] * A[5] */ + "ldr r6, [%[a], #20]\n\t" + "umull r6, r7, r6, r6\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "str r4, [r8, #40]\n\t" + "mov r4, #0\n\t" + /* A[4] * A[7] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[a], #28]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[5] * A[6] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r7, [%[a], #24]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + "str r5, [r8, #44]\n\t" + "mov r5, #0\n\t" + /* A[5] * A[7] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r7, [%[a], #28]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[6] * A[6] */ + "ldr r6, [%[a], #24]\n\t" + "umull r6, r7, r6, r6\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "str r3, [r8, #48]\n\t" + "mov r3, #0\n\t" + /* A[6] * A[7] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[a], #28]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "str r4, [r8, #52]\n\t" + "mov r4, #0\n\t" + /* A[7] * A[7] */ + "ldr r6, [%[a], #28]\n\t" + "umull r6, r7, r6, r6\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "str r5, [r8, #56]\n\t" + "str r3, [r8, #60]\n\t" + "ldr r3, [%[tmp], #0]\n\t" + "ldr r4, [%[tmp], #4]\n\t" + "ldr r5, [%[tmp], #8]\n\t" + "ldr r6, [%[tmp], #12]\n\t" + "str r3, [r8, #0]\n\t" + "str r4, [r8, #4]\n\t" + "str r5, [r8, #8]\n\t" + "str r6, [r8, #12]\n\t" + "ldr r3, [%[tmp], #16]\n\t" + "ldr r4, [%[tmp], #20]\n\t" + "ldr r5, [%[tmp], #24]\n\t" + "ldr r6, [%[tmp], #28]\n\t" + "str r3, [r8, #16]\n\t" + "str r4, [r8, #20]\n\t" + "str r5, [r8, #24]\n\t" + "str r6, [r8, #28]\n\t" + "mov %[r], r8\n\t" + : + : [r] "r" (r), [a] "r" (a), [tmp] "r" (tmp) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8" + ); +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_3072_add_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "adds r4, r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5" + ); + + return c; +} + +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_3072_sub_in_place_16(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r6, [%[b], #4]\n\t" + "subs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #0]\n\t" + "str r4, [%[a], #4]\n\t" + "ldr r3, [%[a], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r6, [%[b], #12]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #8]\n\t" + "str r4, [%[a], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r6, [%[b], #20]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #16]\n\t" + "str r4, [%[a], #20]\n\t" + "ldr r3, [%[a], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r6, [%[b], #28]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #24]\n\t" + "str r4, [%[a], #28]\n\t" + "ldr r3, [%[a], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r6, [%[b], #36]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #32]\n\t" + "str r4, [%[a], #36]\n\t" + "ldr r3, [%[a], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r6, [%[b], #44]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #40]\n\t" + "str r4, [%[a], #44]\n\t" + "ldr r3, [%[a], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #48]\n\t" + "ldr r6, [%[b], #52]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #48]\n\t" + "str r4, [%[a], #52]\n\t" + "ldr r3, [%[a], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #56]\n\t" + "ldr r6, [%[b], #60]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #56]\n\t" + "str r4, [%[a], #60]\n\t" + "sbc %[c], %[c], %[c]\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6" + ); + + return c; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_3072_add_16(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "adds r4, r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[b], #48]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #52]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[b], #56]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #60]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #60]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5" + ); + + return c; +} + +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_3072_mask_8(sp_digit* r, sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<8; i++) + r[i] = a[i] & m; +#else + r[0] = a[0] & m; + r[1] = a[1] & m; + r[2] = a[2] & m; + r[3] = a[3] & m; + r[4] = a[4] & m; + r[5] = a[5] & m; + r[6] = a[6] & m; + r[7] = a[7] & m; +#endif +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_3072_mul_16(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[16]; + sp_digit a1[8]; + sp_digit b1[8]; + sp_digit z2[16]; + sp_digit u, ca, cb; + + ca = sp_3072_add_8(a1, a, &a[8]); + cb = sp_3072_add_8(b1, b, &b[8]); + u = ca & cb; + sp_3072_mul_8(z1, a1, b1); + sp_3072_mul_8(z2, &a[8], &b[8]); + sp_3072_mul_8(z0, a, b); + sp_3072_mask_8(r + 16, a1, 0 - cb); + sp_3072_mask_8(b1, b1, 0 - ca); + u += sp_3072_add_8(r + 16, r + 16, b1); + u += sp_3072_sub_in_place_16(z1, z2); + u += sp_3072_sub_in_place_16(z1, z0); + u += sp_3072_add_16(r + 8, r + 8, z1); + r[24] = u; + XMEMSET(r + 24 + 1, 0, sizeof(sp_digit) * (8 - 1)); + sp_3072_add_16(r + 16, r + 16, z2); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_3072_sqr_16(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z2[16]; + sp_digit z1[16]; + sp_digit a1[8]; + sp_digit u; + + u = sp_3072_add_8(a1, a, &a[8]); + sp_3072_sqr_8(z1, a1); + sp_3072_sqr_8(z2, &a[8]); + sp_3072_sqr_8(z0, a); + sp_3072_mask_8(r + 16, a1, 0 - u); + u += sp_3072_add_8(r + 16, r + 16, r + 16); + u += sp_3072_sub_in_place_16(z1, z2); + u += sp_3072_sub_in_place_16(z1, z0); + u += sp_3072_add_16(r + 8, r + 8, z1); + r[24] = u; + XMEMSET(r + 24 + 1, 0, sizeof(sp_digit) * (8 - 1)); + sp_3072_add_16(r + 16, r + 16, z2); +} + +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_3072_sub_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[a], #4]\n\t" + "ldr r6, [%[b], #0]\n\t" + "ldr r7, [%[b], #4]\n\t" + "subs r4, r4, r6\n\t" + "sbcs r5, r5, r7\n\t" + "str r4, [%[r], #0]\n\t" + "str r5, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[a], #12]\n\t" + "ldr r6, [%[b], #8]\n\t" + "ldr r7, [%[b], #12]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r7\n\t" + "str r4, [%[r], #8]\n\t" + "str r5, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[a], #20]\n\t" + "ldr r6, [%[b], #16]\n\t" + "ldr r7, [%[b], #20]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r7\n\t" + "str r4, [%[r], #16]\n\t" + "str r5, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[a], #28]\n\t" + "ldr r6, [%[b], #24]\n\t" + "ldr r7, [%[b], #28]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r7\n\t" + "str r4, [%[r], #24]\n\t" + "str r5, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[a], #36]\n\t" + "ldr r6, [%[b], #32]\n\t" + "ldr r7, [%[b], #36]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r7\n\t" + "str r4, [%[r], #32]\n\t" + "str r5, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[a], #44]\n\t" + "ldr r6, [%[b], #40]\n\t" + "ldr r7, [%[b], #44]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r7\n\t" + "str r4, [%[r], #40]\n\t" + "str r5, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[a], #52]\n\t" + "ldr r6, [%[b], #48]\n\t" + "ldr r7, [%[b], #52]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r7\n\t" + "str r4, [%[r], #48]\n\t" + "str r5, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[a], #60]\n\t" + "ldr r6, [%[b], #56]\n\t" + "ldr r7, [%[b], #60]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r7\n\t" + "str r4, [%[r], #56]\n\t" + "str r5, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[a], #68]\n\t" + "ldr r6, [%[b], #64]\n\t" + "ldr r7, [%[b], #68]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r7\n\t" + "str r4, [%[r], #64]\n\t" + "str r5, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[a], #76]\n\t" + "ldr r6, [%[b], #72]\n\t" + "ldr r7, [%[b], #76]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r7\n\t" + "str r4, [%[r], #72]\n\t" + "str r5, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[a], #84]\n\t" + "ldr r6, [%[b], #80]\n\t" + "ldr r7, [%[b], #84]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r7\n\t" + "str r4, [%[r], #80]\n\t" + "str r5, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[a], #92]\n\t" + "ldr r6, [%[b], #88]\n\t" + "ldr r7, [%[b], #92]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r7\n\t" + "str r4, [%[r], #88]\n\t" + "str r5, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[a], #100]\n\t" + "ldr r6, [%[b], #96]\n\t" + "ldr r7, [%[b], #100]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r7\n\t" + "str r4, [%[r], #96]\n\t" + "str r5, [%[r], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[a], #108]\n\t" + "ldr r6, [%[b], #104]\n\t" + "ldr r7, [%[b], #108]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r7\n\t" + "str r4, [%[r], #104]\n\t" + "str r5, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[a], #116]\n\t" + "ldr r6, [%[b], #112]\n\t" + "ldr r7, [%[b], #116]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r7\n\t" + "str r4, [%[r], #112]\n\t" + "str r5, [%[r], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[a], #124]\n\t" + "ldr r6, [%[b], #120]\n\t" + "ldr r7, [%[b], #124]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r7\n\t" + "str r4, [%[r], #120]\n\t" + "str r5, [%[r], #124]\n\t" + "sbc %[c], %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r7" + ); + + return c; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_3072_add_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "adds r4, r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[b], #48]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #52]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[b], #56]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #60]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[b], #64]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #68]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[b], #72]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #76]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[b], #80]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #84]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[b], #88]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #92]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[b], #96]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #100]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[b], #104]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #108]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[b], #112]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #116]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[b], #120]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #124]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #124]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5" + ); + + return c; +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_3072_mul_48(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit p0[32]; + sp_digit p1[32]; + sp_digit p2[32]; + sp_digit p3[32]; + sp_digit p4[32]; + sp_digit p5[32]; + sp_digit t0[32]; + sp_digit t1[32]; + sp_digit t2[32]; + sp_digit a0[16]; + sp_digit a1[16]; + sp_digit a2[16]; + sp_digit b0[16]; + sp_digit b1[16]; + sp_digit b2[16]; + sp_3072_add_16(a0, a, &a[16]); + sp_3072_add_16(b0, b, &b[16]); + sp_3072_add_16(a1, &a[16], &a[32]); + sp_3072_add_16(b1, &b[16], &b[32]); + sp_3072_add_16(a2, a0, &a[32]); + sp_3072_add_16(b2, b0, &b[32]); + sp_3072_mul_16(p0, a, b); + sp_3072_mul_16(p2, &a[16], &b[16]); + sp_3072_mul_16(p4, &a[32], &b[32]); + sp_3072_mul_16(p1, a0, b0); + sp_3072_mul_16(p3, a1, b1); + sp_3072_mul_16(p5, a2, b2); + XMEMSET(r, 0, sizeof(*r)*2*48); + sp_3072_sub_32(t0, p3, p2); + sp_3072_sub_32(t1, p1, p2); + sp_3072_sub_32(t2, p5, t0); + sp_3072_sub_32(t2, t2, t1); + sp_3072_sub_32(t0, t0, p4); + sp_3072_sub_32(t1, t1, p0); + sp_3072_add_32(r, r, p0); + sp_3072_add_32(&r[16], &r[16], t1); + sp_3072_add_32(&r[32], &r[32], t2); + sp_3072_add_32(&r[48], &r[48], t0); + sp_3072_add_32(&r[64], &r[64], p4); +} + +/* Square a into r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_3072_sqr_48(sp_digit* r, const sp_digit* a) +{ + sp_digit p0[32]; + sp_digit p1[32]; + sp_digit p2[32]; + sp_digit p3[32]; + sp_digit p4[32]; + sp_digit p5[32]; + sp_digit t0[32]; + sp_digit t1[32]; + sp_digit t2[32]; + sp_digit a0[16]; + sp_digit a1[16]; + sp_digit a2[16]; + sp_3072_add_16(a0, a, &a[16]); + sp_3072_add_16(a1, &a[16], &a[32]); + sp_3072_add_16(a2, a0, &a[32]); + sp_3072_sqr_16(p0, a); + sp_3072_sqr_16(p2, &a[16]); + sp_3072_sqr_16(p4, &a[32]); + sp_3072_sqr_16(p1, a0); + sp_3072_sqr_16(p3, a1); + sp_3072_sqr_16(p5, a2); + XMEMSET(r, 0, sizeof(*r)*2*48); + sp_3072_sub_32(t0, p3, p2); + sp_3072_sub_32(t1, p1, p2); + sp_3072_sub_32(t2, p5, t0); + sp_3072_sub_32(t2, t2, t1); + sp_3072_sub_32(t0, t0, p4); + sp_3072_sub_32(t1, t1, p0); + sp_3072_add_32(r, r, p0); + sp_3072_add_32(&r[16], &r[16], t1); + sp_3072_add_32(&r[32], &r[32], t2); + sp_3072_add_32(&r[48], &r[48], t0); + sp_3072_add_32(&r[64], &r[64], p4); +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_3072_add_48(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r7, #0\n\t" + "mvn r7, r7\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "adds r4, r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[b], #48]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #52]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[b], #56]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #60]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[b], #64]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #68]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[b], #72]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #76]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[b], #80]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #84]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[b], #88]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #92]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[b], #96]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #100]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[b], #104]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #108]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[b], #112]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #116]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[b], #120]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #124]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #124]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c], %[c]\n\t" + "add %[a], %[a], #0x80\n\t" + "add %[b], %[b], #0x80\n\t" + "add %[r], %[r], #0x80\n\t" + "adds %[c], %[c], r7\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[b], #48]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #52]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[b], #56]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #60]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #60]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r7" + ); + + return c; +} + +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_3072_sub_in_place_96(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r6, [%[b], #4]\n\t" + "subs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #0]\n\t" + "str r4, [%[a], #4]\n\t" + "ldr r3, [%[a], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r6, [%[b], #12]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #8]\n\t" + "str r4, [%[a], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r6, [%[b], #20]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #16]\n\t" + "str r4, [%[a], #20]\n\t" + "ldr r3, [%[a], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r6, [%[b], #28]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #24]\n\t" + "str r4, [%[a], #28]\n\t" + "ldr r3, [%[a], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r6, [%[b], #36]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #32]\n\t" + "str r4, [%[a], #36]\n\t" + "ldr r3, [%[a], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r6, [%[b], #44]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #40]\n\t" + "str r4, [%[a], #44]\n\t" + "ldr r3, [%[a], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #48]\n\t" + "ldr r6, [%[b], #52]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #48]\n\t" + "str r4, [%[a], #52]\n\t" + "ldr r3, [%[a], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #56]\n\t" + "ldr r6, [%[b], #60]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #56]\n\t" + "str r4, [%[a], #60]\n\t" + "ldr r3, [%[a], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #64]\n\t" + "ldr r6, [%[b], #68]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #64]\n\t" + "str r4, [%[a], #68]\n\t" + "ldr r3, [%[a], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #72]\n\t" + "ldr r6, [%[b], #76]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #72]\n\t" + "str r4, [%[a], #76]\n\t" + "ldr r3, [%[a], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #80]\n\t" + "ldr r6, [%[b], #84]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #80]\n\t" + "str r4, [%[a], #84]\n\t" + "ldr r3, [%[a], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #88]\n\t" + "ldr r6, [%[b], #92]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #88]\n\t" + "str r4, [%[a], #92]\n\t" + "ldr r3, [%[a], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #96]\n\t" + "ldr r6, [%[b], #100]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #96]\n\t" + "str r4, [%[a], #100]\n\t" + "ldr r3, [%[a], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #104]\n\t" + "ldr r6, [%[b], #108]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #104]\n\t" + "str r4, [%[a], #108]\n\t" + "ldr r3, [%[a], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #112]\n\t" + "ldr r6, [%[b], #116]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #112]\n\t" + "str r4, [%[a], #116]\n\t" + "ldr r3, [%[a], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #120]\n\t" + "ldr r6, [%[b], #124]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #120]\n\t" + "str r4, [%[a], #124]\n\t" + "sbc %[c], %[c], %[c]\n\t" + "add %[a], %[a], #0x80\n\t" + "add %[b], %[b], #0x80\n\t" + "mov r5, #0\n\t" + "sub r5, r5, %[c]\n\t" + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #0]\n\t" + "str r4, [%[a], #4]\n\t" + "ldr r3, [%[a], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r6, [%[b], #12]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #8]\n\t" + "str r4, [%[a], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r6, [%[b], #20]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #16]\n\t" + "str r4, [%[a], #20]\n\t" + "ldr r3, [%[a], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r6, [%[b], #28]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #24]\n\t" + "str r4, [%[a], #28]\n\t" + "ldr r3, [%[a], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r6, [%[b], #36]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #32]\n\t" + "str r4, [%[a], #36]\n\t" + "ldr r3, [%[a], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r6, [%[b], #44]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #40]\n\t" + "str r4, [%[a], #44]\n\t" + "ldr r3, [%[a], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #48]\n\t" + "ldr r6, [%[b], #52]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #48]\n\t" + "str r4, [%[a], #52]\n\t" + "ldr r3, [%[a], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #56]\n\t" + "ldr r6, [%[b], #60]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #56]\n\t" + "str r4, [%[a], #60]\n\t" + "ldr r3, [%[a], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #64]\n\t" + "ldr r6, [%[b], #68]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #64]\n\t" + "str r4, [%[a], #68]\n\t" + "ldr r3, [%[a], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #72]\n\t" + "ldr r6, [%[b], #76]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #72]\n\t" + "str r4, [%[a], #76]\n\t" + "ldr r3, [%[a], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #80]\n\t" + "ldr r6, [%[b], #84]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #80]\n\t" + "str r4, [%[a], #84]\n\t" + "ldr r3, [%[a], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #88]\n\t" + "ldr r6, [%[b], #92]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #88]\n\t" + "str r4, [%[a], #92]\n\t" + "ldr r3, [%[a], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #96]\n\t" + "ldr r6, [%[b], #100]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #96]\n\t" + "str r4, [%[a], #100]\n\t" + "ldr r3, [%[a], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #104]\n\t" + "ldr r6, [%[b], #108]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #104]\n\t" + "str r4, [%[a], #108]\n\t" + "ldr r3, [%[a], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #112]\n\t" + "ldr r6, [%[b], #116]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #112]\n\t" + "str r4, [%[a], #116]\n\t" + "ldr r3, [%[a], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #120]\n\t" + "ldr r6, [%[b], #124]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #120]\n\t" + "str r4, [%[a], #124]\n\t" + "sbc %[c], %[c], %[c]\n\t" + "add %[a], %[a], #0x80\n\t" + "add %[b], %[b], #0x80\n\t" + "mov r5, #0\n\t" + "sub r5, r5, %[c]\n\t" + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #0]\n\t" + "str r4, [%[a], #4]\n\t" + "ldr r3, [%[a], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r6, [%[b], #12]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #8]\n\t" + "str r4, [%[a], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r6, [%[b], #20]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #16]\n\t" + "str r4, [%[a], #20]\n\t" + "ldr r3, [%[a], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r6, [%[b], #28]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #24]\n\t" + "str r4, [%[a], #28]\n\t" + "ldr r3, [%[a], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r6, [%[b], #36]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #32]\n\t" + "str r4, [%[a], #36]\n\t" + "ldr r3, [%[a], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r6, [%[b], #44]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #40]\n\t" + "str r4, [%[a], #44]\n\t" + "ldr r3, [%[a], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #48]\n\t" + "ldr r6, [%[b], #52]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #48]\n\t" + "str r4, [%[a], #52]\n\t" + "ldr r3, [%[a], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #56]\n\t" + "ldr r6, [%[b], #60]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #56]\n\t" + "str r4, [%[a], #60]\n\t" + "ldr r3, [%[a], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #64]\n\t" + "ldr r6, [%[b], #68]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #64]\n\t" + "str r4, [%[a], #68]\n\t" + "ldr r3, [%[a], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #72]\n\t" + "ldr r6, [%[b], #76]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #72]\n\t" + "str r4, [%[a], #76]\n\t" + "ldr r3, [%[a], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #80]\n\t" + "ldr r6, [%[b], #84]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #80]\n\t" + "str r4, [%[a], #84]\n\t" + "ldr r3, [%[a], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #88]\n\t" + "ldr r6, [%[b], #92]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #88]\n\t" + "str r4, [%[a], #92]\n\t" + "ldr r3, [%[a], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #96]\n\t" + "ldr r6, [%[b], #100]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #96]\n\t" + "str r4, [%[a], #100]\n\t" + "ldr r3, [%[a], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #104]\n\t" + "ldr r6, [%[b], #108]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #104]\n\t" + "str r4, [%[a], #108]\n\t" + "ldr r3, [%[a], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #112]\n\t" + "ldr r6, [%[b], #116]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #112]\n\t" + "str r4, [%[a], #116]\n\t" + "ldr r3, [%[a], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #120]\n\t" + "ldr r6, [%[b], #124]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #120]\n\t" + "str r4, [%[a], #124]\n\t" + "sbc %[c], %[c], %[c]\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6" + ); + + return c; +} + +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_3072_add_96(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r7, #0\n\t" + "mvn r7, r7\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "adds r4, r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[b], #48]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #52]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[b], #56]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #60]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[b], #64]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #68]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[b], #72]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #76]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[b], #80]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #84]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[b], #88]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #92]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[b], #96]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #100]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[b], #104]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #108]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[b], #112]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #116]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[b], #120]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #124]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #124]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c], %[c]\n\t" + "add %[a], %[a], #0x80\n\t" + "add %[b], %[b], #0x80\n\t" + "add %[r], %[r], #0x80\n\t" + "adds %[c], %[c], r7\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[b], #48]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #52]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[b], #56]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #60]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[b], #64]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #68]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[b], #72]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #76]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[b], #80]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #84]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[b], #88]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #92]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[b], #96]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #100]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[b], #104]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #108]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[b], #112]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #116]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[b], #120]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #124]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #124]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c], %[c]\n\t" + "add %[a], %[a], #0x80\n\t" + "add %[b], %[b], #0x80\n\t" + "add %[r], %[r], #0x80\n\t" + "adds %[c], %[c], r7\n\t" + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "ldr r4, [%[a], #32]\n\t" + "ldr r5, [%[b], #32]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #36]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #36]\n\t" + "ldr r4, [%[a], #40]\n\t" + "ldr r5, [%[b], #40]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #44]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #44]\n\t" + "ldr r4, [%[a], #48]\n\t" + "ldr r5, [%[b], #48]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #52]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #52]\n\t" + "ldr r4, [%[a], #56]\n\t" + "ldr r5, [%[b], #56]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #60]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #60]\n\t" + "ldr r4, [%[a], #64]\n\t" + "ldr r5, [%[b], #64]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #68]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #68]\n\t" + "ldr r4, [%[a], #72]\n\t" + "ldr r5, [%[b], #72]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #76]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #76]\n\t" + "ldr r4, [%[a], #80]\n\t" + "ldr r5, [%[b], #80]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #84]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #84]\n\t" + "ldr r4, [%[a], #88]\n\t" + "ldr r5, [%[b], #88]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #92]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #92]\n\t" + "ldr r4, [%[a], #96]\n\t" + "ldr r5, [%[b], #96]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #100]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #100]\n\t" + "ldr r4, [%[a], #104]\n\t" + "ldr r5, [%[b], #104]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #108]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #108]\n\t" + "ldr r4, [%[a], #112]\n\t" + "ldr r5, [%[b], #112]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #116]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #116]\n\t" + "ldr r4, [%[a], #120]\n\t" + "ldr r5, [%[b], #120]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #124]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #124]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r7" + ); + + return c; +} + +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_3072_mask_48(sp_digit* r, sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<48; i++) + r[i] = a[i] & m; +#else + int i; + + for (i = 0; i < 48; i += 8) { + r[i+0] = a[i+0] & m; + r[i+1] = a[i+1] & m; + r[i+2] = a[i+2] & m; + r[i+3] = a[i+3] & m; + r[i+4] = a[i+4] & m; + r[i+5] = a[i+5] & m; + r[i+6] = a[i+6] & m; + r[i+7] = a[i+7] & m; + } +#endif +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_3072_mul_96(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[96]; + sp_digit a1[48]; + sp_digit b1[48]; + sp_digit z2[96]; + sp_digit u, ca, cb; + + ca = sp_3072_add_48(a1, a, &a[48]); + cb = sp_3072_add_48(b1, b, &b[48]); + u = ca & cb; + sp_3072_mul_48(z1, a1, b1); + sp_3072_mul_48(z2, &a[48], &b[48]); + sp_3072_mul_48(z0, a, b); + sp_3072_mask_48(r + 96, a1, 0 - cb); + sp_3072_mask_48(b1, b1, 0 - ca); + u += sp_3072_add_48(r + 96, r + 96, b1); + u += sp_3072_sub_in_place_96(z1, z2); + u += sp_3072_sub_in_place_96(z1, z0); + u += sp_3072_add_96(r + 48, r + 48, z1); + r[144] = u; + XMEMSET(r + 144 + 1, 0, sizeof(sp_digit) * (48 - 1)); + sp_3072_add_96(r + 96, r + 96, z2); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_3072_sqr_96(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z2[96]; + sp_digit z1[96]; + sp_digit a1[48]; + sp_digit u; + + u = sp_3072_add_48(a1, a, &a[48]); + sp_3072_sqr_48(z1, a1); + sp_3072_sqr_48(z2, &a[48]); + sp_3072_sqr_48(z0, a); + sp_3072_mask_48(r + 96, a1, 0 - u); + u += sp_3072_add_48(r + 96, r + 96, r + 96); + u += sp_3072_sub_in_place_96(z1, z2); + u += sp_3072_sub_in_place_96(z1, z0); + u += sp_3072_add_96(r + 48, r + 48, z1); + r[144] = u; + XMEMSET(r + 144 + 1, 0, sizeof(sp_digit) * (48 - 1)); + sp_3072_add_96(r + 96, r + 96, z2); +} + +#endif /* !WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_3072_add_96(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r6, %[a]\n\t" + "mov r7, #0\n\t" + "mov r4, #1\n\t" + "lsl r4, r4, #8\n\t" + "add r4, r4, #128\n\t" + "sub r7, r7, #1\n\t" + "add r6, r6, r4\n\t" + "\n1:\n\t" + "adds %[c], %[c], r7\n\t" + "ldr r4, [%[a]]\n\t" + "ldr r5, [%[b]]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r]]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c], %[c]\n\t" + "add %[a], %[a], #4\n\t" + "add %[b], %[b], #4\n\t" + "add %[r], %[r], #4\n\t" + "cmp %[a], r6\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r7" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into a. (a -= b) + * + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_3072_sub_in_place_96(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + __asm__ __volatile__ ( + "mov r7, %[a]\n\t" + "mov r5, #1\n\t" + "lsl r5, r5, #8\n\t" + "add r5, r5, #128\n\t" + "add r7, r7, r5\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "subs r5, r5, %[c]\n\t" + "ldr r3, [%[a]]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b]]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a]]\n\t" + "str r4, [%[a], #4]\n\t" + "sbc %[c], %[c], %[c]\n\t" + "add %[a], %[a], #8\n\t" + "add %[b], %[b], #8\n\t" + "cmp %[a], r7\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6", "r7" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_3072_mul_96(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit tmp[96 * 2]; + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r8, r3\n\t" + "mov r11, %[r]\n\t" + "mov r9, %[a]\n\t" + "mov r10, %[b]\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, r6, #128\n\t" + "add r6, r6, r9\n\t" + "mov r12, r6\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r5, #0\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, r6, #124\n\t" + "mov %[a], r8\n\t" + "subs %[a], %[a], r6\n\t" + "sbc r6, r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], %[a], r6\n\t" + "mov %[b], r8\n\t" + "sub %[b], %[b], %[a]\n\t" + "add %[a], %[a], r9\n\t" + "add %[b], %[b], r10\n\t" + "\n2:\n\t" + /* Multiply Start */ + "ldr r6, [%[a]]\n\t" + "ldr r7, [%[b]]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* Multiply Done */ + "add %[a], %[a], #4\n\t" + "sub %[b], %[b], #4\n\t" + "cmp %[a], r12\n\t" + "beq 3f\n\t" + "mov r6, r8\n\t" + "add r6, r6, r9\n\t" + "cmp %[a], r6\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r11\n\t" + "mov r7, r8\n\t" + "str r3, [%[r], r7]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "add r7, r7, #4\n\t" + "mov r8, r7\n\t" + "mov r6, #2\n\t" + "lsl r6, r6, #8\n\t" + "add r6, r6, #248\n\t" + "cmp r7, r6\n\t" + "ble 1b\n\t" + "str r3, [%[r], r7]\n\t" + "mov %[a], r9\n\t" + "mov %[b], r10\n\t" + : + : [r] "r" (tmp), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_3072_sqr_96(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r5, #0\n\t" + "mov r8, r3\n\t" + "mov r11, %[r]\n\t" + "mov r6, #3\n\t" + "lsl r6, r6, #8\n\t" + "neg r6, r6\n\t" + "add sp, sp, r6\n\t" + "mov r10, sp\n\t" + "mov r9, %[a]\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, r6, #124\n\t" + "mov %[a], r8\n\t" + "subs %[a], %[a], r6\n\t" + "sbc r6, r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], %[a], r6\n\t" + "mov r2, r8\n\t" + "sub r2, r2, %[a]\n\t" + "add %[a], %[a], r9\n\t" + "add r2, r2, r9\n\t" + "\n2:\n\t" + "cmp r2, %[a]\n\t" + "beq 4f\n\t" + /* Multiply * 2: Start */ + "ldr r6, [%[a]]\n\t" + "ldr r7, [r2]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* Multiply * 2: Done */ + "bal 5f\n\t" + "\n4:\n\t" + /* Square: Start */ + "ldr r6, [%[a]]\n\t" + "umull r6, r7, r6, r6\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* Square: Done */ + "\n5:\n\t" + "add %[a], %[a], #4\n\t" + "sub r2, r2, #4\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, r6, #128\n\t" + "add r6, r6, r9\n\t" + "cmp %[a], r6\n\t" + "beq 3f\n\t" + "cmp %[a], r2\n\t" + "bgt 3f\n\t" + "mov r7, r8\n\t" + "add r7, r7, r9\n\t" + "cmp %[a], r7\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r10\n\t" + "mov r7, r8\n\t" + "str r3, [%[r], r7]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "add r7, r7, #4\n\t" + "mov r8, r7\n\t" + "mov r6, #2\n\t" + "lsl r6, r6, #8\n\t" + "add r6, r6, #248\n\t" + "cmp r7, r6\n\t" + "ble 1b\n\t" + "mov %[a], r9\n\t" + "str r3, [%[r], r7]\n\t" + "mov %[r], r11\n\t" + "mov %[a], r10\n\t" + "mov r3, #2\n\t" + "lsl r3, r3, #8\n\t" + "add r3, r3, #252\n\t" + "\n4:\n\t" + "ldr r6, [%[a], r3]\n\t" + "str r6, [%[r], r3]\n\t" + "subs r3, r3, #4\n\t" + "bge 4b\n\t" + "mov r6, #3\n\t" + "lsl r6, r6, #8\n\t" + "add sp, sp, r6\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11" + ); +} + +#endif /* WOLFSSL_SP_SMALL */ +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +#ifdef WOLFSSL_SP_SMALL +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_3072_mask_48(sp_digit* r, sp_digit* a, sp_digit m) +{ + int i; + + for (i=0; i<48; i++) + r[i] = a[i] & m; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_3072_add_48(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r6, %[a]\n\t" + "mov r7, #0\n\t" + "add r6, r6, #192\n\t" + "sub r7, r7, #1\n\t" + "\n1:\n\t" + "adds %[c], %[c], r7\n\t" + "ldr r4, [%[a]]\n\t" + "ldr r5, [%[b]]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r]]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c], %[c]\n\t" + "add %[a], %[a], #4\n\t" + "add %[b], %[b], #4\n\t" + "add %[r], %[r], #4\n\t" + "cmp %[a], r6\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r7" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +#ifdef WOLFSSL_SP_SMALL +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_3072_mul_48(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit tmp[48 * 2]; + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r8, r3\n\t" + "mov r11, %[r]\n\t" + "mov r9, %[a]\n\t" + "mov r10, %[b]\n\t" + "mov r6, #192\n\t" + "add r6, r6, r9\n\t" + "mov r12, r6\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r5, #0\n\t" + "mov r6, #188\n\t" + "mov %[a], r8\n\t" + "subs %[a], %[a], r6\n\t" + "sbc r6, r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], %[a], r6\n\t" + "mov %[b], r8\n\t" + "sub %[b], %[b], %[a]\n\t" + "add %[a], %[a], r9\n\t" + "add %[b], %[b], r10\n\t" + "\n2:\n\t" + /* Multiply Start */ + "ldr r6, [%[a]]\n\t" + "ldr r7, [%[b]]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* Multiply Done */ + "add %[a], %[a], #4\n\t" + "sub %[b], %[b], #4\n\t" + "cmp %[a], r12\n\t" + "beq 3f\n\t" + "mov r6, r8\n\t" + "add r6, r6, r9\n\t" + "cmp %[a], r6\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r11\n\t" + "mov r7, r8\n\t" + "str r3, [%[r], r7]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "add r7, r7, #4\n\t" + "mov r8, r7\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, r6, #120\n\t" + "cmp r7, r6\n\t" + "ble 1b\n\t" + "str r3, [%[r], r7]\n\t" + "mov %[a], r9\n\t" + "mov %[b], r10\n\t" + : + : [r] "r" (tmp), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12" + ); + + XMEMCPY(r, tmp, sizeof(tmp)); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_3072_sqr_48(sp_digit* r, const sp_digit* a) +{ + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "mov r5, #0\n\t" + "mov r8, r3\n\t" + "mov r11, %[r]\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, r6, #128\n\t" + "neg r6, r6\n\t" + "add sp, sp, r6\n\t" + "mov r10, sp\n\t" + "mov r9, %[a]\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r6, #188\n\t" + "mov %[a], r8\n\t" + "subs %[a], %[a], r6\n\t" + "sbc r6, r6, r6\n\t" + "mvn r6, r6\n\t" + "and %[a], %[a], r6\n\t" + "mov r2, r8\n\t" + "sub r2, r2, %[a]\n\t" + "add %[a], %[a], r9\n\t" + "add r2, r2, r9\n\t" + "\n2:\n\t" + "cmp r2, %[a]\n\t" + "beq 4f\n\t" + /* Multiply * 2: Start */ + "ldr r6, [%[a]]\n\t" + "ldr r7, [r2]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* Multiply * 2: Done */ + "bal 5f\n\t" + "\n4:\n\t" + /* Square: Start */ + "ldr r6, [%[a]]\n\t" + "umull r6, r7, r6, r6\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* Square: Done */ + "\n5:\n\t" + "add %[a], %[a], #4\n\t" + "sub r2, r2, #4\n\t" + "mov r6, #192\n\t" + "add r6, r6, r9\n\t" + "cmp %[a], r6\n\t" + "beq 3f\n\t" + "cmp %[a], r2\n\t" + "bgt 3f\n\t" + "mov r7, r8\n\t" + "add r7, r7, r9\n\t" + "cmp %[a], r7\n\t" + "ble 2b\n\t" + "\n3:\n\t" + "mov %[r], r10\n\t" + "mov r7, r8\n\t" + "str r3, [%[r], r7]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + "add r7, r7, #4\n\t" + "mov r8, r7\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, r6, #120\n\t" + "cmp r7, r6\n\t" + "ble 1b\n\t" + "mov %[a], r9\n\t" + "str r3, [%[r], r7]\n\t" + "mov %[r], r11\n\t" + "mov %[a], r10\n\t" + "mov r3, #1\n\t" + "lsl r3, r3, #8\n\t" + "add r3, r3, #124\n\t" + "\n4:\n\t" + "ldr r6, [%[a], r3]\n\t" + "str r6, [%[r], r3]\n\t" + "subs r3, r3, #4\n\t" + "bge 4b\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, r6, #128\n\t" + "add sp, sp, r6\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11" + ); +} + +#endif /* WOLFSSL_SP_SMALL */ +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +/* Caclulate the bottom digit of -1/a mod 2^n. + * + * a A single precision number. + * rho Bottom word of inverse. + */ +static void sp_3072_mont_setup(sp_digit* a, sp_digit* rho) +{ + sp_digit x, b; + + b = a[0]; + x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ + x *= 2 - b * x; /* here x*a==1 mod 2**8 */ + x *= 2 - b * x; /* here x*a==1 mod 2**16 */ + x *= 2 - b * x; /* here x*a==1 mod 2**32 */ + + /* rho = -1/m mod b */ + *rho = -x; +} + +/* Mul a by digit b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision digit. + */ +SP_NOINLINE static void sp_3072_mul_d_96(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ + __asm__ __volatile__ ( + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, r6, #128\n\t" + "add r6, r6, %[a]\n\t" + "mov r8, %[r]\n\t" + "mov r9, r6\n\t" + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r5, #0\n\t" + /* A[] * B */ + "ldr r6, [%[a]]\n\t" + "umull r6, r7, r6, %[b]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[] * B - Done */ + "mov %[r], r8\n\t" + "str r3, [%[r]]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "add %[r], %[r], #4\n\t" + "add %[a], %[a], #4\n\t" + "mov r8, %[r]\n\t" + "cmp %[a], r9\n\t" + "blt 1b\n\t" + "str r3, [%[r]]\n\t" + : [r] "+r" (r), [a] "+r" (a) + : [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9" + ); +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into a. (a -= b) + * + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_3072_sub_in_place_48(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + __asm__ __volatile__ ( + "mov r7, %[a]\n\t" + "add r7, r7, #192\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "subs r5, r5, %[c]\n\t" + "ldr r3, [%[a]]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b]]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a]]\n\t" + "str r4, [%[a], #4]\n\t" + "sbc %[c], %[c], %[c]\n\t" + "add %[a], %[a], #8\n\t" + "add %[b], %[b], #8\n\t" + "cmp %[a], r7\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6", "r7" + ); + + return c; +} + +#else +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_3072_sub_in_place_48(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r6, [%[b], #4]\n\t" + "subs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #0]\n\t" + "str r4, [%[a], #4]\n\t" + "ldr r3, [%[a], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r6, [%[b], #12]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #8]\n\t" + "str r4, [%[a], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r6, [%[b], #20]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #16]\n\t" + "str r4, [%[a], #20]\n\t" + "ldr r3, [%[a], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r6, [%[b], #28]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #24]\n\t" + "str r4, [%[a], #28]\n\t" + "ldr r3, [%[a], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r6, [%[b], #36]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #32]\n\t" + "str r4, [%[a], #36]\n\t" + "ldr r3, [%[a], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r6, [%[b], #44]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #40]\n\t" + "str r4, [%[a], #44]\n\t" + "ldr r3, [%[a], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #48]\n\t" + "ldr r6, [%[b], #52]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #48]\n\t" + "str r4, [%[a], #52]\n\t" + "ldr r3, [%[a], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #56]\n\t" + "ldr r6, [%[b], #60]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #56]\n\t" + "str r4, [%[a], #60]\n\t" + "ldr r3, [%[a], #64]\n\t" + "ldr r4, [%[a], #68]\n\t" + "ldr r5, [%[b], #64]\n\t" + "ldr r6, [%[b], #68]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #64]\n\t" + "str r4, [%[a], #68]\n\t" + "ldr r3, [%[a], #72]\n\t" + "ldr r4, [%[a], #76]\n\t" + "ldr r5, [%[b], #72]\n\t" + "ldr r6, [%[b], #76]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #72]\n\t" + "str r4, [%[a], #76]\n\t" + "ldr r3, [%[a], #80]\n\t" + "ldr r4, [%[a], #84]\n\t" + "ldr r5, [%[b], #80]\n\t" + "ldr r6, [%[b], #84]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #80]\n\t" + "str r4, [%[a], #84]\n\t" + "ldr r3, [%[a], #88]\n\t" + "ldr r4, [%[a], #92]\n\t" + "ldr r5, [%[b], #88]\n\t" + "ldr r6, [%[b], #92]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #88]\n\t" + "str r4, [%[a], #92]\n\t" + "ldr r3, [%[a], #96]\n\t" + "ldr r4, [%[a], #100]\n\t" + "ldr r5, [%[b], #96]\n\t" + "ldr r6, [%[b], #100]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #96]\n\t" + "str r4, [%[a], #100]\n\t" + "ldr r3, [%[a], #104]\n\t" + "ldr r4, [%[a], #108]\n\t" + "ldr r5, [%[b], #104]\n\t" + "ldr r6, [%[b], #108]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #104]\n\t" + "str r4, [%[a], #108]\n\t" + "ldr r3, [%[a], #112]\n\t" + "ldr r4, [%[a], #116]\n\t" + "ldr r5, [%[b], #112]\n\t" + "ldr r6, [%[b], #116]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #112]\n\t" + "str r4, [%[a], #116]\n\t" + "ldr r3, [%[a], #120]\n\t" + "ldr r4, [%[a], #124]\n\t" + "ldr r5, [%[b], #120]\n\t" + "ldr r6, [%[b], #124]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #120]\n\t" + "str r4, [%[a], #124]\n\t" + "sbc %[c], %[c], %[c]\n\t" + "add %[a], %[a], #0x80\n\t" + "add %[b], %[b], #0x80\n\t" + "mov r5, #0\n\t" + "sub r5, r5, %[c]\n\t" + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #0]\n\t" + "str r4, [%[a], #4]\n\t" + "ldr r3, [%[a], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r6, [%[b], #12]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #8]\n\t" + "str r4, [%[a], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r6, [%[b], #20]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #16]\n\t" + "str r4, [%[a], #20]\n\t" + "ldr r3, [%[a], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r6, [%[b], #28]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #24]\n\t" + "str r4, [%[a], #28]\n\t" + "ldr r3, [%[a], #32]\n\t" + "ldr r4, [%[a], #36]\n\t" + "ldr r5, [%[b], #32]\n\t" + "ldr r6, [%[b], #36]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #32]\n\t" + "str r4, [%[a], #36]\n\t" + "ldr r3, [%[a], #40]\n\t" + "ldr r4, [%[a], #44]\n\t" + "ldr r5, [%[b], #40]\n\t" + "ldr r6, [%[b], #44]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #40]\n\t" + "str r4, [%[a], #44]\n\t" + "ldr r3, [%[a], #48]\n\t" + "ldr r4, [%[a], #52]\n\t" + "ldr r5, [%[b], #48]\n\t" + "ldr r6, [%[b], #52]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #48]\n\t" + "str r4, [%[a], #52]\n\t" + "ldr r3, [%[a], #56]\n\t" + "ldr r4, [%[a], #60]\n\t" + "ldr r5, [%[b], #56]\n\t" + "ldr r6, [%[b], #60]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #56]\n\t" + "str r4, [%[a], #60]\n\t" + "sbc %[c], %[c], %[c]\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* r = 2^n mod m where n is the number of bits to reduce by. + * Given m must be 3072 bits, just need to subtract. + * + * r A single precision number. + * m A signle precision number. + */ +static void sp_3072_mont_norm_48(sp_digit* r, sp_digit* m) +{ + XMEMSET(r, 0, sizeof(sp_digit) * 48); + + /* r = 2^n mod m */ + sp_3072_sub_in_place_48(r, m); +} + +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not copying. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +SP_NOINLINE static sp_digit sp_3072_cond_sub_48(sp_digit* r, sp_digit* a, + sp_digit* b, sp_digit m) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r5, #192\n\t" + "mov r8, r5\n\t" + "mov r7, #0\n\t" + "\n1:\n\t" + "ldr r6, [%[b], r7]\n\t" + "and r6, r6, %[m]\n\t" + "mov r5, #0\n\t" + "subs r5, r5, %[c]\n\t" + "ldr r5, [%[a], r7]\n\t" + "sbcs r5, r5, r6\n\t" + "sbcs %[c], %[c], %[c]\n\t" + "str r5, [%[r], r7]\n\t" + "add r7, r7, #4\n\t" + "cmp r7, r8\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r5", "r6", "r7", "r8" + ); + + return c; +} + +/* Reduce the number back to 3072 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +SP_NOINLINE static void sp_3072_mont_reduce_48(sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "mov r8, %[mp]\n\t" + "mov r12, %[ca]\n\t" + "mov r14, %[m]\n\t" + "mov r9, %[a]\n\t" + "mov r4, #0\n\t" + /* i = 0 */ + "mov r11, r4\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "mov %[ca], #0\n\t" + /* mu = a[i] * mp */ + "mov %[mp], r8\n\t" + "ldr %[a], [%[a]]\n\t" + "mul %[mp], %[mp], %[a]\n\t" + "mov %[m], r14\n\t" + "mov r10, r9\n\t" + "\n2:\n\t" + /* a[i+j] += m[j] * mu */ + "mov %[a], r10\n\t" + "ldr %[a], [%[a]]\n\t" + "mov %[ca], #0\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + /* Multiply m[j] and mu - Start */ + "ldr r7, [%[m]]\n\t" + "umull r6, r7, %[mp], r7\n\t" + "adds %[a], %[a], r6\n\t" + "adcs r5, r5, r7\n\t" + /* Multiply m[j] and mu - Done */ + "adds r4, r4, %[a]\n\t" + "adc r5, r5, %[ca]\n\t" + "mov %[a], r10\n\t" + "str r4, [%[a]]\n\t" + "mov r6, #4\n\t" + "add %[m], %[m], #4\n\t" + "add r10, r10, r6\n\t" + "mov r4, #188\n\t" + "add r4, r4, r9\n\t" + "cmp r10, r4\n\t" + "blt 2b\n\t" + /* a[i+47] += m[47] * mu */ + "mov %[ca], #0\n\t" + "mov r4, r12\n\t" + "mov %[a], #0\n\t" + /* Multiply m[47] and mu - Start */ + "ldr r7, [%[m]]\n\t" + "umull r6, r7, %[mp], r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc %[a], %[a], %[ca]\n\t" + /* Multiply m[47] and mu - Done */ + "mov %[ca], %[a]\n\t" + "mov %[a], r10\n\t" + "ldr r7, [%[a], #4]\n\t" + "ldr %[a], [%[a]]\n\t" + "mov r6, #0\n\t" + "adds r5, r5, %[a]\n\t" + "adcs r7, r7, r4\n\t" + "adc %[ca], %[ca], r6\n\t" + "mov %[a], r10\n\t" + "str r5, [%[a]]\n\t" + "str r7, [%[a], #4]\n\t" + /* i += 1 */ + "mov r6, #4\n\t" + "add r9, r9, r6\n\t" + "add r11, r11, r6\n\t" + "mov r12, %[ca]\n\t" + "mov %[a], r9\n\t" + "mov r4, #192\n\t" + "cmp r11, r4\n\t" + "blt 1b\n\t" + "mov %[m], r14\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14" + ); + + sp_3072_cond_sub_48(a - 48, a, m, (sp_digit)0 - ca); +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_3072_mont_mul_48(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_3072_mul_48(r, a, b); + sp_3072_mont_reduce_48(r, m, mp); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_3072_mont_sqr_48(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_3072_sqr_48(r, a); + sp_3072_mont_reduce_48(r, m, mp); +} + +/* Mul a by digit b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision digit. + */ +SP_NOINLINE static void sp_3072_mul_d_48(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ + __asm__ __volatile__ ( + "mov r6, #192\n\t" + "add r6, r6, %[a]\n\t" + "mov r8, %[r]\n\t" + "mov r9, r6\n\t" + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r5, #0\n\t" + /* A[] * B */ + "ldr r6, [%[a]]\n\t" + "umull r6, r7, r6, %[b]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[] * B - Done */ + "mov %[r], r8\n\t" + "str r3, [%[r]]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "add %[r], %[r], #4\n\t" + "add %[a], %[a], #4\n\t" + "mov r8, %[r]\n\t" + "cmp %[a], r9\n\t" + "blt 1b\n\t" + "str r3, [%[r]]\n\t" + : [r] "+r" (r), [a] "+r" (a) + : [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9" + ); +} + +/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) + * + * d1 The high order half of the number to divide. + * d0 The low order half of the number to divide. + * div The dividend. + * returns the result of the division. + * + * Note that this is an approximate div. It may give an answer 1 larger. + */ +SP_NOINLINE static sp_digit div_3072_word_48(sp_digit d1, sp_digit d0, + sp_digit div) +{ + sp_digit r = 0; + + __asm__ __volatile__ ( + "lsr r6, %[div], #16\n\t" + "add r6, r6, #1\n\t" + "udiv r4, %[d1], r6\n\t" + "lsl r7, r4, #16\n\t" + "umull r4, r5, %[div], r7\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "udiv r5, %[d1], r6\n\t" + "lsl r4, r5, #16\n\t" + "add r7, r7, r4\n\t" + "umull r4, r5, %[div], r4\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "lsl r4, %[d1], #16\n\t" + "orr r4, r4, %[d0], lsr 16\n\t" + "udiv r4, r4, r6\n\t" + "add r7, r7, r4\n\t" + "umull r4, r5, %[div], r4\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "lsl r4, %[d1], #16\n\t" + "orr r4, r4, %[d0], lsr 16\n\t" + "udiv r4, r4, r6\n\t" + "add r7, r7, r4\n\t" + "umull r4, r5, %[div], r4\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "udiv r4, %[d0], %[div]\n\t" + "add r7, r7, r4\n\t" + "mov %[r], r7\n\t" + : [r] "+r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "r4", "r5", "r6", "r7" + ); + return r; +} + +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +SP_NOINLINE static int32_t sp_3072_cmp_48(sp_digit* a, sp_digit* b) +{ + sp_digit r = 0; + + + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mvn r3, r3\n\t" + "mov r6, #188\n\t" + "\n1:\n\t" + "ldr r7, [%[a], r6]\n\t" + "ldr r5, [%[b], r6]\n\t" + "and r7, r7, r3\n\t" + "and r5, r5, r3\n\t" + "mov r4, r7\n\t" + "subs r7, r7, r5\n\t" + "sbc r7, r7, r7\n\t" + "add %[r], %[r], r7\n\t" + "mvn r7, r7\n\t" + "and r3, r3, r7\n\t" + "subs r5, r5, r4\n\t" + "sbc r7, r7, r7\n\t" + "sub %[r], %[r], r7\n\t" + "mvn r7, r7\n\t" + "and r3, r3, r7\n\t" + "sub r6, r6, #4\n\t" + "cmp r6, #0\n\t" + "bge 1b\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "r3", "r4", "r5", "r6", "r7" + ); + + return r; +} + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_3072_div_48(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[96], t2[49]; + sp_digit div, r1; + int i; + + (void)m; + + div = d[47]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 48); + for (i=47; i>=0; i--) { + r1 = div_3072_word_48(t1[48 + i], t1[48 + i - 1], div); + + sp_3072_mul_d_48(t2, d, r1); + t1[48 + i] += sp_3072_sub_in_place_48(&t1[i], t2); + t1[48 + i] -= t2[48]; + sp_3072_mask_48(t2, d, t1[48 + i]); + t1[48 + i] += sp_3072_add_48(&t1[i], &t1[i], t2); + sp_3072_mask_48(t2, d, t1[48 + i]); + t1[48 + i] += sp_3072_add_48(&t1[i], &t1[i], t2); + } + + r1 = sp_3072_cmp_48(t1, d) >= 0; + sp_3072_cond_sub_48(r, t1, d, (sp_digit)0 - r1); + + return MP_OKAY; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_3072_mod_48(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_3072_div_48(a, m, NULL, r); +} + +#ifdef WOLFSSL_SP_SMALL +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_3072_mod_exp_48(sp_digit* r, sp_digit* a, sp_digit* e, + int bits, sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[16][96]; +#else + sp_digit* t[16]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 96, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<16; i++) + t[i] = td + i * 96; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_48(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 48); + if (reduceA) { + err = sp_3072_mod_48(t[1] + 48, a, m); + if (err == MP_OKAY) + err = sp_3072_mod_48(t[1], t[1], m); + } + else { + XMEMCPY(t[1] + 48, a, sizeof(sp_digit) * 48); + err = sp_3072_mod_48(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_3072_mont_sqr_48(t[ 2], t[ 1], m, mp); + sp_3072_mont_mul_48(t[ 3], t[ 2], t[ 1], m, mp); + sp_3072_mont_sqr_48(t[ 4], t[ 2], m, mp); + sp_3072_mont_mul_48(t[ 5], t[ 3], t[ 2], m, mp); + sp_3072_mont_sqr_48(t[ 6], t[ 3], m, mp); + sp_3072_mont_mul_48(t[ 7], t[ 4], t[ 3], m, mp); + sp_3072_mont_sqr_48(t[ 8], t[ 4], m, mp); + sp_3072_mont_mul_48(t[ 9], t[ 5], t[ 4], m, mp); + sp_3072_mont_sqr_48(t[10], t[ 5], m, mp); + sp_3072_mont_mul_48(t[11], t[ 6], t[ 5], m, mp); + sp_3072_mont_sqr_48(t[12], t[ 6], m, mp); + sp_3072_mont_mul_48(t[13], t[ 7], t[ 6], m, mp); + sp_3072_mont_sqr_48(t[14], t[ 7], m, mp); + sp_3072_mont_mul_48(t[15], t[ 8], t[ 7], m, mp); + + i = (bits - 1) / 32; + n = e[i--]; + y = n >> 28; + n <<= 4; + c = 28; + XMEMCPY(r, t[y], sizeof(sp_digit) * 48); + for (; i>=0 || c>=4; ) { + if (c == 0) { + n = e[i--]; + y = n >> 28; + n <<= 4; + c = 28; + } + else if (c < 4) { + y = n >> 28; + n = e[i--]; + c = 4 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 28) & 0xf; + n <<= 4; + c -= 4; + } + + sp_3072_mont_sqr_48(r, r, m, mp); + sp_3072_mont_sqr_48(r, r, m, mp); + sp_3072_mont_sqr_48(r, r, m, mp); + sp_3072_mont_sqr_48(r, r, m, mp); + + sp_3072_mont_mul_48(r, r, t[y], m, mp); + } + y = e[0] & ((1 << c) - 1); + for (; c > 0; c--) + sp_3072_mont_sqr_48(r, r, m, mp); + sp_3072_mont_mul_48(r, r, t[y], m, mp); + + XMEMSET(&r[48], 0, sizeof(sp_digit) * 48); + sp_3072_mont_reduce_48(r, m, mp); + + mask = 0 - (sp_3072_cmp_48(r, m) >= 0); + sp_3072_cond_sub_48(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#else +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_3072_mod_exp_48(sp_digit* r, sp_digit* a, sp_digit* e, + int bits, sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][96]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 96, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<32; i++) + t[i] = td + i * 96; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_48(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 48); + if (reduceA) { + err = sp_3072_mod_48(t[1] + 48, a, m); + if (err == MP_OKAY) + err = sp_3072_mod_48(t[1], t[1], m); + } + else { + XMEMCPY(t[1] + 48, a, sizeof(sp_digit) * 48); + err = sp_3072_mod_48(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_3072_mont_sqr_48(t[ 2], t[ 1], m, mp); + sp_3072_mont_mul_48(t[ 3], t[ 2], t[ 1], m, mp); + sp_3072_mont_sqr_48(t[ 4], t[ 2], m, mp); + sp_3072_mont_mul_48(t[ 5], t[ 3], t[ 2], m, mp); + sp_3072_mont_sqr_48(t[ 6], t[ 3], m, mp); + sp_3072_mont_mul_48(t[ 7], t[ 4], t[ 3], m, mp); + sp_3072_mont_sqr_48(t[ 8], t[ 4], m, mp); + sp_3072_mont_mul_48(t[ 9], t[ 5], t[ 4], m, mp); + sp_3072_mont_sqr_48(t[10], t[ 5], m, mp); + sp_3072_mont_mul_48(t[11], t[ 6], t[ 5], m, mp); + sp_3072_mont_sqr_48(t[12], t[ 6], m, mp); + sp_3072_mont_mul_48(t[13], t[ 7], t[ 6], m, mp); + sp_3072_mont_sqr_48(t[14], t[ 7], m, mp); + sp_3072_mont_mul_48(t[15], t[ 8], t[ 7], m, mp); + sp_3072_mont_sqr_48(t[16], t[ 8], m, mp); + sp_3072_mont_mul_48(t[17], t[ 9], t[ 8], m, mp); + sp_3072_mont_sqr_48(t[18], t[ 9], m, mp); + sp_3072_mont_mul_48(t[19], t[10], t[ 9], m, mp); + sp_3072_mont_sqr_48(t[20], t[10], m, mp); + sp_3072_mont_mul_48(t[21], t[11], t[10], m, mp); + sp_3072_mont_sqr_48(t[22], t[11], m, mp); + sp_3072_mont_mul_48(t[23], t[12], t[11], m, mp); + sp_3072_mont_sqr_48(t[24], t[12], m, mp); + sp_3072_mont_mul_48(t[25], t[13], t[12], m, mp); + sp_3072_mont_sqr_48(t[26], t[13], m, mp); + sp_3072_mont_mul_48(t[27], t[14], t[13], m, mp); + sp_3072_mont_sqr_48(t[28], t[14], m, mp); + sp_3072_mont_mul_48(t[29], t[15], t[14], m, mp); + sp_3072_mont_sqr_48(t[30], t[15], m, mp); + sp_3072_mont_mul_48(t[31], t[16], t[15], m, mp); + + i = (bits - 1) / 32; + n = e[i--]; + y = n >> 27; + n <<= 5; + c = 27; + XMEMCPY(r, t[y], sizeof(sp_digit) * 48); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 27; + n <<= 5; + c = 27; + } + else if (c < 5) { + y = n >> 27; + n = e[i--]; + c = 5 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 27) & 0x1f; + n <<= 5; + c -= 5; + } + + sp_3072_mont_sqr_48(r, r, m, mp); + sp_3072_mont_sqr_48(r, r, m, mp); + sp_3072_mont_sqr_48(r, r, m, mp); + sp_3072_mont_sqr_48(r, r, m, mp); + sp_3072_mont_sqr_48(r, r, m, mp); + + sp_3072_mont_mul_48(r, r, t[y], m, mp); + } + y = e[0] & ((1 << c) - 1); + for (; c > 0; c--) + sp_3072_mont_sqr_48(r, r, m, mp); + sp_3072_mont_mul_48(r, r, t[y], m, mp); + + XMEMSET(&r[48], 0, sizeof(sp_digit) * 48); + sp_3072_mont_reduce_48(r, m, mp); + + mask = 0 - (sp_3072_cmp_48(r, m) >= 0); + sp_3072_cond_sub_48(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#endif /* WOLFSSL_SP_SMALL */ + +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) +/* r = 2^n mod m where n is the number of bits to reduce by. + * Given m must be 3072 bits, just need to subtract. + * + * r A single precision number. + * m A signle precision number. + */ +static void sp_3072_mont_norm_96(sp_digit* r, sp_digit* m) +{ + XMEMSET(r, 0, sizeof(sp_digit) * 96); + + /* r = 2^n mod m */ + sp_3072_sub_in_place_96(r, m); +} + +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not copying. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +SP_NOINLINE static sp_digit sp_3072_cond_sub_96(sp_digit* r, sp_digit* a, + sp_digit* b, sp_digit m) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r5, #1\n\t" + "lsl r5, r5, #8\n\t" + "add r5, r5, #128\n\t" + "mov r8, r5\n\t" + "mov r7, #0\n\t" + "\n1:\n\t" + "ldr r6, [%[b], r7]\n\t" + "and r6, r6, %[m]\n\t" + "mov r5, #0\n\t" + "subs r5, r5, %[c]\n\t" + "ldr r5, [%[a], r7]\n\t" + "sbcs r5, r5, r6\n\t" + "sbcs %[c], %[c], %[c]\n\t" + "str r5, [%[r], r7]\n\t" + "add r7, r7, #4\n\t" + "cmp r7, r8\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r5", "r6", "r7", "r8" + ); + + return c; +} + +/* Reduce the number back to 3072 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +SP_NOINLINE static void sp_3072_mont_reduce_96(sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "mov r8, %[mp]\n\t" + "mov r12, %[ca]\n\t" + "mov r14, %[m]\n\t" + "mov r9, %[a]\n\t" + "mov r4, #0\n\t" + /* i = 0 */ + "mov r11, r4\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "mov %[ca], #0\n\t" + /* mu = a[i] * mp */ + "mov %[mp], r8\n\t" + "ldr %[a], [%[a]]\n\t" + "mul %[mp], %[mp], %[a]\n\t" + "mov %[m], r14\n\t" + "mov r10, r9\n\t" + "\n2:\n\t" + /* a[i+j] += m[j] * mu */ + "mov %[a], r10\n\t" + "ldr %[a], [%[a]]\n\t" + "mov %[ca], #0\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + /* Multiply m[j] and mu - Start */ + "ldr r7, [%[m]]\n\t" + "umull r6, r7, %[mp], r7\n\t" + "adds %[a], %[a], r6\n\t" + "adcs r5, r5, r7\n\t" + /* Multiply m[j] and mu - Done */ + "adds r4, r4, %[a]\n\t" + "adc r5, r5, %[ca]\n\t" + "mov %[a], r10\n\t" + "str r4, [%[a]]\n\t" + "mov r6, #4\n\t" + "add %[m], %[m], #4\n\t" + "add r10, r10, r6\n\t" + "mov r4, #1\n\t" + "lsl r4, r4, #8\n\t" + "add r4, r4, #124\n\t" + "add r4, r4, r9\n\t" + "cmp r10, r4\n\t" + "blt 2b\n\t" + /* a[i+95] += m[95] * mu */ + "mov %[ca], #0\n\t" + "mov r4, r12\n\t" + "mov %[a], #0\n\t" + /* Multiply m[95] and mu - Start */ + "ldr r7, [%[m]]\n\t" + "umull r6, r7, %[mp], r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc %[a], %[a], %[ca]\n\t" + /* Multiply m[95] and mu - Done */ + "mov %[ca], %[a]\n\t" + "mov %[a], r10\n\t" + "ldr r7, [%[a], #4]\n\t" + "ldr %[a], [%[a]]\n\t" + "mov r6, #0\n\t" + "adds r5, r5, %[a]\n\t" + "adcs r7, r7, r4\n\t" + "adc %[ca], %[ca], r6\n\t" + "mov %[a], r10\n\t" + "str r5, [%[a]]\n\t" + "str r7, [%[a], #4]\n\t" + /* i += 1 */ + "mov r6, #4\n\t" + "add r9, r9, r6\n\t" + "add r11, r11, r6\n\t" + "mov r12, %[ca]\n\t" + "mov %[a], r9\n\t" + "mov r4, #1\n\t" + "lsl r4, r4, #8\n\t" + "add r4, r4, #128\n\t" + "cmp r11, r4\n\t" + "blt 1b\n\t" + "mov %[m], r14\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14" + ); + + sp_3072_cond_sub_96(a - 96, a, m, (sp_digit)0 - ca); +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_3072_mont_mul_96(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_3072_mul_96(r, a, b); + sp_3072_mont_reduce_96(r, m, mp); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_3072_mont_sqr_96(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_3072_sqr_96(r, a); + sp_3072_mont_reduce_96(r, m, mp); +} + +/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) + * + * d1 The high order half of the number to divide. + * d0 The low order half of the number to divide. + * div The dividend. + * returns the result of the division. + * + * Note that this is an approximate div. It may give an answer 1 larger. + */ +SP_NOINLINE static sp_digit div_3072_word_96(sp_digit d1, sp_digit d0, + sp_digit div) +{ + sp_digit r = 0; + + __asm__ __volatile__ ( + "lsr r6, %[div], #16\n\t" + "add r6, r6, #1\n\t" + "udiv r4, %[d1], r6\n\t" + "lsl r7, r4, #16\n\t" + "umull r4, r5, %[div], r7\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "udiv r5, %[d1], r6\n\t" + "lsl r4, r5, #16\n\t" + "add r7, r7, r4\n\t" + "umull r4, r5, %[div], r4\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "lsl r4, %[d1], #16\n\t" + "orr r4, r4, %[d0], lsr 16\n\t" + "udiv r4, r4, r6\n\t" + "add r7, r7, r4\n\t" + "umull r4, r5, %[div], r4\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "lsl r4, %[d1], #16\n\t" + "orr r4, r4, %[d0], lsr 16\n\t" + "udiv r4, r4, r6\n\t" + "add r7, r7, r4\n\t" + "umull r4, r5, %[div], r4\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "udiv r4, %[d0], %[div]\n\t" + "add r7, r7, r4\n\t" + "mov %[r], r7\n\t" + : [r] "+r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "r4", "r5", "r6", "r7" + ); + return r; +} + +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_3072_mask_96(sp_digit* r, sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<96; i++) + r[i] = a[i] & m; +#else + int i; + + for (i = 0; i < 96; i += 8) { + r[i+0] = a[i+0] & m; + r[i+1] = a[i+1] & m; + r[i+2] = a[i+2] & m; + r[i+3] = a[i+3] & m; + r[i+4] = a[i+4] & m; + r[i+5] = a[i+5] & m; + r[i+6] = a[i+6] & m; + r[i+7] = a[i+7] & m; + } +#endif +} + +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +SP_NOINLINE static int32_t sp_3072_cmp_96(sp_digit* a, sp_digit* b) +{ + sp_digit r = 0; + + + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mvn r3, r3\n\t" + "mov r6, #1\n\t" + "lsl r6, r6, #8\n\t" + "add r6, r6, #124\n\t" + "\n1:\n\t" + "ldr r7, [%[a], r6]\n\t" + "ldr r5, [%[b], r6]\n\t" + "and r7, r7, r3\n\t" + "and r5, r5, r3\n\t" + "mov r4, r7\n\t" + "subs r7, r7, r5\n\t" + "sbc r7, r7, r7\n\t" + "add %[r], %[r], r7\n\t" + "mvn r7, r7\n\t" + "and r3, r3, r7\n\t" + "subs r5, r5, r4\n\t" + "sbc r7, r7, r7\n\t" + "sub %[r], %[r], r7\n\t" + "mvn r7, r7\n\t" + "and r3, r3, r7\n\t" + "sub r6, r6, #4\n\t" + "cmp r6, #0\n\t" + "bge 1b\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "r3", "r4", "r5", "r6", "r7" + ); + + return r; +} + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_3072_div_96(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[192], t2[97]; + sp_digit div, r1; + int i; + + (void)m; + + div = d[95]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 96); + for (i=95; i>=0; i--) { + r1 = div_3072_word_96(t1[96 + i], t1[96 + i - 1], div); + + sp_3072_mul_d_96(t2, d, r1); + t1[96 + i] += sp_3072_sub_in_place_96(&t1[i], t2); + t1[96 + i] -= t2[96]; + sp_3072_mask_96(t2, d, t1[96 + i]); + t1[96 + i] += sp_3072_add_96(&t1[i], &t1[i], t2); + sp_3072_mask_96(t2, d, t1[96 + i]); + t1[96 + i] += sp_3072_add_96(&t1[i], &t1[i], t2); + } + + r1 = sp_3072_cmp_96(t1, d) >= 0; + sp_3072_cond_sub_96(r, t1, d, (sp_digit)0 - r1); + + return MP_OKAY; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_3072_mod_96(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_3072_div_96(a, m, NULL, r); +} + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_3072_div_96_cond(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[192], t2[97]; + sp_digit div, r1; + int i; + + (void)m; + + div = d[95]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 96); + for (i=95; i>=0; i--) { + r1 = div_3072_word_96(t1[96 + i], t1[96 + i - 1], div); + + sp_3072_mul_d_96(t2, d, r1); + t1[96 + i] += sp_3072_sub_in_place_96(&t1[i], t2); + t1[96 + i] -= t2[96]; + if (t1[96 + i] != 0) { + t1[96 + i] += sp_3072_add_96(&t1[i], &t1[i], d); + if (t1[96 + i] != 0) + t1[96 + i] += sp_3072_add_96(&t1[i], &t1[i], d); + } + } + + r1 = sp_3072_cmp_96(t1, d) >= 0; + sp_3072_cond_sub_96(r, t1, d, (sp_digit)0 - r1); + + return MP_OKAY; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_3072_mod_96_cond(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_3072_div_96_cond(a, m, NULL, r); +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \ + defined(WOLFSSL_HAVE_SP_DH) +#ifdef WOLFSSL_SP_SMALL +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_3072_mod_exp_96(sp_digit* r, sp_digit* a, sp_digit* e, + int bits, sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[16][192]; +#else + sp_digit* t[16]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 192, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<16; i++) + t[i] = td + i * 192; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_96(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 96); + if (reduceA) { + err = sp_3072_mod_96(t[1] + 96, a, m); + if (err == MP_OKAY) + err = sp_3072_mod_96(t[1], t[1], m); + } + else { + XMEMCPY(t[1] + 96, a, sizeof(sp_digit) * 96); + err = sp_3072_mod_96(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_3072_mont_sqr_96(t[ 2], t[ 1], m, mp); + sp_3072_mont_mul_96(t[ 3], t[ 2], t[ 1], m, mp); + sp_3072_mont_sqr_96(t[ 4], t[ 2], m, mp); + sp_3072_mont_mul_96(t[ 5], t[ 3], t[ 2], m, mp); + sp_3072_mont_sqr_96(t[ 6], t[ 3], m, mp); + sp_3072_mont_mul_96(t[ 7], t[ 4], t[ 3], m, mp); + sp_3072_mont_sqr_96(t[ 8], t[ 4], m, mp); + sp_3072_mont_mul_96(t[ 9], t[ 5], t[ 4], m, mp); + sp_3072_mont_sqr_96(t[10], t[ 5], m, mp); + sp_3072_mont_mul_96(t[11], t[ 6], t[ 5], m, mp); + sp_3072_mont_sqr_96(t[12], t[ 6], m, mp); + sp_3072_mont_mul_96(t[13], t[ 7], t[ 6], m, mp); + sp_3072_mont_sqr_96(t[14], t[ 7], m, mp); + sp_3072_mont_mul_96(t[15], t[ 8], t[ 7], m, mp); + + i = (bits - 1) / 32; + n = e[i--]; + y = n >> 28; + n <<= 4; + c = 28; + XMEMCPY(r, t[y], sizeof(sp_digit) * 96); + for (; i>=0 || c>=4; ) { + if (c == 0) { + n = e[i--]; + y = n >> 28; + n <<= 4; + c = 28; + } + else if (c < 4) { + y = n >> 28; + n = e[i--]; + c = 4 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 28) & 0xf; + n <<= 4; + c -= 4; + } + + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + + sp_3072_mont_mul_96(r, r, t[y], m, mp); + } + y = e[0] & ((1 << c) - 1); + for (; c > 0; c--) + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_mul_96(r, r, t[y], m, mp); + + XMEMSET(&r[96], 0, sizeof(sp_digit) * 96); + sp_3072_mont_reduce_96(r, m, mp); + + mask = 0 - (sp_3072_cmp_96(r, m) >= 0); + sp_3072_cond_sub_96(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#else +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_3072_mod_exp_96(sp_digit* r, sp_digit* a, sp_digit* e, + int bits, sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][192]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 192, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<32; i++) + t[i] = td + i * 192; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_96(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 96); + if (reduceA) { + err = sp_3072_mod_96(t[1] + 96, a, m); + if (err == MP_OKAY) + err = sp_3072_mod_96(t[1], t[1], m); + } + else { + XMEMCPY(t[1] + 96, a, sizeof(sp_digit) * 96); + err = sp_3072_mod_96(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_3072_mont_sqr_96(t[ 2], t[ 1], m, mp); + sp_3072_mont_mul_96(t[ 3], t[ 2], t[ 1], m, mp); + sp_3072_mont_sqr_96(t[ 4], t[ 2], m, mp); + sp_3072_mont_mul_96(t[ 5], t[ 3], t[ 2], m, mp); + sp_3072_mont_sqr_96(t[ 6], t[ 3], m, mp); + sp_3072_mont_mul_96(t[ 7], t[ 4], t[ 3], m, mp); + sp_3072_mont_sqr_96(t[ 8], t[ 4], m, mp); + sp_3072_mont_mul_96(t[ 9], t[ 5], t[ 4], m, mp); + sp_3072_mont_sqr_96(t[10], t[ 5], m, mp); + sp_3072_mont_mul_96(t[11], t[ 6], t[ 5], m, mp); + sp_3072_mont_sqr_96(t[12], t[ 6], m, mp); + sp_3072_mont_mul_96(t[13], t[ 7], t[ 6], m, mp); + sp_3072_mont_sqr_96(t[14], t[ 7], m, mp); + sp_3072_mont_mul_96(t[15], t[ 8], t[ 7], m, mp); + sp_3072_mont_sqr_96(t[16], t[ 8], m, mp); + sp_3072_mont_mul_96(t[17], t[ 9], t[ 8], m, mp); + sp_3072_mont_sqr_96(t[18], t[ 9], m, mp); + sp_3072_mont_mul_96(t[19], t[10], t[ 9], m, mp); + sp_3072_mont_sqr_96(t[20], t[10], m, mp); + sp_3072_mont_mul_96(t[21], t[11], t[10], m, mp); + sp_3072_mont_sqr_96(t[22], t[11], m, mp); + sp_3072_mont_mul_96(t[23], t[12], t[11], m, mp); + sp_3072_mont_sqr_96(t[24], t[12], m, mp); + sp_3072_mont_mul_96(t[25], t[13], t[12], m, mp); + sp_3072_mont_sqr_96(t[26], t[13], m, mp); + sp_3072_mont_mul_96(t[27], t[14], t[13], m, mp); + sp_3072_mont_sqr_96(t[28], t[14], m, mp); + sp_3072_mont_mul_96(t[29], t[15], t[14], m, mp); + sp_3072_mont_sqr_96(t[30], t[15], m, mp); + sp_3072_mont_mul_96(t[31], t[16], t[15], m, mp); + + i = (bits - 1) / 32; + n = e[i--]; + y = n >> 27; + n <<= 5; + c = 27; + XMEMCPY(r, t[y], sizeof(sp_digit) * 96); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 27; + n <<= 5; + c = 27; + } + else if (c < 5) { + y = n >> 27; + n = e[i--]; + c = 5 - c; + y |= n >> (32 - c); + n <<= c; + c = 32 - c; + } + else { + y = (n >> 27) & 0x1f; + n <<= 5; + c -= 5; + } + + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_sqr_96(r, r, m, mp); + + sp_3072_mont_mul_96(r, r, t[y], m, mp); + } + y = e[0] & ((1 << c) - 1); + for (; c > 0; c--) + sp_3072_mont_sqr_96(r, r, m, mp); + sp_3072_mont_mul_96(r, r, t[y], m, mp); + + XMEMSET(&r[96], 0, sizeof(sp_digit) * 96); + sp_3072_mont_reduce_96(r, m, mp); + + mask = 0 - (sp_3072_cmp_96(r, m) >= 0); + sp_3072_cond_sub_96(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#endif /* WOLFSSL_SP_SMALL */ +#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ + +#ifdef WOLFSSL_HAVE_SP_RSA +/* RSA public key operation. + * + * in Array of bytes representing the number to exponentiate, base. + * inLen Number of bytes in base. + * em Public exponent. + * mm Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 384 bytes long. + * outLen Number of bytes in result. + * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when + * an array is too long and MEMORY_E when dynamic memory allocation fails. + */ +int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm, + byte* out, word32* outLen) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit ad[192], md[96], rd[192]; +#else + sp_digit* d = NULL; +#endif + sp_digit* a; + sp_digit *ah; + sp_digit* m; + sp_digit* r; + sp_digit e[1]; + int err = MP_OKAY; + + if (*outLen < 384) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(em) > 32 || inLen > 384 || + mp_count_bits(mm) != 3072)) + err = MP_READ_E; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 96 * 5, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + a = d; + r = a + 96 * 2; + m = r + 96 * 2; + ah = a + 96; + } +#else + a = ad; + m = md; + r = rd; + ah = a + 96; +#endif + + if (err == MP_OKAY) { + sp_3072_from_bin(ah, 96, in, inLen); +#if DIGIT_BIT >= 32 + e[0] = em->dp[0]; +#else + e[0] = em->dp[0]; + if (em->used > 1) + e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT; +#endif + if (e[0] == 0) + err = MP_EXPTMOD_E; + } + if (err == MP_OKAY) { + sp_3072_from_mp(m, 96, mm); + + if (e[0] == 0x3) { + if (err == MP_OKAY) { + sp_3072_sqr_96(r, ah); + err = sp_3072_mod_96_cond(r, r, m); + } + if (err == MP_OKAY) { + sp_3072_mul_96(r, ah, r); + err = sp_3072_mod_96_cond(r, r, m); + } + } + else { + int i; + sp_digit mp; + + sp_3072_mont_setup(m, &mp); + + /* Convert to Montgomery form. */ + XMEMSET(a, 0, sizeof(sp_digit) * 96); + err = sp_3072_mod_96_cond(a, a, m); + + if (err == MP_OKAY) { + for (i=31; i>=0; i--) + if (e[0] >> i) + break; + + XMEMCPY(r, a, sizeof(sp_digit) * 96); + for (i--; i>=0; i--) { + sp_3072_mont_sqr_96(r, r, m, mp); + if (((e[0] >> i) & 1) == 1) + sp_3072_mont_mul_96(r, r, a, m, mp); + } + XMEMSET(&r[96], 0, sizeof(sp_digit) * 96); + sp_3072_mont_reduce_96(r, m, mp); + + for (i = 95; i > 0; i--) { + if (r[i] != m[i]) + break; + } + if (r[i] >= m[i]) + sp_3072_sub_in_place_96(r, m); + } + } + } + + if (err == MP_OKAY) { + sp_3072_to_bin(r, out); + *outLen = 384; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_RSA); +#endif + + return err; +} + +/* RSA private key operation. + * + * in Array of bytes representing the number to exponentiate, base. + * inLen Number of bytes in base. + * dm Private exponent. + * pm First prime. + * qm Second prime. + * dpm First prime's CRT exponent. + * dqm Second prime's CRT exponent. + * qim Inverse of second prime mod p. + * mm Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 384 bytes long. + * outLen Number of bytes in result. + * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when + * an array is too long and MEMORY_E when dynamic memory allocation fails. + */ +int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, + mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm, + byte* out, word32* outLen) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit ad[96 * 2]; + sp_digit pd[48], qd[48], dpd[48]; + sp_digit tmpad[96], tmpbd[96]; +#else + sp_digit* t = NULL; +#endif + sp_digit* a; + sp_digit* p; + sp_digit* q; + sp_digit* dp; + sp_digit* dq; + sp_digit* qi; + sp_digit* tmp; + sp_digit* tmpa; + sp_digit* tmpb; + sp_digit* r; + sp_digit c; + int err = MP_OKAY; + + (void)dm; + (void)mm; + + if (*outLen < 384) + err = MP_TO_E; + if (err == MP_OKAY && (inLen > 384 || mp_count_bits(mm) != 3072)) + err = MP_READ_E; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 48 * 11, NULL, + DYNAMIC_TYPE_RSA); + if (t == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + a = t; + p = a + 96 * 2; + q = p + 48; + qi = dq = dp = q + 48; + tmpa = qi + 48; + tmpb = tmpa + 96; + + tmp = t; + r = tmp + 96; + } +#else + r = a = ad; + p = pd; + q = qd; + qi = dq = dp = dpd; + tmpa = tmpad; + tmpb = tmpbd; + tmp = a + 96; +#endif + + if (err == MP_OKAY) { + sp_3072_from_bin(a, 96, in, inLen); + sp_3072_from_mp(p, 48, pm); + sp_3072_from_mp(q, 48, qm); + sp_3072_from_mp(dp, 48, dpm); + + err = sp_3072_mod_exp_48(tmpa, a, dp, 1536, p, 1); + } + if (err == MP_OKAY) { + sp_3072_from_mp(dq, 48, dqm); + err = sp_3072_mod_exp_48(tmpb, a, dq, 1536, q, 1); + } + + if (err == MP_OKAY) { + c = sp_3072_sub_in_place_48(tmpa, tmpb); + sp_3072_mask_48(tmp, p, c); + sp_3072_add_48(tmpa, tmpa, tmp); + + sp_3072_from_mp(qi, 48, qim); + sp_3072_mul_48(tmpa, tmpa, qi); + err = sp_3072_mod_48(tmpa, tmpa, p); + } + + if (err == MP_OKAY) { + sp_3072_mul_48(tmpa, q, tmpa); + XMEMSET(&tmpb[48], 0, sizeof(sp_digit) * 48); + sp_3072_add_96(r, tmpb, tmpa); + + sp_3072_to_bin(r, out); + *outLen = 384; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_digit) * 48 * 11); + XFREE(t, NULL, DYNAMIC_TYPE_RSA); + } +#else + XMEMSET(tmpad, 0, sizeof(tmpad)); + XMEMSET(tmpbd, 0, sizeof(tmpbd)); + XMEMSET(pd, 0, sizeof(pd)); + XMEMSET(qd, 0, sizeof(qd)); + XMEMSET(dpd, 0, sizeof(dpd)); +#endif + + return err; +} +#endif /* WOLFSSL_HAVE_SP_RSA */ +#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \ + !defined(WOLFSSL_RSA_PUBLIC_ONLY)) +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_3072_to_mp(sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (3072 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { +#if DIGIT_BIT == 32 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 96); + r->used = 96; + mp_clamp(r); +#elif DIGIT_BIT < 32 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 96; i++) { + r->dp[j] |= a[i] << s; + r->dp[j] &= (1l << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + while (s + DIGIT_BIT <= 32) { + s += DIGIT_BIT; + r->dp[j] &= (1l << DIGIT_BIT) - 1; + r->dp[++j] = a[i] >> s; + } + s = 32 - s; + } + r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 96; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 32 >= DIGIT_BIT) { + #if DIGIT_BIT < 32 + r->dp[j] &= (1l << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 32 - s; + } + else + s += 32; + } + r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returs 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ + int err = MP_OKAY; + sp_digit b[192], e[96], m[96]; + sp_digit* r = b; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 3072 || expBits > 3072 || + mp_count_bits(mod) != 3072) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + sp_3072_from_mp(b, 96, base); + sp_3072_from_mp(e, 96, exp); + sp_3072_from_mp(m, 96, mod); + + err = sp_3072_mod_exp_96(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + err = sp_3072_to_mp(r, res); + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} + +#ifdef WOLFSSL_HAVE_SP_DH +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. + * exp Array of bytes that is the exponent. + * expLen Length of data, in bytes, in exponent. + * mod Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 384 bytes long. + * outLen Length, in bytes, of exponentiation result. + * returs 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen, + mp_int* mod, byte* out, word32* outLen) +{ + int err = MP_OKAY; + sp_digit b[192], e[96], m[96]; + sp_digit* r = b; + word32 i; + + if (mp_count_bits(base) > 3072 || expLen > 384 || + mp_count_bits(mod) != 3072) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + sp_3072_from_mp(b, 96, base); + sp_3072_from_bin(e, 96, exp, expLen); + sp_3072_from_mp(m, 96, mod); + + err = sp_3072_mod_exp_96(r, b, e, expLen * 8, m, 0); + } + + if (err == MP_OKAY) { + sp_3072_to_bin(r, out); + *outLen = 384; + for (i=0; i<384 && out[i] == 0; i++) { + } + *outLen -= i; + XMEMMOVE(out, out + i, *outLen); + + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} +#endif /* WOLFSSL_HAVE_SP_DH */ + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returs 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ + int err = MP_OKAY; + sp_digit b[96], e[48], m[48]; + sp_digit* r = b; + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 1536 || expBits > 1536 || + mp_count_bits(mod) != 1536) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + sp_3072_from_mp(b, 48, base); + sp_3072_from_mp(e, 48, exp); + sp_3072_from_mp(m, 48, mod); + + err = sp_3072_mod_exp_48(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + XMEMSET(r + 48, 0, sizeof(*r) * 48); + err = sp_3072_to_mp(r, res); + res->used = mod->used; + mp_clamp(res); + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} + +#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ + +#endif /* !WOLFSSL_SP_NO_3072 */ + +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +#ifdef WOLFSSL_HAVE_SP_ECC +#ifndef WOLFSSL_SP_NO_256 + +/* Point structure to use. */ +typedef struct sp_point { + sp_digit x[2 * 8]; + sp_digit y[2 * 8]; + sp_digit z[2 * 8]; + int infinity; +} sp_point; + +/* The modulus (prime) of the curve P256. */ +static sp_digit p256_mod[8] = { + 0xffffffff,0xffffffff,0xffffffff,0x00000000,0x00000000,0x00000000, + 0x00000001,0xffffffff +}; +/* The Montogmery normalizer for modulus of the curve P256. */ +static sp_digit p256_norm_mod[8] = { + 0x00000001,0x00000000,0x00000000,0xffffffff,0xffffffff,0xffffffff, + 0xfffffffe,0x00000000 +}; +/* The Montogmery multiplier for modulus of the curve P256. */ +static sp_digit p256_mp_mod = 0x00000001; +#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ + defined(HAVE_ECC_VERIFY) +/* The order of the curve P256. */ +static sp_digit p256_order[8] = { + 0xfc632551,0xf3b9cac2,0xa7179e84,0xbce6faad,0xffffffff,0xffffffff, + 0x00000000,0xffffffff +}; +#endif +/* The order of the curve P256 minus 2. */ +static sp_digit p256_order2[8] = { + 0xfc63254f,0xf3b9cac2,0xa7179e84,0xbce6faad,0xffffffff,0xffffffff, + 0x00000000,0xffffffff +}; +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +/* The Montogmery normalizer for order of the curve P256. */ +static sp_digit p256_norm_order[8] = { + 0x039cdaaf,0x0c46353d,0x58e8617b,0x43190552,0x00000000,0x00000000, + 0xffffffff,0x00000000 +}; +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +/* The Montogmery multiplier for order of the curve P256. */ +static sp_digit p256_mp_order = 0xee00bc4f; +#endif +/* The base point of curve P256. */ +static sp_point p256_base = { + /* X ordinate */ + { + 0xd898c296,0xf4a13945,0x2deb33a0,0x77037d81,0x63a440f2,0xf8bce6e5, + 0xe12c4247,0x6b17d1f2 + }, + /* Y ordinate */ + { + 0x37bf51f5,0xcbb64068,0x6b315ece,0x2bce3357,0x7c0f9e16,0x8ee7eb4a, + 0xfe1a7f9b,0x4fe342e2 + }, + /* Z ordinate */ + { + 0x00000001,0x00000000,0x00000000,0x00000000,0x00000000,0x00000000, + 0x00000000,0x00000000 + }, + /* infinity */ + 0 +}; +#if defined(HAVE_ECC_CHECK_KEY) || defined(HAVE_COMP_KEY) +static sp_digit p256_b[8] = { + 0x27d2604b,0x3bce3c3e,0xcc53b0f6,0x651d06b0,0x769886bc,0xb3ebbd55, + 0xaa3a93e7,0x5ac635d8 +}; +#endif + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) +/* Allocate memory for point and return error. */ +#define sp_ecc_point_new(heap, sp, p) \ + ((p = (sp_point*)XMALLOC(sizeof(sp_point), heap, DYNAMIC_TYPE_ECC)) \ + == NULL) ? MEMORY_E : MP_OKAY +#else +/* Set pointer to data and return no error. */ +#define sp_ecc_point_new(heap, sp, p) ((p = &sp) == NULL) ? MEMORY_E : MP_OKAY +#endif + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) +/* If valid pointer then clear point data if requested and free data. */ +#define sp_ecc_point_free(p, clear, heap) \ + do { \ + if (p != NULL) { \ + if (clear) \ + XMEMSET(p, 0, sizeof(*p)); \ + XFREE(p, heap, DYNAMIC_TYPE_ECC); \ + } \ + } \ + while (0) +#else +/* Clear point data if requested. */ +#define sp_ecc_point_free(p, clear, heap) \ + do { \ + if (clear) \ + XMEMSET(p, 0, sizeof(*p)); \ + } \ + while (0) +#endif + +/* Multiply a number by Montogmery normalizer mod modulus (prime). + * + * r The resulting Montgomery form number. + * a The number to convert. + * m The modulus (prime). + */ +static int sp_256_mod_mul_norm_8(sp_digit* r, sp_digit* a, sp_digit* m) +{ + int64_t t[8]; + int64_t a64[8]; + int64_t o; + + (void)m; + + a64[0] = a[0]; + a64[1] = a[1]; + a64[2] = a[2]; + a64[3] = a[3]; + a64[4] = a[4]; + a64[5] = a[5]; + a64[6] = a[6]; + a64[7] = a[7]; + + /* 1 1 0 -1 -1 -1 -1 0 */ + t[0] = 0 + a64[0] + a64[1] - a64[3] - a64[4] - a64[5] - a64[6]; + /* 0 1 1 0 -1 -1 -1 -1 */ + t[1] = 0 + a64[1] + a64[2] - a64[4] - a64[5] - a64[6] - a64[7]; + /* 0 0 1 1 0 -1 -1 -1 */ + t[2] = 0 + a64[2] + a64[3] - a64[5] - a64[6] - a64[7]; + /* -1 -1 0 2 2 1 0 -1 */ + t[3] = 0 - a64[0] - a64[1] + 2 * a64[3] + 2 * a64[4] + a64[5] - a64[7]; + /* 0 -1 -1 0 2 2 1 0 */ + t[4] = 0 - a64[1] - a64[2] + 2 * a64[4] + 2 * a64[5] + a64[6]; + /* 0 0 -1 -1 0 2 2 1 */ + t[5] = 0 - a64[2] - a64[3] + 2 * a64[5] + 2 * a64[6] + a64[7]; + /* -1 -1 0 0 0 1 3 2 */ + t[6] = 0 - a64[0] - a64[1] + a64[5] + 3 * a64[6] + 2 * a64[7]; + /* 1 0 -1 -1 -1 -1 0 3 */ + t[7] = 0 + a64[0] - a64[2] - a64[3] - a64[4] - a64[5] + 3 * a64[7]; + + t[1] += t[0] >> 32; t[0] &= 0xffffffff; + t[2] += t[1] >> 32; t[1] &= 0xffffffff; + t[3] += t[2] >> 32; t[2] &= 0xffffffff; + t[4] += t[3] >> 32; t[3] &= 0xffffffff; + t[5] += t[4] >> 32; t[4] &= 0xffffffff; + t[6] += t[5] >> 32; t[5] &= 0xffffffff; + t[7] += t[6] >> 32; t[6] &= 0xffffffff; + o = t[7] >> 32; t[7] &= 0xffffffff; + t[0] += o; + t[3] -= o; + t[6] -= o; + t[7] += o; + t[1] += t[0] >> 32; t[0] &= 0xffffffff; + t[2] += t[1] >> 32; t[1] &= 0xffffffff; + t[3] += t[2] >> 32; t[2] &= 0xffffffff; + t[4] += t[3] >> 32; t[3] &= 0xffffffff; + t[5] += t[4] >> 32; t[4] &= 0xffffffff; + t[6] += t[5] >> 32; t[5] &= 0xffffffff; + t[7] += t[6] >> 32; t[6] &= 0xffffffff; + r[0] = t[0]; + r[1] = t[1]; + r[2] = t[2]; + r[3] = t[3]; + r[4] = t[4]; + r[5] = t[5]; + r[6] = t[6]; + r[7] = t[7]; + + return MP_OKAY; +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * a A multi-precision integer. + */ +static void sp_256_from_mp(sp_digit* r, int max, mp_int* a) +{ +#if DIGIT_BIT == 32 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < max; j++) + r[j] = 0; +#elif DIGIT_BIT > 32 + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= a->dp[i] << s; + r[j] &= 0xffffffff; + s = 32 - s; + if (j + 1 >= max) + break; + r[++j] = a->dp[i] >> s; + while (s + 32 <= DIGIT_BIT) { + s += 32; + r[j] &= 0xffffffff; + if (j + 1 >= max) + break; + if (s < DIGIT_BIT) + r[++j] = a->dp[i] >> s; + else + r[++j] = 0; + } + s = DIGIT_BIT - s; + } + + for (j++; j < max; j++) + r[j] = 0; +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 32) { + r[j] &= 0xffffffff; + if (j + 1 >= max) + break; + s = 32 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else + s += DIGIT_BIT; + } + + for (j++; j < max; j++) + r[j] = 0; +#endif +} + +/* Convert a point of type ecc_point to type sp_point. + * + * p Point of type sp_point (result). + * pm Point of type ecc_point. + */ +static void sp_256_point_from_ecc_point_8(sp_point* p, ecc_point* pm) +{ + XMEMSET(p->x, 0, sizeof(p->x)); + XMEMSET(p->y, 0, sizeof(p->y)); + XMEMSET(p->z, 0, sizeof(p->z)); + sp_256_from_mp(p->x, 8, pm->x); + sp_256_from_mp(p->y, 8, pm->y); + sp_256_from_mp(p->z, 8, pm->z); + p->infinity = 0; +} + +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_256_to_mp(sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (256 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { +#if DIGIT_BIT == 32 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 8); + r->used = 8; + mp_clamp(r); +#elif DIGIT_BIT < 32 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 8; i++) { + r->dp[j] |= a[i] << s; + r->dp[j] &= (1l << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + while (s + DIGIT_BIT <= 32) { + s += DIGIT_BIT; + r->dp[j] &= (1l << DIGIT_BIT) - 1; + r->dp[++j] = a[i] >> s; + } + s = 32 - s; + } + r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 8; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 32 >= DIGIT_BIT) { + #if DIGIT_BIT < 32 + r->dp[j] &= (1l << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 32 - s; + } + else + s += 32; + } + r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Convert a point of type sp_point to type ecc_point. + * + * p Point of type sp_point. + * pm Point of type ecc_point (result). + * returns MEMORY_E when allocation of memory in ecc_point fails otherwise + * MP_OKAY. + */ +static int sp_256_point_to_ecc_point_8(sp_point* p, ecc_point* pm) +{ + int err; + + err = sp_256_to_mp(p->x, pm->x); + if (err == MP_OKAY) + err = sp_256_to_mp(p->y, pm->y); + if (err == MP_OKAY) + err = sp_256_to_mp(p->z, pm->z); + + return err; +} + +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +SP_NOINLINE static int32_t sp_256_cmp_8(sp_digit* a, sp_digit* b) +{ + sp_digit r = 0; + + + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "mvn r3, r3\n\t" + "mov r6, #28\n\t" + "\n1:\n\t" + "ldr r7, [%[a], r6]\n\t" + "ldr r5, [%[b], r6]\n\t" + "and r7, r7, r3\n\t" + "and r5, r5, r3\n\t" + "mov r4, r7\n\t" + "subs r7, r7, r5\n\t" + "sbc r7, r7, r7\n\t" + "add %[r], %[r], r7\n\t" + "mvn r7, r7\n\t" + "and r3, r3, r7\n\t" + "subs r5, r5, r4\n\t" + "sbc r7, r7, r7\n\t" + "sub %[r], %[r], r7\n\t" + "mvn r7, r7\n\t" + "and r3, r3, r7\n\t" + "sub r6, r6, #4\n\t" + "cmp r6, #0\n\t" + "bge 1b\n\t" + : [r] "+r" (r) + : [a] "r" (a), [b] "r" (b) + : "r3", "r4", "r5", "r6", "r7" + ); + + return r; +} + +/* Normalize the values in each word to 32. + * + * a Array of sp_digit to normalize. + */ +#define sp_256_norm_8(a) + +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not copying. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +SP_NOINLINE static sp_digit sp_256_cond_sub_8(sp_digit* r, sp_digit* a, + sp_digit* b, sp_digit m) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r5, #32\n\t" + "mov r8, r5\n\t" + "mov r7, #0\n\t" + "\n1:\n\t" + "ldr r6, [%[b], r7]\n\t" + "and r6, r6, %[m]\n\t" + "mov r5, #0\n\t" + "subs r5, r5, %[c]\n\t" + "ldr r5, [%[a], r7]\n\t" + "sbcs r5, r5, r6\n\t" + "sbcs %[c], %[c], %[c]\n\t" + "str r5, [%[r], r7]\n\t" + "add r7, r7, #4\n\t" + "cmp r7, r8\n\t" + "blt 1b\n\t" + : [c] "+r" (c) + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [m] "r" (m) + : "memory", "r5", "r6", "r7", "r8" + ); + + return c; +} + +/* Reduce the number back to 256 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +SP_NOINLINE static void sp_256_mont_reduce_8(sp_digit* a, sp_digit* m, + sp_digit mp) +{ + (void)mp; + (void)m; + + __asm__ __volatile__ ( + "mov r2, #0\n\t" + "mov r1, #0\n\t" + /* i = 0 */ + "mov r8, r2\n\t" + "\n1:\n\t" + "mov r4, #0\n\t" + /* mu = a[i] * 1 (mp) = a[i] */ + "ldr r3, [%[a]]\n\t" + /* a[i] += -1 * mu = -1 * a[i] => a[i] = 0 no carry */ + /* a[i+1] += -1 * mu */ + "ldr r6, [%[a], #4]\n\t" + "mov r5, #0\n\t" + "adds r4, r4, r6\n\t" + "adc r5, r5, r2\n\t" + "str r4, [%[a], #4]\n\t" + /* a[i+2] += -1 * mu */ + "ldr r6, [%[a], #8]\n\t" + "mov r4, #0\n\t" + "adds r5, r5, r6\n\t" + "adc r4, r4, r2\n\t" + "str r5, [%[a], #8]\n\t" + /* a[i+3] += 0 * mu */ + "ldr r6, [%[a], #12]\n\t" + "mov r5, #0\n\t" + "adds r4, r4, r3\n\t" + "adc r5, r5, r2\n\t" + "adds r4, r4, r6\n\t" + "adc r5, r5, r2\n\t" + "str r4, [%[a], #12]\n\t" + /* a[i+4] += 0 * mu */ + "ldr r6, [%[a], #16]\n\t" + "mov r4, #0\n\t" + "adds r5, r5, r6\n\t" + "adc r4, r4, r2\n\t" + "str r5, [%[a], #16]\n\t" + /* a[i+5] += 0 * mu */ + "ldr r6, [%[a], #20]\n\t" + "mov r5, #0\n\t" + "adds r4, r4, r6\n\t" + "adc r5, r5, r2\n\t" + "str r4, [%[a], #20]\n\t" + /* a[i+6] += 1 * mu */ + "ldr r6, [%[a], #24]\n\t" + "mov r4, #0\n\t" + "adds r5, r5, r3\n\t" + "adc r4, r4, r2\n\t" + "adds r5, r5, r6\n\t" + "adc r4, r4, r2\n\t" + "str r5, [%[a], #24]\n\t" + /* a[i+7] += -1 * mu */ + "ldr r6, [%[a], #28]\n\t" + "ldr r7, [%[a], #32]\n\t" + "adds r5, r1, r3\n\t" + "mov r1, #0\n\t" + "adc r1, r1, r2\n\t" + "subs r4, r4, r3\n\t" + "sbcs r5, r5, r2\n\t" + "sbc r1, r1, r2\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r1, r1, r2\n\t" + "str r4, [%[a], #28]\n\t" + "str r5, [%[a], #32]\n\t" + /* i += 1 */ + "add r8, r8, #1\n\t" + "add %[a], %[a], #4\n\t" + "mov r6, #8\n\t" + "cmp r8, r6\n\t" + "blt 1b\n\t" + "sub %[a], %[a], #32\n\t" + "mov r3, r1\n\t" + "sub r1, r1, #1\n\t" + "mvn r1, r1\n\t" + "ldr r4, [%[a],#32]\n\t" + "ldr r5, [%[a],#36]\n\t" + "ldr r6, [%[a],#40]\n\t" + "ldr r7, [%[a],#44]\n\t" + "subs r4, r4, r1\n\t" + "sbcs r5, r5, r1\n\t" + "sbcs r6, r6, r1\n\t" + "sbcs r7, r7, r2\n\t" + "str r4, [%[a],#0]\n\t" + "str r5, [%[a],#4]\n\t" + "str r6, [%[a],#8]\n\t" + "str r7, [%[a],#12]\n\t" + "ldr r4, [%[a],#48]\n\t" + "ldr r5, [%[a],#52]\n\t" + "ldr r6, [%[a],#56]\n\t" + "ldr r7, [%[a],#60]\n\t" + "sbcs r4, r4, r2\n\t" + "sbcs r5, r5, r2\n\t" + "sbcs r6, r6, r3\n\t" + "sbc r7, r7, r1\n\t" + "str r4, [%[a],#16]\n\t" + "str r5, [%[a],#20]\n\t" + "str r6, [%[a],#24]\n\t" + "str r7, [%[a],#28]\n\t" + : [a] "+r" (a) + : + : "memory", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8" + ); + + + (void)m; + (void)mp; +} + +/* Reduce the number back to 256 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +SP_NOINLINE static void sp_256_mont_reduce_order_8(sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_digit ca = 0; + + __asm__ __volatile__ ( + "mov r8, %[mp]\n\t" + "mov r12, %[ca]\n\t" + "mov r14, %[m]\n\t" + "mov r9, %[a]\n\t" + "mov r4, #0\n\t" + /* i = 0 */ + "mov r11, r4\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "mov %[ca], #0\n\t" + /* mu = a[i] * mp */ + "mov %[mp], r8\n\t" + "ldr %[a], [%[a]]\n\t" + "mul %[mp], %[mp], %[a]\n\t" + "mov %[m], r14\n\t" + "mov r10, r9\n\t" + "\n2:\n\t" + /* a[i+j] += m[j] * mu */ + "mov %[a], r10\n\t" + "ldr %[a], [%[a]]\n\t" + "mov %[ca], #0\n\t" + "mov r4, r5\n\t" + "mov r5, #0\n\t" + /* Multiply m[j] and mu - Start */ + "ldr r7, [%[m]]\n\t" + "umull r6, r7, %[mp], r7\n\t" + "adds %[a], %[a], r6\n\t" + "adcs r5, r5, r7\n\t" + /* Multiply m[j] and mu - Done */ + "adds r4, r4, %[a]\n\t" + "adc r5, r5, %[ca]\n\t" + "mov %[a], r10\n\t" + "str r4, [%[a]]\n\t" + "mov r6, #4\n\t" + "add %[m], %[m], #4\n\t" + "add r10, r10, r6\n\t" + "mov r4, #28\n\t" + "add r4, r4, r9\n\t" + "cmp r10, r4\n\t" + "blt 2b\n\t" + /* a[i+7] += m[7] * mu */ + "mov %[ca], #0\n\t" + "mov r4, r12\n\t" + "mov %[a], #0\n\t" + /* Multiply m[7] and mu - Start */ + "ldr r7, [%[m]]\n\t" + "umull r6, r7, %[mp], r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc %[a], %[a], %[ca]\n\t" + /* Multiply m[7] and mu - Done */ + "mov %[ca], %[a]\n\t" + "mov %[a], r10\n\t" + "ldr r7, [%[a], #4]\n\t" + "ldr %[a], [%[a]]\n\t" + "mov r6, #0\n\t" + "adds r5, r5, %[a]\n\t" + "adcs r7, r7, r4\n\t" + "adc %[ca], %[ca], r6\n\t" + "mov %[a], r10\n\t" + "str r5, [%[a]]\n\t" + "str r7, [%[a], #4]\n\t" + /* i += 1 */ + "mov r6, #4\n\t" + "add r9, r9, r6\n\t" + "add r11, r11, r6\n\t" + "mov r12, %[ca]\n\t" + "mov %[a], r9\n\t" + "mov r4, #32\n\t" + "cmp r11, r4\n\t" + "blt 1b\n\t" + "mov %[m], r14\n\t" + : [ca] "+r" (ca), [a] "+r" (a) + : [m] "r" (m), [mp] "r" (mp) + : "memory", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14" + ); + + sp_256_cond_sub_8(a - 8, a, m, (sp_digit)0 - ca); +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_256_mul_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit tmp[8]; + __asm__ __volatile__ ( + "mov r8, %[r]\n\t" + "mov %[r], #0\n\t" + /* A[0] * B[0] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[b], #0]\n\t" + "umull r3, r4, r6, r7\n\t" + "mov r5, #0\n\t" + "str r3, [%[tmp], #0]\n\t" + "mov r3, #0\n\t" + /* A[0] * B[1] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[b], #4]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[1] * B[0] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[b], #0]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "str r4, [%[tmp], #4]\n\t" + "mov r4, #0\n\t" + /* A[0] * B[2] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[b], #8]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[1] * B[1] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[b], #4]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[2] * B[0] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[b], #0]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + "str r5, [%[tmp], #8]\n\t" + "mov r5, #0\n\t" + /* A[0] * B[3] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[b], #12]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[1] * B[2] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[b], #8]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[2] * B[1] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[b], #4]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[3] * B[0] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b], #0]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "str r3, [%[tmp], #12]\n\t" + "mov r3, #0\n\t" + /* A[0] * B[4] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[b], #16]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[1] * B[3] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[b], #12]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[2] * B[2] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[b], #8]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[3] * B[1] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b], #4]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[4] * B[0] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[b], #0]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "str r4, [%[tmp], #16]\n\t" + "mov r4, #0\n\t" + /* A[0] * B[5] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[b], #20]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[1] * B[4] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[b], #16]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[2] * B[3] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[b], #12]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[3] * B[2] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b], #8]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[4] * B[1] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[b], #4]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[5] * B[0] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r7, [%[b], #0]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + "str r5, [%[tmp], #20]\n\t" + "mov r5, #0\n\t" + /* A[0] * B[6] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[b], #24]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[1] * B[5] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[b], #20]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[2] * B[4] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[b], #16]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[3] * B[3] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b], #12]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[4] * B[2] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[b], #8]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[5] * B[1] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r7, [%[b], #4]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[6] * B[0] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[b], #0]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "str r3, [%[tmp], #24]\n\t" + "mov r3, #0\n\t" + /* A[0] * B[7] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[b], #28]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[1] * B[6] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[b], #24]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[2] * B[5] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[b], #20]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[3] * B[4] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b], #16]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[4] * B[3] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[b], #12]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[5] * B[2] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r7, [%[b], #8]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[6] * B[1] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[b], #4]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[7] * B[0] */ + "ldr r6, [%[a], #28]\n\t" + "ldr r7, [%[b], #0]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "str r4, [%[tmp], #28]\n\t" + "mov r4, #0\n\t" + /* A[1] * B[7] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[b], #28]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[2] * B[6] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[b], #24]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[3] * B[5] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b], #20]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[4] * B[4] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[b], #16]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[5] * B[3] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r7, [%[b], #12]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[6] * B[2] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[b], #8]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[7] * B[1] */ + "ldr r6, [%[a], #28]\n\t" + "ldr r7, [%[b], #4]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + "str r5, [r8, #32]\n\t" + "mov r5, #0\n\t" + /* A[2] * B[7] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[b], #28]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[3] * B[6] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b], #24]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[4] * B[5] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[b], #20]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[5] * B[4] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r7, [%[b], #16]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[6] * B[3] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[b], #12]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[7] * B[2] */ + "ldr r6, [%[a], #28]\n\t" + "ldr r7, [%[b], #8]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "str r3, [r8, #36]\n\t" + "mov r3, #0\n\t" + /* A[3] * B[7] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[b], #28]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[4] * B[6] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[b], #24]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[5] * B[5] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r7, [%[b], #20]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[6] * B[4] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[b], #16]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[7] * B[3] */ + "ldr r6, [%[a], #28]\n\t" + "ldr r7, [%[b], #12]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "str r4, [r8, #40]\n\t" + "mov r4, #0\n\t" + /* A[4] * B[7] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[b], #28]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[5] * B[6] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r7, [%[b], #24]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[6] * B[5] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[b], #20]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[7] * B[4] */ + "ldr r6, [%[a], #28]\n\t" + "ldr r7, [%[b], #16]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + "str r5, [r8, #44]\n\t" + "mov r5, #0\n\t" + /* A[5] * B[7] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r7, [%[b], #28]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[6] * B[6] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[b], #24]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[7] * B[5] */ + "ldr r6, [%[a], #28]\n\t" + "ldr r7, [%[b], #20]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "str r3, [r8, #48]\n\t" + "mov r3, #0\n\t" + /* A[6] * B[7] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[b], #28]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[7] * B[6] */ + "ldr r6, [%[a], #28]\n\t" + "ldr r7, [%[b], #24]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "str r4, [r8, #52]\n\t" + "mov r4, #0\n\t" + /* A[7] * B[7] */ + "ldr r6, [%[a], #28]\n\t" + "ldr r7, [%[b], #28]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "str r5, [r8, #56]\n\t" + "str r3, [r8, #60]\n\t" + "ldr r3, [%[tmp], #0]\n\t" + "ldr r4, [%[tmp], #4]\n\t" + "ldr r5, [%[tmp], #8]\n\t" + "ldr r6, [%[tmp], #12]\n\t" + "str r3, [r8, #0]\n\t" + "str r4, [r8, #4]\n\t" + "str r5, [r8, #8]\n\t" + "str r6, [r8, #12]\n\t" + "ldr r3, [%[tmp], #16]\n\t" + "ldr r4, [%[tmp], #20]\n\t" + "ldr r5, [%[tmp], #24]\n\t" + "ldr r6, [%[tmp], #28]\n\t" + "str r3, [r8, #16]\n\t" + "str r4, [r8, #20]\n\t" + "str r5, [r8, #24]\n\t" + "str r6, [r8, #28]\n\t" + "mov %[r], r8\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b), [tmp] "r" (tmp) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8" + ); +} + +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_256_mont_mul_8(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_256_mul_8(r, a, b); + sp_256_mont_reduce_8(r, m, mp); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_256_sqr_8(sp_digit* r, const sp_digit* a) +{ + sp_digit tmp[8]; + __asm__ __volatile__ ( + "mov r8, %[r]\n\t" + "mov %[r], #0\n\t" + /* A[0] * A[0] */ + "ldr r6, [%[a], #0]\n\t" + "umull r3, r4, r6, r6\n\t" + "mov r5, #0\n\t" + "str r3, [%[tmp], #0]\n\t" + "mov r3, #0\n\t" + /* A[0] * A[1] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[a], #4]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "str r4, [%[tmp], #4]\n\t" + "mov r4, #0\n\t" + /* A[0] * A[2] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[a], #8]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[1] * A[1] */ + "ldr r6, [%[a], #4]\n\t" + "umull r6, r7, r6, r6\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + "str r5, [%[tmp], #8]\n\t" + "mov r5, #0\n\t" + /* A[0] * A[3] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[a], #12]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[1] * A[2] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[a], #8]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "str r3, [%[tmp], #12]\n\t" + "mov r3, #0\n\t" + /* A[0] * A[4] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[a], #16]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[1] * A[3] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[a], #12]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[2] * A[2] */ + "ldr r6, [%[a], #8]\n\t" + "umull r6, r7, r6, r6\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "str r4, [%[tmp], #16]\n\t" + "mov r4, #0\n\t" + /* A[0] * A[5] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[a], #20]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[1] * A[4] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[a], #16]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[2] * A[3] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #12]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + "str r5, [%[tmp], #20]\n\t" + "mov r5, #0\n\t" + /* A[0] * A[6] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[a], #24]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[1] * A[5] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[a], #20]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[2] * A[4] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #16]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[3] * A[3] */ + "ldr r6, [%[a], #12]\n\t" + "umull r6, r7, r6, r6\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "str r3, [%[tmp], #24]\n\t" + "mov r3, #0\n\t" + /* A[0] * A[7] */ + "ldr r6, [%[a], #0]\n\t" + "ldr r7, [%[a], #28]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[1] * A[6] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[a], #24]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[2] * A[5] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #20]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[3] * A[4] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[a], #16]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "str r4, [%[tmp], #28]\n\t" + "mov r4, #0\n\t" + /* A[1] * A[7] */ + "ldr r6, [%[a], #4]\n\t" + "ldr r7, [%[a], #28]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[2] * A[6] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #24]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[3] * A[5] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[a], #20]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[4] * A[4] */ + "ldr r6, [%[a], #16]\n\t" + "umull r6, r7, r6, r6\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + "str r5, [r8, #32]\n\t" + "mov r5, #0\n\t" + /* A[2] * A[7] */ + "ldr r6, [%[a], #8]\n\t" + "ldr r7, [%[a], #28]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[3] * A[6] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[a], #24]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[4] * A[5] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[a], #20]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "str r3, [r8, #36]\n\t" + "mov r3, #0\n\t" + /* A[3] * A[7] */ + "ldr r6, [%[a], #12]\n\t" + "ldr r7, [%[a], #28]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[4] * A[6] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[a], #24]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + /* A[5] * A[5] */ + "ldr r6, [%[a], #20]\n\t" + "umull r6, r7, r6, r6\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "str r4, [r8, #40]\n\t" + "mov r4, #0\n\t" + /* A[4] * A[7] */ + "ldr r6, [%[a], #16]\n\t" + "ldr r7, [%[a], #28]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + /* A[5] * A[6] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r7, [%[a], #24]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "adc r4, r4, %[r]\n\t" + "str r5, [r8, #44]\n\t" + "mov r5, #0\n\t" + /* A[5] * A[7] */ + "ldr r6, [%[a], #20]\n\t" + "ldr r7, [%[a], #28]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[6] * A[6] */ + "ldr r6, [%[a], #24]\n\t" + "umull r6, r7, r6, r6\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + "str r3, [r8, #48]\n\t" + "mov r3, #0\n\t" + /* A[6] * A[7] */ + "ldr r6, [%[a], #24]\n\t" + "ldr r7, [%[a], #28]\n\t" + "umull r6, r7, r6, r7\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "adc r3, r3, %[r]\n\t" + "str r4, [r8, #52]\n\t" + "mov r4, #0\n\t" + /* A[7] * A[7] */ + "ldr r6, [%[a], #28]\n\t" + "umull r6, r7, r6, r6\n\t" + "adds r5, r5, r6\n\t" + "adcs r3, r3, r7\n\t" + "str r5, [r8, #56]\n\t" + "str r3, [r8, #60]\n\t" + "ldr r3, [%[tmp], #0]\n\t" + "ldr r4, [%[tmp], #4]\n\t" + "ldr r5, [%[tmp], #8]\n\t" + "ldr r6, [%[tmp], #12]\n\t" + "str r3, [r8, #0]\n\t" + "str r4, [r8, #4]\n\t" + "str r5, [r8, #8]\n\t" + "str r6, [r8, #12]\n\t" + "ldr r3, [%[tmp], #16]\n\t" + "ldr r4, [%[tmp], #20]\n\t" + "ldr r5, [%[tmp], #24]\n\t" + "ldr r6, [%[tmp], #28]\n\t" + "str r3, [r8, #16]\n\t" + "str r4, [r8, #20]\n\t" + "str r5, [r8, #24]\n\t" + "str r6, [r8, #28]\n\t" + "mov %[r], r8\n\t" + : + : [r] "r" (r), [a] "r" (a), [tmp] "r" (tmp) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8" + ); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_256_mont_sqr_8(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_256_sqr_8(r, a); + sp_256_mont_reduce_8(r, m, mp); +} + +#if !defined(WOLFSSL_SP_SMALL) || defined(HAVE_COMP_KEY) +/* Square the Montgomery form number a number of times. (r = a ^ n mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * n Number of times to square. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_256_mont_sqr_n_8(sp_digit* r, sp_digit* a, int n, + sp_digit* m, sp_digit mp) +{ + sp_256_mont_sqr_8(r, a, m, mp); + for (; n > 1; n--) + sp_256_mont_sqr_8(r, r, m, mp); +} + +#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */ +#ifdef WOLFSSL_SP_SMALL +/* Mod-2 for the P256 curve. */ +static const uint32_t p256_mod_2[8] = { + 0xfffffffd,0xffffffff,0xffffffff,0x00000000,0x00000000,0x00000000, + 0x00000001,0xffffffff +}; +#endif /* !WOLFSSL_SP_SMALL */ + +/* Invert the number, in Montgomery form, modulo the modulus (prime) of the + * P256 curve. (r = 1 / a mod m) + * + * r Inverse result. + * a Number to invert. + * td Temporary data. + */ +static void sp_256_mont_inv_8(sp_digit* r, sp_digit* a, sp_digit* td) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* t = td; + int i; + + XMEMCPY(t, a, sizeof(sp_digit) * 8); + for (i=254; i>=0; i--) { + sp_256_mont_sqr_8(t, t, p256_mod, p256_mp_mod); + if (p256_mod_2[i / 32] & ((sp_digit)1 << (i % 32))) + sp_256_mont_mul_8(t, t, a, p256_mod, p256_mp_mod); + } + XMEMCPY(r, t, sizeof(sp_digit) * 8); +#else + sp_digit* t = td; + sp_digit* t2 = td + 2 * 8; + sp_digit* t3 = td + 4 * 8; + + /* t = a^2 */ + sp_256_mont_sqr_8(t, a, p256_mod, p256_mp_mod); + /* t = a^3 = t * a */ + sp_256_mont_mul_8(t, t, a, p256_mod, p256_mp_mod); + /* t2= a^c = t ^ 2 ^ 2 */ + sp_256_mont_sqr_n_8(t2, t, 2, p256_mod, p256_mp_mod); + /* t3= a^d = t2 * a */ + sp_256_mont_mul_8(t3, t2, a, p256_mod, p256_mp_mod); + /* t = a^f = t2 * t */ + sp_256_mont_mul_8(t, t2, t, p256_mod, p256_mp_mod); + /* t2= a^f0 = t ^ 2 ^ 4 */ + sp_256_mont_sqr_n_8(t2, t, 4, p256_mod, p256_mp_mod); + /* t3= a^fd = t2 * t3 */ + sp_256_mont_mul_8(t3, t2, t3, p256_mod, p256_mp_mod); + /* t = a^ff = t2 * t */ + sp_256_mont_mul_8(t, t2, t, p256_mod, p256_mp_mod); + /* t2= a^ff00 = t ^ 2 ^ 8 */ + sp_256_mont_sqr_n_8(t2, t, 8, p256_mod, p256_mp_mod); + /* t3= a^fffd = t2 * t3 */ + sp_256_mont_mul_8(t3, t2, t3, p256_mod, p256_mp_mod); + /* t = a^ffff = t2 * t */ + sp_256_mont_mul_8(t, t2, t, p256_mod, p256_mp_mod); + /* t2= a^ffff0000 = t ^ 2 ^ 16 */ + sp_256_mont_sqr_n_8(t2, t, 16, p256_mod, p256_mp_mod); + /* t3= a^fffffffd = t2 * t3 */ + sp_256_mont_mul_8(t3, t2, t3, p256_mod, p256_mp_mod); + /* t = a^ffffffff = t2 * t */ + sp_256_mont_mul_8(t, t2, t, p256_mod, p256_mp_mod); + /* t = a^ffffffff00000000 = t ^ 2 ^ 32 */ + sp_256_mont_sqr_n_8(t2, t, 32, p256_mod, p256_mp_mod); + /* t2= a^ffffffffffffffff = t2 * t */ + sp_256_mont_mul_8(t, t2, t, p256_mod, p256_mp_mod); + /* t2= a^ffffffff00000001 = t2 * a */ + sp_256_mont_mul_8(t2, t2, a, p256_mod, p256_mp_mod); + /* t2= a^ffffffff000000010000000000000000000000000000000000000000 + * = t2 ^ 2 ^ 160 */ + sp_256_mont_sqr_n_8(t2, t2, 160, p256_mod, p256_mp_mod); + /* t2= a^ffffffff00000001000000000000000000000000ffffffffffffffff + * = t2 * t */ + sp_256_mont_mul_8(t2, t2, t, p256_mod, p256_mp_mod); + /* t2= a^ffffffff00000001000000000000000000000000ffffffffffffffff00000000 + * = t2 ^ 2 ^ 32 */ + sp_256_mont_sqr_n_8(t2, t2, 32, p256_mod, p256_mp_mod); + /* r = a^ffffffff00000001000000000000000000000000fffffffffffffffffffffffd + * = t2 * t3 */ + sp_256_mont_mul_8(r, t2, t3, p256_mod, p256_mp_mod); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Map the Montgomery form projective co-ordinate point to an affine point. + * + * r Resulting affine co-ordinate point. + * p Montgomery form projective co-ordinate point. + * t Temporary ordinate data. + */ +static void sp_256_map_8(sp_point* r, sp_point* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*8; + int32_t n; + + sp_256_mont_inv_8(t1, p->z, t + 2*8); + + sp_256_mont_sqr_8(t2, t1, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t1, t2, t1, p256_mod, p256_mp_mod); + + /* x /= z^2 */ + sp_256_mont_mul_8(r->x, p->x, t2, p256_mod, p256_mp_mod); + XMEMSET(r->x + 8, 0, sizeof(r->x) / 2); + sp_256_mont_reduce_8(r->x, p256_mod, p256_mp_mod); + /* Reduce x to less than modulus */ + n = sp_256_cmp_8(r->x, p256_mod); + sp_256_cond_sub_8(r->x, r->x, p256_mod, 0 - (n >= 0)); + sp_256_norm_8(r->x); + + /* y /= z^3 */ + sp_256_mont_mul_8(r->y, p->y, t1, p256_mod, p256_mp_mod); + XMEMSET(r->y + 8, 0, sizeof(r->y) / 2); + sp_256_mont_reduce_8(r->y, p256_mod, p256_mp_mod); + /* Reduce y to less than modulus */ + n = sp_256_cmp_8(r->y, p256_mod); + sp_256_cond_sub_8(r->y, r->y, p256_mod, 0 - (n >= 0)); + sp_256_norm_8(r->y); + + XMEMSET(r->z, 0, sizeof(r->z)); + r->z[0] = 1; + +} + +#ifdef WOLFSSL_SP_SMALL +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_256_add_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r6, %[a]\n\t" + "mov r7, #0\n\t" + "add r6, r6, #32\n\t" + "sub r7, r7, #1\n\t" + "\n1:\n\t" + "adds %[c], %[c], r7\n\t" + "ldr r4, [%[a]]\n\t" + "ldr r5, [%[b]]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r]]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c], %[c]\n\t" + "add %[a], %[a], #4\n\t" + "add %[b], %[b], #4\n\t" + "add %[r], %[r], #4\n\t" + "cmp %[a], r6\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r7" + ); + + return c; +} + +#else +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_256_add_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[b], #0]\n\t" + "adds r4, r4, r5\n\t" + "str r4, [%[r], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #4]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[b], #8]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #12]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[b], #16]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #20]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[b], #24]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #28]\n\t" + "adcs r4, r4, r5\n\t" + "str r4, [%[r], #28]\n\t" + "mov %[c], #0\n\t" + "adc %[c], %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Add two Montgomery form numbers (r = a + b % m). + * + * r Result of addition. + * a First number to add in Montogmery form. + * b Second number to add in Montogmery form. + * m Modulus (prime). + */ +SP_NOINLINE static void sp_256_mont_add_8(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m) +{ + (void)m; + + __asm__ __volatile__ ( + "mov r3, #0\n\t" + "ldr r4, [%[a],#0]\n\t" + "ldr r5, [%[a],#4]\n\t" + "ldr r6, [%[b],#0]\n\t" + "ldr r7, [%[b],#4]\n\t" + "adds r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "str r4, [%[r],#0]\n\t" + "str r5, [%[r],#4]\n\t" + "ldr r4, [%[a],#8]\n\t" + "ldr r5, [%[a],#12]\n\t" + "ldr r6, [%[b],#8]\n\t" + "ldr r7, [%[b],#12]\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "str r4, [%[r],#8]\n\t" + "str r5, [%[r],#12]\n\t" + "ldr r4, [%[a],#16]\n\t" + "ldr r5, [%[a],#20]\n\t" + "ldr r6, [%[b],#16]\n\t" + "ldr r7, [%[b],#20]\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "mov r8, r4\n\t" + "mov r9, r5\n\t" + "ldr r4, [%[a],#24]\n\t" + "ldr r5, [%[a],#28]\n\t" + "ldr r6, [%[b],#24]\n\t" + "ldr r7, [%[b],#28]\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r7\n\t" + "mov r10, r4\n\t" + "mov r11, r5\n\t" + "adc r3, r3, r3\n\t" + "mov r6, r3\n\t" + "sub r3, r3, #1\n\t" + "mvn r3, r3\n\t" + "mov r7, #0\n\t" + "ldr r4, [%[r],#0]\n\t" + "ldr r5, [%[r],#4]\n\t" + "subs r4, r4, r3\n\t" + "sbcs r5, r5, r3\n\t" + "str r4, [%[r],#0]\n\t" + "str r5, [%[r],#4]\n\t" + "ldr r4, [%[r],#8]\n\t" + "ldr r5, [%[r],#12]\n\t" + "sbcs r4, r4, r3\n\t" + "sbcs r5, r5, r7\n\t" + "str r4, [%[r],#8]\n\t" + "str r5, [%[r],#12]\n\t" + "mov r4, r8\n\t" + "mov r5, r9\n\t" + "sbcs r4, r4, r7\n\t" + "sbcs r5, r5, r7\n\t" + "str r4, [%[r],#16]\n\t" + "str r5, [%[r],#20]\n\t" + "mov r4, r10\n\t" + "mov r5, r11\n\t" + "sbcs r4, r4, r6\n\t" + "sbc r5, r5, r3\n\t" + "str r4, [%[r],#24]\n\t" + "str r5, [%[r],#28]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11" + ); +} + +/* Double a Montgomery form number (r = a + a % m). + * + * r Result of doubling. + * a Number to double in Montogmery form. + * m Modulus (prime). + */ +SP_NOINLINE static void sp_256_mont_dbl_8(sp_digit* r, sp_digit* a, sp_digit* m) +{ + (void)m; + + __asm__ __volatile__ ( + "ldr r4, [%[a],#0]\n\t" + "ldr r5, [%[a],#4]\n\t" + "ldr r6, [%[a],#8]\n\t" + "ldr r7, [%[a],#12]\n\t" + "adds r4, r4, r4\n\t" + "adcs r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adcs r7, r7, r7\n\t" + "str r4, [%[r],#0]\n\t" + "str r5, [%[r],#4]\n\t" + "str r6, [%[r],#8]\n\t" + "str r7, [%[r],#12]\n\t" + "ldr r4, [%[a],#16]\n\t" + "ldr r5, [%[a],#20]\n\t" + "ldr r6, [%[a],#24]\n\t" + "ldr r7, [%[a],#28]\n\t" + "adcs r4, r4, r4\n\t" + "adcs r5, r5, r5\n\t" + "adcs r6, r6, r6\n\t" + "adcs r7, r7, r7\n\t" + "mov r8, r4\n\t" + "mov r9, r5\n\t" + "mov r10, r6\n\t" + "mov r11, r7\n\t" + "mov r3, #0\n\t" + "mov r7, #0\n\t" + "adc r3, r3, r3\n\t" + "mov r2, r3\n\t" + "sub r3, r3, #1\n\t" + "mvn r3, r3\n\t" + "ldr r4, [%[r],#0]\n\t" + "ldr r5, [%[r],#4]\n\t" + "ldr r6, [%[r],#8]\n\t" + "subs r4, r4, r3\n\t" + "sbcs r5, r5, r3\n\t" + "sbcs r6, r6, r3\n\t" + "str r4, [%[r],#0]\n\t" + "str r5, [%[r],#4]\n\t" + "str r6, [%[r],#8]\n\t" + "ldr r4, [%[r],#12]\n\t" + "mov r5, r8\n\t" + "mov r6, r9\n\t" + "sbcs r4, r4, r7\n\t" + "sbcs r5, r5, r7\n\t" + "sbcs r6, r6, r7\n\t" + "str r4, [%[r],#12]\n\t" + "str r5, [%[r],#16]\n\t" + "str r6, [%[r],#20]\n\t" + "mov r4, r10\n\t" + "mov r5, r11\n\t" + "sbcs r4, r4, r2\n\t" + "sbc r5, r5, r3\n\t" + "str r4, [%[r],#24]\n\t" + "str r5, [%[r],#28]\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r3", "r2", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11" + ); +} + +/* Triple a Montgomery form number (r = a + a + a % m). + * + * r Result of Tripling. + * a Number to triple in Montogmery form. + * m Modulus (prime). + */ +SP_NOINLINE static void sp_256_mont_tpl_8(sp_digit* r, sp_digit* a, sp_digit* m) +{ + (void)m; + + __asm__ __volatile__ ( + "ldr r6, [%[a],#0]\n\t" + "ldr r7, [%[a],#4]\n\t" + "ldr r4, [%[a],#8]\n\t" + "ldr r5, [%[a],#12]\n\t" + "adds r6, r6, r6\n\t" + "adcs r7, r7, r7\n\t" + "adcs r4, r4, r4\n\t" + "adcs r5, r5, r5\n\t" + "mov r8, r4\n\t" + "mov r9, r5\n\t" + "ldr r2, [%[a],#16]\n\t" + "ldr r3, [%[a],#20]\n\t" + "ldr r4, [%[a],#24]\n\t" + "ldr r5, [%[a],#28]\n\t" + "adcs r2, r2, r2\n\t" + "adcs r3, r3, r3\n\t" + "adcs r4, r4, r4\n\t" + "adcs r5, r5, r5\n\t" + "mov r10, r2\n\t" + "mov r11, r3\n\t" + "mov r12, r4\n\t" + "mov r14, r5\n\t" + "mov r3, #0\n\t" + "mov r5, #0\n\t" + "adc r3, r3, r3\n\t" + "mov r4, r3\n\t" + "sub r3, r3, #1\n\t" + "mvn r3, r3\n\t" + "subs r6, r6, r3\n\t" + "sbcs r7, r7, r3\n\t" + "mov r2, r8\n\t" + "sbcs r2, r2, r3\n\t" + "mov r8, r2\n\t" + "mov r2, r9\n\t" + "sbcs r2, r2, r5\n\t" + "mov r9, r2\n\t" + "mov r2, r10\n\t" + "sbcs r2, r2, r5\n\t" + "mov r10, r2\n\t" + "mov r2, r11\n\t" + "sbcs r2, r2, r5\n\t" + "mov r11, r2\n\t" + "mov r2, r12\n\t" + "sbcs r2, r2, r4\n\t" + "mov r12, r2\n\t" + "mov r2, r14\n\t" + "sbc r2, r2, r3\n\t" + "mov r14, r2\n\t" + "ldr r2, [%[a],#0]\n\t" + "ldr r3, [%[a],#4]\n\t" + "adds r6, r6, r2\n\t" + "adcs r7, r7, r3\n\t" + "ldr r2, [%[a],#8]\n\t" + "ldr r3, [%[a],#12]\n\t" + "mov r4, r8\n\t" + "mov r5, r9\n\t" + "adcs r2, r2, r4\n\t" + "adcs r3, r3, r5\n\t" + "mov r8, r2\n\t" + "mov r9, r3\n\t" + "ldr r2, [%[a],#16]\n\t" + "ldr r3, [%[a],#20]\n\t" + "mov r4, r10\n\t" + "mov r5, r11\n\t" + "adcs r2, r2, r4\n\t" + "adcs r3, r3, r5\n\t" + "mov r10, r2\n\t" + "mov r11, r3\n\t" + "ldr r2, [%[a],#24]\n\t" + "ldr r3, [%[a],#28]\n\t" + "mov r4, r12\n\t" + "mov r5, r14\n\t" + "adcs r2, r2, r4\n\t" + "adcs r3, r3, r5\n\t" + "mov r12, r2\n\t" + "mov r14, r3\n\t" + "mov r3, #0\n\t" + "mov r5, #0\n\t" + "adc r3, r3, r3\n\t" + "mov r4, r3\n\t" + "sub r3, r3, #1\n\t" + "mvn r3, r3\n\t" + "subs r6, r6, r3\n\t" + "str r6, [%[r],#0]\n\t" + "sbcs r7, r7, r3\n\t" + "str r7, [%[r],#4]\n\t" + "mov r2, r8\n\t" + "sbcs r2, r2, r3\n\t" + "str r2, [%[r],#8]\n\t" + "mov r2, r9\n\t" + "sbcs r2, r2, r5\n\t" + "str r2, [%[r],#12]\n\t" + "mov r2, r10\n\t" + "sbcs r2, r2, r5\n\t" + "str r2, [%[r],#16]\n\t" + "mov r2, r11\n\t" + "sbcs r2, r2, r5\n\t" + "str r2, [%[r],#20]\n\t" + "mov r2, r12\n\t" + "sbcs r2, r2, r4\n\t" + "str r2, [%[r],#24]\n\t" + "mov r2, r14\n\t" + "sbc r2, r2, r3\n\t" + "str r2, [%[r],#28]\n\t" + : + : [r] "r" (r), [a] "r" (a) + : "memory", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14" + ); +} + +/* Subtract two Montgomery form numbers (r = a - b % m). + * + * r Result of subtration. + * a Number to subtract from in Montogmery form. + * b Number to subtract with in Montogmery form. + * m Modulus (prime). + */ +SP_NOINLINE static void sp_256_mont_sub_8(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m) +{ + (void)m; + + __asm__ __volatile__ ( + "ldr r4, [%[a],#0]\n\t" + "ldr r5, [%[a],#4]\n\t" + "ldr r6, [%[b],#0]\n\t" + "ldr r7, [%[b],#4]\n\t" + "subs r4, r4, r6\n\t" + "sbcs r5, r5, r7\n\t" + "str r4, [%[r],#0]\n\t" + "str r5, [%[r],#4]\n\t" + "ldr r4, [%[a],#8]\n\t" + "ldr r5, [%[a],#12]\n\t" + "ldr r6, [%[b],#8]\n\t" + "ldr r7, [%[b],#12]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r7\n\t" + "str r4, [%[r],#8]\n\t" + "str r5, [%[r],#12]\n\t" + "ldr r4, [%[a],#16]\n\t" + "ldr r5, [%[a],#20]\n\t" + "ldr r6, [%[b],#16]\n\t" + "ldr r7, [%[b],#20]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r7\n\t" + "mov r8, r4\n\t" + "mov r9, r5\n\t" + "ldr r4, [%[a],#24]\n\t" + "ldr r5, [%[a],#28]\n\t" + "ldr r6, [%[b],#24]\n\t" + "ldr r7, [%[b],#28]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r7\n\t" + "mov r10, r4\n\t" + "mov r11, r5\n\t" + "sbc r3, r3, r3\n\t" + "lsr r7, r3, #31\n\t" + "mov r6, #0\n\t" + "ldr r4, [%[r],#0]\n\t" + "ldr r5, [%[r],#4]\n\t" + "adds r4, r4, r3\n\t" + "adcs r5, r5, r3\n\t" + "str r4, [%[r],#0]\n\t" + "str r5, [%[r],#4]\n\t" + "ldr r4, [%[r],#8]\n\t" + "ldr r5, [%[r],#12]\n\t" + "adcs r4, r4, r3\n\t" + "adcs r5, r5, r6\n\t" + "str r4, [%[r],#8]\n\t" + "str r5, [%[r],#12]\n\t" + "mov r4, r8\n\t" + "mov r5, r9\n\t" + "adcs r4, r4, r6\n\t" + "adcs r5, r5, r6\n\t" + "str r4, [%[r],#16]\n\t" + "str r5, [%[r],#20]\n\t" + "mov r4, r10\n\t" + "mov r5, r11\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, r3\n\t" + "str r4, [%[r],#24]\n\t" + "str r5, [%[r],#28]\n\t" + : + : [r] "r" (r), [a] "r" (a), [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11" + ); +} + +/* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m) + * + * r Result of division by 2. + * a Number to divide. + * m Modulus (prime). + */ +SP_NOINLINE static void sp_256_div2_8(sp_digit* r, sp_digit* a, sp_digit* m) +{ + __asm__ __volatile__ ( + "ldr r7, [%[a], #0]\n\t" + "lsl r7, r7, #31\n\t" + "lsr r7, r7, #31\n\t" + "mov r5, #0\n\t" + "sub r5, r5, r7\n\t" + "mov r7, #0\n\t" + "lsl r6, r5, #31\n\t" + "lsr r6, r6, #31\n\t" + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "adds r3, r3, r5\n\t" + "adcs r4, r4, r5\n\t" + "str r3, [%[r], #0]\n\t" + "str r4, [%[r], #4]\n\t" + "ldr r3, [%[a], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "adcs r3, r3, r5\n\t" + "adcs r4, r4, r7\n\t" + "str r3, [%[r], #8]\n\t" + "str r4, [%[r], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "adcs r3, r3, r7\n\t" + "adcs r4, r4, r7\n\t" + "str r3, [%[r], #16]\n\t" + "str r4, [%[r], #20]\n\t" + "ldr r3, [%[a], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "adcs r3, r3, r6\n\t" + "adcs r4, r4, r5\n\t" + "adc r7, r7, r7\n\t" + "lsl r7, r7, #31\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, #31\n\t" + "lsr r6, r4, #1\n\t" + "lsl r4, r4, #31\n\t" + "orr r5, r5, r4\n\t" + "orr r6, r6, r7\n\t" + "mov r7, r3\n\t" + "str r5, [%[r], #24]\n\t" + "str r6, [%[r], #28]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, #31\n\t" + "lsr r6, r4, #1\n\t" + "lsl r4, r4, #31\n\t" + "orr r5, r5, r4\n\t" + "orr r6, r6, r7\n\t" + "mov r7, r3\n\t" + "str r5, [%[r], #16]\n\t" + "str r6, [%[r], #20]\n\t" + "ldr r3, [%[a], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "lsr r5, r3, #1\n\t" + "lsl r3, r3, #31\n\t" + "lsr r6, r4, #1\n\t" + "lsl r4, r4, #31\n\t" + "orr r5, r5, r4\n\t" + "orr r6, r6, r7\n\t" + "mov r7, r3\n\t" + "str r5, [%[r], #8]\n\t" + "str r6, [%[r], #12]\n\t" + "ldr r3, [%[r], #0]\n\t" + "ldr r4, [%[r], #4]\n\t" + "lsr r5, r3, #1\n\t" + "lsr r6, r4, #1\n\t" + "lsl r4, r4, #31\n\t" + "orr r5, r5, r4\n\t" + "orr r6, r6, r7\n\t" + "str r5, [%[r], #0]\n\t" + "str r6, [%[r], #4]\n\t" + : + : [r] "r" (r), [a] "r" (a), [m] "r" (m) + : "memory", "r3", "r4", "r5", "r6", "r7" + ); +} + +/* Double the Montgomery form projective point p. + * + * r Result of doubling point. + * p Point to double. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_dbl_8(sp_point* r, sp_point* p, sp_digit* t) +{ + sp_point* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*8; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* When infinity don't double point passed in - constant time. */ + rp[0] = r; + rp[1] = (sp_point*)t; + XMEMSET(rp[1], 0, sizeof(sp_point)); + x = rp[p->infinity]->x; + y = rp[p->infinity]->y; + z = rp[p->infinity]->z; + /* Put point to double into result - good for infinty. */ + if (r != p) { + for (i=0; i<8; i++) + r->x[i] = p->x[i]; + for (i=0; i<8; i++) + r->y[i] = p->y[i]; + for (i=0; i<8; i++) + r->z[i] = p->z[i]; + r->infinity = p->infinity; + } + + /* T1 = Z * Z */ + sp_256_mont_sqr_8(t1, z, p256_mod, p256_mp_mod); + /* Z = Y * Z */ + sp_256_mont_mul_8(z, y, z, p256_mod, p256_mp_mod); + /* Z = 2Z */ + sp_256_mont_dbl_8(z, z, p256_mod); + /* T2 = X - T1 */ + sp_256_mont_sub_8(t2, x, t1, p256_mod); + /* T1 = X + T1 */ + sp_256_mont_add_8(t1, x, t1, p256_mod); + /* T2 = T1 * T2 */ + sp_256_mont_mul_8(t2, t1, t2, p256_mod, p256_mp_mod); + /* T1 = 3T2 */ + sp_256_mont_tpl_8(t1, t2, p256_mod); + /* Y = 2Y */ + sp_256_mont_dbl_8(y, y, p256_mod); + /* Y = Y * Y */ + sp_256_mont_sqr_8(y, y, p256_mod, p256_mp_mod); + /* T2 = Y * Y */ + sp_256_mont_sqr_8(t2, y, p256_mod, p256_mp_mod); + /* T2 = T2/2 */ + sp_256_div2_8(t2, t2, p256_mod); + /* Y = Y * X */ + sp_256_mont_mul_8(y, y, x, p256_mod, p256_mp_mod); + /* X = T1 * T1 */ + sp_256_mont_mul_8(x, t1, t1, p256_mod, p256_mp_mod); + /* X = X - Y */ + sp_256_mont_sub_8(x, x, y, p256_mod); + /* X = X - Y */ + sp_256_mont_sub_8(x, x, y, p256_mod); + /* Y = Y - X */ + sp_256_mont_sub_8(y, y, x, p256_mod); + /* Y = Y * T1 */ + sp_256_mont_mul_8(y, y, t1, p256_mod, p256_mp_mod); + /* Y = Y - T2 */ + sp_256_mont_sub_8(y, y, t2, p256_mod); + +} + +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_256_sub_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "mov r6, %[a]\n\t" + "add r6, r6, #32\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "subs r5, r5, %[c]\n\t" + "ldr r4, [%[a]]\n\t" + "ldr r5, [%[b]]\n\t" + "sbcs r4, r4, r5\n\t" + "str r4, [%[r]]\n\t" + "sbc %[c], %[c], %[c]\n\t" + "add %[a], %[a], #4\n\t" + "add %[b], %[b], #4\n\t" + "add %[r], %[r], #4\n\t" + "cmp %[a], r6\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6" + ); + + return c; +} + +#else +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_256_sub_8(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r4, [%[a], #0]\n\t" + "ldr r5, [%[a], #4]\n\t" + "ldr r6, [%[b], #0]\n\t" + "ldr r7, [%[b], #4]\n\t" + "subs r4, r4, r6\n\t" + "sbcs r5, r5, r7\n\t" + "str r4, [%[r], #0]\n\t" + "str r5, [%[r], #4]\n\t" + "ldr r4, [%[a], #8]\n\t" + "ldr r5, [%[a], #12]\n\t" + "ldr r6, [%[b], #8]\n\t" + "ldr r7, [%[b], #12]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r7\n\t" + "str r4, [%[r], #8]\n\t" + "str r5, [%[r], #12]\n\t" + "ldr r4, [%[a], #16]\n\t" + "ldr r5, [%[a], #20]\n\t" + "ldr r6, [%[b], #16]\n\t" + "ldr r7, [%[b], #20]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r7\n\t" + "str r4, [%[r], #16]\n\t" + "str r5, [%[r], #20]\n\t" + "ldr r4, [%[a], #24]\n\t" + "ldr r5, [%[a], #28]\n\t" + "ldr r6, [%[b], #24]\n\t" + "ldr r7, [%[b], #28]\n\t" + "sbcs r4, r4, r6\n\t" + "sbcs r5, r5, r7\n\t" + "str r4, [%[r], #24]\n\t" + "str r5, [%[r], #28]\n\t" + "sbc %[c], %[c], %[c]\n\t" + : [c] "+r" (c), [r] "+r" (r), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r4", "r5", "r6", "r7" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Compare two numbers to determine if they are equal. + * Constant time implementation. + * + * a First number to compare. + * b Second number to compare. + * returns 1 when equal and 0 otherwise. + */ +static int sp_256_cmp_equal_8(const sp_digit* a, const sp_digit* b) +{ + return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]) | (a[3] ^ b[3]) | + (a[4] ^ b[4]) | (a[5] ^ b[5]) | (a[6] ^ b[6]) | (a[7] ^ b[7])) == 0; +} + +/* Add two Montgomery form projective points. + * + * r Result of addition. + * p Frist point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_add_8(sp_point* r, sp_point* p, sp_point* q, + sp_digit* t) +{ + sp_point* ap[2]; + sp_point* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*8; + sp_digit* t3 = t + 4*8; + sp_digit* t4 = t + 6*8; + sp_digit* t5 = t + 8*8; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + sp_point* a = p; + p = q; + q = a; + } + + /* Check double */ + sp_256_sub_8(t1, p256_mod, q->y); + sp_256_norm_8(t1); + if (sp_256_cmp_equal_8(p->x, q->x) & sp_256_cmp_equal_8(p->z, q->z) & + (sp_256_cmp_equal_8(p->y, q->y) | sp_256_cmp_equal_8(p->y, t1))) { + sp_256_proj_point_dbl_8(r, p, t); + } + else { + rp[0] = r; + rp[1] = (sp_point*)t; + XMEMSET(rp[1], 0, sizeof(sp_point)); + x = rp[p->infinity | q->infinity]->x; + y = rp[p->infinity | q->infinity]->y; + z = rp[p->infinity | q->infinity]->z; + + ap[0] = p; + ap[1] = q; + for (i=0; i<8; i++) + r->x[i] = ap[p->infinity]->x[i]; + for (i=0; i<8; i++) + r->y[i] = ap[p->infinity]->y[i]; + for (i=0; i<8; i++) + r->z[i] = ap[p->infinity]->z[i]; + r->infinity = ap[p->infinity]->infinity; + + /* U1 = X1*Z2^2 */ + sp_256_mont_sqr_8(t1, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t3, t1, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t1, t1, x, p256_mod, p256_mp_mod); + /* U2 = X2*Z1^2 */ + sp_256_mont_sqr_8(t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t4, t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t2, t2, q->x, p256_mod, p256_mp_mod); + /* S1 = Y1*Z2^3 */ + sp_256_mont_mul_8(t3, t3, y, p256_mod, p256_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_256_mont_mul_8(t4, t4, q->y, p256_mod, p256_mp_mod); + /* H = U2 - U1 */ + sp_256_mont_sub_8(t2, t2, t1, p256_mod); + /* R = S2 - S1 */ + sp_256_mont_sub_8(t4, t4, t3, p256_mod); + /* Z3 = H*Z1*Z2 */ + sp_256_mont_mul_8(z, z, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(z, z, t2, p256_mod, p256_mp_mod); + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_256_mont_sqr_8(x, t4, p256_mod, p256_mp_mod); + sp_256_mont_sqr_8(t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(y, t1, t5, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t5, t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_sub_8(x, x, t5, p256_mod); + sp_256_mont_dbl_8(t1, y, p256_mod); + sp_256_mont_sub_8(x, x, t1, p256_mod); + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_256_mont_sub_8(y, y, x, p256_mod); + sp_256_mont_mul_8(y, y, t4, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t5, t5, t3, p256_mod, p256_mp_mod); + sp_256_mont_sub_8(y, y, t5, p256_mod); + } +} + +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_fast_8(sp_point* r, sp_point* g, sp_digit* k, + int map, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point td[16]; + sp_point rtd; + sp_digit tmpd[2 * 8 * 5]; +#endif + sp_point* t; + sp_point* rt; + sp_digit* tmp; + sp_digit n; + int i; + int c, y; + int err; + + (void)heap; + + err = sp_ecc_point_new(heap, rtd, rt); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + t = (sp_point*)XMALLOC(sizeof(sp_point) * 16, heap, DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 5, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; +#else + t = td; + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + /* t[0] = {0, 0, 1} * norm */ + XMEMSET(&t[0], 0, sizeof(t[0])); + t[0].infinity = 1; + /* t[1] = {g->x, g->y, g->z} * norm */ + sp_256_mod_mul_norm_8(t[1].x, g->x, p256_mod); + sp_256_mod_mul_norm_8(t[1].y, g->y, p256_mod); + sp_256_mod_mul_norm_8(t[1].z, g->z, p256_mod); + t[1].infinity = 0; + sp_256_proj_point_dbl_8(&t[ 2], &t[ 1], tmp); + t[ 2].infinity = 0; + sp_256_proj_point_add_8(&t[ 3], &t[ 2], &t[ 1], tmp); + t[ 3].infinity = 0; + sp_256_proj_point_dbl_8(&t[ 4], &t[ 2], tmp); + t[ 4].infinity = 0; + sp_256_proj_point_add_8(&t[ 5], &t[ 3], &t[ 2], tmp); + t[ 5].infinity = 0; + sp_256_proj_point_dbl_8(&t[ 6], &t[ 3], tmp); + t[ 6].infinity = 0; + sp_256_proj_point_add_8(&t[ 7], &t[ 4], &t[ 3], tmp); + t[ 7].infinity = 0; + sp_256_proj_point_dbl_8(&t[ 8], &t[ 4], tmp); + t[ 8].infinity = 0; + sp_256_proj_point_add_8(&t[ 9], &t[ 5], &t[ 4], tmp); + t[ 9].infinity = 0; + sp_256_proj_point_dbl_8(&t[10], &t[ 5], tmp); + t[10].infinity = 0; + sp_256_proj_point_add_8(&t[11], &t[ 6], &t[ 5], tmp); + t[11].infinity = 0; + sp_256_proj_point_dbl_8(&t[12], &t[ 6], tmp); + t[12].infinity = 0; + sp_256_proj_point_add_8(&t[13], &t[ 7], &t[ 6], tmp); + t[13].infinity = 0; + sp_256_proj_point_dbl_8(&t[14], &t[ 7], tmp); + t[14].infinity = 0; + sp_256_proj_point_add_8(&t[15], &t[ 8], &t[ 7], tmp); + t[15].infinity = 0; + + i = 6; + n = k[i+1] << 0; + c = 28; + y = n >> 28; + XMEMCPY(rt, &t[y], sizeof(sp_point)); + n <<= 4; + for (; i>=0 || c>=4; ) { + if (c < 4) { + n |= k[i--] << (0 - c); + c += 32; + } + y = (n >> 28) & 0xf; + n <<= 4; + c -= 4; + + sp_256_proj_point_dbl_8(rt, rt, tmp); + sp_256_proj_point_dbl_8(rt, rt, tmp); + sp_256_proj_point_dbl_8(rt, rt, tmp); + sp_256_proj_point_dbl_8(rt, rt, tmp); + + sp_256_proj_point_add_8(rt, rt, &t[y], tmp); + } + + if (map) + sp_256_map_8(r, rt, tmp); + else + XMEMCPY(r, rt, sizeof(sp_point)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (tmp != NULL) { + XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 8 * 5); + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + } + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_point) * 16); + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } +#else + ForceZero(tmpd, sizeof(tmpd)); + ForceZero(td, sizeof(td)); +#endif + sp_ecc_point_free(rt, 1, heap); + + return err; +} + +/* A table entry for pre-computed points. */ +typedef struct sp_table_entry { + sp_digit x[8]; + sp_digit y[8]; + byte infinity; +} sp_table_entry; + +#ifdef FP_ECC +/* Double the Montgomery form projective point p a number of times. + * + * r Result of repeated doubling of point. + * p Point to double. + * n Number of times to double + * t Temporary ordinate data. + */ +static void sp_256_proj_point_dbl_n_8(sp_point* r, sp_point* p, int n, + sp_digit* t) +{ + sp_point* rp[2]; + sp_digit* w = t; + sp_digit* a = t + 2*8; + sp_digit* b = t + 4*8; + sp_digit* t1 = t + 6*8; + sp_digit* t2 = t + 8*8; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + rp[0] = r; + rp[1] = (sp_point*)t; + XMEMSET(rp[1], 0, sizeof(sp_point)); + x = rp[p->infinity]->x; + y = rp[p->infinity]->y; + z = rp[p->infinity]->z; + if (r != p) { + for (i=0; i<8; i++) + r->x[i] = p->x[i]; + for (i=0; i<8; i++) + r->y[i] = p->y[i]; + for (i=0; i<8; i++) + r->z[i] = p->z[i]; + r->infinity = p->infinity; + } + + /* Y = 2*Y */ + sp_256_mont_dbl_8(y, y, p256_mod); + /* W = Z^4 */ + sp_256_mont_sqr_8(w, z, p256_mod, p256_mp_mod); + sp_256_mont_sqr_8(w, w, p256_mod, p256_mp_mod); + while (n--) { + /* A = 3*(X^2 - W) */ + sp_256_mont_sqr_8(t1, x, p256_mod, p256_mp_mod); + sp_256_mont_sub_8(t1, t1, w, p256_mod); + sp_256_mont_tpl_8(a, t1, p256_mod); + /* B = X*Y^2 */ + sp_256_mont_sqr_8(t2, y, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(b, t2, x, p256_mod, p256_mp_mod); + /* X = A^2 - 2B */ + sp_256_mont_sqr_8(x, a, p256_mod, p256_mp_mod); + sp_256_mont_dbl_8(t1, b, p256_mod); + sp_256_mont_sub_8(x, x, t1, p256_mod); + /* Z = Z*Y */ + sp_256_mont_mul_8(z, z, y, p256_mod, p256_mp_mod); + /* t2 = Y^4 */ + sp_256_mont_sqr_8(t2, t2, p256_mod, p256_mp_mod); + if (n) { + /* W = W*Y^4 */ + sp_256_mont_mul_8(w, w, t2, p256_mod, p256_mp_mod); + } + /* y = 2*A*(B - X) - Y^4 */ + sp_256_mont_sub_8(y, b, x, p256_mod); + sp_256_mont_mul_8(y, y, a, p256_mod, p256_mp_mod); + sp_256_mont_dbl_8(y, y, p256_mod); + sp_256_mont_sub_8(y, y, t2, p256_mod); + } + /* Y = Y/2 */ + sp_256_div2_8(y, y, p256_mod); +} + +/* Convert the projective point to affine. + * Ordinates are in Montgomery form. + * + * a Point to convert. + * t Temprorary data. + */ +static void sp_256_proj_to_affine_8(sp_point* a, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 8; + sp_digit* tmp = t + 4 * 8; + + sp_256_mont_inv_8(t1, a->z, tmp); + + sp_256_mont_sqr_8(t2, t1, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t1, t2, t1, p256_mod, p256_mp_mod); + + sp_256_mont_mul_8(a->x, a->x, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(a->y, a->y, t1, p256_mod, p256_mp_mod); + XMEMCPY(a->z, p256_norm_mod, sizeof(p256_norm_mod)); +} + +#endif /* FP_ECC */ +/* Add two Montgomery form projective points. The second point has a q value of + * one. + * Only the first point can be the same pointer as the result point. + * + * r Result of addition. + * p Frist point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_add_qz1_8(sp_point* r, sp_point* p, + sp_point* q, sp_digit* t) +{ + sp_point* ap[2]; + sp_point* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*8; + sp_digit* t3 = t + 4*8; + sp_digit* t4 = t + 6*8; + sp_digit* t5 = t + 8*8; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* Check double */ + sp_256_sub_8(t1, p256_mod, q->y); + sp_256_norm_8(t1); + if (sp_256_cmp_equal_8(p->x, q->x) & sp_256_cmp_equal_8(p->z, q->z) & + (sp_256_cmp_equal_8(p->y, q->y) | sp_256_cmp_equal_8(p->y, t1))) { + sp_256_proj_point_dbl_8(r, p, t); + } + else { + rp[0] = r; + rp[1] = (sp_point*)t; + XMEMSET(rp[1], 0, sizeof(sp_point)); + x = rp[p->infinity | q->infinity]->x; + y = rp[p->infinity | q->infinity]->y; + z = rp[p->infinity | q->infinity]->z; + + ap[0] = p; + ap[1] = q; + for (i=0; i<8; i++) + r->x[i] = ap[p->infinity]->x[i]; + for (i=0; i<8; i++) + r->y[i] = ap[p->infinity]->y[i]; + for (i=0; i<8; i++) + r->z[i] = ap[p->infinity]->z[i]; + r->infinity = ap[p->infinity]->infinity; + + /* U2 = X2*Z1^2 */ + sp_256_mont_sqr_8(t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t4, t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t2, t2, q->x, p256_mod, p256_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_256_mont_mul_8(t4, t4, q->y, p256_mod, p256_mp_mod); + /* H = U2 - X1 */ + sp_256_mont_sub_8(t2, t2, x, p256_mod); + /* R = S2 - Y1 */ + sp_256_mont_sub_8(t4, t4, y, p256_mod); + /* Z3 = H*Z1 */ + sp_256_mont_mul_8(z, z, t2, p256_mod, p256_mp_mod); + /* X3 = R^2 - H^3 - 2*X1*H^2 */ + sp_256_mont_sqr_8(t1, t4, p256_mod, p256_mp_mod); + sp_256_mont_sqr_8(t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t3, x, t5, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t5, t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_sub_8(x, t1, t5, p256_mod); + sp_256_mont_dbl_8(t1, t3, p256_mod); + sp_256_mont_sub_8(x, x, t1, p256_mod); + /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */ + sp_256_mont_sub_8(t3, t3, x, p256_mod); + sp_256_mont_mul_8(t3, t3, t4, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(t5, t5, y, p256_mod, p256_mp_mod); + sp_256_mont_sub_8(y, t3, t5, p256_mod); + } +} + +#ifdef WOLFSSL_SP_SMALL +#ifdef FP_ECC +/* Generate the pre-computed table of points for the base point. + * + * a The base point. + * table Place to store generated point data. + * tmp Temprorary data. + * heap Heap to use for allocation. + */ +static int sp_256_gen_stripe_table_8(sp_point* a, + sp_table_entry* table, sp_digit* tmp, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point td, s1d, s2d; +#endif + sp_point* t; + sp_point* s1 = NULL; + sp_point* s2 = NULL; + int i, j; + int err; + + (void)heap; + + err = sp_ecc_point_new(heap, td, t); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, s1d, s1); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, s2d, s2); + + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_8(t->x, a->x, p256_mod); + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_8(t->y, a->y, p256_mod); + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_8(t->z, a->z, p256_mod); + if (err == MP_OKAY) { + t->infinity = 0; + sp_256_proj_to_affine_8(t, tmp); + + XMEMCPY(s1->z, p256_norm_mod, sizeof(p256_norm_mod)); + s1->infinity = 0; + XMEMCPY(s2->z, p256_norm_mod, sizeof(p256_norm_mod)); + s2->infinity = 0; + + /* table[0] = {0, 0, infinity} */ + XMEMSET(&table[0], 0, sizeof(sp_table_entry)); + table[0].infinity = 1; + /* table[1] = Affine version of 'a' in Montgomery form */ + XMEMCPY(table[1].x, t->x, sizeof(table->x)); + XMEMCPY(table[1].y, t->y, sizeof(table->y)); + table[1].infinity = 0; + + for (i=1; i<4; i++) { + sp_256_proj_point_dbl_n_8(t, t, 64, tmp); + sp_256_proj_to_affine_8(t, tmp); + XMEMCPY(table[1<x, sizeof(table->x)); + XMEMCPY(table[1<y, sizeof(table->y)); + table[1<x, table[1<x)); + XMEMCPY(s1->y, table[1<y)); + for (j=(1<x, table[j-(1<x)); + XMEMCPY(s2->y, table[j-(1<y)); + sp_256_proj_point_add_qz1_8(t, s1, s2, tmp); + sp_256_proj_to_affine_8(t, tmp); + XMEMCPY(table[j].x, t->x, sizeof(table->x)); + XMEMCPY(table[j].y, t->y, sizeof(table->y)); + table[j].infinity = 0; + } + } + } + + sp_ecc_point_free(s2, 0, heap); + sp_ecc_point_free(s1, 0, heap); + sp_ecc_point_free( t, 0, heap); + + return err; +} + +#endif /* FP_ECC */ +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_stripe_8(sp_point* r, sp_point* g, + sp_table_entry* table, sp_digit* k, int map, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point rtd; + sp_point pd; + sp_digit td[2 * 8 * 5]; +#endif + sp_point* rt; + sp_point* p = NULL; + sp_digit* t; + int i, j; + int y, x; + int err; + + (void)g; + (void)heap; + + err = sp_ecc_point_new(heap, rtd, rt); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 5, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#else + t = td; +#endif + + if (err == MP_OKAY) { + XMEMCPY(p->z, p256_norm_mod, sizeof(p256_norm_mod)); + XMEMCPY(rt->z, p256_norm_mod, sizeof(p256_norm_mod)); + + y = 0; + for (j=0,x=63; j<4; j++,x+=64) + y |= ((k[x / 32] >> (x % 32)) & 1) << j; + XMEMCPY(rt->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(rt->y, table[y].y, sizeof(table[y].y)); + rt->infinity = table[y].infinity; + for (i=62; i>=0; i--) { + y = 0; + for (j=0,x=i; j<4; j++,x+=64) + y |= ((k[x / 32] >> (x % 32)) & 1) << j; + + sp_256_proj_point_dbl_8(rt, rt, t); + XMEMCPY(p->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(p->y, table[y].y, sizeof(table[y].y)); + p->infinity = table[y].infinity; + sp_256_proj_point_add_qz1_8(rt, rt, p, t); + } + + if (map) + sp_256_map_8(r, rt, t); + else + XMEMCPY(r, rt, sizeof(sp_point)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p, 0, heap); + sp_ecc_point_free(rt, 0, heap); + + return err; +} + +#ifdef FP_ECC +#ifndef FP_ENTRIES + #define FP_ENTRIES 16 +#endif + +typedef struct sp_cache_t { + sp_digit x[8]; + sp_digit y[8]; + sp_table_entry table[16]; + uint32_t cnt; + int set; +} sp_cache_t; + +static THREAD_LS_T sp_cache_t sp_cache[FP_ENTRIES]; +static THREAD_LS_T int sp_cache_last = -1; +static THREAD_LS_T int sp_cache_inited = 0; + +#ifndef HAVE_THREAD_LS + static volatile int initCacheMutex = 0; + static wolfSSL_Mutex sp_cache_lock; +#endif + +static void sp_ecc_get_cache(sp_point* g, sp_cache_t** cache) +{ + int i, j; + uint32_t least; + + if (sp_cache_inited == 0) { + for (i=0; ix, sp_cache[i].x) & + sp_256_cmp_equal_8(g->y, sp_cache[i].y)) { + sp_cache[i].cnt++; + break; + } + } + + /* No match. */ + if (i == FP_ENTRIES) { + /* Find empty entry. */ + i = (sp_cache_last + 1) % FP_ENTRIES; + for (; i != sp_cache_last; i=(i+1)%FP_ENTRIES) { + if (!sp_cache[i].set) { + break; + } + } + + /* Evict least used. */ + if (i == sp_cache_last) { + least = sp_cache[0].cnt; + for (j=1; jx, sizeof(sp_cache[i].x)); + XMEMCPY(sp_cache[i].y, g->y, sizeof(sp_cache[i].y)); + sp_cache[i].set = 1; + sp_cache[i].cnt = 1; + } + + *cache = &sp_cache[i]; + sp_cache_last = i; +} +#endif /* FP_ECC */ + +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_8(sp_point* r, sp_point* g, sp_digit* k, + int map, void* heap) +{ +#ifndef FP_ECC + return sp_256_ecc_mulmod_fast_8(r, g, k, map, heap); +#else + sp_digit tmp[2 * 8 * 5]; + sp_cache_t* cache; + int err = MP_OKAY; + +#ifndef HAVE_THREAD_LS + if (initCacheMutex == 0) { + wc_InitMutex(&sp_cache_lock); + initCacheMutex = 1; + } + if (wc_LockMutex(&sp_cache_lock) != 0) + err = BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + if (err == MP_OKAY) { + sp_ecc_get_cache(g, &cache); + if (cache->cnt == 2) + sp_256_gen_stripe_table_8(g, cache->table, tmp, heap); + +#ifndef HAVE_THREAD_LS + wc_UnLockMutex(&sp_cache_lock); +#endif /* HAVE_THREAD_LS */ + + if (cache->cnt < 2) { + err = sp_256_ecc_mulmod_fast_8(r, g, k, map, heap); + } + else { + err = sp_256_ecc_mulmod_stripe_8(r, g, cache->table, k, + map, heap); + } + } + + return err; +#endif +} + +#else +#ifdef FP_ECC +/* Generate the pre-computed table of points for the base point. + * + * a The base point. + * table Place to store generated point data. + * tmp Temprorary data. + * heap Heap to use for allocation. + */ +static int sp_256_gen_stripe_table_8(sp_point* a, + sp_table_entry* table, sp_digit* tmp, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point td, s1d, s2d; +#endif + sp_point* t; + sp_point* s1 = NULL; + sp_point* s2 = NULL; + int i, j; + int err; + + (void)heap; + + err = sp_ecc_point_new(heap, td, t); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, s1d, s1); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, s2d, s2); + + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_8(t->x, a->x, p256_mod); + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_8(t->y, a->y, p256_mod); + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_8(t->z, a->z, p256_mod); + if (err == MP_OKAY) { + t->infinity = 0; + sp_256_proj_to_affine_8(t, tmp); + + XMEMCPY(s1->z, p256_norm_mod, sizeof(p256_norm_mod)); + s1->infinity = 0; + XMEMCPY(s2->z, p256_norm_mod, sizeof(p256_norm_mod)); + s2->infinity = 0; + + /* table[0] = {0, 0, infinity} */ + XMEMSET(&table[0], 0, sizeof(sp_table_entry)); + table[0].infinity = 1; + /* table[1] = Affine version of 'a' in Montgomery form */ + XMEMCPY(table[1].x, t->x, sizeof(table->x)); + XMEMCPY(table[1].y, t->y, sizeof(table->y)); + table[1].infinity = 0; + + for (i=1; i<8; i++) { + sp_256_proj_point_dbl_n_8(t, t, 32, tmp); + sp_256_proj_to_affine_8(t, tmp); + XMEMCPY(table[1<x, sizeof(table->x)); + XMEMCPY(table[1<y, sizeof(table->y)); + table[1<x, table[1<x)); + XMEMCPY(s1->y, table[1<y)); + for (j=(1<x, table[j-(1<x)); + XMEMCPY(s2->y, table[j-(1<y)); + sp_256_proj_point_add_qz1_8(t, s1, s2, tmp); + sp_256_proj_to_affine_8(t, tmp); + XMEMCPY(table[j].x, t->x, sizeof(table->x)); + XMEMCPY(table[j].y, t->y, sizeof(table->y)); + table[j].infinity = 0; + } + } + } + + sp_ecc_point_free(s2, 0, heap); + sp_ecc_point_free(s1, 0, heap); + sp_ecc_point_free( t, 0, heap); + + return err; +} + +#endif /* FP_ECC */ +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_stripe_8(sp_point* r, sp_point* g, + sp_table_entry* table, sp_digit* k, int map, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point rtd; + sp_point pd; + sp_digit td[2 * 8 * 5]; +#endif + sp_point* rt; + sp_point* p = NULL; + sp_digit* t; + int i, j; + int y, x; + int err; + + (void)g; + (void)heap; + + err = sp_ecc_point_new(heap, rtd, rt); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 5, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#else + t = td; +#endif + + if (err == MP_OKAY) { + XMEMCPY(p->z, p256_norm_mod, sizeof(p256_norm_mod)); + XMEMCPY(rt->z, p256_norm_mod, sizeof(p256_norm_mod)); + + y = 0; + for (j=0,x=31; j<8; j++,x+=32) + y |= ((k[x / 32] >> (x % 32)) & 1) << j; + XMEMCPY(rt->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(rt->y, table[y].y, sizeof(table[y].y)); + rt->infinity = table[y].infinity; + for (i=30; i>=0; i--) { + y = 0; + for (j=0,x=i; j<8; j++,x+=32) + y |= ((k[x / 32] >> (x % 32)) & 1) << j; + + sp_256_proj_point_dbl_8(rt, rt, t); + XMEMCPY(p->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(p->y, table[y].y, sizeof(table[y].y)); + p->infinity = table[y].infinity; + sp_256_proj_point_add_qz1_8(rt, rt, p, t); + } + + if (map) + sp_256_map_8(r, rt, t); + else + XMEMCPY(r, rt, sizeof(sp_point)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p, 0, heap); + sp_ecc_point_free(rt, 0, heap); + + return err; +} + +#ifdef FP_ECC +#ifndef FP_ENTRIES + #define FP_ENTRIES 16 +#endif + +typedef struct sp_cache_t { + sp_digit x[8]; + sp_digit y[8]; + sp_table_entry table[256]; + uint32_t cnt; + int set; +} sp_cache_t; + +static THREAD_LS_T sp_cache_t sp_cache[FP_ENTRIES]; +static THREAD_LS_T int sp_cache_last = -1; +static THREAD_LS_T int sp_cache_inited = 0; + +#ifndef HAVE_THREAD_LS + static volatile int initCacheMutex = 0; + static wolfSSL_Mutex sp_cache_lock; +#endif + +static void sp_ecc_get_cache(sp_point* g, sp_cache_t** cache) +{ + int i, j; + uint32_t least; + + if (sp_cache_inited == 0) { + for (i=0; ix, sp_cache[i].x) & + sp_256_cmp_equal_8(g->y, sp_cache[i].y)) { + sp_cache[i].cnt++; + break; + } + } + + /* No match. */ + if (i == FP_ENTRIES) { + /* Find empty entry. */ + i = (sp_cache_last + 1) % FP_ENTRIES; + for (; i != sp_cache_last; i=(i+1)%FP_ENTRIES) { + if (!sp_cache[i].set) { + break; + } + } + + /* Evict least used. */ + if (i == sp_cache_last) { + least = sp_cache[0].cnt; + for (j=1; jx, sizeof(sp_cache[i].x)); + XMEMCPY(sp_cache[i].y, g->y, sizeof(sp_cache[i].y)); + sp_cache[i].set = 1; + sp_cache[i].cnt = 1; + } + + *cache = &sp_cache[i]; + sp_cache_last = i; +} +#endif /* FP_ECC */ + +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_8(sp_point* r, sp_point* g, sp_digit* k, + int map, void* heap) +{ +#ifndef FP_ECC + return sp_256_ecc_mulmod_fast_8(r, g, k, map, heap); +#else + sp_digit tmp[2 * 8 * 5]; + sp_cache_t* cache; + int err = MP_OKAY; + +#ifndef HAVE_THREAD_LS + if (initCacheMutex == 0) { + wc_InitMutex(&sp_cache_lock); + initCacheMutex = 1; + } + if (wc_LockMutex(&sp_cache_lock) != 0) + err = BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + if (err == MP_OKAY) { + sp_ecc_get_cache(g, &cache); + if (cache->cnt == 2) + sp_256_gen_stripe_table_8(g, cache->table, tmp, heap); + +#ifndef HAVE_THREAD_LS + wc_UnLockMutex(&sp_cache_lock); +#endif /* HAVE_THREAD_LS */ + + if (cache->cnt < 2) { + err = sp_256_ecc_mulmod_fast_8(r, g, k, map, heap); + } + else { + err = sp_256_ecc_mulmod_stripe_8(r, g, cache->table, k, + map, heap); + } + } + + return err; +#endif +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * km Scalar to multiply by. + * p Point to multiply. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_256(mp_int* km, ecc_point* gm, ecc_point* r, int map, + void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point p; + sp_digit kd[8]; +#endif + sp_point* point; + sp_digit* k = NULL; + int err = MP_OKAY; + + err = sp_ecc_point_new(heap, p, point); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + if (err == MP_OKAY) { + sp_256_from_mp(k, 8, km); + sp_256_point_from_ecc_point_8(point, gm); + + err = sp_256_ecc_mulmod_8(point, point, k, map, heap); + } + if (err == MP_OKAY) + err = sp_256_point_to_ecc_point_8(point, r); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(point, 0, heap); + + return err; +} + +#ifdef WOLFSSL_SP_SMALL +static sp_table_entry p256_table[16] = { + /* 0 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 */ + { { 0x18a9143c,0x79e730d4,0x5fedb601,0x75ba95fc,0x77622510,0x79fb732b, + 0xa53755c6,0x18905f76 }, + { 0xce95560a,0xddf25357,0xba19e45c,0x8b4ab8e4,0xdd21f325,0xd2e88688, + 0x25885d85,0x8571ff18 }, + 0 }, + /* 2 */ + { { 0x16a0d2bb,0x4f922fc5,0x1a623499,0x0d5cc16c,0x57c62c8b,0x9241cf3a, + 0xfd1b667f,0x2f5e6961 }, + { 0xf5a01797,0x5c15c70b,0x60956192,0x3d20b44d,0x071fdb52,0x04911b37, + 0x8d6f0f7b,0xf648f916 }, + 0 }, + /* 3 */ + { { 0xe137bbbc,0x9e566847,0x8a6a0bec,0xe434469e,0x79d73463,0xb1c42761, + 0x133d0015,0x5abe0285 }, + { 0xc04c7dab,0x92aa837c,0x43260c07,0x573d9f4c,0x78e6cc37,0x0c931562, + 0x6b6f7383,0x94bb725b }, + 0 }, + /* 4 */ + { { 0xbfe20925,0x62a8c244,0x8fdce867,0x91c19ac3,0xdd387063,0x5a96a5d5, + 0x21d324f6,0x61d587d4 }, + { 0xa37173ea,0xe87673a2,0x53778b65,0x23848008,0x05bab43e,0x10f8441e, + 0x4621efbe,0xfa11fe12 }, + 0 }, + /* 5 */ + { { 0x2cb19ffd,0x1c891f2b,0xb1923c23,0x01ba8d5b,0x8ac5ca8e,0xb6d03d67, + 0x1f13bedc,0x586eb04c }, + { 0x27e8ed09,0x0c35c6e5,0x1819ede2,0x1e81a33c,0x56c652fa,0x278fd6c0, + 0x70864f11,0x19d5ac08 }, + 0 }, + /* 6 */ + { { 0xd2b533d5,0x62577734,0xa1bdddc0,0x673b8af6,0xa79ec293,0x577e7c9a, + 0xc3b266b1,0xbb6de651 }, + { 0xb65259b3,0xe7e9303a,0xd03a7480,0xd6a0afd3,0x9b3cfc27,0xc5ac83d1, + 0x5d18b99b,0x60b4619a }, + 0 }, + /* 7 */ + { { 0x1ae5aa1c,0xbd6a38e1,0x49e73658,0xb8b7652b,0xee5f87ed,0x0b130014, + 0xaeebffcd,0x9d0f27b2 }, + { 0x7a730a55,0xca924631,0xddbbc83a,0x9c955b2f,0xac019a71,0x07c1dfe0, + 0x356ec48d,0x244a566d }, + 0 }, + /* 8 */ + { { 0xf4f8b16a,0x56f8410e,0xc47b266a,0x97241afe,0x6d9c87c1,0x0a406b8e, + 0xcd42ab1b,0x803f3e02 }, + { 0x04dbec69,0x7f0309a8,0x3bbad05f,0xa83b85f7,0xad8e197f,0xc6097273, + 0x5067adc1,0xc097440e }, + 0 }, + /* 9 */ + { { 0xc379ab34,0x846a56f2,0x841df8d1,0xa8ee068b,0x176c68ef,0x20314459, + 0x915f1f30,0xf1af32d5 }, + { 0x5d75bd50,0x99c37531,0xf72f67bc,0x837cffba,0x48d7723f,0x0613a418, + 0xe2d41c8b,0x23d0f130 }, + 0 }, + /* 10 */ + { { 0xd5be5a2b,0xed93e225,0x5934f3c6,0x6fe79983,0x22626ffc,0x43140926, + 0x7990216a,0x50bbb4d9 }, + { 0xe57ec63e,0x378191c6,0x181dcdb2,0x65422c40,0x0236e0f6,0x41a8099b, + 0x01fe49c3,0x2b100118 }, + 0 }, + /* 11 */ + { { 0x9b391593,0xfc68b5c5,0x598270fc,0xc385f5a2,0xd19adcbb,0x7144f3aa, + 0x83fbae0c,0xdd558999 }, + { 0x74b82ff4,0x93b88b8e,0x71e734c9,0xd2e03c40,0x43c0322a,0x9a7a9eaf, + 0x149d6041,0xe6e4c551 }, + 0 }, + /* 12 */ + { { 0x80ec21fe,0x5fe14bfe,0xc255be82,0xf6ce116a,0x2f4a5d67,0x98bc5a07, + 0xdb7e63af,0xfad27148 }, + { 0x29ab05b3,0x90c0b6ac,0x4e251ae6,0x37a9a83c,0xc2aade7d,0x0a7dc875, + 0x9f0e1a84,0x77387de3 }, + 0 }, + /* 13 */ + { { 0xa56c0dd7,0x1e9ecc49,0x46086c74,0xa5cffcd8,0xf505aece,0x8f7a1408, + 0xbef0c47e,0xb37b85c0 }, + { 0xcc0e6a8f,0x3596b6e4,0x6b388f23,0xfd6d4bbf,0xc39cef4e,0xaba453fa, + 0xf9f628d5,0x9c135ac8 }, + 0 }, + /* 14 */ + { { 0x95c8f8be,0x0a1c7294,0x3bf362bf,0x2961c480,0xdf63d4ac,0x9e418403, + 0x91ece900,0xc109f9cb }, + { 0x58945705,0xc2d095d0,0xddeb85c0,0xb9083d96,0x7a40449b,0x84692b8d, + 0x2eee1ee1,0x9bc3344f }, + 0 }, + /* 15 */ + { { 0x42913074,0x0d5ae356,0x48a542b1,0x55491b27,0xb310732a,0x469ca665, + 0x5f1a4cc1,0x29591d52 }, + { 0xb84f983f,0xe76f5b6b,0x9f5f84e1,0xbe7eef41,0x80baa189,0x1200d496, + 0x18ef332c,0x6376551f }, + 0 }, +}; + +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_base_8(sp_point* r, sp_digit* k, + int map, void* heap) +{ + return sp_256_ecc_mulmod_stripe_8(r, &p256_base, p256_table, + k, map, heap); +} + +#else +static sp_table_entry p256_table[256] = { + /* 0 */ + { { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 */ + { { 0x18a9143c,0x79e730d4,0x5fedb601,0x75ba95fc,0x77622510,0x79fb732b, + 0xa53755c6,0x18905f76 }, + { 0xce95560a,0xddf25357,0xba19e45c,0x8b4ab8e4,0xdd21f325,0xd2e88688, + 0x25885d85,0x8571ff18 }, + 0 }, + /* 2 */ + { { 0x4147519a,0x20288602,0x26b372f0,0xd0981eac,0xa785ebc8,0xa9d4a7ca, + 0xdbdf58e9,0xd953c50d }, + { 0xfd590f8f,0x9d6361cc,0x44e6c917,0x72e9626b,0x22eb64cf,0x7fd96110, + 0x9eb288f3,0x863ebb7e }, + 0 }, + /* 3 */ + { { 0x5cdb6485,0x7856b623,0x2f0a2f97,0x808f0ea2,0x4f7e300b,0x3e68d954, + 0xb5ff80a0,0x00076055 }, + { 0x838d2010,0x7634eb9b,0x3243708a,0x54014fbb,0x842a6606,0xe0e47d39, + 0x34373ee0,0x83087761 }, + 0 }, + /* 4 */ + { { 0x16a0d2bb,0x4f922fc5,0x1a623499,0x0d5cc16c,0x57c62c8b,0x9241cf3a, + 0xfd1b667f,0x2f5e6961 }, + { 0xf5a01797,0x5c15c70b,0x60956192,0x3d20b44d,0x071fdb52,0x04911b37, + 0x8d6f0f7b,0xf648f916 }, + 0 }, + /* 5 */ + { { 0xe137bbbc,0x9e566847,0x8a6a0bec,0xe434469e,0x79d73463,0xb1c42761, + 0x133d0015,0x5abe0285 }, + { 0xc04c7dab,0x92aa837c,0x43260c07,0x573d9f4c,0x78e6cc37,0x0c931562, + 0x6b6f7383,0x94bb725b }, + 0 }, + /* 6 */ + { { 0x720f141c,0xbbf9b48f,0x2df5bc74,0x6199b3cd,0x411045c4,0xdc3f6129, + 0x2f7dc4ef,0xcdd6bbcb }, + { 0xeaf436fd,0xcca6700b,0xb99326be,0x6f647f6d,0x014f2522,0x0c0fa792, + 0x4bdae5f6,0xa361bebd }, + 0 }, + /* 7 */ + { { 0x597c13c7,0x28aa2558,0x50b7c3e1,0xc38d635f,0xf3c09d1d,0x07039aec, + 0xc4b5292c,0xba12ca09 }, + { 0x59f91dfd,0x9e408fa4,0xceea07fb,0x3af43b66,0x9d780b29,0x1eceb089, + 0x701fef4b,0x53ebb99d }, + 0 }, + /* 8 */ + { { 0xb0e63d34,0x4fe7ee31,0xa9e54fab,0xf4600572,0xd5e7b5a4,0xc0493334, + 0x06d54831,0x8589fb92 }, + { 0x6583553a,0xaa70f5cc,0xe25649e5,0x0879094a,0x10044652,0xcc904507, + 0x02541c4f,0xebb0696d }, + 0 }, + /* 9 */ + { { 0xac1647c5,0x4616ca15,0xc4cf5799,0xb8127d47,0x764dfbac,0xdc666aa3, + 0xd1b27da3,0xeb2820cb }, + { 0x6a87e008,0x9406f8d8,0x922378f3,0xd87dfa9d,0x80ccecb2,0x56ed2e42, + 0x55a7da1d,0x1f28289b }, + 0 }, + /* 10 */ + { { 0x3b89da99,0xabbaa0c0,0xb8284022,0xa6f2d79e,0xb81c05e8,0x27847862, + 0x05e54d63,0x337a4b59 }, + { 0x21f7794a,0x3c67500d,0x7d6d7f61,0x207005b7,0x04cfd6e8,0x0a5a3781, + 0xf4c2fbd6,0x0d65e0d5 }, + 0 }, + /* 11 */ + { { 0xb5275d38,0xd9d09bbe,0x0be0a358,0x4268a745,0x973eb265,0xf0762ff4, + 0x52f4a232,0xc23da242 }, + { 0x0b94520c,0x5da1b84f,0xb05bd78e,0x09666763,0x94d29ea1,0x3a4dcb86, + 0xc790cff1,0x19de3b8c }, + 0 }, + /* 12 */ + { { 0x26c5fe04,0x183a716c,0x3bba1bdb,0x3b28de0b,0xa4cb712c,0x7432c586, + 0x91fccbfd,0xe34dcbd4 }, + { 0xaaa58403,0xb408d46b,0x82e97a53,0x9a697486,0x36aaa8af,0x9e390127, + 0x7b4e0f7f,0xe7641f44 }, + 0 }, + /* 13 */ + { { 0xdf64ba59,0x7d753941,0x0b0242fc,0xd33f10ec,0xa1581859,0x4f06dfc6, + 0x052a57bf,0x4a12df57 }, + { 0x9439dbd0,0xbfa6338f,0xbde53e1f,0xd3c24bd4,0x21f1b314,0xfd5e4ffa, + 0xbb5bea46,0x6af5aa93 }, + 0 }, + /* 14 */ + { { 0x10c91999,0xda10b699,0x2a580491,0x0a24b440,0xb8cc2090,0x3e0094b4, + 0x66a44013,0x5fe3475a }, + { 0xf93e7b4b,0xb0f8cabd,0x7c23f91a,0x292b501a,0xcd1e6263,0x42e889ae, + 0xecfea916,0xb544e308 }, + 0 }, + /* 15 */ + { { 0x16ddfdce,0x6478c6e9,0xf89179e6,0x2c329166,0x4d4e67e1,0x4e8d6e76, + 0xa6b0c20b,0xe0b6b2bd }, + { 0xbb7efb57,0x0d312df2,0x790c4007,0x1aac0dde,0x679bc944,0xf90336ad, + 0x25a63774,0x71c023de }, + 0 }, + /* 16 */ + { { 0xbfe20925,0x62a8c244,0x8fdce867,0x91c19ac3,0xdd387063,0x5a96a5d5, + 0x21d324f6,0x61d587d4 }, + { 0xa37173ea,0xe87673a2,0x53778b65,0x23848008,0x05bab43e,0x10f8441e, + 0x4621efbe,0xfa11fe12 }, + 0 }, + /* 17 */ + { { 0x2cb19ffd,0x1c891f2b,0xb1923c23,0x01ba8d5b,0x8ac5ca8e,0xb6d03d67, + 0x1f13bedc,0x586eb04c }, + { 0x27e8ed09,0x0c35c6e5,0x1819ede2,0x1e81a33c,0x56c652fa,0x278fd6c0, + 0x70864f11,0x19d5ac08 }, + 0 }, + /* 18 */ + { { 0x309a4e1f,0x1e99f581,0xe9270074,0xab7de71b,0xefd28d20,0x26a5ef0b, + 0x7f9c563f,0xe7c0073f }, + { 0x0ef59f76,0x1f6d663a,0x20fcb050,0x669b3b54,0x7a6602d4,0xc08c1f7a, + 0xc65b3c0a,0xe08504fe }, + 0 }, + /* 19 */ + { { 0xa031b3ca,0xf098f68d,0xe6da6d66,0x6d1cab9e,0x94f246e8,0x5bfd81fa, + 0x5b0996b4,0x78f01882 }, + { 0x3a25787f,0xb7eefde4,0x1dccac9b,0x8016f80d,0xb35bfc36,0x0cea4877, + 0x7e94747a,0x43a773b8 }, + 0 }, + /* 20 */ + { { 0xd2b533d5,0x62577734,0xa1bdddc0,0x673b8af6,0xa79ec293,0x577e7c9a, + 0xc3b266b1,0xbb6de651 }, + { 0xb65259b3,0xe7e9303a,0xd03a7480,0xd6a0afd3,0x9b3cfc27,0xc5ac83d1, + 0x5d18b99b,0x60b4619a }, + 0 }, + /* 21 */ + { { 0x1ae5aa1c,0xbd6a38e1,0x49e73658,0xb8b7652b,0xee5f87ed,0x0b130014, + 0xaeebffcd,0x9d0f27b2 }, + { 0x7a730a55,0xca924631,0xddbbc83a,0x9c955b2f,0xac019a71,0x07c1dfe0, + 0x356ec48d,0x244a566d }, + 0 }, + /* 22 */ + { { 0xeacf1f96,0x6db0394a,0x024c271c,0x9f2122a9,0x82cbd3b9,0x2626ac1b, + 0x3581ef69,0x45e58c87 }, + { 0xa38f9dbc,0xd3ff479d,0xe888a040,0xa8aaf146,0x46e0bed7,0x945adfb2, + 0xc1e4b7a4,0xc040e21c }, + 0 }, + /* 23 */ + { { 0x6f8117b6,0x847af000,0x73a35433,0x651969ff,0x1d9475eb,0x482b3576, + 0x682c6ec7,0x1cdf5c97 }, + { 0x11f04839,0x7db775b4,0x48de1698,0x7dbeacf4,0xb70b3219,0xb2921dd1, + 0xa92dff3d,0x046755f8 }, + 0 }, + /* 24 */ + { { 0xbce8ffcd,0xcc8ac5d2,0x2fe61a82,0x0d53c48b,0x7202d6c7,0xf6f16172, + 0x3b83a5f3,0x046e5e11 }, + { 0xd8007f01,0xe7b8ff64,0x5af43183,0x7fb1ef12,0x35e1a03c,0x045c5ea6, + 0x303d005b,0x6e0106c3 }, + 0 }, + /* 25 */ + { { 0x88dd73b1,0x48c73584,0x995ed0d9,0x7670708f,0xc56a2ab7,0x38385ea8, + 0xe901cf1f,0x442594ed }, + { 0x12d4b65b,0xf8faa2c9,0x96c90c37,0x94c2343b,0x5e978d1f,0xd326e4a1, + 0x4c2ee68e,0xa796fa51 }, + 0 }, + /* 26 */ + { { 0x823addd7,0x359fb604,0xe56693b3,0x9e2a6183,0x3cbf3c80,0xf885b78e, + 0xc69766e9,0xe4ad2da9 }, + { 0x8e048a61,0x357f7f42,0xc092d9a0,0x082d198c,0xc03ed8ef,0xfc3a1af4, + 0xc37b5143,0xc5e94046 }, + 0 }, + /* 27 */ + { { 0x2be75f9e,0x476a538c,0xcb123a78,0x6fd1a9e8,0xb109c04b,0xd85e4df0, + 0xdb464747,0x63283daf }, + { 0xbaf2df15,0xce728cf7,0x0ad9a7f4,0xe592c455,0xe834bcc3,0xfab226ad, + 0x1981a938,0x68bd19ab }, + 0 }, + /* 28 */ + { { 0x1887d659,0xc08ead51,0xb359305a,0x3374d5f4,0xcfe74fe3,0x96986981, + 0x3c6fdfd6,0x495292f5 }, + { 0x1acec896,0x4a878c9e,0xec5b4484,0xd964b210,0x664d60a7,0x6696f7e2, + 0x26036837,0x0ec7530d }, + 0 }, + /* 29 */ + { { 0xad2687bb,0x2da13a05,0xf32e21fa,0xa1f83b6a,0x1dd4607b,0x390f5ef5, + 0x64863f0b,0x0f6207a6 }, + { 0x0f138233,0xbd67e3bb,0x272aa718,0xdd66b96c,0x26ec88ae,0x8ed00407, + 0x08ed6dcf,0xff0db072 }, + 0 }, + /* 30 */ + { { 0x4c95d553,0x749fa101,0x5d680a8a,0xa44052fd,0xff3b566f,0x183b4317, + 0x88740ea3,0x313b513c }, + { 0x08d11549,0xb402e2ac,0xb4dee21c,0x071ee10b,0x47f2320e,0x26b987dd, + 0x86f19f81,0x2d3abcf9 }, + 0 }, + /* 31 */ + { { 0x815581a2,0x4c288501,0x632211af,0x9a0a6d56,0x0cab2e99,0x19ba7a0f, + 0xded98cdf,0xc036fa10 }, + { 0xc1fbd009,0x29ae08ba,0x06d15816,0x0b68b190,0x9b9e0d8f,0xc2eb3277, + 0xb6d40194,0xa6b2a2c4 }, + 0 }, + /* 32 */ + { { 0x6d3549cf,0xd433e50f,0xfacd665e,0x6f33696f,0xce11fcb4,0x695bfdac, + 0xaf7c9860,0x810ee252 }, + { 0x7159bb2c,0x65450fe1,0x758b357b,0xf7dfbebe,0xd69fea72,0x2b057e74, + 0x92731745,0xd485717a }, + 0 }, + /* 33 */ + { { 0xf0cb5a98,0x11741a8a,0x1f3110bf,0xd3da8f93,0xab382adf,0x1994e2cb, + 0x2f9a604e,0x6a6045a7 }, + { 0xa2b2411d,0x170c0d3f,0x510e96e0,0xbe0eb83e,0x8865b3cc,0x3bcc9f73, + 0xf9e15790,0xd3e45cfa }, + 0 }, + /* 34 */ + { { 0xe83f7669,0xce1f69bb,0x72877d6b,0x09f8ae82,0x3244278d,0x9548ae54, + 0xe3c2c19c,0x207755de }, + { 0x6fef1945,0x87bd61d9,0xb12d28c3,0x18813cef,0x72df64aa,0x9fbcd1d6, + 0x7154b00d,0x48dc5ee5 }, + 0 }, + /* 35 */ + { { 0xf7e5a199,0x123790bf,0x989ccbb7,0xe0efb8cf,0x0a519c79,0xc27a2bfe, + 0xdff6f445,0xf2fb0aed }, + { 0xf0b5025f,0x41c09575,0x40fa9f22,0x550543d7,0x380bfbd0,0x8fa3c8ad, + 0xdb28d525,0xa13e9015 }, + 0 }, + /* 36 */ + { { 0xa2b65cbc,0xf9f7a350,0x2a464226,0x0b04b972,0xe23f07a1,0x265ce241, + 0x1497526f,0x2bf0d6b0 }, + { 0x4b216fb7,0xd3d4dd3f,0xfbdda26a,0xf7d7b867,0x6708505c,0xaeb7b83f, + 0x162fe89f,0x42a94a5a }, + 0 }, + /* 37 */ + { { 0xeaadf191,0x5846ad0b,0x25a268d7,0x0f8a4890,0x494dc1f6,0xe8603050, + 0xc65ede3d,0x2c2dd969 }, + { 0x93849c17,0x6d02171d,0x1da250dd,0x460488ba,0x3c3a5485,0x4810c706, + 0x42c56dbc,0xf437fa1f }, + 0 }, + /* 38 */ + { { 0x4a0f7dab,0x6aa0d714,0x1776e9ac,0x0f049793,0xf5f39786,0x52c0a050, + 0x54707aa8,0xaaf45b33 }, + { 0xc18d364a,0x85e37c33,0x3e497165,0xd40b9b06,0x15ec5444,0xf4171681, + 0xf4f272bc,0xcdf6310d }, + 0 }, + /* 39 */ + { { 0x8ea8b7ef,0x7473c623,0x85bc2287,0x08e93518,0x2bda8e34,0x41956772, + 0xda9e2ff2,0xf0d008ba }, + { 0x2414d3b1,0x2912671d,0xb019ea76,0xb3754985,0x453bcbdb,0x5c61b96d, + 0xca887b8b,0x5bd5c2f5 }, + 0 }, + /* 40 */ + { { 0xf49a3154,0xef0f469e,0x6e2b2e9a,0x3e85a595,0xaa924a9c,0x45aaec1e, + 0xa09e4719,0xaa12dfc8 }, + { 0x4df69f1d,0x26f27227,0xa2ff5e73,0xe0e4c82c,0xb7a9dd44,0xb9d8ce73, + 0xe48ca901,0x6c036e73 }, + 0 }, + /* 41 */ + { { 0x0f6e3138,0x5cfae12a,0x25ad345a,0x6966ef00,0x45672bc5,0x8993c64b, + 0x96afbe24,0x292ff658 }, + { 0x5e213402,0xd5250d44,0x4392c9fe,0xf6580e27,0xda1c72e8,0x097b397f, + 0x311b7276,0x644e0c90 }, + 0 }, + /* 42 */ + { { 0xa47153f0,0xe1e421e1,0x920418c9,0xb86c3b79,0x705d7672,0x93bdce87, + 0xcab79a77,0xf25ae793 }, + { 0x6d869d0c,0x1f3194a3,0x4986c264,0x9d55c882,0x096e945e,0x49fb5ea3, + 0x13db0a3e,0x39b8e653 }, + 0 }, + /* 43 */ + { { 0xb6fd2e59,0x37754200,0x9255c98f,0x35e2c066,0x0e2a5739,0xd9dab21a, + 0x0f19db06,0x39122f2f }, + { 0x03cad53c,0xcfbce1e0,0xe65c17e3,0x225b2c0f,0x9aa13877,0x72baf1d2, + 0xce80ff8d,0x8de80af8 }, + 0 }, + /* 44 */ + { { 0x207bbb76,0xafbea8d9,0x21782758,0x921c7e7c,0x1c0436b1,0xdfa2b74b, + 0x2e368c04,0x87194906 }, + { 0xa3993df5,0xb5f928bb,0xf3b3d26a,0x639d75b5,0x85b55050,0x011aa78a, + 0x5b74fde1,0xfc315e6a }, + 0 }, + /* 45 */ + { { 0xe8d6ecfa,0x561fd41a,0x1aec7f86,0x5f8c44f6,0x4924741d,0x98452a7b, + 0xee389088,0xe6d4a7ad }, + { 0x4593c75d,0x60552ed1,0xdd271162,0x70a70da4,0x7ba2c7db,0xd2aede93, + 0x9be2ae57,0x35dfaf9a }, + 0 }, + /* 46 */ + { { 0xaa736636,0x6b956fcd,0xae2cab7e,0x09f51d97,0x0f349966,0xfb10bf41, + 0x1c830d2b,0x1da5c7d7 }, + { 0x3cce6825,0x5c41e483,0xf9573c3b,0x15ad118f,0xf23036b8,0xa28552c7, + 0xdbf4b9d6,0x7077c0fd }, + 0 }, + /* 47 */ + { { 0x46b9661c,0xbf63ff8d,0x0d2cfd71,0xa1dfd36b,0xa847f8f7,0x0373e140, + 0xe50efe44,0x53a8632e }, + { 0x696d8051,0x0976ff68,0xc74f468a,0xdaec0c95,0x5e4e26bd,0x62994dc3, + 0x34e1fcc1,0x028ca76d }, + 0 }, + /* 48 */ + { { 0xfc9877ee,0xd11d47dc,0x801d0002,0xc8b36210,0x54c260b6,0xd002c117, + 0x6962f046,0x04c17cd8 }, + { 0xb0daddf5,0x6d9bd094,0x24ce55c0,0xbea23575,0x72da03b5,0x663356e6, + 0xfed97474,0xf7ba4de9 }, + 0 }, + /* 49 */ + { { 0xebe1263f,0xd0dbfa34,0x71ae7ce6,0x55763735,0x82a6f523,0xd2440553, + 0x52131c41,0xe31f9600 }, + { 0xea6b6ec6,0xd1bb9216,0x73c2fc44,0x37a1d12e,0x89d0a294,0xc10e7eac, + 0xce34d47b,0xaa3a6259 }, + 0 }, + /* 50 */ + { { 0x36f3dcd3,0xfbcf9df5,0xd2bf7360,0x6ceded50,0xdf504f5b,0x491710fa, + 0x7e79daee,0x2398dd62 }, + { 0x6d09569e,0xcf4705a3,0x5149f769,0xea0619bb,0x35f6034c,0xff9c0377, + 0x1c046210,0x5717f5b2 }, + 0 }, + /* 51 */ + { { 0x21dd895e,0x9fe229c9,0x40c28451,0x8e518500,0x1d637ecd,0xfa13d239, + 0x0e3c28de,0x660a2c56 }, + { 0xd67fcbd0,0x9cca88ae,0x0ea9f096,0xc8472478,0x72e92b4d,0x32b2f481, + 0x4f522453,0x624ee54c }, + 0 }, + /* 52 */ + { { 0xd897eccc,0x09549ce4,0x3f9880aa,0x4d49d1d9,0x043a7c20,0x723c2423, + 0x92bdfbc0,0x4f392afb }, + { 0x7de44fd9,0x6969f8fa,0x57b32156,0xb66cfbe4,0x368ebc3c,0xdb2fa803, + 0xccdb399c,0x8a3e7977 }, + 0 }, + /* 53 */ + { { 0x06c4b125,0xdde1881f,0xf6e3ca8c,0xae34e300,0x5c7a13e9,0xef6999de, + 0x70c24404,0x3888d023 }, + { 0x44f91081,0x76280356,0x5f015504,0x3d9fcf61,0x632cd36e,0x1827edc8, + 0x18102336,0xa5e62e47 }, + 0 }, + /* 54 */ + { { 0x2facd6c8,0x1a825ee3,0x54bcbc66,0x699c6354,0x98df9931,0x0ce3edf7, + 0x466a5adc,0x2c4768e6 }, + { 0x90a64bc9,0xb346ff8c,0xe4779f5c,0x630a6020,0xbc05e884,0xd949d064, + 0xf9e652a0,0x7b5e6441 }, + 0 }, + /* 55 */ + { { 0x1d28444a,0x2169422c,0xbe136a39,0xe996c5d8,0xfb0c7fce,0x2387afe5, + 0x0c8d744a,0xb8af73cb }, + { 0x338b86fd,0x5fde83aa,0xa58a5cff,0xfee3f158,0x20ac9433,0xc9ee8f6f, + 0x7f3f0895,0xa036395f }, + 0 }, + /* 56 */ + { { 0xa10f7770,0x8c73c6bb,0xa12a0e24,0xa6f16d81,0x51bc2b9f,0x100df682, + 0x875fb533,0x4be36b01 }, + { 0x9fb56dbb,0x9226086e,0x07e7a4f8,0x306fef8b,0x66d52f20,0xeeaccc05, + 0x1bdc00c0,0x8cbc9a87 }, + 0 }, + /* 57 */ + { { 0xc0dac4ab,0xe131895c,0x712ff112,0xa874a440,0x6a1cee57,0x6332ae7c, + 0x0c0835f8,0x44e7553e }, + { 0x7734002d,0x6d503fff,0x0b34425c,0x9d35cb8b,0x0e8738b5,0x95f70276, + 0x5eb8fc18,0x470a683a }, + 0 }, + /* 58 */ + { { 0x90513482,0x81b761dc,0x01e9276a,0x0287202a,0x0ce73083,0xcda441ee, + 0xc63dc6ef,0x16410690 }, + { 0x6d06a2ed,0xf5034a06,0x189b100b,0xdd4d7745,0xab8218c9,0xd914ae72, + 0x7abcbb4f,0xd73479fd }, + 0 }, + /* 59 */ + { { 0x5ad4c6e5,0x7edefb16,0x5b06d04d,0x262cf08f,0x8575cb14,0x12ed5bb1, + 0x0771666b,0x816469e3 }, + { 0x561e291e,0xd7ab9d79,0xc1de1661,0xeb9daf22,0x135e0513,0xf49827eb, + 0xf0dd3f9c,0x0a36dd23 }, + 0 }, + /* 60 */ + { { 0x41d5533c,0x098d32c7,0x8684628f,0x7c5f5a9e,0xe349bd11,0x39a228ad, + 0xfdbab118,0xe331dfd6 }, + { 0x6bcc6ed8,0x5100ab68,0xef7a260e,0x7160c3bd,0xbce850d7,0x9063d9a7, + 0x492e3389,0xd3b4782a }, + 0 }, + /* 61 */ + { { 0xf3821f90,0xa149b6e8,0x66eb7aad,0x92edd9ed,0x1a013116,0x0bb66953, + 0x4c86a5bd,0x7281275a }, + { 0xd3ff47e5,0x503858f7,0x61016441,0x5e1616bc,0x7dfd9bb1,0x62b0f11a, + 0xce145059,0x2c062e7e }, + 0 }, + /* 62 */ + { { 0x0159ac2e,0xa76f996f,0xcbdb2713,0x281e7736,0x08e46047,0x2ad6d288, + 0x2c4e7ef1,0x282a35f9 }, + { 0xc0ce5cd2,0x9c354b1e,0x1379c229,0xcf99efc9,0x3e82c11e,0x992caf38, + 0x554d2abd,0xc71cd513 }, + 0 }, + /* 63 */ + { { 0x09b578f4,0x4885de9c,0xe3affa7a,0x1884e258,0x59182f1f,0x8f76b1b7, + 0xcf47f3a3,0xc50f6740 }, + { 0x374b68ea,0xa9c4adf3,0x69965fe2,0xa406f323,0x85a53050,0x2f86a222, + 0x212958dc,0xb9ecb3a7 }, + 0 }, + /* 64 */ + { { 0xf4f8b16a,0x56f8410e,0xc47b266a,0x97241afe,0x6d9c87c1,0x0a406b8e, + 0xcd42ab1b,0x803f3e02 }, + { 0x04dbec69,0x7f0309a8,0x3bbad05f,0xa83b85f7,0xad8e197f,0xc6097273, + 0x5067adc1,0xc097440e }, + 0 }, + /* 65 */ + { { 0xc379ab34,0x846a56f2,0x841df8d1,0xa8ee068b,0x176c68ef,0x20314459, + 0x915f1f30,0xf1af32d5 }, + { 0x5d75bd50,0x99c37531,0xf72f67bc,0x837cffba,0x48d7723f,0x0613a418, + 0xe2d41c8b,0x23d0f130 }, + 0 }, + /* 66 */ + { { 0xf41500d9,0x857ab6ed,0xfcbeada8,0x0d890ae5,0x89725951,0x52fe8648, + 0xc0a3fadd,0xb0288dd6 }, + { 0x650bcb08,0x85320f30,0x695d6e16,0x71af6313,0xb989aa76,0x31f520a7, + 0xf408c8d2,0xffd3724f }, + 0 }, + /* 67 */ + { { 0xb458e6cb,0x53968e64,0x317a5d28,0x992dad20,0x7aa75f56,0x3814ae0b, + 0xd78c26df,0xf5590f4a }, + { 0xcf0ba55a,0x0fc24bd3,0x0c778bae,0x0fc4724a,0x683b674a,0x1ce9864f, + 0xf6f74a20,0x18d6da54 }, + 0 }, + /* 68 */ + { { 0xd5be5a2b,0xed93e225,0x5934f3c6,0x6fe79983,0x22626ffc,0x43140926, + 0x7990216a,0x50bbb4d9 }, + { 0xe57ec63e,0x378191c6,0x181dcdb2,0x65422c40,0x0236e0f6,0x41a8099b, + 0x01fe49c3,0x2b100118 }, + 0 }, + /* 69 */ + { { 0x9b391593,0xfc68b5c5,0x598270fc,0xc385f5a2,0xd19adcbb,0x7144f3aa, + 0x83fbae0c,0xdd558999 }, + { 0x74b82ff4,0x93b88b8e,0x71e734c9,0xd2e03c40,0x43c0322a,0x9a7a9eaf, + 0x149d6041,0xe6e4c551 }, + 0 }, + /* 70 */ + { { 0x1e9af288,0x55f655bb,0xf7ada931,0x647e1a64,0xcb2820e5,0x43697e4b, + 0x07ed56ff,0x51e00db1 }, + { 0x771c327e,0x43d169b8,0x4a96c2ad,0x29cdb20b,0x3deb4779,0xc07d51f5, + 0x49829177,0xe22f4241 }, + 0 }, + /* 71 */ + { { 0x635f1abb,0xcd45e8f4,0x68538874,0x7edc0cb5,0xb5a8034d,0xc9472c1f, + 0x52dc48c9,0xf709373d }, + { 0xa8af30d6,0x401966bb,0xf137b69c,0x95bf5f4a,0x9361c47e,0x3966162a, + 0xe7275b11,0xbd52d288 }, + 0 }, + /* 72 */ + { { 0x9c5fa877,0xab155c7a,0x7d3a3d48,0x17dad672,0x73d189d8,0x43f43f9e, + 0xc8aa77a6,0xa0d0f8e4 }, + { 0xcc94f92d,0x0bbeafd8,0x0c4ddb3a,0xd818c8be,0xb82eba14,0x22cc65f8, + 0x946d6a00,0xa56c78c7 }, + 0 }, + /* 73 */ + { { 0x0dd09529,0x2962391b,0x3daddfcf,0x803e0ea6,0x5b5bf481,0x2c77351f, + 0x731a367a,0xd8befdf8 }, + { 0xfc0157f4,0xab919d42,0xfec8e650,0xf51caed7,0x02d48b0a,0xcdf9cb40, + 0xce9f6478,0x854a68a5 }, + 0 }, + /* 74 */ + { { 0x63506ea5,0xdc35f67b,0xa4fe0d66,0x9286c489,0xfe95cd4d,0x3f101d3b, + 0x98846a95,0x5cacea0b }, + { 0x9ceac44d,0xa90df60c,0x354d1c3a,0x3db29af4,0xad5dbabe,0x08dd3de8, + 0x35e4efa9,0xe4982d12 }, + 0 }, + /* 75 */ + { { 0xc34cd55e,0x23104a22,0x2680d132,0x58695bb3,0x1fa1d943,0xfb345afa, + 0x16b20499,0x8046b7f6 }, + { 0x38e7d098,0xb533581e,0xf46f0b70,0xd7f61e8d,0x44cb78c4,0x30dea9ea, + 0x9082af55,0xeb17ca7b }, + 0 }, + /* 76 */ + { { 0x76a145b9,0x1751b598,0xc1bc71ec,0xa5cf6b0f,0x392715bb,0xd3e03565, + 0xfab5e131,0x097b00ba }, + { 0x565f69e1,0xaa66c8e9,0xb5be5199,0x77e8f75a,0xda4fd984,0x6033ba11, + 0xafdbcc9e,0xf95c747b }, + 0 }, + /* 77 */ + { { 0xbebae45e,0x558f01d3,0xc4bc6955,0xa8ebe9f0,0xdbc64fc6,0xaeb705b1, + 0x566ed837,0x3512601e }, + { 0xfa1161cd,0x9336f1e1,0x4c65ef87,0x328ab8d5,0x724f21e5,0x4757eee2, + 0x6068ab6b,0x0ef97123 }, + 0 }, + /* 78 */ + { { 0x54ca4226,0x02598cf7,0xf8642c8e,0x5eede138,0x468e1790,0x48963f74, + 0x3b4fbc95,0xfc16d933 }, + { 0xe7c800ca,0xbe96fb31,0x2678adaa,0x13806331,0x6ff3e8b5,0x3d624497, + 0xb95d7a17,0x14ca4af1 }, + 0 }, + /* 79 */ + { { 0xbd2f81d5,0x7a4771ba,0x01f7d196,0x1a5f9d69,0xcad9c907,0xd898bef7, + 0xf59c231d,0x4057b063 }, + { 0x89c05c0a,0xbffd82fe,0x1dc0df85,0xe4911c6f,0xa35a16db,0x3befccae, + 0xf1330b13,0x1c3b5d64 }, + 0 }, + /* 80 */ + { { 0x80ec21fe,0x5fe14bfe,0xc255be82,0xf6ce116a,0x2f4a5d67,0x98bc5a07, + 0xdb7e63af,0xfad27148 }, + { 0x29ab05b3,0x90c0b6ac,0x4e251ae6,0x37a9a83c,0xc2aade7d,0x0a7dc875, + 0x9f0e1a84,0x77387de3 }, + 0 }, + /* 81 */ + { { 0xa56c0dd7,0x1e9ecc49,0x46086c74,0xa5cffcd8,0xf505aece,0x8f7a1408, + 0xbef0c47e,0xb37b85c0 }, + { 0xcc0e6a8f,0x3596b6e4,0x6b388f23,0xfd6d4bbf,0xc39cef4e,0xaba453fa, + 0xf9f628d5,0x9c135ac8 }, + 0 }, + /* 82 */ + { { 0x84e35743,0x32aa3202,0x85a3cdef,0x320d6ab1,0x1df19819,0xb821b176, + 0xc433851f,0x5721361f }, + { 0x71fc9168,0x1f0db36a,0x5e5c403c,0x5f98ba73,0x37bcd8f5,0xf64ca87e, + 0xe6bb11bd,0xdcbac3c9 }, + 0 }, + /* 83 */ + { { 0x4518cbe2,0xf01d9968,0x9c9eb04e,0xd242fc18,0xe47feebf,0x727663c7, + 0x2d626862,0xb8c1c89e }, + { 0xc8e1d569,0x51a58bdd,0xb7d88cd0,0x563809c8,0xf11f31eb,0x26c27fd9, + 0x2f9422d4,0x5d23bbda }, + 0 }, + /* 84 */ + { { 0x95c8f8be,0x0a1c7294,0x3bf362bf,0x2961c480,0xdf63d4ac,0x9e418403, + 0x91ece900,0xc109f9cb }, + { 0x58945705,0xc2d095d0,0xddeb85c0,0xb9083d96,0x7a40449b,0x84692b8d, + 0x2eee1ee1,0x9bc3344f }, + 0 }, + /* 85 */ + { { 0x42913074,0x0d5ae356,0x48a542b1,0x55491b27,0xb310732a,0x469ca665, + 0x5f1a4cc1,0x29591d52 }, + { 0xb84f983f,0xe76f5b6b,0x9f5f84e1,0xbe7eef41,0x80baa189,0x1200d496, + 0x18ef332c,0x6376551f }, + 0 }, + /* 86 */ + { { 0x562976cc,0xbda5f14e,0x0ef12c38,0x22bca3e6,0x6cca9852,0xbbfa3064, + 0x08e2987a,0xbdb79dc8 }, + { 0xcb06a772,0xfd2cb5c9,0xfe536dce,0x38f475aa,0x7c2b5db8,0xc2a3e022, + 0xadd3c14a,0x8ee86001 }, + 0 }, + /* 87 */ + { { 0xa4ade873,0xcbe96981,0xc4fba48c,0x7ee9aa4d,0x5a054ba5,0x2cee2899, + 0x6f77aa4b,0x92e51d7a }, + { 0x7190a34d,0x948bafa8,0xf6bd1ed1,0xd698f75b,0x0caf1144,0xd00ee6e3, + 0x0a56aaaa,0x5182f86f }, + 0 }, + /* 88 */ + { { 0x7a4cc99c,0xfba6212c,0x3e6d9ca1,0xff609b68,0x5ac98c5a,0x5dbb27cb, + 0x4073a6f2,0x91dcab5d }, + { 0x5f575a70,0x01b6cc3d,0x6f8d87fa,0x0cb36139,0x89981736,0x165d4e8c, + 0x97974f2b,0x17a0cedb }, + 0 }, + /* 89 */ + { { 0x076c8d3a,0x38861e2a,0x210f924b,0x701aad39,0x13a835d9,0x94d0eae4, + 0x7f4cdf41,0x2e8ce36c }, + { 0x037a862b,0x91273dab,0x60e4c8fa,0x01ba9bb7,0x33baf2dd,0xf9645388, + 0x34f668f3,0xf4ccc6cb }, + 0 }, + /* 90 */ + { { 0xf1f79687,0x44ef525c,0x92efa815,0x7c595495,0xa5c78d29,0xe1231741, + 0x9a0df3c9,0xac0db488 }, + { 0xdf01747f,0x86bfc711,0xef17df13,0x592b9358,0x5ccb6bb5,0xe5880e4f, + 0x94c974a2,0x95a64a61 }, + 0 }, + /* 91 */ + { { 0xc15a4c93,0x72c1efda,0x82585141,0x40269b73,0x16cb0bad,0x6a8dfb1c, + 0x29210677,0x231e54ba }, + { 0x8ae6d2dc,0xa70df917,0x39112918,0x4d6aa63f,0x5e5b7223,0xf627726b, + 0xd8a731e1,0xab0be032 }, + 0 }, + /* 92 */ + { { 0x8d131f2d,0x097ad0e9,0x3b04f101,0x637f09e3,0xd5e9a748,0x1ac86196, + 0x2cf6a679,0xf1bcc880 }, + { 0xe8daacb4,0x25c69140,0x60f65009,0x3c4e4055,0x477937a6,0x591cc8fc, + 0x5aebb271,0x85169469 }, + 0 }, + /* 93 */ + { { 0xf1dcf593,0xde35c143,0xb018be3b,0x78202b29,0x9bdd9d3d,0xe9cdadc2, + 0xdaad55d8,0x8f67d9d2 }, + { 0x7481ea5f,0x84111656,0xe34c590c,0xe7d2dde9,0x05053fa8,0xffdd43f4, + 0xc0728b5d,0xf84572b9 }, + 0 }, + /* 94 */ + { { 0x97af71c9,0x5e1a7a71,0x7a736565,0xa1449444,0x0e1d5063,0xa1b4ae07, + 0x616b2c19,0xedee2710 }, + { 0x11734121,0xb2f034f5,0x4a25e9f0,0x1cac6e55,0xa40c2ecf,0x8dc148f3, + 0x44ebd7f4,0x9fd27e9b }, + 0 }, + /* 95 */ + { { 0xf6e2cb16,0x3cc7658a,0xfe5919b6,0xe3eb7d2c,0x168d5583,0x5a8c5816, + 0x958ff387,0xa40c2fb6 }, + { 0xfedcc158,0x8c9ec560,0x55f23056,0x7ad804c6,0x9a307e12,0xd9396704, + 0x7dc6decf,0x99bc9bb8 }, + 0 }, + /* 96 */ + { { 0x927dafc6,0x84a9521d,0x5c09cd19,0x52c1fb69,0xf9366dde,0x9d9581a0, + 0xa16d7e64,0x9abe210b }, + { 0x48915220,0x480af84a,0x4dd816c6,0xfa73176a,0x1681ca5a,0xc7d53987, + 0x87f344b0,0x7881c257 }, + 0 }, + /* 97 */ + { { 0xe0bcf3ff,0x93399b51,0x127f74f6,0x0d02cbc5,0xdd01d968,0x8fb465a2, + 0xa30e8940,0x15e6e319 }, + { 0x3e0e05f4,0x646d6e0d,0x43588404,0xfad7bddc,0xc4f850d3,0xbe61c7d1, + 0x191172ce,0x0e55facf }, + 0 }, + /* 98 */ + { { 0xf8787564,0x7e9d9806,0x31e85ce6,0x1a331721,0xb819e8d6,0x6b0158ca, + 0x6fe96577,0xd73d0976 }, + { 0x1eb7206e,0x42483425,0xc618bb42,0xa519290f,0x5e30a520,0x5dcbb859, + 0x8f15a50b,0x9250a374 }, + 0 }, + /* 99 */ + { { 0xbe577410,0xcaff08f8,0x5077a8c6,0xfd408a03,0xec0a63a4,0xf1f63289, + 0xc1cc8c0b,0x77414082 }, + { 0xeb0991cd,0x05a40fa6,0x49fdc296,0xc1ca0866,0xb324fd40,0x3a68a3c7, + 0x12eb20b9,0x8cb04f4d }, + 0 }, + /* 100 */ + { { 0x6906171c,0xb1c2d055,0xb0240c3f,0x9073e9cd,0xd8906841,0xdb8e6b4f, + 0x47123b51,0xe4e429ef }, + { 0x38ec36f4,0x0b8dd53c,0xff4b6a27,0xf9d2dc01,0x879a9a48,0x5d066e07, + 0x3c6e6552,0x37bca2ff }, + 0 }, + /* 101 */ + { { 0xdf562470,0x4cd2e3c7,0xc0964ac9,0x44f272a2,0x80c793be,0x7c6d5df9, + 0x3002b22a,0x59913edc }, + { 0x5750592a,0x7a139a83,0xe783de02,0x99e01d80,0xea05d64f,0xcf8c0375, + 0xb013e226,0x43786e4a }, + 0 }, + /* 102 */ + { { 0x9e56b5a6,0xff32b0ed,0xd9fc68f9,0x0750d9a6,0x597846a7,0xec15e845, + 0xb7e79e7a,0x8638ca98 }, + { 0x0afc24b2,0x2f5ae096,0x4dace8f2,0x05398eaf,0xaecba78f,0x3b765dd0, + 0x7b3aa6f0,0x1ecdd36a }, + 0 }, + /* 103 */ + { { 0x6c5ff2f3,0x5d3acd62,0x2873a978,0xa2d516c0,0xd2110d54,0xad94c9fa, + 0xd459f32d,0xd85d0f85 }, + { 0x10b11da3,0x9f700b8d,0xa78318c4,0xd2c22c30,0x9208decd,0x556988f4, + 0xb4ed3c62,0xa04f19c3 }, + 0 }, + /* 104 */ + { { 0xed7f93bd,0x087924c8,0x392f51f6,0xcb64ac5d,0x821b71af,0x7cae330a, + 0x5c0950b0,0x92b2eeea }, + { 0x85b6e235,0x85ac4c94,0x2936c0f0,0xab2ca4a9,0xe0508891,0x80faa6b3, + 0x5834276c,0x1ee78221 }, + 0 }, + /* 105 */ + { { 0xe63e79f7,0xa60a2e00,0xf399d906,0xf590e7b2,0x6607c09d,0x9021054a, + 0x57a6e150,0xf3f2ced8 }, + { 0xf10d9b55,0x200510f3,0xd8642648,0x9d2fcfac,0xe8bd0e7c,0xe5631aa7, + 0x3da3e210,0x0f56a454 }, + 0 }, + /* 106 */ + { { 0x1043e0df,0x5b21bffa,0x9c007e6d,0x6c74b6cc,0xd4a8517a,0x1a656ec0, + 0x1969e263,0xbd8f1741 }, + { 0xbeb7494a,0x8a9bbb86,0x45f3b838,0x1567d46f,0xa4e5a79a,0xdf7a12a7, + 0x30ccfa09,0x2d1a1c35 }, + 0 }, + /* 107 */ + { { 0x506508da,0x192e3813,0xa1d795a7,0x336180c4,0x7a9944b3,0xcddb5949, + 0xb91fba46,0xa107a65e }, + { 0x0f94d639,0xe6d1d1c5,0x8a58b7d7,0x8b4af375,0xbd37ca1c,0x1a7c5584, + 0xf87a9af2,0x183d760a }, + 0 }, + /* 108 */ + { { 0x0dde59a4,0x29d69711,0x0e8bef87,0xf1ad8d07,0x4f2ebe78,0x229b4963, + 0xc269d754,0x1d44179d }, + { 0x8390d30e,0xb32dc0cf,0x0de8110c,0x0a3b2753,0x2bc0339a,0x31af1dc5, + 0x9606d262,0x771f9cc2 }, + 0 }, + /* 109 */ + { { 0x85040739,0x99993e77,0x8026a939,0x44539db9,0xf5f8fc26,0xcf40f6f2, + 0x0362718e,0x64427a31 }, + { 0x85428aa8,0x4f4f2d87,0xebfb49a8,0x7b7adc3f,0xf23d01ac,0x201b2c6d, + 0x6ae90d6d,0x49d9b749 }, + 0 }, + /* 110 */ + { { 0x435d1099,0xcc78d8bc,0x8e8d1a08,0x2adbcd4e,0x2cb68a41,0x02c2e2a0, + 0x3f605445,0x9037d81b }, + { 0x074c7b61,0x7cdbac27,0x57bfd72e,0xfe2031ab,0x596d5352,0x61ccec96, + 0x7cc0639c,0x08c3de6a }, + 0 }, + /* 111 */ + { { 0xf6d552ab,0x20fdd020,0x05cd81f1,0x56baff98,0x91351291,0x06fb7c3e, + 0x45796b2f,0xc6909442 }, + { 0x41231bd1,0x17b3ae9c,0x5cc58205,0x1eac6e87,0xf9d6a122,0x208837ab, + 0xcafe3ac0,0x3fa3db02 }, + 0 }, + /* 112 */ + { { 0x05058880,0xd75a3e65,0x643943f2,0x7da365ef,0xfab24925,0x4147861c, + 0xfdb808ff,0xc5c4bdb0 }, + { 0xb272b56b,0x73513e34,0x11b9043a,0xc8327e95,0xf8844969,0xfd8ce37d, + 0x46c2b6b5,0x2d56db94 }, + 0 }, + /* 113 */ + { { 0xff46ac6b,0x2461782f,0x07a2e425,0xd19f7926,0x09a48de1,0xfafea3c4, + 0xe503ba42,0x0f56bd9d }, + { 0x345cda49,0x137d4ed1,0x816f299d,0x821158fc,0xaeb43402,0xe7c6a54a, + 0x1173b5f1,0x4003bb9d }, + 0 }, + /* 114 */ + { { 0xa0803387,0x3b8e8189,0x39cbd404,0xece115f5,0xd2877f21,0x4297208d, + 0xa07f2f9e,0x53765522 }, + { 0xa8a4182d,0xa4980a21,0x3219df79,0xa2bbd07a,0x1a19a2d4,0x674d0a2e, + 0x6c5d4549,0x7a056f58 }, + 0 }, + /* 115 */ + { { 0x9d8a2a47,0x646b2558,0xc3df2773,0x5b582948,0xabf0d539,0x51ec000e, + 0x7a1a2675,0x77d482f1 }, + { 0x87853948,0xb8a1bd95,0x6cfbffee,0xa6f817bd,0x80681e47,0xab6ec057, + 0x2b38b0e4,0x4115012b }, + 0 }, + /* 116 */ + { { 0x6de28ced,0x3c73f0f4,0x9b13ec47,0x1d5da760,0x6e5c6392,0x61b8ce9e, + 0xfbea0946,0xcdf04572 }, + { 0x6c53c3b0,0x1cb3c58b,0x447b843c,0x97fe3c10,0x2cb9780e,0xfb2b8ae1, + 0x97383109,0xee703dda }, + 0 }, + /* 117 */ + { { 0xff57e43a,0x34515140,0xb1b811b8,0xd44660d3,0x8f42b986,0x2b3b5dff, + 0xa162ce21,0x2a0ad89d }, + { 0x6bc277ba,0x64e4a694,0xc141c276,0xc788c954,0xcabf6274,0x141aa64c, + 0xac2b4659,0xd62d0b67 }, + 0 }, + /* 118 */ + { { 0x2c054ac4,0x39c5d87b,0xf27df788,0x57005859,0xb18128d6,0xedf7cbf3, + 0x991c2426,0xb39a23f2 }, + { 0xf0b16ae5,0x95284a15,0xa136f51b,0x0c6a05b1,0xf2700783,0x1d63c137, + 0xc0674cc5,0x04ed0092 }, + 0 }, + /* 119 */ + { { 0x9ae90393,0x1f4185d1,0x4a3d64e6,0x3047b429,0x9854fc14,0xae0001a6, + 0x0177c387,0xa0a91fc1 }, + { 0xae2c831e,0xff0a3f01,0x2b727e16,0xbb76ae82,0x5a3075b4,0x8f12c8a1, + 0x9ed20c41,0x084cf988 }, + 0 }, + /* 120 */ + { { 0xfca6becf,0xd98509de,0x7dffb328,0x2fceae80,0x4778e8b9,0x5d8a15c4, + 0x73abf77e,0xd57955b2 }, + { 0x31b5d4f1,0x210da79e,0x3cfa7a1c,0xaa52f04b,0xdc27c20b,0xd4d12089, + 0x02d141f1,0x8e14ea42 }, + 0 }, + /* 121 */ + { { 0xf2897042,0xeed50345,0x43402c4a,0x8d05331f,0xc8bdfb21,0xc8d9c194, + 0x2aa4d158,0x597e1a37 }, + { 0xcf0bd68c,0x0327ec1a,0xab024945,0x6d4be0dc,0xc9fe3e84,0x5b9c8d7a, + 0x199b4dea,0xca3f0236 }, + 0 }, + /* 122 */ + { { 0x6170bd20,0x592a10b5,0x6d3f5de7,0x0ea897f1,0x44b2ade2,0xa3363ff1, + 0x309c07e4,0xbde7fd7e }, + { 0xb8f5432c,0x516bb6d2,0xe043444b,0x210dc1cb,0xf8f95b5a,0x3db01e6f, + 0x0a7dd198,0xb623ad0e }, + 0 }, + /* 123 */ + { { 0x60c7b65b,0xa75bd675,0x23a4a289,0xab8c5590,0xd7b26795,0xf8220fd0, + 0x58ec137b,0xd6aa2e46 }, + { 0x5138bb85,0x10abc00b,0xd833a95c,0x8c31d121,0x1702a32e,0xb24ff00b, + 0x2dcc513a,0x111662e0 }, + 0 }, + /* 124 */ + { { 0xefb42b87,0x78114015,0x1b6c4dff,0xbd9f5d70,0xa7d7c129,0x66ecccd7, + 0x94b750f8,0xdb3ee1cb }, + { 0xf34837cf,0xb26f3db0,0xb9578d4f,0xe7eed18b,0x7c56657d,0x5d2cdf93, + 0x52206a59,0x886a6442 }, + 0 }, + /* 125 */ + { { 0x65b569ea,0x3c234cfb,0xf72119c1,0x20011141,0xa15a619e,0x8badc85d, + 0x018a17bc,0xa70cf4eb }, + { 0x8c4a6a65,0x224f97ae,0x0134378f,0x36e5cf27,0x4f7e0960,0xbe3a609e, + 0xd1747b77,0xaa4772ab }, + 0 }, + /* 126 */ + { { 0x7aa60cc0,0x67676131,0x0368115f,0xc7916361,0xbbc1bb5a,0xded98bb4, + 0x30faf974,0x611a6ddc }, + { 0xc15ee47a,0x30e78cbc,0x4e0d96a5,0x2e896282,0x3dd9ed88,0x36f35adf, + 0x16429c88,0x5cfffaf8 }, + 0 }, + /* 127 */ + { { 0x9b7a99cd,0xc0d54cff,0x843c45a1,0x7bf3b99d,0x62c739e1,0x038a908f, + 0x7dc1994c,0x6e5a6b23 }, + { 0x0ba5db77,0xef8b454e,0xacf60d63,0xb7b8807f,0x76608378,0xe591c0c6, + 0x242dabcc,0x481a238d }, + 0 }, + /* 128 */ + { { 0x35d0b34a,0xe3417bc0,0x8327c0a7,0x440b386b,0xac0362d1,0x8fb7262d, + 0xe0cdf943,0x2c41114c }, + { 0xad95a0b1,0x2ba5cef1,0x67d54362,0xc09b37a8,0x01e486c9,0x26d6cdd2, + 0x42ff9297,0x20477abf }, + 0 }, + /* 129 */ + { { 0x18d65dbf,0x2f75173c,0x339edad8,0x77bf940e,0xdcf1001c,0x7022d26b, + 0xc77396b6,0xac66409a }, + { 0xc6261cc3,0x8b0bb36f,0x190e7e90,0x213f7bc9,0xa45e6c10,0x6541ceba, + 0xcc122f85,0xce8e6975 }, + 0 }, + /* 130 */ + { { 0xbc0a67d2,0x0f121b41,0x444d248a,0x62d4760a,0x659b4737,0x0e044f1d, + 0x250bb4a8,0x08fde365 }, + { 0x848bf287,0xaceec3da,0xd3369d6e,0xc2a62182,0x92449482,0x3582dfdc, + 0x565d6cd7,0x2f7e2fd2 }, + 0 }, + /* 131 */ + { { 0xc3770fa7,0xae4b92db,0x379043f9,0x095e8d5c,0x17761171,0x54f34e9d, + 0x907702ae,0xc65be92e }, + { 0xf6fd0a40,0x2758a303,0xbcce784b,0xe7d822e3,0x4f9767bf,0x7ae4f585, + 0xd1193b3a,0x4bff8e47 }, + 0 }, + /* 132 */ + { { 0x00ff1480,0xcd41d21f,0x0754db16,0x2ab8fb7d,0xbbe0f3ea,0xac81d2ef, + 0x5772967d,0x3e4e4ae6 }, + { 0x3c5303e6,0x7e18f36d,0x92262397,0x3bd9994b,0x1324c3c0,0x9ed70e26, + 0x58ec6028,0x5388aefd }, + 0 }, + /* 133 */ + { { 0x5e5d7713,0xad1317eb,0x75de49da,0x09b985ee,0xc74fb261,0x32f5bc4f, + 0x4f75be0e,0x5cf908d1 }, + { 0x8e657b12,0x76043510,0xb96ed9e6,0xbfd421a5,0x8970ccc2,0x0e29f51f, + 0x60f00ce2,0xa698ba40 }, + 0 }, + /* 134 */ + { { 0xef748fec,0x73db1686,0x7e9d2cf9,0xe6e755a2,0xce265eff,0x630b6544, + 0x7aebad8d,0xb142ef8a }, + { 0x17d5770a,0xad31af9f,0x2cb3412f,0x66af3b67,0xdf3359de,0x6bd60d1b, + 0x58515075,0xd1896a96 }, + 0 }, + /* 135 */ + { { 0x33c41c08,0xec5957ab,0x5468e2e1,0x87de94ac,0xac472f6c,0x18816b73, + 0x7981da39,0x267b0e0b }, + { 0x8e62b988,0x6e554e5d,0x116d21e7,0xd8ddc755,0x3d2a6f99,0x4610faf0, + 0xa1119393,0xb54e287a }, + 0 }, + /* 136 */ + { { 0x178a876b,0x0a0122b5,0x085104b4,0x51ff96ff,0x14f29f76,0x050b31ab, + 0x5f87d4e6,0x84abb28b }, + { 0x8270790a,0xd5ed439f,0x85e3f46b,0x2d6cb59d,0x6c1e2212,0x75f55c1b, + 0x17655640,0xe5436f67 }, + 0 }, + /* 137 */ + { { 0x2286e8d5,0x53f9025e,0x864453be,0x353c95b4,0xe408e3a0,0xd832f5bd, + 0x5b9ce99e,0x0404f68b }, + { 0xa781e8e5,0xcad33bde,0x163c2f5b,0x3cdf5018,0x0119caa3,0x57576960, + 0x0ac1c701,0x3a4263df }, + 0 }, + /* 138 */ + { { 0x9aeb596d,0xc2965ecc,0x023c92b4,0x01ea03e7,0x2e013961,0x4704b4b6, + 0x905ea367,0x0ca8fd3f }, + { 0x551b2b61,0x92523a42,0x390fcd06,0x1eb7a89c,0x0392a63e,0xe7f1d2be, + 0x4ddb0c33,0x96dca264 }, + 0 }, + /* 139 */ + { { 0x387510af,0x203bb43a,0xa9a36a01,0x846feaa8,0x2f950378,0xd23a5770, + 0x3aad59dc,0x4363e212 }, + { 0x40246a47,0xca43a1c7,0xe55dd24d,0xb362b8d2,0x5d8faf96,0xf9b08604, + 0xd8bb98c4,0x840e115c }, + 0 }, + /* 140 */ + { { 0x1023e8a7,0xf12205e2,0xd8dc7a0b,0xc808a8cd,0x163a5ddf,0xe292a272, + 0x30ded6d4,0x5e0d6abd }, + { 0x7cfc0f64,0x07a721c2,0x0e55ed88,0x42eec01d,0x1d1f9db2,0x26a7bef9, + 0x2945a25a,0x7dea48f4 }, + 0 }, + /* 141 */ + { { 0xe5060a81,0xabdf6f1c,0xf8f95615,0xe79f9c72,0x06ac268b,0xcfd36c54, + 0xebfd16d1,0xabc2a2be }, + { 0xd3e2eac7,0x8ac66f91,0xd2dd0466,0x6f10ba63,0x0282d31b,0x6790e377, + 0x6c7eefc1,0x4ea35394 }, + 0 }, + /* 142 */ + { { 0x5266309d,0xed8a2f8d,0x81945a3e,0x0a51c6c0,0x578c5dc1,0xcecaf45a, + 0x1c94ffc3,0x3a76e689 }, + { 0x7d7b0d0f,0x9aace8a4,0x8f584a5f,0x963ace96,0x4e697fbe,0x51a30c72, + 0x465e6464,0x8212a10a }, + 0 }, + /* 143 */ + { { 0xcfab8caa,0xef7c61c3,0x0e142390,0x18eb8e84,0x7e9733ca,0xcd1dff67, + 0x599cb164,0xaa7cab71 }, + { 0xbc837bd1,0x02fc9273,0xc36af5d7,0xc06407d0,0xf423da49,0x17621292, + 0xfe0617c3,0x40e38073 }, + 0 }, + /* 144 */ + { { 0xa7bf9b7c,0xf4f80824,0x3fbe30d0,0x365d2320,0x97cf9ce3,0xbfbe5320, + 0xb3055526,0xe3604700 }, + { 0x6cc6c2c7,0x4dcb9911,0xba4cbee6,0x72683708,0x637ad9ec,0xdcded434, + 0xa3dee15f,0x6542d677 }, + 0 }, + /* 145 */ + { { 0x7b6c377a,0x3f32b6d0,0x903448be,0x6cb03847,0x20da8af7,0xd6fdd3a8, + 0x09bb6f21,0xa6534aee }, + { 0x1035facf,0x30a1780d,0x9dcb47e6,0x35e55a33,0xc447f393,0x6ea50fe1, + 0xdc9aef22,0xf3cb672f }, + 0 }, + /* 146 */ + { { 0x3b55fd83,0xeb3719fe,0x875ddd10,0xe0d7a46c,0x05cea784,0x33ac9fa9, + 0xaae870e7,0x7cafaa2e }, + { 0x1d53b338,0x9b814d04,0xef87e6c6,0xe0acc0a0,0x11672b0f,0xfb93d108, + 0xb9bd522e,0x0aab13c1 }, + 0 }, + /* 147 */ + { { 0xd2681297,0xddcce278,0xb509546a,0xcb350eb1,0x7661aaf2,0x2dc43173, + 0x847012e9,0x4b91a602 }, + { 0x72f8ddcf,0xdcff1095,0x9a911af4,0x08ebf61e,0xc372430e,0x48f4360a, + 0x72321cab,0x49534c53 }, + 0 }, + /* 148 */ + { { 0xf07b7e9d,0x83df7d71,0x13cd516f,0xa478efa3,0x6c047ee3,0x78ef264b, + 0xd65ac5ee,0xcaf46c4f }, + { 0x92aa8266,0xa04d0c77,0x913684bb,0xedf45466,0xae4b16b0,0x56e65168, + 0x04c6770f,0x14ce9e57 }, + 0 }, + /* 149 */ + { { 0x965e8f91,0x99445e3e,0xcb0f2492,0xd3aca1ba,0x90c8a0a0,0xd31cc70f, + 0x3e4c9a71,0x1bb708a5 }, + { 0x558bdd7a,0xd5ca9e69,0x018a26b1,0x734a0508,0x4c9cf1ec,0xb093aa71, + 0xda300102,0xf9d126f2 }, + 0 }, + /* 150 */ + { { 0xaff9563e,0x749bca7a,0xb49914a0,0xdd077afe,0xbf5f1671,0xe27a0311, + 0x729ecc69,0x807afcb9 }, + { 0xc9b08b77,0x7f8a9337,0x443c7e38,0x86c3a785,0x476fd8ba,0x85fafa59, + 0x6568cd8c,0x751adcd1 }, + 0 }, + /* 151 */ + { { 0x10715c0d,0x8aea38b4,0x8f7697f7,0xd113ea71,0x93fbf06d,0x665eab14, + 0x2537743f,0x29ec4468 }, + { 0xb50bebbc,0x3d94719c,0xe4505422,0x399ee5bf,0x8d2dedb1,0x90cd5b3a, + 0x92a4077d,0xff9370e3 }, + 0 }, + /* 152 */ + { { 0xc6b75b65,0x59a2d69b,0x266651c5,0x4188f8d5,0x3de9d7d2,0x28a9f33e, + 0xa2a9d01a,0x9776478b }, + { 0x929af2c7,0x8852622d,0x4e690923,0x334f5d6d,0xa89a51e9,0xce6cc7e5, + 0xac2f82fa,0x74a6313f }, + 0 }, + /* 153 */ + { { 0xb75f079c,0xb2f4dfdd,0x18e36fbb,0x85b07c95,0xe7cd36dd,0x1b6cfcf0, + 0x0ff4863d,0xab75be15 }, + { 0x173fc9b7,0x81b367c0,0xd2594fd0,0xb90a7420,0xc4091236,0x15fdbf03, + 0x0b4459f6,0x4ebeac2e }, + 0 }, + /* 154 */ + { { 0x5c9f2c53,0xeb6c5fe7,0x8eae9411,0xd2522011,0xf95ac5d8,0xc8887633, + 0x2c1baffc,0xdf99887b }, + { 0x850aaecb,0xbb78eed2,0x01d6a272,0x9d49181b,0xb1cdbcac,0x978dd511, + 0x779f4058,0x27b040a7 }, + 0 }, + /* 155 */ + { { 0xf73b2eb2,0x90405db7,0x8e1b2118,0xe0df8508,0x5962327e,0x501b7152, + 0xe4cfa3f5,0xb393dd37 }, + { 0x3fd75165,0xa1230e7b,0xbcd33554,0xd66344c2,0x0f7b5022,0x6c36f1be, + 0xd0463419,0x09588c12 }, + 0 }, + /* 156 */ + { { 0x02601c3b,0xe086093f,0xcf5c335f,0xfb0252f8,0x894aff28,0x955cf280, + 0xdb9f648b,0x81c879a9 }, + { 0xc6f56c51,0x040e687c,0x3f17618c,0xfed47169,0x9059353b,0x44f88a41, + 0x5fc11bc4,0xfa0d48f5 }, + 0 }, + /* 157 */ + { { 0xe1608e4d,0xbc6e1c9d,0x3582822c,0x010dda11,0x157ec2d7,0xf6b7ddc1, + 0xb6a367d6,0x8ea0e156 }, + { 0x2383b3b4,0xa354e02f,0x3f01f53c,0x69966b94,0x2de03ca5,0x4ff6632b, + 0xfa00b5ac,0x3f5ab924 }, + 0 }, + /* 158 */ + { { 0x59739efb,0x337bb0d9,0xe7ebec0d,0xc751b0f4,0x411a67d1,0x2da52dd6, + 0x2b74256e,0x8bc76887 }, + { 0x82d3d253,0xa5be3b72,0xf58d779f,0xa9f679a1,0xe16767bb,0xa1cac168, + 0x60fcf34f,0xb386f190 }, + 0 }, + /* 159 */ + { { 0x2fedcfc2,0x31f3c135,0x62f8af0d,0x5396bf62,0xe57288c2,0x9a02b4ea, + 0x1b069c4d,0x4cb460f7 }, + { 0x5b8095ea,0xae67b4d3,0x6fc07603,0x92bbf859,0xb614a165,0xe1475f66, + 0x95ef5223,0x52c0d508 }, + 0 }, + /* 160 */ + { { 0x15339848,0x231c210e,0x70778c8d,0xe87a28e8,0x6956e170,0x9d1de661, + 0x2bb09c0b,0x4ac3c938 }, + { 0x6998987d,0x19be0551,0xae09f4d6,0x8b2376c4,0x1a3f933d,0x1de0b765, + 0xe39705f4,0x380d94c7 }, + 0 }, + /* 161 */ + { { 0x81542e75,0x01a355aa,0xee01b9b7,0x96c724a1,0x624d7087,0x6b3a2977, + 0xde2637af,0x2ce3e171 }, + { 0xf5d5bc1a,0xcfefeb49,0x2777e2b5,0xa655607e,0x9513756c,0x4feaac2f, + 0x0b624e4d,0x2e6cd852 }, + 0 }, + /* 162 */ + { { 0x8c31c31d,0x3685954b,0x5bf21a0c,0x68533d00,0x75c79ec9,0x0bd7626e, + 0x42c69d54,0xca177547 }, + { 0xf6d2dbb2,0xcc6edaff,0x174a9d18,0xfd0d8cbd,0xaa4578e8,0x875e8793, + 0x9cab2ce6,0xa976a713 }, + 0 }, + /* 163 */ + { { 0x93fb353d,0x0a651f1b,0x57fcfa72,0xd75cab8b,0x31b15281,0xaa88cfa7, + 0x0a1f4999,0x8720a717 }, + { 0x693e1b90,0x8c3e8d37,0x16f6dfc3,0xd345dc0b,0xb52a8742,0x8ea8d00a, + 0xc769893c,0x9719ef29 }, + 0 }, + /* 164 */ + { { 0x58e35909,0x820eed8d,0x33ddc116,0x9366d8dc,0x6e205026,0xd7f999d0, + 0xe15704c1,0xa5072976 }, + { 0xc4e70b2e,0x002a37ea,0x6890aa8a,0x84dcf657,0x645b2a5c,0xcd71bf18, + 0xf7b77725,0x99389c9d }, + 0 }, + /* 165 */ + { { 0x7ada7a4b,0x238c08f2,0xfd389366,0x3abe9d03,0x766f512c,0x6b672e89, + 0x202c82e4,0xa88806aa }, + { 0xd380184e,0x6602044a,0x126a8b85,0xa8cb78c4,0xad844f17,0x79d670c0, + 0x4738dcfe,0x0043bffb }, + 0 }, + /* 166 */ + { { 0x36d5192e,0x8d59b5dc,0x4590b2af,0xacf885d3,0x11601781,0x83566d0a, + 0xba6c4866,0x52f3ef01 }, + { 0x0edcb64d,0x3986732a,0x8068379f,0x0a482c23,0x7040f309,0x16cbe5fa, + 0x9ef27e75,0x3296bd89 }, + 0 }, + /* 167 */ + { { 0x454d81d7,0x476aba89,0x51eb9b3c,0x9eade7ef,0x81c57986,0x619a21cd, + 0xaee571e9,0x3b90febf }, + { 0x5496f7cb,0x9393023e,0x7fb51bc4,0x55be41d8,0x99beb5ce,0x03f1dd48, + 0x9f810b18,0x6e88069d }, + 0 }, + /* 168 */ + { { 0xb43ea1db,0xce37ab11,0x5259d292,0x0a7ff1a9,0x8f84f186,0x851b0221, + 0xdefaad13,0xa7222bea }, + { 0x2b0a9144,0xa2ac78ec,0xf2fa59c5,0x5a024051,0x6147ce38,0x91d1eca5, + 0xbc2ac690,0xbe94d523 }, + 0 }, + /* 169 */ + { { 0x0b226ce7,0x72f4945e,0x967e8b70,0xb8afd747,0x85a6c63e,0xedea46f1, + 0x9be8c766,0x7782defe }, + { 0x3db38626,0x760d2aa4,0x76f67ad1,0x460ae787,0x54499cdb,0x341b86fc, + 0xa2892e4b,0x03838567 }, + 0 }, + /* 170 */ + { { 0x79ec1a0f,0x2d8daefd,0xceb39c97,0x3bbcd6fd,0x58f61a95,0xf5575ffc, + 0xadf7b420,0xdbd986c4 }, + { 0x15f39eb7,0x81aa8814,0xb98d976c,0x6ee2fcf5,0xcf2f717d,0x5465475d, + 0x6860bbd0,0x8e24d3c4 }, + 0 }, + /* 171 */ + { { 0x9a587390,0x749d8e54,0x0cbec588,0x12bb194f,0xb25983c6,0x46e07da4, + 0x407bafc8,0x541a99c4 }, + { 0x624c8842,0xdb241692,0xd86c05ff,0x6044c12a,0x4f7fcf62,0xc59d14b4, + 0xf57d35d1,0xc0092c49 }, + 0 }, + /* 172 */ + { { 0xdf2e61ef,0xd3cc75c3,0x2e1b35ca,0x7e8841c8,0x909f29f4,0xc62d30d1, + 0x7286944d,0x75e40634 }, + { 0xbbc237d0,0xe7d41fc5,0xec4f01c9,0xc9537bf0,0x282bd534,0x91c51a16, + 0xc7848586,0x5b7cb658 }, + 0 }, + /* 173 */ + { { 0x8a28ead1,0x964a7084,0xfd3b47f6,0x802dc508,0x767e5b39,0x9ae4bfd1, + 0x8df097a1,0x7ae13eba }, + { 0xeadd384e,0xfd216ef8,0xb6b2ff06,0x0361a2d9,0x4bcdb5f3,0x204b9878, + 0xe2a8e3fd,0x787d8074 }, + 0 }, + /* 174 */ + { { 0x757fbb1c,0xc5e25d6b,0xca201deb,0xe47bddb2,0x6d2233ff,0x4a55e9a3, + 0x9ef28484,0x5c222819 }, + { 0x88315250,0x773d4a85,0x827097c1,0x21b21a2b,0xdef5d33f,0xab7c4ea1, + 0xbaf0f2b0,0xe45d37ab }, + 0 }, + /* 175 */ + { { 0x28511c8a,0xd2df1e34,0xbdca6cd3,0xebb229c8,0x627c39a7,0x578a71a7, + 0x84dfb9d3,0xed7bc122 }, + { 0x93dea561,0xcf22a6df,0xd48f0ed1,0x5443f18d,0x5bad23e8,0xd8b86140, + 0x45ca6d27,0xaac97cc9 }, + 0 }, + /* 176 */ + { { 0xa16bd00a,0xeb54ea74,0xf5c0bcc1,0xd839e9ad,0x1f9bfc06,0x092bb7f1, + 0x1163dc4e,0x318f97b3 }, + { 0xc30d7138,0xecc0c5be,0xabc30220,0x44e8df23,0xb0223606,0x2bb7972f, + 0x9a84ff4d,0xfa41faa1 }, + 0 }, + /* 177 */ + { { 0xa6642269,0x4402d974,0x9bb783bd,0xc81814ce,0x7941e60b,0x398d38e4, + 0x1d26e9e2,0x38bb6b2c }, + { 0x6a577f87,0xc64e4a25,0xdc11fe1c,0x8b52d253,0x62280728,0xff336abf, + 0xce7601a5,0x94dd0905 }, + 0 }, + /* 178 */ + { { 0xde93f92a,0x156cf7dc,0x89b5f315,0xa01333cb,0xc995e750,0x02404df9, + 0xd25c2ae9,0x92077867 }, + { 0x0bf39d44,0xe2471e01,0x96bb53d7,0x5f2c9020,0x5c9c3d8f,0x4c44b7b3, + 0xd29beb51,0x81e8428b }, + 0 }, + /* 179 */ + { { 0xc477199f,0x6dd9c2ba,0x6b5ecdd9,0x8cb8eeee,0xee40fd0e,0x8af7db3f, + 0xdbbfa4b1,0x1b94ab62 }, + { 0xce47f143,0x44f0d8b3,0x63f46163,0x51e623fc,0xcc599383,0xf18f270f, + 0x055590ee,0x06a38e28 }, + 0 }, + /* 180 */ + { { 0xb3355b49,0x2e5b0139,0xb4ebf99b,0x20e26560,0xd269f3dc,0xc08ffa6b, + 0x83d9d4f8,0xa7b36c20 }, + { 0x1b3e8830,0x64d15c3a,0xa89f9c0b,0xd5fceae1,0xe2d16930,0xcfeee4a2, + 0xa2822a20,0xbe54c6b4 }, + 0 }, + /* 181 */ + { { 0x8d91167c,0xd6cdb3df,0xe7a6625e,0x517c3f79,0x346ac7f4,0x7105648f, + 0xeae022bb,0xbf30a5ab }, + { 0x93828a68,0x8e7785be,0x7f3ef036,0x5161c332,0x592146b2,0xe11b5feb, + 0x2732d13a,0xd1c820de }, + 0 }, + /* 182 */ + { { 0x9038b363,0x043e1347,0x6b05e519,0x58c11f54,0x6026cad1,0x4fe57abe, + 0x68a18da3,0xb7d17bed }, + { 0xe29c2559,0x44ca5891,0x5bfffd84,0x4f7a0376,0x74e46948,0x498de4af, + 0x6412cc64,0x3997fd5e }, + 0 }, + /* 183 */ + { { 0x8bd61507,0xf2074682,0x34a64d2a,0x29e132d5,0x8a8a15e3,0xffeddfb0, + 0x3c6c13e8,0x0eeb8929 }, + { 0xa7e259f8,0xe9b69a3e,0xd13e7e67,0xce1db7e6,0xad1fa685,0x277318f6, + 0xc922b6ef,0x228916f8 }, + 0 }, + /* 184 */ + { { 0x0a12ab5b,0x959ae25b,0x957bc136,0xcc11171f,0xd16e2b0c,0x8058429e, + 0x6e93097e,0xec05ad1d }, + { 0xac3f3708,0x157ba5be,0x30b59d77,0x31baf935,0x118234e5,0x47b55237, + 0x7ff11b37,0x7d314156 }, + 0 }, + /* 185 */ + { { 0xf6dfefab,0x7bd9c05c,0xdcb37707,0xbe2f2268,0x3a38bb95,0xe53ead97, + 0x9bc1d7a3,0xe9ce66fc }, + { 0x6f6a02a1,0x75aa1576,0x60e600ed,0x38c087df,0x68cdc1b9,0xf8947f34, + 0x72280651,0xd9650b01 }, + 0 }, + /* 186 */ + { { 0x5a057e60,0x504b4c4a,0x8def25e4,0xcbccc3be,0x17c1ccbd,0xa6353208, + 0x804eb7a2,0x14d6699a }, + { 0xdb1f411a,0x2c8a8415,0xf80d769c,0x09fbaf0b,0x1c2f77ad,0xb4deef90, + 0x0d43598a,0x6f4c6841 }, + 0 }, + /* 187 */ + { { 0x96c24a96,0x8726df4e,0xfcbd99a3,0x534dbc85,0x8b2ae30a,0x3c466ef2, + 0x61189abb,0x4c4350fd }, + { 0xf855b8da,0x2967f716,0x463c38a1,0x41a42394,0xeae93343,0xc37e1413, + 0x5a3118b5,0xa726d242 }, + 0 }, + /* 188 */ + { { 0x948c1086,0xdae6b3ee,0xcbd3a2e1,0xf1de503d,0x03d022f3,0x3f35ed3f, + 0xcc6cf392,0x13639e82 }, + { 0xcdafaa86,0x9ac938fb,0x2654a258,0xf45bc5fb,0x45051329,0x1963b26e, + 0xc1a335a3,0xca9365e1 }, + 0 }, + /* 189 */ + { { 0x4c3b2d20,0x3615ac75,0x904e241b,0x742a5417,0xcc9d071d,0xb08521c4, + 0x970b72a5,0x9ce29c34 }, + { 0x6d3e0ad6,0x8cc81f73,0xf2f8434c,0x8060da9e,0x6ce862d9,0x35ed1d1a, + 0xab42af98,0x48c4abd7 }, + 0 }, + /* 190 */ + { { 0x40c7485a,0xd221b0cc,0xe5274dbf,0xead455bb,0x9263d2e8,0x493c7698, + 0xf67b33cb,0x78017c32 }, + { 0x930cb5ee,0xb9d35769,0x0c408ed2,0xc0d14e94,0x272f1a4d,0xf8b7bf55, + 0xde5c1c04,0x53cd0454 }, + 0 }, + /* 191 */ + { { 0x5d28ccac,0xbcd585fa,0x005b746e,0x5f823e56,0xcd0123aa,0x7c79f0a1, + 0xd3d7fa8f,0xeea465c1 }, + { 0x0551803b,0x7810659f,0x7ce6af70,0x6c0b599f,0x29288e70,0x4195a770, + 0x7ae69193,0x1b6e42a4 }, + 0 }, + /* 192 */ + { { 0xf67d04c3,0x2e80937c,0x89eeb811,0x1e312be2,0x92594d60,0x56b5d887, + 0x187fbd3d,0x0224da14 }, + { 0x0c5fe36f,0x87abb863,0x4ef51f5f,0x580f3c60,0xb3b429ec,0x964fb1bf, + 0x42bfff33,0x60838ef0 }, + 0 }, + /* 193 */ + { { 0x7e0bbe99,0x432cb2f2,0x04aa39ee,0x7bda44f3,0x9fa93903,0x5f497c7a, + 0x2d331643,0x636eb202 }, + { 0x93ae00aa,0xfcfd0e61,0x31ae6d2f,0x875a00fe,0x9f93901c,0xf43658a2, + 0x39218bac,0x8844eeb6 }, + 0 }, + /* 194 */ + { { 0x6b3bae58,0x114171d2,0x17e39f3e,0x7db3df71,0x81a8eada,0xcd37bc7f, + 0x51fb789e,0x27ba83dc }, + { 0xfbf54de5,0xa7df439f,0xb5fe1a71,0x7277030b,0xdb297a48,0x42ee8e35, + 0x87f3a4ab,0xadb62d34 }, + 0 }, + /* 195 */ + { { 0xa175df2a,0x9b1168a2,0x618c32e9,0x082aa04f,0x146b0916,0xc9e4f2e7, + 0x75e7c8b2,0xb990fd76 }, + { 0x4df37313,0x0829d96b,0xd0b40789,0x1c205579,0x78087711,0x66c9ae4a, + 0x4d10d18d,0x81707ef9 }, + 0 }, + /* 196 */ + { { 0x03d6ff96,0x97d7cab2,0x0d843360,0x5b851bfc,0xd042db4b,0x268823c4, + 0xd5a8aa5c,0x3792daea }, + { 0x941afa0b,0x52818865,0x42d83671,0xf3e9e741,0x5be4e0a7,0x17c82527, + 0x94b001ba,0x5abd635e }, + 0 }, + /* 197 */ + { { 0x0ac4927c,0x727fa84e,0xa7c8cf23,0xe3886035,0x4adca0df,0xa4bcd5ea, + 0x846ab610,0x5995bf21 }, + { 0x829dfa33,0xe90f860b,0x958fc18b,0xcaafe2ae,0x78630366,0x9b3baf44, + 0xd483411e,0x44c32ca2 }, + 0 }, + /* 198 */ + { { 0xe40ed80c,0xa74a97f1,0x31d2ca82,0x5f938cb1,0x7c2d6ad9,0x53f2124b, + 0x8082a54c,0x1f2162fb }, + { 0x720b173e,0x7e467cc5,0x085f12f9,0x40e8a666,0x4c9d65dc,0x8cebc20e, + 0xc3e907c9,0x8f1d402b }, + 0 }, + /* 199 */ + { { 0xfbc4058a,0x4f592f9c,0x292f5670,0xb15e14b6,0xbc1d8c57,0xc55cfe37, + 0x926edbf9,0xb1980f43 }, + { 0x32c76b09,0x98c33e09,0x33b07f78,0x1df5279d,0x863bb461,0x6f08ead4, + 0x37448e45,0x2828ad9b }, + 0 }, + /* 200 */ + { { 0xc4cf4ac5,0x696722c4,0xdde64afb,0xf5ac1a3f,0xe0890832,0x0551baa2, + 0x5a14b390,0x4973f127 }, + { 0x322eac5d,0xe59d8335,0x0bd9b568,0x5e07eef5,0xa2588393,0xab36720f, + 0xdb168ac7,0x6dac8ed0 }, + 0 }, + /* 201 */ + { { 0xeda835ef,0xf7b545ae,0x1d10ed51,0x4aa113d2,0x13741b09,0x035a65e0, + 0x20b9de4c,0x4b23ef59 }, + { 0x3c4c7341,0xe82bb680,0x3f58bc37,0xd457706d,0xa51e3ee8,0x73527863, + 0xddf49a4e,0x4dd71534 }, + 0 }, + /* 202 */ + { { 0x95476cd9,0xbf944672,0xe31a725b,0x648d072f,0xfc4b67e0,0x1441c8b8, + 0x2f4a4dbb,0xfd317000 }, + { 0x8995d0e1,0x1cb43ff4,0x0ef729aa,0x76e695d1,0x41798982,0xe0d5f976, + 0x9569f365,0x14fac58c }, + 0 }, + /* 203 */ + { { 0xf312ae18,0xad9a0065,0xfcc93fc9,0x51958dc0,0x8a7d2846,0xd9a14240, + 0x36abda50,0xed7c7651 }, + { 0x25d4abbc,0x46270f1a,0xf1a113ea,0x9b5dd8f3,0x5b51952f,0xc609b075, + 0x4d2e9f53,0xfefcb7f7 }, + 0 }, + /* 204 */ + { { 0xba119185,0xbd09497a,0xaac45ba4,0xd54e8c30,0xaa521179,0x492479de, + 0x87e0d80b,0x1801a57e }, + { 0xfcafffb0,0x073d3f8d,0xae255240,0x6cf33c0b,0x5b5fdfbc,0x781d763b, + 0x1ead1064,0x9f8fc11e }, + 0 }, + /* 205 */ + { { 0x5e69544c,0x1583a171,0xf04b7813,0x0eaf8567,0x278a4c32,0x1e22a8fd, + 0x3d3a69a9,0xa9d3809d }, + { 0x59a2da3b,0x936c2c2c,0x1895c847,0x38ccbcf6,0x63d50869,0x5e65244e, + 0xe1178ef7,0x3006b9ae }, + 0 }, + /* 206 */ + { { 0xc9eead28,0x0bb1f2b0,0x89f4dfbc,0x7eef635d,0xb2ce8939,0x074757fd, + 0x45f8f761,0x0ab85fd7 }, + { 0x3e5b4549,0xecda7c93,0x97922f21,0x4be2bb5c,0xb43b8040,0x261a1274, + 0x11e942c2,0xb122d675 }, + 0 }, + /* 207 */ + { { 0x66a5ae7a,0x3be607be,0x76adcbe3,0x01e703fa,0x4eb6e5c5,0xaf904301, + 0x097dbaec,0x9f599dc1 }, + { 0x0ff250ed,0x6d75b718,0x349a20dc,0x8eb91574,0x10b227a3,0x425605a4, + 0x8a294b78,0x7d5528e0 }, + 0 }, + /* 208 */ + { { 0x20c26def,0xf0f58f66,0x582b2d1e,0x025585ea,0x01ce3881,0xfbe7d79b, + 0x303f1730,0x28ccea01 }, + { 0x79644ba5,0xd1dabcd1,0x06fff0b8,0x1fc643e8,0x66b3e17b,0xa60a76fc, + 0xa1d013bf,0xc18baf48 }, + 0 }, + /* 209 */ + { { 0x5dc4216d,0x34e638c8,0x206142ac,0x00c01067,0x95f5064a,0xd453a171, + 0xb7a9596b,0x9def809d }, + { 0x67ab8d2c,0x41e8642e,0x6237a2b6,0xb4240433,0x64c4218b,0x7d506a6d, + 0x68808ce5,0x0357f8b0 }, + 0 }, + /* 210 */ + { { 0x4cd2cc88,0x8e9dbe64,0xf0b8f39d,0xcc61c28d,0xcd30a0c8,0x4a309874, + 0x1b489887,0xe4a01add }, + { 0xf57cd8f9,0x2ed1eeac,0xbd594c48,0x1b767d3e,0x7bd2f787,0xa7295c71, + 0xce10cc30,0x466d7d79 }, + 0 }, + /* 211 */ + { { 0x9dada2c7,0x47d31892,0x8f9aa27d,0x4fa0a6c3,0x820a59e1,0x90e4fd28, + 0x451ead1a,0xc672a522 }, + { 0x5d86b655,0x30607cc8,0xf9ad4af1,0xf0235d3b,0x571172a6,0x99a08680, + 0xf2a67513,0x5e3d64fa }, + 0 }, + /* 212 */ + { { 0x9b3b4416,0xaa6410c7,0xeab26d99,0xcd8fcf85,0xdb656a74,0x5ebff74a, + 0xeb8e42fc,0x6c8a7a95 }, + { 0xb02a63bd,0x10c60ba7,0x8b8f0047,0x6b2f2303,0x312d90b0,0x8c6c3738, + 0xad82ca91,0x348ae422 }, + 0 }, + /* 213 */ + { { 0x5ccda2fb,0x7f474663,0x8e0726d2,0x22accaa1,0x492b1f20,0x85adf782, + 0xd9ef2d2e,0xc1074de0 }, + { 0xae9a65b3,0xfcf3ce44,0x05d7151b,0xfd71e4ac,0xce6a9788,0xd4711f50, + 0xc9e54ffc,0xfbadfbdb }, + 0 }, + /* 214 */ + { { 0x20a99363,0x1713f1cd,0x6cf22775,0xb915658f,0x24d359b2,0x968175cd, + 0x83716fcd,0xb7f976b4 }, + { 0x5d6dbf74,0x5758e24d,0x71c3af36,0x8d23bafd,0x0243dfe3,0x48f47760, + 0xcafcc805,0xf4d41b2e }, + 0 }, + /* 215 */ + { { 0xfdabd48d,0x51f1cf28,0x32c078a4,0xce81be36,0x117146e9,0x6ace2974, + 0xe0160f10,0x180824ea }, + { 0x66e58358,0x0387698b,0xce6ca358,0x63568752,0x5e41e6c5,0x82380e34, + 0x83cf6d25,0x67e5f639 }, + 0 }, + /* 216 */ + { { 0xcf4899ef,0xf89ccb8d,0x9ebb44c0,0x949015f0,0xb2598ec9,0x546f9276, + 0x04c11fc6,0x9fef789a }, + { 0x53d2a071,0x6d367ecf,0xa4519b09,0xb10e1a7f,0x611e2eef,0xca6b3fb0, + 0xa99c4e20,0xbc80c181 }, + 0 }, + /* 217 */ + { { 0xe5eb82e6,0x972536f8,0xf56cb920,0x1a484fc7,0x50b5da5e,0xc78e2171, + 0x9f8cdf10,0x49270e62 }, + { 0xea6b50ad,0x1a39b7bb,0xa2388ffc,0x9a0284c1,0x8107197b,0x5403eb17, + 0x61372f7f,0xd2ee52f9 }, + 0 }, + /* 218 */ + { { 0x88e0362a,0xd37cd285,0x8fa5d94d,0x442fa8a7,0xa434a526,0xaff836e5, + 0xe5abb733,0xdfb478be }, + { 0x673eede6,0xa91f1ce7,0x2b5b2f04,0xa5390ad4,0x5530da2f,0x5e66f7bf, + 0x08df473a,0xd9a140b4 }, + 0 }, + /* 219 */ + { { 0x6e8ea498,0x0e0221b5,0x3563ee09,0x62347829,0x335d2ade,0xe06b8391, + 0x623f4b1a,0x760c058d }, + { 0xc198aa79,0x0b89b58c,0xf07aba7f,0xf74890d2,0xfde2556a,0x4e204110, + 0x8f190409,0x7141982d }, + 0 }, + /* 220 */ + { { 0x4d4b0f45,0x6f0a0e33,0x392a94e1,0xd9280b38,0xb3c61d5e,0x3af324c6, + 0x89d54e47,0x3af9d1ce }, + { 0x20930371,0xfd8f7981,0x21c17097,0xeda2664c,0xdc42309b,0x0e9545dc, + 0x73957dd6,0xb1f815c3 }, + 0 }, + /* 221 */ + { { 0x89fec44a,0x84faa78e,0x3caa4caf,0xc8c2ae47,0xc1b6a624,0x691c807d, + 0x1543f052,0xa41aed14 }, + { 0x7d5ffe04,0x42435399,0x625b6e20,0x8bacb2df,0x87817775,0x85d660be, + 0x86fb60ef,0xd6e9c1dd }, + 0 }, + /* 222 */ + { { 0xc6853264,0x3aa2e97e,0xe2304a0b,0x771533b7,0xb8eae9be,0x1b912bb7, + 0xae9bf8c2,0x9c9c6e10 }, + { 0xe030b74c,0xa2309a59,0x6a631e90,0x4ed7494d,0xa49b79f2,0x89f44b23, + 0x40fa61b6,0x566bd596 }, + 0 }, + /* 223 */ + { { 0xc18061f3,0x066c0118,0x7c83fc70,0x190b25d3,0x27273245,0xf05fc8e0, + 0xf525345e,0xcf2c7390 }, + { 0x10eb30cf,0xa09bceb4,0x0d77703a,0xcfd2ebba,0x150ff255,0xe842c43a, + 0x8aa20979,0x02f51755 }, + 0 }, + /* 224 */ + { { 0xaddb7d07,0x396ef794,0x24455500,0x0b4fc742,0xc78aa3ce,0xfaff8eac, + 0xe8d4d97d,0x14e9ada5 }, + { 0x2f7079e2,0xdaa480a1,0xe4b0800e,0x45baa3cd,0x7838157d,0x01765e2d, + 0x8e9d9ae8,0xa0ad4fab }, + 0 }, + /* 225 */ + { { 0x4a653618,0x0bfb7621,0x31eaaa5f,0x1872813c,0x44949d5e,0x1553e737, + 0x6e56ed1e,0xbcd530b8 }, + { 0x32e9c47b,0x169be853,0xb50059ab,0xdc2776fe,0x192bfbb4,0xcdba9761, + 0x6979341d,0x909283cf }, + 0 }, + /* 226 */ + { { 0x76e81a13,0x67b00324,0x62171239,0x9bee1a99,0xd32e19d6,0x08ed361b, + 0xace1549a,0x35eeb7c9 }, + { 0x7e4e5bdc,0x1280ae5a,0xb6ceec6e,0x2dcd2cd3,0x6e266bc1,0x52e4224c, + 0x448ae864,0x9a8b2cf4 }, + 0 }, + /* 227 */ + { { 0x09d03b59,0xf6471bf2,0xb65af2ab,0xc90e62a3,0xebd5eec9,0xff7ff168, + 0xd4491379,0x6bdb60f4 }, + { 0x8a55bc30,0xdadafebc,0x10097fe0,0xc79ead16,0x4c1e3bdd,0x42e19741, + 0x94ba08a9,0x01ec3cfd }, + 0 }, + /* 228 */ + { { 0xdc9485c2,0xba6277eb,0x22fb10c7,0x48cc9a79,0x70a28d8a,0x4f61d60f, + 0x475464f6,0xd1acb1c0 }, + { 0x26f36612,0xd26902b1,0xe0618d8b,0x59c3a44e,0x308357ee,0x4df8a813, + 0x405626c2,0x7dcd079d }, + 0 }, + /* 229 */ + { { 0xf05a4b48,0x5ce7d4d3,0x37230772,0xadcd2952,0x812a915a,0xd18f7971, + 0x377d19b8,0x0bf53589 }, + { 0x6c68ea73,0x35ecd95a,0x823a584d,0xc7f3bbca,0xf473a723,0x9fb674c6, + 0xe16686fc,0xd28be4d9 }, + 0 }, + /* 230 */ + { { 0x38fa8e4b,0x5d2b9906,0x893fd8fc,0x559f186e,0x436fb6fc,0x3a6de2aa, + 0x510f88ce,0xd76007aa }, + { 0x523a4988,0x2d10aab6,0x74dd0273,0xb455cf44,0xa3407278,0x7f467082, + 0xb303bb01,0xf2b52f68 }, + 0 }, + /* 231 */ + { { 0x9835b4ca,0x0d57eafa,0xbb669cbc,0x2d2232fc,0xc6643198,0x8eeeb680, + 0xcc5aed3a,0xd8dbe98e }, + { 0xc5a02709,0xcba9be3f,0xf5ba1fa8,0x30be68e5,0xf10ea852,0xfebd43cd, + 0xee559705,0xe01593a3 }, + 0 }, + /* 232 */ + { { 0xea75a0a6,0xd3e5af50,0x57858033,0x512226ac,0xd0176406,0x6fe6d50f, + 0xaeb8ef06,0xafec07b1 }, + { 0x80bb0a31,0x7fb99567,0x37309aae,0x6f1af3cc,0x01abf389,0x9153a15a, + 0x6e2dbfdd,0xa71b9354 }, + 0 }, + /* 233 */ + { { 0x18f593d2,0xbf8e12e0,0xa078122b,0xd1a90428,0x0ba4f2ad,0x150505db, + 0x628523d9,0x53a2005c }, + { 0xe7f2b935,0x07c8b639,0xc182961a,0x2bff975a,0x7518ca2c,0x86bceea7, + 0x3d588e3d,0xbf47d19b }, + 0 }, + /* 234 */ + { { 0xdd7665d5,0x672967a7,0x2f2f4de5,0x4e303057,0x80d4903f,0x144005ae, + 0x39c9a1b6,0x001c2c7f }, + { 0x69efc6d6,0x143a8014,0x7bc7a724,0xc810bdaa,0xa78150a4,0x5f65670b, + 0x86ffb99b,0xfdadf8e7 }, + 0 }, + /* 235 */ + { { 0xffc00785,0xfd38cb88,0x3b48eb67,0x77fa7591,0xbf368fbc,0x0454d055, + 0x5aa43c94,0x3a838e4d }, + { 0x3e97bb9a,0x56166329,0x441d94d9,0x9eb93363,0x0adb2a83,0x515591a6, + 0x873e1da3,0x3cdb8257 }, + 0 }, + /* 236 */ + { { 0x7de77eab,0x137140a9,0x41648109,0xf7e1c50d,0xceb1d0df,0x762dcad2, + 0xf1f57fba,0x5a60cc89 }, + { 0x40d45673,0x80b36382,0x5913c655,0x1b82be19,0xdd64b741,0x057284b8, + 0xdbfd8fc0,0x922ff56f }, + 0 }, + /* 237 */ + { { 0xc9a129a1,0x1b265dee,0xcc284e04,0xa5b1ce57,0xcebfbe3c,0x04380c46, + 0xf6c5cd62,0x72919a7d }, + { 0x8fb90f9a,0x298f453a,0x88e4031b,0xd719c00b,0x796f1856,0xe32c0e77, + 0x3624089a,0x5e791780 }, + 0 }, + /* 238 */ + { { 0x7f63cdfb,0x5c16ec55,0xf1cae4fd,0x8e6a3571,0x560597ca,0xfce26bea, + 0xe24c2fab,0x4e0a5371 }, + { 0xa5765357,0x276a40d3,0x0d73a2b4,0x3c89af44,0x41d11a32,0xb8f370ae, + 0xd56604ee,0xf5ff7818 }, + 0 }, + /* 239 */ + { { 0x1a09df21,0xfbf3e3fe,0xe66e8e47,0x26d5d28e,0x29c89015,0x2096bd0a, + 0x533f5e64,0xe41df0e9 }, + { 0xb3ba9e3f,0x305fda40,0x2604d895,0xf2340ceb,0x7f0367c7,0x0866e192, + 0xac4f155f,0x8edd7d6e }, + 0 }, + /* 240 */ + { { 0x0bfc8ff3,0xc9a1dc0e,0xe936f42f,0x14efd82b,0xcca381ef,0x67016f7c, + 0xed8aee96,0x1432c1ca }, + { 0x70b23c26,0xec684829,0x0735b273,0xa64fe873,0xeaef0f5a,0xe389f6e5, + 0x5ac8d2c6,0xcaef480b }, + 0 }, + /* 241 */ + { { 0x75315922,0x5245c978,0x3063cca5,0xd8295171,0xb64ef2cb,0xf3ce60d0, + 0x8efae236,0xd0ba177e }, + { 0xb1b3af60,0x53a9ae8f,0x3d2da20e,0x1a796ae5,0xdf9eef28,0x01d63605, + 0x1c54ae16,0xf31c957c }, + 0 }, + /* 242 */ + { { 0x49cc4597,0xc0f58d52,0xbae0a028,0xdc5015b0,0x734a814a,0xefc5fc55, + 0x96e17c3a,0x013404cb }, + { 0xc9a824bf,0xb29e2585,0x001eaed7,0xd593185e,0x61ef68ac,0x8d6ee682, + 0x91933e6c,0x6f377c4b }, + 0 }, + /* 243 */ + { { 0xa8333fd2,0x9f93bad1,0x5a2a95b8,0xa8930202,0xeaf75ace,0x211e5037, + 0xd2d09506,0x6dba3e4e }, + { 0xd04399cd,0xa48ef98c,0xe6b73ade,0x1811c66e,0xc17ecaf3,0x72f60752, + 0x3becf4a7,0xf13cf342 }, + 0 }, + /* 244 */ + { { 0xa919e2eb,0xceeb9ec0,0xf62c0f68,0x83a9a195,0x7aba2299,0xcfba3bb6, + 0x274bbad3,0xc83fa9a9 }, + { 0x62fa1ce0,0x0d7d1b0b,0x3418efbf,0xe58b60f5,0x52706f04,0xbfa8ef9e, + 0x5d702683,0xb49d70f4 }, + 0 }, + /* 245 */ + { { 0xfad5513b,0x914c7510,0xb1751e2d,0x05f32eec,0xd9fb9d59,0x6d850418, + 0x0c30f1cf,0x59cfadbb }, + { 0x55cb7fd6,0xe167ac23,0x820426a3,0x249367b8,0x90a78864,0xeaeec58c, + 0x354a4b67,0x5babf362 }, + 0 }, + /* 246 */ + { { 0xee424865,0x37c981d1,0xf2e5577f,0x8b002878,0xb9e0c058,0x702970f1, + 0x9026c8f0,0x6188c6a7 }, + { 0xd0f244da,0x06f9a19b,0xfb080873,0x1ecced5c,0x9f213637,0x35470f9b, + 0xdf50b9d9,0x993fe475 }, + 0 }, + /* 247 */ + { { 0x9b2c3609,0x68e31cdf,0x2c46d4ea,0x84eb19c0,0x9a775101,0x7ac9ec1a, + 0x4c80616b,0x81f76466 }, + { 0x75fbe978,0x1d7c2a5a,0xf183b356,0x6743fed3,0x501dd2bf,0x838d1f04, + 0x5fe9060d,0x564a812a }, + 0 }, + /* 248 */ + { { 0xfa817d1d,0x7a5a64f4,0xbea82e0f,0x55f96844,0xcd57f9aa,0xb5ff5a0f, + 0x00e51d6c,0x226bf3cf }, + { 0x2f2833cf,0xd6d1a9f9,0x4f4f89a8,0x20a0a35a,0x8f3f7f77,0x11536c49, + 0xff257836,0x68779f47 }, + 0 }, + /* 249 */ + { { 0x73043d08,0x79b0c1c1,0x1fc020fa,0xa5446774,0x9a6d26d0,0xd3767e28, + 0xeb092e0b,0x97bcb0d1 }, + { 0xf32ed3c3,0x2ab6eaa8,0xb281bc48,0xc8a4f151,0xbfa178f3,0x4d1bf4f3, + 0x0a784655,0xa872ffe8 }, + 0 }, + /* 250 */ + { { 0xa32b2086,0xb1ab7935,0x8160f486,0xe1eb710e,0x3b6ae6be,0x9bd0cd91, + 0xb732a36a,0x02812bfc }, + { 0xcf605318,0xa63fd7ca,0xfdfd6d1d,0x646e5d50,0x2102d619,0xa1d68398, + 0xfe5396af,0x07391cc9 }, + 0 }, + /* 251 */ + { { 0x8b80d02b,0xc50157f0,0x62877f7f,0x6b8333d1,0x78d542ae,0x7aca1af8, + 0x7e6d2a08,0x355d2adc }, + { 0x287386e1,0xb41f335a,0xf8e43275,0xfd272a94,0xe79989ea,0x286ca2cd, + 0x7c2a3a79,0x3dc2b1e3 }, + 0 }, + /* 252 */ + { { 0x04581352,0xd689d21c,0x376782be,0x0a00c825,0x9fed701f,0x203bd590, + 0x3ccd846b,0xc4786910 }, + { 0x24c768ed,0x5dba7708,0x6841f657,0x72feea02,0x6accce0e,0x73313ed5, + 0xd5bb4d32,0xccc42968 }, + 0 }, + /* 253 */ + { { 0x3d7620b9,0x94e50de1,0x5992a56a,0xd89a5c8a,0x675487c9,0xdc007640, + 0xaa4871cf,0xe147eb42 }, + { 0xacf3ae46,0x274ab4ee,0x50350fbe,0xfd4936fb,0x48c840ea,0xdf2afe47, + 0x080e96e3,0x239ac047 }, + 0 }, + /* 254 */ + { { 0x2bfee8d4,0x481d1f35,0xfa7b0fec,0xce80b5cf,0x2ce9af3c,0x105c4c9e, + 0xf5f7e59d,0xc55fa1a3 }, + { 0x8257c227,0x3186f14e,0x342be00b,0xc5b1653f,0xaa904fb2,0x09afc998, + 0xd4f4b699,0x094cd99c }, + 0 }, + /* 255 */ + { { 0xd703beba,0x8a981c84,0x32ceb291,0x8631d150,0xe3bd49ec,0xa445f2c9, + 0x42abad33,0xb90a30b6 }, + { 0xb4a5abf9,0xb465404f,0x75db7603,0x004750c3,0xca35d89f,0x6f9a42cc, + 0x1b7924f7,0x019f8b9a }, + 0 }, +}; + +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_base_8(sp_point* r, sp_digit* k, + int map, void* heap) +{ + return sp_256_ecc_mulmod_stripe_8(r, &p256_base, p256_table, + k, map, heap); +} + +#endif + +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * km Scalar to multiply by. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_base_256(mp_int* km, ecc_point* r, int map, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point p; + sp_digit kd[8]; +#endif + sp_point* point; + sp_digit* k = NULL; + int err = MP_OKAY; + + err = sp_ecc_point_new(heap, p, point); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + if (err == MP_OKAY) { + sp_256_from_mp(k, 8, km); + + err = sp_256_ecc_mulmod_base_8(point, k, map, heap); + } + if (err == MP_OKAY) + err = sp_256_point_to_ecc_point_8(point, r); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(point, 0, heap); + + return err; +} + +#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ + defined(HAVE_ECC_VERIFY) +/* Returns 1 if the number of zero. + * Implementation is constant time. + * + * a Number to check. + * returns 1 if the number is zero and 0 otherwise. + */ +static int sp_256_iszero_8(const sp_digit* a) +{ + return (a[0] | a[1] | a[2] | a[3] | a[4] | a[5] | a[6] | a[7]) == 0; +} + +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN || HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +/* Add 1 to a. (a = a + 1) + * + * a A single precision integer. + */ +SP_NOINLINE static void sp_256_add_one_8(sp_digit* a) +{ + __asm__ __volatile__ ( + "mov r2, #1\n\t" + "ldr r1, [%[a], #0]\n\t" + "adds r1, r1, r2\n\t" + "mov r2, #0\n\t" + "str r1, [%[a], #0]\n\t" + "ldr r1, [%[a], #4]\n\t" + "adcs r1, r1, r2\n\t" + "str r1, [%[a], #4]\n\t" + "ldr r1, [%[a], #8]\n\t" + "adcs r1, r1, r2\n\t" + "str r1, [%[a], #8]\n\t" + "ldr r1, [%[a], #12]\n\t" + "adcs r1, r1, r2\n\t" + "str r1, [%[a], #12]\n\t" + "ldr r1, [%[a], #16]\n\t" + "adcs r1, r1, r2\n\t" + "str r1, [%[a], #16]\n\t" + "ldr r1, [%[a], #20]\n\t" + "adcs r1, r1, r2\n\t" + "str r1, [%[a], #20]\n\t" + "ldr r1, [%[a], #24]\n\t" + "adcs r1, r1, r2\n\t" + "str r1, [%[a], #24]\n\t" + "ldr r1, [%[a], #28]\n\t" + "adcs r1, r1, r2\n\t" + "str r1, [%[a], #28]\n\t" + : + : [a] "r" (a) + : "memory", "r1", "r2" + ); +} + +/* Read big endian unsigned byte aray into r. + * + * r A single precision integer. + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_256_from_bin(sp_digit* r, int max, const byte* a, int n) +{ + int i, j = 0, s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= ((sp_digit)a[i]) << s; + if (s >= 24) { + r[j] &= 0xffffffff; + s = 32 - s; + if (j + 1 >= max) + break; + r[++j] = a[i] >> s; + s = 8 - s; + } + else + s += 8; + } + + for (j++; j < max; j++) + r[j] = 0; +} + +/* Generates a scalar that is in the range 1..order-1. + * + * rng Random number generator. + * k Scalar value. + * returns RNG failures, MEMORY_E when memory allocation fails and + * MP_OKAY on success. + */ +static int sp_256_ecc_gen_k_8(WC_RNG* rng, sp_digit* k) +{ + int err; + byte buf[32]; + + do { + err = wc_RNG_GenerateBlock(rng, buf, sizeof(buf)); + if (err == 0) { + sp_256_from_bin(k, 8, buf, sizeof(buf)); + if (sp_256_cmp_8(k, p256_order2) < 0) { + sp_256_add_one_8(k); + break; + } + } + } + while (err == 0); + + return err; +} + +/* Makes a random EC key pair. + * + * rng Random number generator. + * priv Generated private value. + * pub Generated public point. + * heap Heap to use for allocation. + * returns ECC_INF_E when the point does not have the correct order, RNG + * failures, MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point p; + sp_digit kd[8]; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point inf; +#endif +#endif + sp_point* point; + sp_digit* k = NULL; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point* infinity; +#endif + int err; + + (void)heap; + + err = sp_ecc_point_new(heap, p, point); +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, inf, infinity); +#endif +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + + if (err == MP_OKAY) + err = sp_256_ecc_gen_k_8(rng, k); + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_base_8(point, k, 1, NULL); + } + +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_8(infinity, point, p256_order, 1, NULL); + } + if (err == MP_OKAY) { + if (!sp_256_iszero_8(point->x) || !sp_256_iszero_8(point->y)) + err = ECC_INF_E; + } +#endif + + if (err == MP_OKAY) + err = sp_256_to_mp(k, priv); + if (err == MP_OKAY) + err = sp_256_point_to_ecc_point_8(point, pub); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); +#endif +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_ecc_point_free(infinity, 1, heap); +#endif + sp_ecc_point_free(point, 1, heap); + + return err; +} + +#ifdef HAVE_ECC_DHE +/* Write r as big endian to byte aray. + * Fixed length number of bytes written: 32 + * + * r A single precision integer. + * a Byte array. + */ +static void sp_256_to_bin(sp_digit* r, byte* a) +{ + int i, j, s = 0, b; + + j = 256 / 8 - 1; + a[j] = 0; + for (i=0; i<8 && j>=0; i++) { + b = 0; + a[j--] |= r[i] << s; b += 8 - s; + if (j < 0) + break; + while (b < 32) { + a[j--] = r[i] >> b; b += 8; + if (j < 0) + break; + } + s = 8 - (b - 32); + if (j >= 0) + a[j] = 0; + if (s != 0) + j++; + } +} + +/* Multiply the point by the scalar and serialize the X ordinate. + * The number is 0 padded to maximum size on output. + * + * priv Scalar to multiply the point by. + * pub Point to multiply. + * out Buffer to hold X ordinate. + * outLen On entry, size of the buffer in bytes. + * On exit, length of data in buffer in bytes. + * heap Heap to use for allocation. + * returns BUFFER_E if the buffer is to small for output size, + * MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_secret_gen_256(mp_int* priv, ecc_point* pub, byte* out, + word32* outLen, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point p; + sp_digit kd[8]; +#endif + sp_point* point = NULL; + sp_digit* k = NULL; + int err = MP_OKAY; + + if (*outLen < 32) + err = BUFFER_E; + + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, p, point); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(k, 8, priv); + sp_256_point_from_ecc_point_8(point, pub); + err = sp_256_ecc_mulmod_8(point, point, k, 1, heap); + } + if (err == MP_OKAY) { + sp_256_to_bin(point->x, out); + *outLen = 32; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(point, 0, heap); + + return err; +} +#endif /* HAVE_ECC_DHE */ + +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +#ifdef WOLFSSL_SP_SMALL +/* Sub b from a into a. (a -= b) + * + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_256_sub_in_place_8(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + __asm__ __volatile__ ( + "mov r7, %[a]\n\t" + "add r7, r7, #32\n\t" + "\n1:\n\t" + "mov r5, #0\n\t" + "subs r5, r5, %[c]\n\t" + "ldr r3, [%[a]]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b]]\n\t" + "ldr r6, [%[b], #4]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a]]\n\t" + "str r4, [%[a], #4]\n\t" + "sbc %[c], %[c], %[c]\n\t" + "add %[a], %[a], #8\n\t" + "add %[b], %[b], #8\n\t" + "cmp %[a], r7\n\t" + "bne 1b\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6", "r7" + ); + + return c; +} + +#else +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static sp_digit sp_256_sub_in_place_8(sp_digit* a, + const sp_digit* b) +{ + sp_digit c = 0; + + __asm__ __volatile__ ( + "ldr r3, [%[a], #0]\n\t" + "ldr r4, [%[a], #4]\n\t" + "ldr r5, [%[b], #0]\n\t" + "ldr r6, [%[b], #4]\n\t" + "subs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #0]\n\t" + "str r4, [%[a], #4]\n\t" + "ldr r3, [%[a], #8]\n\t" + "ldr r4, [%[a], #12]\n\t" + "ldr r5, [%[b], #8]\n\t" + "ldr r6, [%[b], #12]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #8]\n\t" + "str r4, [%[a], #12]\n\t" + "ldr r3, [%[a], #16]\n\t" + "ldr r4, [%[a], #20]\n\t" + "ldr r5, [%[b], #16]\n\t" + "ldr r6, [%[b], #20]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #16]\n\t" + "str r4, [%[a], #20]\n\t" + "ldr r3, [%[a], #24]\n\t" + "ldr r4, [%[a], #28]\n\t" + "ldr r5, [%[b], #24]\n\t" + "ldr r6, [%[b], #28]\n\t" + "sbcs r3, r3, r5\n\t" + "sbcs r4, r4, r6\n\t" + "str r3, [%[a], #24]\n\t" + "str r4, [%[a], #28]\n\t" + "sbc %[c], %[c], %[c]\n\t" + : [c] "+r" (c), [a] "+r" (a), [b] "+r" (b) + : + : "memory", "r3", "r4", "r5", "r6" + ); + + return c; +} + +#endif /* WOLFSSL_SP_SMALL */ +/* Mul a by digit b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision digit. + */ +SP_NOINLINE static void sp_256_mul_d_8(sp_digit* r, const sp_digit* a, + const sp_digit b) +{ + __asm__ __volatile__ ( + "mov r6, #32\n\t" + "add r6, r6, %[a]\n\t" + "mov r8, %[r]\n\t" + "mov r9, r6\n\t" + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "\n1:\n\t" + "mov %[r], #0\n\t" + "mov r5, #0\n\t" + /* A[] * B */ + "ldr r6, [%[a]]\n\t" + "umull r6, r7, r6, %[b]\n\t" + "adds r3, r3, r6\n\t" + "adcs r4, r4, r7\n\t" + "adc r5, r5, %[r]\n\t" + /* A[] * B - Done */ + "mov %[r], r8\n\t" + "str r3, [%[r]]\n\t" + "mov r3, r4\n\t" + "mov r4, r5\n\t" + "add %[r], %[r], #4\n\t" + "add %[a], %[a], #4\n\t" + "mov r8, %[r]\n\t" + "cmp %[a], r9\n\t" + "blt 1b\n\t" + "str r3, [%[r]]\n\t" + : [r] "+r" (r), [a] "+r" (a) + : [b] "r" (b) + : "memory", "r3", "r4", "r5", "r6", "r7", "r8", "r9" + ); +} + +/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) + * + * d1 The high order half of the number to divide. + * d0 The low order half of the number to divide. + * div The dividend. + * returns the result of the division. + * + * Note that this is an approximate div. It may give an answer 1 larger. + */ +SP_NOINLINE static sp_digit div_256_word_8(sp_digit d1, sp_digit d0, + sp_digit div) +{ + sp_digit r = 0; + + __asm__ __volatile__ ( + "lsr r6, %[div], #16\n\t" + "add r6, r6, #1\n\t" + "udiv r4, %[d1], r6\n\t" + "lsl r7, r4, #16\n\t" + "umull r4, r5, %[div], r7\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "udiv r5, %[d1], r6\n\t" + "lsl r4, r5, #16\n\t" + "add r7, r7, r4\n\t" + "umull r4, r5, %[div], r4\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "lsl r4, %[d1], #16\n\t" + "orr r4, r4, %[d0], lsr 16\n\t" + "udiv r4, r4, r6\n\t" + "add r7, r7, r4\n\t" + "umull r4, r5, %[div], r4\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "lsl r4, %[d1], #16\n\t" + "orr r4, r4, %[d0], lsr 16\n\t" + "udiv r4, r4, r6\n\t" + "add r7, r7, r4\n\t" + "umull r4, r5, %[div], r4\n\t" + "subs %[d0], %[d0], r4\n\t" + "sbc %[d1], %[d1], r5\n\t" + "udiv r4, %[d0], %[div]\n\t" + "add r7, r7, r4\n\t" + "mov %[r], r7\n\t" + : [r] "+r" (r) + : [d1] "r" (d1), [d0] "r" (d0), [div] "r" (div) + : "r4", "r5", "r6", "r7" + ); + return r; +} + +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_256_mask_8(sp_digit* r, sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<8; i++) + r[i] = a[i] & m; +#else + r[0] = a[0] & m; + r[1] = a[1] & m; + r[2] = a[2] & m; + r[3] = a[3] & m; + r[4] = a[4] & m; + r[5] = a[5] & m; + r[6] = a[6] & m; + r[7] = a[7] & m; +#endif +} + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_256_div_8(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[16], t2[9]; + sp_digit div, r1; + int i; + + (void)m; + + div = d[7]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 8); + for (i=7; i>=0; i--) { + r1 = div_256_word_8(t1[8 + i], t1[8 + i - 1], div); + + sp_256_mul_d_8(t2, d, r1); + t1[8 + i] += sp_256_sub_in_place_8(&t1[i], t2); + t1[8 + i] -= t2[8]; + sp_256_mask_8(t2, d, t1[8 + i]); + t1[8 + i] += sp_256_add_8(&t1[i], &t1[i], t2); + sp_256_mask_8(t2, d, t1[8 + i]); + t1[8 + i] += sp_256_add_8(&t1[i], &t1[i], t2); + } + + r1 = sp_256_cmp_8(t1, d) >= 0; + sp_256_cond_sub_8(r, t1, d, (sp_digit)0 - r1); + + return MP_OKAY; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_256_mod_8(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_256_div_8(a, m, NULL, r); +} + +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +#ifdef WOLFSSL_SP_SMALL +/* Order-2 for the P256 curve. */ +static const uint32_t p256_order_2[8] = { + 0xfc63254f,0xf3b9cac2,0xa7179e84,0xbce6faad,0xffffffff,0xffffffff, + 0x00000000,0xffffffff +}; +#else +/* The low half of the order-2 of the P256 curve. */ +static const uint32_t p256_order_low[4] = { + 0xfc63254f,0xf3b9cac2,0xa7179e84,0xbce6faad +}; +#endif /* WOLFSSL_SP_SMALL */ + +/* Multiply two number mod the order of P256 curve. (r = a * b mod order) + * + * r Result of the multiplication. + * a First operand of the multiplication. + * b Second operand of the multiplication. + */ +static void sp_256_mont_mul_order_8(sp_digit* r, sp_digit* a, sp_digit* b) +{ + sp_256_mul_8(r, a, b); + sp_256_mont_reduce_order_8(r, p256_order, p256_mp_order); +} + +/* Square number mod the order of P256 curve. (r = a * a mod order) + * + * r Result of the squaring. + * a Number to square. + */ +static void sp_256_mont_sqr_order_8(sp_digit* r, sp_digit* a) +{ + sp_256_sqr_8(r, a); + sp_256_mont_reduce_order_8(r, p256_order, p256_mp_order); +} + +#ifndef WOLFSSL_SP_SMALL +/* Square number mod the order of P256 curve a number of times. + * (r = a ^ n mod order) + * + * r Result of the squaring. + * a Number to square. + */ +static void sp_256_mont_sqr_n_order_8(sp_digit* r, sp_digit* a, int n) +{ + int i; + + sp_256_mont_sqr_order_8(r, a); + for (i=1; i=0; i--) { + sp_256_mont_sqr_order_8(t, t); + if (p256_order_2[i / 32] & ((sp_digit)1 << (i % 32))) + sp_256_mont_mul_order_8(t, t, a); + } + XMEMCPY(r, t, sizeof(sp_digit) * 8); +#else + sp_digit* t = td; + sp_digit* t2 = td + 2 * 8; + sp_digit* t3 = td + 4 * 8; + int i; + + /* t = a^2 */ + sp_256_mont_sqr_order_8(t, a); + /* t = a^3 = t * a */ + sp_256_mont_mul_order_8(t, t, a); + /* t2= a^c = t ^ 2 ^ 2 */ + sp_256_mont_sqr_n_order_8(t2, t, 2); + /* t3= a^f = t2 * t */ + sp_256_mont_mul_order_8(t3, t2, t); + /* t2= a^f0 = t3 ^ 2 ^ 4 */ + sp_256_mont_sqr_n_order_8(t2, t3, 4); + /* t = a^ff = t2 * t3 */ + sp_256_mont_mul_order_8(t, t2, t3); + /* t3= a^ff00 = t ^ 2 ^ 8 */ + sp_256_mont_sqr_n_order_8(t2, t, 8); + /* t = a^ffff = t2 * t */ + sp_256_mont_mul_order_8(t, t2, t); + /* t2= a^ffff0000 = t ^ 2 ^ 16 */ + sp_256_mont_sqr_n_order_8(t2, t, 16); + /* t = a^ffffffff = t2 * t */ + sp_256_mont_mul_order_8(t, t2, t); + /* t2= a^ffffffff0000000000000000 = t ^ 2 ^ 64 */ + sp_256_mont_sqr_n_order_8(t2, t, 64); + /* t2= a^ffffffff00000000ffffffff = t2 * t */ + sp_256_mont_mul_order_8(t2, t2, t); + /* t2= a^ffffffff00000000ffffffff00000000 = t2 ^ 2 ^ 32 */ + sp_256_mont_sqr_n_order_8(t2, t2, 32); + /* t2= a^ffffffff00000000ffffffffffffffff = t2 * t */ + sp_256_mont_mul_order_8(t2, t2, t); + /* t2= a^ffffffff00000000ffffffffffffffffbce6 */ + for (i=127; i>=112; i--) { + sp_256_mont_sqr_order_8(t2, t2); + if (p256_order_low[i / 32] & ((sp_digit)1 << (i % 32))) + sp_256_mont_mul_order_8(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6f */ + sp_256_mont_sqr_n_order_8(t2, t2, 4); + sp_256_mont_mul_order_8(t2, t2, t3); + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84 */ + for (i=107; i>=64; i--) { + sp_256_mont_sqr_order_8(t2, t2); + if (p256_order_low[i / 32] & ((sp_digit)1 << (i % 32))) + sp_256_mont_mul_order_8(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f */ + sp_256_mont_sqr_n_order_8(t2, t2, 4); + sp_256_mont_mul_order_8(t2, t2, t3); + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2 */ + for (i=59; i>=32; i--) { + sp_256_mont_sqr_order_8(t2, t2); + if (p256_order_low[i / 32] & ((sp_digit)1 << (i % 32))) + sp_256_mont_mul_order_8(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2f */ + sp_256_mont_sqr_n_order_8(t2, t2, 4); + sp_256_mont_mul_order_8(t2, t2, t3); + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254 */ + for (i=27; i>=0; i--) { + sp_256_mont_sqr_order_8(t2, t2); + if (p256_order_low[i / 32] & ((sp_digit)1 << (i % 32))) + sp_256_mont_mul_order_8(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632540 */ + sp_256_mont_sqr_n_order_8(t2, t2, 4); + /* r = a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f */ + sp_256_mont_mul_order_8(r, t2, t3); +#endif /* WOLFSSL_SP_SMALL */ +} + +#endif /* HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +#ifdef HAVE_ECC_SIGN +#ifndef SP_ECC_MAX_SIG_GEN +#define SP_ECC_MAX_SIG_GEN 64 +#endif + +/* Sign the hash using the private key. + * e = [hash, 256 bits] from binary + * r = (k.G)->x mod order + * s = (r * x + e) / k mod order + * The hash is truncated to the first 256 bits. + * + * hash Hash to sign. + * hashLen Length of the hash data. + * rng Random number generator. + * priv Private part of key - scalar. + * rm First part of result as an mp_int. + * sm Sirst part of result as an mp_int. + * heap Heap to use for allocation. + * returns RNG failures, MEMORY_E when memory allocation fails and + * MP_OKAY on success. + */ +int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, + mp_int* rm, mp_int* sm, void* heap) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d = NULL; +#else + sp_digit ed[2*8]; + sp_digit xd[2*8]; + sp_digit kd[2*8]; + sp_digit rd[2*8]; + sp_digit td[3 * 2*8]; + sp_point p; +#endif + sp_digit* e = NULL; + sp_digit* x = NULL; + sp_digit* k = NULL; + sp_digit* r = NULL; + sp_digit* tmp = NULL; + sp_point* point = NULL; + sp_digit carry; + sp_digit* s; + sp_digit* kInv; + int err = MP_OKAY; + int32_t c; + int i; + + (void)heap; + + err = sp_ecc_point_new(heap, p, point); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 8, heap, + DYNAMIC_TYPE_ECC); + if (d != NULL) { + e = d + 0 * 8; + x = d + 2 * 8; + k = d + 4 * 8; + r = d + 6 * 8; + tmp = d + 8 * 8; + } + else + err = MEMORY_E; + } +#else + e = ed; + x = xd; + k = kd; + r = rd; + tmp = td; +#endif + s = e; + kInv = k; + + if (err == MP_OKAY) { + if (hashLen > 32) + hashLen = 32; + + sp_256_from_bin(e, 8, hash, hashLen); + } + + for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { + sp_256_from_mp(x, 8, priv); + + /* New random point. */ + err = sp_256_ecc_gen_k_8(rng, k); + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_base_8(point, k, 1, NULL); + } + + if (err == MP_OKAY) { + /* r = point->x mod order */ + XMEMCPY(r, point->x, sizeof(sp_digit) * 8); + sp_256_norm_8(r); + c = sp_256_cmp_8(r, p256_order); + sp_256_cond_sub_8(r, r, p256_order, 0 - (c >= 0)); + sp_256_norm_8(r); + + /* Conv k to Montgomery form (mod order) */ + sp_256_mul_8(k, k, p256_norm_order); + err = sp_256_mod_8(k, k, p256_order); + } + if (err == MP_OKAY) { + sp_256_norm_8(k); + /* kInv = 1/k mod order */ + sp_256_mont_inv_order_8(kInv, k, tmp); + sp_256_norm_8(kInv); + + /* s = r * x + e */ + sp_256_mul_8(x, x, r); + err = sp_256_mod_8(x, x, p256_order); + } + if (err == MP_OKAY) { + sp_256_norm_8(x); + carry = sp_256_add_8(s, e, x); + sp_256_cond_sub_8(s, s, p256_order, 0 - carry); + sp_256_norm_8(s); + c = sp_256_cmp_8(s, p256_order); + sp_256_cond_sub_8(s, s, p256_order, 0 - (c >= 0)); + sp_256_norm_8(s); + + /* s = s * k^-1 mod order */ + sp_256_mont_mul_order_8(s, s, kInv); + sp_256_norm_8(s); + + /* Check that signature is usable. */ + if (!sp_256_iszero_8(s)) + break; + } + } + + if (i == 0) + err = RNG_FAILURE_E; + + if (err == MP_OKAY) + err = sp_256_to_mp(r, rm); + if (err == MP_OKAY) + err = sp_256_to_mp(s, sm); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) { + XMEMSET(d, 0, sizeof(sp_digit) * 8 * 8); + XFREE(d, heap, DYNAMIC_TYPE_ECC); + } +#else + XMEMSET(e, 0, sizeof(sp_digit) * 2 * 8); + XMEMSET(x, 0, sizeof(sp_digit) * 2 * 8); + XMEMSET(k, 0, sizeof(sp_digit) * 2 * 8); + XMEMSET(r, 0, sizeof(sp_digit) * 2 * 8); + XMEMSET(r, 0, sizeof(sp_digit) * 2 * 8); + XMEMSET(tmp, 0, sizeof(sp_digit) * 3 * 2*8); +#endif + sp_ecc_point_free(point, 1, heap); + + return err; +} +#endif /* HAVE_ECC_SIGN */ + +#ifdef HAVE_ECC_VERIFY +/* Verify the signature values with the hash and public key. + * e = Truncate(hash, 256) + * u1 = e/s mod order + * u2 = r/s mod order + * r == (u1.G + u2.Q)->x mod order + * Optimization: Leave point in projective form. + * (x, y, 1) == (x' / z'*z', y' / z'*z'*z', z' / z') + * (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' + * The hash is truncated to the first 256 bits. + * + * hash Hash to sign. + * hashLen Length of the hash data. + * rng Random number generator. + * priv Private part of key - scalar. + * rm First part of result as an mp_int. + * sm Sirst part of result as an mp_int. + * heap Heap to use for allocation. + * returns RNG failures, MEMORY_E when memory allocation fails and + * MP_OKAY on success. + */ +int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, + mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d = NULL; +#else + sp_digit u1d[2*8]; + sp_digit u2d[2*8]; + sp_digit sd[2*8]; + sp_digit tmpd[2*8 * 5]; + sp_point p1d; + sp_point p2d; +#endif + sp_digit* u1; + sp_digit* u2; + sp_digit* s; + sp_digit* tmp; + sp_point* p1; + sp_point* p2 = NULL; + sp_digit carry; + int32_t c; + int err; + + err = sp_ecc_point_new(heap, p1d, p1); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, p2d, p2); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 8, heap, + DYNAMIC_TYPE_ECC); + if (d != NULL) { + u1 = d + 0 * 8; + u2 = d + 2 * 8; + s = d + 4 * 8; + tmp = d + 6 * 8; + } + else + err = MEMORY_E; + } +#else + u1 = u1d; + u2 = u2d; + s = sd; + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + if (hashLen > 32) + hashLen = 32; + + sp_256_from_bin(u1, 8, hash, hashLen); + sp_256_from_mp(u2, 8, r); + sp_256_from_mp(s, 8, sm); + sp_256_from_mp(p2->x, 8, pX); + sp_256_from_mp(p2->y, 8, pY); + sp_256_from_mp(p2->z, 8, pZ); + + sp_256_mul_8(s, s, p256_norm_order); + err = sp_256_mod_8(s, s, p256_order); + } + if (err == MP_OKAY) { + sp_256_norm_8(s); + { + sp_256_mont_inv_order_8(s, s, tmp); + sp_256_mont_mul_order_8(u1, u1, s); + sp_256_mont_mul_order_8(u2, u2, s); + } + + err = sp_256_ecc_mulmod_base_8(p1, u1, 0, heap); + } + if (err == MP_OKAY) { + err = sp_256_ecc_mulmod_8(p2, p2, u2, 0, heap); + } + + if (err == MP_OKAY) { + sp_256_proj_point_add_8(p1, p1, p2, tmp); + + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_256_from_mp(u2, 8, r); + err = sp_256_mod_mul_norm_8(u2, u2, p256_mod); + } + + if (err == MP_OKAY) { + /* u1 = r.z'.z' mod prime */ + sp_256_mont_sqr_8(p1->z, p1->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(u1, u2, p1->z, p256_mod, p256_mp_mod); + *res = sp_256_cmp_8(p1->x, u1) == 0; + if (*res == 0) { + /* Reload r and add order. */ + sp_256_from_mp(u2, 8, r); + carry = sp_256_add_8(u2, u2, p256_order); + /* Carry means result is greater than mod and is not valid. */ + if (!carry) { + sp_256_norm_8(u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_256_cmp_8(u2, p256_mod); + if (c < 0) { + /* Convert to Montogomery form */ + err = sp_256_mod_mul_norm_8(u2, u2, p256_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_256_mont_mul_8(u1, u2, p1->z, p256_mod, + p256_mp_mod); + *res = sp_256_cmp_8(p1->x, u2) == 0; + } + } + } + } + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p1, 0, heap); + sp_ecc_point_free(p2, 0, heap); + + return err; +} +#endif /* HAVE_ECC_VERIFY */ + +#ifdef HAVE_ECC_CHECK_KEY +/* Check that the x and y oridinates are a valid point on the curve. + * + * point EC point. + * heap Heap to use if dynamically allocating. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +static int sp_256_ecc_is_point_8(sp_point* point, void* heap) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d = NULL; +#else + sp_digit t1d[2*8]; + sp_digit t2d[2*8]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8 * 4, heap, + DYNAMIC_TYPE_ECC); + if (d != NULL) { + t1 = d + 0 * 8; + t2 = d + 2 * 8; + } + else + err = MEMORY_E; +#else + (void)heap; + + t1 = t1d; + t2 = t2d; +#endif + + if (err == MP_OKAY) { + sp_256_sqr_8(t1, point->y); + sp_256_mod_8(t1, t1, p256_mod); + sp_256_sqr_8(t2, point->x); + sp_256_mod_8(t2, t2, p256_mod); + sp_256_mul_8(t2, t2, point->x); + sp_256_mod_8(t2, t2, p256_mod); + sp_256_sub_8(t2, p256_mod, t2); + sp_256_mont_add_8(t1, t1, t2, p256_mod); + + sp_256_mont_add_8(t1, t1, point->x, p256_mod); + sp_256_mont_add_8(t1, t1, point->x, p256_mod); + sp_256_mont_add_8(t1, t1, point->x, p256_mod); + + if (sp_256_cmp_8(t1, p256_b) != 0) + err = MP_VAL; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Check that the x and y oridinates are a valid point on the curve. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +int sp_ecc_is_point_256(mp_int* pX, mp_int* pY) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point pubd; +#endif + sp_point* pub; + byte one[1] = { 1 }; + int err; + + err = sp_ecc_point_new(NULL, pubd, pub); + if (err == MP_OKAY) { + sp_256_from_mp(pub->x, 8, pX); + sp_256_from_mp(pub->y, 8, pY); + sp_256_from_bin(pub->z, 8, one, sizeof(one)); + + err = sp_256_ecc_is_point_8(pub, NULL); + } + + sp_ecc_point_free(pub, 0, NULL); + + return err; +} + +/* Check that the private scalar generates the EC point (px, py), the point is + * on the curve and the point has the correct order. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * privm Private scalar that generates EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve, ECC_INF_E if the point does not have the correct order, + * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and + * MP_OKAY otherwise. + */ +int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit privd[8]; + sp_point pubd; + sp_point pd; +#endif + sp_digit* priv = NULL; + sp_point* pub; + sp_point* p = NULL; + byte one[1] = { 1 }; + int err; + + err = sp_ecc_point_new(heap, pubd, pub); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 8, heap, + DYNAMIC_TYPE_ECC); + if (priv == NULL) + err = MEMORY_E; + } +#else + priv = privd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(pub->x, 8, pX); + sp_256_from_mp(pub->y, 8, pY); + sp_256_from_bin(pub->z, 8, one, sizeof(one)); + sp_256_from_mp(priv, 8, privm); + + /* Check point at infinitiy. */ + if (sp_256_iszero_8(pub->x) && + sp_256_iszero_8(pub->y)) + err = ECC_INF_E; + } + + if (err == MP_OKAY) { + /* Check range of X and Y */ + if (sp_256_cmp_8(pub->x, p256_mod) >= 0 || + sp_256_cmp_8(pub->y, p256_mod) >= 0) + err = ECC_OUT_OF_RANGE_E; + } + + if (err == MP_OKAY) { + /* Check point is on curve */ + err = sp_256_ecc_is_point_8(pub, heap); + } + + if (err == MP_OKAY) { + /* Point * order = infinity */ + err = sp_256_ecc_mulmod_8(p, pub, p256_order, 1, heap); + } + if (err == MP_OKAY) { + /* Check result is infinity */ + if (!sp_256_iszero_8(p->x) || + !sp_256_iszero_8(p->y)) { + err = ECC_INF_E; + } + } + + if (err == MP_OKAY) { + /* Base * private = point */ + err = sp_256_ecc_mulmod_base_8(p, priv, 1, heap); + } + if (err == MP_OKAY) { + /* Check result is public key */ + if (sp_256_cmp_8(p->x, pub->x) != 0 || + sp_256_cmp_8(p->y, pub->y) != 0) { + err = ECC_PRIV_KEY_E; + } + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (priv != NULL) + XFREE(priv, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p, 0, heap); + sp_ecc_point_free(pub, 0, heap); + + return err; +} +#endif +#ifdef WOLFSSL_PUBLIC_ECC_ADD_DBL +/* Add two projective EC points together. + * (pX, pY, pZ) + (qX, qY, qZ) = (rX, rY, rZ) + * + * pX First EC point's X ordinate. + * pY First EC point's Y ordinate. + * pZ First EC point's Z ordinate. + * qX Second EC point's X ordinate. + * qY Second EC point's Y ordinate. + * qZ Second EC point's Z ordinate. + * rX Resultant EC point's X ordinate. + * rY Resultant EC point's Y ordinate. + * rZ Resultant EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* qX, mp_int* qY, mp_int* qZ, + mp_int* rX, mp_int* rY, mp_int* rZ) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit tmpd[2 * 8 * 5]; + sp_point pd; + sp_point qd; +#endif + sp_digit* tmp; + sp_point* p; + sp_point* q = NULL; + int err; + + err = sp_ecc_point_new(NULL, pd, p); + if (err == MP_OKAY) + err = sp_ecc_point_new(NULL, qd, q); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 5, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } +#else + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 8, pX); + sp_256_from_mp(p->y, 8, pY); + sp_256_from_mp(p->z, 8, pZ); + sp_256_from_mp(q->x, 8, qX); + sp_256_from_mp(q->y, 8, qY); + sp_256_from_mp(q->z, 8, qZ); + + sp_256_proj_point_add_8(p, p, q, tmp); + } + + if (err == MP_OKAY) + err = sp_256_to_mp(p->x, rX); + if (err == MP_OKAY) + err = sp_256_to_mp(p->y, rY); + if (err == MP_OKAY) + err = sp_256_to_mp(p->z, rZ); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (tmp != NULL) + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(q, 0, NULL); + sp_ecc_point_free(p, 0, NULL); + + return err; +} + +/* Double a projective EC point. + * (pX, pY, pZ) + (pX, pY, pZ) = (rX, rY, rZ) + * + * pX EC point's X ordinate. + * pY EC point's Y ordinate. + * pZ EC point's Z ordinate. + * rX Resultant EC point's X ordinate. + * rY Resultant EC point's Y ordinate. + * rZ Resultant EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* rX, mp_int* rY, mp_int* rZ) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit tmpd[2 * 8 * 2]; + sp_point pd; +#endif + sp_digit* tmp; + sp_point* p; + int err; + + err = sp_ecc_point_new(NULL, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 2, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } +#else + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 8, pX); + sp_256_from_mp(p->y, 8, pY); + sp_256_from_mp(p->z, 8, pZ); + + sp_256_proj_point_dbl_8(p, p, tmp); + } + + if (err == MP_OKAY) + err = sp_256_to_mp(p->x, rX); + if (err == MP_OKAY) + err = sp_256_to_mp(p->y, rY); + if (err == MP_OKAY) + err = sp_256_to_mp(p->z, rZ); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (tmp != NULL) + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p, 0, NULL); + + return err; +} + +/* Map a projective EC point to affine in place. + * pZ will be one. + * + * pX EC point's X ordinate. + * pY EC point's Y ordinate. + * pZ EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit tmpd[2 * 8 * 4]; + sp_point pd; +#endif + sp_digit* tmp; + sp_point* p; + int err; + + err = sp_ecc_point_new(NULL, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 8 * 4, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } +#else + tmp = tmpd; +#endif + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 8, pX); + sp_256_from_mp(p->y, 8, pY); + sp_256_from_mp(p->z, 8, pZ); + + sp_256_map_8(p, p, tmp); + } + + if (err == MP_OKAY) + err = sp_256_to_mp(p->x, pX); + if (err == MP_OKAY) + err = sp_256_to_mp(p->y, pY); + if (err == MP_OKAY) + err = sp_256_to_mp(p->z, pZ); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (tmp != NULL) + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p, 0, NULL); + + return err; +} +#endif /* WOLFSSL_PUBLIC_ECC_ADD_DBL */ +#ifdef HAVE_COMP_KEY +/* Find the square root of a number mod the prime of the curve. + * + * y The number to operate on and the result. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +static int sp_256_mont_sqrt_8(sp_digit* y) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d; +#else + sp_digit t1d[2 * 8]; + sp_digit t2d[2 * 8]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 8, NULL, DYNAMIC_TYPE_ECC); + if (d != NULL) { + t1 = d + 0 * 8; + t2 = d + 2 * 8; + } + else + err = MEMORY_E; +#else + t1 = t1d; + t2 = t2d; +#endif + + if (err == MP_OKAY) { + { + /* t2 = y ^ 0x2 */ + sp_256_mont_sqr_8(t2, y, p256_mod, p256_mp_mod); + /* t1 = y ^ 0x3 */ + sp_256_mont_mul_8(t1, t2, y, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xc */ + sp_256_mont_sqr_n_8(t2, t1, 2, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xf */ + sp_256_mont_mul_8(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xf0 */ + sp_256_mont_sqr_n_8(t2, t1, 4, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xff */ + sp_256_mont_mul_8(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xff00 */ + sp_256_mont_sqr_n_8(t2, t1, 8, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffff */ + sp_256_mont_mul_8(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xffff0000 */ + sp_256_mont_sqr_n_8(t2, t1, 16, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff */ + sp_256_mont_mul_8(t1, t1, t2, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000000 */ + sp_256_mont_sqr_n_8(t1, t1, 32, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001 */ + sp_256_mont_mul_8(t1, t1, y, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001000000000000000000000000 */ + sp_256_mont_sqr_n_8(t1, t1, 96, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001000000000000000000000001 */ + sp_256_mont_mul_8(t1, t1, y, p256_mod, p256_mp_mod); + sp_256_mont_sqr_n_8(y, t1, 94, p256_mod, p256_mp_mod); + } + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Uncompress the point given the X ordinate. + * + * xm X ordinate. + * odd Whether the Y ordinate is odd. + * ym Calculated Y ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d; +#else + sp_digit xd[2 * 8]; + sp_digit yd[2 * 8]; +#endif + sp_digit* x; + sp_digit* y; + int err = MP_OKAY; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 8, NULL, DYNAMIC_TYPE_ECC); + if (d != NULL) { + x = d + 0 * 8; + y = d + 2 * 8; + } + else + err = MEMORY_E; +#else + x = xd; + y = yd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(x, 8, xm); + + err = sp_256_mod_mul_norm_8(x, x, p256_mod); + } + + if (err == MP_OKAY) { + /* y = x^3 */ + { + sp_256_mont_sqr_8(y, x, p256_mod, p256_mp_mod); + sp_256_mont_mul_8(y, y, x, p256_mod, p256_mp_mod); + } + /* y = x^3 - 3x */ + sp_256_mont_sub_8(y, y, x, p256_mod); + sp_256_mont_sub_8(y, y, x, p256_mod); + sp_256_mont_sub_8(y, y, x, p256_mod); + /* y = x^3 - 3x + b */ + err = sp_256_mod_mul_norm_8(x, p256_b, p256_mod); + } + if (err == MP_OKAY) { + sp_256_mont_add_8(y, y, x, p256_mod); + /* y = sqrt(x^3 - 3x + b) */ + err = sp_256_mont_sqrt_8(y); + } + if (err == MP_OKAY) { + XMEMSET(y + 8, 0, 8 * sizeof(sp_digit)); + sp_256_mont_reduce_8(y, p256_mod, p256_mp_mod); + if (((y[0] ^ odd) & 1) != 0) + sp_256_mont_sub_8(y, p256_mod, y, p256_mod); + + err = sp_256_to_mp(y, ym); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_ECC); +#endif + + return err; +} +#endif +#endif /* !WOLFSSL_SP_NO_256 */ +#endif /* WOLFSSL_HAVE_SP_ECC */ +#endif /* WOLFSSL_SP_ARM_CORTEX_M_ASM */ +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH || WOLFSSL_HAVE_SP_ECC */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/sp_int.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/sp_int.c new file mode 100755 index 0000000..d93d920 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/sp_int.c @@ -0,0 +1,754 @@ +/* sp_int.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/* Implementation by Sean Parkinson. */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include +#include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + + +#ifdef WOLFSSL_SP_MATH + +#include + +/* Initialize the big number to be zero. + * + * a SP integer. + * returns MP_OKAY always. + */ +int sp_init(sp_int* a) +{ + a->used = 0; + a->size = SP_INT_DIGITS; + + return MP_OKAY; +} + +#if !defined(WOLFSSL_RSA_PUBLIC_ONLY) || (!defined(NO_DH) || defined(HAVE_ECC)) +/* Initialize up to six big numbers to be zero. + * + * a SP integer. + * b SP integer. + * c SP integer. + * d SP integer. + * e SP integer. + * f SP integer. + * returns MP_OKAY always. + */ +int sp_init_multi(sp_int* a, sp_int* b, sp_int* c, sp_int* d, sp_int* e, + sp_int* f) +{ + if (a != NULL) { + a->used = 0; + a->size = SP_INT_DIGITS; + } + if (b != NULL) { + b->used = 0; + b->size = SP_INT_DIGITS; + } + if (c != NULL) { + c->used = 0; + c->size = SP_INT_DIGITS; + } + if (d != NULL) { + d->used = 0; + d->size = SP_INT_DIGITS; + } + if (e != NULL) { + e->used = 0; + e->size = SP_INT_DIGITS; + } + if (f != NULL) { + f->used = 0; + f->size = SP_INT_DIGITS; + } + + return MP_OKAY; +} +#endif + +/* Clear the data from the big number and set to zero. + * + * a SP integer. + */ +void sp_clear(sp_int* a) +{ + if (a != NULL) { + int i; + + for (i=0; iused; i++) + a->dp[i] = 0; + a->used = 0; + } +} + +/* Calculate the number of 8-bit values required to represent the big number. + * + * a SP integer. + * returns the count. + */ +int sp_unsigned_bin_size(sp_int* a) +{ + int size = sp_count_bits(a); + return (size + 7) / 8; +} + +/* Convert a number as an array of bytes in big-endian format to a big number. + * + * a SP integer. + * in Array of bytes. + * inSz Number of data bytes in array. + * returns MP_OKAY always. + */ +int sp_read_unsigned_bin(sp_int* a, const byte* in, word32 inSz) +{ + int i, j = 0, s = 0; + + a->dp[0] = 0; + for (i = inSz-1; i >= 0; i--) { + a->dp[j] |= ((sp_int_digit)in[i]) << s; + if (s == DIGIT_BIT - 8) { + a->dp[++j] = 0; + s = 0; + } + else if (s > DIGIT_BIT - 8) { + s = DIGIT_BIT - s; + if (j + 1 >= a->size) + break; + a->dp[++j] = in[i] >> s; + s = 8 - s; + } + else + s += 8; + } + + a->used = j + 1; + if (a->dp[j] == 0) + a->used--; + + for (j++; j < a->size; j++) + a->dp[j] = 0; + + return MP_OKAY; +} + +#ifdef HAVE_ECC +/* Convert a number as string in big-endian format to a big number. + * Only supports base-16 (hexadecimal). + * Negative values not supported. + * + * a SP integer. + * in NUL terminated string. + * radix Number of values in a digit. + * returns BAD_FUNC_ARG when radix not supported or value is negative, MP_VAL + * when a character is not valid and MP_OKAY otherwise. + */ +int sp_read_radix(sp_int* a, const char* in, int radix) +{ + int i, j, k; + char ch; + + if (radix != 16) + return BAD_FUNC_ARG; + + if (*in == '-') { + return BAD_FUNC_ARG; + } + + j = 0; + k = 0; + a->dp[0] = 0; + for (i = (int)(XSTRLEN(in) - 1); i >= 0; i--) { + ch = in[i]; + if (ch >= '0' && ch <= '9') + ch -= '0'; + else if (ch >= 'A' && ch <= 'F') + ch -= 'A' - 10; + else if (ch >= 'a' && ch <= 'f') + ch -= 'a' - 10; + else + return MP_VAL; + + a->dp[k] |= ((sp_int_digit)ch) << j; + j += 4; + if (j == DIGIT_BIT && k < SP_INT_DIGITS) + a->dp[++k] = 0; + j &= DIGIT_BIT - 1; + } + + a->used = k + 1; + if (a->dp[k] == 0) + a->used--; + + for (k++; k < a->size; k++) + a->dp[k] = 0; + + return MP_OKAY; +} +#endif + +/* Compare two big numbers. + * + * a SP integer. + * b SP integer. + * returns MP_GT if a is greater than b, MP_LT if a is less than b and MP_EQ + * when a equals b. + */ +int sp_cmp(sp_int* a, sp_int* b) +{ + int i; + + if (a->used > b->used) + return MP_GT; + else if (a->used < b->used) + return MP_LT; + + for (i = a->used - 1; i >= 0; i--) { + if (a->dp[i] > b->dp[i]) + return MP_GT; + else if (a->dp[i] < b->dp[i]) + return MP_LT; + } + return MP_EQ; +} + +/* Count the number of bits in the big number. + * + * a SP integer. + * returns the number of bits. + */ +int sp_count_bits(sp_int* a) +{ + int r = 0; + sp_int_digit d; + + r = a->used - 1; + while (r >= 0 && a->dp[r] == 0) + r--; + if (r < 0) + r = 0; + else { + d = a->dp[r]; + r *= DIGIT_BIT; + while (d != 0) { + r++; + d >>= 1; + } + } + + return r; +} + +/* Determine if the most significant byte of the encoded big number as the top + * bit set. + * + * a SP integer. + * returns 1 when the top bit is set and 0 otherwise. + */ +int sp_leading_bit(sp_int* a) +{ + int bit = 0; + sp_int_digit d; + + if (a->used > 0) { + d = a->dp[a->used - 1]; + while (d > (sp_int_digit)0xff) + d >>= 8; + bit = (int)(d >> 7); + } + + return bit; +} + +#if !defined(NO_DH) || defined(HAVE_ECC) || defined(WC_RSA_BLINDING) || \ + !defined(WOLFSSL_RSA_VERIFY_ONLY) +/* Convert the big number to an array of bytes in big-endian format. + * The array must be large enough for encoded number - use mp_unsigned_bin_size + * to calculate the number of bytes required. + * + * a SP integer. + * out Array to put encoding into. + * returns MP_OKAY always. + */ +int sp_to_unsigned_bin(sp_int* a, byte* out) +{ + int i, j, b; + + j = sp_unsigned_bin_size(a) - 1; + for (i=0; j>=0; i++) { + for (b = 0; b < SP_WORD_SIZE; b += 8) { + out[j--] = a->dp[i] >> b; + if (j < 0) + break; + } + } + + return MP_OKAY; +} +#endif + +/* Convert the big number to an array of bytes in big-endian format. + * The array must be large enough for encoded number - use mp_unsigned_bin_size + * to calculate the number of bytes required. + * Front-pads the output array with zeros make number the size of the array. + * + * a SP integer. + * out Array to put encoding into. + * outSz Size of the array. + * returns MP_OKAY always. + */ +int sp_to_unsigned_bin_len(sp_int* a, byte* out, int outSz) +{ + int i, j, b; + + j = outSz - 1; + for (i=0; j>=0; i++) { + for (b = 0; b < SP_WORD_SIZE; b += 8) { + out[j--] = a->dp[i] >> b; + if (j < 0) + break; + } + } + + return MP_OKAY; +} + +#if !defined(WOLFSSL_RSA_PUBLIC_ONLY) || (!defined(NO_DH) || defined(HAVE_ECC)) +/* Ensure the data in the big number is zeroed. + * + * a SP integer. + */ +void sp_forcezero(sp_int* a) +{ + ForceZero(a->dp, a->used * sizeof(sp_int_digit)); + a->used = 0; +} +#endif + +#if !defined(WOLFSSL_RSA_VERIFY_ONLY) || (!defined(NO_DH) || defined(HAVE_ECC)) +/* Copy value of big number a into b. + * + * a SP integer. + * b SP integer. + * returns MP_OKAY always. + */ +int sp_copy(sp_int* a, sp_int* b) +{ + if (a != b) { + XMEMCPY(b->dp, a->dp, a->used * sizeof(sp_int_digit)); + b->used = a->used; + } + return MP_OKAY; +} +#endif + +/* Set the big number to be the value of the digit. + * + * a SP integer. + * d Digit to be set. + * returns MP_OKAY always. + */ +int sp_set(sp_int* a, sp_int_digit d) +{ + a->dp[0] = d; + a->used = 1; + return MP_OKAY; +} + +#if defined(WC_MP_TO_RADIX) || !defined(NO_DH) || defined(HAVE_ECC) +/* Checks whether the value of the big number is zero. + * + * a SP integer. + * returns 1 when value is zero and 0 otherwise. + */ +int sp_iszero(sp_int* a) +{ + return a->used == 0; +} +#endif + +#if !defined(WOLFSSL_RSA_VERIFY_ONLY) || (!defined(NO_DH) || defined(HAVE_ECC)) +/* Recalculate the number of digits used. + * + * a SP integer. + */ +void sp_clamp(sp_int* a) +{ + int i; + + for (i = a->used - 1; i >= 0 && a->dp[i] == 0; i--) { + } + a->used = i + 1; +} + +/* Grow big number to be able to hold l digits. + * This function does nothing as the number of digits is fixed. + * + * a SP integer. + * l Number of digits. + * returns MP_MEM if the number of digits requested is more than available and + * MP_OKAY otherwise. + */ +int sp_grow(sp_int* a, int l) +{ + if (l > a->size) + return MP_MEM; + (void)a; + (void)l; + return MP_OKAY; +} + +/* Sub a one digit number from the big number. + * + * a SP integer. + * d Digit to subtract. + * r SP integer - result. + * returns MP_OKAY always. + */ +int sp_sub_d(sp_int* a, sp_int_digit d, sp_int* r) +{ + int i = 0; + + r->used = a->used; + r->dp[0] = a->dp[0] - d; + if (r->dp[i] > a->dp[i]) { + for (; i < a->used; i++) { + r->dp[i] = a->dp[i] - 1; + if (r->dp[i] != (sp_int_digit)-1) + break; + } + } + for (; i < a->used; i++) + r->dp[i] = a->dp[i]; + + return MP_OKAY; +} +#endif + +/* Compare a one digit number with a big number. + * + * a SP integer. + * d Digit to compare with. + * returns MP_GT if a is greater than d, MP_LT if a is less than d and MP_EQ + * when a equals d. + */ +int sp_cmp_d(sp_int *a, sp_int_digit d) +{ + /* special case for zero*/ + if (a->used == 0) { + if (d == 0) + return MP_EQ; + else + return MP_LT; + } + else if (a->used > 1) + return MP_GT; + + /* compare the only digit of a to d */ + if (a->dp[0] > d) + return MP_GT; + else if (a->dp[0] < d) + return MP_LT; + return MP_EQ; +} + +#if !defined(NO_DH) || defined(HAVE_ECC) || !defined(WOLFSSL_RSA_VERIFY_ONLY) +/* Left shift the number by number of bits. + * Bits may be larger than the word size. + * + * a SP integer. + * n Number of bits to shift. + * returns MP_OKAY always. + */ +static int sp_lshb(sp_int* a, int n) +{ + int i; + + if (n >= SP_WORD_SIZE) { + sp_lshd(a, n / SP_WORD_SIZE); + n %= SP_WORD_SIZE; + } + + if (n == 0) + return MP_OKAY; + + a->dp[a->used] = 0; + for (i = a->used - 1; i >= 0; i--) { + a->dp[i+1] |= a->dp[i] >> (SP_WORD_SIZE - n); + a->dp[i] = a->dp[i] << n; + } + if (a->dp[a->used] != 0) + a->used++; + + return MP_OKAY; +} + +/* Subtract two large numbers into result: r = a - b + * a must be greater than b. + * + * a SP integer. + * b SP integer. + * r SP integer. + * returns MP_OKAY always. + */ +static int sp_sub(sp_int* a, sp_int* b, sp_int* r) +{ + int i; + sp_int_digit c = 0; + sp_int_digit t; + + for (i = 0; i < a->used && i < b->used; i++) { + t = a->dp[i] - b->dp[i] - c; + if (c == 0) + c = t > a->dp[i]; + else + c = t >= a->dp[i]; + r->dp[i] = t; + } + for (; i < a->used; i++) { + r->dp[i] = a->dp[i] - c; + c = r->dp[i] == (sp_int_digit)-1; + } + r->used = i; + sp_clamp(r); + + return MP_OKAY; +} + +/* Calculate the r = a mod m. + * + * a SP integer. + * m SP integer. + * r SP integer. + * returns MP_OKAY always. + */ +int sp_mod(sp_int* a, sp_int* m, sp_int* r) +{ + sp_int t; + int mBits = sp_count_bits(m); + int rBits; + + if (a != r) + sp_copy(a, r); + sp_init(&t); + + rBits = sp_count_bits(r); + while (rBits > mBits) { + sp_copy(m, &t); + sp_lshb(&t, rBits - mBits); + + if (sp_cmp(&t, r) == MP_GT) { + sp_copy(m, &t); + sp_lshb(&t, rBits - mBits - 1); + } + sp_sub(r, &t, r); + + rBits = sp_count_bits(r); + } + if (sp_cmp(r, m) != MP_LT) + sp_sub(r, m, r); + + return MP_OKAY; +} +#endif + +/* Clear all data in the big number and sets value to zero. + * + * a SP integer. + */ +void sp_zero(sp_int* a) +{ + XMEMSET(a->dp, 0, a->size * sizeof(*a->dp)); + a->used = 0; +} + +/* Add a one digit number to the big number. + * + * a SP integer. + * d Digit to add. + * r SP integer - result. + * returns MP_OKAY always. + */ +int sp_add_d(sp_int* a, sp_int_digit d, sp_int* r) +{ + int i = 0; + + r->used = a->used; + r->dp[0] = a->dp[0] + d; + if (r->dp[i] < a->dp[i]) { + for (; i < a->used; i++) { + r->dp[i] = a->dp[i] + 1; + if (r->dp[i] != 0) + break; + } + + if (i == a->used) { + r->used++; + r->dp[i] = 1; + } + } + for (; i < a->used; i++) + r->dp[i] = a->dp[i]; + + return MP_OKAY; +} + +#if !defined(NO_DH) || defined(HAVE_ECC) || defined(WC_RSA_BLINDING) || \ + !defined(WOLFSSL_RSA_VERIFY_ONLY) +/* Left shift the big number by a number of digits. + * WIll chop off digits overflowing maximum size. + * + * a SP integer. + * s Number of digits to shift. + * returns MP_OKAY always. + */ +int sp_lshd(sp_int* a, int s) +{ + if (a->used + s > a->size) + a->used = a->size - s; + + XMEMMOVE(a->dp + s, a->dp, a->used * sizeof(sp_int_digit)); + a->used += s; + XMEMSET(a->dp, 0, s * sizeof(sp_int_digit)); + + return MP_OKAY; +} +#endif + +#if !defined(WOLFSSL_RSA_VERIFY_ONLY) || (!defined(NO_DH) || defined(HAVE_ECC)) +#ifndef NO_PWDBASED +/* Add two large numbers into result: r = a + b + * + * a SP integer. + * b SP integer. + * r SP integer. + * returns MP_OKAY always. + */ +int sp_add(sp_int* a, sp_int* b, sp_int* r) +{ + int i; + sp_digit c = 0; + sp_digit t; + + for (i = 0; i < a->used && i < b->used; i++) { + t = a->dp[i] + b->dp[i] + c; + if (c == 0) + c = t < a->dp[i]; + else + c = t <= a->dp[i]; + r->dp[i] = t; + } + for (; i < a->used; i++) { + r->dp[i] = a->dp[i] + c; + c = r->dp[i] == 0; + } + for (; i < b->used; i++) { + r->dp[i] = b->dp[i] + c; + c = r->dp[i] == 0; + } + r->dp[i] = c; + r->used = (int)(i + c); + + return MP_OKAY; +} +#endif /* NO_PWDBASED */ +#endif /* !WOLFSSL_RSA_VERIFY_ONLY || (!NO_DH || HAVE_ECC) */ + +#ifndef NO_RSA +/* Set a number into the big number. + * + * a SP integer. + * b Value to set. + * returns MP_OKAY always. + */ +int sp_set_int(sp_int* a, unsigned long b) +{ + a->used = 1; + a->dp[0] = b; + + return MP_OKAY; +} +#endif /* !NO_RSA */ + +#ifdef WC_MP_TO_RADIX +/* Hex string characters. */ +static const char sp_hex_char[16] = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' +}; + +/* Put the hex string version, big-endian, of a in str. + * + * a SP integer. + * str Hex string is stored here. + * returns MP_OKAY always. + */ +int sp_tohex(sp_int* a, char* str) +{ + int i, j; + + /* quick out if its zero */ + if (sp_iszero(a) == MP_YES) { + *str++ = '0'; + *str = '\0'; + return MP_OKAY; + } + + i = a->used - 1; + for (j = SP_WORD_SIZE - 4; j >= 0; j -= 4) { + if (((a->dp[i] >> j) & 0xf) != 0) + break; + } + for (; j >= 0; j -= 4) + *(str++) = sp_hex_char[(a->dp[i] >> j) & 0xf]; + for (--i; i >= 0; i--) { + for (j = SP_WORD_SIZE - 4; j >= 0; j -= 4) + *(str++) = sp_hex_char[(a->dp[i] >> j) & 0xf]; + } + *str = '\0'; + + return MP_OKAY; +} +#endif /* WC_MP_TO_RADIX */ + +#if !defined(USE_FAST_MATH) +/* Returns the run time settings. + * + * returns the settings value. + */ +word32 CheckRunTimeSettings(void) +{ + return CTC_SETTINGS; +} +#endif /* !USE_FAST_MATH */ + +#endif /* WOLFSSL_SP_MATH */ + diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/sp_x86_64.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/sp_x86_64.c new file mode 100755 index 0000000..f7d7165 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/sp_x86_64.c @@ -0,0 +1,21246 @@ +/* sp.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/* Implementation by Sean Parkinson. */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include +#include +#include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) || \ + defined(WOLFSSL_HAVE_SP_ECC) + +#ifdef RSA_LOW_MEM +#ifndef WOLFSSL_SP_SMALL +#define WOLFSSL_SP_SMALL +#endif +#endif + +#include + +#ifdef WOLFSSL_SP_X86_64_ASM +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) +#ifndef WOLFSSL_SP_NO_2048 +/* Read big endian unsigned byte aray into r. + * + * r A single precision integer. + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_2048_from_bin(sp_digit* r, int max, const byte* a, int n) +{ + int i, j = 0, s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= ((sp_digit)a[i]) << s; + if (s >= 56) { + r[j] &= 0xffffffffffffffffl; + s = 64 - s; + if (j + 1 >= max) + break; + r[++j] = a[i] >> s; + s = 8 - s; + } + else + s += 8; + } + + for (j++; j < max; j++) + r[j] = 0; +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * a A multi-precision integer. + */ +static void sp_2048_from_mp(sp_digit* r, int max, mp_int* a) +{ +#if DIGIT_BIT == 64 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < max; j++) + r[j] = 0; +#elif DIGIT_BIT > 64 + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= a->dp[i] << s; + r[j] &= 0xffffffffffffffffl; + s = 64 - s; + if (j + 1 >= max) + break; + r[++j] = a->dp[i] >> s; + while (s + 64 <= DIGIT_BIT) { + s += 64; + r[j] &= 0xffffffffffffffffl; + if (j + 1 >= max) + break; + if (s < DIGIT_BIT) + r[++j] = a->dp[i] >> s; + else + r[++j] = 0; + } + s = DIGIT_BIT - s; + } + + for (j++; j < max; j++) + r[j] = 0; +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 64) { + r[j] &= 0xffffffffffffffffl; + if (j + 1 >= max) + break; + s = 64 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else + s += DIGIT_BIT; + } + + for (j++; j < max; j++) + r[j] = 0; +#endif +} + +/* Write r as big endian to byte aray. + * Fixed length number of bytes written: 256 + * + * r A single precision integer. + * a Byte array. + */ +static void sp_2048_to_bin(sp_digit* r, byte* a) +{ + int i, j, s = 0, b; + + j = 2048 / 8 - 1; + a[j] = 0; + for (i=0; i<32 && j>=0; i++) { + b = 0; + a[j--] |= r[i] << s; b += 8 - s; + if (j < 0) + break; + while (b < 64) { + a[j--] = r[i] >> b; b += 8; + if (j < 0) + break; + } + s = 8 - (b - 64); + if (j >= 0) + a[j] = 0; + if (s != 0) + j++; + } +} + +extern void sp_2048_mul_16(sp_digit* r, const sp_digit* a, const sp_digit* b); +extern void sp_2048_sqr_16(sp_digit* r, const sp_digit* a); +extern void sp_2048_mul_avx2_16(sp_digit* r, const sp_digit* a, const sp_digit* b); +extern void sp_2048_sqr_avx2_16(sp_digit* r, const sp_digit* a); +extern sp_digit sp_2048_add_16(sp_digit* r, const sp_digit* a, const sp_digit* b); +extern sp_digit sp_2048_sub_in_place_32(sp_digit* a, const sp_digit* b); +extern sp_digit sp_2048_add_32(sp_digit* r, const sp_digit* a, const sp_digit* b); +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_2048_mask_16(sp_digit* r, sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<16; i++) + r[i] = a[i] & m; +#else + int i; + + for (i = 0; i < 16; i += 8) { + r[i+0] = a[i+0] & m; + r[i+1] = a[i+1] & m; + r[i+2] = a[i+2] & m; + r[i+3] = a[i+3] & m; + r[i+4] = a[i+4] & m; + r[i+5] = a[i+5] & m; + r[i+6] = a[i+6] & m; + r[i+7] = a[i+7] & m; + } +#endif +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_2048_mul_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[32]; + sp_digit a1[16]; + sp_digit b1[16]; + sp_digit z2[32]; + sp_digit u, ca, cb; + + ca = sp_2048_add_16(a1, a, &a[16]); + cb = sp_2048_add_16(b1, b, &b[16]); + u = ca & cb; + sp_2048_mul_16(z1, a1, b1); + sp_2048_mul_16(z2, &a[16], &b[16]); + sp_2048_mul_16(z0, a, b); + sp_2048_mask_16(r + 32, a1, 0 - cb); + sp_2048_mask_16(b1, b1, 0 - ca); + u += sp_2048_add_16(r + 32, r + 32, b1); + u += sp_2048_sub_in_place_32(z1, z2); + u += sp_2048_sub_in_place_32(z1, z0); + u += sp_2048_add_32(r + 16, r + 16, z1); + r[48] = u; + XMEMSET(r + 48 + 1, 0, sizeof(sp_digit) * (16 - 1)); + sp_2048_add_32(r + 32, r + 32, z2); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_2048_sqr_32(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z2[32]; + sp_digit z1[32]; + sp_digit a1[16]; + sp_digit u; + + u = sp_2048_add_16(a1, a, &a[16]); + sp_2048_sqr_16(z1, a1); + sp_2048_sqr_16(z2, &a[16]); + sp_2048_sqr_16(z0, a); + sp_2048_mask_16(r + 32, a1, 0 - u); + u += sp_2048_add_16(r + 32, r + 32, r + 32); + u += sp_2048_sub_in_place_32(z1, z2); + u += sp_2048_sub_in_place_32(z1, z0); + u += sp_2048_add_32(r + 16, r + 16, z1); + r[48] = u; + XMEMSET(r + 48 + 1, 0, sizeof(sp_digit) * (16 - 1)); + sp_2048_add_32(r + 32, r + 32, z2); +} + +#ifdef HAVE_INTEL_AVX2 +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_2048_mul_avx2_32(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[32]; + sp_digit a1[16]; + sp_digit b1[16]; + sp_digit z2[32]; + sp_digit u, ca, cb; + + ca = sp_2048_add_16(a1, a, &a[16]); + cb = sp_2048_add_16(b1, b, &b[16]); + u = ca & cb; + sp_2048_mul_avx2_16(z1, a1, b1); + sp_2048_mul_avx2_16(z2, &a[16], &b[16]); + sp_2048_mul_avx2_16(z0, a, b); + sp_2048_mask_16(r + 32, a1, 0 - cb); + sp_2048_mask_16(b1, b1, 0 - ca); + u += sp_2048_add_16(r + 32, r + 32, b1); + u += sp_2048_sub_in_place_32(z1, z2); + u += sp_2048_sub_in_place_32(z1, z0); + u += sp_2048_add_32(r + 16, r + 16, z1); + r[48] = u; + XMEMSET(r + 48 + 1, 0, sizeof(sp_digit) * (16 - 1)); + sp_2048_add_32(r + 32, r + 32, z2); +} +#endif /* HAVE_INTEL_AVX2 */ + +#ifdef HAVE_INTEL_AVX2 +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_2048_sqr_avx2_32(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z2[32]; + sp_digit z1[32]; + sp_digit a1[16]; + sp_digit u; + + u = sp_2048_add_16(a1, a, &a[16]); + sp_2048_sqr_avx2_16(z1, a1); + sp_2048_sqr_avx2_16(z2, &a[16]); + sp_2048_sqr_avx2_16(z0, a); + sp_2048_mask_16(r + 32, a1, 0 - u); + u += sp_2048_add_16(r + 32, r + 32, r + 32); + u += sp_2048_sub_in_place_32(z1, z2); + u += sp_2048_sub_in_place_32(z1, z0); + u += sp_2048_add_32(r + 16, r + 16, z1); + r[48] = u; + XMEMSET(r + 48 + 1, 0, sizeof(sp_digit) * (16 - 1)); + sp_2048_add_32(r + 32, r + 32, z2); +} +#endif /* HAVE_INTEL_AVX2 */ + +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +/* Caclulate the bottom digit of -1/a mod 2^n. + * + * a A single precision number. + * rho Bottom word of inverse. + */ +static void sp_2048_mont_setup(sp_digit* a, sp_digit* rho) +{ + sp_digit x, b; + + b = a[0]; + x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ + x *= 2 - b * x; /* here x*a==1 mod 2**8 */ + x *= 2 - b * x; /* here x*a==1 mod 2**16 */ + x *= 2 - b * x; /* here x*a==1 mod 2**32 */ + x *= 2 - b * x; /* here x*a==1 mod 2**64 */ + + /* rho = -1/m mod b */ + *rho = -x; +} + +extern void sp_2048_mul_d_32(sp_digit* r, const sp_digit* a, const sp_digit b); +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +extern sp_digit sp_2048_sub_in_place_16(sp_digit* a, const sp_digit* b); +/* r = 2^n mod m where n is the number of bits to reduce by. + * Given m must be 2048 bits, just need to subtract. + * + * r A single precision number. + * m A signle precision number. + */ +static void sp_2048_mont_norm_16(sp_digit* r, sp_digit* m) +{ + XMEMSET(r, 0, sizeof(sp_digit) * 16); + + /* r = 2^n mod m */ + sp_2048_sub_in_place_16(r, m); +} + +extern sp_digit sp_2048_cond_sub_16(sp_digit* r, sp_digit* a, sp_digit* b, sp_digit m); +extern void sp_2048_mont_reduce_16(sp_digit* a, sp_digit* m, sp_digit mp); +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_2048_mont_mul_16(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_2048_mul_16(r, a, b); + sp_2048_mont_reduce_16(r, m, mp); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_2048_mont_sqr_16(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_2048_sqr_16(r, a); + sp_2048_mont_reduce_16(r, m, mp); +} + +extern void sp_2048_mul_d_16(sp_digit* r, const sp_digit* a, const sp_digit b); +extern void sp_2048_mul_d_avx2_16(sp_digit* r, const sp_digit* a, const sp_digit b); +/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) + * + * d1 The high order half of the number to divide. + * d0 The low order half of the number to divide. + * div The dividend. + * returns the result of the division. + */ +static WC_INLINE sp_digit div_2048_word_16(sp_digit d1, sp_digit d0, + sp_digit div) +{ + register sp_digit r asm("rax"); + __asm__ __volatile__ ( + "divq %3" + : "=a" (r) + : "d" (d1), "a" (d0), "r" (div) + : + ); + return r; +} +extern int64_t sp_2048_cmp_16(sp_digit* a, sp_digit* b); +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_2048_div_16(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[32], t2[17]; + sp_digit div, r1; + int i; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + (void)m; + + div = d[15]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 16); + for (i=15; i>=0; i--) { + r1 = div_2048_word_16(t1[16 + i], t1[16 + i - 1], div); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_2048_mul_d_avx2_16(t2, d, r1); + else +#endif + sp_2048_mul_d_16(t2, d, r1); + t1[16 + i] += sp_2048_sub_in_place_16(&t1[i], t2); + t1[16 + i] -= t2[16]; + sp_2048_mask_16(t2, d, t1[16 + i]); + t1[16 + i] += sp_2048_add_16(&t1[i], &t1[i], t2); + sp_2048_mask_16(t2, d, t1[16 + i]); + t1[16 + i] += sp_2048_add_16(&t1[i], &t1[i], t2); + } + + r1 = sp_2048_cmp_16(t1, d) >= 0; + sp_2048_cond_sub_16(r, t1, d, (sp_digit)0 - r1); + + return MP_OKAY; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_2048_mod_16(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_2048_div_16(a, m, NULL, r); +} + +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_2048_mod_exp_16(sp_digit* r, sp_digit* a, sp_digit* e, + int bits, sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][32]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 32, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<32; i++) + t[i] = td + i * 32; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_16(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 16); + if (reduceA) { + err = sp_2048_mod_16(t[1] + 16, a, m); + if (err == MP_OKAY) + err = sp_2048_mod_16(t[1], t[1], m); + } + else { + XMEMCPY(t[1] + 16, a, sizeof(sp_digit) * 16); + err = sp_2048_mod_16(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_2048_mont_sqr_16(t[ 2], t[ 1], m, mp); + sp_2048_mont_mul_16(t[ 3], t[ 2], t[ 1], m, mp); + sp_2048_mont_sqr_16(t[ 4], t[ 2], m, mp); + sp_2048_mont_mul_16(t[ 5], t[ 3], t[ 2], m, mp); + sp_2048_mont_sqr_16(t[ 6], t[ 3], m, mp); + sp_2048_mont_mul_16(t[ 7], t[ 4], t[ 3], m, mp); + sp_2048_mont_sqr_16(t[ 8], t[ 4], m, mp); + sp_2048_mont_mul_16(t[ 9], t[ 5], t[ 4], m, mp); + sp_2048_mont_sqr_16(t[10], t[ 5], m, mp); + sp_2048_mont_mul_16(t[11], t[ 6], t[ 5], m, mp); + sp_2048_mont_sqr_16(t[12], t[ 6], m, mp); + sp_2048_mont_mul_16(t[13], t[ 7], t[ 6], m, mp); + sp_2048_mont_sqr_16(t[14], t[ 7], m, mp); + sp_2048_mont_mul_16(t[15], t[ 8], t[ 7], m, mp); + sp_2048_mont_sqr_16(t[16], t[ 8], m, mp); + sp_2048_mont_mul_16(t[17], t[ 9], t[ 8], m, mp); + sp_2048_mont_sqr_16(t[18], t[ 9], m, mp); + sp_2048_mont_mul_16(t[19], t[10], t[ 9], m, mp); + sp_2048_mont_sqr_16(t[20], t[10], m, mp); + sp_2048_mont_mul_16(t[21], t[11], t[10], m, mp); + sp_2048_mont_sqr_16(t[22], t[11], m, mp); + sp_2048_mont_mul_16(t[23], t[12], t[11], m, mp); + sp_2048_mont_sqr_16(t[24], t[12], m, mp); + sp_2048_mont_mul_16(t[25], t[13], t[12], m, mp); + sp_2048_mont_sqr_16(t[26], t[13], m, mp); + sp_2048_mont_mul_16(t[27], t[14], t[13], m, mp); + sp_2048_mont_sqr_16(t[28], t[14], m, mp); + sp_2048_mont_mul_16(t[29], t[15], t[14], m, mp); + sp_2048_mont_sqr_16(t[30], t[15], m, mp); + sp_2048_mont_mul_16(t[31], t[16], t[15], m, mp); + + i = (bits - 1) / 64; + n = e[i--]; + y = n >> 59; + n <<= 5; + c = 59; + XMEMCPY(r, t[y], sizeof(sp_digit) * 16); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 59; + n <<= 5; + c = 59; + } + else if (c < 5) { + y = n >> 59; + n = e[i--]; + c = 5 - c; + y |= n >> (64 - c); + n <<= c; + c = 64 - c; + } + else { + y = (n >> 59) & 0x1f; + n <<= 5; + c -= 5; + } + + sp_2048_mont_sqr_16(r, r, m, mp); + sp_2048_mont_sqr_16(r, r, m, mp); + sp_2048_mont_sqr_16(r, r, m, mp); + sp_2048_mont_sqr_16(r, r, m, mp); + sp_2048_mont_sqr_16(r, r, m, mp); + + sp_2048_mont_mul_16(r, r, t[y], m, mp); + } + y = e[0] & ((1 << c) - 1); + for (; c > 0; c--) + sp_2048_mont_sqr_16(r, r, m, mp); + sp_2048_mont_mul_16(r, r, t[y], m, mp); + + XMEMSET(&r[16], 0, sizeof(sp_digit) * 16); + sp_2048_mont_reduce_16(r, m, mp); + + mask = 0 - (sp_2048_cmp_16(r, m) >= 0); + sp_2048_cond_sub_16(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} + +extern void sp_2048_mont_reduce_avx2_16(sp_digit* a, sp_digit* m, sp_digit mp); +#ifdef HAVE_INTEL_AVX2 +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_2048_mont_mul_avx2_16(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_2048_mul_avx2_16(r, a, b); + sp_2048_mont_reduce_avx2_16(r, m, mp); +} + +#endif /* HAVE_INTEL_AVX2 */ +#ifdef HAVE_INTEL_AVX2 +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_2048_mont_sqr_avx2_16(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_2048_sqr_avx2_16(r, a); + sp_2048_mont_reduce_avx2_16(r, m, mp); +} + +#endif /* HAVE_INTEL_AVX2 */ +#ifdef HAVE_INTEL_AVX2 +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_2048_mod_exp_avx2_16(sp_digit* r, sp_digit* a, sp_digit* e, + int bits, sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][32]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 32, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<32; i++) + t[i] = td + i * 32; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_16(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 16); + if (reduceA) { + err = sp_2048_mod_16(t[1] + 16, a, m); + if (err == MP_OKAY) + err = sp_2048_mod_16(t[1], t[1], m); + } + else { + XMEMCPY(t[1] + 16, a, sizeof(sp_digit) * 16); + err = sp_2048_mod_16(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_2048_mont_sqr_avx2_16(t[ 2], t[ 1], m, mp); + sp_2048_mont_mul_avx2_16(t[ 3], t[ 2], t[ 1], m, mp); + sp_2048_mont_sqr_avx2_16(t[ 4], t[ 2], m, mp); + sp_2048_mont_mul_avx2_16(t[ 5], t[ 3], t[ 2], m, mp); + sp_2048_mont_sqr_avx2_16(t[ 6], t[ 3], m, mp); + sp_2048_mont_mul_avx2_16(t[ 7], t[ 4], t[ 3], m, mp); + sp_2048_mont_sqr_avx2_16(t[ 8], t[ 4], m, mp); + sp_2048_mont_mul_avx2_16(t[ 9], t[ 5], t[ 4], m, mp); + sp_2048_mont_sqr_avx2_16(t[10], t[ 5], m, mp); + sp_2048_mont_mul_avx2_16(t[11], t[ 6], t[ 5], m, mp); + sp_2048_mont_sqr_avx2_16(t[12], t[ 6], m, mp); + sp_2048_mont_mul_avx2_16(t[13], t[ 7], t[ 6], m, mp); + sp_2048_mont_sqr_avx2_16(t[14], t[ 7], m, mp); + sp_2048_mont_mul_avx2_16(t[15], t[ 8], t[ 7], m, mp); + sp_2048_mont_sqr_avx2_16(t[16], t[ 8], m, mp); + sp_2048_mont_mul_avx2_16(t[17], t[ 9], t[ 8], m, mp); + sp_2048_mont_sqr_avx2_16(t[18], t[ 9], m, mp); + sp_2048_mont_mul_avx2_16(t[19], t[10], t[ 9], m, mp); + sp_2048_mont_sqr_avx2_16(t[20], t[10], m, mp); + sp_2048_mont_mul_avx2_16(t[21], t[11], t[10], m, mp); + sp_2048_mont_sqr_avx2_16(t[22], t[11], m, mp); + sp_2048_mont_mul_avx2_16(t[23], t[12], t[11], m, mp); + sp_2048_mont_sqr_avx2_16(t[24], t[12], m, mp); + sp_2048_mont_mul_avx2_16(t[25], t[13], t[12], m, mp); + sp_2048_mont_sqr_avx2_16(t[26], t[13], m, mp); + sp_2048_mont_mul_avx2_16(t[27], t[14], t[13], m, mp); + sp_2048_mont_sqr_avx2_16(t[28], t[14], m, mp); + sp_2048_mont_mul_avx2_16(t[29], t[15], t[14], m, mp); + sp_2048_mont_sqr_avx2_16(t[30], t[15], m, mp); + sp_2048_mont_mul_avx2_16(t[31], t[16], t[15], m, mp); + + i = (bits - 1) / 64; + n = e[i--]; + y = n >> 59; + n <<= 5; + c = 59; + XMEMCPY(r, t[y], sizeof(sp_digit) * 16); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 59; + n <<= 5; + c = 59; + } + else if (c < 5) { + y = n >> 59; + n = e[i--]; + c = 5 - c; + y |= n >> (64 - c); + n <<= c; + c = 64 - c; + } + else { + y = (n >> 59) & 0x1f; + n <<= 5; + c -= 5; + } + + sp_2048_mont_sqr_avx2_16(r, r, m, mp); + sp_2048_mont_sqr_avx2_16(r, r, m, mp); + sp_2048_mont_sqr_avx2_16(r, r, m, mp); + sp_2048_mont_sqr_avx2_16(r, r, m, mp); + sp_2048_mont_sqr_avx2_16(r, r, m, mp); + + sp_2048_mont_mul_avx2_16(r, r, t[y], m, mp); + } + y = e[0] & ((1 << c) - 1); + for (; c > 0; c--) + sp_2048_mont_sqr_avx2_16(r, r, m, mp); + sp_2048_mont_mul_avx2_16(r, r, t[y], m, mp); + + XMEMSET(&r[16], 0, sizeof(sp_digit) * 16); + sp_2048_mont_reduce_avx2_16(r, m, mp); + + mask = 0 - (sp_2048_cmp_16(r, m) >= 0); + sp_2048_cond_sub_16(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#endif /* HAVE_INTEL_AVX2 */ + +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) +/* r = 2^n mod m where n is the number of bits to reduce by. + * Given m must be 2048 bits, just need to subtract. + * + * r A single precision number. + * m A signle precision number. + */ +static void sp_2048_mont_norm_32(sp_digit* r, sp_digit* m) +{ + XMEMSET(r, 0, sizeof(sp_digit) * 32); + + /* r = 2^n mod m */ + sp_2048_sub_in_place_32(r, m); +} + +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +extern sp_digit sp_2048_cond_sub_32(sp_digit* r, sp_digit* a, sp_digit* b, sp_digit m); +extern void sp_2048_mont_reduce_32(sp_digit* a, sp_digit* m, sp_digit mp); +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_2048_mont_mul_32(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_2048_mul_32(r, a, b); + sp_2048_mont_reduce_32(r, m, mp); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_2048_mont_sqr_32(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_2048_sqr_32(r, a); + sp_2048_mont_reduce_32(r, m, mp); +} + +#ifndef WOLFSSL_RSA_PUBLIC_ONLY +extern void sp_2048_mul_d_avx2_32(sp_digit* r, const sp_digit* a, const sp_digit b); +/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) + * + * d1 The high order half of the number to divide. + * d0 The low order half of the number to divide. + * div The dividend. + * returns the result of the division. + */ +static WC_INLINE sp_digit div_2048_word_32(sp_digit d1, sp_digit d0, + sp_digit div) +{ + register sp_digit r asm("rax"); + __asm__ __volatile__ ( + "divq %3" + : "=a" (r) + : "d" (d1), "a" (d0), "r" (div) + : + ); + return r; +} +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_2048_mask_32(sp_digit* r, sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<32; i++) + r[i] = a[i] & m; +#else + int i; + + for (i = 0; i < 32; i += 8) { + r[i+0] = a[i+0] & m; + r[i+1] = a[i+1] & m; + r[i+2] = a[i+2] & m; + r[i+3] = a[i+3] & m; + r[i+4] = a[i+4] & m; + r[i+5] = a[i+5] & m; + r[i+6] = a[i+6] & m; + r[i+7] = a[i+7] & m; + } +#endif +} + +extern int64_t sp_2048_cmp_32(sp_digit* a, sp_digit* b); +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_2048_div_32(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[64], t2[33]; + sp_digit div, r1; + int i; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + (void)m; + + div = d[31]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 32); + for (i=31; i>=0; i--) { + r1 = div_2048_word_32(t1[32 + i], t1[32 + i - 1], div); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_2048_mul_d_avx2_32(t2, d, r1); + else +#endif + sp_2048_mul_d_32(t2, d, r1); + t1[32 + i] += sp_2048_sub_in_place_32(&t1[i], t2); + t1[32 + i] -= t2[32]; + sp_2048_mask_32(t2, d, t1[32 + i]); + t1[32 + i] += sp_2048_add_32(&t1[i], &t1[i], t2); + sp_2048_mask_32(t2, d, t1[32 + i]); + t1[32 + i] += sp_2048_add_32(&t1[i], &t1[i], t2); + } + + r1 = sp_2048_cmp_32(t1, d) >= 0; + sp_2048_cond_sub_32(r, t1, d, (sp_digit)0 - r1); + + return MP_OKAY; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_2048_mod_32(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_2048_div_32(a, m, NULL, r); +} + +#endif /* WOLFSSL_RSA_PUBLIC_ONLY */ +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_2048_div_32_cond(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[64], t2[33]; + sp_digit div, r1; + int i; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + (void)m; + + div = d[31]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 32); + for (i=31; i>=0; i--) { + r1 = div_2048_word_32(t1[32 + i], t1[32 + i - 1], div); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_2048_mul_d_avx2_32(t2, d, r1); + else +#endif + sp_2048_mul_d_32(t2, d, r1); + t1[32 + i] += sp_2048_sub_in_place_32(&t1[i], t2); + t1[32 + i] -= t2[32]; + if (t1[32 + i] != 0) { + t1[32 + i] += sp_2048_add_32(&t1[i], &t1[i], d); + if (t1[32 + i] != 0) + t1[32 + i] += sp_2048_add_32(&t1[i], &t1[i], d); + } + } + + r1 = sp_2048_cmp_32(t1, d) >= 0; + sp_2048_cond_sub_32(r, t1, d, (sp_digit)0 - r1); + + return MP_OKAY; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_2048_mod_32_cond(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_2048_div_32_cond(a, m, NULL, r); +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH) +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_2048_mod_exp_32(sp_digit* r, sp_digit* a, sp_digit* e, + int bits, sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][64]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 64, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<32; i++) + t[i] = td + i * 64; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_32(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 32); + if (reduceA) { + err = sp_2048_mod_32(t[1] + 32, a, m); + if (err == MP_OKAY) + err = sp_2048_mod_32(t[1], t[1], m); + } + else { + XMEMCPY(t[1] + 32, a, sizeof(sp_digit) * 32); + err = sp_2048_mod_32(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_2048_mont_sqr_32(t[ 2], t[ 1], m, mp); + sp_2048_mont_mul_32(t[ 3], t[ 2], t[ 1], m, mp); + sp_2048_mont_sqr_32(t[ 4], t[ 2], m, mp); + sp_2048_mont_mul_32(t[ 5], t[ 3], t[ 2], m, mp); + sp_2048_mont_sqr_32(t[ 6], t[ 3], m, mp); + sp_2048_mont_mul_32(t[ 7], t[ 4], t[ 3], m, mp); + sp_2048_mont_sqr_32(t[ 8], t[ 4], m, mp); + sp_2048_mont_mul_32(t[ 9], t[ 5], t[ 4], m, mp); + sp_2048_mont_sqr_32(t[10], t[ 5], m, mp); + sp_2048_mont_mul_32(t[11], t[ 6], t[ 5], m, mp); + sp_2048_mont_sqr_32(t[12], t[ 6], m, mp); + sp_2048_mont_mul_32(t[13], t[ 7], t[ 6], m, mp); + sp_2048_mont_sqr_32(t[14], t[ 7], m, mp); + sp_2048_mont_mul_32(t[15], t[ 8], t[ 7], m, mp); + sp_2048_mont_sqr_32(t[16], t[ 8], m, mp); + sp_2048_mont_mul_32(t[17], t[ 9], t[ 8], m, mp); + sp_2048_mont_sqr_32(t[18], t[ 9], m, mp); + sp_2048_mont_mul_32(t[19], t[10], t[ 9], m, mp); + sp_2048_mont_sqr_32(t[20], t[10], m, mp); + sp_2048_mont_mul_32(t[21], t[11], t[10], m, mp); + sp_2048_mont_sqr_32(t[22], t[11], m, mp); + sp_2048_mont_mul_32(t[23], t[12], t[11], m, mp); + sp_2048_mont_sqr_32(t[24], t[12], m, mp); + sp_2048_mont_mul_32(t[25], t[13], t[12], m, mp); + sp_2048_mont_sqr_32(t[26], t[13], m, mp); + sp_2048_mont_mul_32(t[27], t[14], t[13], m, mp); + sp_2048_mont_sqr_32(t[28], t[14], m, mp); + sp_2048_mont_mul_32(t[29], t[15], t[14], m, mp); + sp_2048_mont_sqr_32(t[30], t[15], m, mp); + sp_2048_mont_mul_32(t[31], t[16], t[15], m, mp); + + i = (bits - 1) / 64; + n = e[i--]; + y = n >> 59; + n <<= 5; + c = 59; + XMEMCPY(r, t[y], sizeof(sp_digit) * 32); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 59; + n <<= 5; + c = 59; + } + else if (c < 5) { + y = n >> 59; + n = e[i--]; + c = 5 - c; + y |= n >> (64 - c); + n <<= c; + c = 64 - c; + } + else { + y = (n >> 59) & 0x1f; + n <<= 5; + c -= 5; + } + + sp_2048_mont_sqr_32(r, r, m, mp); + sp_2048_mont_sqr_32(r, r, m, mp); + sp_2048_mont_sqr_32(r, r, m, mp); + sp_2048_mont_sqr_32(r, r, m, mp); + sp_2048_mont_sqr_32(r, r, m, mp); + + sp_2048_mont_mul_32(r, r, t[y], m, mp); + } + y = e[0] & ((1 << c) - 1); + for (; c > 0; c--) + sp_2048_mont_sqr_32(r, r, m, mp); + sp_2048_mont_mul_32(r, r, t[y], m, mp); + + XMEMSET(&r[32], 0, sizeof(sp_digit) * 32); + sp_2048_mont_reduce_32(r, m, mp); + + mask = 0 - (sp_2048_cmp_32(r, m) >= 0); + sp_2048_cond_sub_32(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ + +extern void sp_2048_mont_reduce_avx2_32(sp_digit* a, sp_digit* m, sp_digit mp); +#ifdef HAVE_INTEL_AVX2 +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_2048_mont_mul_avx2_32(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_2048_mul_avx2_32(r, a, b); + sp_2048_mont_reduce_avx2_32(r, m, mp); +} + +#endif /* HAVE_INTEL_AVX2 */ +#ifdef HAVE_INTEL_AVX2 +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_2048_mont_sqr_avx2_32(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_2048_sqr_avx2_32(r, a); + sp_2048_mont_reduce_avx2_32(r, m, mp); +} + +#endif /* HAVE_INTEL_AVX2 */ +#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH) +#ifdef HAVE_INTEL_AVX2 +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_2048_mod_exp_avx2_32(sp_digit* r, sp_digit* a, sp_digit* e, + int bits, sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][64]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 64, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<32; i++) + t[i] = td + i * 64; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_2048_mont_setup(m, &mp); + sp_2048_mont_norm_32(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 32); + if (reduceA) { + err = sp_2048_mod_32(t[1] + 32, a, m); + if (err == MP_OKAY) + err = sp_2048_mod_32(t[1], t[1], m); + } + else { + XMEMCPY(t[1] + 32, a, sizeof(sp_digit) * 32); + err = sp_2048_mod_32(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_2048_mont_sqr_avx2_32(t[ 2], t[ 1], m, mp); + sp_2048_mont_mul_avx2_32(t[ 3], t[ 2], t[ 1], m, mp); + sp_2048_mont_sqr_avx2_32(t[ 4], t[ 2], m, mp); + sp_2048_mont_mul_avx2_32(t[ 5], t[ 3], t[ 2], m, mp); + sp_2048_mont_sqr_avx2_32(t[ 6], t[ 3], m, mp); + sp_2048_mont_mul_avx2_32(t[ 7], t[ 4], t[ 3], m, mp); + sp_2048_mont_sqr_avx2_32(t[ 8], t[ 4], m, mp); + sp_2048_mont_mul_avx2_32(t[ 9], t[ 5], t[ 4], m, mp); + sp_2048_mont_sqr_avx2_32(t[10], t[ 5], m, mp); + sp_2048_mont_mul_avx2_32(t[11], t[ 6], t[ 5], m, mp); + sp_2048_mont_sqr_avx2_32(t[12], t[ 6], m, mp); + sp_2048_mont_mul_avx2_32(t[13], t[ 7], t[ 6], m, mp); + sp_2048_mont_sqr_avx2_32(t[14], t[ 7], m, mp); + sp_2048_mont_mul_avx2_32(t[15], t[ 8], t[ 7], m, mp); + sp_2048_mont_sqr_avx2_32(t[16], t[ 8], m, mp); + sp_2048_mont_mul_avx2_32(t[17], t[ 9], t[ 8], m, mp); + sp_2048_mont_sqr_avx2_32(t[18], t[ 9], m, mp); + sp_2048_mont_mul_avx2_32(t[19], t[10], t[ 9], m, mp); + sp_2048_mont_sqr_avx2_32(t[20], t[10], m, mp); + sp_2048_mont_mul_avx2_32(t[21], t[11], t[10], m, mp); + sp_2048_mont_sqr_avx2_32(t[22], t[11], m, mp); + sp_2048_mont_mul_avx2_32(t[23], t[12], t[11], m, mp); + sp_2048_mont_sqr_avx2_32(t[24], t[12], m, mp); + sp_2048_mont_mul_avx2_32(t[25], t[13], t[12], m, mp); + sp_2048_mont_sqr_avx2_32(t[26], t[13], m, mp); + sp_2048_mont_mul_avx2_32(t[27], t[14], t[13], m, mp); + sp_2048_mont_sqr_avx2_32(t[28], t[14], m, mp); + sp_2048_mont_mul_avx2_32(t[29], t[15], t[14], m, mp); + sp_2048_mont_sqr_avx2_32(t[30], t[15], m, mp); + sp_2048_mont_mul_avx2_32(t[31], t[16], t[15], m, mp); + + i = (bits - 1) / 64; + n = e[i--]; + y = n >> 59; + n <<= 5; + c = 59; + XMEMCPY(r, t[y], sizeof(sp_digit) * 32); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 59; + n <<= 5; + c = 59; + } + else if (c < 5) { + y = n >> 59; + n = e[i--]; + c = 5 - c; + y |= n >> (64 - c); + n <<= c; + c = 64 - c; + } + else { + y = (n >> 59) & 0x1f; + n <<= 5; + c -= 5; + } + + sp_2048_mont_sqr_avx2_32(r, r, m, mp); + sp_2048_mont_sqr_avx2_32(r, r, m, mp); + sp_2048_mont_sqr_avx2_32(r, r, m, mp); + sp_2048_mont_sqr_avx2_32(r, r, m, mp); + sp_2048_mont_sqr_avx2_32(r, r, m, mp); + + sp_2048_mont_mul_avx2_32(r, r, t[y], m, mp); + } + y = e[0] & ((1 << c) - 1); + for (; c > 0; c--) + sp_2048_mont_sqr_avx2_32(r, r, m, mp); + sp_2048_mont_mul_avx2_32(r, r, t[y], m, mp); + + XMEMSET(&r[32], 0, sizeof(sp_digit) * 32); + sp_2048_mont_reduce_avx2_32(r, m, mp); + + mask = 0 - (sp_2048_cmp_32(r, m) >= 0); + sp_2048_cond_sub_32(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#endif /* HAVE_INTEL_AVX2 */ +#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ + +#ifdef WOLFSSL_HAVE_SP_RSA +/* RSA public key operation. + * + * in Array of bytes representing the number to exponentiate, base. + * inLen Number of bytes in base. + * em Public exponent. + * mm Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 256 bytes long. + * outLen Number of bytes in result. + * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when + * an array is too long and MEMORY_E when dynamic memory allocation fails. + */ +int sp_RsaPublic_2048(const byte* in, word32 inLen, mp_int* em, mp_int* mm, + byte* out, word32* outLen) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit ad[64], md[32], rd[64]; +#else + sp_digit* d = NULL; +#endif + sp_digit* a; + sp_digit *ah; + sp_digit* m; + sp_digit* r; + sp_digit e[1]; + int err = MP_OKAY; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + if (*outLen < 256) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(em) > 64 || inLen > 256 || + mp_count_bits(mm) != 2048)) + err = MP_READ_E; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 5, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + a = d; + r = a + 32 * 2; + m = r + 32 * 2; + ah = a + 32; + } +#else + a = ad; + m = md; + r = rd; + ah = a + 32; +#endif + + if (err == MP_OKAY) { + sp_2048_from_bin(ah, 32, in, inLen); +#if DIGIT_BIT >= 64 + e[0] = em->dp[0]; +#else + e[0] = em->dp[0]; + if (em->used > 1) + e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT; +#endif + if (e[0] == 0) + err = MP_EXPTMOD_E; + } + if (err == MP_OKAY) { + sp_2048_from_mp(m, 32, mm); + + if (e[0] == 0x3) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + if (err == MP_OKAY) { + sp_2048_sqr_avx2_32(r, ah); + err = sp_2048_mod_32_cond(r, r, m); + } + if (err == MP_OKAY) { + sp_2048_mul_avx2_32(r, ah, r); + err = sp_2048_mod_32_cond(r, r, m); + } + } + else +#endif + { + if (err == MP_OKAY) { + sp_2048_sqr_32(r, ah); + err = sp_2048_mod_32_cond(r, r, m); + } + if (err == MP_OKAY) { + sp_2048_mul_32(r, ah, r); + err = sp_2048_mod_32_cond(r, r, m); + } + } + } + else { + int i; + sp_digit mp; + + sp_2048_mont_setup(m, &mp); + + /* Convert to Montgomery form. */ + XMEMSET(a, 0, sizeof(sp_digit) * 32); + err = sp_2048_mod_32_cond(a, a, m); + + if (err == MP_OKAY) { + for (i=63; i>=0; i--) + if (e[0] >> i) + break; + + XMEMCPY(r, a, sizeof(sp_digit) * 32); +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + for (i--; i>=0; i--) { + sp_2048_mont_sqr_avx2_32(r, r, m, mp); + if (((e[0] >> i) & 1) == 1) + sp_2048_mont_mul_avx2_32(r, r, a, m, mp); + } + XMEMSET(&r[32], 0, sizeof(sp_digit) * 32); + sp_2048_mont_reduce_avx2_32(r, m, mp); + } + else +#endif + { + for (i--; i>=0; i--) { + sp_2048_mont_sqr_32(r, r, m, mp); + if (((e[0] >> i) & 1) == 1) + sp_2048_mont_mul_32(r, r, a, m, mp); + } + XMEMSET(&r[32], 0, sizeof(sp_digit) * 32); + sp_2048_mont_reduce_32(r, m, mp); + } + + for (i = 31; i > 0; i--) { + if (r[i] != m[i]) + break; + } + if (r[i] >= m[i]) + sp_2048_sub_in_place_32(r, m); + } + } + } + + if (err == MP_OKAY) { + sp_2048_to_bin(r, out); + *outLen = 256; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_RSA); +#endif + + return err; +} + +/* RSA private key operation. + * + * in Array of bytes representing the number to exponentiate, base. + * inLen Number of bytes in base. + * dm Private exponent. + * pm First prime. + * qm Second prime. + * dpm First prime's CRT exponent. + * dqm Second prime's CRT exponent. + * qim Inverse of second prime mod p. + * mm Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 256 bytes long. + * outLen Number of bytes in result. + * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when + * an array is too long and MEMORY_E when dynamic memory allocation fails. + */ +int sp_RsaPrivate_2048(const byte* in, word32 inLen, mp_int* dm, + mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm, + byte* out, word32* outLen) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit ad[32 * 2]; + sp_digit pd[16], qd[16], dpd[16]; + sp_digit tmpad[32], tmpbd[32]; +#else + sp_digit* t = NULL; +#endif + sp_digit* a; + sp_digit* p; + sp_digit* q; + sp_digit* dp; + sp_digit* dq; + sp_digit* qi; + sp_digit* tmp; + sp_digit* tmpa; + sp_digit* tmpb; + sp_digit* r; + sp_digit c; + int err = MP_OKAY; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + (void)dm; + (void)mm; + + if (*outLen < 256) + err = MP_TO_E; + if (err == MP_OKAY && (inLen > 256 || mp_count_bits(mm) != 2048)) + err = MP_READ_E; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 11, NULL, + DYNAMIC_TYPE_RSA); + if (t == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + a = t; + p = a + 32 * 2; + q = p + 16; + qi = dq = dp = q + 16; + tmpa = qi + 16; + tmpb = tmpa + 32; + + tmp = t; + r = tmp + 32; + } +#else + r = a = ad; + p = pd; + q = qd; + qi = dq = dp = dpd; + tmpa = tmpad; + tmpb = tmpbd; + tmp = a + 32; +#endif + + if (err == MP_OKAY) { + sp_2048_from_bin(a, 32, in, inLen); + sp_2048_from_mp(p, 16, pm); + sp_2048_from_mp(q, 16, qm); + sp_2048_from_mp(dp, 16, dpm); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_2048_mod_exp_avx2_16(tmpa, a, dp, 1024, p, 1); + else +#endif + err = sp_2048_mod_exp_16(tmpa, a, dp, 1024, p, 1); + } + if (err == MP_OKAY) { + sp_2048_from_mp(dq, 16, dqm); +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_2048_mod_exp_avx2_16(tmpb, a, dq, 1024, q, 1); + else +#endif + err = sp_2048_mod_exp_16(tmpb, a, dq, 1024, q, 1); + } + + if (err == MP_OKAY) { + c = sp_2048_sub_in_place_16(tmpa, tmpb); + sp_2048_mask_16(tmp, p, c); + sp_2048_add_16(tmpa, tmpa, tmp); + + sp_2048_from_mp(qi, 16, qim); +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_2048_mul_avx2_16(tmpa, tmpa, qi); + else +#endif + sp_2048_mul_16(tmpa, tmpa, qi); + err = sp_2048_mod_16(tmpa, tmpa, p); + } + + if (err == MP_OKAY) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_2048_mul_avx2_16(tmpa, q, tmpa); + else +#endif + sp_2048_mul_16(tmpa, q, tmpa); + XMEMSET(&tmpb[16], 0, sizeof(sp_digit) * 16); + sp_2048_add_32(r, tmpb, tmpa); + + sp_2048_to_bin(r, out); + *outLen = 256; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_digit) * 16 * 11); + XFREE(t, NULL, DYNAMIC_TYPE_RSA); + } +#else + XMEMSET(tmpad, 0, sizeof(tmpad)); + XMEMSET(tmpbd, 0, sizeof(tmpbd)); + XMEMSET(pd, 0, sizeof(pd)); + XMEMSET(qd, 0, sizeof(qd)); + XMEMSET(dpd, 0, sizeof(dpd)); +#endif + + return err; +} +#endif /* WOLFSSL_HAVE_SP_RSA */ +#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \ + !defined(WOLFSSL_RSA_PUBLIC_ONLY)) +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_2048_to_mp(sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (2048 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { +#if DIGIT_BIT == 64 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 32); + r->used = 32; + mp_clamp(r); +#elif DIGIT_BIT < 64 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 32; i++) { + r->dp[j] |= a[i] << s; + r->dp[j] &= (1l << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + while (s + DIGIT_BIT <= 64) { + s += DIGIT_BIT; + r->dp[j] &= (1l << DIGIT_BIT) - 1; + r->dp[++j] = a[i] >> s; + } + s = 64 - s; + } + r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 32; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 64 >= DIGIT_BIT) { + #if DIGIT_BIT < 64 + r->dp[j] &= (1l << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 64 - s; + } + else + s += 64; + } + r->used = (2048 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returs 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ + int err = MP_OKAY; + sp_digit b[64], e[32], m[32]; + sp_digit* r = b; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 2048 || expBits > 2048 || + mp_count_bits(mod) != 2048) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + sp_2048_from_mp(b, 32, base); + sp_2048_from_mp(e, 32, exp); + sp_2048_from_mp(m, 32, mod); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_2048_mod_exp_avx2_32(r, b, e, expBits, m, 0); + else +#endif + err = sp_2048_mod_exp_32(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + err = sp_2048_to_mp(r, res); + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. + * exp Array of bytes that is the exponent. + * expLen Length of data, in bytes, in exponent. + * mod Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 256 bytes long. + * outLen Length, in bytes, of exponentiation result. + * returs 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen, + mp_int* mod, byte* out, word32* outLen) +{ + int err = MP_OKAY; + sp_digit b[64], e[32], m[32]; + sp_digit* r = b; + word32 i; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + if (mp_count_bits(base) > 2048 || expLen > 256 || + mp_count_bits(mod) != 2048) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + sp_2048_from_mp(b, 32, base); + sp_2048_from_bin(e, 32, exp, expLen); + sp_2048_from_mp(m, 32, mod); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_2048_mod_exp_avx2_32(r, b, e, expLen * 8, m, 0); + else +#endif + err = sp_2048_mod_exp_32(r, b, e, expLen * 8, m, 0); + } + + if (err == MP_OKAY) { + sp_2048_to_bin(r, out); + *outLen = 256; + for (i=0; i<256 && out[i] == 0; i++) { + } + *outLen -= i; + XMEMMOVE(out, out + i, *outLen); + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returs 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ + int err = MP_OKAY; + sp_digit b[32], e[16], m[16]; + sp_digit* r = b; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 1024 || expBits > 1024 || + mp_count_bits(mod) != 1024) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + sp_2048_from_mp(b, 16, base); + sp_2048_from_mp(e, 16, exp); + sp_2048_from_mp(m, 16, mod); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_2048_mod_exp_avx2_16(r, b, e, expBits, m, 0); + else +#endif + err = sp_2048_mod_exp_16(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + XMEMSET(r + 16, 0, sizeof(*r) * 16); + err = sp_2048_to_mp(r, res); + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} + +#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ + +#endif /* !WOLFSSL_SP_NO_2048 */ + +#ifndef WOLFSSL_SP_NO_3072 +/* Read big endian unsigned byte aray into r. + * + * r A single precision integer. + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_3072_from_bin(sp_digit* r, int max, const byte* a, int n) +{ + int i, j = 0, s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= ((sp_digit)a[i]) << s; + if (s >= 56) { + r[j] &= 0xffffffffffffffffl; + s = 64 - s; + if (j + 1 >= max) + break; + r[++j] = a[i] >> s; + s = 8 - s; + } + else + s += 8; + } + + for (j++; j < max; j++) + r[j] = 0; +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * a A multi-precision integer. + */ +static void sp_3072_from_mp(sp_digit* r, int max, mp_int* a) +{ +#if DIGIT_BIT == 64 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < max; j++) + r[j] = 0; +#elif DIGIT_BIT > 64 + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= a->dp[i] << s; + r[j] &= 0xffffffffffffffffl; + s = 64 - s; + if (j + 1 >= max) + break; + r[++j] = a->dp[i] >> s; + while (s + 64 <= DIGIT_BIT) { + s += 64; + r[j] &= 0xffffffffffffffffl; + if (j + 1 >= max) + break; + if (s < DIGIT_BIT) + r[++j] = a->dp[i] >> s; + else + r[++j] = 0; + } + s = DIGIT_BIT - s; + } + + for (j++; j < max; j++) + r[j] = 0; +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 64) { + r[j] &= 0xffffffffffffffffl; + if (j + 1 >= max) + break; + s = 64 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else + s += DIGIT_BIT; + } + + for (j++; j < max; j++) + r[j] = 0; +#endif +} + +/* Write r as big endian to byte aray. + * Fixed length number of bytes written: 384 + * + * r A single precision integer. + * a Byte array. + */ +static void sp_3072_to_bin(sp_digit* r, byte* a) +{ + int i, j, s = 0, b; + + j = 3072 / 8 - 1; + a[j] = 0; + for (i=0; i<48 && j>=0; i++) { + b = 0; + a[j--] |= r[i] << s; b += 8 - s; + if (j < 0) + break; + while (b < 64) { + a[j--] = r[i] >> b; b += 8; + if (j < 0) + break; + } + s = 8 - (b - 64); + if (j >= 0) + a[j] = 0; + if (s != 0) + j++; + } +} + +extern void sp_3072_mul_24(sp_digit* r, const sp_digit* a, const sp_digit* b); +extern void sp_3072_sqr_24(sp_digit* r, const sp_digit* a); +extern void sp_3072_mul_avx2_24(sp_digit* r, const sp_digit* a, const sp_digit* b); +extern void sp_3072_sqr_avx2_24(sp_digit* r, const sp_digit* a); +extern sp_digit sp_3072_add_24(sp_digit* r, const sp_digit* a, const sp_digit* b); +extern sp_digit sp_3072_sub_in_place_48(sp_digit* a, const sp_digit* b); +extern sp_digit sp_3072_add_48(sp_digit* r, const sp_digit* a, const sp_digit* b); +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_3072_mask_24(sp_digit* r, sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<24; i++) + r[i] = a[i] & m; +#else + int i; + + for (i = 0; i < 24; i += 8) { + r[i+0] = a[i+0] & m; + r[i+1] = a[i+1] & m; + r[i+2] = a[i+2] & m; + r[i+3] = a[i+3] & m; + r[i+4] = a[i+4] & m; + r[i+5] = a[i+5] & m; + r[i+6] = a[i+6] & m; + r[i+7] = a[i+7] & m; + } +#endif +} + +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_3072_mul_48(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[48]; + sp_digit a1[24]; + sp_digit b1[24]; + sp_digit z2[48]; + sp_digit u, ca, cb; + + ca = sp_3072_add_24(a1, a, &a[24]); + cb = sp_3072_add_24(b1, b, &b[24]); + u = ca & cb; + sp_3072_mul_24(z1, a1, b1); + sp_3072_mul_24(z2, &a[24], &b[24]); + sp_3072_mul_24(z0, a, b); + sp_3072_mask_24(r + 48, a1, 0 - cb); + sp_3072_mask_24(b1, b1, 0 - ca); + u += sp_3072_add_24(r + 48, r + 48, b1); + u += sp_3072_sub_in_place_48(z1, z2); + u += sp_3072_sub_in_place_48(z1, z0); + u += sp_3072_add_48(r + 24, r + 24, z1); + r[72] = u; + XMEMSET(r + 72 + 1, 0, sizeof(sp_digit) * (24 - 1)); + sp_3072_add_48(r + 48, r + 48, z2); +} + +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_3072_sqr_48(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z2[48]; + sp_digit z1[48]; + sp_digit a1[24]; + sp_digit u; + + u = sp_3072_add_24(a1, a, &a[24]); + sp_3072_sqr_24(z1, a1); + sp_3072_sqr_24(z2, &a[24]); + sp_3072_sqr_24(z0, a); + sp_3072_mask_24(r + 48, a1, 0 - u); + u += sp_3072_add_24(r + 48, r + 48, r + 48); + u += sp_3072_sub_in_place_48(z1, z2); + u += sp_3072_sub_in_place_48(z1, z0); + u += sp_3072_add_48(r + 24, r + 24, z1); + r[72] = u; + XMEMSET(r + 72 + 1, 0, sizeof(sp_digit) * (24 - 1)); + sp_3072_add_48(r + 48, r + 48, z2); +} + +#ifdef HAVE_INTEL_AVX2 +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +SP_NOINLINE static void sp_3072_mul_avx2_48(sp_digit* r, const sp_digit* a, + const sp_digit* b) +{ + sp_digit* z0 = r; + sp_digit z1[48]; + sp_digit a1[24]; + sp_digit b1[24]; + sp_digit z2[48]; + sp_digit u, ca, cb; + + ca = sp_3072_add_24(a1, a, &a[24]); + cb = sp_3072_add_24(b1, b, &b[24]); + u = ca & cb; + sp_3072_mul_avx2_24(z1, a1, b1); + sp_3072_mul_avx2_24(z2, &a[24], &b[24]); + sp_3072_mul_avx2_24(z0, a, b); + sp_3072_mask_24(r + 48, a1, 0 - cb); + sp_3072_mask_24(b1, b1, 0 - ca); + u += sp_3072_add_24(r + 48, r + 48, b1); + u += sp_3072_sub_in_place_48(z1, z2); + u += sp_3072_sub_in_place_48(z1, z0); + u += sp_3072_add_48(r + 24, r + 24, z1); + r[72] = u; + XMEMSET(r + 72 + 1, 0, sizeof(sp_digit) * (24 - 1)); + sp_3072_add_48(r + 48, r + 48, z2); +} +#endif /* HAVE_INTEL_AVX2 */ + +#ifdef HAVE_INTEL_AVX2 +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +SP_NOINLINE static void sp_3072_sqr_avx2_48(sp_digit* r, const sp_digit* a) +{ + sp_digit* z0 = r; + sp_digit z2[48]; + sp_digit z1[48]; + sp_digit a1[24]; + sp_digit u; + + u = sp_3072_add_24(a1, a, &a[24]); + sp_3072_sqr_avx2_24(z1, a1); + sp_3072_sqr_avx2_24(z2, &a[24]); + sp_3072_sqr_avx2_24(z0, a); + sp_3072_mask_24(r + 48, a1, 0 - u); + u += sp_3072_add_24(r + 48, r + 48, r + 48); + u += sp_3072_sub_in_place_48(z1, z2); + u += sp_3072_sub_in_place_48(z1, z0); + u += sp_3072_add_48(r + 24, r + 24, z1); + r[72] = u; + XMEMSET(r + 72 + 1, 0, sizeof(sp_digit) * (24 - 1)); + sp_3072_add_48(r + 48, r + 48, z2); +} +#endif /* HAVE_INTEL_AVX2 */ + +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +/* Caclulate the bottom digit of -1/a mod 2^n. + * + * a A single precision number. + * rho Bottom word of inverse. + */ +static void sp_3072_mont_setup(sp_digit* a, sp_digit* rho) +{ + sp_digit x, b; + + b = a[0]; + x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ + x *= 2 - b * x; /* here x*a==1 mod 2**8 */ + x *= 2 - b * x; /* here x*a==1 mod 2**16 */ + x *= 2 - b * x; /* here x*a==1 mod 2**32 */ + x *= 2 - b * x; /* here x*a==1 mod 2**64 */ + + /* rho = -1/m mod b */ + *rho = -x; +} + +extern void sp_3072_mul_d_48(sp_digit* r, const sp_digit* a, const sp_digit b); +#if (defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH)) && !defined(WOLFSSL_RSA_PUBLIC_ONLY) +extern sp_digit sp_3072_sub_in_place_24(sp_digit* a, const sp_digit* b); +/* r = 2^n mod m where n is the number of bits to reduce by. + * Given m must be 3072 bits, just need to subtract. + * + * r A single precision number. + * m A signle precision number. + */ +static void sp_3072_mont_norm_24(sp_digit* r, sp_digit* m) +{ + XMEMSET(r, 0, sizeof(sp_digit) * 24); + + /* r = 2^n mod m */ + sp_3072_sub_in_place_24(r, m); +} + +extern sp_digit sp_3072_cond_sub_24(sp_digit* r, sp_digit* a, sp_digit* b, sp_digit m); +extern void sp_3072_mont_reduce_24(sp_digit* a, sp_digit* m, sp_digit mp); +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_3072_mont_mul_24(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_3072_mul_24(r, a, b); + sp_3072_mont_reduce_24(r, m, mp); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_3072_mont_sqr_24(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_3072_sqr_24(r, a); + sp_3072_mont_reduce_24(r, m, mp); +} + +extern void sp_3072_mul_d_24(sp_digit* r, const sp_digit* a, const sp_digit b); +extern void sp_3072_mul_d_avx2_24(sp_digit* r, const sp_digit* a, const sp_digit b); +/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) + * + * d1 The high order half of the number to divide. + * d0 The low order half of the number to divide. + * div The dividend. + * returns the result of the division. + */ +static WC_INLINE sp_digit div_3072_word_24(sp_digit d1, sp_digit d0, + sp_digit div) +{ + register sp_digit r asm("rax"); + __asm__ __volatile__ ( + "divq %3" + : "=a" (r) + : "d" (d1), "a" (d0), "r" (div) + : + ); + return r; +} +extern int64_t sp_3072_cmp_24(sp_digit* a, sp_digit* b); +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_3072_div_24(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[48], t2[25]; + sp_digit div, r1; + int i; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + (void)m; + + div = d[23]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 24); + for (i=23; i>=0; i--) { + r1 = div_3072_word_24(t1[24 + i], t1[24 + i - 1], div); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_3072_mul_d_avx2_24(t2, d, r1); + else +#endif + sp_3072_mul_d_24(t2, d, r1); + t1[24 + i] += sp_3072_sub_in_place_24(&t1[i], t2); + t1[24 + i] -= t2[24]; + sp_3072_mask_24(t2, d, t1[24 + i]); + t1[24 + i] += sp_3072_add_24(&t1[i], &t1[i], t2); + sp_3072_mask_24(t2, d, t1[24 + i]); + t1[24 + i] += sp_3072_add_24(&t1[i], &t1[i], t2); + } + + r1 = sp_3072_cmp_24(t1, d) >= 0; + sp_3072_cond_sub_24(r, t1, d, (sp_digit)0 - r1); + + return MP_OKAY; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_3072_mod_24(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_3072_div_24(a, m, NULL, r); +} + +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_3072_mod_exp_24(sp_digit* r, sp_digit* a, sp_digit* e, + int bits, sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][48]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 48, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<32; i++) + t[i] = td + i * 48; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_24(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 24); + if (reduceA) { + err = sp_3072_mod_24(t[1] + 24, a, m); + if (err == MP_OKAY) + err = sp_3072_mod_24(t[1], t[1], m); + } + else { + XMEMCPY(t[1] + 24, a, sizeof(sp_digit) * 24); + err = sp_3072_mod_24(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_3072_mont_sqr_24(t[ 2], t[ 1], m, mp); + sp_3072_mont_mul_24(t[ 3], t[ 2], t[ 1], m, mp); + sp_3072_mont_sqr_24(t[ 4], t[ 2], m, mp); + sp_3072_mont_mul_24(t[ 5], t[ 3], t[ 2], m, mp); + sp_3072_mont_sqr_24(t[ 6], t[ 3], m, mp); + sp_3072_mont_mul_24(t[ 7], t[ 4], t[ 3], m, mp); + sp_3072_mont_sqr_24(t[ 8], t[ 4], m, mp); + sp_3072_mont_mul_24(t[ 9], t[ 5], t[ 4], m, mp); + sp_3072_mont_sqr_24(t[10], t[ 5], m, mp); + sp_3072_mont_mul_24(t[11], t[ 6], t[ 5], m, mp); + sp_3072_mont_sqr_24(t[12], t[ 6], m, mp); + sp_3072_mont_mul_24(t[13], t[ 7], t[ 6], m, mp); + sp_3072_mont_sqr_24(t[14], t[ 7], m, mp); + sp_3072_mont_mul_24(t[15], t[ 8], t[ 7], m, mp); + sp_3072_mont_sqr_24(t[16], t[ 8], m, mp); + sp_3072_mont_mul_24(t[17], t[ 9], t[ 8], m, mp); + sp_3072_mont_sqr_24(t[18], t[ 9], m, mp); + sp_3072_mont_mul_24(t[19], t[10], t[ 9], m, mp); + sp_3072_mont_sqr_24(t[20], t[10], m, mp); + sp_3072_mont_mul_24(t[21], t[11], t[10], m, mp); + sp_3072_mont_sqr_24(t[22], t[11], m, mp); + sp_3072_mont_mul_24(t[23], t[12], t[11], m, mp); + sp_3072_mont_sqr_24(t[24], t[12], m, mp); + sp_3072_mont_mul_24(t[25], t[13], t[12], m, mp); + sp_3072_mont_sqr_24(t[26], t[13], m, mp); + sp_3072_mont_mul_24(t[27], t[14], t[13], m, mp); + sp_3072_mont_sqr_24(t[28], t[14], m, mp); + sp_3072_mont_mul_24(t[29], t[15], t[14], m, mp); + sp_3072_mont_sqr_24(t[30], t[15], m, mp); + sp_3072_mont_mul_24(t[31], t[16], t[15], m, mp); + + i = (bits - 1) / 64; + n = e[i--]; + y = n >> 59; + n <<= 5; + c = 59; + XMEMCPY(r, t[y], sizeof(sp_digit) * 24); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 59; + n <<= 5; + c = 59; + } + else if (c < 5) { + y = n >> 59; + n = e[i--]; + c = 5 - c; + y |= n >> (64 - c); + n <<= c; + c = 64 - c; + } + else { + y = (n >> 59) & 0x1f; + n <<= 5; + c -= 5; + } + + sp_3072_mont_sqr_24(r, r, m, mp); + sp_3072_mont_sqr_24(r, r, m, mp); + sp_3072_mont_sqr_24(r, r, m, mp); + sp_3072_mont_sqr_24(r, r, m, mp); + sp_3072_mont_sqr_24(r, r, m, mp); + + sp_3072_mont_mul_24(r, r, t[y], m, mp); + } + y = e[0] & ((1 << c) - 1); + for (; c > 0; c--) + sp_3072_mont_sqr_24(r, r, m, mp); + sp_3072_mont_mul_24(r, r, t[y], m, mp); + + XMEMSET(&r[24], 0, sizeof(sp_digit) * 24); + sp_3072_mont_reduce_24(r, m, mp); + + mask = 0 - (sp_3072_cmp_24(r, m) >= 0); + sp_3072_cond_sub_24(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} + +extern void sp_3072_mont_reduce_avx2_24(sp_digit* a, sp_digit* m, sp_digit mp); +#ifdef HAVE_INTEL_AVX2 +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_3072_mont_mul_avx2_24(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_3072_mul_avx2_24(r, a, b); + sp_3072_mont_reduce_avx2_24(r, m, mp); +} + +#endif /* HAVE_INTEL_AVX2 */ +#ifdef HAVE_INTEL_AVX2 +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_3072_mont_sqr_avx2_24(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_3072_sqr_avx2_24(r, a); + sp_3072_mont_reduce_avx2_24(r, m, mp); +} + +#endif /* HAVE_INTEL_AVX2 */ +#ifdef HAVE_INTEL_AVX2 +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_3072_mod_exp_avx2_24(sp_digit* r, sp_digit* a, sp_digit* e, + int bits, sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][48]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 48, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<32; i++) + t[i] = td + i * 48; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_24(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 24); + if (reduceA) { + err = sp_3072_mod_24(t[1] + 24, a, m); + if (err == MP_OKAY) + err = sp_3072_mod_24(t[1], t[1], m); + } + else { + XMEMCPY(t[1] + 24, a, sizeof(sp_digit) * 24); + err = sp_3072_mod_24(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_3072_mont_sqr_avx2_24(t[ 2], t[ 1], m, mp); + sp_3072_mont_mul_avx2_24(t[ 3], t[ 2], t[ 1], m, mp); + sp_3072_mont_sqr_avx2_24(t[ 4], t[ 2], m, mp); + sp_3072_mont_mul_avx2_24(t[ 5], t[ 3], t[ 2], m, mp); + sp_3072_mont_sqr_avx2_24(t[ 6], t[ 3], m, mp); + sp_3072_mont_mul_avx2_24(t[ 7], t[ 4], t[ 3], m, mp); + sp_3072_mont_sqr_avx2_24(t[ 8], t[ 4], m, mp); + sp_3072_mont_mul_avx2_24(t[ 9], t[ 5], t[ 4], m, mp); + sp_3072_mont_sqr_avx2_24(t[10], t[ 5], m, mp); + sp_3072_mont_mul_avx2_24(t[11], t[ 6], t[ 5], m, mp); + sp_3072_mont_sqr_avx2_24(t[12], t[ 6], m, mp); + sp_3072_mont_mul_avx2_24(t[13], t[ 7], t[ 6], m, mp); + sp_3072_mont_sqr_avx2_24(t[14], t[ 7], m, mp); + sp_3072_mont_mul_avx2_24(t[15], t[ 8], t[ 7], m, mp); + sp_3072_mont_sqr_avx2_24(t[16], t[ 8], m, mp); + sp_3072_mont_mul_avx2_24(t[17], t[ 9], t[ 8], m, mp); + sp_3072_mont_sqr_avx2_24(t[18], t[ 9], m, mp); + sp_3072_mont_mul_avx2_24(t[19], t[10], t[ 9], m, mp); + sp_3072_mont_sqr_avx2_24(t[20], t[10], m, mp); + sp_3072_mont_mul_avx2_24(t[21], t[11], t[10], m, mp); + sp_3072_mont_sqr_avx2_24(t[22], t[11], m, mp); + sp_3072_mont_mul_avx2_24(t[23], t[12], t[11], m, mp); + sp_3072_mont_sqr_avx2_24(t[24], t[12], m, mp); + sp_3072_mont_mul_avx2_24(t[25], t[13], t[12], m, mp); + sp_3072_mont_sqr_avx2_24(t[26], t[13], m, mp); + sp_3072_mont_mul_avx2_24(t[27], t[14], t[13], m, mp); + sp_3072_mont_sqr_avx2_24(t[28], t[14], m, mp); + sp_3072_mont_mul_avx2_24(t[29], t[15], t[14], m, mp); + sp_3072_mont_sqr_avx2_24(t[30], t[15], m, mp); + sp_3072_mont_mul_avx2_24(t[31], t[16], t[15], m, mp); + + i = (bits - 1) / 64; + n = e[i--]; + y = n >> 59; + n <<= 5; + c = 59; + XMEMCPY(r, t[y], sizeof(sp_digit) * 24); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 59; + n <<= 5; + c = 59; + } + else if (c < 5) { + y = n >> 59; + n = e[i--]; + c = 5 - c; + y |= n >> (64 - c); + n <<= c; + c = 64 - c; + } + else { + y = (n >> 59) & 0x1f; + n <<= 5; + c -= 5; + } + + sp_3072_mont_sqr_avx2_24(r, r, m, mp); + sp_3072_mont_sqr_avx2_24(r, r, m, mp); + sp_3072_mont_sqr_avx2_24(r, r, m, mp); + sp_3072_mont_sqr_avx2_24(r, r, m, mp); + sp_3072_mont_sqr_avx2_24(r, r, m, mp); + + sp_3072_mont_mul_avx2_24(r, r, t[y], m, mp); + } + y = e[0] & ((1 << c) - 1); + for (; c > 0; c--) + sp_3072_mont_sqr_avx2_24(r, r, m, mp); + sp_3072_mont_mul_avx2_24(r, r, t[y], m, mp); + + XMEMSET(&r[24], 0, sizeof(sp_digit) * 24); + sp_3072_mont_reduce_avx2_24(r, m, mp); + + mask = 0 - (sp_3072_cmp_24(r, m) >= 0); + sp_3072_cond_sub_24(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#endif /* HAVE_INTEL_AVX2 */ + +#endif /* (WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH) && !WOLFSSL_RSA_PUBLIC_ONLY */ + +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) +/* r = 2^n mod m where n is the number of bits to reduce by. + * Given m must be 3072 bits, just need to subtract. + * + * r A single precision number. + * m A signle precision number. + */ +static void sp_3072_mont_norm_48(sp_digit* r, sp_digit* m) +{ + XMEMSET(r, 0, sizeof(sp_digit) * 48); + + /* r = 2^n mod m */ + sp_3072_sub_in_place_48(r, m); +} + +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +extern sp_digit sp_3072_cond_sub_48(sp_digit* r, sp_digit* a, sp_digit* b, sp_digit m); +extern void sp_3072_mont_reduce_48(sp_digit* a, sp_digit* m, sp_digit mp); +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_3072_mont_mul_48(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_3072_mul_48(r, a, b); + sp_3072_mont_reduce_48(r, m, mp); +} + +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_3072_mont_sqr_48(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_3072_sqr_48(r, a); + sp_3072_mont_reduce_48(r, m, mp); +} + +#ifndef WOLFSSL_RSA_PUBLIC_ONLY +extern void sp_3072_mul_d_avx2_48(sp_digit* r, const sp_digit* a, const sp_digit b); +/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) + * + * d1 The high order half of the number to divide. + * d0 The low order half of the number to divide. + * div The dividend. + * returns the result of the division. + */ +static WC_INLINE sp_digit div_3072_word_48(sp_digit d1, sp_digit d0, + sp_digit div) +{ + register sp_digit r asm("rax"); + __asm__ __volatile__ ( + "divq %3" + : "=a" (r) + : "d" (d1), "a" (d0), "r" (div) + : + ); + return r; +} +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_3072_mask_48(sp_digit* r, sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<48; i++) + r[i] = a[i] & m; +#else + int i; + + for (i = 0; i < 48; i += 8) { + r[i+0] = a[i+0] & m; + r[i+1] = a[i+1] & m; + r[i+2] = a[i+2] & m; + r[i+3] = a[i+3] & m; + r[i+4] = a[i+4] & m; + r[i+5] = a[i+5] & m; + r[i+6] = a[i+6] & m; + r[i+7] = a[i+7] & m; + } +#endif +} + +extern int64_t sp_3072_cmp_48(sp_digit* a, sp_digit* b); +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_3072_div_48(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[96], t2[49]; + sp_digit div, r1; + int i; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + (void)m; + + div = d[47]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 48); + for (i=47; i>=0; i--) { + r1 = div_3072_word_48(t1[48 + i], t1[48 + i - 1], div); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_3072_mul_d_avx2_48(t2, d, r1); + else +#endif + sp_3072_mul_d_48(t2, d, r1); + t1[48 + i] += sp_3072_sub_in_place_48(&t1[i], t2); + t1[48 + i] -= t2[48]; + sp_3072_mask_48(t2, d, t1[48 + i]); + t1[48 + i] += sp_3072_add_48(&t1[i], &t1[i], t2); + sp_3072_mask_48(t2, d, t1[48 + i]); + t1[48 + i] += sp_3072_add_48(&t1[i], &t1[i], t2); + } + + r1 = sp_3072_cmp_48(t1, d) >= 0; + sp_3072_cond_sub_48(r, t1, d, (sp_digit)0 - r1); + + return MP_OKAY; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_3072_mod_48(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_3072_div_48(a, m, NULL, r); +} + +#endif /* WOLFSSL_RSA_PUBLIC_ONLY */ +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_3072_div_48_cond(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[96], t2[49]; + sp_digit div, r1; + int i; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + (void)m; + + div = d[47]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 48); + for (i=47; i>=0; i--) { + r1 = div_3072_word_48(t1[48 + i], t1[48 + i - 1], div); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_3072_mul_d_avx2_48(t2, d, r1); + else +#endif + sp_3072_mul_d_48(t2, d, r1); + t1[48 + i] += sp_3072_sub_in_place_48(&t1[i], t2); + t1[48 + i] -= t2[48]; + if (t1[48 + i] != 0) { + t1[48 + i] += sp_3072_add_48(&t1[i], &t1[i], d); + if (t1[48 + i] != 0) + t1[48 + i] += sp_3072_add_48(&t1[i], &t1[i], d); + } + } + + r1 = sp_3072_cmp_48(t1, d) >= 0; + sp_3072_cond_sub_48(r, t1, d, (sp_digit)0 - r1); + + return MP_OKAY; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_3072_mod_48_cond(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_3072_div_48_cond(a, m, NULL, r); +} + +#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH) +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_3072_mod_exp_48(sp_digit* r, sp_digit* a, sp_digit* e, + int bits, sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][96]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 96, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<32; i++) + t[i] = td + i * 96; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_48(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 48); + if (reduceA) { + err = sp_3072_mod_48(t[1] + 48, a, m); + if (err == MP_OKAY) + err = sp_3072_mod_48(t[1], t[1], m); + } + else { + XMEMCPY(t[1] + 48, a, sizeof(sp_digit) * 48); + err = sp_3072_mod_48(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_3072_mont_sqr_48(t[ 2], t[ 1], m, mp); + sp_3072_mont_mul_48(t[ 3], t[ 2], t[ 1], m, mp); + sp_3072_mont_sqr_48(t[ 4], t[ 2], m, mp); + sp_3072_mont_mul_48(t[ 5], t[ 3], t[ 2], m, mp); + sp_3072_mont_sqr_48(t[ 6], t[ 3], m, mp); + sp_3072_mont_mul_48(t[ 7], t[ 4], t[ 3], m, mp); + sp_3072_mont_sqr_48(t[ 8], t[ 4], m, mp); + sp_3072_mont_mul_48(t[ 9], t[ 5], t[ 4], m, mp); + sp_3072_mont_sqr_48(t[10], t[ 5], m, mp); + sp_3072_mont_mul_48(t[11], t[ 6], t[ 5], m, mp); + sp_3072_mont_sqr_48(t[12], t[ 6], m, mp); + sp_3072_mont_mul_48(t[13], t[ 7], t[ 6], m, mp); + sp_3072_mont_sqr_48(t[14], t[ 7], m, mp); + sp_3072_mont_mul_48(t[15], t[ 8], t[ 7], m, mp); + sp_3072_mont_sqr_48(t[16], t[ 8], m, mp); + sp_3072_mont_mul_48(t[17], t[ 9], t[ 8], m, mp); + sp_3072_mont_sqr_48(t[18], t[ 9], m, mp); + sp_3072_mont_mul_48(t[19], t[10], t[ 9], m, mp); + sp_3072_mont_sqr_48(t[20], t[10], m, mp); + sp_3072_mont_mul_48(t[21], t[11], t[10], m, mp); + sp_3072_mont_sqr_48(t[22], t[11], m, mp); + sp_3072_mont_mul_48(t[23], t[12], t[11], m, mp); + sp_3072_mont_sqr_48(t[24], t[12], m, mp); + sp_3072_mont_mul_48(t[25], t[13], t[12], m, mp); + sp_3072_mont_sqr_48(t[26], t[13], m, mp); + sp_3072_mont_mul_48(t[27], t[14], t[13], m, mp); + sp_3072_mont_sqr_48(t[28], t[14], m, mp); + sp_3072_mont_mul_48(t[29], t[15], t[14], m, mp); + sp_3072_mont_sqr_48(t[30], t[15], m, mp); + sp_3072_mont_mul_48(t[31], t[16], t[15], m, mp); + + i = (bits - 1) / 64; + n = e[i--]; + y = n >> 59; + n <<= 5; + c = 59; + XMEMCPY(r, t[y], sizeof(sp_digit) * 48); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 59; + n <<= 5; + c = 59; + } + else if (c < 5) { + y = n >> 59; + n = e[i--]; + c = 5 - c; + y |= n >> (64 - c); + n <<= c; + c = 64 - c; + } + else { + y = (n >> 59) & 0x1f; + n <<= 5; + c -= 5; + } + + sp_3072_mont_sqr_48(r, r, m, mp); + sp_3072_mont_sqr_48(r, r, m, mp); + sp_3072_mont_sqr_48(r, r, m, mp); + sp_3072_mont_sqr_48(r, r, m, mp); + sp_3072_mont_sqr_48(r, r, m, mp); + + sp_3072_mont_mul_48(r, r, t[y], m, mp); + } + y = e[0] & ((1 << c) - 1); + for (; c > 0; c--) + sp_3072_mont_sqr_48(r, r, m, mp); + sp_3072_mont_mul_48(r, r, t[y], m, mp); + + XMEMSET(&r[48], 0, sizeof(sp_digit) * 48); + sp_3072_mont_reduce_48(r, m, mp); + + mask = 0 - (sp_3072_cmp_48(r, m) >= 0); + sp_3072_cond_sub_48(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ + +extern void sp_3072_mont_reduce_avx2_48(sp_digit* a, sp_digit* m, sp_digit mp); +#ifdef HAVE_INTEL_AVX2 +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_3072_mont_mul_avx2_48(sp_digit* r, sp_digit* a, sp_digit* b, + sp_digit* m, sp_digit mp) +{ + sp_3072_mul_avx2_48(r, a, b); + sp_3072_mont_reduce_avx2_48(r, m, mp); +} + +#endif /* HAVE_INTEL_AVX2 */ +#ifdef HAVE_INTEL_AVX2 +/* Square the Montgomery form number. (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_3072_mont_sqr_avx2_48(sp_digit* r, sp_digit* a, sp_digit* m, + sp_digit mp) +{ + sp_3072_sqr_avx2_48(r, a); + sp_3072_mont_reduce_avx2_48(r, m, mp); +} + +#endif /* HAVE_INTEL_AVX2 */ +#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || defined(WOLFSSL_HAVE_SP_DH) +#ifdef HAVE_INTEL_AVX2 +/* Modular exponentiate a to the e mod m. (r = a^e mod m) + * + * r A single precision number that is the result of the operation. + * a A single precision number being exponentiated. + * e A single precision number that is the exponent. + * bits The number of bits in the exponent. + * m A single precision number that is the modulus. + * returns 0 on success and MEMORY_E on dynamic memory allocation failure. + */ +static int sp_3072_mod_exp_avx2_48(sp_digit* r, sp_digit* a, sp_digit* e, + int bits, sp_digit* m, int reduceA) +{ +#ifndef WOLFSSL_SMALL_STACK + sp_digit t[32][96]; +#else + sp_digit* t[32]; + sp_digit* td; +#endif + sp_digit* norm; + sp_digit mp = 1; + sp_digit n; + sp_digit mask; + int i; + int c, y; + int err = MP_OKAY; + +#ifdef WOLFSSL_SMALL_STACK + td = (sp_digit*)XMALLOC(sizeof(sp_digit) * 32 * 96, NULL, + DYNAMIC_TYPE_TMP_BUFFER); + if (td == NULL) + err = MEMORY_E; + + if (err == MP_OKAY) { + for (i=0; i<32; i++) + t[i] = td + i * 96; + norm = t[0]; + } +#else + norm = t[0]; +#endif + + if (err == MP_OKAY) { + sp_3072_mont_setup(m, &mp); + sp_3072_mont_norm_48(norm, m); + + XMEMSET(t[1], 0, sizeof(sp_digit) * 48); + if (reduceA) { + err = sp_3072_mod_48(t[1] + 48, a, m); + if (err == MP_OKAY) + err = sp_3072_mod_48(t[1], t[1], m); + } + else { + XMEMCPY(t[1] + 48, a, sizeof(sp_digit) * 48); + err = sp_3072_mod_48(t[1], t[1], m); + } + } + + if (err == MP_OKAY) { + sp_3072_mont_sqr_avx2_48(t[ 2], t[ 1], m, mp); + sp_3072_mont_mul_avx2_48(t[ 3], t[ 2], t[ 1], m, mp); + sp_3072_mont_sqr_avx2_48(t[ 4], t[ 2], m, mp); + sp_3072_mont_mul_avx2_48(t[ 5], t[ 3], t[ 2], m, mp); + sp_3072_mont_sqr_avx2_48(t[ 6], t[ 3], m, mp); + sp_3072_mont_mul_avx2_48(t[ 7], t[ 4], t[ 3], m, mp); + sp_3072_mont_sqr_avx2_48(t[ 8], t[ 4], m, mp); + sp_3072_mont_mul_avx2_48(t[ 9], t[ 5], t[ 4], m, mp); + sp_3072_mont_sqr_avx2_48(t[10], t[ 5], m, mp); + sp_3072_mont_mul_avx2_48(t[11], t[ 6], t[ 5], m, mp); + sp_3072_mont_sqr_avx2_48(t[12], t[ 6], m, mp); + sp_3072_mont_mul_avx2_48(t[13], t[ 7], t[ 6], m, mp); + sp_3072_mont_sqr_avx2_48(t[14], t[ 7], m, mp); + sp_3072_mont_mul_avx2_48(t[15], t[ 8], t[ 7], m, mp); + sp_3072_mont_sqr_avx2_48(t[16], t[ 8], m, mp); + sp_3072_mont_mul_avx2_48(t[17], t[ 9], t[ 8], m, mp); + sp_3072_mont_sqr_avx2_48(t[18], t[ 9], m, mp); + sp_3072_mont_mul_avx2_48(t[19], t[10], t[ 9], m, mp); + sp_3072_mont_sqr_avx2_48(t[20], t[10], m, mp); + sp_3072_mont_mul_avx2_48(t[21], t[11], t[10], m, mp); + sp_3072_mont_sqr_avx2_48(t[22], t[11], m, mp); + sp_3072_mont_mul_avx2_48(t[23], t[12], t[11], m, mp); + sp_3072_mont_sqr_avx2_48(t[24], t[12], m, mp); + sp_3072_mont_mul_avx2_48(t[25], t[13], t[12], m, mp); + sp_3072_mont_sqr_avx2_48(t[26], t[13], m, mp); + sp_3072_mont_mul_avx2_48(t[27], t[14], t[13], m, mp); + sp_3072_mont_sqr_avx2_48(t[28], t[14], m, mp); + sp_3072_mont_mul_avx2_48(t[29], t[15], t[14], m, mp); + sp_3072_mont_sqr_avx2_48(t[30], t[15], m, mp); + sp_3072_mont_mul_avx2_48(t[31], t[16], t[15], m, mp); + + i = (bits - 1) / 64; + n = e[i--]; + y = n >> 59; + n <<= 5; + c = 59; + XMEMCPY(r, t[y], sizeof(sp_digit) * 48); + for (; i>=0 || c>=5; ) { + if (c == 0) { + n = e[i--]; + y = n >> 59; + n <<= 5; + c = 59; + } + else if (c < 5) { + y = n >> 59; + n = e[i--]; + c = 5 - c; + y |= n >> (64 - c); + n <<= c; + c = 64 - c; + } + else { + y = (n >> 59) & 0x1f; + n <<= 5; + c -= 5; + } + + sp_3072_mont_sqr_avx2_48(r, r, m, mp); + sp_3072_mont_sqr_avx2_48(r, r, m, mp); + sp_3072_mont_sqr_avx2_48(r, r, m, mp); + sp_3072_mont_sqr_avx2_48(r, r, m, mp); + sp_3072_mont_sqr_avx2_48(r, r, m, mp); + + sp_3072_mont_mul_avx2_48(r, r, t[y], m, mp); + } + y = e[0] & ((1 << c) - 1); + for (; c > 0; c--) + sp_3072_mont_sqr_avx2_48(r, r, m, mp); + sp_3072_mont_mul_avx2_48(r, r, t[y], m, mp); + + XMEMSET(&r[48], 0, sizeof(sp_digit) * 48); + sp_3072_mont_reduce_avx2_48(r, m, mp); + + mask = 0 - (sp_3072_cmp_48(r, m) >= 0); + sp_3072_cond_sub_48(r, r, m, mask); + } + +#ifdef WOLFSSL_SMALL_STACK + if (td != NULL) + XFREE(td, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} +#endif /* HAVE_INTEL_AVX2 */ +#endif /* (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) || WOLFSSL_HAVE_SP_DH */ + +#ifdef WOLFSSL_HAVE_SP_RSA +/* RSA public key operation. + * + * in Array of bytes representing the number to exponentiate, base. + * inLen Number of bytes in base. + * em Public exponent. + * mm Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 384 bytes long. + * outLen Number of bytes in result. + * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when + * an array is too long and MEMORY_E when dynamic memory allocation fails. + */ +int sp_RsaPublic_3072(const byte* in, word32 inLen, mp_int* em, mp_int* mm, + byte* out, word32* outLen) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit ad[96], md[48], rd[96]; +#else + sp_digit* d = NULL; +#endif + sp_digit* a; + sp_digit *ah; + sp_digit* m; + sp_digit* r; + sp_digit e[1]; + int err = MP_OKAY; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + if (*outLen < 384) + err = MP_TO_E; + if (err == MP_OKAY && (mp_count_bits(em) > 64 || inLen > 384 || + mp_count_bits(mm) != 3072)) + err = MP_READ_E; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 48 * 5, NULL, + DYNAMIC_TYPE_RSA); + if (d == NULL) + err = MEMORY_E; + } + + if (err == MP_OKAY) { + a = d; + r = a + 48 * 2; + m = r + 48 * 2; + ah = a + 48; + } +#else + a = ad; + m = md; + r = rd; + ah = a + 48; +#endif + + if (err == MP_OKAY) { + sp_3072_from_bin(ah, 48, in, inLen); +#if DIGIT_BIT >= 64 + e[0] = em->dp[0]; +#else + e[0] = em->dp[0]; + if (em->used > 1) + e[0] |= ((sp_digit)em->dp[1]) << DIGIT_BIT; +#endif + if (e[0] == 0) + err = MP_EXPTMOD_E; + } + if (err == MP_OKAY) { + sp_3072_from_mp(m, 48, mm); + + if (e[0] == 0x3) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + if (err == MP_OKAY) { + sp_3072_sqr_avx2_48(r, ah); + err = sp_3072_mod_48_cond(r, r, m); + } + if (err == MP_OKAY) { + sp_3072_mul_avx2_48(r, ah, r); + err = sp_3072_mod_48_cond(r, r, m); + } + } + else +#endif + { + if (err == MP_OKAY) { + sp_3072_sqr_48(r, ah); + err = sp_3072_mod_48_cond(r, r, m); + } + if (err == MP_OKAY) { + sp_3072_mul_48(r, ah, r); + err = sp_3072_mod_48_cond(r, r, m); + } + } + } + else { + int i; + sp_digit mp; + + sp_3072_mont_setup(m, &mp); + + /* Convert to Montgomery form. */ + XMEMSET(a, 0, sizeof(sp_digit) * 48); + err = sp_3072_mod_48_cond(a, a, m); + + if (err == MP_OKAY) { + for (i=63; i>=0; i--) + if (e[0] >> i) + break; + + XMEMCPY(r, a, sizeof(sp_digit) * 48); +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + for (i--; i>=0; i--) { + sp_3072_mont_sqr_avx2_48(r, r, m, mp); + if (((e[0] >> i) & 1) == 1) + sp_3072_mont_mul_avx2_48(r, r, a, m, mp); + } + XMEMSET(&r[48], 0, sizeof(sp_digit) * 48); + sp_3072_mont_reduce_avx2_48(r, m, mp); + } + else +#endif + { + for (i--; i>=0; i--) { + sp_3072_mont_sqr_48(r, r, m, mp); + if (((e[0] >> i) & 1) == 1) + sp_3072_mont_mul_48(r, r, a, m, mp); + } + XMEMSET(&r[48], 0, sizeof(sp_digit) * 48); + sp_3072_mont_reduce_48(r, m, mp); + } + + for (i = 47; i > 0; i--) { + if (r[i] != m[i]) + break; + } + if (r[i] >= m[i]) + sp_3072_sub_in_place_48(r, m); + } + } + } + + if (err == MP_OKAY) { + sp_3072_to_bin(r, out); + *outLen = 384; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_RSA); +#endif + + return err; +} + +/* RSA private key operation. + * + * in Array of bytes representing the number to exponentiate, base. + * inLen Number of bytes in base. + * dm Private exponent. + * pm First prime. + * qm Second prime. + * dpm First prime's CRT exponent. + * dqm Second prime's CRT exponent. + * qim Inverse of second prime mod p. + * mm Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 384 bytes long. + * outLen Number of bytes in result. + * returns 0 on success, MP_TO_E when the outLen is too small, MP_READ_E when + * an array is too long and MEMORY_E when dynamic memory allocation fails. + */ +int sp_RsaPrivate_3072(const byte* in, word32 inLen, mp_int* dm, + mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, mp_int* mm, + byte* out, word32* outLen) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit ad[48 * 2]; + sp_digit pd[24], qd[24], dpd[24]; + sp_digit tmpad[48], tmpbd[48]; +#else + sp_digit* t = NULL; +#endif + sp_digit* a; + sp_digit* p; + sp_digit* q; + sp_digit* dp; + sp_digit* dq; + sp_digit* qi; + sp_digit* tmp; + sp_digit* tmpa; + sp_digit* tmpb; + sp_digit* r; + sp_digit c; + int err = MP_OKAY; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + (void)dm; + (void)mm; + + if (*outLen < 384) + err = MP_TO_E; + if (err == MP_OKAY && (inLen > 384 || mp_count_bits(mm) != 3072)) + err = MP_READ_E; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 24 * 11, NULL, + DYNAMIC_TYPE_RSA); + if (t == NULL) + err = MEMORY_E; + } + if (err == MP_OKAY) { + a = t; + p = a + 48 * 2; + q = p + 24; + qi = dq = dp = q + 24; + tmpa = qi + 24; + tmpb = tmpa + 48; + + tmp = t; + r = tmp + 48; + } +#else + r = a = ad; + p = pd; + q = qd; + qi = dq = dp = dpd; + tmpa = tmpad; + tmpb = tmpbd; + tmp = a + 48; +#endif + + if (err == MP_OKAY) { + sp_3072_from_bin(a, 48, in, inLen); + sp_3072_from_mp(p, 24, pm); + sp_3072_from_mp(q, 24, qm); + sp_3072_from_mp(dp, 24, dpm); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_3072_mod_exp_avx2_24(tmpa, a, dp, 1536, p, 1); + else +#endif + err = sp_3072_mod_exp_24(tmpa, a, dp, 1536, p, 1); + } + if (err == MP_OKAY) { + sp_3072_from_mp(dq, 24, dqm); +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_3072_mod_exp_avx2_24(tmpb, a, dq, 1536, q, 1); + else +#endif + err = sp_3072_mod_exp_24(tmpb, a, dq, 1536, q, 1); + } + + if (err == MP_OKAY) { + c = sp_3072_sub_in_place_24(tmpa, tmpb); + sp_3072_mask_24(tmp, p, c); + sp_3072_add_24(tmpa, tmpa, tmp); + + sp_3072_from_mp(qi, 24, qim); +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_3072_mul_avx2_24(tmpa, tmpa, qi); + else +#endif + sp_3072_mul_24(tmpa, tmpa, qi); + err = sp_3072_mod_24(tmpa, tmpa, p); + } + + if (err == MP_OKAY) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_3072_mul_avx2_24(tmpa, q, tmpa); + else +#endif + sp_3072_mul_24(tmpa, q, tmpa); + XMEMSET(&tmpb[24], 0, sizeof(sp_digit) * 24); + sp_3072_add_48(r, tmpb, tmpa); + + sp_3072_to_bin(r, out); + *outLen = 384; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_digit) * 24 * 11); + XFREE(t, NULL, DYNAMIC_TYPE_RSA); + } +#else + XMEMSET(tmpad, 0, sizeof(tmpad)); + XMEMSET(tmpbd, 0, sizeof(tmpbd)); + XMEMSET(pd, 0, sizeof(pd)); + XMEMSET(qd, 0, sizeof(qd)); + XMEMSET(dpd, 0, sizeof(dpd)); +#endif + + return err; +} +#endif /* WOLFSSL_HAVE_SP_RSA */ +#if defined(WOLFSSL_HAVE_SP_DH) || (defined(WOLFSSL_HAVE_SP_RSA) && \ + !defined(WOLFSSL_RSA_PUBLIC_ONLY)) +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_3072_to_mp(sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (3072 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { +#if DIGIT_BIT == 64 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 48); + r->used = 48; + mp_clamp(r); +#elif DIGIT_BIT < 64 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 48; i++) { + r->dp[j] |= a[i] << s; + r->dp[j] &= (1l << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + while (s + DIGIT_BIT <= 64) { + s += DIGIT_BIT; + r->dp[j] &= (1l << DIGIT_BIT) - 1; + r->dp[++j] = a[i] >> s; + } + s = 64 - s; + } + r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 48; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 64 >= DIGIT_BIT) { + #if DIGIT_BIT < 64 + r->dp[j] &= (1l << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 64 - s; + } + else + s += 64; + } + r->used = (3072 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returs 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ + int err = MP_OKAY; + sp_digit b[96], e[48], m[48]; + sp_digit* r = b; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 3072 || expBits > 3072 || + mp_count_bits(mod) != 3072) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + sp_3072_from_mp(b, 48, base); + sp_3072_from_mp(e, 48, exp); + sp_3072_from_mp(m, 48, mod); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_3072_mod_exp_avx2_48(r, b, e, expBits, m, 0); + else +#endif + err = sp_3072_mod_exp_48(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + err = sp_3072_to_mp(r, res); + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} + +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. + * exp Array of bytes that is the exponent. + * expLen Length of data, in bytes, in exponent. + * mod Modulus. + * out Buffer to hold big-endian bytes of exponentiation result. + * Must be at least 384 bytes long. + * outLen Length, in bytes, of exponentiation result. + * returs 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen, + mp_int* mod, byte* out, word32* outLen) +{ + int err = MP_OKAY; + sp_digit b[96], e[48], m[48]; + sp_digit* r = b; + word32 i; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + if (mp_count_bits(base) > 3072 || expLen > 384 || + mp_count_bits(mod) != 3072) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + sp_3072_from_mp(b, 48, base); + sp_3072_from_bin(e, 48, exp, expLen); + sp_3072_from_mp(m, 48, mod); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_3072_mod_exp_avx2_48(r, b, e, expLen * 8, m, 0); + else +#endif + err = sp_3072_mod_exp_48(r, b, e, expLen * 8, m, 0); + } + + if (err == MP_OKAY) { + sp_3072_to_bin(r, out); + *outLen = 384; + for (i=0; i<384 && out[i] == 0; i++) { + } + *outLen -= i; + XMEMMOVE(out, out + i, *outLen); + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} +/* Perform the modular exponentiation for Diffie-Hellman. + * + * base Base. MP integer. + * exp Exponent. MP integer. + * mod Modulus. MP integer. + * res Result. MP integer. + * returs 0 on success, MP_READ_E if there are too many bytes in an array + * and MEMORY_E if memory allocation fails. + */ +int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, mp_int* res) +{ + int err = MP_OKAY; + sp_digit b[48], e[24], m[24]; + sp_digit* r = b; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + int expBits = mp_count_bits(exp); + + if (mp_count_bits(base) > 1536 || expBits > 1536 || + mp_count_bits(mod) != 1536) { + err = MP_READ_E; + } + + if (err == MP_OKAY) { + sp_3072_from_mp(b, 24, base); + sp_3072_from_mp(e, 24, exp); + sp_3072_from_mp(m, 24, mod); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_3072_mod_exp_avx2_24(r, b, e, expBits, m, 0); + else +#endif + err = sp_3072_mod_exp_24(r, b, e, expBits, m, 0); + } + + if (err == MP_OKAY) { + XMEMSET(r + 24, 0, sizeof(*r) * 24); + err = sp_3072_to_mp(r, res); + } + + XMEMSET(e, 0, sizeof(e)); + + return err; +} + +#endif /* WOLFSSL_HAVE_SP_DH || (WOLFSSL_HAVE_SP_RSA && !WOLFSSL_RSA_PUBLIC_ONLY) */ + +#endif /* !WOLFSSL_SP_NO_3072 */ + +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH */ +#ifdef WOLFSSL_HAVE_SP_ECC +#ifndef WOLFSSL_SP_NO_256 + +/* Point structure to use. */ +typedef struct sp_point { + sp_digit x[2 * 4]; + sp_digit y[2 * 4]; + sp_digit z[2 * 4]; + int infinity; +} sp_point; + +/* The modulus (prime) of the curve P256. */ +static sp_digit p256_mod[4] = { + 0xffffffffffffffffl,0x00000000ffffffffl,0x0000000000000000l, + 0xffffffff00000001l +}; +/* The Montogmery normalizer for modulus of the curve P256. */ +static sp_digit p256_norm_mod[4] = { + 0x0000000000000001l,0xffffffff00000000l,0xffffffffffffffffl, + 0x00000000fffffffel +}; +/* The Montogmery multiplier for modulus of the curve P256. */ +static sp_digit p256_mp_mod = 0x0000000000000001; +#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ + defined(HAVE_ECC_VERIFY) +/* The order of the curve P256. */ +static sp_digit p256_order[4] = { + 0xf3b9cac2fc632551l,0xbce6faada7179e84l,0xffffffffffffffffl, + 0xffffffff00000000l +}; +#endif +/* The order of the curve P256 minus 2. */ +static sp_digit p256_order2[4] = { + 0xf3b9cac2fc63254fl,0xbce6faada7179e84l,0xffffffffffffffffl, + 0xffffffff00000000l +}; +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +/* The Montogmery normalizer for order of the curve P256. */ +static sp_digit p256_norm_order[4] = { + 0x0c46353d039cdaafl,0x4319055258e8617bl,0x0000000000000000l, + 0x00000000ffffffffl +}; +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +/* The Montogmery multiplier for order of the curve P256. */ +static sp_digit p256_mp_order = 0xccd1c8aaee00bc4fl; +#endif +#ifdef WOLFSSL_SP_SMALL +/* The base point of curve P256. */ +static sp_point p256_base = { + /* X ordinate */ + { + 0xf4a13945d898c296l,0x77037d812deb33a0l,0xf8bce6e563a440f2l, + 0x6b17d1f2e12c4247l + }, + /* Y ordinate */ + { + 0xcbb6406837bf51f5l,0x2bce33576b315ecel,0x8ee7eb4a7c0f9e16l, + 0x4fe342e2fe1a7f9bl + }, + /* Z ordinate */ + { + 0x0000000000000001l,0x0000000000000000l,0x0000000000000000l, + 0x0000000000000000l + }, + /* infinity */ + 0 +}; +#endif /* WOLFSSL_SP_SMALL */ +#if defined(HAVE_ECC_CHECK_KEY) || defined(HAVE_COMP_KEY) +static sp_digit p256_b[4] = { + 0x3bce3c3e27d2604bl,0x651d06b0cc53b0f6l,0xb3ebbd55769886bcl, + 0x5ac635d8aa3a93e7l +}; +#endif + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) +/* Allocate memory for point and return error. */ +#define sp_ecc_point_new(heap, sp, p) \ + ((p = (sp_point*)XMALLOC(sizeof(sp_point), heap, DYNAMIC_TYPE_ECC)) \ + == NULL) ? MEMORY_E : MP_OKAY +#else +/* Set pointer to data and return no error. */ +#define sp_ecc_point_new(heap, sp, p) ((p = &sp) == NULL) ? MEMORY_E : MP_OKAY +#endif + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) +/* If valid pointer then clear point data if requested and free data. */ +#define sp_ecc_point_free(p, clear, heap) \ + do { \ + if (p != NULL) { \ + if (clear) \ + XMEMSET(p, 0, sizeof(*p)); \ + XFREE(p, heap, DYNAMIC_TYPE_ECC); \ + } \ + } \ + while (0) +#else +/* Clear point data if requested. */ +#define sp_ecc_point_free(p, clear, heap) \ + do { \ + if (clear) \ + XMEMSET(p, 0, sizeof(*p)); \ + } \ + while (0) +#endif + +/* Multiply a number by Montogmery normalizer mod modulus (prime). + * + * r The resulting Montgomery form number. + * a The number to convert. + * m The modulus (prime). + */ +static int sp_256_mod_mul_norm_4(sp_digit* r, sp_digit* a, sp_digit* m) +{ + int64_t t[8]; + int64_t a32[8]; + int64_t o; + + (void)m; + + a32[0] = a[0] & 0xffffffff; + a32[1] = a[0] >> 32; + a32[2] = a[1] & 0xffffffff; + a32[3] = a[1] >> 32; + a32[4] = a[2] & 0xffffffff; + a32[5] = a[2] >> 32; + a32[6] = a[3] & 0xffffffff; + a32[7] = a[3] >> 32; + + /* 1 1 0 -1 -1 -1 -1 0 */ + t[0] = 0 + a32[0] + a32[1] - a32[3] - a32[4] - a32[5] - a32[6]; + /* 0 1 1 0 -1 -1 -1 -1 */ + t[1] = 0 + a32[1] + a32[2] - a32[4] - a32[5] - a32[6] - a32[7]; + /* 0 0 1 1 0 -1 -1 -1 */ + t[2] = 0 + a32[2] + a32[3] - a32[5] - a32[6] - a32[7]; + /* -1 -1 0 2 2 1 0 -1 */ + t[3] = 0 - a32[0] - a32[1] + 2 * a32[3] + 2 * a32[4] + a32[5] - a32[7]; + /* 0 -1 -1 0 2 2 1 0 */ + t[4] = 0 - a32[1] - a32[2] + 2 * a32[4] + 2 * a32[5] + a32[6]; + /* 0 0 -1 -1 0 2 2 1 */ + t[5] = 0 - a32[2] - a32[3] + 2 * a32[5] + 2 * a32[6] + a32[7]; + /* -1 -1 0 0 0 1 3 2 */ + t[6] = 0 - a32[0] - a32[1] + a32[5] + 3 * a32[6] + 2 * a32[7]; + /* 1 0 -1 -1 -1 -1 0 3 */ + t[7] = 0 + a32[0] - a32[2] - a32[3] - a32[4] - a32[5] + 3 * a32[7]; + + t[1] += t[0] >> 32; t[0] &= 0xffffffff; + t[2] += t[1] >> 32; t[1] &= 0xffffffff; + t[3] += t[2] >> 32; t[2] &= 0xffffffff; + t[4] += t[3] >> 32; t[3] &= 0xffffffff; + t[5] += t[4] >> 32; t[4] &= 0xffffffff; + t[6] += t[5] >> 32; t[5] &= 0xffffffff; + t[7] += t[6] >> 32; t[6] &= 0xffffffff; + o = t[7] >> 32; t[7] &= 0xffffffff; + t[0] += o; + t[3] -= o; + t[6] -= o; + t[7] += o; + t[1] += t[0] >> 32; t[0] &= 0xffffffff; + t[2] += t[1] >> 32; t[1] &= 0xffffffff; + t[3] += t[2] >> 32; t[2] &= 0xffffffff; + t[4] += t[3] >> 32; t[3] &= 0xffffffff; + t[5] += t[4] >> 32; t[4] &= 0xffffffff; + t[6] += t[5] >> 32; t[5] &= 0xffffffff; + t[7] += t[6] >> 32; t[6] &= 0xffffffff; + r[0] = (t[1] << 32) | t[0]; + r[1] = (t[3] << 32) | t[2]; + r[2] = (t[5] << 32) | t[4]; + r[3] = (t[7] << 32) | t[6]; + + return MP_OKAY; +} + +/* Convert an mp_int to an array of sp_digit. + * + * r A single precision integer. + * a A multi-precision integer. + */ +static void sp_256_from_mp(sp_digit* r, int max, mp_int* a) +{ +#if DIGIT_BIT == 64 + int j; + + XMEMCPY(r, a->dp, sizeof(sp_digit) * a->used); + + for (j = a->used; j < max; j++) + r[j] = 0; +#elif DIGIT_BIT > 64 + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= a->dp[i] << s; + r[j] &= 0xffffffffffffffffl; + s = 64 - s; + if (j + 1 >= max) + break; + r[++j] = a->dp[i] >> s; + while (s + 64 <= DIGIT_BIT) { + s += 64; + r[j] &= 0xffffffffffffffffl; + if (j + 1 >= max) + break; + if (s < DIGIT_BIT) + r[++j] = a->dp[i] >> s; + else + r[++j] = 0; + } + s = DIGIT_BIT - s; + } + + for (j++; j < max; j++) + r[j] = 0; +#else + int i, j = 0, s = 0; + + r[0] = 0; + for (i = 0; i < a->used && j < max; i++) { + r[j] |= ((sp_digit)a->dp[i]) << s; + if (s + DIGIT_BIT >= 64) { + r[j] &= 0xffffffffffffffffl; + if (j + 1 >= max) + break; + s = 64 - s; + if (s == DIGIT_BIT) { + r[++j] = 0; + s = 0; + } + else { + r[++j] = a->dp[i] >> s; + s = DIGIT_BIT - s; + } + } + else + s += DIGIT_BIT; + } + + for (j++; j < max; j++) + r[j] = 0; +#endif +} + +/* Convert a point of type ecc_point to type sp_point. + * + * p Point of type sp_point (result). + * pm Point of type ecc_point. + */ +static void sp_256_point_from_ecc_point_4(sp_point* p, ecc_point* pm) +{ + XMEMSET(p->x, 0, sizeof(p->x)); + XMEMSET(p->y, 0, sizeof(p->y)); + XMEMSET(p->z, 0, sizeof(p->z)); + sp_256_from_mp(p->x, 4, pm->x); + sp_256_from_mp(p->y, 4, pm->y); + sp_256_from_mp(p->z, 4, pm->z); + p->infinity = 0; +} + +/* Convert an array of sp_digit to an mp_int. + * + * a A single precision integer. + * r A multi-precision integer. + */ +static int sp_256_to_mp(sp_digit* a, mp_int* r) +{ + int err; + + err = mp_grow(r, (256 + DIGIT_BIT - 1) / DIGIT_BIT); + if (err == MP_OKAY) { +#if DIGIT_BIT == 64 + XMEMCPY(r->dp, a, sizeof(sp_digit) * 4); + r->used = 4; + mp_clamp(r); +#elif DIGIT_BIT < 64 + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 4; i++) { + r->dp[j] |= a[i] << s; + r->dp[j] &= (1l << DIGIT_BIT) - 1; + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + while (s + DIGIT_BIT <= 64) { + s += DIGIT_BIT; + r->dp[j] &= (1l << DIGIT_BIT) - 1; + r->dp[++j] = a[i] >> s; + } + s = 64 - s; + } + r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#else + int i, j = 0, s = 0; + + r->dp[0] = 0; + for (i = 0; i < 4; i++) { + r->dp[j] |= ((mp_digit)a[i]) << s; + if (s + 64 >= DIGIT_BIT) { + #if DIGIT_BIT < 64 + r->dp[j] &= (1l << DIGIT_BIT) - 1; + #endif + s = DIGIT_BIT - s; + r->dp[++j] = a[i] >> s; + s = 64 - s; + } + else + s += 64; + } + r->used = (256 + DIGIT_BIT - 1) / DIGIT_BIT; + mp_clamp(r); +#endif + } + + return err; +} + +/* Convert a point of type sp_point to type ecc_point. + * + * p Point of type sp_point. + * pm Point of type ecc_point (result). + * returns MEMORY_E when allocation of memory in ecc_point fails otherwise + * MP_OKAY. + */ +static int sp_256_point_to_ecc_point_4(sp_point* p, ecc_point* pm) +{ + int err; + + err = sp_256_to_mp(p->x, pm->x); + if (err == MP_OKAY) + err = sp_256_to_mp(p->y, pm->y); + if (err == MP_OKAY) + err = sp_256_to_mp(p->z, pm->z); + + return err; +} + +extern void sp_256_cond_copy_4(sp_digit* r, sp_digit* a, sp_digit m); +extern int64_t sp_256_cmp_4(sp_digit* a, sp_digit* b); +/* Normalize the values in each word to 64. + * + * a Array of sp_digit to normalize. + */ +#define sp_256_norm_4(a) + +extern sp_digit sp_256_cond_sub_4(sp_digit* r, sp_digit* a, sp_digit* b, sp_digit m); +extern sp_digit sp_256_sub_4(sp_digit* r, const sp_digit* a, const sp_digit* b); +#define sp_256_mont_reduce_order_4 sp_256_mont_reduce_4 + +extern void sp_256_mont_reduce_4(sp_digit* a, sp_digit* m, sp_digit mp); +extern void sp_256_mont_mul_4(sp_digit* r, sp_digit* a, sp_digit* b, sp_digit* m, sp_digit mp); +extern void sp_256_mont_sqr_4(sp_digit* r, sp_digit* a, sp_digit* m, sp_digit mp); +#if !defined(WOLFSSL_SP_SMALL) || defined(HAVE_COMP_KEY) +/* Square the Montgomery form number a number of times. (r = a ^ n mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * n Number of times to square. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_256_mont_sqr_n_4(sp_digit* r, sp_digit* a, int n, + sp_digit* m, sp_digit mp) +{ + sp_256_mont_sqr_4(r, a, m, mp); + for (; n > 1; n--) + sp_256_mont_sqr_4(r, r, m, mp); +} + +#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */ +#ifdef WOLFSSL_SP_SMALL +/* Mod-2 for the P256 curve. */ +static const uint64_t p256_mod_2[4] = { + 0xfffffffffffffffd,0x00000000ffffffff,0x0000000000000000, + 0xffffffff00000001 +}; +#endif /* !WOLFSSL_SP_SMALL */ + +/* Invert the number, in Montgomery form, modulo the modulus (prime) of the + * P256 curve. (r = 1 / a mod m) + * + * r Inverse result. + * a Number to invert. + * td Temporary data. + */ +static void sp_256_mont_inv_4(sp_digit* r, sp_digit* a, sp_digit* td) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* t = td; + int i; + + XMEMCPY(t, a, sizeof(sp_digit) * 4); + for (i=254; i>=0; i--) { + sp_256_mont_sqr_4(t, t, p256_mod, p256_mp_mod); + if (p256_mod_2[i / 64] & ((sp_digit)1 << (i % 64))) + sp_256_mont_mul_4(t, t, a, p256_mod, p256_mp_mod); + } + XMEMCPY(r, t, sizeof(sp_digit) * 4); +#else + sp_digit* t = td; + sp_digit* t2 = td + 2 * 4; + sp_digit* t3 = td + 4 * 4; + + /* t = a^2 */ + sp_256_mont_sqr_4(t, a, p256_mod, p256_mp_mod); + /* t = a^3 = t * a */ + sp_256_mont_mul_4(t, t, a, p256_mod, p256_mp_mod); + /* t2= a^c = t ^ 2 ^ 2 */ + sp_256_mont_sqr_n_4(t2, t, 2, p256_mod, p256_mp_mod); + /* t3= a^d = t2 * a */ + sp_256_mont_mul_4(t3, t2, a, p256_mod, p256_mp_mod); + /* t = a^f = t2 * t */ + sp_256_mont_mul_4(t, t2, t, p256_mod, p256_mp_mod); + /* t2= a^f0 = t ^ 2 ^ 4 */ + sp_256_mont_sqr_n_4(t2, t, 4, p256_mod, p256_mp_mod); + /* t3= a^fd = t2 * t3 */ + sp_256_mont_mul_4(t3, t2, t3, p256_mod, p256_mp_mod); + /* t = a^ff = t2 * t */ + sp_256_mont_mul_4(t, t2, t, p256_mod, p256_mp_mod); + /* t2= a^ff00 = t ^ 2 ^ 8 */ + sp_256_mont_sqr_n_4(t2, t, 8, p256_mod, p256_mp_mod); + /* t3= a^fffd = t2 * t3 */ + sp_256_mont_mul_4(t3, t2, t3, p256_mod, p256_mp_mod); + /* t = a^ffff = t2 * t */ + sp_256_mont_mul_4(t, t2, t, p256_mod, p256_mp_mod); + /* t2= a^ffff0000 = t ^ 2 ^ 16 */ + sp_256_mont_sqr_n_4(t2, t, 16, p256_mod, p256_mp_mod); + /* t3= a^fffffffd = t2 * t3 */ + sp_256_mont_mul_4(t3, t2, t3, p256_mod, p256_mp_mod); + /* t = a^ffffffff = t2 * t */ + sp_256_mont_mul_4(t, t2, t, p256_mod, p256_mp_mod); + /* t = a^ffffffff00000000 = t ^ 2 ^ 32 */ + sp_256_mont_sqr_n_4(t2, t, 32, p256_mod, p256_mp_mod); + /* t2= a^ffffffffffffffff = t2 * t */ + sp_256_mont_mul_4(t, t2, t, p256_mod, p256_mp_mod); + /* t2= a^ffffffff00000001 = t2 * a */ + sp_256_mont_mul_4(t2, t2, a, p256_mod, p256_mp_mod); + /* t2= a^ffffffff000000010000000000000000000000000000000000000000 + * = t2 ^ 2 ^ 160 */ + sp_256_mont_sqr_n_4(t2, t2, 160, p256_mod, p256_mp_mod); + /* t2= a^ffffffff00000001000000000000000000000000ffffffffffffffff + * = t2 * t */ + sp_256_mont_mul_4(t2, t2, t, p256_mod, p256_mp_mod); + /* t2= a^ffffffff00000001000000000000000000000000ffffffffffffffff00000000 + * = t2 ^ 2 ^ 32 */ + sp_256_mont_sqr_n_4(t2, t2, 32, p256_mod, p256_mp_mod); + /* r = a^ffffffff00000001000000000000000000000000fffffffffffffffffffffffd + * = t2 * t3 */ + sp_256_mont_mul_4(r, t2, t3, p256_mod, p256_mp_mod); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Map the Montgomery form projective co-ordinate point to an affine point. + * + * r Resulting affine co-ordinate point. + * p Montgomery form projective co-ordinate point. + * t Temporary ordinate data. + */ +static void sp_256_map_4(sp_point* r, sp_point* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*4; + int64_t n; + + sp_256_mont_inv_4(t1, p->z, t + 2*4); + + sp_256_mont_sqr_4(t2, t1, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t1, t2, t1, p256_mod, p256_mp_mod); + + /* x /= z^2 */ + sp_256_mont_mul_4(r->x, p->x, t2, p256_mod, p256_mp_mod); + XMEMSET(r->x + 4, 0, sizeof(r->x) / 2); + sp_256_mont_reduce_4(r->x, p256_mod, p256_mp_mod); + /* Reduce x to less than modulus */ + n = sp_256_cmp_4(r->x, p256_mod); + sp_256_cond_sub_4(r->x, r->x, p256_mod, 0 - (n >= 0)); + sp_256_norm_4(r->x); + + /* y /= z^3 */ + sp_256_mont_mul_4(r->y, p->y, t1, p256_mod, p256_mp_mod); + XMEMSET(r->y + 4, 0, sizeof(r->y) / 2); + sp_256_mont_reduce_4(r->y, p256_mod, p256_mp_mod); + /* Reduce y to less than modulus */ + n = sp_256_cmp_4(r->y, p256_mod); + sp_256_cond_sub_4(r->y, r->y, p256_mod, 0 - (n >= 0)); + sp_256_norm_4(r->y); + + XMEMSET(r->z, 0, sizeof(r->z)); + r->z[0] = 1; + +} + +extern void sp_256_mont_add_4(sp_digit* r, sp_digit* a, sp_digit* b, sp_digit* m); +extern void sp_256_mont_dbl_4(sp_digit* r, sp_digit* a, sp_digit* m); +extern void sp_256_mont_tpl_4(sp_digit* r, sp_digit* a, sp_digit* m); +extern void sp_256_mont_sub_4(sp_digit* r, sp_digit* a, sp_digit* b, sp_digit* m); +extern void sp_256_div2_4(sp_digit* r, const sp_digit* a, const sp_digit* m); +/* Double the Montgomery form projective point p. + * + * r Result of doubling point. + * p Point to double. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_dbl_4(sp_point* r, sp_point* p, sp_digit* t) +{ + sp_point* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*4; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* When infinity don't double point passed in - constant time. */ + rp[0] = r; + rp[1] = (sp_point*)t; + XMEMSET(rp[1], 0, sizeof(sp_point)); + x = rp[p->infinity]->x; + y = rp[p->infinity]->y; + z = rp[p->infinity]->z; + /* Put point to double into result - good for infinty. */ + if (r != p) { + for (i=0; i<4; i++) + r->x[i] = p->x[i]; + for (i=0; i<4; i++) + r->y[i] = p->y[i]; + for (i=0; i<4; i++) + r->z[i] = p->z[i]; + r->infinity = p->infinity; + } + + /* T1 = Z * Z */ + sp_256_mont_sqr_4(t1, z, p256_mod, p256_mp_mod); + /* Z = Y * Z */ + sp_256_mont_mul_4(z, y, z, p256_mod, p256_mp_mod); + /* Z = 2Z */ + sp_256_mont_dbl_4(z, z, p256_mod); + /* T2 = X - T1 */ + sp_256_mont_sub_4(t2, x, t1, p256_mod); + /* T1 = X + T1 */ + sp_256_mont_add_4(t1, x, t1, p256_mod); + /* T2 = T1 * T2 */ + sp_256_mont_mul_4(t2, t1, t2, p256_mod, p256_mp_mod); + /* T1 = 3T2 */ + sp_256_mont_tpl_4(t1, t2, p256_mod); + /* Y = 2Y */ + sp_256_mont_dbl_4(y, y, p256_mod); + /* Y = Y * Y */ + sp_256_mont_sqr_4(y, y, p256_mod, p256_mp_mod); + /* T2 = Y * Y */ + sp_256_mont_sqr_4(t2, y, p256_mod, p256_mp_mod); + /* T2 = T2/2 */ + sp_256_div2_4(t2, t2, p256_mod); + /* Y = Y * X */ + sp_256_mont_mul_4(y, y, x, p256_mod, p256_mp_mod); + /* X = T1 * T1 */ + sp_256_mont_mul_4(x, t1, t1, p256_mod, p256_mp_mod); + /* X = X - Y */ + sp_256_mont_sub_4(x, x, y, p256_mod); + /* X = X - Y */ + sp_256_mont_sub_4(x, x, y, p256_mod); + /* Y = Y - X */ + sp_256_mont_sub_4(y, y, x, p256_mod); + /* Y = Y * T1 */ + sp_256_mont_mul_4(y, y, t1, p256_mod, p256_mp_mod); + /* Y = Y - T2 */ + sp_256_mont_sub_4(y, y, t2, p256_mod); + +} + +/* Double the Montgomery form projective point p a number of times. + * + * r Result of repeated doubling of point. + * p Point to double. + * n Number of times to double + * t Temporary ordinate data. + */ +static void sp_256_proj_point_dbl_n_4(sp_point* r, sp_point* p, int n, + sp_digit* t) +{ + sp_point* rp[2]; + sp_digit* w = t; + sp_digit* a = t + 2*4; + sp_digit* b = t + 4*4; + sp_digit* t1 = t + 6*4; + sp_digit* t2 = t + 8*4; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + rp[0] = r; + rp[1] = (sp_point*)t; + XMEMSET(rp[1], 0, sizeof(sp_point)); + x = rp[p->infinity]->x; + y = rp[p->infinity]->y; + z = rp[p->infinity]->z; + if (r != p) { + for (i=0; i<4; i++) + r->x[i] = p->x[i]; + for (i=0; i<4; i++) + r->y[i] = p->y[i]; + for (i=0; i<4; i++) + r->z[i] = p->z[i]; + r->infinity = p->infinity; + } + + /* Y = 2*Y */ + sp_256_mont_dbl_4(y, y, p256_mod); + /* W = Z^4 */ + sp_256_mont_sqr_4(w, z, p256_mod, p256_mp_mod); + sp_256_mont_sqr_4(w, w, p256_mod, p256_mp_mod); + while (n--) { + /* A = 3*(X^2 - W) */ + sp_256_mont_sqr_4(t1, x, p256_mod, p256_mp_mod); + sp_256_mont_sub_4(t1, t1, w, p256_mod); + sp_256_mont_tpl_4(a, t1, p256_mod); + /* B = X*Y^2 */ + sp_256_mont_sqr_4(t2, y, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(b, t2, x, p256_mod, p256_mp_mod); + /* X = A^2 - 2B */ + sp_256_mont_sqr_4(x, a, p256_mod, p256_mp_mod); + sp_256_mont_dbl_4(t1, b, p256_mod); + sp_256_mont_sub_4(x, x, t1, p256_mod); + /* Z = Z*Y */ + sp_256_mont_mul_4(z, z, y, p256_mod, p256_mp_mod); + /* t2 = Y^4 */ + sp_256_mont_sqr_4(t2, t2, p256_mod, p256_mp_mod); + if (n) { + /* W = W*Y^4 */ + sp_256_mont_mul_4(w, w, t2, p256_mod, p256_mp_mod); + } + /* y = 2*A*(B - X) - Y^4 */ + sp_256_mont_sub_4(y, b, x, p256_mod); + sp_256_mont_mul_4(y, y, a, p256_mod, p256_mp_mod); + sp_256_mont_dbl_4(y, y, p256_mod); + sp_256_mont_sub_4(y, y, t2, p256_mod); + } + /* Y = Y/2 */ + sp_256_div2_4(y, y, p256_mod); +} + +/* Compare two numbers to determine if they are equal. + * Constant time implementation. + * + * a First number to compare. + * b Second number to compare. + * returns 1 when equal and 0 otherwise. + */ +static int sp_256_cmp_equal_4(const sp_digit* a, const sp_digit* b) +{ + return ((a[0] ^ b[0]) | (a[1] ^ b[1]) | (a[2] ^ b[2]) | (a[3] ^ b[3])) == 0; +} + +/* Add two Montgomery form projective points. + * + * r Result of addition. + * p Frist point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_add_4(sp_point* r, sp_point* p, sp_point* q, + sp_digit* t) +{ + sp_point* ap[2]; + sp_point* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*4; + sp_digit* t3 = t + 4*4; + sp_digit* t4 = t + 6*4; + sp_digit* t5 = t + 8*4; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + sp_point* a = p; + p = q; + q = a; + } + + /* Check double */ + sp_256_sub_4(t1, p256_mod, q->y); + sp_256_norm_4(t1); + if (sp_256_cmp_equal_4(p->x, q->x) & sp_256_cmp_equal_4(p->z, q->z) & + (sp_256_cmp_equal_4(p->y, q->y) | sp_256_cmp_equal_4(p->y, t1))) { + sp_256_proj_point_dbl_4(r, p, t); + } + else { + rp[0] = r; + rp[1] = (sp_point*)t; + XMEMSET(rp[1], 0, sizeof(sp_point)); + x = rp[p->infinity | q->infinity]->x; + y = rp[p->infinity | q->infinity]->y; + z = rp[p->infinity | q->infinity]->z; + + ap[0] = p; + ap[1] = q; + for (i=0; i<4; i++) + r->x[i] = ap[p->infinity]->x[i]; + for (i=0; i<4; i++) + r->y[i] = ap[p->infinity]->y[i]; + for (i=0; i<4; i++) + r->z[i] = ap[p->infinity]->z[i]; + r->infinity = ap[p->infinity]->infinity; + + /* U1 = X1*Z2^2 */ + sp_256_mont_sqr_4(t1, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t3, t1, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t1, t1, x, p256_mod, p256_mp_mod); + /* U2 = X2*Z1^2 */ + sp_256_mont_sqr_4(t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t4, t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t2, t2, q->x, p256_mod, p256_mp_mod); + /* S1 = Y1*Z2^3 */ + sp_256_mont_mul_4(t3, t3, y, p256_mod, p256_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_256_mont_mul_4(t4, t4, q->y, p256_mod, p256_mp_mod); + /* H = U2 - U1 */ + sp_256_mont_sub_4(t2, t2, t1, p256_mod); + /* R = S2 - S1 */ + sp_256_mont_sub_4(t4, t4, t3, p256_mod); + /* Z3 = H*Z1*Z2 */ + sp_256_mont_mul_4(z, z, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(z, z, t2, p256_mod, p256_mp_mod); + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_256_mont_sqr_4(x, t4, p256_mod, p256_mp_mod); + sp_256_mont_sqr_4(t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(y, t1, t5, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t5, t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_sub_4(x, x, t5, p256_mod); + sp_256_mont_dbl_4(t1, y, p256_mod); + sp_256_mont_sub_4(x, x, t1, p256_mod); + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_256_mont_sub_4(y, y, x, p256_mod); + sp_256_mont_mul_4(y, y, t4, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t5, t5, t3, p256_mod, p256_mp_mod); + sp_256_mont_sub_4(y, y, t5, p256_mod); + } +} + +/* Double the Montgomery form projective point p a number of times. + * + * r Result of repeated doubling of point. + * p Point to double. + * n Number of times to double + * t Temporary ordinate data. + */ +static void sp_256_proj_point_dbl_n_store_4(sp_point* r, sp_point* p, + int n, int m, sp_digit* t) +{ + sp_digit* w = t; + sp_digit* a = t + 2*4; + sp_digit* b = t + 4*4; + sp_digit* t1 = t + 6*4; + sp_digit* t2 = t + 8*4; + sp_digit* x = r[2*m].x; + sp_digit* y = r[(1<x[i]; + for (i=0; i<4; i++) + y[i] = p->y[i]; + for (i=0; i<4; i++) + z[i] = p->z[i]; + + /* Y = 2*Y */ + sp_256_mont_dbl_4(y, y, p256_mod); + /* W = Z^4 */ + sp_256_mont_sqr_4(w, z, p256_mod, p256_mp_mod); + sp_256_mont_sqr_4(w, w, p256_mod, p256_mp_mod); + for (i=1; i<=n; i++) { + /* A = 3*(X^2 - W) */ + sp_256_mont_sqr_4(t1, x, p256_mod, p256_mp_mod); + sp_256_mont_sub_4(t1, t1, w, p256_mod); + sp_256_mont_tpl_4(a, t1, p256_mod); + /* B = X*Y^2 */ + sp_256_mont_sqr_4(t2, y, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(b, t2, x, p256_mod, p256_mp_mod); + x = r[(1<x; + sp_digit* y = ra->y; + sp_digit* z = ra->z; + sp_digit* xs = rs->x; + sp_digit* ys = rs->y; + sp_digit* zs = rs->z; + + + XMEMCPY(x, p->x, sizeof(p->x) / 2); + XMEMCPY(y, p->y, sizeof(p->y) / 2); + XMEMCPY(z, p->z, sizeof(p->z) / 2); + ra->infinity = 0; + rs->infinity = 0; + + /* U1 = X1*Z2^2 */ + sp_256_mont_sqr_4(t1, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t3, t1, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t1, t1, x, p256_mod, p256_mp_mod); + /* U2 = X2*Z1^2 */ + sp_256_mont_sqr_4(t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t4, t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t2, t2, q->x, p256_mod, p256_mp_mod); + /* S1 = Y1*Z2^3 */ + sp_256_mont_mul_4(t3, t3, y, p256_mod, p256_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_256_mont_mul_4(t4, t4, q->y, p256_mod, p256_mp_mod); + /* H = U2 - U1 */ + sp_256_mont_sub_4(t2, t2, t1, p256_mod); + /* RS = S2 + S1 */ + sp_256_mont_add_4(t6, t4, t3, p256_mod); + /* R = S2 - S1 */ + sp_256_mont_sub_4(t4, t4, t3, p256_mod); + /* Z3 = H*Z1*Z2 */ + /* ZS = H*Z1*Z2 */ + sp_256_mont_mul_4(z, z, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(z, z, t2, p256_mod, p256_mp_mod); + XMEMCPY(zs, z, sizeof(p->z)/2); + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + /* XS = RS^2 - H^3 - 2*U1*H^2 */ + sp_256_mont_sqr_4(x, t4, p256_mod, p256_mp_mod); + sp_256_mont_sqr_4(xs, t6, p256_mod, p256_mp_mod); + sp_256_mont_sqr_4(t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(y, t1, t5, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t5, t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_sub_4(x, x, t5, p256_mod); + sp_256_mont_sub_4(xs, xs, t5, p256_mod); + sp_256_mont_dbl_4(t1, y, p256_mod); + sp_256_mont_sub_4(x, x, t1, p256_mod); + sp_256_mont_sub_4(xs, xs, t1, p256_mod); + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + /* YS = -RS*(U1*H^2 - XS) - S1*H^3 */ + sp_256_mont_sub_4(ys, y, xs, p256_mod); + sp_256_mont_sub_4(y, y, x, p256_mod); + sp_256_mont_mul_4(y, y, t4, p256_mod, p256_mp_mod); + sp_256_sub_4(t6, p256_mod, t6); + sp_256_mont_mul_4(ys, ys, t6, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t5, t5, t3, p256_mod, p256_mp_mod); + sp_256_mont_sub_4(y, y, t5, p256_mod); + sp_256_mont_sub_4(ys, ys, t5, p256_mod); +} + +/* Structure used to describe recoding of scalar multiplication. */ +typedef struct ecc_recode { + /* Index into pre-computation table. */ + uint8_t i; + /* Use the negative of the point. */ + uint8_t neg; +} ecc_recode; + +/* The index into pre-computation table to use. */ +static uint8_t recode_index_4_6[66] = { + 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, 26, 27, 28, 29, 30, 31, + 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, + 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, + 0, 1, +}; + +/* Whether to negate y-ordinate. */ +static uint8_t recode_neg_4_6[66] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, +}; + +/* Recode the scalar for multiplication using pre-computed values and + * subtraction. + * + * k Scalar to multiply by. + * v Vector of operations to peform. + */ +static void sp_256_ecc_recode_6_4(sp_digit* k, ecc_recode* v) +{ + int i, j; + uint8_t y; + int carry = 0; + int o; + sp_digit n; + + j = 0; + n = k[j]; + o = 0; + for (i=0; i<43; i++) { + y = n; + if (o + 6 < 64) { + y &= 0x3f; + n >>= 6; + o += 6; + } + else if (o + 6 == 64) { + n >>= 6; + if (++j < 4) + n = k[j]; + o = 0; + } + else if (++j < 4) { + n = k[j]; + y |= (n << (64 - o)) & 0x3f; + o -= 58; + n >>= o; + } + + y += carry; + v[i].i = recode_index_4_6[y]; + v[i].neg = recode_neg_4_6[y]; + carry = (y >> 6) + v[i].neg; + } +} + +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_win_add_sub_4(sp_point* r, sp_point* g, + sp_digit* k, int map, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point td[33]; + sp_point rtd, pd; + sp_digit tmpd[2 * 4 * 6]; +#endif + sp_point* t; + sp_point* rt; + sp_point* p = NULL; + sp_digit* tmp; + sp_digit* negy; + int i; + ecc_recode v[43]; + int err; + + (void)heap; + + err = sp_ecc_point_new(heap, rtd, rt); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + t = (sp_point*)XMALLOC(sizeof(sp_point) * 33, heap, DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 6, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; +#else + t = td; + tmp = tmpd; +#endif + + + if (err == MP_OKAY) { + /* t[0] = {0, 0, 1} * norm */ + XMEMSET(&t[0], 0, sizeof(t[0])); + t[0].infinity = 1; + /* t[1] = {g->x, g->y, g->z} * norm */ + err = sp_256_mod_mul_norm_4(t[1].x, g->x, p256_mod); + } + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_4(t[1].y, g->y, p256_mod); + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_4(t[1].z, g->z, p256_mod); + + if (err == MP_OKAY) { + t[1].infinity = 0; + /* t[2] ... t[32] */ + sp_256_proj_point_dbl_n_store_4(t, &t[ 1], 5, 1, tmp); + sp_256_proj_point_add_4(&t[ 3], &t[ 2], &t[ 1], tmp); + sp_256_proj_point_dbl_4(&t[ 6], &t[ 3], tmp); + sp_256_proj_point_add_sub_4(&t[ 7], &t[ 5], &t[ 6], &t[ 1], tmp); + sp_256_proj_point_dbl_4(&t[10], &t[ 5], tmp); + sp_256_proj_point_add_sub_4(&t[11], &t[ 9], &t[10], &t[ 1], tmp); + sp_256_proj_point_dbl_4(&t[12], &t[ 6], tmp); + sp_256_proj_point_dbl_4(&t[14], &t[ 7], tmp); + sp_256_proj_point_add_sub_4(&t[15], &t[13], &t[14], &t[ 1], tmp); + sp_256_proj_point_dbl_4(&t[18], &t[ 9], tmp); + sp_256_proj_point_add_sub_4(&t[19], &t[17], &t[18], &t[ 1], tmp); + sp_256_proj_point_dbl_4(&t[20], &t[10], tmp); + sp_256_proj_point_dbl_4(&t[22], &t[11], tmp); + sp_256_proj_point_add_sub_4(&t[23], &t[21], &t[22], &t[ 1], tmp); + sp_256_proj_point_dbl_4(&t[24], &t[12], tmp); + sp_256_proj_point_dbl_4(&t[26], &t[13], tmp); + sp_256_proj_point_add_sub_4(&t[27], &t[25], &t[26], &t[ 1], tmp); + sp_256_proj_point_dbl_4(&t[28], &t[14], tmp); + sp_256_proj_point_dbl_4(&t[30], &t[15], tmp); + sp_256_proj_point_add_sub_4(&t[31], &t[29], &t[30], &t[ 1], tmp); + + negy = t[0].y; + + sp_256_ecc_recode_6_4(k, v); + + i = 42; + XMEMCPY(rt, &t[v[i].i], sizeof(sp_point)); + for (--i; i>=0; i--) { + sp_256_proj_point_dbl_n_4(rt, rt, 6, tmp); + + XMEMCPY(p, &t[v[i].i], sizeof(sp_point)); + sp_256_sub_4(negy, p256_mod, p->y); + sp_256_cond_copy_4(p->y, negy, (sp_digit)0 - v[i].neg); + sp_256_proj_point_add_4(rt, rt, p, tmp); + } + + if (map) + sp_256_map_4(r, rt, tmp); + else + XMEMCPY(r, rt, sizeof(sp_point)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + if (tmp != NULL) + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p, 0, heap); + sp_ecc_point_free(rt, 0, heap); + + return err; +} + +#ifdef HAVE_INTEL_AVX2 +extern void sp_256_mont_mul_avx2_4(sp_digit* r, sp_digit* a, sp_digit* b, sp_digit* m, sp_digit mp); +extern void sp_256_mont_sqr_avx2_4(sp_digit* r, sp_digit* a, sp_digit* m, sp_digit mp); +#if !defined(WOLFSSL_SP_SMALL) || defined(HAVE_COMP_KEY) +/* Square the Montgomery form number a number of times. (r = a ^ n mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * n Number of times to square. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +static void sp_256_mont_sqr_n_avx2_4(sp_digit* r, sp_digit* a, int n, + sp_digit* m, sp_digit mp) +{ + sp_256_mont_sqr_avx2_4(r, a, m, mp); + for (; n > 1; n--) + sp_256_mont_sqr_avx2_4(r, r, m, mp); +} + +#endif /* !WOLFSSL_SP_SMALL || HAVE_COMP_KEY */ + +/* Invert the number, in Montgomery form, modulo the modulus (prime) of the + * P256 curve. (r = 1 / a mod m) + * + * r Inverse result. + * a Number to invert. + * td Temporary data. + */ +static void sp_256_mont_inv_avx2_4(sp_digit* r, sp_digit* a, sp_digit* td) +{ +#ifdef WOLFSSL_SP_SMALL + sp_digit* t = td; + int i; + + XMEMCPY(t, a, sizeof(sp_digit) * 4); + for (i=254; i>=0; i--) { + sp_256_mont_sqr_avx2_4(t, t, p256_mod, p256_mp_mod); + if (p256_mod_2[i / 64] & ((sp_digit)1 << (i % 64))) + sp_256_mont_mul_avx2_4(t, t, a, p256_mod, p256_mp_mod); + } + XMEMCPY(r, t, sizeof(sp_digit) * 4); +#else + sp_digit* t = td; + sp_digit* t2 = td + 2 * 4; + sp_digit* t3 = td + 4 * 4; + + /* t = a^2 */ + sp_256_mont_sqr_avx2_4(t, a, p256_mod, p256_mp_mod); + /* t = a^3 = t * a */ + sp_256_mont_mul_avx2_4(t, t, a, p256_mod, p256_mp_mod); + /* t2= a^c = t ^ 2 ^ 2 */ + sp_256_mont_sqr_n_avx2_4(t2, t, 2, p256_mod, p256_mp_mod); + /* t3= a^d = t2 * a */ + sp_256_mont_mul_avx2_4(t3, t2, a, p256_mod, p256_mp_mod); + /* t = a^f = t2 * t */ + sp_256_mont_mul_avx2_4(t, t2, t, p256_mod, p256_mp_mod); + /* t2= a^f0 = t ^ 2 ^ 4 */ + sp_256_mont_sqr_n_avx2_4(t2, t, 4, p256_mod, p256_mp_mod); + /* t3= a^fd = t2 * t3 */ + sp_256_mont_mul_avx2_4(t3, t2, t3, p256_mod, p256_mp_mod); + /* t = a^ff = t2 * t */ + sp_256_mont_mul_avx2_4(t, t2, t, p256_mod, p256_mp_mod); + /* t2= a^ff00 = t ^ 2 ^ 8 */ + sp_256_mont_sqr_n_avx2_4(t2, t, 8, p256_mod, p256_mp_mod); + /* t3= a^fffd = t2 * t3 */ + sp_256_mont_mul_avx2_4(t3, t2, t3, p256_mod, p256_mp_mod); + /* t = a^ffff = t2 * t */ + sp_256_mont_mul_avx2_4(t, t2, t, p256_mod, p256_mp_mod); + /* t2= a^ffff0000 = t ^ 2 ^ 16 */ + sp_256_mont_sqr_n_avx2_4(t2, t, 16, p256_mod, p256_mp_mod); + /* t3= a^fffffffd = t2 * t3 */ + sp_256_mont_mul_avx2_4(t3, t2, t3, p256_mod, p256_mp_mod); + /* t = a^ffffffff = t2 * t */ + sp_256_mont_mul_avx2_4(t, t2, t, p256_mod, p256_mp_mod); + /* t = a^ffffffff00000000 = t ^ 2 ^ 32 */ + sp_256_mont_sqr_n_avx2_4(t2, t, 32, p256_mod, p256_mp_mod); + /* t2= a^ffffffffffffffff = t2 * t */ + sp_256_mont_mul_avx2_4(t, t2, t, p256_mod, p256_mp_mod); + /* t2= a^ffffffff00000001 = t2 * a */ + sp_256_mont_mul_avx2_4(t2, t2, a, p256_mod, p256_mp_mod); + /* t2= a^ffffffff000000010000000000000000000000000000000000000000 + * = t2 ^ 2 ^ 160 */ + sp_256_mont_sqr_n_avx2_4(t2, t2, 160, p256_mod, p256_mp_mod); + /* t2= a^ffffffff00000001000000000000000000000000ffffffffffffffff + * = t2 * t */ + sp_256_mont_mul_avx2_4(t2, t2, t, p256_mod, p256_mp_mod); + /* t2= a^ffffffff00000001000000000000000000000000ffffffffffffffff00000000 + * = t2 ^ 2 ^ 32 */ + sp_256_mont_sqr_n_avx2_4(t2, t2, 32, p256_mod, p256_mp_mod); + /* r = a^ffffffff00000001000000000000000000000000fffffffffffffffffffffffd + * = t2 * t3 */ + sp_256_mont_mul_avx2_4(r, t2, t3, p256_mod, p256_mp_mod); +#endif /* WOLFSSL_SP_SMALL */ +} + +/* Map the Montgomery form projective co-ordinate point to an affine point. + * + * r Resulting affine co-ordinate point. + * p Montgomery form projective co-ordinate point. + * t Temporary ordinate data. + */ +static void sp_256_map_avx2_4(sp_point* r, sp_point* p, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2*4; + int64_t n; + + sp_256_mont_inv_avx2_4(t1, p->z, t + 2*4); + + sp_256_mont_sqr_avx2_4(t2, t1, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(t1, t2, t1, p256_mod, p256_mp_mod); + + /* x /= z^2 */ + sp_256_mont_mul_avx2_4(r->x, p->x, t2, p256_mod, p256_mp_mod); + XMEMSET(r->x + 4, 0, sizeof(r->x) / 2); + sp_256_mont_reduce_4(r->x, p256_mod, p256_mp_mod); + /* Reduce x to less than modulus */ + n = sp_256_cmp_4(r->x, p256_mod); + sp_256_cond_sub_4(r->x, r->x, p256_mod, 0 - (n >= 0)); + sp_256_norm_4(r->x); + + /* y /= z^3 */ + sp_256_mont_mul_avx2_4(r->y, p->y, t1, p256_mod, p256_mp_mod); + XMEMSET(r->y + 4, 0, sizeof(r->y) / 2); + sp_256_mont_reduce_4(r->y, p256_mod, p256_mp_mod); + /* Reduce y to less than modulus */ + n = sp_256_cmp_4(r->y, p256_mod); + sp_256_cond_sub_4(r->y, r->y, p256_mod, 0 - (n >= 0)); + sp_256_norm_4(r->y); + + XMEMSET(r->z, 0, sizeof(r->z)); + r->z[0] = 1; + +} + +/* Double the Montgomery form projective point p. + * + * r Result of doubling point. + * p Point to double. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_dbl_avx2_4(sp_point* r, sp_point* p, sp_digit* t) +{ + sp_point* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*4; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* When infinity don't double point passed in - constant time. */ + rp[0] = r; + rp[1] = (sp_point*)t; + XMEMSET(rp[1], 0, sizeof(sp_point)); + x = rp[p->infinity]->x; + y = rp[p->infinity]->y; + z = rp[p->infinity]->z; + /* Put point to double into result - good for infinty. */ + if (r != p) { + for (i=0; i<4; i++) + r->x[i] = p->x[i]; + for (i=0; i<4; i++) + r->y[i] = p->y[i]; + for (i=0; i<4; i++) + r->z[i] = p->z[i]; + r->infinity = p->infinity; + } + + /* T1 = Z * Z */ + sp_256_mont_sqr_avx2_4(t1, z, p256_mod, p256_mp_mod); + /* Z = Y * Z */ + sp_256_mont_mul_avx2_4(z, y, z, p256_mod, p256_mp_mod); + /* Z = 2Z */ + sp_256_mont_dbl_4(z, z, p256_mod); + /* T2 = X - T1 */ + sp_256_mont_sub_4(t2, x, t1, p256_mod); + /* T1 = X + T1 */ + sp_256_mont_add_4(t1, x, t1, p256_mod); + /* T2 = T1 * T2 */ + sp_256_mont_mul_avx2_4(t2, t1, t2, p256_mod, p256_mp_mod); + /* T1 = 3T2 */ + sp_256_mont_tpl_4(t1, t2, p256_mod); + /* Y = 2Y */ + sp_256_mont_dbl_4(y, y, p256_mod); + /* Y = Y * Y */ + sp_256_mont_sqr_avx2_4(y, y, p256_mod, p256_mp_mod); + /* T2 = Y * Y */ + sp_256_mont_sqr_avx2_4(t2, y, p256_mod, p256_mp_mod); + /* T2 = T2/2 */ + sp_256_div2_4(t2, t2, p256_mod); + /* Y = Y * X */ + sp_256_mont_mul_avx2_4(y, y, x, p256_mod, p256_mp_mod); + /* X = T1 * T1 */ + sp_256_mont_mul_avx2_4(x, t1, t1, p256_mod, p256_mp_mod); + /* X = X - Y */ + sp_256_mont_sub_4(x, x, y, p256_mod); + /* X = X - Y */ + sp_256_mont_sub_4(x, x, y, p256_mod); + /* Y = Y - X */ + sp_256_mont_sub_4(y, y, x, p256_mod); + /* Y = Y * T1 */ + sp_256_mont_mul_avx2_4(y, y, t1, p256_mod, p256_mp_mod); + /* Y = Y - T2 */ + sp_256_mont_sub_4(y, y, t2, p256_mod); + +} + +/* Double the Montgomery form projective point p a number of times. + * + * r Result of repeated doubling of point. + * p Point to double. + * n Number of times to double + * t Temporary ordinate data. + */ +static void sp_256_proj_point_dbl_n_avx2_4(sp_point* r, sp_point* p, int n, + sp_digit* t) +{ + sp_point* rp[2]; + sp_digit* w = t; + sp_digit* a = t + 2*4; + sp_digit* b = t + 4*4; + sp_digit* t1 = t + 6*4; + sp_digit* t2 = t + 8*4; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + rp[0] = r; + rp[1] = (sp_point*)t; + XMEMSET(rp[1], 0, sizeof(sp_point)); + x = rp[p->infinity]->x; + y = rp[p->infinity]->y; + z = rp[p->infinity]->z; + if (r != p) { + for (i=0; i<4; i++) + r->x[i] = p->x[i]; + for (i=0; i<4; i++) + r->y[i] = p->y[i]; + for (i=0; i<4; i++) + r->z[i] = p->z[i]; + r->infinity = p->infinity; + } + + /* Y = 2*Y */ + sp_256_mont_dbl_4(y, y, p256_mod); + /* W = Z^4 */ + sp_256_mont_sqr_avx2_4(w, z, p256_mod, p256_mp_mod); + sp_256_mont_sqr_avx2_4(w, w, p256_mod, p256_mp_mod); + while (n--) { + /* A = 3*(X^2 - W) */ + sp_256_mont_sqr_avx2_4(t1, x, p256_mod, p256_mp_mod); + sp_256_mont_sub_4(t1, t1, w, p256_mod); + sp_256_mont_tpl_4(a, t1, p256_mod); + /* B = X*Y^2 */ + sp_256_mont_sqr_avx2_4(t2, y, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(b, t2, x, p256_mod, p256_mp_mod); + /* X = A^2 - 2B */ + sp_256_mont_sqr_avx2_4(x, a, p256_mod, p256_mp_mod); + sp_256_mont_dbl_4(t1, b, p256_mod); + sp_256_mont_sub_4(x, x, t1, p256_mod); + /* Z = Z*Y */ + sp_256_mont_mul_avx2_4(z, z, y, p256_mod, p256_mp_mod); + /* t2 = Y^4 */ + sp_256_mont_sqr_avx2_4(t2, t2, p256_mod, p256_mp_mod); + if (n) { + /* W = W*Y^4 */ + sp_256_mont_mul_avx2_4(w, w, t2, p256_mod, p256_mp_mod); + } + /* y = 2*A*(B - X) - Y^4 */ + sp_256_mont_sub_4(y, b, x, p256_mod); + sp_256_mont_mul_avx2_4(y, y, a, p256_mod, p256_mp_mod); + sp_256_mont_dbl_4(y, y, p256_mod); + sp_256_mont_sub_4(y, y, t2, p256_mod); + } + /* Y = Y/2 */ + sp_256_div2_4(y, y, p256_mod); +} + +/* Add two Montgomery form projective points. + * + * r Result of addition. + * p Frist point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_add_avx2_4(sp_point* r, sp_point* p, sp_point* q, + sp_digit* t) +{ + sp_point* ap[2]; + sp_point* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*4; + sp_digit* t3 = t + 4*4; + sp_digit* t4 = t + 6*4; + sp_digit* t5 = t + 8*4; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* Ensure only the first point is the same as the result. */ + if (q == r) { + sp_point* a = p; + p = q; + q = a; + } + + /* Check double */ + sp_256_sub_4(t1, p256_mod, q->y); + sp_256_norm_4(t1); + if (sp_256_cmp_equal_4(p->x, q->x) & sp_256_cmp_equal_4(p->z, q->z) & + (sp_256_cmp_equal_4(p->y, q->y) | sp_256_cmp_equal_4(p->y, t1))) { + sp_256_proj_point_dbl_4(r, p, t); + } + else { + rp[0] = r; + rp[1] = (sp_point*)t; + XMEMSET(rp[1], 0, sizeof(sp_point)); + x = rp[p->infinity | q->infinity]->x; + y = rp[p->infinity | q->infinity]->y; + z = rp[p->infinity | q->infinity]->z; + + ap[0] = p; + ap[1] = q; + for (i=0; i<4; i++) + r->x[i] = ap[p->infinity]->x[i]; + for (i=0; i<4; i++) + r->y[i] = ap[p->infinity]->y[i]; + for (i=0; i<4; i++) + r->z[i] = ap[p->infinity]->z[i]; + r->infinity = ap[p->infinity]->infinity; + + /* U1 = X1*Z2^2 */ + sp_256_mont_sqr_avx2_4(t1, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(t3, t1, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(t1, t1, x, p256_mod, p256_mp_mod); + /* U2 = X2*Z1^2 */ + sp_256_mont_sqr_avx2_4(t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(t4, t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(t2, t2, q->x, p256_mod, p256_mp_mod); + /* S1 = Y1*Z2^3 */ + sp_256_mont_mul_avx2_4(t3, t3, y, p256_mod, p256_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_256_mont_mul_avx2_4(t4, t4, q->y, p256_mod, p256_mp_mod); + /* H = U2 - U1 */ + sp_256_mont_sub_4(t2, t2, t1, p256_mod); + /* R = S2 - S1 */ + sp_256_mont_sub_4(t4, t4, t3, p256_mod); + /* Z3 = H*Z1*Z2 */ + sp_256_mont_mul_avx2_4(z, z, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(z, z, t2, p256_mod, p256_mp_mod); + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + sp_256_mont_sqr_avx2_4(x, t4, p256_mod, p256_mp_mod); + sp_256_mont_sqr_avx2_4(t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(y, t1, t5, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(t5, t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_sub_4(x, x, t5, p256_mod); + sp_256_mont_dbl_4(t1, y, p256_mod); + sp_256_mont_sub_4(x, x, t1, p256_mod); + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + sp_256_mont_sub_4(y, y, x, p256_mod); + sp_256_mont_mul_avx2_4(y, y, t4, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(t5, t5, t3, p256_mod, p256_mp_mod); + sp_256_mont_sub_4(y, y, t5, p256_mod); + } +} + +/* Double the Montgomery form projective point p a number of times. + * + * r Result of repeated doubling of point. + * p Point to double. + * n Number of times to double + * t Temporary ordinate data. + */ +static void sp_256_proj_point_dbl_n_store_avx2_4(sp_point* r, sp_point* p, + int n, int m, sp_digit* t) +{ + sp_digit* w = t; + sp_digit* a = t + 2*4; + sp_digit* b = t + 4*4; + sp_digit* t1 = t + 6*4; + sp_digit* t2 = t + 8*4; + sp_digit* x = r[2*m].x; + sp_digit* y = r[(1<x[i]; + for (i=0; i<4; i++) + y[i] = p->y[i]; + for (i=0; i<4; i++) + z[i] = p->z[i]; + + /* Y = 2*Y */ + sp_256_mont_dbl_4(y, y, p256_mod); + /* W = Z^4 */ + sp_256_mont_sqr_avx2_4(w, z, p256_mod, p256_mp_mod); + sp_256_mont_sqr_avx2_4(w, w, p256_mod, p256_mp_mod); + for (i=1; i<=n; i++) { + /* A = 3*(X^2 - W) */ + sp_256_mont_sqr_avx2_4(t1, x, p256_mod, p256_mp_mod); + sp_256_mont_sub_4(t1, t1, w, p256_mod); + sp_256_mont_tpl_4(a, t1, p256_mod); + /* B = X*Y^2 */ + sp_256_mont_sqr_avx2_4(t2, y, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(b, t2, x, p256_mod, p256_mp_mod); + x = r[(1<x; + sp_digit* y = ra->y; + sp_digit* z = ra->z; + sp_digit* xs = rs->x; + sp_digit* ys = rs->y; + sp_digit* zs = rs->z; + + + XMEMCPY(x, p->x, sizeof(p->x) / 2); + XMEMCPY(y, p->y, sizeof(p->y) / 2); + XMEMCPY(z, p->z, sizeof(p->z) / 2); + ra->infinity = 0; + rs->infinity = 0; + + /* U1 = X1*Z2^2 */ + sp_256_mont_sqr_avx2_4(t1, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(t3, t1, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(t1, t1, x, p256_mod, p256_mp_mod); + /* U2 = X2*Z1^2 */ + sp_256_mont_sqr_avx2_4(t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(t4, t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(t2, t2, q->x, p256_mod, p256_mp_mod); + /* S1 = Y1*Z2^3 */ + sp_256_mont_mul_avx2_4(t3, t3, y, p256_mod, p256_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_256_mont_mul_avx2_4(t4, t4, q->y, p256_mod, p256_mp_mod); + /* H = U2 - U1 */ + sp_256_mont_sub_4(t2, t2, t1, p256_mod); + /* RS = S2 + S1 */ + sp_256_mont_add_4(t6, t4, t3, p256_mod); + /* R = S2 - S1 */ + sp_256_mont_sub_4(t4, t4, t3, p256_mod); + /* Z3 = H*Z1*Z2 */ + /* ZS = H*Z1*Z2 */ + sp_256_mont_mul_avx2_4(z, z, q->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(z, z, t2, p256_mod, p256_mp_mod); + XMEMCPY(zs, z, sizeof(p->z)/2); + /* X3 = R^2 - H^3 - 2*U1*H^2 */ + /* XS = RS^2 - H^3 - 2*U1*H^2 */ + sp_256_mont_sqr_avx2_4(x, t4, p256_mod, p256_mp_mod); + sp_256_mont_sqr_avx2_4(xs, t6, p256_mod, p256_mp_mod); + sp_256_mont_sqr_avx2_4(t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(y, t1, t5, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(t5, t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_sub_4(x, x, t5, p256_mod); + sp_256_mont_sub_4(xs, xs, t5, p256_mod); + sp_256_mont_dbl_4(t1, y, p256_mod); + sp_256_mont_sub_4(x, x, t1, p256_mod); + sp_256_mont_sub_4(xs, xs, t1, p256_mod); + /* Y3 = R*(U1*H^2 - X3) - S1*H^3 */ + /* YS = -RS*(U1*H^2 - XS) - S1*H^3 */ + sp_256_mont_sub_4(ys, y, xs, p256_mod); + sp_256_mont_sub_4(y, y, x, p256_mod); + sp_256_mont_mul_avx2_4(y, y, t4, p256_mod, p256_mp_mod); + sp_256_sub_4(t6, p256_mod, t6); + sp_256_mont_mul_avx2_4(ys, ys, t6, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(t5, t5, t3, p256_mod, p256_mp_mod); + sp_256_mont_sub_4(y, y, t5, p256_mod); + sp_256_mont_sub_4(ys, ys, t5, p256_mod); +} + +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_win_add_sub_avx2_4(sp_point* r, sp_point* g, + sp_digit* k, int map, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point td[33]; + sp_point rtd, pd; + sp_digit tmpd[2 * 4 * 6]; +#endif + sp_point* t; + sp_point* rt; + sp_point* p = NULL; + sp_digit* tmp; + sp_digit* negy; + int i; + ecc_recode v[43]; + int err; + + (void)heap; + + err = sp_ecc_point_new(heap, rtd, rt); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + t = (sp_point*)XMALLOC(sizeof(sp_point) * 33, heap, DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 6, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; +#else + t = td; + tmp = tmpd; +#endif + + + if (err == MP_OKAY) { + /* t[0] = {0, 0, 1} * norm */ + XMEMSET(&t[0], 0, sizeof(t[0])); + t[0].infinity = 1; + /* t[1] = {g->x, g->y, g->z} * norm */ + err = sp_256_mod_mul_norm_4(t[1].x, g->x, p256_mod); + } + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_4(t[1].y, g->y, p256_mod); + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_4(t[1].z, g->z, p256_mod); + + if (err == MP_OKAY) { + t[1].infinity = 0; + /* t[2] ... t[32] */ + sp_256_proj_point_dbl_n_store_avx2_4(t, &t[ 1], 5, 1, tmp); + sp_256_proj_point_add_avx2_4(&t[ 3], &t[ 2], &t[ 1], tmp); + sp_256_proj_point_dbl_avx2_4(&t[ 6], &t[ 3], tmp); + sp_256_proj_point_add_sub_avx2_4(&t[ 7], &t[ 5], &t[ 6], &t[ 1], tmp); + sp_256_proj_point_dbl_avx2_4(&t[10], &t[ 5], tmp); + sp_256_proj_point_add_sub_avx2_4(&t[11], &t[ 9], &t[10], &t[ 1], tmp); + sp_256_proj_point_dbl_avx2_4(&t[12], &t[ 6], tmp); + sp_256_proj_point_dbl_avx2_4(&t[14], &t[ 7], tmp); + sp_256_proj_point_add_sub_avx2_4(&t[15], &t[13], &t[14], &t[ 1], tmp); + sp_256_proj_point_dbl_avx2_4(&t[18], &t[ 9], tmp); + sp_256_proj_point_add_sub_avx2_4(&t[19], &t[17], &t[18], &t[ 1], tmp); + sp_256_proj_point_dbl_avx2_4(&t[20], &t[10], tmp); + sp_256_proj_point_dbl_avx2_4(&t[22], &t[11], tmp); + sp_256_proj_point_add_sub_avx2_4(&t[23], &t[21], &t[22], &t[ 1], tmp); + sp_256_proj_point_dbl_avx2_4(&t[24], &t[12], tmp); + sp_256_proj_point_dbl_avx2_4(&t[26], &t[13], tmp); + sp_256_proj_point_add_sub_avx2_4(&t[27], &t[25], &t[26], &t[ 1], tmp); + sp_256_proj_point_dbl_avx2_4(&t[28], &t[14], tmp); + sp_256_proj_point_dbl_avx2_4(&t[30], &t[15], tmp); + sp_256_proj_point_add_sub_avx2_4(&t[31], &t[29], &t[30], &t[ 1], tmp); + + negy = t[0].y; + + sp_256_ecc_recode_6_4(k, v); + + i = 42; + XMEMCPY(rt, &t[v[i].i], sizeof(sp_point)); + for (--i; i>=0; i--) { + sp_256_proj_point_dbl_n_avx2_4(rt, rt, 6, tmp); + + XMEMCPY(p, &t[v[i].i], sizeof(sp_point)); + sp_256_sub_4(negy, p256_mod, p->y); + sp_256_cond_copy_4(p->y, negy, (sp_digit)0 - v[i].neg); + sp_256_proj_point_add_avx2_4(rt, rt, p, tmp); + } + + if (map) + sp_256_map_avx2_4(r, rt, tmp); + else + XMEMCPY(r, rt, sizeof(sp_point)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); + if (tmp != NULL) + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p, 0, heap); + sp_ecc_point_free(rt, 0, heap); + + return err; +} + +#endif /* HAVE_INTEL_AVX2 */ +/* A table entry for pre-computed points. */ +typedef struct sp_table_entry { + sp_digit x[4]; + sp_digit y[4]; + byte infinity; +} sp_table_entry; + +#if defined(FP_ECC) || defined(WOLFSSL_SP_SMALL) +#endif /* FP_ECC || WOLFSSL_SP_SMALL */ +/* Add two Montgomery form projective points. The second point has a q value of + * one. + * Only the first point can be the same pointer as the result point. + * + * r Result of addition. + * p Frist point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_add_qz1_4(sp_point* r, sp_point* p, + sp_point* q, sp_digit* t) +{ + sp_point* ap[2]; + sp_point* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*4; + sp_digit* t3 = t + 4*4; + sp_digit* t4 = t + 6*4; + sp_digit* t5 = t + 8*4; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* Check double */ + sp_256_sub_4(t1, p256_mod, q->y); + sp_256_norm_4(t1); + if (sp_256_cmp_equal_4(p->x, q->x) & sp_256_cmp_equal_4(p->z, q->z) & + (sp_256_cmp_equal_4(p->y, q->y) | sp_256_cmp_equal_4(p->y, t1))) { + sp_256_proj_point_dbl_4(r, p, t); + } + else { + rp[0] = r; + rp[1] = (sp_point*)t; + XMEMSET(rp[1], 0, sizeof(sp_point)); + x = rp[p->infinity | q->infinity]->x; + y = rp[p->infinity | q->infinity]->y; + z = rp[p->infinity | q->infinity]->z; + + ap[0] = p; + ap[1] = q; + for (i=0; i<4; i++) + r->x[i] = ap[p->infinity]->x[i]; + for (i=0; i<4; i++) + r->y[i] = ap[p->infinity]->y[i]; + for (i=0; i<4; i++) + r->z[i] = ap[p->infinity]->z[i]; + r->infinity = ap[p->infinity]->infinity; + + /* U2 = X2*Z1^2 */ + sp_256_mont_sqr_4(t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t4, t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t2, t2, q->x, p256_mod, p256_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_256_mont_mul_4(t4, t4, q->y, p256_mod, p256_mp_mod); + /* H = U2 - X1 */ + sp_256_mont_sub_4(t2, t2, x, p256_mod); + /* R = S2 - Y1 */ + sp_256_mont_sub_4(t4, t4, y, p256_mod); + /* Z3 = H*Z1 */ + sp_256_mont_mul_4(z, z, t2, p256_mod, p256_mp_mod); + /* X3 = R^2 - H^3 - 2*X1*H^2 */ + sp_256_mont_sqr_4(t1, t4, p256_mod, p256_mp_mod); + sp_256_mont_sqr_4(t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t3, x, t5, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t5, t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_sub_4(x, t1, t5, p256_mod); + sp_256_mont_dbl_4(t1, t3, p256_mod); + sp_256_mont_sub_4(x, x, t1, p256_mod); + /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */ + sp_256_mont_sub_4(t3, t3, x, p256_mod); + sp_256_mont_mul_4(t3, t3, t4, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t5, t5, y, p256_mod, p256_mp_mod); + sp_256_mont_sub_4(y, t3, t5, p256_mod); + } +} + +#ifdef FP_ECC +/* Convert the projective point to affine. + * Ordinates are in Montgomery form. + * + * a Point to convert. + * t Temprorary data. + */ +static void sp_256_proj_to_affine_4(sp_point* a, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 4; + sp_digit* tmp = t + 4 * 4; + + sp_256_mont_inv_4(t1, a->z, tmp); + + sp_256_mont_sqr_4(t2, t1, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(t1, t2, t1, p256_mod, p256_mp_mod); + + sp_256_mont_mul_4(a->x, a->x, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(a->y, a->y, t1, p256_mod, p256_mp_mod); + XMEMCPY(a->z, p256_norm_mod, sizeof(p256_norm_mod)); +} + +/* Generate the pre-computed table of points for the base point. + * + * a The base point. + * table Place to store generated point data. + * tmp Temprorary data. + * heap Heap to use for allocation. + */ +static int sp_256_gen_stripe_table_4(sp_point* a, + sp_table_entry* table, sp_digit* tmp, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point td, s1d, s2d; +#endif + sp_point* t; + sp_point* s1 = NULL; + sp_point* s2 = NULL; + int i, j; + int err; + + (void)heap; + + err = sp_ecc_point_new(heap, td, t); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, s1d, s1); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, s2d, s2); + + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_4(t->x, a->x, p256_mod); + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_4(t->y, a->y, p256_mod); + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_4(t->z, a->z, p256_mod); + if (err == MP_OKAY) { + t->infinity = 0; + sp_256_proj_to_affine_4(t, tmp); + + XMEMCPY(s1->z, p256_norm_mod, sizeof(p256_norm_mod)); + s1->infinity = 0; + XMEMCPY(s2->z, p256_norm_mod, sizeof(p256_norm_mod)); + s2->infinity = 0; + + /* table[0] = {0, 0, infinity} */ + XMEMSET(&table[0], 0, sizeof(sp_table_entry)); + table[0].infinity = 1; + /* table[1] = Affine version of 'a' in Montgomery form */ + XMEMCPY(table[1].x, t->x, sizeof(table->x)); + XMEMCPY(table[1].y, t->y, sizeof(table->y)); + table[1].infinity = 0; + + for (i=1; i<8; i++) { + sp_256_proj_point_dbl_n_4(t, t, 32, tmp); + sp_256_proj_to_affine_4(t, tmp); + XMEMCPY(table[1<x, sizeof(table->x)); + XMEMCPY(table[1<y, sizeof(table->y)); + table[1<x, table[1<x)); + XMEMCPY(s1->y, table[1<y)); + for (j=(1<x, table[j-(1<x)); + XMEMCPY(s2->y, table[j-(1<y)); + sp_256_proj_point_add_qz1_4(t, s1, s2, tmp); + sp_256_proj_to_affine_4(t, tmp); + XMEMCPY(table[j].x, t->x, sizeof(table->x)); + XMEMCPY(table[j].y, t->y, sizeof(table->y)); + table[j].infinity = 0; + } + } + } + + sp_ecc_point_free(s2, 0, heap); + sp_ecc_point_free(s1, 0, heap); + sp_ecc_point_free( t, 0, heap); + + return err; +} + +#endif /* FP_ECC */ +#if defined(FP_ECC) || defined(WOLFSSL_SP_SMALL) +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_stripe_4(sp_point* r, sp_point* g, + sp_table_entry* table, sp_digit* k, int map, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point rtd; + sp_point pd; + sp_digit td[2 * 4 * 5]; +#endif + sp_point* rt; + sp_point* p = NULL; + sp_digit* t; + int i, j; + int y, x; + int err; + + (void)g; + (void)heap; + + err = sp_ecc_point_new(heap, rtd, rt); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 5, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#else + t = td; +#endif + + if (err == MP_OKAY) { + XMEMCPY(p->z, p256_norm_mod, sizeof(p256_norm_mod)); + XMEMCPY(rt->z, p256_norm_mod, sizeof(p256_norm_mod)); + + y = 0; + for (j=0,x=31; j<8; j++,x+=32) + y |= ((k[x / 64] >> (x % 64)) & 1) << j; + XMEMCPY(rt->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(rt->y, table[y].y, sizeof(table[y].y)); + rt->infinity = table[y].infinity; + for (i=30; i>=0; i--) { + y = 0; + for (j=0,x=i; j<8; j++,x+=32) + y |= ((k[x / 64] >> (x % 64)) & 1) << j; + + sp_256_proj_point_dbl_4(rt, rt, t); + XMEMCPY(p->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(p->y, table[y].y, sizeof(table[y].y)); + p->infinity = table[y].infinity; + sp_256_proj_point_add_qz1_4(rt, rt, p, t); + } + + if (map) + sp_256_map_4(r, rt, t); + else + XMEMCPY(r, rt, sizeof(sp_point)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p, 0, heap); + sp_ecc_point_free(rt, 0, heap); + + return err; +} + +#endif /* FP_ECC || WOLFSSL_SP_SMALL */ +#ifdef FP_ECC +#ifndef FP_ENTRIES + #define FP_ENTRIES 16 +#endif + +typedef struct sp_cache_t { + sp_digit x[4]; + sp_digit y[4]; + sp_table_entry table[256]; + uint32_t cnt; + int set; +} sp_cache_t; + +static THREAD_LS_T sp_cache_t sp_cache[FP_ENTRIES]; +static THREAD_LS_T int sp_cache_last = -1; +static THREAD_LS_T int sp_cache_inited = 0; + +#ifndef HAVE_THREAD_LS + static volatile int initCacheMutex = 0; + static wolfSSL_Mutex sp_cache_lock; +#endif + +static void sp_ecc_get_cache(sp_point* g, sp_cache_t** cache) +{ + int i, j; + uint32_t least; + + if (sp_cache_inited == 0) { + for (i=0; ix, sp_cache[i].x) & + sp_256_cmp_equal_4(g->y, sp_cache[i].y)) { + sp_cache[i].cnt++; + break; + } + } + + /* No match. */ + if (i == FP_ENTRIES) { + /* Find empty entry. */ + i = (sp_cache_last + 1) % FP_ENTRIES; + for (; i != sp_cache_last; i=(i+1)%FP_ENTRIES) { + if (!sp_cache[i].set) { + break; + } + } + + /* Evict least used. */ + if (i == sp_cache_last) { + least = sp_cache[0].cnt; + for (j=1; jx, sizeof(sp_cache[i].x)); + XMEMCPY(sp_cache[i].y, g->y, sizeof(sp_cache[i].y)); + sp_cache[i].set = 1; + sp_cache[i].cnt = 1; + } + + *cache = &sp_cache[i]; + sp_cache_last = i; +} +#endif /* FP_ECC */ + +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_4(sp_point* r, sp_point* g, sp_digit* k, + int map, void* heap) +{ +#ifndef FP_ECC + return sp_256_ecc_mulmod_win_add_sub_4(r, g, k, map, heap); +#else + sp_digit tmp[2 * 4 * 5]; + sp_cache_t* cache; + int err = MP_OKAY; + +#ifndef HAVE_THREAD_LS + if (initCacheMutex == 0) { + wc_InitMutex(&sp_cache_lock); + initCacheMutex = 1; + } + if (wc_LockMutex(&sp_cache_lock) != 0) + err = BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + if (err == MP_OKAY) { + sp_ecc_get_cache(g, &cache); + if (cache->cnt == 2) + sp_256_gen_stripe_table_4(g, cache->table, tmp, heap); + +#ifndef HAVE_THREAD_LS + wc_UnLockMutex(&sp_cache_lock); +#endif /* HAVE_THREAD_LS */ + + if (cache->cnt < 2) { + err = sp_256_ecc_mulmod_win_add_sub_4(r, g, k, map, heap); + } + else { + err = sp_256_ecc_mulmod_stripe_4(r, g, cache->table, k, + map, heap); + } + } + + return err; +#endif +} + +#ifdef HAVE_INTEL_AVX2 +#if defined(FP_ECC) || defined(WOLFSSL_SP_SMALL) +#endif /* FP_ECC || WOLFSSL_SP_SMALL */ +/* Add two Montgomery form projective points. The second point has a q value of + * one. + * Only the first point can be the same pointer as the result point. + * + * r Result of addition. + * p Frist point to add. + * q Second point to add. + * t Temporary ordinate data. + */ +static void sp_256_proj_point_add_qz1_avx2_4(sp_point* r, sp_point* p, + sp_point* q, sp_digit* t) +{ + sp_point* ap[2]; + sp_point* rp[2]; + sp_digit* t1 = t; + sp_digit* t2 = t + 2*4; + sp_digit* t3 = t + 4*4; + sp_digit* t4 = t + 6*4; + sp_digit* t5 = t + 8*4; + sp_digit* x; + sp_digit* y; + sp_digit* z; + int i; + + /* Check double */ + sp_256_sub_4(t1, p256_mod, q->y); + sp_256_norm_4(t1); + if (sp_256_cmp_equal_4(p->x, q->x) & sp_256_cmp_equal_4(p->z, q->z) & + (sp_256_cmp_equal_4(p->y, q->y) | sp_256_cmp_equal_4(p->y, t1))) { + sp_256_proj_point_dbl_4(r, p, t); + } + else { + rp[0] = r; + rp[1] = (sp_point*)t; + XMEMSET(rp[1], 0, sizeof(sp_point)); + x = rp[p->infinity | q->infinity]->x; + y = rp[p->infinity | q->infinity]->y; + z = rp[p->infinity | q->infinity]->z; + + ap[0] = p; + ap[1] = q; + for (i=0; i<4; i++) + r->x[i] = ap[p->infinity]->x[i]; + for (i=0; i<4; i++) + r->y[i] = ap[p->infinity]->y[i]; + for (i=0; i<4; i++) + r->z[i] = ap[p->infinity]->z[i]; + r->infinity = ap[p->infinity]->infinity; + + /* U2 = X2*Z1^2 */ + sp_256_mont_sqr_avx2_4(t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(t4, t2, z, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(t2, t2, q->x, p256_mod, p256_mp_mod); + /* S2 = Y2*Z1^3 */ + sp_256_mont_mul_avx2_4(t4, t4, q->y, p256_mod, p256_mp_mod); + /* H = U2 - X1 */ + sp_256_mont_sub_4(t2, t2, x, p256_mod); + /* R = S2 - Y1 */ + sp_256_mont_sub_4(t4, t4, y, p256_mod); + /* Z3 = H*Z1 */ + sp_256_mont_mul_avx2_4(z, z, t2, p256_mod, p256_mp_mod); + /* X3 = R^2 - H^3 - 2*X1*H^2 */ + sp_256_mont_sqr_avx2_4(t1, t4, p256_mod, p256_mp_mod); + sp_256_mont_sqr_avx2_4(t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(t3, x, t5, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(t5, t5, t2, p256_mod, p256_mp_mod); + sp_256_mont_sub_4(x, t1, t5, p256_mod); + sp_256_mont_dbl_4(t1, t3, p256_mod); + sp_256_mont_sub_4(x, x, t1, p256_mod); + /* Y3 = R*(X1*H^2 - X3) - Y1*H^3 */ + sp_256_mont_sub_4(t3, t3, x, p256_mod); + sp_256_mont_mul_avx2_4(t3, t3, t4, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(t5, t5, y, p256_mod, p256_mp_mod); + sp_256_mont_sub_4(y, t3, t5, p256_mod); + } +} + +#ifdef FP_ECC +/* Convert the projective point to affine. + * Ordinates are in Montgomery form. + * + * a Point to convert. + * t Temprorary data. + */ +static void sp_256_proj_to_affine_avx2_4(sp_point* a, sp_digit* t) +{ + sp_digit* t1 = t; + sp_digit* t2 = t + 2 * 4; + sp_digit* tmp = t + 4 * 4; + + sp_256_mont_inv_avx2_4(t1, a->z, tmp); + + sp_256_mont_sqr_avx2_4(t2, t1, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(t1, t2, t1, p256_mod, p256_mp_mod); + + sp_256_mont_mul_avx2_4(a->x, a->x, t2, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(a->y, a->y, t1, p256_mod, p256_mp_mod); + XMEMCPY(a->z, p256_norm_mod, sizeof(p256_norm_mod)); +} + +/* Generate the pre-computed table of points for the base point. + * + * a The base point. + * table Place to store generated point data. + * tmp Temprorary data. + * heap Heap to use for allocation. + */ +static int sp_256_gen_stripe_table_avx2_4(sp_point* a, + sp_table_entry* table, sp_digit* tmp, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point td, s1d, s2d; +#endif + sp_point* t; + sp_point* s1 = NULL; + sp_point* s2 = NULL; + int i, j; + int err; + + (void)heap; + + err = sp_ecc_point_new(heap, td, t); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, s1d, s1); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, s2d, s2); + + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_4(t->x, a->x, p256_mod); + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_4(t->y, a->y, p256_mod); + if (err == MP_OKAY) + err = sp_256_mod_mul_norm_4(t->z, a->z, p256_mod); + if (err == MP_OKAY) { + t->infinity = 0; + sp_256_proj_to_affine_avx2_4(t, tmp); + + XMEMCPY(s1->z, p256_norm_mod, sizeof(p256_norm_mod)); + s1->infinity = 0; + XMEMCPY(s2->z, p256_norm_mod, sizeof(p256_norm_mod)); + s2->infinity = 0; + + /* table[0] = {0, 0, infinity} */ + XMEMSET(&table[0], 0, sizeof(sp_table_entry)); + table[0].infinity = 1; + /* table[1] = Affine version of 'a' in Montgomery form */ + XMEMCPY(table[1].x, t->x, sizeof(table->x)); + XMEMCPY(table[1].y, t->y, sizeof(table->y)); + table[1].infinity = 0; + + for (i=1; i<8; i++) { + sp_256_proj_point_dbl_n_avx2_4(t, t, 32, tmp); + sp_256_proj_to_affine_avx2_4(t, tmp); + XMEMCPY(table[1<x, sizeof(table->x)); + XMEMCPY(table[1<y, sizeof(table->y)); + table[1<x, table[1<x)); + XMEMCPY(s1->y, table[1<y)); + for (j=(1<x, table[j-(1<x)); + XMEMCPY(s2->y, table[j-(1<y)); + sp_256_proj_point_add_qz1_avx2_4(t, s1, s2, tmp); + sp_256_proj_to_affine_avx2_4(t, tmp); + XMEMCPY(table[j].x, t->x, sizeof(table->x)); + XMEMCPY(table[j].y, t->y, sizeof(table->y)); + table[j].infinity = 0; + } + } + } + + sp_ecc_point_free(s2, 0, heap); + sp_ecc_point_free(s1, 0, heap); + sp_ecc_point_free( t, 0, heap); + + return err; +} + +#endif /* FP_ECC */ +#if defined(FP_ECC) || defined(WOLFSSL_SP_SMALL) +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_stripe_avx2_4(sp_point* r, sp_point* g, + sp_table_entry* table, sp_digit* k, int map, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point rtd; + sp_point pd; + sp_digit td[2 * 4 * 5]; +#endif + sp_point* rt; + sp_point* p = NULL; + sp_digit* t; + int i, j; + int y, x; + int err; + + (void)g; + (void)heap; + + err = sp_ecc_point_new(heap, rtd, rt); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + t = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 5, heap, + DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; +#else + t = td; +#endif + + if (err == MP_OKAY) { + XMEMCPY(p->z, p256_norm_mod, sizeof(p256_norm_mod)); + XMEMCPY(rt->z, p256_norm_mod, sizeof(p256_norm_mod)); + + y = 0; + for (j=0,x=31; j<8; j++,x+=32) + y |= ((k[x / 64] >> (x % 64)) & 1) << j; + XMEMCPY(rt->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(rt->y, table[y].y, sizeof(table[y].y)); + rt->infinity = table[y].infinity; + for (i=30; i>=0; i--) { + y = 0; + for (j=0,x=i; j<8; j++,x+=32) + y |= ((k[x / 64] >> (x % 64)) & 1) << j; + + sp_256_proj_point_dbl_avx2_4(rt, rt, t); + XMEMCPY(p->x, table[y].x, sizeof(table[y].x)); + XMEMCPY(p->y, table[y].y, sizeof(table[y].y)); + p->infinity = table[y].infinity; + sp_256_proj_point_add_qz1_avx2_4(rt, rt, p, t); + } + + if (map) + sp_256_map_avx2_4(r, rt, t); + else + XMEMCPY(r, rt, sizeof(sp_point)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (t != NULL) + XFREE(t, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p, 0, heap); + sp_ecc_point_free(rt, 0, heap); + + return err; +} + +#endif /* FP_ECC || WOLFSSL_SP_SMALL */ +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * g Point to multiply. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_avx2_4(sp_point* r, sp_point* g, sp_digit* k, + int map, void* heap) +{ +#ifndef FP_ECC + return sp_256_ecc_mulmod_win_add_sub_avx2_4(r, g, k, map, heap); +#else + sp_digit tmp[2 * 4 * 5]; + sp_cache_t* cache; + int err = MP_OKAY; + +#ifndef HAVE_THREAD_LS + if (initCacheMutex == 0) { + wc_InitMutex(&sp_cache_lock); + initCacheMutex = 1; + } + if (wc_LockMutex(&sp_cache_lock) != 0) + err = BAD_MUTEX_E; +#endif /* HAVE_THREAD_LS */ + + if (err == MP_OKAY) { + sp_ecc_get_cache(g, &cache); + if (cache->cnt == 2) + sp_256_gen_stripe_table_avx2_4(g, cache->table, tmp, heap); + +#ifndef HAVE_THREAD_LS + wc_UnLockMutex(&sp_cache_lock); +#endif /* HAVE_THREAD_LS */ + + if (cache->cnt < 2) { + err = sp_256_ecc_mulmod_win_add_sub_avx2_4(r, g, k, map, heap); + } + else { + err = sp_256_ecc_mulmod_stripe_avx2_4(r, g, cache->table, k, + map, heap); + } + } + + return err; +#endif +} + +#endif /* HAVE_INTEL_AVX2 */ +/* Multiply the point by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * km Scalar to multiply by. + * p Point to multiply. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_256(mp_int* km, ecc_point* gm, ecc_point* r, int map, + void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point p; + sp_digit kd[4]; +#endif + sp_point* point; + sp_digit* k = NULL; + int err = MP_OKAY; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + err = sp_ecc_point_new(heap, p, point); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + if (err == MP_OKAY) { + sp_256_from_mp(k, 4, km); + sp_256_point_from_ecc_point_4(point, gm); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_256_ecc_mulmod_avx2_4(point, point, k, map, heap); + else +#endif + err = sp_256_ecc_mulmod_4(point, point, k, map, heap); + } + if (err == MP_OKAY) + err = sp_256_point_to_ecc_point_4(point, r); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(point, 0, heap); + + return err; +} + +#ifdef WOLFSSL_SP_SMALL +static sp_table_entry p256_table[256] = { + /* 0 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 */ + { { 0x79e730d418a9143cl,0x75ba95fc5fedb601l,0x79fb732b77622510l, + 0x18905f76a53755c6l }, + { 0xddf25357ce95560al,0x8b4ab8e4ba19e45cl,0xd2e88688dd21f325l, + 0x8571ff1825885d85l }, + 0 }, + /* 2 */ + { { 0x202886024147519al,0xd0981eac26b372f0l,0xa9d4a7caa785ebc8l, + 0xd953c50ddbdf58e9l }, + { 0x9d6361ccfd590f8fl,0x72e9626b44e6c917l,0x7fd9611022eb64cfl, + 0x863ebb7e9eb288f3l }, + 0 }, + /* 3 */ + { { 0x7856b6235cdb6485l,0x808f0ea22f0a2f97l,0x3e68d9544f7e300bl, + 0x00076055b5ff80a0l }, + { 0x7634eb9b838d2010l,0x54014fbb3243708al,0xe0e47d39842a6606l, + 0x8308776134373ee0l }, + 0 }, + /* 4 */ + { { 0x4f922fc516a0d2bbl,0x0d5cc16c1a623499l,0x9241cf3a57c62c8bl, + 0x2f5e6961fd1b667fl }, + { 0x5c15c70bf5a01797l,0x3d20b44d60956192l,0x04911b37071fdb52l, + 0xf648f9168d6f0f7bl }, + 0 }, + /* 5 */ + { { 0x9e566847e137bbbcl,0xe434469e8a6a0becl,0xb1c4276179d73463l, + 0x5abe0285133d0015l }, + { 0x92aa837cc04c7dabl,0x573d9f4c43260c07l,0x0c93156278e6cc37l, + 0x94bb725b6b6f7383l }, + 0 }, + /* 6 */ + { { 0xbbf9b48f720f141cl,0x6199b3cd2df5bc74l,0xdc3f6129411045c4l, + 0xcdd6bbcb2f7dc4efl }, + { 0xcca6700beaf436fdl,0x6f647f6db99326bel,0x0c0fa792014f2522l, + 0xa361bebd4bdae5f6l }, + 0 }, + /* 7 */ + { { 0x28aa2558597c13c7l,0xc38d635f50b7c3e1l,0x07039aecf3c09d1dl, + 0xba12ca09c4b5292cl }, + { 0x9e408fa459f91dfdl,0x3af43b66ceea07fbl,0x1eceb0899d780b29l, + 0x53ebb99d701fef4bl }, + 0 }, + /* 8 */ + { { 0x4fe7ee31b0e63d34l,0xf4600572a9e54fabl,0xc0493334d5e7b5a4l, + 0x8589fb9206d54831l }, + { 0xaa70f5cc6583553al,0x0879094ae25649e5l,0xcc90450710044652l, + 0xebb0696d02541c4fl }, + 0 }, + /* 9 */ + { { 0x4616ca15ac1647c5l,0xb8127d47c4cf5799l,0xdc666aa3764dfbacl, + 0xeb2820cbd1b27da3l }, + { 0x9406f8d86a87e008l,0xd87dfa9d922378f3l,0x56ed2e4280ccecb2l, + 0x1f28289b55a7da1dl }, + 0 }, + /* 10 */ + { { 0xabbaa0c03b89da99l,0xa6f2d79eb8284022l,0x27847862b81c05e8l, + 0x337a4b5905e54d63l }, + { 0x3c67500d21f7794al,0x207005b77d6d7f61l,0x0a5a378104cfd6e8l, + 0x0d65e0d5f4c2fbd6l }, + 0 }, + /* 11 */ + { { 0xd9d09bbeb5275d38l,0x4268a7450be0a358l,0xf0762ff4973eb265l, + 0xc23da24252f4a232l }, + { 0x5da1b84f0b94520cl,0x09666763b05bd78el,0x3a4dcb8694d29ea1l, + 0x19de3b8cc790cff1l }, + 0 }, + /* 12 */ + { { 0x183a716c26c5fe04l,0x3b28de0b3bba1bdbl,0x7432c586a4cb712cl, + 0xe34dcbd491fccbfdl }, + { 0xb408d46baaa58403l,0x9a69748682e97a53l,0x9e39012736aaa8afl, + 0xe7641f447b4e0f7fl }, + 0 }, + /* 13 */ + { { 0x7d753941df64ba59l,0xd33f10ec0b0242fcl,0x4f06dfc6a1581859l, + 0x4a12df57052a57bfl }, + { 0xbfa6338f9439dbd0l,0xd3c24bd4bde53e1fl,0xfd5e4ffa21f1b314l, + 0x6af5aa93bb5bea46l }, + 0 }, + /* 14 */ + { { 0xda10b69910c91999l,0x0a24b4402a580491l,0x3e0094b4b8cc2090l, + 0x5fe3475a66a44013l }, + { 0xb0f8cabdf93e7b4bl,0x292b501a7c23f91al,0x42e889aecd1e6263l, + 0xb544e308ecfea916l }, + 0 }, + /* 15 */ + { { 0x6478c6e916ddfdcel,0x2c329166f89179e6l,0x4e8d6e764d4e67e1l, + 0xe0b6b2bda6b0c20bl }, + { 0x0d312df2bb7efb57l,0x1aac0dde790c4007l,0xf90336ad679bc944l, + 0x71c023de25a63774l }, + 0 }, + /* 16 */ + { { 0x62a8c244bfe20925l,0x91c19ac38fdce867l,0x5a96a5d5dd387063l, + 0x61d587d421d324f6l }, + { 0xe87673a2a37173eal,0x2384800853778b65l,0x10f8441e05bab43el, + 0xfa11fe124621efbel }, + 0 }, + /* 17 */ + { { 0x1c891f2b2cb19ffdl,0x01ba8d5bb1923c23l,0xb6d03d678ac5ca8el, + 0x586eb04c1f13bedcl }, + { 0x0c35c6e527e8ed09l,0x1e81a33c1819ede2l,0x278fd6c056c652fal, + 0x19d5ac0870864f11l }, + 0 }, + /* 18 */ + { { 0x1e99f581309a4e1fl,0xab7de71be9270074l,0x26a5ef0befd28d20l, + 0xe7c0073f7f9c563fl }, + { 0x1f6d663a0ef59f76l,0x669b3b5420fcb050l,0xc08c1f7a7a6602d4l, + 0xe08504fec65b3c0al }, + 0 }, + /* 19 */ + { { 0xf098f68da031b3cal,0x6d1cab9ee6da6d66l,0x5bfd81fa94f246e8l, + 0x78f018825b0996b4l }, + { 0xb7eefde43a25787fl,0x8016f80d1dccac9bl,0x0cea4877b35bfc36l, + 0x43a773b87e94747al }, + 0 }, + /* 20 */ + { { 0x62577734d2b533d5l,0x673b8af6a1bdddc0l,0x577e7c9aa79ec293l, + 0xbb6de651c3b266b1l }, + { 0xe7e9303ab65259b3l,0xd6a0afd3d03a7480l,0xc5ac83d19b3cfc27l, + 0x60b4619a5d18b99bl }, + 0 }, + /* 21 */ + { { 0xbd6a38e11ae5aa1cl,0xb8b7652b49e73658l,0x0b130014ee5f87edl, + 0x9d0f27b2aeebffcdl }, + { 0xca9246317a730a55l,0x9c955b2fddbbc83al,0x07c1dfe0ac019a71l, + 0x244a566d356ec48dl }, + 0 }, + /* 22 */ + { { 0x6db0394aeacf1f96l,0x9f2122a9024c271cl,0x2626ac1b82cbd3b9l, + 0x45e58c873581ef69l }, + { 0xd3ff479da38f9dbcl,0xa8aaf146e888a040l,0x945adfb246e0bed7l, + 0xc040e21cc1e4b7a4l }, + 0 }, + /* 23 */ + { { 0x847af0006f8117b6l,0x651969ff73a35433l,0x482b35761d9475ebl, + 0x1cdf5c97682c6ec7l }, + { 0x7db775b411f04839l,0x7dbeacf448de1698l,0xb2921dd1b70b3219l, + 0x046755f8a92dff3dl }, + 0 }, + /* 24 */ + { { 0xcc8ac5d2bce8ffcdl,0x0d53c48b2fe61a82l,0xf6f161727202d6c7l, + 0x046e5e113b83a5f3l }, + { 0xe7b8ff64d8007f01l,0x7fb1ef125af43183l,0x045c5ea635e1a03cl, + 0x6e0106c3303d005bl }, + 0 }, + /* 25 */ + { { 0x48c7358488dd73b1l,0x7670708f995ed0d9l,0x38385ea8c56a2ab7l, + 0x442594ede901cf1fl }, + { 0xf8faa2c912d4b65bl,0x94c2343b96c90c37l,0xd326e4a15e978d1fl, + 0xa796fa514c2ee68el }, + 0 }, + /* 26 */ + { { 0x359fb604823addd7l,0x9e2a6183e56693b3l,0xf885b78e3cbf3c80l, + 0xe4ad2da9c69766e9l }, + { 0x357f7f428e048a61l,0x082d198cc092d9a0l,0xfc3a1af4c03ed8efl, + 0xc5e94046c37b5143l }, + 0 }, + /* 27 */ + { { 0x476a538c2be75f9el,0x6fd1a9e8cb123a78l,0xd85e4df0b109c04bl, + 0x63283dafdb464747l }, + { 0xce728cf7baf2df15l,0xe592c4550ad9a7f4l,0xfab226ade834bcc3l, + 0x68bd19ab1981a938l }, + 0 }, + /* 28 */ + { { 0xc08ead511887d659l,0x3374d5f4b359305al,0x96986981cfe74fe3l, + 0x495292f53c6fdfd6l }, + { 0x4a878c9e1acec896l,0xd964b210ec5b4484l,0x6696f7e2664d60a7l, + 0x0ec7530d26036837l }, + 0 }, + /* 29 */ + { { 0x2da13a05ad2687bbl,0xa1f83b6af32e21fal,0x390f5ef51dd4607bl, + 0x0f6207a664863f0bl }, + { 0xbd67e3bb0f138233l,0xdd66b96c272aa718l,0x8ed0040726ec88ael, + 0xff0db07208ed6dcfl }, + 0 }, + /* 30 */ + { { 0x749fa1014c95d553l,0xa44052fd5d680a8al,0x183b4317ff3b566fl, + 0x313b513c88740ea3l }, + { 0xb402e2ac08d11549l,0x071ee10bb4dee21cl,0x26b987dd47f2320el, + 0x2d3abcf986f19f81l }, + 0 }, + /* 31 */ + { { 0x4c288501815581a2l,0x9a0a6d56632211afl,0x19ba7a0f0cab2e99l, + 0xc036fa10ded98cdfl }, + { 0x29ae08bac1fbd009l,0x0b68b19006d15816l,0xc2eb32779b9e0d8fl, + 0xa6b2a2c4b6d40194l }, + 0 }, + /* 32 */ + { { 0xd433e50f6d3549cfl,0x6f33696ffacd665el,0x695bfdacce11fcb4l, + 0x810ee252af7c9860l }, + { 0x65450fe17159bb2cl,0xf7dfbebe758b357bl,0x2b057e74d69fea72l, + 0xd485717a92731745l }, + 0 }, + /* 33 */ + { { 0x11741a8af0cb5a98l,0xd3da8f931f3110bfl,0x1994e2cbab382adfl, + 0x6a6045a72f9a604el }, + { 0x170c0d3fa2b2411dl,0xbe0eb83e510e96e0l,0x3bcc9f738865b3ccl, + 0xd3e45cfaf9e15790l }, + 0 }, + /* 34 */ + { { 0xce1f69bbe83f7669l,0x09f8ae8272877d6bl,0x9548ae543244278dl, + 0x207755dee3c2c19cl }, + { 0x87bd61d96fef1945l,0x18813cefb12d28c3l,0x9fbcd1d672df64aal, + 0x48dc5ee57154b00dl }, + 0 }, + /* 35 */ + { { 0x123790bff7e5a199l,0xe0efb8cf989ccbb7l,0xc27a2bfe0a519c79l, + 0xf2fb0aeddff6f445l }, + { 0x41c09575f0b5025fl,0x550543d740fa9f22l,0x8fa3c8ad380bfbd0l, + 0xa13e9015db28d525l }, + 0 }, + /* 36 */ + { { 0xf9f7a350a2b65cbcl,0x0b04b9722a464226l,0x265ce241e23f07a1l, + 0x2bf0d6b01497526fl }, + { 0xd3d4dd3f4b216fb7l,0xf7d7b867fbdda26al,0xaeb7b83f6708505cl, + 0x42a94a5a162fe89fl }, + 0 }, + /* 37 */ + { { 0x5846ad0beaadf191l,0x0f8a489025a268d7l,0xe8603050494dc1f6l, + 0x2c2dd969c65ede3dl }, + { 0x6d02171d93849c17l,0x460488ba1da250ddl,0x4810c7063c3a5485l, + 0xf437fa1f42c56dbcl }, + 0 }, + /* 38 */ + { { 0x6aa0d7144a0f7dabl,0x0f0497931776e9acl,0x52c0a050f5f39786l, + 0xaaf45b3354707aa8l }, + { 0x85e37c33c18d364al,0xd40b9b063e497165l,0xf417168115ec5444l, + 0xcdf6310df4f272bcl }, + 0 }, + /* 39 */ + { { 0x7473c6238ea8b7efl,0x08e9351885bc2287l,0x419567722bda8e34l, + 0xf0d008bada9e2ff2l }, + { 0x2912671d2414d3b1l,0xb3754985b019ea76l,0x5c61b96d453bcbdbl, + 0x5bd5c2f5ca887b8bl }, + 0 }, + /* 40 */ + { { 0xef0f469ef49a3154l,0x3e85a5956e2b2e9al,0x45aaec1eaa924a9cl, + 0xaa12dfc8a09e4719l }, + { 0x26f272274df69f1dl,0xe0e4c82ca2ff5e73l,0xb9d8ce73b7a9dd44l, + 0x6c036e73e48ca901l }, + 0 }, + /* 41 */ + { { 0x5cfae12a0f6e3138l,0x6966ef0025ad345al,0x8993c64b45672bc5l, + 0x292ff65896afbe24l }, + { 0xd5250d445e213402l,0xf6580e274392c9fel,0x097b397fda1c72e8l, + 0x644e0c90311b7276l }, + 0 }, + /* 42 */ + { { 0xe1e421e1a47153f0l,0xb86c3b79920418c9l,0x93bdce87705d7672l, + 0xf25ae793cab79a77l }, + { 0x1f3194a36d869d0cl,0x9d55c8824986c264l,0x49fb5ea3096e945el, + 0x39b8e65313db0a3el }, + 0 }, + /* 43 */ + { { 0x37754200b6fd2e59l,0x35e2c0669255c98fl,0xd9dab21a0e2a5739l, + 0x39122f2f0f19db06l }, + { 0xcfbce1e003cad53cl,0x225b2c0fe65c17e3l,0x72baf1d29aa13877l, + 0x8de80af8ce80ff8dl }, + 0 }, + /* 44 */ + { { 0xafbea8d9207bbb76l,0x921c7e7c21782758l,0xdfa2b74b1c0436b1l, + 0x871949062e368c04l }, + { 0xb5f928bba3993df5l,0x639d75b5f3b3d26al,0x011aa78a85b55050l, + 0xfc315e6a5b74fde1l }, + 0 }, + /* 45 */ + { { 0x561fd41ae8d6ecfal,0x5f8c44f61aec7f86l,0x98452a7b4924741dl, + 0xe6d4a7adee389088l }, + { 0x60552ed14593c75dl,0x70a70da4dd271162l,0xd2aede937ba2c7dbl, + 0x35dfaf9a9be2ae57l }, + 0 }, + /* 46 */ + { { 0x6b956fcdaa736636l,0x09f51d97ae2cab7el,0xfb10bf410f349966l, + 0x1da5c7d71c830d2bl }, + { 0x5c41e4833cce6825l,0x15ad118ff9573c3bl,0xa28552c7f23036b8l, + 0x7077c0fddbf4b9d6l }, + 0 }, + /* 47 */ + { { 0xbf63ff8d46b9661cl,0xa1dfd36b0d2cfd71l,0x0373e140a847f8f7l, + 0x53a8632ee50efe44l }, + { 0x0976ff68696d8051l,0xdaec0c95c74f468al,0x62994dc35e4e26bdl, + 0x028ca76d34e1fcc1l }, + 0 }, + /* 48 */ + { { 0xd11d47dcfc9877eel,0xc8b36210801d0002l,0xd002c11754c260b6l, + 0x04c17cd86962f046l }, + { 0x6d9bd094b0daddf5l,0xbea2357524ce55c0l,0x663356e672da03b5l, + 0xf7ba4de9fed97474l }, + 0 }, + /* 49 */ + { { 0xd0dbfa34ebe1263fl,0x5576373571ae7ce6l,0xd244055382a6f523l, + 0xe31f960052131c41l }, + { 0xd1bb9216ea6b6ec6l,0x37a1d12e73c2fc44l,0xc10e7eac89d0a294l, + 0xaa3a6259ce34d47bl }, + 0 }, + /* 50 */ + { { 0xfbcf9df536f3dcd3l,0x6ceded50d2bf7360l,0x491710fadf504f5bl, + 0x2398dd627e79daeel }, + { 0xcf4705a36d09569el,0xea0619bb5149f769l,0xff9c037735f6034cl, + 0x5717f5b21c046210l }, + 0 }, + /* 51 */ + { { 0x9fe229c921dd895el,0x8e51850040c28451l,0xfa13d2391d637ecdl, + 0x660a2c560e3c28del }, + { 0x9cca88aed67fcbd0l,0xc84724780ea9f096l,0x32b2f48172e92b4dl, + 0x624ee54c4f522453l }, + 0 }, + /* 52 */ + { { 0x09549ce4d897ecccl,0x4d49d1d93f9880aal,0x723c2423043a7c20l, + 0x4f392afb92bdfbc0l }, + { 0x6969f8fa7de44fd9l,0xb66cfbe457b32156l,0xdb2fa803368ebc3cl, + 0x8a3e7977ccdb399cl }, + 0 }, + /* 53 */ + { { 0xdde1881f06c4b125l,0xae34e300f6e3ca8cl,0xef6999de5c7a13e9l, + 0x3888d02370c24404l }, + { 0x7628035644f91081l,0x3d9fcf615f015504l,0x1827edc8632cd36el, + 0xa5e62e4718102336l }, + 0 }, + /* 54 */ + { { 0x1a825ee32facd6c8l,0x699c635454bcbc66l,0x0ce3edf798df9931l, + 0x2c4768e6466a5adcl }, + { 0xb346ff8c90a64bc9l,0x630a6020e4779f5cl,0xd949d064bc05e884l, + 0x7b5e6441f9e652a0l }, + 0 }, + /* 55 */ + { { 0x2169422c1d28444al,0xe996c5d8be136a39l,0x2387afe5fb0c7fcel, + 0xb8af73cb0c8d744al }, + { 0x5fde83aa338b86fdl,0xfee3f158a58a5cffl,0xc9ee8f6f20ac9433l, + 0xa036395f7f3f0895l }, + 0 }, + /* 56 */ + { { 0x8c73c6bba10f7770l,0xa6f16d81a12a0e24l,0x100df68251bc2b9fl, + 0x4be36b01875fb533l }, + { 0x9226086e9fb56dbbl,0x306fef8b07e7a4f8l,0xeeaccc0566d52f20l, + 0x8cbc9a871bdc00c0l }, + 0 }, + /* 57 */ + { { 0xe131895cc0dac4abl,0xa874a440712ff112l,0x6332ae7c6a1cee57l, + 0x44e7553e0c0835f8l }, + { 0x6d503fff7734002dl,0x9d35cb8b0b34425cl,0x95f702760e8738b5l, + 0x470a683a5eb8fc18l }, + 0 }, + /* 58 */ + { { 0x81b761dc90513482l,0x0287202a01e9276al,0xcda441ee0ce73083l, + 0x16410690c63dc6efl }, + { 0xf5034a066d06a2edl,0xdd4d7745189b100bl,0xd914ae72ab8218c9l, + 0xd73479fd7abcbb4fl }, + 0 }, + /* 59 */ + { { 0x7edefb165ad4c6e5l,0x262cf08f5b06d04dl,0x12ed5bb18575cb14l, + 0x816469e30771666bl }, + { 0xd7ab9d79561e291el,0xeb9daf22c1de1661l,0xf49827eb135e0513l, + 0x0a36dd23f0dd3f9cl }, + 0 }, + /* 60 */ + { { 0x098d32c741d5533cl,0x7c5f5a9e8684628fl,0x39a228ade349bd11l, + 0xe331dfd6fdbab118l }, + { 0x5100ab686bcc6ed8l,0x7160c3bdef7a260el,0x9063d9a7bce850d7l, + 0xd3b4782a492e3389l }, + 0 }, + /* 61 */ + { { 0xa149b6e8f3821f90l,0x92edd9ed66eb7aadl,0x0bb669531a013116l, + 0x7281275a4c86a5bdl }, + { 0x503858f7d3ff47e5l,0x5e1616bc61016441l,0x62b0f11a7dfd9bb1l, + 0x2c062e7ece145059l }, + 0 }, + /* 62 */ + { { 0xa76f996f0159ac2el,0x281e7736cbdb2713l,0x2ad6d28808e46047l, + 0x282a35f92c4e7ef1l }, + { 0x9c354b1ec0ce5cd2l,0xcf99efc91379c229l,0x992caf383e82c11el, + 0xc71cd513554d2abdl }, + 0 }, + /* 63 */ + { { 0x4885de9c09b578f4l,0x1884e258e3affa7al,0x8f76b1b759182f1fl, + 0xc50f6740cf47f3a3l }, + { 0xa9c4adf3374b68eal,0xa406f32369965fe2l,0x2f86a22285a53050l, + 0xb9ecb3a7212958dcl }, + 0 }, + /* 64 */ + { { 0x56f8410ef4f8b16al,0x97241afec47b266al,0x0a406b8e6d9c87c1l, + 0x803f3e02cd42ab1bl }, + { 0x7f0309a804dbec69l,0xa83b85f73bbad05fl,0xc6097273ad8e197fl, + 0xc097440e5067adc1l }, + 0 }, + /* 65 */ + { { 0x846a56f2c379ab34l,0xa8ee068b841df8d1l,0x20314459176c68efl, + 0xf1af32d5915f1f30l }, + { 0x99c375315d75bd50l,0x837cffbaf72f67bcl,0x0613a41848d7723fl, + 0x23d0f130e2d41c8bl }, + 0 }, + /* 66 */ + { { 0x857ab6edf41500d9l,0x0d890ae5fcbeada8l,0x52fe864889725951l, + 0xb0288dd6c0a3faddl }, + { 0x85320f30650bcb08l,0x71af6313695d6e16l,0x31f520a7b989aa76l, + 0xffd3724ff408c8d2l }, + 0 }, + /* 67 */ + { { 0x53968e64b458e6cbl,0x992dad20317a5d28l,0x3814ae0b7aa75f56l, + 0xf5590f4ad78c26dfl }, + { 0x0fc24bd3cf0ba55al,0x0fc4724a0c778bael,0x1ce9864f683b674al, + 0x18d6da54f6f74a20l }, + 0 }, + /* 68 */ + { { 0xed93e225d5be5a2bl,0x6fe799835934f3c6l,0x4314092622626ffcl, + 0x50bbb4d97990216al }, + { 0x378191c6e57ec63el,0x65422c40181dcdb2l,0x41a8099b0236e0f6l, + 0x2b10011801fe49c3l }, + 0 }, + /* 69 */ + { { 0xfc68b5c59b391593l,0xc385f5a2598270fcl,0x7144f3aad19adcbbl, + 0xdd55899983fbae0cl }, + { 0x93b88b8e74b82ff4l,0xd2e03c4071e734c9l,0x9a7a9eaf43c0322al, + 0xe6e4c551149d6041l }, + 0 }, + /* 70 */ + { { 0x55f655bb1e9af288l,0x647e1a64f7ada931l,0x43697e4bcb2820e5l, + 0x51e00db107ed56ffl }, + { 0x43d169b8771c327el,0x29cdb20b4a96c2adl,0xc07d51f53deb4779l, + 0xe22f424149829177l }, + 0 }, + /* 71 */ + { { 0xcd45e8f4635f1abbl,0x7edc0cb568538874l,0xc9472c1fb5a8034dl, + 0xf709373d52dc48c9l }, + { 0x401966bba8af30d6l,0x95bf5f4af137b69cl,0x3966162a9361c47el, + 0xbd52d288e7275b11l }, + 0 }, + /* 72 */ + { { 0xab155c7a9c5fa877l,0x17dad6727d3a3d48l,0x43f43f9e73d189d8l, + 0xa0d0f8e4c8aa77a6l }, + { 0x0bbeafd8cc94f92dl,0xd818c8be0c4ddb3al,0x22cc65f8b82eba14l, + 0xa56c78c7946d6a00l }, + 0 }, + /* 73 */ + { { 0x2962391b0dd09529l,0x803e0ea63daddfcfl,0x2c77351f5b5bf481l, + 0xd8befdf8731a367al }, + { 0xab919d42fc0157f4l,0xf51caed7fec8e650l,0xcdf9cb4002d48b0al, + 0x854a68a5ce9f6478l }, + 0 }, + /* 74 */ + { { 0xdc35f67b63506ea5l,0x9286c489a4fe0d66l,0x3f101d3bfe95cd4dl, + 0x5cacea0b98846a95l }, + { 0xa90df60c9ceac44dl,0x3db29af4354d1c3al,0x08dd3de8ad5dbabel, + 0xe4982d1235e4efa9l }, + 0 }, + /* 75 */ + { { 0x23104a22c34cd55el,0x58695bb32680d132l,0xfb345afa1fa1d943l, + 0x8046b7f616b20499l }, + { 0xb533581e38e7d098l,0xd7f61e8df46f0b70l,0x30dea9ea44cb78c4l, + 0xeb17ca7b9082af55l }, + 0 }, + /* 76 */ + { { 0x1751b59876a145b9l,0xa5cf6b0fc1bc71ecl,0xd3e03565392715bbl, + 0x097b00bafab5e131l }, + { 0xaa66c8e9565f69e1l,0x77e8f75ab5be5199l,0x6033ba11da4fd984l, + 0xf95c747bafdbcc9el }, + 0 }, + /* 77 */ + { { 0x558f01d3bebae45el,0xa8ebe9f0c4bc6955l,0xaeb705b1dbc64fc6l, + 0x3512601e566ed837l }, + { 0x9336f1e1fa1161cdl,0x328ab8d54c65ef87l,0x4757eee2724f21e5l, + 0x0ef971236068ab6bl }, + 0 }, + /* 78 */ + { { 0x02598cf754ca4226l,0x5eede138f8642c8el,0x48963f74468e1790l, + 0xfc16d9333b4fbc95l }, + { 0xbe96fb31e7c800cal,0x138063312678adaal,0x3d6244976ff3e8b5l, + 0x14ca4af1b95d7a17l }, + 0 }, + /* 79 */ + { { 0x7a4771babd2f81d5l,0x1a5f9d6901f7d196l,0xd898bef7cad9c907l, + 0x4057b063f59c231dl }, + { 0xbffd82fe89c05c0al,0xe4911c6f1dc0df85l,0x3befccaea35a16dbl, + 0x1c3b5d64f1330b13l }, + 0 }, + /* 80 */ + { { 0x5fe14bfe80ec21fel,0xf6ce116ac255be82l,0x98bc5a072f4a5d67l, + 0xfad27148db7e63afl }, + { 0x90c0b6ac29ab05b3l,0x37a9a83c4e251ae6l,0x0a7dc875c2aade7dl, + 0x77387de39f0e1a84l }, + 0 }, + /* 81 */ + { { 0x1e9ecc49a56c0dd7l,0xa5cffcd846086c74l,0x8f7a1408f505aecel, + 0xb37b85c0bef0c47el }, + { 0x3596b6e4cc0e6a8fl,0xfd6d4bbf6b388f23l,0xaba453fac39cef4el, + 0x9c135ac8f9f628d5l }, + 0 }, + /* 82 */ + { { 0x32aa320284e35743l,0x320d6ab185a3cdefl,0xb821b1761df19819l, + 0x5721361fc433851fl }, + { 0x1f0db36a71fc9168l,0x5f98ba735e5c403cl,0xf64ca87e37bcd8f5l, + 0xdcbac3c9e6bb11bdl }, + 0 }, + /* 83 */ + { { 0xf01d99684518cbe2l,0xd242fc189c9eb04el,0x727663c7e47feebfl, + 0xb8c1c89e2d626862l }, + { 0x51a58bddc8e1d569l,0x563809c8b7d88cd0l,0x26c27fd9f11f31ebl, + 0x5d23bbda2f9422d4l }, + 0 }, + /* 84 */ + { { 0x0a1c729495c8f8bel,0x2961c4803bf362bfl,0x9e418403df63d4acl, + 0xc109f9cb91ece900l }, + { 0xc2d095d058945705l,0xb9083d96ddeb85c0l,0x84692b8d7a40449bl, + 0x9bc3344f2eee1ee1l }, + 0 }, + /* 85 */ + { { 0x0d5ae35642913074l,0x55491b2748a542b1l,0x469ca665b310732al, + 0x29591d525f1a4cc1l }, + { 0xe76f5b6bb84f983fl,0xbe7eef419f5f84e1l,0x1200d49680baa189l, + 0x6376551f18ef332cl }, + 0 }, + /* 86 */ + { { 0xbda5f14e562976ccl,0x22bca3e60ef12c38l,0xbbfa30646cca9852l, + 0xbdb79dc808e2987al }, + { 0xfd2cb5c9cb06a772l,0x38f475aafe536dcel,0xc2a3e0227c2b5db8l, + 0x8ee86001add3c14al }, + 0 }, + /* 87 */ + { { 0xcbe96981a4ade873l,0x7ee9aa4dc4fba48cl,0x2cee28995a054ba5l, + 0x92e51d7a6f77aa4bl }, + { 0x948bafa87190a34dl,0xd698f75bf6bd1ed1l,0xd00ee6e30caf1144l, + 0x5182f86f0a56aaaal }, + 0 }, + /* 88 */ + { { 0xfba6212c7a4cc99cl,0xff609b683e6d9ca1l,0x5dbb27cb5ac98c5al, + 0x91dcab5d4073a6f2l }, + { 0x01b6cc3d5f575a70l,0x0cb361396f8d87fal,0x165d4e8c89981736l, + 0x17a0cedb97974f2bl }, + 0 }, + /* 89 */ + { { 0x38861e2a076c8d3al,0x701aad39210f924bl,0x94d0eae413a835d9l, + 0x2e8ce36c7f4cdf41l }, + { 0x91273dab037a862bl,0x01ba9bb760e4c8fal,0xf964538833baf2ddl, + 0xf4ccc6cb34f668f3l }, + 0 }, + /* 90 */ + { { 0x44ef525cf1f79687l,0x7c59549592efa815l,0xe1231741a5c78d29l, + 0xac0db4889a0df3c9l }, + { 0x86bfc711df01747fl,0x592b9358ef17df13l,0xe5880e4f5ccb6bb5l, + 0x95a64a6194c974a2l }, + 0 }, + /* 91 */ + { { 0x72c1efdac15a4c93l,0x40269b7382585141l,0x6a8dfb1c16cb0badl, + 0x231e54ba29210677l }, + { 0xa70df9178ae6d2dcl,0x4d6aa63f39112918l,0xf627726b5e5b7223l, + 0xab0be032d8a731e1l }, + 0 }, + /* 92 */ + { { 0x097ad0e98d131f2dl,0x637f09e33b04f101l,0x1ac86196d5e9a748l, + 0xf1bcc8802cf6a679l }, + { 0x25c69140e8daacb4l,0x3c4e405560f65009l,0x591cc8fc477937a6l, + 0x851694695aebb271l }, + 0 }, + /* 93 */ + { { 0xde35c143f1dcf593l,0x78202b29b018be3bl,0xe9cdadc29bdd9d3dl, + 0x8f67d9d2daad55d8l }, + { 0x841116567481ea5fl,0xe7d2dde9e34c590cl,0xffdd43f405053fa8l, + 0xf84572b9c0728b5dl }, + 0 }, + /* 94 */ + { { 0x5e1a7a7197af71c9l,0xa14494447a736565l,0xa1b4ae070e1d5063l, + 0xedee2710616b2c19l }, + { 0xb2f034f511734121l,0x1cac6e554a25e9f0l,0x8dc148f3a40c2ecfl, + 0x9fd27e9b44ebd7f4l }, + 0 }, + /* 95 */ + { { 0x3cc7658af6e2cb16l,0xe3eb7d2cfe5919b6l,0x5a8c5816168d5583l, + 0xa40c2fb6958ff387l }, + { 0x8c9ec560fedcc158l,0x7ad804c655f23056l,0xd93967049a307e12l, + 0x99bc9bb87dc6decfl }, + 0 }, + /* 96 */ + { { 0x84a9521d927dafc6l,0x52c1fb695c09cd19l,0x9d9581a0f9366ddel, + 0x9abe210ba16d7e64l }, + { 0x480af84a48915220l,0xfa73176a4dd816c6l,0xc7d539871681ca5al, + 0x7881c25787f344b0l }, + 0 }, + /* 97 */ + { { 0x93399b51e0bcf3ffl,0x0d02cbc5127f74f6l,0x8fb465a2dd01d968l, + 0x15e6e319a30e8940l }, + { 0x646d6e0d3e0e05f4l,0xfad7bddc43588404l,0xbe61c7d1c4f850d3l, + 0x0e55facf191172cel }, + 0 }, + /* 98 */ + { { 0x7e9d9806f8787564l,0x1a33172131e85ce6l,0x6b0158cab819e8d6l, + 0xd73d09766fe96577l }, + { 0x424834251eb7206el,0xa519290fc618bb42l,0x5dcbb8595e30a520l, + 0x9250a3748f15a50bl }, + 0 }, + /* 99 */ + { { 0xcaff08f8be577410l,0xfd408a035077a8c6l,0xf1f63289ec0a63a4l, + 0x77414082c1cc8c0bl }, + { 0x05a40fa6eb0991cdl,0xc1ca086649fdc296l,0x3a68a3c7b324fd40l, + 0x8cb04f4d12eb20b9l }, + 0 }, + /* 100 */ + { { 0xb1c2d0556906171cl,0x9073e9cdb0240c3fl,0xdb8e6b4fd8906841l, + 0xe4e429ef47123b51l }, + { 0x0b8dd53c38ec36f4l,0xf9d2dc01ff4b6a27l,0x5d066e07879a9a48l, + 0x37bca2ff3c6e6552l }, + 0 }, + /* 101 */ + { { 0x4cd2e3c7df562470l,0x44f272a2c0964ac9l,0x7c6d5df980c793bel, + 0x59913edc3002b22al }, + { 0x7a139a835750592al,0x99e01d80e783de02l,0xcf8c0375ea05d64fl, + 0x43786e4ab013e226l }, + 0 }, + /* 102 */ + { { 0xff32b0ed9e56b5a6l,0x0750d9a6d9fc68f9l,0xec15e845597846a7l, + 0x8638ca98b7e79e7al }, + { 0x2f5ae0960afc24b2l,0x05398eaf4dace8f2l,0x3b765dd0aecba78fl, + 0x1ecdd36a7b3aa6f0l }, + 0 }, + /* 103 */ + { { 0x5d3acd626c5ff2f3l,0xa2d516c02873a978l,0xad94c9fad2110d54l, + 0xd85d0f85d459f32dl }, + { 0x9f700b8d10b11da3l,0xd2c22c30a78318c4l,0x556988f49208decdl, + 0xa04f19c3b4ed3c62l }, + 0 }, + /* 104 */ + { { 0x087924c8ed7f93bdl,0xcb64ac5d392f51f6l,0x7cae330a821b71afl, + 0x92b2eeea5c0950b0l }, + { 0x85ac4c9485b6e235l,0xab2ca4a92936c0f0l,0x80faa6b3e0508891l, + 0x1ee782215834276cl }, + 0 }, + /* 105 */ + { { 0xa60a2e00e63e79f7l,0xf590e7b2f399d906l,0x9021054a6607c09dl, + 0xf3f2ced857a6e150l }, + { 0x200510f3f10d9b55l,0x9d2fcfacd8642648l,0xe5631aa7e8bd0e7cl, + 0x0f56a4543da3e210l }, + 0 }, + /* 106 */ + { { 0x5b21bffa1043e0dfl,0x6c74b6cc9c007e6dl,0x1a656ec0d4a8517al, + 0xbd8f17411969e263l }, + { 0x8a9bbb86beb7494al,0x1567d46f45f3b838l,0xdf7a12a7a4e5a79al, + 0x2d1a1c3530ccfa09l }, + 0 }, + /* 107 */ + { { 0x192e3813506508dal,0x336180c4a1d795a7l,0xcddb59497a9944b3l, + 0xa107a65eb91fba46l }, + { 0xe6d1d1c50f94d639l,0x8b4af3758a58b7d7l,0x1a7c5584bd37ca1cl, + 0x183d760af87a9af2l }, + 0 }, + /* 108 */ + { { 0x29d697110dde59a4l,0xf1ad8d070e8bef87l,0x229b49634f2ebe78l, + 0x1d44179dc269d754l }, + { 0xb32dc0cf8390d30el,0x0a3b27530de8110cl,0x31af1dc52bc0339al, + 0x771f9cc29606d262l }, + 0 }, + /* 109 */ + { { 0x99993e7785040739l,0x44539db98026a939l,0xcf40f6f2f5f8fc26l, + 0x64427a310362718el }, + { 0x4f4f2d8785428aa8l,0x7b7adc3febfb49a8l,0x201b2c6df23d01acl, + 0x49d9b7496ae90d6dl }, + 0 }, + /* 110 */ + { { 0xcc78d8bc435d1099l,0x2adbcd4e8e8d1a08l,0x02c2e2a02cb68a41l, + 0x9037d81b3f605445l }, + { 0x7cdbac27074c7b61l,0xfe2031ab57bfd72el,0x61ccec96596d5352l, + 0x08c3de6a7cc0639cl }, + 0 }, + /* 111 */ + { { 0x20fdd020f6d552abl,0x56baff9805cd81f1l,0x06fb7c3e91351291l, + 0xc690944245796b2fl }, + { 0x17b3ae9c41231bd1l,0x1eac6e875cc58205l,0x208837abf9d6a122l, + 0x3fa3db02cafe3ac0l }, + 0 }, + /* 112 */ + { { 0xd75a3e6505058880l,0x7da365ef643943f2l,0x4147861cfab24925l, + 0xc5c4bdb0fdb808ffl }, + { 0x73513e34b272b56bl,0xc8327e9511b9043al,0xfd8ce37df8844969l, + 0x2d56db9446c2b6b5l }, + 0 }, + /* 113 */ + { { 0x2461782fff46ac6bl,0xd19f792607a2e425l,0xfafea3c409a48de1l, + 0x0f56bd9de503ba42l }, + { 0x137d4ed1345cda49l,0x821158fc816f299dl,0xe7c6a54aaeb43402l, + 0x4003bb9d1173b5f1l }, + 0 }, + /* 114 */ + { { 0x3b8e8189a0803387l,0xece115f539cbd404l,0x4297208dd2877f21l, + 0x53765522a07f2f9el }, + { 0xa4980a21a8a4182dl,0xa2bbd07a3219df79l,0x674d0a2e1a19a2d4l, + 0x7a056f586c5d4549l }, + 0 }, + /* 115 */ + { { 0x646b25589d8a2a47l,0x5b582948c3df2773l,0x51ec000eabf0d539l, + 0x77d482f17a1a2675l }, + { 0xb8a1bd9587853948l,0xa6f817bd6cfbffeel,0xab6ec05780681e47l, + 0x4115012b2b38b0e4l }, + 0 }, + /* 116 */ + { { 0x3c73f0f46de28cedl,0x1d5da7609b13ec47l,0x61b8ce9e6e5c6392l, + 0xcdf04572fbea0946l }, + { 0x1cb3c58b6c53c3b0l,0x97fe3c10447b843cl,0xfb2b8ae12cb9780el, + 0xee703dda97383109l }, + 0 }, + /* 117 */ + { { 0x34515140ff57e43al,0xd44660d3b1b811b8l,0x2b3b5dff8f42b986l, + 0x2a0ad89da162ce21l }, + { 0x64e4a6946bc277bal,0xc788c954c141c276l,0x141aa64ccabf6274l, + 0xd62d0b67ac2b4659l }, + 0 }, + /* 118 */ + { { 0x39c5d87b2c054ac4l,0x57005859f27df788l,0xedf7cbf3b18128d6l, + 0xb39a23f2991c2426l }, + { 0x95284a15f0b16ae5l,0x0c6a05b1a136f51bl,0x1d63c137f2700783l, + 0x04ed0092c0674cc5l }, + 0 }, + /* 119 */ + { { 0x1f4185d19ae90393l,0x3047b4294a3d64e6l,0xae0001a69854fc14l, + 0xa0a91fc10177c387l }, + { 0xff0a3f01ae2c831el,0xbb76ae822b727e16l,0x8f12c8a15a3075b4l, + 0x084cf9889ed20c41l }, + 0 }, + /* 120 */ + { { 0xd98509defca6becfl,0x2fceae807dffb328l,0x5d8a15c44778e8b9l, + 0xd57955b273abf77el }, + { 0x210da79e31b5d4f1l,0xaa52f04b3cfa7a1cl,0xd4d12089dc27c20bl, + 0x8e14ea4202d141f1l }, + 0 }, + /* 121 */ + { { 0xeed50345f2897042l,0x8d05331f43402c4al,0xc8d9c194c8bdfb21l, + 0x597e1a372aa4d158l }, + { 0x0327ec1acf0bd68cl,0x6d4be0dcab024945l,0x5b9c8d7ac9fe3e84l, + 0xca3f0236199b4deal }, + 0 }, + /* 122 */ + { { 0x592a10b56170bd20l,0x0ea897f16d3f5de7l,0xa3363ff144b2ade2l, + 0xbde7fd7e309c07e4l }, + { 0x516bb6d2b8f5432cl,0x210dc1cbe043444bl,0x3db01e6ff8f95b5al, + 0xb623ad0e0a7dd198l }, + 0 }, + /* 123 */ + { { 0xa75bd67560c7b65bl,0xab8c559023a4a289l,0xf8220fd0d7b26795l, + 0xd6aa2e4658ec137bl }, + { 0x10abc00b5138bb85l,0x8c31d121d833a95cl,0xb24ff00b1702a32el, + 0x111662e02dcc513al }, + 0 }, + /* 124 */ + { { 0x78114015efb42b87l,0xbd9f5d701b6c4dffl,0x66ecccd7a7d7c129l, + 0xdb3ee1cb94b750f8l }, + { 0xb26f3db0f34837cfl,0xe7eed18bb9578d4fl,0x5d2cdf937c56657dl, + 0x886a644252206a59l }, + 0 }, + /* 125 */ + { { 0x3c234cfb65b569eal,0x20011141f72119c1l,0x8badc85da15a619el, + 0xa70cf4eb018a17bcl }, + { 0x224f97ae8c4a6a65l,0x36e5cf270134378fl,0xbe3a609e4f7e0960l, + 0xaa4772abd1747b77l }, + 0 }, + /* 126 */ + { { 0x676761317aa60cc0l,0xc79163610368115fl,0xded98bb4bbc1bb5al, + 0x611a6ddc30faf974l }, + { 0x30e78cbcc15ee47al,0x2e8962824e0d96a5l,0x36f35adf3dd9ed88l, + 0x5cfffaf816429c88l }, + 0 }, + /* 127 */ + { { 0xc0d54cff9b7a99cdl,0x7bf3b99d843c45a1l,0x038a908f62c739e1l, + 0x6e5a6b237dc1994cl }, + { 0xef8b454e0ba5db77l,0xb7b8807facf60d63l,0xe591c0c676608378l, + 0x481a238d242dabccl }, + 0 }, + /* 128 */ + { { 0xe3417bc035d0b34al,0x440b386b8327c0a7l,0x8fb7262dac0362d1l, + 0x2c41114ce0cdf943l }, + { 0x2ba5cef1ad95a0b1l,0xc09b37a867d54362l,0x26d6cdd201e486c9l, + 0x20477abf42ff9297l }, + 0 }, + /* 129 */ + { { 0x2f75173c18d65dbfl,0x77bf940e339edad8l,0x7022d26bdcf1001cl, + 0xac66409ac77396b6l }, + { 0x8b0bb36fc6261cc3l,0x213f7bc9190e7e90l,0x6541cebaa45e6c10l, + 0xce8e6975cc122f85l }, + 0 }, + /* 130 */ + { { 0x0f121b41bc0a67d2l,0x62d4760a444d248al,0x0e044f1d659b4737l, + 0x08fde365250bb4a8l }, + { 0xaceec3da848bf287l,0xc2a62182d3369d6el,0x3582dfdc92449482l, + 0x2f7e2fd2565d6cd7l }, + 0 }, + /* 131 */ + { { 0xae4b92dbc3770fa7l,0x095e8d5c379043f9l,0x54f34e9d17761171l, + 0xc65be92e907702ael }, + { 0x2758a303f6fd0a40l,0xe7d822e3bcce784bl,0x7ae4f5854f9767bfl, + 0x4bff8e47d1193b3al }, + 0 }, + /* 132 */ + { { 0xcd41d21f00ff1480l,0x2ab8fb7d0754db16l,0xac81d2efbbe0f3eal, + 0x3e4e4ae65772967dl }, + { 0x7e18f36d3c5303e6l,0x3bd9994b92262397l,0x9ed70e261324c3c0l, + 0x5388aefd58ec6028l }, + 0 }, + /* 133 */ + { { 0xad1317eb5e5d7713l,0x09b985ee75de49dal,0x32f5bc4fc74fb261l, + 0x5cf908d14f75be0el }, + { 0x760435108e657b12l,0xbfd421a5b96ed9e6l,0x0e29f51f8970ccc2l, + 0xa698ba4060f00ce2l }, + 0 }, + /* 134 */ + { { 0x73db1686ef748fecl,0xe6e755a27e9d2cf9l,0x630b6544ce265effl, + 0xb142ef8a7aebad8dl }, + { 0xad31af9f17d5770al,0x66af3b672cb3412fl,0x6bd60d1bdf3359del, + 0xd1896a9658515075l }, + 0 }, + /* 135 */ + { { 0xec5957ab33c41c08l,0x87de94ac5468e2e1l,0x18816b73ac472f6cl, + 0x267b0e0b7981da39l }, + { 0x6e554e5d8e62b988l,0xd8ddc755116d21e7l,0x4610faf03d2a6f99l, + 0xb54e287aa1119393l }, + 0 }, + /* 136 */ + { { 0x0a0122b5178a876bl,0x51ff96ff085104b4l,0x050b31ab14f29f76l, + 0x84abb28b5f87d4e6l }, + { 0xd5ed439f8270790al,0x2d6cb59d85e3f46bl,0x75f55c1b6c1e2212l, + 0xe5436f6717655640l }, + 0 }, + /* 137 */ + { { 0x53f9025e2286e8d5l,0x353c95b4864453bel,0xd832f5bde408e3a0l, + 0x0404f68b5b9ce99el }, + { 0xcad33bdea781e8e5l,0x3cdf5018163c2f5bl,0x575769600119caa3l, + 0x3a4263df0ac1c701l }, + 0 }, + /* 138 */ + { { 0xc2965ecc9aeb596dl,0x01ea03e7023c92b4l,0x4704b4b62e013961l, + 0x0ca8fd3f905ea367l }, + { 0x92523a42551b2b61l,0x1eb7a89c390fcd06l,0xe7f1d2be0392a63el, + 0x96dca2644ddb0c33l }, + 0 }, + /* 139 */ + { { 0x203bb43a387510afl,0x846feaa8a9a36a01l,0xd23a57702f950378l, + 0x4363e2123aad59dcl }, + { 0xca43a1c740246a47l,0xb362b8d2e55dd24dl,0xf9b086045d8faf96l, + 0x840e115cd8bb98c4l }, + 0 }, + /* 140 */ + { { 0xf12205e21023e8a7l,0xc808a8cdd8dc7a0bl,0xe292a272163a5ddfl, + 0x5e0d6abd30ded6d4l }, + { 0x07a721c27cfc0f64l,0x42eec01d0e55ed88l,0x26a7bef91d1f9db2l, + 0x7dea48f42945a25al }, + 0 }, + /* 141 */ + { { 0xabdf6f1ce5060a81l,0xe79f9c72f8f95615l,0xcfd36c5406ac268bl, + 0xabc2a2beebfd16d1l }, + { 0x8ac66f91d3e2eac7l,0x6f10ba63d2dd0466l,0x6790e3770282d31bl, + 0x4ea353946c7eefc1l }, + 0 }, + /* 142 */ + { { 0xed8a2f8d5266309dl,0x0a51c6c081945a3el,0xcecaf45a578c5dc1l, + 0x3a76e6891c94ffc3l }, + { 0x9aace8a47d7b0d0fl,0x963ace968f584a5fl,0x51a30c724e697fbel, + 0x8212a10a465e6464l }, + 0 }, + /* 143 */ + { { 0xef7c61c3cfab8caal,0x18eb8e840e142390l,0xcd1dff677e9733cal, + 0xaa7cab71599cb164l }, + { 0x02fc9273bc837bd1l,0xc06407d0c36af5d7l,0x17621292f423da49l, + 0x40e38073fe0617c3l }, + 0 }, + /* 144 */ + { { 0xf4f80824a7bf9b7cl,0x365d23203fbe30d0l,0xbfbe532097cf9ce3l, + 0xe3604700b3055526l }, + { 0x4dcb99116cc6c2c7l,0x72683708ba4cbee6l,0xdcded434637ad9ecl, + 0x6542d677a3dee15fl }, + 0 }, + /* 145 */ + { { 0x3f32b6d07b6c377al,0x6cb03847903448bel,0xd6fdd3a820da8af7l, + 0xa6534aee09bb6f21l }, + { 0x30a1780d1035facfl,0x35e55a339dcb47e6l,0x6ea50fe1c447f393l, + 0xf3cb672fdc9aef22l }, + 0 }, + /* 146 */ + { { 0xeb3719fe3b55fd83l,0xe0d7a46c875ddd10l,0x33ac9fa905cea784l, + 0x7cafaa2eaae870e7l }, + { 0x9b814d041d53b338l,0xe0acc0a0ef87e6c6l,0xfb93d10811672b0fl, + 0x0aab13c1b9bd522el }, + 0 }, + /* 147 */ + { { 0xddcce278d2681297l,0xcb350eb1b509546al,0x2dc431737661aaf2l, + 0x4b91a602847012e9l }, + { 0xdcff109572f8ddcfl,0x08ebf61e9a911af4l,0x48f4360ac372430el, + 0x49534c5372321cabl }, + 0 }, + /* 148 */ + { { 0x83df7d71f07b7e9dl,0xa478efa313cd516fl,0x78ef264b6c047ee3l, + 0xcaf46c4fd65ac5eel }, + { 0xa04d0c7792aa8266l,0xedf45466913684bbl,0x56e65168ae4b16b0l, + 0x14ce9e5704c6770fl }, + 0 }, + /* 149 */ + { { 0x99445e3e965e8f91l,0xd3aca1bacb0f2492l,0xd31cc70f90c8a0a0l, + 0x1bb708a53e4c9a71l }, + { 0xd5ca9e69558bdd7al,0x734a0508018a26b1l,0xb093aa714c9cf1ecl, + 0xf9d126f2da300102l }, + 0 }, + /* 150 */ + { { 0x749bca7aaff9563el,0xdd077afeb49914a0l,0xe27a0311bf5f1671l, + 0x807afcb9729ecc69l }, + { 0x7f8a9337c9b08b77l,0x86c3a785443c7e38l,0x85fafa59476fd8bal, + 0x751adcd16568cd8cl }, + 0 }, + /* 151 */ + { { 0x8aea38b410715c0dl,0xd113ea718f7697f7l,0x665eab1493fbf06dl, + 0x29ec44682537743fl }, + { 0x3d94719cb50bebbcl,0x399ee5bfe4505422l,0x90cd5b3a8d2dedb1l, + 0xff9370e392a4077dl }, + 0 }, + /* 152 */ + { { 0x59a2d69bc6b75b65l,0x4188f8d5266651c5l,0x28a9f33e3de9d7d2l, + 0x9776478ba2a9d01al }, + { 0x8852622d929af2c7l,0x334f5d6d4e690923l,0xce6cc7e5a89a51e9l, + 0x74a6313fac2f82fal }, + 0 }, + /* 153 */ + { { 0xb2f4dfddb75f079cl,0x85b07c9518e36fbbl,0x1b6cfcf0e7cd36ddl, + 0xab75be150ff4863dl }, + { 0x81b367c0173fc9b7l,0xb90a7420d2594fd0l,0x15fdbf03c4091236l, + 0x4ebeac2e0b4459f6l }, + 0 }, + /* 154 */ + { { 0xeb6c5fe75c9f2c53l,0xd25220118eae9411l,0xc8887633f95ac5d8l, + 0xdf99887b2c1baffcl }, + { 0xbb78eed2850aaecbl,0x9d49181b01d6a272l,0x978dd511b1cdbcacl, + 0x27b040a7779f4058l }, + 0 }, + /* 155 */ + { { 0x90405db7f73b2eb2l,0xe0df85088e1b2118l,0x501b71525962327el, + 0xb393dd37e4cfa3f5l }, + { 0xa1230e7b3fd75165l,0xd66344c2bcd33554l,0x6c36f1be0f7b5022l, + 0x09588c12d0463419l }, + 0 }, + /* 156 */ + { { 0xe086093f02601c3bl,0xfb0252f8cf5c335fl,0x955cf280894aff28l, + 0x81c879a9db9f648bl }, + { 0x040e687cc6f56c51l,0xfed471693f17618cl,0x44f88a419059353bl, + 0xfa0d48f55fc11bc4l }, + 0 }, + /* 157 */ + { { 0xbc6e1c9de1608e4dl,0x010dda113582822cl,0xf6b7ddc1157ec2d7l, + 0x8ea0e156b6a367d6l }, + { 0xa354e02f2383b3b4l,0x69966b943f01f53cl,0x4ff6632b2de03ca5l, + 0x3f5ab924fa00b5acl }, + 0 }, + /* 158 */ + { { 0x337bb0d959739efbl,0xc751b0f4e7ebec0dl,0x2da52dd6411a67d1l, + 0x8bc768872b74256el }, + { 0xa5be3b7282d3d253l,0xa9f679a1f58d779fl,0xa1cac168e16767bbl, + 0xb386f19060fcf34fl }, + 0 }, + /* 159 */ + { { 0x31f3c1352fedcfc2l,0x5396bf6262f8af0dl,0x9a02b4eae57288c2l, + 0x4cb460f71b069c4dl }, + { 0xae67b4d35b8095eal,0x92bbf8596fc07603l,0xe1475f66b614a165l, + 0x52c0d50895ef5223l }, + 0 }, + /* 160 */ + { { 0x231c210e15339848l,0xe87a28e870778c8dl,0x9d1de6616956e170l, + 0x4ac3c9382bb09c0bl }, + { 0x19be05516998987dl,0x8b2376c4ae09f4d6l,0x1de0b7651a3f933dl, + 0x380d94c7e39705f4l }, + 0 }, + /* 161 */ + { { 0x01a355aa81542e75l,0x96c724a1ee01b9b7l,0x6b3a2977624d7087l, + 0x2ce3e171de2637afl }, + { 0xcfefeb49f5d5bc1al,0xa655607e2777e2b5l,0x4feaac2f9513756cl, + 0x2e6cd8520b624e4dl }, + 0 }, + /* 162 */ + { { 0x3685954b8c31c31dl,0x68533d005bf21a0cl,0x0bd7626e75c79ec9l, + 0xca17754742c69d54l }, + { 0xcc6edafff6d2dbb2l,0xfd0d8cbd174a9d18l,0x875e8793aa4578e8l, + 0xa976a7139cab2ce6l }, + 0 }, + /* 163 */ + { { 0x0a651f1b93fb353dl,0xd75cab8b57fcfa72l,0xaa88cfa731b15281l, + 0x8720a7170a1f4999l }, + { 0x8c3e8d37693e1b90l,0xd345dc0b16f6dfc3l,0x8ea8d00ab52a8742l, + 0x9719ef29c769893cl }, + 0 }, + /* 164 */ + { { 0x820eed8d58e35909l,0x9366d8dc33ddc116l,0xd7f999d06e205026l, + 0xa5072976e15704c1l }, + { 0x002a37eac4e70b2el,0x84dcf6576890aa8al,0xcd71bf18645b2a5cl, + 0x99389c9df7b77725l }, + 0 }, + /* 165 */ + { { 0x238c08f27ada7a4bl,0x3abe9d03fd389366l,0x6b672e89766f512cl, + 0xa88806aa202c82e4l }, + { 0x6602044ad380184el,0xa8cb78c4126a8b85l,0x79d670c0ad844f17l, + 0x0043bffb4738dcfel }, + 0 }, + /* 166 */ + { { 0x8d59b5dc36d5192el,0xacf885d34590b2afl,0x83566d0a11601781l, + 0x52f3ef01ba6c4866l }, + { 0x3986732a0edcb64dl,0x0a482c238068379fl,0x16cbe5fa7040f309l, + 0x3296bd899ef27e75l }, + 0 }, + /* 167 */ + { { 0x476aba89454d81d7l,0x9eade7ef51eb9b3cl,0x619a21cd81c57986l, + 0x3b90febfaee571e9l }, + { 0x9393023e5496f7cbl,0x55be41d87fb51bc4l,0x03f1dd4899beb5cel, + 0x6e88069d9f810b18l }, + 0 }, + /* 168 */ + { { 0xce37ab11b43ea1dbl,0x0a7ff1a95259d292l,0x851b02218f84f186l, + 0xa7222beadefaad13l }, + { 0xa2ac78ec2b0a9144l,0x5a024051f2fa59c5l,0x91d1eca56147ce38l, + 0xbe94d523bc2ac690l }, + 0 }, + /* 169 */ + { { 0x72f4945e0b226ce7l,0xb8afd747967e8b70l,0xedea46f185a6c63el, + 0x7782defe9be8c766l }, + { 0x760d2aa43db38626l,0x460ae78776f67ad1l,0x341b86fc54499cdbl, + 0x03838567a2892e4bl }, + 0 }, + /* 170 */ + { { 0x2d8daefd79ec1a0fl,0x3bbcd6fdceb39c97l,0xf5575ffc58f61a95l, + 0xdbd986c4adf7b420l }, + { 0x81aa881415f39eb7l,0x6ee2fcf5b98d976cl,0x5465475dcf2f717dl, + 0x8e24d3c46860bbd0l }, + 0 }, + /* 171 */ + { { 0x749d8e549a587390l,0x12bb194f0cbec588l,0x46e07da4b25983c6l, + 0x541a99c4407bafc8l }, + { 0xdb241692624c8842l,0x6044c12ad86c05ffl,0xc59d14b44f7fcf62l, + 0xc0092c49f57d35d1l }, + 0 }, + /* 172 */ + { { 0xd3cc75c3df2e61efl,0x7e8841c82e1b35cal,0xc62d30d1909f29f4l, + 0x75e406347286944dl }, + { 0xe7d41fc5bbc237d0l,0xc9537bf0ec4f01c9l,0x91c51a16282bd534l, + 0x5b7cb658c7848586l }, + 0 }, + /* 173 */ + { { 0x964a70848a28ead1l,0x802dc508fd3b47f6l,0x9ae4bfd1767e5b39l, + 0x7ae13eba8df097a1l }, + { 0xfd216ef8eadd384el,0x0361a2d9b6b2ff06l,0x204b98784bcdb5f3l, + 0x787d8074e2a8e3fdl }, + 0 }, + /* 174 */ + { { 0xc5e25d6b757fbb1cl,0xe47bddb2ca201debl,0x4a55e9a36d2233ffl, + 0x5c2228199ef28484l }, + { 0x773d4a8588315250l,0x21b21a2b827097c1l,0xab7c4ea1def5d33fl, + 0xe45d37abbaf0f2b0l }, + 0 }, + /* 175 */ + { { 0xd2df1e3428511c8al,0xebb229c8bdca6cd3l,0x578a71a7627c39a7l, + 0xed7bc12284dfb9d3l }, + { 0xcf22a6df93dea561l,0x5443f18dd48f0ed1l,0xd8b861405bad23e8l, + 0xaac97cc945ca6d27l }, + 0 }, + /* 176 */ + { { 0xeb54ea74a16bd00al,0xd839e9adf5c0bcc1l,0x092bb7f11f9bfc06l, + 0x318f97b31163dc4el }, + { 0xecc0c5bec30d7138l,0x44e8df23abc30220l,0x2bb7972fb0223606l, + 0xfa41faa19a84ff4dl }, + 0 }, + /* 177 */ + { { 0x4402d974a6642269l,0xc81814ce9bb783bdl,0x398d38e47941e60bl, + 0x38bb6b2c1d26e9e2l }, + { 0xc64e4a256a577f87l,0x8b52d253dc11fe1cl,0xff336abf62280728l, + 0x94dd0905ce7601a5l }, + 0 }, + /* 178 */ + { { 0x156cf7dcde93f92al,0xa01333cb89b5f315l,0x02404df9c995e750l, + 0x92077867d25c2ae9l }, + { 0xe2471e010bf39d44l,0x5f2c902096bb53d7l,0x4c44b7b35c9c3d8fl, + 0x81e8428bd29beb51l }, + 0 }, + /* 179 */ + { { 0x6dd9c2bac477199fl,0x8cb8eeee6b5ecdd9l,0x8af7db3fee40fd0el, + 0x1b94ab62dbbfa4b1l }, + { 0x44f0d8b3ce47f143l,0x51e623fc63f46163l,0xf18f270fcc599383l, + 0x06a38e28055590eel }, + 0 }, + /* 180 */ + { { 0x2e5b0139b3355b49l,0x20e26560b4ebf99bl,0xc08ffa6bd269f3dcl, + 0xa7b36c2083d9d4f8l }, + { 0x64d15c3a1b3e8830l,0xd5fceae1a89f9c0bl,0xcfeee4a2e2d16930l, + 0xbe54c6b4a2822a20l }, + 0 }, + /* 181 */ + { { 0xd6cdb3df8d91167cl,0x517c3f79e7a6625el,0x7105648f346ac7f4l, + 0xbf30a5abeae022bbl }, + { 0x8e7785be93828a68l,0x5161c3327f3ef036l,0xe11b5feb592146b2l, + 0xd1c820de2732d13al }, + 0 }, + /* 182 */ + { { 0x043e13479038b363l,0x58c11f546b05e519l,0x4fe57abe6026cad1l, + 0xb7d17bed68a18da3l }, + { 0x44ca5891e29c2559l,0x4f7a03765bfffd84l,0x498de4af74e46948l, + 0x3997fd5e6412cc64l }, + 0 }, + /* 183 */ + { { 0xf20746828bd61507l,0x29e132d534a64d2al,0xffeddfb08a8a15e3l, + 0x0eeb89293c6c13e8l }, + { 0xe9b69a3ea7e259f8l,0xce1db7e6d13e7e67l,0x277318f6ad1fa685l, + 0x228916f8c922b6efl }, + 0 }, + /* 184 */ + { { 0x959ae25b0a12ab5bl,0xcc11171f957bc136l,0x8058429ed16e2b0cl, + 0xec05ad1d6e93097el }, + { 0x157ba5beac3f3708l,0x31baf93530b59d77l,0x47b55237118234e5l, + 0x7d3141567ff11b37l }, + 0 }, + /* 185 */ + { { 0x7bd9c05cf6dfefabl,0xbe2f2268dcb37707l,0xe53ead973a38bb95l, + 0xe9ce66fc9bc1d7a3l }, + { 0x75aa15766f6a02a1l,0x38c087df60e600edl,0xf8947f3468cdc1b9l, + 0xd9650b0172280651l }, + 0 }, + /* 186 */ + { { 0x504b4c4a5a057e60l,0xcbccc3be8def25e4l,0xa635320817c1ccbdl, + 0x14d6699a804eb7a2l }, + { 0x2c8a8415db1f411al,0x09fbaf0bf80d769cl,0xb4deef901c2f77adl, + 0x6f4c68410d43598al }, + 0 }, + /* 187 */ + { { 0x8726df4e96c24a96l,0x534dbc85fcbd99a3l,0x3c466ef28b2ae30al, + 0x4c4350fd61189abbl }, + { 0x2967f716f855b8dal,0x41a42394463c38a1l,0xc37e1413eae93343l, + 0xa726d2425a3118b5l }, + 0 }, + /* 188 */ + { { 0xdae6b3ee948c1086l,0xf1de503dcbd3a2e1l,0x3f35ed3f03d022f3l, + 0x13639e82cc6cf392l }, + { 0x9ac938fbcdafaa86l,0xf45bc5fb2654a258l,0x1963b26e45051329l, + 0xca9365e1c1a335a3l }, + 0 }, + /* 189 */ + { { 0x3615ac754c3b2d20l,0x742a5417904e241bl,0xb08521c4cc9d071dl, + 0x9ce29c34970b72a5l }, + { 0x8cc81f736d3e0ad6l,0x8060da9ef2f8434cl,0x35ed1d1a6ce862d9l, + 0x48c4abd7ab42af98l }, + 0 }, + /* 190 */ + { { 0xd221b0cc40c7485al,0xead455bbe5274dbfl,0x493c76989263d2e8l, + 0x78017c32f67b33cbl }, + { 0xb9d35769930cb5eel,0xc0d14e940c408ed2l,0xf8b7bf55272f1a4dl, + 0x53cd0454de5c1c04l }, + 0 }, + /* 191 */ + { { 0xbcd585fa5d28ccacl,0x5f823e56005b746el,0x7c79f0a1cd0123aal, + 0xeea465c1d3d7fa8fl }, + { 0x7810659f0551803bl,0x6c0b599f7ce6af70l,0x4195a77029288e70l, + 0x1b6e42a47ae69193l }, + 0 }, + /* 192 */ + { { 0x2e80937cf67d04c3l,0x1e312be289eeb811l,0x56b5d88792594d60l, + 0x0224da14187fbd3dl }, + { 0x87abb8630c5fe36fl,0x580f3c604ef51f5fl,0x964fb1bfb3b429ecl, + 0x60838ef042bfff33l }, + 0 }, + /* 193 */ + { { 0x432cb2f27e0bbe99l,0x7bda44f304aa39eel,0x5f497c7a9fa93903l, + 0x636eb2022d331643l }, + { 0xfcfd0e6193ae00aal,0x875a00fe31ae6d2fl,0xf43658a29f93901cl, + 0x8844eeb639218bacl }, + 0 }, + /* 194 */ + { { 0x114171d26b3bae58l,0x7db3df7117e39f3el,0xcd37bc7f81a8eadal, + 0x27ba83dc51fb789el }, + { 0xa7df439ffbf54de5l,0x7277030bb5fe1a71l,0x42ee8e35db297a48l, + 0xadb62d3487f3a4abl }, + 0 }, + /* 195 */ + { { 0x9b1168a2a175df2al,0x082aa04f618c32e9l,0xc9e4f2e7146b0916l, + 0xb990fd7675e7c8b2l }, + { 0x0829d96b4df37313l,0x1c205579d0b40789l,0x66c9ae4a78087711l, + 0x81707ef94d10d18dl }, + 0 }, + /* 196 */ + { { 0x97d7cab203d6ff96l,0x5b851bfc0d843360l,0x268823c4d042db4bl, + 0x3792daead5a8aa5cl }, + { 0x52818865941afa0bl,0xf3e9e74142d83671l,0x17c825275be4e0a7l, + 0x5abd635e94b001bal }, + 0 }, + /* 197 */ + { { 0x727fa84e0ac4927cl,0xe3886035a7c8cf23l,0xa4bcd5ea4adca0dfl, + 0x5995bf21846ab610l }, + { 0xe90f860b829dfa33l,0xcaafe2ae958fc18bl,0x9b3baf4478630366l, + 0x44c32ca2d483411el }, + 0 }, + /* 198 */ + { { 0xa74a97f1e40ed80cl,0x5f938cb131d2ca82l,0x53f2124b7c2d6ad9l, + 0x1f2162fb8082a54cl }, + { 0x7e467cc5720b173el,0x40e8a666085f12f9l,0x8cebc20e4c9d65dcl, + 0x8f1d402bc3e907c9l }, + 0 }, + /* 199 */ + { { 0x4f592f9cfbc4058al,0xb15e14b6292f5670l,0xc55cfe37bc1d8c57l, + 0xb1980f43926edbf9l }, + { 0x98c33e0932c76b09l,0x1df5279d33b07f78l,0x6f08ead4863bb461l, + 0x2828ad9b37448e45l }, + 0 }, + /* 200 */ + { { 0x696722c4c4cf4ac5l,0xf5ac1a3fdde64afbl,0x0551baa2e0890832l, + 0x4973f1275a14b390l }, + { 0xe59d8335322eac5dl,0x5e07eef50bd9b568l,0xab36720fa2588393l, + 0x6dac8ed0db168ac7l }, + 0 }, + /* 201 */ + { { 0xf7b545aeeda835efl,0x4aa113d21d10ed51l,0x035a65e013741b09l, + 0x4b23ef5920b9de4cl }, + { 0xe82bb6803c4c7341l,0xd457706d3f58bc37l,0x73527863a51e3ee8l, + 0x4dd71534ddf49a4el }, + 0 }, + /* 202 */ + { { 0xbf94467295476cd9l,0x648d072fe31a725bl,0x1441c8b8fc4b67e0l, + 0xfd3170002f4a4dbbl }, + { 0x1cb43ff48995d0e1l,0x76e695d10ef729aal,0xe0d5f97641798982l, + 0x14fac58c9569f365l }, + 0 }, + /* 203 */ + { { 0xad9a0065f312ae18l,0x51958dc0fcc93fc9l,0xd9a142408a7d2846l, + 0xed7c765136abda50l }, + { 0x46270f1a25d4abbcl,0x9b5dd8f3f1a113eal,0xc609b0755b51952fl, + 0xfefcb7f74d2e9f53l }, + 0 }, + /* 204 */ + { { 0xbd09497aba119185l,0xd54e8c30aac45ba4l,0x492479deaa521179l, + 0x1801a57e87e0d80bl }, + { 0x073d3f8dfcafffb0l,0x6cf33c0bae255240l,0x781d763b5b5fdfbcl, + 0x9f8fc11e1ead1064l }, + 0 }, + /* 205 */ + { { 0x1583a1715e69544cl,0x0eaf8567f04b7813l,0x1e22a8fd278a4c32l, + 0xa9d3809d3d3a69a9l }, + { 0x936c2c2c59a2da3bl,0x38ccbcf61895c847l,0x5e65244e63d50869l, + 0x3006b9aee1178ef7l }, + 0 }, + /* 206 */ + { { 0x0bb1f2b0c9eead28l,0x7eef635d89f4dfbcl,0x074757fdb2ce8939l, + 0x0ab85fd745f8f761l }, + { 0xecda7c933e5b4549l,0x4be2bb5c97922f21l,0x261a1274b43b8040l, + 0xb122d67511e942c2l }, + 0 }, + /* 207 */ + { { 0x3be607be66a5ae7al,0x01e703fa76adcbe3l,0xaf9043014eb6e5c5l, + 0x9f599dc1097dbaecl }, + { 0x6d75b7180ff250edl,0x8eb91574349a20dcl,0x425605a410b227a3l, + 0x7d5528e08a294b78l }, + 0 }, + /* 208 */ + { { 0xf0f58f6620c26defl,0x025585ea582b2d1el,0xfbe7d79b01ce3881l, + 0x28ccea01303f1730l }, + { 0xd1dabcd179644ba5l,0x1fc643e806fff0b8l,0xa60a76fc66b3e17bl, + 0xc18baf48a1d013bfl }, + 0 }, + /* 209 */ + { { 0x34e638c85dc4216dl,0x00c01067206142acl,0xd453a17195f5064al, + 0x9def809db7a9596bl }, + { 0x41e8642e67ab8d2cl,0xb42404336237a2b6l,0x7d506a6d64c4218bl, + 0x0357f8b068808ce5l }, + 0 }, + /* 210 */ + { { 0x8e9dbe644cd2cc88l,0xcc61c28df0b8f39dl,0x4a309874cd30a0c8l, + 0xe4a01add1b489887l }, + { 0x2ed1eeacf57cd8f9l,0x1b767d3ebd594c48l,0xa7295c717bd2f787l, + 0x466d7d79ce10cc30l }, + 0 }, + /* 211 */ + { { 0x47d318929dada2c7l,0x4fa0a6c38f9aa27dl,0x90e4fd28820a59e1l, + 0xc672a522451ead1al }, + { 0x30607cc85d86b655l,0xf0235d3bf9ad4af1l,0x99a08680571172a6l, + 0x5e3d64faf2a67513l }, + 0 }, + /* 212 */ + { { 0xaa6410c79b3b4416l,0xcd8fcf85eab26d99l,0x5ebff74adb656a74l, + 0x6c8a7a95eb8e42fcl }, + { 0x10c60ba7b02a63bdl,0x6b2f23038b8f0047l,0x8c6c3738312d90b0l, + 0x348ae422ad82ca91l }, + 0 }, + /* 213 */ + { { 0x7f4746635ccda2fbl,0x22accaa18e0726d2l,0x85adf782492b1f20l, + 0xc1074de0d9ef2d2el }, + { 0xfcf3ce44ae9a65b3l,0xfd71e4ac05d7151bl,0xd4711f50ce6a9788l, + 0xfbadfbdbc9e54ffcl }, + 0 }, + /* 214 */ + { { 0x1713f1cd20a99363l,0xb915658f6cf22775l,0x968175cd24d359b2l, + 0xb7f976b483716fcdl }, + { 0x5758e24d5d6dbf74l,0x8d23bafd71c3af36l,0x48f477600243dfe3l, + 0xf4d41b2ecafcc805l }, + 0 }, + /* 215 */ + { { 0x51f1cf28fdabd48dl,0xce81be3632c078a4l,0x6ace2974117146e9l, + 0x180824eae0160f10l }, + { 0x0387698b66e58358l,0x63568752ce6ca358l,0x82380e345e41e6c5l, + 0x67e5f63983cf6d25l }, + 0 }, + /* 216 */ + { { 0xf89ccb8dcf4899efl,0x949015f09ebb44c0l,0x546f9276b2598ec9l, + 0x9fef789a04c11fc6l }, + { 0x6d367ecf53d2a071l,0xb10e1a7fa4519b09l,0xca6b3fb0611e2eefl, + 0xbc80c181a99c4e20l }, + 0 }, + /* 217 */ + { { 0x972536f8e5eb82e6l,0x1a484fc7f56cb920l,0xc78e217150b5da5el, + 0x49270e629f8cdf10l }, + { 0x1a39b7bbea6b50adl,0x9a0284c1a2388ffcl,0x5403eb178107197bl, + 0xd2ee52f961372f7fl }, + 0 }, + /* 218 */ + { { 0xd37cd28588e0362al,0x442fa8a78fa5d94dl,0xaff836e5a434a526l, + 0xdfb478bee5abb733l }, + { 0xa91f1ce7673eede6l,0xa5390ad42b5b2f04l,0x5e66f7bf5530da2fl, + 0xd9a140b408df473al }, + 0 }, + /* 219 */ + { { 0x0e0221b56e8ea498l,0x623478293563ee09l,0xe06b8391335d2adel, + 0x760c058d623f4b1al }, + { 0x0b89b58cc198aa79l,0xf74890d2f07aba7fl,0x4e204110fde2556al, + 0x7141982d8f190409l }, + 0 }, + /* 220 */ + { { 0x6f0a0e334d4b0f45l,0xd9280b38392a94e1l,0x3af324c6b3c61d5el, + 0x3af9d1ce89d54e47l }, + { 0xfd8f798120930371l,0xeda2664c21c17097l,0x0e9545dcdc42309bl, + 0xb1f815c373957dd6l }, + 0 }, + /* 221 */ + { { 0x84faa78e89fec44al,0xc8c2ae473caa4cafl,0x691c807dc1b6a624l, + 0xa41aed141543f052l }, + { 0x424353997d5ffe04l,0x8bacb2df625b6e20l,0x85d660be87817775l, + 0xd6e9c1dd86fb60efl }, + 0 }, + /* 222 */ + { { 0x3aa2e97ec6853264l,0x771533b7e2304a0bl,0x1b912bb7b8eae9bel, + 0x9c9c6e10ae9bf8c2l }, + { 0xa2309a59e030b74cl,0x4ed7494d6a631e90l,0x89f44b23a49b79f2l, + 0x566bd59640fa61b6l }, + 0 }, + /* 223 */ + { { 0x066c0118c18061f3l,0x190b25d37c83fc70l,0xf05fc8e027273245l, + 0xcf2c7390f525345el }, + { 0xa09bceb410eb30cfl,0xcfd2ebba0d77703al,0xe842c43a150ff255l, + 0x02f517558aa20979l }, + 0 }, + /* 224 */ + { { 0x396ef794addb7d07l,0x0b4fc74224455500l,0xfaff8eacc78aa3cel, + 0x14e9ada5e8d4d97dl }, + { 0xdaa480a12f7079e2l,0x45baa3cde4b0800el,0x01765e2d7838157dl, + 0xa0ad4fab8e9d9ae8l }, + 0 }, + /* 225 */ + { { 0x0bfb76214a653618l,0x1872813c31eaaa5fl,0x1553e73744949d5el, + 0xbcd530b86e56ed1el }, + { 0x169be85332e9c47bl,0xdc2776feb50059abl,0xcdba9761192bfbb4l, + 0x909283cf6979341dl }, + 0 }, + /* 226 */ + { { 0x67b0032476e81a13l,0x9bee1a9962171239l,0x08ed361bd32e19d6l, + 0x35eeb7c9ace1549al }, + { 0x1280ae5a7e4e5bdcl,0x2dcd2cd3b6ceec6el,0x52e4224c6e266bc1l, + 0x9a8b2cf4448ae864l }, + 0 }, + /* 227 */ + { { 0xf6471bf209d03b59l,0xc90e62a3b65af2abl,0xff7ff168ebd5eec9l, + 0x6bdb60f4d4491379l }, + { 0xdadafebc8a55bc30l,0xc79ead1610097fe0l,0x42e197414c1e3bddl, + 0x01ec3cfd94ba08a9l }, + 0 }, + /* 228 */ + { { 0xba6277ebdc9485c2l,0x48cc9a7922fb10c7l,0x4f61d60f70a28d8al, + 0xd1acb1c0475464f6l }, + { 0xd26902b126f36612l,0x59c3a44ee0618d8bl,0x4df8a813308357eel, + 0x7dcd079d405626c2l }, + 0 }, + /* 229 */ + { { 0x5ce7d4d3f05a4b48l,0xadcd295237230772l,0xd18f7971812a915al, + 0x0bf53589377d19b8l }, + { 0x35ecd95a6c68ea73l,0xc7f3bbca823a584dl,0x9fb674c6f473a723l, + 0xd28be4d9e16686fcl }, + 0 }, + /* 230 */ + { { 0x5d2b990638fa8e4bl,0x559f186e893fd8fcl,0x3a6de2aa436fb6fcl, + 0xd76007aa510f88cel }, + { 0x2d10aab6523a4988l,0xb455cf4474dd0273l,0x7f467082a3407278l, + 0xf2b52f68b303bb01l }, + 0 }, + /* 231 */ + { { 0x0d57eafa9835b4cal,0x2d2232fcbb669cbcl,0x8eeeb680c6643198l, + 0xd8dbe98ecc5aed3al }, + { 0xcba9be3fc5a02709l,0x30be68e5f5ba1fa8l,0xfebd43cdf10ea852l, + 0xe01593a3ee559705l }, + 0 }, + /* 232 */ + { { 0xd3e5af50ea75a0a6l,0x512226ac57858033l,0x6fe6d50fd0176406l, + 0xafec07b1aeb8ef06l }, + { 0x7fb9956780bb0a31l,0x6f1af3cc37309aael,0x9153a15a01abf389l, + 0xa71b93546e2dbfddl }, + 0 }, + /* 233 */ + { { 0xbf8e12e018f593d2l,0xd1a90428a078122bl,0x150505db0ba4f2adl, + 0x53a2005c628523d9l }, + { 0x07c8b639e7f2b935l,0x2bff975ac182961al,0x86bceea77518ca2cl, + 0xbf47d19b3d588e3dl }, + 0 }, + /* 234 */ + { { 0x672967a7dd7665d5l,0x4e3030572f2f4de5l,0x144005ae80d4903fl, + 0x001c2c7f39c9a1b6l }, + { 0x143a801469efc6d6l,0xc810bdaa7bc7a724l,0x5f65670ba78150a4l, + 0xfdadf8e786ffb99bl }, + 0 }, + /* 235 */ + { { 0xfd38cb88ffc00785l,0x77fa75913b48eb67l,0x0454d055bf368fbcl, + 0x3a838e4d5aa43c94l }, + { 0x561663293e97bb9al,0x9eb93363441d94d9l,0x515591a60adb2a83l, + 0x3cdb8257873e1da3l }, + 0 }, + /* 236 */ + { { 0x137140a97de77eabl,0xf7e1c50d41648109l,0x762dcad2ceb1d0dfl, + 0x5a60cc89f1f57fbal }, + { 0x80b3638240d45673l,0x1b82be195913c655l,0x057284b8dd64b741l, + 0x922ff56fdbfd8fc0l }, + 0 }, + /* 237 */ + { { 0x1b265deec9a129a1l,0xa5b1ce57cc284e04l,0x04380c46cebfbe3cl, + 0x72919a7df6c5cd62l }, + { 0x298f453a8fb90f9al,0xd719c00b88e4031bl,0xe32c0e77796f1856l, + 0x5e7917803624089al }, + 0 }, + /* 238 */ + { { 0x5c16ec557f63cdfbl,0x8e6a3571f1cae4fdl,0xfce26bea560597cal, + 0x4e0a5371e24c2fabl }, + { 0x276a40d3a5765357l,0x3c89af440d73a2b4l,0xb8f370ae41d11a32l, + 0xf5ff7818d56604eel }, + 0 }, + /* 239 */ + { { 0xfbf3e3fe1a09df21l,0x26d5d28ee66e8e47l,0x2096bd0a29c89015l, + 0xe41df0e9533f5e64l }, + { 0x305fda40b3ba9e3fl,0xf2340ceb2604d895l,0x0866e1927f0367c7l, + 0x8edd7d6eac4f155fl }, + 0 }, + /* 240 */ + { { 0xc9a1dc0e0bfc8ff3l,0x14efd82be936f42fl,0x67016f7ccca381efl, + 0x1432c1caed8aee96l }, + { 0xec68482970b23c26l,0xa64fe8730735b273l,0xe389f6e5eaef0f5al, + 0xcaef480b5ac8d2c6l }, + 0 }, + /* 241 */ + { { 0x5245c97875315922l,0xd82951713063cca5l,0xf3ce60d0b64ef2cbl, + 0xd0ba177e8efae236l }, + { 0x53a9ae8fb1b3af60l,0x1a796ae53d2da20el,0x01d63605df9eef28l, + 0xf31c957c1c54ae16l }, + 0 }, + /* 242 */ + { { 0xc0f58d5249cc4597l,0xdc5015b0bae0a028l,0xefc5fc55734a814al, + 0x013404cb96e17c3al }, + { 0xb29e2585c9a824bfl,0xd593185e001eaed7l,0x8d6ee68261ef68acl, + 0x6f377c4b91933e6cl }, + 0 }, + /* 243 */ + { { 0x9f93bad1a8333fd2l,0xa89302025a2a95b8l,0x211e5037eaf75acel, + 0x6dba3e4ed2d09506l }, + { 0xa48ef98cd04399cdl,0x1811c66ee6b73adel,0x72f60752c17ecaf3l, + 0xf13cf3423becf4a7l }, + 0 }, + /* 244 */ + { { 0xceeb9ec0a919e2ebl,0x83a9a195f62c0f68l,0xcfba3bb67aba2299l, + 0xc83fa9a9274bbad3l }, + { 0x0d7d1b0b62fa1ce0l,0xe58b60f53418efbfl,0xbfa8ef9e52706f04l, + 0xb49d70f45d702683l }, + 0 }, + /* 245 */ + { { 0x914c7510fad5513bl,0x05f32eecb1751e2dl,0x6d850418d9fb9d59l, + 0x59cfadbb0c30f1cfl }, + { 0xe167ac2355cb7fd6l,0x249367b8820426a3l,0xeaeec58c90a78864l, + 0x5babf362354a4b67l }, + 0 }, + /* 246 */ + { { 0x37c981d1ee424865l,0x8b002878f2e5577fl,0x702970f1b9e0c058l, + 0x6188c6a79026c8f0l }, + { 0x06f9a19bd0f244dal,0x1ecced5cfb080873l,0x35470f9b9f213637l, + 0x993fe475df50b9d9l }, + 0 }, + /* 247 */ + { { 0x68e31cdf9b2c3609l,0x84eb19c02c46d4eal,0x7ac9ec1a9a775101l, + 0x81f764664c80616bl }, + { 0x1d7c2a5a75fbe978l,0x6743fed3f183b356l,0x838d1f04501dd2bfl, + 0x564a812a5fe9060dl }, + 0 }, + /* 248 */ + { { 0x7a5a64f4fa817d1dl,0x55f96844bea82e0fl,0xb5ff5a0fcd57f9aal, + 0x226bf3cf00e51d6cl }, + { 0xd6d1a9f92f2833cfl,0x20a0a35a4f4f89a8l,0x11536c498f3f7f77l, + 0x68779f47ff257836l }, + 0 }, + /* 249 */ + { { 0x79b0c1c173043d08l,0xa54467741fc020fal,0xd3767e289a6d26d0l, + 0x97bcb0d1eb092e0bl }, + { 0x2ab6eaa8f32ed3c3l,0xc8a4f151b281bc48l,0x4d1bf4f3bfa178f3l, + 0xa872ffe80a784655l }, + 0 }, + /* 250 */ + { { 0xb1ab7935a32b2086l,0xe1eb710e8160f486l,0x9bd0cd913b6ae6bel, + 0x02812bfcb732a36al }, + { 0xa63fd7cacf605318l,0x646e5d50fdfd6d1dl,0xa1d683982102d619l, + 0x07391cc9fe5396afl }, + 0 }, + /* 251 */ + { { 0xc50157f08b80d02bl,0x6b8333d162877f7fl,0x7aca1af878d542ael, + 0x355d2adc7e6d2a08l }, + { 0xb41f335a287386e1l,0xfd272a94f8e43275l,0x286ca2cde79989eal, + 0x3dc2b1e37c2a3a79l }, + 0 }, + /* 252 */ + { { 0xd689d21c04581352l,0x0a00c825376782bel,0x203bd5909fed701fl, + 0xc47869103ccd846bl }, + { 0x5dba770824c768edl,0x72feea026841f657l,0x73313ed56accce0el, + 0xccc42968d5bb4d32l }, + 0 }, + /* 253 */ + { { 0x94e50de13d7620b9l,0xd89a5c8a5992a56al,0xdc007640675487c9l, + 0xe147eb42aa4871cfl }, + { 0x274ab4eeacf3ae46l,0xfd4936fb50350fbel,0xdf2afe4748c840eal, + 0x239ac047080e96e3l }, + 0 }, + /* 254 */ + { { 0x481d1f352bfee8d4l,0xce80b5cffa7b0fecl,0x105c4c9e2ce9af3cl, + 0xc55fa1a3f5f7e59dl }, + { 0x3186f14e8257c227l,0xc5b1653f342be00bl,0x09afc998aa904fb2l, + 0x094cd99cd4f4b699l }, + 0 }, + /* 255 */ + { { 0x8a981c84d703bebal,0x8631d15032ceb291l,0xa445f2c9e3bd49ecl, + 0xb90a30b642abad33l }, + { 0xb465404fb4a5abf9l,0x004750c375db7603l,0x6f9a42ccca35d89fl, + 0x019f8b9a1b7924f7l }, + 0 }, +}; + +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_base_4(sp_point* r, sp_digit* k, + int map, void* heap) +{ + return sp_256_ecc_mulmod_stripe_4(r, &p256_base, p256_table, + k, map, heap); +} + +#ifdef HAVE_INTEL_AVX2 +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_base_avx2_4(sp_point* r, sp_digit* k, + int map, void* heap) +{ + return sp_256_ecc_mulmod_stripe_avx2_4(r, &p256_base, p256_table, + k, map, heap); +} + +#endif /* HAVE_INTEL_AVX2 */ +#else /* WOLFSSL_SP_SMALL */ +/* A table entry for pre-computed points. */ +typedef struct sp_table_entry_sum { + sp_digit x[4]; + sp_digit y[4]; + byte infinity; +} sp_table_entry_sum; + +/* Table of pre-computed values for P256 with 3 multiples and width of 8 bits. + */ +static sp_table_entry_sum p256_table[33][58] = { + { + /* 0 << 0 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 0 */ + { { 0x79e730d418a9143cl,0x75ba95fc5fedb601l,0x79fb732b77622510l, + 0x18905f76a53755c6l }, + { 0xddf25357ce95560al,0x8b4ab8e4ba19e45cl,0xd2e88688dd21f325l, + 0x8571ff1825885d85l }, + 0 }, + /* 3 << 0 */ + { { 0xffac3f904eebc127l,0xb027f84a087d81fbl,0x66ad77dd87cbbc98l, + 0x26936a3fb6ff747el }, + { 0xb04c5c1fc983a7ebl,0x583e47ad0861fe1al,0x788208311a2ee98el, + 0xd5f06a29e587cc07l }, + 0 }, + /* 4 << 0 */ + { { 0x74b0b50d46918dccl,0x4650a6edc623c173l,0x0cdaacace8100af2l, + 0x577362f541b0176bl }, + { 0x2d96f24ce4cbaba6l,0x17628471fad6f447l,0x6b6c36dee5ddd22el, + 0x84b14c394c5ab863l }, + 0 }, + /* 5 << 0 */ + { { 0xbe1b8aaec45c61f5l,0x90ec649a94b9537dl,0x941cb5aad076c20cl, + 0xc9079605890523c8l }, + { 0xeb309b4ae7ba4f10l,0x73c568efe5eb882bl,0x3540a9877e7a1f68l, + 0x73a076bb2dd1e916l }, + 0 }, + /* 7 << 0 */ + { { 0x0746354ea0173b4fl,0x2bd20213d23c00f7l,0xf43eaab50c23bb08l, + 0x13ba5119c3123e03l }, + { 0x2847d0303f5b9d4dl,0x6742f2f25da67bddl,0xef933bdc77c94195l, + 0xeaedd9156e240867l }, + 0 }, + /* 9 << 0 */ + { { 0x75c96e8f264e20e8l,0xabe6bfed59a7a841l,0x2cc09c0444c8eb00l, + 0xe05b3080f0c4e16bl }, + { 0x1eb7777aa45f3314l,0x56af7bedce5d45e3l,0x2b6e019a88b12f1al, + 0x086659cdfd835f9bl }, + 0 }, + /* 10 << 0 */ + { { 0x2c18dbd19dc21ec8l,0x98f9868a0fcf8139l,0x737d2cd648250b49l, + 0xcc61c94724b3428fl }, + { 0x0c2b407880dd9e76l,0xc43a8991383fbe08l,0x5f7d2d65779be5d2l, + 0x78719a54eb3b4ab5l }, + 0 }, + /* 11 << 0 */ + { { 0xea7d260a6245e404l,0x9de407956e7fdfe0l,0x1ff3a4158dac1ab5l, + 0x3e7090f1649c9073l }, + { 0x1a7685612b944e88l,0x250f939ee57f61c8l,0x0c0daa891ead643dl, + 0x68930023e125b88el }, + 0 }, + /* 13 << 0 */ + { { 0xccc425634b2ed709l,0x0e356769856fd30dl,0xbcbcd43f559e9811l, + 0x738477ac5395b759l }, + { 0x35752b90c00ee17fl,0x68748390742ed2e3l,0x7cd06422bd1f5bc1l, + 0xfbc08769c9e7b797l }, + 0 }, + /* 15 << 0 */ + { { 0x72bcd8b7bc60055bl,0x03cc23ee56e27e4bl,0xee337424e4819370l, + 0xe2aa0e430ad3da09l }, + { 0x40b8524f6383c45dl,0xd766355442a41b25l,0x64efa6de778a4797l, + 0x2042170a7079adf4l }, + 0 }, + /* 16 << 0 */ + { { 0x808b0b650bc6fb80l,0x5882e0753ffe2e6bl,0xd5ef2f7c2c83f549l, + 0x54d63c809103b723l }, + { 0xf2f11bd652a23f9bl,0x3670c3194b0b6587l,0x55c4623bb1580e9el, + 0x64edf7b201efe220l }, + 0 }, + /* 17 << 0 */ + { { 0x97091dcbd53c5c9dl,0xf17624b6ac0a177bl,0xb0f139752cfe2dffl, + 0xc1a35c0a6c7a574el }, + { 0x227d314693e79987l,0x0575bf30e89cb80el,0x2f4e247f0d1883bbl, + 0xebd512263274c3d0l }, + 0 }, + /* 19 << 0 */ + { { 0xfea912baa5659ae8l,0x68363aba25e1a16el,0xb8842277752c41acl, + 0xfe545c282897c3fcl }, + { 0x2d36e9e7dc4c696bl,0x5806244afba977c5l,0x85665e9be39508c1l, + 0xf720ee256d12597bl }, + 0 }, + /* 21 << 0 */ + { { 0x562e4cecc135b208l,0x74e1b2654783f47dl,0x6d2a506c5a3f3b30l, + 0xecead9f4c16762fcl }, + { 0xf29dd4b2e286e5b9l,0x1b0fadc083bb3c61l,0x7a75023e7fac29a4l, + 0xc086d5f1c9477fa3l }, + 0 }, + /* 23 << 0 */ + { { 0xf4f876532de45068l,0x37c7a7e89e2e1f6el,0xd0825fa2a3584069l, + 0xaf2cea7c1727bf42l }, + { 0x0360a4fb9e4785a9l,0xe5fda49c27299f4al,0x48068e1371ac2f71l, + 0x83d0687b9077666fl }, + 0 }, + /* 25 << 0 */ + { { 0xa4a319acd837879fl,0x6fc1b49eed6b67b0l,0xe395993332f1f3afl, + 0x966742eb65432a2el }, + { 0x4b8dc9feb4966228l,0x96cc631243f43950l,0x12068859c9b731eel, + 0x7b948dc356f79968l }, + 0 }, + /* 27 << 0 */ + { { 0x042c2af497e2feb4l,0xd36a42d7aebf7313l,0x49d2c9eb084ffdd7l, + 0x9f8aa54b2ef7c76al }, + { 0x9200b7ba09895e70l,0x3bd0c66fddb7fb58l,0x2d97d10878eb4cbbl, + 0x2d431068d84bde31l }, + 0 }, + /* 28 << 0 */ + { { 0x4b523eb7172ccd1fl,0x7323cb2830a6a892l,0x97082ec0cfe153ebl, + 0xe97f6b6af2aadb97l }, + { 0x1d3d393ed1a83da1l,0xa6a7f9c7804b2a68l,0x4a688b482d0cb71el, + 0xa9b4cc5f40585278l }, + 0 }, + /* 29 << 0 */ + { { 0x5e5db46acb66e132l,0xf1be963a0d925880l,0x944a70270317b9e2l, + 0xe266f95948603d48l }, + { 0x98db66735c208899l,0x90472447a2fb18a3l,0x8a966939777c619fl, + 0x3798142a2a3be21bl }, + 0 }, + /* 31 << 0 */ + { { 0xe2f73c696755ff89l,0xdd3cf7e7473017e6l,0x8ef5689d3cf7600dl, + 0x948dc4f8b1fc87b4l }, + { 0xd9e9fe814ea53299l,0x2d921ca298eb6028l,0xfaecedfd0c9803fcl, + 0xf38ae8914d7b4745l }, + 0 }, + /* 33 << 0 */ + { { 0x871514560f664534l,0x85ceae7c4b68f103l,0xac09c4ae65578ab9l, + 0x33ec6868f044b10cl }, + { 0x6ac4832b3a8ec1f1l,0x5509d1285847d5efl,0xf909604f763f1574l, + 0xb16c4303c32f63c4l }, + 0 }, + /* 34 << 0 */ + { { 0xb6ab20147ca23cd3l,0xcaa7a5c6a391849dl,0x5b0673a375678d94l, + 0xc982ddd4dd303e64l }, + { 0xfd7b000b5db6f971l,0xbba2cb1f6f876f92l,0xc77332a33c569426l, + 0xa159100c570d74f8l }, + 0 }, + /* 35 << 0 */ + { { 0xfd16847fdec67ef5l,0x742ee464233e76b7l,0x0b8e4134efc2b4c8l, + 0xca640b8642a3e521l }, + { 0x653a01908ceb6aa9l,0x313c300c547852d5l,0x24e4ab126b237af7l, + 0x2ba901628bb47af8l }, + 0 }, + /* 36 << 0 */ + { { 0x3d5e58d6a8219bb7l,0xc691d0bd1b06c57fl,0x0ae4cb10d257576el, + 0x3569656cd54a3dc3l }, + { 0xe5ebaebd94cda03al,0x934e82d3162bfe13l,0x450ac0bae251a0c6l, + 0x480b9e11dd6da526l }, + 0 }, + /* 37 << 0 */ + { { 0x00467bc58cce08b5l,0xb636458c7f178d55l,0xc5748baea677d806l, + 0x2763a387dfa394ebl }, + { 0xa12b448a7d3cebb6l,0xe7adda3e6f20d850l,0xf63ebce51558462cl, + 0x58b36143620088a8l }, + 0 }, + /* 39 << 0 */ + { { 0xa9d89488a059c142l,0x6f5ae714ff0b9346l,0x068f237d16fb3664l, + 0x5853e4c4363186acl }, + { 0xe2d87d2363c52f98l,0x2ec4a76681828876l,0x47b864fae14e7b1cl, + 0x0c0bc0e569192408l }, + 0 }, + /* 40 << 0 */ + { { 0xe4d7681db82e9f3el,0x83200f0bdf25e13cl,0x8909984c66f27280l, + 0x462d7b0075f73227l }, + { 0xd90ba188f2651798l,0x74c6e18c36ab1c34l,0xab256ea35ef54359l, + 0x03466612d1aa702fl }, + 0 }, + /* 41 << 0 */ + { { 0x624d60492ed22e91l,0x6fdfe0b56f072822l,0xeeca111539ce2271l, + 0x98100a4fdb01614fl }, + { 0xb6b0daa2a35c628fl,0xb6f94d2ec87e9a47l,0xc67732591d57d9cel, + 0xf70bfeec03884a7bl }, + 0 }, + /* 43 << 0 */ + { { 0x4ff23ffd248a7d06l,0x80c5bfb4878873fal,0xb7d9ad9005745981l, + 0x179c85db3db01994l }, + { 0xba41b06261a6966cl,0x4d82d052eadce5a8l,0x9e91cd3ba5e6a318l, + 0x47795f4f95b2dda0l }, + 0 }, + /* 44 << 0 */ + { { 0xecfd7c1fd55a897cl,0x009194abb29110fbl,0x5f0e2046e381d3b0l, + 0x5f3425f6a98dd291l }, + { 0xbfa06687730d50dal,0x0423446c4b083b7fl,0x397a247dd69d3417l, + 0xeb629f90387ba42al }, + 0 }, + /* 45 << 0 */ + { { 0x1ee426ccd5cd79bfl,0x0032940b946c6e18l,0x1b1e8ae057477f58l, + 0xe94f7d346d823278l }, + { 0xc747cb96782ba21al,0xc5254469f72b33a5l,0x772ef6dec7f80c81l, + 0xd73acbfe2cd9e6b5l }, + 0 }, + /* 46 << 0 */ + { { 0x4075b5b149ee90d9l,0x785c339aa06e9ebal,0xa1030d5babf825e0l, + 0xcec684c3a42931dcl }, + { 0x42ab62c9c1586e63l,0x45431d665ab43f2bl,0x57c8b2c055f7835dl, + 0x033da338c1b7f865l }, + 0 }, + /* 47 << 0 */ + { { 0x283c7513caa76097l,0x0a624fa936c83906l,0x6b20afec715af2c7l, + 0x4b969974eba78bfdl }, + { 0x220755ccd921d60el,0x9b944e107baeca13l,0x04819d515ded93d4l, + 0x9bbff86e6dddfd27l }, + 0 }, + /* 48 << 0 */ + { { 0x6b34413077adc612l,0xa7496529bbd803a0l,0x1a1baaa76d8805bdl, + 0xc8403902470343adl }, + { 0x39f59f66175adff1l,0x0b26d7fbb7d8c5b7l,0xa875f5ce529d75e3l, + 0x85efc7e941325cc2l }, + 0 }, + /* 49 << 0 */ + { { 0x21950b421ff6acd3l,0xffe7048453dc6909l,0xff4cd0b228766127l, + 0xabdbe6084fb7db2bl }, + { 0x837c92285e1109e8l,0x26147d27f4645b5al,0x4d78f592f7818ed8l, + 0xd394077ef247fa36l }, + 0 }, + /* 51 << 0 */ + { { 0x508cec1c3b3f64c9l,0xe20bc0ba1e5edf3fl,0xda1deb852f4318d4l, + 0xd20ebe0d5c3fa443l }, + { 0x370b4ea773241ea3l,0x61f1511c5e1a5f65l,0x99a5e23d82681c62l, + 0xd731e383a2f54c2dl }, + 0 }, + /* 52 << 0 */ + { { 0x2692f36e83445904l,0x2e0ec469af45f9c0l,0x905a3201c67528b7l, + 0x88f77f34d0e5e542l }, + { 0xf67a8d295864687cl,0x23b92eae22df3562l,0x5c27014b9bbec39el, + 0x7ef2f2269c0f0f8dl }, + 0 }, + /* 53 << 0 */ + { { 0x97359638546c4d8dl,0x5f9c3fc492f24679l,0x912e8beda8c8acd9l, + 0xec3a318d306634b0l }, + { 0x80167f41c31cb264l,0x3db82f6f522113f2l,0xb155bcd2dcafe197l, + 0xfba1da5943465283l }, + 0 }, + /* 55 << 0 */ + { { 0x258bbbf9e7305683l,0x31eea5bf07ef5be6l,0x0deb0e4a46c814c1l, + 0x5cee8449a7b730ddl }, + { 0xeab495c5a0182bdel,0xee759f879e27a6b4l,0xc2cf6a6880e518cal, + 0x25e8013ff14cf3f4l }, + 0 }, + /* 57 << 0 */ + { { 0x3ec832e77acaca28l,0x1bfeea57c7385b29l,0x068212e3fd1eaf38l, + 0xc13298306acf8cccl }, + { 0xb909f2db2aac9e59l,0x5748060db661782al,0xc5ab2632c79b7a01l, + 0xda44c6c600017626l }, + 0 }, + /* 59 << 0 */ + { { 0x69d44ed65c46aa8el,0x2100d5d3a8d063d1l,0xcb9727eaa2d17c36l, + 0x4c2bab1b8add53b7l }, + { 0xa084e90c15426704l,0x778afcd3a837ebeal,0x6651f7017ce477f8l, + 0xa062499846fb7a8bl }, + 0 }, + /* 60 << 0 */ + { { 0xdc1e6828ed8a6e19l,0x33fc23364189d9c7l,0x026f8fe2671c39bcl, + 0xd40c4ccdbc6f9915l }, + { 0xafa135bbf80e75cal,0x12c651a022adff2cl,0xc40a04bd4f51ad96l, + 0x04820109bbe4e832l }, + 0 }, + /* 61 << 0 */ + { { 0x3667eb1a7f4c04ccl,0x59556621a9404f84l,0x71cdf6537eceb50al, + 0x994a44a69b8335fal }, + { 0xd7faf819dbeb9b69l,0x473c5680eed4350dl,0xb6658466da44bba2l, + 0x0d1bc780872bdbf3l }, + 0 }, + /* 63 << 0 */ + { { 0xb8d3d9319ff91fe5l,0x039c4800f0518eedl,0x95c376329182cb26l, + 0x0763a43482fc568dl }, + { 0x707c04d5383e76bal,0xac98b930824e8197l,0x92bf7c8f91230de0l, + 0x90876a0140959b70l }, + 0 }, + /* 64 << 0 */ + { { 0xdb6d96f305968b80l,0x380a0913089f73b9l,0x7da70b83c2c61e01l, + 0x95fb8394569b38c7l }, + { 0x9a3c651280edfe2fl,0x8f726bb98faeaf82l,0x8010a4a078424bf8l, + 0x296720440e844970l }, + 0 }, + /* 65 << 0 */ + { { 0xdc2306ebfcdbb2b2l,0x79527db7ba66f4b9l,0xbf639ed67765765el, + 0x01628c4706b6090al }, + { 0x66eb62f1b957b4a1l,0x33cb7691ba659f46l,0x2c90d98cf3e055d6l, + 0x7d096ac42f174750l }, + 0 }, + /* 71 << 0 */ + { { 0xf19f382e92aa7864l,0x49c7cb94fc05804bl,0xf94aa89b40750d01l, + 0xdd421b5d4a210364l }, + { 0x56cd001e39df3672l,0x030a119fdd4af1ecl,0x11f947e696cd0572l, + 0x574cc7b293786791l }, + 0 }, + /* 77 << 0 */ + { { 0x0a2193bfc266f85cl,0x719a87be5a0ec9cel,0x9c30c6422b2f9c49l, + 0xdb15e4963d5baeb1l }, + { 0x83c3139be0d37321l,0x4788522b2e9fdbb2l,0x2b4f0c7877eb94eal, + 0x854dc9d595105f9el }, + 0 }, + /* 83 << 0 */ + { { 0x2c9ee62dc3363a22l,0x125d4714ec67199al,0xf87abebf2ab80485l, + 0xcf3086e87a243ca4l }, + { 0x5c52b051c64e09ddl,0x5e9b16125625aad7l,0x0536a39db19c6126l, + 0x97f0013247b64be5l }, + 0 }, + /* 89 << 0 */ + { { 0xc1ee6264a7eabe67l,0x62d51e29fd54487dl,0x3ea123446310eb5al, + 0xbd88aca74765b805l }, + { 0xb7b284be14fb691al,0x640388f83b9fffefl,0x7ab49dd209f98f9al, + 0x7150f87e7211e445l }, + 0 }, + /* 95 << 0 */ + { { 0x263e039bb308cc40l,0x6684ad762b346fd2l,0x9a127f2bcaa12d0dl, + 0x76a8f9fea974291fl }, + { 0xc802049b68aa19e4l,0x65499c990c5dbba0l,0xee1b1cb5344455a1l, + 0x3f293fda2cd6f439l }, + 0 }, + /* 101 << 0 */ + { { 0xb7a96e0a4ea6fdf7l,0xbbe914d3b99cd026l,0x6a610374c569a602l, + 0xe9b1c23914da499el }, + { 0xb5f6f0feadc19a99l,0x731251826f21687cl,0x5a8a14644be77793l, + 0x94ce9e0adba8bfc7l }, + 0 }, + /* 107 << 0 */ + { { 0x2ca0ba9c3796f4c7l,0x3571e4d1592ce334l,0x28f9cdebe9f6e877l, + 0xee206023efce1a70l }, + { 0xb2159e08b76369dcl,0x2754e4260a7f687cl,0xe008039e02de2ff1l, + 0xccd7e9418ea700c1l }, + 0 }, + /* 113 << 0 */ + { { 0xa125e6c1b7ebcb88l,0x3289e86e10ec0d40l,0xcc3a5ecb98353869l, + 0x734e0d078a2b0d3al }, + { 0xe0d92e9a51933360l,0xfa6bcdb1786076b9l,0xd13cca90747f19ecl, + 0x61d8209d49f3a53dl }, + 0 }, + /* 116 << 0 */ + { { 0x87f9793bc9826344l,0x4b3de89bb2f5f79cl,0xc9f08a5659cb1b6el, + 0xd8f1fc5f6a92b9aal }, + { 0x86357f9eb412595el,0x53c30bbe65b80f16l,0xf06c2c8c70549a57l, + 0xa9c8a4b42b9157dal }, + 0 }, + /* 119 << 0 */ + { { 0x87af199e6cc47305l,0x062afb7c1e314ddel,0x2be22ba0f3a49fb4l, + 0x6ed0b988157b7f56l }, + { 0x8162cf502d653fd9l,0x17d29c64877b7497l,0xd7e814380f67b514l, + 0xfedf1014fe6ee703l }, + 0 }, + /* 125 << 0 */ + { { 0xaab54cfc93740130l,0xf72dab6d225733fal,0x04b76d2d1ed32559l, + 0xa9fe2396bb85b9cbl }, + { 0x128b0d24bf2219f0l,0x2292393b579f3ce2l,0x51dc5fac145ff0d5l, + 0xb16d6af8c3febbc1l }, + 0 }, + }, + { + /* 0 << 8 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 8 */ + { { 0x486d8ffa696946fcl,0x50fbc6d8b9cba56dl,0x7e3d423e90f35a15l, + 0x7c3da195c0dd962cl }, + { 0xe673fdb03cfd5d8bl,0x0704b7c2889dfca5l,0xf6ce581ff52305aal, + 0x399d49eb914d5e53l }, + 0 }, + /* 3 << 8 */ + { { 0x35d6a53eed4c3717l,0x9f8240cf3d0ed2a3l,0x8c0d4d05e5543aa5l, + 0x45d5bbfbdd33b4b4l }, + { 0xfa04cc73137fd28el,0x862ac6efc73b3ffdl,0x403ff9f531f51ef2l, + 0x34d5e0fcbc73f5a2l }, + 0 }, + /* 4 << 8 */ + { { 0x4f7081e144cc3addl,0xd5ffa1d687be82cfl,0x89890b6c0edd6472l, + 0xada26e1a3ed17863l }, + { 0x276f271563483caal,0xe6924cd92f6077fdl,0x05a7fe980a466e3cl, + 0xf1c794b0b1902d1fl }, + 0 }, + /* 5 << 8 */ + { { 0x33b2385c08369a90l,0x2990c59b190eb4f8l,0x819a6145c68eac80l, + 0x7a786d622ec4a014l }, + { 0x33faadbe20ac3a8dl,0x31a217815aba2d30l,0x209d2742dba4f565l, + 0xdb2ce9e355aa0fbbl }, + 0 }, + /* 7 << 8 */ + { { 0x0c4a58d474a86108l,0xf8048a8fee4c5d90l,0xe3c7c924e86d4c80l, + 0x28c889de056a1e60l }, + { 0x57e2662eb214a040l,0xe8c48e9837e10347l,0x8774286280ac748al, + 0xf1c24022186b06f2l }, + 0 }, + /* 9 << 8 */ + { { 0xe8cbf1e5d5923359l,0xdb0cea9d539b9fb0l,0x0c5b34cf49859b98l, + 0x5e583c56a4403cc6l }, + { 0x11fc1a2dd48185b7l,0xc93fbc7e6e521787l,0x47e7a05805105b8bl, + 0x7b4d4d58db8260c8l }, + 0 }, + /* 10 << 8 */ + { { 0xb31bd6136339c083l,0x39ff8155dfb64701l,0x7c3388d2e29604abl, + 0x1e19084ba6b10442l }, + { 0x17cf54c0eccd47efl,0x896933854a5dfb30l,0x69d023fb47daf9f6l, + 0x9222840b7d91d959l }, + 0 }, + /* 11 << 8 */ + { { 0xc510610939842194l,0xb7e2353e49d05295l,0xfc8c1d5cefb42ee0l, + 0xe04884eb08ce811cl }, + { 0xf1f75d817419f40el,0x5b0ac162a995c241l,0x120921bbc4c55646l, + 0x713520c28d33cf97l }, + 0 }, + /* 13 << 8 */ + { { 0x41d04ee21726931al,0x0bbbb2c83660ecfdl,0xa6ef6de524818e18l, + 0xe421cc51e7d57887l }, + { 0xf127d208bea87be6l,0x16a475d3b1cdd682l,0x9db1b684439b63f7l, + 0x5359b3dbf0f113b6l }, + 0 }, + /* 15 << 8 */ + { { 0x3a5c752edcc18770l,0x4baf1f2f8825c3a5l,0xebd63f7421b153edl, + 0xa2383e47b2f64723l }, + { 0xe7bf620a2646d19al,0x56cb44ec03c83ffdl,0xaf7267c94f6be9f1l, + 0x8b2dfd7bc06bb5e9l }, + 0 }, + /* 16 << 8 */ + { { 0x6772b0e5ab4b35a2l,0x1d8b6001f5eeaacfl,0x728f7ce4795b9580l, + 0x4a20ed2a41fb81dal }, + { 0x9f685cd44fec01e6l,0x3ed7ddcca7ff50adl,0x460fd2640c2d97fdl, + 0x3a241426eb82f4f9l }, + 0 }, + /* 17 << 8 */ + { { 0xc503cd33bccd9617l,0x365dede4ba7730a3l,0x798c63555ddb0786l, + 0xa6c3200efc9cd3bcl }, + { 0x060ffb2ce5e35efdl,0x99a4e25b5555a1c1l,0x11d95375f70b3751l, + 0x0a57354a160e1bf6l }, + 0 }, + /* 19 << 8 */ + { { 0xc033bdc719803511l,0xa9f97b3b8888c3bel,0x3d68aebc85c6d05el, + 0xc3b88a9d193919ebl }, + { 0x2d300748c48b0ee3l,0x7506bc7c07a746c1l,0xfc48437c6e6d57f3l, + 0x5bd71587cfeaa91al }, + 0 }, + /* 21 << 8 */ + { { 0xe40736d3df61bc76l,0x13a619c03f778cdbl,0x6dd921a4c56ea28fl, + 0x76a524332fa647b4l }, + { 0x23591891ac5bdc5dl,0xff4a1a72bac7dc01l,0x9905e26162df8453l, + 0x3ac045dfe63b265fl }, + 0 }, + /* 23 << 8 */ + { { 0x8435bd6994b03ed1l,0xd9ad1de3634cc546l,0x2cf423fc00e420cal, + 0xeed26d80a03096ddl }, + { 0xd7f60be7a4db09d2l,0xf47f569d960622f7l,0xe5925fd77296c729l, + 0xeff2db2626ca2715l }, + 0 }, + /* 25 << 8 */ + { { 0x5dfee80f83774bddl,0x6313160285734485l,0xa1b524ae914a69a9l, + 0xebc2ffafd4e300d7l }, + { 0x52c93db77cfa46a5l,0x71e6161f21653b50l,0x3574fc57a4bc580al, + 0xc09015dde1bc1253l }, + 0 }, + /* 27 << 8 */ + { { 0x9c38ddcceb5b76c1l,0x746f528526fc0ab4l,0x52a63a50d62c269fl, + 0x60049c5599458621l }, + { 0xe7f48f823c2f7c9el,0x6bd99043917d5cf3l,0xeb1317a88701f469l, + 0xbd3fe2ed9a449fe0l }, + 0 }, + /* 28 << 8 */ + { { 0xe652533b3cef0d7dl,0xd94f7b182bbb4381l,0x838752be0e80f500l, + 0x8e6e24889e9c9bfbl }, + { 0xc975169716caca6al,0x866c49d838531ad9l,0xc917e2397151ade1l, + 0x2d016ec16037c407l }, + 0 }, + /* 29 << 8 */ + { { 0x202f6a9c31c71f7bl,0x01f95aa3296ffe5cl,0x5fc0601453cec3a3l, + 0xeb9912375f498a45l }, + { 0xae9a935e5d91ba87l,0xc6ac62810b564a19l,0x8a8fe81c3bd44e69l, + 0x7c8b467f9dd11d45l }, + 0 }, + /* 31 << 8 */ + { { 0x21d3634d39eedbbal,0x35cd2e680455a46dl,0xc8cafe65f9d7eb0cl, + 0xbda3ce9e00cefb3el }, + { 0xddc17a602c9cf7a4l,0x01572ee47bcb8773l,0xa92b2b018c7548dfl, + 0x732fd309a84600e3l }, + 0 }, + /* 33 << 8 */ + { { 0x65cf89a2e0600afal,0xcf51482f753c5ceal,0x4f2b2d25a5c2bfc5l, + 0x9381f57187098256l }, + { 0x89210f676e976e4bl,0xe2cf12f489f47a7bl,0xc21a1658e8484050l, + 0xa224dbf82f0fff01l }, + 0 }, + /* 34 << 8 */ + { { 0xc28961087282513dl,0x9a78c4296a3f8fb8l,0xddfa56f9a31e24b7l, + 0xb1e14f84fb72611fl }, + { 0x1d0f70ab45078d65l,0xb247aef3819924d8l,0x8d519f9dbb9877c1l, + 0x495c2ece8368c7c9l }, + 0 }, + /* 35 << 8 */ + { { 0xca9129a0bdb69d12l,0xbe3e319978f39adfl,0xa88506df5fe49438l, + 0x17ddb7a7aafe894cl }, + { 0x28d1456f6d1d742fl,0xeec09651917d1268l,0xdecb1c700fd5b4c0l, + 0x32d14f6acf2861dbl }, + 0 }, + /* 36 << 8 */ + { { 0x903f6e3960e913afl,0xb2b58bee98bf140dl,0x9deff025354890b8l, + 0x155810068d2e924el }, + { 0xb5755db493c95e5bl,0x3fac42f0dae20eb8l,0x9377c8c109b6d8e0l, + 0xa43e2b46ab47ceffl }, + 0 }, + /* 37 << 8 */ + { { 0x6c3f5a51cb61e7e7l,0x264aebc80d9c73b2l,0xc404b2114a0d9288l, + 0x5178d3cf8b3a79e9l }, + { 0x4080be5372a420d7l,0xa39396adef026429l,0x22fbb92e8dde4728l, + 0x19e42d8874d949fcl }, + 0 }, + /* 39 << 8 */ + { { 0xde352d78387f5557l,0x6770149969367413l,0x255bb8c00b0cc102l, + 0x63cad1be1f4d262el }, + { 0xf34f9a8a3f8f4fb6l,0x32bc13aae03a969fl,0xb29d4336218371cdl, + 0x799d76ab285bd210l }, + 0 }, + /* 40 << 8 */ + { { 0x5f57b2fbfacfa459l,0x874b1498c1b5aa6bl,0xb9e89acac4db2092l, + 0x1362bf8ddf4381dal }, + { 0x25d76830b76328a0l,0x38188b7098572ae4l,0xb43e941429132f7dl, + 0x7895a29f22dd42c9l }, + 0 }, + /* 41 << 8 */ + { { 0x85bded619e808c05l,0x6e0fc2bcc7ef83bbl,0xed70e0b499bedf77l, + 0x300e777dc1aaffc0l }, + { 0xe2da2359c43e6d2cl,0xacf6d60a275226e0l,0x18ca38f7f82558bdl, + 0xd7b017d475ae2591l }, + 0 }, + /* 43 << 8 */ + { { 0xed299e2d7cd92ee2l,0x2c08eb37ad847153l,0x7b372aa712acfd81l, + 0x574d27f5fabda29cl }, + { 0xbd8247f0f2ee6ebcl,0x8bf76710d06be261l,0x26e95b4bcb186d4cl, + 0x4fa3ac1d1ebb4a46l }, + 0 }, + /* 44 << 8 */ + { { 0xcbde78dd5e22cbb2l,0xf449c85b76bb4391l,0x4289f357b6a4273bl, + 0x9fce23fd48e84a19l }, + { 0xcfc32730939eb3b4l,0x8b3d982c16c32280l,0x5ac234bad5f1346cl, + 0x781954b470769fc9l }, + 0 }, + /* 45 << 8 */ + { { 0xff0d4d30062c7dbdl,0x2c483081e6f9fcf0l,0x22f96316d67e070fl, + 0xdd9be459c0e68c44l }, + { 0xb9c1edffce2edd4dl,0x1a54782021fc538cl,0x93849be49979aee1l, + 0x3f313629a590949el }, + 0 }, + /* 46 << 8 */ + { { 0x160b836b266be332l,0x49de38215f340575l,0x782e8f6701edce66l, + 0x83ae008b5df1a93el }, + { 0x85d33a263ed9ffebl,0xae2f9f961e79db97l,0xf64f209b95ae9e34l, + 0x2b6b03455e957d49l }, + 0 }, + /* 47 << 8 */ + { { 0x7a24a21a331d6bdal,0xfdba302f6328f742l,0x37a36dd47744dca4l, + 0xda2832ce6fef500fl }, + { 0x23da304a7b49d73al,0xeede2cebc6ad834fl,0xf21a81248dec3c78l, + 0x4bc9469b19b721e3l }, + 0 }, + /* 48 << 8 */ + { { 0x6faf68feaae6ee70l,0x78f4cc155602b0c9l,0x7e3321a86e94052al, + 0x2fb3a0d6734d5d80l }, + { 0xf3b98f3bb25a43bal,0x30bf803119ee2951l,0x7ffee43321b0612al, + 0x12f775e42eb821d0l }, + 0 }, + /* 49 << 8 */ + { { 0x31cc342913e5c1d6l,0x05deaa3cee54e334l,0x21ea2b61cd5087d8l, + 0x73a1841e70d1b8bcl }, + { 0xd44e2b41b078bf14l,0xc295732fcea2a30el,0x30cdab42954939f7l, + 0xc1b4e43a2dba0b7cl }, + 0 }, + /* 51 << 8 */ + { { 0x5f33f618b6a20132l,0xc8d73e3cfbbf3022l,0xf3b9844d47ed4320l, + 0xab5868aa927f00cal }, + { 0x06cb1113077f6e1cl,0x1417b43a5c94faaal,0x7666cb90cf4cd1e9l, + 0x99e009f210900566l }, + 0 }, + /* 52 << 8 */ + { { 0x4fdff805f57209b5l,0x9bd65ac3f952ac8dl,0x02a3abd3c7969a6fl, + 0x1359927ef523775fl }, + { 0xe09b463f88d2e861l,0x661d2199623287c3l,0x821e64495a70eb7al, + 0x0afbbb1dd67dc684l }, + 0 }, + /* 53 << 8 */ + { { 0x2c5a2b2d55750eb2l,0x54d756c29dc28d9fl,0x798c8d113af97f71l, + 0x54e21ee21f6d1853l }, + { 0x34e0c8bceffc3f8al,0xed3cc4dda96f193fl,0x86436a84fad97110l, + 0x8530ca522c97205el }, + 0 }, + /* 55 << 8 */ + { { 0x9b6c8452f7236867l,0x21cf260c777b44fdl,0x659fc99dceb00c52l, + 0xda97098e2439e8dbl }, + { 0x647efe510ed6e14fl,0x37c8ca122a6600f3l,0x53e89b0badf6f4a7l, + 0xd9fc8c716645618al }, + 0 }, + /* 57 << 8 */ + { { 0x9cecfb8eee6ebd31l,0x4603994b1ff25529l,0x707bc80af4b141c4l, + 0x3a83d56c07524d3al }, + { 0x7035c746613a3020l,0x7aa766b286626a1cl,0x3af656095ac76c78l, + 0x4039c655171e47d6l }, + 0 }, + /* 59 << 8 */ + { { 0x79cb147f0ce33b63l,0xa1328a622d160c61l,0xf99538f3cf7eb87el, + 0x0334d4958e2241d5l }, + { 0x3ad97e02f3e49e48l,0xdcfcc754037c3679l,0x76078ba61a8ff67cl, + 0x8054aa55c2a64964l }, + 0 }, + /* 60 << 8 */ + { { 0x5852104b87453b28l,0x073e8128b387344dl,0x300e78e4817cfc08l, + 0x3a82ed4799362088l }, + { 0xe222304c88de46a4l,0x666c94fd57fadf4al,0x40b2d08ea0c8e108l, + 0x4b2955b909e050fal }, + 0 }, + /* 61 << 8 */ + { { 0x656078565f814881l,0x0fc3d1ce58466117l,0x0ae377d3c6c1e68al, + 0xe3dd8d5cba566c48l }, + { 0x9404849ec4b63be6l,0x1e22b03ba5be9c92l,0x08145122a8b03e63l, + 0x71248243771fe153l }, + 0 }, + /* 63 << 8 */ + { { 0xa80a0e83b41ac541l,0xa77570ea533e5f9bl,0x416a14c0216dc452l, + 0x2a8d728a19f7ee59l }, + { 0x58494c8cd6552eaal,0x4d635acd60145722l,0xa8e9b127327b1cbcl, + 0xb429a62e9f8235f0l }, + 0 }, + /* 64 << 8 */ + { { 0xf8d112e76e6485b3l,0x4d3e24db771c52f8l,0x48e3ee41684a2f6dl, + 0x7161957d21d95551l }, + { 0x19631283cdb12a6cl,0xbf3fa8822e50e164l,0xf6254b633166cc73l, + 0x3aefa7aeaee8cc38l }, + 0 }, + /* 65 << 8 */ + { { 0xd52d2cb746ef1c7el,0xebd4f7c4d8fb6e07l,0x16f77a48cf6dd2b4l, + 0x6e8f0431e77e4d51l }, + { 0x59d94cc4e9177bf2l,0xb58a578f7a7181a1l,0xeefbc4cde8f6d330l, + 0xa66c85560fe05490l }, + 0 }, + /* 71 << 8 */ + { { 0x0e6db7a35d9649dal,0x4d2f25193be3d362l,0xcd891fd5a6b137b5l, + 0xa4b7e4ddacd377a9l }, + { 0x20ccd6f24355f258l,0x842c08673aafb413l,0xdd55db99d6873b88l, + 0x04d15f4fea5a2a55l }, + 0 }, + /* 77 << 8 */ + { { 0x679cd93dfae289c2l,0x84cadd61ff92ba1bl,0x548b5a6f2cd734aal, + 0x1827507db8267082l }, + { 0xa903a6010c6d5b4cl,0xde0d96befdfb952bl,0x2fc9419c6a2e24f9l, + 0x27333e3936bb3203l }, + 0 }, + /* 83 << 8 */ + { { 0x3eb7f062dde4aa6al,0x40effae07f354cc0l,0xe9a14bc2a066c05el, + 0x7817b11356afc543l }, + { 0x5f0ed1f28bdda262l,0x001e23d2e007ec13l,0x435878a59c57de6al, + 0x84d0e20895ac263cl }, + 0 }, + /* 89 << 8 */ + { { 0xedf24aec97a66678l,0xd1f93cf8ccf55671l,0x4ed2ce8a9379a49dl, + 0x64991862c39b0ac9l }, + { 0xc15b24e31ff67e04l,0x4ee8fc76c3c084fel,0x262012b4f64bcd46l, + 0x3b5086732425c622l }, + 0 }, + /* 95 << 8 */ + { { 0xaa3e451fe65002f7l,0xf5ff2617eb46d253l,0x918d146e572afca2l, + 0x0a9333b7e56a8553l }, + { 0x9b7e232d94127dc0l,0xcd0687d6831014e6l,0x725ce5baf08e1c71l, + 0x56e26f48cde0e4edl }, + 0 }, + /* 101 << 8 */ + { { 0xae78dde8db833460l,0xaf1736fe762cb78al,0x5cd85742eae5ac60l, + 0x7b6c52fe955e981al }, + { 0x9f823e8555599f97l,0xb9ce70d21a4b46b3l,0xb6076175d7d09829l, + 0x21e77d22abf390a4l }, + 0 }, + /* 107 << 8 */ + { { 0xf704f09da142ad7el,0xb60ec2e1bab9f5d2l,0x4180314681e54d0dl, + 0x0de50506309335e6l }, + { 0x4135374e05aec64fl,0xb5d31041b556808al,0x0092eb86049033a8l, + 0x5b7a2fa0bde0d737l }, + 0 }, + /* 113 << 8 */ + { { 0xc0dfa6bbefb40cfal,0x86a6fe279c5037f3l,0xf153cd37f71155f4l, + 0xf16d6029767664f9l }, + { 0x7441aa54c635aa57l,0x547f82e9e8186b2el,0x330b464bfbf7c7fel, + 0xb5556770a1f6fddel }, + 0 }, + /* 116 << 8 */ + { { 0xa0a9c5d1e8f9edf1l,0x9814c26b6946cea3l,0xcbb47a37d8e6a08dl, + 0x517a3d9b2cba11b1l }, + { 0x94edc73dab43c540l,0x4fd0b82a753e552cl,0x419aab8bd14ae853l, + 0x94955f9ca68abad8l }, + 0 }, + /* 119 << 8 */ + { { 0x3a162e06ed169150l,0x8c9683a6ba1194a8l,0x53fead66ccc28d04l, + 0xdbb2a85bef09809al }, + { 0x58e677439d3ab018l,0xff9a2046b6e56bd0l,0xf4b8215eb28061e9l, + 0xcf16d9f7b10e358fl }, + 0 }, + /* 125 << 8 */ + { { 0x265ceae9a55abe39l,0x9e3783f796a98f84l,0xb799628af0757d99l, + 0xebb5f12665472fb3l }, + { 0xd83619f52ba517d8l,0x5672105f50382bdfl,0x32c5681c4a12ee9fl, + 0x31e6f60d834a9fedl }, + 0 }, + }, + { + /* 0 << 16 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 16 */ + { { 0x0f0165fce3779ee3l,0xe00e7f9dbd495d9el,0x1fa4efa220284e7al, + 0x4564bade47ac6219l }, + { 0x90e6312ac4708e8el,0x4f5725fba71e9adfl,0xe95f55ae3d684b9fl, + 0x47f7ccb11e94b415l }, + 0 }, + /* 3 << 16 */ + { { 0xbd9b8b1dbe7a2af3l,0xec51caa94fb74a72l,0xb9937a4b63879697l, + 0x7c9a9d20ec2687d5l }, + { 0x1773e44f6ef5f014l,0x8abcf412e90c6900l,0x387bd0228142161el, + 0x50393755fcb6ff2al }, + 0 }, + /* 4 << 16 */ + { { 0xfabf770977f7195al,0x8ec86167adeb838fl,0xea1285a8bb4f012dl, + 0xd68835039a3eab3fl }, + { 0xee5d24f8309004c2l,0xa96e4b7613ffe95el,0x0cdffe12bd223ea4l, + 0x8f5c2ee5b6739a53l }, + 0 }, + /* 5 << 16 */ + { { 0x3d61333959145a65l,0xcd9bc368fa406337l,0x82d11be32d8a52a0l, + 0xf6877b2797a1c590l }, + { 0x837a819bf5cbdb25l,0x2a4fd1d8de090249l,0x622a7de774990e5fl, + 0x840fa5a07945511bl }, + 0 }, + /* 7 << 16 */ + { { 0x26e08c07e3533d77l,0xd7222e6a2e341c99l,0x9d60ec3d8d2dc4edl, + 0xbdfe0d8f7c476cf8l }, + { 0x1fe59ab61d056605l,0xa9ea9df686a8551fl,0x8489941e47fb8d8cl, + 0xfeb874eb4a7f1b10l }, + 0 }, + /* 9 << 16 */ + { { 0x9164088d977eab40l,0x51f4c5b62760b390l,0xd238238f340dd553l, + 0x358566c3db1d31c9l }, + { 0x3a5ad69e5068f5ffl,0xf31435fcdaff6b06l,0xae549a5bd6debff0l, + 0x59e5f0b775e01331l }, + 0 }, + /* 10 << 16 */ + { { 0x2cc5226138634818l,0x501814f4b44c2e0bl,0xf7e181aa54dfdba3l, + 0xcfd58ff0e759718cl }, + { 0xf90cdb14d3b507a8l,0x57bd478ec50bdad8l,0x29c197e250e5f9aal, + 0x4db6eef8e40bc855l }, + 0 }, + /* 11 << 16 */ + { { 0xd5d5cdd35958cd79l,0x3580a1b51d373114l,0xa36e4c91fa935726l, + 0xa38c534def20d760l }, + { 0x7088e40a2ff5845bl,0xe5bb40bdbd78177fl,0x4f06a7a8857f9920l, + 0xe3cc3e50e968f05dl }, + 0 }, + /* 13 << 16 */ + { { 0x10595b5696a71cbal,0x944938b2fdcadeb7l,0xa282da4cfccd8471l, + 0x98ec05f30d37bfe1l }, + { 0xe171ce1b0698304al,0x2d69144421bdf79bl,0xd0cd3b741b21dec1l, + 0x712ecd8b16a15f71l }, + 0 }, + /* 15 << 16 */ + { { 0xe89f48c85963a46el,0x658ab875a99e61c7l,0x6e296f874b8517b4l, + 0x36c4fcdcfc1bc656l }, + { 0xde5227a1a3906defl,0x9fe95f5762418945l,0x20c91e81fdd96cdel, + 0x5adbe47eda4480del }, + 0 }, + /* 16 << 16 */ + { { 0xa7a8746a584c5e20l,0x267e4ea1b9dc7035l,0x593a15cfb9548c9bl, + 0x5e6e21354bd012f3l }, + { 0xdf31cc6a8c8f936el,0x8af84d04b5c241dcl,0x63990a6f345efb86l, + 0x6fef4e61b9b962cbl }, + 0 }, + /* 17 << 16 */ + { { 0xaa35809ddfe6e2a0l,0xebb4d7d4356a2222l,0x7d500a6a319f33b7l, + 0x4895a47d4ac99011l }, + { 0x300ab40bdf3812b2l,0xd0764ec88aec8b9fl,0x86b61d95e591b2a7l, + 0xc1b2a0b72ed74603l }, + 0 }, + /* 19 << 16 */ + { { 0x6001bf5d3849c680l,0xd7a1a4e4c1d3faccl,0xa0f2776418c5e351l, + 0x0849c0736c29c623l }, + { 0x3317e143ac751c0cl,0x9bcb1f3eda06200bl,0x40a63a75541419b5l, + 0x8fad9c983f62c513l }, + 0 }, + /* 21 << 16 */ + { { 0xacff0828d03b2242l,0x5a9375c43abb7389l,0x41b1a318d0192baal, + 0x105bd3100458e97bl }, + { 0x71582dc7ed496315l,0x8ab2884a4d4bda18l,0xb8b638b494bc5bb8l, + 0xb42ed1309500bb04l }, + 0 }, + /* 23 << 16 */ + { { 0x73e04f02ad1ed952l,0x680051cadfa5bdb7l,0xbe0bef3c0c7437b9l, + 0x45d6f3a40e65e627l }, + { 0x5295e060c9436a75l,0xbe84ba78d289ba9el,0x350887fd69c09364l, + 0xf27bfd17671c64a7l }, + 0 }, + /* 25 << 16 */ + { { 0xc8afbdc3adf6ffc5l,0x4a4fb35876385891l,0xc7fa86424d41453fl, + 0x19490b7672eedd06l }, + { 0xc883e45337d22d6al,0x8e6e38e4a9009f96l,0x44e2811eb1c560c6l, + 0x8a0021bf4439cfcfl }, + 0 }, + /* 27 << 16 */ + { { 0xba768f8b7615a327l,0x6c8b320d7b15bbe7l,0x5d8d5bcbaaa9ca64l, + 0x19a2b99f3d13cdfdl }, + { 0x858288a26f172e10l,0x2412a4da37a00f94l,0xfc67fd2edaa7f6c6l, + 0x4aea0eadafa2a5c5l }, + 0 }, + /* 28 << 16 */ + { { 0x5c80ccef6cd77b30l,0x49978299ec99b6d0l,0x6bf4485eb939d335l, + 0xc53e61ab86d7c147l }, + { 0xdd948052fb601dddl,0x34c5eb393511dd48l,0x91f5c67600e6f61cl, + 0x33f1b525b1e71f34l }, + 0 }, + /* 29 << 16 */ + { { 0xb4cb4a151d2dad36l,0x709a61631e60b60dl,0x2f18f3bd932ece4fl, + 0x70f495a8e92368bel }, + { 0x6e88be2bb7aeaa6fl,0x4efebd9ae1bf1d6el,0x49925e6e44e94993l, + 0x33b7aba0ef0517dcl }, + 0 }, + /* 31 << 16 */ + { { 0x69ce1f207afe6c37l,0xe1148ba984f68db5l,0x32668bdc2c594a8al, + 0x2cb60d3063ac4fb3l }, + { 0x5e6efe1dd9e036f8l,0x917cb2a27db4739fl,0x70ea601ded4e0b5el, + 0x5928f068ae7ac8a6l }, + 0 }, + /* 33 << 16 */ + { { 0x9e4ad0073f2d96abl,0x51a9697f2d058c03l,0xcd5c0a7522d1e795l, + 0xaa1a121c2ac4f019l }, + { 0xa837c14c3e3631f4l,0x6a997381236a5576l,0xb305e7db2753782bl, + 0xae561b0237243afbl }, + 0 }, + /* 34 << 16 */ + { { 0x20176baca787897bl,0x057b8b979a9f67d9l,0xe7d5c4f761e14e09l, + 0x8e4856901e6cd6d0l }, + { 0x3eeffbba9b925d52l,0xe651a5383046927bl,0x02326d1fe92d4352l, + 0xad2d6493d697369fl }, + 0 }, + /* 35 << 16 */ + { { 0xe9de299c548c4ca5l,0x66f64ef54be3bde3l,0xcf6d39ebf2d5ebc9l, + 0x665ca727898953e1l }, + { 0x521ec435e33ac1b4l,0x8418fa7534ab2b82l,0x94d6c0c4771a3a87l, + 0x21feb6054859ee22l }, + 0 }, + /* 36 << 16 */ + { { 0xde7153f8eed9dd1dl,0xba09ad1152ebcb2el,0xaa41b015e1843fb6l, + 0xf933a2abdd4ce6f0l }, + { 0x777f834313f6b83fl,0x28df7da4db113a75l,0x6d7d1b3c72a5d143l, + 0x6f789698966c6ddfl }, + 0 }, + /* 37 << 16 */ + { { 0x57d11ed7a95e704el,0x7d5ac6dc380ad582l,0xb175421d5ab6e377l, + 0x4e383b0ba760dd4dl }, + { 0xde07b81a352b6cb3l,0x342abe825c2e1704l,0x90988de20dd48537l, + 0x4a7fec0544821591l }, + 0 }, + /* 39 << 16 */ + { { 0xb0e4d17c90a94eb7l,0x27555067aceb0176l,0x587576e15c38c4e2l, + 0xe647d9dd445f2880l }, + { 0x00beb2f5ca502f83l,0x4e89e638c44767c7l,0xbef361da154a5757l, + 0x2dc632a2dc0675f2l }, + 0 }, + /* 40 << 16 */ + { { 0xed439a33a72ba054l,0xa3170a15ead265bal,0xcf7eb903fe99a58el, + 0xcf6db0c633d80c26l }, + { 0xd031255ef613e71al,0x12ccbe5718ca255cl,0xdd21d0537808c40dl, + 0xf5488ebc3af2be6bl }, + 0 }, + /* 41 << 16 */ + { { 0x589a125ac10f8157l,0x3c8a15bde1353e49l,0x7d9bbd0c22ce2dd0l, + 0xdfcd019211ac7bb1l }, + { 0x0e1d67151193c5b1l,0xd4de115ab0e8c285l,0x0b3e94c2272c29fel, + 0xea640843c8213581l }, + 0 }, + /* 43 << 16 */ + { { 0x7a01aeed6aca2231l,0x8135cf2ace80abbel,0xdc1a41b2ae5fdec9l, + 0xde34ea4da0174364l }, + { 0xa5104e453cf8b845l,0x4b6fd986675ba557l,0x4bc750af29c8cb4al, + 0x8bebb266583f9391l }, + 0 }, + /* 44 << 16 */ + { { 0x47110d7c1be3f9c5l,0x12b9e4485eadb4ddl,0x6e8c09870b713d41l, + 0xe1e20356733d56ael }, + { 0xe68d6bab445ea727l,0x9ef4f6eac934a1a4l,0xe0155547f8cef1c3l, + 0xdb5c3909159bdcbfl }, + 0 }, + /* 45 << 16 */ + { { 0xef0449cb32fa8a37l,0x95071f5dcd246405l,0x1c56ad776c598891l, + 0x981781de0fa9cd42l }, + { 0x0f93d456d29c0500l,0x43aa7bc1483f52c4l,0xd7c8736666c8abadl, + 0x47552530ea5050efl }, + 0 }, + /* 46 << 16 */ + { { 0x40dd9ca9fa9b8d3dl,0xf27b7bc056da41d9l,0x87967f4b66db8845l, + 0xf6918c9444de6bc7l }, + { 0x4d76d51135568d4dl,0x7ab18f9a40e7fa5al,0x069a44bba5bbbdc6l, + 0x19e6c04bb4c8f808l }, + 0 }, + /* 47 << 16 */ + { { 0x5fd2501108b2b6c7l,0xcce85a3ec41cad21l,0x90857daffdd70387l, + 0x7a679062c63789f4l }, + { 0x9c462134ef8666e2l,0xcb7dba108c8505bdl,0x7c4a7e2fc610f2e7l, + 0x22906f65d68315f9l }, + 0 }, + /* 48 << 16 */ + { { 0xf2efe23d442a8ad1l,0xc3816a7d06b9c164l,0xa9df2d8bdc0aa5e5l, + 0x191ae46f120a8e65l }, + { 0x83667f8700611c5bl,0x83171ed7ff109948l,0x33a2ecf8ca695952l, + 0xfa4a73eef48d1a13l }, + 0 }, + /* 49 << 16 */ + { { 0x41dd38c1118de9a0l,0x3485cb3be2d8f6f5l,0xd4bac751b1dcc577l, + 0x2148d93fed12ea6bl }, + { 0xde3504729da8cb18l,0x6046daf89eb85925l,0xddbc357b942b1044l, + 0x248e7afe815b8b7cl }, + 0 }, + /* 51 << 16 */ + { { 0xd4bb77b3acb21004l,0xe9f236cf83392035l,0xa9894c5c52133743l, + 0x4d6112749a7b054al }, + { 0xa61675ea4ba2a553l,0x59c199681da6aa78l,0x3988c36590f474del, + 0x73e751bbd001be43l }, + 0 }, + /* 52 << 16 */ + { { 0x97cacf846604007dl,0x1e92b4b22d47a9f1l,0x858ae0d6374ed165l, + 0x4c973e6f307aefb8l }, + { 0x6f524a238a10eb72l,0x7b4a92a9eb2849d6l,0x3678bda42fe91eddl, + 0x56092acd7c0fc35cl }, + 0 }, + /* 53 << 16 */ + { { 0x93bea99b1b9b43c4l,0x2f6af6f3e145fda2l,0x862f0607278adf0dl, + 0x647be08398456ccal }, + { 0xce79ba1487250c28l,0x1c1c4fc8efedab42l,0x966f612af90caa8dl, + 0xb1a2cf6e72c440f8l }, + 0 }, + /* 55 << 16 */ + { { 0x2fca1be45b3b7dd5l,0x453c19853c211bcal,0x313cb21969a46484l, + 0x66082837414bd5dfl }, + { 0xab7a97bf2ac1cdf7l,0x45cd1792676d778fl,0x42fb6c4f6a5b560al, + 0x45747fe30b8f17e9l }, + 0 }, + /* 57 << 16 */ + { { 0x38b6db6235db6218l,0xa10cdfe1bb54bacal,0x56fd4a1d610f7f6bl, + 0xc4bea78b76d183d7l }, + { 0xc0e6ca9fbf730d26l,0x1b1e271aed6cf535l,0x6fef275faadbe375l, + 0xfa2e8da903e489bal }, + 0 }, + /* 59 << 16 */ + { { 0x6f79d25c7c4626ecl,0xfe27690232d55d6cl,0x3f5c5768afa19ce3l, + 0xa1373777f8834739l }, + { 0x761d67a8a4ce960al,0xb34de1ea459e656al,0x8725b0f09db6f269l, + 0x75316f250dbfe22el }, + 0 }, + /* 60 << 16 */ + { { 0x091d5b631a093b40l,0xb85c1c075862f24al,0xc5d74eb53e8f85bfl, + 0xf51c7746cab22456l }, + { 0xc25cb8d9e761da89l,0x2670ec2fc0f028b5l,0x873fd30d2db9af5cl, + 0x3d0f1ea18262565el }, + 0 }, + /* 61 << 16 */ + { { 0x8f9492c261c23b3cl,0xd366baeb631688a4l,0x55e759e78093bb07l, + 0xf6d0eaf47218f765l }, + { 0xb8a174ff54ca583bl,0x790f10e0b23d14cel,0xfebe7333be83cbbal, + 0xfeb6dcc5eed67536l }, + 0 }, + /* 63 << 16 */ + { { 0x175b3bacce027e5bl,0xe0728a99c48252c4l,0x0be25d4507a39c7cl, + 0xcb9c2d3aba8e8c72l }, + { 0x6185a48d1abd459al,0x27207feadff9a27bl,0xfd92e8231d34393fl, + 0x738511534351d965l }, + 0 }, + /* 64 << 16 */ + { { 0xfcde7cc8f43a730fl,0xe89b6f3c33ab590el,0xc823f529ad03240bl, + 0x82b79afe98bea5dbl }, + { 0x568f2856962fe5del,0x0c590adb60c591f3l,0x1fc74a144a28a858l, + 0x3b662498b3203f4cl }, + 0 }, + /* 65 << 16 */ + { { 0x8ede0fcdc11682eel,0x41e3faa1b2ab5664l,0x58b2a7dc26a35ff5l, + 0x939bcd6b701b89e9l }, + { 0x55f66fd188e0838fl,0x99d1a77b4ff1f975l,0x103abbf72e060cc5l, + 0x91c77beb6bc4bdbbl }, + 0 }, + /* 71 << 16 */ + { { 0xcd048abca380cc72l,0x91cab1bbd0e13662l,0x68115b18686de4cel, + 0x484724e63deccbf5l }, + { 0xf164ba54f176137el,0x5189793662ab2728l,0x6afdecf9b60a5458l, + 0xca40472d0aabafd2l }, + 0 }, + /* 77 << 16 */ + { { 0x7a9439183b98d725l,0x1c1763e8ece1ea3cl,0x45c44ef639840476l, + 0x689271e69c009133l }, + { 0xa017405f56a51fe1l,0xd54cc7253e0d0970l,0x212ad075cfe09e8bl, + 0x999f21c37af7bf30l }, + 0 }, + /* 83 << 16 */ + { { 0xdc2a2af12bf95f73l,0xb88b4ca76de82cbel,0xa31a21aaecb8e84el, + 0x86d19a601b74f5bel }, + { 0xc68bf64406008019l,0xe52ab50e9431c694l,0x6375463d627ab11cl, + 0xdd3eeaa03c0ef241l }, + 0 }, + /* 89 << 16 */ + { { 0x608d9cb323f1caf8l,0x95069450b1700741l,0xe3132bd2bc2fa7aal, + 0xc4f363e7f64e4f06l }, + { 0xb059c4191ca888c2l,0x1004cb1f8d17bf5dl,0x6b6ba6f934ea5711l, + 0x071d94abd79b2c8al }, + 0 }, + /* 95 << 16 */ + { { 0xc7ef9b42d147a39dl,0x36dd5d770a10cd5bl,0x3bf6cc77d0eea34bl, + 0x60c84591197479c7l }, + { 0xf95860ac50ba50edl,0xe1c94a8dc4cdc8fal,0x780818d685e24a23l, + 0x1950e3c0c8abbd27l }, + 0 }, + /* 101 << 16 */ + { { 0x9908c694ae04778el,0x2e37a6790a0d36ffl,0x212a340f52b067bdl, + 0xec89c9fad080b914l }, + { 0x920dc2f005ab8a23l,0xecff5c78655e8984l,0x80eedd34f66211acl, + 0xa7a56366ef58d4d8l }, + 0 }, + /* 107 << 16 */ + { { 0x4f95debe2bca42f0l,0xf0346307844334d2l,0x7003a60521d600aal, + 0x1eb98c6365c5248al }, + { 0x6757b3822fa202cal,0x32765d399fb12f36l,0xe851b476d7b44c9al, + 0x27cd7d1b4e0bab4cl }, + 0 }, + /* 113 << 16 */ + { { 0xd0c1f7c9c43ea1a3l,0x73d944f49f42907dl,0xd113f34619352c92l, + 0x86a1ad53b149cdc1l }, + { 0x32c34e8f848d1be4l,0xba8afda7c3d9360bl,0x17e8bc32eea8bf96l, + 0x3174cae499c87febl }, + 0 }, + /* 116 << 16 */ + { { 0x4b215f016671b47el,0xb67633ca4a8dae2al,0x2915120f79fd3cdbl, + 0xc1f8a06fb064e6del }, + { 0xf4d5368cc1d57420l,0x6ada51a8e18de475l,0xa0f0d47cc749d4b0l, + 0xabfa2c0074526aa5l }, + 0 }, + /* 119 << 16 */ + { { 0xf752f6659e5ce44fl,0x7b97ebfa189d35ecl,0x9540cbb90fc609abl, + 0x19c1dc6999632cc8l }, + { 0x0a957700e08ca9a8l,0xb0cd0ab7a3246a4el,0xca687cfcc8d6a544l, + 0xb6281f0035f82a77l }, + 0 }, + /* 125 << 16 */ + { { 0x547027012b818036l,0xf72315f729c8f14cl,0x95f1bc15230e74bel, + 0x2e7c492f1abe20d4l }, + { 0xe1ea8b1cd7e78ab1l,0xc3f6ba59043585adl,0xac404ea9477ac053l, + 0xaa6872914ec6d0e3l }, + 0 }, + }, + { + /* 0 << 24 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 24 */ + { { 0xd9d0c8c4868af75dl,0xd7325cff45c8c7eal,0xab471996cc81ecb0l, + 0xff5d55f3611824edl }, + { 0xbe3145411977a0eel,0x5085c4c5722038c6l,0x2d5335bff94bb495l, + 0x894ad8a6c8e2a082l }, + 0 }, + /* 3 << 24 */ + { { 0xd1e059b21994ef20l,0x2a653b69638ae318l,0x70d5eb582f699010l, + 0x279739f709f5f84al }, + { 0x5da4663c8b799336l,0xfdfdf14d203c37ebl,0x32d8a9dca1dbfb2dl, + 0xab40cff077d48f9bl }, + 0 }, + /* 4 << 24 */ + { { 0xf2369f0b879fbbedl,0x0ff0ae86da9d1869l,0x5251d75956766f45l, + 0x4984d8c02be8d0fcl }, + { 0x7ecc95a6d21008f0l,0x29bd54a03a1a1c49l,0xab9828c5d26c50f3l, + 0x32c0087c51d0d251l }, + 0 }, + /* 5 << 24 */ + { { 0xf61790abfbaf50a5l,0xdf55e76b684e0750l,0xec516da7f176b005l, + 0x575553bb7a2dddc7l }, + { 0x37c87ca3553afa73l,0x315f3ffc4d55c251l,0xe846442aaf3e5d35l, + 0x61b911496495ff28l }, + 0 }, + /* 7 << 24 */ + { { 0x4bdf3a4956f90823l,0xba0f5080741d777bl,0x091d71c3f38bf760l, + 0x9633d50f9b625b02l }, + { 0x03ecb743b8c9de61l,0xb47512545de74720l,0x9f9defc974ce1cb2l, + 0x774a4f6a00bd32efl }, + 0 }, + /* 9 << 24 */ + { { 0x327bc002b0131e5bl,0x1739e6d5cb2514d9l,0xc8cbdafe55a81543l, + 0x5bb1a36ce1137243l }, + { 0x205da3c517325327l,0xc35c1a36515a057el,0xf00f64c942925f9bl, + 0xbd14633cb7d59f7al }, + 0 }, + /* 10 << 24 */ + { { 0xae2ad171656e8c3al,0xc0e2a4631acd0705l,0x006f6a8aa0b6055cl, + 0xaf4513d72b65a26el }, + { 0x3f549e14d616d5bcl,0x64ee395571253b1fl,0xe8b10bc1b8ce243al, + 0xbcbeace5913a4e77l }, + 0 }, + /* 11 << 24 */ + { { 0x47c1004341f37dbdl,0x96eccae36168ecf6l,0x65bde59d1ca46aa3l, + 0x38a7027ab8698ffal }, + { 0xa2b89dc86dc34437l,0x5a0a118d43a4153fl,0x9e330a861ce22fd8l, + 0x28382af6b3bbd3bcl }, + 0 }, + /* 13 << 24 */ + { { 0x0b2e27c0d81e0271l,0xa67a7596117a317cl,0x17f08928a6723d99l, + 0x71a75681485310a3l }, + { 0x90465462afb66ca9l,0x185e97ccfbbe229dl,0x6a1a606addad8fc2l, + 0x2431f316b3c797cfl }, + 0 }, + /* 15 << 24 */ + { { 0x4703401193529432l,0x1f106bdd30743462l,0xabfb9964cd66d8cal, + 0x934d9d5ae9bdadd5l }, + { 0x5976d815908e3d22l,0x344a362f28e057bdl,0xf92cdadc5443dfb3l, + 0x001297adf089603bl }, + 0 }, + /* 16 << 24 */ + { { 0x7f99824f20151427l,0x206828b692430206l,0xaa9097d7e1112357l, + 0xacf9a2f209e414ecl }, + { 0xdbdac9da27915356l,0x7e0734b7001efee3l,0x54fab5bbd2b288e2l, + 0x4c630fc4f62dd09cl }, + 0 }, + /* 17 << 24 */ + { { 0x4a2fce605044066bl,0x904a019cfa3a47f4l,0xba81ea9c0c5c0a60l, + 0xd7e4ea0d96c098bdl }, + { 0xefe700419cd50a02l,0xc0c839d42d7f048cl,0xe2daf264e09b561fl, + 0x0cbc13185034b18bl }, + 0 }, + /* 19 << 24 */ + { { 0x11e5f2e388323f7al,0xe07a74c2927584cdl,0x1e774b3495613d2dl, + 0x9c9b52c52c787488l }, + { 0x3cdd3c3ebe421f08l,0x5ff7819e223e3d5fl,0xba8739b2c1da09b9l, + 0x6b7263164e8b491bl }, + 0 }, + /* 21 << 24 */ + { { 0xb5afd13ca0943befl,0xd651772957abb1ccl,0x9d5a52dc9b61b5bcl, + 0x85cefaa6806e31cdl }, + { 0xab84257a720a1deal,0x6a60261bced70d35l,0xc023f94db9d6da61l, + 0x947f7eec54a0ae0el }, + 0 }, + /* 23 << 24 */ + { { 0xc3b787569f83b787l,0xd6d249263694ddd7l,0x58d248945d70a02el, + 0xac16670e8c278c6al }, + { 0x71a94d58e370b6e6l,0xe4d763840253db05l,0x99b1c98814b32cfel, + 0x4e6bd870cc78cc95l }, + 0 }, + /* 25 << 24 */ + { { 0xf5f7ca79c8b63614l,0xf3bfb2158af4903cl,0x2bdb9f5496d47bd3l, + 0xd6e715300e8a63bal }, + { 0x67e90a497a93bec4l,0x8613478b8c1e63eel,0xe36bd9c8f2dde561l, + 0x681486518a768689l }, + 0 }, + /* 27 << 24 */ + { { 0xef617a9494aa531cl,0x9ac35e2fd6f4ad87l,0xbcd2a047122468fbl, + 0xbd7a423fef7c5ca6l }, + { 0xab58cb52064c8040l,0x93ef4ed54a644716l,0xf7d17097c32cd48dl, + 0xb249a173d17fcf42l }, + 0 }, + /* 28 << 24 */ + { { 0x66fe0fffe298cdf5l,0x3f61bea47b2e51b6l,0x7d372117bad3afa4l, + 0x6521a09cef656e2fl }, + { 0xb3b8c966e8a58fe7l,0x25203a115a47ebc7l,0xfe81588d5c4be573l, + 0x6132e2f31f49a03cl }, + 0 }, + /* 29 << 24 */ + { { 0xbbe5c108b7a7ecc4l,0x62a5a78ebfd22e4cl,0xb7974033df188bd2l, + 0xcf11deea4df7d1ael }, + { 0x99cc774a53ace3eal,0xe0373a71105cc1f6l,0xd751987f133d7a20l, + 0xab86ee04ae215871l }, + 0 }, + /* 31 << 24 */ + { { 0x2094f9a280cd10e6l,0x045232aa7b8a0da7l,0x969a81b69c03244el, + 0x1293b4ca7e98d955l }, + { 0x1631421dd68f3ab0l,0xa0106422c3738c82l,0xc5f43845f82c4ff9l, + 0xb479acbe1aa0f58fl }, + 0 }, + /* 33 << 24 */ + { { 0xf1db0267f67683cfl,0xa6b13c9e44ce009dl,0x04b4eed505884a69l, + 0xf2ff9c16d9087a0bl }, + { 0x2c53699b3e35b4a6l,0x5020c0142369afb8l,0xf83bfe0095be37f1l, + 0xd300d8c553b29d80l }, + 0 }, + /* 34 << 24 */ + { { 0x16893055811cf4bbl,0x580dd1e55aeb5027l,0xcaf47fba5ae3c71cl, + 0xde79698129ebbb07l }, + { 0xbed1db33d262cdd3l,0x78315e3748c7313bl,0xfc9561f02fe1368dl, + 0xe0209698ccacacc7l }, + 0 }, + /* 35 << 24 */ + { { 0xd61af89a781ece24l,0xf3b90626008f41e9l,0xd715dbf7c5693191l, + 0x8d6c05de6f299edel }, + { 0xf18d62637ca50aacl,0x7987bf5cb0dd5fdcl,0x424136bd2cfa702bl, + 0xaa7e237ded859db2l }, + 0 }, + /* 36 << 24 */ + { { 0xde7169e4e5d41796l,0x6700333e33c0a380l,0xe20b95780343a994l, + 0xa745455e1fb3a1c3l }, + { 0x97e0ff88ce029a7fl,0x3b3481c976e384bcl,0x028b339dddad5951l, + 0xa1fdcdbae4b95cfcl }, + 0 }, + /* 37 << 24 */ + { { 0xcc9221baed20c6adl,0xf2619a51fa9c73aal,0xfc2cff847d7f55a5l, + 0xd56c23d65f01d4dal }, + { 0x6d20f88cb3d84d5fl,0x048825f75dcc615dl,0x73634d3f85631a6el, + 0xa57a02e3ad7b2e2dl }, + 0 }, + /* 39 << 24 */ + { { 0x067a8dcf08aa81ffl,0x62948258c23f3d16l,0xb61bd04316f2fe7bl, + 0xf250f769b6a766b1l }, + { 0x32df97246d0b241el,0xb736e4bb714e5f88l,0x50da15022c1d40d7l, + 0x013e0edebdd285a4l }, + 0 }, + /* 40 << 24 */ + { { 0x1b92c3a0181a5d8fl,0x6429531d9adb77c7l,0x629152b53af710eel, + 0x4e3f27370bd5647el }, + { 0xfb7c392b77553c7dl,0xa930abacefe78c87l,0xf80c8cd6a05a6991l, + 0x751469b71be5f6f5l }, + 0 }, + /* 41 << 24 */ + { { 0xf89f2b0b3e2f2af0l,0x52f634099eefc39al,0x505005c679906cb6l, + 0x820c2216b2de0b1el }, + { 0x96f0f2831f20ad7al,0xcd33125c718ffcb0l,0xf6130ef278f0c578l, + 0x4cda2471d0b76b95l }, + 0 }, + /* 43 << 24 */ + { { 0x611dd83f39485581l,0x96c47051803e1b20l,0xefacc736830f44c7l, + 0x5588d8ce688b12bal }, + { 0x44f4edf3eee70fadl,0x1026dfd8869539f7l,0xa4c146ee8ddb0e00l, + 0x9f4f55816efb41c8l }, + 0 }, + /* 44 << 24 */ + { { 0x6036ed0236cbace7l,0x5a70e4abada837ddl,0xf06918aff10b2fefl, + 0x08a8a9f69fd31590l }, + { 0x6c4a1ba6916af88dl,0x4868bc1466016037l,0x06d345af164228a9l, + 0x2c1961d19b550dd9l }, + 0 }, + /* 45 << 24 */ + { { 0x8b72775c6851f0acl,0x7827242bd70f5975l,0x2de91f1e34db4a6fl, + 0x586bf3d58538f5eel }, + { 0xf0a15aed25d9a09bl,0x43018e56f74deb46l,0xc2af1ad0f50e0e67l, + 0x49cc9528b10cff6fl }, + 0 }, + /* 46 << 24 */ + { { 0x05eb146c9d55c425l,0xe2b557ccbc62261fl,0x2a716301bd077089l, + 0x83a63c81e0527d02l }, + { 0x055ff7f8a0d9203bl,0x05d09f0525bf5a04l,0x2e44545fb3eb0b30l, + 0xed7c57c4d279a1adl }, + 0 }, + /* 47 << 24 */ + { { 0x6928f6e45e0ebdd5l,0xd7e44ddf092d233bl,0xe7148066d1b7026fl, + 0xf645a2e53d5f25c3l }, + { 0x6eeb25ee58ff9eb4l,0x60f1fcf737f87ebfl,0x9eaaf1e5c4679c70l, + 0x4609fb13b7b7dc7el }, + 0 }, + /* 48 << 24 */ + { { 0xae915f5d5fa067d1l,0x4134b57f9668960cl,0xbd3656d6a48edaacl, + 0xdac1e3e4fc1d7436l }, + { 0x674ff869d81fbb26l,0x449ed3ecb26c33d4l,0x85138705d94203e8l, + 0xccde538bbeeb6f4al }, + 0 }, + /* 49 << 24 */ + { { 0x27f317af2b33987fl,0xd2d3cf5d51e59588l,0x333999bd031f27c9l, + 0x6ddfa3f22e0a3306l }, + { 0x23e0e651990041b0l,0xf028aba1585837acl,0x1c6ad72b25226f53l, + 0xf243c991d1fca64al }, + 0 }, + /* 51 << 24 */ + { { 0x72b8a13272cbae1fl,0xfe0b1c4fbfdbd64al,0x98bc7876c5e76921l, + 0x51c726bfdb1f5af7l }, + { 0x97e88a842c186e8bl,0x9ed99516ed8eb7b4l,0x3e54a17dafc818ebl, + 0xfcfbf25a1e8f77d8l }, + 0 }, + /* 52 << 24 */ + { { 0x7780d7d68f7d5c6el,0x6725b49a454101e6l,0xceddc26586b0770cl, + 0xc26624615666f504l }, + { 0x16b77477ce040f75l,0x13f9113c293f8b45l,0xff0cfa07e2dcc91el, + 0x1948d8bd41c202f5l }, + 0 }, + /* 53 << 24 */ + { { 0x4c6ae39a1dfbe13al,0xafb1e5c46be9c200l,0x39e728d168bb08c3l, + 0xc794b905acc9166fl }, + { 0x1cb0dec2d9c7c3e4l,0xc4c3053289f14d65l,0x4af80801a6a9d609l, + 0x79d7e82de0d6ab24l }, + 0 }, + /* 55 << 24 */ + { { 0xb905c6af8ad4cf6el,0x785590b0f6d1be13l,0x78f402c2a0ef76bel, + 0x739b22ea5c19a40bl }, + { 0xd4d3262553d596b6l,0x01598eb4d571666bl,0xf8dc150b8173486al, + 0xd8aa43af15e94f09l }, + 0 }, + /* 57 << 24 */ + { { 0xcfa387cd984393b5l,0x1645659e21a1bf92l,0xb4ab3966dd46c7eel, + 0xcf8c296d89482623l }, + { 0x72e4d01cf976b4c0l,0x44ad07e8fa0fa5ebl,0xd6c82681b486fdd2l, + 0x2d9074f89b8845b4l }, + 0 }, + /* 59 << 24 */ + { { 0x96e4fc08d96862dbl,0xf9e29bb6c50c14b2l,0xfedaad64f8f9be75l, + 0xab6b2d79ae9e1274l }, + { 0x033e3eb58d84dec0l,0xc136904ccbd113e7l,0xb82b0aed6061f289l, + 0x3476d9247b699e25l }, + 0 }, + /* 60 << 24 */ + { { 0x8fb5ceeb969231dcl,0xaed13be1686ff6cdl,0x71d7c67bdd69db87l, + 0x49613e08fb53f33al }, + { 0x2899729ead8e802fl,0x83bfde49d1982a1dl,0x675c45ea878239d2l, + 0xb7bf59cd0d8240d3l }, + 0 }, + /* 61 << 24 */ + { { 0x853d8cd1baf53b8bl,0x9c73d04cff95fc18l,0xae8a94412d1d6aacl, + 0xd8a15ce901500b70l }, + { 0xaef813499aacba59l,0x2cd2ba0ac493cd8dl,0x01c37ee1f398f034l, + 0xed72d51d0f7299fcl }, + 0 }, + /* 63 << 24 */ + { { 0x2c204940e7592fb1l,0xcc1bb19b49366f08l,0x31855e8a7c927935l, + 0x16f7e9a2c590b81dl }, + { 0xa5fbb7c1ed8df240l,0x7b5204122de2d7f5l,0x7eb1eb989a637588l, + 0x5ef4eca89540d2e8l }, + 0 }, + /* 64 << 24 */ + { { 0x55d5c68da61a76fal,0x598b441dca1554dcl,0xd39923b9773b279cl, + 0x33331d3c36bf9efcl }, + { 0x2d4c848e298de399l,0xcfdb8e77a1a27f56l,0x94c855ea57b8ab70l, + 0xdcdb9dae6f7879bal }, + 0 }, + /* 65 << 24 */ + { { 0x811e14dd9594afb8l,0xaf6c1b10d349124al,0x8488021b6528a642l, + 0xecf6834341cf1447l }, + { 0x7a40acb756924446l,0xd9c11bbed98ec4cfl,0x0cef00bfb2bff163l, + 0xfaaad8015432803bl }, + 0 }, + /* 71 << 24 */ + { { 0x5a217d5e6b075cbel,0x7ef88d1dc89b513bl,0xb6d015da0531c93bl, + 0x477b502a6333834al }, + { 0x4655e48b2fb458d5l,0x93f21a7cb7674ca8l,0xa0616786502d1f3al, + 0x82d16d17f26bb6ccl }, + 0 }, + /* 77 << 24 */ + { { 0x3d995aa9183c1688l,0xa125906c3766d2e8l,0x23ed7871c5f10d5bl, + 0xdfe1e1cc6df80368l }, + { 0x8bfcb54271eaae2cl,0xe94e6f910945a7bbl,0xd543ef90862f650al, + 0x0dc043b803eed66bl }, + 0 }, + /* 83 << 24 */ + { { 0x0c6a5620060d2ccdl,0xcd8200e37a8a03a4l,0x6018d304793867e6l, + 0xad23dd61a74d054dl }, + { 0x5a856faeebc21eb4l,0x66be16714b5cd7dbl,0xe0d0441ec75f8c9dl, + 0xb80ca9ecf90dbc6dl }, + 0 }, + /* 89 << 24 */ + { { 0xbd6902ccd24692cbl,0xbcce6bbc21920408l,0x40f120ca55dec4c5l, + 0xd9f1f5ef5361c8b3l }, + { 0x535d368226935dffl,0x9635447b01a9998al,0x8c4ec40d99e36d12l, + 0xbaeef8912b793369l }, + 0 }, + /* 95 << 24 */ + { { 0xded3a51c1cd887ebl,0xd43225568376515cl,0xdaf3a2271ca7c097l, + 0x089156fdecd4d90cl }, + { 0x2b354810ca0727c9l,0xb7257c1966c19d8cl,0x5e68a379432d5072l, + 0x75c04c2443e585c7l }, + 0 }, + /* 101 << 24 */ + { { 0xb5ba2a8fe5e0952fl,0x2c2d086811040b4el,0x27448bd5f818e253l, + 0x720f677987a92c85l }, + { 0x2c9b2367b9d035fal,0xf18ad8ce16c15ab9l,0xd65a360841bd57eel, + 0xeb4b07c9ff6ae897l }, + 0 }, + /* 107 << 24 */ + { { 0xcffb6d71d38589acl,0x812372920fa509d3l,0x94db5ba6e54725e8l, + 0x1ad2b4206cfbb825l }, + { 0x8592c1f238cfb9f2l,0xbe8e917e0eec6a27l,0x53921bfe9d93d42fl, + 0x1aa95e6269454a35l }, + 0 }, + /* 113 << 24 */ + { { 0xc25e8934d898049dl,0xeeaf4e6d3bb3d459l,0xc3ac44447d29ad10l, + 0xccdf9fcbcef8fa04l }, + { 0x1d995a3fb9679cb9l,0x3d6c5eab46fabc14l,0xd3849ff066385d4dl, + 0xc0eb21bacff08be2l }, + 0 }, + /* 116 << 24 */ + { { 0x8213c71e90d13fd6l,0x114321149bb6b733l,0xaaf8037880ac4902l, + 0xb24e046b555f7557l }, + { 0x5f6ed2881db79832l,0xd493a758ac760e5dl,0xbc30a2a7a1c0f570l, + 0xa5009807161174e3l }, + 0 }, + /* 119 << 24 */ + { { 0x9e9b864a6889e952l,0xee908932f352f31al,0xe421f2423166b932l, + 0x6dd4aa3b7ddbdb35l }, + { 0x553cc5639e8b88a4l,0x05457f171f04704dl,0x1dcc3004c9554e6bl, + 0x3a4a3a253f1b61e7l }, + 0 }, + /* 125 << 24 */ + { { 0x7ac0a5e7c56e303al,0x7c7bab64037b0a19l,0x11f103fcc8d29a2bl, + 0x7d99dc46cf0b1340l }, + { 0x0481588ceffba92el,0x8a817356b04e77bcl,0x19edf4dbce1b708dl, + 0xa2a1f7a6e6f9d52cl }, + 0 }, + }, + { + /* 0 << 32 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 32 */ + { { 0x202886024147519al,0xd0981eac26b372f0l,0xa9d4a7caa785ebc8l, + 0xd953c50ddbdf58e9l }, + { 0x9d6361ccfd590f8fl,0x72e9626b44e6c917l,0x7fd9611022eb64cfl, + 0x863ebb7e9eb288f3l }, + 0 }, + /* 3 << 32 */ + { { 0xa18f07e0e90fb21el,0x00fd2b80bba7fca1l,0x20387f2795cd67b5l, + 0x5b89a4e7d39707f7l }, + { 0x8f83ad3f894407cel,0xa0025b946c226132l,0xc79563c7f906c13bl, + 0x5f548f314e7bb025l }, + 0 }, + /* 4 << 32 */ + { { 0x0ee6d3a7c35d8794l,0x042e65580356bae5l,0x9f59698d643322fdl, + 0x9379ae1550a61967l }, + { 0x64b9ae62fcc9981el,0xaed3d6316d2934c6l,0x2454b3025e4e65ebl, + 0xab09f647f9950428l }, + 0 }, + /* 5 << 32 */ + { { 0xc1b3d3d331b85f09l,0x0f45354aa88ae64al,0xa8b626d32fec50fdl, + 0x1bdcfbd4e828834fl }, + { 0xe45a2866cd522539l,0xfa9d4732810f7ab3l,0xd8c1d6b4c905f293l, + 0x10ac80473461b597l }, + 0 }, + /* 7 << 32 */ + { { 0xbbb175146fc627e2l,0xa0569bc591573a51l,0xa7016d9e358243d5l, + 0x0dac0c56ac1d6692l }, + { 0x993833b5da590d5fl,0xa8067803de817491l,0x65b4f2124dbf75d0l, + 0xcc960232ccf80cfbl }, + 0 }, + /* 9 << 32 */ + { { 0x35d742806cf3d65bl,0x4b7c790678b28dd9l,0xc4fcdd2f95e1f85fl, + 0xcf6fb7ba591350b6l }, + { 0x9f8e3287edfc26afl,0xe2dd9e73c2d0ed9al,0xeab5d67f24cbb703l, + 0x60c293999a759a5al }, + 0 }, + /* 10 << 32 */ + { { 0xcf8625d7708f97cdl,0xfb6c5119ea419de4l,0xe8cb234dc03f9b06l, + 0x5a7822c335e23972l }, + { 0x9b876319a284ff10l,0xefcc49977093fdcel,0xdddfd62a878fe39al, + 0x44bfbe53910aa059l }, + 0 }, + /* 11 << 32 */ + { { 0xfb93ca3d7ca53d5fl,0x432649f004379cbfl,0xf506113acba2ff75l, + 0x4594ae2103718b35l }, + { 0x1aa6cee50d044627l,0xc0e0d2b7f5c94aa2l,0x0bf33d3dee4dd3f5l, + 0xaca96e288477c97al }, + 0 }, + /* 13 << 32 */ + { { 0x995c068e6861a713l,0xa9ba339463de88dcl,0xab954344689a964fl, + 0x58195aec0f5a0d6cl }, + { 0xc5f207d5c98f8b50l,0x6600cd280c98ccf6l,0x1a680fe339c3e6c2l, + 0xa23f3931660e87c0l }, + 0 }, + /* 15 << 32 */ + { { 0x43bc1b42c78440a1l,0x9a07e22632ac6c3fl,0xaf3d7ba10f4bcd15l, + 0x3ad43c9da36814c6l }, + { 0xca11f742a0c9c162l,0xd3e06fc6c90b96ecl,0xeace6e766bf2d03fl, + 0x8bcd98e8f8032795l }, + 0 }, + /* 16 << 32 */ + { { 0xe27a6dbe305406ddl,0x8eb7dc7fdd5d1957l,0xf54a6876387d4d8fl, + 0x9c479409c7762de4l }, + { 0xbe4d5b5d99b30778l,0x25380c566e793682l,0x602d37f3dac740e3l, + 0x140deabe1566e4ael }, + 0 }, + /* 17 << 32 */ + { { 0x7be3ddb77099ae96l,0x83d6157306e0da6al,0x31bcac5f74bf9870l, + 0x7f7aa3b422b256f1l }, + { 0xff84d63caa212e20l,0x7d636556decdc8b5l,0x8fed824dbf909d62l, + 0x62d70186e5fb1445l }, + 0 }, + /* 19 << 32 */ + { { 0x8796989f67d8ab8al,0xa46282253700b772l,0xa353cadf05f799abl, + 0x7a8be2741eeb06bbl }, + { 0xf74a367e4653b134l,0x4e43449660c70340l,0xc99b6d6b72e10b18l, + 0xcf1adf0f1ba636e1l }, + 0 }, + /* 21 << 32 */ + { { 0xb0260fb57c6a0958l,0xae791b9c2fc2731el,0xb339f2bf8ce6e575l, + 0x769214a816e2639fl }, + { 0xbaf422e1346da10el,0xc7805fdf7a56f463l,0xf47b6b766f845428l, + 0x8f21369e38492948l }, + 0 }, + /* 23 << 32 */ + { { 0x2bac716a17931a90l,0x42a5e27cc8267236l,0xfd4b367c0bafeb78l, + 0x5856e69c6173db02l }, + { 0xfaac7358973d73c4l,0xbfbffcc36768d285l,0x05444ff2be3eb243l, + 0x9f8d3692f3c323fel }, + 0 }, + /* 25 << 32 */ + { { 0xac296863221c31a9l,0x46f3a24ef1ca99a9l,0xd927648a7535a864l, + 0xd7e3c47d5848e497l }, + { 0xc19595b782a98ac7l,0x9a9bf627273ff554l,0xe29aa48fb62298a1l, + 0xed3f068ee797e9e3l }, + 0 }, + /* 27 << 32 */ + { { 0x8d16a1660eb9227bl,0xe04c6bc58c37c74bl,0xd1be9585cc1ef78cl, + 0xa5cfe1962e929d9bl }, + { 0xc9b0ea21417c1cc6l,0x316352d345b79599l,0xc1502c4dc2d54af7l, + 0xe7f4412990f83445l }, + 0 }, + /* 28 << 32 */ + { { 0x0f6704abd95917e8l,0x168dafaeaec6e899l,0xd2833e8cde710027l, + 0x34ea277e68ee3c59l }, + { 0x3689e2350054d4e5l,0x6f3a568d11013943l,0xb5ce1ff69bc2b144l, + 0x705bfe7e72b33a59l }, + 0 }, + /* 29 << 32 */ + { { 0x1baa4f02c8e93284l,0xec6b93ea3c97d3e8l,0xb656c149034f8b32l, + 0x3cab9063cd4cc69fl }, + { 0xd8de5989d61031ccl,0xcf85329fc1b1de1dl,0xf18b78b323d8cb9al, + 0x6dc04bc61a6b69eal }, + 0 }, + /* 31 << 32 */ + { { 0x79cf86314a1d4f8fl,0xda5ba331aa47394el,0x36f9c0be8ff20527l, + 0xccdc719bbc7097f6l }, + { 0x2304a3ba5cb052bbl,0xab80cdea392f0ab5l,0x0ac1858bf38de03bl, + 0xd6e2119878a8f55dl }, + 0 }, + /* 33 << 32 */ + { { 0x6bdebc26584bc618l,0x499f0f1894591499l,0xd35ed50bf4a573dal, + 0x5a622e73ff2792d0l }, + { 0x8510cbce68d41a3bl,0x6610f43c94e919afl,0x4527373dc163c8a1l, + 0x50afb46f280a8a7dl }, + 0 }, + /* 34 << 32 */ + { { 0x33e779cd8de7707al,0xf94bbd94438f535bl,0x61159864be144878l, + 0xb6623235f098ce4al }, + { 0x6813b71ba65568d8l,0x6603dd4c2f796451l,0x9a97d88c8b9ee5b2l, + 0xaaa4593549d5926cl }, + 0 }, + /* 35 << 32 */ + { { 0x2e01fc75ebe75bf2l,0x8270318d6cbdd09cl,0x534e4f21d3f1a196l, + 0x6c9eaeca9459173el }, + { 0xda454fe0b642a1d4l,0xe45b69bfc4664c4al,0x4724bd423e078dc8l, + 0x39ac8fe603336b81l }, + 0 }, + /* 36 << 32 */ + { { 0x0a2e53dd302e9485l,0x75882a19deaa9ff4l,0xe283242eac8de4ddl, + 0x2742105cc678dba7l }, + { 0x9f6f0a88cdb3a8a2l,0x5c9d3338f722e894l,0xf1fa3143c38c31c1l, + 0x22137e2db18c77acl }, + 0 }, + /* 37 << 32 */ + { { 0xd821665e368d7835l,0x3300c012b596c6ecl,0xb60da7353557b2ddl, + 0x6c3d9db6fb8cf9ael }, + { 0x092d8b0b8b4b0d34l,0x900a0bf4b3d4107dl,0x75371a245e813ec3l, + 0x91125a17f2ad56d5l }, + 0 }, + /* 39 << 32 */ + { { 0x5e6594e2fe0073e6l,0x908a93778be13cb7l,0xa2c3d5c8ac26617cl, + 0xa0bab085c317c6b9l }, + { 0x0bdc183b83664109l,0x6bbba2b468f9dcd9l,0x697a50785814be41l, + 0x12a59b183a5e5f98l }, + 0 }, + /* 40 << 32 */ + { { 0xbd9802e6c30fa92bl,0x5a70d96d9a552784l,0x9085c4ea3f83169bl, + 0xfa9423bb06908228l }, + { 0x2ffebe12fe97a5b9l,0x85da604971b99118l,0x9cbc2f7f63178846l, + 0xfd96bc709153218el }, + 0 }, + /* 41 << 32 */ + { { 0xb5a85c61bfa70ca6l,0x4edc7f2d4c1f745fl,0x05aea9aa3ded1eb5l, + 0x750385efb82e5918l }, + { 0xdcbc53221fdc5164l,0x32a5721f6794184el,0x5c5b2269ff09c90bl, + 0x96d009115323ca42l }, + 0 }, + /* 43 << 32 */ + { { 0x12c73403f43f1440l,0xc94813eb66cc1f50l,0x04d5957b9b035151l, + 0x76011bca4bfaafa8l }, + { 0x56806c13574f1f0al,0x98f63a4697652a62l,0x17c63ef4a3178de9l, + 0xf7ce961a65009a52l }, + 0 }, + /* 44 << 32 */ + { { 0x58f92aebe4173516l,0xdc37d99275e42d44l,0x76dcec5b4d48e1bal, + 0x07e0608e25676448l }, + { 0xa1877bcd1d4af36al,0x38b62b3c5a8ccf0cl,0x60522e88aeab7f75l, + 0xbef213ed5e03547al }, + 0 }, + /* 45 << 32 */ + { { 0x8acd5ba4e6ed0282l,0x792328f06a04531dl,0xe95de8aa80297e50l, + 0x79d33ce07d60e05cl }, + { 0xcb84646dd827d602l,0xd3421521302a608cl,0x867970a4524f9751l, + 0x05e2f7e347a75734l }, + 0 }, + /* 46 << 32 */ + { { 0x64e4de4a01c66263l,0xbcfe16a4d0033d4cl,0x359e23d4817de1dcl, + 0xb01e812ec259449cl }, + { 0x90c9ade2df53499fl,0xabbeaa27288c6862l,0x5a655db4cd1b896fl, + 0x416f10a5a022a3d6l }, + 0 }, + /* 47 << 32 */ + { { 0x0d17e1ef98601fd5l,0x9a3f85e0eab76a6fl,0x0b9eaed1510b80a1l, + 0x3282fd747ec30422l }, + { 0xaca5815a70a4a402l,0xfad3121cf2439cb2l,0xba251af81fccabd6l, + 0xb382843fa5c127d5l }, + 0 }, + /* 48 << 32 */ + { { 0x958381db1782269bl,0xae34bf792597e550l,0xbb5c60645f385153l, + 0x6f0e96afe3088048l }, + { 0xbf6a021577884456l,0xb3b5688c69310ea7l,0x17c9429504fad2del, + 0xe020f0e517896d4dl }, + 0 }, + /* 49 << 32 */ + { { 0x442fdfe920cd1ebel,0xa8317dfa6a250d62l,0x5214576d082d5a2dl, + 0xc1a5d31930803c33l }, + { 0x33eee5b25e4a2cd0l,0x7df181b3b4db8011l,0x249285145b5c6b0bl, + 0x464c1c5828bf8837l }, + 0 }, + /* 51 << 32 */ + { { 0x5464da65d55babd1l,0x50eaad2a0048d80fl,0x782ca3dd2b9bce90l, + 0x41107164ab526844l }, + { 0xad3f0602d56e0a5fl,0xc1f0248018455114l,0xe05d8dcab1527931l, + 0x87818cf5bb1295d7l }, + 0 }, + /* 52 << 32 */ + { { 0x95aeb5bd483e333al,0x003af31effeaededl,0xfc5532e87efb1e4fl, + 0xb37e0fb52dfa24a5l }, + { 0x485d4cecdc140b08l,0xb81a0d23983bd787l,0xd19928dae8d489fdl, + 0x3fa0312c177b9dbdl }, + 0 }, + /* 53 << 32 */ + { { 0xade391470c6d7e88l,0x4fd1e8cd47072c45l,0x145760fed5a65c56l, + 0x198960c7be4887del }, + { 0xfe7974a82640257al,0xf838a19b774febefl,0xb2aecad11b6e988el, + 0x643f44fa448e4a8fl }, + 0 }, + /* 55 << 32 */ + { { 0xc35ceffdee756e71l,0x2c1364d88ea932c4l,0xbd594d8d837d2d9fl, + 0x5b334bdac9d74d48l }, + { 0x72dc3e03b8fac08bl,0x38f01de006fdf70fl,0x4bde74b31d298ba4l, + 0x2598d183ad5f42a9l }, + 0 }, + /* 57 << 32 */ + { { 0x02c6ba15f62befa2l,0x6399ceb55c8ccee9l,0x3638bd6e08d3473el, + 0xb8f1f13d2f8f4a9cl }, + { 0x50d7560655827a74l,0x8d6e65f33fb4f32cl,0x40a5d21189ee621al, + 0x6d3f9e11c4474716l }, + 0 }, + /* 59 << 32 */ + { { 0xcb633a4ce9b2bb8fl,0x0475703f8c529253l,0x61e007b5a8878873l, + 0x342d77ba14504159l }, + { 0x2925175c313578dfl,0x4e631897b6b097f1l,0xe64d138929350e41l, + 0x2fb20608ec7adccdl }, + 0 }, + /* 60 << 32 */ + { { 0xa560c234d5c0f5d1l,0x74f84bf62bdef0efl,0x61ed00005cbd3d0bl, + 0xc74262d087fb408bl }, + { 0xad30a6496cc64128l,0x708e3a31a4a8b154l,0xaf21ce2637f82074l, + 0x31d33b38204c9a74l }, + 0 }, + /* 61 << 32 */ + { { 0x8f609fe04cc2f575l,0xe44f9784b35488c4l,0x0d464bb6180fa375l, + 0x4f44d5d2de2247b8l }, + { 0xf538eb38141ef077l,0x781f8f6e8fa456a4l,0x67e9a46429b4f39dl, + 0x245d21e8b704c3e9l }, + 0 }, + /* 63 << 32 */ + { { 0x45a94ee858ffa7cdl,0x4d38bc6818053549l,0x0b4bc65a499d79f3l, + 0xa81e3ab09159cab7l }, + { 0xf13716efb47898cel,0xb7ee597c2e2d9044l,0x09396b90e6158276l, + 0x5c644dc36a533fcel }, + 0 }, + /* 64 << 32 */ + { { 0xcca4428dbbe5a1a9l,0x8187fd5f3126bd67l,0x0036973a48105826l, + 0xa39b6663b8bd61a0l }, + { 0x6d42deef2d65a808l,0x4969044f94636b19l,0xf611ee47dd5d564cl, + 0x7b2f3a49d2873077l }, + 0 }, + /* 65 << 32 */ + { { 0xbe4c16c3bf429668l,0xd32f56f0ef35db3bl,0xae8355de9ea4e3f1l, + 0x8f66c4a2a450944el }, + { 0xafab94c8b798fbe2l,0x18c57baff7f3d5cfl,0x692d191c5cfa5c7dl, + 0xc0c25f69a689daebl }, + 0 }, + /* 71 << 32 */ + { { 0x15fb3ae398340d4cl,0xa8b9233a7de82134l,0x44971a545fc0dbc6l, + 0xb2b4f0f3a1d3f094l }, + { 0x8d9eaba1b6242bd4l,0xd8aad777787cc557l,0xb1ab8b7870d1a2bbl, + 0x5d20f48cead3bfe3l }, + 0 }, + /* 77 << 32 */ + { { 0x4dacbf09a2bf9772l,0x969a4c4357aa8457l,0xadbe673b273ebfc5l, + 0xb85582bb927778c9l }, + { 0x748371855c03752cl,0xc337bc6bc2f60d11l,0x2c3838e4ad456a09l, + 0xaf479c897e381842l }, + 0 }, + /* 83 << 32 */ + { { 0x8530ae751b1aea77l,0xf43b923ba8310cb9l,0x9c1a60c6bf4dd6c5l, + 0x11885b863e3aaaa5l }, + { 0x594a8fa90f69821el,0x1eece3d66bc37998l,0x1fd718f518df32bfl, + 0x1c00c7d461d84082l }, + 0 }, + /* 89 << 32 */ + { { 0xd67ee3a4c763c3cfl,0x760b128305969234l,0x1a5ff331ec17f2d1l, + 0x25f0392a84fecfefl }, + { 0xb1bc004a3a80d47el,0xf450bf08182fee3bl,0xf11117681e19751el, + 0x5b4127dae28ed23fl }, + 0 }, + /* 95 << 32 */ + { { 0x91e00defdaf08f09l,0x7ef41724f4738a07l,0x990fbbceaf1263fcl, + 0x779121e3e6eeb5aal }, + { 0x3e162c7a5a3ecf52l,0x73ae568a51be5faal,0x8bea1bfa451be8a9l, + 0x3e8cd5db90e11097l }, + 0 }, + /* 101 << 32 */ + { { 0x90390f7224d27159l,0x685c139efd07e5d4l,0x4e21e44a3bc234a8l, + 0x61b50f34eeb14dacl }, + { 0x7beb0aa087555d58l,0x781326bcc806f0d2l,0xc289537a1eb7199fl, + 0x44a31a037b42766el }, + 0 }, + /* 107 << 32 */ + { { 0x7d778206edde4b40l,0x34539fa18eb92fcdl,0x5a0bdd79bf52a552l, + 0x066d3672fdcca75el }, + { 0xd73fa893e28b5a5bl,0xb495135876c38698l,0x44469b0114ae16cfl, + 0xb428c763691d6618l }, + 0 }, + /* 113 << 32 */ + { { 0x9022db8b69196353l,0x152ebb7dd7a4afd0l,0xea36fae57fcf1765l, + 0xa8fc00ba0decea8al }, + { 0x1047206a0c0b0414l,0x6607d8ade076df28l,0xf343e19966b8aba1l, + 0x7f03c1ad311e208dl }, + 0 }, + /* 116 << 32 */ + { { 0xe6b4c96e888f3870l,0xa21bb618fe544042l,0x7122ee88bd817699l, + 0xcb38ecebfa66e173l }, + { 0x6ed5b3482c9cc05fl,0x591affc84ae0fd9el,0x7cf325ac6e7aaac0l, + 0x2397c053d05e5be0l }, + 0 }, + /* 119 << 32 */ + { { 0x95363f61eaa96552l,0xe03bc6b38fb15b73l,0xa5c5808f2c389053l, + 0xcd021e6c11b2030cl }, + { 0x349ca9bdc038e30al,0x0a3368d4165afa2cl,0x043630debbfa1cc6l, + 0xb8c4456ba7cdbf69l }, + 0 }, + /* 125 << 32 */ + { { 0x63aa3315fd7d2983l,0xaf4c96afa6a04bedl,0x3a5c0b5410814a74l, + 0x9906f5e30f9b0770l }, + { 0x622be6523676986fl,0x09ac5bc0173e7cb5l,0x1c40e56a502c8b3cl, + 0xabb9a0f7253ce8f6l }, + 0 }, + }, + { + /* 0 << 40 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 40 */ + { { 0x889f6d65533ef217l,0x7158c7e4c3ca2e87l,0xfb670dfbdc2b4167l, + 0x75910a01844c257fl }, + { 0xf336bf07cf88577dl,0x22245250e45e2acel,0x2ed92e8d7ca23d85l, + 0x29f8be4c2b812f58l }, + 0 }, + /* 3 << 40 */ + { { 0xc51e414351facc61l,0xbaf2647de68a25bcl,0x8f5271a00ff872edl, + 0x8f32ef993d2d9659l }, + { 0xca12488c7593cbd4l,0xed266c5d02b82fabl,0x0a2f78ad14eb3f16l, + 0xc34049484d47afe3l }, + 0 }, + /* 4 << 40 */ + { { 0xa6f3d574c005979dl,0xc2072b426a40e350l,0xfca5c1568de2ecf9l, + 0xa8c8bf5ba515344el }, + { 0x97aee555114df14al,0xd4374a4dfdc5ec6bl,0x754cc28f2ca85418l, + 0x71cb9e27d3c41f78l }, + 0 }, + /* 5 << 40 */ + { { 0x09c1670209470496l,0xa489a5edebd23815l,0xc4dde4648edd4398l, + 0x3ca7b94a80111696l }, + { 0x3c385d682ad636a4l,0x6702702508dc5f1el,0x0c1965deafa21943l, + 0x18666e16610be69el }, + 0 }, + /* 7 << 40 */ + { { 0x45beb4ca2a604b3bl,0x56f651843a616762l,0xf52f5a70978b806el, + 0x7aa3978711dc4480l }, + { 0xe13fac2a0e01fabcl,0x7c6ee8a5237d99f9l,0x251384ee05211ffel, + 0x4ff6976d1bc9d3ebl }, + 0 }, + /* 9 << 40 */ + { { 0xdde0492316e043a2l,0x98a452611dd3d209l,0xeaf9f61bd431ebe8l, + 0x00919f4dbaf56abdl }, + { 0xe42417db6d8774b1l,0x5fc5279c58e0e309l,0x64aa40613adf81eal, + 0xef419edabc627c7fl }, + 0 }, + /* 10 << 40 */ + { { 0x3919759239ef620fl,0x9d47284074fa29c4l,0x4e428fa39d416d83l, + 0xd1a7c25129f30269l }, + { 0x46076e1cd746218fl,0xf3ad6ee8110d967el,0xfbb5f434a00ae61fl, + 0x3cd2c01980d4c929l }, + 0 }, + /* 11 << 40 */ + { { 0xfa24d0537a4af00fl,0x3f938926ca294614l,0x0d700c183982182el, + 0x801334434cc59947l }, + { 0xf0397106ec87c925l,0x62bd59fc0ed6665cl,0xe8414348c7cca8b5l, + 0x574c76209f9f0a30l }, + 0 }, + /* 13 << 40 */ + { { 0x95be42e2bb8b6a07l,0x64be74eeca23f86al,0xa73d74fd154ce470l, + 0x1c2d2857d8dc076al }, + { 0xb1fa1c575a887868l,0x38df8e0b3de64818l,0xd88e52f9c34e8967l, + 0x274b4f018b4cc76cl }, + 0 }, + /* 15 << 40 */ + { { 0x3f5c05b4f8b7559dl,0x0be4c7acfae29200l,0xdd6d3ef756532accl, + 0xf6c3ed87eea7a285l }, + { 0xe463b0a8f46ec59bl,0x531d9b14ecea6c83l,0x3d6bdbafc2dc836bl, + 0x3ee501e92ab27f0bl }, + 0 }, + /* 16 << 40 */ + { { 0x8df275455922ac1cl,0xa7b3ef5ca52b3f63l,0x8e77b21471de57c4l, + 0x31682c10834c008bl }, + { 0xc76824f04bd55d31l,0xb6d1c08617b61c71l,0x31db0903c2a5089dl, + 0x9c092172184e5d3fl }, + 0 }, + /* 17 << 40 */ + { { 0x7b1a921ea6b3340bl,0x6d7c4d7d7438a53el,0x2b9ef73c5bf71d8fl, + 0xb5f6e0182b167a7cl }, + { 0x5ada98ab0ce536a3l,0xee0f16f9e1fea850l,0xf6424e9d74f1c0c5l, + 0x4d00de0cd3d10b41l }, + 0 }, + /* 19 << 40 */ + { { 0xd542f522a6533610l,0xfdde15a734ec439al,0x696560fedc87dd0dl, + 0x69eab421e01fd05fl }, + { 0xca4febdc95cc5988l,0x839be396c44d92fbl,0x7bedff6daffe543bl, + 0xd2bb97296f6da43al }, + 0 }, + /* 21 << 40 */ + { { 0x5bc6dea80b8d0077l,0xb2adf5d1ea9c49efl,0x7104c20eaafe8659l, + 0x1e3604f37866ee7el }, + { 0x0cfc7e7b3075c8c5l,0x5281d9bb639c5a2bl,0xcbdf42494bc44ee3l, + 0x835ab066655e9209l }, + 0 }, + /* 23 << 40 */ + { { 0x78fbda4b90b94ffal,0x447e52eb7beb993cl,0x920011bc92620d15l, + 0x7bad6ecf481fd396l }, + { 0xad3bd28ba989a09el,0x20491784a3e62b78l,0xcdcd7096b07bd9efl, + 0x9bf5bb7337d780adl }, + 0 }, + /* 25 << 40 */ + { { 0xbe911a71a976c8d4l,0xba0346743fdd778el,0x2359e7434cf87ea1l, + 0x8dccf65f07ebb691l }, + { 0x6c2c18eb09746d87l,0x6a19945fd2ecc8fal,0xc67121ff2ffa0339l, + 0x408c95ba9bd9fc31l }, + 0 }, + /* 27 << 40 */ + { { 0xa317204bcaa5da39l,0xd390df7468bf53d7l,0x56de18b2dbd71c0dl, + 0xcb4d3bee75184779l }, + { 0x815a219499d920a5l,0x9e10fb4ecf3d3a64l,0x7fd4901dfe92e1eel, + 0x5d86d10d3ab87b2el }, + 0 }, + /* 28 << 40 */ + { { 0x24f2a692840bb336l,0x7c353bdca669fa7bl,0xda20d6fcdec9c300l, + 0x625fbe2fa13a4f17l }, + { 0xa2b1b61adbc17328l,0x008965bfa9515621l,0x49690939c620ff46l, + 0x182dd27d8717e91cl }, + 0 }, + /* 29 << 40 */ + { { 0x98e9136c878303e4l,0x2769e74fd1e65efdl,0x6154c545809da56el, + 0x8c5d50a04301638cl }, + { 0x10f3d2068214b763l,0x2da9a2fc44df0644l,0xca912bab588a6fcdl, + 0xe9e82d9b227e1932l }, + 0 }, + /* 31 << 40 */ + { { 0xcbdc4d66d080e55bl,0xad3f11e5b8f98d6bl,0x31bea68e18a32480l, + 0xdf1c6fd52c1bcf6el }, + { 0xadcda7ee118a3f39l,0xbd02f857ac060d5fl,0xd2d0265d86631997l, + 0xb866a7d33818f2d4l }, + 0 }, + /* 33 << 40 */ + { { 0xfbcce2d31892d98dl,0x2e34bc9507de73dcl,0x3a48d1a94891eec1l, + 0xe64499c24d31060bl }, + { 0xe9674b7149745520l,0xf126ccaca6594a2cl,0x33e5c1a079945342l, + 0x02aa0629066e061fl }, + 0 }, + /* 34 << 40 */ + { { 0xdfd7c0ae7af3191el,0x923ec111d68c70d9l,0xb6f1380bb675f013l, + 0x9192a224f23d45bal }, + { 0xbe7890f9524891e3l,0x45b24c47eba996bbl,0x59331e48320447e9l, + 0x0e4d8753ac9afad4l }, + 0 }, + /* 35 << 40 */ + { { 0x49e49c38c9f5a6c3l,0x3f5eea44d8ee2a65l,0x02bf3e761c74bbb4l, + 0x50d291cdef565571l }, + { 0xf4edc290a36dd5fal,0x3015df9556dd6b85l,0x4494926aa5549a16l, + 0x5de6c59390399e4al }, + 0 }, + /* 36 << 40 */ + { { 0x29be11c6ce800998l,0x72bb1752b90360d9l,0x2c1931975a4ad590l, + 0x2ba2f5489fc1dbc0l }, + { 0x7fe4eebbe490ebe0l,0x12a0a4cd7fae11c0l,0x7197cf81e903ba37l, + 0xcf7d4aa8de1c6dd8l }, + 0 }, + /* 37 << 40 */ + { { 0x961fa6317e249e7bl,0x5c4f707796caed50l,0x6b176e62d7e50885l, + 0x4dd5de72f390cbecl }, + { 0x91fa29954b2bd762l,0x80427e6395b8dadel,0xd565bf1de2c34743l, + 0x911da39d16e6c841l }, + 0 }, + /* 39 << 40 */ + { { 0x48365465802ff016l,0x6d2a561f71beece6l,0xdd299ce6f9707052l, + 0x62a32698a23407bbl }, + { 0x1d55bdb147004afbl,0xfadec124369b1084l,0x1ce78adf291c89f7l, + 0x9f2eaf03278bc529l }, + 0 }, + /* 40 << 40 */ + { { 0x92af6bf43fd5684cl,0x2b26eecf80360aa1l,0xbd960f3000546a82l, + 0x407b3c43f59ad8fel }, + { 0x86cae5fe249c82bal,0x9e0faec72463744cl,0x87f551e894916272l, + 0x033f93446ceb0615l }, + 0 }, + /* 41 << 40 */ + { { 0x04658ad212dba0cel,0x9e600624068822f0l,0x84661f11b26d368bl, + 0xbca867d894ebb87al }, + { 0x79506dc42f1bad89l,0x1a8322d3ebcbe7a1l,0xb4f1e102ac197178l, + 0x29a950b779f7198cl }, + 0 }, + /* 43 << 40 */ + { { 0x19a6fb0984a3d1d5l,0x6c75c3a2ba5f5307l,0x7983485bf9698447l, + 0x689f41b88b1cdc1el }, + { 0x18f6fbd74c1979d0l,0x3e6be9a27a0b6708l,0x06acb615f63d5a8al, + 0x8a817c098d0f64b1l }, + 0 }, + /* 44 << 40 */ + { { 0x1e5eb0d18be82e84l,0x89967f0e7a582fefl,0xbcf687d5a6e921fal, + 0xdfee4cf3d37a09bal }, + { 0x94f06965b493c465l,0x638b9a1c7635c030l,0x7666786466f05e9fl, + 0xccaf6808c04da725l }, + 0 }, + /* 45 << 40 */ + { { 0xa9b3479b1b53a173l,0xc041eda3392eddc0l,0xdb8f804755edd7eel, + 0xaf1f7a37ab60683cl }, + { 0x9318603a72c0accbl,0xab1bb9fe401cbf3cl,0xc40e991e88afe245l, + 0x9298a4580d06ac35l }, + 0 }, + /* 46 << 40 */ + { { 0x58e127d5036c2fe7l,0x5fe5020555b93361l,0xc1373d850f74a045l, + 0x28cd79dbe8228e4bl }, + { 0x0ae82320c2018d9al,0xf6d0049c78f8016al,0x381b6fe2149b31fbl, + 0x33a0e8adec3cfbcfl }, + 0 }, + /* 47 << 40 */ + { { 0x23a6612e9eab5da7l,0xb645fe29d94d6431l,0xe3d74594ca1210c4l, + 0xdc1376bceeca0674l }, + { 0xfd40dfef657f0154l,0x7952a548d52cbac5l,0x0ee189583685ad28l, + 0xd13639409ba9ca46l }, + 0 }, + /* 48 << 40 */ + { { 0xca2eb690768fccfcl,0xf402d37db835b362l,0x0efac0d0e2fdfccel, + 0xefc9cdefb638d990l }, + { 0x2af12b72d1669a8bl,0x33c536bc5774ccbdl,0x30b21909fb34870el, + 0xc38fa2f77df25acal }, + 0 }, + /* 49 << 40 */ + { { 0x1337902f1c982cd6l,0x222e08fe14ec53eal,0x6c8abd0d330ef3e5l, + 0xeb59e01531f6fd9dl }, + { 0xd74ae554a8532df4l,0xbc010db1ab44c83el,0xe98016561b8f9285l, + 0x65a9612783acc546l }, + 0 }, + /* 51 << 40 */ + { { 0x36a8b0a76770cfb1l,0x3338d52f9bb578fcl,0x5136c785f5ed12a4l, + 0x652d47ed87bf129el }, + { 0x9c6c827e6067c2d0l,0x61fc2f410345533al,0x2d7fb182130cea19l, + 0x71a0186330b3ef85l }, + 0 }, + /* 52 << 40 */ + { { 0x74c5f02bbf81f3f5l,0x0525a5aeaf7e4581l,0x88d2aaba433c54ael, + 0xed9775db806a56c5l }, + { 0xd320738ac0edb37dl,0x25fdb6ee66cc1f51l,0xac661d1710600d76l, + 0x931ec1f3bdd1ed76l }, + 0 }, + /* 53 << 40 */ + { { 0xb81e239161faa569l,0xb379f759bb40eebfl,0x9f2fd1b2a2c54549l, + 0x0a968f4b0d6ba0ael }, + { 0xaa869e6eedfe8c75l,0x0e36b298645ab173l,0x5a76282b0bcdefd7l, + 0x9e949331d05293f2l }, + 0 }, + /* 55 << 40 */ + { { 0xc1cfa9a1c59fac6el,0x2648bffcb72747cel,0x5f8a39805f2e2637l, + 0x8bd3a8eb73e65758l }, + { 0xd9c43f1df14381a7l,0xecc1c3b0d6a86c10l,0xffcf4fa8a4a6dc74l, + 0x7304fa834cea0a46l }, + 0 }, + /* 57 << 40 */ + { { 0x4460760c34dca952l,0xeac9cf2444c70444l,0xb879297b8493c87el, + 0x295941a54b2dccb7l }, + { 0x1e5cecede58721cdl,0xc8b58db74ca0d12bl,0x1927965c6da1d034l, + 0x7220b02839ed1369l }, + 0 }, + /* 59 << 40 */ + { { 0xc38746c83c2e34b6l,0x9f27362e38a51042l,0x26febec02067afebl, + 0xd9c4e15544e7371fl }, + { 0x6035f469f92930d1l,0xe6ed7c08b4431b8bl,0xa25bf5903e16410dl, + 0x147d83368adf4c18l }, + 0 }, + /* 60 << 40 */ + { { 0x7f01c9ecaa80ba59l,0x3083411a68538e51l,0x970370f1e88128afl, + 0x625cc3db91dec14bl }, + { 0xfef9666c01ac3107l,0xb2a8d577d5057ac3l,0xb0f2629992be5df7l, + 0xf579c8e500353924l }, + 0 }, + /* 61 << 40 */ + { { 0xbd9398d6ca02669fl,0x896e053bf9ad11a1l,0xe024b699a3556f9fl, + 0x23b4b96ad53cbca3l }, + { 0x549d2d6c89733dd6l,0x3dae193f394f3179l,0x8bf7ec1cdfeda825l, + 0xf6a1db7a8a4844b4l }, + 0 }, + /* 63 << 40 */ + { { 0x3b5403d56437a027l,0xda32bbd233ed30aal,0xd2ad3baa906de0cal, + 0x3b6df514533f736el }, + { 0x986f1cab5df9b9c4l,0x41cd2088970d330el,0xaae7c2238c20a923l, + 0x52760a6e1e951dc0l }, + 0 }, + /* 64 << 40 */ + { { 0xb8fa3d931341ed7al,0x4223272ca7b59d49l,0x3dcb194783b8c4a4l, + 0x4e413c01ed1302e4l }, + { 0x6d999127e17e44cel,0xee86bf7533b3adfbl,0xf6902fe625aa96cal, + 0xb73540e4e5aae47dl }, + 0 }, + /* 65 << 40 */ + { { 0x55318a525e34036cl,0xc3acafaaf9884e3fl,0xe5ba15cea042ba04l, + 0x56a1d8960ada550el }, + { 0xa5198cae87b76764l,0xd079d1f0b6fd84fbl,0xb22b637bcbe363edl, + 0xbe8ab7d64499deaal }, + 0 }, + /* 71 << 40 */ + { { 0xbe8eba5eb4925f25l,0x00f8bf582e3159d6l,0xb1aa24fa18856070l, + 0x22ea8b74e4c30b22l }, + { 0x512f633e55bbe4e8l,0x82ba62318678aee9l,0xea05da90fdf72b7el, + 0x616b9bc7a4fc65eel }, + 0 }, + /* 77 << 40 */ + { { 0xe31ee3b3b7c221e7l,0x10353824e353fa43l,0x9d2f3df69dd2a86fl, + 0x8a12ab9322ccffecl }, + { 0x25c8e326d666f9e5l,0x33ea98a0598da7fbl,0x2fc1de0917f74e17l, + 0x0d0b6c7a35efb211l }, + 0 }, + /* 83 << 40 */ + { { 0x22a82c6c804e6ecel,0x824a170b1d8fce9el,0x621802becee65ed0l, + 0x4a4e9e7895ec4285l }, + { 0x8da0988fa8940b7al,0xaff89c5b86445aa5l,0x386fdbdad689cde9l, + 0x3aeaae7d9f5caaccl }, + 0 }, + /* 89 << 40 */ + { { 0xe9cb9e68a7b62f4cl,0x515cae0ec3b7092el,0xb8abec354b491f52l, + 0x672673fd01eeabc1l }, + { 0x65e5739f7ad6e8a1l,0xc2da8e003d91b2f9l,0xcc43229cced84319l, + 0x0f8cbf9574ccf2d1l }, + 0 }, + /* 95 << 40 */ + { { 0xb03d1cfb1b2f872al,0x88aef4670872b6f7l,0xaafe55e48ea9170cl, + 0xd5cc4875f24aa689l }, + { 0x7e5732908458ce84l,0xef4e143d58bfc16dl,0xc58626efaa222836l, + 0x01c60ec0ca5e0cb8l }, + 0 }, + /* 101 << 40 */ + { { 0x123901aa36337c09l,0x1697acadd2f5e675l,0xc0a1ddd022fe2bael, + 0xf68ea88cff0210ddl }, + { 0x665d11e014168709l,0x912a575f45f25321l,0x7e7ed38070c78934l, + 0x663d692cb0a46322l }, + 0 }, + /* 107 << 40 */ + { { 0x912ab8bd8642cba4l,0x97fab1a3b6b50b73l,0x76666b3cb86ef354l, + 0x16d41330fa5ecce9l }, + { 0x77c7c138c7da404bl,0xc6508cb78c983fb0l,0xe5881733f9004984l, + 0x76dea7794182c7abl }, + 0 }, + /* 113 << 40 */ + { { 0x16db18583556b765l,0x39c18c200263755al,0x7b6691f591c15201l, + 0x4e4c17b168514ea9l }, + { 0xacbe449e06f5f20al,0xeb9119d2541ddfb6l,0x2f6e687bf2eac86fl, + 0xb161471ec14ac508l }, + 0 }, + /* 116 << 40 */ + { { 0x58846d32c4744733l,0x40517c71379f9e34l,0x2f65655f130ef6cal, + 0x526e4488f1f3503fl }, + { 0x8467bd177ee4a976l,0x1d9dc913921363d1l,0xd8d24c33b069e041l, + 0x5eb5da0a2cdf7f51l }, + 0 }, + /* 119 << 40 */ + { { 0x81c2cc32951ab3e7l,0xc86d9a109b0c7e87l,0x0b7a18bd606ef408l, + 0x099b5bbfe6c2251el }, + { 0x46d627d0bfce880fl,0xbfaddcbbe1c6865al,0xa9ab6183d2bb9a00l, + 0x23cb9a2720ad9789l }, + 0 }, + /* 125 << 40 */ + { { 0x1592d0630c25fbebl,0x13869ec24995a3fal,0x6413f494861d0a73l, + 0xa3b782342f9f1b89l }, + { 0x113689e2b6cad351l,0x53be2014a873dcc1l,0xccf405e0c6bb1be7l, + 0x4fff7b4ca9061ca9l }, + 0 }, + }, + { + /* 0 << 48 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 48 */ + { { 0xcc7a64880a750c0fl,0x39bacfe34e548e83l,0x3d418c760c110f05l, + 0x3e4daa4cb1f11588l }, + { 0x2733e7b55ffc69ffl,0x46f147bc92053127l,0x885b2434d722df94l, + 0x6a444f65e6fc6b7cl }, + 0 }, + /* 3 << 48 */ + { { 0x6d0b16f4bdaedfbdl,0x23fd326086746cedl,0x8bfb1d2fff4b3e17l, + 0xc7f2ec2d019c14c8l }, + { 0x3e0832f245104b0dl,0x5f00dafbadea2b7el,0x29e5cf6699fbfb0fl, + 0x264f972361827cdal }, + 0 }, + /* 4 << 48 */ + { { 0x97b14f7ea90567e6l,0x513257b7b6ae5cb7l,0x85454a3c9f10903dl, + 0xd8d2c9ad69bc3724l }, + { 0x38da93246b29cb44l,0xb540a21d77c8cbacl,0x9bbfe43501918e42l, + 0xfffa707a56c3614el }, + 0 }, + /* 5 << 48 */ + { { 0x6eb1a2f3e30bc27fl,0xe5f0c05ab0836511l,0x4d741bbf4965ab0el, + 0xfeec41ca83464bbdl }, + { 0x1aca705f99d0b09fl,0xc5d6cc56f42da5fal,0x49964eddcc52b931l, + 0x8ae59615c884d8d8l }, + 0 }, + /* 7 << 48 */ + { { 0xf634b57b39f8868al,0xe27f4fd475cc69afl,0xa47e58cbd0d5496el, + 0x8a26793fd323e07fl }, + { 0xc61a9b72fa30f349l,0x94c9d9c9b696d134l,0x792beca85880a6d1l, + 0xbdcc4645af039995l }, + 0 }, + /* 9 << 48 */ + { { 0xce7ef8e58c796c3cl,0x9adaae84dd66e57al,0x784ae13e45227f33l, + 0xb046c5b82a85e757l }, + { 0xb7aa50aeec37631fl,0xbedc4fca3b300758l,0x0f82567e0ac9700bl, + 0x1071d9d44ff5f8d2l }, + 0 }, + /* 10 << 48 */ + { { 0x61360ee99e240d18l,0x057cdcacb4b94466l,0xe7667cd12fe5325cl, + 0x1fa297b521974e3bl }, + { 0xfa4081e7db083d76l,0x31993be6f206bd15l,0x8949269b14c19f8cl, + 0x21468d72a9d92357l }, + 0 }, + /* 11 << 48 */ + { { 0xd09ef6c4e51a2811l,0x39f6862bb8fb66b9l,0x64e77f8d22dfaa99l, + 0x7b10504461b08aacl }, + { 0x71704e4c4a7df332l,0xd09734342ffe015bl,0xab0eaf4408d3020el, + 0x28b1909eed63b97al }, + 0 }, + /* 13 << 48 */ + { { 0x2f3fa882cdadcd4fl,0xa4ef68595f631995l,0xe52ca2f9e531766fl, + 0x20af5c3057e2c1d3l }, + { 0x1e4828f6e51e94b8l,0xf900a1751a2f5d4fl,0xe831adb3392c58a0l, + 0x4c5a90ca1b6e5866l }, + 0 }, + /* 15 << 48 */ + { { 0x5f3dcba86182827cl,0xd1a448ddbd7e7252l,0x2d8f96fcf493b815l, + 0xba0a4c263b0aa95fl }, + { 0x88a1514063a0007fl,0x9564c25e6a9c5846l,0x5a4d7b0fdc0fcbcal, + 0x2275daa33f8a740el }, + 0 }, + /* 16 << 48 */ + { { 0x83f49167ceca9754l,0x426d2cf64b7939a0l,0x2555e355723fd0bfl, + 0xa96e6d06c4f144e2l }, + { 0x4768a8dd87880e61l,0x15543815e508e4d5l,0x09d7e772b1b65e15l, + 0x63439dd6ac302fa0l }, + 0 }, + /* 17 << 48 */ + { { 0x159591cc0461086bl,0xb695aa9495e66e51l,0x2d4c946779ded531l, + 0xbd2482ba89c2be79l }, + { 0x8ee2658aa20bbf19l,0xc000528a32247917l,0xd924be4affeae845l, + 0x51312bebed992c8bl }, + 0 }, + /* 19 << 48 */ + { { 0x3a01b958dc752bd9l,0x2babdbc20c215d45l,0xe689d79a131641c1l, + 0x48e8f0da80e05ed4l }, + { 0x4b505feb77bb70c4l,0xefbd3e2bb6057ef7l,0x7583e22dce603ca5l, + 0xfbe3b1f22c5c70c7l }, + 0 }, + /* 21 << 48 */ + { { 0x8ec1ecf029e5e35al,0x2f3168e58645c2b3l,0xe9297362c7f94cb2l, + 0x4fbf1466d1c90b39l }, + { 0x3e4f7656920bae2al,0x805d04b9f1beb172l,0x729a7208dbdbd4b4l, + 0x1aade45687aeca53l }, + 0 }, + /* 23 << 48 */ + { { 0xb0ff1f541934a508l,0x19e1397604bbf31al,0xb2a8e6033717a6b4l, + 0xd601e45d0ef12cb9l }, + { 0x563f0af5b515e98el,0x9b129db633984f9bl,0xe34aba2fa47e4a65l, + 0xb56f82d19e3f9d82l }, + 0 }, + /* 25 << 48 */ + { { 0x0203effdb1209b86l,0x21f063edb19d6cbfl,0x59f53476980f275bl, + 0x202456d7b7ac5e80l }, + { 0xe5a8c05f4900edc9l,0x04c08eb470f01e86l,0xf74ac2241dcd98cel, + 0x7e77cc0ce2e830dbl }, + 0 }, + /* 27 << 48 */ + { { 0x74e37234a9747edel,0x4fc9fbb1361b1013l,0xe7b533733cf357efl, + 0x6aa2dd2c991c4193l }, + { 0x7887e4d2a770917al,0xdd1809b4c20d24cbl,0x004cd7c38e9c2d3el, + 0xc77c5baba9970abel }, + 0 }, + /* 28 << 48 */ + { { 0x20ac0351d598d710l,0x272c4166cb3a4da4l,0xdb82fe1aca71de1fl, + 0x746e79f2d8f54b0fl }, + { 0x6e7fc7364b573e9bl,0x75d03f46fd4b5040l,0x5c1cc36d0b98d87bl, + 0x513ba3f11f472da1l }, + 0 }, + /* 29 << 48 */ + { { 0x52927eaac3af237fl,0xfaa06065d7398767l,0x042e72b497c6ce0bl, + 0xdaed0cc40a9f2361l }, + { 0xddc2e11c2fc1bb4al,0x631da5770c1a9ef8l,0x8a4cfe44680272bfl, + 0xc76b9f7262fb5cc3l }, + 0 }, + /* 31 << 48 */ + { { 0x248f814538b3aae3l,0xb5345864bc204334l,0x66d6b5bc1d127524l, + 0xe312080d14f572d3l }, + { 0x13ed15a716abafebl,0x6f18ce27dba967bel,0x96c9e826ef08552dl, + 0x2c191b06be2b63e0l }, + 0 }, + /* 33 << 48 */ + { { 0xde4be45dc115ca51l,0xa028cafe934dabd6l,0x7e875663d1c0f8c5l, + 0xa8e32ab063d17473l }, + { 0x33f55bd5543199aal,0x79d2c937a2071d6el,0xa6a6758ceff16f28l, + 0x9c5f93ef87d85201l }, + 0 }, + /* 34 << 48 */ + { { 0x7f2e440381e9ede3l,0x243c3894caf6df0al,0x7c605bb11c073b11l, + 0xcd06a541ba6a4a62l }, + { 0x2916894949d4e2e5l,0x33649d074af66880l,0xbfc0c885e9a85035l, + 0xb4e52113fc410f4bl }, + 0 }, + /* 35 << 48 */ + { { 0xe86f21bc3ad4c81el,0x53b408403a37dcebl,0xaa606087383402cdl, + 0xc248caf185452b1dl }, + { 0x38853772576b57cdl,0xe2798e5441b7a6edl,0x7c2f1eed95ef4a33l, + 0xccd7e776adb1873cl }, + 0 }, + /* 36 << 48 */ + { { 0xdca3b70678a6513bl,0x92ea4a2a9edb1943l,0x02642216db6e2dd8l, + 0x9b45d0b49fd57894l }, + { 0x114e70dbc69d11ael,0x1477dd194c57595fl,0xbc2208b4ec77c272l, + 0x95c5b4d7db68f59cl }, + 0 }, + /* 37 << 48 */ + { { 0xd978bb791c61030al,0xa47325d2218222f3l,0x65ad4d4832e67d97l, + 0x31e4ed632e0d162al }, + { 0x7308ea317f76da37l,0xcfdffe87d93f35d8l,0xf4b2d60ee6f96cc4l, + 0x8028f3bd0117c421l }, + 0 }, + /* 39 << 48 */ + { { 0x7df80cbb9543edb6l,0xa07a54df40b0b3bcl,0xacbd067cc1888488l, + 0x61ad61318a00c721l }, + { 0x67e7599ebe2e6fe6l,0x8349d568f7270e06l,0x5630aabc307bc0c7l, + 0x97210b3f71af442fl }, + 0 }, + /* 40 << 48 */ + { { 0xfe541fa47ea67c77l,0x952bd2afe3ea810cl,0x791fef568d01d374l, + 0xa3a1c6210f11336el }, + { 0x5ad0d5a9c7ec6d79l,0xff7038af3225c342l,0x003c6689bc69601bl, + 0x25059bc745e8747dl }, + 0 }, + /* 41 << 48 */ + { { 0x58bdabb7ef701b5fl,0x64f987aee00c3a96l,0x533b391e2d585679l, + 0x30ad79d97a862e03l }, + { 0xd941471e8177b261l,0x33f65cb856a9018el,0x985ce9f607759fc4l, + 0x9b085f33aefdbd9el }, + 0 }, + /* 43 << 48 */ + { { 0xab2fa51a9c43ee15l,0x457f338263f30575l,0xce8dcd863e75a6e0l, + 0x67a03ab86e70421al }, + { 0xe72c37893e174230l,0x45ffff6c066f4816l,0x3a3dd84879a2d4a7l, + 0xefa4b7e68b76c24cl }, + 0 }, + /* 44 << 48 */ + { { 0x9a75c80676cb2566l,0x8f76acb1b24892d9l,0x7ae7b9cc1f08fe45l, + 0x19ef73296a4907d8l }, + { 0x2db4ab715f228bf0l,0xf3cdea39817032d7l,0x0b1f482edcabe3c0l, + 0x3baf76b4bb86325cl }, + 0 }, + /* 45 << 48 */ + { { 0xd6be8f00e39e056al,0xb58f87a6232fa3bcl,0xd5cb09dc6b18c772l, + 0x3177256da8e7e17bl }, + { 0x1877fd34230bf92cl,0x6f9031175a36f632l,0x526a288728e2c9d9l, + 0xc373fc94415ec45cl }, + 0 }, + /* 46 << 48 */ + { { 0xd49065e010089465l,0x3bab5d298e77c596l,0x7636c3a6193dbd95l, + 0xdef5d294b246e499l }, + { 0xb22c58b9286b2475l,0xa0b93939cd80862bl,0x3002c83af0992388l, + 0x6de01f9beacbe14cl }, + 0 }, + /* 47 << 48 */ + { { 0x70fa6e2a2bf5e373l,0x501691739271694cl,0xd6ebb98c5d2ed9f1l, + 0x11fd0b3f225bf92dl }, + { 0x51ffbcea1e3d5520l,0xa7c549875513ad47l,0xe9689750b431d46dl, + 0x6e69fecbb620cb9al }, + 0 }, + /* 48 << 48 */ + { { 0x6aac688eadd70482l,0x708de92a7b4a4e8al,0x75b6dd73758a6eefl, + 0xea4bf352725b3c43l }, + { 0x10041f2c87912868l,0xb1b1be95ef09297al,0x19ae23c5a9f3860al, + 0xc4f0f839515dcf4bl }, + 0 }, + /* 49 << 48 */ + { { 0xf3c22398e04b5734l,0x4fba59b275f2579dl,0xbf95182d691901b3l, + 0x4c139534eb599496l }, + { 0xf3f821de33b77e8bl,0x66e580743785d42fl,0xe3ba3d5abdc89c2dl, + 0x7ee988bdd19f37b9l }, + 0 }, + /* 51 << 48 */ + { { 0xe9ba62ca2ee53eb0l,0x64295ae23401d7dal,0x70ed8be24e493580l, + 0x702caa624502732fl }, + { 0xb1f4e21278d0cedfl,0x130b114bdc97057bl,0x9c5d0bd3c38c77b5l, + 0xd9d641e18bad68e7l }, + 0 }, + /* 52 << 48 */ + { { 0xc71e27bf8538a5c6l,0x195c63dd89abff17l,0xfd3152851b71e3dal, + 0x9cbdfda7fa680fa0l }, + { 0x9db876ca849d7eabl,0xebe2764b3c273271l,0x663357e3f208dceal, + 0x8c5bd833565b1b70l }, + 0 }, + /* 53 << 48 */ + { { 0x7c2dea1d122aebd4l,0x090bee4a138c1e4dl,0x94a9ffe59e4aca6cl, + 0x8f3212ba5d405c7fl }, + { 0x6618185f180b5e85l,0x76298d46f455ab9fl,0x0c804076476b2d88l, + 0x45ea9d03d5a40b39l }, + 0 }, + /* 55 << 48 */ + { { 0xdf325ac76a2ed772l,0x35da47ccb0da2765l,0x94ce6f460bc9b166l, + 0xe0fc82fb5f7f3628l }, + { 0x2b26d588c055f576l,0xb9d37c97ec2bae98l,0xffbbead856908806l, + 0xa8c2df87437f4c84l }, + 0 }, + /* 57 << 48 */ + { { 0x47d11c3528430994l,0x0183df71cf13d9d3l,0x98604c89aa138fe5l, + 0xb1432e1c32c09aa1l }, + { 0xf19bc45d99bd5e34l,0xb198be72108e9b89l,0xee500ae9dacde648l, + 0x5936cf98746870a9l }, + 0 }, + /* 59 << 48 */ + { { 0x6d8efb98ed1d5a9bl,0x2e0b08e697f778fal,0xda728454dc5e0835l, + 0x2c28a45f8e3651c4l }, + { 0x667fab6f7ee77088l,0xd94429c8f29a94b4l,0xd83d594d9deea5b2l, + 0x2dc08ccbbea58080l }, + 0 }, + /* 60 << 48 */ + { { 0xba5514df3fd165e8l,0x499fd6a9061f8811l,0x72cd1fe0bfef9f00l, + 0x120a4bb979ad7e8al }, + { 0xf2ffd0955f4a5ac5l,0xcfd174f195a7a2f0l,0xd42301ba9d17baf1l, + 0xd2fa487a77f22089l }, + 0 }, + /* 61 << 48 */ + { { 0xfb5f53ba20a9a01el,0x3adb174fd20d6a9cl,0x6db8bb6d80e0f64fl, + 0x596e428df6a26f76l }, + { 0xbab1f846e6a4e362l,0x8bdb22af9b1becbdl,0x62b48335f31352adl, + 0xd72c26409634f727l }, + 0 }, + /* 63 << 48 */ + { { 0xaaa61cb22b1ec1c3l,0x3b5156722cb6f00el,0x67d1be0a8bf83f60l, + 0x88f1627aa4b804bcl }, + { 0xc52b11a7cdade2abl,0xa6a8b71a606a4e9dl,0x04e0e6697b900551l, + 0x35cfa33c8d5ad0d2l }, + 0 }, + /* 64 << 48 */ + { { 0xb93452381d531696l,0x57201c0088cdde69l,0xdde922519a86afc7l, + 0xe3043895bd35cea8l }, + { 0x7608c1e18555970dl,0x8267dfa92535935el,0xd4c60a57322ea38bl, + 0xe0bf7977804ef8b5l }, + 0 }, + /* 65 << 48 */ + { { 0x375ca189b60f0d5al,0xc9458cf949a78362l,0x61c1c5024262c03al, + 0x299353db4363d5bel }, + { 0xe3565124dac407fel,0x16ea66cd5b93c532l,0xe5c6aec2749df8e3l, + 0x59181317ce3ee4bfl }, + 0 }, + /* 71 << 48 */ + { { 0xd46ea34af41c2a3cl,0x9936184916545c98l,0xd7cb800ccf2498b4l, + 0xe71d088d9353fe87l }, + { 0x43443cbeae2e172cl,0x77131656ca905cb3l,0x76471fd1dce63594l, + 0x346b1d1738f5e264l }, + 0 }, + /* 77 << 48 */ + { { 0x22b1e639f6d0a419l,0x8bbb1fad7cea278cl,0xf07f6c01370cc86al, + 0x661bd027d39b837fl }, + { 0x042c7a69de606098l,0x93433b154e44eb12l,0x20f44ada88d8bfe8l, + 0xb44f66e64ccbfab6l }, + 0 }, + /* 83 << 48 */ + { { 0x1cc32158583d9745l,0x9306223cad1c2201l,0x76aa8d0995748039l, + 0x29425391707e9b59l }, + { 0x8501c0d4487cdf9el,0xbe08e89c205c5611l,0xa950400b04ccc48bl, + 0xb614b69b637e966bl }, + 0 }, + /* 89 << 48 */ + { { 0xd9c3c1238ffa5c4bl,0xc65765f7f3593988l,0x9a7e5d2728242119l, + 0x0ad27b5097ad7620l }, + { 0x154cc5eb413a8b23l,0xae93d8de7afa8254l,0x9ce5116cab9907b5l, + 0x9a163d78063103b9l }, + 0 }, + /* 95 << 48 */ + { { 0x5c4c299291086d2al,0x42c6ca9de8e2d951l,0xe67ecf93dd353f30l, + 0xba54557fe7167c2el }, + { 0x04a7eb2db734c779l,0x8f345605e300711al,0x4811c1ad67b27de6l, + 0xb7ac8e842731d5f0l }, + 0 }, + /* 101 << 48 */ + { { 0xee33a1d8e449ac46l,0x2500ba0aaaebfa2dl,0x8fb914ebc424eff4l, + 0x3a36545d3989255el }, + { 0xd24f2484761235e6l,0x2fc5d5ddd9b2c04bl,0x73660f86070ab0dbl, + 0x2e266d0479d20c7bl }, + 0 }, + /* 107 << 48 */ + { { 0x143752d5316d19a3l,0x56a55e01915497b8l,0x44ba4b2609a5fd15l, + 0xe4fc3e7fd9bee4eel }, + { 0x6f9d8609878a9f26l,0xdf36b5bd2ede7a20l,0x8e03e712a9a3e435l, + 0x4ced555b56546d33l }, + 0 }, + /* 113 << 48 */ + { { 0x89a6aaab0882717el,0x56a9736b43fa5153l,0xdb07dcc9d0e1fb1al, + 0xe7c986d34145e227l }, + { 0x57be66abb10dad51l,0xa47b964e4aa01ea7l,0xd851d9f36bb837cbl, + 0x9851ab3d652e13f7l }, + 0 }, + /* 116 << 48 */ + { { 0x22b88a805616ee30l,0xfb09548fe7ab1083l,0x8ad6ab0d511270cdl, + 0x61f6c57a6924d9abl }, + { 0xa0f7bf7290aecb08l,0x849f87c90df784a4l,0x27c79c15cfaf1d03l, + 0xbbf9f675c463facel }, + 0 }, + /* 119 << 48 */ + { { 0x65512fb716dd6ce1l,0xfa76ebc960d53b35l,0x31e5322e19ada3bel, + 0x7e259b75d0ccc3cdl }, + { 0xd36d03f0e025fd69l,0xbefab782eea9e5f3l,0x1569969dd09ce6a7l, + 0x2df5396178c385b0l }, + 0 }, + /* 125 << 48 */ + { { 0x4201652fce0ccac7l,0x12f8e93df1d29d2dl,0x6c2ac9b2220f00c1l, + 0x4ee6a685a850baa9l }, + { 0x2c2371f163ee8829l,0xddff16488f464433l,0xeab6cd8869a2c413l, + 0xcae34beb85e4c2a8l }, + 0 }, + }, + { + /* 0 << 56 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 56 */ + { { 0xc7913e91991724f3l,0x5eda799c39cbd686l,0xddb595c763d4fc1el, + 0x6b63b80bac4fed54l }, + { 0x6ea0fc697e5fb516l,0x737708bad0f1c964l,0x9628745f11a92ca5l, + 0x61f379589a86967al }, + 0 }, + /* 3 << 56 */ + { { 0x46a8c4180d738dedl,0x6f1a5bb0e0de5729l,0xf10230b98ba81675l, + 0x32c6f30c112b33d4l }, + { 0x7559129dd8fffb62l,0x6a281b47b459bf05l,0x77c1bd3afa3b6776l, + 0x0709b3807829973al }, + 0 }, + /* 4 << 56 */ + { { 0x8c26b232a3326505l,0x38d69272ee1d41bfl,0x0459453effe32afal, + 0xce8143ad7cb3ea87l }, + { 0x932ec1fa7e6ab666l,0x6cd2d23022286264l,0x459a46fe6736f8edl, + 0x50bf0d009eca85bbl }, + 0 }, + /* 5 << 56 */ + { { 0x0b825852877a21ecl,0x300414a70f537a94l,0x3f1cba4021a9a6a2l, + 0x50824eee76943c00l }, + { 0xa0dbfcecf83cba5dl,0xf953814893b4f3c0l,0x6174416248f24dd7l, + 0x5322d64de4fb09ddl }, + 0 }, + /* 7 << 56 */ + { { 0xa337c447f1f0ced1l,0x800cc7939492dd2bl,0x4b93151dbea08efal, + 0x820cf3f8de0a741el }, + { 0xff1982dc1c0f7d13l,0xef92196084dde6cal,0x1ad7d97245f96ee3l, + 0x319c8dbe29dea0c7l }, + 0 }, + /* 9 << 56 */ + { { 0x0ae1d63b0eb919b0l,0xd74ee51da74b9620l,0x395458d0a674290cl, + 0x324c930f4620a510l }, + { 0x2d1f4d19fbac27d4l,0x4086e8ca9bedeeacl,0x0cdd211b9b679ab8l, + 0x5970167d7090fec4l }, + 0 }, + /* 10 << 56 */ + { { 0x3420f2c9faf1fc63l,0x616d333a328c8bb4l,0x7d65364c57f1fe4al, + 0x9343e87755e5c73al }, + { 0x5795176be970e78cl,0xa36ccebf60533627l,0xfc7c738009cdfc1bl, + 0xb39a2afeb3fec326l }, + 0 }, + /* 11 << 56 */ + { { 0xb7ff1ba16224408al,0xcc856e92247cfc5el,0x01f102e7c18bc493l, + 0x4613ab742091c727l }, + { 0xaa25e89cc420bf2bl,0x00a5317690337ec2l,0xd2be9f437d025fc7l, + 0x3316fb856e6fe3dcl }, + 0 }, + /* 13 << 56 */ + { { 0x67332cfc2064cfd1l,0x339c31deb0651934l,0x719b28d52a3bcbeal, + 0xee74c82b9d6ae5c6l }, + { 0x0927d05ebaf28ee6l,0x82cecf2c9d719028l,0x0b0d353eddb30289l, + 0xfe4bb977fddb2e29l }, + 0 }, + /* 15 << 56 */ + { { 0xe10b2ab817a91cael,0xb89aab6508e27f63l,0x7b3074a7dba3ddf9l, + 0x1c20ce09330c2972l }, + { 0x6b9917b45fcf7e33l,0xe6793743945ceb42l,0x18fc22155c633d19l, + 0xad1adb3cc7485474l }, + 0 }, + /* 16 << 56 */ + { { 0x646f96796424c49bl,0xf888dfe867c241c9l,0xe12d4b9324f68b49l, + 0x9a6b62d8a571df20l }, + { 0x81b4b26d179483cbl,0x666f96329511fae2l,0xd281b3e4d53aa51fl, + 0x7f96a7657f3dbd16l }, + 0 }, + /* 17 << 56 */ + { { 0xa7f8b5bf074a30cel,0xd7f52107005a32e6l,0x6f9e090750237ed4l, + 0x2f21da478096fa2bl }, + { 0xf3e19cb4eec863a0l,0xd18f77fd9527620al,0x9505c81c407c1cf8l, + 0x9998db4e1b6ec284l }, + 0 }, + /* 19 << 56 */ + { { 0x794e2d5984ac066cl,0xf5954a92e68c69a0l,0x28c524584fd99dccl, + 0x60e639fcb1012517l }, + { 0xc2e601257de79248l,0xe9ef6404f12fc6d7l,0x4c4f28082a3b5d32l, + 0x865ad32ec768eb8al }, + 0 }, + /* 21 << 56 */ + { { 0x4f4ddf91b2f1ac7al,0xf99eaabb760fee27l,0x57f4008a49c228e5l, + 0x090be4401cf713bbl }, + { 0xac91fbe45004f022l,0xd838c2c2569e1af6l,0xd6c7d20b0f1daaa5l, + 0xaa063ac11bbb02c0l }, + 0 }, + /* 23 << 56 */ + { { 0x54935fcb81d73c9el,0x6d07e9790a5e97abl,0x4dc7b30acf3a6babl, + 0x147ab1f3170bee11l }, + { 0x0aaf8e3d9fafdee4l,0xfab3dbcb538a8b95l,0x405df4b36ef13871l, + 0xf1f4e9cb088d5a49l }, + 0 }, + /* 25 << 56 */ + { { 0x43c01b87459afccdl,0x6bd45143b7432652l,0x8473453055b5d78el, + 0x81088fdb1554ba7dl }, + { 0xada0a52c1e269375l,0xf9f037c42dc5ec10l,0xc066060794bfbc11l, + 0xc0a630bbc9c40d2fl }, + 0 }, + /* 27 << 56 */ + { { 0x9a730ed44763eb50l,0x24a0e221c1ab0d66l,0x643b6393648748f3l, + 0x1982daa16d3c6291l }, + { 0x6f00a9f78bbc5549l,0x7a1783e17f36384el,0xe8346323de977f50l, + 0x91ab688db245502al }, + 0 }, + /* 28 << 56 */ + { { 0x331ab6b56d0bdd66l,0x0a6ef32e64b71229l,0x1028150efe7c352fl, + 0x27e04350ce7b39d3l }, + { 0x2a3c8acdc1070c82l,0xfb2034d380c9feefl,0x2d729621709f3729l, + 0x8df290bf62cb4549l }, + 0 }, + /* 29 << 56 */ + { { 0x02f99f33fc2e4326l,0x3b30076d5eddf032l,0xbb21f8cf0c652fb5l, + 0x314fb49eed91cf7bl }, + { 0xa013eca52f700750l,0x2b9e3c23712a4575l,0xe5355557af30fbb0l, + 0x1ada35167c77e771l }, + 0 }, + /* 31 << 56 */ + { { 0xdc9f46fc609e4a74l,0x2a44a143ba667f91l,0xbc3d8b95b4d83436l, + 0xa01e4bd0c7bd2958l }, + { 0x7b18293273483c90l,0xa79c6aa1a7c7b598l,0xbf3983c6eaaac07el, + 0x8f18181e96e0d4e6l }, + 0 }, + /* 33 << 56 */ + { { 0x0bfc27eeacee5043l,0xae419e732eb10f02l,0x19c028d18943fb05l, + 0x71f01cf7ff13aa2al }, + { 0x7790737e8887a132l,0x6751330966318410l,0x9819e8a37ddb795el, + 0xfecb8ef5dad100b2l }, + 0 }, + /* 34 << 56 */ + { { 0x59f74a223021926al,0xb7c28a496f9b4c1cl,0xed1a733f912ad0abl, + 0x42a910af01a5659cl }, + { 0x3842c6e07bd68cabl,0x2b57fa3876d70ac8l,0x8a6707a83c53aaebl, + 0x62c1c51065b4db18l }, + 0 }, + /* 35 << 56 */ + { { 0x8de2c1fbb2d09dc7l,0xc3dfed12266bd23bl,0x927d039bd5b27db6l, + 0x2fb2f0f1103243dal }, + { 0xf855a07b80be7399l,0xed9327ce1f9f27a8l,0xa0bd99c7729bdef7l, + 0x2b67125e28250d88l }, + 0 }, + /* 36 << 56 */ + { { 0x784b26e88670ced7l,0xe3dfe41fc31bd3b4l,0x9e353a06bcc85cbcl, + 0x302e290960178a9dl }, + { 0x860abf11a6eac16el,0x76447000aa2b3aacl,0x46ff9d19850afdabl, + 0x35bdd6a5fdb2d4c1l }, + 0 }, + /* 37 << 56 */ + { { 0xe82594b07e5c9ce9l,0x0f379e5320af346el,0x608b31e3bc65ad4al, + 0x710c6b12267c4826l }, + { 0x51c966f971954cf1l,0xb1cec7930d0aa215l,0x1f15598986bd23a8l, + 0xae2ff99cf9452e86l }, + 0 }, + /* 39 << 56 */ + { { 0xb5a741a76b2515cfl,0x71c416019585c749l,0x78350d4fe683de97l, + 0x31d6152463d0b5f5l }, + { 0x7a0cc5e1fbce090bl,0xaac927edfbcb2a5bl,0xe920de4920d84c35l, + 0x8c06a0b622b4de26l }, + 0 }, + /* 40 << 56 */ + { { 0xd34dd58bafe7ddf3l,0x55851fedc1e6e55bl,0xd1395616960696e7l, + 0x940304b25f22705fl }, + { 0x6f43f861b0a2a860l,0xcf1212820e7cc981l,0x121862120ab64a96l, + 0x09215b9ab789383cl }, + 0 }, + /* 41 << 56 */ + { { 0x311eb30537387c09l,0xc5832fcef03ee760l,0x30358f5832f7ea19l, + 0xe01d3c3491d53551l }, + { 0x1ca5ee41da48ea80l,0x34e71e8ecf4fa4c1l,0x312abd257af1e1c7l, + 0xe3afcdeb2153f4a5l }, + 0 }, + /* 43 << 56 */ + { { 0x2a17747fa6d74081l,0x60ea4c0555a26214l,0x53514bb41f88c5fel, + 0xedd645677e83426cl }, + { 0xd5d6cbec96460b25l,0xa12fd0ce68dc115el,0xc5bc3ed2697840eal, + 0x969876a8a6331e31l }, + 0 }, + /* 44 << 56 */ + { { 0x60c36217472ff580l,0xf42297054ad41393l,0x4bd99ef0a03b8b92l, + 0x501c7317c144f4f6l }, + { 0x159009b318464945l,0x6d5e594c74c5c6bel,0x2d587011321a3660l, + 0xd1e184b13898d022l }, + 0 }, + /* 45 << 56 */ + { { 0x5ba047524c6a7e04l,0x47fa1e2b45550b65l,0x9419daf048c0a9a5l, + 0x663629537c243236l }, + { 0xcd0744b15cb12a88l,0x561b6f9a2b646188l,0x599415a566c2c0c0l, + 0xbe3f08590f83f09al }, + 0 }, + /* 46 << 56 */ + { { 0x9141c5beb92041b8l,0x01ae38c726477d0dl,0xca8b71f3d12c7a94l, + 0xfab5b31f765c70dbl }, + { 0x76ae7492487443e9l,0x8595a310990d1349l,0xf8dbeda87d460a37l, + 0x7f7ad0821e45a38fl }, + 0 }, + /* 47 << 56 */ + { { 0xed1d4db61059705al,0xa3dd492ae6b9c697l,0x4b92ee3a6eb38bd5l, + 0xbab2609d67cc0bb7l }, + { 0x7fc4fe896e70ee82l,0xeff2c56e13e6b7e3l,0x9b18959e34d26fcal, + 0x2517ab66889d6b45l }, + 0 }, + /* 48 << 56 */ + { { 0xf167b4e0bdefdd4fl,0x69958465f366e401l,0x5aa368aba73bbec0l, + 0x121487097b240c21l }, + { 0x378c323318969006l,0xcb4d73cee1fe53d1l,0x5f50a80e130c4361l, + 0xd67f59517ef5212bl }, + 0 }, + /* 49 << 56 */ + { { 0xf145e21e9e70c72el,0xb2e52e295566d2fbl,0x44eaba4a032397f5l, + 0x5e56937b7e31a7del }, + { 0x68dcf517456c61e1l,0xbc2e954aa8b0a388l,0xe3552fa760a8b755l, + 0x03442dae73ad0cdel }, + 0 }, + /* 51 << 56 */ + { { 0x3fcbdbce478e2135l,0x7547b5cfbda35342l,0xa97e81f18a677af6l, + 0xc8c2bf8328817987l }, + { 0xdf07eaaf45580985l,0xc68d1f05c93b45cbl,0x106aa2fec77b4cacl, + 0x4c1d8afc04a7ae86l }, + 0 }, + /* 52 << 56 */ + { { 0xdb41c3fd9eb45ab2l,0x5b234b5bd4b22e74l,0xda253decf215958al, + 0x67e0606ea04edfa0l }, + { 0xabbbf070ef751b11l,0xf352f175f6f06dcel,0xdfc4b6af6839f6b4l, + 0x53ddf9a89959848el }, + 0 }, + /* 53 << 56 */ + { { 0xda49c379c21520b0l,0x90864ff0dbd5d1b6l,0x2f055d235f49c7f7l, + 0xe51e4e6aa796b2d8l }, + { 0xc361a67f5c9dc340l,0x5ad53c37bca7c620l,0xda1d658832c756d0l, + 0xad60d9118bb67e13l }, + 0 }, + /* 55 << 56 */ + { { 0xd1183316fd6f7140l,0xf9fadb5bbd8e81f7l,0x701d5e0c5a02d962l, + 0xfdee4dbf1b601324l }, + { 0xbed1740735d7620el,0x04e3c2c3f48c0012l,0x9ee29da73455449al, + 0x562cdef491a836c4l }, + 0 }, + /* 57 << 56 */ + { { 0x147ebf01fad097a5l,0x49883ea8610e815dl,0xe44d60ba8a11de56l, + 0xa970de6e827a7a6dl }, + { 0x2be414245e17fc19l,0xd833c65701214057l,0x1375813b363e723fl, + 0x6820bb88e6a52e9bl }, + 0 }, + /* 59 << 56 */ + { { 0xe1b6f60c08191224l,0xc4126ebbde4ec091l,0xe1dff4dc4ae38d84l, + 0xde3f57db4f2ef985l }, + { 0x34964337d446a1ddl,0x7bf217a0859e77f6l,0x8ff105278e1d13f5l, + 0xa304ef0374eeae27l }, + 0 }, + /* 60 << 56 */ + { { 0xfc6f5e47d19dfa5al,0xdb007de37fad982bl,0x28205ad1613715f5l, + 0x251e67297889529el }, + { 0x727051841ae98e78l,0xf818537d271cac32l,0xc8a15b7eb7f410f5l, + 0xc474356f81f62393l }, + 0 }, + /* 61 << 56 */ + { { 0x92dbdc5ac242316bl,0xabe060acdbf4aff5l,0x6e8c38fe909a8ec6l, + 0x43e514e56116cb94l }, + { 0x2078fa3807d784f9l,0x1161a880f4b5b357l,0x5283ce7913adea3dl, + 0x0756c3e6cc6a910bl }, + 0 }, + /* 63 << 56 */ + { { 0xa573a4966d17fbc7l,0x0cd1a70a73d2b24el,0x34e2c5cab2676937l, + 0xe7050b06bf669f21l }, + { 0xfbe948b61ede9046l,0xa053005197662659l,0x58cbd4edf10124c5l, + 0xde2646e4dd6c06c8l }, + 0 }, + /* 64 << 56 */ + { { 0x332f81088cad38c0l,0x471b7e906bd68ae2l,0x56ac3fb20d8e27a3l, + 0xb54660db136b4b0dl }, + { 0x123a1e11a6fd8de4l,0x44dbffeaa37799efl,0x4540b977ce6ac17cl, + 0x495173a8af60acefl }, + 0 }, + /* 65 << 56 */ + { { 0xc48b1478db447d0bl,0xe1b85f5d46104fbbl,0x4ab31e7d991c60b9l, + 0xaa674a9258a0cfd0l }, + { 0x179fc2cd316f4297l,0x90c18642dcccbc82l,0x65d4309e56a4c163l, + 0xf211a9c7145a33ecl }, + 0 }, + /* 71 << 56 */ + { { 0x9669170cdc32717fl,0x52d69b5138133e34l,0xaed24e5fb079c3b2l, + 0xaba44a91a21ea3d2l }, + { 0xd6814f1938d40105l,0x38289fe463462e7al,0x1793eefa3a80cbf5l, + 0x05816a0795f29bacl }, + 0 }, + /* 77 << 56 */ + { { 0xdca88ad98f850641l,0x8c1152c447999b0dl,0x509f654e654aff33l, + 0x2228550f08a12f14l }, + { 0x60fe99dbb6a0ccdbl,0x80d6829bfc2cddccl,0x190f454dd5617aa4l, + 0x0aea05fe36295d2dl }, + 0 }, + /* 83 << 56 */ + { { 0x1de06c8af9bef9a5l,0xe24d85d3fb2d3164l,0x3dbe455e8d203d3el, + 0x439bee4735ea47a9l }, + { 0xcc143432784893d7l,0x9b71073bd9bebd00l,0x6c106b343aa2fe88l, + 0x9df2a42734746f7al }, + 0 }, + /* 89 << 56 */ + { { 0x1ad0b3725a8c2168l,0x64e52d6d143f0402l,0xd933c783e320f31fl, + 0x1ccf90a80ff14f52l }, + { 0xd3a3133ee1e6d0c0l,0xfd75a2d5b4acc8cal,0x62659b8e5559d171l, + 0x5087d6e9f13ad52al }, + 0 }, + /* 95 << 56 */ + { { 0xb4d647a5deef31a4l,0x95bf4ab180975ea9l,0x2f92d15adf57b03el, + 0x5ee808ab746b26d6l }, + { 0x4341597c1082f261l,0x027795eb40c45e95l,0xcb77744b3b690c30l, + 0xdd87c084af3f88d1l }, + 0 }, + /* 101 << 56 */ + { { 0x469f177572109785l,0xf365e55123f84d6cl,0x8006a9c28a046dbbl, + 0x1b9fbe892fa09f52l }, + { 0xac18a88016075e9el,0x4a3069bc1e3fd628l,0x20c61eaa60c61c14l, + 0x315b59daf61f004bl }, + 0 }, + /* 107 << 56 */ + { { 0x0a94387f26d04857l,0x952a4ebc43d6de95l,0xb422e15cf14abdfal, + 0x5b7a0153324ef90cl }, + { 0x6aefa20e9826ec5bl,0x0e529886ad2fe161l,0xb710a74ec0d416e8l, + 0x6cf4b0a5fb6c90bcl }, + 0 }, + /* 113 << 56 */ + { { 0x822aea4031979d3bl,0xb504eafde215a109l,0xa8761ead84bf2377l, + 0xb55c1e55efb3d942l }, + { 0xd01f9b0212b7f17bl,0x41b62c2a891bfbbfl,0x50800e6b08938149l, + 0x527b50a9b0a55d82l }, + 0 }, + /* 116 << 56 */ + { { 0x6bc84d8d1d9ce3c4l,0x53b465072a308df0l,0x6c3da9bfca79c88al, + 0x9636ad9c36372acfl }, + { 0x8840e92c425ef14cl,0x863191f96af3225bl,0xd56d82d0d369b857l, + 0x2053a2527a4c41f9l }, + 0 }, + /* 119 << 56 */ + { { 0x20aecd6609ca8805l,0x945d9b31dc818ee6l,0x1424647c2119b44bl, + 0xbe934d7e5a6641f9l }, + { 0xe91d53184559e55el,0xc2fb8e0b4dfbc3d4l,0x9e92e20676cb937fl, + 0x0f5582e4f2932429l }, + 0 }, + /* 125 << 56 */ + { { 0xb5fc22a42d31809fl,0x6d582d2b0e35b7b4l,0x5fac415158c5f576l, + 0xdff239371e4cd7c9l }, + { 0x0f62b329ed4d1925l,0x00994a2e6010fb16l,0xb4b91076bd754837l, + 0xfde219463345103al }, + 0 }, + }, + { + /* 0 << 64 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 64 */ + { { 0x4f922fc516a0d2bbl,0x0d5cc16c1a623499l,0x9241cf3a57c62c8bl, + 0x2f5e6961fd1b667fl }, + { 0x5c15c70bf5a01797l,0x3d20b44d60956192l,0x04911b37071fdb52l, + 0xf648f9168d6f0f7bl }, + 0 }, + /* 3 << 64 */ + { { 0x4090914bb5def996l,0x1cb69c83233dd1e7l,0xc1e9c1d39b3d5e76l, + 0x1f3338edfccf6012l }, + { 0xb1e95d0d2f5378a8l,0xacf4c2c72f00cd21l,0x6e984240eb5fe290l, + 0xd66c038d248088ael }, + 0 }, + /* 4 << 64 */ + { { 0x9ad5462bb4d8bc50l,0x181c0b16a9195770l,0xebd4fe1c78412a68l, + 0xae0341bcc0dff48cl }, + { 0xb6bc45cf7003e866l,0xf11a6dea8a24a41bl,0x5407151ad04c24c2l, + 0x62c9d27dda5b7b68l }, + 0 }, + /* 5 << 64 */ + { { 0xd4992b30614c0900l,0xda98d121bd00c24bl,0x7f534dc87ec4bfa1l, + 0x4a5ff67437dc34bcl }, + { 0x68c196b81d7ea1d7l,0x38cf289380a6d208l,0xfd56cd09e3cbbd6el, + 0xec72e27e4205a5b6l }, + 0 }, + /* 7 << 64 */ + { { 0xe8b97932b88756ddl,0xed4e8652f17e3e61l,0xc2dd14993ee1c4a4l, + 0xc0aaee17597f8c0el }, + { 0x15c4edb96c168af3l,0x6563c7bfb39ae875l,0xadfadb6f20adb436l, + 0xad55e8c99a042ac0l }, + 0 }, + /* 9 << 64 */ + { { 0x65c29219909523c8l,0xa62f648fa3a1c741l,0x88598d4f60c9e55al, + 0xbce9141b0e4f347al }, + { 0x9af97d8435f9b988l,0x0210da62320475b6l,0x3c076e229191476cl, + 0x7520dbd944fc7834l }, + 0 }, + /* 10 << 64 */ + { { 0x87a7ebd1e0a1b12al,0x1e4ef88d770ba95fl,0x8c33345cdc2ae9cbl, + 0xcecf127601cc8403l }, + { 0x687c012e1b39b80fl,0xfd90d0ad35c33ba4l,0xa3ef5a675c9661c2l, + 0x368fc88ee017429el }, + 0 }, + /* 11 << 64 */ + { { 0x664300b07850ec06l,0xac5a38b97d3a10cfl,0x9233188de34ab39dl, + 0xe77057e45072cbb9l }, + { 0xbcf0c042b59e78dfl,0x4cfc91e81d97de52l,0x4661a26c3ee0ca4al, + 0x5620a4c1fb8507bcl }, + 0 }, + /* 13 << 64 */ + { { 0x84b9ca1504b6c5a0l,0x35216f3918f0e3a3l,0x3ec2d2bcbd986c00l, + 0x8bf546d9d19228fel }, + { 0xd1c655a44cd623c3l,0x366ce718502b8e5al,0x2cfc84b4eea0bfe7l, + 0xe01d5ceecf443e8el }, + 0 }, + /* 15 << 64 */ + { { 0xa75feacabe063f64l,0x9b392f43bce47a09l,0xd42415091ad07acal, + 0x4b0c591b8d26cd0fl }, + { 0x2d42ddfd92f1169al,0x63aeb1ac4cbf2392l,0x1de9e8770691a2afl, + 0xebe79af7d98021dal }, + 0 }, + /* 16 << 64 */ + { { 0x58af2010f5b343bcl,0x0f2e400af2f142fel,0x3483bfdea85f4bdfl, + 0xf0b1d09303bfeaa9l }, + { 0x2ea01b95c7081603l,0xe943e4c93dba1097l,0x47be92adb438f3a6l, + 0x00bb7742e5bf6636l }, + 0 }, + /* 17 << 64 */ + { { 0x66917ce63b5f1cc4l,0x37ae52eace872e62l,0xbb087b722905f244l, + 0x120770861e6af74fl }, + { 0x4b644e491058edeal,0x827510e3b638ca1dl,0x8cf2b7046038591cl, + 0xffc8b47afe635063l }, + 0 }, + /* 19 << 64 */ + { { 0x7677408d6dfafed3l,0x33a0165339661588l,0x3c9c15ec0b726fa0l, + 0x090cfd936c9b56dal }, + { 0xe34f4baea3c40af5l,0x3469eadbd21129f1l,0xcc51674a1e207ce8l, + 0x1e293b24c83b1ef9l }, + 0 }, + /* 21 << 64 */ + { { 0x796d3a85825808bdl,0x51dc3cb73fd6e902l,0x643c768a916219d1l, + 0x36cd7685a2ad7d32l }, + { 0xe3db9d05b22922a4l,0x6494c87edba29660l,0xf0ac91dfbcd2ebc7l, + 0x4deb57a045107f8dl }, + 0 }, + /* 23 << 64 */ + { { 0xb6c69ac82094cec3l,0x9976fb88403b770cl,0x1dea026c4859590dl, + 0xb6acbb468562d1fdl }, + { 0x7cd6c46144569d85l,0xc3190a3697f0891dl,0xc6f5319548d5a17dl, + 0x7d919966d749abc8l }, + 0 }, + /* 25 << 64 */ + { { 0xb53b7de561906373l,0x858dbadeeb999595l,0x8cbb47b2a59e5c36l, + 0x660318b3dcf4e842l }, + { 0xbd161ccd12ba4b7al,0xf399daabf8c8282al,0x1587633aeeb2130dl, + 0xa465311ada38dd7dl }, + 0 }, + /* 27 << 64 */ + { { 0x2dae9082be7cf3a6l,0xcc86ba92bc967274l,0xf28a2ce8aea0a8a9l, + 0x404ca6d96ee988b3l }, + { 0xfd7e9c5d005921b8l,0xf56297f144e79bf9l,0xa163b4600d75ddc2l, + 0x30b23616a1f2be87l }, + 0 }, + /* 28 << 64 */ + { { 0x19e6125dec3f1decl,0x07b1f040911178dal,0xd93ededa904a6738l, + 0x55187a5a0bebedcdl }, + { 0xf7d04722eb329d41l,0xf449099ef170b391l,0xfd317a69ca99f828l, + 0x50c3db2b34a4976dl }, + 0 }, + /* 29 << 64 */ + { { 0x0064d8585499fb32l,0x7b67bad977a8aeb7l,0x1d3eb9772d08eec5l, + 0x5fc047a6cbabae1dl }, + { 0x0577d159e54a64bbl,0x8862201bc43497e4l,0xad6b4e282ce0608dl, + 0x8b687b7d0b167aacl }, + 0 }, + /* 31 << 64 */ + { { 0xe9f9669cda94951el,0x4b6af58d66b8d418l,0xfa32107417d426a4l, + 0xc78e66a99dde6027l }, + { 0x0516c0834a53b964l,0xfc659d38ff602330l,0x0ab55e5c58c5c897l, + 0x985099b2838bc5dfl }, + 0 }, + /* 33 << 64 */ + { { 0xe7a935fa1684cb3bl,0x571650b5a7d7e69dl,0x6ba9ffa40328c168l, + 0xac43f6bc7e46f358l }, + { 0x54f75e567cb6a779l,0x4e4e2cc8c61320del,0xb94258bc2b8903d0l, + 0xc7f32d57ceecabe0l }, + 0 }, + /* 34 << 64 */ + { { 0x34739f16cd7d9d89l,0x6daab4267ca080b5l,0x772086ff40e19f45l, + 0x43caa56118c61b42l }, + { 0x0ba3d4a8dbf365f1l,0xa0db435ee760ad97l,0xfd6f30d56916c59bl, + 0xab34cb5dafe12f5dl }, + 0 }, + /* 35 << 64 */ + { { 0x445b86ea02a3260al,0x8c51d6428d689babl,0x183334d65588904cl, + 0xf8a3b84d479d6422l }, + { 0x581acfa0f0833d00l,0xc50827bc3b567d2dl,0x2c935e6daddcf73el, + 0x2a645f7704dd19f2l }, + 0 }, + /* 36 << 64 */ + { { 0x78d2e8dfcb564473l,0x4349a97357d5621al,0x9d835d89218f8b24l, + 0x01fe7bc5079b6ee2l }, + { 0xe57f2a2b5b3b5dcel,0x5a8637b75fe55565l,0x83ff34aea41dbae7l, + 0xfce1199c950a7a8fl }, + 0 }, + /* 37 << 64 */ + { { 0x0ca5d25bf8e71ce2l,0x204edc4a062685dal,0x06fe407d87678ec2l, + 0xd16936a07defa39al }, + { 0x3b108d84af3d16d0l,0xf2e9616d0305cad0l,0xbc9537e6f27bed97l, + 0x71c2d699ebc9f45cl }, + 0 }, + /* 39 << 64 */ + { { 0x203bdd84cdcd3a85l,0x1107b901ade3ccfal,0xa7da89e95533159dl, + 0x8d834005860e8c64l }, + { 0x914bc0eb2a7638f7l,0xc66ce0a6620e8606l,0x11ef98c2e6c12dc0l, + 0x25666b1d7780fc0el }, + 0 }, + /* 40 << 64 */ + { { 0x374f541f3e707706l,0x9a4d3638a831d0cfl,0x4ab4f4831518ca04l, + 0x54e3ee5dfe38c318l }, + { 0x383ae36403c8819bl,0xa9d1daa12e17864cl,0x245a97b350eeaa5bl, + 0x5362d00999bf4e83l }, + 0 }, + /* 41 << 64 */ + { { 0x6667e89f4ded8a4fl,0xa59161abc36a7795l,0x1c96f6f9331ccf94l, + 0xf2727e879a686d49l }, + { 0x0f94894bb841295fl,0xb0fe8f744a0503d1l,0x60c581c7ef407926l, + 0x1980c8e13edb7e1cl }, + 0 }, + /* 43 << 64 */ + { { 0x47948c84c5de1a41l,0xd595d14a48959688l,0x3bfca4be86ff21c9l, + 0xb5ff59b86a4191cal }, + { 0xced1dd1d65094c86l,0xd57b86559dc9d001l,0xbcac6fa3486e51d7l, + 0x8e97e2637b774c1bl }, + 0 }, + /* 44 << 64 */ + { { 0xfc0313c29bd43980l,0x9c954b70f172db29l,0x679bdcb7f954a21al, + 0x6b48170954e2e4fcl }, + { 0x318af5f530baf1d0l,0x26ea8a3ccbf92060l,0xc3c69d7ccd5ae258l, + 0xa73ba0470ead07c9l }, + 0 }, + /* 45 << 64 */ + { { 0xe82eb003e35dca85l,0xfd0000fa31e39180l,0xbca90f746735f378l, + 0xe6aa783158c943edl }, + { 0x0e94ecd5b6a438d7l,0xc02b60faf9a5f114l,0x4063568b8b1611ebl, + 0x1398bdc1272509ecl }, + 0 }, + /* 46 << 64 */ + { { 0xc2ef6a01be3e92d1l,0x1bce9c27282bd5ddl,0xf7e488f3adda0568l, + 0xd4f15fdb1af9bb8bl }, + { 0x8c490ade4da846efl,0x76229da17f0b825el,0xc8b812082a6711c6l, + 0x511f5e23b4c523aal }, + 0 }, + /* 47 << 64 */ + { { 0xbdf4e7049970f46el,0x70e220288dadbd1al,0x2b86c97fb1223d26l, + 0x042ad22ecf62f51al }, + { 0x72944339ba2ed2e9l,0x0ba0d10ef94fa61dl,0x3f86164194e68f15l, + 0x1312a74acb86c545l }, + 0 }, + /* 48 << 64 */ + { { 0x3a63c39731815e69l,0x6df9cbd6dcdd2802l,0x4c47ed4a15b4f6afl, + 0x62009d826ac0f978l }, + { 0x664d80d28b898fc7l,0x72f1eeda2c17c91fl,0x9e84d3bc7aae6609l, + 0x58c7c19528376895l }, + 0 }, + /* 49 << 64 */ + { { 0x640ebf5d5b8d354al,0xa5f3a8fdb396ff64l,0xd53f041d8378ed81l, + 0x1969d61bc1234ad2l }, + { 0x16d7acffeb68bde2l,0x63767a68f23e9368l,0x937a533c38928d95l, + 0xee2190bbbeb0f1f2l }, + 0 }, + /* 51 << 64 */ + { { 0xb6860c9a73a4aafbl,0xb2f996290488870dl,0x16ef6232572d9e25l, + 0x5b9eb1bad1383389l }, + { 0xabf713a7ed8d77f8l,0xd2b4a2e9e2b69e64l,0xa1a22cfd6d6f17c2l, + 0x4bfd6f992d604511l }, + 0 }, + /* 52 << 64 */ + { { 0xdcff7630d9294f07l,0x89b765d68dba8fd0l,0x553e55de8dbcaccdl, + 0x9b4a009eed702bf8l }, + { 0xf6e534dd27b8ca0dl,0xc4496b346177fd52l,0x378ce6f6c87bb7b7l, + 0x68633d4844cc19f0l }, + 0 }, + /* 53 << 64 */ + { { 0xfe550021bc84c625l,0x8d7169986d45e4a3l,0xa09c6ded4c0c66b7l, + 0xe32313aeb9e1d547l }, + { 0x8ce775b4d1e8e0b9l,0xa899f9102654dd15l,0x7c38aa066cc8b2a9l, + 0xe6ebb291d6ce6cc0l }, + 0 }, + /* 55 << 64 */ + { { 0x5963df62a6991216l,0x4c17f72246996010l,0x131dc2b840477722l, + 0x78bf50b0d1765a75l }, + { 0x360afd587ceaca12l,0xebc55dbb139cd470l,0x9083e27e4c05541cl, + 0xc10057a3b873d757l }, + 0 }, + /* 57 << 64 */ + { { 0x440009c3deed7769l,0xde2fa58a14fd8a44l,0x509e7df35b627596l, + 0x3d76a87cc3bb07a7l }, + { 0x8018fee5b8ef000al,0x71ce33e9823fd4b6l,0x3a1cac37469c0bb1l, + 0x92fe7aeaf3eec8eel }, + 0 }, + /* 59 << 64 */ + { { 0x37ad0eb8de64e568l,0x4ac669bca1e3e20el,0x240d0ac22ce944edl, + 0xd532039a3c1b28fbl }, + { 0xa2bb899a23acba6cl,0xd472af671af937e1l,0x04478f7b8851e753l, + 0x74030eef5ea05307l }, + 0 }, + /* 60 << 64 */ + { { 0x3559e7b67dc17874l,0xd0caf0ef8195cc2al,0x07c067880cd24dd9l, + 0x01a99ea002857c41l }, + { 0xd86579e490f82f63l,0xb1e0658ae41c9237l,0x075ffafd93fd1e79l, + 0x6e70403547f60b8fl }, + 0 }, + /* 61 << 64 */ + { { 0x2246ad76c1d68c31l,0x9126202b0d5c4677l,0x5f40de81638882dcl, + 0xb131988ca3253a7fl }, + { 0x766f1897ba9ae0a8l,0xf0e01dd41d8b5fefl,0x03e28ce3ed7b12c8l, + 0x44b3a2be1fd20e1el }, + 0 }, + /* 63 << 64 */ + { { 0xd4c8e8e5f2a5f247l,0x42ffd816c2c7c979l,0x89e1485211093d1al, + 0x98f44a4613871ebbl }, + { 0x374849964b032e2dl,0x28a430f445995a61l,0xf2f9acbad5be16b6l, + 0xac98a5402d8e02aal }, + 0 }, + /* 64 << 64 */ + { { 0x0d53f5c7a3e6fcedl,0xe8cbbdd5f45fbdebl,0xf85c01df13339a70l, + 0x0ff71880142ceb81l }, + { 0x4c4e8774bd70437al,0x5fb32891ba0bda6al,0x1cdbebd2f18bd26el, + 0x2f9526f103a9d522l }, + 0 }, + /* 65 << 64 */ + { { 0x48334fdcc20b8d30l,0x25f887d749414fddl,0x9ccd513311a2cf0dl, + 0x7e7799e4d08975a4l }, + { 0xb5993a53729b951cl,0x0cf14a5a62dbc6a8l,0xb39ed36efe4d16eel, + 0xb75f3fb681bda63al }, + 0 }, + /* 71 << 64 */ + { { 0xac7db8706d4f68b5l,0x819a13c7be49b3a4l,0x646ae2b1418bf1e9l, + 0x25b53a5f69b3a5ccl }, + { 0xd23d94d37de26578l,0x8bb581caecdd138al,0x9e053f67f857b0dal, + 0xe679cc7a255ff474l }, + 0 }, + /* 77 << 64 */ + { { 0x4a4b8d990df097f9l,0x0ae1227a0b4173cal,0x0d401778adb72178l, + 0xd29848b43f421e0cl }, + { 0xc5eec6096eb0722dl,0x527d72877e12c028l,0xed12a9e71b5dcc0cl, + 0x26b27344dcf4b4dal }, + 0 }, + /* 83 << 64 */ + { { 0x695c502565e4408al,0x2d23768fcbce94e6l,0x1505fa1e5080b88dl, + 0x5c8fbab6855f7cc1l }, + { 0x70d876f275fb125dl,0x456421330a252007l,0xfe99249a8ee05be1l, + 0x0893b620f4bf5490l }, + 0 }, + /* 89 << 64 */ + { { 0x2a59df1ed9fe6bdfl,0x96a9c791785e057fl,0x4b0d795f86a1d751l, + 0x196c8e0aec642886l }, + { 0x6df67899bc0e055cl,0x4173204a63007433l,0xb5ee4efec21c9245l, + 0x2f7d4c75c1451bael }, + 0 }, + /* 95 << 64 */ + { { 0x2ad7f836b1047b7fl,0x368d431a71f6bfe1l,0xfcd933b103db4667l, + 0xfff77ed3ecb81330l }, + { 0x3677935b44958bd4l,0xa6cfcda8a1d5a9e7l,0xb2b73bc699ff9fael, + 0x1c2cd628f866d3c4l }, + 0 }, + /* 101 << 64 */ + { { 0x2756873495031ceel,0xebed373d51091c1bl,0x398fef0819aa2f27l, + 0x2f26174e2c0a9feal }, + { 0xedca72b6b219be3fl,0x001a8fdc80503df8l,0x9a2fadbb6b93f643l, + 0xd48e552cd44cebc3l }, + 0 }, + /* 107 << 64 */ + { { 0x6c0dbb68667a7ab6l,0x00490ce757630e91l,0x04976cd57eb2f382l, + 0x9ee486b655dda4a3l }, + { 0x4ea5c9c9cca0d01cl,0xa6e054b639f69c6dl,0xb3b7ac992ecab239l, + 0x80c9f6d17597512el }, + 0 }, + /* 113 << 64 */ + { { 0x64dfdd68b942fad9l,0xe7d8e88da5eb3d14l,0xb7281dc2382f6301l, + 0xcfa2ee6dbfe00a7fl }, + { 0x6e617657dc7be39fl,0x22d58dd6591c6e3al,0xd3a4003918318c13l, + 0xcac6c830981b6b72l }, + 0 }, + /* 116 << 64 */ + { { 0x009690ffb4fbfaa0l,0x8bbbdab73619c6dbl,0xc6d44273728356e8l, + 0xfd76f0d8e453ec35l }, + { 0x775c2554aac28a29l,0x28f7af9d5c55e4f0l,0xbacf54a688e8ad4dl, + 0x85b018e80aa76ddfl }, + 0 }, + /* 119 << 64 */ + { { 0x27893f7983ce88e4l,0x9556c9977785f13dl,0x83d3c38d3a35831el, + 0x3856c829d12f0a1dl }, + { 0xb308d84c93259c1al,0x4ef87ab4691ffd28l,0x76a18d5321a88c58l, + 0xf13cd5d53503cb4dl }, + 0 }, + /* 125 << 64 */ + { { 0x669d93dba8cc0db3l,0x403cb9200dfcfcf4l,0x5def4a03e77c3979l, + 0x2a05c9423e2e2522l }, + { 0xd86dca52b5f48bf0l,0x174766de5828a135l,0x116290b40d3a96d0l, + 0xe1999457aeea1193l }, + 0 }, + }, + { + /* 0 << 72 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 72 */ + { { 0x0db2fb5ed005832al,0x5f5efd3b91042e4fl,0x8c4ffdc6ed70f8cal, + 0xe4645d0bb52da9ccl }, + { 0x9596f58bc9001d1fl,0x52c8f0bc4e117205l,0xfd4aa0d2e398a084l, + 0x815bfe3a104f49del }, + 0 }, + /* 3 << 72 */ + { { 0x524d226ad7ab9a2dl,0x9c00090d7dfae958l,0x0ba5f5398751d8c2l, + 0x8afcbcdd3ab8262dl }, + { 0x57392729e99d043bl,0xef51263baebc943al,0x9feace9320862935l, + 0x639efc03b06c817bl }, + 0 }, + /* 4 << 72 */ + { { 0xe839be7d341d81dcl,0xcddb688932148379l,0xda6211a1f7026eadl, + 0xf3b2575ff4d1cc5el }, + { 0x40cfc8f6a7a73ae6l,0x83879a5e61d5b483l,0xc5acb1ed41a50ebcl, + 0x59a60cc83c07d8fal }, + 0 }, + /* 5 << 72 */ + { { 0xdec98d4ac3b81990l,0x1cb837229e0cc8fel,0xfe0b0491d2b427b9l, + 0x0f2386ace983a66cl }, + { 0x930c4d1eb3291213l,0xa2f82b2e59a62ae4l,0x77233853f93e89e3l, + 0x7f8063ac11777c7fl }, + 0 }, + /* 7 << 72 */ + { { 0x36e607cf02ff6072l,0xa47d2ca98ad98cdcl,0xbf471d1ef5f56609l, + 0xbcf86623f264ada0l }, + { 0xb70c0687aa9e5cb6l,0xc98124f217401c6cl,0x8189635fd4a61435l, + 0xd28fb8afa9d98ea6l }, + 0 }, + /* 9 << 72 */ + { { 0x3d4da8c3017025f3l,0xefcf628cfb9579b4l,0x5c4d00161f3716ecl, + 0x9c27ebc46801116el }, + { 0x5eba0ea11da1767el,0xfe15145247004c57l,0x3ace6df68c2373b7l, + 0x75c3dffe5dbc37acl }, + 0 }, + /* 10 << 72 */ + { { 0xa2a147dba28a0749l,0x246c20d6ee519165l,0x5068d1b1d3810715l, + 0xb1e7018c748160b9l }, + { 0x03f5b1faf380ff62l,0xef7fb1ddf3cb2c1el,0xeab539a8fc91a7dal, + 0x83ddb707f3f9b561l }, + 0 }, + /* 11 << 72 */ + { { 0xb57276d980101b98l,0x760883fdb82f0f66l,0x89d7de754bc3eff3l, + 0x03b606435dc2ab40l }, + { 0xcd6e53dfe05beeacl,0xf2f1e862bc3325cdl,0xdd0f7921774f03c3l, + 0x97ca72214552cc1bl }, + 0 }, + /* 13 << 72 */ + { { 0x760cb3b5e224c5d7l,0xfa3baf8c68616919l,0x9fbca1138d142552l, + 0x1ab18bf17669ebf5l }, + { 0x55e6f53e9bdf25ddl,0x04cc0bf3cb6cd154l,0x595bef4995e89080l, + 0xfe9459a8104a9ac1l }, + 0 }, + /* 15 << 72 */ + { { 0x694b64c5abb020e8l,0x3d18c18419c4eec7l,0x9c4673ef1c4793e5l, + 0xc7b8aeb5056092e6l }, + { 0x3aa1ca43f0f8c16bl,0x224ed5ecd679b2f6l,0x0d56eeaf55a205c9l, + 0xbfe115ba4b8e028bl }, + 0 }, + /* 16 << 72 */ + { { 0x3e22a7b397acf4ecl,0x0426c4005ea8b640l,0x5e3295a64e969285l, + 0x22aabc59a6a45670l }, + { 0xb929714c5f5942bcl,0x9a6168bdfa3182edl,0x2216a665104152bal, + 0x46908d03b6926368l }, + 0 }, + /* 17 << 72 */ + { { 0x9b8be0247fcba850l,0x81eb5797820a181el,0xa0f2812230a01211l, + 0x7e9cdc3cae7b8821l }, + { 0x202332cc72ce15e7l,0xcd3cb2bbcb8238d7l,0xe4ab63dfc6e82c43l, + 0x58bd00283183d717l }, + 0 }, + /* 19 << 72 */ + { { 0x02d57b7e717ed7b5l,0xd22e5b244dbce1a2l,0x174bd7712a4cdcf5l, + 0xa6fdb801408205bbl }, + { 0x67b4b0695e1387e9l,0x332b19a10591a442l,0x24edd916ccacf366l, + 0xbe34cc4534958a50l }, + 0 }, + /* 21 << 72 */ + { { 0xa3f46e1e3e66d391l,0xb4a732cd7d6369b2l,0x99c3b85d402c1022l, + 0x7dccfcbe2b54932el }, + { 0xa6ddaa7b56b1dfe2l,0x31dc78a5e34a82c9l,0x8abeb3da704f3941l, + 0xdf11a36cca55fa98l }, + 0 }, + /* 23 << 72 */ + { { 0x6c01f77a16e00c1bl,0x82515490839eaaacl,0x62f3a4ef3470d334l, + 0x5a29a6491c1dcd6cl }, + { 0x46b6782ece997a25l,0x9978fb35d3579953l,0x98f5a9df0960e0cel, + 0x547dc8391f527a4cl }, + 0 }, + /* 25 << 72 */ + { { 0x395b15835d9dc24fl,0xa4256932c73ae680l,0x0542960efaa2c8e9l, + 0x2bb3adee71068c6al }, + { 0xa706099b570b4554l,0x85d12bb5f4e278d6l,0xd78af6f664296843l, + 0xc7d3b3888428c633l }, + 0 }, + /* 27 << 72 */ + { { 0x34d44f9343b7e597l,0xdde440a7c2530f42l,0x7270a0817856bdb9l, + 0x86a945eb5353032fl }, + { 0x6c2f8e9966d39810l,0x0642a31b9b8b4b6bl,0x51679e62d1509d82l, + 0x0120001c90f8ff16l }, + 0 }, + /* 28 << 72 */ + { { 0x50a1c1062e36e34al,0x74e8f58ce024ed1al,0x3f0f1dfa1300d726l, + 0x6680df267b4a2d18l }, + { 0x12b5979d8235b3b7l,0x1d2fafcb8a611493l,0x73ebda968848ece5l, + 0xe996c275a413e399l }, + 0 }, + /* 29 << 72 */ + { { 0x46b7d7c7495ff000l,0xe60ed097baed95d1l,0xaa8804ac6e38f9c0l, + 0x92990c0645c6f9bbl }, + { 0xcae6a439c0919851l,0x713dff151bf5e1f2l,0x5d262c302eb38cdbl, + 0xb73d505190df31dfl }, + 0 }, + /* 31 << 72 */ + { { 0x921e7b1c32d9268cl,0x34db2b964276fad4l,0x0ec56d34cc44e730l, + 0x59be3a46096545b7l }, + { 0xe9fdbc9766cf3a6al,0x7b2f83edd04e9b53l,0x6d99b3cc8fbae3e7l, + 0x8eb5646c7ada3a40l }, + 0 }, + /* 33 << 72 */ + { { 0xa69ab906fc3302bfl,0x49ae6ba7d0872e90l,0xc9e2d6d1f3a1bfc3l, + 0x11dfe85f1a033500l }, + { 0x45189c2998666dbdl,0xba6aab88bbfd13cel,0xcf9c8b43dbd38cd4l, + 0xa0cb581b68009236l }, + 0 }, + /* 34 << 72 */ + { { 0xff18c42a16288a7al,0x6363ace430699163l,0x8546d6332a2ce353l, + 0x5e0379ef7b6b3418l }, + { 0x2df2bb463e941bb2l,0xae7c091888e1aacel,0x6bc0982d83f5a37al, + 0x8521bd02676d09e0l }, + 0 }, + /* 35 << 72 */ + { { 0x6531dff33d361aacl,0x59b954477c8cac2el,0xcc104df6c5cb7363l, + 0x68b571c519364acdl }, + { 0x7521e962979c3bc0l,0xbe0544c9c4aa1f92l,0x59127fe92a31eabbl, + 0x760ac28593d8b55bl }, + 0 }, + /* 36 << 72 */ + { { 0x62ed534c6115164bl,0xaebe9e4cdce84ceal,0xd81c91a1c83f64c3l, + 0x325a8ca8ecacd09al }, + { 0x7ea57ad968b45df1l,0xa555636fd530c5d2l,0x23aff510591cfe32l, + 0x46ff147637bedab9l }, + 0 }, + /* 37 << 72 */ + { { 0xa5a7e81ecb2edb3bl,0x9b0dc5f4f8fbe238l,0xc6f258087c66dd34l, + 0xb4a57503a3f8f38al }, + { 0x195b433513571b5bl,0xa32840763ccbc30bl,0x64ae1ffccf99ddd5l, + 0x0dfc8772aa844e76l }, + 0 }, + /* 39 << 72 */ + { { 0x8b471afbfb22341dl,0xbf448b43397afdd2l,0x4cb08409682c37edl, + 0xc3acfae6a948f1f6l }, + { 0xf58462549e634707l,0x50161a78bd949f52l,0xf0529e752fe73566l, + 0xe7e3fdef6fda53e0l }, + 0 }, + /* 40 << 72 */ + { { 0x56dab1c8321a518cl,0xfd4439a68bce226fl,0xe0b30d194facb9fal, + 0xb5052f307583571bl }, + { 0x1442641012afd476l,0xd02e417203fe624al,0xfc394f65531c92e6l, + 0x16d4bf5ad4bc0b52l }, + 0 }, + /* 41 << 72 */ + { { 0xa38ac25eb4ec4f0fl,0x5399c024de72b27dl,0x08318aafd81a3d65l, + 0x1af227a70c20e5d9l }, + { 0x6389cc9a26c54e25l,0x438298bba47dc27fl,0x75386cca1a63fa0el, + 0xc941e84cdf7bc1b0l }, + 0 }, + /* 43 << 72 */ + { { 0x81cad748fdfe3faal,0x752107b453ff1988l,0x8d8bb7001a8fd829l, + 0x69838e15ca821d8el }, + { 0x24371ede3b9f6b34l,0x19b4bb24d91e1495l,0x90899ca1e598ded1l, + 0xbbb78b167c14e9e3l }, + 0 }, + /* 44 << 72 */ + { { 0xa577e84cbef239aal,0x656d2b6f8904b4d4l,0x2f6defe6ca4007edl, + 0xca6e517737770796l }, + { 0x4c62fcba298b6448l,0x046849660f62e00dl,0x806c2f0390b07d82l, + 0x730855795e8d1e60l }, + 0 }, + /* 45 << 72 */ + { { 0x24488802f4703b78l,0x6c9323bee9eaa1e0l,0x242990e2aa94c170l, + 0x3292bc42a15b5886l }, + { 0x60ccb5bc908af203l,0x8fd63583713b09bdl,0x40791ecad693fa28l, + 0xea80abf2941af8a1l }, + 0 }, + /* 46 << 72 */ + { { 0xf9c0315071145fe3l,0x80a71b55d7873a7dl,0xd134244b5e10bac7l, + 0x303f7e12ded3a4b4l }, + { 0x58e6f17e803b7a3bl,0xcd6f64130b1ca6b4l,0x25e744ce2ce65aa2l, + 0xf2bbc66b952efa51l }, + 0 }, + /* 47 << 72 */ + { { 0xc8b212e75913e1f3l,0xf018ab208d416886l,0x28249e15b617cac4l, + 0x837fcba1693ed09al }, + { 0x9c457e511c15a1bcl,0x9354758756c7f3f1l,0x1afd80348be18306l, + 0xa43d56982256ab14l }, + 0 }, + /* 48 << 72 */ + { { 0xce06b88210395755l,0x117ce6345ec1df80l,0xfefae513eff55e96l, + 0xcf36cba6fd7fed1el }, + { 0x7340eca9a40ebf88l,0xe6ec1bcfb3d37e12l,0xca51b64e86bbf9ffl, + 0x4e0dbb588b40e05el }, + 0 }, + /* 49 << 72 */ + { { 0xf9c063f62f2be34bl,0x9ca32fa99c20f16bl,0xe02e350d0125a01al, + 0x62d66c54e6516c25l }, + { 0x21b154ad5120bedbl,0xb1077f4e8d6ff9d8l,0xd01a46c300bb4941l, + 0x9d381847d1460588l }, + 0 }, + /* 51 << 72 */ + { { 0xf3a9b311581cb57bl,0x65fb3fb649727d13l,0xb8496e3d35131142l, + 0xf7642f554d0cdab9l }, + { 0xe2f66f0e9f6d7e45l,0xbae14cedaa22fcd4l,0x1f769f0e49b2e05al, + 0x08c4d7784ac5191el }, + 0 }, + /* 52 << 72 */ + { { 0x86f9108ece4aa825l,0xbe5b2f317e5a5fbfl,0x2772c1b49254bb78l, + 0xae6cdf5f4ff8ac5cl }, + { 0x106cd94bf6b7a12el,0xbe0915d6d1c7a1a5l,0x8bf6bc8d3b40ac5el, + 0xbb89180423ee3acal }, + 0 }, + /* 53 << 72 */ + { { 0x76f15eaa618b5ea1l,0xec1ea62e6d4ad0c8l,0x301b60c8168d57fal, + 0x454d5f771edbfb05l }, + { 0xea888e29a936031al,0x01303d3f0174dd17l,0x8b5e06b4244254e7l, + 0x00ebf03509724acfl }, + 0 }, + /* 55 << 72 */ + { { 0x66ce3ded8e66d509l,0x368e38d05a488586l,0x7b9ae220c7eedf5el, + 0x67e9ea52bfbf9d62l }, + { 0xe9cbf53d99b7ecb3l,0xfde3e8c0908bf072l,0x288400ab1107e21fl, + 0x24c8856256532667l }, + 0 }, + /* 57 << 72 */ + { { 0x0d5f9955ca9d3ad1l,0x545feba13a1daec0l,0xd22972016cb30f23l, + 0x9660175ccef6cf6el }, + { 0xbf3e341a395738dcl,0x74a5efbc80f7cca4l,0xc4f9a07bbebc6a60l, + 0x2f1e3dad4b1f915al }, + 0 }, + /* 59 << 72 */ + { { 0xada4423f0d5e2e34l,0x2d31f4920b372358l,0xd7f469370e2d6a8cl, + 0xf5e7ccfe0028e4ael }, + { 0x20fcb1f3928854b2l,0x2a8973c507271bf6l,0xe87de33e5fa88fe1l, + 0xe9af2dce7bd3c2a6l }, + 0 }, + /* 60 << 72 */ + { { 0x185a19d959d097b2l,0xb1c72a3a0dea2875l,0x3b371628f9021f08l, + 0x45f1255bfa9d6ac1l }, + { 0x9ff36a90cfd72c0dl,0x8c7315db24fe2376l,0x9aebcde04b34d42cl, + 0x2129ab16923025f3l }, + 0 }, + /* 61 << 72 */ + { { 0x341b9dd714b4cf50l,0x7c6e4634d619d00el,0x571d6e2fdf2165ael, + 0xdedf9cd18dbe9db5l }, + { 0x52a152777c5f3dc3l,0x7d27c97ef2901cf7l,0x5e098b54d02a85dfl, + 0x6fce3e13088e3640l }, + 0 }, + /* 63 << 72 */ + { { 0xfa95be147a939904l,0xdfcf5b9bb56365ccl,0xdbb546bdd2d66922l, + 0xf26a8b9cda03ca7fl }, + { 0x96a8042d16821c0cl,0xe6729970e88ede60l,0xd028130d1285e303l, + 0x1678b01688b7de75l }, + 0 }, + /* 64 << 72 */ + { { 0x96649933aed1d1f7l,0x566eaff350563090l,0x345057f0ad2e39cfl, + 0x148ff65b1f832124l }, + { 0x042e89d4cf94cf0dl,0x319bec84520c58b3l,0x2a2676265361aa0dl, + 0xc86fa3028fbc87adl }, + 0 }, + /* 65 << 72 */ + { { 0x5db4884124627d04l,0xf92740766f7e3febl,0xd09eb11773496240l, + 0xd48e51419a6b9ec9l }, + { 0xcbb2ac97b7336e27l,0xe794fb760640bf6cl,0xc0b7f78dc7c7fa3fl, + 0x1355d071fd2edbb9l }, + 0 }, + /* 71 << 72 */ + { { 0x575d9724e84e25a3l,0x068690a13d4d8708l,0x8a7b1c6c54dd62d0l, + 0x8c45e1b37f88e231l }, + { 0x38c665466d85afe2l,0x65231642e1d69f1bl,0xb71c53a090687ec1l, + 0xdf8469d777fb5981l }, + 0 }, + /* 77 << 72 */ + { { 0xb920b503144fe6bcl,0x54b0f0593914c130l,0x63188d5a8269b650l, + 0x8d7780962fc7064dl }, + { 0xbf7b0eec5e50839al,0xaf8a7ddbe242cd06l,0x93df850809cecdb9l, + 0x4db58a72410659e9l }, + 0 }, + /* 83 << 72 */ + { { 0x460d9b383baba3cdl,0x52386e4d2cf860b8l,0xd224fe5da3924b9al, + 0xe4a4be7bcf14d813l }, + { 0xb0759e82ed3774fdl,0x57c064b38d9b6c59l,0x301ab902aee183d0l, + 0xf1c873495ba207c3l }, + 0 }, + /* 89 << 72 */ + { { 0xe8245b0a6dd58696l,0x0714eedb61091043l,0x7d9874459101129bl, + 0x4a7f1f03a0b27a21l }, + { 0x282e5cff71ee2045l,0x25c694a3da5c6b41l,0xb3d8e21f5542ca55l, + 0x57d64170e3601af0l }, + 0 }, + /* 95 << 72 */ + { { 0x9c8e86c6c6c4fee6l,0x70194db5a596119bl,0xfc6271d30e06050cl, + 0x17d94c89b15f18d2l }, + { 0x76c9e9bd49817224l,0x42621638b989c5bcl,0x1e9c4cbeb769d70cl, + 0x85e227c3b87f2783l }, + 0 }, + /* 101 << 72 */ + { { 0x146185d2117e73c5l,0xbf6214696dc38116l,0x9af9d9b5459e72cbl, + 0x7512882fb3930b85l }, + { 0xfe935379d36583b8l,0xb83ad35e7c7fdcdel,0x093ca0ab2658ae4bl, + 0xc9b16d60a756681bl }, + 0 }, + /* 107 << 72 */ + { { 0x12c24d9195d3519bl,0x1fc6db1bdb43fd06l,0x1ae49fed25bbde51l, + 0x27072e0b76d2827bl }, + { 0xdcb92e05aeb8c47fl,0x601d414056145f67l,0xcb7002652a39e8f7l, + 0x6ce9facc35620d8cl }, + 0 }, + /* 113 << 72 */ + { { 0x5c428a5ebd702c22l,0xcb6863291616129dl,0xe6278994eabcb9a1l, + 0xb409a10b9327e540l }, + { 0x6899f7cb66cf96aal,0xa9225f051c64b545l,0x00c5522ee3feec21l, + 0x35503728e083315cl }, + 0 }, + /* 116 << 72 */ + { { 0x1916d88cf1600077l,0x1ac9c238e3a58b2bl,0x3080df8535f3508dl, + 0x86cc18712744912bl }, + { 0x56aec9d5ccd15044l,0x8dd9061a5db0ab17l,0x84d6bc4e2c84171dl, + 0xd569c7d70989a5bdl }, + 0 }, + /* 119 << 72 */ + { { 0x24446b2702af35abl,0x071710478eea4565l,0xba4989db728306e6l, + 0x2cd692a85954a558l }, + { 0x644e02763576b32el,0x7efdb65c1f9fe65dl,0x04b2828e8796c048l, + 0xcfd22481187b979bl }, + 0 }, + /* 125 << 72 */ + { { 0xa10d104084ea9701l,0x27dd0dcb415e187dl,0xf667c5e939bfe45cl, + 0x3995e4ae55b67506l }, + { 0xb25117d9b5a14801l,0xeee58525fe142e92l,0x100b856a6dbae9f1l, + 0xada7057629586658l }, + 0 }, + }, + { + /* 0 << 80 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 80 */ + { { 0xe4050f1cf1c367cal,0x9bc85a9bc90fbc7dl,0xa373c4a2e1a11032l, + 0xb64232b7ad0393a9l }, + { 0xf5577eb0167dad29l,0x1604f30194b78ab2l,0x0baa94afe829348bl, + 0x77fbd8dd41654342l }, + 0 }, + /* 3 << 80 */ + { { 0xa2f7932c68af43eel,0x5502468e703d00bdl,0xe5dc978f2fb061f5l, + 0xc9a1904a28c815adl }, + { 0xd3af538d470c56a4l,0x159abc5f193d8cedl,0x2a37245f20108ef3l, + 0xfa17081e223f7178l }, + 0 }, + /* 4 << 80 */ + { { 0x1fe2a9b2b4b4b67cl,0xc1d10df0e8020604l,0x9d64abfcbc8058d8l, + 0x8943b9b2712a0fbbl }, + { 0x90eed9143b3def04l,0x85ab3aa24ce775ffl,0x605fd4ca7bbc9040l, + 0x8b34a564e2c75dfbl }, + 0 }, + /* 5 << 80 */ + { { 0x5c18acf88e2f7d90l,0xfdbf33d777be32cdl,0x0a085cd7d2eb5ee9l, + 0x2d702cfbb3201115l }, + { 0xb6e0ebdb85c88ce8l,0x23a3ce3c1e01d617l,0x3041618e567333acl, + 0x9dd0fd8f157edb6bl }, + 0 }, + /* 7 << 80 */ + { { 0x516ff3a36fa6110cl,0x74fb1eb1fb93561fl,0x6c0c90478457522bl, + 0xcfd321046bb8bdc6l }, + { 0x2d6884a2cc80ad57l,0x7c27fc3586a9b637l,0x3461baedadf4e8cdl, + 0x1d56251a617242f0l }, + 0 }, + /* 9 << 80 */ + { { 0x892c81a321175ec1l,0x9159a505ee018109l,0xc70130532d8be316l, + 0x76060c21426fa2e5l }, + { 0x074d2dfc6b6f0f22l,0x9725fc64ca01a671l,0x3f6679b92770bd8el, + 0x8fe6604fd7c9b3fel }, + 0 }, + /* 10 << 80 */ + { { 0xce711154b6e00a84l,0xd9fe7e4224890e60l,0xd10bc6c34560988fl, + 0xbdc2ef526859b004l }, + { 0xdcf0d868d5c890eel,0x893115e6119c47dcl,0xe97966fbee714567l, + 0x117813355c85aa53l }, + 0 }, + /* 11 << 80 */ + { { 0x71d530cc73204349l,0xc9df473d94a0679cl,0xc572f0014261e031l, + 0x9786b71f22f135fel }, + { 0xed6505fa6b64e56fl,0xe2fb48e905219c46l,0x0dbec45bedf53d71l, + 0xd7d782f2c589f406l }, + 0 }, + /* 13 << 80 */ + { { 0x06513c8a446cd7f4l,0x158c423b906d52a6l,0x71503261c423866cl, + 0x4b96f57093c148eel }, + { 0x5daf9cc7239a8523l,0x611b597695ac4b8bl,0xde3981db724bf7f6l, + 0x7e7d0f7867afc443l }, + 0 }, + /* 15 << 80 */ + { { 0x3d1ab80c8ce59954l,0x742c5a9478222ac0l,0x3ddacbf894f878ddl, + 0xfc085117e7d54a99l }, + { 0xfb0f1dfa21e38ec2l,0x1c7b59cb16f4ff7fl,0x988752397ea888fel, + 0x705d270cb10dc889l }, + 0 }, + /* 16 << 80 */ + { { 0xe5aa692a87dec0e1l,0x010ded8df7b39d00l,0x7b1b80c854cfa0b5l, + 0x66beb876a0f8ea28l }, + { 0x50d7f5313476cd0el,0xa63d0e65b08d3949l,0x1a09eea953479fc6l, + 0x82ae9891f499e742l }, + 0 }, + /* 17 << 80 */ + { { 0xd7c89ba1e7d1cefdl,0xcb33553a9a91e03dl,0xa01caaff59f01e54l, + 0x4a71c141de07def7l }, + { 0xe1616a4034d467d1l,0x6f395ab2e8ba8817l,0xf781ea64e45869abl, + 0x8b9513bb7134f484l }, + 0 }, + /* 19 << 80 */ + { { 0x0b0ec9035948c135l,0xaee219539a990127l,0x9d15ba0eb185dda1l, + 0xd87bc2fb2c7d6802l }, + { 0x05a480307a82d7f8l,0x7b591ce4e7e11ec3l,0x14d4cc22a0e15fdbl, + 0xf2d4213576def955l }, + 0 }, + /* 21 << 80 */ + { { 0xd56d69e4117a5f59l,0xcae6008a01286e97l,0x716a0a282dab13b0l, + 0xc821da99b3a8d2d0l }, + { 0x6898b66239c305e6l,0xe42d3394c8b61142l,0x54c1d2b253b16712l, + 0x3cec3953a01f4be6l }, + 0 }, + /* 23 << 80 */ + { { 0x5bd1e3036951b85el,0x1a73f1fb164d79a4l,0x6e77abd39fb22bc3l, + 0x8ae4c181b3d18dfdl }, + { 0xdd4226f5a6a14ed1l,0x620e111feb4e1d92l,0xffce6e59edca4fe8l, + 0x39f5fc053d0a717dl }, + 0 }, + /* 25 << 80 */ + { { 0xef8fa78cd91aff44l,0x6f3f9749bdc03be7l,0x171545f8b8596075l, + 0xbe31a73e2af132cel }, + { 0x5b4e174123884e1dl,0x4373357ea9fa75f0l,0x8dba2731bc06f49el, + 0xa09aebc877fa6de8l }, + 0 }, + /* 27 << 80 */ + { { 0xd4974e518293e18cl,0x1e4cfc5331ec0e8fl,0x80b4258325d40b1el, + 0x5cfb73a2a85f7588l }, + { 0xe553efd204c0e00bl,0xdaa6750e9a48ac39l,0xf20936b00abda06al, + 0xbfd3c7e4bf85771cl }, + 0 }, + /* 28 << 80 */ + { { 0x72669c3c7292495cl,0xa627e2dd82786572l,0xbdbfce5cd39c3e3dl, + 0xba6164927feed3d6l }, + { 0x4eb5f513e77b7318l,0x133f2e834337c2e0l,0xdea20f07f408bec6l, + 0x848a8396e3c87655l }, + 0 }, + /* 29 << 80 */ + { { 0x3086643551138f2bl,0x1176d8e6108a36bal,0xd78b3b400d4d4b66l, + 0x99ddd9bd956dbff1l }, + { 0x91dfe72822f08e5fl,0x7fd8cfe6a081ac4el,0x8ebb278ed75285c2l, + 0x2335fe00ef457ac0l }, + 0 }, + /* 31 << 80 */ + { { 0xe9d79c50f058191al,0x6749c3b05d3183f8l,0x5edc2708dbfeb1ecl, + 0x2c18f93621275986l }, + { 0x3a093e1f0703389fl,0xdf065e4a3ef60f44l,0x6860e4df87e7c458l, + 0xdb22d96e8bfe4c7dl }, + 0 }, + /* 33 << 80 */ + { { 0xb7193811b48dad42l,0x23b9dca320ad0f0cl,0x55511ffb54efb61bl, + 0xac8ed94626f9ce42l }, + { 0xa42b4bc73fc4cbd9l,0x2a4670905c6f8e39l,0xb50040f87eb592del, + 0x6633f81bdc2541f3l }, + 0 }, + /* 34 << 80 */ + { { 0xc104e02ed2d6d9c2l,0xa4876e870302517al,0x0263c9b2912f5005l, + 0x902f364a3d89d268l }, + { 0x76070565bb20a5a8l,0xa3a8977452109e98l,0x51fbffec463aa476l, + 0xfa8519625daa1503l }, + 0 }, + /* 35 << 80 */ + { { 0xe449dd8f82a9a4f3l,0xa1a2f405797e6b36l,0x76913537787785e8l, + 0x0315a3cfe064481el }, + { 0xc02291ee83df11e2l,0x5b59a0e9bcd178f0l,0xd5e8d10ce6b4c63al, + 0x9eee599f3fc60a82l }, + 0 }, + /* 36 << 80 */ + { { 0x051e589759621468l,0xb92c06327293621el,0xee17ea647762e4f2l, + 0x412107a771abd28cl }, + { 0xa083d87bf02d65ebl,0xbd4a3f165594395el,0x1d5694337c8882f3l, + 0xc5eb10c55f9c63cfl }, + 0 }, + /* 37 << 80 */ + { { 0x4b196728c8e62c4el,0x03dbd04cb74a757cl,0xe960a65b8520f044l, + 0x9eda0f33f7937337l }, + { 0x06ff0b86b6dc7dfbl,0x3bd276c11fc1ac35l,0x0e67055b1b255c27l, + 0xe43ae552eff899f8l }, + 0 }, + /* 39 << 80 */ + { { 0xc64c914d3b156d76l,0x784c1f61d794345dl,0xcda0c77c365d7a50l, + 0xcc5a1e205b32dbd0l }, + { 0x2f4e78bff90b6ac0l,0xbead62f9a2d4862dl,0xa8f67e7dcc346b53l, + 0xa38d7ae947e59dbdl }, + 0 }, + /* 40 << 80 */ + { { 0x7dc1605d480aca4dl,0x08c37750ef263aabl,0xd5c6b7c93f166725l, + 0xf99982f30ff2853bl }, + { 0xc61b9583a8ecb64al,0x041211a91b771741l,0x50ba64154e156f97l, + 0xb6595ea871b8954el }, + 0 }, + /* 41 << 80 */ + { { 0x4ae760845eb3b4eel,0xcafefdc6c62ed274l,0x4eabeacf113f790bl, + 0x10c2cc88a5ff64c9l }, + { 0xe7b59f8a49965d80l,0xd04884b50df07712l,0x6316ac5ba5f7bab1l, + 0x388111d99e78a075l }, + 0 }, + /* 43 << 80 */ + { { 0x8d437128f24804efl,0x12a687dd7b71dd53l,0x8b8f71d96139a60el, + 0xb047fed42a095ec7l }, + { 0xef238041fba59ee8l,0x61b17fac64045514l,0x45b1cf4857afa184l, + 0x8592c50a4bff5fc5l }, + 0 }, + /* 44 << 80 */ + { { 0x2830592394b745dcl,0x53e9ec16b09cb993l,0x59d0b57f9a134ed1l, + 0x89d7b439c56ee0ebl }, + { 0xc3656539991e22a2l,0xd27a89372a345043l,0x55dd5341064038eel, + 0xc9ee3f0348cb42efl }, + 0 }, + /* 45 << 80 */ + { { 0x08518c631d56c1cbl,0x5650f79f31235521l,0x33fc08d648911017l, + 0xbb8b58538a0a33c8l }, + { 0xb54554f2f869a62al,0x67f8cf48222457e5l,0x46e13911f276cc0dl, + 0x4b3a2ad6943b389el }, + 0 }, + /* 46 << 80 */ + { { 0x0e72b816b11a4c9dl,0x919b2738e9028fa4l,0xab80e1117698a5d6l, + 0xcd7950f56cd49adal }, + { 0x0db75c908dfb13a5l,0x2178578770f12cebl,0xfab72d5243486ff6l, + 0x66d55d726a0673ebl }, + 0 }, + /* 47 << 80 */ + { { 0xe98014b922667519l,0x7fcab2b3a95da9c0l,0x9bdbccd8438d5060l, + 0xa72fff5455a726b6l }, + { 0x7ae032943a5e769bl,0xf7291e9b559a0734l,0x18ae4f182ce18eeel, + 0x88e49f7328b7b4f0l }, + 0 }, + /* 48 << 80 */ + { { 0x90fe7a1d214aeb18l,0x1506af3c741432f7l,0xbb5565f9e591a0c4l, + 0x10d41a77b44f1bc3l }, + { 0xa09d65e4a84bde96l,0x42f060d8f20a6a1cl,0x652a3bfdf27f9ce7l, + 0xb6bdb65c3b3d739fl }, + 0 }, + /* 49 << 80 */ + { { 0xc6a2923e60ef9d87l,0xac66cdd8c3a64f1cl,0x069292d26e0bb0ccl, + 0x9e491414451e52a0l }, + { 0x2e76cedf0e0d35b3l,0x311b7ae9af682b84l,0xaa1017a02f90b176l, + 0xac0b43a794feb6e8l }, + 0 }, + /* 51 << 80 */ + { { 0x7ddb42f9214e82f5l,0x91c88566f67269d7l,0x1763ed8cdd0ff422l, + 0x045dd690ad284ddfl }, + { 0x5713bbb141e48fe7l,0xdc5bef28f8eb580fl,0x4bd0b288ed2992c2l, + 0x436587faaf5ef2b3l }, + 0 }, + /* 52 << 80 */ + { { 0xbbc1a48d6e5822c4l,0x16c3135daacebd02l,0xd0c6c543b56157dfl, + 0xae249a0ef49f44a1l }, + { 0x1f2c23ce72c47341l,0x8f52dc2a25974313l,0x2c99bc0a958e0e6bl, + 0xe57eab6b950cd492l }, + 0 }, + /* 53 << 80 */ + { { 0xea66db638934efc0l,0x7bfe479193c6f7c7l,0x78438d535ef90d99l, + 0xe63b87c9c665736dl }, + { 0x6de32d82db49e1bbl,0xbfa877dcd0ad1648l,0xdb2e85de1197806dl, + 0x74e9dbd3cfee7854l }, + 0 }, + /* 55 << 80 */ + { { 0xd2c26e2edb6d7e0al,0x9103119a531009cdl,0xb5dc49869a8b9d54l, + 0x4781b83bb408b427l }, + { 0x70d98b2ccb4ba2f7l,0x112ed5d7fa8a36b8l,0x97257bc6fdde1675l, + 0xd2a9c711db211cb7l }, + 0 }, + /* 57 << 80 */ + { { 0xe4aa6a06ee79fe8cl,0x06e210233dff8a54l,0x63e11ac5bf50731al, + 0xb8b9944f544125b8l }, + { 0xcba92c41d359aeb0l,0xd201c893249bca36l,0xfe79bd77cb501216l, + 0x694b21488d525ba4l }, + 0 }, + /* 59 << 80 */ + { { 0x60c90e11ee3dde2al,0x7df08e17bb36c4a2l,0xb6c3210dcc5b3c17l, + 0xa814180955cec91cl }, + { 0xf4ecbc05a8193dffl,0xf43cdef8da5744fal,0x4895a6c6f12f8a2el, + 0x44282692eb7b910al }, + 0 }, + /* 60 << 80 */ + { { 0x1a405e1886d6e13al,0x6a18c91827a7c67cl,0xc34877ebe127bfd7l, + 0x3c9fab08c098e692l }, + { 0xfe2dc65bc2066586l,0xb107603a8f68a0a9l,0x74ef0ef8127cd340l, + 0xfe577b5b86788d87l }, + 0 }, + /* 61 << 80 */ + { { 0xdc7ff83c71234c81l,0xee48d9c6d868c82fl,0xb80bac5e37e4f365l, + 0x2bfbe94efcb951c2l }, + { 0x55829049a374d0b0l,0x2a502cada87a5fb4l,0x0742ac9d9ee840bal, + 0x7689bf53eecd05b1l }, + 0 }, + /* 63 << 80 */ + { { 0x0e7f459320059c22l,0x47c273e0e49368a2l,0x5ccb960ac6946ee2l, + 0xd8209ec48b3271b6l }, + { 0x7fd5142cdfb9e947l,0x46a89c83ff737ab1l,0xa45f6b0282d875ecl, + 0x19a16e0e34c296d6l }, + 0 }, + /* 64 << 80 */ + { { 0xeb5ddcb6ec7fae9fl,0x995f2714efb66e5al,0xdee95d8e69445d52l, + 0x1b6c2d4609e27620l }, + { 0x32621c318129d716l,0xb03909f10958c1aal,0x8c468ef91af4af63l, + 0x162c429ffba5cdf6l }, + 0 }, + /* 65 << 80 */ + { { 0x65c93be33607927bl,0x86feaaecdae5411dl,0x4a1686c6dd2e2c3dl, + 0xf78200068acdf51dl }, + { 0xf82c4d0239ed3e50l,0x5ac04047b4c3a4a4l,0xbdd14d7ec34b07a7l, + 0x9911d7027cc12db5l }, + 0 }, + /* 71 << 80 */ + { { 0x4ed5dbbd1751abc9l,0xaf374229a23cc54al,0x9b5fa66ea4ed3f9al, + 0xc56dd9613d380643l }, + { 0x7d77897144b38021l,0xdf4712d0d3584508l,0x0018e2eecd7ab168l, + 0xc8a3a166293d29a7l }, + 0 }, + /* 77 << 80 */ + { { 0x34681bdb3a5a0214l,0xe188d6f1f718797el,0xaa751de7db761c5fl, + 0x347c50324959a5cel }, + { 0x108705fc338be49cl,0x1dc5eada95abf7a8l,0xb863808f0fc3f0b7l, + 0x529c27c1a05c4d43l }, + 0 }, + /* 83 << 80 */ + { { 0xa75f90677f699f79l,0xd01cf9c866356f99l,0xf90f9b73fdfbaae7l, + 0xe0b5f4412c304d2fl }, + { 0x17cbfb11807f3f57l,0xe902d542af8a9eb4l,0x3335285461f89b4al, + 0x3a51c54d3628c0ael }, + 0 }, + /* 89 << 80 */ + { { 0xae5fd487c704212dl,0x82dd07a565e2e32cl,0x46d4c9646c19c199l, + 0xe7f428593778eedcl }, + { 0x084a4e9b6dcc5ec9l,0x757e04ba2d0538b7l,0x4ec0a573a3fba4cdl, + 0x2432a4e5c627c2fcl }, + 0 }, + /* 95 << 80 */ + { { 0xfde00b3094c8a424l,0x20a57d8cd224c232l,0xd6ace1a170019992l, + 0x1a648d40697e67a3l }, + { 0xed1fb10691338d84l,0x828004a08372bfc8l,0xb93030fefad3bfedl, + 0x883dea23f27369ecl }, + 0 }, + /* 101 << 80 */ + { { 0xfbbf36a62a710d73l,0x8db834024b3cc6bbl,0xa60c47cf16d7b1fcl, + 0xf9778fa6cd16ce8fl }, + { 0xd77023086d14a1a6l,0x01f139cb06e8247cl,0xd89af2979770b9c1l, + 0x94bf1ca97d9fb550l }, + 0 }, + /* 107 << 80 */ + { { 0xe17e2e6dc2d45f34l,0x5969d8ee26efc6cbl,0x6f175231b9219cfbl, + 0x027f333c189f1175l }, + { 0x5bc60fad54f6da49l,0xc52e09af8ae5c3f3l,0x6c0e3927ed07f46dl, + 0xbfd9e598f39cf16bl }, + 0 }, + /* 113 << 80 */ + { { 0x9dffd95b090aefb9l,0x26db7b73637224fel,0xb78a679e92e2aa0cl, + 0xfc7c824ffc8f895dl }, + { 0xdc8287e8e636b3a8l,0x6b3ccc0f28b7a639l,0x38e6e2cc653de56al, + 0x998cf6985392c3cal }, + 0 }, + /* 116 << 80 */ + { { 0xe68de79e57f0d6fal,0xe707b252ff9c06f7l,0x5613698a4a061697l, + 0xd83d6453b5390352l }, + { 0x59b007599867c708l,0xcfe24fd7b41ea7adl,0x4692abf3da5b7de6l, + 0xd99a6f3bf0c54e8fl }, + 0 }, + /* 119 << 80 */ + { { 0xe8ee870dea4addc3l,0x0d1fb29559841f3el,0xdc05b5581dba2f14l, + 0xb8bf38324e3f4600l }, + { 0x1a909e66fd57c48al,0xb65ca4c24e2d76dfl,0x0b27755ae7c60d89l, + 0x9fcfa75acb9003f6l }, + 0 }, + /* 125 << 80 */ + { { 0xbbbdf4c49e5325aal,0x6879fe11d0d1f281l,0x7a400f890633002el, + 0xc3633c779bb79ac9l }, + { 0x15a4cfae93ab9bc3l,0x379bbdea42594603l,0x7c61dfa257d2af3fl, + 0x20190537b51bfb62l }, + 0 }, + }, + { + /* 0 << 88 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 88 */ + { { 0xa80d1db6f79588c0l,0xfa52fc69b55768ccl,0x0b4df1ae7f54438al, + 0x0cadd1a7f9b46a4fl }, + { 0xb40ea6b31803dd6fl,0x488e4fa555eaae35l,0x9f047d55382e4e16l, + 0xc9b5b7e02f6e0c98l }, + 0 }, + /* 3 << 88 */ + { { 0x4b7d0e0683a7337bl,0x1e3416d4ffecf249l,0x24840eff66a2b71fl, + 0xd0d9a50ab37cc26dl }, + { 0xe21981506fe28ef7l,0x3cc5ef1623324c7fl,0x220f3455769b5263l, + 0xe2ade2f1a10bf475l }, + 0 }, + /* 4 << 88 */ + { { 0x9894344f3a29467al,0xde81e949c51eba6dl,0xdaea066ba5e5c2f2l, + 0x3fc8a61408c8c7b3l }, + { 0x7adff88f06d0de9fl,0xbbc11cf53b75ce0al,0x9fbb7accfbbc87d5l, + 0xa1458e267badfde2l }, + 0 }, + /* 5 << 88 */ + { { 0x03b6c8c7dacddb7dl,0x92ed50047e1edcadl,0xa0e46c2f54080633l, + 0xcd37663d46dec1cel }, + { 0x396984c5f365b7ccl,0x294e3a2ae79bb95dl,0x9aa17d7727b1d3c1l, + 0x3ffd3cfae49440f5l }, + 0 }, + /* 7 << 88 */ + { { 0x26679d11399f9cf3l,0x78e7a48e1e3c4394l,0x08722dea0d98daf1l, + 0x37e7ed5880030ea3l }, + { 0xf3731ad43c8aae72l,0x7878be95ac729695l,0x6a643affbbc28352l, + 0xef8b801b78759b61l }, + 0 }, + /* 9 << 88 */ + { { 0xdcdd3709b63afe75l,0xad9d7f0b3f1af8ffl,0xdd6a8045194f4beel, + 0x867724cc2f7d998cl }, + { 0xd51d0aa5837751bel,0x21d6754a959a0658l,0xd2212611695f7e58l, + 0xec4b93c2297363efl }, + 0 }, + /* 10 << 88 */ + { { 0x0ac1c5fab6ef26cfl,0xcd8ba0c5a39de8eel,0x11ba7537dd7796e0l, + 0x1215933476d58d6dl }, + { 0xf51eb76f529fda4cl,0x2fd9209ddedaa8a3l,0x555a675615efac65l, + 0xb784c9ca7fd42fe9l }, + 0 }, + /* 11 << 88 */ + { { 0x8165ec11b9d1a70fl,0x01347efc384f6cael,0xe95c01a0ab7aeca9l, + 0x459ba1c5c6c99530l }, + { 0x38967a635cf3416bl,0x5c3761fd1e5457e2l,0x43e6077af03e9df6l, + 0xb15d34628bd1c7f6l }, + 0 }, + /* 13 << 88 */ + { { 0xad87d3db35a75c49l,0xc69d800961af03c5l,0x31aef61a3a6a6c4cl, + 0xb3292640aa10a993l }, + { 0x959aae80aaee340fl,0xf900528e7f381a3bl,0x44ecf76e853691a3l, + 0xa081663ce749e68el }, + 0 }, + /* 15 << 88 */ + { { 0x4f2782136283e34al,0x6f9fcf60fbfa315fl,0x224a2ab99b701364l, + 0xb4b1b418f9fecadcl }, + { 0xbf7280fe50ba1b9al,0x7e68259c33f36db9l,0x8ccb754e154c9fb0l, + 0xf281adb1db2328f1l }, + 0 }, + /* 16 << 88 */ + { { 0xf92dda31be24319al,0x03f7d28be095a8e7l,0xa52fe84098782185l, + 0x276ddafe29c24dbcl }, + { 0x80cd54961d7a64ebl,0xe43608897f1dbe42l,0x2f81a8778438d2d5l, + 0x7e4d52a885169036l }, + 0 }, + /* 17 << 88 */ + { { 0xc2a950ad2d6608bel,0xab415e2a51c3c2b6l,0xffbd2a65f5c803e7l, + 0x3f81dc3eca908532l }, + { 0x0ec47397c28c04f4l,0xf6c632e8153f58e8l,0xccac35f8efb4a6d8l, + 0x22a1b677ee6d7407l }, + 0 }, + /* 19 << 88 */ + { { 0x276662435243c119l,0x79cb8580e707363el,0x5bf5ebf4d01682d6l, + 0x8a980173762811e0l }, + { 0xe2f2be1fc7547d77l,0x21a50fffb925fec6l,0x5e6cf2ef40115509l, + 0xb69beae18faa0fc0l }, + 0 }, + /* 21 << 88 */ + { { 0xfa147da8cec36e75l,0xba184e5a42860484l,0xe8ec25df222fb1e6l, + 0xce91dcb18ff8403cl }, + { 0xf1b0e27ead7faa32l,0x097d881d42a3a205l,0xa8865dd43f8f56d4l, + 0x624d7a451aef929dl }, + 0 }, + /* 23 << 88 */ + { { 0x3db0238ad01698e8l,0xbb7186dc00306082l,0x542f4377250f830el, + 0x34b8a67dae438c50l }, + { 0xada528a0858d8048l,0x561aa3336b57afc1l,0x8d9188e0fda35f7al, + 0x5838d1211dcad0c5l }, + 0 }, + /* 25 << 88 */ + { { 0x4f97d1529f17511dl,0x8b9f012776fdb9ebl,0x53a0a72d4056e6a7l, + 0x5ff937d64e262eeel }, + { 0xaa64a8dc489fbe6dl,0xc19947dfea02bc69l,0x76f0bbb91492c9bel, + 0xe53881098d89cd01l }, + 0 }, + /* 27 << 88 */ + { { 0x16083309456057b7l,0x2810c08040a331f6l,0x0561656c3c166929l, + 0x16f0d8d6ed1c3999l }, + { 0x37b6da7294697927l,0xd821c2cc23ca6c9cl,0x42ef1bdb8ca4351cl, + 0x7ca32bad5edfa682l }, + 0 }, + /* 28 << 88 */ + { { 0xdc1de17d98119f10l,0x74353c5d488c36a6l,0x14aaf33a3d8e23dfl, + 0x31e075c078baf593l }, + { 0x0f7ca03a46d1ca3cl,0x99c5e3ac47b660c7l,0x70d0241388fe2e59l, + 0x2e9a6be12a7ec005l }, + 0 }, + /* 29 << 88 */ + { { 0x4d1f087f184252b1l,0xfd3ace273f5b49c6l,0x6e874447bbb04da2l, + 0x2347e3a1b3767ff0l }, + { 0x990d4010f868966al,0x35320090dd658b5el,0x1105bfb974fe972al, + 0x3961f7dc8e7ad2c6l }, + 0 }, + /* 31 << 88 */ + { { 0x100d8b54741e3286l,0x65d9108ef3abc7afl,0x172b450620ef8fbcl, + 0x11bd7db2d81b8a2el }, + { 0xf89210e1e8e41de5l,0x910613f3d98a868bl,0xbfc85241849aa909l, + 0x68a43e21c7d3a7cal }, + 0 }, + /* 33 << 88 */ + { { 0x68f891479a4f8293l,0x48262328a5eb9101l,0x7eca2a178fe218b5l, + 0xde6c22dbc733f768l }, + { 0xde7171d108d6084dl,0xd153827a0f0f8092l,0xc7b52d8f85a9252fl, + 0xfa29ca3a5708b31fl }, + 0 }, + /* 34 << 88 */ + { { 0x20518ddf9e0ad7e7l,0x33d5d079e8d28b9bl,0x1149b393d13058b0l, + 0x708cc65586d4651dl }, + { 0xd7fefaa694207435l,0xce882c0d96312f8fl,0x2fd5cb2059d091a7l, + 0x4533a88a0e1ece94l }, + 0 }, + /* 35 << 88 */ + { { 0xceddd9b5a59c28bcl,0xaa4808f9572e2a5dl,0x38bc191999014a1el, + 0x1aacefdaa6d85686l }, + { 0xa59283d42a573fddl,0x84359db29c387594l,0x79994773dca3acc8l, + 0xe4323e7654cf7653l }, + 0 }, + /* 36 << 88 */ + { { 0xac449695241fbd6fl,0x67c9b170081c1223l,0x16868f21b56aac6fl, + 0x34bd8fa3f8bcb721l }, + { 0x06b6bd33b6691c76l,0x6c924766381a7973l,0x6a12444ca54078dbl, + 0xd02e91a96d1051ccl }, + 0 }, + /* 37 << 88 */ + { { 0x512f5fb35f30b344l,0xb13ade169d516885l,0x18812e9b2b468802l, + 0xf15d730e6b28979al }, + { 0x5015616f6889348bl,0xe0b02a0a96af0401l,0x3b02007b61204c89l, + 0x9ece2aa7432742a4l }, + 0 }, + /* 39 << 88 */ + { { 0xd5f7e09c7c1cc4a1l,0x313ac04218b2d854l,0xbc4fe2a04c253b10l, + 0x25a696a3c7080b5cl }, + { 0x6de3cb6aef811877l,0x4d242fecd15f9644l,0xb9bfa2480ee6a136l, + 0x8122679e9c8d181el }, + 0 }, + /* 40 << 88 */ + { { 0x37e5684744ddfa35l,0x9ccfc5c5dab3f747l,0x9ac1df3f1ee96cf4l, + 0x0c0571a13b480b8fl }, + { 0x2fbeb3d54b3a7b3cl,0x35c036695dcdbb99l,0x52a0f5dcb2415b3al, + 0xd57759b44413ed9al }, + 0 }, + /* 41 << 88 */ + { { 0xc2c7daec96a8d727l,0x8a11631a17f3abf9l,0x06aba65c0ae8940al, + 0xfca280c7873d3635l }, + { 0x57496889ddb72b87l,0xaa9a3359320793d4l,0x11b6864d43120741l, + 0x1877cd4e51527639l }, + 0 }, + /* 43 << 88 */ + { { 0x8b35ce4e6f43dfc6l,0x4114b2fe9a19f3bfl,0x8c4af8024ffa45cal, + 0xa3ab5f869328b847l }, + { 0x0986de3e555f30f0l,0xaae6e3eac8cb84c4l,0x2a7dcdbaa4ba01f7l, + 0xfa32efa729f5dc6cl }, + 0 }, + /* 44 << 88 */ + { { 0x077379c00b33d3f8l,0x421883c67064e409l,0x2d0873d76c29c8f6l, + 0xbfa433a3d274c0c8l }, + { 0x56dc778f23a5891el,0xd663bf6535e2de04l,0x488fdb485db517cel, + 0x00bba55e19b226c2l }, + 0 }, + /* 45 << 88 */ + { { 0x879b30ead7260d78l,0x04954ba2eac5201fl,0x3210c0e3ff2529d1l, + 0x0743823488b470b3l }, + { 0x8b618de48854cc0dl,0x98270d5e35b795eel,0x0e47d651aa33ca37l, + 0x77d75fda1e87d0cfl }, + 0 }, + /* 46 << 88 */ + { { 0x789dbe987803fbf9l,0x940589aa17ede316l,0x032902bd85a1988cl, + 0x43cbc0031c47f7f0l }, + { 0xc6ff73714709148fl,0x769957122d9b8a5el,0xb4520e462597b70el, + 0x00d19f39f67ff3b8l }, + 0 }, + /* 47 << 88 */ + { { 0xe2dfcef9b159f403l,0xe8e9e8d8855644afl,0x2796247163fa1068l, + 0x400e992a968a5400l }, + { 0xe2b9d29f56e563c1l,0xed66759c2885fabfl,0x788b6263750abdffl, + 0x30adb00d6cbbdcacl }, + 0 }, + /* 48 << 88 */ + { { 0x1fe647d83d30a2c5l,0x0857f77ef78a81dcl,0x11d5a334131a4a9bl, + 0xc0a94af929d393f5l }, + { 0xbc3a5c0bdaa6ec1al,0xba9fe49388d2d7edl,0xbb4335b4bb614797l, + 0x991c4d6872f83533l }, + 0 }, + /* 49 << 88 */ + { { 0x5548d3423fa17b28l,0x38587952823ee731l,0x8ee9b90a0a28bcd1l, + 0xcfc029bf6676917el }, + { 0x7e08306d2a212358l,0x66a9488dc88a66bcl,0x7a09db327d7c9e65l, + 0x20eaf4e72cbc1790l }, + 0 }, + /* 51 << 88 */ + { { 0xb3095b491f2a9605l,0x7cfc4205f72691c7l,0x1544bf964d889b90l, + 0xdc44d20ba0bbae7al }, + { 0xee369b670b1f0b23l,0xf3ec25e818a7bdcbl,0xf614ab5df47ecf65l, + 0x4869762f80a4a09dl }, + 0 }, + /* 52 << 88 */ + { { 0xedbbeee78a058fb6l,0xb9d19ddcfb09121al,0xa41bb45bd34dddcel, + 0x2dbc80b900964bc4l }, + { 0x4ed9137d1d6cb654l,0x1b9016db483d01c5l,0x5fc501bc6528e22el, + 0xb2d2f8816cad646bl }, + 0 }, + /* 53 << 88 */ + { { 0xb57aa72a89043e56l,0x8fbca2435c5319fdl,0xe66aef43b13ce900l, + 0x2c7c3927c3382934l }, + { 0x434d9104a835fdf5l,0x419470b81b3b85bel,0xeaec374abeb4d448l, + 0x26a53b51f33cda51l }, + 0 }, + /* 55 << 88 */ + { { 0x421f1725bb1db793l,0x20214d4f558c94a9l,0x3371233b7696092cl, + 0x774d3fcb1902ab0el }, + { 0x4ce223ded149aecel,0x174b260e33057bc7l,0xdf70cfa3f6effee4l, + 0x3d8cd01f80880678l }, + 0 }, + /* 57 << 88 */ + { { 0x32db21862e59985cl,0x448865abaa1b39e1l,0x250ce79cd89fe98dl, + 0x962710e763e3fb10l }, + { 0xa8fc70561ac10e3el,0x9eed208fa3b132fbl,0xf499d638937051f5l, + 0x27acf7ec21a9f78fl }, + 0 }, + /* 59 << 88 */ + { { 0x148e572a4c7b445el,0xdc10a0214dc95a4fl,0xe60e9c2e02237869l, + 0xbfdfcb3aa393c3a4l }, + { 0x8b799db211a64cf0l,0x1ca865ea2e16f59fl,0x865441fbd3a17e46l, + 0x23315b9753409692l }, + 0 }, + /* 60 << 88 */ + { { 0x5e76fb2f286bad39l,0xbad9efe39dcad1e2l,0x60e75190edc7e904l, + 0x6a6f063e0fecb5a5l }, + { 0x5150ed85aed8acc3l,0xb56ccfbc6d20af6cl,0x7e0d1e982c69dbfal, + 0xabf5628a7c7e10a9l }, + 0 }, + /* 61 << 88 */ + { { 0xb84af2c00df6d61fl,0x02c651c52acbaf4bl,0xfb605754afaaa0bfl, + 0xa03f5257dff61017l }, + { 0x9e3ffb1672762093l,0x4f9a5da0c4f40bd3l,0x37dce5220d26f8e1l, + 0x260f736fc06a1a07l }, + 0 }, + /* 63 << 88 */ + { { 0xb92aba79b1077d55l,0xc52f81081a42f5f5l,0x9913f04f86e5aa99l, + 0x6814b0b1f3c7f504l }, + { 0xb7d61fd34d354bdal,0xf27926e39581d25el,0x97724001c2dc21adl, + 0x835778231d5c4788l }, + 0 }, + /* 64 << 88 */ + { { 0x77b868cee978a1d3l,0xe3a68b337ab92d04l,0x5102979487a5b862l, + 0x5f0606c33a61d41dl }, + { 0x2814be276f9326f1l,0x2f521c14c6fe3c2el,0x17464d7dacdf7351l, + 0x10f5f9d3777f7e44l }, + 0 }, + /* 65 << 88 */ + { { 0x53857462ff9727a2l,0xe6870e7dc68488e7l,0x276da72808c79656l, + 0x1308eb61d86c24ebl }, + { 0x34c43a84db0a3e56l,0x03961b5525335a59l,0xf9bc2d5805689d86l, + 0xfa4d3c01eb29d6d6l }, + 0 }, + /* 71 << 88 */ + { { 0xd07dac3037d10ffal,0xb2b0a0fd8bef0a79l,0xa2e804510ec02505l, + 0xf256c18962f55f5fl }, + { 0x0ca3f9b10b39f4f0l,0x7bf4e1cf3bb7c8e9l,0x7a8a43f8ee11f227l, + 0x2ad8431a3e4056ebl }, + 0 }, + /* 77 << 88 */ + { { 0xb8cf71ed031c1871l,0x702431806f703102l,0x9a87e1c24ec6f1b0l, + 0xf7e6e5b4664f275dl }, + { 0xc70a8b4e8c76b505l,0x6ba69bf2a002e9cfl,0x33ed74f7a0d8c9bfl, + 0x17f5f4b18d9989del }, + 0 }, + /* 83 << 88 */ + { { 0xcd116dcb1b13a4a1l,0x591adb831c369877l,0x697be1aca6b8e80bl, + 0xb2d4baa1b975d781l }, + { 0xd4a9a496b16b48e7l,0x64de2d7af293997dl,0x039ae039af09a492l, + 0x66e31a2665f3a485l }, + 0 }, + /* 89 << 88 */ + { { 0x110a8a42fec01a53l,0x1f5fcc1b38affab8l,0x757310ca9941a19el, + 0x11ef95f76c29d6cbl }, + { 0x0756bdb22dd427bal,0x8de8d44af3e16c33l,0xf9d28355e25aec52l, + 0xeb761efc02f36465l }, + 0 }, + /* 95 << 88 */ + { { 0xfc83bf7454bfcd7al,0x51d861794837b6bel,0x8165b3f9801a324dl, + 0x3a5972bc634cfd61l }, + { 0xeecfe6d825258ed6l,0x51d968df1451ced0l,0x3010cdb8316aa0ael, + 0xc295b8522900eaf2l }, + 0 }, + /* 101 << 88 */ + { { 0x5ad434a3890cc798l,0x4c17ff5e1531bce4l,0x825b5b5a5ea8e26fl, + 0xacca9d5dd66fd7b3l }, + { 0xb647dbde37ae6f92l,0xa5594868f3600416l,0x7b90ac53ab0c5d63l, + 0x4b66ad7ceb43e1d0l }, + 0 }, + /* 107 << 88 */ + { { 0x04a211fac09ccbffl,0x9c96ad9ee873d898l,0x9eb1deb69c481f86l, + 0xb3616ce8b2d70298l }, + { 0x67a6fe9b9073726dl,0x5b8aa37d4c9bf744l,0xf558603ebb6aa0efl, + 0x72767f5103d304fbl }, + 0 }, + /* 113 << 88 */ + { { 0x787cb8b8d6e9b7e3l,0x8bb30222e079fc68l,0x651a2ea6e3145a0bl, + 0x0254c5da9ab18fa8l }, + { 0x83722ffc12e1611fl,0xb0ddf1ffa7cc61bel,0x7c9c7e10ac0ac8d7l, + 0x8241a8191da12218l }, + 0 }, + /* 116 << 88 */ + { { 0x70bb7719bc407e6el,0x231328efd84ceb41l,0x8bca6a1fc104bb20l, + 0xd6f4e425280b9071l }, + { 0xb41b95a292896a82l,0x735cf435fa34df67l,0xbc331a08d9d6d769l, + 0x579786052682747el }, + 0 }, + /* 119 << 88 */ + { { 0x048ba499eb3af9a9l,0x43a8c367d50b82cel,0xedf9e2b21e0724d9l, + 0x3098aab3d607140bl }, + { 0xd1f18f1e5ed49eb9l,0xf9c6bb6ae0bb02a2l,0x204f96aa0cd245ddl, + 0xdaadaf4afb011ed5l }, + 0 }, + /* 125 << 88 */ + { { 0xb298ce2de50404b1l,0x04dd38c45bf9b581l,0x229deabdfada51e8l, + 0x74bd233f8788a132l }, + { 0x951ba5ecf03e6c30l,0x9da2f5aa45bf1a41l,0x6bec7fea7e52b860l, + 0x76e3778964b0a9ddl }, + 0 }, + }, + { + /* 0 << 96 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 96 */ + { { 0x4fe7ee31b0e63d34l,0xf4600572a9e54fabl,0xc0493334d5e7b5a4l, + 0x8589fb9206d54831l }, + { 0xaa70f5cc6583553al,0x0879094ae25649e5l,0xcc90450710044652l, + 0xebb0696d02541c4fl }, + 0 }, + /* 3 << 96 */ + { { 0xb99f0e0399375235l,0x7614c847b9917970l,0xfec93ce9524ec067l, + 0xe40e7bf89b122520l }, + { 0xb5670631ee4c4774l,0x6f03847a3b04914cl,0xc96e9429dc9dd226l, + 0x43489b6c8c57c1f8l }, + 0 }, + /* 4 << 96 */ + { { 0x0e299d23fe67ba66l,0x9145076093cf2f34l,0xf45b5ea997fcf913l, + 0x5be008438bd7dddal }, + { 0x358c3e05d53ff04dl,0xbf7ccdc35de91ef7l,0xad684dbfb69ec1a0l, + 0x367e7cf2801fd997l }, + 0 }, + /* 5 << 96 */ + { { 0x46ffd227cc2338fbl,0x89ff6fa990e26153l,0xbe570779331a0076l, + 0x43d241c506e1f3afl }, + { 0xfdcdb97dde9b62a3l,0x6a06e984a0ae30eal,0xc9bf16804fbddf7dl, + 0x170471a2d36163c4l }, + 0 }, + /* 7 << 96 */ + { { 0x361619e455950cc3l,0xc71d665c56b66bb8l,0xea034b34afac6d84l, + 0xa987f832e5e4c7e3l }, + { 0xa07427727a79a6a7l,0x56e5d017e26d6c23l,0x7e50b97638167e10l, + 0xaa6c81efe88aa84el }, + 0 }, + /* 9 << 96 */ + { { 0x473959d74d325bbfl,0x2a61beec8d6114b9l,0x25672a94924be2eel, + 0xa48595dbf2c23d0cl }, + { 0xe476848b6a221838l,0xe743e69a35c1b673l,0x2ab42499d8468503l, + 0x62aa0054e9e90ba7l }, + 0 }, + /* 10 << 96 */ + { { 0x358d13f1bc482911l,0x685d1971b7fa7f26l,0x3e67a51d2be1aee4l, + 0xe041850998d114a9l }, + { 0x59639f604e052561l,0x32075c49155d0818l,0x2aa2343b67b64b1cl, + 0x1b445e2967f53e6al }, + 0 }, + /* 11 << 96 */ + { { 0xbdfb271773a904e0l,0x7ce1e40b28888d73l,0x2e7e35f6eaa97d1bl, + 0xd061772aa9afa097l }, + { 0x434ac7c47a1f7c59l,0x6e21124ae79b7b9al,0x055acff3bb22ecc7l, + 0x8bfd7ac984c858d3l }, + 0 }, + /* 13 << 96 */ + { { 0x2fd57df59f1f68adl,0x5ddcc6dbb06470c8l,0x801b6451a9b47307l, + 0x6b51c8e376551bf4l }, + { 0xef0bd1f7d44e1da9l,0x714bcb1d4d4e600cl,0xc57bb9e40c6540c7l, + 0x71bd1ec2327cc644l }, + 0 }, + /* 15 << 96 */ + { { 0x9a52cf7e7f4dd81fl,0xa0132be15e69c05el,0x90dab7472a0f4d72l, + 0xc142f911312d6706l }, + { 0xe8d3631f8261998bl,0xf0f42fae615c1c94l,0x2f4e948caec3fa5dl, + 0x242ae7a8a374101el }, + 0 }, + /* 16 << 96 */ + { { 0x0f893a5dc8de610bl,0xe8c515fb67e223cel,0x7774bfa64ead6dc5l, + 0x89d20f95925c728fl }, + { 0x7a1e0966098583cel,0xa2eedb9493f2a7d7l,0x1b2820974c304d4al, + 0x0842e3dac077282dl }, + 0 }, + /* 17 << 96 */ + { { 0x1fa878cad088be52l,0x89c2cb07a9e1e656l,0x385bc5c3219d62dbl, + 0xd82b676b5fda2752l }, + { 0x2449dc9ee304eafcl,0x1e9e7991632f4ea2l,0x3036e061cdd5e0b9l, + 0x75a6f6ff830825bcl }, + 0 }, + /* 19 << 96 */ + { { 0xb10fcddc449dedb4l,0x2c890042d1244acfl,0x9b3072cac7fc7017l, + 0x1acda6859ce8063fl }, + { 0xd243313c7f51e2f5l,0x52a3f1a4d73d9578l,0xda785b7a64f0ce6el, + 0x2e766315442a4c2dl }, + 0 }, + /* 21 << 96 */ + { { 0x94f9b004151f111al,0xc7a5035b07dbc5fal,0x53958ea7609e49d7l, + 0x0526b4d79013f4c0l }, + { 0x66de5ebb593e2fbdl,0x6e7cf8b44c2e0c37l,0x6f72fc8b8c983e78l, + 0x6fab9b632348f9d7l }, + 0 }, + /* 23 << 96 */ + { { 0xc748a3526a3d8468l,0x3fab479927e38032l,0x91ad3629fa430ce7l, + 0xc5af0b2c71614c44l }, + { 0xcede3fa50c211611l,0x6e6889ba02338083l,0xee0a195977f0fe32l, + 0x01ea905d0f4bbc5al }, + 0 }, + /* 25 << 96 */ + { { 0x12cfb25e8193db48l,0xddb4ae633bea708cl,0xdaae102ef181f821l, + 0x9d9d923024a089d9l }, + { 0x71c4122da0876aeal,0x1a63ea3bbbe19c09l,0x3b898076016f8d0cl, + 0xa5cccc5daea6b713l }, + 0 }, + /* 27 << 96 */ + { { 0xc3f22baf4a8e2f61l,0x77d29ede176da6a6l,0x40a55f211607da63l, + 0x858b38561452e391l }, + { 0x0dd3c267fe1b3c56l,0x66c04bdd7d55227al,0xfbd2fe55e6404e09l, + 0x5981cf49ea9cfcbcl }, + 0 }, + /* 28 << 96 */ + { { 0xe549237f78890732l,0xc443bef953fcb4d9l,0x9884d8a6eb3480d6l, + 0x8a35b6a13048b186l }, + { 0xb4e4471665e9a90al,0x45bf380d653006c0l,0x8f3f820d4fe9ae3bl, + 0x244a35a0979a3b71l }, + 0 }, + /* 29 << 96 */ + { { 0xae46a902aea870afl,0xa9b9fcf57cbedc99l,0x74f2ca3f79b7e793l, + 0xadb8f2231dbeeb28l }, + { 0x6302060e6764df85l,0x363320d257ebd554l,0xd9fd573e798d22e1l, + 0x285f85f5ebb67dedl }, + 0 }, + /* 31 << 96 */ + { { 0xd86b329211caa2b5l,0x2a26258e39337bd1l,0x4dc5a9b579c8c291l, + 0x16443d87741942e6l }, + { 0x6bc9a2f8f811400cl,0x819c69359eeb4e0el,0xe1be7273ce0c214bl, + 0x429afb8184b61581l }, + 0 }, + /* 33 << 96 */ + { { 0xb37e188756af5812l,0xd662bdb485aff83el,0xc89742d07bc63de7l, + 0xea103f9d0279f487l }, + { 0x4d26916a3a6cc639l,0x4eea3a3c7c743b94l,0x6a3e0dc7007376d9l, + 0xdb6ef3cf573f904el }, + 0 }, + /* 34 << 96 */ + { { 0x9b1058ecb0b0fb53l,0x8955f5f75f8a9a9fl,0xf5f92e7f9f6f9e6dl, + 0x03f5df6c50ec198bl }, + { 0x6c8741f2b8aedbcel,0x8f4e60cfed8018f7l,0x6ca5297c9fa01f89l, + 0x8591cf7a864995dbl }, + 0 }, + /* 35 << 96 */ + { { 0xa126147eb0a11b9bl,0xeedcc9e198900232l,0x15d94f8c2bead119l, + 0x042423cfefc38691l }, + { 0x6ce86fbe77165d91l,0xa07732126b3fd565l,0x8cdc409150b1f9c7l, + 0x7f5ad1af064595acl }, + 0 }, + /* 36 << 96 */ + { { 0xed374a6658926dddl,0x138b2d49908015b8l,0x886c6579de1f7ab8l, + 0x888b9aa0c3020b7al }, + { 0xd3ec034e3a96e355l,0xba65b0b8f30fbe9al,0x064c8e50ff21367al, + 0x1f508ea40b04b46el }, + 0 }, + /* 37 << 96 */ + { { 0x73644c158f8402a0l,0x0d9b5354f4730eb9l,0x78542af4e94cc278l, + 0xf4dbede3e395f33al }, + { 0x8fe8cbc590c70b00l,0x9c35bb2d7db197f6l,0x229b4973e6599746l, + 0x0817d04e1a84b986l }, + 0 }, + /* 39 << 96 */ + { { 0x8ffe34e95ecd09b3l,0x6a7c3de4153b7cael,0xf02713e4a81044b7l, + 0x85ca6158c70545c8l }, + { 0xd3ff392845d88bffl,0x3a251a07f0bafe89l,0x61290e1287cea7f4l, + 0xa360a17efa4808adl }, + 0 }, + /* 40 << 96 */ + { { 0x98561a49747c866cl,0xbbb1e5fe0518a062l,0x20ff4e8becdc3608l, + 0x7f55cded20184027l }, + { 0x8d73ec95f38c85f0l,0x5b589fdf8bc3b8c3l,0xbe95dd980f12b66fl, + 0xf5bd1a090e338e01l }, + 0 }, + /* 41 << 96 */ + { { 0x2d1751083edf4e2bl,0x30e6e90fa29c10d0l,0xfee1eb14c9c6ccd2l, + 0x244670c756a81453l }, + { 0x90b33eefc5185c22l,0xd77ae4b63db82d28l,0xce5ee034f228f940l, + 0x5d7660847bb47be5l }, + 0 }, + /* 43 << 96 */ + { { 0x88b7eec499b9a8c6l,0x56048d9e14e8ef0cl,0xa18f93215c89cf78l, + 0xbd2087616d327e66l }, + { 0x5b187225d9e53e27l,0xa57ca6c7bf4d0317l,0x187731d2e9557736l, + 0xd4ce2f78a874982el }, + 0 }, + /* 44 << 96 */ + { { 0x65163ae55e915918l,0x6158d6d986f8a46bl,0x8466b538eeebf99cl, + 0xca8761f6bca477efl }, + { 0xaf3449c29ebbc601l,0xef3b0f41e0c3ae2fl,0xaa6c577d5de63752l, + 0xe916660164682a51l }, + 0 }, + /* 45 << 96 */ + { { 0xf5b602bb29f47deal,0x42853c9659ddd679l,0x5c25be4041d7c001l, + 0x8e069399d4a3b307l }, + { 0x1782152e736ce467l,0x2e264109c9cb4f08l,0xf900cb11ab124698l, + 0x1bbed1d02d6e05b1l }, + 0 }, + /* 46 << 96 */ + { { 0x9cc3fedc7da08b1fl,0x0f44949361d5ed38l,0xc8cbc4209b991b6bl, + 0xee62a342891c42e1l }, + { 0x11c496bb1a179139l,0x94ece2892eac4d8el,0x35f303a5a98d5570l, + 0x69d4340514a31552l }, + 0 }, + /* 47 << 96 */ + { { 0x29d45e50892dfcbal,0x653e613e5c30cee3l,0x7b8c1ae61868a348l, + 0x40ab51654f2c612al }, + { 0x56e977f9891cdc8cl,0xee1ca12a34ca7cd1l,0xa4e283ee17b5ddf8l, + 0x4e36f2fb6f536205l }, + 0 }, + /* 48 << 96 */ + { { 0x5a3097befc15aa1el,0x40d12548b54b0745l,0x5bad4706519a5f12l, + 0xed03f717a439dee6l }, + { 0x0794bb6c4a02c499l,0xf725083dcffe71d2l,0x2cad75190f3adcafl, + 0x7f68ea1c43729310l }, + 0 }, + /* 49 << 96 */ + { { 0xa3834d85e89ea13fl,0x2ca00f942db803bbl,0x0f378681400ed3dal, + 0x1028af6b54854da3l }, + { 0x3928c2da06400c7fl,0x21119785d82aac92l,0x06618c17724e4af0l, + 0x22b42b161470736bl }, + 0 }, + /* 51 << 96 */ + { { 0x7d0cfd48f7f2ac65l,0x46e1ac705f641b60l,0x0ab9566a0fcf0137l, + 0xbd4380e0db460fb8l }, + { 0x4550efbf6db99b55l,0x33846e669764b744l,0xacffa0cae34ca007l, + 0xce642d6a077e646cl }, + 0 }, + /* 52 << 96 */ + { { 0xe747c8c7b7ffd977l,0xec104c3580761a22l,0x8395ebaf5a3ffb83l, + 0xfb3261f4e4b63db7l }, + { 0x53544960d883e544l,0x13520d708cc2eeb8l,0x08f6337bd3d65f99l, + 0x83997db2781cf95bl }, + 0 }, + /* 53 << 96 */ + { { 0xd89112c47d8037a3l,0xcba48ad3464c2025l,0x3afea8399814a09dl, + 0x69e52260269030b5l }, + { 0x5b7067365c674805l,0x8c3fd33d87343f56l,0xc572c858b1c61edfl, + 0x43d8f4ded06749cbl }, + 0 }, + /* 55 << 96 */ + { { 0x04da1f06b4066003l,0xf7d4e52f372749e8l,0x56cd667114b38747l, + 0x1943a22a22eb6d9el }, + { 0xc2c5391990714b0al,0xb6e3abb7d13cf3ael,0xfcd8d671676115cbl, + 0x178ce1a0c06a0d3al }, + 0 }, + /* 57 << 96 */ + { { 0x94485b36913508f8l,0x92f87fe36de83b42l,0xedd476f0ed77e666l, + 0xee90fbc68da2cf53l }, + { 0x6f4afc53fc6cf3d9l,0x231bceb9f21f6ecfl,0x6504a11d494c6e9cl, + 0xd3728f032c211461l }, + 0 }, + /* 59 << 96 */ + { { 0x09a9b93799562ca2l,0xb7d5c5cf6a5a5aa8l,0x52f5d7b9987b219dl, + 0x33849f9ec38014d4l }, + { 0x299adaf628f23880l,0x738ecc8874875588l,0x39d707adca2af665l, + 0xc8c11f688f4c5f73l }, + 0 }, + /* 60 << 96 */ + { { 0x68e4f15e9afdfb3cl,0x49a561435bdfb6dfl,0xa9bc1bd45f823d97l, + 0xbceb5970ea111c2al }, + { 0x366b455fb269bbc4l,0x7cd85e1ee9bc5d62l,0xc743c41c4f18b086l, + 0xa4b4099095294fb9l }, + 0 }, + /* 61 << 96 */ + { { 0x2ae046d66aa34757l,0x34db1addaa6d7e9dl,0x2b4b7e017ccf432bl, + 0xfbe0bfa590d319c6l }, + { 0xfb2981687ec7a7f2l,0x346cc46004f5132el,0x782b2e53b40aceddl, + 0x402e1d64e3f0b8b9l }, + 0 }, + /* 63 << 96 */ + { { 0x2aa3b21d25a56088l,0xae6ee57543d08962l,0x669e42bff1e22297l, + 0x7b4c635732e3a47al }, + { 0x22b16260ea464a25l,0xad8ca59072d5cd7al,0x7c244266104eb96al, + 0x1def95e28e7c11d2l }, + 0 }, + /* 64 << 96 */ + { { 0x9c7c581d26ee8382l,0xcf17dcc5359d638el,0xee8273abb728ae3dl, + 0x1d112926f821f047l }, + { 0x1149847750491a74l,0x687fa761fde0dfb9l,0x2c2580227ea435abl, + 0x6b8bdb9491ce7e3fl }, + 0 }, + /* 65 << 96 */ + { { 0x1f04524cdc27e1f7l,0xa0c74f61572eab14l,0xdd5d0cfced272074l, + 0x95533c1d5bfe4f65l }, + { 0x3039d57ecce817cal,0x029967d73b822082l,0x9fca43866c4a10d3l, + 0xf8b2a7f0bb4968ebl }, + 0 }, + /* 71 << 96 */ + { { 0x933cd6dcbfbf6407l,0xd08f21504be673f8l,0x0e1c4d0db1140a2el, + 0x0502a092431b270al }, + { 0x5d99f9508768c00al,0xda3ce5079b3ff3c7l,0x1c648b75031c11abl, + 0x5e3de47bf2776305l }, + 0 }, + /* 77 << 96 */ + { { 0xe22af9274d2b9de4l,0xf3690f55a69609ecl,0x20260a6e453fbe18l, + 0x8edcb46b42d0b085l }, + { 0xd4ef250b7d9c7f58l,0x5e8578dfc83c3433l,0x9751d9b9e46e320al, + 0xb02bd03cf3c58af6l }, + 0 }, + /* 83 << 96 */ + { { 0x0ab299ede1b4d1ccl,0x22e7301cec4d18d2l,0xf2380f2a7b86d4ffl, + 0xca19ef9e40753713l }, + { 0x52bb0d24678c38a1l,0xcc9d6fd499001c02l,0xa2dd6b00bc5876e4l, + 0xfe04b402409fe2b3l }, + 0 }, + /* 89 << 96 */ + { { 0x7db986b1ff69f8d3l,0x648865e59d6266b9l,0x7ccfe96183f7dae5l, + 0x0f59a8bd6828379bl }, + { 0xad97e5ef0ac7c4e8l,0xa75914be784e9c18l,0x053e015bb18c1bb8l, + 0x18f6cefcb347043el }, + 0 }, + /* 95 << 96 */ + { { 0xb4d641bdf257c38al,0xadcea4d0c1372574l,0x7f8d20be71c8f0d0l, + 0x14a1d24c41dc6344l }, + { 0xe446054e41f35526l,0x4664213823c952ddl,0xfbde483401f6b0acl, + 0xc89eee66d75b6318l }, + 0 }, + /* 101 << 96 */ + { { 0x700242937a087392l,0xd42bd3aad5da04del,0xee64cb5b1f803414l, + 0xd6341ecbbab52988l }, + { 0x7ad522f343170a74l,0x5fba22536d61d9del,0x230304c1e845a6e5l, + 0xd69feabfbc9e326bl }, + 0 }, + /* 107 << 96 */ + { { 0xef7e49412e8a11d7l,0x4cb8963662c8bae1l,0xecc741198aad5816l, + 0x13490782c7af5175l }, + { 0x10c701f73e91a604l,0xcb8c6c7124cc30c1l,0xce0d479c071eb382l, + 0xa3dc71fb058087d4l }, + 0 }, + /* 113 << 96 */ + { { 0xec368492541eb6d1l,0x567735d6e09a94abl,0xb8039ec172350329l, + 0x3bd83a8f4894ddafl }, + { 0x740ef2a39c07063dl,0xba25e72277da7b59l,0xb09e248e3bf42e82l, + 0x7ff36da0b017d037l }, + 0 }, + /* 116 << 96 */ + { { 0xca80416651b8d9a3l,0x42531bc90ffb0db1l,0x72ce4718aa82e7cel, + 0x6e199913df574741l }, + { 0xd5f1b13dd5d36946l,0x8255dc65f68f0194l,0xdc9df4cd8710d230l, + 0x3453c20f138c1988l }, + 0 }, + /* 119 << 96 */ + { { 0x913f23b9ed08ac04l,0x18e336643590d098l,0xd3f72934e67536dcl, + 0xf949a757ec7ecde9l }, + { 0x37fc6583cf9cbd37l,0xcbe62cc043b1228el,0x777124948a743274l, + 0x3ea3668c716ce6f1l }, + 0 }, + /* 125 << 96 */ + { { 0xc89ce010a90d375bl,0x39ac669340503fe3l,0x9036f782d33ecb0el, + 0x5190656841fdc7d1l }, + { 0xbefd136e917d94cdl,0x05fea2f22a511b24l,0x80e62d76f9076e0cl, + 0x8c57635e418ba653l }, + 0 }, + }, + { + /* 0 << 104 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 104 */ + { { 0x20d3c982cf7d62d2l,0x1f36e29d23ba8150l,0x48ae0bf092763f9el, + 0x7a527e6b1d3a7007l }, + { 0xb4a89097581a85e3l,0x1f1a520fdc158be5l,0xf98db37d167d726el, + 0x8802786e1113e862l }, + 0 }, + /* 3 << 104 */ + { { 0xf6e894d1f4c6b6ecl,0x526b082718b3cd9bl,0x73f952a812117fbfl, + 0x2be864b011945bf5l }, + { 0x86f18ea542099b64l,0x2770b28a07548ce2l,0x97390f28295c1c9cl, + 0x672e6a43cb5206c3l }, + 0 }, + /* 4 << 104 */ + { { 0xc37c7dd0c55c4496l,0xa6a9635725bbabd2l,0x5b7e63f2add7f363l, + 0x9dce37822e73f1dfl }, + { 0xe1e5a16ab2b91f71l,0xe44898235ba0163cl,0xf2759c32f6e515adl, + 0xa5e2f1f88615eecfl }, + 0 }, + /* 5 << 104 */ + { { 0xcacce2c847c64367l,0x6a496b9f45af4ec0l,0x2a0836f36034042cl, + 0x14a1f3900b6c62eal }, + { 0xe7fa93633ef1f540l,0xd323b30a72a76d93l,0xffeec8b50feae451l, + 0x4eafc172bd04ef87l }, + 0 }, + /* 7 << 104 */ + { { 0xe4435a51b3e59b89l,0x136139554133a1c9l,0x87f46973440bee59l, + 0x714710f800c401e4l }, + { 0xc0cf4bced6c446c9l,0xe0aa7fd66c4d5368l,0xde5d811afc68fc37l, + 0x61febd72b7c2a057l }, + 0 }, + /* 9 << 104 */ + { { 0x27375fe665f837e2l,0x93f8c68bd882179fl,0x584feadc59b16187l, + 0xe5b50be9483bc162l }, + { 0x7ad9d6f1a2776625l,0xe9d1008004ff457bl,0x5b56d322677618a6l, + 0x036694eae3e68673l }, + 0 }, + /* 10 << 104 */ + { { 0x6ca4f87e822e37bel,0x73f237b4253bda4el,0xf747f3a241190aebl, + 0xf06fa36f804cf284l }, + { 0x0a6bbb6efc621c12l,0x5d624b6440b80ec6l,0x4b0724257ba556f3l, + 0x7fa0c3543e2d20a8l }, + 0 }, + /* 11 << 104 */ + { { 0x6feaffc51d8a4fd1l,0x59663b205f1ad208l,0xefc93cef24acb46al, + 0x54929de05967118cl }, + { 0x885708009acffb1cl,0x492bbf2b145639ecl,0x71f495a638f0018el, + 0xe24365dbc2792847l }, + 0 }, + /* 13 << 104 */ + { { 0x4bedae86a6f29002l,0x7abedb56e034457al,0x8bf3eec6179bff2al, + 0x9d626d57390f4e6bl }, + { 0x653fe0e914dd6ea3l,0x7483715989bd6d08l,0x85fb05b4ebd9b03dl, + 0x7dc3f2214a768bbcl }, + 0 }, + /* 15 << 104 */ + { { 0xaacc63f132b0ed8fl,0x041237242bafefd2l,0x0df9a7987e2d2a13l, + 0x09bd13cf9c27591fl }, + { 0xaa5f5e476e1afb50l,0xcd146a42b66eb646l,0x3f07561d1442ec3cl, + 0x7e5471738ae8ec47l }, + 0 }, + /* 16 << 104 */ + { { 0x8de2b7bc453cadd6l,0x203900a7bc0bc1f8l,0xbcd86e47a6abd3afl, + 0x911cac128502effbl }, + { 0x2d550242ec965469l,0x0e9f769229e0017el,0x633f078f65979885l, + 0xfb87d4494cf751efl }, + 0 }, + /* 17 << 104 */ + { { 0x2c3e61196c0c6cd5l,0x5e01a49a99f4aac8l,0xfa518fc92ef1565el, + 0xf64ff8714f772366l }, + { 0x52fcbc2b726420d0l,0x30fbf6eb76cfa9eel,0x0bd17139fa618268l, + 0x23ed6e122087535dl }, + 0 }, + /* 19 << 104 */ + { { 0x76098e38bb4ccb2cl,0x44e88aeeafbad6d1l,0x5c4d286771928778l, + 0xb1df868138534c94l }, + { 0x67eb8f4d77ce9debl,0x2a86d0461a77c55dl,0xc327181e46a6a3e7l, + 0x68fd611b8710e206l }, + 0 }, + /* 21 << 104 */ + { { 0xc093f3fc0c82bdf1l,0x21db25894f76c4a6l,0xf3dcb22ee410a7ael, + 0x1db37114f3c22ffel }, + { 0x9bd0a1fb58f6801dl,0x2cab103bd1b55cc8l,0x2ae1a7f5077ba4b2l, + 0x82b46642ce5ab2b3l }, + 0 }, + /* 23 << 104 */ + { { 0xc8477ec52546684cl,0xe3f9387702ff02b5l,0xefb72133ae5d04cdl, + 0x644905c339f10d02l }, + { 0x1750c87c13d8d356l,0x0e9b8063b41e7640l,0xc7ece04f5647b05bl, + 0x89a43da7ca9df9c4l }, + 0 }, + /* 25 << 104 */ + { { 0x02610ef1920eb7d9l,0x34bd2fc2e1ea1dc0l,0xcb89da255170b890l, + 0xaaa2796461cff827l }, + { 0xc308c9d37103ed6al,0xe82d63d5a467564al,0x94c897c4a0fa7732l, + 0x75eb52fa64c7aa5fl }, + 0 }, + /* 27 << 104 */ + { { 0x52582f9cb985fcb6l,0xaaef8d9f8508a691l,0x494c2c346e505131l, + 0x6d062362d55f30f6l }, + { 0x70059e9122e1e32fl,0x1507c3fe9e51abb0l,0xd8aba31b2b7bda72l, + 0x5acbc5f77b753f13l }, + 0 }, + /* 28 << 104 */ + { { 0x15bfb8bf5116f937l,0x7c64a586c1268943l,0x71e25cc38419a2c8l, + 0x9fd6b0c48335f463l }, + { 0x4bf0ba3ce8ee0e0el,0x6f6fba60298c21fal,0x57d57b39ae66bee0l, + 0x292d513022672544l }, + 0 }, + /* 29 << 104 */ + { { 0x075dc81953952ff6l,0xd4d9eeda20b7384dl,0x8a81c1bfd2d6c6a5l, + 0x319368a0db050f3bl }, + { 0x91f476de31f1cee2l,0x1b38604500d0e17fl,0xed2081889a820384l, + 0x8d00c411a0f1a637l }, + 0 }, + /* 31 << 104 */ + { { 0xb029b687a47fd8f0l,0xa531360696371a05l,0x7b84e88c5ab09140l, + 0x87dad7c85eeb1d14l }, + { 0xef0749b9d0edf6f3l,0x29fc7310e2ef198bl,0x01e05df5069ed399l, + 0x121db4ecdf4e2fcal }, + 0 }, + /* 33 << 104 */ + { { 0xe730f3f62826bee0l,0xb9bdbe3fce332a8fl,0x1ecad11766ec00aal, + 0x7503d835617a62d1l }, + { 0x9f34e161b862b139l,0xde42194cf30f6a67l,0x5037a953c1e879fel, + 0x62f321f89bda45dbl }, + 0 }, + /* 34 << 104 */ + { { 0xe87771d8033f2876l,0xb0186ec67d5cc3dbl,0x58e8bb803bc9bc1dl, + 0x4d1395cc6f6ef60el }, + { 0xa73c62d6186244a0l,0x918e5f23110a5b53l,0xed4878ca741b7eabl, + 0x3038d71adbe03e51l }, + 0 }, + /* 35 << 104 */ + { { 0xcbdba27c40234d55l,0x24352b6cb3eb56c9l,0xae681b85a8e9295al, + 0x2a6cfba1f1171664l }, + { 0x49f045838ca40c3cl,0xe56da25c6eb0f8eal,0x8e62f86fc4341a4el, + 0x7f68bdc64c3f947fl }, + 0 }, + /* 36 << 104 */ + { { 0x840204b7a93c3246l,0x21ab6069a0b9b4cdl,0xf5fa6e2bb1d64218l, + 0x1de6ad0ef3d56191l }, + { 0x570aaa88ff1929c7l,0xc6df4c6b640e87b5l,0xde8a74f2c65f0cccl, + 0x8b972fd5e6f6cc01l }, + 0 }, + /* 37 << 104 */ + { { 0x862013c00bf22173l,0xfd004c834acd8e23l,0x50e422ca310b1649l, + 0xe6d04de65bbe1854l }, + { 0x651f646385761ef3l,0x3b17d38652cf85c9l,0xbdce284a5f54ecc7l, + 0x72efcd3ec7c2106cl }, + 0 }, + /* 39 << 104 */ + { { 0x34324b182ff07e3el,0x29938f38f50bcb71l,0xd0e3d7b977e2bcc3l, + 0x8e78f007c0a3292bl }, + { 0xfa28c530005c2c00l,0x6f9c21d51faa0c5al,0x3df01abd7b9c78f3l, + 0x0e5618c1ccaaeb7el }, + 0 }, + /* 40 << 104 */ + { { 0xaa6778fce7560b90l,0xb4073e61a7e824cel,0xff0d693cd642eba8l, + 0x7ce2e57a5dccef38l }, + { 0x89c2c7891df1ad46l,0x83a06922098346fdl,0x2d715d72da2fc177l, + 0x7b6dd71d85b6cf1dl }, + 0 }, + /* 41 << 104 */ + { { 0x4601a6a492ad3889l,0xdc8e3364d9a0709fl,0x0c687f2b2c260327l, + 0xe882af62e1a79573l }, + { 0x0cfd00ab945d9017l,0xe6df7505d0e3c188l,0xb389a66dbde825a2l, + 0x126d77b6bcd8e14fl }, + 0 }, + /* 43 << 104 */ + { { 0xc800acc7db18ec73l,0x0ebecc78d86e99efl,0x675796cdbd05bc5fl, + 0x254498126afd7c7fl }, + { 0x96293b695969b165l,0xd8514d83c162c8dal,0xe174f8b674a15a5cl, + 0x880d687389a2f73cl }, + 0 }, + /* 44 << 104 */ + { { 0x53703a328300129fl,0x1f63766268c43bfdl,0xbcbd191300e54051l, + 0x812fcc627bf5a8c5l }, + { 0x3f969d5f29fb85dal,0x72f4e00a694759e8l,0x426b6e52790726b7l, + 0x617bbc873bdbb209l }, + 0 }, + /* 45 << 104 */ + { { 0xf536f07cad1deb2el,0x2a13a11ea87a710el,0x0ce2ccab64f4dc96l, + 0x16178694f5a55464l }, + { 0x1496168da2cb3986l,0xb079a5b9d56a93a9l,0x97005e99092893d3l, + 0x55df5ed6e8fcc6c3l }, + 0 }, + /* 46 << 104 */ + { { 0x511f8bb997aee317l,0x812a4096e81536a8l,0x137dfe593ac09b9bl, + 0x0682238fba8c9a7al }, + { 0x7072ead6aeccb4bdl,0x6a34e9aa692ba633l,0xc82eaec26fff9d33l, + 0xfb7535121d4d2b62l }, + 0 }, + /* 47 << 104 */ + { { 0x821dca8bbf328b1cl,0x24596ddd5a3d6830l,0x061c4c15635b5b4cl, + 0x0e2b3bef4fa3560al }, + { 0xffced37498906c43l,0x10ebd174e26b3784l,0x7cd068c470039bb5l, + 0xc47dda0f88404e59l }, + 0 }, + /* 48 << 104 */ + { { 0x1a0445ff1d7aadabl,0x65d38260d5f6a67cl,0x6e62fb0891cfb26fl, + 0xef1e0fa55c7d91d6l }, + { 0x47e7c7ba33db72cdl,0x017cbc09fa7c74b2l,0x3c931590f50a503cl, + 0xcac54f60616baa42l }, + 0 }, + /* 49 << 104 */ + { { 0x7ad7d13569185235l,0x19771949fb69e030l,0xd4de9717bc45fb4fl, + 0x5657b076167e5739l }, + { 0x9503a71fdd27449el,0xfa2fabf73cc01347l,0xf8ecef24c83fb301l, + 0x527012bd5a8d5078l }, + 0 }, + /* 51 << 104 */ + { { 0x70a550d7e6fc3a32l,0x8e5875841951fe57l,0x5e6d43eaaab9788bl, + 0x1e406fed80599794l }, + { 0xd8164ace9ed2557cl,0xf9648f30ff593e10l,0x53af2fd80c2ff879l, + 0x6705993cc9409bf4l }, + 0 }, + /* 52 << 104 */ + { { 0x04b005b6c6458293l,0x36bb5276e8d10af7l,0xacf2dc138ee617b8l, + 0x470d2d35b004b3d4l }, + { 0x06790832feeb1b77l,0x2bb75c3985657f9cl,0xd70bd4edc0f60004l, + 0xfe797ecc219b018bl }, + 0 }, + /* 53 << 104 */ + { { 0xeca02ebf0ef19ceel,0xac691fbe2de090a4l,0x1f3866641b374547l, + 0xbd8018c6a12ee85fl }, + { 0x3e851318ee63e0f1l,0x45b0c37a161987d3l,0x67fe36056eb567c4l, + 0x07c291b563200c5bl }, + 0 }, + /* 55 << 104 */ + { { 0xc85535ac1a956a8al,0x7bf4d70bc0ade321l,0xaf2efc48237bc56fl, + 0xf9bfe13e31ba97e7l }, + { 0x2ca5fac4cf7c6c65l,0xc23b14ff03ec3e35l,0xc5109923217bcfd2l, + 0xf02f96a1c58f32f3l }, + 0 }, + /* 57 << 104 */ + { { 0x3b1f715b0d0aeff4l,0xbe406d62f0d44536l,0xe413843d567bcb38l, + 0x75b7fb43791e705al }, + { 0x5b831d4b224f85e5l,0x3fea6659d9a35eael,0xd6f8bd097c85480bl, + 0x2a9561a34a959267l }, + 0 }, + /* 59 << 104 */ + { { 0x4a96a3535a303c10l,0x9aa3ad71c37c8d7el,0x4e2d077fde52014fl, + 0x4d8bec5df8e3964dl }, + { 0xda88ab94e865e142l,0x52df506d10a88091l,0x9aebff0092fc38a2l, + 0xdfc034395608b0a2l }, + 0 }, + /* 60 << 104 */ + { { 0xee23fa819966e7eel,0x64ec4aa805b7920dl,0x2d44462d2d90aad4l, + 0xf44dd195df277ad5l }, + { 0x8d6471f1bb46b6a1l,0x1e65d313fd885090l,0x33a800f513a977b4l, + 0xaca9d7210797e1efl }, + 0 }, + /* 61 << 104 */ + { { 0xb1557be2a4ea787el,0x59324973019f667fl,0x262ceced5595367cl, + 0x8a676897ec598640l }, + { 0x2df6cebfc7f06f4fl,0xb255723138078f9al,0xad553c46524a0dd1l, + 0xe20bb20a5a68d62al }, + 0 }, + /* 63 << 104 */ + { { 0x6f47e3779589e263l,0x7cb83e3d35106bb8l,0x2642d87bcc632fc2l, + 0x4d18f34d8b77eb36l }, + { 0x7de6bf6d19ca4d1cl,0x438e8f02f7e926aal,0xb539021250ac930al, + 0xe34ddfc15b219a9fl }, + 0 }, + /* 64 << 104 */ + { { 0x98857ceb1bf4581cl,0xe635e186aca7b166l,0x278ddd22659722acl, + 0xa0903c4c1db68007l }, + { 0x366e458948f21402l,0x31b49c14b96abda2l,0x329c4b09e0403190l, + 0x97197ca3d29f43fel }, + 0 }, + /* 65 << 104 */ + { { 0xfe4de13781479db4l,0x307331f012f08ea5l,0x7f59a64758c04c13l, + 0x6b41189abdc9b3c9l }, + { 0xb10f11e5a6f8c5edl,0x757fb7a3f5b0579el,0x456d0a873c90d027l, + 0x7e8bb6bf32361796l }, + 0 }, + /* 71 << 104 */ + { { 0x6aa1dc6c9e689d8dl,0xaa5fa015479cdd09l,0x7eb4dbb582fc000al, + 0x4a57b689eff4e701l }, + { 0x7bfe8d2a8e15cd8cl,0xab109b1cc9074e1al,0x5716715fee1619a5l, + 0xf29a51eccdcb40bcl }, + 0 }, + /* 77 << 104 */ + { { 0x14c76234ddf03c6el,0xdfb5d388baeb2eddl,0x4bd85da26d413d2dl, + 0x5b0dd9be3ae38469l }, + { 0xe4d8a9d89ab3ae61l,0xb9e37b880ee63951l,0x17f08e9b21a7f30fl, + 0x173db1e8119af788l }, + 0 }, + /* 83 << 104 */ + { { 0x2352ad4a170d43f6l,0x098d74f65a0ae4b0l,0x290f5236c3a46c2al, + 0xea9266102dd87e7fl }, + { 0xd7ee90f6848e6911l,0xebe8f4cce0d8886fl,0xa2038320558ff6a0l, + 0x1f716534f37c38cfl }, + 0 }, + /* 89 << 104 */ + { { 0x9754209439a4a159l,0xe6135412fed24278l,0xbba62254d70e2cabl, + 0x4ac6a8ac85895130l }, + { 0xc01614fee1a45363l,0x720ad3f8b67294f2l,0x724ea95cb420ea51l, + 0x1f40ab2d712b856cl }, + 0 }, + /* 95 << 104 */ + { { 0x708e1c7975f3d30cl,0x423f1535e2172da3l,0x7a29be342a06a0b1l, + 0x9de5c9eb32c68ba2l }, + { 0x70217b0232d48793l,0x3cf3855bac1471cfl,0x6762d03f8321e179l, + 0x06ee12ea236fa7cfl }, + 0 }, + /* 101 << 104 */ + { { 0x1718e7428779109bl,0x6188008d0aca350bl,0xbbe227e00594bc15l, + 0x4a7b6423ddbdea35l }, + { 0x06ad632dfa44e1bfl,0xaf9c163d1e97b409l,0x64dafec3c61f2b2fl, + 0xc6759d905525c0c9l }, + 0 }, + /* 107 << 104 */ + { { 0x76d6294787517149l,0x2bda339baa77d325l,0x04b1bec067ad1fd1l, + 0x49f63fcc0aec7c73l }, + { 0x005cb459ec1bf494l,0x8fa99c1b1ec6f8bbl,0x70a4e6d78b59dd43l, + 0xfd70bcb313d6594dl }, + 0 }, + /* 113 << 104 */ + { { 0x2987a7cb13966c11l,0x74ad0a26a783f283l,0xf011200ae54d27f0l, + 0xbd8632963fb38396l }, + { 0x7ec7fe8c9b86d059l,0xfa94ca76d0cd33a7l,0xf6ad741cdc646993l, + 0x83054a427ebc34e9l }, + 0 }, + /* 116 << 104 */ + { { 0xadef8c5a192ef710l,0x88afbd4b3b7431f9l,0x7e1f740764250c9el, + 0x6e31318db58bec07l }, + { 0xfd4fc4b824f89b4el,0x65a5dd8848c36a2al,0x4f1eccfff024baa7l, + 0x22a21cf2cba94650l }, + 0 }, + /* 119 << 104 */ + { { 0x7b45865478f39754l,0xcbb8b96c4564e003l,0xb492d2bf69b35752l, + 0x4e6287e065ee5ad3l }, + { 0x07906c14eb1ffe62l,0xf350390c681fcdf8l,0xc351386f6be3eec3l, + 0x8480d00ee5df919dl }, + 0 }, + /* 125 << 104 */ + { { 0x399861ecf8a2d5aal,0xb179adeb046f78cbl,0x056a6cd88792f647l, + 0xd3dfc91c3d411820l }, + { 0x4ccf92d179693be1l,0x12ecd9a3f65cb250l,0x58e5d2102538b9e7l, + 0x4e655882ff977ccal }, + 0 }, + }, + { + /* 0 << 112 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 112 */ + { { 0x8ce9b6bfc360e25al,0xe6425195075a1a78l,0x9dc756a8481732f4l, + 0x83c0440f5432b57al }, + { 0xc670b3f1d720281fl,0x2205910ed135e051l,0xded14b0edb052be7l, + 0x697b3d27c568ea39l }, + 0 }, + /* 3 << 112 */ + { { 0x0b89de9314092ebbl,0xf17256bd428e240cl,0xcf89a7f393d2f064l, + 0x4f57841ee1ed3b14l }, + { 0x4ee14405e708d855l,0x856aae7203f1c3d0l,0xc8e5424fbdd7eed5l, + 0x3333e4ef73ab4270l }, + 0 }, + /* 4 << 112 */ + { { 0x3bc77adedda492f8l,0xc11a3aea78297205l,0x5e89a3e734931b4cl, + 0x17512e2e9f5694bbl }, + { 0x5dc349f3177bf8b6l,0x232ea4ba08c7ff3el,0x9c4f9d16f511145dl, + 0xccf109a333b379c3l }, + 0 }, + /* 5 << 112 */ + { { 0xe75e7a88a1f25897l,0x7ac6961fa1b5d4d8l,0xe3e1077308f3ed5cl, + 0x208a54ec0a892dfbl }, + { 0xbe826e1978660710l,0x0cf70a97237df2c8l,0x418a7340ed704da5l, + 0xa3eeb9a908ca33fdl }, + 0 }, + /* 7 << 112 */ + { { 0xb4323d588434a920l,0xc0af8e93622103c5l,0x667518ef938dbf9al, + 0xa184307383a9cdf2l }, + { 0x350a94aa5447ab80l,0xe5e5a325c75a3d61l,0x74ba507f68411a9el, + 0x10581fc1594f70c5l }, + 0 }, + /* 9 << 112 */ + { { 0x5aaa98a7cb0c9c8cl,0x75105f3081c4375cl,0xceee50575ef1c90fl, + 0xb31e065fc23a17bfl }, + { 0x5364d275d4b6d45al,0xd363f3ad62ec8996l,0xb5d212394391c65bl, + 0x84564765ebb41b47l }, + 0 }, + /* 10 << 112 */ + { { 0x20d18ecc37107c78l,0xacff3b6b570c2a66l,0x22f975d99bd0d845l, + 0xef0a0c46ba178fa0l }, + { 0x1a41965176b6028el,0xc49ec674248612d4l,0x5b6ac4f27338af55l, + 0x06145e627bee5a36l }, + 0 }, + /* 11 << 112 */ + { { 0x33e95d07e75746b5l,0x1c1e1f6dc40c78bel,0x967833ef222ff8e2l, + 0x4bedcf6ab49180adl }, + { 0x6b37e9c13d7a4c8al,0x2748887c6ddfe760l,0xf7055123aa3a5bbcl, + 0x954ff2257bbb8e74l }, + 0 }, + /* 13 << 112 */ + { { 0x4e23ca446d3fea55l,0xb4ae9c86f4810568l,0x47bfb91b2a62f27dl, + 0x60deb4c9d9bac28cl }, + { 0xa892d8947de6c34cl,0x4ee682594494587dl,0x914ee14e1a3f8a5bl, + 0xbb113eaa28700385l }, + 0 }, + /* 15 << 112 */ + { { 0xef9dc899a7b56eafl,0x00c0e52c34ef7316l,0x5b1e4e24fe818a86l, + 0x9d31e20dc538be47l }, + { 0x22eb932d3ed68974l,0xe44bbc087c4e87c4l,0x4121086e0dde9aefl, + 0x8e6b9cff134f4345l }, + 0 }, + /* 16 << 112 */ + { { 0x96892c1f711b0eb9l,0xb905f2c8780ab954l,0xace26309a20792dbl, + 0xec8ac9b30684e126l }, + { 0x486ad8b6b40a2447l,0x60121fc19fe3fb24l,0x5626fccf1a8e3b3fl, + 0x4e5686226ad1f394l }, + 0 }, + /* 17 << 112 */ + { { 0xda7aae0d196aa5a1l,0xe0df8c771041b5fbl,0x451465d926b318b7l, + 0xc29b6e557ab136e9l }, + { 0x2c2ab48b71148463l,0xb5738de364454a76l,0x54ccf9a05a03abe4l, + 0x377c02960427d58el }, + 0 }, + /* 19 << 112 */ + { { 0x90e4f7c92d7d1413l,0x67e2d6b59834f597l,0x4fd4f4f9a808c3e8l, + 0xaf8237e0d5281ec1l }, + { 0x25ab5fdc84687ceel,0xc5ded6b1a5b26c09l,0x8e4a5aecc8ea7650l, + 0x23b73e5c14cc417fl }, + 0 }, + /* 21 << 112 */ + { { 0xb4293fdcf50225f9l,0xc52e175cb0e12b03l,0xf649c3bad0a8bf64l, + 0x745a8fefeb8ae3c6l }, + { 0x30d7e5a358321bc3l,0xb1732be70bc4df48l,0x1f217993e9ea5058l, + 0xf7a71cde3e4fd745l }, + 0 }, + /* 23 << 112 */ + { { 0xa188b2502d0f39aal,0x622118bb15a85947l,0x2ebf520ffde0f4fal, + 0xa40e9f294860e539l }, + { 0x7b6a51eb22b57f0fl,0x849a33b97e80644al,0x50e5d16f1cf095fel, + 0xd754b54eec55f002l }, + 0 }, + /* 25 << 112 */ + { { 0xcd821dfb988baf01l,0xe6331a7ddbb16647l,0x1eb8ad33094cb960l, + 0x593cca38c91bbca5l }, + { 0x384aac8d26567456l,0x40fa0309c04b6490l,0x97834cd6dab6c8f6l, + 0x68a7318d3f91e55fl }, + 0 }, + /* 27 << 112 */ + { { 0xc7bfd486605daaa6l,0x46fd72b7bb9a6c9el,0xe4847fb1a124fb89l, + 0x75959cbda2d8ffbcl }, + { 0x42579f65c8a588eel,0x368c92e6b80b499dl,0xea4ef6cd999a5df1l, + 0xaa73bb7f936fe604l }, + 0 }, + /* 28 << 112 */ + { { 0xf347a70d6457d188l,0x86eda86b8b7a388bl,0xb7cdff060ccd6013l, + 0xbeb1b6c7d0053fb2l }, + { 0x0b02238799240a9fl,0x1bbb384f776189b2l,0x8695e71e9066193al, + 0x2eb5009706ffac7el }, + 0 }, + /* 29 << 112 */ + { { 0x0654a9c04a7d2caal,0x6f3fb3d1a5aaa290l,0x835db041ff476e8fl, + 0x540b8b0bc42295e4l }, + { 0xa5c73ac905e214f5l,0x9a74075a56a0b638l,0x2e4b1090ce9e680bl, + 0x57a5b4796b8d9afal }, + 0 }, + /* 31 << 112 */ + { { 0x2a2bfa7f650006f0l,0xdfd7dad350c0fbb2l,0x92452495ccf9ad96l, + 0x183bf494d95635f9l }, + { 0x02d5df434a7bd989l,0x505385cca5431095l,0xdd98e67dfd43f53el, + 0xd61e1a6c500c34a9l }, + 0 }, + /* 33 << 112 */ + { { 0x41d85ea1ef74c45bl,0x2cfbfa66ae328506l,0x98b078f53ada7da9l, + 0xd985fe37ec752fbbl }, + { 0xeece68fe5a0148b4l,0x6f9a55c72d78136dl,0x232dccc4d2b729cel, + 0xa27e0dfd90aafbc4l }, + 0 }, + /* 34 << 112 */ + { { 0x9647445212b4603el,0xa876c5516b706d14l,0xdf145fcf69a9d412l, + 0xe2ab75b72d479c34l }, + { 0x12df9a761a23ff97l,0xc61389925d359d10l,0x6e51c7aefa835f22l, + 0x69a79cb1c0fcc4d9l }, + 0 }, + /* 35 << 112 */ + { { 0xf57f350d594cc7e1l,0x3079ca633350ab79l,0x226fb6149aff594al, + 0x35afec026d59a62bl }, + { 0x9bee46f406ed2c6el,0x58da17357d939a57l,0x44c504028fd1797el, + 0xd8853e7c5ccea6cal }, + 0 }, + /* 36 << 112 */ + { { 0x4065508da35fcd5fl,0x8965df8c495ccaebl,0x0f2da85012e1a962l, + 0xee471b94c1cf1cc4l }, + { 0xcef19bc80a08fb75l,0x704958f581de3591l,0x2867f8b23aef4f88l, + 0x8d749384ea9f9a5fl }, + 0 }, + /* 37 << 112 */ + { { 0x1b3855378c9049f4l,0x5be948f37b92d8b6l,0xd96f725db6e2bd6bl, + 0x37a222bc958c454dl }, + { 0xe7c61abb8809bf61l,0x46f07fbc1346f18dl,0xfb567a7ae87c0d1cl, + 0x84a461c87ef3d07al }, + 0 }, + /* 39 << 112 */ + { { 0x3ab3d5afbd76e195l,0x478dd1ad6938a810l,0x6ffab3936ee3d5cbl, + 0xdfb693db22b361e4l }, + { 0xf969449651dbf1a7l,0xcab4b4ef08a2e762l,0xe8c92f25d39bba9al, + 0x850e61bcf1464d96l }, + 0 }, + /* 40 << 112 */ + { { 0xb7e830e3dc09508bl,0xfaf6d2cf74317655l,0x72606cebdf690355l, + 0x48bb92b3d0c3ded6l }, + { 0x65b754845c7cf892l,0xf6cd7ac9d5d5f01fl,0xc2c30a5996401d69l, + 0x91268650ed921878l }, + 0 }, + /* 41 << 112 */ + { { 0x380bf913b78c558fl,0x43c0baebc8afdaa9l,0x377f61d554f169d3l, + 0xf8da07e3ae5ff20bl }, + { 0xb676c49da8a90ea8l,0x81c1ff2b83a29b21l,0x383297ac2ad8d276l, + 0x3001122fba89f982l }, + 0 }, + /* 43 << 112 */ + { { 0xbbe1e6a6c93f72d6l,0xd5f75d12cad800eal,0xfa40a09fe7acf117l, + 0x32c8cdd57581a355l }, + { 0x742219927023c499l,0xa8afe5d738ec3901l,0x5691afcba90e83f0l, + 0x41bcaa030b8f8eacl }, + 0 }, + /* 44 << 112 */ + { { 0xe38b5ff98d2668d5l,0x0715281a7ad81965l,0x1bc8fc7c03c6ce11l, + 0xcbbee6e28b650436l }, + { 0x06b00fe80cdb9808l,0x17d6e066fe3ed315l,0x2e9d38c64d0b5018l, + 0xab8bfd56844dcaefl }, + 0 }, + /* 45 << 112 */ + { { 0x42894a59513aed8bl,0xf77f3b6d314bd07al,0xbbdecb8f8e42b582l, + 0xf10e2fa8d2390fe6l }, + { 0xefb9502262a2f201l,0x4d59ea5050ee32b0l,0xd87f77286da789a8l, + 0xcf98a2cff79492c4l }, + 0 }, + /* 46 << 112 */ + { { 0xf9577239720943c2l,0xba044cf53990b9d0l,0x5aa8e82395f2884al, + 0x834de6ed0278a0afl }, + { 0xc8e1ee9a5f25bd12l,0x9259ceaa6f7ab271l,0x7e6d97a277d00b76l, + 0x5c0c6eeaa437832al }, + 0 }, + /* 47 << 112 */ + { { 0x5232c20f5606b81dl,0xabd7b3750d991ee5l,0x4d2bfe358632d951l, + 0x78f8514698ed9364l }, + { 0x951873f0f30c3282l,0x0da8ac80a789230bl,0x3ac7789c5398967fl, + 0xa69b8f7fbdda0fb5l }, + 0 }, + /* 48 << 112 */ + { { 0xe5db77176add8545l,0x1b71cb6672c49b66l,0xd856073968421d77l, + 0x03840fe883e3afeal }, + { 0xb391dad51ec69977l,0xae243fb9307f6726l,0xc88ac87be8ca160cl, + 0x5174cced4ce355f4l }, + 0 }, + /* 49 << 112 */ + { { 0x98a35966e58ba37dl,0xfdcc8da27817335dl,0x5b75283083fbc7bfl, + 0x68e419d4d9c96984l }, + { 0x409a39f402a40380l,0x88940faf1fe977bcl,0xc640a94b8f8edea6l, + 0x1e22cd17ed11547dl }, + 0 }, + /* 51 << 112 */ + { { 0x17ba93b1a20ef103l,0xad8591306ba6577bl,0x65c91cf66fa214a0l, + 0xd7d49c6c27990da5l }, + { 0xecd9ec8d20bb569dl,0xbd4b2502eeffbc33l,0x2056ca5a6bed0467l, + 0x7916a1f75b63728cl }, + 0 }, + /* 52 << 112 */ + { { 0xd4f9497d53a4f566l,0x8973466497b56810l,0xf8e1da740494a621l, + 0x82546a938d011c68l }, + { 0x1f3acb19c61ac162l,0x52f8fa9cabad0d3el,0x15356523b4b7ea43l, + 0x5a16ad61ae608125l }, + 0 }, + /* 53 << 112 */ + { { 0xb0bcb87f4faed184l,0x5f236b1d5029f45fl,0xd42c76070bc6b1fcl, + 0xc644324e68aefce3l }, + { 0x8e191d595c5d8446l,0xc020807713ae1979l,0xadcaee553ba59cc7l, + 0x20ed6d6ba2cb81bal }, + 0 }, + /* 55 << 112 */ + { { 0x7392b41a530ccbbdl,0x87c82146ea823525l,0xa52f984c05d98d0cl, + 0x2ae57d735ef6974cl }, + { 0x9377f7bf3042a6ddl,0xb1a007c019647a64l,0xfaa9079a0cca9767l, + 0x3d81a25bf68f72d5l }, + 0 }, + /* 57 << 112 */ + { { 0xc110d830b0f2ac95l,0x48d0995aab20e64el,0x0f3e00e17729cd9al, + 0x2a570c20dd556946l }, + { 0x912dbcfd4e86214dl,0x2d014ee2cf615498l,0x55e2b1e63530d76el, + 0xc5135ae4fd0fd6d1l }, + 0 }, + /* 59 << 112 */ + { { 0x1854daa5061f1658l,0xc0016df1df0cd2b3l,0xc2a3f23e833d50del, + 0x73b681d2bbbd3017l }, + { 0x2f046dc43ac343c0l,0x9c847e7d85716421l,0xe1e13c910917eed4l, + 0x3fc9eebd63a1b9c6l }, + 0 }, + /* 60 << 112 */ + { { 0x0f816a727fe02299l,0x6335ccc2294f3319l,0x3820179f4745c5bel, + 0xe647b782922f066el }, + { 0xc22e49de02cafb8al,0x299bc2fffcc2ecccl,0x9a8feea26e0e8282l, + 0xa627278bfe893205l }, + 0 }, + /* 61 << 112 */ + { { 0xa7e197337933e47bl,0xf4ff6b132e766402l,0xa4d8be0a98440d9fl, + 0x658f5c2f38938808l }, + { 0x90b75677c95b3b3el,0xfa0442693137b6ffl,0x077b039b43c47c29l, + 0xcca95dd38a6445b2l }, + 0 }, + /* 63 << 112 */ + { { 0x583f3703f9374ab6l,0x864f91956e564145l,0x33bc3f4822526d50l, + 0x9f323c801262a496l }, + { 0xaa97a7ae3f046a9al,0x70da183edf8a039al,0x5b68f71c52aa0ba6l, + 0x9be0fe5121459c2dl }, + 0 }, + /* 64 << 112 */ + { { 0xc1e17eb6cbc613e5l,0x33131d55497ea61cl,0x2f69d39eaf7eded5l, + 0x73c2f434de6af11bl }, + { 0x4ca52493a4a375fal,0x5f06787cb833c5c2l,0x814e091f3e6e71cfl, + 0x76451f578b746666l }, + 0 }, + /* 65 << 112 */ + { { 0xa700767eabd0cc76l,0xa14ae98015889273l,0x5acf2cc466ea6380l, + 0xb942cc40d08d18b9l }, + { 0x9b5daa763ae45782l,0x61a25e0fb72f0ce0l,0xf94c0e80435fefe3l, + 0x73d552cf1620e1c9l }, + 0 }, + /* 71 << 112 */ + { { 0x57130582727185c1l,0x8f2b8ebc163897ecl,0x4a059cc7a04e4a6bl, + 0x4b1de9fe0908a366l }, + { 0xa4f7738688d0fef0l,0x55e3bb1d9ebfc138l,0x9022bbef005ae362l, + 0xf5669edc8741d349l }, + 0 }, + /* 77 << 112 */ + { { 0xf192c0f7ede937a4l,0xd2e91d62810c1b1el,0xf2b40b64dcc39c69l, + 0xe125fbd028f03b0el }, + { 0x52966dd78da708f9l,0x92d400a3cc0e7f32l,0x4e35aae36b0842b8l, + 0x0b4fe66ded3ad3cfl }, + 0 }, + /* 83 << 112 */ + { { 0x14b81d951f1ff6b5l,0x1d82f132ed9b03b8l,0x52f6f029b4fa4047l, + 0xea653682601e5913l }, + { 0x4e900375edeee046l,0xd22ed267f9428714l,0xb004fb3b1753e873l, + 0xfef061ba245b2c09l }, + 0 }, + /* 89 << 112 */ + { { 0x5e2376eaf9deba2bl,0x1ed1e9e5269a18cfl,0x8dffd66dcb1cada8l, + 0xb13239f068369c77l }, + { 0x2fede3a67f25426fl,0xc885cf0c6f90a2a6l,0xd950162d4eeac543l, + 0x53011aa09abc201bl }, + 0 }, + /* 95 << 112 */ + { { 0x7a63925d432b798al,0x92e762cfc9bd6da9l,0xf22fb9706a190382l, + 0x19919b847b18a9b3l }, + { 0x16793b803adfde86l,0xf9ce15ace8b1d44cl,0x4bf74144c0a140b8l, + 0x680468616f853f6cl }, + 0 }, + /* 101 << 112 */ + { { 0xd4e0d8460db84ba2l,0x9a162a3a360b68bbl,0x7297f3939233146cl, + 0xbc93c2f4ec77412dl }, + { 0x13ddf0a7e07e1065l,0x000a8d45fb5e5131l,0xb4373078cf61d467l, + 0xa4a1fd67bf3bb6f9l }, + 0 }, + /* 107 << 112 */ + { { 0x6f2473f9d7585098l,0x45a29448d4f23c1al,0x47fe40f1c22bdc25l, + 0x4e46ed1f31347673l }, + { 0x5e43a8624148898cl,0x4a02ededa993954el,0x83d830b52f8a1847l, + 0x007e3156a7f6a378l }, + 0 }, + /* 113 << 112 */ + { { 0x01a39fe7e847ca18l,0xaf2722418fed2772l,0x3104ef891fbb1748l, + 0x5b55331b2b9dd5ffl }, + { 0xe7806e31cec6a787l,0x9f49ed881e9c0af2l,0xf5a66373a3905b36l, + 0x77b5bca9efab75f3l }, + 0 }, + /* 116 << 112 */ + { { 0xd4d75f4bf0831932l,0x5e770ac477fe8cc9l,0x52b5e748862e72a2l, + 0xe9a45482501d35fel }, + { 0x8a93e7424a9ab187l,0x5a72506de88ca017l,0xe680dcb201eb2defl, + 0xdc5aa4e6ba68209dl }, + 0 }, + /* 119 << 112 */ + { { 0x2defa3dc3d01a344l,0x11fd939b162e459al,0x928453b97313d720l, + 0x08696dc053184a65l }, + { 0xd9f8a69c721f7415l,0x304eb0e079539019l,0xc9b0ca6dbb0c6313l, + 0xa10133eba93dc74el }, + 0 }, + /* 125 << 112 */ + { { 0xee0b164004393f1el,0x511547dfe1301979l,0xc00dfc3516d26d87l, + 0x06227c8aab847494l }, + { 0x178ca86748b2fdc7l,0xb51296f01a8ba1dcl,0xf252787731e1dd14l, + 0x7ecb5456c0ba2a1fl }, + 0 }, + }, + { + /* 0 << 120 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 120 */ + { { 0x3e0e5c9dd111f8ecl,0xbcc33f8db7c4e760l,0x702f9a91bd392a51l, + 0x7da4a795c132e92dl }, + { 0x1a0b0ae30bb1151bl,0x54febac802e32251l,0xea3a5082694e9e78l, + 0xe58ffec1e4fe40b8l }, + 0 }, + /* 3 << 120 */ + { { 0x7b23c513516e19e4l,0x56e2e847c5c4d593l,0x9f727d735ce71ef6l, + 0x5b6304a6f79a44c5l }, + { 0x6638a7363ab7e433l,0x1adea470fe742f83l,0xe054b8545b7fc19fl, + 0xf935381aba1d0698l }, + 0 }, + /* 4 << 120 */ + { { 0xb5504f9d918e4936l,0x65035ef6b2513982l,0x0553a0c26f4d9cb9l, + 0x6cb10d56bea85509l }, + { 0x48d957b7a242da11l,0x16a4d3dd672b7268l,0x3d7e637c8502a96bl, + 0x27c7032b730d463bl }, + 0 }, + /* 5 << 120 */ + { { 0x55366b7d5846426fl,0xe7d09e89247d441dl,0x510b404d736fbf48l, + 0x7fa003d0e784bd7dl }, + { 0x25f7614f17fd9596l,0x49e0e0a135cb98dbl,0x2c65957b2e83a76al, + 0x5d40da8dcddbe0f8l }, + 0 }, + /* 7 << 120 */ + { { 0x9fb3bba354530bb2l,0xbde3ef77cb0869eal,0x89bc90460b431163l, + 0x4d03d7d2e4819a35l }, + { 0x33ae4f9e43b6a782l,0x216db3079c88a686l,0x91dd88e000ffedd9l, + 0xb280da9f12bd4840l }, + 0 }, + /* 9 << 120 */ + { { 0xa37f3573f37f5937l,0xeb0f6c7dd1e4fca5l,0x2965a554ac8ab0fcl, + 0x17fbf56c274676acl }, + { 0x2e2f6bd9acf7d720l,0x41fc8f8810224766l,0x517a14b385d53befl, + 0xdae327a57d76a7d1l }, + 0 }, + /* 10 << 120 */ + { { 0x515d5c891f5f82dcl,0x9a7f67d76361079el,0xa8da81e311a35330l, + 0xe44990c44b18be1bl }, + { 0xc7d5ed95af103e59l,0xece8aba78dac9261l,0xbe82b0999394b8d3l, + 0x6830f09a16adfe83l }, + 0 }, + /* 11 << 120 */ + { { 0x43c41ac194d7d9b1l,0x5bafdd82c82e7f17l,0xdf0614c15fda0fcal, + 0x74b043a7a8ae37adl }, + { 0x3ba6afa19e71734cl,0x15d5437e9c450f2el,0x4a5883fe67e242b1l, + 0x5143bdc22c1953c2l }, + 0 }, + /* 13 << 120 */ + { { 0xc676d7f2b1f3390bl,0x9f7a1b8ca5b61272l,0x4ebebfc9c2e127a9l, + 0x4602500c5dd997bfl }, + { 0x7f09771c4711230fl,0x058eb37c020f09c1l,0xab693d4bfee5e38bl, + 0x9289eb1f4653cbc0l }, + 0 }, + /* 15 << 120 */ + { { 0x54da9dc7ab952578l,0xb5423df226e84d0bl,0xa8b64eeb9b872042l, + 0xac2057825990f6dfl }, + { 0x4ff696eb21f4c77al,0x1a79c3e4aab273afl,0x29bc922e9436b3f1l, + 0xff807ef8d6d9a27al }, + 0 }, + /* 16 << 120 */ + { { 0xc7f3a8f833f6746cl,0x21e46f65fea990cal,0x915fd5c5caddb0a9l, + 0xbd41f01678614555l }, + { 0x346f4434426ffb58l,0x8055943614dbc204l,0xf3dd20fe5a969b7fl, + 0x9d59e956e899a39al }, + 0 }, + /* 17 << 120 */ + { { 0xe4ca688fd06f56c0l,0xa48af70ddf027972l,0x691f0f045e9a609dl, + 0xa9dd82cdee61270el }, + { 0x8903ca63a0ef18d3l,0x9fb7ee353d6ca3bdl,0xa7b4a09cabf47d03l, + 0x4cdada011c67de8el }, + 0 }, + /* 19 << 120 */ + { { 0xac127dc1e038a675l,0x729deff38c5c6320l,0xb7df8fd4a90d2c53l, + 0x9b74b0ec681e7cd3l }, + { 0x5cb5a623dab407e5l,0xcdbd361576b340c6l,0xa184415a7d28392cl, + 0xc184c1d8e96f7830l }, + 0 }, + /* 21 << 120 */ + { { 0x86a9303b2f7e85c3l,0x5fce462171988f9bl,0x5b935bf6c138acb5l, + 0x30ea7d6725661212l }, + { 0xef1eb5f4e51ab9a2l,0x0587c98aae067c78l,0xb3ce1b3c77ca9ca6l, + 0x2a553d4d54b5f057l }, + 0 }, + /* 23 << 120 */ + { { 0x2c7156e10b1894a0l,0x92034001d81c68c0l,0xed225d00c8b115b5l, + 0x237f9c2283b907f2l }, + { 0x0ea2f32f4470e2c0l,0xb725f7c158be4e95l,0x0f1dcafab1ae5463l, + 0x59ed51871ba2fc04l }, + 0 }, + /* 25 << 120 */ + { { 0xd1b0ccdec9520711l,0x55a9e4ed3c8b84bfl,0x9426bd39a1fef314l, + 0x4f5f638e6eb93f2bl }, + { 0xba2a1ed32bf9341bl,0xd63c13214d42d5a9l,0xd2964a89316dc7c5l, + 0xd1759606ca511851l }, + 0 }, + /* 27 << 120 */ + { { 0xedf69feaf8c51187l,0x05bb67ec741e4da7l,0x47df0f3208114345l, + 0x56facb07bb9792b1l }, + { 0xf3e007e98f6229e4l,0x62d103f4526fba0fl,0x4f33bef7b0339d79l, + 0x9841357bb59bfec1l }, + 0 }, + /* 28 << 120 */ + { { 0xae1e0b67e28ef5bal,0x2c9a4699cb18e169l,0x0ecd0e331e6bbd20l, + 0x571b360eaf5e81d2l }, + { 0xcd9fea58101c1d45l,0x6651788e18880452l,0xa99726351f8dd446l, + 0x44bed022e37281d0l }, + 0 }, + /* 29 << 120 */ + { { 0x830e6eea60dbac1fl,0x23d8c484da06a2f7l,0x896714b050ca535bl, + 0xdc8d3644ebd97a9bl }, + { 0x106ef9fab12177b4l,0xf79bf464534d5d9cl,0x2537a349a6ab360bl, + 0xc7c54253a00c744fl }, + 0 }, + /* 31 << 120 */ + { { 0x24d661d168754ab0l,0x801fce1d6f429a76l,0xc068a85fa58ce769l, + 0xedc35c545d5eca2bl }, + { 0xea31276fa3f660d1l,0xa0184ebeb8fc7167l,0x0f20f21a1d8db0ael, + 0xd96d095f56c35e12l }, + 0 }, + /* 33 << 120 */ + { { 0x57d2046b59da06ebl,0x3c076d5fa49f6d74l,0x6b4c96e616f82ea0l, + 0xaf7b0f1f90536c0bl }, + { 0x7999f86d204a9b2dl,0x7e420264126c9f87l,0x4c967a1f262ac4e5l, + 0xe8174a09900e79adl }, + 0 }, + /* 34 << 120 */ + { { 0xd51687f2cb82516bl,0x8a440cfc040e4670l,0xeafd2bcfe7738d32l, + 0x7071e9162a1e911al }, + { 0xbd3abd44cfea57bbl,0x9c3add16085b19e2l,0xb194c01d6baa5aa6l, + 0x6f3d3faf92f85c64l }, + 0 }, + /* 35 << 120 */ + { { 0xe23e0769488a280el,0x8e55a728e63a5904l,0x01690716ab84cccfl, + 0xfe796130b78b3c98l }, + { 0x15cc475b9117f211l,0xbdc178761d1b9d56l,0x8df5594a3e37b9b9l, + 0x97747e341e37e494l }, + 0 }, + /* 36 << 120 */ + { { 0xf2a6370ed2f896e1l,0x27100e63802987afl,0xb4db1cff4678ebc7l, + 0x6e5f28d937b4b263l }, + { 0xd29030009711ebc4l,0xf14dcb9ff8712484l,0x7a46ec3eea449146l, + 0x200155e9c1c51179l }, + 0 }, + /* 37 << 120 */ + { { 0x8130f007f1968d55l,0x18823e7097ed9803l,0xdc9fec559402762dl, + 0x9e0bd57e278f5abbl }, + { 0xaa41b913c9ebf303l,0x1105ec43a76b9353l,0xf8e4ee4cf4e6c6b5l, + 0x3a630972bd7be696l }, + 0 }, + /* 39 << 120 */ + { { 0x5c7da7e16356b3eel,0x951bfe458ccf9b48l,0x6f2c6e91d0555d0cl, + 0x47d7f7b58efd38eel }, + { 0x957256c8af6fd630l,0xa690c65bdc01774cl,0xad52b27c7c8dafdal, + 0x81fbc16af44a145fl }, + 0 }, + /* 40 << 120 */ + { { 0x497c3a3481b0493al,0x2b3ab20d71bc8408l,0x0c60226aa03769d1l, + 0x4ac89c7ad10708b0l }, + { 0x62398ea5092f7e6al,0x7f408f54de96d526l,0x025bde6f85bf102cl, + 0xcc2f85120a4aa72el }, + 0 }, + /* 41 << 120 */ + { { 0x8a65e0386884a9c3l,0xd2e6ac047bf8c794l,0xc9c5d3d3f7bcdfb9l, + 0x0000ce42a33f2c12l }, + { 0xea1c0a9a7dd13b2bl,0xbfd97d7f0c35c3b1l,0x0ba75cf3347fcefel, + 0xc3c5f28f1333460dl }, + 0 }, + /* 43 << 120 */ + { { 0x7810ebf575baa708l,0xe7fa7a0dd7440549l,0x25b813baf0667e4al, + 0x30a46740d15838a8l }, + { 0x13207b1ad04b22f7l,0x09e601ffd1419699l,0xb1038fc77f687b27l, + 0xa4547dc9a127f95bl }, + 0 }, + /* 44 << 120 */ + { { 0x83b2e3b3056ecd2cl,0xd17dcdaaf03dfd36l,0xee24a5f81dcef956l, + 0xb6746cd0b7239f16l }, + { 0xed6cb311c8458c48l,0xe8c0fc9805d27da4l,0x4610e9a0a1bf0970l, + 0x1947f01d9906c19el }, + 0 }, + /* 45 << 120 */ + { { 0x8b979126217c7cd7l,0x65c57a378050067el,0x6a50c6383f34838cl, + 0x3de617c29b7bc81fl }, + { 0x58488d24253a0ac7l,0x3fe53ec75520ba0bl,0x9156dca763f0607el, + 0xdd08c5705d1fe134l }, + 0 }, + /* 46 << 120 */ + { { 0xbfb1d9e1e33ba77fl,0x0985311ccaef6c01l,0xc8b59e9accca8948l, + 0x1256280945416f25l }, + { 0xc90edbc257f53218l,0xcaa08c05125d8fb5l,0x33ea3fd49a1aad3bl, + 0x2aa8bd83d005e8bel }, + 0 }, + /* 47 << 120 */ + { { 0xcbd2f1a3c2b22963l,0x0f7bd29c0c8ac2b3l,0xddb932432d405bfdl, + 0xeabd4805328413b5l }, + { 0xcc79d31748ebb6b9l,0x09604f831f521aael,0xd3487fdf4c7d188cl, + 0xd219c318d1552ea9l }, + 0 }, + /* 48 << 120 */ + { { 0xef4f115c775d6ecel,0x69d2e3bbe8c0e78dl,0xb0264ef1145cfc81l, + 0x0a41e9fa1b69788bl }, + { 0x0d9233be909a1f0bl,0x150a84520ae76b30l,0xea3375370632bb69l, + 0x15f7b3cfaa25584al }, + 0 }, + /* 49 << 120 */ + { { 0xfc4c623e321f7b11l,0xd36c1066f9cbc693l,0x8165235835dc0c0al, + 0xa3ce2e18c824e97el }, + { 0x59ea7cbcc6ff405el,0xced5a94a1e56a1e2l,0x88d744c53ab64b39l, + 0x8963d029073a36e7l }, + 0 }, + /* 51 << 120 */ + { { 0x97aa902cb19f3edbl,0x8e605ff9bbf2975bl,0x0536fa8ba6eb299bl, + 0xfd96da4f7cd03ac0l }, + { 0x29c5b5b578f9a265l,0x1f025a6d5fd0bc1bl,0x440486ee58e0f8e1l, + 0x8f191f7d593e49e9l }, + 0 }, + /* 52 << 120 */ + { { 0xbddf656baea9c13fl,0x083c5d514c678b37l,0x975431b630878ed4l, + 0x6de13d4608d9cf1cl }, + { 0xfbb639cc02427c45l,0x6190ca0c5a6cd989l,0x35a6aa26c53f11b7l, + 0x73f9e17dddfd86f6l }, + 0 }, + /* 53 << 120 */ + { { 0xd30478a317be7689l,0x6fc3f634e358f7a7l,0x4057ece515688d9fl, + 0xb5397495d3d91eefl }, + { 0x62fac49e2f49bde4l,0xeb4a3e1860125c73l,0x15f38be8dabdac55l, + 0x18bf29f7d334d52al }, + 0 }, + /* 55 << 120 */ + { { 0xf684162b68777538l,0x3e2a770bbb3381f4l,0x1b7562c1b374577cl, + 0x9eec22dc5cf21688l }, + { 0xc35014b1d472be2cl,0xafe2317035f086fbl,0xb9c9c4c9a1491ce1l, + 0x2df1e669b56792ddl }, + 0 }, + /* 57 << 120 */ + { { 0xcf7d36fe1830f624l,0x176c3c12ed0474bdl,0x25b802c8f82b493dl, + 0x683c2a744c78147el }, + { 0x0db99444f8f3e446l,0x437bcac6800a56c7l,0xb4e592264d08b25fl, + 0xcaf1b4142e691ca7l }, + 0 }, + /* 59 << 120 */ + { { 0x378bd47b9d231cafl,0xde3aa2f01f4db832l,0xf609d16ab29bd7d5l, + 0x13feab54bdfb54dfl }, + { 0x274abbbc22fc1a12l,0x267febb47d30ef1bl,0xeffa996d80717cd8l, + 0x065a86d1118d0812l }, + 0 }, + /* 60 << 120 */ + { { 0xc681a8656a3cb3afl,0x528f25a981751414l,0x6669f07cc7eac946l, + 0x9fb3a53f3cc6cc6bl }, + { 0x2919d92a11ae224al,0xa59141110b170a19l,0xdc16c611e2042f16l, + 0x58ace12decd4180bl }, + 0 }, + /* 61 << 120 */ + { { 0x689bb1ec107bb59fl,0x8129702adad2b385l,0x10bd3baeb1630603l, + 0xaadec5d15f23e7cfl }, + { 0x572f234f4586f7fbl,0x13abdec95ec11b32l,0xa462a7ec6191c26al, + 0x4a7d92a06685c8d3l }, + 0 }, + /* 63 << 120 */ + { { 0xdd4e2b63b16628eal,0xdf0c8fc8eefa5e86l,0xb0ec710205662720l, + 0x3f4c6956fe81e9dal }, + { 0x5732ad8f52e356f7l,0x045a103968a658f0l,0x9c40b0b6506ba33al, + 0x0a426010cb54258dl }, + 0 }, + /* 64 << 120 */ + { { 0x09891641d4c5105fl,0x1ae80f8e6d7fbd65l,0x9d67225fbee6bdb0l, + 0x3b433b597fc4d860l }, + { 0x44e66db693e85638l,0xf7b59252e3e9862fl,0xdb785157665c32ecl, + 0x702fefd7ae362f50l }, + 0 }, + /* 65 << 120 */ + { { 0x3902ab14c3254641l,0xa63cfd9fd8c001c8l,0x597d155c52d0af3cl, + 0xc5a2cbc4a0dbe688l }, + { 0xac8a841b249195aal,0xc98f01aaed14426fl,0xeb4a8ce8353905f1l, + 0x4d6668171ecee1b7l }, + 0 }, + /* 71 << 120 */ + { { 0xbd66e7d9a94da8cdl,0x7bc04735801ef314l,0x90f3eba1c5cc2904l, + 0x3c7dfed6f71bb36dl }, + { 0x89a50c8da75e3086l,0x88b8b4746f8e3418l,0x26fe17f4a44a5dbdl, + 0x98bf74c16a1e24fel }, + 0 }, + /* 77 << 120 */ + { { 0xca7b470679e0db85l,0x7f46c7716fc897fdl,0x9537e7918edfc0f3l, + 0xa46d4b4405e91ddfl }, + { 0x97d21061ee5575e7l,0x1f4f32da59650429l,0x2d1d6af878995129l, + 0x41d6fc228a0e4260l }, + 0 }, + /* 83 << 120 */ + { { 0xb30a1a89107d2282l,0x5433d7673a5e1323l,0xb9eeab822abdfeafl, + 0x9579cb46df3e0dbfl }, + { 0x6fc3ff2c7e088e79l,0x94b32360d7314326l,0xd2e82b59e5ad82e4l, + 0x7372dc4a55bc24e3l }, + 0 }, + /* 89 << 120 */ + { { 0x355697215f3c03cbl,0x4150adf2a146edcdl,0x16ec1a421a252e1cl, + 0xdf4d0f94424984eal }, + { 0x15142b5f5fabe961l,0xe6a73c29567ec13al,0xe6d370795d12070al, + 0x437743d0206fd7c6l }, + 0 }, + /* 95 << 120 */ + { { 0x483b7a95d66bc594l,0xf6a7064e8a6113bbl,0x373ce20f4ed34f72l, + 0x6aa876ab24f429b2l }, + { 0x378d5c25412c3102l,0xe4219a97b493199cl,0x01c7cafaa0b37332l, + 0x9305cc85f7633f7dl }, + 0 }, + /* 101 << 120 */ + { { 0x0259b43aaadf2273l,0x869c5bd3cf9dc1c2l,0x4f18a6e4068d6628l, + 0xd110637fec2d4547l }, + { 0x1ae88a791e94aaddl,0xe8b4be39de64f5f9l,0x85cbd9b24dc6b2bbl, + 0xb65091fa1bc352b2l }, + 0 }, + /* 107 << 120 */ + { { 0x7c5cea5d20f6a354l,0xe936ff1582f3ed39l,0x54e7a775b779368el, + 0x8ca8a46e3cb17c9el }, + { 0x753ca1fa0138974dl,0x9ce311eba72902ffl,0xcb727e56973f72b6l, + 0xde72538d91685710l }, + 0 }, + /* 113 << 120 */ + { { 0xf423569f1bec8f85l,0x23376da5ca844ac4l,0xce7b407a111523f4l, + 0x736fb92dde7aa46dl }, + { 0xd9139edcc7662640l,0x520fbf0656a85e24l,0x14e3b5857e5284b5l, + 0xcbae4e8321d56ef3l }, + 0 }, + /* 116 << 120 */ + { { 0x69830a05564470a1l,0x1a1e26cf5b702e8el,0xe5fdf7d9d8fae645l, + 0xe4774f74a9950c66l }, + { 0x18bdda7cd1466825l,0xe6ab4ce6d115218al,0xfcb8c50064528629l, + 0xd705f429e70deed9l }, + 0 }, + /* 119 << 120 */ + { { 0x3f992d7ba99df096l,0x08993b4125e78725l,0x79eaad13117c4cafl, + 0x7230594c9fa87285l }, + { 0xac23d7edf2673e27l,0xc9d76fb53b9eb111l,0x7a0a036a9e9db78al, + 0x7c6ec39df9565cffl }, + 0 }, + /* 125 << 120 */ + { { 0x956ad1441fd4f7a1l,0x6c511ffecb7546cal,0x11becdaef5ae6ddbl, + 0x67587741946168b2l }, + { 0x99cd45edf54379a7l,0x687f8462e2748decl,0x2b2be1e1837bd066l, + 0x3862659c0c45a5a9l }, + 0 }, + }, + { + /* 0 << 128 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 128 */ + { { 0x62a8c244bfe20925l,0x91c19ac38fdce867l,0x5a96a5d5dd387063l, + 0x61d587d421d324f6l }, + { 0xe87673a2a37173eal,0x2384800853778b65l,0x10f8441e05bab43el, + 0xfa11fe124621efbel }, + 0 }, + /* 3 << 128 */ + { { 0xc0f734a3b2335834l,0x9526205a90ef6860l,0xcb8be71704e2bb0dl, + 0x2418871e02f383fal }, + { 0xd71776814082c157l,0xcc914ad029c20073l,0xf186c1ebe587e728l, + 0x6fdb3c2261bcd5fdl }, + 0 }, + /* 4 << 128 */ + { { 0xb4480f0441c23fa3l,0xb4712eb0c1989a2el,0x3ccbba0f93a29ca7l, + 0x6e205c14d619428cl }, + { 0x90db7957b3641686l,0x0432691d45ac8b4el,0x07a759acf64e0350l, + 0x0514d89c9c972517l }, + 0 }, + /* 5 << 128 */ + { { 0xcc7c4c1c2cf9d7c1l,0x1320886aee95e5abl,0xbb7b9056beae170cl, + 0xc8a5b250dbc0d662l }, + { 0x4ed81432c11d2303l,0x7da669121f03769fl,0x3ac7a5fd84539828l, + 0x14dada943bccdd02l }, + 0 }, + /* 7 << 128 */ + { { 0x51b90651cbae2f70l,0xefc4bc0593aaa8ebl,0x8ecd8689dd1df499l, + 0x1aee99a822f367a5l }, + { 0x95d485b9ae8274c5l,0x6c14d4457d30b39cl,0xbafea90bbcc1ef81l, + 0x7c5f317aa459a2edl }, + 0 }, + /* 9 << 128 */ + { { 0x410dc6a90deeaf52l,0xb003fb024c641c15l,0x1384978c5bc504c4l, + 0x37640487864a6a77l }, + { 0x05991bc6222a77dal,0x62260a575e47eb11l,0xc7af6613f21b432cl, + 0x22f3acc9ab4953e9l }, + 0 }, + /* 10 << 128 */ + { { 0x27c8919240be34e8l,0xc7162b3791907f35l,0x90188ec1a956702bl, + 0xca132f7ddf93769cl }, + { 0x3ece44f90e2025b4l,0x67aaec690c62f14cl,0xad74141822e3cc11l, + 0xcf9b75c37ff9a50el }, + 0 }, + /* 11 << 128 */ + { { 0x0d0942770c24efc8l,0x0349fd04bef737a4l,0x6d1c9dd2514cdd28l, + 0x29c135ff30da9521l }, + { 0xea6e4508f78b0b6fl,0x176f5dd2678c143cl,0x081484184be21e65l, + 0x27f7525ce7df38c4l }, + 0 }, + /* 13 << 128 */ + { { 0x9faaccf5e4652f1dl,0xbd6fdd2ad56157b2l,0xa4f4fb1f6261ec50l, + 0x244e55ad476bcd52l }, + { 0x881c9305047d320bl,0x1ca983d56181263fl,0x354e9a44278fb8eel, + 0xad2dbc0f396e4964l }, + 0 }, + /* 15 << 128 */ + { { 0xfce0176788a2ffe4l,0xdc506a3528e169a5l,0x0ea108617af9c93al, + 0x1ed2436103fa0e08l }, + { 0x96eaaa92a3d694e7l,0xc0f43b4def50bc74l,0xce6aa58c64114db4l, + 0x8218e8ea7c000fd4l }, + 0 }, + /* 16 << 128 */ + { { 0x6a7091c2e48fb889l,0x26882c137b8a9d06l,0xa24986631b82a0e2l, + 0x844ed7363518152dl }, + { 0x282f476fd86e27c7l,0xa04edaca04afefdcl,0x8b256ebc6119e34dl, + 0x56a413e90787d78bl }, + 0 }, + /* 17 << 128 */ + { { 0xd1ffd160deb58b9bl,0x78492428c007273cl,0x47c908048ef06073l, + 0x746cd0dfe48c659el }, + { 0xbd7e8e109d47055bl,0xe070967e39711c04l,0x3d8869c99c9444f6l, + 0x6c67ccc834ac85fcl }, + 0 }, + /* 19 << 128 */ + { { 0x8a42d8b087b05be1l,0xef00df8d3e4e1456l,0x148cc8e8fbfc8cd2l, + 0x0288ae4c4878804fl }, + { 0x44e669a73b4f6872l,0xa4a8dbd4aab53c5bl,0x843fa963c9660052l, + 0x128e2d2571c05dd2l }, + 0 }, + /* 21 << 128 */ + { { 0x3ea86174a9f1b59bl,0xc747ea076a9a8845l,0x733710b5ab242123l, + 0x6381b546d386a60cl }, + { 0xba0e286366a44904l,0x770f618de9db556cl,0x39e567f828fb198dl, + 0xb5f1bef040147ee8l }, + 0 }, + /* 23 << 128 */ + { { 0x1adee1d516391617l,0x962d9184a3315fd9l,0x91c229750c805d59l, + 0x4575eaf2cd9a1877l }, + { 0x83fef163451831b9l,0x829d6bdd6f09e30fl,0x9379272dcc6b4e6al, + 0xd7a049bd95fbee4al }, + 0 }, + /* 25 << 128 */ + { { 0x695f70da44ae09c6l,0x79793892bb99de1dl,0xde269352f696b429l, + 0xe37ea97f8104c825l }, + { 0x3166cac6b0e72e63l,0xa82e633ca03ba670l,0x1106e3843e505667l, + 0xc2994f3dffb788b6l }, + 0 }, + /* 27 << 128 */ + { { 0xd36a5ab37c53073bl,0xc44a9940ebdc7e35l,0x7dd86c8bf3ded136l, + 0x9fe9879fd5a0eb14l }, + { 0xa210726c9b99bf9cl,0x3faf4456861036afl,0x1661f1c9615d091al, + 0x2c63f630911551bcl }, + 0 }, + /* 28 << 128 */ + { { 0x1554d46da670ff1dl,0x24833d88cb97a1ccl,0x8fa6ab3cded97493l, + 0x215e037189926498l }, + { 0x549bd592e56d74ffl,0x58a8caf543b5e1ecl,0x3c6087a323e93cb9l, + 0x8b0549875648b83cl }, + 0 }, + /* 29 << 128 */ + { { 0x232974230554f94fl,0x4f445a380f3a7618l,0xb9fb40bee4abefd6l, + 0xfbf3eaf9c15eb07cl }, + { 0xed469c23aca0c8b3l,0xc5209f68846e3f8fl,0x33d51d13d75da468l, + 0x9406e10a3d5c6e29l }, + 0 }, + /* 31 << 128 */ + { { 0xb9a44b1f5c6cad21l,0xaa9947751ee60a83l,0xc89af3858c390401l, + 0xef1e450b8dd51056l }, + { 0x5f5f069879ac84d1l,0x68d82982ef57b1afl,0x31f1d90f50849555l, + 0xff9577e57d9fc8f6l }, + 0 }, + /* 33 << 128 */ + { { 0xaeebc5c0b430d6a1l,0x39b87a13dc3a9c04l,0xf0c445252db4a631l, + 0xe32d95482c66fcf6l }, + { 0x16f11bafb17849c4l,0xdd1c76615eca71f7l,0x4389ad2e32e6c944l, + 0x727c11a5889a06bbl }, + 0 }, + /* 34 << 128 */ + { { 0x38dd1ac021e5781al,0x578318dbfd019ee2l,0x096b677d5f88e574l, + 0xdbec82b216ad9f4fl }, + { 0x348debe23260e8d9l,0x9334126064dfcda1l,0xdc5fb34cefc8faael, + 0x5fa048beb4a6fc25l }, + 0 }, + /* 35 << 128 */ + { { 0xe18806fd60b3258cl,0xb7d2926b1364df47l,0xe208300fa107ce99l, + 0x8d2f29fe7918df0el }, + { 0x0b012d77a1244f4cl,0xf01076f4213a11cfl,0x8e623223181c559dl, + 0x9df196ee995a281dl }, + 0 }, + /* 36 << 128 */ + { { 0xc431a238013ff83bl,0x7c0018b2fad69d08l,0x99aeb52a4c9589eal, + 0x121f41ab9b1cf19fl }, + { 0x0cfbbcbaef0f5958l,0x8deb3aeb7be8fbdcl,0x12b954081f15aa31l, + 0x5acc09b34c0c06fdl }, + 0 }, + /* 37 << 128 */ + { { 0xfaa821383a721940l,0xdd70f54dd0008b83l,0x00decb507d32a52dl, + 0x04563529cdd87deal }, + { 0xb0e7e2a2db81643dl,0x445f4c383a6fef50l,0x5c0ef211df694ae1l, + 0xa5a8fead923d0f1cl }, + 0 }, + /* 39 << 128 */ + { { 0xbc0e08b0325b2601l,0xae9e4c6105815b7al,0x07f664faf944a4a1l, + 0x0ad19d29288f83b3l }, + { 0x8615cd677232c458l,0x98edff6e9038e7d1l,0x082e0c4395a4dfccl, + 0x336267afeceee00el }, + 0 }, + /* 40 << 128 */ + { { 0x775cbfa86d518ffbl,0xdecee1f6930f124bl,0x9a402804f5e81d0fl, + 0x0e8225c52a0eeb2fl }, + { 0x884a5d39fee9e867l,0x9540428ffb505454l,0xb2bf2e20107a70d1l, + 0xd9917c3ba010b2aal }, + 0 }, + /* 41 << 128 */ + { { 0xc88ad4452a29bfdel,0x3072ebfa998368b7l,0xa754cbf7f5384692l, + 0x85f7e16906b13146l }, + { 0x42a7095f6a549fbel,0xef44edf91f7f1f42l,0xbea2989737b0c863l, + 0x13b096d87a1e7fc3l }, + 0 }, + /* 43 << 128 */ + { { 0x51add77ce2a3a251l,0x840ca1384d8476adl,0x08d01d26f6096478l, + 0x10d501a532f1662bl }, + { 0xc8d63f811165a955l,0x587aa2e34095046al,0x759506c617af9000l, + 0xd6201fe4a32ab8d2l }, + 0 }, + /* 44 << 128 */ + { { 0xa98f42fa3d843d53l,0x33777cc613ef927al,0xc440cdbecb84ca74l, + 0x8c22f9631dc7c5ddl }, + { 0x4bc82b70c8d94708l,0x7e0b43fcc814364fl,0x286d4e2486f59b7el, + 0x1abc895e4d6bf4c4l }, + 0 }, + /* 45 << 128 */ + { { 0x7c52500cfc8c9bbdl,0x635563381534d9f7l,0xf55f38cbfd52c990l, + 0xc585ae85058f52e7l }, + { 0xb710a28bf9f19a01l,0x891861bdf0273ca4l,0x38a7aa2b034b0b7cl, + 0xa2ecead52a809fb1l }, + 0 }, + /* 46 << 128 */ + { { 0x3df614f1ec3ca8eal,0x6bb24e9f9505bc08l,0x23ba1afbf37ace22l, + 0x2e51b03b3463c261l }, + { 0x59a0fca9c39e6558l,0x819f271ca342ccd9l,0x0c913d54df7ac033l, + 0xba0f83de573257d3l }, + 0 }, + /* 47 << 128 */ + { { 0xdf62817ab3b32fbcl,0x616d74b0964670d4l,0xa37bc6270e26020bl, + 0xda46d655b7d40bdal }, + { 0x2840f155b5773f84l,0xbb633777897774b6l,0x59ff1df79a1ed3fal, + 0xf7011ee2bac571f9l }, + 0 }, + /* 48 << 128 */ + { { 0x38151e274d559d96l,0x4f18c0d3b8db6c01l,0x49a3aa836f9921afl, + 0xdbeab27b8c046029l }, + { 0x242b9eaa7040bf3bl,0x39c479e51614b091l,0x338ede2b0e4baf5dl, + 0x5bb192b7f0a53945l }, + 0 }, + /* 49 << 128 */ + { { 0xd612951861535bb0l,0xbf14364016f6a954l,0x3e0931eedde18024l, + 0x79d791c8139441c0l }, + { 0xba4fe7ecb67b8269l,0x7f30d848224b96c1l,0xa7e0a6abf0341068l, + 0x78db42c37198ea2dl }, + 0 }, + /* 51 << 128 */ + { { 0x13354044185ce776l,0x109a6e059ff0100cl,0xafa3b61b03144cb1l, + 0x4e4c814585265586l }, + { 0xa8dafd33edb35364l,0x6691781bfd2606bel,0x2e06a9786182f5ccl, + 0x588784ebe77faeecl }, + 0 }, + /* 52 << 128 */ + { { 0x896d572337e440d7l,0x685c5fd9ade23f68l,0xb5b1a26dc2c64918l, + 0xb9390e30dad6580cl }, + { 0x87911c4e7dee5b9bl,0xb90c5053deb04f6el,0x37b942a18f065aa6l, + 0x34acdf2a1ca0928dl }, + 0 }, + /* 53 << 128 */ + { { 0xc773f525606f8f04l,0x75ae4a4b41b0a5bbl,0xb2aa058eaf7df93cl, + 0xf15bea4feafed676l }, + { 0xd2967b236a3c4fd7l,0xa698628090e30e7fl,0xf1b5166d316418bdl, + 0x5748682e1c13cb29l }, + 0 }, + /* 55 << 128 */ + { { 0xe7b11babfff3605bl,0xdbce1b74cbac080fl,0xa0be39bd6535f082l, + 0x2b6501805f826684l }, + { 0xf90cea2400f5244fl,0xe279f2fadd244a1cl,0xd3fca77c9421c3ael, + 0xe66bc7ee81a5210al }, + 0 }, + /* 57 << 128 */ + { { 0x114085dac40c6461l,0xaf78cb47f47d41b8l,0x7a9ae851755b0adbl, + 0x8d2e8c66a0600b6dl }, + { 0x5fb19045389758c0l,0xfa6e2cdabe7c91b2l,0x6472a432663983a2l, + 0xc9370829e0e19363l }, + 0 }, + /* 59 << 128 */ + { { 0xd335856ec50bf2ffl,0x89b42295dfa708c2l,0x5dfb42241b201b4el, + 0x6c94d6b94eecbf9cl }, + { 0xabe5a47a7a634097l,0xf3d53b1643febecfl,0xff18619faca9846el, + 0x80ad8629a4066177l }, + 0 }, + /* 60 << 128 */ + { { 0x7872e34b3390ff23l,0x968ce4abde7d18efl,0x9b4a745e627fe7b1l, + 0x9607b0a0caff3e2al }, + { 0x1b05818eeb40e3a5l,0x6ac62204c0fa8d7al,0xb5b9058571ed4809l, + 0xb2432ef0f7cb65f2l }, + 0 }, + /* 61 << 128 */ + { { 0xc1203418f8a144b7l,0xb3413f808378f901l,0xf6badea161857095l, + 0xcd2816c2b2e93efel }, + { 0x6a8303ea174a0ee6l,0x98b62f29150b28b6l,0x68071bbc9c2a05b6l, + 0xcfcf41a39f00e36el }, + 0 }, + /* 63 << 128 */ + { { 0xcaf564f234d6bc29l,0x9e9a6507f3c8edb0l,0x2fb889edd4e5502el, + 0xb70d4ceb6cc9d8edl }, + { 0x0de25356b020f740l,0xa68d9263d11fe5e6l,0xe86400679d85dd77l, + 0xa95dfa7dec2c8c8dl }, + 0 }, + /* 64 << 128 */ + { { 0x715c9f973112795fl,0xe8244437984e6ee1l,0x55cb4858ecb66bcdl, + 0x7c136735abaffbeel }, + { 0x546615955dbec38el,0x51c0782c388ad153l,0x9ba4c53ac6e0952fl, + 0x27e6782a1b21dfa8l }, + 0 }, + /* 65 << 128 */ + { { 0x3f9bc63ece59397dl,0x3f0f98a93eaa6104l,0x2f82c37c002d9271l, + 0x6ac0495d4985353cl }, + { 0xbde52f629191527bl,0xa3a13fce475aa640l,0x1d71ae17ce673f89l, + 0x2b5cc61529120ec1l }, + 0 }, + /* 71 << 128 */ + { { 0xa0ab0f9924318c1cl,0x0cc5ca7da80ca60bl,0x24e27598abb965bal, + 0xc4863198b44d1351l }, + { 0x4d913783a28f04bel,0x404e78088cce8960l,0x2973b4e46286873el, + 0x7b6e0f3219f42b50l }, + 0 }, + /* 77 << 128 */ + { { 0x0091a786306a6349l,0x4640ceab2098622dl,0x9928022be8182233l, + 0xf261bee4514d0bedl }, + { 0x70cdcc44c5f64fedl,0x4e19fec4f9eb2dfel,0xd05bdc09058b0b69l, + 0x16f3007ed3bc6190l }, + 0 }, + /* 83 << 128 */ + { { 0x8f7f16957f136df1l,0x6d7547019b4f4215l,0xfb22d55eb4cc46a6l, + 0x0b53ef53a8563034l }, + { 0x8b105acc42bc9353l,0xe44c0a396079d59dl,0x78441fee35ee38ddl, + 0x87ad93e43dcc0119l }, + 0 }, + /* 89 << 128 */ + { { 0x98a1c55358d9f73al,0xaa0843f0540e2b91l,0x701f8831d0647459l, + 0xc4ae9d0484673005l }, + { 0x9c37bc9f30b3ea20l,0x24cb4e2dbcbfb2b2l,0x8513e6f313cbf070l, + 0x0c4db4334e76c79el }, + 0 }, + /* 95 << 128 */ + { { 0x882a2b9cbc8320b8l,0x16e9c11e3ad9e222l,0x24399ac19b23cb1dl, + 0x334c5496799a89c7l }, + { 0x72b6f9b8df3d774cl,0x42955bcbb11b6704l,0x3c4d6021ad2d4eafl, + 0x5416b309afe2b671l }, + 0 }, + /* 101 << 128 */ + { { 0x1bbe9e662bf7c2a6l,0x22a3a10ca4acfddbl,0x2424eaab46bae581l, + 0xebec1bbf40d6bdadl }, + { 0xd7e3fa1a5b012aedl,0xc0f82c23f1dc6204l,0x42787c82e319477dl, + 0xca1ae7a14cf57573l }, + 0 }, + /* 107 << 128 */ + { { 0x44b7d589d51bbde9l,0x15de755fd6a4cc98l,0x9b6ea8e582fb8e2el, + 0x9d9294f04332bc22l }, + { 0x53c6b2b7d1fa239al,0x286bf536693ca4f1l,0xc3fa754603c00f65l, + 0xc046713af49cdb48l }, + 0 }, + /* 113 << 128 */ + { { 0xe356f5f11d82d5d6l,0xa0346a73d035ca0cl,0x14c76adee1884448l, + 0xd8369bdd1c23dde9l }, + { 0x13017862fe025eafl,0x6b5ac5e9a76be1d7l,0x52d621a94933bb6el, + 0xb045b53baa8c1d3fl }, + 0 }, + /* 116 << 128 */ + { { 0x242da39e4e40466al,0xc03cb184ac322b07l,0x776b744f9aaa10bfl, + 0xb80d9f14fe7d4beal }, + { 0x75cd14308f9c4908l,0xa4e59ce9087b3d7al,0x3bbdce598cdca614l, + 0x58c57113bc1a5df1l }, + 0 }, + /* 119 << 128 */ + { { 0x2a70af1abd79d467l,0x68dc4f23f63e2b73l,0x4345572f1f67b23dl, + 0xc012b08f3a340718l }, + { 0x9458585cc963dbe2l,0x21d84032223a495cl,0x0d54a4ea0dc28159l, + 0xd9549e2c9b927dafl }, + 0 }, + /* 125 << 128 */ + { { 0xcd54ebd2d43c8cd2l,0x5ff4ded6a817b9f9l,0x6f59bc31245386d3l, + 0x65b67cb0a2077821l }, + { 0x36407956405ffa07l,0x723e0252d589f27al,0x052004b888e1239el, + 0x8e6d188d69fdf94dl }, + 0 }, + }, + { + /* 0 << 136 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 136 */ + { { 0xc16c236e846e364fl,0x7f33527cdea50ca0l,0xc48107750926b86dl, + 0x6c2a36090598e70cl }, + { 0xa6755e52f024e924l,0xe0fa07a49db4afcal,0x15c3ce7d66831790l, + 0x5b4ef350a6cbb0d6l }, + 0 }, + /* 3 << 136 */ + { { 0xe2a37598a9d82abfl,0x5f188ccbe6c170f5l,0x816822005066b087l, + 0xda22c212c7155adal }, + { 0x151e5d3afbddb479l,0x4b606b846d715b99l,0x4a73b54bf997cb2el, + 0x9a1bfe433ecd8b66l }, + 0 }, + /* 4 << 136 */ + { { 0xe13122f3dbfb894el,0xbe9b79f6ce274b18l,0x85a49de5ca58aadfl, + 0x2495775811487351l }, + { 0x111def61bb939099l,0x1d6a974a26d13694l,0x4474b4ced3fc253bl, + 0x3a1485e64c5db15el }, + 0 }, + /* 5 << 136 */ + { { 0x5afddab61430c9abl,0x0bdd41d32238e997l,0xf0947430418042ael, + 0x71f9addacdddc4cbl }, + { 0x7090c016c52dd907l,0xd9bdf44d29e2047fl,0xe6f1fe801b1011a6l, + 0xb63accbcd9acdc78l }, + 0 }, + /* 7 << 136 */ + { { 0x0ad7337ac0b7eff3l,0x8552225ec5e48b3cl,0xe6f78b0c73f13a5fl, + 0x5e70062e82349cbel }, + { 0x6b8d5048e7073969l,0x392d2a29c33cb3d2l,0xee4f727c4ecaa20fl, + 0xa068c99e2ccde707l }, + 0 }, + /* 9 << 136 */ + { { 0x5b826fcb1b3ec67bl,0xece1b4b041356616l,0x7d5ce77e56a3ab4fl, + 0xf6087f13aa212da0l }, + { 0xe63015054db92129l,0xb8ae4c9940407d11l,0x2b6de222dfab8385l, + 0x9b323022b7d6c3b4l }, + 0 }, + /* 10 << 136 */ + { { 0x057ef17a5ae6ad84l,0x9feae00b293a6ae0l,0xd18bb6c154266408l, + 0xd3d3e1209c8e8e48l }, + { 0xba8d4ca80e94fc8fl,0x80262ffc8a8ea0fel,0xac5b2855f71655fdl, + 0xa348f8fae9aced89l }, + 0 }, + /* 11 << 136 */ + { { 0x60684b69a5660af3l,0x69aad23b9066d14bl,0x4d9f9b49fa4d020al, + 0xafb54ec1b5cd6a4al }, + { 0x2b25fe1832fd864dl,0xee6945062b6b64d0l,0x954a2a515001d8aal, + 0x5e1008557082b5b3l }, + 0 }, + /* 13 << 136 */ + { { 0x20ecf71cbc90eb1bl,0x4234facf651c1df4l,0xc720fce9e681f678l, + 0x680becdda7c007f4l }, + { 0x7c08dc063181afeal,0x75c1b050a34eca91l,0x7d3479d54b9e2333l, + 0xed16640af3951aa3l }, + 0 }, + /* 15 << 136 */ + { { 0x911b596264723e54l,0x34384f8c004b327cl,0x06ca5c61b85435f2l, + 0x12e0cd25e2c1075cl }, + { 0xa4b84cb8ac727394l,0x50bd720492b352c1l,0xe85524a49cbd0fb4l, + 0x10b9274be7876024l }, + 0 }, + /* 16 << 136 */ + { { 0xef0a3fecfa181e69l,0x9ea02f8130d69a98l,0xb2e9cf8e66eab95dl, + 0x520f2beb24720021l }, + { 0x621c540a1df84361l,0x1203772171fa6d5dl,0x6e3c7b510ff5f6ffl, + 0x817a069babb2bef3l }, + 0 }, + /* 17 << 136 */ + { { 0xb7cf93c3aace2c6al,0x017a96e658ff1bbfl,0x3b401301624a8250l, + 0xf5ef158529266518l }, + { 0x3c968bef7585838dl,0x8e97d023853191abl,0x175022e4f6823389l, + 0xb6a3bfc2f6a9b4c1l }, + 0 }, + /* 19 << 136 */ + { { 0x515acf174591d77el,0xb393c89e3c3b25b6l,0x291e068e9c95abd7l, + 0x256b72c046c02544l }, + { 0x8172af03915ea92fl,0xc1b324ae4fcd0f03l,0x8abc779215108993l, + 0xe05fe6867ab815ael }, + 0 }, + /* 21 << 136 */ + { { 0xca08d4095bc42740l,0xdd2c19d3e26e2e60l,0x27afdeded7c091fal, + 0x3b943b0faf25cb22l }, + { 0x400af8be026047e9l,0x3149b35f772b8ff9l,0x3ddb2c06f17229d9l, + 0xcd604aeadac152fcl }, + 0 }, + /* 23 << 136 */ + { { 0xea2275311c0f6803l,0x9ae82d5ea394cc08l,0xc107a2cfbe32080cl, + 0x550f35a76429f6d7l }, + { 0x483c94dacfb70c0cl,0xf26f8e5d90190c94l,0x8574b3cf86bf2620l, + 0xe7258e45df9f482fl }, + 0 }, + /* 25 << 136 */ + { { 0x8f8dc582da46f1cfl,0x61d76cf91e1e7427l,0x8aceb48b306c84aal, + 0xecaa142f28ebff98l }, + { 0xac5bd940401d80fel,0x0caacb8fe800cf9el,0x99068da9b3359af5l, + 0x92fdd5795225b8c0l }, + 0 }, + /* 27 << 136 */ + { { 0x5a29d1c5ab56a3fbl,0x4e46ffc0a9aab4afl,0xa210472624d83080l, + 0xb5820998007f08b6l }, + { 0x9ce1188e4bc07b3el,0xbf6d0dbe32a19898l,0x5d5c68ea5b2350bal, + 0xd6c794eb3aa20b45l }, + 0 }, + /* 28 << 136 */ + { { 0x3de605ba9ec598cfl,0x1933d3ae4d3029ael,0x6bf2fabd9b140516l, + 0x712dfc5559a7d01cl }, + { 0xff3eaae0d2576366l,0x36e407f948701cf8l,0xede21d89b41f4bd4l, + 0xc5292f5c666eefa9l }, + 0 }, + /* 29 << 136 */ + { { 0x30045782c3ebcd77l,0xaa0cf3c73fdbe72el,0x719ec58ef8f43b39l, + 0x9716fb9972574d3al }, + { 0x300afc2b0d03ccd6l,0xb60016a34f3fac41l,0x8898910ea3a439f6l, + 0xdc00a99707ca11f5l }, + 0 }, + /* 31 << 136 */ + { { 0x291b15ee8ed34662l,0xb780d54b2ee422a7l,0x5b9e3788fcfe4ccbl, + 0x4554cb8cbe8b7c3al }, + { 0xfdaccc2209a85a7fl,0x51f4a8ec555497edl,0x07dc69037da33505l, + 0xa3bc8bfcbc1fc1dbl }, + 0 }, + /* 33 << 136 */ + { { 0x661638c151e25257l,0x0a6fd99c53304974l,0x29d8ae165078eec6l, + 0xed7512ad447b73del }, + { 0x0e21de607a4d0e9bl,0x842abd422462be01l,0x3be82afa5cddc709l, + 0x25bb9da99b52797dl }, + 0 }, + /* 34 << 136 */ + { { 0x80613af28adc986al,0x4602284935776a41l,0x17d33e0f4665d03cl, + 0xeb12eb6c0df12b50l }, + { 0x0f0effa0ee41527fl,0x8ca2edb680531563l,0x4c354679f28c52c3l, + 0x67f1ba5c2f6df66dl }, + 0 }, + /* 35 << 136 */ + { { 0x9c27207a2479fb3fl,0xef6e0f13515fb902l,0x3f7ad9e9d0d9436el, + 0x36eb4ea5893bbcf5l }, + { 0x5c53a2ac02b316b7l,0x10c75ee1f54f7585l,0x29e5879c3c7a4c1bl, + 0x77da3c82f29c67d6l }, + 0 }, + /* 36 << 136 */ + { { 0xf2b75d21ef78a852l,0xba38cd34dd31a900l,0x72b3a68658ffe18al, + 0x7464190cbfd95745l }, + { 0x406e532177ed6e81l,0x1af0975bde535eabl,0x66ba22c760c54c82l, + 0x88e3b1ceb00a2fe0l }, + 0 }, + /* 37 << 136 */ + { { 0xb6099b7df7e5c69bl,0x84aa1e26ba34ee2fl,0x5952600405c338bbl, + 0xe9a134374951a539l }, + { 0xb12276526ec196bdl,0x26a7be264b6dce36l,0x052e10a4e2a68458l, + 0x475fc74c1f38898bl }, + 0 }, + /* 39 << 136 */ + { { 0x120167fc0a3eb4e1l,0xaa94bc70c0c21204l,0x313cd835e1243b75l, + 0x3bb63fb20bfd6a4al }, + { 0xa615dcae21ef05cfl,0x63774c2ec23c3ee5l,0x39365b1fed0dfd65l, + 0xb610e6ff5d2a2d7dl }, + 0 }, + /* 40 << 136 */ + { { 0x55b7f977f0337b15l,0x3bc872a30e94973al,0x624ad983770deea0l, + 0xcaab336413a5efdbl }, + { 0x391dd0027a0d4247l,0x39590d5df312aed5l,0x532802c9351365acl, + 0xdd2e824578a2e22al }, + 0 }, + /* 41 << 136 */ + { { 0x81b0d7be7f774fb8l,0x62f32bb3aa412425l,0xbe7afe26bbcd2162l, + 0xa6ce167c53c7fa7dl }, + { 0x8deca64fc5c4fc5bl,0x70e546aba6efd2fel,0xf2d8495987ff672al, + 0x2ca551f249c3059el }, + 0 }, + /* 43 << 136 */ + { { 0x40b62d528eb99155l,0xe6b048947420a7e0l,0x9ebecb2bc685e58al, + 0x3ea642d8d3c8d2cbl }, + { 0x5340ac6ed489d0dfl,0xf3846d08c2b7588el,0x4cecd8a0611c289bl, + 0xdddc39c50dd71421l }, + 0 }, + /* 44 << 136 */ + { { 0x98c6a6a52ebee687l,0xcdf65bfa56c1c731l,0x48e8132772def210l, + 0x4ea119418083b5a5l }, + { 0x3fdcea4fffebb525l,0x55aaea19fb50bf72l,0x5fbedc0a2a85b40cl, + 0x0d6fd954bf44f29fl }, + 0 }, + /* 45 << 136 */ + { { 0x83a8302a9db4071el,0x52f104436f8ae934l,0x96de829d175b800al, + 0x20ff5035373e97cel }, + { 0xf58660185f65356al,0x992c15054c8cd782l,0x0b962c8eb57d727fl, + 0xe8a9abc92bba8bc7l }, + 0 }, + /* 46 << 136 */ + { { 0x81a85ddd7cf2b565l,0x5e51e6afc34a0305l,0xa8d94ccefbc89faal, + 0x2bfd97c1e68cd288l }, + { 0x16d79c21af2958b8l,0x5e5d989defda7df8l,0x6d2f0ca6ff734c8al, + 0xfa5b8dd32cc9bafel }, + 0 }, + /* 47 << 136 */ + { { 0x5787a9934e6ed688l,0x6815f3b5aab42f46l,0x7960f45b093c6c66l, + 0xb2b9829728be10cfl }, + { 0x1d4c7790296568cdl,0xa279a877f048e194l,0xcf7c20f4c6a58b4el, + 0xf0c717afa1f9c00fl }, + 0 }, + /* 48 << 136 */ + { { 0x8a10b53189e800cal,0x50fe0c17145208fdl,0x9e43c0d3b714ba37l, + 0x427d200e34189accl }, + { 0x05dee24fe616e2c0l,0x9c25f4c8ee1854c1l,0x4d3222a58f342a73l, + 0x0807804fa027c952l }, + 0 }, + /* 49 << 136 */ + { { 0x79730084ba196afcl,0x17d38e98054bd539l,0xc5cfff3918583239l, + 0x4b0db5a2d9adbee6l }, + { 0x9bc9f1e3c2a304e8l,0xbaa61de7de406fa8l,0x8e921ca9e4bec498l, + 0xd9f4e5ae6604ab02l }, + 0 }, + /* 51 << 136 */ + { { 0xdf6b97b5b37f2097l,0x7576c3f9b4a5d2b9l,0x6eb697ed3588cabbl, + 0x4d75b38622598d8fl }, + { 0x4e6d93b522ff55e8l,0x4620ec635b8f7edal,0xd5006209f97b7749l, + 0x9e22e3a84da8b464l }, + 0 }, + /* 52 << 136 */ + { { 0xbabfb7f82e8f326fl,0xed9cac225625a519l,0xf1109c1a0edae0a9l, + 0x45f80a9858521259l }, + { 0x37a44b075ab71f44l,0x21699eb64a21161bl,0xb523fddf56fe67eel, + 0x9f5c3a2120b9f72el }, + 0 }, + /* 53 << 136 */ + { { 0x12c1131508b75673l,0xfa20121823b096d6l,0x839f01aeeacd6537l, + 0x0e592be787df32cal }, + { 0xfe3f65ff8b7dd0fcl,0xed09b4875c1d9a80l,0x8c09dd97b79786d8l, + 0x74eba2806c5bc983l }, + 0 }, + /* 55 << 136 */ + { { 0xf917704862987b50l,0xcc84cdc6bc4ac456l,0x8bd2c922ae08fe12l, + 0x09d5f661fc2d06c7l }, + { 0xd10ac6dd9457d47fl,0x65aa30a23668060cl,0x33cddac6745161fcl, + 0xf4c18b5ea51e540fl }, + 0 }, + /* 57 << 136 */ + { { 0x591c064ede723c1fl,0x92e5d4e601a4adael,0x3d7ee8a3145716ecl, + 0x0ef4c62061727816l }, + { 0x0e17c576f1bf6d6el,0x173104015ae18045l,0xdad620aae9589b75l, + 0xb10c7e2d0eda4905l }, + 0 }, + /* 59 << 136 */ + { { 0xb8020f16aa08df6fl,0x03cf58ffd67054e9l,0x302e003c11fe3d1al, + 0x9c194bc1c638a3ecl }, + { 0x8ed3cb3adefd3f1el,0xc4115e079bf39de4l,0x8dece48bdf46fdf6l, + 0xebd1dbcf30eafeafl }, + 0 }, + /* 60 << 136 */ + { { 0x058eb276fba319c5l,0xd33a91127f7fa54al,0xf060c1b4932a2dabl, + 0xce3a224e79c7d9bfl }, + { 0x6fb0388c0ba92823l,0x8d31738a69787881l,0x2d86eb0203cd00b7l, + 0x4e6e44512b69911bl }, + 0 }, + /* 61 << 136 */ + { { 0xff2efe1cfdcca1cfl,0x08f22c69b5bb71e3l,0xc63f4a9f7023076el, + 0x88fb2aa0ce0c490el }, + { 0xcc7c97f91f77783cl,0x360026d942ab36b7l,0x547c34ecefd68f70l, + 0xebe7f99efbabfdabl }, + 0 }, + /* 63 << 136 */ + { { 0xe7c1c1788613e87al,0xb035d65e60b82654l,0x055a82d03583a254l, + 0x27ce1ffc9b3b22fal }, + { 0x0cf904917ec83cd5l,0xfc6c21805604aa40l,0x1330604099357428l, + 0x9b0982f9ad4818b7l }, + 0 }, + /* 64 << 136 */ + { { 0xc222653a4f0d56f3l,0x961e4047ca28b805l,0x2c03f8b04a73434bl, + 0x4c966787ab712a19l }, + { 0xcc196c42864fee42l,0xc1be93da5b0ece5cl,0xa87d9f22c131c159l, + 0x2bb6d593dce45655l }, + 0 }, + /* 65 << 136 */ + { { 0x3a6080d9fb56bc3al,0xf1552dcad6212d7el,0x977ac5b59420f4f6l, + 0xef914d370e3cd97fl }, + { 0x807bd6e69c04f768l,0x743a7b552bb803f6l,0x7f5c20804215f4b0l, + 0x41e331288fc6ce42l }, + 0 }, + /* 71 << 136 */ + { { 0x5a31c9ac61e6a460l,0x55102e4093e7eeddl,0x969fe0612da6adcel, + 0xe8cddc2f3ffea1d9l }, + { 0xaa26c6b1f0f327c5l,0x9e5b63743544f5e1l,0x5159fa1ddbaa685bl, + 0x9892d03aa7f44b99l }, + 0 }, + /* 77 << 136 */ + { { 0x4dfcbf12e2c6fc1fl,0x703f2f5b7535ac29l,0x78f8617e82f7dc0fl, + 0x54b835ff853e792dl }, + { 0x3cc7f000df9f7353l,0x0d7ffd68db5a157al,0x2c1c33691672b21cl, + 0x694b4904ac970ef8l }, + 0 }, + /* 83 << 136 */ + { { 0xd655bc42c1d2c45cl,0x572f603cbd22b05fl,0xa7fbf09388e4531al, + 0x8d38bbd91fdde98dl }, + { 0x16cc2aaa73b0fa01l,0x515019a25e8ffb04l,0xb075990611e792ccl, + 0x89df06f399112c90l }, + 0 }, + /* 89 << 136 */ + { { 0x26d435c2481b46dal,0x73ab7e96266e9b3al,0x22d5b1db3c613c40l, + 0x9de4021c6727e399l }, + { 0x451ebba56051f8c9l,0xa37f6ec52c281a58l,0x3d7a28fe0e9f4cc5l, + 0x0f45bcd655b64df7l }, + 0 }, + /* 95 << 136 */ + { { 0xba2a718c66616fbel,0x4b27810b3369a9acl,0x50b8391a2b426d5fl, + 0x420c88efa626fa05l }, + { 0xe39cef97b9c39a30l,0xcae7cde85e67e5d0l,0x3821f8319a58e521l, + 0xbf474d1941479509l }, + 0 }, + /* 101 << 136 */ + { { 0x401bbab58fb15118l,0xb0376892dbf38b39l,0x10e4b9dd3a3ca42al, + 0xa69c2693f8063ffel }, + { 0xe10facdde07cb761l,0x96f4dde831d7759al,0xd702fdecc2cc7f9fl, + 0x9e87e46e1ac0162cl }, + 0 }, + /* 107 << 136 */ + { { 0xb6cd60518479ca8fl,0xcca345e60968f6c7l,0x7b57248a64a9afe7l, + 0x5552e3511d0d4db9l }, + { 0x8f749b199dc68aabl,0x0fb86f06db1f7819l,0x23b300963143ac09l, + 0x61c166d8abfbcb9bl }, + 0 }, + /* 113 << 136 */ + { { 0x4c96e85a43101165l,0x393a882fcf39bd19l,0xef9e1d42c2df6f33l, + 0xe1775c990278f088l }, + { 0xb1581929a9250d4al,0x582b0608c4168873l,0x0b3ffba3a1e68cd8l, + 0x3f78147ef9490897l }, + 0 }, + /* 116 << 136 */ + { { 0x277b5177eb18ff20l,0x48002e9828f06d62l,0xece8d6c30e506d8dl, + 0x5cde0a58cd9ff963l }, + { 0x3b97cdb74e3baa0el,0x50560c0b631238f9l,0xe1c31b35cf79793dl, + 0x95d12f14355e2178l }, + 0 }, + /* 119 << 136 */ + { { 0x0143f695bcc31b77l,0x3627aed14c49b65al,0x6e4f7a9ce441c183l, + 0xb708c79de1bfa0a3l }, + { 0xdbf0fc313a0726b8l,0xe04d82a8852d78bbl,0xb859001e3be5d398l, + 0x92dcc20c8e89bd11l }, + 0 }, + /* 125 << 136 */ + { { 0x5f2416a3df9026b4l,0xffc01f3afcb29a1bl,0x18d02c9f1d94b20fl, + 0xd93b0f2f81cfdef3l }, + { 0xe6b0fd4713adf5f2l,0xcc9067b7ba06dff3l,0xb48c0cbb2256f842l, + 0xc2ae741dfd34df2fl }, + 0 }, + }, + { + /* 0 << 144 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 144 */ + { { 0x80531fe1c63c4962l,0x50541e89981fdb25l,0xdc1291a1fd4c2b6bl, + 0xc0693a17a6df4fcal }, + { 0xb2c4604e0117f203l,0x245f19630a99b8d0l,0xaedc20aac6212c44l, + 0xb1ed4e56520f52a8l }, + 0 }, + /* 3 << 144 */ + { { 0x18f37a9c6bdf22dal,0xefbc432f90dc82dfl,0xc52cef8e5d703651l, + 0x82887ba0d99881a5l }, + { 0x7cec9ddab920ec1dl,0xd0d7e8c3ec3e8d3bl,0x445bc3954ca88747l, + 0xedeaa2e09fd53535l }, + 0 }, + /* 4 << 144 */ + { { 0xa12b384ece53c2d0l,0x779d897d5e4606dal,0xa53e47b073ec12b0l, + 0x462dbbba5756f1adl }, + { 0x69fe09f2cafe37b6l,0x273d1ebfecce2e17l,0x8ac1d5383cf607fdl, + 0x8035f7ff12e10c25l }, + 0 }, + /* 5 << 144 */ + { { 0xb7d4cc0f296c9005l,0x4b9094fa7b0aebdbl,0xe1bf10f1c00ec8d4l, + 0xd807b1c4d667c101l }, + { 0xa9412cdfbe713383l,0x435e063e81142ba1l,0x984c15ecaf0a6bdcl, + 0x592c246092a3dab9l }, + 0 }, + /* 7 << 144 */ + { { 0x9365690016e23e9dl,0xcb220c6ba7cc41e1l,0xb36b20c369d6245cl, + 0x2d63c348b62e9a6al }, + { 0xa3473e19cdc0bcb5l,0x70f18b3f8f601b98l,0x8ad7a2c7cde346e4l, + 0xae9f6ec3bd3aaa64l }, + 0 }, + /* 9 << 144 */ + { { 0x030223503274c7e1l,0x61ee8c934c4b6c26l,0x3c4397e3199389cel, + 0xe0082600488757cel }, + { 0xaac3a2df06b4dafbl,0x45af0700ddff5b6al,0x0a5974248c1d9fa0l, + 0x1640087d391fc68bl }, + 0 }, + /* 10 << 144 */ + { { 0x26a43e41d07fa53dl,0x3154a78a74e35bc5l,0x7b768924e0da2f8cl, + 0xba964a2b23613f9al }, + { 0x5a548d35ba1d16c4l,0x2e1bfed1fb54d057l,0xff992136bc640205l, + 0xf39cb9148156df29l }, + 0 }, + /* 11 << 144 */ + { { 0xf4873fcf4e5548bdl,0x8725da3f03ce57f0l,0xd82f5c95ca953258l, + 0xac647f127cf0747el }, + { 0xff2038b02d570bd5l,0xb0c2a767a13ae03fl,0xebaa27cde9932d16l, + 0xa686e3fc1234e901l }, + 0 }, + /* 13 << 144 */ + { { 0x9f80435e63261eccl,0x6302a62e4337d6c9l,0x91916a49ca4958a0l, + 0x554958993149d5d3l }, + { 0x378d020b9f91de3cl,0x47b839a34dd25170l,0x2825854138b7f258l, + 0xea5b14f7437e7decl }, + 0 }, + /* 15 << 144 */ + { { 0x74f08736b0018f44l,0xf4a03417b446d0f5l,0x66a4aa2fa40ca6b2l, + 0x215679f0badb60edl }, + { 0x3871195a323e4eefl,0x8f0940c320952b16l,0xfe8dac62879d5f7dl, + 0x649cb623c1a6e875l }, + 0 }, + /* 16 << 144 */ + { { 0xecaff541338d6e43l,0x56f7dd734541d5ccl,0xb5d426de96bc88cal, + 0x48d94f6b9ed3a2c3l }, + { 0x6354a3bb2ef8279cl,0xd575465b0b1867f2l,0xef99b0ff95225151l, + 0xf3e19d88f94500d8l }, + 0 }, + /* 17 << 144 */ + { { 0xa26a9087133ec108l,0x5dc5699f2712bdc0l,0x96903f4dd14224a9l, + 0x3da5992429e47b80l }, + { 0xb717712ff9dbba5al,0x9e52004b756391c9l,0xe669a11dcc9d219cl, + 0x3b6e6b84d1d6c07dl }, + 0 }, + /* 19 << 144 */ + { { 0x5feec06a676feadbl,0xfc449bc59d69f322l,0x1d8d7b5e7cda8895l, + 0x5ed54dc11a3314a7l }, + { 0x1a11d2ae6de889c0l,0xb2a979724ced2bd9l,0x6ecf6989306a5ef6l, + 0x1611d57b8cc8a249l }, + 0 }, + /* 21 << 144 */ + { { 0x2d9942ba007cbf87l,0x4e62bce6df3fc926l,0xe7eee5b0e4560affl, + 0xe51963bb7cb009b7l }, + { 0xaa5118cee29b37ddl,0x5cd84a4747263903l,0x3050caa6620055d8l, + 0x7ef576a76c4b1e3dl }, + 0 }, + /* 23 << 144 */ + { { 0x9026a4dde6008ff1l,0x49e995ad1c8cd96cl,0x80722e73503e589bl, + 0x05bcbce184c2bc26l }, + { 0x255f9abbd4682c2cl,0xc42bcfc2f084d456l,0xa0eae9b0641c0767l, + 0x1b45632d864c9a2dl }, + 0 }, + /* 25 << 144 */ + { { 0xcf25793b6ae024e0l,0x1b6607b484b5c4b0l,0x9579fa903f1624c8l, + 0x37fb65be68bd57e8l }, + { 0xd693a55efc39c203l,0x4e267ac4c87252e9l,0xb8d78bb09f899413l, + 0xe4c014070b3b8508l }, + 0 }, + /* 27 << 144 */ + { { 0x662906e5bc3f3553l,0xde38d53531459684l,0x8f46a8c634f7280dl, + 0xaaf91b873d24198el }, + { 0xecd5ee115f9b117el,0xce00ffbe50ae8ddal,0x263a3d4e7710a9ael, + 0x0ff3f721f26ba74fl }, + 0 }, + /* 28 << 144 */ + { { 0x4a8a4f47f0cefa69l,0xdc8e4cbaa4546866l,0x359ba69b23f603c1l, + 0xdab4d601187b7ac5l }, + { 0xa6ca4337c1ebc8d9l,0x9fa6585452b4074bl,0x1a4b4f81902fb733l, + 0xd2bb5d7aa525deaal }, + 0 }, + /* 29 << 144 */ + { { 0xcc287ac2e6b3577al,0xd7528ca7f612003bl,0x8afdb6f12c1400b8l, + 0x103a2ed346a2dd8dl }, + { 0xc8f8c54d2ee21339l,0x8f011b92355a2d20l,0x81c6fc9f1346f2acl, + 0xdb6042f005a6d24bl }, + 0 }, + /* 31 << 144 */ + { { 0xfc90e3630da4f996l,0x8ceca49daa6d6fe4l,0x1084affdbdfc619bl, + 0x2029f672c1140b04l }, + { 0x606ec25f136f3e5el,0x6d24149b02224c4al,0xabb0f142cfdfcf4cl, + 0xe40d0419fab1a0edl }, + 0 }, + /* 33 << 144 */ + { { 0xcfdd08265cbccb84l,0x2258a16e88ad93c4l,0xb3ac365e728c5ad3l, + 0x0bbf97808560df1fl }, + { 0x42d08a39bad8c7b8l,0x1e3960106d3e8b91l,0xc332b39910274f58l, + 0xe0a84dacce2ea778l }, + 0 }, + /* 34 << 144 */ + { { 0x113e1189ff432945l,0x4a0d2c3d04e1106cl,0xcde487744f3597b1l, + 0x853b029174fa26eal }, + { 0x2149e0ff02662e26l,0xb3181eaa5e6a030fl,0x086fc2159b006340l, + 0xa1df84a694a4e0bbl }, + 0 }, + /* 35 << 144 */ + { { 0xc2cbd80ac99f8d3dl,0xe24b9d8f50ecf4f4l,0xf18d34728ecb126al, + 0x83966662e1670aael }, + { 0x1cece80fda5f594el,0x545e94ae65f391e0l,0xf3286dff93f98bb7l, + 0xf945e6cdf5abf176l }, + 0 }, + /* 36 << 144 */ + { { 0x00ba5995dd95ac33l,0xa4957a40738f3bf4l,0x073539f599438a85l, + 0xcc9c43acc2eb1411l }, + { 0xe27501b5be2ec3d2l,0xa88d4ed057a85458l,0x870ae236755c8777l, + 0x0933c5af89216cbal }, + 0 }, + /* 37 << 144 */ + { { 0xb5feea219e40e37fl,0x8c5ccb159e20fd60l,0xaeddc502ce8209a1l, + 0xbdf873cc11e793b3l }, + { 0xbc938103f0de8db5l,0x619fb72fb0e9d3d5l,0x800147cb588ed2adl, + 0x260f92bb7901ced8l }, + 0 }, + /* 39 << 144 */ + { { 0x72dd9b089848c699l,0xc6086381185dacc1l,0x9489f11ff7d5a4c8l, + 0xedb41d5628dee90fl }, + { 0x1091db6b09af693cl,0xc7587551ae4b6413l,0x806aefb0768227adl, + 0x4214b83eafb3c88el }, + 0 }, + /* 40 << 144 */ + { { 0xddfb02c4c753c45fl,0x18ca81b6f9c840fel,0x846fd09ab0f8a3e6l, + 0xb1162adde7733dbcl }, + { 0x7070ad20236e3ab6l,0xf88cdaf5b2a56326l,0x05fc8719997cbc7al, + 0x442cd4524b665272l }, + 0 }, + /* 41 << 144 */ + { { 0x748819f9aa9c0ef5l,0xd7227d8ba458ad48l,0x8d67399f27aef626l, + 0xc6241a1859bf0a4cl }, + { 0xed9b0bfcc31cb9bbl,0x591254f896142555l,0x80e4bab461134151l, + 0x7c5e680243efbd83l }, + 0 }, + /* 43 << 144 */ + { { 0x7f3f5a1706b9b7ddl,0x392132e75faeb417l,0x508ac4788fae38a2l, + 0x2b854ead0d3499c3l }, + { 0x26a687d8ef18bf0fl,0x62ff0c4a8ae00b61l,0x84111011f48578f2l, + 0xa879f383cd0fcd3al }, + 0 }, + /* 44 << 144 */ + { { 0xeb7615aa202992f0l,0xde0562b38361d0b3l,0x789a302862027ee0l, + 0xe3e3e9921048f899l }, + { 0x07945c246deadab4l,0xeb06a15ec77d894el,0xb825af36bab1416bl, + 0x99083c4df4b4e04fl }, + 0 }, + /* 45 << 144 */ + { { 0x4684a8f27b3ad6c3l,0x58238dbd928d9b6bl,0x31865b998da2c495l, + 0xc1ca784fb8e7cda1l }, + { 0xc9605dc71e081572l,0x8f560bcdef8ed104l,0x51f73981bd3feaedl, + 0xc778aa4e4251c88dl }, + 0 }, + /* 46 << 144 */ + { { 0x9c0daa63aa502800l,0x73c7959a1e15b9bdl,0xd0447bcb7ab10f6cl, + 0x05b8fbc8b8311bdel }, + { 0xa8a74be1915d5c4el,0x38d41c1e0b7c0351l,0x5bb2d49ff52d6568l, + 0x6c48d8eed5e43593l }, + 0 }, + /* 47 << 144 */ + { { 0x387b26d554159498l,0x92e92fad1ec34eb4l,0x0f88705e7a51b635l, + 0x66bcbf4dedca735fl }, + { 0x0a4c6112dcb896ccl,0x148e1dfe6fc72ad9l,0x3de977fd2b4c9585l, + 0x0cd6e65f741e62cal }, + 0 }, + /* 48 << 144 */ + { { 0x7807f364b71698f5l,0x6ba418d29f7b605el,0xfd20b00fa03b2cbbl, + 0x883eca37da54386fl }, + { 0xff0be43ff3437f24l,0xe910b432a48bb33cl,0x4963a128329df765l, + 0xac1dd556be2fe6f7l }, + 0 }, + /* 49 << 144 */ + { { 0x98ae40d53ce533bal,0x10342e1931fdd9c2l,0x54a255c8abf8b2bfl, + 0x8facc41b15f6fef7l }, + { 0x2e195565bc65b38bl,0xb9f3abaaeaea63cbl,0xede2ab9bf2b7518bl, + 0x5e84102ce9ea3d81l }, + 0 }, + /* 51 << 144 */ + { { 0x162abc35113bc262l,0x8012f06829eb3fd4l,0x0e2727eb2c1ccf9cl, + 0x89561ff44b455b20l }, + { 0xc48db835ee3b1fd4l,0x4075ca86095bbfa7l,0x0c498d7d98745182l, + 0x828fb93c5dfb5205l }, + 0 }, + /* 52 << 144 */ + { { 0xf95c7a5f0a76333bl,0x07603929cd607927l,0xabde328591028d3el, + 0x55765e8fa032a400l }, + { 0x3041f2cabed17cd7l,0x018a5b7b9a9e5923l,0xca4867975bb9bae3l, + 0x741c802ecc382cb5l }, + 0 }, + /* 53 << 144 */ + { { 0x182a10311e5a3d8el,0xc352b8c8986c4d10l,0x7c50a172434c02ebl, + 0x121d728c4420c41cl }, + { 0x0f8eca2a8a51812fl,0xdb6c4a4ea5158430l,0x67944e0b8d8f4144l, + 0x387cc2052405c77al }, + 0 }, + /* 55 << 144 */ + { { 0x98b36eb47e95ad76l,0x1973fa7d5f7e5ff7l,0xc4827abc6cc8a25cl, + 0x4263a0d3ec822ae4l }, + { 0x49f113f35217a6f4l,0xf27cc9bb81748aa6l,0x9cb81d97d822e08el, + 0x698d2826b5c360bcl }, + 0 }, + /* 57 << 144 */ + { { 0x895f81514eb6d0b8l,0x32ef71df9f786536l,0x032a449430379a79l, + 0xa8c1076218bdb83fl }, + { 0x7a3b0b8fe53a4064l,0x0e724a54e2ce89b7l,0x565baeba7a31f6bcl, + 0x12b9fa6387d18a7bl }, + 0 }, + /* 59 << 144 */ + { { 0x027231a3585bcfbdl,0x8690e977dca24269l,0x229c021afc6f1422l, + 0xd98050d044084cabl }, + { 0x6add95d79d4fd09al,0x12484c68c15b24ddl,0xa79a8f4facf4f551l, + 0xf53204e27a83cbecl }, + 0 }, + /* 60 << 144 */ + { { 0xbc006413a906f7aal,0x9c8cd648bbeaf464l,0xaf5c7c64fb78cdf2l, + 0xe45839eafabc2375l }, + { 0x1eb89bd150012172l,0x9d0d76194488518cl,0xd55a7238bd534d32l, + 0x48f35d5e95b4fe55l }, + 0 }, + /* 61 << 144 */ + { { 0xa6c5574f3e70a35al,0x35c11b5a8df97d97l,0x8f629f6cda85dd27l, + 0x94dab294c218452el }, + { 0xa2e1882e8916c731l,0xc02ce77c8929e350l,0xa7ed351fe4eff8afl, + 0xeb76ef0654c3e1c1l }, + 0 }, + /* 63 << 144 */ + { { 0xc31d7cf87e3f5be5l,0x1472af0d3ce7f3a0l,0x226414f8f962e1afl, + 0xd318e3df16f54295l }, + { 0x9a3f6aaf41477cd3l,0x7034172f66ec6b2el,0xbea54eb537413a62l, + 0x79f81262dc515e73l }, + 0 }, + /* 64 << 144 */ + { { 0x994f523a626332d5l,0x7bc388335561bb44l,0x005ed4b03d845ea2l, + 0xd39d3ee1c2a1f08al }, + { 0x6561fdd3e7676b0dl,0x620e35fffb706017l,0x36ce424ff264f9a8l, + 0xc4c3419fda2681f7l }, + 0 }, + /* 65 << 144 */ + { { 0xb71a52b8b6bf8719l,0x0c7701f73196db36l,0xff1b936f53141cf4l, + 0x684d8a3c1b94a31cl }, + { 0xe555633ab52386e1l,0x9353a2af91450578l,0xc53db6fab99b14bcl, + 0x1f2d42adcf619d36l }, + 0 }, + /* 71 << 144 */ + { { 0xbeb535ef3851c573l,0x3105fff585589843l,0xbe9f62a1d47aaf06l, + 0x6bb2ee5d107e1131l }, + { 0x82530247a4a7699fl,0x3fb475e144872afbl,0x8ad43fd73c4c49f2l, + 0x3f7632882e045fc4l }, + 0 }, + /* 77 << 144 */ + { { 0x48440beb2924d7b2l,0x234163809c88fc57l,0xdc1d23d54ab08c2bl, + 0x576400b6e70feab0l }, + { 0x3b8afb8ba66da779l,0x7a7e3bf445468f16l,0x1976ddf3231f79dfl, + 0xbe61c170b8531a9el }, + 0 }, + /* 83 << 144 */ + { { 0xf8d2dc768bf191b2l,0x3269e68813a39eb9l,0x104bb84be755eccfl, + 0xb8d1330f2868f807l }, + { 0x2b29c74cb06c6059l,0x3648baa1a6440a26l,0x5dfae323f1e6b2c9l, + 0x9d0319b79330ac0al }, + 0 }, + /* 89 << 144 */ + { { 0x526ba3770e708bb2l,0x95c21ba327565dd9l,0x7071f46d48a0a873l, + 0xe4b9959efed6cc74l }, + { 0x1b16bfd1e08a5afal,0xc87fec98d1789782l,0x200186e946cfd068l, + 0x88ea35a7280bf3ebl }, + 0 }, + /* 95 << 144 */ + { { 0x9e31943d42ac0e6cl,0xe61374cf1db8e40fl,0xbe27ea35a27db609l, + 0x7c5b91d67bf192e9l }, + { 0xc2af846defd0a24bl,0x1b2efc37669b647al,0xbfc3c38e5e58ef8al, + 0xb6afb167e13ab5a2l }, + 0 }, + /* 101 << 144 */ + { { 0x08612d29b9f2aad4l,0x43c41330ad09dd17l,0xa45cb84a9f740519l, + 0x0a9ea9a7512ec031l }, + { 0x6e90dccaee747f35l,0xe4388bd1f0a1479bl,0x966140c4e20a9029l, + 0x1bb1f65d7dd956abl }, + 0 }, + /* 107 << 144 */ + { { 0x066d206ea8f12bb3l,0xc9023b1b4325ec13l,0x1f56c72c96ead8ddl, + 0x454050fd8003e4c2l }, + { 0x9ca258a58917aa9dl,0xfe24b282d94593cfl,0xea66c203752741cfl, + 0x5714268c295a895el }, + 0 }, + /* 113 << 144 */ + { { 0x72a9fbecc177d694l,0x38bb9387d68454d3l,0xa3d347bf590bc7d2l, + 0xcb6e292605ccc234l }, + { 0x588abfcf0d393c01l,0xf053dadf539e5568l,0xad7480fef2a8b157l, + 0xff28c8bb018cac8fl }, + 0 }, + /* 116 << 144 */ + { { 0x12f1a00e7f5b8821l,0x0afa44e489b4b0cel,0x2dcaad8f6006338el, + 0x79c022cdba41242bl }, + { 0x7f6ef7e17871d350l,0x946c2a91674253adl,0xf686d137a9cbbdd9l, + 0xa47ce2eaf7d4f9f2l }, + 0 }, + /* 119 << 144 */ + { { 0x1824991b205d40d6l,0x49cca1c085046a90l,0x7e23c1acd005e3c2l, + 0x093a9ae6d102c8ffl }, + { 0xf4791082d2f40843l,0xe456021811645483l,0x8a59c3b0fd3a6b39l, + 0x39130e7f820de158l }, + 0 }, + /* 125 << 144 */ + { { 0xf7eef88d83b90783l,0xff60762af336d581l,0xf64f2d5dd801f5a0l, + 0x672b6ee7d6b3b8b9l }, + { 0xa2a2dceb08034d69l,0x3eca27f635638218l,0xe7065986fa17fefdl, + 0xf1b74445f5803af1l }, + 0 }, + }, + { + /* 0 << 152 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 152 */ + { { 0x32670d2f7189e71fl,0xc64387485ecf91e7l,0x15758e57db757a21l, + 0x427d09f8290a9ce5l }, + { 0x846a308f38384a7al,0xaac3acb4b0732b99l,0x9e94100917845819l, + 0x95cba111a7ce5e03l }, + 0 }, + /* 3 << 152 */ + { { 0x37a01e48a105fc8el,0x769d754a289ba48cl,0xc08c6fe1d51c2180l, + 0xb032dd33b7bd1387l }, + { 0x953826db020b0aa6l,0x05137e800664c73cl,0xc66302c4660cf95dl, + 0x99004e11b2cef28al }, + 0 }, + /* 4 << 152 */ + { { 0x214bc9a7d298c241l,0xe3b697ba56807cfdl,0xef1c78024564eadbl, + 0xdde8cdcfb48149c5l }, + { 0x946bf0a75a4d2604l,0x27154d7f6c1538afl,0x95cc9230de5b1fccl, + 0xd88519e966864f82l }, + 0 }, + /* 5 << 152 */ + { { 0x1013e4f796ea6ca1l,0x567cdc2a1f792871l,0xadb728705c658d45l, + 0xf7c1ff4ace600e98l }, + { 0xa1ba86574b6cad39l,0x3d58d634ba20b428l,0xc0011cdea2e6fdfbl, + 0xa832367a7b18960dl }, + 0 }, + /* 7 << 152 */ + { { 0x1ecc032af416448dl,0x4a7e8c10ec76d971l,0x854f9805b90b6eael, + 0xfd0b15324bed0594l }, + { 0x89f71848d98b5ca3l,0xd01fe5fcf039b3efl,0x4481332e627bda2el, + 0xe67cecd7a5073e41l }, + 0 }, + /* 9 << 152 */ + { { 0x2ab0bce94595a859l,0x4d8c2da082084ee7l,0x21ff8be5acca3d3cl, + 0xd8b805337827f633l }, + { 0xf74e8c026becabbfl,0x9fae4dbefede4828l,0xd3885a5b3cc46bcfl, + 0x2d535e2b6e6ad144l }, + 0 }, + /* 10 << 152 */ + { { 0x63d3444507d9e240l,0x6fbadf4338cff7e6l,0x8717624a959c9461l, + 0xd7d951c411fb775bl }, + { 0x4049161af6fc3a2bl,0x0dfa2547a1a8e98dl,0xeca780d439c2139cl, + 0xd8c2d8cbd73ea8efl }, + 0 }, + /* 11 << 152 */ + { { 0x3aa1974f07605b28l,0x4f3d82a71e296255l,0xbbe5ea03b4e23f16l, + 0x8f5c6c6b4e654193l }, + { 0x27181182d3e8ab01l,0xc68bb231f3ba6bc2l,0x90a244d820af1fd7l, + 0x605abc055b713f4fl }, + 0 }, + /* 13 << 152 */ + { { 0xca5fe19bd221991al,0x271ff066f05f400el,0x9d46ec4c9cf09896l, + 0xdcaa8dfdec4febc3l }, + { 0xaa3995a0adf19d04l,0xc98634239da573a6l,0x378058b2f2465b2bl, + 0x20d389f9b4c31612l }, + 0 }, + /* 15 << 152 */ + { { 0xd7d199c7b7631c9dl,0x1322c2b8bb123942l,0xe662b68fbe8b6848l, + 0xc970faf2cde99b14l }, + { 0x61b27134b06655e5l,0xadcef8f781365d89l,0x917b5ab521b851aal, + 0x4f4472121cf694a7l }, + 0 }, + /* 16 << 152 */ + { { 0x488f1185ca8d9d1al,0xadf2c77dd987ded2l,0x5f3039f060c46124l, + 0xe5d70b7571e095f4l }, + { 0x82d586506260e70fl,0x39d75ea7f750d105l,0x8cf3d0b175bac364l, + 0xf3a7564d21d01329l }, + 0 }, + /* 17 << 152 */ + { { 0x241e3907fe44e547l,0x42d464c36b992187l,0xeaa8fa989ba72f28l, + 0x965a8b8f6afbb81fl }, + { 0x69356a7a8b375ea5l,0x22501ec741bdcc83l,0xf80f4e1445fb180cl, + 0xc0b12e95f5e1b822l }, + 0 }, + /* 19 << 152 */ + { { 0x977234e05483dc02l,0x0167430c13d8dcb2l,0xa9971278049912edl, + 0xab044b18ca40fa39l }, + { 0xac9587449ff3896cl,0x75bb32eb860d1240l,0xf807071f6b958654l, + 0x67d2d3dc7121b4b6l }, + 0 }, + /* 21 << 152 */ + { { 0x3b61e67722f9f017l,0x9c593eb1a8541696l,0xbeba950050eda653l, + 0x07b5a48f5e673f6al }, + { 0x748dca0013257aa3l,0x6bbddf9a7372e942l,0xc012f4badde83977l, + 0x6e59b327392ddb53l }, + 0 }, + /* 23 << 152 */ + { { 0xb2f3fff641356603l,0x50e63537545f042bl,0x55e5149770eb530dl, + 0x5a7383c310860c3bl }, + { 0x7be30382ea669a09l,0xfdf735d289cc1c7fl,0x6e51ed844e0607cfl, + 0xdab566df4893795el }, + 0 }, + /* 25 << 152 */ + { { 0x20e3be0f8920690dl,0x98db80eaac279c05l,0x4cd5c60a44b8a4f8l, + 0xeda7e91c7b0335f4l }, + { 0x45c1302a41ee5713l,0x1f6455fe588508d0l,0x82cb7311163d2fc3l, + 0xe866b90322f10b71l }, + 0 }, + /* 27 << 152 */ + { { 0xc217a2e259b4041el,0x85b96ce274526cbfl,0xcbfc4f5473f12687l, + 0x097caa5fd40225e7l }, + { 0x0871ad406e91293fl,0x5f2ea207033b98ecl,0x0b3b8fac1f27d37al, + 0x7d72dd4c7f03876cl }, + 0 }, + /* 28 << 152 */ + { { 0xb51a40a51e6a75c1l,0x24327c760ea7d817l,0x0663018207774597l, + 0xd6fdbec397fa7164l }, + { 0x20c99dfb13c90f48l,0xd6ac5273686ef263l,0xc6a50bdcfef64eebl, + 0xcd87b28186fdfc32l }, + 0 }, + /* 29 << 152 */ + { { 0x2f0c49ac95861439l,0xcdcb051b2e36e38al,0x459474080ae20c0cl, + 0x374baad2dddf0aabl }, + { 0x291abc85d5d104a4l,0x0758001958a0657cl,0xd0f428e1a905ea13l, + 0x12599ddcf7241dbfl }, + 0 }, + /* 31 << 152 */ + { { 0x16222ce81bc3c403l,0xbacc1508fc13ca02l,0xfa98db4d920ee8e9l, + 0xe5fc39c4df12a359l }, + { 0x4e8c9b90188733e8l,0x04283dd81394936cl,0x93b3db51cd130432l, + 0x33bfe3163c93ce31l }, + 0 }, + /* 33 << 152 */ + { { 0xb48591e9840b1724l,0x1009559f5885ec6fl,0x45ee51121b077620l, + 0x848f9800f1f4cc8al }, + { 0x6ec1e0f74e97bceal,0x953bc23a98e80642l,0x9f0d1e8194ce7181l, + 0xeb3e6b9700eec596l }, + 0 }, + /* 34 << 152 */ + { { 0x6d34b39bff7514dal,0x29ffe49825be3634l,0x63e56598f28c8b82l, + 0x78b99133aab41bcel }, + { 0x11febd5a52563180l,0xa3be94c5c356a8c0l,0x5e9b422e0d61f864l, + 0x2bf4ca1278fd259el }, + 0 }, + /* 35 << 152 */ + { { 0x8f60e40266914514l,0x6d9e280fef178167l,0x2ff7aec9e2949a48l, + 0x422389ce72d37511l }, + { 0xe9b156f3307ac1d2l,0x1cb581a78518e79fl,0x56d43f302185cf82l, + 0x8d46c5aade59562cl }, + 0 }, + /* 36 << 152 */ + { { 0x50fc0711745edc11l,0x9dd9ad7d3dc87558l,0xce6931fbb49d1e64l, + 0x6c77a0a2c98bd0f9l }, + { 0x62b9a6296baf7cb1l,0xcf065f91ccf72d22l,0x7203cce979639071l, + 0x09ae4885f9cb732fl }, + 0 }, + /* 37 << 152 */ + { { 0xd007d682e4b35428l,0x80c162315bcdc0d6l,0xe55a86bd36fce9b2l, + 0x16772edb969a87cfl }, + { 0xff323a2d3f370c94l,0x8d3c8028bf3c1afcl,0x4e1591e73b0c3fafl, + 0xfbd6475cb981ce83l }, + 0 }, + /* 39 << 152 */ + { { 0xcf414ae3315b2471l,0xf54abf8033168de6l,0x6883efc5df5cdb24l, + 0x3eca788c8efe81acl }, + { 0xdb58c6c778eeccadl,0x3c77939082fecfb7l,0x5736cdd9c9b513f3l, + 0xab7e6ea57b02aaf2l }, + 0 }, + /* 40 << 152 */ + { { 0x5e7c3becee8314f3l,0x1c068aeddbea298fl,0x08d381f17c80acecl, + 0x03b56be8e330495bl }, + { 0xaeffb8f29222882dl,0x95ff38f6c4af8bf7l,0x50e32d351fc57d8cl, + 0x6635be5217b444f0l }, + 0 }, + /* 41 << 152 */ + { { 0x2cec7ba64805d895l,0x4c8399870ac78e7cl,0x031ad6c7f79416c5l, + 0x1b2f2621f1838d2fl }, + { 0x60835eac91447f90l,0x59147af1f9bab5d9l,0x7a3005d6f393f175l, + 0x8cf3c468c4120ba2l }, + 0 }, + /* 43 << 152 */ + { { 0xeccffc7d8a2c1f08l,0x308916d37e384bd4l,0x6b8c2ff55e366384l, + 0xf4b2850d03e4747cl }, + { 0xe839c569e96c1488l,0xa46ff7f956c9cb10l,0xd968c74c362fd172l, + 0x2aa7fe4cad6bb601l }, + 0 }, + /* 44 << 152 */ + { { 0x04d15276a5177900l,0x4e1dbb47f6858752l,0x5b475622c615796cl, + 0xa6fa0387691867bfl }, + { 0xed7f5d562844c6d0l,0xc633cf9b03a2477dl,0xf6be5c402d3721d6l, + 0xaf312eb7e9fd68e6l }, + 0 }, + /* 45 << 152 */ + { { 0xf3b8164eec04c847l,0xa305ca93fe65816cl,0xa65f9963c7e2ce52l, + 0xc448005198882cfcl }, + { 0x46a998df05c165bbl,0xc38f4edf9dfe1e98l,0xb96ec43f8739f77al, + 0x10a23af9313b40bfl }, + 0 }, + /* 46 << 152 */ + { { 0xe476c3e3ee668e0cl,0xcec6a984478197c2l,0xc9fa1d68897147c1l, + 0x4e6aec0ea6465793l }, + { 0xedca9db76b219c3bl,0xa2cd57942e508d3bl,0x38b384663936e02al, + 0x0b8d3b4ca54ce90fl }, + 0 }, + /* 47 << 152 */ + { { 0x66e06537af08e0fcl,0x70fe0f2a907f1a93l,0x8c25245285ec1647l, + 0x0b8b2964d5560eddl }, + { 0xda45a326f3ef8e14l,0xf3adf9a6abc3494bl,0xbbdd93c11eda0d92l, + 0x1b5e12c609912773l }, + 0 }, + /* 48 << 152 */ + { { 0x242792d2e7417ce1l,0xff42bc71970ee7f5l,0x1ff4dc6d5c67a41el, + 0x77709b7b20882a58l }, + { 0x3554731dbe217f2cl,0x2af2a8cd5bb72177l,0x58eee769591dd059l, + 0xbb2930c94bba6477l }, + 0 }, + /* 49 << 152 */ + { { 0x5d9d507551d01848l,0x53dadb405b600d1el,0x7ba5b4dc5cb0a9a3l, + 0xdb85b04c6795e547l }, + { 0x480e7443f0354843l,0xc7efe6e813012322l,0x479b674a2aeee1e6l, + 0xf5481f19704f4ea3l }, + 0 }, + /* 51 << 152 */ + { { 0x76a38d6978c7816el,0xe020c87df84ec554l,0x99af2f78f9818010l, + 0x31cf103d988136eal }, + { 0x6b095a114816a5aal,0x5a4cd2a4eff0a4afl,0x543041a5892e5e04l, + 0x460f94c30aab9ee1l }, + 0 }, + /* 52 << 152 */ + { { 0x863ee0477d930cfcl,0x4c262ad1396fd1f4l,0xf4765bc8039af7e1l, + 0x2519834b5ba104f6l }, + { 0x7cd61b4cd105f961l,0xa5415da5d63bca54l,0x778280a088a1f17cl, + 0xc49689492329512cl }, + 0 }, + /* 53 << 152 */ + { { 0x282d92b48cd3948al,0x95d219dfe168205bl,0xf6111a6f87bf3abcl, + 0x910f8ce655fee9f2l }, + { 0xb6c806f74f71ac89l,0xd0cc300fb7235f73l,0xfe37ccb47d0d45bbl, + 0x5b2445f6952f0eaal }, + 0 }, + /* 55 << 152 */ + { { 0x03870be447141962l,0x8b79033f4a2b3f7fl,0xb6983b5ed2e5e274l, + 0x2a2f8018501ed99cl }, + { 0x07a92eb9feb49656l,0x063f0a9e482e2972l,0x413be27a57435832l, + 0x56363c5f6f9d3de1l }, + 0 }, + /* 57 << 152 */ + { { 0xd247153163b50214l,0x32b435eeb2b897del,0xc49f0b01b05df4del, + 0x97b6aa40b7df9b91l }, + { 0x58ff34ec8ec39d78l,0xab0889005e0114a3l,0x6872b4de4822b7b8l, + 0x7614c0d0ab239073l }, + 0 }, + /* 59 << 152 */ + { { 0x81891d378aa5d80al,0xf48ca24292e45f2cl,0xba711b6c0d04904cl, + 0x5992cda349f16ed6l }, + { 0x18b9a739790593eel,0x8b98e84dc4ba16d1l,0xac55701cb7b81615l, + 0xadb4533b15822291l }, + 0 }, + /* 60 << 152 */ + { { 0x6210db7181236c97l,0x74f7685b3ee0781fl,0x4df7da7ba3e41372l, + 0x2aae38b1b1a1553el }, + { 0x1688e222f6dd9d1bl,0x576954485b8b6487l,0x478d21274b2edeaal, + 0xb2818fa51e85956al }, + 0 }, + /* 61 << 152 */ + { { 0xc0677533f255ba8el,0x2bdae2a1efa2aabel,0xf7aebbd4b086c8a6l, + 0x148455d992cb1147l }, + { 0xa084e8d715402565l,0x33f111a8fa41bf23l,0x4bc990d627ac189bl, + 0x48dbe6569d505f76l }, + 0 }, + /* 63 << 152 */ + { { 0x59df7fab596766f3l,0x4cadcbfe604f26e4l,0x0cf199338a6af592l, + 0x3af1ace287b826c1l }, + { 0xf09a5b38ee60684el,0xa04cbeda4ed7c711l,0xdb28c42eb1731040l, + 0x75fcc0ec2e6e6523l }, + 0 }, + /* 64 << 152 */ + { { 0x1e6adddaf176f2c0l,0x01ca4604e2572658l,0x0a404ded85342ffbl, + 0x8cf60f96441838d6l }, + { 0x9bbc691cc9071c4al,0xfd58874434442803l,0x97101c85809c0d81l, + 0xa7fb754c8c456f7fl }, + 0 }, + /* 65 << 152 */ + { { 0x4374020072196f30l,0x59ed0dc0dcd6c935l,0x17d4ed8e5034161bl, + 0x8abe3e13009e7170l }, + { 0xe51c41c96c791456l,0xc671807704d72bb6l,0xd4309cf56bba424al, + 0x6122b951d0ca4ceal }, + 0 }, + /* 71 << 152 */ + { { 0xdfdb2e9c4278982bl,0xf3a282b32d6a2a61l,0x5611650cd2f2b03cl, + 0xa62c177f43f7f83al }, + { 0x372310ab4c593d32l,0x2bb6903a2b570f9cl,0x2930da3df43af904l, + 0x2bbd04aa2c8a5a7dl }, + 0 }, + /* 77 << 152 */ + { { 0x10c324c007e536del,0xc456836d377be1b4l,0x9a627d75d785af3fl, + 0xde74559118b58b31l }, + { 0xeac83ea60c47239al,0x35da24abbc02f670l,0x2d4abde0c3af6e63l, + 0xac53acba5a7ebf1bl }, + 0 }, + /* 83 << 152 */ + { { 0x2b03ec2efd9a9f3el,0xc967cd2b9d898a09l,0xb24bcba8039dc4f6l, + 0x0ea1d297061ada1el }, + { 0x3a7a25fbc134b8bcl,0x846282d6f61cd312l,0xfa1de0d2e0d778d9l, + 0xf75fad4ef09be264l }, + 0 }, + /* 89 << 152 */ + { { 0x7d35695bcf74afb3l,0x34d43d9f15bb36fbl,0x15f0b43960b45fbel, + 0xb15db8d84f38ec06l }, + { 0x93ce7d50f7da1406l,0x2db97edd9f076aaal,0x27ebb9aa354429dcl, + 0xf97eb5c446ace469l }, + 0 }, + /* 95 << 152 */ + { { 0x758fa2312dcf498fl,0xaa8c14d15cf3853al,0x416f5dab097d786al, + 0xceec00ef38f242a0l }, + { 0x2f8b10b9d8b75ef2l,0xee64912b2281be6al,0xa883481aa382a51el, + 0x9442300f61b16b8al }, + 0 }, + /* 101 << 152 */ + { { 0x80e7fbc4f4b171e1l,0xdd2246f5661564a4l,0xcf08d73cd00d4e54l, + 0xf725f5389fca9a30l }, + { 0xd9607358af20debel,0xa97c81e16f7d1cf2l,0x72794ae70dedfb2al, + 0xc328cb93159ff29dl }, + 0 }, + /* 107 << 152 */ + { { 0xaf9491d6252f6d59l,0x6744d7518feda60dl,0xa485f8aa34c5c048l, + 0x2ed794b4b50ea53bl }, + { 0x0da82650db26c289l,0xed3ab4c50904af55l,0x425eda1176544463l, + 0x917be5f48939b29bl }, + 0 }, + /* 113 << 152 */ + { { 0xa2e72d0f8e208e5dl,0x5a5e4344234a5fedl,0x6dcc56535005bee8l, + 0x09d0c254854e2e04l }, + { 0xade4bcdba82f0789l,0x5a3e3cd4ec460a91l,0x6b1a867be76695b2l, + 0xd1eb9df0a28b9331l }, + 0 }, + /* 116 << 152 */ + { { 0x3f5cf5f678e62ddcl,0x2267c45407fd752bl,0x5e361b6b5e437bbel, + 0x95c595018354e075l }, + { 0xec725f85f2b254d9l,0x844b617d2cb52b4el,0xed8554f5cf425fb5l, + 0xab67703e2af9f312l }, + 0 }, + /* 119 << 152 */ + { { 0x8dcc920005fb96bbl,0x29d2442470f84705l,0x540bb6e63f09628fl, + 0x07f8b4de2a9c2359l }, + { 0xb8e002d1957e41dcl,0x9a0fe82b9e683a3fl,0x996b1a5250e633fdl, + 0x748a11e500c669cal }, + 0 }, + /* 125 << 152 */ + { { 0x0593a788581dfd6el,0x99f1164f64e1b329l,0x1142c44b1defddbbl, + 0xbc95c9c7660b9036l }, + { 0xf24b5a47079179ccl,0x6175b52c21f7033bl,0x8b5d84183bc2eec0l, + 0xc1332c8272d12670l }, + 0 }, + }, + { + /* 0 << 160 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 160 */ + { { 0xd433e50f6d3549cfl,0x6f33696ffacd665el,0x695bfdacce11fcb4l, + 0x810ee252af7c9860l }, + { 0x65450fe17159bb2cl,0xf7dfbebe758b357bl,0x2b057e74d69fea72l, + 0xd485717a92731745l }, + 0 }, + /* 3 << 160 */ + { { 0x6c8d0aa9b898fd52l,0x2fb38a57be9af1a7l,0xe1f2b9a93b4f03f8l, + 0x2b1aad44c3f0cc6fl }, + { 0x58b5332e7cf2c084l,0x1c57d96f0367d26dl,0x2297eabdfa6e4a8dl, + 0x65a947ee4a0e2b6al }, + 0 }, + /* 4 << 160 */ + { { 0xaaafafb0285b9491l,0x01a0be881e4c705el,0xff1d4f5d2ad9caabl, + 0x6e349a4ac37a233fl }, + { 0xcf1c12464a1c6a16l,0xd99e6b6629383260l,0xea3d43665f6d5471l, + 0x36974d04ff8cc89bl }, + 0 }, + /* 5 << 160 */ + { { 0xf535b616fdd5b854l,0x592549c85728719fl,0xe231468606921cadl, + 0x98c8ce34311b1ef8l }, + { 0x28b937e7e9090b36l,0x67fc3ab90bf7bbb7l,0x12337097a9d87974l, + 0x3e5adca1f970e3fel }, + 0 }, + /* 7 << 160 */ + { { 0xcdcc68a7b3f85ff0l,0xacd21cdd1a888044l,0xb6719b2e05dbe894l, + 0xfae1d3d88b8260d4l }, + { 0xedfedece8a1c5d92l,0xbca01a94dc52077el,0xc085549c16dd13edl, + 0xdc5c3bae495ebaadl }, + 0 }, + /* 9 << 160 */ + { { 0xcc17063fbe7b643al,0x7872e1c846085760l,0x86b0fffbb4214c9el, + 0xb18bbc0e72bf3638l }, + { 0x8b17de0c722591c9l,0x1edeab1948c29e0cl,0x9fbfd98ef4304f20l, + 0x2d1dbb6b9c77ffb6l }, + 0 }, + /* 10 << 160 */ + { { 0xf53f2c658ead09f7l,0x1335e1d59780d14dl,0x69cc20e0cd1b66bcl, + 0x9b670a37bbe0bfc8l }, + { 0xce53dc8128efbeedl,0x0c74e77c8326a6e5l,0x3604e0d2b88e9a63l, + 0xbab38fca13dc2248l }, + 0 }, + /* 11 << 160 */ + { { 0x255616d3c7141771l,0xa86691ab2f226b66l,0xda19fea4b3ca63a9l, + 0xfc05dc42ae672f2bl }, + { 0xa9c6e786718ba28fl,0x07b7995b9c66b984l,0x0f434f551b3702f2l, + 0xd6f6212fda84eeffl }, + 0 }, + /* 13 << 160 */ + { { 0x4b0e7987b5b41d78l,0xea7df9074bf0c4f8l,0xb4d03560fab80ecdl, + 0x6cf306f6fb1db7e5l }, + { 0x0d59fb5689fd4773l,0xab254f4000f9be33l,0x18a09a9277352da4l, + 0xf81862f5641ea3efl }, + 0 }, + /* 15 << 160 */ + { { 0xb59b01579f759d01l,0xa2923d2f7eae4fdel,0x18327757690ba8c0l, + 0x4bf7e38b44f51443l }, + { 0xb6812563b413fc26l,0xedb7d36379e53b36l,0x4fa585c4c389f66dl, + 0x8e1adc3154bd3416l }, + 0 }, + /* 16 << 160 */ + { { 0xd3b3a13f1402b9d0l,0x573441c32c7bc863l,0x4b301ec4578c3e6el, + 0xc26fc9c40adaf57el }, + { 0x96e71bfd7493cea3l,0xd05d4b3f1af81456l,0xdaca2a8a6a8c608fl, + 0x53ef07f60725b276l }, + 0 }, + /* 17 << 160 */ + { { 0x971e9eedd5098497l,0x97692be63077d8a7l,0xb57e02ad79625a8al, + 0x5e3d20f6a688ecd5l }, + { 0xa4431a28188f964dl,0xd4eb23bd5a11c1dbl,0xfcda853eadc7446fl, + 0x9e2e98b593c94046l }, + 0 }, + /* 19 << 160 */ + { { 0x4a649b66eddaa4f1l,0x35a04f185e690c50l,0x1639bdcff908bc53l, + 0xce6d525c121726e8l }, + { 0x70f34948902b402cl,0x3a40c6950e290579l,0x7b0ed90f469a0085l, + 0xecb979c60189c501l }, + 0 }, + /* 21 << 160 */ + { { 0x847e2bde5cee8d07l,0x1bed198cd3340037l,0x439ffb3ce41586e3l, + 0x594980f1856f15b0l }, + { 0x22c3b86c6e9307c6l,0xf8b3ee08876382dbl,0x850c628e628f3f30l, + 0x22ec0acb51ee3659l }, + 0 }, + /* 23 << 160 */ + { { 0xa4052591efcef5a0l,0x82692a47106d55afl,0xdac3ea88e6ead453l, + 0xaa1368fcf3dfd875l }, + { 0x87bc688aa0c539eal,0x905e206040b1de3el,0x072240b8f1d52452l, + 0x3ebf0644d57b6580l }, + 0 }, + /* 25 << 160 */ + { { 0x12109bcc07a0b2f8l,0x336f87d2ca23f14cl,0xb39ae282452a2ea2l, + 0x8e085f5bab59a500l }, + { 0xf7daeb69b63f015cl,0x44c555bcacb47b38l,0x96190454b623910al, + 0x4b666e2255b41b70l }, + 0 }, + /* 27 << 160 */ + { { 0xf146914eb53419fdl,0xd2109b07493e88bfl,0x30bf9cbccc54bcd5l, + 0xcf9ea59750e34a1fl }, + { 0x70ade8a59588591dl,0xf668be676b41c269l,0x3497c58f78df2e6bl, + 0x0fad05cc71042b56l }, + 0 }, + /* 28 << 160 */ + { { 0x27f536e049ce89e7l,0x18908539cc890cb5l,0x308909abd83c2aa1l, + 0xecd3142b1ab73bd3l }, + { 0x6a85bf59b3f5ab84l,0x3c320a68f2bea4c6l,0xad8dc5386da4541fl, + 0xeaf34eb0b7c41186l }, + 0 }, + /* 29 << 160 */ + { { 0x709da836093aa5f6l,0x567a9becb4644edel,0xae02a46044466b0cl, + 0xc80b237a407f1b3bl }, + { 0x451df45ab4168a98l,0xdc9b40ef24a3f7c9l,0x23593ef32671341dl, + 0x40f4533190b90faal }, + 0 }, + /* 31 << 160 */ + { { 0x7f97768e922f36e3l,0x936943f8491034a2l,0x72f6c17f21483753l, + 0x5489fa0cb2918619l }, + { 0x55b31aa59cc21a46l,0xde4cc71a8e54ab14l,0x942cb8be9eaff8b0l, + 0xe38f6116d1755231l }, + 0 }, + /* 33 << 160 */ + { { 0xf0c0606a395b39abl,0x0efcbc699b5166a5l,0x85995e6895453d85l, + 0xadc9a2920806ee5cl }, + { 0xc3662e804928fe09l,0x2a2ddcc6969c87e7l,0xa02d7947111d319dl, + 0xde23bcf12d20f66dl }, + 0 }, + /* 34 << 160 */ + { { 0xc47cb3395f6d4a09l,0x6b4f355cee52b826l,0x3d100f5df51b930al, + 0xf4512fac9f668f69l }, + { 0x546781d5206c4c74l,0xd021d4d4cb4d2e48l,0x494a54c2ca085c2dl, + 0xf1dbaca4520850a8l }, + 0 }, + /* 35 << 160 */ + { { 0xb2d15b14a911cc2bl,0xab2dfaf7643e28eal,0xfccc9ed1f52c4c2dl, + 0xfb4b1d4a09d8faa3l }, + { 0x6fd72a9b7f5ce767l,0x0233c856a287e2b5l,0xd42135e05775ebb9l, + 0xb3c9dada7376568bl }, + 0 }, + /* 36 << 160 */ + { { 0x63c79326490a1acal,0xcb64dd9c41526b02l,0xbb772591a2979258l, + 0x3f58297048d97846l }, + { 0xd66b70d17c213ba7l,0xc28febb5e8a0ced4l,0x6b911831c10338c1l, + 0x0d54e389bf0126f3l }, + 0 }, + /* 37 << 160 */ + { { 0x5952996b5306af1bl,0x99f444f4354b67bel,0x6f670181633a2928l, + 0x289023f0e9bdc4a6l }, + { 0xcbed12148f7455a2l,0x501ace2f659a4858l,0x83ee678d5f8e1784l, + 0x95c984587335c5bdl }, + 0 }, + /* 39 << 160 */ + { { 0x2e25a1f3e0233000l,0xed0028cd44fe8ba9l,0x447501a6021d43b3l, + 0x4ec203906b4dffccl }, + { 0x50642f9ad0169740l,0x9360003373cc58adl,0x825f1a82fe9cf9acl, + 0x456194c653242bd6l }, + 0 }, + /* 40 << 160 */ + { { 0x40242efeb483689bl,0x2575d3f6513ac262l,0xf30037c80ca6db72l, + 0xc9fcce8298864be2l }, + { 0x84a112ff0149362dl,0x95e575821c4ae971l,0x1fa4b1a8945cf86cl, + 0x4525a7340b024a2fl }, + 0 }, + /* 41 << 160 */ + { { 0x83205e8f5db5e2b1l,0x94e7a2621e311c12l,0xe1cac7333e37068fl, + 0xe3f43f6d39965acfl }, + { 0xd28db9e854d905bal,0x686f372a101f2162l,0x409cfe5d3d1b46d4l, + 0x17648f1cbd0bb63al }, + 0 }, + /* 43 << 160 */ + { { 0xef83315b821f4ee4l,0xb90766998ba78b4dl,0xee6a15880fce5260l, + 0x828f4a72d754affbl }, + { 0x4650ec7daaae54d2l,0x3174301f1057efe9l,0x174e0683eb7704cel, + 0xb7e6aeb357eb0b14l }, + 0 }, + /* 44 << 160 */ + { { 0xcaead1c2c905d85fl,0xe9d7f7900733ae57l,0x24c9a65cf07cdd94l, + 0x7389359ca4b55931l }, + { 0xf58709b7367e45f7l,0x1f203067cb7e7adcl,0x82444bffc7b72818l, + 0x07303b35baac8033l }, + 0 }, + /* 45 << 160 */ + { { 0xd59528fb38a0dc96l,0x8179dc9088d0e857l,0x55e9ba039ed4b1afl, + 0x8a2c0dc787b74cacl }, + { 0xe8ca91aeef1c0006l,0x67f59ab2de0e15d4l,0xba0cddf86e6634d2l, + 0x352803657b7ba591l }, + 0 }, + /* 46 << 160 */ + { { 0x1e1ee4e4d13b7ea1l,0xe6489b24e0e74180l,0xa5f2c6107e70ef70l, + 0xa1655412bdd10894l }, + { 0x555ebefb7af4194el,0x533c1c3c8e89bd9cl,0x735b9b5789895856l, + 0x15fb3cd2567f5c15l }, + 0 }, + /* 47 << 160 */ + { { 0xef07bfedfb0986c7l,0xde138afe47c1659al,0x8b79c159a555e907l, + 0x21d572f1125518bbl }, + { 0x2005999ad320410cl,0x4167dc469484414bl,0x0cd965c34c6aaefdl, + 0x2a1abc9a0e1d5e9dl }, + 0 }, + /* 48 << 160 */ + { { 0x057fed45526f09fdl,0xe8a4f10c8128240al,0x9332efc4ff2bfd8dl, + 0x214e77a0bd35aa31l }, + { 0x32896d7314faa40el,0x767867ec01e5f186l,0xc9adf8f117a1813el, + 0xcb6cda7854741795l }, + 0 }, + /* 49 << 160 */ + { { 0xadfaf39b888dedf1l,0x4f8b178aab1750b9l,0x26418617ffe6b0eal, + 0x01d1be82af04a59fl }, + { 0x41584147e652db64l,0xf7775ac5727f9ea7l,0x58052a20e72ad8bbl, + 0x5badf0dc6021160el }, + 0 }, + /* 51 << 160 */ + { { 0x8490ea99183de59dl,0xc95f72146f5c6f8cl,0x89b55d15df00c334l, + 0x84386ad8a0ec36f7l }, + { 0x24dadaefe4dc1ed1l,0xc606ba4c1e717227l,0x7e4756c0bbfa62eal, + 0x3916cf14afc29cf3l }, + 0 }, + /* 52 << 160 */ + { { 0xb7b4d00101dae185l,0x45434e0b9b7a94bcl,0xf54339affbd8cb0bl, + 0xdcc4569ee98ef49el }, + { 0x7789318a09a51299l,0x81b4d206b2b025d8l,0xf64aa418fae85792l, + 0x3e50258facd7baf7l }, + 0 }, + /* 53 << 160 */ + { { 0x4152c508492d91f3l,0x59d6cf9c678f9db4l,0xb0a8c966404608d1l, + 0xdced55d0e3fed558l }, + { 0x0914a3cb33a76188l,0x79df212423d35d46l,0x2322507fca13b364l, + 0x0aed41d60078ab93l }, + 0 }, + /* 55 << 160 */ + { { 0x7acdaa7f6b2ebfc2l,0xb5ab1a9a80d9f67fl,0x53ba8173ff8aa8b0l, + 0x9cd85cf874ca56a6l }, + { 0xabac57f49c4fad81l,0x2325bb8521078995l,0xbac5e3a1b928a054l, + 0x7219047a2394cc2al }, + 0 }, + /* 57 << 160 */ + { { 0xa33410d2aa75fd37l,0x821093affc0f1192l,0xe45e85ed155e39a9l, + 0xd0e87cd12de67188l }, + { 0xdeca97d965d43d87l,0x8c73826f9d2c99ecl,0x1bfe111e33237ddbl, + 0xda32e865587bfb28l }, + 0 }, + /* 59 << 160 */ + { { 0xde456d92c89e9e4el,0xe45688a98e47f3cdl,0x3deacfca3bacbde0l, + 0xdf9b32efc9683a70l }, + { 0x749bc007e1691106l,0x788a05342a5154d7l,0x1a06baecf7c7b70dl, + 0xb5b608eeae6ffc4cl }, + 0 }, + /* 60 << 160 */ + { { 0x4cd296df5579bea4l,0x10e35ac85ceedaf1l,0x04c4c5fde3bcc5b1l, + 0x95f9ee8a89412cf9l }, + { 0x2c9459ee82b6eb0fl,0x2e84576595c2aaddl,0x774a84aed327fcfel, + 0xd8c937220368d476l }, + 0 }, + /* 61 << 160 */ + { { 0x39ebf947ccd25abbl,0x74e7a868cb49ebael,0x576ea108332e6147l, + 0xcf3ba166150c1e5dl }, + { 0xb5411fc3515c0e93l,0x51b15761f15c8a34l,0x362a4a3a0d213f38l, + 0xf6f63c2e24e93aeal }, + 0 }, + /* 63 << 160 */ + { { 0x0cb3a2dcb78528d5l,0xa1888c18d585bb41l,0x210cca40de402a6el, + 0x10c6339d9ed7c381l }, + { 0xcd3558d561fe2a0cl,0xc97db05dad5140b1l,0x3366b028b21f8d11l, + 0x878b09033e38be13l }, + 0 }, + /* 64 << 160 */ + { { 0x211cde10296c36efl,0x7ee8967282c4da77l,0xb617d270a57836dal, + 0xf0cd9c319cb7560bl }, + { 0x01fdcbf7e455fe90l,0x3fb53cbb7e7334f3l,0x781e2ea44e7de4ecl, + 0x8adab3ad0b384fd0l }, + 0 }, + /* 65 << 160 */ + { { 0x081e505aa353ba05l,0x244ab34a288b86b1l,0x1155f06214e3a829l, + 0x383300daf2118a6bl }, + { 0xe8fc17cef27032b9l,0xed7f05c9c7bd2389l,0x78f70d14202f8a88l, + 0x8a8310c0647b3f20l }, + 0 }, + /* 71 << 160 */ + { { 0xc80786e1a3633369l,0x496d55de9073f5b9l,0x10deeb6a89ae93cel, + 0x6a2dd5c8b12e00c6l }, + { 0xc25cd2f90c68e26dl,0x29d7ad8b53f0bb64l,0x2dd0d027d7fc9b00l, + 0xad21e1f7ca9c4d5dl }, + 0 }, + /* 77 << 160 */ + { { 0xd45cb932d83465f3l,0x95830c0faf22fdbdl,0x41d830e007cd2a0al, + 0x4a08500e3616e716l }, + { 0x5931fc9f277755a5l,0x7d11680731006764l,0xa409a0ad1b3999aal, + 0xec70368c9939d566l }, + 0 }, + /* 83 << 160 */ + { { 0x3905cb59f2030370l,0x7e9bdee56dcc8fd7l,0xb1b7b04e9806e06fl, + 0xfbdadce22c73eb57l }, + { 0xfb1ab2e98d5b2eb3l,0x58fbf2df7699338bl,0x81b1c54a63b5a032l, + 0xefd1a1896a5d7ff4l }, + 0 }, + /* 89 << 160 */ + { { 0x0265189da1f769eal,0x22fa0bbbfdb5a502l,0xf69f0d1b21027534l, + 0x64302b81f6066b99l }, + { 0xdef85fc98a717e80l,0xe066166386879a3bl,0xe5489b347f95b22cl, + 0x106dca9aa054a563l }, + 0 }, + /* 95 << 160 */ + { { 0xd624b4f4b4be9a77l,0x21a11ed77d50acb1l,0x707181f43d406e11l, + 0x3f324d203ef158bcl }, + { 0xb29a2a34aa8cc8del,0x482f4a15315db969l,0x42ce4fc7d9af272el, + 0x784665b1f8f4cdc4l }, + 0 }, + /* 101 << 160 */ + { { 0x66ff7f73ab43a863l,0xa90be2cba77fd07el,0x84843997f76e5288l, + 0x288c197f3cee129bl }, + { 0x39acc080c0a060a6l,0x4c8e574bd24e27cal,0x1dd6170ffcd3d5e9l, + 0x9736bb51f75e5150l }, + 0 }, + /* 107 << 160 */ + { { 0x2133810e6ba75716l,0x4debf728712886a8l,0x351e46a1f527d1f3l, + 0x29709ae8e9591564l }, + { 0x696163d3a3dc1780l,0xd5b7825ae02aadf3l,0x23579d7cd565ae68l, + 0x105380124fa42cecl }, + 0 }, + /* 113 << 160 */ + { { 0x04eb554d13ffa704l,0x7441a62f2ed33d20l,0xaa926fa0b5b81324l, + 0xb981bcb829836f61l }, + { 0x313a78d4cc9a7a15l,0xff1242d11b3921d2l,0xc0053fd36a209d4dl, + 0x95ac85caf7e92ca9l }, + 0 }, + /* 116 << 160 */ + { { 0x6d2a483d6f73c51el,0xa4cb2412ea0dc2ddl,0x50663c411eb917ffl, + 0x3d3a74cfeade299el }, + { 0x29b3990f4a7a9202l,0xa9bccf59a7b15c3dl,0x66a3ccdca5df9208l, + 0x48027c1443f2f929l }, + 0 }, + /* 119 << 160 */ + { { 0xdf8a6f9673c3f6fbl,0xe4b1f0d98cc03220l,0x5ddacd618350480cl, + 0x485c4fababdfb016l }, + { 0xdc840628b4d424b7l,0x07d3a99c215b2359l,0xad3dc5af56dff52el, + 0x5a3a6754973b6825l }, + 0 }, + /* 125 << 160 */ + { { 0xcfe231b83539a06dl,0xb36d1f72f46770ddl,0x126049747bb900d6l, + 0x8d0990973fc31661l }, + { 0x03b2749c920bc39el,0xf933d510b0486e23l,0x09cc958f0e9b0bb5l, + 0x0b254dd1aa1e23abl }, + 0 }, + }, + { + /* 0 << 168 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 168 */ + { { 0x263a2cfb9db3b381l,0x9c3a2deed4df0a4bl,0x728d06e97d04e61fl, + 0x8b1adfbc42449325l }, + { 0x6ec1d9397e053a1bl,0xee2be5c766daf707l,0x80ba1e14810ac7abl, + 0xdd2ae778f530f174l }, + 0 }, + /* 3 << 168 */ + { { 0xadbaeb79b6828f36l,0x9d7a025801bd5b9el,0xeda01e0d1e844b0cl, + 0x4b625175887edfc9l }, + { 0x14109fdd9669b621l,0x88a2ca56f6f87b98l,0xfe2eb788170df6bcl, + 0x0cea06f4ffa473f9l }, + 0 }, + /* 4 << 168 */ + { { 0x43ed81b5c4e83d33l,0xd9f358795efd488bl,0x164a620f9deb4d0fl, + 0xc6927bdbac6a7394l }, + { 0x45c28df79f9e0f03l,0x2868661efcd7e1a9l,0x7cf4e8d0ffa348f1l, + 0x6bd4c284398538e0l }, + 0 }, + /* 5 << 168 */ + { { 0x2618a091289a8619l,0xef796e606671b173l,0x664e46e59090c632l, + 0xa38062d41e66f8fbl }, + { 0x6c744a200573274el,0xd07b67e4a9271394l,0x391223b26bdc0e20l, + 0xbe2d93f1eb0a05a7l }, + 0 }, + /* 7 << 168 */ + { { 0x7efa14b84444896bl,0x64974d2ff94027fbl,0xefdcd0e8de84487dl, + 0x8c45b2602b48989bl }, + { 0xa8fcbbc2d8463487l,0xd1b2b3f73fbc476cl,0x21d005b7c8f443c0l, + 0x518f2e6740c0139cl }, + 0 }, + /* 9 << 168 */ + { { 0xae51dca2a91f6791l,0x2abe41909baa9efcl,0xd9d2e2f4559c7ac1l, + 0xe82f4b51fc9f773al }, + { 0xa77130274073e81cl,0xc0276facfbb596fcl,0x1d819fc9a684f70cl, + 0x29b47fddc9f7b1e0l }, + 0 }, + /* 10 << 168 */ + { { 0x358de103459b1940l,0xec881c595b013e93l,0x51574c9349532ad3l, + 0x2db1d445b37b46del }, + { 0xc6445b87df239fd8l,0xc718af75151d24eel,0xaea1c4a4f43c6259l, + 0x40c0e5d770be02f7l }, + 0 }, + /* 11 << 168 */ + { { 0x6a4590f4721b33f2l,0x2124f1fbfedf04eal,0xf8e53cde9745efe7l, + 0xe7e1043265f046d9l }, + { 0xc3fca28ee4d0c7e6l,0x847e339a87253b1bl,0x9b5953483743e643l, + 0xcb6a0a0b4fd12fc5l }, + 0 }, + /* 13 << 168 */ + { { 0xec1214eda714181dl,0x609ac13b6067b341l,0xff4b4c97a545df1fl, + 0xa124050134d2076bl }, + { 0x6efa0c231409ca97l,0x254cc1a820638c43l,0xd4e363afdcfb46cdl, + 0x62c2adc303942a27l }, + 0 }, + /* 15 << 168 */ + { { 0x27b6a8ab3fd40e09l,0xe455842e77313ea9l,0x8b51d1e21f55988bl, + 0x5716dd73062bbbfcl }, + { 0x633c11e54e8bf3del,0x9a0e77b61b85be3bl,0x565107290911cca6l, + 0x27e76495efa6590fl }, + 0 }, + /* 16 << 168 */ + { { 0xe4ac8b33070d3aabl,0x2643672b9a2cd5e5l,0x52eff79b1cfc9173l, + 0x665ca49b90a7c13fl }, + { 0x5a8dda59b3efb998l,0x8a5b922d052f1341l,0xae9ebbab3cf9a530l, + 0x35986e7bf56da4d7l }, + 0 }, + /* 17 << 168 */ + { { 0x3a636b5cff3513ccl,0xbb0cf8ba3198f7ddl,0xb8d4052241f16f86l, + 0x760575d8de13a7bfl }, + { 0x36f74e169f7aa181l,0x163a3ecff509ed1cl,0x6aead61f3c40a491l, + 0x158c95fcdfe8fcaal }, + 0 }, + /* 19 << 168 */ + { { 0x6b47accdd9eee96cl,0x0ca277fbe58cec37l,0x113fe413e702c42al, + 0xdd1764eec47cbe51l }, + { 0x041e7cde7b3ed739l,0x50cb74595ce9e1c0l,0x355685132925b212l, + 0x7cff95c4001b081cl }, + 0 }, + /* 21 << 168 */ + { { 0x726f0973da50c991l,0x48afcd5b822d6ee2l,0xe5fc718b20fd7771l, + 0xb9e8e77dfd0807a1l }, + { 0x7f5e0f4499a7703dl,0x6972930e618e36f3l,0x2b7c77b823807bbel, + 0xe5b82405cb27ff50l }, + 0 }, + /* 23 << 168 */ + { { 0x98cb1ae9255c0980l,0x4bd863812b4a739fl,0x5a5c31e11e4a45a1l, + 0x1e5d55fe9cb0db2fl }, + { 0x74661b068ff5cc29l,0x026b389f0eb8a4f4l,0x536b21a458848c24l, + 0x2e5bf8ec81dc72b0l }, + 0 }, + /* 25 << 168 */ + { { 0x9f0af483d309cbe6l,0x5b020d8ae0bced4fl,0x606e986db38023e3l, + 0xad8f2c9d1abc6933l }, + { 0x19292e1de7400e93l,0xfe3e18a952be5e4dl,0xe8e9771d2e0680bfl, + 0x8c5bec98c54db063l }, + 0 }, + /* 27 << 168 */ + { { 0x4c23f62a2c160dcdl,0x34e6c5e38f90eaefl,0x35865519a9a65d5al, + 0x07c48aae8fd38a3dl }, + { 0xb7e7aeda50068527l,0x2c09ef231c90936al,0x31ecfeb6e879324cl, + 0xa0871f6bfb0ec938l }, + 0 }, + /* 28 << 168 */ + { { 0xb1f0fb68d84d835dl,0xc90caf39861dc1e6l,0x12e5b0467594f8d7l, + 0x26897ae265012b92l }, + { 0xbcf68a08a4d6755dl,0x403ee41c0991fbdal,0x733e343e3bbf17e8l, + 0xd2c7980d679b3d65l }, + 0 }, + /* 29 << 168 */ + { { 0x33056232d2e11305l,0x966be492f3c07a6fl,0x6a8878ffbb15509dl, + 0xff2211010a9b59a4l }, + { 0x6c9f564aabe30129l,0xc6f2c940336e64cfl,0x0fe752628b0c8022l, + 0xbe0267e96ae8db87l }, + 0 }, + /* 31 << 168 */ + { { 0x9d031369a5e829e5l,0xcbb4c6fc1607aa41l,0x75ac59a6241d84c1l, + 0xc043f2bf8829e0eel }, + { 0x82a38f758ea5e185l,0x8bda40b9d87cbd9fl,0x9e65e75e2d8fc601l, + 0x3d515f74a35690b3l }, + 0 }, + /* 33 << 168 */ + { { 0xf6b5b2d0bc8fa5bcl,0x8a5ead67500c277bl,0x214625e6dfa08a5dl, + 0x51fdfedc959cf047l }, + { 0x6bc9430b289fca32l,0xe36ff0cf9d9bdc3fl,0x2fe187cb58ea0edel, + 0xed66af205a900b3fl }, + 0 }, + /* 34 << 168 */ + { { 0x00e0968b5fa9f4d6l,0x2d4066ce37a362e7l,0xa99a9748bd07e772l, + 0x710989c006a4f1d0l }, + { 0xd5dedf35ce40cbd8l,0xab55c5f01743293dl,0x766f11448aa24e2cl, + 0x94d874f8605fbcb4l }, + 0 }, + /* 35 << 168 */ + { { 0xa365f0e8a518001bl,0xee605eb69d04ef0fl,0x5a3915cdba8d4d25l, + 0x44c0e1b8b5113472l }, + { 0xcbb024e88b6740dcl,0x89087a53ee1d4f0cl,0xa88fa05c1fc4e372l, + 0x8bf395cbaf8b3af2l }, + 0 }, + /* 36 << 168 */ + { { 0x1e71c9a1deb8568bl,0xa35daea080fb3d32l,0xe8b6f2662cf8fb81l, + 0x6d51afe89490696al }, + { 0x81beac6e51803a19l,0xe3d24b7f86219080l,0x727cfd9ddf6f463cl, + 0x8c6865ca72284ee8l }, + 0 }, + /* 37 << 168 */ + { { 0x32c88b7db743f4efl,0x3793909be7d11dcel,0xd398f9222ff2ebe8l, + 0x2c70ca44e5e49796l }, + { 0xdf4d9929cb1131b1l,0x7826f29825888e79l,0x4d3a112cf1d8740al, + 0x00384cb6270afa8bl }, + 0 }, + /* 39 << 168 */ + { { 0xbe7e990ff0d796a0l,0x5fc62478df0e8b02l,0x8aae8bf4030c00adl, + 0x3d2db93b9004ba0fl }, + { 0xe48c8a79d85d5ddcl,0xe907caa76bb07f34l,0x58db343aa39eaed5l, + 0x0ea6e007adaf5724l }, + 0 }, + /* 40 << 168 */ + { { 0xe00df169d23233f3l,0x3e32279677cb637fl,0x1f897c0e1da0cf6cl, + 0xa651f5d831d6bbddl }, + { 0xdd61af191a230c76l,0xbd527272cdaa5e4al,0xca753636d0abcd7el, + 0x78bdd37c370bd8dcl }, + 0 }, + /* 41 << 168 */ + { { 0xc23916c217cd93fel,0x65b97a4ddadce6e2l,0xe04ed4eb174e42f8l, + 0x1491ccaabb21480al }, + { 0x145a828023196332l,0x3c3862d7587b479al,0x9f4a88a301dcd0edl, + 0x4da2b7ef3ea12f1fl }, + 0 }, + /* 43 << 168 */ + { { 0x71965cbfc3dd9b4dl,0xce23edbffc068a87l,0xb78d4725745b029bl, + 0x74610713cefdd9bdl }, + { 0x7116f75f1266bf52l,0x0204672218e49bb6l,0xdf43df9f3d6f19e3l, + 0xef1bc7d0e685cb2fl }, + 0 }, + /* 44 << 168 */ + { { 0xcddb27c17078c432l,0xe1961b9cb77fedb7l,0x1edc2f5cc2290570l, + 0x2c3fefca19cbd886l }, + { 0xcf880a36c2af389al,0x96c610fdbda71ceal,0xf03977a932aa8463l, + 0x8eb7763f8586d90al }, + 0 }, + /* 45 << 168 */ + { { 0x3f3424542a296e77l,0xc871868342837a35l,0x7dc710906a09c731l, + 0x54778ffb51b816dbl }, + { 0x6b33bfecaf06defdl,0xfe3c105f8592b70bl,0xf937fda461da6114l, + 0x3c13e6514c266ad7l }, + 0 }, + /* 46 << 168 */ + { { 0xe363a829855938e8l,0x2eeb5d9e9de54b72l,0xbeb93b0e20ccfab9l, + 0x3dffbb5f25e61a25l }, + { 0x7f655e431acc093dl,0x0cb6cc3d3964ce61l,0x6ab283a1e5e9b460l, + 0x55d787c5a1c7e72dl }, + 0 }, + /* 47 << 168 */ + { { 0x4d2efd47deadbf02l,0x11e80219ac459068l,0x810c762671f311f0l, + 0xfa17ef8d4ab6ef53l }, + { 0xaf47fd2593e43bffl,0x5cb5ff3f0be40632l,0x546871068ee61da3l, + 0x7764196eb08afd0fl }, + 0 }, + /* 48 << 168 */ + { { 0x831ab3edf0290a8fl,0xcae81966cb47c387l,0xaad7dece184efb4fl, + 0xdcfc53b34749110el }, + { 0x6698f23c4cb632f9l,0xc42a1ad6b91f8067l,0xb116a81d6284180al, + 0xebedf5f8e901326fl }, + 0 }, + /* 49 << 168 */ + { { 0xf2274c9f97e3e044l,0x4201852011d09fc9l,0x56a65f17d18e6e23l, + 0x2ea61e2a352b683cl }, + { 0x27d291bc575eaa94l,0x9e7bc721b8ff522dl,0x5f7268bfa7f04d6fl, + 0x5868c73faba41748l }, + 0 }, + /* 51 << 168 */ + { { 0x1c52e63596e78cc4l,0x5385c8b20c06b4a8l,0xd84ddfdbb0e87d03l, + 0xc49dfb66934bafadl }, + { 0x7071e17059f70772l,0x3a073a843a1db56bl,0x034949033b8af190l, + 0x7d882de3d32920f0l }, + 0 }, + /* 52 << 168 */ + { { 0x91633f0ab2cf8940l,0x72b0b1786f948f51l,0x2d28dc30782653c8l, + 0x88829849db903a05l }, + { 0xb8095d0c6a19d2bbl,0x4b9e7f0c86f782cbl,0x7af739882d907064l, + 0xd12be0fe8b32643cl }, + 0 }, + /* 53 << 168 */ + { { 0x358ed23d0e165dc3l,0x3d47ce624e2378cel,0x7e2bb0b9feb8a087l, + 0x3246e8aee29e10b9l }, + { 0x459f4ec703ce2b4dl,0xe9b4ca1bbbc077cfl,0x2613b4f20e9940c1l, + 0xfc598bb9047d1eb1l }, + 0 }, + /* 55 << 168 */ + { { 0x52fb0c9d7fc63668l,0x6886c9dd0c039cdel,0x602bd59955b22351l, + 0xb00cab02360c7c13l }, + { 0x8cb616bc81b69442l,0x41486700b55c3ceel,0x71093281f49ba278l, + 0xad956d9c64a50710l }, + 0 }, + /* 57 << 168 */ + { { 0xbaca6591d4b66947l,0xb452ce9804460a8cl,0x6830d24643768f55l, + 0xf4197ed87dff12dfl }, + { 0x6521b472400dd0f7l,0x59f5ca8f4b1e7093l,0x6feff11b080338ael, + 0x0ada31f6a29ca3c6l }, + 0 }, + /* 59 << 168 */ + { { 0x04e5dfe0d809c7bdl,0xd7b2580c8f1050abl,0x6d91ad78d8a4176fl, + 0x0af556ee4e2e897cl }, + { 0x162a8b73921de0acl,0x52ac9c227ea78400l,0xee2a4eeaefce2174l, + 0xbe61844e6d637f79l }, + 0 }, + /* 60 << 168 */ + { { 0x0491f1bc789a283bl,0x72d3ac3d880836f4l,0xaa1c5ea388e5402dl, + 0x1b192421d5cc473dl }, + { 0x5c0b99989dc84cacl,0xb0a8482d9c6e75b8l,0x639961d03a191ce2l, + 0xda3bc8656d837930l }, + 0 }, + /* 61 << 168 */ + { { 0xca990653056e6f8fl,0x84861c4164d133a7l,0x8b403276746abe40l, + 0xb7b4d51aebf8e303l }, + { 0x05b43211220a255dl,0xc997152c02419e6el,0x76ff47b6630c2feal, + 0x50518677281fdadel }, + 0 }, + /* 63 << 168 */ + { { 0x6d2d99b7ea7b979bl,0xcd78cd74e6fb3bcdl,0x11e45a9e86cffbfel, + 0x78a61cf4637024f6l }, + { 0xd06bc8723d502295l,0xf1376854458cb288l,0xb9db26a1342f8586l, + 0xf33effcf4beee09el }, + 0 }, + /* 64 << 168 */ + { { 0xd7e0c4cdb30cfb3al,0x6d09b8c16c9db4c8l,0x40ba1a4207c8d9dfl, + 0x6fd495f71c52c66dl }, + { 0xfb0e169f275264dal,0x80c2b746e57d8362l,0xedd987f749ad7222l, + 0xfdc229af4398ec7bl }, + 0 }, + /* 65 << 168 */ + { { 0xfe81af4609418a51l,0xdbb60b836f18e3a5l,0x5e7a86ea4566ec9cl, + 0xb76ff40f25093925l }, + { 0x5fe6662c429c5554l,0xfc9ec35384e478cfl,0x73dbb5f3e8cfa761l, + 0x031e506592f82709l }, + 0 }, + /* 71 << 168 */ + { { 0x108c736abd49f2e0l,0xe230f2417487dcc8l,0x073fc4f8f74d939cl, + 0x98532487e9745bbel }, + { 0x5208eb981714b10bl,0xec35d0510458725dl,0x35dbb60bf203f4b6l, + 0x064299b27781ab38l }, + 0 }, + /* 77 << 168 */ + { { 0x43cc7bbc02d26929l,0xeb00a683162d9607l,0x2af152b8ed9fa224l, + 0xf24e8bee12257f0cl }, + { 0xdf065dd5d004b1cbl,0x6aa20bcf9f9908c6l,0x8e5e86b6941c593dl, + 0x0e0034b398969717l }, + 0 }, + /* 83 << 168 */ + { { 0x5be62e155c43b8fcl,0xd9e0adfc3c445636l,0xc5141df0e0d78f48l, + 0xd134bbed2c277716l }, + { 0x79033a84598fe069l,0x6c704367b081614cl,0x55c45d66bf5bf772l, + 0xf08744c57a444730l }, + 0 }, + /* 89 << 168 */ + { { 0x866752091422b528l,0xdb297411c3e028eel,0x1f5575b040e1c3ccl, + 0x85367b84d333b04fl }, + { 0x57864c86e9804aa9l,0xf13fa8e3439156dfl,0xa3b337e0464e0aecl, + 0x0018dfd7f2ae382bl }, + 0 }, + /* 95 << 168 */ + { { 0xe93cece9cea132fcl,0x985542d8f74e867al,0x2a3d18a5cc8fcf87l, + 0xa0561055479d0039l }, + { 0x3513c7eaac4b3f9dl,0xc095967256477606l,0xa63960f330df8ad6l, + 0x59ca8d53cc9ddcb3l }, + 0 }, + /* 101 << 168 */ + { { 0x6d8e942b2f208191l,0xd49a6d9453fe5457l,0x2b55e391003010bal, + 0x3dd1fd9fdf4605ebl }, + { 0xdc006a3358682886l,0x60a5e86c1bd9ac88l,0xc4bd320ed0cab8f2l, + 0x7281e7cb7751855bl }, + 0 }, + /* 107 << 168 */ + { { 0x7d564222e1881e7al,0x59061a89db0673c2l,0x1f9d607213f27313l, + 0x5b3b29368ff3aeb7l }, + { 0x6cf2304ccf969f43l,0x8eff4a25e7f69ae5l,0xbaeb6411d17da4ffl, + 0x666af0af9eea17ecl }, + 0 }, + /* 113 << 168 */ + { { 0x6c0b811697f4cd0bl,0xcd7825d40e4ea852l,0x80158fb0677fef3dl, + 0x5bb1a3aaa10ee693l }, + { 0xc5df66678066fc9bl,0x3200dc11f404d4a6l,0x58868950a8686d8el, + 0xbdaaffb53770fabal }, + 0 }, + /* 116 << 168 */ + { { 0xba6a9f84660326f5l,0x61c1e44161bc3e88l,0xfbf992a0bde85cf8l, + 0xe704dd1e6f8c8f5fl }, + { 0x231caa0ab1d7d486l,0xd10616d8891cd571l,0x2ddada75c008833cl, + 0x44337d6dad514c94l }, + 0 }, + /* 119 << 168 */ + { { 0xd48678b8f6933cf0l,0x7b4d623e0b739471l,0x4ad620287b216238l, + 0xb4d4918959c4fabel }, + { 0x8c2a1bdc296d42d5l,0x9235d0ec2fd3eb96l,0xfe271972f81c135bl, + 0x82b5181741471e16l }, + 0 }, + /* 125 << 168 */ + { { 0xe9aa8ce4051f8e81l,0x14484af67cd1391fl,0x53a361dcafb1656el, + 0x6ad8ba02f4d9d0cbl }, + { 0xfb4385466c50a722l,0x2f1c5bbc7edb37f4l,0x8dc90ccb16e4b795l, + 0xbcb32e1508127094l }, + 0 }, + }, + { + /* 0 << 176 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 176 */ + { { 0xb81d783e979f3925l,0x1efd130aaf4c89a7l,0x525c2144fd1bf7fal, + 0x4b2969041b265a9el }, + { 0xed8e9634b9db65b6l,0x35c82e3203599d8al,0xdaa7a54f403563f3l, + 0x9df088ad022c38abl }, + 0 }, + /* 3 << 176 */ + { { 0x9e93ba24f111661el,0xedced484b105eb04l,0x96dc9ba1f424b578l, + 0xbf8f66b7e83e9069l }, + { 0x872d4df4d7ed8216l,0xbf07f3778e2cbecfl,0x4281d89998e73754l, + 0xfec85fbb8aab8708l }, + 0 }, + /* 4 << 176 */ + { { 0x13b5bf22765fa7d0l,0x59805bf01d6a5370l,0x67a5e29d4280db98l, + 0x4f53916f776b1ce3l }, + { 0x714ff61f33ddf626l,0x4206238ea085d103l,0x1c50d4b7e5809ee3l, + 0x999f450d85f8eb1dl }, + 0 }, + /* 5 << 176 */ + { { 0x82eebe731a3a93bcl,0x42bbf465a21adc1al,0xc10b6fa4ef030efdl, + 0x247aa4c787b097bbl }, + { 0x8b8dc632f60c77dal,0x6ffbc26ac223523el,0xa4f6ff11344579cfl, + 0x5825653c980250f6l }, + 0 }, + /* 7 << 176 */ + { { 0xeda6c595d314e7bcl,0x2ee7464b467899edl,0x1cef423c0a1ed5d3l, + 0x217e76ea69cc7613l }, + { 0x27ccce1fe7cda917l,0x12d8016b8a893f16l,0xbcd6de849fc74f6bl, + 0xfa5817e2f3144e61l }, + 0 }, + /* 9 << 176 */ + { { 0xc0b48d4e49ccd6d7l,0xff8fb02c88bd5580l,0xc75235e907d473b2l, + 0x4fab1ac5a2188af3l }, + { 0x030fa3bc97576ec0l,0xe8c946e80b7e7d2fl,0x40a5c9cc70305600l, + 0x6d8260a9c8b013b4l }, + 0 }, + /* 10 << 176 */ + { { 0xe6c51073615cd9e4l,0x498ec047f1243c06l,0x3e5a8809b17b3d8cl, + 0x5cd99e610cc565f1l }, + { 0x81e312df7851dafel,0xf156f5baa79061e2l,0x80d62b71880c590el, + 0xbec9746f0a39faa1l }, + 0 }, + /* 11 << 176 */ + { { 0x2b09d2c3cfdcf7ddl,0x41a9fce3723fcab4l,0x73d905f707f57ca3l, + 0x080f9fb1ac8e1555l }, + { 0x7c088e849ba7a531l,0x07d35586ed9a147fl,0x602846abaf48c336l, + 0x7320fd320ccf0e79l }, + 0 }, + /* 13 << 176 */ + { { 0x92eb40907f8f875dl,0x9c9d754e56c26bbfl,0x158cea618110bbe7l, + 0x62a6b802745f91eal }, + { 0xa79c41aac6e7394bl,0x445b6a83ad57ef10l,0x0c5277eb6ea6f40cl, + 0x319fe96b88633365l }, + 0 }, + /* 15 << 176 */ + { { 0x77f84203d39b8c34l,0xed8b1be63125eddbl,0x5bbf2441f6e39dc5l, + 0xb00f6ee66a5d678al }, + { 0xba456ecf57d0ea99l,0xdcae0f5817e06c43l,0x01643de40f5b4baal, + 0x2c324341d161b9bel }, + 0 }, + /* 16 << 176 */ + { { 0x949c9976e1337c26l,0x6faadebdd73d68e5l,0x9e158614f1b768d9l, + 0x22dfa5579cc4f069l }, + { 0xccd6da17be93c6d6l,0x24866c61a504f5b9l,0x2121353c8d694da1l, + 0x1c6ca5800140b8c6l }, + 0 }, + /* 17 << 176 */ + { { 0x4e77c5575b45afb4l,0xe9ded649efb8912dl,0x7ec9bbf542f6e557l, + 0x2570dfff62671f00l }, + { 0x2b3bfb7888e084bdl,0xa024b238f37fe5b4l,0x44e7dc0495649aeel, + 0x498ca2555e7ec1d8l }, + 0 }, + /* 19 << 176 */ + { { 0x2e44d22526a1fc90l,0x0d6d10d24d70705dl,0xd94b6b10d70c45f4l, + 0x0f201022b216c079l }, + { 0xcec966c5658fde41l,0xa8d2bc7d7e27601dl,0xbfcce3e1ff230be7l, + 0x3394ff6b0033ffb5l }, + 0 }, + /* 21 << 176 */ + { { 0x05d99be8b9c20cdal,0x89f7aad5d5cd0c98l,0x7ef936fe5bb94183l, + 0x92ca0753b05cd7f2l }, + { 0x9d65db1174a1e035l,0x02628cc813eaea92l,0xf2d9e24249e4fbf2l, + 0x94fdfd9be384f8b7l }, + 0 }, + /* 23 << 176 */ + { { 0x29882d7c98379d44l,0xd000bdfb509edc8al,0xc6f95979e66fe464l, + 0x504a6115fa61bde0l }, + { 0x56b3b871effea31al,0x2d3de26df0c21a54l,0x21dbff31834753bfl, + 0xe67ecf4969269d86l }, + 0 }, + /* 25 << 176 */ + { { 0xed29a56da16d4b34l,0x7fba9d09dca21c4fl,0x66d7ac006d8de486l, + 0x6006198773a2a5e1l }, + { 0x8b400f869da28ff0l,0x3133f70843c4599cl,0x9911c9b8ee28cb0dl, + 0xcd7e28748e0af61dl }, + 0 }, + /* 27 << 176 */ + { { 0x6a7bb6a93b5bdb83l,0x08da65c0a4a72318l,0xc58d22aa63eb065fl, + 0x1717596c1b15d685l }, + { 0x112df0d0b266d88bl,0xf688ae975941945al,0x487386e37c292cacl, + 0x42f3b50d57d6985cl }, + 0 }, + /* 28 << 176 */ + { { 0x69e3be0427596893l,0xb6bb02a645bf452bl,0x0875c11af4c698c8l, + 0x6652b5c7bece3794l }, + { 0x7b3755fd4f5c0499l,0x6ea16558b5532b38l,0xd1c69889a2e96ef7l, + 0x9c773c3a61ed8f48l }, + 0 }, + /* 29 << 176 */ + { { 0x5a304ada8545d185l,0x82ae44ea738bb8cbl,0x628a35e3df87e10el, + 0xd3624f3da15b9fe3l }, + { 0xcc44209b14be4254l,0x7d0efcbcbdbc2ea5l,0x1f60336204c37bbel, + 0x21f363f556a5852cl }, + 0 }, + /* 31 << 176 */ + { { 0x81262e4225346689l,0x716da290b07c7004l,0x35f911eab7950ee3l, + 0x6fd72969261d21b5l }, + { 0x5238980308b640d3l,0x5b0026ee887f12a1l,0x20e21660742e9311l, + 0x0ef6d5415ff77ff7l }, + 0 }, + /* 33 << 176 */ + { { 0x64aa0874925dd0b0l,0x5ffd503851c474c6l,0x4478c72c8ebd4157l, + 0xb98694cb8c8375e2l }, + { 0xeda4edeecd8e208cl,0xf98a053d2c0670a6l,0x564bd3057f346b9dl, + 0xafbbf3e94c318fddl }, + 0 }, + /* 34 << 176 */ + { { 0x8a03410aa96c4685l,0xef1b6b16a978a31bl,0x44738a3b629df6cfl, + 0xa1dc65da807713e9l }, + { 0x569cc7884c373442l,0x1f30a2464965fb52l,0x56822f1677ff5e2el, + 0x63f18812e303748bl }, + 0 }, + /* 35 << 176 */ + { { 0x2abdc403dd0983ecl,0xec0c08c7f365c6f5l,0xe555083fbdb66b8bl, + 0x593685bc4e8973ffl }, + { 0x737df3f920e9c705l,0x00c7bcc309c31a5al,0x5f1d23e2efdcb34dl, + 0x79d9b382470f7949l }, + 0 }, + /* 36 << 176 */ + { { 0x44a315645fd2eb1dl,0x4e7397263fdd1356l,0x9b96735463200efel, + 0xcb70402e520bbb6al }, + { 0xcbc90d7e693d2642l,0x6fb00064bc9b4002l,0x95f2eab3d96f7150l, + 0xb1619e3fe035f47al }, + 0 }, + /* 37 << 176 */ + { { 0xd22d6073d1561bb7l,0x40666e4ba9928683l,0x90654dab8ab3f9b1l, + 0x7625c507b8773421l }, + { 0x288f28220ca88cd2l,0xbb88114ed8d005c1l,0xbeec2b0af603a11bl, + 0x8fdda60325f7949el }, + 0 }, + /* 39 << 176 */ + { { 0x6503632d6ee4f1d0l,0xd5449747ea394840l,0xd696167a8abe13a1l, + 0xc080f76e609ebaa9l }, + { 0x181acf0c10aa70d6l,0x70614461291e5e50l,0x7ade8e84b9f0c0a3l, + 0xef1de9f2cb11b41el }, + 0 }, + /* 40 << 176 */ + { { 0x2d5c3c848e592413l,0x727022961832ba2cl,0x22979b51596c6321l, + 0x738f31cb5a04db64l }, + { 0x0bdaa6ca98f84ee5l,0x4e9e827c15e21eeel,0x4c59dbcc3ea632e0l, + 0xed3404db5bc6f027l }, + 0 }, + /* 41 << 176 */ + { { 0x2841f05cfbaf8b26l,0xac9830db5b243770l,0xde3ab1707787f324l, + 0x1ee12efe079209bcl }, + { 0x2d3fd62d5bcf6e3cl,0x8a680655d60b0582l,0xdafc5061bc2b64a1l, + 0xe0d91e7526a88788l }, + 0 }, + /* 43 << 176 */ + { { 0x2d49c685426b1b1el,0x6c2149caeabb02f7l,0xa4697d7fde11984fl, + 0xa0e32fb3ed3c8707l }, + { 0xb783e825f4ca12dal,0xb2666e2448770a50l,0x82d47f478660e923l, + 0x6e36cd71fb4a984fl }, + 0 }, + /* 44 << 176 */ + { { 0x3295a8ea43c66b92l,0x99387af6ac5d19d4l,0x545f9b1b8e9d2090l, + 0x138b1c4c2660f530l }, + { 0xbfb05fd2ff872627l,0xb6614b0f4c3bc45cl,0x13defece62ca0fb0l, + 0x82ddae134fededd8l }, + 0 }, + /* 45 << 176 */ + { { 0x5a34499b871c4cbbl,0x3ab0e69a2eb6084bl,0xa8d0160025ef7755l, + 0x5db8f611d9e70f5dl }, + { 0x63f9eb9a7afa95d7l,0x328b97f9706d7964l,0x8bcf9a0f4b71dfcal, + 0x53d4c3042a5c7934l }, + 0 }, + /* 46 << 176 */ + { { 0x0c87dd3a8768d9aal,0x201ce5a082f6a55fl,0xa3de6f3049ca4602l, + 0x36f421422aeb5f17l }, + { 0x5c9962399817b77al,0x2584a10ae8d165acl,0x80f683d0c726f4aal, + 0x524307502dcdfa48l }, + 0 }, + /* 47 << 176 */ + { { 0x0c04399f94683df2l,0x0978e9d4e954838dl,0x01faa5e8cf4a7a7bl, + 0x92f6e6a90dae61cfl }, + { 0x0c0f1293373dc957l,0x8320178fd8cc6b67l,0x4af977ed4b6444f2l, + 0xd8c9a401ad8e5f84l }, + 0 }, + /* 48 << 176 */ + { { 0xbd5660ed9aed9f40l,0x70ca6ad1532a8c99l,0xc4978bfb95c371eal, + 0xe5464d0d7003109dl }, + { 0x1af32fdfd9e535efl,0xabf57ea798c9185bl,0xed7a741712b42488l, + 0x8e0296a7e97286fal }, + 0 }, + /* 49 << 176 */ + { { 0x79ee35ac16fca804l,0x8f16e6165f59782el,0x8fbef1011737694el, + 0xb34b7625462be08bl }, + { 0x7e63e1b016e75c91l,0xb6a18edd2d23728dl,0xcf761a1e7f299ab6l, + 0x796dcdebf16c770el }, + 0 }, + /* 51 << 176 */ + { { 0x47354f22308ee4afl,0x96959a538ecd6f4bl,0xf60b5f104055cbd2l, + 0x04b1c9599bd86095l }, + { 0x26accd8486008564l,0x46b2fe0478f31ea7l,0x5500dbf72dd76f23l, + 0x36bcdf584c496c6fl }, + 0 }, + /* 52 << 176 */ + { { 0x8836cd431527d7cel,0x1f236623187a50eal,0x6470c0ae847221f0l, + 0xc61f86b47e449110l }, + { 0x7cc9cc20fa9fcec1l,0xa394903019134349l,0xafe5a08ff53ab467l, + 0x9caba02301ed2919l }, + 0 }, + /* 53 << 176 */ + { { 0xffecbdce406abf1el,0x0ef4bcd73ae340d4l,0x7e37bae0e19d5613l, + 0xe191669be4c6e97al }, + { 0x9fafe59797292db7l,0xab7ef3713172d716l,0x9f0fff330ce3b533l, + 0xca94ff8f932dd8cfl }, + 0 }, + /* 55 << 176 */ + { { 0x659c8b5d78aea69el,0xdde7ab46476a8fb9l,0x26bfe303bd01b5e6l, + 0xf3dfb08a726a937cl }, + { 0xe7a591fa0a263670l,0xe872c3f8f97434a0l,0x4881a82e2e0f2c21l, + 0x17624e48788ef958l }, + 0 }, + /* 57 << 176 */ + { { 0xd526d66da7222e5bl,0xd33bb78efeb00e25l,0x9a7d670b932c8d08l, + 0xea31e5273cee093fl }, + { 0x55cc091bd04b7a43l,0x12b08d6dd01a123dl,0x1d98a6467fb0e7bal, + 0xdabb09483535fd0dl }, + 0 }, + /* 59 << 176 */ + { { 0x2862314d08b69b19l,0x9cf302e191effcfal,0x43bdc8462ead917al, + 0x21b238bbf94b3d8fl }, + { 0xa3736160e2f465d3l,0x4d7fb6818541e255l,0x46fa089a23551edcl, + 0xf7c41d17c1fefa8cl }, + 0 }, + /* 60 << 176 */ + { { 0x8ed0807fed113000l,0x8e1672d04c691484l,0x33a13ab31ee86ca0l, + 0x9df0d9573bcaee4fl }, + { 0x0cf0c638ef0dfb71l,0x1e0fe22ac2c9510al,0x43f506716fcc6a21l, + 0xccb58404cec03a94l }, + 0 }, + /* 61 << 176 */ + { { 0x59547e37fd0936c1l,0x81e0517df45140b1l,0xcc6ccd89ed49e3fcl, + 0xc2fa23eff3b897del }, + { 0x149511ef2050c80al,0xf66bea6b3140b833l,0xbbe1401e2786d723l, + 0x0aeb549c887509bcl }, + 0 }, + /* 63 << 176 */ + { { 0xf938e85060f5867al,0x806e1fff72429adcl,0x5ff7962a45f43b52l, + 0xd8375ab6b2bbb403l }, + { 0x00d5819b21b287fcl,0x15c7190ebae37d58l,0x075ce5ce05fcfb07l, + 0x76368d06dbc003cbl }, + 0 }, + /* 64 << 176 */ + { { 0x01079383171b445fl,0x9bcf21e38131ad4cl,0x8cdfe205c93987e8l, + 0xe63f4152c92e8c8fl }, + { 0x729462a930add43dl,0x62ebb143c980f05al,0x4f3954e53b06e968l, + 0xfe1d75ad242cf6b1l }, + 0 }, + /* 65 << 176 */ + { { 0x1cf508197630655el,0x9b4685c408d417f5l,0x6ea942619b049259l, + 0x31c29b54fe73b755l }, + { 0x3d2872a1f1f2af17l,0xbcd1139956bcbc4bl,0x4d14f59890d7a85cl, + 0xd2c46040dbcbe998l }, + 0 }, + /* 71 << 176 */ + { { 0x3c8a06ca9792c42al,0x92535628602460ddl,0xa95e13f2ddd4c676l, + 0xe823841d3b20d463l }, + { 0x0248605bbfad6051l,0x82985dd61af51233l,0x3d243a5cdef7d742l, + 0x0a88ce55ff6aa911l }, + 0 }, + /* 77 << 176 */ + { { 0xcf5b5962449aec98l,0x40322a6531a41389l,0xcd15606fd72c0527l, + 0xfe91eac7b90d65a0l }, + { 0xcd32415487636360l,0x82f2c7bdfc653a6fl,0xd04d138ae315ce7cl, + 0x40ebfd5e78118dbcl }, + 0 }, + /* 83 << 176 */ + { { 0x0f9ea6ae4144660fl,0x02345c6513279b25l,0x139497b65c7671cbl, + 0x7259f14b2ebed1d5l }, + { 0xa1e5d98ce9b29988l,0xaed0efcd8df73ac8l,0x88339f073b81a77cl, + 0x28f2bbca7109c8a6l }, + 0 }, + /* 89 << 176 */ + { { 0xa264f99d811472ddl,0x0e7eae0afc07a80cl,0x77f264d4a683cdc6l, + 0x0512df49d053c668l }, + { 0x2b4dfbade61dea15l,0x83de61acfd74890al,0xd2552bab32d41182l, + 0x1fb9411435924e6al }, + 0 }, + /* 95 << 176 */ + { { 0x85efe53ade23c988l,0x89d41dbbf897f91bl,0x1357f91e7873fa8dl, + 0x7a6ec2e3718d911cl }, + { 0xf9e4f92e8f209a01l,0x4ffb96a70fdd67f3l,0x4c81a787f83dde1cl, + 0x0d68fce15e163b60l }, + 0 }, + /* 101 << 176 */ + { { 0xbc79b4b26ab6da9dl,0xb4be5c278bb005f1l,0x63624530cd3b280bl, + 0x543142f04e880026l }, + { 0xbf7fb14cad90ddbfl,0xfe456e8a3966732dl,0x85499fb987ce35e9l, + 0x8af09e6b24f1305dl }, + 0 }, + /* 107 << 176 */ + { { 0x5fc563ec16dc2b4bl,0xfe5631b25d0e535fl,0xbf4c489f9a93e36cl, + 0x56badff1da2a07c4l }, + { 0x72ac6b77fb7c5595l,0x4b25b9428e6645d9l,0xeeae127251f0657el, + 0x30779ca51abeb76bl }, + 0 }, + /* 113 << 176 */ + { { 0x3d602ef5d909f43dl,0x2b2951a6bb347c79l,0x44903bfaa0d88896l, + 0xd4ab20e8684c104fl }, + { 0x55f70b4dd9b7e626l,0x084b3ee646a5f9ecl,0x1799cbe3da4ae81al, + 0xc7cfac937fd6b80fl }, + 0 }, + /* 116 << 176 */ + { { 0x45647911ca20c525l,0x78f83186004706abl,0x5596377d97510538l, + 0x047863defe041f8cl }, + { 0xaea784896ec82367l,0x9d4eac2601eee8fcl,0xb32728f19b57d9dbl, + 0x60a158f5313c0f65l }, + 0 }, + /* 119 << 176 */ + { { 0xf78caf129754377bl,0xa7fce16b6966f0c4l,0xfea937555a54a2b7l, + 0x52d7f79b7cdfe951l }, + { 0x3e14b92e94b1dac0l,0x363f2e5af168b73bl,0xcc0e9dcb6436a8c2l, + 0x2dbece4bb52cbd27l }, + 0 }, + /* 125 << 176 */ + { { 0x7e7907ed8df38ffel,0xa68ec827e24e8a24l,0x5093a97e5f168732l, + 0xa9ffea2f39ebb6dbl }, + { 0x89e02c12284276d4l,0xc1179e3b3f9502d6l,0x01becb51d8f69eb6l, + 0x86eee2935eb1c73cl }, + 0 }, + }, + { + /* 0 << 184 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 184 */ + { { 0xf3b7963f4c830320l,0x842c7aa0903203e3l,0xaf22ca0ae7327afbl, + 0x38e13092967609b6l }, + { 0x73b8fb62757558f1l,0x3cc3e831f7eca8c1l,0xe4174474f6331627l, + 0xa77989cac3c40234l }, + 0 }, + /* 3 << 184 */ + { { 0xb32cb8b0b796d219l,0xc3e95f4f34741dd9l,0x8721212568edf6f5l, + 0x7a03aee4a2b9cb8el }, + { 0x0cd3c376f53a89aal,0x0d8af9b1948a28dcl,0xcf86a3f4902ab04fl, + 0x8aacb62a7f42002dl }, + 0 }, + /* 4 << 184 */ + { { 0xfd8e139f8f5fcda8l,0xf3e558c4bdee5bfdl,0xd76cbaf4e33f9f77l, + 0x3a4c97a471771969l }, + { 0xda27e84bf6dce6a7l,0xff373d9613e6c2d1l,0xf115193cd759a6e9l, + 0x3f9b702563d2262cl }, + 0 }, + /* 5 << 184 */ + { { 0x9cb0ae6c252bd479l,0x05e0f88a12b5848fl,0x78f6d2b2a5c97663l, + 0x6f6e149bc162225cl }, + { 0xe602235cde601a89l,0xd17bbe98f373be1fl,0xcaf49a5ba8471827l, + 0x7e1a0a8518aaa116l }, + 0 }, + /* 7 << 184 */ + { { 0x8b1e572235e6fc06l,0x3477728f0b3e13d5l,0x150c294daa8a7372l, + 0xc0291d433bfa528al }, + { 0xc6c8bc67cec5a196l,0xdeeb31e45c2e8a7cl,0xba93e244fb6e1c51l, + 0xb9f8b71b2e28e156l }, + 0 }, + /* 9 << 184 */ + { { 0x343ac0a3ee9523f0l,0xbb75eab2975ea978l,0x1bccf332107387f4l, + 0x790f92599ab0062el }, + { 0xf1a363ad1e4f6a5fl,0x06e08b8462519a50l,0x609151877265f1eel, + 0x6a80ca3493ae985el }, + 0 }, + /* 10 << 184 */ + { { 0xa3f4f521e447f2c4l,0x81b8da7a604291f0l,0xd680bc467d5926del, + 0x84f21fd534a1202fl }, + { 0x1d1e31814e9df3d8l,0x1ca4861a39ab8d34l,0x809ddeec5b19aa4al, + 0x59f72f7e4d329366l }, + 0 }, + /* 11 << 184 */ + { { 0x2dfb9e08be0f4492l,0x3ff0da03e9d5e517l,0x03dbe9a1f79466a8l, + 0x0b87bcd015ea9932l }, + { 0xeb64fc83ab1f58abl,0x6d9598da817edc8al,0x699cff661d3b67e5l, + 0x645c0f2992635853l }, + 0 }, + /* 13 << 184 */ + { { 0xd50e57c7d7fe71f3l,0x15342190bc97ce38l,0x51bda2de4df07b63l, + 0xba12aeae200eb87dl }, + { 0xabe135d2a9b4f8f6l,0x04619d65fad6d99cl,0x4a6683a77994937cl, + 0x7a778c8b6f94f09al }, + 0 }, + /* 15 << 184 */ + { { 0x8dd1fb83425c6559l,0x7fc00ee60af06fdal,0xe98c922533d956dfl, + 0x0f1ef3354fbdc8a2l }, + { 0x2abb5145b79b8ea2l,0x40fd2945bdbff288l,0x6a814ac4d7185db7l, + 0xc4329d6fc084609al }, + 0 }, + /* 16 << 184 */ + { { 0x511053e453544774l,0x834d0ecc3adba2bcl,0x4215d7f7bae371f5l, + 0xfcfd57bf6c8663bcl }, + { 0xded2383dd6901b1dl,0x3b49fbb4b5587dc3l,0xfd44a08d07625f62l, + 0x3ee4d65b9de9b762l }, + 0 }, + /* 17 << 184 */ + { { 0x55ef9d3dcc26e8b0l,0xf869c827729b707al,0xdbbf450d8c47e00cl, + 0x73d546ea60972ed7l }, + { 0x9563e11f0dcd6821l,0xe48e1af57d80de7fl,0xbe7139b49057838dl, + 0xf3f0ad4d7e5ca535l }, + 0 }, + /* 19 << 184 */ + { { 0xac66d1d49f8f8cc2l,0x43fe5c154ef18941l,0xbae77b6ddc30fcbfl, + 0xdb95ea7d945723b7l }, + { 0x43298e2bda8097e2l,0x8004167baf22ea9bl,0x9cf5974196a83d57l, + 0xb35c9aba3cf67d5el }, + 0 }, + /* 21 << 184 */ + { { 0x0569a48df766f793l,0x6b4c7b16706b3442l,0xcc97754416ff41e0l, + 0x800c56e31fee2e86l }, + { 0xce0c3d0fcdf93450l,0x6ec3703582f35916l,0x902520d5bbc11e68l, + 0x7e2b988505078223l }, + 0 }, + /* 23 << 184 */ + { { 0xb30d1769101da00bl,0xb26872d5113cfdb6l,0x7b0491da44e48db5l, + 0x810e73bb2013f8c9l }, + { 0xc86e579a570f0b59l,0xf34107e37a918f34l,0x49286d00277473f1l, + 0x74423f5abc85905dl }, + 0 }, + /* 25 << 184 */ + { { 0x90d7417879de6b48l,0xe762caf0d14fa75bl,0xa309dcf3bd91ec5dl, + 0x7aafe1ddf526d04fl }, + { 0x76911342d39e36ffl,0xe28994d2fabb34b8l,0xac23a92c863110cbl, + 0x9f0f69673aabd166l }, + 0 }, + /* 27 << 184 */ + { { 0x7436bdf47e333f98l,0x879cf31f2455af64l,0x07933a9cf6cfde92l, + 0xfcac38a5b6e3203fl }, + { 0xa39b6a8098e5a6e0l,0x1d600b5da4837528l,0x54718de7c32d412bl, + 0x02870f46317937ccl }, + 0 }, + /* 28 << 184 */ + { { 0x1f13756db1761ec8l,0xe53c8b98a4b97e55l,0xb2aee3f84096cc28l, + 0x48c361a0920f1a8dl }, + { 0xa98b672d8c31190al,0x7bc1e7d1001855d4l,0x242cfb07bf3f4b2al, + 0x9bf44a3f32a28bc4l }, + 0 }, + /* 29 << 184 */ + { { 0x96d4b271e36eeccdl,0x2d8c01b859237e23l,0x24f7a6eb8adf2653l, + 0xc08ac4ab41183d80l }, + { 0xc35e5bb7036367c3l,0xd8c97cbc0ba59f61l,0x296b1f4c5aafe986l, + 0xa519c7a17d179c37l }, + 0 }, + /* 31 << 184 */ + { { 0x4043490790ae5f49l,0x8ac8f73649556b81l,0xb57a89b0f4e77a16l, + 0xe1a1565d071020eal }, + { 0x4a27f34d3dda8450l,0x65af18b9bc395814l,0xaf21939f9ff49991l, + 0x47e00639b4af7691l }, + 0 }, + /* 33 << 184 */ + { { 0x4b3e263246b1f9b2l,0x6457d838efde99d3l,0x77d5142325e56171l, + 0xb45de3df7d54996cl }, + { 0x1ee2dd3194098d98l,0x986896141f3ebdc5l,0x2704a107997efb47l, + 0x96b502eecb11e520l }, + 0 }, + /* 34 << 184 */ + { { 0x58c8039ec19f866el,0xc84c053e386c2644l,0xb3708ab049435704l, + 0x1b70c3c86fc47b24l }, + { 0x235582a27f095649l,0x0d344b66673c9a9el,0x777c9e71e2b00efdl, + 0x91691d6e5b877856l }, + 0 }, + /* 35 << 184 */ + { { 0x11c663c49cd31e22l,0x46ae0bd95fb943d7l,0x6e36bca6a392fc01l, + 0x4f8cc3a77948716fl }, + { 0x10ae9d6b3aa4bbb0l,0xcc9b6cb5d8001a86l,0x012c8e3aa0a4ceedl, + 0xe462971e52274942l }, + 0 }, + /* 36 << 184 */ + { { 0x9982e2ac42e176a5l,0x324eba46e2782b64l,0x3d8caaafe18350f5l, + 0xf3d82af2f5d674cal }, + { 0xc2090fed56600d1el,0x4548e0ef5950de07l,0xb2f0023f765a4febl, + 0xb303103339f16790l }, + 0 }, + /* 37 << 184 */ + { { 0xb94095dc7bdacf7al,0x0e73db39509b310al,0x76e99a6b41b5f772l, + 0xef40e9c596f3dbd7l }, + { 0xd0d644f980f2179el,0xe0db831d5a89807el,0xa0188493c2a2d6c6l, + 0xf2d9a85e5ba9faa9l }, + 0 }, + /* 39 << 184 */ + { { 0x598b7876cdd95b93l,0x5f7cc827336966e8l,0x01887109e797f102l, + 0x665671c446c7c296l }, + { 0xb314793c6e019c72l,0x5a6c81580e0329acl,0x4faf2f1b44281b98l, + 0x825884072e1fc97el }, + 0 }, + /* 40 << 184 */ + { { 0xa692781d61a3c8b3l,0x08bc385432876d0el,0xbecf05fb28027b03l, + 0x636c687da4b1e12fl }, + { 0x00e3003d07217c58l,0x613ba9375e01b2a3l,0xa58c8405881de16el, + 0xc653c43014f8f48bl }, + 0 }, + /* 41 << 184 */ + { { 0x68e53c7c89c0c7c2l,0xf2e680b23c423272l,0xacd47fae60f50133l, + 0x4c484c6534f05605l }, + { 0x663bdcf9ebffbb7dl,0xb49cff3be42421c6l,0x0549f7b13f53f261l, + 0xc516aeda7c374766l }, + 0 }, + /* 43 << 184 */ + { { 0xa515fe0f76a0ec26l,0xf727c0797b0b8b21l,0xaeed4c671993651el, + 0x1465a7f828ac7c87l }, + { 0x776bd5131f0ef90bl,0x57515d2cd9773e61l,0x235455e95564c50bl, + 0xf44daef80bf06a24l }, + 0 }, + /* 44 << 184 */ + { { 0xbc1c6897d6a0d0f9l,0xd8e0ea0e3b0d7f55l,0xb35baa92b85b7aadl, + 0x2becd1b7674e48f4l }, + { 0xe2d7f78d6d7a9ac2l,0xf5074262f99c95d0l,0x4852470a89f611e9l, + 0xf7aa911992869decl }, + 0 }, + /* 45 << 184 */ + { { 0x0bd1755b0ac4840fl,0x0f4c6c2aa22eef10l,0x3f72fe2d78d16dd9l, + 0xb2d49200ff7096a4l }, + { 0xa5dead555ffca031l,0x1d013c320b65f4cfl,0x67e498582a23f441l, + 0x55bae166d02412c0l }, + 0 }, + /* 46 << 184 */ + { { 0x546dd4545739a62al,0x353dc1422a30b836l,0x1462449d99cbd704l, + 0xda02d0772da69411l }, + { 0xcb115fe565b1a1adl,0x395235f501230a22l,0x8ae630eed164d970l, + 0x60b679f0074e3a7el }, + 0 }, + /* 47 << 184 */ + { { 0x2e64695245d231e1l,0xc96663ac00d8a0fbl,0xc1fbaa0cd07e1f41l, + 0x4b31484488758781l }, + { 0xd6971a835183e72el,0xd1d01f174cbe99b7l,0xe90b438c5a2f7512l, + 0xf858fa452957c620l }, + 0 }, + /* 48 << 184 */ + { { 0xed7f2e774e6daae2l,0x7b3ae0e39e0a19bcl,0xd3293f8a91ae677el, + 0xd363b0cb45c8611fl }, + { 0xbe1d1ccf309ae93bl,0xa3f80be73920cae1l,0xaaacba74498edf01l, + 0x1e6d2a4ab2f5ac90l }, + 0 }, + /* 49 << 184 */ + { { 0xb5c5bb67b972a778l,0xc2423a4a190f9b5al,0x4e693cf365247948l, + 0xc37d129ea94a65a3l }, + { 0xbea4736b6e9cd47bl,0xf3d1bd212338f524l,0xa2a0278e067a45dal, + 0xc86d631b5b5dce9bl }, + 0 }, + /* 51 << 184 */ + { { 0xc2d75f46116952cel,0xd2b66269b75e40dal,0x024f670f921c4111l, + 0x37ffd854c91fd490l }, + { 0x6be44d0385b2f613l,0x040cd7d9ba11c4f9l,0x04c1cb762c0efb1fl, + 0xd905ff4f505e4698l }, + 0 }, + /* 52 << 184 */ + { { 0x60c5f03f233550f1l,0xd4d09411925afd2el,0xa95b65c3d258e5a6l, + 0x1a19cfb59f902c6al }, + { 0xb486013af5ad5c68l,0xa2506776979638f3l,0x1232b4d0a38e0b28l, + 0xa64784b8d36a7b4fl }, + 0 }, + /* 53 << 184 */ + { { 0x22c75830a13dcb47l,0xd6e81258efd7a08fl,0x6db703b6e4fc49b8l, + 0x8a5ac636f01817e9l }, + { 0x8d27b6e1b3f24514l,0x40edc3bc708c51d7l,0x9a1eec7765bb086dl, + 0x812ccb42b10800f8l }, + 0 }, + /* 55 << 184 */ + { { 0x1a39c6acd4338453l,0x3d93822954b1295dl,0x7bf0bf45e0d81165l, + 0x83d58ca5972804d2l }, + { 0x105d3ddb00524b94l,0x65d516e7920378ecl,0x1d28f5f1aea33926l, + 0xa0b354313901c906l }, + 0 }, + /* 57 << 184 */ + { { 0x000442a1e4f354del,0x165b44d9d1d112f5l,0x67fd9ced0d05c0a9l, + 0xd6ce074360bd5d60l }, + { 0x9ac80c931522af2al,0x8232d522fa07d449l,0x287b5534c3fdb652l, + 0x9f0548b3abd2ab98l }, + 0 }, + /* 59 << 184 */ + { { 0xde8d7086b9aea1d4l,0x692180d98a7dc3fcl,0xd64ffb53bad3e6f3l, + 0x84628acf36ce3f91l }, + { 0xf76e470b6d498ac5l,0xa16945547abad602l,0x5b8fd6a5a255c1f6l, + 0xffe24e4a8576ae2al }, + 0 }, + /* 60 << 184 */ + { { 0x5655179de7d70e03l,0x3e780c5c72a84570l,0xc102b4cb1d50029cl, + 0x3e71bdd5f075e839l }, + { 0x6460f4f0b498b822l,0x2682e06c6d4b8da5l,0x4eae53c996a740d4l, + 0xc19d8bef6389702cl }, + 0 }, + /* 61 << 184 */ + { { 0x711be2081025fe1dl,0x2e562c89f0bc6a99l,0xcfd2be3a28bf4150l, + 0x33037b4a38e5bc91l }, + { 0x10c6da9df52fea02l,0x511f62444f0ea410l,0x19d37ca81a294c3fl, + 0x7e40f444618e6fd3l }, + 0 }, + /* 63 << 184 */ + { { 0x4095f5ddbedb8734l,0x9c16027c4432f51al,0xced8179d873d0f11l, + 0x70c2bc9f6ebe6e61l }, + { 0x5c31035d616cf2f4l,0xf92e0fbd00a4af3dl,0xe6048a03511893c4l, + 0x639a804b52e2f462l }, + 0 }, + /* 64 << 184 */ + { { 0x8735728dc2c6ff70l,0x79d6122fc5dc2235l,0x23f5d00319e277f9l, + 0x7ee84e25dded8cc7l }, + { 0x91a8afb063cd880al,0x3f3ea7c63574af60l,0x0cfcdc8402de7f42l, + 0x62d0792fb31aa152l }, + 0 }, + /* 65 << 184 */ + { { 0x0f4bcefd9da373e4l,0x7278f44d119271a3l,0xb2dff94449e111c0l, + 0xb0a3abf8e5d2b2d4l }, + { 0x01baabb48ea80631l,0x27517ed3da305f85l,0x0a1ca6fc3f56aa86l, + 0x183d9c7694c22839l }, + 0 }, + /* 71 << 184 */ + { { 0xe9a0dfbf22e238d7l,0x8690dfd97e8d8d31l,0xb3cb2a0d4006c59cl, + 0xe4d297caa1850d74l }, + { 0x066f10517842d14cl,0x68dd32737d43602bl,0x1f9f5cf931345f39l, + 0x44f18c2b10593890l }, + 0 }, + /* 77 << 184 */ + { { 0x8d8c0233a7c3f60bl,0xfb59fe2d2bcbbd4cl,0xfa311680dc3e5b44l, + 0xb3cba9f3fbea5eedl }, + { 0xcb353b2f61e0e690l,0x06edf0c1b6e0efe0l,0xa29578cb1d0c02a2l, + 0xaeb2d677937fec07l }, + 0 }, + /* 83 << 184 */ + { { 0xa19a81c5cdd0cac9l,0x5c10b942ec9cf85bl,0x0843ef4639e8c298l, + 0xcfd45d0e6c043258l }, + { 0x1011bcb9fb7e4b58l,0xae6362a544402bbdl,0x9ecc8c68ec15d751l, + 0xbc05998869d1a00bl }, + 0 }, + /* 89 << 184 */ + { { 0xe9a43619460147e3l,0x881a6af423067448l,0x94f93ae6cee17a6bl, + 0x469e692f10782558l }, + { 0x01e244a1289bdb32l,0x240645779dddf970l,0x664cbd92d8f521ecl, + 0xadaf8ffb600222d0l }, + 0 }, + /* 95 << 184 */ + { { 0x68314c740dbec437l,0x2095e1295ec75e2cl,0x8e88a3ddf0e6c606l, + 0x40ac647d1230f6b2l }, + { 0x09d124aaa2e6b991l,0xa22f9e2bcc81037cl,0xc842b64d15c3a1c2l, + 0x4d822becce808c65l }, + 0 }, + /* 101 << 184 */ + { { 0xb02204d06ffb396bl,0x82eb6ecc881bead6l,0xf58432cebd6896c8l, + 0xc243468da38f4b9dl }, + { 0x8486402df8e628bdl,0x5dd338a1a4df2401l,0x748a41ab0daac953l, + 0xaa121d13e51e6235l }, + 0 }, + /* 107 << 184 */ + { { 0x6daa0a4e50abc6aal,0x99fcc5bdeafb7cf2l,0xc705f64c4b8dbd2al, + 0x7deff836e7b51e90l }, + { 0xd92f42b859a8180fl,0x3bb298f8618d24acl,0x2433aa7357a56438l, + 0xcf29895b48a6a238l }, + 0 }, + /* 113 << 184 */ + { { 0x74079dc59ed25aafl,0x7988245c023d5143l,0x7edfc6a6feb79c24l, + 0x7ed03c50a6baa70fl }, + { 0x71d3413596a753b4l,0x59efbafcef976246l,0xed050260a4a6947fl, + 0xabbc1f8066254247l }, + 0 }, + /* 116 << 184 */ + { { 0x1f804e00caa4646fl,0x8643dc8870944924l,0xa37f1ca273f86de9l, + 0xa3199f9228889898l }, + { 0xc273ba580c1e4adfl,0x0f0d38af65bc82f0l,0xd8b28ab5f8a6cd3bl, + 0xeea6e08575894d8el }, + 0 }, + /* 119 << 184 */ + { { 0x398f39132c1620f7l,0x9046d2dea921f3a3l,0x40a25a2785b50bb0l, + 0xb9adeca0d32e95f3l }, + { 0xa4199b1bdede5cbfl,0x9068aee084f5410bl,0x6665e4f5730f0397l, + 0x2e9ba18c8ae20659l }, + 0 }, + /* 125 << 184 */ + { { 0xd76e9b2351835897l,0x72a0e000012deda6l,0x5bf08922bfec23e4l, + 0x8c2fcf1385cf2b7bl }, + { 0x6c42f935c63332c6l,0x8736c58395eccce9l,0x2d2abbb10721afc8l, + 0x1f7a76cc42d4e029l }, + 0 }, + }, + { + /* 0 << 192 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 192 */ + { { 0x56f8410ef4f8b16al,0x97241afec47b266al,0x0a406b8e6d9c87c1l, + 0x803f3e02cd42ab1bl }, + { 0x7f0309a804dbec69l,0xa83b85f73bbad05fl,0xc6097273ad8e197fl, + 0xc097440e5067adc1l }, + 0 }, + /* 3 << 192 */ + { { 0x266344a43794f8dcl,0xdcca923a483c5c36l,0x2d6b6bbf3f9d10a0l, + 0xb320c5ca81d9bdf3l }, + { 0x620e28ff47b50a95l,0x933e3b01cef03371l,0xf081bf8599100153l, + 0x183be9a0c3a8c8d6l }, + 0 }, + /* 4 << 192 */ + { { 0xb6c185c341dca566l,0x7de7fedad8622aa3l,0x99e84d92901b6dfbl, + 0x30a02b0e7c4ad288l }, + { 0xc7c81daa2fd3cf36l,0xd1319547df89e59fl,0xb2be8184cd496733l, + 0xd5f449eb93d3412bl }, + 0 }, + /* 5 << 192 */ + { { 0x25470fabe085116bl,0x04a4337587285310l,0x4e39187ee2bfd52fl, + 0x36166b447d9ebc74l }, + { 0x92ad433cfd4b322cl,0x726aa817ba79ab51l,0xf96eacd8c1db15ebl, + 0xfaf71e910476be63l }, + 0 }, + /* 7 << 192 */ + { { 0x72cfd2e949dee168l,0x1ae052233e2af239l,0x009e75be1d94066al, + 0x6cca31c738abf413l }, + { 0xb50bd61d9bc49908l,0x4a9b4a8cf5e2bc1el,0xeb6cc5f7946f83acl, + 0x27da93fcebffab28l }, + 0 }, + /* 9 << 192 */ + { { 0x3ce519ef76257c51l,0x6f5818d318d477e7l,0xab022e037963edc0l, + 0xf0403a898bd1f5f3l }, + { 0xe43b8da0496033cal,0x0994e10ea1cfdd72l,0xb1ec6d20ba73c0e2l, + 0x0329c9ecb6bcfad1l }, + 0 }, + /* 10 << 192 */ + { { 0xf1ff42a12c84bd9dl,0x751f3ec4390c674al,0x27bb36f701e5e0cal, + 0x65dfff515caf6692l }, + { 0x5df579c4cd7bbd3fl,0xef8fb29785591205l,0x1ded7203e47ac732l, + 0xa93dc45ccd1c331al }, + 0 }, + /* 11 << 192 */ + { { 0xbdec338e3318d2d4l,0x733dd7bbbe8de963l,0x61bcc3baa2c47ebdl, + 0xa821ad1935efcbdel }, + { 0x91ac668c024cdd5cl,0x7ba558e4c1cdfa49l,0x491d4ce0908fb4dal, + 0x7ba869f9f685bde8l }, + 0 }, + /* 13 << 192 */ + { { 0xed1b5ec279f464bal,0x2d65e42c47d72e26l,0x8198e5749e67f926l, + 0x4106673834747e44l }, + { 0x4637acc1e37e5447l,0x02cbc9ecf3e15822l,0x58a8e98e805aa83cl, + 0x73facd6e5595e800l }, + 0 }, + /* 15 << 192 */ + { { 0x468ff80338330507l,0x06f34ddf4037a53el,0x70cd1a408d6993a4l, + 0xf85a159743e5c022l }, + { 0x396fc9c2c125a67dl,0x03b7bebf1064bfcbl,0x7c444592a9806dcbl, + 0x1b02614b4487cd54l }, + 0 }, + /* 16 << 192 */ + { { 0x8303604f692ac542l,0xf079ffe1227b91d3l,0x19f63e6315aaf9bdl, + 0xf99ee565f1f344fbl }, + { 0x8a1d661fd6219199l,0x8c883bc6d48ce41cl,0x1065118f3c74d904l, + 0x713889ee0faf8b1bl }, + 0 }, + /* 17 << 192 */ + { { 0xb47b60f70de21bb6l,0x64acae4fdcd836cal,0x3375ea6dc744ce63l, + 0xb764265fb047955bl }, + { 0xc68a5d4c9841c2c3l,0x60e98fd7cf454f60l,0xc701fbe2756aea0cl, + 0x09c8885eaab21c79l }, + 0 }, + /* 19 << 192 */ + { { 0x45bb810869d2d46cl,0xe47c8b3968c8365al,0xf3b87663267551bdl, + 0x1590768f5b67547al }, + { 0x371c1db2fb2ed3ffl,0xe316691917a59440l,0x03c0d178df242c14l, + 0x40c93fceed862ac1l }, + 0 }, + /* 21 << 192 */ + { { 0x1286da692bc982d6l,0x5f6d80f27bdae7e3l,0x3d9c5647a6f064fbl, + 0xfdc8e6a1d74c1540l }, + { 0x97da48c6d68b135al,0xc2097979d66dbfffl,0x0296adb9ea20531dl, + 0xa333730d4ab2c8f0l }, + 0 }, + /* 23 << 192 */ + { { 0x0eb3565429847fedl,0xfdc142860a673dd0l,0x721b36278b62dd0bl, + 0x105a293e711a5771l }, + { 0xdf001cce7f761927l,0xf7b681b011d04c7dl,0x16dff792a3ac1996l, + 0x580c120b0fc4ae30l }, + 0 }, + /* 25 << 192 */ + { { 0x31ea3d4f7ee8d0bcl,0x3832f22a0f42c3dcl,0xc661061a1a87a2f4l, + 0x0978c9f64b45576bl }, + { 0xb7abac3c6dfb5fd2l,0x27f36a00b7e01b90l,0x68f733cde9429e36l, + 0x953a4681dcbfe8cbl }, + 0 }, + /* 27 << 192 */ + { { 0xbfb7c41067fe1eafl,0xa2073c6a6929a785l,0x6f2536f4a75fdb79l, + 0x859ad26d809bca69l }, + { 0x06f2c0693b197e7bl,0x656ad9f48ec0a573l,0xe7c7901f9a4d0262l, + 0xbec29443b938602bl }, + 0 }, + /* 28 << 192 */ + { { 0xd00397fc0f0073a4l,0x5b668fa46f8d675fl,0x14374ac91522108cl, + 0x92efa7d10283e42el }, + { 0x673e6df90b6d024al,0x05f914d457581f26l,0xf5c8516267df8c12l, + 0x1197f1b4e06c2462l }, + 0 }, + /* 29 << 192 */ + { { 0x6e2d1cb3dd9c90c1l,0x28f82d5a7990579el,0x90e189cd06226195l, + 0xbd2939df19b0dc74l }, + { 0x18b18505c0917177l,0xeed5470d3117d9c4l,0x39ef92eb6c893ca0l, + 0x4533ef8244a41940l }, + 0 }, + /* 31 << 192 */ + { { 0xcaee9dec34943ddal,0x8e50e98e8b4b6782l,0x24358ea591ea3a1fl, + 0x71c4c827a9e1c194l }, + { 0xa38baa5d09bb7a94l,0xfb4ab4c057b58f9cl,0x4a01065e24e0ee19l, + 0xb9cf805107b877bfl }, + 0 }, + /* 33 << 192 */ + { { 0xd38c1ce0a2980d5el,0x8b84cca4541face7l,0x93298136dbd8d05dl, + 0x582708d03f85c85al }, + { 0x6545eec7282960e4l,0x92e184aebaadec07l,0x05452564fd27a20fl, + 0x79d4668abddce6ebl }, + 0 }, + /* 34 << 192 */ + { { 0xf5cc5cccf5191707l,0xe800328bd5d01f67l,0x0572012ebd9b1599l, + 0xf5be11a6863d0125l }, + { 0x4da7ca876ea441e0l,0x47dbf83b321b134al,0x5cbadcdac1acfb4al, + 0x19ac798a734f8e25l }, + 0 }, + /* 35 << 192 */ + { { 0xe312623a7002114fl,0xb888b637e047686bl,0x23b2c270cbac91bdl, + 0xb50b31884dbfe02dl }, + { 0x8335ce43de97eef6l,0x6a4e65502bac193al,0xf2b35aac3101f720l, + 0x5b2c88d5379a2015l }, + 0 }, + /* 36 << 192 */ + { { 0xf445e77131547128l,0x22761665e27811cal,0x9b944e91a37c6681l, + 0xc0aa06a536899860l }, + { 0x8c2b5816cfcd557el,0xf2734a19945aa357l,0x536ca07ca55a0049l, + 0x8328fdccc636d967l }, + 0 }, + /* 37 << 192 */ + { { 0x52b513616aca06bdl,0x8d19b893cdf16560l,0x06b28179c3b438cdl, + 0xde1ef747cd1819e4l }, + { 0xbc6cc43b5f557985l,0xa277e11f61e0142al,0x58890f1e429cc392l, + 0x28d17dbfe5fc8f5el }, + 0 }, + /* 39 << 192 */ + { { 0x556df61a29a8f7cbl,0x5cf554dfd14ab27al,0x243f933ba755b886l, + 0xa4d0b06ff2d4ce87l }, + { 0xa745eb8d2c0f1d39l,0xc228747aea3047a5l,0xced774c41d2cecc0l, + 0x54a55c3a774fb01al }, + 0 }, + /* 40 << 192 */ + { { 0xa691398a4a9eb3f0l,0x56c1dbff3b99a48fl,0x9a87e1b91b4b5b32l, + 0xad6396145378b5fel }, + { 0x437a243ec26b5302l,0x0275878c3ccb4c10l,0x0e81e4a21de07015l, + 0x0c6265c9850df3c0l }, + 0 }, + /* 41 << 192 */ + { { 0x182c3f0e6be95db0l,0x8c5ab38cae065c62l,0xcce8294ebe23abacl, + 0xed5b65c47d0add6dl }, + { 0xbce57d78cc9494cal,0x76f75c717f435877l,0xb3084b2eb06560a9l, + 0x67216bc850b55981l }, + 0 }, + /* 43 << 192 */ + { { 0x49c9fd92557de68bl,0x357aa44fc3151b7al,0xd36286d11e4aebd0l, + 0x84562cd736a51203l }, + { 0x42a57e7c3cacc002l,0x794a47751b1e25a3l,0x2c2ab68cac0d4356l, + 0xececb6addb31afdcl }, + 0 }, + /* 44 << 192 */ + { { 0x47a5f010b4c21bfel,0x45c5610f0ac3dc20l,0x20e689fcea3bf4dcl, + 0xf244ea49fb5f46e4l }, + { 0xd918e59e8ca38e45l,0x7d6c601d96189a6fl,0x1a40f03854138471l, + 0xfe867d7308a9d034l }, + 0 }, + /* 45 << 192 */ + { { 0x3b49e489100c0410l,0x8831d3992adc2b29l,0xb6726cd1247a8116l, + 0x83a71a59d1d56d8el }, + { 0x82ade2fe5cd333e9l,0x3b087ef83ea11f1al,0x17b96ca66ce879cel, + 0xc2f74a971871dc43l }, + 0 }, + /* 46 << 192 */ + { { 0xa11a1e3680b576cel,0xf91278bbce2683e8l,0xc3bab95fbae8bc5bl, + 0x642ca26397351715l }, + { 0x5ffc14726fecbbc1l,0x2465e996a23f36d4l,0x06fc53bf5187d428l, + 0x54b4014351fbce91l }, + 0 }, + /* 47 << 192 */ + { { 0x081ca6f0eafc7b2cl,0x1ba047a38c48703fl,0xe84865046663accfl, + 0xde1f97568d43689cl }, + { 0xf5373e1d5bc19f75l,0x4e48c493d64b0a54l,0x0c43f4e25807dbf6l, + 0x73bef15167778c36l }, + 0 }, + /* 48 << 192 */ + { { 0xca6c0937b1b76ba6l,0x1a2eab854d2026dcl,0xb1715e1519d9ae0al, + 0xf1ad9199bac4a026l }, + { 0x35b3dfb807ea7b0el,0xedf5496f3ed9eb89l,0x8932e5ff2d6d08abl, + 0xf314874e25bd2731l }, + 0 }, + /* 49 << 192 */ + { { 0x9d5322e89e9bba53l,0xdd7c9ceb989ff350l,0xd76147eadab0d7b3l, + 0x8e45b1c6d7a9a9a1l }, + { 0x8f896a91d4f10c10l,0x999a73c54068de06l,0x84a9d0839cf0a779l, + 0x4d7cc7689f608ab2l }, + 0 }, + /* 51 << 192 */ + { { 0x1833ccddaee93c82l,0x6a05ef7b9f35f20fl,0xc538dac9ae413bc2l, + 0x1e74f4658b4784bdl }, + { 0xccb2bc4a49ffd544l,0x9b88183d2b17ae88l,0x96037a136e43824fl, + 0xbbb61441480bf3dfl }, + 0 }, + /* 52 << 192 */ + { { 0x13319d20e090ad42l,0x4ff3186e12cbb719l,0xf38e504913fc0a46l, + 0x83185a1254e60378l }, + { 0x08c4057797ea8935l,0x7b2212a946b614f9l,0xedcdfa520634cfb3l, + 0xdbc60eed9e7d5726l }, + 0 }, + /* 53 << 192 */ + { { 0x9b0785c6c7e1070fl,0xec112f53cbf561e5l,0xc93511e37fab3464l, + 0x9e6dc4da9de8e0c2l }, + { 0x7733c425e206b4eel,0xb8b254ef50cedf29l,0xfaee4bbbd50ad285l, + 0x216e76d58c4eb6cfl }, + 0 }, + /* 55 << 192 */ + { { 0x9d6a28641d51f254l,0x26c5062a0c2822c3l,0xd74ebba8334bf4eel, + 0x6e5446eb0b8f7305l }, + { 0x5988ae8eb629beccl,0x71e576d0a1de7d1dl,0x15e39592a8873970l, + 0x2b1f9a9342ecc74el }, + 0 }, + /* 57 << 192 */ + { { 0xcbdb70727c519bf9l,0x112986bbcaaf48e6l,0x64d4c6d1a13baf3cl, + 0x85ccf6f7a065e77el }, + { 0x183be337749beaedl,0xb3703096cba6c9b1l,0x1edf81f0e42b8afel, + 0xf04ed594ccb73ad7l }, + 0 }, + /* 59 << 192 */ + { { 0xfa954ebc38491e9fl,0xf75a5808d32f0b03l,0x196d4a828083b9d3l, + 0x92d5a0be5e8dc9fel }, + { 0x4a507ae9aea628bal,0xeea5861e11a02fb5l,0xa033b84fd23ec8f7l, + 0x1a68c36ec60f11d5l }, + 0 }, + /* 60 << 192 */ + { { 0x3dfb55bdab920ef2l,0xe0090971e6244484l,0xdc39fd08f7c6e1a3l, + 0x1ca765356ee79e72l }, + { 0x472c8985287d590cl,0x67635e35ad6daeb4l,0x06ec4e7980f9fee3l, + 0x0aceb39921dc5fdbl }, + 0 }, + /* 61 << 192 */ + { { 0xdb2478fd9410a756l,0xd106aefe3a53a1e6l,0x1f4c940d14286333l, + 0x6a98659d04950958l }, + { 0x3232a1c6a6bbe060l,0x19ad132ca5e7ca9bl,0x3c9c13ef800fae29l, + 0x9b0d9068b8660f49l }, + 0 }, + /* 63 << 192 */ + { { 0x1e7f043795c53027l,0x5221e5c0da9a3806l,0xf297d8e379d9385fl, + 0x4d69e95f78ba697el }, + { 0xdda936cee76d13c1l,0xd9a5790a485b12f5l,0xeab84add51efbfd0l, + 0xc9a3ee9ca9f44aa4l }, + 0 }, + /* 64 << 192 */ + { { 0xefb26a753f73f449l,0x1d1c94f88d44fc79l,0x49f0fbc53bc0dc4dl, + 0xb747ea0b3698a0d0l }, + { 0x5218c3fe228d291el,0x35b804b543c129d6l,0xfac859b8d1acc516l, + 0x6c10697d95d6e668l }, + 0 }, + /* 65 << 192 */ + { { 0x8c12e87a15454db4l,0xbc1fc546908e8fbcl,0xc35d83c7e4cf1636l, + 0xcb2f5ac820641524l }, + { 0x2400aae2e644ecd0l,0x9b01e2d14be37119l,0x6cffd52831b54857l, + 0xb3fd5d864b5cbf81l }, + 0 }, + /* 71 << 192 */ + { { 0x2e999a4739709fb9l,0x4cb4bbdb62c2b30fl,0x4c7259ac09de0c92l, + 0x73c1e34f8c59a0ffl }, + { 0x0a9e5f2e48cb0a12l,0x5e07449fcf499bb0l,0x0527a8b4b02c4a54l, + 0x7381287159da01e4l }, + 0 }, + /* 77 << 192 */ + { { 0xe0b876ca0548ff87l,0x74b5a9b25e03bae3l,0xd5564cc5dd0642d2l, + 0x29ed211b668c4977l }, + { 0xf29d3b7aa7422b11l,0x17f2d3586d29b8bal,0x2e35cdda2bb887del, + 0x650f148078e4444bl }, + 0 }, + /* 83 << 192 */ + { { 0x8c75532fb47435ebl,0x2234e2c5a113f905l,0x27b75fea31508ae9l, + 0x09733e40d489ad0bl }, + { 0x73b38464a1b06da1l,0x0aed522dc5b7ccf2l,0xcc04783e78d7e5afl, + 0xa81c8a8ff23eaab7l }, + 0 }, + /* 89 << 192 */ + { { 0x6bb5eca73c149ffal,0x4593d851c536487al,0x3675daaad85eb9edl, + 0xbf65d0f9b8a58ffbl }, + { 0x1dc6ddddc22e83eel,0xb673397ee10d3c17l,0x6bdc20600ca62c93l, + 0x260389c30b821f6dl }, + 0 }, + /* 95 << 192 */ + { { 0x45f5cf07b417be10l,0x0acb1a44e5d561d8l,0x54b7baeafb1dfbe9l, + 0x0e6e66219044672el }, + { 0xa9b6db6d9a793601l,0xd70eadb8a4a0ba4al,0xaedace846098b89el, + 0x970f2c23ac39d40fl }, + 0 }, + /* 101 << 192 */ + { { 0x9dff8d289c7eaaa8l,0x38bcd076db0cc361l,0x25760147cdea9db8l, + 0x44c89dd40163f343l }, + { 0x18815d7544db8365l,0xa186d57b37f3e4b3l,0xa71de7806e84a7fal, + 0xf1c08989e56646b3l }, + 0 }, + /* 107 << 192 */ + { { 0xad73e1448fb56a43l,0x078c14fb715543c9l,0xa57770fd64b92d54l, + 0xf0420a9277e9b919l }, + { 0xc660d0cb588ccc1dl,0x069baa1471415c2el,0x747438dc32982740l, + 0x4782ce08767381eel }, + 0 }, + /* 113 << 192 */ + { { 0xc2a1ee5fdb3b6b5dl,0x08ce544820e1339fl,0x3cb954b77073955fl, + 0xb9ed2ee7f32d0832l }, + { 0xc0a998b1b4aac98el,0x4912273dbca4bac7l,0xac0f5014c3f92c4al, + 0xbf3dc27f9e916e78l }, + 0 }, + /* 116 << 192 */ + { { 0x222c7bae28833944l,0xbb78a867f5e3cf67l,0x590cbd96faf6cfd6l, + 0x1c50aecb3b0d842el }, + { 0x8f2c5df1dbade9a5l,0x60923fb7e3840cecl,0xe8f2db6b03a67512l, + 0x90af187be0d7c628l }, + 0 }, + /* 119 << 192 */ + { { 0xb4162b615fee3ccbl,0xe9786e7d7327e651l,0x6c85bd938812d9c1l, + 0xfe4905083dc9e838l }, + { 0xe66f25178a6765dfl,0x72fd294edeee184cl,0x07608bd27b6ec227l, + 0x9df7b664dfdaa5e6l }, + 0 }, + /* 125 << 192 */ + { { 0x4aea16602d53a155l,0x7285069a32ab07fdl,0xf6f3000d8b6fcd19l, + 0x010b1f246e98953fl }, + { 0xe180bc559f9aa221l,0x7717ee383cba4534l,0x5997f3aa36cbda06l, + 0x54c6090064a04b05l }, + 0 }, + }, + { + /* 0 << 200 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 200 */ + { { 0x25914f7881fdad90l,0xcf638f560d2cf6abl,0xb90bc03fcc054de5l, + 0x932811a718b06350l }, + { 0x2f00b3309bbd11ffl,0x76108a6fb4044974l,0x801bb9e0a851d266l, + 0x0dd099bebf8990c1l }, + 0 }, + /* 3 << 200 */ + { { 0xebd6a6777b0ac93dl,0xa6e37b0d78f5e0d7l,0x2516c09676f5492bl, + 0x1e4bf8889ac05f3al }, + { 0xcdb42ce04df0ba2bl,0x935d5cfd5062341bl,0x8a30333382acac20l, + 0x429438c45198b00el }, + 0 }, + /* 4 << 200 */ + { { 0xfb2838be67e573e0l,0x05891db94084c44bl,0x9131137396c1c2c5l, + 0x6aebfa3fd958444bl }, + { 0xac9cdce9e56e55c1l,0x7148ced32caa46d0l,0x2e10c7efb61fe8ebl, + 0x9fd835daff97cf4dl }, + 0 }, + /* 5 << 200 */ + { { 0x6c626f56c1770616l,0x5351909e09da9a2dl,0xe58e6825a3730e45l, + 0x9d8c8bc003ef0a79l }, + { 0x543f78b6056becfdl,0x33f13253a090b36dl,0x82ad4997794432f9l, + 0x1386493c4721f502l }, + 0 }, + /* 7 << 200 */ + { { 0xe566f400b008733al,0xcba0697d512e1f57l,0x9537c2b240509cd0l, + 0x5f989c6957353d8cl }, + { 0x7dbec9724c3c2b2fl,0x90e02fa8ff031fa8l,0xf4d15c53cfd5d11fl, + 0xb3404fae48314dfcl }, + 0 }, + /* 9 << 200 */ + { { 0xf02cc3a9f327a07fl,0xefb27a9b4490937dl,0x81451e96b1b3afa5l, + 0x67e24de891883be4l }, + { 0x1ad65d4770869e54l,0xd36291a464a3856al,0x070a1abf7132e880l, + 0x9511d0a30e28dfdfl }, + 0 }, + /* 10 << 200 */ + { { 0xfdeed650f8d1cac4l,0xeb99194b6d16bda5l,0xb53b19f71cabbe46l, + 0x5f45af5039b9276cl }, + { 0xd0784c6126ee9d77l,0xf7a1558b0c02ca5dl,0xb61d6c59f032e720l, + 0xae3ffb95470cf3f7l }, + 0 }, + /* 11 << 200 */ + { { 0x9b185facc72a4be5l,0xf66de2364d848089l,0xba14d07c717afea9l, + 0x25bfbfc02d551c1cl }, + { 0x2cef0ecd4cdf3d88l,0x8cee2aa3647f73c4l,0xc10a7d3d722d67f7l, + 0x090037a294564a21l }, + 0 }, + /* 13 << 200 */ + { { 0x6ac07bb84f3815c4l,0xddb9f6241aa9017el,0x31e30228ca85720al, + 0xe59d63f57cb75838l }, + { 0x69e18e777baad2d0l,0x2cfdb784d42f5d73l,0x025dd53df5774983l, + 0x2f80e7cee042cd52l }, + 0 }, + /* 15 << 200 */ + { { 0x43f18d7f4d6ee4abl,0xd3ac8cde9570c3dcl,0x527e49070b8c9b2al, + 0x716709a7c5a4c0f1l }, + { 0x930852b0916a26b1l,0x3cc17fcf4e071177l,0x34f5e3d459694868l, + 0xee0341aba28f655dl }, + 0 }, + /* 16 << 200 */ + { { 0xf431f462060b5f61l,0xa56f46b47bd057c2l,0x348dca6c47e1bf65l, + 0x9a38783e41bcf1ffl }, + { 0x7a5d33a9da710718l,0x5a7799872e0aeaf6l,0xca87314d2d29d187l, + 0xfa0edc3ec687d733l }, + 0 }, + /* 17 << 200 */ + { { 0x4b764317aa365220l,0x7a24affe68cc0355l,0x76732ed0ceb3df5el, + 0x2ce1332aae096ed0l }, + { 0x89ce70a7b8adac9dl,0xfdddcf05b3fc85c8l,0xbd7b29c6f2ee8bfel, + 0xa1effcb9457d50f3l }, + 0 }, + /* 19 << 200 */ + { { 0x6053972dac953207l,0xc2ca9a8408ad12f6l,0x9ed6cd386ba36190l, + 0xa5b50a48539d18a4l }, + { 0xd9491347dbf18c2al,0x2cdce4662e9697cfl,0x4e97db5ca9e31819l, + 0x0fb02e2d4c044b74l }, + 0 }, + /* 21 << 200 */ + { { 0x66a4dd414aa5e9ddl,0x6ec7576e64f6aeb9l,0x3f08ce06c7e980b5l, + 0x52fe9fd6c1a2aa7el }, + { 0xfe46e6d95074326al,0xd570ed734c126c1dl,0x86c7ec257217d55al, + 0x3cb434057c3de2b2l }, + 0 }, + /* 23 << 200 */ + { { 0x48e0295dcc9e79bfl,0x2419485693eb403dl,0x9386fb7709dd8194l, + 0xb6e89bb101a242f6l }, + { 0xc7994f3924d308d7l,0xf0fbc392de673d88l,0x43eed52ea11abb62l, + 0xc900f9d0c83e7fbel }, + 0 }, + /* 25 << 200 */ + { { 0x214a10dca8152891l,0xe6787b4c64f1abb2l,0x276333d9fa1a10edl, + 0xc0e1c88e47dbccbcl }, + { 0x8a3c37c4849dd12el,0x2144a8c8d86e109fl,0xbb6891f7286c140cl, + 0xb0b8c5e29cce5e6fl }, + 0 }, + /* 27 << 200 */ + { { 0x3f9e0e3499753288l,0x6b26f1ebe559d93al,0x647fe21d9841faf1l, + 0x48a4b6efa786ea02l }, + { 0x6e09cd22665a882dl,0x95390d81b63ccda6l,0x5b014db4b026a44al, + 0x5b96efb22ad30ff1l }, + 0 }, + /* 28 << 200 */ + { { 0x64c50c8b4a3b99e9l,0x2489a675d0a26f4fl,0xe2aacaeed85bc6fdl, + 0x556882038a6019bal }, + { 0x7ceb9da645cfac07l,0xe1ad3d25652dbd09l,0x086adf348d3b5d2bl, + 0xf9256d8aec3654a0l }, + 0 }, + /* 29 << 200 */ + { { 0x571c246bf009a690l,0x8fe54231ccd90d3al,0x8adde6adfe173b79l, + 0x75d9a392b05a5e3bl }, + { 0x607f47b0d1bb3a84l,0xe4e3b472058e691al,0xfc0f793bf3d956e3l, + 0x6a6730b605de54dal }, + 0 }, + /* 31 << 200 */ + { { 0x4daf7f540d80aaa1l,0xc571d04c229c4574l,0x469e2da5fffca53dl, + 0x9fffe29513ff7f59l }, + { 0x2075da5a33a254f7l,0x769f33acd35e575dl,0x7b940d2c3d35001al, + 0x2d606b57e34c95b7l }, + 0 }, + /* 33 << 200 */ + { { 0xc7e4f8b899365f86l,0x8f6f959faae69527l,0x749ffedffdfaeeeal, + 0x2b91f0221b54c2a0l }, + { 0xe75c2352addbdf83l,0xe7329922fff2694cl,0xbb65ae06badadeacl, + 0x16cbb9d1f56be3b5l }, + 0 }, + /* 34 << 200 */ + { { 0xb100a4c67a07bd70l,0x222fee7634787efel,0xa4dafc14f1e79d1bl, + 0x0d3a82dad18b8be4l }, + { 0xe0181445fc06922fl,0x0873d99b714a90b6l,0xdf43082fa5087a0el, + 0x195e49367399e0dbl }, + 0 }, + /* 35 << 200 */ + { { 0x7e83545aae6fcc9cl,0x1a24fce819e15ce2l,0x4a3465c536d8c6a8l, + 0xd1e5f24109436ae0l }, + { 0xed334bfc6be463d5l,0xc46a600b934fbdcfl,0xbd2fd65b920321ffl, + 0x953fa91767fa154el }, + 0 }, + /* 36 << 200 */ + { { 0x5dca4995f93ddad1l,0x061efcabf72470c2l,0xad78d54d5e7e0741l, + 0xa91f4e839c4e0ab4l }, + { 0xdd4403af5c75aa0dl,0x4308c8ee13c69113l,0x3a3b66f51ebc36adl, + 0xc07cc3f0f4bf777al }, + 0 }, + /* 37 << 200 */ + { { 0x3fd1963e37a86b32l,0x22e236d60bd0880el,0xb87467cf89f0fa5cl, + 0x85b9c6c0310e0265l }, + { 0x82979a96783459ael,0xd19b0919bd529ed3l,0xa21f771808434f94l, + 0x3dd130a9195369c6l }, + 0 }, + /* 39 << 200 */ + { { 0xc61e62767915d157l,0xc48244279e07fb0el,0x8980c1cc8420ea49l, + 0x10d82e4a588d4e2bl }, + { 0xdddecd52b17eff2dl,0xe44c7b2ded8492a4l,0x96ca89ebb9bea6afl, + 0x724166fe1b03ed03l }, + 0 }, + /* 40 << 200 */ + { { 0xfc87975f8fb54738l,0x3516078827c3ead3l,0x834116d2b74a085al, + 0x53c99a73a62fe996l }, + { 0x87585be05b81c51bl,0x925bafa8be0852b7l,0x76a4fafda84d19a7l, + 0x39a45982585206d4l }, + 0 }, + /* 41 << 200 */ + { { 0x8bbc484ed551f3e1l,0x6e058a90b7eb06d2l,0xfaccd9a0e5cd281al, + 0xe7661b78d5b44900l }, + { 0x03afe115725fde22l,0xbe929230c7229fd1l,0x5cd0d16a0000035el, + 0x1f6a9df0c8f5a910l }, + 0 }, + /* 43 << 200 */ + { { 0xe54bbcfd535dfc82l,0x89be0b89a9012196l,0xa67831ee71011beal, + 0x2ea7a8292db43878l }, + { 0xff7c144378ffe871l,0xa67dc3d4c63f65eal,0xbbfc7fc2a1527419l, + 0x6440380bf6c36b8fl }, + 0 }, + /* 44 << 200 */ + { { 0x71ab9f69d812d7e6l,0x2847c5516e142126l,0x9e27755bb31e7753l, + 0xb89533e2943b8c7fl }, + { 0xbe7f0c6e14fa7dc6l,0x782a06388cee1f7al,0x7069292938e13a6bl, + 0x1e1221f0c63f4d28l }, + 0 }, + /* 45 << 200 */ + { { 0x9030aa9a63a431f4l,0x0fa7b5d45039a318l,0x6a0cf40af083687dl, + 0x46689cec659fa752l }, + { 0x8259727a456fa97el,0x4f618a355b08d7fcl,0x2c44217b72028d15l, + 0x8083b09935111e32l }, + 0 }, + /* 46 << 200 */ + { { 0xaa5976523b5b29f1l,0xb07f10ab37432a54l,0x16e3e2236e36556fl, + 0xf1c7c9bd47cd4586l }, + { 0xa4eef99d3f87216dl,0x4e54d3c52e1eaa79l,0x534c5901d2540d91l, + 0x718df7c9b6f0fcfcl }, + 0 }, + /* 47 << 200 */ + { { 0x99497f8a2eb0ee3bl,0x87e550c1caeb3a20l,0xd23e053dfb91627cl, + 0xb971c043873124e6l }, + { 0x3581ab853b16e467l,0x24541c926145187bl,0x4423ec5c010c2527l, + 0x775f13029fa82a68l }, + 0 }, + /* 48 << 200 */ + { { 0x499b6ab65eb03c0el,0xf19b795472bc3fdel,0xa86b5b9c6e3a80d2l, + 0xe43775086d42819fl }, + { 0xc1663650bb3ee8a3l,0x75eb14fcb132075fl,0xa8ccc9067ad834f6l, + 0xea6a2474e6e92ffdl }, + 0 }, + /* 49 << 200 */ + { { 0xbaebdd8a0c40aec4l,0x5eccafb563e8cfd0l,0x1c204c0eb5159938l, + 0x607109d34b996aa9l }, + { 0x024c6c4b9cef59fel,0xbc846e216ed4b6f1l,0xf6a50ff3ff652c0al, + 0x368af2c72d95220cl }, + 0 }, + /* 51 << 200 */ + { { 0xec9c2e35cbd3ccafl,0xb9eeff3ddcda8f30l,0x82012e191062d02el, + 0xed964cc94efc6b6el }, + { 0x8853ea0a6bf54c22l,0xea40fcc0f3cbe264l,0x21f9c01ddecf114el, + 0x05e754c63da71e59l }, + 0 }, + /* 52 << 200 */ + { { 0xe6a26d38046dfc72l,0x70409579c2175175l,0x2a575ac5d44e0c1dl, + 0xb35395e01479ab5al }, + { 0x1550a5d4f7bfbd8el,0x01daeb680778807bl,0xe0aa940321294dbal, + 0x84bcdc8c5b5a93b7l }, + 0 }, + /* 53 << 200 */ + { { 0x876cc4d2520f04abl,0x6e320f5da85ff6a8l,0x7c504720ce17bc80l, + 0xe7907079a62089f9l }, + { 0xa45c4ac7bca45feel,0xd8f3facd5bd54b0cl,0xc0b036277b3e4a24l, + 0xaabe96dfe4cd4b57l }, + 0 }, + /* 55 << 200 */ + { { 0xdc85a54773862ce4l,0x169051a3cc6f5d85l,0x8e3d3be0355f4df7l, + 0xa139d6fac72bac76l }, + { 0xddc95d0dfeb0a6f0l,0xd53f70e545cd6955l,0x18eede5e47e54112l, + 0x4a135dc9cbc6a52el }, + 0 }, + /* 57 << 200 */ + { { 0x705a08ba90a58fb4l,0x10eef880fb3f8a64l,0x4ced9ba2f8e585ffl, + 0xb4f0f955fc6ebef5l }, + { 0x152c1a338d8b739el,0xb2be701db495bee5l,0xd27141a8d3540a74l, + 0x20c8a00247f9e9d7l }, + 0 }, + /* 59 << 200 */ + { { 0x6d5ae921f5adcb3fl,0xaed1047003a3b610l,0x7c75e36f22256df9l, + 0xe664b36fb97dae99l }, + { 0x138b5eca91e746ael,0xb3e01ef5648674a7l,0xa3f256da9e375c74l, + 0xa00e82bc6a82d6f3l }, + 0 }, + /* 60 << 200 */ + { { 0xe7a01eae6e28b4a8l,0xb3bf8224782166c9l,0x0b7ba2a06a244510l, + 0x9751a69c2abbb4dbl }, + { 0xb611adc1b3f9fcbcl,0x1d08eb3b436c4675l,0x1c71e98a20f96a64l, + 0x33d9b58c7ffd3f08l }, + 0 }, + /* 61 << 200 */ + { { 0x7c7b03c1affa2d6cl,0x5f189bb9aec6e624l,0xe77a1eedadeff5e7l, + 0xfc58b90f4280b467l }, + { 0x561e5d579b71cb4el,0x8ed767aa36d6a17el,0x38d8671e8aa9e188l, + 0x7bc68f07a95350c0l }, + 0 }, + /* 63 << 200 */ + { { 0xe0cd38cf98c01384l,0xc6741123a4226d9fl,0xdd1d42dbf877a0b8l, + 0xc5986ef0110b3cbal }, + { 0xeba949f809c8cebel,0x96b47bc4bd39f1dcl,0xbad140b6e07a2a3cl, + 0x2a8d80999ac5ca8al }, + 0 }, + /* 64 << 200 */ + { { 0x39d934abd3c095f1l,0x04b261bee4b76d71l,0x1d2e6970e73e6984l, + 0x879fb23b5e5fcb11l }, + { 0x11506c72dfd75490l,0x3a97d08561bcf1c1l,0x43201d82bf5e7007l, + 0x7f0ac52f798232a7l }, + 0 }, + /* 65 << 200 */ + { { 0x8cf27618590ca850l,0x58134f6f44bb94f2l,0x0a147562b78b4eecl, + 0x2e5986e39f1ed647l }, + { 0x9becf893348393b0l,0xaea21b92c31c2a86l,0x3d69859e5ff1b9a6l, + 0x6fcd19f4cd805691l }, + 0 }, + /* 71 << 200 */ + { { 0x81619bd4841f43c3l,0x3a3325538e5c61f0l,0x2b68921eda862151l, + 0x97f5c8a741a491f8l }, + { 0x8b452094d3b9afa0l,0x93b2b7b4f2124dbcl,0x53285e7d26e0e26dl, + 0x3f003fc5c8a24edel }, + 0 }, + /* 77 << 200 */ + { { 0x4cdabb586c025824l,0x5935ad1586bfcd7dl,0x8ce2c3101b7c5533l, + 0x761c9fe96cae8808l }, + { 0x8a0723f5d9e66d70l,0xb640b323dcced11dl,0x5768528051ae548cl, + 0x83576f75d53f3f2cl }, + 0 }, + /* 83 << 200 */ + { { 0xc715edc47b532ec3l,0x159765e6c4a6e14bl,0x4a74f15228cd2d45l, + 0xbfd309edae8c753bl }, + { 0xf56bb5315d6d5245l,0x2c89c21833b30a55l,0xe436141acd4ed5fal, + 0x7eb7a5c707868ee6l }, + 0 }, + /* 89 << 200 */ + { { 0x9a3ad3ffb0c7c48cl,0x25e8d977738e3638l,0xbb6c6c9d1c024074l, + 0xeda1ac0f8cfdf416l }, + { 0x93059ba538de49e2l,0xdb199cfc1b9ce741l,0x49b05e9446f3b494l, + 0x717cafc606480902l }, + 0 }, + /* 95 << 200 */ + { { 0x8d27421052885708l,0x9d2297fd74e5b9b5l,0xe7cb6a68dc4d7318l, + 0x0b60b0d276357b31l }, + { 0x57301994532c2095l,0xfbae2ba203373452l,0xe8020b20ba700583l, + 0x1ca7772c2988919cl }, + 0 }, + /* 101 << 200 */ + { { 0x723296eb918f3eecl,0x358c9ff0b79901c6l,0x64a1934c8d5e814cl, + 0x7e5a9afced165177l }, + { 0xd783840168733e7al,0xfcf3c0b6f61ede6dl,0x94ec0bf08434e804l, + 0xa5a70153c192c1cdl }, + 0 }, + /* 107 << 200 */ + { { 0x03cdf976c23e49d4l,0x51e5cfa5a2ae72d5l,0x7716faa3100f7a51l, + 0xc53153a2c14dc015l }, + { 0xe7c69b052b47ec18l,0xff4756907ea93b01l,0x55fde3c540a2f205l, + 0x0263d0b12f85aed6l }, + 0 }, + /* 113 << 200 */ + { { 0x668c56619686fe30l,0x382a8ccd8f73a476l,0xda012cbfb40a85e7l, + 0x55ea1e72e9e88b91l }, + { 0x8312556088cc5afcl,0x44ae54cbc45b19c7l,0xc91fffa8f86a02cdl, + 0xc79f573752d7e89bl }, + 0 }, + /* 116 << 200 */ + { { 0x652b50523e357579l,0x08ce7d3a2afe5746l,0x9dc1cca6f71a12efl, + 0x80a221c24f6c4196l }, + { 0xdde40eff0f49f508l,0x7995bb46913b0dc3l,0x4adbdeb385e44f6el, + 0x6816bb3ab222e4bbl }, + 0 }, + /* 119 << 200 */ + { { 0xce1ee518579a1a4dl,0x5d86e8912bc3870al,0x230878d18da907c4l, + 0xc648392777ae7ea8l }, + { 0x64319653016c0ad7l,0x7cbfa0b0b71f20dal,0xbf087dc3395ed4d8l, + 0x59512add307d218dl }, + 0 }, + /* 125 << 200 */ + { { 0x7378a969d8ae335el,0x11c69965506d3a42l,0x212539769949468al, + 0x570cf87e64995050l }, + { 0xf300ad2e30b94e22l,0xbc159cf8f36dad32l,0xdff3b3767ca8aa6al, + 0xa5de93b5627fb9e7l }, + 0 }, + }, + { + /* 0 << 208 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 208 */ + { { 0x75d9bc15adf7cccfl,0x81a3e5d6dfa1e1b0l,0x8c39e444249bc17el, + 0xf37dccb28ea7fd43l }, + { 0xda654873907fba12l,0x35daa6da4a372904l,0x0564cfc66283a6c5l, + 0xd09fa4f64a9395bfl }, + 0 }, + /* 3 << 208 */ + { { 0xc51aa29e5cfe5c48l,0x82c020ae815ee096l,0x7848ad827549a68al, + 0x7933d48960471355l }, + { 0x04998d2e67c51e57l,0x0f64020ad9944afcl,0x7a299fe1a7fadac6l, + 0x40c73ff45aefe92cl }, + 0 }, + /* 4 << 208 */ + { { 0xe5f649be9d8e68fdl,0xdb0f05331b044320l,0xf6fde9b3e0c33398l, + 0x92f4209b66c8cfael }, + { 0xe9d1afcc1a739d4bl,0x09aea75fa28ab8del,0x14375fb5eac6f1d0l, + 0x6420b560708f7aa5l }, + 0 }, + /* 5 << 208 */ + { { 0xbf44ffc75488771al,0xcb76e3f17f2f2191l,0x4197bde394f86a42l, + 0x45c25bb970641d9al }, + { 0xd8a29e31f88ce6dcl,0xbe2becfd4bb7ac7dl,0x13094214b5670cc7l, + 0xe90a8fd560af8433l }, + 0 }, + /* 7 << 208 */ + { { 0x0ecf9b8b4ebd3f02l,0xa47acd9d86b770eal,0x93b84a6a2da213cel, + 0xd760871b53e7c8cfl }, + { 0x7a5f58e536e530d7l,0x7abc52a51912ad51l,0x7ad43db02ea0252al, + 0x498b00ecc176b742l }, + 0 }, + /* 9 << 208 */ + { { 0x9ff713ef888ae17fl,0x6007f68fb34b7bebl,0x5d2b18983b653d64l, + 0xcbf73e91d3ca4b1bl }, + { 0x4b050ad56cdfb3a1l,0x41bd3ec3d1f833a4l,0x78d7e2ee719d7bf5l, + 0xea4604672a27412el }, + 0 }, + /* 10 << 208 */ + { { 0x7dad6d1b42cd7900l,0xb6e6b439e058f8a4l,0x8836f1e662aa3bbcl, + 0xd45bf2c811142b0al }, + { 0xae324bac3c045ed1l,0x372be24d270a8333l,0xeeda7a3a6b7c73b6l, + 0xf6675402db49562al }, + 0 }, + /* 11 << 208 */ + { { 0xc312ba68441e760dl,0x84d0d061a50e512el,0xfe764f4e4bbdd849l, + 0xa924adcf9dadd5c0l }, + { 0x08685961debfe976l,0xd3d846c529fba601l,0x43bf8227dc3f4040l, + 0x05e767b8a49e9ff5l }, + 0 }, + /* 13 << 208 */ + { { 0xc4689c309953e453l,0x5e355a2e1712dca5l,0x1ff83c81f1cd96f7l, + 0xb06b89fb44cf56dbl }, + { 0x1827705365f16e0dl,0x6403b91de5618672l,0xba3f9475be384bc6l, + 0x7f691cbe303ce5f3l }, + 0 }, + /* 15 << 208 */ + { { 0x4589ba03210f4045l,0xd5e7366301e8012al,0x1c26052d74462ffal, + 0xe78f600c4f989519l }, + { 0xc63ca0c97cee0b2fl,0xbe588573af760b5fl,0x05906fc4593773cdl, + 0xd5970fb0e322d5afl }, + 0 }, + /* 16 << 208 */ + { { 0x103c46e60ebcf726l,0x4482b8316231470el,0x6f6dfaca487c2109l, + 0x2e0ace9762e666efl }, + { 0x3246a9d31f8d1f42l,0x1b1e83f1574944d2l,0x13dfa63aa57f334bl, + 0x0cf8daed9f025d81l }, + 0 }, + /* 17 << 208 */ + { { 0xf67c098aae0690aal,0x1a4656422b7bc62bl,0xaffc6b917220dea2l, + 0xd97ac543d2552deel }, + { 0x1f84514a7e816b8el,0xe9887e81a8f38552l,0x2e6358e6847ad46bl, + 0x1f67871e6bc9895el }, + 0 }, + /* 19 << 208 */ + { { 0x2462b6e0d47f43fal,0x71db3610d8a245e5l,0x0c26b0e734208974l, + 0x0cd6d49d2029bd2el }, + { 0xf207c9f6091922b8l,0x0c476c5c7f0fbf66l,0x6de7efb2295d6da8l, + 0xea054ee10ced6cfel }, + 0 }, + /* 21 << 208 */ + { { 0xd21496e3e9bd795cl,0xf293f617c6a557del,0x9d041b7239a45642l, + 0xe8353dab4ac87f80l }, + { 0x21e9f35620d8d019l,0x1f4adca9d2fb2668l,0xe5f68227dfecd64al, + 0x10d71b79d7f09ec0l }, + 0 }, + /* 23 << 208 */ + { { 0xca3f068999f87118l,0x99a933911b2417f0l,0xa383481a3d1f70e5l, + 0x7a31a6c833b14414l }, + { 0x9d60f4368b2a9931l,0xd4c97ded80588534l,0x7cb29e82ab6a8bdal, + 0x3799bdad97b4c45al }, + 0 }, + /* 25 << 208 */ + { { 0x51da0ff629011af3l,0xcbb03c809a4f0855l,0xea3536725555b10bl, + 0x4bf94e025c7da97el }, + { 0x384352f5ff713300l,0xb2c2b675192d41e6l,0x4ff66861625ca046l, + 0xf0f5e472013dddc4l }, + 0 }, + /* 27 << 208 */ + { { 0x38c44cdc59987914l,0xad7f2829757fb853l,0x9aabf1c8688e3342l, + 0xbe0f1e4ef534c850l }, + { 0x732cac652ec24ecal,0x9328b657933bb5e4l,0xe2747ff60bb31033l, + 0xdbaab72cfcdc36acl }, + 0 }, + /* 28 << 208 */ + { { 0x0e5e3049a639fc6bl,0xe75c35d986003625l,0x0cf35bd85dcc1646l, + 0x8bcaced26c26273al }, + { 0xe22ecf1db5536742l,0x013dd8971a9e068bl,0x17f411cb8a7909c5l, + 0x5757ac98861dd506l }, + 0 }, + /* 29 << 208 */ + { { 0xaf410d5aac66a3e8l,0x39fcbffb2031f658l,0xd29e58c947ce11fbl, + 0x7f0b874965f73e49l }, + { 0xedc30f4b27fea6c6l,0xe03b9103d2baa340l,0xa7bb3f17ae680612l, + 0xe06656a8197af6f0l }, + 0 }, + /* 31 << 208 */ + { { 0x84562095bff86165l,0x994194e916bc7589l,0xb1320c7ec14c6710l, + 0x508a8d7f766e978fl }, + { 0xd04adc9ec7e1f6fel,0x7bafaff68398cecfl,0x906df2fccef3b934l, + 0xc65afe18f3008c38l }, + 0 }, + /* 33 << 208 */ + { { 0x477ffeeeab983130l,0x5426363a96e83d55l,0xcf0370a15204af42l, + 0x99834414b5a6ea8fl }, + { 0xf475ba711ab4ee8al,0x8486da5d0102d8f2l,0x55082e713839c821l, + 0xa57e58395b65defal }, + 0 }, + /* 34 << 208 */ + { { 0x34b2185bbbb33a76l,0x189038b7d48158c2l,0xfa32eb90e9e90217l, + 0x79271771730e74dfl }, + { 0x315ed8c2a5d01ffdl,0x9799dae723e6a95el,0x40070aa016f5715al, + 0x40e6c0ca5ea51f8cl }, + 0 }, + /* 35 << 208 */ + { { 0x099c0570d8132163l,0xcd5508a3023dbbf3l,0x18162ff526bfe6a6l, + 0xf39e071144bbb455l }, + { 0x49664996eaa3cf96l,0x1c6442d5e2649be9l,0x6199f740c01d269dl, + 0x4be605ee37542c11l }, + 0 }, + /* 36 << 208 */ + { { 0xc7313e9cf36658f0l,0xc433ef1c71f8057el,0x853262461b6a835al, + 0xc8f053987c86394cl }, + { 0xff398cdfe983c4a1l,0xbf5e816203b7b931l,0x93193c46b7b9045bl, + 0x1e4ebf5da4a6e46bl }, + 0 }, + /* 37 << 208 */ + { { 0xd032fbfd0dbf82b4l,0x707181f668e58969l,0xef434381e7be2d5el, + 0x290669176f2c64ddl }, + { 0xf66cffc3772769abl,0x68d8a76a17aad01cl,0xdd3991c590f6e078l, + 0xdb74db06ea4ac7dcl }, + 0 }, + /* 39 << 208 */ + { { 0x9f34a7c11c78be71l,0x7bf2f2d149ca6987l,0xb528a514dcd34afcl, + 0x4dddb3f1183a68b1l }, + { 0x54d2626660b83883l,0x9073e4e0e0cd8dadl,0xbd2b837d9eb818b2l, + 0x5fa5f9086ae2e32dl }, + 0 }, + /* 40 << 208 */ + { { 0xf9942a6043a24fe7l,0x29c1191effb3492bl,0x9f662449902fde05l, + 0xc792a7ac6713c32dl }, + { 0x2fd88ad8b737982cl,0x7e3a0319a21e60e3l,0x09b0de447383591al, + 0x6df141ee8310a456l }, + 0 }, + /* 41 << 208 */ + { { 0xcd02ba1e0df98a64l,0x301b6bfa03f5676el,0x41e1a8d4a2fe4090l, + 0x489c1cbf47f0e1dcl }, + { 0x4171a98c20760847l,0xdcb21cee77af4796l,0x5fb0f0c9d0b7e981l, + 0x4c2791dff33b9f8dl }, + 0 }, + /* 43 << 208 */ + { { 0x95d7ec0c50420a50l,0x5794665c2a6756d5l,0x73558c6e9101e7f5l, + 0xa3fa0f8c1642af0el }, + { 0xa11b309b4ee43551l,0x3939de30cb8fc712l,0x9710f2320fde8921l, + 0x2a4db2d5cae8b41cl }, + 0 }, + /* 44 << 208 */ + { { 0xaec1a039e6d6f471l,0x14b2ba0f1198d12el,0xebc1a1603aeee5acl, + 0x401f4836e0b964cel }, + { 0x2ee437964fd03f66l,0x3fdb4e49dd8f3f12l,0x6ef267f629380f18l, + 0x3e8e96708da64d16l }, + 0 }, + /* 45 << 208 */ + { { 0xdf6cdac0bc4c78adl,0xbe9e32182e97376el,0xa37f9d8b1a139274l, + 0x7640c3982807128el }, + { 0xe9735166c05b5f85l,0xbccd3675100e5716l,0x51376a293e5c9682l, + 0x95efe088848f6aeal }, + 0 }, + /* 46 << 208 */ + { { 0xfac2d7dd23d14105l,0xdda17149a9136f52l,0xb9f3a9c672d1a99bl, + 0x2fcf532a142c3b20l }, + { 0xc2731f1e61190c1bl,0x26dbe810a76509e4l,0xc96cc431908bb92fl, + 0x5661a84d80e3e694l }, + 0 }, + /* 47 << 208 */ + { { 0x5194d144150ba121l,0x8de57c48b6b11561l,0x803228da96c156d9l, + 0x2112e4250a8f6376l }, + { 0x15436294643449ffl,0xfc3880add4118cd0l,0x16ed90731e3f7413l, + 0xa400699901d38d6dl }, + 0 }, + /* 48 << 208 */ + { { 0xbc19180c207674f1l,0x112e09a733ae8fdbl,0x996675546aaeb71el, + 0x79432af1e101b1c7l }, + { 0xd5eb558fde2ddec6l,0x81392d1f5357753fl,0xa7a76b973ae1158al, + 0x416fbbff4a899991l }, + 0 }, + /* 49 << 208 */ + { { 0xf84c9147c52d7384l,0x86391accec01efa6l,0xffd68616f9c6f3f4l, + 0xc7536461b17c2de6l }, + { 0xa81f4ba10121abdfl,0xa068a2e26f6eae27l,0xe0ee90350eb159f0l, + 0x4c48f761fd8c4b9cl }, + 0 }, + /* 51 << 208 */ + { { 0x4b6d71e87790000cl,0xced195744ce9293el,0xc25626a3747585e8l, + 0xb8307d22d7044270l }, + { 0xf08e7ef6117c24cbl,0xae6403162f660d04l,0xbc3ffdcff224a2fdl, + 0x1ebc0328d0586c7el }, + 0 }, + /* 52 << 208 */ + { { 0x9e65fdfd0d4a9dcfl,0x7bc29e48944ddf12l,0xbc1a92d93c856866l, + 0x273c69056e98dfe2l }, + { 0x69fce418cdfaa6b8l,0x606bd8235061c69fl,0x42d495a06af75e27l, + 0x8ed3d5056d873a1fl }, + 0 }, + /* 53 << 208 */ + { { 0x46b160e5a6022278l,0x86b1d50cc30a51fcl,0xe898ac0e684b81b7l, + 0x04d591e277b93597l }, + { 0xd20cac347626e18al,0xb49c941f0a968733l,0x054e6e7e21631627l, + 0xd6d33db9d4c716b1l }, + 0 }, + /* 55 << 208 */ + { { 0xaa79ab4bf91e9b75l,0x7df3235bd34d961dl,0x9f3954e6534a40e1l, + 0x80f88d2c790b4456l }, + { 0x98f7711b21e9fb2al,0x0a04c318877d27e6l,0x499b7c2412338848l, + 0x0b1dbe9ccd5e7ec3l }, + 0 }, + /* 57 << 208 */ + { { 0xb430ff44e04715ffl,0x671358d565d076d0l,0x3946d38f22c3aa06l, + 0x80919ea363b2d627l }, + { 0x14ffa219e8790922l,0xfe1d895ae8d89c48l,0x717e9e51748e806el, + 0xb91e1ddf550d711dl }, + 0 }, + /* 59 << 208 */ + { { 0x8aac26225f540127l,0x57cd5d7cba25f742l,0x87006a6b1df7a0fcl, + 0x88e9ab863ecbf26cl }, + { 0xe1b8155f9143b314l,0xc00196130b679bddl,0x819e7b61a1871d07l, + 0xc36e7892cc2c9cc9l }, + 0 }, + /* 60 << 208 */ + { { 0x4b03c55b8e33787fl,0xef42f975a6384673l,0xff7304f75051b9f0l, + 0x18aca1dc741c87c2l }, + { 0x56f120a72d4bfe80l,0xfd823b3d053e732cl,0x11bccfe47537ca16l, + 0xdf6c9c741b5a996bl }, + 0 }, + /* 61 << 208 */ + { { 0x65729b05301ee370l,0x3ed09a2a24c2824cl,0x781ef66a33481977l, + 0xf2ccdeec193506d0l }, + { 0x92b4f70d703422d6l,0x7f004a43f80a1b99l,0x47db23607a856445l, + 0x783a8dd1ce5b0622l }, + 0 }, + /* 63 << 208 */ + { { 0x7febefd34e9aac5al,0x601c89e2bdd6173el,0x79b08930c257431el, + 0x915d601d399ee099l }, + { 0xfa48347eca02acd2l,0xc33249baeeb7ccedl,0xd76e408755704722l, + 0xd3709c600dcf4878l }, + 0 }, + /* 64 << 208 */ + { { 0xee7332c7904fc3fal,0x14a23f45c7e3636al,0xc38659c3f091d9aal, + 0x4a995e5db12d8540l }, + { 0x20a53becf3a5598al,0x56534b17b1eaa995l,0x9ed3dca4bf04e03cl, + 0x716c563ad8d56268l }, + 0 }, + /* 65 << 208 */ + { { 0x963353201580f3adl,0x6c495304b0cd50d4l,0xd035cdc7555ff981l, + 0xe65cd063c6b6bdfbl }, + { 0x7deb3cbb437e749cl,0xa9de9f3db5dc24a1l,0xe2e76a2b35c29ffal, + 0x4d35e261323ba650l }, + 0 }, + /* 71 << 208 */ + { { 0x52c46fc8c89e2766l,0x7330b02bb945e5f2l,0xc77ef75c2673ebbcl, + 0x1740e72657c33783l }, + { 0xf0312d29623565fbl,0xff9f707af0ca1ed9l,0xb98609ca5ea51a4al, + 0xde86b9a87b5cc91fl }, + 0 }, + /* 77 << 208 */ + { { 0x0dece4badca158b7l,0x5e39baf6a3e9f837l,0xcf14e6dc4d57b640l, + 0x0548aaa4b67bcbe7l }, + { 0xb6cf5b393c90e434l,0xf8b3c5645006f3abl,0xa74e92859bf04bd9l, + 0xf59a3a6bf99c8977l }, + 0 }, + /* 83 << 208 */ + { { 0x652ca66ac5b072d5l,0x2102b55993ad4928l,0x1b5f192d88210f9bl, + 0xb18710144c6ad7e5l }, + { 0x3979fde3bc0abf13l,0xb5cb4c7dac3fd631l,0x4aedffa6c200ec7bl, + 0x8aed81ceaddf3610l }, + 0 }, + /* 89 << 208 */ + { { 0x72b48105abeefbael,0x0e9e6e41827bb22bl,0xf45ada151e52a848l, + 0xb8e94579534867a2l }, + { 0x3a08773b7adb0fdcl,0xe7133a28b83316dfl,0xc8b7b08c5bb41470l, + 0x28719eb4aaf140c7l }, + 0 }, + /* 95 << 208 */ + { { 0x398996cd430007cel,0x20d8c0e07642d616l,0x81566639a7eb2397l, + 0x74aa0b692e133732l }, + { 0x326745907ba80aa7l,0x56a491c39bd69d64l,0xc8c8b040e54dcce0l, + 0x3f991872d571d037l }, + 0 }, + /* 101 << 208 */ + { { 0x70e681fa4fb595c9l,0xf0635d6386b4d97bl,0xfc029284c1347081l, + 0x5a4e9cbe4fee0303l }, + { 0xd43da8609c31094fl,0x0412cfed6515b4aal,0x10fc06da8d53be86l, + 0x4b7b380b4bccc94dl }, + 0 }, + /* 107 << 208 */ + { { 0x560d57408e7d6738l,0xa82268a8937f12a2l,0x87787b2d3d95b463l, + 0xb36539b2030e23bfl }, + { 0x60d16b8fd61e761dl,0x96ba2949fe8efccdl,0x8c170eda667fa7ebl, + 0xc880d74cf800d7c3l }, + 0 }, + /* 113 << 208 */ + { { 0x7c05d6c1efcbfea0l,0xae7ba3291a2f6dd8l,0x521598ed5bd42ecfl, + 0x58e07842ef0ab40cl }, + { 0xae65105f66c752a5l,0x4910fba45f99d499l,0xbfdaf5fce9e44357l, + 0x6aaf4053796ee5b6l }, + 0 }, + /* 116 << 208 */ + { { 0xf58fecb16f640f62l,0xe274b92b39f51946l,0x7f4dfc046288af44l, + 0x0a91f32aeac329e5l }, + { 0x43ad274bd6aaba31l,0x719a16400f6884f9l,0x685d29f6daf91e20l, + 0x5ec1cc3327e49d52l }, + 0 }, + /* 119 << 208 */ + { { 0x615ac02527ba93edl,0x0d43915d3556ef47l,0x8c739fd1cb0cda89l, + 0xa2318169625f7a16l }, + { 0x17d486113e0479cel,0x814beb6038ee541el,0x09c9807fb98ef355l, + 0x4ad3668752d07af6l }, + 0 }, + /* 125 << 208 */ + { { 0x5c1f42e444f3f568l,0xd743b7c078fb409bl,0xe09edccb6224362cl, + 0x7f13d140c5fe872cl }, + { 0x85e8cb88f403c0ebl,0x918a231b688d20a0l,0xc65b7ab9f246c73fl, + 0xda743fbf76dbd6adl }, + 0 }, + }, + { + /* 0 << 216 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 216 */ + { { 0xa0158eeae457a477l,0xd19857dbee6ddc05l,0xb326522418c41671l, + 0x3ffdfc7e3c2c0d58l }, + { 0x3a3a525426ee7cdal,0x341b0869df02c3a8l,0xa023bf42723bbfc8l, + 0x3d15002a14452691l }, + 0 }, + /* 3 << 216 */ + { { 0xf3cae7e9262a3539l,0x78a49d1d6670d59el,0x37de0f63c1c5e1b9l, + 0x3072c30c69cb7c1cl }, + { 0x1d278a5277c850e6l,0x84f15f8f1f6a3de6l,0x46a8bb45592ca7adl, + 0x1912e3eee4d424b8l }, + 0 }, + /* 4 << 216 */ + { { 0x6ba7a92079e5fb67l,0xe1331feb70aa725el,0x5080ccf57df5d837l, + 0xe4cae01d7ff72e21l }, + { 0xd9243ee60412a77dl,0x06ff7cacdf449025l,0xbe75f7cd23ef5a31l, + 0xbc9578220ddef7a8l }, + 0 }, + /* 5 << 216 */ + { { 0xdc988086365e668bl,0xada8dcdaaabda5fbl,0xbc146b4c255f1fbel, + 0x9cfcde29cf34cfc3l }, + { 0xacbb453e7e85d1e4l,0x9ca09679f92358b5l,0x15fc2d96240823ffl, + 0x8d65adf70c11d11el }, + 0 }, + /* 7 << 216 */ + { { 0x775557f10296f4fdl,0x1dca76a3ea51b436l,0xf3e98f60fb950805l, + 0x31ff32ea831cf7f1l }, + { 0x643e7bf18d2c714bl,0x64b5c3392e9d2acal,0xa9fd9ccc6adc2d23l, + 0xfc2397eccc721b9bl }, + 0 }, + /* 9 << 216 */ + { { 0xf031182db48ec57dl,0x515d32f804b233b9l,0x06bbb1d4093aad26l, + 0x88a142fe0d83d1ecl }, + { 0x3b95c099245c73f8l,0xb126d4af52edcd32l,0xf8022c1e8fcb52e6l, + 0x5a51ac4c0106d339l }, + 0 }, + /* 10 << 216 */ + { { 0xc589e1ce44ace150l,0xe0f8d3d94381e97cl,0x59e99b1162c5a4b8l, + 0x90d262f7fd0ec9f9l }, + { 0xfbc854c9283e13c9l,0x2d04fde7aedc7085l,0x057d776547dcbecbl, + 0x8dbdf5919a76fa5fl }, + 0 }, + /* 11 << 216 */ + { { 0xb7f70a1a7c64a054l,0x0dc1c0df9db43e79l,0x6d0a4ae251fe63d6l, + 0xe0d5e3327f0c8abfl }, + { 0xff5500362b7ecee8l,0x3ea0e6f75d055008l,0x30deb62ff24ac84fl, + 0x936969fd5d7116b7l }, + 0 }, + /* 13 << 216 */ + { { 0x02da76122617cf7fl,0xd6e25d4eeee35260l,0xb2fa5b0afd3533e9l, + 0xe76bb7b0b9126f88l }, + { 0x692e6a9988856866l,0x3fdf394f49db65cal,0x2529699122d8d606l, + 0xe815bfbf3dd7c4cfl }, + 0 }, + /* 15 << 216 */ + { { 0x69c984ed4d844e7fl,0xd354b2174a2e8a82l,0x25bd4addfb2c4136l, + 0xf72df4de144b26e1l }, + { 0xd0aa9db0e6101afdl,0x4445efaae49bd1b8l,0x5dc54eee331593b2l, + 0xfa35e3b9094bf10bl }, + 0 }, + /* 16 << 216 */ + { { 0xdb567d6ac42bd6d2l,0x6df86468bb1f96ael,0x0efe5b1a4843b28el, + 0x961bbb056379b240l }, + { 0xb6caf5f070a6a26bl,0x70686c0d328e6e39l,0x80da06cf895fc8d3l, + 0x804d8810b363fdc9l }, + 0 }, + /* 17 << 216 */ + { { 0x660a0f893ea089c3l,0xa25823aac9009b09l,0xb2262d7ba681f5e5l, + 0x4fc30c8c3413863al }, + { 0x691544b7c32059f7l,0xf65cf276b21c6134l,0xe3a96b2a5104dabal, + 0xbb08d109a43ee42fl }, + 0 }, + /* 19 << 216 */ + { { 0x85a52d69f9916861l,0x595469a4da4fa813l,0x1dd7786e3338502fl, + 0x34b8ef2853963ac5l }, + { 0xc0f019f81a891b25l,0xb619970c4f4bd775l,0x8c2a5af3be19f681l, + 0x9463db0498ec1728l }, + 0 }, + /* 21 << 216 */ + { { 0xeb62c27801f39eabl,0x27de39340ab3a4aal,0xfbd17520a982ca8dl, + 0x58817ec2e4bdc6edl }, + { 0x312d78de31c6ac13l,0x9483bf7609202ea6l,0xf64ab8b622c6d8e1l, + 0xdddf589ce580de74l }, + 0 }, + /* 23 << 216 */ + { { 0xe0fa3336ee98a92al,0x7d80eeef66a4d745l,0xb612531bba0119d3l, + 0x86e770c1b351fe15l }, + { 0xafbad6f882d5a397l,0x1e5f1cb80dbf0110l,0x25138ac09f79063dl, + 0x089ed22f2746a156l }, + 0 }, + /* 25 << 216 */ + { { 0x198d1b5d7d8b8ddel,0xf32c11078dab37fbl,0xf15fcb6d42b93874l, + 0x91ddb74f41f94f84l }, + { 0x6a64540a271524b2l,0x950a0c12758b5a64l,0xf9f237933dce9580l, + 0xc8edd0ab2cf8ce32l }, + 0 }, + /* 27 << 216 */ + { { 0xefc6357eae1046b7l,0xe6704929612932e4l,0xa20305d4b1355b17l, + 0x88a9136a58b4a156l }, + { 0xbc379985b4d275ecl,0x718b91316eaf338bl,0x61229a7ad152a509l, + 0x1109f7c445157ae9l }, + 0 }, + /* 28 << 216 */ + { { 0xcf197ca7fb8088fal,0x014272474ddc96c5l,0xa2d2550a30777176l, + 0x534698984d0cf71dl }, + { 0x6ce937b83a2aaac6l,0xe9f91dc35af38d9bl,0x2598ad83c8bf2899l, + 0x8e706ac9b5536c16l }, + 0 }, + /* 29 << 216 */ + { { 0x2bde42140df85c2cl,0x4fb839f4058a7a63l,0x7c10572a47f51231l, + 0x878826231989824el }, + { 0xa8293d2016e1564al,0xcb11c0f818c04576l,0x83b91e7d9740c631l, + 0xbdcb23d0cbffcea0l }, + 0 }, + /* 31 << 216 */ + { { 0x64bdfd2a9094bfc8l,0x8558acc60fc54d1el,0x3992848faf27721el, + 0x7a8fcbdaa14cd009l }, + { 0x6de6120900a4b9c2l,0xbd192b1b20cf8f28l,0x2356b90168d9be83l, + 0xce1e7a944a49a48al }, + 0 }, + /* 33 << 216 */ + { { 0x7630103b6ac189b9l,0x15d35edc6f1f5549l,0x9051799d31cb58edl, + 0xb4f32694a7a8579el }, + { 0x6f037435f2abe306l,0xf0595696410fb2f7l,0x2a0d347a5cc98f59l, + 0x9c19a9a87e3bbd69l }, + 0 }, + /* 34 << 216 */ + { { 0x87f8df7c0e58d493l,0xb1ae5ed058b73f12l,0xc368f784dea0c34dl, + 0x9bd0a120859a91a0l }, + { 0xb00d88b7cc863c68l,0x3a1cc11e3d1f4d65l,0xea38e0e70aa85593l, + 0x37f13e987dc4aee8l }, + 0 }, + /* 35 << 216 */ + { { 0x91dbe00e49430cd2l,0xcc67c0b17aa8ef6bl,0x769985b8a273f1a5l, + 0x358371dc360e5dafl }, + { 0xbf9b9127d6d8b5e8l,0x748ae12cb45588c1l,0x9c609eb556076c58l, + 0xf287489109733e89l }, + 0 }, + /* 36 << 216 */ + { { 0x10d38667bc947badl,0x738e07ce2a36ee2el,0xc93470cdc577fcacl, + 0xdee1b6162782470dl }, + { 0x36a25e672e793d12l,0xd6aa6caee0f186dal,0x474d0fd980e07af7l, + 0xf7cdc47dba8a5cd4l }, + 0 }, + /* 37 << 216 */ + { { 0xceb6aa80f8a08fddl,0xd98fc56f46fead7bl,0xe26bd3f8b07b3f1fl, + 0x3547e9b99d361c3el }, + { 0x1a89f802e94b8eccl,0x2210a590c0a40ef2l,0xe7e5b965afc01bf2l, + 0xca3d57fe234b936bl }, + 0 }, + /* 39 << 216 */ + { { 0x9230a70db9f9e8cdl,0xa63cebfcb81ba2ecl,0x8482ca87a8f664d6l, + 0xa8ae78e00b137064l }, + { 0xb787bd558384c687l,0xfde1d1bdb29ae830l,0xc4a9b2e39f0b7535l, + 0x7e6c9a15efde2d01l }, + 0 }, + /* 40 << 216 */ + { { 0x7d2e5c054f7269b1l,0xfcf30777e287c385l,0x10edc84ff2a46f21l, + 0x354417574f43fa36l }, + { 0xf1327899fd703431l,0xa438d7a616dd587al,0x65c34c57e9c8352dl, + 0xa728edab5cc5a24el }, + 0 }, + /* 41 << 216 */ + { { 0xcd6e6db872896d4fl,0x324afa99896c4640l,0x37d18c3d33a292bdl, + 0x98dba3b44143421fl }, + { 0x2406f3c949c61b84l,0x402d974754899588l,0xc73b7fd634a485e5l, + 0x75c9bae08587f0c3l }, + 0 }, + /* 43 << 216 */ + { { 0x6c32fa8cb0b4a04dl,0xeb58d0d875fda587l,0x61d8a157c4b86563l, + 0x92191bf01006b8afl }, + { 0xd04d3eff32d3478bl,0x3cc52eab2a684fc8l,0xb19a0f1625de54ccl, + 0x5c5295973620db2dl }, + 0 }, + /* 44 << 216 */ + { { 0xa97b51265c3427b0l,0x6401405cd282c9bdl,0x3629f8d7222c5c45l, + 0xb1c02c16e8d50aedl }, + { 0xbea2ed75d9635bc9l,0x226790c76e24552fl,0x3c33f2a365f1d066l, + 0x2a43463e6dfccc2el }, + 0 }, + /* 45 << 216 */ + { { 0x09b2e0d3b8da1e01l,0xa3a1a8fee9c0eb04l,0x59af5afe8bf653bal, + 0xba979f8bd0a54836l }, + { 0xa0d8194b51ee6ffbl,0x451c29e2f4b0586cl,0x7eb5fddb7471ee3dl, + 0x84b627d4bcb3afd8l }, + 0 }, + /* 46 << 216 */ + { { 0x8cc3453adb483761l,0xe7cc608565d5672bl,0x277ed6cbde3efc87l, + 0x19f2f36869234eafl }, + { 0x9aaf43175c0b800bl,0x1f1e7c898b6da6e2l,0x6cfb4715b94ec75el, + 0xd590dd5f453118c2l }, + 0 }, + /* 47 << 216 */ + { { 0xa70e9b0afb54e812l,0x092a0d7d8d86819bl,0x5421ff042e669090l, + 0x8af770c6b133c952l }, + { 0xc8e8dd596c8b1426l,0x1c92eb0e9523b483l,0x5a7c88f2cf3d40edl, + 0x4cc0c04bf5dd98f8l }, + 0 }, + /* 48 << 216 */ + { { 0x14e49da11f17a34cl,0x5420ab39235a1456l,0xb76372412f50363bl, + 0x7b15d623c3fabb6el }, + { 0xa0ef40b1e274e49cl,0x5cf5074496b1860al,0xd6583fbf66afe5a4l, + 0x44240510f47e3e9al }, + 0 }, + /* 49 << 216 */ + { { 0xb3939a8ffd617288l,0x3d37e5c2d68c2636l,0x4a595fac9d666c0el, + 0xfebcad9edb3a4978l }, + { 0x6d284a49c125016fl,0x05a7b9c80ee246a2l,0xe8b351739436c6e9l, + 0xffb89032d4be40b7l }, + 0 }, + /* 51 << 216 */ + { { 0xba1387a5436ebf33l,0xc351a400e8d05267l,0x18645dde4259dbe8l, + 0x5fc32895c10fd676l }, + { 0x1ef7a944807f040el,0x9486b5c625738e5fl,0xc9e56cf4a7e3e96cl, + 0x34c7dc87a20be832l }, + 0 }, + /* 52 << 216 */ + { { 0xe10d49996fe8393fl,0x0f809a3fe91f3a32l,0x61096d1c802f63c8l, + 0x289e146257750d3dl }, + { 0xed06167e9889feeal,0xd5c9c0e2e0993909l,0x46fca0d856508ac6l, + 0x918260474f1b8e83l }, + 0 }, + /* 53 << 216 */ + { { 0x1d5f2ad7a9bf79cbl,0x228fb24fca9c2f98l,0x5f7c3883701c4b71l, + 0x18cf76c4ec42d686l }, + { 0x3680d2e94dcdec8dl,0x6d58e87ba0d60cb6l,0x72fbf086a0e513cfl, + 0xb922d3c5346ed99al }, + 0 }, + /* 55 << 216 */ + { { 0x1678d658c2b9b874l,0x0e0b2c47f6360d4dl,0x01a45c02a0c9b9acl, + 0x05e82e9d0da69afbl }, + { 0x50be4001f28b8018l,0x503d967b667d8241l,0x6cd816534981da04l, + 0x9b18c3117f09c35fl }, + 0 }, + /* 57 << 216 */ + { { 0xdfdfd5b409d22331l,0xf445126817f0c6a2l,0xe51d1aa8a5cde27bl, + 0xb61a12a37aaf9513l }, + { 0xe43a241d3b3ea114l,0x5c62b624366ae28dl,0x085a530db5f237eal, + 0x7c4ed375651205afl }, + 0 }, + /* 59 << 216 */ + { { 0xf9de879dce842decl,0xe505320a94cedb89l,0xee55dae7f05ad888l, + 0x44ffbfa7f028b4efl }, + { 0xa3c1b32e63b2cd31l,0x201a058910c5ab29l,0x20f930afcd4085d6l, + 0xda79ed169f6ff24bl }, + 0 }, + /* 60 << 216 */ + { { 0x7e8cfbcf704e23c6l,0xc71b7d2228aaa65bl,0xa041b2bd245e3c83l, + 0x69b98834d21854ffl }, + { 0x89d227a3963bfeecl,0x99947aaade7da7cbl,0x1d9ee9dbee68a9b1l, + 0x0a08f003698ec368l }, + 0 }, + /* 61 << 216 */ + { { 0x04c64f33b0959be5l,0x182332ba396a7fe2l,0x4c5401e302e15b97l, + 0x92880f9877db104bl }, + { 0x0bf0b9cc21726a33l,0x780264741acc7b6dl,0x9721f621a26f08e3l, + 0xe3935b434197fed1l }, + 0 }, + /* 63 << 216 */ + { { 0x0bffae503652be69l,0x395a9c6afb3fd5d8l,0x17f66adaa4fadfbfl, + 0x1ee92a35f9268f8cl }, + { 0x40ded34d6827781al,0xcd36224e34e63dccl,0xec90cf571cd1ef7al, + 0xf6067d578f72a3bfl }, + 0 }, + /* 64 << 216 */ + { { 0x142b55021a93507al,0xb4cd11878d3c06cfl,0xdf70e76a91ec3f40l, + 0x484e81ad4e7553c2l }, + { 0x830f87b5272e9d6el,0xea1c93e5c6ff514al,0x67cc2adcc4192a8el, + 0xc77e27e242f4535al }, + 0 }, + /* 65 << 216 */ + { { 0x537388d299e2f9d2l,0x15ead88612cd6d08l,0x33dfe3a769082d86l, + 0x0ef25f4266d79d40l }, + { 0x8035b4e546ba5cf1l,0x4e48f53711eec591l,0x40b56cda122a7aael, + 0x78e270211dbb79a7l }, + 0 }, + /* 71 << 216 */ + { { 0x520b655355b4a5b1l,0xeee835cafb4f5fdel,0xb2ae86e59a823d7fl, + 0x24325f4fc084497fl }, + { 0x542bed4e6f0eefa4l,0x2909233b141792fdl,0x74bfc3bfc847a946l, + 0x8ec1d009e212cb44l }, + 0 }, + /* 77 << 216 */ + { { 0xc2082b6d5cedd516l,0xaf148eadeafa3a10l,0x104cd5855ad63aa6l, + 0xe3fdbf8c78c11e1el }, + { 0x78651c493c25c24el,0x8064c4f37b7cce0el,0xa55441d4a6d8a928l, + 0x4525c40eb0db3adcl }, + 0 }, + /* 83 << 216 */ + { { 0x5f69e49cfde6001el,0xc61e753aee59b47el,0xd0d4559971b0db5bl, + 0x7f76f7b45ad4acc3l }, + { 0xb0318a9c39830897l,0x2b15da22feef3822l,0x34049400acfb0753l, + 0x16f4fb51a5114ed4l }, + 0 }, + /* 89 << 216 */ + { { 0x0b5c76928defbf10l,0xb9f1795cb79cdb6el,0xba17e7759a90317cl, + 0x3cb69cf950cf514bl }, + { 0x076cc4c1e5b892ffl,0x75724e8fb548b73cl,0x2ebcdb33248ff2e6l, + 0x1f12967be109b08fl }, + 0 }, + /* 95 << 216 */ + { { 0x3f514c63461b7bb3l,0x3bdca5aa70afbad7l,0x368ce251eab3e38bl, + 0xdc0fb3300d101049l }, + { 0x7ce09abdff5013eel,0x926dd7dd7d10729dl,0xe6fe47ab6f486197l, + 0xd23964eaa6eb6903l }, + 0 }, + /* 101 << 216 */ + { { 0x537ceb74eca30797l,0xf171bba557b0f338l,0x220a31fee831f1f8l, + 0xabbc2c7c5ae6bbbcl }, + { 0xaf7609f27eadfb60l,0x22cff1d58f28b51bl,0x63c3d76d6d1863bdl, + 0x3a6a2fb489e8a4c8l }, + 0 }, + /* 107 << 216 */ + { { 0x9e74f8beb26e38f0l,0xc4c73fc4ea8bd55bl,0x086f688e1429e1fcl, + 0x91438ff40f78159fl }, + { 0x3571ae5f20810acbl,0x305edafe7451eb00l,0x8443c96d5704385cl, + 0xc03b234e542605b5l }, + 0 }, + /* 113 << 216 */ + { { 0x2e5ff4fed85567c2l,0x136f49c7e4abd0c6l,0x5a68730cfb8a62d1l, + 0x101ebfd030bcb848l }, + { 0x634b0618fee950bbl,0xfa748d21c8aa65bal,0xc1d67c3e699f5560l, + 0x6fb0546cb22889d2l }, + 0 }, + /* 116 << 216 */ + { { 0xa9784ebd9c95f0f9l,0x5ed9deb224640771l,0x31244af7035561c4l, + 0x87332f3a7ee857del }, + { 0x09e16e9e2b9e0d88l,0x52d910f456a06049l,0x507ed477a9592f48l, + 0x85cb917b2365d678l }, + 0 }, + /* 119 << 216 */ + { { 0x6108f2b458a9d40dl,0xb036034838e15a52l,0xcc5610a3fd5625d6l, + 0x79825dd083b0418el }, + { 0xf83a95fc6324b6e5l,0x2463114deedfc4ebl,0x58b177e32250707fl, + 0x778dcd454af8d942l }, + 0 }, + /* 125 << 216 */ + { { 0x1ecf2670eb816bf8l,0xa2d6e73aaa6d59c6l,0xf9a11434156852ebl, + 0x9bc9bb70f6f82c83l }, + { 0xd23a018d9c874836l,0xd26bf8bc6db5a8b5l,0x1d648846bec0c624l, + 0x39f15d97ef90302fl }, + 0 }, + }, + { + /* 0 << 224 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 224 */ + { { 0xe3417bc035d0b34al,0x440b386b8327c0a7l,0x8fb7262dac0362d1l, + 0x2c41114ce0cdf943l }, + { 0x2ba5cef1ad95a0b1l,0xc09b37a867d54362l,0x26d6cdd201e486c9l, + 0x20477abf42ff9297l }, + 0 }, + /* 3 << 224 */ + { { 0x126f35b51e706ad9l,0xb99cebb4c3a9ebdfl,0xa75389afbf608d90l, + 0x76113c4fc6c89858l }, + { 0x80de8eb097e2b5aal,0x7e1022cc63b91304l,0x3bdab6056ccc066cl, + 0x33cbb144b2edf900l }, + 0 }, + /* 4 << 224 */ + { { 0xc41764717af715d2l,0xe2f7f594d0134a96l,0x2c1873efa41ec956l, + 0xe4e7b4f677821304l }, + { 0xe5c8ff9788d5374al,0x2b915e6380823d5bl,0xea6bc755b2ee8fe2l, + 0x6657624ce7112651l }, + 0 }, + /* 5 << 224 */ + { { 0x157af101dace5acal,0xc4fdbcf211a6a267l,0xdaddf340c49c8609l, + 0x97e49f52e9604a65l }, + { 0x9be8e790937e2ad5l,0x846e2508326e17f1l,0x3f38007a0bbbc0dcl, + 0xcf03603fb11e16d6l }, + 0 }, + /* 7 << 224 */ + { { 0x5ed0c007f8ae7c38l,0x6db07a5c3d740192l,0xbe5e9c2a5fe36db3l, + 0xd5b9d57a76e95046l }, + { 0x54ac32e78eba20f2l,0xef11ca8f71b9a352l,0x305e373eff98a658l, + 0xffe5a100823eb667l }, + 0 }, + /* 9 << 224 */ + { { 0x5c8ed8d5da64309dl,0x61a6de5691b30704l,0xd6b52f6a2f9b5808l, + 0x0eee419498c958a7l }, + { 0xcddd9aab771e4caal,0x83965dfd78bc21bel,0x02affce3b3b504f5l, + 0x30847a21561c8291l }, + 0 }, + /* 10 << 224 */ + { { 0xd2eb2cf152bfda05l,0xe0e4c4e96197b98cl,0x1d35076cf8a1726fl, + 0x6c06085b2db11e3dl }, + { 0x15c0c4d74463ba14l,0x9d292f830030238cl,0x1311ee8b3727536dl, + 0xfeea86efbeaedc1el }, + 0 }, + /* 11 << 224 */ + { { 0xb9d18cd366131e2el,0xf31d974f80fe2682l,0xb6e49e0fe4160289l, + 0x7c48ec0b08e92799l }, + { 0x818111d8d1989aa7l,0xb34fa0aaebf926f9l,0xdb5fe2f5a245474al, + 0xf80a6ebb3c7ca756l }, + 0 }, + /* 13 << 224 */ + { { 0x8ea610593de9abe3l,0x404348819cdc03bel,0x9b261245cfedce8cl, + 0x78c318b4cf5234a1l }, + { 0x510bcf16fde24c99l,0x2a77cb75a2c2ff5dl,0x9c895c2b27960fb4l, + 0xd30ce975b0eda42bl }, + 0 }, + /* 15 << 224 */ + { { 0x09521177ff57d051l,0x2ff38037fb6a1961l,0xfc0aba74a3d76ad4l, + 0x7c76480325a7ec17l }, + { 0x7532d75f48879bc8l,0xea7eacc058ce6bc1l,0xc82176b48e896c16l, + 0x9a30e0b22c750fedl }, + 0 }, + /* 16 << 224 */ + { { 0xc37e2c2e421d3aa4l,0xf926407ce84fa840l,0x18abc03d1454e41cl, + 0x26605ecd3f7af644l }, + { 0x242341a6d6a5eabfl,0x1edb84f4216b668el,0xd836edb804010102l, + 0x5b337ce7945e1d8cl }, + 0 }, + /* 17 << 224 */ + { { 0xd2075c77c055dc14l,0x2a0ffa2581d89cdfl,0x8ce815ea6ffdcbafl, + 0xa3428878fb648867l }, + { 0x277699cf884655fbl,0xfa5b5bd6364d3e41l,0x01f680c6441e1cb7l, + 0x3fd61e66b70a7d67l }, + 0 }, + /* 19 << 224 */ + { { 0xfd5bb657b1fa70fbl,0xfa07f50fd8073a00l,0xf72e3aa7bca02500l, + 0xf68f895d9975740dl }, + { 0x301120605cae2a6al,0x01bd721802874842l,0x3d4238917ce47bd3l, + 0xa66663c1789544f6l }, + 0 }, + /* 21 << 224 */ + { { 0xb4b9a39b36194d40l,0xe857a7c577612601l,0xf4209dd24ecf2f58l, + 0x82b9e66d5a033487l }, + { 0xc1e36934e4e8b9ddl,0xd2372c9da42377d7l,0x51dc94c70e3ae43bl, + 0x4c57761e04474f6fl }, + 0 }, + /* 23 << 224 */ + { { 0xa39114e24415503bl,0xc08ff7c64cbb17e9l,0x1eff674dd7dec966l, + 0x6d4690af53376f63l }, + { 0xff6fe32eea74237bl,0xc436d17ecd57508el,0x15aa28e1edcc40fel, + 0x0d769c04581bbb44l }, + 0 }, + /* 25 << 224 */ + { { 0xfe51d0296ae55043l,0x8931e98f44a87de1l,0xe57f1cc609e4fee2l, + 0x0d063b674e072d92l }, + { 0x70a998b9ed0e4316l,0xe74a736b306aca46l,0xecf0fbf24fda97c7l, + 0xa40f65cb3e178d93l }, + 0 }, + /* 27 << 224 */ + { { 0x8667e981c27253c9l,0x05a6aefb92b36a45l,0xa62c4b369cb7bb46l, + 0x8394f37511f7027bl }, + { 0x747bc79c5f109d0fl,0xcad88a765b8cc60al,0x80c5a66b58f09e68l, + 0xe753d451f6127eacl }, + 0 }, + /* 28 << 224 */ + { { 0xc44b74a15b0ec6f5l,0x47989fe45289b2b8l,0x745f848458d6fc73l, + 0xec362a6ff61c70abl }, + { 0x070c98a7b3a8ad41l,0x73a20fc07b63db51l,0xed2c2173f44c35f4l, + 0x8a56149d9acc9dcal }, + 0 }, + /* 29 << 224 */ + { { 0x98f178819ac6e0f4l,0x360fdeafa413b5edl,0x0625b8f4a300b0fdl, + 0xf1f4d76a5b3222d3l }, + { 0x9d6f5109587f76b8l,0x8b4ee08d2317fdb5l,0x88089bb78c68b095l, + 0x95570e9a5808d9b9l }, + 0 }, + /* 31 << 224 */ + { { 0x2e1284943fb42622l,0x3b2700ac500907d5l,0xf370fb091a95ec63l, + 0xf8f30be231b6dfbdl }, + { 0xf2b2f8d269e55f15l,0x1fead851cc1323e9l,0xfa366010d9e5eef6l, + 0x64d487b0e316107el }, + 0 }, + /* 33 << 224 */ + { { 0xc9a9513929607745l,0x0ca07420a26f2b28l,0xcb2790e74bc6f9ddl, + 0x345bbb58adcaffc0l }, + { 0xc65ea38cbe0f27a2l,0x67c24d7c641fcb56l,0x2c25f0a7a9e2c757l, + 0x93f5cdb016f16c49l }, + 0 }, + /* 34 << 224 */ + { { 0x2ca5a9d7c5ee30a1l,0xd1593635b909b729l,0x804ce9f3dadeff48l, + 0xec464751b07c30c3l }, + { 0x89d65ff39e49af6al,0xf2d6238a6f3d01bcl,0x1095561e0bced843l, + 0x51789e12c8a13fd8l }, + 0 }, + /* 35 << 224 */ + { { 0xd633f929763231dfl,0x46df9f7de7cbddefl,0x01c889c0cb265da8l, + 0xfce1ad10af4336d2l }, + { 0x8d110df6fc6a0a7el,0xdd431b986da425dcl,0xcdc4aeab1834aabel, + 0x84deb1248439b7fcl }, + 0 }, + /* 36 << 224 */ + { { 0x8796f1693c2a5998l,0x9b9247b47947190dl,0x55b9d9a511597014l, + 0x7e9dd70d7b1566eel }, + { 0x94ad78f7cbcd5e64l,0x0359ac179bd4c032l,0x3b11baaf7cc222ael, + 0xa6a6e284ba78e812l }, + 0 }, + /* 37 << 224 */ + { { 0x8392053f24cea1a0l,0xc97bce4a33621491l,0x7eb1db3435399ee9l, + 0x473f78efece81ad1l }, + { 0x41d72fe0f63d3d0dl,0xe620b880afab62fcl,0x92096bc993158383l, + 0x41a213578f896f6cl }, + 0 }, + /* 39 << 224 */ + { { 0x6fb4d4e42bad4d5fl,0xfa4c3590fef0059bl,0x6a10218af5122294l, + 0x9a78a81aa85751d1l }, + { 0x04f20579a98e84e7l,0xfe1242c04997e5b5l,0xe77a273bca21e1e4l, + 0xfcc8b1ef9411939dl }, + 0 }, + /* 40 << 224 */ + { { 0xe20ea30292d0487al,0x1442dbec294b91fel,0x1f7a4afebb6b0e8fl, + 0x1700ef746889c318l }, + { 0xf5bbffc370f1fc62l,0x3b31d4b669c79ccal,0xe8bc2aaba7f6340dl, + 0xb0b08ab4a725e10al }, + 0 }, + /* 41 << 224 */ + { { 0x44f05701ae340050l,0xba4b30161cf0c569l,0x5aa29f83fbe19a51l, + 0x1b9ed428b71d752el }, + { 0x1666e54eeb4819f5l,0x616cdfed9e18b75bl,0x112ed5be3ee27b0bl, + 0xfbf2831944c7de4dl }, + 0 }, + /* 43 << 224 */ + { { 0x722eb104e2b4e075l,0x49987295437c4926l,0xb1e4c0e446a9b82dl, + 0xd0cb319757a006f5l }, + { 0xf3de0f7dd7808c56l,0xb5c54d8f51f89772l,0x500a114aadbd31aal, + 0x9afaaaa6295f6cabl }, + 0 }, + /* 44 << 224 */ + { { 0x94705e2104cf667al,0xfc2a811b9d3935d7l,0x560b02806d09267cl, + 0xf19ed119f780e53bl }, + { 0xf0227c09067b6269l,0x967b85335caef599l,0x155b924368efeebcl, + 0xcd6d34f5c497bae6l }, + 0 }, + /* 45 << 224 */ + { { 0x1dd8d5d36cceb370l,0x2aeac579a78d7bf9l,0x5d65017d70b67a62l, + 0x70c8e44f17c53f67l }, + { 0xd1fc095086a34d09l,0xe0fca256e7134907l,0xe24fa29c80fdd315l, + 0x2c4acd03d87499adl }, + 0 }, + /* 46 << 224 */ + { { 0xbaaf75173b5a9ba6l,0xb9cbe1f612e51a51l,0xd88edae35e154897l, + 0xe4309c3c77b66ca0l }, + { 0xf5555805f67f3746l,0x85fc37baa36401ffl,0xdf86e2cad9499a53l, + 0x6270b2a3ecbc955bl }, + 0 }, + /* 47 << 224 */ + { { 0xafae64f5974ad33bl,0x04d85977fe7b2df1l,0x2a3db3ff4ab03f73l, + 0x0b87878a8702740al }, + { 0x6d263f015a061732l,0xc25430cea32a1901l,0xf7ebab3ddb155018l, + 0x3a86f69363a9b78el }, + 0 }, + /* 48 << 224 */ + { { 0x349ae368da9f3804l,0x470f07fea164349cl,0xd52f4cc98562baa5l, + 0xc74a9e862b290df3l }, + { 0xd3a1aa3543471a24l,0x239446beb8194511l,0xbec2dd0081dcd44dl, + 0xca3d7f0fc42ac82dl }, + 0 }, + /* 49 << 224 */ + { { 0x1f3db085fdaf4520l,0xbb6d3e804549daf2l,0xf5969d8a19ad5c42l, + 0x7052b13ddbfd1511l }, + { 0x11890d1b682b9060l,0xa71d3883ac34452cl,0xa438055b783805b4l, + 0x432412774725b23el }, + 0 }, + /* 51 << 224 */ + { { 0x40b08f7443b30ca8l,0xe10b5bbad9934583l,0xe8a546d6b51110adl, + 0x1dd50e6628e0b6c5l }, + { 0x292e9d54cff2b821l,0x3882555d47281760l,0x134838f83724d6e3l, + 0xf2c679e022ddcda1l }, + 0 }, + /* 52 << 224 */ + { { 0x40ee88156d2a5768l,0x7f227bd21c1e7e2dl,0x487ba134d04ff443l, + 0x76e2ff3dc614e54bl }, + { 0x36b88d6fa3177ec7l,0xbf731d512328fff5l,0x758caea249ba158el, + 0x5ab8ff4c02938188l }, + 0 }, + /* 53 << 224 */ + { { 0x33e1605635edc56dl,0x5a69d3497e940d79l,0x6c4fd00103866dcbl, + 0x20a38f574893cdefl }, + { 0xfbf3e790fac3a15bl,0x6ed7ea2e7a4f8e6bl,0xa663eb4fbc3aca86l, + 0x22061ea5080d53f7l }, + 0 }, + /* 55 << 224 */ + { { 0x635a8e5ec3a0ee43l,0x70aaebca679898ffl,0x9ee9f5475dc63d56l, + 0xce987966ffb34d00l }, + { 0xf9f86b195e26310al,0x9e435484382a8ca8l,0x253bcb81c2352fe4l, + 0xa4eac8b04474b571l }, + 0 }, + /* 57 << 224 */ + { { 0x2617f91c93aa96b8l,0x0fc8716b7fca2e13l,0xa7106f5e95328723l, + 0xd1c9c40b262e6522l }, + { 0xb9bafe8642b7c094l,0x1873439d1543c021l,0xe1baa5de5cbefd5dl, + 0xa363fc5e521e8affl }, + 0 }, + /* 59 << 224 */ + { { 0xbc00fc2f2f8ba2c7l,0x0966eb2f7c67aa28l,0x13f7b5165a786972l, + 0x3bfb75578a2fbba0l }, + { 0x131c4f235a2b9620l,0xbff3ed276faf46bel,0x9b4473d17e172323l, + 0x421e8878339f6246l }, + 0 }, + /* 60 << 224 */ + { { 0x0fa8587a25a41632l,0xc0814124a35b6c93l,0x2b18a9f559ebb8dbl, + 0x264e335776edb29cl }, + { 0xaf245ccdc87c51e2l,0x16b3015b501e6214l,0xbb31c5600a3882cel, + 0x6961bb94fec11e04l }, + 0 }, + /* 61 << 224 */ + { { 0x3b825b8deff7a3a0l,0xbec33738b1df7326l,0x68ad747c99604a1fl, + 0xd154c9349a3bd499l }, + { 0xac33506f1cc7a906l,0x73bb53926c560e8fl,0x6428fcbe263e3944l, + 0xc11828d51c387434l }, + 0 }, + /* 63 << 224 */ + { { 0x659b17c8d8ceb147l,0x9b649eeeb70a5554l,0x6b7fa0b5ac6bc634l, + 0xd99fe2c71d6e732fl }, + { 0x30e6e7628d3abba2l,0x18fee6e7a797b799l,0x5c9d360dc696464dl, + 0xe3baeb4827bfde12l }, + 0 }, + /* 64 << 224 */ + { { 0x2bf5db47f23206d5l,0x2f6d34201d260152l,0x17b876533f8ff89al, + 0x5157c30c378fa458l }, + { 0x7517c5c52d4fb936l,0xef22f7ace6518cdcl,0xdeb483e6bf847a64l, + 0xf508455892e0fa89l }, + 0 }, + /* 65 << 224 */ + { { 0xf77bb113a74ed3bel,0x89e4eb8f074f2637l,0x7fbfa84df7ce2aebl, + 0xe7c6ecd5baaefe4cl }, + { 0x176bba7df6319542l,0x70098120f6080799l,0x2e2118339054d9aal, + 0x1be4c6a78295a912l }, + 0 }, + /* 71 << 224 */ + { { 0x6bb4d8c35df1455fl,0xb839f08f0384b033l,0x718868af11f95d50l, + 0xae256a92e07a8801l }, + { 0xa5bafaf24d71a273l,0x18ff04ea2a30e68fl,0x364c193287ba727el, + 0x4bb8cf99befcaf73l }, + 0 }, + /* 77 << 224 */ + { { 0xc79f5b1f4e9fb3d7l,0x52854970a51cccddl,0xa4e27e97f00054a3l, + 0x26a79792240e1232l }, + { 0xb15579fecb5ff465l,0x6ef54c3bd1722a84l,0xee211bfa5239a4d8l, + 0x36c7db27270b7059l }, + 0 }, + /* 83 << 224 */ + { { 0x5e7da0a9f9858cd3l,0x67459de5b633de49l,0x2db0d54b2e73892el, + 0x37f50877adae399al }, + { 0x83c28b83b65e6179l,0xae5a915ca39faf17l,0x6ab8f3fbe841b53cl, + 0x7c30997b0df7d004l }, + 0 }, + /* 89 << 224 */ + { { 0x87904ca7b3b862bdl,0x7593db93cf9ea671l,0x8a2670f8739aa783l, + 0x3921d779f5154ca6l }, + { 0xe81ca56468f65ebbl,0x0c600603bc4e64d4l,0xdf170049cb83b2d1l, + 0x373893b863487064l }, + 0 }, + /* 95 << 224 */ + { { 0x7c3c52b9c0c4e88el,0x0f0484d06f0c2446l,0xeb876827000fe87bl, + 0xa749b3136d20f94al }, + { 0x0876dae9d55abda6l,0xe6e4367620726911l,0xf85e8a8c4a2676b4l, + 0x4e8c97f1b4a890ebl }, + 0 }, + /* 101 << 224 */ + { { 0xa992f482a3c0a4f4l,0xe1536f3f7a8d961al,0x26fc79ae000752b0l, + 0xdbfb706b76ad8508l }, + { 0x2642b2ed6f4cf9e4l,0xa013db54557fa7e2l,0x2ef711821d326116l, + 0x8dc3f5bcbafc83ecl }, + 0 }, + /* 107 << 224 */ + { { 0x9671258578e5a201l,0xc71aca1de9125569l,0x360c45c0e2231379l, + 0x2d71783512e82369l }, + { 0x392432d3d84b2153l,0x502fd3f6d6939ffel,0x33c440ae6e766cacl, + 0x99f1fbee28062416l }, + 0 }, + /* 113 << 224 */ + { { 0xe51ad841861604cbl,0x1ec9c54f630283a7l,0xcc42cad582a39473l, + 0xa2eb053709929c4al }, + { 0xe374459767f655a3l,0x9f54c2451d7f2674l,0xd85e9163fbc8aba5l, + 0x12fd0b55866bc892l }, + 0 }, + /* 116 << 224 */ + { { 0x4f2c3063d7bd4661l,0xe533798d57a974ccl,0x44860d503ea02d85l, + 0xf2a7f4e5acaa0521l }, + { 0x05593061abb108f0l,0x56d1056044528309l,0x1f674df9c88b6d1el, + 0x19fdc4cbd8744c4dl }, + 0 }, + /* 119 << 224 */ + { { 0xfd1488ec00f2f1d5l,0x24fcc67b44a825ddl,0xc7bfae2ea925a0f4l, + 0x5e03249cad59cf48l }, + { 0x1dc5a8e11af4844cl,0x89b2fbc58a598c20l,0xb0f56afff2078121l, + 0x8194012d4878bb0dl }, + 0 }, + /* 125 << 224 */ + { { 0xc1cbe9d3a5ae1031l,0x38da74435706b987l,0x01844b55b353f188l, + 0x390c59ca87a807c5l }, + { 0x55ac7b1fb13b780cl,0x060970bff375c1cbl,0x8dd1f378c7ab4e5cl, + 0xcca782e5cf726645l }, + 0 }, + }, + { + /* 0 << 232 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 232 */ + { { 0x91213462f23f2d92l,0x6cab71bd60b94078l,0x6bdd0a63176cde20l, + 0x54c9b20cee4d54bcl }, + { 0x3cd2d8aa9f2ac02fl,0x03f8e617206eedb0l,0xc7f68e1693086434l, + 0x831469c592dd3db9l }, + 0 }, + /* 3 << 232 */ + { { 0x4a9090cde36d0757l,0xf722d7b1d9a29382l,0xfb7fb04c04b48ddfl, + 0x628ad2a7ebe16f43l }, + { 0xcd3fbfb520226040l,0x6c34ecb15104b6c4l,0x30c0754ec903c188l, + 0xec336b082d23cab0l }, + 0 }, + /* 4 << 232 */ + { { 0x9f51439e558df019l,0x230da4baac712b27l,0x518919e355185a24l, + 0x4dcefcdd84b78f50l }, + { 0xa7d90fb2a47d4c5al,0x55ac9abfb30e009el,0xfd2fc35974eed273l, + 0xb72d824cdbea8fafl }, + 0 }, + /* 5 << 232 */ + { { 0xd213f923cbb13d1bl,0x98799f425bfb9bfel,0x1ae8ddc9701144a9l, + 0x0b8b3bb64c5595eel }, + { 0x0ea9ef2e3ecebb21l,0x17cb6c4b3671f9a7l,0x47ef464f726f1d1fl, + 0x171b94846943a276l }, + 0 }, + /* 7 << 232 */ + { { 0xc9941109a607419dl,0xfaa71e62bb6bca80l,0x34158c1307c431f3l, + 0x594abebc992bc47al }, + { 0x6dfea691eb78399fl,0x48aafb353f42cba4l,0xedcd65af077c04f0l, + 0x1a29a366e884491al }, + 0 }, + /* 9 << 232 */ + { { 0x7bf6a5c1f7ea25aal,0xd165e6bffbb07d5fl,0xe353936189e78671l, + 0xa3fcac892bac4219l }, + { 0xdfab6fd4f0baa8abl,0x5a4adac1e2c1c2e5l,0x6cd75e3140d85849l, + 0xce263fea19b39181l }, + 0 }, + /* 10 << 232 */ + { { 0xb8d804a3315980cdl,0x693bc492fa3bebf7l,0x3578aeee2253c504l, + 0x158de498cd2474a2l }, + { 0x1331f5c7cfda8368l,0xd2d7bbb378d7177el,0xdf61133af3c1e46el, + 0x5836ce7dd30e7be8l }, + 0 }, + /* 11 << 232 */ + { { 0xe042ece59a29a5c5l,0xb19b3c073b6c8402l,0xc97667c719d92684l, + 0xb5624622ebc66372l }, + { 0x0cb96e653c04fa02l,0x83a7176c8eaa39aal,0x2033561deaa1633fl, + 0x45a9d0864533df73l }, + 0 }, + /* 13 << 232 */ + { { 0xa29ae9df5ece6e7cl,0x0603ac8f0facfb55l,0xcfe85b7adda233a5l, + 0xe618919fbd75f0b8l }, + { 0xf555a3d299bf1603l,0x1f43afc9f184255al,0xdcdaf341319a3e02l, + 0xd3b117ef03903a39l }, + 0 }, + /* 15 << 232 */ + { { 0xb6b82fa74d82f4c2l,0x90725a606804efb3l,0xbc82ec46adc3425el, + 0xb7b805812787843el }, + { 0xdf46d91cdd1fc74cl,0xdc1c62cbe783a6c4l,0x59d1b9f31a04cbbal, + 0xd87f6f7295e40764l }, + 0 }, + /* 16 << 232 */ + { { 0x196860411e84e0e5l,0xa5db84d3aea34c93l,0xf9d5bb197073a732l, + 0xb8d2fe566bcfd7c0l }, + { 0x45775f36f3eb82fal,0x8cb20cccfdff8b58l,0x1659b65f8374c110l, + 0xb8b4a422330c789al }, + 0 }, + /* 17 << 232 */ + { { 0xa6312c9e8977d99bl,0xbe94433183f531e7l,0x8232c0c218d3b1d4l, + 0x617aae8be1247b73l }, + { 0x40153fc4282aec3bl,0xc6063d2ff7b8f823l,0x68f10e583304f94cl, + 0x31efae74ee676346l }, + 0 }, + /* 19 << 232 */ + { { 0xd98bf2a43734e520l,0x5e3abbe3209bdcbal,0x77c76553bc945b35l, + 0x5331c093c6ef14aal }, + { 0x518ffe2976b60c80l,0x2285593b7ace16f8l,0xab1f64ccbe2b9784l, + 0xe8f2c0d9ab2421b6l }, + 0 }, + /* 21 << 232 */ + { { 0x481dae5fd5ecfefcl,0x07084fd8c2bff8fcl,0x8040a01aea324596l, + 0x4c646980d4de4036l }, + { 0x9eb8ab4ed65abfc3l,0xe01cb91f13541ec7l,0x8f029adbfd695012l, + 0x9ae284833c7569ecl }, + 0 }, + /* 23 << 232 */ + { { 0xc83605f6f10ff927l,0xd387145123739fc6l,0x6d163450cac1c2ccl, + 0x6b521296a2ec1ac5l }, + { 0x0606c4f96e3cb4a5l,0xe47d3f41778abff7l,0x425a8d5ebe8e3a45l, + 0x53ea9e97a6102160l }, + 0 }, + /* 25 << 232 */ + { { 0x6b72fab526bc2797l,0x13670d1699f16771l,0x001700521e3e48d1l, + 0x978fe401b7adf678l }, + { 0x55ecfb92d41c5dd4l,0x5ff8e247c7b27da5l,0xe7518272013fb606l, + 0x5768d7e52f547a3cl }, + 0 }, + /* 27 << 232 */ + { { 0x0e966e64c73b2383l,0x49eb3447d17d8762l,0xde1078218da05dabl, + 0x443d8baa016b7236l }, + { 0x163b63a5ea7610d6l,0xe47e4185ce1ca979l,0xae648b6580baa132l, + 0xebf53de20e0d5b64l }, + 0 }, + /* 28 << 232 */ + { { 0x6ba535da9a85788bl,0xd21f03aebd0626d4l,0x099f8c47e873dc64l, + 0xcda8564d018ec97el }, + { 0x3e8d7a5cde92c68cl,0x78e035a173323cc4l,0x3ef26275f880ff7cl, + 0xa4ee3dff273eedaal }, + 0 }, + /* 29 << 232 */ + { { 0x8bbaec49571d92acl,0x569e85fe4692517fl,0x8333b014a14ea4afl, + 0x32f2a62f12e5c5adl }, + { 0x98c2ce3a06d89b85l,0xb90741aa2ff77a08l,0x2530defc01f795a2l, + 0xd6e5ba0b84b3c199l }, + 0 }, + /* 31 << 232 */ + { { 0x3d1b24cb28c682c6l,0x27f252288612575bl,0xb587c779e8e66e98l, + 0x7b0c03e9405eb1fel }, + { 0xfdf0d03015b548e7l,0xa8be76e038b36af7l,0x4cdab04a4f310c40l, + 0x6287223ef47ecaecl }, + 0 }, + /* 33 << 232 */ + { { 0x0a4c6f3670ad54aal,0xc24cfd0d2a543909l,0xe1b0bc5b745c1a97l, + 0xb8431cfd68f0ddbfl }, + { 0x326357989ed8cb06l,0xa00a80ff759d2b7dl,0x81f335c190570e02l, + 0xbfccd89849c4e4d9l }, + 0 }, + /* 34 << 232 */ + { { 0x4dcb646bfd16d8c4l,0x76a6b640e38ba57bl,0xd92de1f79d8ae7e2l, + 0x126f48f13f77f23bl }, + { 0xb7b53ca977e8abc2l,0x3faa17112c0787ffl,0xf8f9308c8e5762f8l, + 0x600a8a7f6b83aea8l }, + 0 }, + /* 35 << 232 */ + { { 0xa2aed4a799aa03c0l,0x1f93b93da18b79c5l,0x7b4550b7314192c3l, + 0x9da00676272bb08el }, + { 0xe42f0d7e23e072edl,0x7ce76494888b5783l,0x4c7900203680b63bl, + 0x6040c83f662a8718l }, + 0 }, + /* 36 << 232 */ + { { 0xba9e5c88a56d73edl,0x6c24f7712ca054d3l,0x4a37c235083beae1l, + 0x04a883b26483e9fdl }, + { 0x0c63f3aee27c2c5dl,0x0e1da88dae4671f1l,0xa577e8e25995e1dbl, + 0xbfc4b1b16ed6066al }, + 0 }, + /* 37 << 232 */ + { { 0x8b398541f53d9e63l,0x4ab045bb019395cbl,0x69a1b90371dd70c7l, + 0xdedf284b38aaa431l }, + { 0xb45e245aaed3efe7l,0x49460905079f2facl,0xde4dee470845bd78l, + 0x0540524039d02ec3l }, + 0 }, + /* 39 << 232 */ + { { 0x300cf051675cc986l,0x758afea99324219fl,0xf524c3fad5a93b5fl, + 0xb73385abc3864a8al }, + { 0xbde19289f6be9050l,0xbb9018558205a3f3l,0x99a9d14d229f6b89l, + 0x4c3a802f4336e68fl }, + 0 }, + /* 40 << 232 */ + { { 0xdd4a12d8e12b31f8l,0x577e29bc177736e6l,0x2353722ba88935e8l, + 0xca1d3729015f286dl }, + { 0x86c7b6a239a3e035l,0x6e5250bfd3b03a9fl,0x79d98930fd0d536el, + 0x8c4cbbabfa0c3832l }, + 0 }, + /* 41 << 232 */ + { { 0x92ecff374f8e6163l,0x171cc8830f35faeal,0xc5434242bcd36142l, + 0x707049adb28b63bbl }, + { 0xa1f4d1dbf6443da9l,0x002bb062dabc108bl,0x17287f171a272b08l, + 0x2a3aac8c884cf6bbl }, + 0 }, + /* 43 << 232 */ + { { 0x55524645651c0a5al,0x14624a9703cf0d12l,0xca9315a8f884a9e2l, + 0x9840c6e2df7c9d59l }, + { 0xd96bd10a7438e8d5l,0x12be73d2b2f887del,0x5e47445dca2493efl, + 0x85aef555e9fff03el }, + 0 }, + /* 44 << 232 */ + { { 0x169b38c9a43b2339l,0x884308d91732bfabl,0xe4b593a28ff202ddl, + 0xaf51d11f1e65376cl }, + { 0x6ec648de741525ffl,0xf93cbd369ff4c628l,0xc76df9efb1129c79l, + 0x31a5f2e2b7a67294l }, + 0 }, + /* 45 << 232 */ + { { 0x0661bc02801d0e38l,0x4a37dc0e71fc46b7l,0x0b224cfc80c3e311l, + 0x2dd3d2779646a957l }, + { 0xfa45aa18ef524012l,0x5d2a2d0916185a09l,0x34d5c630b5313dcel, + 0xd9581ed151e4cf84l }, + 0 }, + /* 46 << 232 */ + { { 0x5845aa4a8ebd2af8l,0x141404ecd3df43ccl,0xff3fc7681ffd48d9l, + 0x8a096e72e0cefb65l }, + { 0xc9c81cfdffc3a5cdl,0x7550aa3029b27cf9l,0x34dca72b65fa0380l, + 0xe8c5f6059ddd032bl }, + 0 }, + /* 47 << 232 */ + { { 0xe53da8a46bfbadb3l,0x4a9dfa55afaeeb5el,0x076245ea6644b1d4l, + 0xc19be4012307bbcbl }, + { 0x097774c19d77318bl,0xacc8a1519cfd51c4l,0x736ef6b3ecaa7b08l, + 0x107479132d643a80l }, + 0 }, + /* 48 << 232 */ + { { 0x2d500910cab91f1el,0xbedd9e444d1cd216l,0xd634b74fedd02252l, + 0xbd60f8e11258617al }, + { 0xd8c7537b9e05614al,0xfd26c766e7af5fc5l,0x0660b581582bd926l, + 0x87019244acf07fc8l }, + 0 }, + /* 49 << 232 */ + { { 0xd4889fdf6220ae8el,0x745d67ec1abf1549l,0x957b2e3d2fb89c36l, + 0x9768c90edc62ada9l }, + { 0x90332fd748e6c46el,0x5aa5a4e54e90ef0dl,0x58838fd3ddcc8571l, + 0xd12f6c6f9a721126l }, + 0 }, + /* 51 << 232 */ + { { 0x2f0fd0b2cec757bal,0x46a7a9c63032cd1dl,0x9af3a600547d7a77l, + 0x828e16eca43da1bal }, + { 0x0b303a66092a8d92l,0x78ba0389c23d08bal,0x52aed08d4616bd29l, + 0x4c0ff1210539c9fal }, + 0 }, + /* 52 << 232 */ + { { 0x2c3b7322badcfe8el,0x6e0616fac5e25a04l,0x0a3c12753da6e4a2l, + 0xe46c957e077bca01l }, + { 0xb46ca4e3da4be64bl,0xa59bda668e75ee78l,0x41835184a4de98f2l, + 0x6efb1f924ed6a568l }, + 0 }, + /* 53 << 232 */ + { { 0xbb8cdc094af1dd72l,0x93c0aa38a2460633l,0xf66f5d238a7ebc93l, + 0x43ecda843e8e37a6l }, + { 0x399da8265fd5139el,0x8b39930fd446f38el,0x114414135d2b68efl, + 0x8be163b8d1637c38l }, + 0 }, + /* 55 << 232 */ + { { 0x488e2a35b70ddbd3l,0xb4aa5f718da50077l,0xb38b74b1d8752bbdl, + 0x7007f328416106a3l }, + { 0xe6a62e4fcec4ea68l,0x9fdfb79741ef920bl,0x1a19d7dfe3c337a6l, + 0x08f643558be0f586l }, + 0 }, + /* 57 << 232 */ + { { 0x91a5d8ff60343a1fl,0x921e442173ef8cdfl,0x4358f27b975138cdl, + 0x36fd8577a4992b08l }, + { 0xc07c8ca1f8d044c6l,0xcf42903687747b6bl,0x0932ffb0867c8632l, + 0x7e565213250e5a89l }, + 0 }, + /* 59 << 232 */ + { { 0xae7c3b9b06255feal,0x2eb1d9a78a6fe229l,0xf81548e77601e6f8l, + 0x777394eb7bd96d6cl }, + { 0x54734187000a3509l,0xaeec146492d43c04l,0xc9b7f0d7c428b4acl, + 0x9d4bcedccd7f7018l }, + 0 }, + /* 60 << 232 */ + { { 0x4741b9b311370605l,0x47fa72f75d09b355l,0x391a71ac7a144c6al, + 0x0808c0f498b6e3cal }, + { 0x7eaed9ef7fe53900l,0xf157a2a5e5a830bal,0xd13ec09127974afcl, + 0x78d710a70b87997dl }, + 0 }, + /* 61 << 232 */ + { { 0xcbb96ecb4e263f81l,0x093e0d1509084351l,0x7af3232629220a81l, + 0xd721b415c60f36dcl }, + { 0xe3340a87fe9387a1l,0x6088bf482ff2b126l,0xd31028f1d2bc982cl, + 0x9794e106630d52cbl }, + 0 }, + /* 63 << 232 */ + { { 0x1dac76780b11e972l,0x46e814c62698dafel,0x553f7370c37640d6l, + 0xdcf588cc51cede93l }, + { 0x4d6b56d3c3f6215bl,0x07edc6621b8f8f03l,0xdfef9d60b9a5dfbcl, + 0x377edf4d10af7a5bl }, + 0 }, + /* 64 << 232 */ + { { 0x8928e99aeeaf8c49l,0xee7aa73d6e24d728l,0x4c5007c2e72b156cl, + 0x5fcf57c5ed408a1dl }, + { 0x9f719e39b6057604l,0x7d343c01c2868bbfl,0x2cca254b7e103e2dl, + 0xe6eb38a9f131bea2l }, + 0 }, + /* 65 << 232 */ + { { 0x26ae28bede7a4b7el,0xd2f07569d2664163l,0x798690d4ff69266al, + 0x77093d356ef3695dl }, + { 0xaca9903d567dd3dfl,0x259c59a3a274c67bl,0x9f34bc0bfc1198b0l, + 0x51a7726290b1521cl }, + 0 }, + /* 71 << 232 */ + { { 0xa20644bc80ca5391l,0xf9cdb4f7e5b36ea3l,0xe7936c0641426e22l, + 0x39bc23033eef8a52l }, + { 0x31253f43e5d8f896l,0xb0e5a588dc3df499l,0x1d03519a2d7e66d5l, + 0x923de91f6d7da5e3l }, + 0 }, + /* 77 << 232 */ + { { 0x17a833ffedf861e4l,0x0ee3d0af4ebec965l,0xd0fac1c1ea66870el, + 0x325756d0ae810cf4l }, + { 0x4ed78d2c78e9a415l,0x6cc65685192046e4l,0x03e4243d8498a91el, + 0x56a02dd25ab97794l }, + 0 }, + /* 83 << 232 */ + { { 0xc2fd373748e2b156l,0x259e9a98139645bel,0xe90106fb9877b4f1l, + 0x49e5bac5889ce002l }, + { 0x936a7dd18cf14e0bl,0x70bf6d304e3a8a01l,0x99d3e8bfeb748b62l, + 0xa52a27c99b31c55cl }, + 0 }, + /* 89 << 232 */ + { { 0x9db1d41d300637d5l,0xe38744397c2dd836l,0x36179baf0d04ceb3l, + 0xe9ccd17b251b3f2dl }, + { 0xd8228073442b6d1dl,0x59a038363eed2971l,0xb443732046979f5cl, + 0x54ad4113ae63937cl }, + 0 }, + /* 95 << 232 */ + { { 0x092c34e6d9246e9fl,0xb4b3b63d3eeb18a7l,0x8b3778beed9d1383l, + 0xe4cb7be9d70d5d80l }, + { 0xcff12e9b3d059203l,0x277af117ba86699fl,0x9bd4e8e363603585l, + 0x0750b0f28e89c8d5l }, + 0 }, + /* 101 << 232 */ + { { 0x38b77e5958f7187bl,0x31c7068de0cb618el,0xa0f8e0d6c11ebe62l, + 0x07adc8010473d7ebl }, + { 0x36161a2c5c3e9510l,0xb2ec90d64ad04815l,0x01e2dd1f917d8166l, + 0x549bcbdd6aa0f794l }, + 0 }, + /* 107 << 232 */ + { { 0x4ab27c3a8e4e45e5l,0xf6bd9d82f2bb99e7l,0xcab48c735e9da59fl, + 0xdeb09eb2b9727353l }, + { 0xc4a7954bafb8fa3el,0x34af2a49abf6803dl,0xc1ee1416d63e13bbl, + 0xd49bf42d7a949193l }, + 0 }, + /* 113 << 232 */ + { { 0x504823ea9c9c07c6l,0x9dbec902bee2288cl,0x018d7875f0ceb6bbl, + 0x678b997304f7022cl }, + { 0x74d658238c5fb369l,0x7d4e1f114ca89ee8l,0x148316399905abc0l, + 0xc107324e2c4deff4l }, + 0 }, + /* 116 << 232 */ + { { 0x1bc4fa8bdadc4404l,0x0edb9534daa12ee3l,0x084481b6a5f7289cl, + 0x7f42461d9d8fb3d2l }, + { 0xf93f1d3212293c70l,0xc14706596bb73ea3l,0xf80834afde339cadl, + 0x99dcfc0081f22953l }, + 0 }, + /* 119 << 232 */ + { { 0x497e544f9fca737el,0x7f6342210e91e1afl,0x638e500c78d7b20bl, + 0xb1ffed3f7ebaa947l }, + { 0x751aa54871086f83l,0x8100bb703cf97848l,0xc32f91ace19ad68fl, + 0x7dffb6851fb9157el }, + 0 }, + /* 125 << 232 */ + { { 0x5108589778e25060l,0x33e3cb7316cfe6cbl,0x0884cb8d410c0822l, + 0xaa806ecc0be3fc94l }, + { 0x9f9121f5f692353el,0xb9ab0310f8ee3349l,0x390032ce2561973el, + 0xc07b6c6c8856b766l }, + 0 }, + }, + { + /* 0 << 240 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 240 */ + { { 0x1083e2ea1f095615l,0x0a28ad7714e68c33l,0x6bfc02523d8818bel, + 0xb585113af35850cdl }, + { 0x7d935f0b30df8aa1l,0xaddda07c4ab7e3acl,0x92c34299552f00cbl, + 0xc33ed1de2909df6cl }, + 0 }, + /* 3 << 240 */ + { { 0xabe7905a83cdd60el,0x50602fb5a1170184l,0x689886cdb023642al, + 0xd568d090a6e1fb00l }, + { 0x5b1922c70259217fl,0x93831cd9c43141e4l,0xdfca35870c95f86el, + 0xdec2057a568ae828l }, + 0 }, + /* 4 << 240 */ + { { 0x568f8925913cc16dl,0x18bc5b6de1a26f5al,0xdfa413bef5f499ael, + 0xf8835decc3f0ae84l }, + { 0xb6e60bd865a40ab0l,0x65596439194b377el,0xbcd8562592084a69l, + 0x5ce433b94f23ede0l }, + 0 }, + /* 5 << 240 */ + { { 0x860d523d42e06189l,0xbf0779414e3aff13l,0x0b616dcac1b20650l, + 0xe66dd6d12131300dl }, + { 0xd4a0fd67ff99abdel,0xc9903550c7aac50dl,0x022ecf8b7c46b2d7l, + 0x3333b1e83abf92afl }, + 0 }, + /* 7 << 240 */ + { { 0xefecdef7be42a582l,0xd3fc608065046be6l,0xc9af13c809e8dba9l, + 0x1e6c9847641491ffl }, + { 0x3b574925d30c31f7l,0xb7eb72baac2a2122l,0x776a0dacef0859e7l, + 0x06fec31421900942l }, + 0 }, + /* 9 << 240 */ + { { 0x7ec62fbbf4737f21l,0xd8dba5ab6209f5acl,0x24b5d7a9a5f9adbel, + 0x707d28f7a61dc768l }, + { 0x7711460bcaa999eal,0xba7b174d1c92e4ccl,0x3c4bab6618d4bf2dl, + 0xb8f0c980eb8bd279l }, + 0 }, + /* 10 << 240 */ + { { 0x9d658932790691bfl,0xed61058906b736ael,0x712c2f04c0d63b6el, + 0x5cf06fd5c63d488fl }, + { 0x97363facd9588e41l,0x1f9bf7622b93257el,0xa9d1ffc4667acacel, + 0x1cf4a1aa0a061ecfl }, + 0 }, + /* 11 << 240 */ + { { 0x28d675b2c0519a23l,0x9ebf94fe4f6952e3l,0xf28bb767a2294a8al, + 0x85512b4dfe0af3f5l }, + { 0x18958ba899b16a0dl,0x95c2430cba7548a7l,0xb30d1b10a16be615l, + 0xe3ebbb9785bfb74cl }, + 0 }, + /* 13 << 240 */ + { { 0x81eeb865d2fdca23l,0x5a15ee08cc8ef895l,0x768fa10a01905614l, + 0xeff5b8ef880ee19bl }, + { 0xf0c0cabbcb1c8a0el,0x2e1ee9cdb8c838f9l,0x0587d8b88a4a14c0l, + 0xf6f278962ff698e5l }, + 0 }, + /* 15 << 240 */ + { { 0x9c4b646e9e2fce99l,0x68a210811e80857fl,0x06d54e443643b52al, + 0xde8d6d630d8eb843l }, + { 0x7032156342146a0al,0x8ba826f25eaa3622l,0x227a58bd86138787l, + 0x43b6c03c10281d37l }, + 0 }, + /* 16 << 240 */ + { { 0x02b37a952f41deffl,0x0e44a59ae63b89b7l,0x673257dc143ff951l, + 0x19c02205d752baf4l }, + { 0x46c23069c4b7d692l,0x2e6392c3fd1502acl,0x6057b1a21b220846l, + 0xe51ff9460c1b5b63l }, + 0 }, + /* 17 << 240 */ + { { 0x7aca2632f02fc0f0l,0xb92b337dc7f01c86l,0x624bc4bf5afbdc7dl, + 0x812b07bc4de21a5el }, + { 0x29d137240b2090ccl,0x0403c5095a1b2132l,0x1dca34d50e35e015l, + 0xf085ed7d3bbbb66fl }, + 0 }, + /* 19 << 240 */ + { { 0xc27b98f9f781e865l,0x51e1f692994e1345l,0x0807d516e19361eel, + 0x13885ceffb998aefl }, + { 0xd223d5e92f0f8a17l,0x48672010e8d20280l,0x6f02fd60237eac98l, + 0xcc51bfad9ada7ee7l }, + 0 }, + /* 21 << 240 */ + { { 0x2756bcdd1e09701dl,0x94e31db990d45c80l,0xb9e856a98566e584l, + 0x4f87d9deab10e3f3l }, + { 0x166ecb373ded9cb2l,0xfd14c7073f653d3el,0x105d049b92aec425l, + 0x7f657e4909a42e11l }, + 0 }, + /* 23 << 240 */ + { { 0xea6490076a159594l,0x3e424d6b1f97ce52l,0xac6df30a185e8ccbl, + 0xad56ec80517747bfl }, + { 0xf0935ccf4391fe93l,0x866b260f03811d40l,0x792047b99f7b9abel, + 0xb1600bc88ee42d84l }, + 0 }, + /* 25 << 240 */ + { { 0x2d97b3db7768a85fl,0x2b78f6334287e038l,0x86c947676f892bb1l, + 0x920bfb1ac0a9c200l }, + { 0x4292f6ec332041b2l,0xa30bb937c9989d54l,0x39f941ebc6d5879el, + 0x76a450fcdfdbb187l }, + 0 }, + /* 27 << 240 */ + { { 0x31256089ee430db6l,0xaece9bd8f6836f56l,0x484cfc4bfb85a046l, + 0xee1e3e2c1599b2b9l }, + { 0x7e3c38903d122eafl,0xaa940ce0c770556cl,0x4802d6631b08fae8l, + 0xb08a85807f69f8bal }, + 0 }, + /* 28 << 240 */ + { { 0x70ed0a0405411eael,0x60deb08f16494c66l,0x8cf20fc6133797bbl, + 0x3e30f4f50c6bc310l }, + { 0x1a677c29749c46c7l,0xfe1d93f4f11e981cl,0x937303d82e3e688bl, + 0x01aef5a7a6aa9e85l }, + 0 }, + /* 29 << 240 */ + { { 0x4902f495b959b920l,0x13b0fdbdfca2d885l,0x41cbd9e7b6a2f0fal, + 0xf9bdf11056430b87l }, + { 0xd705a223954d19b9l,0x74d0fc5c972a4fdel,0xcbcbfed6912977eal, + 0x870611fdcc59a5afl }, + 0 }, + /* 31 << 240 */ + { { 0xf4f19bd04089236al,0x3b206c12313d0e0bl,0x73e70df303feaeb2l, + 0x09dba0eb9bd1efe0l }, + { 0x4c7fd532fc4e5305l,0xd792ffede93d787al,0xc72dc4e2e4245010l, + 0xe7e0d47d0466bbbdl }, + 0 }, + /* 33 << 240 */ + { { 0x549c861983e4f8bbl,0xf70133fbd8e06829l,0xc962b8e28c64e849l, + 0xad87f5b1901e4c25l }, + { 0xd005bde568a1cab5l,0x6a591acf0d2a95bal,0x728f14ce30ebcae4l, + 0x303cec99a3459b0fl }, + 0 }, + /* 34 << 240 */ + { { 0x62e62f258350e6bcl,0x5a5ea94d96adba1fl,0x36c2a2844a23c7b3l, + 0x32f50a72992f5c8bl }, + { 0x55d685204136c6afl,0x1aafd32992794f20l,0x69f5d820b59aa9bfl, + 0x218966a8570e209al }, + 0 }, + /* 35 << 240 */ + { { 0xf3204feb2f9a31fcl,0x77f33a360429f463l,0xfb9f3a5a59a1d6a7l, + 0x4445a2e93b1a78e0l }, + { 0xc77a9b6fd58e32d3l,0xa44e23c8302e6390l,0x7d8e00b4c0f7bcb0l, + 0xd2e2237b0ffa46f4l }, + 0 }, + /* 36 << 240 */ + { { 0xb3046cb13c8ea6d3l,0xf0151b5efce2f445l,0xa968e60b55e5715el, + 0x39e52662587dce61l }, + { 0xfde176e0b7de2862l,0x298d83e68e8db497l,0x1042136773641bfbl, + 0xd72ac78d36e0bb0dl }, + 0 }, + /* 37 << 240 */ + { { 0x2cabb94fff6b8340l,0xf425a35a21771acbl,0x564fec3d12c4a758l, + 0x57a61af39ba8f281l }, + { 0x5807e78c97e9a71dl,0x991d9be75b8314e6l,0x1cd90b16ec4133b9l, + 0xff043efa0f1ac621l }, + 0 }, + /* 39 << 240 */ + { { 0xea6e5527d7e58321l,0xfb95c13c04056ff1l,0x9447361f2fc4e732l, + 0x63cbc655786d0154l }, + { 0x302c0d668610fb71l,0xbf692d6920d06613l,0x8465b74b4be8355al, + 0xcc883c95c31356b7l }, + 0 }, + /* 40 << 240 */ + { { 0x4ab6e919b33eabcal,0xb58f0998a1acacbfl,0xa747e5782ddbc28fl, + 0xf9dd04ca59866cbcl }, + { 0x084c062ff7a0073fl,0x6d22acdfb577fc38l,0x0870ee08eacd907cl, + 0x710b4b266c9fcf95l }, + 0 }, + /* 41 << 240 */ + { { 0xa99546faf1c835a7l,0x1514a5a30d59f933l,0x1f6ad0f81bedd730l, + 0x24de76287b528aaal }, + { 0x4d9e7845c02fff87l,0xba74f8a942c79e67l,0x5bf5015f476e285bl, + 0x0b1a5d8b1b93b364l }, + 0 }, + /* 43 << 240 */ + { { 0x8c7c0d7ff839819fl,0xc82b819827a95965l,0xce7294d377270519l, + 0xfb508d6cad47aff7l }, + { 0xf6de15431035076al,0x697d60ac5dd465c6l,0x88d771b8a76dcd26l, + 0x8c7ce11ab10c9c44l }, + 0 }, + /* 44 << 240 */ + { { 0x215ea44a08216060l,0xccfa18a187996cf6l,0xccfb2483f7eccdd2l, + 0x07aa601ad453c66al }, + { 0xd43cf263cffee9e2l,0x230bc099718f69bfl,0xc43de21300c193e8l, + 0x94cf251799c8746fl }, + 0 }, + /* 45 << 240 */ + { { 0x4785d7f87d1320c5l,0x84bed8c3d0771dcbl,0xff28044d22254edbl, + 0x2e5992a445f71504l }, + { 0xcb92695b72bbf5cdl,0x9bcbde35c42422e5l,0x856594fd1d07ed86l, + 0x3aaf0b717716b4ffl }, + 0 }, + /* 46 << 240 */ + { { 0x3edf24f9eebed405l,0x9e3141360eccb503l,0xf7704c25b85c2bc2l, + 0x4cb7c1de9a3247eel }, + { 0x798ac8f2f0b507c5l,0x6e6217206851bbf1l,0xc0b89398c0d9ed16l, + 0xf7d5d2a09f20728fl }, + 0 }, + /* 47 << 240 */ + { { 0x7358a94a19f0ededl,0x5e08c4c3e32ccfbbl,0x84a8eeeb0089f071l, + 0xdaf0514c41fc436el }, + { 0x30fe216f310309afl,0xe72f77bd564e6fc9l,0xe7ef3bddfdc59fd5l, + 0xd199b1c9a8e1169cl }, + 0 }, + /* 48 << 240 */ + { { 0xb9dc857c5b0f7bd4l,0x6990c2c9108ea1cdl,0x84730b83b984c7a9l, + 0x552723d2eab18a78l }, + { 0x9752c2e2919ba0f9l,0x075a3bd94bf40890l,0x71e52a04a6d98212l, + 0x3fb6607a9f18a4c8l }, + 0 }, + /* 49 << 240 */ + { { 0xa0305d01e8c3214dl,0x025b3cae8d51cea3l,0xeeaf7ab239923274l, + 0x51179407c876b72cl }, + { 0xcf0241c7d4549a68l,0xffae7f4c793dab3dl,0xdfb5917b4bdf2280l, + 0xcf25c870a652e391l }, + 0 }, + /* 51 << 240 */ + { { 0xb1345466b922e1c8l,0xae42f46ab5bf8a34l,0x1e1ab6053310e604l, + 0x64093cd9b4d7a658l }, + { 0x5d3b385ab3d9242cl,0x2225b99ae56f8ec7l,0x19a8cbfc9a916e11l, + 0x11c5df831f957c03l }, + 0 }, + /* 52 << 240 */ + { { 0x09f1d04af381147bl,0x7be13628b26b345fl,0xd8371966d1c60b78l, + 0xf1743c2c5d91808fl }, + { 0x8a2966acafc71cc3l,0x0ba9702efdfc24c3l,0x60c80158e6fbb539l, + 0x58eaee49812c32f4l }, + 0 }, + /* 53 << 240 */ + { { 0x31af7f5ee89d0b84l,0xa776dada6caa110bl,0xd67b7891df6d54ddl, + 0x831613cab82b8a5cl }, + { 0x7a4eb86ef020af6dl,0x2914fd11bd795a7bl,0xc038a273fcb54a17l, + 0x6b2dc8e18219cc75l }, + 0 }, + /* 55 << 240 */ + { { 0x031fc875464ba9b5l,0xe268cf45bd812dd3l,0x443f57defbfb664al, + 0xfd1a38544e28c2fal }, + { 0xb8799782cb96515bl,0xa12d3e3f1138c95dl,0x0cc5ee117748ee57l, + 0x6ab167cf955a7dfcl }, + 0 }, + /* 57 << 240 */ + { { 0x0d54aaca4dc1c74fl,0x74af1807bf2e0d61l,0x151254f87aebe0f1l, + 0x4072f38bf6376095l }, + { 0x31ebe17a26646abfl,0xdc8cb6b40ecc1282l,0x4f6326bbbc095a66l, + 0x37dad65a0363636dl }, + 0 }, + /* 59 << 240 */ + { { 0xc851860a70f8c15al,0xb2d4555488368381l,0xbfd46e197019c7b6l, + 0xa1a9b12f6bb6f33bl }, + { 0xecfd5fe6f170c82bl,0x6d58bb52d601afc3l,0xb8b3de15fe6eb102l, + 0xad07336886a47964l }, + 0 }, + /* 60 << 240 */ + { { 0x89f514c91911840fl,0xc9fa6b504cc106bcl,0x70a97f0dfe55b4f1l, + 0xada6306be5888609l }, + { 0xa9437881c6dc8d15l,0x0fc0f5368411f3dfl,0xd26162087a913dd2l, + 0x4fe1c7c4e92848cdl }, + 0 }, + /* 61 << 240 */ + { { 0xaa18eb262e07383dl,0xb948c35c34e90f3dl,0x95e97f81d3653565l, + 0x4a821a2687b5b75dl }, + { 0x87b4d81c892db882l,0xa69e65d689f3bfadl,0xe475f532eb371cacl, + 0xd8cc23fa17194d5dl }, + 0 }, + /* 63 << 240 */ + { { 0x3fc0052ad789d484l,0xe8c67aac29324323l,0x133fd07cf54c43d3l, + 0xd4a0848fb91d4faal }, + { 0xf683ce065ea5098fl,0xe84348f9887c8a76l,0x38f8c2cf79b224b6l, + 0x327e4c534a818cb1l }, + 0 }, + /* 64 << 240 */ + { { 0xb6d92a7f3e5f9f11l,0x9afe153ad6cb3b8el,0x4d1a6dd7ddf800bdl, + 0xf6c13cc0caf17e19l }, + { 0x15f6c58e325fc3eel,0x71095400a31dc3b2l,0x168e7c07afa3d3e7l, + 0x3f8417a194c7ae2dl }, + 0 }, + /* 65 << 240 */ + { { 0x0c9e9237d5f812bcl,0xdae5b7e9595f02e5l,0x5ec1dece42b1e9a8l, + 0x506a6ef8e527a685l }, + { 0xe3049290236af251l,0x6322dd1bf81970acl,0x1459d39c516d5e61l, + 0x672f502d9455b694l }, + 0 }, + /* 71 << 240 */ + { { 0xf83788e06b228af2l,0xaafc823911f596fal,0x6d47fa592f0fcb13l, + 0x0b7af65f1c99c5d4l }, + { 0xbc4c185dca961e6fl,0xec02b09f158481a4l,0x4bbfd9f31423fdd4l, + 0x0ff44a53b619644bl }, + 0 }, + /* 77 << 240 */ + { { 0x23e255a3ea3f59d8l,0x1f4a47a8261ac30bl,0x346bf409c8faf0b3l, + 0xd13e73fbc03a226bl }, + { 0x670ddc792fe8a79bl,0x335fa172f1aac412l,0xe2347de1a5ceff20l, + 0x66e02c73381130f2l }, + 0 }, + /* 83 << 240 */ + { { 0xa6b874c51db717cdl,0x027d318ab00f160bl,0x578f89f49be791afl, + 0x659ef2f01f3b5e9bl }, + { 0xa0c593033835d84cl,0xb71e261fdb6f9a60l,0x65837c7f44b7813fl, + 0xea776163ea4bcc96l }, + 0 }, + /* 89 << 240 */ + { { 0x208234118df3f15fl,0xe0514d4694f341acl,0xdc66282d6486d704l, + 0xd5fb354ad2548389l }, + { 0xf3e98d72df273295l,0x27ded7fa50cd09fcl,0x4f486af3c5c1c169l, + 0xe51044150aa41ba3l }, + 0 }, + /* 95 << 240 */ + { { 0x66b14d296fce0aecl,0x35fe5e60c8915ceal,0x06a023b736c5da39l, + 0x0977c9f0404e932fl }, + { 0x1dd6f95db54866del,0xe5ec79359387430cl,0x98dee57b5ef42e67l, + 0x1707f01912ed3ad0l }, + 0 }, + /* 101 << 240 */ + { { 0xeb3abdedeec82495l,0x587a696e764a41c7l,0x13fdcce2add1a6a3l, + 0x299a0d43286b2162l }, + { 0x2c4e71e18131f1b4l,0x48f0e806ada3d04fl,0x91d2de80c57491b2l, + 0x1b1266236cc355cbl }, + 0 }, + /* 107 << 240 */ + { { 0xdc28afe5a6d44444l,0xb5ad8d3cfe0b947bl,0x50c6126c96ce9fb9l, + 0x5384a998d1fc7d39l }, + { 0xa43ff8898788f51cl,0x30359593a6bc7b87l,0x3e1691dccc0d019al, + 0xda0ef5ad7943abcdl }, + 0 }, + /* 113 << 240 */ + { { 0x5bc58b6f020b5cd7l,0x9098e202e103ff4el,0xc1f1a3d9f6fce7c7l, + 0xf9dc32a856090ccel }, + { 0x4c7d2520a9cc3b09l,0x98d47b5dd8c4dfcel,0xdcee788297e689b4l, + 0xe5eec71815f982b9l }, + 0 }, + /* 116 << 240 */ + { { 0xff154bb8a1e1538cl,0xb9883276f7dcfae9l,0x1ac0a4d2c1c8cba4l, + 0x511a54cc76e6b284l }, + { 0xe2da436f00011f6dl,0x4d357a190f43a8adl,0xf36899c95458655bl, + 0xe5f75c768d613ed9l }, + 0 }, + /* 119 << 240 */ + { { 0x15b4af1d93f12ef8l,0x3f4c5868fd032f88l,0x39f67a08f27d86bdl, + 0x2f551820da32db6bl }, + { 0x72fe295ac2c16214l,0x39927c381a2cf9afl,0x8dda23d6b1dc1ae7l, + 0x1209ff3ed32071d4l }, + 0 }, + /* 125 << 240 */ + { { 0x861fdceb9a3c6c6fl,0x76d7a01386778453l,0xbf8d147cd5e422cbl, + 0xd16f532e51772d19l }, + { 0x72025ee2570d02cdl,0xe8e7737be80c7664l,0x81b7d56c334a8d8fl, + 0x42477a0ff1b79308l }, + 0 }, + }, + { + /* 0 << 248 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 248 */ + { { 0xf306a3c8ee3c76cbl,0x3cf11623d32a1f6el,0xe6d5ab646863e956l, + 0x3b8a4cbe5c005c26l }, + { 0xdcd529a59ce6bb27l,0xc4afaa5204d4b16fl,0xb0624a267923798dl, + 0x85e56df66b307fabl }, + 0 }, + /* 3 << 248 */ + { { 0x896895959884aaf7l,0xb1959be307b348a6l,0x96250e573c147c87l, + 0xae0efb3add0c61f8l }, + { 0xed00745eca8c325el,0x3c911696ecff3f70l,0x73acbc65319ad41dl, + 0x7b01a020f0b1c7efl }, + 0 }, + /* 4 << 248 */ + { { 0x9910ba6b23a5d896l,0x1fe19e357fe4364el,0x6e1da8c39a33c677l, + 0x15b4488b29fd9fd0l }, + { 0x1f4392541a1f22bfl,0x920a8a70ab8163e8l,0x3fd1b24907e5658el, + 0xf2c4f79cb6ec839bl }, + 0 }, + /* 5 << 248 */ + { { 0x262143b5224c08dcl,0x2bbb09b481b50c91l,0xc16ed709aca8c84fl, + 0xa6210d9db2850ca8l }, + { 0x6d8df67a09cb54d6l,0x91eef6e0500919a4l,0x90f613810f132857l, + 0x9acede47f8d5028bl }, + 0 }, + /* 7 << 248 */ + { { 0x45e21446de673629l,0x57f7aa1e703c2d21l,0xa0e99b7f98c868c7l, + 0x4e42f66d8b641676l }, + { 0x602884dc91077896l,0xa0d690cfc2c9885bl,0xfeb4da333b9a5187l, + 0x5f789598153c87eel }, + 0 }, + /* 9 << 248 */ + { { 0xb19b1c4fca66eca8l,0xf04a20b55663de54l,0x42a29a33c223b617l, + 0x86c68d0d44827e11l }, + { 0x71f90ddeadba1206l,0xeeffb4167a6ceeeal,0x9e302fbac543e8afl, + 0xcf07f7471aa77b96l }, + 0 }, + /* 10 << 248 */ + { { 0xcf57fca29849e95bl,0x96e9793ed510053cl,0x89fa443d07d3e75el, + 0xfe2bc235e52800a0l }, + { 0x1c208b8c0ac7e740l,0xb5852a49e7222263l,0x217e4005e541e592l, + 0xee52747dc960b0e1l }, + 0 }, + /* 11 << 248 */ + { { 0x5fd7cafb475952afl,0x23a6d71954a43337l,0xa83a7523b1617941l, + 0x0b7f35d412b37dd4l }, + { 0x81ec51292ae27eafl,0x7ca92fb3318169dfl,0xc01bfd6078d0875al, + 0xcc6074e3c99c436el }, + 0 }, + /* 13 << 248 */ + { { 0x4ca6bdebf57912b8l,0x9a17577e98507b5al,0x8ed4ab7759e51dfcl, + 0x103b7b2a470f5a36l }, + { 0x0c8545ac12553321l,0xab5861a760482817l,0xf4b5f602b9b856cfl, + 0x609955787adf2e5fl }, + 0 }, + /* 15 << 248 */ + { { 0x60ce25b1ee5cb44fl,0xddcc7d182c2d7598l,0x1765a1b301847b5cl, + 0xf5d9c3635d0d23b7l }, + { 0x42ff1ba7928b65d0l,0x587ac69d6148e043l,0x3099be0dd320390bl, + 0xa7b88dfc4278329fl }, + 0 }, + /* 16 << 248 */ + { { 0x80802dc91ec34f9el,0xd8772d3533810603l,0x3f06d66c530cb4f3l, + 0x7be5ed0dc475c129l }, + { 0xcb9e3c1931e82b10l,0xc63d2857c9ff6b4cl,0xb92118c692a1b45el, + 0x0aec44147285bbcal }, + 0 }, + /* 17 << 248 */ + { { 0x7685bb9e0ba4e0b7l,0x330a7ebc5e58c29bl,0xbc1d9173e8a3797al, + 0x7c506a16ea60f86cl }, + { 0x9defb9248c099445l,0xcf1ddcc0256df210l,0x4844ce293d07e990l, + 0x92318e37e2628503l }, + 0 }, + /* 19 << 248 */ + { { 0x61acd597fdf968d7l,0x7321a8b26598c381l,0xcb86a2809f448a0cl, + 0x38534a01855df66al }, + { 0xc119ec141e29037fl,0xe23c20ad0b42ba67l,0xefb1c4e033fb4f22l, + 0xf088358f445a5032l }, + 0 }, + /* 21 << 248 */ + { { 0x2d73f5d1b8475744l,0xcc297e0a9d399b06l,0xa8c61d4038d3df06l, + 0xacc6e8651a2d27a0l }, + { 0x63dd6f6230153bf2l,0x6b23ad7bd73b83b7l,0x25382bf767ff7dcdl, + 0x7e268c8fcf7ce2d1l }, + 0 }, + /* 23 << 248 */ + { { 0x4b9161c3cb2ebef1l,0x6009716b669ed801l,0x97c65219aacefe44l, + 0xde13597d71aae4b5l }, + { 0x3a077a816141d651l,0xe1b4e80129f876eal,0x729aed6d5c00c96cl, + 0x0c6f404374cc645el }, + 0 }, + /* 25 << 248 */ + { { 0x22c51812df5a66e1l,0x1c8069c9ae7dedeal,0xcff9d86f0eea5180l, + 0x676dbd6f44235ddal }, + { 0xa53f01383db1ad42l,0xd079e571bcf19029l,0x1e37b9ecfab0cf82l, + 0x93ae35ed4844e9c4l }, + 0 }, + /* 27 << 248 */ + { { 0xdaee55a543756358l,0x0ace18d41b2d3f89l,0x3391fa36824dd7d4l, + 0x7b9963d1770e5f3fl }, + { 0xc1fb9a78c94f724dl,0x94ff86fe76c4da6bl,0xb5d928c64170609bl, + 0xc9372becfb015a9fl }, + 0 }, + /* 28 << 248 */ + { { 0x9c34b650e16e05e9l,0x965a774094e74640l,0xa3fd22fbcea3f029l, + 0x1eb6a9688f95277cl }, + { 0x2520a63d7bad84f6l,0xad917201f58f2feel,0xea92c1669b840d48l, + 0x12109c4aacef5cbdl }, + 0 }, + /* 29 << 248 */ + { { 0xd85850d0d407a252l,0x6fa3b14de63909d4l,0x2ff9f6593e0fba69l, + 0x7f9fd2a2d1b2cd0bl }, + { 0x611233d745ad896al,0xfe4211648df850f9l,0x7808832399e32983l, + 0x4b040859dee6741dl }, + 0 }, + /* 31 << 248 */ + { { 0x7dd2afd456e1ed5cl,0xd48429ec41ba4992l,0x97a02188968bab27l, + 0x09ecf813e63c4168l }, + { 0xf4ac65e77288b10cl,0x10630ab2afac7410l,0x4e3e59c3bb049e56l, + 0x25972fff40fea0b1l }, + 0 }, + /* 33 << 248 */ + { { 0xfd8363da98365c18l,0x8aa57b1a8d47bf91l,0x423dce57695f4dd6l, + 0xfccf54d4cc17f034l }, + { 0x8fdba27c3610ea51l,0xcc0a06d654306b06l,0xb97a121c389b9dfdl, + 0x7dbb90eb1ed0ca42l }, + 0 }, + /* 34 << 248 */ + { { 0xd32d7cec0094e84cl,0x862ae25e2ece8f72l,0x8644ef1cdfceb8abl, + 0x68a9969c8e225628l }, + { 0xdf209e27b3117876l,0x308a6e1882ba242bl,0xcbd09a659bf0cdb6l, + 0x79f2826cc85b9705l }, + 0 }, + /* 35 << 248 */ + { { 0x3b36b6bf8f011496l,0xea6acc1a9bcf6ef8l,0x6db132263b101f12l, + 0x4fc4e35e3b7585c3l }, + { 0x641de27556eb64c6l,0x9b2834d3f3b08519l,0xebb76a2ba1f44b40l, + 0x1b545ccd3cd31677l }, + 0 }, + /* 36 << 248 */ + { { 0xab293027aad991c1l,0x598d0bf8849be4b7l,0x8c94a21ab972da90l, + 0xada4cfdd7ecfa840l }, + { 0x93d4b9c0fbcec63al,0x7ca617a203219a34l,0x900424eb6a652a55l, + 0xaf9346e9eb8562e0l }, + 0 }, + /* 37 << 248 */ + { { 0x9681a73d2d8bc904l,0x8b5f9b317b1553bel,0xfb03b874f6bc852fl, + 0x8e658fb8cbbec8b0l }, + { 0x9b2ff17bb9e9f9d1l,0xf46e9bf3e8679854l,0x7fbb1323618ed3aal, + 0x064a1c5d714ebc3dl }, + 0 }, + /* 39 << 248 */ + { { 0xac0bdfc39f0e69dcl,0x71957386ae12f132l,0xa263ef2e6aa90b5bl, + 0xa94b152390d42976l }, + { 0xfb2d17741bcdbf7bl,0xba77b77c3a04f72fl,0xa6818ed8ec3e25a1l, + 0x2e0e01743733e251l }, + 0 }, + /* 40 << 248 */ + { { 0xc3e04d7902381461l,0xb1643ab5911bc478l,0xc92becfa390b3ef2l, + 0x54476778acd2f1b6l }, + { 0x8daa0c4d66bf3aafl,0x2bc1287b2c21c65al,0xee182910b5a13ac3l, + 0xbb04730090b0790al }, + 0 }, + /* 41 << 248 */ + { { 0x8bdd6f35a8540489l,0x788c03e5ee390d4el,0x203323c18f653017l, + 0x39953308c4bc0094l }, + { 0x6ee0857118308d0bl,0x70e9f90b450b0002l,0x191662aa8139f145l, + 0xd7c5415b62d71124l }, + 0 }, + /* 43 << 248 */ + { { 0x41b37d72b927231cl,0xca17b5429e4de13al,0x7bc03469cded2ce3l, + 0x961b0ecb4f4560f9l }, + { 0x7c5bd41b43d31fa1l,0x3ed047f643f44dc3l,0x5b02083efe1a4d14l, + 0xcc2c66ac18b330bcl }, + 0 }, + /* 44 << 248 */ + { { 0x83766947d17d4e0bl,0xc5772beefdc3a47bl,0x765a50db1a6fd0ffl, + 0x17f904ba45b0995el }, + { 0xcee643832883487el,0xf56db7f3c270aaedl,0x6738d94f46cb1fd9l, + 0xc8fa426a142fd4d5l }, + 0 }, + /* 45 << 248 */ + { { 0xc85bef5b5a78efcel,0xaf380c6b0580e41el,0x6c093256a43b8d9bl, + 0xed9d07bbea670933l }, + { 0xfdb9a295f1682c6el,0x4cc29a63532b6bb7l,0x21a918f9f8e42dd0l, + 0x9ac935ce0edacca0l }, + 0 }, + /* 46 << 248 */ + { { 0xbfe48a8ff43daf9dl,0xd7799b31b313c052l,0x46d480d77119c60el, + 0x5090d91f0b80bcb9l }, + { 0xc94c4c1e873bd7bfl,0x16e69b4f9915aa0al,0x769be02bb1d5928cl, + 0x3fdaf62162e1d85al }, + 0 }, + /* 47 << 248 */ + { { 0x03497a57371c1b5cl,0x11e4c0b3552ab6abl,0xf857061f0a169ee7l, + 0xc21c6c43e6d1bc66l }, + { 0x706283a82832be7al,0xd35b143299aba62cl,0x7f4da83de9aef62dl, + 0x2b7e5fc8723fa4e5l }, + 0 }, + /* 48 << 248 */ + { { 0xae485bb72b724759l,0x945353e1b2d4c63al,0x82159d07de7d6f2cl, + 0x389caef34ec5b109l }, + { 0x4a8ebb53db65ef14l,0x2dc2cb7edd99de43l,0x816fa3ed83f2405fl, + 0x73429bb9c14208a3l }, + 0 }, + /* 49 << 248 */ + { { 0xc086e737eb4cfa54l,0x9400e1ad3c44aad9l,0x210bba94336959b4l, + 0x08621a809106f0cal }, + { 0x2ae66096c510ee9cl,0x2ba21617fc76a895l,0xc0707f8b0c186f1el, + 0x1fe170a3ed0bfe25l }, + 0 }, + /* 51 << 248 */ + { { 0x3780fe2084759c5cl,0x716ec626b7050aa7l,0x6a43fb8b84b63bd1l, + 0xb01098a039bc449fl }, + { 0x96b3ff8ebb7daa4dl,0x2d146882654a7f01l,0x2500f701dcae6143l, + 0xc13d51d01626fd3bl }, + 0 }, + /* 52 << 248 */ + { { 0x08ed8febd56daf06l,0x8d98277b4a837f69l,0x9947c636a9b6e05al, + 0x58c8a77ac0d58abdl }, + { 0xf45496a45f121e4fl,0x16cd67c71076d3d3l,0xecbd1958e3fb0c5dl, + 0xfbe185ec38e1eb47l }, + 0 }, + /* 53 << 248 */ + { { 0x65b067eb740216e3l,0x1e19a71479db8760l,0x8d30dca18878de5al, + 0x627d03e8aa47c005l }, + { 0x096d58c0d2536c96l,0x232e6a4d69b12c2al,0x850eb8c0e7044bcel, + 0xd9cf923bef2ee9a1l }, + 0 }, + /* 55 << 248 */ + { { 0x8b301094c8eaee90l,0x9a96950b8330928fl,0x472ba105faccc3bal, + 0x00f8620e9153172al }, + { 0x019b8164303fcdf5l,0x614d5c3c41fb4c73l,0x632d98f2c5992f89l, + 0xfbeb29d790e2dea5l }, + 0 }, + /* 57 << 248 */ + { { 0xefd48b577f91d6e0l,0x8575605595bcf5d4l,0x7677b4a7bb9d891bl, + 0xdc9931e9685912c9l }, + { 0x69bca306f31a07c8l,0x3dd729534962a7f0l,0xdcea49cc9d366c2al, + 0xce664ba7dc79a57dl }, + 0 }, + /* 59 << 248 */ + { { 0x7842d547013ec3b5l,0xa2785ceb433cf990l,0x9d667e5f700ab14al, + 0x4b46f362a0f46d55l }, + { 0x152c0e80cc7a3487l,0x7f3a88cef86f5e68l,0x6f950a73f1b2a75fl, + 0x9be5b1aa51d24f3bl }, + 0 }, + /* 60 << 248 */ + { { 0xaea68626dc4ad4f4l,0x5dc516824ddbc0b6l,0xa76697bd602e9065l, + 0xbeeb3ea58c37888el }, + { 0x1ec4a2f214569113l,0xe48b820ca35f4484l,0x9fb560949ae44df2l, + 0x6ca1346292cc09fdl }, + 0 }, + /* 61 << 248 */ + { { 0x887e0b87bcdc3a36l,0x6b0d617d503dee65l,0x96bda1f6cebcb893l, + 0xdc0dd17341e20b3el }, + { 0x812fbacfa6657c11l,0x32492fcbc94a6f4bl,0x854a0bcb6a772123l, + 0x1ed573f65d463f31l }, + 0 }, + /* 63 << 248 */ + { { 0x22c7ef7bd022cc4dl,0xeec383d61e63b4bcl,0x52e0aaa06502b46fl, + 0x9224187ded5e41bfl }, + { 0x3a01f53dd26faf1cl,0x9bc4ee2e4e591d10l,0x10b7a98eea7e4c88l, + 0xe521c150e2c1beccl }, + 0 }, + /* 64 << 248 */ + { { 0xb618d590b01e6e27l,0x047e2ccde180b2dcl,0xd1b299b504aea4a9l, + 0x412c9e1e9fa403a4l }, + { 0x88d28a3679407552l,0x49c50136f332b8e3l,0x3a1b6fcce668de19l, + 0x178851bc75122b97l }, + 0 }, + /* 65 << 248 */ + { { 0x26f9b9322ed53a71l,0x0bac7348c72ef2e0l,0x7e96001da5c6faf1l, + 0x5d43f76dea00eb2dl }, + { 0x1327370f44f1c478l,0x1c83a9ac6bb964c8l,0xa3a9769f76ffbd25l, + 0xdf045fb6b04f1bddl }, + 0 }, + /* 71 << 248 */ + { { 0x4283898d556b975el,0x6e2301ffe3880361l,0xc6d3b2bbe9198077l, + 0xc4799578d21cac02l }, + { 0x11448ff8f784eb7cl,0xb775973fbb81898dl,0x4e51f061519c76b9l, + 0xaba1f3ef3cad0393l }, + 0 }, + /* 77 << 248 */ + { { 0x59d60c1c9b339830l,0x5af60a44ac32746dl,0x5ac006bc9dea8d80l, + 0x4a2a56d97f2b1180l }, + { 0x2032845a46946fc4l,0xe25b911226a3b503l,0xfed89db9a28827d3l, + 0xdd2d7e90c6b74593l }, + 0 }, + /* 83 << 248 */ + { { 0x9b047a26cda38ecfl,0x6889284f5f6cb442l,0x4d128bcb14753820l, + 0x8f9937c160eedd78l }, + { 0xe333bad751ab9127l,0xd31b01c67ace3b19l,0x0732de39d7c0b4bel, + 0xad04fa4c649e2b9bl }, + 0 }, + /* 89 << 248 */ + { { 0x02e042689d1495bal,0x95dca5a85591b5f8l,0xb10488d856f46c71l, + 0x97829baf3590000al }, + { 0xaeda5cb378c9e78al,0x3615873a7ba1c71cl,0x7c9f9f4d4333aa12l, + 0x893fab42cea8e6d3l }, + 0 }, + /* 95 << 248 */ + { { 0x9eb09fff69aaa09fl,0xf36678a926731322l,0x8be61ee1cafcabafl, + 0x77a172f558ddb763l }, + { 0x7e09dfc66471130el,0x7f8909791039771el,0x0e44071d37800b9bl, + 0x09123d27fe762d10l }, + 0 }, + /* 101 << 248 */ + { { 0xffd455a7a1b7fdd6l,0xb6162cb4dabdffael,0xf859519ec89c0e56l, + 0x07406c1b421f2846l }, + { 0x42db24ed9e96ddbbl,0x03bcae092dc5da85l,0x75099cd217aa7493l, + 0x8cd1aa4266b8740dl }, + 0 }, + /* 107 << 248 */ + { { 0xe94333d5dde7fec3l,0x894fd673745a9be3l,0xaf3d97c725683748l, + 0xeaa469a2c9ec165fl }, + { 0xc9a18decdc7abd3bl,0xf059008082717b02l,0x9816374a4fdf4300l, + 0x449d3eb74fb5a6cel }, + 0 }, + /* 113 << 248 */ + { { 0x7fc983ebd28001a6l,0xeabf5276dae74b6bl,0x50adb67d742ed0a5l, + 0x1d2ad363650e1446l }, + { 0x5a564253d122f5d0l,0x7e5aefc7e30471del,0xdc64cbb3e5dc2f2cl, + 0xe645b9fa9437be4el }, + 0 }, + /* 116 << 248 */ + { { 0x0f58cec54e27d357l,0x08dcf2b70004539el,0xb1ead64104f96709l, + 0x350fed185a914c72l }, + { 0x44f43523c5147854l,0x45f8b46f46d04ac7l,0x62c306869a449d51l, + 0xaacc0f0d9e66d9a3l }, + 0 }, + /* 119 << 248 */ + { { 0x94cb62e5bdd61b63l,0xe6ce5b5104a0ec57l,0x0461cb95f0bda8a4l, + 0xca2d6220cbadfe8fl }, + { 0x6c19bdf03c1ad65el,0x774a49bae04239d5l,0xf78cb7404a2fd59dl, + 0xaebf90ed66a09130l }, + 0 }, + /* 125 << 248 */ + { { 0x10e4074857cc8d54l,0x29985831918e3cf9l,0x3d87def9f2e344eel, + 0x8899992c68977860l }, + { 0xbdc8d73b210f3c50l,0x98aa042fa9857f46l,0x76a34daf6c71357fl, + 0x086289d3200bcb6dl }, + 0 }, + }, + { + /* 0 << 256 */ + { { 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00 }, + 1 }, + /* 1 << 256 */ + { { 0xb4e370af3aeac968l,0xe4f7fee9c4b63266l,0xb4acd4c2e3ac5664l, + 0xf8910bd2ceb38cbfl }, + { 0x1c3ae50cc9c0726el,0x15309569d97b40bfl,0x70884b7ffd5a5a1bl, + 0x3890896aef8314cdl }, + 0 }, + /* 3 << 256 */ + { { 0x996884f5903fa271l,0xe6da0fd2b9da921el,0xa6f2f2695db01e54l, + 0x1ee3e9bd6876214el }, + { 0xa26e181ce27a9497l,0x36d254e48e215e04l,0x42f32a6c252cabcal, + 0x9948148780b57614l }, + 0 }, + /* 4 << 256 */ + { { 0xab41b43a43228d83l,0x24ae1c304ad63f99l,0x8e525f1a46a51229l, + 0x14af860fcd26d2b4l }, + { 0xd6baef613f714aa1l,0xf51865adeb78795el,0xd3e21fcee6a9d694l, + 0x82ceb1dd8a37b527l }, + 0 }, + /* 5 << 256 */ + { { 0x4a665bfd2f9fd51al,0x7f2f1fe2481b97f7l,0xcad05d69ad36ce50l, + 0x314fc2a4844f4dedl }, + { 0xd5593d8cb55fc5c6l,0xe3510ce8bfb1e23dl,0xf9b7be6937453ccel, + 0xd3541b7969fae631l }, + 0 }, + /* 7 << 256 */ + { { 0x711b8a4176a9f05dl,0x06ca4e4b9011d488l,0x543bc62ba248a65el, + 0x017535ffc9290894l }, + { 0x840b84ce406851d7l,0xafa3acdf90e960b4l,0xac3394af7128fd34l, + 0x54eb4d5b2ac0f92cl }, + 0 }, + /* 9 << 256 */ + { { 0x3549a0f14df48fecl,0x6ae7b1eec239f83al,0x001dcf253eb90ff3l, + 0x02ff0f02581e90edl }, + { 0x72921d8ca103dcefl,0x2c513c3c5876293el,0xc07064ca6b68875el, + 0x7198d44653b9537cl }, + 0 }, + /* 10 << 256 */ + { { 0x58349b77685e089bl,0x1c678441219b7b8cl,0xba8da91f61e2e20dl, + 0xf9c50b8c309fd4e6l }, + { 0x99b0164996d0ef64l,0xac334ded60cdb63al,0x6b9ada19fb0bce4fl, + 0x39dc9375c7896377l }, + 0 }, + /* 11 << 256 */ + { { 0x068dda8b7e1bc126l,0x77c7c58176243a21l,0xcc8ba55c875f9dael, + 0xdde7afe2ce469f95l }, + { 0xde2a15f5e9523b85l,0x447512c6d85674ael,0x5691f89e12c6c20cl, + 0xd64ef40e0fae4513l }, + 0 }, + /* 13 << 256 */ + { { 0x10db2041c4d9eb40l,0x420eccb724f03f8al,0x64470fd17d29080el, + 0xf66c5b4416e52414l }, + { 0xa32cc70e4ca94031l,0xa67931592c8401bal,0x34f2dc29abfcc58dl, + 0x6f340f9a07325d7dl }, + 0 }, + /* 15 << 256 */ + { { 0xf55d446b060a52bbl,0x2f33cb9f02939f24l,0x0f27a01bc8953718l, + 0x362882917fcd3932l }, + { 0x7485613488ed4436l,0xcfe69e27195f089el,0xd6ab040a8ff10bd8l, + 0x9741c5472e4a1623l }, + 0 }, + /* 16 << 256 */ + { { 0xc52d8d8b6d55d6a4l,0xc4130fb3be58e8f9l,0x5f55c345e1275627l, + 0xb881a03c117042d3l }, + { 0x00a970a53238d301l,0x40d7cf2412a2c4f1l,0xace4a2f5d770ea74l, + 0x36a2e587e96940b2l }, + 0 }, + /* 17 << 256 */ + { { 0x84793d9fef12d4c8l,0x04b89b152d8a163cl,0x0fdb566fb4a87740l, + 0xf7e6e5cf9e595680l }, + { 0xbcb973e41c5cd74el,0xafcb439fe4ed49d8l,0xd5c0820aebbae8eel, + 0x23483d836f56e2a2l }, + 0 }, + /* 19 << 256 */ + { { 0x91f9b8be5e8ad115l,0xf1fd6a2e225db496l,0xf362d2cf4a444085l, + 0x033d9201eea043ebl }, + { 0x1e50c0989951a150l,0x4814fca5cfcf1f94l,0xaf3e8ef41bf82de5l, + 0xba0e2991038cff53l }, + 0 }, + /* 21 << 256 */ + { { 0x904a41ae5fc373fal,0x235556d61a6a3fc4l,0xe44eb3ea36eeb570l, + 0xa4e1b34a26ba5ca6l }, + { 0x210e7c9131180257l,0x2c28669622158b0cl,0xc78b69c783ddd341l, + 0xfc05941b294e1750l }, + 0 }, + /* 23 << 256 */ + { { 0x70666f51fc167dedl,0x47e9e289fe75b8d1l,0x8a5f59739605a03el, + 0x19876a58dd579094l }, + { 0x69a5c8cca964e426l,0xed74a652ccf20306l,0x5c93ae3cf06d31d5l, + 0x51922fa2127a8a12l }, + 0 }, + /* 25 << 256 */ + { { 0xa18e26f99e3d509el,0xbc296dd2c10814fal,0x5dadd6eeaa24e147l, + 0xdba2121a8340f12el }, + { 0xd348e7f3e245ca21l,0x1e45a42978e3eb5bl,0x252bf89c169677bbl, + 0xfb33a2564021ac55l }, + 0 }, + /* 27 << 256 */ + { { 0x30dc46586e7d72b8l,0x38df46fb0d81c3d6l,0x901bab6e10e84162l, + 0x25d7303ff7932801l }, + { 0xe781d5f37500be42l,0x9a7104c3380ff208l,0xfa801181652121a1l, + 0xef89f4f18d3bed43l }, + 0 }, + /* 28 << 256 */ + { { 0xbe4ae5683594917al,0xef7c1c47a04bf81el,0xa1dc3612046d91a0l, + 0x3eee37affb11b338l }, + { 0x7e90278fd03d8f51l,0x3045a6da4fa183c6l,0xb39e573391cd16a9l, + 0xc748a504e54e9411l }, + 0 }, + /* 29 << 256 */ + { { 0x07804331a1c6ec56l,0x25358e795b347123l,0x1ab9b39acf9432a4l, + 0x9628501d0a7881cel }, + { 0x749d58988a46d98el,0x01ea43346a17c321l,0xe2b197f9b1f9160fl, + 0x2052c7c07815f2a2l }, + 0 }, + /* 31 << 256 */ + { { 0xaa691bfbc57a1a6dl,0x06cae127d737d525l,0x5be04b2f963c7c98l, + 0x936b1f5bfc00bc4al }, + { 0x3fed4ac77eda6a34l,0xba6ca7aa2500a438l,0x1e979fa6786c2a75l, + 0xa3db26bec13f37d4l }, + 0 }, + /* 33 << 256 */ + { { 0x20afae333d7006d1l,0xdcbca6fbbda467d1l,0x2714b3827df4006cl, + 0x9abc0510c8e94549l }, + { 0x5b30a6d464c14915l,0xba91d0c35752b44fl,0x7ad9b19bbb389f1fl, + 0xe4c7aa04ef7c6e13l }, + 0 }, + /* 34 << 256 */ + { { 0x1e24a3f23d12e2b6l,0xf99df403febd6db3l,0x61e580a6b0c8e12fl, + 0x819341b7c2bfe085l }, + { 0xd53002d640828921l,0x31e1eb65cea010efl,0xc48d0cfe85b3279fl, + 0xb90de69089f35fa5l }, + 0 }, + /* 35 << 256 */ + { { 0xa3f6fd3c88ed748fl,0x6d72613af48127b9l,0xe85ed703d1e6f7e5l, + 0xbb563db449636f40l }, + { 0x23bae3c9708497bal,0x89dbff163aa65cf4l,0x70861847e6c0850al, + 0x5ef19d5d48b2e90cl }, + 0 }, + /* 36 << 256 */ + { { 0xab6a1e13107f7bacl,0x83a8bc57972091f5l,0x3c65b454f6dcba41l, + 0xd7606ff96abc431dl }, + { 0xa3af9c189bd09971l,0x6ddd3bbf276bad63l,0xd2aba9beab4f0816l, + 0x8f13063c151581edl }, + 0 }, + /* 37 << 256 */ + { { 0xf9c02364f5761b15l,0x3cfa250afd478139l,0x67d51e7416e26191l, + 0x0281bbf65eda396cl }, + { 0xbd38d4d70d1f4510l,0x2032a930edff593el,0x0ab74a0cf2ea4ad7l, + 0xb95aa9c3302498d6l }, + 0 }, + /* 39 << 256 */ + { { 0x2995495dd7da3c7cl,0x28d579d0a0bb703el,0xabec6afec8288837l, + 0x93c34dfd05ab989bl }, + { 0xcc94f05dde5ea3dfl,0xc3e3d4ef90f436e6l,0x32b3dee1cf59dc4el, + 0x5eab01635447d9d9l }, + 0 }, + /* 40 << 256 */ + { { 0xd31c5e8e2c23464el,0x5bcc382f50cfbde7l,0x6cee3d8da93c3d9bl, + 0xbee2948909ee62acl }, + { 0x4848d59c10742b84l,0x2486796fe35e9c84l,0x1a1d9570cd8f391al, + 0x839aa0913eedb743l }, + 0 }, + /* 41 << 256 */ + { { 0xae02a7ce0f83f369l,0x3b67c56097994835l,0x715def441ae4bbeal, + 0x11e764ee59f6b9eel }, + { 0x70c775051c962c3al,0x42811507d937a258l,0x06dbdceed03e6e86l, + 0x39a3a7ed48cae79el }, + 0 }, + /* 43 << 256 */ + { { 0xa32e729fb220eef8l,0x12d876baf37ac5d7l,0x9376ab45105a7f34l, + 0xb422331a4deb7275l }, + { 0x6ea07fb7686dea5el,0xba67ed3e1d8e32c9l,0x5ae52632bbc6bb9cl, + 0xdca55b86d1397575l }, + 0 }, + /* 44 << 256 */ + { { 0xd9183f74378200b1l,0xe5ea1645762f5605l,0x78b42e2f7bd6290fl, + 0xa0bdfccc07fa0899l }, + { 0x2f92ea52dacda629l,0x810b4e6c48de27e2l,0x013d8587d9d1250dl, + 0xc153d519dd5141d5l }, + 0 }, + /* 45 << 256 */ + { { 0x8f1f6cb5b8f1d719l,0xa9abc27b04e15a4el,0xc0d944a92ad42296l, + 0x69ecc877f3d2b0e5l }, + { 0xec60dbea16a5581al,0x2a0ead5fb85130d6l,0x7b3d2ebb6fddac23l, + 0x06213269ac448663l }, + 0 }, + /* 46 << 256 */ + { { 0xe1074008ac11e180l,0xdff3339c14b8f830l,0x136e22be636504f3l, + 0xb07ae98aa09c5c4cl }, + { 0x9b0a0517192168e9l,0x39e09fac86ad0865l,0x24f90705adb08d41l, + 0x9c699cc759d3be24l }, + 0 }, + /* 47 << 256 */ + { { 0xd9e16551907e36b0l,0x57f24b6caf91cb5al,0xbdb7dfdb062edae4l, + 0x99e3bffe4b85f424l }, + { 0x250774f4b2961ba7l,0xe7c0f2386d993c51l,0xcd0aae29f559b4bdl, + 0x3b12893a09a6859bl }, + 0 }, + /* 48 << 256 */ + { { 0xac177eb985ae12c3l,0x8e6cb5cc6cf76537l,0x134abb19f265f9e3l, + 0xc37309b71ba3f55dl }, + { 0x570833b4392d564bl,0xaa273a27d8c22f00l,0x9ba6b6276006773al, + 0x2156c94f0a16c092l }, + 0 }, + /* 49 << 256 */ + { { 0x2be0436b408e1258l,0xb179a2e34f47f121l,0x140b948fa42d3cfcl, + 0x96649c6700d2b4e6l }, + { 0x2bf934c7d08a4b34l,0x371c770136b472ddl,0x36297876e06adc73l, + 0x59e0d8251c3e6558l }, + 0 }, + /* 51 << 256 */ + { { 0x9368cfd304a8bc81l,0x145249d4c49e58c7l,0x8c7ac1891392be01l, + 0x58cbcb5fbc7b0903l }, + { 0x502218a1a0377b0al,0x5c17eb8afb625836l,0x845c09ef349f4d26l, + 0x15fdeb2554ddce85l }, + 0 }, + /* 52 << 256 */ + { { 0xf773535a64e8344dl,0xb8486a33d0dbabe6l,0x43c2df99b578862dl, + 0xcead29a11a39820el }, + { 0x3e5466fe63134d63l,0xc37ea88fdf43a104l,0x3b34ac34bbaacb5al, + 0x8281c240bc20be5al }, + 0 }, + /* 53 << 256 */ + { { 0x55113d5e0f8dec77l,0xdfe59f251d7e1543l,0x3b2837e0a63a849al, + 0xdfbdb8b67a5691afl }, + { 0x8dd6faf0bd4cf444l,0x28b2bdfaab128b6cl,0x44af3ee24b1098ebl, + 0xbbf328ebe50b2d02l }, + 0 }, + /* 55 << 256 */ + { { 0xf231b1f4e4e6151al,0x6ac7130413258c6al,0x6f9cb1c1a09b9f86l, + 0xbfc9291ee52ed880l }, + { 0x2a7d8230bea258a2l,0xd52a0da6baf386acl,0x5166764b3af00b7el, + 0x84792b043c985be2l }, + 0 }, + /* 57 << 256 */ + { { 0x914ca588a906d9e4l,0xb4e4e86abc27a876l,0x97e6ed27724324f2l, + 0xda7e9aa5c0b87d2cl }, + { 0xafccbe6b33a56f84l,0x69e8fd4ac892d90al,0xb47512910bb5457fl, + 0xad65e4d05cb136fal }, + 0 }, + /* 59 << 256 */ + { { 0xb09974d2fd679a1bl,0x17abc2a54578faf0l,0xe7da92828c830388l, + 0x7e455d8b0edf6146l }, + { 0xdff3b2f0c324bdb6l,0xe7a1718769f4a4f9l,0xfb4e0b3129c500a4l, + 0x1ed50799a09c5a07l }, + 0 }, + /* 60 << 256 */ + { { 0x6b669496c679d9f9l,0x3b741f36e78f0830l,0xf99d4857eb3f9e53l, + 0x41be594276f7d4ael }, + { 0x75f44d57c09a112bl,0xa5139fd68475eeb7l,0xa4560cd5c6bc9df6l, + 0x8ce2c4cf50845434l }, + 0 }, + /* 61 << 256 */ + { { 0x96b515c32b3cb0a6l,0x65836de3930d5344l,0xfb032d5b00e6d403l, + 0x2648301843c93bd1l }, + { 0xfc4525dd4b572363l,0x12b7923e7b28ab5cl,0xf376b633e22ac5e6l, + 0xd6ff6582e30b4707l }, + 0 }, + /* 63 << 256 */ + { { 0x8bdce75c83b09e07l,0x64228b19227717c4l,0xeae8f8a2dc6a1f02l, + 0x1081031be72f3b6dl }, + { 0xba0f876072c3f736l,0xde38a0c5246a28adl,0x0b116fe08596c412l, + 0xb9e37be3fa135d11l }, + 0 }, + /* 64 << 256 */ + { { 0x09800dc1b48d4168l,0xa740b282bfee87a2l,0x80c6b75dc94a547al, + 0x8cb622f0099c1985l }, + { 0xe6c789631467e05dl,0x027b658822fd3064l,0xe14735e2c2fdb68cl, + 0xfd2869947d853158l }, + 0 }, + /* 65 << 256 */ + { { 0x301916a5bbd7caf1l,0xef563fda4e2076c2l,0xccbc56088467f279l, + 0xd7de3088b8d0f1bfl }, + { 0x3d9adcce8586910dl,0x3fa3b8b9d775e0e9l,0x4b7a4a1d88136503l, + 0xc748656de4994fcel }, + 0 }, + /* 71 << 256 */ + { { 0x18cc605c2d9f8646l,0x3764f1c29e441b64l,0xb0ea7f7fc4b64ee3l, + 0xb5c22d0c042f8678l }, + { 0x3761f7f89b3057fdl,0xc85b8de64a207ce4l,0x11da715bc5c04cf7l, + 0x0cb1fa77c8e99c1fl }, + 0 }, + /* 77 << 256 */ + { { 0x35f9cfc8045dab4el,0x08a65c6771a7d720l,0xf076767b8eef1351l, + 0x5351dbff8638fbe5l }, + { 0x5aead6f7772ad54cl,0x5f6b441fafe93e69l,0xb7b83d1aeeb876b5l, + 0xbe1ba4a7cdc094d9l }, + 0 }, + /* 83 << 256 */ + { { 0x005d8f04ec0377bal,0x036b8e1ace58f05dl,0xdd6ffc6f1b28cf58l, + 0xc3d95a58e206189fl }, + { 0xcb2873c1f52e8b8cl,0xcffdb18d80142af1l,0x7cf88eb64c77ed78l, + 0xb3a3141981ef2c12l }, + 0 }, + /* 89 << 256 */ + { { 0xbb17e6f957c175b1l,0xf33abc63260a6f6dl,0x9435f2de620ddd6bl, + 0x90bdde59ff3e99eal }, + { 0x3d7875e0567b520fl,0xdd6954aa813b4978l,0x1af3dc24de7b631cl, + 0x82ddcd08934d3c97l }, + 0 }, + /* 95 << 256 */ + { { 0x7a9d60affc5ce598l,0xc6f507597c37abfdl,0xaa1b32f3a79355d0l, + 0xac581b94d7e4fcf3l }, + { 0x2669cefd139f6466l,0x560a98bb26f97570l,0x32e1c1db2837b908l, + 0x7823d7922d252781l }, + 0 }, + /* 101 << 256 */ + { { 0xea018b4cdedf9af0l,0x4b64c0a380c1d2f9l,0x527a0b1c36992c44l, + 0x72a2408142b7adffl }, + { 0x0023d10f97a502eel,0xc0f9ed067b401ac4l,0xabd1bd03d6d3b516l, + 0xc320e3e478c5d0bel }, + 0 }, + /* 107 << 256 */ + { { 0x9f5d2a6a37dd009cl,0x88c0f42ac2c3cbacl,0x3155636977552a1el, + 0xe78ec89d02f8098fl }, + { 0x276c2ad71b6eeff9l,0xf4c49a28f7f91856l,0x698a2368dc795124l, + 0x5502810de92a6c0fl }, + 0 }, + /* 113 << 256 */ + { { 0x82a5042e9f5e5192l,0x64da65fac0965a88l,0xf4c80dd56668399el, + 0x635323757e33c233l }, + { 0x5e5339b1a0048616l,0x4a17b1931c91741fl,0x65fdc7c213dcf3d0l, + 0x230181426d10c410l }, + 0 }, + /* 116 << 256 */ + { { 0x090a04220f46c635l,0xc7eac842a04de3f5l,0x45b69d4c8990d4b2l, + 0x032aeb50b8e0cdc6l }, + { 0x02ce332a4ee3f307l,0x3c80c1545043980fl,0xc774838bcbd5287cl, + 0x052661074a37d0ael }, + 0 }, + /* 119 << 256 */ + { { 0xc401b9c0f4d70fbfl,0xf82bbfde98ee47fel,0x94965118c84d91afl, + 0xdd9a67c4d3b6ad1dl }, + { 0x85c9cf1eb66a3ad4l,0x05580a0fbf5f514cl,0xf3ef0fd00218536el, + 0x1dc2cf2bd14a7ca9l }, + 0 }, + /* 125 << 256 */ + { { 0x18c83e337c1e24d4l,0x30911165563657c6l,0xf9be1af679e53083l, + 0x9b058059637753cel }, + { 0x6a37fa24e54522b9l,0xc11d38b426dbf4c4l,0xbc6738655ebd4d9al, + 0x2b40e9427fd4e2ecl }, + 0 }, + }, +}; + +/* Structure used to describe recoding of scalar multiplication. */ +typedef struct ecc_recode_sum { + /* Index into pre-computation table. */ + uint8_t i; + /* Multiplier to add point into. */ + uint8_t mul; + /* Use the negative of the point. */ + uint8_t neg; +} ecc_recode_sum; + +/* The index into pre-computation table to use. */ +static uint8_t recode_index_4_8[258] = { + 0, 1, 1, 1, 3, 4, 2, 5, 3, 2, 4, 8, 3, 9, 5, 4, + 11, 12, 6, 13, 7, 5, 8, 15, 55, 16, 9, 6, 18, 19, 7, 20, + 11, 8, 12, 23, 24, 25, 13, 9, 27, 28, 14, 29, 30, 10, 15, 33, + 11, 35, 16, 12, 37, 38, 17, 39, 18, 13, 19, 41, 42, 43, 20, 14, + 45, 46, 21, 44, 22, 15, 23, 47, 24, 43, 25, 16, 42, 48, 26, 41, + 27, 17, 28, 49, 18, 40, 29, 19, 30, 50, 31, 39, 32, 20, 33, 51, + 34, 38, 35, 21, 37, 52, 22, 36, 37, 23, 38, 53, 24, 35, 39, 25, + 34, 54, 40, 33, 55, 26, 32, 56, 27, 31, 43, 28, 30, 57, 44, 29, + 45, 29, 44, 57, 30, 28, 43, 31, 27, 56, 32, 26, 55, 33, 40, 54, + 34, 25, 39, 35, 24, 53, 38, 23, 37, 36, 22, 52, 37, 21, 35, 38, + 34, 51, 33, 20, 32, 39, 31, 50, 30, 19, 29, 40, 18, 49, 28, 17, + 27, 41, 26, 48, 42, 16, 25, 43, 24, 47, 23, 15, 22, 44, 21, 46, + 45, 14, 20, 43, 42, 41, 19, 13, 18, 39, 17, 38, 37, 12, 16, 35, + 11, 33, 15, 10, 30, 29, 14, 28, 27, 9, 13, 25, 24, 23, 12, 8, + 11, 20, 7, 19, 18, 6, 9, 16, 55, 15, 8, 5, 7, 13, 6, 12, + 11, 4, 5, 9, 3, 8, 4, 2, 3, 5, 2, 4, 3, 1, 1, 1, + 0, 1, +}; + +/* Multiple to add point into. */ +static uint8_t recode_mul_4_8[258] = { + 0, 1, 2, 3, 1, 1, 2, 1, 2, 3, 2, 1, 3, 1, 2, 3, + 1, 1, 2, 1, 2, 3, 2, 1, 2, 1, 2, 3, 1, 1, 3, 1, + 2, 3, 2, 1, 1, 1, 2, 3, 1, 1, 2, 1, 1, 3, 2, 1, + 3, 1, 2, 3, 1, 1, 2, 1, 2, 3, 2, 1, 1, 1, 2, 3, + 1, 1, 2, 3, 2, 3, 2, 1, 2, 3, 2, 3, 3, 1, 2, 3, + 2, 3, 2, 1, 3, 3, 2, 3, 2, 1, 2, 3, 2, 3, 2, 1, + 2, 3, 2, 3, 3, 1, 3, 3, 2, 3, 2, 1, 3, 3, 2, 3, + 3, 1, 2, 3, 1, 3, 3, 1, 3, 3, 2, 3, 3, 1, 2, 3, + 2, 3, 2, 1, 3, 3, 2, 3, 3, 1, 3, 3, 1, 3, 2, 1, + 3, 3, 2, 3, 3, 1, 2, 3, 2, 3, 3, 1, 3, 3, 2, 3, + 2, 1, 2, 3, 2, 3, 2, 1, 2, 3, 2, 3, 3, 1, 2, 3, + 2, 3, 2, 1, 3, 3, 2, 3, 2, 1, 2, 3, 2, 3, 2, 1, + 1, 3, 2, 1, 1, 1, 2, 3, 2, 1, 2, 1, 1, 3, 2, 1, + 3, 1, 2, 3, 1, 1, 2, 1, 1, 3, 2, 1, 1, 1, 2, 3, + 2, 1, 3, 1, 1, 3, 2, 1, 2, 1, 2, 3, 2, 1, 2, 1, + 1, 3, 2, 1, 3, 1, 2, 3, 2, 1, 2, 1, 1, 3, 2, 1, + 0, 1, +}; + +/* Whether to negate y-ordinate. */ +static uint8_t recode_neg_4_8[258] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, + 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, + 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, + 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, + 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, + 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, + 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, + 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 0, 0, +}; + +/* Recode the scalar for multiplication using pre-computed values, multipliers + * and subtraction. + * + * k Scalar to multiply by. + * v Vector of operations to peform. + */ +static void sp_256_ecc_recode_sum_8_4(sp_digit* k, ecc_recode_sum* v) +{ + int i, j; + uint16_t y; + int carry = 0; + int o; + sp_digit n; + + j = 0; + n = k[j]; + o = 0; + for (i=0; i<33; i++) { + y = n; + if (o + 8 < 64) { + y &= 0xff; + n >>= 8; + o += 8; + } + else if (o + 8 == 64) { + n >>= 8; + if (++j < 4) + n = k[j]; + o = 0; + } + else if (++j < 4) { + n = k[j]; + y |= (n << (64 - o)) & 0xff; + o -= 56; + n >>= o; + } + + y += carry; + v[i].i = recode_index_4_8[y]; + v[i].mul = recode_mul_4_8[y]; + v[i].neg = recode_neg_4_8[y]; + carry = (y >> 8) + v[i].neg; + } +} + +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_base_4(sp_point* r, sp_digit* k, int map, + void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point td[4]; + sp_point pd; + sp_digit tmpd[2 * 4 * 5]; +#endif + sp_point* t; + sp_point* p; + sp_digit* tmp; + sp_digit* negy; + int i; + ecc_recode_sum v[33]; + int err; + + (void)heap; + + err = sp_ecc_point_new(heap, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + t = (sp_point*)XMALLOC(sizeof(sp_point) * 4, heap, DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 5, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; +#else + t = td; + tmp = tmpd; +#endif + negy = tmp; + + if (err == MP_OKAY) { + sp_256_ecc_recode_sum_8_4(k, v); + + XMEMCPY(p->z, p256_norm_mod, sizeof(p256_norm_mod)); + XMEMSET(t, 0, sizeof(sp_point) * 4); + for (i=0; i<4; i++) { + XMEMCPY(t[i].z, p256_norm_mod, sizeof(p256_norm_mod)); + t[i].infinity = 1; + } + + i = 32; + XMEMCPY(t[v[i].mul].x, p256_table[i][v[i].i].x, + sizeof(p256_table[i]->x)); + XMEMCPY(t[v[i].mul].y, p256_table[i][v[i].i].y, + sizeof(p256_table[i]->y)); + t[v[i].mul].infinity = p256_table[i][v[i].i].infinity; + for (--i; i>=0; i--) { + XMEMCPY(p->x, p256_table[i][v[i].i].x, sizeof(p256_table[i]->x)); + XMEMCPY(p->y, p256_table[i][v[i].i].y, sizeof(p256_table[i]->y)); + p->infinity = p256_table[i][v[i].i].infinity; + sp_256_sub_4(negy, p256_mod, p->y); + sp_256_cond_copy_4(p->y, negy, (sp_digit)0 - v[i].neg); + sp_256_proj_point_add_qz1_4(&t[v[i].mul], &t[v[i].mul], p, + tmp); + } + sp_256_proj_point_add_4(&t[2], &t[2], &t[3], tmp); + sp_256_proj_point_add_4(&t[1], &t[1], &t[3], tmp); + sp_256_proj_point_dbl_4(&t[2], &t[2], tmp); + sp_256_proj_point_add_4(&t[1], &t[1], &t[2], tmp); + + if (map) + sp_256_map_4(r, &t[1], tmp); + else + XMEMCPY(r, &t[1], sizeof(sp_point)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_point) * 4); + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } + if (tmp != NULL) { + XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 4 * 5); + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + } +#else + ForceZero(tmpd, sizeof(tmpd)); + ForceZero(td, sizeof(td)); +#endif + sp_ecc_point_free(p, 0, heap); + + return MP_OKAY; +} + +#ifdef HAVE_INTEL_AVX2 +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * r Resulting point. + * k Scalar to multiply by. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +static int sp_256_ecc_mulmod_base_avx2_4(sp_point* r, sp_digit* k, int map, + void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point td[4]; + sp_point pd; + sp_digit tmpd[2 * 4 * 5]; +#endif + sp_point* t; + sp_point* p; + sp_digit* tmp; + sp_digit* negy; + int i; + ecc_recode_sum v[33]; + int err; + + (void)heap; + + err = sp_ecc_point_new(heap, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + t = (sp_point*)XMALLOC(sizeof(sp_point) * 4, heap, DYNAMIC_TYPE_ECC); + if (t == NULL) + err = MEMORY_E; + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 5, heap, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; +#else + t = td; + tmp = tmpd; +#endif + negy = tmp; + + if (err == MP_OKAY) { + sp_256_ecc_recode_sum_8_4(k, v); + + XMEMCPY(p->z, p256_norm_mod, sizeof(p256_norm_mod)); + XMEMSET(t, 0, sizeof(sp_point) * 4); + for (i=0; i<4; i++) { + XMEMCPY(t[i].z, p256_norm_mod, sizeof(p256_norm_mod)); + t[i].infinity = 1; + } + + i = 32; + XMEMCPY(t[v[i].mul].x, p256_table[i][v[i].i].x, + sizeof(p256_table[i]->x)); + XMEMCPY(t[v[i].mul].y, p256_table[i][v[i].i].y, + sizeof(p256_table[i]->y)); + t[v[i].mul].infinity = p256_table[i][v[i].i].infinity; + for (--i; i>=0; i--) { + XMEMCPY(p->x, p256_table[i][v[i].i].x, sizeof(p256_table[i]->x)); + XMEMCPY(p->y, p256_table[i][v[i].i].y, sizeof(p256_table[i]->y)); + p->infinity = p256_table[i][v[i].i].infinity; + sp_256_sub_4(negy, p256_mod, p->y); + sp_256_cond_copy_4(p->y, negy, (sp_digit)0 - v[i].neg); + sp_256_proj_point_add_qz1_avx2_4(&t[v[i].mul], &t[v[i].mul], p, + tmp); + } + sp_256_proj_point_add_avx2_4(&t[2], &t[2], &t[3], tmp); + sp_256_proj_point_add_avx2_4(&t[1], &t[1], &t[3], tmp); + sp_256_proj_point_dbl_avx2_4(&t[2], &t[2], tmp); + sp_256_proj_point_add_avx2_4(&t[1], &t[1], &t[2], tmp); + + if (map) + sp_256_map_avx2_4(r, &t[1], tmp); + else + XMEMCPY(r, &t[1], sizeof(sp_point)); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (t != NULL) { + XMEMSET(t, 0, sizeof(sp_point) * 4); + XFREE(t, heap, DYNAMIC_TYPE_ECC); + } + if (tmp != NULL) { + XMEMSET(tmp, 0, sizeof(sp_digit) * 2 * 4 * 5); + XFREE(tmp, heap, DYNAMIC_TYPE_ECC); + } +#else + ForceZero(tmpd, sizeof(tmpd)); + ForceZero(td, sizeof(td)); +#endif + sp_ecc_point_free(p, 0, heap); + + return MP_OKAY; +} + +#endif /* HAVE_INTEL_AVX2 */ +#endif /* WOLFSSL_SP_SMALL */ +/* Multiply the base point of P256 by the scalar and return the result. + * If map is true then convert result to affine co-ordinates. + * + * km Scalar to multiply by. + * r Resulting point. + * map Indicates whether to convert result to affine. + * heap Heap to use for allocation. + * returns MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_mulmod_base_256(mp_int* km, ecc_point* r, int map, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point p; + sp_digit kd[4]; +#endif + sp_point* point; + sp_digit* k = NULL; + int err = MP_OKAY; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + err = sp_ecc_point_new(heap, p, point); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + if (err == MP_OKAY) { + sp_256_from_mp(k, 4, km); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_256_ecc_mulmod_base_avx2_4(point, k, map, heap); + else +#endif + err = sp_256_ecc_mulmod_base_4(point, k, map, heap); + } + if (err == MP_OKAY) + err = sp_256_point_to_ecc_point_4(point, r); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(point, 0, heap); + + return err; +} + +#if defined(WOLFSSL_VALIDATE_ECC_KEYGEN) || defined(HAVE_ECC_SIGN) || \ + defined(HAVE_ECC_VERIFY) +/* Returns 1 if the number of zero. + * Implementation is constant time. + * + * a Number to check. + * returns 1 if the number is zero and 0 otherwise. + */ +static int sp_256_iszero_4(const sp_digit* a) +{ + return (a[0] | a[1] | a[2] | a[3]) == 0; +} + +#endif /* WOLFSSL_VALIDATE_ECC_KEYGEN || HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +extern void sp_256_add_one_4(sp_digit* a); +/* Read big endian unsigned byte aray into r. + * + * r A single precision integer. + * a Byte array. + * n Number of bytes in array to read. + */ +static void sp_256_from_bin(sp_digit* r, int max, const byte* a, int n) +{ + int i, j = 0, s = 0; + + r[0] = 0; + for (i = n-1; i >= 0; i--) { + r[j] |= ((sp_digit)a[i]) << s; + if (s >= 56) { + r[j] &= 0xffffffffffffffffl; + s = 64 - s; + if (j + 1 >= max) + break; + r[++j] = a[i] >> s; + s = 8 - s; + } + else + s += 8; + } + + for (j++; j < max; j++) + r[j] = 0; +} + +/* Generates a scalar that is in the range 1..order-1. + * + * rng Random number generator. + * k Scalar value. + * returns RNG failures, MEMORY_E when memory allocation fails and + * MP_OKAY on success. + */ +static int sp_256_ecc_gen_k_4(WC_RNG* rng, sp_digit* k) +{ + int err; + byte buf[32]; + + do { + err = wc_RNG_GenerateBlock(rng, buf, sizeof(buf)); + if (err == 0) { + sp_256_from_bin(k, 4, buf, sizeof(buf)); + if (sp_256_cmp_4(k, p256_order2) < 0) { + sp_256_add_one_4(k); + break; + } + } + } + while (err == 0); + + return err; +} + +/* Makes a random EC key pair. + * + * rng Random number generator. + * priv Generated private value. + * pub Generated public point. + * heap Heap to use for allocation. + * returns ECC_INF_E when the point does not have the correct order, RNG + * failures, MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point p; + sp_digit kd[4]; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point inf; +#endif +#endif + sp_point* point; + sp_digit* k = NULL; +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_point* infinity; +#endif + int err; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + (void)heap; + + err = sp_ecc_point_new(heap, p, point); +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, inf, infinity); +#endif +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + + if (err == MP_OKAY) + err = sp_256_ecc_gen_k_4(rng, k); + if (err == MP_OKAY) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_256_ecc_mulmod_base_avx2_4(point, k, 1, NULL); + else +#endif + err = sp_256_ecc_mulmod_base_4(point, k, 1, NULL); + } + +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + if (err == MP_OKAY) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + err = sp_256_ecc_mulmod_avx2_4(infinity, point, p256_order, 1, + NULL); + } + else +#endif + err = sp_256_ecc_mulmod_4(infinity, point, p256_order, 1, NULL); + } + if (err == MP_OKAY) { + if (!sp_256_iszero_4(point->x) || !sp_256_iszero_4(point->y)) + err = ECC_INF_E; + } +#endif + + if (err == MP_OKAY) + err = sp_256_to_mp(k, priv); + if (err == MP_OKAY) + err = sp_256_point_to_ecc_point_4(point, pub); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); +#endif +#ifdef WOLFSSL_VALIDATE_ECC_KEYGEN + sp_ecc_point_free(infinity, 1, heap); +#endif + sp_ecc_point_free(point, 1, heap); + + return err; +} + +#ifdef HAVE_ECC_DHE +/* Write r as big endian to byte aray. + * Fixed length number of bytes written: 32 + * + * r A single precision integer. + * a Byte array. + */ +static void sp_256_to_bin(sp_digit* r, byte* a) +{ + int i, j, s = 0, b; + + j = 256 / 8 - 1; + a[j] = 0; + for (i=0; i<4 && j>=0; i++) { + b = 0; + a[j--] |= r[i] << s; b += 8 - s; + if (j < 0) + break; + while (b < 64) { + a[j--] = r[i] >> b; b += 8; + if (j < 0) + break; + } + s = 8 - (b - 64); + if (j >= 0) + a[j] = 0; + if (s != 0) + j++; + } +} + +/* Multiply the point by the scalar and serialize the X ordinate. + * The number is 0 padded to maximum size on output. + * + * priv Scalar to multiply the point by. + * pub Point to multiply. + * out Buffer to hold X ordinate. + * outLen On entry, size of the buffer in bytes. + * On exit, length of data in buffer in bytes. + * heap Heap to use for allocation. + * returns BUFFER_E if the buffer is to small for output size, + * MEMORY_E when memory allocation fails and MP_OKAY on success. + */ +int sp_ecc_secret_gen_256(mp_int* priv, ecc_point* pub, byte* out, + word32* outLen, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point p; + sp_digit kd[4]; +#endif + sp_point* point = NULL; + sp_digit* k = NULL; + int err = MP_OKAY; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + if (*outLen < 32) + err = BUFFER_E; + + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, p, point); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + k = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4, heap, + DYNAMIC_TYPE_ECC); + if (k == NULL) + err = MEMORY_E; + } +#else + k = kd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(k, 4, priv); + sp_256_point_from_ecc_point_4(point, pub); +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_256_ecc_mulmod_avx2_4(point, point, k, 1, heap); + else +#endif + err = sp_256_ecc_mulmod_4(point, point, k, 1, heap); + } + if (err == MP_OKAY) { + sp_256_to_bin(point->x, out); + *outLen = 32; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (k != NULL) + XFREE(k, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(point, 0, heap); + + return err; +} +#endif /* HAVE_ECC_DHE */ + +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +extern sp_digit sp_256_add_4(sp_digit* r, const sp_digit* a, const sp_digit* b); +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +extern void sp_256_mul_4(sp_digit* r, const sp_digit* a, const sp_digit* b); +#ifdef HAVE_INTEL_AVX2 +extern void sp_256_mul_avx2_4(sp_digit* r, const sp_digit* a, const sp_digit* b); +#endif /* HAVE_INTEL_AVX2 */ +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +extern sp_digit sp_256_sub_in_place_4(sp_digit* a, const sp_digit* b); +extern void sp_256_mul_d_4(sp_digit* r, const sp_digit* a, const sp_digit b); +extern void sp_256_mul_d_avx2_4(sp_digit* r, const sp_digit* a, const sp_digit b); +/* Divide the double width number (d1|d0) by the dividend. (d1|d0 / div) + * + * d1 The high order half of the number to divide. + * d0 The low order half of the number to divide. + * div The dividend. + * returns the result of the division. + */ +static WC_INLINE sp_digit div_256_word_4(sp_digit d1, sp_digit d0, + sp_digit div) +{ + register sp_digit r asm("rax"); + __asm__ __volatile__ ( + "divq %3" + : "=a" (r) + : "d" (d1), "a" (d0), "r" (div) + : + ); + return r; +} +/* AND m into each word of a and store in r. + * + * r A single precision integer. + * a A single precision integer. + * m Mask to AND against each digit. + */ +static void sp_256_mask_4(sp_digit* r, sp_digit* a, sp_digit m) +{ +#ifdef WOLFSSL_SP_SMALL + int i; + + for (i=0; i<4; i++) + r[i] = a[i] & m; +#else + r[0] = a[0] & m; + r[1] = a[1] & m; + r[2] = a[2] & m; + r[3] = a[3] & m; +#endif +} + +/* Divide d in a and put remainder into r (m*d + r = a) + * m is not calculated as it is not needed at this time. + * + * a Nmber to be divided. + * d Number to divide with. + * m Multiplier result. + * r Remainder from the division. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_256_div_4(sp_digit* a, sp_digit* d, sp_digit* m, + sp_digit* r) +{ + sp_digit t1[8], t2[5]; + sp_digit div, r1; + int i; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + (void)m; + + div = d[3]; + XMEMCPY(t1, a, sizeof(*t1) * 2 * 4); + for (i=3; i>=0; i--) { + r1 = div_256_word_4(t1[4 + i], t1[4 + i - 1], div); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_256_mul_d_avx2_4(t2, d, r1); + else +#endif + sp_256_mul_d_4(t2, d, r1); + t1[4 + i] += sp_256_sub_in_place_4(&t1[i], t2); + t1[4 + i] -= t2[4]; + sp_256_mask_4(t2, d, t1[4 + i]); + t1[4 + i] += sp_256_add_4(&t1[i], &t1[i], t2); + sp_256_mask_4(t2, d, t1[4 + i]); + t1[4 + i] += sp_256_add_4(&t1[i], &t1[i], t2); + } + + r1 = sp_256_cmp_4(t1, d) >= 0; + sp_256_cond_sub_4(r, t1, d, (sp_digit)0 - r1); + + return MP_OKAY; +} + +/* Reduce a modulo m into r. (r = a mod m) + * + * r A single precision number that is the reduced result. + * a A single precision number that is to be reduced. + * m A single precision number that is the modulus to reduce with. + * returns MP_OKAY indicating success. + */ +static WC_INLINE int sp_256_mod_4(sp_digit* r, sp_digit* a, sp_digit* m) +{ + return sp_256_div_4(a, m, NULL, r); +} + +#endif +#if defined(HAVE_ECC_SIGN) || defined(HAVE_ECC_VERIFY) +extern void sp_256_sqr_4(sp_digit* r, const sp_digit* a); +#ifdef WOLFSSL_SP_SMALL +/* Order-2 for the P256 curve. */ +static const uint64_t p256_order_2[4] = { + 0xf3b9cac2fc63254f,0xbce6faada7179e84,0xffffffffffffffff, + 0xffffffff00000000 +}; +#else +/* The low half of the order-2 of the P256 curve. */ +static const uint64_t p256_order_low[2] = { + 0xf3b9cac2fc63254f,0xbce6faada7179e84 +}; +#endif /* WOLFSSL_SP_SMALL */ + +/* Multiply two number mod the order of P256 curve. (r = a * b mod order) + * + * r Result of the multiplication. + * a First operand of the multiplication. + * b Second operand of the multiplication. + */ +static void sp_256_mont_mul_order_4(sp_digit* r, sp_digit* a, sp_digit* b) +{ + sp_256_mul_4(r, a, b); + sp_256_mont_reduce_order_4(r, p256_order, p256_mp_order); +} + +/* Square number mod the order of P256 curve. (r = a * a mod order) + * + * r Result of the squaring. + * a Number to square. + */ +static void sp_256_mont_sqr_order_4(sp_digit* r, sp_digit* a) +{ + sp_256_sqr_4(r, a); + sp_256_mont_reduce_order_4(r, p256_order, p256_mp_order); +} + +#ifndef WOLFSSL_SP_SMALL +/* Square number mod the order of P256 curve a number of times. + * (r = a ^ n mod order) + * + * r Result of the squaring. + * a Number to square. + */ +static void sp_256_mont_sqr_n_order_4(sp_digit* r, sp_digit* a, int n) +{ + int i; + + sp_256_mont_sqr_order_4(r, a); + for (i=1; i=0; i--) { + sp_256_mont_sqr_order_4(t, t); + if (p256_order_2[i / 64] & ((sp_digit)1 << (i % 64))) + sp_256_mont_mul_order_4(t, t, a); + } + XMEMCPY(r, t, sizeof(sp_digit) * 4); +#else + sp_digit* t = td; + sp_digit* t2 = td + 2 * 4; + sp_digit* t3 = td + 4 * 4; + int i; + + /* t = a^2 */ + sp_256_mont_sqr_order_4(t, a); + /* t = a^3 = t * a */ + sp_256_mont_mul_order_4(t, t, a); + /* t2= a^c = t ^ 2 ^ 2 */ + sp_256_mont_sqr_n_order_4(t2, t, 2); + /* t3= a^f = t2 * t */ + sp_256_mont_mul_order_4(t3, t2, t); + /* t2= a^f0 = t3 ^ 2 ^ 4 */ + sp_256_mont_sqr_n_order_4(t2, t3, 4); + /* t = a^ff = t2 * t3 */ + sp_256_mont_mul_order_4(t, t2, t3); + /* t3= a^ff00 = t ^ 2 ^ 8 */ + sp_256_mont_sqr_n_order_4(t2, t, 8); + /* t = a^ffff = t2 * t */ + sp_256_mont_mul_order_4(t, t2, t); + /* t2= a^ffff0000 = t ^ 2 ^ 16 */ + sp_256_mont_sqr_n_order_4(t2, t, 16); + /* t = a^ffffffff = t2 * t */ + sp_256_mont_mul_order_4(t, t2, t); + /* t2= a^ffffffff0000000000000000 = t ^ 2 ^ 64 */ + sp_256_mont_sqr_n_order_4(t2, t, 64); + /* t2= a^ffffffff00000000ffffffff = t2 * t */ + sp_256_mont_mul_order_4(t2, t2, t); + /* t2= a^ffffffff00000000ffffffff00000000 = t2 ^ 2 ^ 32 */ + sp_256_mont_sqr_n_order_4(t2, t2, 32); + /* t2= a^ffffffff00000000ffffffffffffffff = t2 * t */ + sp_256_mont_mul_order_4(t2, t2, t); + /* t2= a^ffffffff00000000ffffffffffffffffbce6 */ + for (i=127; i>=112; i--) { + sp_256_mont_sqr_order_4(t2, t2); + if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64))) + sp_256_mont_mul_order_4(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6f */ + sp_256_mont_sqr_n_order_4(t2, t2, 4); + sp_256_mont_mul_order_4(t2, t2, t3); + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84 */ + for (i=107; i>=64; i--) { + sp_256_mont_sqr_order_4(t2, t2); + if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64))) + sp_256_mont_mul_order_4(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f */ + sp_256_mont_sqr_n_order_4(t2, t2, 4); + sp_256_mont_mul_order_4(t2, t2, t3); + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2 */ + for (i=59; i>=32; i--) { + sp_256_mont_sqr_order_4(t2, t2); + if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64))) + sp_256_mont_mul_order_4(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2f */ + sp_256_mont_sqr_n_order_4(t2, t2, 4); + sp_256_mont_mul_order_4(t2, t2, t3); + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254 */ + for (i=27; i>=0; i--) { + sp_256_mont_sqr_order_4(t2, t2); + if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64))) + sp_256_mont_mul_order_4(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632540 */ + sp_256_mont_sqr_n_order_4(t2, t2, 4); + /* r = a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f */ + sp_256_mont_mul_order_4(r, t2, t3); +#endif /* WOLFSSL_SP_SMALL */ +} + +#ifdef HAVE_INTEL_AVX2 +extern void sp_256_sqr_avx2_4(sp_digit* r, const sp_digit* a); +#define sp_256_mont_reduce_order_avx2_4 sp_256_mont_reduce_avx2_4 + +extern void sp_256_mont_reduce_avx2_4(sp_digit* a, sp_digit* m, sp_digit mp); +/* Multiply two number mod the order of P256 curve. (r = a * b mod order) + * + * r Result of the multiplication. + * a First operand of the multiplication. + * b Second operand of the multiplication. + */ +static void sp_256_mont_mul_order_avx2_4(sp_digit* r, sp_digit* a, sp_digit* b) +{ + sp_256_mul_avx2_4(r, a, b); + sp_256_mont_reduce_order_avx2_4(r, p256_order, p256_mp_order); +} + +/* Square number mod the order of P256 curve. (r = a * a mod order) + * + * r Result of the squaring. + * a Number to square. + */ +static void sp_256_mont_sqr_order_avx2_4(sp_digit* r, sp_digit* a) +{ + sp_256_sqr_avx2_4(r, a); + sp_256_mont_reduce_order_avx2_4(r, p256_order, p256_mp_order); +} + +#ifndef WOLFSSL_SP_SMALL +/* Square number mod the order of P256 curve a number of times. + * (r = a ^ n mod order) + * + * r Result of the squaring. + * a Number to square. + */ +static void sp_256_mont_sqr_n_order_avx2_4(sp_digit* r, sp_digit* a, int n) +{ + int i; + + sp_256_mont_sqr_order_avx2_4(r, a); + for (i=1; i=0; i--) { + sp_256_mont_sqr_order_avx2_4(t, t); + if (p256_order_2[i / 64] & ((sp_digit)1 << (i % 64))) + sp_256_mont_mul_order_avx2_4(t, t, a); + } + XMEMCPY(r, t, sizeof(sp_digit) * 4); +#else + sp_digit* t = td; + sp_digit* t2 = td + 2 * 4; + sp_digit* t3 = td + 4 * 4; + int i; + + /* t = a^2 */ + sp_256_mont_sqr_order_avx2_4(t, a); + /* t = a^3 = t * a */ + sp_256_mont_mul_order_avx2_4(t, t, a); + /* t2= a^c = t ^ 2 ^ 2 */ + sp_256_mont_sqr_n_order_avx2_4(t2, t, 2); + /* t3= a^f = t2 * t */ + sp_256_mont_mul_order_avx2_4(t3, t2, t); + /* t2= a^f0 = t3 ^ 2 ^ 4 */ + sp_256_mont_sqr_n_order_avx2_4(t2, t3, 4); + /* t = a^ff = t2 * t3 */ + sp_256_mont_mul_order_avx2_4(t, t2, t3); + /* t3= a^ff00 = t ^ 2 ^ 8 */ + sp_256_mont_sqr_n_order_avx2_4(t2, t, 8); + /* t = a^ffff = t2 * t */ + sp_256_mont_mul_order_avx2_4(t, t2, t); + /* t2= a^ffff0000 = t ^ 2 ^ 16 */ + sp_256_mont_sqr_n_order_avx2_4(t2, t, 16); + /* t = a^ffffffff = t2 * t */ + sp_256_mont_mul_order_avx2_4(t, t2, t); + /* t2= a^ffffffff0000000000000000 = t ^ 2 ^ 64 */ + sp_256_mont_sqr_n_order_avx2_4(t2, t, 64); + /* t2= a^ffffffff00000000ffffffff = t2 * t */ + sp_256_mont_mul_order_avx2_4(t2, t2, t); + /* t2= a^ffffffff00000000ffffffff00000000 = t2 ^ 2 ^ 32 */ + sp_256_mont_sqr_n_order_avx2_4(t2, t2, 32); + /* t2= a^ffffffff00000000ffffffffffffffff = t2 * t */ + sp_256_mont_mul_order_avx2_4(t2, t2, t); + /* t2= a^ffffffff00000000ffffffffffffffffbce6 */ + for (i=127; i>=112; i--) { + sp_256_mont_sqr_order_avx2_4(t2, t2); + if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64))) + sp_256_mont_mul_order_avx2_4(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6f */ + sp_256_mont_sqr_n_order_avx2_4(t2, t2, 4); + sp_256_mont_mul_order_avx2_4(t2, t2, t3); + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84 */ + for (i=107; i>=64; i--) { + sp_256_mont_sqr_order_avx2_4(t2, t2); + if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64))) + sp_256_mont_mul_order_avx2_4(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f */ + sp_256_mont_sqr_n_order_avx2_4(t2, t2, 4); + sp_256_mont_mul_order_avx2_4(t2, t2, t3); + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2 */ + for (i=59; i>=32; i--) { + sp_256_mont_sqr_order_avx2_4(t2, t2); + if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64))) + sp_256_mont_mul_order_avx2_4(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2f */ + sp_256_mont_sqr_n_order_avx2_4(t2, t2, 4); + sp_256_mont_mul_order_avx2_4(t2, t2, t3); + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254 */ + for (i=27; i>=0; i--) { + sp_256_mont_sqr_order_avx2_4(t2, t2); + if (p256_order_low[i / 64] & ((sp_digit)1 << (i % 64))) + sp_256_mont_mul_order_avx2_4(t2, t2, a); + } + /* t2= a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632540 */ + sp_256_mont_sqr_n_order_avx2_4(t2, t2, 4); + /* r = a^ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f */ + sp_256_mont_mul_order_avx2_4(r, t2, t3); +#endif /* WOLFSSL_SP_SMALL */ +} + +#endif /* HAVE_INTEL_AVX2 */ +#endif /* HAVE_ECC_SIGN || HAVE_ECC_VERIFY */ +#ifdef HAVE_ECC_SIGN +#ifndef SP_ECC_MAX_SIG_GEN +#define SP_ECC_MAX_SIG_GEN 64 +#endif + +/* Sign the hash using the private key. + * e = [hash, 256 bits] from binary + * r = (k.G)->x mod order + * s = (r * x + e) / k mod order + * The hash is truncated to the first 256 bits. + * + * hash Hash to sign. + * hashLen Length of the hash data. + * rng Random number generator. + * priv Private part of key - scalar. + * rm First part of result as an mp_int. + * sm Sirst part of result as an mp_int. + * heap Heap to use for allocation. + * returns RNG failures, MEMORY_E when memory allocation fails and + * MP_OKAY on success. + */ +int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, + mp_int* rm, mp_int* sm, void* heap) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d = NULL; +#else + sp_digit ed[2*4]; + sp_digit xd[2*4]; + sp_digit kd[2*4]; + sp_digit rd[2*4]; + sp_digit td[3 * 2*4]; + sp_point p; +#endif + sp_digit* e = NULL; + sp_digit* x = NULL; + sp_digit* k = NULL; + sp_digit* r = NULL; + sp_digit* tmp = NULL; + sp_point* point = NULL; + sp_digit carry; + sp_digit* s; + sp_digit* kInv; + int err = MP_OKAY; + int64_t c; + int i; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + (void)heap; + + err = sp_ecc_point_new(heap, p, point); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 7 * 2 * 4, heap, + DYNAMIC_TYPE_ECC); + if (d != NULL) { + e = d + 0 * 4; + x = d + 2 * 4; + k = d + 4 * 4; + r = d + 6 * 4; + tmp = d + 8 * 4; + } + else + err = MEMORY_E; + } +#else + e = ed; + x = xd; + k = kd; + r = rd; + tmp = td; +#endif + s = e; + kInv = k; + + if (err == MP_OKAY) { + if (hashLen > 32) + hashLen = 32; + + sp_256_from_bin(e, 4, hash, hashLen); + } + + for (i = SP_ECC_MAX_SIG_GEN; err == MP_OKAY && i > 0; i--) { + sp_256_from_mp(x, 4, priv); + + /* New random point. */ + err = sp_256_ecc_gen_k_4(rng, k); + if (err == MP_OKAY) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_256_ecc_mulmod_base_avx2_4(point, k, 1, heap); + else +#endif + err = sp_256_ecc_mulmod_base_4(point, k, 1, NULL); + } + + if (err == MP_OKAY) { + /* r = point->x mod order */ + XMEMCPY(r, point->x, sizeof(sp_digit) * 4); + sp_256_norm_4(r); + c = sp_256_cmp_4(r, p256_order); + sp_256_cond_sub_4(r, r, p256_order, 0 - (c >= 0)); + sp_256_norm_4(r); + + /* Conv k to Montgomery form (mod order) */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_256_mul_avx2_4(k, k, p256_norm_order); + else +#endif + sp_256_mul_4(k, k, p256_norm_order); + err = sp_256_mod_4(k, k, p256_order); + } + if (err == MP_OKAY) { + sp_256_norm_4(k); + /* kInv = 1/k mod order */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_256_mont_inv_order_avx2_4(kInv, k, tmp); + else +#endif + sp_256_mont_inv_order_4(kInv, k, tmp); + sp_256_norm_4(kInv); + + /* s = r * x + e */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_256_mul_avx2_4(x, x, r); + else +#endif + sp_256_mul_4(x, x, r); + err = sp_256_mod_4(x, x, p256_order); + } + if (err == MP_OKAY) { + sp_256_norm_4(x); + carry = sp_256_add_4(s, e, x); + sp_256_cond_sub_4(s, s, p256_order, 0 - carry); + sp_256_norm_4(s); + c = sp_256_cmp_4(s, p256_order); + sp_256_cond_sub_4(s, s, p256_order, 0 - (c >= 0)); + sp_256_norm_4(s); + + /* s = s * k^-1 mod order */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_256_mont_mul_order_avx2_4(s, s, kInv); + else +#endif + sp_256_mont_mul_order_4(s, s, kInv); + sp_256_norm_4(s); + + /* Check that signature is usable. */ + if (!sp_256_iszero_4(s)) + break; + } + } + + if (i == 0) + err = RNG_FAILURE_E; + + if (err == MP_OKAY) + err = sp_256_to_mp(r, rm); + if (err == MP_OKAY) + err = sp_256_to_mp(s, sm); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) { + XMEMSET(d, 0, sizeof(sp_digit) * 8 * 4); + XFREE(d, heap, DYNAMIC_TYPE_ECC); + } +#else + XMEMSET(e, 0, sizeof(sp_digit) * 2 * 4); + XMEMSET(x, 0, sizeof(sp_digit) * 2 * 4); + XMEMSET(k, 0, sizeof(sp_digit) * 2 * 4); + XMEMSET(r, 0, sizeof(sp_digit) * 2 * 4); + XMEMSET(r, 0, sizeof(sp_digit) * 2 * 4); + XMEMSET(tmp, 0, sizeof(sp_digit) * 3 * 2*4); +#endif + sp_ecc_point_free(point, 1, heap); + + return err; +} +#endif /* HAVE_ECC_SIGN */ + +#ifdef HAVE_ECC_VERIFY +/* Verify the signature values with the hash and public key. + * e = Truncate(hash, 256) + * u1 = e/s mod order + * u2 = r/s mod order + * r == (u1.G + u2.Q)->x mod order + * Optimization: Leave point in projective form. + * (x, y, 1) == (x' / z'*z', y' / z'*z'*z', z' / z') + * (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' + * The hash is truncated to the first 256 bits. + * + * hash Hash to sign. + * hashLen Length of the hash data. + * rng Random number generator. + * priv Private part of key - scalar. + * rm First part of result as an mp_int. + * sm Sirst part of result as an mp_int. + * heap Heap to use for allocation. + * returns RNG failures, MEMORY_E when memory allocation fails and + * MP_OKAY on success. + */ +int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, + mp_int* pY, mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d = NULL; +#else + sp_digit u1d[2*4]; + sp_digit u2d[2*4]; + sp_digit sd[2*4]; + sp_digit tmpd[2*4 * 5]; + sp_point p1d; + sp_point p2d; +#endif + sp_digit* u1; + sp_digit* u2; + sp_digit* s; + sp_digit* tmp; + sp_point* p1; + sp_point* p2 = NULL; + sp_digit carry; + int64_t c; + int err; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + err = sp_ecc_point_new(heap, p1d, p1); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, p2d, p2); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 16 * 4, heap, + DYNAMIC_TYPE_ECC); + if (d != NULL) { + u1 = d + 0 * 4; + u2 = d + 2 * 4; + s = d + 4 * 4; + tmp = d + 6 * 4; + } + else + err = MEMORY_E; + } +#else + u1 = u1d; + u2 = u2d; + s = sd; + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + if (hashLen > 32) + hashLen = 32; + + sp_256_from_bin(u1, 4, hash, hashLen); + sp_256_from_mp(u2, 4, r); + sp_256_from_mp(s, 4, sm); + sp_256_from_mp(p2->x, 4, pX); + sp_256_from_mp(p2->y, 4, pY); + sp_256_from_mp(p2->z, 4, pZ); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_256_mul_avx2_4(s, s, p256_norm_order); + else +#endif + sp_256_mul_4(s, s, p256_norm_order); + err = sp_256_mod_4(s, s, p256_order); + } + if (err == MP_OKAY) { + sp_256_norm_4(s); +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + sp_256_mont_inv_order_avx2_4(s, s, tmp); + sp_256_mont_mul_order_avx2_4(u1, u1, s); + sp_256_mont_mul_order_avx2_4(u2, u2, s); + } + else +#endif + { + sp_256_mont_inv_order_4(s, s, tmp); + sp_256_mont_mul_order_4(u1, u1, s); + sp_256_mont_mul_order_4(u2, u2, s); + } + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_256_ecc_mulmod_base_avx2_4(p1, u1, 0, heap); + else +#endif + err = sp_256_ecc_mulmod_base_4(p1, u1, 0, heap); + } + if (err == MP_OKAY) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_256_ecc_mulmod_avx2_4(p2, p2, u2, 0, heap); + else +#endif + err = sp_256_ecc_mulmod_4(p2, p2, u2, 0, heap); + } + + if (err == MP_OKAY) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_256_proj_point_add_avx2_4(p1, p1, p2, tmp); + else +#endif + sp_256_proj_point_add_4(p1, p1, p2, tmp); + + /* (r + n*order).z'.z' mod prime == (u1.G + u2.Q)->x' */ + /* Reload r and convert to Montgomery form. */ + sp_256_from_mp(u2, 4, r); + err = sp_256_mod_mul_norm_4(u2, u2, p256_mod); + } + + if (err == MP_OKAY) { + /* u1 = r.z'.z' mod prime */ + sp_256_mont_sqr_4(p1->z, p1->z, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(u1, u2, p1->z, p256_mod, p256_mp_mod); + *res = sp_256_cmp_4(p1->x, u1) == 0; + if (*res == 0) { + /* Reload r and add order. */ + sp_256_from_mp(u2, 4, r); + carry = sp_256_add_4(u2, u2, p256_order); + /* Carry means result is greater than mod and is not valid. */ + if (!carry) { + sp_256_norm_4(u2); + + /* Compare with mod and if greater or equal then not valid. */ + c = sp_256_cmp_4(u2, p256_mod); + if (c < 0) { + /* Convert to Montogomery form */ + err = sp_256_mod_mul_norm_4(u2, u2, p256_mod); + if (err == MP_OKAY) { + /* u1 = (r + 1*order).z'.z' mod prime */ + sp_256_mont_mul_4(u1, u2, p1->z, p256_mod, + p256_mp_mod); + *res = sp_256_cmp_4(p1->x, u2) == 0; + } + } + } + } + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p1, 0, heap); + sp_ecc_point_free(p2, 0, heap); + + return err; +} +#endif /* HAVE_ECC_VERIFY */ + +#ifdef HAVE_ECC_CHECK_KEY +/* Check that the x and y oridinates are a valid point on the curve. + * + * point EC point. + * heap Heap to use if dynamically allocating. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +static int sp_256_ecc_is_point_4(sp_point* point, void* heap) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d = NULL; +#else + sp_digit t1d[2*4]; + sp_digit t2d[2*4]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 4, heap, + DYNAMIC_TYPE_ECC); + if (d != NULL) { + t1 = d + 0 * 4; + t2 = d + 2 * 4; + } + else + err = MEMORY_E; +#else + (void)heap; + + t1 = t1d; + t2 = t2d; +#endif + + if (err == MP_OKAY) { + sp_256_sqr_4(t1, point->y); + sp_256_mod_4(t1, t1, p256_mod); + sp_256_sqr_4(t2, point->x); + sp_256_mod_4(t2, t2, p256_mod); + sp_256_mul_4(t2, t2, point->x); + sp_256_mod_4(t2, t2, p256_mod); + sp_256_sub_4(t2, p256_mod, t2); + sp_256_mont_add_4(t1, t1, t2, p256_mod); + + sp_256_mont_add_4(t1, t1, point->x, p256_mod); + sp_256_mont_add_4(t1, t1, point->x, p256_mod); + sp_256_mont_add_4(t1, t1, point->x, p256_mod); + + if (sp_256_cmp_4(t1, p256_b) != 0) + err = MP_VAL; + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, heap, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Check that the x and y oridinates are a valid point on the curve. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve and MP_OKAY otherwise. + */ +int sp_ecc_is_point_256(mp_int* pX, mp_int* pY) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_point pubd; +#endif + sp_point* pub; + byte one[1] = { 1 }; + int err; + + err = sp_ecc_point_new(NULL, pubd, pub); + if (err == MP_OKAY) { + sp_256_from_mp(pub->x, 4, pX); + sp_256_from_mp(pub->y, 4, pY); + sp_256_from_bin(pub->z, 4, one, sizeof(one)); + + err = sp_256_ecc_is_point_4(pub, NULL); + } + + sp_ecc_point_free(pub, 0, NULL); + + return err; +} + +/* Check that the private scalar generates the EC point (px, py), the point is + * on the curve and the point has the correct order. + * + * pX X ordinate of EC point. + * pY Y ordinate of EC point. + * privm Private scalar that generates EC point. + * returns MEMORY_E if dynamic memory allocation fails, MP_VAL if the point is + * not on the curve, ECC_INF_E if the point does not have the correct order, + * ECC_PRIV_KEY_E when the private scalar doesn't generate the EC point and + * MP_OKAY otherwise. + */ +int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit privd[4]; + sp_point pubd; + sp_point pd; +#endif + sp_digit* priv = NULL; + sp_point* pub; + sp_point* p = NULL; + byte one[1] = { 1 }; + int err; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + err = sp_ecc_point_new(heap, pubd, pub); + if (err == MP_OKAY) + err = sp_ecc_point_new(heap, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + priv = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4, heap, + DYNAMIC_TYPE_ECC); + if (priv == NULL) + err = MEMORY_E; + } +#else + priv = privd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(pub->x, 4, pX); + sp_256_from_mp(pub->y, 4, pY); + sp_256_from_bin(pub->z, 4, one, sizeof(one)); + sp_256_from_mp(priv, 4, privm); + + /* Check point at infinitiy. */ + if (sp_256_iszero_4(pub->x) && + sp_256_iszero_4(pub->y)) + err = ECC_INF_E; + } + + if (err == MP_OKAY) { + /* Check range of X and Y */ + if (sp_256_cmp_4(pub->x, p256_mod) >= 0 || + sp_256_cmp_4(pub->y, p256_mod) >= 0) + err = ECC_OUT_OF_RANGE_E; + } + + if (err == MP_OKAY) { + /* Check point is on curve */ + err = sp_256_ecc_is_point_4(pub, heap); + } + + if (err == MP_OKAY) { + /* Point * order = infinity */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_256_ecc_mulmod_avx2_4(p, pub, p256_order, 1, heap); + else +#endif + err = sp_256_ecc_mulmod_4(p, pub, p256_order, 1, heap); + } + if (err == MP_OKAY) { + /* Check result is infinity */ + if (!sp_256_iszero_4(p->x) || + !sp_256_iszero_4(p->y)) { + err = ECC_INF_E; + } + } + + if (err == MP_OKAY) { + /* Base * private = point */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + err = sp_256_ecc_mulmod_base_avx2_4(p, priv, 1, heap); + else +#endif + err = sp_256_ecc_mulmod_base_4(p, priv, 1, heap); + } + if (err == MP_OKAY) { + /* Check result is public key */ + if (sp_256_cmp_4(p->x, pub->x) != 0 || + sp_256_cmp_4(p->y, pub->y) != 0) { + err = ECC_PRIV_KEY_E; + } + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (priv != NULL) + XFREE(priv, heap, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p, 0, heap); + sp_ecc_point_free(pub, 0, heap); + + return err; +} +#endif +#ifdef WOLFSSL_PUBLIC_ECC_ADD_DBL +/* Add two projective EC points together. + * (pX, pY, pZ) + (qX, qY, qZ) = (rX, rY, rZ) + * + * pX First EC point's X ordinate. + * pY First EC point's Y ordinate. + * pZ First EC point's Z ordinate. + * qX Second EC point's X ordinate. + * qY Second EC point's Y ordinate. + * qZ Second EC point's Z ordinate. + * rX Resultant EC point's X ordinate. + * rY Resultant EC point's Y ordinate. + * rZ Resultant EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* qX, mp_int* qY, mp_int* qZ, + mp_int* rX, mp_int* rY, mp_int* rZ) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit tmpd[2 * 4 * 5]; + sp_point pd; + sp_point qd; +#endif + sp_digit* tmp; + sp_point* p; + sp_point* q = NULL; + int err; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + err = sp_ecc_point_new(NULL, pd, p); + if (err == MP_OKAY) + err = sp_ecc_point_new(NULL, qd, q); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 5, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } +#else + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 4, pX); + sp_256_from_mp(p->y, 4, pY); + sp_256_from_mp(p->z, 4, pZ); + sp_256_from_mp(q->x, 4, qX); + sp_256_from_mp(q->y, 4, qY); + sp_256_from_mp(q->z, 4, qZ); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_256_proj_point_add_avx2_4(p, p, q, tmp); + else +#endif + sp_256_proj_point_add_4(p, p, q, tmp); + } + + if (err == MP_OKAY) + err = sp_256_to_mp(p->x, rX); + if (err == MP_OKAY) + err = sp_256_to_mp(p->y, rY); + if (err == MP_OKAY) + err = sp_256_to_mp(p->z, rZ); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (tmp != NULL) + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(q, 0, NULL); + sp_ecc_point_free(p, 0, NULL); + + return err; +} + +/* Double a projective EC point. + * (pX, pY, pZ) + (pX, pY, pZ) = (rX, rY, rZ) + * + * pX EC point's X ordinate. + * pY EC point's Y ordinate. + * pZ EC point's Z ordinate. + * rX Resultant EC point's X ordinate. + * rY Resultant EC point's Y ordinate. + * rZ Resultant EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* rX, mp_int* rY, mp_int* rZ) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit tmpd[2 * 4 * 2]; + sp_point pd; +#endif + sp_digit* tmp; + sp_point* p; + int err; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + + err = sp_ecc_point_new(NULL, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 2, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } +#else + tmp = tmpd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 4, pX); + sp_256_from_mp(p->y, 4, pY); + sp_256_from_mp(p->z, 4, pZ); + +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) + sp_256_proj_point_dbl_avx2_4(p, p, tmp); + else +#endif + sp_256_proj_point_dbl_4(p, p, tmp); + } + + if (err == MP_OKAY) + err = sp_256_to_mp(p->x, rX); + if (err == MP_OKAY) + err = sp_256_to_mp(p->y, rY); + if (err == MP_OKAY) + err = sp_256_to_mp(p->z, rZ); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (tmp != NULL) + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p, 0, NULL); + + return err; +} + +/* Map a projective EC point to affine in place. + * pZ will be one. + * + * pX EC point's X ordinate. + * pY EC point's Y ordinate. + * pZ EC point's Z ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ) +{ +#if !defined(WOLFSSL_SP_SMALL) && !defined(WOLFSSL_SMALL_STACK) + sp_digit tmpd[2 * 4 * 4]; + sp_point pd; +#endif + sp_digit* tmp; + sp_point* p; + int err; + + err = sp_ecc_point_new(NULL, pd, p); +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (err == MP_OKAY) { + tmp = (sp_digit*)XMALLOC(sizeof(sp_digit) * 2 * 4 * 4, NULL, + DYNAMIC_TYPE_ECC); + if (tmp == NULL) + err = MEMORY_E; + } +#else + tmp = tmpd; +#endif + if (err == MP_OKAY) { + sp_256_from_mp(p->x, 4, pX); + sp_256_from_mp(p->y, 4, pY); + sp_256_from_mp(p->z, 4, pZ); + + sp_256_map_4(p, p, tmp); + } + + if (err == MP_OKAY) + err = sp_256_to_mp(p->x, pX); + if (err == MP_OKAY) + err = sp_256_to_mp(p->y, pY); + if (err == MP_OKAY) + err = sp_256_to_mp(p->z, pZ); + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (tmp != NULL) + XFREE(tmp, NULL, DYNAMIC_TYPE_ECC); +#endif + sp_ecc_point_free(p, 0, NULL); + + return err; +} +#endif /* WOLFSSL_PUBLIC_ECC_ADD_DBL */ +#ifdef HAVE_COMP_KEY +/* Find the square root of a number mod the prime of the curve. + * + * y The number to operate on and the result. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +static int sp_256_mont_sqrt_4(sp_digit* y) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d; +#else + sp_digit t1d[2 * 4]; + sp_digit t2d[2 * 4]; +#endif + sp_digit* t1; + sp_digit* t2; + int err = MP_OKAY; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 4, NULL, DYNAMIC_TYPE_ECC); + if (d != NULL) { + t1 = d + 0 * 4; + t2 = d + 2 * 4; + } + else + err = MEMORY_E; +#else + t1 = t1d; + t2 = t2d; +#endif + + if (err == MP_OKAY) { +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + /* t2 = y ^ 0x2 */ + sp_256_mont_sqr_avx2_4(t2, y, p256_mod, p256_mp_mod); + /* t1 = y ^ 0x3 */ + sp_256_mont_mul_avx2_4(t1, t2, y, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xc */ + sp_256_mont_sqr_n_avx2_4(t2, t1, 2, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xf */ + sp_256_mont_mul_avx2_4(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xf0 */ + sp_256_mont_sqr_n_avx2_4(t2, t1, 4, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xff */ + sp_256_mont_mul_avx2_4(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xff00 */ + sp_256_mont_sqr_n_avx2_4(t2, t1, 8, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffff */ + sp_256_mont_mul_avx2_4(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xffff0000 */ + sp_256_mont_sqr_n_avx2_4(t2, t1, 16, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff */ + sp_256_mont_mul_avx2_4(t1, t1, t2, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000000 */ + sp_256_mont_sqr_n_avx2_4(t1, t1, 32, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001 */ + sp_256_mont_mul_avx2_4(t1, t1, y, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001000000000000000000000000 */ + sp_256_mont_sqr_n_avx2_4(t1, t1, 96, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001000000000000000000000001 */ + sp_256_mont_mul_avx2_4(t1, t1, y, p256_mod, p256_mp_mod); + sp_256_mont_sqr_n_avx2_4(y, t1, 94, p256_mod, p256_mp_mod); + } + else +#endif + { + /* t2 = y ^ 0x2 */ + sp_256_mont_sqr_4(t2, y, p256_mod, p256_mp_mod); + /* t1 = y ^ 0x3 */ + sp_256_mont_mul_4(t1, t2, y, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xc */ + sp_256_mont_sqr_n_4(t2, t1, 2, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xf */ + sp_256_mont_mul_4(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xf0 */ + sp_256_mont_sqr_n_4(t2, t1, 4, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xff */ + sp_256_mont_mul_4(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xff00 */ + sp_256_mont_sqr_n_4(t2, t1, 8, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffff */ + sp_256_mont_mul_4(t1, t1, t2, p256_mod, p256_mp_mod); + /* t2 = y ^ 0xffff0000 */ + sp_256_mont_sqr_n_4(t2, t1, 16, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff */ + sp_256_mont_mul_4(t1, t1, t2, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000000 */ + sp_256_mont_sqr_n_4(t1, t1, 32, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001 */ + sp_256_mont_mul_4(t1, t1, y, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001000000000000000000000000 */ + sp_256_mont_sqr_n_4(t1, t1, 96, p256_mod, p256_mp_mod); + /* t1 = y ^ 0xffffffff00000001000000000000000000000001 */ + sp_256_mont_mul_4(t1, t1, y, p256_mod, p256_mp_mod); + sp_256_mont_sqr_n_4(y, t1, 94, p256_mod, p256_mp_mod); + } + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_ECC); +#endif + + return err; +} + +/* Uncompress the point given the X ordinate. + * + * xm X ordinate. + * odd Whether the Y ordinate is odd. + * ym Calculated Y ordinate. + * returns MEMORY_E if dynamic memory allocation fails and MP_OKAY otherwise. + */ +int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym) +{ +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + sp_digit* d; +#else + sp_digit xd[2 * 4]; + sp_digit yd[2 * 4]; +#endif + sp_digit* x; + sp_digit* y; + int err = MP_OKAY; +#ifdef HAVE_INTEL_AVX2 + word32 cpuid_flags = cpuid_get_flags(); +#endif + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + d = (sp_digit*)XMALLOC(sizeof(sp_digit) * 4 * 4, NULL, DYNAMIC_TYPE_ECC); + if (d != NULL) { + x = d + 0 * 4; + y = d + 2 * 4; + } + else + err = MEMORY_E; +#else + x = xd; + y = yd; +#endif + + if (err == MP_OKAY) { + sp_256_from_mp(x, 4, xm); + + err = sp_256_mod_mul_norm_4(x, x, p256_mod); + } + + if (err == MP_OKAY) { + /* y = x^3 */ +#ifdef HAVE_INTEL_AVX2 + if (IS_INTEL_BMI2(cpuid_flags) && IS_INTEL_ADX(cpuid_flags)) { + sp_256_mont_sqr_avx2_4(y, x, p256_mod, p256_mp_mod); + sp_256_mont_mul_avx2_4(y, y, x, p256_mod, p256_mp_mod); + } + else +#endif + { + sp_256_mont_sqr_4(y, x, p256_mod, p256_mp_mod); + sp_256_mont_mul_4(y, y, x, p256_mod, p256_mp_mod); + } + /* y = x^3 - 3x */ + sp_256_mont_sub_4(y, y, x, p256_mod); + sp_256_mont_sub_4(y, y, x, p256_mod); + sp_256_mont_sub_4(y, y, x, p256_mod); + /* y = x^3 - 3x + b */ + err = sp_256_mod_mul_norm_4(x, p256_b, p256_mod); + } + if (err == MP_OKAY) { + sp_256_mont_add_4(y, y, x, p256_mod); + /* y = sqrt(x^3 - 3x + b) */ + err = sp_256_mont_sqrt_4(y); + } + if (err == MP_OKAY) { + XMEMSET(y + 4, 0, 4 * sizeof(sp_digit)); + sp_256_mont_reduce_4(y, p256_mod, p256_mp_mod); + if (((y[0] ^ odd) & 1) != 0) + sp_256_mont_sub_4(y, p256_mod, y, p256_mod); + + err = sp_256_to_mp(y, ym); + } + +#if defined(WOLFSSL_SP_SMALL) || defined(WOLFSSL_SMALL_STACK) + if (d != NULL) + XFREE(d, NULL, DYNAMIC_TYPE_ECC); +#endif + + return err; +} +#endif +#endif /* !WOLFSSL_SP_NO_256 */ +#endif /* WOLFSSL_HAVE_SP_ECC */ +#endif /* WOLFSSL_SP_X86_64_ASM */ +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH || WOLFSSL_HAVE_SP_ECC */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/sp_x86_64_asm.S b/beken_os/beken378/func/wolfssl/wolfcrypt/src/sp_x86_64_asm.S new file mode 100755 index 0000000..fa93f54 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/sp_x86_64_asm.S @@ -0,0 +1,26390 @@ +/* sp_x86_64_asm + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#define HAVE_INTEL_AVX2 +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_2048_mul_16 +.type sp_2048_mul_16,@function +.align 16 +sp_2048_mul_16: +#else +.globl _sp_2048_mul_16 +.p2align 4 +_sp_2048_mul_16: +#endif /* __APPLE__ */ + movq %rdx, %rcx + subq $128, %rsp + # A[0] * B[0] + movq (%rcx), %rax + mulq (%rsi) + xorq %r10, %r10 + movq %rax, (%rsp) + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rcx), %rax + mulq (%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[1] * B[0] + movq (%rcx), %rax + mulq 8(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + movq %r9, 8(%rsp) + # A[0] * B[2] + movq 16(%rcx), %rax + mulq (%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[1] * B[1] + movq 8(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[2] * B[0] + movq (%rcx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + movq %r10, 16(%rsp) + # A[0] * B[3] + movq 24(%rcx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[1] * B[2] + movq 16(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[2] * B[1] + movq 8(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[3] * B[0] + movq (%rcx), %rax + mulq 24(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + movq %r8, 24(%rsp) + # A[0] * B[4] + movq 32(%rcx), %rax + mulq (%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[1] * B[3] + movq 24(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[2] * B[2] + movq 16(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[3] * B[1] + movq 8(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[4] * B[0] + movq (%rcx), %rax + mulq 32(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + movq %r9, 32(%rsp) + # A[0] * B[5] + movq 40(%rcx), %rax + mulq (%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[1] * B[4] + movq 32(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[2] * B[3] + movq 24(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[3] * B[2] + movq 16(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[4] * B[1] + movq 8(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[5] * B[0] + movq (%rcx), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + movq %r10, 40(%rsp) + # A[0] * B[6] + movq 48(%rcx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[1] * B[5] + movq 40(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[2] * B[4] + movq 32(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[3] * B[3] + movq 24(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[4] * B[2] + movq 16(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[5] * B[1] + movq 8(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[6] * B[0] + movq (%rcx), %rax + mulq 48(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + movq %r8, 48(%rsp) + # A[0] * B[7] + movq 56(%rcx), %rax + mulq (%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[1] * B[6] + movq 48(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[2] * B[5] + movq 40(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[3] * B[4] + movq 32(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[4] * B[3] + movq 24(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[5] * B[2] + movq 16(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[6] * B[1] + movq 8(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[7] * B[0] + movq (%rcx), %rax + mulq 56(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + movq %r9, 56(%rsp) + # A[0] * B[8] + movq 64(%rcx), %rax + mulq (%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[1] * B[7] + movq 56(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[2] * B[6] + movq 48(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[3] * B[5] + movq 40(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[4] * B[4] + movq 32(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[5] * B[3] + movq 24(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[6] * B[2] + movq 16(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[7] * B[1] + movq 8(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[8] * B[0] + movq (%rcx), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + movq %r10, 64(%rsp) + # A[0] * B[9] + movq 72(%rcx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[1] * B[8] + movq 64(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[2] * B[7] + movq 56(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[3] * B[6] + movq 48(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[4] * B[5] + movq 40(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[5] * B[4] + movq 32(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[6] * B[3] + movq 24(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[7] * B[2] + movq 16(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[8] * B[1] + movq 8(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[9] * B[0] + movq (%rcx), %rax + mulq 72(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + movq %r8, 72(%rsp) + # A[0] * B[10] + movq 80(%rcx), %rax + mulq (%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[1] * B[9] + movq 72(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[2] * B[8] + movq 64(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[3] * B[7] + movq 56(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[4] * B[6] + movq 48(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[5] * B[5] + movq 40(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[6] * B[4] + movq 32(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[7] * B[3] + movq 24(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[8] * B[2] + movq 16(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[9] * B[1] + movq 8(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[10] * B[0] + movq (%rcx), %rax + mulq 80(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + movq %r9, 80(%rsp) + # A[0] * B[11] + movq 88(%rcx), %rax + mulq (%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[1] * B[10] + movq 80(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[2] * B[9] + movq 72(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[3] * B[8] + movq 64(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[4] * B[7] + movq 56(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[5] * B[6] + movq 48(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[6] * B[5] + movq 40(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[7] * B[4] + movq 32(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[8] * B[3] + movq 24(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[9] * B[2] + movq 16(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[10] * B[1] + movq 8(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[11] * B[0] + movq (%rcx), %rax + mulq 88(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + movq %r10, 88(%rsp) + # A[0] * B[12] + movq 96(%rcx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[1] * B[11] + movq 88(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[2] * B[10] + movq 80(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[3] * B[9] + movq 72(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[4] * B[8] + movq 64(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[5] * B[7] + movq 56(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[6] * B[6] + movq 48(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[7] * B[5] + movq 40(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[8] * B[4] + movq 32(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[9] * B[3] + movq 24(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[10] * B[2] + movq 16(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[11] * B[1] + movq 8(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[12] * B[0] + movq (%rcx), %rax + mulq 96(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + movq %r8, 96(%rsp) + # A[0] * B[13] + movq 104(%rcx), %rax + mulq (%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[1] * B[12] + movq 96(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[2] * B[11] + movq 88(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[3] * B[10] + movq 80(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[4] * B[9] + movq 72(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[5] * B[8] + movq 64(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[6] * B[7] + movq 56(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[7] * B[6] + movq 48(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[8] * B[5] + movq 40(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[9] * B[4] + movq 32(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[10] * B[3] + movq 24(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[11] * B[2] + movq 16(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[12] * B[1] + movq 8(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[13] * B[0] + movq (%rcx), %rax + mulq 104(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + movq %r9, 104(%rsp) + # A[0] * B[14] + movq 112(%rcx), %rax + mulq (%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[1] * B[13] + movq 104(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[2] * B[12] + movq 96(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[3] * B[11] + movq 88(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[4] * B[10] + movq 80(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[5] * B[9] + movq 72(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[6] * B[8] + movq 64(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[7] * B[7] + movq 56(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[8] * B[6] + movq 48(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[9] * B[5] + movq 40(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[10] * B[4] + movq 32(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[11] * B[3] + movq 24(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[12] * B[2] + movq 16(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[13] * B[1] + movq 8(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[14] * B[0] + movq (%rcx), %rax + mulq 112(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + movq %r10, 112(%rsp) + # A[0] * B[15] + movq 120(%rcx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[1] * B[14] + movq 112(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[2] * B[13] + movq 104(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[3] * B[12] + movq 96(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[4] * B[11] + movq 88(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[5] * B[10] + movq 80(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[6] * B[9] + movq 72(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[7] * B[8] + movq 64(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[8] * B[7] + movq 56(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[9] * B[6] + movq 48(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[10] * B[5] + movq 40(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[11] * B[4] + movq 32(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[12] * B[3] + movq 24(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[13] * B[2] + movq 16(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[14] * B[1] + movq 8(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[15] * B[0] + movq (%rcx), %rax + mulq 120(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + movq %r8, 120(%rsp) + # A[1] * B[15] + movq 120(%rcx), %rax + mulq 8(%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[2] * B[14] + movq 112(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[3] * B[13] + movq 104(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[4] * B[12] + movq 96(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[5] * B[11] + movq 88(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[6] * B[10] + movq 80(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[7] * B[9] + movq 72(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[8] * B[8] + movq 64(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[9] * B[7] + movq 56(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[10] * B[6] + movq 48(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[11] * B[5] + movq 40(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[12] * B[4] + movq 32(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[13] * B[3] + movq 24(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[14] * B[2] + movq 16(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[15] * B[1] + movq 8(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + movq %r9, 128(%rdi) + # A[2] * B[15] + movq 120(%rcx), %rax + mulq 16(%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[3] * B[14] + movq 112(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[4] * B[13] + movq 104(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[5] * B[12] + movq 96(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[6] * B[11] + movq 88(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[7] * B[10] + movq 80(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[8] * B[9] + movq 72(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[9] * B[8] + movq 64(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[10] * B[7] + movq 56(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[11] * B[6] + movq 48(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[12] * B[5] + movq 40(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[13] * B[4] + movq 32(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[14] * B[3] + movq 24(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[15] * B[2] + movq 16(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + movq %r10, 136(%rdi) + # A[3] * B[15] + movq 120(%rcx), %rax + mulq 24(%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[4] * B[14] + movq 112(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[5] * B[13] + movq 104(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[6] * B[12] + movq 96(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[7] * B[11] + movq 88(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[8] * B[10] + movq 80(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[9] * B[9] + movq 72(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[10] * B[8] + movq 64(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[11] * B[7] + movq 56(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[12] * B[6] + movq 48(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[13] * B[5] + movq 40(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[14] * B[4] + movq 32(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[15] * B[3] + movq 24(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + movq %r8, 144(%rdi) + # A[4] * B[15] + movq 120(%rcx), %rax + mulq 32(%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[5] * B[14] + movq 112(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[6] * B[13] + movq 104(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[7] * B[12] + movq 96(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[8] * B[11] + movq 88(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[9] * B[10] + movq 80(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[10] * B[9] + movq 72(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[11] * B[8] + movq 64(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[12] * B[7] + movq 56(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[13] * B[6] + movq 48(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[14] * B[5] + movq 40(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[15] * B[4] + movq 32(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + movq %r9, 152(%rdi) + # A[5] * B[15] + movq 120(%rcx), %rax + mulq 40(%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[6] * B[14] + movq 112(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[7] * B[13] + movq 104(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[8] * B[12] + movq 96(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[9] * B[11] + movq 88(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[10] * B[10] + movq 80(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[11] * B[9] + movq 72(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[12] * B[8] + movq 64(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[13] * B[7] + movq 56(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[14] * B[6] + movq 48(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[15] * B[5] + movq 40(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + movq %r10, 160(%rdi) + # A[6] * B[15] + movq 120(%rcx), %rax + mulq 48(%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[7] * B[14] + movq 112(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[8] * B[13] + movq 104(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[9] * B[12] + movq 96(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[10] * B[11] + movq 88(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[11] * B[10] + movq 80(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[12] * B[9] + movq 72(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[13] * B[8] + movq 64(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[14] * B[7] + movq 56(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[15] * B[6] + movq 48(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + movq %r8, 168(%rdi) + # A[7] * B[15] + movq 120(%rcx), %rax + mulq 56(%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[8] * B[14] + movq 112(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[9] * B[13] + movq 104(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[10] * B[12] + movq 96(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[11] * B[11] + movq 88(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[12] * B[10] + movq 80(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[13] * B[9] + movq 72(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[14] * B[8] + movq 64(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[15] * B[7] + movq 56(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + movq %r9, 176(%rdi) + # A[8] * B[15] + movq 120(%rcx), %rax + mulq 64(%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[9] * B[14] + movq 112(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[10] * B[13] + movq 104(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[11] * B[12] + movq 96(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[12] * B[11] + movq 88(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[13] * B[10] + movq 80(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[14] * B[9] + movq 72(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[15] * B[8] + movq 64(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + movq %r10, 184(%rdi) + # A[9] * B[15] + movq 120(%rcx), %rax + mulq 72(%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[10] * B[14] + movq 112(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[11] * B[13] + movq 104(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[12] * B[12] + movq 96(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[13] * B[11] + movq 88(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[14] * B[10] + movq 80(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[15] * B[9] + movq 72(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + movq %r8, 192(%rdi) + # A[10] * B[15] + movq 120(%rcx), %rax + mulq 80(%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[11] * B[14] + movq 112(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[12] * B[13] + movq 104(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[13] * B[12] + movq 96(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[14] * B[11] + movq 88(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[15] * B[10] + movq 80(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + movq %r9, 200(%rdi) + # A[11] * B[15] + movq 120(%rcx), %rax + mulq 88(%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[12] * B[14] + movq 112(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[13] * B[13] + movq 104(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[14] * B[12] + movq 96(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[15] * B[11] + movq 88(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + movq %r10, 208(%rdi) + # A[12] * B[15] + movq 120(%rcx), %rax + mulq 96(%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[13] * B[14] + movq 112(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[14] * B[13] + movq 104(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[15] * B[12] + movq 96(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + movq %r8, 216(%rdi) + # A[13] * B[15] + movq 120(%rcx), %rax + mulq 104(%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[14] * B[14] + movq 112(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[15] * B[13] + movq 104(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + movq %r9, 224(%rdi) + # A[14] * B[15] + movq 120(%rcx), %rax + mulq 112(%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[15] * B[14] + movq 112(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + movq %r10, 232(%rdi) + # A[15] * B[15] + movq 120(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + movq %r8, 240(%rdi) + movq %r9, 248(%rdi) + movq (%rsp), %rax + movq 8(%rsp), %rdx + movq 16(%rsp), %r8 + movq 24(%rsp), %r9 + movq %rax, (%rdi) + movq %rdx, 8(%rdi) + movq %r8, 16(%rdi) + movq %r9, 24(%rdi) + movq 32(%rsp), %rax + movq 40(%rsp), %rdx + movq 48(%rsp), %r8 + movq 56(%rsp), %r9 + movq %rax, 32(%rdi) + movq %rdx, 40(%rdi) + movq %r8, 48(%rdi) + movq %r9, 56(%rdi) + movq 64(%rsp), %rax + movq 72(%rsp), %rdx + movq 80(%rsp), %r8 + movq 88(%rsp), %r9 + movq %rax, 64(%rdi) + movq %rdx, 72(%rdi) + movq %r8, 80(%rdi) + movq %r9, 88(%rdi) + movq 96(%rsp), %rax + movq 104(%rsp), %rdx + movq 112(%rsp), %r8 + movq 120(%rsp), %r9 + movq %rax, 96(%rdi) + movq %rdx, 104(%rdi) + movq %r8, 112(%rdi) + movq %r9, 120(%rdi) + addq $128, %rsp + repz retq +#ifndef __APPLE__ +.size sp_2048_mul_16,.-sp_2048_mul_16 +#endif /* __APPLE__ */ +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_2048_sqr_16 +.type sp_2048_sqr_16,@function +.align 16 +sp_2048_sqr_16: +#else +.globl _sp_2048_sqr_16 +.p2align 4 +_sp_2048_sqr_16: +#endif /* __APPLE__ */ + push %r12 + subq $128, %rsp + # A[0] * A[0] + movq (%rsi), %rax + mulq %rax + xorq %r9, %r9 + movq %rax, (%rsp) + movq %rdx, %r8 + # A[0] * A[1] + movq 8(%rsi), %rax + mulq (%rsi) + xorq %rcx, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + movq %r8, 8(%rsp) + # A[0] * A[2] + movq 16(%rsi), %rax + mulq (%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0, %r8 + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0, %r8 + # A[1] * A[1] + movq 8(%rsi), %rax + mulq %rax + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0, %r8 + movq %r9, 16(%rsp) + # A[0] * A[3] + movq 24(%rsi), %rax + mulq (%rsi) + xorq %r9, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + # A[1] * A[2] + movq 16(%rsi), %rax + mulq 8(%rsi) + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + movq %rcx, 24(%rsp) + # A[0] * A[4] + movq 32(%rsi), %rax + mulq (%rsi) + xorq %rcx, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + # A[1] * A[3] + movq 24(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + # A[2] * A[2] + movq 16(%rsi), %rax + mulq %rax + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + movq %r8, 32(%rsp) + # A[0] * A[5] + movq 40(%rsi), %rax + mulq (%rsi) + xorq %r8, %r8 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[4] + movq 32(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[2] * A[3] + movq 24(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %r9 + adcq %r11, %rcx + adcq %r12, %r8 + movq %r9, 40(%rsp) + # A[0] * A[6] + movq 48(%rsi), %rax + mulq (%rsi) + xorq %r9, %r9 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[5] + movq 40(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[2] * A[4] + movq 32(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[3] * A[3] + movq 24(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %rcx + adcq %r11, %r8 + adcq %r12, %r9 + movq %rcx, 48(%rsp) + # A[0] * A[7] + movq 56(%rsi), %rax + mulq (%rsi) + xorq %rcx, %rcx + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[6] + movq 48(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[2] * A[5] + movq 40(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[3] * A[4] + movq 32(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %r8 + adcq %r11, %r9 + adcq %r12, %rcx + movq %r8, 56(%rsp) + # A[0] * A[8] + movq 64(%rsi), %rax + mulq (%rsi) + xorq %r8, %r8 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[7] + movq 56(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[2] * A[6] + movq 48(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[3] * A[5] + movq 40(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[4] * A[4] + movq 32(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r9 + adcq %r11, %rcx + adcq %r12, %r8 + movq %r9, 64(%rsp) + # A[0] * A[9] + movq 72(%rsi), %rax + mulq (%rsi) + xorq %r9, %r9 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[8] + movq 64(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[2] * A[7] + movq 56(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[3] * A[6] + movq 48(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[4] * A[5] + movq 40(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %rcx + adcq %r11, %r8 + adcq %r12, %r9 + movq %rcx, 72(%rsp) + # A[0] * A[10] + movq 80(%rsi), %rax + mulq (%rsi) + xorq %rcx, %rcx + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[9] + movq 72(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[2] * A[8] + movq 64(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[3] * A[7] + movq 56(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[4] * A[6] + movq 48(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[5] * A[5] + movq 40(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r8 + adcq %r11, %r9 + adcq %r12, %rcx + movq %r8, 80(%rsp) + # A[0] * A[11] + movq 88(%rsi), %rax + mulq (%rsi) + xorq %r8, %r8 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[10] + movq 80(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[2] * A[9] + movq 72(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[3] * A[8] + movq 64(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[4] * A[7] + movq 56(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[5] * A[6] + movq 48(%rsi), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %r9 + adcq %r11, %rcx + adcq %r12, %r8 + movq %r9, 88(%rsp) + # A[0] * A[12] + movq 96(%rsi), %rax + mulq (%rsi) + xorq %r9, %r9 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[11] + movq 88(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[2] * A[10] + movq 80(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[3] * A[9] + movq 72(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[4] * A[8] + movq 64(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[5] * A[7] + movq 56(%rsi), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[6] * A[6] + movq 48(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %rcx + adcq %r11, %r8 + adcq %r12, %r9 + movq %rcx, 96(%rsp) + # A[0] * A[13] + movq 104(%rsi), %rax + mulq (%rsi) + xorq %rcx, %rcx + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[12] + movq 96(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[2] * A[11] + movq 88(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[3] * A[10] + movq 80(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[4] * A[9] + movq 72(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[5] * A[8] + movq 64(%rsi), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[6] * A[7] + movq 56(%rsi), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %r8 + adcq %r11, %r9 + adcq %r12, %rcx + movq %r8, 104(%rsp) + # A[0] * A[14] + movq 112(%rsi), %rax + mulq (%rsi) + xorq %r8, %r8 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[13] + movq 104(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[2] * A[12] + movq 96(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[3] * A[11] + movq 88(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[4] * A[10] + movq 80(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[5] * A[9] + movq 72(%rsi), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[6] * A[8] + movq 64(%rsi), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[7] * A[7] + movq 56(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r9 + adcq %r11, %rcx + adcq %r12, %r8 + movq %r9, 112(%rsp) + # A[0] * A[15] + movq 120(%rsi), %rax + mulq (%rsi) + xorq %r9, %r9 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[14] + movq 112(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[2] * A[13] + movq 104(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[3] * A[12] + movq 96(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[4] * A[11] + movq 88(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[5] * A[10] + movq 80(%rsi), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[6] * A[9] + movq 72(%rsi), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[7] * A[8] + movq 64(%rsi), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %rcx + adcq %r11, %r8 + adcq %r12, %r9 + movq %rcx, 120(%rsp) + # A[1] * A[15] + movq 120(%rsi), %rax + mulq 8(%rsi) + xorq %rcx, %rcx + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[2] * A[14] + movq 112(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[3] * A[13] + movq 104(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[4] * A[12] + movq 96(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[5] * A[11] + movq 88(%rsi), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[6] * A[10] + movq 80(%rsi), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[7] * A[9] + movq 72(%rsi), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[8] * A[8] + movq 64(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r8 + adcq %r11, %r9 + adcq %r12, %rcx + movq %r8, 128(%rdi) + # A[2] * A[15] + movq 120(%rsi), %rax + mulq 16(%rsi) + xorq %r8, %r8 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[3] * A[14] + movq 112(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[4] * A[13] + movq 104(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[5] * A[12] + movq 96(%rsi), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[6] * A[11] + movq 88(%rsi), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[7] * A[10] + movq 80(%rsi), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[8] * A[9] + movq 72(%rsi), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %r9 + adcq %r11, %rcx + adcq %r12, %r8 + movq %r9, 136(%rdi) + # A[3] * A[15] + movq 120(%rsi), %rax + mulq 24(%rsi) + xorq %r9, %r9 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[4] * A[14] + movq 112(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[5] * A[13] + movq 104(%rsi), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[6] * A[12] + movq 96(%rsi), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[7] * A[11] + movq 88(%rsi), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[8] * A[10] + movq 80(%rsi), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[9] * A[9] + movq 72(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %rcx + adcq %r11, %r8 + adcq %r12, %r9 + movq %rcx, 144(%rdi) + # A[4] * A[15] + movq 120(%rsi), %rax + mulq 32(%rsi) + xorq %rcx, %rcx + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[5] * A[14] + movq 112(%rsi), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[6] * A[13] + movq 104(%rsi), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[7] * A[12] + movq 96(%rsi), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[8] * A[11] + movq 88(%rsi), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[9] * A[10] + movq 80(%rsi), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %r8 + adcq %r11, %r9 + adcq %r12, %rcx + movq %r8, 152(%rdi) + # A[5] * A[15] + movq 120(%rsi), %rax + mulq 40(%rsi) + xorq %r8, %r8 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[6] * A[14] + movq 112(%rsi), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[7] * A[13] + movq 104(%rsi), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[8] * A[12] + movq 96(%rsi), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[9] * A[11] + movq 88(%rsi), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[10] * A[10] + movq 80(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r9 + adcq %r11, %rcx + adcq %r12, %r8 + movq %r9, 160(%rdi) + # A[6] * A[15] + movq 120(%rsi), %rax + mulq 48(%rsi) + xorq %r9, %r9 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[7] * A[14] + movq 112(%rsi), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[8] * A[13] + movq 104(%rsi), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[9] * A[12] + movq 96(%rsi), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[10] * A[11] + movq 88(%rsi), %rax + mulq 80(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %rcx + adcq %r11, %r8 + adcq %r12, %r9 + movq %rcx, 168(%rdi) + # A[7] * A[15] + movq 120(%rsi), %rax + mulq 56(%rsi) + xorq %rcx, %rcx + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[8] * A[14] + movq 112(%rsi), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[9] * A[13] + movq 104(%rsi), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[10] * A[12] + movq 96(%rsi), %rax + mulq 80(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[11] * A[11] + movq 88(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r8 + adcq %r11, %r9 + adcq %r12, %rcx + movq %r8, 176(%rdi) + # A[8] * A[15] + movq 120(%rsi), %rax + mulq 64(%rsi) + xorq %r8, %r8 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[9] * A[14] + movq 112(%rsi), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[10] * A[13] + movq 104(%rsi), %rax + mulq 80(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[11] * A[12] + movq 96(%rsi), %rax + mulq 88(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %r9 + adcq %r11, %rcx + adcq %r12, %r8 + movq %r9, 184(%rdi) + # A[9] * A[15] + movq 120(%rsi), %rax + mulq 72(%rsi) + xorq %r9, %r9 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[10] * A[14] + movq 112(%rsi), %rax + mulq 80(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[11] * A[13] + movq 104(%rsi), %rax + mulq 88(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[12] * A[12] + movq 96(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %rcx + adcq %r11, %r8 + adcq %r12, %r9 + movq %rcx, 192(%rdi) + # A[10] * A[15] + movq 120(%rsi), %rax + mulq 80(%rsi) + xorq %rcx, %rcx + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[11] * A[14] + movq 112(%rsi), %rax + mulq 88(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[12] * A[13] + movq 104(%rsi), %rax + mulq 96(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %r8 + adcq %r11, %r9 + adcq %r12, %rcx + movq %r8, 200(%rdi) + # A[11] * A[15] + movq 120(%rsi), %rax + mulq 88(%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0, %r8 + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0, %r8 + # A[12] * A[14] + movq 112(%rsi), %rax + mulq 96(%rsi) + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0, %r8 + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0, %r8 + # A[13] * A[13] + movq 104(%rsi), %rax + mulq %rax + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0, %r8 + movq %r9, 208(%rdi) + # A[12] * A[15] + movq 120(%rsi), %rax + mulq 96(%rsi) + xorq %r9, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + # A[13] * A[14] + movq 112(%rsi), %rax + mulq 104(%rsi) + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + movq %rcx, 216(%rdi) + # A[13] * A[15] + movq 120(%rsi), %rax + mulq 104(%rsi) + xorq %rcx, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + # A[14] * A[14] + movq 112(%rsi), %rax + mulq %rax + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + movq %r8, 224(%rdi) + # A[14] * A[15] + movq 120(%rsi), %rax + mulq 112(%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0, %r8 + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0, %r8 + movq %r9, 232(%rdi) + # A[15] * A[15] + movq 120(%rsi), %rax + mulq %rax + addq %rax, %rcx + adcq %rdx, %r8 + movq %rcx, 240(%rdi) + movq %r8, 248(%rdi) + movq (%rsp), %rax + movq 8(%rsp), %rdx + movq 16(%rsp), %r10 + movq 24(%rsp), %r11 + movq %rax, (%rdi) + movq %rdx, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 32(%rsp), %rax + movq 40(%rsp), %rdx + movq 48(%rsp), %r10 + movq 56(%rsp), %r11 + movq %rax, 32(%rdi) + movq %rdx, 40(%rdi) + movq %r10, 48(%rdi) + movq %r11, 56(%rdi) + movq 64(%rsp), %rax + movq 72(%rsp), %rdx + movq 80(%rsp), %r10 + movq 88(%rsp), %r11 + movq %rax, 64(%rdi) + movq %rdx, 72(%rdi) + movq %r10, 80(%rdi) + movq %r11, 88(%rdi) + movq 96(%rsp), %rax + movq 104(%rsp), %rdx + movq 112(%rsp), %r10 + movq 120(%rsp), %r11 + movq %rax, 96(%rdi) + movq %rdx, 104(%rdi) + movq %r10, 112(%rdi) + movq %r11, 120(%rdi) + addq $128, %rsp + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_2048_sqr_16,.-sp_2048_sqr_16 +#endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 +/* Multiply a and b into r. (r = a * b) + * + * r Result of multiplication. + * a First number to multiply. + * b Second number to multiply. + */ +#ifndef __APPLE__ +.globl sp_2048_mul_avx2_16 +.type sp_2048_mul_avx2_16,@function +.align 16 +sp_2048_mul_avx2_16: +#else +.globl _sp_2048_mul_avx2_16 +.p2align 4 +_sp_2048_mul_avx2_16: +#endif /* __APPLE__ */ + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + push %rbx + movq %rdx, %rbp + subq $128, %rsp + movq $0, %r14 + movq (%rsi), %rdx + # A[0] * B[0] + mulx (%rbp), %r8, %r9 + # A[0] * B[1] + mulx 8(%rbp), %rax, %r10 + movq %r8, (%rsp) + adcxq %rax, %r9 + # A[0] * B[2] + mulx 16(%rbp), %rax, %r11 + movq %r9, 8(%rsp) + adcxq %rax, %r10 + # A[0] * B[3] + mulx 24(%rbp), %rax, %r12 + movq %r10, 16(%rsp) + adcxq %rax, %r11 + movq %r11, 24(%rsp) + # A[0] * B[4] + mulx 32(%rbp), %rax, %r8 + adcxq %rax, %r12 + # A[0] * B[5] + mulx 40(%rbp), %rax, %r9 + movq %r12, 32(%rsp) + adcxq %rax, %r8 + # A[0] * B[6] + mulx 48(%rbp), %rax, %r10 + movq %r8, 40(%rsp) + adcxq %rax, %r9 + # A[0] * B[7] + mulx 56(%rbp), %rax, %r11 + movq %r9, 48(%rsp) + adcxq %rax, %r10 + movq %r10, 56(%rsp) + # A[0] * B[8] + mulx 64(%rbp), %rax, %r12 + adcxq %rax, %r11 + # A[0] * B[9] + mulx 72(%rbp), %rax, %r8 + movq %r11, 64(%rsp) + adcxq %rax, %r12 + # A[0] * B[10] + mulx 80(%rbp), %rax, %r9 + movq %r12, 72(%rsp) + adcxq %rax, %r8 + # A[0] * B[11] + mulx 88(%rbp), %rax, %r10 + movq %r8, 80(%rsp) + adcxq %rax, %r9 + movq %r9, 88(%rsp) + # A[0] * B[12] + mulx 96(%rbp), %rax, %r11 + adcxq %rax, %r10 + # A[0] * B[13] + mulx 104(%rbp), %rax, %r12 + movq %r10, 96(%rsp) + adcxq %rax, %r11 + # A[0] * B[14] + mulx 112(%rbp), %rax, %r8 + movq %r11, 104(%rsp) + adcxq %rax, %r12 + # A[0] * B[15] + mulx 120(%rbp), %rax, %r9 + movq %r12, %r15 + adcxq %rax, %r8 + adcxq %r14, %r9 + movq %r14, %r13 + adcxq %r14, %r13 + movq %r8, %rbx + movq %r9, 128(%rdi) + movq 8(%rsi), %rdx + movq 8(%rsp), %r9 + movq 16(%rsp), %r10 + movq 24(%rsp), %r11 + movq 32(%rsp), %r12 + movq 40(%rsp), %r8 + # A[1] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[1] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r9, 8(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[1] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r10, 16(%rsp) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[1] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r11, 24(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + movq %r12, 32(%rsp) + movq 48(%rsp), %r9 + movq 56(%rsp), %r10 + movq 64(%rsp), %r11 + movq 72(%rsp), %r12 + # A[1] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[1] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r8, 40(%rsp) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[1] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r9, 48(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[1] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r10, 56(%rsp) + adcxq %rax, %r11 + adoxq %rcx, %r12 + movq %r11, 64(%rsp) + movq 80(%rsp), %r8 + movq 88(%rsp), %r9 + movq 96(%rsp), %r10 + movq 104(%rsp), %r11 + # A[1] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[1] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r12, 72(%rsp) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[1] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r8, 80(%rsp) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[1] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r9, 88(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 96(%rsp) + movq %r15, %r12 + movq %rbx, %r8 + movq 128(%rdi), %r9 + # A[1] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[1] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r11, 104(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[1] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r12, %r15 + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[1] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r8, %rbx + movq %r14, %r10 + adcxq %rax, %r9 + adoxq %rcx, %r10 + adcxq %r13, %r10 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r9, 128(%rdi) + movq %r10, 136(%rdi) + movq 16(%rsi), %rdx + movq 16(%rsp), %r10 + movq 24(%rsp), %r11 + movq 32(%rsp), %r12 + movq 40(%rsp), %r8 + movq 48(%rsp), %r9 + # A[2] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[2] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r10, 16(%rsp) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[2] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r11, 24(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[2] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r12, 32(%rsp) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 40(%rsp) + movq 56(%rsp), %r10 + movq 64(%rsp), %r11 + movq 72(%rsp), %r12 + movq 80(%rsp), %r8 + # A[2] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[2] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r9, 48(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[2] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r10, 56(%rsp) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[2] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r11, 64(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + movq %r12, 72(%rsp) + movq 88(%rsp), %r9 + movq 96(%rsp), %r10 + movq 104(%rsp), %r11 + movq %r15, %r12 + # A[2] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[2] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r8, 80(%rsp) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[2] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r9, 88(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[2] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r10, 96(%rsp) + adcxq %rax, %r11 + adoxq %rcx, %r12 + movq %r11, 104(%rsp) + movq %rbx, %r8 + movq 128(%rdi), %r9 + movq 136(%rdi), %r10 + # A[2] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[2] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r12, %r15 + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[2] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r8, %rbx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[2] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r9, 128(%rdi) + movq %r14, %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + adcxq %r13, %r11 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r10, 136(%rdi) + movq %r11, 144(%rdi) + movq 24(%rsi), %rdx + movq 24(%rsp), %r11 + movq 32(%rsp), %r12 + movq 40(%rsp), %r8 + movq 48(%rsp), %r9 + movq 56(%rsp), %r10 + # A[3] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[3] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r11, 24(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[3] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r12, 32(%rsp) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[3] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r8, 40(%rsp) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 48(%rsp) + movq 64(%rsp), %r11 + movq 72(%rsp), %r12 + movq 80(%rsp), %r8 + movq 88(%rsp), %r9 + # A[3] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[3] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r10, 56(%rsp) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[3] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r11, 64(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[3] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r12, 72(%rsp) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 80(%rsp) + movq 96(%rsp), %r10 + movq 104(%rsp), %r11 + movq %r15, %r12 + movq %rbx, %r8 + # A[3] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[3] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r9, 88(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[3] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r10, 96(%rsp) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[3] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r11, 104(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + movq %r12, %r15 + movq 128(%rdi), %r9 + movq 136(%rdi), %r10 + movq 144(%rdi), %r11 + # A[3] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[3] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r8, %rbx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[3] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r9, 128(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[3] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r10, 136(%rdi) + movq %r14, %r12 + adcxq %rax, %r11 + adoxq %rcx, %r12 + adcxq %r13, %r12 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r11, 144(%rdi) + movq %r12, 152(%rdi) + movq 32(%rsi), %rdx + movq 32(%rsp), %r12 + movq 40(%rsp), %r8 + movq 48(%rsp), %r9 + movq 56(%rsp), %r10 + movq 64(%rsp), %r11 + # A[4] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[4] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r12, 32(%rsp) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[4] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r8, 40(%rsp) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[4] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r9, 48(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 56(%rsp) + movq 72(%rsp), %r12 + movq 80(%rsp), %r8 + movq 88(%rsp), %r9 + movq 96(%rsp), %r10 + # A[4] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[4] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r11, 64(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[4] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r12, 72(%rsp) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[4] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r8, 80(%rsp) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 88(%rsp) + movq 104(%rsp), %r11 + movq %r15, %r12 + movq %rbx, %r8 + movq 128(%rdi), %r9 + # A[4] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[4] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r10, 96(%rsp) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[4] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r11, 104(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[4] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r12, %r15 + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, %rbx + movq 136(%rdi), %r10 + movq 144(%rdi), %r11 + movq 152(%rdi), %r12 + # A[4] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[4] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r9, 128(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[4] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r10, 136(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[4] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r11, 144(%rdi) + movq %r14, %r8 + adcxq %rax, %r12 + adoxq %rcx, %r8 + adcxq %r13, %r8 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r12, 152(%rdi) + movq %r8, 160(%rdi) + movq 40(%rsi), %rdx + movq 40(%rsp), %r8 + movq 48(%rsp), %r9 + movq 56(%rsp), %r10 + movq 64(%rsp), %r11 + movq 72(%rsp), %r12 + # A[5] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[5] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r8, 40(%rsp) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[5] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r9, 48(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[5] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r10, 56(%rsp) + adcxq %rax, %r11 + adoxq %rcx, %r12 + movq %r11, 64(%rsp) + movq 80(%rsp), %r8 + movq 88(%rsp), %r9 + movq 96(%rsp), %r10 + movq 104(%rsp), %r11 + # A[5] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[5] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r12, 72(%rsp) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[5] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r8, 80(%rsp) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[5] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r9, 88(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 96(%rsp) + movq %r15, %r12 + movq %rbx, %r8 + movq 128(%rdi), %r9 + movq 136(%rdi), %r10 + # A[5] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[5] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r11, 104(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[5] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r12, %r15 + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[5] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r8, %rbx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 128(%rdi) + movq 144(%rdi), %r11 + movq 152(%rdi), %r12 + movq 160(%rdi), %r8 + # A[5] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[5] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r10, 136(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[5] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r11, 144(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[5] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r12, 152(%rdi) + movq %r14, %r9 + adcxq %rax, %r8 + adoxq %rcx, %r9 + adcxq %r13, %r9 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r8, 160(%rdi) + movq %r9, 168(%rdi) + movq 48(%rsi), %rdx + movq 48(%rsp), %r9 + movq 56(%rsp), %r10 + movq 64(%rsp), %r11 + movq 72(%rsp), %r12 + movq 80(%rsp), %r8 + # A[6] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[6] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r9, 48(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[6] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r10, 56(%rsp) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[6] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r11, 64(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + movq %r12, 72(%rsp) + movq 88(%rsp), %r9 + movq 96(%rsp), %r10 + movq 104(%rsp), %r11 + movq %r15, %r12 + # A[6] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[6] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r8, 80(%rsp) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[6] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r9, 88(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[6] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r10, 96(%rsp) + adcxq %rax, %r11 + adoxq %rcx, %r12 + movq %r11, 104(%rsp) + movq %rbx, %r8 + movq 128(%rdi), %r9 + movq 136(%rdi), %r10 + movq 144(%rdi), %r11 + # A[6] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[6] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r12, %r15 + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[6] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r8, %rbx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[6] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r9, 128(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 136(%rdi) + movq 152(%rdi), %r12 + movq 160(%rdi), %r8 + movq 168(%rdi), %r9 + # A[6] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[6] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r11, 144(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[6] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r12, 152(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[6] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r8, 160(%rdi) + movq %r14, %r10 + adcxq %rax, %r9 + adoxq %rcx, %r10 + adcxq %r13, %r10 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r9, 168(%rdi) + movq %r10, 176(%rdi) + movq 56(%rsi), %rdx + movq 56(%rsp), %r10 + movq 64(%rsp), %r11 + movq 72(%rsp), %r12 + movq 80(%rsp), %r8 + movq 88(%rsp), %r9 + # A[7] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[7] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r10, 56(%rsp) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[7] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r11, 64(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[7] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r12, 72(%rsp) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 80(%rsp) + movq 96(%rsp), %r10 + movq 104(%rsp), %r11 + movq %r15, %r12 + movq %rbx, %r8 + # A[7] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[7] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r9, 88(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[7] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r10, 96(%rsp) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[7] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r11, 104(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + movq %r12, %r15 + movq 128(%rdi), %r9 + movq 136(%rdi), %r10 + movq 144(%rdi), %r11 + movq 152(%rdi), %r12 + # A[7] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[7] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r8, %rbx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[7] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r9, 128(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[7] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r10, 136(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + movq %r11, 144(%rdi) + movq 160(%rdi), %r8 + movq 168(%rdi), %r9 + movq 176(%rdi), %r10 + # A[7] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[7] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r12, 152(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[7] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r8, 160(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[7] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r9, 168(%rdi) + movq %r14, %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + adcxq %r13, %r11 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r10, 176(%rdi) + movq %r11, 184(%rdi) + movq 64(%rsi), %rdx + movq 64(%rsp), %r11 + movq 72(%rsp), %r12 + movq 80(%rsp), %r8 + movq 88(%rsp), %r9 + movq 96(%rsp), %r10 + # A[8] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[8] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r11, 64(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[8] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r12, 72(%rsp) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[8] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r8, 80(%rsp) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 88(%rsp) + movq 104(%rsp), %r11 + movq %r15, %r12 + movq %rbx, %r8 + movq 128(%rdi), %r9 + # A[8] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[8] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r10, 96(%rsp) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[8] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r11, 104(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[8] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r12, %r15 + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, %rbx + movq 136(%rdi), %r10 + movq 144(%rdi), %r11 + movq 152(%rdi), %r12 + movq 160(%rdi), %r8 + # A[8] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[8] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r9, 128(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[8] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r10, 136(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[8] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r11, 144(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + movq %r12, 152(%rdi) + movq 168(%rdi), %r9 + movq 176(%rdi), %r10 + movq 184(%rdi), %r11 + # A[8] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[8] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r8, 160(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[8] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r9, 168(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[8] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r10, 176(%rdi) + movq %r14, %r12 + adcxq %rax, %r11 + adoxq %rcx, %r12 + adcxq %r13, %r12 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r11, 184(%rdi) + movq %r12, 192(%rdi) + movq 72(%rsi), %rdx + movq 72(%rsp), %r12 + movq 80(%rsp), %r8 + movq 88(%rsp), %r9 + movq 96(%rsp), %r10 + movq 104(%rsp), %r11 + # A[9] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[9] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r12, 72(%rsp) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[9] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r8, 80(%rsp) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[9] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r9, 88(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 96(%rsp) + movq %r15, %r12 + movq %rbx, %r8 + movq 128(%rdi), %r9 + movq 136(%rdi), %r10 + # A[9] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[9] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r11, 104(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[9] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r12, %r15 + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[9] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r8, %rbx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 128(%rdi) + movq 144(%rdi), %r11 + movq 152(%rdi), %r12 + movq 160(%rdi), %r8 + movq 168(%rdi), %r9 + # A[9] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[9] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r10, 136(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[9] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r11, 144(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[9] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r12, 152(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 160(%rdi) + movq 176(%rdi), %r10 + movq 184(%rdi), %r11 + movq 192(%rdi), %r12 + # A[9] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[9] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r9, 168(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[9] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r10, 176(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[9] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r11, 184(%rdi) + movq %r14, %r8 + adcxq %rax, %r12 + adoxq %rcx, %r8 + adcxq %r13, %r8 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r12, 192(%rdi) + movq %r8, 200(%rdi) + movq 80(%rsi), %rdx + movq 80(%rsp), %r8 + movq 88(%rsp), %r9 + movq 96(%rsp), %r10 + movq 104(%rsp), %r11 + movq %r15, %r12 + # A[10] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[10] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r8, 80(%rsp) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[10] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r9, 88(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[10] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r10, 96(%rsp) + adcxq %rax, %r11 + adoxq %rcx, %r12 + movq %r11, 104(%rsp) + movq %rbx, %r8 + movq 128(%rdi), %r9 + movq 136(%rdi), %r10 + movq 144(%rdi), %r11 + # A[10] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[10] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r12, %r15 + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[10] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r8, %rbx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[10] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r9, 128(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 136(%rdi) + movq 152(%rdi), %r12 + movq 160(%rdi), %r8 + movq 168(%rdi), %r9 + movq 176(%rdi), %r10 + # A[10] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[10] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r11, 144(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[10] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r12, 152(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[10] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r8, 160(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 168(%rdi) + movq 184(%rdi), %r11 + movq 192(%rdi), %r12 + movq 200(%rdi), %r8 + # A[10] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[10] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r10, 176(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[10] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r11, 184(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[10] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r12, 192(%rdi) + movq %r14, %r9 + adcxq %rax, %r8 + adoxq %rcx, %r9 + adcxq %r13, %r9 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r8, 200(%rdi) + movq %r9, 208(%rdi) + movq 88(%rsi), %rdx + movq 88(%rsp), %r9 + movq 96(%rsp), %r10 + movq 104(%rsp), %r11 + movq %r15, %r12 + movq %rbx, %r8 + # A[11] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[11] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r9, 88(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[11] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r10, 96(%rsp) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[11] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r11, 104(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + movq %r12, %r15 + movq 128(%rdi), %r9 + movq 136(%rdi), %r10 + movq 144(%rdi), %r11 + movq 152(%rdi), %r12 + # A[11] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[11] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r8, %rbx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[11] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r9, 128(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[11] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r10, 136(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + movq %r11, 144(%rdi) + movq 160(%rdi), %r8 + movq 168(%rdi), %r9 + movq 176(%rdi), %r10 + movq 184(%rdi), %r11 + # A[11] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[11] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r12, 152(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[11] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r8, 160(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[11] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r9, 168(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 176(%rdi) + movq 192(%rdi), %r12 + movq 200(%rdi), %r8 + movq 208(%rdi), %r9 + # A[11] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[11] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r11, 184(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[11] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r12, 192(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[11] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r8, 200(%rdi) + movq %r14, %r10 + adcxq %rax, %r9 + adoxq %rcx, %r10 + adcxq %r13, %r10 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r9, 208(%rdi) + movq %r10, 216(%rdi) + movq 96(%rsi), %rdx + movq 96(%rsp), %r10 + movq 104(%rsp), %r11 + movq %r15, %r12 + movq %rbx, %r8 + movq 128(%rdi), %r9 + # A[12] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[12] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r10, 96(%rsp) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[12] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r11, 104(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[12] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r12, %r15 + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, %rbx + movq 136(%rdi), %r10 + movq 144(%rdi), %r11 + movq 152(%rdi), %r12 + movq 160(%rdi), %r8 + # A[12] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[12] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r9, 128(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[12] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r10, 136(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[12] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r11, 144(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + movq %r12, 152(%rdi) + movq 168(%rdi), %r9 + movq 176(%rdi), %r10 + movq 184(%rdi), %r11 + movq 192(%rdi), %r12 + # A[12] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[12] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r8, 160(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[12] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r9, 168(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[12] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r10, 176(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + movq %r11, 184(%rdi) + movq 200(%rdi), %r8 + movq 208(%rdi), %r9 + movq 216(%rdi), %r10 + # A[12] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[12] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r12, 192(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[12] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r8, 200(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[12] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r9, 208(%rdi) + movq %r14, %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + adcxq %r13, %r11 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r10, 216(%rdi) + movq %r11, 224(%rdi) + movq 104(%rsi), %rdx + movq 104(%rsp), %r11 + movq %r15, %r12 + movq %rbx, %r8 + movq 128(%rdi), %r9 + movq 136(%rdi), %r10 + # A[13] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[13] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r11, 104(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[13] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r12, %r15 + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[13] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r8, %rbx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 128(%rdi) + movq 144(%rdi), %r11 + movq 152(%rdi), %r12 + movq 160(%rdi), %r8 + movq 168(%rdi), %r9 + # A[13] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[13] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r10, 136(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[13] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r11, 144(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[13] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r12, 152(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 160(%rdi) + movq 176(%rdi), %r10 + movq 184(%rdi), %r11 + movq 192(%rdi), %r12 + movq 200(%rdi), %r8 + # A[13] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[13] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r9, 168(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[13] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r10, 176(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[13] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r11, 184(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + movq %r12, 192(%rdi) + movq 208(%rdi), %r9 + movq 216(%rdi), %r10 + movq 224(%rdi), %r11 + # A[13] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[13] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r8, 200(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[13] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r9, 208(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[13] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r10, 216(%rdi) + movq %r14, %r12 + adcxq %rax, %r11 + adoxq %rcx, %r12 + adcxq %r13, %r12 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r11, 224(%rdi) + movq %r12, 232(%rdi) + movq 112(%rsi), %rdx + movq %r15, %r12 + movq %rbx, %r8 + movq 128(%rdi), %r9 + movq 136(%rdi), %r10 + movq 144(%rdi), %r11 + # A[14] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[14] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r12, %r15 + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[14] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r8, %rbx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[14] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r9, 128(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 136(%rdi) + movq 152(%rdi), %r12 + movq 160(%rdi), %r8 + movq 168(%rdi), %r9 + movq 176(%rdi), %r10 + # A[14] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[14] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r11, 144(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[14] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r12, 152(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[14] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r8, 160(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 168(%rdi) + movq 184(%rdi), %r11 + movq 192(%rdi), %r12 + movq 200(%rdi), %r8 + movq 208(%rdi), %r9 + # A[14] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[14] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r10, 176(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[14] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r11, 184(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[14] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r12, 192(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 200(%rdi) + movq 216(%rdi), %r10 + movq 224(%rdi), %r11 + movq 232(%rdi), %r12 + # A[14] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[14] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r9, 208(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[14] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r10, 216(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[14] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r11, 224(%rdi) + movq %r14, %r8 + adcxq %rax, %r12 + adoxq %rcx, %r8 + adcxq %r13, %r8 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r12, 232(%rdi) + movq %r8, 240(%rdi) + movq 120(%rsi), %rdx + movq %rbx, %r8 + movq 128(%rdi), %r9 + movq 136(%rdi), %r10 + movq 144(%rdi), %r11 + movq 152(%rdi), %r12 + # A[15] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[15] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r8, %rbx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[15] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r9, 128(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[15] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r10, 136(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + movq %r11, 144(%rdi) + movq 160(%rdi), %r8 + movq 168(%rdi), %r9 + movq 176(%rdi), %r10 + movq 184(%rdi), %r11 + # A[15] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[15] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r12, 152(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[15] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r8, 160(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[15] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r9, 168(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 176(%rdi) + movq 192(%rdi), %r12 + movq 200(%rdi), %r8 + movq 208(%rdi), %r9 + movq 216(%rdi), %r10 + # A[15] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[15] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r11, 184(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[15] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r12, 192(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[15] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r8, 200(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 208(%rdi) + movq 224(%rdi), %r11 + movq 232(%rdi), %r12 + movq 240(%rdi), %r8 + # A[15] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[15] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r10, 216(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[15] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r11, 224(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[15] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r12, 232(%rdi) + movq %r14, %r9 + adcxq %rax, %r8 + adoxq %rcx, %r9 + adcxq %r13, %r9 + movq %r8, 240(%rdi) + movq %r9, 248(%rdi) + movq (%rsp), %r8 + movq 8(%rsp), %r9 + movq 16(%rsp), %r10 + movq 24(%rsp), %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 32(%rsp), %r8 + movq 40(%rsp), %r9 + movq 48(%rsp), %r10 + movq 56(%rsp), %r11 + movq %r8, 32(%rdi) + movq %r9, 40(%rdi) + movq %r10, 48(%rdi) + movq %r11, 56(%rdi) + movq 64(%rsp), %r8 + movq 72(%rsp), %r9 + movq 80(%rsp), %r10 + movq 88(%rsp), %r11 + movq %r8, 64(%rdi) + movq %r9, 72(%rdi) + movq %r10, 80(%rdi) + movq %r11, 88(%rdi) + movq 96(%rsp), %r8 + movq 104(%rsp), %r9 + movq %r15, %r10 + movq %rbx, %r11 + movq %r8, 96(%rdi) + movq %r9, 104(%rdi) + movq %r10, 112(%rdi) + movq %r11, 120(%rdi) + addq $128, %rsp + pop %rbx + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + repz retq +#ifndef __APPLE__ +.size sp_2048_mul_avx2_16,.-sp_2048_mul_avx2_16 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +#ifdef HAVE_INTEL_AVX2 +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_2048_sqr_avx2_16 +.type sp_2048_sqr_avx2_16,@function +.align 16 +sp_2048_sqr_avx2_16: +#else +.globl _sp_2048_sqr_avx2_16 +.p2align 4 +_sp_2048_sqr_avx2_16: +#endif /* __APPLE__ */ + push %rbp + push %r12 + push %r13 + subq $128, %rsp + cmpq %rdi, %rsi + movq %rsp, %rbp + cmovne %rdi, %rbp + xorq %r12, %r12 + # Diagonal 1 + xorq %r8, %r8 + xorq %r9, %r9 + xorq %r10, %r10 + xorq %r11, %r11 + # A[1] x A[0] + movq (%rsi), %rdx + mulxq 8(%rsi), %r8, %r9 + # A[2] x A[0] + mulxq 16(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[3] x A[0] + mulxq 24(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r8, 8(%rbp) + movq %r9, 16(%rbp) + movq %r10, 24(%rbp) + movq %r12, %r8 + movq %r12, %r9 + movq %r12, %r10 + # A[4] x A[0] + mulxq 32(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[5] x A[0] + mulxq 40(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[6] x A[0] + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r11, 32(%rbp) + movq %r8, 40(%rbp) + movq %r9, 48(%rbp) + movq %r12, %r11 + movq %r12, %r8 + movq %r12, %r9 + # A[7] x A[0] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[8] x A[0] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[9] x A[0] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r10, 56(%rbp) + movq %r11, 64(%rbp) + movq %r8, 72(%rbp) + movq %r12, %r10 + movq %r12, %r11 + movq %r12, %r8 + # A[10] x A[0] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[11] x A[0] + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[12] x A[0] + mulxq 96(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + movq %r9, 80(%rbp) + movq %r10, 88(%rbp) + movq %r11, 96(%rbp) + movq %r12, %r9 + movq %r12, %r10 + movq %r12, %r11 + # A[13] x A[0] + mulxq 104(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[14] x A[0] + mulxq 112(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[15] x A[0] + mulxq 120(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r8, 104(%rbp) + movq %r9, 112(%rbp) + movq %r10, 120(%rbp) + # Carry + adcxq %r12, %r11 + movq %r12, %r13 + adcxq %r12, %r13 + adoxq %r12, %r13 + movq %r11, 128(%rdi) + # Diagonal 2 + movq 24(%rbp), %r11 + movq 32(%rbp), %r8 + movq 40(%rbp), %r9 + movq 48(%rbp), %r10 + # A[2] x A[1] + movq 8(%rsi), %rdx + mulxq 16(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[3] x A[1] + mulxq 24(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[4] x A[1] + mulxq 32(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r11, 24(%rbp) + movq %r8, 32(%rbp) + movq %r9, 40(%rbp) + movq 56(%rbp), %r11 + movq 64(%rbp), %r8 + movq 72(%rbp), %r9 + # A[5] x A[1] + mulxq 40(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[6] x A[1] + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[7] x A[1] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r10, 48(%rbp) + movq %r11, 56(%rbp) + movq %r8, 64(%rbp) + movq 80(%rbp), %r10 + movq 88(%rbp), %r11 + movq 96(%rbp), %r8 + # A[8] x A[1] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[9] x A[1] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[10] x A[1] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + movq %r9, 72(%rbp) + movq %r10, 80(%rbp) + movq %r11, 88(%rbp) + movq 104(%rbp), %r9 + movq 112(%rbp), %r10 + movq 120(%rbp), %r11 + # A[11] x A[1] + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[12] x A[1] + mulxq 96(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[13] x A[1] + mulxq 104(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r8, 96(%rbp) + movq %r9, 104(%rbp) + movq %r10, 112(%rbp) + movq 128(%rdi), %r8 + movq %r12, %r9 + movq %r12, %r10 + # A[14] x A[1] + mulxq 112(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[15] x A[1] + mulxq 120(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[15] x A[2] + movq 16(%rsi), %rdx + mulxq 120(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r11, 120(%rbp) + movq %r8, 128(%rdi) + movq %r9, 136(%rdi) + # Carry + adcxq %r13, %r10 + movq %r12, %r13 + adcxq %r12, %r13 + adoxq %r12, %r13 + movq %r10, 144(%rdi) + # Diagonal 3 + movq 40(%rbp), %r10 + movq 48(%rbp), %r11 + movq 56(%rbp), %r8 + movq 64(%rbp), %r9 + # A[3] x A[2] + mulxq 24(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[4] x A[2] + mulxq 32(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[5] x A[2] + mulxq 40(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r10, 40(%rbp) + movq %r11, 48(%rbp) + movq %r8, 56(%rbp) + movq 72(%rbp), %r10 + movq 80(%rbp), %r11 + movq 88(%rbp), %r8 + # A[6] x A[2] + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[7] x A[2] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[8] x A[2] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + movq %r9, 64(%rbp) + movq %r10, 72(%rbp) + movq %r11, 80(%rbp) + movq 96(%rbp), %r9 + movq 104(%rbp), %r10 + movq 112(%rbp), %r11 + # A[9] x A[2] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[10] x A[2] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[11] x A[2] + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r8, 88(%rbp) + movq %r9, 96(%rbp) + movq %r10, 104(%rbp) + movq 120(%rbp), %r8 + movq 128(%rdi), %r9 + movq 136(%rdi), %r10 + # A[12] x A[2] + mulxq 96(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[13] x A[2] + mulxq 104(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[14] x A[2] + mulxq 112(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r11, 112(%rbp) + movq %r8, 120(%rbp) + movq %r9, 128(%rdi) + movq 144(%rdi), %r11 + movq %r12, %r8 + movq %r12, %r9 + # A[14] x A[3] + movq 112(%rsi), %rdx + mulxq 24(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[14] x A[4] + mulxq 32(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[14] x A[5] + mulxq 40(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r10, 136(%rdi) + movq %r11, 144(%rdi) + movq %r8, 152(%rdi) + # Carry + adcxq %r13, %r9 + movq %r12, %r13 + adcxq %r12, %r13 + adoxq %r12, %r13 + movq %r9, 160(%rdi) + # Diagonal 4 + movq 56(%rbp), %r9 + movq 64(%rbp), %r10 + movq 72(%rbp), %r11 + movq 80(%rbp), %r8 + # A[4] x A[3] + movq 24(%rsi), %rdx + mulxq 32(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[5] x A[3] + mulxq 40(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[6] x A[3] + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + movq %r9, 56(%rbp) + movq %r10, 64(%rbp) + movq %r11, 72(%rbp) + movq 88(%rbp), %r9 + movq 96(%rbp), %r10 + movq 104(%rbp), %r11 + # A[7] x A[3] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[8] x A[3] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[9] x A[3] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r8, 80(%rbp) + movq %r9, 88(%rbp) + movq %r10, 96(%rbp) + movq 112(%rbp), %r8 + movq 120(%rbp), %r9 + movq 128(%rdi), %r10 + # A[10] x A[3] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[11] x A[3] + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[12] x A[3] + mulxq 96(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r11, 104(%rbp) + movq %r8, 112(%rbp) + movq %r9, 120(%rbp) + movq 136(%rdi), %r11 + movq 144(%rdi), %r8 + movq 152(%rdi), %r9 + # A[13] x A[3] + mulxq 104(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[13] x A[4] + movq 104(%rsi), %rdx + mulxq 32(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[13] x A[5] + mulxq 40(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r10, 128(%rdi) + movq %r11, 136(%rdi) + movq %r8, 144(%rdi) + movq 160(%rdi), %r10 + movq %r12, %r11 + movq %r12, %r8 + # A[13] x A[6] + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[13] x A[7] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[13] x A[8] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + movq %r9, 152(%rdi) + movq %r10, 160(%rdi) + movq %r11, 168(%rdi) + # Carry + adcxq %r13, %r8 + movq %r12, %r13 + adcxq %r12, %r13 + adoxq %r12, %r13 + movq %r8, 176(%rdi) + # Diagonal 5 + movq 72(%rbp), %r8 + movq 80(%rbp), %r9 + movq 88(%rbp), %r10 + movq 96(%rbp), %r11 + # A[5] x A[4] + movq 32(%rsi), %rdx + mulxq 40(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[6] x A[4] + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[7] x A[4] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r8, 72(%rbp) + movq %r9, 80(%rbp) + movq %r10, 88(%rbp) + movq 104(%rbp), %r8 + movq 112(%rbp), %r9 + movq 120(%rbp), %r10 + # A[8] x A[4] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[9] x A[4] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[10] x A[4] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r11, 96(%rbp) + movq %r8, 104(%rbp) + movq %r9, 112(%rbp) + movq 128(%rdi), %r11 + movq 136(%rdi), %r8 + movq 144(%rdi), %r9 + # A[11] x A[4] + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[12] x A[4] + mulxq 96(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[12] x A[5] + movq 96(%rsi), %rdx + mulxq 40(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r10, 120(%rbp) + movq %r11, 128(%rdi) + movq %r8, 136(%rdi) + movq 152(%rdi), %r10 + movq 160(%rdi), %r11 + movq 168(%rdi), %r8 + # A[12] x A[6] + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[12] x A[7] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[12] x A[8] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + movq %r9, 144(%rdi) + movq %r10, 152(%rdi) + movq %r11, 160(%rdi) + movq 176(%rdi), %r9 + movq %r12, %r10 + movq %r12, %r11 + # A[12] x A[9] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[12] x A[10] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[12] x A[11] + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r8, 168(%rdi) + movq %r9, 176(%rdi) + movq %r10, 184(%rdi) + # Carry + adcxq %r13, %r11 + movq %r12, %r13 + adcxq %r12, %r13 + adoxq %r12, %r13 + movq %r11, 192(%rdi) + # Diagonal 6 + movq 88(%rbp), %r11 + movq 96(%rbp), %r8 + movq 104(%rbp), %r9 + movq 112(%rbp), %r10 + # A[6] x A[5] + movq 40(%rsi), %rdx + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[7] x A[5] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[8] x A[5] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r11, 88(%rbp) + movq %r8, 96(%rbp) + movq %r9, 104(%rbp) + movq 120(%rbp), %r11 + movq 128(%rdi), %r8 + movq 136(%rdi), %r9 + # A[9] x A[5] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[10] x A[5] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[11] x A[5] + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r10, 112(%rbp) + movq %r11, 120(%rbp) + movq %r8, 128(%rdi) + movq 144(%rdi), %r10 + movq 152(%rdi), %r11 + movq 160(%rdi), %r8 + # A[11] x A[6] + movq 88(%rsi), %rdx + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[11] x A[7] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[11] x A[8] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + movq %r9, 136(%rdi) + movq %r10, 144(%rdi) + movq %r11, 152(%rdi) + movq 168(%rdi), %r9 + movq 176(%rdi), %r10 + movq 184(%rdi), %r11 + # A[11] x A[9] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[11] x A[10] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[13] x A[9] + movq 104(%rsi), %rdx + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r8, 160(%rdi) + movq %r9, 168(%rdi) + movq %r10, 176(%rdi) + movq 192(%rdi), %r8 + movq %r12, %r9 + movq %r12, %r10 + # A[13] x A[10] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[13] x A[11] + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[13] x A[12] + mulxq 96(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r11, 184(%rdi) + movq %r8, 192(%rdi) + movq %r9, 200(%rdi) + # Carry + adcxq %r13, %r10 + movq %r12, %r13 + adcxq %r12, %r13 + adoxq %r12, %r13 + movq %r10, 208(%rdi) + # Diagonal 7 + movq 104(%rbp), %r10 + movq 112(%rbp), %r11 + movq 120(%rbp), %r8 + movq 128(%rdi), %r9 + # A[7] x A[6] + movq 48(%rsi), %rdx + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[8] x A[6] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[9] x A[6] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r10, 104(%rbp) + movq %r11, 112(%rbp) + movq %r8, 120(%rbp) + movq 136(%rdi), %r10 + movq 144(%rdi), %r11 + movq 152(%rdi), %r8 + # A[10] x A[6] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[10] x A[7] + movq 80(%rsi), %rdx + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[10] x A[8] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + movq %r9, 128(%rdi) + movq %r10, 136(%rdi) + movq %r11, 144(%rdi) + movq 160(%rdi), %r9 + movq 168(%rdi), %r10 + movq 176(%rdi), %r11 + # A[10] x A[9] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[14] x A[6] + movq 112(%rsi), %rdx + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[14] x A[7] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r8, 152(%rdi) + movq %r9, 160(%rdi) + movq %r10, 168(%rdi) + movq 184(%rdi), %r8 + movq 192(%rdi), %r9 + movq 200(%rdi), %r10 + # A[14] x A[8] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[14] x A[9] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[14] x A[10] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r11, 176(%rdi) + movq %r8, 184(%rdi) + movq %r9, 192(%rdi) + movq 208(%rdi), %r11 + movq %r12, %r8 + movq %r12, %r9 + # A[14] x A[11] + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[14] x A[12] + mulxq 96(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[14] x A[13] + mulxq 104(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r10, 200(%rdi) + movq %r11, 208(%rdi) + movq %r8, 216(%rdi) + # Carry + adcxq %r13, %r9 + movq %r12, %r13 + adcxq %r12, %r13 + adoxq %r12, %r13 + movq %r9, 224(%rdi) + # Diagonal 8 + movq 120(%rbp), %r9 + movq 128(%rdi), %r10 + movq 136(%rdi), %r11 + movq 144(%rdi), %r8 + # A[8] x A[7] + movq 56(%rsi), %rdx + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[9] x A[7] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[9] x A[8] + movq 64(%rsi), %rdx + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + movq %r9, 120(%rbp) + movq %r10, 128(%rdi) + movq %r11, 136(%rdi) + movq 152(%rdi), %r9 + movq 160(%rdi), %r10 + movq 168(%rdi), %r11 + # A[15] x A[3] + movq 120(%rsi), %rdx + mulxq 24(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[15] x A[4] + mulxq 32(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[15] x A[5] + mulxq 40(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r8, 144(%rdi) + movq %r9, 152(%rdi) + movq %r10, 160(%rdi) + movq 176(%rdi), %r8 + movq 184(%rdi), %r9 + movq 192(%rdi), %r10 + # A[15] x A[6] + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[15] x A[7] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[15] x A[8] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r11, 168(%rdi) + movq %r8, 176(%rdi) + movq %r9, 184(%rdi) + movq 200(%rdi), %r11 + movq 208(%rdi), %r8 + movq 216(%rdi), %r9 + # A[15] x A[9] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[15] x A[10] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[15] x A[11] + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r10, 192(%rdi) + movq %r11, 200(%rdi) + movq %r8, 208(%rdi) + movq 224(%rdi), %r10 + movq %r12, %r11 + movq %r12, %r8 + # A[15] x A[12] + mulxq 96(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[15] x A[13] + mulxq 104(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[15] x A[14] + mulxq 112(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + movq %r9, 216(%rdi) + movq %r10, 224(%rdi) + movq %r11, 232(%rdi) + # Carry + adcxq %r13, %r8 + movq %r12, %r13 + adcxq %r12, %r13 + adoxq %r12, %r13 + movq %r8, 240(%rdi) + movq %r13, 248(%rdi) + # Double and Add in A[i] x A[i] + movq 8(%rbp), %r9 + # A[0] x A[0] + movq (%rsi), %rdx + mulxq %rdx, %rax, %rcx + movq %rax, (%rbp) + adoxq %r9, %r9 + adcxq %rcx, %r9 + movq %r9, 8(%rbp) + movq 16(%rbp), %r8 + movq 24(%rbp), %r9 + # A[1] x A[1] + movq 8(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adcxq %rax, %r8 + adoxq %r9, %r9 + adcxq %rcx, %r9 + movq %r8, 16(%rbp) + movq %r9, 24(%rbp) + movq 32(%rbp), %r8 + movq 40(%rbp), %r9 + # A[2] x A[2] + movq 16(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adcxq %rax, %r8 + adoxq %r9, %r9 + adcxq %rcx, %r9 + movq %r8, 32(%rbp) + movq %r9, 40(%rbp) + movq 48(%rbp), %r8 + movq 56(%rbp), %r9 + # A[3] x A[3] + movq 24(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adcxq %rax, %r8 + adoxq %r9, %r9 + adcxq %rcx, %r9 + movq %r8, 48(%rbp) + movq %r9, 56(%rbp) + movq 64(%rbp), %r8 + movq 72(%rbp), %r9 + # A[4] x A[4] + movq 32(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adcxq %rax, %r8 + adoxq %r9, %r9 + adcxq %rcx, %r9 + movq %r8, 64(%rbp) + movq %r9, 72(%rbp) + movq 80(%rbp), %r8 + movq 88(%rbp), %r9 + # A[5] x A[5] + movq 40(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adcxq %rax, %r8 + adoxq %r9, %r9 + adcxq %rcx, %r9 + movq %r8, 80(%rbp) + movq %r9, 88(%rbp) + movq 96(%rbp), %r8 + movq 104(%rbp), %r9 + # A[6] x A[6] + movq 48(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adcxq %rax, %r8 + adoxq %r9, %r9 + adcxq %rcx, %r9 + movq %r8, 96(%rbp) + movq %r9, 104(%rbp) + movq 112(%rbp), %r8 + movq 120(%rbp), %r9 + # A[7] x A[7] + movq 56(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adcxq %rax, %r8 + adoxq %r9, %r9 + adcxq %rcx, %r9 + movq %r8, 112(%rbp) + movq %r9, 120(%rbp) + movq 128(%rdi), %r8 + movq 136(%rdi), %r9 + # A[8] x A[8] + movq 64(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adcxq %rax, %r8 + adoxq %r9, %r9 + adcxq %rcx, %r9 + movq %r8, 128(%rdi) + movq %r9, 136(%rdi) + movq 144(%rdi), %r8 + movq 152(%rdi), %r9 + # A[9] x A[9] + movq 72(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adcxq %rax, %r8 + adoxq %r9, %r9 + adcxq %rcx, %r9 + movq %r8, 144(%rdi) + movq %r9, 152(%rdi) + movq 160(%rdi), %r8 + movq 168(%rdi), %r9 + # A[10] x A[10] + movq 80(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adcxq %rax, %r8 + adoxq %r9, %r9 + adcxq %rcx, %r9 + movq %r8, 160(%rdi) + movq %r9, 168(%rdi) + movq 176(%rdi), %r8 + movq 184(%rdi), %r9 + # A[11] x A[11] + movq 88(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adcxq %rax, %r8 + adoxq %r9, %r9 + adcxq %rcx, %r9 + movq %r8, 176(%rdi) + movq %r9, 184(%rdi) + movq 192(%rdi), %r8 + movq 200(%rdi), %r9 + # A[12] x A[12] + movq 96(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adcxq %rax, %r8 + adoxq %r9, %r9 + adcxq %rcx, %r9 + movq %r8, 192(%rdi) + movq %r9, 200(%rdi) + movq 208(%rdi), %r8 + movq 216(%rdi), %r9 + # A[13] x A[13] + movq 104(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adcxq %rax, %r8 + adoxq %r9, %r9 + adcxq %rcx, %r9 + movq %r8, 208(%rdi) + movq %r9, 216(%rdi) + movq 224(%rdi), %r8 + movq 232(%rdi), %r9 + # A[14] x A[14] + movq 112(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adcxq %rax, %r8 + adoxq %r9, %r9 + adcxq %rcx, %r9 + movq %r8, 224(%rdi) + movq %r9, 232(%rdi) + movq 240(%rdi), %r8 + movq 248(%rdi), %r9 + # A[15] x A[15] + movq 120(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adcxq %rax, %r8 + adoxq %r9, %r9 + adcxq %rcx, %r9 + movq %r8, 240(%rdi) + movq %r9, 248(%rdi) + cmpq %rdi, %rsi + jne L_end_2048_sqr_avx2_16 + movq (%rbp), %r8 + movq 8(%rbp), %r9 + movq 16(%rbp), %r10 + movq 24(%rbp), %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 32(%rbp), %r8 + movq 40(%rbp), %r9 + movq 48(%rbp), %r10 + movq 56(%rbp), %r11 + movq %r8, 32(%rdi) + movq %r9, 40(%rdi) + movq %r10, 48(%rdi) + movq %r11, 56(%rdi) + movq 64(%rbp), %r8 + movq 72(%rbp), %r9 + movq 80(%rbp), %r10 + movq 88(%rbp), %r11 + movq %r8, 64(%rdi) + movq %r9, 72(%rdi) + movq %r10, 80(%rdi) + movq %r11, 88(%rdi) + movq 96(%rbp), %r8 + movq 104(%rbp), %r9 + movq 112(%rbp), %r10 + movq 120(%rbp), %r11 + movq %r8, 96(%rdi) + movq %r9, 104(%rdi) + movq %r10, 112(%rdi) + movq %r11, 120(%rdi) +L_end_2048_sqr_avx2_16: + addq $128, %rsp + pop %r13 + pop %r12 + pop %rbp + repz retq +#ifndef __APPLE__ +.size sp_2048_sqr_avx2_16,.-sp_2048_sqr_avx2_16 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_2048_add_16 +.type sp_2048_add_16,@function +.align 16 +sp_2048_add_16: +#else +.globl _sp_2048_add_16 +.p2align 4 +_sp_2048_add_16: +#endif /* __APPLE__ */ + xorq %rax, %rax + movq (%rsi), %rcx + addq (%rdx), %rcx + movq %rcx, (%rdi) + movq 8(%rsi), %rcx + adcq 8(%rdx), %rcx + movq %rcx, 8(%rdi) + movq 16(%rsi), %rcx + adcq 16(%rdx), %rcx + movq %rcx, 16(%rdi) + movq 24(%rsi), %rcx + adcq 24(%rdx), %rcx + movq %rcx, 24(%rdi) + movq 32(%rsi), %rcx + adcq 32(%rdx), %rcx + movq %rcx, 32(%rdi) + movq 40(%rsi), %rcx + adcq 40(%rdx), %rcx + movq %rcx, 40(%rdi) + movq 48(%rsi), %rcx + adcq 48(%rdx), %rcx + movq %rcx, 48(%rdi) + movq 56(%rsi), %rcx + adcq 56(%rdx), %rcx + movq %rcx, 56(%rdi) + movq 64(%rsi), %rcx + adcq 64(%rdx), %rcx + movq %rcx, 64(%rdi) + movq 72(%rsi), %rcx + adcq 72(%rdx), %rcx + movq %rcx, 72(%rdi) + movq 80(%rsi), %rcx + adcq 80(%rdx), %rcx + movq %rcx, 80(%rdi) + movq 88(%rsi), %rcx + adcq 88(%rdx), %rcx + movq %rcx, 88(%rdi) + movq 96(%rsi), %rcx + adcq 96(%rdx), %rcx + movq %rcx, 96(%rdi) + movq 104(%rsi), %rcx + adcq 104(%rdx), %rcx + movq %rcx, 104(%rdi) + movq 112(%rsi), %rcx + adcq 112(%rdx), %rcx + movq %rcx, 112(%rdi) + movq 120(%rsi), %rcx + adcq 120(%rdx), %rcx + movq %rcx, 120(%rdi) + adcq $0, %rax + repz retq +#ifndef __APPLE__ +.size sp_2048_add_16,.-sp_2048_add_16 +#endif /* __APPLE__ */ +/* Sub b from a into a. (a -= b) + * + * a A single precision integer and result. + * b A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_2048_sub_in_place_32 +.type sp_2048_sub_in_place_32,@function +.align 16 +sp_2048_sub_in_place_32: +#else +.globl _sp_2048_sub_in_place_32 +.p2align 4 +_sp_2048_sub_in_place_32: +#endif /* __APPLE__ */ + xorq %rax, %rax + movq (%rdi), %rdx + movq 8(%rdi), %rcx + movq (%rsi), %r8 + movq 8(%rsi), %r9 + subq %r8, %rdx + movq 16(%rsi), %r8 + movq %rdx, (%rdi) + movq 16(%rdi), %rdx + sbbq %r9, %rcx + movq 24(%rsi), %r9 + movq %rcx, 8(%rdi) + movq 24(%rdi), %rcx + sbbq %r8, %rdx + movq 32(%rsi), %r8 + movq %rdx, 16(%rdi) + movq 32(%rdi), %rdx + sbbq %r9, %rcx + movq 40(%rsi), %r9 + movq %rcx, 24(%rdi) + movq 40(%rdi), %rcx + sbbq %r8, %rdx + movq 48(%rsi), %r8 + movq %rdx, 32(%rdi) + movq 48(%rdi), %rdx + sbbq %r9, %rcx + movq 56(%rsi), %r9 + movq %rcx, 40(%rdi) + movq 56(%rdi), %rcx + sbbq %r8, %rdx + movq 64(%rsi), %r8 + movq %rdx, 48(%rdi) + movq 64(%rdi), %rdx + sbbq %r9, %rcx + movq 72(%rsi), %r9 + movq %rcx, 56(%rdi) + movq 72(%rdi), %rcx + sbbq %r8, %rdx + movq 80(%rsi), %r8 + movq %rdx, 64(%rdi) + movq 80(%rdi), %rdx + sbbq %r9, %rcx + movq 88(%rsi), %r9 + movq %rcx, 72(%rdi) + movq 88(%rdi), %rcx + sbbq %r8, %rdx + movq 96(%rsi), %r8 + movq %rdx, 80(%rdi) + movq 96(%rdi), %rdx + sbbq %r9, %rcx + movq 104(%rsi), %r9 + movq %rcx, 88(%rdi) + movq 104(%rdi), %rcx + sbbq %r8, %rdx + movq 112(%rsi), %r8 + movq %rdx, 96(%rdi) + movq 112(%rdi), %rdx + sbbq %r9, %rcx + movq 120(%rsi), %r9 + movq %rcx, 104(%rdi) + movq 120(%rdi), %rcx + sbbq %r8, %rdx + movq 128(%rsi), %r8 + movq %rdx, 112(%rdi) + movq 128(%rdi), %rdx + sbbq %r9, %rcx + movq 136(%rsi), %r9 + movq %rcx, 120(%rdi) + movq 136(%rdi), %rcx + sbbq %r8, %rdx + movq 144(%rsi), %r8 + movq %rdx, 128(%rdi) + movq 144(%rdi), %rdx + sbbq %r9, %rcx + movq 152(%rsi), %r9 + movq %rcx, 136(%rdi) + movq 152(%rdi), %rcx + sbbq %r8, %rdx + movq 160(%rsi), %r8 + movq %rdx, 144(%rdi) + movq 160(%rdi), %rdx + sbbq %r9, %rcx + movq 168(%rsi), %r9 + movq %rcx, 152(%rdi) + movq 168(%rdi), %rcx + sbbq %r8, %rdx + movq 176(%rsi), %r8 + movq %rdx, 160(%rdi) + movq 176(%rdi), %rdx + sbbq %r9, %rcx + movq 184(%rsi), %r9 + movq %rcx, 168(%rdi) + movq 184(%rdi), %rcx + sbbq %r8, %rdx + movq 192(%rsi), %r8 + movq %rdx, 176(%rdi) + movq 192(%rdi), %rdx + sbbq %r9, %rcx + movq 200(%rsi), %r9 + movq %rcx, 184(%rdi) + movq 200(%rdi), %rcx + sbbq %r8, %rdx + movq 208(%rsi), %r8 + movq %rdx, 192(%rdi) + movq 208(%rdi), %rdx + sbbq %r9, %rcx + movq 216(%rsi), %r9 + movq %rcx, 200(%rdi) + movq 216(%rdi), %rcx + sbbq %r8, %rdx + movq 224(%rsi), %r8 + movq %rdx, 208(%rdi) + movq 224(%rdi), %rdx + sbbq %r9, %rcx + movq 232(%rsi), %r9 + movq %rcx, 216(%rdi) + movq 232(%rdi), %rcx + sbbq %r8, %rdx + movq 240(%rsi), %r8 + movq %rdx, 224(%rdi) + movq 240(%rdi), %rdx + sbbq %r9, %rcx + movq 248(%rsi), %r9 + movq %rcx, 232(%rdi) + movq 248(%rdi), %rcx + sbbq %r8, %rdx + movq %rdx, 240(%rdi) + sbbq %r9, %rcx + movq %rcx, 248(%rdi) + sbbq $0, %rax + repz retq +#ifndef __APPLE__ +.size sp_2048_sub_in_place_32,.-sp_2048_sub_in_place_32 +#endif /* __APPLE__ */ +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_2048_add_32 +.type sp_2048_add_32,@function +.align 16 +sp_2048_add_32: +#else +.globl _sp_2048_add_32 +.p2align 4 +_sp_2048_add_32: +#endif /* __APPLE__ */ + xorq %rax, %rax + movq (%rsi), %rcx + addq (%rdx), %rcx + movq %rcx, (%rdi) + movq 8(%rsi), %rcx + adcq 8(%rdx), %rcx + movq %rcx, 8(%rdi) + movq 16(%rsi), %rcx + adcq 16(%rdx), %rcx + movq %rcx, 16(%rdi) + movq 24(%rsi), %rcx + adcq 24(%rdx), %rcx + movq %rcx, 24(%rdi) + movq 32(%rsi), %rcx + adcq 32(%rdx), %rcx + movq %rcx, 32(%rdi) + movq 40(%rsi), %rcx + adcq 40(%rdx), %rcx + movq %rcx, 40(%rdi) + movq 48(%rsi), %rcx + adcq 48(%rdx), %rcx + movq %rcx, 48(%rdi) + movq 56(%rsi), %rcx + adcq 56(%rdx), %rcx + movq %rcx, 56(%rdi) + movq 64(%rsi), %rcx + adcq 64(%rdx), %rcx + movq %rcx, 64(%rdi) + movq 72(%rsi), %rcx + adcq 72(%rdx), %rcx + movq %rcx, 72(%rdi) + movq 80(%rsi), %rcx + adcq 80(%rdx), %rcx + movq %rcx, 80(%rdi) + movq 88(%rsi), %rcx + adcq 88(%rdx), %rcx + movq %rcx, 88(%rdi) + movq 96(%rsi), %rcx + adcq 96(%rdx), %rcx + movq %rcx, 96(%rdi) + movq 104(%rsi), %rcx + adcq 104(%rdx), %rcx + movq %rcx, 104(%rdi) + movq 112(%rsi), %rcx + adcq 112(%rdx), %rcx + movq %rcx, 112(%rdi) + movq 120(%rsi), %rcx + adcq 120(%rdx), %rcx + movq %rcx, 120(%rdi) + movq 128(%rsi), %rcx + adcq 128(%rdx), %rcx + movq %rcx, 128(%rdi) + movq 136(%rsi), %rcx + adcq 136(%rdx), %rcx + movq %rcx, 136(%rdi) + movq 144(%rsi), %rcx + adcq 144(%rdx), %rcx + movq %rcx, 144(%rdi) + movq 152(%rsi), %rcx + adcq 152(%rdx), %rcx + movq %rcx, 152(%rdi) + movq 160(%rsi), %rcx + adcq 160(%rdx), %rcx + movq %rcx, 160(%rdi) + movq 168(%rsi), %rcx + adcq 168(%rdx), %rcx + movq %rcx, 168(%rdi) + movq 176(%rsi), %rcx + adcq 176(%rdx), %rcx + movq %rcx, 176(%rdi) + movq 184(%rsi), %rcx + adcq 184(%rdx), %rcx + movq %rcx, 184(%rdi) + movq 192(%rsi), %rcx + adcq 192(%rdx), %rcx + movq %rcx, 192(%rdi) + movq 200(%rsi), %rcx + adcq 200(%rdx), %rcx + movq %rcx, 200(%rdi) + movq 208(%rsi), %rcx + adcq 208(%rdx), %rcx + movq %rcx, 208(%rdi) + movq 216(%rsi), %rcx + adcq 216(%rdx), %rcx + movq %rcx, 216(%rdi) + movq 224(%rsi), %rcx + adcq 224(%rdx), %rcx + movq %rcx, 224(%rdi) + movq 232(%rsi), %rcx + adcq 232(%rdx), %rcx + movq %rcx, 232(%rdi) + movq 240(%rsi), %rcx + adcq 240(%rdx), %rcx + movq %rcx, 240(%rdi) + movq 248(%rsi), %rcx + adcq 248(%rdx), %rcx + movq %rcx, 248(%rdi) + adcq $0, %rax + repz retq +#ifndef __APPLE__ +.size sp_2048_add_32,.-sp_2048_add_32 +#endif /* __APPLE__ */ +/* Mul a by digit b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision digit. + */ +#ifndef __APPLE__ +.globl sp_2048_mul_d_32 +.type sp_2048_mul_d_32,@function +.align 16 +sp_2048_mul_d_32: +#else +.globl _sp_2048_mul_d_32 +.p2align 4 +_sp_2048_mul_d_32: +#endif /* __APPLE__ */ + movq %rdx, %rcx + # A[0] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + movq %r8, (%rdi) + # A[1] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 8(%rsi) + addq %rax, %r9 + movq %r9, 8(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[2] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 16(%rsi) + addq %rax, %r10 + movq %r10, 16(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[3] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 24(%rsi) + addq %rax, %r8 + movq %r8, 24(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[4] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 32(%rsi) + addq %rax, %r9 + movq %r9, 32(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[5] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 40(%rsi) + addq %rax, %r10 + movq %r10, 40(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[6] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 48(%rsi) + addq %rax, %r8 + movq %r8, 48(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[7] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 56(%rsi) + addq %rax, %r9 + movq %r9, 56(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[8] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 64(%rsi) + addq %rax, %r10 + movq %r10, 64(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[9] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 72(%rsi) + addq %rax, %r8 + movq %r8, 72(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[10] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 80(%rsi) + addq %rax, %r9 + movq %r9, 80(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[11] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 88(%rsi) + addq %rax, %r10 + movq %r10, 88(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[12] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 96(%rsi) + addq %rax, %r8 + movq %r8, 96(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[13] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 104(%rsi) + addq %rax, %r9 + movq %r9, 104(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[14] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 112(%rsi) + addq %rax, %r10 + movq %r10, 112(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[15] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 120(%rsi) + addq %rax, %r8 + movq %r8, 120(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[16] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 128(%rsi) + addq %rax, %r9 + movq %r9, 128(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[17] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 136(%rsi) + addq %rax, %r10 + movq %r10, 136(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[18] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 144(%rsi) + addq %rax, %r8 + movq %r8, 144(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[19] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 152(%rsi) + addq %rax, %r9 + movq %r9, 152(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[20] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 160(%rsi) + addq %rax, %r10 + movq %r10, 160(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[21] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 168(%rsi) + addq %rax, %r8 + movq %r8, 168(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[22] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 176(%rsi) + addq %rax, %r9 + movq %r9, 176(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[23] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 184(%rsi) + addq %rax, %r10 + movq %r10, 184(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[24] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 192(%rsi) + addq %rax, %r8 + movq %r8, 192(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[25] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 200(%rsi) + addq %rax, %r9 + movq %r9, 200(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[26] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 208(%rsi) + addq %rax, %r10 + movq %r10, 208(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[27] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 216(%rsi) + addq %rax, %r8 + movq %r8, 216(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[28] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 224(%rsi) + addq %rax, %r9 + movq %r9, 224(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[29] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 232(%rsi) + addq %rax, %r10 + movq %r10, 232(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[30] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 240(%rsi) + addq %rax, %r8 + movq %r8, 240(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # # A[31] * B + movq %rcx, %rax + mulq 248(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + movq %r9, 248(%rdi) + movq %r10, 256(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_2048_mul_d_32,.-sp_2048_mul_d_32 +#endif /* __APPLE__ */ +/* Sub b from a into a. (a -= b) + * + * a A single precision integer and result. + * b A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_2048_sub_in_place_16 +.type sp_2048_sub_in_place_16,@function +.align 16 +sp_2048_sub_in_place_16: +#else +.globl _sp_2048_sub_in_place_16 +.p2align 4 +_sp_2048_sub_in_place_16: +#endif /* __APPLE__ */ + xorq %rax, %rax + movq (%rdi), %rdx + movq 8(%rdi), %rcx + movq (%rsi), %r8 + movq 8(%rsi), %r9 + subq %r8, %rdx + movq 16(%rsi), %r8 + movq %rdx, (%rdi) + movq 16(%rdi), %rdx + sbbq %r9, %rcx + movq 24(%rsi), %r9 + movq %rcx, 8(%rdi) + movq 24(%rdi), %rcx + sbbq %r8, %rdx + movq 32(%rsi), %r8 + movq %rdx, 16(%rdi) + movq 32(%rdi), %rdx + sbbq %r9, %rcx + movq 40(%rsi), %r9 + movq %rcx, 24(%rdi) + movq 40(%rdi), %rcx + sbbq %r8, %rdx + movq 48(%rsi), %r8 + movq %rdx, 32(%rdi) + movq 48(%rdi), %rdx + sbbq %r9, %rcx + movq 56(%rsi), %r9 + movq %rcx, 40(%rdi) + movq 56(%rdi), %rcx + sbbq %r8, %rdx + movq 64(%rsi), %r8 + movq %rdx, 48(%rdi) + movq 64(%rdi), %rdx + sbbq %r9, %rcx + movq 72(%rsi), %r9 + movq %rcx, 56(%rdi) + movq 72(%rdi), %rcx + sbbq %r8, %rdx + movq 80(%rsi), %r8 + movq %rdx, 64(%rdi) + movq 80(%rdi), %rdx + sbbq %r9, %rcx + movq 88(%rsi), %r9 + movq %rcx, 72(%rdi) + movq 88(%rdi), %rcx + sbbq %r8, %rdx + movq 96(%rsi), %r8 + movq %rdx, 80(%rdi) + movq 96(%rdi), %rdx + sbbq %r9, %rcx + movq 104(%rsi), %r9 + movq %rcx, 88(%rdi) + movq 104(%rdi), %rcx + sbbq %r8, %rdx + movq 112(%rsi), %r8 + movq %rdx, 96(%rdi) + movq 112(%rdi), %rdx + sbbq %r9, %rcx + movq 120(%rsi), %r9 + movq %rcx, 104(%rdi) + movq 120(%rdi), %rcx + sbbq %r8, %rdx + movq %rdx, 112(%rdi) + sbbq %r9, %rcx + movq %rcx, 120(%rdi) + sbbq $0, %rax + repz retq +#ifndef __APPLE__ +.size sp_2048_sub_in_place_16,.-sp_2048_sub_in_place_16 +#endif /* __APPLE__ */ +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not copying. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +#ifndef __APPLE__ +.globl sp_2048_cond_sub_16 +.type sp_2048_cond_sub_16,@function +.align 16 +sp_2048_cond_sub_16: +#else +.globl _sp_2048_cond_sub_16 +.p2align 4 +_sp_2048_cond_sub_16: +#endif /* __APPLE__ */ + subq $128, %rsp + movq $0, %rax + movq (%rdx), %r8 + movq 8(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, (%rsp) + movq %r9, 8(%rsp) + movq 16(%rdx), %r8 + movq 24(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 16(%rsp) + movq %r9, 24(%rsp) + movq 32(%rdx), %r8 + movq 40(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 32(%rsp) + movq %r9, 40(%rsp) + movq 48(%rdx), %r8 + movq 56(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 48(%rsp) + movq %r9, 56(%rsp) + movq 64(%rdx), %r8 + movq 72(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 64(%rsp) + movq %r9, 72(%rsp) + movq 80(%rdx), %r8 + movq 88(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 80(%rsp) + movq %r9, 88(%rsp) + movq 96(%rdx), %r8 + movq 104(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 96(%rsp) + movq %r9, 104(%rsp) + movq 112(%rdx), %r8 + movq 120(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 112(%rsp) + movq %r9, 120(%rsp) + movq (%rsi), %r8 + movq (%rsp), %rdx + subq %rdx, %r8 + movq 8(%rsi), %r9 + movq 8(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, (%rdi) + movq 16(%rsi), %r8 + movq 16(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 8(%rdi) + movq 24(%rsi), %r9 + movq 24(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 16(%rdi) + movq 32(%rsi), %r8 + movq 32(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 24(%rdi) + movq 40(%rsi), %r9 + movq 40(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 32(%rdi) + movq 48(%rsi), %r8 + movq 48(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 40(%rdi) + movq 56(%rsi), %r9 + movq 56(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 48(%rdi) + movq 64(%rsi), %r8 + movq 64(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 56(%rdi) + movq 72(%rsi), %r9 + movq 72(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 64(%rdi) + movq 80(%rsi), %r8 + movq 80(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 72(%rdi) + movq 88(%rsi), %r9 + movq 88(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 80(%rdi) + movq 96(%rsi), %r8 + movq 96(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 88(%rdi) + movq 104(%rsi), %r9 + movq 104(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 96(%rdi) + movq 112(%rsi), %r8 + movq 112(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 104(%rdi) + movq 120(%rsi), %r9 + movq 120(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 112(%rdi) + movq %r9, 120(%rdi) + sbbq $0, %rax + addq $128, %rsp + repz retq +#ifndef __APPLE__ +.size sp_2048_cond_sub_16,.-sp_2048_cond_sub_16 +#endif /* __APPLE__ */ +/* Reduce the number back to 2048 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +#ifndef __APPLE__ +.globl sp_2048_mont_reduce_16 +.type sp_2048_mont_reduce_16,@function +.align 16 +sp_2048_mont_reduce_16: +#else +.globl _sp_2048_mont_reduce_16 +.p2align 4 +_sp_2048_mont_reduce_16: +#endif /* __APPLE__ */ + push %r12 + push %r13 + push %r14 + push %r15 + movq %rdx, %rcx + xorq %r15, %r15 + # i = 0 + movq $16, %r8 + movq (%rdi), %r13 + movq 8(%rdi), %r14 +L_mont_loop_16: + # mu = a[i] * mp + movq %r13, %r11 + imulq %rcx, %r11 + # a[i+0] += m[0] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq (%rsi) + addq %rax, %r13 + adcq %rdx, %r10 + # a[i+1] += m[1] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 8(%rsi) + movq %r14, %r13 + addq %rax, %r13 + adcq %rdx, %r9 + addq %r10, %r13 + adcq $0, %r9 + # a[i+2] += m[2] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 16(%rsi) + movq 16(%rdi), %r14 + addq %rax, %r14 + adcq %rdx, %r10 + addq %r9, %r14 + adcq $0, %r10 + # a[i+3] += m[3] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 24(%rsi) + movq 24(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 24(%rdi) + adcq $0, %r9 + # a[i+4] += m[4] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 32(%rsi) + movq 32(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 32(%rdi) + adcq $0, %r10 + # a[i+5] += m[5] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 40(%rsi) + movq 40(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 40(%rdi) + adcq $0, %r9 + # a[i+6] += m[6] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 48(%rsi) + movq 48(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 48(%rdi) + adcq $0, %r10 + # a[i+7] += m[7] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 56(%rsi) + movq 56(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 56(%rdi) + adcq $0, %r9 + # a[i+8] += m[8] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 64(%rsi) + movq 64(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 64(%rdi) + adcq $0, %r10 + # a[i+9] += m[9] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 72(%rsi) + movq 72(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 72(%rdi) + adcq $0, %r9 + # a[i+10] += m[10] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 80(%rsi) + movq 80(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 80(%rdi) + adcq $0, %r10 + # a[i+11] += m[11] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 88(%rsi) + movq 88(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 88(%rdi) + adcq $0, %r9 + # a[i+12] += m[12] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 96(%rsi) + movq 96(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 96(%rdi) + adcq $0, %r10 + # a[i+13] += m[13] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 104(%rsi) + movq 104(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 104(%rdi) + adcq $0, %r9 + # a[i+14] += m[14] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 112(%rsi) + movq 112(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 112(%rdi) + adcq $0, %r10 + # a[i+15] += m[15] * mu + movq %r11, %rax + mulq 120(%rsi) + movq 120(%rdi), %r12 + addq %rax, %r10 + adcq %r15, %rdx + movq $0, %r15 + adcq $0, %r15 + addq %r10, %r12 + movq %r12, 120(%rdi) + adcq %rdx, 128(%rdi) + adcq $0, %r15 + # i += 1 + addq $8, %rdi + decq %r8 + jnz L_mont_loop_16 + movq %r13, (%rdi) + movq %r14, 8(%rdi) + negq %r15 + movq %r15, %rcx + movq %rsi, %rdx + movq %rdi, %rsi + movq %rdi, %rdi + subq $128, %rdi +#ifndef __APPLE__ + callq sp_2048_cond_sub_16@plt +#else + callq _sp_2048_cond_sub_16 +#endif /* __APPLE__ */ + pop %r15 + pop %r14 + pop %r13 + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_2048_mont_reduce_16,.-sp_2048_mont_reduce_16 +#endif /* __APPLE__ */ +/* Mul a by digit b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision digit. + */ +#ifndef __APPLE__ +.globl sp_2048_mul_d_16 +.type sp_2048_mul_d_16,@function +.align 16 +sp_2048_mul_d_16: +#else +.globl _sp_2048_mul_d_16 +.p2align 4 +_sp_2048_mul_d_16: +#endif /* __APPLE__ */ + movq %rdx, %rcx + # A[0] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + movq %r8, (%rdi) + # A[1] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 8(%rsi) + addq %rax, %r9 + movq %r9, 8(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[2] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 16(%rsi) + addq %rax, %r10 + movq %r10, 16(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[3] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 24(%rsi) + addq %rax, %r8 + movq %r8, 24(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[4] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 32(%rsi) + addq %rax, %r9 + movq %r9, 32(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[5] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 40(%rsi) + addq %rax, %r10 + movq %r10, 40(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[6] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 48(%rsi) + addq %rax, %r8 + movq %r8, 48(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[7] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 56(%rsi) + addq %rax, %r9 + movq %r9, 56(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[8] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 64(%rsi) + addq %rax, %r10 + movq %r10, 64(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[9] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 72(%rsi) + addq %rax, %r8 + movq %r8, 72(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[10] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 80(%rsi) + addq %rax, %r9 + movq %r9, 80(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[11] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 88(%rsi) + addq %rax, %r10 + movq %r10, 88(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[12] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 96(%rsi) + addq %rax, %r8 + movq %r8, 96(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[13] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 104(%rsi) + addq %rax, %r9 + movq %r9, 104(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[14] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 112(%rsi) + addq %rax, %r10 + movq %r10, 112(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # # A[15] * B + movq %rcx, %rax + mulq 120(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + movq %r8, 120(%rdi) + movq %r9, 128(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_2048_mul_d_16,.-sp_2048_mul_d_16 +#endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 +/* Mul a by digit b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision digit. + */ +#ifndef __APPLE__ +.globl sp_2048_mul_d_avx2_16 +.type sp_2048_mul_d_avx2_16,@function +.align 16 +sp_2048_mul_d_avx2_16: +#else +.globl _sp_2048_mul_d_avx2_16 +.p2align 4 +_sp_2048_mul_d_avx2_16: +#endif /* __APPLE__ */ + movq %rdx, %rax + # A[0] * B + movq %rax, %rdx + xorq %r11, %r11 + mulxq (%rsi), %r9, %r10 + movq %r9, (%rdi) + # A[1] * B + mulxq 8(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 8(%rdi) + adoxq %r8, %r9 + # A[2] * B + mulxq 16(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 16(%rdi) + adoxq %r8, %r10 + # A[3] * B + mulxq 24(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 24(%rdi) + adoxq %r8, %r9 + # A[4] * B + mulxq 32(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 32(%rdi) + adoxq %r8, %r10 + # A[5] * B + mulxq 40(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 40(%rdi) + adoxq %r8, %r9 + # A[6] * B + mulxq 48(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 48(%rdi) + adoxq %r8, %r10 + # A[7] * B + mulxq 56(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 56(%rdi) + adoxq %r8, %r9 + # A[8] * B + mulxq 64(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 64(%rdi) + adoxq %r8, %r10 + # A[9] * B + mulxq 72(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 72(%rdi) + adoxq %r8, %r9 + # A[10] * B + mulxq 80(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 80(%rdi) + adoxq %r8, %r10 + # A[11] * B + mulxq 88(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 88(%rdi) + adoxq %r8, %r9 + # A[12] * B + mulxq 96(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 96(%rdi) + adoxq %r8, %r10 + # A[13] * B + mulxq 104(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 104(%rdi) + adoxq %r8, %r9 + # A[14] * B + mulxq 112(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 112(%rdi) + adoxq %r8, %r10 + # A[15] * B + mulxq 120(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + adoxq %r8, %r9 + adcxq %r11, %r9 + movq %r10, 120(%rdi) + movq %r9, 128(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_2048_mul_d_avx2_16,.-sp_2048_mul_d_avx2_16 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +#ifndef __APPLE__ +.globl sp_2048_cmp_16 +.type sp_2048_cmp_16,@function +.align 16 +sp_2048_cmp_16: +#else +.globl _sp_2048_cmp_16 +.p2align 4 +_sp_2048_cmp_16: +#endif /* __APPLE__ */ + xorq %rcx, %rcx + movq $-1, %rdx + movq $-1, %rax + movq $1, %r8 + movq 120(%rdi), %r9 + movq 120(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 112(%rdi), %r9 + movq 112(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 104(%rdi), %r9 + movq 104(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 96(%rdi), %r9 + movq 96(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 88(%rdi), %r9 + movq 88(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 80(%rdi), %r9 + movq 80(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 72(%rdi), %r9 + movq 72(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 64(%rdi), %r9 + movq 64(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 56(%rdi), %r9 + movq 56(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 48(%rdi), %r9 + movq 48(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 40(%rdi), %r9 + movq 40(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 32(%rdi), %r9 + movq 32(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 24(%rdi), %r9 + movq 24(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 16(%rdi), %r9 + movq 16(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 8(%rdi), %r9 + movq 8(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq (%rdi), %r9 + movq (%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + xorq %rdx, %rax + repz retq +#ifndef __APPLE__ +.size sp_2048_cmp_16,.-sp_2048_cmp_16 +#endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 +/* Reduce the number back to 2048 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +#ifndef __APPLE__ +.globl sp_2048_mont_reduce_avx2_16 +.type sp_2048_mont_reduce_avx2_16,@function +.align 16 +sp_2048_mont_reduce_avx2_16: +#else +.globl _sp_2048_mont_reduce_avx2_16 +.p2align 4 +_sp_2048_mont_reduce_avx2_16: +#endif /* __APPLE__ */ + push %r12 + push %r13 + push %r14 + movq %rdx, %rax + xorq %r14, %r14 + # i = 0 + movq $16, %r9 + movq (%rdi), %r13 + xorq %r12, %r12 +L_mont_loop_avx2_16: + # mu = a[i] * mp + movq %r13, %rdx + mulxq %rax, %rdx, %r8 + movq %r13, %r10 + # a[i+0] += m[0] * mu + mulxq (%rsi), %rcx, %r8 + movq 8(%rdi), %r13 + adcxq %rcx, %r10 + adoxq %r8, %r13 + # a[i+1] += m[1] * mu + mulxq 8(%rsi), %rcx, %r8 + movq 16(%rdi), %r10 + adcxq %rcx, %r13 + adoxq %r8, %r10 + # a[i+2] += m[2] * mu + mulxq 16(%rsi), %rcx, %r8 + movq 24(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 16(%rdi) + # a[i+3] += m[3] * mu + mulxq 24(%rsi), %rcx, %r8 + movq 32(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 24(%rdi) + # a[i+4] += m[4] * mu + mulxq 32(%rsi), %rcx, %r8 + movq 40(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 32(%rdi) + # a[i+5] += m[5] * mu + mulxq 40(%rsi), %rcx, %r8 + movq 48(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 40(%rdi) + # a[i+6] += m[6] * mu + mulxq 48(%rsi), %rcx, %r8 + movq 56(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 48(%rdi) + # a[i+7] += m[7] * mu + mulxq 56(%rsi), %rcx, %r8 + movq 64(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 56(%rdi) + # a[i+8] += m[8] * mu + mulxq 64(%rsi), %rcx, %r8 + movq 72(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 64(%rdi) + # a[i+9] += m[9] * mu + mulxq 72(%rsi), %rcx, %r8 + movq 80(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 72(%rdi) + # a[i+10] += m[10] * mu + mulxq 80(%rsi), %rcx, %r8 + movq 88(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 80(%rdi) + # a[i+11] += m[11] * mu + mulxq 88(%rsi), %rcx, %r8 + movq 96(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 88(%rdi) + # a[i+12] += m[12] * mu + mulxq 96(%rsi), %rcx, %r8 + movq 104(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 96(%rdi) + # a[i+13] += m[13] * mu + mulxq 104(%rsi), %rcx, %r8 + movq 112(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 104(%rdi) + # a[i+14] += m[14] * mu + mulxq 112(%rsi), %rcx, %r8 + movq 120(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 112(%rdi) + # a[i+15] += m[15] * mu + mulxq 120(%rsi), %rcx, %r8 + movq 128(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 120(%rdi) + adcxq %r14, %r10 + movq %r12, %r14 + adoxq %r12, %r14 + adcxq %r12, %r14 + movq %r10, 128(%rdi) + # i += 1 + addq $8, %rdi + decq %r9 + jnz L_mont_loop_avx2_16 + movq %r13, (%rdi) + negq %r14 + movq %r14, %rcx + movq %rsi, %rdx + movq %rdi, %rsi + movq %rdi, %rdi + subq $128, %rdi +#ifndef __APPLE__ + callq sp_2048_cond_sub_16@plt +#else + callq _sp_2048_cond_sub_16 +#endif /* __APPLE__ */ + pop %r14 + pop %r13 + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_2048_mont_reduce_avx2_16,.-sp_2048_mont_reduce_avx2_16 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not copying. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +#ifndef __APPLE__ +.globl sp_2048_cond_sub_32 +.type sp_2048_cond_sub_32,@function +.align 16 +sp_2048_cond_sub_32: +#else +.globl _sp_2048_cond_sub_32 +.p2align 4 +_sp_2048_cond_sub_32: +#endif /* __APPLE__ */ + subq $256, %rsp + movq $0, %rax + movq (%rdx), %r8 + movq 8(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, (%rsp) + movq %r9, 8(%rsp) + movq 16(%rdx), %r8 + movq 24(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 16(%rsp) + movq %r9, 24(%rsp) + movq 32(%rdx), %r8 + movq 40(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 32(%rsp) + movq %r9, 40(%rsp) + movq 48(%rdx), %r8 + movq 56(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 48(%rsp) + movq %r9, 56(%rsp) + movq 64(%rdx), %r8 + movq 72(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 64(%rsp) + movq %r9, 72(%rsp) + movq 80(%rdx), %r8 + movq 88(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 80(%rsp) + movq %r9, 88(%rsp) + movq 96(%rdx), %r8 + movq 104(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 96(%rsp) + movq %r9, 104(%rsp) + movq 112(%rdx), %r8 + movq 120(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 112(%rsp) + movq %r9, 120(%rsp) + movq 128(%rdx), %r8 + movq 136(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 128(%rsp) + movq %r9, 136(%rsp) + movq 144(%rdx), %r8 + movq 152(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 144(%rsp) + movq %r9, 152(%rsp) + movq 160(%rdx), %r8 + movq 168(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 160(%rsp) + movq %r9, 168(%rsp) + movq 176(%rdx), %r8 + movq 184(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 176(%rsp) + movq %r9, 184(%rsp) + movq 192(%rdx), %r8 + movq 200(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 192(%rsp) + movq %r9, 200(%rsp) + movq 208(%rdx), %r8 + movq 216(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 208(%rsp) + movq %r9, 216(%rsp) + movq 224(%rdx), %r8 + movq 232(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 224(%rsp) + movq %r9, 232(%rsp) + movq 240(%rdx), %r8 + movq 248(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 240(%rsp) + movq %r9, 248(%rsp) + movq (%rsi), %r8 + movq (%rsp), %rdx + subq %rdx, %r8 + movq 8(%rsi), %r9 + movq 8(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, (%rdi) + movq 16(%rsi), %r8 + movq 16(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 8(%rdi) + movq 24(%rsi), %r9 + movq 24(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 16(%rdi) + movq 32(%rsi), %r8 + movq 32(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 24(%rdi) + movq 40(%rsi), %r9 + movq 40(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 32(%rdi) + movq 48(%rsi), %r8 + movq 48(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 40(%rdi) + movq 56(%rsi), %r9 + movq 56(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 48(%rdi) + movq 64(%rsi), %r8 + movq 64(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 56(%rdi) + movq 72(%rsi), %r9 + movq 72(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 64(%rdi) + movq 80(%rsi), %r8 + movq 80(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 72(%rdi) + movq 88(%rsi), %r9 + movq 88(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 80(%rdi) + movq 96(%rsi), %r8 + movq 96(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 88(%rdi) + movq 104(%rsi), %r9 + movq 104(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 96(%rdi) + movq 112(%rsi), %r8 + movq 112(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 104(%rdi) + movq 120(%rsi), %r9 + movq 120(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 112(%rdi) + movq 128(%rsi), %r8 + movq 128(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 120(%rdi) + movq 136(%rsi), %r9 + movq 136(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 128(%rdi) + movq 144(%rsi), %r8 + movq 144(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 136(%rdi) + movq 152(%rsi), %r9 + movq 152(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 144(%rdi) + movq 160(%rsi), %r8 + movq 160(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 152(%rdi) + movq 168(%rsi), %r9 + movq 168(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 160(%rdi) + movq 176(%rsi), %r8 + movq 176(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 168(%rdi) + movq 184(%rsi), %r9 + movq 184(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 176(%rdi) + movq 192(%rsi), %r8 + movq 192(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 184(%rdi) + movq 200(%rsi), %r9 + movq 200(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 192(%rdi) + movq 208(%rsi), %r8 + movq 208(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 200(%rdi) + movq 216(%rsi), %r9 + movq 216(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 208(%rdi) + movq 224(%rsi), %r8 + movq 224(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 216(%rdi) + movq 232(%rsi), %r9 + movq 232(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 224(%rdi) + movq 240(%rsi), %r8 + movq 240(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 232(%rdi) + movq 248(%rsi), %r9 + movq 248(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 240(%rdi) + movq %r9, 248(%rdi) + sbbq $0, %rax + addq $256, %rsp + repz retq +#ifndef __APPLE__ +.size sp_2048_cond_sub_32,.-sp_2048_cond_sub_32 +#endif /* __APPLE__ */ +/* Reduce the number back to 2048 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +#ifndef __APPLE__ +.globl sp_2048_mont_reduce_32 +.type sp_2048_mont_reduce_32,@function +.align 16 +sp_2048_mont_reduce_32: +#else +.globl _sp_2048_mont_reduce_32 +.p2align 4 +_sp_2048_mont_reduce_32: +#endif /* __APPLE__ */ + push %r12 + push %r13 + push %r14 + push %r15 + movq %rdx, %rcx + xorq %r15, %r15 + # i = 0 + movq $32, %r8 + movq (%rdi), %r13 + movq 8(%rdi), %r14 +L_mont_loop_32: + # mu = a[i] * mp + movq %r13, %r11 + imulq %rcx, %r11 + # a[i+0] += m[0] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq (%rsi) + addq %rax, %r13 + adcq %rdx, %r10 + # a[i+1] += m[1] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 8(%rsi) + movq %r14, %r13 + addq %rax, %r13 + adcq %rdx, %r9 + addq %r10, %r13 + adcq $0, %r9 + # a[i+2] += m[2] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 16(%rsi) + movq 16(%rdi), %r14 + addq %rax, %r14 + adcq %rdx, %r10 + addq %r9, %r14 + adcq $0, %r10 + # a[i+3] += m[3] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 24(%rsi) + movq 24(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 24(%rdi) + adcq $0, %r9 + # a[i+4] += m[4] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 32(%rsi) + movq 32(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 32(%rdi) + adcq $0, %r10 + # a[i+5] += m[5] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 40(%rsi) + movq 40(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 40(%rdi) + adcq $0, %r9 + # a[i+6] += m[6] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 48(%rsi) + movq 48(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 48(%rdi) + adcq $0, %r10 + # a[i+7] += m[7] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 56(%rsi) + movq 56(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 56(%rdi) + adcq $0, %r9 + # a[i+8] += m[8] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 64(%rsi) + movq 64(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 64(%rdi) + adcq $0, %r10 + # a[i+9] += m[9] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 72(%rsi) + movq 72(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 72(%rdi) + adcq $0, %r9 + # a[i+10] += m[10] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 80(%rsi) + movq 80(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 80(%rdi) + adcq $0, %r10 + # a[i+11] += m[11] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 88(%rsi) + movq 88(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 88(%rdi) + adcq $0, %r9 + # a[i+12] += m[12] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 96(%rsi) + movq 96(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 96(%rdi) + adcq $0, %r10 + # a[i+13] += m[13] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 104(%rsi) + movq 104(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 104(%rdi) + adcq $0, %r9 + # a[i+14] += m[14] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 112(%rsi) + movq 112(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 112(%rdi) + adcq $0, %r10 + # a[i+15] += m[15] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 120(%rsi) + movq 120(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 120(%rdi) + adcq $0, %r9 + # a[i+16] += m[16] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 128(%rsi) + movq 128(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 128(%rdi) + adcq $0, %r10 + # a[i+17] += m[17] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 136(%rsi) + movq 136(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 136(%rdi) + adcq $0, %r9 + # a[i+18] += m[18] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 144(%rsi) + movq 144(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 144(%rdi) + adcq $0, %r10 + # a[i+19] += m[19] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 152(%rsi) + movq 152(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 152(%rdi) + adcq $0, %r9 + # a[i+20] += m[20] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 160(%rsi) + movq 160(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 160(%rdi) + adcq $0, %r10 + # a[i+21] += m[21] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 168(%rsi) + movq 168(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 168(%rdi) + adcq $0, %r9 + # a[i+22] += m[22] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 176(%rsi) + movq 176(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 176(%rdi) + adcq $0, %r10 + # a[i+23] += m[23] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 184(%rsi) + movq 184(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 184(%rdi) + adcq $0, %r9 + # a[i+24] += m[24] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 192(%rsi) + movq 192(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 192(%rdi) + adcq $0, %r10 + # a[i+25] += m[25] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 200(%rsi) + movq 200(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 200(%rdi) + adcq $0, %r9 + # a[i+26] += m[26] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 208(%rsi) + movq 208(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 208(%rdi) + adcq $0, %r10 + # a[i+27] += m[27] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 216(%rsi) + movq 216(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 216(%rdi) + adcq $0, %r9 + # a[i+28] += m[28] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 224(%rsi) + movq 224(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 224(%rdi) + adcq $0, %r10 + # a[i+29] += m[29] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 232(%rsi) + movq 232(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 232(%rdi) + adcq $0, %r9 + # a[i+30] += m[30] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 240(%rsi) + movq 240(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 240(%rdi) + adcq $0, %r10 + # a[i+31] += m[31] * mu + movq %r11, %rax + mulq 248(%rsi) + movq 248(%rdi), %r12 + addq %rax, %r10 + adcq %r15, %rdx + movq $0, %r15 + adcq $0, %r15 + addq %r10, %r12 + movq %r12, 248(%rdi) + adcq %rdx, 256(%rdi) + adcq $0, %r15 + # i += 1 + addq $8, %rdi + decq %r8 + jnz L_mont_loop_32 + movq %r13, (%rdi) + movq %r14, 8(%rdi) + negq %r15 + movq %r15, %rcx + movq %rsi, %rdx + movq %rdi, %rsi + movq %rdi, %rdi + subq $256, %rdi +#ifndef __APPLE__ + callq sp_2048_cond_sub_32@plt +#else + callq _sp_2048_cond_sub_32 +#endif /* __APPLE__ */ + pop %r15 + pop %r14 + pop %r13 + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_2048_mont_reduce_32,.-sp_2048_mont_reduce_32 +#endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 +/* Mul a by digit b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision digit. + */ +#ifndef __APPLE__ +.globl sp_2048_mul_d_avx2_32 +.type sp_2048_mul_d_avx2_32,@function +.align 16 +sp_2048_mul_d_avx2_32: +#else +.globl _sp_2048_mul_d_avx2_32 +.p2align 4 +_sp_2048_mul_d_avx2_32: +#endif /* __APPLE__ */ + movq %rdx, %rax + # A[0] * B + movq %rax, %rdx + xorq %r11, %r11 + mulxq (%rsi), %r9, %r10 + movq %r9, (%rdi) + # A[1] * B + mulxq 8(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 8(%rdi) + adoxq %r8, %r9 + # A[2] * B + mulxq 16(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 16(%rdi) + adoxq %r8, %r10 + # A[3] * B + mulxq 24(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 24(%rdi) + adoxq %r8, %r9 + # A[4] * B + mulxq 32(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 32(%rdi) + adoxq %r8, %r10 + # A[5] * B + mulxq 40(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 40(%rdi) + adoxq %r8, %r9 + # A[6] * B + mulxq 48(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 48(%rdi) + adoxq %r8, %r10 + # A[7] * B + mulxq 56(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 56(%rdi) + adoxq %r8, %r9 + # A[8] * B + mulxq 64(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 64(%rdi) + adoxq %r8, %r10 + # A[9] * B + mulxq 72(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 72(%rdi) + adoxq %r8, %r9 + # A[10] * B + mulxq 80(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 80(%rdi) + adoxq %r8, %r10 + # A[11] * B + mulxq 88(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 88(%rdi) + adoxq %r8, %r9 + # A[12] * B + mulxq 96(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 96(%rdi) + adoxq %r8, %r10 + # A[13] * B + mulxq 104(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 104(%rdi) + adoxq %r8, %r9 + # A[14] * B + mulxq 112(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 112(%rdi) + adoxq %r8, %r10 + # A[15] * B + mulxq 120(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 120(%rdi) + adoxq %r8, %r9 + # A[16] * B + mulxq 128(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 128(%rdi) + adoxq %r8, %r10 + # A[17] * B + mulxq 136(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 136(%rdi) + adoxq %r8, %r9 + # A[18] * B + mulxq 144(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 144(%rdi) + adoxq %r8, %r10 + # A[19] * B + mulxq 152(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 152(%rdi) + adoxq %r8, %r9 + # A[20] * B + mulxq 160(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 160(%rdi) + adoxq %r8, %r10 + # A[21] * B + mulxq 168(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 168(%rdi) + adoxq %r8, %r9 + # A[22] * B + mulxq 176(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 176(%rdi) + adoxq %r8, %r10 + # A[23] * B + mulxq 184(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 184(%rdi) + adoxq %r8, %r9 + # A[24] * B + mulxq 192(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 192(%rdi) + adoxq %r8, %r10 + # A[25] * B + mulxq 200(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 200(%rdi) + adoxq %r8, %r9 + # A[26] * B + mulxq 208(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 208(%rdi) + adoxq %r8, %r10 + # A[27] * B + mulxq 216(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 216(%rdi) + adoxq %r8, %r9 + # A[28] * B + mulxq 224(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 224(%rdi) + adoxq %r8, %r10 + # A[29] * B + mulxq 232(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 232(%rdi) + adoxq %r8, %r9 + # A[30] * B + mulxq 240(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 240(%rdi) + adoxq %r8, %r10 + # A[31] * B + mulxq 248(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + adoxq %r8, %r9 + adcxq %r11, %r9 + movq %r10, 248(%rdi) + movq %r9, 256(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_2048_mul_d_avx2_32,.-sp_2048_mul_d_avx2_32 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +#ifndef __APPLE__ +.globl sp_2048_cmp_32 +.type sp_2048_cmp_32,@function +.align 16 +sp_2048_cmp_32: +#else +.globl _sp_2048_cmp_32 +.p2align 4 +_sp_2048_cmp_32: +#endif /* __APPLE__ */ + xorq %rcx, %rcx + movq $-1, %rdx + movq $-1, %rax + movq $1, %r8 + movq 248(%rdi), %r9 + movq 248(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 240(%rdi), %r9 + movq 240(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 232(%rdi), %r9 + movq 232(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 224(%rdi), %r9 + movq 224(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 216(%rdi), %r9 + movq 216(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 208(%rdi), %r9 + movq 208(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 200(%rdi), %r9 + movq 200(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 192(%rdi), %r9 + movq 192(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 184(%rdi), %r9 + movq 184(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 176(%rdi), %r9 + movq 176(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 168(%rdi), %r9 + movq 168(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 160(%rdi), %r9 + movq 160(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 152(%rdi), %r9 + movq 152(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 144(%rdi), %r9 + movq 144(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 136(%rdi), %r9 + movq 136(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 128(%rdi), %r9 + movq 128(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 120(%rdi), %r9 + movq 120(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 112(%rdi), %r9 + movq 112(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 104(%rdi), %r9 + movq 104(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 96(%rdi), %r9 + movq 96(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 88(%rdi), %r9 + movq 88(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 80(%rdi), %r9 + movq 80(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 72(%rdi), %r9 + movq 72(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 64(%rdi), %r9 + movq 64(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 56(%rdi), %r9 + movq 56(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 48(%rdi), %r9 + movq 48(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 40(%rdi), %r9 + movq 40(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 32(%rdi), %r9 + movq 32(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 24(%rdi), %r9 + movq 24(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 16(%rdi), %r9 + movq 16(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 8(%rdi), %r9 + movq 8(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq (%rdi), %r9 + movq (%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + xorq %rdx, %rax + repz retq +#ifndef __APPLE__ +.size sp_2048_cmp_32,.-sp_2048_cmp_32 +#endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 +/* Reduce the number back to 2048 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +#ifndef __APPLE__ +.globl sp_2048_mont_reduce_avx2_32 +.type sp_2048_mont_reduce_avx2_32,@function +.align 16 +sp_2048_mont_reduce_avx2_32: +#else +.globl _sp_2048_mont_reduce_avx2_32 +.p2align 4 +_sp_2048_mont_reduce_avx2_32: +#endif /* __APPLE__ */ + push %r12 + push %r13 + push %r14 + movq %rdx, %rax + xorq %r14, %r14 + # i = 0 + movq $32, %r9 + movq (%rdi), %r13 + xorq %r12, %r12 +L_mont_loop_avx2_32: + # mu = a[i] * mp + movq %r13, %rdx + mulxq %rax, %rdx, %r8 + movq %r13, %r10 + # a[i+0] += m[0] * mu + mulxq (%rsi), %rcx, %r8 + movq 8(%rdi), %r13 + adcxq %rcx, %r10 + adoxq %r8, %r13 + # a[i+1] += m[1] * mu + mulxq 8(%rsi), %rcx, %r8 + movq 16(%rdi), %r10 + adcxq %rcx, %r13 + adoxq %r8, %r10 + # a[i+2] += m[2] * mu + mulxq 16(%rsi), %rcx, %r8 + movq 24(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 16(%rdi) + # a[i+3] += m[3] * mu + mulxq 24(%rsi), %rcx, %r8 + movq 32(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 24(%rdi) + # a[i+4] += m[4] * mu + mulxq 32(%rsi), %rcx, %r8 + movq 40(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 32(%rdi) + # a[i+5] += m[5] * mu + mulxq 40(%rsi), %rcx, %r8 + movq 48(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 40(%rdi) + # a[i+6] += m[6] * mu + mulxq 48(%rsi), %rcx, %r8 + movq 56(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 48(%rdi) + # a[i+7] += m[7] * mu + mulxq 56(%rsi), %rcx, %r8 + movq 64(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 56(%rdi) + # a[i+8] += m[8] * mu + mulxq 64(%rsi), %rcx, %r8 + movq 72(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 64(%rdi) + # a[i+9] += m[9] * mu + mulxq 72(%rsi), %rcx, %r8 + movq 80(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 72(%rdi) + # a[i+10] += m[10] * mu + mulxq 80(%rsi), %rcx, %r8 + movq 88(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 80(%rdi) + # a[i+11] += m[11] * mu + mulxq 88(%rsi), %rcx, %r8 + movq 96(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 88(%rdi) + # a[i+12] += m[12] * mu + mulxq 96(%rsi), %rcx, %r8 + movq 104(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 96(%rdi) + # a[i+13] += m[13] * mu + mulxq 104(%rsi), %rcx, %r8 + movq 112(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 104(%rdi) + # a[i+14] += m[14] * mu + mulxq 112(%rsi), %rcx, %r8 + movq 120(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 112(%rdi) + # a[i+15] += m[15] * mu + mulxq 120(%rsi), %rcx, %r8 + movq 128(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 120(%rdi) + # a[i+16] += m[16] * mu + mulxq 128(%rsi), %rcx, %r8 + movq 136(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 128(%rdi) + # a[i+17] += m[17] * mu + mulxq 136(%rsi), %rcx, %r8 + movq 144(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 136(%rdi) + # a[i+18] += m[18] * mu + mulxq 144(%rsi), %rcx, %r8 + movq 152(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 144(%rdi) + # a[i+19] += m[19] * mu + mulxq 152(%rsi), %rcx, %r8 + movq 160(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 152(%rdi) + # a[i+20] += m[20] * mu + mulxq 160(%rsi), %rcx, %r8 + movq 168(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 160(%rdi) + # a[i+21] += m[21] * mu + mulxq 168(%rsi), %rcx, %r8 + movq 176(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 168(%rdi) + # a[i+22] += m[22] * mu + mulxq 176(%rsi), %rcx, %r8 + movq 184(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 176(%rdi) + # a[i+23] += m[23] * mu + mulxq 184(%rsi), %rcx, %r8 + movq 192(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 184(%rdi) + # a[i+24] += m[24] * mu + mulxq 192(%rsi), %rcx, %r8 + movq 200(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 192(%rdi) + # a[i+25] += m[25] * mu + mulxq 200(%rsi), %rcx, %r8 + movq 208(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 200(%rdi) + # a[i+26] += m[26] * mu + mulxq 208(%rsi), %rcx, %r8 + movq 216(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 208(%rdi) + # a[i+27] += m[27] * mu + mulxq 216(%rsi), %rcx, %r8 + movq 224(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 216(%rdi) + # a[i+28] += m[28] * mu + mulxq 224(%rsi), %rcx, %r8 + movq 232(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 224(%rdi) + # a[i+29] += m[29] * mu + mulxq 232(%rsi), %rcx, %r8 + movq 240(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 232(%rdi) + # a[i+30] += m[30] * mu + mulxq 240(%rsi), %rcx, %r8 + movq 248(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 240(%rdi) + # a[i+31] += m[31] * mu + mulxq 248(%rsi), %rcx, %r8 + movq 256(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 248(%rdi) + adcxq %r14, %r10 + movq %r12, %r14 + adoxq %r12, %r14 + adcxq %r12, %r14 + movq %r10, 256(%rdi) + # i += 1 + addq $8, %rdi + decq %r9 + jnz L_mont_loop_avx2_32 + movq %r13, (%rdi) + negq %r14 + movq %r14, %rcx + movq %rsi, %rdx + movq %rdi, %rsi + movq %rdi, %rdi + subq $256, %rdi +#ifndef __APPLE__ + callq sp_2048_cond_sub_32@plt +#else + callq _sp_2048_cond_sub_32 +#endif /* __APPLE__ */ + pop %r14 + pop %r13 + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_2048_mont_reduce_avx2_32,.-sp_2048_mont_reduce_avx2_32 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_3072_mul_24 +.type sp_3072_mul_24,@function +.align 16 +sp_3072_mul_24: +#else +.globl _sp_3072_mul_24 +.p2align 4 +_sp_3072_mul_24: +#endif /* __APPLE__ */ + movq %rdx, %rcx + subq $192, %rsp + # A[0] * B[0] + movq (%rcx), %rax + mulq (%rsi) + xorq %r10, %r10 + movq %rax, (%rsp) + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rcx), %rax + mulq (%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[1] * B[0] + movq (%rcx), %rax + mulq 8(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + movq %r9, 8(%rsp) + # A[0] * B[2] + movq 16(%rcx), %rax + mulq (%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[1] * B[1] + movq 8(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[2] * B[0] + movq (%rcx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + movq %r10, 16(%rsp) + # A[0] * B[3] + movq 24(%rcx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[1] * B[2] + movq 16(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[2] * B[1] + movq 8(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[3] * B[0] + movq (%rcx), %rax + mulq 24(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + movq %r8, 24(%rsp) + # A[0] * B[4] + movq 32(%rcx), %rax + mulq (%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[1] * B[3] + movq 24(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[2] * B[2] + movq 16(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[3] * B[1] + movq 8(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[4] * B[0] + movq (%rcx), %rax + mulq 32(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + movq %r9, 32(%rsp) + # A[0] * B[5] + movq 40(%rcx), %rax + mulq (%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[1] * B[4] + movq 32(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[2] * B[3] + movq 24(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[3] * B[2] + movq 16(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[4] * B[1] + movq 8(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[5] * B[0] + movq (%rcx), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + movq %r10, 40(%rsp) + # A[0] * B[6] + movq 48(%rcx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[1] * B[5] + movq 40(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[2] * B[4] + movq 32(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[3] * B[3] + movq 24(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[4] * B[2] + movq 16(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[5] * B[1] + movq 8(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[6] * B[0] + movq (%rcx), %rax + mulq 48(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + movq %r8, 48(%rsp) + # A[0] * B[7] + movq 56(%rcx), %rax + mulq (%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[1] * B[6] + movq 48(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[2] * B[5] + movq 40(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[3] * B[4] + movq 32(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[4] * B[3] + movq 24(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[5] * B[2] + movq 16(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[6] * B[1] + movq 8(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[7] * B[0] + movq (%rcx), %rax + mulq 56(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + movq %r9, 56(%rsp) + # A[0] * B[8] + movq 64(%rcx), %rax + mulq (%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[1] * B[7] + movq 56(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[2] * B[6] + movq 48(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[3] * B[5] + movq 40(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[4] * B[4] + movq 32(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[5] * B[3] + movq 24(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[6] * B[2] + movq 16(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[7] * B[1] + movq 8(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[8] * B[0] + movq (%rcx), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + movq %r10, 64(%rsp) + # A[0] * B[9] + movq 72(%rcx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[1] * B[8] + movq 64(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[2] * B[7] + movq 56(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[3] * B[6] + movq 48(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[4] * B[5] + movq 40(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[5] * B[4] + movq 32(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[6] * B[3] + movq 24(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[7] * B[2] + movq 16(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[8] * B[1] + movq 8(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[9] * B[0] + movq (%rcx), %rax + mulq 72(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + movq %r8, 72(%rsp) + # A[0] * B[10] + movq 80(%rcx), %rax + mulq (%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[1] * B[9] + movq 72(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[2] * B[8] + movq 64(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[3] * B[7] + movq 56(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[4] * B[6] + movq 48(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[5] * B[5] + movq 40(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[6] * B[4] + movq 32(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[7] * B[3] + movq 24(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[8] * B[2] + movq 16(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[9] * B[1] + movq 8(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[10] * B[0] + movq (%rcx), %rax + mulq 80(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + movq %r9, 80(%rsp) + # A[0] * B[11] + movq 88(%rcx), %rax + mulq (%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[1] * B[10] + movq 80(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[2] * B[9] + movq 72(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[3] * B[8] + movq 64(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[4] * B[7] + movq 56(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[5] * B[6] + movq 48(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[6] * B[5] + movq 40(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[7] * B[4] + movq 32(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[8] * B[3] + movq 24(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[9] * B[2] + movq 16(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[10] * B[1] + movq 8(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[11] * B[0] + movq (%rcx), %rax + mulq 88(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + movq %r10, 88(%rsp) + # A[0] * B[12] + movq 96(%rcx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[1] * B[11] + movq 88(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[2] * B[10] + movq 80(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[3] * B[9] + movq 72(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[4] * B[8] + movq 64(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[5] * B[7] + movq 56(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[6] * B[6] + movq 48(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[7] * B[5] + movq 40(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[8] * B[4] + movq 32(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[9] * B[3] + movq 24(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[10] * B[2] + movq 16(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[11] * B[1] + movq 8(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[12] * B[0] + movq (%rcx), %rax + mulq 96(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + movq %r8, 96(%rsp) + # A[0] * B[13] + movq 104(%rcx), %rax + mulq (%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[1] * B[12] + movq 96(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[2] * B[11] + movq 88(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[3] * B[10] + movq 80(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[4] * B[9] + movq 72(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[5] * B[8] + movq 64(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[6] * B[7] + movq 56(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[7] * B[6] + movq 48(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[8] * B[5] + movq 40(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[9] * B[4] + movq 32(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[10] * B[3] + movq 24(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[11] * B[2] + movq 16(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[12] * B[1] + movq 8(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[13] * B[0] + movq (%rcx), %rax + mulq 104(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + movq %r9, 104(%rsp) + # A[0] * B[14] + movq 112(%rcx), %rax + mulq (%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[1] * B[13] + movq 104(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[2] * B[12] + movq 96(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[3] * B[11] + movq 88(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[4] * B[10] + movq 80(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[5] * B[9] + movq 72(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[6] * B[8] + movq 64(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[7] * B[7] + movq 56(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[8] * B[6] + movq 48(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[9] * B[5] + movq 40(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[10] * B[4] + movq 32(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[11] * B[3] + movq 24(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[12] * B[2] + movq 16(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[13] * B[1] + movq 8(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[14] * B[0] + movq (%rcx), %rax + mulq 112(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + movq %r10, 112(%rsp) + # A[0] * B[15] + movq 120(%rcx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[1] * B[14] + movq 112(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[2] * B[13] + movq 104(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[3] * B[12] + movq 96(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[4] * B[11] + movq 88(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[5] * B[10] + movq 80(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[6] * B[9] + movq 72(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[7] * B[8] + movq 64(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[8] * B[7] + movq 56(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[9] * B[6] + movq 48(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[10] * B[5] + movq 40(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[11] * B[4] + movq 32(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[12] * B[3] + movq 24(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[13] * B[2] + movq 16(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[14] * B[1] + movq 8(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[15] * B[0] + movq (%rcx), %rax + mulq 120(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + movq %r8, 120(%rsp) + # A[0] * B[16] + movq 128(%rcx), %rax + mulq (%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[1] * B[15] + movq 120(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[2] * B[14] + movq 112(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[3] * B[13] + movq 104(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[4] * B[12] + movq 96(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[5] * B[11] + movq 88(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[6] * B[10] + movq 80(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[7] * B[9] + movq 72(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[8] * B[8] + movq 64(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[9] * B[7] + movq 56(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[10] * B[6] + movq 48(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[11] * B[5] + movq 40(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[12] * B[4] + movq 32(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[13] * B[3] + movq 24(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[14] * B[2] + movq 16(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[15] * B[1] + movq 8(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[16] * B[0] + movq (%rcx), %rax + mulq 128(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + movq %r9, 128(%rsp) + # A[0] * B[17] + movq 136(%rcx), %rax + mulq (%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[1] * B[16] + movq 128(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[2] * B[15] + movq 120(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[3] * B[14] + movq 112(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[4] * B[13] + movq 104(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[5] * B[12] + movq 96(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[6] * B[11] + movq 88(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[7] * B[10] + movq 80(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[8] * B[9] + movq 72(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[9] * B[8] + movq 64(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[10] * B[7] + movq 56(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[11] * B[6] + movq 48(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[12] * B[5] + movq 40(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[13] * B[4] + movq 32(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[14] * B[3] + movq 24(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[15] * B[2] + movq 16(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[16] * B[1] + movq 8(%rcx), %rax + mulq 128(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[17] * B[0] + movq (%rcx), %rax + mulq 136(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + movq %r10, 136(%rsp) + # A[0] * B[18] + movq 144(%rcx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[1] * B[17] + movq 136(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[2] * B[16] + movq 128(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[3] * B[15] + movq 120(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[4] * B[14] + movq 112(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[5] * B[13] + movq 104(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[6] * B[12] + movq 96(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[7] * B[11] + movq 88(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[8] * B[10] + movq 80(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[9] * B[9] + movq 72(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[10] * B[8] + movq 64(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[11] * B[7] + movq 56(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[12] * B[6] + movq 48(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[13] * B[5] + movq 40(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[14] * B[4] + movq 32(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[15] * B[3] + movq 24(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[16] * B[2] + movq 16(%rcx), %rax + mulq 128(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[17] * B[1] + movq 8(%rcx), %rax + mulq 136(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[18] * B[0] + movq (%rcx), %rax + mulq 144(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + movq %r8, 144(%rsp) + # A[0] * B[19] + movq 152(%rcx), %rax + mulq (%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[1] * B[18] + movq 144(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[2] * B[17] + movq 136(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[3] * B[16] + movq 128(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[4] * B[15] + movq 120(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[5] * B[14] + movq 112(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[6] * B[13] + movq 104(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[7] * B[12] + movq 96(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[8] * B[11] + movq 88(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[9] * B[10] + movq 80(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[10] * B[9] + movq 72(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[11] * B[8] + movq 64(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[12] * B[7] + movq 56(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[13] * B[6] + movq 48(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[14] * B[5] + movq 40(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[15] * B[4] + movq 32(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[16] * B[3] + movq 24(%rcx), %rax + mulq 128(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[17] * B[2] + movq 16(%rcx), %rax + mulq 136(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[18] * B[1] + movq 8(%rcx), %rax + mulq 144(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[19] * B[0] + movq (%rcx), %rax + mulq 152(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + movq %r9, 152(%rsp) + # A[0] * B[20] + movq 160(%rcx), %rax + mulq (%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[1] * B[19] + movq 152(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[2] * B[18] + movq 144(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[3] * B[17] + movq 136(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[4] * B[16] + movq 128(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[5] * B[15] + movq 120(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[6] * B[14] + movq 112(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[7] * B[13] + movq 104(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[8] * B[12] + movq 96(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[9] * B[11] + movq 88(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[10] * B[10] + movq 80(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[11] * B[9] + movq 72(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[12] * B[8] + movq 64(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[13] * B[7] + movq 56(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[14] * B[6] + movq 48(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[15] * B[5] + movq 40(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[16] * B[4] + movq 32(%rcx), %rax + mulq 128(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[17] * B[3] + movq 24(%rcx), %rax + mulq 136(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[18] * B[2] + movq 16(%rcx), %rax + mulq 144(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[19] * B[1] + movq 8(%rcx), %rax + mulq 152(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[20] * B[0] + movq (%rcx), %rax + mulq 160(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + movq %r10, 160(%rsp) + # A[0] * B[21] + movq 168(%rcx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[1] * B[20] + movq 160(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[2] * B[19] + movq 152(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[3] * B[18] + movq 144(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[4] * B[17] + movq 136(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[5] * B[16] + movq 128(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[6] * B[15] + movq 120(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[7] * B[14] + movq 112(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[8] * B[13] + movq 104(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[9] * B[12] + movq 96(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[10] * B[11] + movq 88(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[11] * B[10] + movq 80(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[12] * B[9] + movq 72(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[13] * B[8] + movq 64(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[14] * B[7] + movq 56(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[15] * B[6] + movq 48(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[16] * B[5] + movq 40(%rcx), %rax + mulq 128(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[17] * B[4] + movq 32(%rcx), %rax + mulq 136(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[18] * B[3] + movq 24(%rcx), %rax + mulq 144(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[19] * B[2] + movq 16(%rcx), %rax + mulq 152(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[20] * B[1] + movq 8(%rcx), %rax + mulq 160(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[21] * B[0] + movq (%rcx), %rax + mulq 168(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + movq %r8, 168(%rsp) + # A[0] * B[22] + movq 176(%rcx), %rax + mulq (%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[1] * B[21] + movq 168(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[2] * B[20] + movq 160(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[3] * B[19] + movq 152(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[4] * B[18] + movq 144(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[5] * B[17] + movq 136(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[6] * B[16] + movq 128(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[7] * B[15] + movq 120(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[8] * B[14] + movq 112(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[9] * B[13] + movq 104(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[10] * B[12] + movq 96(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[11] * B[11] + movq 88(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[12] * B[10] + movq 80(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[13] * B[9] + movq 72(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[14] * B[8] + movq 64(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[15] * B[7] + movq 56(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[16] * B[6] + movq 48(%rcx), %rax + mulq 128(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[17] * B[5] + movq 40(%rcx), %rax + mulq 136(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[18] * B[4] + movq 32(%rcx), %rax + mulq 144(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[19] * B[3] + movq 24(%rcx), %rax + mulq 152(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[20] * B[2] + movq 16(%rcx), %rax + mulq 160(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[21] * B[1] + movq 8(%rcx), %rax + mulq 168(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[22] * B[0] + movq (%rcx), %rax + mulq 176(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + movq %r9, 176(%rsp) + # A[0] * B[23] + movq 184(%rcx), %rax + mulq (%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[1] * B[22] + movq 176(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[2] * B[21] + movq 168(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[3] * B[20] + movq 160(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[4] * B[19] + movq 152(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[5] * B[18] + movq 144(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[6] * B[17] + movq 136(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[7] * B[16] + movq 128(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[8] * B[15] + movq 120(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[9] * B[14] + movq 112(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[10] * B[13] + movq 104(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[11] * B[12] + movq 96(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[12] * B[11] + movq 88(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[13] * B[10] + movq 80(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[14] * B[9] + movq 72(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[15] * B[8] + movq 64(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[16] * B[7] + movq 56(%rcx), %rax + mulq 128(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[17] * B[6] + movq 48(%rcx), %rax + mulq 136(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[18] * B[5] + movq 40(%rcx), %rax + mulq 144(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[19] * B[4] + movq 32(%rcx), %rax + mulq 152(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[20] * B[3] + movq 24(%rcx), %rax + mulq 160(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[21] * B[2] + movq 16(%rcx), %rax + mulq 168(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[22] * B[1] + movq 8(%rcx), %rax + mulq 176(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[23] * B[0] + movq (%rcx), %rax + mulq 184(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + movq %r10, 184(%rsp) + # A[1] * B[23] + movq 184(%rcx), %rax + mulq 8(%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[2] * B[22] + movq 176(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[3] * B[21] + movq 168(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[4] * B[20] + movq 160(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[5] * B[19] + movq 152(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[6] * B[18] + movq 144(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[7] * B[17] + movq 136(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[8] * B[16] + movq 128(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[9] * B[15] + movq 120(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[10] * B[14] + movq 112(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[11] * B[13] + movq 104(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[12] * B[12] + movq 96(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[13] * B[11] + movq 88(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[14] * B[10] + movq 80(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[15] * B[9] + movq 72(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[16] * B[8] + movq 64(%rcx), %rax + mulq 128(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[17] * B[7] + movq 56(%rcx), %rax + mulq 136(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[18] * B[6] + movq 48(%rcx), %rax + mulq 144(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[19] * B[5] + movq 40(%rcx), %rax + mulq 152(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[20] * B[4] + movq 32(%rcx), %rax + mulq 160(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[21] * B[3] + movq 24(%rcx), %rax + mulq 168(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[22] * B[2] + movq 16(%rcx), %rax + mulq 176(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[23] * B[1] + movq 8(%rcx), %rax + mulq 184(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + movq %r8, 192(%rdi) + # A[2] * B[23] + movq 184(%rcx), %rax + mulq 16(%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[3] * B[22] + movq 176(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[4] * B[21] + movq 168(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[5] * B[20] + movq 160(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[6] * B[19] + movq 152(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[7] * B[18] + movq 144(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[8] * B[17] + movq 136(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[9] * B[16] + movq 128(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[10] * B[15] + movq 120(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[11] * B[14] + movq 112(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[12] * B[13] + movq 104(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[13] * B[12] + movq 96(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[14] * B[11] + movq 88(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[15] * B[10] + movq 80(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[16] * B[9] + movq 72(%rcx), %rax + mulq 128(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[17] * B[8] + movq 64(%rcx), %rax + mulq 136(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[18] * B[7] + movq 56(%rcx), %rax + mulq 144(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[19] * B[6] + movq 48(%rcx), %rax + mulq 152(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[20] * B[5] + movq 40(%rcx), %rax + mulq 160(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[21] * B[4] + movq 32(%rcx), %rax + mulq 168(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[22] * B[3] + movq 24(%rcx), %rax + mulq 176(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[23] * B[2] + movq 16(%rcx), %rax + mulq 184(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + movq %r9, 200(%rdi) + # A[3] * B[23] + movq 184(%rcx), %rax + mulq 24(%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[4] * B[22] + movq 176(%rcx), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[5] * B[21] + movq 168(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[6] * B[20] + movq 160(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[7] * B[19] + movq 152(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[8] * B[18] + movq 144(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[9] * B[17] + movq 136(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[10] * B[16] + movq 128(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[11] * B[15] + movq 120(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[12] * B[14] + movq 112(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[13] * B[13] + movq 104(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[14] * B[12] + movq 96(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[15] * B[11] + movq 88(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[16] * B[10] + movq 80(%rcx), %rax + mulq 128(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[17] * B[9] + movq 72(%rcx), %rax + mulq 136(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[18] * B[8] + movq 64(%rcx), %rax + mulq 144(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[19] * B[7] + movq 56(%rcx), %rax + mulq 152(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[20] * B[6] + movq 48(%rcx), %rax + mulq 160(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[21] * B[5] + movq 40(%rcx), %rax + mulq 168(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[22] * B[4] + movq 32(%rcx), %rax + mulq 176(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[23] * B[3] + movq 24(%rcx), %rax + mulq 184(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + movq %r10, 208(%rdi) + # A[4] * B[23] + movq 184(%rcx), %rax + mulq 32(%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[5] * B[22] + movq 176(%rcx), %rax + mulq 40(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[6] * B[21] + movq 168(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[7] * B[20] + movq 160(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[8] * B[19] + movq 152(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[9] * B[18] + movq 144(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[10] * B[17] + movq 136(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[11] * B[16] + movq 128(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[12] * B[15] + movq 120(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[13] * B[14] + movq 112(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[14] * B[13] + movq 104(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[15] * B[12] + movq 96(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[16] * B[11] + movq 88(%rcx), %rax + mulq 128(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[17] * B[10] + movq 80(%rcx), %rax + mulq 136(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[18] * B[9] + movq 72(%rcx), %rax + mulq 144(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[19] * B[8] + movq 64(%rcx), %rax + mulq 152(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[20] * B[7] + movq 56(%rcx), %rax + mulq 160(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[21] * B[6] + movq 48(%rcx), %rax + mulq 168(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[22] * B[5] + movq 40(%rcx), %rax + mulq 176(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[23] * B[4] + movq 32(%rcx), %rax + mulq 184(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + movq %r8, 216(%rdi) + # A[5] * B[23] + movq 184(%rcx), %rax + mulq 40(%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[6] * B[22] + movq 176(%rcx), %rax + mulq 48(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[7] * B[21] + movq 168(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[8] * B[20] + movq 160(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[9] * B[19] + movq 152(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[10] * B[18] + movq 144(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[11] * B[17] + movq 136(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[12] * B[16] + movq 128(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[13] * B[15] + movq 120(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[14] * B[14] + movq 112(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[15] * B[13] + movq 104(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[16] * B[12] + movq 96(%rcx), %rax + mulq 128(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[17] * B[11] + movq 88(%rcx), %rax + mulq 136(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[18] * B[10] + movq 80(%rcx), %rax + mulq 144(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[19] * B[9] + movq 72(%rcx), %rax + mulq 152(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[20] * B[8] + movq 64(%rcx), %rax + mulq 160(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[21] * B[7] + movq 56(%rcx), %rax + mulq 168(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[22] * B[6] + movq 48(%rcx), %rax + mulq 176(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[23] * B[5] + movq 40(%rcx), %rax + mulq 184(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + movq %r9, 224(%rdi) + # A[6] * B[23] + movq 184(%rcx), %rax + mulq 48(%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[7] * B[22] + movq 176(%rcx), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[8] * B[21] + movq 168(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[9] * B[20] + movq 160(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[10] * B[19] + movq 152(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[11] * B[18] + movq 144(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[12] * B[17] + movq 136(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[13] * B[16] + movq 128(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[14] * B[15] + movq 120(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[15] * B[14] + movq 112(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[16] * B[13] + movq 104(%rcx), %rax + mulq 128(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[17] * B[12] + movq 96(%rcx), %rax + mulq 136(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[18] * B[11] + movq 88(%rcx), %rax + mulq 144(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[19] * B[10] + movq 80(%rcx), %rax + mulq 152(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[20] * B[9] + movq 72(%rcx), %rax + mulq 160(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[21] * B[8] + movq 64(%rcx), %rax + mulq 168(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[22] * B[7] + movq 56(%rcx), %rax + mulq 176(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[23] * B[6] + movq 48(%rcx), %rax + mulq 184(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + movq %r10, 232(%rdi) + # A[7] * B[23] + movq 184(%rcx), %rax + mulq 56(%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[8] * B[22] + movq 176(%rcx), %rax + mulq 64(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[9] * B[21] + movq 168(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[10] * B[20] + movq 160(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[11] * B[19] + movq 152(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[12] * B[18] + movq 144(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[13] * B[17] + movq 136(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[14] * B[16] + movq 128(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[15] * B[15] + movq 120(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[16] * B[14] + movq 112(%rcx), %rax + mulq 128(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[17] * B[13] + movq 104(%rcx), %rax + mulq 136(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[18] * B[12] + movq 96(%rcx), %rax + mulq 144(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[19] * B[11] + movq 88(%rcx), %rax + mulq 152(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[20] * B[10] + movq 80(%rcx), %rax + mulq 160(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[21] * B[9] + movq 72(%rcx), %rax + mulq 168(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[22] * B[8] + movq 64(%rcx), %rax + mulq 176(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[23] * B[7] + movq 56(%rcx), %rax + mulq 184(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + movq %r8, 240(%rdi) + # A[8] * B[23] + movq 184(%rcx), %rax + mulq 64(%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[9] * B[22] + movq 176(%rcx), %rax + mulq 72(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[10] * B[21] + movq 168(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[11] * B[20] + movq 160(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[12] * B[19] + movq 152(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[13] * B[18] + movq 144(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[14] * B[17] + movq 136(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[15] * B[16] + movq 128(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[16] * B[15] + movq 120(%rcx), %rax + mulq 128(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[17] * B[14] + movq 112(%rcx), %rax + mulq 136(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[18] * B[13] + movq 104(%rcx), %rax + mulq 144(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[19] * B[12] + movq 96(%rcx), %rax + mulq 152(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[20] * B[11] + movq 88(%rcx), %rax + mulq 160(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[21] * B[10] + movq 80(%rcx), %rax + mulq 168(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[22] * B[9] + movq 72(%rcx), %rax + mulq 176(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[23] * B[8] + movq 64(%rcx), %rax + mulq 184(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + movq %r9, 248(%rdi) + # A[9] * B[23] + movq 184(%rcx), %rax + mulq 72(%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[10] * B[22] + movq 176(%rcx), %rax + mulq 80(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[11] * B[21] + movq 168(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[12] * B[20] + movq 160(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[13] * B[19] + movq 152(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[14] * B[18] + movq 144(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[15] * B[17] + movq 136(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[16] * B[16] + movq 128(%rcx), %rax + mulq 128(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[17] * B[15] + movq 120(%rcx), %rax + mulq 136(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[18] * B[14] + movq 112(%rcx), %rax + mulq 144(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[19] * B[13] + movq 104(%rcx), %rax + mulq 152(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[20] * B[12] + movq 96(%rcx), %rax + mulq 160(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[21] * B[11] + movq 88(%rcx), %rax + mulq 168(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[22] * B[10] + movq 80(%rcx), %rax + mulq 176(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[23] * B[9] + movq 72(%rcx), %rax + mulq 184(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + movq %r10, 256(%rdi) + # A[10] * B[23] + movq 184(%rcx), %rax + mulq 80(%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[11] * B[22] + movq 176(%rcx), %rax + mulq 88(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[12] * B[21] + movq 168(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[13] * B[20] + movq 160(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[14] * B[19] + movq 152(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[15] * B[18] + movq 144(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[16] * B[17] + movq 136(%rcx), %rax + mulq 128(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[17] * B[16] + movq 128(%rcx), %rax + mulq 136(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[18] * B[15] + movq 120(%rcx), %rax + mulq 144(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[19] * B[14] + movq 112(%rcx), %rax + mulq 152(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[20] * B[13] + movq 104(%rcx), %rax + mulq 160(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[21] * B[12] + movq 96(%rcx), %rax + mulq 168(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[22] * B[11] + movq 88(%rcx), %rax + mulq 176(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[23] * B[10] + movq 80(%rcx), %rax + mulq 184(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + movq %r8, 264(%rdi) + # A[11] * B[23] + movq 184(%rcx), %rax + mulq 88(%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[12] * B[22] + movq 176(%rcx), %rax + mulq 96(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[13] * B[21] + movq 168(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[14] * B[20] + movq 160(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[15] * B[19] + movq 152(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[16] * B[18] + movq 144(%rcx), %rax + mulq 128(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[17] * B[17] + movq 136(%rcx), %rax + mulq 136(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[18] * B[16] + movq 128(%rcx), %rax + mulq 144(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[19] * B[15] + movq 120(%rcx), %rax + mulq 152(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[20] * B[14] + movq 112(%rcx), %rax + mulq 160(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[21] * B[13] + movq 104(%rcx), %rax + mulq 168(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[22] * B[12] + movq 96(%rcx), %rax + mulq 176(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[23] * B[11] + movq 88(%rcx), %rax + mulq 184(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + movq %r9, 272(%rdi) + # A[12] * B[23] + movq 184(%rcx), %rax + mulq 96(%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[13] * B[22] + movq 176(%rcx), %rax + mulq 104(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[14] * B[21] + movq 168(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[15] * B[20] + movq 160(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[16] * B[19] + movq 152(%rcx), %rax + mulq 128(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[17] * B[18] + movq 144(%rcx), %rax + mulq 136(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[18] * B[17] + movq 136(%rcx), %rax + mulq 144(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[19] * B[16] + movq 128(%rcx), %rax + mulq 152(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[20] * B[15] + movq 120(%rcx), %rax + mulq 160(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[21] * B[14] + movq 112(%rcx), %rax + mulq 168(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[22] * B[13] + movq 104(%rcx), %rax + mulq 176(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[23] * B[12] + movq 96(%rcx), %rax + mulq 184(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + movq %r10, 280(%rdi) + # A[13] * B[23] + movq 184(%rcx), %rax + mulq 104(%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[14] * B[22] + movq 176(%rcx), %rax + mulq 112(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[15] * B[21] + movq 168(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[16] * B[20] + movq 160(%rcx), %rax + mulq 128(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[17] * B[19] + movq 152(%rcx), %rax + mulq 136(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[18] * B[18] + movq 144(%rcx), %rax + mulq 144(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[19] * B[17] + movq 136(%rcx), %rax + mulq 152(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[20] * B[16] + movq 128(%rcx), %rax + mulq 160(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[21] * B[15] + movq 120(%rcx), %rax + mulq 168(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[22] * B[14] + movq 112(%rcx), %rax + mulq 176(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[23] * B[13] + movq 104(%rcx), %rax + mulq 184(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + movq %r8, 288(%rdi) + # A[14] * B[23] + movq 184(%rcx), %rax + mulq 112(%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[15] * B[22] + movq 176(%rcx), %rax + mulq 120(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[16] * B[21] + movq 168(%rcx), %rax + mulq 128(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[17] * B[20] + movq 160(%rcx), %rax + mulq 136(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[18] * B[19] + movq 152(%rcx), %rax + mulq 144(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[19] * B[18] + movq 144(%rcx), %rax + mulq 152(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[20] * B[17] + movq 136(%rcx), %rax + mulq 160(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[21] * B[16] + movq 128(%rcx), %rax + mulq 168(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[22] * B[15] + movq 120(%rcx), %rax + mulq 176(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[23] * B[14] + movq 112(%rcx), %rax + mulq 184(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + movq %r9, 296(%rdi) + # A[15] * B[23] + movq 184(%rcx), %rax + mulq 120(%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[16] * B[22] + movq 176(%rcx), %rax + mulq 128(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[17] * B[21] + movq 168(%rcx), %rax + mulq 136(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[18] * B[20] + movq 160(%rcx), %rax + mulq 144(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[19] * B[19] + movq 152(%rcx), %rax + mulq 152(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[20] * B[18] + movq 144(%rcx), %rax + mulq 160(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[21] * B[17] + movq 136(%rcx), %rax + mulq 168(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[22] * B[16] + movq 128(%rcx), %rax + mulq 176(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[23] * B[15] + movq 120(%rcx), %rax + mulq 184(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + movq %r10, 304(%rdi) + # A[16] * B[23] + movq 184(%rcx), %rax + mulq 128(%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[17] * B[22] + movq 176(%rcx), %rax + mulq 136(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[18] * B[21] + movq 168(%rcx), %rax + mulq 144(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[19] * B[20] + movq 160(%rcx), %rax + mulq 152(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[20] * B[19] + movq 152(%rcx), %rax + mulq 160(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[21] * B[18] + movq 144(%rcx), %rax + mulq 168(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[22] * B[17] + movq 136(%rcx), %rax + mulq 176(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[23] * B[16] + movq 128(%rcx), %rax + mulq 184(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + movq %r8, 312(%rdi) + # A[17] * B[23] + movq 184(%rcx), %rax + mulq 136(%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[18] * B[22] + movq 176(%rcx), %rax + mulq 144(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[19] * B[21] + movq 168(%rcx), %rax + mulq 152(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[20] * B[20] + movq 160(%rcx), %rax + mulq 160(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[21] * B[19] + movq 152(%rcx), %rax + mulq 168(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[22] * B[18] + movq 144(%rcx), %rax + mulq 176(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[23] * B[17] + movq 136(%rcx), %rax + mulq 184(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + movq %r9, 320(%rdi) + # A[18] * B[23] + movq 184(%rcx), %rax + mulq 144(%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[19] * B[22] + movq 176(%rcx), %rax + mulq 152(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[20] * B[21] + movq 168(%rcx), %rax + mulq 160(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[21] * B[20] + movq 160(%rcx), %rax + mulq 168(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[22] * B[19] + movq 152(%rcx), %rax + mulq 176(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[23] * B[18] + movq 144(%rcx), %rax + mulq 184(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + movq %r10, 328(%rdi) + # A[19] * B[23] + movq 184(%rcx), %rax + mulq 152(%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[20] * B[22] + movq 176(%rcx), %rax + mulq 160(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[21] * B[21] + movq 168(%rcx), %rax + mulq 168(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[22] * B[20] + movq 160(%rcx), %rax + mulq 176(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[23] * B[19] + movq 152(%rcx), %rax + mulq 184(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + movq %r8, 336(%rdi) + # A[20] * B[23] + movq 184(%rcx), %rax + mulq 160(%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[21] * B[22] + movq 176(%rcx), %rax + mulq 168(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[22] * B[21] + movq 168(%rcx), %rax + mulq 176(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[23] * B[20] + movq 160(%rcx), %rax + mulq 184(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + movq %r9, 344(%rdi) + # A[21] * B[23] + movq 184(%rcx), %rax + mulq 168(%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[22] * B[22] + movq 176(%rcx), %rax + mulq 176(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[23] * B[21] + movq 168(%rcx), %rax + mulq 184(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + movq %r10, 352(%rdi) + # A[22] * B[23] + movq 184(%rcx), %rax + mulq 176(%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[23] * B[22] + movq 176(%rcx), %rax + mulq 184(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + movq %r8, 360(%rdi) + # A[23] * B[23] + movq 184(%rcx), %rax + mulq 184(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + movq %r9, 368(%rdi) + movq %r10, 376(%rdi) + movq (%rsp), %rax + movq 8(%rsp), %rdx + movq 16(%rsp), %r8 + movq 24(%rsp), %r9 + movq %rax, (%rdi) + movq %rdx, 8(%rdi) + movq %r8, 16(%rdi) + movq %r9, 24(%rdi) + movq 32(%rsp), %rax + movq 40(%rsp), %rdx + movq 48(%rsp), %r8 + movq 56(%rsp), %r9 + movq %rax, 32(%rdi) + movq %rdx, 40(%rdi) + movq %r8, 48(%rdi) + movq %r9, 56(%rdi) + movq 64(%rsp), %rax + movq 72(%rsp), %rdx + movq 80(%rsp), %r8 + movq 88(%rsp), %r9 + movq %rax, 64(%rdi) + movq %rdx, 72(%rdi) + movq %r8, 80(%rdi) + movq %r9, 88(%rdi) + movq 96(%rsp), %rax + movq 104(%rsp), %rdx + movq 112(%rsp), %r8 + movq 120(%rsp), %r9 + movq %rax, 96(%rdi) + movq %rdx, 104(%rdi) + movq %r8, 112(%rdi) + movq %r9, 120(%rdi) + movq 128(%rsp), %rax + movq 136(%rsp), %rdx + movq 144(%rsp), %r8 + movq 152(%rsp), %r9 + movq %rax, 128(%rdi) + movq %rdx, 136(%rdi) + movq %r8, 144(%rdi) + movq %r9, 152(%rdi) + movq 160(%rsp), %rax + movq 168(%rsp), %rdx + movq 176(%rsp), %r8 + movq 184(%rsp), %r9 + movq %rax, 160(%rdi) + movq %rdx, 168(%rdi) + movq %r8, 176(%rdi) + movq %r9, 184(%rdi) + addq $192, %rsp + repz retq +#ifndef __APPLE__ +.size sp_3072_mul_24,.-sp_3072_mul_24 +#endif /* __APPLE__ */ +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_3072_sqr_24 +.type sp_3072_sqr_24,@function +.align 16 +sp_3072_sqr_24: +#else +.globl _sp_3072_sqr_24 +.p2align 4 +_sp_3072_sqr_24: +#endif /* __APPLE__ */ + push %r12 + subq $192, %rsp + # A[0] * A[0] + movq (%rsi), %rax + mulq %rax + xorq %r9, %r9 + movq %rax, (%rsp) + movq %rdx, %r8 + # A[0] * A[1] + movq 8(%rsi), %rax + mulq (%rsi) + xorq %rcx, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + movq %r8, 8(%rsp) + # A[0] * A[2] + movq 16(%rsi), %rax + mulq (%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0, %r8 + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0, %r8 + # A[1] * A[1] + movq 8(%rsi), %rax + mulq %rax + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0, %r8 + movq %r9, 16(%rsp) + # A[0] * A[3] + movq 24(%rsi), %rax + mulq (%rsi) + xorq %r9, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + # A[1] * A[2] + movq 16(%rsi), %rax + mulq 8(%rsi) + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + movq %rcx, 24(%rsp) + # A[0] * A[4] + movq 32(%rsi), %rax + mulq (%rsi) + xorq %rcx, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + # A[1] * A[3] + movq 24(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + # A[2] * A[2] + movq 16(%rsi), %rax + mulq %rax + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + movq %r8, 32(%rsp) + # A[0] * A[5] + movq 40(%rsi), %rax + mulq (%rsi) + xorq %r8, %r8 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[4] + movq 32(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[2] * A[3] + movq 24(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %r9 + adcq %r11, %rcx + adcq %r12, %r8 + movq %r9, 40(%rsp) + # A[0] * A[6] + movq 48(%rsi), %rax + mulq (%rsi) + xorq %r9, %r9 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[5] + movq 40(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[2] * A[4] + movq 32(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[3] * A[3] + movq 24(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %rcx + adcq %r11, %r8 + adcq %r12, %r9 + movq %rcx, 48(%rsp) + # A[0] * A[7] + movq 56(%rsi), %rax + mulq (%rsi) + xorq %rcx, %rcx + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[6] + movq 48(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[2] * A[5] + movq 40(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[3] * A[4] + movq 32(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %r8 + adcq %r11, %r9 + adcq %r12, %rcx + movq %r8, 56(%rsp) + # A[0] * A[8] + movq 64(%rsi), %rax + mulq (%rsi) + xorq %r8, %r8 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[7] + movq 56(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[2] * A[6] + movq 48(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[3] * A[5] + movq 40(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[4] * A[4] + movq 32(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r9 + adcq %r11, %rcx + adcq %r12, %r8 + movq %r9, 64(%rsp) + # A[0] * A[9] + movq 72(%rsi), %rax + mulq (%rsi) + xorq %r9, %r9 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[8] + movq 64(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[2] * A[7] + movq 56(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[3] * A[6] + movq 48(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[4] * A[5] + movq 40(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %rcx + adcq %r11, %r8 + adcq %r12, %r9 + movq %rcx, 72(%rsp) + # A[0] * A[10] + movq 80(%rsi), %rax + mulq (%rsi) + xorq %rcx, %rcx + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[9] + movq 72(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[2] * A[8] + movq 64(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[3] * A[7] + movq 56(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[4] * A[6] + movq 48(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[5] * A[5] + movq 40(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r8 + adcq %r11, %r9 + adcq %r12, %rcx + movq %r8, 80(%rsp) + # A[0] * A[11] + movq 88(%rsi), %rax + mulq (%rsi) + xorq %r8, %r8 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[10] + movq 80(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[2] * A[9] + movq 72(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[3] * A[8] + movq 64(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[4] * A[7] + movq 56(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[5] * A[6] + movq 48(%rsi), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %r9 + adcq %r11, %rcx + adcq %r12, %r8 + movq %r9, 88(%rsp) + # A[0] * A[12] + movq 96(%rsi), %rax + mulq (%rsi) + xorq %r9, %r9 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[11] + movq 88(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[2] * A[10] + movq 80(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[3] * A[9] + movq 72(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[4] * A[8] + movq 64(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[5] * A[7] + movq 56(%rsi), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[6] * A[6] + movq 48(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %rcx + adcq %r11, %r8 + adcq %r12, %r9 + movq %rcx, 96(%rsp) + # A[0] * A[13] + movq 104(%rsi), %rax + mulq (%rsi) + xorq %rcx, %rcx + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[12] + movq 96(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[2] * A[11] + movq 88(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[3] * A[10] + movq 80(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[4] * A[9] + movq 72(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[5] * A[8] + movq 64(%rsi), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[6] * A[7] + movq 56(%rsi), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %r8 + adcq %r11, %r9 + adcq %r12, %rcx + movq %r8, 104(%rsp) + # A[0] * A[14] + movq 112(%rsi), %rax + mulq (%rsi) + xorq %r8, %r8 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[13] + movq 104(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[2] * A[12] + movq 96(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[3] * A[11] + movq 88(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[4] * A[10] + movq 80(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[5] * A[9] + movq 72(%rsi), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[6] * A[8] + movq 64(%rsi), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[7] * A[7] + movq 56(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r9 + adcq %r11, %rcx + adcq %r12, %r8 + movq %r9, 112(%rsp) + # A[0] * A[15] + movq 120(%rsi), %rax + mulq (%rsi) + xorq %r9, %r9 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[14] + movq 112(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[2] * A[13] + movq 104(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[3] * A[12] + movq 96(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[4] * A[11] + movq 88(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[5] * A[10] + movq 80(%rsi), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[6] * A[9] + movq 72(%rsi), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[7] * A[8] + movq 64(%rsi), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %rcx + adcq %r11, %r8 + adcq %r12, %r9 + movq %rcx, 120(%rsp) + # A[0] * A[16] + movq 128(%rsi), %rax + mulq (%rsi) + xorq %rcx, %rcx + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[15] + movq 120(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[2] * A[14] + movq 112(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[3] * A[13] + movq 104(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[4] * A[12] + movq 96(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[5] * A[11] + movq 88(%rsi), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[6] * A[10] + movq 80(%rsi), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[7] * A[9] + movq 72(%rsi), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[8] * A[8] + movq 64(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r8 + adcq %r11, %r9 + adcq %r12, %rcx + movq %r8, 128(%rsp) + # A[0] * A[17] + movq 136(%rsi), %rax + mulq (%rsi) + xorq %r8, %r8 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[16] + movq 128(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[2] * A[15] + movq 120(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[3] * A[14] + movq 112(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[4] * A[13] + movq 104(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[5] * A[12] + movq 96(%rsi), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[6] * A[11] + movq 88(%rsi), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[7] * A[10] + movq 80(%rsi), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[8] * A[9] + movq 72(%rsi), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %r9 + adcq %r11, %rcx + adcq %r12, %r8 + movq %r9, 136(%rsp) + # A[0] * A[18] + movq 144(%rsi), %rax + mulq (%rsi) + xorq %r9, %r9 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[17] + movq 136(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[2] * A[16] + movq 128(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[3] * A[15] + movq 120(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[4] * A[14] + movq 112(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[5] * A[13] + movq 104(%rsi), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[6] * A[12] + movq 96(%rsi), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[7] * A[11] + movq 88(%rsi), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[8] * A[10] + movq 80(%rsi), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[9] * A[9] + movq 72(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %rcx + adcq %r11, %r8 + adcq %r12, %r9 + movq %rcx, 144(%rsp) + # A[0] * A[19] + movq 152(%rsi), %rax + mulq (%rsi) + xorq %rcx, %rcx + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[18] + movq 144(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[2] * A[17] + movq 136(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[3] * A[16] + movq 128(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[4] * A[15] + movq 120(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[5] * A[14] + movq 112(%rsi), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[6] * A[13] + movq 104(%rsi), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[7] * A[12] + movq 96(%rsi), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[8] * A[11] + movq 88(%rsi), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[9] * A[10] + movq 80(%rsi), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %r8 + adcq %r11, %r9 + adcq %r12, %rcx + movq %r8, 152(%rsp) + # A[0] * A[20] + movq 160(%rsi), %rax + mulq (%rsi) + xorq %r8, %r8 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[19] + movq 152(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[2] * A[18] + movq 144(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[3] * A[17] + movq 136(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[4] * A[16] + movq 128(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[5] * A[15] + movq 120(%rsi), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[6] * A[14] + movq 112(%rsi), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[7] * A[13] + movq 104(%rsi), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[8] * A[12] + movq 96(%rsi), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[9] * A[11] + movq 88(%rsi), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[10] * A[10] + movq 80(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r9 + adcq %r11, %rcx + adcq %r12, %r8 + movq %r9, 160(%rsp) + # A[0] * A[21] + movq 168(%rsi), %rax + mulq (%rsi) + xorq %r9, %r9 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[20] + movq 160(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[2] * A[19] + movq 152(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[3] * A[18] + movq 144(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[4] * A[17] + movq 136(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[5] * A[16] + movq 128(%rsi), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[6] * A[15] + movq 120(%rsi), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[7] * A[14] + movq 112(%rsi), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[8] * A[13] + movq 104(%rsi), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[9] * A[12] + movq 96(%rsi), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[10] * A[11] + movq 88(%rsi), %rax + mulq 80(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %rcx + adcq %r11, %r8 + adcq %r12, %r9 + movq %rcx, 168(%rsp) + # A[0] * A[22] + movq 176(%rsi), %rax + mulq (%rsi) + xorq %rcx, %rcx + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[21] + movq 168(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[2] * A[20] + movq 160(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[3] * A[19] + movq 152(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[4] * A[18] + movq 144(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[5] * A[17] + movq 136(%rsi), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[6] * A[16] + movq 128(%rsi), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[7] * A[15] + movq 120(%rsi), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[8] * A[14] + movq 112(%rsi), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[9] * A[13] + movq 104(%rsi), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[10] * A[12] + movq 96(%rsi), %rax + mulq 80(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[11] * A[11] + movq 88(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r8 + adcq %r11, %r9 + adcq %r12, %rcx + movq %r8, 176(%rsp) + # A[0] * A[23] + movq 184(%rsi), %rax + mulq (%rsi) + xorq %r8, %r8 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[1] * A[22] + movq 176(%rsi), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[2] * A[21] + movq 168(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[3] * A[20] + movq 160(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[4] * A[19] + movq 152(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[5] * A[18] + movq 144(%rsi), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[6] * A[17] + movq 136(%rsi), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[7] * A[16] + movq 128(%rsi), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[8] * A[15] + movq 120(%rsi), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[9] * A[14] + movq 112(%rsi), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[10] * A[13] + movq 104(%rsi), %rax + mulq 80(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[11] * A[12] + movq 96(%rsi), %rax + mulq 88(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %r9 + adcq %r11, %rcx + adcq %r12, %r8 + movq %r9, 184(%rsp) + # A[1] * A[23] + movq 184(%rsi), %rax + mulq 8(%rsi) + xorq %r9, %r9 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[2] * A[22] + movq 176(%rsi), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[3] * A[21] + movq 168(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[4] * A[20] + movq 160(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[5] * A[19] + movq 152(%rsi), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[6] * A[18] + movq 144(%rsi), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[7] * A[17] + movq 136(%rsi), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[8] * A[16] + movq 128(%rsi), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[9] * A[15] + movq 120(%rsi), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[10] * A[14] + movq 112(%rsi), %rax + mulq 80(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[11] * A[13] + movq 104(%rsi), %rax + mulq 88(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[12] * A[12] + movq 96(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %rcx + adcq %r11, %r8 + adcq %r12, %r9 + movq %rcx, 192(%rdi) + # A[2] * A[23] + movq 184(%rsi), %rax + mulq 16(%rsi) + xorq %rcx, %rcx + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[3] * A[22] + movq 176(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[4] * A[21] + movq 168(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[5] * A[20] + movq 160(%rsi), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[6] * A[19] + movq 152(%rsi), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[7] * A[18] + movq 144(%rsi), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[8] * A[17] + movq 136(%rsi), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[9] * A[16] + movq 128(%rsi), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[10] * A[15] + movq 120(%rsi), %rax + mulq 80(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[11] * A[14] + movq 112(%rsi), %rax + mulq 88(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[12] * A[13] + movq 104(%rsi), %rax + mulq 96(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %r8 + adcq %r11, %r9 + adcq %r12, %rcx + movq %r8, 200(%rdi) + # A[3] * A[23] + movq 184(%rsi), %rax + mulq 24(%rsi) + xorq %r8, %r8 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[4] * A[22] + movq 176(%rsi), %rax + mulq 32(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[5] * A[21] + movq 168(%rsi), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[6] * A[20] + movq 160(%rsi), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[7] * A[19] + movq 152(%rsi), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[8] * A[18] + movq 144(%rsi), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[9] * A[17] + movq 136(%rsi), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[10] * A[16] + movq 128(%rsi), %rax + mulq 80(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[11] * A[15] + movq 120(%rsi), %rax + mulq 88(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[12] * A[14] + movq 112(%rsi), %rax + mulq 96(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[13] * A[13] + movq 104(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r9 + adcq %r11, %rcx + adcq %r12, %r8 + movq %r9, 208(%rdi) + # A[4] * A[23] + movq 184(%rsi), %rax + mulq 32(%rsi) + xorq %r9, %r9 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[5] * A[22] + movq 176(%rsi), %rax + mulq 40(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[6] * A[21] + movq 168(%rsi), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[7] * A[20] + movq 160(%rsi), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[8] * A[19] + movq 152(%rsi), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[9] * A[18] + movq 144(%rsi), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[10] * A[17] + movq 136(%rsi), %rax + mulq 80(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[11] * A[16] + movq 128(%rsi), %rax + mulq 88(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[12] * A[15] + movq 120(%rsi), %rax + mulq 96(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[13] * A[14] + movq 112(%rsi), %rax + mulq 104(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %rcx + adcq %r11, %r8 + adcq %r12, %r9 + movq %rcx, 216(%rdi) + # A[5] * A[23] + movq 184(%rsi), %rax + mulq 40(%rsi) + xorq %rcx, %rcx + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[6] * A[22] + movq 176(%rsi), %rax + mulq 48(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[7] * A[21] + movq 168(%rsi), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[8] * A[20] + movq 160(%rsi), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[9] * A[19] + movq 152(%rsi), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[10] * A[18] + movq 144(%rsi), %rax + mulq 80(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[11] * A[17] + movq 136(%rsi), %rax + mulq 88(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[12] * A[16] + movq 128(%rsi), %rax + mulq 96(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[13] * A[15] + movq 120(%rsi), %rax + mulq 104(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[14] * A[14] + movq 112(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r8 + adcq %r11, %r9 + adcq %r12, %rcx + movq %r8, 224(%rdi) + # A[6] * A[23] + movq 184(%rsi), %rax + mulq 48(%rsi) + xorq %r8, %r8 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[7] * A[22] + movq 176(%rsi), %rax + mulq 56(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[8] * A[21] + movq 168(%rsi), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[9] * A[20] + movq 160(%rsi), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[10] * A[19] + movq 152(%rsi), %rax + mulq 80(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[11] * A[18] + movq 144(%rsi), %rax + mulq 88(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[12] * A[17] + movq 136(%rsi), %rax + mulq 96(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[13] * A[16] + movq 128(%rsi), %rax + mulq 104(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[14] * A[15] + movq 120(%rsi), %rax + mulq 112(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %r9 + adcq %r11, %rcx + adcq %r12, %r8 + movq %r9, 232(%rdi) + # A[7] * A[23] + movq 184(%rsi), %rax + mulq 56(%rsi) + xorq %r9, %r9 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[8] * A[22] + movq 176(%rsi), %rax + mulq 64(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[9] * A[21] + movq 168(%rsi), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[10] * A[20] + movq 160(%rsi), %rax + mulq 80(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[11] * A[19] + movq 152(%rsi), %rax + mulq 88(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[12] * A[18] + movq 144(%rsi), %rax + mulq 96(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[13] * A[17] + movq 136(%rsi), %rax + mulq 104(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[14] * A[16] + movq 128(%rsi), %rax + mulq 112(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[15] * A[15] + movq 120(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %rcx + adcq %r11, %r8 + adcq %r12, %r9 + movq %rcx, 240(%rdi) + # A[8] * A[23] + movq 184(%rsi), %rax + mulq 64(%rsi) + xorq %rcx, %rcx + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[9] * A[22] + movq 176(%rsi), %rax + mulq 72(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[10] * A[21] + movq 168(%rsi), %rax + mulq 80(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[11] * A[20] + movq 160(%rsi), %rax + mulq 88(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[12] * A[19] + movq 152(%rsi), %rax + mulq 96(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[13] * A[18] + movq 144(%rsi), %rax + mulq 104(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[14] * A[17] + movq 136(%rsi), %rax + mulq 112(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[15] * A[16] + movq 128(%rsi), %rax + mulq 120(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %r8 + adcq %r11, %r9 + adcq %r12, %rcx + movq %r8, 248(%rdi) + # A[9] * A[23] + movq 184(%rsi), %rax + mulq 72(%rsi) + xorq %r8, %r8 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[10] * A[22] + movq 176(%rsi), %rax + mulq 80(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[11] * A[21] + movq 168(%rsi), %rax + mulq 88(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[12] * A[20] + movq 160(%rsi), %rax + mulq 96(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[13] * A[19] + movq 152(%rsi), %rax + mulq 104(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[14] * A[18] + movq 144(%rsi), %rax + mulq 112(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[15] * A[17] + movq 136(%rsi), %rax + mulq 120(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[16] * A[16] + movq 128(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r9 + adcq %r11, %rcx + adcq %r12, %r8 + movq %r9, 256(%rdi) + # A[10] * A[23] + movq 184(%rsi), %rax + mulq 80(%rsi) + xorq %r9, %r9 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[11] * A[22] + movq 176(%rsi), %rax + mulq 88(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[12] * A[21] + movq 168(%rsi), %rax + mulq 96(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[13] * A[20] + movq 160(%rsi), %rax + mulq 104(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[14] * A[19] + movq 152(%rsi), %rax + mulq 112(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[15] * A[18] + movq 144(%rsi), %rax + mulq 120(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[16] * A[17] + movq 136(%rsi), %rax + mulq 128(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %rcx + adcq %r11, %r8 + adcq %r12, %r9 + movq %rcx, 264(%rdi) + # A[11] * A[23] + movq 184(%rsi), %rax + mulq 88(%rsi) + xorq %rcx, %rcx + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[12] * A[22] + movq 176(%rsi), %rax + mulq 96(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[13] * A[21] + movq 168(%rsi), %rax + mulq 104(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[14] * A[20] + movq 160(%rsi), %rax + mulq 112(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[15] * A[19] + movq 152(%rsi), %rax + mulq 120(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[16] * A[18] + movq 144(%rsi), %rax + mulq 128(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[17] * A[17] + movq 136(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r8 + adcq %r11, %r9 + adcq %r12, %rcx + movq %r8, 272(%rdi) + # A[12] * A[23] + movq 184(%rsi), %rax + mulq 96(%rsi) + xorq %r8, %r8 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[13] * A[22] + movq 176(%rsi), %rax + mulq 104(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[14] * A[21] + movq 168(%rsi), %rax + mulq 112(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[15] * A[20] + movq 160(%rsi), %rax + mulq 120(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[16] * A[19] + movq 152(%rsi), %rax + mulq 128(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[17] * A[18] + movq 144(%rsi), %rax + mulq 136(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %r9 + adcq %r11, %rcx + adcq %r12, %r8 + movq %r9, 280(%rdi) + # A[13] * A[23] + movq 184(%rsi), %rax + mulq 104(%rsi) + xorq %r9, %r9 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[14] * A[22] + movq 176(%rsi), %rax + mulq 112(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[15] * A[21] + movq 168(%rsi), %rax + mulq 120(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[16] * A[20] + movq 160(%rsi), %rax + mulq 128(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[17] * A[19] + movq 152(%rsi), %rax + mulq 136(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[18] * A[18] + movq 144(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %rcx + adcq %r11, %r8 + adcq %r12, %r9 + movq %rcx, 288(%rdi) + # A[14] * A[23] + movq 184(%rsi), %rax + mulq 112(%rsi) + xorq %rcx, %rcx + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[15] * A[22] + movq 176(%rsi), %rax + mulq 120(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[16] * A[21] + movq 168(%rsi), %rax + mulq 128(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[17] * A[20] + movq 160(%rsi), %rax + mulq 136(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[18] * A[19] + movq 152(%rsi), %rax + mulq 144(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %r8 + adcq %r11, %r9 + adcq %r12, %rcx + movq %r8, 296(%rdi) + # A[15] * A[23] + movq 184(%rsi), %rax + mulq 120(%rsi) + xorq %r8, %r8 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[16] * A[22] + movq 176(%rsi), %rax + mulq 128(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[17] * A[21] + movq 168(%rsi), %rax + mulq 136(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[18] * A[20] + movq 160(%rsi), %rax + mulq 144(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[19] * A[19] + movq 152(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r9 + adcq %r11, %rcx + adcq %r12, %r8 + movq %r9, 304(%rdi) + # A[16] * A[23] + movq 184(%rsi), %rax + mulq 128(%rsi) + xorq %r9, %r9 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[17] * A[22] + movq 176(%rsi), %rax + mulq 136(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[18] * A[21] + movq 168(%rsi), %rax + mulq 144(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[19] * A[20] + movq 160(%rsi), %rax + mulq 152(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %rcx + adcq %r11, %r8 + adcq %r12, %r9 + movq %rcx, 312(%rdi) + # A[17] * A[23] + movq 184(%rsi), %rax + mulq 136(%rsi) + xorq %rcx, %rcx + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[18] * A[22] + movq 176(%rsi), %rax + mulq 144(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[19] * A[21] + movq 168(%rsi), %rax + mulq 152(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[20] * A[20] + movq 160(%rsi), %rax + mulq %rax + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r8 + adcq %r11, %r9 + adcq %r12, %rcx + movq %r8, 320(%rdi) + # A[18] * A[23] + movq 184(%rsi), %rax + mulq 144(%rsi) + xorq %r8, %r8 + xorq %r12, %r12 + movq %rax, %r10 + movq %rdx, %r11 + # A[19] * A[22] + movq 176(%rsi), %rax + mulq 152(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[20] * A[21] + movq 168(%rsi), %rax + mulq 160(%rsi) + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + addq %r10, %r9 + adcq %r11, %rcx + adcq %r12, %r8 + movq %r9, 328(%rdi) + # A[19] * A[23] + movq 184(%rsi), %rax + mulq 152(%rsi) + xorq %r9, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + # A[20] * A[22] + movq 176(%rsi), %rax + mulq 160(%rsi) + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + # A[21] * A[21] + movq 168(%rsi), %rax + mulq %rax + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + movq %rcx, 336(%rdi) + # A[20] * A[23] + movq 184(%rsi), %rax + mulq 160(%rsi) + xorq %rcx, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + # A[21] * A[22] + movq 176(%rsi), %rax + mulq 168(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + movq %r8, 344(%rdi) + # A[21] * A[23] + movq 184(%rsi), %rax + mulq 168(%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0, %r8 + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0, %r8 + # A[22] * A[22] + movq 176(%rsi), %rax + mulq %rax + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0, %r8 + movq %r9, 352(%rdi) + # A[22] * A[23] + movq 184(%rsi), %rax + mulq 176(%rsi) + xorq %r9, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + movq %rcx, 360(%rdi) + # A[23] * A[23] + movq 184(%rsi), %rax + mulq %rax + addq %rax, %r8 + adcq %rdx, %r9 + movq %r8, 368(%rdi) + movq %r9, 376(%rdi) + movq (%rsp), %rax + movq 8(%rsp), %rdx + movq 16(%rsp), %r10 + movq 24(%rsp), %r11 + movq %rax, (%rdi) + movq %rdx, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 32(%rsp), %rax + movq 40(%rsp), %rdx + movq 48(%rsp), %r10 + movq 56(%rsp), %r11 + movq %rax, 32(%rdi) + movq %rdx, 40(%rdi) + movq %r10, 48(%rdi) + movq %r11, 56(%rdi) + movq 64(%rsp), %rax + movq 72(%rsp), %rdx + movq 80(%rsp), %r10 + movq 88(%rsp), %r11 + movq %rax, 64(%rdi) + movq %rdx, 72(%rdi) + movq %r10, 80(%rdi) + movq %r11, 88(%rdi) + movq 96(%rsp), %rax + movq 104(%rsp), %rdx + movq 112(%rsp), %r10 + movq 120(%rsp), %r11 + movq %rax, 96(%rdi) + movq %rdx, 104(%rdi) + movq %r10, 112(%rdi) + movq %r11, 120(%rdi) + movq 128(%rsp), %rax + movq 136(%rsp), %rdx + movq 144(%rsp), %r10 + movq 152(%rsp), %r11 + movq %rax, 128(%rdi) + movq %rdx, 136(%rdi) + movq %r10, 144(%rdi) + movq %r11, 152(%rdi) + movq 160(%rsp), %rax + movq 168(%rsp), %rdx + movq 176(%rsp), %r10 + movq 184(%rsp), %r11 + movq %rax, 160(%rdi) + movq %rdx, 168(%rdi) + movq %r10, 176(%rdi) + movq %r11, 184(%rdi) + addq $192, %rsp + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_3072_sqr_24,.-sp_3072_sqr_24 +#endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 +/* Multiply a and b into r. (r = a * b) + * + * r Result of multiplication. + * a First number to multiply. + * b Second number to multiply. + */ +#ifndef __APPLE__ +.globl sp_3072_mul_avx2_24 +.type sp_3072_mul_avx2_24,@function +.align 16 +sp_3072_mul_avx2_24: +#else +.globl _sp_3072_mul_avx2_24 +.p2align 4 +_sp_3072_mul_avx2_24: +#endif /* __APPLE__ */ + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + push %rbx + movq %rdx, %rbp + subq $192, %rsp + movq $0, %r14 + movq (%rsi), %rdx + # A[0] * B[0] + mulx (%rbp), %r8, %r9 + # A[0] * B[1] + mulx 8(%rbp), %rax, %r10 + movq %r8, (%rsp) + adcxq %rax, %r9 + # A[0] * B[2] + mulx 16(%rbp), %rax, %r11 + movq %r9, 8(%rsp) + adcxq %rax, %r10 + # A[0] * B[3] + mulx 24(%rbp), %rax, %r12 + movq %r10, 16(%rsp) + adcxq %rax, %r11 + movq %r11, 24(%rsp) + # A[0] * B[4] + mulx 32(%rbp), %rax, %r8 + adcxq %rax, %r12 + # A[0] * B[5] + mulx 40(%rbp), %rax, %r9 + movq %r12, 32(%rsp) + adcxq %rax, %r8 + # A[0] * B[6] + mulx 48(%rbp), %rax, %r10 + movq %r8, 40(%rsp) + adcxq %rax, %r9 + # A[0] * B[7] + mulx 56(%rbp), %rax, %r11 + movq %r9, 48(%rsp) + adcxq %rax, %r10 + movq %r10, 56(%rsp) + # A[0] * B[8] + mulx 64(%rbp), %rax, %r12 + adcxq %rax, %r11 + # A[0] * B[9] + mulx 72(%rbp), %rax, %r8 + movq %r11, 64(%rsp) + adcxq %rax, %r12 + # A[0] * B[10] + mulx 80(%rbp), %rax, %r9 + movq %r12, 72(%rsp) + adcxq %rax, %r8 + # A[0] * B[11] + mulx 88(%rbp), %rax, %r10 + movq %r8, 80(%rsp) + adcxq %rax, %r9 + movq %r9, 88(%rsp) + # A[0] * B[12] + mulx 96(%rbp), %rax, %r11 + adcxq %rax, %r10 + # A[0] * B[13] + mulx 104(%rbp), %rax, %r12 + movq %r10, 96(%rsp) + adcxq %rax, %r11 + # A[0] * B[14] + mulx 112(%rbp), %rax, %r8 + movq %r11, 104(%rsp) + adcxq %rax, %r12 + # A[0] * B[15] + mulx 120(%rbp), %rax, %r9 + movq %r12, 112(%rsp) + adcxq %rax, %r8 + movq %r8, 120(%rsp) + # A[0] * B[16] + mulx 128(%rbp), %rax, %r10 + adcxq %rax, %r9 + # A[0] * B[17] + mulx 136(%rbp), %rax, %r11 + movq %r9, 128(%rsp) + adcxq %rax, %r10 + # A[0] * B[18] + mulx 144(%rbp), %rax, %r12 + movq %r10, 136(%rsp) + adcxq %rax, %r11 + # A[0] * B[19] + mulx 152(%rbp), %rax, %r8 + movq %r11, 144(%rsp) + adcxq %rax, %r12 + movq %r12, 152(%rsp) + # A[0] * B[20] + mulx 160(%rbp), %rax, %r9 + adcxq %rax, %r8 + # A[0] * B[21] + mulx 168(%rbp), %rax, %r10 + movq %r8, 160(%rsp) + adcxq %rax, %r9 + # A[0] * B[22] + mulx 176(%rbp), %rax, %r11 + movq %r9, 168(%rsp) + adcxq %rax, %r10 + # A[0] * B[23] + mulx 184(%rbp), %rax, %r12 + movq %r10, %r15 + adcxq %rax, %r11 + adcxq %r14, %r12 + movq %r14, %r13 + adcxq %r14, %r13 + movq %r11, %rbx + movq %r12, 192(%rdi) + movq 8(%rsi), %rdx + movq 8(%rsp), %r9 + movq 16(%rsp), %r10 + movq 24(%rsp), %r11 + movq 32(%rsp), %r12 + movq 40(%rsp), %r8 + # A[1] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[1] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r9, 8(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[1] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r10, 16(%rsp) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[1] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r11, 24(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + movq %r12, 32(%rsp) + movq 48(%rsp), %r9 + movq 56(%rsp), %r10 + movq 64(%rsp), %r11 + movq 72(%rsp), %r12 + # A[1] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[1] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r8, 40(%rsp) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[1] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r9, 48(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[1] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r10, 56(%rsp) + adcxq %rax, %r11 + adoxq %rcx, %r12 + movq %r11, 64(%rsp) + movq 80(%rsp), %r8 + movq 88(%rsp), %r9 + movq 96(%rsp), %r10 + movq 104(%rsp), %r11 + # A[1] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[1] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r12, 72(%rsp) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[1] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r8, 80(%rsp) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[1] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r9, 88(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 96(%rsp) + movq 112(%rsp), %r12 + movq 120(%rsp), %r8 + movq 128(%rsp), %r9 + movq 136(%rsp), %r10 + # A[1] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[1] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r11, 104(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[1] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r12, 112(%rsp) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[1] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r8, 120(%rsp) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 128(%rsp) + movq 144(%rsp), %r11 + movq 152(%rsp), %r12 + movq 160(%rsp), %r8 + movq 168(%rsp), %r9 + # A[1] * B[16] + mulx 128(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[1] * B[17] + mulx 136(%rbp), %rax, %rcx + movq %r10, 136(%rsp) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[1] * B[18] + mulx 144(%rbp), %rax, %rcx + movq %r11, 144(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[1] * B[19] + mulx 152(%rbp), %rax, %rcx + movq %r12, 152(%rsp) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 160(%rsp) + movq %r15, %r10 + movq %rbx, %r11 + movq 192(%rdi), %r12 + # A[1] * B[20] + mulx 160(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[1] * B[21] + mulx 168(%rbp), %rax, %rcx + movq %r9, 168(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[1] * B[22] + mulx 176(%rbp), %rax, %rcx + movq %r10, %r15 + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[1] * B[23] + mulx 184(%rbp), %rax, %rcx + movq %r11, %rbx + movq %r14, %r8 + adcxq %rax, %r12 + adoxq %rcx, %r8 + adcxq %r13, %r8 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r12, 192(%rdi) + movq %r8, 200(%rdi) + movq 16(%rsi), %rdx + movq 16(%rsp), %r10 + movq 24(%rsp), %r11 + movq 32(%rsp), %r12 + movq 40(%rsp), %r8 + movq 48(%rsp), %r9 + # A[2] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[2] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r10, 16(%rsp) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[2] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r11, 24(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[2] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r12, 32(%rsp) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 40(%rsp) + movq 56(%rsp), %r10 + movq 64(%rsp), %r11 + movq 72(%rsp), %r12 + movq 80(%rsp), %r8 + # A[2] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[2] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r9, 48(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[2] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r10, 56(%rsp) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[2] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r11, 64(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + movq %r12, 72(%rsp) + movq 88(%rsp), %r9 + movq 96(%rsp), %r10 + movq 104(%rsp), %r11 + movq 112(%rsp), %r12 + # A[2] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[2] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r8, 80(%rsp) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[2] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r9, 88(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[2] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r10, 96(%rsp) + adcxq %rax, %r11 + adoxq %rcx, %r12 + movq %r11, 104(%rsp) + movq 120(%rsp), %r8 + movq 128(%rsp), %r9 + movq 136(%rsp), %r10 + movq 144(%rsp), %r11 + # A[2] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[2] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r12, 112(%rsp) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[2] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r8, 120(%rsp) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[2] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r9, 128(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 136(%rsp) + movq 152(%rsp), %r12 + movq 160(%rsp), %r8 + movq 168(%rsp), %r9 + movq %r15, %r10 + # A[2] * B[16] + mulx 128(%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[2] * B[17] + mulx 136(%rbp), %rax, %rcx + movq %r11, 144(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[2] * B[18] + mulx 144(%rbp), %rax, %rcx + movq %r12, 152(%rsp) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[2] * B[19] + mulx 152(%rbp), %rax, %rcx + movq %r8, 160(%rsp) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 168(%rsp) + movq %rbx, %r11 + movq 192(%rdi), %r12 + movq 200(%rdi), %r8 + # A[2] * B[20] + mulx 160(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[2] * B[21] + mulx 168(%rbp), %rax, %rcx + movq %r10, %r15 + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[2] * B[22] + mulx 176(%rbp), %rax, %rcx + movq %r11, %rbx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[2] * B[23] + mulx 184(%rbp), %rax, %rcx + movq %r12, 192(%rdi) + movq %r14, %r9 + adcxq %rax, %r8 + adoxq %rcx, %r9 + adcxq %r13, %r9 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r8, 200(%rdi) + movq %r9, 208(%rdi) + movq 24(%rsi), %rdx + movq 24(%rsp), %r11 + movq 32(%rsp), %r12 + movq 40(%rsp), %r8 + movq 48(%rsp), %r9 + movq 56(%rsp), %r10 + # A[3] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[3] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r11, 24(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[3] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r12, 32(%rsp) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[3] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r8, 40(%rsp) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 48(%rsp) + movq 64(%rsp), %r11 + movq 72(%rsp), %r12 + movq 80(%rsp), %r8 + movq 88(%rsp), %r9 + # A[3] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[3] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r10, 56(%rsp) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[3] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r11, 64(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[3] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r12, 72(%rsp) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 80(%rsp) + movq 96(%rsp), %r10 + movq 104(%rsp), %r11 + movq 112(%rsp), %r12 + movq 120(%rsp), %r8 + # A[3] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[3] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r9, 88(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[3] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r10, 96(%rsp) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[3] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r11, 104(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + movq %r12, 112(%rsp) + movq 128(%rsp), %r9 + movq 136(%rsp), %r10 + movq 144(%rsp), %r11 + movq 152(%rsp), %r12 + # A[3] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[3] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r8, 120(%rsp) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[3] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r9, 128(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[3] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r10, 136(%rsp) + adcxq %rax, %r11 + adoxq %rcx, %r12 + movq %r11, 144(%rsp) + movq 160(%rsp), %r8 + movq 168(%rsp), %r9 + movq %r15, %r10 + movq %rbx, %r11 + # A[3] * B[16] + mulx 128(%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[3] * B[17] + mulx 136(%rbp), %rax, %rcx + movq %r12, 152(%rsp) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[3] * B[18] + mulx 144(%rbp), %rax, %rcx + movq %r8, 160(%rsp) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[3] * B[19] + mulx 152(%rbp), %rax, %rcx + movq %r9, 168(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, %r15 + movq 192(%rdi), %r12 + movq 200(%rdi), %r8 + movq 208(%rdi), %r9 + # A[3] * B[20] + mulx 160(%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[3] * B[21] + mulx 168(%rbp), %rax, %rcx + movq %r11, %rbx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[3] * B[22] + mulx 176(%rbp), %rax, %rcx + movq %r12, 192(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[3] * B[23] + mulx 184(%rbp), %rax, %rcx + movq %r8, 200(%rdi) + movq %r14, %r10 + adcxq %rax, %r9 + adoxq %rcx, %r10 + adcxq %r13, %r10 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r9, 208(%rdi) + movq %r10, 216(%rdi) + movq 32(%rsi), %rdx + movq 32(%rsp), %r12 + movq 40(%rsp), %r8 + movq 48(%rsp), %r9 + movq 56(%rsp), %r10 + movq 64(%rsp), %r11 + # A[4] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[4] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r12, 32(%rsp) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[4] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r8, 40(%rsp) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[4] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r9, 48(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 56(%rsp) + movq 72(%rsp), %r12 + movq 80(%rsp), %r8 + movq 88(%rsp), %r9 + movq 96(%rsp), %r10 + # A[4] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[4] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r11, 64(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[4] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r12, 72(%rsp) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[4] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r8, 80(%rsp) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 88(%rsp) + movq 104(%rsp), %r11 + movq 112(%rsp), %r12 + movq 120(%rsp), %r8 + movq 128(%rsp), %r9 + # A[4] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[4] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r10, 96(%rsp) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[4] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r11, 104(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[4] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r12, 112(%rsp) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 120(%rsp) + movq 136(%rsp), %r10 + movq 144(%rsp), %r11 + movq 152(%rsp), %r12 + movq 160(%rsp), %r8 + # A[4] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[4] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r9, 128(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[4] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r10, 136(%rsp) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[4] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r11, 144(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + movq %r12, 152(%rsp) + movq 168(%rsp), %r9 + movq %r15, %r10 + movq %rbx, %r11 + movq 192(%rdi), %r12 + # A[4] * B[16] + mulx 128(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[4] * B[17] + mulx 136(%rbp), %rax, %rcx + movq %r8, 160(%rsp) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[4] * B[18] + mulx 144(%rbp), %rax, %rcx + movq %r9, 168(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[4] * B[19] + mulx 152(%rbp), %rax, %rcx + movq %r10, %r15 + adcxq %rax, %r11 + adoxq %rcx, %r12 + movq %r11, %rbx + movq 200(%rdi), %r8 + movq 208(%rdi), %r9 + movq 216(%rdi), %r10 + # A[4] * B[20] + mulx 160(%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[4] * B[21] + mulx 168(%rbp), %rax, %rcx + movq %r12, 192(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[4] * B[22] + mulx 176(%rbp), %rax, %rcx + movq %r8, 200(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[4] * B[23] + mulx 184(%rbp), %rax, %rcx + movq %r9, 208(%rdi) + movq %r14, %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + adcxq %r13, %r11 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r10, 216(%rdi) + movq %r11, 224(%rdi) + movq 40(%rsi), %rdx + movq 40(%rsp), %r8 + movq 48(%rsp), %r9 + movq 56(%rsp), %r10 + movq 64(%rsp), %r11 + movq 72(%rsp), %r12 + # A[5] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[5] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r8, 40(%rsp) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[5] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r9, 48(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[5] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r10, 56(%rsp) + adcxq %rax, %r11 + adoxq %rcx, %r12 + movq %r11, 64(%rsp) + movq 80(%rsp), %r8 + movq 88(%rsp), %r9 + movq 96(%rsp), %r10 + movq 104(%rsp), %r11 + # A[5] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[5] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r12, 72(%rsp) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[5] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r8, 80(%rsp) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[5] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r9, 88(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 96(%rsp) + movq 112(%rsp), %r12 + movq 120(%rsp), %r8 + movq 128(%rsp), %r9 + movq 136(%rsp), %r10 + # A[5] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[5] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r11, 104(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[5] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r12, 112(%rsp) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[5] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r8, 120(%rsp) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 128(%rsp) + movq 144(%rsp), %r11 + movq 152(%rsp), %r12 + movq 160(%rsp), %r8 + movq 168(%rsp), %r9 + # A[5] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[5] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r10, 136(%rsp) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[5] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r11, 144(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[5] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r12, 152(%rsp) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 160(%rsp) + movq %r15, %r10 + movq %rbx, %r11 + movq 192(%rdi), %r12 + movq 200(%rdi), %r8 + # A[5] * B[16] + mulx 128(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[5] * B[17] + mulx 136(%rbp), %rax, %rcx + movq %r9, 168(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[5] * B[18] + mulx 144(%rbp), %rax, %rcx + movq %r10, %r15 + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[5] * B[19] + mulx 152(%rbp), %rax, %rcx + movq %r11, %rbx + adcxq %rax, %r12 + adoxq %rcx, %r8 + movq %r12, 192(%rdi) + movq 208(%rdi), %r9 + movq 216(%rdi), %r10 + movq 224(%rdi), %r11 + # A[5] * B[20] + mulx 160(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[5] * B[21] + mulx 168(%rbp), %rax, %rcx + movq %r8, 200(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[5] * B[22] + mulx 176(%rbp), %rax, %rcx + movq %r9, 208(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[5] * B[23] + mulx 184(%rbp), %rax, %rcx + movq %r10, 216(%rdi) + movq %r14, %r12 + adcxq %rax, %r11 + adoxq %rcx, %r12 + adcxq %r13, %r12 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r11, 224(%rdi) + movq %r12, 232(%rdi) + movq 48(%rsi), %rdx + movq 48(%rsp), %r9 + movq 56(%rsp), %r10 + movq 64(%rsp), %r11 + movq 72(%rsp), %r12 + movq 80(%rsp), %r8 + # A[6] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[6] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r9, 48(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[6] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r10, 56(%rsp) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[6] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r11, 64(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + movq %r12, 72(%rsp) + movq 88(%rsp), %r9 + movq 96(%rsp), %r10 + movq 104(%rsp), %r11 + movq 112(%rsp), %r12 + # A[6] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[6] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r8, 80(%rsp) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[6] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r9, 88(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[6] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r10, 96(%rsp) + adcxq %rax, %r11 + adoxq %rcx, %r12 + movq %r11, 104(%rsp) + movq 120(%rsp), %r8 + movq 128(%rsp), %r9 + movq 136(%rsp), %r10 + movq 144(%rsp), %r11 + # A[6] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[6] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r12, 112(%rsp) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[6] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r8, 120(%rsp) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[6] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r9, 128(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 136(%rsp) + movq 152(%rsp), %r12 + movq 160(%rsp), %r8 + movq 168(%rsp), %r9 + movq %r15, %r10 + # A[6] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[6] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r11, 144(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[6] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r12, 152(%rsp) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[6] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r8, 160(%rsp) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 168(%rsp) + movq %rbx, %r11 + movq 192(%rdi), %r12 + movq 200(%rdi), %r8 + movq 208(%rdi), %r9 + # A[6] * B[16] + mulx 128(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[6] * B[17] + mulx 136(%rbp), %rax, %rcx + movq %r10, %r15 + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[6] * B[18] + mulx 144(%rbp), %rax, %rcx + movq %r11, %rbx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[6] * B[19] + mulx 152(%rbp), %rax, %rcx + movq %r12, 192(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 200(%rdi) + movq 216(%rdi), %r10 + movq 224(%rdi), %r11 + movq 232(%rdi), %r12 + # A[6] * B[20] + mulx 160(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[6] * B[21] + mulx 168(%rbp), %rax, %rcx + movq %r9, 208(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[6] * B[22] + mulx 176(%rbp), %rax, %rcx + movq %r10, 216(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[6] * B[23] + mulx 184(%rbp), %rax, %rcx + movq %r11, 224(%rdi) + movq %r14, %r8 + adcxq %rax, %r12 + adoxq %rcx, %r8 + adcxq %r13, %r8 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r12, 232(%rdi) + movq %r8, 240(%rdi) + movq 56(%rsi), %rdx + movq 56(%rsp), %r10 + movq 64(%rsp), %r11 + movq 72(%rsp), %r12 + movq 80(%rsp), %r8 + movq 88(%rsp), %r9 + # A[7] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[7] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r10, 56(%rsp) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[7] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r11, 64(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[7] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r12, 72(%rsp) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 80(%rsp) + movq 96(%rsp), %r10 + movq 104(%rsp), %r11 + movq 112(%rsp), %r12 + movq 120(%rsp), %r8 + # A[7] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[7] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r9, 88(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[7] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r10, 96(%rsp) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[7] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r11, 104(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + movq %r12, 112(%rsp) + movq 128(%rsp), %r9 + movq 136(%rsp), %r10 + movq 144(%rsp), %r11 + movq 152(%rsp), %r12 + # A[7] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[7] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r8, 120(%rsp) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[7] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r9, 128(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[7] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r10, 136(%rsp) + adcxq %rax, %r11 + adoxq %rcx, %r12 + movq %r11, 144(%rsp) + movq 160(%rsp), %r8 + movq 168(%rsp), %r9 + movq %r15, %r10 + movq %rbx, %r11 + # A[7] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[7] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r12, 152(%rsp) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[7] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r8, 160(%rsp) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[7] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r9, 168(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, %r15 + movq 192(%rdi), %r12 + movq 200(%rdi), %r8 + movq 208(%rdi), %r9 + movq 216(%rdi), %r10 + # A[7] * B[16] + mulx 128(%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[7] * B[17] + mulx 136(%rbp), %rax, %rcx + movq %r11, %rbx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[7] * B[18] + mulx 144(%rbp), %rax, %rcx + movq %r12, 192(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[7] * B[19] + mulx 152(%rbp), %rax, %rcx + movq %r8, 200(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 208(%rdi) + movq 224(%rdi), %r11 + movq 232(%rdi), %r12 + movq 240(%rdi), %r8 + # A[7] * B[20] + mulx 160(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[7] * B[21] + mulx 168(%rbp), %rax, %rcx + movq %r10, 216(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[7] * B[22] + mulx 176(%rbp), %rax, %rcx + movq %r11, 224(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[7] * B[23] + mulx 184(%rbp), %rax, %rcx + movq %r12, 232(%rdi) + movq %r14, %r9 + adcxq %rax, %r8 + adoxq %rcx, %r9 + adcxq %r13, %r9 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r8, 240(%rdi) + movq %r9, 248(%rdi) + movq 64(%rsi), %rdx + movq 64(%rsp), %r11 + movq 72(%rsp), %r12 + movq 80(%rsp), %r8 + movq 88(%rsp), %r9 + movq 96(%rsp), %r10 + # A[8] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[8] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r11, 64(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[8] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r12, 72(%rsp) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[8] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r8, 80(%rsp) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 88(%rsp) + movq 104(%rsp), %r11 + movq 112(%rsp), %r12 + movq 120(%rsp), %r8 + movq 128(%rsp), %r9 + # A[8] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[8] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r10, 96(%rsp) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[8] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r11, 104(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[8] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r12, 112(%rsp) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 120(%rsp) + movq 136(%rsp), %r10 + movq 144(%rsp), %r11 + movq 152(%rsp), %r12 + movq 160(%rsp), %r8 + # A[8] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[8] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r9, 128(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[8] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r10, 136(%rsp) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[8] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r11, 144(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + movq %r12, 152(%rsp) + movq 168(%rsp), %r9 + movq %r15, %r10 + movq %rbx, %r11 + movq 192(%rdi), %r12 + # A[8] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[8] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r8, 160(%rsp) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[8] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r9, 168(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[8] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r10, %r15 + adcxq %rax, %r11 + adoxq %rcx, %r12 + movq %r11, %rbx + movq 200(%rdi), %r8 + movq 208(%rdi), %r9 + movq 216(%rdi), %r10 + movq 224(%rdi), %r11 + # A[8] * B[16] + mulx 128(%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[8] * B[17] + mulx 136(%rbp), %rax, %rcx + movq %r12, 192(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[8] * B[18] + mulx 144(%rbp), %rax, %rcx + movq %r8, 200(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[8] * B[19] + mulx 152(%rbp), %rax, %rcx + movq %r9, 208(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 216(%rdi) + movq 232(%rdi), %r12 + movq 240(%rdi), %r8 + movq 248(%rdi), %r9 + # A[8] * B[20] + mulx 160(%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[8] * B[21] + mulx 168(%rbp), %rax, %rcx + movq %r11, 224(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[8] * B[22] + mulx 176(%rbp), %rax, %rcx + movq %r12, 232(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[8] * B[23] + mulx 184(%rbp), %rax, %rcx + movq %r8, 240(%rdi) + movq %r14, %r10 + adcxq %rax, %r9 + adoxq %rcx, %r10 + adcxq %r13, %r10 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r9, 248(%rdi) + movq %r10, 256(%rdi) + movq 72(%rsi), %rdx + movq 72(%rsp), %r12 + movq 80(%rsp), %r8 + movq 88(%rsp), %r9 + movq 96(%rsp), %r10 + movq 104(%rsp), %r11 + # A[9] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[9] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r12, 72(%rsp) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[9] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r8, 80(%rsp) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[9] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r9, 88(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 96(%rsp) + movq 112(%rsp), %r12 + movq 120(%rsp), %r8 + movq 128(%rsp), %r9 + movq 136(%rsp), %r10 + # A[9] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[9] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r11, 104(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[9] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r12, 112(%rsp) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[9] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r8, 120(%rsp) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 128(%rsp) + movq 144(%rsp), %r11 + movq 152(%rsp), %r12 + movq 160(%rsp), %r8 + movq 168(%rsp), %r9 + # A[9] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[9] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r10, 136(%rsp) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[9] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r11, 144(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[9] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r12, 152(%rsp) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 160(%rsp) + movq %r15, %r10 + movq %rbx, %r11 + movq 192(%rdi), %r12 + movq 200(%rdi), %r8 + # A[9] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[9] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r9, 168(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[9] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r10, %r15 + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[9] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r11, %rbx + adcxq %rax, %r12 + adoxq %rcx, %r8 + movq %r12, 192(%rdi) + movq 208(%rdi), %r9 + movq 216(%rdi), %r10 + movq 224(%rdi), %r11 + movq 232(%rdi), %r12 + # A[9] * B[16] + mulx 128(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[9] * B[17] + mulx 136(%rbp), %rax, %rcx + movq %r8, 200(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[9] * B[18] + mulx 144(%rbp), %rax, %rcx + movq %r9, 208(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[9] * B[19] + mulx 152(%rbp), %rax, %rcx + movq %r10, 216(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + movq %r11, 224(%rdi) + movq 240(%rdi), %r8 + movq 248(%rdi), %r9 + movq 256(%rdi), %r10 + # A[9] * B[20] + mulx 160(%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[9] * B[21] + mulx 168(%rbp), %rax, %rcx + movq %r12, 232(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[9] * B[22] + mulx 176(%rbp), %rax, %rcx + movq %r8, 240(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[9] * B[23] + mulx 184(%rbp), %rax, %rcx + movq %r9, 248(%rdi) + movq %r14, %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + adcxq %r13, %r11 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r10, 256(%rdi) + movq %r11, 264(%rdi) + movq 80(%rsi), %rdx + movq 80(%rsp), %r8 + movq 88(%rsp), %r9 + movq 96(%rsp), %r10 + movq 104(%rsp), %r11 + movq 112(%rsp), %r12 + # A[10] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[10] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r8, 80(%rsp) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[10] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r9, 88(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[10] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r10, 96(%rsp) + adcxq %rax, %r11 + adoxq %rcx, %r12 + movq %r11, 104(%rsp) + movq 120(%rsp), %r8 + movq 128(%rsp), %r9 + movq 136(%rsp), %r10 + movq 144(%rsp), %r11 + # A[10] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[10] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r12, 112(%rsp) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[10] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r8, 120(%rsp) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[10] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r9, 128(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 136(%rsp) + movq 152(%rsp), %r12 + movq 160(%rsp), %r8 + movq 168(%rsp), %r9 + movq %r15, %r10 + # A[10] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[10] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r11, 144(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[10] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r12, 152(%rsp) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[10] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r8, 160(%rsp) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 168(%rsp) + movq %rbx, %r11 + movq 192(%rdi), %r12 + movq 200(%rdi), %r8 + movq 208(%rdi), %r9 + # A[10] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[10] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r10, %r15 + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[10] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r11, %rbx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[10] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r12, 192(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 200(%rdi) + movq 216(%rdi), %r10 + movq 224(%rdi), %r11 + movq 232(%rdi), %r12 + movq 240(%rdi), %r8 + # A[10] * B[16] + mulx 128(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[10] * B[17] + mulx 136(%rbp), %rax, %rcx + movq %r9, 208(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[10] * B[18] + mulx 144(%rbp), %rax, %rcx + movq %r10, 216(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[10] * B[19] + mulx 152(%rbp), %rax, %rcx + movq %r11, 224(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + movq %r12, 232(%rdi) + movq 248(%rdi), %r9 + movq 256(%rdi), %r10 + movq 264(%rdi), %r11 + # A[10] * B[20] + mulx 160(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[10] * B[21] + mulx 168(%rbp), %rax, %rcx + movq %r8, 240(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[10] * B[22] + mulx 176(%rbp), %rax, %rcx + movq %r9, 248(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[10] * B[23] + mulx 184(%rbp), %rax, %rcx + movq %r10, 256(%rdi) + movq %r14, %r12 + adcxq %rax, %r11 + adoxq %rcx, %r12 + adcxq %r13, %r12 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r11, 264(%rdi) + movq %r12, 272(%rdi) + movq 88(%rsi), %rdx + movq 88(%rsp), %r9 + movq 96(%rsp), %r10 + movq 104(%rsp), %r11 + movq 112(%rsp), %r12 + movq 120(%rsp), %r8 + # A[11] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[11] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r9, 88(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[11] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r10, 96(%rsp) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[11] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r11, 104(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + movq %r12, 112(%rsp) + movq 128(%rsp), %r9 + movq 136(%rsp), %r10 + movq 144(%rsp), %r11 + movq 152(%rsp), %r12 + # A[11] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[11] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r8, 120(%rsp) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[11] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r9, 128(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[11] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r10, 136(%rsp) + adcxq %rax, %r11 + adoxq %rcx, %r12 + movq %r11, 144(%rsp) + movq 160(%rsp), %r8 + movq 168(%rsp), %r9 + movq %r15, %r10 + movq %rbx, %r11 + # A[11] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[11] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r12, 152(%rsp) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[11] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r8, 160(%rsp) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[11] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r9, 168(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, %r15 + movq 192(%rdi), %r12 + movq 200(%rdi), %r8 + movq 208(%rdi), %r9 + movq 216(%rdi), %r10 + # A[11] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[11] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r11, %rbx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[11] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r12, 192(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[11] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r8, 200(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 208(%rdi) + movq 224(%rdi), %r11 + movq 232(%rdi), %r12 + movq 240(%rdi), %r8 + movq 248(%rdi), %r9 + # A[11] * B[16] + mulx 128(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[11] * B[17] + mulx 136(%rbp), %rax, %rcx + movq %r10, 216(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[11] * B[18] + mulx 144(%rbp), %rax, %rcx + movq %r11, 224(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[11] * B[19] + mulx 152(%rbp), %rax, %rcx + movq %r12, 232(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 240(%rdi) + movq 256(%rdi), %r10 + movq 264(%rdi), %r11 + movq 272(%rdi), %r12 + # A[11] * B[20] + mulx 160(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[11] * B[21] + mulx 168(%rbp), %rax, %rcx + movq %r9, 248(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[11] * B[22] + mulx 176(%rbp), %rax, %rcx + movq %r10, 256(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[11] * B[23] + mulx 184(%rbp), %rax, %rcx + movq %r11, 264(%rdi) + movq %r14, %r8 + adcxq %rax, %r12 + adoxq %rcx, %r8 + adcxq %r13, %r8 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r12, 272(%rdi) + movq %r8, 280(%rdi) + movq 96(%rsi), %rdx + movq 96(%rsp), %r10 + movq 104(%rsp), %r11 + movq 112(%rsp), %r12 + movq 120(%rsp), %r8 + movq 128(%rsp), %r9 + # A[12] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[12] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r10, 96(%rsp) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[12] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r11, 104(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[12] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r12, 112(%rsp) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 120(%rsp) + movq 136(%rsp), %r10 + movq 144(%rsp), %r11 + movq 152(%rsp), %r12 + movq 160(%rsp), %r8 + # A[12] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[12] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r9, 128(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[12] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r10, 136(%rsp) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[12] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r11, 144(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + movq %r12, 152(%rsp) + movq 168(%rsp), %r9 + movq %r15, %r10 + movq %rbx, %r11 + movq 192(%rdi), %r12 + # A[12] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[12] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r8, 160(%rsp) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[12] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r9, 168(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[12] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r10, %r15 + adcxq %rax, %r11 + adoxq %rcx, %r12 + movq %r11, %rbx + movq 200(%rdi), %r8 + movq 208(%rdi), %r9 + movq 216(%rdi), %r10 + movq 224(%rdi), %r11 + # A[12] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[12] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r12, 192(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[12] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r8, 200(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[12] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r9, 208(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 216(%rdi) + movq 232(%rdi), %r12 + movq 240(%rdi), %r8 + movq 248(%rdi), %r9 + movq 256(%rdi), %r10 + # A[12] * B[16] + mulx 128(%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[12] * B[17] + mulx 136(%rbp), %rax, %rcx + movq %r11, 224(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[12] * B[18] + mulx 144(%rbp), %rax, %rcx + movq %r12, 232(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[12] * B[19] + mulx 152(%rbp), %rax, %rcx + movq %r8, 240(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 248(%rdi) + movq 264(%rdi), %r11 + movq 272(%rdi), %r12 + movq 280(%rdi), %r8 + # A[12] * B[20] + mulx 160(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[12] * B[21] + mulx 168(%rbp), %rax, %rcx + movq %r10, 256(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[12] * B[22] + mulx 176(%rbp), %rax, %rcx + movq %r11, 264(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[12] * B[23] + mulx 184(%rbp), %rax, %rcx + movq %r12, 272(%rdi) + movq %r14, %r9 + adcxq %rax, %r8 + adoxq %rcx, %r9 + adcxq %r13, %r9 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r8, 280(%rdi) + movq %r9, 288(%rdi) + movq 104(%rsi), %rdx + movq 104(%rsp), %r11 + movq 112(%rsp), %r12 + movq 120(%rsp), %r8 + movq 128(%rsp), %r9 + movq 136(%rsp), %r10 + # A[13] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[13] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r11, 104(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[13] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r12, 112(%rsp) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[13] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r8, 120(%rsp) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 128(%rsp) + movq 144(%rsp), %r11 + movq 152(%rsp), %r12 + movq 160(%rsp), %r8 + movq 168(%rsp), %r9 + # A[13] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[13] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r10, 136(%rsp) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[13] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r11, 144(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[13] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r12, 152(%rsp) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 160(%rsp) + movq %r15, %r10 + movq %rbx, %r11 + movq 192(%rdi), %r12 + movq 200(%rdi), %r8 + # A[13] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[13] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r9, 168(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[13] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r10, %r15 + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[13] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r11, %rbx + adcxq %rax, %r12 + adoxq %rcx, %r8 + movq %r12, 192(%rdi) + movq 208(%rdi), %r9 + movq 216(%rdi), %r10 + movq 224(%rdi), %r11 + movq 232(%rdi), %r12 + # A[13] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[13] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r8, 200(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[13] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r9, 208(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[13] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r10, 216(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + movq %r11, 224(%rdi) + movq 240(%rdi), %r8 + movq 248(%rdi), %r9 + movq 256(%rdi), %r10 + movq 264(%rdi), %r11 + # A[13] * B[16] + mulx 128(%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[13] * B[17] + mulx 136(%rbp), %rax, %rcx + movq %r12, 232(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[13] * B[18] + mulx 144(%rbp), %rax, %rcx + movq %r8, 240(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[13] * B[19] + mulx 152(%rbp), %rax, %rcx + movq %r9, 248(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 256(%rdi) + movq 272(%rdi), %r12 + movq 280(%rdi), %r8 + movq 288(%rdi), %r9 + # A[13] * B[20] + mulx 160(%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[13] * B[21] + mulx 168(%rbp), %rax, %rcx + movq %r11, 264(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[13] * B[22] + mulx 176(%rbp), %rax, %rcx + movq %r12, 272(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[13] * B[23] + mulx 184(%rbp), %rax, %rcx + movq %r8, 280(%rdi) + movq %r14, %r10 + adcxq %rax, %r9 + adoxq %rcx, %r10 + adcxq %r13, %r10 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r9, 288(%rdi) + movq %r10, 296(%rdi) + movq 112(%rsi), %rdx + movq 112(%rsp), %r12 + movq 120(%rsp), %r8 + movq 128(%rsp), %r9 + movq 136(%rsp), %r10 + movq 144(%rsp), %r11 + # A[14] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[14] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r12, 112(%rsp) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[14] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r8, 120(%rsp) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[14] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r9, 128(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 136(%rsp) + movq 152(%rsp), %r12 + movq 160(%rsp), %r8 + movq 168(%rsp), %r9 + movq %r15, %r10 + # A[14] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[14] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r11, 144(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[14] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r12, 152(%rsp) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[14] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r8, 160(%rsp) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 168(%rsp) + movq %rbx, %r11 + movq 192(%rdi), %r12 + movq 200(%rdi), %r8 + movq 208(%rdi), %r9 + # A[14] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[14] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r10, %r15 + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[14] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r11, %rbx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[14] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r12, 192(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 200(%rdi) + movq 216(%rdi), %r10 + movq 224(%rdi), %r11 + movq 232(%rdi), %r12 + movq 240(%rdi), %r8 + # A[14] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[14] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r9, 208(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[14] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r10, 216(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[14] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r11, 224(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + movq %r12, 232(%rdi) + movq 248(%rdi), %r9 + movq 256(%rdi), %r10 + movq 264(%rdi), %r11 + movq 272(%rdi), %r12 + # A[14] * B[16] + mulx 128(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[14] * B[17] + mulx 136(%rbp), %rax, %rcx + movq %r8, 240(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[14] * B[18] + mulx 144(%rbp), %rax, %rcx + movq %r9, 248(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[14] * B[19] + mulx 152(%rbp), %rax, %rcx + movq %r10, 256(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + movq %r11, 264(%rdi) + movq 280(%rdi), %r8 + movq 288(%rdi), %r9 + movq 296(%rdi), %r10 + # A[14] * B[20] + mulx 160(%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[14] * B[21] + mulx 168(%rbp), %rax, %rcx + movq %r12, 272(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[14] * B[22] + mulx 176(%rbp), %rax, %rcx + movq %r8, 280(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[14] * B[23] + mulx 184(%rbp), %rax, %rcx + movq %r9, 288(%rdi) + movq %r14, %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + adcxq %r13, %r11 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r10, 296(%rdi) + movq %r11, 304(%rdi) + movq 120(%rsi), %rdx + movq 120(%rsp), %r8 + movq 128(%rsp), %r9 + movq 136(%rsp), %r10 + movq 144(%rsp), %r11 + movq 152(%rsp), %r12 + # A[15] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[15] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r8, 120(%rsp) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[15] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r9, 128(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[15] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r10, 136(%rsp) + adcxq %rax, %r11 + adoxq %rcx, %r12 + movq %r11, 144(%rsp) + movq 160(%rsp), %r8 + movq 168(%rsp), %r9 + movq %r15, %r10 + movq %rbx, %r11 + # A[15] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[15] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r12, 152(%rsp) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[15] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r8, 160(%rsp) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[15] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r9, 168(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, %r15 + movq 192(%rdi), %r12 + movq 200(%rdi), %r8 + movq 208(%rdi), %r9 + movq 216(%rdi), %r10 + # A[15] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[15] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r11, %rbx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[15] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r12, 192(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[15] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r8, 200(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 208(%rdi) + movq 224(%rdi), %r11 + movq 232(%rdi), %r12 + movq 240(%rdi), %r8 + movq 248(%rdi), %r9 + # A[15] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[15] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r10, 216(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[15] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r11, 224(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[15] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r12, 232(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 240(%rdi) + movq 256(%rdi), %r10 + movq 264(%rdi), %r11 + movq 272(%rdi), %r12 + movq 280(%rdi), %r8 + # A[15] * B[16] + mulx 128(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[15] * B[17] + mulx 136(%rbp), %rax, %rcx + movq %r9, 248(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[15] * B[18] + mulx 144(%rbp), %rax, %rcx + movq %r10, 256(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[15] * B[19] + mulx 152(%rbp), %rax, %rcx + movq %r11, 264(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + movq %r12, 272(%rdi) + movq 288(%rdi), %r9 + movq 296(%rdi), %r10 + movq 304(%rdi), %r11 + # A[15] * B[20] + mulx 160(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[15] * B[21] + mulx 168(%rbp), %rax, %rcx + movq %r8, 280(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[15] * B[22] + mulx 176(%rbp), %rax, %rcx + movq %r9, 288(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[15] * B[23] + mulx 184(%rbp), %rax, %rcx + movq %r10, 296(%rdi) + movq %r14, %r12 + adcxq %rax, %r11 + adoxq %rcx, %r12 + adcxq %r13, %r12 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r11, 304(%rdi) + movq %r12, 312(%rdi) + movq 128(%rsi), %rdx + movq 128(%rsp), %r9 + movq 136(%rsp), %r10 + movq 144(%rsp), %r11 + movq 152(%rsp), %r12 + movq 160(%rsp), %r8 + # A[16] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[16] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r9, 128(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[16] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r10, 136(%rsp) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[16] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r11, 144(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + movq %r12, 152(%rsp) + movq 168(%rsp), %r9 + movq %r15, %r10 + movq %rbx, %r11 + movq 192(%rdi), %r12 + # A[16] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[16] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r8, 160(%rsp) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[16] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r9, 168(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[16] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r10, %r15 + adcxq %rax, %r11 + adoxq %rcx, %r12 + movq %r11, %rbx + movq 200(%rdi), %r8 + movq 208(%rdi), %r9 + movq 216(%rdi), %r10 + movq 224(%rdi), %r11 + # A[16] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[16] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r12, 192(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[16] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r8, 200(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[16] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r9, 208(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 216(%rdi) + movq 232(%rdi), %r12 + movq 240(%rdi), %r8 + movq 248(%rdi), %r9 + movq 256(%rdi), %r10 + # A[16] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[16] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r11, 224(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[16] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r12, 232(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[16] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r8, 240(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 248(%rdi) + movq 264(%rdi), %r11 + movq 272(%rdi), %r12 + movq 280(%rdi), %r8 + movq 288(%rdi), %r9 + # A[16] * B[16] + mulx 128(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[16] * B[17] + mulx 136(%rbp), %rax, %rcx + movq %r10, 256(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[16] * B[18] + mulx 144(%rbp), %rax, %rcx + movq %r11, 264(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[16] * B[19] + mulx 152(%rbp), %rax, %rcx + movq %r12, 272(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 280(%rdi) + movq 296(%rdi), %r10 + movq 304(%rdi), %r11 + movq 312(%rdi), %r12 + # A[16] * B[20] + mulx 160(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[16] * B[21] + mulx 168(%rbp), %rax, %rcx + movq %r9, 288(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[16] * B[22] + mulx 176(%rbp), %rax, %rcx + movq %r10, 296(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[16] * B[23] + mulx 184(%rbp), %rax, %rcx + movq %r11, 304(%rdi) + movq %r14, %r8 + adcxq %rax, %r12 + adoxq %rcx, %r8 + adcxq %r13, %r8 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r12, 312(%rdi) + movq %r8, 320(%rdi) + movq 136(%rsi), %rdx + movq 136(%rsp), %r10 + movq 144(%rsp), %r11 + movq 152(%rsp), %r12 + movq 160(%rsp), %r8 + movq 168(%rsp), %r9 + # A[17] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[17] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r10, 136(%rsp) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[17] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r11, 144(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[17] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r12, 152(%rsp) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 160(%rsp) + movq %r15, %r10 + movq %rbx, %r11 + movq 192(%rdi), %r12 + movq 200(%rdi), %r8 + # A[17] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[17] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r9, 168(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[17] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r10, %r15 + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[17] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r11, %rbx + adcxq %rax, %r12 + adoxq %rcx, %r8 + movq %r12, 192(%rdi) + movq 208(%rdi), %r9 + movq 216(%rdi), %r10 + movq 224(%rdi), %r11 + movq 232(%rdi), %r12 + # A[17] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[17] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r8, 200(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[17] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r9, 208(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[17] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r10, 216(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + movq %r11, 224(%rdi) + movq 240(%rdi), %r8 + movq 248(%rdi), %r9 + movq 256(%rdi), %r10 + movq 264(%rdi), %r11 + # A[17] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[17] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r12, 232(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[17] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r8, 240(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[17] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r9, 248(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 256(%rdi) + movq 272(%rdi), %r12 + movq 280(%rdi), %r8 + movq 288(%rdi), %r9 + movq 296(%rdi), %r10 + # A[17] * B[16] + mulx 128(%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[17] * B[17] + mulx 136(%rbp), %rax, %rcx + movq %r11, 264(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[17] * B[18] + mulx 144(%rbp), %rax, %rcx + movq %r12, 272(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[17] * B[19] + mulx 152(%rbp), %rax, %rcx + movq %r8, 280(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 288(%rdi) + movq 304(%rdi), %r11 + movq 312(%rdi), %r12 + movq 320(%rdi), %r8 + # A[17] * B[20] + mulx 160(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[17] * B[21] + mulx 168(%rbp), %rax, %rcx + movq %r10, 296(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[17] * B[22] + mulx 176(%rbp), %rax, %rcx + movq %r11, 304(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[17] * B[23] + mulx 184(%rbp), %rax, %rcx + movq %r12, 312(%rdi) + movq %r14, %r9 + adcxq %rax, %r8 + adoxq %rcx, %r9 + adcxq %r13, %r9 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r8, 320(%rdi) + movq %r9, 328(%rdi) + movq 144(%rsi), %rdx + movq 144(%rsp), %r11 + movq 152(%rsp), %r12 + movq 160(%rsp), %r8 + movq 168(%rsp), %r9 + movq %r15, %r10 + # A[18] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[18] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r11, 144(%rsp) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[18] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r12, 152(%rsp) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[18] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r8, 160(%rsp) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 168(%rsp) + movq %rbx, %r11 + movq 192(%rdi), %r12 + movq 200(%rdi), %r8 + movq 208(%rdi), %r9 + # A[18] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[18] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r10, %r15 + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[18] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r11, %rbx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[18] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r12, 192(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 200(%rdi) + movq 216(%rdi), %r10 + movq 224(%rdi), %r11 + movq 232(%rdi), %r12 + movq 240(%rdi), %r8 + # A[18] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[18] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r9, 208(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[18] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r10, 216(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[18] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r11, 224(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + movq %r12, 232(%rdi) + movq 248(%rdi), %r9 + movq 256(%rdi), %r10 + movq 264(%rdi), %r11 + movq 272(%rdi), %r12 + # A[18] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[18] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r8, 240(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[18] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r9, 248(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[18] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r10, 256(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + movq %r11, 264(%rdi) + movq 280(%rdi), %r8 + movq 288(%rdi), %r9 + movq 296(%rdi), %r10 + movq 304(%rdi), %r11 + # A[18] * B[16] + mulx 128(%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[18] * B[17] + mulx 136(%rbp), %rax, %rcx + movq %r12, 272(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[18] * B[18] + mulx 144(%rbp), %rax, %rcx + movq %r8, 280(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[18] * B[19] + mulx 152(%rbp), %rax, %rcx + movq %r9, 288(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 296(%rdi) + movq 312(%rdi), %r12 + movq 320(%rdi), %r8 + movq 328(%rdi), %r9 + # A[18] * B[20] + mulx 160(%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[18] * B[21] + mulx 168(%rbp), %rax, %rcx + movq %r11, 304(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[18] * B[22] + mulx 176(%rbp), %rax, %rcx + movq %r12, 312(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[18] * B[23] + mulx 184(%rbp), %rax, %rcx + movq %r8, 320(%rdi) + movq %r14, %r10 + adcxq %rax, %r9 + adoxq %rcx, %r10 + adcxq %r13, %r10 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r9, 328(%rdi) + movq %r10, 336(%rdi) + movq 152(%rsi), %rdx + movq 152(%rsp), %r12 + movq 160(%rsp), %r8 + movq 168(%rsp), %r9 + movq %r15, %r10 + movq %rbx, %r11 + # A[19] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[19] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r12, 152(%rsp) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[19] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r8, 160(%rsp) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[19] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r9, 168(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, %r15 + movq 192(%rdi), %r12 + movq 200(%rdi), %r8 + movq 208(%rdi), %r9 + movq 216(%rdi), %r10 + # A[19] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[19] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r11, %rbx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[19] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r12, 192(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[19] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r8, 200(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 208(%rdi) + movq 224(%rdi), %r11 + movq 232(%rdi), %r12 + movq 240(%rdi), %r8 + movq 248(%rdi), %r9 + # A[19] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[19] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r10, 216(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[19] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r11, 224(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[19] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r12, 232(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 240(%rdi) + movq 256(%rdi), %r10 + movq 264(%rdi), %r11 + movq 272(%rdi), %r12 + movq 280(%rdi), %r8 + # A[19] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[19] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r9, 248(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[19] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r10, 256(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[19] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r11, 264(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + movq %r12, 272(%rdi) + movq 288(%rdi), %r9 + movq 296(%rdi), %r10 + movq 304(%rdi), %r11 + movq 312(%rdi), %r12 + # A[19] * B[16] + mulx 128(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[19] * B[17] + mulx 136(%rbp), %rax, %rcx + movq %r8, 280(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[19] * B[18] + mulx 144(%rbp), %rax, %rcx + movq %r9, 288(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[19] * B[19] + mulx 152(%rbp), %rax, %rcx + movq %r10, 296(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + movq %r11, 304(%rdi) + movq 320(%rdi), %r8 + movq 328(%rdi), %r9 + movq 336(%rdi), %r10 + # A[19] * B[20] + mulx 160(%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[19] * B[21] + mulx 168(%rbp), %rax, %rcx + movq %r12, 312(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[19] * B[22] + mulx 176(%rbp), %rax, %rcx + movq %r8, 320(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[19] * B[23] + mulx 184(%rbp), %rax, %rcx + movq %r9, 328(%rdi) + movq %r14, %r11 + adcxq %rax, %r10 + adoxq %rcx, %r11 + adcxq %r13, %r11 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r10, 336(%rdi) + movq %r11, 344(%rdi) + movq 160(%rsi), %rdx + movq 160(%rsp), %r8 + movq 168(%rsp), %r9 + movq %r15, %r10 + movq %rbx, %r11 + movq 192(%rdi), %r12 + # A[20] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[20] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r8, 160(%rsp) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[20] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r9, 168(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[20] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r10, %r15 + adcxq %rax, %r11 + adoxq %rcx, %r12 + movq %r11, %rbx + movq 200(%rdi), %r8 + movq 208(%rdi), %r9 + movq 216(%rdi), %r10 + movq 224(%rdi), %r11 + # A[20] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[20] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r12, 192(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[20] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r8, 200(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[20] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r9, 208(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 216(%rdi) + movq 232(%rdi), %r12 + movq 240(%rdi), %r8 + movq 248(%rdi), %r9 + movq 256(%rdi), %r10 + # A[20] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[20] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r11, 224(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[20] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r12, 232(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[20] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r8, 240(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 248(%rdi) + movq 264(%rdi), %r11 + movq 272(%rdi), %r12 + movq 280(%rdi), %r8 + movq 288(%rdi), %r9 + # A[20] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[20] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r10, 256(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[20] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r11, 264(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[20] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r12, 272(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 280(%rdi) + movq 296(%rdi), %r10 + movq 304(%rdi), %r11 + movq 312(%rdi), %r12 + movq 320(%rdi), %r8 + # A[20] * B[16] + mulx 128(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[20] * B[17] + mulx 136(%rbp), %rax, %rcx + movq %r9, 288(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[20] * B[18] + mulx 144(%rbp), %rax, %rcx + movq %r10, 296(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[20] * B[19] + mulx 152(%rbp), %rax, %rcx + movq %r11, 304(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + movq %r12, 312(%rdi) + movq 328(%rdi), %r9 + movq 336(%rdi), %r10 + movq 344(%rdi), %r11 + # A[20] * B[20] + mulx 160(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[20] * B[21] + mulx 168(%rbp), %rax, %rcx + movq %r8, 320(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[20] * B[22] + mulx 176(%rbp), %rax, %rcx + movq %r9, 328(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[20] * B[23] + mulx 184(%rbp), %rax, %rcx + movq %r10, 336(%rdi) + movq %r14, %r12 + adcxq %rax, %r11 + adoxq %rcx, %r12 + adcxq %r13, %r12 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r11, 344(%rdi) + movq %r12, 352(%rdi) + movq 168(%rsi), %rdx + movq 168(%rsp), %r9 + movq %r15, %r10 + movq %rbx, %r11 + movq 192(%rdi), %r12 + movq 200(%rdi), %r8 + # A[21] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[21] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r9, 168(%rsp) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[21] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r10, %r15 + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[21] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r11, %rbx + adcxq %rax, %r12 + adoxq %rcx, %r8 + movq %r12, 192(%rdi) + movq 208(%rdi), %r9 + movq 216(%rdi), %r10 + movq 224(%rdi), %r11 + movq 232(%rdi), %r12 + # A[21] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[21] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r8, 200(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[21] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r9, 208(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[21] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r10, 216(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + movq %r11, 224(%rdi) + movq 240(%rdi), %r8 + movq 248(%rdi), %r9 + movq 256(%rdi), %r10 + movq 264(%rdi), %r11 + # A[21] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[21] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r12, 232(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[21] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r8, 240(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[21] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r9, 248(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 256(%rdi) + movq 272(%rdi), %r12 + movq 280(%rdi), %r8 + movq 288(%rdi), %r9 + movq 296(%rdi), %r10 + # A[21] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[21] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r11, 264(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[21] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r12, 272(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[21] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r8, 280(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 288(%rdi) + movq 304(%rdi), %r11 + movq 312(%rdi), %r12 + movq 320(%rdi), %r8 + movq 328(%rdi), %r9 + # A[21] * B[16] + mulx 128(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[21] * B[17] + mulx 136(%rbp), %rax, %rcx + movq %r10, 296(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[21] * B[18] + mulx 144(%rbp), %rax, %rcx + movq %r11, 304(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[21] * B[19] + mulx 152(%rbp), %rax, %rcx + movq %r12, 312(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 320(%rdi) + movq 336(%rdi), %r10 + movq 344(%rdi), %r11 + movq 352(%rdi), %r12 + # A[21] * B[20] + mulx 160(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[21] * B[21] + mulx 168(%rbp), %rax, %rcx + movq %r9, 328(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[21] * B[22] + mulx 176(%rbp), %rax, %rcx + movq %r10, 336(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[21] * B[23] + mulx 184(%rbp), %rax, %rcx + movq %r11, 344(%rdi) + movq %r14, %r8 + adcxq %rax, %r12 + adoxq %rcx, %r8 + adcxq %r13, %r8 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r12, 352(%rdi) + movq %r8, 360(%rdi) + movq 176(%rsi), %rdx + movq %r15, %r10 + movq %rbx, %r11 + movq 192(%rdi), %r12 + movq 200(%rdi), %r8 + movq 208(%rdi), %r9 + # A[22] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[22] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r10, %r15 + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[22] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r11, %rbx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[22] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r12, 192(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 200(%rdi) + movq 216(%rdi), %r10 + movq 224(%rdi), %r11 + movq 232(%rdi), %r12 + movq 240(%rdi), %r8 + # A[22] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[22] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r9, 208(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[22] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r10, 216(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[22] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r11, 224(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + movq %r12, 232(%rdi) + movq 248(%rdi), %r9 + movq 256(%rdi), %r10 + movq 264(%rdi), %r11 + movq 272(%rdi), %r12 + # A[22] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[22] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r8, 240(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[22] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r9, 248(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[22] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r10, 256(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + movq %r11, 264(%rdi) + movq 280(%rdi), %r8 + movq 288(%rdi), %r9 + movq 296(%rdi), %r10 + movq 304(%rdi), %r11 + # A[22] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[22] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r12, 272(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[22] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r8, 280(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[22] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r9, 288(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 296(%rdi) + movq 312(%rdi), %r12 + movq 320(%rdi), %r8 + movq 328(%rdi), %r9 + movq 336(%rdi), %r10 + # A[22] * B[16] + mulx 128(%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[22] * B[17] + mulx 136(%rbp), %rax, %rcx + movq %r11, 304(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[22] * B[18] + mulx 144(%rbp), %rax, %rcx + movq %r12, 312(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[22] * B[19] + mulx 152(%rbp), %rax, %rcx + movq %r8, 320(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 328(%rdi) + movq 344(%rdi), %r11 + movq 352(%rdi), %r12 + movq 360(%rdi), %r8 + # A[22] * B[20] + mulx 160(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[22] * B[21] + mulx 168(%rbp), %rax, %rcx + movq %r10, 336(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[22] * B[22] + mulx 176(%rbp), %rax, %rcx + movq %r11, 344(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[22] * B[23] + mulx 184(%rbp), %rax, %rcx + movq %r12, 352(%rdi) + movq %r14, %r9 + adcxq %rax, %r8 + adoxq %rcx, %r9 + adcxq %r13, %r9 + movq %r14, %r13 + adoxq %r14, %r13 + adcxq %r14, %r13 + movq %r8, 360(%rdi) + movq %r9, 368(%rdi) + movq 184(%rsi), %rdx + movq %rbx, %r11 + movq 192(%rdi), %r12 + movq 200(%rdi), %r8 + movq 208(%rdi), %r9 + movq 216(%rdi), %r10 + # A[23] * B[0] + mulx (%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[23] * B[1] + mulx 8(%rbp), %rax, %rcx + movq %r11, %rbx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[23] * B[2] + mulx 16(%rbp), %rax, %rcx + movq %r12, 192(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[23] * B[3] + mulx 24(%rbp), %rax, %rcx + movq %r8, 200(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r9, 208(%rdi) + movq 224(%rdi), %r11 + movq 232(%rdi), %r12 + movq 240(%rdi), %r8 + movq 248(%rdi), %r9 + # A[23] * B[4] + mulx 32(%rbp), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[23] * B[5] + mulx 40(%rbp), %rax, %rcx + movq %r10, 216(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[23] * B[6] + mulx 48(%rbp), %rax, %rcx + movq %r11, 224(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[23] * B[7] + mulx 56(%rbp), %rax, %rcx + movq %r12, 232(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r8, 240(%rdi) + movq 256(%rdi), %r10 + movq 264(%rdi), %r11 + movq 272(%rdi), %r12 + movq 280(%rdi), %r8 + # A[23] * B[8] + mulx 64(%rbp), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[23] * B[9] + mulx 72(%rbp), %rax, %rcx + movq %r9, 248(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[23] * B[10] + mulx 80(%rbp), %rax, %rcx + movq %r10, 256(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[23] * B[11] + mulx 88(%rbp), %rax, %rcx + movq %r11, 264(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + movq %r12, 272(%rdi) + movq 288(%rdi), %r9 + movq 296(%rdi), %r10 + movq 304(%rdi), %r11 + movq 312(%rdi), %r12 + # A[23] * B[12] + mulx 96(%rbp), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[23] * B[13] + mulx 104(%rbp), %rax, %rcx + movq %r8, 280(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[23] * B[14] + mulx 112(%rbp), %rax, %rcx + movq %r9, 288(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[23] * B[15] + mulx 120(%rbp), %rax, %rcx + movq %r10, 296(%rdi) + adcxq %rax, %r11 + adoxq %rcx, %r12 + movq %r11, 304(%rdi) + movq 320(%rdi), %r8 + movq 328(%rdi), %r9 + movq 336(%rdi), %r10 + movq 344(%rdi), %r11 + # A[23] * B[16] + mulx 128(%rbp), %rax, %rcx + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[23] * B[17] + mulx 136(%rbp), %rax, %rcx + movq %r12, 312(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[23] * B[18] + mulx 144(%rbp), %rax, %rcx + movq %r8, 320(%rdi) + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[23] * B[19] + mulx 152(%rbp), %rax, %rcx + movq %r9, 328(%rdi) + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r10, 336(%rdi) + movq 352(%rdi), %r12 + movq 360(%rdi), %r8 + movq 368(%rdi), %r9 + # A[23] * B[20] + mulx 160(%rbp), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r12 + # A[23] * B[21] + mulx 168(%rbp), %rax, %rcx + movq %r11, 344(%rdi) + adcxq %rax, %r12 + adoxq %rcx, %r8 + # A[23] * B[22] + mulx 176(%rbp), %rax, %rcx + movq %r12, 352(%rdi) + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[23] * B[23] + mulx 184(%rbp), %rax, %rcx + movq %r8, 360(%rdi) + movq %r14, %r10 + adcxq %rax, %r9 + adoxq %rcx, %r10 + adcxq %r13, %r10 + movq %r9, 368(%rdi) + movq %r10, 376(%rdi) + movq (%rsp), %r8 + movq 8(%rsp), %r9 + movq 16(%rsp), %r10 + movq 24(%rsp), %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 32(%rsp), %r8 + movq 40(%rsp), %r9 + movq 48(%rsp), %r10 + movq 56(%rsp), %r11 + movq %r8, 32(%rdi) + movq %r9, 40(%rdi) + movq %r10, 48(%rdi) + movq %r11, 56(%rdi) + movq 64(%rsp), %r8 + movq 72(%rsp), %r9 + movq 80(%rsp), %r10 + movq 88(%rsp), %r11 + movq %r8, 64(%rdi) + movq %r9, 72(%rdi) + movq %r10, 80(%rdi) + movq %r11, 88(%rdi) + movq 96(%rsp), %r8 + movq 104(%rsp), %r9 + movq 112(%rsp), %r10 + movq 120(%rsp), %r11 + movq %r8, 96(%rdi) + movq %r9, 104(%rdi) + movq %r10, 112(%rdi) + movq %r11, 120(%rdi) + movq 128(%rsp), %r8 + movq 136(%rsp), %r9 + movq 144(%rsp), %r10 + movq 152(%rsp), %r11 + movq %r8, 128(%rdi) + movq %r9, 136(%rdi) + movq %r10, 144(%rdi) + movq %r11, 152(%rdi) + movq 160(%rsp), %r8 + movq 168(%rsp), %r9 + movq %r15, %r10 + movq %rbx, %r11 + movq %r8, 160(%rdi) + movq %r9, 168(%rdi) + movq %r10, 176(%rdi) + movq %r11, 184(%rdi) + addq $192, %rsp + pop %rbx + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + repz retq +#ifndef __APPLE__ +.size sp_3072_mul_avx2_24,.-sp_3072_mul_avx2_24 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +#ifdef HAVE_INTEL_AVX2 +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_3072_sqr_avx2_24 +.type sp_3072_sqr_avx2_24,@function +.align 16 +sp_3072_sqr_avx2_24: +#else +.globl _sp_3072_sqr_avx2_24 +.p2align 4 +_sp_3072_sqr_avx2_24: +#endif /* __APPLE__ */ + push %rbp + push %r12 + push %r13 + subq $192, %rsp + cmpq %rdi, %rsi + movq %rsp, %rbp + cmovne %rdi, %rbp + xorq %r12, %r12 + # Diagonal 1 + xorq %r8, %r8 + xorq %r9, %r9 + xorq %r10, %r10 + xorq %r11, %r11 + # A[1] x A[0] + movq (%rsi), %rdx + mulxq 8(%rsi), %r8, %r9 + # A[2] x A[0] + mulxq 16(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[3] x A[0] + mulxq 24(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r8, 8(%rbp) + movq %r9, 16(%rbp) + movq %r10, 24(%rbp) + movq %r12, %r8 + movq %r12, %r9 + movq %r12, %r10 + # A[4] x A[0] + mulxq 32(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[5] x A[0] + mulxq 40(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[6] x A[0] + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r11, 32(%rbp) + movq %r8, 40(%rbp) + movq %r9, 48(%rbp) + movq %r12, %r11 + movq %r12, %r8 + movq %r12, %r9 + # A[7] x A[0] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[8] x A[0] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[9] x A[0] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r10, 56(%rbp) + movq %r11, 64(%rbp) + movq %r8, 72(%rbp) + movq %r12, %r10 + movq %r12, %r11 + movq %r12, %r8 + # A[10] x A[0] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[11] x A[0] + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[12] x A[0] + mulxq 96(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + movq %r9, 80(%rbp) + movq %r10, 88(%rbp) + movq %r11, 96(%rbp) + movq %r12, %r9 + movq %r12, %r10 + movq %r12, %r11 + # A[13] x A[0] + mulxq 104(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[14] x A[0] + mulxq 112(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[15] x A[0] + mulxq 120(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r8, 104(%rbp) + movq %r9, 112(%rbp) + movq %r10, 120(%rbp) + movq %r12, %r8 + movq %r12, %r9 + movq %r12, %r10 + # A[16] x A[0] + mulxq 128(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[17] x A[0] + mulxq 136(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[18] x A[0] + mulxq 144(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r11, 128(%rbp) + movq %r8, 136(%rbp) + movq %r9, 144(%rbp) + movq %r12, %r11 + movq %r12, %r8 + movq %r12, %r9 + # A[19] x A[0] + mulxq 152(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[20] x A[0] + mulxq 160(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[21] x A[0] + mulxq 168(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r10, 152(%rbp) + movq %r11, 160(%rbp) + movq %r8, 168(%rbp) + movq %r12, %r10 + movq %r12, %r11 + # A[22] x A[0] + mulxq 176(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[23] x A[0] + mulxq 184(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r9, 176(%rbp) + movq %r10, 184(%rbp) + # Carry + adcxq %r12, %r11 + movq %r12, %r13 + adcxq %r12, %r13 + adoxq %r12, %r13 + movq %r11, 192(%rdi) + # Diagonal 2 + movq 24(%rbp), %r11 + movq 32(%rbp), %r8 + movq 40(%rbp), %r9 + movq 48(%rbp), %r10 + # A[2] x A[1] + movq 8(%rsi), %rdx + mulxq 16(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[3] x A[1] + mulxq 24(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[4] x A[1] + mulxq 32(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r11, 24(%rbp) + movq %r8, 32(%rbp) + movq %r9, 40(%rbp) + movq 56(%rbp), %r11 + movq 64(%rbp), %r8 + movq 72(%rbp), %r9 + # A[5] x A[1] + mulxq 40(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[6] x A[1] + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[7] x A[1] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r10, 48(%rbp) + movq %r11, 56(%rbp) + movq %r8, 64(%rbp) + movq 80(%rbp), %r10 + movq 88(%rbp), %r11 + movq 96(%rbp), %r8 + # A[8] x A[1] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[9] x A[1] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[10] x A[1] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + movq %r9, 72(%rbp) + movq %r10, 80(%rbp) + movq %r11, 88(%rbp) + movq 104(%rbp), %r9 + movq 112(%rbp), %r10 + movq 120(%rbp), %r11 + # A[11] x A[1] + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[12] x A[1] + mulxq 96(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[13] x A[1] + mulxq 104(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r8, 96(%rbp) + movq %r9, 104(%rbp) + movq %r10, 112(%rbp) + movq 128(%rbp), %r8 + movq 136(%rbp), %r9 + movq 144(%rbp), %r10 + # A[14] x A[1] + mulxq 112(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[15] x A[1] + mulxq 120(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[16] x A[1] + mulxq 128(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r11, 120(%rbp) + movq %r8, 128(%rbp) + movq %r9, 136(%rbp) + movq 152(%rbp), %r11 + movq 160(%rbp), %r8 + movq 168(%rbp), %r9 + # A[17] x A[1] + mulxq 136(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[18] x A[1] + mulxq 144(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[19] x A[1] + mulxq 152(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r10, 144(%rbp) + movq %r11, 152(%rbp) + movq %r8, 160(%rbp) + movq 176(%rbp), %r10 + movq 184(%rbp), %r11 + movq 192(%rdi), %r8 + # A[20] x A[1] + mulxq 160(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[21] x A[1] + mulxq 168(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[22] x A[1] + mulxq 176(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + movq %r9, 168(%rbp) + movq %r10, 176(%rbp) + movq %r11, 184(%rbp) + movq %r12, %r9 + movq %r12, %r10 + # A[23] x A[1] + mulxq 184(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[23] x A[2] + movq 16(%rsi), %rdx + mulxq 184(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r8, 192(%rdi) + movq %r9, 200(%rdi) + # Carry + adcxq %r13, %r10 + movq %r12, %r13 + adcxq %r12, %r13 + adoxq %r12, %r13 + movq %r10, 208(%rdi) + # Diagonal 3 + movq 40(%rbp), %r10 + movq 48(%rbp), %r11 + movq 56(%rbp), %r8 + movq 64(%rbp), %r9 + # A[3] x A[2] + mulxq 24(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[4] x A[2] + mulxq 32(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[5] x A[2] + mulxq 40(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r10, 40(%rbp) + movq %r11, 48(%rbp) + movq %r8, 56(%rbp) + movq 72(%rbp), %r10 + movq 80(%rbp), %r11 + movq 88(%rbp), %r8 + # A[6] x A[2] + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[7] x A[2] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[8] x A[2] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + movq %r9, 64(%rbp) + movq %r10, 72(%rbp) + movq %r11, 80(%rbp) + movq 96(%rbp), %r9 + movq 104(%rbp), %r10 + movq 112(%rbp), %r11 + # A[9] x A[2] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[10] x A[2] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[11] x A[2] + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r8, 88(%rbp) + movq %r9, 96(%rbp) + movq %r10, 104(%rbp) + movq 120(%rbp), %r8 + movq 128(%rbp), %r9 + movq 136(%rbp), %r10 + # A[12] x A[2] + mulxq 96(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[13] x A[2] + mulxq 104(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[14] x A[2] + mulxq 112(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r11, 112(%rbp) + movq %r8, 120(%rbp) + movq %r9, 128(%rbp) + movq 144(%rbp), %r11 + movq 152(%rbp), %r8 + movq 160(%rbp), %r9 + # A[15] x A[2] + mulxq 120(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[16] x A[2] + mulxq 128(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[17] x A[2] + mulxq 136(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r10, 136(%rbp) + movq %r11, 144(%rbp) + movq %r8, 152(%rbp) + movq 168(%rbp), %r10 + movq 176(%rbp), %r11 + movq 184(%rbp), %r8 + # A[18] x A[2] + mulxq 144(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[19] x A[2] + mulxq 152(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[20] x A[2] + mulxq 160(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + movq %r9, 160(%rbp) + movq %r10, 168(%rbp) + movq %r11, 176(%rbp) + movq 192(%rdi), %r9 + movq 200(%rdi), %r10 + movq 208(%rdi), %r11 + # A[21] x A[2] + mulxq 168(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[22] x A[2] + mulxq 176(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[22] x A[3] + movq 176(%rsi), %rdx + mulxq 24(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r8, 184(%rbp) + movq %r9, 192(%rdi) + movq %r10, 200(%rdi) + movq %r12, %r8 + movq %r12, %r9 + # A[22] x A[4] + mulxq 32(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[22] x A[5] + mulxq 40(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r11, 208(%rdi) + movq %r8, 216(%rdi) + # Carry + adcxq %r13, %r9 + movq %r12, %r13 + adcxq %r12, %r13 + adoxq %r12, %r13 + movq %r9, 224(%rdi) + # Diagonal 4 + movq 56(%rbp), %r9 + movq 64(%rbp), %r10 + movq 72(%rbp), %r11 + movq 80(%rbp), %r8 + # A[4] x A[3] + movq 24(%rsi), %rdx + mulxq 32(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[5] x A[3] + mulxq 40(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[6] x A[3] + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + movq %r9, 56(%rbp) + movq %r10, 64(%rbp) + movq %r11, 72(%rbp) + movq 88(%rbp), %r9 + movq 96(%rbp), %r10 + movq 104(%rbp), %r11 + # A[7] x A[3] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[8] x A[3] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[9] x A[3] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r8, 80(%rbp) + movq %r9, 88(%rbp) + movq %r10, 96(%rbp) + movq 112(%rbp), %r8 + movq 120(%rbp), %r9 + movq 128(%rbp), %r10 + # A[10] x A[3] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[11] x A[3] + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[12] x A[3] + mulxq 96(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r11, 104(%rbp) + movq %r8, 112(%rbp) + movq %r9, 120(%rbp) + movq 136(%rbp), %r11 + movq 144(%rbp), %r8 + movq 152(%rbp), %r9 + # A[13] x A[3] + mulxq 104(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[14] x A[3] + mulxq 112(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[15] x A[3] + mulxq 120(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r10, 128(%rbp) + movq %r11, 136(%rbp) + movq %r8, 144(%rbp) + movq 160(%rbp), %r10 + movq 168(%rbp), %r11 + movq 176(%rbp), %r8 + # A[16] x A[3] + mulxq 128(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[17] x A[3] + mulxq 136(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[18] x A[3] + mulxq 144(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + movq %r9, 152(%rbp) + movq %r10, 160(%rbp) + movq %r11, 168(%rbp) + movq 184(%rbp), %r9 + movq 192(%rdi), %r10 + movq 200(%rdi), %r11 + # A[19] x A[3] + mulxq 152(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[20] x A[3] + mulxq 160(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[21] x A[3] + mulxq 168(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r8, 176(%rbp) + movq %r9, 184(%rbp) + movq %r10, 192(%rdi) + movq 208(%rdi), %r8 + movq 216(%rdi), %r9 + movq 224(%rdi), %r10 + # A[21] x A[4] + movq 168(%rsi), %rdx + mulxq 32(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[21] x A[5] + mulxq 40(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[21] x A[6] + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r11, 200(%rdi) + movq %r8, 208(%rdi) + movq %r9, 216(%rdi) + movq %r12, %r11 + movq %r12, %r8 + # A[21] x A[7] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[21] x A[8] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + movq %r10, 224(%rdi) + movq %r11, 232(%rdi) + # Carry + adcxq %r13, %r8 + movq %r12, %r13 + adcxq %r12, %r13 + adoxq %r12, %r13 + movq %r8, 240(%rdi) + # Diagonal 5 + movq 72(%rbp), %r8 + movq 80(%rbp), %r9 + movq 88(%rbp), %r10 + movq 96(%rbp), %r11 + # A[5] x A[4] + movq 32(%rsi), %rdx + mulxq 40(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[6] x A[4] + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[7] x A[4] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r8, 72(%rbp) + movq %r9, 80(%rbp) + movq %r10, 88(%rbp) + movq 104(%rbp), %r8 + movq 112(%rbp), %r9 + movq 120(%rbp), %r10 + # A[8] x A[4] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[9] x A[4] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[10] x A[4] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r11, 96(%rbp) + movq %r8, 104(%rbp) + movq %r9, 112(%rbp) + movq 128(%rbp), %r11 + movq 136(%rbp), %r8 + movq 144(%rbp), %r9 + # A[11] x A[4] + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[12] x A[4] + mulxq 96(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[13] x A[4] + mulxq 104(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r10, 120(%rbp) + movq %r11, 128(%rbp) + movq %r8, 136(%rbp) + movq 152(%rbp), %r10 + movq 160(%rbp), %r11 + movq 168(%rbp), %r8 + # A[14] x A[4] + mulxq 112(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[15] x A[4] + mulxq 120(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[16] x A[4] + mulxq 128(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + movq %r9, 144(%rbp) + movq %r10, 152(%rbp) + movq %r11, 160(%rbp) + movq 176(%rbp), %r9 + movq 184(%rbp), %r10 + movq 192(%rdi), %r11 + # A[17] x A[4] + mulxq 136(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[18] x A[4] + mulxq 144(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[19] x A[4] + mulxq 152(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r8, 168(%rbp) + movq %r9, 176(%rbp) + movq %r10, 184(%rbp) + movq 200(%rdi), %r8 + movq 208(%rdi), %r9 + movq 216(%rdi), %r10 + # A[20] x A[4] + mulxq 160(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[20] x A[5] + movq 160(%rsi), %rdx + mulxq 40(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[20] x A[6] + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r11, 192(%rdi) + movq %r8, 200(%rdi) + movq %r9, 208(%rdi) + movq 224(%rdi), %r11 + movq 232(%rdi), %r8 + movq 240(%rdi), %r9 + # A[20] x A[7] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[20] x A[8] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[20] x A[9] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r10, 216(%rdi) + movq %r11, 224(%rdi) + movq %r8, 232(%rdi) + movq %r12, %r10 + movq %r12, %r11 + # A[20] x A[10] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[20] x A[11] + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r9, 240(%rdi) + movq %r10, 248(%rdi) + # Carry + adcxq %r13, %r11 + movq %r12, %r13 + adcxq %r12, %r13 + adoxq %r12, %r13 + movq %r11, 256(%rdi) + # Diagonal 6 + movq 88(%rbp), %r11 + movq 96(%rbp), %r8 + movq 104(%rbp), %r9 + movq 112(%rbp), %r10 + # A[6] x A[5] + movq 40(%rsi), %rdx + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[7] x A[5] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[8] x A[5] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r11, 88(%rbp) + movq %r8, 96(%rbp) + movq %r9, 104(%rbp) + movq 120(%rbp), %r11 + movq 128(%rbp), %r8 + movq 136(%rbp), %r9 + # A[9] x A[5] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[10] x A[5] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[11] x A[5] + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r10, 112(%rbp) + movq %r11, 120(%rbp) + movq %r8, 128(%rbp) + movq 144(%rbp), %r10 + movq 152(%rbp), %r11 + movq 160(%rbp), %r8 + # A[12] x A[5] + mulxq 96(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[13] x A[5] + mulxq 104(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[14] x A[5] + mulxq 112(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + movq %r9, 136(%rbp) + movq %r10, 144(%rbp) + movq %r11, 152(%rbp) + movq 168(%rbp), %r9 + movq 176(%rbp), %r10 + movq 184(%rbp), %r11 + # A[15] x A[5] + mulxq 120(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[16] x A[5] + mulxq 128(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[17] x A[5] + mulxq 136(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r8, 160(%rbp) + movq %r9, 168(%rbp) + movq %r10, 176(%rbp) + movq 192(%rdi), %r8 + movq 200(%rdi), %r9 + movq 208(%rdi), %r10 + # A[18] x A[5] + mulxq 144(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[19] x A[5] + mulxq 152(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[19] x A[6] + movq 152(%rsi), %rdx + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r11, 184(%rbp) + movq %r8, 192(%rdi) + movq %r9, 200(%rdi) + movq 216(%rdi), %r11 + movq 224(%rdi), %r8 + movq 232(%rdi), %r9 + # A[19] x A[7] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[19] x A[8] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[19] x A[9] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r10, 208(%rdi) + movq %r11, 216(%rdi) + movq %r8, 224(%rdi) + movq 240(%rdi), %r10 + movq 248(%rdi), %r11 + movq 256(%rdi), %r8 + # A[19] x A[10] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[19] x A[11] + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[19] x A[12] + mulxq 96(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + movq %r9, 232(%rdi) + movq %r10, 240(%rdi) + movq %r11, 248(%rdi) + movq %r12, %r9 + movq %r12, %r10 + # A[19] x A[13] + mulxq 104(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[19] x A[14] + mulxq 112(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r8, 256(%rdi) + movq %r9, 264(%rdi) + # Carry + adcxq %r13, %r10 + movq %r12, %r13 + adcxq %r12, %r13 + adoxq %r12, %r13 + movq %r10, 272(%rdi) + # Diagonal 7 + movq 104(%rbp), %r10 + movq 112(%rbp), %r11 + movq 120(%rbp), %r8 + movq 128(%rbp), %r9 + # A[7] x A[6] + movq 48(%rsi), %rdx + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[8] x A[6] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[9] x A[6] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r10, 104(%rbp) + movq %r11, 112(%rbp) + movq %r8, 120(%rbp) + movq 136(%rbp), %r10 + movq 144(%rbp), %r11 + movq 152(%rbp), %r8 + # A[10] x A[6] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[11] x A[6] + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[12] x A[6] + mulxq 96(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + movq %r9, 128(%rbp) + movq %r10, 136(%rbp) + movq %r11, 144(%rbp) + movq 160(%rbp), %r9 + movq 168(%rbp), %r10 + movq 176(%rbp), %r11 + # A[13] x A[6] + mulxq 104(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[14] x A[6] + mulxq 112(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[15] x A[6] + mulxq 120(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r8, 152(%rbp) + movq %r9, 160(%rbp) + movq %r10, 168(%rbp) + movq 184(%rbp), %r8 + movq 192(%rdi), %r9 + movq 200(%rdi), %r10 + # A[16] x A[6] + mulxq 128(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[17] x A[6] + mulxq 136(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[18] x A[6] + mulxq 144(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r11, 176(%rbp) + movq %r8, 184(%rbp) + movq %r9, 192(%rdi) + movq 208(%rdi), %r11 + movq 216(%rdi), %r8 + movq 224(%rdi), %r9 + # A[18] x A[7] + movq 144(%rsi), %rdx + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[18] x A[8] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[18] x A[9] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r10, 200(%rdi) + movq %r11, 208(%rdi) + movq %r8, 216(%rdi) + movq 232(%rdi), %r10 + movq 240(%rdi), %r11 + movq 248(%rdi), %r8 + # A[18] x A[10] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[18] x A[11] + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[18] x A[12] + mulxq 96(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + movq %r9, 224(%rdi) + movq %r10, 232(%rdi) + movq %r11, 240(%rdi) + movq 256(%rdi), %r9 + movq 264(%rdi), %r10 + movq 272(%rdi), %r11 + # A[18] x A[13] + mulxq 104(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[18] x A[14] + mulxq 112(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[18] x A[15] + mulxq 120(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r8, 248(%rdi) + movq %r9, 256(%rdi) + movq %r10, 264(%rdi) + movq %r12, %r8 + movq %r12, %r9 + # A[18] x A[16] + mulxq 128(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[18] x A[17] + mulxq 136(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r11, 272(%rdi) + movq %r8, 280(%rdi) + # Carry + adcxq %r13, %r9 + movq %r12, %r13 + adcxq %r12, %r13 + adoxq %r12, %r13 + movq %r9, 288(%rdi) + # Diagonal 8 + movq 120(%rbp), %r9 + movq 128(%rbp), %r10 + movq 136(%rbp), %r11 + movq 144(%rbp), %r8 + # A[8] x A[7] + movq 56(%rsi), %rdx + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[9] x A[7] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[10] x A[7] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + movq %r9, 120(%rbp) + movq %r10, 128(%rbp) + movq %r11, 136(%rbp) + movq 152(%rbp), %r9 + movq 160(%rbp), %r10 + movq 168(%rbp), %r11 + # A[11] x A[7] + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[12] x A[7] + mulxq 96(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[13] x A[7] + mulxq 104(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r8, 144(%rbp) + movq %r9, 152(%rbp) + movq %r10, 160(%rbp) + movq 176(%rbp), %r8 + movq 184(%rbp), %r9 + movq 192(%rdi), %r10 + # A[14] x A[7] + mulxq 112(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[15] x A[7] + mulxq 120(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[16] x A[7] + mulxq 128(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r11, 168(%rbp) + movq %r8, 176(%rbp) + movq %r9, 184(%rbp) + movq 200(%rdi), %r11 + movq 208(%rdi), %r8 + movq 216(%rdi), %r9 + # A[17] x A[7] + mulxq 136(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[17] x A[8] + movq 136(%rsi), %rdx + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[17] x A[9] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r10, 192(%rdi) + movq %r11, 200(%rdi) + movq %r8, 208(%rdi) + movq 224(%rdi), %r10 + movq 232(%rdi), %r11 + movq 240(%rdi), %r8 + # A[17] x A[10] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[17] x A[11] + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[17] x A[12] + mulxq 96(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + movq %r9, 216(%rdi) + movq %r10, 224(%rdi) + movq %r11, 232(%rdi) + movq 248(%rdi), %r9 + movq 256(%rdi), %r10 + movq 264(%rdi), %r11 + # A[17] x A[13] + mulxq 104(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[17] x A[14] + mulxq 112(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[17] x A[15] + mulxq 120(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r8, 240(%rdi) + movq %r9, 248(%rdi) + movq %r10, 256(%rdi) + movq 272(%rdi), %r8 + movq 280(%rdi), %r9 + movq 288(%rdi), %r10 + # A[17] x A[16] + mulxq 128(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[19] x A[15] + movq 152(%rsi), %rdx + mulxq 120(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[19] x A[16] + mulxq 128(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r11, 264(%rdi) + movq %r8, 272(%rdi) + movq %r9, 280(%rdi) + movq %r12, %r11 + movq %r12, %r8 + # A[19] x A[17] + mulxq 136(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[19] x A[18] + mulxq 144(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + movq %r10, 288(%rdi) + movq %r11, 296(%rdi) + # Carry + adcxq %r13, %r8 + movq %r12, %r13 + adcxq %r12, %r13 + adoxq %r12, %r13 + movq %r8, 304(%rdi) + # Diagonal 9 + movq 136(%rbp), %r8 + movq 144(%rbp), %r9 + movq 152(%rbp), %r10 + movq 160(%rbp), %r11 + # A[9] x A[8] + movq 64(%rsi), %rdx + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[10] x A[8] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[11] x A[8] + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r8, 136(%rbp) + movq %r9, 144(%rbp) + movq %r10, 152(%rbp) + movq 168(%rbp), %r8 + movq 176(%rbp), %r9 + movq 184(%rbp), %r10 + # A[12] x A[8] + mulxq 96(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[13] x A[8] + mulxq 104(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[14] x A[8] + mulxq 112(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r11, 160(%rbp) + movq %r8, 168(%rbp) + movq %r9, 176(%rbp) + movq 192(%rdi), %r11 + movq 200(%rdi), %r8 + movq 208(%rdi), %r9 + # A[15] x A[8] + mulxq 120(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[16] x A[8] + mulxq 128(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[16] x A[9] + movq 128(%rsi), %rdx + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r10, 184(%rbp) + movq %r11, 192(%rdi) + movq %r8, 200(%rdi) + movq 216(%rdi), %r10 + movq 224(%rdi), %r11 + movq 232(%rdi), %r8 + # A[16] x A[10] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[16] x A[11] + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[16] x A[12] + mulxq 96(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + movq %r9, 208(%rdi) + movq %r10, 216(%rdi) + movq %r11, 224(%rdi) + movq 240(%rdi), %r9 + movq 248(%rdi), %r10 + movq 256(%rdi), %r11 + # A[16] x A[13] + mulxq 104(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[16] x A[14] + mulxq 112(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[16] x A[15] + mulxq 120(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r8, 232(%rdi) + movq %r9, 240(%rdi) + movq %r10, 248(%rdi) + movq 264(%rdi), %r8 + movq 272(%rdi), %r9 + movq 280(%rdi), %r10 + # A[20] x A[12] + movq 160(%rsi), %rdx + mulxq 96(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[20] x A[13] + mulxq 104(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[20] x A[14] + mulxq 112(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r11, 256(%rdi) + movq %r8, 264(%rdi) + movq %r9, 272(%rdi) + movq 288(%rdi), %r11 + movq 296(%rdi), %r8 + movq 304(%rdi), %r9 + # A[20] x A[15] + mulxq 120(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[20] x A[16] + mulxq 128(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[20] x A[17] + mulxq 136(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r10, 280(%rdi) + movq %r11, 288(%rdi) + movq %r8, 296(%rdi) + movq %r12, %r10 + movq %r12, %r11 + # A[20] x A[18] + mulxq 144(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[20] x A[19] + mulxq 152(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r9, 304(%rdi) + movq %r10, 312(%rdi) + # Carry + adcxq %r13, %r11 + movq %r12, %r13 + adcxq %r12, %r13 + adoxq %r12, %r13 + movq %r11, 320(%rdi) + # Diagonal 10 + movq 152(%rbp), %r11 + movq 160(%rbp), %r8 + movq 168(%rbp), %r9 + movq 176(%rbp), %r10 + # A[10] x A[9] + movq 72(%rsi), %rdx + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[11] x A[9] + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[12] x A[9] + mulxq 96(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r11, 152(%rbp) + movq %r8, 160(%rbp) + movq %r9, 168(%rbp) + movq 184(%rbp), %r11 + movq 192(%rdi), %r8 + movq 200(%rdi), %r9 + # A[13] x A[9] + mulxq 104(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[14] x A[9] + mulxq 112(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[15] x A[9] + mulxq 120(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r10, 176(%rbp) + movq %r11, 184(%rbp) + movq %r8, 192(%rdi) + movq 208(%rdi), %r10 + movq 216(%rdi), %r11 + movq 224(%rdi), %r8 + # A[15] x A[10] + movq 120(%rsi), %rdx + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[15] x A[11] + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[15] x A[12] + mulxq 96(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + movq %r9, 200(%rdi) + movq %r10, 208(%rdi) + movq %r11, 216(%rdi) + movq 232(%rdi), %r9 + movq 240(%rdi), %r10 + movq 248(%rdi), %r11 + # A[15] x A[13] + mulxq 104(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[15] x A[14] + mulxq 112(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[21] x A[9] + movq 168(%rsi), %rdx + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r8, 224(%rdi) + movq %r9, 232(%rdi) + movq %r10, 240(%rdi) + movq 256(%rdi), %r8 + movq 264(%rdi), %r9 + movq 272(%rdi), %r10 + # A[21] x A[10] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[21] x A[11] + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[21] x A[12] + mulxq 96(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r11, 248(%rdi) + movq %r8, 256(%rdi) + movq %r9, 264(%rdi) + movq 280(%rdi), %r11 + movq 288(%rdi), %r8 + movq 296(%rdi), %r9 + # A[21] x A[13] + mulxq 104(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[21] x A[14] + mulxq 112(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[21] x A[15] + mulxq 120(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r10, 272(%rdi) + movq %r11, 280(%rdi) + movq %r8, 288(%rdi) + movq 304(%rdi), %r10 + movq 312(%rdi), %r11 + movq 320(%rdi), %r8 + # A[21] x A[16] + mulxq 128(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[21] x A[17] + mulxq 136(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[21] x A[18] + mulxq 144(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + movq %r9, 296(%rdi) + movq %r10, 304(%rdi) + movq %r11, 312(%rdi) + movq %r12, %r9 + movq %r12, %r10 + # A[21] x A[19] + mulxq 152(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[21] x A[20] + mulxq 160(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r8, 320(%rdi) + movq %r9, 328(%rdi) + # Carry + adcxq %r13, %r10 + movq %r12, %r13 + adcxq %r12, %r13 + adoxq %r12, %r13 + movq %r10, 336(%rdi) + # Diagonal 11 + movq 168(%rbp), %r10 + movq 176(%rbp), %r11 + movq 184(%rbp), %r8 + movq 192(%rdi), %r9 + # A[11] x A[10] + movq 80(%rsi), %rdx + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[12] x A[10] + mulxq 96(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[13] x A[10] + mulxq 104(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r10, 168(%rbp) + movq %r11, 176(%rbp) + movq %r8, 184(%rbp) + movq 200(%rdi), %r10 + movq 208(%rdi), %r11 + movq 216(%rdi), %r8 + # A[14] x A[10] + mulxq 112(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[14] x A[11] + movq 112(%rsi), %rdx + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[14] x A[12] + mulxq 96(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + movq %r9, 192(%rdi) + movq %r10, 200(%rdi) + movq %r11, 208(%rdi) + movq 224(%rdi), %r9 + movq 232(%rdi), %r10 + movq 240(%rdi), %r11 + # A[14] x A[13] + mulxq 104(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[22] x A[6] + movq 176(%rsi), %rdx + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[22] x A[7] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r8, 216(%rdi) + movq %r9, 224(%rdi) + movq %r10, 232(%rdi) + movq 248(%rdi), %r8 + movq 256(%rdi), %r9 + movq 264(%rdi), %r10 + # A[22] x A[8] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[22] x A[9] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[22] x A[10] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r11, 240(%rdi) + movq %r8, 248(%rdi) + movq %r9, 256(%rdi) + movq 272(%rdi), %r11 + movq 280(%rdi), %r8 + movq 288(%rdi), %r9 + # A[22] x A[11] + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[22] x A[12] + mulxq 96(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[22] x A[13] + mulxq 104(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r10, 264(%rdi) + movq %r11, 272(%rdi) + movq %r8, 280(%rdi) + movq 296(%rdi), %r10 + movq 304(%rdi), %r11 + movq 312(%rdi), %r8 + # A[22] x A[14] + mulxq 112(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[22] x A[15] + mulxq 120(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[22] x A[16] + mulxq 128(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + movq %r9, 288(%rdi) + movq %r10, 296(%rdi) + movq %r11, 304(%rdi) + movq 320(%rdi), %r9 + movq 328(%rdi), %r10 + movq 336(%rdi), %r11 + # A[22] x A[17] + mulxq 136(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[22] x A[18] + mulxq 144(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[22] x A[19] + mulxq 152(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r8, 312(%rdi) + movq %r9, 320(%rdi) + movq %r10, 328(%rdi) + movq %r12, %r8 + movq %r12, %r9 + # A[22] x A[20] + mulxq 160(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[22] x A[21] + mulxq 168(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r11, 336(%rdi) + movq %r8, 344(%rdi) + # Carry + adcxq %r13, %r9 + movq %r12, %r13 + adcxq %r12, %r13 + adoxq %r12, %r13 + movq %r9, 352(%rdi) + # Diagonal 12 + movq 184(%rbp), %r9 + movq 192(%rdi), %r10 + movq 200(%rdi), %r11 + movq 208(%rdi), %r8 + # A[12] x A[11] + movq 88(%rsi), %rdx + mulxq 96(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[13] x A[11] + mulxq 104(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[13] x A[12] + movq 96(%rsi), %rdx + mulxq 104(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + movq %r9, 184(%rbp) + movq %r10, 192(%rdi) + movq %r11, 200(%rdi) + movq 216(%rdi), %r9 + movq 224(%rdi), %r10 + movq 232(%rdi), %r11 + # A[23] x A[3] + movq 184(%rsi), %rdx + mulxq 24(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[23] x A[4] + mulxq 32(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[23] x A[5] + mulxq 40(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r8, 208(%rdi) + movq %r9, 216(%rdi) + movq %r10, 224(%rdi) + movq 240(%rdi), %r8 + movq 248(%rdi), %r9 + movq 256(%rdi), %r10 + # A[23] x A[6] + mulxq 48(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[23] x A[7] + mulxq 56(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[23] x A[8] + mulxq 64(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r11, 232(%rdi) + movq %r8, 240(%rdi) + movq %r9, 248(%rdi) + movq 264(%rdi), %r11 + movq 272(%rdi), %r8 + movq 280(%rdi), %r9 + # A[23] x A[9] + mulxq 72(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[23] x A[10] + mulxq 80(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[23] x A[11] + mulxq 88(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + movq %r10, 256(%rdi) + movq %r11, 264(%rdi) + movq %r8, 272(%rdi) + movq 288(%rdi), %r10 + movq 296(%rdi), %r11 + movq 304(%rdi), %r8 + # A[23] x A[12] + mulxq 96(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[23] x A[13] + mulxq 104(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[23] x A[14] + mulxq 112(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + movq %r9, 280(%rdi) + movq %r10, 288(%rdi) + movq %r11, 296(%rdi) + movq 312(%rdi), %r9 + movq 320(%rdi), %r10 + movq 328(%rdi), %r11 + # A[23] x A[15] + mulxq 120(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[23] x A[16] + mulxq 128(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + # A[23] x A[17] + mulxq 136(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + movq %r8, 304(%rdi) + movq %r9, 312(%rdi) + movq %r10, 320(%rdi) + movq 336(%rdi), %r8 + movq 344(%rdi), %r9 + movq 352(%rdi), %r10 + # A[23] x A[18] + mulxq 144(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + # A[23] x A[19] + mulxq 152(%rsi), %rax, %rcx + adcxq %rax, %r8 + adoxq %rcx, %r9 + # A[23] x A[20] + mulxq 160(%rsi), %rax, %rcx + adcxq %rax, %r9 + adoxq %rcx, %r10 + movq %r11, 328(%rdi) + movq %r8, 336(%rdi) + movq %r9, 344(%rdi) + movq %r12, %r11 + movq %r12, %r8 + # A[23] x A[21] + mulxq 168(%rsi), %rax, %rcx + adcxq %rax, %r10 + adoxq %rcx, %r11 + # A[23] x A[22] + mulxq 176(%rsi), %rax, %rcx + adcxq %rax, %r11 + adoxq %rcx, %r8 + movq %r10, 352(%rdi) + movq %r11, 360(%rdi) + # Carry + adcxq %r13, %r8 + movq %r12, %r13 + adcxq %r12, %r13 + adoxq %r12, %r13 + movq %r8, 368(%rdi) + movq %r13, 376(%rdi) + # Double and Add in A[i] x A[i] + movq 8(%rbp), %r9 + # A[0] x A[0] + movq (%rsi), %rdx + mulxq %rdx, %rax, %rcx + movq %rax, (%rbp) + adoxq %r9, %r9 + adcxq %rcx, %r9 + movq %r9, 8(%rbp) + movq 16(%rbp), %r8 + movq 24(%rbp), %r9 + # A[1] x A[1] + movq 8(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adcxq %rax, %r8 + adoxq %r9, %r9 + adcxq %rcx, %r9 + movq %r8, 16(%rbp) + movq %r9, 24(%rbp) + movq 32(%rbp), %r8 + movq 40(%rbp), %r9 + # A[2] x A[2] + movq 16(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adcxq %rax, %r8 + adoxq %r9, %r9 + adcxq %rcx, %r9 + movq %r8, 32(%rbp) + movq %r9, 40(%rbp) + movq 48(%rbp), %r8 + movq 56(%rbp), %r9 + # A[3] x A[3] + movq 24(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adcxq %rax, %r8 + adoxq %r9, %r9 + adcxq %rcx, %r9 + movq %r8, 48(%rbp) + movq %r9, 56(%rbp) + movq 64(%rbp), %r8 + movq 72(%rbp), %r9 + # A[4] x A[4] + movq 32(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adcxq %rax, %r8 + adoxq %r9, %r9 + adcxq %rcx, %r9 + movq %r8, 64(%rbp) + movq %r9, 72(%rbp) + movq 80(%rbp), %r8 + movq 88(%rbp), %r9 + # A[5] x A[5] + movq 40(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adcxq %rax, %r8 + adoxq %r9, %r9 + adcxq %rcx, %r9 + movq %r8, 80(%rbp) + movq %r9, 88(%rbp) + movq 96(%rbp), %r8 + movq 104(%rbp), %r9 + # A[6] x A[6] + movq 48(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adcxq %rax, %r8 + adoxq %r9, %r9 + adcxq %rcx, %r9 + movq %r8, 96(%rbp) + movq %r9, 104(%rbp) + movq 112(%rbp), %r8 + movq 120(%rbp), %r9 + # A[7] x A[7] + movq 56(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adcxq %rax, %r8 + adoxq %r9, %r9 + adcxq %rcx, %r9 + movq %r8, 112(%rbp) + movq %r9, 120(%rbp) + movq 128(%rbp), %r8 + movq 136(%rbp), %r9 + # A[8] x A[8] + movq 64(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adcxq %rax, %r8 + adoxq %r9, %r9 + adcxq %rcx, %r9 + movq %r8, 128(%rbp) + movq %r9, 136(%rbp) + movq 144(%rbp), %r8 + movq 152(%rbp), %r9 + # A[9] x A[9] + movq 72(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adcxq %rax, %r8 + adoxq %r9, %r9 + adcxq %rcx, %r9 + movq %r8, 144(%rbp) + movq %r9, 152(%rbp) + movq 160(%rbp), %r8 + movq 168(%rbp), %r9 + # A[10] x A[10] + movq 80(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adcxq %rax, %r8 + adoxq %r9, %r9 + adcxq %rcx, %r9 + movq %r8, 160(%rbp) + movq %r9, 168(%rbp) + movq 176(%rbp), %r8 + movq 184(%rbp), %r9 + # A[11] x A[11] + movq 88(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adcxq %rax, %r8 + adoxq %r9, %r9 + adcxq %rcx, %r9 + movq %r8, 176(%rbp) + movq %r9, 184(%rbp) + movq 192(%rdi), %r8 + movq 200(%rdi), %r9 + # A[12] x A[12] + movq 96(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adcxq %rax, %r8 + adoxq %r9, %r9 + adcxq %rcx, %r9 + movq %r8, 192(%rdi) + movq %r9, 200(%rdi) + movq 208(%rdi), %r8 + movq 216(%rdi), %r9 + # A[13] x A[13] + movq 104(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adcxq %rax, %r8 + adoxq %r9, %r9 + adcxq %rcx, %r9 + movq %r8, 208(%rdi) + movq %r9, 216(%rdi) + movq 224(%rdi), %r8 + movq 232(%rdi), %r9 + # A[14] x A[14] + movq 112(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adcxq %rax, %r8 + adoxq %r9, %r9 + adcxq %rcx, %r9 + movq %r8, 224(%rdi) + movq %r9, 232(%rdi) + movq 240(%rdi), %r8 + movq 248(%rdi), %r9 + # A[15] x A[15] + movq 120(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adcxq %rax, %r8 + adoxq %r9, %r9 + adcxq %rcx, %r9 + movq %r8, 240(%rdi) + movq %r9, 248(%rdi) + movq 256(%rdi), %r8 + movq 264(%rdi), %r9 + # A[16] x A[16] + movq 128(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adcxq %rax, %r8 + adoxq %r9, %r9 + adcxq %rcx, %r9 + movq %r8, 256(%rdi) + movq %r9, 264(%rdi) + movq 272(%rdi), %r8 + movq 280(%rdi), %r9 + # A[17] x A[17] + movq 136(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adcxq %rax, %r8 + adoxq %r9, %r9 + adcxq %rcx, %r9 + movq %r8, 272(%rdi) + movq %r9, 280(%rdi) + movq 288(%rdi), %r8 + movq 296(%rdi), %r9 + # A[18] x A[18] + movq 144(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adcxq %rax, %r8 + adoxq %r9, %r9 + adcxq %rcx, %r9 + movq %r8, 288(%rdi) + movq %r9, 296(%rdi) + movq 304(%rdi), %r8 + movq 312(%rdi), %r9 + # A[19] x A[19] + movq 152(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adcxq %rax, %r8 + adoxq %r9, %r9 + adcxq %rcx, %r9 + movq %r8, 304(%rdi) + movq %r9, 312(%rdi) + movq 320(%rdi), %r8 + movq 328(%rdi), %r9 + # A[20] x A[20] + movq 160(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adcxq %rax, %r8 + adoxq %r9, %r9 + adcxq %rcx, %r9 + movq %r8, 320(%rdi) + movq %r9, 328(%rdi) + movq 336(%rdi), %r8 + movq 344(%rdi), %r9 + # A[21] x A[21] + movq 168(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adcxq %rax, %r8 + adoxq %r9, %r9 + adcxq %rcx, %r9 + movq %r8, 336(%rdi) + movq %r9, 344(%rdi) + movq 352(%rdi), %r8 + movq 360(%rdi), %r9 + # A[22] x A[22] + movq 176(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adcxq %rax, %r8 + adoxq %r9, %r9 + adcxq %rcx, %r9 + movq %r8, 352(%rdi) + movq %r9, 360(%rdi) + movq 368(%rdi), %r8 + movq 376(%rdi), %r9 + # A[23] x A[23] + movq 184(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adoxq %r8, %r8 + adcxq %rax, %r8 + adoxq %r9, %r9 + adcxq %rcx, %r9 + movq %r8, 368(%rdi) + movq %r9, 376(%rdi) + cmpq %rdi, %rsi + jne L_end_3072_sqr_avx2_24 + movq (%rbp), %r8 + movq 8(%rbp), %r9 + movq 16(%rbp), %r10 + movq 24(%rbp), %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq 32(%rbp), %r8 + movq 40(%rbp), %r9 + movq 48(%rbp), %r10 + movq 56(%rbp), %r11 + movq %r8, 32(%rdi) + movq %r9, 40(%rdi) + movq %r10, 48(%rdi) + movq %r11, 56(%rdi) + movq 64(%rbp), %r8 + movq 72(%rbp), %r9 + movq 80(%rbp), %r10 + movq 88(%rbp), %r11 + movq %r8, 64(%rdi) + movq %r9, 72(%rdi) + movq %r10, 80(%rdi) + movq %r11, 88(%rdi) + movq 96(%rbp), %r8 + movq 104(%rbp), %r9 + movq 112(%rbp), %r10 + movq 120(%rbp), %r11 + movq %r8, 96(%rdi) + movq %r9, 104(%rdi) + movq %r10, 112(%rdi) + movq %r11, 120(%rdi) + movq 128(%rbp), %r8 + movq 136(%rbp), %r9 + movq 144(%rbp), %r10 + movq 152(%rbp), %r11 + movq %r8, 128(%rdi) + movq %r9, 136(%rdi) + movq %r10, 144(%rdi) + movq %r11, 152(%rdi) + movq 160(%rbp), %r8 + movq 168(%rbp), %r9 + movq 176(%rbp), %r10 + movq 184(%rbp), %r11 + movq %r8, 160(%rdi) + movq %r9, 168(%rdi) + movq %r10, 176(%rdi) + movq %r11, 184(%rdi) +L_end_3072_sqr_avx2_24: + addq $192, %rsp + pop %r13 + pop %r12 + pop %rbp + repz retq +#ifndef __APPLE__ +.size sp_3072_sqr_avx2_24,.-sp_3072_sqr_avx2_24 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_3072_add_24 +.type sp_3072_add_24,@function +.align 16 +sp_3072_add_24: +#else +.globl _sp_3072_add_24 +.p2align 4 +_sp_3072_add_24: +#endif /* __APPLE__ */ + xorq %rax, %rax + movq (%rsi), %rcx + addq (%rdx), %rcx + movq %rcx, (%rdi) + movq 8(%rsi), %rcx + adcq 8(%rdx), %rcx + movq %rcx, 8(%rdi) + movq 16(%rsi), %rcx + adcq 16(%rdx), %rcx + movq %rcx, 16(%rdi) + movq 24(%rsi), %rcx + adcq 24(%rdx), %rcx + movq %rcx, 24(%rdi) + movq 32(%rsi), %rcx + adcq 32(%rdx), %rcx + movq %rcx, 32(%rdi) + movq 40(%rsi), %rcx + adcq 40(%rdx), %rcx + movq %rcx, 40(%rdi) + movq 48(%rsi), %rcx + adcq 48(%rdx), %rcx + movq %rcx, 48(%rdi) + movq 56(%rsi), %rcx + adcq 56(%rdx), %rcx + movq %rcx, 56(%rdi) + movq 64(%rsi), %rcx + adcq 64(%rdx), %rcx + movq %rcx, 64(%rdi) + movq 72(%rsi), %rcx + adcq 72(%rdx), %rcx + movq %rcx, 72(%rdi) + movq 80(%rsi), %rcx + adcq 80(%rdx), %rcx + movq %rcx, 80(%rdi) + movq 88(%rsi), %rcx + adcq 88(%rdx), %rcx + movq %rcx, 88(%rdi) + movq 96(%rsi), %rcx + adcq 96(%rdx), %rcx + movq %rcx, 96(%rdi) + movq 104(%rsi), %rcx + adcq 104(%rdx), %rcx + movq %rcx, 104(%rdi) + movq 112(%rsi), %rcx + adcq 112(%rdx), %rcx + movq %rcx, 112(%rdi) + movq 120(%rsi), %rcx + adcq 120(%rdx), %rcx + movq %rcx, 120(%rdi) + movq 128(%rsi), %rcx + adcq 128(%rdx), %rcx + movq %rcx, 128(%rdi) + movq 136(%rsi), %rcx + adcq 136(%rdx), %rcx + movq %rcx, 136(%rdi) + movq 144(%rsi), %rcx + adcq 144(%rdx), %rcx + movq %rcx, 144(%rdi) + movq 152(%rsi), %rcx + adcq 152(%rdx), %rcx + movq %rcx, 152(%rdi) + movq 160(%rsi), %rcx + adcq 160(%rdx), %rcx + movq %rcx, 160(%rdi) + movq 168(%rsi), %rcx + adcq 168(%rdx), %rcx + movq %rcx, 168(%rdi) + movq 176(%rsi), %rcx + adcq 176(%rdx), %rcx + movq %rcx, 176(%rdi) + movq 184(%rsi), %rcx + adcq 184(%rdx), %rcx + movq %rcx, 184(%rdi) + adcq $0, %rax + repz retq +#ifndef __APPLE__ +.size sp_3072_add_24,.-sp_3072_add_24 +#endif /* __APPLE__ */ +/* Sub b from a into a. (a -= b) + * + * a A single precision integer and result. + * b A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_3072_sub_in_place_48 +.type sp_3072_sub_in_place_48,@function +.align 16 +sp_3072_sub_in_place_48: +#else +.globl _sp_3072_sub_in_place_48 +.p2align 4 +_sp_3072_sub_in_place_48: +#endif /* __APPLE__ */ + xorq %rax, %rax + movq (%rdi), %rdx + movq 8(%rdi), %rcx + movq (%rsi), %r8 + movq 8(%rsi), %r9 + subq %r8, %rdx + movq 16(%rsi), %r8 + movq %rdx, (%rdi) + movq 16(%rdi), %rdx + sbbq %r9, %rcx + movq 24(%rsi), %r9 + movq %rcx, 8(%rdi) + movq 24(%rdi), %rcx + sbbq %r8, %rdx + movq 32(%rsi), %r8 + movq %rdx, 16(%rdi) + movq 32(%rdi), %rdx + sbbq %r9, %rcx + movq 40(%rsi), %r9 + movq %rcx, 24(%rdi) + movq 40(%rdi), %rcx + sbbq %r8, %rdx + movq 48(%rsi), %r8 + movq %rdx, 32(%rdi) + movq 48(%rdi), %rdx + sbbq %r9, %rcx + movq 56(%rsi), %r9 + movq %rcx, 40(%rdi) + movq 56(%rdi), %rcx + sbbq %r8, %rdx + movq 64(%rsi), %r8 + movq %rdx, 48(%rdi) + movq 64(%rdi), %rdx + sbbq %r9, %rcx + movq 72(%rsi), %r9 + movq %rcx, 56(%rdi) + movq 72(%rdi), %rcx + sbbq %r8, %rdx + movq 80(%rsi), %r8 + movq %rdx, 64(%rdi) + movq 80(%rdi), %rdx + sbbq %r9, %rcx + movq 88(%rsi), %r9 + movq %rcx, 72(%rdi) + movq 88(%rdi), %rcx + sbbq %r8, %rdx + movq 96(%rsi), %r8 + movq %rdx, 80(%rdi) + movq 96(%rdi), %rdx + sbbq %r9, %rcx + movq 104(%rsi), %r9 + movq %rcx, 88(%rdi) + movq 104(%rdi), %rcx + sbbq %r8, %rdx + movq 112(%rsi), %r8 + movq %rdx, 96(%rdi) + movq 112(%rdi), %rdx + sbbq %r9, %rcx + movq 120(%rsi), %r9 + movq %rcx, 104(%rdi) + movq 120(%rdi), %rcx + sbbq %r8, %rdx + movq 128(%rsi), %r8 + movq %rdx, 112(%rdi) + movq 128(%rdi), %rdx + sbbq %r9, %rcx + movq 136(%rsi), %r9 + movq %rcx, 120(%rdi) + movq 136(%rdi), %rcx + sbbq %r8, %rdx + movq 144(%rsi), %r8 + movq %rdx, 128(%rdi) + movq 144(%rdi), %rdx + sbbq %r9, %rcx + movq 152(%rsi), %r9 + movq %rcx, 136(%rdi) + movq 152(%rdi), %rcx + sbbq %r8, %rdx + movq 160(%rsi), %r8 + movq %rdx, 144(%rdi) + movq 160(%rdi), %rdx + sbbq %r9, %rcx + movq 168(%rsi), %r9 + movq %rcx, 152(%rdi) + movq 168(%rdi), %rcx + sbbq %r8, %rdx + movq 176(%rsi), %r8 + movq %rdx, 160(%rdi) + movq 176(%rdi), %rdx + sbbq %r9, %rcx + movq 184(%rsi), %r9 + movq %rcx, 168(%rdi) + movq 184(%rdi), %rcx + sbbq %r8, %rdx + movq 192(%rsi), %r8 + movq %rdx, 176(%rdi) + movq 192(%rdi), %rdx + sbbq %r9, %rcx + movq 200(%rsi), %r9 + movq %rcx, 184(%rdi) + movq 200(%rdi), %rcx + sbbq %r8, %rdx + movq 208(%rsi), %r8 + movq %rdx, 192(%rdi) + movq 208(%rdi), %rdx + sbbq %r9, %rcx + movq 216(%rsi), %r9 + movq %rcx, 200(%rdi) + movq 216(%rdi), %rcx + sbbq %r8, %rdx + movq 224(%rsi), %r8 + movq %rdx, 208(%rdi) + movq 224(%rdi), %rdx + sbbq %r9, %rcx + movq 232(%rsi), %r9 + movq %rcx, 216(%rdi) + movq 232(%rdi), %rcx + sbbq %r8, %rdx + movq 240(%rsi), %r8 + movq %rdx, 224(%rdi) + movq 240(%rdi), %rdx + sbbq %r9, %rcx + movq 248(%rsi), %r9 + movq %rcx, 232(%rdi) + movq 248(%rdi), %rcx + sbbq %r8, %rdx + movq 256(%rsi), %r8 + movq %rdx, 240(%rdi) + movq 256(%rdi), %rdx + sbbq %r9, %rcx + movq 264(%rsi), %r9 + movq %rcx, 248(%rdi) + movq 264(%rdi), %rcx + sbbq %r8, %rdx + movq 272(%rsi), %r8 + movq %rdx, 256(%rdi) + movq 272(%rdi), %rdx + sbbq %r9, %rcx + movq 280(%rsi), %r9 + movq %rcx, 264(%rdi) + movq 280(%rdi), %rcx + sbbq %r8, %rdx + movq 288(%rsi), %r8 + movq %rdx, 272(%rdi) + movq 288(%rdi), %rdx + sbbq %r9, %rcx + movq 296(%rsi), %r9 + movq %rcx, 280(%rdi) + movq 296(%rdi), %rcx + sbbq %r8, %rdx + movq 304(%rsi), %r8 + movq %rdx, 288(%rdi) + movq 304(%rdi), %rdx + sbbq %r9, %rcx + movq 312(%rsi), %r9 + movq %rcx, 296(%rdi) + movq 312(%rdi), %rcx + sbbq %r8, %rdx + movq 320(%rsi), %r8 + movq %rdx, 304(%rdi) + movq 320(%rdi), %rdx + sbbq %r9, %rcx + movq 328(%rsi), %r9 + movq %rcx, 312(%rdi) + movq 328(%rdi), %rcx + sbbq %r8, %rdx + movq 336(%rsi), %r8 + movq %rdx, 320(%rdi) + movq 336(%rdi), %rdx + sbbq %r9, %rcx + movq 344(%rsi), %r9 + movq %rcx, 328(%rdi) + movq 344(%rdi), %rcx + sbbq %r8, %rdx + movq 352(%rsi), %r8 + movq %rdx, 336(%rdi) + movq 352(%rdi), %rdx + sbbq %r9, %rcx + movq 360(%rsi), %r9 + movq %rcx, 344(%rdi) + movq 360(%rdi), %rcx + sbbq %r8, %rdx + movq 368(%rsi), %r8 + movq %rdx, 352(%rdi) + movq 368(%rdi), %rdx + sbbq %r9, %rcx + movq 376(%rsi), %r9 + movq %rcx, 360(%rdi) + movq 376(%rdi), %rcx + sbbq %r8, %rdx + movq %rdx, 368(%rdi) + sbbq %r9, %rcx + movq %rcx, 376(%rdi) + sbbq $0, %rax + repz retq +#ifndef __APPLE__ +.size sp_3072_sub_in_place_48,.-sp_3072_sub_in_place_48 +#endif /* __APPLE__ */ +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_3072_add_48 +.type sp_3072_add_48,@function +.align 16 +sp_3072_add_48: +#else +.globl _sp_3072_add_48 +.p2align 4 +_sp_3072_add_48: +#endif /* __APPLE__ */ + xorq %rax, %rax + movq (%rsi), %rcx + addq (%rdx), %rcx + movq %rcx, (%rdi) + movq 8(%rsi), %rcx + adcq 8(%rdx), %rcx + movq %rcx, 8(%rdi) + movq 16(%rsi), %rcx + adcq 16(%rdx), %rcx + movq %rcx, 16(%rdi) + movq 24(%rsi), %rcx + adcq 24(%rdx), %rcx + movq %rcx, 24(%rdi) + movq 32(%rsi), %rcx + adcq 32(%rdx), %rcx + movq %rcx, 32(%rdi) + movq 40(%rsi), %rcx + adcq 40(%rdx), %rcx + movq %rcx, 40(%rdi) + movq 48(%rsi), %rcx + adcq 48(%rdx), %rcx + movq %rcx, 48(%rdi) + movq 56(%rsi), %rcx + adcq 56(%rdx), %rcx + movq %rcx, 56(%rdi) + movq 64(%rsi), %rcx + adcq 64(%rdx), %rcx + movq %rcx, 64(%rdi) + movq 72(%rsi), %rcx + adcq 72(%rdx), %rcx + movq %rcx, 72(%rdi) + movq 80(%rsi), %rcx + adcq 80(%rdx), %rcx + movq %rcx, 80(%rdi) + movq 88(%rsi), %rcx + adcq 88(%rdx), %rcx + movq %rcx, 88(%rdi) + movq 96(%rsi), %rcx + adcq 96(%rdx), %rcx + movq %rcx, 96(%rdi) + movq 104(%rsi), %rcx + adcq 104(%rdx), %rcx + movq %rcx, 104(%rdi) + movq 112(%rsi), %rcx + adcq 112(%rdx), %rcx + movq %rcx, 112(%rdi) + movq 120(%rsi), %rcx + adcq 120(%rdx), %rcx + movq %rcx, 120(%rdi) + movq 128(%rsi), %rcx + adcq 128(%rdx), %rcx + movq %rcx, 128(%rdi) + movq 136(%rsi), %rcx + adcq 136(%rdx), %rcx + movq %rcx, 136(%rdi) + movq 144(%rsi), %rcx + adcq 144(%rdx), %rcx + movq %rcx, 144(%rdi) + movq 152(%rsi), %rcx + adcq 152(%rdx), %rcx + movq %rcx, 152(%rdi) + movq 160(%rsi), %rcx + adcq 160(%rdx), %rcx + movq %rcx, 160(%rdi) + movq 168(%rsi), %rcx + adcq 168(%rdx), %rcx + movq %rcx, 168(%rdi) + movq 176(%rsi), %rcx + adcq 176(%rdx), %rcx + movq %rcx, 176(%rdi) + movq 184(%rsi), %rcx + adcq 184(%rdx), %rcx + movq %rcx, 184(%rdi) + movq 192(%rsi), %rcx + adcq 192(%rdx), %rcx + movq %rcx, 192(%rdi) + movq 200(%rsi), %rcx + adcq 200(%rdx), %rcx + movq %rcx, 200(%rdi) + movq 208(%rsi), %rcx + adcq 208(%rdx), %rcx + movq %rcx, 208(%rdi) + movq 216(%rsi), %rcx + adcq 216(%rdx), %rcx + movq %rcx, 216(%rdi) + movq 224(%rsi), %rcx + adcq 224(%rdx), %rcx + movq %rcx, 224(%rdi) + movq 232(%rsi), %rcx + adcq 232(%rdx), %rcx + movq %rcx, 232(%rdi) + movq 240(%rsi), %rcx + adcq 240(%rdx), %rcx + movq %rcx, 240(%rdi) + movq 248(%rsi), %rcx + adcq 248(%rdx), %rcx + movq %rcx, 248(%rdi) + movq 256(%rsi), %rcx + adcq 256(%rdx), %rcx + movq %rcx, 256(%rdi) + movq 264(%rsi), %rcx + adcq 264(%rdx), %rcx + movq %rcx, 264(%rdi) + movq 272(%rsi), %rcx + adcq 272(%rdx), %rcx + movq %rcx, 272(%rdi) + movq 280(%rsi), %rcx + adcq 280(%rdx), %rcx + movq %rcx, 280(%rdi) + movq 288(%rsi), %rcx + adcq 288(%rdx), %rcx + movq %rcx, 288(%rdi) + movq 296(%rsi), %rcx + adcq 296(%rdx), %rcx + movq %rcx, 296(%rdi) + movq 304(%rsi), %rcx + adcq 304(%rdx), %rcx + movq %rcx, 304(%rdi) + movq 312(%rsi), %rcx + adcq 312(%rdx), %rcx + movq %rcx, 312(%rdi) + movq 320(%rsi), %rcx + adcq 320(%rdx), %rcx + movq %rcx, 320(%rdi) + movq 328(%rsi), %rcx + adcq 328(%rdx), %rcx + movq %rcx, 328(%rdi) + movq 336(%rsi), %rcx + adcq 336(%rdx), %rcx + movq %rcx, 336(%rdi) + movq 344(%rsi), %rcx + adcq 344(%rdx), %rcx + movq %rcx, 344(%rdi) + movq 352(%rsi), %rcx + adcq 352(%rdx), %rcx + movq %rcx, 352(%rdi) + movq 360(%rsi), %rcx + adcq 360(%rdx), %rcx + movq %rcx, 360(%rdi) + movq 368(%rsi), %rcx + adcq 368(%rdx), %rcx + movq %rcx, 368(%rdi) + movq 376(%rsi), %rcx + adcq 376(%rdx), %rcx + movq %rcx, 376(%rdi) + adcq $0, %rax + repz retq +#ifndef __APPLE__ +.size sp_3072_add_48,.-sp_3072_add_48 +#endif /* __APPLE__ */ +/* Mul a by digit b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision digit. + */ +#ifndef __APPLE__ +.globl sp_3072_mul_d_48 +.type sp_3072_mul_d_48,@function +.align 16 +sp_3072_mul_d_48: +#else +.globl _sp_3072_mul_d_48 +.p2align 4 +_sp_3072_mul_d_48: +#endif /* __APPLE__ */ + movq %rdx, %rcx + # A[0] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + movq %r8, (%rdi) + # A[1] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 8(%rsi) + addq %rax, %r9 + movq %r9, 8(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[2] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 16(%rsi) + addq %rax, %r10 + movq %r10, 16(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[3] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 24(%rsi) + addq %rax, %r8 + movq %r8, 24(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[4] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 32(%rsi) + addq %rax, %r9 + movq %r9, 32(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[5] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 40(%rsi) + addq %rax, %r10 + movq %r10, 40(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[6] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 48(%rsi) + addq %rax, %r8 + movq %r8, 48(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[7] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 56(%rsi) + addq %rax, %r9 + movq %r9, 56(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[8] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 64(%rsi) + addq %rax, %r10 + movq %r10, 64(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[9] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 72(%rsi) + addq %rax, %r8 + movq %r8, 72(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[10] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 80(%rsi) + addq %rax, %r9 + movq %r9, 80(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[11] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 88(%rsi) + addq %rax, %r10 + movq %r10, 88(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[12] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 96(%rsi) + addq %rax, %r8 + movq %r8, 96(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[13] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 104(%rsi) + addq %rax, %r9 + movq %r9, 104(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[14] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 112(%rsi) + addq %rax, %r10 + movq %r10, 112(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[15] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 120(%rsi) + addq %rax, %r8 + movq %r8, 120(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[16] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 128(%rsi) + addq %rax, %r9 + movq %r9, 128(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[17] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 136(%rsi) + addq %rax, %r10 + movq %r10, 136(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[18] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 144(%rsi) + addq %rax, %r8 + movq %r8, 144(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[19] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 152(%rsi) + addq %rax, %r9 + movq %r9, 152(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[20] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 160(%rsi) + addq %rax, %r10 + movq %r10, 160(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[21] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 168(%rsi) + addq %rax, %r8 + movq %r8, 168(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[22] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 176(%rsi) + addq %rax, %r9 + movq %r9, 176(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[23] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 184(%rsi) + addq %rax, %r10 + movq %r10, 184(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[24] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 192(%rsi) + addq %rax, %r8 + movq %r8, 192(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[25] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 200(%rsi) + addq %rax, %r9 + movq %r9, 200(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[26] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 208(%rsi) + addq %rax, %r10 + movq %r10, 208(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[27] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 216(%rsi) + addq %rax, %r8 + movq %r8, 216(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[28] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 224(%rsi) + addq %rax, %r9 + movq %r9, 224(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[29] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 232(%rsi) + addq %rax, %r10 + movq %r10, 232(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[30] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 240(%rsi) + addq %rax, %r8 + movq %r8, 240(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[31] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 248(%rsi) + addq %rax, %r9 + movq %r9, 248(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[32] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 256(%rsi) + addq %rax, %r10 + movq %r10, 256(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[33] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 264(%rsi) + addq %rax, %r8 + movq %r8, 264(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[34] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 272(%rsi) + addq %rax, %r9 + movq %r9, 272(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[35] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 280(%rsi) + addq %rax, %r10 + movq %r10, 280(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[36] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 288(%rsi) + addq %rax, %r8 + movq %r8, 288(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[37] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 296(%rsi) + addq %rax, %r9 + movq %r9, 296(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[38] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 304(%rsi) + addq %rax, %r10 + movq %r10, 304(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[39] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 312(%rsi) + addq %rax, %r8 + movq %r8, 312(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[40] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 320(%rsi) + addq %rax, %r9 + movq %r9, 320(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[41] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 328(%rsi) + addq %rax, %r10 + movq %r10, 328(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[42] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 336(%rsi) + addq %rax, %r8 + movq %r8, 336(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[43] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 344(%rsi) + addq %rax, %r9 + movq %r9, 344(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[44] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 352(%rsi) + addq %rax, %r10 + movq %r10, 352(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[45] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 360(%rsi) + addq %rax, %r8 + movq %r8, 360(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[46] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 368(%rsi) + addq %rax, %r9 + movq %r9, 368(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # # A[47] * B + movq %rcx, %rax + mulq 376(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + movq %r10, 376(%rdi) + movq %r8, 384(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_3072_mul_d_48,.-sp_3072_mul_d_48 +#endif /* __APPLE__ */ +/* Sub b from a into a. (a -= b) + * + * a A single precision integer and result. + * b A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_3072_sub_in_place_24 +.type sp_3072_sub_in_place_24,@function +.align 16 +sp_3072_sub_in_place_24: +#else +.globl _sp_3072_sub_in_place_24 +.p2align 4 +_sp_3072_sub_in_place_24: +#endif /* __APPLE__ */ + xorq %rax, %rax + movq (%rdi), %rdx + movq 8(%rdi), %rcx + movq (%rsi), %r8 + movq 8(%rsi), %r9 + subq %r8, %rdx + movq 16(%rsi), %r8 + movq %rdx, (%rdi) + movq 16(%rdi), %rdx + sbbq %r9, %rcx + movq 24(%rsi), %r9 + movq %rcx, 8(%rdi) + movq 24(%rdi), %rcx + sbbq %r8, %rdx + movq 32(%rsi), %r8 + movq %rdx, 16(%rdi) + movq 32(%rdi), %rdx + sbbq %r9, %rcx + movq 40(%rsi), %r9 + movq %rcx, 24(%rdi) + movq 40(%rdi), %rcx + sbbq %r8, %rdx + movq 48(%rsi), %r8 + movq %rdx, 32(%rdi) + movq 48(%rdi), %rdx + sbbq %r9, %rcx + movq 56(%rsi), %r9 + movq %rcx, 40(%rdi) + movq 56(%rdi), %rcx + sbbq %r8, %rdx + movq 64(%rsi), %r8 + movq %rdx, 48(%rdi) + movq 64(%rdi), %rdx + sbbq %r9, %rcx + movq 72(%rsi), %r9 + movq %rcx, 56(%rdi) + movq 72(%rdi), %rcx + sbbq %r8, %rdx + movq 80(%rsi), %r8 + movq %rdx, 64(%rdi) + movq 80(%rdi), %rdx + sbbq %r9, %rcx + movq 88(%rsi), %r9 + movq %rcx, 72(%rdi) + movq 88(%rdi), %rcx + sbbq %r8, %rdx + movq 96(%rsi), %r8 + movq %rdx, 80(%rdi) + movq 96(%rdi), %rdx + sbbq %r9, %rcx + movq 104(%rsi), %r9 + movq %rcx, 88(%rdi) + movq 104(%rdi), %rcx + sbbq %r8, %rdx + movq 112(%rsi), %r8 + movq %rdx, 96(%rdi) + movq 112(%rdi), %rdx + sbbq %r9, %rcx + movq 120(%rsi), %r9 + movq %rcx, 104(%rdi) + movq 120(%rdi), %rcx + sbbq %r8, %rdx + movq 128(%rsi), %r8 + movq %rdx, 112(%rdi) + movq 128(%rdi), %rdx + sbbq %r9, %rcx + movq 136(%rsi), %r9 + movq %rcx, 120(%rdi) + movq 136(%rdi), %rcx + sbbq %r8, %rdx + movq 144(%rsi), %r8 + movq %rdx, 128(%rdi) + movq 144(%rdi), %rdx + sbbq %r9, %rcx + movq 152(%rsi), %r9 + movq %rcx, 136(%rdi) + movq 152(%rdi), %rcx + sbbq %r8, %rdx + movq 160(%rsi), %r8 + movq %rdx, 144(%rdi) + movq 160(%rdi), %rdx + sbbq %r9, %rcx + movq 168(%rsi), %r9 + movq %rcx, 152(%rdi) + movq 168(%rdi), %rcx + sbbq %r8, %rdx + movq 176(%rsi), %r8 + movq %rdx, 160(%rdi) + movq 176(%rdi), %rdx + sbbq %r9, %rcx + movq 184(%rsi), %r9 + movq %rcx, 168(%rdi) + movq 184(%rdi), %rcx + sbbq %r8, %rdx + movq %rdx, 176(%rdi) + sbbq %r9, %rcx + movq %rcx, 184(%rdi) + sbbq $0, %rax + repz retq +#ifndef __APPLE__ +.size sp_3072_sub_in_place_24,.-sp_3072_sub_in_place_24 +#endif /* __APPLE__ */ +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not copying. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +#ifndef __APPLE__ +.globl sp_3072_cond_sub_24 +.type sp_3072_cond_sub_24,@function +.align 16 +sp_3072_cond_sub_24: +#else +.globl _sp_3072_cond_sub_24 +.p2align 4 +_sp_3072_cond_sub_24: +#endif /* __APPLE__ */ + subq $192, %rsp + movq $0, %rax + movq (%rdx), %r8 + movq 8(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, (%rsp) + movq %r9, 8(%rsp) + movq 16(%rdx), %r8 + movq 24(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 16(%rsp) + movq %r9, 24(%rsp) + movq 32(%rdx), %r8 + movq 40(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 32(%rsp) + movq %r9, 40(%rsp) + movq 48(%rdx), %r8 + movq 56(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 48(%rsp) + movq %r9, 56(%rsp) + movq 64(%rdx), %r8 + movq 72(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 64(%rsp) + movq %r9, 72(%rsp) + movq 80(%rdx), %r8 + movq 88(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 80(%rsp) + movq %r9, 88(%rsp) + movq 96(%rdx), %r8 + movq 104(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 96(%rsp) + movq %r9, 104(%rsp) + movq 112(%rdx), %r8 + movq 120(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 112(%rsp) + movq %r9, 120(%rsp) + movq 128(%rdx), %r8 + movq 136(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 128(%rsp) + movq %r9, 136(%rsp) + movq 144(%rdx), %r8 + movq 152(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 144(%rsp) + movq %r9, 152(%rsp) + movq 160(%rdx), %r8 + movq 168(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 160(%rsp) + movq %r9, 168(%rsp) + movq 176(%rdx), %r8 + movq 184(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 176(%rsp) + movq %r9, 184(%rsp) + movq (%rsi), %r8 + movq (%rsp), %rdx + subq %rdx, %r8 + movq 8(%rsi), %r9 + movq 8(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, (%rdi) + movq 16(%rsi), %r8 + movq 16(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 8(%rdi) + movq 24(%rsi), %r9 + movq 24(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 16(%rdi) + movq 32(%rsi), %r8 + movq 32(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 24(%rdi) + movq 40(%rsi), %r9 + movq 40(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 32(%rdi) + movq 48(%rsi), %r8 + movq 48(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 40(%rdi) + movq 56(%rsi), %r9 + movq 56(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 48(%rdi) + movq 64(%rsi), %r8 + movq 64(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 56(%rdi) + movq 72(%rsi), %r9 + movq 72(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 64(%rdi) + movq 80(%rsi), %r8 + movq 80(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 72(%rdi) + movq 88(%rsi), %r9 + movq 88(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 80(%rdi) + movq 96(%rsi), %r8 + movq 96(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 88(%rdi) + movq 104(%rsi), %r9 + movq 104(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 96(%rdi) + movq 112(%rsi), %r8 + movq 112(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 104(%rdi) + movq 120(%rsi), %r9 + movq 120(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 112(%rdi) + movq 128(%rsi), %r8 + movq 128(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 120(%rdi) + movq 136(%rsi), %r9 + movq 136(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 128(%rdi) + movq 144(%rsi), %r8 + movq 144(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 136(%rdi) + movq 152(%rsi), %r9 + movq 152(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 144(%rdi) + movq 160(%rsi), %r8 + movq 160(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 152(%rdi) + movq 168(%rsi), %r9 + movq 168(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 160(%rdi) + movq 176(%rsi), %r8 + movq 176(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 168(%rdi) + movq 184(%rsi), %r9 + movq 184(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 176(%rdi) + movq %r9, 184(%rdi) + sbbq $0, %rax + addq $192, %rsp + repz retq +#ifndef __APPLE__ +.size sp_3072_cond_sub_24,.-sp_3072_cond_sub_24 +#endif /* __APPLE__ */ +/* Reduce the number back to 3072 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +#ifndef __APPLE__ +.globl sp_3072_mont_reduce_24 +.type sp_3072_mont_reduce_24,@function +.align 16 +sp_3072_mont_reduce_24: +#else +.globl _sp_3072_mont_reduce_24 +.p2align 4 +_sp_3072_mont_reduce_24: +#endif /* __APPLE__ */ + push %r12 + push %r13 + push %r14 + push %r15 + movq %rdx, %rcx + xorq %r15, %r15 + # i = 0 + movq $24, %r8 + movq (%rdi), %r13 + movq 8(%rdi), %r14 +L_mont_loop_24: + # mu = a[i] * mp + movq %r13, %r11 + imulq %rcx, %r11 + # a[i+0] += m[0] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq (%rsi) + addq %rax, %r13 + adcq %rdx, %r10 + # a[i+1] += m[1] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 8(%rsi) + movq %r14, %r13 + addq %rax, %r13 + adcq %rdx, %r9 + addq %r10, %r13 + adcq $0, %r9 + # a[i+2] += m[2] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 16(%rsi) + movq 16(%rdi), %r14 + addq %rax, %r14 + adcq %rdx, %r10 + addq %r9, %r14 + adcq $0, %r10 + # a[i+3] += m[3] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 24(%rsi) + movq 24(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 24(%rdi) + adcq $0, %r9 + # a[i+4] += m[4] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 32(%rsi) + movq 32(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 32(%rdi) + adcq $0, %r10 + # a[i+5] += m[5] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 40(%rsi) + movq 40(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 40(%rdi) + adcq $0, %r9 + # a[i+6] += m[6] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 48(%rsi) + movq 48(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 48(%rdi) + adcq $0, %r10 + # a[i+7] += m[7] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 56(%rsi) + movq 56(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 56(%rdi) + adcq $0, %r9 + # a[i+8] += m[8] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 64(%rsi) + movq 64(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 64(%rdi) + adcq $0, %r10 + # a[i+9] += m[9] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 72(%rsi) + movq 72(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 72(%rdi) + adcq $0, %r9 + # a[i+10] += m[10] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 80(%rsi) + movq 80(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 80(%rdi) + adcq $0, %r10 + # a[i+11] += m[11] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 88(%rsi) + movq 88(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 88(%rdi) + adcq $0, %r9 + # a[i+12] += m[12] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 96(%rsi) + movq 96(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 96(%rdi) + adcq $0, %r10 + # a[i+13] += m[13] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 104(%rsi) + movq 104(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 104(%rdi) + adcq $0, %r9 + # a[i+14] += m[14] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 112(%rsi) + movq 112(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 112(%rdi) + adcq $0, %r10 + # a[i+15] += m[15] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 120(%rsi) + movq 120(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 120(%rdi) + adcq $0, %r9 + # a[i+16] += m[16] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 128(%rsi) + movq 128(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 128(%rdi) + adcq $0, %r10 + # a[i+17] += m[17] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 136(%rsi) + movq 136(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 136(%rdi) + adcq $0, %r9 + # a[i+18] += m[18] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 144(%rsi) + movq 144(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 144(%rdi) + adcq $0, %r10 + # a[i+19] += m[19] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 152(%rsi) + movq 152(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 152(%rdi) + adcq $0, %r9 + # a[i+20] += m[20] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 160(%rsi) + movq 160(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 160(%rdi) + adcq $0, %r10 + # a[i+21] += m[21] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 168(%rsi) + movq 168(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 168(%rdi) + adcq $0, %r9 + # a[i+22] += m[22] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 176(%rsi) + movq 176(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 176(%rdi) + adcq $0, %r10 + # a[i+23] += m[23] * mu + movq %r11, %rax + mulq 184(%rsi) + movq 184(%rdi), %r12 + addq %rax, %r10 + adcq %r15, %rdx + movq $0, %r15 + adcq $0, %r15 + addq %r10, %r12 + movq %r12, 184(%rdi) + adcq %rdx, 192(%rdi) + adcq $0, %r15 + # i += 1 + addq $8, %rdi + decq %r8 + jnz L_mont_loop_24 + movq %r13, (%rdi) + movq %r14, 8(%rdi) + negq %r15 + movq %r15, %rcx + movq %rsi, %rdx + movq %rdi, %rsi + movq %rdi, %rdi + subq $192, %rdi +#ifndef __APPLE__ + callq sp_3072_cond_sub_24@plt +#else + callq _sp_3072_cond_sub_24 +#endif /* __APPLE__ */ + pop %r15 + pop %r14 + pop %r13 + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_3072_mont_reduce_24,.-sp_3072_mont_reduce_24 +#endif /* __APPLE__ */ +/* Mul a by digit b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision digit. + */ +#ifndef __APPLE__ +.globl sp_3072_mul_d_24 +.type sp_3072_mul_d_24,@function +.align 16 +sp_3072_mul_d_24: +#else +.globl _sp_3072_mul_d_24 +.p2align 4 +_sp_3072_mul_d_24: +#endif /* __APPLE__ */ + movq %rdx, %rcx + # A[0] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + movq %r8, (%rdi) + # A[1] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 8(%rsi) + addq %rax, %r9 + movq %r9, 8(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[2] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 16(%rsi) + addq %rax, %r10 + movq %r10, 16(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[3] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 24(%rsi) + addq %rax, %r8 + movq %r8, 24(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[4] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 32(%rsi) + addq %rax, %r9 + movq %r9, 32(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[5] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 40(%rsi) + addq %rax, %r10 + movq %r10, 40(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[6] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 48(%rsi) + addq %rax, %r8 + movq %r8, 48(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[7] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 56(%rsi) + addq %rax, %r9 + movq %r9, 56(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[8] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 64(%rsi) + addq %rax, %r10 + movq %r10, 64(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[9] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 72(%rsi) + addq %rax, %r8 + movq %r8, 72(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[10] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 80(%rsi) + addq %rax, %r9 + movq %r9, 80(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[11] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 88(%rsi) + addq %rax, %r10 + movq %r10, 88(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[12] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 96(%rsi) + addq %rax, %r8 + movq %r8, 96(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[13] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 104(%rsi) + addq %rax, %r9 + movq %r9, 104(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[14] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 112(%rsi) + addq %rax, %r10 + movq %r10, 112(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[15] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 120(%rsi) + addq %rax, %r8 + movq %r8, 120(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[16] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 128(%rsi) + addq %rax, %r9 + movq %r9, 128(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[17] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 136(%rsi) + addq %rax, %r10 + movq %r10, 136(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[18] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 144(%rsi) + addq %rax, %r8 + movq %r8, 144(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[19] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 152(%rsi) + addq %rax, %r9 + movq %r9, 152(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[20] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 160(%rsi) + addq %rax, %r10 + movq %r10, 160(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # A[21] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq 168(%rsi) + addq %rax, %r8 + movq %r8, 168(%rdi) + adcq %rdx, %r9 + adcq $0, %r10 + # A[22] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 176(%rsi) + addq %rax, %r9 + movq %r9, 176(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # # A[23] * B + movq %rcx, %rax + mulq 184(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + movq %r10, 184(%rdi) + movq %r8, 192(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_3072_mul_d_24,.-sp_3072_mul_d_24 +#endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 +/* Mul a by digit b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision digit. + */ +#ifndef __APPLE__ +.globl sp_3072_mul_d_avx2_24 +.type sp_3072_mul_d_avx2_24,@function +.align 16 +sp_3072_mul_d_avx2_24: +#else +.globl _sp_3072_mul_d_avx2_24 +.p2align 4 +_sp_3072_mul_d_avx2_24: +#endif /* __APPLE__ */ + movq %rdx, %rax + # A[0] * B + movq %rax, %rdx + xorq %r11, %r11 + mulxq (%rsi), %r9, %r10 + movq %r9, (%rdi) + # A[1] * B + mulxq 8(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 8(%rdi) + adoxq %r8, %r9 + # A[2] * B + mulxq 16(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 16(%rdi) + adoxq %r8, %r10 + # A[3] * B + mulxq 24(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 24(%rdi) + adoxq %r8, %r9 + # A[4] * B + mulxq 32(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 32(%rdi) + adoxq %r8, %r10 + # A[5] * B + mulxq 40(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 40(%rdi) + adoxq %r8, %r9 + # A[6] * B + mulxq 48(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 48(%rdi) + adoxq %r8, %r10 + # A[7] * B + mulxq 56(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 56(%rdi) + adoxq %r8, %r9 + # A[8] * B + mulxq 64(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 64(%rdi) + adoxq %r8, %r10 + # A[9] * B + mulxq 72(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 72(%rdi) + adoxq %r8, %r9 + # A[10] * B + mulxq 80(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 80(%rdi) + adoxq %r8, %r10 + # A[11] * B + mulxq 88(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 88(%rdi) + adoxq %r8, %r9 + # A[12] * B + mulxq 96(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 96(%rdi) + adoxq %r8, %r10 + # A[13] * B + mulxq 104(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 104(%rdi) + adoxq %r8, %r9 + # A[14] * B + mulxq 112(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 112(%rdi) + adoxq %r8, %r10 + # A[15] * B + mulxq 120(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 120(%rdi) + adoxq %r8, %r9 + # A[16] * B + mulxq 128(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 128(%rdi) + adoxq %r8, %r10 + # A[17] * B + mulxq 136(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 136(%rdi) + adoxq %r8, %r9 + # A[18] * B + mulxq 144(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 144(%rdi) + adoxq %r8, %r10 + # A[19] * B + mulxq 152(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 152(%rdi) + adoxq %r8, %r9 + # A[20] * B + mulxq 160(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 160(%rdi) + adoxq %r8, %r10 + # A[21] * B + mulxq 168(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 168(%rdi) + adoxq %r8, %r9 + # A[22] * B + mulxq 176(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 176(%rdi) + adoxq %r8, %r10 + # A[23] * B + mulxq 184(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + adoxq %r8, %r9 + adcxq %r11, %r9 + movq %r10, 184(%rdi) + movq %r9, 192(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_3072_mul_d_avx2_24,.-sp_3072_mul_d_avx2_24 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +#ifndef __APPLE__ +.globl sp_3072_cmp_24 +.type sp_3072_cmp_24,@function +.align 16 +sp_3072_cmp_24: +#else +.globl _sp_3072_cmp_24 +.p2align 4 +_sp_3072_cmp_24: +#endif /* __APPLE__ */ + xorq %rcx, %rcx + movq $-1, %rdx + movq $-1, %rax + movq $1, %r8 + movq 184(%rdi), %r9 + movq 184(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 176(%rdi), %r9 + movq 176(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 168(%rdi), %r9 + movq 168(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 160(%rdi), %r9 + movq 160(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 152(%rdi), %r9 + movq 152(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 144(%rdi), %r9 + movq 144(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 136(%rdi), %r9 + movq 136(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 128(%rdi), %r9 + movq 128(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 120(%rdi), %r9 + movq 120(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 112(%rdi), %r9 + movq 112(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 104(%rdi), %r9 + movq 104(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 96(%rdi), %r9 + movq 96(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 88(%rdi), %r9 + movq 88(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 80(%rdi), %r9 + movq 80(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 72(%rdi), %r9 + movq 72(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 64(%rdi), %r9 + movq 64(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 56(%rdi), %r9 + movq 56(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 48(%rdi), %r9 + movq 48(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 40(%rdi), %r9 + movq 40(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 32(%rdi), %r9 + movq 32(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 24(%rdi), %r9 + movq 24(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 16(%rdi), %r9 + movq 16(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 8(%rdi), %r9 + movq 8(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq (%rdi), %r9 + movq (%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + xorq %rdx, %rax + repz retq +#ifndef __APPLE__ +.size sp_3072_cmp_24,.-sp_3072_cmp_24 +#endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 +/* Reduce the number back to 3072 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +#ifndef __APPLE__ +.globl sp_3072_mont_reduce_avx2_24 +.type sp_3072_mont_reduce_avx2_24,@function +.align 16 +sp_3072_mont_reduce_avx2_24: +#else +.globl _sp_3072_mont_reduce_avx2_24 +.p2align 4 +_sp_3072_mont_reduce_avx2_24: +#endif /* __APPLE__ */ + push %r12 + push %r13 + push %r14 + movq %rdx, %rax + xorq %r14, %r14 + # i = 0 + movq $24, %r9 + movq (%rdi), %r13 + xorq %r12, %r12 +L_mont_loop_avx2_24: + # mu = a[i] * mp + movq %r13, %rdx + mulxq %rax, %rdx, %r8 + movq %r13, %r10 + # a[i+0] += m[0] * mu + mulxq (%rsi), %rcx, %r8 + movq 8(%rdi), %r13 + adcxq %rcx, %r10 + adoxq %r8, %r13 + # a[i+1] += m[1] * mu + mulxq 8(%rsi), %rcx, %r8 + movq 16(%rdi), %r10 + adcxq %rcx, %r13 + adoxq %r8, %r10 + # a[i+2] += m[2] * mu + mulxq 16(%rsi), %rcx, %r8 + movq 24(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 16(%rdi) + # a[i+3] += m[3] * mu + mulxq 24(%rsi), %rcx, %r8 + movq 32(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 24(%rdi) + # a[i+4] += m[4] * mu + mulxq 32(%rsi), %rcx, %r8 + movq 40(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 32(%rdi) + # a[i+5] += m[5] * mu + mulxq 40(%rsi), %rcx, %r8 + movq 48(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 40(%rdi) + # a[i+6] += m[6] * mu + mulxq 48(%rsi), %rcx, %r8 + movq 56(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 48(%rdi) + # a[i+7] += m[7] * mu + mulxq 56(%rsi), %rcx, %r8 + movq 64(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 56(%rdi) + # a[i+8] += m[8] * mu + mulxq 64(%rsi), %rcx, %r8 + movq 72(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 64(%rdi) + # a[i+9] += m[9] * mu + mulxq 72(%rsi), %rcx, %r8 + movq 80(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 72(%rdi) + # a[i+10] += m[10] * mu + mulxq 80(%rsi), %rcx, %r8 + movq 88(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 80(%rdi) + # a[i+11] += m[11] * mu + mulxq 88(%rsi), %rcx, %r8 + movq 96(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 88(%rdi) + # a[i+12] += m[12] * mu + mulxq 96(%rsi), %rcx, %r8 + movq 104(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 96(%rdi) + # a[i+13] += m[13] * mu + mulxq 104(%rsi), %rcx, %r8 + movq 112(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 104(%rdi) + # a[i+14] += m[14] * mu + mulxq 112(%rsi), %rcx, %r8 + movq 120(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 112(%rdi) + # a[i+15] += m[15] * mu + mulxq 120(%rsi), %rcx, %r8 + movq 128(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 120(%rdi) + # a[i+16] += m[16] * mu + mulxq 128(%rsi), %rcx, %r8 + movq 136(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 128(%rdi) + # a[i+17] += m[17] * mu + mulxq 136(%rsi), %rcx, %r8 + movq 144(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 136(%rdi) + # a[i+18] += m[18] * mu + mulxq 144(%rsi), %rcx, %r8 + movq 152(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 144(%rdi) + # a[i+19] += m[19] * mu + mulxq 152(%rsi), %rcx, %r8 + movq 160(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 152(%rdi) + # a[i+20] += m[20] * mu + mulxq 160(%rsi), %rcx, %r8 + movq 168(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 160(%rdi) + # a[i+21] += m[21] * mu + mulxq 168(%rsi), %rcx, %r8 + movq 176(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 168(%rdi) + # a[i+22] += m[22] * mu + mulxq 176(%rsi), %rcx, %r8 + movq 184(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 176(%rdi) + # a[i+23] += m[23] * mu + mulxq 184(%rsi), %rcx, %r8 + movq 192(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 184(%rdi) + adcxq %r14, %r10 + movq %r12, %r14 + adoxq %r12, %r14 + adcxq %r12, %r14 + movq %r10, 192(%rdi) + # i += 1 + addq $8, %rdi + decq %r9 + jnz L_mont_loop_avx2_24 + movq %r13, (%rdi) + negq %r14 + movq %r14, %rcx + movq %rsi, %rdx + movq %rdi, %rsi + movq %rdi, %rdi + subq $192, %rdi +#ifndef __APPLE__ + callq sp_3072_cond_sub_24@plt +#else + callq _sp_3072_cond_sub_24 +#endif /* __APPLE__ */ + pop %r14 + pop %r13 + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_3072_mont_reduce_avx2_24,.-sp_3072_mont_reduce_avx2_24 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not copying. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +#ifndef __APPLE__ +.globl sp_3072_cond_sub_48 +.type sp_3072_cond_sub_48,@function +.align 16 +sp_3072_cond_sub_48: +#else +.globl _sp_3072_cond_sub_48 +.p2align 4 +_sp_3072_cond_sub_48: +#endif /* __APPLE__ */ + subq $384, %rsp + movq $0, %rax + movq (%rdx), %r8 + movq 8(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, (%rsp) + movq %r9, 8(%rsp) + movq 16(%rdx), %r8 + movq 24(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 16(%rsp) + movq %r9, 24(%rsp) + movq 32(%rdx), %r8 + movq 40(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 32(%rsp) + movq %r9, 40(%rsp) + movq 48(%rdx), %r8 + movq 56(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 48(%rsp) + movq %r9, 56(%rsp) + movq 64(%rdx), %r8 + movq 72(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 64(%rsp) + movq %r9, 72(%rsp) + movq 80(%rdx), %r8 + movq 88(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 80(%rsp) + movq %r9, 88(%rsp) + movq 96(%rdx), %r8 + movq 104(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 96(%rsp) + movq %r9, 104(%rsp) + movq 112(%rdx), %r8 + movq 120(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 112(%rsp) + movq %r9, 120(%rsp) + movq 128(%rdx), %r8 + movq 136(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 128(%rsp) + movq %r9, 136(%rsp) + movq 144(%rdx), %r8 + movq 152(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 144(%rsp) + movq %r9, 152(%rsp) + movq 160(%rdx), %r8 + movq 168(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 160(%rsp) + movq %r9, 168(%rsp) + movq 176(%rdx), %r8 + movq 184(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 176(%rsp) + movq %r9, 184(%rsp) + movq 192(%rdx), %r8 + movq 200(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 192(%rsp) + movq %r9, 200(%rsp) + movq 208(%rdx), %r8 + movq 216(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 208(%rsp) + movq %r9, 216(%rsp) + movq 224(%rdx), %r8 + movq 232(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 224(%rsp) + movq %r9, 232(%rsp) + movq 240(%rdx), %r8 + movq 248(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 240(%rsp) + movq %r9, 248(%rsp) + movq 256(%rdx), %r8 + movq 264(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 256(%rsp) + movq %r9, 264(%rsp) + movq 272(%rdx), %r8 + movq 280(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 272(%rsp) + movq %r9, 280(%rsp) + movq 288(%rdx), %r8 + movq 296(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 288(%rsp) + movq %r9, 296(%rsp) + movq 304(%rdx), %r8 + movq 312(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 304(%rsp) + movq %r9, 312(%rsp) + movq 320(%rdx), %r8 + movq 328(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 320(%rsp) + movq %r9, 328(%rsp) + movq 336(%rdx), %r8 + movq 344(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 336(%rsp) + movq %r9, 344(%rsp) + movq 352(%rdx), %r8 + movq 360(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 352(%rsp) + movq %r9, 360(%rsp) + movq 368(%rdx), %r8 + movq 376(%rdx), %r9 + andq %rcx, %r8 + andq %rcx, %r9 + movq %r8, 368(%rsp) + movq %r9, 376(%rsp) + movq (%rsi), %r8 + movq (%rsp), %rdx + subq %rdx, %r8 + movq 8(%rsi), %r9 + movq 8(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, (%rdi) + movq 16(%rsi), %r8 + movq 16(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 8(%rdi) + movq 24(%rsi), %r9 + movq 24(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 16(%rdi) + movq 32(%rsi), %r8 + movq 32(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 24(%rdi) + movq 40(%rsi), %r9 + movq 40(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 32(%rdi) + movq 48(%rsi), %r8 + movq 48(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 40(%rdi) + movq 56(%rsi), %r9 + movq 56(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 48(%rdi) + movq 64(%rsi), %r8 + movq 64(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 56(%rdi) + movq 72(%rsi), %r9 + movq 72(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 64(%rdi) + movq 80(%rsi), %r8 + movq 80(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 72(%rdi) + movq 88(%rsi), %r9 + movq 88(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 80(%rdi) + movq 96(%rsi), %r8 + movq 96(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 88(%rdi) + movq 104(%rsi), %r9 + movq 104(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 96(%rdi) + movq 112(%rsi), %r8 + movq 112(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 104(%rdi) + movq 120(%rsi), %r9 + movq 120(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 112(%rdi) + movq 128(%rsi), %r8 + movq 128(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 120(%rdi) + movq 136(%rsi), %r9 + movq 136(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 128(%rdi) + movq 144(%rsi), %r8 + movq 144(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 136(%rdi) + movq 152(%rsi), %r9 + movq 152(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 144(%rdi) + movq 160(%rsi), %r8 + movq 160(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 152(%rdi) + movq 168(%rsi), %r9 + movq 168(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 160(%rdi) + movq 176(%rsi), %r8 + movq 176(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 168(%rdi) + movq 184(%rsi), %r9 + movq 184(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 176(%rdi) + movq 192(%rsi), %r8 + movq 192(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 184(%rdi) + movq 200(%rsi), %r9 + movq 200(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 192(%rdi) + movq 208(%rsi), %r8 + movq 208(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 200(%rdi) + movq 216(%rsi), %r9 + movq 216(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 208(%rdi) + movq 224(%rsi), %r8 + movq 224(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 216(%rdi) + movq 232(%rsi), %r9 + movq 232(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 224(%rdi) + movq 240(%rsi), %r8 + movq 240(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 232(%rdi) + movq 248(%rsi), %r9 + movq 248(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 240(%rdi) + movq 256(%rsi), %r8 + movq 256(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 248(%rdi) + movq 264(%rsi), %r9 + movq 264(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 256(%rdi) + movq 272(%rsi), %r8 + movq 272(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 264(%rdi) + movq 280(%rsi), %r9 + movq 280(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 272(%rdi) + movq 288(%rsi), %r8 + movq 288(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 280(%rdi) + movq 296(%rsi), %r9 + movq 296(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 288(%rdi) + movq 304(%rsi), %r8 + movq 304(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 296(%rdi) + movq 312(%rsi), %r9 + movq 312(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 304(%rdi) + movq 320(%rsi), %r8 + movq 320(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 312(%rdi) + movq 328(%rsi), %r9 + movq 328(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 320(%rdi) + movq 336(%rsi), %r8 + movq 336(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 328(%rdi) + movq 344(%rsi), %r9 + movq 344(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 336(%rdi) + movq 352(%rsi), %r8 + movq 352(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 344(%rdi) + movq 360(%rsi), %r9 + movq 360(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 352(%rdi) + movq 368(%rsi), %r8 + movq 368(%rsp), %rdx + sbbq %rdx, %r8 + movq %r9, 360(%rdi) + movq 376(%rsi), %r9 + movq 376(%rsp), %rdx + sbbq %rdx, %r9 + movq %r8, 368(%rdi) + movq %r9, 376(%rdi) + sbbq $0, %rax + addq $384, %rsp + repz retq +#ifndef __APPLE__ +.size sp_3072_cond_sub_48,.-sp_3072_cond_sub_48 +#endif /* __APPLE__ */ +/* Reduce the number back to 3072 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +#ifndef __APPLE__ +.globl sp_3072_mont_reduce_48 +.type sp_3072_mont_reduce_48,@function +.align 16 +sp_3072_mont_reduce_48: +#else +.globl _sp_3072_mont_reduce_48 +.p2align 4 +_sp_3072_mont_reduce_48: +#endif /* __APPLE__ */ + push %r12 + push %r13 + push %r14 + push %r15 + movq %rdx, %rcx + xorq %r15, %r15 + # i = 0 + movq $48, %r8 + movq (%rdi), %r13 + movq 8(%rdi), %r14 +L_mont_loop_48: + # mu = a[i] * mp + movq %r13, %r11 + imulq %rcx, %r11 + # a[i+0] += m[0] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq (%rsi) + addq %rax, %r13 + adcq %rdx, %r10 + # a[i+1] += m[1] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 8(%rsi) + movq %r14, %r13 + addq %rax, %r13 + adcq %rdx, %r9 + addq %r10, %r13 + adcq $0, %r9 + # a[i+2] += m[2] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 16(%rsi) + movq 16(%rdi), %r14 + addq %rax, %r14 + adcq %rdx, %r10 + addq %r9, %r14 + adcq $0, %r10 + # a[i+3] += m[3] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 24(%rsi) + movq 24(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 24(%rdi) + adcq $0, %r9 + # a[i+4] += m[4] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 32(%rsi) + movq 32(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 32(%rdi) + adcq $0, %r10 + # a[i+5] += m[5] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 40(%rsi) + movq 40(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 40(%rdi) + adcq $0, %r9 + # a[i+6] += m[6] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 48(%rsi) + movq 48(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 48(%rdi) + adcq $0, %r10 + # a[i+7] += m[7] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 56(%rsi) + movq 56(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 56(%rdi) + adcq $0, %r9 + # a[i+8] += m[8] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 64(%rsi) + movq 64(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 64(%rdi) + adcq $0, %r10 + # a[i+9] += m[9] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 72(%rsi) + movq 72(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 72(%rdi) + adcq $0, %r9 + # a[i+10] += m[10] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 80(%rsi) + movq 80(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 80(%rdi) + adcq $0, %r10 + # a[i+11] += m[11] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 88(%rsi) + movq 88(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 88(%rdi) + adcq $0, %r9 + # a[i+12] += m[12] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 96(%rsi) + movq 96(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 96(%rdi) + adcq $0, %r10 + # a[i+13] += m[13] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 104(%rsi) + movq 104(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 104(%rdi) + adcq $0, %r9 + # a[i+14] += m[14] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 112(%rsi) + movq 112(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 112(%rdi) + adcq $0, %r10 + # a[i+15] += m[15] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 120(%rsi) + movq 120(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 120(%rdi) + adcq $0, %r9 + # a[i+16] += m[16] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 128(%rsi) + movq 128(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 128(%rdi) + adcq $0, %r10 + # a[i+17] += m[17] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 136(%rsi) + movq 136(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 136(%rdi) + adcq $0, %r9 + # a[i+18] += m[18] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 144(%rsi) + movq 144(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 144(%rdi) + adcq $0, %r10 + # a[i+19] += m[19] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 152(%rsi) + movq 152(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 152(%rdi) + adcq $0, %r9 + # a[i+20] += m[20] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 160(%rsi) + movq 160(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 160(%rdi) + adcq $0, %r10 + # a[i+21] += m[21] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 168(%rsi) + movq 168(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 168(%rdi) + adcq $0, %r9 + # a[i+22] += m[22] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 176(%rsi) + movq 176(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 176(%rdi) + adcq $0, %r10 + # a[i+23] += m[23] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 184(%rsi) + movq 184(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 184(%rdi) + adcq $0, %r9 + # a[i+24] += m[24] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 192(%rsi) + movq 192(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 192(%rdi) + adcq $0, %r10 + # a[i+25] += m[25] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 200(%rsi) + movq 200(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 200(%rdi) + adcq $0, %r9 + # a[i+26] += m[26] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 208(%rsi) + movq 208(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 208(%rdi) + adcq $0, %r10 + # a[i+27] += m[27] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 216(%rsi) + movq 216(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 216(%rdi) + adcq $0, %r9 + # a[i+28] += m[28] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 224(%rsi) + movq 224(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 224(%rdi) + adcq $0, %r10 + # a[i+29] += m[29] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 232(%rsi) + movq 232(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 232(%rdi) + adcq $0, %r9 + # a[i+30] += m[30] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 240(%rsi) + movq 240(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 240(%rdi) + adcq $0, %r10 + # a[i+31] += m[31] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 248(%rsi) + movq 248(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 248(%rdi) + adcq $0, %r9 + # a[i+32] += m[32] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 256(%rsi) + movq 256(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 256(%rdi) + adcq $0, %r10 + # a[i+33] += m[33] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 264(%rsi) + movq 264(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 264(%rdi) + adcq $0, %r9 + # a[i+34] += m[34] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 272(%rsi) + movq 272(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 272(%rdi) + adcq $0, %r10 + # a[i+35] += m[35] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 280(%rsi) + movq 280(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 280(%rdi) + adcq $0, %r9 + # a[i+36] += m[36] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 288(%rsi) + movq 288(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 288(%rdi) + adcq $0, %r10 + # a[i+37] += m[37] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 296(%rsi) + movq 296(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 296(%rdi) + adcq $0, %r9 + # a[i+38] += m[38] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 304(%rsi) + movq 304(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 304(%rdi) + adcq $0, %r10 + # a[i+39] += m[39] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 312(%rsi) + movq 312(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 312(%rdi) + adcq $0, %r9 + # a[i+40] += m[40] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 320(%rsi) + movq 320(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 320(%rdi) + adcq $0, %r10 + # a[i+41] += m[41] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 328(%rsi) + movq 328(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 328(%rdi) + adcq $0, %r9 + # a[i+42] += m[42] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 336(%rsi) + movq 336(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 336(%rdi) + adcq $0, %r10 + # a[i+43] += m[43] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 344(%rsi) + movq 344(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 344(%rdi) + adcq $0, %r9 + # a[i+44] += m[44] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 352(%rsi) + movq 352(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 352(%rdi) + adcq $0, %r10 + # a[i+45] += m[45] * mu + movq %r11, %rax + xorq %r9, %r9 + mulq 360(%rsi) + movq 360(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r9 + addq %r10, %r12 + movq %r12, 360(%rdi) + adcq $0, %r9 + # a[i+46] += m[46] * mu + movq %r11, %rax + xorq %r10, %r10 + mulq 368(%rsi) + movq 368(%rdi), %r12 + addq %rax, %r12 + adcq %rdx, %r10 + addq %r9, %r12 + movq %r12, 368(%rdi) + adcq $0, %r10 + # a[i+47] += m[47] * mu + movq %r11, %rax + mulq 376(%rsi) + movq 376(%rdi), %r12 + addq %rax, %r10 + adcq %r15, %rdx + movq $0, %r15 + adcq $0, %r15 + addq %r10, %r12 + movq %r12, 376(%rdi) + adcq %rdx, 384(%rdi) + adcq $0, %r15 + # i += 1 + addq $8, %rdi + decq %r8 + jnz L_mont_loop_48 + movq %r13, (%rdi) + movq %r14, 8(%rdi) + negq %r15 + movq %r15, %rcx + movq %rsi, %rdx + movq %rdi, %rsi + movq %rdi, %rdi + subq $384, %rdi +#ifndef __APPLE__ + callq sp_3072_cond_sub_48@plt +#else + callq _sp_3072_cond_sub_48 +#endif /* __APPLE__ */ + pop %r15 + pop %r14 + pop %r13 + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_3072_mont_reduce_48,.-sp_3072_mont_reduce_48 +#endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 +/* Mul a by digit b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision digit. + */ +#ifndef __APPLE__ +.globl sp_3072_mul_d_avx2_48 +.type sp_3072_mul_d_avx2_48,@function +.align 16 +sp_3072_mul_d_avx2_48: +#else +.globl _sp_3072_mul_d_avx2_48 +.p2align 4 +_sp_3072_mul_d_avx2_48: +#endif /* __APPLE__ */ + movq %rdx, %rax + # A[0] * B + movq %rax, %rdx + xorq %r11, %r11 + mulxq (%rsi), %r9, %r10 + movq %r9, (%rdi) + # A[1] * B + mulxq 8(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 8(%rdi) + adoxq %r8, %r9 + # A[2] * B + mulxq 16(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 16(%rdi) + adoxq %r8, %r10 + # A[3] * B + mulxq 24(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 24(%rdi) + adoxq %r8, %r9 + # A[4] * B + mulxq 32(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 32(%rdi) + adoxq %r8, %r10 + # A[5] * B + mulxq 40(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 40(%rdi) + adoxq %r8, %r9 + # A[6] * B + mulxq 48(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 48(%rdi) + adoxq %r8, %r10 + # A[7] * B + mulxq 56(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 56(%rdi) + adoxq %r8, %r9 + # A[8] * B + mulxq 64(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 64(%rdi) + adoxq %r8, %r10 + # A[9] * B + mulxq 72(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 72(%rdi) + adoxq %r8, %r9 + # A[10] * B + mulxq 80(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 80(%rdi) + adoxq %r8, %r10 + # A[11] * B + mulxq 88(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 88(%rdi) + adoxq %r8, %r9 + # A[12] * B + mulxq 96(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 96(%rdi) + adoxq %r8, %r10 + # A[13] * B + mulxq 104(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 104(%rdi) + adoxq %r8, %r9 + # A[14] * B + mulxq 112(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 112(%rdi) + adoxq %r8, %r10 + # A[15] * B + mulxq 120(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 120(%rdi) + adoxq %r8, %r9 + # A[16] * B + mulxq 128(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 128(%rdi) + adoxq %r8, %r10 + # A[17] * B + mulxq 136(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 136(%rdi) + adoxq %r8, %r9 + # A[18] * B + mulxq 144(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 144(%rdi) + adoxq %r8, %r10 + # A[19] * B + mulxq 152(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 152(%rdi) + adoxq %r8, %r9 + # A[20] * B + mulxq 160(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 160(%rdi) + adoxq %r8, %r10 + # A[21] * B + mulxq 168(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 168(%rdi) + adoxq %r8, %r9 + # A[22] * B + mulxq 176(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 176(%rdi) + adoxq %r8, %r10 + # A[23] * B + mulxq 184(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 184(%rdi) + adoxq %r8, %r9 + # A[24] * B + mulxq 192(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 192(%rdi) + adoxq %r8, %r10 + # A[25] * B + mulxq 200(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 200(%rdi) + adoxq %r8, %r9 + # A[26] * B + mulxq 208(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 208(%rdi) + adoxq %r8, %r10 + # A[27] * B + mulxq 216(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 216(%rdi) + adoxq %r8, %r9 + # A[28] * B + mulxq 224(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 224(%rdi) + adoxq %r8, %r10 + # A[29] * B + mulxq 232(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 232(%rdi) + adoxq %r8, %r9 + # A[30] * B + mulxq 240(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 240(%rdi) + adoxq %r8, %r10 + # A[31] * B + mulxq 248(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 248(%rdi) + adoxq %r8, %r9 + # A[32] * B + mulxq 256(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 256(%rdi) + adoxq %r8, %r10 + # A[33] * B + mulxq 264(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 264(%rdi) + adoxq %r8, %r9 + # A[34] * B + mulxq 272(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 272(%rdi) + adoxq %r8, %r10 + # A[35] * B + mulxq 280(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 280(%rdi) + adoxq %r8, %r9 + # A[36] * B + mulxq 288(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 288(%rdi) + adoxq %r8, %r10 + # A[37] * B + mulxq 296(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 296(%rdi) + adoxq %r8, %r9 + # A[38] * B + mulxq 304(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 304(%rdi) + adoxq %r8, %r10 + # A[39] * B + mulxq 312(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 312(%rdi) + adoxq %r8, %r9 + # A[40] * B + mulxq 320(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 320(%rdi) + adoxq %r8, %r10 + # A[41] * B + mulxq 328(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 328(%rdi) + adoxq %r8, %r9 + # A[42] * B + mulxq 336(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 336(%rdi) + adoxq %r8, %r10 + # A[43] * B + mulxq 344(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 344(%rdi) + adoxq %r8, %r9 + # A[44] * B + mulxq 352(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 352(%rdi) + adoxq %r8, %r10 + # A[45] * B + mulxq 360(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 360(%rdi) + adoxq %r8, %r9 + # A[46] * B + mulxq 368(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 368(%rdi) + adoxq %r8, %r10 + # A[47] * B + mulxq 376(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + adoxq %r8, %r9 + adcxq %r11, %r9 + movq %r10, 376(%rdi) + movq %r9, 384(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_3072_mul_d_avx2_48,.-sp_3072_mul_d_avx2_48 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +#ifndef __APPLE__ +.globl sp_3072_cmp_48 +.type sp_3072_cmp_48,@function +.align 16 +sp_3072_cmp_48: +#else +.globl _sp_3072_cmp_48 +.p2align 4 +_sp_3072_cmp_48: +#endif /* __APPLE__ */ + xorq %rcx, %rcx + movq $-1, %rdx + movq $-1, %rax + movq $1, %r8 + movq 376(%rdi), %r9 + movq 376(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 368(%rdi), %r9 + movq 368(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 360(%rdi), %r9 + movq 360(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 352(%rdi), %r9 + movq 352(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 344(%rdi), %r9 + movq 344(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 336(%rdi), %r9 + movq 336(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 328(%rdi), %r9 + movq 328(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 320(%rdi), %r9 + movq 320(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 312(%rdi), %r9 + movq 312(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 304(%rdi), %r9 + movq 304(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 296(%rdi), %r9 + movq 296(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 288(%rdi), %r9 + movq 288(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 280(%rdi), %r9 + movq 280(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 272(%rdi), %r9 + movq 272(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 264(%rdi), %r9 + movq 264(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 256(%rdi), %r9 + movq 256(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 248(%rdi), %r9 + movq 248(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 240(%rdi), %r9 + movq 240(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 232(%rdi), %r9 + movq 232(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 224(%rdi), %r9 + movq 224(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 216(%rdi), %r9 + movq 216(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 208(%rdi), %r9 + movq 208(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 200(%rdi), %r9 + movq 200(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 192(%rdi), %r9 + movq 192(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 184(%rdi), %r9 + movq 184(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 176(%rdi), %r9 + movq 176(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 168(%rdi), %r9 + movq 168(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 160(%rdi), %r9 + movq 160(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 152(%rdi), %r9 + movq 152(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 144(%rdi), %r9 + movq 144(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 136(%rdi), %r9 + movq 136(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 128(%rdi), %r9 + movq 128(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 120(%rdi), %r9 + movq 120(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 112(%rdi), %r9 + movq 112(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 104(%rdi), %r9 + movq 104(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 96(%rdi), %r9 + movq 96(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 88(%rdi), %r9 + movq 88(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 80(%rdi), %r9 + movq 80(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 72(%rdi), %r9 + movq 72(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 64(%rdi), %r9 + movq 64(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 56(%rdi), %r9 + movq 56(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 48(%rdi), %r9 + movq 48(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 40(%rdi), %r9 + movq 40(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 32(%rdi), %r9 + movq 32(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 24(%rdi), %r9 + movq 24(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 16(%rdi), %r9 + movq 16(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 8(%rdi), %r9 + movq 8(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq (%rdi), %r9 + movq (%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + xorq %rdx, %rax + repz retq +#ifndef __APPLE__ +.size sp_3072_cmp_48,.-sp_3072_cmp_48 +#endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 +/* Reduce the number back to 3072 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +#ifndef __APPLE__ +.globl sp_3072_mont_reduce_avx2_48 +.type sp_3072_mont_reduce_avx2_48,@function +.align 16 +sp_3072_mont_reduce_avx2_48: +#else +.globl _sp_3072_mont_reduce_avx2_48 +.p2align 4 +_sp_3072_mont_reduce_avx2_48: +#endif /* __APPLE__ */ + push %r12 + push %r13 + push %r14 + movq %rdx, %rax + xorq %r14, %r14 + # i = 0 + movq $48, %r9 + movq (%rdi), %r13 + xorq %r12, %r12 +L_mont_loop_avx2_48: + # mu = a[i] * mp + movq %r13, %rdx + mulxq %rax, %rdx, %r8 + movq %r13, %r10 + # a[i+0] += m[0] * mu + mulxq (%rsi), %rcx, %r8 + movq 8(%rdi), %r13 + adcxq %rcx, %r10 + adoxq %r8, %r13 + # a[i+1] += m[1] * mu + mulxq 8(%rsi), %rcx, %r8 + movq 16(%rdi), %r10 + adcxq %rcx, %r13 + adoxq %r8, %r10 + # a[i+2] += m[2] * mu + mulxq 16(%rsi), %rcx, %r8 + movq 24(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 16(%rdi) + # a[i+3] += m[3] * mu + mulxq 24(%rsi), %rcx, %r8 + movq 32(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 24(%rdi) + # a[i+4] += m[4] * mu + mulxq 32(%rsi), %rcx, %r8 + movq 40(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 32(%rdi) + # a[i+5] += m[5] * mu + mulxq 40(%rsi), %rcx, %r8 + movq 48(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 40(%rdi) + # a[i+6] += m[6] * mu + mulxq 48(%rsi), %rcx, %r8 + movq 56(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 48(%rdi) + # a[i+7] += m[7] * mu + mulxq 56(%rsi), %rcx, %r8 + movq 64(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 56(%rdi) + # a[i+8] += m[8] * mu + mulxq 64(%rsi), %rcx, %r8 + movq 72(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 64(%rdi) + # a[i+9] += m[9] * mu + mulxq 72(%rsi), %rcx, %r8 + movq 80(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 72(%rdi) + # a[i+10] += m[10] * mu + mulxq 80(%rsi), %rcx, %r8 + movq 88(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 80(%rdi) + # a[i+11] += m[11] * mu + mulxq 88(%rsi), %rcx, %r8 + movq 96(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 88(%rdi) + # a[i+12] += m[12] * mu + mulxq 96(%rsi), %rcx, %r8 + movq 104(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 96(%rdi) + # a[i+13] += m[13] * mu + mulxq 104(%rsi), %rcx, %r8 + movq 112(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 104(%rdi) + # a[i+14] += m[14] * mu + mulxq 112(%rsi), %rcx, %r8 + movq 120(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 112(%rdi) + # a[i+15] += m[15] * mu + mulxq 120(%rsi), %rcx, %r8 + movq 128(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 120(%rdi) + # a[i+16] += m[16] * mu + mulxq 128(%rsi), %rcx, %r8 + movq 136(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 128(%rdi) + # a[i+17] += m[17] * mu + mulxq 136(%rsi), %rcx, %r8 + movq 144(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 136(%rdi) + # a[i+18] += m[18] * mu + mulxq 144(%rsi), %rcx, %r8 + movq 152(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 144(%rdi) + # a[i+19] += m[19] * mu + mulxq 152(%rsi), %rcx, %r8 + movq 160(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 152(%rdi) + # a[i+20] += m[20] * mu + mulxq 160(%rsi), %rcx, %r8 + movq 168(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 160(%rdi) + # a[i+21] += m[21] * mu + mulxq 168(%rsi), %rcx, %r8 + movq 176(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 168(%rdi) + # a[i+22] += m[22] * mu + mulxq 176(%rsi), %rcx, %r8 + movq 184(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 176(%rdi) + # a[i+23] += m[23] * mu + mulxq 184(%rsi), %rcx, %r8 + movq 192(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 184(%rdi) + # a[i+24] += m[24] * mu + mulxq 192(%rsi), %rcx, %r8 + movq 200(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 192(%rdi) + # a[i+25] += m[25] * mu + mulxq 200(%rsi), %rcx, %r8 + movq 208(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 200(%rdi) + # a[i+26] += m[26] * mu + mulxq 208(%rsi), %rcx, %r8 + movq 216(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 208(%rdi) + # a[i+27] += m[27] * mu + mulxq 216(%rsi), %rcx, %r8 + movq 224(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 216(%rdi) + # a[i+28] += m[28] * mu + mulxq 224(%rsi), %rcx, %r8 + movq 232(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 224(%rdi) + # a[i+29] += m[29] * mu + mulxq 232(%rsi), %rcx, %r8 + movq 240(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 232(%rdi) + # a[i+30] += m[30] * mu + mulxq 240(%rsi), %rcx, %r8 + movq 248(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 240(%rdi) + # a[i+31] += m[31] * mu + mulxq 248(%rsi), %rcx, %r8 + movq 256(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 248(%rdi) + # a[i+32] += m[32] * mu + mulxq 256(%rsi), %rcx, %r8 + movq 264(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 256(%rdi) + # a[i+33] += m[33] * mu + mulxq 264(%rsi), %rcx, %r8 + movq 272(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 264(%rdi) + # a[i+34] += m[34] * mu + mulxq 272(%rsi), %rcx, %r8 + movq 280(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 272(%rdi) + # a[i+35] += m[35] * mu + mulxq 280(%rsi), %rcx, %r8 + movq 288(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 280(%rdi) + # a[i+36] += m[36] * mu + mulxq 288(%rsi), %rcx, %r8 + movq 296(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 288(%rdi) + # a[i+37] += m[37] * mu + mulxq 296(%rsi), %rcx, %r8 + movq 304(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 296(%rdi) + # a[i+38] += m[38] * mu + mulxq 304(%rsi), %rcx, %r8 + movq 312(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 304(%rdi) + # a[i+39] += m[39] * mu + mulxq 312(%rsi), %rcx, %r8 + movq 320(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 312(%rdi) + # a[i+40] += m[40] * mu + mulxq 320(%rsi), %rcx, %r8 + movq 328(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 320(%rdi) + # a[i+41] += m[41] * mu + mulxq 328(%rsi), %rcx, %r8 + movq 336(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 328(%rdi) + # a[i+42] += m[42] * mu + mulxq 336(%rsi), %rcx, %r8 + movq 344(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 336(%rdi) + # a[i+43] += m[43] * mu + mulxq 344(%rsi), %rcx, %r8 + movq 352(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 344(%rdi) + # a[i+44] += m[44] * mu + mulxq 352(%rsi), %rcx, %r8 + movq 360(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 352(%rdi) + # a[i+45] += m[45] * mu + mulxq 360(%rsi), %rcx, %r8 + movq 368(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 360(%rdi) + # a[i+46] += m[46] * mu + mulxq 368(%rsi), %rcx, %r8 + movq 376(%rdi), %r11 + adcxq %rcx, %r10 + adoxq %r8, %r11 + movq %r10, 368(%rdi) + # a[i+47] += m[47] * mu + mulxq 376(%rsi), %rcx, %r8 + movq 384(%rdi), %r10 + adcxq %rcx, %r11 + adoxq %r8, %r10 + movq %r11, 376(%rdi) + adcxq %r14, %r10 + movq %r12, %r14 + adoxq %r12, %r14 + adcxq %r12, %r14 + movq %r10, 384(%rdi) + # i += 1 + addq $8, %rdi + decq %r9 + jnz L_mont_loop_avx2_48 + movq %r13, (%rdi) + negq %r14 + movq %r14, %rcx + movq %rsi, %rdx + movq %rdi, %rsi + movq %rdi, %rdi + subq $384, %rdi +#ifndef __APPLE__ + callq sp_3072_cond_sub_48@plt +#else + callq _sp_3072_cond_sub_48 +#endif /* __APPLE__ */ + pop %r14 + pop %r13 + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_3072_mont_reduce_avx2_48,.-sp_3072_mont_reduce_avx2_48 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +/* Conditionally copy a into r using the mask m. + * m is -1 to copy and 0 when not. + * + * r A single precision number to copy over. + * a A single precision number to copy. + * m Mask value to apply. + */ +#ifndef __APPLE__ +.globl sp_256_cond_copy_4 +.type sp_256_cond_copy_4,@function +.align 16 +sp_256_cond_copy_4: +#else +.globl _sp_256_cond_copy_4 +.p2align 4 +_sp_256_cond_copy_4: +#endif /* __APPLE__ */ + movq (%rdi), %rax + movq 8(%rdi), %rcx + movq 16(%rdi), %r8 + movq 24(%rdi), %r9 + xorq (%rsi), %rax + xorq 8(%rsi), %rcx + xorq 16(%rsi), %r8 + xorq 24(%rsi), %r9 + andq %rdx, %rax + andq %rdx, %rcx + andq %rdx, %r8 + andq %rdx, %r9 + xorq %rax, (%rdi) + xorq %rcx, 8(%rdi) + xorq %r8, 16(%rdi) + xorq %r9, 24(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_256_cond_copy_4,.-sp_256_cond_copy_4 +#endif /* __APPLE__ */ +/* Compare a with b in constant time. + * + * a A single precision integer. + * b A single precision integer. + * return -ve, 0 or +ve if a is less than, equal to or greater than b + * respectively. + */ +#ifndef __APPLE__ +.globl sp_256_cmp_4 +.type sp_256_cmp_4,@function +.align 16 +sp_256_cmp_4: +#else +.globl _sp_256_cmp_4 +.p2align 4 +_sp_256_cmp_4: +#endif /* __APPLE__ */ + xorq %rcx, %rcx + movq $-1, %rdx + movq $-1, %rax + movq $1, %r8 + movq 24(%rdi), %r9 + movq 24(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 16(%rdi), %r9 + movq 16(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq 8(%rdi), %r9 + movq 8(%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + movq (%rdi), %r9 + movq (%rsi), %r10 + andq %rdx, %r9 + andq %rdx, %r10 + subq %r10, %r9 + cmova %r8, %rax + cmovc %rdx, %rax + cmovnz %rcx, %rdx + xorq %rdx, %rax + repz retq +#ifndef __APPLE__ +.size sp_256_cmp_4,.-sp_256_cmp_4 +#endif /* __APPLE__ */ +/* Conditionally subtract b from a using the mask m. + * m is -1 to subtract and 0 when not copying. + * + * r A single precision number representing condition subtract result. + * a A single precision number to subtract from. + * b A single precision number to subtract. + * m Mask value to apply. + */ +#ifndef __APPLE__ +.globl sp_256_cond_sub_4 +.type sp_256_cond_sub_4,@function +.align 16 +sp_256_cond_sub_4: +#else +.globl _sp_256_cond_sub_4 +.p2align 4 +_sp_256_cond_sub_4: +#endif /* __APPLE__ */ + push %r12 + push %r13 + push %r14 + push %r15 + movq $0, %rax + movq (%rdx), %r12 + movq 8(%rdx), %r13 + movq 16(%rdx), %r14 + movq 24(%rdx), %r15 + andq %rcx, %r12 + andq %rcx, %r13 + andq %rcx, %r14 + andq %rcx, %r15 + movq (%rsi), %r8 + movq 8(%rsi), %r9 + movq 16(%rsi), %r10 + movq 24(%rsi), %r11 + subq %r12, %r8 + sbbq %r13, %r9 + sbbq %r14, %r10 + sbbq %r15, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + sbbq $0, %rax + pop %r15 + pop %r14 + pop %r13 + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_256_cond_sub_4,.-sp_256_cond_sub_4 +#endif /* __APPLE__ */ +/* Sub b from a into r. (r = a - b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_256_sub_4 +.type sp_256_sub_4,@function +.align 16 +sp_256_sub_4: +#else +.globl _sp_256_sub_4 +.p2align 4 +_sp_256_sub_4: +#endif /* __APPLE__ */ + push %r12 + push %r13 + push %r14 + push %r15 + xorq %rax, %rax + movq (%rsi), %r8 + movq 8(%rsi), %r9 + movq 16(%rsi), %r10 + movq 24(%rsi), %r11 + movq (%rdx), %r12 + movq 8(%rdx), %r13 + movq 16(%rdx), %r14 + movq 24(%rdx), %r15 + subq %r12, %r8 + sbbq %r13, %r9 + sbbq %r14, %r10 + sbbq %r15, %r11 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + sbbq $0, %rax + pop %r15 + pop %r14 + pop %r13 + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_256_sub_4,.-sp_256_sub_4 +#endif /* __APPLE__ */ +/* Reduce the number back to 256 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +#ifndef __APPLE__ +.globl sp_256_mont_reduce_4 +.type sp_256_mont_reduce_4,@function +.align 16 +sp_256_mont_reduce_4: +#else +.globl _sp_256_mont_reduce_4 +.p2align 4 +_sp_256_mont_reduce_4: +#endif /* __APPLE__ */ + push %r12 + push %r13 + push %r14 + push %r15 + movq %rdx, %rcx + # i = 0 + xorq %r14, %r14 + movq $4, %r8 + movq %rdi, %r13 +L_mont_loop_4: + # mu = a[i] * mp + movq (%r13), %r12 + imulq %rcx, %r12 + # a[i+0] += m[0] * mu + movq (%rsi), %rax + movq 8(%rsi), %r10 + mulq %r12 + movq (%r13), %r15 + addq %rax, %r15 + movq %rdx, %r9 + movq %r15, (%r13) + adcq $0, %r9 + # a[i+1] += m[1] * mu + movq %r10, %rax + mulq %r12 + movq 16(%rsi), %r10 + movq 8(%r13), %r15 + addq %r9, %rax + movq %rdx, %r11 + adcq $0, %r11 + addq %rax, %r15 + movq %r15, 8(%r13) + adcq $0, %r11 + # a[i+2] += m[2] * mu + movq %r10, %rax + mulq %r12 + movq 24(%rsi), %r10 + movq 16(%r13), %r15 + addq %r11, %rax + movq %rdx, %r9 + adcq $0, %r9 + addq %rax, %r15 + movq %r15, 16(%r13) + adcq $0, %r9 + # a[i+3] += m[3] * mu + movq %r10, %rax + mulq %r12 + movq 24(%r13), %r15 + addq %r9, %rax + adcq %r14, %rdx + movq $0, %r14 + adcq $0, %r14 + addq %rax, %r15 + movq %r15, 24(%r13) + adcq %rdx, 32(%r13) + adcq $0, %r14 + # i += 1 + addq $8, %r13 + decq %r8 + jnz L_mont_loop_4 + xorq %rax, %rax + movq 32(%rdi), %rdx + movq 40(%rdi), %r8 + movq 48(%rdi), %r15 + movq 56(%rdi), %r9 + subq %r14, %rax + movq (%rsi), %r10 + movq 8(%rsi), %r11 + movq 16(%rsi), %r12 + movq 24(%rsi), %r13 + andq %rax, %r10 + andq %rax, %r11 + andq %rax, %r12 + andq %rax, %r13 + subq %r10, %rdx + sbbq %r11, %r8 + sbbq %r12, %r15 + sbbq %r13, %r9 + movq %rdx, (%rdi) + movq %r8, 8(%rdi) + movq %r15, 16(%rdi) + movq %r9, 24(%rdi) + pop %r15 + pop %r14 + pop %r13 + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_256_mont_reduce_4,.-sp_256_mont_reduce_4 +#endif /* __APPLE__ */ +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +#ifndef __APPLE__ +.globl sp_256_mont_mul_4 +.type sp_256_mont_mul_4,@function +.align 16 +sp_256_mont_mul_4: +#else +.globl _sp_256_mont_mul_4 +.p2align 4 +_sp_256_mont_mul_4: +#endif /* __APPLE__ */ + push %r12 + push %r13 + push %r14 + push %r15 + push %rbx + movq %rdx, %r8 + # A[0] * B[0] + movq (%r8), %rax + mulq (%rsi) + movq %rax, %r9 + movq %rdx, %r10 + # A[0] * B[1] + movq 8(%r8), %rax + mulq (%rsi) + xorq %r11, %r11 + addq %rax, %r10 + adcq %rdx, %r11 + # A[1] * B[0] + movq (%r8), %rax + mulq 8(%rsi) + xorq %r12, %r12 + addq %rax, %r10 + adcq %rdx, %r11 + adcq $0, %r12 + # A[0] * B[2] + movq 16(%r8), %rax + mulq (%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + # A[1] * B[1] + movq 8(%r8), %rax + mulq 8(%rsi) + xorq %r13, %r13 + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0, %r13 + # A[2] * B[0] + movq (%r8), %rax + mulq 16(%rsi) + addq %rax, %r11 + adcq %rdx, %r12 + adcq $0, %r13 + # A[0] * B[3] + movq 24(%r8), %rax + mulq (%rsi) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0, %r14 + # A[1] * B[2] + movq 16(%r8), %rax + mulq 8(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0, %r14 + # A[2] * B[1] + movq 8(%r8), %rax + mulq 16(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0, %r14 + # A[3] * B[0] + movq (%r8), %rax + mulq 24(%rsi) + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0, %r14 + # A[1] * B[3] + movq 24(%r8), %rax + mulq 8(%rsi) + xorq %r15, %r15 + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0, %r15 + # A[2] * B[2] + movq 16(%r8), %rax + mulq 16(%rsi) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0, %r15 + # A[3] * B[1] + movq 8(%r8), %rax + mulq 24(%rsi) + addq %rax, %r13 + adcq %rdx, %r14 + adcq $0, %r15 + # A[2] * B[3] + movq 24(%r8), %rax + mulq 16(%rsi) + xorq %rbx, %rbx + addq %rax, %r14 + adcq %rdx, %r15 + adcq $0, %rbx + # A[3] * B[2] + movq 16(%r8), %rax + mulq 24(%rsi) + addq %rax, %r14 + adcq %rdx, %r15 + adcq $0, %rbx + # A[3] * B[3] + movq 24(%r8), %rax + mulq 24(%rsi) + addq %rax, %r15 + adcq %rdx, %rbx + # Start Reduction + # mu = a[0]-a[3] + a[0]-a[2] << 32 << 64 + (a[0] * 2) << 192 + # - a[0] << 32 << 192 + # + (a[0] * 2) << 192 + movq %r9, %rax + movq %r12, %rdx + addq %r9, %rdx + movq %r10, %rsi + addq %r9, %rdx + movq %r11, %r8 + # a[0]-a[2] << 32 + shlq $32, %r9 + shldq $32, %rsi, %r11 + shldq $32, %rax, %r10 + # - a[0] << 32 << 192 + subq %r9, %rdx + # + a[0]-a[2] << 32 << 64 + addq %r9, %rsi + adcq %r10, %r8 + adcq %r11, %rdx + # a += (mu << 256) - (mu << 224) + (mu << 192) + (mu << 96) - mu + # a += mu << 256 + xorq %r9, %r9 + addq %rax, %r13 + adcq %rsi, %r14 + adcq %r8, %r15 + adcq %rdx, %rbx + sbbq $0, %r9 + # a += mu << 192 + addq %rax, %r12 + adcq %rsi, %r13 + adcq %r8, %r14 + adcq %rdx, %r15 + adcq $0, %rbx + sbbq $0, %r9 + # mu <<= 32 + movq %rdx, %rcx + shldq $32, %r8, %rdx + shldq $32, %rsi, %r8 + shldq $32, %rax, %rsi + shrq $32, %rcx + shlq $32, %rax + # a += (mu << 32) << 64 + addq %r8, %r12 + adcq %rdx, %r13 + adcq %rcx, %r14 + adcq $0, %r15 + adcq $0, %rbx + sbbq $0, %r9 + # a -= (mu << 32) << 192 + subq %rax, %r12 + movq $4294967295, %rax + sbbq %rsi, %r13 + movq $18446744069414584321, %rsi + sbbq %r8, %r14 + sbbq %rdx, %r15 + sbbq %rcx, %rbx + adcq $0, %r9 + # mask m and sub from result if overflow + # m[0] = -1 & mask = mask + andq %r9, %rax + # m[2] = 0 & mask = 0 + andq %r9, %rsi + subq %r9, %r13 + sbbq %rax, %r14 + sbbq $0, %r15 + sbbq %rsi, %rbx + movq %r13, (%rdi) + movq %r14, 8(%rdi) + movq %r15, 16(%rdi) + movq %rbx, 24(%rdi) + pop %rbx + pop %r15 + pop %r14 + pop %r13 + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_256_mont_mul_4,.-sp_256_mont_mul_4 +#endif /* __APPLE__ */ +/* Square the Montgomery form number mod the modulus (prime). (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +#ifndef __APPLE__ +.globl sp_256_mont_sqr_4 +.type sp_256_mont_sqr_4,@function +.align 16 +sp_256_mont_sqr_4: +#else +.globl _sp_256_mont_sqr_4 +.p2align 4 +_sp_256_mont_sqr_4: +#endif /* __APPLE__ */ + push %r12 + push %r13 + push %r14 + push %r15 + push %rbx + # A[0] * A[1] + movq (%rsi), %rax + mulq 8(%rsi) + movq %rax, %r10 + movq %rdx, %r11 + # A[0] * A[2] + movq (%rsi), %rax + mulq 16(%rsi) + xorq %r12, %r12 + addq %rax, %r11 + adcq %rdx, %r12 + # A[0] * A[3] + movq (%rsi), %rax + mulq 24(%rsi) + xorq %r13, %r13 + addq %rax, %r12 + adcq %rdx, %r13 + # A[1] * A[2] + movq 8(%rsi), %rax + mulq 16(%rsi) + xorq %r14, %r14 + addq %rax, %r12 + adcq %rdx, %r13 + adcq $0, %r14 + # A[1] * A[3] + movq 8(%rsi), %rax + mulq 24(%rsi) + addq %rax, %r13 + adcq %rdx, %r14 + # A[2] * A[3] + movq 16(%rsi), %rax + mulq 24(%rsi) + xorq %r15, %r15 + addq %rax, %r14 + adcq %rdx, %r15 + # Double + xorq %rbx, %rbx + addq %r10, %r10 + adcq %r11, %r11 + adcq %r12, %r12 + adcq %r13, %r13 + adcq %r14, %r14 + adcq %r15, %r15 + adcq $0, %rbx + # A[0] * A[0] + movq (%rsi), %rax + mulq %rax + movq %rax, %rax + movq %rdx, %rdx + movq %rax, %r9 + movq %rdx, %r8 + # A[1] * A[1] + movq 8(%rsi), %rax + mulq %rax + movq %rax, %rax + movq %rdx, %rdx + addq %r8, %r10 + adcq %rax, %r11 + adcq $0, %rdx + movq %rdx, %r8 + # A[2] * A[2] + movq 16(%rsi), %rax + mulq %rax + movq %rax, %rax + movq %rdx, %rdx + addq %r8, %r12 + adcq %rax, %r13 + adcq $0, %rdx + movq %rdx, %r8 + # A[3] * A[3] + movq 24(%rsi), %rax + mulq %rax + addq %rax, %r15 + adcq %rdx, %rbx + addq %r8, %r14 + adcq $0, %r15 + adcq $0, %rbx + # Start Reduction + # mu = a[0]-a[3] + a[0]-a[2] << 32 << 64 + (a[0] * 2) << 192 + # - a[0] << 32 << 192 + # + (a[0] * 2) << 192 + movq %r9, %rax + movq %r12, %rdx + addq %r9, %rdx + movq %r10, %rsi + addq %r9, %rdx + movq %r11, %r8 + # a[0]-a[2] << 32 + shlq $32, %r9 + shldq $32, %rsi, %r11 + shldq $32, %rax, %r10 + # - a[0] << 32 << 192 + subq %r9, %rdx + # + a[0]-a[2] << 32 << 64 + addq %r9, %rsi + adcq %r10, %r8 + adcq %r11, %rdx + # a += (mu << 256) - (mu << 224) + (mu << 192) + (mu << 96) - mu + # a += mu << 256 + xorq %r9, %r9 + addq %rax, %r13 + adcq %rsi, %r14 + adcq %r8, %r15 + adcq %rdx, %rbx + sbbq $0, %r9 + # a += mu << 192 + addq %rax, %r12 + adcq %rsi, %r13 + adcq %r8, %r14 + adcq %rdx, %r15 + adcq $0, %rbx + sbbq $0, %r9 + # mu <<= 32 + movq %rdx, %rcx + shldq $32, %r8, %rdx + shldq $32, %rsi, %r8 + shldq $32, %rax, %rsi + shrq $32, %rcx + shlq $32, %rax + # a += (mu << 32) << 64 + addq %r8, %r12 + adcq %rdx, %r13 + adcq %rcx, %r14 + adcq $0, %r15 + adcq $0, %rbx + sbbq $0, %r9 + # a -= (mu << 32) << 192 + subq %rax, %r12 + movq $4294967295, %rax + sbbq %rsi, %r13 + movq $18446744069414584321, %rsi + sbbq %r8, %r14 + sbbq %rdx, %r15 + sbbq %rcx, %rbx + adcq $0, %r9 + # mask m and sub from result if overflow + # m[0] = -1 & mask = mask + andq %r9, %rax + # m[2] = 0 & mask = 0 + andq %r9, %rsi + subq %r9, %r13 + sbbq %rax, %r14 + sbbq $0, %r15 + sbbq %rsi, %rbx + movq %r13, (%rdi) + movq %r14, 8(%rdi) + movq %r15, 16(%rdi) + movq %rbx, 24(%rdi) + pop %rbx + pop %r15 + pop %r14 + pop %r13 + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_256_mont_sqr_4,.-sp_256_mont_sqr_4 +#endif /* __APPLE__ */ +/* Add two Montgomery form numbers (r = a + b % m). + * + * r Result of addition. + * a First number to add in Montogmery form. + * b Second number to add in Montogmery form. + * m Modulus (prime). + */ +#ifndef __APPLE__ +.globl sp_256_mont_add_4 +.type sp_256_mont_add_4,@function +.align 16 +sp_256_mont_add_4: +#else +.globl _sp_256_mont_add_4 +.p2align 4 +_sp_256_mont_add_4: +#endif /* __APPLE__ */ + movq (%rsi), %rax + movq 8(%rsi), %rcx + movq 16(%rsi), %r8 + movq 24(%rsi), %r9 + addq (%rdx), %rax + adcq 8(%rdx), %rcx + movq $4294967295, %r10 + adcq 16(%rdx), %r8 + movq $18446744069414584321, %r11 + adcq 24(%rdx), %r9 + movq $0, %rdx + sbbq $0, %rdx + andq %rdx, %r10 + andq %rdx, %r11 + subq %rdx, %rax + sbbq %r10, %rcx + movq %rax, (%rdi) + sbbq $0, %r8 + movq %rcx, 8(%rdi) + sbbq %r11, %r9 + movq %r8, 16(%rdi) + movq %r9, 24(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_256_mont_add_4,.-sp_256_mont_add_4 +#endif /* __APPLE__ */ +/* Double a Montgomery form number (r = a + a % m). + * + * r Result of doubling. + * a Number to double in Montogmery form. + * m Modulus (prime). + */ +#ifndef __APPLE__ +.globl sp_256_mont_dbl_4 +.type sp_256_mont_dbl_4,@function +.align 16 +sp_256_mont_dbl_4: +#else +.globl _sp_256_mont_dbl_4 +.p2align 4 +_sp_256_mont_dbl_4: +#endif /* __APPLE__ */ + movq (%rsi), %rdx + movq 8(%rsi), %rax + movq 16(%rsi), %rcx + movq 24(%rsi), %r8 + xorq %r11, %r11 + addq %rdx, %rdx + adcq %rax, %rax + movq $4294967295, %r9 + adcq %rcx, %rcx + adcq %r8, %r8 + movq $18446744069414584321, %r10 + sbbq $0, %r11 + andq %r11, %r9 + andq %r11, %r10 + subq %r11, %rdx + sbbq %r9, %rax + movq %rdx, (%rdi) + sbbq $0, %rcx + movq %rax, 8(%rdi) + sbbq %r10, %r8 + movq %rcx, 16(%rdi) + movq %r8, 24(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_256_mont_dbl_4,.-sp_256_mont_dbl_4 +#endif /* __APPLE__ */ +/* Triple a Montgomery form number (r = a + a + a % m). + * + * r Result of Tripling. + * a Number to triple in Montogmery form. + * m Modulus (prime). + */ +#ifndef __APPLE__ +.globl sp_256_mont_tpl_4 +.type sp_256_mont_tpl_4,@function +.align 16 +sp_256_mont_tpl_4: +#else +.globl _sp_256_mont_tpl_4 +.p2align 4 +_sp_256_mont_tpl_4: +#endif /* __APPLE__ */ + movq (%rsi), %rdx + movq 8(%rsi), %rax + movq 16(%rsi), %rcx + movq 24(%rsi), %r8 + xorq %r11, %r11 + addq %rdx, %rdx + adcq %rax, %rax + movq $4294967295, %r9 + adcq %rcx, %rcx + adcq %r8, %r8 + movq $18446744069414584321, %r10 + sbbq $0, %r11 + andq %r11, %r9 + andq %r11, %r10 + subq %r11, %rdx + sbbq %r9, %rax + sbbq $0, %rcx + sbbq %r10, %r8 + xorq %r11, %r11 + addq (%rsi), %rdx + adcq 8(%rsi), %rax + movq $4294967295, %r9 + adcq 16(%rsi), %rcx + adcq 24(%rsi), %r8 + movq $18446744069414584321, %r10 + sbbq $0, %r11 + andq %r11, %r9 + andq %r11, %r10 + subq %r11, %rdx + sbbq %r9, %rax + movq %rdx, (%rdi) + sbbq $0, %rcx + movq %rax, 8(%rdi) + sbbq %r10, %r8 + movq %rcx, 16(%rdi) + movq %r8, 24(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_256_mont_tpl_4,.-sp_256_mont_tpl_4 +#endif /* __APPLE__ */ +/* Subtract two Montgomery form numbers (r = a - b % m). + * + * r Result of subtration. + * a Number to subtract from in Montogmery form. + * b Number to subtract with in Montogmery form. + * m Modulus (prime). + */ +#ifndef __APPLE__ +.globl sp_256_mont_sub_4 +.type sp_256_mont_sub_4,@function +.align 16 +sp_256_mont_sub_4: +#else +.globl _sp_256_mont_sub_4 +.p2align 4 +_sp_256_mont_sub_4: +#endif /* __APPLE__ */ + movq (%rsi), %rax + movq 8(%rsi), %rcx + movq 16(%rsi), %r8 + movq 24(%rsi), %r9 + subq (%rdx), %rax + sbbq 8(%rdx), %rcx + movq $4294967295, %r10 + sbbq 16(%rdx), %r8 + movq $18446744069414584321, %r11 + sbbq 24(%rdx), %r9 + movq $0, %rdx + sbbq $0, %rdx + andq %rdx, %r10 + andq %rdx, %r11 + addq %rdx, %rax + adcq %r10, %rcx + movq %rax, (%rdi) + adcq $0, %r8 + movq %rcx, 8(%rdi) + adcq %r11, %r9 + movq %r8, 16(%rdi) + movq %r9, 24(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_256_mont_sub_4,.-sp_256_mont_sub_4 +#endif /* __APPLE__ */ +/* Divide the number by 2 mod the modulus (prime). (r = a / 2 % m) + * + * r Result of division by 2. + * a Number to divide. + * m Modulus (prime). + */ +#ifndef __APPLE__ +.globl sp_256_div2_4 +.type sp_256_div2_4,@function +.align 16 +sp_256_div2_4: +#else +.globl _sp_256_div2_4 +.p2align 4 +_sp_256_div2_4: +#endif /* __APPLE__ */ + movq (%rsi), %rdx + movq 8(%rsi), %rax + movq 16(%rsi), %rcx + movq 24(%rsi), %r8 + movq $4294967295, %r9 + movq $18446744069414584321, %r10 + movq %rdx, %r11 + andq $1, %r11 + negq %r11 + andq %r11, %r9 + andq %r11, %r10 + addq %r11, %rdx + adcq %r9, %rax + adcq $0, %rcx + adcq %r10, %r8 + movq $0, %r11 + adcq $0, %r11 + shrdq $1, %rax, %rdx + shrdq $1, %rcx, %rax + shrdq $1, %r8, %rcx + shrdq $1, %r11, %r8 + movq %rdx, (%rdi) + movq %rax, 8(%rdi) + movq %rcx, 16(%rdi) + movq %r8, 24(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_256_div2_4,.-sp_256_div2_4 +#endif /* __APPLE__ */ +/* Multiply two Montogmery form numbers mod the modulus (prime). + * (r = a * b mod m) + * + * r Result of multiplication. + * a First number to multiply in Montogmery form. + * b Second number to multiply in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +#ifndef __APPLE__ +.globl sp_256_mont_mul_avx2_4 +.type sp_256_mont_mul_avx2_4,@function +.align 16 +sp_256_mont_mul_avx2_4: +#else +.globl _sp_256_mont_mul_avx2_4 +.p2align 4 +_sp_256_mont_mul_avx2_4: +#endif /* __APPLE__ */ + push %rbx + push %rbp + push %r12 + push %r13 + push %r14 + push %r15 + movq %rdx, %rbp + # A[0] * B[0] + movq (%rbp), %rdx + mulxq (%rsi), %r8, %r9 + # A[2] * B[0] + mulxq 16(%rsi), %r10, %r11 + # A[1] * B[0] + mulxq 8(%rsi), %rax, %rcx + xorq %r15, %r15 + adcxq %rax, %r9 + # A[1] * B[3] + movq 24(%rbp), %rdx + mulxq 8(%rsi), %r12, %r13 + adcxq %rcx, %r10 + # A[0] * B[1] + movq 8(%rbp), %rdx + mulxq (%rsi), %rax, %rcx + adoxq %rax, %r9 + # A[2] * B[1] + mulxq 16(%rsi), %rax, %r14 + adoxq %rcx, %r10 + adcxq %rax, %r11 + # A[1] * B[2] + movq 16(%rbp), %rdx + mulxq 8(%rsi), %rax, %rcx + adcxq %r14, %r12 + adoxq %rax, %r11 + adcxq %r15, %r13 + adoxq %rcx, %r12 + # A[0] * B[2] + mulxq (%rsi), %rax, %rcx + adoxq %r15, %r13 + xorq %r14, %r14 + adcxq %rax, %r10 + # A[1] * B[1] + movq 8(%rbp), %rdx + mulxq 8(%rsi), %rdx, %rax + adcxq %rcx, %r11 + adoxq %rdx, %r10 + # A[3] * B[1] + movq 8(%rbp), %rdx + adoxq %rax, %r11 + mulxq 24(%rsi), %rax, %rcx + adcxq %rax, %r12 + # A[2] * B[2] + movq 16(%rbp), %rdx + mulxq 16(%rsi), %rdx, %rax + adcxq %rcx, %r13 + adoxq %rdx, %r12 + # A[3] * B[3] + movq 24(%rbp), %rdx + adoxq %rax, %r13 + mulxq 24(%rsi), %rax, %rcx + adoxq %r15, %r14 + adcxq %rax, %r14 + # A[0] * B[3] + mulxq (%rsi), %rdx, %rax + adcxq %rcx, %r15 + xorq %rcx, %rcx + adcxq %rdx, %r11 + # A[3] * B[0] + movq 24(%rsi), %rdx + adcxq %rax, %r12 + mulxq (%rbp), %rbx, %rax + adoxq %rbx, %r11 + adoxq %rax, %r12 + # A[3] * B[2] + mulxq 16(%rbp), %rdx, %rax + adcxq %rdx, %r13 + # A[2] * B[3] + movq 24(%rbp), %rdx + adcxq %rax, %r14 + mulxq 16(%rsi), %rax, %rdx + adcxq %rcx, %r15 + adoxq %rax, %r13 + adoxq %rdx, %r14 + adoxq %rcx, %r15 + # Start Reduction + # mu = a[0]-a[3] + a[0]-a[2] << 32 << 64 + (a[0] * 2) << 192 + # - a[0] << 32 << 192 + # + (a[0] * 2) << 192 + movq %r8, %rax + movq %r11, %rdx + addq %r8, %rdx + movq %r9, %rsi + addq %r8, %rdx + movq %r10, %rbp + # a[0]-a[2] << 32 + shlq $32, %r8 + shldq $32, %rsi, %r10 + shldq $32, %rax, %r9 + # - a[0] << 32 << 192 + subq %r8, %rdx + # + a[0]-a[2] << 32 << 64 + addq %r8, %rsi + adcq %r9, %rbp + adcq %r10, %rdx + # a += (mu << 256) - (mu << 224) + (mu << 192) + (mu << 96) - mu + # a += mu << 256 + xorq %r8, %r8 + addq %rax, %r12 + adcq %rsi, %r13 + adcq %rbp, %r14 + adcq %rdx, %r15 + sbbq $0, %r8 + # a += mu << 192 + addq %rax, %r11 + adcq %rsi, %r12 + adcq %rbp, %r13 + adcq %rdx, %r14 + adcq $0, %r15 + sbbq $0, %r8 + # mu <<= 32 + movq %rdx, %rcx + shldq $32, %rbp, %rdx + shldq $32, %rsi, %rbp + shldq $32, %rax, %rsi + shrq $32, %rcx + shlq $32, %rax + # a += (mu << 32) << 64 + addq %rbp, %r11 + adcq %rdx, %r12 + adcq %rcx, %r13 + adcq $0, %r14 + adcq $0, %r15 + sbbq $0, %r8 + # a -= (mu << 32) << 192 + subq %rax, %r11 + movq $4294967295, %rax + sbbq %rsi, %r12 + movq $18446744069414584321, %rsi + sbbq %rbp, %r13 + sbbq %rdx, %r14 + sbbq %rcx, %r15 + adcq $0, %r8 + # mask m and sub from result if overflow + # m[0] = -1 & mask = mask + andq %r8, %rax + # m[2] = 0 & mask = 0 + andq %r8, %rsi + subq %r8, %r12 + sbbq %rax, %r13 + sbbq $0, %r14 + sbbq %rsi, %r15 + movq %r12, (%rdi) + movq %r13, 8(%rdi) + movq %r14, 16(%rdi) + movq %r15, 24(%rdi) + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbp + pop %rbx + repz retq +#ifndef __APPLE__ +.size sp_256_mont_mul_avx2_4,.-sp_256_mont_mul_avx2_4 +#endif /* __APPLE__ */ +/* Square the Montgomery form number mod the modulus (prime). (r = a * a mod m) + * + * r Result of squaring. + * a Number to square in Montogmery form. + * m Modulus (prime). + * mp Montogmery mulitplier. + */ +#ifndef __APPLE__ +.globl sp_256_mont_sqr_avx2_4 +.type sp_256_mont_sqr_avx2_4,@function +.align 16 +sp_256_mont_sqr_avx2_4: +#else +.globl _sp_256_mont_sqr_avx2_4 +.p2align 4 +_sp_256_mont_sqr_avx2_4: +#endif /* __APPLE__ */ + push %r12 + push %r13 + push %r14 + push %r15 + push %rbx + # A[0] * A[1] + movq (%rsi), %rdx + mulxq 8(%rsi), %r9, %r10 + # A[0] * A[3] + mulxq 24(%rsi), %r11, %r12 + # A[2] * A[1] + movq 16(%rsi), %rdx + mulxq 8(%rsi), %rcx, %rbx + xorq %r15, %r15 + adoxq %rcx, %r11 + # A[2] * A[3] + mulxq 24(%rsi), %r13, %r14 + adoxq %rbx, %r12 + # A[2] * A[0] + mulxq (%rsi), %rcx, %rbx + adoxq %r15, %r13 + adcxq %rcx, %r10 + adoxq %r15, %r14 + # A[1] * A[3] + movq 8(%rsi), %rdx + mulxq 24(%rsi), %rax, %r8 + adcxq %rbx, %r11 + adcxq %rax, %r12 + adcxq %r8, %r13 + adcxq %r15, %r14 + # Double with Carry Flag + # A[0] * A[0] + movq (%rsi), %rdx + mulxq %rdx, %r8, %rax + adcxq %r9, %r9 + adcxq %r10, %r10 + adoxq %rax, %r9 + # A[1] * A[1] + movq 8(%rsi), %rdx + mulxq %rdx, %rcx, %rbx + adcxq %r11, %r11 + adoxq %rcx, %r10 + # A[2] * A[2] + movq 16(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adcxq %r12, %r12 + adoxq %rbx, %r11 + adcxq %r13, %r13 + adoxq %rax, %r12 + adcxq %r14, %r14 + # A[3] * A[3] + movq 24(%rsi), %rdx + mulxq %rdx, %rax, %rbx + adoxq %rcx, %r13 + adcxq %r15, %r15 + adoxq %rax, %r14 + adoxq %rbx, %r15 + # Start Reduction + # mu = a[0]-a[3] + a[0]-a[2] << 32 << 64 + (a[0] * 2) << 192 + # - a[0] << 32 << 192 + # + (a[0] * 2) << 192 + movq %r8, %rax + movq %r11, %rdx + addq %r8, %rdx + movq %r9, %rsi + addq %r8, %rdx + movq %r10, %rcx + # a[0]-a[2] << 32 + shlq $32, %r8 + shldq $32, %rsi, %r10 + shldq $32, %rax, %r9 + # - a[0] << 32 << 192 + subq %r8, %rdx + # + a[0]-a[2] << 32 << 64 + addq %r8, %rsi + adcq %r9, %rcx + adcq %r10, %rdx + # a += (mu << 256) - (mu << 224) + (mu << 192) + (mu << 96) - mu + # a += mu << 256 + movq $0, %r8 + addq %rax, %r12 + adcq %rsi, %r13 + adcq %rcx, %r14 + adcq %rdx, %r15 + sbbq $0, %r8 + # a += mu << 192 + addq %rax, %r11 + adcq %rsi, %r12 + adcq %rcx, %r13 + adcq %rdx, %r14 + adcq $0, %r15 + sbbq $0, %r8 + # mu <<= 32 + movq %rdx, %rbx + shldq $32, %rcx, %rdx + shldq $32, %rsi, %rcx + shldq $32, %rax, %rsi + shrq $32, %rbx + shlq $32, %rax + # a += (mu << 32) << 64 + addq %rcx, %r11 + adcq %rdx, %r12 + adcq %rbx, %r13 + adcq $0, %r14 + adcq $0, %r15 + sbbq $0, %r8 + # a -= (mu << 32) << 192 + subq %rax, %r11 + movq $4294967295, %rax + sbbq %rsi, %r12 + movq $18446744069414584321, %rsi + sbbq %rcx, %r13 + sbbq %rdx, %r14 + sbbq %rbx, %r15 + adcq $0, %r8 + # mask m and sub from result if overflow + # m[0] = -1 & mask = mask + andq %r8, %rax + # m[2] = 0 & mask = 0 + andq %r8, %rsi + subq %r8, %r12 + sbbq %rax, %r13 + sbbq $0, %r14 + sbbq %rsi, %r15 + movq %r12, (%rdi) + movq %r13, 8(%rdi) + movq %r14, 16(%rdi) + movq %r15, 24(%rdi) + pop %rbx + pop %r15 + pop %r14 + pop %r13 + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_256_mont_sqr_avx2_4,.-sp_256_mont_sqr_avx2_4 +#endif /* __APPLE__ */ +/* Add 1 to a. (a = a + 1) + * + * a A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_256_add_one_4 +.type sp_256_add_one_4,@function +.align 16 +sp_256_add_one_4: +#else +.globl _sp_256_add_one_4 +.p2align 4 +_sp_256_add_one_4: +#endif /* __APPLE__ */ + addq $1, (%rdi) + adcq $0, 8(%rdi) + adcq $0, 16(%rdi) + adcq $0, 24(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_256_add_one_4,.-sp_256_add_one_4 +#endif /* __APPLE__ */ +/* Add b to a into r. (r = a + b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_256_add_4 +.type sp_256_add_4,@function +.align 16 +sp_256_add_4: +#else +.globl _sp_256_add_4 +.p2align 4 +_sp_256_add_4: +#endif /* __APPLE__ */ + xorq %rax, %rax + movq (%rsi), %rcx + addq (%rdx), %rcx + movq %rcx, (%rdi) + movq 8(%rsi), %rcx + adcq 8(%rdx), %rcx + movq %rcx, 8(%rdi) + movq 16(%rsi), %rcx + adcq 16(%rdx), %rcx + movq %rcx, 16(%rdi) + movq 24(%rsi), %rcx + adcq 24(%rdx), %rcx + movq %rcx, 24(%rdi) + adcq $0, %rax + repz retq +#ifndef __APPLE__ +.size sp_256_add_4,.-sp_256_add_4 +#endif /* __APPLE__ */ +/* Multiply a and b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_256_mul_4 +.type sp_256_mul_4,@function +.align 16 +sp_256_mul_4: +#else +.globl _sp_256_mul_4 +.p2align 4 +_sp_256_mul_4: +#endif /* __APPLE__ */ + movq %rdx, %rcx + subq $32, %rsp + # A[0] * B[0] + movq (%rcx), %rax + mulq (%rsi) + xorq %r10, %r10 + movq %rax, (%rsp) + movq %rdx, %r9 + # A[0] * B[1] + movq 8(%rcx), %rax + mulq (%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[1] * B[0] + movq (%rcx), %rax + mulq 8(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + movq %r9, 8(%rsp) + # A[0] * B[2] + movq 16(%rcx), %rax + mulq (%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[1] * B[1] + movq 8(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[2] * B[0] + movq (%rcx), %rax + mulq 16(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + movq %r10, 16(%rsp) + # A[0] * B[3] + movq 24(%rcx), %rax + mulq (%rsi) + xorq %r10, %r10 + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[1] * B[2] + movq 16(%rcx), %rax + mulq 8(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[2] * B[1] + movq 8(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + # A[3] * B[0] + movq (%rcx), %rax + mulq 24(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %r10 + movq %r8, 24(%rsp) + # A[1] * B[3] + movq 24(%rcx), %rax + mulq 8(%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[2] * B[2] + movq 16(%rcx), %rax + mulq 16(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + # A[3] * B[1] + movq 8(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r9 + adcq %rdx, %r10 + adcq $0, %r8 + movq %r9, 32(%rdi) + # A[2] * B[3] + movq 24(%rcx), %rax + mulq 16(%rsi) + xorq %r9, %r9 + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + # A[3] * B[2] + movq 16(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r10 + adcq %rdx, %r8 + adcq $0, %r9 + movq %r10, 40(%rdi) + # A[3] * B[3] + movq 24(%rcx), %rax + mulq 24(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + movq %r8, 48(%rdi) + movq %r9, 56(%rdi) + movq (%rsp), %rax + movq 8(%rsp), %rdx + movq 16(%rsp), %r8 + movq 24(%rsp), %r9 + movq %rax, (%rdi) + movq %rdx, 8(%rdi) + movq %r8, 16(%rdi) + movq %r9, 24(%rdi) + addq $32, %rsp + repz retq +#ifndef __APPLE__ +.size sp_256_mul_4,.-sp_256_mul_4 +#endif /* __APPLE__ */ +/* Multiply a and b into r. (r = a * b) + * + * r Result of multiplication. + * a First number to multiply. + * b Second number to multiply. + */ +#ifndef __APPLE__ +.globl sp_256_mul_avx2_4 +.type sp_256_mul_avx2_4,@function +.align 16 +sp_256_mul_avx2_4: +#else +.globl _sp_256_mul_avx2_4 +.p2align 4 +_sp_256_mul_avx2_4: +#endif /* __APPLE__ */ + push %r12 + push %r13 + push %r14 + push %r15 + push %rbx + movq %rdx, %rax + # A[0] * B[0] + movq (%rax), %rdx + mulxq (%rsi), %r9, %r10 + # A[2] * B[0] + mulxq 16(%rsi), %r11, %r12 + # A[1] * B[0] + mulxq 8(%rsi), %rcx, %r8 + xorq %rbx, %rbx + adcxq %rcx, %r10 + # A[1] * B[3] + movq 24(%rax), %rdx + mulxq 8(%rsi), %r13, %r14 + adcxq %r8, %r11 + # A[0] * B[1] + movq 8(%rax), %rdx + mulxq (%rsi), %rcx, %r8 + adoxq %rcx, %r10 + # A[2] * B[1] + mulxq 16(%rsi), %rcx, %r15 + adoxq %r8, %r11 + adcxq %rcx, %r12 + # A[1] * B[2] + movq 16(%rax), %rdx + mulxq 8(%rsi), %rcx, %r8 + adcxq %r15, %r13 + adoxq %rcx, %r12 + adcxq %rbx, %r14 + adoxq %r8, %r13 + # A[0] * B[2] + mulxq (%rsi), %rcx, %r8 + adoxq %rbx, %r14 + xorq %r15, %r15 + adcxq %rcx, %r11 + # A[1] * B[1] + movq 8(%rax), %rdx + mulxq 8(%rsi), %rdx, %rcx + adcxq %r8, %r12 + adoxq %rdx, %r11 + # A[3] * B[1] + movq 8(%rax), %rdx + adoxq %rcx, %r12 + mulxq 24(%rsi), %rcx, %r8 + adcxq %rcx, %r13 + # A[2] * B[2] + movq 16(%rax), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %r8, %r14 + adoxq %rdx, %r13 + # A[3] * B[3] + movq 24(%rax), %rdx + adoxq %rcx, %r14 + mulxq 24(%rsi), %rcx, %r8 + adoxq %rbx, %r15 + adcxq %rcx, %r15 + # A[0] * B[3] + mulxq (%rsi), %rdx, %rcx + adcxq %r8, %rbx + xorq %r8, %r8 + adcxq %rdx, %r12 + # A[3] * B[0] + movq (%rax), %rdx + adcxq %rcx, %r13 + mulxq 24(%rsi), %rdx, %rcx + adoxq %rdx, %r12 + adoxq %rcx, %r13 + # A[2] * B[3] + movq 24(%rax), %rdx + mulxq 16(%rsi), %rdx, %rcx + adcxq %rdx, %r14 + # A[3] * B[2] + movq 16(%rax), %rdx + adcxq %rcx, %r15 + mulxq 24(%rsi), %rcx, %rdx + adcxq %r8, %rbx + adoxq %rcx, %r14 + adoxq %rdx, %r15 + adoxq %r8, %rbx + movq %r9, (%rdi) + movq %r10, 8(%rdi) + movq %r11, 16(%rdi) + movq %r12, 24(%rdi) + movq %r13, 32(%rdi) + movq %r14, 40(%rdi) + movq %r15, 48(%rdi) + movq %rbx, 56(%rdi) + pop %rbx + pop %r15 + pop %r14 + pop %r13 + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_256_mul_avx2_4,.-sp_256_mul_avx2_4 +#endif /* __APPLE__ */ +/* Sub b from a into a. (a -= b) + * + * a A single precision integer and result. + * b A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_256_sub_in_place_4 +.type sp_256_sub_in_place_4,@function +.align 16 +sp_256_sub_in_place_4: +#else +.globl _sp_256_sub_in_place_4 +.p2align 4 +_sp_256_sub_in_place_4: +#endif /* __APPLE__ */ + xorq %rax, %rax + movq (%rsi), %rdx + movq 8(%rsi), %rcx + movq 16(%rsi), %r8 + movq 24(%rsi), %r9 + subq %rdx, (%rdi) + sbbq %rcx, 8(%rdi) + sbbq %r8, 16(%rdi) + sbbq %r9, 24(%rdi) + sbbq $0, %rax + repz retq +#ifndef __APPLE__ +.size sp_256_sub_in_place_4,.-sp_256_sub_in_place_4 +#endif /* __APPLE__ */ +/* Mul a by digit b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision digit. + */ +#ifndef __APPLE__ +.globl sp_256_mul_d_4 +.type sp_256_mul_d_4,@function +.align 16 +sp_256_mul_d_4: +#else +.globl _sp_256_mul_d_4 +.p2align 4 +_sp_256_mul_d_4: +#endif /* __APPLE__ */ + movq %rdx, %rcx + # A[0] * B + movq %rcx, %rax + xorq %r10, %r10 + mulq (%rsi) + movq %rax, %r8 + movq %rdx, %r9 + movq %r8, (%rdi) + # A[1] * B + movq %rcx, %rax + xorq %r8, %r8 + mulq 8(%rsi) + addq %rax, %r9 + movq %r9, 8(%rdi) + adcq %rdx, %r10 + adcq $0, %r8 + # A[2] * B + movq %rcx, %rax + xorq %r9, %r9 + mulq 16(%rsi) + addq %rax, %r10 + movq %r10, 16(%rdi) + adcq %rdx, %r8 + adcq $0, %r9 + # # A[3] * B + movq %rcx, %rax + mulq 24(%rsi) + addq %rax, %r8 + adcq %rdx, %r9 + movq %r8, 24(%rdi) + movq %r9, 32(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_256_mul_d_4,.-sp_256_mul_d_4 +#endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 +/* Mul a by digit b into r. (r = a * b) + * + * r A single precision integer. + * a A single precision integer. + * b A single precision digit. + */ +#ifndef __APPLE__ +.globl sp_256_mul_d_avx2_4 +.type sp_256_mul_d_avx2_4,@function +.align 16 +sp_256_mul_d_avx2_4: +#else +.globl _sp_256_mul_d_avx2_4 +.p2align 4 +_sp_256_mul_d_avx2_4: +#endif /* __APPLE__ */ + movq %rdx, %rax + # A[0] * B + movq %rax, %rdx + xorq %r11, %r11 + mulxq (%rsi), %r9, %r10 + movq %r9, (%rdi) + # A[1] * B + mulxq 8(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + movq %r10, 8(%rdi) + adoxq %r8, %r9 + # A[2] * B + mulxq 16(%rsi), %rcx, %r8 + movq %r11, %r10 + adcxq %rcx, %r9 + movq %r9, 16(%rdi) + adoxq %r8, %r10 + # A[3] * B + mulxq 24(%rsi), %rcx, %r8 + movq %r11, %r9 + adcxq %rcx, %r10 + adoxq %r8, %r9 + adcxq %r11, %r9 + movq %r10, 24(%rdi) + movq %r9, 32(%rdi) + repz retq +#ifndef __APPLE__ +.size sp_256_mul_d_avx2_4,.-sp_256_mul_d_avx2_4 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ +/* Square a and put result in r. (r = a * a) + * + * r A single precision integer. + * a A single precision integer. + */ +#ifndef __APPLE__ +.globl sp_256_sqr_4 +.type sp_256_sqr_4,@function +.align 16 +sp_256_sqr_4: +#else +.globl _sp_256_sqr_4 +.p2align 4 +_sp_256_sqr_4: +#endif /* __APPLE__ */ + push %r12 + subq $32, %rsp + # A[0] * A[0] + movq (%rsi), %rax + mulq %rax + xorq %r9, %r9 + movq %rax, (%rsp) + movq %rdx, %r8 + # A[0] * A[1] + movq 8(%rsi), %rax + mulq (%rsi) + xorq %rcx, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + movq %r8, 8(%rsp) + # A[0] * A[2] + movq 16(%rsi), %rax + mulq (%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0, %r8 + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0, %r8 + # A[1] * A[1] + movq 8(%rsi), %rax + mulq %rax + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0, %r8 + movq %r9, 16(%rsp) + # A[0] * A[3] + movq 24(%rsi), %rax + mulq (%rsi) + xorq %r9, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + # A[1] * A[2] + movq 16(%rsi), %rax + mulq 8(%rsi) + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + addq %rax, %rcx + adcq %rdx, %r8 + adcq $0, %r9 + movq %rcx, 24(%rsp) + # A[1] * A[3] + movq 24(%rsi), %rax + mulq 8(%rsi) + xorq %rcx, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + # A[2] * A[2] + movq 16(%rsi), %rax + mulq %rax + addq %rax, %r8 + adcq %rdx, %r9 + adcq $0, %rcx + movq %r8, 32(%rdi) + # A[2] * A[3] + movq 24(%rsi), %rax + mulq 16(%rsi) + xorq %r8, %r8 + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0, %r8 + addq %rax, %r9 + adcq %rdx, %rcx + adcq $0, %r8 + movq %r9, 40(%rdi) + # A[3] * A[3] + movq 24(%rsi), %rax + mulq %rax + addq %rax, %rcx + adcq %rdx, %r8 + movq %rcx, 48(%rdi) + movq %r8, 56(%rdi) + movq (%rsp), %rax + movq 8(%rsp), %rdx + movq 16(%rsp), %r10 + movq 24(%rsp), %r11 + movq %rax, (%rdi) + movq %rdx, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + addq $32, %rsp + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_256_sqr_4,.-sp_256_sqr_4 +#endif /* __APPLE__ */ +/* Square a and put result in r. (r = a * a) + * + * r Result of squaring. + * a Number to square in Montogmery form. + */ +#ifndef __APPLE__ +.globl sp_256_sqr_avx2_4 +.type sp_256_sqr_avx2_4,@function +.align 16 +sp_256_sqr_avx2_4: +#else +.globl _sp_256_sqr_avx2_4 +.p2align 4 +_sp_256_sqr_avx2_4: +#endif /* __APPLE__ */ + push %rbx + push %r12 + push %r13 + push %r14 + push %r15 + # A[0] * A[1] + movq (%rsi), %rdx + mulxq 8(%rsi), %r9, %r10 + # A[0] * A[3] + mulxq 24(%rsi), %r11, %r12 + # A[2] * A[1] + movq 16(%rsi), %rdx + mulxq 8(%rsi), %rcx, %rbx + xorq %r15, %r15 + adoxq %rcx, %r11 + # A[2] * A[3] + mulxq 24(%rsi), %r13, %r14 + adoxq %rbx, %r12 + # A[2] * A[0] + mulxq (%rsi), %rcx, %rbx + adoxq %r15, %r13 + adcxq %rcx, %r10 + adoxq %r15, %r14 + # A[1] * A[3] + movq 8(%rsi), %rdx + mulxq 24(%rsi), %rax, %r8 + adcxq %rbx, %r11 + adcxq %rax, %r12 + adcxq %r8, %r13 + adcxq %r15, %r14 + # Double with Carry Flag + xorq %r15, %r15 + # A[0] * A[0] + movq (%rsi), %rdx + mulxq %rdx, %r8, %rax + adcxq %r9, %r9 + # A[1] * A[1] + movq 8(%rsi), %rdx + mulxq %rdx, %rcx, %rbx + adcxq %r10, %r10 + adoxq %rax, %r9 + adcxq %r11, %r11 + adoxq %rcx, %r10 + # A[2] * A[2] + movq 16(%rsi), %rdx + mulxq %rdx, %rax, %rcx + adcxq %r12, %r12 + adoxq %rbx, %r11 + adcxq %r13, %r13 + adoxq %rax, %r12 + # A[3] * A[3] + movq 24(%rsi), %rdx + mulxq %rdx, %rax, %rbx + adcxq %r14, %r14 + adoxq %rcx, %r13 + adcxq %r15, %r15 + adoxq %rax, %r14 + adoxq %rbx, %r15 + movq %r8, (%rdi) + movq %r9, 8(%rdi) + movq %r10, 16(%rdi) + movq %r11, 24(%rdi) + movq %r12, 32(%rdi) + movq %r13, 40(%rdi) + movq %r14, 48(%rdi) + movq %r15, 56(%rdi) + pop %r15 + pop %r14 + pop %r13 + pop %r12 + pop %rbx + repz retq +#ifndef __APPLE__ +.size sp_256_sqr_avx2_4,.-sp_256_sqr_avx2_4 +#endif /* __APPLE__ */ +#ifdef HAVE_INTEL_AVX2 +/* Reduce the number back to 256 bits using Montgomery reduction. + * + * a A single precision number to reduce in place. + * m The single precision number representing the modulus. + * mp The digit representing the negative inverse of m mod 2^n. + */ +#ifndef __APPLE__ +.globl sp_256_mont_reduce_avx2_4 +.type sp_256_mont_reduce_avx2_4,@function +.align 16 +sp_256_mont_reduce_avx2_4: +#else +.globl _sp_256_mont_reduce_avx2_4 +.p2align 4 +_sp_256_mont_reduce_avx2_4: +#endif /* __APPLE__ */ + push %r12 + push %r13 + push %r14 + push %r15 + push %rbx + movq %rdx, %rax + movq (%rdi), %r12 + movq 8(%rdi), %r13 + movq 16(%rdi), %r14 + movq 24(%rdi), %r15 + xorq %r11, %r11 + xorq %r10, %r10 + # a[0-4] += m[0-3] * mu = m[0-3] * (a[0] * mp) + movq 32(%rdi), %rbx + # mu = a[0] * mp + movq %r12, %rdx + mulxq %rax, %rdx, %rcx + # a[0] += m[0] * mu + mulx (%rsi), %r8, %r9 + adcxq %r8, %r12 + # a[1] += m[1] * mu + mulx 8(%rsi), %r8, %rcx + adoxq %r9, %r13 + adcxq %r8, %r13 + # a[2] += m[2] * mu + mulx 16(%rsi), %r8, %r9 + adoxq %rcx, %r14 + adcxq %r8, %r14 + # a[3] += m[3] * mu + mulx 24(%rsi), %r8, %rcx + adoxq %r9, %r15 + adcxq %r8, %r15 + # a[4] += carry + adoxq %rcx, %rbx + adcxq %r10, %rbx + # carry + adoxq %r10, %r11 + adcxq %r10, %r11 + # a[1-5] += m[0-3] * mu = m[0-3] * (a[1] * mp) + movq 40(%rdi), %r12 + # mu = a[1] * mp + movq %r13, %rdx + mulxq %rax, %rdx, %rcx + # a[1] += m[0] * mu + mulx (%rsi), %r8, %r9 + adcxq %r8, %r13 + # a[2] += m[1] * mu + mulx 8(%rsi), %r8, %rcx + adoxq %r9, %r14 + adcxq %r8, %r14 + # a[3] += m[2] * mu + mulx 16(%rsi), %r8, %r9 + adoxq %rcx, %r15 + adcxq %r8, %r15 + # a[4] += m[3] * mu + mulx 24(%rsi), %r8, %rcx + adoxq %r9, %rbx + adcxq %r8, %rbx + # a[5] += carry + adoxq %rcx, %r12 + adcxq %r11, %r12 + movq %r10, %r11 + # carry + adoxq %r10, %r11 + adcxq %r10, %r11 + # a[2-6] += m[0-3] * mu = m[0-3] * (a[2] * mp) + movq 48(%rdi), %r13 + # mu = a[2] * mp + movq %r14, %rdx + mulxq %rax, %rdx, %rcx + # a[2] += m[0] * mu + mulx (%rsi), %r8, %r9 + adcxq %r8, %r14 + # a[3] += m[1] * mu + mulx 8(%rsi), %r8, %rcx + adoxq %r9, %r15 + adcxq %r8, %r15 + # a[4] += m[2] * mu + mulx 16(%rsi), %r8, %r9 + adoxq %rcx, %rbx + adcxq %r8, %rbx + # a[5] += m[3] * mu + mulx 24(%rsi), %r8, %rcx + adoxq %r9, %r12 + adcxq %r8, %r12 + # a[6] += carry + adoxq %rcx, %r13 + adcxq %r11, %r13 + movq %r10, %r11 + # carry + adoxq %r10, %r11 + adcxq %r10, %r11 + # a[3-7] += m[0-3] * mu = m[0-3] * (a[3] * mp) + movq 56(%rdi), %r14 + # mu = a[3] * mp + movq %r15, %rdx + mulxq %rax, %rdx, %rcx + # a[3] += m[0] * mu + mulx (%rsi), %r8, %r9 + adcxq %r8, %r15 + # a[4] += m[1] * mu + mulx 8(%rsi), %r8, %rcx + adoxq %r9, %rbx + adcxq %r8, %rbx + # a[5] += m[2] * mu + mulx 16(%rsi), %r8, %r9 + adoxq %rcx, %r12 + adcxq %r8, %r12 + # a[6] += m[3] * mu + mulx 24(%rsi), %r8, %rcx + adoxq %r9, %r13 + adcxq %r8, %r13 + # a[7] += carry + adoxq %rcx, %r14 + adcxq %r11, %r14 + movq %r10, %r11 + # carry + adoxq %r10, %r11 + adcxq %r10, %r11 + # Subtract mod if carry + negq %r11 + movq $17562291160714782033, %r8 + movq $13611842547513532036, %r9 + movq $18446744069414584320, %rdx + andq %r11, %r8 + andq %r11, %r9 + movq %r11, %r11 + andq %r11, %rdx + subq %r8, %rbx + sbbq %r9, %r12 + sbbq %r11, %r13 + sbbq %rdx, %r14 + movq %rbx, (%rdi) + movq %r12, 8(%rdi) + movq %r13, 16(%rdi) + movq %r14, 24(%rdi) + pop %rbx + pop %r15 + pop %r14 + pop %r13 + pop %r12 + repz retq +#ifndef __APPLE__ +.size sp_256_mont_reduce_avx2_4,.-sp_256_mont_reduce_avx2_4 +#endif /* __APPLE__ */ +#endif /* HAVE_INTEL_AVX2 */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/srp.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/srp.c new file mode 100755 index 0000000..017f67c --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/srp.c @@ -0,0 +1,756 @@ +/* srp.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifdef WOLFCRYPT_HAVE_SRP + +#include +#include +#include + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +/** Computes the session key using the Mask Generation Function 1. */ +static int wc_SrpSetKey(Srp* srp, byte* secret, word32 size); + +static int SrpHashInit(SrpHash* hash, SrpType type) +{ + hash->type = type; + + switch (type) { + case SRP_TYPE_SHA: + #ifndef NO_SHA + return wc_InitSha(&hash->data.sha); + #else + return BAD_FUNC_ARG; + #endif + + case SRP_TYPE_SHA256: + #ifndef NO_SHA256 + return wc_InitSha256(&hash->data.sha256); + #else + return BAD_FUNC_ARG; + #endif + + case SRP_TYPE_SHA384: + #ifdef WOLFSSL_SHA384 + return wc_InitSha384(&hash->data.sha384); + #else + return BAD_FUNC_ARG; + #endif + + case SRP_TYPE_SHA512: + #ifdef WOLFSSL_SHA512 + return wc_InitSha512(&hash->data.sha512); + #else + return BAD_FUNC_ARG; + #endif + + default: + return BAD_FUNC_ARG; + } +} + +static int SrpHashUpdate(SrpHash* hash, const byte* data, word32 size) +{ + switch (hash->type) { + case SRP_TYPE_SHA: + #ifndef NO_SHA + return wc_ShaUpdate(&hash->data.sha, data, size); + #else + return BAD_FUNC_ARG; + #endif + + case SRP_TYPE_SHA256: + #ifndef NO_SHA256 + return wc_Sha256Update(&hash->data.sha256, data, size); + #else + return BAD_FUNC_ARG; + #endif + + case SRP_TYPE_SHA384: + #ifdef WOLFSSL_SHA384 + return wc_Sha384Update(&hash->data.sha384, data, size); + #else + return BAD_FUNC_ARG; + #endif + + case SRP_TYPE_SHA512: + #ifdef WOLFSSL_SHA512 + return wc_Sha512Update(&hash->data.sha512, data, size); + #else + return BAD_FUNC_ARG; + #endif + + default: + return BAD_FUNC_ARG; + } +} + +static int SrpHashFinal(SrpHash* hash, byte* digest) +{ + switch (hash->type) { + case SRP_TYPE_SHA: + #ifndef NO_SHA + return wc_ShaFinal(&hash->data.sha, digest); + #else + return BAD_FUNC_ARG; + #endif + + case SRP_TYPE_SHA256: + #ifndef NO_SHA256 + return wc_Sha256Final(&hash->data.sha256, digest); + #else + return BAD_FUNC_ARG; + #endif + + case SRP_TYPE_SHA384: + #ifdef WOLFSSL_SHA384 + return wc_Sha384Final(&hash->data.sha384, digest); + #else + return BAD_FUNC_ARG; + #endif + + case SRP_TYPE_SHA512: + #ifdef WOLFSSL_SHA512 + return wc_Sha512Final(&hash->data.sha512, digest); + #else + return BAD_FUNC_ARG; + #endif + + default: + return BAD_FUNC_ARG; + } +} + +static word32 SrpHashSize(SrpType type) +{ + switch (type) { + case SRP_TYPE_SHA: + #ifndef NO_SHA + return WC_SHA_DIGEST_SIZE; + #else + return 0; + #endif + + case SRP_TYPE_SHA256: + #ifndef NO_SHA256 + return WC_SHA256_DIGEST_SIZE; + #else + return 0; + #endif + + case SRP_TYPE_SHA384: + #ifdef WOLFSSL_SHA384 + return WC_SHA384_DIGEST_SIZE; + #else + return 0; + #endif + + case SRP_TYPE_SHA512: + #ifdef WOLFSSL_SHA512 + return WC_SHA512_DIGEST_SIZE; + #else + return 0; + #endif + + default: + return 0; + } +} + +int wc_SrpInit(Srp* srp, SrpType type, SrpSide side) +{ + int r; + + /* validating params */ + + if (!srp) + return BAD_FUNC_ARG; + + if (side != SRP_CLIENT_SIDE && side != SRP_SERVER_SIDE) + return BAD_FUNC_ARG; + + switch (type) { + case SRP_TYPE_SHA: + #ifdef NO_SHA + return NOT_COMPILED_IN; + #else + break; /* OK */ + #endif + + case SRP_TYPE_SHA256: + #ifdef NO_SHA256 + return NOT_COMPILED_IN; + #else + break; /* OK */ + #endif + + case SRP_TYPE_SHA384: + #ifndef WOLFSSL_SHA384 + return NOT_COMPILED_IN; + #else + break; /* OK */ + #endif + + case SRP_TYPE_SHA512: + #ifndef WOLFSSL_SHA512 + return NOT_COMPILED_IN; + #else + break; /* OK */ + #endif + + default: + return BAD_FUNC_ARG; + } + + /* initializing variables */ + + XMEMSET(srp, 0, sizeof(Srp)); + + if ((r = SrpHashInit(&srp->client_proof, type)) != 0) + return r; + + if ((r = SrpHashInit(&srp->server_proof, type)) != 0) + return r; + + if ((r = mp_init_multi(&srp->N, &srp->g, &srp->auth, + &srp->priv, 0, 0)) != 0) + return r; + + srp->side = side; srp->type = type; + srp->salt = NULL; srp->saltSz = 0; + srp->user = NULL; srp->userSz = 0; + srp->key = NULL; srp->keySz = 0; + + srp->keyGenFunc_cb = wc_SrpSetKey; + + /* default heap hint to NULL or test value */ +#ifdef WOLFSSL_HEAP_TEST + srp->heap = (void*)WOLFSSL_HEAP_TEST; +#else + srp->heap = NULL; +#endif + + return 0; +} + +void wc_SrpTerm(Srp* srp) +{ + if (srp) { + mp_clear(&srp->N); mp_clear(&srp->g); + mp_clear(&srp->auth); mp_clear(&srp->priv); + if (srp->salt) { + ForceZero(srp->salt, srp->saltSz); + XFREE(srp->salt, srp->heap, DYNAMIC_TYPE_SRP); + } + if (srp->user) { + ForceZero(srp->user, srp->userSz); + XFREE(srp->user, srp->heap, DYNAMIC_TYPE_SRP); + } + if (srp->key) { + ForceZero(srp->key, srp->keySz); + XFREE(srp->key, srp->heap, DYNAMIC_TYPE_SRP); + } + + ForceZero(srp, sizeof(Srp)); + } +} + +int wc_SrpSetUsername(Srp* srp, const byte* username, word32 size) +{ + if (!srp || !username) + return BAD_FUNC_ARG; + + srp->user = (byte*)XMALLOC(size, srp->heap, DYNAMIC_TYPE_SRP); + if (srp->user == NULL) + return MEMORY_E; + + srp->userSz = size; + XMEMCPY(srp->user, username, srp->userSz); + + return 0; +} + +int wc_SrpSetParams(Srp* srp, const byte* N, word32 nSz, + const byte* g, word32 gSz, + const byte* salt, word32 saltSz) +{ + SrpHash hash; + byte digest1[SRP_MAX_DIGEST_SIZE]; + byte digest2[SRP_MAX_DIGEST_SIZE]; + byte pad = 0; + int i, r; + int j = 0; + + if (!srp || !N || !g || !salt || nSz < gSz) + return BAD_FUNC_ARG; + + if (!srp->user) + return SRP_CALL_ORDER_E; + + /* Set N */ + if (mp_read_unsigned_bin(&srp->N, N, nSz) != MP_OKAY) + return MP_READ_E; + + if (mp_count_bits(&srp->N) < SRP_MODULUS_MIN_BITS) + return BAD_FUNC_ARG; + + /* Set g */ + if (mp_read_unsigned_bin(&srp->g, g, gSz) != MP_OKAY) + return MP_READ_E; + + if (mp_cmp(&srp->N, &srp->g) != MP_GT) + return BAD_FUNC_ARG; + + /* Set salt */ + if (srp->salt) { + ForceZero(srp->salt, srp->saltSz); + XFREE(srp->salt, srp->heap, DYNAMIC_TYPE_SRP); + } + + srp->salt = (byte*)XMALLOC(saltSz, srp->heap, DYNAMIC_TYPE_SRP); + if (srp->salt == NULL) + return MEMORY_E; + + XMEMCPY(srp->salt, salt, saltSz); + srp->saltSz = saltSz; + + /* Set k = H(N, g) */ + r = SrpHashInit(&hash, srp->type); + if (!r) r = SrpHashUpdate(&hash, (byte*) N, nSz); + for (i = 0; (word32)i < nSz - gSz; i++) { + if (!r) r = SrpHashUpdate(&hash, &pad, 1); + } + if (!r) r = SrpHashUpdate(&hash, (byte*) g, gSz); + if (!r) r = SrpHashFinal(&hash, srp->k); + + /* update client proof */ + + /* digest1 = H(N) */ + if (!r) r = SrpHashInit(&hash, srp->type); + if (!r) r = SrpHashUpdate(&hash, (byte*) N, nSz); + if (!r) r = SrpHashFinal(&hash, digest1); + + /* digest2 = H(g) */ + if (!r) r = SrpHashInit(&hash, srp->type); + if (!r) r = SrpHashUpdate(&hash, (byte*) g, gSz); + if (!r) r = SrpHashFinal(&hash, digest2); + + /* digest1 = H(N) ^ H(g) */ + if (r == 0) { + for (i = 0, j = SrpHashSize(srp->type); i < j; i++) + digest1[i] ^= digest2[i]; + } + + /* digest2 = H(user) */ + if (!r) r = SrpHashInit(&hash, srp->type); + if (!r) r = SrpHashUpdate(&hash, srp->user, srp->userSz); + if (!r) r = SrpHashFinal(&hash, digest2); + + /* client proof = H( H(N) ^ H(g) | H(user) | salt) */ + if (!r) r = SrpHashUpdate(&srp->client_proof, digest1, j); + if (!r) r = SrpHashUpdate(&srp->client_proof, digest2, j); + if (!r) r = SrpHashUpdate(&srp->client_proof, salt, saltSz); + + return r; +} + +int wc_SrpSetPassword(Srp* srp, const byte* password, word32 size) +{ + SrpHash hash; + byte digest[SRP_MAX_DIGEST_SIZE]; + word32 digestSz; + int r; + + if (!srp || !password || srp->side != SRP_CLIENT_SIDE) + return BAD_FUNC_ARG; + + if (!srp->salt) + return SRP_CALL_ORDER_E; + + digestSz = SrpHashSize(srp->type); + + /* digest = H(username | ':' | password) */ + r = SrpHashInit(&hash, srp->type); + if (!r) r = SrpHashUpdate(&hash, srp->user, srp->userSz); + if (!r) r = SrpHashUpdate(&hash, (const byte*) ":", 1); + if (!r) r = SrpHashUpdate(&hash, password, size); + if (!r) r = SrpHashFinal(&hash, digest); + + /* digest = H(salt | H(username | ':' | password)) */ + if (!r) r = SrpHashInit(&hash, srp->type); + if (!r) r = SrpHashUpdate(&hash, srp->salt, srp->saltSz); + if (!r) r = SrpHashUpdate(&hash, digest, digestSz); + if (!r) r = SrpHashFinal(&hash, digest); + + /* Set x (private key) */ + if (!r) r = mp_read_unsigned_bin(&srp->auth, digest, digestSz); + + ForceZero(digest, SRP_MAX_DIGEST_SIZE); + + return r; +} + +int wc_SrpGetVerifier(Srp* srp, byte* verifier, word32* size) +{ + mp_int v; + int r; + + if (!srp || !verifier || !size || srp->side != SRP_CLIENT_SIDE) + return BAD_FUNC_ARG; + + if (mp_iszero(&srp->auth) == MP_YES) + return SRP_CALL_ORDER_E; + + r = mp_init(&v); + if (r != MP_OKAY) + return MP_INIT_E; + + /* v = g ^ x % N */ + if (!r) r = mp_exptmod(&srp->g, &srp->auth, &srp->N, &v); + if (!r) r = *size < (word32)mp_unsigned_bin_size(&v) ? BUFFER_E : MP_OKAY; + if (!r) r = mp_to_unsigned_bin(&v, verifier); + if (!r) *size = mp_unsigned_bin_size(&v); + + mp_clear(&v); + + return r; +} + +int wc_SrpSetVerifier(Srp* srp, const byte* verifier, word32 size) +{ + if (!srp || !verifier || srp->side != SRP_SERVER_SIDE) + return BAD_FUNC_ARG; + + return mp_read_unsigned_bin(&srp->auth, verifier, size); +} + +int wc_SrpSetPrivate(Srp* srp, const byte* priv, word32 size) +{ + mp_int p; + int r; + + if (!srp || !priv || !size) + return BAD_FUNC_ARG; + + if (mp_iszero(&srp->auth) == MP_YES) + return SRP_CALL_ORDER_E; + + r = mp_init(&p); + if (r != MP_OKAY) + return MP_INIT_E; + if (!r) r = mp_read_unsigned_bin(&p, priv, size); + if (!r) r = mp_mod(&p, &srp->N, &srp->priv); + if (!r) r = mp_iszero(&srp->priv) == MP_YES ? SRP_BAD_KEY_E : 0; + + mp_clear(&p); + + return r; +} + +/** Generates random data using wolfcrypt RNG. */ +static int wc_SrpGenPrivate(Srp* srp, byte* priv, word32 size) +{ + WC_RNG rng; + int r = wc_InitRng(&rng); + + if (!r) r = wc_RNG_GenerateBlock(&rng, priv, size); + if (!r) r = wc_SrpSetPrivate(srp, priv, size); + if (!r) wc_FreeRng(&rng); + + return r; +} + +int wc_SrpGetPublic(Srp* srp, byte* pub, word32* size) +{ + mp_int pubkey; + word32 modulusSz; + int r; + + if (!srp || !pub || !size) + return BAD_FUNC_ARG; + + if (mp_iszero(&srp->auth) == MP_YES) + return SRP_CALL_ORDER_E; + + modulusSz = mp_unsigned_bin_size(&srp->N); + if (*size < modulusSz) + return BUFFER_E; + + r = mp_init(&pubkey); + if (r != MP_OKAY) + return MP_INIT_E; + + /* priv = random() */ + if (mp_iszero(&srp->priv) == MP_YES) + r = wc_SrpGenPrivate(srp, pub, SRP_PRIVATE_KEY_MIN_BITS / 8); + + /* client side: A = g ^ a % N */ + if (srp->side == SRP_CLIENT_SIDE) { + if (!r) r = mp_exptmod(&srp->g, &srp->priv, &srp->N, &pubkey); + + /* server side: B = (k * v + (g ^ b % N)) % N */ + } else { + mp_int i, j; + + if (mp_init_multi(&i, &j, 0, 0, 0, 0) == MP_OKAY) { + if (!r) r = mp_read_unsigned_bin(&i, srp->k,SrpHashSize(srp->type)); + if (!r) r = mp_iszero(&i) == MP_YES ? SRP_BAD_KEY_E : 0; + if (!r) r = mp_exptmod(&srp->g, &srp->priv, &srp->N, &pubkey); + if (!r) r = mp_mulmod(&i, &srp->auth, &srp->N, &j); + if (!r) r = mp_add(&j, &pubkey, &i); + if (!r) r = mp_mod(&i, &srp->N, &pubkey); + + mp_clear(&i); mp_clear(&j); + } + } + + /* extract public key to buffer */ + XMEMSET(pub, 0, modulusSz); + if (!r) r = mp_to_unsigned_bin(&pubkey, pub); + if (!r) *size = mp_unsigned_bin_size(&pubkey); + mp_clear(&pubkey); + + return r; +} + +static int wc_SrpSetKey(Srp* srp, byte* secret, word32 size) +{ + SrpHash hash; + byte digest[SRP_MAX_DIGEST_SIZE]; + word32 i, j, digestSz = SrpHashSize(srp->type); + byte counter[4]; + int r = BAD_FUNC_ARG; + + XMEMSET(digest, 0, SRP_MAX_DIGEST_SIZE); + + srp->key = (byte*)XMALLOC(2 * digestSz, srp->heap, DYNAMIC_TYPE_SRP); + if (srp->key == NULL) + return MEMORY_E; + + srp->keySz = 2 * digestSz; + + for (i = j = 0; j < srp->keySz; i++) { + counter[0] = (i >> 24) & 0xFF; + counter[1] = (i >> 16) & 0xFF; + counter[2] = (i >> 8) & 0xFF; + counter[3] = i & 0xFF; + + r = SrpHashInit(&hash, srp->type); + if (!r) r = SrpHashUpdate(&hash, secret, size); + if (!r) r = SrpHashUpdate(&hash, counter, 4); + + if (j + digestSz > srp->keySz) { + if (!r) r = SrpHashFinal(&hash, digest); + XMEMCPY(srp->key + j, digest, srp->keySz - j); + j = srp->keySz; + } + else { + if (!r) r = SrpHashFinal(&hash, srp->key + j); + j += digestSz; + } + } + + ForceZero(digest, sizeof(digest)); + ForceZero(&hash, sizeof(SrpHash)); + + return r; +} + +int wc_SrpComputeKey(Srp* srp, byte* clientPubKey, word32 clientPubKeySz, + byte* serverPubKey, word32 serverPubKeySz) +{ + SrpHash hash; + byte *secret; + byte digest[SRP_MAX_DIGEST_SIZE]; + word32 i, secretSz, digestSz; + mp_int u, s, temp1, temp2; + byte pad = 0; + int r; + + /* validating params */ + + if (!srp || !clientPubKey || clientPubKeySz == 0 + || !serverPubKey || serverPubKeySz == 0) + return BAD_FUNC_ARG; + + if (mp_iszero(&srp->priv) == MP_YES) + return SRP_CALL_ORDER_E; + + /* initializing variables */ + + if ((r = SrpHashInit(&hash, srp->type)) != 0) + return r; + + digestSz = SrpHashSize(srp->type); + secretSz = mp_unsigned_bin_size(&srp->N); + + if ((secret = (byte*)XMALLOC(secretSz, srp->heap, DYNAMIC_TYPE_SRP)) ==NULL) + return MEMORY_E; + + if ((r = mp_init_multi(&u, &s, &temp1, &temp2, 0, 0)) != MP_OKAY) { + XFREE(secret, srp->heap, DYNAMIC_TYPE_SRP); + return r; + } + + /* building u (random scrambling parameter) */ + + /* H(A) */ + for (i = 0; !r && i < secretSz - clientPubKeySz; i++) + r = SrpHashUpdate(&hash, &pad, 1); + if (!r) r = SrpHashUpdate(&hash, clientPubKey, clientPubKeySz); + + /* H(A | B) */ + for (i = 0; !r && i < secretSz - serverPubKeySz; i++) + r = SrpHashUpdate(&hash, &pad, 1); + if (!r) r = SrpHashUpdate(&hash, serverPubKey, serverPubKeySz); + + /* set u */ + if (!r) r = SrpHashFinal(&hash, digest); + if (!r) r = mp_read_unsigned_bin(&u, digest, SrpHashSize(srp->type)); + + /* building s (secret) */ + + if (!r && srp->side == SRP_CLIENT_SIDE) { + + /* temp1 = B - k * v; rejects k == 0, B == 0 and B >= N. */ + r = mp_read_unsigned_bin(&temp1, srp->k, digestSz); + if (!r) r = mp_iszero(&temp1) == MP_YES ? SRP_BAD_KEY_E : 0; + if (!r) r = mp_exptmod(&srp->g, &srp->auth, &srp->N, &temp2); + if (!r) r = mp_mulmod(&temp1, &temp2, &srp->N, &s); + if (!r) r = mp_read_unsigned_bin(&temp2, serverPubKey, serverPubKeySz); + if (!r) r = mp_iszero(&temp2) == MP_YES ? SRP_BAD_KEY_E : 0; + if (!r) r = mp_cmp(&temp2, &srp->N) != MP_LT ? SRP_BAD_KEY_E : 0; + if (!r) r = mp_sub(&temp2, &s, &temp1); + + /* temp2 = a + u * x */ + if (!r) r = mp_mulmod(&u, &srp->auth, &srp->N, &s); + if (!r) r = mp_add(&srp->priv, &s, &temp2); + + /* secret = temp1 ^ temp2 % N */ + if (!r) r = mp_exptmod(&temp1, &temp2, &srp->N, &s); + + } else if (!r && srp->side == SRP_SERVER_SIDE) { + /* temp1 = v ^ u % N */ + r = mp_exptmod(&srp->auth, &u, &srp->N, &temp1); + + /* temp2 = A * temp1 % N; rejects A == 0, A >= N */ + if (!r) r = mp_read_unsigned_bin(&s, clientPubKey, clientPubKeySz); + if (!r) r = mp_iszero(&s) == MP_YES ? SRP_BAD_KEY_E : 0; + if (!r) r = mp_cmp(&s, &srp->N) != MP_LT ? SRP_BAD_KEY_E : 0; + if (!r) r = mp_mulmod(&s, &temp1, &srp->N, &temp2); + + /* rejects A * v ^ u % N >= 1, A * v ^ u % N == -1 % N */ + if (!r) r = mp_read_unsigned_bin(&temp1, (const byte*)"\001", 1); + if (!r) r = mp_cmp(&temp2, &temp1) != MP_GT ? SRP_BAD_KEY_E : 0; + if (!r) r = mp_sub(&srp->N, &temp1, &s); + if (!r) r = mp_cmp(&temp2, &s) == MP_EQ ? SRP_BAD_KEY_E : 0; + + /* secret = temp2 * b % N */ + if (!r) r = mp_exptmod(&temp2, &srp->priv, &srp->N, &s); + } + + /* building session key from secret */ + + if (!r) r = mp_to_unsigned_bin(&s, secret); + if (!r) r = srp->keyGenFunc_cb(srp, secret, mp_unsigned_bin_size(&s)); + + /* updating client proof = H( H(N) ^ H(g) | H(user) | salt | A | B | K) */ + + if (!r) r = SrpHashUpdate(&srp->client_proof, clientPubKey, clientPubKeySz); + if (!r) r = SrpHashUpdate(&srp->client_proof, serverPubKey, serverPubKeySz); + if (!r) r = SrpHashUpdate(&srp->client_proof, srp->key, srp->keySz); + + /* updating server proof = H(A) */ + + if (!r) r = SrpHashUpdate(&srp->server_proof, clientPubKey, clientPubKeySz); + + XFREE(secret, srp->heap, DYNAMIC_TYPE_SRP); + mp_clear(&u); mp_clear(&s); mp_clear(&temp1); mp_clear(&temp2); + + return r; +} + +int wc_SrpGetProof(Srp* srp, byte* proof, word32* size) +{ + int r; + + if (!srp || !proof || !size) + return BAD_FUNC_ARG; + + if (*size < SrpHashSize(srp->type)) + return BUFFER_E; + + if ((r = SrpHashFinal(srp->side == SRP_CLIENT_SIDE + ? &srp->client_proof + : &srp->server_proof, proof)) != 0) + return r; + + *size = SrpHashSize(srp->type); + + if (srp->side == SRP_CLIENT_SIDE) { + /* server proof = H( A | client proof | K) */ + if (!r) r = SrpHashUpdate(&srp->server_proof, proof, *size); + if (!r) r = SrpHashUpdate(&srp->server_proof, srp->key, srp->keySz); + } + + return r; +} + +int wc_SrpVerifyPeersProof(Srp* srp, byte* proof, word32 size) +{ + byte digest[SRP_MAX_DIGEST_SIZE]; + int r; + + if (!srp || !proof) + return BAD_FUNC_ARG; + + if (size != SrpHashSize(srp->type)) + return BUFFER_E; + + r = SrpHashFinal(srp->side == SRP_CLIENT_SIDE ? &srp->server_proof + : &srp->client_proof, digest); + + if (srp->side == SRP_SERVER_SIDE) { + /* server proof = H( A | client proof | K) */ + if (!r) r = SrpHashUpdate(&srp->server_proof, proof, size); + if (!r) r = SrpHashUpdate(&srp->server_proof, srp->key, srp->keySz); + } + + if (!r && XMEMCMP(proof, digest, size) != 0) + r = SRP_VERIFY_E; + + return r; +} + +#endif /* WOLFCRYPT_HAVE_SRP */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/tfm.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/tfm.c new file mode 100755 index 0000000..99a4281 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/tfm.c @@ -0,0 +1,4455 @@ +/* tfm.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +/* + * Based on public domain TomsFastMath 0.10 by Tom St Denis, tomstdenis@iahu.ca, + * http://math.libtomcrypt.com + */ + +/** + * Edited by Moises Guimaraes (moises@wolfssl.com) + * to fit wolfSSL's needs. + */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +/* in case user set USE_FAST_MATH there */ +#include +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#ifdef USE_FAST_MATH + +#include +#include +#include /* will define asm MACROS or C ones */ +#include /* common functions */ + +#if defined(FREESCALE_LTC_TFM) + #include +#endif +#ifdef WOLFSSL_DEBUG_MATH + #include +#endif + +#ifdef USE_WINDOWS_API + #pragma warning(disable:4127) + /* Disables the warning: + * 4127: conditional expression is constant + * in this file. + */ +#endif + +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) +#ifdef __cplusplus + extern "C" { +#endif +WOLFSSL_LOCAL int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, + mp_int* res); +WOLFSSL_LOCAL int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, + mp_int* res); +WOLFSSL_LOCAL int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, + mp_int* res); +WOLFSSL_LOCAL int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, + mp_int* res); +#ifdef __cplusplus + } /* extern "C" */ +#endif +#endif + + + +/* math settings check */ +word32 CheckRunTimeSettings(void) +{ + return CTC_SETTINGS; +} + + +/* math settings size check */ +word32 CheckRunTimeFastMath(void) +{ + return FP_SIZE; +} + + +/* Functions */ + +void fp_add(fp_int *a, fp_int *b, fp_int *c) +{ + int sa, sb; + + /* get sign of both inputs */ + sa = a->sign; + sb = b->sign; + + /* handle two cases, not four */ + if (sa == sb) { + /* both positive or both negative */ + /* add their magnitudes, copy the sign */ + c->sign = sa; + s_fp_add (a, b, c); + } else { + /* one positive, the other negative */ + /* subtract the one with the greater magnitude from */ + /* the one of the lesser magnitude. The result gets */ + /* the sign of the one with the greater magnitude. */ + if (fp_cmp_mag (a, b) == FP_LT) { + c->sign = sb; + s_fp_sub (b, a, c); + } else { + c->sign = sa; + s_fp_sub (a, b, c); + } + } +} + +/* unsigned addition */ +void s_fp_add(fp_int *a, fp_int *b, fp_int *c) +{ + int x, y, oldused; + fp_word t; + + y = MAX(a->used, b->used); + oldused = MIN(c->used, FP_SIZE); /* help static analysis w/ largest size */ + c->used = y; + + t = 0; + for (x = 0; x < y; x++) { + t += ((fp_word)a->dp[x]) + ((fp_word)b->dp[x]); + c->dp[x] = (fp_digit)t; + t >>= DIGIT_BIT; + } + if (t != 0 && x < FP_SIZE) { + c->dp[c->used++] = (fp_digit)t; + ++x; + } + + c->used = x; + + /* zero any excess digits on the destination that we didn't write to */ + for (; x < oldused; x++) { + c->dp[x] = 0; + } + fp_clamp(c); +} + +/* c = a - b */ +void fp_sub(fp_int *a, fp_int *b, fp_int *c) +{ + int sa, sb; + + sa = a->sign; + sb = b->sign; + + if (sa != sb) { + /* subtract a negative from a positive, OR */ + /* subtract a positive from a negative. */ + /* In either case, ADD their magnitudes, */ + /* and use the sign of the first number. */ + c->sign = sa; + s_fp_add (a, b, c); + } else { + /* subtract a positive from a positive, OR */ + /* subtract a negative from a negative. */ + /* First, take the difference between their */ + /* magnitudes, then... */ + if (fp_cmp_mag (a, b) != FP_LT) { + /* Copy the sign from the first */ + c->sign = sa; + /* The first has a larger or equal magnitude */ + s_fp_sub (a, b, c); + } else { + /* The result has the *opposite* sign from */ + /* the first number. */ + c->sign = (sa == FP_ZPOS) ? FP_NEG : FP_ZPOS; + /* The second has a larger magnitude */ + s_fp_sub (b, a, c); + } + } +} + +/* unsigned subtraction ||a|| >= ||b|| ALWAYS! */ +void s_fp_sub(fp_int *a, fp_int *b, fp_int *c) +{ + int x, oldbused, oldused; + fp_word t; + + oldused = c->used; + oldbused = b->used; + c->used = a->used; + t = 0; + for (x = 0; x < oldbused; x++) { + t = ((fp_word)a->dp[x]) - (((fp_word)b->dp[x]) + t); + c->dp[x] = (fp_digit)t; + t = (t >> DIGIT_BIT)&1; + } + for (; x < a->used; x++) { + t = ((fp_word)a->dp[x]) - t; + c->dp[x] = (fp_digit)t; + t = (t >> DIGIT_BIT)&1; + } + + /* zero any excess digits on the destination that we didn't write to */ + for (; x < oldused; x++) { + c->dp[x] = 0; + } + fp_clamp(c); +} + +/* c = a * b */ +int fp_mul(fp_int *A, fp_int *B, fp_int *C) +{ + int ret = 0; + int y, yy, oldused; + +#if defined(WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI) + ret = esp_mp_mul(A, B, C); + if(ret != -2) return ret; +#endif + + oldused = C->used; + + y = MAX(A->used, B->used); + yy = MIN(A->used, B->used); + + /* call generic if we're out of range */ + if (y + yy > FP_SIZE) { + ret = fp_mul_comba(A, B, C); + goto clean; + } + + /* pick a comba (unrolled 4/8/16/32 x or rolled) based on the size + of the largest input. We also want to avoid doing excess mults if the + inputs are not close to the next power of two. That is, for example, + if say y=17 then we would do (32-17)^2 = 225 unneeded multiplications + */ + +#if defined(TFM_MUL3) && FP_SIZE >= 6 + if (y <= 3) { + ret = fp_mul_comba3(A,B,C); + goto clean; + } +#endif +#if defined(TFM_MUL4) && FP_SIZE >= 8 + if (y == 4) { + ret = fp_mul_comba4(A,B,C); + goto clean; + } +#endif +#if defined(TFM_MUL6) && FP_SIZE >= 12 + if (y <= 6) { + ret = fp_mul_comba6(A,B,C); + goto clean; + } +#endif +#if defined(TFM_MUL7) && FP_SIZE >= 14 + if (y == 7) { + ret = fp_mul_comba7(A,B,C); + goto clean; + } +#endif +#if defined(TFM_MUL8) && FP_SIZE >= 16 + if (y == 8) { + ret = fp_mul_comba8(A,B,C); + goto clean; + } +#endif +#if defined(TFM_MUL9) && FP_SIZE >= 18 + if (y == 9) { + ret = fp_mul_comba9(A,B,C); + goto clean; + } +#endif +#if defined(TFM_MUL12) && FP_SIZE >= 24 + if (y <= 12) { + ret = fp_mul_comba12(A,B,C); + goto clean; + } +#endif +#if defined(TFM_MUL17) && FP_SIZE >= 34 + if (y <= 17) { + ret = fp_mul_comba17(A,B,C); + goto clean; + } +#endif + +#if defined(TFM_SMALL_SET) && FP_SIZE >= 32 + if (y <= 16) { + ret = fp_mul_comba_small(A,B,C); + goto clean; + } +#endif +#if defined(TFM_MUL20) && FP_SIZE >= 40 + if (y <= 20) { + ret = fp_mul_comba20(A,B,C); + goto clean; + } +#endif +#if defined(TFM_MUL24) && FP_SIZE >= 48 + if (yy >= 16 && y <= 24) { + ret = fp_mul_comba24(A,B,C); + goto clean; + } +#endif +#if defined(TFM_MUL28) && FP_SIZE >= 56 + if (yy >= 20 && y <= 28) { + ret = fp_mul_comba28(A,B,C); + goto clean; + } +#endif +#if defined(TFM_MUL32) && FP_SIZE >= 64 + if (yy >= 24 && y <= 32) { + ret = fp_mul_comba32(A,B,C); + goto clean; + } +#endif +#if defined(TFM_MUL48) && FP_SIZE >= 96 + if (yy >= 40 && y <= 48) { + ret = fp_mul_comba48(A,B,C); + goto clean; + } +#endif +#if defined(TFM_MUL64) && FP_SIZE >= 128 + if (yy >= 56 && y <= 64) { + ret = fp_mul_comba64(A,B,C); + goto clean; + } +#endif + ret = fp_mul_comba(A,B,C); + +clean: + /* zero any excess digits on the destination that we didn't write to */ + for (y = C->used; y >= 0 && y < oldused; y++) { + C->dp[y] = 0; + } + + return ret; +} + +void fp_mul_2(fp_int * a, fp_int * b) +{ + int x, oldused; + + oldused = b->used; + b->used = a->used; + + { + fp_digit r, rr, *tmpa, *tmpb; + + /* alias for source */ + tmpa = a->dp; + + /* alias for dest */ + tmpb = b->dp; + + /* carry */ + r = 0; + for (x = 0; x < a->used; x++) { + + /* get what will be the *next* carry bit from the + * MSB of the current digit + */ + rr = *tmpa >> ((fp_digit)(DIGIT_BIT - 1)); + + /* now shift up this digit, add in the carry [from the previous] */ + *tmpb++ = ((*tmpa++ << ((fp_digit)1)) | r); + + /* copy the carry that would be from the source + * digit into the next iteration + */ + r = rr; + } + + /* new leading digit? */ + if (r != 0 && b->used != (FP_SIZE-1)) { + /* add a MSB which is always 1 at this point */ + *tmpb = 1; + ++(b->used); + } + + /* zero any excess digits on the destination that we didn't write to */ + tmpb = b->dp + b->used; + for (x = b->used; x < oldused; x++) { + *tmpb++ = 0; + } + } + b->sign = a->sign; +} + +/* c = a * b */ +void fp_mul_d(fp_int *a, fp_digit b, fp_int *c) +{ + fp_word w; + int x, oldused; + + oldused = c->used; + c->used = a->used; + c->sign = a->sign; + w = 0; + for (x = 0; x < a->used; x++) { + w = ((fp_word)a->dp[x]) * ((fp_word)b) + w; + c->dp[x] = (fp_digit)w; + w = w >> DIGIT_BIT; + } + if (w != 0 && (a->used != FP_SIZE)) { + c->dp[c->used++] = (fp_digit) w; + ++x; + } + + /* zero any excess digits on the destination that we didn't write to */ + for (; x < oldused; x++) { + c->dp[x] = 0; + } + fp_clamp(c); +} + +/* c = a * 2**d */ +void fp_mul_2d(fp_int *a, int b, fp_int *c) +{ + fp_digit carry, carrytmp, shift; + int x; + + /* copy it */ + fp_copy(a, c); + + /* handle whole digits */ + if (b >= DIGIT_BIT) { + fp_lshd(c, b/DIGIT_BIT); + } + b %= DIGIT_BIT; + + /* shift the digits */ + if (b != 0) { + carry = 0; + shift = DIGIT_BIT - b; + for (x = 0; x < c->used; x++) { + carrytmp = c->dp[x] >> shift; + c->dp[x] = (c->dp[x] << b) + carry; + carry = carrytmp; + } + /* store last carry if room */ + if (carry && x < FP_SIZE) { + c->dp[c->used++] = carry; + } + } + fp_clamp(c); +} + +/* generic PxQ multiplier */ +#if defined(HAVE_INTEL_MULX) + +WC_INLINE static int fp_mul_comba_mulx(fp_int *A, fp_int *B, fp_int *C) + +{ + int ix, iy, iz, pa; + fp_int *dst; +#ifndef WOLFSSL_SMALL_STACK + fp_int tmp[1]; +#else + fp_int *tmp; +#endif + +#ifdef WOLFSSL_SMALL_STACK + tmp = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) + return FP_MEM; +#endif + + /* get size of output and trim */ + pa = A->used + B->used; + if (pa >= FP_SIZE) { + pa = FP_SIZE-1; + } + + /* Always take branch to use tmp variable. This avoids a cache attack for + * determining if C equals A */ + if (1) { + fp_init(tmp); + dst = tmp; + } + + TFM_INTEL_MUL_COMBA(A, B, dst) ; + + dst->used = pa; + dst->sign = A->sign ^ B->sign; + fp_clamp(dst); + fp_copy(dst, C); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return FP_OKAY; +} +#endif + +int fp_mul_comba(fp_int *A, fp_int *B, fp_int *C) +{ + int ret = 0; + int ix, iy, iz, tx, ty, pa; + fp_digit c0, c1, c2, *tmpx, *tmpy; + fp_int *dst; +#ifndef WOLFSSL_SMALL_STACK + fp_int tmp[1]; +#else + fp_int *tmp; +#endif + + IF_HAVE_INTEL_MULX(ret = fp_mul_comba_mulx(A, B, C), return ret) ; + +#ifdef WOLFSSL_SMALL_STACK + tmp = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) + return FP_MEM; +#endif + + COMBA_START; + COMBA_CLEAR; + + /* get size of output and trim */ + pa = A->used + B->used; + if (pa >= FP_SIZE) { + pa = FP_SIZE-1; + } + + /* Always take branch to use tmp variable. This avoids a cache attack for + * determining if C equals A */ + if (1) { + fp_init(tmp); + dst = tmp; + } + + for (ix = 0; ix < pa; ix++) { + /* get offsets into the two bignums */ + ty = MIN(ix, (B->used > 0 ? B->used - 1 : 0)); + tx = ix - ty; + + /* setup temp aliases */ + tmpx = A->dp + tx; + tmpy = B->dp + ty; + + /* this is the number of times the loop will iterate, essentially its + while (tx++ < a->used && ty-- >= 0) { ... } + */ + iy = MIN(A->used-tx, ty+1); + + /* execute loop */ + COMBA_FORWARD; + for (iz = 0; iz < iy; ++iz) { + fp_digit _tmpx = *tmpx++; + fp_digit _tmpy = *tmpy--; + MULADD(_tmpx, _tmpy); + } + + /* store term */ + COMBA_STORE(dst->dp[ix]); + } + COMBA_FINI; + + dst->used = pa; + dst->sign = A->sign ^ B->sign; + fp_clamp(dst); + fp_copy(dst, C); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; +} + +/* a/b => cb + d == a */ +int fp_div(fp_int *a, fp_int *b, fp_int *c, fp_int *d) +{ + int n, t, i, norm, neg; +#ifndef WOLFSSL_SMALL_STACK + fp_int q[1], x[1], y[1], t1[1], t2[1]; +#else + fp_int *q, *x, *y, *t1, *t2; +#endif + + /* is divisor zero ? */ + if (fp_iszero (b) == FP_YES) { + return FP_VAL; + } + + /* if a < b then q=0, r = a */ + if (fp_cmp_mag (a, b) == FP_LT) { + if (d != NULL) { + fp_copy (a, d); + } + if (c != NULL) { + fp_zero (c); + } + return FP_OKAY; + } + +#ifdef WOLFSSL_SMALL_STACK + q = (fp_int*)XMALLOC(sizeof(fp_int) * 5, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (q == NULL) { + return FP_MEM; + } + x = &q[1]; y = &q[2]; t1 = &q[3]; t2 = &q[4]; +#endif + + fp_init(q); + q->used = a->used + 2; + + fp_init(t1); + fp_init(t2); + fp_init_copy(x, a); + fp_init_copy(y, b); + + /* fix the sign */ + neg = (a->sign == b->sign) ? FP_ZPOS : FP_NEG; + x->sign = y->sign = FP_ZPOS; + + /* normalize both x and y, ensure that y >= b/2, [b == 2**DIGIT_BIT] */ + norm = fp_count_bits(y) % DIGIT_BIT; + if (norm < (int)(DIGIT_BIT-1)) { + norm = (DIGIT_BIT-1) - norm; + fp_mul_2d (x, norm, x); + fp_mul_2d (y, norm, y); + } else { + norm = 0; + } + + /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */ + n = x->used - 1; + t = y->used - 1; + + /* while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} } */ + fp_lshd (y, n - t); /* y = y*b**{n-t} */ + + while (fp_cmp (x, y) != FP_LT) { + ++(q->dp[n - t]); + fp_sub (x, y, x); + } + + /* reset y by shifting it back down */ + fp_rshd (y, n - t); + + /* step 3. for i from n down to (t + 1) */ + for (i = n; i >= (t + 1); i--) { + if (i > x->used) { + continue; + } + + /* step 3.1 if xi == yt then set q{i-t-1} to b-1, + * otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */ + if (x->dp[i] == y->dp[t]) { + q->dp[i - t - 1] = (fp_digit) ((((fp_word)1) << DIGIT_BIT) - 1); + } else { + fp_word tmp; + tmp = ((fp_word) x->dp[i]) << ((fp_word) DIGIT_BIT); + tmp |= ((fp_word) x->dp[i - 1]); + tmp /= ((fp_word)y->dp[t]); + q->dp[i - t - 1] = (fp_digit) (tmp); + } + + /* while (q{i-t-1} * (yt * b + y{t-1})) > + xi * b**2 + xi-1 * b + xi-2 + + do q{i-t-1} -= 1; + */ + q->dp[i - t - 1] = (q->dp[i - t - 1] + 1); + do { + q->dp[i - t - 1] = (q->dp[i - t - 1] - 1); + + /* find left hand */ + fp_zero (t1); + t1->dp[0] = (t - 1 < 0) ? 0 : y->dp[t - 1]; + t1->dp[1] = y->dp[t]; + t1->used = 2; + fp_mul_d (t1, q->dp[i - t - 1], t1); + + /* find right hand */ + t2->dp[0] = (i - 2 < 0) ? 0 : x->dp[i - 2]; + t2->dp[1] = (i - 1 < 0) ? 0 : x->dp[i - 1]; + t2->dp[2] = x->dp[i]; + t2->used = 3; + } while (fp_cmp_mag(t1, t2) == FP_GT); + + /* step 3.3 x = x - q{i-t-1} * y * b**{i-t-1} */ + fp_mul_d (y, q->dp[i - t - 1], t1); + fp_lshd (t1, i - t - 1); + fp_sub (x, t1, x); + + /* if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; } */ + if (x->sign == FP_NEG) { + fp_copy (y, t1); + fp_lshd (t1, i - t - 1); + fp_add (x, t1, x); + q->dp[i - t - 1] = q->dp[i - t - 1] - 1; + } + } + + /* now q is the quotient and x is the remainder + * [which we have to normalize] + */ + + /* get sign before writing to c */ + x->sign = x->used == 0 ? FP_ZPOS : a->sign; + + if (c != NULL) { + fp_clamp (q); + fp_copy (q, c); + c->sign = neg; + } + + if (d != NULL) { + fp_div_2d (x, norm, x, NULL); + + /* zero any excess digits on the destination that we didn't write to */ + for (i = b->used; i < x->used; i++) { + x->dp[i] = 0; + } + fp_clamp(x); + fp_copy (x, d); + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(q, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; +} + +/* b = a/2 */ +void fp_div_2(fp_int * a, fp_int * b) +{ + int x, oldused; + + oldused = b->used; + b->used = a->used; + { + fp_digit r, rr, *tmpa, *tmpb; + + /* source alias */ + tmpa = a->dp + b->used - 1; + + /* dest alias */ + tmpb = b->dp + b->used - 1; + + /* carry */ + r = 0; + for (x = b->used - 1; x >= 0; x--) { + /* get the carry for the next iteration */ + rr = *tmpa & 1; + + /* shift the current digit, add in carry and store */ + *tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1)); + + /* forward carry to next iteration */ + r = rr; + } + + /* zero any excess digits on the destination that we didn't write to */ + tmpb = b->dp + b->used; + for (x = b->used; x < oldused; x++) { + *tmpb++ = 0; + } + } + b->sign = a->sign; + fp_clamp (b); +} + +/* c = a / 2**b */ +void fp_div_2d(fp_int *a, int b, fp_int *c, fp_int *d) +{ + int D; + + /* if the shift count is <= 0 then we do no work */ + if (b <= 0) { + fp_copy (a, c); + if (d != NULL) { + fp_zero (d); + } + return; + } + + /* get the remainder before a is changed in calculating c */ + if (a == c && d != NULL) { + fp_mod_2d (a, b, d); + } + + /* copy */ + fp_copy(a, c); + + /* shift by as many digits in the bit count */ + if (b >= (int)DIGIT_BIT) { + fp_rshd (c, b / DIGIT_BIT); + } + + /* shift any bit count < DIGIT_BIT */ + D = (b % DIGIT_BIT); + if (D != 0) { + fp_rshb(c, D); + } + + /* get the remainder if a is not changed in calculating c */ + if (a != c && d != NULL) { + fp_mod_2d (a, b, d); + } + + fp_clamp (c); +} + +/* c = a mod b, 0 <= c < b */ +int fp_mod(fp_int *a, fp_int *b, fp_int *c) +{ +#ifndef WOLFSSL_SMALL_STACK + fp_int t[1]; +#else + fp_int *t; +#endif + int err; + +#ifdef WOLFSSL_SMALL_STACK + t = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (t == NULL) + return FP_MEM; +#endif + + fp_init(t); + err = fp_div(a, b, NULL, t); + if (err == FP_OKAY) { + if (t->sign != b->sign) { + fp_add(t, b, c); + } else { + fp_copy(t, c); + } + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(t, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return err; +} + +/* c = a mod 2**d */ +void fp_mod_2d(fp_int *a, int b, fp_int *c) +{ + int x; + + /* zero if count less than or equal to zero */ + if (b <= 0) { + fp_zero(c); + return; + } + + /* get copy of input */ + fp_copy(a, c); + + /* if 2**d is larger than we just return */ + if (b >= (DIGIT_BIT * a->used)) { + return; + } + + /* zero digits above the last digit of the modulus */ + for (x = (b / DIGIT_BIT) + ((b % DIGIT_BIT) == 0 ? 0 : 1); x < c->used; x++) { + c->dp[x] = 0; + } + /* clear the digit that is not completely outside/inside the modulus */ + c->dp[b / DIGIT_BIT] &= ~((fp_digit)0) >> (DIGIT_BIT - b); + fp_clamp (c); +} + +static int fp_invmod_slow (fp_int * a, fp_int * b, fp_int * c) +{ +#ifndef WOLFSSL_SMALL_STACK + fp_int x[1], y[1], u[1], v[1], A[1], B[1], C[1], D[1]; +#else + fp_int *x, *y, *u, *v, *A, *B, *C, *D; +#endif + int err; + + /* b cannot be negative */ + if (b->sign == FP_NEG || fp_iszero(b) == FP_YES) { + return FP_VAL; + } + +#ifdef WOLFSSL_SMALL_STACK + x = (fp_int*)XMALLOC(sizeof(fp_int) * 8, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (x == NULL) { + return FP_MEM; + } + y = &x[1]; u = &x[2]; v = &x[3]; A = &x[4]; B = &x[5]; C = &x[6]; D = &x[7]; +#endif + + /* init temps */ + fp_init(x); fp_init(y); + fp_init(u); fp_init(v); + fp_init(A); fp_init(B); + fp_init(C); fp_init(D); + + /* x = a, y = b */ + if ((err = fp_mod(a, b, x)) != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(x, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return err; + } + fp_copy(b, y); + + /* 2. [modified] if x,y are both even then return an error! */ + if (fp_iseven (x) == FP_YES && fp_iseven (y) == FP_YES) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(x, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return FP_VAL; + } + + /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */ + fp_copy (x, u); + fp_copy (y, v); + fp_set (A, 1); + fp_set (D, 1); + +top: + /* 4. while u is even do */ + while (fp_iseven (u) == FP_YES) { + /* 4.1 u = u/2 */ + fp_div_2 (u, u); + + /* 4.2 if A or B is odd then */ + if (fp_isodd (A) == FP_YES || fp_isodd (B) == FP_YES) { + /* A = (A+y)/2, B = (B-x)/2 */ + fp_add (A, y, A); + fp_sub (B, x, B); + } + /* A = A/2, B = B/2 */ + fp_div_2 (A, A); + fp_div_2 (B, B); + } + + /* 5. while v is even do */ + while (fp_iseven (v) == FP_YES) { + /* 5.1 v = v/2 */ + fp_div_2 (v, v); + + /* 5.2 if C or D is odd then */ + if (fp_isodd (C) == FP_YES || fp_isodd (D) == FP_YES) { + /* C = (C+y)/2, D = (D-x)/2 */ + fp_add (C, y, C); + fp_sub (D, x, D); + } + /* C = C/2, D = D/2 */ + fp_div_2 (C, C); + fp_div_2 (D, D); + } + + /* 6. if u >= v then */ + if (fp_cmp (u, v) != FP_LT) { + /* u = u - v, A = A - C, B = B - D */ + fp_sub (u, v, u); + fp_sub (A, C, A); + fp_sub (B, D, B); + } else { + /* v - v - u, C = C - A, D = D - B */ + fp_sub (v, u, v); + fp_sub (C, A, C); + fp_sub (D, B, D); + } + + /* if not zero goto step 4 */ + if (fp_iszero (u) == FP_NO) + goto top; + + /* now a = C, b = D, gcd == g*v */ + + /* if v != 1 then there is no inverse */ + if (fp_cmp_d (v, 1) != FP_EQ) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(x, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return FP_VAL; + } + + /* if its too low */ + while (fp_cmp_d(C, 0) == FP_LT) { + fp_add(C, b, C); + } + + /* too big */ + while (fp_cmp_mag(C, b) != FP_LT) { + fp_sub(C, b, C); + } + + /* C is now the inverse */ + fp_copy(C, c); +#ifdef WOLFSSL_SMALL_STACK + XFREE(x, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; +} + +/* c = 1/a (mod b) for odd b only */ +int fp_invmod(fp_int *a, fp_int *b, fp_int *c) +{ +#ifndef WOLFSSL_SMALL_STACK + fp_int x[1], y[1], u[1], v[1], B[1], D[1]; +#else + fp_int *x, *y, *u, *v, *B, *D; +#endif + int neg; + + /* 2. [modified] b must be odd */ + if (fp_iseven (b) == FP_YES) { + return fp_invmod_slow(a,b,c); + } + +#ifdef WOLFSSL_SMALL_STACK + x = (fp_int*)XMALLOC(sizeof(fp_int) * 6, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (x == NULL) { + return FP_MEM; + } + y = &x[1]; u = &x[2]; v = &x[3]; B = &x[4]; D = &x[5]; +#endif + + /* init all our temps */ + fp_init(x); fp_init(y); + fp_init(u); fp_init(v); + fp_init(B); fp_init(D); + + /* x == modulus, y == value to invert */ + fp_copy(b, x); + + /* we need y = |a| */ + fp_abs(a, y); + + /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */ + fp_copy(x, u); + fp_copy(y, v); + fp_set (D, 1); + +top: + /* 4. while u is even do */ + while (fp_iseven (u) == FP_YES) { + /* 4.1 u = u/2 */ + fp_div_2 (u, u); + + /* 4.2 if B is odd then */ + if (fp_isodd (B) == FP_YES) { + fp_sub (B, x, B); + } + /* B = B/2 */ + fp_div_2 (B, B); + } + + /* 5. while v is even do */ + while (fp_iseven (v) == FP_YES) { + /* 5.1 v = v/2 */ + fp_div_2 (v, v); + + /* 5.2 if D is odd then */ + if (fp_isodd (D) == FP_YES) { + /* D = (D-x)/2 */ + fp_sub (D, x, D); + } + /* D = D/2 */ + fp_div_2 (D, D); + } + + /* 6. if u >= v then */ + if (fp_cmp (u, v) != FP_LT) { + /* u = u - v, B = B - D */ + fp_sub (u, v, u); + fp_sub (B, D, B); + } else { + /* v - v - u, D = D - B */ + fp_sub (v, u, v); + fp_sub (D, B, D); + } + + /* if not zero goto step 4 */ + if (fp_iszero (u) == FP_NO) { + goto top; + } + + /* now a = C, b = D, gcd == g*v */ + + /* if v != 1 then there is no inverse */ + if (fp_cmp_d (v, 1) != FP_EQ) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(x, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return FP_VAL; + } + + /* b is now the inverse */ + neg = a->sign; + while (D->sign == FP_NEG) { + fp_add (D, b, D); + } + /* too big */ + while (fp_cmp_mag(D, b) != FP_LT) { + fp_sub(D, b, D); + } + fp_copy (D, c); + c->sign = neg; +#ifdef WOLFSSL_SMALL_STACK + XFREE(x, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; +} + +/* d = a * b (mod c) */ +int fp_mulmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d) +{ + int err; +#ifndef WOLFSSL_SMALL_STACK + fp_int t[1]; +#else + fp_int *t; +#endif + +#ifdef WOLFSSL_SMALL_STACK + t = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (t == NULL) + return FP_MEM; +#endif + + fp_init(t); + err = fp_mul(a, b, t); + if (err == FP_OKAY) { + #if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT) + if (d->size < FP_SIZE) { + err = fp_mod(t, c, t); + fp_copy(t, d); + } else + #endif + { + err = fp_mod(t, c, d); + } + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(t, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return err; +} + +/* d = a - b (mod c) */ +int fp_submod(fp_int *a, fp_int *b, fp_int *c, fp_int *d) +{ + int err; +#ifndef WOLFSSL_SMALL_STACK + fp_int t[1]; +#else + fp_int *t; +#endif + +#ifdef WOLFSSL_SMALL_STACK + t = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (t == NULL) + return FP_MEM; +#endif + + fp_init(t); + fp_sub(a, b, t); +#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT) + if (d->size < FP_SIZE) { + err = fp_mod(t, c, t); + fp_copy(t, d); + } else +#endif + { + err = fp_mod(t, c, d); + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(t, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return err; +} + +/* d = a + b (mod c) */ +int fp_addmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d) +{ + int err; +#ifndef WOLFSSL_SMALL_STACK + fp_int t[1]; +#else + fp_int *t; +#endif + +#ifdef WOLFSSL_SMALL_STACK + t = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (t == NULL) + return FP_MEM; +#endif + + fp_init(t); + fp_add(a, b, t); +#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT) + if (d->size < FP_SIZE) { + err = fp_mod(t, c, t); + fp_copy(t, d); + } else +#endif + { + err = fp_mod(t, c, d); + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(t, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return err; +} + +#ifdef TFM_TIMING_RESISTANT + +#ifdef WC_RSA_NONBLOCK + +#ifdef WC_RSA_NONBLOCK_TIME + /* User can override the check-time at build-time using the + * FP_EXPTMOD_NB_CHECKTIME macro to define your own function */ + #ifndef FP_EXPTMOD_NB_CHECKTIME + /* instruction count for each type of operation */ + /* array lookup is using TFM_EXPTMOD_NB_* states */ + static const word32 exptModNbInst[TFM_EXPTMOD_NB_COUNT] = { + #ifdef TFM_PPC32 + #ifdef _DEBUG + 11098, 8701, 3971, 178394, 858093, 1040, 822, 178056, 181574, 90883, 184339, 236813 + #else + 7050, 2554, 3187, 43178, 200422, 384, 275, 43024, 43550, 30450, 46270, 61376 + #endif + #elif defined(TFM_X86_64) + #ifdef _DEBUG + 954, 2377, 858, 19027, 90840, 287, 407, 20140, 7874, 11385, 8005, 6151 + #else + 765, 1007, 771, 5216, 34993, 248, 193, 4975, 4201, 3947, 4275, 3811 + #endif + #else /* software only fast math */ + #ifdef _DEBUG + 798, 2245, 802, 16657, 66920, 352, 186, 16997, 16145, 12789, 16742, 15006 + #else + 775, 1084, 783, 4692, 37510, 207, 183, 4374, 4392, 3097, 4442, 4079 + #endif + #endif + }; + + static int fp_exptmod_nb_checktime(exptModNb_t* nb) + { + word32 totalInst; + + /* if no max time has been set then stop (do not block) */ + if (nb->maxBlockInst == 0 || nb->state >= TFM_EXPTMOD_NB_COUNT) { + return TFM_EXPTMOD_NB_STOP; + } + + /* if instruction table not set then use maxBlockInst as simple counter */ + if (exptModNbInst[nb->state] == 0) { + if (++nb->totalInst < nb->maxBlockInst) + return TFM_EXPTMOD_NB_CONTINUE; + + nb->totalInst = 0; /* reset counter */ + return TFM_EXPTMOD_NB_STOP; + } + + /* get total instruction count including next operation */ + totalInst = nb->totalInst + exptModNbInst[nb->state]; + /* if the next operation can completed within the maximum then continue */ + if (totalInst <= nb->maxBlockInst) { + return TFM_EXPTMOD_NB_CONTINUE; + } + + return TFM_EXPTMOD_NB_STOP; + } + #define FP_EXPTMOD_NB_CHECKTIME(nb) fp_exptmod_nb_checktime((nb)) + #endif /* !FP_EXPTMOD_NB_CHECKTIME */ +#endif /* WC_RSA_NONBLOCK_TIME */ + +/* non-blocking version of timing resistant fp_exptmod function */ +/* supports cache resistance */ +int fp_exptmod_nb(exptModNb_t* nb, fp_int* G, fp_int* X, fp_int* P, fp_int* Y) +{ + int err, ret = FP_WOULDBLOCK; + + if (nb == NULL) + return FP_VAL; + +#ifdef WC_RSA_NONBLOCK_TIME + nb->totalInst = 0; + do { + nb->totalInst += exptModNbInst[nb->state]; +#endif + + switch (nb->state) { + case TFM_EXPTMOD_NB_INIT: + /* now setup montgomery */ + if ((err = fp_montgomery_setup(P, &nb->mp)) != FP_OKAY) { + nb->state = TFM_EXPTMOD_NB_INIT; + return err; + } + + /* init ints */ + fp_init(&nb->R[0]); + fp_init(&nb->R[1]); + #ifndef WC_NO_CACHE_RESISTANT + fp_init(&nb->R[2]); + #endif + nb->state = TFM_EXPTMOD_NB_MONT; + break; + + case TFM_EXPTMOD_NB_MONT: + /* mod m -> R[0] */ + fp_montgomery_calc_normalization(&nb->R[0], P); + + nb->state = TFM_EXPTMOD_NB_MONT_RED; + break; + + case TFM_EXPTMOD_NB_MONT_RED: + /* reduce G -> R[1] */ + if (fp_cmp_mag(P, G) != FP_GT) { + /* G > P so we reduce it first */ + fp_mod(G, P, &nb->R[1]); + } else { + fp_copy(G, &nb->R[1]); + } + + nb->state = TFM_EXPTMOD_NB_MONT_MUL; + break; + + case TFM_EXPTMOD_NB_MONT_MUL: + /* G (R[1]) * m (R[0]) */ + err = fp_mul(&nb->R[1], &nb->R[0], &nb->R[1]); + if (err != FP_OKAY) { + nb->state = TFM_EXPTMOD_NB_INIT; + return err; + } + + nb->state = TFM_EXPTMOD_NB_MONT_MOD; + break; + + case TFM_EXPTMOD_NB_MONT_MOD: + /* mod m */ + err = fp_div(&nb->R[1], P, NULL, &nb->R[1]); + if (err != FP_OKAY) { + nb->state = TFM_EXPTMOD_NB_INIT; + return err; + } + + nb->state = TFM_EXPTMOD_NB_MONT_MODCHK; + break; + + case TFM_EXPTMOD_NB_MONT_MODCHK: + /* m matches sign of (G * R mod m) */ + if (nb->R[1].sign != P->sign) { + fp_add(&nb->R[1], P, &nb->R[1]); + } + + /* set initial mode and bit cnt */ + nb->bitcnt = 1; + nb->buf = 0; + nb->digidx = X->used - 1; + + nb->state = TFM_EXPTMOD_NB_NEXT; + break; + + case TFM_EXPTMOD_NB_NEXT: + /* grab next digit as required */ + if (--nb->bitcnt == 0) { + /* if nb->digidx == -1 we are out of digits so break */ + if (nb->digidx == -1) { + nb->state = TFM_EXPTMOD_NB_RED; + break; + } + /* read next digit and reset nb->bitcnt */ + nb->buf = X->dp[nb->digidx--]; + nb->bitcnt = (int)DIGIT_BIT; + } + + /* grab the next msb from the exponent */ + nb->y = (int)(nb->buf >> (DIGIT_BIT - 1)) & 1; + nb->buf <<= (fp_digit)1; + nb->state = TFM_EXPTMOD_NB_MUL; + FALL_THROUGH; + + case TFM_EXPTMOD_NB_MUL: + fp_mul(&nb->R[0], &nb->R[1], &nb->R[nb->y^1]); + nb->state = TFM_EXPTMOD_NB_MUL_RED; + break; + + case TFM_EXPTMOD_NB_MUL_RED: + fp_montgomery_reduce(&nb->R[nb->y^1], P, nb->mp); + nb->state = TFM_EXPTMOD_NB_SQR; + break; + + case TFM_EXPTMOD_NB_SQR: + #ifdef WC_NO_CACHE_RESISTANT + fp_sqr(&nb->R[nb->y], &nb->R[nb->y]); + #else + fp_copy((fp_int*) ( ((wolfssl_word)&nb->R[0] & wc_off_on_addr[nb->y^1]) + + ((wolfssl_word)&nb->R[1] & wc_off_on_addr[nb->y]) ), + &nb->R[2]); + fp_sqr(&nb->R[2], &nb->R[2]); + #endif /* WC_NO_CACHE_RESISTANT */ + + nb->state = TFM_EXPTMOD_NB_SQR_RED; + break; + + case TFM_EXPTMOD_NB_SQR_RED: + #ifdef WC_NO_CACHE_RESISTANT + fp_montgomery_reduce(&nb->R[nb->y], P, nb->mp); + #else + fp_montgomery_reduce(&nb->R[2], P, nb->mp); + fp_copy(&nb->R[2], + (fp_int*) ( ((wolfssl_word)&nb->R[0] & wc_off_on_addr[nb->y^1]) + + ((wolfssl_word)&nb->R[1] & wc_off_on_addr[nb->y]) ) ); + #endif /* WC_NO_CACHE_RESISTANT */ + + nb->state = TFM_EXPTMOD_NB_NEXT; + break; + + case TFM_EXPTMOD_NB_RED: + /* final reduce */ + fp_montgomery_reduce(&nb->R[0], P, nb->mp); + fp_copy(&nb->R[0], Y); + + nb->state = TFM_EXPTMOD_NB_INIT; + ret = FP_OKAY; + break; + } /* switch */ + +#ifdef WC_RSA_NONBLOCK_TIME + /* determine if maximum blocking time has been reached */ + } while (ret == FP_WOULDBLOCK && + FP_EXPTMOD_NB_CHECKTIME(nb) == TFM_EXPTMOD_NB_CONTINUE); +#endif + + return ret; +} + +#endif /* WC_RSA_NONBLOCK */ + + +/* timing resistant montgomery ladder based exptmod + Based on work by Marc Joye, Sung-Ming Yen, "The Montgomery Powering Ladder", + Cryptographic Hardware and Embedded Systems, CHES 2002 +*/ +static int _fp_exptmod(fp_int * G, fp_int * X, fp_int * P, fp_int * Y) +{ +#ifndef WOLFSSL_SMALL_STACK +#ifdef WC_NO_CACHE_RESISTANT + fp_int R[2]; +#else + fp_int R[3]; /* need a temp for cache resistance */ +#endif +#else + fp_int *R; +#endif + fp_digit buf, mp; + int err, bitcnt, digidx, y; + + /* now setup montgomery */ + if ((err = fp_montgomery_setup (P, &mp)) != FP_OKAY) { + return err; + } + +#ifdef WOLFSSL_SMALL_STACK +#ifndef WC_NO_CACHE_RESISTANT + R = (fp_int*)XMALLOC(sizeof(fp_int) * 3, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#else + R = (fp_int*)XMALLOC(sizeof(fp_int) * 2, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + if (R == NULL) + return FP_MEM; +#endif + fp_init(&R[0]); + fp_init(&R[1]); +#ifndef WC_NO_CACHE_RESISTANT + fp_init(&R[2]); +#endif + + /* now we need R mod m */ + fp_montgomery_calc_normalization (&R[0], P); + + /* now set R[0][1] to G * R mod m */ + if (fp_cmp_mag(P, G) != FP_GT) { + /* G > P so we reduce it first */ + fp_mod(G, P, &R[1]); + } else { + fp_copy(G, &R[1]); + } + fp_mulmod (&R[1], &R[0], P, &R[1]); + + /* for j = t-1 downto 0 do + r_!k = R0*R1; r_k = r_k^2 + */ + + /* set initial mode and bit cnt */ + bitcnt = 1; + buf = 0; + digidx = X->used - 1; + + for (;;) { + /* grab next digit as required */ + if (--bitcnt == 0) { + /* if digidx == -1 we are out of digits so break */ + if (digidx == -1) { + break; + } + /* read next digit and reset bitcnt */ + buf = X->dp[digidx--]; + bitcnt = (int)DIGIT_BIT; + } + + /* grab the next msb from the exponent */ + y = (int)(buf >> (DIGIT_BIT - 1)) & 1; + buf <<= (fp_digit)1; + + /* do ops */ + err = fp_mul(&R[0], &R[1], &R[y^1]); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(R, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return err; + } + err = fp_montgomery_reduce(&R[y^1], P, mp); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(R, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return err; + } + +#ifdef WC_NO_CACHE_RESISTANT + err = fp_sqr(&R[y], &R[y]); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(R, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return err; + } + err = fp_montgomery_reduce(&R[y], P, mp); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(R, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return err; + } +#else + /* instead of using R[y] for sqr, which leaks key bit to cache monitor, + * use R[2] as temp, make sure address calc is constant, keep + * &R[0] and &R[1] in cache */ + fp_copy((fp_int*) ( ((wolfssl_word)&R[0] & wc_off_on_addr[y^1]) + + ((wolfssl_word)&R[1] & wc_off_on_addr[y]) ), + &R[2]); + err = fp_sqr(&R[2], &R[2]); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(R, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return err; + } + err = fp_montgomery_reduce(&R[2], P, mp); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(R, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return err; + } + fp_copy(&R[2], + (fp_int*) ( ((wolfssl_word)&R[0] & wc_off_on_addr[y^1]) + + ((wolfssl_word)&R[1] & wc_off_on_addr[y]) ) ); +#endif /* WC_NO_CACHE_RESISTANT */ + } + + err = fp_montgomery_reduce(&R[0], P, mp); + fp_copy(&R[0], Y); +#ifdef WOLFSSL_SMALL_STACK + XFREE(R, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return err; +} + +#else /* TFM_TIMING_RESISTANT */ + +/* y = g**x (mod b) + * Some restrictions... x must be positive and < b + */ +static int _fp_exptmod(fp_int * G, fp_int * X, fp_int * P, fp_int * Y) +{ + fp_digit buf, mp; + int err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize; +#ifdef WOLFSSL_SMALL_STACK + fp_int *res; + fp_int *M; +#else + fp_int res[1]; + fp_int M[64]; +#endif + + /* find window size */ + x = fp_count_bits (X); + if (x <= 21) { + winsize = 1; + } else if (x <= 36) { + winsize = 3; + } else if (x <= 140) { + winsize = 4; + } else if (x <= 450) { + winsize = 5; + } else { + winsize = 6; + } + + /* now setup montgomery */ + if ((err = fp_montgomery_setup (P, &mp)) != FP_OKAY) { + return err; + } + +#ifdef WOLFSSL_SMALL_STACK + /* only allocate space for what's needed for window plus res */ + M = (fp_int*)XMALLOC(sizeof(fp_int)*((1 << winsize) + 1), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (M == NULL) { + return FP_MEM; + } + res = &M[1 << winsize]; +#endif + + /* init M array */ + for(x = 0; x < (1 << winsize); x++) + fp_init(&M[x]); + + /* setup result */ + fp_init(res); + + /* create M table + * + * The M table contains powers of the input base, e.g. M[x] = G^x mod P + * + * The first half of the table is not computed though except for M[0] and M[1] + */ + + /* now we need R mod m */ + fp_montgomery_calc_normalization (res, P); + + /* now set M[1] to G * R mod m */ + if (fp_cmp_mag(P, G) != FP_GT) { + /* G > P so we reduce it first */ + fp_mod(G, P, &M[1]); + } else { + fp_copy(G, &M[1]); + } + fp_mulmod (&M[1], res, P, &M[1]); + + /* compute the value at M[1<<(winsize-1)] by + * squaring M[1] (winsize-1) times */ + fp_copy (&M[1], &M[1 << (winsize - 1)]); + for (x = 0; x < (winsize - 1); x++) { + fp_sqr (&M[1 << (winsize - 1)], &M[1 << (winsize - 1)]); + err = fp_montgomery_reduce (&M[1 << (winsize - 1)], P, mp); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(M, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return err; + } + } + + /* create upper table */ + for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) { + err = fp_mul(&M[x - 1], &M[1], &M[x]); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(M, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return err; + } + err = fp_montgomery_reduce(&M[x], P, mp); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(M, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return err; + } + } + + /* set initial mode and bit cnt */ + mode = 0; + bitcnt = 1; + buf = 0; + digidx = X->used - 1; + bitcpy = 0; + bitbuf = 0; + + for (;;) { + /* grab next digit as required */ + if (--bitcnt == 0) { + /* if digidx == -1 we are out of digits so break */ + if (digidx == -1) { + break; + } + /* read next digit and reset bitcnt */ + buf = X->dp[digidx--]; + bitcnt = (int)DIGIT_BIT; + } + + /* grab the next msb from the exponent */ + y = (int)(buf >> (DIGIT_BIT - 1)) & 1; + buf <<= (fp_digit)1; + + /* if the bit is zero and mode == 0 then we ignore it + * These represent the leading zero bits before the first 1 bit + * in the exponent. Technically this opt is not required but it + * does lower the # of trivial squaring/reductions used + */ + if (mode == 0 && y == 0) { + continue; + } + + /* if the bit is zero and mode == 1 then we square */ + if (mode == 1 && y == 0) { + err = fp_sqr(res, res); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(M, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return err; + } + fp_montgomery_reduce(res, P, mp); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(M, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return err; + } + continue; + } + + /* else we add it to the window */ + bitbuf |= (y << (winsize - ++bitcpy)); + mode = 2; + + if (bitcpy == winsize) { + /* ok window is filled so square as required and multiply */ + /* square first */ + for (x = 0; x < winsize; x++) { + err = fp_sqr(res, res); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(M, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return err; + } + err = fp_montgomery_reduce(res, P, mp); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(M, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return err; + } + } + + /* then multiply */ + err = fp_mul(res, &M[bitbuf], res); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(M, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return err; + } + err = fp_montgomery_reduce(res, P, mp); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(M, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return err; + } + + /* empty window and reset */ + bitcpy = 0; + bitbuf = 0; + mode = 1; + } + } + + /* if bits remain then square/multiply */ + if (mode == 2 && bitcpy > 0) { + /* square then multiply if the bit is set */ + for (x = 0; x < bitcpy; x++) { + err = fp_sqr(res, res); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(M, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return err; + } + err = fp_montgomery_reduce(res, P, mp); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(M, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return err; + } + + /* get next bit of the window */ + bitbuf <<= 1; + if ((bitbuf & (1 << winsize)) != 0) { + /* then multiply */ + err = fp_mul(res, &M[1], res); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(M, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return err; + } + err = fp_montgomery_reduce(res, P, mp); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(M, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return err; + } + } + } + } + + /* fixup result if Montgomery reduction is used + * recall that any value in a Montgomery system is + * actually multiplied by R mod n. So we have + * to reduce one more time to cancel out the factor + * of R. + */ + err = fp_montgomery_reduce(res, P, mp); + + /* swap res with Y */ + fp_copy (res, Y); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(M, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return err; +} + +#endif /* TFM_TIMING_RESISTANT */ + +int fp_exptmod(fp_int * G, fp_int * X, fp_int * P, fp_int * Y) +{ + +#if defined(WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI) + int x = fp_count_bits (X); +#endif + + /* prevent overflows */ + if (P->used > (FP_SIZE/2)) { + return FP_VAL; + } + +#if defined(WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI) + if(x > EPS_RSA_EXPT_XBTIS) { + return esp_mp_exptmod(G, X, x, P, Y); + } +#endif + + if (X->sign == FP_NEG) { +#ifndef POSITIVE_EXP_ONLY /* reduce stack if assume no negatives */ + int err; + #ifndef WOLFSSL_SMALL_STACK + fp_int tmp[1]; + #else + fp_int *tmp; + #endif + + #ifdef WOLFSSL_SMALL_STACK + tmp = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) + return FP_MEM; + #endif + + /* yes, copy G and invmod it */ + fp_init_copy(tmp, G); + err = fp_invmod(tmp, P, tmp); + if (err == FP_OKAY) { + X->sign = FP_ZPOS; + err = _fp_exptmod(tmp, X, P, Y); + if (X != Y) { + X->sign = FP_NEG; + } + } + #ifdef WOLFSSL_SMALL_STACK + XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return err; +#else + return FP_VAL; +#endif + } + else { + /* Positive exponent so just exptmod */ + return _fp_exptmod(G, X, P, Y); + } +} + +/* computes a = 2**b */ +void fp_2expt(fp_int *a, int b) +{ + int z; + + /* zero a as per default */ + fp_zero (a); + + if (b < 0) { + return; + } + + z = b / DIGIT_BIT; + if (z >= FP_SIZE) { + return; + } + + /* set the used count of where the bit will go */ + a->used = z + 1; + + /* put the single bit in its place */ + a->dp[z] = ((fp_digit)1) << (b % DIGIT_BIT); +} + +/* b = a*a */ +int fp_sqr(fp_int *A, fp_int *B) +{ + int err; + int y, oldused; + + oldused = B->used; + y = A->used; + + /* call generic if we're out of range */ + if (y + y > FP_SIZE) { + err = fp_sqr_comba(A, B); + goto clean; + } + +#if defined(TFM_SQR3) && FP_SIZE >= 6 + if (y <= 3) { + err = fp_sqr_comba3(A,B); + goto clean; + } +#endif +#if defined(TFM_SQR4) && FP_SIZE >= 8 + if (y == 4) { + err = fp_sqr_comba4(A,B); + goto clean; + } +#endif +#if defined(TFM_SQR6) && FP_SIZE >= 12 + if (y <= 6) { + err = fp_sqr_comba6(A,B); + goto clean; + } +#endif +#if defined(TFM_SQR7) && FP_SIZE >= 14 + if (y == 7) { + err = fp_sqr_comba7(A,B); + goto clean; + } +#endif +#if defined(TFM_SQR8) && FP_SIZE >= 16 + if (y == 8) { + err = fp_sqr_comba8(A,B); + goto clean; + } +#endif +#if defined(TFM_SQR9) && FP_SIZE >= 18 + if (y == 9) { + err = fp_sqr_comba9(A,B); + goto clean; + } +#endif +#if defined(TFM_SQR12) && FP_SIZE >= 24 + if (y <= 12) { + err = fp_sqr_comba12(A,B); + goto clean; + } +#endif +#if defined(TFM_SQR17) && FP_SIZE >= 34 + if (y <= 17) { + err = fp_sqr_comba17(A,B); + goto clean; + } +#endif +#if defined(TFM_SMALL_SET) + if (y <= 16) { + err = fp_sqr_comba_small(A,B); + goto clean; + } +#endif +#if defined(TFM_SQR20) && FP_SIZE >= 40 + if (y <= 20) { + err = fp_sqr_comba20(A,B); + goto clean; + } +#endif +#if defined(TFM_SQR24) && FP_SIZE >= 48 + if (y <= 24) { + err = fp_sqr_comba24(A,B); + goto clean; + } +#endif +#if defined(TFM_SQR28) && FP_SIZE >= 56 + if (y <= 28) { + err = fp_sqr_comba28(A,B); + goto clean; + } +#endif +#if defined(TFM_SQR32) && FP_SIZE >= 64 + if (y <= 32) { + err = fp_sqr_comba32(A,B); + goto clean; + } +#endif +#if defined(TFM_SQR48) && FP_SIZE >= 96 + if (y <= 48) { + err = fp_sqr_comba48(A,B); + goto clean; + } +#endif +#if defined(TFM_SQR64) && FP_SIZE >= 128 + if (y <= 64) { + err = fp_sqr_comba64(A,B); + goto clean; + } +#endif + err = fp_sqr_comba(A, B); + +clean: + /* zero any excess digits on the destination that we didn't write to */ + for (y = B->used; y >= 0 && y < oldused; y++) { + B->dp[y] = 0; + } + + return err; +} + +/* generic comba squarer */ +int fp_sqr_comba(fp_int *A, fp_int *B) +{ + int pa, ix, iz; + fp_digit c0, c1, c2; +#ifdef TFM_ISO + fp_word tt; +#endif + fp_int *dst; +#ifndef WOLFSSL_SMALL_STACK + fp_int tmp[1]; +#else + fp_int *tmp; +#endif + +#ifdef WOLFSSL_SMALL_STACK + tmp = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) + return FP_MEM; +#endif + + /* get size of output and trim */ + pa = A->used + A->used; + if (pa >= FP_SIZE) { + pa = FP_SIZE-1; + } + + /* number of output digits to produce */ + COMBA_START; + COMBA_CLEAR; + + if (A == B) { + fp_init(tmp); + dst = tmp; + } else { + fp_zero(B); + dst = B; + } + + for (ix = 0; ix < pa; ix++) { + int tx, ty, iy; + fp_digit *tmpy, *tmpx; + + /* get offsets into the two bignums */ + ty = MIN(A->used-1, ix); + tx = ix - ty; + + /* setup temp aliases */ + tmpx = A->dp + tx; + tmpy = A->dp + ty; + + /* this is the number of times the loop will iterate, + while (tx++ < a->used && ty-- >= 0) { ... } + */ + iy = MIN(A->used-tx, ty+1); + + /* now for squaring tx can never equal ty + * we halve the distance since they approach + * at a rate of 2x and we have to round because + * odd cases need to be executed + */ + iy = MIN(iy, (ty-tx+1)>>1); + + /* forward carries */ + COMBA_FORWARD; + + /* execute loop */ + for (iz = 0; iz < iy; iz++) { + SQRADD2(*tmpx++, *tmpy--); + } + + /* even columns have the square term in them */ + if ((ix&1) == 0) { + /* TAO change COMBA_ADD back to SQRADD */ + SQRADD(A->dp[ix>>1], A->dp[ix>>1]); + } + + /* store it */ + COMBA_STORE(dst->dp[ix]); + } + + COMBA_FINI; + + /* setup dest */ + dst->used = pa; + fp_clamp (dst); + if (dst != B) { + fp_copy(dst, B); + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; +} + +int fp_cmp(fp_int *a, fp_int *b) +{ + if (a->sign == FP_NEG && b->sign == FP_ZPOS) { + return FP_LT; + } else if (a->sign == FP_ZPOS && b->sign == FP_NEG) { + return FP_GT; + } else { + /* compare digits */ + if (a->sign == FP_NEG) { + /* if negative compare opposite direction */ + return fp_cmp_mag(b, a); + } else { + return fp_cmp_mag(a, b); + } + } +} + +/* compare against a single digit */ +int fp_cmp_d(fp_int *a, fp_digit b) +{ + /* special case for zero*/ + if (a->used == 0 && b == 0) + return FP_EQ; + + /* compare based on sign */ + if ((b && a->used == 0) || a->sign == FP_NEG) { + return FP_LT; + } + + /* compare based on magnitude */ + if (a->used > 1) { + return FP_GT; + } + + /* compare the only digit of a to b */ + if (a->dp[0] > b) { + return FP_GT; + } else if (a->dp[0] < b) { + return FP_LT; + } else { + return FP_EQ; + } + +} + +int fp_cmp_mag(fp_int *a, fp_int *b) +{ + int x; + + if (a->used > b->used) { + return FP_GT; + } else if (a->used < b->used) { + return FP_LT; + } else { + for (x = a->used - 1; x >= 0; x--) { + if (a->dp[x] > b->dp[x]) { + return FP_GT; + } else if (a->dp[x] < b->dp[x]) { + return FP_LT; + } + } + } + return FP_EQ; +} + +/* sets up the montgomery reduction */ +int fp_montgomery_setup(fp_int *a, fp_digit *rho) +{ + fp_digit x, b; + +/* fast inversion mod 2**k + * + * Based on the fact that + * + * XA = 1 (mod 2**n) => (X(2-XA)) A = 1 (mod 2**2n) + * => 2*X*A - X*X*A*A = 1 + * => 2*(1) - (1) = 1 + */ + b = a->dp[0]; + + if ((b & 1) == 0) { + return FP_VAL; + } + + x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */ + x *= 2 - b * x; /* here x*a==1 mod 2**8 */ + x *= 2 - b * x; /* here x*a==1 mod 2**16 */ + x *= 2 - b * x; /* here x*a==1 mod 2**32 */ +#ifdef FP_64BIT + x *= 2 - b * x; /* here x*a==1 mod 2**64 */ +#endif + + /* rho = -1/m mod b */ + *rho = (fp_digit) (((fp_word) 1 << ((fp_word) DIGIT_BIT)) - ((fp_word)x)); + + return FP_OKAY; +} + +/* computes a = B**n mod b without division or multiplication useful for + * normalizing numbers in a Montgomery system. + */ +void fp_montgomery_calc_normalization(fp_int *a, fp_int *b) +{ + int x, bits; + + /* how many bits of last digit does b use */ + bits = fp_count_bits (b) % DIGIT_BIT; + if (!bits) bits = DIGIT_BIT; + + /* compute A = B^(n-1) * 2^(bits-1) */ + if (b->used > 1) { + fp_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1); + } else { + fp_set(a, 1); + bits = 1; + } + + /* now compute C = A * B mod b */ + for (x = bits - 1; x < (int)DIGIT_BIT; x++) { + fp_mul_2 (a, a); + if (fp_cmp_mag (a, b) != FP_LT) { + s_fp_sub (a, b, a); + } + } +} + + +#ifdef TFM_SMALL_MONT_SET + #include "fp_mont_small.i" +#endif + +#ifdef HAVE_INTEL_MULX +static WC_INLINE void innermul8_mulx(fp_digit *c_mulx, fp_digit *cy_mulx, fp_digit *tmpm, fp_digit mu) +{ + fp_digit cy = *cy_mulx ; + INNERMUL8_MULX ; + *cy_mulx = cy ; +} + +/* computes x/R == x (mod N) via Montgomery Reduction */ +static int fp_montgomery_reduce_mulx(fp_int *a, fp_int *m, fp_digit mp) +{ +#ifndef WOLFSSL_SMALL_STACK + fp_digit c[FP_SIZE+1]; +#else + fp_digit *c; +#endif + fp_digit *_c, *tmpm, mu = 0; + int oldused, x, y, pa; + + /* bail if too large */ + if (m->used > (FP_SIZE/2)) { + (void)mu; /* shut up compiler */ + return FP_OKAY; + } + +#ifdef TFM_SMALL_MONT_SET + if (m->used <= 16) { + return fp_montgomery_reduce_small(a, m, mp); + } +#endif + +#ifdef WOLFSSL_SMALL_STACK + /* only allocate space for what's needed for window plus res */ + c = (fp_digit*)XMALLOC(sizeof(fp_digit)*(FP_SIZE + 1), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (c == NULL) { + return FP_MEM; + } +#endif + + /* now zero the buff */ + XMEMSET(c, 0, sizeof(fp_digit)*(FP_SIZE + 1)); + pa = m->used; + + /* copy the input */ + oldused = a->used; + for (x = 0; x < oldused; x++) { + c[x] = a->dp[x]; + } + MONT_START; + + for (x = 0; x < pa; x++) { + fp_digit cy = 0; + /* get Mu for this round */ + LOOP_START; + _c = c + x; + tmpm = m->dp; + y = 0; + for (; y < (pa & ~7); y += 8) { + innermul8_mulx(_c, &cy, tmpm, mu) ; + _c += 8; + tmpm += 8; + } + for (; y < pa; y++) { + INNERMUL; + ++_c; + } + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + } + + /* now copy out */ + _c = c + pa; + tmpm = a->dp; + for (x = 0; x < pa+1; x++) { + *tmpm++ = *_c++; + } + + /* zero any excess digits on the destination that we didn't write to */ + for (; x < oldused; x++) { + *tmpm++ = 0; + } + + MONT_FINI; + + a->used = pa+1; + fp_clamp(a); + + /* if A >= m then A = A - m */ + if (fp_cmp_mag (a, m) != FP_LT) { + s_fp_sub (a, m, a); + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(c, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; +} +#endif + +/* computes x/R == x (mod N) via Montgomery Reduction */ +int fp_montgomery_reduce(fp_int *a, fp_int *m, fp_digit mp) +{ +#ifndef WOLFSSL_SMALL_STACK + fp_digit c[FP_SIZE+1]; +#else + fp_digit *c; +#endif + fp_digit *_c, *tmpm, mu = 0; + int oldused, x, y, pa, err; + + IF_HAVE_INTEL_MULX(err = fp_montgomery_reduce_mulx(a, m, mp), return err) ; + (void)err; + + /* bail if too large */ + if (m->used > (FP_SIZE/2)) { + (void)mu; /* shut up compiler */ + return FP_OKAY; + } + +#ifdef TFM_SMALL_MONT_SET + if (m->used <= 16) { + return fp_montgomery_reduce_small(a, m, mp); + } +#endif + +#ifdef WOLFSSL_SMALL_STACK + /* only allocate space for what's needed for window plus res */ + c = (fp_digit*)XMALLOC(sizeof(fp_digit)*(FP_SIZE + 1), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (c == NULL) { + return FP_MEM; + } +#endif + + /* now zero the buff */ + XMEMSET(c, 0, sizeof(fp_digit)*(FP_SIZE + 1)); + pa = m->used; + + /* copy the input */ + oldused = a->used; + for (x = 0; x < oldused; x++) { + c[x] = a->dp[x]; + } + MONT_START; + + for (x = 0; x < pa; x++) { + fp_digit cy = 0; + /* get Mu for this round */ + LOOP_START; + _c = c + x; + tmpm = m->dp; + y = 0; +#if defined(INNERMUL8) + for (; y < (pa & ~7); y += 8) { + INNERMUL8 ; + _c += 8; + tmpm += 8; + } +#endif + for (; y < pa; y++) { + INNERMUL; + ++_c; + } + LOOP_END; + while (cy) { + PROPCARRY; + ++_c; + } + } + + /* now copy out */ + _c = c + pa; + tmpm = a->dp; + for (x = 0; x < pa+1; x++) { + *tmpm++ = *_c++; + } + + /* zero any excess digits on the destination that we didn't write to */ + for (; x < oldused; x++) { + *tmpm++ = 0; + } + + MONT_FINI; + + a->used = pa+1; + fp_clamp(a); + + /* if A >= m then A = A - m */ + if (fp_cmp_mag (a, m) != FP_LT) { + s_fp_sub (a, m, a); + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(c, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; +} + +void fp_read_unsigned_bin(fp_int *a, const unsigned char *b, int c) +{ +#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT) + const word32 maxC = (a->size * sizeof(fp_digit)); +#else + const word32 maxC = (FP_SIZE * sizeof(fp_digit)); +#endif + + /* zero the int */ + fp_zero (a); + + /* if input b excess max, then truncate */ + if (c > 0 && (word32)c > maxC) { + int excess = (c - maxC); + c -= excess; + b += excess; + } + + /* If we know the endianness of this architecture, and we're using + 32-bit fp_digits, we can optimize this */ +#if (defined(LITTLE_ENDIAN_ORDER) || defined(BIG_ENDIAN_ORDER)) && \ + defined(FP_32BIT) + /* But not for both simultaneously */ +#if defined(LITTLE_ENDIAN_ORDER) && defined(BIG_ENDIAN_ORDER) +#error Both LITTLE_ENDIAN_ORDER and BIG_ENDIAN_ORDER defined. +#endif + { + unsigned char *pd = (unsigned char *)a->dp; + + a->used = (c + sizeof(fp_digit) - 1)/sizeof(fp_digit); + /* read the bytes in */ +#ifdef BIG_ENDIAN_ORDER + { + /* Use Duff's device to unroll the loop. */ + int idx = (c - 1) & ~3; + switch (c % 4) { + case 0: do { pd[idx+0] = *b++; // fallthrough + case 3: pd[idx+1] = *b++; // fallthrough + case 2: pd[idx+2] = *b++; // fallthrough + case 1: pd[idx+3] = *b++; // fallthrough + idx -= 4; + } while ((c -= 4) > 0); + } + } +#else + for (c -= 1; c >= 0; c -= 1) { + pd[c] = *b++; + } +#endif + } +#else + /* read the bytes in */ + for (; c > 0; c--) { + fp_mul_2d (a, 8, a); + a->dp[0] |= *b++; + + if (a->used == 0) { + a->used = 1; + } + } +#endif + fp_clamp (a); +} + +int fp_to_unsigned_bin_at_pos(int x, fp_int *t, unsigned char *b) +{ +#if DIGIT_BIT == 64 || DIGIT_BIT == 32 + int i, j; + fp_digit n; + + for (j=0,i=0; iused-1; ) { + b[x++] = (unsigned char)(t->dp[i] >> j); + j += 8; + i += j == DIGIT_BIT; + j &= DIGIT_BIT - 1; + } + n = t->dp[i]; + while (n != 0) { + b[x++] = (unsigned char)n; + n >>= 8; + } + return x; +#else + while (fp_iszero (t) == FP_NO) { + b[x++] = (unsigned char) (t->dp[0] & 255); + fp_div_2d (t, 8, t, NULL); + } + return x; +#endif +} + +int fp_to_unsigned_bin(fp_int *a, unsigned char *b) +{ + int x; +#ifndef WOLFSSL_SMALL_STACK + fp_int t[1]; +#else + fp_int *t; +#endif + +#ifdef WOLFSSL_SMALL_STACK + t = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (t == NULL) + return FP_MEM; +#endif + + fp_init_copy(t, a); + + x = fp_to_unsigned_bin_at_pos(0, t, b); + fp_reverse (b, x); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(t, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; +} + +int fp_to_unsigned_bin_len(fp_int *a, unsigned char *b, int c) +{ +#if DIGIT_BIT == 64 || DIGIT_BIT == 32 + int i, j, x; + + for (x=c-1,j=0,i=0; x >= 0; x--) { + b[x] = (unsigned char)(a->dp[i] >> j); + j += 8; + i += j == DIGIT_BIT; + j &= DIGIT_BIT - 1; + } + + return FP_OKAY; +#else + int x; +#ifndef WOLFSSL_SMALL_STACK + fp_int t[1]; +#else + fp_int *t; +#endif + +#ifdef WOLFSSL_SMALL_STACK + t = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (t == NULL) + return FP_MEM; +#endif + + fp_init_copy(t, a); + + for (x = 0; x < c; x++) { + b[x] = (unsigned char) (t->dp[0] & 255); + fp_div_2d (t, 8, t, NULL); + } + fp_reverse (b, x); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(t, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; +#endif +} + +int fp_unsigned_bin_size(fp_int *a) +{ + int size = fp_count_bits (a); + return (size / 8 + ((size & 7) != 0 ? 1 : 0)); +} + +void fp_set(fp_int *a, fp_digit b) +{ + fp_zero(a); + a->dp[0] = b; + a->used = a->dp[0] ? 1 : 0; +} + + +#ifndef MP_SET_CHUNK_BITS + #define MP_SET_CHUNK_BITS 4 +#endif +void fp_set_int(fp_int *a, unsigned long b) +{ + int x; + + /* use direct fp_set if b is less than fp_digit max */ + if (b < FP_DIGIT_MAX) { + fp_set (a, (fp_digit)b); + return; + } + + fp_zero (a); + + /* set chunk bits at a time */ + for (x = 0; x < (int)(sizeof(b) * 8) / MP_SET_CHUNK_BITS; x++) { + fp_mul_2d (a, MP_SET_CHUNK_BITS, a); + + /* OR in the top bits of the source */ + a->dp[0] |= (b >> ((sizeof(b) * 8) - MP_SET_CHUNK_BITS)) & + ((1 << MP_SET_CHUNK_BITS) - 1); + + /* shift the source up to the next chunk bits */ + b <<= MP_SET_CHUNK_BITS; + + /* ensure that digits are not clamped off */ + a->used += 1; + } + + /* clamp digits */ + fp_clamp(a); +} + +/* check if a bit is set */ +int fp_is_bit_set (fp_int *a, fp_digit b) +{ + fp_digit i; + + if (b > FP_MAX_BITS) + return 0; + else + i = b/DIGIT_BIT; + + if ((fp_digit)a->used < i) + return 0; + + return (int)((a->dp[i] >> b%DIGIT_BIT) & (fp_digit)1); +} + +/* set the b bit of a */ +int fp_set_bit (fp_int * a, fp_digit b) +{ + fp_digit i; + + if (b > FP_MAX_BITS) + return 0; + else + i = b/DIGIT_BIT; + + /* set the used count of where the bit will go if required */ + if (a->used < (int)(i+1)) + a->used = (int)(i+1); + + /* put the single bit in its place */ + a->dp[i] |= ((fp_digit)1) << (b % DIGIT_BIT); + + return MP_OKAY; +} + +int fp_count_bits (fp_int * a) +{ + int r; + fp_digit q; + + /* shortcut */ + if (a->used == 0) { + return 0; + } + + /* get number of digits and add that */ + r = (a->used - 1) * DIGIT_BIT; + + /* take the last digit and count the bits in it */ + q = a->dp[a->used - 1]; + while (q > ((fp_digit) 0)) { + ++r; + q >>= ((fp_digit) 1); + } + + return r; +} + +int fp_leading_bit(fp_int *a) +{ + int bit = 0; + + if (a->used != 0) { + fp_digit q = a->dp[a->used - 1]; + int qSz = sizeof(fp_digit); + + while (qSz > 0) { + if ((unsigned char)q != 0) + bit = (q & 0x80) != 0; + q >>= 8; + qSz--; + } + } + + return bit; +} + +void fp_lshd(fp_int *a, int x) +{ + int y; + + /* move up and truncate as required */ + y = MIN(a->used + x - 1, (int)(FP_SIZE-1)); + + /* store new size */ + a->used = y + 1; + + /* move digits */ + for (; y >= x; y--) { + a->dp[y] = a->dp[y-x]; + } + + /* zero lower digits */ + for (; y >= 0; y--) { + a->dp[y] = 0; + } + + /* clamp digits */ + fp_clamp(a); +} + + +/* right shift by bit count */ +void fp_rshb(fp_int *c, int x) +{ + fp_digit *tmpc, mask, shift; + fp_digit r, rr; + fp_digit D = x; + + /* mask */ + mask = (((fp_digit)1) << D) - 1; + + /* shift for lsb */ + shift = DIGIT_BIT - D; + + /* alias */ + tmpc = c->dp + (c->used - 1); + + /* carry */ + r = 0; + for (x = c->used - 1; x >= 0; x--) { + /* get the lower bits of this word in a temp */ + rr = *tmpc & mask; + + /* shift the current word and mix in the carry bits from previous word */ + *tmpc = (*tmpc >> D) | (r << shift); + --tmpc; + + /* set the carry to the carry bits of the current word found above */ + r = rr; + } + + /* clamp digits */ + fp_clamp(c); +} + + +void fp_rshd(fp_int *a, int x) +{ + int y; + + /* too many digits just zero and return */ + if (x >= a->used) { + fp_zero(a); + return; + } + + /* shift */ + for (y = 0; y < a->used - x; y++) { + a->dp[y] = a->dp[y+x]; + } + + /* zero rest */ + for (; y < a->used; y++) { + a->dp[y] = 0; + } + + /* decrement count */ + a->used -= x; + fp_clamp(a); +} + +/* reverse an array, used for radix code */ +void fp_reverse (unsigned char *s, int len) +{ + int ix, iy; + unsigned char t; + + ix = 0; + iy = len - 1; + while (ix < iy) { + t = s[ix]; + s[ix] = s[iy]; + s[iy] = t; + ++ix; + --iy; + } +} + + +/* c = a - b */ +int fp_sub_d(fp_int *a, fp_digit b, fp_int *c) +{ +#ifndef WOLFSSL_SMALL_STACK + fp_int tmp[1]; +#else + fp_int *tmp; +#endif + +#ifdef WOLFSSL_SMALL_STACK + tmp = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (tmp == NULL) + return FP_MEM; +#endif + + fp_init(tmp); + fp_set(tmp, b); +#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT) + if (c->size < FP_SIZE) { + fp_sub(a, tmp, tmp); + fp_copy(tmp, c); + } else +#endif + { + fp_sub(a, tmp, c); + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; +} + + +/* wolfSSL callers from normal lib */ + +/* init a new mp_int */ +int mp_init (mp_int * a) +{ + if (a) + fp_init(a); + return MP_OKAY; +} + +void fp_init(fp_int *a) +{ +#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT) + a->size = FP_SIZE; +#endif +#ifdef HAVE_WOLF_BIGINT + wc_bigint_init(&a->raw); +#endif + fp_zero(a); +} + +void fp_zero(fp_int *a) +{ + int size = FP_SIZE; + a->used = 0; + a->sign = FP_ZPOS; +#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT) + size = a->size; +#endif + XMEMSET(a->dp, 0, size * sizeof(fp_digit)); +} + +void fp_clear(fp_int *a) +{ + int size = FP_SIZE; + a->used = 0; + a->sign = FP_ZPOS; +#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT) + size = a->size; +#endif + XMEMSET(a->dp, 0, size * sizeof(fp_digit)); + fp_free(a); +} + +void fp_forcezero (mp_int * a) +{ + int size = FP_SIZE; + a->used = 0; + a->sign = FP_ZPOS; +#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT) + size = a->size; +#endif + ForceZero(a->dp, size * sizeof(fp_digit)); +#ifdef HAVE_WOLF_BIGINT + wc_bigint_zero(&a->raw); +#endif + fp_free(a); +} + +void mp_forcezero (mp_int * a) +{ + fp_forcezero(a); +} + +void fp_free(fp_int* a) +{ +#ifdef HAVE_WOLF_BIGINT + wc_bigint_free(&a->raw); +#else + (void)a; +#endif +} + + +/* clear one (frees) */ +void mp_clear (mp_int * a) +{ + if (a == NULL) + return; + fp_clear(a); +} + +void mp_free(mp_int* a) +{ + fp_free(a); +} + +/* handle up to 6 inits */ +int mp_init_multi(mp_int* a, mp_int* b, mp_int* c, mp_int* d, + mp_int* e, mp_int* f) +{ + if (a) + fp_init(a); + if (b) + fp_init(b); + if (c) + fp_init(c); + if (d) + fp_init(d); + if (e) + fp_init(e); + if (f) + fp_init(f); + + return MP_OKAY; +} + +/* high level addition (handles signs) */ +int mp_add (mp_int * a, mp_int * b, mp_int * c) +{ + fp_add(a, b, c); + return MP_OKAY; +} + +/* high level subtraction (handles signs) */ +int mp_sub (mp_int * a, mp_int * b, mp_int * c) +{ + fp_sub(a, b, c); + return MP_OKAY; +} + +/* high level multiplication (handles sign) */ +#if defined(FREESCALE_LTC_TFM) +int wolfcrypt_mp_mul(mp_int * a, mp_int * b, mp_int * c) +#else +int mp_mul (mp_int * a, mp_int * b, mp_int * c) +#endif +{ + return fp_mul(a, b, c); +} + +int mp_mul_d (mp_int * a, mp_digit b, mp_int * c) +{ + fp_mul_d(a, b, c); + return MP_OKAY; +} + +/* d = a * b (mod c) */ +#if defined(FREESCALE_LTC_TFM) +int wolfcrypt_mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d) +#else +int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d) +#endif +{ + #if defined(WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI) + int A = fp_count_bits (a); + int B = fp_count_bits (b); + + if( A >= ESP_RSA_MULM_BITS && B >= ESP_RSA_MULM_BITS) + return esp_mp_mulmod(a, b, c, d); + else + #endif + return fp_mulmod(a, b, c, d); +} + +/* d = a - b (mod c) */ +int mp_submod(mp_int *a, mp_int *b, mp_int *c, mp_int *d) +{ + return fp_submod(a, b, c, d); +} + +/* d = a + b (mod c) */ +int mp_addmod(mp_int *a, mp_int *b, mp_int *c, mp_int *d) +{ + return fp_addmod(a, b, c, d); +} + +/* c = a mod b, 0 <= c < b */ +#if defined(FREESCALE_LTC_TFM) +int wolfcrypt_mp_mod (mp_int * a, mp_int * b, mp_int * c) +#else +int mp_mod (mp_int * a, mp_int * b, mp_int * c) +#endif +{ + return fp_mod (a, b, c); +} + +/* hac 14.61, pp608 */ +#if defined(FREESCALE_LTC_TFM) +int wolfcrypt_mp_invmod (mp_int * a, mp_int * b, mp_int * c) +#else +int mp_invmod (mp_int * a, mp_int * b, mp_int * c) +#endif +{ + return fp_invmod(a, b, c); +} + +/* this is a shell function that calls either the normal or Montgomery + * exptmod functions. Originally the call to the montgomery code was + * embedded in the normal function but that wasted alot of stack space + * for nothing (since 99% of the time the Montgomery code would be called) + */ +#if defined(FREESCALE_LTC_TFM) +int wolfcrypt_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) +#else +int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y) +#endif +{ + return fp_exptmod(G, X, P, Y); +} + +/* compare two ints (signed)*/ +int mp_cmp (mp_int * a, mp_int * b) +{ + return fp_cmp(a, b); +} + +/* compare a digit */ +int mp_cmp_d(mp_int * a, mp_digit b) +{ + return fp_cmp_d(a, b); +} + +/* get the size for an unsigned equivalent */ +int mp_unsigned_bin_size (mp_int * a) +{ + return fp_unsigned_bin_size(a); +} + +int mp_to_unsigned_bin_at_pos(int x, fp_int *t, unsigned char *b) +{ + return fp_to_unsigned_bin_at_pos(x, t, b); +} + +/* store in unsigned [big endian] format */ +int mp_to_unsigned_bin (mp_int * a, unsigned char *b) +{ + return fp_to_unsigned_bin(a,b); +} + +int mp_to_unsigned_bin_len(mp_int * a, unsigned char *b, int c) +{ + return fp_to_unsigned_bin_len(a, b, c); +} +/* reads a unsigned char array, assumes the msb is stored first [big endian] */ +int mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c) +{ + fp_read_unsigned_bin(a, b, c); + return MP_OKAY; +} + + +int mp_sub_d(fp_int *a, fp_digit b, fp_int *c) +{ + return fp_sub_d(a, b, c); +} + +int mp_mul_2d(fp_int *a, int b, fp_int *c) +{ + fp_mul_2d(a, b, c); + return MP_OKAY; +} + +int mp_2expt(fp_int* a, int b) +{ + fp_2expt(a, b); + return MP_OKAY; +} + +int mp_div(fp_int * a, fp_int * b, fp_int * c, fp_int * d) +{ + return fp_div(a, b, c, d); +} + +int mp_div_2d(fp_int* a, int b, fp_int* c, fp_int* d) +{ + fp_div_2d(a, b, c, d); + return MP_OKAY; +} + +void fp_copy(fp_int *a, fp_int *b) +{ + /* if source and destination are different */ + if (a != b) { +#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT) + /* verify a will fit in b */ + if (b->size >= a->used) { + int x, oldused; + oldused = b->used; + b->used = a->used; + b->sign = a->sign; + + XMEMCPY(b->dp, a->dp, a->used * sizeof(fp_digit)); + + /* zero any excess digits on the destination that we didn't write to */ + for (x = b->used; x >= 0 && x < oldused; x++) { + b->dp[x] = 0; + } + } + else { + /* TODO: Handle error case */ + } +#else + /* all dp's are same size, so do straight copy */ + b->used = a->used; + b->sign = a->sign; + XMEMCPY(b->dp, a->dp, FP_SIZE * sizeof(fp_digit)); +#endif + } +} + +void fp_init_copy(fp_int *a, fp_int* b) +{ + if (a != b) { + fp_init(a); + fp_copy(b, a); + } +} + +/* fast math wrappers */ +int mp_copy(fp_int* a, fp_int* b) +{ + fp_copy(a, b); + return MP_OKAY; +} + +int mp_isodd(mp_int* a) +{ + return fp_isodd(a); +} + +int mp_iszero(mp_int* a) +{ + return fp_iszero(a); +} + +int mp_count_bits (mp_int* a) +{ + return fp_count_bits(a); +} + +int mp_leading_bit (mp_int* a) +{ + return fp_leading_bit(a); +} + +void mp_rshb (mp_int* a, int x) +{ + fp_rshb(a, x); +} + +void mp_rshd (mp_int* a, int x) +{ + fp_rshd(a, x); +} + +int mp_set_int(mp_int *a, unsigned long b) +{ + fp_set_int(a, b); + return MP_OKAY; +} + +int mp_is_bit_set (mp_int *a, mp_digit b) +{ + return fp_is_bit_set(a, b); +} + +int mp_set_bit(mp_int *a, mp_digit b) +{ + return fp_set_bit(a, b); +} + +#if defined(WOLFSSL_KEY_GEN) || defined (HAVE_ECC) || !defined(NO_DH) || \ + !defined(NO_DSA) || !defined(NO_RSA) + +/* c = a * a (mod b) */ +int fp_sqrmod(fp_int *a, fp_int *b, fp_int *c) +{ + int err; +#ifndef WOLFSSL_SMALL_STACK + fp_int t[1]; +#else + fp_int *t; +#endif + +#ifdef WOLFSSL_SMALL_STACK + t = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (t == NULL) + return FP_MEM; +#endif + + fp_init(t); + err = fp_sqr(a, t); + if (err == FP_OKAY) { + #if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT) + if (c->size < FP_SIZE) { + err = fp_mod(t, b, t); + fp_copy(t, c); + } + else + #endif + { + err = fp_mod(t, b, c); + } + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(t, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return err; +} + +/* fast math conversion */ +int mp_sqrmod(mp_int *a, mp_int *b, mp_int *c) +{ + return fp_sqrmod(a, b, c); +} + +/* fast math conversion */ +int mp_montgomery_calc_normalization(mp_int *a, mp_int *b) +{ + fp_montgomery_calc_normalization(a, b); + return MP_OKAY; +} + +#endif /* WOLFSSL_KEYGEN || HAVE_ECC */ + + +#if defined(WC_MP_TO_RADIX) || !defined(NO_DH) || !defined(NO_DSA) || \ + !defined(NO_RSA) + +#ifdef WOLFSSL_KEY_GEN +/* swap the elements of two integers, for cases where you can't simply swap the + * mp_int pointers around + */ +static int fp_exch (fp_int * a, fp_int * b) +{ +#ifndef WOLFSSL_SMALL_STACK + fp_int t[1]; +#else + fp_int *t; +#endif + +#ifdef WOLFSSL_SMALL_STACK + t = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (t == NULL) + return FP_MEM; +#endif + + *t = *a; + *a = *b; + *b = *t; + +#ifdef WOLFSSL_SMALL_STACK + XFREE(t, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; +} +#endif + +static const int lnz[16] = { + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 +}; + +/* Counts the number of lsbs which are zero before the first zero bit */ +int fp_cnt_lsb(fp_int *a) +{ + int x; + fp_digit q, qq; + + /* easy out */ + if (fp_iszero(a) == FP_YES) { + return 0; + } + + /* scan lower digits until non-zero */ + for (x = 0; x < a->used && a->dp[x] == 0; x++) {} + q = a->dp[x]; + x *= DIGIT_BIT; + + /* now scan this digit until a 1 is found */ + if ((q & 1) == 0) { + do { + qq = q & 15; + x += lnz[qq]; + q >>= 4; + } while (qq == 0); + } + return x; +} + + +static int s_is_power_of_two(fp_digit b, int *p) +{ + int x; + + /* fast return if no power of two */ + if ((b==0) || (b & (b-1))) { + return FP_NO; + } + + for (x = 0; x < DIGIT_BIT; x++) { + if (b == (((fp_digit)1)< cb + d == a */ +static int fp_div_d(fp_int *a, fp_digit b, fp_int *c, fp_digit *d) +{ +#ifndef WOLFSSL_SMALL_STACK + fp_int q[1]; +#else + fp_int *q; +#endif + fp_word w; + fp_digit t; + int ix; + + /* cannot divide by zero */ + if (b == 0) { + return FP_VAL; + } + + /* quick outs */ + if (b == 1 || fp_iszero(a) == FP_YES) { + if (d != NULL) { + *d = 0; + } + if (c != NULL) { + fp_copy(a, c); + } + return FP_OKAY; + } + + /* power of two ? */ + if (s_is_power_of_two(b, &ix) == FP_YES) { + if (d != NULL) { + *d = a->dp[0] & ((((fp_digit)1)<used = a->used; + q->sign = a->sign; + } + + w = 0; + for (ix = a->used - 1; ix >= 0; ix--) { + w = (w << ((fp_word)DIGIT_BIT)) | ((fp_word)a->dp[ix]); + + if (w >= b) { + t = (fp_digit)(w / b); + w -= ((fp_word)t) * ((fp_word)b); + } else { + t = 0; + } + if (c != NULL) + q->dp[ix] = (fp_digit)t; + } + + if (d != NULL) { + *d = (fp_digit)w; + } + + if (c != NULL) { + fp_clamp(q); + fp_copy(q, c); + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(q, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; +} + + +/* c = a mod b, 0 <= c < b */ +static int fp_mod_d(fp_int *a, fp_digit b, fp_digit *c) +{ + return fp_div_d(a, b, NULL, c); +} + +int mp_mod_d(fp_int *a, fp_digit b, fp_digit *c) +{ + return fp_mod_d(a, b, c); +} + +#endif /* WC_MP_TO_RADIX || !NO_DH || !NO_DSA || !NO_RSA */ + + +#if !defined(NO_DH) || !defined(NO_DSA) || !defined(NO_RSA) || \ + defined(WOLFSSL_KEY_GEN) + +static int fp_isprime_ex(fp_int *a, int t, int* result); + + +int mp_prime_is_prime(mp_int* a, int t, int* result) +{ + return fp_isprime_ex(a, t, result); +} + +/* Miller-Rabin test of "a" to the base of "b" as described in + * HAC pp. 139 Algorithm 4.24 + * + * Sets result to 0 if definitely composite or 1 if probably prime. + * Randomly the chance of error is no more than 1/4 and often + * very much lower. + */ +static int fp_prime_miller_rabin_ex(fp_int * a, fp_int * b, int *result, + fp_int *n1, fp_int *y, fp_int *r) +{ + int s, j; + int err; + + /* default */ + *result = FP_NO; + + /* ensure b > 1 */ + if (fp_cmp_d(b, 1) != FP_GT) { + return FP_OKAY; + } + + /* get n1 = a - 1 */ + fp_copy(a, n1); + err = fp_sub_d(n1, 1, n1); + if (err != FP_OKAY) { + return err; + } + + /* set 2**s * r = n1 */ + fp_copy(n1, r); + + /* count the number of least significant bits + * which are zero + */ + s = fp_cnt_lsb(r); + + /* now divide n - 1 by 2**s */ + fp_div_2d (r, s, r, NULL); + + /* compute y = b**r mod a */ + fp_zero(y); +#if (defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_RSA_PUBLIC_ONLY)) || \ + defined(WOLFSSL_HAVE_SP_DH) +#ifndef WOLFSSL_SP_NO_2048 + if (fp_count_bits(a) == 1024) + sp_ModExp_1024(b, r, a, y); + else if (fp_count_bits(a) == 2048) + sp_ModExp_2048(b, r, a, y); + else +#endif +#ifndef WOLFSSL_SP_NO_3072 + if (fp_count_bits(a) == 1536) + sp_ModExp_1536(b, r, a, y); + else if (fp_count_bits(a) == 3072) + sp_ModExp_3072(b, r, a, y); + else +#endif +#endif + fp_exptmod(b, r, a, y); + + /* if y != 1 and y != n1 do */ + if (fp_cmp_d (y, 1) != FP_EQ && fp_cmp (y, n1) != FP_EQ) { + j = 1; + /* while j <= s-1 and y != n1 */ + while ((j <= (s - 1)) && fp_cmp (y, n1) != FP_EQ) { + fp_sqrmod (y, a, y); + + /* if y == 1 then composite */ + if (fp_cmp_d (y, 1) == FP_EQ) { + return FP_OKAY; + } + ++j; + } + + /* if y != n1 then composite */ + if (fp_cmp (y, n1) != FP_EQ) { + return FP_OKAY; + } + } + + /* probably prime now */ + *result = FP_YES; + + return FP_OKAY; +} + +static int fp_prime_miller_rabin(fp_int * a, fp_int * b, int *result) +{ + int err; +#ifndef WOLFSSL_SMALL_STACK + fp_int n1[1], y[1], r[1]; +#else + fp_int *n1, *y, *r; +#endif + +#ifdef WOLFSSL_SMALL_STACK + n1 = (fp_int*)XMALLOC(sizeof(fp_int) * 3, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (n1 == NULL) { + return FP_MEM; + } + y = &n1[1]; r = &n1[2]; +#endif + + fp_init(n1); + fp_init(y); + fp_init(r); + + err = fp_prime_miller_rabin_ex(a, b, result, n1, y, r); + + fp_clear(n1); + fp_clear(y); + fp_clear(r); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(n1, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return err; +} + + +/* a few primes */ +static const fp_digit primes[FP_PRIME_SIZE] = { + 0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013, + 0x0017, 0x001D, 0x001F, 0x0025, 0x0029, 0x002B, 0x002F, 0x0035, + 0x003B, 0x003D, 0x0043, 0x0047, 0x0049, 0x004F, 0x0053, 0x0059, + 0x0061, 0x0065, 0x0067, 0x006B, 0x006D, 0x0071, 0x007F, 0x0083, + 0x0089, 0x008B, 0x0095, 0x0097, 0x009D, 0x00A3, 0x00A7, 0x00AD, + 0x00B3, 0x00B5, 0x00BF, 0x00C1, 0x00C5, 0x00C7, 0x00D3, 0x00DF, + 0x00E3, 0x00E5, 0x00E9, 0x00EF, 0x00F1, 0x00FB, 0x0101, 0x0107, + 0x010D, 0x010F, 0x0115, 0x0119, 0x011B, 0x0125, 0x0133, 0x0137, + + 0x0139, 0x013D, 0x014B, 0x0151, 0x015B, 0x015D, 0x0161, 0x0167, + 0x016F, 0x0175, 0x017B, 0x017F, 0x0185, 0x018D, 0x0191, 0x0199, + 0x01A3, 0x01A5, 0x01AF, 0x01B1, 0x01B7, 0x01BB, 0x01C1, 0x01C9, + 0x01CD, 0x01CF, 0x01D3, 0x01DF, 0x01E7, 0x01EB, 0x01F3, 0x01F7, + 0x01FD, 0x0209, 0x020B, 0x021D, 0x0223, 0x022D, 0x0233, 0x0239, + 0x023B, 0x0241, 0x024B, 0x0251, 0x0257, 0x0259, 0x025F, 0x0265, + 0x0269, 0x026B, 0x0277, 0x0281, 0x0283, 0x0287, 0x028D, 0x0293, + 0x0295, 0x02A1, 0x02A5, 0x02AB, 0x02B3, 0x02BD, 0x02C5, 0x02CF, + + 0x02D7, 0x02DD, 0x02E3, 0x02E7, 0x02EF, 0x02F5, 0x02F9, 0x0301, + 0x0305, 0x0313, 0x031D, 0x0329, 0x032B, 0x0335, 0x0337, 0x033B, + 0x033D, 0x0347, 0x0355, 0x0359, 0x035B, 0x035F, 0x036D, 0x0371, + 0x0373, 0x0377, 0x038B, 0x038F, 0x0397, 0x03A1, 0x03A9, 0x03AD, + 0x03B3, 0x03B9, 0x03C7, 0x03CB, 0x03D1, 0x03D7, 0x03DF, 0x03E5, + 0x03F1, 0x03F5, 0x03FB, 0x03FD, 0x0407, 0x0409, 0x040F, 0x0419, + 0x041B, 0x0425, 0x0427, 0x042D, 0x043F, 0x0443, 0x0445, 0x0449, + 0x044F, 0x0455, 0x045D, 0x0463, 0x0469, 0x047F, 0x0481, 0x048B, + + 0x0493, 0x049D, 0x04A3, 0x04A9, 0x04B1, 0x04BD, 0x04C1, 0x04C7, + 0x04CD, 0x04CF, 0x04D5, 0x04E1, 0x04EB, 0x04FD, 0x04FF, 0x0503, + 0x0509, 0x050B, 0x0511, 0x0515, 0x0517, 0x051B, 0x0527, 0x0529, + 0x052F, 0x0551, 0x0557, 0x055D, 0x0565, 0x0577, 0x0581, 0x058F, + 0x0593, 0x0595, 0x0599, 0x059F, 0x05A7, 0x05AB, 0x05AD, 0x05B3, + 0x05BF, 0x05C9, 0x05CB, 0x05CF, 0x05D1, 0x05D5, 0x05DB, 0x05E7, + 0x05F3, 0x05FB, 0x0607, 0x060D, 0x0611, 0x0617, 0x061F, 0x0623, + 0x062B, 0x062F, 0x063D, 0x0641, 0x0647, 0x0649, 0x064D, 0x0653 +}; + +int fp_isprime_ex(fp_int *a, int t, int* result) +{ +#ifndef WOLFSSL_SMALL_STACK + fp_int b[1]; +#else + fp_int *b; +#endif + fp_digit d; + int r, res; + + if (t <= 0 || t > FP_PRIME_SIZE) { + return FP_NO; + } + + /* check against primes table */ + for (r = 0; r < FP_PRIME_SIZE; r++) { + if (fp_cmp_d(a, primes[r]) == FP_EQ) { + *result = FP_YES; + return FP_OKAY; + } + } + + /* do trial division */ + for (r = 0; r < FP_PRIME_SIZE; r++) { + res = fp_mod_d(a, primes[r], &d); + if (res != MP_OKAY || d == 0) { + *result = FP_NO; + return FP_OKAY; + } + } + +#ifdef WOLFSSL_SMALL_STACK + b = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (b == NULL) + return FP_MEM; +#endif + /* now do 't' miller rabins */ + fp_init(b); + for (r = 0; r < t; r++) { + fp_set(b, primes[r]); + fp_prime_miller_rabin(a, b, &res); + if (res == FP_NO) { + *result = FP_NO; + #ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return FP_OKAY; + } + } + *result = FP_YES; +#ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; +} + + +int mp_prime_is_prime_ex(mp_int* a, int t, int* result, WC_RNG* rng) +{ + int ret = FP_YES; + + if (a == NULL || result == NULL || rng == NULL) + return FP_VAL; + + if (ret == FP_YES) { + fp_digit d; + int r; + + /* check against primes table */ + for (r = 0; r < FP_PRIME_SIZE; r++) { + if (fp_cmp_d(a, primes[r]) == FP_EQ) { + *result = FP_YES; + return FP_OKAY; + } + } + + /* do trial division */ + for (r = 0; r < FP_PRIME_SIZE; r++) { + if (fp_mod_d(a, primes[r], &d) == MP_OKAY) { + if (d == 0) { + *result = FP_NO; + return FP_OKAY; + } + } + else + return FP_VAL; + } + } + +#ifndef WC_NO_RNG + /* now do a miller rabin with up to t random numbers, this should + * give a (1/4)^t chance of a false prime. */ + if (ret == FP_YES) { + #ifndef WOLFSSL_SMALL_STACK + fp_int b[1], c[1], n1[1], y[1], r[1]; + byte base[FP_MAX_PRIME_SIZE]; + #else + fp_int *b, *c, *n1, *y, *r; + byte* base; + #endif + word32 baseSz; + int err; + + baseSz = fp_count_bits(a); + /* The base size is the number of bits / 8. One is added if the number + * of bits isn't an even 8. */ + baseSz = (baseSz / 8) + ((baseSz % 8) ? 1 : 0); + + #ifndef WOLFSSL_SMALL_STACK + if (baseSz > sizeof(base)) + return FP_MEM; + #else + base = (byte*)XMALLOC(baseSz, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (base == NULL) + return FP_MEM; + + b = (fp_int*)XMALLOC(sizeof(fp_int) * 5, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (b == NULL) { + return FP_MEM; + } + c = &b[1]; n1 = &b[2]; y= &b[3]; r = &b[4]; + #endif + + fp_init(b); + fp_init(c); + fp_init(n1); + fp_init(y); + fp_init(r); + + err = fp_sub_d(a, 2, c); + if (err != FP_OKAY) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(base, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return err; + } + while (t > 0) { + if ((err = wc_RNG_GenerateBlock(rng, base, baseSz)) != 0) { + #ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(base, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return err; + } + + fp_read_unsigned_bin(b, base, baseSz); + if (fp_cmp_d(b, 2) != FP_GT || fp_cmp(b, c) != FP_LT) { + continue; + } + + fp_prime_miller_rabin_ex(a, b, &ret, n1, y, r); + if (ret == FP_NO) + break; + fp_zero(b); + t--; + } + + fp_clear(n1); + fp_clear(y); + fp_clear(r); + fp_clear(b); + fp_clear(c); + #ifdef WOLFSSL_SMALL_STACK + XFREE(b, NULL, DYNAMIC_TYPE_TMP_BUFFER); + XFREE(base, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + } +#else + (void)t; +#endif /* !WC_NO_RNG */ + + *result = ret; + return FP_OKAY; +} +#endif /* !NO_RSA || !NO_DSA || !NO_DH || WOLFSSL_KEY_GEN */ + + +#ifdef WOLFSSL_KEY_GEN + +static int fp_gcd(fp_int *a, fp_int *b, fp_int *c); +static int fp_lcm(fp_int *a, fp_int *b, fp_int *c); +static int fp_randprime(fp_int* N, int len, WC_RNG* rng, void* heap); + +int mp_gcd(fp_int *a, fp_int *b, fp_int *c) +{ + return fp_gcd(a, b, c); +} + + +int mp_lcm(fp_int *a, fp_int *b, fp_int *c) +{ + return fp_lcm(a, b, c); +} + +int mp_rand_prime(mp_int* N, int len, WC_RNG* rng, void* heap) +{ + int err; + + err = fp_randprime(N, len, rng, heap); + switch(err) { + case FP_VAL: + return MP_VAL; + case FP_MEM: + return MP_MEM; + default: + break; + } + + return MP_OKAY; +} + +int mp_exch (mp_int * a, mp_int * b) +{ + return fp_exch(a, b); +} + + + +int fp_randprime(fp_int* N, int len, WC_RNG* rng, void* heap) +{ + static const int USE_BBS = 1; + int err, type; + int isPrime = FP_YES; + /* Assume the candidate is probably prime and then test until + * it is proven composite. */ + byte* buf; + + /* get type */ + if (len < 0) { + type = USE_BBS; + len = -len; + } else { + type = 0; + } + + /* allow sizes between 2 and 512 bytes for a prime size */ + if (len < 2 || len > 512) { + return FP_VAL; + } + + /* allocate buffer to work with */ + buf = (byte*)XMALLOC(len, heap, DYNAMIC_TYPE_TMP_BUFFER); + if (buf == NULL) { + return FP_MEM; + } + XMEMSET(buf, 0, len); + + do { +#ifdef SHOW_GEN + printf("."); + fflush(stdout); +#endif + /* generate value */ + err = wc_RNG_GenerateBlock(rng, buf, len); + if (err != 0) { + XFREE(buf, heap, DYNAMIC_TYPE_TMP_BUFFER); + return FP_VAL; + } + + /* munge bits */ + buf[0] |= 0x80 | 0x40; + buf[len-1] |= 0x01 | ((type & USE_BBS) ? 0x02 : 0x00); + + /* load value */ + fp_read_unsigned_bin(N, buf, len); + + /* test */ + /* Running Miller-Rabin up to 3 times gives us a 2^{-80} chance + * of a 1024-bit candidate being a false positive, when it is our + * prime candidate. (Note 4.49 of Handbook of Applied Cryptography.) + * Using 8 because we've always used 8 */ + mp_prime_is_prime_ex(N, 8, &isPrime, rng); + } while (isPrime == FP_NO); + + XMEMSET(buf, 0, len); + XFREE(buf, heap, DYNAMIC_TYPE_TMP_BUFFER); + + return FP_OKAY; +} + +/* c = [a, b] */ +int fp_lcm(fp_int *a, fp_int *b, fp_int *c) +{ + int err; +#ifndef WOLFSSL_SMALL_STACK + fp_int t[2]; +#else + fp_int *t; +#endif + +#ifdef WOLFSSL_SMALL_STACK + t = (fp_int*)XMALLOC(sizeof(fp_int) * 2, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (t == NULL) { + return FP_MEM; + } +#endif + + fp_init(&t[0]); + fp_init(&t[1]); + err = fp_gcd(a, b, &t[0]); + if (err == FP_OKAY) { + if (fp_cmp_mag(a, b) == FP_GT) { + err = fp_div(a, &t[0], &t[1], NULL); + if (err == FP_OKAY) + err = fp_mul(b, &t[1], c); + } else { + err = fp_div(b, &t[0], &t[1], NULL); + if (err == FP_OKAY) + err = fp_mul(a, &t[1], c); + } + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(t, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return err; +} + + + +/* c = (a, b) */ +int fp_gcd(fp_int *a, fp_int *b, fp_int *c) +{ +#ifndef WOLFSSL_SMALL_STACK + fp_int u[1], v[1], r[1]; +#else + fp_int *u, *v, *r; +#endif + + /* either zero than gcd is the largest */ + if (fp_iszero (a) == FP_YES && fp_iszero (b) == FP_NO) { + fp_abs (b, c); + return FP_OKAY; + } + if (fp_iszero (a) == FP_NO && fp_iszero (b) == FP_YES) { + fp_abs (a, c); + return FP_OKAY; + } + + /* optimized. At this point if a == 0 then + * b must equal zero too + */ + if (fp_iszero (a) == FP_YES) { + fp_zero(c); + return FP_OKAY; + } + +#ifdef WOLFSSL_SMALL_STACK + u = (fp_int*)XMALLOC(sizeof(fp_int) * 3, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (u == NULL) { + return FP_MEM; + } + v = &u[1]; r = &u[2]; +#endif + + /* sort inputs */ + if (fp_cmp_mag(a, b) != FP_LT) { + fp_init_copy(u, a); + fp_init_copy(v, b); + } else { + fp_init_copy(u, b); + fp_init_copy(v, a); + } + + fp_init(r); + while (fp_iszero(v) == FP_NO) { + fp_mod(u, v, r); + fp_copy(v, u); + fp_copy(r, v); + } + fp_copy(u, c); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(u, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; +} + +#endif /* WOLFSSL_KEY_GEN */ + + +#if defined(HAVE_ECC) || !defined(NO_PWDBASED) || defined(OPENSSL_EXTRA) || \ + defined(WC_RSA_BLINDING) || !defined(NO_DSA) || \ + (!defined(NO_RSA) && !defined(NO_RSA_BOUNDS_CHECK)) +/* c = a + b */ +void fp_add_d(fp_int *a, fp_digit b, fp_int *c) +{ +#ifndef WOLFSSL_SMALL_STACK + fp_int tmp; + fp_init(&tmp); + fp_set(&tmp, b); + fp_add(a, &tmp, c); +#else + int i; + fp_word t = b; + + fp_copy(a, c); + for (i = 0; t != 0 && i < FP_SIZE && i < c->used; i++) { + t += c->dp[i]; + c->dp[i] = (fp_digit)t; + t >>= DIGIT_BIT; + } + if (i == c->used && i < FP_SIZE && t != 0) { + c->dp[i] = t; + c->used++; + } +#endif +} + +/* external compatibility */ +int mp_add_d(fp_int *a, fp_digit b, fp_int *c) +{ + fp_add_d(a, b, c); + return MP_OKAY; +} + +#endif /* HAVE_ECC || !NO_PWDBASED || OPENSSL_EXTRA || WC_RSA_BLINDING || + !NO_DSA || (!NO_RSA && !NO_RSA_BOUNDS_CHECK) */ + + +#if !defined(NO_DSA) || defined(HAVE_ECC) || defined(WOLFSSL_KEY_GEN) || \ + defined(HAVE_COMP_KEY) || defined(WOLFSSL_DEBUG_MATH) || \ + defined(DEBUG_WOLFSSL) || defined(OPENSSL_EXTRA) || defined(WC_MP_TO_RADIX) + +/* chars used in radix conversions */ +static const char* const fp_s_rmap = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz+/"; +#endif + +#if !defined(NO_DSA) || defined(HAVE_ECC) +#if DIGIT_BIT == 64 || DIGIT_BIT == 32 +static int fp_read_radix_16(fp_int *a, const char *str) +{ + int i, j, k, neg; + char ch; + + /* if the leading digit is a + * minus set the sign to negative. + */ + if (*str == '-') { + ++str; + neg = FP_NEG; + } else { + neg = FP_ZPOS; + } + + j = 0; + k = 0; + for (i = (int)(XSTRLEN(str) - 1); i >= 0; i--) { + ch = str[i]; + if (ch >= '0' && ch <= '9') + ch -= '0'; + else if (ch >= 'A' && ch <= 'F') + ch -= 'A' - 10; + else if (ch >= 'a' && ch <= 'f') + ch -= 'a' - 10; + else + return FP_VAL; + + a->dp[k] |= ((fp_digit)ch) << j; + j += 4; + k += j == DIGIT_BIT; + j &= DIGIT_BIT - 1; + } + + a->used = k + 1; + fp_clamp(a); + /* set the sign only if a != 0 */ + if (fp_iszero(a) != FP_YES) { + a->sign = neg; + } + return FP_OKAY; +} +#endif + +static int fp_read_radix(fp_int *a, const char *str, int radix) +{ + int y, neg; + char ch; + + /* set the integer to the default of zero */ + fp_zero (a); + +#if DIGIT_BIT == 64 || DIGIT_BIT == 32 + if (radix == 16) + return fp_read_radix_16(a, str); +#endif + + /* make sure the radix is ok */ + if (radix < 2 || radix > 64) { + return FP_VAL; + } + + /* if the leading digit is a + * minus set the sign to negative. + */ + if (*str == '-') { + ++str; + neg = FP_NEG; + } else { + neg = FP_ZPOS; + } + + /* process each digit of the string */ + while (*str) { + /* if the radix <= 36 the conversion is case insensitive + * this allows numbers like 1AB and 1ab to represent the same value + * [e.g. in hex] + */ + ch = (char)((radix <= 36) ? XTOUPPER((unsigned char)*str) : *str); + for (y = 0; y < 64; y++) { + if (ch == fp_s_rmap[y]) { + break; + } + } + + /* if the char was found in the map + * and is less than the given radix add it + * to the number, otherwise exit the loop. + */ + if (y < radix) { + fp_mul_d (a, (fp_digit) radix, a); + fp_add_d (a, (fp_digit) y, a); + } else { + break; + } + ++str; + } + + /* set the sign only if a != 0 */ + if (fp_iszero(a) != FP_YES) { + a->sign = neg; + } + return FP_OKAY; +} + +/* fast math conversion */ +int mp_read_radix(mp_int *a, const char *str, int radix) +{ + return fp_read_radix(a, str, radix); +} + +#endif /* !defined(NO_DSA) || defined(HAVE_ECC) */ + +#ifdef HAVE_ECC + +/* fast math conversion */ +int mp_sqr(fp_int *A, fp_int *B) +{ + return fp_sqr(A, B); +} + +/* fast math conversion */ +int mp_montgomery_reduce(fp_int *a, fp_int *m, fp_digit mp) +{ + return fp_montgomery_reduce(a, m, mp); +} + + +/* fast math conversion */ +int mp_montgomery_setup(fp_int *a, fp_digit *rho) +{ + return fp_montgomery_setup(a, rho); +} + +int mp_div_2(fp_int * a, fp_int * b) +{ + fp_div_2(a, b); + return MP_OKAY; +} + + +int mp_init_copy(fp_int * a, fp_int * b) +{ + fp_init_copy(a, b); + return MP_OKAY; +} + +#ifdef HAVE_COMP_KEY + +int mp_cnt_lsb(fp_int* a) +{ + return fp_cnt_lsb(a); +} + +#endif /* HAVE_COMP_KEY */ + +#endif /* HAVE_ECC */ + +#if defined(HAVE_ECC) || !defined(NO_RSA) || !defined(NO_DSA) || \ + defined(WOLFSSL_KEY_GEN) +/* fast math conversion */ +int mp_set(fp_int *a, fp_digit b) +{ + fp_set(a,b); + return MP_OKAY; +} +#endif + +#ifdef WC_MP_TO_RADIX + +/* returns size of ASCII representation */ +int mp_radix_size (mp_int *a, int radix, int *size) +{ + int res, digs; + fp_digit d; +#ifndef WOLFSSL_SMALL_STACK + fp_int t[1]; +#else + fp_int *t; +#endif + + *size = 0; + + /* special case for binary */ + if (radix == 2) { + *size = fp_count_bits (a) + (a->sign == FP_NEG ? 1 : 0) + 1; + return FP_YES; + } + + /* make sure the radix is in range */ + if (radix < 2 || radix > 64) { + return FP_VAL; + } + + if (fp_iszero(a) == MP_YES) { + *size = 2; + return FP_OKAY; + } + + /* digs is the digit count */ + digs = 0; + + /* if it's negative add one for the sign */ + if (a->sign == FP_NEG) { + ++digs; + } + +#ifdef WOLFSSL_SMALL_STACK + t = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (t == NULL) + return FP_MEM; +#endif + + /* init a copy of the input */ + fp_init_copy (t, a); + + /* force temp to positive */ + t->sign = FP_ZPOS; + + /* fetch out all of the digits */ + while (fp_iszero (t) == FP_NO) { + if ((res = fp_div_d (t, (mp_digit) radix, t, &d)) != FP_OKAY) { + fp_zero (t); + #ifdef WOLFSSL_SMALL_STACK + XFREE(t, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return res; + } + ++digs; + } + fp_zero (t); + + /* return digs + 1, the 1 is for the NULL byte that would be required. */ + *size = digs + 1; +#ifdef WOLFSSL_SMALL_STACK + XFREE(t, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; +} + +/* stores a bignum as a ASCII string in a given radix (2..64) */ +int mp_toradix (mp_int *a, char *str, int radix) +{ + int res, digs; + fp_digit d; + char *_s = str; +#ifndef WOLFSSL_SMALL_STACK + fp_int t[1]; +#else + fp_int *t; +#endif + + /* check range of the radix */ + if (radix < 2 || radix > 64) { + return FP_VAL; + } + + /* quick out if its zero */ + if (fp_iszero(a) == FP_YES) { + *str++ = '0'; + *str = '\0'; + return FP_YES; + } + +#ifdef WOLFSSL_SMALL_STACK + t = (fp_int*)XMALLOC(sizeof(fp_int), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (t == NULL) + return FP_MEM; +#endif + + /* init a copy of the input */ + fp_init_copy (t, a); + + /* if it is negative output a - */ + if (t->sign == FP_NEG) { + ++_s; + *str++ = '-'; + t->sign = FP_ZPOS; + } + + digs = 0; + while (fp_iszero (t) == FP_NO) { + if ((res = fp_div_d (t, (fp_digit) radix, t, &d)) != FP_OKAY) { + fp_zero (t); + #ifdef WOLFSSL_SMALL_STACK + XFREE(t, NULL, DYNAMIC_TYPE_TMP_BUFFER); + #endif + return res; + } + *str++ = fp_s_rmap[d]; + ++digs; + } + + /* reverse the digits of the string. In this case _s points + * to the first digit [excluding the sign] of the number] + */ + fp_reverse ((unsigned char *)_s, digs); + + /* append a NULL so the string is properly terminated */ + *str = '\0'; + + fp_zero (t); +#ifdef WOLFSSL_SMALL_STACK + XFREE(t, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return FP_OKAY; +} + +#ifdef WOLFSSL_DEBUG_MATH +void mp_dump(const char* desc, mp_int* a, byte verbose) +{ + char buffer[FP_SIZE * sizeof(fp_digit) * 2]; + int size = FP_SIZE; + +#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT) + size = a->size; +#endif + + printf("%s: ptr=%p, used=%d, sign=%d, size=%d, fpd=%d\n", + desc, a, a->used, a->sign, size, (int)sizeof(fp_digit)); + + mp_tohex(a, buffer); + printf(" %s\n ", buffer); + + if (verbose) { + int i; + for(i=0; idp) + i)); + } + printf("\n"); + } +} +#endif /* WOLFSSL_DEBUG_MATH */ + +#endif /* WC_MP_TO_RADIX */ + + +int mp_abs(mp_int* a, mp_int* b) +{ + fp_abs(a, b); + return FP_OKAY; +} + + +int mp_lshd (mp_int * a, int b) +{ + fp_lshd(a, b); + return FP_OKAY; +} + +#endif /* USE_FAST_MATH */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/wc_encrypt.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/wc_encrypt.c new file mode 100755 index 0000000..9bc9e55 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/wc_encrypt.c @@ -0,0 +1,622 @@ +/* wc_encrypt.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#if !defined(NO_AES) && defined(HAVE_AES_CBC) +#ifdef HAVE_AES_DECRYPT +int wc_AesCbcDecryptWithKey(byte* out, const byte* in, word32 inSz, + const byte* key, word32 keySz, const byte* iv) +{ + int ret = 0; +#ifdef WOLFSSL_SMALL_STACK + Aes* aes = NULL; +#else + Aes aes[1]; +#endif + + if (out == NULL || in == NULL || key == NULL || iv == NULL) { + return BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + aes = (Aes*)XMALLOC(sizeof(Aes), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (aes == NULL) + return MEMORY_E; +#endif + + ret = wc_AesInit(aes, NULL, INVALID_DEVID); + if (ret == 0) { + ret = wc_AesSetKey(aes, key, keySz, iv, AES_DECRYPTION); + if (ret == 0) + ret = wc_AesCbcDecrypt(aes, out, in, inSz); + + wc_AesFree(aes); + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(aes, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} +#endif /* HAVE_AES_DECRYPT */ + +int wc_AesCbcEncryptWithKey(byte* out, const byte* in, word32 inSz, + const byte* key, word32 keySz, const byte* iv) +{ + int ret = 0; +#ifdef WOLFSSL_SMALL_STACK + Aes* aes = NULL; +#else + Aes aes[1]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + aes = (Aes*)XMALLOC(sizeof(Aes), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (aes == NULL) + return MEMORY_E; +#endif + + ret = wc_AesInit(aes, NULL, INVALID_DEVID); + if (ret == 0) { + ret = wc_AesSetKey(aes, key, keySz, iv, AES_ENCRYPTION); + if (ret == 0) + ret = wc_AesCbcEncrypt(aes, out, in, inSz); + + wc_AesFree(aes); + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(aes, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} +#endif /* !NO_AES && HAVE_AES_CBC */ + + +#if !defined(NO_DES3) && !defined(WOLFSSL_TI_CRYPT) +int wc_Des_CbcEncryptWithKey(byte* out, const byte* in, word32 sz, + const byte* key, const byte* iv) +{ + int ret = 0; +#ifdef WOLFSSL_SMALL_STACK + Des* des = NULL; +#else + Des des[1]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + des = (Des*)XMALLOC(sizeof(Des), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (des == NULL) + return MEMORY_E; +#endif + + ret = wc_Des_SetKey(des, key, iv, DES_ENCRYPTION); + if (ret == 0) + ret = wc_Des_CbcEncrypt(des, out, in, sz); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(des, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +int wc_Des_CbcDecryptWithKey(byte* out, const byte* in, word32 sz, + const byte* key, const byte* iv) +{ + int ret = 0; +#ifdef WOLFSSL_SMALL_STACK + Des* des = NULL; +#else + Des des[1]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + des = (Des*)XMALLOC(sizeof(Des), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (des == NULL) + return MEMORY_E; +#endif + + ret = wc_Des_SetKey(des, key, iv, DES_DECRYPTION); + if (ret == 0) + ret = wc_Des_CbcDecrypt(des, out, in, sz); + +#ifdef WOLFSSL_SMALL_STACK + XFREE(des, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + + +int wc_Des3_CbcEncryptWithKey(byte* out, const byte* in, word32 sz, + const byte* key, const byte* iv) +{ + int ret = 0; +#ifdef WOLFSSL_SMALL_STACK + Des3* des3 = NULL; +#else + Des3 des3[1]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + des3 = (Des3*)XMALLOC(sizeof(Des3), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (des3 == NULL) + return MEMORY_E; +#endif + + ret = wc_Des3Init(des3, NULL, INVALID_DEVID); + if (ret == 0) { + ret = wc_Des3_SetKey(des3, key, iv, DES_ENCRYPTION); + if (ret == 0) + ret = wc_Des3_CbcEncrypt(des3, out, in, sz); + wc_Des3Free(des3); + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(des3, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + + +int wc_Des3_CbcDecryptWithKey(byte* out, const byte* in, word32 sz, + const byte* key, const byte* iv) +{ + int ret = 0; +#ifdef WOLFSSL_SMALL_STACK + Des3* des3 = NULL; +#else + Des3 des3[1]; +#endif + +#ifdef WOLFSSL_SMALL_STACK + des3 = (Des3*)XMALLOC(sizeof(Des3), NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (des3 == NULL) + return MEMORY_E; +#endif + + ret = wc_Des3Init(des3, NULL, INVALID_DEVID); + if (ret == 0) { + ret = wc_Des3_SetKey(des3, key, iv, DES_DECRYPTION); + if (ret == 0) + ret = wc_Des3_CbcDecrypt(des3, out, in, sz); + wc_Des3Free(des3); + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(des3, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +#endif /* !NO_DES3 */ + + +#ifdef WOLFSSL_ENCRYPTED_KEYS + +int wc_BufferKeyDecrypt(EncryptedInfo* info, byte* der, word32 derSz, + const byte* password, int passwordSz, int hashType) +{ + int ret = NOT_COMPILED_IN; +#ifdef WOLFSSL_SMALL_STACK + byte* key = NULL; +#else + byte key[WC_MAX_SYM_KEY_SIZE]; +#endif + + (void)derSz; + (void)passwordSz; + (void)hashType; + + if (der == NULL || password == NULL || info == NULL || info->keySz == 0) { + return BAD_FUNC_ARG; + } + + /* use file's salt for key derivation, hex decode first */ + if (Base16_Decode(info->iv, info->ivSz, info->iv, &info->ivSz) != 0) { + return BUFFER_E; + } + if (info->ivSz < PKCS5_SALT_SZ) + return BUFFER_E; + +#ifdef WOLFSSL_SMALL_STACK + key = (byte*)XMALLOC(WC_MAX_SYM_KEY_SIZE, NULL, DYNAMIC_TYPE_SYMMETRIC_KEY); + if (key == NULL) { + return MEMORY_E; + } +#endif + + (void)XMEMSET(key, 0, WC_MAX_SYM_KEY_SIZE); + +#ifndef NO_PWDBASED + if ((ret = wc_PBKDF1(key, password, passwordSz, info->iv, PKCS5_SALT_SZ, 1, + info->keySz, hashType)) != 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(key, NULL, DYNAMIC_TYPE_SYMMETRIC_KEY); +#endif + return ret; + } +#endif + +#ifndef NO_DES3 + if (info->cipherType == WC_CIPHER_DES) + ret = wc_Des_CbcDecryptWithKey(der, der, derSz, key, info->iv); + if (info->cipherType == WC_CIPHER_DES3) + ret = wc_Des3_CbcDecryptWithKey(der, der, derSz, key, info->iv); +#endif /* NO_DES3 */ +#if !defined(NO_AES) && defined(HAVE_AES_CBC) && defined(HAVE_AES_DECRYPT) + if (info->cipherType == WC_CIPHER_AES_CBC) + ret = wc_AesCbcDecryptWithKey(der, der, derSz, key, info->keySz, + info->iv); +#endif /* !NO_AES && HAVE_AES_CBC && HAVE_AES_DECRYPT */ + +#ifdef WOLFSSL_SMALL_STACK + XFREE(key, NULL, DYNAMIC_TYPE_SYMMETRIC_KEY); +#endif + + return ret; +} + +int wc_BufferKeyEncrypt(EncryptedInfo* info, byte* der, word32 derSz, + const byte* password, int passwordSz, int hashType) +{ + int ret = NOT_COMPILED_IN; +#ifdef WOLFSSL_SMALL_STACK + byte* key = NULL; +#else + byte key[WC_MAX_SYM_KEY_SIZE]; +#endif + + (void)derSz; + (void)passwordSz; + (void)hashType; + + if (der == NULL || password == NULL || info == NULL || info->keySz == 0 || + info->ivSz < PKCS5_SALT_SZ) { + return BAD_FUNC_ARG; + } + +#ifdef WOLFSSL_SMALL_STACK + key = (byte*)XMALLOC(WC_MAX_SYM_KEY_SIZE, NULL, DYNAMIC_TYPE_SYMMETRIC_KEY); + if (key == NULL) { + return MEMORY_E; + } +#endif /* WOLFSSL_SMALL_STACK */ + + (void)XMEMSET(key, 0, WC_MAX_SYM_KEY_SIZE); + +#ifndef NO_PWDBASED + if ((ret = wc_PBKDF1(key, password, passwordSz, info->iv, PKCS5_SALT_SZ, 1, + info->keySz, hashType)) != 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(key, NULL, DYNAMIC_TYPE_SYMMETRIC_KEY); +#endif + return ret; + } +#endif + +#ifndef NO_DES3 + if (info->cipherType == WC_CIPHER_DES) + ret = wc_Des_CbcEncryptWithKey(der, der, derSz, key, info->iv); + if (info->cipherType == WC_CIPHER_DES3) + ret = wc_Des3_CbcEncryptWithKey(der, der, derSz, key, info->iv); +#endif /* NO_DES3 */ +#if !defined(NO_AES) && defined(HAVE_AES_CBC) + if (info->cipherType == WC_CIPHER_AES_CBC) + ret = wc_AesCbcEncryptWithKey(der, der, derSz, key, info->keySz, + info->iv); +#endif /* !NO_AES && HAVE_AES_CBC */ + +#ifdef WOLFSSL_SMALL_STACK + XFREE(key, NULL, DYNAMIC_TYPE_SYMMETRIC_KEY); +#endif + + return ret; +} + +#endif /* WOLFSSL_ENCRYPTED_KEYS */ + + +#ifndef NO_PWDBASED + +#if defined(HAVE_PKCS8) || defined(HAVE_PKCS12) +/* Decrypt/Encrypt input in place from parameters based on id + * + * returns a negative value on fail case + */ +int wc_CryptKey(const char* password, int passwordSz, byte* salt, + int saltSz, int iterations, int id, byte* input, + int length, int version, byte* cbcIv, int enc) +{ + int typeH; + int derivedLen; + int ret = 0; +#ifdef WOLFSSL_SMALL_STACK + byte* key; +#else + byte key[MAX_KEY_SIZE]; +#endif + + (void)input; + (void)length; + (void)enc; + + WOLFSSL_ENTER("wc_CryptKey"); + + switch (id) { + #ifndef NO_DES3 + #ifndef NO_MD5 + case PBE_MD5_DES: + typeH = WC_MD5; + derivedLen = 16; /* may need iv for v1.5 */ + break; + #endif + #ifndef NO_SHA + case PBE_SHA1_DES: + typeH = WC_SHA; + derivedLen = 16; /* may need iv for v1.5 */ + break; + + case PBE_SHA1_DES3: + typeH = WC_SHA; + derivedLen = 32; /* may need iv for v1.5 */ + break; + #endif /* !NO_SHA */ + #endif /* !NO_DES3 */ + #if !defined(NO_SHA) && !defined(NO_RC4) + case PBE_SHA1_RC4_128: + typeH = WC_SHA; + derivedLen = 16; + break; + #endif + #ifdef WOLFSSL_AES_256 + case PBE_AES256_CBC: + typeH = WC_SHA256; + derivedLen = 32; + break; + #endif + default: + WOLFSSL_MSG("Unknown/Unsupported encrypt/decrypt id"); + return ALGO_ID_E; + } + +#ifdef WOLFSSL_SMALL_STACK + key = (byte*)XMALLOC(MAX_KEY_SIZE, NULL, DYNAMIC_TYPE_TMP_BUFFER); + if (key == NULL) + return MEMORY_E; +#endif + + if (version == PKCS5v2) + ret = wc_PBKDF2(key, (byte*)password, passwordSz, + salt, saltSz, iterations, derivedLen, typeH); +#ifndef NO_SHA + else if (version == PKCS5) + ret = wc_PBKDF1(key, (byte*)password, passwordSz, + salt, saltSz, iterations, derivedLen, typeH); +#endif + else if (version == PKCS12v1) { + int i, idx = 0; + byte unicodePasswd[MAX_UNICODE_SZ]; + + if ( (passwordSz * 2 + 2) > (int)sizeof(unicodePasswd)) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return UNICODE_SIZE_E; + } + + for (i = 0; i < passwordSz; i++) { + unicodePasswd[idx++] = 0x00; + unicodePasswd[idx++] = (byte)password[i]; + } + /* add trailing NULL */ + unicodePasswd[idx++] = 0x00; + unicodePasswd[idx++] = 0x00; + + ret = wc_PKCS12_PBKDF(key, unicodePasswd, idx, salt, saltSz, + iterations, derivedLen, typeH, 1); + if (id != PBE_SHA1_RC4_128) + ret += wc_PKCS12_PBKDF(cbcIv, unicodePasswd, idx, salt, saltSz, + iterations, 8, typeH, 2); + } + else { +#ifdef WOLFSSL_SMALL_STACK + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + WOLFSSL_MSG("Unknown/Unsupported PKCS version"); + return ALGO_ID_E; + } + + if (ret != 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + switch (id) { +#ifndef NO_DES3 + #if !defined(NO_SHA) || !defined(NO_MD5) + case PBE_MD5_DES: + case PBE_SHA1_DES: + { + Des des; + byte* desIv = key + 8; + + if (version == PKCS5v2 || version == PKCS12v1) + desIv = cbcIv; + + if (enc) { + ret = wc_Des_SetKey(&des, key, desIv, DES_ENCRYPTION); + } + else { + ret = wc_Des_SetKey(&des, key, desIv, DES_DECRYPTION); + } + if (ret != 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + + if (enc) { + wc_Des_CbcEncrypt(&des, input, input, length); + } + else { + wc_Des_CbcDecrypt(&des, input, input, length); + } + break; + } + #endif /* !NO_SHA || !NO_MD5 */ + + #ifndef NO_SHA + case PBE_SHA1_DES3: + { + Des3 des; + byte* desIv = key + 24; + + if (version == PKCS5v2 || version == PKCS12v1) + desIv = cbcIv; + + ret = wc_Des3Init(&des, NULL, INVALID_DEVID); + if (ret != 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + if (enc) { + ret = wc_Des3_SetKey(&des, key, desIv, DES_ENCRYPTION); + } + else { + ret = wc_Des3_SetKey(&des, key, desIv, DES_DECRYPTION); + } + if (ret != 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + if (enc) { + ret = wc_Des3_CbcEncrypt(&des, input, input, length); + } + else { + ret = wc_Des3_CbcDecrypt(&des, input, input, length); + } + if (ret != 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + break; + } + #endif /* !NO_SHA */ +#endif +#if !defined(NO_RC4) && !defined(NO_SHA) + case PBE_SHA1_RC4_128: + { + Arc4 dec; + + wc_Arc4SetKey(&dec, key, derivedLen); + wc_Arc4Process(&dec, input, input, length); + break; + } +#endif +#if !defined(NO_AES) && defined(HAVE_AES_CBC) + #ifdef WOLFSSL_AES_256 + case PBE_AES256_CBC: + { + Aes aes; + ret = wc_AesInit(&aes, NULL, INVALID_DEVID); + if (ret == 0) { + if (enc) { + ret = wc_AesSetKey(&aes, key, derivedLen, cbcIv, + AES_ENCRYPTION); + } + else { + ret = wc_AesSetKey(&aes, key, derivedLen, cbcIv, + AES_DECRYPTION); + } + } + if (ret == 0) { + if (enc) + ret = wc_AesCbcEncrypt(&aes, input, input, length); + else + ret = wc_AesCbcDecrypt(&aes, input, input, length); + } + if (ret != 0) { +#ifdef WOLFSSL_SMALL_STACK + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + return ret; + } + ForceZero(&aes, sizeof(Aes)); + break; + } + #endif /* WOLFSSL_AES_256 */ +#endif /* !NO_AES && HAVE_AES_CBC */ + + default: +#ifdef WOLFSSL_SMALL_STACK + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + WOLFSSL_MSG("Unknown/Unsupported encrypt/decryption algorithm"); + return ALGO_ID_E; + } + +#ifdef WOLFSSL_SMALL_STACK + XFREE(key, NULL, DYNAMIC_TYPE_TMP_BUFFER); +#endif + + return ret; +} + +#endif /* HAVE_PKCS8 || HAVE_PKCS12 */ +#endif /* !NO_PWDBASED */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/wc_pkcs11.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/wc_pkcs11.c new file mode 100755 index 0000000..bcaae56 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/wc_pkcs11.c @@ -0,0 +1,2538 @@ +/* wc_pkcs11.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + +#ifdef HAVE_PKCS11 + +#include + +#include +#include +#include +#include +#ifndef NO_RSA + #include +#endif +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + +#define MAX_EC_PARAM_LEN 16 + +#if defined(NO_PKCS11_RSA) && !defined(NO_RSA) + #define NO_RSA +#endif +#if defined(NO_PKCS11_ECC) && defined(HAVE_ECC) + #undef HAVE_ECC +#endif +#if defined(NO_PKCS11_AES) && !defined(NO_AES) + #define NO_AES +#endif +#if defined(NO_PKCS11_AESGCM) && defined(HAVE_AESGCM) + #undef HAVE_AESGCM +#endif +#if defined(NO_PKCS11_AESCBC) && defined(HAVE_AES_CBC) + #undef HAVE_AES_CBC +#endif +#if defined(NO_PKCS11_HMAC) && !defined(NO_HMAC) + #define NO_HMAC +#endif +#if defined(NO_PKCS11_RNG) && !defined(WC_NO_RNG) + #define WC_NO_RNG +#endif + + +#if defined(HAVE_ECC) && !defined(NO_PKCS11_ECDH) +static CK_BBOOL ckFalse = CK_FALSE; +#endif +#if !defined(NO_RSA) || defined(HAVE_ECC) || (!defined(NO_AES) && \ + (defined(HAVE_AESGCM) || defined(HAVE_AES_CBC))) || !defined(NO_HMAC) +static CK_BBOOL ckTrue = CK_TRUE; +#endif + +#ifndef NO_RSA +static CK_KEY_TYPE rsaKeyType = CKK_RSA; +#endif +#ifdef HAVE_ECC +static CK_KEY_TYPE ecKeyType = CKK_EC; +#endif +#if !defined(NO_RSA) || defined(HAVE_ECC) +static CK_OBJECT_CLASS pubKeyClass = CKO_PUBLIC_KEY; +static CK_OBJECT_CLASS privKeyClass = CKO_PRIVATE_KEY; +#endif +#if (!defined(NO_AES) && (defined(HAVE_AESGCM) || defined(HAVE_AES_CBC))) || \ + !defined(NO_HMAC) || (defined(HAVE_ECC) && !defined(NO_PKCS11_ECDH)) +static CK_OBJECT_CLASS secretKeyClass = CKO_SECRET_KEY; +#endif + +/** + * Load library, get function list and initialize PKCS#11. + * + * @param dev [in] Device object. + * @param library [in] Library name including path. + * @return BAD_FUNC_ARG when dev or library are NULL pointers. + * BAD_PATH_ERROR when dynamic library cannot be opened. + * WC_INIT_E when the initialization PKCS#11 fails. + * WC_HW_E when unable to get PKCS#11 function list. + * 0 on success. + */ +int wc_Pkcs11_Initialize(Pkcs11Dev* dev, const char* library, void* heap) +{ + int ret = 0; + void* func; + CK_C_INITIALIZE_ARGS args; + + if (dev == NULL || library == NULL) + ret = BAD_FUNC_ARG; + + if (ret == 0) { + dev->heap = heap; + dev->dlHandle = dlopen(library, RTLD_NOW | RTLD_LOCAL); + if (dev->dlHandle == NULL) { + WOLFSSL_MSG(dlerror()); + ret = BAD_PATH_ERROR; + } + } + + if (ret == 0) { + dev->func = NULL; + func = dlsym(dev->dlHandle, "C_GetFunctionList"); + if (func == NULL) + ret = WC_HW_E; + } + if (ret == 0) { + if (((CK_C_GetFunctionList)func)(&dev->func) != CKR_OK) + ret = WC_HW_E; + } + + if (ret == 0) { + XMEMSET(&args, 0x00, sizeof(args)); + args.flags = CKF_OS_LOCKING_OK; + if (dev->func->C_Initialize(&args) != CKR_OK) + ret = WC_INIT_E; + } + + if (ret != 0) + wc_Pkcs11_Finalize(dev); + + return ret; +} + +/** + * Close the Pkcs#11 library. + * + * @param dev [in] Device object. + */ +void wc_Pkcs11_Finalize(Pkcs11Dev* dev) +{ + if (dev != NULL && dev->dlHandle != NULL) { + if (dev->func != NULL) { + dev->func->C_Finalize(NULL); + dev->func = NULL; + } + dlclose(dev->dlHandle); + dev->dlHandle = NULL; + } +} + +/** + * Set up a token for use. + * + * @param token [in] Token object. + * @param dev [in] PKCS#11 device object. + * @param slotId [in] Slot number of the token.
+ * Passing -1 uses the first available slot. + * @param tokenName [in] Name of token to initialize. + * @param userPin [in] PIN to use to login as user. + * @param userPinSz [in] Number of bytes in PIN. + * @return BAD_FUNC_ARG when token, dev and/or tokenName is NULL. + * WC_INIT_E when initializing token fails. + * WC_HW_E when another PKCS#11 library call fails. + * -1 when no slot available. + * 0 on success. + */ +int wc_Pkcs11Token_Init(Pkcs11Token* token, Pkcs11Dev* dev, int slotId, + const char* tokenName, const unsigned char* userPin, int userPinSz) +{ + int ret = 0; + CK_RV rv; + CK_SLOT_ID* slot = NULL; + CK_ULONG slotCnt = 0; + + if (token == NULL || dev == NULL || tokenName == NULL) + ret = BAD_FUNC_ARG; + + if (ret == 0) { + if (slotId < 0) { + /* Use first available slot with a token. */ + rv = dev->func->C_GetSlotList(CK_TRUE, NULL, &slotCnt); + if (rv != CKR_OK) + ret = WC_HW_E; + if (ret == 0) { + slot = (CK_SLOT_ID*)XMALLOC(slotCnt * sizeof(*slot), dev->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (slot == NULL) + ret = MEMORY_E; + } + if (ret == 0) { + rv = dev->func->C_GetSlotList(CK_TRUE, slot, &slotCnt); + if (rv != CKR_OK) + ret = WC_HW_E; + } + if (ret == 0) { + if (slotCnt > 0) + slotId = (int)slot[0]; + else + ret = WC_HW_E; + } + } + } + if (ret == 0) { + token->func = dev->func; + token->slotId = (CK_SLOT_ID)slotId; + token->handle = NULL_PTR; + token->userPin = (CK_UTF8CHAR_PTR)userPin; + token->userPinSz = (CK_ULONG)userPinSz; + } + + if (slot != NULL) + XFREE(slot, dev->heap, DYNAMIC_TYPE_TMP_BUFFER); + + return ret; +} + +/** + * Finalize token. + * Closes all sessions on token. + * + * @param token [in] Token object. + */ +void wc_Pkcs11Token_Final(Pkcs11Token* token) +{ + if (token != NULL && token->func != NULL) { + token->func->C_CloseAllSessions(token->slotId); + token->handle = NULL_PTR; + ForceZero(token->userPin, (word32)token->userPinSz); + } +} + +/** + * Open a session on a token. + * + * @param token [in] Token object. + * @param session [in] Session object. + * @param readWrite [in] Boolean indicating to open session for Read/Write. + * @return BAD_FUNC_ARG when token or session is NULL. + * WC_HW_E when opening the session fails. + * 0 on success. + */ +static int Pkcs11OpenSession(Pkcs11Token* token, Pkcs11Session* session, + int readWrite) +{ + int ret = 0; + CK_RV rv; + + if (token == NULL || session == NULL) + ret = BAD_FUNC_ARG; + + if (ret == 0) { + if (token->handle != NULL_PTR) + session->handle = token->handle; + else { + /* Create a new session. */ + CK_FLAGS flags = CKF_SERIAL_SESSION; + + if (readWrite) + flags |= CKF_RW_SESSION; + + rv = token->func->C_OpenSession(token->slotId, flags, + (CK_VOID_PTR)NULL, (CK_NOTIFY)NULL, + &session->handle); + if (rv != CKR_OK) + ret = WC_HW_E; + if (ret == 0 && token->userPin != NULL) { + rv = token->func->C_Login(session->handle, CKU_USER, + token->userPin, token->userPinSz); + if (rv != CKR_OK) + ret = WC_HW_E; + } + } + } + if (ret == 0) { + session->func = token->func; + session->slotId = token->slotId; + } + + return ret; +} + +/** + * Close a session on a token. + * Won't close a session created externally. + * + * @param token [in] Token object. + * @param session [in] Session object. + */ +static void Pkcs11CloseSession(Pkcs11Token* token, Pkcs11Session* session) +{ + if (token != NULL && session != NULL && token->handle != session->handle) { + if (token->userPin != NULL) + session->func->C_Logout(session->handle); + session->func->C_CloseSession(session->handle); + } +} + +/** + * Open a session on the token to be used for all operations. + * + * @param token [in] Token object. + * @param readWrite [in] Boolean indicating to open session for Read/Write. + * @return BAD_FUNC_ARG when token is NULL. + * WC_HW_E when opening the session fails. + * 0 on success. + */ +int wc_Pkcs11Token_Open(Pkcs11Token* token, int readWrite) +{ + int ret = 0; + Pkcs11Session session; + + if (token == NULL) + ret = BAD_FUNC_ARG; + + if (ret == 0) { + ret = Pkcs11OpenSession(token, &session, readWrite); + token->handle = session.handle; + } + + return ret; +} + +/** + * Close the token's session. + * All object, like keys, will be destoyed. + * + * @param token [in] Token object. + */ +void wc_Pkcs11Token_Close(Pkcs11Token* token) +{ + Pkcs11Session session; + + if (token != NULL) { + session.func = token->func; + session.handle = token->handle; + token->handle = NULL_PTR; + Pkcs11CloseSession(token, &session); + } +} + + +#if (!defined(NO_AES) && (defined(HAVE_AESGCM) || defined(HAVE_AES_CBC))) || \ + !defined(NO_HMAC) +static int Pkcs11CreateSecretKey(CK_OBJECT_HANDLE* key, Pkcs11Session* session, + CK_KEY_TYPE keyType, unsigned char* data, + int len, unsigned char* id, int idLen) +{ + int ret = 0; + CK_RV rv; + CK_ATTRIBUTE keyTemplate[] = { + { CKA_CLASS, &secretKeyClass, sizeof(secretKeyClass) }, + { CKA_KEY_TYPE, &keyType, sizeof(keyType) }, + { CKA_ENCRYPT, &ckTrue, sizeof(ckTrue) }, + { CKA_VALUE, NULL, 0 }, + { CKA_ID, id, (CK_ULONG)idLen } + }; + int keyTmplCnt = 4; + + WOLFSSL_MSG("PKCS#11: Create Secret Key"); + + /* Set the modulus and public exponent data. */ + keyTemplate[3].pValue = data; + keyTemplate[3].ulValueLen = (CK_ULONG)len; + + if (idLen > 0) + keyTmplCnt++; + + /* Create an object containing key data for device to use. */ + rv = session->func->C_CreateObject(session->handle, keyTemplate, keyTmplCnt, + key); + if (rv != CKR_OK) + ret = WC_HW_E; + + return ret; +} +#endif + +#ifndef NO_RSA +/** + * Create a PKCS#11 object containing the RSA private key data. + * + * @param privateKey [out] Henadle to private key object. + * @param session [in] Session object. + * @param rsaKey [in] RSA key with private key data. + * @return WC_HW_E when a PKCS#11 library call fails. + * 0 on success. + */ +static int Pkcs11CreateRsaPrivateKey(CK_OBJECT_HANDLE* privateKey, + Pkcs11Session* session, + RsaKey* rsaKey) +{ + int ret = 0; + CK_RV rv; + CK_ATTRIBUTE keyTemplate[] = { + { CKA_CLASS, &privKeyClass, sizeof(privKeyClass) }, + { CKA_KEY_TYPE, &rsaKeyType, sizeof(rsaKeyType) }, + { CKA_DECRYPT, &ckTrue, sizeof(ckTrue) }, + { CKA_MODULUS, NULL, 0 }, + { CKA_PRIVATE_EXPONENT, NULL, 0 }, + { CKA_PRIME_1, NULL, 0 }, + { CKA_PRIME_2, NULL, 0 }, + { CKA_EXPONENT_1, NULL, 0 }, + { CKA_EXPONENT_2, NULL, 0 }, + { CKA_COEFFICIENT, NULL, 0 }, + { CKA_PUBLIC_EXPONENT, NULL, 0 } + }; + CK_ULONG keyTmplCnt = sizeof(keyTemplate) / sizeof(*keyTemplate); + + /* Set the modulus and private key data. */ + keyTemplate[ 3].pValue = rsaKey->n.raw.buf; + keyTemplate[ 3].ulValueLen = rsaKey->n.raw.len; + keyTemplate[ 4].pValue = rsaKey->d.raw.buf; + keyTemplate[ 4].ulValueLen = rsaKey->d.raw.len; + keyTemplate[ 5].pValue = rsaKey->p.raw.buf; + keyTemplate[ 5].ulValueLen = rsaKey->p.raw.len; + keyTemplate[ 6].pValue = rsaKey->q.raw.buf; + keyTemplate[ 6].ulValueLen = rsaKey->q.raw.len; + keyTemplate[ 7].pValue = rsaKey->dP.raw.buf; + keyTemplate[ 7].ulValueLen = rsaKey->dP.raw.len; + keyTemplate[ 8].pValue = rsaKey->dQ.raw.buf; + keyTemplate[ 8].ulValueLen = rsaKey->dQ.raw.len; + keyTemplate[ 9].pValue = rsaKey->u.raw.buf; + keyTemplate[ 9].ulValueLen = rsaKey->u.raw.len; + keyTemplate[10].pValue = rsaKey->e.raw.buf; + keyTemplate[10].ulValueLen = rsaKey->e.raw.len; + + rv = session->func->C_CreateObject(session->handle, keyTemplate, keyTmplCnt, + privateKey); + if (rv != CKR_OK) + ret = WC_HW_E; + + return ret; +} +#endif + +#ifdef HAVE_ECC +/** + * Set the ECC parameters into the template. + * + * @param key [in] ECC key. + * @param tmpl [in] PKCS#11 template. + * @param idx [in] Index of template to put parameters into. + * @return NOT_COMPILE_IN when the EC parameters are not known. + * 0 on success. + */ +static int Pkcs11EccSetParams(ecc_key* key, CK_ATTRIBUTE* tmpl, int idx) +{ + int ret = 0; + + if (key->dp != NULL && key->dp->oid != NULL) { + unsigned char* derParams = tmpl[idx].pValue; + /* ASN.1 encoding: OBJ + ecc parameters OID */ + tmpl[idx].ulValueLen = key->dp->oidSz + 2; + derParams[0] = ASN_OBJECT_ID; + derParams[1] = key->dp->oidSz; + XMEMCPY(derParams + 2, key->dp->oid, key->dp->oidSz); + } + else + ret = NOT_COMPILED_IN; + + return ret; +} + +/** + * Create a PKCS#11 object containing the ECC private key data. + * + * @param privateKey [out] Henadle to private key object. + * @param session [in] Session object. + * @param private_key [in] ECC private key. + * @param operation [in] Cryptographic operation key is to be used for. + * @return WC_HW_E when a PKCS#11 library call fails. + * 0 on success. + */ +static int Pkcs11CreateEccPrivateKey(CK_OBJECT_HANDLE* privateKey, + Pkcs11Session* session, + ecc_key* private_key, + CK_ATTRIBUTE_TYPE operation) +{ + int ret = 0; + CK_RV rv; + CK_UTF8CHAR params[MAX_EC_PARAM_LEN]; + CK_ATTRIBUTE keyTemplate[] = { + { CKA_CLASS, &privKeyClass, sizeof(privKeyClass) }, + { CKA_KEY_TYPE, &ecKeyType, sizeof(ecKeyType) }, + { operation, &ckTrue, sizeof(ckTrue) }, + { CKA_EC_PARAMS, params, 0 }, + { CKA_VALUE, NULL, 0 } + }; + CK_ULONG keyTmplCnt = sizeof(keyTemplate) / sizeof(*keyTemplate); + + ret = Pkcs11EccSetParams(private_key, keyTemplate, 3); + if (ret == 0) { + keyTemplate[4].pValue = private_key->k.raw.buf; + keyTemplate[4].ulValueLen = private_key->k.raw.len; + + rv = session->func->C_CreateObject(session->handle, keyTemplate, + keyTmplCnt, privateKey); + if (rv != CKR_OK) + ret = WC_HW_E; + } + + return ret; +} +#endif + +#if !defined(NO_RSA) || defined(HAVE_ECC) || (!defined(NO_AES) && \ + (defined(HAVE_AESGCM) || defined(HAVE_AES_CBC))) || !defined(NO_HMAC) +/** + * Check if mechanism is available in session on token. + * + * @param session [in] Session object. + * @param mech [in] Mechanism to look for. + * @return NOT_COMPILED_IN when mechanism not avaialble. + * 0 when mechanism is available. + */ +static int Pkcs11MechAvail(Pkcs11Session* session, CK_MECHANISM_TYPE mech) +{ + int ret = 0; + CK_RV rv; + CK_MECHANISM_INFO mechInfo; + + rv = session->func->C_GetMechanismInfo(session->slotId, mech, &mechInfo); + if (rv != CKR_OK) + ret = NOT_COMPILED_IN; + + return ret; +} +#endif + +#ifndef NO_HMAC +/** + * Return the mechanism type and key type for the digest type when using HMAC. + * + * @param macType [in] Digest type - e.g. WC_SHA256. + * @param mechType [in] Mechanism type - e.g. CKM_SHA256_HMAC. + * @param keyType [in] Key type - e.g. CKK_SHA256_HMAC. + * @return NOT_COMPILED_IN if the digest algorithm isn't recognised. + * 0 otherwise. + */ +static int Pkcs11HmacTypes(int macType, int* mechType, int* keyType) +{ + int ret = 0; + + switch (macType) + { + #ifndef NO_MD5 + case WC_MD5: + *mechType = CKM_MD5_HMAC; + *keyType = CKK_MD5_HMAC; + break; + #endif + #ifndef NO_SHA + case WC_SHA: + *mechType = CKM_SHA_1_HMAC; + *keyType = CKK_SHA_1_HMAC; + break; + #endif + #ifdef WOLFSSL_SHA224 + case WC_SHA224: + *mechType = CKM_SHA224_HMAC; + *keyType = CKK_SHA224_HMAC; + break; + #endif + #ifndef NO_SHA256 + case WC_SHA256: + *mechType = CKM_SHA256_HMAC; + *keyType = CKK_SHA256_HMAC; + break; + #endif + #ifdef WOLFSSL_SHA384 + case WC_SHA384: + *mechType = CKM_SHA384_HMAC; + *keyType = CKK_SHA384_HMAC; + break; + #endif + #ifdef WOLFSSL_SHA512 + case WC_SHA512: + *mechType = CKM_SHA512_HMAC; + *keyType = CKK_SHA512_HMAC; + break; + #endif + default: + ret = NOT_COMPILED_IN; + break; + } + + return ret; +} +#endif + +/** + * Store the private key on the token in the session. + * + * @param token [in] Token to store private key on. + * @param type [in] Key type. + * @param clear [in] Clear out the private data from software key. + * @param key [in] Key type specific object. + * @return NOT_COMPILED_IN when mechanism not available. + * 0 on success. + */ +int wc_Pkcs11StoreKey(Pkcs11Token* token, int type, int clear, void* key) +{ + int ret = 0; + Pkcs11Session session; + CK_OBJECT_HANDLE privKey = NULL_PTR; + + ret = Pkcs11OpenSession(token, &session, 1); + if (ret == 0) { + switch (type) { + #if !defined(NO_AES) && defined(HAVE_AESGCM) + case PKCS11_KEY_TYPE_AES_GCM: { + Aes* aes = (Aes*)key; + + ret = Pkcs11MechAvail(&session, CKM_AES_GCM); + if (ret == 0) { + ret = Pkcs11CreateSecretKey(&privKey, &session, CKK_AES, + (unsigned char*)aes->devKey, + aes->keylen, + (unsigned char*)aes->id, + aes->idLen); + } + if (ret == 0 && clear) + ForceZero(aes->devKey, aes->keylen); + break; + } + #endif + #if !defined(NO_AES) && defined(HAVE_AES_CBC) + case PKCS11_KEY_TYPE_AES_CBC: { + Aes* aes = (Aes*)key; + + ret = Pkcs11MechAvail(&session, CKM_AES_CBC); + if (ret == 0) { + ret = Pkcs11CreateSecretKey(&privKey, &session, CKK_AES, + (unsigned char*)aes->devKey, + aes->keylen, + (unsigned char*)aes->id, + aes->idLen); + } + if (ret == 0 && clear) + ForceZero(aes->devKey, aes->keylen); + break; + } + #endif + #ifndef NO_HMAC + case PKCS11_KEY_TYPE_HMAC: { + Hmac* hmac = (Hmac*)key; + int mechType; + int keyType; + + ret = Pkcs11HmacTypes(hmac->macType, &mechType, &keyType); + if (ret == NOT_COMPILED_IN) + break; + + if (ret == 0) + ret = Pkcs11MechAvail(&session, mechType); + if (ret == 0) { + ret = Pkcs11CreateSecretKey(&privKey, &session, keyType, + (unsigned char*)hmac->keyRaw, + hmac->keyLen, + (unsigned char*)hmac->id, + hmac->idLen); + if (ret == WC_HW_E) { + ret = Pkcs11CreateSecretKey(&privKey, &session, + CKK_GENERIC_SECRET, + (unsigned char*)hmac->keyRaw, + hmac->keyLen, + (unsigned char*)hmac->id, + hmac->idLen); + } + } + break; + } + #endif + #ifndef NO_RSA + case PKCS11_KEY_TYPE_RSA: { + RsaKey* rsaKey = (RsaKey*)key; + + ret = Pkcs11MechAvail(&session, CKM_RSA_X_509); + if (ret == 0) + ret = Pkcs11CreateRsaPrivateKey(&privKey, &session, rsaKey); + if (ret == 0 && clear) { + mp_forcezero(&rsaKey->u); + mp_forcezero(&rsaKey->dQ); + mp_forcezero(&rsaKey->dP); + mp_forcezero(&rsaKey->q); + mp_forcezero(&rsaKey->p); + mp_forcezero(&rsaKey->d); + } + break; + } + #endif + #ifdef HAVE_ECC + case PKCS11_KEY_TYPE_EC: { + ecc_key* eccKey = (ecc_key*)key; + int ret2 = NOT_COMPILED_IN; + + #ifndef NO_PKCS11_ECDH + /* Try ECDH mechanism first. */ + ret = Pkcs11MechAvail(&session, CKM_ECDH1_DERIVE); + if (ret == 0) { + ret = Pkcs11CreateEccPrivateKey(&privKey, &session, eccKey, + CKA_DERIVE); + } + #endif + if (ret == 0 || ret == NOT_COMPILED_IN) { + /* Try ECDSA mechanism next. */ + ret2 = Pkcs11MechAvail(&session, CKM_ECDSA); + if (ret2 == 0) { + ret2 = Pkcs11CreateEccPrivateKey(&privKey, &session, + eccKey, CKA_SIGN); + } + /* OK for this to fail if set for ECDH. */ + if (ret == NOT_COMPILED_IN) + ret = ret2; + } + if (ret == 0 && clear) + mp_forcezero(&eccKey->k); + break; + } + #endif + default: + ret = NOT_COMPILED_IN; + break; + } + + Pkcs11CloseSession(token, &session); + } + + (void)privKey; + (void)clear; + (void)key; + + return ret; +} + +#if !defined(NO_RSA) || defined(HAVE_ECC) || (!defined(NO_AES) && \ + (defined(HAVE_AESGCM) || defined(HAVE_AES_CBC))) || !defined(NO_HMAC) +/** + * Find the PKCS#11 object containing the RSA public or private key data with + * the modulus specified. + * + * @param key [out] Henadle to key object. + * @param keyClass [in] Public or private key class. + * @param keyType [in] Type of key. + * @param session [in] Session object. + * @param id [in] Identifier set against a key. + * @param idLen [in] Length of identifier. + * @return WC_HW_E when a PKCS#11 library call fails. + * 0 on success. + */ +static int Pkcs11FindKeyById(CK_OBJECT_HANDLE* key, CK_OBJECT_CLASS keyClass, + CK_KEY_TYPE keyType, Pkcs11Session* session, + byte* id, int idLen) +{ + int ret = 0; + CK_RV rv; + CK_ULONG count; + CK_ATTRIBUTE keyTemplate[] = { + { CKA_CLASS, &keyClass, sizeof(keyClass) }, + { CKA_KEY_TYPE, &keyType, sizeof(keyType) }, + { CKA_ID, id, (CK_ULONG)idLen } + }; + CK_ULONG keyTmplCnt = sizeof(keyTemplate) / sizeof(*keyTemplate); + + WOLFSSL_MSG("PKCS#11: Find Key By Id"); + + rv = session->func->C_FindObjectsInit(session->handle, keyTemplate, + keyTmplCnt); + if (rv != CKR_OK) + ret = WC_HW_E; + if (ret == 0) { + rv = session->func->C_FindObjects(session->handle, key, 1, &count); + if (rv != CKR_OK) + ret = WC_HW_E; + rv = session->func->C_FindObjectsFinal(session->handle); + if (rv != CKR_OK) + ret = WC_HW_E; + } + if (ret == 0 && count == 0) + ret = WC_HW_E; + + return ret; +} +#endif + +#ifndef NO_RSA +/** + * Find the PKCS#11 object containing the RSA public or private key data with + * the modulus specified. + * + * @param key [out] Henadle to key object. + * @param keyClass [in] Public or private key class. + * @param session [in] Session object. + * @param rsaKey [in] RSA key with modulus to search on. + * @return WC_HW_E when a PKCS#11 library call fails. + * 0 on success. + */ +static int Pkcs11FindRsaKey(CK_OBJECT_HANDLE* key, CK_OBJECT_CLASS keyClass, + Pkcs11Session* session, RsaKey* rsaKey) +{ + int ret = 0; + CK_RV rv; + CK_ULONG count; + CK_ATTRIBUTE keyTemplate[] = { + { CKA_CLASS, &keyClass, sizeof(keyClass) }, + { CKA_KEY_TYPE, &rsaKeyType, sizeof(rsaKeyType) }, + { CKA_MODULUS, NULL, 0 }, + }; + CK_ULONG keyTmplCnt = sizeof(keyTemplate) / sizeof(*keyTemplate); + + /* Set the modulus. */ + keyTemplate[2].pValue = rsaKey->n.raw.buf; + keyTemplate[2].ulValueLen = rsaKey->n.raw.len; + + rv = session->func->C_FindObjectsInit(session->handle, keyTemplate, + keyTmplCnt); + if (rv != CKR_OK) + ret = WC_HW_E; + if (ret == 0) { + rv = session->func->C_FindObjects(session->handle, key, 1, &count); + if (rv != CKR_OK) + ret = WC_HW_E; + rv = session->func->C_FindObjectsFinal(session->handle); + if (rv != CKR_OK) + ret = WC_HW_E; + } + + return ret; +} + +/** + * Exponentiate the input with the public part of the RSA key. + * Used in public encrypt and decrypt. + * + * @param session [in] Session object. + * @param info [in] Cryptographic operation data. + * @return WC_HW_E when a PKCS#11 library call fails. + * 0 on success. + */ +static int Pkcs11RsaPublic(Pkcs11Session* session, wc_CryptoInfo* info) +{ + int ret = 0; + CK_RV rv; + CK_MECHANISM mech; + CK_ULONG outLen; + CK_OBJECT_HANDLE publicKey = NULL_PTR; + int sessionKey = 0; + CK_ATTRIBUTE keyTemplate[] = { + { CKA_CLASS, &pubKeyClass, sizeof(pubKeyClass) }, + { CKA_KEY_TYPE, &rsaKeyType, sizeof(rsaKeyType) }, + { CKA_ENCRYPT, &ckTrue, sizeof(ckTrue) }, + { CKA_MODULUS, NULL, 0 }, + { CKA_PUBLIC_EXPONENT, NULL, 0 } + }; + CK_ULONG keyTmplCnt = sizeof(keyTemplate) / sizeof(*keyTemplate); + + WOLFSSL_MSG("PKCS#11: RSA Public Key Operation"); + + if (ret == 0 && info->pk.rsa.outLen == NULL) { + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + if ((sessionKey = !mp_iszero(&info->pk.rsa.key->e))) { + /* Set the modulus and public exponent data. */ + keyTemplate[3].pValue = info->pk.rsa.key->n.raw.buf; + keyTemplate[3].ulValueLen = info->pk.rsa.key->n.raw.len; + keyTemplate[4].pValue = info->pk.rsa.key->e.raw.buf; + keyTemplate[4].ulValueLen = info->pk.rsa.key->e.raw.len; + + /* Create an object containing public key data for device to use. */ + rv = session->func->C_CreateObject(session->handle, keyTemplate, + keyTmplCnt, &publicKey); + if (rv != CKR_OK) + ret = WC_HW_E; + } + else { + ret = Pkcs11FindKeyById(&publicKey, CKO_PUBLIC_KEY, CKK_RSA, + session, info->pk.rsa.key->id, + info->pk.rsa.key->idLen); + } + } + + if (ret == 0) { + /* Raw RSA encrypt/decrypt operation. */ + mech.mechanism = CKM_RSA_X_509; + mech.ulParameterLen = 0; + mech.pParameter = NULL; + + rv = session->func->C_EncryptInit(session->handle, &mech, publicKey); + if (rv != CKR_OK) + ret = WC_HW_E; + } + if (ret == 0) { + outLen = (CK_ULONG)*info->pk.rsa.outLen; + rv = session->func->C_Encrypt(session->handle, + (CK_BYTE_PTR)info->pk.rsa.in, info->pk.rsa.inLen, + info->pk.rsa.out, &outLen); + if (rv != CKR_OK) + ret = WC_HW_E; + } + if (ret == 0) + *info->pk.rsa.outLen = (word32)outLen; + + if (sessionKey) + session->func->C_DestroyObject(session->handle, publicKey); + + return ret; +} + +/** + * Exponentiate the input with the private part of the RSA key. + * Used in private encrypt and decrypt. + * + * @param session [in] Session object. + * @param info [in] Cryptographic operation data. + * @return WC_HW_E when a PKCS#11 library call fails. + * 0 on success. + */ +static int Pkcs11RsaPrivate(Pkcs11Session* session, wc_CryptoInfo* info) +{ + int ret = 0; + CK_RV rv; + CK_MECHANISM mech; + CK_ULONG outLen; + CK_OBJECT_HANDLE privateKey = NULL_PTR; + int sessionKey = 0; + + WOLFSSL_MSG("PKCS#11: RSA Private Key Operation"); + + if (ret == 0 && info->pk.rsa.outLen == NULL) { + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + if ((sessionKey = !mp_iszero(&info->pk.rsa.key->d))) { + ret = Pkcs11CreateRsaPrivateKey(&privateKey, session, + info->pk.rsa.key); + } + else if (info->pk.rsa.key->idLen > 0) { + ret = Pkcs11FindKeyById(&privateKey, CKO_PRIVATE_KEY, CKK_RSA, + session, info->pk.rsa.key->id, + info->pk.rsa.key->idLen); + } + else { + ret = Pkcs11FindRsaKey(&privateKey, CKO_PRIVATE_KEY, session, + info->pk.rsa.key); + } + } + + if (ret == 0) { + /* Raw RSA encrypt/decrypt operation. */ + mech.mechanism = CKM_RSA_X_509; + mech.ulParameterLen = 0; + mech.pParameter = NULL; + + rv = session->func->C_DecryptInit(session->handle, &mech, privateKey); + if (rv != CKR_OK) + ret = WC_HW_E; + } + if (ret == 0) { + outLen = (CK_ULONG)*info->pk.rsa.outLen; + rv = session->func->C_Decrypt(session->handle, + (CK_BYTE_PTR)info->pk.rsa.in, info->pk.rsa.inLen, + info->pk.rsa.out, &outLen); + if (rv != CKR_OK) + ret = WC_HW_E; + } + if (ret == 0) + *info->pk.rsa.outLen = (word32)outLen; + + if (sessionKey) + session->func->C_DestroyObject(session->handle, privateKey); + + return ret; +} + +/** + * Perform an RSA operation. + * + * @param session [in] Session object. + * @param info [in] Cryptographic operation data. + * @return WC_HW_E when a PKCS#11 library call fails. + * 0 on success. + */ +static int Pkcs11Rsa(Pkcs11Session* session, wc_CryptoInfo* info) +{ + int ret = 0; + CK_RV rv; + CK_MECHANISM_INFO mechInfo; + + /* Check operation is supported. */ + rv = session->func->C_GetMechanismInfo(session->slotId, CKM_RSA_X_509, + &mechInfo); + if (rv != CKR_OK) + ret = NOT_COMPILED_IN; + + if (ret == 0) { + if (info->pk.rsa.type == RSA_PUBLIC_ENCRYPT || + info->pk.rsa.type == RSA_PUBLIC_DECRYPT) { + if ((mechInfo.flags & CKF_ENCRYPT) == 0) + ret = NOT_COMPILED_IN; + else + ret = Pkcs11RsaPublic(session, info); + } + else if (info->pk.rsa.type == RSA_PRIVATE_ENCRYPT || + info->pk.rsa.type == RSA_PRIVATE_DECRYPT) { + if ((mechInfo.flags & CKF_DECRYPT) == 0) + ret = NOT_COMPILED_IN; + else + ret = Pkcs11RsaPrivate(session, info); + } + else + ret = NOT_COMPILED_IN; + } + + return ret; +} + +#ifdef WOLFSSL_KEY_GEN +/** + * Get the RSA public key data from the PKCS#11 object. + * + * @param key [in] RSA key to put the data into. + * @param session [in] Session object. + * @param pubkey [in] Public key object. + * @return WC_HW_E when a PKCS#11 library call fails. + * MEMORY_E when a memory allocation fails. + * 0 on success. + */ +static int Pkcs11GetRsaPublicKey(RsaKey* key, Pkcs11Session* session, + CK_OBJECT_HANDLE pubKey) +{ + int ret = 0; + unsigned char* mod = NULL; + unsigned char* exp = NULL; + int modSz, expSz; + CK_ATTRIBUTE tmpl[] = { + { CKA_MODULUS, NULL_PTR, 0 }, + { CKA_PUBLIC_EXPONENT, NULL_PTR, 0 } + }; + CK_ULONG tmplCnt = sizeof(tmpl) / sizeof(*tmpl); + CK_RV rv; + + rv = session->func->C_GetAttributeValue(session->handle, pubKey, tmpl, + tmplCnt); + if (rv != CKR_OK) + ret = WC_HW_E; + + if (ret == 0) { + modSz = tmpl[0].ulValueLen; + expSz = tmpl[1].ulValueLen; + mod = (unsigned char*)XMALLOC(modSz, key->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (mod == NULL) + ret = MEMORY_E; + } + if (ret == 0) { + exp = (unsigned char*)XMALLOC(expSz, key->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (exp == NULL) + ret = MEMORY_E; + } + if (ret == 0) { + tmpl[0].pValue = mod; + tmpl[1].pValue = exp; + + rv = session->func->C_GetAttributeValue(session->handle, pubKey, + tmpl, tmplCnt); + if (rv != CKR_OK) + ret = WC_HW_E; + } + if (ret == 0) + ret = wc_RsaPublicKeyDecodeRaw(mod, modSz, exp, expSz, key); + + if (exp != NULL) + XFREE(exp, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + if (mod != NULL) + XFREE(mod, key->heap, DYNAMIC_TYPE_TMP_BUFFER); + + return ret; +} + +/** + * Perform an RSA key generation operation. + * The private key data stays on the device. + * + * @param session [in] Session object. + * @param info [in] Cryptographic operation data. + * @return WC_HW_E when a PKCS#11 library call fails. + * 0 on success. + */ +static int Pkcs11RsaKeyGen(Pkcs11Session* session, wc_CryptoInfo* info) +{ + int ret = 0; + RsaKey* key = info->pk.rsakg.key; + CK_RV rv; + CK_ULONG bits = info->pk.rsakg.size; + CK_OBJECT_HANDLE pubKey = NULL_PTR, privKey = NULL_PTR; + CK_MECHANISM mech; + static CK_BYTE pub_exp[] = { 0x01, 0x00, 0x01, 0x00 }; + CK_ATTRIBUTE pubKeyTmpl[] = { + { CKA_MODULUS_BITS, &bits, sizeof(bits) }, + { CKA_ENCRYPT, &ckTrue, sizeof(ckTrue) }, + { CKA_VERIFY, &ckTrue, sizeof(ckTrue) }, + { CKA_PUBLIC_EXPONENT, &pub_exp, sizeof(pub_exp) } + }; + CK_ULONG pubTmplCnt = sizeof(pubKeyTmpl)/sizeof(*pubKeyTmpl); + CK_ATTRIBUTE privKeyTmpl[] = { + {CKA_DECRYPT, &ckTrue, sizeof(ckTrue) }, + {CKA_SIGN, &ckTrue, sizeof(ckTrue) }, + {CKA_ID, NULL, 0 } + }; + int privTmplCnt = 2; + int i; + + ret = Pkcs11MechAvail(session, CKM_RSA_PKCS_KEY_PAIR_GEN); + if (ret == 0) { + WOLFSSL_MSG("PKCS#11: RSA Key Generation Operation"); + + /* Most commonly used public exponent value (array initialized). */ + if (info->pk.rsakg.e != WC_RSA_EXPONENT) { + for (i = 0; i < (int)sizeof(pub_exp); i++) + pub_exp[i] = (info->pk.rsakg.e >> (8 * i)) & 0xff; + } + for (i = (int)sizeof(pub_exp) - 1; pub_exp[i] == 0; i--) { + } + pubKeyTmpl[3].ulValueLen = i + 1; + + if (key->idLen != 0) { + privKeyTmpl[privTmplCnt].pValue = key->id; + privKeyTmpl[privTmplCnt].ulValueLen = key->idLen; + privTmplCnt++; + } + + mech.mechanism = CKM_RSA_PKCS_KEY_PAIR_GEN; + mech.ulParameterLen = 0; + mech.pParameter = NULL; + + rv = session->func->C_GenerateKeyPair(session->handle, &mech, + pubKeyTmpl, pubTmplCnt, + privKeyTmpl, privTmplCnt, + &pubKey, &privKey); + if (rv != CKR_OK) + ret = -1; + } + + if (ret == 0) + ret = Pkcs11GetRsaPublicKey(key, session, pubKey); + + if (pubKey != NULL_PTR) + ret = session->func->C_DestroyObject(session->handle, pubKey); + if (ret != 0 && privKey != NULL_PTR) + ret = session->func->C_DestroyObject(session->handle, privKey); + + return ret; +} +#endif /* WOLFSSL_KEY_GEN */ +#endif /* !NO_RSA */ + +#ifdef HAVE_ECC +/** + * Find the PKCS#11 object containing the ECC public or private key data with + * the modulus specified. + * + * @param key [out] Henadle to key object. + * @param keyClass [in] Public or private key class. + * @param session [in] Session object. + * @param eccKey [in] ECC key with parameters. + * @return WC_HW_E when a PKCS#11 library call fails. + * MEMORY_E when a memory allocation fails. + * 0 on success. + */ +static int Pkcs11FindEccKey(CK_OBJECT_HANDLE* key, CK_OBJECT_CLASS keyClass, + Pkcs11Session* session, ecc_key* eccKey) +{ + int ret = 0; + int i; + unsigned char* ecPoint = NULL; + word32 len; + CK_RV rv; + CK_ULONG count; + CK_UTF8CHAR params[MAX_EC_PARAM_LEN]; + CK_ATTRIBUTE keyTemplate[] = { + { CKA_CLASS, &keyClass, sizeof(keyClass) }, + { CKA_KEY_TYPE, &ecKeyType, sizeof(ecKeyType) }, + { CKA_EC_PARAMS, params, 0 }, + { CKA_EC_POINT, NULL, 0 }, + }; + CK_ULONG attrCnt = 3; + + ret = Pkcs11EccSetParams(eccKey, keyTemplate, 2); + if (ret == 0 && keyClass == CKO_PUBLIC_KEY) { + /* ASN1 encoded: OCT + uncompressed point */ + len = 3 + 1 + 2 * eccKey->dp->size; + ecPoint = (unsigned char*)XMALLOC(len, eccKey->heap, DYNAMIC_TYPE_ECC); + if (ecPoint == NULL) + ret = MEMORY_E; + } + if (ret == 0 && keyClass == CKO_PUBLIC_KEY) { + len -= 3; + i = 0; + ecPoint[i++] = ASN_OCTET_STRING; + if (len >= ASN_LONG_LENGTH) + ecPoint[i++] = (ASN_LONG_LENGTH | 1); + ecPoint[i++] = len; + ret = wc_ecc_export_x963(eccKey, ecPoint + i, &len); + } + if (ret == 0 && keyClass == CKO_PUBLIC_KEY) { + keyTemplate[3].pValue = ecPoint; + keyTemplate[3].ulValueLen = len + i; + attrCnt++; + } + if (ret == 0) { + rv = session->func->C_FindObjectsInit(session->handle, keyTemplate, + attrCnt); + if (rv != CKR_OK) + ret = WC_HW_E; + } + if (ret == 0) { + rv = session->func->C_FindObjects(session->handle, key, 1, &count); + if (rv != CKR_OK) + ret = WC_HW_E; + rv = session->func->C_FindObjectsFinal(session->handle); + if (rv != CKR_OK) + ret = WC_HW_E; + } + + if (ecPoint != NULL) + XFREE(ecPoint, eccKey->heap, DYNAMIC_TYPE_ECC); + + return ret; +} + +/** + * Create a PKCS#11 object containing the ECC public key data. + * Encode the public key as an OCTET_STRING of the encoded point. + * + * @param publicKey [out] Henadle to public key object. + * @param session [in] Session object. + * @param public_key [in] ECC public key. + * @param operation [in] Cryptographic operation key is to be used for. + * @return WC_HW_E when a PKCS#11 library call fails. + * MEMORY_E when a memory allocation fails. + * 0 on success. + */ +static int Pkcs11CreateEccPublicKey(CK_OBJECT_HANDLE* publicKey, + Pkcs11Session* session, + ecc_key* public_key, + CK_ATTRIBUTE_TYPE operation) +{ + int ret = 0; + int i; + unsigned char* ecPoint = NULL; + word32 len; + CK_RV rv; + CK_UTF8CHAR params[MAX_EC_PARAM_LEN]; + CK_ATTRIBUTE keyTemplate[] = { + { CKA_CLASS, &pubKeyClass, sizeof(pubKeyClass) }, + { CKA_KEY_TYPE, &ecKeyType, sizeof(ecKeyType) }, + { operation, &ckTrue, sizeof(ckTrue) }, + { CKA_EC_PARAMS, params, 0 }, + { CKA_EC_POINT, NULL, 0 } + }; + CK_ULONG keyTmplCnt = sizeof(keyTemplate) / sizeof(*keyTemplate); + + ret = Pkcs11EccSetParams(public_key, keyTemplate, 3); + if (ret == 0) { + /* ASN1 encoded: OCT + uncompressed point */ + len = 3 + 1 + 2 * public_key->dp->size; + ecPoint = (unsigned char*)XMALLOC(len, public_key->heap, + DYNAMIC_TYPE_ECC); + if (ecPoint == NULL) + ret = MEMORY_E; + } + if (ret == 0) { + len -= 3; + i = 0; + ecPoint[i++] = ASN_OCTET_STRING; + if (len >= ASN_LONG_LENGTH) + ecPoint[i++] = ASN_LONG_LENGTH | 1; + ecPoint[i++] = len; + ret = wc_ecc_export_x963(public_key, ecPoint + i, &len); + } + if (ret == 0) { + keyTemplate[4].pValue = ecPoint; + keyTemplate[4].ulValueLen = len + i; + + rv = session->func->C_CreateObject(session->handle, keyTemplate, + keyTmplCnt, publicKey); + if (rv != CKR_OK) + ret = WC_HW_E; + } + + if (ecPoint != NULL) + XFREE(ecPoint, public_key->heap, DYNAMIC_TYPE_ECC); + + return ret; +} + +#ifndef NO_PKCS11_EC_KEYGEN +/** + * Gets the public key data from the PKCS#11 object and puts into the ECC key. + * + * @param key [in] ECC public key. + * @param session [in] Session object. + * @param pubKey [in] ECC public key PKCS#11 object. + * @return WC_HW_E when a PKCS#11 library call fails. + * MEMORY_E when a memory allocation fails. + * 0 on success. + */ +static int Pkcs11GetEccPublicKey(ecc_key* key, Pkcs11Session* session, + CK_OBJECT_HANDLE pubKey) +{ + int ret = 0; + int i = 0; + int curveIdx; + unsigned char* point = NULL; + int pointSz; + CK_RV rv; + CK_ATTRIBUTE tmpl[] = { + { CKA_EC_POINT, NULL_PTR, 0 }, + }; + CK_ULONG tmplCnt = sizeof(tmpl) / sizeof(*tmpl); + + rv = session->func->C_GetAttributeValue(session->handle, pubKey, tmpl, + tmplCnt); + if (rv != CKR_OK) + ret = WC_HW_E; + + if (ret == 0) { + pointSz = (int)tmpl[0].ulValueLen; + point = (unsigned char*)XMALLOC(pointSz, key->heap, DYNAMIC_TYPE_ECC); + if (point == NULL) + ret = MEMORY_E; + } + if (ret == 0) { + tmpl[0].pValue = point; + + rv = session->func->C_GetAttributeValue(session->handle, pubKey, + tmpl, tmplCnt); + if (rv != CKR_OK) + ret = WC_HW_E; + } + + /* Make sure the data is big enough for ASN.1: OCT + uncompressed point */ + if (ret == 0 && pointSz < key->dp->size * 2 + 1 + 2) + ret = ASN_PARSE_E; + /* Step over the OCTET_STRING wrapper. */ + if (ret == 0 && point[i++] != ASN_OCTET_STRING) + ret = ASN_PARSE_E; + if (ret == 0 && point[i] >= ASN_LONG_LENGTH) { + if (point[i++] != (ASN_LONG_LENGTH | 1)) + ret = ASN_PARSE_E; + else if (pointSz < key->dp->size * 2 + 1 + 3) + ret = ASN_PARSE_E; + } + if (ret == 0 && point[i++] != key->dp->size * 2 + 1) + ret = ASN_PARSE_E; + + if (ret == 0) { + curveIdx = wc_ecc_get_curve_idx(key->dp->id); + ret = wc_ecc_import_point_der(point + i, pointSz - i, curveIdx, + &key->pubkey); + } + + if (point != NULL) + XFREE(point, key->heap, DYNAMIC_TYPE_ECC); + + return ret; +} + +/** + * Perform an ECC key generation operation. + * The private key data stays on the device. + * + * @param session [in] Session object. + * @param info [in] Cryptographic operation data. + * @return WC_HW_E when a PKCS#11 library call fails. + * 0 on success. + */ +static int Pkcs11EcKeyGen(Pkcs11Session* session, wc_CryptoInfo* info) +{ + int ret = 0; + ecc_key* key = info->pk.eckg.key; + CK_RV rv; + CK_OBJECT_HANDLE pubKey = NULL_PTR, privKey = NULL_PTR; + CK_MECHANISM mech; + CK_UTF8CHAR params[MAX_EC_PARAM_LEN]; + CK_ATTRIBUTE pubKeyTmpl[] = { + { CKA_EC_PARAMS, params, 0 }, + { CKA_ENCRYPT, &ckTrue, sizeof(ckTrue) }, + { CKA_VERIFY, &ckTrue, sizeof(ckTrue) }, + }; + int pubTmplCnt = sizeof(pubKeyTmpl)/sizeof(*pubKeyTmpl); + CK_ATTRIBUTE privKeyTmpl[] = { + { CKA_DECRYPT, &ckTrue, sizeof(ckTrue) }, + { CKA_SIGN, &ckTrue, sizeof(ckTrue) }, + { CKA_DERIVE, &ckTrue, sizeof(ckTrue) }, + { CKA_ID, NULL, 0 }, + }; + int privTmplCnt = 3; + + ret = Pkcs11MechAvail(session, CKM_EC_KEY_PAIR_GEN); + if (ret == 0) { + WOLFSSL_MSG("PKCS#11: EC Key Generation Operation"); + + ret = Pkcs11EccSetParams(key, pubKeyTmpl, 0); + } + if (ret == 0) { + if (key->idLen != 0) { + privKeyTmpl[privTmplCnt].pValue = key->id; + privKeyTmpl[privTmplCnt].ulValueLen = key->idLen; + privTmplCnt++; + } + + mech.mechanism = CKM_EC_KEY_PAIR_GEN; + mech.ulParameterLen = 0; + mech.pParameter = NULL; + + rv = session->func->C_GenerateKeyPair(session->handle, &mech, + pubKeyTmpl, pubTmplCnt, + privKeyTmpl, privTmplCnt, + &pubKey, &privKey); + if (rv != CKR_OK) + ret = -1; + } + + if (ret == 0) + ret = Pkcs11GetEccPublicKey(key, session, pubKey); + + if (pubKey != NULL_PTR) + session->func->C_DestroyObject(session->handle, pubKey); + if (ret != 0 && privKey != NULL_PTR) + session->func->C_DestroyObject(session->handle, privKey); + + return ret; +} +#endif + +#ifndef NO_PKCS11_ECDH +/** + * Extracts the secret key data from the PKCS#11 object. + * + * @param session [in] Session object. + * @param secret [in] PKCS#11 object with the secret key data. + * @param out [in] Buffer to hold secret data. + * @param outLen [in,out] On in, length of buffer. + * On out, the length of data in buffer. + * @return WC_HW_E when a PKCS#11 library call fails. + * 0 on success. + */ +static int Pkcs11ExtractSecret(Pkcs11Session* session, CK_OBJECT_HANDLE secret, + byte* out, word32* outLen) +{ + int ret = 0; + CK_ATTRIBUTE tmpl[] = { + {CKA_VALUE, NULL_PTR, 0} + }; + CK_ULONG tmplCnt = sizeof(tmpl) / sizeof(*tmpl); + CK_RV rv; + + rv = session->func->C_GetAttributeValue(session->handle, secret, tmpl, + tmplCnt); + if (rv != CKR_OK) + ret = WC_HW_E; + if (ret == 0) { + if (tmpl[0].ulValueLen > *outLen) + ret = BUFFER_E; + } + if (ret == 0) { + tmpl[0].pValue = out; + rv = session->func->C_GetAttributeValue(session->handle, secret, + tmpl, tmplCnt); + if (rv != CKR_OK) + ret = WC_HW_E; + *outLen = (word32)tmpl[0].ulValueLen; + } + + return ret; +} + +/** + * Performs the ECDH secret generation operation. + * + * @param session [in] Session object. + * @param info [in] Cryptographic operation data. + * @return WC_HW_E when a PKCS#11 library call fails. + * 0 on success. + */ +static int Pkcs11ECDH(Pkcs11Session* session, wc_CryptoInfo* info) +{ + int ret = 0; + int sessionKey = 0; + unsigned char* point = NULL; + word32 pointLen; + CK_RV rv; + CK_KEY_TYPE keyType = CKK_GENERIC_SECRET; + CK_MECHANISM mech; + CK_ECDH1_DERIVE_PARAMS params; + CK_OBJECT_HANDLE privateKey = NULL_PTR; + CK_OBJECT_HANDLE secret = CK_INVALID_HANDLE; + CK_ULONG secSz; + CK_ATTRIBUTE tmpl[] = { + { CKA_CLASS, &secretKeyClass, sizeof(secretKeyClass) }, + { CKA_KEY_TYPE, &keyType, sizeof(keyType) }, + { CKA_PRIVATE, &ckFalse, sizeof(ckFalse) }, + { CKA_SENSITIVE, &ckFalse, sizeof(ckFalse) }, + { CKA_EXTRACTABLE, &ckTrue, sizeof(ckTrue) }, + { CKA_VALUE_LEN, &secSz, sizeof(secSz) } + }; + CK_ULONG tmplCnt = sizeof(tmpl) / sizeof(*tmpl); + + ret = Pkcs11MechAvail(session, CKM_ECDH1_DERIVE); + if (ret == 0 && info->pk.ecdh.outlen == NULL) { + ret = BAD_FUNC_ARG; + } + if (ret == 0) { + WOLFSSL_MSG("PKCS#11: EC Key Derivation Operation"); + + + if ((sessionKey = !mp_iszero(&info->pk.ecdh.private_key->k))) + ret = Pkcs11CreateEccPrivateKey(&privateKey, session, + info->pk.ecdh.private_key, CKA_DERIVE); + else if (info->pk.ecdh.private_key->idLen > 0) { + ret = Pkcs11FindKeyById(&privateKey, CKO_PRIVATE_KEY, CKK_EC, + session, info->pk.ecdh.private_key->id, + info->pk.ecdh.private_key->idLen); + } + else { + ret = Pkcs11FindEccKey(&privateKey, CKO_PRIVATE_KEY, session, + info->pk.ecdh.public_key); + } + } + if (ret == 0) { + ret = wc_ecc_export_x963(info->pk.ecdh.public_key, NULL, &pointLen); + if (ret == LENGTH_ONLY_E) { + point = (unsigned char*)XMALLOC(pointLen, + info->pk.ecdh.public_key->heap, + DYNAMIC_TYPE_ECC_BUFFER); + ret = wc_ecc_export_x963(info->pk.ecdh.public_key, point, + &pointLen); + } + } + + if (ret == 0) { + secSz = *info->pk.ecdh.outlen; + if (secSz > (CK_ULONG)info->pk.ecdh.private_key->dp->size) + secSz = info->pk.ecdh.private_key->dp->size; + + params.kdf = CKD_NULL; + params.pSharedData = NULL; + params.ulSharedDataLen = 0; + params.pPublicData = point; + params.ulPublicDataLen = pointLen; + + mech.mechanism = CKM_ECDH1_DERIVE; + mech.ulParameterLen = sizeof(params); + mech.pParameter = ¶ms; + + rv = session->func->C_DeriveKey(session->handle, &mech, privateKey, + tmpl, tmplCnt, &secret); + if (rv != CKR_OK) + ret = WC_HW_E; + } + + if (ret == 0) { + ret = Pkcs11ExtractSecret(session, secret, info->pk.ecdh.out, + info->pk.ecdh.outlen); + } + + if (sessionKey) + session->func->C_DestroyObject(session->handle, privateKey); + + if (point != NULL) + XFREE(point, info->pk.ecdh.public_key->heap, DYNAMIC_TYPE_ECC_BUFFER); + + return ret; +} +#endif + +/** + * Encode, in place, the ECDSA signature. + * Two fixed width values into ASN.1 DER encoded SEQ { INT, INT } + * + * @param sig [in,out] Signature data. + * @param sz [in] Size of original signature data. + * @return Length of the ASN.1 DER enencoded signature. + */ +static word32 Pkcs11ECDSASig_Encode(byte* sig, word32 sz) +{ + word32 rHigh, sHigh, seqLen; + word32 rStart = 0, sStart = 0; + word32 sigSz, rSz, rLen, sSz, sLen; + word32 i; + + /* Find first byte of data in r and s. */ + while (rStart < sz - 1 && sig[rStart] == 0x00) + rStart++; + while (sig[sz + sStart] == 0x00 && sStart < sz - 1) + sStart++; + /* Check if 0 needs to be prepended to make integer a positive number. */ + rHigh = sig[rStart] >> 7; + sHigh = sig[sz + sStart] >> 7; + /* Calculate length of integer to put into ASN.1 encoding. */ + rLen = sz - rStart; + sLen = sz - sStart; + /* r and s: INT (2 bytes) + [ 0x00 ] + integer */ + rSz = 2 + rHigh + rLen; + sSz = 2 + sHigh + sLen; + /* Calculate the complete ASN.1 DER encoded size. */ + sigSz = rSz + sSz; + if (sigSz >= ASN_LONG_LENGTH) + seqLen = 3; + else + seqLen = 2; + + /* Move s and then r integers into their final places. */ + XMEMMOVE(sig + seqLen + rSz + (sSz - sLen), sig + sz + sStart, sLen); + XMEMMOVE(sig + seqLen + (rSz - rLen), sig + rStart, rLen); + + /* Put the ASN.1 DER encoding around data. */ + i = 0; + sig[i++] = ASN_CONSTRUCTED | ASN_SEQUENCE; + if (seqLen == 3) + sig[i++] = ASN_LONG_LENGTH | 0x01; + sig[i++] = sigSz; + sig[i++] = ASN_INTEGER; + sig[i++] = rHigh + (sz - rStart); + if (rHigh) + sig[i++] = 0x00; + i += sz - rStart; + sig[i++] = ASN_INTEGER; + sig[i++] = sHigh + (sz - sStart); + if (sHigh) + sig[i] = 0x00; + + return seqLen + sigSz; +} + +/** + * Decode the ECDSA signature. + * ASN.1 DER encode SEQ { INT, INT } converted to two fixed with values. + * + * @param in [in] ASN.1 DER encoded signature. + * @param inSz [in] Size of ASN.1 signature. + * @param sig [in] Output buffer. + * @param sz [in] Size of output buffer. + * @return ASN_PARSE_E when the ASN.1 encoding is invalid. + * 0 on success. + */ +static int Pkcs11ECDSASig_Decode(const byte* in, word32 inSz, byte* sig, + word32 sz) +{ + int ret = 0; + word32 i = 0; + int len, seqLen = 2; + + /* Make sure zeros in place when decoding short integers. */ + XMEMSET(sig, 0, sz * 2); + + /* Check min data for: SEQ + INT. */ + if (inSz < 5) + ret = ASN_PARSE_E; + /* Check SEQ */ + if (ret == 0 && in[i++] != (ASN_CONSTRUCTED | ASN_SEQUENCE)) + ret = ASN_PARSE_E; + if (ret == 0 && in[i] >= ASN_LONG_LENGTH) { + if (in[i] != (ASN_LONG_LENGTH | 0x01)) + ret = ASN_PARSE_E; + else { + i++; + seqLen++; + } + } + if (ret == 0 && in[i++] != inSz - seqLen) + ret = ASN_PARSE_E; + + /* Check INT */ + if (ret == 0 && in[i++] != ASN_INTEGER) + ret = ASN_PARSE_E; + if (ret == 0 && (len = in[i++]) > sz + 1) + ret = ASN_PARSE_E; + /* Check there is space for INT data */ + if (ret == 0 && i + len > inSz) + ret = ASN_PARSE_E; + if (ret == 0) { + /* Skip leading zero */ + if (in[i] == 0x00) { + i++; + len--; + } + /* Copy r into sig. */ + XMEMCPY(sig + sz - len, in + i, len); + i += len; + } + + /* Check min data for: INT. */ + if (ret == 0 && i + 2 > inSz) + ret = ASN_PARSE_E; + /* Check INT */ + if (ret == 0 && in[i++] != ASN_INTEGER) + ret = ASN_PARSE_E; + if (ret == 0 && (len = in[i++]) > sz + 1) + ret = ASN_PARSE_E; + /* Check there is space for INT data */ + if (ret == 0 && i + len > inSz) + ret = ASN_PARSE_E; + if (ret == 0) { + /* Skip leading zero */ + if (in[i] == 0x00) { + i++; + len--; + } + /* Copy s into sig. */ + XMEMCPY(sig + sz + sz - len, in + i, len); + } + + return ret; +} + +/** + * Get the parameters from the private key on the device. + * + * @param session [in] Session object. + * @param privKey [in] PKCS #11 object handle of private key.. + * @param key [in] Ecc key to set parameters against. + * @return WC_HW_E when a PKCS#11 library call fails. + * 0 on success. + */ +static int Pkcs11GetEccParams(Pkcs11Session* session, CK_OBJECT_HANDLE privKey, + ecc_key* key) +{ + int ret = 0; + int curveId; + CK_RV rv; + byte oid[16]; + CK_ATTRIBUTE template[] = { + { CKA_EC_PARAMS, (CK_VOID_PTR)oid, sizeof(oid) } + }; + + rv = session->func->C_GetAttributeValue(session->handle, privKey, template, + 1); + if (rv != CKR_OK) + ret = WC_HW_E; + if (ret == 0) { + /* PKCS #11 wraps the OID in ASN.1 */ + curveId = wc_ecc_get_curve_id_from_oid(oid + 2, + (word32)template[0].ulValueLen - 2); + if (curveId == ECC_CURVE_INVALID) + ret = WC_HW_E; + } + if (ret == 0) + ret = wc_ecc_set_curve(key, 0, curveId); + + return ret; +} + +/** + * Performs the ECDSA signing operation. + * + * @param session [in] Session object. + * @param info [in] Cryptographic operation data. + * @return WC_HW_E when a PKCS#11 library call fails. + * 0 on success. + */ +static int Pkcs11ECDSA_Sign(Pkcs11Session* session, wc_CryptoInfo* info) +{ + int ret = 0; + int sessionKey = 0; + word32 sz; + CK_RV rv; + CK_ULONG outLen; + CK_MECHANISM mech; + CK_MECHANISM_INFO mechInfo; + CK_OBJECT_HANDLE privateKey = NULL_PTR; + + /* Check operation is supported. */ + rv = session->func->C_GetMechanismInfo(session->slotId, CKM_ECDSA, + &mechInfo); + if (rv != CKR_OK || (mechInfo.flags & CKF_SIGN) == 0) + ret = NOT_COMPILED_IN; + + if (ret == 0 && info->pk.eccsign.outlen == NULL) { + ret = BAD_FUNC_ARG; + } + if (ret == 0) { + WOLFSSL_MSG("PKCS#11: EC Signing Operation"); + + if ((sessionKey = !mp_iszero(&info->pk.eccsign.key->k))) + ret = Pkcs11CreateEccPrivateKey(&privateKey, session, + info->pk.eccsign.key, CKA_SIGN); + else if (info->pk.eccsign.key->idLen > 0) { + ret = Pkcs11FindKeyById(&privateKey, CKO_PRIVATE_KEY, CKK_EC, + session, info->pk.eccsign.key->id, + info->pk.eccsign.key->idLen); + if (ret == 0 && info->pk.eccsign.key->dp == NULL) { + ret = Pkcs11GetEccParams(session, privateKey, + info->pk.eccsign.key); + } + } + else { + ret = Pkcs11FindEccKey(&privateKey, CKO_PRIVATE_KEY, session, + info->pk.eccsign.key); + } + } + + if (ret == 0) { + sz = info->pk.eccsign.key->dp->size; + /* Maximum encoded size is two ordinates + 8 bytes of ASN.1. */ + if (*info->pk.eccsign.outlen < (word32)wc_ecc_sig_size_calc(sz)) + ret = BUFFER_E; + } + + if (ret == 0) { + mech.mechanism = CKM_ECDSA; + mech.ulParameterLen = 0; + mech.pParameter = NULL; + + rv = session->func->C_SignInit(session->handle, &mech, privateKey); + if (rv != CKR_OK) + ret = WC_HW_E; + } + + if (ret == 0) { + outLen = *info->pk.eccsign.outlen; + rv = session->func->C_Sign(session->handle, + (CK_BYTE_PTR)info->pk.eccsign.in, + info->pk.eccsign.inlen, info->pk.eccsign.out, + &outLen); + if (rv != CKR_OK) + ret = WC_HW_E; + } + + if (ret == 0) { + *info->pk.eccsign.outlen = Pkcs11ECDSASig_Encode(info->pk.eccsign.out, + sz); + } + + if (sessionKey) + session->func->C_DestroyObject(session->handle, privateKey); + + return ret; +} + +/** + * Performs the ECDSA verification operation. + * + * @param session [in] Session object. + * @param info [in] Cryptographic operation data. + * @return WC_HW_E when a PKCS#11 library call fails. + * MEMORY_E when a memory allocation fails. + * 0 on success. + */ +static int Pkcs11ECDSA_Verify(Pkcs11Session* session, wc_CryptoInfo* info) +{ + int ret = 0; + CK_RV rv; + CK_MECHANISM mech; + CK_MECHANISM_INFO mechInfo; + CK_OBJECT_HANDLE publicKey = NULL_PTR; + unsigned char* sig = NULL; + word32 sz = info->pk.eccverify.key->dp->size; + + /* Check operation is supported. */ + rv = session->func->C_GetMechanismInfo(session->slotId, CKM_ECDSA, + &mechInfo); + if (rv != CKR_OK || (mechInfo.flags & CKF_VERIFY) == 0) + ret = NOT_COMPILED_IN; + + if (ret == 0 && info->pk.eccverify.res == NULL) { + ret = BAD_FUNC_ARG; + } + + if (ret == 0) { + WOLFSSL_MSG("PKCS#11: EC Verification Operation"); + + ret = Pkcs11CreateEccPublicKey(&publicKey, session, + info->pk.eccverify.key, CKA_VERIFY); + } + + if (ret == 0) { + sig = XMALLOC(sz * 2, info->pk.eccverify.key->heap, + DYNAMIC_TYPE_TMP_BUFFER); + if (sig == NULL) + ret = MEMORY_E; + } + + if (ret == 0) { + ret = Pkcs11ECDSASig_Decode(info->pk.eccverify.sig, + info->pk.eccverify.siglen, sig, sz); + } + if (ret == 0) { + mech.mechanism = CKM_ECDSA; + mech.ulParameterLen = 0; + mech.pParameter = NULL; + + rv = session->func->C_VerifyInit(session->handle, &mech, publicKey); + if (rv != CKR_OK) + ret = WC_HW_E; + } + + if (ret == 0) { + *info->pk.eccverify.res = 0; + rv = session->func->C_Verify(session->handle, + (CK_BYTE_PTR)info->pk.eccverify.hash, + info->pk.eccverify.hashlen, + (CK_BYTE_PTR)sig, sz * 2); + if (rv == CKR_SIGNATURE_INVALID) { + } + else if (rv != CKR_OK) + ret = WC_HW_E; + else + *info->pk.eccverify.res = 1; + } + + if (publicKey != NULL_PTR) + session->func->C_DestroyObject(session->handle, publicKey); + + if (sig != NULL) + XFREE(sig, info->pk.eccverify.key->heap, DYNAMIC_TYPE_TMP_BUFFER); + + return ret; +} +#endif + +#if !defined(NO_AES) && defined(HAVE_AESGCM) +/** + * Performs the AES-GCM encryption operation. + * + * @param session [in] Session object. + * @param info [in] Cryptographic operation data. + * @return WC_HW_E when a PKCS#11 library call fails. + * MEMORY_E when a memory allocation fails. + * 0 on success. + */ +static int Pkcs11AesGcmEncrypt(Pkcs11Session* session, wc_CryptoInfo* info) +{ + int ret = 0; + CK_RV rv; + Aes* aes = info->cipher.aesgcm_enc.aes; + CK_GCM_PARAMS params; + CK_MECHANISM_INFO mechInfo; + CK_OBJECT_HANDLE key = NULL_PTR; + CK_MECHANISM mech; + CK_ULONG outLen; + + /* Check operation is supported. */ + rv = session->func->C_GetMechanismInfo(session->slotId, CKM_AES_GCM, + &mechInfo); + if (rv != CKR_OK || (mechInfo.flags & CKF_ENCRYPT) == 0) + ret = NOT_COMPILED_IN; + + if (ret == 0) { + WOLFSSL_MSG("PKCS#11: AES-GCM Encryption Operation"); + } + + /* Create a private key object or find by id. */ + if (ret == 0 && aes->idLen == 0) { + ret = Pkcs11CreateSecretKey(&key, session, CKK_AES, + (unsigned char*)aes->devKey, aes->keylen, + NULL, 0); + + } + else if (ret == 0) { + ret = Pkcs11FindKeyById(&key, CKO_SECRET_KEY, CKK_AES, session, aes->id, + aes->idLen); + } + + if (ret == 0) { + params.pIv = (CK_BYTE_PTR)info->cipher.aesgcm_enc.iv; + params.ulIvLen = info->cipher.aesgcm_enc.ivSz; + params.pAAD = (CK_BYTE_PTR)info->cipher.aesgcm_enc.authIn; + params.ulAADLen = info->cipher.aesgcm_enc.authInSz; + params.ulTagBits = info->cipher.aesgcm_enc.authTagSz * 8; + + mech.mechanism = CKM_AES_GCM; + mech.ulParameterLen = sizeof(params); + mech.pParameter = ¶ms; + + rv = session->func->C_EncryptInit(session->handle, &mech, key); + if (rv != CKR_OK) + ret = WC_HW_E; + } + if (ret == 0) { + outLen = info->cipher.aesgcm_enc.sz; + rv = session->func->C_EncryptUpdate(session->handle, + (CK_BYTE_PTR)info->cipher.aesgcm_enc.in, + info->cipher.aesgcm_enc.sz, + info->cipher.aesgcm_enc.out, + &outLen); + if (rv != CKR_OK) + ret = WC_HW_E; + } + if (ret == 0) { + /* Authentication tag comes out in final block. */ + outLen = info->cipher.aesgcm_enc.authTagSz; + rv = session->func->C_EncryptFinal(session->handle, + info->cipher.aesgcm_enc.authTag, + &outLen); + if (rv != CKR_OK) + ret = WC_HW_E; + } + + if (aes->idLen == 0 && key != NULL_PTR) + session->func->C_DestroyObject(session->handle, key); + + return ret; +} + +/** + * Performs the AES-GCM decryption operation. + * + * @param session [in] Session object. + * @param info [in] Cryptographic operation data. + * @return WC_HW_E when a PKCS#11 library call fails. + * MEMORY_E when a memory allocation fails. + * 0 on success. + */ +static int Pkcs11AesGcmDecrypt(Pkcs11Session* session, wc_CryptoInfo* info) +{ + int ret = 0; + CK_RV rv; + Aes* aes = info->cipher.aesgcm_enc.aes; + CK_GCM_PARAMS params; + CK_MECHANISM_INFO mechInfo; + CK_OBJECT_HANDLE key = NULL_PTR; + CK_MECHANISM mech; + CK_ULONG outLen; + word32 len; + + /* Check operation is supported. */ + rv = session->func->C_GetMechanismInfo(session->slotId, CKM_AES_GCM, + &mechInfo); + if (rv != CKR_OK || (mechInfo.flags & CKF_DECRYPT) == 0) + ret = NOT_COMPILED_IN; + + if (ret == 0) { + WOLFSSL_MSG("PKCS#11: AES-GCM Decryption Operation"); + } + + /* Create a private key object or find by id. */ + if (ret == 0 && aes->idLen == 0) { + ret = Pkcs11CreateSecretKey(&key, session, CKK_AES, + (unsigned char*)aes->devKey, aes->keylen, + NULL, 0); + } + else if (ret == 0) { + ret = Pkcs11FindKeyById(&key, CKO_SECRET_KEY, CKK_AES, session, aes->id, + aes->idLen); + } + + if (ret == 0) { + params.pIv = (CK_BYTE_PTR)info->cipher.aesgcm_dec.iv; + params.ulIvLen = info->cipher.aesgcm_dec.ivSz; + params.pAAD = (CK_BYTE_PTR)info->cipher.aesgcm_dec.authIn; + params.ulAADLen = info->cipher.aesgcm_dec.authInSz; + params.ulTagBits = info->cipher.aesgcm_dec.authTagSz * 8; + + mech.mechanism = CKM_AES_GCM; + mech.ulParameterLen = sizeof(params); + mech.pParameter = ¶ms; + + rv = session->func->C_DecryptInit(session->handle, &mech, key); + if (rv != CKR_OK) + ret = WC_HW_E; + } + if (ret == 0) { + outLen = len = info->cipher.aesgcm_dec.sz; + rv = session->func->C_DecryptUpdate(session->handle, + (CK_BYTE_PTR)info->cipher.aesgcm_dec.in, + info->cipher.aesgcm_dec.sz, + info->cipher.aesgcm_dec.out, + &outLen); + if (rv != CKR_OK) + ret = WC_HW_E; + } + if (ret == 0) { + /* Put authentication tag in as encrypted data. */ + outLen = len = (len + info->cipher.aesgcm_dec.authTagSz - + (word32)outLen); + rv = session->func->C_DecryptUpdate(session->handle, + (CK_BYTE_PTR)info->cipher.aesgcm_dec.authTag, + info->cipher.aesgcm_dec.authTagSz, + info->cipher.aesgcm_dec.out, + &outLen); + if (rv != CKR_OK) + ret = WC_HW_E; + } + if (ret == 0) { + outLen = len = (len - (word32)outLen); + /* Decrypted data comes out now. */ + rv = session->func->C_DecryptFinal(session->handle, + info->cipher.aesgcm_dec.out, + &outLen); + if (rv != CKR_OK) + ret = WC_HW_E; + } + + if (aes->idLen == 0 && key != NULL_PTR) + session->func->C_DestroyObject(session->handle, key); + + return ret; +} +#endif + +#if !defined(NO_AES) && defined(HAVE_AES_CBC) +/** + * Performs the AES-CBC encryption operation. + * + * @param session [in] Session object. + * @param info [in] Cryptographic operation data. + * @return WC_HW_E when a PKCS#11 library call fails. + * MEMORY_E when a memory allocation fails. + * 0 on success. + */ +static int Pkcs11AesCbcEncrypt(Pkcs11Session* session, wc_CryptoInfo* info) +{ + int ret = 0; + CK_RV rv; + Aes* aes = info->cipher.aescbc.aes; + CK_MECHANISM_INFO mechInfo; + CK_OBJECT_HANDLE key = NULL_PTR; + CK_MECHANISM mech; + CK_ULONG outLen; + + /* Check operation is supported. */ + rv = session->func->C_GetMechanismInfo(session->slotId, CKM_AES_CBC, + &mechInfo); + if (rv != CKR_OK || (mechInfo.flags & CKF_ENCRYPT) == 0) + ret = NOT_COMPILED_IN; + + if (ret == 0) { + WOLFSSL_MSG("PKCS#11: AES-CBC Encryption Operation"); + } + + /* Create a private key object or find by id. */ + if (ret == 0 && aes->idLen == 0) { + ret = Pkcs11CreateSecretKey(&key, session, CKK_AES, + (unsigned char*)aes->devKey, aes->keylen, + NULL, 0); + + } + else if (ret == 0) { + ret = Pkcs11FindKeyById(&key, CKO_SECRET_KEY, CKK_AES, session, aes->id, + aes->idLen); + } + + if (ret == 0) { + mech.mechanism = CKM_AES_CBC; + mech.ulParameterLen = AES_BLOCK_SIZE; + mech.pParameter = (CK_BYTE_PTR)info->cipher.aescbc.aes->reg; + + rv = session->func->C_EncryptInit(session->handle, &mech, key); + if (rv != CKR_OK) + ret = WC_HW_E; + } + if (ret == 0) { + outLen = info->cipher.aescbc.sz; + rv = session->func->C_Encrypt(session->handle, + (CK_BYTE_PTR)info->cipher.aescbc.in, + info->cipher.aescbc.sz, + info->cipher.aescbc.out, + &outLen); + if (rv != CKR_OK) + ret = WC_HW_E; + } + + if (aes->idLen == 0 && key != NULL_PTR) + session->func->C_DestroyObject(session->handle, key); + + return ret; +} + +/** + * Performs the AES-CBC decryption operation. + * + * @param session [in] Session object. + * @param info [in] Cryptographic operation data. + * @return WC_HW_E when a PKCS#11 library call fails. + * MEMORY_E when a memory allocation fails. + * 0 on success. + */ +static int Pkcs11AesCbcDecrypt(Pkcs11Session* session, wc_CryptoInfo* info) +{ + int ret = 0; + CK_RV rv; + Aes* aes = info->cipher.aescbc.aes; + CK_MECHANISM_INFO mechInfo; + CK_OBJECT_HANDLE key = NULL_PTR; + CK_MECHANISM mech; + CK_ULONG outLen; + + /* Check operation is supported. */ + rv = session->func->C_GetMechanismInfo(session->slotId, CKM_AES_CBC, + &mechInfo); + if (rv != CKR_OK || (mechInfo.flags & CKF_DECRYPT) == 0) + ret = NOT_COMPILED_IN; + + if (ret == 0) { + WOLFSSL_MSG("PKCS#11: AES-CBC Decryption Operation"); + } + + /* Create a private key object or find by id. */ + if (ret == 0 && aes->idLen == 0) { + ret = Pkcs11CreateSecretKey(&key, session, CKK_AES, + (unsigned char*)aes->devKey, aes->keylen, + NULL, 0); + } + else if (ret == 0) { + ret = Pkcs11FindKeyById(&key, CKO_SECRET_KEY, CKK_AES, session, aes->id, + aes->idLen); + } + + if (ret == 0) { + mech.mechanism = CKM_AES_CBC; + mech.ulParameterLen = AES_BLOCK_SIZE; + mech.pParameter = (CK_BYTE_PTR)info->cipher.aescbc.aes->reg; + + rv = session->func->C_DecryptInit(session->handle, &mech, key); + if (rv != CKR_OK) + ret = WC_HW_E; + } + if (ret == 0) { + outLen = info->cipher.aescbc.sz; + rv = session->func->C_DecryptUpdate(session->handle, + (CK_BYTE_PTR)info->cipher.aescbc.in, + info->cipher.aescbc.sz, + info->cipher.aescbc.out, + &outLen); + if (rv != CKR_OK) + ret = WC_HW_E; + } + + if (aes->idLen == 0 && key != NULL_PTR) + session->func->C_DestroyObject(session->handle, key); + + return ret; +} +#endif + +#ifndef NO_HMAC +/** + * Updates or calculates the HMAC of the data. + * + * @param session [in] Session object. + * @param info [in] Cryptographic operation data. + * @return WC_HW_E when a PKCS#11 library call fails. + * 0 on success. + */ +static int Pkcs11Hmac(Pkcs11Session* session, wc_CryptoInfo* info) +{ + int ret = 0; + CK_RV rv; + Hmac* hmac = info->hmac.hmac; + CK_MECHANISM_INFO mechInfo; + CK_OBJECT_HANDLE key = NULL_PTR; + CK_MECHANISM mech; + CK_ULONG outLen; + int mechType; + int keyType; + + if (hmac->innerHashKeyed == WC_HMAC_INNER_HASH_KEYED_SW) + ret = NOT_COMPILED_IN; + + if (ret == 0) + ret = Pkcs11HmacTypes(info->hmac.macType, &mechType, &keyType); + if (ret == 0) { + /* Check operation is supported. */ + rv = session->func->C_GetMechanismInfo(session->slotId, mechType, + &mechInfo); + if (rv != CKR_OK || (mechInfo.flags & CKF_SIGN) == 0) + ret = NOT_COMPILED_IN; + } + + /* Check whether key been used to initialized. */ + if (ret == 0 && !hmac->innerHashKeyed) { + WOLFSSL_MSG("PKCS#11: HMAC Init"); + + /* Check device supports key length. */ + if (mechInfo.ulMaxKeySize > 0 && + (hmac->keyLen < mechInfo.ulMinKeySize || + hmac->keyLen > mechInfo.ulMaxKeySize)) { + WOLFSSL_MSG("PKCS#11: Key Length not supported"); + ret = NOT_COMPILED_IN; + } + + /* Create a private key object or find by id. */ + if (ret == 0 && hmac->idLen == 0) { + ret = Pkcs11CreateSecretKey(&key, session, keyType, + (unsigned char*)hmac->keyRaw, hmac->keyLen, + NULL, 0); + if (ret == WC_HW_E) { + ret = Pkcs11CreateSecretKey(&key, session, CKK_GENERIC_SECRET, + (unsigned char*)hmac->keyRaw, hmac->keyLen, + NULL, 0); + } + + } + else if (ret == 0) { + ret = Pkcs11FindKeyById(&key, CKO_SECRET_KEY, keyType, session, + hmac->id, hmac->idLen); + if (ret == WC_HW_E) { + ret = Pkcs11FindKeyById(&key, CKO_SECRET_KEY, + CKK_GENERIC_SECRET, session, hmac->id, + hmac->idLen); + } + } + + /* Initialize HMAC operation */ + if (ret == 0) { + mech.mechanism = mechType; + mech.ulParameterLen = 0; + mech.pParameter = NULL; + + rv = session->func->C_SignInit(session->handle, &mech, key); + if (rv != CKR_OK) + ret = WC_HW_E; + } + + /* Don't imitialize HMAC again if this succeeded */ + if (ret == 0) + hmac->innerHashKeyed = WC_HMAC_INNER_HASH_KEYED_DEV; + } + /* Update the HMAC if input data passed in. */ + if (ret == 0 && info->hmac.inSz > 0) { + WOLFSSL_MSG("PKCS#11: HMAC Update"); + + rv = session->func->C_SignUpdate(session->handle, + (CK_BYTE_PTR)info->hmac.in, + info->hmac.inSz); + /* Some algorithm implementations only support C_Sign. */ + if (rv == CKR_MECHANISM_INVALID) { + WOLFSSL_MSG("PKCS#11: HMAC Update/Final not supported"); + ret = NOT_COMPILED_IN; + /* Allow software implementation to set key. */ + hmac->innerHashKeyed = 0; + } + else if (rv != CKR_OK) + ret = WC_HW_E; + } + /* Calculate the HMAC result if output buffer specified. */ + if (ret == 0 && info->hmac.digest != NULL) { + WOLFSSL_MSG("PKCS#11: HMAC Final"); + + outLen = WC_MAX_DIGEST_SIZE; + rv = session->func->C_SignFinal(session->handle, + (CK_BYTE_PTR)info->hmac.digest, + &outLen); + /* Some algorithm implementations only support C_Sign. */ + if (rv != CKR_OK) + ret = WC_HW_E; + else + hmac->innerHashKeyed = 0; + } + + if (hmac->idLen == 0 && key != NULL_PTR) + session->func->C_DestroyObject(session->handle, key); + + return ret; +} +#endif + +#ifndef WC_NO_RNG +#ifndef HAVE_HASHDRBG +/** + * Performs random number generation. + * + * @param session [in] Session object. + * @param info [in] Cryptographic operation data. + * @return WC_HW_E when a PKCS#11 library call fails. + * 0 on success. + */ +static int Pkcs11RandomBlock(Pkcs11Session* session, wc_CryptoInfo* info) +{ + int ret = 0; + CK_RV rv; + + rv = session->func->C_GenerateRandom(session->handle, info->rng.out, + info->rng.sz); + if (rv != CKR_OK) + ret = WC_HW_E; + return ret; +} +#endif + +/** + * Generates entropy (seed) data. + * + * @param session [in] Session object. + * @param info [in] Cryptographic operation data. + * @return WC_HW_E when a PKCS#11 library call fails. + * 0 on success. + */ +static int Pkcs11RandomSeed(Pkcs11Session* session, wc_CryptoInfo* info) +{ + int ret = 0; + CK_RV rv; + + rv = session->func->C_GenerateRandom(session->handle, info->seed.seed, + info->seed.sz); + if (rv != CKR_OK) + ret = WC_HW_E; + return ret; +} +#endif + +/** + * Perform a cryptographic operation using PKCS#11 device. + * + * @param devId [in] Device identifier. + * @param info [in] Cryptographic operation data. + * @param ctx [in] Context data for device - the token object. + * @return WC_HW_E when a PKCS#11 library call fails. + * 0 on success. + */ +int wc_Pkcs11_CryptoDevCb(int devId, wc_CryptoInfo* info, void* ctx) +{ + int ret = 0; + Pkcs11Token* token = (Pkcs11Token*)ctx; + Pkcs11Session session; + int readWrite = 0; + + if (devId <= INVALID_DEVID || info == NULL || ctx == NULL) + ret = BAD_FUNC_ARG; + + if (ret == 0) { + ret = Pkcs11OpenSession(token, &session, readWrite); + if (ret == 0) { + if (info->algo_type == WC_ALGO_TYPE_PK) { +#if !defined(NO_RSA) || defined(HAVE_ECC) + switch (info->pk.type) { + #ifndef NO_RSA + case WC_PK_TYPE_RSA: + ret = Pkcs11Rsa(&session, info); + break; + #ifdef WOLFSSL_KEY_GEN + case WC_PK_TYPE_RSA_KEYGEN: + ret = Pkcs11RsaKeyGen(&session, info); + break; + #endif + #endif + #ifdef HAVE_ECC + #ifndef NO_PKCS11_EC_KEYGEN + case WC_PK_TYPE_EC_KEYGEN: + ret = Pkcs11EcKeyGen(&session, info); + break; + #endif + #ifndef NO_PKCS11_ECDH + case WC_PK_TYPE_ECDH: + ret = Pkcs11ECDH(&session, info); + break; + #endif + case WC_PK_TYPE_ECDSA_SIGN: + ret = Pkcs11ECDSA_Sign(&session, info); + break; + case WC_PK_TYPE_ECDSA_VERIFY: + ret = Pkcs11ECDSA_Verify(&session, info); + break; + #endif + default: + ret = NOT_COMPILED_IN; + break; + } +#else + ret = NOT_COMPILED_IN; +#endif /* !NO_RSA || HAVE_ECC */ + } + else if (info->algo_type == WC_ALGO_TYPE_CIPHER) { + #ifndef NO_AES + switch (info->cipher.type) { + #ifdef HAVE_AESGCM + case WC_CIPHER_AES_GCM: + if (info->cipher.enc) + ret = Pkcs11AesGcmEncrypt(&session, info); + else + ret = Pkcs11AesGcmDecrypt(&session, info); + break; + #endif + #ifdef HAVE_AES_CBC + case WC_CIPHER_AES_CBC: + if (info->cipher.enc) + ret = Pkcs11AesCbcEncrypt(&session, info); + else + ret = Pkcs11AesCbcDecrypt(&session, info); + break; + #endif + } + #else + ret = NOT_COMPILED_IN; + #endif + } + else if (info->algo_type == WC_ALGO_TYPE_HMAC) { + #ifndef NO_HMAC + ret = Pkcs11Hmac(&session, info); + #else + ret = NOT_COMPILED_IN; + #endif + } + else if (info->algo_type == WC_ALGO_TYPE_RNG) { + #if !defined(WC_NO_RNG) && !defined(HAVE_HASHDRBG) + ret = Pkcs11RandomBlock(&session, info); + #else + ret = NOT_COMPILED_IN; + #endif + } + else if (info->algo_type == WC_ALGO_TYPE_SEED) { + #ifndef WC_NO_RNG + ret = Pkcs11RandomSeed(&session, info); + #else + ret = NOT_COMPILED_IN; + #endif + } + else + ret = NOT_COMPILED_IN; + + Pkcs11CloseSession(token, &session); + } + } + + return ret; +} + +#endif /* HAVE_PKCS11 */ + diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/wc_port.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/wc_port.c new file mode 100755 index 0000000..7f9b568 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/wc_port.c @@ -0,0 +1,2206 @@ +/* port.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include +#include +#include +#include +#include +#ifdef HAVE_ECC + #include +#endif +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif + +/* IPP header files for library initialization */ +#ifdef HAVE_FAST_RSA + #include + #include +#endif + +#ifdef FREESCALE_LTC_TFM + #include +#endif + +#if defined(WOLFSSL_ATMEL) || defined(WOLFSSL_ATECC508A) + #include +#endif + +#if defined(WOLFSSL_STSAFEA100) + #include +#endif + +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + #include +#endif + +#if defined(USE_WOLFSSL_MEMORY) && defined(WOLFSSL_TRACK_MEMORY) + #include + #include +#endif + +#if defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG) || \ + defined(WOLFSSL_IMX6_CAAM_BLOB) + #include +#endif + +#ifdef WOLF_CRYPTO_CB + #include +#endif + +#ifdef _MSC_VER + /* 4996 warning to use MS extensions e.g., strcpy_s instead of strncpy */ + #pragma warning(disable: 4996) +#endif + +/* prevent multiple mutex initializations */ +static volatile int initRefCount = 0; + +/* Used to initialize state for wolfcrypt + return 0 on success + */ +int wolfCrypt_Init(void) +{ + int ret = 0; + + if (initRefCount == 0) { + WOLFSSL_ENTER("wolfCrypt_Init"); + + #ifdef WOLFSSL_FORCE_MALLOC_FAIL_TEST + { + word32 rngMallocFail; + time_t seed = time(NULL); + srand((word32)seed); + rngMallocFail = rand() % 2000; /* max 2000 */ + printf("\n--- RNG MALLOC FAIL AT %d---\n", rngMallocFail); + wolfSSL_SetMemFailCount(rngMallocFail); + } + #endif + + #ifdef WOLF_CRYPTO_CB + wc_CryptoCb_Init(); + #endif + + #ifdef WOLFSSL_ASYNC_CRYPT + ret = wolfAsync_HardwareStart(); + if (ret != 0) { + WOLFSSL_MSG("Async hardware start failed"); + /* don't return failure, allow operation to continue */ + } + #endif + + #if defined(WOLFSSL_TRACK_MEMORY) && !defined(WOLFSSL_STATIC_MEMORY) + ret = InitMemoryTracker(); + if (ret != 0) { + WOLFSSL_MSG("InitMemoryTracker failed"); + return ret; + } + #endif + + #if WOLFSSL_CRYPT_HW_MUTEX + /* If crypto hardware mutex protection is enabled, then initialize it */ + ret = wolfSSL_CryptHwMutexInit(); + if (ret != 0) { + WOLFSSL_MSG("Hw crypt mutex init failed"); + return ret; + } + #endif + + /* if defined have fast RSA then initialize Intel IPP */ + #ifdef HAVE_FAST_RSA + WOLFSSL_MSG("Attempting to use optimized IPP Library"); + if ((ret = ippInit()) != ippStsNoErr) { + /* possible to get a CPU feature support status on optimized IPP + library but still use default library and see competitive speeds */ + WOLFSSL_MSG("Warning when trying to set up optimization"); + WOLFSSL_MSG(ippGetStatusString(ret)); + WOLFSSL_MSG("Using default fast IPP library"); + ret = 0; + (void)ret; /* suppress not read warning */ + } + #endif + + #if defined(FREESCALE_LTC_TFM) || defined(FREESCALE_LTC_ECC) + ret = ksdk_port_init(); + if (ret != 0) { + WOLFSSL_MSG("KSDK port init failed"); + return ret; + } + #endif + + #if defined(WOLFSSL_ATMEL) || defined(WOLFSSL_ATECC508A) + ret = atmel_init(); + if (ret != 0) { + WOLFSSL_MSG("CryptoAuthLib init failed"); + return ret; + } + #endif + #if defined(WOLFSSL_CRYPTOCELL) + /* enable and initialize the ARM CryptoCell 3xx runtime library */ + ret = cc310_Init(); + if (ret != 0) { + WOLFSSL_MSG("CRYPTOCELL init failed"); + return ret; + } + #endif + #if defined(WOLFSSL_STSAFEA100) + stsafe_interface_init(); + #endif + + #ifdef WOLFSSL_ARMASM + WOLFSSL_MSG("Using ARM hardware acceleration"); + #endif + + #ifdef WOLFSSL_AFALG + WOLFSSL_MSG("Using AF_ALG for crypto acceleration"); + #endif + + #if !defined(WOLFCRYPT_ONLY) && \ + ( defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) ) + wolfSSL_EVP_init(); + #endif + + #if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) + if ((ret = wc_LoggingInit()) != 0) { + WOLFSSL_MSG("Error creating logging mutex"); + return ret; + } + #endif + +#ifdef HAVE_ECC + #ifdef ECC_CACHE_CURVE + if ((ret = wc_ecc_curve_cache_init()) != 0) { + WOLFSSL_MSG("Error creating curve cache"); + return ret; + } + #endif +#endif + +#if defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG) || \ + defined(WOLFSSL_IMX6_CAAM_BLOB) + if ((ret = wc_caamInit()) != 0) { + return ret; + } +#endif + + initRefCount = 1; + } + + return ret; +} + + +/* return success value is the same as wolfCrypt_Init */ +int wolfCrypt_Cleanup(void) +{ + int ret = 0; + + if (initRefCount == 1) { + WOLFSSL_ENTER("wolfCrypt_Cleanup"); + +#ifdef HAVE_ECC + #ifdef FP_ECC + wc_ecc_fp_free(); + #endif + #ifdef ECC_CACHE_CURVE + wc_ecc_curve_cache_free(); + #endif +#endif /* HAVE_ECC */ + + #if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) + ret = wc_LoggingCleanup(); + #endif + + #if defined(WOLFSSL_TRACK_MEMORY) && !defined(WOLFSSL_STATIC_MEMORY) + ShowMemoryTracker(); + #endif + + #ifdef WOLFSSL_ASYNC_CRYPT + wolfAsync_HardwareStop(); + #endif + + #if defined(WOLFSSL_IMX6_CAAM) || defined(WOLFSSL_IMX6_CAAM_RNG) || \ + defined(WOLFSSL_IMX6_CAAM_BLOB) + wc_caamFree(); + #endif + #if defined(WOLFSSL_CRYPTOCELL) + cc310_Free(); + #endif + initRefCount = 0; /* allow re-init */ + } + + return ret; +} + +#if !defined(NO_FILESYSTEM) && !defined(NO_WOLFSSL_DIR) && \ + !defined(WOLFSSL_NUCLEUS) && !defined(WOLFSSL_NUCLEUS_1_2) + +/* File Handling Helpers */ +/* returns 0 if file found, WC_READDIR_NOFILE if no files or negative error */ +int wc_ReadDirFirst(ReadDirCtx* ctx, const char* path, char** name) +{ + int ret = WC_READDIR_NOFILE; /* default to no files found */ + int pathLen = 0; + int dnameLen = 0; + + if (name) + *name = NULL; + + if (ctx == NULL || path == NULL) { + return BAD_FUNC_ARG; + } + + XMEMSET(ctx->name, 0, MAX_FILENAME_SZ); + pathLen = (int)XSTRLEN(path); + +#ifdef USE_WINDOWS_API + if (pathLen > MAX_FILENAME_SZ - 3) + return BAD_PATH_ERROR; + + XSTRNCPY(ctx->name, path, MAX_FILENAME_SZ - 3); + XSTRNCPY(ctx->name + pathLen, "\\*", MAX_FILENAME_SZ - pathLen); + + ctx->hFind = FindFirstFileA(ctx->name, &ctx->FindFileData); + if (ctx->hFind == INVALID_HANDLE_VALUE) { + WOLFSSL_MSG("FindFirstFile for path verify locations failed"); + return BAD_PATH_ERROR; + } + + do { + if (!(ctx->FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { + dnameLen = (int)XSTRLEN(ctx->FindFileData.cFileName); + + if (pathLen + dnameLen + 2 > MAX_FILENAME_SZ) { + return BAD_PATH_ERROR; + } + XSTRNCPY(ctx->name, path, pathLen + 1); + ctx->name[pathLen] = '\\'; + XSTRNCPY(ctx->name + pathLen + 1, + ctx->FindFileData.cFileName, + MAX_FILENAME_SZ - pathLen - 1); + if (name) + *name = ctx->name; + return 0; + } + } while (FindNextFileA(ctx->hFind, &ctx->FindFileData)); +#elif defined(WOLFSSL_ZEPHYR) + if (fs_opendir(&ctx->dir, path) != 0) { + WOLFSSL_MSG("opendir path verify locations failed"); + return BAD_PATH_ERROR; + } + ctx->dirp = &ctx->dir; + + while ((fs_readdir(&ctx->dir, &ctx->entry)) != 0) { + dnameLen = (int)XSTRLEN(ctx->entry.name); + + if (pathLen + dnameLen + 2 >= MAX_FILENAME_SZ) { + ret = BAD_PATH_ERROR; + break; + } + XSTRNCPY(ctx->name, path, pathLen + 1); + ctx->name[pathLen] = '/'; + + /* Use dnameLen + 1 for GCC 8 warnings of truncating d_name. Because + * of earlier check it is known that dnameLen is less than + * MAX_FILENAME_SZ - (pathLen + 2) so dnameLen +1 will fit */ + XSTRNCPY(ctx->name + pathLen + 1, ctx->entry.name, dnameLen + 1); + if (fs_stat(ctx->name, &ctx->s) != 0) { + WOLFSSL_MSG("stat on name failed"); + ret = BAD_PATH_ERROR; + break; + } else if (ctx->s.type == FS_DIR_ENTRY_FILE) { + if (name) + *name = ctx->name; + return 0; + } + } +#elif defined(WOLFSSL_TELIT_M2MB) + ctx->dir = m2mb_fs_opendir((const CHAR*)path); + if (ctx->dir == NULL) { + WOLFSSL_MSG("opendir path verify locations failed"); + return BAD_PATH_ERROR; + } + + while ((ctx->entry = m2mb_fs_readdir(ctx->dir)) != NULL) { + dnameLen = (int)XSTRLEN(ctx->entry->d_name); + + if (pathLen + dnameLen + 2 >= MAX_FILENAME_SZ) { + ret = BAD_PATH_ERROR; + break; + } + XSTRNCPY(ctx->name, path, pathLen + 1); + ctx->name[pathLen] = '/'; + + /* Use dnameLen + 1 for GCC 8 warnings of truncating d_name. Because + * of earlier check it is known that dnameLen is less than + * MAX_FILENAME_SZ - (pathLen + 2) so dnameLen +1 will fit */ + XSTRNCPY(ctx->name + pathLen + 1, ctx->entry->d_name, dnameLen + 1); + + if (m2mb_fs_stat(ctx->name, &ctx->s) != 0) { + WOLFSSL_MSG("stat on name failed"); + ret = BAD_PATH_ERROR; + break; + } + else if (ctx->s.st_mode & M2MB_S_IFREG) { + if (name) + *name = ctx->name; + return 0; + } + } +#else + ctx->dir = opendir(path); + if (ctx->dir == NULL) { + WOLFSSL_MSG("opendir path verify locations failed"); + return BAD_PATH_ERROR; + } + + while ((ctx->entry = readdir(ctx->dir)) != NULL) { + dnameLen = (int)XSTRLEN(ctx->entry->d_name); + + if (pathLen + dnameLen + 2 >= MAX_FILENAME_SZ) { + ret = BAD_PATH_ERROR; + break; + } + XSTRNCPY(ctx->name, path, pathLen + 1); + ctx->name[pathLen] = '/'; + + /* Use dnameLen + 1 for GCC 8 warnings of truncating d_name. Because + * of earlier check it is known that dnameLen is less than + * MAX_FILENAME_SZ - (pathLen + 2) so dnameLen +1 will fit */ + XSTRNCPY(ctx->name + pathLen + 1, ctx->entry->d_name, dnameLen + 1); + if (stat(ctx->name, &ctx->s) != 0) { + WOLFSSL_MSG("stat on name failed"); + ret = BAD_PATH_ERROR; + break; + } else if (S_ISREG(ctx->s.st_mode)) { + if (name) + *name = ctx->name; + return 0; + } + } +#endif + wc_ReadDirClose(ctx); + + return ret; +} + +/* returns 0 if file found, WC_READDIR_NOFILE if no more files */ +int wc_ReadDirNext(ReadDirCtx* ctx, const char* path, char** name) +{ + int ret = WC_READDIR_NOFILE; /* default to no file found */ + int pathLen = 0; + int dnameLen = 0; + + if (name) + *name = NULL; + + if (ctx == NULL || path == NULL) { + return BAD_FUNC_ARG; + } + + XMEMSET(ctx->name, 0, MAX_FILENAME_SZ); + pathLen = (int)XSTRLEN(path); + +#ifdef USE_WINDOWS_API + while (FindNextFileA(ctx->hFind, &ctx->FindFileData)) { + if (!(ctx->FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { + dnameLen = (int)XSTRLEN(ctx->FindFileData.cFileName); + + if (pathLen + dnameLen + 2 > MAX_FILENAME_SZ) { + return BAD_PATH_ERROR; + } + XSTRNCPY(ctx->name, path, pathLen + 1); + ctx->name[pathLen] = '\\'; + XSTRNCPY(ctx->name + pathLen + 1, + ctx->FindFileData.cFileName, + MAX_FILENAME_SZ - pathLen - 1); + if (name) + *name = ctx->name; + return 0; + } + } +#elif defined(WOLFSSL_ZEPHYR) + while ((fs_readdir(&ctx->dir, &ctx->entry)) != 0) { + dnameLen = (int)XSTRLEN(ctx->entry.name); + + if (pathLen + dnameLen + 2 >= MAX_FILENAME_SZ) { + ret = BAD_PATH_ERROR; + break; + } + XSTRNCPY(ctx->name, path, pathLen + 1); + ctx->name[pathLen] = '/'; + /* Use dnameLen + 1 for GCC 8 warnings of truncating d_name. Because + * of earlier check it is known that dnameLen is less than + * MAX_FILENAME_SZ - (pathLen + 2) so that dnameLen +1 will fit */ + XSTRNCPY(ctx->name + pathLen + 1, ctx->entry.name, dnameLen + 1); + + if (fs_stat(ctx->name, &ctx->s) != 0) { + WOLFSSL_MSG("stat on name failed"); + ret = BAD_PATH_ERROR; + break; + } else if (ctx->s.type == FS_DIR_ENTRY_FILE) { + if (name) + *name = ctx->name; + return 0; + } + } +#elif defined(WOLFSSL_TELIT_M2MB) + while ((ctx->entry = m2mb_fs_readdir(ctx->dir)) != NULL) { + dnameLen = (int)XSTRLEN(ctx->entry->d_name); + + if (pathLen + dnameLen + 2 >= MAX_FILENAME_SZ) { + ret = BAD_PATH_ERROR; + break; + } + XSTRNCPY(ctx->name, path, pathLen + 1); + ctx->name[pathLen] = '/'; + + /* Use dnameLen + 1 for GCC 8 warnings of truncating d_name. Because + * of earlier check it is known that dnameLen is less than + * MAX_FILENAME_SZ - (pathLen + 2) so dnameLen +1 will fit */ + XSTRNCPY(ctx->name + pathLen + 1, ctx->entry->d_name, dnameLen + 1); + + if (m2mb_fs_stat(ctx->name, &ctx->s) != 0) { + WOLFSSL_MSG("stat on name failed"); + ret = BAD_PATH_ERROR; + break; + } + else if (ctx->s.st_mode & M2MB_S_IFREG) { + if (name) + *name = ctx->name; + return 0; + } + } +#else + while ((ctx->entry = readdir(ctx->dir)) != NULL) { + dnameLen = (int)XSTRLEN(ctx->entry->d_name); + + if (pathLen + dnameLen + 2 >= MAX_FILENAME_SZ) { + ret = BAD_PATH_ERROR; + break; + } + XSTRNCPY(ctx->name, path, pathLen + 1); + ctx->name[pathLen] = '/'; + /* Use dnameLen + 1 for GCC 8 warnings of truncating d_name. Because + * of earlier check it is known that dnameLen is less than + * MAX_FILENAME_SZ - (pathLen + 2) so that dnameLen +1 will fit */ + XSTRNCPY(ctx->name + pathLen + 1, ctx->entry->d_name, dnameLen + 1); + + if (stat(ctx->name, &ctx->s) != 0) { + WOLFSSL_MSG("stat on name failed"); + ret = BAD_PATH_ERROR; + break; + } else if (S_ISREG(ctx->s.st_mode)) { + if (name) + *name = ctx->name; + return 0; + } + } +#endif + + wc_ReadDirClose(ctx); + + return ret; +} + +void wc_ReadDirClose(ReadDirCtx* ctx) +{ + if (ctx == NULL) { + return; + } + +#ifdef USE_WINDOWS_API + if (ctx->hFind != INVALID_HANDLE_VALUE) { + FindClose(ctx->hFind); + ctx->hFind = INVALID_HANDLE_VALUE; + } +#elif defined(WOLFSSL_ZEPHYR) + if (ctx->dirp) { + fs_closedir(ctx->dirp); + ctx->dirp = NULL; + } +#elif defined(WOLFSSL_TELIT_M2MB) + if (ctx->dir) { + m2mb_fs_closedir(ctx->dir); + ctx->dir = NULL; + } +#else + if (ctx->dir) { + closedir(ctx->dir); + ctx->dir = NULL; + } +#endif +} + +#endif /* !NO_FILESYSTEM && !NO_WOLFSSL_DIR */ + +#if !defined(NO_FILESYSTEM) && defined(WOLFSSL_ZEPHYR) +XFILE z_fs_open(const char* filename, const char* perm) +{ + XFILE file; + + file = XMALLOC(sizeof(*file), NULL, DYNAMIC_TYPE_FILE); + if (file != NULL) { + if (fs_open(file, filename) != 0) { + XFREE(file); + file = NULL; + } + } + + return file; +} + +int z_fs_close(XFILE file) +{ + int ret; + + if (file == NULL) + return -1; + ret = (fs_close(file) == 0) ? 0 : -1; + + XFREE(file, NULL, DYNAMIC_TYPE_FILE); + + return ret; +} + +#endif /* !NO_FILESYSTEM && !WOLFSSL_ZEPHYR */ + + +wolfSSL_Mutex* wc_InitAndAllocMutex(void) +{ + wolfSSL_Mutex* m = (wolfSSL_Mutex*) XMALLOC(sizeof(wolfSSL_Mutex), NULL, + DYNAMIC_TYPE_MUTEX); + if (m != NULL) { + if (wc_InitMutex(m) != 0) { + WOLFSSL_MSG("Init Mutex failed"); + XFREE(m, NULL, DYNAMIC_TYPE_MUTEX); + m = NULL; + } + } + else { + WOLFSSL_MSG("Memory error with Mutex allocation"); + } + + return m; +} + +#ifdef USE_WOLF_STRTOK +/* String token (delim) search. If str is null use nextp. */ +char* wc_strtok(char *str, const char *delim, char **nextp) +{ + char* ret; + int i, j; + + /* Use next if str is NULL */ + if (str == NULL && nextp) + str = *nextp; + + /* verify str input */ + if (str == NULL || *str == '\0') + return NULL; + + /* match on entire delim */ + for (i = 0; str[i]; i++) { + for (j = 0; delim[j]; j++) { + if (delim[j] == str[i]) + break; + } + if (!delim[j]) + break; + } + str += i; + /* if end of string, not found so return NULL */ + if (*str == '\0') + return NULL; + + ret = str; + + /* match on first delim */ + for (i = 0; str[i]; i++) { + for (j = 0; delim[j]; j++) { + if (delim[j] == str[i]) + break; + } + if (delim[j] == str[i]) + break; + } + str += i; + + /* null terminate found string */ + if (*str) + *str++ = '\0'; + + /* return pointer to next */ + if (nextp) + *nextp = str; + + return ret; +} +#endif /* USE_WOLF_STRTOK */ + +#ifdef USE_WOLF_STRSEP +char* wc_strsep(char **stringp, const char *delim) +{ + char *s, *tok; + const char *spanp; + + /* null check */ + if (stringp == NULL || *stringp == NULL) + return NULL; + + s = *stringp; + for (tok = s; *tok; ++tok) { + for (spanp = delim; *spanp; ++spanp) { + /* found delimiter */ + if (*tok == *spanp) { + *tok = '\0'; /* replace delim with null term */ + *stringp = tok + 1; /* return past delim */ + return s; + } + } + } + + *stringp = NULL; + return s; +} +#endif /* USE_WOLF_STRSEP */ + +#if WOLFSSL_CRYPT_HW_MUTEX +/* Mutex for protection of cryptography hardware */ +static wolfSSL_Mutex wcCryptHwMutex; +static int wcCryptHwMutexInit = 0; + +int wolfSSL_CryptHwMutexInit(void) { + int ret = 0; + if(wcCryptHwMutexInit == 0) { + ret = wc_InitMutex(&wcCryptHwMutex); + if(ret == 0) { + wcCryptHwMutexInit = 1; + } + } + return ret; +} + +int wolfSSL_CryptHwMutexLock(void) { + int ret = BAD_MUTEX_E; + + /* Make sure HW Mutex has been initialized */ + wolfSSL_CryptHwMutexInit(); + + if(wcCryptHwMutexInit) { + ret = wc_LockMutex(&wcCryptHwMutex); + } + return ret; +} + +int wolfSSL_CryptHwMutexUnLock(void) { + int ret = BAD_MUTEX_E; + + if(wcCryptHwMutexInit) { + ret = wc_UnLockMutex(&wcCryptHwMutex); + } + return ret; +} +#endif /* WOLFSSL_CRYPT_HW_MUTEX */ + + +/* ---------------------------------------------------------------------------*/ +/* Mutex Ports */ +/* ---------------------------------------------------------------------------*/ +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + static mutex_cb* compat_mutex_cb = NULL; + + /* Function that locks or unlocks a mutex based on the flag passed in. + * + * flag lock or unlock i.e. CRYPTO_LOCK + * type the type of lock to unlock or lock + * file name of the file calling + * line the line number from file calling + */ + int wc_LockMutex_ex(int flag, int type, const char* file, int line) + { + if (compat_mutex_cb != NULL) { + compat_mutex_cb(flag, type, file, line); + return 0; + } + else { + WOLFSSL_MSG("Mutex call back function not set. Call wc_SetMutexCb"); + return BAD_STATE_E; + } + } + + + /* Set the callback function to use for locking/unlocking mutex + * + * cb callback function to use + */ + int wc_SetMutexCb(mutex_cb* cb) + { + compat_mutex_cb = cb; + return 0; + } +#endif /* defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) */ +#ifdef SINGLE_THREADED + + int wc_InitMutex(wolfSSL_Mutex* m) + { + (void)m; + return 0; + } + + int wc_FreeMutex(wolfSSL_Mutex *m) + { + (void)m; + return 0; + } + + + int wc_LockMutex(wolfSSL_Mutex *m) + { + (void)m; + return 0; + } + + + int wc_UnLockMutex(wolfSSL_Mutex *m) + { + (void)m; + return 0; + } + +#elif defined(FREERTOS) || defined(FREERTOS_TCP) || \ + defined(FREESCALE_FREE_RTOS) + + int wc_InitMutex(wolfSSL_Mutex* m) + { + int iReturn; + + *m = ( wolfSSL_Mutex ) xSemaphoreCreateMutex(); + if( *m != NULL ) + iReturn = 0; + else + iReturn = BAD_MUTEX_E; + + return iReturn; + } + + int wc_FreeMutex(wolfSSL_Mutex* m) + { + vSemaphoreDelete( *m ); + return 0; + } + + int wc_LockMutex(wolfSSL_Mutex* m) + { + /* Assume an infinite block, or should there be zero block? */ + xSemaphoreTake( *m, portMAX_DELAY ); + return 0; + } + + int wc_UnLockMutex(wolfSSL_Mutex* m) + { + xSemaphoreGive( *m ); + return 0; + } + +#elif defined(WOLFSSL_SAFERTOS) + + int wc_InitMutex(wolfSSL_Mutex* m) + { + vSemaphoreCreateBinary(m->mutexBuffer, m->mutex); + if (m->mutex == NULL) + return BAD_MUTEX_E; + + return 0; + } + + int wc_FreeMutex(wolfSSL_Mutex* m) + { + (void)m; + return 0; + } + + int wc_LockMutex(wolfSSL_Mutex* m) + { + /* Assume an infinite block */ + xSemaphoreTake(m->mutex, portMAX_DELAY); + return 0; + } + + int wc_UnLockMutex(wolfSSL_Mutex* m) + { + xSemaphoreGive(m->mutex); + return 0; + } + +#elif defined(USE_WINDOWS_API) + + int wc_InitMutex(wolfSSL_Mutex* m) + { + InitializeCriticalSection(m); + return 0; + } + + + int wc_FreeMutex(wolfSSL_Mutex* m) + { + DeleteCriticalSection(m); + return 0; + } + + + int wc_LockMutex(wolfSSL_Mutex* m) + { + EnterCriticalSection(m); + return 0; + } + + + int wc_UnLockMutex(wolfSSL_Mutex* m) + { + LeaveCriticalSection(m); + return 0; + } + +#elif defined(WOLFSSL_PTHREADS) + + int wc_InitMutex(wolfSSL_Mutex* m) + { + if (pthread_mutex_init(m, 0) == 0) + return 0; + else + return BAD_MUTEX_E; + } + + + int wc_FreeMutex(wolfSSL_Mutex* m) + { + if (pthread_mutex_destroy(m) == 0) + return 0; + else + return BAD_MUTEX_E; + } + + + int wc_LockMutex(wolfSSL_Mutex* m) + { + if (pthread_mutex_lock(m) == 0) + return 0; + else + return BAD_MUTEX_E; + } + + + int wc_UnLockMutex(wolfSSL_Mutex* m) + { + if (pthread_mutex_unlock(m) == 0) + return 0; + else + return BAD_MUTEX_E; + } + +#elif defined(WOLFSSL_VXWORKS) + + int wc_InitMutex(wolfSSL_Mutex* m) + { + if (m) { + if ((*m = semMCreate(0)) != SEM_ID_NULL) + return 0; + } + return BAD_MUTEX_E; + } + + + int wc_FreeMutex(wolfSSL_Mutex* m) + { + if (m) { + if (semDelete(*m) == OK) + return 0; + } + return BAD_MUTEX_E; + } + + + int wc_LockMutex(wolfSSL_Mutex* m) + { + if (m) { + if (semTake(*m, WAIT_FOREVER) == OK) + return 0; + } + return BAD_MUTEX_E; + } + + + int wc_UnLockMutex(wolfSSL_Mutex* m) + { + if (m) { + if (semGive(*m) == OK) + return 0; + } + return BAD_MUTEX_E; + } + +#elif defined(THREADX) + + int wc_InitMutex(wolfSSL_Mutex* m) + { + if (tx_mutex_create(m, "wolfSSL Mutex", TX_NO_INHERIT) == 0) + return 0; + else + return BAD_MUTEX_E; + } + + + int wc_FreeMutex(wolfSSL_Mutex* m) + { + if (tx_mutex_delete(m) == 0) + return 0; + else + return BAD_MUTEX_E; + } + + + int wc_LockMutex(wolfSSL_Mutex* m) + { + if (tx_mutex_get(m, TX_WAIT_FOREVER) == 0) + return 0; + else + return BAD_MUTEX_E; + } + + int wc_UnLockMutex(wolfSSL_Mutex* m) + { + if (tx_mutex_put(m) == 0) + return 0; + else + return BAD_MUTEX_E; + } + +#elif defined(WOLFSSL_DEOS) + + int wc_InitMutex(wolfSSL_Mutex* m) + { + mutexStatus mutStat; + /* + The empty string "" denotes an anonymous mutex, so objects do not cause name collisions. + `protectWolfSSLTemp` in an XML configuration element template describing a mutex. + */ + if (m) { + mutStat = createMutex("", "protectWolfSSLTemp", m); + if (mutStat == mutexSuccess) + return 0; + else{ + WOLFSSL_MSG("wc_InitMutex failed"); + return mutStat; + } + } + return BAD_MUTEX_E; + } + + int wc_FreeMutex(wolfSSL_Mutex* m) + { + mutexStatus mutStat; + if (m) { + mutStat = deleteMutex(*m); + if (mutStat == mutexSuccess) + return 0; + else{ + WOLFSSL_MSG("wc_FreeMutex failed"); + return mutStat; + } + } + return BAD_MUTEX_E; + } + + int wc_LockMutex(wolfSSL_Mutex* m) + { + mutexStatus mutStat; + if (m) { + mutStat = lockMutex(*m); + if (mutStat == mutexSuccess) + return 0; + else{ + WOLFSSL_MSG("wc_LockMutex failed"); + return mutStat; + } + } + return BAD_MUTEX_E; + } + + int wc_UnLockMutex(wolfSSL_Mutex* m) + { + mutexStatus mutStat; + if (m) { + mutStat = unlockMutex(*m); + if (mutStat== mutexSuccess) + return 0; + else{ + WOLFSSL_MSG("wc_UnLockMutex failed"); + return mutStat; + } + } + return BAD_MUTEX_E; + } + +#elif defined(MICRIUM) + + int wc_InitMutex(wolfSSL_Mutex* m) + { + OS_ERR err; + + OSMutexCreate(m, "wolfSSL Mutex", &err); + + if (err == OS_ERR_NONE) + return 0; + else + return BAD_MUTEX_E; + } + + int wc_FreeMutex(wolfSSL_Mutex* m) + { + #if (OS_CFG_MUTEX_DEL_EN == DEF_ENABLED) + OS_ERR err; + + OSMutexDel(m, OS_OPT_DEL_ALWAYS, &err); + + if (err == OS_ERR_NONE) + return 0; + else + return BAD_MUTEX_E; + #else + return 0; + #endif + } + + int wc_LockMutex(wolfSSL_Mutex* m) + { + OS_ERR err; + + OSMutexPend(m, 0, OS_OPT_PEND_BLOCKING, NULL, &err); + + if (err == OS_ERR_NONE) + return 0; + else + return BAD_MUTEX_E; + } + + int wc_UnLockMutex(wolfSSL_Mutex* m) + { + OS_ERR err; + + OSMutexPost(m, OS_OPT_POST_NONE, &err); + + if (err == OS_ERR_NONE) + return 0; + else + return BAD_MUTEX_E; + } + +#elif defined(EBSNET) + + int wc_InitMutex(wolfSSL_Mutex* m) + { + if (rtp_sig_mutex_alloc(m, "wolfSSL Mutex") == -1) + return BAD_MUTEX_E; + else + return 0; + } + + int wc_FreeMutex(wolfSSL_Mutex* m) + { + rtp_sig_mutex_free(*m); + return 0; + } + + int wc_LockMutex(wolfSSL_Mutex* m) + { + if (rtp_sig_mutex_claim_timed(*m, RTIP_INF) == 0) + return 0; + else + return BAD_MUTEX_E; + } + + int wc_UnLockMutex(wolfSSL_Mutex* m) + { + rtp_sig_mutex_release(*m); + return 0; + } + +#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) + + int wc_InitMutex(wolfSSL_Mutex* m) + { + if (_mutex_init(m, NULL) == MQX_EOK) + return 0; + else + return BAD_MUTEX_E; + } + + int wc_FreeMutex(wolfSSL_Mutex* m) + { + if (_mutex_destroy(m) == MQX_EOK) + return 0; + else + return BAD_MUTEX_E; + } + + int wc_LockMutex(wolfSSL_Mutex* m) + { + if (_mutex_lock(m) == MQX_EOK) + return 0; + else + return BAD_MUTEX_E; + } + + int wc_UnLockMutex(wolfSSL_Mutex* m) + { + if (_mutex_unlock(m) == MQX_EOK) + return 0; + else + return BAD_MUTEX_E; + } + +#elif defined(WOLFSSL_TIRTOS) + #include + + int wc_InitMutex(wolfSSL_Mutex* m) + { + Semaphore_Params params; + Error_Block eb; + + Error_init(&eb); + Semaphore_Params_init(¶ms); + params.mode = Semaphore_Mode_BINARY; + + *m = Semaphore_create(1, ¶ms, &eb); + if (Error_check(&eb)) { + Error_raise(&eb, Error_E_generic, "Failed to Create the semaphore.", + NULL); + return BAD_MUTEX_E; + } + else + return 0; + } + + int wc_FreeMutex(wolfSSL_Mutex* m) + { + Semaphore_delete(m); + + return 0; + } + + int wc_LockMutex(wolfSSL_Mutex* m) + { + Semaphore_pend(*m, BIOS_WAIT_FOREVER); + + return 0; + } + + int wc_UnLockMutex(wolfSSL_Mutex* m) + { + Semaphore_post(*m); + + return 0; + } + +#elif defined(WOLFSSL_uITRON4) + + int wc_InitMutex(wolfSSL_Mutex* m) + { + int iReturn; + m->sem.sematr = TA_TFIFO; + m->sem.isemcnt = 1; + m->sem.maxsem = 1; + m->sem.name = NULL; + + m->id = acre_sem(&m->sem); + if( m->id != E_OK ) + iReturn = 0; + else + iReturn = BAD_MUTEX_E; + + return iReturn; + } + + int wc_FreeMutex(wolfSSL_Mutex* m) + { + del_sem( m->id ); + return 0; + } + + int wc_LockMutex(wolfSSL_Mutex* m) + { + wai_sem(m->id); + return 0; + } + + int wc_UnLockMutex(wolfSSL_Mutex* m) + { + sig_sem(m->id); + return 0; + } + + /**** uITRON malloc/free ***/ + static ID ID_wolfssl_MPOOL = 0; + static T_CMPL wolfssl_MPOOL = {TA_TFIFO, 0, NULL, "wolfSSL_MPOOL"}; + + int uITRON4_minit(size_t poolsz) { + ER ercd; + wolfssl_MPOOL.mplsz = poolsz; + ercd = acre_mpl(&wolfssl_MPOOL); + if (ercd > 0) { + ID_wolfssl_MPOOL = ercd; + return 0; + } else { + return -1; + } + } + + void *uITRON4_malloc(size_t sz) { + ER ercd; + void *p; + ercd = get_mpl(ID_wolfssl_MPOOL, sz, (VP)&p); + if (ercd == E_OK) { + return p; + } else { + return 0; + } + } + + void *uITRON4_realloc(void *p, size_t sz) { + ER ercd; + void *newp; + if(p) { + ercd = get_mpl(ID_wolfssl_MPOOL, sz, (VP)&newp); + if (ercd == E_OK) { + XMEMCPY(newp, p, sz); + ercd = rel_mpl(ID_wolfssl_MPOOL, (VP)p); + if (ercd == E_OK) { + return newp; + } + } + } + return 0; + } + + void uITRON4_free(void *p) { + ER ercd; + ercd = rel_mpl(ID_wolfssl_MPOOL, (VP)p); + if (ercd == E_OK) { + return; + } else { + return; + } + } + +#elif defined(WOLFSSL_uTKERNEL2) + + int wc_InitMutex(wolfSSL_Mutex* m) + { + int iReturn; + m->sem.sematr = TA_TFIFO; + m->sem.isemcnt = 1; + m->sem.maxsem = 1; + + m->id = tk_cre_sem(&m->sem); + if( m->id != NULL ) + iReturn = 0; + else + iReturn = BAD_MUTEX_E; + + return iReturn; + } + + int wc_FreeMutex(wolfSSL_Mutex* m) + { + tk_del_sem(m->id); + return 0; + } + + int wc_LockMutex(wolfSSL_Mutex* m) + { + tk_wai_sem(m->id, 1, TMO_FEVR); + return 0; + } + + int wc_UnLockMutex(wolfSSL_Mutex* m) + { + tk_sig_sem(m->id, 1); + return 0; + } + + /**** uT-Kernel malloc/free ***/ + static ID ID_wolfssl_MPOOL = 0; + static T_CMPL wolfssl_MPOOL = { + NULL, /* Extended information */ + TA_TFIFO, /* Memory pool attribute */ + 0, /* Size of whole memory pool (byte) */ + "wolfSSL" /* Object name (max 8-char) */ + }; + + int uTKernel_init_mpool(unsigned int sz) { + ER ercd; + wolfssl_MPOOL.mplsz = sz; + ercd = tk_cre_mpl(&wolfssl_MPOOL); + if (ercd > 0) { + ID_wolfssl_MPOOL = ercd; + return 0; + } else { + return (int)ercd; + } + } + + void *uTKernel_malloc(unsigned int sz) { + ER ercd; + void *p; + ercd = tk_get_mpl(ID_wolfssl_MPOOL, sz, (VP)&p, TMO_FEVR); + if (ercd == E_OK) { + return p; + } else { + return 0; + } + } + + void *uTKernel_realloc(void *p, unsigned int sz) { + ER ercd; + void *newp; + if (p) { + ercd = tk_get_mpl(ID_wolfssl_MPOOL, sz, (VP)&newp, TMO_FEVR); + if (ercd == E_OK) { + XMEMCPY(newp, p, sz); + ercd = tk_rel_mpl(ID_wolfssl_MPOOL, (VP)p); + if (ercd == E_OK) { + return newp; + } + } + } + return 0; + } + + void uTKernel_free(void *p) { + ER ercd; + ercd = tk_rel_mpl(ID_wolfssl_MPOOL, (VP)p); + if (ercd == E_OK) { + return; + } else { + return; + } + } + +#elif defined (WOLFSSL_FROSTED) + + int wc_InitMutex(wolfSSL_Mutex* m) + { + *m = mutex_init(); + if (*m) + return 0; + else + return -1; + } + + int wc_FreeMutex(wolfSSL_Mutex* m) + { + mutex_destroy(*m); + return(0); + } + + int wc_LockMutex(wolfSSL_Mutex* m) + { + mutex_lock(*m); + return 0; + } + + int wc_UnLockMutex(wolfSSL_Mutex* m) + { + mutex_unlock(*m); + return 0; + } + +#elif defined(WOLFSSL_CMSIS_RTOS) + + #define CMSIS_NMUTEX 10 + osMutexDef(wolfSSL_mt0); osMutexDef(wolfSSL_mt1); osMutexDef(wolfSSL_mt2); + osMutexDef(wolfSSL_mt3); osMutexDef(wolfSSL_mt4); osMutexDef(wolfSSL_mt5); + osMutexDef(wolfSSL_mt6); osMutexDef(wolfSSL_mt7); osMutexDef(wolfSSL_mt8); + osMutexDef(wolfSSL_mt9); + + static const osMutexDef_t *CMSIS_mutex[] = { osMutex(wolfSSL_mt0), + osMutex(wolfSSL_mt1), osMutex(wolfSSL_mt2), osMutex(wolfSSL_mt3), + osMutex(wolfSSL_mt4), osMutex(wolfSSL_mt5), osMutex(wolfSSL_mt6), + osMutex(wolfSSL_mt7), osMutex(wolfSSL_mt8), osMutex(wolfSSL_mt9) }; + + static osMutexId CMSIS_mutexID[CMSIS_NMUTEX] = {0}; + + int wc_InitMutex(wolfSSL_Mutex* m) + { + int i; + for (i=0; itm_sec = (int) dayclock % 60; + ret->tm_min = (int)(dayclock % 3600) / 60; + ret->tm_hour = (int) dayclock / 3600; + ret->tm_wday = (int) (dayno + 4) % 7; /* day 0 a Thursday */ + + while(dayno >= (unsigned long)YEARSIZE(year)) { + dayno -= YEARSIZE(year); + year++; + } + + ret->tm_year = year - YEAR0; + ret->tm_yday = (int)dayno; + ret->tm_mon = 0; + + while(dayno >= (unsigned long)_ytab[LEAPYEAR(year)][ret->tm_mon]) { + dayno -= _ytab[LEAPYEAR(year)][ret->tm_mon]; + ret->tm_mon++; + } + + ret->tm_mday = (int)++dayno; + ret->tm_isdst = 0; + + return ret; +} +#endif /* WOLFSSL_GMTIME */ + + +#if defined(HAVE_RTP_SYS) +#define YEAR0 1900 + +struct tm* rtpsys_gmtime(const time_t* timer) /* has a gmtime() but hangs */ +{ + static struct tm st_time; + struct tm* ret = &st_time; + + DC_RTC_CALENDAR cal; + dc_rtc_time_get(&cal, TRUE); + + ret->tm_year = cal.year - YEAR0; /* gm starts at 1900 */ + ret->tm_mon = cal.month - 1; /* gm starts at 0 */ + ret->tm_mday = cal.day; + ret->tm_hour = cal.hour; + ret->tm_min = cal.minute; + ret->tm_sec = cal.second; + + return ret; +} + +#endif /* HAVE_RTP_SYS */ + + +#if defined(MICROCHIP_TCPIP_V5) || defined(MICROCHIP_TCPIP) + +/* + * time() is just a stub in Microchip libraries. We need our own + * implementation. Use SNTP client to get seconds since epoch. + */ +time_t pic32_time(time_t* timer) +{ +#ifdef MICROCHIP_TCPIP_V5 + DWORD sec = 0; +#else + uint32_t sec = 0; +#endif + time_t localTime; + + if (timer == NULL) + timer = &localTime; + +#ifdef MICROCHIP_MPLAB_HARMONY + sec = TCPIP_SNTP_UTCSecondsGet(); +#else + sec = SNTPGetUTCSeconds(); +#endif + *timer = (time_t) sec; + + return *timer; +} + +#endif /* MICROCHIP_TCPIP || MICROCHIP_TCPIP_V5 */ + +#if defined(WOLFSSL_DEOS) + +time_t deos_time(time_t* timer) +{ + const uint32_t systemTickTimeInHz = 1000000 / systemTickInMicroseconds(); + uint32_t *systemTickPtr = systemTickPointer(); + + if (timer != NULL) + *timer = *systemTickPtr/systemTickTimeInHz; + + #if defined(CURRENT_UNIX_TIMESTAMP) + /* CURRENT_UNIX_TIMESTAMP is seconds since Jan 01 1970. (UTC) */ + return (time_t) *systemTickPtr/systemTickTimeInHz + CURRENT_UNIX_TIMESTAMP; + #else + return (time_t) *systemTickPtr/systemTickTimeInHz; + #endif +} +#endif /* WOLFSSL_DEOS */ + +#if defined(MICRIUM) + +time_t micrium_time(time_t* timer) +{ + CLK_TS_SEC sec; + + Clk_GetTS_Unix(&sec); + + if (timer != NULL) + *timer = sec; + + return (time_t) sec; +} + +#endif /* MICRIUM */ + +#if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) + +time_t mqx_time(time_t* timer) +{ + time_t localTime; + TIME_STRUCT time_s; + + if (timer == NULL) + timer = &localTime; + + _time_get(&time_s); + *timer = (time_t) time_s.SECONDS; + + return *timer; +} + +#endif /* FREESCALE_MQX || FREESCALE_KSDK_MQX */ + + +#if defined(WOLFSSL_TIRTOS) && defined(USER_TIME) + +time_t XTIME(time_t * timer) +{ + time_t sec = 0; + + sec = (time_t) Seconds_get(); + + if (timer != NULL) + *timer = sec; + + return sec; +} + +#endif /* WOLFSSL_TIRTOS */ + +#if defined(WOLFSSL_XILINX) +#include "xrtcpsu.h" + +time_t XTIME(time_t * timer) +{ + time_t sec = 0; + XRtcPsu_Config* con; + XRtcPsu rtc; + + con = XRtcPsu_LookupConfig(XPAR_XRTCPSU_0_DEVICE_ID); + if (con != NULL) { + if (XRtcPsu_CfgInitialize(&rtc, con, con->BaseAddr) == XST_SUCCESS) { + sec = (time_t)XRtcPsu_GetCurrentTime(&rtc); + } + else { + WOLFSSL_MSG("Unable to initialize RTC"); + } + } + + if (timer != NULL) + *timer = sec; + + return sec; +} + +#endif /* WOLFSSL_XILINX */ + +#if defined(WOLFSSL_ZEPHYR) + +time_t z_time(time_t * timer) +{ + struct timespec ts; + + if (clock_gettime(CLOCK_REALTIME, &ts) == 0) + if (timer != NULL) + *timer = ts.tv_sec; + + return ts.tv_sec; +} + +#endif /* WOLFSSL_ZEPHYR */ + + +#if defined(WOLFSSL_WICED) + #ifndef WOLFSSL_WICED_PSEUDO_UNIX_EPOCH_TIME + #error Please define WOLFSSL_WICED_PSEUDO_UNIX_EPOCH_TIME at build time. + #endif /* WOLFSSL_WICED_PSEUDO_UNIX_EPOCH_TIME */ + +time_t wiced_pseudo_unix_epoch_time(time_t * timer) +{ + time_t epoch_time; + /* The time() function return uptime on WICED platform. */ + epoch_time = time(NULL) + WOLFSSL_WICED_PSEUDO_UNIX_EPOCH_TIME; + + if (timer != NULL) { + *timer = epoch_time; + } + return epoch_time; +} +#endif /* WOLFSSL_WICED */ + +#ifdef WOLFSSL_TELIT_M2MB + time_t m2mb_xtime(time_t * timer) + { + time_t myTime = 0; + INT32 fd = m2mb_rtc_open("/dev/rtc0", 0); + if (fd >= 0) { + M2MB_RTC_TIMEVAL_T timeval; + + m2mb_rtc_ioctl(fd, M2MB_RTC_IOCTL_GET_TIMEVAL, &timeval); + + myTime = timeval.sec; + + m2mb_rtc_close(fd); + } + return myTime; + } + #ifdef WOLFSSL_TLS13 + time_t m2mb_xtime_ms(time_t * timer) + { + time_t myTime = 0; + INT32 fd = m2mb_rtc_open("/dev/rtc0", 0); + if (fd >= 0) { + M2MB_RTC_TIMEVAL_T timeval; + + m2mb_rtc_ioctl(fd, M2MB_RTC_IOCTL_GET_TIMEVAL, &timeval); + + myTime = timeval.sec + timeval.msec; + + m2mb_rtc_close(fd); + } + return myTime; + } + #endif /* WOLFSSL_TLS13 */ + #ifndef NO_CRYPT_BENCHMARK + double m2mb_xtime_bench(int reset) + { + double myTime = 0; + INT32 fd = m2mb_rtc_open("/dev/rtc0", 0); + if (fd >= 0) { + M2MB_RTC_TIMEVAL_T timeval; + + m2mb_rtc_ioctl(fd, M2MB_RTC_IOCTL_GET_TIMEVAL, &timeval); + + myTime = (double)timeval.sec + ((double)timeval.msec / 1000); + + m2mb_rtc_close(fd); + } + return myTime; + } + #endif /* !NO_CRYPT_BENCHMARK */ +#endif /* WOLFSSL_TELIT_M2MB */ + +#endif /* !NO_ASN_TIME */ + +#ifndef WOLFSSL_LEANPSK +char* mystrnstr(const char* s1, const char* s2, unsigned int n) +{ + unsigned int s2_len = (unsigned int)XSTRLEN(s2); + + if (s2_len == 0) + return (char*)s1; + + while (n >= s2_len && s1[0]) { + if (s1[0] == s2[0]) + if (XMEMCMP(s1, s2, s2_len) == 0) + return (char*)s1; + s1++; + n--; + } + + return NULL; +} +#endif + +/* custom memory wrappers */ +#ifdef WOLFSSL_NUCLEUS_1_2 + + /* system memory pool */ + extern NU_MEMORY_POOL System_Memory; + + void* nucleus_malloc(unsigned long size, void* heap, int type) + { + STATUS status; + void* stack_ptr; + + status = NU_Allocate_Memory(&System_Memory, &stack_ptr, size, + NU_NO_SUSPEND); + if (status == NU_SUCCESS) { + return 0; + } else { + return stack_ptr; + } + } + + void* nucleus_realloc(void* ptr, unsigned long size, void* heap, int type) + { + STATUS status; + DM_HEADER* old_header; + word32 old_size, copy_size; + void* new_mem; + + /* if ptr is NULL, behave like malloc */ + new_mem = nucleus_malloc(size, NULL, 0); + if (new_mem == 0 || ptr == 0) { + return new_mem; + } + + /* calculate old memory block size */ + /* mem pointers stored in block headers (ref dm_defs.h) */ + old_header = (DM_HEADER*) ((byte*)ptr - DM_OVERHEAD); + old_size = (byte*)old_header->dm_next_memory - (byte*)ptr; + + /* copy old to new */ + if (old_size < size) { + copy_size = old_size; + } else { + copy_size = size; + } + XMEMCPY(new_mem, ptr, copy_size); + + /* free old */ + nucleus_free(ptr, NULL, 0); + + return new_mem; + } + + void nucleus_free(void* ptr, void* heap, int type) + { + if (ptr != NULL) + NU_Deallocate_Memory(ptr); + } + +#endif /* WOLFSSL_NUCLEUS_1_2 */ + +#if defined(WOLFSSL_TI_CRYPT) || defined(WOLFSSL_TI_HASH) + #include /* initialize and Mutex for TI Crypt Engine */ + #include /* md5, sha1, sha224, sha256 */ +#endif + +#if defined(WOLFSSL_CRYPTOCELL) + #define WOLFSSL_CRYPTOCELL_C + #include /* CC310, RTC and RNG */ + #if !defined(NO_SHA256) + #define WOLFSSL_CRYPTOCELL_HASH_C + #include /* sha256 */ + #endif +#endif diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/wolfevent.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/wolfevent.c new file mode 100755 index 0000000..4efc6a8 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/wolfevent.c @@ -0,0 +1,283 @@ +/* wolfevent.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +#include + + +#ifdef HAVE_WOLF_EVENT + +#include +#include +#include + +#include + + +int wolfEvent_Init(WOLF_EVENT* event, WOLF_EVENT_TYPE type, void* context) +{ + if (event == NULL) { + return BAD_FUNC_ARG; + } + + if (event->state == WOLF_EVENT_STATE_PENDING) { + WOLFSSL_MSG("Event already pending!"); + return BAD_COND_E; + } + + XMEMSET(event, 0, sizeof(WOLF_EVENT)); + event->type = type; + event->context = context; + + return 0; +} + +int wolfEvent_Poll(WOLF_EVENT* event, WOLF_EVENT_FLAG flags) +{ + int ret = BAD_COND_E; + + /* Check hardware */ +#ifdef WOLFSSL_ASYNC_CRYPT + if (event->type >= WOLF_EVENT_TYPE_ASYNC_FIRST && + event->type <= WOLF_EVENT_TYPE_ASYNC_LAST) + { + ret = wolfAsync_EventPoll(event, flags); + } +#endif /* WOLFSSL_ASYNC_CRYPT */ + + return ret; +} + +int wolfEventQueue_Init(WOLF_EVENT_QUEUE* queue) +{ + int ret = 0; + + if (queue == NULL) { + return BAD_FUNC_ARG; + } + + XMEMSET(queue, 0, sizeof(WOLF_EVENT_QUEUE)); +#ifndef SINGLE_THREADED + ret = wc_InitMutex(&queue->lock); +#endif + return ret; +} + + +int wolfEventQueue_Push(WOLF_EVENT_QUEUE* queue, WOLF_EVENT* event) +{ + int ret; + + if (queue == NULL || event == NULL) { + return BAD_FUNC_ARG; + } + +#ifndef SINGLE_THREADED + if ((ret = wc_LockMutex(&queue->lock)) != 0) { + return ret; + } +#endif + + ret = wolfEventQueue_Add(queue, event); + +#ifndef SINGLE_THREADED + wc_UnLockMutex(&queue->lock); +#endif + + return ret; +} + +int wolfEventQueue_Pop(WOLF_EVENT_QUEUE* queue, WOLF_EVENT** event) +{ + int ret = 0; + + if (queue == NULL || event == NULL) { + return BAD_FUNC_ARG; + } + +#ifndef SINGLE_THREADED + /* In single threaded mode "event_queue.lock" doesn't exist */ + if ((ret = wc_LockMutex(&queue->lock)) != 0) { + return ret; + } +#endif + + /* Pop first item off queue */ + *event = queue->head; + ret = wolfEventQueue_Remove(queue, *event); + +#ifndef SINGLE_THREADED + wc_UnLockMutex(&queue->lock); +#endif + + return ret; +} + +/* assumes queue is locked by caller */ +int wolfEventQueue_Add(WOLF_EVENT_QUEUE* queue, WOLF_EVENT* event) +{ + if (queue == NULL || event == NULL) { + return BAD_FUNC_ARG; + } + + event->next = NULL; /* added to end */ + event->prev = NULL; + if (queue->tail == NULL) { + queue->head = event; + } + else { + queue->tail->next = event; + event->prev = queue->tail; + } + queue->tail = event; /* add to the end either way */ + queue->count++; + + return 0; +} + +/* assumes queue is locked by caller */ +int wolfEventQueue_Remove(WOLF_EVENT_QUEUE* queue, WOLF_EVENT* event) +{ + int ret = 0; + + if (queue == NULL || event == NULL) { + return BAD_FUNC_ARG; + } + + if (event == queue->head && event == queue->tail) { + queue->head = NULL; + queue->tail = NULL; + } + else if (event == queue->head) { + queue->head = event->next; + queue->head->prev = NULL; + } + else if (event == queue->tail) { + queue->tail = event->prev; + queue->tail->next = NULL; + } + else { + WOLF_EVENT* next = event->next; + WOLF_EVENT* prev = event->prev; + next->prev = prev; + prev->next = next; + } + queue->count--; + + return ret; +} + +int wolfEventQueue_Poll(WOLF_EVENT_QUEUE* queue, void* context_filter, + WOLF_EVENT** events, int maxEvents, WOLF_EVENT_FLAG flags, int* eventCount) +{ + WOLF_EVENT* event; + int ret = 0, count = 0; + + if (queue == NULL) { + return BAD_FUNC_ARG; + } + +#ifndef SINGLE_THREADED + /* In single threaded mode "event_queue.lock" doesn't exist */ + if ((ret = wc_LockMutex(&queue->lock)) != 0) { + return ret; + } +#endif + + /* itterate event queue */ + for (event = queue->head; event != NULL; event = event->next) + { + /* optional filter based on context */ + if (context_filter == NULL || event->context == context_filter) { + + /* poll event */ + ret = wolfEvent_Poll(event, flags); + if (ret < 0) break; /* exit for */ + + /* If event is done then process */ + if (event->state == WOLF_EVENT_STATE_DONE) { + /* remove from queue */ + ret = wolfEventQueue_Remove(queue, event); + if (ret < 0) break; /* exit for */ + + /* return pointer in 'events' arg */ + if (events) { + events[count] = event; /* return pointer */ + } + count++; + + /* check to make sure our event list isn't full */ + if (events && count >= maxEvents) { + break; /* exit for */ + } + } + } + } + +#ifndef SINGLE_THREADED + wc_UnLockMutex(&queue->lock); +#endif + + /* return number of properly populated events */ + if (eventCount) { + *eventCount = count; + } + + return ret; +} + +int wolfEventQueue_Count(WOLF_EVENT_QUEUE* queue) +{ + int ret; + + if (queue == NULL) { + return BAD_FUNC_ARG; + } + +#ifndef SINGLE_THREADED + /* In single threaded mode "event_queue.lock" doesn't exist */ + if ((ret = wc_LockMutex(&queue->lock)) != 0) { + return ret; + } +#endif + + ret = queue->count; + +#ifndef SINGLE_THREADED + wc_UnLockMutex(&queue->lock); +#endif + + return ret; +} + +void wolfEventQueue_Free(WOLF_EVENT_QUEUE* queue) +{ + if (queue) { + #ifndef SINGLE_THREADED + wc_FreeMutex(&queue->lock); + #endif + } +} + +#endif /* HAVE_WOLF_EVENT */ diff --git a/beken_os/beken378/func/wolfssl/wolfcrypt/src/wolfmath.c b/beken_os/beken378/func/wolfssl/wolfcrypt/src/wolfmath.c new file mode 100755 index 0000000..04863dc --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfcrypt/src/wolfmath.c @@ -0,0 +1,337 @@ +/* wolfmath.c + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +/* common functions for either math library */ + +#ifdef HAVE_CONFIG_H + #include +#endif + +/* in case user set USE_FAST_MATH there */ +#include + +#include + +#include +#include + +#if defined(USE_FAST_MATH) || !defined(NO_BIG_INT) + +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif + +#ifdef NO_INLINE + #include +#else + #define WOLFSSL_MISC_INCLUDED + #include +#endif + + +#if !defined(WC_NO_CACHE_RESISTANT) && \ + ((defined(HAVE_ECC) && defined(ECC_TIMING_RESISTANT)) || \ + (defined(USE_FAST_MATH) && defined(TFM_TIMING_RESISTANT))) + + /* all off / all on pointer addresses for constant calculations */ + /* ecc.c uses same table */ + const wolfssl_word wc_off_on_addr[2] = + { + #if defined(WC_64BIT_CPU) + W64LIT(0x0000000000000000), + W64LIT(0xffffffffffffffff) + #elif defined(WC_16BIT_CPU) + 0x0000U, + 0xffffU + #else + /* 32 bit */ + 0x00000000U, + 0xffffffffU + #endif + }; +#endif + + +int get_digit_count(mp_int* a) +{ + if (a == NULL) + return 0; + + return a->used; +} + +mp_digit get_digit(mp_int* a, int n) +{ + if (a == NULL) + return 0; + + return (n >= a->used || n < 0) ? 0 : a->dp[n]; +} + +#ifndef WC_NO_RNG +int get_rand_digit(WC_RNG* rng, mp_digit* d) +{ + return wc_RNG_GenerateBlock(rng, (byte*)d, sizeof(mp_digit)); +} + +#ifdef WC_RSA_BLINDING +int mp_rand(mp_int* a, int digits, WC_RNG* rng) +{ + int ret = 0; + DECLARE_VAR(d, mp_digit, 1, rng ? rng->heap : NULL); + + if (rng == NULL) { + ret = MISSING_RNG_E; goto exit; + } + + if (a == NULL + #ifdef WOLFSSL_ASYNC_CRYPT + || d == NULL + #endif + ) { + ret = BAD_FUNC_ARG; goto exit; + } + + mp_zero(a); + if (digits <= 0) { + ret = MP_OKAY; goto exit; + } + + /* first place a random non-zero digit */ + do { + ret = get_rand_digit(rng, d); + if (ret != 0) { + goto exit; + } + } while (*d == 0); + + if ((ret = mp_add_d(a, *d, a)) != MP_OKAY) { + goto exit; + } + + while (--digits > 0) { + if ((ret = mp_lshd(a, 1)) != MP_OKAY) { + goto exit; + } + if ((ret = get_rand_digit(rng, d)) != 0) { + goto exit; + } + if ((ret = mp_add_d(a, *d, a)) != MP_OKAY) { + goto exit; + } + } + +exit: + FREE_VAR(d, rng ? rng->heap : NULL); + + return ret; +} +#endif /* WC_RSA_BLINDING */ +#endif + +/* export an mp_int as unsigned char or hex string + * encType is WC_TYPE_UNSIGNED_BIN or WC_TYPE_HEX_STR + * return MP_OKAY on success */ +int wc_export_int(mp_int* mp, byte* buf, word32* len, word32 keySz, + int encType) +{ + int err; + + if (mp == NULL) + return BAD_FUNC_ARG; + + /* check buffer size */ + if (*len < keySz) { + *len = keySz; + return BUFFER_E; + } + + *len = keySz; + XMEMSET(buf, 0, *len); + + if (encType == WC_TYPE_HEX_STR) { + #ifdef WC_MP_TO_RADIX + err = mp_tohex(mp, (char*)buf); + #else + err = NOT_COMPILED_IN; + #endif + } + else { + err = mp_to_unsigned_bin(mp, buf + (keySz - mp_unsigned_bin_size(mp))); + } + + return err; +} + + +#ifdef HAVE_WOLF_BIGINT +void wc_bigint_init(WC_BIGINT* a) +{ + if (a != NULL) { + a->buf = NULL; + a->len = 0; + a->heap = NULL; + } +} + +int wc_bigint_alloc(WC_BIGINT* a, word32 sz) +{ + int err = MP_OKAY; + + if (a == NULL) + return BAD_FUNC_ARG; + + if (sz > 0) { + if (a->buf && sz > a->len) { + wc_bigint_free(a); + } + if (a->buf == NULL) { + a->buf = (byte*)XMALLOC(sz, a->heap, DYNAMIC_TYPE_WOLF_BIGINT); + } + if (a->buf == NULL) { + err = MP_MEM; + } + else { + XMEMSET(a->buf, 0, sz); + } + } + a->len = sz; + + return err; +} + +/* assumes input is big endian format */ +int wc_bigint_from_unsigned_bin(WC_BIGINT* a, const byte* in, word32 inlen) +{ + int err; + + if (a == NULL || in == NULL || inlen == 0) + return BAD_FUNC_ARG; + + err = wc_bigint_alloc(a, inlen); + if (err == 0) { + XMEMCPY(a->buf, in, inlen); + } + + return err; +} + +int wc_bigint_to_unsigned_bin(WC_BIGINT* a, byte* out, word32* outlen) +{ + word32 sz; + + if (a == NULL || out == NULL || outlen == NULL || *outlen == 0) + return BAD_FUNC_ARG; + + /* trim to fit into output buffer */ + sz = a->len; + if (a->len > *outlen) { + WOLFSSL_MSG("wc_bigint_export: Truncating output"); + sz = *outlen; + } + + if (a->buf) { + XMEMCPY(out, a->buf, sz); + } + + *outlen = sz; + + return MP_OKAY; +} + +void wc_bigint_zero(WC_BIGINT* a) +{ + if (a && a->buf) { + ForceZero(a->buf, a->len); + } +} + +void wc_bigint_free(WC_BIGINT* a) +{ + if (a) { + if (a->buf) { + XFREE(a->buf, a->heap, DYNAMIC_TYPE_WOLF_BIGINT); + } + a->buf = NULL; + a->len = 0; + } +} + +/* sz: make sure the buffer is at least that size and zero padded. + * A `sz == 0` will use the size of `src`. + * The calulcates sz is stored into dst->len in `wc_bigint_alloc`. + */ +int wc_mp_to_bigint_sz(mp_int* src, WC_BIGINT* dst, word32 sz) +{ + int err; + word32 x, y; + + if (src == NULL || dst == NULL) + return BAD_FUNC_ARG; + + /* get size of source */ + x = mp_unsigned_bin_size(src); + if (sz < x) + sz = x; + + /* make sure destination is allocated and large enough */ + err = wc_bigint_alloc(dst, sz); + if (err == MP_OKAY) { + + /* leading zero pad */ + y = sz - x; + XMEMSET(dst->buf, 0, y); + + /* export src as unsigned bin to destination buf */ + err = mp_to_unsigned_bin(src, dst->buf + y); + } + + return err; +} + +int wc_mp_to_bigint(mp_int* src, WC_BIGINT* dst) +{ + if (src == NULL || dst == NULL) + return BAD_FUNC_ARG; + + return wc_mp_to_bigint_sz(src, dst, 0); +} + +int wc_bigint_to_mp(WC_BIGINT* src, mp_int* dst) +{ + int err; + + if (src == NULL || dst == NULL) + return BAD_FUNC_ARG; + + if (src->buf == NULL) + return BAD_FUNC_ARG; + + err = mp_read_unsigned_bin(dst, src->buf, src->len); + wc_bigint_free(src); + + return err; +} + +#endif /* HAVE_WOLF_BIGINT */ + +#endif /* USE_FAST_MATH || !NO_BIG_INT */ diff --git a/beken_os/beken378/func/wolfssl/wolfssl/callbacks.h b/beken_os/beken378/func/wolfssl/wolfssl/callbacks.h new file mode 100755 index 0000000..619f8d2 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/callbacks.h @@ -0,0 +1,91 @@ +/* callbacks.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifndef WOLFSSL_CALLBACKS_H +#define WOLFSSL_CALLBACKS_H + +#include + +#ifdef __cplusplus + extern "C" { +#endif + + +enum { /* CALLBACK CONTSTANTS */ + MAX_PACKETNAME_SZ = 24, + MAX_CIPHERNAME_SZ = 24, + MAX_TIMEOUT_NAME_SZ = 24, + MAX_PACKETS_HANDSHAKE = 14, /* 12 for client auth plus 2 alerts */ + MAX_VALUE_SZ = 128, /* all handshake packets but Cert should + fit here */ +}; + +struct WOLFSSL; + +typedef struct handShakeInfo_st { + struct WOLFSSL* ssl; + char cipherName[MAX_CIPHERNAME_SZ + 1]; /* negotiated cipher */ + char packetNames[MAX_PACKETS_HANDSHAKE][MAX_PACKETNAME_SZ + 1]; + /* SSL packet names */ + int numberPackets; /* actual # of packets */ + int negotiationError; /* cipher/parameter err */ +} HandShakeInfo; + + +#if defined(HAVE_SYS_TIME_H) && !defined(NO_TIMEVAL) + typedef struct timeval Timeval; +#else /* HAVE_SYS_TIME_H */ + /* Define the Timeval explicitly. */ + typedef struct { + long tv_sec; /* Seconds. */ + long tv_usec; /* Microseconds. */ + } Timeval; +#endif /* HAVE_SYS_TIME_H */ + + +typedef struct packetInfo_st { + char packetName[MAX_PACKETNAME_SZ + 1]; /* SSL packet name */ + Timeval timestamp; /* when it occurred */ + unsigned char value[MAX_VALUE_SZ]; /* if fits, it's here */ + unsigned char* bufferValue; /* otherwise here (non 0) */ + int valueSz; /* sz of value or buffer */ +} PacketInfo; + + +typedef struct timeoutInfo_st { + char timeoutName[MAX_TIMEOUT_NAME_SZ + 1]; /* timeout Name */ + int flags; /* for future use */ + int numberPackets; /* actual # of packets */ + PacketInfo packets[MAX_PACKETS_HANDSHAKE]; /* list of all packets */ + Timeval timeoutValue; /* timer that caused it */ +} TimeoutInfo; + + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + + +#endif /* WOLFSSL_CALLBACKS_H */ + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/certs_test.h b/beken_os/beken378/func/wolfssl/wolfssl/certs_test.h new file mode 100755 index 0000000..deefb57 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/certs_test.h @@ -0,0 +1,3207 @@ +/* certs_test.h */ + +#ifndef WOLFSSL_CERTS_TEST_H +#define WOLFSSL_CERTS_TEST_H + +#ifdef USE_CERT_BUFFERS_1024 + +/* ./certs/1024/client-key.der, 1024-bit */ +static const unsigned char client_key_der_1024[] = +{ + 0x30, 0x82, 0x02, 0x5C, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, + 0x00, 0xBC, 0x73, 0x0E, 0xA8, 0x49, 0xF3, 0x74, 0xA2, 0xA9, + 0xEF, 0x18, 0xA5, 0xDA, 0x55, 0x99, 0x21, 0xF9, 0xC8, 0xEC, + 0xB3, 0x6D, 0x48, 0xE5, 0x35, 0x35, 0x75, 0x77, 0x37, 0xEC, + 0xD1, 0x61, 0x90, 0x5F, 0x3E, 0xD9, 0xE4, 0xD5, 0xDF, 0x94, + 0xCA, 0xC1, 0xA9, 0xD7, 0x19, 0xDA, 0x86, 0xC9, 0xE8, 0x4D, + 0xC4, 0x61, 0x36, 0x82, 0xFE, 0xAB, 0xAD, 0x7E, 0x77, 0x25, + 0xBB, 0x8D, 0x11, 0xA5, 0xBC, 0x62, 0x3A, 0xA8, 0x38, 0xCC, + 0x39, 0xA2, 0x04, 0x66, 0xB4, 0xF7, 0xF7, 0xF3, 0xAA, 0xDA, + 0x4D, 0x02, 0x0E, 0xBB, 0x5E, 0x8D, 0x69, 0x48, 0xDC, 0x77, + 0xC9, 0x28, 0x0E, 0x22, 0xE9, 0x6B, 0xA4, 0x26, 0xBA, 0x4C, + 0xE8, 0xC1, 0xFD, 0x4A, 0x6F, 0x2B, 0x1F, 0xEF, 0x8A, 0xAE, + 0xF6, 0x90, 0x62, 0xE5, 0x64, 0x1E, 0xEB, 0x2B, 0x3C, 0x67, + 0xC8, 0xDC, 0x27, 0x00, 0xF6, 0x91, 0x68, 0x65, 0xA9, 0x02, + 0x03, 0x01, 0x00, 0x01, 0x02, 0x81, 0x80, 0x13, 0x97, 0xEA, + 0xE8, 0x38, 0x78, 0x25, 0xA2, 0x5C, 0x04, 0xCE, 0x0D, 0x40, + 0x7C, 0x31, 0xE5, 0xC4, 0x70, 0xCD, 0x9B, 0x82, 0x3B, 0x58, + 0x09, 0x86, 0x3B, 0x66, 0x5F, 0xDC, 0x31, 0x90, 0xF1, 0x4F, + 0xD5, 0xDB, 0x15, 0xDD, 0xDE, 0xD7, 0x3B, 0x95, 0x93, 0x31, + 0x18, 0x31, 0x0E, 0x5E, 0xA3, 0xD6, 0xA2, 0x1A, 0x71, 0x6E, + 0x81, 0x48, 0x1C, 0x4B, 0xCF, 0xDB, 0x8E, 0x7A, 0x86, 0x61, + 0x32, 0xDC, 0xFB, 0x55, 0xC1, 0x16, 0x6D, 0x27, 0x92, 0x24, + 0x45, 0x8B, 0xF1, 0xB8, 0x48, 0xB1, 0x4B, 0x1D, 0xAC, 0xDE, + 0xDA, 0xDD, 0x8E, 0x2F, 0xC2, 0x91, 0xFB, 0xA5, 0xA9, 0x6E, + 0xF8, 0x3A, 0x6A, 0xF1, 0xFD, 0x50, 0x18, 0xEF, 0x9F, 0xE7, + 0xC3, 0xCA, 0x78, 0xEA, 0x56, 0xD3, 0xD3, 0x72, 0x5B, 0x96, + 0xDD, 0x4E, 0x06, 0x4E, 0x3A, 0xC3, 0xD9, 0xBE, 0x72, 0xB6, + 0x65, 0x07, 0x07, 0x4C, 0x01, 0x02, 0x41, 0x00, 0xFA, 0x47, + 0xD4, 0x7A, 0x7C, 0x92, 0x3C, 0x55, 0xEF, 0x81, 0xF0, 0x41, + 0x30, 0x2D, 0xA3, 0xCF, 0x8F, 0x1C, 0xE6, 0x87, 0x27, 0x05, + 0x70, 0x0D, 0xDF, 0x98, 0x35, 0xD6, 0xF1, 0x8B, 0x38, 0x2F, + 0x24, 0xB5, 0xD0, 0x84, 0xB6, 0x79, 0x4F, 0x71, 0x29, 0x94, + 0x5A, 0xF0, 0x64, 0x6A, 0xAC, 0xE7, 0x72, 0xC6, 0xED, 0x4D, + 0x59, 0x98, 0x3E, 0x67, 0x3A, 0xF3, 0x74, 0x2C, 0xF9, 0x61, + 0x17, 0x69, 0x02, 0x41, 0x00, 0xC0, 0xC1, 0x82, 0x0D, 0x0C, + 0xEB, 0xC6, 0x2F, 0xDC, 0x92, 0xF9, 0x9D, 0x82, 0x1A, 0x31, + 0xE9, 0xE9, 0xF7, 0x4B, 0xF2, 0x82, 0x87, 0x1C, 0xEE, 0x16, + 0x6A, 0xD1, 0x1D, 0x18, 0x82, 0x70, 0xF3, 0xC0, 0xB6, 0x2F, + 0xF6, 0xF3, 0xF7, 0x1D, 0xF1, 0x86, 0x23, 0xC8, 0x4E, 0xEB, + 0x8F, 0x56, 0x8E, 0x8F, 0xF5, 0xBF, 0xF1, 0xF7, 0x2B, 0xB5, + 0xCC, 0x3D, 0xC6, 0x57, 0x39, 0x0C, 0x1B, 0x54, 0x41, 0x02, + 0x41, 0x00, 0x9D, 0x7E, 0x05, 0xDE, 0xED, 0xF4, 0xB7, 0xB2, + 0xFB, 0xFC, 0x30, 0x4B, 0x55, 0x1D, 0xE3, 0x2F, 0x01, 0x47, + 0x96, 0x69, 0x05, 0xCD, 0x0E, 0x2E, 0x2C, 0xBD, 0x83, 0x63, + 0xB6, 0xAB, 0x7C, 0xB7, 0x6D, 0xCA, 0x5B, 0x64, 0xA7, 0xCE, + 0xBE, 0x86, 0xDF, 0x3B, 0x53, 0xDE, 0x61, 0xD2, 0x1E, 0xEB, + 0xA5, 0xF6, 0x37, 0xED, 0xAC, 0xAB, 0x78, 0xD9, 0x4C, 0xE7, + 0x55, 0xFB, 0xD7, 0x11, 0x99, 0xC1, 0x02, 0x40, 0x18, 0x98, + 0x18, 0x29, 0xE6, 0x1E, 0x27, 0x39, 0x70, 0x21, 0x68, 0xAC, + 0x0A, 0x2F, 0xA1, 0x72, 0xC1, 0x21, 0x86, 0x95, 0x38, 0xC6, + 0x58, 0x90, 0xA0, 0x57, 0x9C, 0xBA, 0xE3, 0xA7, 0xB1, 0x15, + 0xC8, 0xDE, 0xF6, 0x1B, 0xC2, 0x61, 0x23, 0x76, 0xEF, 0xB0, + 0x9D, 0x1C, 0x44, 0xBE, 0x13, 0x43, 0x39, 0x67, 0x17, 0xC8, + 0x9D, 0xCA, 0xFB, 0xF5, 0x45, 0x64, 0x8B, 0x38, 0x82, 0x2C, + 0xF2, 0x81, 0x02, 0x40, 0x39, 0x89, 0xE5, 0x9C, 0x19, 0x55, + 0x30, 0xBA, 0xB7, 0x48, 0x8C, 0x48, 0x14, 0x0E, 0xF4, 0x9F, + 0x7E, 0x77, 0x97, 0x43, 0xE1, 0xB4, 0x19, 0x35, 0x31, 0x23, + 0x75, 0x9C, 0x3B, 0x44, 0xAD, 0x69, 0x12, 0x56, 0xEE, 0x00, + 0x61, 0x64, 0x16, 0x66, 0xD3, 0x7C, 0x74, 0x2B, 0x15, 0xB4, + 0xA2, 0xFE, 0xBF, 0x08, 0x6B, 0x1A, 0x5D, 0x3F, 0x90, 0x12, + 0xB1, 0x05, 0x86, 0x31, 0x29, 0xDB, 0xD9, 0xE2 +}; +static const int sizeof_client_key_der_1024 = sizeof(client_key_der_1024); + +/* ./certs/1024/client-keyPub.der, 1024-bit */ +static const unsigned char client_keypub_der_1024[] = +{ + 0x30, 0x81, 0x9F, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, + 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x81, + 0x8D, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, 0xBC, + 0x73, 0x0E, 0xA8, 0x49, 0xF3, 0x74, 0xA2, 0xA9, 0xEF, 0x18, + 0xA5, 0xDA, 0x55, 0x99, 0x21, 0xF9, 0xC8, 0xEC, 0xB3, 0x6D, + 0x48, 0xE5, 0x35, 0x35, 0x75, 0x77, 0x37, 0xEC, 0xD1, 0x61, + 0x90, 0x5F, 0x3E, 0xD9, 0xE4, 0xD5, 0xDF, 0x94, 0xCA, 0xC1, + 0xA9, 0xD7, 0x19, 0xDA, 0x86, 0xC9, 0xE8, 0x4D, 0xC4, 0x61, + 0x36, 0x82, 0xFE, 0xAB, 0xAD, 0x7E, 0x77, 0x25, 0xBB, 0x8D, + 0x11, 0xA5, 0xBC, 0x62, 0x3A, 0xA8, 0x38, 0xCC, 0x39, 0xA2, + 0x04, 0x66, 0xB4, 0xF7, 0xF7, 0xF3, 0xAA, 0xDA, 0x4D, 0x02, + 0x0E, 0xBB, 0x5E, 0x8D, 0x69, 0x48, 0xDC, 0x77, 0xC9, 0x28, + 0x0E, 0x22, 0xE9, 0x6B, 0xA4, 0x26, 0xBA, 0x4C, 0xE8, 0xC1, + 0xFD, 0x4A, 0x6F, 0x2B, 0x1F, 0xEF, 0x8A, 0xAE, 0xF6, 0x90, + 0x62, 0xE5, 0x64, 0x1E, 0xEB, 0x2B, 0x3C, 0x67, 0xC8, 0xDC, + 0x27, 0x00, 0xF6, 0x91, 0x68, 0x65, 0xA9, 0x02, 0x03, 0x01, + 0x00, 0x01 +}; +static const int sizeof_client_keypub_der_1024 = sizeof(client_keypub_der_1024); + +/* ./certs/1024/client-cert.der, 1024-bit */ +static const unsigned char client_cert_der_1024[] = +{ + 0x30, 0x82, 0x03, 0xC5, 0x30, 0x82, 0x03, 0x2E, 0xA0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0xBB, 0xD3, 0x10, 0x03, + 0xE6, 0x9D, 0x28, 0x03, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, + 0x81, 0x9E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x08, 0x0C, 0x07, 0x4D, 0x6F, 0x6E, 0x74, + 0x61, 0x6E, 0x61, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, + 0x04, 0x07, 0x0C, 0x07, 0x42, 0x6F, 0x7A, 0x65, 0x6D, 0x61, + 0x6E, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0C, 0x77, 0x6F, 0x6C, 0x66, 0x53, 0x53, 0x4C, 0x5F, + 0x31, 0x30, 0x32, 0x34, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, + 0x55, 0x04, 0x0B, 0x0C, 0x10, 0x50, 0x72, 0x6F, 0x67, 0x72, + 0x61, 0x6D, 0x6D, 0x69, 0x6E, 0x67, 0x2D, 0x31, 0x30, 0x32, + 0x34, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, + 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, + 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, + 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, + 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, + 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x38, 0x30, 0x34, 0x31, 0x33, + 0x31, 0x35, 0x32, 0x33, 0x30, 0x39, 0x5A, 0x17, 0x0D, 0x32, + 0x31, 0x30, 0x31, 0x30, 0x37, 0x31, 0x35, 0x32, 0x33, 0x30, + 0x39, 0x5A, 0x30, 0x81, 0x9E, 0x31, 0x0B, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, + 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0C, 0x07, 0x4D, + 0x6F, 0x6E, 0x74, 0x61, 0x6E, 0x61, 0x31, 0x10, 0x30, 0x0E, + 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x42, 0x6F, 0x7A, + 0x65, 0x6D, 0x61, 0x6E, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, + 0x55, 0x04, 0x0A, 0x0C, 0x0C, 0x77, 0x6F, 0x6C, 0x66, 0x53, + 0x53, 0x4C, 0x5F, 0x31, 0x30, 0x32, 0x34, 0x31, 0x19, 0x30, + 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x10, 0x50, 0x72, + 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x6D, 0x69, 0x6E, 0x67, 0x2D, + 0x31, 0x30, 0x32, 0x34, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, + 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, + 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, + 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, + 0x6F, 0x40, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, + 0x63, 0x6F, 0x6D, 0x30, 0x81, 0x9F, 0x30, 0x0D, 0x06, 0x09, + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, + 0x00, 0x03, 0x81, 0x8D, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, + 0x81, 0x00, 0xBC, 0x73, 0x0E, 0xA8, 0x49, 0xF3, 0x74, 0xA2, + 0xA9, 0xEF, 0x18, 0xA5, 0xDA, 0x55, 0x99, 0x21, 0xF9, 0xC8, + 0xEC, 0xB3, 0x6D, 0x48, 0xE5, 0x35, 0x35, 0x75, 0x77, 0x37, + 0xEC, 0xD1, 0x61, 0x90, 0x5F, 0x3E, 0xD9, 0xE4, 0xD5, 0xDF, + 0x94, 0xCA, 0xC1, 0xA9, 0xD7, 0x19, 0xDA, 0x86, 0xC9, 0xE8, + 0x4D, 0xC4, 0x61, 0x36, 0x82, 0xFE, 0xAB, 0xAD, 0x7E, 0x77, + 0x25, 0xBB, 0x8D, 0x11, 0xA5, 0xBC, 0x62, 0x3A, 0xA8, 0x38, + 0xCC, 0x39, 0xA2, 0x04, 0x66, 0xB4, 0xF7, 0xF7, 0xF3, 0xAA, + 0xDA, 0x4D, 0x02, 0x0E, 0xBB, 0x5E, 0x8D, 0x69, 0x48, 0xDC, + 0x77, 0xC9, 0x28, 0x0E, 0x22, 0xE9, 0x6B, 0xA4, 0x26, 0xBA, + 0x4C, 0xE8, 0xC1, 0xFD, 0x4A, 0x6F, 0x2B, 0x1F, 0xEF, 0x8A, + 0xAE, 0xF6, 0x90, 0x62, 0xE5, 0x64, 0x1E, 0xEB, 0x2B, 0x3C, + 0x67, 0xC8, 0xDC, 0x27, 0x00, 0xF6, 0x91, 0x68, 0x65, 0xA9, + 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x82, 0x01, 0x07, 0x30, + 0x82, 0x01, 0x03, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, + 0x04, 0x16, 0x04, 0x14, 0x81, 0x69, 0x0F, 0xF8, 0xDF, 0xDD, + 0xCF, 0x34, 0x29, 0xD5, 0x67, 0x75, 0x71, 0x85, 0xC7, 0x75, + 0x10, 0x69, 0x59, 0xEC, 0x30, 0x81, 0xD3, 0x06, 0x03, 0x55, + 0x1D, 0x23, 0x04, 0x81, 0xCB, 0x30, 0x81, 0xC8, 0x80, 0x14, + 0x81, 0x69, 0x0F, 0xF8, 0xDF, 0xDD, 0xCF, 0x34, 0x29, 0xD5, + 0x67, 0x75, 0x71, 0x85, 0xC7, 0x75, 0x10, 0x69, 0x59, 0xEC, + 0xA1, 0x81, 0xA4, 0xA4, 0x81, 0xA1, 0x30, 0x81, 0x9E, 0x31, + 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0C, 0x07, 0x4D, 0x6F, 0x6E, 0x74, 0x61, 0x6E, 0x61, + 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, + 0x07, 0x42, 0x6F, 0x7A, 0x65, 0x6D, 0x61, 0x6E, 0x31, 0x15, + 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0C, 0x77, + 0x6F, 0x6C, 0x66, 0x53, 0x53, 0x4C, 0x5F, 0x31, 0x30, 0x32, + 0x34, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x0C, 0x10, 0x50, 0x72, 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x6D, + 0x69, 0x6E, 0x67, 0x2D, 0x31, 0x30, 0x32, 0x34, 0x31, 0x18, + 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x77, + 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, + 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, + 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, 0x6F, 0x6C, 0x66, + 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x82, 0x09, 0x00, + 0xBB, 0xD3, 0x10, 0x03, 0xE6, 0x9D, 0x28, 0x03, 0x30, 0x0C, + 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, + 0x01, 0xFF, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, + 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03, 0x81, 0x81, + 0x00, 0x84, 0x99, 0xD9, 0xE5, 0x37, 0xC4, 0x44, 0x7D, 0xCE, + 0x29, 0xB8, 0xB6, 0x80, 0x0E, 0xEA, 0xA3, 0xE2, 0xFA, 0xA2, + 0x2F, 0x5C, 0xD2, 0x4A, 0x85, 0x67, 0xB9, 0x8B, 0xFA, 0x9F, + 0x7D, 0xDA, 0x6D, 0x85, 0x2A, 0xC2, 0x20, 0xF3, 0x18, 0xC8, + 0xD4, 0x6B, 0x26, 0xB2, 0x7A, 0x68, 0xE7, 0x82, 0x52, 0x87, + 0xE7, 0x0C, 0x5B, 0x08, 0x47, 0x7A, 0x55, 0xA5, 0x0D, 0xFA, + 0x72, 0xCE, 0x6B, 0xA1, 0xB2, 0xAE, 0x5A, 0xA1, 0x63, 0xFF, + 0x68, 0xDB, 0xE5, 0x49, 0xEF, 0xF1, 0x0E, 0x98, 0x96, 0x09, + 0xB5, 0x04, 0x5F, 0xD4, 0x0A, 0x9B, 0x8A, 0xAF, 0xD2, 0x31, + 0x1F, 0x95, 0xE5, 0x0F, 0xA8, 0xCD, 0xBB, 0xA1, 0x2D, 0x64, + 0xB0, 0xB7, 0xEE, 0x47, 0xA7, 0x58, 0xD9, 0xC7, 0xDB, 0xB0, + 0x92, 0xBB, 0xAA, 0xCF, 0xB8, 0x8A, 0x04, 0x5B, 0x0F, 0x9F, + 0x3E, 0xE0, 0xD2, 0x42, 0x52, 0xBD, 0x5D, 0xA7, 0x48 +}; +static const int sizeof_client_cert_der_1024 = sizeof(client_cert_der_1024); + +/* ./certs/1024/dh1024.der, 1024-bit */ +static const unsigned char dh_key_der_1024[] = +{ + 0x30, 0x81, 0x87, 0x02, 0x81, 0x81, 0x00, 0xA4, 0xD2, 0xB8, + 0x6E, 0x78, 0xF5, 0xD9, 0xED, 0x2D, 0x7C, 0xDD, 0xB6, 0x16, + 0x86, 0x5A, 0x4B, 0x05, 0x76, 0x90, 0xDD, 0x66, 0x61, 0xB9, + 0x6D, 0x52, 0xA7, 0x1C, 0xAF, 0x62, 0xC6, 0x69, 0x47, 0x7B, + 0x39, 0xF2, 0xFB, 0x94, 0xEC, 0xBC, 0x79, 0xFF, 0x24, 0x5E, + 0xEF, 0x79, 0xBB, 0x59, 0xB2, 0xFC, 0xCA, 0x07, 0xD6, 0xF4, + 0xE9, 0x34, 0xF7, 0xE8, 0x38, 0xE7, 0xD7, 0x33, 0x44, 0x1D, + 0xA3, 0x64, 0x76, 0x1A, 0x84, 0x97, 0x54, 0x74, 0x40, 0x84, + 0x1F, 0x15, 0xFE, 0x7C, 0x25, 0x2A, 0x2B, 0x25, 0xFD, 0x9E, + 0xC1, 0x89, 0x33, 0x8C, 0x39, 0x25, 0x2B, 0x40, 0xE6, 0xCD, + 0xF8, 0xA8, 0xA1, 0x8A, 0x53, 0xC6, 0x47, 0xB2, 0xA0, 0xD7, + 0x8F, 0xEB, 0x2E, 0x60, 0x0A, 0x0D, 0x4B, 0xF8, 0xB4, 0x94, + 0x8C, 0x63, 0x0A, 0xAD, 0xC7, 0x10, 0xEA, 0xC7, 0xA1, 0xB9, + 0x9D, 0xF2, 0xA8, 0x37, 0x73, 0x02, 0x01, 0x02 +}; +static const int sizeof_dh_key_der_1024 = sizeof(dh_key_der_1024); + +/* ./certs/1024/dsa1024.der, 1024-bit */ +static const unsigned char dsa_key_der_1024[] = +{ + 0x30, 0x82, 0x01, 0xBC, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, + 0x00, 0xF7, 0x4B, 0xF9, 0xBB, 0x15, 0x98, 0xEB, 0xDD, 0xDE, + 0x1E, 0x4E, 0x71, 0x88, 0x85, 0xF2, 0xB7, 0xBA, 0xE2, 0x4A, + 0xDA, 0x76, 0x40, 0xCD, 0x69, 0x48, 0x9E, 0x83, 0x7C, 0x11, + 0xF7, 0x65, 0x31, 0x78, 0xF5, 0x25, 0x2D, 0xF7, 0xB7, 0xF8, + 0x52, 0x3F, 0xBE, 0xD8, 0xB6, 0xC5, 0xFE, 0x18, 0x15, 0x5B, + 0xB9, 0xD5, 0x92, 0x86, 0xBC, 0xB2, 0x17, 0x7C, 0xD8, 0xB0, + 0xBE, 0xA0, 0x7C, 0xF2, 0xD5, 0x73, 0x7A, 0x58, 0x8F, 0x8D, + 0xE5, 0x4A, 0x00, 0x99, 0x83, 0x4A, 0xC0, 0x9E, 0x16, 0x09, + 0xA1, 0x10, 0x34, 0xD5, 0x19, 0xBB, 0x63, 0xE3, 0xDD, 0x83, + 0x74, 0x7F, 0x10, 0xCA, 0x73, 0x75, 0xEE, 0x31, 0x4A, 0xDD, + 0x9F, 0xE0, 0x02, 0x6A, 0x9D, 0xEE, 0xB2, 0x4B, 0xA7, 0x6B, + 0x2A, 0x6C, 0xC7, 0x86, 0x77, 0xE8, 0x04, 0x15, 0xDC, 0x92, + 0xB4, 0x7A, 0x29, 0x1F, 0x4E, 0x83, 0x63, 0x85, 0x55, 0x02, + 0x15, 0x00, 0xD2, 0x05, 0xE4, 0x73, 0xFB, 0xC1, 0x99, 0xC5, + 0xDC, 0x68, 0xA4, 0x8D, 0x92, 0x27, 0x3D, 0xE2, 0x52, 0x5F, + 0x89, 0x8B, 0x02, 0x81, 0x81, 0x00, 0xAA, 0x21, 0x02, 0x09, + 0x43, 0x6E, 0xFB, 0xA2, 0x54, 0x14, 0x85, 0x0A, 0xF4, 0x28, + 0x7C, 0xCB, 0xCC, 0xDB, 0xF5, 0x1E, 0xA2, 0x18, 0xA9, 0x21, + 0xDE, 0x88, 0x88, 0x33, 0x8C, 0x2E, 0xEB, 0x8D, 0xA3, 0xF0, + 0x1D, 0xC8, 0x8F, 0xF6, 0x7E, 0xF8, 0xCF, 0x12, 0xF5, 0xB4, + 0xA1, 0x11, 0x6F, 0x0C, 0xD4, 0xF0, 0x06, 0xAD, 0xC4, 0xFC, + 0x14, 0x45, 0xC7, 0x94, 0x15, 0xBC, 0x19, 0x4B, 0xAE, 0xEF, + 0x93, 0x6A, 0x4F, 0xCC, 0x14, 0xD8, 0x47, 0x8B, 0x39, 0x66, + 0x87, 0x02, 0xD4, 0x28, 0x0A, 0xB8, 0xEE, 0x09, 0x37, 0xF4, + 0x00, 0xA0, 0x04, 0xA7, 0x79, 0xA7, 0xD2, 0x3C, 0xF7, 0x34, + 0x43, 0x56, 0x8E, 0xD0, 0x7C, 0xC2, 0xD8, 0x4D, 0x0F, 0x89, + 0xED, 0x14, 0xC1, 0x2C, 0x9C, 0x4C, 0x19, 0x9B, 0x9E, 0xDC, + 0x53, 0x09, 0x9F, 0xDF, 0x2D, 0xF0, 0x0C, 0x27, 0x54, 0x3A, + 0x77, 0x14, 0x2D, 0xDE, 0x02, 0x81, 0x81, 0x00, 0xE8, 0x1F, + 0x7C, 0xB7, 0xC0, 0x54, 0x51, 0xA7, 0x28, 0x2D, 0x58, 0x7C, + 0xDE, 0xD4, 0x5C, 0xDD, 0xD5, 0x76, 0x84, 0x3C, 0x36, 0x20, + 0xC0, 0xC3, 0x25, 0xD7, 0x3A, 0x38, 0xE1, 0x54, 0xC8, 0xFD, + 0x40, 0x68, 0x1A, 0x21, 0x54, 0x26, 0x39, 0x14, 0xBF, 0xF6, + 0xA3, 0x9C, 0x5E, 0xD9, 0x2B, 0xF7, 0xC9, 0x25, 0xBA, 0x00, + 0x09, 0xCB, 0x7F, 0x0C, 0x4A, 0x24, 0xFD, 0x15, 0x16, 0x15, + 0x48, 0xCD, 0x0B, 0x52, 0x44, 0x40, 0x7B, 0x90, 0x63, 0x2B, + 0x90, 0x22, 0xC5, 0x18, 0x05, 0x80, 0x53, 0xAF, 0x83, 0x1F, + 0x54, 0xE2, 0xB0, 0xA2, 0x0B, 0x5A, 0x92, 0x24, 0xE1, 0x62, + 0x28, 0x3F, 0xB7, 0xCA, 0xB9, 0x89, 0xD6, 0xA0, 0xB7, 0xAD, + 0xAE, 0x05, 0xE1, 0xC1, 0x59, 0x40, 0xED, 0x4A, 0x1B, 0x68, + 0xA7, 0x7B, 0xFB, 0xC3, 0x20, 0x81, 0xEF, 0x4B, 0xF3, 0x69, + 0x91, 0xB0, 0xCE, 0x3A, 0xB0, 0x38, 0x02, 0x14, 0x25, 0x38, + 0x3B, 0xA1, 0x19, 0x75, 0xDF, 0x9B, 0xF5, 0x72, 0x53, 0x4F, + 0x39, 0xE1, 0x1C, 0xEC, 0x13, 0x84, 0x82, 0x18 +}; +static const int sizeof_dsa_key_der_1024 = sizeof(dsa_key_der_1024); + +/* ./certs/1024/rsa1024.der, 1024-bit */ +static const unsigned char rsa_key_der_1024[] = +{ + 0x30, 0x82, 0x02, 0x5D, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, + 0x00, 0xBE, 0x70, 0x70, 0xB8, 0x04, 0x18, 0xE5, 0x28, 0xFE, + 0x66, 0xD8, 0x90, 0x88, 0xE0, 0xF1, 0xB7, 0xC3, 0xD0, 0xD2, + 0x3E, 0xE6, 0x4B, 0x94, 0x74, 0xB0, 0xFF, 0xB0, 0xF7, 0x63, + 0xA5, 0xAB, 0x7E, 0xAF, 0xB6, 0x2B, 0xB7, 0x38, 0x16, 0x1A, + 0x50, 0xBF, 0xF1, 0xCA, 0x87, 0x3A, 0xD5, 0xB0, 0xDA, 0xF8, + 0x43, 0x7A, 0x15, 0xB9, 0x7E, 0xEA, 0x2A, 0x80, 0xD2, 0x51, + 0xB0, 0x35, 0xAF, 0x07, 0xF3, 0xF2, 0x5D, 0x24, 0x3A, 0x4B, + 0x87, 0x56, 0x48, 0x1B, 0x3C, 0x24, 0x9A, 0xDA, 0x70, 0x80, + 0xBD, 0x3C, 0x8B, 0x03, 0x4A, 0x0C, 0x83, 0x71, 0xDE, 0xE3, + 0x03, 0x70, 0xA2, 0xB7, 0x60, 0x09, 0x1B, 0x5E, 0xC7, 0x3D, + 0xA0, 0x64, 0x60, 0xE3, 0xA9, 0x06, 0x8D, 0xD3, 0xFF, 0x42, + 0xBB, 0x0A, 0x94, 0x27, 0x2D, 0x57, 0x42, 0x0D, 0xB0, 0x2D, + 0xE0, 0xBA, 0x18, 0x25, 0x60, 0x92, 0x11, 0x92, 0xF3, 0x02, + 0x03, 0x01, 0x00, 0x01, 0x02, 0x81, 0x80, 0x0E, 0xEE, 0x1D, + 0xC8, 0x2F, 0x7A, 0x0C, 0x2D, 0x44, 0x94, 0xA7, 0x91, 0xDD, + 0x49, 0x55, 0x6A, 0x04, 0xCE, 0x10, 0x4D, 0xA2, 0x1C, 0x76, + 0xCD, 0x17, 0x3B, 0x54, 0x92, 0x70, 0x9B, 0x82, 0x70, 0x72, + 0x32, 0x24, 0x07, 0x3F, 0x3C, 0x6C, 0x5F, 0xBC, 0x4C, 0xA6, + 0x86, 0x27, 0x94, 0xAD, 0x42, 0xDD, 0x87, 0xDC, 0xC0, 0x6B, + 0x44, 0x89, 0xF3, 0x3F, 0x1A, 0x3E, 0x11, 0x44, 0x84, 0x2E, + 0x69, 0x4C, 0xBB, 0x4A, 0x71, 0x1A, 0xBB, 0x9A, 0x52, 0x3C, + 0x6B, 0xDE, 0xBC, 0xB2, 0x7C, 0x51, 0xEF, 0x4F, 0x8F, 0x3A, + 0xDC, 0x50, 0x04, 0x4E, 0xB6, 0x31, 0x66, 0xA8, 0x8E, 0x06, + 0x3B, 0x51, 0xA9, 0xC1, 0x8A, 0xCB, 0xC4, 0x81, 0xCA, 0x2D, + 0x69, 0xEC, 0x88, 0xFC, 0x33, 0x88, 0xD1, 0xD4, 0x29, 0x47, + 0x87, 0x37, 0xF9, 0x6A, 0x22, 0x69, 0xB9, 0xC9, 0xFE, 0xEB, + 0x8C, 0xC5, 0x21, 0x41, 0x71, 0x02, 0x41, 0x00, 0xFD, 0x17, + 0x98, 0x42, 0x54, 0x1C, 0x23, 0xF8, 0xD7, 0x5D, 0xEF, 0x49, + 0x4F, 0xAF, 0xD9, 0x35, 0x6F, 0x08, 0xC6, 0xC7, 0x40, 0x5C, + 0x7E, 0x58, 0x86, 0xC2, 0xB2, 0x16, 0x39, 0x24, 0xC5, 0x06, + 0xB0, 0x3D, 0xAF, 0x02, 0xD2, 0x87, 0x77, 0xD2, 0x76, 0xBA, + 0xE3, 0x59, 0x60, 0x42, 0xF1, 0x16, 0xEF, 0x33, 0x0B, 0xF2, + 0x0B, 0xBA, 0x99, 0xCC, 0xB6, 0x4C, 0x46, 0x3F, 0x33, 0xE4, + 0xD4, 0x67, 0x02, 0x41, 0x00, 0xC0, 0xA0, 0x91, 0x6D, 0xFE, + 0x28, 0xE0, 0x81, 0x5A, 0x15, 0xA7, 0xC9, 0xA8, 0x98, 0xC6, + 0x0A, 0xAB, 0x00, 0xC5, 0x40, 0xC9, 0x21, 0xBB, 0xB2, 0x33, + 0x5A, 0xA7, 0xCB, 0x6E, 0xB8, 0x08, 0x56, 0x4A, 0x76, 0x28, + 0xE8, 0x6D, 0xBD, 0xF5, 0x26, 0x7B, 0xBF, 0xC5, 0x46, 0x45, + 0x0D, 0xEC, 0x7D, 0xEE, 0x82, 0xD6, 0xCA, 0x5F, 0x3D, 0x6E, + 0xCC, 0x94, 0x73, 0xCD, 0xCE, 0x86, 0x6E, 0x95, 0x95, 0x02, + 0x40, 0x38, 0xFD, 0x28, 0x1E, 0xBF, 0x5B, 0xBA, 0xC9, 0xDC, + 0x8C, 0xDD, 0x45, 0xAF, 0xB8, 0xD3, 0xFB, 0x11, 0x2E, 0x73, + 0xBC, 0x08, 0x05, 0x0B, 0xBA, 0x19, 0x56, 0x1B, 0xCD, 0x9F, + 0x3E, 0x65, 0x53, 0x15, 0x3A, 0x3E, 0x7F, 0x2F, 0x32, 0xAB, + 0xCB, 0x6B, 0x4A, 0xB7, 0xC8, 0xB7, 0x41, 0x3B, 0x92, 0x43, + 0x78, 0x46, 0x17, 0x51, 0x86, 0xC9, 0xFC, 0xEB, 0x8B, 0x8F, + 0x41, 0xCA, 0x08, 0x9B, 0xBF, 0x02, 0x41, 0x00, 0xAD, 0x9B, + 0x89, 0xB6, 0xF2, 0x8C, 0x70, 0xDA, 0xE4, 0x10, 0x04, 0x6B, + 0x11, 0x92, 0xAF, 0x5A, 0xCA, 0x08, 0x25, 0xBF, 0x60, 0x07, + 0x11, 0x1D, 0x68, 0x7F, 0x5A, 0x1F, 0x55, 0x28, 0x74, 0x0B, + 0x21, 0x8D, 0x21, 0x0D, 0x6A, 0x6A, 0xFB, 0xD9, 0xB5, 0x4A, + 0x7F, 0x47, 0xF7, 0xD0, 0xB6, 0xC6, 0x41, 0x02, 0x97, 0x07, + 0x49, 0x93, 0x1A, 0x9B, 0x33, 0x68, 0xB3, 0xA2, 0x61, 0x32, + 0xA5, 0x89, 0x02, 0x41, 0x00, 0x8F, 0xEF, 0xAD, 0xB5, 0xB0, + 0xB0, 0x7E, 0x86, 0x03, 0x43, 0x93, 0x6E, 0xDD, 0x3C, 0x2D, + 0x9B, 0x6A, 0x55, 0xFF, 0x6F, 0x3E, 0x70, 0x2A, 0xD4, 0xBF, + 0x1F, 0x8C, 0x93, 0x60, 0x9E, 0x6D, 0x2F, 0x18, 0x6C, 0x11, + 0x36, 0x98, 0x3F, 0x10, 0x78, 0xE8, 0x3E, 0x8F, 0xFE, 0x55, + 0xB9, 0x9E, 0xD5, 0x5B, 0x2E, 0x87, 0x1C, 0x58, 0xD0, 0x37, + 0x89, 0x96, 0xEC, 0x48, 0x54, 0xF5, 0x9F, 0x0F, 0xB3 +}; +static const int sizeof_rsa_key_der_1024 = sizeof(rsa_key_der_1024); + +/* ./certs/1024/ca-key.der, 1024-bit */ +static const unsigned char ca_key_der_1024[] = +{ + 0x30, 0x82, 0x02, 0x5E, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, + 0x00, 0xCD, 0xAC, 0xDD, 0x47, 0xEC, 0xBE, 0xB7, 0x24, 0xC3, + 0x63, 0x1B, 0x54, 0x98, 0x79, 0xE1, 0xC7, 0x31, 0x16, 0x59, + 0xD6, 0x9D, 0x77, 0x9D, 0x8D, 0xE2, 0x8B, 0xED, 0x04, 0x17, + 0xB2, 0xC6, 0xEB, 0xE4, 0x9B, 0x91, 0xBE, 0x31, 0x50, 0x62, + 0x97, 0x58, 0xB5, 0x7F, 0x29, 0xDE, 0xB3, 0x71, 0x24, 0x0B, + 0xBF, 0x97, 0x09, 0x7F, 0x26, 0xDC, 0x2D, 0xEC, 0xA8, 0x2E, + 0xB2, 0x64, 0x2B, 0x7A, 0x2B, 0x35, 0x19, 0x2D, 0xA2, 0x80, + 0xCB, 0x99, 0xFD, 0x94, 0x71, 0x1B, 0x23, 0x8D, 0x54, 0xDB, + 0x2E, 0x62, 0x8D, 0x81, 0x08, 0x2D, 0xF4, 0x24, 0x72, 0x27, + 0x6C, 0xF9, 0xC9, 0x8E, 0xDB, 0x4C, 0x75, 0xBA, 0x9B, 0x01, + 0xF8, 0x3F, 0x18, 0xF4, 0xE6, 0x7F, 0xFB, 0x57, 0x94, 0x92, + 0xCC, 0x88, 0xC4, 0xB4, 0x00, 0xC2, 0xAA, 0xD4, 0xE5, 0x88, + 0x18, 0xB3, 0x11, 0x2F, 0x73, 0xC0, 0xD6, 0x29, 0x09, 0x02, + 0x03, 0x01, 0x00, 0x01, 0x02, 0x81, 0x80, 0x52, 0x35, 0x3D, + 0x01, 0x29, 0xA4, 0x95, 0x29, 0x71, 0x9B, 0x64, 0x6A, 0x2C, + 0xC3, 0xD2, 0xB5, 0xBE, 0x6E, 0x13, 0x9C, 0x8F, 0xB6, 0x26, + 0xD8, 0x76, 0x6B, 0xBD, 0x61, 0xBC, 0x63, 0x2D, 0xD5, 0x4D, + 0xBB, 0xCC, 0xC6, 0x3B, 0x89, 0xC8, 0xCE, 0x7B, 0x9B, 0x97, + 0xE7, 0x51, 0x67, 0x61, 0xDA, 0xA9, 0x83, 0x7B, 0xC8, 0x44, + 0xF5, 0x70, 0x5E, 0x3E, 0xD0, 0x7E, 0x51, 0xB9, 0x6E, 0x13, + 0x57, 0x08, 0x5C, 0xE1, 0x67, 0x4F, 0x61, 0x5E, 0xA5, 0x09, + 0xEC, 0x11, 0xDD, 0xE4, 0xB8, 0xB4, 0xF4, 0xE0, 0x63, 0x34, + 0x4C, 0xDA, 0x32, 0x20, 0x1F, 0x85, 0x41, 0x5D, 0xBC, 0xDB, + 0x24, 0xC5, 0xAF, 0xBE, 0x02, 0x5F, 0x22, 0xF1, 0x7C, 0xCC, + 0x05, 0x56, 0xA6, 0xA6, 0x37, 0x9A, 0xEB, 0xFF, 0x52, 0x2D, + 0xBF, 0x30, 0x4B, 0x9A, 0x1D, 0xEE, 0xAB, 0x9C, 0x2C, 0xE2, + 0xC1, 0xB8, 0x9D, 0xC9, 0x31, 0x02, 0x41, 0x00, 0xE9, 0x89, + 0x16, 0xCD, 0xAC, 0x2E, 0xF2, 0x4D, 0x66, 0x17, 0xBD, 0x78, + 0x12, 0x12, 0x8D, 0x8E, 0x84, 0x24, 0xDE, 0x2D, 0x50, 0x41, + 0x85, 0x8C, 0x34, 0x09, 0xFA, 0xFB, 0x6D, 0x87, 0x51, 0x4C, + 0x13, 0x28, 0xF0, 0x60, 0x11, 0x86, 0x3D, 0xC2, 0xA4, 0xCF, + 0x5E, 0xC5, 0x6F, 0x5B, 0x11, 0x32, 0x0A, 0xB5, 0x28, 0xD0, + 0x82, 0x47, 0x44, 0x26, 0x92, 0xE2, 0x78, 0x59, 0xB4, 0x08, + 0xB3, 0xFD, 0x02, 0x41, 0x00, 0xE1, 0x75, 0xB4, 0x6A, 0xB5, + 0x8C, 0x11, 0xFB, 0xCC, 0x42, 0x02, 0xC5, 0xDA, 0x48, 0xCE, + 0x29, 0x43, 0x14, 0x01, 0x9A, 0x2C, 0xB3, 0xA4, 0xCB, 0x73, + 0xEB, 0xA1, 0x35, 0x57, 0xAD, 0xB5, 0x16, 0x17, 0x80, 0x03, + 0x5F, 0x32, 0x37, 0xBE, 0xA2, 0x6F, 0xF9, 0x31, 0x84, 0xBF, + 0x00, 0x6E, 0x8D, 0x03, 0x0E, 0x30, 0x1C, 0xD0, 0x2F, 0x37, + 0xF0, 0x7E, 0xC2, 0x64, 0xBF, 0xEE, 0x4B, 0xE8, 0xFD, 0x02, + 0x41, 0x00, 0xE1, 0x99, 0x8B, 0x2B, 0xD8, 0x9F, 0xE9, 0x76, + 0x97, 0x9F, 0x6B, 0x6B, 0x28, 0x9A, 0x3F, 0xA1, 0x63, 0x4A, + 0x72, 0x4E, 0xF7, 0xEE, 0xB3, 0xE2, 0x43, 0x0B, 0x39, 0x27, + 0xD6, 0x21, 0x18, 0x8A, 0x13, 0x20, 0x43, 0x45, 0xAA, 0xE8, + 0x31, 0x95, 0x6C, 0xBC, 0xDE, 0xE2, 0x7F, 0xB6, 0x4B, 0xA0, + 0x39, 0xF3, 0xD3, 0x9F, 0xC9, 0x9A, 0xAA, 0xDD, 0x50, 0x9B, + 0xF2, 0x83, 0x45, 0x85, 0xFA, 0xC9, 0x02, 0x41, 0x00, 0xAF, + 0xB0, 0xC7, 0x7C, 0xF8, 0x28, 0x44, 0xC3, 0x50, 0xF2, 0x87, + 0xB2, 0xA2, 0x5D, 0x65, 0xBA, 0x25, 0xB9, 0x6B, 0x5E, 0x37, + 0x43, 0x6E, 0x41, 0xD4, 0xFD, 0x63, 0x4C, 0x6C, 0x1C, 0xC3, + 0x26, 0x89, 0xFD, 0x89, 0xA3, 0x1F, 0x40, 0xED, 0x5F, 0x2B, + 0x9E, 0xA6, 0x85, 0xE9, 0x49, 0x6E, 0xDC, 0x97, 0xEA, 0xF0, + 0x77, 0x23, 0x8C, 0x08, 0x2D, 0x72, 0xBA, 0x0D, 0x44, 0xBB, + 0x6F, 0x90, 0x09, 0x02, 0x41, 0x00, 0x91, 0xE4, 0x2E, 0xCA, + 0x8C, 0x0A, 0x69, 0x2F, 0x62, 0xE2, 0x62, 0x3B, 0xA5, 0x8D, + 0x5A, 0x2C, 0x56, 0x3E, 0x7F, 0x67, 0x42, 0x92, 0x12, 0x92, + 0x5F, 0xF3, 0x97, 0xDD, 0xE1, 0xA9, 0x7F, 0xAD, 0x2E, 0x2D, + 0xF4, 0x4A, 0x57, 0xB3, 0x7A, 0x10, 0xBD, 0xD7, 0xE4, 0xEC, + 0x6A, 0x08, 0x21, 0xE9, 0xF2, 0x46, 0x49, 0xD2, 0x69, 0x47, + 0x8A, 0x20, 0x4B, 0xF2, 0xB1, 0x52, 0x83, 0xAB, 0x6F, 0x10 + +}; +static const int sizeof_ca_key_der_1024 = sizeof(ca_key_der_1024); + +/* ./certs/1024/ca-cert.der, 1024-bit */ +static const unsigned char ca_cert_der_1024[] = +{ + 0x30, 0x82, 0x03, 0xB5, 0x30, 0x82, 0x03, 0x1E, 0xA0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0xDA, 0xFB, 0x6A, 0x0D, + 0xFE, 0xCF, 0x9B, 0x47, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, + 0x81, 0x99, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x08, 0x0C, 0x07, 0x4D, 0x6F, 0x6E, 0x74, + 0x61, 0x6E, 0x61, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, + 0x04, 0x07, 0x0C, 0x07, 0x42, 0x6F, 0x7A, 0x65, 0x6D, 0x61, + 0x6E, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x08, 0x53, 0x61, 0x77, 0x74, 0x6F, 0x6F, 0x74, 0x68, + 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, + 0x0F, 0x43, 0x6F, 0x6E, 0x73, 0x75, 0x6C, 0x74, 0x69, 0x6E, + 0x67, 0x5F, 0x31, 0x30, 0x32, 0x34, 0x31, 0x18, 0x30, 0x16, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x77, 0x77, 0x77, + 0x2E, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, + 0x6F, 0x6D, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, + 0x6E, 0x66, 0x6F, 0x40, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, + 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x30, 0x1E, 0x17, 0x0D, 0x31, + 0x38, 0x30, 0x34, 0x31, 0x33, 0x31, 0x35, 0x32, 0x33, 0x31, + 0x30, 0x5A, 0x17, 0x0D, 0x32, 0x31, 0x30, 0x31, 0x30, 0x37, + 0x31, 0x35, 0x32, 0x33, 0x31, 0x30, 0x5A, 0x30, 0x81, 0x99, + 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, + 0x04, 0x08, 0x0C, 0x07, 0x4D, 0x6F, 0x6E, 0x74, 0x61, 0x6E, + 0x61, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, + 0x0C, 0x07, 0x42, 0x6F, 0x7A, 0x65, 0x6D, 0x61, 0x6E, 0x31, + 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x08, + 0x53, 0x61, 0x77, 0x74, 0x6F, 0x6F, 0x74, 0x68, 0x31, 0x18, + 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x0F, 0x43, + 0x6F, 0x6E, 0x73, 0x75, 0x6C, 0x74, 0x69, 0x6E, 0x67, 0x5F, + 0x31, 0x30, 0x32, 0x34, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, + 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, + 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, + 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, + 0x6F, 0x40, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, + 0x63, 0x6F, 0x6D, 0x30, 0x81, 0x9F, 0x30, 0x0D, 0x06, 0x09, + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, + 0x00, 0x03, 0x81, 0x8D, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, + 0x81, 0x00, 0xCD, 0xAC, 0xDD, 0x47, 0xEC, 0xBE, 0xB7, 0x24, + 0xC3, 0x63, 0x1B, 0x54, 0x98, 0x79, 0xE1, 0xC7, 0x31, 0x16, + 0x59, 0xD6, 0x9D, 0x77, 0x9D, 0x8D, 0xE2, 0x8B, 0xED, 0x04, + 0x17, 0xB2, 0xC6, 0xEB, 0xE4, 0x9B, 0x91, 0xBE, 0x31, 0x50, + 0x62, 0x97, 0x58, 0xB5, 0x7F, 0x29, 0xDE, 0xB3, 0x71, 0x24, + 0x0B, 0xBF, 0x97, 0x09, 0x7F, 0x26, 0xDC, 0x2D, 0xEC, 0xA8, + 0x2E, 0xB2, 0x64, 0x2B, 0x7A, 0x2B, 0x35, 0x19, 0x2D, 0xA2, + 0x80, 0xCB, 0x99, 0xFD, 0x94, 0x71, 0x1B, 0x23, 0x8D, 0x54, + 0xDB, 0x2E, 0x62, 0x8D, 0x81, 0x08, 0x2D, 0xF4, 0x24, 0x72, + 0x27, 0x6C, 0xF9, 0xC9, 0x8E, 0xDB, 0x4C, 0x75, 0xBA, 0x9B, + 0x01, 0xF8, 0x3F, 0x18, 0xF4, 0xE6, 0x7F, 0xFB, 0x57, 0x94, + 0x92, 0xCC, 0x88, 0xC4, 0xB4, 0x00, 0xC2, 0xAA, 0xD4, 0xE5, + 0x88, 0x18, 0xB3, 0x11, 0x2F, 0x73, 0xC0, 0xD6, 0x29, 0x09, + 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x82, 0x01, 0x01, 0x30, + 0x81, 0xFE, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, + 0x16, 0x04, 0x14, 0xD3, 0x22, 0x8F, 0x28, 0x2C, 0xE0, 0x05, + 0xEE, 0xD3, 0xED, 0xC3, 0x71, 0x3D, 0xC9, 0xB2, 0x36, 0x3A, + 0x1D, 0xBF, 0xA8, 0x30, 0x81, 0xCE, 0x06, 0x03, 0x55, 0x1D, + 0x23, 0x04, 0x81, 0xC6, 0x30, 0x81, 0xC3, 0x80, 0x14, 0xD3, + 0x22, 0x8F, 0x28, 0x2C, 0xE0, 0x05, 0xEE, 0xD3, 0xED, 0xC3, + 0x71, 0x3D, 0xC9, 0xB2, 0x36, 0x3A, 0x1D, 0xBF, 0xA8, 0xA1, + 0x81, 0x9F, 0xA4, 0x81, 0x9C, 0x30, 0x81, 0x99, 0x31, 0x0B, + 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, + 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0C, 0x07, 0x4D, 0x6F, 0x6E, 0x74, 0x61, 0x6E, 0x61, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, + 0x42, 0x6F, 0x7A, 0x65, 0x6D, 0x61, 0x6E, 0x31, 0x11, 0x30, + 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x08, 0x53, 0x61, + 0x77, 0x74, 0x6F, 0x6F, 0x74, 0x68, 0x31, 0x18, 0x30, 0x16, + 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x0F, 0x43, 0x6F, 0x6E, + 0x73, 0x75, 0x6C, 0x74, 0x69, 0x6E, 0x67, 0x5F, 0x31, 0x30, + 0x32, 0x34, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, + 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, + 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, + 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, + 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, + 0x6D, 0x82, 0x09, 0x00, 0xDA, 0xFB, 0x6A, 0x0D, 0xFE, 0xCF, + 0x9B, 0x47, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, + 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x0D, 0x06, 0x09, + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, + 0x00, 0x03, 0x81, 0x81, 0x00, 0x1D, 0x48, 0xF6, 0x40, 0x41, + 0x04, 0x06, 0xF2, 0xE4, 0x72, 0x2F, 0xEA, 0xFF, 0xC1, 0x67, + 0x6B, 0x15, 0xBB, 0x0A, 0x28, 0x23, 0x28, 0x07, 0xC6, 0xD7, + 0x13, 0x2C, 0xBE, 0x00, 0x00, 0xAC, 0x1D, 0xF7, 0xF4, 0x92, + 0xD3, 0x2B, 0xAF, 0x23, 0xEB, 0x9F, 0x1A, 0xE2, 0x11, 0x3C, + 0x2D, 0x97, 0xF2, 0x0F, 0xAC, 0xAE, 0x97, 0x86, 0x0A, 0xFB, + 0xA8, 0x4F, 0x74, 0x1B, 0xDE, 0x19, 0x51, 0xDB, 0xCD, 0xE2, + 0x11, 0x38, 0xC1, 0xA4, 0x9D, 0x56, 0xAB, 0x47, 0x5C, 0xDE, + 0xBA, 0xEB, 0x27, 0xDF, 0x6D, 0xC8, 0x7E, 0x3A, 0xBD, 0x2E, + 0x9B, 0x2A, 0xAD, 0x22, 0x3B, 0x95, 0xA9, 0xF2, 0x28, 0x03, + 0xBC, 0xE5, 0xEC, 0xCC, 0xF2, 0x08, 0xD4, 0xC8, 0x2F, 0xDB, + 0xEA, 0xFB, 0x2E, 0x52, 0x16, 0x8C, 0x42, 0x02, 0xA4, 0x59, + 0x6D, 0x4C, 0x33, 0xB4, 0x9A, 0xD2, 0x73, 0x4A, 0x1E, 0x9F, + 0xD9, 0xC8, 0x83 +}; +static const int sizeof_ca_cert_der_1024 = sizeof(ca_cert_der_1024); + +/* ./certs/1024/server-key.der, 1024-bit */ +static const unsigned char server_key_der_1024[] = +{ + 0x30, 0x82, 0x02, 0x5D, 0x02, 0x01, 0x00, 0x02, 0x81, 0x81, + 0x00, 0xAA, 0x3E, 0xA5, 0x9C, 0xD3, 0x17, 0x49, 0x65, 0x43, + 0xDE, 0xD0, 0xF3, 0x4B, 0x1C, 0xDB, 0x49, 0x0C, 0xFC, 0x7A, + 0x65, 0x05, 0x6D, 0xDE, 0x6A, 0xC4, 0xE4, 0x73, 0x2C, 0x8A, + 0x96, 0x82, 0x8F, 0x23, 0xA5, 0x06, 0x71, 0x1C, 0x06, 0x3E, + 0x2F, 0x92, 0x8D, 0x0B, 0x29, 0x34, 0x45, 0x59, 0xE9, 0xA9, + 0xBC, 0x61, 0xD7, 0x24, 0x37, 0x5D, 0xB5, 0xC4, 0x37, 0x8D, + 0xBA, 0x67, 0xB2, 0xEF, 0x03, 0x27, 0xFA, 0xC1, 0xB4, 0xCD, + 0x6B, 0x00, 0x66, 0xB4, 0xD6, 0x73, 0x70, 0x1F, 0x08, 0x3A, + 0xCC, 0x77, 0xAD, 0xE9, 0xF9, 0x34, 0xD4, 0xF3, 0xA0, 0x2D, + 0xA9, 0xE7, 0x58, 0xA9, 0xC0, 0x61, 0x84, 0xB6, 0xEC, 0x3D, + 0x0A, 0xAD, 0xFD, 0x5C, 0x86, 0x73, 0xAA, 0x6B, 0x47, 0xD8, + 0x8B, 0x2E, 0x58, 0x4B, 0x69, 0x12, 0x82, 0x26, 0x55, 0xE6, + 0x14, 0xBF, 0x55, 0x70, 0x88, 0xFE, 0xF9, 0x75, 0xE1, 0x02, + 0x03, 0x01, 0x00, 0x01, 0x02, 0x81, 0x80, 0x0A, 0x4C, 0xC1, + 0xFE, 0x4B, 0xF3, 0x23, 0xB8, 0xA1, 0xB3, 0x90, 0x56, 0xB7, + 0xDB, 0xA6, 0x14, 0xB4, 0x59, 0x6E, 0x1A, 0x40, 0x8A, 0xD6, + 0x23, 0x05, 0x88, 0x80, 0xC3, 0x58, 0x1B, 0x25, 0x08, 0xFD, + 0xF2, 0x15, 0x02, 0xB0, 0xDC, 0x5B, 0xD4, 0xCA, 0xFC, 0x07, + 0x89, 0xD5, 0xA4, 0xC0, 0x7C, 0xD7, 0x8D, 0x13, 0x2A, 0x4E, + 0x01, 0x9F, 0x84, 0xC8, 0xBB, 0x47, 0xB2, 0xD8, 0x65, 0x45, + 0xFA, 0x84, 0x9F, 0x88, 0xD0, 0xF4, 0xF5, 0x22, 0x35, 0x77, + 0x11, 0x67, 0x1C, 0xDE, 0x5F, 0x85, 0x6D, 0x55, 0xD8, 0xA7, + 0x07, 0x15, 0x8C, 0xE1, 0xB0, 0xA7, 0x79, 0xB4, 0x47, 0x9D, + 0x70, 0xB3, 0xD2, 0xF1, 0x1F, 0x41, 0x4C, 0x65, 0x72, 0x26, + 0xEB, 0x66, 0xC8, 0x95, 0xF6, 0x6D, 0x87, 0x35, 0x53, 0xFE, + 0xB1, 0x52, 0x4D, 0x76, 0x5B, 0x61, 0x53, 0x89, 0xB1, 0x20, + 0x1A, 0x8B, 0xE4, 0x7D, 0xF1, 0x02, 0x41, 0x00, 0xD9, 0x6E, + 0xE1, 0xD9, 0x06, 0x56, 0xA1, 0xF6, 0xDF, 0x54, 0x45, 0xC5, + 0xEC, 0x6A, 0xC8, 0x2A, 0x38, 0x4E, 0x6B, 0xC6, 0xE8, 0xEA, + 0xFB, 0x6F, 0x65, 0x2D, 0xBA, 0xDE, 0x27, 0x63, 0x37, 0x21, + 0x2E, 0xA4, 0x55, 0xAB, 0xE7, 0xDB, 0xCE, 0x71, 0xE1, 0x08, + 0xFC, 0xF2, 0xCA, 0x52, 0x33, 0x55, 0xE8, 0x39, 0xB3, 0xDA, + 0xC5, 0xB0, 0x69, 0x84, 0x6E, 0xE3, 0xCF, 0x47, 0x80, 0xA6, + 0xB6, 0x85, 0x02, 0x41, 0x00, 0xC8, 0x71, 0x0D, 0x37, 0x47, + 0xE1, 0x7B, 0x21, 0x2D, 0x11, 0x2D, 0x95, 0x2E, 0xC7, 0xD0, + 0xB6, 0xD3, 0x7C, 0x5C, 0x93, 0x3C, 0x5B, 0x22, 0xE5, 0xE0, + 0x8B, 0x6D, 0x47, 0xF9, 0x14, 0x0F, 0x9E, 0x08, 0x1B, 0x53, + 0xAB, 0x0A, 0xA9, 0xE4, 0x7F, 0x40, 0xD3, 0xDF, 0x62, 0x74, + 0x10, 0xA2, 0xFE, 0x83, 0x1F, 0xCF, 0x55, 0x66, 0xEB, 0x5D, + 0xC5, 0x83, 0xBA, 0xEC, 0x9F, 0xD2, 0xB5, 0x06, 0xAD, 0x02, + 0x41, 0x00, 0xB7, 0x68, 0x19, 0xA7, 0xC7, 0xF9, 0xF1, 0x9A, + 0xDD, 0x5D, 0x27, 0x91, 0xC1, 0x4F, 0x7D, 0x52, 0x67, 0xB6, + 0x76, 0xA1, 0x0D, 0x3D, 0x91, 0x23, 0xB0, 0xB3, 0xF7, 0x49, + 0x86, 0xED, 0xE0, 0xC5, 0xE3, 0xA3, 0x09, 0x04, 0xFD, 0x89, + 0xE2, 0xC5, 0x1A, 0x6E, 0x4B, 0x77, 0xBD, 0x03, 0xC3, 0x7B, + 0xB6, 0x6C, 0x5D, 0xF2, 0xAF, 0x08, 0x94, 0xA8, 0xFA, 0x24, + 0xBD, 0x66, 0x71, 0xF5, 0xAE, 0x45, 0x02, 0x40, 0x15, 0x52, + 0xD1, 0x91, 0x1B, 0xF8, 0x84, 0xDC, 0xD6, 0xAA, 0x89, 0x2A, + 0xE1, 0xBB, 0x28, 0x1D, 0x0B, 0x0A, 0xA3, 0xDE, 0x96, 0x01, + 0x2C, 0x09, 0x40, 0x86, 0x14, 0xAE, 0x1F, 0x75, 0x5E, 0xE3, + 0xF5, 0x00, 0xD3, 0x39, 0xD2, 0xFC, 0x97, 0xEE, 0x61, 0xBB, + 0x28, 0x7C, 0x94, 0xD4, 0x60, 0x42, 0xAB, 0x38, 0x6B, 0x1A, + 0x2E, 0xC4, 0xC3, 0x49, 0x0B, 0xE6, 0x8A, 0xDD, 0xC5, 0xD0, + 0xB4, 0x51, 0x02, 0x41, 0x00, 0xA9, 0x8B, 0xA7, 0xA9, 0xEE, + 0xAE, 0xBB, 0x17, 0xCB, 0x72, 0xF2, 0x50, 0x22, 0x9D, 0xB3, + 0xDF, 0xE0, 0x40, 0x37, 0x08, 0xD5, 0x7F, 0x19, 0x58, 0x80, + 0x70, 0x79, 0x69, 0x99, 0xDF, 0x62, 0x0D, 0x21, 0xAB, 0xDD, + 0xB2, 0xCE, 0x68, 0xB3, 0x9F, 0x87, 0xAF, 0x55, 0xF4, 0xAA, + 0xE1, 0x00, 0x72, 0xBE, 0x6E, 0xC3, 0x94, 0x49, 0xDC, 0xBB, + 0x8E, 0x1A, 0x78, 0xE5, 0x49, 0x1F, 0x55, 0x41, 0xA1 +}; +static const int sizeof_server_key_der_1024 = sizeof(server_key_der_1024); + +/* ./certs/1024/server-cert.der, 1024-bit */ +static const unsigned char server_cert_der_1024[] = +{ + 0x30, 0x82, 0x03, 0xA9, 0x30, 0x82, 0x03, 0x12, 0xA0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x30, 0x0D, 0x06, 0x09, + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, + 0x00, 0x30, 0x81, 0x99, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, + 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, + 0x0E, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0C, 0x07, 0x4D, 0x6F, + 0x6E, 0x74, 0x61, 0x6E, 0x61, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x42, 0x6F, 0x7A, 0x65, + 0x6D, 0x61, 0x6E, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, + 0x04, 0x0A, 0x0C, 0x08, 0x53, 0x61, 0x77, 0x74, 0x6F, 0x6F, + 0x74, 0x68, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x0C, 0x0F, 0x43, 0x6F, 0x6E, 0x73, 0x75, 0x6C, 0x74, + 0x69, 0x6E, 0x67, 0x5F, 0x31, 0x30, 0x32, 0x34, 0x31, 0x18, + 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x77, + 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, + 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, + 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, 0x6F, 0x6C, 0x66, + 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x30, 0x1E, 0x17, + 0x0D, 0x31, 0x38, 0x30, 0x34, 0x31, 0x33, 0x31, 0x35, 0x32, + 0x33, 0x31, 0x30, 0x5A, 0x17, 0x0D, 0x32, 0x31, 0x30, 0x31, + 0x30, 0x37, 0x31, 0x35, 0x32, 0x33, 0x31, 0x30, 0x5A, 0x30, + 0x81, 0x95, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x08, 0x0C, 0x07, 0x4D, 0x6F, 0x6E, 0x74, + 0x61, 0x6E, 0x61, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, + 0x04, 0x07, 0x0C, 0x07, 0x42, 0x6F, 0x7A, 0x65, 0x6D, 0x61, + 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x07, 0x77, 0x6F, 0x6C, 0x66, 0x53, 0x53, 0x4C, 0x31, + 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x0C, + 0x53, 0x75, 0x70, 0x70, 0x6F, 0x72, 0x74, 0x5F, 0x31, 0x30, + 0x32, 0x34, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, + 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, + 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, + 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, + 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, + 0x6D, 0x30, 0x81, 0x9F, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, + 0x81, 0x8D, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, 0x81, 0x00, + 0xAA, 0x3E, 0xA5, 0x9C, 0xD3, 0x17, 0x49, 0x65, 0x43, 0xDE, + 0xD0, 0xF3, 0x4B, 0x1C, 0xDB, 0x49, 0x0C, 0xFC, 0x7A, 0x65, + 0x05, 0x6D, 0xDE, 0x6A, 0xC4, 0xE4, 0x73, 0x2C, 0x8A, 0x96, + 0x82, 0x8F, 0x23, 0xA5, 0x06, 0x71, 0x1C, 0x06, 0x3E, 0x2F, + 0x92, 0x8D, 0x0B, 0x29, 0x34, 0x45, 0x59, 0xE9, 0xA9, 0xBC, + 0x61, 0xD7, 0x24, 0x37, 0x5D, 0xB5, 0xC4, 0x37, 0x8D, 0xBA, + 0x67, 0xB2, 0xEF, 0x03, 0x27, 0xFA, 0xC1, 0xB4, 0xCD, 0x6B, + 0x00, 0x66, 0xB4, 0xD6, 0x73, 0x70, 0x1F, 0x08, 0x3A, 0xCC, + 0x77, 0xAD, 0xE9, 0xF9, 0x34, 0xD4, 0xF3, 0xA0, 0x2D, 0xA9, + 0xE7, 0x58, 0xA9, 0xC0, 0x61, 0x84, 0xB6, 0xEC, 0x3D, 0x0A, + 0xAD, 0xFD, 0x5C, 0x86, 0x73, 0xAA, 0x6B, 0x47, 0xD8, 0x8B, + 0x2E, 0x58, 0x4B, 0x69, 0x12, 0x82, 0x26, 0x55, 0xE6, 0x14, + 0xBF, 0x55, 0x70, 0x88, 0xFE, 0xF9, 0x75, 0xE1, 0x02, 0x03, + 0x01, 0x00, 0x01, 0xA3, 0x82, 0x01, 0x01, 0x30, 0x81, 0xFE, + 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, + 0x14, 0xD9, 0x3C, 0x35, 0xEA, 0x74, 0x0E, 0x23, 0xBE, 0x9C, + 0xFC, 0xFA, 0x29, 0x90, 0x09, 0xC1, 0xE7, 0x84, 0x16, 0x9F, + 0x7C, 0x30, 0x81, 0xCE, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, + 0x81, 0xC6, 0x30, 0x81, 0xC3, 0x80, 0x14, 0xD3, 0x22, 0x8F, + 0x28, 0x2C, 0xE0, 0x05, 0xEE, 0xD3, 0xED, 0xC3, 0x71, 0x3D, + 0xC9, 0xB2, 0x36, 0x3A, 0x1D, 0xBF, 0xA8, 0xA1, 0x81, 0x9F, + 0xA4, 0x81, 0x9C, 0x30, 0x81, 0x99, 0x31, 0x0B, 0x30, 0x09, + 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0C, 0x07, + 0x4D, 0x6F, 0x6E, 0x74, 0x61, 0x6E, 0x61, 0x31, 0x10, 0x30, + 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x42, 0x6F, + 0x7A, 0x65, 0x6D, 0x61, 0x6E, 0x31, 0x11, 0x30, 0x0F, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x08, 0x53, 0x61, 0x77, 0x74, + 0x6F, 0x6F, 0x74, 0x68, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, + 0x55, 0x04, 0x0B, 0x0C, 0x0F, 0x43, 0x6F, 0x6E, 0x73, 0x75, + 0x6C, 0x74, 0x69, 0x6E, 0x67, 0x5F, 0x31, 0x30, 0x32, 0x34, + 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, 0x73, + 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, 0x1D, + 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, + 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, 0x6F, + 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x82, + 0x09, 0x00, 0xDA, 0xFB, 0x6A, 0x0D, 0xFE, 0xCF, 0x9B, 0x47, + 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, + 0x03, 0x01, 0x01, 0xFF, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03, + 0x81, 0x81, 0x00, 0x0B, 0xC3, 0xAF, 0x43, 0x85, 0x64, 0x61, + 0xE7, 0xAB, 0x5A, 0x2A, 0x1B, 0xB2, 0x29, 0xD5, 0x66, 0x68, + 0x44, 0x1A, 0x6D, 0x66, 0xFC, 0x3D, 0xB1, 0x88, 0xEC, 0xA5, + 0x41, 0x18, 0x67, 0x62, 0x34, 0xA4, 0x5E, 0xC9, 0x69, 0xCD, + 0x40, 0xC8, 0x56, 0x7E, 0xBF, 0xEB, 0xBC, 0x61, 0x1F, 0x33, + 0x34, 0x58, 0xBE, 0x57, 0xFD, 0xE6, 0x98, 0xDD, 0x51, 0x27, + 0x7C, 0xB7, 0x2C, 0xBC, 0xC9, 0x39, 0xE5, 0xE5, 0x95, 0x82, + 0xE1, 0x3F, 0xD9, 0xB9, 0x97, 0x30, 0x4E, 0x33, 0x2C, 0xEF, + 0xF8, 0xDB, 0xB4, 0xEE, 0x35, 0x75, 0x9E, 0x7A, 0x3F, 0x22, + 0x8F, 0xA5, 0x71, 0xD4, 0x01, 0x64, 0x6C, 0xF2, 0x85, 0xF7, + 0x72, 0x99, 0x2C, 0x80, 0x0F, 0xA4, 0x31, 0x1D, 0xD4, 0x0B, + 0x1E, 0xA5, 0x0F, 0xE7, 0x53, 0x0A, 0xDE, 0x15, 0x0D, 0xB2, + 0xD0, 0x6B, 0xF4, 0xD6, 0x2F, 0xE2, 0x0B, 0xA3, 0x8A, 0x5A, + 0x6E +}; +static const int sizeof_server_cert_der_1024 = sizeof(server_cert_der_1024); + +#endif /* USE_CERT_BUFFERS_1024 */ + +#ifdef USE_CERT_BUFFERS_2048 + +/* ./certs/client-key.der, 2048-bit */ +static const unsigned char client_key_der_2048[] = +{ + 0x30, 0x82, 0x04, 0xA4, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, + 0x01, 0x00, 0xC3, 0x03, 0xD1, 0x2B, 0xFE, 0x39, 0xA4, 0x32, + 0x45, 0x3B, 0x53, 0xC8, 0x84, 0x2B, 0x2A, 0x7C, 0x74, 0x9A, + 0xBD, 0xAA, 0x2A, 0x52, 0x07, 0x47, 0xD6, 0xA6, 0x36, 0xB2, + 0x07, 0x32, 0x8E, 0xD0, 0xBA, 0x69, 0x7B, 0xC6, 0xC3, 0x44, + 0x9E, 0xD4, 0x81, 0x48, 0xFD, 0x2D, 0x68, 0xA2, 0x8B, 0x67, + 0xBB, 0xA1, 0x75, 0xC8, 0x36, 0x2C, 0x4A, 0xD2, 0x1B, 0xF7, + 0x8B, 0xBA, 0xCF, 0x0D, 0xF9, 0xEF, 0xEC, 0xF1, 0x81, 0x1E, + 0x7B, 0x9B, 0x03, 0x47, 0x9A, 0xBF, 0x65, 0xCC, 0x7F, 0x65, + 0x24, 0x69, 0xA6, 0xE8, 0x14, 0x89, 0x5B, 0xE4, 0x34, 0xF7, + 0xC5, 0xB0, 0x14, 0x93, 0xF5, 0x67, 0x7B, 0x3A, 0x7A, 0x78, + 0xE1, 0x01, 0x56, 0x56, 0x91, 0xA6, 0x13, 0x42, 0x8D, 0xD2, + 0x3C, 0x40, 0x9C, 0x4C, 0xEF, 0xD1, 0x86, 0xDF, 0x37, 0x51, + 0x1B, 0x0C, 0xA1, 0x3B, 0xF5, 0xF1, 0xA3, 0x4A, 0x35, 0xE4, + 0xE1, 0xCE, 0x96, 0xDF, 0x1B, 0x7E, 0xBF, 0x4E, 0x97, 0xD0, + 0x10, 0xE8, 0xA8, 0x08, 0x30, 0x81, 0xAF, 0x20, 0x0B, 0x43, + 0x14, 0xC5, 0x74, 0x67, 0xB4, 0x32, 0x82, 0x6F, 0x8D, 0x86, + 0xC2, 0x88, 0x40, 0x99, 0x36, 0x83, 0xBA, 0x1E, 0x40, 0x72, + 0x22, 0x17, 0xD7, 0x52, 0x65, 0x24, 0x73, 0xB0, 0xCE, 0xEF, + 0x19, 0xCD, 0xAE, 0xFF, 0x78, 0x6C, 0x7B, 0xC0, 0x12, 0x03, + 0xD4, 0x4E, 0x72, 0x0D, 0x50, 0x6D, 0x3B, 0xA3, 0x3B, 0xA3, + 0x99, 0x5E, 0x9D, 0xC8, 0xD9, 0x0C, 0x85, 0xB3, 0xD9, 0x8A, + 0xD9, 0x54, 0x26, 0xDB, 0x6D, 0xFA, 0xAC, 0xBB, 0xFF, 0x25, + 0x4C, 0xC4, 0xD1, 0x79, 0xF4, 0x71, 0xD3, 0x86, 0x40, 0x18, + 0x13, 0xB0, 0x63, 0xB5, 0x72, 0x4E, 0x30, 0xC4, 0x97, 0x84, + 0x86, 0x2D, 0x56, 0x2F, 0xD7, 0x15, 0xF7, 0x7F, 0xC0, 0xAE, + 0xF5, 0xFC, 0x5B, 0xE5, 0xFB, 0xA1, 0xBA, 0xD3, 0x02, 0x03, + 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, 0x01, 0x00, 0xA2, 0xE6, + 0xD8, 0x5F, 0x10, 0x71, 0x64, 0x08, 0x9E, 0x2E, 0x6D, 0xD1, + 0x6D, 0x1E, 0x85, 0xD2, 0x0A, 0xB1, 0x8C, 0x47, 0xCE, 0x2C, + 0x51, 0x6A, 0xA0, 0x12, 0x9E, 0x53, 0xDE, 0x91, 0x4C, 0x1D, + 0x6D, 0xEA, 0x59, 0x7B, 0xF2, 0x77, 0xAA, 0xD9, 0xC6, 0xD9, + 0x8A, 0xAB, 0xD8, 0xE1, 0x16, 0xE4, 0x63, 0x26, 0xFF, 0xB5, + 0x6C, 0x13, 0x59, 0xB8, 0xE3, 0xA5, 0xC8, 0x72, 0x17, 0x2E, + 0x0C, 0x9F, 0x6F, 0xE5, 0x59, 0x3F, 0x76, 0x6F, 0x49, 0xB1, + 0x11, 0xC2, 0x5A, 0x2E, 0x16, 0x29, 0x0D, 0xDE, 0xB7, 0x8E, + 0xDC, 0x40, 0xD5, 0xA2, 0xEE, 0xE0, 0x1E, 0xA1, 0xF4, 0xBE, + 0x97, 0xDB, 0x86, 0x63, 0x96, 0x14, 0xCD, 0x98, 0x09, 0x60, + 0x2D, 0x30, 0x76, 0x9C, 0x3C, 0xCD, 0xE6, 0x88, 0xEE, 0x47, + 0x92, 0x79, 0x0B, 0x5A, 0x00, 0xE2, 0x5E, 0x5F, 0x11, 0x7C, + 0x7D, 0xF9, 0x08, 0xB7, 0x20, 0x06, 0x89, 0x2A, 0x5D, 0xFD, + 0x00, 0xAB, 0x22, 0xE1, 0xF0, 0xB3, 0xBC, 0x24, 0xA9, 0x5E, + 0x26, 0x0E, 0x1F, 0x00, 0x2D, 0xFE, 0x21, 0x9A, 0x53, 0x5B, + 0x6D, 0xD3, 0x2B, 0xAB, 0x94, 0x82, 0x68, 0x43, 0x36, 0xD8, + 0xF6, 0x2F, 0xC6, 0x22, 0xFC, 0xB5, 0x41, 0x5D, 0x0D, 0x33, + 0x60, 0xEA, 0xA4, 0x7D, 0x7E, 0xE8, 0x4B, 0x55, 0x91, 0x56, + 0xD3, 0x5C, 0x57, 0x8F, 0x1F, 0x94, 0x17, 0x2F, 0xAA, 0xDE, + 0xE9, 0x9E, 0xA8, 0xF4, 0xCF, 0x8A, 0x4C, 0x8E, 0xA0, 0xE4, + 0x56, 0x73, 0xB2, 0xCF, 0x4F, 0x86, 0xC5, 0x69, 0x3C, 0xF3, + 0x24, 0x20, 0x8B, 0x5C, 0x96, 0x0C, 0xFA, 0x6B, 0x12, 0x3B, + 0x9A, 0x67, 0xC1, 0xDF, 0xC6, 0x96, 0xB2, 0xA5, 0xD5, 0x92, + 0x0D, 0x9B, 0x09, 0x42, 0x68, 0x24, 0x10, 0x45, 0xD4, 0x50, + 0xE4, 0x17, 0x39, 0x48, 0xD0, 0x35, 0x8B, 0x94, 0x6D, 0x11, + 0xDE, 0x8F, 0xCA, 0x59, 0x02, 0x81, 0x81, 0x00, 0xEA, 0x24, + 0xA7, 0xF9, 0x69, 0x33, 0xE9, 0x71, 0xDC, 0x52, 0x7D, 0x88, + 0x21, 0x28, 0x2F, 0x49, 0xDE, 0xBA, 0x72, 0x16, 0xE9, 0xCC, + 0x47, 0x7A, 0x88, 0x0D, 0x94, 0x57, 0x84, 0x58, 0x16, 0x3A, + 0x81, 0xB0, 0x3F, 0xA2, 0xCF, 0xA6, 0x6C, 0x1E, 0xB0, 0x06, + 0x29, 0x00, 0x8F, 0xE7, 0x77, 0x76, 0xAC, 0xDB, 0xCA, 0xC7, + 0xD9, 0x5E, 0x9B, 0x3F, 0x26, 0x90, 0x52, 0xAE, 0xFC, 0x38, + 0x90, 0x00, 0x14, 0xBB, 0xB4, 0x0F, 0x58, 0x94, 0xE7, 0x2F, + 0x6A, 0x7E, 0x1C, 0x4F, 0x41, 0x21, 0xD4, 0x31, 0x59, 0x1F, + 0x4E, 0x8A, 0x1A, 0x8D, 0xA7, 0x57, 0x6C, 0x22, 0xD8, 0xE5, + 0xF4, 0x7E, 0x32, 0xA6, 0x10, 0xCB, 0x64, 0xA5, 0x55, 0x03, + 0x87, 0xA6, 0x27, 0x05, 0x8C, 0xC3, 0xD7, 0xB6, 0x27, 0xB2, + 0x4D, 0xBA, 0x30, 0xDA, 0x47, 0x8F, 0x54, 0xD3, 0x3D, 0x8B, + 0x84, 0x8D, 0x94, 0x98, 0x58, 0xA5, 0x02, 0x81, 0x81, 0x00, + 0xD5, 0x38, 0x1B, 0xC3, 0x8F, 0xC5, 0x93, 0x0C, 0x47, 0x0B, + 0x6F, 0x35, 0x92, 0xC5, 0xB0, 0x8D, 0x46, 0xC8, 0x92, 0x18, + 0x8F, 0xF5, 0x80, 0x0A, 0xF7, 0xEF, 0xA1, 0xFE, 0x80, 0xB9, + 0xB5, 0x2A, 0xBA, 0xCA, 0x18, 0xB0, 0x5D, 0xA5, 0x07, 0xD0, + 0x93, 0x8D, 0xD8, 0x9C, 0x04, 0x1C, 0xD4, 0x62, 0x8E, 0xA6, + 0x26, 0x81, 0x01, 0xFF, 0xCE, 0x8A, 0x2A, 0x63, 0x34, 0x35, + 0x40, 0xAA, 0x6D, 0x80, 0xDE, 0x89, 0x23, 0x6A, 0x57, 0x4D, + 0x9E, 0x6E, 0xAD, 0x93, 0x4E, 0x56, 0x90, 0x0B, 0x6D, 0x9D, + 0x73, 0x8B, 0x0C, 0xAE, 0x27, 0x3D, 0xDE, 0x4E, 0xF0, 0xAA, + 0xC5, 0x6C, 0x78, 0x67, 0x6C, 0x94, 0x52, 0x9C, 0x37, 0x67, + 0x6C, 0x2D, 0xEF, 0xBB, 0xAF, 0xDF, 0xA6, 0x90, 0x3C, 0xC4, + 0x47, 0xCF, 0x8D, 0x96, 0x9E, 0x98, 0xA9, 0xB4, 0x9F, 0xC5, + 0xA6, 0x50, 0xDC, 0xB3, 0xF0, 0xFB, 0x74, 0x17, 0x02, 0x81, + 0x80, 0x5E, 0x83, 0x09, 0x62, 0xBD, 0xBA, 0x7C, 0xA2, 0xBF, + 0x42, 0x74, 0xF5, 0x7C, 0x1C, 0xD2, 0x69, 0xC9, 0x04, 0x0D, + 0x85, 0x7E, 0x3E, 0x3D, 0x24, 0x12, 0xC3, 0x18, 0x7B, 0xF3, + 0x29, 0xF3, 0x5F, 0x0E, 0x76, 0x6C, 0x59, 0x75, 0xE4, 0x41, + 0x84, 0x69, 0x9D, 0x32, 0xF3, 0xCD, 0x22, 0xAB, 0xB0, 0x35, + 0xBA, 0x4A, 0xB2, 0x3C, 0xE5, 0xD9, 0x58, 0xB6, 0x62, 0x4F, + 0x5D, 0xDE, 0xE5, 0x9E, 0x0A, 0xCA, 0x53, 0xB2, 0x2C, 0xF7, + 0x9E, 0xB3, 0x6B, 0x0A, 0x5B, 0x79, 0x65, 0xEC, 0x6E, 0x91, + 0x4E, 0x92, 0x20, 0xF6, 0xFC, 0xFC, 0x16, 0xED, 0xD3, 0x76, + 0x0C, 0xE2, 0xEC, 0x7F, 0xB2, 0x69, 0x13, 0x6B, 0x78, 0x0E, + 0x5A, 0x46, 0x64, 0xB4, 0x5E, 0xB7, 0x25, 0xA0, 0x5A, 0x75, + 0x3A, 0x4B, 0xEF, 0xC7, 0x3C, 0x3E, 0xF7, 0xFD, 0x26, 0xB8, + 0x20, 0xC4, 0x99, 0x0A, 0x9A, 0x73, 0xBE, 0xC3, 0x19, 0x02, + 0x81, 0x81, 0x00, 0xBA, 0x44, 0x93, 0x14, 0xAC, 0x34, 0x19, + 0x3B, 0x5F, 0x91, 0x60, 0xAC, 0xF7, 0xB4, 0xD6, 0x81, 0x05, + 0x36, 0x51, 0x53, 0x3D, 0xE8, 0x65, 0xDC, 0xAF, 0x2E, 0xDC, + 0x61, 0x3E, 0xC9, 0x7D, 0xB8, 0x7F, 0x87, 0xF0, 0x3B, 0x9B, + 0x03, 0x82, 0x29, 0x37, 0xCE, 0x72, 0x4E, 0x11, 0xD5, 0xB1, + 0xC1, 0x0C, 0x07, 0xA0, 0x99, 0x91, 0x4A, 0x8D, 0x7F, 0xEC, + 0x79, 0xCF, 0xF1, 0x39, 0xB5, 0xE9, 0x85, 0xEC, 0x62, 0xF7, + 0xDA, 0x7D, 0xBC, 0x64, 0x4D, 0x22, 0x3C, 0x0E, 0xF2, 0xD6, + 0x51, 0xF5, 0x87, 0xD8, 0x99, 0xC0, 0x11, 0x20, 0x5D, 0x0F, + 0x29, 0xFD, 0x5B, 0xE2, 0xAE, 0xD9, 0x1C, 0xD9, 0x21, 0x56, + 0x6D, 0xFC, 0x84, 0xD0, 0x5F, 0xED, 0x10, 0x15, 0x1C, 0x18, + 0x21, 0xE7, 0xC4, 0x3D, 0x4B, 0xD7, 0xD0, 0x9E, 0x6A, 0x95, + 0xCF, 0x22, 0xC9, 0x03, 0x7B, 0x9E, 0xE3, 0x60, 0x01, 0xFC, + 0x2F, 0x02, 0x81, 0x80, 0x11, 0xD0, 0x4B, 0xCF, 0x1B, 0x67, + 0xB9, 0x9F, 0x10, 0x75, 0x47, 0x86, 0x65, 0xAE, 0x31, 0xC2, + 0xC6, 0x30, 0xAC, 0x59, 0x06, 0x50, 0xD9, 0x0F, 0xB5, 0x70, + 0x06, 0xF7, 0xF0, 0xD3, 0xC8, 0x62, 0x7C, 0xA8, 0xDA, 0x6E, + 0xF6, 0x21, 0x3F, 0xD3, 0x7F, 0x5F, 0xEA, 0x8A, 0xAB, 0x3F, + 0xD9, 0x2A, 0x5E, 0xF3, 0x51, 0xD2, 0xC2, 0x30, 0x37, 0xE3, + 0x2D, 0xA3, 0x75, 0x0D, 0x1E, 0x4D, 0x21, 0x34, 0xD5, 0x57, + 0x70, 0x5C, 0x89, 0xBF, 0x72, 0xEC, 0x4A, 0x6E, 0x68, 0xD5, + 0xCD, 0x18, 0x74, 0x33, 0x4E, 0x8C, 0x3A, 0x45, 0x8F, 0xE6, + 0x96, 0x40, 0xEB, 0x63, 0xF9, 0x19, 0x86, 0x3A, 0x51, 0xDD, + 0x89, 0x4B, 0xB0, 0xF3, 0xF9, 0x9F, 0x5D, 0x28, 0x95, 0x38, + 0xBE, 0x35, 0xAB, 0xCA, 0x5C, 0xE7, 0x93, 0x53, 0x34, 0xA1, + 0x45, 0x5D, 0x13, 0x39, 0x65, 0x42, 0x46, 0xA1, 0x9F, 0xCD, + 0xF5, 0xBF +}; +static const int sizeof_client_key_der_2048 = sizeof(client_key_der_2048); + +/* ./certs/client-keyPub.der, 2048-bit */ +static const unsigned char client_keypub_der_2048[] = +{ + 0x30, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, + 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, + 0x01, 0x01, 0x00, 0xC3, 0x03, 0xD1, 0x2B, 0xFE, 0x39, 0xA4, + 0x32, 0x45, 0x3B, 0x53, 0xC8, 0x84, 0x2B, 0x2A, 0x7C, 0x74, + 0x9A, 0xBD, 0xAA, 0x2A, 0x52, 0x07, 0x47, 0xD6, 0xA6, 0x36, + 0xB2, 0x07, 0x32, 0x8E, 0xD0, 0xBA, 0x69, 0x7B, 0xC6, 0xC3, + 0x44, 0x9E, 0xD4, 0x81, 0x48, 0xFD, 0x2D, 0x68, 0xA2, 0x8B, + 0x67, 0xBB, 0xA1, 0x75, 0xC8, 0x36, 0x2C, 0x4A, 0xD2, 0x1B, + 0xF7, 0x8B, 0xBA, 0xCF, 0x0D, 0xF9, 0xEF, 0xEC, 0xF1, 0x81, + 0x1E, 0x7B, 0x9B, 0x03, 0x47, 0x9A, 0xBF, 0x65, 0xCC, 0x7F, + 0x65, 0x24, 0x69, 0xA6, 0xE8, 0x14, 0x89, 0x5B, 0xE4, 0x34, + 0xF7, 0xC5, 0xB0, 0x14, 0x93, 0xF5, 0x67, 0x7B, 0x3A, 0x7A, + 0x78, 0xE1, 0x01, 0x56, 0x56, 0x91, 0xA6, 0x13, 0x42, 0x8D, + 0xD2, 0x3C, 0x40, 0x9C, 0x4C, 0xEF, 0xD1, 0x86, 0xDF, 0x37, + 0x51, 0x1B, 0x0C, 0xA1, 0x3B, 0xF5, 0xF1, 0xA3, 0x4A, 0x35, + 0xE4, 0xE1, 0xCE, 0x96, 0xDF, 0x1B, 0x7E, 0xBF, 0x4E, 0x97, + 0xD0, 0x10, 0xE8, 0xA8, 0x08, 0x30, 0x81, 0xAF, 0x20, 0x0B, + 0x43, 0x14, 0xC5, 0x74, 0x67, 0xB4, 0x32, 0x82, 0x6F, 0x8D, + 0x86, 0xC2, 0x88, 0x40, 0x99, 0x36, 0x83, 0xBA, 0x1E, 0x40, + 0x72, 0x22, 0x17, 0xD7, 0x52, 0x65, 0x24, 0x73, 0xB0, 0xCE, + 0xEF, 0x19, 0xCD, 0xAE, 0xFF, 0x78, 0x6C, 0x7B, 0xC0, 0x12, + 0x03, 0xD4, 0x4E, 0x72, 0x0D, 0x50, 0x6D, 0x3B, 0xA3, 0x3B, + 0xA3, 0x99, 0x5E, 0x9D, 0xC8, 0xD9, 0x0C, 0x85, 0xB3, 0xD9, + 0x8A, 0xD9, 0x54, 0x26, 0xDB, 0x6D, 0xFA, 0xAC, 0xBB, 0xFF, + 0x25, 0x4C, 0xC4, 0xD1, 0x79, 0xF4, 0x71, 0xD3, 0x86, 0x40, + 0x18, 0x13, 0xB0, 0x63, 0xB5, 0x72, 0x4E, 0x30, 0xC4, 0x97, + 0x84, 0x86, 0x2D, 0x56, 0x2F, 0xD7, 0x15, 0xF7, 0x7F, 0xC0, + 0xAE, 0xF5, 0xFC, 0x5B, 0xE5, 0xFB, 0xA1, 0xBA, 0xD3, 0x02, + 0x03, 0x01, 0x00, 0x01 +}; +static const int sizeof_client_keypub_der_2048 = sizeof(client_keypub_der_2048); + +/* ./certs/client-cert.der, 2048-bit */ +static const unsigned char client_cert_der_2048[] = +{ + 0x30, 0x82, 0x04, 0xCA, 0x30, 0x82, 0x03, 0xB2, 0xA0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0xAA, 0xC4, 0xBF, 0x4C, + 0x50, 0xBD, 0x55, 0x77, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, + 0x81, 0x9E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x08, 0x0C, 0x07, 0x4D, 0x6F, 0x6E, 0x74, + 0x61, 0x6E, 0x61, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, + 0x04, 0x07, 0x0C, 0x07, 0x42, 0x6F, 0x7A, 0x65, 0x6D, 0x61, + 0x6E, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0C, 0x77, 0x6F, 0x6C, 0x66, 0x53, 0x53, 0x4C, 0x5F, + 0x32, 0x30, 0x34, 0x38, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, + 0x55, 0x04, 0x0B, 0x0C, 0x10, 0x50, 0x72, 0x6F, 0x67, 0x72, + 0x61, 0x6D, 0x6D, 0x69, 0x6E, 0x67, 0x2D, 0x32, 0x30, 0x34, + 0x38, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, + 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, + 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, + 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, + 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, + 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x38, 0x30, 0x34, 0x31, 0x33, + 0x31, 0x35, 0x32, 0x33, 0x30, 0x39, 0x5A, 0x17, 0x0D, 0x32, + 0x31, 0x30, 0x31, 0x30, 0x37, 0x31, 0x35, 0x32, 0x33, 0x30, + 0x39, 0x5A, 0x30, 0x81, 0x9E, 0x31, 0x0B, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, + 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0C, 0x07, 0x4D, + 0x6F, 0x6E, 0x74, 0x61, 0x6E, 0x61, 0x31, 0x10, 0x30, 0x0E, + 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x42, 0x6F, 0x7A, + 0x65, 0x6D, 0x61, 0x6E, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, + 0x55, 0x04, 0x0A, 0x0C, 0x0C, 0x77, 0x6F, 0x6C, 0x66, 0x53, + 0x53, 0x4C, 0x5F, 0x32, 0x30, 0x34, 0x38, 0x31, 0x19, 0x30, + 0x17, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x10, 0x50, 0x72, + 0x6F, 0x67, 0x72, 0x61, 0x6D, 0x6D, 0x69, 0x6E, 0x67, 0x2D, + 0x32, 0x30, 0x34, 0x38, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, + 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, + 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, + 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, + 0x6F, 0x40, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, + 0x63, 0x6F, 0x6D, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, + 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, + 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, + 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xC3, 0x03, 0xD1, 0x2B, + 0xFE, 0x39, 0xA4, 0x32, 0x45, 0x3B, 0x53, 0xC8, 0x84, 0x2B, + 0x2A, 0x7C, 0x74, 0x9A, 0xBD, 0xAA, 0x2A, 0x52, 0x07, 0x47, + 0xD6, 0xA6, 0x36, 0xB2, 0x07, 0x32, 0x8E, 0xD0, 0xBA, 0x69, + 0x7B, 0xC6, 0xC3, 0x44, 0x9E, 0xD4, 0x81, 0x48, 0xFD, 0x2D, + 0x68, 0xA2, 0x8B, 0x67, 0xBB, 0xA1, 0x75, 0xC8, 0x36, 0x2C, + 0x4A, 0xD2, 0x1B, 0xF7, 0x8B, 0xBA, 0xCF, 0x0D, 0xF9, 0xEF, + 0xEC, 0xF1, 0x81, 0x1E, 0x7B, 0x9B, 0x03, 0x47, 0x9A, 0xBF, + 0x65, 0xCC, 0x7F, 0x65, 0x24, 0x69, 0xA6, 0xE8, 0x14, 0x89, + 0x5B, 0xE4, 0x34, 0xF7, 0xC5, 0xB0, 0x14, 0x93, 0xF5, 0x67, + 0x7B, 0x3A, 0x7A, 0x78, 0xE1, 0x01, 0x56, 0x56, 0x91, 0xA6, + 0x13, 0x42, 0x8D, 0xD2, 0x3C, 0x40, 0x9C, 0x4C, 0xEF, 0xD1, + 0x86, 0xDF, 0x37, 0x51, 0x1B, 0x0C, 0xA1, 0x3B, 0xF5, 0xF1, + 0xA3, 0x4A, 0x35, 0xE4, 0xE1, 0xCE, 0x96, 0xDF, 0x1B, 0x7E, + 0xBF, 0x4E, 0x97, 0xD0, 0x10, 0xE8, 0xA8, 0x08, 0x30, 0x81, + 0xAF, 0x20, 0x0B, 0x43, 0x14, 0xC5, 0x74, 0x67, 0xB4, 0x32, + 0x82, 0x6F, 0x8D, 0x86, 0xC2, 0x88, 0x40, 0x99, 0x36, 0x83, + 0xBA, 0x1E, 0x40, 0x72, 0x22, 0x17, 0xD7, 0x52, 0x65, 0x24, + 0x73, 0xB0, 0xCE, 0xEF, 0x19, 0xCD, 0xAE, 0xFF, 0x78, 0x6C, + 0x7B, 0xC0, 0x12, 0x03, 0xD4, 0x4E, 0x72, 0x0D, 0x50, 0x6D, + 0x3B, 0xA3, 0x3B, 0xA3, 0x99, 0x5E, 0x9D, 0xC8, 0xD9, 0x0C, + 0x85, 0xB3, 0xD9, 0x8A, 0xD9, 0x54, 0x26, 0xDB, 0x6D, 0xFA, + 0xAC, 0xBB, 0xFF, 0x25, 0x4C, 0xC4, 0xD1, 0x79, 0xF4, 0x71, + 0xD3, 0x86, 0x40, 0x18, 0x13, 0xB0, 0x63, 0xB5, 0x72, 0x4E, + 0x30, 0xC4, 0x97, 0x84, 0x86, 0x2D, 0x56, 0x2F, 0xD7, 0x15, + 0xF7, 0x7F, 0xC0, 0xAE, 0xF5, 0xFC, 0x5B, 0xE5, 0xFB, 0xA1, + 0xBA, 0xD3, 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x82, 0x01, + 0x07, 0x30, 0x82, 0x01, 0x03, 0x30, 0x1D, 0x06, 0x03, 0x55, + 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x33, 0xD8, 0x45, 0x66, + 0xD7, 0x68, 0x87, 0x18, 0x7E, 0x54, 0x0D, 0x70, 0x27, 0x91, + 0xC7, 0x26, 0xD7, 0x85, 0x65, 0xC0, 0x30, 0x81, 0xD3, 0x06, + 0x03, 0x55, 0x1D, 0x23, 0x04, 0x81, 0xCB, 0x30, 0x81, 0xC8, + 0x80, 0x14, 0x33, 0xD8, 0x45, 0x66, 0xD7, 0x68, 0x87, 0x18, + 0x7E, 0x54, 0x0D, 0x70, 0x27, 0x91, 0xC7, 0x26, 0xD7, 0x85, + 0x65, 0xC0, 0xA1, 0x81, 0xA4, 0xA4, 0x81, 0xA1, 0x30, 0x81, + 0x9E, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, + 0x55, 0x04, 0x08, 0x0C, 0x07, 0x4D, 0x6F, 0x6E, 0x74, 0x61, + 0x6E, 0x61, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x0C, 0x07, 0x42, 0x6F, 0x7A, 0x65, 0x6D, 0x61, 0x6E, + 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x0C, 0x77, 0x6F, 0x6C, 0x66, 0x53, 0x53, 0x4C, 0x5F, 0x32, + 0x30, 0x34, 0x38, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, + 0x04, 0x0B, 0x0C, 0x10, 0x50, 0x72, 0x6F, 0x67, 0x72, 0x61, + 0x6D, 0x6D, 0x69, 0x6E, 0x67, 0x2D, 0x32, 0x30, 0x34, 0x38, + 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, 0x73, + 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, 0x1D, + 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, + 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, 0x6F, + 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x82, + 0x09, 0x00, 0xAA, 0xC4, 0xBF, 0x4C, 0x50, 0xBD, 0x55, 0x77, + 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, + 0x03, 0x01, 0x01, 0xFF, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03, + 0x82, 0x01, 0x01, 0x00, 0x80, 0x52, 0x54, 0x61, 0x2A, 0x77, + 0x80, 0x53, 0x44, 0xA9, 0x80, 0x6D, 0x45, 0xFF, 0x0D, 0x25, + 0x7D, 0x1A, 0x8F, 0x23, 0x93, 0x53, 0x74, 0x35, 0x12, 0x6F, + 0xF0, 0x2E, 0x20, 0xEA, 0xED, 0x80, 0x63, 0x69, 0x88, 0xE6, + 0x0C, 0xA1, 0x49, 0x30, 0xE0, 0x82, 0xDB, 0x68, 0x0F, 0x7E, + 0x84, 0xAC, 0xFF, 0xFF, 0x7B, 0x42, 0xFA, 0x7E, 0x2F, 0xB2, + 0x52, 0x9F, 0xD2, 0x79, 0x5E, 0x35, 0x12, 0x27, 0x36, 0xBC, + 0xDF, 0x96, 0x58, 0x44, 0x96, 0x55, 0xC8, 0x4A, 0x94, 0x02, + 0x5F, 0x4A, 0x9D, 0xDC, 0xD3, 0x3A, 0xF7, 0x6D, 0xAC, 0x8B, + 0x79, 0x6E, 0xFC, 0xBE, 0x8F, 0x23, 0x58, 0x6A, 0x8A, 0xF5, + 0x38, 0x0A, 0x42, 0xF6, 0x98, 0x74, 0x88, 0x53, 0x2E, 0x02, + 0xAF, 0xE1, 0x0E, 0xBE, 0x6F, 0xCC, 0x74, 0x33, 0x7C, 0xEC, + 0xB4, 0xCB, 0xA7, 0x49, 0x6D, 0x82, 0x42, 0x4F, 0xEB, 0x73, + 0x29, 0xC3, 0x32, 0x00, 0x2B, 0x15, 0xF8, 0x88, 0x7A, 0x8F, + 0x6D, 0x20, 0x1B, 0xAE, 0x65, 0x5F, 0xC5, 0xD0, 0x8A, 0xD1, + 0xE2, 0x64, 0x6D, 0xA3, 0xA8, 0xFE, 0x64, 0xE1, 0xA9, 0x5B, + 0xE6, 0xD0, 0x23, 0xD6, 0x02, 0x72, 0x5A, 0xEC, 0x03, 0x8E, + 0x87, 0x67, 0x19, 0x8D, 0xE4, 0xA8, 0x99, 0x15, 0xC1, 0x3D, + 0x91, 0x48, 0x99, 0x8D, 0xFE, 0xAE, 0x1C, 0xBF, 0xF6, 0x28, + 0x1B, 0x45, 0xBE, 0xAD, 0xEF, 0x72, 0x83, 0x9A, 0xF6, 0xC7, + 0x3B, 0x51, 0xA3, 0x6E, 0x7A, 0x73, 0xBD, 0x83, 0xAA, 0x97, + 0xFD, 0x63, 0xB4, 0xF4, 0x6B, 0x1C, 0x14, 0x81, 0x9A, 0xEF, + 0x14, 0x24, 0xD3, 0xE1, 0x8B, 0xF4, 0x04, 0x04, 0x84, 0x54, + 0x0F, 0x61, 0xA2, 0xA8, 0xF2, 0x50, 0x37, 0x0C, 0x17, 0x0C, + 0xBC, 0xE0, 0xC2, 0x84, 0x85, 0xF4, 0x0B, 0xAE, 0x00, 0xCA, + 0x9F, 0x27, 0xE2, 0x44, 0x4F, 0x15, 0x0B, 0x8B, 0x1D, 0xB4 + +}; +static const int sizeof_client_cert_der_2048 = sizeof(client_cert_der_2048); + +/* ./certs/dh2048.der, 2048-bit */ +static const unsigned char dh_key_der_2048[] = +{ + 0x30, 0x82, 0x01, 0x08, 0x02, 0x82, 0x01, 0x01, 0x00, 0xB0, + 0xA1, 0x08, 0x06, 0x9C, 0x08, 0x13, 0xBA, 0x59, 0x06, 0x3C, + 0xBC, 0x30, 0xD5, 0xF5, 0x00, 0xC1, 0x4F, 0x44, 0xA7, 0xD6, + 0xEF, 0x4A, 0xC6, 0x25, 0x27, 0x1C, 0xE8, 0xD2, 0x96, 0x53, + 0x0A, 0x5C, 0x91, 0xDD, 0xA2, 0xC2, 0x94, 0x84, 0xBF, 0x7D, + 0xB2, 0x44, 0x9F, 0x9B, 0xD2, 0xC1, 0x8A, 0xC5, 0xBE, 0x72, + 0x5C, 0xA7, 0xE7, 0x91, 0xE6, 0xD4, 0x9F, 0x73, 0x07, 0x85, + 0x5B, 0x66, 0x48, 0xC7, 0x70, 0xFA, 0xB4, 0xEE, 0x02, 0xC9, + 0x3D, 0x9A, 0x4A, 0xDA, 0x3D, 0xC1, 0x46, 0x3E, 0x19, 0x69, + 0xD1, 0x17, 0x46, 0x07, 0xA3, 0x4D, 0x9F, 0x2B, 0x96, 0x17, + 0x39, 0x6D, 0x30, 0x8D, 0x2A, 0xF3, 0x94, 0xD3, 0x75, 0xCF, + 0xA0, 0x75, 0xE6, 0xF2, 0x92, 0x1F, 0x1A, 0x70, 0x05, 0xAA, + 0x04, 0x83, 0x57, 0x30, 0xFB, 0xDA, 0x76, 0x93, 0x38, 0x50, + 0xE8, 0x27, 0xFD, 0x63, 0xEE, 0x3C, 0xE5, 0xB7, 0xC8, 0x09, + 0xAE, 0x6F, 0x50, 0x35, 0x8E, 0x84, 0xCE, 0x4A, 0x00, 0xE9, + 0x12, 0x7E, 0x5A, 0x31, 0xD7, 0x33, 0xFC, 0x21, 0x13, 0x76, + 0xCC, 0x16, 0x30, 0xDB, 0x0C, 0xFC, 0xC5, 0x62, 0xA7, 0x35, + 0xB8, 0xEF, 0xB7, 0xB0, 0xAC, 0xC0, 0x36, 0xF6, 0xD9, 0xC9, + 0x46, 0x48, 0xF9, 0x40, 0x90, 0x00, 0x2B, 0x1B, 0xAA, 0x6C, + 0xE3, 0x1A, 0xC3, 0x0B, 0x03, 0x9E, 0x1B, 0xC2, 0x46, 0xE4, + 0x48, 0x4E, 0x22, 0x73, 0x6F, 0xC3, 0x5F, 0xD4, 0x9A, 0xD6, + 0x30, 0x07, 0x48, 0xD6, 0x8C, 0x90, 0xAB, 0xD4, 0xF6, 0xF1, + 0xE3, 0x48, 0xD3, 0x58, 0x4B, 0xA6, 0xB9, 0xCD, 0x29, 0xBF, + 0x68, 0x1F, 0x08, 0x4B, 0x63, 0x86, 0x2F, 0x5C, 0x6B, 0xD6, + 0xB6, 0x06, 0x65, 0xF7, 0xA6, 0xDC, 0x00, 0x67, 0x6B, 0xBB, + 0xC3, 0xA9, 0x41, 0x83, 0xFB, 0xC7, 0xFA, 0xC8, 0xE2, 0x1E, + 0x7E, 0xAF, 0x00, 0x3F, 0x93, 0x02, 0x01, 0x02 +}; +static const int sizeof_dh_key_der_2048 = sizeof(dh_key_der_2048); + +/* ./certs/dsa2048.der, 2048-bit */ +static const unsigned char dsa_key_der_2048[] = +{ + 0x30, 0x82, 0x03, 0x3F, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, + 0x01, 0x00, 0xCC, 0x8E, 0xC9, 0xA0, 0xD5, 0x9A, 0x27, 0x1C, + 0xDA, 0x52, 0xDF, 0xC7, 0xC0, 0xE6, 0x06, 0xA4, 0x3E, 0x8A, + 0x66, 0x49, 0xD0, 0x59, 0x33, 0x51, 0x69, 0xC4, 0x9C, 0x5E, + 0x64, 0x85, 0xC7, 0xF1, 0xAB, 0xD5, 0xD9, 0x62, 0xAC, 0xFD, + 0xA1, 0xE0, 0x1B, 0x57, 0xFF, 0x96, 0xEF, 0x0C, 0x9F, 0xC8, + 0x44, 0x87, 0xEB, 0x5C, 0x91, 0xD0, 0x46, 0x42, 0x09, 0x50, + 0x6A, 0x23, 0xCB, 0x89, 0x6F, 0x55, 0xE9, 0x6A, 0x11, 0xA9, + 0xA8, 0x32, 0xAB, 0x33, 0x0D, 0x51, 0xB5, 0x79, 0x51, 0xB4, + 0xAB, 0xA2, 0x25, 0x11, 0x8D, 0xE5, 0x24, 0xBE, 0xD8, 0xF1, + 0x9D, 0x4E, 0x12, 0x6F, 0xAC, 0x44, 0x54, 0x80, 0xA9, 0xB4, + 0x81, 0x68, 0x4E, 0x44, 0x0E, 0xB8, 0x39, 0xF3, 0xBE, 0x83, + 0x08, 0x74, 0xA2, 0xC6, 0x7A, 0xD7, 0x6A, 0x7D, 0x0A, 0x88, + 0x57, 0x83, 0x48, 0xDC, 0xCF, 0x5E, 0x6F, 0xEE, 0x68, 0x0C, + 0xF7, 0xFF, 0x03, 0x04, 0x90, 0xAA, 0xF7, 0x07, 0x98, 0xF8, + 0x67, 0x5A, 0x83, 0x23, 0x66, 0x47, 0x60, 0xC3, 0x43, 0x6E, + 0x03, 0x91, 0xAC, 0x28, 0x66, 0xCB, 0xF0, 0xD3, 0x05, 0xC8, + 0x09, 0x97, 0xB5, 0xAE, 0x01, 0x5E, 0x80, 0x3B, 0x9D, 0x4F, + 0xDE, 0x3E, 0x94, 0xFE, 0xCB, 0x82, 0xB0, 0xB1, 0xFC, 0x91, + 0x8B, 0x1D, 0x8A, 0xEE, 0xC6, 0x06, 0x1F, 0x37, 0x91, 0x48, + 0xD2, 0xF8, 0x6C, 0x5D, 0x60, 0x13, 0x83, 0xA7, 0x81, 0xAC, + 0xCA, 0x8D, 0xD0, 0x6A, 0x04, 0x0A, 0xEA, 0x3E, 0x22, 0x4E, + 0x13, 0xF1, 0x0D, 0xBB, 0x60, 0x6B, 0xCD, 0xBC, 0x5C, 0x87, + 0xA3, 0x67, 0x2B, 0x42, 0xA1, 0x9F, 0xCD, 0x39, 0x58, 0xBE, + 0x55, 0xB1, 0x93, 0x84, 0xCE, 0xB2, 0x10, 0x4E, 0xE4, 0xC3, + 0x9F, 0xB2, 0x53, 0x61, 0x01, 0x29, 0xAA, 0x96, 0xCB, 0x20, + 0x60, 0x42, 0x1D, 0xBA, 0x75, 0x4B, 0x63, 0xC1, 0x02, 0x15, + 0x00, 0xE7, 0xA5, 0x39, 0xD4, 0x6A, 0x37, 0x5E, 0x95, 0x06, + 0x39, 0x07, 0x77, 0x0A, 0xEB, 0xA0, 0x03, 0xEB, 0x78, 0x82, + 0x9B, 0x02, 0x82, 0x01, 0x01, 0x00, 0x9A, 0xD4, 0x4C, 0x71, + 0x2F, 0xEC, 0xFA, 0x32, 0xB2, 0x80, 0x7E, 0x61, 0x4A, 0x6B, + 0x5F, 0x18, 0x76, 0x43, 0xC3, 0x69, 0xBA, 0x41, 0xC7, 0xA7, + 0x1D, 0x79, 0x01, 0xEC, 0xAF, 0x34, 0x87, 0x67, 0x4F, 0x29, + 0x80, 0xA8, 0x3B, 0x87, 0xF6, 0xE8, 0xA1, 0xE8, 0xCD, 0x1B, + 0x1C, 0x86, 0x38, 0xF6, 0xD1, 0x0C, 0x46, 0x2E, 0xC8, 0xE0, + 0xC9, 0x30, 0x26, 0xD5, 0x2C, 0x7F, 0xC1, 0x08, 0xBF, 0xCC, + 0x5A, 0x82, 0x8E, 0xD4, 0xD4, 0x49, 0xAA, 0xA2, 0xFA, 0xE6, + 0xC1, 0x9D, 0xF0, 0xD9, 0x96, 0xB0, 0xFF, 0x0C, 0x5B, 0x33, + 0x8E, 0x06, 0xDD, 0x9D, 0x28, 0xA9, 0xE9, 0x80, 0x41, 0x3B, + 0xD8, 0x7A, 0x94, 0x21, 0x8F, 0x56, 0xF1, 0xA2, 0xB4, 0x2B, + 0x89, 0x1C, 0x74, 0xFF, 0x7E, 0x91, 0xDC, 0x1F, 0x91, 0x13, + 0x98, 0xAF, 0xC7, 0x06, 0xD2, 0x4C, 0x90, 0xA2, 0xBD, 0xDA, + 0x16, 0xBA, 0x65, 0xB0, 0x2D, 0x68, 0x87, 0x3C, 0x6E, 0x25, + 0x8D, 0x90, 0xC7, 0xBC, 0x0D, 0xA9, 0x43, 0x03, 0xC9, 0xBE, + 0xCF, 0x85, 0x6F, 0xDB, 0x07, 0x7B, 0x8C, 0xF8, 0xB1, 0xC2, + 0x49, 0x10, 0x69, 0x63, 0x56, 0x37, 0xC5, 0x30, 0xD2, 0xFB, + 0x71, 0x9A, 0xE8, 0x82, 0x07, 0x2E, 0x3E, 0x95, 0x50, 0xF3, + 0x73, 0xCF, 0x34, 0x5B, 0xD5, 0xAB, 0x02, 0x15, 0xF2, 0xCC, + 0xD7, 0x52, 0xC5, 0x28, 0xD8, 0x41, 0x19, 0x55, 0x6F, 0xB8, + 0x5F, 0xF1, 0x99, 0xB3, 0xC7, 0xD9, 0xB3, 0x71, 0xF4, 0x2D, + 0xDF, 0x22, 0x59, 0x35, 0x86, 0xDB, 0x39, 0xCA, 0x1B, 0x4D, + 0x35, 0x90, 0x19, 0x6B, 0x31, 0xE3, 0xC8, 0xC6, 0x09, 0xBF, + 0x7C, 0xED, 0x01, 0xB4, 0xB2, 0xF5, 0x6E, 0xDA, 0x63, 0x41, + 0x3C, 0xE6, 0x3A, 0x72, 0x2D, 0x65, 0x48, 0xF6, 0x07, 0xCD, + 0x92, 0x84, 0x8B, 0x1D, 0xA7, 0x31, 0x6B, 0xD6, 0xF0, 0xFB, + 0xD9, 0xF4, 0x02, 0x82, 0x01, 0x00, 0x66, 0x4B, 0xBB, 0xB7, + 0xC9, 0x48, 0x95, 0x0D, 0x5A, 0xA6, 0x2D, 0xA1, 0x7F, 0xDF, + 0x1F, 0x67, 0x6D, 0xED, 0x52, 0x4B, 0x16, 0x6C, 0x17, 0xC6, + 0xAE, 0xF8, 0x6A, 0xC4, 0x57, 0xED, 0x2F, 0xB3, 0xF0, 0x2A, + 0x55, 0xAB, 0xBA, 0xCA, 0xEA, 0x17, 0xE8, 0x35, 0x7C, 0xE5, + 0x31, 0x0D, 0x4A, 0x95, 0xFC, 0x43, 0x6F, 0x97, 0x3C, 0x5C, + 0x67, 0xAC, 0xBE, 0x67, 0x7F, 0xE9, 0x4E, 0xAA, 0x48, 0xB3, + 0x92, 0xA1, 0x76, 0x75, 0xEA, 0x04, 0x34, 0x7F, 0x87, 0x33, + 0x2D, 0x24, 0xB6, 0x29, 0x97, 0xE3, 0x04, 0x77, 0x93, 0x89, + 0x13, 0xDB, 0x1B, 0x93, 0xB8, 0x2C, 0x90, 0x1A, 0x09, 0x3B, + 0x26, 0xD9, 0x59, 0xF3, 0x2A, 0x09, 0x58, 0xDC, 0xAC, 0x25, + 0xB4, 0xA9, 0x45, 0x3B, 0xA2, 0x3A, 0x6C, 0x61, 0x84, 0xBF, + 0x68, 0xD4, 0xEA, 0x9B, 0xC5, 0x29, 0x48, 0x60, 0x15, 0x10, + 0x35, 0x2C, 0x44, 0x1D, 0xB5, 0x9A, 0xEE, 0xAC, 0xC1, 0x68, + 0xE8, 0x47, 0xB7, 0x41, 0x34, 0x39, 0x9A, 0xF8, 0xA5, 0x20, + 0xE9, 0x24, 0xC4, 0x2C, 0x58, 0x3F, 0x4C, 0x41, 0x30, 0x3A, + 0x14, 0x6E, 0x8D, 0xEA, 0xAD, 0xBA, 0x9B, 0x43, 0xD3, 0x98, + 0x2F, 0x83, 0xD8, 0x14, 0x67, 0xE8, 0xF8, 0xD5, 0x4F, 0xAC, + 0xE0, 0x3B, 0xBF, 0xA7, 0x54, 0x16, 0x5E, 0x49, 0x64, 0x26, + 0x54, 0xA4, 0x6B, 0x69, 0x7C, 0xBA, 0x8A, 0x83, 0xD9, 0x2E, + 0x65, 0x0A, 0xA2, 0x27, 0xEF, 0x99, 0x99, 0x08, 0xD7, 0xB5, + 0x9F, 0xA0, 0x01, 0xEF, 0x7E, 0x17, 0xBF, 0x83, 0x6B, 0x2E, + 0xDD, 0xC0, 0x39, 0x38, 0x23, 0x68, 0xB4, 0x76, 0x6B, 0xE5, + 0xCA, 0xF7, 0x7C, 0xEE, 0xC0, 0x52, 0xE2, 0xDD, 0xAD, 0x59, + 0x3A, 0x42, 0x06, 0x45, 0xB0, 0xC7, 0xC1, 0x77, 0x05, 0xB2, + 0x0C, 0x32, 0x40, 0x46, 0xAA, 0xDA, 0x79, 0x77, 0x04, 0x71, + 0xDF, 0x7A, 0x02, 0x15, 0x00, 0x98, 0xEE, 0xB9, 0x51, 0x37, + 0x3E, 0x75, 0x13, 0x13, 0x06, 0x8F, 0x94, 0xD3, 0xE6, 0xE9, + 0x00, 0xCB, 0x62, 0x6D, 0x9A +}; +static const int sizeof_dsa_key_der_2048 = sizeof(dsa_key_der_2048); + +/* ./certs/rsa2048.der, 2048-bit */ +static const unsigned char rsa_key_der_2048[] = +{ + 0x30, 0x82, 0x04, 0xA3, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, + 0x01, 0x00, 0xE9, 0x8A, 0x5D, 0x15, 0xA4, 0xD4, 0x34, 0xB9, + 0x59, 0xA2, 0xDA, 0xAF, 0x74, 0xC8, 0xC9, 0x03, 0x26, 0x38, + 0xFA, 0x48, 0xFC, 0x4D, 0x30, 0x6E, 0xEA, 0x76, 0x89, 0xCE, + 0x4F, 0xF6, 0x87, 0xDE, 0x32, 0x3A, 0x46, 0x6E, 0x38, 0x12, + 0x58, 0x37, 0x22, 0x0D, 0x80, 0xAC, 0x2D, 0xAF, 0x2F, 0x12, + 0x3E, 0x62, 0x73, 0x60, 0x66, 0x68, 0x90, 0xB2, 0x6F, 0x47, + 0x17, 0x04, 0x2B, 0xCA, 0xB7, 0x26, 0xB7, 0x10, 0xC2, 0x13, + 0xF9, 0x7A, 0x62, 0x0A, 0x93, 0x32, 0x90, 0x42, 0x0D, 0x16, + 0x2E, 0xFA, 0xD7, 0x29, 0xD7, 0x9F, 0x54, 0xE4, 0xFC, 0x65, + 0x74, 0xF8, 0xF6, 0x43, 0x6B, 0x4E, 0x9E, 0x34, 0x7F, 0xCB, + 0x6B, 0x1C, 0x1A, 0xDE, 0x82, 0x81, 0xBF, 0x08, 0x5D, 0x3F, + 0xC0, 0xB6, 0xB1, 0xA8, 0xA5, 0x9C, 0x81, 0x70, 0xA7, 0x4E, + 0x32, 0x87, 0x15, 0x1C, 0x78, 0x0E, 0xF0, 0x18, 0xFE, 0xEB, + 0x4B, 0x37, 0x2B, 0xE9, 0xE1, 0xF7, 0xFA, 0x51, 0xC6, 0x58, + 0xB9, 0xD8, 0x06, 0x03, 0xED, 0xC0, 0x03, 0x18, 0x55, 0x8B, + 0x98, 0xFE, 0xB1, 0xF6, 0xD0, 0x3D, 0xFA, 0x63, 0xC0, 0x38, + 0x19, 0xC7, 0x00, 0xEF, 0x4D, 0x99, 0x60, 0xB4, 0xBA, 0xCE, + 0xE3, 0xCE, 0xD9, 0x6B, 0x2D, 0x76, 0x94, 0xFF, 0xFB, 0x77, + 0x18, 0x4A, 0xFE, 0x65, 0xF0, 0x0A, 0x91, 0x5C, 0x3B, 0x22, + 0x94, 0x85, 0xD0, 0x20, 0x18, 0x59, 0x2E, 0xA5, 0x33, 0x03, + 0xAC, 0x1B, 0x5F, 0x78, 0x32, 0x11, 0x25, 0xEE, 0x7F, 0x96, + 0x21, 0xA9, 0xD6, 0x76, 0x97, 0x8D, 0x66, 0x7E, 0xB2, 0x91, + 0xD0, 0x36, 0x2E, 0xA3, 0x1D, 0xBF, 0xF1, 0x85, 0xED, 0xC0, + 0x3E, 0x60, 0xB8, 0x5A, 0x9F, 0xAB, 0x80, 0xE0, 0xEA, 0x5D, + 0x5F, 0x75, 0x56, 0xC7, 0x4D, 0x51, 0x8E, 0xD4, 0x1F, 0x34, + 0xA6, 0x36, 0xF1, 0x30, 0x1F, 0x51, 0x99, 0x2F, 0x02, 0x03, + 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, 0x00, 0x52, 0x11, 0x33, + 0x40, 0xC5, 0xD9, 0x64, 0x65, 0xB5, 0xE0, 0x0A, 0xA5, 0x19, + 0x8E, 0xED, 0x44, 0x54, 0x0C, 0x35, 0xB7, 0xAC, 0x21, 0x9B, + 0xE1, 0x7E, 0x37, 0x05, 0x9A, 0x20, 0x73, 0x6B, 0xAF, 0x63, + 0x4B, 0x23, 0x30, 0xDC, 0x37, 0x66, 0x14, 0x89, 0xBC, 0xE0, + 0xF8, 0xA0, 0x5D, 0x2D, 0x57, 0x65, 0xE0, 0xC6, 0xD6, 0x9B, + 0x66, 0x27, 0x62, 0xEC, 0xC3, 0xB8, 0x8C, 0xD8, 0xAE, 0xB5, + 0xC9, 0xBF, 0x0E, 0xFE, 0x84, 0x72, 0x68, 0xD5, 0x47, 0x0E, + 0x0E, 0xF8, 0xAE, 0x9D, 0x56, 0xAC, 0x4F, 0xAD, 0x88, 0xA0, + 0xA2, 0xF6, 0xFC, 0x38, 0xCD, 0x96, 0x5B, 0x5E, 0x7E, 0xB6, + 0x98, 0xBB, 0xF3, 0x8A, 0xEC, 0xFA, 0xC8, 0xB7, 0x90, 0x75, + 0xA0, 0x0E, 0x77, 0x6B, 0xFD, 0x59, 0x45, 0x5A, 0x0C, 0xFF, + 0x95, 0x8D, 0xCE, 0xFE, 0x9B, 0xF6, 0x19, 0x8E, 0x0B, 0xA1, + 0x0C, 0xEE, 0xC6, 0x79, 0xDD, 0x9D, 0x61, 0x85, 0x5C, 0x19, + 0x6C, 0x47, 0xCC, 0x08, 0xFF, 0xA5, 0x62, 0xDB, 0xE4, 0x2D, + 0x2D, 0xDD, 0x14, 0x67, 0xD6, 0x4A, 0x64, 0x2A, 0x66, 0x49, + 0x54, 0x9C, 0xE3, 0x85, 0x18, 0xE7, 0x31, 0x42, 0xE2, 0xD0, + 0x2C, 0x20, 0xA0, 0x74, 0x0F, 0x1F, 0x20, 0x89, 0xBA, 0xAB, + 0x80, 0xD8, 0x38, 0xD9, 0x46, 0x69, 0xBB, 0xEF, 0xCC, 0x8B, + 0xA1, 0x73, 0xA7, 0xF2, 0xE4, 0x38, 0x5D, 0xD6, 0x75, 0x9F, + 0x88, 0x0E, 0x56, 0xCD, 0xD8, 0x84, 0x59, 0x29, 0x73, 0xF5, + 0xA1, 0x79, 0xDA, 0x7A, 0x1F, 0xBF, 0x73, 0x83, 0xC0, 0x6D, + 0x9F, 0x8B, 0x34, 0x15, 0xC0, 0x6D, 0x69, 0x6A, 0x20, 0xE6, + 0x51, 0xCF, 0x45, 0x6E, 0xCC, 0x05, 0xC4, 0x3A, 0xC0, 0x9E, + 0xAA, 0xC1, 0x06, 0x2F, 0xAB, 0x99, 0x30, 0xE1, 0x6E, 0x9D, + 0x45, 0x7A, 0xFF, 0xA9, 0xCE, 0x70, 0xB8, 0x16, 0x1A, 0x0E, + 0x20, 0xFA, 0xC1, 0x02, 0x81, 0x81, 0x00, 0xFF, 0x30, 0x11, + 0xC2, 0x3C, 0x6B, 0xB4, 0xD6, 0x9E, 0x6B, 0xC1, 0x93, 0xD1, + 0x48, 0xCE, 0x80, 0x2D, 0xBE, 0xAF, 0xF7, 0xBA, 0xB2, 0xD7, + 0xC3, 0xC4, 0x53, 0x6E, 0x15, 0x02, 0xAA, 0x61, 0xB9, 0xEA, + 0x05, 0x9B, 0x79, 0x67, 0x0B, 0xCE, 0xD9, 0xFB, 0x98, 0x8C, + 0x1D, 0x6B, 0xF4, 0x5A, 0xA7, 0xA0, 0x5E, 0x54, 0x18, 0xE9, + 0x31, 0x44, 0x7C, 0xC7, 0x52, 0xD8, 0x6D, 0xA0, 0x3E, 0xD6, + 0x14, 0x2D, 0x7B, 0x15, 0x9D, 0x1E, 0x39, 0x87, 0x96, 0xDD, + 0xA8, 0x33, 0x55, 0x2A, 0x8E, 0x32, 0xC0, 0xC4, 0xE5, 0xB8, + 0xCB, 0xCD, 0x32, 0x8D, 0xAD, 0x7B, 0xE5, 0xC6, 0x7E, 0x4D, + 0x6F, 0xF3, 0xA4, 0xC5, 0xA6, 0x40, 0xBE, 0x90, 0x3A, 0x33, + 0x6A, 0x24, 0xB2, 0x80, 0x81, 0x12, 0xAC, 0xE3, 0x7B, 0x26, + 0x63, 0xCF, 0x88, 0xB9, 0xFF, 0x74, 0x23, 0x37, 0x52, 0xF0, + 0xC4, 0x27, 0x5D, 0x45, 0x1F, 0x02, 0x81, 0x81, 0x00, 0xEA, + 0x48, 0xA7, 0xDD, 0x73, 0x41, 0x56, 0x21, 0x15, 0xF7, 0x42, + 0x45, 0x4D, 0xA9, 0xE1, 0x66, 0x5B, 0xBD, 0x25, 0x7D, 0xF7, + 0xA8, 0x65, 0x13, 0xAE, 0x2D, 0x38, 0x11, 0xCD, 0x93, 0xFC, + 0x30, 0xA3, 0x2C, 0x44, 0xBB, 0xCF, 0xD0, 0x21, 0x8F, 0xFB, + 0xC1, 0xF9, 0xAD, 0x1D, 0xEE, 0x96, 0xCF, 0x97, 0x49, 0x60, + 0x53, 0x80, 0xA5, 0xA2, 0xF8, 0xEE, 0xB9, 0xD5, 0x77, 0x44, + 0xDD, 0xFD, 0x19, 0x2A, 0xF1, 0x81, 0xF4, 0xD9, 0x3C, 0xEC, + 0x73, 0xD0, 0x2A, 0xD8, 0x3C, 0x27, 0x87, 0x79, 0x12, 0x86, + 0xE7, 0x57, 0x0C, 0x59, 0xD1, 0x44, 0x55, 0xAE, 0xC3, 0x4D, + 0x42, 0xAD, 0xA9, 0xB3, 0x28, 0x61, 0xB4, 0x9C, 0xA6, 0x63, + 0xD3, 0x96, 0xB1, 0x75, 0x9F, 0x2A, 0x78, 0x99, 0xE3, 0x1E, + 0x71, 0x47, 0x39, 0xF4, 0x52, 0xE3, 0x66, 0xF1, 0xEB, 0x7F, + 0xEF, 0xC6, 0x81, 0x93, 0x4C, 0x99, 0xF1, 0x02, 0x81, 0x81, + 0x00, 0xC5, 0xB6, 0x20, 0x8C, 0x34, 0xF3, 0xDD, 0xF0, 0x4A, + 0x5D, 0x82, 0x65, 0x5C, 0x48, 0xE4, 0x75, 0x3A, 0xFB, 0xFA, + 0xAA, 0x1C, 0xE4, 0x63, 0x77, 0x31, 0xAC, 0xD2, 0x25, 0x45, + 0x23, 0x6D, 0x03, 0xF5, 0xE4, 0xD2, 0x48, 0x85, 0x26, 0x08, + 0xE5, 0xAA, 0xA0, 0xCE, 0x2E, 0x1D, 0x6D, 0xFC, 0xAE, 0xD2, + 0xF9, 0x42, 0x7E, 0xEA, 0x6D, 0x59, 0x7A, 0xB3, 0x93, 0xE4, + 0x4B, 0x4B, 0x54, 0x63, 0xD8, 0xCE, 0x44, 0x06, 0xC2, 0xEC, + 0x9F, 0xF6, 0x05, 0x55, 0x46, 0xF4, 0x3E, 0x8F, 0xF2, 0x0C, + 0x30, 0x7E, 0x5C, 0xDD, 0x88, 0x49, 0x3B, 0x59, 0xB9, 0x87, + 0xBC, 0xC6, 0xC5, 0x24, 0x8A, 0x10, 0x63, 0x21, 0x1F, 0x66, + 0x1A, 0x3E, 0xF4, 0x58, 0xD1, 0x6C, 0x0D, 0x40, 0xB2, 0xC0, + 0x1D, 0x63, 0x42, 0x0E, 0xC4, 0x56, 0x0E, 0xC0, 0xCC, 0xC2, + 0xD6, 0x66, 0x0E, 0xC4, 0xAB, 0xB5, 0x33, 0xF6, 0x51, 0x02, + 0x81, 0x80, 0x19, 0x7E, 0xE6, 0xA5, 0xB6, 0xD1, 0x39, 0x6A, + 0x48, 0x55, 0xAC, 0x24, 0x96, 0x9B, 0x12, 0x28, 0x6D, 0x7B, + 0x5C, 0x05, 0x25, 0x5A, 0x72, 0x05, 0x7E, 0x42, 0xF5, 0x83, + 0x1A, 0x78, 0x2C, 0x4D, 0xAE, 0xB4, 0x36, 0x96, 0xA9, 0xBA, + 0xE0, 0xAC, 0x26, 0x9D, 0xA9, 0x6A, 0x29, 0x83, 0xB9, 0x6D, + 0xC5, 0xEC, 0xFA, 0x4A, 0x9C, 0x09, 0x6A, 0x7E, 0xE4, 0x9B, + 0xDC, 0x9B, 0x2A, 0x27, 0x6E, 0x4F, 0xBA, 0xD8, 0xA5, 0x67, + 0xDB, 0xEC, 0x41, 0x5F, 0x29, 0x1C, 0x40, 0x83, 0xEB, 0x59, + 0x56, 0xD7, 0xA9, 0x4E, 0xAB, 0xAE, 0x70, 0x67, 0xD1, 0xA3, + 0xF1, 0x6C, 0xD7, 0x8F, 0x96, 0x0E, 0x8D, 0xAC, 0xAB, 0x55, + 0x58, 0x66, 0xD3, 0x1E, 0x47, 0x9B, 0xF0, 0x4C, 0xED, 0xF6, + 0x49, 0xE8, 0xE9, 0x7B, 0x32, 0x61, 0x20, 0x31, 0x95, 0x05, + 0xB2, 0xF6, 0x09, 0xEA, 0x32, 0x14, 0x0F, 0xCF, 0x9A, 0x41, + 0x02, 0x81, 0x80, 0x77, 0x3F, 0xB6, 0x14, 0x8D, 0xC5, 0x13, + 0x08, 0x7E, 0xC9, 0xC4, 0xEA, 0xD4, 0xBA, 0x0D, 0xA4, 0x9E, + 0xB3, 0x6E, 0xDE, 0x1A, 0x7A, 0xF8, 0x89, 0x88, 0xEF, 0x36, + 0x3C, 0x11, 0xBC, 0x83, 0xE8, 0x30, 0x6C, 0x81, 0x7C, 0x47, + 0xF3, 0x4D, 0xCA, 0xEA, 0x56, 0x01, 0x62, 0x55, 0x2E, 0x4B, + 0x89, 0xA9, 0xBD, 0x6F, 0x01, 0xF6, 0x74, 0x02, 0xAA, 0xE3, + 0x84, 0x66, 0x06, 0x95, 0x34, 0xA1, 0xE2, 0xCA, 0x65, 0xFE, + 0xA3, 0x2D, 0x43, 0x97, 0x95, 0x6C, 0x6F, 0xD5, 0xB4, 0x38, + 0xF6, 0xF9, 0x95, 0x30, 0xFA, 0xF8, 0x9C, 0x25, 0x2B, 0xB6, + 0x14, 0x51, 0xCC, 0x2E, 0xB3, 0x5B, 0xD6, 0xDC, 0x1A, 0xEC, + 0x2D, 0x09, 0x5B, 0x3F, 0x3A, 0xD0, 0xB8, 0x4E, 0x27, 0x1F, + 0xDC, 0x2A, 0xEE, 0xAC, 0xA9, 0x59, 0x5D, 0x07, 0x63, 0x11, + 0x83, 0x0B, 0xD4, 0x74, 0x80, 0xB6, 0x7D, 0x62, 0x45, 0xBF, + 0x56 +}; +static const int sizeof_rsa_key_der_2048 = sizeof(rsa_key_der_2048); + +/* ./certs/ca-key.der, 2048-bit */ +static const unsigned char ca_key_der_2048[] = +{ + 0x30, 0x82, 0x04, 0xA4, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, + 0x01, 0x00, 0xBF, 0x0C, 0xCA, 0x2D, 0x14, 0xB2, 0x1E, 0x84, + 0x42, 0x5B, 0xCD, 0x38, 0x1F, 0x4A, 0xF2, 0x4D, 0x75, 0x10, + 0xF1, 0xB6, 0x35, 0x9F, 0xDF, 0xCA, 0x7D, 0x03, 0x98, 0xD3, + 0xAC, 0xDE, 0x03, 0x66, 0xEE, 0x2A, 0xF1, 0xD8, 0xB0, 0x7D, + 0x6E, 0x07, 0x54, 0x0B, 0x10, 0x98, 0x21, 0x4D, 0x80, 0xCB, + 0x12, 0x20, 0xE7, 0xCC, 0x4F, 0xDE, 0x45, 0x7D, 0xC9, 0x72, + 0x77, 0x32, 0xEA, 0xCA, 0x90, 0xBB, 0x69, 0x52, 0x10, 0x03, + 0x2F, 0xA8, 0xF3, 0x95, 0xC5, 0xF1, 0x8B, 0x62, 0x56, 0x1B, + 0xEF, 0x67, 0x6F, 0xA4, 0x10, 0x41, 0x95, 0xAD, 0x0A, 0x9B, + 0xE3, 0xA5, 0xC0, 0xB0, 0xD2, 0x70, 0x76, 0x50, 0x30, 0x5B, + 0xA8, 0xE8, 0x08, 0x2C, 0x7C, 0xED, 0xA7, 0xA2, 0x7A, 0x8D, + 0x38, 0x29, 0x1C, 0xAC, 0xC7, 0xED, 0xF2, 0x7C, 0x95, 0xB0, + 0x95, 0x82, 0x7D, 0x49, 0x5C, 0x38, 0xCD, 0x77, 0x25, 0xEF, + 0xBD, 0x80, 0x75, 0x53, 0x94, 0x3C, 0x3D, 0xCA, 0x63, 0x5B, + 0x9F, 0x15, 0xB5, 0xD3, 0x1D, 0x13, 0x2F, 0x19, 0xD1, 0x3C, + 0xDB, 0x76, 0x3A, 0xCC, 0xB8, 0x7D, 0xC9, 0xE5, 0xC2, 0xD7, + 0xDA, 0x40, 0x6F, 0xD8, 0x21, 0xDC, 0x73, 0x1B, 0x42, 0x2D, + 0x53, 0x9C, 0xFE, 0x1A, 0xFC, 0x7D, 0xAB, 0x7A, 0x36, 0x3F, + 0x98, 0xDE, 0x84, 0x7C, 0x05, 0x67, 0xCE, 0x6A, 0x14, 0x38, + 0x87, 0xA9, 0xF1, 0x8C, 0xB5, 0x68, 0xCB, 0x68, 0x7F, 0x71, + 0x20, 0x2B, 0xF5, 0xA0, 0x63, 0xF5, 0x56, 0x2F, 0xA3, 0x26, + 0xD2, 0xB7, 0x6F, 0xB1, 0x5A, 0x17, 0xD7, 0x38, 0x99, 0x08, + 0xFE, 0x93, 0x58, 0x6F, 0xFE, 0xC3, 0x13, 0x49, 0x08, 0x16, + 0x0B, 0xA7, 0x4D, 0x67, 0x00, 0x52, 0x31, 0x67, 0x23, 0x4E, + 0x98, 0xED, 0x51, 0x45, 0x1D, 0xB9, 0x04, 0xD9, 0x0B, 0xEC, + 0xD8, 0x28, 0xB3, 0x4B, 0xBD, 0xED, 0x36, 0x79, 0x02, 0x03, + 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, 0x00, 0x3D, 0x6E, 0x4E, + 0x60, 0x1A, 0x84, 0x7F, 0x9D, 0x85, 0x7C, 0xE1, 0x4B, 0x07, + 0x7C, 0xE0, 0xD6, 0x99, 0x2A, 0xDE, 0x9D, 0xF9, 0x36, 0x34, + 0x0E, 0x77, 0x0E, 0x3E, 0x08, 0xEA, 0x4F, 0xE5, 0x06, 0x26, + 0xD4, 0xF6, 0x38, 0xF7, 0xDF, 0x0D, 0x0F, 0x1C, 0x2E, 0x06, + 0xA2, 0xF4, 0x2A, 0x68, 0x9C, 0x63, 0x72, 0xE3, 0x35, 0xE6, + 0x04, 0x91, 0x91, 0xB5, 0xC1, 0xB1, 0xA4, 0x54, 0xAC, 0xD7, + 0xC6, 0xFB, 0x41, 0xA0, 0xD6, 0x75, 0x6F, 0xBD, 0x0B, 0x4E, + 0xBF, 0xB1, 0x52, 0xE8, 0x5F, 0x49, 0x26, 0x98, 0x56, 0x47, + 0xC7, 0xDE, 0xE9, 0xEA, 0x3C, 0x60, 0x01, 0xBF, 0x28, 0xDC, + 0x31, 0xBF, 0x49, 0x5F, 0x93, 0x49, 0x87, 0x7A, 0x81, 0x5B, + 0x96, 0x4B, 0x4D, 0xCA, 0x5C, 0x38, 0x4F, 0xB7, 0xE1, 0xB2, + 0xD3, 0xC7, 0x21, 0xDA, 0x3C, 0x12, 0x87, 0x07, 0xE4, 0x1B, + 0xDC, 0x43, 0xEC, 0xE8, 0xEC, 0x54, 0x61, 0xE7, 0xF6, 0xED, + 0xA6, 0x0B, 0x2E, 0xF5, 0xDF, 0x82, 0x7F, 0xC6, 0x1F, 0x61, + 0x19, 0x9C, 0xA4, 0x83, 0x39, 0xDF, 0x21, 0x85, 0x89, 0x6F, + 0x77, 0xAF, 0x86, 0x15, 0x32, 0x08, 0xA2, 0x5A, 0x0B, 0x26, + 0x61, 0xFB, 0x70, 0x0C, 0xCA, 0x9C, 0x38, 0x7D, 0xBC, 0x22, + 0xEE, 0xEB, 0xA3, 0xA8, 0x16, 0x00, 0xF9, 0x8A, 0x80, 0x1E, + 0x00, 0x84, 0xA8, 0x4A, 0x41, 0xF8, 0x84, 0x03, 0x67, 0x2F, + 0x23, 0x5B, 0x2F, 0x9B, 0x6B, 0x26, 0xC3, 0x07, 0x34, 0x94, + 0xA3, 0x03, 0x3B, 0x72, 0xD5, 0x9F, 0x72, 0xE0, 0xAD, 0xCC, + 0x34, 0xAB, 0xBD, 0xC7, 0xD5, 0xF5, 0x26, 0x30, 0x85, 0x0F, + 0x30, 0x23, 0x39, 0x52, 0xFF, 0x3C, 0xCB, 0x99, 0x21, 0x4D, + 0x88, 0xA5, 0xAB, 0xEE, 0x62, 0xB9, 0xC7, 0xE0, 0xBB, 0x47, + 0x87, 0xC1, 0x69, 0xCF, 0x73, 0xF3, 0x30, 0xBE, 0xCE, 0x39, + 0x04, 0x9C, 0xE5, 0x02, 0x81, 0x81, 0x00, 0xE1, 0x76, 0x45, + 0x80, 0x59, 0xB6, 0xD3, 0x49, 0xDF, 0x0A, 0xEF, 0x12, 0xD6, + 0x0F, 0xF0, 0xB7, 0xCB, 0x2A, 0x37, 0xBF, 0xA7, 0xF8, 0xB5, + 0x4D, 0xF5, 0x31, 0x35, 0xAD, 0xE4, 0xA3, 0x94, 0xA1, 0xDB, + 0xF1, 0x96, 0xAD, 0xB5, 0x05, 0x64, 0x85, 0x83, 0xFC, 0x1B, + 0x5B, 0x29, 0xAA, 0xBE, 0xF8, 0x26, 0x3F, 0x76, 0x7E, 0xAD, + 0x1C, 0xF0, 0xCB, 0xD7, 0x26, 0xB4, 0x1B, 0x05, 0x8E, 0x56, + 0x86, 0x7E, 0x08, 0x62, 0x21, 0xC1, 0x86, 0xD6, 0x47, 0x79, + 0x3E, 0xB7, 0x5D, 0xA4, 0xC6, 0x3A, 0xD7, 0xB1, 0x74, 0x20, + 0xF6, 0x50, 0x97, 0x41, 0x04, 0x53, 0xED, 0x3F, 0x26, 0xD6, + 0x6F, 0x91, 0xFA, 0x68, 0x26, 0xEC, 0x2A, 0xDC, 0x9A, 0xF1, + 0xE7, 0xDC, 0xFB, 0x73, 0xF0, 0x79, 0x43, 0x1B, 0x21, 0xA3, + 0x59, 0x04, 0x63, 0x52, 0x07, 0xC9, 0xD7, 0xE6, 0xD1, 0x1B, + 0x5D, 0x5E, 0x96, 0xFA, 0x53, 0x02, 0x81, 0x81, 0x00, 0xD8, + 0xED, 0x4E, 0x64, 0x61, 0x6B, 0x91, 0x0C, 0x61, 0x01, 0xB5, + 0x0F, 0xBB, 0x44, 0x67, 0x53, 0x1E, 0xDC, 0x07, 0xC4, 0x24, + 0x7E, 0x9E, 0x6C, 0x84, 0x23, 0x91, 0x0C, 0xE4, 0x12, 0x04, + 0x16, 0x4D, 0x78, 0x98, 0xCC, 0x96, 0x3D, 0x20, 0x4E, 0x0F, + 0x45, 0x9A, 0xB6, 0xF8, 0xB3, 0x93, 0x0D, 0xB2, 0xA2, 0x1B, + 0x29, 0xF2, 0x26, 0x79, 0xC8, 0xC5, 0xD2, 0x78, 0x7E, 0x5E, + 0x73, 0xF2, 0xD7, 0x70, 0x61, 0xBB, 0x40, 0xCE, 0x61, 0x05, + 0xFE, 0x69, 0x1E, 0x82, 0x29, 0xE6, 0x14, 0xB8, 0xA1, 0xE7, + 0x96, 0xD0, 0x23, 0x3F, 0x05, 0x93, 0x00, 0xF2, 0xE1, 0x4D, + 0x7E, 0xED, 0xB7, 0x96, 0x6C, 0xF7, 0xF0, 0xE4, 0xD1, 0xCF, + 0x01, 0x98, 0x4F, 0xDC, 0x74, 0x54, 0xAA, 0x6D, 0x5E, 0x5A, + 0x41, 0x31, 0xFE, 0xFF, 0x9A, 0xB6, 0xA0, 0x05, 0xDD, 0xA9, + 0x10, 0x54, 0xF8, 0x6B, 0xD0, 0xAA, 0x83, 0x02, 0x81, 0x80, + 0x21, 0xD3, 0x04, 0x8A, 0x44, 0xEB, 0x50, 0xB7, 0x7C, 0x66, + 0xBF, 0x87, 0x2B, 0xE6, 0x28, 0x4E, 0xEA, 0x83, 0xE2, 0xE9, + 0x35, 0xE1, 0xF2, 0x11, 0x47, 0xFF, 0xA1, 0xF5, 0xFC, 0x9F, + 0x2D, 0xE5, 0x3A, 0x81, 0xFC, 0x01, 0x03, 0x6F, 0x53, 0xAD, + 0x54, 0x27, 0xB6, 0x52, 0xEE, 0xE5, 0x56, 0xD1, 0x13, 0xAB, + 0xE1, 0xB3, 0x0F, 0x75, 0x90, 0x0A, 0x84, 0xB4, 0xA1, 0xC0, + 0x8C, 0x0C, 0xD6, 0x9E, 0x46, 0xBA, 0x2B, 0x3E, 0xB5, 0x31, + 0xED, 0x63, 0xBB, 0xA4, 0xD5, 0x0D, 0x8F, 0x72, 0xCD, 0xD1, + 0x1E, 0x26, 0x35, 0xEB, 0xBE, 0x1B, 0x72, 0xFD, 0x9B, 0x39, + 0xB4, 0x87, 0xB7, 0x13, 0xF5, 0xEA, 0x83, 0x45, 0x93, 0x98, + 0xBA, 0x8F, 0xE4, 0x4A, 0xCC, 0xB4, 0x4C, 0xA8, 0x7F, 0x08, + 0xBA, 0x41, 0x49, 0xA8, 0x49, 0x28, 0x3D, 0x5E, 0x3D, 0xC1, + 0xCE, 0x37, 0x00, 0xCB, 0xF9, 0x2C, 0xDD, 0x51, 0x02, 0x81, + 0x81, 0x00, 0xA1, 0x57, 0x9F, 0x3E, 0xB9, 0xD6, 0xAF, 0x83, + 0x6D, 0x83, 0x3F, 0x8F, 0xFB, 0xD0, 0xDC, 0xA8, 0xCE, 0x03, + 0x09, 0x23, 0xB1, 0xA1, 0x1B, 0x63, 0xCA, 0xC4, 0x49, 0x56, + 0x35, 0x2B, 0xD1, 0x2E, 0x65, 0x60, 0x95, 0x05, 0x55, 0x99, + 0x11, 0x35, 0xFD, 0xD5, 0xDF, 0x44, 0xC7, 0xA5, 0x88, 0x72, + 0x5F, 0xB2, 0x82, 0x51, 0xA8, 0x71, 0x45, 0x93, 0x36, 0xCF, + 0x5C, 0x1F, 0x61, 0x51, 0x0C, 0x05, 0x80, 0xE8, 0xAF, 0xC5, + 0x7B, 0xBA, 0x5E, 0x22, 0xE3, 0x3C, 0x75, 0xC3, 0x84, 0x05, + 0x55, 0x6D, 0xD6, 0x3A, 0x2D, 0x84, 0x89, 0x93, 0x33, 0xCB, + 0x38, 0xDA, 0xAA, 0x31, 0x05, 0xCD, 0xCE, 0x6C, 0x2D, 0xDD, + 0x55, 0xD3, 0x57, 0x0B, 0xF0, 0xA5, 0x35, 0x6A, 0xB0, 0xAE, + 0x31, 0xBA, 0x43, 0x96, 0xCA, 0x00, 0xC7, 0x4B, 0xE3, 0x19, + 0x12, 0x43, 0xD3, 0x42, 0xFA, 0x6F, 0xEA, 0x80, 0xC0, 0xD1, + 0x02, 0x81, 0x81, 0x00, 0xB9, 0xDB, 0x89, 0x20, 0x34, 0x27, + 0x70, 0x62, 0x34, 0xEA, 0x5F, 0x25, 0x62, 0x12, 0xF3, 0x9D, + 0x81, 0xBF, 0x48, 0xEE, 0x9A, 0x0E, 0xC1, 0x8D, 0x10, 0xFF, + 0x65, 0x9A, 0x9D, 0x2D, 0x1A, 0x8A, 0x94, 0x5A, 0xC8, 0xC0, + 0xA5, 0xA5, 0x84, 0x61, 0x9E, 0xD4, 0x24, 0xB9, 0xEF, 0xA9, + 0x9D, 0xC9, 0x77, 0x0B, 0xC7, 0x70, 0x66, 0x3D, 0xBA, 0xC8, + 0x54, 0xDF, 0xD2, 0x33, 0xE1, 0xF5, 0x7F, 0xF9, 0x27, 0x61, + 0xBE, 0x57, 0x45, 0xDD, 0xB7, 0x45, 0x17, 0x24, 0xF5, 0x23, + 0xE4, 0x38, 0x0E, 0x91, 0x27, 0xEE, 0xE3, 0x20, 0xD8, 0x14, + 0xC8, 0x94, 0x47, 0x77, 0x40, 0x77, 0x45, 0x18, 0x9E, 0x0D, + 0xCE, 0x79, 0x3F, 0x57, 0x31, 0x56, 0x09, 0x49, 0x67, 0xBE, + 0x94, 0x58, 0x4F, 0xF6, 0xC4, 0xAB, 0xE2, 0x89, 0xE3, 0xE3, + 0x8A, 0xC0, 0x05, 0x55, 0x2C, 0x24, 0xC0, 0x4A, 0x97, 0x04, + 0x27, 0x9A +}; +static const int sizeof_ca_key_der_2048 = sizeof(ca_key_der_2048); + +/* ./certs/ca-cert.der, 2048-bit */ +static const unsigned char ca_cert_der_2048[] = +{ + 0x30, 0x82, 0x04, 0xAA, 0x30, 0x82, 0x03, 0x92, 0xA0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0x86, 0xFF, 0xF5, 0x8E, + 0x10, 0xDE, 0xB8, 0xFB, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, + 0x81, 0x94, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x08, 0x0C, 0x07, 0x4D, 0x6F, 0x6E, 0x74, + 0x61, 0x6E, 0x61, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, + 0x04, 0x07, 0x0C, 0x07, 0x42, 0x6F, 0x7A, 0x65, 0x6D, 0x61, + 0x6E, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x08, 0x53, 0x61, 0x77, 0x74, 0x6F, 0x6F, 0x74, 0x68, + 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, + 0x0A, 0x43, 0x6F, 0x6E, 0x73, 0x75, 0x6C, 0x74, 0x69, 0x6E, + 0x67, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, + 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, + 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, + 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, + 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, + 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x38, 0x30, 0x34, 0x31, 0x33, + 0x31, 0x35, 0x32, 0x33, 0x30, 0x39, 0x5A, 0x17, 0x0D, 0x32, + 0x31, 0x30, 0x31, 0x30, 0x37, 0x31, 0x35, 0x32, 0x33, 0x30, + 0x39, 0x5A, 0x30, 0x81, 0x94, 0x31, 0x0B, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, + 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0C, 0x07, 0x4D, + 0x6F, 0x6E, 0x74, 0x61, 0x6E, 0x61, 0x31, 0x10, 0x30, 0x0E, + 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x42, 0x6F, 0x7A, + 0x65, 0x6D, 0x61, 0x6E, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, + 0x55, 0x04, 0x0A, 0x0C, 0x08, 0x53, 0x61, 0x77, 0x74, 0x6F, + 0x6F, 0x74, 0x68, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, + 0x04, 0x0B, 0x0C, 0x0A, 0x43, 0x6F, 0x6E, 0x73, 0x75, 0x6C, + 0x74, 0x69, 0x6E, 0x67, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, + 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, + 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, + 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, + 0x6F, 0x40, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, + 0x63, 0x6F, 0x6D, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, + 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, + 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, + 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xBF, 0x0C, 0xCA, 0x2D, + 0x14, 0xB2, 0x1E, 0x84, 0x42, 0x5B, 0xCD, 0x38, 0x1F, 0x4A, + 0xF2, 0x4D, 0x75, 0x10, 0xF1, 0xB6, 0x35, 0x9F, 0xDF, 0xCA, + 0x7D, 0x03, 0x98, 0xD3, 0xAC, 0xDE, 0x03, 0x66, 0xEE, 0x2A, + 0xF1, 0xD8, 0xB0, 0x7D, 0x6E, 0x07, 0x54, 0x0B, 0x10, 0x98, + 0x21, 0x4D, 0x80, 0xCB, 0x12, 0x20, 0xE7, 0xCC, 0x4F, 0xDE, + 0x45, 0x7D, 0xC9, 0x72, 0x77, 0x32, 0xEA, 0xCA, 0x90, 0xBB, + 0x69, 0x52, 0x10, 0x03, 0x2F, 0xA8, 0xF3, 0x95, 0xC5, 0xF1, + 0x8B, 0x62, 0x56, 0x1B, 0xEF, 0x67, 0x6F, 0xA4, 0x10, 0x41, + 0x95, 0xAD, 0x0A, 0x9B, 0xE3, 0xA5, 0xC0, 0xB0, 0xD2, 0x70, + 0x76, 0x50, 0x30, 0x5B, 0xA8, 0xE8, 0x08, 0x2C, 0x7C, 0xED, + 0xA7, 0xA2, 0x7A, 0x8D, 0x38, 0x29, 0x1C, 0xAC, 0xC7, 0xED, + 0xF2, 0x7C, 0x95, 0xB0, 0x95, 0x82, 0x7D, 0x49, 0x5C, 0x38, + 0xCD, 0x77, 0x25, 0xEF, 0xBD, 0x80, 0x75, 0x53, 0x94, 0x3C, + 0x3D, 0xCA, 0x63, 0x5B, 0x9F, 0x15, 0xB5, 0xD3, 0x1D, 0x13, + 0x2F, 0x19, 0xD1, 0x3C, 0xDB, 0x76, 0x3A, 0xCC, 0xB8, 0x7D, + 0xC9, 0xE5, 0xC2, 0xD7, 0xDA, 0x40, 0x6F, 0xD8, 0x21, 0xDC, + 0x73, 0x1B, 0x42, 0x2D, 0x53, 0x9C, 0xFE, 0x1A, 0xFC, 0x7D, + 0xAB, 0x7A, 0x36, 0x3F, 0x98, 0xDE, 0x84, 0x7C, 0x05, 0x67, + 0xCE, 0x6A, 0x14, 0x38, 0x87, 0xA9, 0xF1, 0x8C, 0xB5, 0x68, + 0xCB, 0x68, 0x7F, 0x71, 0x20, 0x2B, 0xF5, 0xA0, 0x63, 0xF5, + 0x56, 0x2F, 0xA3, 0x26, 0xD2, 0xB7, 0x6F, 0xB1, 0x5A, 0x17, + 0xD7, 0x38, 0x99, 0x08, 0xFE, 0x93, 0x58, 0x6F, 0xFE, 0xC3, + 0x13, 0x49, 0x08, 0x16, 0x0B, 0xA7, 0x4D, 0x67, 0x00, 0x52, + 0x31, 0x67, 0x23, 0x4E, 0x98, 0xED, 0x51, 0x45, 0x1D, 0xB9, + 0x04, 0xD9, 0x0B, 0xEC, 0xD8, 0x28, 0xB3, 0x4B, 0xBD, 0xED, + 0x36, 0x79, 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x81, 0xFC, + 0x30, 0x81, 0xF9, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, + 0x04, 0x16, 0x04, 0x14, 0x27, 0x8E, 0x67, 0x11, 0x74, 0xC3, + 0x26, 0x1D, 0x3F, 0xED, 0x33, 0x63, 0xB3, 0xA4, 0xD8, 0x1D, + 0x30, 0xE5, 0xE8, 0xD5, 0x30, 0x81, 0xC9, 0x06, 0x03, 0x55, + 0x1D, 0x23, 0x04, 0x81, 0xC1, 0x30, 0x81, 0xBE, 0x80, 0x14, + 0x27, 0x8E, 0x67, 0x11, 0x74, 0xC3, 0x26, 0x1D, 0x3F, 0xED, + 0x33, 0x63, 0xB3, 0xA4, 0xD8, 0x1D, 0x30, 0xE5, 0xE8, 0xD5, + 0xA1, 0x81, 0x9A, 0xA4, 0x81, 0x97, 0x30, 0x81, 0x94, 0x31, + 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0C, 0x07, 0x4D, 0x6F, 0x6E, 0x74, 0x61, 0x6E, 0x61, + 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, + 0x07, 0x42, 0x6F, 0x7A, 0x65, 0x6D, 0x61, 0x6E, 0x31, 0x11, + 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x08, 0x53, + 0x61, 0x77, 0x74, 0x6F, 0x6F, 0x74, 0x68, 0x31, 0x13, 0x30, + 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x0A, 0x43, 0x6F, + 0x6E, 0x73, 0x75, 0x6C, 0x74, 0x69, 0x6E, 0x67, 0x31, 0x18, + 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x77, + 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, + 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, + 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, 0x6F, 0x6C, 0x66, + 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x82, 0x09, 0x00, + 0x86, 0xFF, 0xF5, 0x8E, 0x10, 0xDE, 0xB8, 0xFB, 0x30, 0x0C, + 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, + 0x01, 0xFF, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, + 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03, 0x82, 0x01, + 0x01, 0x00, 0x9E, 0x28, 0x88, 0x72, 0x00, 0xCA, 0xE6, 0xE7, + 0x97, 0xCA, 0xC1, 0xF1, 0x1F, 0x9E, 0x12, 0xB2, 0xB8, 0xC7, + 0x51, 0xEA, 0x28, 0xE1, 0x36, 0xB5, 0x2D, 0xE6, 0x2F, 0x08, + 0x23, 0xCB, 0xA9, 0x4A, 0x87, 0x25, 0xC6, 0x5D, 0x89, 0x45, + 0xEA, 0xF5, 0x00, 0x98, 0xAC, 0x76, 0xFB, 0x1B, 0xAF, 0xF0, + 0xCE, 0x64, 0x9E, 0xDA, 0x08, 0xBF, 0xB6, 0xEB, 0xB4, 0xB5, + 0x0C, 0xA0, 0xE7, 0xF6, 0x47, 0x59, 0x1C, 0x61, 0xCF, 0x2E, + 0x0E, 0x58, 0xA4, 0x82, 0xAC, 0x0F, 0x3F, 0xEC, 0xC4, 0xAE, + 0x80, 0xF7, 0xB0, 0x8A, 0x1E, 0x85, 0x41, 0xE8, 0xFF, 0xFE, + 0xFE, 0x4F, 0x1A, 0x24, 0xD5, 0x49, 0xFA, 0xFB, 0xFE, 0x5E, + 0xE5, 0xD3, 0x91, 0x0E, 0x4F, 0x4E, 0x0C, 0x21, 0x51, 0x71, + 0x83, 0x04, 0x6B, 0x62, 0x7B, 0x4F, 0x59, 0x76, 0x48, 0x81, + 0x1E, 0xB4, 0xF7, 0x04, 0x47, 0x8A, 0x91, 0x57, 0xA3, 0x11, + 0xA9, 0xF2, 0x20, 0xB4, 0x78, 0x33, 0x62, 0x3D, 0xB0, 0x5E, + 0x0D, 0xF9, 0x86, 0x38, 0x82, 0xDA, 0xA1, 0x98, 0x8D, 0x19, + 0x06, 0x87, 0x21, 0x39, 0xB7, 0x02, 0xF7, 0xDA, 0x7D, 0x58, + 0xBA, 0x52, 0x15, 0xD8, 0x3B, 0xC9, 0x7B, 0x58, 0x34, 0xA0, + 0xC7, 0xE2, 0x7C, 0xA9, 0x83, 0x13, 0xE1, 0xB6, 0xEC, 0x01, + 0xBF, 0x52, 0x33, 0x0B, 0xC4, 0xFE, 0x43, 0xD3, 0xC6, 0xA4, + 0x8E, 0x2F, 0x87, 0x7F, 0x7A, 0x44, 0xEA, 0xCA, 0x53, 0x6C, + 0x85, 0xED, 0x65, 0x76, 0x73, 0x31, 0x03, 0x4E, 0xEA, 0xBD, + 0x35, 0x54, 0x13, 0xF3, 0x64, 0x87, 0x6B, 0xDF, 0x34, 0xDD, + 0x34, 0xA1, 0x88, 0x3B, 0xDB, 0x4D, 0xAF, 0x1B, 0x64, 0x90, + 0x92, 0x71, 0x30, 0x8E, 0xC8, 0xCC, 0xE5, 0x60, 0x24, 0xAF, + 0x31, 0x16, 0x39, 0x33, 0x91, 0x50, 0xF9, 0xAB, 0x68, 0x42, + 0x74, 0x7A, 0x35, 0xD9, 0xDD, 0xC8, 0xC4, 0x52 +}; +static const int sizeof_ca_cert_der_2048 = sizeof(ca_cert_der_2048); + +/* ./certs/ca-cert-chain.der, 2048-bit */ +static const unsigned char ca_cert_chain_der[] = +{ + 0x30, 0x82, 0x03, 0xB5, 0x30, 0x82, 0x03, 0x1E, 0xA0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0xDA, 0xFB, 0x6A, 0x0D, + 0xFE, 0xCF, 0x9B, 0x47, 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, 0x30, + 0x81, 0x99, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x08, 0x0C, 0x07, 0x4D, 0x6F, 0x6E, 0x74, + 0x61, 0x6E, 0x61, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, + 0x04, 0x07, 0x0C, 0x07, 0x42, 0x6F, 0x7A, 0x65, 0x6D, 0x61, + 0x6E, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x08, 0x53, 0x61, 0x77, 0x74, 0x6F, 0x6F, 0x74, 0x68, + 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, + 0x0F, 0x43, 0x6F, 0x6E, 0x73, 0x75, 0x6C, 0x74, 0x69, 0x6E, + 0x67, 0x5F, 0x31, 0x30, 0x32, 0x34, 0x31, 0x18, 0x30, 0x16, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x77, 0x77, 0x77, + 0x2E, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, + 0x6F, 0x6D, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, + 0x6E, 0x66, 0x6F, 0x40, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, + 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x30, 0x1E, 0x17, 0x0D, 0x31, + 0x38, 0x30, 0x34, 0x31, 0x33, 0x31, 0x35, 0x32, 0x33, 0x31, + 0x30, 0x5A, 0x17, 0x0D, 0x32, 0x31, 0x30, 0x31, 0x30, 0x37, + 0x31, 0x35, 0x32, 0x33, 0x31, 0x30, 0x5A, 0x30, 0x81, 0x99, + 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, + 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, + 0x04, 0x08, 0x0C, 0x07, 0x4D, 0x6F, 0x6E, 0x74, 0x61, 0x6E, + 0x61, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, + 0x0C, 0x07, 0x42, 0x6F, 0x7A, 0x65, 0x6D, 0x61, 0x6E, 0x31, + 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x08, + 0x53, 0x61, 0x77, 0x74, 0x6F, 0x6F, 0x74, 0x68, 0x31, 0x18, + 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x0F, 0x43, + 0x6F, 0x6E, 0x73, 0x75, 0x6C, 0x74, 0x69, 0x6E, 0x67, 0x5F, + 0x31, 0x30, 0x32, 0x34, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, + 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, + 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, + 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, + 0x6F, 0x40, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, + 0x63, 0x6F, 0x6D, 0x30, 0x81, 0x9F, 0x30, 0x0D, 0x06, 0x09, + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, + 0x00, 0x03, 0x81, 0x8D, 0x00, 0x30, 0x81, 0x89, 0x02, 0x81, + 0x81, 0x00, 0xCD, 0xAC, 0xDD, 0x47, 0xEC, 0xBE, 0xB7, 0x24, + 0xC3, 0x63, 0x1B, 0x54, 0x98, 0x79, 0xE1, 0xC7, 0x31, 0x16, + 0x59, 0xD6, 0x9D, 0x77, 0x9D, 0x8D, 0xE2, 0x8B, 0xED, 0x04, + 0x17, 0xB2, 0xC6, 0xEB, 0xE4, 0x9B, 0x91, 0xBE, 0x31, 0x50, + 0x62, 0x97, 0x58, 0xB5, 0x7F, 0x29, 0xDE, 0xB3, 0x71, 0x24, + 0x0B, 0xBF, 0x97, 0x09, 0x7F, 0x26, 0xDC, 0x2D, 0xEC, 0xA8, + 0x2E, 0xB2, 0x64, 0x2B, 0x7A, 0x2B, 0x35, 0x19, 0x2D, 0xA2, + 0x80, 0xCB, 0x99, 0xFD, 0x94, 0x71, 0x1B, 0x23, 0x8D, 0x54, + 0xDB, 0x2E, 0x62, 0x8D, 0x81, 0x08, 0x2D, 0xF4, 0x24, 0x72, + 0x27, 0x6C, 0xF9, 0xC9, 0x8E, 0xDB, 0x4C, 0x75, 0xBA, 0x9B, + 0x01, 0xF8, 0x3F, 0x18, 0xF4, 0xE6, 0x7F, 0xFB, 0x57, 0x94, + 0x92, 0xCC, 0x88, 0xC4, 0xB4, 0x00, 0xC2, 0xAA, 0xD4, 0xE5, + 0x88, 0x18, 0xB3, 0x11, 0x2F, 0x73, 0xC0, 0xD6, 0x29, 0x09, + 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x82, 0x01, 0x01, 0x30, + 0x81, 0xFE, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, + 0x16, 0x04, 0x14, 0xD3, 0x22, 0x8F, 0x28, 0x2C, 0xE0, 0x05, + 0xEE, 0xD3, 0xED, 0xC3, 0x71, 0x3D, 0xC9, 0xB2, 0x36, 0x3A, + 0x1D, 0xBF, 0xA8, 0x30, 0x81, 0xCE, 0x06, 0x03, 0x55, 0x1D, + 0x23, 0x04, 0x81, 0xC6, 0x30, 0x81, 0xC3, 0x80, 0x14, 0xD3, + 0x22, 0x8F, 0x28, 0x2C, 0xE0, 0x05, 0xEE, 0xD3, 0xED, 0xC3, + 0x71, 0x3D, 0xC9, 0xB2, 0x36, 0x3A, 0x1D, 0xBF, 0xA8, 0xA1, + 0x81, 0x9F, 0xA4, 0x81, 0x9C, 0x30, 0x81, 0x99, 0x31, 0x0B, + 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, + 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0C, 0x07, 0x4D, 0x6F, 0x6E, 0x74, 0x61, 0x6E, 0x61, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, + 0x42, 0x6F, 0x7A, 0x65, 0x6D, 0x61, 0x6E, 0x31, 0x11, 0x30, + 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x08, 0x53, 0x61, + 0x77, 0x74, 0x6F, 0x6F, 0x74, 0x68, 0x31, 0x18, 0x30, 0x16, + 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x0F, 0x43, 0x6F, 0x6E, + 0x73, 0x75, 0x6C, 0x74, 0x69, 0x6E, 0x67, 0x5F, 0x31, 0x30, + 0x32, 0x34, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, + 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, + 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, + 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, + 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, + 0x6D, 0x82, 0x09, 0x00, 0xDA, 0xFB, 0x6A, 0x0D, 0xFE, 0xCF, + 0x9B, 0x47, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, + 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x0D, 0x06, 0x09, + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, + 0x00, 0x03, 0x81, 0x81, 0x00, 0x1D, 0x48, 0xF6, 0x40, 0x41, + 0x04, 0x06, 0xF2, 0xE4, 0x72, 0x2F, 0xEA, 0xFF, 0xC1, 0x67, + 0x6B, 0x15, 0xBB, 0x0A, 0x28, 0x23, 0x28, 0x07, 0xC6, 0xD7, + 0x13, 0x2C, 0xBE, 0x00, 0x00, 0xAC, 0x1D, 0xF7, 0xF4, 0x92, + 0xD3, 0x2B, 0xAF, 0x23, 0xEB, 0x9F, 0x1A, 0xE2, 0x11, 0x3C, + 0x2D, 0x97, 0xF2, 0x0F, 0xAC, 0xAE, 0x97, 0x86, 0x0A, 0xFB, + 0xA8, 0x4F, 0x74, 0x1B, 0xDE, 0x19, 0x51, 0xDB, 0xCD, 0xE2, + 0x11, 0x38, 0xC1, 0xA4, 0x9D, 0x56, 0xAB, 0x47, 0x5C, 0xDE, + 0xBA, 0xEB, 0x27, 0xDF, 0x6D, 0xC8, 0x7E, 0x3A, 0xBD, 0x2E, + 0x9B, 0x2A, 0xAD, 0x22, 0x3B, 0x95, 0xA9, 0xF2, 0x28, 0x03, + 0xBC, 0xE5, 0xEC, 0xCC, 0xF2, 0x08, 0xD4, 0xC8, 0x2F, 0xDB, + 0xEA, 0xFB, 0x2E, 0x52, 0x16, 0x8C, 0x42, 0x02, 0xA4, 0x59, + 0x6D, 0x4C, 0x33, 0xB4, 0x9A, 0xD2, 0x73, 0x4A, 0x1E, 0x9F, + 0xD9, 0xC8, 0x83, 0x30, 0x82, 0x04, 0xAA, 0x30, 0x82, 0x03, + 0x92, 0xA0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0x86, + 0xFF, 0xF5, 0x8E, 0x10, 0xDE, 0xB8, 0xFB, 0x30, 0x0D, 0x06, + 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, + 0x05, 0x00, 0x30, 0x81, 0x94, 0x31, 0x0B, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, + 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0C, 0x07, 0x4D, + 0x6F, 0x6E, 0x74, 0x61, 0x6E, 0x61, 0x31, 0x10, 0x30, 0x0E, + 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x42, 0x6F, 0x7A, + 0x65, 0x6D, 0x61, 0x6E, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, + 0x55, 0x04, 0x0A, 0x0C, 0x08, 0x53, 0x61, 0x77, 0x74, 0x6F, + 0x6F, 0x74, 0x68, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, + 0x04, 0x0B, 0x0C, 0x0A, 0x43, 0x6F, 0x6E, 0x73, 0x75, 0x6C, + 0x74, 0x69, 0x6E, 0x67, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, + 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, + 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, + 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, + 0x6F, 0x40, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, + 0x63, 0x6F, 0x6D, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x38, 0x30, + 0x34, 0x31, 0x33, 0x31, 0x35, 0x32, 0x33, 0x30, 0x39, 0x5A, + 0x17, 0x0D, 0x32, 0x31, 0x30, 0x31, 0x30, 0x37, 0x31, 0x35, + 0x32, 0x33, 0x30, 0x39, 0x5A, 0x30, 0x81, 0x94, 0x31, 0x0B, + 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, + 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0C, 0x07, 0x4D, 0x6F, 0x6E, 0x74, 0x61, 0x6E, 0x61, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, + 0x42, 0x6F, 0x7A, 0x65, 0x6D, 0x61, 0x6E, 0x31, 0x11, 0x30, + 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x08, 0x53, 0x61, + 0x77, 0x74, 0x6F, 0x6F, 0x74, 0x68, 0x31, 0x13, 0x30, 0x11, + 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x0A, 0x43, 0x6F, 0x6E, + 0x73, 0x75, 0x6C, 0x74, 0x69, 0x6E, 0x67, 0x31, 0x18, 0x30, + 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x77, 0x77, + 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, + 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, + 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, + 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, 0x6F, 0x6C, 0x66, 0x73, + 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x30, 0x82, 0x01, 0x22, + 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, + 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0F, 0x00, + 0x30, 0x82, 0x01, 0x0A, 0x02, 0x82, 0x01, 0x01, 0x00, 0xBF, + 0x0C, 0xCA, 0x2D, 0x14, 0xB2, 0x1E, 0x84, 0x42, 0x5B, 0xCD, + 0x38, 0x1F, 0x4A, 0xF2, 0x4D, 0x75, 0x10, 0xF1, 0xB6, 0x35, + 0x9F, 0xDF, 0xCA, 0x7D, 0x03, 0x98, 0xD3, 0xAC, 0xDE, 0x03, + 0x66, 0xEE, 0x2A, 0xF1, 0xD8, 0xB0, 0x7D, 0x6E, 0x07, 0x54, + 0x0B, 0x10, 0x98, 0x21, 0x4D, 0x80, 0xCB, 0x12, 0x20, 0xE7, + 0xCC, 0x4F, 0xDE, 0x45, 0x7D, 0xC9, 0x72, 0x77, 0x32, 0xEA, + 0xCA, 0x90, 0xBB, 0x69, 0x52, 0x10, 0x03, 0x2F, 0xA8, 0xF3, + 0x95, 0xC5, 0xF1, 0x8B, 0x62, 0x56, 0x1B, 0xEF, 0x67, 0x6F, + 0xA4, 0x10, 0x41, 0x95, 0xAD, 0x0A, 0x9B, 0xE3, 0xA5, 0xC0, + 0xB0, 0xD2, 0x70, 0x76, 0x50, 0x30, 0x5B, 0xA8, 0xE8, 0x08, + 0x2C, 0x7C, 0xED, 0xA7, 0xA2, 0x7A, 0x8D, 0x38, 0x29, 0x1C, + 0xAC, 0xC7, 0xED, 0xF2, 0x7C, 0x95, 0xB0, 0x95, 0x82, 0x7D, + 0x49, 0x5C, 0x38, 0xCD, 0x77, 0x25, 0xEF, 0xBD, 0x80, 0x75, + 0x53, 0x94, 0x3C, 0x3D, 0xCA, 0x63, 0x5B, 0x9F, 0x15, 0xB5, + 0xD3, 0x1D, 0x13, 0x2F, 0x19, 0xD1, 0x3C, 0xDB, 0x76, 0x3A, + 0xCC, 0xB8, 0x7D, 0xC9, 0xE5, 0xC2, 0xD7, 0xDA, 0x40, 0x6F, + 0xD8, 0x21, 0xDC, 0x73, 0x1B, 0x42, 0x2D, 0x53, 0x9C, 0xFE, + 0x1A, 0xFC, 0x7D, 0xAB, 0x7A, 0x36, 0x3F, 0x98, 0xDE, 0x84, + 0x7C, 0x05, 0x67, 0xCE, 0x6A, 0x14, 0x38, 0x87, 0xA9, 0xF1, + 0x8C, 0xB5, 0x68, 0xCB, 0x68, 0x7F, 0x71, 0x20, 0x2B, 0xF5, + 0xA0, 0x63, 0xF5, 0x56, 0x2F, 0xA3, 0x26, 0xD2, 0xB7, 0x6F, + 0xB1, 0x5A, 0x17, 0xD7, 0x38, 0x99, 0x08, 0xFE, 0x93, 0x58, + 0x6F, 0xFE, 0xC3, 0x13, 0x49, 0x08, 0x16, 0x0B, 0xA7, 0x4D, + 0x67, 0x00, 0x52, 0x31, 0x67, 0x23, 0x4E, 0x98, 0xED, 0x51, + 0x45, 0x1D, 0xB9, 0x04, 0xD9, 0x0B, 0xEC, 0xD8, 0x28, 0xB3, + 0x4B, 0xBD, 0xED, 0x36, 0x79, 0x02, 0x03, 0x01, 0x00, 0x01, + 0xA3, 0x81, 0xFC, 0x30, 0x81, 0xF9, 0x30, 0x1D, 0x06, 0x03, + 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x27, 0x8E, 0x67, + 0x11, 0x74, 0xC3, 0x26, 0x1D, 0x3F, 0xED, 0x33, 0x63, 0xB3, + 0xA4, 0xD8, 0x1D, 0x30, 0xE5, 0xE8, 0xD5, 0x30, 0x81, 0xC9, + 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x81, 0xC1, 0x30, 0x81, + 0xBE, 0x80, 0x14, 0x27, 0x8E, 0x67, 0x11, 0x74, 0xC3, 0x26, + 0x1D, 0x3F, 0xED, 0x33, 0x63, 0xB3, 0xA4, 0xD8, 0x1D, 0x30, + 0xE5, 0xE8, 0xD5, 0xA1, 0x81, 0x9A, 0xA4, 0x81, 0x97, 0x30, + 0x81, 0x94, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x08, 0x0C, 0x07, 0x4D, 0x6F, 0x6E, 0x74, + 0x61, 0x6E, 0x61, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, + 0x04, 0x07, 0x0C, 0x07, 0x42, 0x6F, 0x7A, 0x65, 0x6D, 0x61, + 0x6E, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x08, 0x53, 0x61, 0x77, 0x74, 0x6F, 0x6F, 0x74, 0x68, + 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, + 0x0A, 0x43, 0x6F, 0x6E, 0x73, 0x75, 0x6C, 0x74, 0x69, 0x6E, + 0x67, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, + 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, + 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, + 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, + 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, + 0x82, 0x09, 0x00, 0x86, 0xFF, 0xF5, 0x8E, 0x10, 0xDE, 0xB8, + 0xFB, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x05, + 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x0D, 0x06, 0x09, 0x2A, + 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, 0x00, + 0x03, 0x82, 0x01, 0x01, 0x00, 0x9E, 0x28, 0x88, 0x72, 0x00, + 0xCA, 0xE6, 0xE7, 0x97, 0xCA, 0xC1, 0xF1, 0x1F, 0x9E, 0x12, + 0xB2, 0xB8, 0xC7, 0x51, 0xEA, 0x28, 0xE1, 0x36, 0xB5, 0x2D, + 0xE6, 0x2F, 0x08, 0x23, 0xCB, 0xA9, 0x4A, 0x87, 0x25, 0xC6, + 0x5D, 0x89, 0x45, 0xEA, 0xF5, 0x00, 0x98, 0xAC, 0x76, 0xFB, + 0x1B, 0xAF, 0xF0, 0xCE, 0x64, 0x9E, 0xDA, 0x08, 0xBF, 0xB6, + 0xEB, 0xB4, 0xB5, 0x0C, 0xA0, 0xE7, 0xF6, 0x47, 0x59, 0x1C, + 0x61, 0xCF, 0x2E, 0x0E, 0x58, 0xA4, 0x82, 0xAC, 0x0F, 0x3F, + 0xEC, 0xC4, 0xAE, 0x80, 0xF7, 0xB0, 0x8A, 0x1E, 0x85, 0x41, + 0xE8, 0xFF, 0xFE, 0xFE, 0x4F, 0x1A, 0x24, 0xD5, 0x49, 0xFA, + 0xFB, 0xFE, 0x5E, 0xE5, 0xD3, 0x91, 0x0E, 0x4F, 0x4E, 0x0C, + 0x21, 0x51, 0x71, 0x83, 0x04, 0x6B, 0x62, 0x7B, 0x4F, 0x59, + 0x76, 0x48, 0x81, 0x1E, 0xB4, 0xF7, 0x04, 0x47, 0x8A, 0x91, + 0x57, 0xA3, 0x11, 0xA9, 0xF2, 0x20, 0xB4, 0x78, 0x33, 0x62, + 0x3D, 0xB0, 0x5E, 0x0D, 0xF9, 0x86, 0x38, 0x82, 0xDA, 0xA1, + 0x98, 0x8D, 0x19, 0x06, 0x87, 0x21, 0x39, 0xB7, 0x02, 0xF7, + 0xDA, 0x7D, 0x58, 0xBA, 0x52, 0x15, 0xD8, 0x3B, 0xC9, 0x7B, + 0x58, 0x34, 0xA0, 0xC7, 0xE2, 0x7C, 0xA9, 0x83, 0x13, 0xE1, + 0xB6, 0xEC, 0x01, 0xBF, 0x52, 0x33, 0x0B, 0xC4, 0xFE, 0x43, + 0xD3, 0xC6, 0xA4, 0x8E, 0x2F, 0x87, 0x7F, 0x7A, 0x44, 0xEA, + 0xCA, 0x53, 0x6C, 0x85, 0xED, 0x65, 0x76, 0x73, 0x31, 0x03, + 0x4E, 0xEA, 0xBD, 0x35, 0x54, 0x13, 0xF3, 0x64, 0x87, 0x6B, + 0xDF, 0x34, 0xDD, 0x34, 0xA1, 0x88, 0x3B, 0xDB, 0x4D, 0xAF, + 0x1B, 0x64, 0x90, 0x92, 0x71, 0x30, 0x8E, 0xC8, 0xCC, 0xE5, + 0x60, 0x24, 0xAF, 0x31, 0x16, 0x39, 0x33, 0x91, 0x50, 0xF9, + 0xAB, 0x68, 0x42, 0x74, 0x7A, 0x35, 0xD9, 0xDD, 0xC8, 0xC4, + 0x52 +}; +static const int sizeof_ca_cert_chain_der = sizeof(ca_cert_chain_der); + +/* ./certs/server-key.der, 2048-bit */ +static const unsigned char server_key_der_2048[] = +{ + 0x30, 0x82, 0x04, 0xA5, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, + 0x01, 0x00, 0xC0, 0x95, 0x08, 0xE1, 0x57, 0x41, 0xF2, 0x71, + 0x6D, 0xB7, 0xD2, 0x45, 0x41, 0x27, 0x01, 0x65, 0xC6, 0x45, + 0xAE, 0xF2, 0xBC, 0x24, 0x30, 0xB8, 0x95, 0xCE, 0x2F, 0x4E, + 0xD6, 0xF6, 0x1C, 0x88, 0xBC, 0x7C, 0x9F, 0xFB, 0xA8, 0x67, + 0x7F, 0xFE, 0x5C, 0x9C, 0x51, 0x75, 0xF7, 0x8A, 0xCA, 0x07, + 0xE7, 0x35, 0x2F, 0x8F, 0xE1, 0xBD, 0x7B, 0xC0, 0x2F, 0x7C, + 0xAB, 0x64, 0xA8, 0x17, 0xFC, 0xCA, 0x5D, 0x7B, 0xBA, 0xE0, + 0x21, 0xE5, 0x72, 0x2E, 0x6F, 0x2E, 0x86, 0xD8, 0x95, 0x73, + 0xDA, 0xAC, 0x1B, 0x53, 0xB9, 0x5F, 0x3F, 0xD7, 0x19, 0x0D, + 0x25, 0x4F, 0xE1, 0x63, 0x63, 0x51, 0x8B, 0x0B, 0x64, 0x3F, + 0xAD, 0x43, 0xB8, 0xA5, 0x1C, 0x5C, 0x34, 0xB3, 0xAE, 0x00, + 0xA0, 0x63, 0xC5, 0xF6, 0x7F, 0x0B, 0x59, 0x68, 0x78, 0x73, + 0xA6, 0x8C, 0x18, 0xA9, 0x02, 0x6D, 0xAF, 0xC3, 0x19, 0x01, + 0x2E, 0xB8, 0x10, 0xE3, 0xC6, 0xCC, 0x40, 0xB4, 0x69, 0xA3, + 0x46, 0x33, 0x69, 0x87, 0x6E, 0xC4, 0xBB, 0x17, 0xA6, 0xF3, + 0xE8, 0xDD, 0xAD, 0x73, 0xBC, 0x7B, 0x2F, 0x21, 0xB5, 0xFD, + 0x66, 0x51, 0x0C, 0xBD, 0x54, 0xB3, 0xE1, 0x6D, 0x5F, 0x1C, + 0xBC, 0x23, 0x73, 0xD1, 0x09, 0x03, 0x89, 0x14, 0xD2, 0x10, + 0xB9, 0x64, 0xC3, 0x2A, 0xD0, 0xA1, 0x96, 0x4A, 0xBC, 0xE1, + 0xD4, 0x1A, 0x5B, 0xC7, 0xA0, 0xC0, 0xC1, 0x63, 0x78, 0x0F, + 0x44, 0x37, 0x30, 0x32, 0x96, 0x80, 0x32, 0x23, 0x95, 0xA1, + 0x77, 0xBA, 0x13, 0xD2, 0x97, 0x73, 0xE2, 0x5D, 0x25, 0xC9, + 0x6A, 0x0D, 0xC3, 0x39, 0x60, 0xA4, 0xB4, 0xB0, 0x69, 0x42, + 0x42, 0x09, 0xE9, 0xD8, 0x08, 0xBC, 0x33, 0x20, 0xB3, 0x58, + 0x22, 0xA7, 0xAA, 0xEB, 0xC4, 0xE1, 0xE6, 0x61, 0x83, 0xC5, + 0xD2, 0x96, 0xDF, 0xD9, 0xD0, 0x4F, 0xAD, 0xD7, 0x02, 0x03, + 0x01, 0x00, 0x01, 0x02, 0x82, 0x01, 0x01, 0x00, 0x9A, 0xD0, + 0x34, 0x0F, 0x52, 0x62, 0x05, 0x50, 0x01, 0xEF, 0x9F, 0xED, + 0x64, 0x6E, 0xC2, 0xC4, 0xDA, 0x1A, 0xF2, 0x84, 0xD7, 0x92, + 0x10, 0x48, 0x92, 0xC4, 0xE9, 0x6A, 0xEB, 0x8B, 0x75, 0x6C, + 0xC6, 0x79, 0x38, 0xF2, 0xC9, 0x72, 0x4A, 0x86, 0x64, 0x54, + 0x95, 0x77, 0xCB, 0xC3, 0x9A, 0x9D, 0xB7, 0xD4, 0x1D, 0xA4, + 0x00, 0xC8, 0x9E, 0x4E, 0xE4, 0xDD, 0xC7, 0xBA, 0x67, 0x16, + 0xC1, 0x74, 0xBC, 0xA9, 0xD6, 0x94, 0x8F, 0x2B, 0x30, 0x1A, + 0xFB, 0xED, 0xDF, 0x21, 0x05, 0x23, 0xD9, 0x4A, 0x39, 0xBD, + 0x98, 0x6B, 0x65, 0x9A, 0xB8, 0xDC, 0xC4, 0x7D, 0xEE, 0xA6, + 0x43, 0x15, 0x2E, 0x3D, 0xBE, 0x1D, 0x22, 0x60, 0x2A, 0x73, + 0x30, 0xD5, 0x3E, 0xD8, 0xA2, 0xAC, 0x86, 0x43, 0x2E, 0xC4, + 0xF5, 0x64, 0x5E, 0x3F, 0x89, 0x75, 0x0F, 0x11, 0xD8, 0x51, + 0x25, 0x4E, 0x9F, 0xD8, 0xAA, 0xA3, 0xCE, 0x60, 0xB3, 0xE2, + 0x8A, 0xD9, 0x7E, 0x1B, 0xF0, 0x64, 0xCA, 0x9A, 0x5B, 0x05, + 0x0B, 0x5B, 0xAA, 0xCB, 0xE5, 0xE3, 0x3F, 0x6E, 0x32, 0x22, + 0x05, 0xF3, 0xD0, 0xFA, 0xEF, 0x74, 0x52, 0x81, 0xE2, 0x5F, + 0x74, 0xD3, 0xBD, 0xFF, 0x31, 0x83, 0x45, 0x75, 0xFA, 0x63, + 0x7A, 0x97, 0x2E, 0xD6, 0xB6, 0x19, 0xC6, 0x92, 0x26, 0xE4, + 0x28, 0x06, 0x50, 0x50, 0x0E, 0x78, 0x2E, 0xA9, 0x78, 0x0D, + 0x14, 0x97, 0xB4, 0x12, 0xD8, 0x31, 0x40, 0xAB, 0xA1, 0x01, + 0x41, 0xC2, 0x30, 0xF8, 0x07, 0x5F, 0x16, 0xE4, 0x61, 0x77, + 0xD2, 0x60, 0xF2, 0x9F, 0x8D, 0xE8, 0xF4, 0xBA, 0xEB, 0x63, + 0xDE, 0x2A, 0x97, 0x81, 0xEF, 0x4C, 0x6C, 0xE6, 0x55, 0x34, + 0x51, 0x2B, 0x28, 0x34, 0xF4, 0x53, 0x1C, 0xC4, 0x58, 0x0A, + 0x3F, 0xBB, 0xAF, 0xB5, 0xF7, 0x4A, 0x85, 0x43, 0x2D, 0x3C, + 0xF1, 0x58, 0x58, 0x81, 0x02, 0x81, 0x81, 0x00, 0xF2, 0x2C, + 0x54, 0x76, 0x39, 0x23, 0x63, 0xC9, 0x10, 0x32, 0xB7, 0x93, + 0xAD, 0xAF, 0xBE, 0x19, 0x75, 0x96, 0x81, 0x64, 0xE6, 0xB5, + 0xB8, 0x89, 0x42, 0x41, 0xD1, 0x6D, 0xD0, 0x1C, 0x1B, 0xF8, + 0x1B, 0xAC, 0x69, 0xCB, 0x36, 0x3C, 0x64, 0x7D, 0xDC, 0xF4, + 0x19, 0xB8, 0xC3, 0x60, 0xB1, 0x57, 0x48, 0x5F, 0x52, 0x4F, + 0x59, 0x3A, 0x55, 0x7F, 0x32, 0xC0, 0x19, 0x43, 0x50, 0x3F, + 0xAE, 0xCE, 0x6F, 0x17, 0xF3, 0x0E, 0x9F, 0x40, 0xCA, 0x4E, + 0xAD, 0x15, 0x3B, 0xC9, 0x79, 0xE9, 0xC0, 0x59, 0x38, 0x73, + 0x70, 0x9C, 0x0A, 0x7C, 0xC9, 0x3A, 0x48, 0x32, 0xA7, 0xD8, + 0x49, 0x75, 0x0A, 0x85, 0xC2, 0xC2, 0xFD, 0x15, 0x73, 0xDA, + 0x99, 0x09, 0x2A, 0x69, 0x9A, 0x9F, 0x0A, 0x71, 0xBF, 0xB0, + 0x04, 0xA6, 0x8C, 0x7A, 0x5A, 0x6F, 0x48, 0x5A, 0x54, 0x3B, + 0xC6, 0xB1, 0x53, 0x17, 0xDF, 0xE7, 0x02, 0x81, 0x81, 0x00, + 0xCB, 0x93, 0xDE, 0x77, 0x15, 0x5D, 0xB7, 0x5C, 0x5C, 0x7C, + 0xD8, 0x90, 0xA9, 0x98, 0x2D, 0xD6, 0x69, 0x0E, 0x63, 0xB3, + 0xA3, 0xDC, 0xA6, 0xCC, 0x8B, 0x6A, 0xA4, 0xA2, 0x12, 0x8C, + 0x8E, 0x7B, 0x48, 0x2C, 0xB2, 0x4B, 0x37, 0xDC, 0x06, 0x18, + 0x7D, 0xEA, 0xFE, 0x76, 0xA1, 0xD4, 0xA1, 0xE9, 0x3F, 0x0D, + 0xCD, 0x1B, 0x5F, 0xAF, 0x5F, 0x9E, 0x96, 0x5B, 0x5B, 0x0F, + 0xA1, 0x7C, 0xAF, 0xB3, 0x9B, 0x90, 0xDB, 0x57, 0x73, 0x3A, + 0xED, 0xB0, 0x23, 0x44, 0xAE, 0x41, 0x4F, 0x1F, 0x07, 0x42, + 0x13, 0x23, 0x4C, 0xCB, 0xFA, 0xF4, 0x14, 0xA4, 0xD5, 0xF7, + 0x9E, 0x36, 0x7C, 0x5B, 0x9F, 0xA8, 0x3C, 0xC1, 0x85, 0x5F, + 0x74, 0xD2, 0x39, 0x2D, 0xFF, 0xD0, 0x84, 0xDF, 0xFB, 0xB3, + 0x20, 0x7A, 0x2E, 0x9B, 0x17, 0xAE, 0xE6, 0xBA, 0x0B, 0xAE, + 0x5F, 0x53, 0xA4, 0x52, 0xED, 0x1B, 0xC4, 0x91, 0x02, 0x81, + 0x81, 0x00, 0xEC, 0x98, 0xDA, 0xBB, 0xD5, 0xFE, 0xF9, 0x52, + 0x4A, 0x7D, 0x02, 0x55, 0x49, 0x6F, 0x55, 0x6E, 0x52, 0x2F, + 0x84, 0xA3, 0x2B, 0xB3, 0x86, 0x62, 0xB3, 0x54, 0xD2, 0x63, + 0x52, 0xDA, 0xE3, 0x88, 0x76, 0xA0, 0xEF, 0x8B, 0x15, 0xA5, + 0xD3, 0x18, 0x14, 0x72, 0x77, 0x5E, 0xC7, 0xA3, 0x04, 0x1F, + 0x9E, 0x19, 0x62, 0xB5, 0x1B, 0x1B, 0x9E, 0xC3, 0xF2, 0xB5, + 0x32, 0xF9, 0x4C, 0xC1, 0xAA, 0xEB, 0x0C, 0x26, 0x7D, 0xD4, + 0x5F, 0x4A, 0x51, 0x5C, 0xA4, 0x45, 0x06, 0x70, 0x44, 0xA7, + 0x56, 0xC0, 0xD4, 0x22, 0x14, 0x76, 0x9E, 0xD8, 0x63, 0x50, + 0x89, 0x90, 0xD3, 0xE2, 0xBF, 0x81, 0x95, 0x92, 0x31, 0x41, + 0x87, 0x39, 0x1A, 0x43, 0x0B, 0x18, 0xA5, 0x53, 0x1F, 0x39, + 0x1A, 0x5F, 0x1F, 0x43, 0xBC, 0x87, 0x6A, 0xDF, 0x6E, 0xD3, + 0x22, 0x00, 0xFE, 0x22, 0x98, 0x70, 0x4E, 0x1A, 0x19, 0x29, + 0x02, 0x81, 0x81, 0x00, 0x8A, 0x41, 0x56, 0x28, 0x51, 0x9E, + 0x5F, 0xD4, 0x9E, 0x0B, 0x3B, 0x98, 0xA3, 0x54, 0xF2, 0x6C, + 0x56, 0xD4, 0xAA, 0xE9, 0x69, 0x33, 0x85, 0x24, 0x0C, 0xDA, + 0xD4, 0x0C, 0x2D, 0xC4, 0xBF, 0x4F, 0x02, 0x69, 0x38, 0x7C, + 0xD4, 0xE6, 0xDC, 0x4C, 0xED, 0xD7, 0x16, 0x11, 0xC3, 0x3E, + 0x00, 0xE7, 0xC3, 0x26, 0xC0, 0x51, 0x02, 0xDE, 0xBB, 0x75, + 0x9C, 0x6F, 0x56, 0x9C, 0x7A, 0xF3, 0x8E, 0xEF, 0xCF, 0x8A, + 0xC5, 0x2B, 0xD2, 0xDA, 0x06, 0x6A, 0x44, 0xC9, 0x73, 0xFE, + 0x6E, 0x99, 0x87, 0xF8, 0x5B, 0xBE, 0xF1, 0x7C, 0xE6, 0x65, + 0xB5, 0x4F, 0x6C, 0xF0, 0xC9, 0xC5, 0xFF, 0x16, 0xCA, 0x8B, + 0x1B, 0x17, 0xE2, 0x58, 0x3D, 0xA2, 0x37, 0xAB, 0x01, 0xBC, + 0xBF, 0x40, 0xCE, 0x53, 0x8C, 0x8E, 0xED, 0xEF, 0xEE, 0x59, + 0x9D, 0xE0, 0x63, 0xE6, 0x7C, 0x5E, 0xF5, 0x8E, 0x4B, 0xF1, + 0x3B, 0xC1, 0x02, 0x81, 0x80, 0x4D, 0x45, 0xF9, 0x40, 0x8C, + 0xC5, 0x5B, 0xF4, 0x2A, 0x1A, 0x8A, 0xB4, 0xF2, 0x1C, 0xAC, + 0x6B, 0xE9, 0x0C, 0x56, 0x36, 0xB7, 0x4E, 0x72, 0x96, 0xD5, + 0xE5, 0x8A, 0xD2, 0xE2, 0xFF, 0xF1, 0xF1, 0x18, 0x13, 0x3D, + 0x86, 0x09, 0xB8, 0xD8, 0x76, 0xA7, 0xC9, 0x1C, 0x71, 0x52, + 0x94, 0x30, 0x43, 0xE0, 0xF1, 0x78, 0x74, 0xFD, 0x61, 0x1B, + 0x4C, 0x09, 0xCC, 0xE6, 0x68, 0x2A, 0x71, 0xAD, 0x1C, 0xDF, + 0x43, 0xBC, 0x56, 0xDB, 0xA5, 0xA4, 0xBE, 0x35, 0x70, 0xA4, + 0x5E, 0xCF, 0x4F, 0xFC, 0x00, 0x55, 0x99, 0x3A, 0x3D, 0x23, + 0xCF, 0x67, 0x5A, 0xF5, 0x22, 0xF8, 0xB5, 0x29, 0xD0, 0x44, + 0x11, 0xEB, 0x35, 0x2E, 0x46, 0xBE, 0xFD, 0x8E, 0x18, 0xB2, + 0x5F, 0xA8, 0xBF, 0x19, 0x32, 0xA1, 0xF5, 0xDC, 0x03, 0xE6, + 0x7C, 0x9A, 0x1F, 0x0C, 0x7C, 0xA9, 0xB0, 0x0E, 0x21, 0x37, + 0x3B, 0xF1, 0xB0 +}; +static const int sizeof_server_key_der_2048 = sizeof(server_key_der_2048); + +/* ./certs/server-cert.der, 2048-bit */ +static const unsigned char server_cert_der_2048[] = +{ + 0x30, 0x82, 0x04, 0x9E, 0x30, 0x82, 0x03, 0x86, 0xA0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x30, 0x0D, 0x06, 0x09, + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, + 0x00, 0x30, 0x81, 0x94, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, + 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, + 0x0E, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0C, 0x07, 0x4D, 0x6F, + 0x6E, 0x74, 0x61, 0x6E, 0x61, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x42, 0x6F, 0x7A, 0x65, + 0x6D, 0x61, 0x6E, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, + 0x04, 0x0A, 0x0C, 0x08, 0x53, 0x61, 0x77, 0x74, 0x6F, 0x6F, + 0x74, 0x68, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x0C, 0x0A, 0x43, 0x6F, 0x6E, 0x73, 0x75, 0x6C, 0x74, + 0x69, 0x6E, 0x67, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, + 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, + 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, + 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, + 0x40, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, + 0x6F, 0x6D, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x38, 0x30, 0x34, + 0x31, 0x33, 0x31, 0x35, 0x32, 0x33, 0x31, 0x30, 0x5A, 0x17, + 0x0D, 0x32, 0x31, 0x30, 0x31, 0x30, 0x37, 0x31, 0x35, 0x32, + 0x33, 0x31, 0x30, 0x5A, 0x30, 0x81, 0x90, 0x31, 0x0B, 0x30, + 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, + 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0C, + 0x07, 0x4D, 0x6F, 0x6E, 0x74, 0x61, 0x6E, 0x61, 0x31, 0x10, + 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x42, + 0x6F, 0x7A, 0x65, 0x6D, 0x61, 0x6E, 0x31, 0x10, 0x30, 0x0E, + 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x77, 0x6F, 0x6C, + 0x66, 0x53, 0x53, 0x4C, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, + 0x55, 0x04, 0x0B, 0x0C, 0x07, 0x53, 0x75, 0x70, 0x70, 0x6F, + 0x72, 0x74, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, + 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, + 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, + 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, + 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, + 0x6D, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0D, 0x06, 0x09, 0x2A, + 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, + 0x03, 0x82, 0x01, 0x0F, 0x00, 0x30, 0x82, 0x01, 0x0A, 0x02, + 0x82, 0x01, 0x01, 0x00, 0xC0, 0x95, 0x08, 0xE1, 0x57, 0x41, + 0xF2, 0x71, 0x6D, 0xB7, 0xD2, 0x45, 0x41, 0x27, 0x01, 0x65, + 0xC6, 0x45, 0xAE, 0xF2, 0xBC, 0x24, 0x30, 0xB8, 0x95, 0xCE, + 0x2F, 0x4E, 0xD6, 0xF6, 0x1C, 0x88, 0xBC, 0x7C, 0x9F, 0xFB, + 0xA8, 0x67, 0x7F, 0xFE, 0x5C, 0x9C, 0x51, 0x75, 0xF7, 0x8A, + 0xCA, 0x07, 0xE7, 0x35, 0x2F, 0x8F, 0xE1, 0xBD, 0x7B, 0xC0, + 0x2F, 0x7C, 0xAB, 0x64, 0xA8, 0x17, 0xFC, 0xCA, 0x5D, 0x7B, + 0xBA, 0xE0, 0x21, 0xE5, 0x72, 0x2E, 0x6F, 0x2E, 0x86, 0xD8, + 0x95, 0x73, 0xDA, 0xAC, 0x1B, 0x53, 0xB9, 0x5F, 0x3F, 0xD7, + 0x19, 0x0D, 0x25, 0x4F, 0xE1, 0x63, 0x63, 0x51, 0x8B, 0x0B, + 0x64, 0x3F, 0xAD, 0x43, 0xB8, 0xA5, 0x1C, 0x5C, 0x34, 0xB3, + 0xAE, 0x00, 0xA0, 0x63, 0xC5, 0xF6, 0x7F, 0x0B, 0x59, 0x68, + 0x78, 0x73, 0xA6, 0x8C, 0x18, 0xA9, 0x02, 0x6D, 0xAF, 0xC3, + 0x19, 0x01, 0x2E, 0xB8, 0x10, 0xE3, 0xC6, 0xCC, 0x40, 0xB4, + 0x69, 0xA3, 0x46, 0x33, 0x69, 0x87, 0x6E, 0xC4, 0xBB, 0x17, + 0xA6, 0xF3, 0xE8, 0xDD, 0xAD, 0x73, 0xBC, 0x7B, 0x2F, 0x21, + 0xB5, 0xFD, 0x66, 0x51, 0x0C, 0xBD, 0x54, 0xB3, 0xE1, 0x6D, + 0x5F, 0x1C, 0xBC, 0x23, 0x73, 0xD1, 0x09, 0x03, 0x89, 0x14, + 0xD2, 0x10, 0xB9, 0x64, 0xC3, 0x2A, 0xD0, 0xA1, 0x96, 0x4A, + 0xBC, 0xE1, 0xD4, 0x1A, 0x5B, 0xC7, 0xA0, 0xC0, 0xC1, 0x63, + 0x78, 0x0F, 0x44, 0x37, 0x30, 0x32, 0x96, 0x80, 0x32, 0x23, + 0x95, 0xA1, 0x77, 0xBA, 0x13, 0xD2, 0x97, 0x73, 0xE2, 0x5D, + 0x25, 0xC9, 0x6A, 0x0D, 0xC3, 0x39, 0x60, 0xA4, 0xB4, 0xB0, + 0x69, 0x42, 0x42, 0x09, 0xE9, 0xD8, 0x08, 0xBC, 0x33, 0x20, + 0xB3, 0x58, 0x22, 0xA7, 0xAA, 0xEB, 0xC4, 0xE1, 0xE6, 0x61, + 0x83, 0xC5, 0xD2, 0x96, 0xDF, 0xD9, 0xD0, 0x4F, 0xAD, 0xD7, + 0x02, 0x03, 0x01, 0x00, 0x01, 0xA3, 0x81, 0xFC, 0x30, 0x81, + 0xF9, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, + 0x04, 0x14, 0xB3, 0x11, 0x32, 0xC9, 0x92, 0x98, 0x84, 0xE2, + 0xC9, 0xF8, 0xD0, 0x3B, 0x6E, 0x03, 0x42, 0xCA, 0x1F, 0x0E, + 0x8E, 0x3C, 0x30, 0x81, 0xC9, 0x06, 0x03, 0x55, 0x1D, 0x23, + 0x04, 0x81, 0xC1, 0x30, 0x81, 0xBE, 0x80, 0x14, 0x27, 0x8E, + 0x67, 0x11, 0x74, 0xC3, 0x26, 0x1D, 0x3F, 0xED, 0x33, 0x63, + 0xB3, 0xA4, 0xD8, 0x1D, 0x30, 0xE5, 0xE8, 0xD5, 0xA1, 0x81, + 0x9A, 0xA4, 0x81, 0x97, 0x30, 0x81, 0x94, 0x31, 0x0B, 0x30, + 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, + 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0C, + 0x07, 0x4D, 0x6F, 0x6E, 0x74, 0x61, 0x6E, 0x61, 0x31, 0x10, + 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x42, + 0x6F, 0x7A, 0x65, 0x6D, 0x61, 0x6E, 0x31, 0x11, 0x30, 0x0F, + 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x08, 0x53, 0x61, 0x77, + 0x74, 0x6F, 0x6F, 0x74, 0x68, 0x31, 0x13, 0x30, 0x11, 0x06, + 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x0A, 0x43, 0x6F, 0x6E, 0x73, + 0x75, 0x6C, 0x74, 0x69, 0x6E, 0x67, 0x31, 0x18, 0x30, 0x16, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x77, 0x77, 0x77, + 0x2E, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, + 0x6F, 0x6D, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, + 0x6E, 0x66, 0x6F, 0x40, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, + 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x82, 0x09, 0x00, 0x86, 0xFF, + 0xF5, 0x8E, 0x10, 0xDE, 0xB8, 0xFB, 0x30, 0x0C, 0x06, 0x03, + 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, + 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, + 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, + 0xB4, 0x54, 0x60, 0xAD, 0xA0, 0x03, 0x32, 0xDE, 0x02, 0x7F, + 0x21, 0x4A, 0x81, 0xC6, 0xED, 0xCD, 0xCD, 0xD8, 0x12, 0x8A, + 0xC0, 0xBA, 0x82, 0x5B, 0x75, 0xAD, 0x54, 0xE3, 0x7C, 0x80, + 0x6A, 0xAC, 0x2E, 0x6C, 0x20, 0x4E, 0xBE, 0x4D, 0x82, 0xA7, + 0x47, 0x13, 0x5C, 0xF4, 0xC6, 0x6A, 0x2B, 0x10, 0x99, 0x58, + 0xDE, 0xAB, 0x6B, 0x7C, 0x22, 0x05, 0xC1, 0x83, 0x9D, 0xCB, + 0xFF, 0x3C, 0xE4, 0x2D, 0x57, 0x6A, 0xA6, 0x96, 0xDF, 0xD3, + 0xC1, 0x68, 0xE3, 0xD2, 0xC6, 0x83, 0x4B, 0x97, 0xE2, 0xC6, + 0x32, 0x0E, 0xBE, 0xC4, 0x03, 0xB9, 0x07, 0x8A, 0x5B, 0xB8, + 0x84, 0xBA, 0xC5, 0x39, 0x3F, 0x1C, 0x58, 0xA7, 0x55, 0xD7, + 0xF0, 0x9B, 0xE8, 0xD2, 0x45, 0xB9, 0xE3, 0x83, 0x2E, 0xEE, + 0xB6, 0x71, 0x56, 0xB9, 0x3A, 0xEE, 0x3F, 0x27, 0xD8, 0x77, + 0xE8, 0xFB, 0x44, 0x48, 0x65, 0x27, 0x47, 0x4C, 0xFB, 0xFE, + 0x72, 0xC3, 0xAC, 0x05, 0x7B, 0x1D, 0xCB, 0xEB, 0x5E, 0x65, + 0x9A, 0xAB, 0x02, 0xE4, 0x88, 0x5B, 0x3B, 0x8B, 0x0B, 0xC7, + 0xCC, 0xA9, 0xA6, 0x8B, 0xE1, 0x87, 0xB0, 0x19, 0x1A, 0x0C, + 0x28, 0x58, 0x6F, 0x99, 0x52, 0x7E, 0xED, 0xB0, 0x3A, 0x68, + 0x3B, 0x8C, 0x0A, 0x08, 0x74, 0x72, 0xAB, 0xB9, 0x09, 0xC5, + 0xED, 0x04, 0x7E, 0x6F, 0x0B, 0x1C, 0x09, 0x21, 0xD0, 0xCD, + 0x7F, 0xF9, 0xC4, 0x5E, 0x27, 0x20, 0xE4, 0x85, 0x73, 0x52, + 0x05, 0xD2, 0xBA, 0xF8, 0xD5, 0x8F, 0x41, 0xCC, 0x23, 0x2E, + 0x12, 0x6D, 0xBC, 0x31, 0x98, 0xE7, 0x63, 0xA3, 0x8E, 0x26, + 0xCD, 0xE8, 0x2B, 0x88, 0xEE, 0xE2, 0xFE, 0x3A, 0x74, 0x52, + 0x34, 0x0E, 0xFD, 0x12, 0xE5, 0x5E, 0x69, 0x50, 0x20, 0x31, + 0x34, 0xE4, 0x31, 0xF1, 0xE7, 0xE4, 0x5B, 0x03, 0x13, 0xDA, + 0xAC, 0x41, 0x6C, 0xE7, 0xCF, 0x2B +}; +static const int sizeof_server_cert_der_2048 = sizeof(server_cert_der_2048); + +#endif /* USE_CERT_BUFFERS_2048 */ + +#ifdef USE_CERT_BUFFERS_3072 + +/* ./certs/dh3072.der, 3072-bit */ +static const unsigned char dh_key_der_3072[] = +{ + 0x30, 0x82, 0x01, 0x88, 0x02, 0x82, 0x01, 0x81, 0x00, 0x89, + 0x1B, 0x75, 0x3F, 0x84, 0xB6, 0x11, 0xED, 0x21, 0xF1, 0x08, + 0x0F, 0xB8, 0x06, 0xC9, 0xA3, 0xC9, 0x41, 0xDB, 0x5A, 0xC8, + 0xF8, 0x82, 0x73, 0x0F, 0xEB, 0x89, 0x1E, 0x54, 0x18, 0xBE, + 0xE6, 0x48, 0x41, 0x9E, 0xFA, 0xC2, 0x0C, 0x50, 0x67, 0xC3, + 0x5D, 0xB5, 0xF5, 0x0F, 0x23, 0x6A, 0x43, 0x33, 0x91, 0xD9, + 0x40, 0xF3, 0x66, 0xC6, 0x99, 0xFF, 0x97, 0xB6, 0x7B, 0xAF, + 0x27, 0x72, 0x3B, 0x9F, 0x7E, 0x58, 0x18, 0x14, 0x9F, 0x91, + 0x6E, 0x2B, 0x11, 0xC1, 0x57, 0x49, 0x27, 0x36, 0x78, 0xE1, + 0x09, 0x68, 0x9C, 0x05, 0x5A, 0xAC, 0xE6, 0x00, 0x38, 0xBE, + 0x95, 0x74, 0x81, 0x53, 0x28, 0xF0, 0xAD, 0xDF, 0xB5, 0x87, + 0x1C, 0x72, 0x17, 0x4E, 0xEC, 0x00, 0x91, 0x22, 0xAA, 0xE4, + 0x88, 0xD7, 0xF5, 0x3D, 0x1F, 0x03, 0x13, 0x2D, 0x1C, 0xFB, + 0xDE, 0x59, 0x68, 0xAD, 0xE0, 0x17, 0xA1, 0xEE, 0x8D, 0xCC, + 0xBF, 0xFE, 0xCF, 0x24, 0x42, 0xED, 0x26, 0xDD, 0x29, 0xD0, + 0x4E, 0x62, 0x3C, 0x85, 0x36, 0x1B, 0x5F, 0x6A, 0x47, 0x88, + 0x21, 0xE5, 0x1B, 0x85, 0x0A, 0x2C, 0xE9, 0x2F, 0xE0, 0x20, + 0xFC, 0x1D, 0xCD, 0x55, 0x66, 0xF5, 0xAC, 0x32, 0x00, 0x8E, + 0xA3, 0xE9, 0xED, 0xFB, 0x35, 0xA7, 0xE6, 0x76, 0x53, 0x42, + 0xC6, 0x77, 0x77, 0xAB, 0x90, 0x99, 0x7C, 0xC2, 0xEC, 0xC9, + 0x18, 0x4A, 0x3C, 0xF4, 0x11, 0x75, 0x27, 0x83, 0xBD, 0x9E, + 0xC2, 0x8F, 0x23, 0xAB, 0x52, 0x46, 0xE2, 0x52, 0x5D, 0x9A, + 0x04, 0xC3, 0x15, 0x1F, 0x69, 0x9C, 0x72, 0x69, 0x59, 0x52, + 0xD4, 0x69, 0x3D, 0x19, 0x77, 0x36, 0x25, 0xAF, 0x07, 0x71, + 0x82, 0xDE, 0xB7, 0x24, 0x60, 0x82, 0x6A, 0x72, 0xBB, 0xED, + 0xB6, 0x76, 0xAE, 0x7E, 0xBC, 0x7D, 0x2F, 0x73, 0x4B, 0x04, + 0x16, 0xD5, 0xA4, 0xF3, 0x03, 0x26, 0xFB, 0xF3, 0xCD, 0x7B, + 0x77, 0x7E, 0x7C, 0x8D, 0x65, 0xAE, 0xA5, 0xDC, 0x6C, 0xE3, + 0x70, 0xD2, 0x29, 0x6B, 0xF2, 0xEB, 0x76, 0xC9, 0xE5, 0x46, + 0x18, 0x12, 0x57, 0xB0, 0x55, 0xA5, 0x7C, 0xCD, 0x41, 0x93, + 0x26, 0x99, 0xF7, 0xA5, 0xC5, 0x34, 0xBE, 0x59, 0x79, 0xDE, + 0x0A, 0x57, 0x5F, 0x21, 0xF8, 0x98, 0x52, 0xF0, 0x2F, 0x7B, + 0x57, 0xB6, 0x9D, 0xFC, 0x40, 0xA6, 0x55, 0xFB, 0xAF, 0xD9, + 0x16, 0x9B, 0x20, 0x4F, 0xA8, 0xA3, 0x0B, 0x04, 0x48, 0xE3, + 0x77, 0x22, 0xC4, 0xCC, 0x57, 0x14, 0x33, 0xA2, 0xF0, 0x9A, + 0xE3, 0x12, 0xBD, 0xFF, 0x72, 0x8B, 0xEE, 0x52, 0xF3, 0xC9, + 0x59, 0xC2, 0xA2, 0x6B, 0xA5, 0x75, 0x48, 0x51, 0x82, 0x0E, + 0x7A, 0xFF, 0xFE, 0x41, 0xCD, 0x7C, 0x63, 0xD2, 0x53, 0xA8, + 0x11, 0x03, 0xB9, 0x03, 0x07, 0xFE, 0x66, 0x38, 0x5F, 0xA2, + 0x3E, 0x9C, 0x1B, 0x02, 0x01, 0x02 +}; +static const int sizeof_dh_key_der_3072 = sizeof(dh_key_der_3072); + +/* ./certs/dsa3072.der, 3072-bit */ +static const unsigned char dsa_key_der_3072[] = +{ + 0x30, 0x82, 0x04, 0xD7, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, + 0x81, 0x00, 0xB5, 0xD0, 0x2F, 0x55, 0xC1, 0x27, 0x4C, 0x5B, + 0x28, 0x81, 0x4E, 0xA4, 0x32, 0x0D, 0x73, 0x54, 0x68, 0x4F, + 0x0A, 0x36, 0x68, 0x4A, 0x51, 0xBE, 0xDE, 0x49, 0xD4, 0x9D, + 0xCE, 0xC6, 0xF7, 0x01, 0x70, 0xD2, 0x88, 0x90, 0x1D, 0x60, + 0x30, 0x9B, 0x0A, 0x9C, 0x23, 0xDA, 0xE0, 0x74, 0x46, 0x5B, + 0xC7, 0x41, 0x40, 0x5C, 0xD9, 0x7A, 0xBE, 0x78, 0xCA, 0x49, + 0xF5, 0x2D, 0x7B, 0xD7, 0xBF, 0x67, 0x0D, 0x84, 0x28, 0xBB, + 0x9D, 0xC2, 0xAB, 0x23, 0x06, 0x28, 0x0C, 0x98, 0x46, 0x43, + 0xCE, 0x6F, 0x9E, 0xD0, 0xE9, 0x0E, 0xF3, 0x7E, 0x30, 0x5D, + 0xD3, 0x45, 0x44, 0x7B, 0x0C, 0x7A, 0x73, 0xA6, 0x95, 0x65, + 0xAA, 0x8B, 0xD8, 0x75, 0x6A, 0x11, 0xB3, 0x10, 0x7C, 0x57, + 0xAF, 0xCE, 0xBE, 0x5B, 0xF7, 0xC8, 0xFE, 0x42, 0xA3, 0x77, + 0xB7, 0x0B, 0x3D, 0x66, 0xB5, 0x08, 0x74, 0x22, 0x74, 0x26, + 0xE6, 0xDB, 0x8E, 0xEF, 0xA3, 0x99, 0xAE, 0x0B, 0x42, 0x8C, + 0x5F, 0x7E, 0x48, 0xE9, 0x19, 0x90, 0xA8, 0x35, 0xA9, 0xFC, + 0x48, 0x0D, 0xC8, 0xB8, 0xE4, 0x1A, 0x0C, 0x26, 0xC7, 0x1A, + 0x20, 0x02, 0xEB, 0x72, 0x2E, 0x94, 0xD6, 0x19, 0x34, 0x39, + 0x55, 0x4E, 0xFC, 0x53, 0x48, 0xD8, 0x10, 0x89, 0xA1, 0x6E, + 0x22, 0x39, 0x71, 0x15, 0xA6, 0x13, 0xBC, 0x77, 0x49, 0x53, + 0xCB, 0x16, 0x4B, 0x56, 0x3D, 0x08, 0xA2, 0x71, 0x0E, 0x06, + 0x0C, 0x3A, 0xDE, 0x82, 0xC0, 0xDF, 0xE7, 0x96, 0x57, 0xD7, + 0x3F, 0x6B, 0xF0, 0xAE, 0xD1, 0x38, 0xB8, 0x5B, 0x83, 0x77, + 0x8B, 0xEB, 0x2B, 0xDA, 0x38, 0xC8, 0x4C, 0xA9, 0x48, 0x52, + 0xD8, 0x41, 0x03, 0xD3, 0x11, 0x1C, 0x66, 0x9E, 0xDE, 0xC9, + 0x78, 0x5A, 0xE1, 0x7B, 0xEA, 0x6F, 0xD6, 0xCA, 0x6A, 0x2F, + 0x01, 0xB2, 0x83, 0x37, 0x25, 0xD9, 0x9C, 0xD4, 0xB0, 0x21, + 0xD9, 0x8F, 0xA6, 0xF8, 0xD6, 0x21, 0x82, 0xBB, 0x08, 0x64, + 0x28, 0x0E, 0x0C, 0x26, 0xE6, 0xA5, 0x69, 0xE0, 0x23, 0xE9, + 0xB3, 0xC4, 0xF9, 0xDE, 0xC6, 0xD6, 0x32, 0x00, 0x66, 0x9B, + 0x8A, 0x0B, 0x6F, 0xDE, 0xB8, 0xDD, 0x68, 0x7F, 0x9D, 0x68, + 0x59, 0x6B, 0x55, 0xD9, 0x53, 0x01, 0x7B, 0x1A, 0x1C, 0x8D, + 0xBF, 0xAF, 0xC0, 0xB1, 0x14, 0x9E, 0xC1, 0x8D, 0x3E, 0x1E, + 0xFB, 0x40, 0xF9, 0x6D, 0x48, 0x43, 0xCD, 0x6C, 0xE8, 0xBC, + 0x3C, 0x7C, 0x35, 0x3C, 0x65, 0x6D, 0xA0, 0x25, 0x87, 0xBF, + 0xEC, 0x9B, 0x12, 0x74, 0x48, 0xC8, 0xE4, 0xBF, 0x53, 0x53, + 0x47, 0x78, 0xD9, 0x9B, 0x1A, 0xA5, 0x07, 0x46, 0x15, 0x16, + 0xD2, 0x33, 0x93, 0xCC, 0x41, 0x9B, 0xB7, 0x22, 0xDF, 0x07, + 0xDD, 0x72, 0xC6, 0x1A, 0x9B, 0x92, 0xE7, 0x32, 0x04, 0xAB, + 0x94, 0x80, 0xBD, 0x58, 0xF2, 0x35, 0x02, 0x21, 0x00, 0x9A, + 0xDD, 0x98, 0x1A, 0x6F, 0xEA, 0xB5, 0x8B, 0xC9, 0x68, 0x18, + 0x81, 0xE4, 0x4C, 0xFD, 0x8E, 0x45, 0xCF, 0x5F, 0x0E, 0x62, + 0x1E, 0x7D, 0x2D, 0x4A, 0x4C, 0x5D, 0x7F, 0xF8, 0xD8, 0x52, + 0xD7, 0x02, 0x82, 0x01, 0x81, 0x00, 0x84, 0xDF, 0xAB, 0x91, + 0x61, 0xE4, 0x2B, 0x07, 0x0A, 0x1C, 0xC7, 0x9C, 0xD7, 0xAC, + 0x8D, 0xA5, 0xAA, 0x41, 0x65, 0x9E, 0x4A, 0xED, 0x21, 0x45, + 0x96, 0xF7, 0xF7, 0xCB, 0x7A, 0x88, 0x19, 0x0F, 0x36, 0x80, + 0x25, 0x2F, 0x23, 0x0D, 0xFF, 0x6C, 0x0D, 0x02, 0xBB, 0x6A, + 0x79, 0x6A, 0xCB, 0x05, 0x00, 0x9B, 0x77, 0xED, 0x6B, 0xF3, + 0xC2, 0xEA, 0x1A, 0xDF, 0xB8, 0x15, 0xA8, 0x92, 0x19, 0x5A, + 0x51, 0x3B, 0x76, 0x06, 0x98, 0x47, 0xC7, 0x6F, 0x76, 0x99, + 0xAD, 0x50, 0xC5, 0x98, 0xE7, 0xFF, 0x88, 0xBC, 0x49, 0x77, + 0xEF, 0x96, 0x75, 0xE2, 0x36, 0x66, 0x1F, 0x0C, 0xFA, 0x57, + 0x1E, 0x11, 0xFF, 0x8F, 0x3C, 0xD0, 0xEA, 0x97, 0x25, 0x3F, + 0xFA, 0xD1, 0x4F, 0xBA, 0xDF, 0xE3, 0x35, 0xFB, 0x6E, 0x5C, + 0x65, 0xF9, 0xA2, 0x26, 0x43, 0xF2, 0xF4, 0xE0, 0x05, 0x3D, + 0xC6, 0x5B, 0xC4, 0x21, 0xE7, 0xB1, 0x02, 0xEB, 0xF2, 0xA9, + 0x06, 0x5E, 0xB7, 0x1B, 0xC1, 0xD8, 0x86, 0x34, 0xED, 0x84, + 0x89, 0xCE, 0xCE, 0xC2, 0x63, 0x78, 0x67, 0xF8, 0xC3, 0xAA, + 0x7C, 0x1C, 0x59, 0x32, 0xE4, 0x77, 0xA2, 0x36, 0x31, 0xFE, + 0x4B, 0x9C, 0x98, 0xCE, 0x01, 0x55, 0x61, 0xCE, 0x23, 0xAE, + 0x0F, 0x7E, 0x24, 0x8B, 0x54, 0x8A, 0xE4, 0xCB, 0x8E, 0xDC, + 0x7A, 0x94, 0x4C, 0xF9, 0x3C, 0xF8, 0x67, 0x68, 0x9D, 0x7A, + 0x82, 0xA1, 0xA0, 0x01, 0xC7, 0x1B, 0x8D, 0xA0, 0xC0, 0x53, + 0x1E, 0x93, 0xC7, 0x86, 0x12, 0xD3, 0x16, 0xDC, 0x28, 0xA0, + 0xD1, 0x0D, 0x1E, 0x42, 0x9A, 0xCB, 0x55, 0x8C, 0x22, 0x7F, + 0x41, 0xC3, 0xC9, 0x14, 0xF2, 0xB0, 0x73, 0xA1, 0x4D, 0x72, + 0xFD, 0x88, 0xB6, 0xDE, 0xE5, 0xF0, 0x3C, 0x3A, 0x7E, 0x68, + 0x3E, 0x82, 0x58, 0x60, 0xCD, 0xB4, 0x08, 0x64, 0x18, 0xB2, + 0x24, 0x97, 0x13, 0xA6, 0x07, 0x75, 0xBE, 0xE0, 0x14, 0x92, + 0x9A, 0x98, 0x6C, 0x08, 0x94, 0xD1, 0x0D, 0x48, 0x44, 0xC3, + 0xE3, 0xD5, 0xC0, 0x93, 0x49, 0x79, 0x2F, 0x67, 0x15, 0x76, + 0xD8, 0x90, 0x11, 0xDB, 0xEC, 0xA7, 0xE2, 0xDB, 0xD4, 0x4F, + 0x49, 0x5E, 0xEF, 0xC5, 0xB9, 0x77, 0x69, 0xDA, 0x02, 0xB7, + 0x23, 0xBC, 0xEA, 0xDC, 0x84, 0xD4, 0xA5, 0x5C, 0xA2, 0x6C, + 0xAD, 0x4A, 0x9F, 0xF0, 0x65, 0x48, 0xE9, 0xBF, 0xDF, 0xA5, + 0xB3, 0x99, 0xD6, 0x76, 0x08, 0x87, 0x2C, 0xF2, 0x29, 0x79, + 0xB2, 0x20, 0x7C, 0x6F, 0xC1, 0xC5, 0x3C, 0xB0, 0x50, 0x3F, + 0x72, 0xA5, 0x57, 0xE3, 0xB0, 0x62, 0x18, 0x80, 0x71, 0xB9, + 0x3F, 0x4D, 0x4E, 0x7C, 0xF6, 0x29, 0xDB, 0xB8, 0xAD, 0xF6, + 0x41, 0x69, 0x06, 0x90, 0x45, 0x7B, 0x95, 0x03, 0xE1, 0x9E, + 0xA5, 0xA1, 0x5A, 0xE3, 0x08, 0x26, 0x73, 0xFC, 0x2B, 0x20, + 0x02, 0x82, 0x01, 0x81, 0x00, 0xA5, 0x52, 0x8F, 0x53, 0xF0, + 0xB9, 0x4F, 0x06, 0xB9, 0xC8, 0xB4, 0x50, 0xA4, 0x39, 0xBA, + 0x12, 0x92, 0x75, 0x27, 0x43, 0xA8, 0x30, 0xA9, 0xF2, 0x2A, + 0xC6, 0x93, 0x26, 0x3C, 0x8C, 0x9F, 0xA2, 0x6F, 0x53, 0xD9, + 0x14, 0xAB, 0x3F, 0x00, 0xC6, 0x11, 0x13, 0x90, 0x6A, 0x42, + 0xF2, 0x9D, 0xA3, 0x8F, 0x31, 0x32, 0x46, 0x73, 0xA3, 0x93, + 0x57, 0x5D, 0x76, 0x45, 0x49, 0x6C, 0xBD, 0xEA, 0xAF, 0xAA, + 0xB3, 0x55, 0x25, 0x11, 0x8E, 0xA5, 0x2A, 0xB1, 0xBA, 0xA5, + 0x06, 0x4A, 0x66, 0xAA, 0x78, 0x9E, 0xF6, 0x5C, 0x1E, 0xB1, + 0x4A, 0xCA, 0x5C, 0x3F, 0x1D, 0x33, 0x75, 0x91, 0xF2, 0xF9, + 0x53, 0x14, 0x2F, 0xDC, 0xF0, 0x4C, 0xA4, 0xF4, 0x50, 0x04, + 0x1F, 0xFF, 0xC9, 0x0C, 0xC6, 0x8A, 0x04, 0x8B, 0x80, 0x87, + 0xA7, 0x70, 0x49, 0xD7, 0xE4, 0xE7, 0x83, 0xF1, 0x86, 0x1A, + 0xB0, 0x85, 0x3C, 0x59, 0x04, 0x96, 0xD1, 0x85, 0x47, 0xA1, + 0x57, 0x7D, 0xC6, 0x8E, 0x60, 0x7D, 0xC6, 0xE8, 0x18, 0xB3, + 0x1F, 0xB8, 0x99, 0xF0, 0xC4, 0xE5, 0x1E, 0xBC, 0x34, 0x07, + 0x8E, 0x40, 0x57, 0xA5, 0x8D, 0x3A, 0xA3, 0x88, 0x96, 0xF1, + 0xB3, 0x61, 0xF1, 0x1C, 0x96, 0x8A, 0xA4, 0x9E, 0xCD, 0x21, + 0xA2, 0x94, 0xAE, 0x5E, 0x1F, 0xCD, 0x5B, 0x5B, 0xE3, 0x88, + 0x1E, 0x17, 0x4A, 0x46, 0xAB, 0x9C, 0xE0, 0x59, 0x03, 0x4A, + 0xB8, 0xC8, 0x83, 0xE7, 0xFF, 0x39, 0x27, 0x68, 0x80, 0xA0, + 0x8E, 0xB3, 0xA2, 0x00, 0xC6, 0x2D, 0x2C, 0x76, 0xBA, 0x90, + 0x7C, 0x03, 0x1B, 0x19, 0xC8, 0x33, 0xB2, 0x12, 0x3A, 0xC8, + 0x8D, 0x32, 0xFE, 0xC0, 0xF9, 0xA5, 0x6A, 0x63, 0xE2, 0xA4, + 0x12, 0x43, 0x19, 0xF5, 0x14, 0xF2, 0x27, 0xF8, 0x0B, 0xBD, + 0x1A, 0x22, 0x64, 0x2D, 0xC9, 0x05, 0xFA, 0xD8, 0xDD, 0x11, + 0x1A, 0xD3, 0xF2, 0xBC, 0x99, 0x3A, 0xCD, 0x21, 0xCF, 0x10, + 0x14, 0x36, 0xDF, 0xED, 0x66, 0x02, 0x03, 0x4A, 0x42, 0x70, + 0x71, 0x22, 0xAD, 0xE7, 0x53, 0x91, 0xF4, 0x40, 0x8F, 0x72, + 0x7E, 0x54, 0xA0, 0x5D, 0x58, 0x93, 0xD6, 0xF6, 0xBC, 0x87, + 0x1A, 0x68, 0x0F, 0xAB, 0x94, 0x20, 0x70, 0xC2, 0x11, 0xA1, + 0x14, 0xBC, 0x06, 0xA8, 0x44, 0xB9, 0x1F, 0x04, 0x49, 0x7E, + 0xB3, 0x9A, 0x53, 0x46, 0x05, 0x75, 0x5D, 0x29, 0x77, 0x28, + 0xA9, 0xB1, 0xDC, 0xF1, 0x0D, 0x8A, 0x1C, 0x5E, 0xCD, 0xD7, + 0x4C, 0x16, 0x6F, 0x88, 0xBF, 0xB3, 0x34, 0xE2, 0xAD, 0x9A, + 0xC4, 0x89, 0xE2, 0x2E, 0x5C, 0x20, 0xE1, 0x5F, 0x39, 0xBF, + 0xB7, 0x45, 0xD3, 0x0F, 0x98, 0xB0, 0xD8, 0xC9, 0x18, 0x91, + 0x17, 0x25, 0xBC, 0x53, 0x62, 0xFF, 0x27, 0x85, 0xBD, 0xE2, + 0xE3, 0x9C, 0xA8, 0x06, 0x7A, 0x54, 0xEA, 0xFD, 0xEA, 0x02, + 0x20, 0x4C, 0xAC, 0x69, 0x62, 0x08, 0xE5, 0xCD, 0x14, 0xC8, + 0x2D, 0x4E, 0xDF, 0x1F, 0x60, 0x1D, 0x93, 0x44, 0x86, 0x5D, + 0x73, 0x99, 0x40, 0x1B, 0xDC, 0xA9, 0xBA, 0xC4, 0x1B, 0x12, + 0x6C, 0xFF, 0x53 +}; +static const int sizeof_dsa_key_der_3072 = sizeof(dsa_key_der_3072); + +/* ./certs/rsa3072.der, 3072-bit */ +static const unsigned char rsa_key_der_3072[] = +{ + 0x30, 0x82, 0x06, 0xE4, 0x02, 0x01, 0x00, 0x02, 0x82, 0x01, + 0x81, 0x00, 0xBC, 0x6D, 0x68, 0xFF, 0xC0, 0x07, 0x0E, 0x0C, + 0x4A, 0xE6, 0x76, 0x1F, 0x7A, 0x25, 0x3A, 0x75, 0xA7, 0xE2, + 0xF1, 0x17, 0x00, 0xF8, 0x85, 0xE6, 0x8F, 0x59, 0x14, 0xA7, + 0xDE, 0x8C, 0x74, 0x4B, 0xEB, 0x85, 0xEC, 0x49, 0x9B, 0xFF, + 0x4B, 0x43, 0x0A, 0x08, 0xA1, 0xEC, 0x64, 0x58, 0x47, 0x28, + 0xD5, 0xCE, 0x48, 0xE9, 0xCF, 0x34, 0xDF, 0x15, 0x20, 0x37, + 0x99, 0x0E, 0x3C, 0x81, 0xBE, 0x2E, 0xE4, 0x6C, 0xBB, 0xDE, + 0xD1, 0x93, 0xC5, 0xEC, 0x6C, 0xCC, 0x40, 0x0B, 0x46, 0xA1, + 0xE6, 0xCA, 0xA0, 0xD5, 0x3B, 0x44, 0x48, 0x79, 0x67, 0x52, + 0x6F, 0xDA, 0xED, 0x73, 0x8B, 0x7C, 0x33, 0xDA, 0x17, 0x96, + 0xE8, 0xA2, 0x91, 0x3C, 0x57, 0xDD, 0xC9, 0x2E, 0x01, 0x74, + 0x87, 0x33, 0xA0, 0x12, 0x7C, 0xBB, 0xF9, 0x53, 0xF4, 0xC4, + 0x31, 0x48, 0x53, 0xCB, 0xBB, 0x3C, 0x42, 0x43, 0x0C, 0x7A, + 0x7B, 0xB8, 0x2A, 0xFC, 0xDC, 0x70, 0xD5, 0x64, 0x16, 0x74, + 0xA8, 0x80, 0xDE, 0x16, 0xE0, 0xB2, 0x6C, 0x04, 0x47, 0x6C, + 0x25, 0xA6, 0x7F, 0xB4, 0x73, 0x49, 0xBC, 0xF3, 0xAE, 0xE3, + 0x93, 0x36, 0x87, 0x2B, 0xB7, 0x8F, 0xB5, 0x88, 0x88, 0x22, + 0x47, 0xDF, 0xBF, 0x4D, 0x3C, 0x2A, 0xBD, 0x3F, 0x2F, 0x11, + 0x29, 0xCC, 0x1C, 0x33, 0x40, 0x4E, 0x23, 0xF6, 0x25, 0xF0, + 0xAF, 0x02, 0x16, 0x48, 0xED, 0x1C, 0xD8, 0xC9, 0x92, 0x2F, + 0x5B, 0xAF, 0xBA, 0xDB, 0x60, 0x1E, 0x0E, 0xE1, 0x65, 0x91, + 0x96, 0xF8, 0x7D, 0x73, 0x4C, 0x72, 0x23, 0x33, 0xD5, 0x32, + 0x2B, 0x0F, 0x4F, 0xBC, 0x81, 0x45, 0x9E, 0x31, 0x76, 0xEF, + 0xE1, 0x76, 0x2D, 0x3F, 0x8F, 0xC4, 0x19, 0x8F, 0x27, 0x2A, + 0x8F, 0x6E, 0x76, 0xCC, 0xE0, 0x5D, 0xB0, 0x86, 0x66, 0xFE, + 0x72, 0xD9, 0x06, 0x40, 0xB6, 0xCE, 0x85, 0xC6, 0x2D, 0x34, + 0x33, 0xAA, 0x8E, 0xE5, 0x54, 0x8E, 0xB8, 0xBA, 0xEE, 0x92, + 0x07, 0x5D, 0xB5, 0xF1, 0x67, 0xBF, 0xCA, 0xE4, 0xCA, 0xCB, + 0xD9, 0x01, 0x73, 0x22, 0x01, 0x32, 0x39, 0xF4, 0x0A, 0xEC, + 0x5F, 0x4A, 0x00, 0x10, 0x3F, 0x01, 0x3D, 0x15, 0xBB, 0x55, + 0x91, 0x80, 0xBE, 0xD8, 0xD3, 0x59, 0xCC, 0xB0, 0x7C, 0x56, + 0xF7, 0xFF, 0xE0, 0x28, 0x40, 0x02, 0xB3, 0x98, 0x8A, 0x54, + 0x52, 0x60, 0xA5, 0x0B, 0x95, 0x53, 0x86, 0x6B, 0xA4, 0x35, + 0xCA, 0x04, 0xC7, 0xFB, 0x0A, 0xC8, 0x9D, 0x5A, 0x11, 0x40, + 0xF7, 0x60, 0x07, 0xB1, 0xB3, 0x42, 0xB6, 0x80, 0x8F, 0xE4, + 0x25, 0xC9, 0xE8, 0xBC, 0x8E, 0x21, 0x0D, 0x47, 0xCF, 0xB8, + 0x37, 0x09, 0xAF, 0xBF, 0x2C, 0x34, 0x09, 0x22, 0xC2, 0x6E, + 0x0D, 0x06, 0x30, 0x80, 0x1E, 0xA5, 0x8A, 0x46, 0x2D, 0xDC, + 0x57, 0xD4, 0x57, 0x82, 0x6A, 0x11, 0x02, 0x03, 0x01, 0x00, + 0x01, 0x02, 0x82, 0x01, 0x81, 0x00, 0xAD, 0x99, 0xAF, 0xCF, + 0x51, 0x40, 0x2E, 0xB5, 0x2C, 0x9C, 0xBF, 0xDF, 0xA8, 0x4D, + 0x7C, 0x5A, 0xC1, 0xDE, 0xD8, 0x78, 0x75, 0x30, 0x83, 0x4D, + 0x34, 0x6C, 0xC2, 0x17, 0x17, 0x77, 0x17, 0xFE, 0x8A, 0x73, + 0xCC, 0x8A, 0xD4, 0xEA, 0x94, 0x90, 0xA3, 0x41, 0xE8, 0xCD, + 0x3E, 0x76, 0x06, 0xB9, 0x9C, 0xA2, 0x7D, 0x92, 0xCC, 0x90, + 0xCD, 0xA7, 0x4D, 0x13, 0x6C, 0x34, 0x2D, 0x92, 0xEB, 0x81, + 0x90, 0x7A, 0x8D, 0x6C, 0x70, 0x72, 0x51, 0x3B, 0xCD, 0xD1, + 0x30, 0x80, 0x33, 0x07, 0x1E, 0xF7, 0x38, 0xCE, 0xBB, 0xD7, + 0xE1, 0x5D, 0xD8, 0xCF, 0x9E, 0xB6, 0x79, 0x66, 0xA6, 0xF0, + 0x3B, 0x65, 0x87, 0xAE, 0x45, 0x8E, 0xE1, 0x78, 0x53, 0x0B, + 0xC7, 0x3A, 0x57, 0xA4, 0xE0, 0x9B, 0xB3, 0xB2, 0xD4, 0xB0, + 0xEA, 0xB9, 0x6B, 0x1D, 0x06, 0xBA, 0xB8, 0x59, 0x4F, 0x9B, + 0xE9, 0x00, 0x95, 0x12, 0x93, 0xC1, 0xCD, 0xF9, 0x41, 0xAF, + 0xC3, 0x2A, 0x7F, 0x75, 0xE3, 0x79, 0x37, 0x24, 0xA4, 0xC8, + 0x3D, 0xB4, 0x83, 0x89, 0x23, 0xF7, 0x0E, 0x59, 0x56, 0x8E, + 0x6D, 0x43, 0xA5, 0xB1, 0x8E, 0x04, 0x02, 0xED, 0x48, 0x25, + 0x62, 0xFE, 0xF3, 0x4D, 0x82, 0x22, 0xA6, 0xC1, 0xA5, 0xD9, + 0x4A, 0x9A, 0x57, 0xE6, 0xDC, 0x37, 0x6D, 0x13, 0xDA, 0xFF, + 0x23, 0x2A, 0xB9, 0x31, 0xD2, 0x4B, 0x7D, 0xF3, 0x02, 0x90, + 0xF6, 0x28, 0x3D, 0x98, 0x3C, 0xF6, 0x43, 0x45, 0xAE, 0xAB, + 0x91, 0x15, 0xC7, 0xC4, 0x90, 0x9C, 0x3E, 0xDA, 0xD4, 0x20, + 0x12, 0xB2, 0xE1, 0x2B, 0x56, 0xE2, 0x38, 0x32, 0x9C, 0xE6, + 0xA9, 0x1D, 0xFE, 0xA5, 0xEE, 0xD7, 0x52, 0xB4, 0xE3, 0xE4, + 0x65, 0xEA, 0x41, 0x9D, 0xD4, 0x91, 0x83, 0x5D, 0xFF, 0x52, + 0xA7, 0xC3, 0x42, 0x9F, 0x14, 0x70, 0x9F, 0x98, 0x14, 0xB2, + 0x33, 0xEE, 0x4C, 0x5A, 0xC9, 0x5F, 0x16, 0xF6, 0x06, 0xE9, + 0xF3, 0x39, 0xD2, 0xC5, 0x31, 0x53, 0x2A, 0x39, 0xED, 0x3A, + 0x4D, 0x2A, 0xC1, 0x4C, 0x87, 0x82, 0xC6, 0xCA, 0xCF, 0xF5, + 0x9A, 0x71, 0x27, 0xAE, 0xFB, 0xFE, 0xD0, 0x66, 0xDB, 0xAA, + 0x03, 0x16, 0x4B, 0xEF, 0xB4, 0x28, 0xAB, 0xCF, 0xBE, 0x9B, + 0x58, 0xCF, 0xA4, 0x58, 0x82, 0xD2, 0x37, 0x8C, 0xEA, 0x3D, + 0x75, 0x4D, 0x0B, 0x46, 0x7A, 0x04, 0xDE, 0xF1, 0x6E, 0xBB, + 0x03, 0xBF, 0xF7, 0x8E, 0xE6, 0xF4, 0x9A, 0xE1, 0xCA, 0x26, + 0x2C, 0x41, 0x08, 0xAD, 0x21, 0xA7, 0xC2, 0x40, 0xF5, 0x9C, + 0xDD, 0xAB, 0xC5, 0x5A, 0x4C, 0xF4, 0xE6, 0x9A, 0x50, 0xFD, + 0xAA, 0x47, 0xD6, 0xA6, 0x07, 0x25, 0xB2, 0x4B, 0x9C, 0x1D, + 0x90, 0xA2, 0x4A, 0x98, 0xE0, 0x05, 0x8A, 0x5C, 0xD1, 0x2C, + 0xC0, 0x28, 0xD1, 0x84, 0x3C, 0x72, 0xFF, 0x83, 0xEA, 0xB1, + 0x02, 0x81, 0xC1, 0x00, 0xF8, 0xA0, 0x5F, 0x25, 0x2E, 0x23, + 0x73, 0x30, 0xB6, 0x97, 0xAF, 0x08, 0xE7, 0xD2, 0xD8, 0xC3, + 0x95, 0xEA, 0x9D, 0x8E, 0x9F, 0xF1, 0x36, 0x81, 0xD7, 0x7A, + 0x21, 0x2B, 0x90, 0x38, 0x9C, 0xA6, 0x08, 0x40, 0xEA, 0xD2, + 0x6E, 0x29, 0xB5, 0x0B, 0x3E, 0x91, 0xB2, 0x04, 0x92, 0xCF, + 0x94, 0xFF, 0xA6, 0xA7, 0x1A, 0x5F, 0x93, 0x0C, 0x86, 0xE6, + 0x4B, 0x61, 0xD4, 0x5E, 0xD7, 0xE3, 0x66, 0x0B, 0x83, 0xDB, + 0x16, 0x49, 0x27, 0xD5, 0xA3, 0xB3, 0xF5, 0x5D, 0x8F, 0xC9, + 0x48, 0x10, 0xD7, 0x77, 0x1E, 0x7B, 0x01, 0xC4, 0xFD, 0x14, + 0x0C, 0xAB, 0x40, 0xF7, 0x9B, 0x07, 0xDE, 0x55, 0xEF, 0x36, + 0x4C, 0x22, 0x37, 0x37, 0x09, 0x9D, 0x2A, 0x73, 0xA6, 0xA5, + 0xF4, 0xAF, 0x39, 0x2B, 0x87, 0xB4, 0xB2, 0x28, 0x9E, 0x08, + 0xA6, 0xCA, 0xB4, 0x39, 0x5A, 0x3A, 0xFB, 0x41, 0x93, 0xEC, + 0x44, 0xBB, 0xD2, 0x7C, 0x3B, 0x27, 0x3E, 0x26, 0xFD, 0x7B, + 0x20, 0xFC, 0x44, 0x67, 0xC0, 0x84, 0xD1, 0xA0, 0xCC, 0xBB, + 0x26, 0xC7, 0x32, 0x0E, 0x01, 0x9B, 0x2B, 0x1F, 0x58, 0x85, + 0x5A, 0x6C, 0xD0, 0xC1, 0xAC, 0x14, 0x5E, 0x06, 0x07, 0xCA, + 0x69, 0x52, 0xF5, 0xA6, 0x16, 0x75, 0x42, 0x8A, 0xE1, 0xBA, + 0x8B, 0x46, 0x38, 0x17, 0x7B, 0xF1, 0x7D, 0x79, 0x1F, 0x7E, + 0x4C, 0x6A, 0x75, 0xDC, 0xA8, 0x3B, 0x02, 0x81, 0xC1, 0x00, + 0xC2, 0x03, 0xFE, 0x57, 0xDF, 0x26, 0xD8, 0x79, 0xDC, 0x2C, + 0x47, 0x9B, 0x92, 0x9B, 0x53, 0x40, 0x82, 0xEC, 0xBD, 0x0B, + 0xC0, 0x96, 0x89, 0x21, 0xC5, 0x26, 0x7E, 0x7A, 0x59, 0xA7, + 0x85, 0x11, 0xCC, 0x39, 0x33, 0xA7, 0xE6, 0x42, 0x9C, 0x12, + 0x81, 0xA0, 0x87, 0xBC, 0x57, 0x07, 0xC4, 0x51, 0x93, 0x59, + 0xC6, 0xAB, 0x11, 0xCC, 0xCB, 0xC8, 0xC1, 0x40, 0xDF, 0xCB, + 0xE8, 0x45, 0x31, 0x20, 0x91, 0x88, 0x5F, 0x76, 0x76, 0xEE, + 0x30, 0x37, 0xFA, 0xA7, 0x22, 0x72, 0x82, 0x50, 0x31, 0xE9, + 0xA0, 0x44, 0xCA, 0xDD, 0xD6, 0xAC, 0xEC, 0x82, 0xE8, 0x62, + 0xD8, 0x43, 0xFD, 0x77, 0x0F, 0x1C, 0x23, 0x12, 0x91, 0x1C, + 0xFE, 0x93, 0x2C, 0x87, 0x52, 0xBF, 0x96, 0x79, 0x5E, 0x3A, + 0x5A, 0x33, 0x28, 0x27, 0x3F, 0x20, 0x2C, 0xB3, 0x26, 0xE2, + 0x0D, 0x44, 0xA9, 0x2F, 0x39, 0x7B, 0x7B, 0xAD, 0xA3, 0x21, + 0xD2, 0x7F, 0x3C, 0x89, 0x63, 0xDD, 0x13, 0xB1, 0x2E, 0xD6, + 0x34, 0xFB, 0x2A, 0x83, 0x29, 0xE7, 0x8A, 0x88, 0xD7, 0xA3, + 0x38, 0x3C, 0x43, 0x62, 0x8F, 0x69, 0xFA, 0x4B, 0x15, 0xB5, + 0xF6, 0x59, 0x90, 0x62, 0x7D, 0xCF, 0x1D, 0xDD, 0x49, 0x43, + 0x33, 0x96, 0xA9, 0xF7, 0x76, 0x9F, 0xE4, 0x0D, 0x6E, 0x1C, + 0xEA, 0x18, 0x5B, 0xBD, 0x5C, 0x98, 0x90, 0x09, 0xCA, 0x59, + 0x9E, 0x23, 0x02, 0x81, 0xC0, 0x66, 0xFF, 0x99, 0x2A, 0xFF, + 0xF8, 0x33, 0xAA, 0x44, 0x9A, 0x86, 0x2A, 0xBC, 0x4F, 0x3E, + 0xF9, 0x97, 0xCB, 0xC0, 0x45, 0xEB, 0xC0, 0xB4, 0x02, 0x0A, + 0x50, 0x50, 0x19, 0x89, 0xFF, 0xC9, 0xF5, 0x86, 0x89, 0xCE, + 0x3E, 0x2A, 0xE1, 0x20, 0x5D, 0x6E, 0x28, 0x51, 0x85, 0x4F, + 0x84, 0xAB, 0x87, 0x55, 0x74, 0xF8, 0x9A, 0x0B, 0x83, 0x2F, + 0x07, 0x8C, 0xC7, 0x14, 0x81, 0xCE, 0x12, 0x28, 0x9E, 0x30, + 0x9B, 0xBC, 0x99, 0xC5, 0xE4, 0xDD, 0x92, 0x99, 0xDD, 0x8E, + 0xC9, 0xA6, 0x0F, 0x44, 0x13, 0xD7, 0x0E, 0xC2, 0x66, 0xE7, + 0x29, 0x3D, 0x2E, 0x5D, 0x15, 0xB6, 0xA6, 0x05, 0xD7, 0xB7, + 0xE7, 0xD8, 0x96, 0x7C, 0x25, 0x52, 0xD8, 0x47, 0x53, 0xED, + 0xFF, 0xE6, 0x64, 0x08, 0xDD, 0x1D, 0xB5, 0x1F, 0xF1, 0x6F, + 0xB6, 0xC9, 0xD2, 0x43, 0xE3, 0x56, 0x9C, 0x04, 0xA6, 0xE0, + 0x2F, 0x0B, 0x32, 0x7C, 0x3A, 0x77, 0x0F, 0x04, 0xD2, 0x86, + 0x44, 0x52, 0x1F, 0xEF, 0xFE, 0xC3, 0x64, 0xC2, 0xAB, 0x48, + 0xE5, 0x67, 0x65, 0x32, 0x39, 0x57, 0x34, 0xFF, 0x22, 0x57, + 0x3B, 0xB7, 0x80, 0x48, 0xE3, 0x52, 0xF4, 0x85, 0x17, 0x1E, + 0x77, 0x1E, 0x36, 0xFE, 0x09, 0x36, 0x58, 0x91, 0x9E, 0x93, + 0x71, 0x02, 0x6D, 0xAE, 0xA3, 0x1B, 0xF7, 0xA9, 0x31, 0x5A, + 0x78, 0xAA, 0x13, 0x98, 0x8C, 0x37, 0x2D, 0x02, 0x81, 0xC1, + 0x00, 0xBE, 0x01, 0xD9, 0x3A, 0xC7, 0x81, 0xAC, 0xAA, 0x13, + 0x75, 0x8E, 0x1F, 0x8F, 0x41, 0xED, 0x13, 0x95, 0xE5, 0x31, + 0xF3, 0x6B, 0x86, 0x42, 0x00, 0xBF, 0xAA, 0xC6, 0x5D, 0x1E, + 0xA6, 0x90, 0x0C, 0xF1, 0x1B, 0xE8, 0x39, 0xFB, 0xA8, 0xAA, + 0x5E, 0xF9, 0x72, 0x74, 0xDC, 0x7F, 0xC3, 0x4C, 0x81, 0xB3, + 0xB4, 0x4D, 0x7B, 0xC6, 0x2F, 0xF2, 0x37, 0xC7, 0x03, 0xB8, + 0xE9, 0x62, 0xAD, 0x38, 0xC2, 0xB3, 0xA4, 0x82, 0x11, 0x6B, + 0xC2, 0x33, 0x98, 0xEF, 0x32, 0x75, 0xEA, 0xFD, 0x32, 0x7A, + 0xDF, 0x59, 0xA5, 0x65, 0xA4, 0x42, 0x95, 0x11, 0xFF, 0xD6, + 0x84, 0xCF, 0x56, 0x2E, 0xCA, 0x46, 0x13, 0x01, 0x4A, 0x32, + 0xB1, 0xD9, 0xA3, 0xDB, 0x0D, 0x20, 0x7E, 0x1F, 0x68, 0xF7, + 0x5E, 0x60, 0x6E, 0x0F, 0x59, 0xF8, 0x59, 0x93, 0x4D, 0x54, + 0xBC, 0x37, 0xD0, 0x51, 0x7C, 0xBD, 0x67, 0xF0, 0xA5, 0x09, + 0xC9, 0x9A, 0xF4, 0x1F, 0x1E, 0x52, 0x9D, 0xF5, 0xA6, 0x25, + 0xBF, 0x85, 0x1D, 0xA1, 0xF1, 0xD8, 0xBD, 0x39, 0x10, 0x71, + 0x57, 0x19, 0x40, 0xF3, 0xA1, 0x77, 0xE0, 0x8B, 0x4E, 0xB3, + 0x91, 0x84, 0x15, 0x0C, 0xF1, 0x58, 0x52, 0xD9, 0xE5, 0x98, + 0xD5, 0x66, 0x95, 0x9C, 0x19, 0x8D, 0xA4, 0x63, 0x5C, 0xBF, + 0xC5, 0x33, 0x81, 0xED, 0x7E, 0x93, 0x4B, 0x9A, 0x6C, 0xEC, + 0x2E, 0x3E, 0x4F, 0x02, 0x81, 0xC0, 0x34, 0xF8, 0xDF, 0x74, + 0xC6, 0xC1, 0xD9, 0x03, 0x9B, 0x3B, 0x53, 0x19, 0xEB, 0x43, + 0xC4, 0xAA, 0x1E, 0x73, 0xE3, 0x13, 0x25, 0x32, 0x04, 0x22, + 0x79, 0x4A, 0x07, 0xF0, 0x06, 0x38, 0xBD, 0x57, 0xE6, 0x01, + 0x33, 0x8C, 0xF1, 0x02, 0xCC, 0x34, 0x2C, 0x60, 0x32, 0xA4, + 0x22, 0x1D, 0x0E, 0x39, 0x6B, 0xAB, 0xF7, 0xCE, 0xDB, 0xA7, + 0xC3, 0xD8, 0xA2, 0x3B, 0x70, 0x31, 0x91, 0x68, 0xB9, 0xBF, + 0xE0, 0xA1, 0x39, 0x80, 0xFE, 0x47, 0x99, 0x56, 0x6D, 0x76, + 0x90, 0x17, 0xF5, 0x67, 0x41, 0x44, 0x27, 0x10, 0x07, 0x98, + 0x4D, 0x4C, 0x53, 0xD4, 0x15, 0xDC, 0x0A, 0x2F, 0xE0, 0x83, + 0x28, 0x22, 0x8D, 0x61, 0x3B, 0xE4, 0x8E, 0xE5, 0xE7, 0x24, + 0x98, 0x19, 0xA8, 0xA3, 0xED, 0x70, 0x59, 0x06, 0x86, 0x76, + 0xC2, 0x4B, 0xCB, 0x17, 0xC5, 0x77, 0x12, 0x07, 0xB8, 0xAB, + 0x1A, 0x91, 0xFC, 0x72, 0x8E, 0xB7, 0xB1, 0xE6, 0x74, 0xDD, + 0x3D, 0x92, 0xA7, 0xDE, 0x6C, 0x6E, 0xCB, 0x50, 0x44, 0x2F, + 0xAC, 0x99, 0xF7, 0x36, 0x4D, 0x62, 0xC7, 0xAC, 0xCE, 0x7D, + 0x26, 0xC9, 0xD2, 0x4E, 0x49, 0xD7, 0x8E, 0x66, 0x6C, 0xC1, + 0x53, 0xDF, 0x31, 0xAB, 0x25, 0x35, 0xCA, 0xD6, 0xC4, 0xA3, + 0xA6, 0x9F, 0x7E, 0x3D, 0x2D, 0x1A, 0x44, 0x31, 0x3D, 0x81, + 0x91, 0xB8, 0x36, 0x08, 0x27, 0x42, 0x9E, 0x08 +}; +static const int sizeof_rsa_key_der_3072 = sizeof(rsa_key_der_3072); + +#endif /* USE_CERT_BUFFERS_3072 */ + +#if defined(HAVE_ECC) && defined(USE_CERT_BUFFERS_256) + +/* ./certs/ecc-client-key.der, ECC */ +static const unsigned char ecc_clikey_der_256[] = +{ + 0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0xF8, 0xCF, 0x92, + 0x6B, 0xBD, 0x1E, 0x28, 0xF1, 0xA8, 0xAB, 0xA1, 0x23, 0x4F, + 0x32, 0x74, 0x18, 0x88, 0x50, 0xAD, 0x7E, 0xC7, 0xEC, 0x92, + 0xF8, 0x8F, 0x97, 0x4D, 0xAF, 0x56, 0x89, 0x65, 0xC7, 0xA0, + 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, + 0x07, 0xA1, 0x44, 0x03, 0x42, 0x00, 0x04, 0x55, 0xBF, 0xF4, + 0x0F, 0x44, 0x50, 0x9A, 0x3D, 0xCE, 0x9B, 0xB7, 0xF0, 0xC5, + 0x4D, 0xF5, 0x70, 0x7B, 0xD4, 0xEC, 0x24, 0x8E, 0x19, 0x80, + 0xEC, 0x5A, 0x4C, 0xA2, 0x24, 0x03, 0x62, 0x2C, 0x9B, 0xDA, + 0xEF, 0xA2, 0x35, 0x12, 0x43, 0x84, 0x76, 0x16, 0xC6, 0x56, + 0x95, 0x06, 0xCC, 0x01, 0xA9, 0xBD, 0xF6, 0x75, 0x1A, 0x42, + 0xF7, 0xBD, 0xA9, 0xB2, 0x36, 0x22, 0x5F, 0xC7, 0x5D, 0x7F, + 0xB4 +}; +static const int sizeof_ecc_clikey_der_256 = sizeof(ecc_clikey_der_256); + +/* ./certs/ecc-client-keyPub.der, ECC */ +static const unsigned char ecc_clikeypub_der_256[] = +{ + 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, + 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, + 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0x55, 0xBF, 0xF4, + 0x0F, 0x44, 0x50, 0x9A, 0x3D, 0xCE, 0x9B, 0xB7, 0xF0, 0xC5, + 0x4D, 0xF5, 0x70, 0x7B, 0xD4, 0xEC, 0x24, 0x8E, 0x19, 0x80, + 0xEC, 0x5A, 0x4C, 0xA2, 0x24, 0x03, 0x62, 0x2C, 0x9B, 0xDA, + 0xEF, 0xA2, 0x35, 0x12, 0x43, 0x84, 0x76, 0x16, 0xC6, 0x56, + 0x95, 0x06, 0xCC, 0x01, 0xA9, 0xBD, 0xF6, 0x75, 0x1A, 0x42, + 0xF7, 0xBD, 0xA9, 0xB2, 0x36, 0x22, 0x5F, 0xC7, 0x5D, 0x7F, + 0xB4 +}; +static const int sizeof_ecc_clikeypub_der_256 = sizeof(ecc_clikeypub_der_256); + +/* ./certs/client-ecc-cert.der, ECC */ +static const unsigned char cliecc_cert_der_256[] = +{ + 0x30, 0x82, 0x03, 0x08, 0x30, 0x82, 0x02, 0xAF, 0xA0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0x93, 0xBF, 0x6A, 0xDE, + 0x9B, 0x41, 0x9D, 0xAD, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, + 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x81, 0x8D, 0x31, + 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0C, 0x06, 0x4F, 0x72, 0x65, 0x67, 0x6F, 0x6E, 0x31, + 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x05, + 0x53, 0x61, 0x6C, 0x65, 0x6D, 0x31, 0x13, 0x30, 0x11, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0A, 0x43, 0x6C, 0x69, 0x65, + 0x6E, 0x74, 0x20, 0x45, 0x43, 0x43, 0x31, 0x0D, 0x30, 0x0B, + 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x04, 0x46, 0x61, 0x73, + 0x74, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, + 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, + 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, + 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, + 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, + 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x38, 0x30, 0x34, 0x31, 0x33, + 0x31, 0x35, 0x32, 0x33, 0x31, 0x30, 0x5A, 0x17, 0x0D, 0x32, + 0x31, 0x30, 0x31, 0x30, 0x37, 0x31, 0x35, 0x32, 0x33, 0x31, + 0x30, 0x5A, 0x30, 0x81, 0x8D, 0x31, 0x0B, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x0F, + 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0C, 0x06, 0x4F, + 0x72, 0x65, 0x67, 0x6F, 0x6E, 0x31, 0x0E, 0x30, 0x0C, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x0C, 0x05, 0x53, 0x61, 0x6C, 0x65, + 0x6D, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x0A, 0x43, 0x6C, 0x69, 0x65, 0x6E, 0x74, 0x20, 0x45, + 0x43, 0x43, 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x0C, 0x04, 0x46, 0x61, 0x73, 0x74, 0x31, 0x18, 0x30, + 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x77, 0x77, + 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, + 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, + 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, + 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, 0x6F, 0x6C, 0x66, 0x73, + 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x30, 0x59, 0x30, 0x13, + 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, + 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, + 0x42, 0x00, 0x04, 0x55, 0xBF, 0xF4, 0x0F, 0x44, 0x50, 0x9A, + 0x3D, 0xCE, 0x9B, 0xB7, 0xF0, 0xC5, 0x4D, 0xF5, 0x70, 0x7B, + 0xD4, 0xEC, 0x24, 0x8E, 0x19, 0x80, 0xEC, 0x5A, 0x4C, 0xA2, + 0x24, 0x03, 0x62, 0x2C, 0x9B, 0xDA, 0xEF, 0xA2, 0x35, 0x12, + 0x43, 0x84, 0x76, 0x16, 0xC6, 0x56, 0x95, 0x06, 0xCC, 0x01, + 0xA9, 0xBD, 0xF6, 0x75, 0x1A, 0x42, 0xF7, 0xBD, 0xA9, 0xB2, + 0x36, 0x22, 0x5F, 0xC7, 0x5D, 0x7F, 0xB4, 0xA3, 0x81, 0xF5, + 0x30, 0x81, 0xF2, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, + 0x04, 0x16, 0x04, 0x14, 0xEB, 0xD4, 0x4B, 0x59, 0x6B, 0x95, + 0x61, 0x3F, 0x51, 0x57, 0xB6, 0x04, 0x4D, 0x89, 0x41, 0x88, + 0x44, 0x5C, 0xAB, 0xF2, 0x30, 0x81, 0xC2, 0x06, 0x03, 0x55, + 0x1D, 0x23, 0x04, 0x81, 0xBA, 0x30, 0x81, 0xB7, 0x80, 0x14, + 0xEB, 0xD4, 0x4B, 0x59, 0x6B, 0x95, 0x61, 0x3F, 0x51, 0x57, + 0xB6, 0x04, 0x4D, 0x89, 0x41, 0x88, 0x44, 0x5C, 0xAB, 0xF2, + 0xA1, 0x81, 0x93, 0xA4, 0x81, 0x90, 0x30, 0x81, 0x8D, 0x31, + 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x55, 0x53, 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0C, 0x06, 0x4F, 0x72, 0x65, 0x67, 0x6F, 0x6E, 0x31, + 0x0E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x05, + 0x53, 0x61, 0x6C, 0x65, 0x6D, 0x31, 0x13, 0x30, 0x11, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0A, 0x43, 0x6C, 0x69, 0x65, + 0x6E, 0x74, 0x20, 0x45, 0x43, 0x43, 0x31, 0x0D, 0x30, 0x0B, + 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x04, 0x46, 0x61, 0x73, + 0x74, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, + 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, + 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, + 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, + 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, + 0x82, 0x09, 0x00, 0x93, 0xBF, 0x6A, 0xDE, 0x9B, 0x41, 0x9D, + 0xAD, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x05, + 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x0A, 0x06, 0x08, 0x2A, + 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x03, 0x47, 0x00, + 0x30, 0x44, 0x02, 0x20, 0x61, 0xBC, 0x9D, 0x4D, 0x88, 0x64, + 0x86, 0xB8, 0x71, 0xAA, 0x35, 0x59, 0x68, 0xB8, 0xEE, 0x2C, + 0xF3, 0x23, 0xB5, 0x1A, 0xB9, 0xBA, 0x41, 0x50, 0xA8, 0xC6, + 0xC3, 0x58, 0xEB, 0x58, 0xBD, 0x60, 0x02, 0x20, 0x61, 0xAA, + 0xEB, 0xB5, 0x73, 0x0D, 0x01, 0xDB, 0x69, 0x8F, 0x52, 0xF5, + 0x72, 0x6D, 0x37, 0x42, 0xB5, 0xFD, 0x94, 0xB6, 0x6E, 0xB1, + 0xC4, 0x25, 0x2E, 0x96, 0x96, 0xF3, 0x39, 0xB2, 0x5D, 0xEA + +}; +static const int sizeof_cliecc_cert_der_256 = sizeof(cliecc_cert_der_256); + +/* ./certs/ecc-key.der, ECC */ +static const unsigned char ecc_key_der_256[] = +{ + 0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0x45, 0xB6, 0x69, + 0x02, 0x73, 0x9C, 0x6C, 0x85, 0xA1, 0x38, 0x5B, 0x72, 0xE8, + 0xE8, 0xC7, 0xAC, 0xC4, 0x03, 0x8D, 0x53, 0x35, 0x04, 0xFA, + 0x6C, 0x28, 0xDC, 0x34, 0x8D, 0xE1, 0xA8, 0x09, 0x8C, 0xA0, + 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, + 0x07, 0xA1, 0x44, 0x03, 0x42, 0x00, 0x04, 0xBB, 0x33, 0xAC, + 0x4C, 0x27, 0x50, 0x4A, 0xC6, 0x4A, 0xA5, 0x04, 0xC3, 0x3C, + 0xDE, 0x9F, 0x36, 0xDB, 0x72, 0x2D, 0xCE, 0x94, 0xEA, 0x2B, + 0xFA, 0xCB, 0x20, 0x09, 0x39, 0x2C, 0x16, 0xE8, 0x61, 0x02, + 0xE9, 0xAF, 0x4D, 0xD3, 0x02, 0x93, 0x9A, 0x31, 0x5B, 0x97, + 0x92, 0x21, 0x7F, 0xF0, 0xCF, 0x18, 0xDA, 0x91, 0x11, 0x02, + 0x34, 0x86, 0xE8, 0x20, 0x58, 0x33, 0x0B, 0x80, 0x34, 0x89, + 0xD8 +}; +static const int sizeof_ecc_key_der_256 = sizeof(ecc_key_der_256); + +/* ./certs/ecc-keyPub.der, ECC */ +static const unsigned char ecc_key_pub_der_256[] = +{ + 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, + 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, + 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xBB, 0x33, 0xAC, + 0x4C, 0x27, 0x50, 0x4A, 0xC6, 0x4A, 0xA5, 0x04, 0xC3, 0x3C, + 0xDE, 0x9F, 0x36, 0xDB, 0x72, 0x2D, 0xCE, 0x94, 0xEA, 0x2B, + 0xFA, 0xCB, 0x20, 0x09, 0x39, 0x2C, 0x16, 0xE8, 0x61, 0x02, + 0xE9, 0xAF, 0x4D, 0xD3, 0x02, 0x93, 0x9A, 0x31, 0x5B, 0x97, + 0x92, 0x21, 0x7F, 0xF0, 0xCF, 0x18, 0xDA, 0x91, 0x11, 0x02, + 0x34, 0x86, 0xE8, 0x20, 0x58, 0x33, 0x0B, 0x80, 0x34, 0x89, + 0xD8 +}; +static const int sizeof_ecc_key_pub_der_256 = sizeof(ecc_key_pub_der_256); + +/* ./certs/server-ecc-comp.der, ECC */ +static const unsigned char serv_ecc_comp_der_256[] = +{ + 0x30, 0x82, 0x03, 0x23, 0x30, 0x82, 0x02, 0xCA, 0xA0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0x80, 0x78, 0xC9, 0xB7, + 0x06, 0x5A, 0xC5, 0x83, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, + 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x81, 0xA0, 0x31, + 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0C, 0x07, 0x4D, 0x6F, 0x6E, 0x74, 0x61, 0x6E, 0x61, + 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, + 0x07, 0x42, 0x6F, 0x7A, 0x65, 0x6D, 0x61, 0x6E, 0x31, 0x18, + 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0F, 0x45, + 0x6C, 0x6C, 0x69, 0x70, 0x74, 0x69, 0x63, 0x20, 0x2D, 0x20, + 0x63, 0x6F, 0x6D, 0x70, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, + 0x55, 0x04, 0x0B, 0x0C, 0x0F, 0x53, 0x65, 0x72, 0x76, 0x65, + 0x72, 0x20, 0x45, 0x43, 0x43, 0x2D, 0x63, 0x6F, 0x6D, 0x70, + 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, + 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, 0x73, + 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, 0x1D, + 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, + 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, 0x6F, + 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x30, + 0x1E, 0x17, 0x0D, 0x31, 0x38, 0x30, 0x34, 0x31, 0x33, 0x31, + 0x35, 0x32, 0x33, 0x31, 0x30, 0x5A, 0x17, 0x0D, 0x32, 0x31, + 0x30, 0x31, 0x30, 0x37, 0x31, 0x35, 0x32, 0x33, 0x31, 0x30, + 0x5A, 0x30, 0x81, 0xA0, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, + 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, + 0x0E, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0C, 0x07, 0x4D, 0x6F, + 0x6E, 0x74, 0x61, 0x6E, 0x61, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x42, 0x6F, 0x7A, 0x65, + 0x6D, 0x61, 0x6E, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, + 0x04, 0x0A, 0x0C, 0x0F, 0x45, 0x6C, 0x6C, 0x69, 0x70, 0x74, + 0x69, 0x63, 0x20, 0x2D, 0x20, 0x63, 0x6F, 0x6D, 0x70, 0x31, + 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x0F, + 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x45, 0x43, 0x43, + 0x2D, 0x63, 0x6F, 0x6D, 0x70, 0x31, 0x18, 0x30, 0x16, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, + 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, + 0x6D, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, + 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, + 0x66, 0x6F, 0x40, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, + 0x2E, 0x63, 0x6F, 0x6D, 0x30, 0x39, 0x30, 0x13, 0x06, 0x07, + 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, + 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x22, 0x00, + 0x02, 0xBB, 0x33, 0xAC, 0x4C, 0x27, 0x50, 0x4A, 0xC6, 0x4A, + 0xA5, 0x04, 0xC3, 0x3C, 0xDE, 0x9F, 0x36, 0xDB, 0x72, 0x2D, + 0xCE, 0x94, 0xEA, 0x2B, 0xFA, 0xCB, 0x20, 0x09, 0x39, 0x2C, + 0x16, 0xE8, 0x61, 0xA3, 0x82, 0x01, 0x09, 0x30, 0x82, 0x01, + 0x05, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, + 0x04, 0x14, 0x8C, 0x38, 0x3A, 0x6B, 0xB8, 0x24, 0xB7, 0xDF, + 0x6E, 0xF4, 0x59, 0xAC, 0x56, 0x4E, 0xAA, 0xE2, 0x58, 0xA6, + 0x5A, 0x18, 0x30, 0x81, 0xD5, 0x06, 0x03, 0x55, 0x1D, 0x23, + 0x04, 0x81, 0xCD, 0x30, 0x81, 0xCA, 0x80, 0x14, 0x8C, 0x38, + 0x3A, 0x6B, 0xB8, 0x24, 0xB7, 0xDF, 0x6E, 0xF4, 0x59, 0xAC, + 0x56, 0x4E, 0xAA, 0xE2, 0x58, 0xA6, 0x5A, 0x18, 0xA1, 0x81, + 0xA6, 0xA4, 0x81, 0xA3, 0x30, 0x81, 0xA0, 0x31, 0x0B, 0x30, + 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, + 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0C, + 0x07, 0x4D, 0x6F, 0x6E, 0x74, 0x61, 0x6E, 0x61, 0x31, 0x10, + 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x42, + 0x6F, 0x7A, 0x65, 0x6D, 0x61, 0x6E, 0x31, 0x18, 0x30, 0x16, + 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x0F, 0x45, 0x6C, 0x6C, + 0x69, 0x70, 0x74, 0x69, 0x63, 0x20, 0x2D, 0x20, 0x63, 0x6F, + 0x6D, 0x70, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x0C, 0x0F, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, + 0x45, 0x43, 0x43, 0x2D, 0x63, 0x6F, 0x6D, 0x70, 0x31, 0x18, + 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x77, + 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, + 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, + 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, 0x6F, 0x6C, 0x66, + 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x82, 0x09, 0x00, + 0x80, 0x78, 0xC9, 0xB7, 0x06, 0x5A, 0xC5, 0x83, 0x30, 0x0C, + 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, + 0x01, 0xFF, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, + 0x3D, 0x04, 0x03, 0x02, 0x03, 0x47, 0x00, 0x30, 0x44, 0x02, + 0x20, 0x31, 0x44, 0xD0, 0x4E, 0xD7, 0xC4, 0xB4, 0x96, 0xA3, + 0xE6, 0x25, 0xFD, 0xFA, 0xD6, 0x28, 0xA8, 0x67, 0x51, 0x72, + 0x90, 0x95, 0x31, 0xF9, 0xCD, 0x10, 0xBF, 0x11, 0xE4, 0xEC, + 0xB7, 0x42, 0x5B, 0x02, 0x20, 0x45, 0xDB, 0x45, 0x0A, 0x24, + 0x58, 0x8E, 0x2E, 0xE6, 0xEA, 0x0C, 0x6C, 0xBC, 0x72, 0x4F, + 0x0A, 0x1B, 0xF3, 0x2D, 0x97, 0xE9, 0xC2, 0x19, 0xF9, 0x97, + 0x3A, 0x60, 0xDD, 0x08, 0xD3, 0x52, 0x3E +}; +static const int sizeof_serv_ecc_comp_der_256 = sizeof(serv_ecc_comp_der_256); + +/* ./certs/server-ecc-rsa.der, ECC */ +static const unsigned char serv_ecc_rsa_der_256[] = +{ + 0x30, 0x82, 0x03, 0xE0, 0x30, 0x82, 0x02, 0xC8, 0xA0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x30, 0x0D, 0x06, 0x09, + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x0B, 0x05, + 0x00, 0x30, 0x81, 0x94, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, + 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, + 0x0E, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0C, 0x07, 0x4D, 0x6F, + 0x6E, 0x74, 0x61, 0x6E, 0x61, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x42, 0x6F, 0x7A, 0x65, + 0x6D, 0x61, 0x6E, 0x31, 0x11, 0x30, 0x0F, 0x06, 0x03, 0x55, + 0x04, 0x0A, 0x0C, 0x08, 0x53, 0x61, 0x77, 0x74, 0x6F, 0x6F, + 0x74, 0x68, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x0C, 0x0A, 0x43, 0x6F, 0x6E, 0x73, 0x75, 0x6C, 0x74, + 0x69, 0x6E, 0x67, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, + 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, + 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, + 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, + 0x40, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, + 0x6F, 0x6D, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x38, 0x30, 0x34, + 0x31, 0x33, 0x31, 0x35, 0x32, 0x33, 0x31, 0x30, 0x5A, 0x17, + 0x0D, 0x32, 0x31, 0x30, 0x31, 0x30, 0x37, 0x31, 0x35, 0x32, + 0x33, 0x31, 0x30, 0x5A, 0x30, 0x81, 0x9D, 0x31, 0x0B, 0x30, + 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, + 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0C, + 0x07, 0x4D, 0x6F, 0x6E, 0x74, 0x61, 0x6E, 0x61, 0x31, 0x10, + 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x42, + 0x6F, 0x7A, 0x65, 0x6D, 0x61, 0x6E, 0x31, 0x1A, 0x30, 0x18, + 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x11, 0x45, 0x6C, 0x6C, + 0x69, 0x70, 0x74, 0x69, 0x63, 0x20, 0x2D, 0x20, 0x52, 0x53, + 0x41, 0x73, 0x69, 0x67, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, + 0x55, 0x04, 0x0B, 0x0C, 0x0A, 0x45, 0x43, 0x43, 0x2D, 0x52, + 0x53, 0x41, 0x73, 0x69, 0x67, 0x31, 0x18, 0x30, 0x16, 0x06, + 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, + 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, + 0x6D, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, + 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, + 0x66, 0x6F, 0x40, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, + 0x2E, 0x63, 0x6F, 0x6D, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, + 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, + 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, + 0x04, 0xBB, 0x33, 0xAC, 0x4C, 0x27, 0x50, 0x4A, 0xC6, 0x4A, + 0xA5, 0x04, 0xC3, 0x3C, 0xDE, 0x9F, 0x36, 0xDB, 0x72, 0x2D, + 0xCE, 0x94, 0xEA, 0x2B, 0xFA, 0xCB, 0x20, 0x09, 0x39, 0x2C, + 0x16, 0xE8, 0x61, 0x02, 0xE9, 0xAF, 0x4D, 0xD3, 0x02, 0x93, + 0x9A, 0x31, 0x5B, 0x97, 0x92, 0x21, 0x7F, 0xF0, 0xCF, 0x18, + 0xDA, 0x91, 0x11, 0x02, 0x34, 0x86, 0xE8, 0x20, 0x58, 0x33, + 0x0B, 0x80, 0x34, 0x89, 0xD8, 0xA3, 0x81, 0xFC, 0x30, 0x81, + 0xF9, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, + 0x04, 0x14, 0x5D, 0x5D, 0x26, 0xEF, 0xAC, 0x7E, 0x36, 0xF9, + 0x9B, 0x76, 0x15, 0x2B, 0x4A, 0x25, 0x02, 0x23, 0xEF, 0xB2, + 0x89, 0x30, 0x30, 0x81, 0xC9, 0x06, 0x03, 0x55, 0x1D, 0x23, + 0x04, 0x81, 0xC1, 0x30, 0x81, 0xBE, 0x80, 0x14, 0x27, 0x8E, + 0x67, 0x11, 0x74, 0xC3, 0x26, 0x1D, 0x3F, 0xED, 0x33, 0x63, + 0xB3, 0xA4, 0xD8, 0x1D, 0x30, 0xE5, 0xE8, 0xD5, 0xA1, 0x81, + 0x9A, 0xA4, 0x81, 0x97, 0x30, 0x81, 0x94, 0x31, 0x0B, 0x30, + 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, + 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0C, + 0x07, 0x4D, 0x6F, 0x6E, 0x74, 0x61, 0x6E, 0x61, 0x31, 0x10, + 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x42, + 0x6F, 0x7A, 0x65, 0x6D, 0x61, 0x6E, 0x31, 0x11, 0x30, 0x0F, + 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x08, 0x53, 0x61, 0x77, + 0x74, 0x6F, 0x6F, 0x74, 0x68, 0x31, 0x13, 0x30, 0x11, 0x06, + 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x0A, 0x43, 0x6F, 0x6E, 0x73, + 0x75, 0x6C, 0x74, 0x69, 0x6E, 0x67, 0x31, 0x18, 0x30, 0x16, + 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x77, 0x77, 0x77, + 0x2E, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, + 0x6F, 0x6D, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, + 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, + 0x6E, 0x66, 0x6F, 0x40, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, + 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x82, 0x09, 0x00, 0x86, 0xFF, + 0xF5, 0x8E, 0x10, 0xDE, 0xB8, 0xFB, 0x30, 0x0C, 0x06, 0x03, + 0x55, 0x1D, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, + 0x30, 0x0D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, + 0x01, 0x01, 0x0B, 0x05, 0x00, 0x03, 0x82, 0x01, 0x01, 0x00, + 0x0C, 0xBB, 0x67, 0xBD, 0xFC, 0xCD, 0x53, 0x6C, 0xFB, 0x4E, + 0x58, 0xC8, 0xEA, 0x52, 0x92, 0xEB, 0xE4, 0xC8, 0xBC, 0x57, + 0x0F, 0x08, 0x20, 0xC8, 0x83, 0xB0, 0xD5, 0xEA, 0x57, 0x27, + 0xBD, 0x68, 0x91, 0xFB, 0x99, 0x84, 0x8D, 0x15, 0x9E, 0x4F, + 0x8F, 0xC4, 0xCB, 0x34, 0x61, 0xC0, 0x59, 0x12, 0x9B, 0xC8, + 0x82, 0x17, 0x38, 0x4F, 0x9E, 0x53, 0x08, 0xA3, 0x69, 0x2E, + 0x2F, 0xC0, 0xB4, 0x2F, 0xA2, 0x4E, 0x10, 0x64, 0xB0, 0x07, + 0xA1, 0x51, 0x08, 0x1D, 0x91, 0x53, 0xA2, 0x79, 0x55, 0x20, + 0x41, 0x65, 0x35, 0x3E, 0x0B, 0x38, 0x01, 0x57, 0x02, 0x8C, + 0x25, 0xE7, 0xAB, 0x4F, 0x8B, 0x59, 0xF0, 0xED, 0x8E, 0x4A, + 0x15, 0x0B, 0x32, 0xFB, 0x7A, 0x8B, 0x02, 0xEA, 0x9D, 0xE1, + 0xAB, 0xC4, 0x07, 0xCC, 0xDA, 0x0F, 0xA3, 0x16, 0xDB, 0x8E, + 0x5B, 0xBC, 0x96, 0xAB, 0x10, 0xB8, 0xDE, 0x09, 0x8B, 0xF7, + 0xCB, 0xA7, 0x78, 0x66, 0x17, 0xE3, 0x25, 0x6E, 0x57, 0x9D, + 0x13, 0x61, 0x7B, 0x55, 0x1A, 0xDF, 0x8F, 0x39, 0x15, 0x4E, + 0x42, 0x22, 0x00, 0x85, 0xC4, 0x51, 0x0B, 0x6B, 0xA6, 0x67, + 0xC0, 0xFB, 0xEA, 0x22, 0x77, 0x7D, 0x48, 0x76, 0xAB, 0x39, + 0x20, 0x09, 0xD5, 0x52, 0x89, 0x3E, 0x6B, 0x30, 0x7B, 0x50, + 0x18, 0xE8, 0x62, 0x05, 0xBE, 0xBB, 0x7F, 0x16, 0x77, 0x9C, + 0xBB, 0x5A, 0x22, 0x96, 0x99, 0xB0, 0x96, 0x83, 0xB7, 0x43, + 0x31, 0x97, 0xCF, 0xFD, 0x85, 0x52, 0xD8, 0x52, 0xC8, 0x67, + 0x5C, 0xF8, 0x22, 0x72, 0x35, 0x93, 0x92, 0x6C, 0xEC, 0x3C, + 0x6A, 0xC6, 0x81, 0x20, 0xA5, 0xCD, 0x50, 0xF9, 0x21, 0x7A, + 0xA6, 0x7A, 0x1E, 0xE7, 0x59, 0x22, 0x5D, 0x8A, 0x93, 0x51, + 0x8E, 0xFB, 0x29, 0x56, 0xFB, 0xBE, 0x9B, 0x87, 0x48, 0x5F, + 0xA5, 0x72, 0xE7, 0x4E, 0xFE, 0x5E +}; +static const int sizeof_serv_ecc_rsa_der_256 = sizeof(serv_ecc_rsa_der_256); + +/* ./certs/server-ecc.der, ECC */ +static const unsigned char serv_ecc_der_256[] = +{ + 0x30, 0x82, 0x03, 0x50, 0x30, 0x82, 0x02, 0xF5, 0xA0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x02, 0x10, 0x00, 0x30, 0x0A, 0x06, + 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, + 0x81, 0x97, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, + 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, + 0x03, 0x55, 0x04, 0x08, 0x0C, 0x0A, 0x57, 0x61, 0x73, 0x68, + 0x69, 0x6E, 0x67, 0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, + 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x53, 0x65, 0x61, + 0x74, 0x74, 0x6C, 0x65, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, + 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x77, 0x6F, 0x6C, 0x66, 0x53, + 0x53, 0x4C, 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, + 0x0B, 0x0C, 0x0B, 0x44, 0x65, 0x76, 0x65, 0x6C, 0x6F, 0x70, + 0x6D, 0x65, 0x6E, 0x74, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, + 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, + 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, + 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, + 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, + 0x6F, 0x40, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, + 0x63, 0x6F, 0x6D, 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x37, 0x31, + 0x30, 0x32, 0x30, 0x31, 0x38, 0x31, 0x39, 0x30, 0x36, 0x5A, + 0x17, 0x0D, 0x32, 0x37, 0x31, 0x30, 0x31, 0x38, 0x31, 0x38, + 0x31, 0x39, 0x30, 0x36, 0x5A, 0x30, 0x81, 0x8F, 0x31, 0x0B, + 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, + 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, + 0x0C, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, + 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x0C, 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, 0x6C, 0x65, + 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, + 0x07, 0x45, 0x6C, 0x69, 0x70, 0x74, 0x69, 0x63, 0x31, 0x0C, + 0x30, 0x0A, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x03, 0x45, + 0x43, 0x43, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, + 0x03, 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, + 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, + 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, + 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, + 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, + 0x6D, 0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86, 0x48, + 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, + 0x3D, 0x03, 0x01, 0x07, 0x03, 0x42, 0x00, 0x04, 0xBB, 0x33, + 0xAC, 0x4C, 0x27, 0x50, 0x4A, 0xC6, 0x4A, 0xA5, 0x04, 0xC3, + 0x3C, 0xDE, 0x9F, 0x36, 0xDB, 0x72, 0x2D, 0xCE, 0x94, 0xEA, + 0x2B, 0xFA, 0xCB, 0x20, 0x09, 0x39, 0x2C, 0x16, 0xE8, 0x61, + 0x02, 0xE9, 0xAF, 0x4D, 0xD3, 0x02, 0x93, 0x9A, 0x31, 0x5B, + 0x97, 0x92, 0x21, 0x7F, 0xF0, 0xCF, 0x18, 0xDA, 0x91, 0x11, + 0x02, 0x34, 0x86, 0xE8, 0x20, 0x58, 0x33, 0x0B, 0x80, 0x34, + 0x89, 0xD8, 0xA3, 0x82, 0x01, 0x35, 0x30, 0x82, 0x01, 0x31, + 0x30, 0x09, 0x06, 0x03, 0x55, 0x1D, 0x13, 0x04, 0x02, 0x30, + 0x00, 0x30, 0x11, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x86, + 0xF8, 0x42, 0x01, 0x01, 0x04, 0x04, 0x03, 0x02, 0x06, 0x40, + 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, + 0x14, 0x5D, 0x5D, 0x26, 0xEF, 0xAC, 0x7E, 0x36, 0xF9, 0x9B, + 0x76, 0x15, 0x2B, 0x4A, 0x25, 0x02, 0x23, 0xEF, 0xB2, 0x89, + 0x30, 0x30, 0x81, 0xCC, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, + 0x81, 0xC4, 0x30, 0x81, 0xC1, 0x80, 0x14, 0x56, 0x8E, 0x9A, + 0xC3, 0xF0, 0x42, 0xDE, 0x18, 0xB9, 0x45, 0x55, 0x6E, 0xF9, + 0x93, 0xCF, 0xEA, 0xC3, 0xF3, 0xA5, 0x21, 0xA1, 0x81, 0x9D, + 0xA4, 0x81, 0x9A, 0x30, 0x81, 0x97, 0x31, 0x0B, 0x30, 0x09, + 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, + 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0C, 0x0A, + 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, 0x6F, 0x6E, + 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, + 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, 0x6C, 0x65, 0x31, 0x10, + 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x77, + 0x6F, 0x6C, 0x66, 0x53, 0x53, 0x4C, 0x31, 0x14, 0x30, 0x12, + 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x0B, 0x44, 0x65, 0x76, + 0x65, 0x6C, 0x6F, 0x70, 0x6D, 0x65, 0x6E, 0x74, 0x31, 0x18, + 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x77, + 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, + 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, + 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, + 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, 0x6F, 0x6C, 0x66, + 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x82, 0x09, 0x00, + 0x97, 0xB4, 0xBD, 0x16, 0x78, 0xF8, 0x47, 0xF2, 0x30, 0x0E, + 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, + 0x03, 0x02, 0x03, 0xA8, 0x30, 0x13, 0x06, 0x03, 0x55, 0x1D, + 0x25, 0x04, 0x0C, 0x30, 0x0A, 0x06, 0x08, 0x2B, 0x06, 0x01, + 0x05, 0x05, 0x07, 0x03, 0x01, 0x30, 0x0A, 0x06, 0x08, 0x2A, + 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x03, 0x49, 0x00, + 0x30, 0x46, 0x02, 0x21, 0x00, 0xBE, 0xB8, 0x58, 0xF0, 0xE4, + 0x15, 0x01, 0x1F, 0xDF, 0x70, 0x54, 0x73, 0x4A, 0x6C, 0x40, + 0x1F, 0x77, 0xA8, 0xB4, 0xEB, 0x52, 0x1E, 0xBF, 0xF5, 0x0D, + 0xB1, 0x33, 0xCA, 0x6A, 0xC4, 0x76, 0xB9, 0x02, 0x21, 0x00, + 0x97, 0x08, 0xDE, 0x2C, 0x28, 0xC1, 0x45, 0x71, 0xB6, 0x2C, + 0x54, 0x87, 0x98, 0x63, 0x76, 0xA8, 0x21, 0x34, 0x90, 0xA8, + 0xF7, 0x9E, 0x3F, 0xFC, 0x02, 0xB0, 0xE7, 0xD3, 0x09, 0x31, + 0x27, 0xE4 +}; +static const int sizeof_serv_ecc_der_256 = sizeof(serv_ecc_der_256); + +/* ./certs/ca-ecc-key.der, ECC */ +static const unsigned char ca_ecc_key_der_256[] = +{ + 0x30, 0x77, 0x02, 0x01, 0x01, 0x04, 0x20, 0x02, 0xE1, 0x33, + 0x98, 0x77, 0x97, 0xAC, 0x4A, 0x59, 0x6D, 0x28, 0x9B, 0x6E, + 0xA0, 0x93, 0x9B, 0x07, 0x71, 0x8B, 0x4D, 0x60, 0x63, 0x85, + 0x99, 0xE6, 0xBB, 0x16, 0x70, 0xE9, 0x0A, 0xF6, 0x80, 0xA0, + 0x0A, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, + 0x07, 0xA1, 0x44, 0x03, 0x42, 0x00, 0x04, 0x02, 0xD3, 0xD9, + 0x6E, 0xD6, 0x01, 0x8E, 0x45, 0xC8, 0xB9, 0x90, 0x31, 0xE5, + 0xC0, 0x4C, 0xE3, 0x9E, 0xAD, 0x29, 0x38, 0x98, 0xBA, 0x10, + 0xD6, 0xE9, 0x09, 0x2A, 0x80, 0xA9, 0x2E, 0x17, 0x2A, 0xB9, + 0x8A, 0xBF, 0x33, 0x83, 0x46, 0xE3, 0x95, 0x0B, 0xE4, 0x77, + 0x40, 0xB5, 0x3B, 0x43, 0x45, 0x33, 0x0F, 0x61, 0x53, 0x7C, + 0x37, 0x44, 0xC1, 0xCB, 0xFC, 0x80, 0xCA, 0xE8, 0x43, 0xEA, + 0xA7 +}; +static const int sizeof_ca_ecc_key_der_256 = sizeof(ca_ecc_key_der_256); + +/* ./certs/ca-ecc-cert.der, ECC */ +static const unsigned char ca_ecc_cert_der_256[] = +{ + 0x30, 0x82, 0x02, 0x8B, 0x30, 0x82, 0x02, 0x30, 0xA0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0xFD, 0x0E, 0x29, 0x21, + 0x66, 0xCB, 0x48, 0xA3, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, + 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, 0x30, 0x81, 0x97, 0x31, + 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0C, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, + 0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, + 0x04, 0x07, 0x0C, 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, 0x6C, + 0x65, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x07, 0x77, 0x6F, 0x6C, 0x66, 0x53, 0x53, 0x4C, 0x31, + 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x0B, + 0x44, 0x65, 0x76, 0x65, 0x6C, 0x6F, 0x70, 0x6D, 0x65, 0x6E, + 0x74, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, + 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, + 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, + 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, + 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, + 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x38, 0x30, 0x34, 0x31, 0x33, + 0x31, 0x35, 0x32, 0x33, 0x31, 0x30, 0x5A, 0x17, 0x0D, 0x32, + 0x31, 0x30, 0x31, 0x30, 0x37, 0x31, 0x35, 0x32, 0x33, 0x31, + 0x30, 0x5A, 0x30, 0x81, 0x97, 0x31, 0x0B, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, + 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0C, 0x0A, 0x57, + 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, 0x6F, 0x6E, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, + 0x53, 0x65, 0x61, 0x74, 0x74, 0x6C, 0x65, 0x31, 0x10, 0x30, + 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x77, 0x6F, + 0x6C, 0x66, 0x53, 0x53, 0x4C, 0x31, 0x14, 0x30, 0x12, 0x06, + 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x0B, 0x44, 0x65, 0x76, 0x65, + 0x6C, 0x6F, 0x70, 0x6D, 0x65, 0x6E, 0x74, 0x31, 0x18, 0x30, + 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x77, 0x77, + 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, + 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, + 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, + 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, 0x6F, 0x6C, 0x66, 0x73, + 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x30, 0x59, 0x30, 0x13, + 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, + 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03, + 0x42, 0x00, 0x04, 0x02, 0xD3, 0xD9, 0x6E, 0xD6, 0x01, 0x8E, + 0x45, 0xC8, 0xB9, 0x90, 0x31, 0xE5, 0xC0, 0x4C, 0xE3, 0x9E, + 0xAD, 0x29, 0x38, 0x98, 0xBA, 0x10, 0xD6, 0xE9, 0x09, 0x2A, + 0x80, 0xA9, 0x2E, 0x17, 0x2A, 0xB9, 0x8A, 0xBF, 0x33, 0x83, + 0x46, 0xE3, 0x95, 0x0B, 0xE4, 0x77, 0x40, 0xB5, 0x3B, 0x43, + 0x45, 0x33, 0x0F, 0x61, 0x53, 0x7C, 0x37, 0x44, 0xC1, 0xCB, + 0xFC, 0x80, 0xCA, 0xE8, 0x43, 0xEA, 0xA7, 0xA3, 0x63, 0x30, + 0x61, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, + 0x04, 0x14, 0x56, 0x8E, 0x9A, 0xC3, 0xF0, 0x42, 0xDE, 0x18, + 0xB9, 0x45, 0x55, 0x6E, 0xF9, 0x93, 0xCF, 0xEA, 0xC3, 0xF3, + 0xA5, 0x21, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, + 0x18, 0x30, 0x16, 0x80, 0x14, 0x56, 0x8E, 0x9A, 0xC3, 0xF0, + 0x42, 0xDE, 0x18, 0xB9, 0x45, 0x55, 0x6E, 0xF9, 0x93, 0xCF, + 0xEA, 0xC3, 0xF3, 0xA5, 0x21, 0x30, 0x0F, 0x06, 0x03, 0x55, + 0x1D, 0x13, 0x01, 0x01, 0xFF, 0x04, 0x05, 0x30, 0x03, 0x01, + 0x01, 0xFF, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, + 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x0A, + 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x02, + 0x03, 0x49, 0x00, 0x30, 0x46, 0x02, 0x21, 0x00, 0xF0, 0x7B, + 0xCC, 0x24, 0x73, 0x19, 0x3F, 0x61, 0x68, 0xED, 0xC8, 0x0A, + 0x54, 0x4A, 0xB8, 0xAC, 0x79, 0xEF, 0x10, 0x32, 0x91, 0x52, + 0x2C, 0x3E, 0xBF, 0x50, 0xAA, 0x5F, 0x18, 0xC1, 0x97, 0xF5, + 0x02, 0x21, 0x00, 0xD9, 0x4B, 0x63, 0x67, 0x6F, 0x9B, 0x29, + 0xA9, 0xD7, 0x6B, 0x63, 0x9B, 0x98, 0x9F, 0x32, 0x82, 0x36, + 0xDA, 0xF0, 0xA9, 0xF7, 0x51, 0xB4, 0x97, 0xAA, 0xFA, 0xFA, + 0xDD, 0xEF, 0xEF, 0x4A, 0xAE +}; +static const int sizeof_ca_ecc_cert_der_256 = sizeof(ca_ecc_cert_der_256); + +/* ./certs/ca-ecc384-key.der, ECC */ +static const unsigned char ca_ecc_key_der_384[] = +{ + 0x30, 0x81, 0xA4, 0x02, 0x01, 0x01, 0x04, 0x30, 0x7B, 0x16, + 0xE3, 0xD6, 0xD2, 0x81, 0x94, 0x6C, 0x8A, 0xDD, 0xA8, 0x78, + 0xEE, 0xC7, 0x7E, 0xB3, 0xC5, 0xD1, 0xDB, 0x2E, 0xF3, 0xED, + 0x0E, 0x48, 0x85, 0xB1, 0xF2, 0xE1, 0x7A, 0x39, 0x56, 0xC0, + 0xF1, 0x62, 0x12, 0x0F, 0x35, 0xB7, 0x39, 0xBC, 0x9C, 0x25, + 0xC0, 0x76, 0xEB, 0xFE, 0x55, 0x70, 0xA0, 0x07, 0x06, 0x05, + 0x2B, 0x81, 0x04, 0x00, 0x22, 0xA1, 0x64, 0x03, 0x62, 0x00, + 0x04, 0xEE, 0x82, 0xD4, 0x39, 0x9A, 0xB1, 0x27, 0x82, 0xF4, + 0xD7, 0xEA, 0xC6, 0xBC, 0x03, 0x1D, 0x4D, 0x83, 0x61, 0xF4, + 0x03, 0xAE, 0x7E, 0xBD, 0xD8, 0x5A, 0xA5, 0xB9, 0xF0, 0x8E, + 0xA2, 0xA5, 0xDA, 0xCE, 0x87, 0x3B, 0x5A, 0xAB, 0x44, 0x16, + 0x9C, 0xF5, 0x9F, 0x62, 0xDD, 0xF6, 0x20, 0xCD, 0x9C, 0x76, + 0x3C, 0x40, 0xB1, 0x3F, 0x97, 0x17, 0xDF, 0x59, 0xF6, 0xCD, + 0xDE, 0xCD, 0x46, 0x35, 0xC0, 0xED, 0x5E, 0x2E, 0x48, 0xB6, + 0x66, 0x91, 0x71, 0x74, 0xB7, 0x0C, 0x3F, 0xB9, 0x9A, 0xB7, + 0x83, 0xBD, 0x93, 0x3F, 0x5F, 0x50, 0x2D, 0x70, 0x3F, 0xDE, + 0x35, 0x25, 0xE1, 0x90, 0x3B, 0x86, 0xE0 +}; +static const int sizeof_ca_ecc_key_der_384 = sizeof(ca_ecc_key_der_384); + +/* ./certs/ca-ecc384-cert.der, ECC */ +static const unsigned char ca_ecc_cert_der_384[] = +{ + 0x30, 0x82, 0x02, 0xC7, 0x30, 0x82, 0x02, 0x4D, 0xA0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x09, 0x00, 0xFC, 0x39, 0x04, 0xA4, + 0x0E, 0xA5, 0x6C, 0x87, 0x30, 0x0A, 0x06, 0x08, 0x2A, 0x86, + 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x03, 0x30, 0x81, 0x97, 0x31, + 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x55, 0x53, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0C, 0x0A, 0x57, 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, + 0x74, 0x6F, 0x6E, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, + 0x04, 0x07, 0x0C, 0x07, 0x53, 0x65, 0x61, 0x74, 0x74, 0x6C, + 0x65, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x07, 0x77, 0x6F, 0x6C, 0x66, 0x53, 0x53, 0x4C, 0x31, + 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x0B, + 0x44, 0x65, 0x76, 0x65, 0x6C, 0x6F, 0x70, 0x6D, 0x65, 0x6E, + 0x74, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, + 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, + 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, + 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, + 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, + 0x30, 0x1E, 0x17, 0x0D, 0x31, 0x38, 0x30, 0x34, 0x31, 0x33, + 0x31, 0x35, 0x32, 0x33, 0x31, 0x30, 0x5A, 0x17, 0x0D, 0x32, + 0x31, 0x30, 0x31, 0x30, 0x37, 0x31, 0x35, 0x32, 0x33, 0x31, + 0x30, 0x5A, 0x30, 0x81, 0x97, 0x31, 0x0B, 0x30, 0x09, 0x06, + 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x13, + 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0C, 0x0A, 0x57, + 0x61, 0x73, 0x68, 0x69, 0x6E, 0x67, 0x74, 0x6F, 0x6E, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, + 0x53, 0x65, 0x61, 0x74, 0x74, 0x6C, 0x65, 0x31, 0x10, 0x30, + 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x77, 0x6F, + 0x6C, 0x66, 0x53, 0x53, 0x4C, 0x31, 0x14, 0x30, 0x12, 0x06, + 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x0B, 0x44, 0x65, 0x76, 0x65, + 0x6C, 0x6F, 0x70, 0x6D, 0x65, 0x6E, 0x74, 0x31, 0x18, 0x30, + 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x77, 0x77, + 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, + 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, + 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, + 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, 0x6F, 0x6C, 0x66, 0x73, + 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x30, 0x76, 0x30, 0x10, + 0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, + 0x05, 0x2B, 0x81, 0x04, 0x00, 0x22, 0x03, 0x62, 0x00, 0x04, + 0xEE, 0x82, 0xD4, 0x39, 0x9A, 0xB1, 0x27, 0x82, 0xF4, 0xD7, + 0xEA, 0xC6, 0xBC, 0x03, 0x1D, 0x4D, 0x83, 0x61, 0xF4, 0x03, + 0xAE, 0x7E, 0xBD, 0xD8, 0x5A, 0xA5, 0xB9, 0xF0, 0x8E, 0xA2, + 0xA5, 0xDA, 0xCE, 0x87, 0x3B, 0x5A, 0xAB, 0x44, 0x16, 0x9C, + 0xF5, 0x9F, 0x62, 0xDD, 0xF6, 0x20, 0xCD, 0x9C, 0x76, 0x3C, + 0x40, 0xB1, 0x3F, 0x97, 0x17, 0xDF, 0x59, 0xF6, 0xCD, 0xDE, + 0xCD, 0x46, 0x35, 0xC0, 0xED, 0x5E, 0x2E, 0x48, 0xB6, 0x66, + 0x91, 0x71, 0x74, 0xB7, 0x0C, 0x3F, 0xB9, 0x9A, 0xB7, 0x83, + 0xBD, 0x93, 0x3F, 0x5F, 0x50, 0x2D, 0x70, 0x3F, 0xDE, 0x35, + 0x25, 0xE1, 0x90, 0x3B, 0x86, 0xE0, 0xA3, 0x63, 0x30, 0x61, + 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, + 0x14, 0xAB, 0xE0, 0xC3, 0x26, 0x4C, 0x18, 0xD4, 0x72, 0xBB, + 0xD2, 0x84, 0x8C, 0x9C, 0x0A, 0x05, 0x92, 0x80, 0x12, 0x53, + 0x52, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, + 0x30, 0x16, 0x80, 0x14, 0xAB, 0xE0, 0xC3, 0x26, 0x4C, 0x18, + 0xD4, 0x72, 0xBB, 0xD2, 0x84, 0x8C, 0x9C, 0x0A, 0x05, 0x92, + 0x80, 0x12, 0x53, 0x52, 0x30, 0x0F, 0x06, 0x03, 0x55, 0x1D, + 0x13, 0x01, 0x01, 0xFF, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, + 0xFF, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, + 0xFF, 0x04, 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x0A, 0x06, + 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x04, 0x03, 0x03, 0x03, + 0x68, 0x00, 0x30, 0x65, 0x02, 0x30, 0x0D, 0x0A, 0x62, 0xFB, + 0xE6, 0x3A, 0xFE, 0x71, 0xD8, 0x2B, 0x44, 0xE5, 0x97, 0x34, + 0x04, 0xA9, 0x8C, 0x0A, 0x99, 0x88, 0xA0, 0xBD, 0x1F, 0xB0, + 0xDF, 0x94, 0x59, 0x27, 0xBB, 0x2B, 0xC6, 0x2A, 0xBE, 0xA4, + 0x69, 0x1B, 0xCF, 0x97, 0x78, 0x2A, 0x28, 0x96, 0xEE, 0xBA, + 0xD4, 0x87, 0x45, 0xFD, 0x02, 0x31, 0x00, 0xC0, 0x73, 0x19, + 0x66, 0x76, 0x5E, 0x9F, 0xA3, 0x65, 0x85, 0x41, 0xEF, 0xB7, + 0x7B, 0x3D, 0x63, 0x6D, 0x98, 0x71, 0x99, 0x6F, 0x9C, 0xDB, + 0xA8, 0x5E, 0x53, 0x6E, 0xA0, 0x68, 0x11, 0x65, 0xBC, 0x78, + 0x74, 0x28, 0x69, 0xC7, 0x64, 0x9D, 0x88, 0xF2, 0xD8, 0xC2, + 0x3D, 0x29, 0x03, 0x83, 0x23 +}; +static const int sizeof_ca_ecc_cert_der_384 = sizeof(ca_ecc_cert_der_384); + +#endif /* HAVE_ECC && USE_CERT_BUFFERS_256 */ + +/* dh1024 p */ +static const unsigned char dh_p[] = +{ + 0xE6, 0x96, 0x9D, 0x3D, 0x49, 0x5B, 0xE3, 0x2C, 0x7C, 0xF1, 0x80, 0xC3, + 0xBD, 0xD4, 0x79, 0x8E, 0x91, 0xB7, 0x81, 0x82, 0x51, 0xBB, 0x05, 0x5E, + 0x2A, 0x20, 0x64, 0x90, 0x4A, 0x79, 0xA7, 0x70, 0xFA, 0x15, 0xA2, 0x59, + 0xCB, 0xD5, 0x23, 0xA6, 0xA6, 0xEF, 0x09, 0xC4, 0x30, 0x48, 0xD5, 0xA2, + 0x2F, 0x97, 0x1F, 0x3C, 0x20, 0x12, 0x9B, 0x48, 0x00, 0x0E, 0x6E, 0xDD, + 0x06, 0x1C, 0xBC, 0x05, 0x3E, 0x37, 0x1D, 0x79, 0x4E, 0x53, 0x27, 0xDF, + 0x61, 0x1E, 0xBB, 0xBE, 0x1B, 0xAC, 0x9B, 0x5C, 0x60, 0x44, 0xCF, 0x02, + 0x3D, 0x76, 0xE0, 0x5E, 0xEA, 0x9B, 0xAD, 0x99, 0x1B, 0x13, 0xA6, 0x3C, + 0x97, 0x4E, 0x9E, 0xF1, 0x83, 0x9E, 0xB5, 0xDB, 0x12, 0x51, 0x36, 0xF7, + 0x26, 0x2E, 0x56, 0xA8, 0x87, 0x15, 0x38, 0xDF, 0xD8, 0x23, 0xC6, 0x50, + 0x50, 0x85, 0xE2, 0x1F, 0x0D, 0xD5, 0xC8, 0x6B, +}; + +/* dh1024 g */ +static const unsigned char dh_g[] = +{ + 0x02, +}; + +#if defined(HAVE_ED25519) + +/* ./certs/ed25519/server-ed25519.der, ED25519 */ +static const unsigned char server_ed25519_cert[] = +{ + 0x30, 0x82, 0x02, 0x52, 0x30, 0x82, 0x02, 0x04, 0xA0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x10, 0x00, 0xCD, 0xF2, 0x2F, 0xBE, + 0xDC, 0x07, 0xFA, 0xBB, 0x65, 0x03, 0xE2, 0xFF, 0xEA, 0x6A, + 0x99, 0x30, 0x05, 0x06, 0x03, 0x2B, 0x65, 0x70, 0x30, 0x81, + 0x9D, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, + 0x55, 0x04, 0x08, 0x0C, 0x07, 0x4D, 0x6F, 0x6E, 0x74, 0x61, + 0x6E, 0x61, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x0C, 0x07, 0x42, 0x6F, 0x7A, 0x65, 0x6D, 0x61, 0x6E, + 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x04, 0x0C, + 0x02, 0x43, 0x41, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, + 0x04, 0x0A, 0x0C, 0x07, 0x77, 0x6F, 0x6C, 0x66, 0x53, 0x53, + 0x4C, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, + 0x0C, 0x07, 0x45, 0x44, 0x32, 0x35, 0x35, 0x31, 0x39, 0x31, + 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, + 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, + 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, 0x1D, 0x06, + 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01, + 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, 0x6F, 0x6C, + 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x30, 0x22, + 0x18, 0x0F, 0x32, 0x30, 0x31, 0x38, 0x30, 0x34, 0x31, 0x32, + 0x31, 0x36, 0x32, 0x32, 0x31, 0x37, 0x5A, 0x18, 0x0F, 0x32, + 0x30, 0x32, 0x31, 0x30, 0x31, 0x30, 0x37, 0x31, 0x35, 0x32, + 0x32, 0x31, 0x37, 0x5A, 0x30, 0x81, 0x9F, 0x31, 0x0B, 0x30, + 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, + 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x08, 0x0C, + 0x07, 0x4D, 0x6F, 0x6E, 0x74, 0x61, 0x6E, 0x61, 0x31, 0x10, + 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, 0x07, 0x42, + 0x6F, 0x7A, 0x65, 0x6D, 0x61, 0x6E, 0x31, 0x0D, 0x30, 0x0B, + 0x06, 0x03, 0x55, 0x04, 0x04, 0x0C, 0x04, 0x4C, 0x65, 0x61, + 0x66, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x07, 0x77, 0x6F, 0x6C, 0x66, 0x53, 0x53, 0x4C, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x07, + 0x45, 0x44, 0x32, 0x35, 0x35, 0x31, 0x39, 0x31, 0x18, 0x30, + 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x77, 0x77, + 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, + 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, + 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, + 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, 0x6F, 0x6C, 0x66, 0x73, + 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x30, 0x2A, 0x30, 0x05, + 0x06, 0x03, 0x2B, 0x65, 0x70, 0x03, 0x21, 0x00, 0x61, 0x5D, + 0xEC, 0xB7, 0x45, 0x93, 0xC9, 0x84, 0x7B, 0x68, 0x21, 0x4A, + 0x4D, 0xF4, 0x04, 0x8B, 0xBD, 0xCD, 0x6C, 0x5D, 0x3D, 0xB7, + 0x62, 0x2C, 0x2D, 0x25, 0xC3, 0x22, 0x49, 0xC8, 0x86, 0xF2, + 0xA3, 0x52, 0x30, 0x50, 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, + 0x0E, 0x04, 0x16, 0x04, 0x14, 0x33, 0xC8, 0x28, 0x63, 0x8C, + 0xF4, 0x57, 0xEE, 0x1E, 0xB0, 0xC7, 0x12, 0x12, 0x76, 0x8A, + 0x80, 0x30, 0x3A, 0xCB, 0x10, 0x30, 0x1F, 0x06, 0x03, 0x55, + 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, 0x80, 0x14, 0x92, 0x3F, + 0x96, 0x72, 0x02, 0xFA, 0x61, 0x1C, 0x21, 0x6D, 0x88, 0xDD, + 0xEB, 0xDD, 0x3C, 0x9B, 0x17, 0xC4, 0x9F, 0xB7, 0x30, 0x0E, + 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, + 0x03, 0x02, 0x06, 0xC0, 0x30, 0x05, 0x06, 0x03, 0x2B, 0x65, + 0x70, 0x03, 0x41, 0x00, 0x15, 0x88, 0x86, 0xFC, 0x66, 0xD1, + 0xE0, 0xF6, 0xCF, 0xC9, 0x09, 0x46, 0xD0, 0x50, 0xE2, 0x01, + 0x5D, 0xF7, 0xCF, 0x57, 0xB8, 0xBA, 0x90, 0x84, 0xCB, 0xF1, + 0x24, 0x4B, 0xEF, 0xA5, 0x95, 0x7D, 0x69, 0x92, 0x88, 0xA8, + 0x89, 0x63, 0xCC, 0x90, 0x40, 0xC2, 0x41, 0x3A, 0x40, 0x76, + 0xB1, 0x2D, 0xA8, 0xA8, 0x97, 0xC9, 0x73, 0xC7, 0x82, 0x30, + 0x24, 0x61, 0xB0, 0xAA, 0xCA, 0xAA, 0x68, 0x00 +}; +static const int sizeof_server_ed25519_cert = sizeof(server_ed25519_cert); + +/* ./certs/ed25519/server-ed25519-key.der, ED25519 */ +static const unsigned char server_ed25519_key[] = +{ + 0x30, 0x52, 0x02, 0x01, 0x00, 0x30, 0x05, 0x06, 0x03, 0x2B, + 0x65, 0x70, 0x04, 0x22, 0x04, 0x20, 0x02, 0x2F, 0xC5, 0xFF, + 0xBA, 0x8E, 0xD0, 0xD2, 0xBF, 0x03, 0x8E, 0x76, 0x8F, 0xC8, + 0x86, 0x80, 0x71, 0x87, 0x97, 0x31, 0xE2, 0x40, 0xAC, 0xDF, + 0xBB, 0x90, 0x15, 0x52, 0x6E, 0x24, 0xA1, 0x39, 0xA1, 0x22, + 0x04, 0x20, 0x61, 0x5D, 0xEC, 0xB7, 0x45, 0x93, 0xC9, 0x84, + 0x7B, 0x68, 0x21, 0x4A, 0x4D, 0xF4, 0x04, 0x8B, 0xBD, 0xCD, + 0x6C, 0x5D, 0x3D, 0xB7, 0x62, 0x2C, 0x2D, 0x25, 0xC3, 0x22, + 0x49, 0xC8, 0x86, 0xF2 +}; +static const int sizeof_server_ed25519_key = sizeof(server_ed25519_key); + +/* ./certs/ed25519/ca-ed25519.der, ED25519 */ +static const unsigned char ca_ed25519_cert[] = +{ + 0x30, 0x82, 0x02, 0x60, 0x30, 0x82, 0x02, 0x12, 0xA0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x10, 0x00, 0x80, 0xBA, 0x68, 0x77, + 0xEF, 0xA5, 0xE5, 0x42, 0x7D, 0xC6, 0x73, 0x2C, 0x54, 0x85, + 0xB8, 0x30, 0x05, 0x06, 0x03, 0x2B, 0x65, 0x70, 0x30, 0x81, + 0x9F, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, + 0x55, 0x04, 0x08, 0x0C, 0x07, 0x4D, 0x6F, 0x6E, 0x74, 0x61, + 0x6E, 0x61, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x0C, 0x07, 0x42, 0x6F, 0x7A, 0x65, 0x6D, 0x61, 0x6E, + 0x31, 0x0D, 0x30, 0x0B, 0x06, 0x03, 0x55, 0x04, 0x04, 0x0C, + 0x04, 0x52, 0x6F, 0x6F, 0x74, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x77, 0x6F, 0x6C, 0x66, + 0x53, 0x53, 0x4C, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, + 0x04, 0x0B, 0x0C, 0x07, 0x45, 0x44, 0x32, 0x35, 0x35, 0x31, + 0x39, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, + 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, + 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, + 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, + 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, + 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, + 0x30, 0x22, 0x18, 0x0F, 0x32, 0x30, 0x31, 0x38, 0x30, 0x34, + 0x31, 0x32, 0x31, 0x36, 0x32, 0x32, 0x31, 0x37, 0x5A, 0x18, + 0x0F, 0x32, 0x30, 0x32, 0x31, 0x30, 0x31, 0x30, 0x37, 0x31, + 0x35, 0x32, 0x32, 0x31, 0x37, 0x5A, 0x30, 0x81, 0x9D, 0x31, + 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, + 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x08, 0x0C, 0x07, 0x4D, 0x6F, 0x6E, 0x74, 0x61, 0x6E, 0x61, + 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x07, 0x0C, + 0x07, 0x42, 0x6F, 0x7A, 0x65, 0x6D, 0x61, 0x6E, 0x31, 0x0B, + 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x04, 0x0C, 0x02, 0x43, + 0x41, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, + 0x0C, 0x07, 0x77, 0x6F, 0x6C, 0x66, 0x53, 0x53, 0x4C, 0x31, + 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x07, + 0x45, 0x44, 0x32, 0x35, 0x35, 0x31, 0x39, 0x31, 0x18, 0x30, + 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0C, 0x0F, 0x77, 0x77, + 0x77, 0x2E, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, + 0x63, 0x6F, 0x6D, 0x31, 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, + 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, + 0x69, 0x6E, 0x66, 0x6F, 0x40, 0x77, 0x6F, 0x6C, 0x66, 0x73, + 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x30, 0x2A, 0x30, 0x05, + 0x06, 0x03, 0x2B, 0x65, 0x70, 0x03, 0x21, 0x00, 0x65, 0xAA, + 0x7F, 0x05, 0xA4, 0x04, 0x34, 0xA0, 0xEA, 0xAD, 0x1F, 0xA9, + 0x86, 0xF0, 0xD8, 0x7F, 0x72, 0xDF, 0xA9, 0x0E, 0x13, 0xA0, + 0x38, 0x66, 0x26, 0x5E, 0xEB, 0x48, 0x30, 0x80, 0x48, 0x49, + 0xA3, 0x60, 0x30, 0x5E, 0x30, 0x0C, 0x06, 0x03, 0x55, 0x1D, + 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xFF, 0x30, 0x1D, + 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, 0x14, 0x92, + 0x3F, 0x96, 0x72, 0x02, 0xFA, 0x61, 0x1C, 0x21, 0x6D, 0x88, + 0xDD, 0xEB, 0xDD, 0x3C, 0x9B, 0x17, 0xC4, 0x9F, 0xB7, 0x30, + 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, 0x30, 0x16, + 0x80, 0x14, 0xFE, 0x01, 0x46, 0x7F, 0x6F, 0x2B, 0x3E, 0x1C, + 0xB0, 0x6F, 0xE1, 0xCC, 0x4D, 0x02, 0x25, 0xF7, 0x4D, 0x0A, + 0x95, 0xB8, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x1D, 0x0F, 0x01, + 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, 0x01, 0xC6, 0x30, 0x05, + 0x06, 0x03, 0x2B, 0x65, 0x70, 0x03, 0x41, 0x00, 0x4C, 0x40, + 0xD0, 0x7F, 0xBC, 0xFB, 0xF4, 0xA2, 0x1A, 0x58, 0xF6, 0x72, + 0xE3, 0xE8, 0xDA, 0x18, 0x0D, 0x94, 0xDC, 0x0E, 0xFD, 0xC1, + 0xE7, 0x02, 0xA5, 0x7A, 0xEE, 0xCB, 0xC2, 0x7E, 0xFA, 0xA1, + 0xFC, 0x15, 0x9A, 0xFE, 0x1E, 0xE0, 0x37, 0xDF, 0x7F, 0xAB, + 0x76, 0x50, 0x06, 0xD4, 0x3D, 0x1A, 0x65, 0x73, 0x3F, 0x92, + 0xD4, 0x44, 0x62, 0xA7, 0x4C, 0xB3, 0x2A, 0x01, 0x87, 0xE3, + 0x06, 0x06 +}; +static const int sizeof_ca_ed25519_cert = sizeof(ca_ed25519_cert); + +/* ./certs/ed25519/client-ed25519.der, ED25519 */ +static const unsigned char client_ed25519_cert[] = +{ + 0x30, 0x82, 0x02, 0x58, 0x30, 0x82, 0x02, 0x0A, 0xA0, 0x03, + 0x02, 0x01, 0x02, 0x02, 0x10, 0x00, 0x8F, 0x2F, 0x35, 0xB2, + 0x53, 0xBD, 0x4F, 0x92, 0xD1, 0xFF, 0x1D, 0x4B, 0x40, 0xA5, + 0x49, 0x30, 0x05, 0x06, 0x03, 0x2B, 0x65, 0x70, 0x30, 0x81, + 0xA1, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, + 0x55, 0x04, 0x08, 0x0C, 0x07, 0x4D, 0x6F, 0x6E, 0x74, 0x61, + 0x6E, 0x61, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x0C, 0x07, 0x42, 0x6F, 0x7A, 0x65, 0x6D, 0x61, 0x6E, + 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x04, 0x0C, + 0x06, 0x63, 0x6C, 0x69, 0x65, 0x6E, 0x74, 0x31, 0x10, 0x30, + 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x77, 0x6F, + 0x6C, 0x66, 0x53, 0x53, 0x4C, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x07, 0x45, 0x44, 0x32, 0x35, + 0x35, 0x31, 0x39, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, + 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, + 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, + 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, + 0x40, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, + 0x6F, 0x6D, 0x30, 0x22, 0x18, 0x0F, 0x32, 0x30, 0x31, 0x38, + 0x30, 0x34, 0x31, 0x32, 0x31, 0x36, 0x32, 0x32, 0x31, 0x37, + 0x5A, 0x18, 0x0F, 0x32, 0x30, 0x32, 0x31, 0x30, 0x31, 0x30, + 0x37, 0x31, 0x35, 0x32, 0x32, 0x31, 0x37, 0x5A, 0x30, 0x81, + 0xA1, 0x31, 0x0B, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, + 0x55, 0x04, 0x08, 0x0C, 0x07, 0x4D, 0x6F, 0x6E, 0x74, 0x61, + 0x6E, 0x61, 0x31, 0x10, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x04, + 0x07, 0x0C, 0x07, 0x42, 0x6F, 0x7A, 0x65, 0x6D, 0x61, 0x6E, + 0x31, 0x0F, 0x30, 0x0D, 0x06, 0x03, 0x55, 0x04, 0x04, 0x0C, + 0x06, 0x63, 0x6C, 0x69, 0x65, 0x6E, 0x74, 0x31, 0x10, 0x30, + 0x0E, 0x06, 0x03, 0x55, 0x04, 0x0A, 0x0C, 0x07, 0x77, 0x6F, + 0x6C, 0x66, 0x53, 0x53, 0x4C, 0x31, 0x10, 0x30, 0x0E, 0x06, + 0x03, 0x55, 0x04, 0x0B, 0x0C, 0x07, 0x45, 0x44, 0x32, 0x35, + 0x35, 0x31, 0x39, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, + 0x04, 0x03, 0x0C, 0x0F, 0x77, 0x77, 0x77, 0x2E, 0x77, 0x6F, + 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, 0x6F, 0x6D, 0x31, + 0x1F, 0x30, 0x1D, 0x06, 0x09, 0x2A, 0x86, 0x48, 0x86, 0xF7, + 0x0D, 0x01, 0x09, 0x01, 0x16, 0x10, 0x69, 0x6E, 0x66, 0x6F, + 0x40, 0x77, 0x6F, 0x6C, 0x66, 0x73, 0x73, 0x6C, 0x2E, 0x63, + 0x6F, 0x6D, 0x30, 0x2A, 0x30, 0x05, 0x06, 0x03, 0x2B, 0x65, + 0x70, 0x03, 0x21, 0x00, 0xA2, 0xF1, 0x26, 0x40, 0x9B, 0xA2, + 0x59, 0xDA, 0xDB, 0xE6, 0x15, 0x7F, 0x9A, 0x11, 0xB5, 0x48, + 0x5F, 0x55, 0xBA, 0x5E, 0xED, 0x46, 0xF7, 0x98, 0x67, 0xBE, + 0x0C, 0x93, 0xE3, 0xA4, 0x8E, 0x18, 0xA3, 0x52, 0x30, 0x50, + 0x30, 0x1D, 0x06, 0x03, 0x55, 0x1D, 0x0E, 0x04, 0x16, 0x04, + 0x14, 0xFE, 0x01, 0x46, 0x7F, 0x6F, 0x2B, 0x3E, 0x1C, 0xB0, + 0x6F, 0xE1, 0xCC, 0x4D, 0x02, 0x25, 0xF7, 0x4D, 0x0A, 0x95, + 0xB8, 0x30, 0x1F, 0x06, 0x03, 0x55, 0x1D, 0x23, 0x04, 0x18, + 0x30, 0x16, 0x80, 0x14, 0xFE, 0x01, 0x46, 0x7F, 0x6F, 0x2B, + 0x3E, 0x1C, 0xB0, 0x6F, 0xE1, 0xCC, 0x4D, 0x02, 0x25, 0xF7, + 0x4D, 0x0A, 0x95, 0xB8, 0x30, 0x0E, 0x06, 0x03, 0x55, 0x1D, + 0x0F, 0x01, 0x01, 0xFF, 0x04, 0x04, 0x03, 0x02, 0x06, 0xC0, + 0x30, 0x05, 0x06, 0x03, 0x2B, 0x65, 0x70, 0x03, 0x41, 0x00, + 0x29, 0xF6, 0x69, 0xE2, 0xB9, 0x73, 0x12, 0xD1, 0x64, 0xEB, + 0x8F, 0xE9, 0x6B, 0x61, 0xDB, 0x5F, 0xE9, 0xA7, 0x62, 0x6C, + 0x10, 0x89, 0x41, 0x80, 0xE3, 0xE8, 0xFD, 0x1F, 0xD0, 0x13, + 0xAE, 0x95, 0x00, 0xAF, 0xF7, 0x77, 0xE1, 0x22, 0x32, 0xAD, + 0x46, 0x4F, 0xDC, 0x7E, 0xFE, 0xAE, 0xBC, 0x8A, 0x1F, 0x96, + 0x0A, 0xDA, 0x9F, 0xC9, 0x93, 0x52, 0x27, 0x18, 0xB0, 0x8B, + 0xDA, 0xBE, 0x81, 0x09 +}; +static const int sizeof_client_ed25519_cert = sizeof(client_ed25519_cert); + +/* ./certs/ed25519/client-ed25519-key.der, ED25519 */ +static const unsigned char client_ed25519_key[] = +{ + 0x30, 0x52, 0x02, 0x01, 0x00, 0x30, 0x05, 0x06, 0x03, 0x2B, + 0x65, 0x70, 0x04, 0x22, 0x04, 0x20, 0x27, 0xA3, 0x34, 0x2A, + 0x35, 0xD4, 0xBB, 0xB8, 0xE1, 0xDC, 0xD8, 0xEC, 0x0F, 0xC1, + 0xA0, 0xD1, 0xA2, 0x5C, 0xF9, 0x06, 0xF0, 0x44, 0x5D, 0x3B, + 0x97, 0x4D, 0xBD, 0xDF, 0x4A, 0x3B, 0xA3, 0x4E, 0xA1, 0x22, + 0x04, 0x20, 0xA2, 0xF1, 0x26, 0x40, 0x9B, 0xA2, 0x59, 0xDA, + 0xDB, 0xE6, 0x15, 0x7F, 0x9A, 0x11, 0xB5, 0x48, 0x5F, 0x55, + 0xBA, 0x5E, 0xED, 0x46, 0xF7, 0x98, 0x67, 0xBE, 0x0C, 0x93, + 0xE3, 0xA4, 0x8E, 0x18 +}; +static const int sizeof_client_ed25519_key = sizeof(client_ed25519_key); + +#endif /* HAVE_ED25519 */ + +#endif /* WOLFSSL_CERTS_TEST_H */ + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/crl.h b/beken_os/beken378/func/wolfssl/wolfssl/crl.h new file mode 100755 index 0000000..48b488f --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/crl.h @@ -0,0 +1,50 @@ +/* crl.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifndef WOLFSSL_CRL_H +#define WOLFSSL_CRL_H + + +#ifdef HAVE_CRL + +#include +#include + +#ifdef __cplusplus + extern "C" { +#endif + +WOLFSSL_LOCAL int InitCRL(WOLFSSL_CRL*, WOLFSSL_CERT_MANAGER*); +WOLFSSL_LOCAL void FreeCRL(WOLFSSL_CRL*, int dynamic); + +WOLFSSL_LOCAL int LoadCRL(WOLFSSL_CRL* crl, const char* path, int type, int mon); +WOLFSSL_LOCAL int BufferLoadCRL(WOLFSSL_CRL*, const byte*, long, int, int); +WOLFSSL_LOCAL int CheckCertCRL(WOLFSSL_CRL*, DecodedCert*); + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* HAVE_CRL */ +#endif /* WOLFSSL_CRL_H */ diff --git a/beken_os/beken378/func/wolfssl/wolfssl/error-ssl.h b/beken_os/beken378/func/wolfssl/wolfssl/error-ssl.h new file mode 100755 index 0000000..7d0cf0f --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/error-ssl.h @@ -0,0 +1,199 @@ +/* error-ssl.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifndef WOLFSSL_ERROR_H +#define WOLFSSL_ERROR_H + +#include /* pull in wolfCrypt errors */ + +#ifdef __cplusplus + extern "C" { +#endif + +enum wolfSSL_ErrorCodes { + INPUT_CASE_ERROR = -301, /* process input state error */ + PREFIX_ERROR = -302, /* bad index to key rounds */ + MEMORY_ERROR = -303, /* out of memory */ + VERIFY_FINISHED_ERROR = -304, /* verify problem on finished */ + VERIFY_MAC_ERROR = -305, /* verify mac problem */ + PARSE_ERROR = -306, /* parse error on header */ + UNKNOWN_HANDSHAKE_TYPE = -307, /* weird handshake type */ + SOCKET_ERROR_E = -308, /* error state on socket */ + SOCKET_NODATA = -309, /* expected data, not there */ + INCOMPLETE_DATA = -310, /* don't have enough data to + complete task */ + UNKNOWN_RECORD_TYPE = -311, /* unknown type in record hdr */ + DECRYPT_ERROR = -312, /* error during decryption */ + FATAL_ERROR = -313, /* recvd alert fatal error */ + ENCRYPT_ERROR = -314, /* error during encryption */ + FREAD_ERROR = -315, /* fread problem */ + NO_PEER_KEY = -316, /* need peer's key */ + NO_PRIVATE_KEY = -317, /* need the private key */ + RSA_PRIVATE_ERROR = -318, /* error during rsa priv op */ + NO_DH_PARAMS = -319, /* server missing DH params */ + BUILD_MSG_ERROR = -320, /* build message failure */ + + BAD_HELLO = -321, /* client hello malformed */ + DOMAIN_NAME_MISMATCH = -322, /* peer subject name mismatch */ + WANT_READ = -323, /* want read, call again */ + NOT_READY_ERROR = -324, /* handshake layer not ready */ + + VERSION_ERROR = -326, /* record layer version error */ + WANT_WRITE = -327, /* want write, call again */ + BUFFER_ERROR = -328, /* malformed buffer input */ + VERIFY_CERT_ERROR = -329, /* verify cert error */ + VERIFY_SIGN_ERROR = -330, /* verify sign error */ + CLIENT_ID_ERROR = -331, /* psk client identity error */ + SERVER_HINT_ERROR = -332, /* psk server hint error */ + PSK_KEY_ERROR = -333, /* psk key error */ + + GETTIME_ERROR = -337, /* gettimeofday failed ??? */ + GETITIMER_ERROR = -338, /* getitimer failed ??? */ + SIGACT_ERROR = -339, /* sigaction failed ??? */ + SETITIMER_ERROR = -340, /* setitimer failed ??? */ + LENGTH_ERROR = -341, /* record layer length error */ + PEER_KEY_ERROR = -342, /* can't decode peer key */ + ZERO_RETURN = -343, /* peer sent close notify */ + SIDE_ERROR = -344, /* wrong client/server type */ + NO_PEER_CERT = -345, /* peer didn't send key */ + NTRU_KEY_ERROR = -346, /* NTRU key error */ + NTRU_DRBG_ERROR = -347, /* NTRU drbg error */ + NTRU_ENCRYPT_ERROR = -348, /* NTRU encrypt error */ + NTRU_DECRYPT_ERROR = -349, /* NTRU decrypt error */ + ECC_CURVETYPE_ERROR = -350, /* Bad ECC Curve Type */ + ECC_CURVE_ERROR = -351, /* Bad ECC Curve */ + ECC_PEERKEY_ERROR = -352, /* Bad Peer ECC Key */ + ECC_MAKEKEY_ERROR = -353, /* Bad Make ECC Key */ + ECC_EXPORT_ERROR = -354, /* Bad ECC Export Key */ + ECC_SHARED_ERROR = -355, /* Bad ECC Shared Secret */ + NOT_CA_ERROR = -357, /* Not a CA cert error */ + + BAD_CERT_MANAGER_ERROR = -359, /* Bad Cert Manager */ + OCSP_CERT_REVOKED = -360, /* OCSP Certificate revoked */ + CRL_CERT_REVOKED = -361, /* CRL Certificate revoked */ + CRL_MISSING = -362, /* CRL Not loaded */ + MONITOR_SETUP_E = -363, /* CRL Monitor setup error */ + THREAD_CREATE_E = -364, /* Thread Create Error */ + OCSP_NEED_URL = -365, /* OCSP need an URL for lookup */ + OCSP_CERT_UNKNOWN = -366, /* OCSP responder doesn't know */ + OCSP_LOOKUP_FAIL = -367, /* OCSP lookup not successful */ + MAX_CHAIN_ERROR = -368, /* max chain depth exceeded */ + COOKIE_ERROR = -369, /* dtls cookie error */ + SEQUENCE_ERROR = -370, /* dtls sequence error */ + SUITES_ERROR = -371, /* suites pointer error */ + + OUT_OF_ORDER_E = -373, /* out of order message */ + BAD_KEA_TYPE_E = -374, /* bad KEA type found */ + SANITY_CIPHER_E = -375, /* sanity check on cipher error */ + RECV_OVERFLOW_E = -376, /* RXCB returned more than rqed */ + GEN_COOKIE_E = -377, /* Generate Cookie Error */ + NO_PEER_VERIFY = -378, /* Need peer cert verify Error */ + FWRITE_ERROR = -379, /* fwrite problem */ + CACHE_MATCH_ERROR = -380, /* chache hdr match error */ + UNKNOWN_SNI_HOST_NAME_E = -381, /* Unrecognized host name Error */ + UNKNOWN_MAX_FRAG_LEN_E = -382, /* Unrecognized max frag len Error */ + KEYUSE_SIGNATURE_E = -383, /* KeyUse digSignature error */ + KEYUSE_ENCIPHER_E = -385, /* KeyUse keyEncipher error */ + EXTKEYUSE_AUTH_E = -386, /* ExtKeyUse server|client_auth */ + SEND_OOB_READ_E = -387, /* Send Cb out of bounds read */ + SECURE_RENEGOTIATION_E = -388, /* Invalid Renegotiation Info */ + SESSION_TICKET_LEN_E = -389, /* Session Ticket too large */ + SESSION_TICKET_EXPECT_E = -390, /* Session Ticket missing */ + SCR_DIFFERENT_CERT_E = -391, /* SCR Different cert error */ + SESSION_SECRET_CB_E = -392, /* Session secret Cb fcn failure */ + NO_CHANGE_CIPHER_E = -393, /* Finished before change cipher */ + SANITY_MSG_E = -394, /* Sanity check on msg order error */ + DUPLICATE_MSG_E = -395, /* Duplicate message error */ + SNI_UNSUPPORTED = -396, /* SSL 3.0 does not support SNI */ + SOCKET_PEER_CLOSED_E = -397, /* Underlying transport closed */ + BAD_TICKET_KEY_CB_SZ = -398, /* Bad session ticket key cb size */ + BAD_TICKET_MSG_SZ = -399, /* Bad session ticket msg size */ + BAD_TICKET_ENCRYPT = -400, /* Bad user ticket encrypt */ + DH_KEY_SIZE_E = -401, /* DH Key too small */ + SNI_ABSENT_ERROR = -402, /* No SNI request. */ + RSA_SIGN_FAULT = -403, /* RSA Sign fault */ + HANDSHAKE_SIZE_ERROR = -404, /* Handshake message too large */ + UNKNOWN_ALPN_PROTOCOL_NAME_E = -405, /* Unrecognized protocol name Error*/ + BAD_CERTIFICATE_STATUS_ERROR = -406, /* Bad certificate status message */ + OCSP_INVALID_STATUS = -407, /* Invalid OCSP Status */ + OCSP_WANT_READ = -408, /* OCSP callback response WOLFSSL_CBIO_ERR_WANT_READ */ + RSA_KEY_SIZE_E = -409, /* RSA key too small */ + ECC_KEY_SIZE_E = -410, /* ECC key too small */ + DTLS_EXPORT_VER_E = -411, /* export version error */ + INPUT_SIZE_E = -412, /* input size too big error */ + CTX_INIT_MUTEX_E = -413, /* initialize ctx mutex error */ + EXT_MASTER_SECRET_NEEDED_E = -414, /* need EMS enabled to resume */ + DTLS_POOL_SZ_E = -415, /* exceeded DTLS pool size */ + DECODE_E = -416, /* decode handshake message error */ + HTTP_TIMEOUT = -417, /* HTTP timeout for OCSP or CRL req */ + WRITE_DUP_READ_E = -418, /* Write dup write side can't read */ + WRITE_DUP_WRITE_E = -419, /* Write dup read side can't write */ + INVALID_CERT_CTX_E = -420, /* TLS cert ctx not matching */ + BAD_KEY_SHARE_DATA = -421, /* Key Share data invalid */ + MISSING_HANDSHAKE_DATA = -422, /* Handshake message missing data */ + BAD_BINDER = -423, /* Binder does not match */ + EXT_NOT_ALLOWED = -424, /* Extension not allowed in msg */ + INVALID_PARAMETER = -425, /* Security parameter invalid */ + MCAST_HIGHWATER_CB_E = -426, /* Multicast highwater cb err */ + ALERT_COUNT_E = -427, /* Alert Count exceeded err */ + EXT_MISSING = -428, /* Required extension not found */ + UNSUPPORTED_EXTENSION = -429, /* TLSX not requested by client */ + PRF_MISSING = -430, /* PRF not compiled in */ + DTLS_RETX_OVER_TX = -431, /* Retransmit DTLS flight over */ + DH_PARAMS_NOT_FFDHE_E = -432, /* DH params from server not FFDHE */ + TCA_INVALID_ID_TYPE = -433, /* TLSX TCA ID type invalid */ + TCA_ABSENT_ERROR = -434, /* TLSX TCA ID no response */ + /* add strings to wolfSSL_ERR_reason_error_string in internal.c !!!!! */ + + /* begin negotiation parameter errors */ + UNSUPPORTED_SUITE = -500, /* unsupported cipher suite */ + MATCH_SUITE_ERROR = -501, /* can't match cipher suite */ + COMPRESSION_ERROR = -502, /* compression mismatch */ + KEY_SHARE_ERROR = -503, /* key share mismatch */ + POST_HAND_AUTH_ERROR = -504, /* client won't do post-hand auth */ + HRR_COOKIE_ERROR = -505 /* HRR msg cookie mismatch */ + /* end negotiation parameter errors only 10 for now */ + /* add strings to wolfSSL_ERR_reason_error_string in internal.c !!!!! */ + + /* no error stings go down here, add above negotiation errors !!!! */ +}; + + +#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) + enum { + MIN_PARAM_ERR = UNSUPPORTED_SUITE, + MAX_PARAM_ERR = MIN_PARAM_ERR - 10 + }; +#endif + + +WOLFSSL_LOCAL +void SetErrorString(int err, char* buff); + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + + +#endif /* wolfSSL_ERROR_H */ diff --git a/beken_os/beken378/func/wolfssl/wolfssl/include.am b/beken_os/beken378/func/wolfssl/wolfssl/include.am new file mode 100755 index 0000000..201a96f --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/include.am @@ -0,0 +1,32 @@ +# vim:ft=automake +# All paths should be given relative to the root +# + +include wolfssl/wolfcrypt/include.am +include wolfssl/openssl/include.am + +EXTRA_DIST+= wolfssl/sniffer_error.rc + +nobase_include_HEADERS+= \ + wolfssl/error-ssl.h \ + wolfssl/ssl.h \ + wolfssl/sniffer_error.h \ + wolfssl/sniffer.h \ + wolfssl/callbacks.h \ + wolfssl/certs_test.h \ + wolfssl/test.h \ + wolfssl/version.h \ + wolfssl/ocsp.h \ + wolfssl/crl.h \ + wolfssl/wolfio.h + +noinst_HEADERS+= \ + wolfssl/internal.h + +# For distro build don't install options.h. +# It depends on the architecture and conflicts with Multi-Arch. +if BUILD_DISTRO +noinst_HEADERS+= wolfssl/options.h +else +nobase_include_HEADERS+= wolfssl/options.h +endif diff --git a/beken_os/beken378/func/wolfssl/wolfssl/internal.h b/beken_os/beken378/func/wolfssl/wolfssl/internal.h new file mode 100755 index 0000000..892de66 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/internal.h @@ -0,0 +1,4333 @@ +/* internal.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifndef WOLFSSL_INT_H +#define WOLFSSL_INT_H + + +#include +#include +#ifdef HAVE_CRL + #include +#endif +#include +#ifndef NO_DES3 + #include +#endif +#ifndef NO_HC128 + #include +#endif +#ifndef NO_RABBIT + #include +#endif +#ifdef HAVE_CHACHA + #include +#endif +#ifndef NO_ASN + #include + #include +#endif +#ifndef NO_MD5 + #include +#endif +#ifndef NO_SHA + #include +#endif +#ifndef NO_AES + #include +#endif +#ifdef HAVE_POLY1305 + #include +#endif +#ifdef HAVE_CAMELLIA + #include +#endif +#include +#ifndef NO_HMAC + #include +#endif +#ifndef NO_RC4 + #include +#endif +#ifndef NO_SHA256 + #include +#endif +#ifdef HAVE_OCSP + #include +#endif +#ifdef WOLFSSL_SHA384 + #include +#endif +#ifdef WOLFSSL_SHA512 + #include +#endif +#ifdef HAVE_AESGCM + #include +#endif +#ifdef WOLFSSL_RIPEMD + #include +#endif +#ifdef HAVE_IDEA + #include +#endif +#ifndef NO_RSA + #include +#endif +#ifdef HAVE_ECC + #include +#endif +#ifndef NO_DH + #include +#endif +#ifdef HAVE_ED25519 + #include +#endif +#ifdef HAVE_CURVE25519 + #include +#endif + +#include +#include + +#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) + #include +#endif +#ifdef WOLFSSL_CALLBACKS + #include +#endif + +#ifdef USE_WINDOWS_API + #ifdef WOLFSSL_GAME_BUILD + #include "system/xtl.h" + #else + #if defined(_WIN32_WCE) || defined(WIN32_LEAN_AND_MEAN) + /* On WinCE winsock2.h must be included before windows.h */ + #include + #endif + #include + #endif +#elif defined(THREADX) + #ifndef SINGLE_THREADED + #include "tx_api.h" + #endif + +#elif defined(WOLFSSL_DEOS) + /* do nothing, just don't pick Unix */ +#elif defined(MICRIUM) + /* do nothing, just don't pick Unix */ +#elif defined(FREERTOS) || defined(FREERTOS_TCP) || defined(WOLFSSL_SAFERTOS) + /* do nothing */ +#elif defined(EBSNET) + /* do nothing */ +#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) + /* do nothing */ +#elif defined(FREESCALE_FREE_RTOS) + #include "fsl_os_abstraction.h" +#elif defined(WOLFSSL_uITRON4) + /* do nothing */ +#elif defined(WOLFSSL_uTKERNEL2) + /* do nothing */ +#elif defined(WOLFSSL_CMSIS_RTOS) + #include "cmsis_os.h" +#elif defined(WOLFSSL_CMSIS_RTOSv2) + #include "cmsis_os2.h" +#elif defined(WOLFSSL_MDK_ARM) + #if defined(WOLFSSL_MDK5) + #include "cmsis_os.h" + #else + #include + #endif +#elif defined(MBED) +#elif defined(WOLFSSL_TIRTOS) + /* do nothing */ +#elif defined(INTIME_RTOS) + #include +#elif defined(WOLFSSL_NUCLEUS_1_2) + /* do nothing */ +#elif defined(WOLFSSL_APACHE_MYNEWT) + #if !defined(WOLFSSL_LWIP) + void mynewt_ctx_clear(void *ctx); + void* mynewt_ctx_new(); + #endif +#elif defined(WOLFSSL_ZEPHYR) + #ifndef SINGLE_THREADED + #include + #endif +#elif defined(WOLFSSL_TELIT_M2MB) + /* do nothing */ +#else + #ifndef SINGLE_THREADED + #define WOLFSSL_PTHREADS + #include + #endif + #ifdef OPENSSL_EXTRA + #include /* for close of BIO */ + #endif +#endif + +#ifndef CHAR_BIT + /* Needed for DTLS without big math */ + #include +#endif + + +#ifdef HAVE_LIBZ + #include "zlib.h" +#endif + +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif + +#ifdef OPENSSL_EXTRA + #ifdef WOLFCRYPT_HAVE_SRP + #include + #endif +#endif + +#ifdef _MSC_VER + /* 4996 warning to use MS extensions e.g., strcpy_s instead of strncpy */ + #pragma warning(disable: 4996) +#endif + +#ifdef NO_SHA + #define WC_SHA_DIGEST_SIZE 20 +#endif + +#ifdef NO_SHA256 + #define WC_SHA256_DIGEST_SIZE 32 +#endif + +#ifdef NO_MD5 + #define WC_MD5_DIGEST_SIZE 16 +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + +/* Define or comment out the cipher suites you'd like to be compiled in + make sure to use at least one BUILD_SSL_xxx or BUILD_TLS_xxx is defined + + When adding cipher suites, add name to cipher_names, idx to cipher_name_idx + + Now that there is a maximum strength crypto build, the following BUILD_XXX + flags need to be divided into two groups selected by WOLFSSL_MAX_STRENGTH. + Those that do not use Perfect Forward Security and do not use AEAD ciphers + need to be switched off. Allowed suites use (EC)DHE, AES-GCM|CCM, or + CHACHA-POLY. +*/ + +/* Check that if WOLFSSL_MAX_STRENGTH is set that all the required options are + * not turned off. */ +#if defined(WOLFSSL_MAX_STRENGTH) && \ + ((!defined(HAVE_ECC) && (defined(NO_DH) || defined(NO_RSA))) || \ + (!defined(HAVE_AESGCM) && !defined(HAVE_AESCCM) && \ + (!defined(HAVE_POLY1305) || !defined(HAVE_CHACHA))) || \ + (defined(NO_SHA256) && !defined(WOLFSSL_SHA384)) || \ + !defined(NO_OLD_TLS)) + + #error "You are trying to build max strength with requirements disabled." +#endif + +/* Have QSH : Quantum-safe Handshake */ +#if defined(HAVE_QSH) + #define BUILD_TLS_QSH +#endif + +#ifndef WOLFSSL_MAX_STRENGTH + +#ifdef WOLFSSL_AEAD_ONLY + /* AES CBC ciphers are not allowed in AEAD only mode */ + #undef HAVE_AES_CBC +#endif + +#ifndef WOLFSSL_AEAD_ONLY + #if !defined(NO_RSA) && !defined(NO_RC4) + #if defined(WOLFSSL_STATIC_RSA) + #if !defined(NO_SHA) + #define BUILD_SSL_RSA_WITH_RC4_128_SHA + #endif + #if !defined(NO_MD5) + #define BUILD_SSL_RSA_WITH_RC4_128_MD5 + #endif + #endif + #if !defined(NO_TLS) && defined(HAVE_NTRU) && !defined(NO_SHA) \ + && defined(WOLFSSL_STATIC_RSA) + #define BUILD_TLS_NTRU_RSA_WITH_RC4_128_SHA + #endif + #endif + + #if !defined(NO_RSA) && !defined(NO_DES3) + #if !defined(NO_SHA) + #if defined(WOLFSSL_STATIC_RSA) + #define BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA + #endif + #if !defined(NO_TLS) && defined(HAVE_NTRU) \ + && defined(WOLFSSL_STATIC_RSA) + #define BUILD_TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA + #endif + #endif + #endif + + #if !defined(NO_RSA) && defined(HAVE_IDEA) + #if !defined(NO_SHA) && defined(WOLFSSL_STATIC_RSA) + #define BUILD_SSL_RSA_WITH_IDEA_CBC_SHA + #endif + #endif +#endif /* !WOLFSSL_AEAD_ONLY */ + + #if !defined(NO_RSA) && !defined(NO_AES) && !defined(NO_TLS) + #if !defined(NO_SHA) && defined(HAVE_AES_CBC) + #if defined(WOLFSSL_STATIC_RSA) + #ifdef WOLFSSL_AES_128 + #define BUILD_TLS_RSA_WITH_AES_128_CBC_SHA + #endif + #ifdef WOLFSSL_AES_256 + #define BUILD_TLS_RSA_WITH_AES_256_CBC_SHA + #endif + #endif + #if defined(HAVE_NTRU) && defined(WOLFSSL_STATIC_RSA) + #ifdef WOLFSSL_AES_128 + #define BUILD_TLS_NTRU_RSA_WITH_AES_128_CBC_SHA + #endif + #ifdef WOLFSSL_AES_256 + #define BUILD_TLS_NTRU_RSA_WITH_AES_256_CBC_SHA + #endif + #endif + #endif + #if defined(WOLFSSL_STATIC_RSA) + #if !defined (NO_SHA256) && defined(HAVE_AES_CBC) + #ifdef WOLFSSL_AES_128 + #define BUILD_TLS_RSA_WITH_AES_128_CBC_SHA256 + #endif + #ifdef WOLFSSL_AES_256 + #define BUILD_TLS_RSA_WITH_AES_256_CBC_SHA256 + #endif + #endif + #if defined (HAVE_AESGCM) + #ifdef WOLFSSL_AES_128 + #define BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256 + #endif + #if defined (WOLFSSL_SHA384) && defined(WOLFSSL_AES_256) + #define BUILD_TLS_RSA_WITH_AES_256_GCM_SHA384 + #endif + #endif + #if defined (HAVE_AESCCM) + #ifdef WOLFSSL_AES_128 + #define BUILD_TLS_RSA_WITH_AES_128_CCM_8 + #endif + #ifdef WOLFSSL_AES_256 + #define BUILD_TLS_RSA_WITH_AES_256_CCM_8 + #endif + #endif + #if defined(HAVE_BLAKE2) && defined(HAVE_AES_CBC) + #ifdef WOLFSSL_AES_128 + #define BUILD_TLS_RSA_WITH_AES_128_CBC_B2B256 + #endif + #ifdef WOLFSSL_AES_256 + #define BUILD_TLS_RSA_WITH_AES_256_CBC_B2B256 + #endif + #endif + #endif + #endif + + #if defined(HAVE_CAMELLIA) && !defined(NO_TLS) && !defined(NO_CAMELLIA_CBC) + #ifndef NO_RSA + #if defined(WOLFSSL_STATIC_RSA) + #if !defined(NO_SHA) + #define BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + #define BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA + #endif + #ifndef NO_SHA256 + #define BUILD_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 + #define BUILD_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 + #endif + #endif + #if !defined(NO_DH) + #if !defined(NO_SHA) + #define BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + #define BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + #endif + #ifndef NO_SHA256 + #define BUILD_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + #define BUILD_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + #endif + #endif + #endif + #endif + +#if defined(WOLFSSL_STATIC_PSK) + #if !defined(NO_PSK) && !defined(NO_AES) && !defined(NO_TLS) + #if !defined(NO_SHA) + #ifdef WOLFSSL_AES_128 + #define BUILD_TLS_PSK_WITH_AES_128_CBC_SHA + #endif + #ifdef WOLFSSL_AES_256 + #define BUILD_TLS_PSK_WITH_AES_256_CBC_SHA + #endif + #endif + #ifndef NO_SHA256 + #ifdef WOLFSSL_AES_128 + #ifdef HAVE_AES_CBC + #define BUILD_TLS_PSK_WITH_AES_128_CBC_SHA256 + #endif + #ifdef HAVE_AESGCM + #define BUILD_TLS_PSK_WITH_AES_128_GCM_SHA256 + #endif + #endif /* WOLFSSL_AES_128 */ + #ifdef HAVE_AESCCM + #ifdef WOLFSSL_AES_128 + #define BUILD_TLS_PSK_WITH_AES_128_CCM_8 + #define BUILD_TLS_PSK_WITH_AES_128_CCM + #endif + #ifdef WOLFSSL_AES_256 + #define BUILD_TLS_PSK_WITH_AES_256_CCM_8 + #define BUILD_TLS_PSK_WITH_AES_256_CCM + #endif + #endif + #endif + #if defined(WOLFSSL_SHA384) && defined(WOLFSSL_AES_256) + #ifdef HAVE_AES_CBC + #define BUILD_TLS_PSK_WITH_AES_256_CBC_SHA384 + #endif + #ifdef HAVE_AESGCM + #define BUILD_TLS_PSK_WITH_AES_256_GCM_SHA384 + #endif + #endif + #endif +#endif + + #if !defined(NO_TLS) && defined(HAVE_NULL_CIPHER) + #if !defined(NO_RSA) + #if defined(WOLFSSL_STATIC_RSA) + #ifndef NO_MD5 + #define BUILD_TLS_RSA_WITH_NULL_MD5 + #endif + #if !defined(NO_SHA) + #define BUILD_TLS_RSA_WITH_NULL_SHA + #endif + #ifndef NO_SHA256 + #define BUILD_TLS_RSA_WITH_NULL_SHA256 + #endif + #endif + #endif + #if !defined(NO_PSK) && defined(WOLFSSL_STATIC_PSK) + #if !defined(NO_SHA) + #define BUILD_TLS_PSK_WITH_NULL_SHA + #endif + #ifndef NO_SHA256 + #define BUILD_TLS_PSK_WITH_NULL_SHA256 + #endif + #ifdef WOLFSSL_SHA384 + #define BUILD_TLS_PSK_WITH_NULL_SHA384 + #endif + #endif + #endif + +#if defined(WOLFSSL_STATIC_RSA) + #if !defined(NO_HC128) && !defined(NO_RSA) && !defined(NO_TLS) + #ifndef NO_MD5 + #define BUILD_TLS_RSA_WITH_HC_128_MD5 + #endif + #if !defined(NO_SHA) + #define BUILD_TLS_RSA_WITH_HC_128_SHA + #endif + #if defined(HAVE_BLAKE2) + #define BUILD_TLS_RSA_WITH_HC_128_B2B256 + #endif + #endif + + #if !defined(NO_RABBIT) && !defined(NO_TLS) && !defined(NO_RSA) + #if !defined(NO_SHA) + #define BUILD_TLS_RSA_WITH_RABBIT_SHA + #endif + #endif +#endif + + #if !defined(NO_DH) && !defined(NO_AES) && !defined(NO_TLS) && \ + !defined(NO_RSA) + + #if !defined(NO_SHA) + #if defined(WOLFSSL_AES_128) && defined(HAVE_AES_CBC) + #define BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA + #endif + #if defined(WOLFSSL_AES_256) && defined(HAVE_AES_CBC) + #define BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA + #endif + #if !defined(NO_DES3) + #define BUILD_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + #endif + #endif + #if !defined(NO_SHA256) && defined(HAVE_AES_CBC) + #ifdef WOLFSSL_AES_128 + #define BUILD_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + #endif + #ifdef WOLFSSL_AES_256 + #define BUILD_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + #endif + #endif + #endif + + #if defined(HAVE_ANON) && !defined(NO_TLS) && !defined(NO_DH) && \ + !defined(NO_AES) && !defined(NO_SHA) && defined(WOLFSSL_AES_128) + #ifdef HAVE_AES_CBC + #define BUILD_TLS_DH_anon_WITH_AES_128_CBC_SHA + #endif + + #if defined(WOLFSSL_SHA384) && defined(HAVE_AESGCM) + #define BUILD_TLS_DH_anon_WITH_AES_256_GCM_SHA384 + #endif + #endif + + #if !defined(NO_DH) && !defined(NO_PSK) && !defined(NO_TLS) + #ifndef NO_SHA256 + #if !defined(NO_AES) && defined(WOLFSSL_AES_128) && \ + defined(HAVE_AES_CBC) + #define BUILD_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + #endif + #ifdef HAVE_NULL_CIPHER + #define BUILD_TLS_DHE_PSK_WITH_NULL_SHA256 + #endif + #endif + #ifdef WOLFSSL_SHA384 + #if !defined(NO_AES) && defined(WOLFSSL_AES_256) && \ + defined(HAVE_AES_CBC) + #define BUILD_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + #endif + #ifdef HAVE_NULL_CIPHER + #define BUILD_TLS_DHE_PSK_WITH_NULL_SHA384 + #endif + #endif + #endif + + #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && !defined(NO_TLS) + #if !defined(NO_AES) + #if !defined(NO_SHA) && defined(HAVE_AES_CBC) + #if !defined(NO_RSA) + #ifdef WOLFSSL_AES_128 + #define BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + #endif + #ifdef WOLFSSL_AES_256 + #define BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + #endif + #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC) + #ifdef WOLFSSL_AES_128 + #define BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + #endif + #ifdef WOLFSSL_AES_256 + #define BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + #endif + #endif + #endif + + #if defined(HAVE_ECC) || (defined(HAVE_CURVE25519) && \ + defined(HAVE_ED25519)) + #ifdef WOLFSSL_AES_128 + #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + #endif + #ifdef WOLFSSL_AES_256 + #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + #endif + #endif + + #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC) + #ifdef WOLFSSL_AES_128 + #define BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + #endif + #ifdef WOLFSSL_AES_256 + #define BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + #endif + #endif + #endif /* NO_SHA */ + #if !defined(NO_SHA256) && defined(WOLFSSL_AES_128) && \ + defined(HAVE_AES_CBC) + #if !defined(NO_RSA) + #define BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC) + #define BUILD_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + #endif + #endif + #if defined(HAVE_ECC) || (defined(HAVE_CURVE25519) && \ + defined(HAVE_ED25519)) + #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + #endif + #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC) + #define BUILD_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 + #endif + #endif + + #if defined(WOLFSSL_SHA384) && defined(WOLFSSL_AES_256) && \ + defined(HAVE_AES_CBC) + #if !defined(NO_RSA) + #define BUILD_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC) + #define BUILD_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + #endif + #endif + #if defined(HAVE_ECC) || (defined(HAVE_CURVE25519) && \ + defined(HAVE_ED25519)) + #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + #endif + #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC) + #define BUILD_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 + #endif + #endif + + #if defined (HAVE_AESGCM) + #if !defined(NO_RSA) + #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC) + #ifdef WOLFSSL_AES_128 + #define BUILD_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + #endif + #endif + #if defined(WOLFSSL_SHA384) + #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC) + #ifdef WOLFSSL_AES_256 + #define BUILD_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + #endif + #endif + #endif + #endif + + #if defined(WOLFSSL_STATIC_DH) && defined(WOLFSSL_AES_128) && \ + defined(HAVE_ECC) + #define BUILD_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + #endif + + #if defined(WOLFSSL_SHA384) + #if defined(WOLFSSL_STATIC_DH) && \ + defined(WOLFSSL_AES_256) && defined(HAVE_ECC) + #define BUILD_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + #endif + #endif + #endif + #endif /* NO_AES */ + #if !defined(NO_RC4) + #if !defined(NO_SHA) + #if !defined(NO_RSA) + #define BUILD_TLS_ECDHE_RSA_WITH_RC4_128_SHA + #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC) + #define BUILD_TLS_ECDH_RSA_WITH_RC4_128_SHA + #endif + #endif + + #if defined(HAVE_ECC) || (defined(HAVE_CURVE25519) && \ + defined(HAVE_ED25519)) + #define BUILD_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA + #endif + #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC) + #define BUILD_TLS_ECDH_ECDSA_WITH_RC4_128_SHA + #endif + #endif + #endif + #if !defined(NO_DES3) + #ifndef NO_SHA + #if !defined(NO_RSA) + #define BUILD_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC) + #define BUILD_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA + #endif + #endif + + #if defined(HAVE_ECC) || (defined(HAVE_CURVE25519) && \ + defined(HAVE_ED25519)) + #define BUILD_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA + #endif + #if defined(WOLFSSL_STATIC_DH) && defined(HAVE_ECC) + #define BUILD_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA + #endif + #endif /* NO_SHA */ + #endif + #if defined(HAVE_NULL_CIPHER) + #if !defined(NO_SHA) + #if defined(HAVE_ECC) || (defined(HAVE_CURVE25519) && \ + defined(HAVE_ED25519)) + #define BUILD_TLS_ECDHE_ECDSA_WITH_NULL_SHA + #endif + #endif + #if !defined(NO_PSK) && !defined(NO_SHA256) + #define BUILD_TLS_ECDHE_PSK_WITH_NULL_SHA256 + #endif + #endif + #if !defined(NO_PSK) && !defined(NO_SHA256) && !defined(NO_AES) && \ + defined(WOLFSSL_AES_128) && defined(HAVE_AES_CBC) + #define BUILD_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + #endif + #endif + #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) && !defined(NO_SHA256) + #if !defined(NO_OLD_POLY1305) + #if defined(HAVE_ECC) || (defined(HAVE_CURVE25519) && \ + defined(HAVE_ED25519)) + #define BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256 + #endif + #if !defined(NO_RSA) && defined(HAVE_ECC) + #define BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 + #endif + #if !defined(NO_DH) && !defined(NO_RSA) + #define BUILD_TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 + #endif + #endif /* NO_OLD_POLY1305 */ + #if !defined(NO_PSK) + #define BUILD_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 + #if defined(HAVE_ECC) || defined(HAVE_ED25519) + #define BUILD_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 + #endif + #ifndef NO_DH + #define BUILD_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 + #endif + #endif /* !NO_PSK */ + #endif + +#endif /* !WOLFSSL_MAX_STRENGTH */ + +#if !defined(NO_DH) && !defined(NO_AES) && !defined(NO_TLS) && \ + !defined(NO_RSA) && defined(HAVE_AESGCM) + + #if !defined(NO_SHA256) && defined(WOLFSSL_AES_128) + #define BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + #endif + + #if defined(WOLFSSL_SHA384) && defined(WOLFSSL_AES_256) + #define BUILD_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + #endif +#endif + +#if !defined(NO_DH) && !defined(NO_PSK) && !defined(NO_TLS) + #ifndef NO_SHA256 + #if defined(HAVE_AESGCM) && defined(WOLFSSL_AES_128) + #define BUILD_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + #endif + #ifdef HAVE_AESCCM + #ifdef WOLFSSL_AES_128 + #define BUILD_TLS_DHE_PSK_WITH_AES_128_CCM + #endif + #ifdef WOLFSSL_AES_256 + #define BUILD_TLS_DHE_PSK_WITH_AES_256_CCM + #endif + #endif + #endif + #if defined(WOLFSSL_SHA384) && defined(HAVE_AESGCM) && \ + defined(WOLFSSL_AES_256) + #define BUILD_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 + #endif +#endif + +#if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && !defined(NO_TLS) && \ + !defined(NO_AES) + #ifdef HAVE_AESGCM + #if !defined(NO_SHA256) && defined(WOLFSSL_AES_128) + #if defined(HAVE_ECC) || (defined(HAVE_CURVE25519) && \ + defined(HAVE_ED25519)) + #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + #endif + #ifndef NO_RSA + #define BUILD_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + #endif + #endif + #if defined(WOLFSSL_SHA384) && defined(WOLFSSL_AES_256) + #if defined(HAVE_ECC) || (defined(HAVE_CURVE25519) && \ + defined(HAVE_ED25519)) + #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + #endif + #ifndef NO_RSA + #define BUILD_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + #endif + #endif + #endif + #if defined(HAVE_AESCCM) && !defined(NO_SHA256) + #if defined(HAVE_ECC) || (defined(HAVE_CURVE25519) && \ + defined(HAVE_ED25519)) + #ifdef WOLFSSL_AES_128 + #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM + #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 + #endif + #ifdef WOLFSSL_AES_256 + #define BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 + #endif + #endif + #endif +#endif + +#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) && !defined(NO_SHA256) + #if defined(HAVE_ECC) || defined(HAVE_CURVE25519) + #if defined(HAVE_ECC) || (defined(HAVE_CURVE25519) && \ + defined(HAVE_ED25519)) + #define BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 + #endif + #ifndef NO_RSA + #define BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 + #endif + #endif + #if !defined(NO_DH) && !defined(NO_RSA) + #define BUILD_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 + #endif +#endif + +#if defined(WOLFSSL_TLS13) + #ifdef HAVE_AESGCM + #if !defined(NO_SHA256) && defined(WOLFSSL_AES_128) + #define BUILD_TLS_AES_128_GCM_SHA256 + #endif + #if defined(WOLFSSL_SHA384) && defined(WOLFSSL_AES_256) + #define BUILD_TLS_AES_256_GCM_SHA384 + #endif + #endif + + #if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) + #ifndef NO_SHA256 + #define BUILD_TLS_CHACHA20_POLY1305_SHA256 + #endif + #endif + + #ifdef HAVE_AESCCM + #if !defined(NO_SHA256) && defined(WOLFSSL_AES_128) + #define BUILD_TLS_AES_128_CCM_SHA256 + #define BUILD_TLS_AES_128_CCM_8_SHA256 + #endif + #endif +#endif + +#ifdef WOLFSSL_MULTICAST + #if defined(HAVE_NULL_CIPHER) && !defined(NO_SHA256) + #define BUILD_WDM_WITH_NULL_SHA256 + #endif +#endif + +#if defined(BUILD_SSL_RSA_WITH_RC4_128_SHA) || \ + defined(BUILD_SSL_RSA_WITH_RC4_128_MD5) + #define BUILD_ARC4 +#endif + +#if defined(BUILD_SSL_RSA_WITH_3DES_EDE_CBC_SHA) + #define BUILD_DES3 +#endif + +#if defined(BUILD_TLS_RSA_WITH_AES_128_CBC_SHA) || \ + defined(BUILD_TLS_RSA_WITH_AES_256_CBC_SHA) || \ + defined(BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256) || \ + defined(BUILD_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256) + #undef BUILD_AES + #define BUILD_AES +#endif + +#if defined(BUILD_TLS_RSA_WITH_AES_128_GCM_SHA256) || \ + defined(BUILD_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256) || \ + defined(BUILD_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256) || \ + defined(BUILD_TLS_PSK_WITH_AES_128_GCM_SHA256) || \ + defined(BUILD_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256) || \ + defined(BUILD_TLS_RSA_WITH_AES_256_GCM_SHA384) || \ + defined(BUILD_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384) || \ + defined(BUILD_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384) || \ + defined(BUILD_TLS_PSK_WITH_AES_256_GCM_SHA384) || \ + defined(BUILD_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384) + #define BUILD_AESGCM +#else + /* No AES-GCM cipher suites available with build */ + #define NO_AESGCM_AEAD +#endif + +#if defined(BUILD_TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256) || \ + defined(BUILD_TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256) || \ + defined(BUILD_TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256) || \ + defined(BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256) || \ + defined(BUILD_TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256) || \ + defined(BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256) || \ + defined(BUILD_TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256) || \ + defined(BUILD_TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256) || \ + defined(BUILD_TLS_PSK_WITH_CHACHA20_POLY1305_SHA256) || \ + defined(BUILD_TLS_CHACHA20_POLY1305_SHA256) + /* Have an available ChaCha Poly cipher suite */ +#else + /* No ChaCha Poly cipher suites available with build */ + #define NO_CHAPOL_AEAD +#endif + +#if defined(BUILD_TLS_RSA_WITH_HC_128_SHA) || \ + defined(BUILD_TLS_RSA_WITH_HC_128_MD5) || \ + defined(BUILD_TLS_RSA_WITH_HC_128_B2B256) + #define BUILD_HC128 +#endif + +#if defined(BUILD_TLS_RSA_WITH_RABBIT_SHA) + #define BUILD_RABBIT +#endif + +#ifdef NO_DES3 + #define DES_BLOCK_SIZE 8 +#else + #undef BUILD_DES3 + #define BUILD_DES3 +#endif + +#if defined(NO_AES) || defined(NO_AES_DECRYPT) + #define AES_BLOCK_SIZE 16 + #undef BUILD_AES +#else + #undef BUILD_AES + #define BUILD_AES +#endif + +#ifndef NO_RC4 + #undef BUILD_ARC4 + #define BUILD_ARC4 +#endif + +#ifdef HAVE_CHACHA + #define CHACHA20_BLOCK_SIZE 16 +#endif + +#if defined(WOLFSSL_MAX_STRENGTH) || \ + (defined(HAVE_AESGCM) && !defined(NO_AESGCM_AEAD)) || \ + defined(HAVE_AESCCM) || \ + (defined(HAVE_CHACHA) && defined(HAVE_POLY1305) && !defined(NO_CHAPOL_AEAD)) + + #define HAVE_AEAD +#endif + +#if defined(WOLFSSL_MAX_STRENGTH) || \ + defined(HAVE_ECC) || !defined(NO_DH) + + #define HAVE_PFS +#endif + +#if defined(BUILD_SSL_RSA_WITH_IDEA_CBC_SHA) + #define BUILD_IDEA +#endif + +/* actual cipher values, 2nd byte */ +enum { + TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA = 0x16, + TLS_DHE_RSA_WITH_AES_256_CBC_SHA = 0x39, + TLS_DHE_RSA_WITH_AES_128_CBC_SHA = 0x33, + TLS_DH_anon_WITH_AES_128_CBC_SHA = 0x34, + TLS_RSA_WITH_AES_256_CBC_SHA = 0x35, + TLS_RSA_WITH_AES_128_CBC_SHA = 0x2F, + TLS_RSA_WITH_NULL_MD5 = 0x01, + TLS_RSA_WITH_NULL_SHA = 0x02, + TLS_PSK_WITH_AES_256_CBC_SHA = 0x8d, + TLS_PSK_WITH_AES_128_CBC_SHA256 = 0xae, + TLS_PSK_WITH_AES_256_CBC_SHA384 = 0xaf, + TLS_PSK_WITH_AES_128_CBC_SHA = 0x8c, + TLS_PSK_WITH_NULL_SHA256 = 0xb0, + TLS_PSK_WITH_NULL_SHA384 = 0xb1, + TLS_PSK_WITH_NULL_SHA = 0x2c, + SSL_RSA_WITH_RC4_128_SHA = 0x05, + SSL_RSA_WITH_RC4_128_MD5 = 0x04, + SSL_RSA_WITH_3DES_EDE_CBC_SHA = 0x0A, + SSL_RSA_WITH_IDEA_CBC_SHA = 0x07, + + /* ECC suites, first byte is 0xC0 (ECC_BYTE) */ + TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA = 0x14, + TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA = 0x13, + TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA = 0x0A, + TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA = 0x09, + TLS_ECDHE_RSA_WITH_RC4_128_SHA = 0x11, + TLS_ECDHE_ECDSA_WITH_RC4_128_SHA = 0x07, + TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA = 0x12, + TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA = 0x08, + TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 = 0x27, + TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 = 0x23, + TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 = 0x28, + TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 = 0x24, + TLS_ECDHE_ECDSA_WITH_NULL_SHA = 0x06, + TLS_ECDHE_PSK_WITH_NULL_SHA256 = 0x3a, + TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 = 0x37, + + /* static ECDH, first byte is 0xC0 (ECC_BYTE) */ + TLS_ECDH_RSA_WITH_AES_256_CBC_SHA = 0x0F, + TLS_ECDH_RSA_WITH_AES_128_CBC_SHA = 0x0E, + TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA = 0x05, + TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA = 0x04, + TLS_ECDH_RSA_WITH_RC4_128_SHA = 0x0C, + TLS_ECDH_ECDSA_WITH_RC4_128_SHA = 0x02, + TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA = 0x0D, + TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA = 0x03, + TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 = 0x29, + TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 = 0x25, + TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 = 0x2A, + TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 = 0x26, + + /* wolfSSL extension - eSTREAM */ + TLS_RSA_WITH_HC_128_MD5 = 0xFB, + TLS_RSA_WITH_HC_128_SHA = 0xFC, + TLS_RSA_WITH_RABBIT_SHA = 0xFD, + WDM_WITH_NULL_SHA256 = 0xFE, /* wolfSSL DTLS Multicast */ + + /* wolfSSL extension - Blake2b 256 */ + TLS_RSA_WITH_AES_128_CBC_B2B256 = 0xF8, + TLS_RSA_WITH_AES_256_CBC_B2B256 = 0xF9, + TLS_RSA_WITH_HC_128_B2B256 = 0xFA, /* eSTREAM too */ + + /* wolfSSL extension - NTRU */ + TLS_NTRU_RSA_WITH_RC4_128_SHA = 0xe5, + TLS_NTRU_RSA_WITH_3DES_EDE_CBC_SHA = 0xe6, + TLS_NTRU_RSA_WITH_AES_128_CBC_SHA = 0xe7, /* clashes w/official SHA-256 */ + TLS_NTRU_RSA_WITH_AES_256_CBC_SHA = 0xe8, + + /* wolfSSL extension - NTRU , Quantum-safe Handshake + first byte is 0xD0 (QSH_BYTE) */ + TLS_QSH = 0x01, + + /* SHA256 */ + TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 = 0x6b, + TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 = 0x67, + TLS_RSA_WITH_AES_256_CBC_SHA256 = 0x3d, + TLS_RSA_WITH_AES_128_CBC_SHA256 = 0x3c, + TLS_RSA_WITH_NULL_SHA256 = 0x3b, + TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 = 0xb2, + TLS_DHE_PSK_WITH_NULL_SHA256 = 0xb4, + + /* SHA384 */ + TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 = 0xb3, + TLS_DHE_PSK_WITH_NULL_SHA384 = 0xb5, + + /* AES-GCM */ + TLS_RSA_WITH_AES_128_GCM_SHA256 = 0x9c, + TLS_RSA_WITH_AES_256_GCM_SHA384 = 0x9d, + TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 = 0x9e, + TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 = 0x9f, + TLS_DH_anon_WITH_AES_256_GCM_SHA384 = 0xa7, + TLS_PSK_WITH_AES_128_GCM_SHA256 = 0xa8, + TLS_PSK_WITH_AES_256_GCM_SHA384 = 0xa9, + TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 = 0xaa, + TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 = 0xab, + + /* ECC AES-GCM, first byte is 0xC0 (ECC_BYTE) */ + TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 = 0x2b, + TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 = 0x2c, + TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 = 0x2d, + TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 = 0x2e, + TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 = 0x2f, + TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 = 0x30, + TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 = 0x31, + TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 = 0x32, + + /* AES-CCM, first byte is 0xC0 but isn't ECC, + * also, in some of the other AES-CCM suites + * there will be second byte number conflicts + * with non-ECC AES-GCM */ + TLS_RSA_WITH_AES_128_CCM_8 = 0xa0, + TLS_RSA_WITH_AES_256_CCM_8 = 0xa1, + TLS_ECDHE_ECDSA_WITH_AES_128_CCM = 0xac, + TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8 = 0xae, + TLS_ECDHE_ECDSA_WITH_AES_256_CCM_8 = 0xaf, + TLS_PSK_WITH_AES_128_CCM = 0xa4, + TLS_PSK_WITH_AES_256_CCM = 0xa5, + TLS_PSK_WITH_AES_128_CCM_8 = 0xa8, + TLS_PSK_WITH_AES_256_CCM_8 = 0xa9, + TLS_DHE_PSK_WITH_AES_128_CCM = 0xa6, + TLS_DHE_PSK_WITH_AES_256_CCM = 0xa7, + + /* Camellia */ + TLS_RSA_WITH_CAMELLIA_128_CBC_SHA = 0x41, + TLS_RSA_WITH_CAMELLIA_256_CBC_SHA = 0x84, + TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 0xba, + TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 = 0xc0, + TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA = 0x45, + TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA = 0x88, + TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 = 0xbe, + TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 = 0xc4, + + /* chacha20-poly1305 suites first byte is 0xCC (CHACHA_BYTE) */ + TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0xa8, + TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 = 0xa9, + TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256 = 0xaa, + TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256 = 0xac, + TLS_PSK_WITH_CHACHA20_POLY1305_SHA256 = 0xab, + TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256 = 0xad, + + /* chacha20-poly1305 earlier version of nonce and padding (CHACHA_BYTE) */ + TLS_ECDHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 = 0x13, + TLS_ECDHE_ECDSA_WITH_CHACHA20_OLD_POLY1305_SHA256 = 0x14, + TLS_DHE_RSA_WITH_CHACHA20_OLD_POLY1305_SHA256 = 0x15, + + /* TLS v1.3 cipher suites */ + TLS_AES_128_GCM_SHA256 = 0x01, + TLS_AES_256_GCM_SHA384 = 0x02, + TLS_CHACHA20_POLY1305_SHA256 = 0x03, + TLS_AES_128_CCM_SHA256 = 0x04, + TLS_AES_128_CCM_8_SHA256 = 0x05, + + /* Fallback SCSV (Signaling Cipher Suite Value) */ + TLS_FALLBACK_SCSV = 0x56, + /* Renegotiation Indication Extension Special Suite */ + TLS_EMPTY_RENEGOTIATION_INFO_SCSV = 0xff +}; + + +#ifndef WOLFSSL_SESSION_TIMEOUT + #define WOLFSSL_SESSION_TIMEOUT 500 + /* default session resumption cache timeout in seconds */ +#endif + + +#ifndef WOLFSSL_DTLS_WINDOW_WORDS + #define WOLFSSL_DTLS_WINDOW_WORDS 2 +#endif /* WOLFSSL_DTLS_WINDOW_WORDS */ +#define DTLS_WORD_BITS (sizeof(word32) * CHAR_BIT) +#define DTLS_SEQ_BITS (WOLFSSL_DTLS_WINDOW_WORDS * DTLS_WORD_BITS) +#define DTLS_SEQ_SZ (sizeof(word32) * WOLFSSL_DTLS_WINDOW_WORDS) + +#ifndef WOLFSSL_MULTICAST + #define WOLFSSL_DTLS_PEERSEQ_SZ 1 +#else + #ifndef WOLFSSL_MULTICAST_PEERS + /* max allowed multicast group peers */ + #define WOLFSSL_MULTICAST_PEERS 100 + #endif + #define WOLFSSL_DTLS_PEERSEQ_SZ WOLFSSL_MULTICAST_PEERS +#endif /* WOLFSSL_MULTICAST */ + +#ifndef WOLFSSL_MAX_MTU + #define WOLFSSL_MAX_MTU 1500 +#endif /* WOLFSSL_MAX_MTU */ + + +/* set minimum DH key size allowed */ +#ifndef WOLFSSL_MIN_DHKEY_BITS + #ifdef WOLFSSL_MAX_STRENGTH + #define WOLFSSL_MIN_DHKEY_BITS 2048 + #else + #define WOLFSSL_MIN_DHKEY_BITS 1024 + #endif +#endif +#if (WOLFSSL_MIN_DHKEY_BITS % 8) + #error DH minimum bit size must be multiple of 8 +#endif +#if (WOLFSSL_MIN_DHKEY_BITS > 16000) + #error DH minimum bit size must not be greater than 16000 +#endif +#define MIN_DHKEY_SZ (WOLFSSL_MIN_DHKEY_BITS / 8) +/* set maximum DH key size allowed */ +#ifndef WOLFSSL_MAX_DHKEY_BITS + #if (defined(USE_FAST_MATH) && defined(FP_MAX_BITS) && FP_MAX_BITS >= 16384) + #define WOLFSSL_MAX_DHKEY_BITS 8192 + #else + #define WOLFSSL_MAX_DHKEY_BITS 4096 + #endif +#endif +#if (WOLFSSL_MAX_DHKEY_BITS % 8) + #error DH maximum bit size must be multiple of 8 +#endif +#if (WOLFSSL_MAX_DHKEY_BITS > 16000) + #error DH maximum bit size must not be greater than 16000 +#endif +#define MAX_DHKEY_SZ (WOLFSSL_MAX_DHKEY_BITS / 8) + + + +enum Misc { + CIPHER_BYTE = 0x00, /* Default ciphers */ + ECC_BYTE = 0xC0, /* ECC first cipher suite byte */ + QSH_BYTE = 0xD0, /* Quantum-safe Handshake cipher suite */ + CHACHA_BYTE = 0xCC, /* ChaCha first cipher suite */ + TLS13_BYTE = 0x13, /* TLS v1.3 first byte of cipher suite */ + + SEND_CERT = 1, + SEND_BLANK_CERT = 2, + + DTLS_MAJOR = 0xfe, /* DTLS major version number */ + DTLS_MINOR = 0xff, /* DTLS minor version number */ + DTLSv1_2_MINOR = 0xfd, /* DTLS minor version number */ + SSLv3_MAJOR = 3, /* SSLv3 and TLSv1+ major version number */ + SSLv3_MINOR = 0, /* TLSv1 minor version number */ + TLSv1_MINOR = 1, /* TLSv1 minor version number */ + TLSv1_1_MINOR = 2, /* TLSv1_1 minor version number */ + TLSv1_2_MINOR = 3, /* TLSv1_2 minor version number */ + TLSv1_3_MINOR = 4, /* TLSv1_3 minor version number */ + TLS_DRAFT_MAJOR = 0x7f, /* Draft TLS major version number */ +#ifdef WOLFSSL_TLS13_DRAFT +#ifdef WOLFSSL_TLS13_DRAFT_18 + TLS_DRAFT_MINOR = 0x12, /* Minor version number of TLS draft */ +#elif defined(WOLFSSL_TLS13_DRAFT_22) + TLS_DRAFT_MINOR = 0x16, /* Minor version number of TLS draft */ +#elif defined(WOLFSSL_TLS13_DRAFT_23) + TLS_DRAFT_MINOR = 0x17, /* Minor version number of TLS draft */ +#elif defined(WOLFSSL_TLS13_DRAFT_26) + TLS_DRAFT_MINOR = 0x1a, /* Minor version number of TLS draft */ +#else + TLS_DRAFT_MINOR = 0x1c, /* Minor version number of TLS draft */ +#endif +#endif + OLD_HELLO_ID = 0x01, /* SSLv2 Client Hello Indicator */ + INVALID_BYTE = 0xff, /* Used to initialize cipher specs values */ + NO_COMPRESSION = 0, + ZLIB_COMPRESSION = 221, /* wolfSSL zlib compression */ + HELLO_EXT_SIG_ALGO = 13, /* ID for the sig_algo hello extension */ + HELLO_EXT_EXTMS = 0x0017, /* ID for the extended master secret ext */ + SECRET_LEN = WOLFSSL_MAX_MASTER_KEY_LENGTH, + /* pre RSA and all master */ +#if defined(WOLFSSL_TLS13) + MAX_PSK_ID_LEN = 256, /* max psk identity/hint supported */ +#else + MAX_PSK_ID_LEN = 128, /* max psk identity/hint supported */ +#endif +#if defined(WOLFSSL_MYSQL_COMPATIBLE) || \ + (defined(USE_FAST_MATH) && defined(FP_MAX_BITS) && FP_MAX_BITS > 8192) +#ifndef NO_PSK + ENCRYPT_LEN = 1024 + MAX_PSK_ID_LEN + 2, /* 8192 bit static buffer */ +#else + ENCRYPT_LEN = 1024, /* allow 8192 bit static buffer */ +#endif +#else +#ifndef NO_PSK + ENCRYPT_LEN = 512 + MAX_PSK_ID_LEN + 2, /* 4096 bit static buffer */ +#else + ENCRYPT_LEN = 512, /* allow 4096 bit static buffer */ +#endif +#endif + SIZEOF_SENDER = 4, /* clnt or srvr */ + FINISHED_SZ = 36, /* WC_MD5_DIGEST_SIZE + WC_SHA_DIGEST_SIZE */ + MAX_RECORD_SIZE = 16384, /* 2^14, max size by standard */ + MAX_PLAINTEXT_SZ = (1 << 14), /* Max plaintext sz */ + MAX_TLS_CIPHER_SZ = (1 << 14) + 2048, /* Max TLS encrypted data sz */ +#ifdef WOLFSSL_TLS13 + MAX_TLS13_PLAIN_SZ = (1 << 14) + 1, /* Max unencrypted data sz */ + MAX_TLS13_ENC_SZ = (1 << 14) + 256, /* Max encrypted data sz */ +#endif + MAX_MSG_EXTRA = 38 + WC_MAX_DIGEST_SIZE, + /* max added to msg, mac + pad from */ + /* RECORD_HEADER_SZ + BLOCK_SZ (pad) + Max + digest sz + BLOC_SZ (iv) + pad byte (1) */ + MAX_COMP_EXTRA = 1024, /* max compression extra */ + MAX_MTU = WOLFSSL_MAX_MTU, /* max expected MTU */ + MAX_UDP_SIZE = 8192 - 100, /* was MAX_MTU - 100 */ + MAX_DH_SZ = (MAX_DHKEY_SZ * 3) + 12, /* DH_P, DH_G and DH_Pub */ + /* 4096 p, pub, g + 2 byte size for each */ + MAX_STR_VERSION = 8, /* string rep of protocol version */ + + PAD_MD5 = 48, /* pad length for finished */ + PAD_SHA = 40, /* pad length for finished */ + MAX_PAD_SIZE = 256, /* maximum length of padding */ + + LENGTH_SZ = 2, /* length field for HMAC, data only */ + VERSION_SZ = 2, /* length of proctocol version */ + SEQ_SZ = 8, /* 64 bit sequence number */ + ALERT_SIZE = 2, /* level + description */ + VERIFY_HEADER = 2, /* always use 2 bytes */ + EXTS_SZ = 2, /* always use 2 bytes */ + EXT_ID_SZ = 2, /* always use 2 bytes */ + MAX_DH_SIZE = MAX_DHKEY_SZ+1, + /* Max size plus possible leading 0 */ + NAMED_DH_MASK = 0x100, /* Named group mask for DH parameters */ + MIN_FFHDE_GROUP = 0x100, /* Named group minimum for FFDHE parameters */ + MAX_FFHDE_GROUP = 0x1FF, /* Named group maximum for FFDHE parameters */ + SESSION_HINT_SZ = 4, /* session timeout hint */ + SESSION_ADD_SZ = 4, /* session age add */ + TICKET_NONCE_LEN_SZ = 1, /* Ticket nonce length size */ + DEF_TICKET_NONCE_SZ = 1, /* Default ticket nonce size */ + MAX_TICKET_NONCE_SZ = 8, /* maximum ticket nonce size */ + MAX_LIFETIME = 604800, /* maximum ticket lifetime */ + MAX_EARLY_DATA_SZ = 4096, /* maximum early data size */ + + RAN_LEN = 32, /* random length */ + SEED_LEN = RAN_LEN * 2, /* tls prf seed length */ + ID_LEN = 32, /* session id length */ + COOKIE_SECRET_SZ = 14, /* dtls cookie secret size */ + MAX_COOKIE_LEN = 32, /* max dtls cookie size */ + COOKIE_SZ = 20, /* use a 20 byte cookie */ + SUITE_LEN = 2, /* cipher suite sz length */ + ENUM_LEN = 1, /* always a byte */ + OPAQUE8_LEN = 1, /* 1 byte */ + OPAQUE16_LEN = 2, /* 2 bytes */ + OPAQUE24_LEN = 3, /* 3 bytes */ + OPAQUE32_LEN = 4, /* 4 bytes */ + OPAQUE64_LEN = 8, /* 8 bytes */ + COMP_LEN = 1, /* compression length */ + CURVE_LEN = 2, /* ecc named curve length */ + KE_GROUP_LEN = 2, /* key exchange group length */ + SERVER_ID_LEN = 20, /* server session id length */ + + HANDSHAKE_HEADER_SZ = 4, /* type + length(3) */ + RECORD_HEADER_SZ = 5, /* type + version + len(2) */ + CERT_HEADER_SZ = 3, /* always 3 bytes */ + REQ_HEADER_SZ = 2, /* cert request header sz */ + HINT_LEN_SZ = 2, /* length of hint size field */ + TRUNCATED_HMAC_SZ = 10, /* length of hmac w/ truncated hmac extension */ + HELLO_EXT_SZ = 4, /* base length of a hello extension */ + HELLO_EXT_TYPE_SZ = 2, /* length of a hello extension type */ + HELLO_EXT_SZ_SZ = 2, /* length of a hello extension size */ + HELLO_EXT_SIGALGO_SZ = 2, /* length of number of items in sigalgo list */ + + DTLS_HANDSHAKE_HEADER_SZ = 12, /* normal + seq(2) + offset(3) + length(3) */ + DTLS_RECORD_HEADER_SZ = 13, /* normal + epoch(2) + seq_num(6) */ + DTLS_HANDSHAKE_EXTRA = 8, /* diff from normal */ + DTLS_RECORD_EXTRA = 8, /* diff from normal */ + DTLS_HANDSHAKE_SEQ_SZ = 2, /* handshake header sequence number */ + DTLS_HANDSHAKE_FRAG_SZ = 3, /* fragment offset and length are 24 bit */ + DTLS_POOL_SZ = 255,/* allowed number of list items in TX pool */ + DTLS_EXPORT_PRO = 165,/* wolfSSL protocol for serialized session */ + DTLS_EXPORT_STATE_PRO = 166,/* wolfSSL protocol for serialized state */ + DTLS_EXPORT_VERSION = 4, /* wolfSSL version for serialized session */ + DTLS_EXPORT_OPT_SZ = 60, /* amount of bytes used from Options */ + DTLS_EXPORT_VERSION_3 = 3, /* wolfSSL version before TLS 1.3 addition */ + DTLS_EXPORT_OPT_SZ_3 = 59, /* amount of bytes used from Options */ + DTLS_EXPORT_KEY_SZ = 325 + (DTLS_SEQ_SZ * 2), + /* max amount of bytes used from Keys */ + DTLS_EXPORT_MIN_KEY_SZ = 78 + (DTLS_SEQ_SZ * 2), + /* min amount of bytes used from Keys */ + DTLS_EXPORT_SPC_SZ = 16, /* amount of bytes used from CipherSpecs */ + DTLS_EXPORT_LEN = 2, /* 2 bytes for length and protocol */ + DTLS_EXPORT_IP = 46, /* max ip size IPv4 mapped IPv6 */ + MAX_EXPORT_BUFFER = 514, /* max size of buffer for exporting */ + MAX_EXPORT_STATE_BUFFER = DTLS_EXPORT_KEY_SZ + 3 * DTLS_EXPORT_LEN, + /* max size of buffer for exporting state */ + FINISHED_LABEL_SZ = 15, /* TLS finished label size */ + TLS_FINISHED_SZ = 12, /* TLS has a shorter size */ + EXT_MASTER_LABEL_SZ = 22, /* TLS extended master secret label sz */ + MASTER_LABEL_SZ = 13, /* TLS master secret label sz */ + KEY_LABEL_SZ = 13, /* TLS key block expansion sz */ + PROTOCOL_LABEL_SZ = 9, /* Length of the protocol label */ + MAX_LABEL_SZ = 34, /* Maximum length of a label */ + MAX_HKDF_LABEL_SZ = OPAQUE16_LEN + + OPAQUE8_LEN + PROTOCOL_LABEL_SZ + MAX_LABEL_SZ + + OPAQUE8_LEN + WC_MAX_DIGEST_SIZE, + MAX_REQUEST_SZ = 256, /* Maximum cert req len (no auth yet */ + SESSION_FLUSH_COUNT = 256, /* Flush session cache unless user turns off */ + TLS_MAX_PAD_SZ = 255, /* Max padding in TLS */ + +#if defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) + MAX_SYM_KEY_SIZE = AES_256_KEY_SIZE, +#else + MAX_SYM_KEY_SIZE = WC_MAX_SYM_KEY_SIZE, +#endif + +#ifdef HAVE_SELFTEST + #define WOLFSSL_AES_KEY_SIZE_ENUM + AES_IV_SIZE = 16, + AES_128_KEY_SIZE = 16, + AES_192_KEY_SIZE = 24, + AES_256_KEY_SIZE = 32, +#endif + + MAX_IV_SZ = AES_BLOCK_SIZE, + + AEAD_SEQ_OFFSET = 4, /* Auth Data: Sequence number */ + AEAD_TYPE_OFFSET = 8, /* Auth Data: Type */ + AEAD_VMAJ_OFFSET = 9, /* Auth Data: Major Version */ + AEAD_VMIN_OFFSET = 10, /* Auth Data: Minor Version */ + AEAD_LEN_OFFSET = 11, /* Auth Data: Length */ + AEAD_AUTH_DATA_SZ = 13, /* Size of the data to authenticate */ + AEAD_NONCE_SZ = 12, + AESGCM_IMP_IV_SZ = 4, /* Size of GCM/CCM AEAD implicit IV */ + AESGCM_EXP_IV_SZ = 8, /* Size of GCM/CCM AEAD explicit IV */ + AESGCM_NONCE_SZ = AESGCM_EXP_IV_SZ + AESGCM_IMP_IV_SZ, + + CHACHA20_IMP_IV_SZ = 12, /* Size of ChaCha20 AEAD implicit IV */ + CHACHA20_NONCE_SZ = 12, /* Size of ChacCha20 nonce */ + CHACHA20_OLD_OFFSET = 4, /* Offset for seq # in old poly1305 */ + + /* For any new implicit/explicit IV size adjust AEAD_MAX_***_SZ */ + + AES_GCM_AUTH_SZ = 16, /* AES-GCM Auth Tag length */ + AES_CCM_16_AUTH_SZ = 16, /* AES-CCM-16 Auth Tag length */ + AES_CCM_8_AUTH_SZ = 8, /* AES-CCM-8 Auth Tag Length */ + AESCCM_NONCE_SZ = 12, + + CAMELLIA_128_KEY_SIZE = 16, /* for 128 bit */ + CAMELLIA_192_KEY_SIZE = 24, /* for 192 bit */ + CAMELLIA_256_KEY_SIZE = 32, /* for 256 bit */ + CAMELLIA_IV_SIZE = 16, /* always block size */ + + CHACHA20_256_KEY_SIZE = 32, /* for 256 bit */ + CHACHA20_128_KEY_SIZE = 16, /* for 128 bit */ + CHACHA20_IV_SIZE = 12, /* 96 bits for iv */ + + POLY1305_AUTH_SZ = 16, /* 128 bits */ + + HC_128_KEY_SIZE = 16, /* 128 bits */ + HC_128_IV_SIZE = 16, /* also 128 bits */ + + RABBIT_KEY_SIZE = 16, /* 128 bits */ + RABBIT_IV_SIZE = 8, /* 64 bits for iv */ + + EVP_SALT_SIZE = 8, /* evp salt size 64 bits */ + +#ifndef ECDHE_SIZE /* allow this to be overridden at compile-time */ + ECDHE_SIZE = 32, /* ECHDE server size defaults to 256 bit */ +#endif + MAX_EXPORT_ECC_SZ = 256, /* Export ANS X9.62 max future size */ + MAX_CURVE_NAME_SZ = 16, /* Maximum size of curve name string */ + + NEW_SA_MAJOR = 8, /* Most significant byte used with new sig algos */ + ED25519_SA_MAJOR = 8, /* Most significant byte for ED25519 */ + ED25519_SA_MINOR = 7, /* Least significant byte for ED25519 */ + ED448_SA_MAJOR = 8, /* Most significant byte for ED448 */ + ED448_SA_MINOR = 8, /* Least significant byte for ED448 */ + + MIN_RSA_SHA512_PSS_BITS = 512 * 2 + 8 * 8, /* Min key size */ + MIN_RSA_SHA384_PSS_BITS = 384 * 2 + 8 * 8, /* Min key size */ + +#ifndef NO_RSA + MAX_CERT_VERIFY_SZ = 4096 / 8, /* max RSA - default 4096-bits */ +#elif defined(HAVE_ECC) + MAX_CERT_VERIFY_SZ = ECC_MAX_SIG_SIZE, /* max ECC */ +#elif defined(HAVE_ED25519) + MAX_CERT_VERIFY_SZ = ED25519_SIG_SIZE, /* max Ed25519 */ +#else + MAX_CERT_VERIFY_SZ = 1024, /* max default */ +#endif + CLIENT_HELLO_FIRST = 35, /* Protocol + RAN_LEN + sizeof(id_len) */ + MAX_SUITE_NAME = 48, /* maximum length of cipher suite string */ + + DTLS_TIMEOUT_INIT = 1, /* default timeout init for DTLS receive */ + DTLS_TIMEOUT_MAX = 64, /* default max timeout for DTLS receive */ + DTLS_TIMEOUT_MULTIPLIER = 2, /* default timeout multiplier for DTLS recv */ + + NULL_TERM_LEN = 1, /* length of null '\0' termination character */ + MAX_PSK_KEY_LEN = 64, /* max psk key supported */ + MIN_PSK_ID_LEN = 6, /* min length of identities */ + MIN_PSK_BINDERS_LEN= 33, /* min length of binders */ + MAX_TICKET_AGE_SECS= 10, /* maximum ticket age in seconds */ + + MAX_WOLFSSL_FILE_SIZE = 1024ul * 1024ul * 4, /* 4 mb file size alloc limit */ + +#if defined(HAVE_EX_DATA) || defined(FORTRESS) + MAX_EX_DATA = 5, /* allow for five items of ex_data */ +#endif + + MAX_X509_SIZE = 2048, /* max static x509 buffer size */ + CERT_MIN_SIZE = 256, /* min PEM cert size with header/footer */ + + MAX_NTRU_PUB_KEY_SZ = 1027, /* NTRU max for now */ + MAX_NTRU_ENCRYPT_SZ = 1027, /* NTRU max for now */ + MAX_NTRU_BITS = 256, /* max symmetric bit strength */ + NO_SNIFF = 0, /* not sniffing */ + SNIFF = 1, /* currently sniffing */ + + HASH_SIG_SIZE = 2, /* default SHA1 RSA */ + + NO_COPY = 0, /* should we copy static buffer for write */ + COPY = 1, /* should we copy static buffer for write */ + + INVALID_PEER_ID = 0xFFFF, /* Initialize value for peer ID. */ + + PREV_ORDER = -1, /* Sequence number is in previous epoch. */ + PEER_ORDER = 1, /* Peer sequence number for verify. */ + CUR_ORDER = 0, /* Current sequence number. */ + WRITE_PROTO = 1, /* writing a protocol message */ + READ_PROTO = 0 /* reading a protocol message */ +}; + +/* minimum Downgrade Minor version */ +#ifndef WOLFSSL_MIN_DOWNGRADE + #ifndef NO_OLD_TLS + #define WOLFSSL_MIN_DOWNGRADE TLSv1_MINOR + #else + #define WOLFSSL_MIN_DOWNGRADE TLSv1_2_MINOR + #endif +#endif + +/* Set max implicit IV size for AEAD cipher suites */ +#define AEAD_MAX_IMP_SZ 12 + +/* Set max explicit IV size for AEAD cipher suites */ +#define AEAD_MAX_EXP_SZ 8 + + +#ifndef WOLFSSL_MAX_SUITE_SZ + #define WOLFSSL_MAX_SUITE_SZ 300 + /* 150 suites for now! */ +#endif + +/* number of items in the signature algo list */ +#ifndef WOLFSSL_MAX_SIGALGO + #define WOLFSSL_MAX_SIGALGO 32 +#endif + + +/* set minimum ECC key size allowed */ +#ifndef WOLFSSL_MIN_ECC_BITS + #ifdef WOLFSSL_MAX_STRENGTH + #define WOLFSSL_MIN_ECC_BITS 256 + #else + #define WOLFSSL_MIN_ECC_BITS 224 + #endif +#endif /* WOLFSSL_MIN_ECC_BITS */ +#if (WOLFSSL_MIN_ECC_BITS % 8) + /* Some ECC keys are not divisible by 8 such as prime239v1 or sect131r1. + In these cases round down to the nearest value divisible by 8. The + restriction of being divisible by 8 is in place to match wc_ecc_size + function from wolfSSL. + */ + #error ECC minimum bit size must be a multiple of 8 +#endif +#define MIN_ECCKEY_SZ (WOLFSSL_MIN_ECC_BITS / 8) + +/* set minimum RSA key size allowed */ +#ifndef WOLFSSL_MIN_RSA_BITS + #ifdef WOLFSSL_MAX_STRENGTH + #define WOLFSSL_MIN_RSA_BITS 2048 + #else + #define WOLFSSL_MIN_RSA_BITS 1024 + #endif +#endif /* WOLFSSL_MIN_RSA_BITS */ +#if (WOLFSSL_MIN_RSA_BITS % 8) + /* This is to account for the example case of a min size of 2050 bits but + still allows 2049 bit key. So we need the measurement to be in bytes. */ + #error RSA minimum bit size must be a multiple of 8 +#endif +#define MIN_RSAKEY_SZ (WOLFSSL_MIN_RSA_BITS / 8) + +#ifdef SESSION_INDEX +/* Shift values for making a session index */ +#define SESSIDX_ROW_SHIFT 4 +#define SESSIDX_IDX_MASK 0x0F +#endif + + +/* max cert chain peer depth */ +#ifndef MAX_CHAIN_DEPTH + #define MAX_CHAIN_DEPTH 9 +#endif + +/* max size of a certificate message payload */ +/* assumes MAX_CHAIN_DEPTH number of certificates at 2kb per certificate */ +#ifndef MAX_CERTIFICATE_SZ + #define MAX_CERTIFICATE_SZ \ + CERT_HEADER_SZ + \ + (MAX_X509_SIZE + CERT_HEADER_SZ) * MAX_CHAIN_DEPTH +#endif + +/* max size of a handshake message, currently set to the certificate */ +#ifndef MAX_HANDSHAKE_SZ + #define MAX_HANDSHAKE_SZ MAX_CERTIFICATE_SZ +#endif + +#ifndef SESSION_TICKET_LEN + #define SESSION_TICKET_LEN 256 +#endif + +#ifndef SESSION_TICKET_HINT_DEFAULT + #define SESSION_TICKET_HINT_DEFAULT 300 +#endif + + +/* don't use extra 3/4k stack space unless need to */ +#ifdef HAVE_NTRU + #define MAX_ENCRYPT_SZ MAX_NTRU_ENCRYPT_SZ +#else + #define MAX_ENCRYPT_SZ ENCRYPT_LEN +#endif + + +/* states */ +enum states { + NULL_STATE = 0, + + SERVER_HELLOVERIFYREQUEST_COMPLETE, + SERVER_HELLO_RETRY_REQUEST_COMPLETE, + SERVER_HELLO_COMPLETE, + SERVER_ENCRYPTED_EXTENSIONS_COMPLETE, + SERVER_CERT_COMPLETE, + SERVER_KEYEXCHANGE_COMPLETE, + SERVER_HELLODONE_COMPLETE, + SERVER_CHANGECIPHERSPEC_COMPLETE, + SERVER_FINISHED_COMPLETE, + + CLIENT_HELLO_RETRY, + CLIENT_HELLO_COMPLETE, + CLIENT_KEYEXCHANGE_COMPLETE, + CLIENT_CHANGECIPHERSPEC_COMPLETE, + CLIENT_FINISHED_COMPLETE, + + HANDSHAKE_DONE +}; + +/* SSL Version */ +typedef struct ProtocolVersion { + byte major; + byte minor; +} WOLFSSL_PACK ProtocolVersion; + + +WOLFSSL_LOCAL ProtocolVersion MakeSSLv3(void); +WOLFSSL_LOCAL ProtocolVersion MakeTLSv1(void); +WOLFSSL_LOCAL ProtocolVersion MakeTLSv1_1(void); +WOLFSSL_LOCAL ProtocolVersion MakeTLSv1_2(void); +WOLFSSL_LOCAL ProtocolVersion MakeTLSv1_3(void); + +#ifdef WOLFSSL_DTLS + WOLFSSL_LOCAL ProtocolVersion MakeDTLSv1(void); + WOLFSSL_LOCAL ProtocolVersion MakeDTLSv1_2(void); + + #ifdef WOLFSSL_SESSION_EXPORT + WOLFSSL_LOCAL int wolfSSL_dtls_import_internal(WOLFSSL* ssl, byte* buf, + word32 sz); + WOLFSSL_LOCAL int wolfSSL_dtls_export_internal(WOLFSSL* ssl, byte* buf, + word32 sz); + WOLFSSL_LOCAL int wolfSSL_dtls_export_state_internal(WOLFSSL* ssl, + byte* buf, word32 sz); + WOLFSSL_LOCAL int wolfSSL_dtls_import_state_internal(WOLFSSL* ssl, + byte* buf, word32 sz); + WOLFSSL_LOCAL int wolfSSL_send_session(WOLFSSL* ssl); + #endif +#endif + + +/* wolfSSL BIO_METHOD type */ +struct WOLFSSL_BIO_METHOD { + byte type; /* method type */ +}; + + +/* wolfSSL BIO type */ +struct WOLFSSL_BIO { + WOLFSSL_BUF_MEM* mem_buf; + WOLFSSL* ssl; /* possible associated ssl */ +#ifndef NO_FILESYSTEM + XFILE file; +#endif + WOLFSSL_BIO* prev; /* previous in chain */ + WOLFSSL_BIO* next; /* next in chain */ + WOLFSSL_BIO* pair; /* BIO paired with */ + void* heap; /* user heap hint */ + byte* mem; /* memory buffer */ + int wrSz; /* write buffer size (mem) */ + int wrIdx; /* current index for write buffer */ + int rdIdx; /* current read index */ + int readRq; /* read request */ + int memLen; /* memory buffer length */ + int fd; /* possible file descriptor */ + int eof; /* eof flag */ + int flags; + byte type; /* method type */ + byte close; /* close flag */ +}; + + +/* wolfSSL method type */ +struct WOLFSSL_METHOD { + ProtocolVersion version; + byte side; /* connection side, server or client */ + byte downgrade; /* whether to downgrade version, default no */ +}; + +/* wolfSSL buffer type - internal uses "buffer" type */ +typedef WOLFSSL_BUFFER_INFO buffer; + +typedef struct Suites Suites; + + +/* defaults to client */ +WOLFSSL_LOCAL void InitSSL_Method(WOLFSSL_METHOD*, ProtocolVersion); + +WOLFSSL_LOCAL int InitSSL_Suites(WOLFSSL* ssl); +WOLFSSL_LOCAL int InitSSL_Side(WOLFSSL* ssl, word16 side); + +/* for sniffer */ +WOLFSSL_LOCAL int DoFinished(WOLFSSL* ssl, const byte* input, word32* inOutIdx, + word32 size, word32 totalSz, int sniff); +WOLFSSL_LOCAL int DoApplicationData(WOLFSSL* ssl, byte* input, word32* inOutIdx); +/* TLS v1.3 needs these */ +WOLFSSL_LOCAL int HandleTlsResumption(WOLFSSL* ssl, int bogusID, + Suites* clSuites); +#ifdef WOLFSSL_TLS13 +WOLFSSL_LOCAL int FindSuite(Suites* suites, byte first, byte second); +#endif +WOLFSSL_LOCAL int DoClientHello(WOLFSSL* ssl, const byte* input, word32*, + word32); +#ifdef WOLFSSL_TLS13 +WOLFSSL_LOCAL int DoTls13ClientHello(WOLFSSL* ssl, const byte* input, + word32* inOutIdx, word32 helloSz); +#endif +WOLFSSL_LOCAL int DoServerHello(WOLFSSL* ssl, const byte* input, word32*, + word32); +WOLFSSL_LOCAL int CompleteServerHello(WOLFSSL *ssl); +WOLFSSL_LOCAL int CheckVersion(WOLFSSL *ssl, ProtocolVersion pv); +WOLFSSL_LOCAL int PickHashSigAlgo(WOLFSSL* ssl, const byte* hashSigAlgo, + word32 hashSigAlgoSz); +WOLFSSL_LOCAL int DecodePrivateKey(WOLFSSL *ssl, word16* length); +#ifdef HAVE_PK_CALLBACKS +WOLFSSL_LOCAL int GetPrivateKeySigSize(WOLFSSL* ssl); +#ifndef NO_ASN + WOLFSSL_LOCAL int InitSigPkCb(WOLFSSL* ssl, SignatureCtx* sigCtx); +#endif +#endif +WOLFSSL_LOCAL void FreeKeyExchange(WOLFSSL* ssl); +WOLFSSL_LOCAL int ProcessPeerCerts(WOLFSSL* ssl, byte* input, word32* inOutIdx, word32 size); +WOLFSSL_LOCAL int MatchDomainName(const char* pattern, int len, const char* str); +#ifndef NO_CERTS +WOLFSSL_LOCAL int CheckAltNames(DecodedCert* dCert, char* domain); +#endif +WOLFSSL_LOCAL int CreateTicket(WOLFSSL* ssl); +WOLFSSL_LOCAL int HashOutputRaw(WOLFSSL* ssl, const byte* output, int sz); +WOLFSSL_LOCAL int HashOutput(WOLFSSL* ssl, const byte* output, int sz, + int ivSz); +WOLFSSL_LOCAL int HashInput(WOLFSSL* ssl, const byte* input, int sz); +#if defined(OPENSSL_ALL) || defined(HAVE_STUNNEL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) +WOLFSSL_LOCAL int SNI_Callback(WOLFSSL* ssl); +#endif +#ifdef WOLFSSL_TLS13 +WOLFSSL_LOCAL int DecryptTls13(WOLFSSL* ssl, byte* output, const byte* input, + word16 sz, const byte* aad, word16 aadSz); +WOLFSSL_LOCAL int DoTls13HandShakeMsgType(WOLFSSL* ssl, byte* input, + word32* inOutIdx, byte type, + word32 size, word32 totalSz); +WOLFSSL_LOCAL int DoTls13HandShakeMsg(WOLFSSL* ssl, byte* input, + word32* inOutIdx, word32 totalSz); +WOLFSSL_LOCAL int DoTls13ServerHello(WOLFSSL* ssl, const byte* input, + word32* inOutIdx, word32 helloSz, + byte* extMsgType); +#endif +int TimingPadVerify(WOLFSSL* ssl, const byte* input, int padLen, int t, + int pLen, int content); + + +enum { + FORCED_FREE = 1, + NO_FORCED_FREE = 0 +}; + + +/* only use compression extra if using compression */ +#ifdef HAVE_LIBZ + #define COMP_EXTRA MAX_COMP_EXTRA +#else + #define COMP_EXTRA 0 +#endif + +/* only the sniffer needs space in the buffer for extra MTU record(s) */ +#ifdef WOLFSSL_SNIFFER + #define MTU_EXTRA MAX_MTU * 3 +#else + #define MTU_EXTRA 0 +#endif + + +/* embedded callbacks require large static buffers, make sure on */ +#ifdef WOLFSSL_CALLBACKS + #undef LARGE_STATIC_BUFFERS + #define LARGE_STATIC_BUFFERS +#endif + + +/* give user option to use 16K static buffers */ +#if defined(LARGE_STATIC_BUFFERS) + #define RECORD_SIZE MAX_RECORD_SIZE +#else + #ifdef WOLFSSL_DTLS + #define RECORD_SIZE MAX_MTU + #else + #define RECORD_SIZE 128 + #endif +#endif + + +/* user option to turn off 16K output option */ +/* if using small static buffers (default) and SSL_write tries to write data + larger than the record we have, dynamically get it, unless user says only + write in static buffer chunks */ +#ifndef STATIC_CHUNKS_ONLY + #define OUTPUT_RECORD_SIZE MAX_RECORD_SIZE +#else + #define OUTPUT_RECORD_SIZE RECORD_SIZE +#endif + +/* wolfSSL input buffer + + RFC 2246: + + length + The length (in bytes) of the following TLSPlaintext.fragment. + The length should not exceed 2^14. +*/ +#if defined(LARGE_STATIC_BUFFERS) + #define STATIC_BUFFER_LEN RECORD_HEADER_SZ + RECORD_SIZE + COMP_EXTRA + \ + MTU_EXTRA + MAX_MSG_EXTRA +#else + /* don't fragment memory from the record header */ + #define STATIC_BUFFER_LEN RECORD_HEADER_SZ +#endif + +typedef struct { + ALIGN16 byte staticBuffer[STATIC_BUFFER_LEN]; + byte* buffer; /* place holder for static or dynamic buffer */ + word32 length; /* total buffer length used */ + word32 idx; /* idx to part of length already consumed */ + word32 bufferSize; /* current buffer size */ + byte dynamicFlag; /* dynamic memory currently in use */ + byte offset; /* alignment offset attempt */ +} bufferStatic; + +/* Cipher Suites holder */ +struct Suites { + word16 suiteSz; /* suite length in bytes */ + word16 hashSigAlgoSz; /* SigAlgo extension length in bytes */ + byte suites[WOLFSSL_MAX_SUITE_SZ]; + byte hashSigAlgo[WOLFSSL_MAX_SIGALGO]; /* sig/algo to offer */ + byte setSuites; /* user set suites from default */ + byte hashAlgo; /* selected hash algorithm */ + byte sigAlgo; /* selected sig algorithm */ +}; + + +WOLFSSL_LOCAL void InitSuitesHashSigAlgo(Suites* suites, int haveECDSAsig, + int haveRSAsig, int haveAnon, + int tls1_2, int keySz); +WOLFSSL_LOCAL void InitSuites(Suites*, ProtocolVersion, int, word16, word16, + word16, word16, word16, word16, word16, int); +WOLFSSL_LOCAL int MatchSuite(WOLFSSL* ssl, Suites* peerSuites); +WOLFSSL_LOCAL int SetCipherList(WOLFSSL_CTX*, Suites*, const char* list); + +#ifndef PSK_TYPES_DEFINED + typedef unsigned int (*wc_psk_client_callback)(WOLFSSL*, const char*, char*, + unsigned int, unsigned char*, unsigned int); + typedef unsigned int (*wc_psk_server_callback)(WOLFSSL*, const char*, + unsigned char*, unsigned int); +#ifdef WOLFSSL_TLS13 + typedef unsigned int (*wc_psk_client_tls13_callback)(WOLFSSL*, const char*, + char*, unsigned int, unsigned char*, unsigned int, + const char**); + typedef unsigned int (*wc_psk_server_tls13_callback)(WOLFSSL*, const char*, + unsigned char*, unsigned int, const char**); +#endif +#endif /* PSK_TYPES_DEFINED */ +#if defined(WOLFSSL_DTLS) && defined(WOLFSSL_SESSION_EXPORT) && \ + !defined(WOLFSSL_DTLS_EXPORT_TYPES) + typedef int (*wc_dtls_export)(WOLFSSL* ssl, + unsigned char* exportBuffer, unsigned int sz, void* userCtx); +#define WOLFSSL_DTLS_EXPORT_TYPES +#endif /* WOLFSSL_DTLS_EXPORT_TYPES */ + + +/* wolfSSL Cipher type just points back to SSL */ +struct WOLFSSL_CIPHER { + WOLFSSL* ssl; +}; + + +#ifdef NO_ASN + /* no_asn won't have */ + typedef struct CertStatus CertStatus; +#endif + +#ifndef HAVE_OCSP + typedef struct WOLFSSL_OCSP WOLFSSL_OCSP; +#endif + +/* wolfSSL OCSP controller */ +#ifdef HAVE_OCSP +struct WOLFSSL_OCSP { + WOLFSSL_CERT_MANAGER* cm; /* pointer back to cert manager */ + OcspEntry* ocspList; /* OCSP response list */ + wolfSSL_Mutex ocspLock; /* OCSP list lock */ +#if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) || \ + defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + int(*statusCb)(WOLFSSL*, void*); +#endif +}; +#endif + +#ifndef MAX_DATE_SIZE +#define MAX_DATE_SIZE 32 +#endif + +typedef struct CRL_Entry CRL_Entry; + +#ifdef NO_SHA + #define CRL_DIGEST_SIZE WC_SHA256_DIGEST_SIZE +#else + #define CRL_DIGEST_SIZE WC_SHA_DIGEST_SIZE +#endif + +#ifdef NO_ASN + typedef struct RevokedCert RevokedCert; +#endif + +/* Complete CRL */ +struct CRL_Entry { + CRL_Entry* next; /* next entry */ + byte issuerHash[CRL_DIGEST_SIZE]; /* issuer hash */ + /* byte crlHash[CRL_DIGEST_SIZE]; raw crl data hash */ + /* restore the hash here if needed for optimized comparisons */ + byte lastDate[MAX_DATE_SIZE]; /* last date updated */ + byte nextDate[MAX_DATE_SIZE]; /* next update date */ + byte lastDateFormat; /* last date format */ + byte nextDateFormat; /* next date format */ + RevokedCert* certs; /* revoked cert list */ + int totalCerts; /* number on list */ + int verified; + byte* toBeSigned; + word32 tbsSz; + byte* signature; + word32 signatureSz; + word32 signatureOID; +#if !defined(NO_SKID) && defined(CRL_SKID_READY) + byte extAuthKeyIdSet; + byte extAuthKeyId[KEYID_SIZE]; +#endif +}; + + +typedef struct CRL_Monitor CRL_Monitor; + +/* CRL directory monitor */ +struct CRL_Monitor { + char* path; /* full dir path, if valid pointer we're using */ + int type; /* PEM or ASN1 type */ +}; + + +#if defined(HAVE_CRL) && defined(NO_FILESYSTEM) + #undef HAVE_CRL_MONITOR +#endif + +/* wolfSSL CRL controller */ +struct WOLFSSL_CRL { + WOLFSSL_CERT_MANAGER* cm; /* pointer back to cert manager */ + CRL_Entry* crlList; /* our CRL list */ +#ifdef HAVE_CRL_IO + CbCrlIO crlIOCb; +#endif + wolfSSL_Mutex crlLock; /* CRL list lock */ + CRL_Monitor monitors[2]; /* PEM and DER possible */ +#ifdef HAVE_CRL_MONITOR + pthread_cond_t cond; /* condition to signal setup */ + pthread_t tid; /* monitoring thread */ + int mfd; /* monitor fd, -1 if no init yet */ + int setup; /* thread is setup predicate */ +#endif + void* heap; /* heap hint for dynamic memory */ +}; + + +#ifdef NO_ASN + typedef struct Signer Signer; +#ifdef WOLFSSL_TRUST_PEER_CERT + typedef struct TrustedPeerCert TrustedPeerCert; +#endif +#endif + + +#ifndef CA_TABLE_SIZE + #define CA_TABLE_SIZE 11 +#endif +#ifdef WOLFSSL_TRUST_PEER_CERT + #define TP_TABLE_SIZE 11 +#endif + +/* wolfSSL Certificate Manager */ +struct WOLFSSL_CERT_MANAGER { + Signer* caTable[CA_TABLE_SIZE]; /* the CA signer table */ + void* heap; /* heap helper */ +#ifdef WOLFSSL_TRUST_PEER_CERT + TrustedPeerCert* tpTable[TP_TABLE_SIZE]; /* table of trusted peer certs */ + wolfSSL_Mutex tpLock; /* trusted peer list lock */ +#endif + WOLFSSL_CRL* crl; /* CRL checker */ + WOLFSSL_OCSP* ocsp; /* OCSP checker */ +#if !defined(NO_WOLFSSL_SERVER) && (defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2)) + WOLFSSL_OCSP* ocsp_stapling; /* OCSP checker for OCSP stapling */ +#endif + char* ocspOverrideURL; /* use this responder */ + void* ocspIOCtx; /* I/O callback CTX */ + CallbackCACache caCacheCallback; /* CA cache addition callback */ + CbMissingCRL cbMissingCRL; /* notify through cb of missing crl */ + CbOCSPIO ocspIOCb; /* I/O callback for OCSP lookup */ + CbOCSPRespFree ocspRespFreeCb; /* Frees OCSP Response from IO Cb */ + wolfSSL_Mutex caLock; /* CA list lock */ + byte crlEnabled; /* is CRL on ? */ + byte crlCheckAll; /* always leaf, but all ? */ + byte ocspEnabled; /* is OCSP on ? */ + byte ocspCheckAll; /* always leaf, but all ? */ + byte ocspSendNonce; /* send the OCSP nonce ? */ + byte ocspUseOverrideURL; /* ignore cert's responder, override */ + byte ocspStaplingEnabled; /* is OCSP Stapling on ? */ + +#ifndef NO_RSA + short minRsaKeySz; /* minimum allowed RSA key size */ +#endif +#if defined(HAVE_ECC) || defined(HAVE_ED25519) + short minEccKeySz; /* minimum allowed ECC key size */ +#endif +}; + +WOLFSSL_LOCAL int CM_SaveCertCache(WOLFSSL_CERT_MANAGER*, const char*); +WOLFSSL_LOCAL int CM_RestoreCertCache(WOLFSSL_CERT_MANAGER*, const char*); +WOLFSSL_LOCAL int CM_MemSaveCertCache(WOLFSSL_CERT_MANAGER*, void*, int, int*); +WOLFSSL_LOCAL int CM_MemRestoreCertCache(WOLFSSL_CERT_MANAGER*, const void*, int); +WOLFSSL_LOCAL int CM_GetCertCacheMemSize(WOLFSSL_CERT_MANAGER*); + +/* wolfSSL Sock Addr */ +struct WOLFSSL_SOCKADDR { + unsigned int sz; /* sockaddr size */ + void* sa; /* pointer to the sockaddr_in or sockaddr_in6 */ +}; + +typedef struct WOLFSSL_DTLS_CTX { + WOLFSSL_SOCKADDR peer; + int rfd; + int wfd; +} WOLFSSL_DTLS_CTX; + + +typedef struct WOLFSSL_DTLS_PEERSEQ { + word32 window[WOLFSSL_DTLS_WINDOW_WORDS]; + /* Sliding window for current epoch */ + word16 nextEpoch; /* Expected epoch in next record */ + word16 nextSeq_hi; /* Expected sequence in next record */ + word32 nextSeq_lo; + + word32 prevWindow[WOLFSSL_DTLS_WINDOW_WORDS]; + /* Sliding window for old epoch */ + word32 prevSeq_lo; + word16 prevSeq_hi; /* Next sequence in allowed old epoch */ + +#ifdef WOLFSSL_MULTICAST + word16 peerId; + word32 highwaterMark; +#endif +} WOLFSSL_DTLS_PEERSEQ; + + +#define MAX_WRITE_IV_SZ 16 /* max size of client/server write_IV */ + +/* keys and secrets + * keep as a constant size (no additional ifdefs) for session export */ +typedef struct Keys { +#if !defined(WOLFSSL_AEAD_ONLY) || defined(WOLFSSL_TLS13) + byte client_write_MAC_secret[WC_MAX_DIGEST_SIZE]; /* max sizes */ + byte server_write_MAC_secret[WC_MAX_DIGEST_SIZE]; +#endif + byte client_write_key[MAX_SYM_KEY_SIZE]; /* max sizes */ + byte server_write_key[MAX_SYM_KEY_SIZE]; + byte client_write_IV[MAX_WRITE_IV_SZ]; /* max sizes */ + byte server_write_IV[MAX_WRITE_IV_SZ]; +#if defined(HAVE_AEAD) || defined(WOLFSSL_SESSION_EXPORT) + byte aead_exp_IV[AEAD_MAX_EXP_SZ]; + byte aead_enc_imp_IV[AEAD_MAX_IMP_SZ]; + byte aead_dec_imp_IV[AEAD_MAX_IMP_SZ]; +#endif + + word32 peer_sequence_number_hi; + word32 peer_sequence_number_lo; + word32 sequence_number_hi; + word32 sequence_number_lo; + +#ifdef WOLFSSL_DTLS + word16 curEpoch; /* Received epoch in current record */ + word16 curSeq_hi; /* Received sequence in current record */ + word32 curSeq_lo; +#ifdef WOLFSSL_MULTICAST + byte curPeerId; /* Received peer group ID in current record */ +#endif + WOLFSSL_DTLS_PEERSEQ peerSeq[WOLFSSL_DTLS_PEERSEQ_SZ]; + + word16 dtls_peer_handshake_number; + word16 dtls_expected_peer_handshake_number; + + word16 dtls_epoch; /* Current epoch */ + word16 dtls_sequence_number_hi; /* Current epoch */ + word32 dtls_sequence_number_lo; + word16 dtls_prev_sequence_number_hi; /* Previous epoch */ + word32 dtls_prev_sequence_number_lo; + word16 dtls_handshake_number; /* Current tx handshake seq */ +#endif + + word32 encryptSz; /* last size of encrypted data */ + word32 padSz; /* how much to advance after decrypt part */ + byte encryptionOn; /* true after change cipher spec */ + byte decryptedCur; /* only decrypt current record once */ +#ifdef WOLFSSL_TLS13 + byte updateResponseReq:1; /* KeyUpdate response from peer required. */ + byte keyUpdateRespond:1; /* KeyUpdate is to be responded to. */ +#endif +} Keys; + + + +/** TLS Extensions - RFC 6066 */ +#ifdef HAVE_TLS_EXTENSIONS + +typedef enum { + TLSX_SERVER_NAME = 0x0000, /* a.k.a. SNI */ + TLSX_MAX_FRAGMENT_LENGTH = 0x0001, + TLSX_TRUSTED_CA_KEYS = 0x0003, + TLSX_TRUNCATED_HMAC = 0x0004, + TLSX_STATUS_REQUEST = 0x0005, /* a.k.a. OCSP stapling */ + TLSX_SUPPORTED_GROUPS = 0x000a, /* a.k.a. Supported Curves */ + TLSX_EC_POINT_FORMATS = 0x000b, +#if !defined(WOLFSSL_NO_SIGALG) + TLSX_SIGNATURE_ALGORITHMS = 0x000d, +#endif + TLSX_APPLICATION_LAYER_PROTOCOL = 0x0010, /* a.k.a. ALPN */ + TLSX_STATUS_REQUEST_V2 = 0x0011, /* a.k.a. OCSP stapling v2 */ + TLSX_QUANTUM_SAFE_HYBRID = 0x0018, /* a.k.a. QSH */ + TLSX_SESSION_TICKET = 0x0023, +#ifdef WOLFSSL_TLS13 + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + TLSX_PRE_SHARED_KEY = 0x0029, + #endif + #ifdef WOLFSSL_EARLY_DATA + TLSX_EARLY_DATA = 0x002a, + #endif + TLSX_SUPPORTED_VERSIONS = 0x002b, + TLSX_COOKIE = 0x002c, + #if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + TLSX_PSK_KEY_EXCHANGE_MODES = 0x002d, + #endif + #ifdef WOLFSSL_POST_HANDSHAKE_AUTH + TLSX_POST_HANDSHAKE_AUTH = 0x0031, + #endif + #if defined(WOLFSSL_TLS13_DRAFT_18) || defined(WOLFSSL_TLS13_DRAFT_22) + TLSX_KEY_SHARE = 0x0028, + #else + TLSX_SIGNATURE_ALGORITHMS_CERT = 0x0032, + TLSX_KEY_SHARE = 0x0033, + #endif +#endif + TLSX_RENEGOTIATION_INFO = 0xff01 +} TLSX_Type; + +typedef struct TLSX { + TLSX_Type type; /* Extension Type */ + void* data; /* Extension Data */ + word32 val; /* Extension Value */ + byte resp; /* IsResponse Flag */ + struct TLSX* next; /* List Behavior */ +} TLSX; + +WOLFSSL_LOCAL TLSX* TLSX_Find(TLSX* list, TLSX_Type type); +WOLFSSL_LOCAL void TLSX_Remove(TLSX** list, TLSX_Type type, void* heap); +WOLFSSL_LOCAL void TLSX_FreeAll(TLSX* list, void* heap); +WOLFSSL_LOCAL int TLSX_SupportExtensions(WOLFSSL* ssl); +WOLFSSL_LOCAL int TLSX_PopulateExtensions(WOLFSSL* ssl, byte isRequest); + +#if defined(WOLFSSL_TLS13) || !defined(NO_WOLFSSL_CLIENT) +WOLFSSL_LOCAL int TLSX_GetRequestSize(WOLFSSL* ssl, byte msgType, + word16* pLength); +WOLFSSL_LOCAL int TLSX_WriteRequest(WOLFSSL* ssl, byte* output, + byte msgType, word16* pOffset); +#endif + +#if defined(WOLFSSL_TLS13) || !defined(NO_WOLFSSL_SERVER) +/* TLS 1.3 Certificate messages have extensions. */ +WOLFSSL_LOCAL int TLSX_GetResponseSize(WOLFSSL* ssl, byte msgType, + word16* pLength); +WOLFSSL_LOCAL int TLSX_WriteResponse(WOLFSSL *ssl, byte* output, byte msgType, + word16* pOffset); +#endif + +WOLFSSL_LOCAL int TLSX_ParseVersion(WOLFSSL* ssl, byte* input, word16 length, + byte msgType, int* found); +WOLFSSL_LOCAL int TLSX_Parse(WOLFSSL* ssl, byte* input, word16 length, + byte msgType, Suites *suites); + +#elif defined(HAVE_SNI) \ + || defined(HAVE_MAX_FRAGMENT) \ + || defined(HAVE_TRUSTED_CA) \ + || defined(HAVE_TRUNCATED_HMAC) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) \ + || defined(HAVE_SUPPORTED_CURVES) \ + || defined(HAVE_ALPN) \ + || defined(HAVE_QSH) \ + || defined(HAVE_SESSION_TICKET) \ + || defined(HAVE_SECURE_RENEGOTIATION) \ + || defined(HAVE_SERVER_RENEGOTIATION_INFO) + +#error Using TLS extensions requires HAVE_TLS_EXTENSIONS to be defined. + +#endif /* HAVE_TLS_EXTENSIONS */ + +/** Server Name Indication - RFC 6066 (session 3) */ +#ifdef HAVE_SNI + +typedef struct SNI { + byte type; /* SNI Type */ + union { char* host_name; } data; /* SNI Data */ + struct SNI* next; /* List Behavior */ + byte status; /* Matching result */ +#ifndef NO_WOLFSSL_SERVER + byte options; /* Behavior options */ +#endif +} SNI; + +WOLFSSL_LOCAL int TLSX_UseSNI(TLSX** extensions, byte type, const void* data, + word16 size, void* heap); +WOLFSSL_LOCAL byte TLSX_SNI_Status(TLSX* extensions, byte type); +WOLFSSL_LOCAL word16 TLSX_SNI_GetRequest(TLSX* extensions, byte type, + void** data); + +#ifndef NO_WOLFSSL_SERVER +WOLFSSL_LOCAL void TLSX_SNI_SetOptions(TLSX* extensions, byte type, + byte options); +WOLFSSL_LOCAL int TLSX_SNI_GetFromBuffer(const byte* buffer, word32 bufferSz, + byte type, byte* sni, word32* inOutSz); +#endif + +#endif /* HAVE_SNI */ + +/* Trusted CA Key Indication - RFC 6066 (section 6) */ +#ifdef HAVE_TRUSTED_CA + +typedef struct TCA { + byte type; /* TCA Type */ + byte* id; /* TCA identifier */ + word16 idSz; /* TCA identifier size */ + struct TCA* next; /* List Behavior */ +} TCA; + +WOLFSSL_LOCAL int TLSX_UseTrustedCA(TLSX** extensions, byte type, + const byte* id, word16 idSz, void* heap); + +#endif /* HAVE_TRUSTED_CA */ + +/* Application-Layer Protocol Negotiation - RFC 7301 */ +#ifdef HAVE_ALPN +typedef struct ALPN { + char* protocol_name; /* ALPN protocol name */ + struct ALPN* next; /* List Behavior */ + byte options; /* Behavior options */ + byte negotiated; /* ALPN protocol negotiated or not */ +} ALPN; + +WOLFSSL_LOCAL int TLSX_ALPN_GetRequest(TLSX* extensions, + void** data, word16 *dataSz); + +WOLFSSL_LOCAL int TLSX_UseALPN(TLSX** extensions, const void* data, + word16 size, byte options, void* heap); + +WOLFSSL_LOCAL int TLSX_ALPN_SetOptions(TLSX** extensions, const byte option); + +#endif /* HAVE_ALPN */ + +/** Maximum Fragment Length Negotiation - RFC 6066 (session 4) */ +#ifdef HAVE_MAX_FRAGMENT + +WOLFSSL_LOCAL int TLSX_UseMaxFragment(TLSX** extensions, byte mfl, void* heap); + +#endif /* HAVE_MAX_FRAGMENT */ + +/** Truncated HMAC - RFC 6066 (session 7) */ +#ifdef HAVE_TRUNCATED_HMAC + +WOLFSSL_LOCAL int TLSX_UseTruncatedHMAC(TLSX** extensions, void* heap); + +#endif /* HAVE_TRUNCATED_HMAC */ + +/** Certificate Status Request - RFC 6066 (session 8) */ +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST + +typedef struct { + byte status_type; + byte options; + WOLFSSL* ssl; + union { + OcspRequest ocsp; + } request; +#if defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_SERVER) + buffer response; +#endif +} CertificateStatusRequest; + +WOLFSSL_LOCAL int TLSX_UseCertificateStatusRequest(TLSX** extensions, + byte status_type, byte options, WOLFSSL* ssl, void* heap, int devId); +#ifndef NO_CERTS +WOLFSSL_LOCAL int TLSX_CSR_InitRequest(TLSX* extensions, DecodedCert* cert, + void* heap); +#endif +WOLFSSL_LOCAL void* TLSX_CSR_GetRequest(TLSX* extensions); +WOLFSSL_LOCAL int TLSX_CSR_ForceRequest(WOLFSSL* ssl); + +#endif + +/** Certificate Status Request v2 - RFC 6961 */ +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + +typedef struct CSRIv2 { + byte status_type; + byte options; + word16 requests; + union { + OcspRequest ocsp[1 + MAX_CHAIN_DEPTH]; + } request; + struct CSRIv2* next; +} CertificateStatusRequestItemV2; + +WOLFSSL_LOCAL int TLSX_UseCertificateStatusRequestV2(TLSX** extensions, + byte status_type, byte options, void* heap, int devId); +#ifndef NO_CERTS +WOLFSSL_LOCAL int TLSX_CSR2_InitRequests(TLSX* extensions, DecodedCert* cert, + byte isPeer, void* heap); +#endif +WOLFSSL_LOCAL void* TLSX_CSR2_GetRequest(TLSX* extensions, byte status_type, + byte index); +WOLFSSL_LOCAL int TLSX_CSR2_ForceRequest(WOLFSSL* ssl); + +#endif + +/** Supported Elliptic Curves - RFC 4492 (session 4) */ +#ifdef HAVE_SUPPORTED_CURVES + +typedef struct SupportedCurve { + word16 name; /* Curve Names */ + struct SupportedCurve* next; /* List Behavior */ +} SupportedCurve; + +typedef struct PointFormat { + byte format; /* PointFormat */ + struct PointFormat* next; /* List Behavior */ +} PointFormat; + +WOLFSSL_LOCAL int TLSX_UseSupportedCurve(TLSX** extensions, word16 name, + void* heap); + +WOLFSSL_LOCAL int TLSX_UsePointFormat(TLSX** extensions, byte point, + void* heap); + +#ifndef NO_WOLFSSL_SERVER +WOLFSSL_LOCAL int TLSX_ValidateSupportedCurves(WOLFSSL* ssl, byte first, + byte second); +WOLFSSL_LOCAL int TLSX_SupportedCurve_CheckPriority(WOLFSSL* ssl); +WOLFSSL_LOCAL int TLSX_SupportedFFDHE_Set(WOLFSSL* ssl); +#endif +WOLFSSL_LOCAL int TLSX_SupportedCurve_Preferred(WOLFSSL* ssl, + int checkSupported); + +#endif /* HAVE_SUPPORTED_CURVES */ + +/** Renegotiation Indication - RFC 5746 */ +#if defined(HAVE_SECURE_RENEGOTIATION) \ + || defined(HAVE_SERVER_RENEGOTIATION_INFO) + +enum key_cache_state { + SCR_CACHE_NULL = 0, /* empty / begin state */ + SCR_CACHE_NEEDED, /* need to cache keys */ + SCR_CACHE_COPY, /* we have a cached copy */ + SCR_CACHE_PARTIAL, /* partial restore to real keys */ + SCR_CACHE_COMPLETE /* complete restore to real keys */ +}; + +/* Additional Connection State according to rfc5746 section 3.1 */ +typedef struct SecureRenegotiation { + byte enabled; /* secure_renegotiation flag in rfc */ + byte verifySet; + byte startScr; /* server requested client to start scr */ + enum key_cache_state cache_status; /* track key cache state */ + byte client_verify_data[TLS_FINISHED_SZ]; /* cached */ + byte server_verify_data[TLS_FINISHED_SZ]; /* cached */ + byte subject_hash[KEYID_SIZE]; /* peer cert hash */ + Keys tmp_keys; /* can't overwrite real keys yet */ +} SecureRenegotiation; + +WOLFSSL_LOCAL int TLSX_UseSecureRenegotiation(TLSX** extensions, void* heap); + +#ifdef HAVE_SERVER_RENEGOTIATION_INFO +WOLFSSL_LOCAL int TLSX_AddEmptyRenegotiationInfo(TLSX** extensions, void* heap); +#endif + +#endif /* HAVE_SECURE_RENEGOTIATION */ + +/** Session Ticket - RFC 5077 (session 3.2) */ +#ifdef HAVE_SESSION_TICKET + +typedef struct SessionTicket { + word32 lifetime; +#ifdef WOLFSSL_TLS13 + word64 seen; + word32 ageAdd; +#endif + byte* data; + word16 size; +} SessionTicket; + +WOLFSSL_LOCAL int TLSX_UseSessionTicket(TLSX** extensions, + SessionTicket* ticket, void* heap); +WOLFSSL_LOCAL SessionTicket* TLSX_SessionTicket_Create(word32 lifetime, + byte* data, word16 size, void* heap); +WOLFSSL_LOCAL void TLSX_SessionTicket_Free(SessionTicket* ticket, void* heap); + +#endif /* HAVE_SESSION_TICKET */ + +/** Quantum-Safe-Hybrid - draft-whyte-qsh-tls12-00 */ +#ifdef HAVE_QSH + +typedef struct QSHScheme { + struct QSHScheme* next; /* List Behavior */ + byte* PK; + word16 name; /* QSHScheme Names */ + word16 PKLen; +} QSHScheme; + +typedef struct QSHkey { + struct QSHKey* next; + word16 name; + buffer pub; + buffer pri; +} QSHKey; + +typedef struct QSHSecret { + QSHScheme* list; + buffer* SerSi; + buffer* CliSi; +} QSHSecret; + +/* used in key exchange during handshake */ +WOLFSSL_LOCAL int TLSX_QSHCipher_Parse(WOLFSSL* ssl, const byte* input, + word16 length, byte isServer); +WOLFSSL_LOCAL word16 TLSX_QSHPK_Write(QSHScheme* list, byte* output); +WOLFSSL_LOCAL word16 TLSX_QSH_GetSize(QSHScheme* list, byte isRequest); + +/* used by api for setting a specific QSH scheme */ +WOLFSSL_LOCAL int TLSX_UseQSHScheme(TLSX** extensions, word16 name, + byte* pKey, word16 pKeySz, void* heap); + +/* used when parsing in QSHCipher structs */ +WOLFSSL_LOCAL int QSH_Decrypt(QSHKey* key, byte* in, word32 szIn, + byte* out, word16* szOut); +#ifndef NO_WOLFSSL_SERVER +WOLFSSL_LOCAL int TLSX_ValidateQSHScheme(TLSX** extensions, word16 name); +#endif + +#endif /* HAVE_QSH */ + +#ifdef WOLFSSL_TLS13 +/* Cookie extension information - cookie data. */ +typedef struct Cookie { + word16 len; + byte data; +} Cookie; + +WOLFSSL_LOCAL int TLSX_Cookie_Use(WOLFSSL* ssl, byte* data, word16 len, + byte* mac, byte macSz, int resp); + + +/* Key Share - TLS v1.3 Specification */ + +/* The KeyShare extension information - entry in a linked list. */ +typedef struct KeyShareEntry { + word16 group; /* NamedGroup */ + byte* ke; /* Key exchange data */ + word32 keLen; /* Key exchange data length */ + void* key; /* Private key */ + word32 keyLen; /* Private key length */ + byte* pubKey; /* Public key */ + word32 pubKeyLen; /* Public key length */ + struct KeyShareEntry* next; /* List pointer */ +} KeyShareEntry; + +WOLFSSL_LOCAL int TLSX_KeyShare_Use(WOLFSSL* ssl, word16 group, word16 len, + byte* data, KeyShareEntry **kse); +WOLFSSL_LOCAL int TLSX_KeyShare_Empty(WOLFSSL* ssl); +WOLFSSL_LOCAL int TLSX_KeyShare_Establish(WOLFSSL* ssl); +WOLFSSL_LOCAL int TLSX_KeyShare_DeriveSecret(WOLFSSL* ssl); + + +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) +#ifndef WOLFSSL_TLS13_DRAFT_18 +/* Ticket nonce - for deriving PSK. + * Length allowed to be: 1..255. Only support 4 bytes. + */ +typedef struct TicketNonce { + byte len; + byte data[MAX_TICKET_NONCE_SZ]; +} TicketNonce; +#endif + +/* The PreSharedKey extension information - entry in a linked list. */ +typedef struct PreSharedKey { + word16 identityLen; /* Length of identity */ + byte* identity; /* PSK identity */ + word32 ticketAge; /* Age of the ticket */ + byte cipherSuite0; /* Cipher Suite */ + byte cipherSuite; /* Cipher Suite */ + word32 binderLen; /* Length of HMAC */ + byte binder[WC_MAX_DIGEST_SIZE]; /* HMAC of handshake */ + byte hmac; /* HMAC algorithm */ + byte resumption:1; /* Resumption PSK */ + byte chosen:1; /* Server's choice */ + struct PreSharedKey* next; /* List pointer */ +} PreSharedKey; + +WOLFSSL_LOCAL int TLSX_PreSharedKey_WriteBinders(PreSharedKey* list, + byte* output, byte msgType, + word16* pSz); +WOLFSSL_LOCAL int TLSX_PreSharedKey_GetSizeBinders(PreSharedKey* list, + byte msgType, word16* pSz); +WOLFSSL_LOCAL int TLSX_PreSharedKey_Use(WOLFSSL* ssl, byte* identity, + word16 len, word32 age, byte hmac, + byte cipherSuite0, byte cipherSuite, + byte resumption, + PreSharedKey **preSharedKey); + +/* The possible Pre-Shared Key key exchange modes. */ +enum PskKeyExchangeMode { + PSK_KE, + PSK_DHE_KE +}; + +/* User can define this. */ +#ifndef WOLFSSL_DEF_PSK_CIPHER +#define WOLFSSL_DEF_PSK_CIPHER TLS_AES_128_GCM_SHA256 +#endif + +WOLFSSL_LOCAL int TLSX_PskKeModes_Use(WOLFSSL* ssl, byte modes); + +#ifdef WOLFSSL_EARLY_DATA +WOLFSSL_LOCAL int TLSX_EarlyData_Use(WOLFSSL* ssl, word32 max); +#endif +#endif /* HAVE_SESSION_TICKET || !NO_PSK */ + + +/* The types of keys to derive for. */ +enum DeriveKeyType { + no_key, + early_data_key, + handshake_key, + traffic_key, + update_traffic_key +}; + +/* The key update request values for KeyUpdate message. */ +enum KeyUpdateRequest { + update_not_requested, + update_requested +}; +#endif /* WOLFSSL_TLS13 */ + + +#ifdef OPENSSL_EXTRA +enum SetCBIO { + WOLFSSL_CBIO_NONE = 0, + WOLFSSL_CBIO_RECV = 0x1, + WOLFSSL_CBIO_SEND = 0x2, +}; +#endif + +/* wolfSSL context type */ +struct WOLFSSL_CTX { + WOLFSSL_METHOD* method; +#ifdef SINGLE_THREADED + WC_RNG* rng; /* to be shared with WOLFSSL w/o locking */ +#endif + wolfSSL_Mutex countMutex; /* reference count mutex */ + int refCount; /* reference count */ + int err; /* error code in case of mutex not created */ +#ifndef NO_DH + buffer serverDH_P; + buffer serverDH_G; +#endif +#ifndef NO_CERTS + DerBuffer* certificate; + DerBuffer* certChain; + /* chain after self, in DER, with leading size for each cert */ + #if defined(OPENSSL_EXTRA) || defined(WOLFSSL_EXTRA) + WOLF_STACK_OF(WOLFSSL_X509_NAME)* ca_names; + #endif + #if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) || \ + defined(WOLFSSL_NGINX) || defined (WOLFSSL_HAPROXY) + WOLF_STACK_OF(WOLFSSL_X509)* x509Chain; + #endif +#ifdef WOLFSSL_TLS13 + int certChainCnt; +#endif + DerBuffer* privateKey; + byte privateKeyType:7; + byte privateKeyId:1; + int privateKeySz; + int privateKeyDevId; + WOLFSSL_CERT_MANAGER* cm; /* our cert manager, ctx owns SSL will use */ +#endif +#ifdef KEEP_OUR_CERT + WOLFSSL_X509* ourCert; /* keep alive a X509 struct of cert */ + int ownOurCert; /* Dispose of certificate if we own */ +#endif + Suites* suites; /* make dynamic, user may not need/set */ + void* heap; /* for user memory overrides */ + byte verifyDepth; + byte verifyPeer:1; + byte verifyNone:1; + byte failNoCert:1; + byte failNoCertxPSK:1; /* fail if no cert with the exception of PSK*/ + byte sessionCacheOff:1; + byte sessionCacheFlushOff:1; +#ifdef HAVE_EXT_CACHE + byte internalCacheOff:1; +#endif + byte sendVerify:2; /* for client side (can not be single bit) */ + byte haveRSA:1; /* RSA available */ + byte haveECC:1; /* ECC available */ + byte haveDH:1; /* server DH parms set by user */ + byte haveNTRU:1; /* server private NTRU key loaded */ + byte haveECDSAsig:1; /* server cert signed w/ ECDSA */ + byte haveStaticECC:1; /* static server ECC private key */ + byte partialWrite:1; /* only one msg per write call */ + byte quietShutdown:1; /* don't send close notify */ + byte groupMessages:1; /* group handshake messages before sending */ + byte minDowngrade; /* minimum downgrade version */ + byte haveEMS:1; /* have extended master secret extension */ + byte useClientOrder:1; /* Use client's cipher preference order */ +#ifdef WOLFSSL_TLS13 + byte noTicketTls13:1; /* Server won't create new Ticket */ + byte noPskDheKe:1; /* Don't use (EC)DHE with PSK */ +#endif +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) + byte postHandshakeAuth:1; /* Post-handshake auth supported. */ +#endif +#ifndef NO_DH + #if !defined(WOLFSSL_OLD_PRIME_CHECK) && !defined(HAVE_FIPS) && \ + !defined(HAVE_SELFTEST) + byte dhKeyTested:1; /* Set when key has been tested. */ + #endif +#endif +#ifdef WOLFSSL_MULTICAST + byte haveMcast; /* multicast requested */ + byte mcastID; /* multicast group ID */ +#endif +#if defined(WOLFSSL_SCTP) && defined(WOLFSSL_DTLS) + byte dtlsSctp; /* DTLS-over-SCTP mode */ + word16 dtlsMtuSz; /* DTLS MTU size */ +#endif +#ifndef NO_DH + word16 minDhKeySz; /* minimum DH key size */ + word16 maxDhKeySz; /* maximum DH key size */ +#endif +#ifndef NO_RSA + short minRsaKeySz; /* minimum RSA key size */ +#endif +#if defined(HAVE_ECC) || defined(HAVE_ED25519) + short minEccKeySz; /* minimum ECC key size */ +#endif +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + unsigned long mask; /* store SSL_OP_ flags */ +#endif +#ifdef OPENSSL_EXTRA + byte sessionCtx[ID_LEN]; /* app session context ID */ + word32 disabledCurves; /* curves disabled by user */ + const unsigned char *alpn_cli_protos;/* ALPN client protocol list */ + unsigned int alpn_cli_protos_len; + byte sessionCtxSz; + byte cbioFlag; /* WOLFSSL_CBIO_RECV/SEND: CBIORecv/Send is set */ + CallbackInfoState* CBIS; /* used to get info about SSL state */ +#endif + CallbackIORecv CBIORecv; + CallbackIOSend CBIOSend; +#ifdef WOLFSSL_DTLS + CallbackGenCookie CBIOCookie; /* gen cookie callback */ +#ifdef WOLFSSL_SESSION_EXPORT + wc_dtls_export dtls_export; /* export function for DTLS session */ + CallbackGetPeer CBGetPeer; + CallbackSetPeer CBSetPeer; +#endif +#endif /* WOLFSSL_DTLS */ + VerifyCallback verifyCallback; /* cert verification callback */ + word32 timeout; /* session timeout */ +#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) + word32 ecdhCurveOID; /* curve Ecc_Sum */ +#endif +#ifdef HAVE_ECC + word16 eccTempKeySz; /* in octets 20 - 66 */ +#endif +#if defined(HAVE_ECC) || defined(HAVE_ED25519) + word32 pkCurveOID; /* curve Ecc_Sum */ +#endif +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + byte havePSK; /* psk key set by user */ + wc_psk_client_callback client_psk_cb; /* client callback */ + wc_psk_server_callback server_psk_cb; /* server callback */ +#ifdef WOLFSSL_TLS13 + wc_psk_client_tls13_callback client_psk_tls13_cb; /* client callback */ + wc_psk_server_tls13_callback server_psk_tls13_cb; /* server callback */ +#endif + char server_hint[MAX_PSK_ID_LEN + NULL_TERM_LEN]; +#endif /* HAVE_SESSION_TICKET || !NO_PSK */ +#ifdef WOLFSSL_TLS13 + word16 group[WOLFSSL_MAX_GROUP_COUNT]; + byte numGroups; +#endif +#ifdef WOLFSSL_EARLY_DATA + word32 maxEarlyDataSz; +#endif +#ifdef HAVE_ANON + byte haveAnon; /* User wants to allow Anon suites */ +#endif /* HAVE_ANON */ +#ifdef WOLFSSL_ENCRYPTED_KEYS + pem_password_cb* passwd_cb; + void* passwd_userdata; +#endif +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + WOLFSSL_X509_STORE x509_store; /* points to ctx->cm */ + WOLFSSL_X509_STORE* x509_store_pt; /* take ownership of external store */ + byte readAhead; + void* userPRFArg; /* passed to prf callback */ +#endif +#ifdef HAVE_EX_DATA + void* ex_data[MAX_EX_DATA]; +#endif +#if defined(HAVE_ALPN) && (defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)) + CallbackALPNSelect alpnSelect; + void* alpnSelectArg; +#endif +#if defined(OPENSSL_ALL) || (defined(OPENSSL_EXTRA) && (defined(HAVE_STUNNEL) || \ + defined(WOLFSSL_NGINX) || defined(HAVE_LIGHTY) || \ + defined(WOLFSSL_HAPROXY))) + CallbackSniRecv sniRecvCb; + void* sniRecvCbArg; +#endif +#if defined(WOLFSSL_MULTICAST) && defined(WOLFSSL_DTLS) + CallbackMcastHighwater mcastHwCb; /* Sequence number highwater callback */ + word32 mcastFirstSeq; /* first trigger level */ + word32 mcastSecondSeq; /* second trigger level */ + word32 mcastMaxSeq; /* max level */ +#endif +#ifdef HAVE_OCSP + WOLFSSL_OCSP ocsp; +#endif + int devId; /* async device id to use */ +#ifdef HAVE_TLS_EXTENSIONS + TLSX* extensions; /* RFC 6066 TLS Extensions data */ + #ifndef NO_WOLFSSL_SERVER + #if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + OcspRequest* certOcspRequest; + #endif + #if defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) + OcspRequest* chainOcspRequest[MAX_CHAIN_DEPTH]; + #endif + #endif + #if defined(HAVE_SESSION_TICKET) && !defined(NO_WOLFSSL_SERVER) + SessionTicketEncCb ticketEncCb; /* enc/dec session ticket Cb */ + void* ticketEncCtx; /* session encrypt context */ + int ticketHint; /* ticket hint in seconds */ + #endif + #ifdef HAVE_SUPPORTED_CURVES + byte userCurves; /* indicates user called wolfSSL_CTX_UseSupportedCurve */ + #endif +#endif +#ifdef ATOMIC_USER + CallbackMacEncrypt MacEncryptCb; /* Atomic User Mac/Encrypt Cb */ + CallbackDecryptVerify DecryptVerifyCb; /* Atomic User Decrypt/Verify Cb */ +#endif +#ifdef HAVE_PK_CALLBACKS + #ifdef HAVE_ECC + CallbackEccKeyGen EccKeyGenCb; /* User EccKeyGen Callback Handler */ + CallbackEccSign EccSignCb; /* User EccSign Callback handler */ + CallbackEccVerify EccVerifyCb; /* User EccVerify Callback handler */ + CallbackEccSharedSecret EccSharedSecretCb; /* User EccVerify Callback handler */ + #ifdef HAVE_ED25519 + /* User Ed25519Sign Callback handler */ + CallbackEd25519Sign Ed25519SignCb; + /* User Ed25519Verify Callback handler */ + CallbackEd25519Verify Ed25519VerifyCb; + #endif + #ifdef HAVE_CURVE25519 + /* User X25519 KeyGen Callback Handler */ + CallbackX25519KeyGen X25519KeyGenCb; + /* User X25519 SharedSecret Callback handler */ + CallbackX25519SharedSecret X25519SharedSecretCb; + #endif + #endif /* HAVE_ECC */ + #ifndef NO_DH + CallbackDhAgree DhAgreeCb; /* User DH Agree Callback handler */ + #endif + #ifndef NO_RSA + CallbackRsaSign RsaSignCb; /* User RsaSign Callback handler (priv key) */ + CallbackRsaVerify RsaVerifyCb; /* User RsaVerify Callback handler (pub key) */ + CallbackRsaVerify RsaSignCheckCb; /* User VerifyRsaSign Callback handler (priv key) */ + #ifdef WC_RSA_PSS + CallbackRsaPssSign RsaPssSignCb; /* User RsaSign (priv key) */ + CallbackRsaPssVerify RsaPssVerifyCb; /* User RsaVerify (pub key) */ + CallbackRsaPssVerify RsaPssSignCheckCb; /* User VerifyRsaSign (priv key) */ + #endif + CallbackRsaEnc RsaEncCb; /* User Rsa Public Encrypt handler */ + CallbackRsaDec RsaDecCb; /* User Rsa Private Decrypt handler */ + #endif /* NO_RSA */ +#endif /* HAVE_PK_CALLBACKS */ +#ifdef HAVE_WOLF_EVENT + WOLF_EVENT_QUEUE event_queue; +#endif /* HAVE_WOLF_EVENT */ +#ifdef HAVE_EXT_CACHE + WOLFSSL_SESSION*(*get_sess_cb)(WOLFSSL*, unsigned char*, int, int*); + int (*new_sess_cb)(WOLFSSL*, WOLFSSL_SESSION*); + void (*rem_sess_cb)(WOLFSSL_CTX*, WOLFSSL_SESSION*); +#endif +#if defined(OPENSSL_EXTRA) && defined(WOLFCRYPT_HAVE_SRP) && !defined(NO_SHA256) + Srp* srp; /* TLS Secure Remote Password Protocol*/ + byte* srp_password; +#endif +}; + +WOLFSSL_LOCAL +int InitSSL_Ctx(WOLFSSL_CTX*, WOLFSSL_METHOD*, void* heap); +WOLFSSL_LOCAL +void FreeSSL_Ctx(WOLFSSL_CTX*); +WOLFSSL_LOCAL +void SSL_CtxResourceFree(WOLFSSL_CTX*); + +WOLFSSL_LOCAL +int DeriveTlsKeys(WOLFSSL* ssl); +WOLFSSL_LOCAL +int ProcessOldClientHello(WOLFSSL* ssl, const byte* input, word32* inOutIdx, + word32 inSz, word16 sz); + +#ifndef NO_CERTS + WOLFSSL_LOCAL + int AddCA(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int type, int verify); + WOLFSSL_LOCAL + int AlreadySigner(WOLFSSL_CERT_MANAGER* cm, byte* hash); +#ifdef WOLFSSL_TRUST_PEER_CERT + WOLFSSL_LOCAL + int AddTrustedPeer(WOLFSSL_CERT_MANAGER* cm, DerBuffer** pDer, int verify); + WOLFSSL_LOCAL + int AlreadyTrustedPeer(WOLFSSL_CERT_MANAGER* cm, byte* hash); +#endif +#endif + +/* All cipher suite related info + * Keep as a constant size (no ifdefs) for session export */ +typedef struct CipherSpecs { + word16 key_size; + word16 iv_size; + word16 block_size; + word16 aead_mac_size; + byte bulk_cipher_algorithm; + byte cipher_type; /* block, stream, or aead */ + byte mac_algorithm; + byte kea; /* key exchange algo */ + byte sig_algo; + byte hash_size; + byte pad_size; + byte static_ecdh; +} CipherSpecs; + + +void InitCipherSpecs(CipherSpecs* cs); + + +/* Supported Key Exchange Protocols */ +enum KeyExchangeAlgorithm { + no_kea, + rsa_kea, + diffie_hellman_kea, + fortezza_kea, + psk_kea, + dhe_psk_kea, + ecdhe_psk_kea, + ntru_kea, + ecc_diffie_hellman_kea, + ecc_static_diffie_hellman_kea /* for verify suite only */ +}; + + +/* Supported Authentication Schemes */ +enum SignatureAlgorithm { + anonymous_sa_algo = 0, + rsa_sa_algo = 1, + dsa_sa_algo = 2, + ecc_dsa_sa_algo = 3, + rsa_pss_sa_algo = 8, + ed25519_sa_algo = 9, + rsa_pss_pss_algo = 10 +}; + +#define PSS_RSAE_TO_PSS_PSS(macAlgo) \ + (macAlgo + (pss_sha256 - sha256_mac)) + +#define PSS_PSS_HASH_TO_MAC(macAlgo) \ + (macAlgo - (pss_sha256 - sha256_mac)) + +enum SigAlgRsaPss { + pss_sha256 = 0x09, + pss_sha384 = 0x0a, + pss_sha512 = 0x0b, +}; + + +/* Supprted ECC Curve Types */ +enum EccCurves { + named_curve = 3 +}; + + +/* Valid client certificate request types from page 27 */ +enum ClientCertificateType { + rsa_sign = 1, + dss_sign = 2, + rsa_fixed_dh = 3, + dss_fixed_dh = 4, + rsa_ephemeral_dh = 5, + dss_ephemeral_dh = 6, + fortezza_kea_cert = 20, + ecdsa_sign = 64, + rsa_fixed_ecdh = 65, + ecdsa_fixed_ecdh = 66 +}; + + +#ifndef WOLFSSL_AEAD_ONLY +enum CipherType { stream, block, aead }; +#else +enum CipherType { aead }; +#endif + + + + + + +/* cipher for now */ +typedef struct Ciphers { +#ifdef BUILD_ARC4 + Arc4* arc4; +#endif +#ifdef BUILD_DES3 + Des3* des3; +#endif +#if defined(BUILD_AES) || defined(BUILD_AESGCM) + Aes* aes; + #if defined(BUILD_AESGCM) || defined(HAVE_AESCCM) || defined(WOLFSSL_TLS13) + byte* additional; + byte* nonce; + #endif +#endif +#ifdef HAVE_CAMELLIA + Camellia* cam; +#endif +#ifdef HAVE_CHACHA + ChaCha* chacha; +#endif +#ifdef HAVE_HC128 + HC128* hc128; +#endif +#ifdef BUILD_RABBIT + Rabbit* rabbit; +#endif +#ifdef HAVE_IDEA + Idea* idea; +#endif + byte state; + byte setup; /* have we set it up flag for detection */ +} Ciphers; + + +#ifdef HAVE_ONE_TIME_AUTH +/* Ciphers for one time authentication such as poly1305 */ +typedef struct OneTimeAuth { +#ifdef HAVE_POLY1305 + Poly1305* poly1305; +#endif + byte setup; /* flag for if a cipher has been set */ + +} OneTimeAuth; +#endif + + +WOLFSSL_LOCAL void InitCiphers(WOLFSSL* ssl); +WOLFSSL_LOCAL void FreeCiphers(WOLFSSL* ssl); + + +/* hashes type */ +typedef struct Hashes { + #if !defined(NO_MD5) && !defined(NO_OLD_TLS) + byte md5[WC_MD5_DIGEST_SIZE]; + #endif + #if !defined(NO_SHA) + byte sha[WC_SHA_DIGEST_SIZE]; + #endif + #ifndef NO_SHA256 + byte sha256[WC_SHA256_DIGEST_SIZE]; + #endif + #ifdef WOLFSSL_SHA384 + byte sha384[WC_SHA384_DIGEST_SIZE]; + #endif + #ifdef WOLFSSL_SHA512 + byte sha512[WC_SHA512_DIGEST_SIZE]; + #endif +} Hashes; + +WOLFSSL_LOCAL int BuildCertHashes(WOLFSSL* ssl, Hashes* hashes); + +#ifdef WOLFSSL_TLS13 +typedef union Digest { +#ifndef NO_WOLFSSL_SHA256 + wc_Sha256 sha256; +#endif +#ifdef WOLFSSL_SHA384 + wc_Sha384 sha384; +#endif +#ifdef WOLFSSL_SHA512 + wc_Sha512 sha512; +#endif +} Digest; +#endif + +/* Static x509 buffer */ +typedef struct x509_buffer { + int length; /* actual size */ + byte buffer[MAX_X509_SIZE]; /* max static cert size */ +} x509_buffer; + + +/* wolfSSL X509_CHAIN, for no dynamic memory SESSION_CACHE */ +struct WOLFSSL_X509_CHAIN { + int count; /* total number in chain */ + x509_buffer certs[MAX_CHAIN_DEPTH]; /* only allow max depth 4 for now */ +}; + + +/* wolfSSL session type */ +struct WOLFSSL_SESSION { + word32 bornOn; /* create time in seconds */ + word32 timeout; /* timeout in seconds */ + byte sessionID[ID_LEN]; /* id for protocol */ + byte sessionIDSz; + byte masterSecret[SECRET_LEN]; /* stored secret */ + word16 haveEMS; /* ext master secret flag */ +#ifdef SESSION_CERTS + WOLFSSL_X509_CHAIN chain; /* peer cert chain, static */ + #ifdef WOLFSSL_ALT_CERT_CHAINS + WOLFSSL_X509_CHAIN altChain; /* peer alt cert chain, static */ + #endif +#endif +#if defined(SESSION_CERTS) || (defined(WOLFSSL_TLS13) && \ + defined(HAVE_SESSION_TICKET)) + ProtocolVersion version; /* which version was used */ +#endif +#if defined(SESSION_CERTS) || !defined(NO_RESUME_SUITE_CHECK) || \ + (defined(WOLFSSL_TLS13) && defined(HAVE_SESSION_TICKET)) + byte cipherSuite0; /* first byte, normally 0 */ + byte cipherSuite; /* 2nd byte, actual suite */ +#endif +#ifndef NO_CLIENT_CACHE + word16 idLen; /* serverID length */ + byte serverID[SERVER_ID_LEN]; /* for easier client lookup */ +#endif +#ifdef OPENSSL_EXTRA + byte sessionCtxSz; /* sessionCtx length */ + byte sessionCtx[ID_LEN]; /* app specific context id */ +#endif +#ifdef WOLFSSL_TLS13 + word16 namedGroup; +#endif +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + #ifdef WOLFSSL_TLS13 + word32 ticketSeen; /* Time ticket seen (ms) */ + word32 ticketAdd; /* Added by client */ + #ifndef WOLFSSL_TLS13_DRAFT_18 + TicketNonce ticketNonce; /* Nonce used to derive PSK */ + #endif + #endif + #ifdef WOLFSSL_EARLY_DATA + word32 maxEarlyDataSz; + #endif +#endif +#ifdef HAVE_SESSION_TICKET + byte* ticket; + word16 ticketLen; + byte staticTicket[SESSION_TICKET_LEN]; + byte isDynamic; +#endif +#ifdef HAVE_EXT_CACHE + byte isAlloced; +#endif +#ifdef HAVE_EX_DATA + void* ex_data[MAX_EX_DATA]; +#endif +}; + + +WOLFSSL_LOCAL +WOLFSSL_SESSION* GetSession(WOLFSSL*, byte*, byte); +WOLFSSL_LOCAL +int SetSession(WOLFSSL*, WOLFSSL_SESSION*); + +typedef int (*hmacfp) (WOLFSSL*, byte*, const byte*, word32, int, int, int); + +#ifndef NO_CLIENT_CACHE + WOLFSSL_SESSION* GetSessionClient(WOLFSSL*, const byte*, int); +#endif + +/* client connect state for nonblocking restart */ +enum ConnectState { + CONNECT_BEGIN = 0, + CLIENT_HELLO_SENT, + HELLO_AGAIN, /* HELLO_AGAIN s for DTLS case */ + HELLO_AGAIN_REPLY, + FIRST_REPLY_DONE, + FIRST_REPLY_FIRST, + FIRST_REPLY_SECOND, + FIRST_REPLY_THIRD, + FIRST_REPLY_FOURTH, + FINISHED_DONE, + SECOND_REPLY_DONE +}; + + +/* server accept state for nonblocking restart */ +enum AcceptState { + ACCEPT_BEGIN = 0, + ACCEPT_CLIENT_HELLO_DONE, + ACCEPT_HELLO_RETRY_REQUEST_DONE, + ACCEPT_FIRST_REPLY_DONE, + SERVER_HELLO_SENT, + SERVER_EXTENSIONS_SENT, + CERT_SENT, + CERT_VERIFY_SENT, + CERT_STATUS_SENT, + KEY_EXCHANGE_SENT, + CERT_REQ_SENT, + SERVER_HELLO_DONE, + ACCEPT_SECOND_REPLY_DONE, + TICKET_SENT, + CHANGE_CIPHER_SENT, + ACCEPT_FINISHED_DONE, + ACCEPT_THIRD_REPLY_DONE +}; + +/* TLS 1.3 server accept state for nonblocking restart */ +enum AcceptStateTls13 { + TLS13_ACCEPT_BEGIN = 0, + TLS13_ACCEPT_CLIENT_HELLO_DONE, + TLS13_ACCEPT_HELLO_RETRY_REQUEST_DONE, + TLS13_ACCEPT_FIRST_REPLY_DONE, + TLS13_ACCEPT_SECOND_REPLY_DONE, + TLS13_SERVER_HELLO_SENT, + TLS13_ACCEPT_THIRD_REPLY_DONE, + TLS13_SERVER_EXTENSIONS_SENT, + TLS13_CERT_REQ_SENT, + TLS13_CERT_SENT, + TLS13_CERT_VERIFY_SENT, + TLS13_ACCEPT_FINISHED_SENT, + TLS13_PRE_TICKET_SENT, + TLS13_ACCEPT_FINISHED_DONE, + TLS13_TICKET_SENT +}; + +/* buffers for struct WOLFSSL */ +typedef struct Buffers { + bufferStatic inputBuffer; + bufferStatic outputBuffer; + buffer domainName; /* for client check */ + buffer clearOutputBuffer; + buffer sig; /* signature data */ + buffer digest; /* digest data */ + int prevSent; /* previous plain text bytes sent + when got WANT_WRITE */ + int plainSz; /* plain text bytes in buffer to send + when got WANT_WRITE */ + byte weOwnCert; /* SSL own cert flag */ + byte weOwnCertChain; /* SSL own cert chain flag */ + byte weOwnKey; /* SSL own key flag */ + byte weOwnDH; /* SSL own dh (p,g) flag */ +#ifndef NO_DH + buffer serverDH_P; /* WOLFSSL_CTX owns, unless we own */ + buffer serverDH_G; /* WOLFSSL_CTX owns, unless we own */ + buffer serverDH_Pub; + buffer serverDH_Priv; + DhKey* serverDH_Key; +#endif +#ifndef NO_CERTS + DerBuffer* certificate; /* WOLFSSL_CTX owns, unless we own */ + DerBuffer* key; /* WOLFSSL_CTX owns, unless we own */ + byte keyType:7; /* Type of key: RSA, ECC, Ed25519 */ + byte keyId:1; /* Key data is an id not data */ + int keySz; /* Size of RSA key */ + int keyDevId; /* Device Id for key */ + DerBuffer* certChain; /* WOLFSSL_CTX owns, unless we own */ + /* chain after self, in DER, with leading size for each cert */ +#ifdef WOLFSSL_TLS13 + int certChainCnt; + DerBuffer* certExts; +#endif +#endif +#ifdef WOLFSSL_SEND_HRR_COOKIE + buffer tls13CookieSecret; /* HRR cookie secret */ +#endif +#ifdef WOLFSSL_DTLS + WOLFSSL_DTLS_CTX dtlsCtx; /* DTLS connection context */ + #ifndef NO_WOLFSSL_SERVER + buffer dtlsCookieSecret; /* DTLS cookie secret */ + #endif /* NO_WOLFSSL_SERVER */ +#endif +#ifdef HAVE_PK_CALLBACKS + #ifdef HAVE_ECC + buffer peerEccDsaKey; /* we own for Ecc Verify Callbacks */ + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + buffer peerEd25519Key; /* for Ed25519 Verify Callbacks */ + #endif /* HAVE_ED25519 */ + #ifndef NO_RSA + buffer peerRsaKey; /* we own for Rsa Verify Callbacks */ + #endif /* NO_RSA */ +#endif /* HAVE_PK_CALLBACKS */ +} Buffers; + +/* sub-states for send/do key share (key exchange) */ +enum asyncState { + TLS_ASYNC_BEGIN = 0, + TLS_ASYNC_BUILD, + TLS_ASYNC_DO, + TLS_ASYNC_VERIFY, + TLS_ASYNC_FINALIZE, + TLS_ASYNC_END +}; + +/* sub-states for build message */ +enum buildMsgState { + BUILD_MSG_BEGIN = 0, + BUILD_MSG_SIZE, + BUILD_MSG_HASH, + BUILD_MSG_VERIFY_MAC, + BUILD_MSG_ENCRYPT, +}; + +/* sub-states for cipher operations */ +enum cipherState { + CIPHER_STATE_BEGIN = 0, + CIPHER_STATE_DO, + CIPHER_STATE_END, +}; + +typedef struct Options { +#ifndef NO_PSK + wc_psk_client_callback client_psk_cb; + wc_psk_server_callback server_psk_cb; +#ifdef WOLFSSL_TLS13 + wc_psk_client_tls13_callback client_psk_tls13_cb; /* client callback */ + wc_psk_server_tls13_callback server_psk_tls13_cb; /* server callback */ +#endif +#endif /* NO_PSK */ +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) + unsigned long mask; /* store SSL_OP_ flags */ +#endif + + /* on/off or small bit flags, optimize layout */ +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + word16 havePSK:1; /* psk key set by user */ +#endif /* HAVE_SESSION_TICKET || !NO_PSK */ + word16 sendVerify:2; /* false = 0, true = 1, sendBlank = 2 */ + word16 sessionCacheOff:1; + word16 sessionCacheFlushOff:1; +#ifdef HAVE_EXT_CACHE + word16 internalCacheOff:1; +#endif + word16 side:2; /* client, server or neither end */ + word16 verifyPeer:1; + word16 verifyNone:1; + word16 failNoCert:1; + word16 failNoCertxPSK:1; /* fail for no cert except with PSK */ + word16 downgrade:1; /* allow downgrade of versions */ + word16 resuming:1; + word16 haveSessionId:1; /* server may not send */ + word16 tls:1; /* using TLS ? */ + word16 tls1_1:1; /* using TLSv1.1+ ? */ + word16 tls1_3:1; /* using TLSv1.3+ ? */ + word16 dtls:1; /* using datagrams ? */ + word16 connReset:1; /* has the peer reset */ + word16 isClosed:1; /* if we consider conn closed */ + word16 closeNotify:1; /* we've received a close notify */ + word16 sentNotify:1; /* we've sent a close notify */ + word16 usingCompression:1; /* are we using compression */ + word16 haveRSA:1; /* RSA available */ + word16 haveECC:1; /* ECC available */ + word16 haveDH:1; /* server DH parms set by user */ + word16 haveNTRU:1; /* server NTRU private key loaded */ + word16 haveQSH:1; /* have QSH ability */ + word16 haveECDSAsig:1; /* server ECDSA signed cert */ + word16 haveStaticECC:1; /* static server ECC private key */ + word16 havePeerCert:1; /* do we have peer's cert */ + word16 havePeerVerify:1; /* and peer's cert verify */ + word16 usingPSK_cipher:1; /* are using psk as cipher */ + word16 usingAnon_cipher:1; /* are we using an anon cipher */ + word16 noPskDheKe:1; /* Don't use (EC)DHE with PSK */ + word16 sendAlertState:1; /* nonblocking resume */ + word16 partialWrite:1; /* only one msg per write call */ + word16 quietShutdown:1; /* don't send close notify */ + word16 certOnly:1; /* stop once we get cert */ + word16 groupMessages:1; /* group handshake messages */ + word16 saveArrays:1; /* save array Memory for user get keys + or psk */ + word16 weOwnRng:1; /* will be true unless CTX owns */ + word16 haveEMS:1; /* using extended master secret */ +#ifdef HAVE_POLY1305 + word16 oldPoly:1; /* set when to use old rfc way of poly*/ +#endif +#ifdef HAVE_ANON + word16 haveAnon:1; /* User wants to allow Anon suites */ +#endif +#ifdef HAVE_SESSION_TICKET + word16 createTicket:1; /* Server to create new Ticket */ + word16 useTicket:1; /* Use Ticket not session cache */ + word16 rejectTicket:1; /* Callback rejected ticket */ +#ifdef WOLFSSL_TLS13 + word16 noTicketTls13:1; /* Server won't create new Ticket */ +#endif +#endif +#ifdef WOLFSSL_DTLS + word16 dtlsUseNonblock:1; /* are we using nonblocking socket */ + word16 dtlsHsRetain:1; /* DTLS retaining HS data */ + word16 haveMcast:1; /* using multicast ? */ +#ifdef WOLFSSL_SCTP + word16 dtlsSctp:1; /* DTLS-over-SCTP mode */ +#endif +#endif +#if defined(HAVE_TLS_EXTENSIONS) && defined(HAVE_SUPPORTED_CURVES) + word16 userCurves:1; /* indicates user called wolfSSL_UseSupportedCurve */ +#endif + word16 keepResources:1; /* Keep resources after handshake */ + word16 useClientOrder:1; /* Use client's cipher order */ +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) + word16 postHandshakeAuth:1;/* Client send post_handshake_auth + * extension */ +#endif +#if defined(WOLFSSL_TLS13) && !defined(NO_WOLFSSL_SERVER) + word16 sendCookie:1; /* Server creates a Cookie in HRR */ +#endif +#ifdef WOLFSSL_ALT_CERT_CHAINS + word16 usingAltCertChain:1;/* Alternate cert chain was used */ +#endif +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_TLS13_MIDDLEBOX_COMPAT) + word16 sentChangeCipher:1; /* Change Cipher Spec sent */ +#endif +#if !defined(WOLFSSL_NO_CLIENT_AUTH) && defined(HAVE_ED25519) && \ + !defined(NO_ED25519_CLIENT_AUTH) + word16 cacheMessages:1; /* Cache messages for sign/verify */ +#endif +#ifndef NO_DH + #if !defined(WOLFSSL_OLD_PRIME_CHECK) && \ + !defined(HAVE_FIPS) && !defined(HAVE_SELFTEST) + word16 dhDoKeyTest:1; /* Need to do the DH Key prime test */ + word16 dhKeyTested:1; /* Set when key has been tested. */ + #endif +#endif +#ifdef SINGLE_THREADED + word16 ownSuites:1; /* if suites are malloced in ssl object */ +#endif + + /* need full byte values for this section */ + byte processReply; /* nonblocking resume */ + byte cipherSuite0; /* first byte, normally 0 */ + byte cipherSuite; /* second byte, actual suite */ + byte serverState; + byte clientState; + byte handShakeState; + byte handShakeDone; /* at least one handshake complete */ + byte minDowngrade; /* minimum downgrade version */ + byte connectState; /* nonblocking resume */ + byte acceptState; /* nonblocking resume */ + byte asyncState; /* sub-state for enum asyncState */ + byte buildMsgState; /* sub-state for enum buildMsgState */ + byte alertCount; /* detect warning dos attempt */ +#ifdef WOLFSSL_MULTICAST + word16 mcastID; /* Multicast group ID */ +#endif +#ifndef NO_DH + word16 minDhKeySz; /* minimum DH key size */ + word16 maxDhKeySz; /* minimum DH key size */ + word16 dhKeySz; /* actual DH key size */ +#endif +#ifndef NO_RSA + short minRsaKeySz; /* minimum RSA key size */ +#endif +#if defined(HAVE_ECC) || defined(HAVE_ED25519) + short minEccKeySz; /* minimum ECC key size */ +#endif +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + byte verifyDepth; /* maximum verification depth */ +#endif +#ifdef WOLFSSL_EARLY_DATA + word16 pskIdIndex; + word32 maxEarlyDataSz; +#endif +#ifdef WOLFSSL_TLS13 + byte oldMinor; /* client preferred version < TLS 1.3 */ +#endif +} Options; + +typedef struct Arrays { + byte* pendingMsg; /* defrag buffer */ + byte* preMasterSecret; + word32 preMasterSz; /* differs for DH, actual size */ + word32 pendingMsgSz; /* defrag buffer size */ + word32 pendingMsgOffset; /* current offset into defrag buffer */ +#if defined(HAVE_SESSION_TICKET) || !defined(NO_PSK) + word32 psk_keySz; /* actual size */ + char client_identity[MAX_PSK_ID_LEN + NULL_TERM_LEN]; + char server_hint[MAX_PSK_ID_LEN + NULL_TERM_LEN]; + byte psk_key[MAX_PSK_KEY_LEN]; +#endif + byte clientRandom[RAN_LEN]; + byte serverRandom[RAN_LEN]; + byte sessionID[ID_LEN]; + byte sessionIDSz; +#ifdef WOLFSSL_TLS13 + byte secret[SECRET_LEN]; +#endif + byte masterSecret[SECRET_LEN]; +#ifdef WOLFSSL_DTLS + byte cookie[MAX_COOKIE_LEN]; + byte cookieSz; +#endif + byte pendingMsgType; /* defrag buffer message type */ +} Arrays; + +#ifndef ASN_NAME_MAX +#define ASN_NAME_MAX 256 +#endif + +#ifndef MAX_DATE_SZ +#define MAX_DATE_SZ 32 +#endif + +struct WOLFSSL_STACK { + unsigned long num; /* number of nodes in stack + * (safety measure for freeing and shortcut for count) */ + union { + WOLFSSL_X509* x509; + WOLFSSL_X509_NAME* name; + WOLFSSL_BIO* bio; + WOLFSSL_ASN1_OBJECT* obj; + char* string; + } data; + WOLFSSL_STACK* next; +}; + + +struct WOLFSSL_X509_NAME { + char *name; + int dynamicName; + int sz; + char staticName[ASN_NAME_MAX]; +#if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \ + !defined(NO_ASN) + DecodedName fullName; + WOLFSSL_X509_NAME_ENTRY cnEntry; + WOLFSSL_X509_NAME_ENTRY extra[MAX_NAME_ENTRIES]; /* extra entries added */ + WOLFSSL_X509* x509; /* x509 that struct belongs to */ +#endif /* OPENSSL_EXTRA */ +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) + byte raw[ASN_NAME_MAX]; + int rawLen; +#endif +}; + +#ifndef EXTERNAL_SERIAL_SIZE + #define EXTERNAL_SERIAL_SIZE 32 +#endif + +#ifdef NO_ASN + typedef struct DNS_entry DNS_entry; +#endif + +struct WOLFSSL_X509 { + int version; + int serialSz; +#ifdef WOLFSSL_SEP + int deviceTypeSz; + int hwTypeSz; + byte deviceType[EXTERNAL_SERIAL_SIZE]; + byte hwType[EXTERNAL_SERIAL_SIZE]; + int hwSerialNumSz; + byte hwSerialNum[EXTERNAL_SERIAL_SIZE]; + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + byte certPolicySet; + byte certPolicyCrit; + #endif /* OPENSSL_EXTRA */ +#endif + int notBeforeSz; + int notAfterSz; + byte notBefore[MAX_DATE_SZ]; + byte notAfter[MAX_DATE_SZ]; + buffer sig; + int sigOID; + DNS_entry* altNames; /* alt names list */ + buffer pubKey; + int pubKeyOID; + DNS_entry* altNamesNext; /* hint for retrieval */ + #if defined(HAVE_ECC) || defined(HAVE_ED25519) + word32 pkCurveOID; + #endif /* HAVE_ECC */ + #ifndef NO_CERTS + DerBuffer* derCert; /* may need */ + #endif + void* heap; /* heap hint */ + byte dynamicMemory; /* dynamic memory flag */ + byte isCa:1; +#ifdef WOLFSSL_CERT_EXT + char certPolicies[MAX_CERTPOL_NB][MAX_CERTPOL_SZ]; + int certPoliciesNb; +#endif /* WOLFSSL_CERT_EXT */ +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) +#ifdef HAVE_EX_DATA + void* ex_data[MAX_EX_DATA]; +#endif + byte* authKeyId; + byte* subjKeyId; + byte* extKeyUsageSrc; + const byte* CRLInfo; + byte* authInfo; + word32 pathLength; + word16 keyUsage; + int CRLInfoSz; + int authInfoSz; + word32 authKeyIdSz; + word32 subjKeyIdSz; + word32 extKeyUsageSz; + word32 extKeyUsageCount; + + byte CRLdistSet:1; + byte CRLdistCrit:1; + byte authInfoSet:1; + byte authInfoCrit:1; + byte keyUsageSet:1; + byte keyUsageCrit:1; + byte extKeyUsageCrit:1; + byte subjKeyIdSet:1; + + byte subjKeyIdCrit:1; + byte basicConstSet:1; + byte basicConstCrit:1; + byte basicConstPlSet:1; + byte subjAltNameSet:1; + byte subjAltNameCrit:1; + byte authKeyIdSet:1; + byte authKeyIdCrit:1; +#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ + byte serial[EXTERNAL_SERIAL_SIZE]; + char subjectCN[ASN_NAME_MAX]; /* common name short cut */ +#ifdef WOLFSSL_CERT_REQ + char challengePw[CTC_NAME_SIZE]; /* for REQ certs */ +#endif + WOLFSSL_X509_NAME issuer; + WOLFSSL_X509_NAME subject; +}; + + +/* record layer header for PlainText, Compressed, and CipherText */ +typedef struct RecordLayerHeader { + byte type; + byte pvMajor; + byte pvMinor; + byte length[2]; +} RecordLayerHeader; + + +/* record layer header for DTLS PlainText, Compressed, and CipherText */ +typedef struct DtlsRecordLayerHeader { + byte type; + byte pvMajor; + byte pvMinor; + byte sequence_number[8]; /* per record */ + byte length[2]; +} DtlsRecordLayerHeader; + + +typedef struct DtlsFrag { + word32 begin; + word32 end; + struct DtlsFrag* next; +} DtlsFrag; + + +typedef struct DtlsMsg { + struct DtlsMsg* next; + byte* buf; + byte* msg; + DtlsFrag* fragList; + word32 fragSz; /* Length of fragments received */ + word32 seq; /* Handshake sequence number */ + word32 sz; /* Length of whole message */ + byte type; +} DtlsMsg; + + +#ifdef HAVE_NETX + + /* NETX I/O Callback default */ + typedef struct NetX_Ctx { + NX_TCP_SOCKET* nxSocket; /* send/recv socket handle */ + NX_PACKET* nxPacket; /* incoming packet handle for short reads */ + ULONG nxOffset; /* offset already read from nxPacket */ + ULONG nxWait; /* wait option flag */ + } NetX_Ctx; + +#endif + +/* Handshake messages received from peer (plus change cipher */ +typedef struct MsgsReceived { + word16 got_hello_request:1; + word16 got_client_hello:2; + word16 got_server_hello:2; + word16 got_hello_verify_request:1; + word16 got_session_ticket:1; + word16 got_end_of_early_data:1; + word16 got_hello_retry_request:1; + word16 got_encrypted_extensions:1; + word16 got_certificate:1; + word16 got_certificate_status:1; + word16 got_server_key_exchange:1; + word16 got_certificate_request:1; + word16 got_server_hello_done:1; + word16 got_certificate_verify:1; + word16 got_client_key_exchange:1; + word16 got_finished:1; + word16 got_key_update:1; + word16 got_change_cipher:1; +} MsgsReceived; + + +/* Handshake hashes */ +typedef struct HS_Hashes { + Hashes verifyHashes; + Hashes certHashes; /* for cert verify */ +#ifndef NO_SHA + wc_Sha hashSha; /* sha hash of handshake msgs */ +#endif +#if !defined(NO_MD5) && !defined(NO_OLD_TLS) + wc_Md5 hashMd5; /* md5 hash of handshake msgs */ +#endif +#ifndef NO_SHA256 + wc_Sha256 hashSha256; /* sha256 hash of handshake msgs */ +#endif +#ifdef WOLFSSL_SHA384 + wc_Sha384 hashSha384; /* sha384 hash of handshake msgs */ +#endif +#ifdef WOLFSSL_SHA512 + wc_Sha512 hashSha512; /* sha512 hash of handshake msgs */ +#endif +#if defined(HAVE_ED25519) && !defined(WOLFSSL_NO_CLIENT_AUTH) + byte* messages; /* handshake messages */ + int length; /* length of handshake messages' data */ + int prevLen; /* length of messages but last */ +#endif +} HS_Hashes; + + +#ifdef WOLFSSL_ASYNC_CRYPT + #define MAX_ASYNC_ARGS 18 + typedef void (*FreeArgsCb)(struct WOLFSSL* ssl, void* pArgs); + + struct WOLFSSL_ASYNC { + WC_ASYNC_DEV* dev; + FreeArgsCb freeArgs; /* function pointer to cleanup args */ + word32 args[MAX_ASYNC_ARGS]; /* holder for current args */ + }; +#endif + +#ifdef HAVE_WRITE_DUP + + #define WRITE_DUP_SIDE 1 + #define READ_DUP_SIDE 2 + + typedef struct WriteDup { + wolfSSL_Mutex dupMutex; /* reference count mutex */ + int dupCount; /* reference count */ + int dupErr; /* under dupMutex, pass to other side */ + } WriteDup; + + WOLFSSL_LOCAL void FreeWriteDup(WOLFSSL* ssl); + WOLFSSL_LOCAL int NotifyWriteSide(WOLFSSL* ssl, int err); +#endif /* HAVE_WRITE_DUP */ + +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) +typedef struct CertReqCtx CertReqCtx; + +struct CertReqCtx { + CertReqCtx* next; + byte len; + byte ctx; +}; +#endif + +#ifdef WOLFSSL_EARLY_DATA +typedef enum EarlyDataState { + no_early_data, + expecting_early_data, + process_early_data, + done_early_data +} EarlyDataState; +#endif + +/* wolfSSL ssl type */ +struct WOLFSSL { + WOLFSSL_CTX* ctx; + Suites* suites; /* only need during handshake */ + Arrays* arrays; +#ifdef WOLFSSL_TLS13 + byte clientSecret[SECRET_LEN]; + byte serverSecret[SECRET_LEN]; +#endif + HS_Hashes* hsHashes; + void* IOCB_ReadCtx; + void* IOCB_WriteCtx; + WC_RNG* rng; + void* verifyCbCtx; /* cert verify callback user ctx*/ + VerifyCallback verifyCallback; /* cert verification callback */ + void* heap; /* for user overrides */ +#ifdef HAVE_WRITE_DUP + WriteDup* dupWrite; /* valid pointer indicates ON */ + /* side that decrements dupCount to zero frees overall structure */ + byte dupSide; /* write side or read side */ +#endif +#ifdef OPENSSL_EXTRA + byte cbioFlag; /* WOLFSSL_CBIO_RECV/SEND: CBIORecv/Send is set */ +#endif + CallbackIORecv CBIORecv; + CallbackIOSend CBIOSend; +#ifdef WOLFSSL_STATIC_MEMORY + WOLFSSL_HEAP_HINT heap_hint; +#endif +#ifndef NO_HANDSHAKE_DONE_CB + HandShakeDoneCb hsDoneCb; /* notify user handshake done */ + void* hsDoneCtx; /* user handshake cb context */ +#endif +#ifdef WOLFSSL_ASYNC_CRYPT + struct WOLFSSL_ASYNC async; +#elif defined(WOLFSSL_NONBLOCK_OCSP) + void* nonblockarg; /* dynamic arg for handling non-block resume */ +#endif + void* hsKey; /* Handshake key (RsaKey or ecc_key) allocated from heap */ + word32 hsType; /* Type of Handshake key (hsKey) */ + WOLFSSL_CIPHER cipher; +#ifndef WOLFSSL_AEAD_ONLY + hmacfp hmac; +#endif + Ciphers encrypt; + Ciphers decrypt; + Buffers buffers; + WOLFSSL_SESSION session; +#ifdef HAVE_EXT_CACHE + WOLFSSL_SESSION* extSession; +#endif + WOLFSSL_ALERT_HISTORY alert_history; + int error; + int rfd; /* read file descriptor */ + int wfd; /* write file descriptor */ + int rflags; /* user read flags */ + int wflags; /* user write flags */ + word32 timeout; /* session timeout */ + word32 fragOffset; /* fragment offset */ + word16 curSize; + byte verifyDepth; + RecordLayerHeader curRL; + MsgsReceived msgsReceived; /* peer messages received */ + ProtocolVersion version; /* negotiated version */ + ProtocolVersion chVersion; /* client hello version */ + CipherSpecs specs; + Keys keys; + Options options; +#ifdef OPENSSL_EXTRA + CallbackInfoState* CBIS; /* used to get info about SSL state */ + int cbmode; /* read or write on info callback */ + int cbtype; /* event type in info callback */ + WOLFSSL_BIO* biord; /* socket bio read to free/close */ + WOLFSSL_BIO* biowr; /* socket bio write to free/close */ + byte sessionCtx[ID_LEN]; /* app session context ID */ +#endif +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + unsigned long peerVerifyRet; +#endif +#ifdef OPENSSL_EXTRA + byte readAhead; + byte sessionCtxSz; /* size of sessionCtx stored */ +#ifdef HAVE_PK_CALLBACKS + void* loggingCtx; /* logging callback argument */ +#endif +#endif /* OPENSSL_EXTRA */ +#ifndef NO_RSA + RsaKey* peerRsaKey; + byte peerRsaKeyPresent; +#endif +#ifdef HAVE_QSH + QSHKey* QSH_Key; + QSHKey* peerQSHKey; + QSHSecret* QSH_secret; + byte isQSH; /* is the handshake a QSH? */ + byte sendQSHKeys; /* flag for if the client should sen + public keys */ + byte peerQSHKeyPresent; + byte minRequest; + byte maxRequest; + byte user_set_QSHSchemes; +#endif +#if defined(WOLFSSL_TLS13) || defined(HAVE_FFDHE) + word16 namedGroup; +#endif +#ifdef WOLFSSL_TLS13 + word16 group[WOLFSSL_MAX_GROUP_COUNT]; + byte numGroups; +#endif + word16 pssAlgo; +#ifdef WOLFSSL_TLS13 + #if !defined(WOLFSSL_TLS13_DRAFT_18) && !defined(WOLFSSL_TLS13_DRAFT_22) + word16 certHashSigAlgoSz; /* SigAlgoCert ext length in bytes */ + byte certHashSigAlgo[WOLFSSL_MAX_SIGALGO]; /* cert sig/algo to + * offer */ + #endif /* !WOLFSSL_TLS13_DRAFT_18 && !WOLFSSL_TLS13_DRAFT_22 */ +#endif +#ifdef HAVE_NTRU + word16 peerNtruKeyLen; + byte peerNtruKey[MAX_NTRU_PUB_KEY_SZ]; + byte peerNtruKeyPresent; +#endif +#if defined(HAVE_ECC) || defined(HAVE_ED25519) + int eccVerifyRes; +#endif +#if defined(HAVE_ECC) || defined(HAVE_CURVE25519) + word32 ecdhCurveOID; /* curve Ecc_Sum */ + ecc_key* eccTempKey; /* private ECDHE key */ + byte eccTempKeyPresent; /* also holds type */ + byte peerEccKeyPresent; +#endif +#ifdef HAVE_ECC + ecc_key* peerEccKey; /* peer's ECDHE key */ + ecc_key* peerEccDsaKey; /* peer's ECDSA key */ + word16 eccTempKeySz; /* in octets 20 - 66 */ + byte peerEccDsaKeyPresent; +#endif +#if defined(HAVE_ECC) || defined(HAVE_ED25519) + word32 pkCurveOID; /* curve Ecc_Sum */ +#endif +#ifdef HAVE_ED25519 + ed25519_key* peerEd25519Key; + byte peerEd25519KeyPresent; +#endif +#ifdef HAVE_CURVE25519 + curve25519_key* peerX25519Key; + byte peerX25519KeyPresent; +#endif +#ifdef HAVE_LIBZ + z_stream c_stream; /* compression stream */ + z_stream d_stream; /* decompression stream */ + byte didStreamInit; /* for stream init and end */ +#endif +#ifdef WOLFSSL_DTLS + int dtls_timeout_init; /* starting timeout value */ + int dtls_timeout_max; /* maximum timeout value */ + int dtls_timeout; /* current timeout value, changes */ + word32 dtls_tx_msg_list_sz; + word32 dtls_rx_msg_list_sz; + DtlsMsg* dtls_tx_msg_list; + DtlsMsg* dtls_tx_msg; + DtlsMsg* dtls_rx_msg_list; + void* IOCB_CookieCtx; /* gen cookie ctx */ + word32 dtls_expected_rx; +#ifdef WOLFSSL_SESSION_EXPORT + wc_dtls_export dtls_export; /* export function for session */ +#endif +#ifdef WOLFSSL_SCTP + word16 dtlsMtuSz; +#endif /* WOLFSSL_SCTP */ +#ifdef WOLFSSL_MULTICAST + void* mcastHwCbCtx; /* Multicast highwater callback ctx */ +#endif /* WOLFSSL_MULTICAST */ +#ifdef WOLFSSL_DTLS_DROP_STATS + word32 macDropCount; + word32 replayDropCount; +#endif /* WOLFSSL_DTLS_DROP_STATS */ +#endif /* WOLFSSL_DTLS */ +#ifdef WOLFSSL_CALLBACKS + TimeoutInfo timeoutInfo; /* info saved during handshake */ + HandShakeInfo handShakeInfo; /* info saved during handshake */ +#endif +#ifdef OPENSSL_EXTRA + SSL_Msg_Cb protoMsgCb; /* inspect protocol message callback */ + void* protoMsgCtx; /* user set context with msg callback */ +#endif +#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) + byte hsInfoOn; /* track handshake info */ + byte toInfoOn; /* track timeout info */ +#endif +#ifdef HAVE_FUZZER + CallbackFuzzer fuzzerCb; /* for testing with using fuzzer */ + void* fuzzerCtx; /* user defined pointer */ +#endif +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_POST_HANDSHAKE_AUTH) + CertReqCtx* certReqCtx; +#endif +#ifdef KEEP_PEER_CERT + WOLFSSL_X509 peerCert; /* X509 peer cert */ +#endif +#ifdef KEEP_OUR_CERT + WOLFSSL_X509* ourCert; /* keep alive a X509 struct of cert. + points to ctx if not owned (owned + flag found in buffers.weOwnCert) */ +#endif + byte keepCert; /* keep certificate after handshake */ +#if defined(HAVE_EX_DATA) || defined(FORTRESS) + void* ex_data[MAX_EX_DATA]; /* external data, for Fortress */ +#endif + int devId; /* async device id to use */ +#ifdef HAVE_ONE_TIME_AUTH + OneTimeAuth auth; +#endif +#ifdef HAVE_TLS_EXTENSIONS + TLSX* extensions; /* RFC 6066 TLS Extensions data */ + #ifdef HAVE_MAX_FRAGMENT + word16 max_fragment; + #endif + #ifdef HAVE_TRUNCATED_HMAC + byte truncated_hmac; + #endif + #ifdef HAVE_CERTIFICATE_STATUS_REQUEST + byte status_request; + #endif + #ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 + byte status_request_v2; + #endif + #if defined(HAVE_SECURE_RENEGOTIATION) \ + || defined(HAVE_SERVER_RENEGOTIATION_INFO) + SecureRenegotiation* secure_renegotiation; /* valid pointer indicates */ + #endif /* user turned on */ + #ifdef HAVE_ALPN + char* alpn_client_list; /* keep the client's list */ + #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + CallbackALPNSelect alpnSelect; + void* alpnSelectArg; + #endif + #endif /* of accepted protocols */ + #if !defined(NO_WOLFSSL_CLIENT) && defined(HAVE_SESSION_TICKET) + CallbackSessionTicket session_ticket_cb; + void* session_ticket_ctx; + byte expect_session_ticket; + #endif +#endif /* HAVE_TLS_EXTENSIONS */ +#ifdef HAVE_OCSP + void* ocspIOCtx; + #ifdef OPENSSL_EXTRA + byte* ocspResp; + int ocspRespSz; + #if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + char* url; + #endif + #endif +#endif +#ifdef HAVE_NETX + NetX_Ctx nxCtx; /* NetX IO Context */ +#endif +#if defined(WOLFSSL_APACHE_MYNEWT) && !defined(WOLFSSL_LWIP) + void* mnCtx; /* mynewt mn_socket IO Context */ +#endif /* defined(WOLFSSL_APACHE_MYNEWT) && !defined(WOLFSSL_LWIP) */ +#ifdef SESSION_INDEX + int sessionIndex; /* Session's location in the cache. */ +#endif +#ifdef ATOMIC_USER + void* MacEncryptCtx; /* Atomic User Mac/Encrypt Callback Context */ + void* DecryptVerifyCtx; /* Atomic User Decrypt/Verify Callback Context */ +#endif +#ifdef HAVE_PK_CALLBACKS + #ifdef HAVE_ECC + void* EccKeyGenCtx; /* EccKeyGen Callback Context */ + void* EccSignCtx; /* Ecc Sign Callback Context */ + void* EccVerifyCtx; /* Ecc Verify Callback Context */ + void* EccSharedSecretCtx; /* Ecc Pms Callback Context */ + #ifdef HAVE_ED25519 + void* Ed25519SignCtx; /* ED25519 Sign Callback Context */ + void* Ed25519VerifyCtx; /* ED25519 Verify Callback Context */ + #endif + #ifdef HAVE_CURVE25519 + void* X25519KeyGenCtx; /* X25519 KeyGen Callback Context */ + void* X25519SharedSecretCtx; /* X25519 Pms Callback Context */ + #endif + #endif /* HAVE_ECC */ + #ifndef NO_DH + void* DhAgreeCtx; /* DH Pms Callback Context */ + #endif /* !NO_DH */ + #ifndef NO_RSA + void* RsaSignCtx; /* Rsa Sign Callback Context */ + void* RsaVerifyCtx; /* Rsa Verify Callback Context */ + #ifdef WC_RSA_PSS + void* RsaPssSignCtx; /* Rsa PSS Sign Callback Context */ + void* RsaPssVerifyCtx; /* Rsa PSS Verify Callback Context */ + #endif + void* RsaEncCtx; /* Rsa Public Encrypt Callback Context */ + void* RsaDecCtx; /* Rsa Private Decrypt Callback Context */ + #endif /* NO_RSA */ +#endif /* HAVE_PK_CALLBACKS */ +#ifdef HAVE_SECRET_CALLBACK + SessionSecretCb sessionSecretCb; + void* sessionSecretCtx; +#endif /* HAVE_SECRET_CALLBACK */ +#ifdef WOLFSSL_JNI + void* jObjectRef; /* reference to WolfSSLSession in JNI wrapper */ +#endif /* WOLFSSL_JNI */ +#ifdef WOLFSSL_EARLY_DATA + EarlyDataState earlyData; + word32 earlyDataSz; +#endif +}; + + +WOLFSSL_LOCAL +int SetSSL_CTX(WOLFSSL*, WOLFSSL_CTX*, int); +WOLFSSL_LOCAL +int InitSSL(WOLFSSL*, WOLFSSL_CTX*, int); +WOLFSSL_LOCAL +void FreeSSL(WOLFSSL*, void* heap); +WOLFSSL_API void SSL_ResourceFree(WOLFSSL*); /* Micrium uses */ + + + +#ifndef NO_CERTS + + WOLFSSL_LOCAL int ProcessBuffer(WOLFSSL_CTX* ctx, const unsigned char* buff, + long sz, int format, int type, WOLFSSL* ssl, + long* used, int userChain); + WOLFSSL_LOCAL int ProcessFile(WOLFSSL_CTX* ctx, const char* fname, int format, + int type, WOLFSSL* ssl, int userChain, + WOLFSSL_CRL* crl); + + #ifdef OPENSSL_EXTRA + WOLFSSL_LOCAL int CheckHostName(DecodedCert* dCert, char *domainName, + size_t domainNameLen); + #endif +#endif + + +#if defined(WOLFSSL_CALLBACKS) || defined(OPENSSL_EXTRA) + WOLFSSL_LOCAL + void InitHandShakeInfo(HandShakeInfo*, WOLFSSL*); + WOLFSSL_LOCAL + void FinishHandShakeInfo(HandShakeInfo*); + WOLFSSL_LOCAL + void AddPacketName(WOLFSSL* ssl, const char* name); + + WOLFSSL_LOCAL + void InitTimeoutInfo(TimeoutInfo*); + WOLFSSL_LOCAL + void FreeTimeoutInfo(TimeoutInfo*, void*); + WOLFSSL_LOCAL + void AddPacketInfo(WOLFSSL* ssl, const char* name, int type, + const byte* data, int sz, int write, void* heap); + WOLFSSL_LOCAL + void AddLateName(const char*, TimeoutInfo*); + WOLFSSL_LOCAL + void AddLateRecordHeader(const RecordLayerHeader* rl, TimeoutInfo* info); +#endif + + +/* Record Layer Header identifier from page 12 */ +enum ContentType { + no_type = 0, + change_cipher_spec = 20, + alert = 21, + handshake = 22, + application_data = 23 +}; + + +/* handshake header, same for each message type, pgs 20/21 */ +typedef struct HandShakeHeader { + byte type; + word24 length; +} HandShakeHeader; + + +/* DTLS handshake header, same for each message type */ +typedef struct DtlsHandShakeHeader { + byte type; + word24 length; + byte message_seq[2]; /* start at 0, retransmit gets same # */ + word24 fragment_offset; /* bytes in previous fragments */ + word24 fragment_length; /* length of this fragment */ +} DtlsHandShakeHeader; + + +enum HandShakeType { + hello_request = 0, + client_hello = 1, + server_hello = 2, + hello_verify_request = 3, /* DTLS addition */ + session_ticket = 4, + end_of_early_data = 5, + hello_retry_request = 6, + encrypted_extensions = 8, + certificate = 11, + server_key_exchange = 12, + certificate_request = 13, + server_hello_done = 14, + certificate_verify = 15, + client_key_exchange = 16, + finished = 20, + certificate_status = 22, + key_update = 24, + change_cipher_hs = 55, /* simulate unique handshake type for sanity + checks. record layer change_cipher + conflicts with handshake finished */ + message_hash = 254, /* synthetic message type for TLS v1.3 */ + no_shake = 255 /* used to initialize the DtlsMsg record */ +}; + +enum ProvisionSide { + PROVISION_CLIENT = 1, + PROVISION_SERVER = 2, + PROVISION_CLIENT_SERVER = 3 +}; + + +static const byte client[SIZEOF_SENDER] = { 0x43, 0x4C, 0x4E, 0x54 }; +static const byte server[SIZEOF_SENDER] = { 0x53, 0x52, 0x56, 0x52 }; + +static const byte tls_client[FINISHED_LABEL_SZ + 1] = "client finished"; +static const byte tls_server[FINISHED_LABEL_SZ + 1] = "server finished"; + + +/* internal functions */ +WOLFSSL_LOCAL int SendChangeCipher(WOLFSSL*); +WOLFSSL_LOCAL int SendTicket(WOLFSSL*); +WOLFSSL_LOCAL int DoClientTicket(WOLFSSL*, const byte*, word32); +WOLFSSL_LOCAL int SendData(WOLFSSL*, const void*, int); +#ifdef WOLFSSL_TLS13 +#ifdef WOLFSSL_TLS13_DRAFT_18 +WOLFSSL_LOCAL int SendTls13HelloRetryRequest(WOLFSSL*); +#else +WOLFSSL_LOCAL int SendTls13ServerHello(WOLFSSL*, byte); +#endif +#endif +WOLFSSL_LOCAL int SendCertificate(WOLFSSL*); +WOLFSSL_LOCAL int SendCertificateRequest(WOLFSSL*); +#if defined(HAVE_CERTIFICATE_STATUS_REQUEST) \ + || defined(HAVE_CERTIFICATE_STATUS_REQUEST_V2) +WOLFSSL_LOCAL int CreateOcspResponse(WOLFSSL*, OcspRequest**, buffer*); +#endif +#if defined(HAVE_SECURE_RENEGOTIATION) && \ + defined(HAVE_SERVER_RENEGOTIATION_INFO) +WOLFSSL_LOCAL int SendHelloRequest(WOLFSSL*); +#endif +WOLFSSL_LOCAL int SendCertificateStatus(WOLFSSL*); +WOLFSSL_LOCAL int SendServerKeyExchange(WOLFSSL*); +WOLFSSL_LOCAL int SendBuffered(WOLFSSL*); +WOLFSSL_LOCAL int ReceiveData(WOLFSSL*, byte*, int, int); +WOLFSSL_LOCAL int SendFinished(WOLFSSL*); +WOLFSSL_LOCAL int SendAlert(WOLFSSL*, int, int); +WOLFSSL_LOCAL int ProcessReply(WOLFSSL*); + +WOLFSSL_LOCAL int SetCipherSpecs(WOLFSSL*); +WOLFSSL_LOCAL int MakeMasterSecret(WOLFSSL*); + +WOLFSSL_LOCAL int AddSession(WOLFSSL*); +WOLFSSL_LOCAL int DeriveKeys(WOLFSSL* ssl); +WOLFSSL_LOCAL int StoreKeys(WOLFSSL* ssl, const byte* keyData, int side); + +WOLFSSL_LOCAL int IsTLS(const WOLFSSL* ssl); +WOLFSSL_LOCAL int IsAtLeastTLSv1_2(const WOLFSSL* ssl); +WOLFSSL_LOCAL int IsAtLeastTLSv1_3(const ProtocolVersion pv); + +WOLFSSL_LOCAL void FreeHandshakeResources(WOLFSSL* ssl); +WOLFSSL_LOCAL void ShrinkInputBuffer(WOLFSSL* ssl, int forcedFree); +WOLFSSL_LOCAL void ShrinkOutputBuffer(WOLFSSL* ssl); + +WOLFSSL_LOCAL int VerifyClientSuite(WOLFSSL* ssl); + +WOLFSSL_LOCAL int SetTicket(WOLFSSL*, const byte*, word32); +WOLFSSL_LOCAL int wolfSSL_GetMaxRecordSize(WOLFSSL* ssl, int maxFragment); + +#ifndef NO_CERTS + #ifndef NO_RSA + #ifdef WC_RSA_PSS + WOLFSSL_LOCAL int CheckRsaPssPadding(const byte* plain, word32 plainSz, + byte* out, word32 sigSz, enum wc_HashType hashType); + WOLFSSL_LOCAL int ConvertHashPss(int hashAlgo, + enum wc_HashType* hashType, int* mgf); + #endif + WOLFSSL_LOCAL int VerifyRsaSign(WOLFSSL* ssl, byte* verifySig, + word32 sigSz, const byte* plain, word32 plainSz, int sigAlgo, + int hashAlgo, RsaKey* key, DerBuffer* keyBufInfo); + WOLFSSL_LOCAL int RsaSign(WOLFSSL* ssl, const byte* in, word32 inSz, + byte* out, word32* outSz, int sigAlgo, int hashAlgo, RsaKey* key, + DerBuffer* keyBufInfo); + WOLFSSL_LOCAL int RsaVerify(WOLFSSL* ssl, byte* in, word32 inSz, + byte** out, int sigAlgo, int hashAlgo, RsaKey* key, + buffer* keyBufInfo); + WOLFSSL_LOCAL int RsaDec(WOLFSSL* ssl, byte* in, word32 inSz, byte** out, + word32* outSz, RsaKey* key, DerBuffer* keyBufInfo); + WOLFSSL_LOCAL int RsaEnc(WOLFSSL* ssl, const byte* in, word32 inSz, byte* out, + word32* outSz, RsaKey* key, buffer* keyBufInfo); + #endif /* !NO_RSA */ + + #ifdef HAVE_ECC + WOLFSSL_LOCAL int EccSign(WOLFSSL* ssl, const byte* in, word32 inSz, + byte* out, word32* outSz, ecc_key* key, DerBuffer* keyBufInfo); + WOLFSSL_LOCAL int EccVerify(WOLFSSL* ssl, const byte* in, word32 inSz, + const byte* out, word32 outSz, ecc_key* key, buffer* keyBufInfo); + WOLFSSL_LOCAL int EccSharedSecret(WOLFSSL* ssl, ecc_key* priv_key, + ecc_key* pub_key, byte* pubKeyDer, word32* pubKeySz, byte* out, + word32* outlen, int side); + #endif /* HAVE_ECC */ + #ifdef HAVE_ED25519 + WOLFSSL_LOCAL int Ed25519CheckPubKey(WOLFSSL* ssl); + WOLFSSL_LOCAL int Ed25519Sign(WOLFSSL* ssl, const byte* in, word32 inSz, + byte* out, word32* outSz, ed25519_key* key, DerBuffer* keyBufInfo); + WOLFSSL_LOCAL int Ed25519Verify(WOLFSSL* ssl, const byte* in, + word32 inSz, const byte* msg, word32 msgSz, ed25519_key* key, + buffer* keyBufInfo); + #endif /* HAVE_ED25519 */ + + + #ifdef WOLFSSL_TRUST_PEER_CERT + + /* options for searching hash table for a matching trusted peer cert */ + #define WC_MATCH_SKID 0 + #define WC_MATCH_NAME 1 + + WOLFSSL_LOCAL TrustedPeerCert* GetTrustedPeer(void* vp, byte* hash, + int type); + WOLFSSL_LOCAL int MatchTrustedPeer(TrustedPeerCert* tp, + DecodedCert* cert); + #endif + + WOLFSSL_LOCAL Signer* GetCA(void* cm, byte* hash); + #ifndef NO_SKID + WOLFSSL_LOCAL Signer* GetCAByName(void* cm, byte* hash); + #endif +#endif /* !NO_CERTS */ +WOLFSSL_LOCAL int BuildTlsHandshakeHash(WOLFSSL* ssl, byte* hash, + word32* hashLen); +WOLFSSL_LOCAL int BuildTlsFinished(WOLFSSL* ssl, Hashes* hashes, + const byte* sender); +WOLFSSL_LOCAL void FreeArrays(WOLFSSL* ssl, int keep); +WOLFSSL_LOCAL int CheckAvailableSize(WOLFSSL *ssl, int size); +WOLFSSL_LOCAL int GrowInputBuffer(WOLFSSL* ssl, int size, int usedLength); + +#ifndef NO_TLS + WOLFSSL_LOCAL int MakeTlsMasterSecret(WOLFSSL*); +#ifndef WOLFSSL_AEAD_ONLY + WOLFSSL_LOCAL int TLS_hmac(WOLFSSL* ssl, byte* digest, const byte* in, + word32 sz, int padSz, int content, int verify); +#endif +#endif + +#ifndef NO_WOLFSSL_CLIENT + WOLFSSL_LOCAL int SendClientHello(WOLFSSL*); + #ifdef WOLFSSL_TLS13 + WOLFSSL_LOCAL int SendTls13ClientHello(WOLFSSL*); + #endif + WOLFSSL_LOCAL int SendClientKeyExchange(WOLFSSL*); + WOLFSSL_LOCAL int SendCertificateVerify(WOLFSSL*); +#endif /* NO_WOLFSSL_CLIENT */ + +#ifndef NO_WOLFSSL_SERVER + WOLFSSL_LOCAL int SendServerHello(WOLFSSL*); + WOLFSSL_LOCAL int SendServerHelloDone(WOLFSSL*); +#endif /* NO_WOLFSSL_SERVER */ + +#ifdef WOLFSSL_DTLS + WOLFSSL_LOCAL DtlsMsg* DtlsMsgNew(word32, void*); + WOLFSSL_LOCAL void DtlsMsgDelete(DtlsMsg*, void*); + WOLFSSL_LOCAL void DtlsMsgListDelete(DtlsMsg*, void*); + WOLFSSL_LOCAL int DtlsMsgSet(DtlsMsg*, word32, const byte*, byte, + word32, word32, void*); + WOLFSSL_LOCAL DtlsMsg* DtlsMsgFind(DtlsMsg*, word32); + WOLFSSL_LOCAL void DtlsMsgStore(WOLFSSL*, word32, const byte*, word32, + byte, word32, word32, void*); + WOLFSSL_LOCAL DtlsMsg* DtlsMsgInsert(DtlsMsg*, DtlsMsg*); + + WOLFSSL_LOCAL int DtlsMsgPoolSave(WOLFSSL*, const byte*, word32); + WOLFSSL_LOCAL int DtlsMsgPoolTimeout(WOLFSSL*); + WOLFSSL_LOCAL int VerifyForDtlsMsgPoolSend(WOLFSSL*, byte, word32); + WOLFSSL_LOCAL void DtlsMsgPoolReset(WOLFSSL*); + WOLFSSL_LOCAL int DtlsMsgPoolSend(WOLFSSL*, int); +#endif /* WOLFSSL_DTLS */ + +#ifndef NO_TLS + + +#endif /* NO_TLS */ + +#if defined(WOLFSSL_TLS13) && (defined(HAVE_SESSION_TICKET) || !defined(NO_PSK)) + WOLFSSL_LOCAL word32 TimeNowInMilliseconds(void); +#endif +WOLFSSL_LOCAL word32 LowResTimer(void); + +#ifndef NO_CERTS + WOLFSSL_LOCAL void InitX509Name(WOLFSSL_X509_NAME*, int); + WOLFSSL_LOCAL void FreeX509Name(WOLFSSL_X509_NAME* name, void* heap); + WOLFSSL_LOCAL void InitX509(WOLFSSL_X509*, int, void* heap); + WOLFSSL_LOCAL void FreeX509(WOLFSSL_X509*); + WOLFSSL_LOCAL int CopyDecodedToX509(WOLFSSL_X509*, DecodedCert*); +#endif + +typedef struct CipherSuiteInfo { + const char* name; +#ifndef NO_ERROR_STRINGS + const char* name_iana; +#endif + byte cipherSuite0; + byte cipherSuite; +} CipherSuiteInfo; + +WOLFSSL_LOCAL const CipherSuiteInfo* GetCipherNames(void); +WOLFSSL_LOCAL int GetCipherNamesSize(void); +WOLFSSL_LOCAL const char* GetCipherNameInternal(const byte cipherSuite0, const byte cipherSuite); +WOLFSSL_LOCAL const char* GetCipherNameIana(const byte cipherSuite0, const byte cipherSuite); +WOLFSSL_LOCAL const char* wolfSSL_get_cipher_name_internal(WOLFSSL* ssl); +WOLFSSL_LOCAL const char* wolfSSL_get_cipher_name_iana(WOLFSSL* ssl); +WOLFSSL_LOCAL int GetCipherSuiteFromName(const char* name, byte* cipherSuite0, + byte* cipherSuite); + +enum encrypt_side { + ENCRYPT_SIDE_ONLY = 1, + DECRYPT_SIDE_ONLY, + ENCRYPT_AND_DECRYPT_SIDE +}; + +WOLFSSL_LOCAL int SetKeysSide(WOLFSSL*, enum encrypt_side); + + +#ifndef NO_DH + WOLFSSL_LOCAL int DhGenKeyPair(WOLFSSL* ssl, DhKey* dhKey, + byte* priv, word32* privSz, + byte* pub, word32* pubSz); + WOLFSSL_LOCAL int DhAgree(WOLFSSL* ssl, DhKey* dhKey, + const byte* priv, word32 privSz, + const byte* otherPub, word32 otherPubSz, + byte* agree, word32* agreeSz); +#endif /* !NO_DH */ + +#ifdef HAVE_ECC + WOLFSSL_LOCAL int EccMakeKey(WOLFSSL* ssl, ecc_key* key, ecc_key* peer); +#endif + +WOLFSSL_LOCAL int InitHandshakeHashes(WOLFSSL* ssl); +WOLFSSL_LOCAL void FreeHandshakeHashes(WOLFSSL* ssl); + +WOLFSSL_LOCAL int BuildMessage(WOLFSSL* ssl, byte* output, int outSz, + const byte* input, int inSz, int type, int hashOutput, + int sizeOnly, int asyncOkay); + +#ifdef WOLFSSL_TLS13 +int BuildTls13Message(WOLFSSL* ssl, byte* output, int outSz, const byte* input, + int inSz, int type, int hashOutput, int sizeOnly, int asyncOkay); +#endif + +WOLFSSL_LOCAL int AllocKey(WOLFSSL* ssl, int type, void** pKey); +WOLFSSL_LOCAL void FreeKey(WOLFSSL* ssl, int type, void** pKey); + +#ifdef WOLFSSL_ASYNC_CRYPT + WOLFSSL_LOCAL int wolfSSL_AsyncInit(WOLFSSL* ssl, WC_ASYNC_DEV* asyncDev, word32 flags); + WOLFSSL_LOCAL int wolfSSL_AsyncPop(WOLFSSL* ssl, byte* state); + WOLFSSL_LOCAL int wolfSSL_AsyncPush(WOLFSSL* ssl, WC_ASYNC_DEV* asyncDev); +#endif + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* wolfSSL_INT_H */ diff --git a/beken_os/beken378/func/wolfssl/wolfssl/ocsp.h b/beken_os/beken378/func/wolfssl/wolfssl/ocsp.h new file mode 100755 index 0000000..e494536 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/ocsp.h @@ -0,0 +1,110 @@ +/* ocsp.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +/* wolfSSL OCSP API */ + +#ifndef WOLFSSL_OCSP_H +#define WOLFSSL_OCSP_H + +#ifdef HAVE_OCSP + +#include +#include + +#ifdef __cplusplus + extern "C" { +#endif + +typedef struct WOLFSSL_OCSP WOLFSSL_OCSP; + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) +typedef struct OcspResponse WOLFSSL_OCSP_BASICRESP; + +typedef struct OcspRequest WOLFSSL_OCSP_CERTID; + +typedef struct OcspRequest WOLFSSL_OCSP_ONEREQ; +#endif + +WOLFSSL_LOCAL int InitOCSP(WOLFSSL_OCSP*, WOLFSSL_CERT_MANAGER*); +WOLFSSL_LOCAL void FreeOCSP(WOLFSSL_OCSP*, int dynamic); + +WOLFSSL_LOCAL int CheckCertOCSP(WOLFSSL_OCSP*, DecodedCert*, + WOLFSSL_BUFFER_INFO* responseBuffer); +WOLFSSL_LOCAL int CheckCertOCSP_ex(WOLFSSL_OCSP*, DecodedCert*, + WOLFSSL_BUFFER_INFO* responseBuffer, WOLFSSL* ssl); +WOLFSSL_LOCAL int CheckOcspRequest(WOLFSSL_OCSP* ocsp, + OcspRequest* ocspRequest, WOLFSSL_BUFFER_INFO* responseBuffer); +WOLFSSL_LOCAL int CheckOcspResponse(WOLFSSL_OCSP *ocsp, byte *response, int responseSz, + WOLFSSL_BUFFER_INFO *responseBuffer, CertStatus *status, + OcspEntry *entry, OcspRequest *ocspRequest); + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + + WOLFSSL_API int wolfSSL_OCSP_resp_find_status(WOLFSSL_OCSP_BASICRESP *bs, + WOLFSSL_OCSP_CERTID *id, int *status, int *reason, + WOLFSSL_ASN1_TIME **revtime, WOLFSSL_ASN1_TIME **thisupd, + WOLFSSL_ASN1_TIME **nextupd); +WOLFSSL_API const char *wolfSSL_OCSP_cert_status_str(long s); +WOLFSSL_API int wolfSSL_OCSP_check_validity(WOLFSSL_ASN1_TIME* thisupd, + WOLFSSL_ASN1_TIME* nextupd, long sec, long maxsec); + +WOLFSSL_API void wolfSSL_OCSP_CERTID_free(WOLFSSL_OCSP_CERTID* certId); +WOLFSSL_API WOLFSSL_OCSP_CERTID* wolfSSL_OCSP_cert_to_id( + const WOLFSSL_EVP_MD *dgst, const WOLFSSL_X509 *subject, + const WOLFSSL_X509 *issuer); + +WOLFSSL_API void wolfSSL_OCSP_BASICRESP_free(WOLFSSL_OCSP_BASICRESP* basicResponse); +WOLFSSL_API int wolfSSL_OCSP_basic_verify(WOLFSSL_OCSP_BASICRESP *bs, + WOLF_STACK_OF(WOLFSSL_X509) *certs, WOLFSSL_X509_STORE *st, unsigned long flags); + +WOLFSSL_API void wolfSSL_OCSP_RESPONSE_free(OcspResponse* response); +WOLFSSL_API OcspResponse* wolfSSL_d2i_OCSP_RESPONSE_bio(WOLFSSL_BIO* bio, + OcspResponse** response); +WOLFSSL_API OcspResponse* wolfSSL_d2i_OCSP_RESPONSE(OcspResponse** response, + const unsigned char** data, int len); +WOLFSSL_API int wolfSSL_i2d_OCSP_RESPONSE(OcspResponse* response, + unsigned char** data); +WOLFSSL_API int wolfSSL_OCSP_response_status(OcspResponse *response); +WOLFSSL_API const char *wolfSSL_OCSP_response_status_str(long s); +WOLFSSL_API WOLFSSL_OCSP_BASICRESP* wolfSSL_OCSP_response_get1_basic( + OcspResponse* response); + +WOLFSSL_API OcspRequest* wolfSSL_OCSP_REQUEST_new(void); +WOLFSSL_API void wolfSSL_OCSP_REQUEST_free(OcspRequest* request); +WOLFSSL_API int wolfSSL_i2d_OCSP_REQUEST(OcspRequest* request, + unsigned char** data); +WOLFSSL_API WOLFSSL_OCSP_ONEREQ* wolfSSL_OCSP_request_add0_id(OcspRequest *req, + WOLFSSL_OCSP_CERTID *cid); + +#endif + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + + +#endif /* HAVE_OCSP */ +#endif /* WOLFSSL_OCSP_H */ + + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/options.h b/beken_os/beken378/func/wolfssl/wolfssl/options.h new file mode 100755 index 0000000..f4630a8 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/options.h @@ -0,0 +1,183 @@ +/* wolfssl options.h + * generated from configure options + * + * Copyright (C) 2006-2015 wolfSSL Inc. + * + * This file is part of wolfSSL. (formerly known as CyaSSL) + * + */ + +#ifndef WOLFSSL_OPTIONS_H +#define WOLFSSL_OPTIONS_H + + +#ifdef __cplusplus +extern "C" { +#endif + +#undef HAVE_FFDHE_2048 +#define HAVE_FFDHE_2048 + +#ifndef WOLFSSL_OPTIONS_IGNORE_SYS +#undef _POSIX_THREADS +#define _POSIX_THREADS +#endif + +#undef HAVE_THREAD_LS +#define HAVE_THREAD_LS + +#undef TFM_TIMING_RESISTANT +#define TFM_TIMING_RESISTANT + +#undef ECC_TIMING_RESISTANT +#define ECC_TIMING_RESISTANT + +#undef WC_RSA_BLINDING +#define WC_RSA_BLINDING + + +#undef WOLFSSL_KEY_GEN +#define WOLFSSL_KEY_GEN + +#undef WOLFSSL_DES_ECB +#define WOLFSSL_DES_ECB + +#undef WOLFSSL_WPAS +#define WOLFSSL_WPAS + +#undef HAVE_AESGCM +#define HAVE_AESGCM + +#undef WOLFSSL_SHA512 +#define WOLFSSL_SHA512 + +#undef WOLFSSL_SHA384 +#define WOLFSSL_SHA384 + +#undef HAVE_HKDF +#define HAVE_HKDF + +#undef NO_DSA +#define NO_DSA + +#undef HAVE_ECC +#define HAVE_ECC + +#undef TFM_ECC256 +#define TFM_ECC256 + +#undef ECC_SHAMIR +#define ECC_SHAMIR + +#undef WOLFSSL_CUSTOM_CURVES +#define WOLFSSL_CUSTOM_CURVES + +#undef HAVE_ECC_SECPR2 +#define HAVE_ECC_SECPR2 + +#undef HAVE_ECC_SECPR3 +#define HAVE_ECC_SECPR3 + +#undef HAVE_ECC_BRAINPOOL +#define HAVE_ECC_BRAINPOOL + +#undef HAVE_ECC_KOBLITZ +#define HAVE_ECC_KOBLITZ + +#undef HAVE_ECC_CDH +#define HAVE_ECC_CDH + +#undef HAVE_COMP_KEY +#define HAVE_COMP_KEY + +#undef HAVE_CURVE25519 +#define HAVE_CURVE25519 + +#undef HAVE_ED25519 +#define HAVE_ED25519 + +#undef FP_ECC +#define FP_ECC + +#undef HAVE_ECC_ENCRYPT +#define HAVE_ECC_ENCRYPT + +#undef WOLFSSL_BASE64_ENCODE +#define WOLFSSL_BASE64_ENCODE + +#undef NO_RC4 +#define NO_RC4 + +#undef NO_HC128 +#define NO_HC128 + +#undef NO_RABBIT +#define NO_RABBIT + +#undef WOLFSSL_SHA224 +#define WOLFSSL_SHA224 + +#undef WOLFSSL_SHA3 +#define WOLFSSL_SHA3 + +#undef HAVE_POLY1305 +#define HAVE_POLY1305 + +#undef HAVE_ONE_TIME_AUTH +#define HAVE_ONE_TIME_AUTH + +#undef HAVE_CHACHA +#define HAVE_CHACHA + +#undef HAVE_HASHDRBG +#define HAVE_HASHDRBG + +#undef HAVE_TLS_EXTENSIONS +#define HAVE_TLS_EXTENSIONS + +#undef HAVE_SUPPORTED_CURVES +#define HAVE_SUPPORTED_CURVES + +#undef HAVE_EXTENDED_MASTER +#define HAVE_EXTENDED_MASTER + +#undef NO_PSK +#define NO_PSK + +#undef NO_MD4 +#define NO_MD4 + +#undef HAVE_SUPPORTED_CURVES +#define HAVE_SUPPORTED_CURVES + +#undef NO_PWDBASED +#define NO_PWDBASED + +#undef USE_FAST_MATH +#define USE_FAST_MATH + +//#undef WOLFSSL_X86_64_BUILD +//#define WOLFSSL_X86_64_BUILD + +#undef WC_NO_ASYNC_THREADING +#define WC_NO_ASYNC_THREADING + +#undef HAVE_AES_KEYWRAP +#define HAVE_AES_KEYWRAP + +#undef WOLFSSL_AES_DIRECT +#define WOLFSSL_AES_DIRECT +#undef NO_DES3 +#define NO_DES3 + +#undef HAVE___UINT128_T +#define HAVE___UINT128_T 1 + + +#ifdef __cplusplus +} +#endif + + +#endif /* WOLFSSL_OPTIONS_H */ + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/options.h.in b/beken_os/beken378/func/wolfssl/wolfssl/options.h.in new file mode 100755 index 0000000..29fa97e --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/options.h.in @@ -0,0 +1,40 @@ +/* options.h.in + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +/* default blank options for autoconf */ + +#ifndef WOLFSSL_OPTIONS_H +#define WOLFSSL_OPTIONS_H + + +#ifdef __cplusplus +extern "C" { +#endif + + +#ifdef __cplusplus +} +#endif + + +#endif /* WOLFSSL_OPTIONS_H */ + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/sniffer.h b/beken_os/beken378/func/wolfssl/wolfssl/sniffer.h new file mode 100755 index 0000000..d731c5b --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/sniffer.h @@ -0,0 +1,199 @@ +/* sniffer.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifndef WOLFSSL_SNIFFER_H +#define WOLFSSL_SNIFFER_H + +#include + +#ifdef _WIN32 + #ifdef SSL_SNIFFER_EXPORTS + #define SSL_SNIFFER_API __declspec(dllexport) + #else + #define SSL_SNIFFER_API __declspec(dllimport) + #endif +#else + #define SSL_SNIFFER_API +#endif /* _WIN32 */ + + +#ifdef __cplusplus + extern "C" { +#endif + +/* @param typeK: (formerly keyType) was shadowing a global declaration in + * wolfssl/wolfcrypt/asn.h line 175 + */ +WOLFSSL_API +SSL_SNIFFER_API int ssl_SetPrivateKey(const char* address, int port, + const char* keyFile, int typeK, + const char* password, char* error); + +WOLFSSL_API +SSL_SNIFFER_API int ssl_SetNamedPrivateKey(const char* name, + const char* address, int port, + const char* keyFile, int typeK, + const char* password, char* error); + +WOLFSSL_API +SSL_SNIFFER_API int ssl_DecodePacket(const unsigned char* packet, int length, + unsigned char** data, char* error); + +WOLFSSL_API +SSL_SNIFFER_API int ssl_FreeDecodeBuffer(unsigned char** data, char* error); + +WOLFSSL_API +SSL_SNIFFER_API int ssl_FreeZeroDecodeBuffer(unsigned char** data, int sz, + char* error); + +WOLFSSL_API +SSL_SNIFFER_API int ssl_Trace(const char* traceFile, char* error); + +WOLFSSL_API +SSL_SNIFFER_API int ssl_EnableRecovery(int onOff, int maxMemory, char* error); + +WOLFSSL_API +SSL_SNIFFER_API int ssl_GetSessionStats(unsigned int* active, + unsigned int* total, + unsigned int* peak, + unsigned int* maxSessions, + unsigned int* missedData, + unsigned int* reassemblyMemory, + char* error); + +WOLFSSL_API void ssl_InitSniffer(void); + +WOLFSSL_API void ssl_FreeSniffer(void); + + +/* ssl_SetPrivateKey typeKs */ +enum { + FILETYPE_PEM = 1, + FILETYPE_DER = 2, +}; + + +/* + * New Sniffer API that provides read-only access to the TLS and cipher + * information associated with the SSL session. + */ + +#if defined(__GNUC__) + #define WOLFSSL_PACK __attribute__ ((packed)) +#else + #define WOLFSSL_PACK +#endif + + +typedef struct SSLInfo +{ + unsigned char isValid; + /* indicates if the info in this struct is valid: 0 = no, 1 = yes */ + unsigned char protocolVersionMajor; /* SSL Version: major */ + unsigned char protocolVersionMinor; /* SSL Version: minor */ + unsigned char serverCipherSuite0; /* first byte, normally 0 */ + unsigned char serverCipherSuite; /* second byte, actual suite */ + unsigned char serverCipherSuiteName[256]; + /* cipher name, e.g., "TLS_RSA_..." */ + unsigned char serverNameIndication[128]; + unsigned int keySize; +} WOLFSSL_PACK SSLInfo; + + +WOLFSSL_API +SSL_SNIFFER_API int ssl_DecodePacketWithSessionInfo( + const unsigned char* packet, int length, + unsigned char** data, SSLInfo* sslInfo, char* error); + +typedef void (*SSLConnCb)(const void* session, SSLInfo* info, void* ctx); + +WOLFSSL_API +SSL_SNIFFER_API int ssl_SetConnectionCb(SSLConnCb cb); + +WOLFSSL_API +SSL_SNIFFER_API int ssl_SetConnectionCtx(void* ctx); + + +typedef struct SSLStats +{ + unsigned long int sslStandardConns; + unsigned long int sslClientAuthConns; + unsigned long int sslResumedConns; + unsigned long int sslEphemeralMisses; + unsigned long int sslResumeMisses; + unsigned long int sslCiphersUnsupported; + unsigned long int sslKeysUnmatched; + unsigned long int sslKeyFails; + unsigned long int sslDecodeFails; + unsigned long int sslAlerts; + unsigned long int sslDecryptedBytes; + unsigned long int sslEncryptedBytes; + unsigned long int sslEncryptedPackets; + unsigned long int sslDecryptedPackets; + unsigned long int sslKeyMatches; + unsigned long int sslEncryptedConns; +} SSLStats; + + +WOLFSSL_API +SSL_SNIFFER_API int ssl_ResetStatistics(void); + + +WOLFSSL_API +SSL_SNIFFER_API int ssl_ReadStatistics(SSLStats* stats); + + +WOLFSSL_API +SSL_SNIFFER_API int ssl_ReadResetStatistics(SSLStats* stats); + + +typedef int (*SSLWatchCb)(void* vSniffer, + const unsigned char* certHash, + unsigned int certHashSz, + const unsigned char* certChain, + unsigned int certChainSz, + void* ctx, char* error); + +WOLFSSL_API +SSL_SNIFFER_API int ssl_SetWatchKeyCallback(SSLWatchCb cb, char* error); + +WOLFSSL_API +SSL_SNIFFER_API int ssl_SetWatchKeyCtx(void* ctx, char* error); + +WOLFSSL_API +SSL_SNIFFER_API int ssl_SetWatchKey_buffer(void* vSniffer, + const unsigned char* key, unsigned int keySz, + int keyType, char* error); + +WOLFSSL_API +SSL_SNIFFER_API int ssl_SetWatchKey_file(void* vSniffer, + const char* keyFile, int keyType, + const char* password, char* error); + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* wolfSSL_SNIFFER_H */ + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/sniffer_error.h b/beken_os/beken378/func/wolfssl/wolfssl/sniffer_error.h new file mode 100755 index 0000000..e3bc38b --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/sniffer_error.h @@ -0,0 +1,132 @@ +/* sniffer_error.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifndef WOLFSSL_SNIFFER_ERROR_H +#define WOLFSSL_SNIFFER_ERROR_H + +/* need to have errors as #defines since .rc files can't handle enums */ +/* need to start at 1 and go in order for same reason */ + +#define MEMORY_STR 1 +#define NEW_SERVER_STR 2 +#define IP_CHECK_STR 3 +#define SERVER_NOT_REG_STR 4 +#define TCP_CHECK_STR 5 +#define SERVER_PORT_NOT_REG_STR 6 +#define RSA_DECRYPT_STR 7 +#define RSA_DECODE_STR 8 +#define BAD_CIPHER_SPEC_STR 9 +#define SERVER_HELLO_INPUT_STR 10 + +#define BAD_SESSION_RESUME_STR 11 +#define SERVER_DID_RESUMPTION_STR 12 +#define CLIENT_HELLO_INPUT_STR 13 +#define CLIENT_RESUME_TRY_STR 14 +#define HANDSHAKE_INPUT_STR 15 +#define GOT_HELLO_VERIFY_STR 16 +#define GOT_SERVER_HELLO_STR 17 +#define GOT_CERT_REQ_STR 18 +#define GOT_SERVER_KEY_EX_STR 19 +#define GOT_CERT_STR 20 + +#define GOT_SERVER_HELLO_DONE_STR 21 +#define GOT_FINISHED_STR 22 +#define GOT_CLIENT_HELLO_STR 23 +#define GOT_CLIENT_KEY_EX_STR 24 +#define GOT_CERT_VER_STR 25 +#define GOT_UNKNOWN_HANDSHAKE_STR 26 +#define NEW_SESSION_STR 27 +#define BAD_NEW_SSL_STR 28 +#define GOT_PACKET_STR 29 +#define NO_DATA_STR 30 + +#define BAD_SESSION_STR 31 +#define GOT_OLD_CLIENT_HELLO_STR 32 +#define OLD_CLIENT_INPUT_STR 33 +#define OLD_CLIENT_OK_STR 34 +#define BAD_OLD_CLIENT_STR 35 +#define BAD_RECORD_HDR_STR 36 +#define RECORD_INPUT_STR 37 +#define GOT_HANDSHAKE_STR 38 +#define BAD_HANDSHAKE_STR 39 +#define GOT_CHANGE_CIPHER_STR 40 + +#define GOT_APP_DATA_STR 41 +#define BAD_APP_DATA_STR 42 +#define GOT_ALERT_STR 43 +#define ANOTHER_MSG_STR 44 +#define REMOVE_SESSION_STR 45 +#define KEY_FILE_STR 46 +#define BAD_IPVER_STR 47 +#define BAD_PROTO_STR 48 +#define PACKET_HDR_SHORT_STR 49 +#define GOT_UNKNOWN_RECORD_STR 50 + +#define BAD_TRACE_FILE_STR 51 +#define FATAL_ERROR_STR 52 +#define PARTIAL_INPUT_STR 53 +#define BUFFER_ERROR_STR 54 +#define PARTIAL_ADD_STR 55 +#define DUPLICATE_STR 56 +#define OUT_OF_ORDER_STR 57 +#define OVERLAP_DUPLICATE_STR 58 +#define OVERLAP_REASSEMBLY_BEGIN_STR 59 +#define OVERLAP_REASSEMBLY_END_STR 60 + +#define MISSED_CLIENT_HELLO_STR 61 +#define GOT_HELLO_REQUEST_STR 62 +#define GOT_SESSION_TICKET_STR 63 +#define BAD_INPUT_STR 64 +#define BAD_DECRYPT_TYPE 65 +#define BAD_FINISHED_MSG 66 +#define BAD_COMPRESSION_STR 67 +#define BAD_DERIVE_STR 68 +#define ACK_MISSED_STR 69 +#define BAD_DECRYPT 70 + +#define DECRYPT_KEYS_NOT_SETUP 71 +#define CLIENT_HELLO_LATE_KEY_STR 72 +#define GOT_CERT_STATUS_STR 73 +#define RSA_KEY_MISSING_STR 74 +#define NO_SECURE_RENEGOTIATION 75 + +#define BAD_SESSION_STATS 76 +#define REASSEMBLY_MAX_STR 77 +#define DROPPING_LOST_FRAG_STR 78 +#define DROPPING_PARTIAL_RECORD 79 +#define CLEAR_ACK_FAULT 80 + +#define BAD_DECRYPT_SIZE 81 +#define EXTENDED_MASTER_HASH_STR 82 +#define SPLIT_HANDSHAKE_MSG_STR 83 +#define ECC_DECODE_STR 84 +#define ECC_PUB_DECODE_STR 85 +#define WATCH_CB_MISSING_STR 86 +#define WATCH_HASH_STR 87 +#define WATCH_FAIL_STR 88 +#define BAD_CERT_MSG_STR 89 +/* !!!! also add to msgTable in sniffer.c and .rc file !!!! */ + + +#endif /* wolfSSL_SNIFFER_ERROR_H */ + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/sniffer_error.rc b/beken_os/beken378/func/wolfssl/wolfssl/sniffer_error.rc new file mode 100755 index 0000000..336cf33 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/sniffer_error.rc @@ -0,0 +1,111 @@ + +STRINGTABLE +{ + 1, "Out of Memory" + 2, "New SSL Sniffer Server Registered" + 3, "Checking IP Header" + 4, "SSL Sniffer Server Not Registered" + 5, "Checking TCP Header" + + 6, "SSL Sniffer Server Port Not Registered" + 7, "RSA Private Decrypt Error" + 8, "RSA Private Decode Error" + 9, "Set Cipher Spec Error" + 10, "Server Hello Input Malformed" + + 11, "Couldn't Resume Session Error" + 12, "Server Did Resumption" + 13, "Client Hello Input Malformed" + 14, "Client Trying to Resume" + 15, "Handshake Input Malformed" + + 16, "Got Hello Verify msg" + 17, "Got Server Hello msg" + 18, "Got Cert Request msg" + 19, "Got Server Key Exchange msg" + 20, "Got Cert msg" + + 21, "Got Server Hello Done msg" + 22, "Got Finished msg" + 23, "Got Client Hello msg" + 24, "Got Client Key Exchange msg" + 25, "Got Cert Verify msg" + + 26, "Got Unknown Handshake msg" + 27, "New SSL Sniffer Session created" + 28, "Couldn't create new SSL" + 29, "Got a Packet to decode" + 30, "No data present" + + 31, "Session Not Found" + 32, "Got an Old Client Hello msg" + 33, "Old Client Hello Input Malformed" + 34, "Old Client Hello OK" + 35, "Bad Old Client Hello" + + 36, "Bad Record Header" + 37, "Record Header Input Malformed" + 38, "Got a HandShake msg" + 39, "Bad HandShake msg" + 40, "Got a Change Cipher Spec msg" + + 41, "Got Application Data msg" + 42, "Bad Application Data" + 43, "Got an Alert msg" + 44, "Another msg to Process" + 45, "Removing Session From Table" + + 46, "Bad Key File" + 47, "Wrong IP Version" + 48, "Wrong Protocol type" + 49, "Packet Short for header processing" + 50, "Got Unknown Record Type" + + 51, "Can't Open Trace File" + 52, "Session in Fatal Error State" + 53, "Partial SSL record received" + 54, "Buffer Error, malformed input" + 55, "Added to Partial Input" + + 56, "Received a Duplicate Packet" + 57, "Received an Out of Order Packet" + 58, "Received an Overlap Duplicate Packet" + 59, "Received an Overlap Reassembly Begin Duplicate Packet" + 60, "Received an Overlap Reassembly End Duplicate Packet" + + 61, "Missed the Client Hello Entirely" + 62, "Got Hello Request msg" + 63, "Got Session Ticket msg" + 64, "Bad Input" + 65, "Bad Decrypt Type" + + 66, "Bad Finished Message Processing" + 67, "Bad Compression Type" + 68, "Bad DeriveKeys Error" + 69, "Saw ACK for Missing Packet Error" + 70, "Bad Decrypt Operation" + + 71, "Decrypt Keys Not Set Up" + 72, "Late Key Load Error" + 73, "Got Certificate Status msg" + 74, "RSA Key Missing Error" + 75, "Secure Renegotiation Not Supported" + + 76, "Get Session Stats Failure" + 77, "Reassembly Buffer Size Exceeded" + 78, "Dropping Lost Fragment" + 79, "Dropping Partial Record" + 80, "Clear ACK Fault" + + 81, "Bad Decrypt Size" + 82, "Extended Master Secret Hash Error" + 83, "Handshake Message Split Across TLS Records" + 84, "ECC Private Decode Error" + 85, "ECC Public Decode Error" + + 86, "Watch callback not set" + 87, "Watch hash failed" + 88, "Watch callback failed" + 89, "Bad Certificate Message" +} + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/ssl.h b/beken_os/beken378/func/wolfssl/wolfssl/ssl.h new file mode 100755 index 0000000..53aab49 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/ssl.h @@ -0,0 +1,3122 @@ +/* ssl.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ +/*! + \file ../wolfssl/ssl.h + \brief Header file containing key wolfSSL API +*/ + +/* wolfSSL API */ + +#ifndef WOLFSSL_SSL_H +#define WOLFSSL_SSL_H + + +/* for users not using preprocessor flags*/ +#include +#include +#include +#include + +#ifdef HAVE_WOLF_EVENT + #include +#endif + +#ifndef NO_FILESYSTEM + #if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) + #if MQX_USE_IO_OLD + #include + #else + #include + #endif + #endif +#endif + +#ifdef WOLFSSL_PREFIX + #include "prefix_ssl.h" +#endif + +#ifdef LIBWOLFSSL_VERSION_STRING + #define WOLFSSL_VERSION LIBWOLFSSL_VERSION_STRING +#endif + +#ifdef _WIN32 + /* wincrypt.h clashes */ + #undef OCSP_REQUEST + #undef OCSP_RESPONSE +#endif + +#ifdef OPENSSL_COEXIST + /* mode to allow wolfSSL and OpenSSL to exist together */ + #ifdef TEST_OPENSSL_COEXIST + /* + ./configure --enable-opensslcoexist \ + CFLAGS="-I/usr/local/opt/openssl/include -DTEST_OPENSSL_COEXIST" \ + LDFLAGS="-L/usr/local/opt/openssl/lib -lcrypto" + */ + #include + #include + #include + #include + #include + #include + #endif + + /* make sure old names are disabled */ + #ifndef NO_OLD_SSL_NAMES + #define NO_OLD_SSL_NAMES + #endif + #ifndef NO_OLD_WC_NAMES + #define NO_OLD_WC_NAMES + #endif + +#elif (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) + #include + #include + + /* We need the old SSL names */ + #ifdef NO_OLD_SSL_NAMES + #undef NO_OLD_SSL_NAMES + #endif + #ifdef NO_OLD_WC_NAMES + #undef NO_OLD_WC_NAMES + #endif +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +#ifndef WOLFSSL_WOLFSSL_TYPE_DEFINED +#define WOLFSSL_WOLFSSL_TYPE_DEFINED +typedef struct WOLFSSL WOLFSSL; +#endif +typedef struct WOLFSSL_SESSION WOLFSSL_SESSION; +typedef struct WOLFSSL_METHOD WOLFSSL_METHOD; +#ifndef WOLFSSL_WOLFSSL_CTX_TYPE_DEFINED +#define WOLFSSL_WOLFSSL_CTX_TYPE_DEFINED +typedef struct WOLFSSL_CTX WOLFSSL_CTX; +#endif + +typedef struct WOLFSSL_STACK WOLFSSL_STACK; +typedef struct WOLFSSL_X509 WOLFSSL_X509; +typedef struct WOLFSSL_X509_NAME WOLFSSL_X509_NAME; +typedef struct WOLFSSL_X509_NAME_ENTRY WOLFSSL_X509_NAME_ENTRY; +typedef struct WOLFSSL_X509_CHAIN WOLFSSL_X509_CHAIN; +typedef struct WC_PKCS12 WOLFSSL_X509_PKCS12; + +typedef struct WOLFSSL_CERT_MANAGER WOLFSSL_CERT_MANAGER; +typedef struct WOLFSSL_SOCKADDR WOLFSSL_SOCKADDR; +typedef struct WOLFSSL_CRL WOLFSSL_CRL; + +typedef void *WOLFSSL_X509_STORE_CTX_verify_cb; /* verify callback */ + +/* redeclare guard */ +#define WOLFSSL_TYPES_DEFINED + +#include + + +#ifndef WOLFSSL_RSA_TYPE_DEFINED /* guard on redeclaration */ +typedef struct WOLFSSL_RSA WOLFSSL_RSA; +#define WOLFSSL_RSA_TYPE_DEFINED +#endif + +#ifndef WC_RNG_TYPE_DEFINED /* guard on redeclaration */ + typedef struct WC_RNG WC_RNG; + #define WC_RNG_TYPE_DEFINED +#endif + +#ifndef WOLFSSL_DSA_TYPE_DEFINED /* guard on redeclaration */ +typedef struct WOLFSSL_DSA WOLFSSL_DSA; +#define WOLFSSL_DSA_TYPE_DEFINED +#endif + +#ifndef WOLFSSL_EC_TYPE_DEFINED /* guard on redeclaration */ +typedef struct WOLFSSL_EC_KEY WOLFSSL_EC_KEY; +typedef struct WOLFSSL_EC_POINT WOLFSSL_EC_POINT; +typedef struct WOLFSSL_EC_GROUP WOLFSSL_EC_GROUP; +#define WOLFSSL_EC_TYPE_DEFINED +#endif + +#ifndef WOLFSSL_ECDSA_TYPE_DEFINED /* guard on redeclaration */ +typedef struct WOLFSSL_ECDSA_SIG WOLFSSL_ECDSA_SIG; +#define WOLFSSL_ECDSA_TYPE_DEFINED +#endif + +typedef struct WOLFSSL_CIPHER WOLFSSL_CIPHER; +typedef struct WOLFSSL_X509_LOOKUP WOLFSSL_X509_LOOKUP; +typedef struct WOLFSSL_X509_LOOKUP_METHOD WOLFSSL_X509_LOOKUP_METHOD; +typedef struct WOLFSSL_CRL WOLFSSL_X509_CRL; +typedef struct WOLFSSL_X509_STORE WOLFSSL_X509_STORE; +typedef struct WOLFSSL_X509_VERIFY_PARAM WOLFSSL_X509_VERIFY_PARAM; +typedef struct WOLFSSL_BIO WOLFSSL_BIO; +typedef struct WOLFSSL_BIO_METHOD WOLFSSL_BIO_METHOD; +typedef struct WOLFSSL_X509_EXTENSION WOLFSSL_X509_EXTENSION; +typedef struct WOLFSSL_ASN1_TIME WOLFSSL_ASN1_TIME; +typedef struct WOLFSSL_ASN1_INTEGER WOLFSSL_ASN1_INTEGER; +typedef struct WOLFSSL_ASN1_OBJECT WOLFSSL_ASN1_OBJECT; + +typedef struct WOLFSSL_ASN1_STRING WOLFSSL_ASN1_STRING; +typedef struct WOLFSSL_dynlock_value WOLFSSL_dynlock_value; +typedef struct WOLFSSL_DH WOLFSSL_DH; +typedef struct WOLFSSL_ASN1_BIT_STRING WOLFSSL_ASN1_BIT_STRING; + +#define WOLFSSL_ASN1_UTCTIME WOLFSSL_ASN1_TIME +#define WOLFSSL_ASN1_GENERALIZEDTIME WOLFSSL_ASN1_TIME + +#define WOLFSSL_ASN1_INTEGER_MAX 20 +struct WOLFSSL_ASN1_INTEGER { + /* size can be increased set at 20 for tag, length then to hold at least 16 + * byte type */ + unsigned char intData[WOLFSSL_ASN1_INTEGER_MAX]; + /* ASN_INTEGER | LENGTH | hex of number */ + unsigned char negative; /* negative number flag */ + + unsigned char* data; + unsigned int dataMax; /* max size of data buffer */ + unsigned int isDynamic:1; /* flag for if data pointer dynamic (1 is yes 0 is no) */ +}; + +struct WOLFSSL_ASN1_TIME { + /* MAX_DATA_SIZE is 32 */ + unsigned char data[32 + 2]; + /* ASN_TIME | LENGTH | date bytes */ +}; + +struct WOLFSSL_ASN1_STRING { + char strData[CTC_NAME_SIZE]; + int length; + int type; /* type of string i.e. CTC_UTF8 */ + char* data; + long flags; + unsigned int isDynamic:1; /* flag for if data pointer dynamic (1 is yes 0 is no) */ +}; + +#define WOLFSSL_MAX_SNAME 40 +struct WOLFSSL_ASN1_OBJECT { + void* heap; + const unsigned char* obj; + /* sName is short name i.e sha256 rather than oid (null terminated) */ + char sName[WOLFSSL_MAX_SNAME]; + int type; /* oid */ + int grp; /* type of OID, i.e. oidCertPolicyType */ + int nid; + unsigned int objSz; + unsigned char dynamic; /* if 1 then obj was dynamiclly created, 0 otherwise */ + #define WOLFSSL_ASN1_DYNAMIC 0x1 + #define WOLFSSL_ASN1_DYNAMIC_DATA 0x2 + struct d { /* derefrenced */ + WOLFSSL_ASN1_STRING ia5_internal; + WOLFSSL_ASN1_STRING* ia5; /* points to ia5_internal */ + WOLFSSL_ASN1_STRING* dNSName; + WOLFSSL_ASN1_STRING* iPAddress; + } d; +}; + +struct WOLFSSL_EVP_PKEY { + void* heap; + int type; /* openssh dereference */ + int save_type; /* openssh dereference */ + int pkey_sz; + union { + char* ptr; /* der format of key / or raw for NTRU */ + } pkey; + #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) + #ifndef NO_RSA + WOLFSSL_RSA* rsa; + byte ownRsa; /* if struct owns RSA and should free it */ + #endif + #ifdef HAVE_ECC + WOLFSSL_EC_KEY* ecc; + byte ownEcc; /* if struct owns ECC and should free it */ + #endif + WC_RNG rng; + #endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ + #ifdef HAVE_ECC + int pkey_curve; + #endif +}; +typedef struct WOLFSSL_EVP_PKEY WOLFSSL_PKCS8_PRIV_KEY_INFO; + +#ifndef WOLFSSL_EVP_TYPE_DEFINED /* guard on redeclaration */ +typedef struct WOLFSSL_EVP_PKEY WOLFSSL_EVP_PKEY; +typedef char WOLFSSL_EVP_MD; +#define WOLFSSL_EVP_TYPE_DEFINED +#endif + +#define WOLFSSL_EVP_PKEY_DEFAULT EVP_PKEY_RSA /* default key type */ + + +enum BIO_TYPE { + WOLFSSL_BIO_BUFFER = 1, + WOLFSSL_BIO_SOCKET = 2, + WOLFSSL_BIO_SSL = 3, + WOLFSSL_BIO_MEMORY = 4, + WOLFSSL_BIO_BIO = 5, + WOLFSSL_BIO_FILE = 6, + WOLFSSL_BIO_BASE64 = 7 +}; + +enum BIO_FLAGS { + WOLFSSL_BIO_FLAG_BASE64_NO_NL = 0x01, + WOLFSSL_BIO_FLAG_READ = 0x02, + WOLFSSL_BIO_FLAG_WRITE = 0x04, + WOLFSSL_BIO_FLAG_IO_SPECIAL = 0x08, + WOLFSSL_BIO_FLAG_RETRY = 0x10 +}; + +typedef struct WOLFSSL_BUF_MEM { + char* data; /* dereferenced */ + size_t length; /* current length */ + size_t max; /* maximum length */ +} WOLFSSL_BUF_MEM; + +typedef struct WOLFSSL_COMP_METHOD { + int type; /* stunnel dereference */ +} WOLFSSL_COMP_METHOD; + +struct WOLFSSL_X509_LOOKUP_METHOD { + int type; +}; + +struct WOLFSSL_X509_LOOKUP { + WOLFSSL_X509_STORE *store; +}; + +struct WOLFSSL_X509_STORE { + int cache; /* stunnel dereference */ + WOLFSSL_CERT_MANAGER* cm; + WOLFSSL_X509_LOOKUP lookup; +#ifdef OPENSSL_EXTRA + int isDynamic; +#endif +#if defined(OPENSSL_EXTRA) && defined(HAVE_CRL) + WOLFSSL_X509_CRL *crl; +#endif +}; + +#ifdef OPENSSL_EXTRA +#define WOLFSSL_USE_CHECK_TIME 0x2 +#define WOLFSSL_NO_CHECK_TIME 0x200000 +#define WOLFSSL_NO_WILDCARDS 0x4 +struct WOLFSSL_X509_VERIFY_PARAM { + time_t check_time; + unsigned long flags; +}; +#endif + +typedef struct WOLFSSL_ALERT { + int code; + int level; +} WOLFSSL_ALERT; + +typedef struct WOLFSSL_ALERT_HISTORY { + WOLFSSL_ALERT last_rx; + WOLFSSL_ALERT last_tx; +} WOLFSSL_ALERT_HISTORY; + +typedef struct WOLFSSL_X509_REVOKED { + WOLFSSL_ASN1_INTEGER* serialNumber; /* stunnel dereference */ +} WOLFSSL_X509_REVOKED; + + +typedef struct WOLFSSL_X509_OBJECT { + union { + char* ptr; + WOLFSSL_X509 *x509; + WOLFSSL_X509_CRL* crl; /* stunnel dereference */ + } data; +} WOLFSSL_X509_OBJECT; + +typedef struct WOLFSSL_BUFFER_INFO { + unsigned char* buffer; + unsigned int length; +} WOLFSSL_BUFFER_INFO; + +typedef struct WOLFSSL_X509_STORE_CTX { + WOLFSSL_X509_STORE* store; /* Store full of a CA cert chain */ + WOLFSSL_X509* current_cert; /* current X509 (OPENSSL_EXTRA) */ +#ifdef WOLFSSL_ASIO + WOLFSSL_X509* current_issuer; /* asio dereference */ +#endif + WOLFSSL_X509_CHAIN* sesChain; /* pointer to WOLFSSL_SESSION peer chain */ + WOLFSSL_STACK* chain; +#ifdef OPENSSL_EXTRA + WOLFSSL_X509_VERIFY_PARAM* param; /* certificate validation parameter */ +#endif + char* domain; /* subject CN domain name */ + void* ex_data; /* external data, for fortress build */ + void* userCtx; /* user ctx */ + int error; /* current error */ + int error_depth; /* index of cert depth for this error */ + int discardSessionCerts; /* so verify callback can flag for discard */ + int totalCerts; /* number of peer cert buffers */ + WOLFSSL_BUFFER_INFO* certs; /* peer certs */ + WOLFSSL_X509_STORE_CTX_verify_cb verify_cb; /* verify callback */ +} WOLFSSL_X509_STORE_CTX; + +typedef char* WOLFSSL_STRING; + +/* Valid Alert types from page 16/17 + * Add alert string to the function wolfSSL_alert_type_string_long in src/ssl.c + */ +enum AlertDescription { + close_notify = 0, + unexpected_message = 10, + bad_record_mac = 20, + record_overflow = 22, + decompression_failure = 30, + handshake_failure = 40, + no_certificate = 41, + bad_certificate = 42, + unsupported_certificate = 43, + certificate_revoked = 44, + certificate_expired = 45, + certificate_unknown = 46, + illegal_parameter = 47, + unknown_ca = 48, + decode_error = 50, + decrypt_error = 51, + #ifdef WOLFSSL_MYSQL_COMPATIBLE + /* catch name conflict for enum protocol with MYSQL build */ + wc_protocol_version = 70, + #else + protocol_version = 70, + #endif + inappropriate_fallback = 86, + no_renegotiation = 100, + missing_extension = 109, + unsupported_extension = 110, /**< RFC 5246, section 7.2.2 */ + unrecognized_name = 112, /**< RFC 6066, section 3 */ + bad_certificate_status_response = 113, /**< RFC 6066, section 8 */ + unknown_psk_identity = 115, /**< RFC 4279, section 2 */ + no_application_protocol = 120 +}; + + +enum AlertLevel { + alert_warning = 1, + alert_fatal = 2 +}; + +/* Maximum master key length (SECRET_LEN) */ +#define WOLFSSL_MAX_MASTER_KEY_LENGTH 48 +/* Maximum number of groups that can be set */ +#define WOLFSSL_MAX_GROUP_COUNT 10 + +typedef WOLFSSL_METHOD* (*wolfSSL_method_func)(void* heap); + +/* CTX Method EX Constructor Functions */ +WOLFSSL_API WOLFSSL_METHOD *wolfSSLv3_server_method_ex(void* heap); +WOLFSSL_API WOLFSSL_METHOD *wolfSSLv3_client_method_ex(void* heap); +WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_method_ex(void* heap); +WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_server_method_ex(void* heap); +WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_client_method_ex(void* heap); +WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_1_method_ex(void* heap); +WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_1_server_method_ex(void* heap); +WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_1_client_method_ex(void* heap); +WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_2_method_ex(void* heap); +WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_2_server_method_ex(void* heap); +WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_2_client_method_ex(void* heap); +#ifdef WOLFSSL_TLS13 + WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_3_method_ex(void* heap); + WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_3_server_method_ex(void* heap); + WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_3_client_method_ex(void* heap); +#endif + +WOLFSSL_API WOLFSSL_METHOD *wolfSSLv23_method_ex(void* heap); +WOLFSSL_API WOLFSSL_METHOD *wolfSSLv23_server_method_ex(void* heap); +WOLFSSL_API WOLFSSL_METHOD *wolfSSLv23_client_method_ex(void* heap); + +#ifdef WOLFSSL_DTLS + WOLFSSL_API WOLFSSL_METHOD *wolfDTLS_method_ex(void* heap); + WOLFSSL_API WOLFSSL_METHOD *wolfDTLS_client_method_ex(void* heap); + WOLFSSL_API WOLFSSL_METHOD *wolfDTLS_server_method_ex(void* heap); + WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_method_ex(void* heap); + WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_client_method_ex(void* heap); + WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_server_method_ex(void* heap); + WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_2_method_ex(void* heap); + WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_2_client_method_ex(void* heap); + WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_2_server_method_ex(void* heap); +#endif + +/* CTX Method Constructor Functions */ +WOLFSSL_API WOLFSSL_METHOD *wolfSSLv23_method(void); +WOLFSSL_API WOLFSSL_METHOD *wolfSSLv3_server_method(void); +WOLFSSL_API WOLFSSL_METHOD *wolfSSLv3_client_method(void); +WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_method(void); +WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_server_method(void); +WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_client_method(void); +WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_1_method(void); +WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_1_server_method(void); +WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_1_client_method(void); +WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_2_method(void); +WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_2_server_method(void); +WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_2_client_method(void); +#ifdef WOLFSSL_TLS13 + WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_3_method(void); + WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_3_server_method(void); + WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_3_client_method(void); +#endif + +#ifdef WOLFSSL_DTLS + WOLFSSL_API WOLFSSL_METHOD *wolfDTLS_method(void); + WOLFSSL_API WOLFSSL_METHOD *wolfDTLS_server_method(void); + WOLFSSL_API WOLFSSL_METHOD *wolfDTLS_client_method(void); + WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_method(void); + WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_client_method(void); + WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_server_method(void); + WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_2_method(void); + WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_2_client_method(void); + WOLFSSL_API WOLFSSL_METHOD *wolfDTLSv1_2_server_method(void); +#endif + +#ifdef HAVE_POLY1305 + WOLFSSL_API int wolfSSL_use_old_poly(WOLFSSL*, int); +#endif + +#ifdef WOLFSSL_SESSION_EXPORT +#ifdef WOLFSSL_DTLS + +#ifndef WOLFSSL_DTLS_EXPORT_TYPES +typedef int (*wc_dtls_export)(WOLFSSL* ssl, + unsigned char* exportBuffer, unsigned int sz, void* userCtx); +#define WOLFSSL_DTLS_EXPORT_TYPES +#endif /* WOLFSSL_DTLS_EXPORT_TYPES */ + +WOLFSSL_API int wolfSSL_dtls_import(WOLFSSL* ssl, unsigned char* buf, + unsigned int sz); +WOLFSSL_API int wolfSSL_CTX_dtls_set_export(WOLFSSL_CTX* ctx, + wc_dtls_export func); +WOLFSSL_API int wolfSSL_dtls_set_export(WOLFSSL* ssl, wc_dtls_export func); +WOLFSSL_API int wolfSSL_dtls_export(WOLFSSL* ssl, unsigned char* buf, + unsigned int* sz); +WOLFSSL_API int wolfSSL_dtls_export_state_only(WOLFSSL* ssl, unsigned char* buf, + unsigned int* sz); +#endif /* WOLFSSL_DTLS */ +#endif /* WOLFSSL_SESSION_EXPORT */ + +#ifdef WOLFSSL_STATIC_MEMORY +#ifndef WOLFSSL_MEM_GUARD +#define WOLFSSL_MEM_GUARD + typedef struct WOLFSSL_MEM_STATS WOLFSSL_MEM_STATS; + typedef struct WOLFSSL_MEM_CONN_STATS WOLFSSL_MEM_CONN_STATS; +#endif +WOLFSSL_API int wolfSSL_CTX_load_static_memory(WOLFSSL_CTX** ctx, + wolfSSL_method_func method, + unsigned char* buf, unsigned int sz, + int flag, int max); +WOLFSSL_API int wolfSSL_CTX_is_static_memory(WOLFSSL_CTX* ctx, + WOLFSSL_MEM_STATS* mem_stats); +WOLFSSL_API int wolfSSL_is_static_memory(WOLFSSL* ssl, + WOLFSSL_MEM_CONN_STATS* mem_stats); +#endif + +#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) + +WOLFSSL_API int wolfSSL_CTX_use_certificate_file(WOLFSSL_CTX*, const char*, int); +WOLFSSL_API int wolfSSL_CTX_use_PrivateKey_file(WOLFSSL_CTX*, const char*, int); + +#define WOLFSSL_LOAD_FLAG_NONE 0x00000000 +#define WOLFSSL_LOAD_FLAG_IGNORE_ERR 0x00000001 +#define WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY 0x00000002 +#define WOLFSSL_LOAD_FLAG_PEM_CA_ONLY 0x00000004 +WOLFSSL_API int wolfSSL_CTX_load_verify_locations_ex(WOLFSSL_CTX*, const char*, + const char*, unsigned int); +WOLFSSL_API int wolfSSL_CTX_load_verify_locations(WOLFSSL_CTX*, const char*, + const char*); +#ifdef WOLFSSL_TRUST_PEER_CERT +WOLFSSL_API int wolfSSL_CTX_trust_peer_cert(WOLFSSL_CTX*, const char*, int); +#endif +WOLFSSL_API int wolfSSL_CTX_use_certificate_chain_file(WOLFSSL_CTX *, + const char *file); +WOLFSSL_API int wolfSSL_CTX_use_certificate_chain_file_format(WOLFSSL_CTX *, + const char *file, int format); +WOLFSSL_API int wolfSSL_CTX_use_RSAPrivateKey_file(WOLFSSL_CTX*, const char*, int); + +WOLFSSL_API long wolfSSL_get_verify_depth(WOLFSSL* ssl); +WOLFSSL_API long wolfSSL_CTX_get_verify_depth(WOLFSSL_CTX* ctx); +WOLFSSL_API void wolfSSL_CTX_set_verify_depth(WOLFSSL_CTX *ctx,int depth); +WOLFSSL_API int wolfSSL_use_certificate_file(WOLFSSL*, const char*, int); +WOLFSSL_API int wolfSSL_use_PrivateKey_file(WOLFSSL*, const char*, int); +WOLFSSL_API int wolfSSL_use_certificate_chain_file(WOLFSSL*, const char *file); +WOLFSSL_API int wolfSSL_use_certificate_chain_file_format(WOLFSSL*, + const char *file, int format); +WOLFSSL_API int wolfSSL_use_RSAPrivateKey_file(WOLFSSL*, const char*, int); + +#ifdef WOLFSSL_DER_LOAD + WOLFSSL_API int wolfSSL_CTX_der_load_verify_locations(WOLFSSL_CTX*, + const char*, int); +#endif + +#ifdef HAVE_NTRU + WOLFSSL_API int wolfSSL_CTX_use_NTRUPrivateKey_file(WOLFSSL_CTX*, const char*); + /* load NTRU private key blob */ +#endif + +#endif /* !NO_FILESYSTEM && !NO_CERTS */ + +WOLFSSL_API WOLFSSL_CTX* wolfSSL_CTX_new_ex(WOLFSSL_METHOD* method, void* heap); +WOLFSSL_API WOLFSSL_CTX* wolfSSL_CTX_new(WOLFSSL_METHOD*); +WOLFSSL_API WOLFSSL* wolfSSL_new(WOLFSSL_CTX*); +WOLFSSL_API WOLFSSL_CTX* wolfSSL_get_SSL_CTX(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_is_server(WOLFSSL*); +WOLFSSL_API WOLFSSL* wolfSSL_write_dup(WOLFSSL*); +WOLFSSL_API int wolfSSL_set_fd (WOLFSSL*, int); +WOLFSSL_API int wolfSSL_set_write_fd (WOLFSSL*, int); +WOLFSSL_API int wolfSSL_set_read_fd (WOLFSSL*, int); +WOLFSSL_API char* wolfSSL_get_cipher_list(int priority); +WOLFSSL_API char* wolfSSL_get_cipher_list_ex(WOLFSSL* ssl, int priority); +WOLFSSL_API int wolfSSL_get_ciphers(char*, int); +WOLFSSL_API int wolfSSL_get_ciphers_iana(char*, int); +WOLFSSL_API const char* wolfSSL_get_cipher_name(WOLFSSL* ssl); +WOLFSSL_API const char* wolfSSL_get_cipher_name_from_suite(const unsigned char, + const unsigned char); +WOLFSSL_API const char* wolfSSL_get_shared_ciphers(WOLFSSL* ssl, char* buf, + int len); +WOLFSSL_API const char* wolfSSL_get_curve_name(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_get_fd(const WOLFSSL*); +/* please see note at top of README if you get an error from connect */ +WOLFSSL_API int wolfSSL_connect(WOLFSSL*); +WOLFSSL_API int wolfSSL_write(WOLFSSL*, const void*, int); +WOLFSSL_API int wolfSSL_read(WOLFSSL*, void*, int); +WOLFSSL_API int wolfSSL_peek(WOLFSSL*, void*, int); +WOLFSSL_API int wolfSSL_accept(WOLFSSL*); +#ifdef WOLFSSL_TLS13 +WOLFSSL_API int wolfSSL_send_hrr_cookie(WOLFSSL* ssl, + const unsigned char* secret, unsigned int secretSz); +WOLFSSL_API int wolfSSL_CTX_no_ticket_TLSv13(WOLFSSL_CTX* ctx); +WOLFSSL_API int wolfSSL_no_ticket_TLSv13(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_CTX_no_dhe_psk(WOLFSSL_CTX* ctx); +WOLFSSL_API int wolfSSL_no_dhe_psk(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_update_keys(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_CTX_allow_post_handshake_auth(WOLFSSL_CTX* ctx); +WOLFSSL_API int wolfSSL_allow_post_handshake_auth(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_request_certificate(WOLFSSL* ssl); + +WOLFSSL_API int wolfSSL_preferred_group(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_CTX_set_groups(WOLFSSL_CTX* ctx, int* groups, + int count); +WOLFSSL_API int wolfSSL_set_groups(WOLFSSL* ssl, int* groups, int count); + +WOLFSSL_API int wolfSSL_connect_TLSv13(WOLFSSL*); +WOLFSSL_API int wolfSSL_accept_TLSv13(WOLFSSL*); + +#ifdef WOLFSSL_EARLY_DATA +WOLFSSL_API int wolfSSL_CTX_set_max_early_data(WOLFSSL_CTX* ctx, + unsigned int sz); +WOLFSSL_API int wolfSSL_set_max_early_data(WOLFSSL* ssl, unsigned int sz); +WOLFSSL_API int wolfSSL_write_early_data(WOLFSSL*, const void*, int, int*); +WOLFSSL_API int wolfSSL_read_early_data(WOLFSSL*, void*, int, int*); +#endif +#endif +WOLFSSL_API void wolfSSL_CTX_free(WOLFSSL_CTX*); +WOLFSSL_API void wolfSSL_free(WOLFSSL*); +WOLFSSL_API int wolfSSL_shutdown(WOLFSSL*); +WOLFSSL_API int wolfSSL_send(WOLFSSL*, const void*, int sz, int flags); +WOLFSSL_API int wolfSSL_recv(WOLFSSL*, void*, int sz, int flags); + +WOLFSSL_API void wolfSSL_CTX_set_quiet_shutdown(WOLFSSL_CTX*, int); +WOLFSSL_API void wolfSSL_set_quiet_shutdown(WOLFSSL*, int); + +WOLFSSL_API int wolfSSL_get_error(WOLFSSL*, int); +WOLFSSL_API int wolfSSL_get_alert_history(WOLFSSL*, WOLFSSL_ALERT_HISTORY *); + +WOLFSSL_API int wolfSSL_set_session(WOLFSSL*, WOLFSSL_SESSION*); +WOLFSSL_API long wolfSSL_SSL_SESSION_set_timeout(WOLFSSL_SESSION*, long); +WOLFSSL_API WOLFSSL_SESSION* wolfSSL_get_session(WOLFSSL*); +WOLFSSL_API void wolfSSL_flush_sessions(WOLFSSL_CTX*, long); +WOLFSSL_API int wolfSSL_SetServerID(WOLFSSL*, const unsigned char*, int, int); + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_ASIO) +WOLFSSL_API int wolfSSL_BIO_new_bio_pair(WOLFSSL_BIO**, size_t, + WOLFSSL_BIO**, size_t); + +WOLFSSL_API WOLFSSL_RSA* wolfSSL_d2i_RSAPrivateKey_bio(WOLFSSL_BIO*, WOLFSSL_RSA**); +WOLFSSL_API int wolfSSL_CTX_use_certificate_ASN1(WOLFSSL_CTX*, + int, const unsigned char*); +WOLFSSL_API int wolfSSL_CTX_use_RSAPrivateKey(WOLFSSL_CTX*, WOLFSSL_RSA*); +WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey_bio(WOLFSSL_BIO*, WOLFSSL_EVP_PKEY**); +#endif /* OPENSSL_ALL || WOLFSSL_ASIO */ + +#ifdef SESSION_INDEX +WOLFSSL_API int wolfSSL_GetSessionIndex(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_GetSessionAtIndex(int index, WOLFSSL_SESSION* session); +#endif /* SESSION_INDEX */ + +#if defined(SESSION_INDEX) && defined(SESSION_CERTS) +WOLFSSL_API + WOLFSSL_X509_CHAIN* wolfSSL_SESSION_get_peer_chain(WOLFSSL_SESSION* session); +#endif /* SESSION_INDEX && SESSION_CERTS */ + +typedef int (*VerifyCallback)(int, WOLFSSL_X509_STORE_CTX*); +#ifdef OPENSSL_EXTRA +typedef void (CallbackInfoState)(const WOLFSSL*, int, int); + +typedef struct WOLFSSL_CRYPTO_EX_DATA { + WOLFSSL_STACK* data; +} WOLFSSL_CRYPTO_EX_DATA; + +typedef int (WOLFSSL_CRYPTO_EX_new)(void* p, void* ptr, + WOLFSSL_CRYPTO_EX_DATA* a, int idx, long argValue, void* arg); +typedef int (WOLFSSL_CRYPTO_EX_dup)(WOLFSSL_CRYPTO_EX_DATA* out, + WOLFSSL_CRYPTO_EX_DATA* in, void* inPtr, int idx, long argV, void* arg); +typedef void (WOLFSSL_CRYPTO_EX_free)(void* p, void* ptr, + WOLFSSL_CRYPTO_EX_DATA* a, int idx, long argValue, void* arg); + +WOLFSSL_API int wolfSSL_get_ex_new_index(long argValue, void* arg, + WOLFSSL_CRYPTO_EX_new* a, WOLFSSL_CRYPTO_EX_dup* b, + WOLFSSL_CRYPTO_EX_free* c); +#endif + +WOLFSSL_API void wolfSSL_CTX_set_verify(WOLFSSL_CTX*, int, + VerifyCallback verify_callback); +WOLFSSL_API void wolfSSL_set_verify(WOLFSSL*, int, VerifyCallback verify_callback); +WOLFSSL_API void wolfSSL_SetCertCbCtx(WOLFSSL*, void*); + +WOLFSSL_API int wolfSSL_pending(WOLFSSL*); + +WOLFSSL_API void wolfSSL_load_error_strings(void); +WOLFSSL_API int wolfSSL_library_init(void); +WOLFSSL_API long wolfSSL_CTX_set_session_cache_mode(WOLFSSL_CTX*, long); + +#ifdef HAVE_SECRET_CALLBACK +typedef int (*SessionSecretCb)(WOLFSSL* ssl, + void* secret, int* secretSz, void* ctx); +WOLFSSL_API int wolfSSL_set_session_secret_cb(WOLFSSL*, SessionSecretCb, void*); +#endif /* HAVE_SECRET_CALLBACK */ + +/* session cache persistence */ +WOLFSSL_API int wolfSSL_save_session_cache(const char*); +WOLFSSL_API int wolfSSL_restore_session_cache(const char*); +WOLFSSL_API int wolfSSL_memsave_session_cache(void*, int); +WOLFSSL_API int wolfSSL_memrestore_session_cache(const void*, int); +WOLFSSL_API int wolfSSL_get_session_cache_memsize(void); + +/* certificate cache persistence, uses ctx since certs are per ctx */ +WOLFSSL_API int wolfSSL_CTX_save_cert_cache(WOLFSSL_CTX*, const char*); +WOLFSSL_API int wolfSSL_CTX_restore_cert_cache(WOLFSSL_CTX*, const char*); +WOLFSSL_API int wolfSSL_CTX_memsave_cert_cache(WOLFSSL_CTX*, void*, int, int*); +WOLFSSL_API int wolfSSL_CTX_memrestore_cert_cache(WOLFSSL_CTX*, const void*, int); +WOLFSSL_API int wolfSSL_CTX_get_cert_cache_memsize(WOLFSSL_CTX*); + +/* only supports full name from cipher_name[] delimited by : */ +WOLFSSL_API int wolfSSL_CTX_set_cipher_list(WOLFSSL_CTX*, const char*); +WOLFSSL_API int wolfSSL_set_cipher_list(WOLFSSL*, const char*); + +/* Nonblocking DTLS helper functions */ +WOLFSSL_API void wolfSSL_dtls_set_using_nonblock(WOLFSSL*, int); +WOLFSSL_API int wolfSSL_dtls_get_using_nonblock(WOLFSSL*); +#define wolfSSL_set_using_nonblock wolfSSL_dtls_set_using_nonblock +#define wolfSSL_get_using_nonblock wolfSSL_dtls_get_using_nonblock + /* The old names are deprecated. */ +WOLFSSL_API int wolfSSL_dtls_get_current_timeout(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_dtls_set_timeout_init(WOLFSSL* ssl, int); +WOLFSSL_API int wolfSSL_dtls_set_timeout_max(WOLFSSL* ssl, int); +WOLFSSL_API int wolfSSL_dtls_got_timeout(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_dtls_retransmit(WOLFSSL*); +WOLFSSL_API int wolfSSL_dtls(WOLFSSL* ssl); + +WOLFSSL_API int wolfSSL_dtls_set_peer(WOLFSSL*, void*, unsigned int); +WOLFSSL_API int wolfSSL_dtls_get_peer(WOLFSSL*, void*, unsigned int*); + +WOLFSSL_API int wolfSSL_CTX_dtls_set_sctp(WOLFSSL_CTX*); +WOLFSSL_API int wolfSSL_dtls_set_sctp(WOLFSSL*); +WOLFSSL_API int wolfSSL_CTX_dtls_set_mtu(WOLFSSL_CTX*, unsigned short); +WOLFSSL_API int wolfSSL_dtls_set_mtu(WOLFSSL*, unsigned short); + +WOLFSSL_API int wolfSSL_dtls_get_drop_stats(WOLFSSL*, + unsigned int*, unsigned int*); +WOLFSSL_API int wolfSSL_CTX_mcast_set_member_id(WOLFSSL_CTX*, unsigned short); +WOLFSSL_API int wolfSSL_set_secret(WOLFSSL*, unsigned short, + const unsigned char*, unsigned int, + const unsigned char*, const unsigned char*, + const unsigned char*); +WOLFSSL_API int wolfSSL_mcast_read(WOLFSSL*, unsigned short*, void*, int); +WOLFSSL_API int wolfSSL_mcast_peer_add(WOLFSSL*, unsigned short, int); +WOLFSSL_API int wolfSSL_mcast_peer_known(WOLFSSL*, unsigned short); +WOLFSSL_API int wolfSSL_mcast_get_max_peers(void); +typedef int (*CallbackMcastHighwater)(unsigned short peerId, + unsigned int maxSeq, + unsigned int curSeq, void* ctx); +WOLFSSL_API int wolfSSL_CTX_mcast_set_highwater_cb(WOLFSSL_CTX*, + unsigned int, + unsigned int, + unsigned int, + CallbackMcastHighwater); +WOLFSSL_API int wolfSSL_mcast_set_highwater_ctx(WOLFSSL*, void*); + +WOLFSSL_API int wolfSSL_ERR_GET_REASON(unsigned long err); +WOLFSSL_API char* wolfSSL_ERR_error_string(unsigned long,char*); +WOLFSSL_API void wolfSSL_ERR_error_string_n(unsigned long e, char* buf, + unsigned long sz); +WOLFSSL_API const char* wolfSSL_ERR_reason_error_string(unsigned long); + +/* extras */ + +#ifndef WOLF_STACK_OF + #define WOLF_STACK_OF(x) WOLFSSL_STACK +#endif +#ifndef DECLARE_STACK_OF + #define DECLARE_STACK_OF(x) WOLF_STACK_OF(x); +#endif + +#if defined(HAVE_OCSP) +#include "wolfssl/ocsp.h" +#include "wolfssl/wolfcrypt/asn.h" +#endif + +WOLFSSL_API int wolfSSL_sk_X509_push(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk, + WOLFSSL_X509* x509); +WOLFSSL_API WOLFSSL_X509* wolfSSL_sk_X509_pop(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk); +WOLFSSL_API void wolfSSL_sk_X509_free(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk); +WOLFSSL_API WOLFSSL_ASN1_OBJECT* wolfSSL_sk_GENERAL_NAME_value( + WOLFSSL_STACK* sk, int i); +WOLFSSL_API int wolfSSL_sk_GENERAL_NAME_num(WOLFSSL_STACK* sk); +WOLFSSL_API void wolfSSL_sk_GENERAL_NAME_pop_free(WOLFSSL_STACK* sk, + void f (WOLFSSL_ASN1_OBJECT*)); +WOLFSSL_API WOLFSSL_ASN1_OBJECT* wolfSSL_ASN1_OBJECT_new(void); +WOLFSSL_API void wolfSSL_ASN1_OBJECT_free(WOLFSSL_ASN1_OBJECT* obj); +WOLFSSL_API int wolfSSL_sk_ASN1_OBJECT_push(WOLF_STACK_OF(WOLFSSL_ASN1_OBJEXT)* sk, + WOLFSSL_ASN1_OBJECT* obj); +WOLFSSL_API WOLFSSL_ASN1_OBJECT* wolfSSL_sk_ASN1_OBJECT_pop( + WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk); +WOLFSSL_API void wolfSSL_sk_ASN1_OBJECT_free(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)* sk); +WOLFSSL_API int wolfSSL_ASN1_STRING_to_UTF8(unsigned char **out, WOLFSSL_ASN1_STRING *in); + +WOLFSSL_API int wolfSSL_set_ex_data(WOLFSSL*, int, void*); +WOLFSSL_API int wolfSSL_get_shutdown(const WOLFSSL*); +WOLFSSL_API int wolfSSL_set_rfd(WOLFSSL*, int); +WOLFSSL_API int wolfSSL_set_wfd(WOLFSSL*, int); +WOLFSSL_API void wolfSSL_set_shutdown(WOLFSSL*, int); +WOLFSSL_API int wolfSSL_set_session_id_context(WOLFSSL*, const unsigned char*, + unsigned int); +WOLFSSL_API void wolfSSL_set_connect_state(WOLFSSL*); +WOLFSSL_API void wolfSSL_set_accept_state(WOLFSSL*); +WOLFSSL_API int wolfSSL_session_reused(WOLFSSL*); +WOLFSSL_API void wolfSSL_SESSION_free(WOLFSSL_SESSION* session); +WOLFSSL_API int wolfSSL_is_init_finished(WOLFSSL*); + +WOLFSSL_API const char* wolfSSL_get_version(WOLFSSL*); +WOLFSSL_API int wolfSSL_get_current_cipher_suite(WOLFSSL* ssl); +WOLFSSL_API WOLFSSL_CIPHER* wolfSSL_get_current_cipher(WOLFSSL*); +WOLFSSL_API char* wolfSSL_CIPHER_description(const WOLFSSL_CIPHER*, char*, int); +WOLFSSL_API const char* wolfSSL_CIPHER_get_name(const WOLFSSL_CIPHER* cipher); +WOLFSSL_API const char* wolfSSL_SESSION_CIPHER_get_name(WOLFSSL_SESSION* session); +WOLFSSL_API const char* wolfSSL_get_cipher(WOLFSSL*); +WOLFSSL_API WOLFSSL_SESSION* wolfSSL_get1_session(WOLFSSL* ssl); + /* what's ref count */ + +WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_new(void); + +WOLFSSL_API int wolfSSL_OCSP_parse_url(char* url, char** host, char** port, + char** path, int* ssl); + +WOLFSSL_API WOLFSSL_METHOD* wolfSSLv23_client_method(void); +WOLFSSL_API WOLFSSL_METHOD* wolfSSLv2_client_method(void); +WOLFSSL_API WOLFSSL_METHOD* wolfSSLv2_server_method(void); + +WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_new(WOLFSSL_BIO_METHOD*); +WOLFSSL_API int wolfSSL_BIO_free(WOLFSSL_BIO*); +WOLFSSL_API int wolfSSL_BIO_free_all(WOLFSSL_BIO*); +WOLFSSL_API int wolfSSL_BIO_gets(WOLFSSL_BIO* bio, char* buf, int sz); +WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_next(WOLFSSL_BIO* bio); +WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_find_type(WOLFSSL_BIO* bio, int type); +WOLFSSL_API int wolfSSL_BIO_read(WOLFSSL_BIO*, void*, int); +WOLFSSL_API int wolfSSL_BIO_write(WOLFSSL_BIO*, const void*, int); +WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_push(WOLFSSL_BIO*, WOLFSSL_BIO* append); +WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_pop(WOLFSSL_BIO*); +WOLFSSL_API int wolfSSL_BIO_flush(WOLFSSL_BIO*); +WOLFSSL_API int wolfSSL_BIO_pending(WOLFSSL_BIO*); + +WOLFSSL_API WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_buffer(void); +WOLFSSL_API long wolfSSL_BIO_set_write_buffer_size(WOLFSSL_BIO*, long size); +WOLFSSL_API WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_ssl(void); +WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_new_socket(int sfd, int flag); +WOLFSSL_API int wolfSSL_BIO_eof(WOLFSSL_BIO*); + +WOLFSSL_API WOLFSSL_BIO_METHOD* wolfSSL_BIO_s_mem(void); +WOLFSSL_API WOLFSSL_BIO_METHOD* wolfSSL_BIO_f_base64(void); +WOLFSSL_API void wolfSSL_BIO_set_flags(WOLFSSL_BIO*, int); + +WOLFSSL_API int wolfSSL_BIO_get_mem_data(WOLFSSL_BIO* bio,void* p); +WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_new_mem_buf(void* buf, int len); + + +WOLFSSL_API long wolfSSL_BIO_set_ssl(WOLFSSL_BIO*, WOLFSSL*, int flag); +WOLFSSL_API long wolfSSL_BIO_set_fd(WOLFSSL_BIO* b, int fd, int flag); +WOLFSSL_API void wolfSSL_set_bio(WOLFSSL*, WOLFSSL_BIO* rd, WOLFSSL_BIO* wr); + +#ifndef NO_FILESYSTEM +WOLFSSL_API WOLFSSL_BIO_METHOD *wolfSSL_BIO_s_file(void); +#endif + +WOLFSSL_API WOLFSSL_BIO_METHOD *wolfSSL_BIO_s_bio(void); +WOLFSSL_API WOLFSSL_BIO_METHOD *wolfSSL_BIO_s_socket(void); + +WOLFSSL_API long wolfSSL_BIO_ctrl(WOLFSSL_BIO *bp, int cmd, long larg, void *parg); +WOLFSSL_API long wolfSSL_BIO_int_ctrl(WOLFSSL_BIO *bp, int cmd, long larg, int iarg); + +WOLFSSL_API int wolfSSL_BIO_set_write_buf_size(WOLFSSL_BIO *b, long size); +WOLFSSL_API int wolfSSL_BIO_make_bio_pair(WOLFSSL_BIO *b1, WOLFSSL_BIO *b2); +WOLFSSL_API int wolfSSL_BIO_ctrl_reset_read_request(WOLFSSL_BIO *b); +WOLFSSL_API int wolfSSL_BIO_nread0(WOLFSSL_BIO *bio, char **buf); +WOLFSSL_API int wolfSSL_BIO_nread(WOLFSSL_BIO *bio, char **buf, int num); +WOLFSSL_API int wolfSSL_BIO_nwrite(WOLFSSL_BIO *bio, char **buf, int num); +WOLFSSL_API int wolfSSL_BIO_reset(WOLFSSL_BIO *bio); + +WOLFSSL_API int wolfSSL_BIO_seek(WOLFSSL_BIO *bio, int ofs); +WOLFSSL_API int wolfSSL_BIO_write_filename(WOLFSSL_BIO *bio, char *name); +WOLFSSL_API long wolfSSL_BIO_set_mem_eof_return(WOLFSSL_BIO *bio, int v); +WOLFSSL_API long wolfSSL_BIO_get_mem_ptr(WOLFSSL_BIO *bio, WOLFSSL_BUF_MEM **m); + +WOLFSSL_API void wolfSSL_RAND_screen(void); +WOLFSSL_API const char* wolfSSL_RAND_file_name(char*, unsigned long); +WOLFSSL_API int wolfSSL_RAND_write_file(const char*); +WOLFSSL_API int wolfSSL_RAND_load_file(const char*, long); +WOLFSSL_API int wolfSSL_RAND_egd(const char*); +WOLFSSL_API int wolfSSL_RAND_seed(const void*, int); +WOLFSSL_API void wolfSSL_RAND_Cleanup(void); +WOLFSSL_API void wolfSSL_RAND_add(const void*, int, double); +WOLFSSL_API int wolfSSL_RAND_poll(void); + +WOLFSSL_API WOLFSSL_COMP_METHOD* wolfSSL_COMP_zlib(void); +WOLFSSL_API WOLFSSL_COMP_METHOD* wolfSSL_COMP_rle(void); +WOLFSSL_API int wolfSSL_COMP_add_compression_method(int, void*); + +WOLFSSL_API unsigned long wolfSSL_thread_id(void); +WOLFSSL_API void wolfSSL_set_id_callback(unsigned long (*f)(void)); +WOLFSSL_API void wolfSSL_set_locking_callback(void (*f)(int, int, const char*, + int)); +WOLFSSL_API void wolfSSL_set_dynlock_create_callback(WOLFSSL_dynlock_value* (*f) + (const char*, int)); +WOLFSSL_API void wolfSSL_set_dynlock_lock_callback(void (*f)(int, + WOLFSSL_dynlock_value*, const char*, int)); +WOLFSSL_API void wolfSSL_set_dynlock_destroy_callback(void (*f) + (WOLFSSL_dynlock_value*, const char*, int)); +WOLFSSL_API int wolfSSL_num_locks(void); + +WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_STORE_CTX_get_current_cert( + WOLFSSL_X509_STORE_CTX*); +WOLFSSL_API int wolfSSL_X509_STORE_CTX_get_error(WOLFSSL_X509_STORE_CTX*); +WOLFSSL_API int wolfSSL_X509_STORE_CTX_get_error_depth(WOLFSSL_X509_STORE_CTX*); + +WOLFSSL_API void wolfSSL_X509_STORE_CTX_set_verify_cb(WOLFSSL_X509_STORE_CTX *ctx, + WOLFSSL_X509_STORE_CTX_verify_cb verify_cb); +WOLFSSL_API int wolfSSL_i2d_X509_NAME(WOLFSSL_X509_NAME* n, + unsigned char** out); +WOLFSSL_API int wolfSSL_X509_print(WOLFSSL_BIO* bio, WOLFSSL_X509* x509); +WOLFSSL_API char* wolfSSL_X509_NAME_oneline(WOLFSSL_X509_NAME*, char*, int); +WOLFSSL_API WOLFSSL_X509_NAME* wolfSSL_X509_get_issuer_name(WOLFSSL_X509*); +WOLFSSL_API WOLFSSL_X509_NAME* wolfSSL_X509_get_subject_name(WOLFSSL_X509*); +WOLFSSL_API int wolfSSL_X509_ext_isSet_by_NID(WOLFSSL_X509*, int); +WOLFSSL_API int wolfSSL_X509_ext_get_critical_by_NID(WOLFSSL_X509*, int); +WOLFSSL_API int wolfSSL_X509_get_isCA(WOLFSSL_X509*); +WOLFSSL_API int wolfSSL_X509_get_isSet_pathLength(WOLFSSL_X509*); +WOLFSSL_API unsigned int wolfSSL_X509_get_pathLength(WOLFSSL_X509*); +WOLFSSL_API unsigned int wolfSSL_X509_get_keyUsage(WOLFSSL_X509*); +WOLFSSL_API unsigned char* wolfSSL_X509_get_authorityKeyID( + WOLFSSL_X509*, unsigned char*, int*); +WOLFSSL_API unsigned char* wolfSSL_X509_get_subjectKeyID( + WOLFSSL_X509*, unsigned char*, int*); + +WOLFSSL_API int wolfSSL_X509_verify(WOLFSSL_X509* x509, WOLFSSL_EVP_PKEY* pkey); +WOLFSSL_API int wolfSSL_X509_set_subject_name(WOLFSSL_X509*, + WOLFSSL_X509_NAME*); +WOLFSSL_API int wolfSSL_X509_set_pubkey(WOLFSSL_X509*, WOLFSSL_EVP_PKEY*); + +WOLFSSL_API int wolfSSL_X509_NAME_entry_count(WOLFSSL_X509_NAME*); +WOLFSSL_API int wolfSSL_X509_NAME_get_text_by_NID( + WOLFSSL_X509_NAME*, int, char*, int); +WOLFSSL_API int wolfSSL_X509_NAME_get_index_by_NID( + WOLFSSL_X509_NAME*, int, int); +WOLFSSL_API WOLFSSL_ASN1_STRING* wolfSSL_X509_NAME_ENTRY_get_data(WOLFSSL_X509_NAME_ENTRY*); + +WOLFSSL_API WOLFSSL_ASN1_STRING* wolfSSL_ASN1_STRING_new(void); +WOLFSSL_API WOLFSSL_ASN1_STRING* wolfSSL_ASN1_STRING_type_new(int type); +WOLFSSL_API void wolfSSL_ASN1_STRING_free(WOLFSSL_ASN1_STRING* asn1); +WOLFSSL_API int wolfSSL_ASN1_STRING_set(WOLFSSL_ASN1_STRING* asn1, + const void* data, int dataSz); +WOLFSSL_API unsigned char* wolfSSL_ASN1_STRING_data(WOLFSSL_ASN1_STRING*); +WOLFSSL_API int wolfSSL_ASN1_STRING_length(WOLFSSL_ASN1_STRING*); +WOLFSSL_API int wolfSSL_X509_verify_cert(WOLFSSL_X509_STORE_CTX*); +WOLFSSL_API const char* wolfSSL_X509_verify_cert_error_string(long); +WOLFSSL_API int wolfSSL_X509_get_signature_type(WOLFSSL_X509*); +WOLFSSL_API int wolfSSL_X509_get_signature(WOLFSSL_X509*, unsigned char*, int*); +WOLFSSL_API int wolfSSL_X509_get_pubkey_buffer(WOLFSSL_X509*, unsigned char*, + int*); +WOLFSSL_API int wolfSSL_X509_get_pubkey_type(WOLFSSL_X509* x509); + +WOLFSSL_API int wolfSSL_X509_LOOKUP_add_dir(WOLFSSL_X509_LOOKUP*,const char*,long); +WOLFSSL_API int wolfSSL_X509_LOOKUP_load_file(WOLFSSL_X509_LOOKUP*, const char*, + long); +WOLFSSL_API WOLFSSL_X509_LOOKUP_METHOD* wolfSSL_X509_LOOKUP_hash_dir(void); +WOLFSSL_API WOLFSSL_X509_LOOKUP_METHOD* wolfSSL_X509_LOOKUP_file(void); + +WOLFSSL_API WOLFSSL_X509_LOOKUP* wolfSSL_X509_STORE_add_lookup(WOLFSSL_X509_STORE*, + WOLFSSL_X509_LOOKUP_METHOD*); +WOLFSSL_API WOLFSSL_X509_STORE* wolfSSL_X509_STORE_new(void); +WOLFSSL_API void wolfSSL_X509_STORE_free(WOLFSSL_X509_STORE*); +WOLFSSL_API int wolfSSL_X509_STORE_add_cert( + WOLFSSL_X509_STORE*, WOLFSSL_X509*); +WOLFSSL_API WOLFSSL_STACK* wolfSSL_X509_STORE_CTX_get_chain( + WOLFSSL_X509_STORE_CTX* ctx); +WOLFSSL_API int wolfSSL_X509_STORE_set_flags(WOLFSSL_X509_STORE* store, + unsigned long flag); +WOLFSSL_API int wolfSSL_X509_STORE_set_default_paths(WOLFSSL_X509_STORE*); +WOLFSSL_API int wolfSSL_X509_STORE_get_by_subject(WOLFSSL_X509_STORE_CTX*, + int, WOLFSSL_X509_NAME*, WOLFSSL_X509_OBJECT*); +WOLFSSL_API WOLFSSL_X509_STORE_CTX* wolfSSL_X509_STORE_CTX_new(void); +WOLFSSL_API int wolfSSL_X509_STORE_CTX_init(WOLFSSL_X509_STORE_CTX*, + WOLFSSL_X509_STORE*, WOLFSSL_X509*, WOLF_STACK_OF(WOLFSSL_X509)*); +WOLFSSL_API void wolfSSL_X509_STORE_CTX_free(WOLFSSL_X509_STORE_CTX*); +WOLFSSL_API void wolfSSL_X509_STORE_CTX_cleanup(WOLFSSL_X509_STORE_CTX*); + +WOLFSSL_API WOLFSSL_ASN1_TIME* wolfSSL_X509_CRL_get_lastUpdate(WOLFSSL_X509_CRL*); +WOLFSSL_API WOLFSSL_ASN1_TIME* wolfSSL_X509_CRL_get_nextUpdate(WOLFSSL_X509_CRL*); + +WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_X509_get_pubkey(WOLFSSL_X509*); +WOLFSSL_API int wolfSSL_X509_CRL_verify(WOLFSSL_X509_CRL*, WOLFSSL_EVP_PKEY*); +WOLFSSL_API void wolfSSL_X509_OBJECT_free_contents(WOLFSSL_X509_OBJECT*); +WOLFSSL_API WOLFSSL_PKCS8_PRIV_KEY_INFO* wolfSSL_d2i_PKCS8_PKEY_bio( + WOLFSSL_BIO* bio, WOLFSSL_PKCS8_PRIV_KEY_INFO** pkey); +WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_d2i_PUBKEY_bio(WOLFSSL_BIO* bio, + WOLFSSL_EVP_PKEY** out); +WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_d2i_PUBKEY(WOLFSSL_EVP_PKEY** key, + unsigned char** in, long inSz); +WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey(int type, + WOLFSSL_EVP_PKEY** out, const unsigned char **in, long inSz); +WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_d2i_PrivateKey_EVP(WOLFSSL_EVP_PKEY** key, + unsigned char** in, long inSz); +WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_PKEY_new_ex(void* heap); +WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_PKEY_new(void); +WOLFSSL_API int wolfSSL_X509_cmp_current_time(const WOLFSSL_ASN1_TIME*); +WOLFSSL_API int wolfSSL_sk_X509_REVOKED_num(WOLFSSL_X509_REVOKED*); +#ifdef OPENSSL_EXTRA +WOLFSSL_API void wolfSSL_X509_STORE_CTX_set_time(WOLFSSL_X509_STORE_CTX*, + unsigned long flags, + time_t t); +#endif +WOLFSSL_API WOLFSSL_X509_REVOKED* wolfSSL_X509_CRL_get_REVOKED(WOLFSSL_X509_CRL*); +WOLFSSL_API WOLFSSL_X509_REVOKED* wolfSSL_sk_X509_REVOKED_value( + WOLFSSL_X509_REVOKED*,int); +WOLFSSL_API WOLFSSL_ASN1_INTEGER* wolfSSL_X509_get_serialNumber(WOLFSSL_X509*); +WOLFSSL_API void wolfSSL_ASN1_INTEGER_free(WOLFSSL_ASN1_INTEGER*); +WOLFSSL_API WOLFSSL_ASN1_INTEGER* wolfSSL_ASN1_INTEGER_new(void); + +WOLFSSL_API int wolfSSL_ASN1_TIME_print(WOLFSSL_BIO*, const WOLFSSL_ASN1_TIME*); + +WOLFSSL_API char* wolfSSL_ASN1_TIME_to_string(WOLFSSL_ASN1_TIME* t, + char* buf, int len); +WOLFSSL_API int wolfSSL_ASN1_INTEGER_cmp(const WOLFSSL_ASN1_INTEGER*, + const WOLFSSL_ASN1_INTEGER*); +WOLFSSL_API long wolfSSL_ASN1_INTEGER_get(const WOLFSSL_ASN1_INTEGER*); + +#ifdef OPENSSL_EXTRA +WOLFSSL_API WOLFSSL_BIGNUM *wolfSSL_ASN1_INTEGER_to_BN(const WOLFSSL_ASN1_INTEGER *ai, + WOLFSSL_BIGNUM *bn); +WOLFSSL_API WOLFSSL_ASN1_TIME* wolfSSL_ASN1_TIME_adj(WOLFSSL_ASN1_TIME*, time_t, + int, long); +#endif + +WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_load_client_CA_file(const char*); +WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509_NAME)* wolfSSL_SSL_CTX_get_client_CA_list( + const WOLFSSL_CTX *s); +WOLFSSL_API void wolfSSL_CTX_set_client_CA_list(WOLFSSL_CTX*, + WOLF_STACK_OF(WOLFSSL_X509_NAME)*); +WOLFSSL_API void* wolfSSL_X509_STORE_CTX_get_ex_data(WOLFSSL_X509_STORE_CTX*, int); +WOLFSSL_API int wolfSSL_get_ex_data_X509_STORE_CTX_idx(void); +WOLFSSL_API void wolfSSL_X509_STORE_CTX_set_error( + WOLFSSL_X509_STORE_CTX* ctx, int er); +WOLFSSL_API void* wolfSSL_get_ex_data(const WOLFSSL*, int); + +WOLFSSL_API void wolfSSL_CTX_set_default_passwd_cb_userdata(WOLFSSL_CTX*, + void* userdata); +WOLFSSL_API void wolfSSL_CTX_set_default_passwd_cb(WOLFSSL_CTX*, + pem_password_cb*); +WOLFSSL_API pem_password_cb* wolfSSL_CTX_get_default_passwd_cb(WOLFSSL_CTX *ctx); +WOLFSSL_API void *wolfSSL_CTX_get_default_passwd_cb_userdata(WOLFSSL_CTX *ctx); + +WOLFSSL_API void wolfSSL_CTX_set_info_callback(WOLFSSL_CTX*, + void (*)(const WOLFSSL* ssl, int type, int val)); + +WOLFSSL_API unsigned long wolfSSL_ERR_peek_error(void); +WOLFSSL_API int wolfSSL_GET_REASON(int); + +WOLFSSL_API const char* wolfSSL_alert_type_string_long(int); +WOLFSSL_API const char* wolfSSL_alert_desc_string_long(int); +WOLFSSL_API const char* wolfSSL_state_string_long(const WOLFSSL*); + +WOLFSSL_API WOLFSSL_RSA* wolfSSL_RSA_generate_key(int, unsigned long, + void(*)(int, int, void*), void*); +WOLFSSL_API WOLFSSL_RSA *wolfSSL_d2i_RSAPublicKey(WOLFSSL_RSA **r, + const unsigned char **pp, long len); +WOLFSSL_API WOLFSSL_RSA *wolfSSL_d2i_RSAPrivateKey(WOLFSSL_RSA**, + const unsigned char**, long); +WOLFSSL_API int wolfSSL_i2d_RSAPublicKey(WOLFSSL_RSA *r, const unsigned char **pp); +WOLFSSL_API int wolfSSL_i2d_RSAPrivateKey(WOLFSSL_RSA *r, unsigned char **pp); +WOLFSSL_API void wolfSSL_CTX_set_tmp_rsa_callback(WOLFSSL_CTX *, + WOLFSSL_RSA *(*)(WOLFSSL *, int, int)); + +WOLFSSL_API int wolfSSL_PEM_def_callback(char*, int num, int w, void* key); + +WOLFSSL_API long wolfSSL_CTX_sess_accept(WOLFSSL_CTX*); +WOLFSSL_API long wolfSSL_CTX_sess_connect(WOLFSSL_CTX*); +WOLFSSL_API long wolfSSL_CTX_sess_accept_good(WOLFSSL_CTX*); +WOLFSSL_API long wolfSSL_CTX_sess_connect_good(WOLFSSL_CTX*); +WOLFSSL_API long wolfSSL_CTX_sess_accept_renegotiate(WOLFSSL_CTX*); +WOLFSSL_API long wolfSSL_CTX_sess_connect_renegotiate(WOLFSSL_CTX*); +WOLFSSL_API long wolfSSL_CTX_sess_hits(WOLFSSL_CTX*); +WOLFSSL_API long wolfSSL_CTX_sess_cb_hits(WOLFSSL_CTX*); +WOLFSSL_API long wolfSSL_CTX_sess_cache_full(WOLFSSL_CTX*); +WOLFSSL_API long wolfSSL_CTX_sess_misses(WOLFSSL_CTX*); +WOLFSSL_API long wolfSSL_CTX_sess_timeouts(WOLFSSL_CTX*); +WOLFSSL_API long wolfSSL_CTX_sess_number(WOLFSSL_CTX*); + +WOLFSSL_API long wolfSSL_CTX_add_extra_chain_cert(WOLFSSL_CTX*, WOLFSSL_X509*); +WOLFSSL_API long wolfSSL_CTX_sess_set_cache_size(WOLFSSL_CTX*, long); +WOLFSSL_API long wolfSSL_CTX_sess_get_cache_size(WOLFSSL_CTX*); + +WOLFSSL_API long wolfSSL_CTX_get_session_cache_mode(WOLFSSL_CTX*); +WOLFSSL_API int wolfSSL_CTX_get_read_ahead(WOLFSSL_CTX*); +WOLFSSL_API int wolfSSL_CTX_set_read_ahead(WOLFSSL_CTX*, int v); +WOLFSSL_API long wolfSSL_CTX_set_tlsext_status_arg(WOLFSSL_CTX*, void* arg); +WOLFSSL_API long wolfSSL_CTX_set_tlsext_opaque_prf_input_callback_arg( + WOLFSSL_CTX*, void* arg); +WOLFSSL_API int wolfSSL_CTX_add_client_CA(WOLFSSL_CTX*, WOLFSSL_X509*); +WOLFSSL_API int wolfSSL_CTX_set_srp_password(WOLFSSL_CTX*, char*); +WOLFSSL_API int wolfSSL_CTX_set_srp_username(WOLFSSL_CTX*, char*); + +WOLFSSL_API long wolfSSL_set_options(WOLFSSL *s, long op); +WOLFSSL_API long wolfSSL_get_options(const WOLFSSL *s); +WOLFSSL_API long wolfSSL_clear_options(WOLFSSL *s, long op); +WOLFSSL_API long wolfSSL_clear_num_renegotiations(WOLFSSL *s); +WOLFSSL_API long wolfSSL_total_renegotiations(WOLFSSL *s); +WOLFSSL_API long wolfSSL_set_tmp_dh(WOLFSSL *s, WOLFSSL_DH *dh); +WOLFSSL_API long wolfSSL_set_tlsext_debug_arg(WOLFSSL *s, void *arg); +WOLFSSL_API long wolfSSL_set_tlsext_status_type(WOLFSSL *s, int type); +WOLFSSL_API long wolfSSL_set_tlsext_status_exts(WOLFSSL *s, void *arg); +WOLFSSL_API long wolfSSL_get_tlsext_status_ids(WOLFSSL *s, void *arg); +WOLFSSL_API long wolfSSL_set_tlsext_status_ids(WOLFSSL *s, void *arg); +WOLFSSL_API long wolfSSL_get_tlsext_status_ocsp_resp(WOLFSSL *s, unsigned char **resp); +WOLFSSL_API long wolfSSL_set_tlsext_status_ocsp_resp(WOLFSSL *s, unsigned char *resp, int len); + +WOLFSSL_API void wolfSSL_CONF_modules_unload(int all); +WOLFSSL_API long wolfSSL_get_tlsext_status_exts(WOLFSSL *s, void *arg); +WOLFSSL_API long wolfSSL_get_verify_result(const WOLFSSL *ssl); + +#define WOLFSSL_DEFAULT_CIPHER_LIST "" /* default all */ + +enum { + WOLFSSL_OCSP_URL_OVERRIDE = 1, + WOLFSSL_OCSP_NO_NONCE = 2, + WOLFSSL_OCSP_CHECKALL = 4, + + WOLFSSL_CRL_CHECKALL = 1, + WOLFSSL_CRL_CHECK = 27, +}; + +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || \ + defined(HAVE_WEBSERVER) +/* seperated out from other enums because of size */ +enum { + SSL_OP_MICROSOFT_SESS_ID_BUG = 0x00000001, + SSL_OP_NETSCAPE_CHALLENGE_BUG = 0x00000002, + SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG = 0x00000004, + SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG = 0x00000008, + SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER = 0x00000010, + SSL_OP_MSIE_SSLV2_RSA_PADDING = 0x00000020, + SSL_OP_SSLEAY_080_CLIENT_DH_BUG = 0x00000040, + SSL_OP_TLS_D5_BUG = 0x00000080, + SSL_OP_TLS_BLOCK_PADDING_BUG = 0x00000100, + SSL_OP_TLS_ROLLBACK_BUG = 0x00000200, + SSL_OP_ALL = 0x00000400, + SSL_OP_EPHEMERAL_RSA = 0x00000800, + SSL_OP_NO_SSLv3 = 0x00001000, + SSL_OP_NO_TLSv1 = 0x00002000, + SSL_OP_PKCS1_CHECK_1 = 0x00004000, + SSL_OP_PKCS1_CHECK_2 = 0x00008000, + SSL_OP_NETSCAPE_CA_DN_BUG = 0x00010000, + SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG = 0x00020000, + SSL_OP_SINGLE_DH_USE = 0x00040000, + SSL_OP_NO_TICKET = 0x00080000, + SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS = 0x00100000, + SSL_OP_NO_QUERY_MTU = 0x00200000, + SSL_OP_COOKIE_EXCHANGE = 0x00400000, + SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION = 0x00800000, + SSL_OP_SINGLE_ECDH_USE = 0x01000000, + SSL_OP_CIPHER_SERVER_PREFERENCE = 0x02000000, + SSL_OP_NO_TLSv1_1 = 0x04000000, + SSL_OP_NO_TLSv1_2 = 0x08000000, + SSL_OP_NO_COMPRESSION = 0x10000000, + SSL_OP_NO_TLSv1_3 = 0x20000000, +}; + +enum { +#ifdef HAVE_OCSP + /* OCSP Flags */ + OCSP_NOCERTS = 1, + OCSP_NOINTERN = 2, + OCSP_NOSIGS = 4, + OCSP_NOCHAIN = 8, + OCSP_NOVERIFY = 16, + OCSP_NOEXPLICIT = 32, + OCSP_NOCASIGN = 64, + OCSP_NODELEGATED = 128, + OCSP_NOCHECKS = 256, + OCSP_TRUSTOTHER = 512, + OCSP_RESPID_KEY = 1024, + OCSP_NOTIME = 2048, + + /* OCSP Types */ + OCSP_CERTID = 2, + OCSP_REQUEST = 4, + OCSP_RESPONSE = 8, + OCSP_BASICRESP = 16, +#endif + + ASN1_GENERALIZEDTIME = 4, + SSL_MAX_SSL_SESSION_ID_LENGTH = 32, + + EVP_R_BAD_DECRYPT = 2, + + SSL_ST_CONNECT = 0x1000, + SSL_ST_ACCEPT = 0x2000, + SSL_ST_MASK = 0x0FFF, + + SSL_CB_LOOP = 0x01, + SSL_CB_EXIT = 0x02, + SSL_CB_READ = 0x04, + SSL_CB_WRITE = 0x08, + SSL_CB_HANDSHAKE_START = 0x10, + SSL_CB_HANDSHAKE_DONE = 0x20, + SSL_CB_ALERT = 0x4000, + SSL_CB_READ_ALERT = (SSL_CB_ALERT | SSL_CB_READ), + SSL_CB_WRITE_ALERT = (SSL_CB_ALERT | SSL_CB_WRITE), + SSL_CB_ACCEPT_LOOP = (SSL_ST_ACCEPT | SSL_CB_LOOP), + SSL_CB_ACCEPT_EXIT = (SSL_ST_ACCEPT | SSL_CB_EXIT), + SSL_CB_CONNECT_LOOP = (SSL_ST_CONNECT | SSL_CB_LOOP), + SSL_CB_CONNECT_EXIT = (SSL_ST_CONNECT | SSL_CB_EXIT), + SSL_CB_MODE_READ = 1, + SSL_CB_MODE_WRITE = 2, + + SSL_MODE_ENABLE_PARTIAL_WRITE = 2, + + BIO_FLAGS_BASE64_NO_NL = 1, + BIO_CLOSE = 1, + BIO_NOCLOSE = 0, + + X509_FILETYPE_PEM = 8, + X509_LU_X509 = 9, + X509_LU_CRL = 12, + + X509_V_OK = 0, + X509_V_ERR_CRL_SIGNATURE_FAILURE = 13, + X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD = 14, + X509_V_ERR_CRL_HAS_EXPIRED = 15, + X509_V_ERR_CERT_REVOKED = 16, + X509_V_ERR_CERT_CHAIN_TOO_LONG = 17, + X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT = 18, + X509_V_ERR_CERT_NOT_YET_VALID = 19, + X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD = 20, + X509_V_ERR_CERT_HAS_EXPIRED = 21, + X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD = 22, + X509_V_ERR_CERT_REJECTED = 23, + /* Required for Nginx */ + X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT = 24, + X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN = 25, + X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY = 26, + X509_V_ERR_CERT_UNTRUSTED = 27, + X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE = 28, + X509_V_ERR_SUBJECT_ISSUER_MISMATCH = 29, + /* additional X509_V_ERR_* enums not used in wolfSSL */ + X509_V_ERR_UNABLE_TO_GET_CRL, + X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE, + X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE, + X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY, + X509_V_ERR_CERT_SIGNATURE_FAILURE, + X509_V_ERR_CRL_NOT_YET_VALID, + X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD, + X509_V_ERR_OUT_OF_MEM, + X509_V_ERR_INVALID_CA, + X509_V_ERR_PATH_LENGTH_EXCEEDED, + X509_V_ERR_INVALID_PURPOSE, + X509_V_ERR_AKID_SKID_MISMATCH, + X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH, + X509_V_ERR_KEYUSAGE_NO_CERTSIGN, + X509_V_ERR_UNABLE_TO_GET_CRL_ISSUER, + X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION, + X509_V_ERR_KEYUSAGE_NO_CRL_SIGN, + X509_V_ERR_UNHANDLED_CRITICAL_CRL_EXTENSION, + X509_V_ERR_INVALID_NON_CA, + X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED, + X509_V_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE, + X509_V_ERR_PROXY_CERTIFICATES_NOT_ALLOWED, + X509_V_ERR_INVALID_EXTENSION, + X509_V_ERR_INVALID_POLICY_EXTENSION, + X509_V_ERR_NO_EXPLICIT_POLICY, + X509_V_ERR_UNNESTED_RESOURCE, + + X509_R_CERT_ALREADY_IN_HASH_TABLE, + + XN_FLAG_SPC_EQ = (1 << 23), + XN_FLAG_ONELINE = 0, + XN_FLAG_RFC2253 = 1, + + CRYPTO_LOCK = 1, + CRYPTO_NUM_LOCKS = 10, + + ASN1_STRFLGS_ESC_MSB = 4 +}; +#endif + +/* extras end */ + +#if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM) +/* wolfSSL extension, provide last error from SSL_get_error + since not using thread storage error queue */ +#include +WOLFSSL_API void wolfSSL_ERR_print_errors_fp(XFILE, int err); +#if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) +WOLFSSL_API void wolfSSL_ERR_dump_errors_fp(XFILE fp); +#endif +#endif + + +#ifndef NO_OLD_SSL_NAMES + #define SSL_ERROR_NONE WOLFSSL_ERROR_NONE + #define SSL_FAILURE WOLFSSL_FAILURE + #define SSL_SUCCESS WOLFSSL_SUCCESS + #define SSL_SHUTDOWN_NOT_DONE WOLFSSL_SHUTDOWN_NOT_DONE + + #define SSL_ALPN_NOT_FOUND WOLFSSL_ALPN_NOT_FOUND + #define SSL_BAD_CERTTYPE WOLFSSL_BAD_CERTTYPE + #define SSL_BAD_STAT WOLFSSL_BAD_STAT + #define SSL_BAD_PATH WOLFSSL_BAD_PATH + #define SSL_BAD_FILETYPE WOLFSSL_BAD_FILETYPE + #define SSL_BAD_FILE WOLFSSL_BAD_FILE + #define SSL_NOT_IMPLEMENTED WOLFSSL_NOT_IMPLEMENTED + #define SSL_UNKNOWN WOLFSSL_UNKNOWN + #define SSL_FATAL_ERROR WOLFSSL_FATAL_ERROR + + #define SSL_FILETYPE_ASN1 WOLFSSL_FILETYPE_ASN1 + #define SSL_FILETYPE_PEM WOLFSSL_FILETYPE_PEM + #define SSL_FILETYPE_DEFAULT WOLFSSL_FILETYPE_DEFAULT + #define SSL_FILETYPE_RAW WOLFSSL_FILETYPE_RAW + + #define SSL_VERIFY_NONE WOLFSSL_VERIFY_NONE + #define SSL_VERIFY_PEER WOLFSSL_VERIFY_PEER + #define SSL_VERIFY_FAIL_IF_NO_PEER_CERT WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT + #define SSL_VERIFY_CLIENT_ONCE WOLFSSL_VERIFY_CLIENT_ONCE + #define SSL_VERIFY_FAIL_EXCEPT_PSK WOLFSSL_VERIFY_FAIL_EXCEPT_PSK + + #define SSL_SESS_CACHE_OFF WOLFSSL_SESS_CACHE_OFF + #define SSL_SESS_CACHE_CLIENT WOLFSSL_SESS_CACHE_CLIENT + #define SSL_SESS_CACHE_SERVER WOLFSSL_SESS_CACHE_SERVER + #define SSL_SESS_CACHE_BOTH WOLFSSL_SESS_CACHE_BOTH + #define SSL_SESS_CACHE_NO_AUTO_CLEAR WOLFSSL_SESS_CACHE_NO_AUTO_CLEAR + #define SSL_SESS_CACHE_NO_INTERNAL_LOOKUP WOLFSSL_SESS_CACHE_NO_INTERNAL_LOOKUP + #define SSL_SESS_CACHE_NO_INTERNAL_STORE WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE + #define SSL_SESS_CACHE_NO_INTERNAL WOLFSSL_SESS_CACHE_NO_INTERNAL + + #define SSL_ERROR_WANT_READ WOLFSSL_ERROR_WANT_READ + #define SSL_ERROR_WANT_WRITE WOLFSSL_ERROR_WANT_WRITE + #define SSL_ERROR_WANT_CONNECT WOLFSSL_ERROR_WANT_CONNECT + #define SSL_ERROR_WANT_ACCEPT WOLFSSL_ERROR_WANT_ACCEPT + #define SSL_ERROR_SYSCALL WOLFSSL_ERROR_SYSCALL + #define SSL_ERROR_WANT_X509_LOOKUP WOLFSSL_ERROR_WANT_X509_LOOKUP + #define SSL_ERROR_ZERO_RETURN WOLFSSL_ERROR_ZERO_RETURN + #define SSL_ERROR_SSL WOLFSSL_ERROR_SSL + + #define SSL_SENT_SHUTDOWN WOLFSSL_SENT_SHUTDOWN + #define SSL_RECEIVED_SHUTDOWN WOLFSSL_RECEIVED_SHUTDOWN + #define SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER WOLFSSL_MODE_ACCEPT_MOVING_WRITE_BUFFER + #define SSL_OP_NO_SSLv2 WOLFSSL_OP_NO_SSLv2 + + #define SSL_R_SSL_HANDSHAKE_FAILURE WOLFSSL_R_SSL_HANDSHAKE_FAILURE + #define SSL_R_TLSV1_ALERT_UNKNOWN_CA WOLFSSL_R_TLSV1_ALERT_UNKNOWN_CA + #define SSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN WOLFSSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN + #define SSL_R_SSLV3_ALERT_BAD_CERTIFICATE WOLFSSL_R_SSLV3_ALERT_BAD_CERTIFICATE + + #define PEM_BUFSIZE WOLF_PEM_BUFSIZE +#endif + +enum { /* ssl Constants */ + WOLFSSL_ERROR_NONE = 0, /* for most functions */ + WOLFSSL_FAILURE = 0, /* for some functions */ + WOLFSSL_SUCCESS = 1, + WOLFSSL_SHUTDOWN_NOT_DONE = 2, /* call wolfSSL_shutdown again to complete */ + + WOLFSSL_ALPN_NOT_FOUND = -9, + WOLFSSL_BAD_CERTTYPE = -8, + WOLFSSL_BAD_STAT = -7, + WOLFSSL_BAD_PATH = -6, + WOLFSSL_BAD_FILETYPE = -5, + WOLFSSL_BAD_FILE = -4, + WOLFSSL_NOT_IMPLEMENTED = -3, + WOLFSSL_UNKNOWN = -2, + WOLFSSL_FATAL_ERROR = -1, + + WOLFSSL_FILETYPE_ASN1 = 2, + WOLFSSL_FILETYPE_PEM = 1, + WOLFSSL_FILETYPE_DEFAULT = 2, /* ASN1 */ + WOLFSSL_FILETYPE_RAW = 3, /* NTRU raw key blob */ + + WOLFSSL_VERIFY_NONE = 0, + WOLFSSL_VERIFY_PEER = 1, + WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT = 2, + WOLFSSL_VERIFY_CLIENT_ONCE = 4, + WOLFSSL_VERIFY_FAIL_EXCEPT_PSK = 8, + + WOLFSSL_SESS_CACHE_OFF = 0x0000, + WOLFSSL_SESS_CACHE_CLIENT = 0x0001, + WOLFSSL_SESS_CACHE_SERVER = 0x0002, + WOLFSSL_SESS_CACHE_BOTH = 0x0003, + WOLFSSL_SESS_CACHE_NO_AUTO_CLEAR = 0x0008, + WOLFSSL_SESS_CACHE_NO_INTERNAL_LOOKUP = 0x0100, + WOLFSSL_SESS_CACHE_NO_INTERNAL_STORE = 0x0200, + WOLFSSL_SESS_CACHE_NO_INTERNAL = 0x0300, + + WOLFSSL_ERROR_WANT_READ = 2, + WOLFSSL_ERROR_WANT_WRITE = 3, + WOLFSSL_ERROR_WANT_CONNECT = 7, + WOLFSSL_ERROR_WANT_ACCEPT = 8, + WOLFSSL_ERROR_SYSCALL = 5, + WOLFSSL_ERROR_WANT_X509_LOOKUP = 83, + WOLFSSL_ERROR_ZERO_RETURN = 6, + WOLFSSL_ERROR_SSL = 85, + + WOLFSSL_SENT_SHUTDOWN = 1, + WOLFSSL_RECEIVED_SHUTDOWN = 2, + WOLFSSL_MODE_ACCEPT_MOVING_WRITE_BUFFER = 4, + WOLFSSL_OP_NO_SSLv2 = 8, + + WOLFSSL_R_SSL_HANDSHAKE_FAILURE = 101, + WOLFSSL_R_TLSV1_ALERT_UNKNOWN_CA = 102, + WOLFSSL_R_SSLV3_ALERT_CERTIFICATE_UNKNOWN = 103, + WOLFSSL_R_SSLV3_ALERT_BAD_CERTIFICATE = 104, + + WOLF_PEM_BUFSIZE = 1024 +}; + +#ifndef NO_PSK + typedef unsigned int (*wc_psk_client_callback)(WOLFSSL*, const char*, char*, + unsigned int, unsigned char*, unsigned int); + WOLFSSL_API void wolfSSL_CTX_set_psk_client_callback(WOLFSSL_CTX*, + wc_psk_client_callback); + WOLFSSL_API void wolfSSL_set_psk_client_callback(WOLFSSL*, + wc_psk_client_callback); +#ifdef WOLFSSL_TLS13 + typedef unsigned int (*wc_psk_client_tls13_callback)(WOLFSSL*, const char*, + char*, unsigned int, unsigned char*, unsigned int, const char**); + WOLFSSL_API void wolfSSL_CTX_set_psk_client_tls13_callback(WOLFSSL_CTX*, + wc_psk_client_tls13_callback); + WOLFSSL_API void wolfSSL_set_psk_client_tls13_callback(WOLFSSL*, + wc_psk_client_tls13_callback); +#endif + + WOLFSSL_API const char* wolfSSL_get_psk_identity_hint(const WOLFSSL*); + WOLFSSL_API const char* wolfSSL_get_psk_identity(const WOLFSSL*); + + WOLFSSL_API int wolfSSL_CTX_use_psk_identity_hint(WOLFSSL_CTX*, const char*); + WOLFSSL_API int wolfSSL_use_psk_identity_hint(WOLFSSL*, const char*); + + typedef unsigned int (*wc_psk_server_callback)(WOLFSSL*, const char*, + unsigned char*, unsigned int); + WOLFSSL_API void wolfSSL_CTX_set_psk_server_callback(WOLFSSL_CTX*, + wc_psk_server_callback); + WOLFSSL_API void wolfSSL_set_psk_server_callback(WOLFSSL*, + wc_psk_server_callback); +#ifdef WOLFSSL_TLS13 + typedef unsigned int (*wc_psk_server_tls13_callback)(WOLFSSL*, const char*, + unsigned char*, unsigned int, const char**); + WOLFSSL_API void wolfSSL_CTX_set_psk_server_tls13_callback(WOLFSSL_CTX*, + wc_psk_server_tls13_callback); + WOLFSSL_API void wolfSSL_set_psk_server_tls13_callback(WOLFSSL*, + wc_psk_server_tls13_callback); +#endif + + #define PSK_TYPES_DEFINED +#endif /* NO_PSK */ + + +#ifdef HAVE_ANON + WOLFSSL_API int wolfSSL_CTX_allow_anon_cipher(WOLFSSL_CTX*); +#endif /* HAVE_ANON */ + + +/* extra begins */ +#ifdef OPENSSL_EXTRA +enum { /* ERR Constants */ + ERR_TXT_STRING = 1 +}; + +/* bio misc */ +enum { + WOLFSSL_BIO_ERROR = -1, + WOLFSSL_BIO_UNSET = -2, + WOLFSSL_BIO_SIZE = 17000 /* default BIO write size if not set */ +}; +#endif + +WOLFSSL_API void wolfSSL_ERR_put_error(int lib, int fun, int err, + const char* file, int line); +WOLFSSL_API unsigned long wolfSSL_ERR_get_error_line(const char**, int*); +WOLFSSL_API unsigned long wolfSSL_ERR_get_error_line_data(const char**, int*, + const char**, int *); + +WOLFSSL_API unsigned long wolfSSL_ERR_get_error(void); +WOLFSSL_API void wolfSSL_ERR_clear_error(void); + + +WOLFSSL_API int wolfSSL_RAND_status(void); +WOLFSSL_API int wolfSSL_RAND_pseudo_bytes(unsigned char* buf, int num); +WOLFSSL_API int wolfSSL_RAND_bytes(unsigned char* buf, int num); +WOLFSSL_API WOLFSSL_METHOD *wolfSSLv23_server_method(void); +WOLFSSL_API long wolfSSL_CTX_set_options(WOLFSSL_CTX*, long); +WOLFSSL_API long wolfSSL_CTX_get_options(WOLFSSL_CTX* ctx); +WOLFSSL_API long wolfSSL_CTX_clear_options(WOLFSSL_CTX*, long); + +#ifndef NO_CERTS + WOLFSSL_API int wolfSSL_CTX_check_private_key(const WOLFSSL_CTX*); +#endif /* !NO_CERTS */ + +WOLFSSL_API void wolfSSL_ERR_free_strings(void); +WOLFSSL_API void wolfSSL_ERR_remove_state(unsigned long); +WOLFSSL_API int wolfSSL_clear(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_state(WOLFSSL* ssl); + +WOLFSSL_API void wolfSSL_cleanup_all_ex_data(void); +WOLFSSL_API long wolfSSL_CTX_set_mode(WOLFSSL_CTX* ctx, long mode); +WOLFSSL_API long wolfSSL_CTX_get_mode(WOLFSSL_CTX* ctx); +WOLFSSL_API void wolfSSL_CTX_set_default_read_ahead(WOLFSSL_CTX* ctx, int m); +WOLFSSL_API long wolfSSL_SSL_get_mode(WOLFSSL* ssl); + + +WOLFSSL_API int wolfSSL_CTX_set_default_verify_paths(WOLFSSL_CTX*); +WOLFSSL_API int wolfSSL_CTX_set_session_id_context(WOLFSSL_CTX*, + const unsigned char*, unsigned int); +WOLFSSL_API WOLFSSL_X509* wolfSSL_get_peer_certificate(WOLFSSL* ssl); +WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_get_peer_cert_chain(const WOLFSSL*); + +WOLFSSL_API int wolfSSL_want_read(WOLFSSL*); +WOLFSSL_API int wolfSSL_want_write(WOLFSSL*); + +WOLFSSL_API int wolfSSL_BIO_printf(WOLFSSL_BIO*, const char*, ...); +WOLFSSL_API int wolfSSL_ASN1_UTCTIME_print(WOLFSSL_BIO*, + const WOLFSSL_ASN1_UTCTIME*); +WOLFSSL_API int wolfSSL_ASN1_GENERALIZEDTIME_print(WOLFSSL_BIO*, + const WOLFSSL_ASN1_GENERALIZEDTIME*); +WOLFSSL_API void wolfSSL_ASN1_GENERALIZEDTIME_free(WOLFSSL_ASN1_GENERALIZEDTIME*); +WOLFSSL_API int wolfSSL_sk_num(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)*); +WOLFSSL_API void* wolfSSL_sk_value(WOLF_STACK_OF(WOLFSSL_ASN1_OBJECT)*, int); + +/* stunnel 4.28 needs */ +WOLFSSL_API void* wolfSSL_CTX_get_ex_data(const WOLFSSL_CTX*, int); +WOLFSSL_API int wolfSSL_CTX_set_ex_data(WOLFSSL_CTX*, int, void*); +WOLFSSL_API void wolfSSL_CTX_sess_set_get_cb(WOLFSSL_CTX*, + WOLFSSL_SESSION*(*f)(WOLFSSL*, unsigned char*, int, int*)); +WOLFSSL_API void wolfSSL_CTX_sess_set_new_cb(WOLFSSL_CTX*, + int (*f)(WOLFSSL*, WOLFSSL_SESSION*)); +WOLFSSL_API void wolfSSL_CTX_sess_set_remove_cb(WOLFSSL_CTX*, + void (*f)(WOLFSSL_CTX*, WOLFSSL_SESSION*)); + +WOLFSSL_API int wolfSSL_i2d_SSL_SESSION(WOLFSSL_SESSION*,unsigned char**); +WOLFSSL_API WOLFSSL_SESSION* wolfSSL_d2i_SSL_SESSION(WOLFSSL_SESSION**, + const unsigned char**, long); + +WOLFSSL_API long wolfSSL_SESSION_get_timeout(const WOLFSSL_SESSION*); +WOLFSSL_API long wolfSSL_SESSION_get_time(const WOLFSSL_SESSION*); +WOLFSSL_API int wolfSSL_CTX_get_ex_new_index(long, void*, void*, void*, void*); + +/* extra ends */ + + +/* wolfSSL extensions */ + +/* call before SSL_connect, if verifying will add name check to + date check and signature check */ +WOLFSSL_API int wolfSSL_check_domain_name(WOLFSSL* ssl, const char* dn); + +/* need to call once to load library (session cache) */ +WOLFSSL_API int wolfSSL_Init(void); +/* call when done to cleanup/free session cache mutex / resources */ +WOLFSSL_API int wolfSSL_Cleanup(void); + +/* which library version do we have */ +WOLFSSL_API const char* wolfSSL_lib_version(void); +/* which library version do we have in hex */ +WOLFSSL_API word32 wolfSSL_lib_version_hex(void); + +/* do accept or connect depedning on side */ +WOLFSSL_API int wolfSSL_negotiate(WOLFSSL* ssl); +/* turn on wolfSSL data compression */ +WOLFSSL_API int wolfSSL_set_compression(WOLFSSL* ssl); + +WOLFSSL_API int wolfSSL_set_timeout(WOLFSSL*, unsigned int); +WOLFSSL_API int wolfSSL_CTX_set_timeout(WOLFSSL_CTX*, unsigned int); + +/* get wolfSSL peer X509_CHAIN */ +WOLFSSL_API WOLFSSL_X509_CHAIN* wolfSSL_get_peer_chain(WOLFSSL* ssl); +#ifdef WOLFSSL_ALT_CERT_CHAINS +WOLFSSL_API int wolfSSL_is_peer_alt_cert_chain(const WOLFSSL* ssl); +/* get wolfSSL alternate peer X509_CHAIN */ +WOLFSSL_API WOLFSSL_X509_CHAIN* wolfSSL_get_peer_alt_chain(WOLFSSL* ssl); +#endif +/* peer chain count */ +WOLFSSL_API int wolfSSL_get_chain_count(WOLFSSL_X509_CHAIN* chain); +/* index cert length */ +WOLFSSL_API int wolfSSL_get_chain_length(WOLFSSL_X509_CHAIN*, int idx); +/* index cert */ +WOLFSSL_API unsigned char* wolfSSL_get_chain_cert(WOLFSSL_X509_CHAIN*, int idx); +/* index cert in X509 */ +WOLFSSL_API WOLFSSL_X509* wolfSSL_get_chain_X509(WOLFSSL_X509_CHAIN*, int idx); +/* free X509 */ +#define wolfSSL_FreeX509(x509) wolfSSL_X509_free((x509)) +WOLFSSL_API void wolfSSL_X509_free(WOLFSSL_X509*); +/* get index cert in PEM */ +WOLFSSL_API int wolfSSL_get_chain_cert_pem(WOLFSSL_X509_CHAIN*, int idx, + unsigned char* buf, int inLen, int* outLen); +WOLFSSL_API const unsigned char* wolfSSL_get_sessionID(const WOLFSSL_SESSION* s); +WOLFSSL_API int wolfSSL_X509_get_serial_number(WOLFSSL_X509*,unsigned char*,int*); +WOLFSSL_API char* wolfSSL_X509_get_subjectCN(WOLFSSL_X509*); +WOLFSSL_API const unsigned char* wolfSSL_X509_get_der(WOLFSSL_X509*, int*); +WOLFSSL_API const unsigned char* wolfSSL_X509_get_tbs(WOLFSSL_X509*, int*); +WOLFSSL_API const unsigned char* wolfSSL_X509_notBefore(WOLFSSL_X509*); +WOLFSSL_API const unsigned char* wolfSSL_X509_notAfter(WOLFSSL_X509*); +WOLFSSL_API int wolfSSL_X509_version(WOLFSSL_X509*); + +WOLFSSL_API int wolfSSL_cmp_peer_cert_to_file(WOLFSSL*, const char*); + +WOLFSSL_API char* wolfSSL_X509_get_next_altname(WOLFSSL_X509*); + +WOLFSSL_API WOLFSSL_X509* wolfSSL_d2i_X509(WOLFSSL_X509** x509, + const unsigned char** in, int len); +WOLFSSL_API WOLFSSL_X509* + wolfSSL_X509_d2i(WOLFSSL_X509** x509, const unsigned char* in, int len); +WOLFSSL_API int wolfSSL_i2d_X509(WOLFSSL_X509* x509, unsigned char** out); +WOLFSSL_API WOLFSSL_X509_CRL *wolfSSL_d2i_X509_CRL(WOLFSSL_X509_CRL **crl, + const unsigned char *in, int len); +#ifndef NO_FILESYSTEM +WOLFSSL_API WOLFSSL_X509_CRL *wolfSSL_d2i_X509_CRL_fp(XFILE file, WOLFSSL_X509_CRL **crl); +#endif +WOLFSSL_API void wolfSSL_X509_CRL_free(WOLFSSL_X509_CRL *crl); + +#ifndef NO_FILESYSTEM + #ifndef NO_STDIO_FILESYSTEM + WOLFSSL_API WOLFSSL_X509* + wolfSSL_X509_d2i_fp(WOLFSSL_X509** x509, XFILE file); + #endif +WOLFSSL_API WOLFSSL_X509* + wolfSSL_X509_load_certificate_file(const char* fname, int format); +#endif +WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_load_certificate_buffer( + const unsigned char* buf, int sz, int format); + +#ifdef WOLFSSL_SEP + WOLFSSL_API unsigned char* + wolfSSL_X509_get_device_type(WOLFSSL_X509*, unsigned char*, int*); + WOLFSSL_API unsigned char* + wolfSSL_X509_get_hw_type(WOLFSSL_X509*, unsigned char*, int*); + WOLFSSL_API unsigned char* + wolfSSL_X509_get_hw_serial_number(WOLFSSL_X509*, unsigned char*, int*); +#endif + +/* connect enough to get peer cert */ +WOLFSSL_API int wolfSSL_connect_cert(WOLFSSL* ssl); + + + +/* PKCS12 compatibility */ +typedef struct WC_PKCS12 WC_PKCS12; +WOLFSSL_API WC_PKCS12* wolfSSL_d2i_PKCS12_bio(WOLFSSL_BIO* bio, + WC_PKCS12** pkcs12); +#ifndef NO_FILESYSTEM +WOLFSSL_API WOLFSSL_X509_PKCS12* wolfSSL_d2i_PKCS12_fp(XFILE fp, + WOLFSSL_X509_PKCS12** pkcs12); +#endif +WOLFSSL_API int wolfSSL_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, + WOLFSSL_EVP_PKEY** pkey, WOLFSSL_X509** cert, + WOLF_STACK_OF(WOLFSSL_X509)** ca); +WOLFSSL_API WC_PKCS12* wolfSSL_PKCS12_create(char* pass, char* name, + WOLFSSL_EVP_PKEY* pkey, WOLFSSL_X509* cert, + WOLF_STACK_OF(WOLFSSL_X509)* ca, + int keyNID, int certNID, int itt, int macItt, int keytype); +WOLFSSL_API void wolfSSL_PKCS12_PBE_add(void); + + + +#ifndef NO_DH +/* server Diffie-Hellman parameters */ +WOLFSSL_API int wolfSSL_SetTmpDH(WOLFSSL*, const unsigned char* p, int pSz, + const unsigned char* g, int gSz); +WOLFSSL_API int wolfSSL_SetTmpDH_buffer(WOLFSSL*, const unsigned char* b, long sz, + int format); +WOLFSSL_API int wolfSSL_SetEnableDhKeyTest(WOLFSSL*, int); +#ifndef NO_FILESYSTEM + WOLFSSL_API int wolfSSL_SetTmpDH_file(WOLFSSL*, const char* f, int format); +#endif + +/* server ctx Diffie-Hellman parameters */ +WOLFSSL_API int wolfSSL_CTX_SetTmpDH(WOLFSSL_CTX*, const unsigned char* p, + int pSz, const unsigned char* g, int gSz); +WOLFSSL_API int wolfSSL_CTX_SetTmpDH_buffer(WOLFSSL_CTX*, const unsigned char* b, + long sz, int format); + +#ifndef NO_FILESYSTEM + WOLFSSL_API int wolfSSL_CTX_SetTmpDH_file(WOLFSSL_CTX*, const char* f, + int format); +#endif + +WOLFSSL_API int wolfSSL_CTX_SetMinDhKey_Sz(WOLFSSL_CTX*, word16); +WOLFSSL_API int wolfSSL_SetMinDhKey_Sz(WOLFSSL*, word16); +WOLFSSL_API int wolfSSL_CTX_SetMaxDhKey_Sz(WOLFSSL_CTX*, word16); +WOLFSSL_API int wolfSSL_SetMaxDhKey_Sz(WOLFSSL*, word16); +WOLFSSL_API int wolfSSL_GetDhKey_Sz(WOLFSSL*); +#endif /* NO_DH */ + +#ifndef NO_RSA +WOLFSSL_API int wolfSSL_CTX_SetMinRsaKey_Sz(WOLFSSL_CTX*, short); +WOLFSSL_API int wolfSSL_SetMinRsaKey_Sz(WOLFSSL*, short); +#endif /* NO_RSA */ + +#ifdef HAVE_ECC +WOLFSSL_API int wolfSSL_CTX_SetMinEccKey_Sz(WOLFSSL_CTX*, short); +WOLFSSL_API int wolfSSL_SetMinEccKey_Sz(WOLFSSL*, short); +#endif /* NO_RSA */ + +WOLFSSL_API int wolfSSL_SetTmpEC_DHE_Sz(WOLFSSL*, word16); +WOLFSSL_API int wolfSSL_CTX_SetTmpEC_DHE_Sz(WOLFSSL_CTX*, word16); + +/* keyblock size in bytes or -1 */ +/* need to call wolfSSL_KeepArrays before handshake to save keys */ +WOLFSSL_API int wolfSSL_get_keyblock_size(WOLFSSL*); +WOLFSSL_API int wolfSSL_get_keys(WOLFSSL*,unsigned char** ms, unsigned int* msLen, + unsigned char** sr, unsigned int* srLen, + unsigned char** cr, unsigned int* crLen); + +/* Computes EAP-TLS and EAP-TTLS keying material from the master_secret. */ +WOLFSSL_API int wolfSSL_make_eap_keys(WOLFSSL*, void* key, unsigned int len, + const char* label); + + +#ifndef _WIN32 + #ifndef NO_WRITEV + #ifdef __PPU + #include + #include + #elif !defined(WOLFSSL_MDK_ARM) && !defined(WOLFSSL_IAR_ARM) && \ + !defined(WOLFSSL_PICOTCP) && !defined(WOLFSSL_ROWLEY_ARM) && \ + !defined(WOLFSSL_EMBOS) && !defined(WOLFSSL_FROSTED) && \ + !defined(WOLFSSL_CHIBIOS) && !defined(WOLFSSL_CONTIKI) && \ + !defined(WOLFSSL_ZEPHYR) + #include + #endif + /* allow writev style writing */ + WOLFSSL_API int wolfSSL_writev(WOLFSSL* ssl, const struct iovec* iov, + int iovcnt); + #endif +#endif + + +#ifndef NO_CERTS + /* SSL_CTX versions */ + WOLFSSL_API int wolfSSL_CTX_UnloadCAs(WOLFSSL_CTX*); +#ifdef WOLFSSL_TRUST_PEER_CERT + WOLFSSL_API int wolfSSL_CTX_Unload_trust_peers(WOLFSSL_CTX*); + WOLFSSL_API int wolfSSL_CTX_trust_peer_buffer(WOLFSSL_CTX*, + const unsigned char*, long, int); +#endif + WOLFSSL_API int wolfSSL_CTX_load_verify_buffer(WOLFSSL_CTX*, + const unsigned char*, long, int); + WOLFSSL_API int wolfSSL_CTX_load_verify_chain_buffer_format(WOLFSSL_CTX*, + const unsigned char*, long, int); + WOLFSSL_API int wolfSSL_CTX_use_certificate_buffer(WOLFSSL_CTX*, + const unsigned char*, long, int); + WOLFSSL_API int wolfSSL_CTX_use_PrivateKey_buffer(WOLFSSL_CTX*, + const unsigned char*, long, int); + WOLFSSL_API int wolfSSL_CTX_use_PrivateKey_id(WOLFSSL_CTX*, + const unsigned char*, long, int, long); + WOLFSSL_API int wolfSSL_CTX_use_certificate_chain_buffer_format(WOLFSSL_CTX*, + const unsigned char*, long, int); + WOLFSSL_API int wolfSSL_CTX_use_certificate_chain_buffer(WOLFSSL_CTX*, + const unsigned char*, long); + + /* SSL versions */ + WOLFSSL_API int wolfSSL_use_certificate_buffer(WOLFSSL*, const unsigned char*, + long, int); + WOLFSSL_API int wolfSSL_use_certificate_ASN1(WOLFSSL* ssl, unsigned char* der, + int derSz); + WOLFSSL_API int wolfSSL_use_PrivateKey_buffer(WOLFSSL*, const unsigned char*, + long, int); + WOLFSSL_API int wolfSSL_use_PrivateKey_id(WOLFSSL*, const unsigned char*, + long, int, long); + WOLFSSL_API int wolfSSL_use_certificate_chain_buffer_format(WOLFSSL*, + const unsigned char*, long, int); + WOLFSSL_API int wolfSSL_use_certificate_chain_buffer(WOLFSSL*, + const unsigned char*, long); + WOLFSSL_API int wolfSSL_UnloadCertsKeys(WOLFSSL*); + + #if (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) && \ + defined(KEEP_OUR_CERT) + WOLFSSL_API WOLFSSL_X509* wolfSSL_get_certificate(WOLFSSL* ssl); + #endif +#endif + +WOLFSSL_API int wolfSSL_CTX_set_group_messages(WOLFSSL_CTX*); +WOLFSSL_API int wolfSSL_set_group_messages(WOLFSSL*); + + +#ifdef HAVE_FUZZER +enum fuzzer_type { + FUZZ_HMAC = 0, + FUZZ_ENCRYPT = 1, + FUZZ_SIGNATURE = 2, + FUZZ_HASH = 3, + FUZZ_HEAD = 4 +}; + +typedef int (*CallbackFuzzer)(WOLFSSL* ssl, const unsigned char* buf, int sz, + int type, void* fuzzCtx); + +WOLFSSL_API void wolfSSL_SetFuzzerCb(WOLFSSL* ssl, CallbackFuzzer cbf, void* fCtx); +#endif + + +WOLFSSL_API int wolfSSL_DTLS_SetCookieSecret(WOLFSSL*, + const unsigned char*, + unsigned int); + + +/* I/O Callback default errors */ +enum IOerrors { + WOLFSSL_CBIO_ERR_GENERAL = -1, /* general unexpected err */ + WOLFSSL_CBIO_ERR_WANT_READ = -2, /* need to call read again */ + WOLFSSL_CBIO_ERR_WANT_WRITE = -2, /* need to call write again */ + WOLFSSL_CBIO_ERR_CONN_RST = -3, /* connection reset */ + WOLFSSL_CBIO_ERR_ISR = -4, /* interrupt */ + WOLFSSL_CBIO_ERR_CONN_CLOSE = -5, /* connection closed or epipe */ + WOLFSSL_CBIO_ERR_TIMEOUT = -6 /* socket timeout */ +}; + + +/* CA cache callbacks */ +enum { + WOLFSSL_SSLV3 = 0, + WOLFSSL_TLSV1 = 1, + WOLFSSL_TLSV1_1 = 2, + WOLFSSL_TLSV1_2 = 3, + WOLFSSL_TLSV1_3 = 4, + WOLFSSL_USER_CA = 1, /* user added as trusted */ + WOLFSSL_CHAIN_CA = 2 /* added to cache from trusted chain */ +}; + +WOLFSSL_API WC_RNG* wolfSSL_GetRNG(WOLFSSL*); + +WOLFSSL_API int wolfSSL_CTX_SetMinVersion(WOLFSSL_CTX* ctx, int version); +WOLFSSL_API int wolfSSL_SetMinVersion(WOLFSSL* ssl, int version); +WOLFSSL_API int wolfSSL_GetObjectSize(void); /* object size based on build */ +WOLFSSL_API int wolfSSL_CTX_GetObjectSize(void); +WOLFSSL_API int wolfSSL_METHOD_GetObjectSize(void); +WOLFSSL_API int wolfSSL_GetOutputSize(WOLFSSL*, int); +WOLFSSL_API int wolfSSL_GetMaxOutputSize(WOLFSSL*); +WOLFSSL_API int wolfSSL_GetVersion(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_SetVersion(WOLFSSL* ssl, int version); + +/* moved to asn.c, old names kept for backwards compatability */ +#define wolfSSL_KeyPemToDer wc_KeyPemToDer +#define wolfSSL_CertPemToDer wc_CertPemToDer +#define wolfSSL_PemPubKeyToDer wc_PemPubKeyToDer +#define wolfSSL_PubKeyPemToDer wc_PubKeyPemToDer +#define wolfSSL_PemCertToDer wc_PemCertToDer + + +typedef void (*CallbackCACache)(unsigned char* der, int sz, int type); +typedef void (*CbMissingCRL)(const char* url); +typedef int (*CbOCSPIO)(void*, const char*, int, + unsigned char*, int, unsigned char**); +typedef void (*CbOCSPRespFree)(void*,unsigned char*); + +#ifdef HAVE_CRL_IO +typedef int (*CbCrlIO)(WOLFSSL_CRL* crl, const char* url, int urlSz); +#endif + +/* User Atomic Record Layer CallBacks */ +typedef int (*CallbackMacEncrypt)(WOLFSSL* ssl, unsigned char* macOut, + const unsigned char* macIn, unsigned int macInSz, int macContent, + int macVerify, unsigned char* encOut, const unsigned char* encIn, + unsigned int encSz, void* ctx); +WOLFSSL_API void wolfSSL_CTX_SetMacEncryptCb(WOLFSSL_CTX*, CallbackMacEncrypt); +WOLFSSL_API void wolfSSL_SetMacEncryptCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetMacEncryptCtx(WOLFSSL* ssl); + +typedef int (*CallbackDecryptVerify)(WOLFSSL* ssl, + unsigned char* decOut, const unsigned char* decIn, + unsigned int decSz, int content, int verify, unsigned int* padSz, + void* ctx); +WOLFSSL_API void wolfSSL_CTX_SetDecryptVerifyCb(WOLFSSL_CTX*, + CallbackDecryptVerify); +WOLFSSL_API void wolfSSL_SetDecryptVerifyCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetDecryptVerifyCtx(WOLFSSL* ssl); + +WOLFSSL_API const unsigned char* wolfSSL_GetMacSecret(WOLFSSL*, int); +WOLFSSL_API const unsigned char* wolfSSL_GetClientWriteKey(WOLFSSL*); +WOLFSSL_API const unsigned char* wolfSSL_GetClientWriteIV(WOLFSSL*); +WOLFSSL_API const unsigned char* wolfSSL_GetServerWriteKey(WOLFSSL*); +WOLFSSL_API const unsigned char* wolfSSL_GetServerWriteIV(WOLFSSL*); +WOLFSSL_API int wolfSSL_GetKeySize(WOLFSSL*); +WOLFSSL_API int wolfSSL_GetIVSize(WOLFSSL*); +WOLFSSL_API int wolfSSL_GetSide(WOLFSSL*); +WOLFSSL_API int wolfSSL_IsTLSv1_1(WOLFSSL*); +WOLFSSL_API int wolfSSL_GetBulkCipher(WOLFSSL*); +WOLFSSL_API int wolfSSL_GetCipherBlockSize(WOLFSSL*); +WOLFSSL_API int wolfSSL_GetAeadMacSize(WOLFSSL*); +WOLFSSL_API int wolfSSL_GetHmacSize(WOLFSSL*); +WOLFSSL_API int wolfSSL_GetHmacType(WOLFSSL*); +WOLFSSL_API int wolfSSL_GetCipherType(WOLFSSL*); +WOLFSSL_API int wolfSSL_SetTlsHmacInner(WOLFSSL*, unsigned char*, + word32, int, int); + +/* Atomic User Needs */ +enum { + WOLFSSL_SERVER_END = 0, + WOLFSSL_CLIENT_END = 1, + WOLFSSL_NEITHER_END = 3, + WOLFSSL_BLOCK_TYPE = 2, + WOLFSSL_STREAM_TYPE = 3, + WOLFSSL_AEAD_TYPE = 4, + WOLFSSL_TLS_HMAC_INNER_SZ = 13 /* SEQ_SZ + ENUM + VERSION_SZ + LEN_SZ */ +}; + +/* for GetBulkCipher and internal use */ +enum BulkCipherAlgorithm { + wolfssl_cipher_null, + wolfssl_rc4, + wolfssl_rc2, + wolfssl_des, + wolfssl_triple_des, /* leading 3 (3des) not valid identifier */ + wolfssl_des40, +#ifdef HAVE_IDEA + wolfssl_idea, +#endif + wolfssl_aes, + wolfssl_aes_gcm, + wolfssl_aes_ccm, + wolfssl_chacha, + wolfssl_camellia, + wolfssl_hc128, /* wolfSSL extensions */ + wolfssl_rabbit +}; + + +/* for KDF TLS 1.2 mac types */ +enum KDF_MacAlgorithm { + wolfssl_sha256 = 4, /* needs to match hash.h wc_MACAlgorithm */ + wolfssl_sha384, + wolfssl_sha512 +}; + + +/* Public Key Callback support */ +#ifdef HAVE_PK_CALLBACKS +#ifdef HAVE_ECC + +struct ecc_key; + +typedef int (*CallbackEccKeyGen)(WOLFSSL* ssl, struct ecc_key* key, + unsigned int keySz, int ecc_curve, void* ctx); +WOLFSSL_API void wolfSSL_CTX_SetEccKeyGenCb(WOLFSSL_CTX*, CallbackEccKeyGen); +WOLFSSL_API void wolfSSL_SetEccKeyGenCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetEccKeyGenCtx(WOLFSSL* ssl); + +typedef int (*CallbackEccSign)(WOLFSSL* ssl, + const unsigned char* in, unsigned int inSz, + unsigned char* out, word32* outSz, + const unsigned char* keyDer, unsigned int keySz, + void* ctx); +WOLFSSL_API void wolfSSL_CTX_SetEccSignCb(WOLFSSL_CTX*, CallbackEccSign); +WOLFSSL_API void wolfSSL_SetEccSignCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetEccSignCtx(WOLFSSL* ssl); + +typedef int (*CallbackEccVerify)(WOLFSSL* ssl, + const unsigned char* sig, unsigned int sigSz, + const unsigned char* hash, unsigned int hashSz, + const unsigned char* keyDer, unsigned int keySz, + int* result, void* ctx); +WOLFSSL_API void wolfSSL_CTX_SetEccVerifyCb(WOLFSSL_CTX*, CallbackEccVerify); +WOLFSSL_API void wolfSSL_SetEccVerifyCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetEccVerifyCtx(WOLFSSL* ssl); + +typedef int (*CallbackEccSharedSecret)(WOLFSSL* ssl, struct ecc_key* otherKey, + unsigned char* pubKeyDer, word32* pubKeySz, + unsigned char* out, word32* outlen, + int side, void* ctx); /* side is WOLFSSL_CLIENT_END or WOLFSSL_SERVER_END */ +WOLFSSL_API void wolfSSL_CTX_SetEccSharedSecretCb(WOLFSSL_CTX*, CallbackEccSharedSecret); +WOLFSSL_API void wolfSSL_SetEccSharedSecretCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetEccSharedSecretCtx(WOLFSSL* ssl); +#endif + +#ifndef NO_DH +/* Public DH Key Callback support */ +struct DhKey; +typedef int (*CallbackDhAgree)(WOLFSSL* ssl, struct DhKey* key, + const unsigned char* priv, unsigned int privSz, + const unsigned char* otherPubKeyDer, unsigned int otherPubKeySz, + unsigned char* out, unsigned int* outlen, + void* ctx); +WOLFSSL_API void wolfSSL_CTX_SetDhAgreeCb(WOLFSSL_CTX*, CallbackDhAgree); +WOLFSSL_API void wolfSSL_SetDhAgreeCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetDhAgreeCtx(WOLFSSL* ssl); +#endif /* !NO_DH */ + +#ifdef HAVE_ED25519 +struct ed25519_key; +typedef int (*CallbackEd25519Sign)(WOLFSSL* ssl, + const unsigned char* in, unsigned int inSz, + unsigned char* out, unsigned int* outSz, + const unsigned char* keyDer, unsigned int keySz, + void* ctx); +WOLFSSL_API void wolfSSL_CTX_SetEd25519SignCb(WOLFSSL_CTX*, + CallbackEd25519Sign); +WOLFSSL_API void wolfSSL_SetEd25519SignCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetEd25519SignCtx(WOLFSSL* ssl); + +typedef int (*CallbackEd25519Verify)(WOLFSSL* ssl, + const unsigned char* sig, unsigned int sigSz, + const unsigned char* msg, unsigned int msgSz, + const unsigned char* keyDer, unsigned int keySz, + int* result, void* ctx); +WOLFSSL_API void wolfSSL_CTX_SetEd25519VerifyCb(WOLFSSL_CTX*, + CallbackEd25519Verify); +WOLFSSL_API void wolfSSL_SetEd25519VerifyCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetEd25519VerifyCtx(WOLFSSL* ssl); +#endif + +#ifdef HAVE_CURVE25519 +struct curve25519_key; + +typedef int (*CallbackX25519KeyGen)(WOLFSSL* ssl, struct curve25519_key* key, + unsigned int keySz, void* ctx); +WOLFSSL_API void wolfSSL_CTX_SetX25519KeyGenCb(WOLFSSL_CTX*, CallbackX25519KeyGen); +WOLFSSL_API void wolfSSL_SetX25519KeyGenCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetX25519KeyGenCtx(WOLFSSL* ssl); + +typedef int (*CallbackX25519SharedSecret)(WOLFSSL* ssl, + struct curve25519_key* otherKey, + unsigned char* pubKeyDer, unsigned int* pubKeySz, + unsigned char* out, unsigned int* outlen, + int side, void* ctx); + /* side is WOLFSSL_CLIENT_END or WOLFSSL_SERVER_END */ +WOLFSSL_API void wolfSSL_CTX_SetX25519SharedSecretCb(WOLFSSL_CTX*, + CallbackX25519SharedSecret); +WOLFSSL_API void wolfSSL_SetX25519SharedSecretCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetX25519SharedSecretCtx(WOLFSSL* ssl); +#endif + +#ifndef NO_RSA +typedef int (*CallbackRsaSign)(WOLFSSL* ssl, + const unsigned char* in, unsigned int inSz, + unsigned char* out, unsigned int* outSz, + const unsigned char* keyDer, unsigned int keySz, + void* ctx); +WOLFSSL_API void wolfSSL_CTX_SetRsaSignCb(WOLFSSL_CTX*, CallbackRsaSign); +WOLFSSL_API void wolfSSL_SetRsaSignCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetRsaSignCtx(WOLFSSL* ssl); + +typedef int (*CallbackRsaVerify)(WOLFSSL* ssl, + unsigned char* sig, unsigned int sigSz, + unsigned char** out, + const unsigned char* keyDer, unsigned int keySz, + void* ctx); +WOLFSSL_API void wolfSSL_CTX_SetRsaVerifyCb(WOLFSSL_CTX*, CallbackRsaVerify); +WOLFSSL_API void wolfSSL_CTX_SetRsaSignCheckCb(WOLFSSL_CTX*, CallbackRsaVerify); +WOLFSSL_API void wolfSSL_SetRsaVerifyCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetRsaVerifyCtx(WOLFSSL* ssl); + +#ifdef WC_RSA_PSS +typedef int (*CallbackRsaPssSign)(WOLFSSL* ssl, + const unsigned char* in, unsigned int inSz, + unsigned char* out, unsigned int* outSz, + int hash, int mgf, + const unsigned char* keyDer, unsigned int keySz, + void* ctx); +WOLFSSL_API void wolfSSL_CTX_SetRsaPssSignCb(WOLFSSL_CTX*, CallbackRsaPssSign); +WOLFSSL_API void wolfSSL_SetRsaPssSignCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetRsaPssSignCtx(WOLFSSL* ssl); + +typedef int (*CallbackRsaPssVerify)(WOLFSSL* ssl, + unsigned char* sig, unsigned int sigSz, + unsigned char** out, + int hash, int mgf, + const unsigned char* keyDer, unsigned int keySz, + void* ctx); +WOLFSSL_API void wolfSSL_CTX_SetRsaPssVerifyCb(WOLFSSL_CTX*, + CallbackRsaPssVerify); +WOLFSSL_API void wolfSSL_CTX_SetRsaPssSignCheckCb(WOLFSSL_CTX*, + CallbackRsaPssVerify); +WOLFSSL_API void wolfSSL_SetRsaPssVerifyCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetRsaPssVerifyCtx(WOLFSSL* ssl); +#endif + +/* RSA Public Encrypt cb */ +typedef int (*CallbackRsaEnc)(WOLFSSL* ssl, + const unsigned char* in, unsigned int inSz, + unsigned char* out, unsigned int* outSz, + const unsigned char* keyDer, unsigned int keySz, + void* ctx); +WOLFSSL_API void wolfSSL_CTX_SetRsaEncCb(WOLFSSL_CTX*, CallbackRsaEnc); +WOLFSSL_API void wolfSSL_SetRsaEncCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetRsaEncCtx(WOLFSSL* ssl); + +/* RSA Private Decrypt cb */ +typedef int (*CallbackRsaDec)(WOLFSSL* ssl, + unsigned char* in, unsigned int inSz, + unsigned char** out, + const unsigned char* keyDer, unsigned int keySz, + void* ctx); +WOLFSSL_API void wolfSSL_CTX_SetRsaDecCb(WOLFSSL_CTX*, CallbackRsaDec); +WOLFSSL_API void wolfSSL_SetRsaDecCtx(WOLFSSL* ssl, void *ctx); +WOLFSSL_API void* wolfSSL_GetRsaDecCtx(WOLFSSL* ssl); +#endif +#endif /* HAVE_PK_CALLBACKS */ + +#ifndef NO_CERTS + WOLFSSL_API void wolfSSL_CTX_SetCACb(WOLFSSL_CTX*, CallbackCACache); + + WOLFSSL_API WOLFSSL_CERT_MANAGER* wolfSSL_CTX_GetCertManager(WOLFSSL_CTX*); + + WOLFSSL_API WOLFSSL_CERT_MANAGER* wolfSSL_CertManagerNew_ex(void* heap); + WOLFSSL_API WOLFSSL_CERT_MANAGER* wolfSSL_CertManagerNew(void); + WOLFSSL_API void wolfSSL_CertManagerFree(WOLFSSL_CERT_MANAGER*); + + WOLFSSL_API int wolfSSL_CertManagerLoadCA(WOLFSSL_CERT_MANAGER*, const char* f, + const char* d); + WOLFSSL_API int wolfSSL_CertManagerLoadCABuffer(WOLFSSL_CERT_MANAGER*, + const unsigned char* in, long sz, int format); + WOLFSSL_API int wolfSSL_CertManagerUnloadCAs(WOLFSSL_CERT_MANAGER* cm); +#ifdef WOLFSSL_TRUST_PEER_CERT + WOLFSSL_API int wolfSSL_CertManagerUnload_trust_peers(WOLFSSL_CERT_MANAGER* cm); +#endif + WOLFSSL_API int wolfSSL_CertManagerVerify(WOLFSSL_CERT_MANAGER*, const char* f, + int format); + WOLFSSL_API int wolfSSL_CertManagerVerifyBuffer(WOLFSSL_CERT_MANAGER* cm, + const unsigned char* buff, long sz, int format); + WOLFSSL_API int wolfSSL_CertManagerCheckCRL(WOLFSSL_CERT_MANAGER*, + unsigned char*, int sz); + WOLFSSL_API int wolfSSL_CertManagerEnableCRL(WOLFSSL_CERT_MANAGER*, + int options); + WOLFSSL_API int wolfSSL_CertManagerDisableCRL(WOLFSSL_CERT_MANAGER*); + WOLFSSL_API int wolfSSL_CertManagerLoadCRL(WOLFSSL_CERT_MANAGER*, + const char*, int, int); + WOLFSSL_API int wolfSSL_CertManagerLoadCRLBuffer(WOLFSSL_CERT_MANAGER*, + const unsigned char*, long sz, int); + WOLFSSL_API int wolfSSL_CertManagerSetCRL_Cb(WOLFSSL_CERT_MANAGER*, + CbMissingCRL); + WOLFSSL_API int wolfSSL_CertManagerFreeCRL(WOLFSSL_CERT_MANAGER *); +#ifdef HAVE_CRL_IO + WOLFSSL_API int wolfSSL_CertManagerSetCRL_IOCb(WOLFSSL_CERT_MANAGER*, + CbCrlIO); +#endif +#if defined(HAVE_OCSP) + WOLFSSL_API int wolfSSL_CertManagerCheckOCSPResponse(WOLFSSL_CERT_MANAGER *, + byte *response, int responseSz, WOLFSSL_BUFFER_INFO *responseBuffer, + CertStatus *status, OcspEntry *entry, OcspRequest *ocspRequest); +#endif + WOLFSSL_API int wolfSSL_CertManagerCheckOCSP(WOLFSSL_CERT_MANAGER*, + unsigned char*, int sz); + WOLFSSL_API int wolfSSL_CertManagerEnableOCSP(WOLFSSL_CERT_MANAGER*, + int options); + WOLFSSL_API int wolfSSL_CertManagerDisableOCSP(WOLFSSL_CERT_MANAGER*); + WOLFSSL_API int wolfSSL_CertManagerSetOCSPOverrideURL(WOLFSSL_CERT_MANAGER*, + const char*); + WOLFSSL_API int wolfSSL_CertManagerSetOCSP_Cb(WOLFSSL_CERT_MANAGER*, + CbOCSPIO, CbOCSPRespFree, void*); + + WOLFSSL_API int wolfSSL_CertManagerEnableOCSPStapling( + WOLFSSL_CERT_MANAGER* cm); + WOLFSSL_API int wolfSSL_CertManagerDisableOCSPStapling( + WOLFSSL_CERT_MANAGER* cm); + + WOLFSSL_API int wolfSSL_EnableCRL(WOLFSSL* ssl, int options); + WOLFSSL_API int wolfSSL_DisableCRL(WOLFSSL* ssl); + WOLFSSL_API int wolfSSL_LoadCRL(WOLFSSL*, const char*, int, int); + WOLFSSL_API int wolfSSL_LoadCRLBuffer(WOLFSSL*, + const unsigned char*, long sz, int); + WOLFSSL_API int wolfSSL_SetCRL_Cb(WOLFSSL*, CbMissingCRL); +#ifdef HAVE_CRL_IO + WOLFSSL_API int wolfSSL_SetCRL_IOCb(WOLFSSL* ssl, CbCrlIO cb); +#endif + WOLFSSL_API int wolfSSL_EnableOCSP(WOLFSSL*, int options); + WOLFSSL_API int wolfSSL_DisableOCSP(WOLFSSL*); + WOLFSSL_API int wolfSSL_SetOCSP_OverrideURL(WOLFSSL*, const char*); + WOLFSSL_API int wolfSSL_SetOCSP_Cb(WOLFSSL*, CbOCSPIO, CbOCSPRespFree, void*); + WOLFSSL_API int wolfSSL_EnableOCSPStapling(WOLFSSL*); + WOLFSSL_API int wolfSSL_DisableOCSPStapling(WOLFSSL*); + + WOLFSSL_API int wolfSSL_CTX_EnableCRL(WOLFSSL_CTX* ctx, int options); + WOLFSSL_API int wolfSSL_CTX_DisableCRL(WOLFSSL_CTX* ctx); + WOLFSSL_API int wolfSSL_CTX_LoadCRL(WOLFSSL_CTX*, const char*, int, int); + WOLFSSL_API int wolfSSL_CTX_LoadCRLBuffer(WOLFSSL_CTX*, + const unsigned char*, long sz, int); + WOLFSSL_API int wolfSSL_CTX_SetCRL_Cb(WOLFSSL_CTX*, CbMissingCRL); +#ifdef HAVE_CRL_IO + WOLFSSL_API int wolfSSL_CTX_SetCRL_IOCb(WOLFSSL_CTX*, CbCrlIO); +#endif + + WOLFSSL_API int wolfSSL_CTX_EnableOCSP(WOLFSSL_CTX*, int options); + WOLFSSL_API int wolfSSL_CTX_DisableOCSP(WOLFSSL_CTX*); + WOLFSSL_API int wolfSSL_CTX_SetOCSP_OverrideURL(WOLFSSL_CTX*, const char*); + WOLFSSL_API int wolfSSL_CTX_SetOCSP_Cb(WOLFSSL_CTX*, + CbOCSPIO, CbOCSPRespFree, void*); + WOLFSSL_API int wolfSSL_CTX_EnableOCSPStapling(WOLFSSL_CTX*); + WOLFSSL_API int wolfSSL_CTX_DisableOCSPStapling(WOLFSSL_CTX*); +#endif /* !NO_CERTS */ + + +#ifdef SINGLE_THREADED + WOLFSSL_API int wolfSSL_CTX_new_rng(WOLFSSL_CTX*); +#endif + +/* end of handshake frees temporary arrays, if user needs for get_keys or + psk hints, call KeepArrays before handshake and then FreeArrays when done + if don't want to wait for object free */ +WOLFSSL_API void wolfSSL_KeepArrays(WOLFSSL*); +WOLFSSL_API void wolfSSL_FreeArrays(WOLFSSL*); + +WOLFSSL_API int wolfSSL_KeepHandshakeResources(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_FreeHandshakeResources(WOLFSSL* ssl); + +WOLFSSL_API int wolfSSL_CTX_UseClientSuites(WOLFSSL_CTX* ctx); +WOLFSSL_API int wolfSSL_UseClientSuites(WOLFSSL* ssl); + +/* async additions */ +#define wolfSSL_UseAsync wolfSSL_SetDevId +#define wolfSSL_CTX_UseAsync wolfSSL_CTX_SetDevId +WOLFSSL_API int wolfSSL_SetDevId(WOLFSSL*, int devId); +WOLFSSL_API int wolfSSL_CTX_SetDevId(WOLFSSL_CTX*, int devId); + +/* helpers to get device id and heap */ +WOLFSSL_API int wolfSSL_CTX_GetDevId(WOLFSSL_CTX* ctx, WOLFSSL* ssl); +WOLFSSL_API void* wolfSSL_CTX_GetHeap(WOLFSSL_CTX* ctx, WOLFSSL* ssl); + +/* TLS Extensions */ + +/* Server Name Indication */ +#ifdef HAVE_SNI + +/* SNI types */ +enum { + WOLFSSL_SNI_HOST_NAME = 0 +}; + +WOLFSSL_API int wolfSSL_UseSNI(WOLFSSL* ssl, unsigned char type, + const void* data, unsigned short size); +WOLFSSL_API int wolfSSL_CTX_UseSNI(WOLFSSL_CTX* ctx, unsigned char type, + const void* data, unsigned short size); + +#ifndef NO_WOLFSSL_SERVER + +/* SNI options */ +enum { + /* Do not abort the handshake if the requested SNI didn't match. */ + WOLFSSL_SNI_CONTINUE_ON_MISMATCH = 0x01, + + /* Behave as if the requested SNI matched in a case of mismatch. */ + /* In this case, the status will be set to WOLFSSL_SNI_FAKE_MATCH. */ + WOLFSSL_SNI_ANSWER_ON_MISMATCH = 0x02, + + /* Abort the handshake if the client didn't send a SNI request. */ + WOLFSSL_SNI_ABORT_ON_ABSENCE = 0x04, +}; + +WOLFSSL_API void wolfSSL_SNI_SetOptions(WOLFSSL* ssl, unsigned char type, + unsigned char options); +WOLFSSL_API void wolfSSL_CTX_SNI_SetOptions(WOLFSSL_CTX* ctx, + unsigned char type, unsigned char options); +WOLFSSL_API int wolfSSL_SNI_GetFromBuffer( + const unsigned char* clientHello, unsigned int helloSz, + unsigned char type, unsigned char* sni, unsigned int* inOutSz); + +#endif /* NO_WOLFSSL_SERVER */ + +/* SNI status */ +enum { + WOLFSSL_SNI_NO_MATCH = 0, + WOLFSSL_SNI_FAKE_MATCH = 1, /**< @see WOLFSSL_SNI_ANSWER_ON_MISMATCH */ + WOLFSSL_SNI_REAL_MATCH = 2, + WOLFSSL_SNI_FORCE_KEEP = 3 /** Used with -DWOLFSSL_ALWAYS_KEEP_SNI */ +}; + +WOLFSSL_API unsigned char wolfSSL_SNI_Status(WOLFSSL* ssl, unsigned char type); + +WOLFSSL_API unsigned short wolfSSL_SNI_GetRequest(WOLFSSL *ssl, + unsigned char type, void** data); + +#endif /* HAVE_SNI */ + +/* Trusted CA Key Indication - RFC 6066 (Section 6) */ +#ifdef HAVE_TRUSTED_CA + +/* TCA Identifier Type */ +enum { + WOLFSSL_TRUSTED_CA_PRE_AGREED = 0, + WOLFSSL_TRUSTED_CA_KEY_SHA1 = 1, + WOLFSSL_TRUSTED_CA_X509_NAME = 2, + WOLFSSL_TRUSTED_CA_CERT_SHA1 = 3 +}; + +WOLFSSL_API int wolfSSL_UseTrustedCA(WOLFSSL* ssl, unsigned char type, + const unsigned char* certId, unsigned int certIdSz); +#endif /* HAVE_TRUSTED_CA */ + +/* Application-Layer Protocol Negotiation */ +#ifdef HAVE_ALPN + +/* ALPN status code */ +enum { + WOLFSSL_ALPN_NO_MATCH = 0, + WOLFSSL_ALPN_MATCH = 1, + WOLFSSL_ALPN_CONTINUE_ON_MISMATCH = 2, + WOLFSSL_ALPN_FAILED_ON_MISMATCH = 4, +}; + +enum { + WOLFSSL_MAX_ALPN_PROTO_NAME_LEN = 255, + WOLFSSL_MAX_ALPN_NUMBER = 257 +}; + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) +typedef int (*CallbackALPNSelect)(WOLFSSL* ssl, const unsigned char** out, + unsigned char* outLen, const unsigned char* in, unsigned int inLen, + void *arg); +#endif + +WOLFSSL_API int wolfSSL_UseALPN(WOLFSSL* ssl, char *protocol_name_list, + unsigned int protocol_name_listSz, + unsigned char options); + +WOLFSSL_API int wolfSSL_ALPN_GetProtocol(WOLFSSL* ssl, char **protocol_name, + unsigned short *size); + +WOLFSSL_API int wolfSSL_ALPN_GetPeerProtocol(WOLFSSL* ssl, char **list, + unsigned short *listSz); +WOLFSSL_API int wolfSSL_ALPN_FreePeerProtocol(WOLFSSL* ssl, char **list); +#endif /* HAVE_ALPN */ + +/* Maximum Fragment Length */ +#ifdef HAVE_MAX_FRAGMENT + +/* Fragment lengths */ +enum { + WOLFSSL_MFL_2_9 = 1, /* 512 bytes */ + WOLFSSL_MFL_2_10 = 2, /* 1024 bytes */ + WOLFSSL_MFL_2_11 = 3, /* 2048 bytes */ + WOLFSSL_MFL_2_12 = 4, /* 4096 bytes */ + WOLFSSL_MFL_2_13 = 5, /* 8192 bytes *//* wolfSSL ONLY!!! */ + WOLFSSL_MFL_2_8 = 6, /* 256 bytes *//* wolfSSL ONLY!!! */ + WOLFSSL_MFL_MIN = WOLFSSL_MFL_2_9, + WOLFSSL_MFL_MAX = WOLFSSL_MFL_2_8, +}; + +#ifndef NO_WOLFSSL_CLIENT + +WOLFSSL_API int wolfSSL_UseMaxFragment(WOLFSSL* ssl, unsigned char mfl); +WOLFSSL_API int wolfSSL_CTX_UseMaxFragment(WOLFSSL_CTX* ctx, unsigned char mfl); + +#endif +#endif /* HAVE_MAX_FRAGMENT */ + +/* Truncated HMAC */ +#ifdef HAVE_TRUNCATED_HMAC +#ifndef NO_WOLFSSL_CLIENT + +WOLFSSL_API int wolfSSL_UseTruncatedHMAC(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_CTX_UseTruncatedHMAC(WOLFSSL_CTX* ctx); + +#endif +#endif + +/* Certificate Status Request */ +/* Certificate Status Type */ +enum { + WOLFSSL_CSR_OCSP = 1 +}; + +/* Certificate Status Options (flags) */ +enum { + WOLFSSL_CSR_OCSP_USE_NONCE = 0x01 +}; + +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST +#ifndef NO_WOLFSSL_CLIENT + +WOLFSSL_API int wolfSSL_UseOCSPStapling(WOLFSSL* ssl, + unsigned char status_type, unsigned char options); + +WOLFSSL_API int wolfSSL_CTX_UseOCSPStapling(WOLFSSL_CTX* ctx, + unsigned char status_type, unsigned char options); + +#endif +#endif + +/* Certificate Status Request v2 */ +/* Certificate Status Type */ +enum { + WOLFSSL_CSR2_OCSP = 1, + WOLFSSL_CSR2_OCSP_MULTI = 2 +}; + +/* Certificate Status v2 Options (flags) */ +enum { + WOLFSSL_CSR2_OCSP_USE_NONCE = 0x01 +}; + +#ifdef HAVE_CERTIFICATE_STATUS_REQUEST_V2 +#ifndef NO_WOLFSSL_CLIENT + +WOLFSSL_API int wolfSSL_UseOCSPStaplingV2(WOLFSSL* ssl, + unsigned char status_type, unsigned char options); + +WOLFSSL_API int wolfSSL_CTX_UseOCSPStaplingV2(WOLFSSL_CTX* ctx, + unsigned char status_type, unsigned char options); + +#endif +#endif + +/* Named Groups */ +enum { +#if 0 /* Not Supported */ + WOLFSSL_ECC_SECT163K1 = 1, + WOLFSSL_ECC_SECT163R1 = 2, + WOLFSSL_ECC_SECT163R2 = 3, + WOLFSSL_ECC_SECT193R1 = 4, + WOLFSSL_ECC_SECT193R2 = 5, + WOLFSSL_ECC_SECT233K1 = 6, + WOLFSSL_ECC_SECT233R1 = 7, + WOLFSSL_ECC_SECT239K1 = 8, + WOLFSSL_ECC_SECT283K1 = 9, + WOLFSSL_ECC_SECT283R1 = 10, + WOLFSSL_ECC_SECT409K1 = 11, + WOLFSSL_ECC_SECT409R1 = 12, + WOLFSSL_ECC_SECT571K1 = 13, + WOLFSSL_ECC_SECT571R1 = 14, +#endif + WOLFSSL_ECC_SECP160K1 = 15, + WOLFSSL_ECC_SECP160R1 = 16, + WOLFSSL_ECC_SECP160R2 = 17, + WOLFSSL_ECC_SECP192K1 = 18, + WOLFSSL_ECC_SECP192R1 = 19, + WOLFSSL_ECC_SECP224K1 = 20, + WOLFSSL_ECC_SECP224R1 = 21, + WOLFSSL_ECC_SECP256K1 = 22, + WOLFSSL_ECC_SECP256R1 = 23, + WOLFSSL_ECC_SECP384R1 = 24, + WOLFSSL_ECC_SECP521R1 = 25, + WOLFSSL_ECC_BRAINPOOLP256R1 = 26, + WOLFSSL_ECC_BRAINPOOLP384R1 = 27, + WOLFSSL_ECC_BRAINPOOLP512R1 = 28, + WOLFSSL_ECC_X25519 = 29, + /* Not implemented. */ + WOLFSSL_ECC_X448 = 30, + + WOLFSSL_FFDHE_2048 = 256, + WOLFSSL_FFDHE_3072 = 257, + WOLFSSL_FFDHE_4096 = 258, + WOLFSSL_FFDHE_6144 = 259, + WOLFSSL_FFDHE_8192 = 260, +}; + +enum { + WOLFSSL_EC_PF_UNCOMPRESSED = 0, +#if 0 /* Not Supported */ + WOLFSSL_EC_PF_X962_COMP_PRIME = 1, + WOLFSSL_EC_PF_X962_COMP_CHAR2 = 2, +#endif +}; + +#ifdef HAVE_SUPPORTED_CURVES +#ifndef NO_WOLFSSL_CLIENT + +WOLFSSL_API int wolfSSL_UseSupportedCurve(WOLFSSL* ssl, word16 name); +WOLFSSL_API int wolfSSL_CTX_UseSupportedCurve(WOLFSSL_CTX* ctx, + word16 name); + +#endif +#endif + +#ifdef WOLFSSL_TLS13 +WOLFSSL_API int wolfSSL_UseKeyShare(WOLFSSL* ssl, word16 group); +WOLFSSL_API int wolfSSL_NoKeyShares(WOLFSSL* ssl); +#endif + + +/* Secure Renegotiation */ +#ifdef HAVE_SECURE_RENEGOTIATION + +WOLFSSL_API int wolfSSL_UseSecureRenegotiation(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_StartSecureRenegotiation(WOLFSSL* ssl, int resume); +WOLFSSL_API int wolfSSL_Rehandshake(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_SecureResume(WOLFSSL* ssl); + +#endif + +/* Session Ticket */ +#ifdef HAVE_SESSION_TICKET + +#ifndef NO_WOLFSSL_CLIENT +WOLFSSL_API int wolfSSL_UseSessionTicket(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_CTX_UseSessionTicket(WOLFSSL_CTX* ctx); +WOLFSSL_API int wolfSSL_get_SessionTicket(WOLFSSL*, unsigned char*, word32*); +WOLFSSL_API int wolfSSL_set_SessionTicket(WOLFSSL*, const unsigned char*, word32); +typedef int (*CallbackSessionTicket)(WOLFSSL*, const unsigned char*, int, void*); +WOLFSSL_API int wolfSSL_set_SessionTicket_cb(WOLFSSL*, + CallbackSessionTicket, void*); +#endif /* NO_WOLFSSL_CLIENT */ + + +#define WOLFSSL_TICKET_NAME_SZ 16 +#define WOLFSSL_TICKET_IV_SZ 16 +#define WOLFSSL_TICKET_MAC_SZ 32 + +enum TicketEncRet { + WOLFSSL_TICKET_RET_FATAL = -1, /* fatal error, don't use ticket */ + WOLFSSL_TICKET_RET_OK = 0, /* ok, use ticket */ + WOLFSSL_TICKET_RET_REJECT, /* don't use ticket, but not fatal */ + WOLFSSL_TICKET_RET_CREATE /* existing ticket ok and create new one */ +}; + +#ifndef NO_WOLFSSL_SERVER + +typedef int (*SessionTicketEncCb)(WOLFSSL*, + unsigned char key_name[WOLFSSL_TICKET_NAME_SZ], + unsigned char iv[WOLFSSL_TICKET_IV_SZ], + unsigned char mac[WOLFSSL_TICKET_MAC_SZ], + int enc, unsigned char*, int, int*, void*); +WOLFSSL_API int wolfSSL_CTX_set_TicketEncCb(WOLFSSL_CTX* ctx, + SessionTicketEncCb); +WOLFSSL_API int wolfSSL_CTX_set_TicketHint(WOLFSSL_CTX* ctx, int); +WOLFSSL_API int wolfSSL_CTX_set_TicketEncCtx(WOLFSSL_CTX* ctx, void*); + +#endif /* NO_WOLFSSL_SERVER */ + +#endif /* HAVE_SESSION_TICKET */ + +#ifdef HAVE_QSH +/* Quantum-safe Crypto Schemes */ +enum { + WOLFSSL_NTRU_EESS439 = 0x0101, /* max plaintext length of 65 */ + WOLFSSL_NTRU_EESS593 = 0x0102, /* max plaintext length of 86 */ + WOLFSSL_NTRU_EESS743 = 0x0103, /* max plaintext length of 106 */ + WOLFSSL_LWE_XXX = 0x0201, /* Learning With Error encryption scheme */ + WOLFSSL_HFE_XXX = 0x0301, /* Hidden Field Equation scheme */ + WOLFSSL_NULL_QSH = 0xFFFF /* QSHScheme is not used */ +}; + + +/* test if the connection is using a QSH secure connection return 1 if so */ +WOLFSSL_API int wolfSSL_isQSH(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_UseSupportedQSH(WOLFSSL* ssl, unsigned short name); +#ifndef NO_WOLFSSL_CLIENT + /* user control over sending client public key in hello + when flag = 1 will send keys if flag is 0 or function is not called + then will not send keys in the hello extension */ + WOLFSSL_API int wolfSSL_UseClientQSHKeys(WOLFSSL* ssl, unsigned char flag); +#endif + +#endif /* QSH */ + +/* TLS Extended Master Secret Extension */ +WOLFSSL_API int wolfSSL_DisableExtendedMasterSecret(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_CTX_DisableExtendedMasterSecret(WOLFSSL_CTX* ctx); + + +#define WOLFSSL_CRL_MONITOR 0x01 /* monitor this dir flag */ +#define WOLFSSL_CRL_START_MON 0x02 /* start monitoring flag */ + + +/* notify user the handshake is done */ +typedef int (*HandShakeDoneCb)(WOLFSSL*, void*); +WOLFSSL_API int wolfSSL_SetHsDoneCb(WOLFSSL*, HandShakeDoneCb, void*); + + +WOLFSSL_API int wolfSSL_PrintSessionStats(void); +WOLFSSL_API int wolfSSL_get_session_stats(unsigned int* active, + unsigned int* total, + unsigned int* peak, + unsigned int* maxSessions); +/* External facing KDF */ +WOLFSSL_API +int wolfSSL_MakeTlsMasterSecret(unsigned char* ms, word32 msLen, + const unsigned char* pms, word32 pmsLen, + const unsigned char* cr, const unsigned char* sr, + int tls1_2, int hash_type); + +WOLFSSL_API +int wolfSSL_MakeTlsExtendedMasterSecret(unsigned char* ms, word32 msLen, + const unsigned char* pms, word32 pmsLen, + const unsigned char* sHash, word32 sHashLen, + int tls1_2, int hash_type); + +WOLFSSL_API +int wolfSSL_DeriveTlsKeys(unsigned char* key_data, word32 keyLen, + const unsigned char* ms, word32 msLen, + const unsigned char* sr, const unsigned char* cr, + int tls1_2, int hash_type); + +#ifdef WOLFSSL_CALLBACKS + +/* used internally by wolfSSL while OpenSSL types aren't */ +#include + +typedef int (*HandShakeCallBack)(HandShakeInfo*); +typedef int (*TimeoutCallBack)(TimeoutInfo*); + +/* wolfSSL connect extension allowing HandShakeCallBack and/or TimeoutCallBack + for diagnostics */ +WOLFSSL_API int wolfSSL_connect_ex(WOLFSSL*, HandShakeCallBack, TimeoutCallBack, + Timeval); +WOLFSSL_API int wolfSSL_accept_ex(WOLFSSL*, HandShakeCallBack, TimeoutCallBack, + Timeval); + +#endif /* WOLFSSL_CALLBACKS */ + + +#ifdef WOLFSSL_HAVE_WOLFSCEP + WOLFSSL_API void wolfSSL_wolfSCEP(void); +#endif /* WOLFSSL_HAVE_WOLFSCEP */ + +#ifdef WOLFSSL_HAVE_CERT_SERVICE + WOLFSSL_API void wolfSSL_cert_service(void); +#endif + +#if defined(OPENSSL_ALL) || defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) +/* Smaller subset of X509 compatibility functions. Avoid increasing the size of + * this subset and its memory usage */ + +#include +struct WOLFSSL_X509_NAME_ENTRY { + WOLFSSL_ASN1_OBJECT object; /* static object just for keeping grp, type */ + WOLFSSL_ASN1_STRING data; + WOLFSSL_ASN1_STRING* value; /* points to data, for lighttpd port */ + int nid; /* i.e. ASN_COMMON_NAME */ + int set; + int size; +}; +#endif /* OPENSSL_ALL || OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ + + +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) + +enum { + WOLFSSL_SYS_ACCEPT = 0, + WOLFSSL_SYS_BIND, + WOLFSSL_SYS_CONNECT, + WOLFSSL_SYS_FOPEN, + WOLFSSL_SYS_FREAD, + WOLFSSL_SYS_GETADDRINFO, + WOLFSSL_SYS_GETSOCKOPT, + WOLFSSL_SYS_GETSOCKNAME, + WOLFSSL_SYS_GETHOSTBYNAME, + WOLFSSL_SYS_GETNAMEINFO, + WOLFSSL_SYS_GETSERVBYNAME, + WOLFSSL_SYS_IOCTLSOCKET, + WOLFSSL_SYS_LISTEN, + WOLFSSL_SYS_OPENDIR, + WOLFSSL_SYS_SETSOCKOPT, + WOLFSSL_SYS_SOCKET +}; + +/* Object functions */ +WOLFSSL_API const char * wolfSSL_OBJ_nid2sn(int n); +WOLFSSL_API int wolfSSL_OBJ_obj2nid(const WOLFSSL_ASN1_OBJECT *o); +WOLFSSL_API int wolfSSL_OBJ_sn2nid(const char *sn); + +WOLFSSL_API char* wolfSSL_OBJ_nid2ln(int n); +WOLFSSL_API int wolfSSL_OBJ_txt2nid(const char *sn); + +WOLFSSL_API WOLFSSL_ASN1_OBJECT* wolfSSL_OBJ_nid2obj(int n); +WOLFSSL_LOCAL WOLFSSL_ASN1_OBJECT* wolfSSL_OBJ_nid2obj_ex(int n, WOLFSSL_ASN1_OBJECT *arg_obj); +WOLFSSL_API int wolfSSL_OBJ_obj2txt(char *buf, int buf_len, WOLFSSL_ASN1_OBJECT *a, int no_name); + +WOLFSSL_API void wolfSSL_OBJ_cleanup(void); +/* end of object functions */ + +WOLFSSL_API unsigned long wolfSSL_ERR_peek_last_error_line(const char **file, int *line); +WOLFSSL_API long wolfSSL_ctrl(WOLFSSL* ssl, int cmd, long opt, void* pt); +WOLFSSL_API long wolfSSL_CTX_ctrl(WOLFSSL_CTX* ctx, int cmd, long opt,void* pt); + +#ifndef NO_CERTS +WOLFSSL_API WOLFSSL_X509_NAME_ENTRY* wolfSSL_X509_NAME_ENTRY_create_by_NID( + WOLFSSL_X509_NAME_ENTRY** out, int nid, int type, + unsigned char* data, int dataSz); +WOLFSSL_API int wolfSSL_X509_NAME_add_entry(WOLFSSL_X509_NAME* name, + WOLFSSL_X509_NAME_ENTRY* entry, int idx, int set); +WOLFSSL_API int wolfSSL_X509_NAME_add_entry_by_txt(WOLFSSL_X509_NAME *name, + const char *field, int type, const unsigned char *bytes, int len, int loc, + int set); +WOLFSSL_API int wolfSSL_X509_NAME_cmp(const WOLFSSL_X509_NAME* x, + const WOLFSSL_X509_NAME* y); +WOLFSSL_API WOLFSSL_X509_NAME* wolfSSL_X509_NAME_new(void); +WOLFSSL_API int wolfSSL_check_private_key(const WOLFSSL* ssl); +WOLFSSL_API void* wolfSSL_X509_get_ext_d2i(const WOLFSSL_X509* x509, + int nid, int* c, int* idx); +WOLFSSL_API int wolfSSL_X509_digest(const WOLFSSL_X509* x509, + const WOLFSSL_EVP_MD* digest, unsigned char* buf, unsigned int* len); +WOLFSSL_API int wolfSSL_use_certificate(WOLFSSL* ssl, WOLFSSL_X509* x509); +WOLFSSL_API int wolfSSL_use_PrivateKey(WOLFSSL* ssl, WOLFSSL_EVP_PKEY* pkey); +WOLFSSL_API int wolfSSL_use_PrivateKey_ASN1(int pri, WOLFSSL* ssl, + unsigned char* der, long derSz); +WOLFSSL_API WOLFSSL_EVP_PKEY *wolfSSL_get_privatekey(const WOLFSSL *ssl); +#ifndef NO_RSA +WOLFSSL_API int wolfSSL_use_RSAPrivateKey_ASN1(WOLFSSL* ssl, unsigned char* der, + long derSz); +#endif +#endif /* NO_CERTS */ + +WOLFSSL_API WOLFSSL_DH *wolfSSL_DSA_dup_DH(const WOLFSSL_DSA *r); + +WOLFSSL_API int wolfSSL_SESSION_get_master_key(const WOLFSSL_SESSION* ses, + unsigned char* out, int outSz); +WOLFSSL_API int wolfSSL_SESSION_get_master_key_length(const WOLFSSL_SESSION* ses); + +WOLFSSL_API void wolfSSL_CTX_set_cert_store(WOLFSSL_CTX* ctx, + WOLFSSL_X509_STORE* str); +WOLFSSL_API int wolfSSL_i2d_X509_bio(WOLFSSL_BIO* bio, WOLFSSL_X509* x509); +#if !defined(NO_FILESYSTEM) +WOLFSSL_API WOLFSSL_X509* wolfSSL_d2i_X509_fp(XFILE fp, + WOLFSSL_X509** x509); +#endif +WOLFSSL_API WOLFSSL_X509* wolfSSL_d2i_X509_bio(WOLFSSL_BIO* bio, + WOLFSSL_X509** x509); +WOLFSSL_API WOLFSSL_X509_STORE* wolfSSL_CTX_get_cert_store(WOLFSSL_CTX* ctx); + +WOLFSSL_API size_t wolfSSL_BIO_wpending(const WOLFSSL_BIO *bio); +WOLFSSL_API size_t wolfSSL_BIO_ctrl_pending(WOLFSSL_BIO *b); +WOLFSSL_API size_t wolfSSL_get_server_random(const WOLFSSL *ssl, + unsigned char *out, size_t outlen); +WOLFSSL_API size_t wolfSSL_get_client_random(const WOLFSSL* ssl, + unsigned char* out, size_t outSz); +WOLFSSL_API int wolfSSL_CTX_use_PrivateKey(WOLFSSL_CTX *ctx, WOLFSSL_EVP_PKEY *pkey); +WOLFSSL_API WOLFSSL_X509 *wolfSSL_PEM_read_bio_X509(WOLFSSL_BIO *bp, WOLFSSL_X509 **x, pem_password_cb *cb, void *u); +WOLFSSL_API WOLFSSL_X509 *wolfSSL_PEM_read_bio_X509_AUX + (WOLFSSL_BIO *bp, WOLFSSL_X509 **x, pem_password_cb *cb, void *u); +#ifndef NO_FILESYSTEM +WOLFSSL_API WOLFSSL_X509_CRL *wolfSSL_PEM_read_X509_CRL(XFILE fp, + WOLFSSL_X509_CRL **x, pem_password_cb *cb, void *u); +#endif +WOLFSSL_API int wolfSSL_PEM_get_EVP_CIPHER_INFO(char* header, + EncryptedInfo* cipher); +WOLFSSL_API int wolfSSL_PEM_do_header(EncryptedInfo* cipher, + unsigned char* data, long* len, + pem_password_cb* callback, void* ctx); + +/*lighttp compatibility */ + +struct WOLFSSL_ASN1_BIT_STRING { + int length; + int type; + char* data; + long flags; +}; + + +#if defined(OPENSSL_EXTRA) \ + || defined(OPENSSL_ALL) \ + || defined(HAVE_LIGHTY) \ + || defined(WOLFSSL_MYSQL_COMPATIBLE) \ + || defined(HAVE_STUNNEL) \ + || defined(WOLFSSL_NGINX) \ + || defined(WOLFSSL_HAPROXY) +WOLFSSL_API void wolfSSL_X509_NAME_ENTRY_free(WOLFSSL_X509_NAME_ENTRY* ne); +WOLFSSL_API WOLFSSL_X509_NAME_ENTRY* wolfSSL_X509_NAME_ENTRY_new(void); +WOLFSSL_API void wolfSSL_X509_NAME_free(WOLFSSL_X509_NAME* name); +WOLFSSL_API char wolfSSL_CTX_use_certificate(WOLFSSL_CTX *ctx, WOLFSSL_X509 *x); +WOLFSSL_API int wolfSSL_BIO_read_filename(WOLFSSL_BIO *b, const char *name); +/* These are to be merged shortly */ +WOLFSSL_API void wolfSSL_set_verify_depth(WOLFSSL *ssl,int depth); +WOLFSSL_API void* wolfSSL_get_app_data( const WOLFSSL *ssl); +WOLFSSL_API int wolfSSL_set_app_data(WOLFSSL *ssl, void *arg); +WOLFSSL_API WOLFSSL_ASN1_OBJECT * wolfSSL_X509_NAME_ENTRY_get_object(WOLFSSL_X509_NAME_ENTRY *ne); +WOLFSSL_API WOLFSSL_X509_NAME_ENTRY *wolfSSL_X509_NAME_get_entry(WOLFSSL_X509_NAME *name, int loc); +WOLFSSL_API void wolfSSL_sk_X509_NAME_pop_free(WOLF_STACK_OF(WOLFSSL_X509_NAME)* sk, void f (WOLFSSL_X509_NAME*)); +WOLFSSL_API unsigned char *wolfSSL_SHA1(const unsigned char *d, size_t n, unsigned char *md); +WOLFSSL_API unsigned char *wolfSSL_SHA256(const unsigned char *d, size_t n, unsigned char *md); +WOLFSSL_API unsigned char *wolfSSL_SHA384(const unsigned char *d, size_t n, unsigned char *md); +WOLFSSL_API unsigned char *wolfSSL_SHA512(const unsigned char *d, size_t n, unsigned char *md); +WOLFSSL_API int wolfSSL_X509_check_private_key(WOLFSSL_X509*, WOLFSSL_EVP_PKEY*); +WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509_NAME) *wolfSSL_dup_CA_list( WOLF_STACK_OF(WOLFSSL_X509_NAME) *sk ); +WOLFSSL_API int wolfSSL_X509_check_ca(WOLFSSL_X509 *x509); + +#ifndef NO_FILESYSTEM +WOLFSSL_API long wolfSSL_BIO_set_fp(WOLFSSL_BIO *bio, XFILE fp, int c); +WOLFSSL_API long wolfSSL_BIO_get_fp(WOLFSSL_BIO *bio, XFILE* fp); +#endif + +#endif /* OPENSSL_EXTRA || OPENSSL_ALL || HAVE_LIGHTY || WOLFSSL_MYSQL_COMPATIBLE || HAVE_STUNNEL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */ + +#endif /* OPENSSL_EXTRA || OPENSSL_ALL */ + + +#if defined(OPENSSL_ALL) \ + || defined(HAVE_STUNNEL) \ + || defined(HAVE_LIGHTY) \ + || defined(WOLFSSL_MYSQL_COMPATIBLE) \ + || defined(WOLFSSL_HAPROXY) \ + || defined(OPENSSL_EXTRA) + +WOLFSSL_API WOLFSSL_BIO* wolfSSL_BIO_new_file(const char *filename, const char *mode); +WOLFSSL_API long wolfSSL_CTX_set_tmp_dh(WOLFSSL_CTX*, WOLFSSL_DH*); +WOLFSSL_API WOLFSSL_DH *wolfSSL_PEM_read_bio_DHparams(WOLFSSL_BIO *bp, + WOLFSSL_DH **x, pem_password_cb *cb, void *u); +WOLFSSL_API WOLFSSL_DSA *wolfSSL_PEM_read_bio_DSAparams(WOLFSSL_BIO *bp, + WOLFSSL_DSA **x, pem_password_cb *cb, void *u); +WOLFSSL_API int wolfSSL_PEM_write_bio_X509_REQ(WOLFSSL_BIO *bp,WOLFSSL_X509 *x); +WOLFSSL_API int wolfSSL_PEM_write_bio_X509_AUX(WOLFSSL_BIO *bp,WOLFSSL_X509 *x); +WOLFSSL_API int wolfSSL_PEM_write_bio_X509(WOLFSSL_BIO *bp, WOLFSSL_X509 *x); + +#endif /* HAVE_STUNNEL || HAVE_LIGHTY */ + +#ifdef OPENSSL_ALL +WOLFSSL_API int wolfSSL_i2d_X509_REQ(WOLFSSL_X509* req, unsigned char** out); +WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_REQ_new(void); +WOLFSSL_API void wolfSSL_X509_REQ_free(WOLFSSL_X509* req); +WOLFSSL_API int wolfSSL_X509_REQ_sign(WOLFSSL_X509 *req, WOLFSSL_EVP_PKEY *pkey, + const WOLFSSL_EVP_MD *md); +WOLFSSL_API int wolfSSL_X509_REQ_set_subject_name(WOLFSSL_X509 *req, + WOLFSSL_X509_NAME *name); +WOLFSSL_API int wolfSSL_X509_REQ_set_pubkey(WOLFSSL_X509 *req, + WOLFSSL_EVP_PKEY *pkey); +#endif + + +#if defined(OPENSSL_ALL) \ + || defined(HAVE_STUNNEL) \ + || defined(WOLFSSL_NGINX) \ + || defined(WOLFSSL_HAPROXY) \ + || defined(OPENSSL_EXTRA) \ + || defined(HAVE_LIGHTY) + +#include + +/* SNI received callback type */ +typedef int (*CallbackSniRecv)(WOLFSSL *ssl, int *ret, void* exArg); + +WOLFSSL_API int wolfSSL_CRYPTO_set_mem_ex_functions(void *(*m) (size_t, const char *, int), + void *(*r) (void *, size_t, const char *, int), void (*f) (void *)); + +WOLFSSL_API void wolfSSL_CRYPTO_cleanup_all_ex_data(void); + +WOLFSSL_API WOLFSSL_BIGNUM* wolfSSL_DH_1536_prime(WOLFSSL_BIGNUM* bn); +WOLFSSL_API WOLFSSL_DH *wolfSSL_DH_generate_parameters(int prime_len, int generator, + void (*callback) (int, int, void *), void *cb_arg); + +WOLFSSL_API int wolfSSL_DH_generate_parameters_ex(WOLFSSL_DH*, int, int, + void (*callback) (int, int, void *)); + +WOLFSSL_API void wolfSSL_ERR_load_crypto_strings(void); + +WOLFSSL_API unsigned long wolfSSL_ERR_peek_last_error(void); + +WOLFSSL_API int wolfSSL_FIPS_mode(void); + +WOLFSSL_API int wolfSSL_FIPS_mode_set(int r); + +WOLFSSL_API int wolfSSL_RAND_set_rand_method(const void *meth); + +WOLFSSL_API int wolfSSL_CIPHER_get_bits(const WOLFSSL_CIPHER *c, int *alg_bits); + +WOLFSSL_API int wolfSSL_sk_X509_NAME_num(const WOLF_STACK_OF(WOLFSSL_X509_NAME) *s); + +WOLFSSL_API WOLFSSL_STACK* wolfSSL_sk_X509_new(void); +WOLFSSL_API int wolfSSL_sk_X509_num(const WOLF_STACK_OF(WOLFSSL_X509) *s); + +WOLFSSL_API int wolfSSL_X509_NAME_print_ex(WOLFSSL_BIO*,WOLFSSL_X509_NAME*,int, + unsigned long); + +WOLFSSL_API WOLFSSL_ASN1_BIT_STRING* wolfSSL_X509_get0_pubkey_bitstr( + const WOLFSSL_X509*); + +WOLFSSL_API int wolfSSL_CTX_add_session(WOLFSSL_CTX*, WOLFSSL_SESSION*); + +WOLFSSL_API int wolfSSL_version(WOLFSSL*); + +WOLFSSL_API int wolfSSL_get_state(const WOLFSSL*); + +WOLFSSL_API void* wolfSSL_sk_X509_NAME_value(const WOLF_STACK_OF(WOLFSSL_X509_NAME)*, int); + +WOLFSSL_API void* wolfSSL_sk_X509_value(WOLF_STACK_OF(WOLFSSL_X509)*, int); + +WOLFSSL_API void* wolfSSL_SESSION_get_ex_data(const WOLFSSL_SESSION*, int); + +WOLFSSL_API int wolfSSL_SESSION_set_ex_data(WOLFSSL_SESSION*, int, void*); + +WOLFSSL_API int wolfSSL_SESSION_get_ex_new_index(long,void*,void*,void*, + CRYPTO_free_func*); + +WOLFSSL_API int wolfSSL_X509_NAME_get_sz(WOLFSSL_X509_NAME*); + + +WOLFSSL_API const unsigned char* wolfSSL_SESSION_get_id(WOLFSSL_SESSION*, + unsigned int*); + +WOLFSSL_API int wolfSSL_set_tlsext_host_name(WOLFSSL *, const char *); + +WOLFSSL_API const char* wolfSSL_get_servername(WOLFSSL *, unsigned char); + +WOLFSSL_API WOLFSSL_CTX* wolfSSL_set_SSL_CTX(WOLFSSL*,WOLFSSL_CTX*); + +WOLFSSL_API VerifyCallback wolfSSL_CTX_get_verify_callback(WOLFSSL_CTX*); + +WOLFSSL_API VerifyCallback wolfSSL_get_verify_callback(WOLFSSL*); + +WOLFSSL_API void wolfSSL_CTX_set_servername_callback(WOLFSSL_CTX *, + CallbackSniRecv); +WOLFSSL_API int wolfSSL_CTX_set_tlsext_servername_callback(WOLFSSL_CTX *, + CallbackSniRecv); + +WOLFSSL_API void wolfSSL_CTX_set_servername_arg(WOLFSSL_CTX *, void*); + +WOLFSSL_API void wolfSSL_ERR_remove_thread_state(void*); + +/* support for depricated old name */ +#define WOLFSSL_ERR_remove_thread_state wolfSSL_ERR_remove_thread_state + +#ifndef NO_FILESYSTEM +WOLFSSL_API void wolfSSL_print_all_errors_fp(XFILE fp); +#endif + +WOLFSSL_API void wolfSSL_THREADID_set_callback(void (*threadid_func)(void*)); + +WOLFSSL_API void wolfSSL_THREADID_set_numeric(void* id, unsigned long val); + +WOLFSSL_API WOLF_STACK_OF(WOLFSSL_X509)* wolfSSL_X509_STORE_get1_certs( + WOLFSSL_X509_STORE_CTX*, WOLFSSL_X509_NAME*); + +WOLFSSL_API void wolfSSL_sk_X509_pop_free(WOLF_STACK_OF(WOLFSSL_X509)* sk, void f (WOLFSSL_X509*)); +#endif /* OPENSSL_ALL || HAVE_STUNNEL || WOLFSSL_NGINX || WOLFSSL_HAPROXY || HAVE_LIGHTY */ + +#if defined(OPENSSL_ALL) || \ + defined(HAVE_STUNNEL) || defined(WOLFSSL_MYSQL_COMPATIBLE) || \ + defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + +WOLFSSL_API int wolfSSL_CTX_get_verify_mode(WOLFSSL_CTX* ctx); + +#endif + +#ifdef WOLFSSL_JNI +WOLFSSL_API int wolfSSL_set_jobject(WOLFSSL* ssl, void* objPtr); +WOLFSSL_API void* wolfSSL_get_jobject(WOLFSSL* ssl); +#endif /* WOLFSSL_JNI */ + + +#ifdef WOLFSSL_ASYNC_CRYPT +WOLFSSL_API int wolfSSL_AsyncPoll(WOLFSSL* ssl, WOLF_EVENT_FLAG flags); +WOLFSSL_API int wolfSSL_CTX_AsyncPoll(WOLFSSL_CTX* ctx, WOLF_EVENT** events, int maxEvents, + WOLF_EVENT_FLAG flags, int* eventCount); +#endif /* WOLFSSL_ASYNC_CRYPT */ + +#ifdef OPENSSL_EXTRA +WOLFSSL_API int wolfSSL_CTX_set1_curves_list(WOLFSSL_CTX* ctx, char* names); + +typedef void (*SSL_Msg_Cb)(int write_p, int version, int content_type, + const void *buf, size_t len, WOLFSSL *ssl, void *arg); + +WOLFSSL_API int wolfSSL_CTX_set_msg_callback(WOLFSSL_CTX *ctx, SSL_Msg_Cb cb); +WOLFSSL_API int wolfSSL_set_msg_callback(WOLFSSL *ssl, SSL_Msg_Cb cb); +WOLFSSL_API int wolfSSL_CTX_set_msg_callback_arg(WOLFSSL_CTX *ctx, void* arg); +WOLFSSL_API int wolfSSL_set_msg_callback_arg(WOLFSSL *ssl, void* arg); +WOLFSSL_API unsigned long wolfSSL_ERR_peek_error_line_data(const char **file, + int *line, const char **data, int *flags); +WOLFSSL_API int wolfSSL_CTX_set_alpn_protos(WOLFSSL_CTX *ctx, + const unsigned char *protos, unsigned int protos_len); +WOLFSSL_API void *wolfSSL_OPENSSL_memdup(const void *data, + size_t siz, const char* file, int line); +WOLFSSL_API void wolfSSL_ERR_load_BIO_strings(void); +#endif + +#if defined(OPENSSL_ALL) \ + || defined(WOLFSSL_NGINX) \ + || defined(WOLFSSL_HAPROXY) \ + || defined(OPENSSL_EXTRA) +WOLFSSL_API void wolfSSL_OPENSSL_config(char *config_name); +#endif + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) +/* Not an OpenSSL API. */ +WOLFSSL_LOCAL int wolfSSL_get_ocsp_response(WOLFSSL* ssl, byte** response); +/* Not an OpenSSL API. */ +WOLFSSL_LOCAL char* wolfSSL_get_ocsp_url(WOLFSSL* ssl); +/* Not an OpenSSL API. */ +WOLFSSL_API int wolfSSL_set_ocsp_url(WOLFSSL* ssl, char* url); +#endif + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) \ + || defined(OPENSSL_EXTRA) || defined(HAVE_LIGHTY) +WOLFSSL_API WOLF_STACK_OF(WOLFSSL_CIPHER) *wolfSSL_get_ciphers_compat(const WOLFSSL *ssl); +WOLFSSL_API int wolfSSL_X509_get_ex_new_index(int idx, void *arg, void *a, + void *b, void *c); +WOLFSSL_API void *wolfSSL_X509_get_ex_data(WOLFSSL_X509 *x509, int idx); +WOLFSSL_API int wolfSSL_X509_set_ex_data(WOLFSSL_X509 *x509, int idx, + void *data); + +WOLFSSL_API int wolfSSL_X509_NAME_digest(const WOLFSSL_X509_NAME *data, + const WOLFSSL_EVP_MD *type, unsigned char *md, unsigned int *len); + +WOLFSSL_API long wolfSSL_SSL_CTX_get_timeout(const WOLFSSL_CTX *ctx); +WOLFSSL_API long wolfSSL_get_timeout(WOLFSSL* ssl); +WOLFSSL_API int wolfSSL_SSL_CTX_set_tmp_ecdh(WOLFSSL_CTX *ctx, + WOLFSSL_EC_KEY *ecdh); +WOLFSSL_API int wolfSSL_SSL_CTX_remove_session(WOLFSSL_CTX *, + WOLFSSL_SESSION *c); + +WOLFSSL_API WOLFSSL_BIO *wolfSSL_SSL_get_rbio(const WOLFSSL *s); +WOLFSSL_API WOLFSSL_BIO *wolfSSL_SSL_get_wbio(const WOLFSSL *s); +WOLFSSL_API int wolfSSL_SSL_do_handshake(WOLFSSL *s); +WOLFSSL_API int wolfSSL_SSL_in_init(WOLFSSL *a); /* #define in OpenSSL */ +#ifndef NO_SESSION_CACHE + WOLFSSL_API WOLFSSL_SESSION *wolfSSL_SSL_get0_session(const WOLFSSL *s); +#endif +WOLFSSL_API int wolfSSL_X509_check_host(WOLFSSL_X509 *x, const char *chk, + size_t chklen, unsigned int flags, char **peername); + +WOLFSSL_API int wolfSSL_i2a_ASN1_INTEGER(WOLFSSL_BIO *bp, + const WOLFSSL_ASN1_INTEGER *a); + +#ifdef HAVE_SESSION_TICKET +WOLFSSL_API int wolfSSL_CTX_set_tlsext_ticket_key_cb(WOLFSSL_CTX *, int (*)( + WOLFSSL *ssl, unsigned char *name, unsigned char *iv, + WOLFSSL_EVP_CIPHER_CTX *ectx, WOLFSSL_HMAC_CTX *hctx, int enc)); +#endif + +#if defined(HAVE_OCSP) || defined(OPENSSL_EXTRA) || defined(OPENSSL_ALL) || \ + defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) +WOLFSSL_API int wolfSSL_CTX_get_extra_chain_certs(WOLFSSL_CTX* ctx, + WOLF_STACK_OF(X509)** chain); +WOLFSSL_API int wolfSSL_CTX_set_tlsext_status_cb(WOLFSSL_CTX* ctx, + int(*)(WOLFSSL*, void*)); + +WOLFSSL_API int wolfSSL_X509_STORE_CTX_get1_issuer(WOLFSSL_X509 **issuer, + WOLFSSL_X509_STORE_CTX *ctx, WOLFSSL_X509 *x); + +WOLFSSL_API void wolfSSL_X509_email_free(WOLF_STACK_OF(WOLFSSL_STRING) *sk); +WOLFSSL_API WOLF_STACK_OF(WOLFSSL_STRING) *wolfSSL_X509_get1_ocsp(WOLFSSL_X509 *x); + +WOLFSSL_API int wolfSSL_X509_check_issued(WOLFSSL_X509 *issuer, + WOLFSSL_X509 *subject); + +WOLFSSL_API WOLFSSL_X509* wolfSSL_X509_dup(WOLFSSL_X509 *x); + +WOLFSSL_API char* wolfSSL_sk_WOLFSSL_STRING_value( + WOLF_STACK_OF(WOLFSSL_STRING)* strings, int idx); +#endif /* HAVE_OCSP */ + +WOLFSSL_API int PEM_write_bio_WOLFSSL_X509(WOLFSSL_BIO *bio, + WOLFSSL_X509 *cert); + +#endif /* OPENSSL_ALL || WOLFSSL_NGINX || WOLFSSL_HAPROXY || + OPENSSL_EXTRA || HAVE_LIGHTY*/ + +WOLFSSL_API void wolfSSL_get0_alpn_selected(const WOLFSSL *ssl, + const unsigned char **data, unsigned int *len); +WOLFSSL_API int wolfSSL_select_next_proto(unsigned char **out, + unsigned char *outlen, + const unsigned char *in, unsigned int inlen, + const unsigned char *client, + unsigned int client_len); +WOLFSSL_API void wolfSSL_CTX_set_alpn_select_cb(WOLFSSL_CTX *ctx, + int (*cb) (WOLFSSL *ssl, + const unsigned char **out, + unsigned char *outlen, + const unsigned char *in, + unsigned int inlen, + void *arg), void *arg); +WOLFSSL_API void wolfSSL_CTX_set_next_protos_advertised_cb(WOLFSSL_CTX *s, + int (*cb) (WOLFSSL *ssl, + const unsigned char **out, + unsigned int *outlen, + void *arg), void *arg); +WOLFSSL_API void wolfSSL_CTX_set_next_proto_select_cb(WOLFSSL_CTX *s, + int (*cb) (WOLFSSL *ssl, + unsigned char **out, + unsigned char *outlen, + const unsigned char *in, + unsigned int inlen, + void *arg), void *arg); +WOLFSSL_API void wolfSSL_get0_next_proto_negotiated(const WOLFSSL *s, const unsigned char **data, + unsigned *len); + + +#ifdef OPENSSL_EXTRA +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) +WOLFSSL_API const unsigned char *SSL_SESSION_get0_id_context( + const WOLFSSL_SESSION *sess, unsigned int *sid_ctx_length); +WOLFSSL_API size_t SSL_get_finished(const WOLFSSL *s, void *buf, size_t count); +WOLFSSL_API size_t SSL_get_peer_finished(const WOLFSSL *s, void *buf, size_t count); +#endif + +WOLFSSL_API int SSL_SESSION_set1_id(WOLFSSL_SESSION *s, const unsigned char *sid, unsigned int sid_len); +WOLFSSL_API int SSL_SESSION_set1_id_context(WOLFSSL_SESSION *s, const unsigned char *sid_ctx, unsigned int sid_ctx_len); +WOLFSSL_API void *X509_get0_tbs_sigalg(const WOLFSSL_X509 *x); +WOLFSSL_API void X509_ALGOR_get0(WOLFSSL_ASN1_OBJECT **paobj, int *pptype, const void **ppval, const void *algor); +WOLFSSL_API void *X509_get_X509_PUBKEY(void * x); +WOLFSSL_API int X509_PUBKEY_get0_param(WOLFSSL_ASN1_OBJECT **ppkalg, const unsigned char **pk, int *ppklen, void **pa, WOLFSSL_EVP_PKEY *pub); +WOLFSSL_API int i2t_ASN1_OBJECT(char *buf, int buf_len, WOLFSSL_ASN1_OBJECT *a); +WOLFSSL_API void SSL_CTX_set_tmp_dh_callback(WOLFSSL_CTX *ctx, WOLFSSL_DH *(*dh) (WOLFSSL *ssl, int is_export, int keylength)); +WOLFSSL_API WOLF_STACK_OF(SSL_COMP) *SSL_COMP_get_compression_methods(void); +WOLFSSL_API int X509_STORE_load_locations(WOLFSSL_X509_STORE *ctx, const char *file, const char *dir); +WOLFSSL_API int wolfSSL_X509_STORE_add_crl(WOLFSSL_X509_STORE *ctx, WOLFSSL_X509_CRL *x); +WOLFSSL_API int wolfSSL_sk_SSL_CIPHER_num(const void * p); +WOLFSSL_API int wolfSSL_sk_SSL_COMP_zero(WOLFSSL_STACK* st); +WOLFSSL_API WOLFSSL_CIPHER* wolfSSL_sk_SSL_CIPHER_value(void *ciphers, int idx); +WOLFSSL_API void ERR_load_SSL_strings(void); +WOLFSSL_API void wolfSSL_EC_POINT_dump(const char *msg, const WOLFSSL_EC_POINT *p); + +WOLFSSL_API const char *wolfSSL_ASN1_tag2str(int tag); +WOLFSSL_API int wolfSSL_ASN1_STRING_print_ex(WOLFSSL_BIO *out, WOLFSSL_ASN1_STRING *str, unsigned long flags); +WOLFSSL_API int wolfSSL_ASN1_TIME_get_length(WOLFSSL_ASN1_TIME *t); +WOLFSSL_API unsigned char* wolfSSL_ASN1_TIME_get_data(WOLFSSL_ASN1_TIME *t); +WOLFSSL_API WOLFSSL_ASN1_TIME *wolfSSL_ASN1_TIME_to_generalizedtime(WOLFSSL_ASN1_TIME *t, + WOLFSSL_ASN1_TIME **out); +WOLFSSL_API int wolfSSL_i2c_ASN1_INTEGER(WOLFSSL_ASN1_INTEGER *a, unsigned char **pp); +WOLFSSL_API int wolfSSL_X509_CA_num(WOLFSSL_X509_STORE *store); +WOLFSSL_API long wolfSSL_X509_get_version(const WOLFSSL_X509 *x); +WOLFSSL_API int wolfSSL_X509_get_signature_nid(const WOLFSSL_X509* x); + +WOLFSSL_API int wolfSSL_PEM_write_bio_PKCS8PrivateKey(WOLFSSL_BIO* bio, + WOLFSSL_EVP_PKEY* pkey, const WOLFSSL_EVP_CIPHER* enc, char* passwd, + int passwdSz, pem_password_cb* cb, void* ctx); +WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_d2i_PKCS8PrivateKey_bio(WOLFSSL_BIO* bio, + WOLFSSL_EVP_PKEY** pkey, pem_password_cb* cb, void* u); +WOLFSSL_API WOLFSSL_EVP_PKEY* wolfSSL_d2i_AutoPrivateKey( + WOLFSSL_EVP_PKEY** pkey, const unsigned char** data, long length); + +#endif /* OPENSSL_EXTRA */ + +#ifdef HAVE_PK_CALLBACKS +WOLFSSL_API int wolfSSL_CTX_IsPrivatePkSet(WOLFSSL_CTX* ctx); +#endif + +#ifdef __cplusplus + } /* extern "C" */ +#endif + + +#endif /* WOLFSSL_SSL_H */ diff --git a/beken_os/beken378/func/wolfssl/wolfssl/test.h b/beken_os/beken378/func/wolfssl/wolfssl/test.h new file mode 100755 index 0000000..3cbdba8 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/test.h @@ -0,0 +1,3265 @@ +/* test.h */ + +#ifndef wolfSSL_TEST_H +#define wolfSSL_TEST_H + +#include +#include +#include +#include +#include +#include +#include +#include +#if defined(SHOW_CERTS) && \ + (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) + #include /* for domain component NID value */ +#endif + +#ifdef ATOMIC_USER + #include + #include + #include +#endif +#ifdef HAVE_PK_CALLBACKS + #include + #ifndef NO_RSA + #include + #endif + #ifdef HAVE_ECC + #include + #endif /* HAVE_ECC */ + #ifndef NO_DH + #include + #endif /* !NO_DH */ + #ifdef HAVE_ED25519 + #include + #endif /* HAVE_ED25519 */ + #ifdef HAVE_CURVE25519 + #include + #endif /* HAVE_ECC */ +#endif /*HAVE_PK_CALLBACKS */ + +#ifdef USE_WINDOWS_API + #include + #include + #ifdef TEST_IPV6 /* don't require newer SDK for IPV4 */ + #include + #include + #endif + #define SOCKET_T SOCKET + #define SNPRINTF _snprintf +#elif defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET) + #include + #include "rl_net.h" + #define SOCKET_T int + typedef int socklen_t ; + #define inet_addr wolfSSL_inet_addr + static unsigned long wolfSSL_inet_addr(const char *cp) + { + unsigned int a[4] ; unsigned long ret ; + sscanf(cp, "%d.%d.%d.%d", &a[0], &a[1], &a[2], &a[3]) ; + ret = ((a[3]<<24) + (a[2]<<16) + (a[1]<<8) + a[0]) ; + return(ret) ; + } + #if defined(HAVE_KEIL_RTX) + #define sleep(t) os_dly_wait(t/1000+1); + #elif defined(WOLFSSL_CMSIS_RTOS) || defined(WOLFSSL_CMSIS_RTOSv2) + #define sleep(t) osDelay(t/1000+1); + #endif +#elif defined(WOLFSSL_TIRTOS) + #include + #include + #include + #include + #include + #include + struct hostent { + char *h_name; /* official name of host */ + char **h_aliases; /* alias list */ + int h_addrtype; /* host address type */ + int h_length; /* length of address */ + char **h_addr_list; /* list of addresses from name server */ + }; + #define SOCKET_T int +#elif defined(WOLFSSL_VXWORKS) + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #define SOCKET_T int +#elif defined(WOLFSSL_ZEPHYR) + #include + #include + #include + #define SOCKET_T int + #define SOL_SOCKET 1 + #define SO_REUSEADDR 201 + #define WOLFSSL_USE_GETADDRINFO + + static unsigned long inet_addr(const char *cp) + { + unsigned int a[4]; unsigned long ret; + int i, j; + for (i=0, j=0; i<4; i++) { + a[i] = 0; + while (cp[j] != '.' && cp[j] != '\0') { + a[i] *= 10; + a[i] += cp[j] - '0'; + j++; + } + } + ret = ((a[3]<<24) + (a[2]<<16) + (a[1]<<8) + a[0]) ; + return(ret) ; + } +#else + #include + #include +#ifndef WOLFSSL_LEANPSK + #include + #include + #include + #include + #include + #include + #include + #include + #include + #include + #ifdef TEST_IPV6 + #include + #endif +#endif + #define SOCKET_T int + #ifndef SO_NOSIGPIPE + #include /* ignore SIGPIPE */ + #endif + #define SNPRINTF snprintf +#endif /* USE_WINDOWS_API */ + +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif +#ifdef HAVE_CAVIUM + #include +#endif +#ifdef _MSC_VER + /* disable conversion warning */ + /* 4996 warning to use MS extensions e.g., strcpy_s instead of strncpy */ + #pragma warning(disable:4244 4996) +#endif + +#ifndef WOLFSSL_CIPHER_LIST_MAX_SIZE + #define WOLFSSL_CIPHER_LIST_MAX_SIZE 4096 +#endif +/* Buffer for benchmark tests */ +#ifndef TEST_BUFFER_SIZE + #define TEST_BUFFER_SIZE 16384 +#endif + +#ifndef WOLFSSL_HAVE_MIN + #define WOLFSSL_HAVE_MIN + static WC_INLINE word32 min(word32 a, word32 b) + { + return a > b ? b : a; + } +#endif /* WOLFSSL_HAVE_MIN */ + +/* Socket Handling */ +#ifndef WOLFSSL_SOCKET_INVALID +#ifdef USE_WINDOWS_API + #define WOLFSSL_SOCKET_INVALID ((SOCKET_T)INVALID_SOCKET) +#elif defined(WOLFSSL_TIRTOS) + #define WOLFSSL_SOCKET_INVALID ((SOCKET_T)-1) +#else + #define WOLFSSL_SOCKET_INVALID (SOCKET_T)(0) +#endif +#endif /* WOLFSSL_SOCKET_INVALID */ + +#ifndef WOLFSSL_SOCKET_IS_INVALID +#if defined(USE_WINDOWS_API) || defined(WOLFSSL_TIRTOS) + #define WOLFSSL_SOCKET_IS_INVALID(s) ((SOCKET_T)(s) == WOLFSSL_SOCKET_INVALID) +#else + #define WOLFSSL_SOCKET_IS_INVALID(s) ((SOCKET_T)(s) < WOLFSSL_SOCKET_INVALID) +#endif +#endif /* WOLFSSL_SOCKET_IS_INVALID */ + +#if defined(__MACH__) || defined(USE_WINDOWS_API) + #ifndef _SOCKLEN_T + typedef int socklen_t; + #endif +#endif + + +/* HPUX doesn't use socklent_t for third parameter to accept, unless + _XOPEN_SOURCE_EXTENDED is defined */ +#if !defined(__hpux__) && !defined(WOLFSSL_MDK_ARM) && !defined(WOLFSSL_IAR_ARM)\ + && !defined(WOLFSSL_ROWLEY_ARM) && !defined(WOLFSSL_KEIL_TCP_NET) + typedef socklen_t* ACCEPT_THIRD_T; +#else + #if defined _XOPEN_SOURCE_EXTENDED + typedef socklen_t* ACCEPT_THIRD_T; + #else + typedef int* ACCEPT_THIRD_T; + #endif +#endif + + + +#ifdef SINGLE_THREADED + typedef unsigned int THREAD_RETURN; + typedef void* THREAD_TYPE; + #define WOLFSSL_THREAD +#else + #if defined(_POSIX_THREADS) && !defined(__MINGW32__) + typedef void* THREAD_RETURN; + typedef pthread_t THREAD_TYPE; + #define WOLFSSL_THREAD + #define INFINITE -1 + #define WAIT_OBJECT_0 0L + #elif defined(WOLFSSL_MDK_ARM)|| defined(WOLFSSL_KEIL_TCP_NET) + typedef unsigned int THREAD_RETURN; + typedef int THREAD_TYPE; + #define WOLFSSL_THREAD + #elif defined(WOLFSSL_TIRTOS) + typedef void THREAD_RETURN; + typedef Task_Handle THREAD_TYPE; + #define WOLFSSL_THREAD + #elif defined(WOLFSSL_ZEPHYR) + typedef void THREAD_RETURN; + typedef struct k_thread THREAD_TYPE; + #define WOLFSSL_THREAD + #else + typedef unsigned int THREAD_RETURN; + typedef intptr_t THREAD_TYPE; + #define WOLFSSL_THREAD __stdcall + #endif +#endif + + +#ifdef TEST_IPV6 + typedef struct sockaddr_in6 SOCKADDR_IN_T; + #define AF_INET_V AF_INET6 +#else + typedef struct sockaddr_in SOCKADDR_IN_T; + #define AF_INET_V AF_INET +#endif + + +#ifndef WOLFSSL_NO_TLS12 +#define SERVER_DEFAULT_VERSION 3 +#else +#define SERVER_DEFAULT_VERSION 4 +#endif +#define SERVER_DTLS_DEFAULT_VERSION (-2) +#define SERVER_INVALID_VERSION (-99) +#define SERVER_DOWNGRADE_VERSION (-98) +#ifndef WOLFSSL_NO_TLS12 +#define CLIENT_DEFAULT_VERSION 3 +#else +#define CLIENT_DEFAULT_VERSION 4 +#endif +#define CLIENT_DTLS_DEFAULT_VERSION (-2) +#define CLIENT_INVALID_VERSION (-99) +#define CLIENT_DOWNGRADE_VERSION (-98) +#define EITHER_DOWNGRADE_VERSION (-97) +#if !defined(NO_FILESYSTEM) && defined(WOLFSSL_MAX_STRENGTH) + #define DEFAULT_MIN_DHKEY_BITS 2048 + #define DEFAULT_MAX_DHKEY_BITS 3072 +#else + #define DEFAULT_MIN_DHKEY_BITS 1024 + #define DEFAULT_MAX_DHKEY_BITS 2048 +#endif +#if !defined(NO_FILESYSTEM) && defined(WOLFSSL_MAX_STRENGTH) + #define DEFAULT_MIN_RSAKEY_BITS 2048 +#else + #define DEFAULT_MIN_RSAKEY_BITS 1024 +#endif +#if !defined(NO_FILESYSTEM) && defined(WOLFSSL_MAX_STRENGTH) + #define DEFAULT_MIN_ECCKEY_BITS 256 +#else + #define DEFAULT_MIN_ECCKEY_BITS 224 +#endif + +/* all certs relative to wolfSSL home directory now */ +#if defined(WOLFSSL_NO_CURRDIR) || defined(WOLFSSL_MDK_SHELL) +#define caCertFile "certs/ca-cert.pem" +#define eccCertFile "certs/server-ecc.pem" +#define eccKeyFile "certs/ecc-key.pem" +#define eccRsaCertFile "certs/server-ecc-rsa.pem" +#define svrCertFile "certs/server-cert.pem" +#define svrKeyFile "certs/server-key.pem" +#define cliCertFile "certs/client-cert.pem" +#define cliCertDerFile "certs/client-cert.der" +#define cliKeyFile "certs/client-key.pem" +#define ntruCertFile "certs/ntru-cert.pem" +#define ntruKeyFile "certs/ntru-key.raw" +#define dhParamFile "certs/dh2048.pem" +#define cliEccKeyFile "certs/ecc-client-key.pem" +#define cliEccCertFile "certs/client-ecc-cert.pem" +#define caEccCertFile "certs/ca-ecc-cert.pem" +#define crlPemDir "certs/crl" +#define edCertFile "certs/ed25519/server-ed25519-cert.pem" +#define edKeyFile "certs/ed25519/server-ed25519-priv.pem" +#define cliEdCertFile "certs/ed25519/client-ed25519.pem" +#define cliEdKeyFile "certs/ed25519/client-ed25519-priv.pem" +#define caEdCertFile "certs/ed25519/ca-ed25519.pem" +#ifdef HAVE_WNR + /* Whitewood netRandom default config file */ + #define wnrConfig "wnr-example.conf" +#endif +#else +#define caCertFile "./certs/ca-cert.pem" +#define eccCertFile "./certs/server-ecc.pem" +#define eccKeyFile "./certs/ecc-key.pem" +#define eccRsaCertFile "./certs/server-ecc-rsa.pem" +#define svrCertFile "./certs/server-cert.pem" +#define svrKeyFile "./certs/server-key.pem" +#define cliCertFile "./certs/client-cert.pem" +#define cliCertDerFile "./certs/client-cert.der" +#define cliKeyFile "./certs/client-key.pem" +#define ntruCertFile "./certs/ntru-cert.pem" +#define ntruKeyFile "./certs/ntru-key.raw" +#define dhParamFile "./certs/dh2048.pem" +#define cliEccKeyFile "./certs/ecc-client-key.pem" +#define cliEccCertFile "./certs/client-ecc-cert.pem" +#define caEccCertFile "./certs/ca-ecc-cert.pem" +#define crlPemDir "./certs/crl" +#define edCertFile "./certs/ed25519/server-ed25519-cert.pem" +#define edKeyFile "./certs/ed25519/server-ed25519-priv.pem" +#define cliEdCertFile "./certs/ed25519/client-ed25519.pem" +#define cliEdKeyFile "./certs/ed25519/client-ed25519-priv.pem" +#define caEdCertFile "./certs/ed25519/ca-ed25519.pem" +#ifdef HAVE_WNR + /* Whitewood netRandom default config file */ + #define wnrConfig "./wnr-example.conf" +#endif +#endif + +typedef struct tcp_ready { + word16 ready; /* predicate */ + word16 port; + char* srfName; /* server ready file name */ +#if defined(_POSIX_THREADS) && !defined(__MINGW32__) + pthread_mutex_t mutex; + pthread_cond_t cond; +#endif +} tcp_ready; + + +static WC_INLINE void InitTcpReady(tcp_ready* ready) +{ + ready->ready = 0; + ready->port = 0; + ready->srfName = NULL; +#ifdef SINGLE_THREADED +#elif defined(_POSIX_THREADS) && !defined(__MINGW32__) + pthread_mutex_init(&ready->mutex, 0); + pthread_cond_init(&ready->cond, 0); +#endif +} + + +static WC_INLINE void FreeTcpReady(tcp_ready* ready) +{ +#ifdef SINGLE_THREADED + (void)ready; +#elif defined(_POSIX_THREADS) && !defined(__MINGW32__) + pthread_mutex_destroy(&ready->mutex); + pthread_cond_destroy(&ready->cond); +#else + (void)ready; +#endif +} + +typedef WOLFSSL_METHOD* (*method_provider)(void); +typedef void (*ctx_callback)(WOLFSSL_CTX* ctx); +typedef void (*ssl_callback)(WOLFSSL* ssl); + +typedef struct callback_functions { + method_provider method; + ctx_callback ctx_ready; + ssl_callback ssl_ready; + ssl_callback on_result; + WOLFSSL_CTX* ctx; +} callback_functions; + +typedef struct func_args { + int argc; + char** argv; + int return_code; + tcp_ready* signal; + callback_functions *callbacks; +} func_args; + + + + +void wait_tcp_ready(func_args*); + +#ifdef WOLFSSL_ZEPHYR +typedef void THREAD_FUNC(void*, void*, void*); +#else +typedef THREAD_RETURN WOLFSSL_THREAD THREAD_FUNC(void*); +#endif + +void start_thread(THREAD_FUNC, func_args*, THREAD_TYPE*); +void join_thread(THREAD_TYPE); + +/* wolfSSL */ +#ifndef TEST_IPV6 + static const char* const wolfSSLIP = "127.0.0.1"; +#else + static const char* const wolfSSLIP = "::1"; +#endif +static const word16 wolfSSLPort = 11111; + + + +#ifndef MY_EX_USAGE +#define MY_EX_USAGE 2 +#endif + +#ifndef EXIT_FAILURE +#define EXIT_FAILURE 1 +#endif + +#if defined(WOLFSSL_FORCE_MALLOC_FAIL_TEST) || defined(WOLFSSL_ZEPHYR) + #ifndef EXIT_SUCCESS + #define EXIT_SUCCESS 0 + #endif + #define XEXIT(rc) return rc + #define XEXIT_T(rc) return (THREAD_RETURN)rc +#else + #define XEXIT(rc) exit((int)(rc)) + #define XEXIT_T(rc) exit((int)(rc)) +#endif + + +static WC_INLINE +#if defined(WOLFSSL_FORCE_MALLOC_FAIL_TEST) || defined(WOLFSSL_ZEPHYR) +THREAD_RETURN +#else +WC_NORETURN void +#endif +err_sys(const char* msg) +{ + printf("wolfSSL error: %s\n", msg); + +#if !defined(__GNUC__) + /* scan-build (which pretends to be gnuc) can get confused and think the + * msg pointer can be null even when hardcoded and then it won't exit, + * making null pointer checks above the err_sys() call useless. + * We could just always exit() but some compilers will complain about no + * possible return, with gcc we know the attribute to handle that with + * WC_NORETURN. */ + if (msg) +#endif + { + XEXIT_T(EXIT_FAILURE); + } +} + + +extern int myoptind; +extern char* myoptarg; + +static WC_INLINE int mygetopt(int argc, char** argv, const char* optstring) +{ + static char* next = NULL; + + char c; + char* cp; + + if (myoptind == 0) + next = NULL; /* we're starting new/over */ + + if (next == NULL || *next == '\0') { + if (myoptind == 0) + myoptind++; + + if (myoptind >= argc || argv[myoptind][0] != '-' || + argv[myoptind][1] == '\0') { + myoptarg = NULL; + if (myoptind < argc) + myoptarg = argv[myoptind]; + + return -1; + } + + if (strcmp(argv[myoptind], "--") == 0) { + myoptind++; + myoptarg = NULL; + + if (myoptind < argc) + myoptarg = argv[myoptind]; + + return -1; + } + + next = argv[myoptind]; + next++; /* skip - */ + myoptind++; + } + + c = *next++; + /* The C++ strchr can return a different value */ + cp = (char*)strchr(optstring, c); + + if (cp == NULL || c == ':') + return '?'; + + cp++; + + if (*cp == ':') { + if (*next != '\0') { + myoptarg = next; + next = NULL; + } + else if (myoptind < argc) { + myoptarg = argv[myoptind]; + myoptind++; + } + else + return '?'; + } + + return c; +} + + +#ifdef WOLFSSL_ENCRYPTED_KEYS + +static WC_INLINE int PasswordCallBack(char* passwd, int sz, int rw, void* userdata) +{ + (void)rw; + (void)userdata; + if (userdata != NULL) { + strncpy(passwd, (char*)userdata, sz); + return (int)XSTRLEN((char*)userdata); + } + else { + strncpy(passwd, "yassl123", sz); + return 8; + } +} + +#endif + +static const char* client_showpeer_msg[][8] = { + /* English */ + { + "SSL version is", + "SSL cipher suite is", + "SSL curve name is", + "SSL DH size is", + "SSL reused session", + "Alternate cert chain used", + "peer's cert info:", + NULL + }, +#ifndef NO_MULTIBYTE_PRINT + /* Japanese */ + { + "SSL バージョンは", + "SSL 暗号スイートは", + "SSL 曲線名は", + "SSL DH サイズは", + "SSL 再利用セッション", + "代替証明チェーンを使用", + "相手方証明書情報", + NULL + }, +#endif +}; + +#if defined(KEEP_PEER_CERT) || defined(KEEP_OUR_CERT) || defined(SESSION_CERTS) +static const char* client_showx509_msg[][5] = { + /* English */ + { + "issuer", + "subject", + "altname", + "serial number", + NULL + }, +#ifndef NO_MULTIBYTE_PRINT + /* Japanese */ + { + "発行者", + "サブジェクト", + "代替名", + "シリアル番号", + NULL + }, +#endif +}; + +/* lng_index is to specify the language for displaying message. */ +/* 0:English, 1:Japanese */ +static WC_INLINE void ShowX509Ex(WOLFSSL_X509* x509, const char* hdr, + int lng_index) +{ + char* altName; + char* issuer; + char* subject; + byte serial[32]; + int ret; + int sz = sizeof(serial); + const char** words = client_showx509_msg[lng_index]; + + if (x509 == NULL) { + printf("%s No Cert\n", hdr); + return; + } + + issuer = wolfSSL_X509_NAME_oneline( + wolfSSL_X509_get_issuer_name(x509), 0, 0); + subject = wolfSSL_X509_NAME_oneline( + wolfSSL_X509_get_subject_name(x509), 0, 0); + + printf("%s\n %s : %s\n %s: %s\n", hdr, words[0], issuer, words[1], subject); + + while ( (altName = wolfSSL_X509_get_next_altname(x509)) != NULL) + printf(" %s = %s\n", words[2], altName); + + ret = wolfSSL_X509_get_serial_number(x509, serial, &sz); + if (ret == WOLFSSL_SUCCESS) { + int i; + int strLen; + char serialMsg[80]; + + /* testsuite has multiple threads writing to stdout, get output + message ready to write once */ + strLen = sprintf(serialMsg, " %s", words[3]); + for (i = 0; i < sz; i++) + sprintf(serialMsg + strLen + (i*3), ":%02x ", serial[i]); + printf("%s\n", serialMsg); + } + + XFREE(subject, 0, DYNAMIC_TYPE_OPENSSL); + XFREE(issuer, 0, DYNAMIC_TYPE_OPENSSL); + +#if defined(SHOW_CERTS) && defined(OPENSSL_EXTRA) + { + WOLFSSL_BIO* bio; + char buf[256]; /* should be size of ASN_NAME_MAX */ + int textSz; + + /* print out domain component if certificate has it */ + textSz = wolfSSL_X509_NAME_get_text_by_NID( + wolfSSL_X509_get_subject_name(x509), NID_domainComponent, + buf, sizeof(buf)); + if (textSz > 0) { + printf("Domain Component = %s\n", buf); + } + + bio = wolfSSL_BIO_new(wolfSSL_BIO_s_file()); + if (bio != NULL) { + wolfSSL_BIO_set_fp(bio, stdout, BIO_NOCLOSE); + wolfSSL_X509_print(bio, x509); + wolfSSL_BIO_free(bio); + } + } +#endif /* SHOW_CERTS && OPENSSL_EXTRA */ +} +/* original ShowX509 to maintain compatibility */ +static WC_INLINE void ShowX509(WOLFSSL_X509* x509, const char* hdr) +{ + ShowX509Ex(x509, hdr, 0); +} + +#endif /* KEEP_PEER_CERT || KEEP_OUR_CERT || SESSION_CERTS */ + +#if defined(SHOW_CERTS) && defined(SESSION_CERTS) && \ + (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) +static WC_INLINE void ShowX509Chain(WOLFSSL_X509_CHAIN* chain, int count, + const char* hdr) +{ + int i; + int length; + unsigned char buffer[3072]; + WOLFSSL_X509* chainX509; + + for (i = 0; i < count; i++) { + wolfSSL_get_chain_cert_pem(chain, i, buffer, sizeof(buffer), &length); + buffer[length] = 0; + printf("\n%s: %d has length %d data = \n%s\n", hdr, i, length, buffer); + + chainX509 = wolfSSL_get_chain_X509(chain, i); + if (chainX509) + ShowX509(chainX509, hdr); + else + printf("get_chain_X509 failed\n"); + wolfSSL_FreeX509(chainX509); + } +} +#endif /* SHOW_CERTS && SESSION_CERTS */ + +/* lng_index is to specify the language for displaying message. */ +/* 0:English, 1:Japanese */ +static WC_INLINE void showPeerEx(WOLFSSL* ssl, int lng_index) +{ + WOLFSSL_CIPHER* cipher; + const char** words = client_showpeer_msg[lng_index]; + +#if defined(HAVE_ECC) || !defined(NO_DH) + const char *name; +#endif +#ifndef NO_DH + int bits; +#endif +#ifdef KEEP_PEER_CERT + WOLFSSL_X509* peer = wolfSSL_get_peer_certificate(ssl); + if (peer) + ShowX509Ex(peer, words[6], lng_index); + else + printf("peer has no cert!\n"); + wolfSSL_FreeX509(peer); +#endif +#if defined(SHOW_CERTS) && defined(KEEP_OUR_CERT) && \ + (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) + ShowX509(wolfSSL_get_certificate(ssl), "our cert info:"); + printf("Peer verify result = %lu\n", wolfSSL_get_verify_result(ssl)); +#endif /* SHOW_CERTS && KEEP_OUR_CERT */ + printf("%s %s\n", words[0], wolfSSL_get_version(ssl)); + + cipher = wolfSSL_get_current_cipher(ssl); +#ifdef HAVE_QSH + printf("%s %s%s\n", words[1], (wolfSSL_isQSH(ssl))? "QSH:": "", + wolfSSL_CIPHER_get_name(cipher)); +#else + printf("%s %s\n", words[1], wolfSSL_CIPHER_get_name(cipher)); +#endif +#if defined(HAVE_ECC) || !defined(NO_DH) + if ((name = wolfSSL_get_curve_name(ssl)) != NULL) + printf("%s %s\n", words[2], name); +#endif +#ifndef NO_DH + else if ((bits = wolfSSL_GetDhKey_Sz(ssl)) > 0) + printf("%s %d bits\n", words[3], bits); +#endif + if (wolfSSL_session_reused(ssl)) + printf("%s\n", words[4]); +#ifdef WOLFSSL_ALT_CERT_CHAINS + if (wolfSSL_is_peer_alt_cert_chain(ssl)) + printf("%s\n", words[5]); +#endif + +#if defined(SHOW_CERTS) && defined(SESSION_CERTS) && \ + (defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL)) + { + WOLFSSL_X509_CHAIN* chain; + + chain = wolfSSL_get_peer_chain(ssl); + ShowX509Chain(chain, wolfSSL_get_chain_count(chain), "session cert"); + + #ifdef WOLFSSL_ALT_CERT_CHAINS + if (wolfSSL_is_peer_alt_cert_chain(ssl)) { + chain = wolfSSL_get_peer_alt_chain(ssl); + ShowX509Chain(chain, wolfSSL_get_chain_count(chain), "alt cert"); + } + #endif + } +#endif /* SHOW_CERTS && SESSION_CERTS */ + (void)ssl; +} +/* original showPeer to maintain compatibility */ +static WC_INLINE void showPeer(WOLFSSL* ssl) +{ + showPeerEx(ssl, 0); +} + +static WC_INLINE void build_addr(SOCKADDR_IN_T* addr, const char* peer, + word16 port, int udp, int sctp) +{ + int useLookup = 0; + (void)useLookup; + (void)udp; + (void)sctp; + + if (addr == NULL) + err_sys("invalid argument to build_addr, addr is NULL"); + + XMEMSET(addr, 0, sizeof(SOCKADDR_IN_T)); + +#ifndef TEST_IPV6 + /* peer could be in human readable form */ + if ( ((size_t)peer != INADDR_ANY) && isalpha((int)peer[0])) { + #ifndef WOLFSSL_USE_GETADDRINFO + #if defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET) + int err; + struct hostent* entry = gethostbyname(peer, &err); + #elif defined(WOLFSSL_TIRTOS) + struct hostent* entry = DNSGetHostByName(peer); + #elif defined(WOLFSSL_VXWORKS) + struct hostent* entry = (struct hostent*)hostGetByName((char*)peer); + #else + struct hostent* entry = gethostbyname(peer); + #endif + + if (entry) { + XMEMCPY(&addr->sin_addr.s_addr, entry->h_addr_list[0], + entry->h_length); + useLookup = 1; + } + #else + struct zsock_addrinfo hints, *addrInfo; + char portStr[6]; + XSNPRINTF(portStr, sizeof(portStr), "%d", port); + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = udp ? SOCK_DGRAM : SOCK_STREAM; + hints.ai_protocol = udp ? IPPROTO_UDP : IPPROTO_TCP; + if (getaddrinfo((char*)peer, portStr, &hints, &addrInfo) == 0) { + XMEMCPY(addr, addrInfo->ai_addr, sizeof(*addr)); + useLookup = 1; + } + #endif + else + err_sys("no entry for host"); + } +#endif + + +#ifndef TEST_IPV6 + #if defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET) + addr->sin_family = PF_INET; + #else + addr->sin_family = AF_INET_V; + #endif + addr->sin_port = XHTONS(port); + if ((size_t)peer == INADDR_ANY) + addr->sin_addr.s_addr = INADDR_ANY; + else { + if (!useLookup) + addr->sin_addr.s_addr = inet_addr(peer); + } +#else + addr->sin6_family = AF_INET_V; + addr->sin6_port = XHTONS(port); + if ((size_t)peer == INADDR_ANY) { + addr->sin6_addr = in6addr_any; + } + else { + #if defined(HAVE_GETADDRINFO) || defined(WOLF_C99) + struct addrinfo hints; + struct addrinfo* answer = NULL; + int ret; + char strPort[80]; + + XMEMSET(&hints, 0, sizeof(hints)); + + hints.ai_family = AF_INET_V; + if (udp) { + hints.ai_socktype = SOCK_DGRAM; + hints.ai_protocol = IPPROTO_UDP; + } + #ifdef WOLFSSL_SCTP + else if (sctp) { + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_SCTP; + } + #endif + else { + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + } + + SNPRINTF(strPort, sizeof(strPort), "%d", port); + strPort[79] = '\0'; + + ret = getaddrinfo(peer, strPort, &hints, &answer); + if (ret < 0 || answer == NULL) + err_sys("getaddrinfo failed"); + + XMEMCPY(addr, answer->ai_addr, answer->ai_addrlen); + freeaddrinfo(answer); + #else + printf("no ipv6 getaddrinfo, loopback only tests/examples\n"); + addr->sin6_addr = in6addr_loopback; + #endif + } +#endif +} + + +static WC_INLINE void tcp_socket(SOCKET_T* sockfd, int udp, int sctp) +{ + (void)sctp; + + if (udp) + *sockfd = socket(AF_INET_V, SOCK_DGRAM, IPPROTO_UDP); +#ifdef WOLFSSL_SCTP + else if (sctp) + *sockfd = socket(AF_INET_V, SOCK_STREAM, IPPROTO_SCTP); +#endif + else + *sockfd = socket(AF_INET_V, SOCK_STREAM, IPPROTO_TCP); + + if(WOLFSSL_SOCKET_IS_INVALID(*sockfd)) { + err_sys("socket failed\n"); + } + +#ifndef USE_WINDOWS_API +#ifdef SO_NOSIGPIPE + { + int on = 1; + socklen_t len = sizeof(on); + int res = setsockopt(*sockfd, SOL_SOCKET, SO_NOSIGPIPE, &on, len); + if (res < 0) + err_sys("setsockopt SO_NOSIGPIPE failed\n"); + } +#elif defined(WOLFSSL_MDK_ARM) || defined (WOLFSSL_TIRTOS) ||\ + defined(WOLFSSL_KEIL_TCP_NET) || defined(WOLFSSL_ZEPHYR) + /* nothing to define */ +#else /* no S_NOSIGPIPE */ + signal(SIGPIPE, SIG_IGN); +#endif /* S_NOSIGPIPE */ + +#if defined(TCP_NODELAY) + if (!udp && !sctp) + { + int on = 1; + socklen_t len = sizeof(on); + int res = setsockopt(*sockfd, IPPROTO_TCP, TCP_NODELAY, &on, len); + if (res < 0) + err_sys("setsockopt TCP_NODELAY failed\n"); + } +#endif +#endif /* USE_WINDOWS_API */ +} + +static WC_INLINE void tcp_connect(SOCKET_T* sockfd, const char* ip, word16 port, + int udp, int sctp, WOLFSSL* ssl) +{ + SOCKADDR_IN_T addr; + build_addr(&addr, ip, port, udp, sctp); + if (udp) { + wolfSSL_dtls_set_peer(ssl, &addr, sizeof(addr)); + } + tcp_socket(sockfd, udp, sctp); + + if (!udp) { + if (connect(*sockfd, (const struct sockaddr*)&addr, sizeof(addr)) != 0) + err_sys("tcp connect failed"); + } +} + + +static WC_INLINE void udp_connect(SOCKET_T* sockfd, void* addr, int addrSz) +{ + if (connect(*sockfd, (const struct sockaddr*)addr, addrSz) != 0) + err_sys("tcp connect failed"); +} + + +enum { + TEST_SELECT_FAIL, + TEST_TIMEOUT, + TEST_RECV_READY, + TEST_SEND_READY, + TEST_ERROR_READY +}; + + +#if !defined(WOLFSSL_MDK_ARM) && !defined(WOLFSSL_KEIL_TCP_NET) && \ + !defined(WOLFSSL_TIRTOS) +static WC_INLINE int tcp_select_ex(SOCKET_T socketfd, int to_sec, int rx) +{ + fd_set fds, errfds; + fd_set* recvfds = NULL; + fd_set* sendfds = NULL; + SOCKET_T nfds = socketfd + 1; +#if !defined(__INTEGRITY) + struct timeval timeout = {(to_sec > 0) ? to_sec : 0, 0}; +#else + struct timeval timeout; +#endif + int result; + + FD_ZERO(&fds); + FD_SET(socketfd, &fds); + FD_ZERO(&errfds); + FD_SET(socketfd, &errfds); + + if (rx) + recvfds = &fds; + else + sendfds = &fds; + +#if defined(__INTEGRITY) + timeout.tv_sec = (long long)(to_sec > 0) ? to_sec : 0, 0; +#endif + result = select(nfds, recvfds, sendfds, &errfds, &timeout); + + if (result == 0) + return TEST_TIMEOUT; + else if (result > 0) { + if (FD_ISSET(socketfd, &fds)) { + if (rx) + return TEST_RECV_READY; + else + return TEST_SEND_READY; + } + else if(FD_ISSET(socketfd, &errfds)) + return TEST_ERROR_READY; + } + + return TEST_SELECT_FAIL; +} + +static WC_INLINE int tcp_select(SOCKET_T socketfd, int to_sec) +{ + return tcp_select_ex(socketfd, to_sec, 1); +} + +static WC_INLINE int tcp_select_tx(SOCKET_T socketfd, int to_sec) +{ + return tcp_select_ex(socketfd, to_sec, 0); +} + +#elif defined(WOLFSSL_TIRTOS) || defined(WOLFSSL_KEIL_TCP_NET) +static WC_INLINE int tcp_select(SOCKET_T socketfd, int to_sec) +{ + return TEST_RECV_READY; +} +static WC_INLINE int tcp_select_tx(SOCKET_T socketfd, int to_sec) +{ + return TEST_SEND_READY; +} +#endif /* !WOLFSSL_MDK_ARM */ + + +static WC_INLINE void tcp_listen(SOCKET_T* sockfd, word16* port, int useAnyAddr, + int udp, int sctp) +{ + SOCKADDR_IN_T addr; + + /* don't use INADDR_ANY by default, firewall may block, make user switch + on */ + build_addr(&addr, (useAnyAddr ? INADDR_ANY : wolfSSLIP), *port, udp, sctp); + tcp_socket(sockfd, udp, sctp); + +#if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_MDK_ARM)\ + && !defined(WOLFSSL_KEIL_TCP_NET) && !defined(WOLFSSL_ZEPHYR) + { + int res, on = 1; + socklen_t len = sizeof(on); + res = setsockopt(*sockfd, SOL_SOCKET, SO_REUSEADDR, &on, len); + if (res < 0) + err_sys("setsockopt SO_REUSEADDR failed\n"); + } +#endif + + if (bind(*sockfd, (const struct sockaddr*)&addr, sizeof(addr)) != 0) + err_sys("tcp bind failed"); + if (!udp) { + #ifdef WOLFSSL_KEIL_TCP_NET + #define SOCK_LISTEN_MAX_QUEUE 1 + #else + #define SOCK_LISTEN_MAX_QUEUE 5 + #endif + if (listen(*sockfd, SOCK_LISTEN_MAX_QUEUE) != 0) + err_sys("tcp listen failed"); + } + #if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_TIRTOS) \ + && !defined(WOLFSSL_ZEPHYR) + if (*port == 0) { + socklen_t len = sizeof(addr); + if (getsockname(*sockfd, (struct sockaddr*)&addr, &len) == 0) { + #ifndef TEST_IPV6 + *port = XNTOHS(addr.sin_port); + #else + *port = XNTOHS(addr.sin6_port); + #endif + } + } + #endif +} + + +#if 0 +static WC_INLINE int udp_read_connect(SOCKET_T sockfd) +{ + SOCKADDR_IN_T cliaddr; + byte b[1500]; + int n; + socklen_t len = sizeof(cliaddr); + + n = (int)recvfrom(sockfd, (char*)b, sizeof(b), MSG_PEEK, + (struct sockaddr*)&cliaddr, &len); + if (n > 0) { + if (connect(sockfd, (const struct sockaddr*)&cliaddr, + sizeof(cliaddr)) != 0) + err_sys("udp connect failed"); + } + else + err_sys("recvfrom failed"); + + return sockfd; +} +#endif + +static WC_INLINE void udp_accept(SOCKET_T* sockfd, SOCKET_T* clientfd, + int useAnyAddr, word16 port, func_args* args) +{ + SOCKADDR_IN_T addr; + + (void)args; + build_addr(&addr, (useAnyAddr ? INADDR_ANY : wolfSSLIP), port, 1, 0); + tcp_socket(sockfd, 1, 0); + + +#if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_MDK_ARM) \ + && !defined(WOLFSSL_KEIL_TCP_NET) && !defined(WOLFSSL_ZEPHYR) + { + int res, on = 1; + socklen_t len = sizeof(on); + res = setsockopt(*sockfd, SOL_SOCKET, SO_REUSEADDR, &on, len); + if (res < 0) + err_sys("setsockopt SO_REUSEADDR failed\n"); + } +#endif + + if (bind(*sockfd, (const struct sockaddr*)&addr, sizeof(addr)) != 0) + err_sys("tcp bind failed"); + + #if (defined(NO_MAIN_DRIVER) && !defined(USE_WINDOWS_API)) && !defined(WOLFSSL_TIRTOS) + if (port == 0) { + socklen_t len = sizeof(addr); + if (getsockname(*sockfd, (struct sockaddr*)&addr, &len) == 0) { + #ifndef TEST_IPV6 + port = XNTOHS(addr.sin_port); + #else + port = XNTOHS(addr.sin6_port); + #endif + } + } + #endif + +#if defined(_POSIX_THREADS) && defined(NO_MAIN_DRIVER) && !defined(__MINGW32__) + /* signal ready to accept data */ + { + tcp_ready* ready = args->signal; + pthread_mutex_lock(&ready->mutex); + ready->ready = 1; + ready->port = port; + pthread_cond_signal(&ready->cond); + pthread_mutex_unlock(&ready->mutex); + } +#elif defined (WOLFSSL_TIRTOS) + /* Need mutex? */ + tcp_ready* ready = args->signal; + ready->ready = 1; + ready->port = port; +#endif + + *clientfd = *sockfd; +} + +static WC_INLINE void tcp_accept(SOCKET_T* sockfd, SOCKET_T* clientfd, + func_args* args, word16 port, int useAnyAddr, + int udp, int sctp, int ready_file, int do_listen) +{ + SOCKADDR_IN_T client; + socklen_t client_len = sizeof(client); + tcp_ready* ready = NULL; + + (void) ready; /* Account for case when "ready" is not used */ + + if (udp) { + udp_accept(sockfd, clientfd, useAnyAddr, port, args); + return; + } + + if(do_listen) { + tcp_listen(sockfd, &port, useAnyAddr, udp, sctp); + + #if defined(_POSIX_THREADS) && defined(NO_MAIN_DRIVER) && !defined(__MINGW32__) + /* signal ready to tcp_accept */ + if (args) + ready = args->signal; + if (ready) { + pthread_mutex_lock(&ready->mutex); + ready->ready = 1; + ready->port = port; + pthread_cond_signal(&ready->cond); + pthread_mutex_unlock(&ready->mutex); + } + #elif defined (WOLFSSL_TIRTOS) + /* Need mutex? */ + if (args) + ready = args->signal; + if (ready) { + ready->ready = 1; + ready->port = port; + } + #endif + + if (ready_file) { + #if !defined(NO_FILESYSTEM) || defined(FORCE_BUFFER_TEST) + XFILE srf = NULL; + if (args) + ready = args->signal; + + if (ready) { + srf = fopen(ready->srfName, "w"); + + if (srf) { + /* let's write port sever is listening on to ready file + external monitor can then do ephemeral ports by passing + -p 0 to server on supported platforms with -R ready_file + client can then wait for existence of ready_file and see + which port the server is listening on. */ + fprintf(srf, "%d\n", (int)port); + fclose(srf); + } + } + #endif + } + } + + *clientfd = accept(*sockfd, (struct sockaddr*)&client, + (ACCEPT_THIRD_T)&client_len); + if(WOLFSSL_SOCKET_IS_INVALID(*clientfd)) { + err_sys("tcp accept failed"); + } +} + + +static WC_INLINE void tcp_set_nonblocking(SOCKET_T* sockfd) +{ + #ifdef USE_WINDOWS_API + unsigned long blocking = 1; + int ret = ioctlsocket(*sockfd, FIONBIO, &blocking); + if (ret == SOCKET_ERROR) + err_sys("ioctlsocket failed"); + #elif defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET) \ + || defined (WOLFSSL_TIRTOS)|| defined(WOLFSSL_VXWORKS) \ + || defined(WOLFSSL_ZEPHYR) + /* non blocking not supported, for now */ + #else + int flags = fcntl(*sockfd, F_GETFL, 0); + if (flags < 0) + err_sys("fcntl get failed"); + flags = fcntl(*sockfd, F_SETFL, flags | O_NONBLOCK); + if (flags < 0) + err_sys("fcntl set failed"); + #endif +} + + +#ifndef NO_PSK + +/* identity is OpenSSL testing default for openssl s_client, keep same */ +static const char* kIdentityStr = "Client_identity"; + +static WC_INLINE unsigned int my_psk_client_cb(WOLFSSL* ssl, const char* hint, + char* identity, unsigned int id_max_len, unsigned char* key, + unsigned int key_max_len) +{ + (void)ssl; + (void)hint; + (void)key_max_len; + + /* see internal.h MAX_PSK_ID_LEN for PSK identity limit */ + strncpy(identity, kIdentityStr, id_max_len); + + if (wolfSSL_GetVersion(ssl) < WOLFSSL_TLSV1_3) { + /* test key in hex is 0x1a2b3c4d , in decimal 439,041,101 , we're using + unsigned binary */ + key[0] = 0x1a; + key[1] = 0x2b; + key[2] = 0x3c; + key[3] = 0x4d; + + return 4; /* length of key in octets or 0 for error */ + } + else { + int i; + int b = 0x01; + + for (i = 0; i < 32; i++, b += 0x22) { + if (b >= 0x100) + b = 0x01; + key[i] = b; + } + + return 32; /* length of key in octets or 0 for error */ + } +} + + +static WC_INLINE unsigned int my_psk_server_cb(WOLFSSL* ssl, const char* identity, + unsigned char* key, unsigned int key_max_len) +{ + (void)ssl; + (void)key_max_len; + + /* see internal.h MAX_PSK_ID_LEN for PSK identity limit */ + if (strncmp(identity, kIdentityStr, strlen(kIdentityStr)) != 0) + return 0; + + if (wolfSSL_GetVersion(ssl) < WOLFSSL_TLSV1_3) { + /* test key in hex is 0x1a2b3c4d , in decimal 439,041,101 , we're using + unsigned binary */ + key[0] = 0x1a; + key[1] = 0x2b; + key[2] = 0x3c; + key[3] = 0x4d; + + return 4; /* length of key in octets or 0 for error */ + } + else { + int i; + int b = 0x01; + + for (i = 0; i < 32; i++, b += 0x22) { + if (b >= 0x100) + b = 0x01; + key[i] = b; + } + + return 32; /* length of key in octets or 0 for error */ + } +} + + +static WC_INLINE unsigned int my_psk_client_tls13_cb(WOLFSSL* ssl, + const char* hint, char* identity, unsigned int id_max_len, + unsigned char* key, unsigned int key_max_len, const char** ciphersuite) +{ + int i; + int b = 0x01; + + (void)ssl; + (void)hint; + (void)key_max_len; + + /* see internal.h MAX_PSK_ID_LEN for PSK identity limit */ + strncpy(identity, kIdentityStr, id_max_len); + + for (i = 0; i < 32; i++, b += 0x22) { + if (b >= 0x100) + b = 0x01; + key[i] = b; + } + + *ciphersuite = "TLS13-AES128-GCM-SHA256"; + + return 32; /* length of key in octets or 0 for error */ +} + + +static WC_INLINE unsigned int my_psk_server_tls13_cb(WOLFSSL* ssl, + const char* identity, unsigned char* key, unsigned int key_max_len, + const char** ciphersuite) +{ + int i; + int b = 0x01; + + (void)ssl; + (void)key_max_len; + + /* see internal.h MAX_PSK_ID_LEN for PSK identity limit */ + if (strncmp(identity, kIdentityStr, strlen(kIdentityStr)) != 0) + return 0; + + for (i = 0; i < 32; i++, b += 0x22) { + if (b >= 0x100) + b = 0x01; + key[i] = b; + } + + *ciphersuite = "TLS13-AES128-GCM-SHA256"; + + return 32; /* length of key in octets or 0 for error */ +} + +#endif /* NO_PSK */ + + +#if defined(WOLFSSL_USER_CURRTIME) + extern double current_time(int reset); + +#elif defined(USE_WINDOWS_API) + + #define WIN32_LEAN_AND_MEAN + #include + + static WC_INLINE double current_time(int reset) + { + static int init = 0; + static LARGE_INTEGER freq; + + LARGE_INTEGER count; + + if (!init) { + QueryPerformanceFrequency(&freq); + init = 1; + } + + QueryPerformanceCounter(&count); + + (void)reset; + return (double)count.QuadPart / freq.QuadPart; + } + +#elif defined(WOLFSSL_TIRTOS) + extern double current_time(); +#elif defined(WOLFSSL_ZEPHYR) + extern double current_time(); +#else + +#if !defined(WOLFSSL_MDK_ARM) && !defined(WOLFSSL_KEIL_TCP_NET) && !defined(WOLFSSL_CHIBIOS) + #include + + static WC_INLINE double current_time(int reset) + { + struct timeval tv; + gettimeofday(&tv, 0); + (void)reset; + + return (double)tv.tv_sec + (double)tv.tv_usec / 1000000; + } +#else + extern double current_time(int reset); +#endif +#endif /* USE_WINDOWS_API */ + + +#if defined(HAVE_OCSP) && defined(WOLFSSL_NONBLOCK_OCSP) +static WC_INLINE int OCSPIOCb(void* ioCtx, const char* url, int urlSz, + unsigned char* request, int requestSz, unsigned char** response) +{ +#ifdef TEST_NONBLOCK_CERTS + static int ioCbCnt = 0; +#endif + + (void)ioCtx; + (void)url; + (void)urlSz; + (void)request; + (void)requestSz; + (void)response; + +#ifdef TEST_NONBLOCK_CERTS + if (ioCbCnt) { + ioCbCnt = 0; + return EmbedOcspLookup(ioCtx, url, urlSz, request, requestSz, response); + } + else { + ioCbCnt = 1; + return WOLFSSL_CBIO_ERR_WANT_READ; + } +#else + return EmbedOcspLookup(ioCtx, url, urlSz, request, requestSz, response); +#endif +} + +static WC_INLINE void OCSPRespFreeCb(void* ioCtx, unsigned char* response) +{ + (void)ioCtx; + (void)response; +} +#endif + +#if !defined(NO_CERTS) + #if !defined(NO_FILESYSTEM) || \ + (defined(NO_FILESYSTEM) && defined(FORCE_BUFFER_TEST)) + + /* reads file size, allocates buffer, reads into buffer, returns buffer */ + static WC_INLINE int load_file(const char* fname, byte** buf, size_t* bufLen) + { + int ret; + long int fileSz; + XFILE file; + + if (fname == NULL || buf == NULL || bufLen == NULL) + return BAD_FUNC_ARG; + + /* set defaults */ + *buf = NULL; + *bufLen = 0; + + /* open file (read-only binary) */ + file = fopen(fname, "rb"); + if (!file) { + printf("Error loading %s\n", fname); + return BAD_PATH_ERROR; + } + + fseek(file, 0, SEEK_END); + fileSz = (int)ftell(file); + rewind(file); + if (fileSz > 0) { + *bufLen = (size_t)fileSz; + *buf = (byte*)malloc(*bufLen); + if (*buf == NULL) { + ret = MEMORY_E; + printf("Error allocating %lu bytes\n", (unsigned long)*bufLen); + } + else { + size_t readLen = fread(*buf, *bufLen, 1, file); + + /* check response code */ + ret = (readLen > 0) ? 0 : -1; + } + } + else { + ret = BUFFER_E; + } + fclose(file); + + return ret; + } + + enum { + WOLFSSL_CA = 1, + WOLFSSL_CERT = 2, + WOLFSSL_KEY = 3, + WOLFSSL_CERT_CHAIN = 4, + }; + + static WC_INLINE void load_buffer(WOLFSSL_CTX* ctx, const char* fname, int type) + { + int format = WOLFSSL_FILETYPE_PEM; + byte* buff = NULL; + size_t sz = 0; + + if (load_file(fname, &buff, &sz) != 0) { + err_sys("can't open file for buffer load " + "Please run from wolfSSL home directory if not"); + } + + /* determine format */ + if (strstr(fname, ".der")) + format = WOLFSSL_FILETYPE_ASN1; + + if (type == WOLFSSL_CA) { + if (wolfSSL_CTX_load_verify_buffer(ctx, buff, (long)sz, format) + != WOLFSSL_SUCCESS) + err_sys("can't load buffer ca file"); + } + else if (type == WOLFSSL_CERT) { + if (wolfSSL_CTX_use_certificate_buffer(ctx, buff, (long)sz, + format) != WOLFSSL_SUCCESS) + err_sys("can't load buffer cert file"); + } + else if (type == WOLFSSL_KEY) { + if (wolfSSL_CTX_use_PrivateKey_buffer(ctx, buff, (long)sz, + format) != WOLFSSL_SUCCESS) + err_sys("can't load buffer key file"); + } + else if (type == WOLFSSL_CERT_CHAIN) { + if (wolfSSL_CTX_use_certificate_chain_buffer_format(ctx, buff, + (long)sz, format) != WOLFSSL_SUCCESS) + err_sys("can't load cert chain buffer"); + } + + if (buff) + free(buff); + } + + static WC_INLINE void load_ssl_buffer(WOLFSSL* ssl, const char* fname, int type) + { + int format = WOLFSSL_FILETYPE_PEM; + byte* buff = NULL; + size_t sz = 0; + + if (load_file(fname, &buff, &sz) != 0) { + err_sys("can't open file for buffer load " + "Please run from wolfSSL home directory if not"); + } + + /* determine format */ + if (strstr(fname, ".der")) + format = WOLFSSL_FILETYPE_ASN1; + + if (type == WOLFSSL_CA) { + /* verify certs (CA's) use the shared ctx->cm (WOLFSSL_CERT_MANAGER) */ + WOLFSSL_CTX* ctx = wolfSSL_get_SSL_CTX(ssl); + if (wolfSSL_CTX_load_verify_buffer(ctx, buff, (long)sz, format) + != WOLFSSL_SUCCESS) + err_sys("can't load buffer ca file"); + } + else if (type == WOLFSSL_CERT) { + if (wolfSSL_use_certificate_buffer(ssl, buff, (long)sz, + format) != WOLFSSL_SUCCESS) + err_sys("can't load buffer cert file"); + } + else if (type == WOLFSSL_KEY) { + if (wolfSSL_use_PrivateKey_buffer(ssl, buff, (long)sz, + format) != WOLFSSL_SUCCESS) + err_sys("can't load buffer key file"); + } + else if (type == WOLFSSL_CERT_CHAIN) { + if (wolfSSL_use_certificate_chain_buffer_format(ssl, buff, + (long)sz, format) != WOLFSSL_SUCCESS) + err_sys("can't load cert chain buffer"); + } + + if (buff) + free(buff); + } + + #ifdef TEST_PK_PRIVKEY + static WC_INLINE int load_key_file(const char* fname, byte** derBuf, word32* derLen) + { + int ret; + byte* buf = NULL; + size_t bufLen; + + ret = load_file(fname, &buf, &bufLen); + if (ret != 0) + return ret; + + *derBuf = (byte*)malloc(bufLen); + if (*derBuf == NULL) { + free(buf); + return MEMORY_E; + } + + ret = wc_KeyPemToDer(buf, (word32)bufLen, *derBuf, (word32)bufLen, NULL); + if (ret < 0) { + free(buf); + free(*derBuf); + return ret; + } + *derLen = ret; + free(buf); + + return 0; + } + #endif /* TEST_PK_PRIVKEY */ + + #endif /* !NO_FILESYSTEM || (NO_FILESYSTEM && FORCE_BUFFER_TEST) */ +#endif /* !NO_CERTS */ + +static int myVerifyFail = 0; +static WC_INLINE int myVerify(int preverify, WOLFSSL_X509_STORE_CTX* store) +{ + char buffer[WOLFSSL_MAX_ERROR_SZ]; +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + WOLFSSL_X509* peer; +#endif + (void)preverify; + + /* Verify Callback Arguments: + * preverify: 1=Verify Okay, 0=Failure + * store->error: Failure error code (0 indicates no failure) + * store->current_cert: Current WOLFSSL_X509 object (only with OPENSSL_EXTRA) + * store->error_depth: Current Index + * store->domain: Subject CN as string (null term) + * store->totalCerts: Number of certs presented by peer + * store->certs[i]: A `WOLFSSL_BUFFER_INFO` with plain DER for each cert + * store->store: WOLFSSL_X509_STORE with CA cert chain + * store->store->cm: WOLFSSL_CERT_MANAGER + * store->ex_data: The WOLFSSL object pointer + * store->discardSessionCerts: When set to non-zero value session certs + will be discarded (only with SESSION_CERTS) + */ + + printf("In verification callback, error = %d, %s\n", store->error, + wolfSSL_ERR_error_string(store->error, buffer)); +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + peer = store->current_cert; + if (peer) { + char* issuer = wolfSSL_X509_NAME_oneline( + wolfSSL_X509_get_issuer_name(peer), 0, 0); + char* subject = wolfSSL_X509_NAME_oneline( + wolfSSL_X509_get_subject_name(peer), 0, 0); + printf("\tPeer's cert info:\n issuer : %s\n subject: %s\n", issuer, + subject); + XFREE(subject, 0, DYNAMIC_TYPE_OPENSSL); + XFREE(issuer, 0, DYNAMIC_TYPE_OPENSSL); + } + else + printf("\tPeer has no cert!\n"); +#else + printf("\tPeer certs: %d\n", store->totalCerts); + #ifdef SHOW_CERTS + { int i; + for (i=0; itotalCerts; i++) { + WOLFSSL_BUFFER_INFO* cert = &store->certs[i]; + printf("\t\tCert %d: Ptr %p, Len %u\n", i, cert->buffer, cert->length); + } + } + #endif /* SHOW_CERTS */ +#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ + + printf("\tSubject's domain name at %d is %s\n", store->error_depth, store->domain); + + /* Testing forced fail case by return zero */ + if (myVerifyFail) { + return 0; /* test failure case */ + } + + /* If error indicate we are overriding it for testing purposes */ + if (store->error != 0) { + printf("\tAllowing failed certificate check, testing only " + "(shouldn't do this in production)\n"); + } + + /* A non-zero return code indicates failure override */ + return 1; +} + + +static WC_INLINE int myDateCb(int preverify, WOLFSSL_X509_STORE_CTX* store) +{ + char buffer[WOLFSSL_MAX_ERROR_SZ]; + (void)preverify; + + printf("In verification callback, error = %d, %s\n", store->error, + wolfSSL_ERR_error_string(store->error, buffer)); + printf("Subject's domain name is %s\n", store->domain); + + if (store->error == ASN_BEFORE_DATE_E || store->error == ASN_AFTER_DATE_E) { + printf("Overriding cert date error as example for bad clock testing\n"); + return 1; + } + printf("Cert error is not date error, not overriding\n"); + + return 0; +} + + +#ifdef HAVE_EXT_CACHE + +static WC_INLINE WOLFSSL_SESSION* mySessGetCb(WOLFSSL* ssl, unsigned char* id, + int id_len, int* copy) +{ + (void)ssl; + (void)id; + (void)id_len; + (void)copy; + + /* using internal cache, this is for testing only */ + return NULL; +} + +static WC_INLINE int mySessNewCb(WOLFSSL* ssl, WOLFSSL_SESSION* session) +{ + (void)ssl; + (void)session; + + /* using internal cache, this is for testing only */ + return 0; +} + +static WC_INLINE void mySessRemCb(WOLFSSL_CTX* ctx, WOLFSSL_SESSION* session) +{ + (void)ctx; + (void)session; + + /* using internal cache, this is for testing only */ +} + +#endif /* HAVE_EXT_CACHE */ + + +#ifdef HAVE_CRL + +static WC_INLINE void CRL_CallBack(const char* url) +{ + printf("CRL callback url = %s\n", url); +} + +#endif + +#ifndef NO_DH +static WC_INLINE void SetDH(WOLFSSL* ssl) +{ + /* dh1024 p */ + static const unsigned char p[] = + { + 0xE6, 0x96, 0x9D, 0x3D, 0x49, 0x5B, 0xE3, 0x2C, 0x7C, 0xF1, 0x80, 0xC3, + 0xBD, 0xD4, 0x79, 0x8E, 0x91, 0xB7, 0x81, 0x82, 0x51, 0xBB, 0x05, 0x5E, + 0x2A, 0x20, 0x64, 0x90, 0x4A, 0x79, 0xA7, 0x70, 0xFA, 0x15, 0xA2, 0x59, + 0xCB, 0xD5, 0x23, 0xA6, 0xA6, 0xEF, 0x09, 0xC4, 0x30, 0x48, 0xD5, 0xA2, + 0x2F, 0x97, 0x1F, 0x3C, 0x20, 0x12, 0x9B, 0x48, 0x00, 0x0E, 0x6E, 0xDD, + 0x06, 0x1C, 0xBC, 0x05, 0x3E, 0x37, 0x1D, 0x79, 0x4E, 0x53, 0x27, 0xDF, + 0x61, 0x1E, 0xBB, 0xBE, 0x1B, 0xAC, 0x9B, 0x5C, 0x60, 0x44, 0xCF, 0x02, + 0x3D, 0x76, 0xE0, 0x5E, 0xEA, 0x9B, 0xAD, 0x99, 0x1B, 0x13, 0xA6, 0x3C, + 0x97, 0x4E, 0x9E, 0xF1, 0x83, 0x9E, 0xB5, 0xDB, 0x12, 0x51, 0x36, 0xF7, + 0x26, 0x2E, 0x56, 0xA8, 0x87, 0x15, 0x38, 0xDF, 0xD8, 0x23, 0xC6, 0x50, + 0x50, 0x85, 0xE2, 0x1F, 0x0D, 0xD5, 0xC8, 0x6B, + }; + + /* dh1024 g */ + static const unsigned char g[] = + { + 0x02, + }; + + wolfSSL_SetTmpDH(ssl, p, sizeof(p), g, sizeof(g)); +} + +static WC_INLINE void SetDHCtx(WOLFSSL_CTX* ctx) +{ + /* dh1024 p */ + static const unsigned char p[] = + { + 0xE6, 0x96, 0x9D, 0x3D, 0x49, 0x5B, 0xE3, 0x2C, 0x7C, 0xF1, 0x80, 0xC3, + 0xBD, 0xD4, 0x79, 0x8E, 0x91, 0xB7, 0x81, 0x82, 0x51, 0xBB, 0x05, 0x5E, + 0x2A, 0x20, 0x64, 0x90, 0x4A, 0x79, 0xA7, 0x70, 0xFA, 0x15, 0xA2, 0x59, + 0xCB, 0xD5, 0x23, 0xA6, 0xA6, 0xEF, 0x09, 0xC4, 0x30, 0x48, 0xD5, 0xA2, + 0x2F, 0x97, 0x1F, 0x3C, 0x20, 0x12, 0x9B, 0x48, 0x00, 0x0E, 0x6E, 0xDD, + 0x06, 0x1C, 0xBC, 0x05, 0x3E, 0x37, 0x1D, 0x79, 0x4E, 0x53, 0x27, 0xDF, + 0x61, 0x1E, 0xBB, 0xBE, 0x1B, 0xAC, 0x9B, 0x5C, 0x60, 0x44, 0xCF, 0x02, + 0x3D, 0x76, 0xE0, 0x5E, 0xEA, 0x9B, 0xAD, 0x99, 0x1B, 0x13, 0xA6, 0x3C, + 0x97, 0x4E, 0x9E, 0xF1, 0x83, 0x9E, 0xB5, 0xDB, 0x12, 0x51, 0x36, 0xF7, + 0x26, 0x2E, 0x56, 0xA8, 0x87, 0x15, 0x38, 0xDF, 0xD8, 0x23, 0xC6, 0x50, + 0x50, 0x85, 0xE2, 0x1F, 0x0D, 0xD5, 0xC8, 0x6B, + }; + + /* dh1024 g */ + static const unsigned char g[] = + { + 0x02, + }; + + wolfSSL_CTX_SetTmpDH(ctx, p, sizeof(p), g, sizeof(g)); +} +#endif /* NO_DH */ + +#ifndef NO_CERTS + +static WC_INLINE void CaCb(unsigned char* der, int sz, int type) +{ + (void)der; + printf("Got CA cache add callback, derSz = %d, type = %d\n", sz, type); +} + +#endif /* !NO_CERTS */ + + +/* Wolf Root Directory Helper */ +/* KEIL-RL File System does not support relative directory */ +#if !defined(WOLFSSL_MDK_ARM) && !defined(WOLFSSL_KEIL_FS) && !defined(WOLFSSL_TIRTOS) + /* Maximum depth to search for WolfSSL root */ + #define MAX_WOLF_ROOT_DEPTH 5 + + static WC_INLINE int ChangeToWolfRoot(void) + { + #if !defined(NO_FILESYSTEM) || defined(FORCE_BUFFER_TEST) + int depth, res; + XFILE file; + for(depth = 0; depth <= MAX_WOLF_ROOT_DEPTH; depth++) { + file = fopen(ntruKeyFile, "rb"); + if (file != NULL) { + fclose(file); + return depth; + } + #ifdef USE_WINDOWS_API + res = SetCurrentDirectoryA("..\\"); + #else + res = chdir("../"); + #endif + if (res < 0) { + printf("chdir to ../ failed!\n"); + break; + } + } + + err_sys("wolf root not found"); + return -1; + #else + return 0; + #endif + } +#endif /* !defined(WOLFSSL_MDK_ARM) && !defined(WOLFSSL_KEIL_FS) && !defined(WOLFSSL_TIRTOS) */ + +#ifdef HAVE_STACK_SIZE + +typedef THREAD_RETURN WOLFSSL_THREAD (*thread_func)(void* args); +#define STACK_CHECK_VAL 0x01 + +static WC_INLINE int StackSizeCheck(func_args* args, thread_func tf) +{ + int ret, i, used; + void* status; + unsigned char* myStack = NULL; + int stackSize = 1024*128; + pthread_attr_t myAttr; + pthread_t threadId; + +#ifdef PTHREAD_STACK_MIN + if (stackSize < PTHREAD_STACK_MIN) + stackSize = PTHREAD_STACK_MIN; +#endif + + ret = posix_memalign((void**)&myStack, sysconf(_SC_PAGESIZE), stackSize); + if (ret != 0 || myStack == NULL) + err_sys("posix_memalign failed\n"); + + XMEMSET(myStack, STACK_CHECK_VAL, stackSize); + + ret = pthread_attr_init(&myAttr); + if (ret != 0) + err_sys("attr_init failed"); + + ret = pthread_attr_setstack(&myAttr, myStack, stackSize); + if (ret != 0) + err_sys("attr_setstackaddr failed"); + + ret = pthread_create(&threadId, &myAttr, tf, args); + if (ret != 0) { + perror("pthread_create failed"); + exit(EXIT_FAILURE); + } + + ret = pthread_join(threadId, &status); + if (ret != 0) + err_sys("pthread_join failed"); + + for (i = 0; i < stackSize; i++) { + if (myStack[i] != STACK_CHECK_VAL) { + break; + } + } + + free(myStack); + + used = stackSize - i; + printf("stack used = %d\n", used); + + return (int)((size_t)status); +} + + +#endif /* HAVE_STACK_SIZE */ + + +#ifdef STACK_TRAP + +/* good settings + --enable-debug --disable-shared C_EXTRA_FLAGS="-DUSER_TIME -DTFM_TIMING_RESISTANT -DPOSITIVE_EXP_ONLY -DSTACK_TRAP" + +*/ + +#ifdef HAVE_STACK_SIZE + /* client only for now, setrlimit will fail if pthread_create() called */ + /* STACK_SIZE does pthread_create() on client */ + #error "can't use STACK_TRAP with STACK_SIZE, setrlimit will fail" +#endif /* HAVE_STACK_SIZE */ + +static WC_INLINE void StackTrap(void) +{ + struct rlimit rl; + if (getrlimit(RLIMIT_STACK, &rl) != 0) + err_sys("getrlimit failed"); + printf("rlim_cur = %llu\n", rl.rlim_cur); + rl.rlim_cur = 1024*21; /* adjust trap size here */ + if (setrlimit(RLIMIT_STACK, &rl) != 0) { + perror("setrlimit"); + err_sys("setrlimit failed"); + } +} + +#else /* STACK_TRAP */ + +static WC_INLINE void StackTrap(void) +{ +} + +#endif /* STACK_TRAP */ + + +#ifdef ATOMIC_USER + +/* Atomic Encrypt Context example */ +typedef struct AtomicEncCtx { + int keySetup; /* have we done key setup yet */ + Aes aes; /* for aes example */ +} AtomicEncCtx; + + +/* Atomic Decrypt Context example */ +typedef struct AtomicDecCtx { + int keySetup; /* have we done key setup yet */ + Aes aes; /* for aes example */ +} AtomicDecCtx; + + +static WC_INLINE int myMacEncryptCb(WOLFSSL* ssl, unsigned char* macOut, + const unsigned char* macIn, unsigned int macInSz, int macContent, + int macVerify, unsigned char* encOut, const unsigned char* encIn, + unsigned int encSz, void* ctx) +{ + int ret; + Hmac hmac; + byte myInner[WOLFSSL_TLS_HMAC_INNER_SZ]; + AtomicEncCtx* encCtx = (AtomicEncCtx*)ctx; + const char* tlsStr = "TLS"; + + /* example supports (d)tls aes */ + if (wolfSSL_GetBulkCipher(ssl) != wolfssl_aes) { + printf("myMacEncryptCb not using AES\n"); + return -1; + } + + if (strstr(wolfSSL_get_version(ssl), tlsStr) == NULL) { + printf("myMacEncryptCb not using (D)TLS\n"); + return -1; + } + + /* hmac, not needed if aead mode */ + wolfSSL_SetTlsHmacInner(ssl, myInner, macInSz, macContent, macVerify); + + ret = wc_HmacSetKey(&hmac, wolfSSL_GetHmacType(ssl), + wolfSSL_GetMacSecret(ssl, macVerify), wolfSSL_GetHmacSize(ssl)); + if (ret != 0) + return ret; + ret = wc_HmacUpdate(&hmac, myInner, sizeof(myInner)); + if (ret != 0) + return ret; + ret = wc_HmacUpdate(&hmac, macIn, macInSz); + if (ret != 0) + return ret; + ret = wc_HmacFinal(&hmac, macOut); + if (ret != 0) + return ret; + + + /* encrypt setup on first time */ + if (encCtx->keySetup == 0) { + int keyLen = wolfSSL_GetKeySize(ssl); + const byte* key; + const byte* iv; + + if (wolfSSL_GetSide(ssl) == WOLFSSL_CLIENT_END) { + key = wolfSSL_GetClientWriteKey(ssl); + iv = wolfSSL_GetClientWriteIV(ssl); + } + else { + key = wolfSSL_GetServerWriteKey(ssl); + iv = wolfSSL_GetServerWriteIV(ssl); + } + + ret = wc_AesSetKey(&encCtx->aes, key, keyLen, iv, AES_ENCRYPTION); + if (ret != 0) { + printf("AesSetKey failed in myMacEncryptCb\n"); + return ret; + } + encCtx->keySetup = 1; + } + + /* encrypt */ + return wc_AesCbcEncrypt(&encCtx->aes, encOut, encIn, encSz); +} + + +static WC_INLINE int myDecryptVerifyCb(WOLFSSL* ssl, + unsigned char* decOut, const unsigned char* decIn, + unsigned int decSz, int macContent, int macVerify, + unsigned int* padSz, void* ctx) +{ + AtomicDecCtx* decCtx = (AtomicDecCtx*)ctx; + int ret = 0; + int macInSz = 0; + int ivExtra = 0; + int digestSz = wolfSSL_GetHmacSize(ssl); + unsigned int pad = 0; + unsigned int padByte = 0; + Hmac hmac; + byte myInner[WOLFSSL_TLS_HMAC_INNER_SZ]; + byte verify[WC_MAX_DIGEST_SIZE]; + const char* tlsStr = "TLS"; + + /* example supports (d)tls aes */ + if (wolfSSL_GetBulkCipher(ssl) != wolfssl_aes) { + printf("myMacEncryptCb not using AES\n"); + return -1; + } + + if (strstr(wolfSSL_get_version(ssl), tlsStr) == NULL) { + printf("myMacEncryptCb not using (D)TLS\n"); + return -1; + } + + /*decrypt */ + if (decCtx->keySetup == 0) { + int keyLen = wolfSSL_GetKeySize(ssl); + const byte* key; + const byte* iv; + + /* decrypt is from other side (peer) */ + if (wolfSSL_GetSide(ssl) == WOLFSSL_SERVER_END) { + key = wolfSSL_GetClientWriteKey(ssl); + iv = wolfSSL_GetClientWriteIV(ssl); + } + else { + key = wolfSSL_GetServerWriteKey(ssl); + iv = wolfSSL_GetServerWriteIV(ssl); + } + + ret = wc_AesSetKey(&decCtx->aes, key, keyLen, iv, AES_DECRYPTION); + if (ret != 0) { + printf("AesSetKey failed in myDecryptVerifyCb\n"); + return ret; + } + decCtx->keySetup = 1; + } + + /* decrypt */ + ret = wc_AesCbcDecrypt(&decCtx->aes, decOut, decIn, decSz); + if (ret != 0) + return ret; + + if (wolfSSL_GetCipherType(ssl) == WOLFSSL_AEAD_TYPE) { + *padSz = wolfSSL_GetAeadMacSize(ssl); + return 0; /* hmac, not needed if aead mode */ + } + + if (wolfSSL_GetCipherType(ssl) == WOLFSSL_BLOCK_TYPE) { + pad = *(decOut + decSz - 1); + padByte = 1; + if (wolfSSL_IsTLSv1_1(ssl)) + ivExtra = wolfSSL_GetCipherBlockSize(ssl); + } + + *padSz = wolfSSL_GetHmacSize(ssl) + pad + padByte; + macInSz = decSz - ivExtra - digestSz - pad - padByte; + + wolfSSL_SetTlsHmacInner(ssl, myInner, macInSz, macContent, macVerify); + + ret = wc_HmacSetKey(&hmac, wolfSSL_GetHmacType(ssl), + wolfSSL_GetMacSecret(ssl, macVerify), digestSz); + if (ret != 0) + return ret; + ret = wc_HmacUpdate(&hmac, myInner, sizeof(myInner)); + if (ret != 0) + return ret; + ret = wc_HmacUpdate(&hmac, decOut + ivExtra, macInSz); + if (ret != 0) + return ret; + ret = wc_HmacFinal(&hmac, verify); + if (ret != 0) + return ret; + + if (XMEMCMP(verify, decOut + decSz - digestSz - pad - padByte, + digestSz) != 0) { + printf("myDecryptVerify verify failed\n"); + return -1; + } + + return ret; +} + + +static WC_INLINE void SetupAtomicUser(WOLFSSL_CTX* ctx, WOLFSSL* ssl) +{ + AtomicEncCtx* encCtx; + AtomicDecCtx* decCtx; + + encCtx = (AtomicEncCtx*)malloc(sizeof(AtomicEncCtx)); + if (encCtx == NULL) + err_sys("AtomicEncCtx malloc failed"); + XMEMSET(encCtx, 0, sizeof(AtomicEncCtx)); + + decCtx = (AtomicDecCtx*)malloc(sizeof(AtomicDecCtx)); + if (decCtx == NULL) { + free(encCtx); + err_sys("AtomicDecCtx malloc failed"); + } + XMEMSET(decCtx, 0, sizeof(AtomicDecCtx)); + + wolfSSL_CTX_SetMacEncryptCb(ctx, myMacEncryptCb); + wolfSSL_SetMacEncryptCtx(ssl, encCtx); + + wolfSSL_CTX_SetDecryptVerifyCb(ctx, myDecryptVerifyCb); + wolfSSL_SetDecryptVerifyCtx(ssl, decCtx); +} + + +static WC_INLINE void FreeAtomicUser(WOLFSSL* ssl) +{ + AtomicEncCtx* encCtx = (AtomicEncCtx*)wolfSSL_GetMacEncryptCtx(ssl); + AtomicDecCtx* decCtx = (AtomicDecCtx*)wolfSSL_GetDecryptVerifyCtx(ssl); + + free(decCtx); + free(encCtx); +} + +#endif /* ATOMIC_USER */ + +#ifdef WOLFSSL_STATIC_MEMORY +static WC_INLINE int wolfSSL_PrintStats(WOLFSSL_MEM_STATS* stats) +{ + word16 i; + + if (stats == NULL) { + return 0; + } + + /* print to stderr so is on the same pipe as WOLFSSL_DEBUG */ + fprintf(stderr, "Total mallocs = %d\n", stats->totalAlloc); + fprintf(stderr, "Total frees = %d\n", stats->totalFr); + fprintf(stderr, "Current mallocs = %d\n", stats->curAlloc); + fprintf(stderr, "Available IO = %d\n", stats->avaIO); + fprintf(stderr, "Max con. handshakes = %d\n", stats->maxHa); + fprintf(stderr, "Max con. IO = %d\n", stats->maxIO); + fprintf(stderr, "State of memory blocks: size : available \n"); + for (i = 0; i < WOLFMEM_MAX_BUCKETS; i++) { + fprintf(stderr, " : %d\t : %d\n", stats->blockSz[i], + stats->avaBlock[i]); + } + + return 1; +} +#endif /* WOLFSSL_STATIC_MEMORY */ + +#ifdef HAVE_PK_CALLBACKS + +typedef struct PkCbInfo { + const char* ourKey; +#ifdef TEST_PK_PRIVKEY + union { + #ifdef HAVE_ECC + ecc_key ecc; + #endif + #ifdef HAVE_CURVE25519 + curve25519_key curve; + #endif + } keyGen; +#endif +} PkCbInfo; + +#if defined(DEBUG_PK_CB) || defined(TEST_PK_PRIVKEY) + #define WOLFSSL_PKMSG(_f_, ...) printf(_f_, ##__VA_ARGS__) +#else + #define WOLFSSL_PKMSG(_f_, ...) +#endif + +#ifdef HAVE_ECC + +static WC_INLINE int myEccKeyGen(WOLFSSL* ssl, ecc_key* key, word32 keySz, + int ecc_curve, void* ctx) +{ + int ret; + WC_RNG rng; + PkCbInfo* cbInfo = (PkCbInfo*)ctx; + ecc_key* new_key = key; +#ifdef TEST_PK_PRIVKEY + byte qx[MAX_ECC_BYTES], qy[MAX_ECC_BYTES]; + word32 qxLen = sizeof(qx), qyLen = sizeof(qy); + new_key = &cbInfo->keyGen.ecc; +#endif + + (void)ssl; + (void)cbInfo; + + WOLFSSL_PKMSG("PK ECC KeyGen: keySz %d, Curve ID %d\n", keySz, ecc_curve); + + ret = wc_InitRng(&rng); + if (ret != 0) + return ret; + + ret = wc_ecc_init(new_key); + if (ret == 0) { + /* create new key */ + ret = wc_ecc_make_key_ex(&rng, keySz, new_key, ecc_curve); + + #ifdef TEST_PK_PRIVKEY + if (ret == 0) { + /* extract public portion from new key into `key` arg */ + ret = wc_ecc_export_public_raw(new_key, qx, &qxLen, qy, &qyLen); + if (ret == 0) { + /* load public portion only into key */ + ret = wc_ecc_import_unsigned(key, qx, qy, NULL, ecc_curve); + } + (void)qxLen; + (void)qyLen; + } + #endif + } + + WOLFSSL_PKMSG("PK ECC KeyGen: ret %d\n", ret); + + wc_FreeRng(&rng); + + return ret; +} + +static WC_INLINE int myEccSign(WOLFSSL* ssl, const byte* in, word32 inSz, + byte* out, word32* outSz, const byte* key, word32 keySz, void* ctx) +{ + int ret; + WC_RNG rng; + word32 idx = 0; + ecc_key myKey; + byte* keyBuf = (byte*)key; + PkCbInfo* cbInfo = (PkCbInfo*)ctx; + + (void)ssl; + (void)cbInfo; + + WOLFSSL_PKMSG("PK ECC Sign: inSz %d, keySz %d\n", inSz, keySz); + +#ifdef TEST_PK_PRIVKEY + ret = load_key_file(cbInfo->ourKey, &keyBuf, &keySz); + if (ret != 0) + return ret; +#endif + + ret = wc_InitRng(&rng); + if (ret != 0) + return ret; + + ret = wc_ecc_init(&myKey); + if (ret == 0) { + ret = wc_EccPrivateKeyDecode(keyBuf, &idx, &myKey, keySz); + if (ret == 0) { + WOLFSSL_PKMSG("PK ECC Sign: Curve ID %d\n", myKey.dp->id); + ret = wc_ecc_sign_hash(in, inSz, out, outSz, &rng, &myKey); + } + wc_ecc_free(&myKey); + } + wc_FreeRng(&rng); + +#ifdef TEST_PK_PRIVKEY + free(keyBuf); +#endif + + WOLFSSL_PKMSG("PK ECC Sign: ret %d outSz %d\n", ret, *outSz); + + return ret; +} + + +static WC_INLINE int myEccVerify(WOLFSSL* ssl, const byte* sig, word32 sigSz, + const byte* hash, word32 hashSz, const byte* key, word32 keySz, + int* result, void* ctx) +{ + int ret; + word32 idx = 0; + ecc_key myKey; + PkCbInfo* cbInfo = (PkCbInfo*)ctx; + + (void)ssl; + (void)cbInfo; + + WOLFSSL_PKMSG("PK ECC Verify: sigSz %d, hashSz %d, keySz %d\n", sigSz, hashSz, keySz); + + ret = wc_ecc_init(&myKey); + if (ret == 0) { + ret = wc_EccPublicKeyDecode(key, &idx, &myKey, keySz); + if (ret == 0) + ret = wc_ecc_verify_hash(sig, sigSz, hash, hashSz, result, &myKey); + wc_ecc_free(&myKey); + } + + WOLFSSL_PKMSG("PK ECC Verify: ret %d, result %d\n", ret, *result); + + return ret; +} + +static WC_INLINE int myEccSharedSecret(WOLFSSL* ssl, ecc_key* otherKey, + unsigned char* pubKeyDer, unsigned int* pubKeySz, + unsigned char* out, unsigned int* outlen, + int side, void* ctx) +{ + int ret; + ecc_key* privKey = NULL; + ecc_key* pubKey = NULL; + ecc_key tmpKey; + PkCbInfo* cbInfo = (PkCbInfo*)ctx; + + (void)ssl; + (void)cbInfo; + + WOLFSSL_PKMSG("PK ECC PMS: Side %s, Peer Curve %d\n", + side == WOLFSSL_CLIENT_END ? "client" : "server", otherKey->dp->id); + + ret = wc_ecc_init(&tmpKey); + if (ret != 0) { + return ret; + } + + /* for client: create and export public key */ + if (side == WOLFSSL_CLIENT_END) { + WC_RNG rng; + + privKey = &tmpKey; + pubKey = otherKey; + + ret = wc_InitRng(&rng); + if (ret == 0) { + ret = wc_ecc_make_key_ex(&rng, 0, privKey, otherKey->dp->id); + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wc_AsyncWait(ret, &privKey->asyncDev, WC_ASYNC_FLAG_NONE); + } + #endif + if (ret == 0) + ret = wc_ecc_export_x963(privKey, pubKeyDer, pubKeySz); + wc_FreeRng(&rng); + } + } + + /* for server: import public key */ + else if (side == WOLFSSL_SERVER_END) { + #ifdef TEST_PK_PRIVKEY + privKey = &cbInfo->keyGen.ecc; + #else + privKey = otherKey; + #endif + pubKey = &tmpKey; + + ret = wc_ecc_import_x963_ex(pubKeyDer, *pubKeySz, pubKey, + otherKey->dp->id); + } + else { + ret = BAD_FUNC_ARG; + } + + /* generate shared secret and return it */ + if (ret == 0) { + ret = wc_ecc_shared_secret(privKey, pubKey, out, outlen); + + #ifdef WOLFSSL_ASYNC_CRYPT + if (ret == WC_PENDING_E) { + ret = wc_AsyncWait(ret, &privKey->asyncDev, WC_ASYNC_FLAG_CALL_AGAIN); + } + #endif + } + +#ifdef TEST_PK_PRIVKEY + if (side == WOLFSSL_SERVER_END) { + wc_ecc_free(&cbInfo->keyGen.ecc); + } +#endif + + wc_ecc_free(&tmpKey); + + WOLFSSL_PKMSG("PK ECC PMS: ret %d, PubKeySz %d, OutLen %d\n", ret, *pubKeySz, *outlen); + + return ret; +} + +#ifdef HAVE_ED25519 +static WC_INLINE int myEd25519Sign(WOLFSSL* ssl, const byte* in, word32 inSz, + byte* out, word32* outSz, const byte* key, word32 keySz, void* ctx) +{ + int ret; + word32 idx = 0; + ed25519_key myKey; + byte* keyBuf = (byte*)key; + PkCbInfo* cbInfo = (PkCbInfo*)ctx; + + (void)ssl; + (void)cbInfo; + + WOLFSSL_PKMSG("PK 25519 Sign: inSz %d, keySz %d\n", inSz, keySz); + +#ifdef TEST_PK_PRIVKEY + ret = load_key_file(cbInfo->ourKey, &keyBuf, &keySz); + if (ret != 0) + return ret; +#endif + + ret = wc_ed25519_init(&myKey); + if (ret == 0) { + ret = wc_Ed25519PrivateKeyDecode(keyBuf, &idx, &myKey, keySz); + if (ret == 0) + ret = wc_ed25519_sign_msg(in, inSz, out, outSz, &myKey); + wc_ed25519_free(&myKey); + } + +#ifdef TEST_PK_PRIVKEY + free(keyBuf); +#endif + + WOLFSSL_PKMSG("PK 25519 Sign: ret %d, outSz %d\n", ret, *outSz); + + return ret; +} + + +static WC_INLINE int myEd25519Verify(WOLFSSL* ssl, const byte* sig, word32 sigSz, + const byte* msg, word32 msgSz, const byte* key, word32 keySz, + int* result, void* ctx) +{ + int ret; + ed25519_key myKey; + PkCbInfo* cbInfo = (PkCbInfo*)ctx; + + (void)ssl; + (void)cbInfo; + + WOLFSSL_PKMSG("PK 25519 Verify: sigSz %d, msgSz %d, keySz %d\n", sigSz, msgSz, keySz); + + ret = wc_ed25519_init(&myKey); + if (ret == 0) { + ret = wc_ed25519_import_public(key, keySz, &myKey); + if (ret == 0) { + ret = wc_ed25519_verify_msg(sig, sigSz, msg, msgSz, result, &myKey); + } + wc_ed25519_free(&myKey); + } + + WOLFSSL_PKMSG("PK 25519 Verify: ret %d, result %d\n", ret, *result); + + return ret; +} +#endif /* HAVE_ED25519 */ + +#ifdef HAVE_CURVE25519 +static WC_INLINE int myX25519KeyGen(WOLFSSL* ssl, curve25519_key* key, + unsigned int keySz, void* ctx) +{ + int ret; + WC_RNG rng; + PkCbInfo* cbInfo = (PkCbInfo*)ctx; + + (void)ssl; + (void)cbInfo; + + WOLFSSL_PKMSG("PK 25519 KeyGen: keySz %d\n", keySz); + + ret = wc_InitRng(&rng); + if (ret != 0) + return ret; + + ret = wc_curve25519_make_key(&rng, keySz, key); + + wc_FreeRng(&rng); + + WOLFSSL_PKMSG("PK 25519 KeyGen: ret %d\n", ret); + + return ret; +} + +static WC_INLINE int myX25519SharedSecret(WOLFSSL* ssl, curve25519_key* otherKey, + unsigned char* pubKeyDer, unsigned int* pubKeySz, + unsigned char* out, unsigned int* outlen, + int side, void* ctx) +{ + int ret; + curve25519_key* privKey = NULL; + curve25519_key* pubKey = NULL; + curve25519_key tmpKey; + PkCbInfo* cbInfo = (PkCbInfo*)ctx; + + (void)ssl; + (void)cbInfo; + + WOLFSSL_PKMSG("PK 25519 PMS: side %s\n", + side == WOLFSSL_CLIENT_END ? "client" : "server"); + + ret = wc_curve25519_init(&tmpKey); + if (ret != 0) { + return ret; + } + + /* for client: create and export public key */ + if (side == WOLFSSL_CLIENT_END) { + WC_RNG rng; + + privKey = &tmpKey; + pubKey = otherKey; + + ret = wc_InitRng(&rng); + if (ret == 0) { + ret = wc_curve25519_make_key(&rng, CURVE25519_KEYSIZE, privKey); + if (ret == 0) { + ret = wc_curve25519_export_public_ex(privKey, pubKeyDer, + pubKeySz, EC25519_LITTLE_ENDIAN); + } + wc_FreeRng(&rng); + } + } + + /* for server: import public key */ + else if (side == WOLFSSL_SERVER_END) { + privKey = otherKey; + pubKey = &tmpKey; + + ret = wc_curve25519_import_public_ex(pubKeyDer, *pubKeySz, pubKey, + EC25519_LITTLE_ENDIAN); + } + else { + ret = BAD_FUNC_ARG; + } + + /* generate shared secret and return it */ + if (ret == 0) { + ret = wc_curve25519_shared_secret_ex(privKey, pubKey, out, outlen, + EC25519_LITTLE_ENDIAN); + } + + wc_curve25519_free(&tmpKey); + + WOLFSSL_PKMSG("PK 25519 PMS: ret %d, pubKeySz %d, outLen %d\n", + ret, *pubKeySz, *outlen); + + return ret; +} +#endif /* HAVE_CURVE25519 */ + +#endif /* HAVE_ECC */ + +#ifndef NO_DH +static WC_INLINE int myDhCallback(WOLFSSL* ssl, struct DhKey* key, + const unsigned char* priv, unsigned int privSz, + const unsigned char* pubKeyDer, unsigned int pubKeySz, + unsigned char* out, unsigned int* outlen, + void* ctx) +{ + int ret; + PkCbInfo* cbInfo = (PkCbInfo*)ctx; + + (void)ssl; + (void)cbInfo; + + /* return 0 on success */ + ret = wc_DhAgree(key, out, outlen, priv, privSz, pubKeyDer, pubKeySz); + + WOLFSSL_PKMSG("PK ED Agree: ret %d, privSz %d, pubKeySz %d, outlen %d\n", + ret, privSz, pubKeySz, *outlen); + + return ret; +}; + +#endif /* !NO_DH */ + +#ifndef NO_RSA + +static WC_INLINE int myRsaSign(WOLFSSL* ssl, const byte* in, word32 inSz, + byte* out, word32* outSz, const byte* key, word32 keySz, void* ctx) +{ + WC_RNG rng; + int ret; + word32 idx = 0; + RsaKey myKey; + byte* keyBuf = (byte*)key; + PkCbInfo* cbInfo = (PkCbInfo*)ctx; + + (void)ssl; + (void)cbInfo; + + WOLFSSL_PKMSG("PK RSA Sign: inSz %d, keySz %d\n", inSz, keySz); + +#ifdef TEST_PK_PRIVKEY + ret = load_key_file(cbInfo->ourKey, &keyBuf, &keySz); + if (ret != 0) + return ret; +#endif + + ret = wc_InitRng(&rng); + if (ret != 0) + return ret; + + ret = wc_InitRsaKey(&myKey, NULL); + if (ret == 0) { + ret = wc_RsaPrivateKeyDecode(keyBuf, &idx, &myKey, keySz); + if (ret == 0) + ret = wc_RsaSSL_Sign(in, inSz, out, *outSz, &myKey, &rng); + if (ret > 0) { /* save and convert to 0 success */ + *outSz = ret; + ret = 0; + } + wc_FreeRsaKey(&myKey); + } + wc_FreeRng(&rng); + +#ifdef TEST_PK_PRIVKEY + free(keyBuf); +#endif + + WOLFSSL_PKMSG("PK RSA Sign: ret %d, outSz %d\n", ret, *outSz); + + return ret; +} + + +static WC_INLINE int myRsaVerify(WOLFSSL* ssl, byte* sig, word32 sigSz, + byte** out, const byte* key, word32 keySz, void* ctx) +{ + int ret; + word32 idx = 0; + RsaKey myKey; + PkCbInfo* cbInfo = (PkCbInfo*)ctx; + + (void)ssl; + (void)cbInfo; + + WOLFSSL_PKMSG("PK RSA Verify: sigSz %d, keySz %d\n", sigSz, keySz); + + ret = wc_InitRsaKey(&myKey, NULL); + if (ret == 0) { + ret = wc_RsaPublicKeyDecode(key, &idx, &myKey, keySz); + if (ret == 0) + ret = wc_RsaSSL_VerifyInline(sig, sigSz, out, &myKey); + wc_FreeRsaKey(&myKey); + } + + WOLFSSL_PKMSG("PK RSA Verify: ret %d\n", ret); + + return ret; +} + +static WC_INLINE int myRsaSignCheck(WOLFSSL* ssl, byte* sig, word32 sigSz, + byte** out, const byte* key, word32 keySz, void* ctx) +{ + int ret; + word32 idx = 0; + RsaKey myKey; + byte* keyBuf = (byte*)key; + PkCbInfo* cbInfo = (PkCbInfo*)ctx; + + (void)ssl; + (void)cbInfo; + + WOLFSSL_PKMSG("PK RSA SignCheck: sigSz %d, keySz %d\n", sigSz, keySz); + +#ifdef TEST_PK_PRIVKEY + ret = load_key_file(cbInfo->ourKey, &keyBuf, &keySz); + if (ret != 0) + return ret; +#endif + + ret = wc_InitRsaKey(&myKey, NULL); + if (ret == 0) { + ret = wc_RsaPrivateKeyDecode(keyBuf, &idx, &myKey, keySz); + if (ret == 0) + ret = wc_RsaSSL_VerifyInline(sig, sigSz, out, &myKey); + wc_FreeRsaKey(&myKey); + } +#ifdef TEST_PK_PRIVKEY + free(keyBuf); +#endif + + WOLFSSL_PKMSG("PK RSA SignCheck: ret %d\n", ret); + + return ret; +} + +#ifdef WC_RSA_PSS +static WC_INLINE int myRsaPssSign(WOLFSSL* ssl, const byte* in, word32 inSz, + byte* out, word32* outSz, int hash, int mgf, const byte* key, + word32 keySz, void* ctx) +{ + enum wc_HashType hashType = WC_HASH_TYPE_NONE; + WC_RNG rng; + int ret; + word32 idx = 0; + RsaKey myKey; + byte* keyBuf = (byte*)key; + PkCbInfo* cbInfo = (PkCbInfo*)ctx; + + (void)ssl; + (void)cbInfo; + + WOLFSSL_PKMSG("PK RSA PSS Sign: inSz %d, hash %d, mgf %d, keySz %d\n", + inSz, hash, mgf, keySz); + +#ifdef TEST_PK_PRIVKEY + ret = load_key_file(cbInfo->ourKey, &keyBuf, &keySz); + if (ret != 0) + return ret; +#endif + + switch (hash) { +#ifndef NO_SHA256 + case SHA256h: + hashType = WC_HASH_TYPE_SHA256; + break; +#endif +#ifdef WOLFSSL_SHA384 + case SHA384h: + hashType = WC_HASH_TYPE_SHA384; + break; +#endif +#ifdef WOLFSSL_SHA512 + case SHA512h: + hashType = WC_HASH_TYPE_SHA512; + break; +#endif + } + + ret = wc_InitRng(&rng); + if (ret != 0) + return ret; + + ret = wc_InitRsaKey(&myKey, NULL); + if (ret == 0) { + ret = wc_RsaPrivateKeyDecode(keyBuf, &idx, &myKey, keySz); + if (ret == 0) { + ret = wc_RsaPSS_Sign(in, inSz, out, *outSz, hashType, mgf, &myKey, + &rng); + } + if (ret > 0) { /* save and convert to 0 success */ + *outSz = ret; + ret = 0; + } + wc_FreeRsaKey(&myKey); + } + wc_FreeRng(&rng); + +#ifdef TEST_PK_PRIVKEY + free(keyBuf); +#endif + + WOLFSSL_PKMSG("PK RSA PSS Sign: ret %d, outSz %d\n", ret, *outSz); + + return ret; +} + + +static WC_INLINE int myRsaPssVerify(WOLFSSL* ssl, byte* sig, word32 sigSz, + byte** out, int hash, int mgf, const byte* key, word32 keySz, void* ctx) +{ + int ret; + word32 idx = 0; + RsaKey myKey; + PkCbInfo* cbInfo = (PkCbInfo*)ctx; + enum wc_HashType hashType = WC_HASH_TYPE_NONE; + + (void)ssl; + (void)cbInfo; + + WOLFSSL_PKMSG("PK RSA PSS Verify: sigSz %d, hash %d, mgf %d, keySz %d\n", + sigSz, hash, mgf, keySz); + + switch (hash) { +#ifndef NO_SHA256 + case SHA256h: + hashType = WC_HASH_TYPE_SHA256; + break; +#endif +#ifdef WOLFSSL_SHA384 + case SHA384h: + hashType = WC_HASH_TYPE_SHA384; + break; +#endif +#ifdef WOLFSSL_SHA512 + case SHA512h: + hashType = WC_HASH_TYPE_SHA512; + break; +#endif + } + + ret = wc_InitRsaKey(&myKey, NULL); + if (ret == 0) { + ret = wc_RsaPublicKeyDecode(key, &idx, &myKey, keySz); + if (ret == 0) { + ret = wc_RsaPSS_VerifyInline(sig, sigSz, out, hashType, mgf, + &myKey); + } + wc_FreeRsaKey(&myKey); + } + + WOLFSSL_PKMSG("PK RSA PSS Verify: ret %d\n", ret); + + return ret; +} + +static WC_INLINE int myRsaPssSignCheck(WOLFSSL* ssl, byte* sig, word32 sigSz, + byte** out, int hash, int mgf, const byte* key, word32 keySz, void* ctx) +{ + int ret; + word32 idx = 0; + RsaKey myKey; + byte* keyBuf = (byte*)key; + PkCbInfo* cbInfo = (PkCbInfo*)ctx; + enum wc_HashType hashType = WC_HASH_TYPE_NONE; + + (void)ssl; + (void)cbInfo; + + WOLFSSL_PKMSG("PK RSA PSS SignCheck: sigSz %d, hash %d, mgf %d, keySz %d\n", + sigSz, hash, mgf, keySz); + +#ifdef TEST_PK_PRIVKEY + ret = load_key_file(cbInfo->ourKey, &keyBuf, &keySz); + if (ret != 0) + return ret; +#endif + + switch (hash) { +#ifndef NO_SHA256 + case SHA256h: + hashType = WC_HASH_TYPE_SHA256; + break; +#endif +#ifdef WOLFSSL_SHA384 + case SHA384h: + hashType = WC_HASH_TYPE_SHA384; + break; +#endif +#ifdef WOLFSSL_SHA512 + case SHA512h: + hashType = WC_HASH_TYPE_SHA512; + break; +#endif + } + + ret = wc_InitRsaKey(&myKey, NULL); + if (ret == 0) { + ret = wc_RsaPrivateKeyDecode(keyBuf, &idx, &myKey, keySz); + if (ret == 0) { + ret = wc_RsaPSS_VerifyInline(sig, sigSz, out, hashType, mgf, + &myKey); + } + wc_FreeRsaKey(&myKey); + } + +#ifdef TEST_PK_PRIVKEY + free(keyBuf); +#endif + + WOLFSSL_PKMSG("PK RSA PSS SignCheck: ret %d\n", ret); + + return ret; +} +#endif + + +static WC_INLINE int myRsaEnc(WOLFSSL* ssl, const byte* in, word32 inSz, + byte* out, word32* outSz, const byte* key, + word32 keySz, void* ctx) +{ + int ret; + word32 idx = 0; + RsaKey myKey; + WC_RNG rng; + PkCbInfo* cbInfo = (PkCbInfo*)ctx; + + (void)ssl; + (void)cbInfo; + + WOLFSSL_PKMSG("PK RSA Enc: inSz %d, keySz %d\n", inSz, keySz); + + ret = wc_InitRng(&rng); + if (ret != 0) + return ret; + + ret = wc_InitRsaKey(&myKey, NULL); + if (ret == 0) { + ret = wc_RsaPublicKeyDecode(key, &idx, &myKey, keySz); + if (ret == 0) { + ret = wc_RsaPublicEncrypt(in, inSz, out, *outSz, &myKey, &rng); + if (ret > 0) { + *outSz = ret; + ret = 0; /* reset to success */ + } + } + wc_FreeRsaKey(&myKey); + } + wc_FreeRng(&rng); + + WOLFSSL_PKMSG("PK RSA Enc: ret %d, outSz %d\n", ret, *outSz); + + return ret; +} + +static WC_INLINE int myRsaDec(WOLFSSL* ssl, byte* in, word32 inSz, + byte** out, + const byte* key, word32 keySz, void* ctx) +{ + int ret; + word32 idx = 0; + RsaKey myKey; + byte* keyBuf = (byte*)key; + PkCbInfo* cbInfo = (PkCbInfo*)ctx; + + (void)ssl; + (void)cbInfo; + + WOLFSSL_PKMSG("PK RSA Dec: inSz %d, keySz %d\n", inSz, keySz); + +#ifdef TEST_PK_PRIVKEY + ret = load_key_file(cbInfo->ourKey, &keyBuf, &keySz); + if (ret != 0) + return ret; +#endif + + ret = wc_InitRsaKey(&myKey, NULL); + if (ret == 0) { + ret = wc_RsaPrivateKeyDecode(keyBuf, &idx, &myKey, keySz); + if (ret == 0) { + #ifdef WC_RSA_BLINDING + ret = wc_RsaSetRNG(&myKey, wolfSSL_GetRNG(ssl)); + if (ret != 0) { + wc_FreeRsaKey(&myKey); + return ret; + } + #endif + ret = wc_RsaPrivateDecryptInline(in, inSz, out, &myKey); + } + wc_FreeRsaKey(&myKey); + } + +#ifdef TEST_PK_PRIVKEY + free(keyBuf); +#endif + + WOLFSSL_PKMSG("PK RSA Dec: ret %d\n", ret); + + return ret; +} + +#endif /* NO_RSA */ + +static WC_INLINE void SetupPkCallbacks(WOLFSSL_CTX* ctx) +{ + (void)ctx; + + #ifdef HAVE_ECC + wolfSSL_CTX_SetEccKeyGenCb(ctx, myEccKeyGen); + wolfSSL_CTX_SetEccSignCb(ctx, myEccSign); + wolfSSL_CTX_SetEccVerifyCb(ctx, myEccVerify); + wolfSSL_CTX_SetEccSharedSecretCb(ctx, myEccSharedSecret); + #endif /* HAVE_ECC */ + #ifndef NO_DH + wolfSSL_CTX_SetDhAgreeCb(ctx, myDhCallback); + #endif + #ifdef HAVE_ED25519 + wolfSSL_CTX_SetEd25519SignCb(ctx, myEd25519Sign); + wolfSSL_CTX_SetEd25519VerifyCb(ctx, myEd25519Verify); + #endif + #ifdef HAVE_CURVE25519 + wolfSSL_CTX_SetX25519KeyGenCb(ctx, myX25519KeyGen); + wolfSSL_CTX_SetX25519SharedSecretCb(ctx, myX25519SharedSecret); + #endif + #ifndef NO_RSA + wolfSSL_CTX_SetRsaSignCb(ctx, myRsaSign); + wolfSSL_CTX_SetRsaVerifyCb(ctx, myRsaVerify); + wolfSSL_CTX_SetRsaSignCheckCb(ctx, myRsaSignCheck); + #ifdef WC_RSA_PSS + wolfSSL_CTX_SetRsaPssSignCb(ctx, myRsaPssSign); + wolfSSL_CTX_SetRsaPssVerifyCb(ctx, myRsaPssVerify); + wolfSSL_CTX_SetRsaPssSignCheckCb(ctx, myRsaPssSignCheck); + #endif + wolfSSL_CTX_SetRsaEncCb(ctx, myRsaEnc); + wolfSSL_CTX_SetRsaDecCb(ctx, myRsaDec); + #endif /* NO_RSA */ +} + +static WC_INLINE void SetupPkCallbackContexts(WOLFSSL* ssl, void* myCtx) +{ + #ifdef HAVE_ECC + wolfSSL_SetEccKeyGenCtx(ssl, myCtx); + wolfSSL_SetEccSignCtx(ssl, myCtx); + wolfSSL_SetEccVerifyCtx(ssl, myCtx); + wolfSSL_SetEccSharedSecretCtx(ssl, myCtx); + #endif /* HAVE_ECC */ + #ifndef NO_DH + wolfSSL_SetDhAgreeCtx(ssl, myCtx); + #endif + #ifdef HAVE_ED25519 + wolfSSL_SetEd25519SignCtx(ssl, myCtx); + wolfSSL_SetEd25519VerifyCtx(ssl, myCtx); + #endif + #ifdef HAVE_CURVE25519 + wolfSSL_SetX25519KeyGenCtx(ssl, myCtx); + wolfSSL_SetX25519SharedSecretCtx(ssl, myCtx); + #endif + #ifndef NO_RSA + wolfSSL_SetRsaSignCtx(ssl, myCtx); + wolfSSL_SetRsaVerifyCtx(ssl, myCtx); + #ifdef WC_RSA_PSS + wolfSSL_SetRsaPssSignCtx(ssl, myCtx); + wolfSSL_SetRsaPssVerifyCtx(ssl, myCtx); + #endif + wolfSSL_SetRsaEncCtx(ssl, myCtx); + wolfSSL_SetRsaDecCtx(ssl, myCtx); + #endif /* NO_RSA */ +} + +#endif /* HAVE_PK_CALLBACKS */ + + + + +#if defined(__hpux__) || defined(__MINGW32__) || defined (WOLFSSL_TIRTOS) \ + || defined(_MSC_VER) + +/* HP/UX doesn't have strsep, needed by test/suites.c */ +static WC_INLINE char* strsep(char **stringp, const char *delim) +{ + char* start; + char* end; + + start = *stringp; + if (start == NULL) + return NULL; + + if ((end = strpbrk(start, delim))) { + *end++ = '\0'; + *stringp = end; + } else { + *stringp = NULL; + } + + return start; +} + +#endif /* __hpux__ and others */ + +/* Create unique filename, len is length of tempfn name, assuming + len does not include null terminating character, + num is number of characters in tempfn name to randomize */ +static WC_INLINE const char* mymktemp(char *tempfn, int len, int num) +{ + int x, size; + static const char alphanum[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz"; + WC_RNG rng; + byte out; + + if (tempfn == NULL || len < 1 || num < 1 || len <= num) { + printf("Bad input\n"); + return NULL; + } + + size = len - 1; + + if (wc_InitRng(&rng) != 0) { + printf("InitRng failed\n"); + return NULL; + } + + for (x = size; x > size - num; x--) { + if (wc_RNG_GenerateBlock(&rng,(byte*)&out, sizeof(out)) != 0) { + printf("RNG_GenerateBlock failed\n"); + return NULL; + } + tempfn[x] = alphanum[out % (sizeof(alphanum) - 1)]; + } + tempfn[len] = '\0'; + + wc_FreeRng(&rng); + (void)rng; /* for WC_NO_RNG case */ + + return tempfn; +} + + + +#if defined(HAVE_SESSION_TICKET) && defined(HAVE_CHACHA) && \ + defined(HAVE_POLY1305) + + #include + + typedef struct key_ctx { + byte name[WOLFSSL_TICKET_NAME_SZ]; /* name for this context */ + byte key[CHACHA20_POLY1305_AEAD_KEYSIZE]; /* cipher key */ + } key_ctx; + + static THREAD_LS_T key_ctx myKey_ctx; + static THREAD_LS_T WC_RNG myKey_rng; + + static WC_INLINE int TicketInit(void) + { + int ret = wc_InitRng(&myKey_rng); + if (ret != 0) return ret; + + ret = wc_RNG_GenerateBlock(&myKey_rng, myKey_ctx.key, sizeof(myKey_ctx.key)); + if (ret != 0) return ret; + + ret = wc_RNG_GenerateBlock(&myKey_rng, myKey_ctx.name,sizeof(myKey_ctx.name)); + if (ret != 0) return ret; + + return 0; + } + + static WC_INLINE void TicketCleanup(void) + { + wc_FreeRng(&myKey_rng); + } + + static WC_INLINE int myTicketEncCb(WOLFSSL* ssl, + byte key_name[WOLFSSL_TICKET_NAME_SZ], + byte iv[WOLFSSL_TICKET_IV_SZ], + byte mac[WOLFSSL_TICKET_MAC_SZ], + int enc, byte* ticket, int inLen, int* outLen, + void* userCtx) + { + (void)ssl; + (void)userCtx; + + int ret; + word16 sLen = XHTONS(inLen); + byte aad[WOLFSSL_TICKET_NAME_SZ + WOLFSSL_TICKET_IV_SZ + 2]; + int aadSz = WOLFSSL_TICKET_NAME_SZ + WOLFSSL_TICKET_IV_SZ + 2; + byte* tmp = aad; + + if (enc) { + XMEMCPY(key_name, myKey_ctx.name, WOLFSSL_TICKET_NAME_SZ); + + ret = wc_RNG_GenerateBlock(&myKey_rng, iv, WOLFSSL_TICKET_IV_SZ); + if (ret != 0) return WOLFSSL_TICKET_RET_REJECT; + + /* build aad from key name, iv, and length */ + XMEMCPY(tmp, key_name, WOLFSSL_TICKET_NAME_SZ); + tmp += WOLFSSL_TICKET_NAME_SZ; + XMEMCPY(tmp, iv, WOLFSSL_TICKET_IV_SZ); + tmp += WOLFSSL_TICKET_IV_SZ; + XMEMCPY(tmp, &sLen, 2); + + ret = wc_ChaCha20Poly1305_Encrypt(myKey_ctx.key, iv, + aad, aadSz, + ticket, inLen, + ticket, + mac); + if (ret != 0) return WOLFSSL_TICKET_RET_REJECT; + *outLen = inLen; /* no padding in this mode */ + } else { + /* decrypt */ + + /* see if we know this key */ + if (XMEMCMP(key_name, myKey_ctx.name, WOLFSSL_TICKET_NAME_SZ) != 0){ + printf("client presented unknown ticket key name "); + return WOLFSSL_TICKET_RET_FATAL; + } + + /* build aad from key name, iv, and length */ + XMEMCPY(tmp, key_name, WOLFSSL_TICKET_NAME_SZ); + tmp += WOLFSSL_TICKET_NAME_SZ; + XMEMCPY(tmp, iv, WOLFSSL_TICKET_IV_SZ); + tmp += WOLFSSL_TICKET_IV_SZ; + XMEMCPY(tmp, &sLen, 2); + + ret = wc_ChaCha20Poly1305_Decrypt(myKey_ctx.key, iv, + aad, aadSz, + ticket, inLen, + mac, + ticket); + if (ret != 0) return WOLFSSL_TICKET_RET_REJECT; + *outLen = inLen; /* no padding in this mode */ + } + + return WOLFSSL_TICKET_RET_OK; + } + +#endif /* HAVE_SESSION_TICKET && CHACHA20 && POLY1305 */ + +static WC_INLINE word16 GetRandomPort(void) +{ + word16 port = 0; + + /* Generate random port for testing */ + WC_RNG rng; + if (wc_InitRng(&rng) == 0) { + if (wc_RNG_GenerateBlock(&rng, (byte*)&port, sizeof(port)) == 0) { + port |= 0xC000; /* Make sure its in the 49152 - 65535 range */ + } + wc_FreeRng(&rng); + } + (void)rng; /* for WC_NO_RNG case */ + return port; +} + +#endif /* wolfSSL_TEST_H */ diff --git a/beken_os/beken378/func/wolfssl/wolfssl/version.h b/beken_os/beken378/func/wolfssl/wolfssl/version.h new file mode 100755 index 0000000..eb0b8fe --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/version.h @@ -0,0 +1,40 @@ +/* wolfssl_version.h.in + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifndef WOLFSSL_VERSION_H +#define WOLFSSL_VERSION_H + + +#ifdef __cplusplus +extern "C" { +#endif + +#define LIBWOLFSSL_VERSION_STRING "4.1.0" +#define LIBWOLFSSL_VERSION_HEX 0x04001000 + +#ifdef __cplusplus +} +#endif + + +#endif /* WOLFSSL_VERSION_H */ + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/version.h.in b/beken_os/beken378/func/wolfssl/wolfssl/version.h.in new file mode 100755 index 0000000..099afb2 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/version.h.in @@ -0,0 +1,40 @@ +/* wolfssl_version.h.in + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifndef WOLFSSL_VERSION_H +#define WOLFSSL_VERSION_H + + +#ifdef __cplusplus +extern "C" { +#endif + +#define LIBWOLFSSL_VERSION_STRING "@VERSION@" +#define LIBWOLFSSL_VERSION_HEX @HEX_VERSION@ + +#ifdef __cplusplus +} +#endif + + +#endif /* WOLFSSL_VERSION_H */ + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/aes.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/aes.h new file mode 100755 index 0000000..71fc7b8 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/aes.h @@ -0,0 +1,384 @@ +/* aes.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/*! + \file wolfssl/wolfcrypt/aes.h +*/ + + +#ifndef WOLF_CRYPT_AES_H +#define WOLF_CRYPT_AES_H + +#include + +#ifndef NO_AES + +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + #include +#endif /* HAVE_FIPS_VERSION >= 2 */ + +/* included for fips @wc_fips */ +#if defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) +#include +#if defined(CYASSL_AES_COUNTER) && !defined(WOLFSSL_AES_COUNTER) + #define WOLFSSL_AES_COUNTER +#endif +#if !defined(WOLFSSL_AES_DIRECT) && defined(CYASSL_AES_DIRECT) + #define WOLFSSL_AES_DIRECT +#endif +#endif + +#ifndef WC_NO_RNG + #include +#endif +#ifdef STM32_CRYPTO + #include +#endif + +#ifdef WOLFSSL_AESNI + +#include +#include +#include + +#endif /* WOLFSSL_AESNI */ + + +#ifdef WOLFSSL_XILINX_CRYPT +#include "xsecure_aes.h" +#endif + +#if defined(WOLFSSL_AFALG) || defined(WOLFSSL_AFALG_XILINX_AES) +/* included for struct msghdr */ +#include +#endif + +#if defined(WOLFSSL_DEVCRYPTO_AES) || defined(WOLFSSL_DEVCRYPTO_CBC) +#include +#endif + +#if defined(HAVE_AESGCM) && !defined(WC_NO_RNG) + #include +#endif + +#if defined(WOLFSSL_CRYPTOCELL) + #include +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +/* these are required for FIPS and non-FIPS */ +enum { + AES_128_KEY_SIZE = 16, /* for 128 bit */ + AES_192_KEY_SIZE = 24, /* for 192 bit */ + AES_256_KEY_SIZE = 32, /* for 256 bit */ + + AES_IV_SIZE = 16, /* always block size */ +}; + + +/* avoid redefinition of structs */ +#if !defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) + +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif + +enum { + AES_ENC_TYPE = WC_CIPHER_AES, /* cipher unique type */ + AES_ENCRYPTION = 0, + AES_DECRYPTION = 1, + + AES_BLOCK_SIZE = 16, + + KEYWRAP_BLOCK_SIZE = 8, + + GCM_NONCE_MAX_SZ = 16, /* wolfCrypt's maximum nonce size allowed. */ + GCM_NONCE_MID_SZ = 12, /* The usual default nonce size for AES-GCM. */ + GCM_NONCE_MIN_SZ = 8, /* wolfCrypt's minimum nonce size allowed. */ + CCM_NONCE_MIN_SZ = 7, + CCM_NONCE_MAX_SZ = 13, + CTR_SZ = 4, + AES_IV_FIXED_SZ = 4, + +#ifdef HAVE_PKCS11 + AES_MAX_ID_LEN = 32, +#endif +}; + + +typedef struct Aes { + /* AESNI needs key first, rounds 2nd, not sure why yet */ + ALIGN16 word32 key[60]; + word32 rounds; + int keylen; + + ALIGN16 word32 reg[AES_BLOCK_SIZE / sizeof(word32)]; /* for CBC mode */ + ALIGN16 word32 tmp[AES_BLOCK_SIZE / sizeof(word32)]; /* same */ + +#if defined(HAVE_AESGCM) || defined(HAVE_AESCCM) + word32 invokeCtr[2]; + word32 nonceSz; +#endif +#ifdef HAVE_AESGCM + ALIGN16 byte H[AES_BLOCK_SIZE]; +#ifdef GCM_TABLE + /* key-based fast multiplication table. */ + ALIGN16 byte M0[256][AES_BLOCK_SIZE]; +#endif /* GCM_TABLE */ +#endif /* HAVE_AESGCM */ +#ifdef WOLFSSL_AESNI + byte use_aesni; +#endif /* WOLFSSL_AESNI */ +#ifdef WOLF_CRYPTO_CB + int devId; + void* devCtx; +#endif +#ifdef HAVE_PKCS11 + byte id[AES_MAX_ID_LEN]; + int idLen; +#endif +#ifdef WOLFSSL_ASYNC_CRYPT + word32 asyncKey[AES_MAX_KEY_SIZE/8/sizeof(word32)]; /* raw key */ + word32 asyncIv[AES_BLOCK_SIZE/sizeof(word32)]; /* raw IV */ + WC_ASYNC_DEV asyncDev; +#endif /* WOLFSSL_ASYNC_CRYPT */ +#if defined(WOLFSSL_AES_COUNTER) || defined(WOLFSSL_AES_CFB) + word32 left; /* unused bytes left from last call */ +#endif +#ifdef WOLFSSL_XILINX_CRYPT + XSecure_Aes xilAes; + XCsuDma dma; + word32 key_init[8]; + word32 kup; +#endif +#if defined(WOLFSSL_AFALG) || defined(WOLFSSL_AFALG_XILINX_AES) + int alFd; /* server socket to bind to */ + int rdFd; /* socket to read from */ + struct msghdr msg; + int dir; /* flag for encrpyt or decrypt */ +#ifdef WOLFSSL_AFALG_XILINX_AES + word32 msgBuf[CMSG_SPACE(4) + CMSG_SPACE(sizeof(struct af_alg_iv) + + GCM_NONCE_MID_SZ)]; +#endif +#endif +#if defined(WOLF_CRYPTO_CB) || (defined(WOLFSSL_DEVCRYPTO) && \ + (defined(WOLFSSL_DEVCRYPTO_AES) || defined(WOLFSSL_DEVCRYPTO_CBC))) + word32 devKey[AES_MAX_KEY_SIZE/WOLFSSL_BIT_SIZE/sizeof(word32)]; /* raw key */ +#endif +#if defined(WOLFSSL_DEVCRYPTO) && \ + (defined(WOLFSSL_DEVCRYPTO_AES) || defined(WOLFSSL_DEVCRYPTO_CBC)) + WC_CRYPTODEV ctx; +#endif +#if defined(WOLFSSL_CRYPTOCELL) + aes_context_t ctx; +#endif + void* heap; /* memory hint to use */ +} Aes; + +#ifdef WOLFSSL_AES_XTS +typedef struct XtsAes { + Aes aes; + Aes tweak; +} XtsAes; +#endif + +#ifdef HAVE_AESGCM +typedef struct Gmac { + Aes aes; +} Gmac; +#endif /* HAVE_AESGCM */ +#endif /* HAVE_FIPS */ + + +/* Authenticate cipher function prototypes */ +typedef int (*wc_AesAuthEncryptFunc)(Aes* aes, byte* out, + const byte* in, word32 sz, + const byte* iv, word32 ivSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz); +typedef int (*wc_AesAuthDecryptFunc)(Aes* aes, byte* out, + const byte* in, word32 sz, + const byte* iv, word32 ivSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz); + +/* AES-CBC */ +WOLFSSL_API int wc_AesSetKey(Aes* aes, const byte* key, word32 len, + const byte* iv, int dir); +WOLFSSL_API int wc_AesSetIV(Aes* aes, const byte* iv); + +#ifdef HAVE_AES_CBC +WOLFSSL_API int wc_AesCbcEncrypt(Aes* aes, byte* out, + const byte* in, word32 sz); +WOLFSSL_API int wc_AesCbcDecrypt(Aes* aes, byte* out, + const byte* in, word32 sz); +#endif + +#ifdef WOLFSSL_AES_CFB +WOLFSSL_API int wc_AesCfbEncrypt(Aes* aes, byte* out, + const byte* in, word32 sz); +#ifdef HAVE_AES_DECRYPT +WOLFSSL_API int wc_AesCfbDecrypt(Aes* aes, byte* out, + const byte* in, word32 sz); +#endif /* HAVE_AES_DECRYPT */ +#endif /* WOLFSSL_AES_CFB */ + +#ifdef HAVE_AES_ECB +WOLFSSL_API int wc_AesEcbEncrypt(Aes* aes, byte* out, + const byte* in, word32 sz); +WOLFSSL_API int wc_AesEcbDecrypt(Aes* aes, byte* out, + const byte* in, word32 sz); +#endif + +/* AES-CTR */ +#ifdef WOLFSSL_AES_COUNTER + WOLFSSL_API int wc_AesCtrEncrypt(Aes* aes, byte* out, + const byte* in, word32 sz); +#endif +/* AES-DIRECT */ +#if defined(WOLFSSL_AES_DIRECT) + WOLFSSL_API void wc_AesEncryptDirect(Aes* aes, byte* out, const byte* in); + WOLFSSL_API void wc_AesDecryptDirect(Aes* aes, byte* out, const byte* in); + WOLFSSL_API int wc_AesSetKeyDirect(Aes* aes, const byte* key, word32 len, + const byte* iv, int dir); +#endif + +#ifdef HAVE_AESGCM +#ifdef WOLFSSL_XILINX_CRYPT + WOLFSSL_API int wc_AesGcmSetKey_ex(Aes* aes, const byte* key, word32 len, + word32 kup); +#elif defined(WOLFSSL_AFALG_XILINX_AES) + WOLFSSL_LOCAL int wc_AesGcmSetKey_ex(Aes* aes, const byte* key, word32 len, + word32 kup); +#endif + WOLFSSL_API int wc_AesGcmSetKey(Aes* aes, const byte* key, word32 len); + WOLFSSL_API int wc_AesGcmEncrypt(Aes* aes, byte* out, + const byte* in, word32 sz, + const byte* iv, word32 ivSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz); + WOLFSSL_API int wc_AesGcmDecrypt(Aes* aes, byte* out, + const byte* in, word32 sz, + const byte* iv, word32 ivSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz); + +#ifndef WC_NO_RNG + WOLFSSL_API int wc_AesGcmSetExtIV(Aes* aes, const byte* iv, word32 ivSz); + WOLFSSL_API int wc_AesGcmSetIV(Aes* aes, word32 ivSz, + const byte* ivFixed, word32 ivFixedSz, + WC_RNG* rng); + WOLFSSL_API int wc_AesGcmEncrypt_ex(Aes* aes, byte* out, + const byte* in, word32 sz, + byte* ivOut, word32 ivOutSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz); +#endif /* WC_NO_RNG */ + + WOLFSSL_API int wc_GmacSetKey(Gmac* gmac, const byte* key, word32 len); + WOLFSSL_API int wc_GmacUpdate(Gmac* gmac, const byte* iv, word32 ivSz, + const byte* authIn, word32 authInSz, + byte* authTag, word32 authTagSz); +#ifndef WC_NO_RNG + WOLFSSL_API int wc_Gmac(const byte* key, word32 keySz, byte* iv, word32 ivSz, + const byte* authIn, word32 authInSz, + byte* authTag, word32 authTagSz, WC_RNG* rng); + WOLFSSL_API int wc_GmacVerify(const byte* key, word32 keySz, + const byte* iv, word32 ivSz, + const byte* authIn, word32 authInSz, + const byte* authTag, word32 authTagSz); +#endif /* WC_NO_RNG */ + WOLFSSL_LOCAL void GHASH(Aes* aes, const byte* a, word32 aSz, const byte* c, + word32 cSz, byte* s, word32 sSz); +#endif /* HAVE_AESGCM */ +#ifdef HAVE_AESCCM + WOLFSSL_API int wc_AesCcmSetKey(Aes* aes, const byte* key, word32 keySz); + WOLFSSL_API int wc_AesCcmEncrypt(Aes* aes, byte* out, + const byte* in, word32 inSz, + const byte* nonce, word32 nonceSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz); + WOLFSSL_API int wc_AesCcmDecrypt(Aes* aes, byte* out, + const byte* in, word32 inSz, + const byte* nonce, word32 nonceSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz); + WOLFSSL_API int wc_AesCcmSetNonce(Aes* aes, + const byte* nonce, word32 nonceSz); + WOLFSSL_API int wc_AesCcmEncrypt_ex(Aes* aes, byte* out, + const byte* in, word32 sz, + byte* ivOut, word32 ivOutSz, + byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz); +#endif /* HAVE_AESCCM */ +#ifdef HAVE_AES_KEYWRAP + WOLFSSL_API int wc_AesKeyWrap(const byte* key, word32 keySz, + const byte* in, word32 inSz, + byte* out, word32 outSz, + const byte* iv); + WOLFSSL_API int wc_AesKeyUnWrap(const byte* key, word32 keySz, + const byte* in, word32 inSz, + byte* out, word32 outSz, + const byte* iv); +#endif /* HAVE_AES_KEYWRAP */ + +#ifdef WOLFSSL_AES_XTS + +WOLFSSL_API int wc_AesXtsSetKey(XtsAes* aes, const byte* key, + word32 len, int dir, void* heap, int devId); + +WOLFSSL_API int wc_AesXtsEncryptSector(XtsAes* aes, byte* out, + const byte* in, word32 sz, word64 sector); + +WOLFSSL_API int wc_AesXtsDecryptSector(XtsAes* aes, byte* out, + const byte* in, word32 sz, word64 sector); + +WOLFSSL_API int wc_AesXtsEncrypt(XtsAes* aes, byte* out, + const byte* in, word32 sz, const byte* i, word32 iSz); + +WOLFSSL_API int wc_AesXtsDecrypt(XtsAes* aes, byte* out, + const byte* in, word32 sz, const byte* i, word32 iSz); + +WOLFSSL_API int wc_AesXtsFree(XtsAes* aes); +#endif + +WOLFSSL_API int wc_AesGetKeySize(Aes* aes, word32* keySize); + +WOLFSSL_API int wc_AesInit(Aes* aes, void* heap, int devId); +#ifdef HAVE_PKCS11 +WOLFSSL_API int wc_AesInit_Id(Aes* aes, unsigned char* id, int len, void* heap, + int devId); +#endif +WOLFSSL_API void wc_AesFree(Aes* aes); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + + +#endif /* NO_AES */ +#endif /* WOLF_CRYPT_AES_H */ diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/arc4.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/arc4.h new file mode 100755 index 0000000..3a76099 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/arc4.h @@ -0,0 +1,68 @@ +/* arc4.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/*! + \file wolfssl/wolfcrypt/arc4.h +*/ + +#ifndef WOLF_CRYPT_ARC4_H +#define WOLF_CRYPT_ARC4_H + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif + +enum { + ARC4_ENC_TYPE = 4, /* cipher unique type */ + ARC4_STATE_SIZE = 256, + RC4_KEY_SIZE = 16, /* always 128bit */ +}; + +/* ARC4 encryption and decryption */ +typedef struct Arc4 { + byte x; + byte y; + byte state[ARC4_STATE_SIZE]; +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV asyncDev; +#endif + void* heap; +} Arc4; + +WOLFSSL_API int wc_Arc4Process(Arc4*, byte*, const byte*, word32); +WOLFSSL_API int wc_Arc4SetKey(Arc4*, const byte*, word32); + +WOLFSSL_API int wc_Arc4Init(Arc4*, void*, int); +WOLFSSL_API void wc_Arc4Free(Arc4*); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + + +#endif /* WOLF_CRYPT_ARC4_H */ + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/asn.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/asn.h new file mode 100755 index 0000000..2714791 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/asn.h @@ -0,0 +1,1331 @@ +/* asn.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/*! + \file wolfssl/wolfcrypt/asn.h +*/ + +#ifndef WOLF_CRYPT_ASN_H +#define WOLF_CRYPT_ASN_H + +#include + +#ifndef NO_ASN + + +#if !defined(NO_ASN_TIME) && defined(NO_TIME_H) + #define NO_ASN_TIME /* backwards compatibility with NO_TIME_H */ +#endif + +#include + +/* fips declare of RsaPrivateKeyDecode @wc_fips */ +#if defined(HAVE_FIPS) && !defined(NO_RSA) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) + #include +#endif + +#ifndef NO_DH + #include +#endif +#ifndef NO_DSA + #include +#endif +#ifndef NO_SHA + #include +#endif +#ifndef NO_MD5 + #include +#endif +#include +#include /* public interface */ + +#if defined(NO_SHA) && defined(NO_SHA256) + #define WC_SHA256_DIGEST_SIZE 32 +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +enum { + ISSUER = 0, + SUBJECT = 1, + + EXTERNAL_SERIAL_SIZE = 32, + + BEFORE = 0, + AFTER = 1 +}; + +/* ASN Tags */ +enum ASN_Tags { + ASN_BOOLEAN = 0x01, + ASN_INTEGER = 0x02, + ASN_BIT_STRING = 0x03, + ASN_OCTET_STRING = 0x04, + ASN_TAG_NULL = 0x05, + ASN_OBJECT_ID = 0x06, + ASN_ENUMERATED = 0x0a, + ASN_UTF8STRING = 0x0c, + ASN_SEQUENCE = 0x10, + ASN_SET = 0x11, + ASN_PRINTABLE_STRING = 0x13, + ASN_UTC_TIME = 0x17, + ASN_OTHER_TYPE = 0x00, + ASN_RFC822_TYPE = 0x01, + ASN_DNS_TYPE = 0x02, + ASN_DIR_TYPE = 0x04, + ASN_URI_TYPE = 0x06, /* the value 6 is from GeneralName OID */ + ASN_GENERALIZED_TIME = 0x18, + CRL_EXTENSIONS = 0xa0, + ASN_EXTENSIONS = 0xa3, + ASN_LONG_LENGTH = 0x80, + ASN_INDEF_LENGTH = 0x80, + + /* ASN_Flags - Bitmask */ + ASN_CONSTRUCTED = 0x20, + ASN_APPLICATION = 0x40, + ASN_CONTEXT_SPECIFIC = 0x80, +}; + +#define ASN_UTC_TIME_SIZE 14 +#define ASN_GENERALIZED_TIME_SIZE 16 +#define ASN_GENERALIZED_TIME_MAX 68 + +enum DN_Tags { + ASN_COMMON_NAME = 0x03, /* CN */ + ASN_SUR_NAME = 0x04, /* SN */ + ASN_SERIAL_NUMBER = 0x05, /* serialNumber */ + ASN_COUNTRY_NAME = 0x06, /* C */ + ASN_LOCALITY_NAME = 0x07, /* L */ + ASN_STATE_NAME = 0x08, /* ST */ + ASN_ORG_NAME = 0x0a, /* O */ + ASN_ORGUNIT_NAME = 0x0b, /* OU */ + ASN_BUS_CAT = 0x0f, /* businessCategory */ + ASN_EMAIL_NAME = 0x98, /* not oid number there is 97 in 2.5.4.0-97 */ + + /* pilot attribute types + * OID values of 0.9.2342.19200300.100.1.* */ + ASN_USER_ID = 0x01, /* UID */ + ASN_DOMAIN_COMPONENT = 0x19 /* DC */ +}; + +/* DN Tag Strings */ +#define WOLFSSL_COMMON_NAME "/CN=" +#define WOLFSSL_SUR_NAME "/SN=" +#define WOLFSSL_SERIAL_NUMBER "/serialNumber=" +#define WOLFSSL_COUNTRY_NAME "/C=" +#define WOLFSSL_LOCALITY_NAME "/L=" +#define WOLFSSL_STATE_NAME "/ST=" +#define WOLFSSL_ORG_NAME "/O=" +#define WOLFSSL_ORGUNIT_NAME "/OU=" +#define WOLFSSL_DOMAIN_COMPONENT "/DC=" +#define WOLFSSL_BUS_CAT "/businessCategory=" +#define WOLFSSL_JOI_C "/jurisdictionC=" +#define WOLFSSL_JOI_ST "/jurisdictionST=" +#define WOLFSSL_EMAIL_ADDR "/emailAddress=" + +/* NIDs */ +enum +{ + NID_undef = 0, + NID_des = 66, + NID_des3 = 67, + NID_sha256 = 672, + NID_sha384 = 673, + NID_sha512 = 674, + NID_hw_name_oid = 73, + NID_id_pkix_OCSP_basic = 74, + NID_any_policy = 75, + NID_anyExtendedKeyUsage = 76, + NID_basic_constraints = 133, + NID_key_usage = 129, /* 2.5.29.15 */ + NID_ext_key_usage = 151, /* 2.5.29.37 */ + NID_subject_key_identifier = 128, + NID_authority_key_identifier = 149, + NID_private_key_usage_period = 130, /* 2.5.29.16 */ + NID_subject_alt_name = 131, + NID_issuer_alt_name = 132, + NID_info_access = 69, + NID_sinfo_access = 79, /* id-pe 11 */ + NID_name_constraints = 144, /* 2.5.29.30 */ + NID_certificate_policies = 146, + NID_policy_mappings = 147, + NID_policy_constraints = 150, + NID_inhibit_any_policy = 168, /* 2.5.29.54 */ + NID_tlsfeature = 92, /* id-pe 24 */ + NID_commonName = 0x03, /* matchs ASN_COMMON_NAME in asn.h */ + NID_surname = 0x04, /* SN */ + NID_serialNumber = 0x05, /* serialNumber */ + NID_countryName = 0x06, /* C */ + NID_localityName = 0x07, /* L */ + NID_stateOrProvinceName = 0x08, /* ST */ + NID_organizationName = 0x0a, /* O */ + NID_organizationalUnitName = 0x0b, /* OU */ + NID_domainComponent = 0x19, /* matchs ASN_DOMAIN_COMPONENT in asn.h */ + NID_emailAddress = 0x30, /* emailAddress */ +}; + +enum ECC_TYPES +{ + ECC_PREFIX_0 = 160, + ECC_PREFIX_1 = 161 +}; + +#ifdef WOLFSSL_CERT_PIV + enum PIV_Tags { + ASN_PIV_CERT = 0x0A, + ASN_PIV_NONCE = 0x0B, + ASN_PIV_SIGNED_NONCE = 0x0C, + + ASN_PIV_TAG_CERT = 0x70, + ASN_PIV_TAG_CERT_INFO = 0x71, + ASN_PIV_TAG_MSCUID = 0x72, + ASN_PIV_TAG_ERR_DET = 0xFE, + + /* certificate info masks */ + ASN_PIV_CERT_INFO_COMPRESSED = 0x03, + ASN_PIV_CERT_INFO_ISX509 = 0x04, + }; +#endif /* WOLFSSL_CERT_PIV */ + + +#define ASN_JOI_PREFIX "\x2b\x06\x01\x04\x01\x82\x37\x3c\x02\x01" +#define ASN_JOI_C 0x3 +#define ASN_JOI_ST 0x2 + +#ifndef WC_ASN_NAME_MAX + #ifdef OPENSSL_EXTRA + #define WC_ASN_NAME_MAX 300 + #else + #define WC_ASN_NAME_MAX 256 + #endif +#endif +#define ASN_NAME_MAX WC_ASN_NAME_MAX + +enum Misc_ASN { + MAX_SALT_SIZE = 64, /* MAX PKCS Salt length */ + MAX_IV_SIZE = 64, /* MAX PKCS Iv length */ + ASN_BOOL_SIZE = 2, /* including type */ + ASN_ECC_HEADER_SZ = 2, /* String type + 1 byte len */ + ASN_ECC_CONTEXT_SZ = 2, /* Content specific type + 1 byte len */ +#ifdef NO_SHA + KEYID_SIZE = WC_SHA256_DIGEST_SIZE, +#else + KEYID_SIZE = WC_SHA_DIGEST_SIZE, +#endif + RSA_INTS = 8, /* RSA ints in private key */ + DSA_INTS = 5, /* DSA ints in private key */ + MIN_DATE_SIZE = 13, + MAX_DATE_SIZE = 32, + ASN_GEN_TIME_SZ = 15, /* 7 numbers * 2 + Zulu tag */ +#ifndef NO_RSA + MAX_ENCODED_SIG_SZ = 512, +#elif defined(HAVE_ECC) + MAX_ENCODED_SIG_SZ = 140, +#else + MAX_ENCODED_SIG_SZ = 64, +#endif + MAX_SIG_SZ = 256, + MAX_ALGO_SZ = 20, + MAX_SHORT_SZ = 6, /* asn int + byte len + 4 byte length */ + MAX_SEQ_SZ = 5, /* enum(seq | con) + length(4) */ + MAX_SET_SZ = 5, /* enum(set | con) + length(4) */ + MAX_OCTET_STR_SZ = 5, /* enum(set | con) + length(4) */ + MAX_EXP_SZ = 5, /* enum(contextspec|con|exp) + length(4) */ + MAX_PRSTR_SZ = 5, /* enum(prstr) + length(4) */ + MAX_VERSION_SZ = 5, /* enum + id + version(byte) + (header(2))*/ + MAX_ENCODED_DIG_ASN_SZ= 9, /* enum(bit or octet) + length(4) */ + MAX_ENCODED_DIG_SZ = 64 + MAX_ENCODED_DIG_ASN_SZ, /* asn header + sha512 */ + MAX_RSA_INT_SZ = 517, /* RSA raw sz 4096 for bits + tag + len(4) */ + MAX_NTRU_KEY_SZ = 610, /* NTRU 112 bit public key */ + MAX_NTRU_ENC_SZ = 628, /* NTRU 112 bit DER public encoding */ + MAX_LENGTH_SZ = 4, /* Max length size for DER encoding */ + MAX_RSA_E_SZ = 16, /* Max RSA public e size */ + MAX_CA_SZ = 32, /* Max encoded CA basic constraint length */ + MAX_SN_SZ = 35, /* Max encoded serial number (INT) length */ + MAX_DER_DIGEST_SZ = MAX_ENCODED_DIG_SZ + MAX_ALGO_SZ + MAX_SEQ_SZ, + /* Maximum DER digest size */ + MAX_DER_DIGEST_ASN_SZ = MAX_ENCODED_DIG_ASN_SZ + MAX_ALGO_SZ + MAX_SEQ_SZ, + /* Maximum DER digest ASN header size */ +#ifdef WOLFSSL_CERT_GEN + #ifdef WOLFSSL_CERT_REQ + /* Max encoded cert req attributes length */ + MAX_ATTRIB_SZ = MAX_SEQ_SZ * 3 + (11 + MAX_SEQ_SZ) * 2 + + MAX_PRSTR_SZ + CTC_NAME_SIZE, /* 11 is the OID size */ + #endif + #if defined(WOLFSSL_ALT_NAMES) || defined(WOLFSSL_CERT_EXT) + MAX_EXTENSIONS_SZ = 1 + MAX_LENGTH_SZ + CTC_MAX_ALT_SIZE, + #else + MAX_EXTENSIONS_SZ = 1 + MAX_LENGTH_SZ + MAX_CA_SZ, + #endif + /* Max total extensions, id + len + others */ +#endif +#if defined(WOLFSSL_CERT_EXT) || defined(OPENSSL_EXTRA) || defined(HAVE_PKCS7) + MAX_OID_SZ = 32, /* Max DER length of OID*/ + MAX_OID_STRING_SZ = 64, /* Max string length representation of OID*/ +#endif +#ifdef WOLFSSL_CERT_EXT + MAX_KID_SZ = 45, /* Max encoded KID length (SHA-256 case) */ + MAX_KEYUSAGE_SZ = 18, /* Max encoded Key Usage length */ + MAX_EXTKEYUSAGE_SZ = 12 + (6 * (8 + 2)) + + CTC_MAX_EKU_OID_SZ, /* Max encoded ExtKeyUsage + (SEQ/LEN + OBJID + OCTSTR/LEN + SEQ + + (6 * (SEQ + OID))) */ + MAX_CERTPOL_NB = CTC_MAX_CERTPOL_NB,/* Max number of Cert Policy */ + MAX_CERTPOL_SZ = CTC_MAX_CERTPOL_SZ, +#endif + MAX_NAME_ENTRIES = 5, /* extra entries added to x509 name struct */ + OCSP_NONCE_EXT_SZ = 35, /* OCSP Nonce Extension size */ + MAX_OCSP_EXT_SZ = 58, /* Max OCSP Extension length */ + MAX_OCSP_NONCE_SZ = 16, /* OCSP Nonce size */ + EIGHTK_BUF = 8192, /* Tmp buffer size */ + MAX_PUBLIC_KEY_SZ = MAX_NTRU_ENC_SZ + MAX_ALGO_SZ + MAX_SEQ_SZ * 2, + /* use bigger NTRU size */ +#ifdef WOLFSSL_ENCRYPTED_KEYS + HEADER_ENCRYPTED_KEY_SIZE = 88,/* Extra header size for encrypted key */ +#else + HEADER_ENCRYPTED_KEY_SIZE = 0, +#endif + TRAILING_ZERO = 1, /* Used for size of zero pad */ + ASN_TAG_SZ = 1, /* single byte ASN.1 tag */ + MIN_VERSION_SZ = 3, /* Min bytes needed for GetMyVersion */ +#if defined(OPENSSL_ALL) || defined(WOLFSSL_MYSQL_COMPATIBLE) || \ + defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) || \ + defined(OPENSSL_EXTRA) || defined(HAVE_PKCS7) + MAX_TIME_STRING_SZ = 25, /* Max length of formatted time string */ +#endif + + PKCS5_SALT_SZ = 8, + + PEM_LINE_LEN = 80, /* PEM line max + fudge */ +}; + + +enum Oid_Types { + oidHashType = 0, + oidSigType = 1, + oidKeyType = 2, + oidCurveType = 3, + oidBlkType = 4, + oidOcspType = 5, + oidCertExtType = 6, + oidCertAuthInfoType = 7, + oidCertPolicyType = 8, + oidCertAltNameType = 9, + oidCertKeyUseType = 10, + oidKdfType = 11, + oidKeyWrapType = 12, + oidCmsKeyAgreeType = 13, + oidPBEType = 14, + oidHmacType = 15, + oidCompressType = 16, + oidCertNameType = 17, + oidIgnoreType +}; + + +enum Hash_Sum { + MD2h = 646, + MD5h = 649, + SHAh = 88, + SHA224h = 417, + SHA256h = 414, + SHA384h = 415, + SHA512h = 416, + SHA3_224h = 420, + SHA3_256h = 421, + SHA3_384h = 422, + SHA3_512h = 423 +}; + + +#if !defined(NO_DES3) || !defined(NO_AES) +enum Block_Sum { +#ifdef WOLFSSL_AES_128 + AES128CBCb = 414, + AES128GCMb = 418, + AES128CCMb = 419, +#endif +#ifdef WOLFSSL_AES_192 + AES192CBCb = 434, + AES192GCMb = 438, + AES192CCMb = 439, +#endif +#ifdef WOLFSSL_AES_256 + AES256CBCb = 454, + AES256GCMb = 458, + AES256CCMb = 459, +#endif +#ifndef NO_DES3 + DESb = 69, + DES3b = 652 +#endif +}; +#endif /* !NO_DES3 || !NO_AES */ + + +enum Key_Sum { + DSAk = 515, + RSAk = 645, + NTRUk = 274, + ECDSAk = 518, + ED25519k = 256 +}; + + +#if !defined(NO_AES) || defined(HAVE_PKCS7) +enum KeyWrap_Sum { +#ifdef WOLFSSL_AES_128 + AES128_WRAP = 417, +#endif +#ifdef WOLFSSL_AES_192 + AES192_WRAP = 437, +#endif +#ifdef WOLFSSL_AES_256 + AES256_WRAP = 457, +#endif +#ifdef HAVE_PKCS7 + PWRI_KEK_WRAP = 680 /*id-alg-PWRI-KEK, 1.2.840.113549.1.9.16.3.9 */ +#endif +}; +#endif /* !NO_AES || PKCS7 */ + +enum Key_Agree { + dhSinglePass_stdDH_sha1kdf_scheme = 464, + dhSinglePass_stdDH_sha224kdf_scheme = 188, + dhSinglePass_stdDH_sha256kdf_scheme = 189, + dhSinglePass_stdDH_sha384kdf_scheme = 190, + dhSinglePass_stdDH_sha512kdf_scheme = 191, +}; + + + +enum KDF_Sum { + PBKDF2_OID = 660 +}; + + +enum HMAC_Sum { + HMAC_SHA224_OID = 652, + HMAC_SHA256_OID = 653, + HMAC_SHA384_OID = 654, + HMAC_SHA512_OID = 655, + HMAC_SHA3_224_OID = 426, + HMAC_SHA3_256_OID = 427, + HMAC_SHA3_384_OID = 428, + HMAC_SHA3_512_OID = 429 +}; + + +enum Extensions_Sum { + BASIC_CA_OID = 133, + ALT_NAMES_OID = 131, + CRL_DIST_OID = 145, + AUTH_INFO_OID = 69, /* id-pe 1 */ + AUTH_KEY_OID = 149, + SUBJ_KEY_OID = 128, + CERT_POLICY_OID = 146, + KEY_USAGE_OID = 129, /* 2.5.29.15 */ + INHIBIT_ANY_OID = 168, /* 2.5.29.54 */ + EXT_KEY_USAGE_OID = 151, /* 2.5.29.37 */ + NAME_CONS_OID = 144, /* 2.5.29.30 */ + PRIV_KEY_USAGE_PERIOD_OID = 130, /* 2.5.29.16 */ + SUBJECT_INFO_ACCESS = 79, /* id-pe 11 */ + POLICY_MAP_OID = 147, + POLICY_CONST_OID = 150, + ISSUE_ALT_NAMES_OID = 132, + TLS_FEATURE_OID = 92 /* id-pe 24 */ +}; + +enum CertificatePolicy_Sum { + CP_ANY_OID = 146 /* id-ce 32 0 */ +}; + +enum SepHardwareName_Sum { + HW_NAME_OID = 79 /* 1.3.6.1.5.5.7.8.4 from RFC 4108*/ +}; + +enum AuthInfo_Sum { + AIA_OCSP_OID = 116, /* 1.3.6.1.5.5.7.48.1 */ + AIA_CA_ISSUER_OID = 117 /* 1.3.6.1.5.5.7.48.2 */ +}; + +enum ExtKeyUsage_Sum { /* From RFC 5280 */ + EKU_ANY_OID = 151, /* 2.5.29.37.0, anyExtendedKeyUsage */ + EKU_SERVER_AUTH_OID = 71, /* 1.3.6.1.5.5.7.3.1, id-kp-serverAuth */ + EKU_CLIENT_AUTH_OID = 72, /* 1.3.6.1.5.5.7.3.2, id-kp-clientAuth */ + EKU_CODESIGNING_OID = 73, /* 1.3.6.1.5.5.7.3.3, id-kp-codeSigning */ + EKU_EMAILPROTECT_OID = 74, /* 1.3.6.1.5.5.7.3.4, id-kp-emailProtection */ + EKU_TIMESTAMP_OID = 78, /* 1.3.6.1.5.5.7.3.8, id-kp-timeStamping */ + EKU_OCSP_SIGN_OID = 79 /* 1.3.6.1.5.5.7.3.9, id-kp-OCSPSigning */ +}; + +#ifdef HAVE_LIBZ +enum CompressAlg_Sum { + ZLIBc = 679 /* 1.2.840.113549.1.9.16.3.8, id-alg-zlibCompress */ +}; +#endif + +enum VerifyType { + NO_VERIFY = 0, + VERIFY = 1, + VERIFY_CRL = 2, + VERIFY_OCSP = 3, + VERIFY_NAME = 4 +}; + +#ifdef WOLFSSL_CERT_EXT +enum KeyIdType { + SKID_TYPE = 0, + AKID_TYPE = 1 +}; +#endif + +/* Key usage extension bits (based on RFC 5280) */ +#define KEYUSE_DIGITAL_SIG 0x0080 +#define KEYUSE_CONTENT_COMMIT 0x0040 +#define KEYUSE_KEY_ENCIPHER 0x0020 +#define KEYUSE_DATA_ENCIPHER 0x0010 +#define KEYUSE_KEY_AGREE 0x0008 +#define KEYUSE_KEY_CERT_SIGN 0x0004 +#define KEYUSE_CRL_SIGN 0x0002 +#define KEYUSE_ENCIPHER_ONLY 0x0001 +#define KEYUSE_DECIPHER_ONLY 0x8000 + +/* Extended Key Usage bits (internal mapping only) */ +#define EXTKEYUSE_USER 0x80 +#define EXTKEYUSE_OCSP_SIGN 0x40 +#define EXTKEYUSE_TIMESTAMP 0x20 +#define EXTKEYUSE_EMAILPROT 0x10 +#define EXTKEYUSE_CODESIGN 0x08 +#define EXTKEYUSE_CLIENT_AUTH 0x04 +#define EXTKEYUSE_SERVER_AUTH 0x02 +#define EXTKEYUSE_ANY 0x01 + +typedef struct DNS_entry DNS_entry; + +struct DNS_entry { + DNS_entry* next; /* next on DNS list */ + int type; /* i.e. ASN_DNS_TYPE */ + int len; /* actual DNS len */ + char* name; /* actual DNS name */ +}; + + +typedef struct Base_entry Base_entry; + +struct Base_entry { + Base_entry* next; /* next on name base list */ + char* name; /* actual name base */ + int nameSz; /* name length */ + byte type; /* Name base type (DNS or RFC822) */ +}; + +#define DOMAIN_COMPONENT_MAX 10 +#define DN_NAMES_MAX 9 + +struct DecodedName { + char* fullName; + int fullNameLen; + int entryCount; + int cnIdx; + int cnLen; + int cnNid; + int snIdx; + int snLen; + int snNid; + int cIdx; + int cLen; + int cNid; + int lIdx; + int lLen; + int lNid; + int stIdx; + int stLen; + int stNid; + int oIdx; + int oLen; + int oNid; + int ouIdx; + int ouLen; +#ifdef WOLFSSL_CERT_EXT + int bcIdx; + int bcLen; + int jcIdx; + int jcLen; + int jsIdx; + int jsLen; +#endif + int ouNid; + int emailIdx; + int emailLen; + int emailNid; + int uidIdx; + int uidLen; + int uidNid; + int serialIdx; + int serialLen; + int serialNid; + int dcIdx[DOMAIN_COMPONENT_MAX]; + int dcLen[DOMAIN_COMPONENT_MAX]; + int dcNum; + int dcMode; +#ifdef OPENSSL_EXTRA + /* hold the location / order with which each of the DN tags was found + * + * example of ASN_DOMAIN_COMPONENT at index 0 if first found and so on. + */ + int loc[DOMAIN_COMPONENT_MAX + DN_NAMES_MAX]; + int locSz; +#endif +}; + +enum SignatureState { + SIG_STATE_BEGIN, + SIG_STATE_HASH, + SIG_STATE_KEY, + SIG_STATE_DO, + SIG_STATE_CHECK, +}; + + +#ifdef HAVE_PK_CALLBACKS +#ifdef HAVE_ECC + typedef int (*wc_CallbackEccVerify)( + const unsigned char* sig, unsigned int sigSz, + const unsigned char* hash, unsigned int hashSz, + const unsigned char* keyDer, unsigned int keySz, + int* result, void* ctx); +#endif +#ifndef NO_RSA + typedef int (*wc_CallbackRsaVerify)( + unsigned char* sig, unsigned int sigSz, + unsigned char** out, + const unsigned char* keyDer, unsigned int keySz, + void* ctx); +#endif +#endif /* HAVE_PK_CALLBACKS */ + +struct SignatureCtx { + void* heap; + byte* digest; +#ifndef NO_RSA + byte* out; + byte* plain; +#endif +#if defined(HAVE_ECC) || defined(HAVE_ED25519) + int verify; +#endif + union { + #ifndef NO_RSA + struct RsaKey* rsa; + #endif + #ifdef HAVE_ECC + struct ecc_key* ecc; + #endif + #ifdef HAVE_ED25519 + struct ed25519_key* ed25519; + #endif + void* ptr; + } key; + int devId; + int state; + int typeH; + int digestSz; + word32 keyOID; +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV* asyncDev; + void* asyncCtx; +#endif + +#ifdef HAVE_PK_CALLBACKS +#ifdef HAVE_ECC + wc_CallbackEccVerify pkCbEcc; + void* pkCtxEcc; +#endif +#ifndef NO_RSA + wc_CallbackRsaVerify pkCbRsa; + void* pkCtxRsa; +#endif +#endif /* HAVE_PK_CALLBACKS */ +}; + +enum CertSignState { + CERTSIGN_STATE_BEGIN, + CERTSIGN_STATE_DIGEST, + CERTSIGN_STATE_ENCODE, + CERTSIGN_STATE_DO, +}; + +struct CertSignCtx { + byte* sig; + byte* digest; + #ifndef NO_RSA + byte* encSig; + int encSigSz; + #endif + int state; /* enum CertSignState */ +}; + + +typedef struct DecodedCert DecodedCert; +typedef struct DecodedName DecodedName; +typedef struct Signer Signer; +#ifdef WOLFSSL_TRUST_PEER_CERT +typedef struct TrustedPeerCert TrustedPeerCert; +#endif /* WOLFSSL_TRUST_PEER_CERT */ +typedef struct SignatureCtx SignatureCtx; +typedef struct CertSignCtx CertSignCtx; + + +struct DecodedCert { + const byte* publicKey; + word32 pubKeySize; + int pubKeyStored; + word32 certBegin; /* offset to start of cert */ + word32 sigIndex; /* offset to start of signature */ + word32 sigLength; /* length of signature */ + word32 signatureOID; /* sum of algorithm object id */ + word32 keyOID; /* sum of key algo object id */ + int version; /* cert version, 1 or 3 */ + DNS_entry* altNames; /* alt names list of dns entries */ +#ifndef IGNORE_NAME_CONSTRAINTS + DNS_entry* altEmailNames; /* alt names list of RFC822 entries */ + Base_entry* permittedNames; /* Permitted name bases */ + Base_entry* excludedNames; /* Excluded name bases */ +#endif /* IGNORE_NAME_CONSTRAINTS */ + byte subjectHash[KEYID_SIZE]; /* hash of all Names */ + byte issuerHash[KEYID_SIZE]; /* hash of all Names */ +#ifdef HAVE_OCSP + byte subjectKeyHash[KEYID_SIZE]; /* hash of the public Key */ + byte issuerKeyHash[KEYID_SIZE]; /* hash of the public Key */ +#endif /* HAVE_OCSP */ + const byte* signature; /* not owned, points into raw cert */ + char* subjectCN; /* CommonName */ + int subjectCNLen; /* CommonName Length */ + char subjectCNEnc; /* CommonName Encoding */ + char issuer[ASN_NAME_MAX]; /* full name including common name */ + char subject[ASN_NAME_MAX]; /* full name including common name */ + int verify; /* Default to yes, but could be off */ + const byte* source; /* byte buffer holder cert, NOT owner */ + word32 srcIdx; /* current offset into buffer */ + word32 maxIdx; /* max offset based on init size */ + void* heap; /* for user memory overrides */ + byte serial[EXTERNAL_SERIAL_SIZE]; /* raw serial number */ + int serialSz; /* raw serial bytes stored */ + const byte* extensions; /* not owned, points into raw cert */ + int extensionsSz; /* length of cert extensions */ + word32 extensionsIdx; /* if want to go back and parse later */ + const byte* extAuthInfo; /* Authority Information Access URI */ + int extAuthInfoSz; /* length of the URI */ + const byte* extCrlInfo; /* CRL Distribution Points */ + int extCrlInfoSz; /* length of the URI */ + byte extSubjKeyId[KEYID_SIZE]; /* Subject Key ID */ + byte extAuthKeyId[KEYID_SIZE]; /* Authority Key ID */ + byte pathLength; /* CA basic constraint path length */ + word16 extKeyUsage; /* Key usage bitfield */ + byte extExtKeyUsage; /* Extended Key usage bitfield */ + +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + const byte* extExtKeyUsageSrc; + word32 extExtKeyUsageSz; + word32 extExtKeyUsageCount; + const byte* extAuthKeyIdSrc; + word32 extAuthKeyIdSz; + const byte* extSubjKeyIdSrc; + word32 extSubjKeyIdSz; +#endif + +#if defined(HAVE_ECC) || defined(HAVE_ED25519) + word32 pkCurveOID; /* Public Key's curve OID */ +#endif /* HAVE_ECC */ + const byte* beforeDate; + int beforeDateLen; + const byte* afterDate; + int afterDateLen; +#if defined(HAVE_PKCS7) || defined(WOLFSSL_CERT_EXT) + const byte* issuerRaw; /* pointer to issuer inside source */ + int issuerRawLen; +#endif +#ifndef IGNORE_NAME_CONSTRAINT + const byte* subjectRaw; /* pointer to subject inside source */ + int subjectRawLen; +#endif +#if defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_CERT_EXT) + /* easy access to subject info for other sign */ + char* subjectSN; + int subjectSNLen; + char subjectSNEnc; + char* subjectC; + int subjectCLen; + char subjectCEnc; + char* subjectL; + int subjectLLen; + char subjectLEnc; + char* subjectST; + int subjectSTLen; + char subjectSTEnc; + char* subjectO; + int subjectOLen; + char subjectOEnc; + char* subjectOU; + int subjectOULen; + char subjectOUEnc; + char* subjectSND; + int subjectSNDLen; + char subjectSNDEnc; +#ifdef WOLFSSL_CERT_EXT + char* subjectBC; + int subjectBCLen; + char subjectBCEnc; + char* subjectJC; + int subjectJCLen; + char subjectJCEnc; + char* subjectJS; + int subjectJSLen; + char subjectJSEnc; +#endif + char* subjectEmail; + int subjectEmailLen; +#endif /* WOLFSSL_CERT_GEN */ +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + DecodedName issuerName; + DecodedName subjectName; +#endif /* OPENSSL_EXTRA */ +#ifdef WOLFSSL_SEP + int deviceTypeSz; + byte* deviceType; + int hwTypeSz; + byte* hwType; + int hwSerialNumSz; + byte* hwSerialNum; +#endif /* WOLFSSL_SEP */ +#ifdef WOLFSSL_CERT_EXT + char extCertPolicies[MAX_CERTPOL_NB][MAX_CERTPOL_SZ]; + int extCertPoliciesNb; +#endif /* defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_CERT_EXT) */ + + Signer* ca; +#ifndef NO_CERTS + SignatureCtx sigCtx; +#endif + + /* Option Bits */ + byte subjectCNStored : 1; /* have we saved a copy we own */ + byte extSubjKeyIdSet : 1; /* Set when the SKID was read from cert */ + byte extAuthKeyIdSet : 1; /* Set when the AKID was read from cert */ +#ifndef IGNORE_NAME_CONSTRAINTS + byte extNameConstraintSet : 1; +#endif + byte isCA : 1; /* CA basic constraint true */ + byte pathLengthSet : 1; /* CA basic const path length set */ + byte weOwnAltNames : 1; /* altNames haven't been given to copy */ + byte extKeyUsageSet : 1; + byte extExtKeyUsageSet : 1; /* Extended Key Usage set */ + byte extCRLdistSet : 1; + byte extAuthInfoSet : 1; + byte extBasicConstSet : 1; + byte extSubjAltNameSet : 1; + byte inhibitAnyOidSet : 1; + byte selfSigned : 1; /* Indicates subject and issuer are same */ +#ifdef WOLFSSL_SEP + byte extCertPolicySet : 1; +#endif +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) + byte extCRLdistCrit : 1; + byte extAuthInfoCrit : 1; + byte extBasicConstCrit : 1; + byte extSubjAltNameCrit : 1; + byte extAuthKeyIdCrit : 1; + #ifndef IGNORE_NAME_CONSTRAINTS + byte extNameConstraintCrit : 1; + #endif + byte extSubjKeyIdCrit : 1; + byte extKeyUsageCrit : 1; + byte extExtKeyUsageCrit : 1; +#endif /* OPENSSL_EXTRA */ +#ifdef WOLFSSL_SEP + byte extCertPolicyCrit : 1; +#endif + +}; + + +#ifdef NO_SHA + #define SIGNER_DIGEST_SIZE WC_SHA256_DIGEST_SIZE +#else + #define SIGNER_DIGEST_SIZE WC_SHA_DIGEST_SIZE +#endif + +/* CA Signers */ +/* if change layout change PERSIST_CERT_CACHE functions too */ +struct Signer { + word32 pubKeySize; + word32 keyOID; /* key type */ + word16 keyUsage; + byte pathLength; + byte pathLengthSet : 1; + byte selfSigned : 1; + const byte* publicKey; + int nameLen; + char* name; /* common name */ +#ifndef IGNORE_NAME_CONSTRAINTS + Base_entry* permittedNames; + Base_entry* excludedNames; +#endif /* IGNORE_NAME_CONSTRAINTS */ + byte subjectNameHash[SIGNER_DIGEST_SIZE]; + /* sha hash of names in certificate */ + #ifndef NO_SKID + byte subjectKeyIdHash[SIGNER_DIGEST_SIZE]; + /* sha hash of names in certificate */ + #endif + #ifdef HAVE_OCSP + byte subjectKeyHash[KEYID_SIZE]; + #endif +#ifdef WOLFSSL_SIGNER_DER_CERT + DerBuffer* derCert; +#endif + Signer* next; +}; + + +#ifdef WOLFSSL_TRUST_PEER_CERT +/* used for having trusted peer certs rather then CA */ +struct TrustedPeerCert { + int nameLen; + char* name; /* common name */ + #ifndef IGNORE_NAME_CONSTRAINTS + Base_entry* permittedNames; + Base_entry* excludedNames; + #endif /* IGNORE_NAME_CONSTRAINTS */ + byte subjectNameHash[SIGNER_DIGEST_SIZE]; + /* sha hash of names in certificate */ + #ifndef NO_SKID + byte subjectKeyIdHash[SIGNER_DIGEST_SIZE]; + /* sha hash of names in certificate */ + #endif + word32 sigLen; + byte* sig; + struct TrustedPeerCert* next; +}; +#endif /* WOLFSSL_TRUST_PEER_CERT */ + + +/* for testing or custom openssl wrappers */ +#if defined(WOLFSSL_TEST_CERT) || defined(OPENSSL_EXTRA) || \ + defined(OPENSSL_EXTRA_X509_SMALL) + #define WOLFSSL_ASN_API WOLFSSL_API +#else + #define WOLFSSL_ASN_API WOLFSSL_LOCAL +#endif + +WOLFSSL_LOCAL int CalcHashId(const byte* data, word32 len, byte* hash); + +WOLFSSL_ASN_API int wc_BerToDer(const byte* ber, word32 berSz, byte* der, + word32* derSz); + +WOLFSSL_ASN_API void FreeAltNames(DNS_entry*, void*); +#ifndef IGNORE_NAME_CONSTRAINTS + WOLFSSL_ASN_API void FreeNameSubtrees(Base_entry*, void*); +#endif /* IGNORE_NAME_CONSTRAINTS */ +WOLFSSL_ASN_API void InitDecodedCert(DecodedCert*, const byte*, word32, void*); +WOLFSSL_ASN_API void FreeDecodedCert(DecodedCert*); +WOLFSSL_ASN_API int ParseCert(DecodedCert*, int type, int verify, void* cm); + +WOLFSSL_LOCAL int DecodePolicyOID(char *o, word32 oSz, + const byte *in, word32 inSz); +WOLFSSL_LOCAL int EncodePolicyOID(byte *out, word32 *outSz, + const char *in, void* heap); +WOLFSSL_API int CheckCertSignature(const byte*,word32,void*,void* cm); +WOLFSSL_LOCAL int CheckCertSignaturePubKey(const byte* cert, word32 certSz, + void* heap, const byte* pubKey, word32 pubKeySz, int pubKeyOID); +WOLFSSL_LOCAL int ParseCertRelative(DecodedCert*,int type,int verify,void* cm); +WOLFSSL_LOCAL int DecodeToKey(DecodedCert*, int verify); +WOLFSSL_LOCAL int wc_GetPubX509(DecodedCert* cert, int verify, int* badDate); + +WOLFSSL_LOCAL const byte* OidFromId(word32 id, word32 type, word32* oidSz); +WOLFSSL_LOCAL Signer* MakeSigner(void*); +WOLFSSL_LOCAL void FreeSigner(Signer*, void*); +WOLFSSL_LOCAL void FreeSignerTable(Signer**, int, void*); +#ifdef WOLFSSL_TRUST_PEER_CERT +WOLFSSL_LOCAL void FreeTrustedPeer(TrustedPeerCert*, void*); +WOLFSSL_LOCAL void FreeTrustedPeerTable(TrustedPeerCert**, int, void*); +#endif /* WOLFSSL_TRUST_PEER_CERT */ + +WOLFSSL_ASN_API int ToTraditional(byte* buffer, word32 length); +WOLFSSL_ASN_API int ToTraditional_ex(byte* buffer, word32 length, + word32* algId); +WOLFSSL_LOCAL int ToTraditionalInline(const byte* input, word32* inOutIdx, + word32 length); +WOLFSSL_LOCAL int ToTraditionalInline_ex(const byte* input, word32* inOutIdx, + word32 length, word32* algId); +WOLFSSL_LOCAL int ToTraditionalEnc(byte* buffer, word32 length,const char*,int, + word32* algId); +WOLFSSL_ASN_API int UnTraditionalEnc(byte* key, word32 keySz, byte* out, + word32* outSz, const char* password, int passwordSz, int vPKCS, + int vAlgo, byte* salt, word32 saltSz, int itt, WC_RNG* rng, void* heap); +WOLFSSL_ASN_API int TraditionalEnc(byte* key, word32 keySz, byte* out, + word32* outSz, const char* password, int passwordSz, int vPKCS, + int vAlgo, int encAlgId, byte* salt, word32 saltSz, int itt, + WC_RNG* rng, void* heap); +WOLFSSL_LOCAL int DecryptContent(byte* input, word32 sz,const char* psw,int pswSz); +WOLFSSL_LOCAL int EncryptContent(byte* input, word32 sz, byte* out, word32* outSz, + const char* password,int passwordSz, int vPKCS, int vAlgo, + byte* salt, word32 saltSz, int itt, WC_RNG* rng, void* heap); +WOLFSSL_LOCAL int wc_GetKeyOID(byte* key, word32 keySz, const byte** curveOID, + word32* oidSz, int* algoID, void* heap); + +typedef struct tm wolfssl_tm; +#if defined(OPENSSL_ALL) || defined(WOLFSSL_MYSQL_COMPATIBLE) || defined(OPENSSL_EXTRA) || \ + defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) +WOLFSSL_LOCAL int GetTimeString(byte* date, int format, char* buf, int len); +#endif +#if !defined(NO_ASN_TIME) && defined(HAVE_PKCS7) +WOLFSSL_LOCAL int GetAsnTimeString(void* currTime, byte* buf, word32 len); +#endif +WOLFSSL_LOCAL int ExtractDate(const unsigned char* date, unsigned char format, + wolfssl_tm* certTime, int* idx); +WOLFSSL_LOCAL int ValidateDate(const byte* date, byte format, int dateType); +WOLFSSL_LOCAL int wc_OBJ_sn2nid(const char *sn); + +/* ASN.1 helper functions */ +#ifdef WOLFSSL_CERT_GEN +WOLFSSL_ASN_API int SetName(byte* output, word32 outputSz, CertName* name); +#endif +WOLFSSL_LOCAL int GetShortInt(const byte* input, word32* inOutIdx, int* number, + word32 maxIdx); +WOLFSSL_LOCAL char* GetSigName(int oid); +WOLFSSL_LOCAL int GetLength(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx); +WOLFSSL_LOCAL int GetLength_ex(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx, int check); +WOLFSSL_LOCAL int GetSequence(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx); +WOLFSSL_LOCAL int GetSequence_ex(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx, int check); +WOLFSSL_LOCAL int GetSet(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx); +WOLFSSL_LOCAL int GetSet_ex(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx, int check); +WOLFSSL_LOCAL int GetMyVersion(const byte* input, word32* inOutIdx, + int* version, word32 maxIdx); +WOLFSSL_LOCAL int GetInt(mp_int* mpi, const byte* input, word32* inOutIdx, + word32 maxIdx); +#ifdef HAVE_OID_ENCODING + WOLFSSL_LOCAL int EncodeObjectId(const word16* in, word32 inSz, + byte* out, word32* outSz); +#endif +#ifdef HAVE_OID_DECODING + WOLFSSL_LOCAL int DecodeObjectId(const byte* in, word32 inSz, + word16* out, word32* outSz); +#endif +WOLFSSL_LOCAL int GetASNObjectId(const byte* input, word32* inOutIdx, int* len, + word32 maxIdx); +WOLFSSL_LOCAL int SetObjectId(int len, byte* output); +WOLFSSL_LOCAL int GetObjectId(const byte* input, word32* inOutIdx, word32* oid, + word32 oidType, word32 maxIdx); +WOLFSSL_LOCAL int GetAlgoId(const byte* input, word32* inOutIdx, word32* oid, + word32 oidType, word32 maxIdx); +WOLFSSL_LOCAL word32 SetLength(word32 length, byte* output); +WOLFSSL_LOCAL word32 SetSequence(word32 len, byte* output); +WOLFSSL_LOCAL word32 SetOctetString(word32 len, byte* output); +WOLFSSL_LOCAL word32 SetImplicit(byte tag,byte number,word32 len,byte* output); +WOLFSSL_LOCAL word32 SetExplicit(byte number, word32 len, byte* output); +WOLFSSL_LOCAL word32 SetSet(word32 len, byte* output); +WOLFSSL_LOCAL word32 SetAlgoID(int algoOID,byte* output,int type,int curveSz); +WOLFSSL_LOCAL int SetMyVersion(word32 version, byte* output, int header); +WOLFSSL_LOCAL int SetSerialNumber(const byte* sn, word32 snSz, byte* output, + int maxSnSz); +WOLFSSL_LOCAL int GetSerialNumber(const byte* input, word32* inOutIdx, + byte* serial, int* serialSz, word32 maxIdx); +WOLFSSL_LOCAL int GetNameHash(const byte* source, word32* idx, byte* hash, + int maxIdx); +WOLFSSL_LOCAL int wc_CheckPrivateKey(byte* key, word32 keySz, DecodedCert* der); +WOLFSSL_LOCAL int RsaPublicKeyDerSize(RsaKey* key, int with_header); + +#ifdef HAVE_ECC + /* ASN sig helpers */ + WOLFSSL_LOCAL int StoreECC_DSA_Sig(byte* out, word32* outLen, mp_int* r, + mp_int* s); + WOLFSSL_LOCAL int DecodeECC_DSA_Sig(const byte* sig, word32 sigLen, + mp_int* r, mp_int* s); +#endif + +WOLFSSL_LOCAL void InitSignatureCtx(SignatureCtx* sigCtx, void* heap, int devId); +WOLFSSL_LOCAL void FreeSignatureCtx(SignatureCtx* sigCtx); + +#ifndef NO_CERTS + +WOLFSSL_LOCAL int wc_EncryptedInfoParse(EncryptedInfo* info, char** pBuffer, + size_t bufSz); + +WOLFSSL_LOCAL int PemToDer(const unsigned char* buff, long sz, int type, + DerBuffer** pDer, void* heap, EncryptedInfo* info, + int* eccKey); +WOLFSSL_LOCAL int AllocDer(DerBuffer** der, word32 length, int type, void* heap); +WOLFSSL_LOCAL void FreeDer(DerBuffer** der); + +#endif /* !NO_CERTS */ + +#ifdef WOLFSSL_CERT_GEN + +enum cert_enums { +#ifdef WOLFSSL_CERT_EXT + NAME_ENTRIES = 10, +#else + NAME_ENTRIES = 9, +#endif + JOINT_LEN = 2, + EMAIL_JOINT_LEN = 9, + PILOT_JOINT_LEN = 10, + RSA_KEY = 10, + NTRU_KEY = 11, + ECC_KEY = 12, + ED25519_KEY = 13 +}; + +#endif /* WOLFSSL_CERT_GEN */ + + + +/* for pointer use */ +typedef struct CertStatus CertStatus; + +#ifdef HAVE_OCSP + +enum Ocsp_Response_Status { + OCSP_SUCCESSFUL = 0, /* Response has valid confirmations */ + OCSP_MALFORMED_REQUEST = 1, /* Illegal confirmation request */ + OCSP_INTERNAL_ERROR = 2, /* Internal error in issuer */ + OCSP_TRY_LATER = 3, /* Try again later */ + OCSP_SIG_REQUIRED = 5, /* Must sign the request (4 is skipped) */ + OCSP_UNAUTHROIZED = 6 /* Request unauthorized */ +}; + + +enum Ocsp_Cert_Status { + CERT_GOOD = 0, + CERT_REVOKED = 1, + CERT_UNKNOWN = 2 +}; + + +enum Ocsp_Sums { + OCSP_BASIC_OID = 117, + OCSP_NONCE_OID = 118 +}; + +#ifdef OPENSSL_EXTRA +enum Ocsp_Verify_Error { + OCSP_VERIFY_ERROR_NONE = 0, + OCSP_BAD_ISSUER = 1 +}; +#endif + + +typedef struct OcspRequest OcspRequest; +typedef struct OcspResponse OcspResponse; + + +struct CertStatus { + CertStatus* next; + + byte serial[EXTERNAL_SERIAL_SIZE]; + int serialSz; + + int status; + + byte thisDate[MAX_DATE_SIZE]; + byte nextDate[MAX_DATE_SIZE]; + byte thisDateFormat; + byte nextDateFormat; +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + byte* thisDateAsn; + byte* nextDateAsn; +#endif + + byte* rawOcspResponse; + word32 rawOcspResponseSz; +}; + + +struct OcspResponse { + int responseStatus; /* return code from Responder */ + + byte* response; /* Pointer to beginning of OCSP Response */ + word32 responseSz; /* length of the OCSP Response */ + + byte producedDate[MAX_DATE_SIZE]; + /* Date at which this response was signed */ + byte producedDateFormat; /* format of the producedDate */ + byte* issuerHash; + byte* issuerKeyHash; + + byte* cert; + word32 certSz; + + byte* sig; /* Pointer to sig in source */ + word32 sigSz; /* Length in octets for the sig */ + word32 sigOID; /* OID for hash used for sig */ + + CertStatus* status; /* certificate status to fill out */ + + byte* nonce; /* pointer to nonce inside ASN.1 response */ + int nonceSz; /* length of the nonce string */ + + byte* source; /* pointer to source buffer, not owned */ + word32 maxIdx; /* max offset based on init size */ + +#ifdef OPENSSL_EXTRA + int verifyError; +#endif +}; + + +struct OcspRequest { + byte issuerHash[KEYID_SIZE]; + byte issuerKeyHash[KEYID_SIZE]; + byte* serial; /* copy of the serial number in source cert */ + int serialSz; + byte* url; /* copy of the extAuthInfo in source cert */ + int urlSz; + + byte nonce[MAX_OCSP_NONCE_SZ]; + int nonceSz; + void* heap; + void* ssl; +}; + +typedef struct OcspEntry OcspEntry; + +#ifdef NO_SHA +#define OCSP_DIGEST_SIZE WC_SHA256_DIGEST_SIZE +#else +#define OCSP_DIGEST_SIZE WC_SHA_DIGEST_SIZE +#endif + +struct OcspEntry +{ + OcspEntry *next; /* next entry */ + byte issuerHash[OCSP_DIGEST_SIZE]; /* issuer hash */ + byte issuerKeyHash[OCSP_DIGEST_SIZE]; /* issuer public key hash */ + CertStatus *status; /* OCSP response list */ + int totalStatus; /* number on list */ +}; + +WOLFSSL_LOCAL void InitOcspResponse(OcspResponse*, CertStatus*, byte*, word32); +WOLFSSL_LOCAL int OcspResponseDecode(OcspResponse*, void*, void* heap, int); + +WOLFSSL_LOCAL int InitOcspRequest(OcspRequest*, DecodedCert*, byte, void*); +WOLFSSL_LOCAL void FreeOcspRequest(OcspRequest*); +WOLFSSL_LOCAL int EncodeOcspRequest(OcspRequest*, byte*, word32); +WOLFSSL_LOCAL word32 EncodeOcspRequestExtensions(OcspRequest*, byte*, word32); + + +WOLFSSL_LOCAL int CompareOcspReqResp(OcspRequest*, OcspResponse*); + + +#endif /* HAVE_OCSP */ + + +/* for pointer use */ +typedef struct RevokedCert RevokedCert; + +#ifdef HAVE_CRL + +struct RevokedCert { + byte serialNumber[EXTERNAL_SERIAL_SIZE]; + int serialSz; + RevokedCert* next; +}; + +typedef struct DecodedCRL DecodedCRL; + +struct DecodedCRL { + word32 certBegin; /* offset to start of cert */ + word32 sigIndex; /* offset to start of signature */ + word32 sigLength; /* length of signature */ + word32 signatureOID; /* sum of algorithm object id */ + byte* signature; /* pointer into raw source, not owned */ + byte issuerHash[SIGNER_DIGEST_SIZE]; /* issuer hash */ + byte crlHash[SIGNER_DIGEST_SIZE]; /* raw crl data hash */ + byte lastDate[MAX_DATE_SIZE]; /* last date updated */ + byte nextDate[MAX_DATE_SIZE]; /* next update date */ + byte lastDateFormat; /* format of last date */ + byte nextDateFormat; /* format of next date */ + RevokedCert* certs; /* revoked cert list */ + int totalCerts; /* number on list */ + void* heap; +}; + +WOLFSSL_LOCAL void InitDecodedCRL(DecodedCRL*, void* heap); +WOLFSSL_LOCAL int VerifyCRL_Signature(SignatureCtx* sigCtx, + const byte* toBeSigned, word32 tbsSz, + const byte* signature, word32 sigSz, + word32 signatureOID, Signer *ca, + void* heap); +WOLFSSL_LOCAL int ParseCRL(DecodedCRL*, const byte* buff, word32 sz, void* cm); +WOLFSSL_LOCAL void FreeDecodedCRL(DecodedCRL*); + + +#endif /* HAVE_CRL */ + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* !NO_ASN */ + + +#if !defined(NO_ASN) || !defined(NO_PWDBASED) + +#ifndef MAX_KEY_SIZE + #define MAX_KEY_SIZE 64 /* MAX PKCS Key length */ +#endif +#ifndef MAX_UNICODE_SZ + #define MAX_UNICODE_SZ 256 +#endif + +enum PBESTypes { + PBE_MD5_DES = 0, + PBE_SHA1_RC4_128 = 1, + PBE_SHA1_DES = 2, + PBE_SHA1_DES3 = 3, + PBE_AES256_CBC = 4, + + PBE_SHA1_RC4_128_SUM = 657, + PBE_SHA1_DES3_SUM = 659, + PBES2 = 13 /* algo ID */ +}; + +enum PKCSTypes { + PKCS5v2 = 6, /* PKCS #5 v2.0 */ + PKCS12v1 = 12, /* PKCS #12 */ + PKCS5 = 5, /* PKCS oid tag */ + PKCS8v0 = 0, /* default PKCS#8 version */ +}; + +#endif /* !NO_ASN || !NO_PWDBASED */ + +#endif /* WOLF_CRYPT_ASN_H */ diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/asn_public.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/asn_public.h new file mode 100755 index 0000000..9f5371e --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/asn_public.h @@ -0,0 +1,555 @@ +/* asn_public.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/*! + \file wolfssl/wolfcrypt/asn_public.h +*/ + +#ifndef WOLF_CRYPT_ASN_PUBLIC_H +#define WOLF_CRYPT_ASN_PUBLIC_H + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/* guard on redeclaration */ +#ifndef WC_ECCKEY_TYPE_DEFINED + typedef struct ecc_key ecc_key; + #define WC_ECCKEY_TYPE_DEFINED +#endif +#ifndef WC_ED25519KEY_TYPE_DEFINED + typedef struct ed25519_key ed25519_key; + #define WC_ED25519KEY_TYPE_DEFINED +#endif +#ifndef WC_RSAKEY_TYPE_DEFINED + typedef struct RsaKey RsaKey; + #define WC_RSAKEY_TYPE_DEFINED +#endif +#ifndef WC_RNG_TYPE_DEFINED + typedef struct WC_RNG WC_RNG; + #define WC_RNG_TYPE_DEFINED +#endif + +enum Ecc_Sum { + ECC_SECP112R1_OID = 182, + ECC_SECP112R2_OID = 183, + ECC_SECP128R1_OID = 204, + ECC_SECP128R2_OID = 205, + ECC_SECP160R1_OID = 184, + ECC_SECP160R2_OID = 206, + ECC_SECP160K1_OID = 185, + ECC_BRAINPOOLP160R1_OID = 98, + ECC_SECP192R1_OID = 520, + ECC_PRIME192V2_OID = 521, + ECC_PRIME192V3_OID = 522, + ECC_SECP192K1_OID = 207, + ECC_BRAINPOOLP192R1_OID = 100, + ECC_SECP224R1_OID = 209, + ECC_SECP224K1_OID = 208, + ECC_BRAINPOOLP224R1_OID = 102, + ECC_PRIME239V1_OID = 523, + ECC_PRIME239V2_OID = 524, + ECC_PRIME239V3_OID = 525, + ECC_SECP256R1_OID = 526, + ECC_SECP256K1_OID = 186, + ECC_BRAINPOOLP256R1_OID = 104, + ECC_X25519_OID = 365, + ECC_ED25519_OID = 256, + ECC_BRAINPOOLP320R1_OID = 106, + ECC_SECP384R1_OID = 210, + ECC_BRAINPOOLP384R1_OID = 108, + ECC_BRAINPOOLP512R1_OID = 110, + ECC_SECP521R1_OID = 211, +}; + + +/* Certificate file Type */ +enum CertType { + CERT_TYPE = 0, + PRIVATEKEY_TYPE, + DH_PARAM_TYPE, + DSA_PARAM_TYPE, + CRL_TYPE, + CA_TYPE, + ECC_PRIVATEKEY_TYPE, + DSA_PRIVATEKEY_TYPE, + CERTREQ_TYPE, + DSA_TYPE, + ECC_TYPE, + RSA_TYPE, + PUBLICKEY_TYPE, + RSA_PUBLICKEY_TYPE, + ECC_PUBLICKEY_TYPE, + TRUSTED_PEER_TYPE, + EDDSA_PRIVATEKEY_TYPE, + ED25519_TYPE, + PKCS12_TYPE, + PKCS8_PRIVATEKEY_TYPE, + PKCS8_ENC_PRIVATEKEY_TYPE +}; + + +/* Signature type, by OID sum */ +enum Ctc_SigType { + CTC_SHAwDSA = 517, + CTC_MD2wRSA = 646, + CTC_MD5wRSA = 648, + CTC_SHAwRSA = 649, + CTC_SHAwECDSA = 520, + CTC_SHA224wRSA = 658, + CTC_SHA224wECDSA = 523, + CTC_SHA256wRSA = 655, + CTC_SHA256wECDSA = 524, + CTC_SHA384wRSA = 656, + CTC_SHA384wECDSA = 525, + CTC_SHA512wRSA = 657, + CTC_SHA512wECDSA = 526, + CTC_ED25519 = 256 +}; + +enum Ctc_Encoding { + CTC_UTF8 = 0x0c, /* utf8 */ + CTC_PRINTABLE = 0x13 /* printable */ +}; + +#ifndef WC_CTC_NAME_SIZE + #define WC_CTC_NAME_SIZE 64 +#endif +#ifndef WC_CTC_MAX_ALT_SIZE + #define WC_CTC_MAX_ALT_SIZE 16384 +#endif + +enum Ctc_Misc { + CTC_COUNTRY_SIZE = 2, + CTC_NAME_SIZE = WC_CTC_NAME_SIZE, + CTC_DATE_SIZE = 32, + CTC_MAX_ALT_SIZE = WC_CTC_MAX_ALT_SIZE, /* may be huge, default: 16384 */ + CTC_SERIAL_SIZE = 16, +#ifdef WOLFSSL_CERT_EXT + /* AKID could contains: hash + (Option) AuthCertIssuer,AuthCertSerialNum + * We support only hash */ + CTC_MAX_SKID_SIZE = 32, /* SHA256_DIGEST_SIZE */ + CTC_MAX_AKID_SIZE = 32, /* SHA256_DIGEST_SIZE */ + CTC_MAX_CERTPOL_SZ = 64, + CTC_MAX_CERTPOL_NB = 2 /* Max number of Certificate Policy */ +#endif /* WOLFSSL_CERT_EXT */ +}; + +/* DER buffer */ +typedef struct DerBuffer { + byte* buffer; + void* heap; + word32 length; + int type; /* enum CertType */ + int dynType; /* DYNAMIC_TYPE_* */ +} DerBuffer; + +enum { + IV_SZ = 32, /* max iv sz */ + NAME_SZ = 80, /* max one line */ + + PEM_PASS_READ = 0, + PEM_PASS_WRITE = 1, +}; + + +typedef int (pem_password_cb)(char* passwd, int sz, int rw, void* userdata); + +typedef struct EncryptedInfo { + pem_password_cb* passwd_cb; + void* passwd_userdata; + + long consumed; /* tracks PEM bytes consumed */ + + int cipherType; + word32 keySz; + word32 ivSz; /* salt or encrypted IV size */ + + char name[NAME_SZ]; /* cipher name, such as "DES-CBC" */ + byte iv[IV_SZ]; /* salt or encrypted IV */ + + word16 set:1; /* if encryption set */ +} EncryptedInfo; + + +#if defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_CERT_EXT) +#ifdef WOLFSSL_EKU_OID + #ifndef CTC_MAX_EKU_NB + #define CTC_MAX_EKU_NB 1 + #endif + #ifndef CTC_MAX_EKU_OID_SZ + #define CTC_MAX_EKU_OID_SZ 30 + #endif +#else + #undef CTC_MAX_EKU_OID_SZ + #define CTC_MAX_EKU_OID_SZ 0 +#endif +#endif /* WOLFSSL_CERT_GEN || WOLFSSL_CERT_EXT */ + +#ifdef WOLFSSL_CERT_GEN + +#ifdef WOLFSSL_MULTI_ATTRIB +#ifndef CTC_MAX_ATTRIB + #define CTC_MAX_ATTRIB 4 +#endif + +/* ASN Encoded Name field */ +typedef struct NameAttrib { + int sz; /* actual string value length */ + int id; /* id of name */ + int type; /* enc of name */ + char value[CTC_NAME_SIZE]; /* name */ +} NameAttrib; +#endif /* WOLFSSL_MULTI_ATTRIB */ + + +typedef struct CertName { + char country[CTC_NAME_SIZE]; + char countryEnc; + char state[CTC_NAME_SIZE]; + char stateEnc; + char locality[CTC_NAME_SIZE]; + char localityEnc; + char sur[CTC_NAME_SIZE]; + char surEnc; + char org[CTC_NAME_SIZE]; + char orgEnc; + char unit[CTC_NAME_SIZE]; + char unitEnc; + char commonName[CTC_NAME_SIZE]; + char commonNameEnc; + char serialDev[CTC_NAME_SIZE]; + char serialDevEnc; +#ifdef WOLFSSL_CERT_EXT + char busCat[CTC_NAME_SIZE]; + char busCatEnc; + char joiC[CTC_NAME_SIZE]; + char joiCEnc; + char joiSt[CTC_NAME_SIZE]; + char joiStEnc; +#endif + char email[CTC_NAME_SIZE]; /* !!!! email has to be last !!!! */ +#ifdef WOLFSSL_MULTI_ATTRIB + NameAttrib name[CTC_MAX_ATTRIB]; +#endif +} CertName; + + +/* for user to fill for certificate generation */ +typedef struct Cert { + int version; /* x509 version */ + byte serial[CTC_SERIAL_SIZE]; /* serial number */ + int serialSz; /* serial size */ + int sigType; /* signature algo type */ + CertName issuer; /* issuer info */ + int daysValid; /* validity days */ + int selfSigned; /* self signed flag */ + CertName subject; /* subject info */ + int isCA; /* is this going to be a CA */ + /* internal use only */ + int bodySz; /* pre sign total size */ + int keyType; /* public key type of subject */ +#ifdef WOLFSSL_ALT_NAMES + byte altNames[CTC_MAX_ALT_SIZE]; /* altNames copy */ + int altNamesSz; /* altNames size in bytes */ + byte beforeDate[CTC_DATE_SIZE]; /* before date copy */ + int beforeDateSz; /* size of copy */ + byte afterDate[CTC_DATE_SIZE]; /* after date copy */ + int afterDateSz; /* size of copy */ +#endif +#ifdef WOLFSSL_CERT_EXT + byte skid[CTC_MAX_SKID_SIZE]; /* Subject Key Identifier */ + int skidSz; /* SKID size in bytes */ + byte akid[CTC_MAX_AKID_SIZE]; /* Authority Key Identifier */ + int akidSz; /* AKID size in bytes */ + word16 keyUsage; /* Key Usage */ + byte extKeyUsage; /* Extended Key Usage */ +#ifdef WOLFSSL_EKU_OID + /* Extended Key Usage OIDs */ + byte extKeyUsageOID[CTC_MAX_EKU_NB][CTC_MAX_EKU_OID_SZ]; + byte extKeyUsageOIDSz[CTC_MAX_EKU_NB]; +#endif + char certPolicies[CTC_MAX_CERTPOL_NB][CTC_MAX_CERTPOL_SZ]; + word16 certPoliciesNb; /* Number of Cert Policy */ + byte issRaw[sizeof(CertName)]; /* raw issuer info */ + byte sbjRaw[sizeof(CertName)]; /* raw subject info */ +#endif +#ifdef WOLFSSL_CERT_REQ + char challengePw[CTC_NAME_SIZE]; + int challengePwPrintableString; /* encode as PrintableString */ +#endif + void* decodedCert; /* internal DecodedCert allocated from heap */ + byte* der; /* Pointer to buffer of current DecodedCert cache */ + void* heap; /* heap hint */ +} Cert; + + + +/* Initialize and Set Certificate defaults: + version = 3 (0x2) + serial = 0 (Will be randomly generated) + sigType = SHA_WITH_RSA + issuer = blank + daysValid = 500 + selfSigned = 1 (true) use subject as issuer + subject = blank + isCA = 0 (false) + keyType = RSA_KEY (default) +*/ +WOLFSSL_API int wc_InitCert(Cert*); +WOLFSSL_API int wc_MakeCert_ex(Cert* cert, byte* derBuffer, word32 derSz, + int keyType, void* key, WC_RNG* rng); +WOLFSSL_API int wc_MakeCert(Cert*, byte* derBuffer, word32 derSz, RsaKey*, + ecc_key*, WC_RNG*); +#ifdef WOLFSSL_CERT_REQ + WOLFSSL_API int wc_MakeCertReq_ex(Cert*, byte* derBuffer, word32 derSz, + int, void*); + WOLFSSL_API int wc_MakeCertReq(Cert*, byte* derBuffer, word32 derSz, + RsaKey*, ecc_key*); +#endif +WOLFSSL_API int wc_SignCert_ex(int requestSz, int sType, byte* buffer, + word32 buffSz, int keyType, void* key, + WC_RNG* rng); +WOLFSSL_API int wc_SignCert(int requestSz, int sigType, byte* derBuffer, + word32 derSz, RsaKey*, ecc_key*, WC_RNG*); +WOLFSSL_API int wc_MakeSelfCert(Cert*, byte* derBuffer, word32 derSz, RsaKey*, + WC_RNG*); +WOLFSSL_API int wc_SetIssuer(Cert*, const char*); +WOLFSSL_API int wc_SetSubject(Cert*, const char*); +#ifdef WOLFSSL_ALT_NAMES + WOLFSSL_API int wc_SetAltNames(Cert*, const char*); +#endif + +#ifdef WOLFSSL_CERT_GEN_CACHE +WOLFSSL_API void wc_SetCert_Free(Cert* cert); +#endif + +WOLFSSL_API int wc_SetIssuerBuffer(Cert*, const byte*, int); +WOLFSSL_API int wc_SetSubjectBuffer(Cert*, const byte*, int); +WOLFSSL_API int wc_SetAltNamesBuffer(Cert*, const byte*, int); +WOLFSSL_API int wc_SetDatesBuffer(Cert*, const byte*, int); + +#ifndef NO_ASN_TIME +WOLFSSL_API int wc_GetCertDates(Cert* cert, struct tm* before, + struct tm* after); +#endif + +#ifdef WOLFSSL_CERT_EXT +WOLFSSL_API int wc_SetAuthKeyIdFromPublicKey_ex(Cert *cert, int keyType, + void* key); +WOLFSSL_API int wc_SetAuthKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, + ecc_key *eckey); +WOLFSSL_API int wc_SetAuthKeyIdFromCert(Cert *cert, const byte *der, int derSz); +WOLFSSL_API int wc_SetAuthKeyId(Cert *cert, const char* file); +WOLFSSL_API int wc_SetSubjectKeyIdFromPublicKey_ex(Cert *cert, int keyType, + void* key); +WOLFSSL_API int wc_SetSubjectKeyIdFromPublicKey(Cert *cert, RsaKey *rsakey, + ecc_key *eckey); +WOLFSSL_API int wc_SetSubjectKeyId(Cert *cert, const char* file); +WOLFSSL_API int wc_GetSubjectRaw(byte **subjectRaw, Cert *cert); +WOLFSSL_API int wc_SetSubjectRaw(Cert* cert, const byte* der, int derSz); +WOLFSSL_API int wc_SetIssuerRaw(Cert* cert, const byte* der, int derSz); + +#ifdef HAVE_NTRU +WOLFSSL_API int wc_SetSubjectKeyIdFromNtruPublicKey(Cert *cert, byte *ntruKey, + word16 ntruKeySz); +#endif + +/* Set the KeyUsage. + * Value is a string separated tokens with ','. Accepted tokens are : + * digitalSignature,nonRepudiation,contentCommitment,keyCertSign,cRLSign, + * dataEncipherment,keyAgreement,keyEncipherment,encipherOnly and decipherOnly. + * + * nonRepudiation and contentCommitment are for the same usage. + */ +WOLFSSL_API int wc_SetKeyUsage(Cert *cert, const char *value); + +/* Set ExtendedKeyUsage + * Value is a string separated tokens with ','. Accepted tokens are : + * any,serverAuth,clientAuth,codeSigning,emailProtection,timeStamping,OCSPSigning + */ +WOLFSSL_API int wc_SetExtKeyUsage(Cert *cert, const char *value); + + +#ifdef WOLFSSL_EKU_OID +/* Set ExtendedKeyUsage with unique OID + * oid is expected to be in byte representation + */ +WOLFSSL_API int wc_SetExtKeyUsageOID(Cert *cert, const char *oid, word32 sz, + byte idx, void* heap); +#endif /* WOLFSSL_EKU_OID */ +#endif /* WOLFSSL_CERT_EXT */ + + #ifdef HAVE_NTRU + WOLFSSL_API int wc_MakeNtruCert(Cert*, byte* derBuffer, word32 derSz, + const byte* ntruKey, word16 keySz, + WC_RNG*); + #endif + +#endif /* WOLFSSL_CERT_GEN */ + +WOLFSSL_API int wc_GetDateInfo(const byte* certDate, int certDateSz, + const byte** date, byte* format, int* length); +#ifndef NO_ASN_TIME +WOLFSSL_API int wc_GetDateAsCalendarTime(const byte* date, int length, + byte format, struct tm* time); +#endif + +#if defined(WOLFSSL_PEM_TO_DER) || defined(WOLFSSL_DER_TO_PEM) + + WOLFSSL_API int wc_PemGetHeaderFooter(int type, const char** header, + const char** footer); + +#endif + +WOLFSSL_API int wc_AllocDer(DerBuffer** pDer, word32 length, int type, void* heap); +WOLFSSL_API void wc_FreeDer(DerBuffer** pDer); + +#ifdef WOLFSSL_PEM_TO_DER + WOLFSSL_API int wc_PemToDer(const unsigned char* buff, long longSz, int type, + DerBuffer** pDer, void* heap, EncryptedInfo* info, int* eccKey); + + WOLFSSL_API int wc_KeyPemToDer(const unsigned char*, int, + unsigned char*, int, const char*); + WOLFSSL_API int wc_CertPemToDer(const unsigned char*, int, + unsigned char*, int, int); +#endif /* WOLFSSL_PEM_TO_DER */ + +#if defined(WOLFSSL_CERT_EXT) || defined(WOLFSSL_PUB_PEM_TO_DER) + #ifndef NO_FILESYSTEM + WOLFSSL_API int wc_PemPubKeyToDer(const char* fileName, + unsigned char* derBuf, int derSz); + #endif + + WOLFSSL_API int wc_PubKeyPemToDer(const unsigned char*, int, + unsigned char*, int); +#endif /* WOLFSSL_CERT_EXT || WOLFSSL_PUB_PEM_TO_DER */ + +#ifdef WOLFSSL_CERT_GEN + #ifndef NO_FILESYSTEM + WOLFSSL_API int wc_PemCertToDer(const char* fileName, + unsigned char* derBuf, int derSz); + #endif +#endif /* WOLFSSL_CERT_GEN */ + +#ifdef WOLFSSL_DER_TO_PEM + WOLFSSL_API int wc_DerToPem(const byte* der, word32 derSz, byte* output, + word32 outputSz, int type); + WOLFSSL_API int wc_DerToPemEx(const byte* der, word32 derSz, byte* output, + word32 outputSz, byte *cipherIno, int type); +#endif + +#if !defined(NO_RSA) && !defined(HAVE_USER_RSA) + WOLFSSL_API int wc_RsaPublicKeyDecode_ex(const byte* input, word32* inOutIdx, + word32 inSz, const byte** n, word32* nSz, const byte** e, word32* eSz); +#endif + +#ifdef HAVE_ECC + /* private key helpers */ + WOLFSSL_API int wc_EccPrivateKeyDecode(const byte*, word32*, + ecc_key*, word32); + WOLFSSL_API int wc_EccKeyToDer(ecc_key*, byte* output, word32 inLen); + WOLFSSL_API int wc_EccPrivateKeyToDer(ecc_key* key, byte* output, + word32 inLen); + WOLFSSL_API int wc_EccPrivateKeyToPKCS8(ecc_key* key, byte* output, + word32* outLen); + + /* public key helper */ + WOLFSSL_API int wc_EccPublicKeyDecode(const byte*, word32*, + ecc_key*, word32); + WOLFSSL_API int wc_EccPublicKeyToDer(ecc_key*, byte* output, + word32 inLen, int with_AlgCurve); +#endif + +#ifdef HAVE_ED25519 + /* private key helpers */ + WOLFSSL_API int wc_Ed25519PrivateKeyDecode(const byte*, word32*, + ed25519_key*, word32); + WOLFSSL_API int wc_Ed25519KeyToDer(ed25519_key* key, byte* output, + word32 inLen); + WOLFSSL_API int wc_Ed25519PrivateKeyToDer(ed25519_key* key, byte* output, + word32 inLen); + + /* public key helper */ + WOLFSSL_API int wc_Ed25519PublicKeyDecode(const byte*, word32*, + ed25519_key*, word32); + #if (defined(WOLFSSL_CERT_GEN) || defined(WOLFSSL_KEY_GEN)) + WOLFSSL_API int wc_Ed25519PublicKeyToDer(ed25519_key*, byte* output, + word32 inLen, int with_AlgCurve); + #endif +#endif + +/* DER encode signature */ +WOLFSSL_API word32 wc_EncodeSignature(byte* out, const byte* digest, + word32 digSz, int hashOID); +WOLFSSL_API int wc_GetCTC_HashOID(int type); + +WOLFSSL_API int wc_GetPkcs8TraditionalOffset(byte* input, + word32* inOutIdx, word32 sz); +WOLFSSL_API int wc_CreatePKCS8Key(byte* out, word32* outSz, + byte* key, word32 keySz, int algoID, const byte* curveOID, word32 oidSz); + +#ifndef NO_ASN_TIME +/* Time */ +/* Returns seconds (Epoch/UTC) + * timePtr: is "time_t", which is typically "long" + * Example: + long lTime; + rc = wc_GetTime(&lTime, (word32)sizeof(lTime)); +*/ +WOLFSSL_API int wc_GetTime(void* timePtr, word32 timeSize); +#endif + +#ifdef WOLFSSL_ENCRYPTED_KEYS + WOLFSSL_API int wc_EncryptedInfoGet(EncryptedInfo* info, + const char* cipherInfo); +#endif + + +#ifdef WOLFSSL_CERT_PIV + +typedef struct _wc_CertPIV { + const byte* cert; + word32 certSz; + const byte* certErrDet; + word32 certErrDetSz; + const byte* nonce; /* Identiv Only */ + word32 nonceSz; /* Identiv Only */ + const byte* signedNonce; /* Identiv Only */ + word32 signedNonceSz; /* Identiv Only */ + + /* flags */ + word16 compression:2; + word16 isX509:1; + word16 isIdentiv:1; +} wc_CertPIV; + +WOLFSSL_API int wc_ParseCertPIV(wc_CertPIV* cert, const byte* buf, word32 totalSz); +#endif /* WOLFSSL_CERT_PIV */ + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLF_CRYPT_ASN_PUBLIC_H */ diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/blake2-impl.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/blake2-impl.h new file mode 100755 index 0000000..6c43d81 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/blake2-impl.h @@ -0,0 +1,155 @@ +/* + BLAKE2 reference source code package - reference C implementations + + Written in 2012 by Samuel Neves + + To the extent possible under law, the author(s) have dedicated all copyright + and related and neighboring rights to this software to the public domain + worldwide. This software is distributed without any warranty. + + You should have received a copy of the CC0 Public Domain Dedication along with + this software. If not, see . +*/ +/* blake2-impl.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifndef WOLFCRYPT_BLAKE2_IMPL_H +#define WOLFCRYPT_BLAKE2_IMPL_H + +#include + +static WC_INLINE word32 load32( const void *src ) +{ +#if defined(LITTLE_ENDIAN_ORDER) + return *( word32 * )( src ); +#else + const byte *p = ( byte * )src; + word32 w = *p++; + w |= ( word32 )( *p++ ) << 8; + w |= ( word32 )( *p++ ) << 16; + w |= ( word32 )( *p++ ) << 24; + return w; +#endif +} + +static WC_INLINE word64 load64( const void *src ) +{ +#if defined(LITTLE_ENDIAN_ORDER) + return *( word64 * )( src ); +#else + const byte *p = ( byte * )src; + word64 w = *p++; + w |= ( word64 )( *p++ ) << 8; + w |= ( word64 )( *p++ ) << 16; + w |= ( word64 )( *p++ ) << 24; + w |= ( word64 )( *p++ ) << 32; + w |= ( word64 )( *p++ ) << 40; + w |= ( word64 )( *p++ ) << 48; + w |= ( word64 )( *p++ ) << 56; + return w; +#endif +} + +static WC_INLINE void store32( void *dst, word32 w ) +{ +#if defined(LITTLE_ENDIAN_ORDER) + *( word32 * )( dst ) = w; +#else + byte *p = ( byte * )dst; + *p++ = ( byte )w; w >>= 8; + *p++ = ( byte )w; w >>= 8; + *p++ = ( byte )w; w >>= 8; + *p++ = ( byte )w; +#endif +} + +static WC_INLINE void store64( void *dst, word64 w ) +{ +#if defined(LITTLE_ENDIAN_ORDER) + *( word64 * )( dst ) = w; +#else + byte *p = ( byte * )dst; + *p++ = ( byte )w; w >>= 8; + *p++ = ( byte )w; w >>= 8; + *p++ = ( byte )w; w >>= 8; + *p++ = ( byte )w; w >>= 8; + *p++ = ( byte )w; w >>= 8; + *p++ = ( byte )w; w >>= 8; + *p++ = ( byte )w; w >>= 8; + *p++ = ( byte )w; +#endif +} + +static WC_INLINE word64 load48( const void *src ) +{ + const byte *p = ( const byte * )src; + word64 w = *p++; + w |= ( word64 )( *p++ ) << 8; + w |= ( word64 )( *p++ ) << 16; + w |= ( word64 )( *p++ ) << 24; + w |= ( word64 )( *p++ ) << 32; + w |= ( word64 )( *p++ ) << 40; + return w; +} + +static WC_INLINE void store48( void *dst, word64 w ) +{ + byte *p = ( byte * )dst; + *p++ = ( byte )w; w >>= 8; + *p++ = ( byte )w; w >>= 8; + *p++ = ( byte )w; w >>= 8; + *p++ = ( byte )w; w >>= 8; + *p++ = ( byte )w; w >>= 8; + *p++ = ( byte )w; +} + +static WC_INLINE word32 rotl32( const word32 w, const unsigned c ) +{ + return ( w << c ) | ( w >> ( 32 - c ) ); +} + +static WC_INLINE word64 rotl64( const word64 w, const unsigned c ) +{ + return ( w << c ) | ( w >> ( 64 - c ) ); +} + +static WC_INLINE word32 rotr32( const word32 w, const unsigned c ) +{ + return ( w >> c ) | ( w << ( 32 - c ) ); +} + +static WC_INLINE word64 rotr64( const word64 w, const unsigned c ) +{ + return ( w >> c ) | ( w << ( 64 - c ) ); +} + +/* prevents compiler optimizing out memset() */ +static WC_INLINE void secure_zero_memory( void *v, word64 n ) +{ + volatile byte *p = ( volatile byte * )v; + + while( n-- ) *p++ = 0; +} + +#endif /* WOLFCRYPT_BLAKE2_IMPL_H */ + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/blake2-int.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/blake2-int.h new file mode 100755 index 0000000..ac736b1 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/blake2-int.h @@ -0,0 +1,184 @@ +/* + BLAKE2 reference source code package - reference C implementations + + Written in 2012 by Samuel Neves + + To the extent possible under law, the author(s) have dedicated all copyright + and related and neighboring rights to this software to the public domain + worldwide. This software is distributed without any warranty. + + You should have received a copy of the CC0 Public Domain Dedication along with + this software. If not, see . +*/ +/* blake2-int.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + + +#ifndef WOLFCRYPT_BLAKE2_INT_H +#define WOLFCRYPT_BLAKE2_INT_H + +#include + + +#if defined(_MSC_VER) + #define ALIGN(x) __declspec(align(x)) +#elif defined(__GNUC__) + #define ALIGN(x) __attribute__((aligned(x))) +#else + #define ALIGN(x) +#endif + + +#if defined(__cplusplus) + extern "C" { +#endif + + enum blake2s_constant + { + BLAKE2S_BLOCKBYTES = 64, + BLAKE2S_OUTBYTES = 32, + BLAKE2S_KEYBYTES = 32, + BLAKE2S_SALTBYTES = 8, + BLAKE2S_PERSONALBYTES = 8 + }; + + enum blake2b_constant + { + BLAKE2B_BLOCKBYTES = 128, + BLAKE2B_OUTBYTES = 64, + BLAKE2B_KEYBYTES = 64, + BLAKE2B_SALTBYTES = 16, + BLAKE2B_PERSONALBYTES = 16 + }; + +#pragma pack(push, 1) + typedef struct __blake2s_param + { + byte digest_length; /* 1 */ + byte key_length; /* 2 */ + byte fanout; /* 3 */ + byte depth; /* 4 */ + word32 leaf_length; /* 8 */ + byte node_offset[6];/* 14 */ + byte node_depth; /* 15 */ + byte inner_length; /* 16 */ + /* byte reserved[0]; */ + byte salt[BLAKE2B_SALTBYTES]; /* 24 */ + byte personal[BLAKE2S_PERSONALBYTES]; /* 32 */ + } blake2s_param; + + ALIGN( 32 ) typedef struct __blake2s_state + { + word32 h[8]; + word32 t[2]; + word32 f[2]; + byte buf[2 * BLAKE2S_BLOCKBYTES]; + word32 buflen; + byte last_node; + } blake2s_state ; + + typedef struct __blake2b_param + { + byte digest_length; /* 1 */ + byte key_length; /* 2 */ + byte fanout; /* 3 */ + byte depth; /* 4 */ + word32 leaf_length; /* 8 */ + word64 node_offset; /* 16 */ + byte node_depth; /* 17 */ + byte inner_length; /* 18 */ + byte reserved[14]; /* 32 */ + byte salt[BLAKE2B_SALTBYTES]; /* 48 */ + byte personal[BLAKE2B_PERSONALBYTES]; /* 64 */ + } blake2b_param; + + ALIGN( 64 ) typedef struct __blake2b_state + { + word64 h[8]; + word64 t[2]; + word64 f[2]; + byte buf[2 * BLAKE2B_BLOCKBYTES]; + word64 buflen; + byte last_node; + } blake2b_state; + + typedef struct __blake2sp_state + { + blake2s_state S[8][1]; + blake2s_state R[1]; + byte buf[8 * BLAKE2S_BLOCKBYTES]; + word32 buflen; + } blake2sp_state; + + typedef struct __blake2bp_state + { + blake2b_state S[4][1]; + blake2b_state R[1]; + byte buf[4 * BLAKE2B_BLOCKBYTES]; + word64 buflen; + } blake2bp_state; +#pragma pack(pop) + + /* Streaming API */ + int blake2s_init( blake2s_state *S, const byte outlen ); + int blake2s_init_key( blake2s_state *S, const byte outlen, const void *key, const byte keylen ); + int blake2s_init_param( blake2s_state *S, const blake2s_param *P ); + int blake2s_update( blake2s_state *S, const byte *in, word32 inlen ); + int blake2s_final( blake2s_state *S, byte *out, byte outlen ); + + int blake2b_init( blake2b_state *S, const byte outlen ); + int blake2b_init_key( blake2b_state *S, const byte outlen, const void *key, const byte keylen ); + int blake2b_init_param( blake2b_state *S, const blake2b_param *P ); + int blake2b_update( blake2b_state *S, const byte *in, word64 inlen ); + int blake2b_final( blake2b_state *S, byte *out, byte outlen ); + + int blake2sp_init( blake2sp_state *S, const byte outlen ); + int blake2sp_init_key( blake2sp_state *S, const byte outlen, const void *key, const byte keylen ); + int blake2sp_update( blake2sp_state *S, const byte *in, word32 inlen ); + int blake2sp_final( blake2sp_state *S, byte *out, byte outlen ); + + int blake2bp_init( blake2bp_state *S, const byte outlen ); + int blake2bp_init_key( blake2bp_state *S, const byte outlen, const void *key, const byte keylen ); + int blake2bp_update( blake2bp_state *S, const byte *in, word64 inlen ); + int blake2bp_final( blake2bp_state *S, byte *out, byte outlen ); + + /* Simple API */ + int blake2s( byte *out, const void *in, const void *key, const byte outlen, const word32 inlen, byte keylen ); + int blake2b( byte *out, const void *in, const void *key, const byte outlen, const word64 inlen, byte keylen ); + + int blake2sp( byte *out, const void *in, const void *key, const byte outlen, const word32 inlen, byte keylen ); + int blake2bp( byte *out, const void *in, const void *key, const byte outlen, const word64 inlen, byte keylen ); + + static WC_INLINE int blake2( byte *out, const void *in, const void *key, const byte outlen, const word64 inlen, byte keylen ) + { + return blake2b( out, in, key, outlen, inlen, keylen ); + } + + + +#if defined(__cplusplus) + } +#endif + +#endif /* WOLFCRYPT_BLAKE2_INT_H */ + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/blake2.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/blake2.h new file mode 100755 index 0000000..bf34f31 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/blake2.h @@ -0,0 +1,96 @@ +/* blake2.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/*! + \file wolfssl/wolfcrypt/blake2.h +*/ + +#ifndef WOLF_CRYPT_BLAKE2_H +#define WOLF_CRYPT_BLAKE2_H + +#include + +#if defined(HAVE_BLAKE2) || defined(HAVE_BLAKE2S) + +#include + +/* call old functions if using fips for the sake of hmac @wc_fips */ +#ifdef HAVE_FIPS + /* Since hmac can call blake functions provide original calls */ + #define wc_InitBlake2b InitBlake2b + #define wc_Blake2bUpdate Blake2bUpdate + #define wc_Blake2bFinal Blake2bFinal +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +/* in bytes, variable digest size up to 512 bits (64 bytes) */ +enum { +#ifdef HAVE_BLAKE2B + BLAKE2B_ID = WC_HASH_TYPE_BLAKE2B, + BLAKE2B_256 = 32, /* 256 bit type, SSL default */ +#endif +#ifdef HAVE_BLAKE2S + BLAKE2S_ID = WC_HASH_TYPE_BLAKE2S, + BLAKE2S_256 = 32 /* 256 bit type */ +#endif +}; + + +#ifdef HAVE_BLAKE2B +/* BLAKE2b digest */ +typedef struct Blake2b { + blake2b_state S[1]; /* our state */ + word32 digestSz; /* digest size used on init */ +} Blake2b; +#endif + +#ifdef HAVE_BLAKE2S +/* BLAKE2s digest */ +typedef struct Blake2s { + blake2s_state S[1]; /* our state */ + word32 digestSz; /* digest size used on init */ +} Blake2s; +#endif + + +#ifdef HAVE_BLAKE2B +WOLFSSL_API int wc_InitBlake2b(Blake2b*, word32); +WOLFSSL_API int wc_Blake2bUpdate(Blake2b*, const byte*, word32); +WOLFSSL_API int wc_Blake2bFinal(Blake2b*, byte*, word32); +#endif + +#ifdef HAVE_BLAKE2S +WOLFSSL_API int wc_InitBlake2s(Blake2s*, word32); +WOLFSSL_API int wc_Blake2sUpdate(Blake2s*, const byte*, word32); +WOLFSSL_API int wc_Blake2sFinal(Blake2s*, byte*, word32); +#endif + + +#ifdef __cplusplus + } +#endif + +#endif /* HAVE_BLAKE2 || HAVE_BLAKE2S */ +#endif /* WOLF_CRYPT_BLAKE2_H */ + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/camellia.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/camellia.h new file mode 100755 index 0000000..612a464 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/camellia.h @@ -0,0 +1,101 @@ +/* camellia.h ver 1.2.0 + * + * Copyright (c) 2006,2007 + * NTT (Nippon Telegraph and Telephone Corporation) . All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer as + * the first lines of this file unmodified. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY NTT ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL NTT BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* camellia.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/*! + \file wolfssl/wolfcrypt/camellia.h +*/ + + +#ifndef WOLF_CRYPT_CAMELLIA_H +#define WOLF_CRYPT_CAMELLIA_H + +#include + +#ifdef HAVE_CAMELLIA + +#ifdef __cplusplus + extern "C" { +#endif + +enum { + CAMELLIA_BLOCK_SIZE = 16 +}; + +#define CAMELLIA_TABLE_BYTE_LEN 272 +#define CAMELLIA_TABLE_WORD_LEN (CAMELLIA_TABLE_BYTE_LEN / sizeof(word32)) + +typedef word32 KEY_TABLE_TYPE[CAMELLIA_TABLE_WORD_LEN]; + +typedef struct Camellia { + word32 keySz; + KEY_TABLE_TYPE key; + word32 reg[CAMELLIA_BLOCK_SIZE / sizeof(word32)]; /* for CBC mode */ + word32 tmp[CAMELLIA_BLOCK_SIZE / sizeof(word32)]; /* for CBC mode */ +} Camellia; + + +WOLFSSL_API int wc_CamelliaSetKey(Camellia* cam, + const byte* key, word32 len, const byte* iv); +WOLFSSL_API int wc_CamelliaSetIV(Camellia* cam, const byte* iv); +WOLFSSL_API int wc_CamelliaEncryptDirect(Camellia* cam, byte* out, + const byte* in); +WOLFSSL_API int wc_CamelliaDecryptDirect(Camellia* cam, byte* out, + const byte* in); +WOLFSSL_API int wc_CamelliaCbcEncrypt(Camellia* cam, + byte* out, const byte* in, word32 sz); +WOLFSSL_API int wc_CamelliaCbcDecrypt(Camellia* cam, + byte* out, const byte* in, word32 sz); + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* HAVE_CAMELLIA */ +#endif /* WOLF_CRYPT_CAMELLIA_H */ + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/chacha.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/chacha.h new file mode 100755 index 0000000..274a2d9 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/chacha.h @@ -0,0 +1,82 @@ +/* chacha.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/*! + \file wolfssl/wolfcrypt/chacha.h +*/ + + +#ifndef WOLF_CRYPT_CHACHA_H +#define WOLF_CRYPT_CHACHA_H + +#include + +#ifdef HAVE_CHACHA + +#ifdef __cplusplus + extern "C" { +#endif + +/* Size of the IV */ +#define CHACHA_IV_WORDS 3 +#define CHACHA_IV_BYTES (CHACHA_IV_WORDS * sizeof(word32)) + +/* Size of ChaCha chunks */ +#define CHACHA_CHUNK_WORDS 16 +#define CHACHA_CHUNK_BYTES (CHACHA_CHUNK_WORDS * sizeof(word32)) + +#ifdef WOLFSSL_X86_64_BUILD +#if defined(USE_INTEL_SPEEDUP) && !defined(NO_CHACHA_ASM) + #define USE_INTEL_CHACHA_SPEEDUP + #define HAVE_INTEL_AVX1 +#endif +#endif + +enum { + CHACHA_ENC_TYPE = WC_CIPHER_CHACHA, /* cipher unique type */ + CHACHA_MAX_KEY_SZ = 32, +}; + +typedef struct ChaCha { + word32 X[CHACHA_CHUNK_WORDS]; /* state of cipher */ +#ifdef HAVE_INTEL_AVX1 + /* vpshufd reads 16 bytes but we only use bottom 4. */ + byte extra[12]; +#endif +} ChaCha; + +/** + * IV(nonce) changes with each record + * counter is for what value the block counter should start ... usually 0 + */ +WOLFSSL_API int wc_Chacha_SetIV(ChaCha* ctx, const byte* inIv, word32 counter); + +WOLFSSL_API int wc_Chacha_Process(ChaCha* ctx, byte* cipher, const byte* plain, + word32 msglen); +WOLFSSL_API int wc_Chacha_SetKey(ChaCha* ctx, const byte* key, word32 keySz); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* HAVE_CHACHA */ +#endif /* WOLF_CRYPT_CHACHA_H */ + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/chacha20_poly1305.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/chacha20_poly1305.h new file mode 100755 index 0000000..aef7254 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/chacha20_poly1305.h @@ -0,0 +1,84 @@ +/* chacha20_poly1305.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +/* This implementation of the ChaCha20-Poly1305 AEAD is based on "ChaCha20 + * and Poly1305 for IETF protocols" (draft-irtf-cfrg-chacha20-poly1305-10): + * https://tools.ietf.org/html/draft-irtf-cfrg-chacha20-poly1305-10 + */ + +/*! + \file wolfssl/wolfcrypt/chacha20_poly1305.h +*/ + +#ifndef WOLF_CRYPT_CHACHA20_POLY1305_H +#define WOLF_CRYPT_CHACHA20_POLY1305_H + +#include + +#if defined(HAVE_CHACHA) && defined(HAVE_POLY1305) + +#ifdef __cplusplus + extern "C" { +#endif + +#define CHACHA20_POLY1305_AEAD_KEYSIZE 32 +#define CHACHA20_POLY1305_AEAD_IV_SIZE 12 +#define CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE 16 + +enum { + CHACHA20_POLY_1305_ENC_TYPE = 8 /* cipher unique type */ +}; + + /* + * The IV for this implementation is 96 bits to give the most flexibility. + * + * Some protocols may have unique per-invocation inputs that are not + * 96-bit in length. For example, IPsec may specify a 64-bit nonce. In + * such a case, it is up to the protocol document to define how to + * transform the protocol nonce into a 96-bit nonce, for example by + * concatenating a constant value. + */ + +WOLFSSL_API +int wc_ChaCha20Poly1305_Encrypt( + const byte inKey[CHACHA20_POLY1305_AEAD_KEYSIZE], + const byte inIV[CHACHA20_POLY1305_AEAD_IV_SIZE], + const byte* inAAD, const word32 inAADLen, + const byte* inPlaintext, const word32 inPlaintextLen, + byte* outCiphertext, + byte outAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE]); + +WOLFSSL_API +int wc_ChaCha20Poly1305_Decrypt( + const byte inKey[CHACHA20_POLY1305_AEAD_KEYSIZE], + const byte inIV[CHACHA20_POLY1305_AEAD_IV_SIZE], + const byte* inAAD, const word32 inAADLen, + const byte* inCiphertext, const word32 inCiphertextLen, + const byte inAuthTag[CHACHA20_POLY1305_AEAD_AUTHTAG_SIZE], + byte* outPlaintext); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* HAVE_CHACHA && HAVE_POLY1305 */ +#endif /* WOLF_CRYPT_CHACHA20_POLY1305_H */ diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/cmac.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/cmac.h new file mode 100755 index 0000000..43306c5 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/cmac.h @@ -0,0 +1,92 @@ +/* cmac.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifndef WOLF_CRYPT_CMAC_H +#define WOLF_CRYPT_CMAC_H + +#include +#include + +#if !defined(NO_AES) && defined(WOLFSSL_CMAC) + +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + #include +#endif /* HAVE_FIPS_VERSION >= 2 */ + +#ifdef __cplusplus + extern "C" { +#endif + +/* avoid redefinition of structs */ +#if !defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) + +typedef struct Cmac { + Aes aes; + byte buffer[AES_BLOCK_SIZE]; /* partially stored block */ + byte digest[AES_BLOCK_SIZE]; /* running digest */ + byte k1[AES_BLOCK_SIZE]; + byte k2[AES_BLOCK_SIZE]; + word32 bufferSz; + word32 totalSz; +} Cmac; + + +typedef enum CmacType { + WC_CMAC_AES = 1 +} CmacType; + +#define WC_CMAC_TAG_MAX_SZ AES_BLOCK_SIZE +#define WC_CMAC_TAG_MIN_SZ (AES_BLOCK_SIZE/4) + +#endif /* HAVE_FIPS */ + +WOLFSSL_API +int wc_InitCmac(Cmac* cmac, + const byte* key, word32 keySz, + int type, void* unused); +WOLFSSL_API +int wc_CmacUpdate(Cmac* cmac, + const byte* in, word32 inSz); +WOLFSSL_API +int wc_CmacFinal(Cmac* cmac, + byte* out, word32* outSz); + +WOLFSSL_API +int wc_AesCmacGenerate(byte* out, word32* outSz, + const byte* in, word32 inSz, + const byte* key, word32 keySz); + +WOLFSSL_API +int wc_AesCmacVerify(const byte* check, word32 checkSz, + const byte* in, word32 inSz, + const byte* key, word32 keySz); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + + +#endif /* NO_AES && WOLFSSL_CMAC */ +#endif /* WOLF_CRYPT_CMAC_H */ + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/coding.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/coding.h new file mode 100755 index 0000000..07d193b --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/coding.h @@ -0,0 +1,88 @@ +/* coding.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/*! + \file wolfssl/wolfcrypt/coding.h +*/ + +#ifndef WOLF_CRYPT_CODING_H +#define WOLF_CRYPT_CODING_H + +#include + +#ifdef __cplusplus + extern "C" { +#endif + + +WOLFSSL_API int Base64_Decode(const byte* in, word32 inLen, byte* out, + word32* outLen); + +#if defined(OPENSSL_EXTRA) || defined(SESSION_CERTS) || defined(WOLFSSL_KEY_GEN) \ + || defined(WOLFSSL_CERT_GEN) || defined(HAVE_WEBSERVER) || !defined(NO_DSA) + #ifndef WOLFSSL_BASE64_ENCODE + #define WOLFSSL_BASE64_ENCODE + #endif +#endif + + +#ifdef WOLFSSL_BASE64_ENCODE + enum Escaped { + WC_STD_ENC = 0, /* normal \n line ending encoding */ + WC_ESC_NL_ENC, /* use escape sequence encoding */ + WC_NO_NL_ENC /* no encoding at all */ + }; /* Encoding types */ + + /* encode isn't */ + WOLFSSL_API + int Base64_Encode(const byte* in, word32 inLen, byte* out, + word32* outLen); + WOLFSSL_API + int Base64_EncodeEsc(const byte* in, word32 inLen, byte* out, + word32* outLen); + WOLFSSL_API + int Base64_Encode_NoNl(const byte* in, word32 inLen, byte* out, + word32* outLen); +#endif + +#if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || \ + defined(HAVE_WEBSERVER) || defined(HAVE_FIPS) || \ + defined(HAVE_ECC_CDH) || defined(HAVE_SELFTEST) || \ + defined(WOLFSSL_ENCRYPTED_KEYS) + #ifndef WOLFSSL_BASE16 + #define WOLFSSL_BASE16 + #endif +#endif + +#ifdef WOLFSSL_BASE16 + WOLFSSL_API + int Base16_Decode(const byte* in, word32 inLen, byte* out, word32* outLen); + WOLFSSL_API + int Base16_Encode(const byte* in, word32 inLen, byte* out, word32* outLen); +#endif + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLF_CRYPT_CODING_H */ + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/compress.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/compress.h new file mode 100755 index 0000000..620f775 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/compress.h @@ -0,0 +1,58 @@ +/* compress.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/*! + \file wolfssl/wolfcrypt/compress.h +*/ + + +#ifndef WOLF_CRYPT_COMPRESS_H +#define WOLF_CRYPT_COMPRESS_H + +#include + +#ifdef HAVE_LIBZ + +#ifdef __cplusplus + extern "C" { +#endif + + +#define COMPRESS_FIXED 1 + +#define LIBZ_WINBITS_GZIP 16 + + +WOLFSSL_API int wc_Compress(byte*, word32, const byte*, word32, word32); +WOLFSSL_API int wc_Compress_ex(byte* out, word32 outSz, const byte* in, + word32 inSz, word32 flags, word32 windowBits); +WOLFSSL_API int wc_DeCompress(byte*, word32, const byte*, word32); +WOLFSSL_API int wc_DeCompress_ex(byte* out, word32 outSz, const byte* in, + word32 inSz, int windowBits); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + + +#endif /* HAVE_LIBZ */ +#endif /* WOLF_CRYPT_COMPRESS_H */ + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/cpuid.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/cpuid.h new file mode 100755 index 0000000..4452abc --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/cpuid.h @@ -0,0 +1,62 @@ +/* cpuid.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifndef WOLF_CRYPT_CPUID_H +#define WOLF_CRYPT_CPUID_H + + +#include + + +#ifdef __cplusplus + extern "C" { +#endif + +#if defined(WOLFSSL_X86_64_BUILD) || defined(USE_INTEL_SPEEDUP) || \ + defined(WOLFSSL_AESNI) + #define CPUID_AVX1 0x0001 + #define CPUID_AVX2 0x0002 + #define CPUID_RDRAND 0x0004 + #define CPUID_RDSEED 0x0008 + #define CPUID_BMI2 0x0010 /* MULX, RORX */ + #define CPUID_AESNI 0x0020 + #define CPUID_ADX 0x0040 /* ADCX, ADOX */ + + #define IS_INTEL_AVX1(f) ((f) & CPUID_AVX1) + #define IS_INTEL_AVX2(f) ((f) & CPUID_AVX2) + #define IS_INTEL_RDRAND(f) ((f) & CPUID_RDRAND) + #define IS_INTEL_RDSEED(f) ((f) & CPUID_RDSEED) + #define IS_INTEL_BMI2(f) ((f) & CPUID_BMI2) + #define IS_INTEL_AESNI(f) ((f) & CPUID_AESNI) + #define IS_INTEL_ADX(f) ((f) & CPUID_ADX) + + void cpuid_set_flags(void); + word32 cpuid_get_flags(void); +#endif + +#ifdef __cplusplus + } /* extern "C" */ +#endif + + +#endif /* WOLF_CRYPT_CPUID_H */ diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/cryptocb.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/cryptocb.h new file mode 100755 index 0000000..389c2d0 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/cryptocb.h @@ -0,0 +1,299 @@ +/* cryptocb.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef _WOLF_CRYPTO_CB_H_ +#define _WOLF_CRYPTO_CB_H_ + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/* Defines the Crypto Callback interface version, for compatibility */ +/* Increment this when Crypto Callback interface changes are made */ +#define CRYPTO_CB_VER 2 + + +#ifdef WOLF_CRYPTO_CB + +#ifndef NO_RSA + #include +#endif +#ifdef HAVE_ECC + #include +#endif +#ifndef NO_AES + #include +#endif +#ifndef NO_SHA + #include +#endif +#ifndef NO_SHA256 + #include +#endif +#ifndef NO_HMAC + #include +#endif +#ifndef WC_NO_RNG + #include +#endif +#ifndef NO_DES3 + #include +#endif + + +/* Crypto Information Structure for callbacks */ +typedef struct wc_CryptoInfo { + int algo_type; /* enum wc_AlgoType */ +#if !defined(NO_RSA) || defined(HAVE_ECC) + struct { + int type; /* enum wc_PkType */ + union { + #ifndef NO_RSA + struct { + const byte* in; + word32 inLen; + byte* out; + word32* outLen; + int type; + RsaKey* key; + WC_RNG* rng; + } rsa; + #ifdef WOLFSSL_KEY_GEN + struct { + RsaKey* key; + int size; + long e; + WC_RNG* rng; + } rsakg; + #endif + #endif + #ifdef HAVE_ECC + struct { + WC_RNG* rng; + int size; + ecc_key* key; + int curveId; + } eckg; + struct { + ecc_key* private_key; + ecc_key* public_key; + byte* out; + word32* outlen; + } ecdh; + struct { + const byte* in; + word32 inlen; + byte* out; + word32* outlen; + WC_RNG* rng; + ecc_key* key; + } eccsign; + struct { + const byte* sig; + word32 siglen; + const byte* hash; + word32 hashlen; + int* res; + ecc_key* key; + } eccverify; + #endif + }; + } pk; +#endif /* !NO_RSA || HAVE_ECC */ +#if !defined(NO_AES) || !defined(NO_DES3) + struct { + int type; /* enum wc_CipherType */ + int enc; + union { + #ifdef HAVE_AESGCM + struct { + Aes* aes; + byte* out; + const byte* in; + word32 sz; + const byte* iv; + word32 ivSz; + byte* authTag; + word32 authTagSz; + const byte* authIn; + word32 authInSz; + } aesgcm_enc; + struct { + Aes* aes; + byte* out; + const byte* in; + word32 sz; + const byte* iv; + word32 ivSz; + const byte* authTag; + word32 authTagSz; + const byte* authIn; + word32 authInSz; + } aesgcm_dec; + #endif /* HAVE_AESGCM */ + #ifdef HAVE_AES_CBC + struct { + Aes* aes; + byte* out; + const byte* in; + word32 sz; + } aescbc; + #endif /* HAVE_AES_CBC */ + #ifndef NO_DES3 + struct { + Des3* des; + byte* out; + const byte* in; + word32 sz; + } des3; + #endif + }; + } cipher; +#endif /* !NO_AES || !NO_DES3 */ +#if !defined(NO_SHA) || !defined(NO_SHA256) + struct { + int type; /* enum wc_HashType */ + const byte* in; + word32 inSz; + byte* digest; + union { + #ifndef NO_SHA + wc_Sha* sha1; + #endif + #ifndef NO_SHA256 + wc_Sha256* sha256; + #endif + }; + } hash; +#endif /* !NO_SHA || !NO_SHA256 */ +#ifndef NO_HMAC + struct { + int macType; /* enum wc_HashType */ + const byte* in; + word32 inSz; + byte* digest; + Hmac* hmac; + } hmac; +#endif +#ifndef WC_NO_RNG + struct { + WC_RNG* rng; + byte* out; + word32 sz; + } rng; + struct { + OS_Seed* os; + byte* seed; + word32 sz; + } seed; +#endif +} wc_CryptoInfo; + + +typedef int (*CryptoDevCallbackFunc)(int devId, wc_CryptoInfo* info, void* ctx); + +WOLFSSL_LOCAL void wc_CryptoCb_Init(void); + +WOLFSSL_API int wc_CryptoCb_RegisterDevice(int devId, CryptoDevCallbackFunc cb, void* ctx); +WOLFSSL_API void wc_CryptoCb_UnRegisterDevice(int devId); + +/* old function names */ +#define wc_CryptoDev_RegisterDevice wc_CryptoCb_RegisterDevice +#define wc_CryptoDev_UnRegisterDevice wc_CryptoCb_UnRegisterDevice + + +#ifndef NO_RSA +WOLFSSL_LOCAL int wc_CryptoCb_Rsa(const byte* in, word32 inLen, byte* out, + word32* outLen, int type, RsaKey* key, WC_RNG* rng); + +#ifdef WOLFSSL_KEY_GEN +WOLFSSL_LOCAL int wc_CryptoCb_MakeRsaKey(RsaKey* key, int size, long e, + WC_RNG* rng); +#endif /* WOLFSSL_KEY_GEN */ +#endif /* !NO_RSA */ + +#ifdef HAVE_ECC +WOLFSSL_LOCAL int wc_CryptoCb_MakeEccKey(WC_RNG* rng, int keySize, + ecc_key* key, int curveId); + +WOLFSSL_LOCAL int wc_CryptoCb_Ecdh(ecc_key* private_key, ecc_key* public_key, + byte* out, word32* outlen); + +WOLFSSL_LOCAL int wc_CryptoCb_EccSign(const byte* in, word32 inlen, byte* out, + word32 *outlen, WC_RNG* rng, ecc_key* key); + +WOLFSSL_LOCAL int wc_CryptoCb_EccVerify(const byte* sig, word32 siglen, + const byte* hash, word32 hashlen, int* res, ecc_key* key); +#endif /* HAVE_ECC */ + +#ifndef NO_AES +#ifdef HAVE_AESGCM +WOLFSSL_LOCAL int wc_CryptoCb_AesGcmEncrypt(Aes* aes, byte* out, + const byte* in, word32 sz, const byte* iv, word32 ivSz, + byte* authTag, word32 authTagSz, const byte* authIn, word32 authInSz); + +WOLFSSL_LOCAL int wc_CryptoCb_AesGcmDecrypt(Aes* aes, byte* out, + const byte* in, word32 sz, const byte* iv, word32 ivSz, + const byte* authTag, word32 authTagSz, + const byte* authIn, word32 authInSz); +#endif /* HAVE_AESGCM */ +#ifdef HAVE_AES_CBC +WOLFSSL_LOCAL int wc_CryptoCb_AesCbcEncrypt(Aes* aes, byte* out, + const byte* in, word32 sz); +WOLFSSL_LOCAL int wc_CryptoCb_AesCbcDecrypt(Aes* aes, byte* out, + const byte* in, word32 sz); +#endif /* HAVE_AES_CBC */ +#endif /* !NO_AES */ + +#ifndef NO_DES3 +WOLFSSL_LOCAL int wc_CryptoCb_Des3Encrypt(Des3* des3, byte* out, + const byte* in, word32 sz); +WOLFSSL_LOCAL int wc_CryptoCb_Des3Decrypt(Des3* des3, byte* out, + const byte* in, word32 sz); +#endif /* !NO_DES3 */ + +#ifndef NO_SHA +WOLFSSL_LOCAL int wc_CryptoCb_ShaHash(wc_Sha* sha, const byte* in, + word32 inSz, byte* digest); +#endif /* !NO_SHA */ + +#ifndef NO_SHA256 +WOLFSSL_LOCAL int wc_CryptoCb_Sha256Hash(wc_Sha256* sha256, const byte* in, + word32 inSz, byte* digest); +#endif /* !NO_SHA256 */ +#ifndef NO_HMAC +WOLFSSL_LOCAL int wc_CryptoCb_Hmac(Hmac* hmac, int macType, const byte* in, + word32 inSz, byte* digest); +#endif /* !NO_HMAC */ + +#ifndef WC_NO_RNG +WOLFSSL_LOCAL int wc_CryptoCb_RandomBlock(WC_RNG* rng, byte* out, word32 sz); +WOLFSSL_LOCAL int wc_CryptoCb_RandomSeed(OS_Seed* os, byte* seed, word32 sz); +#endif + +#endif /* WOLF_CRYPTO_CB */ + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* _WOLF_CRYPTO_CB_H_ */ diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/curve25519.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/curve25519.h new file mode 100755 index 0000000..0fb1ea1 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/curve25519.h @@ -0,0 +1,157 @@ +/* curve25519.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/*! + \file wolfssl/wolfcrypt/curve25519.h +*/ + + +#ifndef WOLF_CRYPT_CURVE25519_H +#define WOLF_CRYPT_CURVE25519_H + +#include + +#ifdef HAVE_CURVE25519 + +#include +#include + +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +#define CURVE25519_KEYSIZE 32 + +/* curve25519 set type */ +typedef struct { + int size; /* The size of the curve in octets */ + const char* name; /* name of this curve */ +} curve25519_set_type; + + +/* ECC point, the internal structure is Little endian + * the mathematical functions used the endianess */ +typedef struct { + byte point[CURVE25519_KEYSIZE]; + #ifdef FREESCALE_LTC_ECC + byte pointY[CURVE25519_KEYSIZE]; + #endif +} ECPoint; + +/* A CURVE25519 Key */ +typedef struct curve25519_key { + int idx; /* Index into the ecc_sets[] for the parameters of + this curve if -1, this key is using user supplied + curve in dp */ + const curve25519_set_type* dp; /* domain parameters, either points to + curves (idx >= 0) or user supplied */ + ECPoint p; /* public key */ + ECPoint k; /* private key */ + +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV asyncDev; +#endif +} curve25519_key; + +enum { + EC25519_LITTLE_ENDIAN=0, + EC25519_BIG_ENDIAN=1 +}; + +WOLFSSL_API +int wc_curve25519_make_key(WC_RNG* rng, int keysize, curve25519_key* key); + +WOLFSSL_API +int wc_curve25519_shared_secret(curve25519_key* private_key, + curve25519_key* public_key, + byte* out, word32* outlen); + +WOLFSSL_API +int wc_curve25519_shared_secret_ex(curve25519_key* private_key, + curve25519_key* public_key, + byte* out, word32* outlen, int endian); + +WOLFSSL_API +int wc_curve25519_init(curve25519_key* key); + +WOLFSSL_API +void wc_curve25519_free(curve25519_key* key); + + +/* raw key helpers */ +WOLFSSL_API +int wc_curve25519_import_private(const byte* priv, word32 privSz, + curve25519_key* key); +WOLFSSL_API +int wc_curve25519_import_private_ex(const byte* priv, word32 privSz, + curve25519_key* key, int endian); + +WOLFSSL_API +int wc_curve25519_import_private_raw(const byte* priv, word32 privSz, + const byte* pub, word32 pubSz, curve25519_key* key); +WOLFSSL_API +int wc_curve25519_import_private_raw_ex(const byte* priv, word32 privSz, + const byte* pub, word32 pubSz, + curve25519_key* key, int endian); +WOLFSSL_API +int wc_curve25519_export_private_raw(curve25519_key* key, byte* out, + word32* outLen); +WOLFSSL_API +int wc_curve25519_export_private_raw_ex(curve25519_key* key, byte* out, + word32* outLen, int endian); + +WOLFSSL_API +int wc_curve25519_import_public(const byte* in, word32 inLen, + curve25519_key* key); +WOLFSSL_API +int wc_curve25519_import_public_ex(const byte* in, word32 inLen, + curve25519_key* key, int endian); + +WOLFSSL_API +int wc_curve25519_export_public(curve25519_key* key, byte* out, word32* outLen); +WOLFSSL_API +int wc_curve25519_export_public_ex(curve25519_key* key, byte* out, + word32* outLen, int endian); + +WOLFSSL_API +int wc_curve25519_export_key_raw(curve25519_key* key, + byte* priv, word32 *privSz, + byte* pub, word32 *pubSz); +WOLFSSL_API +int wc_curve25519_export_key_raw_ex(curve25519_key* key, + byte* priv, word32 *privSz, + byte* pub, word32 *pubSz, + int endian); +/* size helper */ +WOLFSSL_API +int wc_curve25519_size(curve25519_key* key); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* HAVE_CURVE25519 */ +#endif /* WOLF_CRYPT_CURVE25519_H */ + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/des3.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/des3.h new file mode 100755 index 0000000..4072454 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/des3.h @@ -0,0 +1,151 @@ +/* des3.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/*! + \file wolfssl/wolfcrypt/des3.h +*/ + +#ifndef WOLF_CRYPT_DES3_H +#define WOLF_CRYPT_DES3_H + +#include + +#ifndef NO_DES3 + +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + #include +#endif /* HAVE_FIPS_VERSION >= 2 */ + +#if defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) +/* included for fips @wc_fips */ +#include +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +/* these are required for FIPS and non-FIPS */ +enum { + DES_KEY_SIZE = 8, /* des */ + DES3_KEY_SIZE = 24, /* 3 des ede */ + DES_IV_SIZE = 8, /* should be the same as DES_BLOCK_SIZE */ +}; + + +/* avoid redefinition of structs */ +#if !defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) + +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif + +enum { + DES_ENC_TYPE = WC_CIPHER_DES, /* cipher unique type */ + DES3_ENC_TYPE = WC_CIPHER_DES3, /* cipher unique type */ + + DES_BLOCK_SIZE = 8, + DES_KS_SIZE = 32, /* internal DES key buffer size */ + + DES_ENCRYPTION = 0, + DES_DECRYPTION = 1 +}; + +#define DES_IVLEN 8 +#define DES_KEYLEN 8 +#define DES3_IVLEN 8 +#define DES3_KEYLEN 24 + + +#if defined(STM32_CRYPTO) +enum { + DES_CBC = 0, + DES_ECB = 1 +}; +#endif + + +/* DES encryption and decryption */ +typedef struct Des { + word32 reg[DES_BLOCK_SIZE / sizeof(word32)]; /* for CBC mode */ + word32 tmp[DES_BLOCK_SIZE / sizeof(word32)]; /* same */ + word32 key[DES_KS_SIZE]; +} Des; + + +/* DES3 encryption and decryption */ +typedef struct Des3 { + word32 key[3][DES_KS_SIZE]; + word32 reg[DES_BLOCK_SIZE / sizeof(word32)]; /* for CBC mode */ + word32 tmp[DES_BLOCK_SIZE / sizeof(word32)]; /* same */ +#ifdef WOLFSSL_ASYNC_CRYPT + const byte* key_raw; + const byte* iv_raw; + WC_ASYNC_DEV asyncDev; +#endif +#ifdef WOLF_CRYPTO_CB + int devId; + void* devCtx; +#endif + void* heap; +} Des3; +#endif /* HAVE_FIPS */ + + +WOLFSSL_API int wc_Des_SetKey(Des* des, const byte* key, + const byte* iv, int dir); +WOLFSSL_API void wc_Des_SetIV(Des* des, const byte* iv); +WOLFSSL_API int wc_Des_CbcEncrypt(Des* des, byte* out, + const byte* in, word32 sz); +WOLFSSL_API int wc_Des_CbcDecrypt(Des* des, byte* out, + const byte* in, word32 sz); +WOLFSSL_API int wc_Des_EcbEncrypt(Des* des, byte* out, + const byte* in, word32 sz); +WOLFSSL_API int wc_Des3_EcbEncrypt(Des3* des, byte* out, + const byte* in, word32 sz); + +/* ECB decrypt same process as encrypt but with decrypt key */ +#define wc_Des_EcbDecrypt wc_Des_EcbEncrypt +#define wc_Des3_EcbDecrypt wc_Des3_EcbEncrypt + +WOLFSSL_API int wc_Des3_SetKey(Des3* des, const byte* key, + const byte* iv,int dir); +WOLFSSL_API int wc_Des3_SetIV(Des3* des, const byte* iv); +WOLFSSL_API int wc_Des3_CbcEncrypt(Des3* des, byte* out, + const byte* in,word32 sz); +WOLFSSL_API int wc_Des3_CbcDecrypt(Des3* des, byte* out, + const byte* in,word32 sz); + +/* These are only required when using either: + static memory (WOLFSSL_STATIC_MEMORY) or asynchronous (WOLFSSL_ASYNC_CRYPT) */ +WOLFSSL_API int wc_Des3Init(Des3*, void*, int); +WOLFSSL_API void wc_Des3Free(Des3*); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* NO_DES3 */ +#endif /* WOLF_CRYPT_DES3_H */ + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/dh.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/dh.h new file mode 100755 index 0000000..1f51c8d --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/dh.h @@ -0,0 +1,127 @@ +/* dh.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/*! + \file wolfssl/wolfcrypt/dh.h +*/ + +#ifndef WOLF_CRYPT_DH_H +#define WOLF_CRYPT_DH_H + +#include + +#ifndef NO_DH + +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + #include +#endif /* HAVE_FIPS_VERSION >= 2 */ + +#include +#include + +#ifdef __cplusplus + extern "C" { +#endif + +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif +typedef struct DhParams { + #ifdef HAVE_FFDHE_Q + const byte* q; + word32 q_len; + #endif /* HAVE_FFDHE_Q */ + const byte* p; + word32 p_len; + const byte* g; + word32 g_len; +} DhParams; + +/* Diffie-Hellman Key */ +typedef struct DhKey { + mp_int p, g, q; /* group parameters */ + void* heap; +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV asyncDev; +#endif +} DhKey; + + +#ifdef HAVE_FFDHE_2048 +WOLFSSL_API const DhParams* wc_Dh_ffdhe2048_Get(void); +#endif +#ifdef HAVE_FFDHE_3072 +WOLFSSL_API const DhParams* wc_Dh_ffdhe3072_Get(void); +#endif +#ifdef HAVE_FFDHE_4096 +WOLFSSL_API const DhParams* wc_Dh_ffdhe4096_Get(void); +#endif +#ifdef HAVE_FFDHE_6144 +WOLFSSL_API const DhParams* wc_Dh_ffdhe6144_Get(void); +#endif +#ifdef HAVE_FFDHE_8192 +WOLFSSL_API const DhParams* wc_Dh_ffdhe8192_Get(void); +#endif + +WOLFSSL_API int wc_InitDhKey(DhKey* key); +WOLFSSL_API int wc_InitDhKey_ex(DhKey* key, void* heap, int devId); +WOLFSSL_API int wc_FreeDhKey(DhKey* key); + +WOLFSSL_API int wc_DhGenerateKeyPair(DhKey* key, WC_RNG* rng, byte* priv, + word32* privSz, byte* pub, word32* pubSz); +WOLFSSL_API int wc_DhAgree(DhKey* key, byte* agree, word32* agreeSz, + const byte* priv, word32 privSz, const byte* otherPub, + word32 pubSz); + +WOLFSSL_API int wc_DhKeyDecode(const byte* input, word32* inOutIdx, DhKey* key, + word32); +WOLFSSL_API int wc_DhSetKey(DhKey* key, const byte* p, word32 pSz, const byte* g, + word32 gSz); +WOLFSSL_API int wc_DhSetKey_ex(DhKey* key, const byte* p, word32 pSz, + const byte* g, word32 gSz, const byte* q, word32 qSz); +WOLFSSL_API int wc_DhSetCheckKey(DhKey* key, const byte* p, word32 pSz, + const byte* g, word32 gSz, const byte* q, word32 qSz, + int trusted, WC_RNG* rng); +WOLFSSL_API int wc_DhParamsLoad(const byte* input, word32 inSz, byte* p, + word32* pInOutSz, byte* g, word32* gInOutSz); +WOLFSSL_API int wc_DhCheckPubKey(DhKey* key, const byte* pub, word32 pubSz); +WOLFSSL_API int wc_DhCheckPubKey_ex(DhKey* key, const byte* pub, word32 pubSz, + const byte* prime, word32 primeSz); +WOLFSSL_API int wc_DhCheckPubValue(const byte* prime, word32 primeSz, + const byte* pub, word32 pubSz); +WOLFSSL_API int wc_DhCheckPrivKey(DhKey* key, const byte* priv, word32 pubSz); +WOLFSSL_API int wc_DhCheckPrivKey_ex(DhKey* key, const byte* priv, word32 pubSz, + const byte* prime, word32 primeSz); +WOLFSSL_API int wc_DhCheckKeyPair(DhKey* key, const byte* pub, word32 pubSz, + const byte* priv, word32 privSz); +WOLFSSL_API int wc_DhGenerateParams(WC_RNG *rng, int modSz, DhKey *dh); +WOLFSSL_API int wc_DhExportParamsRaw(DhKey* dh, byte* p, word32* pSz, + byte* q, word32* qSz, byte* g, word32* gSz); + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* NO_DH */ +#endif /* WOLF_CRYPT_DH_H */ + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/dsa.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/dsa.h new file mode 100755 index 0000000..657dc0b --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/dsa.h @@ -0,0 +1,97 @@ +/* dsa.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/*! + \file wolfssl/wolfcrypt/dsa.h +*/ + +#ifndef WOLF_CRYPT_DSA_H +#define WOLF_CRYPT_DSA_H + +#include + +#ifndef NO_DSA + +#include +#include + +/* for DSA reverse compatibility */ +#define InitDsaKey wc_InitDsaKey +#define FreeDsaKey wc_FreeDsaKey +#define DsaSign wc_DsaSign +#define DsaVerify wc_DsaVerify +#define DsaPublicKeyDecode wc_DsaPublicKeyDecode +#define DsaPrivateKeyDecode wc_DsaPrivateKeyDecode +#define DsaKeyToDer wc_DsaKeyToDer + +#ifdef __cplusplus + extern "C" { +#endif + + +enum { + DSA_PUBLIC = 0, + DSA_PRIVATE = 1 +}; + +/* DSA */ +typedef struct DsaKey { + mp_int p, q, g, y, x; + int type; /* public or private */ + void* heap; /* memory hint */ +} DsaKey; + +WOLFSSL_API int wc_InitDsaKey(DsaKey* key); +WOLFSSL_API int wc_InitDsaKey_h(DsaKey* key, void* h); +WOLFSSL_API void wc_FreeDsaKey(DsaKey* key); +WOLFSSL_API int wc_DsaSign(const byte* digest, byte* out, + DsaKey* key, WC_RNG* rng); +WOLFSSL_API int wc_DsaVerify(const byte* digest, const byte* sig, + DsaKey* key, int* answer); +WOLFSSL_API int wc_DsaPublicKeyDecode(const byte* input, word32* inOutIdx, + DsaKey*, word32); +WOLFSSL_API int wc_DsaPrivateKeyDecode(const byte* input, word32* inOutIdx, + DsaKey*, word32); +WOLFSSL_API int wc_DsaKeyToDer(DsaKey* key, byte* output, word32 inLen); + +#ifdef WOLFSSL_KEY_GEN +WOLFSSL_API int wc_MakeDsaKey(WC_RNG *rng, DsaKey *dsa); +WOLFSSL_API int wc_MakeDsaParameters(WC_RNG *rng, int modulus_size, DsaKey *dsa); +#endif + +/* raw export functions */ +WOLFSSL_API int wc_DsaImportParamsRaw(DsaKey* dsa, const char* p, + const char* q, const char* g); +WOLFSSL_API int wc_DsaImportParamsRawCheck(DsaKey* dsa, const char* p, + const char* q, const char* g, + int trusted, WC_RNG* rng); +WOLFSSL_API int wc_DsaExportParamsRaw(DsaKey* dsa, byte* p, word32* pSz, + byte* q, word32* qSz, byte* g, + word32* gSz); +WOLFSSL_API int wc_DsaExportKeyRaw(DsaKey* dsa, byte* x, word32* xSz, byte* y, + word32* ySz); +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* NO_DSA */ +#endif /* WOLF_CRYPT_DSA_H */ + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/ecc.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/ecc.h new file mode 100755 index 0000000..9304cdb --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/ecc.h @@ -0,0 +1,718 @@ +/* ecc.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/*! + \file wolfssl/wolfcrypt/ecc.h +*/ + + +#ifndef WOLF_CRYPT_ECC_H +#define WOLF_CRYPT_ECC_H + +#include + +#ifdef HAVE_ECC + +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + #include +#endif /* HAVE_FIPS_VERSION >= 2 */ + +#include +#include + +#ifdef HAVE_X963_KDF + #include +#endif + +#ifdef WOLFSSL_ASYNC_CRYPT + #include + #ifdef WOLFSSL_CERT_GEN + #include + #endif +#endif + +#ifdef WOLFSSL_ATECC508A + #include +#endif /* WOLFSSL_ATECC508A */ + +#if defined(WOLFSSL_CRYPTOCELL) + #include +#endif + +#ifdef __cplusplus + extern "C" { +#endif + + +/* Enable curve B parameter if needed */ +#if defined(HAVE_COMP_KEY) || defined(ECC_CACHE_CURVE) + #ifndef USE_ECC_B_PARAM /* Allow someone to force enable */ + #define USE_ECC_B_PARAM + #endif +#endif + + +/* Use this as the key->idx if a custom ecc_set is used for key->dp */ +#define ECC_CUSTOM_IDX (-1) + + +/* Determine max ECC bits based on enabled curves */ +#if defined(HAVE_ECC521) || defined(HAVE_ALL_CURVES) + #define MAX_ECC_BITS 521 +#elif defined(HAVE_ECC512) + #define MAX_ECC_BITS 512 +#elif defined(HAVE_ECC384) + #define MAX_ECC_BITS 384 +#elif defined(HAVE_ECC320) + #define MAX_ECC_BITS 320 +#elif !defined(NO_ECC256) + #define MAX_ECC_BITS 256 +#elif defined(HAVE_ECC239) + #define MAX_ECC_BITS 239 +#elif defined(HAVE_ECC224) + #define MAX_ECC_BITS 224 +#elif defined(HAVE_ECC192) + #define MAX_ECC_BITS 192 +#elif defined(HAVE_ECC160) + #define MAX_ECC_BITS 160 +#elif defined(HAVE_ECC128) + #define MAX_ECC_BITS 128 +#elif defined(HAVE_ECC112) + #define MAX_ECC_BITS 112 +#endif + +/* calculate max ECC bytes */ +#if ((MAX_ECC_BITS * 2) % 8) == 0 + #define MAX_ECC_BYTES (MAX_ECC_BITS / 8) +#else + /* add byte if not aligned */ + #define MAX_ECC_BYTES ((MAX_ECC_BITS / 8) + 1) +#endif + +#ifndef ECC_MAX_PAD_SZ + /* ECC maximum padding size (when MSB is set extra byte required for R and S) */ + #define ECC_MAX_PAD_SZ 2 +#endif + +enum { + ECC_PUBLICKEY = 1, + ECC_PRIVATEKEY = 2, + ECC_PRIVATEKEY_ONLY = 3, + ECC_MAXNAME = 16, /* MAX CURVE NAME LENGTH */ + SIG_HEADER_SZ = 7, /* ECC signature header size (30 81 87 02 42 [R] 02 42 [S]) */ + ECC_BUFSIZE = 256, /* for exported keys temp buffer */ + ECC_MINSIZE = 20, /* MIN Private Key size */ + ECC_MAXSIZE = 66, /* MAX Private Key size */ + ECC_MAXSIZE_GEN = 74, /* MAX Buffer size required when generating ECC keys*/ + ECC_MAX_OID_LEN = 16, + ECC_MAX_SIG_SIZE= ((MAX_ECC_BYTES * 2) + ECC_MAX_PAD_SZ + SIG_HEADER_SZ), + + /* max crypto hardware size */ +#ifdef WOLFSSL_ATECC508A + ECC_MAX_CRYPTO_HW_SIZE = ATECC_KEY_SIZE, /* from port/atmel/atmel.h */ + ECC_MAX_CRYPTO_HW_PUBKEY_SIZE = (ATECC_KEY_SIZE*2), +#elif defined(PLUTON_CRYPTO_ECC) + ECC_MAX_CRYPTO_HW_SIZE = 32, +#elif defined(WOLFSSL_CRYPTOCELL) + #ifndef CRYPTOCELL_KEY_SIZE + CRYPTOCELL_KEY_SIZE = ECC_MAXSIZE, + #endif + ECC_MAX_CRYPTO_HW_SIZE = CRYPTOCELL_KEY_SIZE, +#endif + + /* point compression type */ + ECC_POINT_COMP_EVEN = 0x02, + ECC_POINT_COMP_ODD = 0x03, + ECC_POINT_UNCOMP = 0x04, + + /* Shamir's dual add constants */ + SHAMIR_PRECOMP_SZ = 16, + +#ifdef HAVE_PKCS11 + ECC_MAX_ID_LEN = 32, +#endif +}; + +/* Curve Types */ +typedef enum ecc_curve_id { + ECC_CURVE_INVALID = -1, + ECC_CURVE_DEF = 0, /* NIST or SECP */ + + /* NIST Prime Curves */ + ECC_SECP192R1, + ECC_PRIME192V2, + ECC_PRIME192V3, + ECC_PRIME239V1, + ECC_PRIME239V2, + ECC_PRIME239V3, + ECC_SECP256R1, + + /* SECP Curves */ + ECC_SECP112R1, + ECC_SECP112R2, + ECC_SECP128R1, + ECC_SECP128R2, + ECC_SECP160R1, + ECC_SECP160R2, + ECC_SECP224R1, + ECC_SECP384R1, + ECC_SECP521R1, + + /* Koblitz */ + ECC_SECP160K1, + ECC_SECP192K1, + ECC_SECP224K1, + ECC_SECP256K1, + + /* Brainpool Curves */ + ECC_BRAINPOOLP160R1, + ECC_BRAINPOOLP192R1, + ECC_BRAINPOOLP224R1, + ECC_BRAINPOOLP256R1, + ECC_BRAINPOOLP320R1, + ECC_BRAINPOOLP384R1, + ECC_BRAINPOOLP512R1, + + /* Twisted Edwards Curves */ +#ifdef HAVE_CURVE25519 + ECC_X25519, +#endif +#ifdef HAVE_X448 + ECC_X448, +#endif + +#ifdef WOLFSSL_CUSTOM_CURVES + ECC_CURVE_CUSTOM, +#endif +} ecc_curve_id; + +#ifdef HAVE_OID_ENCODING +typedef word16 ecc_oid_t; +#else +typedef byte ecc_oid_t; + /* OID encoded with ASN scheme: + first element = (oid[0] * 40) + oid[1] + if any element > 127 then MSB 0x80 indicates additional byte */ +#endif + +/* ECC set type defined a GF(p) curve */ +#ifndef USE_WINDOWS_API +typedef struct ecc_set_type { + int size; /* The size of the curve in octets */ + int id; /* id of this curve */ + const char* name; /* name of this curve */ + const char* prime; /* prime that defines the field, curve is in (hex) */ + const char* Af; /* fields A param (hex) */ + const char* Bf; /* fields B param (hex) */ + const char* order; /* order of the curve (hex) */ + const char* Gx; /* x coordinate of the base point on curve (hex) */ + const char* Gy; /* y coordinate of the base point on curve (hex) */ + const ecc_oid_t* oid; + word32 oidSz; + word32 oidSum; /* sum of encoded OID bytes */ + int cofactor; +} ecc_set_type; +#else +/* MSC does something different with the pointers to the arrays than GCC, + * and it causes the FIPS checksum to fail. In the case of windows builds, + * store everything as arrays instead of pointers to strings. */ + +#define MAX_ECC_NAME 16 +#define MAX_ECC_STRING ((MAX_ECC_BYTES * 2) + 1) + /* The values are stored as text strings. */ + +typedef struct ecc_set_type { + int size; /* The size of the curve in octets */ + int id; /* id of this curve */ + const char name[MAX_ECC_NAME]; /* name of this curve */ + const char prime[MAX_ECC_STRING]; /* prime that defines the field, curve is in (hex) */ + const char Af[MAX_ECC_STRING]; /* fields A param (hex) */ + const char Bf[MAX_ECC_STRING]; /* fields B param (hex) */ + const char order[MAX_ECC_STRING]; /* order of the curve (hex) */ + const char Gx[MAX_ECC_STRING]; /* x coordinate of the base point on curve (hex) */ + const char Gy[MAX_ECC_STRING]; /* y coordinate of the base point on curve (hex) */ + const ecc_oid_t oid[10]; + word32 oidSz; + word32 oidSum; /* sum of encoded OID bytes */ + int cofactor; +} ecc_set_type; +#endif + + +#ifdef ALT_ECC_SIZE + +/* Note on ALT_ECC_SIZE: + * The fast math code uses an array of a fixed size to store the big integers. + * By default, the array is big enough for RSA keys. There is a size, + * FP_MAX_BITS which can be used to make the array smaller when one wants ECC + * but not RSA. Some people want fast math sized for both RSA and ECC, where + * ECC won't use as much as RSA. The flag ALT_ECC_SIZE switches in an alternate + * ecc_point structure that uses an alternate fp_int that has a shorter array + * of fp_digits. + * + * Now, without ALT_ECC_SIZE, the ecc_point has three single item arrays of + * mp_ints for the components of the point. With ALT_ECC_SIZE, the components + * of the point are pointers that are set to each of a three item array of + * alt_fp_ints. While an mp_int will have 4096 bits of digit inside the + * structure, the alt_fp_int will only have 528 bits. A size value was added + * in the ALT case, as well, and is set by mp_init() and alt_fp_init(). The + * functions fp_zero() and fp_copy() use the size parameter. An int needs to + * be initialized before using it instead of just fp_zeroing it, the init will + * call zero. FP_MAX_BITS_ECC defaults to 528, but can be set to change the + * number of bits used in the alternate FP_INT. + * + * Do not enable ALT_ECC_SIZE and disable fast math in the configuration. + */ + +#ifndef USE_FAST_MATH + #error USE_FAST_MATH must be defined to use ALT_ECC_SIZE +#endif + +/* determine max bits required for ECC math */ +#ifndef FP_MAX_BITS_ECC + /* check alignment */ + #if ((MAX_ECC_BITS * 2) % DIGIT_BIT) == 0 + /* max bits is double */ + #define FP_MAX_BITS_ECC (MAX_ECC_BITS * 2) + #else + /* max bits is doubled, plus one digit of fudge */ + #define FP_MAX_BITS_ECC ((MAX_ECC_BITS * 2) + DIGIT_BIT) + #endif +#else + /* verify alignment */ + #if FP_MAX_BITS_ECC % CHAR_BIT + #error FP_MAX_BITS_ECC must be a multiple of CHAR_BIT + #endif +#endif + +/* determine buffer size */ +#define FP_SIZE_ECC (FP_MAX_BITS_ECC/DIGIT_BIT) + + +/* This needs to match the size of the fp_int struct, except the + * fp_digit array will be shorter. */ +typedef struct alt_fp_int { + int used, sign, size; + mp_digit dp[FP_SIZE_ECC]; +} alt_fp_int; +#endif /* ALT_ECC_SIZE */ + +#ifndef WC_ECCKEY_TYPE_DEFINED + typedef struct ecc_key ecc_key; + #define WC_ECCKEY_TYPE_DEFINED +#endif + + +/* A point on an ECC curve, stored in Jacbobian format such that (x,y,z) => + (x/z^2, y/z^3, 1) when interpreted as affine */ +typedef struct { +#ifndef ALT_ECC_SIZE + mp_int x[1]; /* The x coordinate */ + mp_int y[1]; /* The y coordinate */ + mp_int z[1]; /* The z coordinate */ +#else + mp_int* x; /* The x coordinate */ + mp_int* y; /* The y coordinate */ + mp_int* z; /* The z coordinate */ + alt_fp_int xyz[3]; +#endif +#ifdef WOLFSSL_SMALL_STACK_CACHE + ecc_key* key; +#endif +} ecc_point; + +/* ECC Flags */ +enum { + WC_ECC_FLAG_NONE = 0x00, +#ifdef HAVE_ECC_CDH + WC_ECC_FLAG_COFACTOR = 0x01, +#endif +}; + +/* An ECC Key */ +struct ecc_key { + int type; /* Public or Private */ + int idx; /* Index into the ecc_sets[] for the parameters of + this curve if -1, this key is using user supplied + curve in dp */ + int state; + word32 flags; + const ecc_set_type* dp; /* domain parameters, either points to NIST + curves (idx >= 0) or user supplied */ +#ifdef WOLFSSL_CUSTOM_CURVES + int deallocSet; +#endif + void* heap; /* heap hint */ + ecc_point pubkey; /* public key */ + mp_int k; /* private key */ +#ifdef WOLFSSL_ATECC508A + int slot; /* Key Slot Number (-1 unknown) */ + byte pubkey_raw[ECC_MAX_CRYPTO_HW_PUBKEY_SIZE]; +#endif +#if defined(PLUTON_CRYPTO_ECC) || defined(WOLF_CRYPTO_CB) + int devId; +#endif +#ifdef WOLFSSL_ASYNC_CRYPT + mp_int* r; /* sign/verify temps */ + mp_int* s; + WC_ASYNC_DEV asyncDev; + #ifdef HAVE_CAVIUM_V + mp_int* e; /* Sign, Verify and Shared Secret */ + mp_int* signK; + #endif + #ifdef WOLFSSL_CERT_GEN + CertSignCtx certSignCtx; /* context info for cert sign (MakeSignature) */ + #endif +#endif /* WOLFSSL_ASYNC_CRYPT */ +#ifdef HAVE_PKCS11 + byte id[ECC_MAX_ID_LEN]; + int idLen; +#endif +#if defined(WOLFSSL_CRYPTOCELL) + ecc_context_t ctx; +#endif + +#ifdef WOLFSSL_SMALL_STACK_CACHE + mp_int* t1; + mp_int* t2; +#ifdef ALT_ECC_SIZE + mp_int* x; + mp_int* y; + mp_int* z; +#endif +#endif +}; + + +/* ECC predefined curve sets */ +extern const ecc_set_type ecc_sets[]; + +WOLFSSL_API +const char* wc_ecc_get_name(int curve_id); + +#ifndef WOLFSSL_ATECC508A + +#ifdef WOLFSSL_PUBLIC_ECC_ADD_DBL + #define ECC_API WOLFSSL_API +#else + #define ECC_API WOLFSSL_LOCAL +#endif + +ECC_API int ecc_mul2add(ecc_point* A, mp_int* kA, + ecc_point* B, mp_int* kB, + ecc_point* C, mp_int* a, mp_int* modulus, void* heap); + +ECC_API int ecc_map(ecc_point*, mp_int*, mp_digit); +ECC_API int ecc_projective_add_point(ecc_point* P, ecc_point* Q, ecc_point* R, + mp_int* a, mp_int* modulus, mp_digit mp); +ECC_API int ecc_projective_dbl_point(ecc_point* P, ecc_point* R, mp_int* a, + mp_int* modulus, mp_digit mp); + +#endif + +WOLFSSL_API +int wc_ecc_make_key(WC_RNG* rng, int keysize, ecc_key* key); +WOLFSSL_API +int wc_ecc_make_key_ex(WC_RNG* rng, int keysize, ecc_key* key, + int curve_id); +WOLFSSL_API +int wc_ecc_make_pub(ecc_key* key, ecc_point* pubOut); +WOLFSSL_API +int wc_ecc_check_key(ecc_key* key); +WOLFSSL_API +int wc_ecc_is_point(ecc_point* ecp, mp_int* a, mp_int* b, mp_int* prime); + +#ifdef HAVE_ECC_DHE +WOLFSSL_API +int wc_ecc_shared_secret(ecc_key* private_key, ecc_key* public_key, byte* out, + word32* outlen); +WOLFSSL_LOCAL +int wc_ecc_shared_secret_gen(ecc_key* private_key, ecc_point* point, + byte* out, word32 *outlen); +WOLFSSL_API +int wc_ecc_shared_secret_ex(ecc_key* private_key, ecc_point* point, + byte* out, word32 *outlen); + +#if defined(WOLFSSL_ATECC508A) || defined(PLUTON_CRYPTO_ECC) || defined(WOLFSSL_CRYPTOCELL) +#define wc_ecc_shared_secret_ssh wc_ecc_shared_secret +#else +#define wc_ecc_shared_secret_ssh wc_ecc_shared_secret_ex /* For backwards compat */ +#endif + +#endif /* HAVE_ECC_DHE */ + +#ifdef HAVE_ECC_SIGN +WOLFSSL_API +int wc_ecc_sign_hash(const byte* in, word32 inlen, byte* out, word32 *outlen, + WC_RNG* rng, ecc_key* key); +WOLFSSL_API +int wc_ecc_sign_hash_ex(const byte* in, word32 inlen, WC_RNG* rng, + ecc_key* key, mp_int *r, mp_int *s); +#endif /* HAVE_ECC_SIGN */ + +#ifdef HAVE_ECC_VERIFY +WOLFSSL_API +int wc_ecc_verify_hash(const byte* sig, word32 siglen, const byte* hash, + word32 hashlen, int* stat, ecc_key* key); +WOLFSSL_API +int wc_ecc_verify_hash_ex(mp_int *r, mp_int *s, const byte* hash, + word32 hashlen, int* stat, ecc_key* key); +#endif /* HAVE_ECC_VERIFY */ + +WOLFSSL_API +int wc_ecc_init(ecc_key* key); +WOLFSSL_API +int wc_ecc_init_ex(ecc_key* key, void* heap, int devId); +#ifdef HAVE_PKCS11 +WOLFSSL_API +int wc_ecc_init_id(ecc_key* key, unsigned char* id, int len, void* heap, + int devId); +#endif +#ifdef WOLFSSL_CUSTOM_CURVES +WOLFSSL_LOCAL +void wc_ecc_free_curve(const ecc_set_type* curve, void* heap); +#endif +WOLFSSL_API +int wc_ecc_free(ecc_key* key); +WOLFSSL_API +int wc_ecc_set_flags(ecc_key* key, word32 flags); +WOLFSSL_API +void wc_ecc_fp_free(void); + +WOLFSSL_API +int wc_ecc_set_curve(ecc_key* key, int keysize, int curve_id); + +WOLFSSL_API +int wc_ecc_is_valid_idx(int n); +WOLFSSL_API +int wc_ecc_get_curve_idx(int curve_id); +WOLFSSL_API +int wc_ecc_get_curve_id(int curve_idx); +#define wc_ecc_get_curve_name_from_id wc_ecc_get_name +WOLFSSL_API +int wc_ecc_get_curve_size_from_id(int curve_id); + +WOLFSSL_API +int wc_ecc_get_curve_idx_from_name(const char* curveName); +WOLFSSL_API +int wc_ecc_get_curve_size_from_name(const char* curveName); +WOLFSSL_API +int wc_ecc_get_curve_id_from_name(const char* curveName); +WOLFSSL_API +int wc_ecc_get_curve_id_from_params(int fieldSize, + const byte* prime, word32 primeSz, const byte* Af, word32 AfSz, + const byte* Bf, word32 BfSz, const byte* order, word32 orderSz, + const byte* Gx, word32 GxSz, const byte* Gy, word32 GySz, int cofactor); +WOLFSSL_API +int wc_ecc_get_curve_id_from_dp_params(const ecc_set_type* dp); + +WOLFSSL_API +int wc_ecc_get_curve_id_from_oid(const byte* oid, word32 len); + +WOLFSSL_API +ecc_point* wc_ecc_new_point(void); +WOLFSSL_API +ecc_point* wc_ecc_new_point_h(void* h); +WOLFSSL_API +void wc_ecc_del_point(ecc_point* p); +WOLFSSL_API +void wc_ecc_del_point_h(ecc_point* p, void* h); +WOLFSSL_API +int wc_ecc_copy_point(ecc_point* p, ecc_point *r); +WOLFSSL_API +int wc_ecc_cmp_point(ecc_point* a, ecc_point *b); +WOLFSSL_API +int wc_ecc_point_is_at_infinity(ecc_point *p); + +#ifndef WOLFSSL_ATECC508A +WOLFSSL_API +int wc_ecc_mulmod(mp_int* k, ecc_point *G, ecc_point *R, + mp_int* a, mp_int* modulus, int map); +WOLFSSL_LOCAL +int wc_ecc_mulmod_ex(mp_int* k, ecc_point *G, ecc_point *R, + mp_int* a, mp_int* modulus, int map, void* heap); +#endif /* !WOLFSSL_ATECC508A */ + + +#ifdef HAVE_ECC_KEY_EXPORT +/* ASN key helpers */ +WOLFSSL_API +int wc_ecc_export_x963(ecc_key*, byte* out, word32* outLen); +WOLFSSL_API +int wc_ecc_export_x963_ex(ecc_key*, byte* out, word32* outLen, int compressed); + /* extended functionality with compressed option */ +#endif /* HAVE_ECC_KEY_EXPORT */ + +#ifdef HAVE_ECC_KEY_IMPORT +WOLFSSL_API +int wc_ecc_import_x963(const byte* in, word32 inLen, ecc_key* key); +WOLFSSL_API +int wc_ecc_import_x963_ex(const byte* in, word32 inLen, ecc_key* key, + int curve_id); +WOLFSSL_API +int wc_ecc_import_private_key(const byte* priv, word32 privSz, const byte* pub, + word32 pubSz, ecc_key* key); +WOLFSSL_API +int wc_ecc_import_private_key_ex(const byte* priv, word32 privSz, + const byte* pub, word32 pubSz, ecc_key* key, int curve_id); +WOLFSSL_API +int wc_ecc_rs_to_sig(const char* r, const char* s, byte* out, word32* outlen); +WOLFSSL_API +int wc_ecc_rs_raw_to_sig(const byte* r, word32 rSz, const byte* s, word32 sSz, + byte* out, word32* outlen); +WOLFSSL_API +int wc_ecc_sig_to_rs(const byte* sig, word32 sigLen, byte* r, word32* rLen, + byte* s, word32* sLen); +WOLFSSL_API +int wc_ecc_import_raw(ecc_key* key, const char* qx, const char* qy, + const char* d, const char* curveName); +WOLFSSL_API +int wc_ecc_import_raw_ex(ecc_key* key, const char* qx, const char* qy, + const char* d, int curve_id); +WOLFSSL_API +int wc_ecc_import_unsigned(ecc_key* key, byte* qx, byte* qy, + byte* d, int curve_id); +#endif /* HAVE_ECC_KEY_IMPORT */ + +#ifdef HAVE_ECC_KEY_EXPORT +WOLFSSL_API +int wc_ecc_export_ex(ecc_key* key, byte* qx, word32* qxLen, + byte* qy, word32* qyLen, byte* d, word32* dLen, + int encType); +WOLFSSL_API +int wc_ecc_export_private_only(ecc_key* key, byte* out, word32* outLen); +WOLFSSL_API +int wc_ecc_export_public_raw(ecc_key* key, byte* qx, word32* qxLen, + byte* qy, word32* qyLen); +WOLFSSL_API +int wc_ecc_export_private_raw(ecc_key* key, byte* qx, word32* qxLen, + byte* qy, word32* qyLen, byte* d, word32* dLen); +#endif /* HAVE_ECC_KEY_EXPORT */ + +#ifdef HAVE_ECC_KEY_EXPORT + +WOLFSSL_API +int wc_ecc_export_point_der(const int curve_idx, ecc_point* point, + byte* out, word32* outLen); +#endif /* HAVE_ECC_KEY_EXPORT */ + + +#ifdef HAVE_ECC_KEY_IMPORT +WOLFSSL_API +int wc_ecc_import_point_der(byte* in, word32 inLen, const int curve_idx, + ecc_point* point); +#endif /* HAVE_ECC_KEY_IMPORT */ + +/* size helper */ +WOLFSSL_API +int wc_ecc_size(ecc_key* key); +WOLFSSL_API +int wc_ecc_sig_size_calc(int sz); +WOLFSSL_API +int wc_ecc_sig_size(ecc_key* key); + +WOLFSSL_API +int wc_ecc_get_oid(word32 oidSum, const byte** oid, word32* oidSz); + +#ifdef WOLFSSL_CUSTOM_CURVES + WOLFSSL_API + int wc_ecc_set_custom_curve(ecc_key* key, const ecc_set_type* dp); +#endif + +#ifdef HAVE_ECC_ENCRYPT +/* ecc encrypt */ + +enum ecEncAlgo { + ecAES_128_CBC = 1, /* default */ + ecAES_256_CBC = 2 +}; + +enum ecKdfAlgo { + ecHKDF_SHA256 = 1, /* default */ + ecHKDF_SHA1 = 2 +}; + +enum ecMacAlgo { + ecHMAC_SHA256 = 1, /* default */ + ecHMAC_SHA1 = 2 +}; + +enum { + KEY_SIZE_128 = 16, + KEY_SIZE_256 = 32, + IV_SIZE_64 = 8, + IV_SIZE_128 = 16, + EXCHANGE_SALT_SZ = 16, + EXCHANGE_INFO_SZ = 23 +}; + +enum ecFlags { + REQ_RESP_CLIENT = 1, + REQ_RESP_SERVER = 2 +}; + + +typedef struct ecEncCtx ecEncCtx; + +WOLFSSL_API +ecEncCtx* wc_ecc_ctx_new(int flags, WC_RNG* rng); +WOLFSSL_API +ecEncCtx* wc_ecc_ctx_new_ex(int flags, WC_RNG* rng, void* heap); +WOLFSSL_API +void wc_ecc_ctx_free(ecEncCtx*); +WOLFSSL_API +int wc_ecc_ctx_reset(ecEncCtx*, WC_RNG*); /* reset for use again w/o alloc/free */ + +WOLFSSL_API +const byte* wc_ecc_ctx_get_own_salt(ecEncCtx*); +WOLFSSL_API +int wc_ecc_ctx_set_peer_salt(ecEncCtx*, const byte* salt); +WOLFSSL_API +int wc_ecc_ctx_set_info(ecEncCtx*, const byte* info, int sz); + +WOLFSSL_API +int wc_ecc_encrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, + word32 msgSz, byte* out, word32* outSz, ecEncCtx* ctx); +WOLFSSL_API +int wc_ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg, + word32 msgSz, byte* out, word32* outSz, ecEncCtx* ctx); + +#endif /* HAVE_ECC_ENCRYPT */ + +#ifdef HAVE_X963_KDF +WOLFSSL_API int wc_X963_KDF(enum wc_HashType type, const byte* secret, + word32 secretSz, const byte* sinfo, word32 sinfoSz, + byte* out, word32 outSz); +#endif + +#ifdef ECC_CACHE_CURVE +WOLFSSL_API int wc_ecc_curve_cache_init(void); +WOLFSSL_API void wc_ecc_curve_cache_free(void); +#endif + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* HAVE_ECC */ +#endif /* WOLF_CRYPT_ECC_H */ diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/ed25519.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/ed25519.h new file mode 100755 index 0000000..3e858bf --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/ed25519.h @@ -0,0 +1,169 @@ +/* ed25519.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/*! + \file wolfssl/wolfcrypt/ed25519.h +*/ + + +#ifndef WOLF_CRYPT_ED25519_H +#define WOLF_CRYPT_ED25519_H + +#include + +#ifdef HAVE_ED25519 + +#include +#include +#include +#include + +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif + +#ifdef __cplusplus + extern "C" { +#endif + + +/* info about EdDSA curve specifically ed25519, defined as an elliptic curve + over GF(p) */ +/* + 32, key size + "ED25519", curve name + "2^255-19", prime number + "SHA512", hash function + "-121665/121666", value of d +*/ + +#define ED25519_KEY_SIZE 32 /* private key only */ +#define ED25519_SIG_SIZE 64 + +#define ED25519_PUB_KEY_SIZE 32 /* compressed */ +/* both private and public key */ +#define ED25519_PRV_KEY_SIZE (ED25519_PUB_KEY_SIZE+ED25519_KEY_SIZE) + + +enum { + Ed25519 = -1, + Ed25519ctx = 0, + Ed25519ph = 1, +}; + +#ifndef WC_ED25519KEY_TYPE_DEFINED + typedef struct ed25519_key ed25519_key; + #define WC_ED25519KEY_TYPE_DEFINED +#endif + +/* An ED25519 Key */ +struct ed25519_key { + byte p[ED25519_PUB_KEY_SIZE]; /* compressed public key */ + byte k[ED25519_PRV_KEY_SIZE]; /* private key : 32 secret -- 32 public */ +#ifdef FREESCALE_LTC_ECC + /* uncompressed point coordinates */ + byte pointX[ED25519_KEY_SIZE]; /* recovered X coordinate */ + byte pointY[ED25519_KEY_SIZE]; /* Y coordinate is the public key with The most significant bit of the final octet always zero. */ +#endif + word16 pubKeySet:1; +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV asyncDev; +#endif +}; + + +WOLFSSL_API +int wc_ed25519_make_public(ed25519_key* key, unsigned char* pubKey, + word32 pubKeySz); +WOLFSSL_API +int wc_ed25519_make_key(WC_RNG* rng, int keysize, ed25519_key* key); +WOLFSSL_API +int wc_ed25519_sign_msg(const byte* in, word32 inLen, byte* out, + word32 *outLen, ed25519_key* key); +WOLFSSL_API +int wc_ed25519ctx_sign_msg(const byte* in, word32 inLen, byte* out, + word32 *outLen, ed25519_key* key, + const byte* context, byte contextLen); +WOLFSSL_API +int wc_ed25519ph_sign_hash(const byte* hash, word32 hashLen, byte* out, + word32 *outLen, ed25519_key* key, + const byte* context, byte contextLen); +WOLFSSL_API +int wc_ed25519ph_sign_msg(const byte* in, word32 inLen, byte* out, + word32 *outLen, ed25519_key* key, const byte* context, + byte contextLen); +WOLFSSL_API +int wc_ed25519_verify_msg(const byte* sig, word32 sigLen, const byte* msg, + word32 msgLen, int* stat, ed25519_key* key); +WOLFSSL_API +int wc_ed25519ctx_verify_msg(const byte* sig, word32 sigLen, const byte* msg, + word32 msgLen, int* stat, ed25519_key* key, + const byte* context, byte contextLen); +WOLFSSL_API +int wc_ed25519ph_verify_hash(const byte* sig, word32 sigLen, const byte* hash, + word32 hashLen, int* stat, ed25519_key* key, + const byte* context, byte contextLen); +WOLFSSL_API +int wc_ed25519ph_verify_msg(const byte* sig, word32 sigLen, const byte* msg, + word32 msgLen, int* stat, ed25519_key* key, + const byte* context, byte contextLen); +WOLFSSL_API +int wc_ed25519_init(ed25519_key* key); +WOLFSSL_API +void wc_ed25519_free(ed25519_key* key); +WOLFSSL_API +int wc_ed25519_import_public(const byte* in, word32 inLen, ed25519_key* key); +WOLFSSL_API +int wc_ed25519_import_private_only(const byte* priv, word32 privSz, + ed25519_key* key); +WOLFSSL_API +int wc_ed25519_import_private_key(const byte* priv, word32 privSz, + const byte* pub, word32 pubSz, ed25519_key* key); +WOLFSSL_API +int wc_ed25519_export_public(ed25519_key*, byte* out, word32* outLen); +WOLFSSL_API +int wc_ed25519_export_private_only(ed25519_key* key, byte* out, word32* outLen); +WOLFSSL_API +int wc_ed25519_export_private(ed25519_key* key, byte* out, word32* outLen); +WOLFSSL_API +int wc_ed25519_export_key(ed25519_key* key, + byte* priv, word32 *privSz, + byte* pub, word32 *pubSz); + +int wc_ed25519_check_key(ed25519_key* key); + +/* size helper */ +WOLFSSL_API +int wc_ed25519_size(ed25519_key* key); +WOLFSSL_API +int wc_ed25519_priv_size(ed25519_key* key); +WOLFSSL_API +int wc_ed25519_pub_size(ed25519_key* key); +WOLFSSL_API +int wc_ed25519_sig_size(ed25519_key* key); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* HAVE_ED25519 */ +#endif /* WOLF_CRYPT_ED25519_H */ + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/error-crypt.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/error-crypt.h new file mode 100755 index 0000000..e91fe8f --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/error-crypt.h @@ -0,0 +1,252 @@ +/* error-crypt.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/*! + \file wolfssl/wolfcrypt/error-crypt.h +*/ + +#ifndef WOLF_CRYPT_ERROR_H +#define WOLF_CRYPT_ERROR_H + +#include + +#if defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) + #include +#endif /* HAVE_FIPS V1 */ + +#ifdef __cplusplus + extern "C" { +#endif + + +/* error codes, add string for new errors !!! */ +enum { + MAX_CODE_E = -100, /* errors -101 - -299 */ + OPEN_RAN_E = -101, /* opening random device error */ + READ_RAN_E = -102, /* reading random device error */ + WINCRYPT_E = -103, /* windows crypt init error */ + CRYPTGEN_E = -104, /* windows crypt generation error */ + RAN_BLOCK_E = -105, /* reading random device would block */ + BAD_MUTEX_E = -106, /* Bad mutex operation */ + WC_TIMEOUT_E = -107, /* timeout error */ + WC_PENDING_E = -108, /* wolfCrypt operation pending (would block) */ + WC_NOT_PENDING_E = -109, /* wolfCrypt operation not pending */ + + MP_INIT_E = -110, /* mp_init error state */ + MP_READ_E = -111, /* mp_read error state */ + MP_EXPTMOD_E = -112, /* mp_exptmod error state */ + MP_TO_E = -113, /* mp_to_xxx error state, can't convert */ + MP_SUB_E = -114, /* mp_sub error state, can't subtract */ + MP_ADD_E = -115, /* mp_add error state, can't add */ + MP_MUL_E = -116, /* mp_mul error state, can't multiply */ + MP_MULMOD_E = -117, /* mp_mulmod error state, can't multiply mod */ + MP_MOD_E = -118, /* mp_mod error state, can't mod */ + MP_INVMOD_E = -119, /* mp_invmod error state, can't inv mod */ + MP_CMP_E = -120, /* mp_cmp error state */ + MP_ZERO_E = -121, /* got a mp zero result, not expected */ + + MEMORY_E = -125, /* out of memory error */ + VAR_STATE_CHANGE_E = -126, /* var state modified by different thread */ + + RSA_WRONG_TYPE_E = -130, /* RSA wrong block type for RSA function */ + RSA_BUFFER_E = -131, /* RSA buffer error, output too small or + input too large */ + BUFFER_E = -132, /* output buffer too small or input too large */ + ALGO_ID_E = -133, /* setting algo id error */ + PUBLIC_KEY_E = -134, /* setting public key error */ + DATE_E = -135, /* setting date validity error */ + SUBJECT_E = -136, /* setting subject name error */ + ISSUER_E = -137, /* setting issuer name error */ + CA_TRUE_E = -138, /* setting CA basic constraint true error */ + EXTENSIONS_E = -139, /* setting extensions error */ + + ASN_PARSE_E = -140, /* ASN parsing error, invalid input */ + ASN_VERSION_E = -141, /* ASN version error, invalid number */ + ASN_GETINT_E = -142, /* ASN get big int error, invalid data */ + ASN_RSA_KEY_E = -143, /* ASN key init error, invalid input */ + ASN_OBJECT_ID_E = -144, /* ASN object id error, invalid id */ + ASN_TAG_NULL_E = -145, /* ASN tag error, not null */ + ASN_EXPECT_0_E = -146, /* ASN expect error, not zero */ + ASN_BITSTR_E = -147, /* ASN bit string error, wrong id */ + ASN_UNKNOWN_OID_E = -148, /* ASN oid error, unknown sum id */ + ASN_DATE_SZ_E = -149, /* ASN date error, bad size */ + ASN_BEFORE_DATE_E = -150, /* ASN date error, current date before */ + ASN_AFTER_DATE_E = -151, /* ASN date error, current date after */ + ASN_SIG_OID_E = -152, /* ASN signature error, mismatched oid */ + ASN_TIME_E = -153, /* ASN time error, unknown time type */ + ASN_INPUT_E = -154, /* ASN input error, not enough data */ + ASN_SIG_CONFIRM_E = -155, /* ASN sig error, confirm failure */ + ASN_SIG_HASH_E = -156, /* ASN sig error, unsupported hash type */ + ASN_SIG_KEY_E = -157, /* ASN sig error, unsupported key type */ + ASN_DH_KEY_E = -158, /* ASN key init error, invalid input */ + ASN_NTRU_KEY_E = -159, /* ASN ntru key decode error, invalid input */ + ASN_CRIT_EXT_E = -160, /* ASN unsupported critical extension */ + ASN_ALT_NAME_E = -161, /* ASN alternate name error */ + ASN_NO_PEM_HEADER = -162, /* ASN no PEM header found */ + + ECC_BAD_ARG_E = -170, /* ECC input argument of wrong type */ + ASN_ECC_KEY_E = -171, /* ASN ECC bad input */ + ECC_CURVE_OID_E = -172, /* Unsupported ECC OID curve type */ + BAD_FUNC_ARG = -173, /* Bad function argument provided */ + NOT_COMPILED_IN = -174, /* Feature not compiled in */ + UNICODE_SIZE_E = -175, /* Unicode password too big */ + NO_PASSWORD = -176, /* no password provided by user */ + ALT_NAME_E = -177, /* alt name size problem, too big */ + BAD_OCSP_RESPONDER = -178, /* missing key usage extensions */ + + AES_GCM_AUTH_E = -180, /* AES-GCM Authentication check failure */ + AES_CCM_AUTH_E = -181, /* AES-CCM Authentication check failure */ + + ASYNC_INIT_E = -182, /* Async Init type error */ + + COMPRESS_INIT_E = -183, /* Compress init error */ + COMPRESS_E = -184, /* Compress error */ + DECOMPRESS_INIT_E = -185, /* DeCompress init error */ + DECOMPRESS_E = -186, /* DeCompress error */ + + BAD_ALIGN_E = -187, /* Bad alignment for operation, no alloc */ + ASN_NO_SIGNER_E = -188, /* ASN no signer to confirm failure */ + ASN_CRL_CONFIRM_E = -189, /* ASN CRL signature confirm failure */ + ASN_CRL_NO_SIGNER_E = -190, /* ASN CRL no signer to confirm failure */ + ASN_OCSP_CONFIRM_E = -191, /* ASN OCSP signature confirm failure */ + + BAD_STATE_E = -192, /* Bad state operation */ + BAD_PADDING_E = -193, /* Bad padding, msg not correct length */ + + REQ_ATTRIBUTE_E = -194, /* setting cert request attributes error */ + + PKCS7_OID_E = -195, /* PKCS#7, mismatched OID error */ + PKCS7_RECIP_E = -196, /* PKCS#7, recipient error */ + FIPS_NOT_ALLOWED_E = -197, /* FIPS not allowed error */ + ASN_NAME_INVALID_E = -198, /* ASN name constraint error */ + + RNG_FAILURE_E = -199, /* RNG Failed, Reinitialize */ + HMAC_MIN_KEYLEN_E = -200, /* FIPS Mode HMAC Minimum Key Length error */ + RSA_PAD_E = -201, /* RSA Padding Error */ + LENGTH_ONLY_E = -202, /* Returning output length only */ + + IN_CORE_FIPS_E = -203, /* In Core Integrity check failure */ + AES_KAT_FIPS_E = -204, /* AES KAT failure */ + DES3_KAT_FIPS_E = -205, /* DES3 KAT failure */ + HMAC_KAT_FIPS_E = -206, /* HMAC KAT failure */ + RSA_KAT_FIPS_E = -207, /* RSA KAT failure */ + DRBG_KAT_FIPS_E = -208, /* HASH DRBG KAT failure */ + DRBG_CONT_FIPS_E = -209, /* HASH DRBG Continuous test failure */ + AESGCM_KAT_FIPS_E = -210, /* AESGCM KAT failure */ + THREAD_STORE_KEY_E = -211, /* Thread local storage key create failure */ + THREAD_STORE_SET_E = -212, /* Thread local storage key set failure */ + + MAC_CMP_FAILED_E = -213, /* MAC comparison failed */ + IS_POINT_E = -214, /* ECC is point on curve failed */ + ECC_INF_E = -215, /* ECC point infinity error */ + ECC_PRIV_KEY_E = -216, /* ECC private key not valid error */ + ECC_OUT_OF_RANGE_E = -217, /* ECC key component out of range */ + + SRP_CALL_ORDER_E = -218, /* SRP function called in the wrong order. */ + SRP_VERIFY_E = -219, /* SRP proof verification failed. */ + SRP_BAD_KEY_E = -220, /* SRP bad ephemeral values. */ + + ASN_NO_SKID = -221, /* ASN no Subject Key Identifier found */ + ASN_NO_AKID = -222, /* ASN no Authority Key Identifier found */ + ASN_NO_KEYUSAGE = -223, /* ASN no Key Usage found */ + SKID_E = -224, /* setting Subject Key Identifier error */ + AKID_E = -225, /* setting Authority Key Identifier error */ + KEYUSAGE_E = -226, /* Bad Key Usage value */ + CERTPOLICIES_E = -227, /* setting Certificate Policies error */ + + WC_INIT_E = -228, /* wolfcrypt failed to initialize */ + SIG_VERIFY_E = -229, /* wolfcrypt signature verify error */ + BAD_COND_E = -230, /* Bad condition variable operation */ + SIG_TYPE_E = -231, /* Signature Type not enabled/available */ + HASH_TYPE_E = -232, /* Hash Type not enabled/available */ + + WC_KEY_SIZE_E = -234, /* Key size error, either too small or large */ + ASN_COUNTRY_SIZE_E = -235, /* ASN Cert Gen, invalid country code size */ + MISSING_RNG_E = -236, /* RNG required but not provided */ + ASN_PATHLEN_SIZE_E = -237, /* ASN CA path length too large error */ + ASN_PATHLEN_INV_E = -238, /* ASN CA path length inversion error */ + + BAD_KEYWRAP_ALG_E = -239, + BAD_KEYWRAP_IV_E = -240, /* Decrypted AES key wrap IV incorrect */ + WC_CLEANUP_E = -241, /* wolfcrypt cleanup failed */ + ECC_CDH_KAT_FIPS_E = -242, /* ECC CDH Known Answer Test failure */ + DH_CHECK_PUB_E = -243, /* DH Check Pub Key error */ + BAD_PATH_ERROR = -244, /* Bad path for opendir */ + + ASYNC_OP_E = -245, /* Async operation error */ + + ECC_PRIVATEONLY_E = -246, /* Invalid use of private only ECC key*/ + EXTKEYUSAGE_E = -247, /* Bad Extended Key Usage value */ + WC_HW_E = -248, /* Error with hardware crypto use */ + WC_HW_WAIT_E = -249, /* Hardware waiting on resource */ + + PSS_SALTLEN_E = -250, /* PSS length of salt is to long for hash */ + PRIME_GEN_E = -251, /* Failure finding a prime. */ + BER_INDEF_E = -252, /* Cannot decode indefinite length BER. */ + RSA_OUT_OF_RANGE_E = -253, /* Ciphertext to decrypt out of range. */ + RSAPSS_PAT_FIPS_E = -254, /* RSA-PSS PAT failure */ + ECDSA_PAT_FIPS_E = -255, /* ECDSA PAT failure */ + DH_KAT_FIPS_E = -256, /* DH KAT failure */ + AESCCM_KAT_FIPS_E = -257, /* AESCCM KAT failure */ + SHA3_KAT_FIPS_E = -258, /* SHA-3 KAT failure */ + ECDHE_KAT_FIPS_E = -259, /* ECDHE KAT failure */ + AES_GCM_OVERFLOW_E = -260, /* AES-GCM invocation counter overflow. */ + AES_CCM_OVERFLOW_E = -261, /* AES-CCM invocation counter overflow. */ + RSA_KEY_PAIR_E = -262, /* RSA Key Pair-Wise Consistency check fail. */ + DH_CHECK_PRIV_E = -263, /* DH Check Priv Key error */ + + WC_AFALG_SOCK_E = -264, /* AF_ALG socket error */ + WC_DEVCRYPTO_E = -265, /* /dev/crypto error */ + + ZLIB_INIT_ERROR = -266, /* zlib init error */ + ZLIB_COMPRESS_ERROR = -267, /* zlib compression error */ + ZLIB_DECOMPRESS_ERROR = -268, /* zlib decompression error */ + + PKCS7_NO_SIGNER_E = -269, /* No signer in PKCS#7 signed data msg */ + WC_PKCS7_WANT_READ_E= -270, /* PKCS7 operations wants more input */ + + CRYPTOCB_UNAVAILABLE= -271, /* Crypto callback unavailable */ + PKCS7_SIGNEEDS_CHECK= -272, /* signature needs verified by caller */ + + WC_LAST_E = -272, /* Update this to indicate last error */ + MIN_CODE_E = -300 /* errors -101 - -299 */ + + /* add new companion error id strings for any new error codes + wolfcrypt/src/error.c !!! */ +}; + + +#ifdef NO_ERROR_STRINGS + #define wc_GetErrorString(error) "no support for error strings built in" + #define wc_ErrorString(err, buf) \ + (void)err; XSTRNCPY((buf), wc_GetErrorString((err)), \ + WOLFSSL_MAX_ERROR_SZ); + +#else +WOLFSSL_API void wc_ErrorString(int err, char* buff); +WOLFSSL_API const char* wc_GetErrorString(int error); +#endif + +#ifdef __cplusplus + } /* extern "C" */ +#endif +#endif /* WOLF_CRYPT_ERROR_H */ diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/fe_operations.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/fe_operations.h new file mode 100755 index 0000000..61d17bb --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/fe_operations.h @@ -0,0 +1,210 @@ +/* fe_operations.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifndef WOLF_CRYPT_FE_OPERATIONS_H +#define WOLF_CRYPT_FE_OPERATIONS_H + +#include + +#if defined(HAVE_CURVE25519) || defined(HAVE_ED25519) + +#if !defined(CURVE25519_SMALL) || !defined(ED25519_SMALL) + #include +#endif + +#include + +#if defined(USE_INTEL_SPEEDUP) && !defined(NO_CURVED25519_X64) + #define CURVED25519_X64 +#elif defined(HAVE___UINT128_T) && !defined(NO_CURVED25519_128BIT) + #define CURVED25519_128BIT +#endif + +#if defined(CURVED25519_X64) + #define CURVED25519_ASM_64BIT + #define CURVED25519_ASM +#endif +#if defined(WOLFSSL_ARMASM) + #ifdef __aarch64__ + #define CURVED25519_ASM_64BIT + #else + #define CURVED25519_ASM_32BIT + #endif + #define CURVED25519_ASM +#endif + +/* +fe means field element. +Here the field is \Z/(2^255-19). +An element t, entries t[0]...t[9], represents the integer +t[0]+2^26 t[1]+2^51 t[2]+2^77 t[3]+2^102 t[4]+...+2^230 t[9]. +Bounds on each t[i] vary depending on context. +*/ + +#ifdef __cplusplus + extern "C" { +#endif + +#if defined(CURVE25519_SMALL) || defined(ED25519_SMALL) + #define F25519_SIZE 32 + + WOLFSSL_LOCAL void lm_copy(byte*, const byte*); + WOLFSSL_LOCAL void lm_add(byte*, const byte*, const byte*); + WOLFSSL_LOCAL void lm_sub(byte*, const byte*, const byte*); + WOLFSSL_LOCAL void lm_neg(byte*,const byte*); + WOLFSSL_LOCAL void lm_invert(byte*, const byte*); + WOLFSSL_LOCAL void lm_mul(byte*,const byte*,const byte*); +#endif + + +#if !defined(FREESCALE_LTC_ECC) +WOLFSSL_LOCAL void fe_init(void); + +WOLFSSL_LOCAL int curve25519(byte * q, byte * n, byte * p); +#endif + +/* default to be faster but take more memory */ +#if !defined(CURVE25519_SMALL) || !defined(ED25519_SMALL) + +#ifdef CURVED25519_ASM_64BIT + typedef int64_t fe[4]; +#elif defined(CURVED25519_ASM_32BIT) + typedef int32_t fe[8]; +#elif defined(CURVED25519_128BIT) + typedef int64_t fe[5]; +#else + typedef int32_t fe[10]; +#endif + +WOLFSSL_LOCAL void fe_copy(fe, const fe); +WOLFSSL_LOCAL void fe_add(fe, const fe, const fe); +WOLFSSL_LOCAL void fe_neg(fe,const fe); +WOLFSSL_LOCAL void fe_sub(fe, const fe, const fe); +WOLFSSL_LOCAL void fe_invert(fe, const fe); +WOLFSSL_LOCAL void fe_mul(fe,const fe,const fe); + + +/* Based On Daniel J Bernstein's curve25519 and ed25519 Public Domain ref10 + work. */ + +WOLFSSL_LOCAL void fe_0(fe); +WOLFSSL_LOCAL void fe_1(fe); +WOLFSSL_LOCAL int fe_isnonzero(const fe); +WOLFSSL_LOCAL int fe_isnegative(const fe); +WOLFSSL_LOCAL void fe_tobytes(unsigned char *, const fe); +WOLFSSL_LOCAL void fe_sq(fe, const fe); +WOLFSSL_LOCAL void fe_sq2(fe,const fe); +WOLFSSL_LOCAL void fe_frombytes(fe,const unsigned char *); +WOLFSSL_LOCAL void fe_cswap(fe, fe, int); +WOLFSSL_LOCAL void fe_mul121666(fe,fe); +WOLFSSL_LOCAL void fe_cmov(fe,const fe, int); +WOLFSSL_LOCAL void fe_pow22523(fe,const fe); + +/* 64 type needed for SHA512 */ +WOLFSSL_LOCAL uint64_t load_3(const unsigned char *in); +WOLFSSL_LOCAL uint64_t load_4(const unsigned char *in); + +#ifdef CURVED25519_ASM +WOLFSSL_LOCAL void fe_ge_to_p2(fe rx, fe ry, fe rz, const fe px, const fe py, + const fe pz, const fe pt); +WOLFSSL_LOCAL void fe_ge_to_p3(fe rx, fe ry, fe rz, fe rt, const fe px, + const fe py, const fe pz, const fe pt); +WOLFSSL_LOCAL void fe_ge_dbl(fe rx, fe ry, fe rz, fe rt, const fe px, + const fe py, const fe pz); +WOLFSSL_LOCAL void fe_ge_madd(fe rx, fe ry, fe rz, fe rt, const fe px, + const fe py, const fe pz, const fe pt, + const fe qxy2d, const fe qyplusx, + const fe qyminusx); +WOLFSSL_LOCAL void fe_ge_msub(fe rx, fe ry, fe rz, fe rt, const fe px, + const fe py, const fe pz, const fe pt, + const fe qxy2d, const fe qyplusx, + const fe qyminusx); +WOLFSSL_LOCAL void fe_ge_add(fe rx, fe ry, fe rz, fe rt, const fe px, + const fe py, const fe pz, const fe pt, const fe qz, + const fe qt2d, const fe qyplusx, + const fe qyminusx); +WOLFSSL_LOCAL void fe_ge_sub(fe rx, fe ry, fe rz, fe rt, const fe px, + const fe py, const fe pz, const fe pt, const fe qz, + const fe qt2d, const fe qyplusx, + const fe qyminusx); +WOLFSSL_LOCAL void fe_cmov_table(fe* r, fe* base, signed char b); +#endif /* CURVED25519_ASM */ +#endif /* !CURVE25519_SMALL || !ED25519_SMALL */ + +/* Use less memory and only 32bit types or less, but is slower + Based on Daniel Beer's public domain work. */ +#if defined(CURVE25519_SMALL) || defined(ED25519_SMALL) +static const byte c25519_base_x[F25519_SIZE] = {9}; +static const byte f25519_zero[F25519_SIZE] = {0}; +static const byte f25519_one[F25519_SIZE] = {1}; +static const byte fprime_zero[F25519_SIZE] = {0}; +static const byte fprime_one[F25519_SIZE] = {1}; + +WOLFSSL_LOCAL void fe_load(byte *x, word32 c); +WOLFSSL_LOCAL void fe_normalize(byte *x); +WOLFSSL_LOCAL void fe_inv__distinct(byte *r, const byte *x); + +/* Conditional copy. If condition == 0, then zero is copied to dst. If + * condition == 1, then one is copied to dst. Any other value results in + * undefined behavior. + */ +WOLFSSL_LOCAL void fe_select(byte *dst, const byte *zero, const byte *one, + byte condition); + +/* Multiply a point by a small constant. The two pointers are not + * required to be distinct. + * + * The constant must be less than 2^24. + */ +WOLFSSL_LOCAL void fe_mul_c(byte *r, const byte *a, word32 b); +WOLFSSL_LOCAL void fe_mul__distinct(byte *r, const byte *a, const byte *b); + +/* Compute one of the square roots of the field element, if the element + * is square. The other square is -r. + * + * If the input is not square, the returned value is a valid field + * element, but not the correct answer. If you don't already know that + * your element is square, you should square the return value and test. + */ +WOLFSSL_LOCAL void fe_sqrt(byte *r, const byte *x); + +/* Conditional copy. If condition == 0, then zero is copied to dst. If + * condition == 1, then one is copied to dst. Any other value results in + * undefined behavior. + */ +WOLFSSL_LOCAL void fprime_select(byte *dst, const byte *zero, const byte *one, + byte condition); +WOLFSSL_LOCAL void fprime_add(byte *r, const byte *a, const byte *modulus); +WOLFSSL_LOCAL void fprime_sub(byte *r, const byte *a, const byte *modulus); +WOLFSSL_LOCAL void fprime_mul(byte *r, const byte *a, const byte *b, + const byte *modulus); +WOLFSSL_LOCAL void fprime_copy(byte *x, const byte *a); + +#endif /* CURVE25519_SMALL || ED25519_SMALL */ + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* HAVE_CURVE25519 || HAVE_ED25519 */ + +#endif /* WOLF_CRYPT_FE_OPERATIONS_H */ diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/fips_test.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/fips_test.h new file mode 100755 index 0000000..1358400 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/fips_test.h @@ -0,0 +1,59 @@ +/* fips_test.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifndef WOLF_CRYPT_FIPS_TEST_H +#define WOLF_CRYPT_FIPS_TEST_H + +#include + + +#ifdef __cplusplus + extern "C" { +#endif + +/* Known Answer Test string inputs are hex, internal */ +WOLFSSL_LOCAL int DoKnownAnswerTests(char*, int); + + +/* FIPS failure callback */ +typedef void(*wolfCrypt_fips_cb)(int ok, int err, const char* hash); + +/* Public set function */ +WOLFSSL_API int wolfCrypt_SetCb_fips(wolfCrypt_fips_cb cbf); + +/* Public get status functions */ +WOLFSSL_API int wolfCrypt_GetStatus_fips(void); +WOLFSSL_API const char* wolfCrypt_GetCoreHash_fips(void); + +#ifdef HAVE_FORCE_FIPS_FAILURE + /* Public function to force failure mode for operational testing */ + WOLFSSL_API int wolfCrypt_SetStatus_fips(int); +#endif + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLF_CRYPT_FIPS_TEST_H */ + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/ge_operations.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/ge_operations.h new file mode 100755 index 0000000..69de2fc --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/ge_operations.h @@ -0,0 +1,113 @@ +/* ge_operations.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + /* Based On Daniel J Bernstein's ed25519 Public Domain ref10 work. */ + +#ifndef WOLF_CRYPT_GE_OPERATIONS_H +#define WOLF_CRYPT_GE_OPERATIONS_H + +#include + +#ifdef HAVE_ED25519 + +#include + +/* +ge means group element. + +Here the group is the set of pairs (x,y) of field elements (see fe.h) +satisfying -x^2 + y^2 = 1 + d x^2y^2 +where d = -121665/121666. + +Representations: + ge_p2 (projective): (X:Y:Z) satisfying x=X/Z, y=Y/Z + ge_p3 (extended): (X:Y:Z:T) satisfying x=X/Z, y=Y/Z, XY=ZT + ge_p1p1 (completed): ((X:Z),(Y:T)) satisfying x=X/Z, y=Y/T + ge_precomp (Duif): (y+x,y-x,2dxy) +*/ + +#ifdef ED25519_SMALL + typedef byte ge[F25519_SIZE]; +#elif defined(CURVED25519_ASM_64BIT) + typedef int64_t ge[4]; +#elif defined(CURVED25519_ASM_32BIT) + typedef int32_t ge[8]; +#elif defined(CURVED25519_128BIT) + typedef int64_t ge[5]; +#else + typedef int32_t ge[10]; +#endif + +typedef struct { + ge X; + ge Y; + ge Z; +} ge_p2; + +typedef struct { + ge X; + ge Y; + ge Z; + ge T; +} ge_p3; + + +WOLFSSL_LOCAL int ge_compress_key(byte* out, const byte* xIn, const byte* yIn, + word32 keySz); +WOLFSSL_LOCAL int ge_frombytes_negate_vartime(ge_p3 *,const unsigned char *); + +WOLFSSL_LOCAL int ge_double_scalarmult_vartime(ge_p2 *,const unsigned char *, + const ge_p3 *,const unsigned char *); +WOLFSSL_LOCAL void ge_scalarmult_base(ge_p3 *,const unsigned char *); +WOLFSSL_LOCAL void sc_reduce(byte* s); +WOLFSSL_LOCAL void sc_muladd(byte* s, const byte* a, const byte* b, + const byte* c); +WOLFSSL_LOCAL void ge_tobytes(unsigned char *,const ge_p2 *); +WOLFSSL_LOCAL void ge_p3_tobytes(unsigned char *,const ge_p3 *); + + +#ifndef ED25519_SMALL +typedef struct { + ge X; + ge Y; + ge Z; + ge T; +} ge_p1p1; + +typedef struct { + ge yplusx; + ge yminusx; + ge xy2d; +} ge_precomp; + +typedef struct { + ge YplusX; + ge YminusX; + ge Z; + ge T2d; +} ge_cached; + +#endif /* !ED25519_SMALL */ + +#endif /* HAVE_ED25519 */ + +#endif /* WOLF_CRYPT_GE_OPERATIONS_H */ diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/hash.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/hash.h new file mode 100755 index 0000000..85983de --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/hash.h @@ -0,0 +1,239 @@ +/* hash.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/*! + \file wolfssl/wolfcrypt/hash.h +*/ + +#ifndef WOLF_CRYPT_HASH_H +#define WOLF_CRYPT_HASH_H + +#include + +#ifndef NO_MD5 + #include +#endif +#ifndef NO_SHA + #include +#endif +#if defined(WOLFSSL_SHA224) || !defined(NO_SHA256) + #include +#endif +#if defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHA512) + #include +#endif +#ifdef HAVE_BLAKE2 + #include +#endif +#ifdef WOLFSSL_SHA3 + #include +#endif +#ifndef NO_MD4 + #include +#endif +#ifdef WOLFSSL_MD2 + #include +#endif +#if defined(HAVE_BLAKE2) || defined(HAVE_BLAKE2S) + #include +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + +#if !defined(HAVE_FIPS) && !defined(NO_OLD_WC_NAMES) + #define MAX_DIGEST_SIZE WC_MAX_DIGEST_SIZE +#endif + + +/* Supported Message Authentication Codes from page 43 */ +enum wc_MACAlgorithm { + no_mac, + md5_mac, + sha_mac, + sha224_mac, + sha256_mac, /* needs to match external KDF_MacAlgorithm */ + sha384_mac, + sha512_mac, + rmd_mac, + blake2b_mac +}; + +enum wc_HashFlags { + WC_HASH_FLAG_NONE = 0x00000000, + WC_HASH_FLAG_WILLCOPY = 0x00000001, /* flag to indicate hash will be copied */ + WC_HASH_FLAG_ISCOPY = 0x00000002, /* hash is copy */ +}; + + +typedef union { + #ifndef NO_MD5 + wc_Md5 md5; + #endif + #ifndef NO_SHA + wc_Sha sha; + #endif + #ifdef WOLFSSL_SHA224 + wc_Sha224 sha224; + #endif + #ifndef NO_SHA256 + wc_Sha256 sha256; + #endif + #ifdef WOLFSSL_SHA384 + wc_Sha384 sha384; + #endif + #ifdef WOLFSSL_SHA512 + wc_Sha512 sha512; + #endif + #ifdef WOLFSSL_SHA3 + wc_Sha3 sha3; + #endif +} wc_HashAlg; + +/* Find largest possible digest size + Note if this gets up to the size of 80 or over check smallstack build */ +#if defined(WOLFSSL_SHA3) + #define WC_MAX_DIGEST_SIZE WC_SHA3_512_DIGEST_SIZE + #define WC_MAX_BLOCK_SIZE WC_SHA3_224_BLOCK_SIZE /* 224 is the largest block size */ +#elif defined(WOLFSSL_SHA512) + #define WC_MAX_DIGEST_SIZE WC_SHA512_DIGEST_SIZE + #define WC_MAX_BLOCK_SIZE WC_SHA512_BLOCK_SIZE +#elif defined(HAVE_BLAKE2) + #define WC_MAX_DIGEST_SIZE BLAKE2B_OUTBYTES + #define WC_MAX_BLOCK_SIZE BLAKE2B_BLOCKBYTES +#elif defined(WOLFSSL_SHA384) + #define WC_MAX_DIGEST_SIZE WC_SHA384_DIGEST_SIZE + #define WC_MAX_BLOCK_SIZE WC_SHA384_BLOCK_SIZE +#elif !defined(NO_SHA256) + #define WC_MAX_DIGEST_SIZE WC_SHA256_DIGEST_SIZE + #define WC_MAX_BLOCK_SIZE WC_SHA256_BLOCK_SIZE +#elif defined(WOLFSSL_SHA224) + #define WC_MAX_DIGEST_SIZE WC_SHA224_DIGEST_SIZE + #define WC_MAX_BLOCK_SIZE WC_SHA224_BLOCK_SIZE +#elif !defined(NO_SHA) + #define WC_MAX_DIGEST_SIZE WC_SHA_DIGEST_SIZE + #define WC_MAX_BLOCK_SIZE WC_SHA_BLOCK_SIZE +#elif !defined(NO_MD5) + #define WC_MAX_DIGEST_SIZE WC_MD5_DIGEST_SIZE + #define WC_MAX_BLOCK_SIZE WC_MD5_BLOCK_SIZE +#else + #define WC_MAX_DIGEST_SIZE 64 /* default to max size of 64 */ + #define WC_MAX_BLOCK_SIZE 128 +#endif + +#if !defined(NO_ASN) || !defined(NO_DH) || defined(HAVE_ECC) +WOLFSSL_API int wc_HashGetOID(enum wc_HashType hash_type); +WOLFSSL_API enum wc_HashType wc_OidGetHash(int oid); +#endif + +WOLFSSL_API enum wc_HashType wc_HashTypeConvert(int hashType); + +WOLFSSL_API int wc_HashGetDigestSize(enum wc_HashType hash_type); +WOLFSSL_API int wc_HashGetBlockSize(enum wc_HashType hash_type); +WOLFSSL_API int wc_Hash(enum wc_HashType hash_type, + const byte* data, word32 data_len, + byte* hash, word32 hash_len); + +/* generic hash operation wrappers */ +WOLFSSL_API int wc_HashInit(wc_HashAlg* hash, enum wc_HashType type); +WOLFSSL_API int wc_HashUpdate(wc_HashAlg* hash, enum wc_HashType type, + const byte* data, word32 dataSz); +WOLFSSL_API int wc_HashFinal(wc_HashAlg* hash, enum wc_HashType type, + byte* out); +WOLFSSL_API int wc_HashFree(wc_HashAlg* hash, enum wc_HashType type); + +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + WOLFSSL_LOCAL int wc_HashSetFlags(wc_HashAlg* hash, enum wc_HashType type, + word32 flags); + WOLFSSL_LOCAL int wc_HashGetFlags(wc_HashAlg* hash, enum wc_HashType type, + word32* flags); +#endif + +#ifndef NO_MD5 +#include +WOLFSSL_API int wc_Md5Hash(const byte* data, word32 len, byte* hash); +#endif + +#ifndef NO_SHA +#include +WOLFSSL_API int wc_ShaHash(const byte*, word32, byte*); +#endif + +#ifdef WOLFSSL_SHA224 +#include +WOLFSSL_API int wc_Sha224Hash(const byte*, word32, byte*); +#endif /* defined(WOLFSSL_SHA224) */ + +#ifndef NO_SHA256 +#include +WOLFSSL_API int wc_Sha256Hash(const byte*, word32, byte*); +#endif + +#ifdef WOLFSSL_SHA384 +#include +WOLFSSL_API int wc_Sha384Hash(const byte*, word32, byte*); +#endif /* defined(WOLFSSL_SHA384) */ + +#ifdef WOLFSSL_SHA512 +#include +WOLFSSL_API int wc_Sha512Hash(const byte*, word32, byte*); +#endif /* WOLFSSL_SHA512 */ + +#ifdef WOLFSSL_SHA3 +#include +WOLFSSL_API int wc_Sha3_224Hash(const byte*, word32, byte*); +WOLFSSL_API int wc_Sha3_256Hash(const byte*, word32, byte*); +WOLFSSL_API int wc_Sha3_384Hash(const byte*, word32, byte*); +WOLFSSL_API int wc_Sha3_512Hash(const byte*, word32, byte*); +#endif /* WOLFSSL_SHA3 */ + +enum max_prf { +#ifdef HAVE_FFDHE_8192 + MAX_PRF_HALF = 516, /* Maximum half secret len */ +#elif defined(HAVE_FFDHE_6144) + MAX_PRF_HALF = 388, /* Maximum half secret len */ +#else + MAX_PRF_HALF = 260, /* Maximum half secret len */ +#endif + MAX_PRF_LABSEED = 128, /* Maximum label + seed len */ + MAX_PRF_DIG = 224 /* Maximum digest len */ +}; + +#ifdef WOLFSSL_HAVE_PRF +WOLFSSL_API int wc_PRF(byte* result, word32 resLen, const byte* secret, + word32 secLen, const byte* seed, word32 seedLen, int hash, + void* heap, int devId); +WOLFSSL_API int wc_PRF_TLSv1(byte* digest, word32 digLen, const byte* secret, + word32 secLen, const byte* label, word32 labLen, + const byte* seed, word32 seedLen, void* heap, int devId); +WOLFSSL_API int wc_PRF_TLS(byte* digest, word32 digLen, const byte* secret, + word32 secLen, const byte* label, word32 labLen, + const byte* seed, word32 seedLen, int useAtLeastSha256, + int hash_type, void* heap, int devId); +#endif /* WOLFSSL_HAVE_PRF */ + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLF_CRYPT_HASH_H */ diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/hc128.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/hc128.h new file mode 100755 index 0000000..7b81f2e --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/hc128.h @@ -0,0 +1,67 @@ +/* hc128.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/*! + \file wolfssl/wolfcrypt/hc128.h +*/ + + +#ifndef WOLF_CRYPT_HC128_H +#define WOLF_CRYPT_HC128_H + +#include + +#ifndef NO_HC128 + +#ifdef __cplusplus + extern "C" { +#endif + +enum { + HC128_ENC_TYPE = WC_CIPHER_HC128, /* cipher unique type */ +}; + +/* HC-128 stream cipher */ +typedef struct HC128 { + word32 T[1024]; /* P[i] = T[i]; Q[i] = T[1024 + i ]; */ + word32 X[16]; + word32 Y[16]; + word32 counter1024; /* counter1024 = i mod 1024 at the ith step */ + word32 key[8]; + word32 iv[8]; +#ifdef XSTREAM_ALIGN + void* heap; /* heap hint, currently XMALLOC only used with aligning */ +#endif +} HC128; + + +WOLFSSL_API int wc_Hc128_Process(HC128*, byte*, const byte*, word32); +WOLFSSL_API int wc_Hc128_SetKey(HC128*, const byte* key, const byte* iv); + +WOLFSSL_LOCAL int wc_Hc128_SetHeap(HC128* ctx, void* heap); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* HAVE_HC128 */ +#endif /* WOLF_CRYPT_HC128_H */ + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/hmac.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/hmac.h new file mode 100755 index 0000000..96e8b36 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/hmac.h @@ -0,0 +1,210 @@ +/* hmac.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/*! + \file wolfssl/wolfcrypt/hmac.h +*/ + +#ifndef NO_HMAC + +#ifndef WOLF_CRYPT_HMAC_H +#define WOLF_CRYPT_HMAC_H + +#include + +#if defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) +/* for fips @wc_fips */ + #include + #define WC_HMAC_BLOCK_SIZE HMAC_BLOCK_SIZE +#endif + + +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + #include +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +/* avoid redefinition of structs */ +#if !defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) + +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif + +#ifndef NO_OLD_WC_NAMES + #define HMAC_BLOCK_SIZE WC_HMAC_BLOCK_SIZE +#endif + +#define WC_HMAC_INNER_HASH_KEYED_SW 1 +#define WC_HMAC_INNER_HASH_KEYED_DEV 2 + +enum { + HMAC_FIPS_MIN_KEY = 14, /* 112 bit key length minimum */ + + IPAD = 0x36, + OPAD = 0x5C, + +/* If any hash is not enabled, add the ID here. */ +#ifdef NO_MD5 + WC_MD5 = WC_HASH_TYPE_MD5, +#endif +#ifdef NO_SHA + WC_SHA = WC_HASH_TYPE_SHA, +#endif +#ifdef NO_SHA256 + WC_SHA256 = WC_HASH_TYPE_SHA256, +#endif +#ifndef WOLFSSL_SHA512 + WC_SHA512 = WC_HASH_TYPE_SHA512, +#endif +#ifndef WOLFSSL_SHA384 + WC_SHA384 = WC_HASH_TYPE_SHA384, +#endif +#ifndef HAVE_BLAKE2B + BLAKE2B_ID = WC_HASH_TYPE_BLAKE2B, +#endif +#ifndef HAVE_BLAKE2S + BLAKE2S_ID = WC_HASH_TYPE_BLAKE2S, +#endif +#ifndef WOLFSSL_SHA224 + WC_SHA224 = WC_HASH_TYPE_SHA224, +#endif +#ifndef WOLFSSL_SHA3 + WC_SHA3_224 = WC_HASH_TYPE_SHA3_224, + WC_SHA3_256 = WC_HASH_TYPE_SHA3_256, + WC_SHA3_384 = WC_HASH_TYPE_SHA3_384, + WC_SHA3_512 = WC_HASH_TYPE_SHA3_512, +#endif +#ifdef HAVE_PKCS11 + HMAC_MAX_ID_LEN = 32, +#endif +}; + +/* Select the largest available hash for the buffer size. */ +#define WC_HMAC_BLOCK_SIZE WC_MAX_BLOCK_SIZE + +#if !defined(WOLFSSL_SHA3) && !defined(WOLFSSL_SHA512) && !defined(HAVE_BLAKE2) && \ + !defined(WOLFSSL_SHA384) && defined(NO_SHA256) && defined(WOLFSSL_SHA224) && \ + defined(NO_SHA) && defined(NO_MD5) + #error "You have to have some kind of hash if you want to use HMAC." +#endif + + +/* hash union */ +typedef union { +#ifndef NO_MD5 + wc_Md5 md5; +#endif +#ifndef NO_SHA + wc_Sha sha; +#endif +#ifdef WOLFSSL_SHA224 + wc_Sha224 sha224; +#endif +#ifndef NO_SHA256 + wc_Sha256 sha256; +#endif +#ifdef WOLFSSL_SHA384 + wc_Sha384 sha384; +#endif +#ifdef WOLFSSL_SHA512 + wc_Sha512 sha512; +#endif +#ifdef HAVE_BLAKE2 + Blake2b blake2b; +#endif +#ifdef WOLFSSL_SHA3 + wc_Sha3 sha3; +#endif +} Hash; + +/* Hmac digest */ +typedef struct Hmac { + Hash hash; + word32 ipad[WC_HMAC_BLOCK_SIZE / sizeof(word32)]; /* same block size all*/ + word32 opad[WC_HMAC_BLOCK_SIZE / sizeof(word32)]; + word32 innerHash[WC_MAX_DIGEST_SIZE / sizeof(word32)]; + void* heap; /* heap hint */ + byte macType; /* md5 sha or sha256 */ + byte innerHashKeyed; /* keyed flag */ +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV asyncDev; +#endif /* WOLFSSL_ASYNC_CRYPT */ +#ifdef WOLF_CRYPTO_CB + int devId; + void* devCtx; + const byte* keyRaw; +#endif +#ifdef HAVE_PKCS11 + byte id[HMAC_MAX_ID_LEN]; + int idLen; +#endif +#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB) + word16 keyLen; /* hmac key length (key in ipad) */ +#endif +} Hmac; + +#endif /* HAVE_FIPS */ + +/* does init */ +WOLFSSL_API int wc_HmacSetKey(Hmac*, int type, const byte* key, word32 keySz); +WOLFSSL_API int wc_HmacUpdate(Hmac*, const byte*, word32); +WOLFSSL_API int wc_HmacFinal(Hmac*, byte*); +WOLFSSL_API int wc_HmacSizeByType(int type); + +WOLFSSL_API int wc_HmacInit(Hmac* hmac, void* heap, int devId); +WOLFSSL_API int wc_HmacInit_Id(Hmac* hmac, byte* id, int len, void* heap, + int devId); +WOLFSSL_API void wc_HmacFree(Hmac*); + +WOLFSSL_API int wolfSSL_GetHmacMaxSize(void); + +WOLFSSL_LOCAL int _InitHmac(Hmac* hmac, int type, void* heap); + +#ifdef HAVE_HKDF + +WOLFSSL_API int wc_HKDF_Extract(int type, const byte* salt, word32 saltSz, + const byte* inKey, word32 inKeySz, byte* out); +WOLFSSL_API int wc_HKDF_Expand(int type, const byte* inKey, word32 inKeySz, + const byte* info, word32 infoSz, + byte* out, word32 outSz); + +WOLFSSL_API int wc_HKDF(int type, const byte* inKey, word32 inKeySz, + const byte* salt, word32 saltSz, + const byte* info, word32 infoSz, + byte* out, word32 outSz); + +#endif /* HAVE_HKDF */ + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLF_CRYPT_HMAC_H */ + +#endif /* NO_HMAC */ + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/idea.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/idea.h new file mode 100755 index 0000000..706ac3c --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/idea.h @@ -0,0 +1,70 @@ +/* idea.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/*! + \file wolfssl/wolfcrypt/idea.h +*/ + +#ifndef WOLF_CRYPT_IDEA_H +#define WOLF_CRYPT_IDEA_H + +#include + +#ifdef HAVE_IDEA + +#ifdef __cplusplus + extern "C" { +#endif + +enum { + IDEA_MODULO = 0x10001, /* 2^16+1 */ + IDEA_2EXP16 = 0x10000, /* 2^16 */ + IDEA_MASK = 0xFFFF, /* 16 bits set to one */ + IDEA_ROUNDS = 8, /* number of rounds for IDEA */ + IDEA_SK_NUM = (6*IDEA_ROUNDS + 4), /* number of subkeys */ + IDEA_KEY_SIZE = 16, /* size of key in bytes */ + IDEA_BLOCK_SIZE = 8, /* size of IDEA blocks in bytes */ + IDEA_IV_SIZE = 8, /* size of IDEA IV in bytes */ + IDEA_ENCRYPTION = 0, + IDEA_DECRYPTION = 1 +}; + +/* IDEA encryption and decryption */ +typedef struct Idea { + word32 reg[IDEA_BLOCK_SIZE / sizeof(word32)]; /* for CBC mode */ + word32 tmp[IDEA_BLOCK_SIZE / sizeof(word32)]; /* for CBC mode */ + word16 skey[IDEA_SK_NUM]; /* 832 bits expanded key */ +} Idea; + +WOLFSSL_API int wc_IdeaSetKey(Idea *idea, const byte* key, word16 keySz, + const byte *iv, int dir); +WOLFSSL_API int wc_IdeaSetIV(Idea *idea, const byte* iv); +WOLFSSL_API int wc_IdeaCipher(Idea *idea, byte* out, const byte* in); +WOLFSSL_API int wc_IdeaCbcEncrypt(Idea *idea, byte* out, + const byte* in, word32 len); +WOLFSSL_API int wc_IdeaCbcDecrypt(Idea *idea, byte* out, + const byte* in, word32 len); +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* HAVE_IDEA */ +#endif /* WOLF_CRYPT_IDEA_H */ diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/include.am b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/include.am new file mode 100755 index 0000000..98a1487 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/include.am @@ -0,0 +1,124 @@ +# vim:ft=automake +# All paths should be given relative to the root + +nobase_include_HEADERS+= \ + wolfssl/wolfcrypt/aes.h \ + wolfssl/wolfcrypt/arc4.h \ + wolfssl/wolfcrypt/asn.h \ + wolfssl/wolfcrypt/asn_public.h \ + wolfssl/wolfcrypt/poly1305.h \ + wolfssl/wolfcrypt/camellia.h \ + wolfssl/wolfcrypt/cmac.h \ + wolfssl/wolfcrypt/coding.h \ + wolfssl/wolfcrypt/compress.h \ + wolfssl/wolfcrypt/des3.h \ + wolfssl/wolfcrypt/dh.h \ + wolfssl/wolfcrypt/dsa.h \ + wolfssl/wolfcrypt/ecc.h \ + wolfssl/wolfcrypt/curve25519.h \ + wolfssl/wolfcrypt/ed25519.h \ + wolfssl/wolfcrypt/fe_operations.h \ + wolfssl/wolfcrypt/ge_operations.h \ + wolfssl/wolfcrypt/error-crypt.h \ + wolfssl/wolfcrypt/fips_test.h \ + wolfssl/wolfcrypt/hash.h \ + wolfssl/wolfcrypt/hc128.h \ + wolfssl/wolfcrypt/hmac.h \ + wolfssl/wolfcrypt/integer.h \ + wolfssl/wolfcrypt/md2.h \ + wolfssl/wolfcrypt/md4.h \ + wolfssl/wolfcrypt/md5.h \ + wolfssl/wolfcrypt/misc.h \ + wolfssl/wolfcrypt/pkcs7.h \ + wolfssl/wolfcrypt/wc_encrypt.h \ + wolfssl/wolfcrypt/wc_port.h \ + wolfssl/wolfcrypt/pwdbased.h \ + wolfssl/wolfcrypt/rabbit.h \ + wolfssl/wolfcrypt/chacha.h \ + wolfssl/wolfcrypt/chacha20_poly1305.h \ + wolfssl/wolfcrypt/random.h \ + wolfssl/wolfcrypt/ripemd.h \ + wolfssl/wolfcrypt/rsa.h \ + wolfssl/wolfcrypt/settings.h \ + wolfssl/wolfcrypt/sha256.h \ + wolfssl/wolfcrypt/sha512.h \ + wolfssl/wolfcrypt/sha.h \ + wolfssl/wolfcrypt/signature.h \ + wolfssl/wolfcrypt/blake2.h \ + wolfssl/wolfcrypt/blake2-int.h \ + wolfssl/wolfcrypt/blake2-impl.h \ + wolfssl/wolfcrypt/tfm.h \ + wolfssl/wolfcrypt/srp.h \ + wolfssl/wolfcrypt/idea.h \ + wolfssl/wolfcrypt/types.h \ + wolfssl/wolfcrypt/visibility.h \ + wolfssl/wolfcrypt/logging.h \ + wolfssl/wolfcrypt/memory.h \ + wolfssl/wolfcrypt/mpi_class.h \ + wolfssl/wolfcrypt/mpi_superclass.h \ + wolfssl/wolfcrypt/mem_track.h \ + wolfssl/wolfcrypt/wolfevent.h \ + wolfssl/wolfcrypt/pkcs12.h \ + wolfssl/wolfcrypt/wolfmath.h \ + wolfssl/wolfcrypt/sha3.h \ + wolfssl/wolfcrypt/cpuid.h \ + wolfssl/wolfcrypt/cryptocb.h + +noinst_HEADERS+= \ + wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h \ + wolfssl/wolfcrypt/port/ti/ti-hash.h \ + wolfssl/wolfcrypt/port/ti/ti-ccm.h \ + wolfssl/wolfcrypt/port/nrf51.h \ + wolfssl/wolfcrypt/port/nxp/ksdk_port.h \ + wolfssl/wolfcrypt/port/xilinx/xil-sha3.h \ + wolfssl/wolfcrypt/port/caam/caam_driver.h \ + wolfssl/wolfcrypt/port/caam/wolfcaam.h \ + wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h \ + wolfssl/wolfcrypt/port/st/stm32.h \ + wolfssl/wolfcrypt/port/st/stsafe.h \ + wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h \ + wolfssl/wolfcrypt/port/arm/cryptoCell.h + +if BUILD_CRYPTOAUTHLIB +nobase_include_HEADERS+= wolfssl/wolfcrypt/port/atmel/atmel.h +endif + +if BUILD_AFALG +nobase_include_HEADERS+= wolfssl/wolfcrypt/port/af_alg/afalg_hash.h +nobase_include_HEADERS+= wolfssl/wolfcrypt/port/af_alg/wc_afalg.h +endif + +if BUILD_DEVCRYPTO +nobase_include_HEADERS+= wolfssl/wolfcrypt/port/devcrypto/wc_devcrypto.h +endif + +if BUILD_ASYNCCRYPT +nobase_include_HEADERS+= wolfssl/wolfcrypt/async.h +endif + +if BUILD_PKCS11 +nobase_include_HEADERS+= wolfssl/wolfcrypt/wc_pkcs11.h +nobase_include_HEADERS+= wolfssl/wolfcrypt/pkcs11.h +endif + +if BUILD_CAVIUM +nobase_include_HEADERS+= wolfssl/wolfcrypt/port/cavium/cavium_nitrox.h +endif + +if BUILD_INTEL_QA +nobase_include_HEADERS+= wolfssl/wolfcrypt/port/intel/quickassist.h +nobase_include_HEADERS+= wolfssl/wolfcrypt/port/intel/quickassist_mem.h +endif + +if BUILD_SP +nobase_include_HEADERS+= wolfssl/wolfcrypt/sp.h +nobase_include_HEADERS+= wolfssl/wolfcrypt/sp_int.h +endif + +if BUILD_SELFTEST +nobase_include_HEADERS+= wolfssl/wolfcrypt/selftest.h +endif + +if BUILD_FIPS_V2 +nobase_include_HEADERS+= wolfssl/wolfcrypt/fips.h +endif diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/integer.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/integer.h new file mode 100755 index 0000000..162bce4 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/integer.h @@ -0,0 +1,402 @@ +/* integer.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +/* + * Based on public domain LibTomMath 0.38 by Tom St Denis, tomstdenis@iahu.ca, + * http://math.libtomcrypt.com + */ + + +#ifndef WOLF_CRYPT_INTEGER_H +#define WOLF_CRYPT_INTEGER_H + +/* may optionally use fast math instead, not yet supported on all platforms and + may not be faster on all +*/ +#include /* will set MP_xxBIT if not default */ +#ifdef WOLFSSL_SP_MATH + #include +#elif defined(USE_FAST_MATH) + #include +#else + +#include + +#ifndef CHAR_BIT + #include +#endif + +#include + + +#ifdef __cplusplus +extern "C" { + +/* C++ compilers don't like assigning void * to mp_digit * */ +#define OPT_CAST(x) (x *) + +#elif defined(_SH3) + +/* SuperH SH3 compiler doesn't like assigning voi* to mp_digit* */ +#define OPT_CAST(x) (x *) + +#else + +/* C on the other hand doesn't care */ +#define OPT_CAST(x) + +#endif /* __cplusplus */ + + +/* detect 64-bit mode if possible */ +#if defined(__x86_64__) && !(defined (_MSC_VER) && defined(__clang__)) + #if !(defined(MP_64BIT) && defined(MP_16BIT) && defined(MP_8BIT)) + #define MP_64BIT + #endif +#endif +/* if intel compiler doesn't provide 128 bit type don't turn on 64bit */ +#if defined(MP_64BIT) && defined(__INTEL_COMPILER) && !defined(HAVE___UINT128_T) + #undef MP_64BIT +#endif + + +/* allow user to define on mp_digit, mp_word, DIGIT_BIT types */ +#ifndef WOLFSSL_BIGINT_TYPES + +/* some default configurations. + * + * A "mp_digit" must be able to hold DIGIT_BIT + 1 bits + * A "mp_word" must be able to hold 2*DIGIT_BIT + 1 bits + * + * At the very least a mp_digit must be able to hold 7 bits + * [any size beyond that is ok provided it doesn't overflow the data type] + */ +#ifdef MP_8BIT + /* 8-bit */ + typedef unsigned char mp_digit; + typedef unsigned short mp_word; + /* don't define DIGIT_BIT, so its calculated below */ +#elif defined(MP_16BIT) + /* 16-bit */ + typedef unsigned int mp_digit; + typedef unsigned long mp_word; + /* don't define DIGIT_BIT, so its calculated below */ +#elif defined(NO_64BIT) + /* 32-bit forced to 16-bit */ + typedef unsigned short mp_digit; + typedef unsigned int mp_word; + #define DIGIT_BIT 12 +#elif defined(MP_64BIT) + /* 64-bit */ + /* for GCC only on supported platforms */ + typedef unsigned long long mp_digit; /* 64 bit type, 128 uses mode(TI) */ + typedef unsigned long mp_word __attribute__ ((mode(TI))); + #define DIGIT_BIT 60 +#else + /* 32-bit default case */ + + #if defined(_MSC_VER) || defined(__BORLANDC__) + typedef unsigned __int64 ulong64; + #else + typedef unsigned long long ulong64; + #endif + + typedef unsigned int mp_digit; /* long could be 64 now, changed TAO */ + typedef ulong64 mp_word; + + #ifdef MP_31BIT + /* this is an extension that uses 31-bit digits */ + #define DIGIT_BIT 31 + #else + /* default case is 28-bit digits, defines MP_28BIT as a handy test macro */ + #define DIGIT_BIT 28 + #define MP_28BIT + #endif +#endif + +#endif /* WOLFSSL_BIGINT_TYPES */ + +/* otherwise the bits per digit is calculated automatically from the size of + a mp_digit */ +#ifndef DIGIT_BIT + #define DIGIT_BIT ((int)((CHAR_BIT * sizeof(mp_digit) - 1))) + /* bits per digit */ +#endif + +#define MP_DIGIT_BIT DIGIT_BIT +#define MP_MASK ((((mp_digit)1)<<((mp_digit)DIGIT_BIT))-((mp_digit)1)) +#define MP_DIGIT_MAX MP_MASK + +/* equalities */ +#define MP_LT -1 /* less than */ +#define MP_EQ 0 /* equal to */ +#define MP_GT 1 /* greater than */ + +#define MP_ZPOS 0 /* positive integer */ +#define MP_NEG 1 /* negative */ + +#define MP_OKAY 0 /* ok result */ +#define MP_MEM -2 /* out of mem */ +#define MP_VAL -3 /* invalid input */ +#define MP_NOT_INF -4 /* point not at infinity */ +#define MP_RANGE MP_NOT_INF + +#define MP_YES 1 /* yes response */ +#define MP_NO 0 /* no response */ + +/* Primality generation flags */ +#define LTM_PRIME_BBS 0x0001 /* BBS style prime */ +#define LTM_PRIME_SAFE 0x0002 /* Safe prime (p-1)/2 == prime */ +#define LTM_PRIME_2MSB_ON 0x0008 /* force 2nd MSB to 1 */ + +typedef int mp_err; + +/* define this to use lower memory usage routines (exptmods mostly) */ +#define MP_LOW_MEM + +/* default precision */ +#ifndef MP_PREC + #ifndef MP_LOW_MEM + #define MP_PREC 32 /* default digits of precision */ + #else + #define MP_PREC 1 /* default digits of precision */ + #endif +#endif + +/* size of comba arrays, should be at least 2 * 2**(BITS_PER_WORD - + BITS_PER_DIGIT*2) */ +#define MP_WARRAY ((mp_word)1 << (sizeof(mp_word) * CHAR_BIT - 2 * DIGIT_BIT + 1)) + +#ifdef HAVE_WOLF_BIGINT + /* raw big integer */ + typedef struct WC_BIGINT { + byte* buf; + word32 len; + void* heap; + } WC_BIGINT; + #define WOLF_BIGINT_DEFINED +#endif + +/* the mp_int structure */ +typedef struct mp_int { + int used, alloc, sign; + mp_digit *dp; + +#ifdef HAVE_WOLF_BIGINT + struct WC_BIGINT raw; /* unsigned binary (big endian) */ +#endif +} mp_int; + +/* wolf big int and common functions */ +#include + + +/* callback for mp_prime_random, should fill dst with random bytes and return + how many read [up to len] */ +typedef int ltm_prime_callback(unsigned char *dst, int len, void *dat); + + +#define USED(m) ((m)->used) +#define DIGIT(m,k) ((m)->dp[(k)]) +#define SIGN(m) ((m)->sign) + + +/* ---> Basic Manipulations <--- */ +#define mp_iszero(a) (((a)->used == 0) ? MP_YES : MP_NO) +#define mp_isone(a) \ + (((((a)->used == 1)) && ((a)->dp[0] == 1u)) ? MP_YES : MP_NO) +#define mp_iseven(a) \ + (((a)->used > 0 && (((a)->dp[0] & 1u) == 0u)) ? MP_YES : MP_NO) +#define mp_isodd(a) \ + (((a)->used > 0 && (((a)->dp[0] & 1u) == 1u)) ? MP_YES : MP_NO) +#define mp_isneg(a) (((a)->sign != MP_ZPOS) ? MP_YES : MP_NO) + +/* number of primes */ +#ifdef MP_8BIT + #define PRIME_SIZE 31 +#else + #define PRIME_SIZE 256 +#endif + +#ifndef MAX_INVMOD_SZ + #if defined(WOLFSSL_MYSQL_COMPATIBLE) + #define MAX_INVMOD_SZ 8192 + #else + #define MAX_INVMOD_SZ 4096 + #endif +#endif + +#define mp_prime_random(a, t, size, bbs, cb, dat) \ + mp_prime_random_ex(a, t, ((size) * 8) + 1, (bbs==1)?LTM_PRIME_BBS:0, cb, dat) + +#define mp_read_raw(mp, str, len) mp_read_signed_bin((mp), (str), (len)) +#define mp_raw_size(mp) mp_signed_bin_size(mp) +#define mp_toraw(mp, str) mp_to_signed_bin((mp), (str)) +#define mp_read_mag(mp, str, len) mp_read_unsigned_bin((mp), (str), (len)) +#define mp_mag_size(mp) mp_unsigned_bin_size(mp) +#define mp_tomag(mp, str) mp_to_unsigned_bin((mp), (str)) + +#define MP_RADIX_BIN 2 +#define MP_RADIX_OCT 8 +#define MP_RADIX_DEC 10 +#define MP_RADIX_HEX 16 +#define MP_RADIX_MAX 64 + +#define mp_tobinary(M, S) mp_toradix((M), (S), MP_RADIX_BIN) +#define mp_tooctal(M, S) mp_toradix((M), (S), MP_RADIX_OCT) +#define mp_todecimal(M, S) mp_toradix((M), (S), MP_RADIX_DEC) +#define mp_tohex(M, S) mp_toradix((M), (S), MP_RADIX_HEX) + +#define s_mp_mul(a, b, c) s_mp_mul_digs(a, b, c, (a)->used + (b)->used + 1) + +#if defined(HAVE_ECC) || defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || \ + defined(WOLFSSL_DEBUG_MATH) || defined(DEBUG_WOLFSSL) +extern const char *mp_s_rmap; +#endif + +/* 6 functions needed by Rsa */ +MP_API int mp_init (mp_int * a); +MP_API void mp_clear (mp_int * a); +MP_API void mp_free (mp_int * a); +MP_API void mp_forcezero(mp_int * a); +MP_API int mp_unsigned_bin_size(mp_int * a); +MP_API int mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c); +MP_API int mp_to_unsigned_bin_at_pos(int x, mp_int *t, unsigned char *b); +MP_API int mp_to_unsigned_bin (mp_int * a, unsigned char *b); +MP_API int mp_to_unsigned_bin_len(mp_int * a, unsigned char *b, int c); +MP_API int mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y); +/* end functions needed by Rsa */ + +/* functions added to support above needed, removed TOOM and KARATSUBA */ +MP_API int mp_count_bits (mp_int * a); +MP_API int mp_leading_bit (mp_int * a); +MP_API int mp_init_copy (mp_int * a, mp_int * b); +MP_API int mp_copy (mp_int * a, mp_int * b); +MP_API int mp_grow (mp_int * a, int size); +MP_API int mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d); +MP_API void mp_zero (mp_int * a); +MP_API void mp_clamp (mp_int * a); +MP_API void mp_exch (mp_int * a, mp_int * b); +MP_API void mp_rshd (mp_int * a, int b); +MP_API void mp_rshb (mp_int * a, int b); +MP_API int mp_mod_2d (mp_int * a, int b, mp_int * c); +MP_API int mp_mul_2d (mp_int * a, int b, mp_int * c); +MP_API int mp_lshd (mp_int * a, int b); +MP_API int mp_abs (mp_int * a, mp_int * b); +MP_API int mp_invmod (mp_int * a, mp_int * b, mp_int * c); +int fast_mp_invmod (mp_int * a, mp_int * b, mp_int * c); +MP_API int mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c); +MP_API int mp_cmp_mag (mp_int * a, mp_int * b); +MP_API int mp_cmp (mp_int * a, mp_int * b); +MP_API int mp_cmp_d(mp_int * a, mp_digit b); +MP_API int mp_set (mp_int * a, mp_digit b); +MP_API int mp_is_bit_set (mp_int * a, mp_digit b); +MP_API int mp_mod (mp_int * a, mp_int * b, mp_int * c); +MP_API int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d); +MP_API int mp_div_2(mp_int * a, mp_int * b); +MP_API int mp_add (mp_int * a, mp_int * b, mp_int * c); +int s_mp_add (mp_int * a, mp_int * b, mp_int * c); +int s_mp_sub (mp_int * a, mp_int * b, mp_int * c); +MP_API int mp_sub (mp_int * a, mp_int * b, mp_int * c); +MP_API int mp_reduce_is_2k_l(mp_int *a); +MP_API int mp_reduce_is_2k(mp_int *a); +MP_API int mp_dr_is_modulus(mp_int *a); +MP_API int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, + int); +MP_API int mp_montgomery_setup (mp_int * n, mp_digit * rho); +int fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho); +MP_API int mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho); +MP_API void mp_dr_setup(mp_int *a, mp_digit *d); +MP_API int mp_dr_reduce (mp_int * x, mp_int * n, mp_digit k); +MP_API int mp_reduce_2k(mp_int *a, mp_int *n, mp_digit d); +int fast_s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs); +int s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs); +MP_API int mp_reduce_2k_setup_l(mp_int *a, mp_int *d); +MP_API int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d); +MP_API int mp_reduce (mp_int * x, mp_int * m, mp_int * mu); +MP_API int mp_reduce_setup (mp_int * a, mp_int * b); +int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode); +MP_API int mp_montgomery_calc_normalization (mp_int * a, mp_int * b); +int s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs); +int s_mp_sqr (mp_int * a, mp_int * b); +int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs); +int fast_s_mp_sqr (mp_int * a, mp_int * b); +MP_API int mp_init_size (mp_int * a, int size); +MP_API int mp_div_3 (mp_int * a, mp_int *c, mp_digit * d); +MP_API int mp_mul_2(mp_int * a, mp_int * b); +MP_API int mp_mul (mp_int * a, mp_int * b, mp_int * c); +MP_API int mp_sqr (mp_int * a, mp_int * b); +MP_API int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d); +MP_API int mp_submod (mp_int* a, mp_int* b, mp_int* c, mp_int* d); +MP_API int mp_addmod (mp_int* a, mp_int* b, mp_int* c, mp_int* d); +MP_API int mp_mul_d (mp_int * a, mp_digit b, mp_int * c); +MP_API int mp_2expt (mp_int * a, int b); +MP_API int mp_set_bit (mp_int * a, int b); +MP_API int mp_reduce_2k_setup(mp_int *a, mp_digit *d); +MP_API int mp_add_d (mp_int* a, mp_digit b, mp_int* c); +MP_API int mp_set_int (mp_int * a, unsigned long b); +MP_API int mp_sub_d (mp_int * a, mp_digit b, mp_int * c); +/* end support added functions */ + +/* added */ +MP_API int mp_init_multi(mp_int* a, mp_int* b, mp_int* c, mp_int* d, mp_int* e, + mp_int* f); +MP_API int mp_toradix (mp_int *a, char *str, int radix); +MP_API int mp_radix_size (mp_int * a, int radix, int *size); + +#ifdef WOLFSSL_DEBUG_MATH + MP_API void mp_dump(const char* desc, mp_int* a, byte verbose); +#else + #define mp_dump(desc, a, verbose) +#endif + +#if defined(HAVE_ECC) || defined(WOLFSSL_KEY_GEN) || !defined(NO_RSA) || \ + !defined(NO_DSA) || !defined(NO_DH) + MP_API int mp_sqrmod(mp_int* a, mp_int* b, mp_int* c); +#endif +#if !defined(NO_DSA) || defined(HAVE_ECC) + MP_API int mp_read_radix(mp_int* a, const char* str, int radix); +#endif + +#if defined(WOLFSSL_KEY_GEN) || !defined(NO_RSA) || !defined(NO_DSA) || !defined(NO_DH) + MP_API int mp_prime_is_prime (mp_int * a, int t, int *result); + MP_API int mp_prime_is_prime_ex (mp_int * a, int t, int *result, WC_RNG*); +#endif /* WOLFSSL_KEY_GEN NO_RSA NO_DSA NO_DH */ +#ifdef WOLFSSL_KEY_GEN + MP_API int mp_gcd (mp_int * a, mp_int * b, mp_int * c); + MP_API int mp_lcm (mp_int * a, mp_int * b, mp_int * c); + MP_API int mp_rand_prime(mp_int* N, int len, WC_RNG* rng, void* heap); +#endif + +MP_API int mp_cnt_lsb(mp_int *a); +MP_API int mp_mod_d(mp_int* a, mp_digit b, mp_digit* c); + + +#ifdef __cplusplus + } +#endif + + +#endif /* USE_FAST_MATH */ + +#endif /* WOLF_CRYPT_INTEGER_H */ + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/logging.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/logging.h new file mode 100755 index 0000000..ae2028c --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/logging.h @@ -0,0 +1,187 @@ +/* logging.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/*! + \file wolfssl/wolfcrypt/logging.h +*/ + + +/* submitted by eof */ + + +#ifndef WOLFSSL_LOGGING_H +#define WOLFSSL_LOGGING_H + +#include + +#ifdef __cplusplus + extern "C" { +#endif + + +enum wc_LogLevels { + ERROR_LOG = 0, + INFO_LOG, + ENTER_LOG, + LEAVE_LOG, + OTHER_LOG +}; + +#ifdef WOLFSSL_FUNC_TIME +/* WARNING: This code is only to be used for debugging performance. + * The code is not thread-safe. + * Do not use WOLFSSL_FUNC_TIME in production code. + */ +enum wc_FuncNum { + WC_FUNC_HELLO_REQUEST_SEND = 0, + WC_FUNC_HELLO_REQUEST_DO, + WC_FUNC_CLIENT_HELLO_SEND, + WC_FUNC_CLIENT_HELLO_DO, + WC_FUNC_SERVER_HELLO_SEND, + WC_FUNC_SERVER_HELLO_DO, + WC_FUNC_ENCRYPTED_EXTENSIONS_SEND, + WC_FUNC_ENCRYPTED_EXTENSIONS_DO, + WC_FUNC_CERTIFICATE_REQUEST_SEND, + WC_FUNC_CERTIFICATE_REQUEST_DO, + WC_FUNC_CERTIFICATE_SEND, + WC_FUNC_CERTIFICATE_DO, + WC_FUNC_CERTIFICATE_VERIFY_SEND, + WC_FUNC_CERTIFICATE_VERIFY_DO, + WC_FUNC_FINISHED_SEND, + WC_FUNC_FINISHED_DO, + WC_FUNC_KEY_UPDATE_SEND, + WC_FUNC_KEY_UPDATE_DO, + WC_FUNC_EARLY_DATA_SEND, + WC_FUNC_EARLY_DATA_DO, + WC_FUNC_NEW_SESSION_TICKET_SEND, + WC_FUNC_NEW_SESSION_TICKET_DO, + WC_FUNC_SERVER_HELLO_DONE_SEND, + WC_FUNC_SERVER_HELLO_DONE_DO, + WC_FUNC_TICKET_SEND, + WC_FUNC_TICKET_DO, + WC_FUNC_CLIENT_KEY_EXCHANGE_SEND, + WC_FUNC_CLIENT_KEY_EXCHANGE_DO, + WC_FUNC_CERTIFICATE_STATUS_SEND, + WC_FUNC_CERTIFICATE_STATUS_DO, + WC_FUNC_SERVER_KEY_EXCHANGE_SEND, + WC_FUNC_SERVER_KEY_EXCHANGE_DO, + WC_FUNC_END_OF_EARLY_DATA_SEND, + WC_FUNC_END_OF_EARLY_DATA_DO, + WC_FUNC_COUNT +}; +#endif + +typedef void (*wolfSSL_Logging_cb)(const int logLevel, + const char *const logMessage); + +WOLFSSL_API int wolfSSL_SetLoggingCb(wolfSSL_Logging_cb log_function); + +/* turn logging on, only if compiled in */ +WOLFSSL_API int wolfSSL_Debugging_ON(void); +/* turn logging off */ +WOLFSSL_API void wolfSSL_Debugging_OFF(void); + + +#if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) + WOLFSSL_LOCAL int wc_LoggingInit(void); + WOLFSSL_LOCAL int wc_LoggingCleanup(void); + WOLFSSL_LOCAL int wc_AddErrorNode(int error, int line, char* buf, + char* file); + WOLFSSL_LOCAL int wc_PeekErrorNode(int index, const char **file, + const char **reason, int *line); + WOLFSSL_LOCAL void wc_RemoveErrorNode(int index); + WOLFSSL_LOCAL void wc_ClearErrorNodes(void); + WOLFSSL_LOCAL int wc_PullErrorNode(const char **file, const char **reason, + int *line); + WOLFSSL_API int wc_SetLoggingHeap(void* h); + WOLFSSL_API int wc_ERR_remove_state(void); + #if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM) + WOLFSSL_API void wc_ERR_print_errors_fp(XFILE fp); + #endif +#endif /* OPENSSL_EXTRA || DEBUG_WOLFSSL_VERBOSE */ + +#ifdef WOLFSSL_FUNC_TIME + /* WARNING: This code is only to be used for debugging performance. + * The code is not thread-safe. + * Do not use WOLFSSL_FUNC_TIME in production code. + */ + WOLFSSL_API void WOLFSSL_START(int funcNum); + WOLFSSL_API void WOLFSSL_END(int funcNum); + WOLFSSL_API void WOLFSSL_TIME(int count); +#else + #define WOLFSSL_START(n) + #define WOLFSSL_END(n) + #define WOLFSSL_TIME(n) +#endif + +#if defined(DEBUG_WOLFSSL) && !defined(WOLFSSL_DEBUG_ERRORS_ONLY) + #if defined(_WIN32) + #if defined(INTIME_RTOS) + #define __func__ NULL + #else + #define __func__ __FUNCTION__ + #endif + #endif + + /* a is prepended to m and b is appended, creating a log msg a + m + b */ + #define WOLFSSL_LOG_CAT(a, m, b) #a " " m " " #b + + WOLFSSL_API void WOLFSSL_ENTER(const char* msg); + WOLFSSL_API void WOLFSSL_LEAVE(const char* msg, int ret); + #define WOLFSSL_STUB(m) \ + WOLFSSL_MSG(WOLFSSL_LOG_CAT(wolfSSL Stub, m, not implemented)) + + WOLFSSL_API void WOLFSSL_MSG(const char* msg); + WOLFSSL_API void WOLFSSL_BUFFER(const byte* buffer, word32 length); + +#else + + #define WOLFSSL_ENTER(m) + #define WOLFSSL_LEAVE(m, r) + #define WOLFSSL_STUB(m) + + #define WOLFSSL_MSG(m) + #define WOLFSSL_BUFFER(b, l) + +#endif /* DEBUG_WOLFSSL && !WOLFSSL_DEBUG_ERRORS_ONLY */ + +#if defined(DEBUG_WOLFSSL) || defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + + #if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) + WOLFSSL_API void WOLFSSL_ERROR_LINE(int err, const char* func, unsigned int line, + const char* file, void* ctx); + #define WOLFSSL_ERROR(x) \ + WOLFSSL_ERROR_LINE((x), __func__, __LINE__, __FILE__, NULL) + #else + WOLFSSL_API void WOLFSSL_ERROR(int err); + #endif + WOLFSSL_API void WOLFSSL_ERROR_MSG(const char* msg); + +#else + #define WOLFSSL_ERROR(e) + #define WOLFSSL_ERROR_MSG(m) +#endif + +#ifdef __cplusplus +} +#endif +#endif /* WOLFSSL_LOGGING_H */ + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/md2.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/md2.h new file mode 100755 index 0000000..51b261a --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/md2.h @@ -0,0 +1,69 @@ +/* md2.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/*! + \file wolfssl/wolfcrypt/md2.h +*/ + + +#ifndef WOLF_CRYPT_MD2_H +#define WOLF_CRYPT_MD2_H + +#include + +#ifdef WOLFSSL_MD2 + +#ifdef __cplusplus + extern "C" { +#endif + +/* in bytes */ +enum { + MD2 = WC_HASH_TYPE_MD2, + MD2_BLOCK_SIZE = 16, + MD2_DIGEST_SIZE = 16, + MD2_PAD_SIZE = 16, + MD2_X_SIZE = 48 +}; + + +/* Md2 digest */ +typedef struct Md2 { + word32 count; /* bytes % PAD_SIZE */ + byte X[MD2_X_SIZE]; + byte C[MD2_BLOCK_SIZE]; + byte buffer[MD2_BLOCK_SIZE]; +} Md2; + + +WOLFSSL_API void wc_InitMd2(Md2*); +WOLFSSL_API void wc_Md2Update(Md2*, const byte*, word32); +WOLFSSL_API void wc_Md2Final(Md2*, byte*); +WOLFSSL_API int wc_Md2Hash(const byte*, word32, byte*); + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLFSSL_MD2 */ +#endif /* WOLF_CRYPT_MD2_H */ + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/md4.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/md4.h new file mode 100755 index 0000000..8b79efe --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/md4.h @@ -0,0 +1,67 @@ +/* md4.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/*! + \file wolfssl/wolfcrypt/md4.h +*/ + +#ifndef WOLF_CRYPT_MD4_H +#define WOLF_CRYPT_MD4_H + +#include + +#ifndef NO_MD4 + +#ifdef __cplusplus + extern "C" { +#endif + +/* in bytes */ +enum { + MD4 = WC_HASH_TYPE_MD4, + MD4_BLOCK_SIZE = 64, + MD4_DIGEST_SIZE = 16, + MD4_PAD_SIZE = 56 +}; + + +/* MD4 digest */ +typedef struct Md4 { + word32 buffLen; /* in bytes */ + word32 loLen; /* length in bytes */ + word32 hiLen; /* length in bytes */ + word32 digest[MD4_DIGEST_SIZE / sizeof(word32)]; + word32 buffer[MD4_BLOCK_SIZE / sizeof(word32)]; +} Md4; + + +WOLFSSL_API void wc_InitMd4(Md4*); +WOLFSSL_API void wc_Md4Update(Md4*, const byte*, word32); +WOLFSSL_API void wc_Md4Final(Md4*, byte*); + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* NO_MD4 */ +#endif /* WOLF_CRYPT_MD4_H */ + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/md5.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/md5.h new file mode 100755 index 0000000..6c27d63 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/md5.h @@ -0,0 +1,130 @@ +/* md5.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/*! + \file wolfssl/wolfcrypt/md5.h +*/ + + +#ifndef WOLF_CRYPT_MD5_H +#define WOLF_CRYPT_MD5_H + +#include + +#ifndef NO_MD5 + +#ifdef HAVE_FIPS + #define wc_InitMd5 InitMd5 + #define wc_Md5Update Md5Update + #define wc_Md5Final Md5Final + #define wc_Md5Hash Md5Hash +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +#ifndef NO_OLD_WC_NAMES + #define Md5 wc_Md5 + #define MD5 WC_MD5 + #define MD5_BLOCK_SIZE WC_MD5_BLOCK_SIZE + #define MD5_DIGEST_SIZE WC_MD5_DIGEST_SIZE + #define WC_MD5_PAD_SIZE WC_MD5_PAD_SIZE +#endif + +/* in bytes */ +enum { + WC_MD5 = WC_HASH_TYPE_MD5, + WC_MD5_BLOCK_SIZE = 64, + WC_MD5_DIGEST_SIZE = 16, + WC_MD5_PAD_SIZE = 56 +}; + + +#ifdef WOLFSSL_MICROCHIP_PIC32MZ + #include +#endif +#ifdef STM32_HASH + #include +#endif +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif + +#ifdef WOLFSSL_TI_HASH + #include "wolfssl/wolfcrypt/port/ti/ti-hash.h" +#elif defined(WOLFSSL_IMX6_CAAM) + #include "wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h" +#else + +/* MD5 digest */ +typedef struct wc_Md5 { +#ifdef STM32_HASH + STM32_HASH_Context stmCtx; +#else + word32 buffLen; /* in bytes */ + word32 loLen; /* length in bytes */ + word32 hiLen; /* length in bytes */ + word32 buffer[WC_MD5_BLOCK_SIZE / sizeof(word32)]; +#ifdef WOLFSSL_PIC32MZ_HASH + word32 digest[PIC32_DIGEST_SIZE / sizeof(word32)]; +#else + word32 digest[WC_MD5_DIGEST_SIZE / sizeof(word32)]; +#endif + void* heap; +#ifdef WOLFSSL_PIC32MZ_HASH + hashUpdCache cache; /* cache for updates */ +#endif +#endif /* STM32_HASH */ +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV asyncDev; +#endif /* WOLFSSL_ASYNC_CRYPT */ +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + word32 flags; /* enum wc_HashFlags in hash.h */ +#endif +} wc_Md5; + +#endif /* WOLFSSL_TI_HASH */ + +WOLFSSL_API int wc_InitMd5(wc_Md5*); +WOLFSSL_API int wc_InitMd5_ex(wc_Md5*, void*, int); +WOLFSSL_API int wc_Md5Update(wc_Md5*, const byte*, word32); +WOLFSSL_API int wc_Md5Final(wc_Md5*, byte*); +WOLFSSL_API void wc_Md5Free(wc_Md5*); + +WOLFSSL_API int wc_Md5GetHash(wc_Md5*, byte*); +WOLFSSL_API int wc_Md5Copy(wc_Md5*, wc_Md5*); + +#ifdef WOLFSSL_PIC32MZ_HASH +WOLFSSL_API void wc_Md5SizeSet(wc_Md5* md5, word32 len); +#endif + +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + WOLFSSL_LOCAL int wc_Md5SetFlags(wc_Md5* md5, word32 flags); + WOLFSSL_LOCAL int wc_Md5GetFlags(wc_Md5* md5, word32* flags); +#endif + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* NO_MD5 */ +#endif /* WOLF_CRYPT_MD5_H */ diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/mem_track.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/mem_track.h new file mode 100755 index 0000000..9754797 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/mem_track.h @@ -0,0 +1,401 @@ +/* mem_track.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +/* The memory tracker overrides the wolfSSL memory callback system and uses a + * static to track the total, peak and currently allocated bytes. + * + * If you are already using the memory callbacks then enabling this will + * override the memory callbacks and prevent your memory callbacks from + * working. This assumes malloc() and free() are available. Feel free to + * customize this for your needs. + + * The enable this feature define the following: + * #define USE_WOLFSSL_MEMORY + * #define WOLFSSL_TRACK_MEMORY + * + * On startup call: + * InitMemoryTracker(); + * + * When ready to dump the memory report call: + * ShowMemoryTracker(); + * + * Report example: + * total Allocs = 228 + * total Bytes = 93442 + * peak Bytes = 8840 + * current Bytes = 0 + * + * + * You can also: + * #define WOLFSSL_DEBUG_MEMORY + * + * To print every alloc/free along with the function and line number. + * Example output: + * Alloc: 0x7fa14a500010 -> 120 at wc_InitRng:496 + * Free: 0x7fa14a500010 -> 120 at wc_FreeRng:606 + */ + + +#ifndef WOLFSSL_MEM_TRACK_H +#define WOLFSSL_MEM_TRACK_H + +#if defined(USE_WOLFSSL_MEMORY) && !defined(WOLFSSL_STATIC_MEMORY) + + #include "wolfssl/wolfcrypt/logging.h" + + #if defined(WOLFSSL_TRACK_MEMORY) + #define DO_MEM_STATS + #if defined(__linux__) || defined(__MACH__) + #define DO_MEM_LIST + #endif + #endif + + + typedef struct memoryStats { + long totalAllocs; /* number of allocations */ + long totalDeallocs; /* number of deallocations */ + long totalBytes; /* total number of bytes allocated */ + long peakBytes; /* concurrent max bytes */ + long currentBytes; /* total current bytes in use */ + } memoryStats; + + typedef struct memHint { + size_t thisSize; /* size of this memory */ + + #ifdef DO_MEM_LIST + struct memHint* next; + struct memHint* prev; + #ifdef WOLFSSL_DEBUG_MEMORY + const char* func; + unsigned int line; + #endif + #endif + void* thisMemory; /* actual memory for user */ + } memHint; + + typedef struct memoryTrack { + union { + memHint hint; + byte alignit[sizeof(memHint) + ((16-1) & ~(16-1))]; /* make sure we have strong alignment */ + } u; + } memoryTrack; + +#ifdef DO_MEM_LIST + /* track allocations and report at end */ + typedef struct memoryList { + memHint* head; + memHint* tail; + word32 count; + } memoryList; +#endif + +#if defined(WOLFSSL_TRACK_MEMORY) + static memoryStats ourMemStats; + + #ifdef DO_MEM_LIST + #include + static memoryList ourMemList; + static pthread_mutex_t memLock = PTHREAD_MUTEX_INITIALIZER; + #endif +#endif + + + /* if defined to not using inline then declare function prototypes */ + #ifdef NO_INLINE + #define WC_STATIC + #ifdef WOLFSSL_DEBUG_MEMORY + WOLFSSL_LOCAL void* TrackMalloc(size_t sz, const char* func, unsigned int line); + WOLFSSL_LOCAL void TrackFree(void* ptr, const char* func, unsigned int line); + WOLFSSL_LOCAL void* TrackRealloc(void* ptr, size_t sz, const char* func, unsigned int line); + #else + WOLFSSL_LOCAL void* TrackMalloc(size_t sz); + WOLFSSL_LOCAL void TrackFree(void* ptr); + WOLFSSL_LOCAL void* TrackRealloc(void* ptr, size_t sz); + #endif + WOLFSSL_LOCAL int InitMemoryTracker(void); + WOLFSSL_LOCAL void ShowMemoryTracker(void); + #else + #define WC_STATIC static + #endif + +#ifdef WOLFSSL_DEBUG_MEMORY + WC_STATIC WC_INLINE void* TrackMalloc(size_t sz, const char* func, unsigned int line) +#else + WC_STATIC WC_INLINE void* TrackMalloc(size_t sz) +#endif + { + memoryTrack* mt; + memHint* header; + + if (sz == 0) + return NULL; + + mt = (memoryTrack*)malloc(sizeof(memoryTrack) + sz); + if (mt == NULL) + return NULL; + + header = &mt->u.hint; + header->thisSize = sz; + header->thisMemory = (byte*)mt + sizeof(memoryTrack); + + #ifdef WOLFSSL_DEBUG_MEMORY + #ifdef WOLFSSL_DEBUG_MEMORY_PRINT + printf("Alloc: %p -> %u at %s:%d\n", header->thisMemory, (word32)sz, func, line); + #else + (void)func; + (void)line; + #endif + #endif + + #ifdef DO_MEM_STATS + ourMemStats.totalAllocs++; + ourMemStats.totalBytes += sz; + ourMemStats.currentBytes += sz; + if (ourMemStats.currentBytes > ourMemStats.peakBytes) + ourMemStats.peakBytes = ourMemStats.currentBytes; + #endif + #ifdef DO_MEM_LIST + if (pthread_mutex_lock(&memLock) == 0) { + #ifdef WOLFSSL_DEBUG_MEMORY + header->func = func; + header->line = line; + #endif + + /* Setup event */ + header->next = NULL; + if (ourMemList.tail == NULL) { + ourMemList.head = header; + header->prev = NULL; + } + else { + ourMemList.tail->next = header; + header->prev = ourMemList.tail; + } + ourMemList.tail = header; /* add to the end either way */ + ourMemList.count++; + + pthread_mutex_unlock(&memLock); + } + #endif + + return header->thisMemory; + } + + +#ifdef WOLFSSL_DEBUG_MEMORY + WC_STATIC WC_INLINE void TrackFree(void* ptr, const char* func, unsigned int line) +#else + WC_STATIC WC_INLINE void TrackFree(void* ptr) +#endif + { + memoryTrack* mt; + memHint* header; + size_t sz; + + if (ptr == NULL) { + return; + } + + mt = (memoryTrack*)((byte*)ptr - sizeof(memoryTrack)); + header = &mt->u.hint; + sz = header->thisSize; + + #ifdef DO_MEM_LIST + if (pthread_mutex_lock(&memLock) == 0) + { + #endif + + #ifdef DO_MEM_STATS + ourMemStats.currentBytes -= header->thisSize; + ourMemStats.totalDeallocs++; + #endif + + #ifdef DO_MEM_LIST + if (header == ourMemList.head && header == ourMemList.tail) { + ourMemList.head = NULL; + ourMemList.tail = NULL; + } + else if (header == ourMemList.head) { + ourMemList.head = header->next; + ourMemList.head->prev = NULL; + } + else if (header == ourMemList.tail) { + ourMemList.tail = header->prev; + ourMemList.tail->next = NULL; + } + else { + memHint* next = header->next; + memHint* prev = header->prev; + if (next) + next->prev = prev; + if (prev) + prev->next = next; + } + ourMemList.count--; + + pthread_mutex_unlock(&memLock); + } + #endif + +#ifdef WOLFSSL_DEBUG_MEMORY +#ifdef WOLFSSL_DEBUG_MEMORY_PRINT + printf("Free: %p -> %u at %s:%d\n", ptr, (word32)sz, func, line); +#else + (void)func; + (void)line; +#endif +#endif + (void)sz; + + free(mt); + } + + +#ifdef WOLFSSL_DEBUG_MEMORY + WC_STATIC WC_INLINE void* TrackRealloc(void* ptr, size_t sz, const char* func, unsigned int line) +#else + WC_STATIC WC_INLINE void* TrackRealloc(void* ptr, size_t sz) +#endif + { + #ifdef WOLFSSL_DEBUG_MEMORY + void* ret = TrackMalloc(sz, func, line); + #else + void* ret = TrackMalloc(sz); + #endif + + if (ptr) { + /* if realloc is bigger, don't overread old ptr */ + memoryTrack* mt; + memHint* header; + + mt = (memoryTrack*)((byte*)ptr - sizeof(memoryTrack)); + header = &mt->u.hint; + + if (header->thisSize < sz) + sz = header->thisSize; + } + + if (ret && ptr) + XMEMCPY(ret, ptr, sz); + + if (ret) { + #ifdef WOLFSSL_DEBUG_MEMORY + TrackFree(ptr, func, line); + #else + TrackFree(ptr); + #endif + } + + return ret; + } + +#ifdef WOLFSSL_TRACK_MEMORY + static wolfSSL_Malloc_cb mfDefault = NULL; + static wolfSSL_Free_cb ffDefault = NULL; + static wolfSSL_Realloc_cb rfDefault = NULL; + + WC_STATIC WC_INLINE int InitMemoryTracker(void) + { + int ret; + + ret = wolfSSL_GetAllocators(&mfDefault, &ffDefault, &rfDefault); + if (ret < 0) { + printf("wolfSSL GetAllocators failed to get the defaults\n"); + } + ret = wolfSSL_SetAllocators(TrackMalloc, TrackFree, TrackRealloc); + if (ret < 0) { + printf("wolfSSL SetAllocators failed for track memory\n"); + return ret; + } + + #ifdef DO_MEM_LIST + if (pthread_mutex_lock(&memLock) == 0) + { + #endif + + #ifdef DO_MEM_STATS + ourMemStats.totalAllocs = 0; + ourMemStats.totalDeallocs = 0; + ourMemStats.totalBytes = 0; + ourMemStats.peakBytes = 0; + ourMemStats.currentBytes = 0; + #endif + + #ifdef DO_MEM_LIST + XMEMSET(&ourMemList, 0, sizeof(ourMemList)); + + pthread_mutex_unlock(&memLock); + } + #endif + + return ret; + } + + WC_STATIC WC_INLINE void ShowMemoryTracker(void) + { + #ifdef DO_MEM_LIST + if (pthread_mutex_lock(&memLock) == 0) + { + #endif + + #ifdef DO_MEM_STATS + printf("total Allocs = %9ld\n", ourMemStats.totalAllocs); + printf("total Deallocs = %9ld\n", ourMemStats.totalDeallocs); + printf("total Bytes = %9ld\n", ourMemStats.totalBytes); + printf("peak Bytes = %9ld\n", ourMemStats.peakBytes); + printf("current Bytes = %9ld\n", ourMemStats.currentBytes); + #endif + + #ifdef DO_MEM_LIST + if (ourMemList.count > 0) { + /* print list of allocations */ + memHint* header; + for (header = ourMemList.head; header != NULL; header = header->next) { + printf("Leak: Ptr %p, Size %u" + #ifdef WOLFSSL_DEBUG_MEMORY + ", Func %s, Line %d" + #endif + "\n", + (byte*)header + sizeof(memHint), (unsigned int)header->thisSize + #ifdef WOLFSSL_DEBUG_MEMORY + , header->func, header->line + #endif + ); + } + } + + pthread_mutex_unlock(&memLock); + } + #endif + } + + WC_STATIC WC_INLINE int CleanupMemoryTracker(void) + { + /* restore default allocators */ + return wolfSSL_SetAllocators(mfDefault, ffDefault, rfDefault); + } +#endif + +#endif /* USE_WOLFSSL_MEMORY */ + +#endif /* WOLFSSL_MEM_TRACK_H */ + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/memory.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/memory.h new file mode 100755 index 0000000..a2ed27b --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/memory.h @@ -0,0 +1,217 @@ +/* memory.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +/* submitted by eof */ + +/*! + \file wolfssl/wolfcrypt/memory.h +*/ + +#ifndef WOLFSSL_MEMORY_H +#define WOLFSSL_MEMORY_H + +#ifndef STRING_USER +#include +#endif +#include + +#ifdef __cplusplus + extern "C" { +#endif + +#ifdef WOLFSSL_FORCE_MALLOC_FAIL_TEST + WOLFSSL_API void wolfSSL_SetMemFailCount(int memFailCount); +#endif + +#ifdef WOLFSSL_STATIC_MEMORY + #ifdef WOLFSSL_DEBUG_MEMORY + typedef void *(*wolfSSL_Malloc_cb)(size_t size, void* heap, int type, const char* func, unsigned int line); + typedef void (*wolfSSL_Free_cb)(void *ptr, void* heap, int type, const char* func, unsigned int line); + typedef void *(*wolfSSL_Realloc_cb)(void *ptr, size_t size, void* heap, int type, const char* func, unsigned int line); + WOLFSSL_API void* wolfSSL_Malloc(size_t size, void* heap, int type, const char* func, unsigned int line); + WOLFSSL_API void wolfSSL_Free(void *ptr, void* heap, int type, const char* func, unsigned int line); + WOLFSSL_API void* wolfSSL_Realloc(void *ptr, size_t size, void* heap, int type, const char* func, unsigned int line); + #else + typedef void *(*wolfSSL_Malloc_cb)(size_t size, void* heap, int type); + typedef void (*wolfSSL_Free_cb)(void *ptr, void* heap, int type); + typedef void *(*wolfSSL_Realloc_cb)(void *ptr, size_t size, void* heap, int type); + WOLFSSL_API void* wolfSSL_Malloc(size_t size, void* heap, int type); + WOLFSSL_API void wolfSSL_Free(void *ptr, void* heap, int type); + WOLFSSL_API void* wolfSSL_Realloc(void *ptr, size_t size, void* heap, int type); + #endif /* WOLFSSL_DEBUG_MEMORY */ +#else + #ifdef WOLFSSL_DEBUG_MEMORY + typedef void *(*wolfSSL_Malloc_cb)(size_t size, const char* func, unsigned int line); + typedef void (*wolfSSL_Free_cb)(void *ptr, const char* func, unsigned int line); + typedef void *(*wolfSSL_Realloc_cb)(void *ptr, size_t size, const char* func, unsigned int line); + + /* Public in case user app wants to use XMALLOC/XFREE */ + WOLFSSL_API void* wolfSSL_Malloc(size_t size, const char* func, unsigned int line); + WOLFSSL_API void wolfSSL_Free(void *ptr, const char* func, unsigned int line); + WOLFSSL_API void* wolfSSL_Realloc(void *ptr, size_t size, const char* func, unsigned int line); + #else + typedef void *(*wolfSSL_Malloc_cb)(size_t size); + typedef void (*wolfSSL_Free_cb)(void *ptr); + typedef void *(*wolfSSL_Realloc_cb)(void *ptr, size_t size); + /* Public in case user app wants to use XMALLOC/XFREE */ + WOLFSSL_API void* wolfSSL_Malloc(size_t size); + WOLFSSL_API void wolfSSL_Free(void *ptr); + WOLFSSL_API void* wolfSSL_Realloc(void *ptr, size_t size); + #endif /* WOLFSSL_DEBUG_MEMORY */ +#endif /* WOLFSSL_STATIC_MEMORY */ + +/* Public get/set functions */ +WOLFSSL_API int wolfSSL_SetAllocators(wolfSSL_Malloc_cb, + wolfSSL_Free_cb, + wolfSSL_Realloc_cb); +WOLFSSL_API int wolfSSL_GetAllocators(wolfSSL_Malloc_cb*, + wolfSSL_Free_cb*, + wolfSSL_Realloc_cb*); + +#ifdef WOLFSSL_STATIC_MEMORY + #define WOLFSSL_STATIC_TIMEOUT 1 + #ifndef WOLFSSL_STATIC_ALIGN + #define WOLFSSL_STATIC_ALIGN 16 + #endif + #ifndef WOLFMEM_MAX_BUCKETS + #define WOLFMEM_MAX_BUCKETS 9 + #endif + #define WOLFMEM_DEF_BUCKETS 9 /* number of default memory blocks */ + #ifndef WOLFMEM_IO_SZ + #define WOLFMEM_IO_SZ 16992 /* 16 byte aligned */ + #endif + #ifndef WOLFMEM_BUCKETS + #ifndef SESSION_CERTS + /* default size of chunks of memory to separate into */ + #define WOLFMEM_BUCKETS 64,128,256,512,1024,2432,3456,4544,16128 + #elif defined (OPENSSL_EXTRA) + /* extra storage in structs for multiple attributes and order */ + #define WOLFMEM_BUCKETS 64,128,256,512,1024,2432,3360,4480,25520 + #elif defined (WOLFSSL_CERT_EXT) + /* certificate extensions requires 24k for the SSL struct */ + #define WOLFMEM_BUCKETS 64,128,256,512,1024,2432,3456,4544,24576 + #else + /* increase 23k for object member of WOLFSSL_X509_NAME_ENTRY */ + #define WOLFMEM_BUCKETS 64,128,256,512,1024,2432,3456,4544,23440 + #endif + #endif + #ifndef WOLFMEM_DIST + #ifndef WOLFSSL_STATIC_MEMORY_SMALL + #define WOLFMEM_DIST 49,10,6,14,5,6,9,1,1 + #else + /* Low resource and not RSA */ + #define WOLFMEM_DIST 29, 7,6, 9,4,4,0,0,0 + #endif + #endif + + /* flags for loading static memory (one hot bit) */ + #define WOLFMEM_GENERAL 0x01 + #define WOLFMEM_IO_POOL 0x02 + #define WOLFMEM_IO_POOL_FIXED 0x04 + #define WOLFMEM_TRACK_STATS 0x08 + + #ifndef WOLFSSL_MEM_GUARD + #define WOLFSSL_MEM_GUARD + typedef struct WOLFSSL_MEM_STATS WOLFSSL_MEM_STATS; + typedef struct WOLFSSL_MEM_CONN_STATS WOLFSSL_MEM_CONN_STATS; + #endif + + struct WOLFSSL_MEM_CONN_STATS { + word32 peakMem; /* peak memory usage */ + word32 curMem; /* current memory usage */ + word32 peakAlloc; /* peak memory allocations */ + word32 curAlloc; /* current memory allocations */ + word32 totalAlloc;/* total memory allocations for lifetime */ + word32 totalFr; /* total frees for lifetime */ + }; + + struct WOLFSSL_MEM_STATS { + word32 curAlloc; /* current memory allocations */ + word32 totalAlloc;/* total memory allocations for lifetime */ + word32 totalFr; /* total frees for lifetime */ + word32 totalUse; /* total amount of memory used in blocks */ + word32 avaIO; /* available IO specific pools */ + word32 maxHa; /* max number of concurent handshakes allowed */ + word32 maxIO; /* max number of concurent IO connections allowed */ + word32 blockSz[WOLFMEM_MAX_BUCKETS]; /* block sizes in stacks */ + word32 avaBlock[WOLFMEM_MAX_BUCKETS];/* ava block sizes */ + word32 usedBlock[WOLFMEM_MAX_BUCKETS]; + int flag; /* flag used */ + }; + + typedef struct wc_Memory wc_Memory; /* internal structure for mem bucket */ + typedef struct WOLFSSL_HEAP { + wc_Memory* ava[WOLFMEM_MAX_BUCKETS]; + wc_Memory* io; /* list of buffers to use for IO */ + word32 maxHa; /* max concurent handshakes */ + word32 curHa; + word32 maxIO; /* max concurrent IO connections */ + word32 curIO; + word32 sizeList[WOLFMEM_MAX_BUCKETS];/* memory sizes in ava list */ + word32 distList[WOLFMEM_MAX_BUCKETS];/* general distribution */ + word32 inUse; /* amount of memory currently in use */ + word32 ioUse; + word32 alloc; /* total number of allocs */ + word32 frAlc; /* total number of frees */ + int flag; + wolfSSL_Mutex memory_mutex; + } WOLFSSL_HEAP; + + /* structure passed into XMALLOC as heap hint + * having this abstraction allows tracking statistics of individual ssl's + */ + typedef struct WOLFSSL_HEAP_HINT { + WOLFSSL_HEAP* memory; + WOLFSSL_MEM_CONN_STATS* stats; /* hold individual connection stats */ + wc_Memory* outBuf; /* set if using fixed io buffers */ + wc_Memory* inBuf; + byte haFlag; /* flag used for checking handshake count */ + } WOLFSSL_HEAP_HINT; + + WOLFSSL_API int wc_LoadStaticMemory(WOLFSSL_HEAP_HINT** pHint, + unsigned char* buf, unsigned int sz, int flag, int max); + + WOLFSSL_LOCAL int wolfSSL_init_memory_heap(WOLFSSL_HEAP* heap); + WOLFSSL_LOCAL int wolfSSL_load_static_memory(byte* buffer, word32 sz, + int flag, WOLFSSL_HEAP* heap); + WOLFSSL_LOCAL int wolfSSL_GetMemStats(WOLFSSL_HEAP* heap, + WOLFSSL_MEM_STATS* stats); + WOLFSSL_LOCAL int SetFixedIO(WOLFSSL_HEAP* heap, wc_Memory** io); + WOLFSSL_LOCAL int FreeFixedIO(WOLFSSL_HEAP* heap, wc_Memory** io); + + WOLFSSL_API int wolfSSL_StaticBufferSz(byte* buffer, word32 sz, int flag); + WOLFSSL_API int wolfSSL_MemoryPaddingSz(void); +#endif /* WOLFSSL_STATIC_MEMORY */ + +#ifdef WOLFSSL_STACK_LOG + WOLFSSL_API void __attribute__((no_instrument_function)) + __cyg_profile_func_enter(void *func, void *caller); + WOLFSSL_API void __attribute__((no_instrument_function)) + __cyg_profile_func_exit(void *func, void *caller); +#endif /* WOLFSSL_STACK_LOG */ + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLFSSL_MEMORY_H */ + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/misc.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/misc.h new file mode 100755 index 0000000..ccf9311 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/misc.h @@ -0,0 +1,115 @@ +/* misc.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifndef WOLF_CRYPT_MISC_H +#define WOLF_CRYPT_MISC_H + + +#include + + +#ifdef __cplusplus + extern "C" { +#endif + + +#ifdef NO_INLINE +WOLFSSL_LOCAL +word32 rotlFixed(word32, word32); +WOLFSSL_LOCAL +word32 rotrFixed(word32, word32); + +WOLFSSL_LOCAL +word32 ByteReverseWord32(word32); +WOLFSSL_LOCAL +void ByteReverseWords(word32*, const word32*, word32); + +WOLFSSL_LOCAL +void XorWords(wolfssl_word*, const wolfssl_word*, word32); +WOLFSSL_LOCAL +void xorbuf(void*, const void*, word32); + +WOLFSSL_LOCAL +void ForceZero(const void*, word32); + +WOLFSSL_LOCAL +int ConstantCompare(const byte*, const byte*, int); + +#ifdef WORD64_AVAILABLE +WOLFSSL_LOCAL +word64 rotlFixed64(word64, word64); +WOLFSSL_LOCAL +word64 rotrFixed64(word64, word64); + +WOLFSSL_LOCAL +word64 ByteReverseWord64(word64); +WOLFSSL_LOCAL +void ByteReverseWords64(word64*, const word64*, word32); +#endif /* WORD64_AVAILABLE */ + +#ifndef WOLFSSL_HAVE_MIN + #if defined(HAVE_FIPS) && !defined(min) /* so ifdef check passes */ + #define min min + #endif + WOLFSSL_LOCAL word32 min(word32 a, word32 b); +#endif + +#ifndef WOLFSSL_HAVE_MAX + #if defined(HAVE_FIPS) && !defined(max) /* so ifdef check passes */ + #define max max + #endif + WOLFSSL_LOCAL word32 max(word32 a, word32 b); +#endif /* WOLFSSL_HAVE_MAX */ + + +void c32to24(word32 in, word24 out); +void c16toa(word16 u16, byte* c); +void c32toa(word32 u32, byte* c); +void c24to32(const word24 u24, word32* u32); +void ato16(const byte* c, word16* u16); +void ato24(const byte* c, word32* u24); +void ato32(const byte* c, word32* u32); +word32 btoi(byte b); + + +WOLFSSL_LOCAL byte ctMaskGT(int a, int b); +WOLFSSL_LOCAL byte ctMaskGTE(int a, int b); +WOLFSSL_LOCAL byte ctMaskLT(int a, int b); +WOLFSSL_LOCAL byte ctMaskLTE(int a, int b); +WOLFSSL_LOCAL byte ctMaskEq(int a, int b); +WOLFSSL_LOCAL word16 ctMask16Eq(int a, int b); +WOLFSSL_LOCAL byte ctMaskNotEq(int a, int b); +WOLFSSL_LOCAL byte ctMaskSel(byte m, byte a, byte b); +WOLFSSL_LOCAL int ctMaskSelInt(byte m, int a, int b); +WOLFSSL_LOCAL byte ctSetLTE(int a, int b); + +#endif /* NO_INLINE */ + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + + +#endif /* WOLF_CRYPT_MISC_H */ + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/mpi_class.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/mpi_class.h new file mode 100755 index 0000000..2a86e77 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/mpi_class.h @@ -0,0 +1,1019 @@ +/* mpi_class.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#if !(defined(LTM1) && defined(LTM2) && defined(LTM3)) +#if defined(LTM2) +#define LTM3 +#endif +#if defined(LTM1) +#define LTM2 +#endif +#define LTM1 + +#if defined(LTM_ALL) +#define BN_ERROR_C +#define BN_FAST_MP_INVMOD_C +#define BN_FAST_MP_MONTGOMERY_REDUCE_C +#define BN_FAST_S_MP_MUL_DIGS_C +#define BN_FAST_S_MP_MUL_HIGH_DIGS_C +#define BN_FAST_S_MP_SQR_C +#define BN_MP_2EXPT_C +#define BN_MP_ABS_C +#define BN_MP_ADD_C +#define BN_MP_ADD_D_C +#define BN_MP_ADDMOD_C +#define BN_MP_AND_C +#define BN_MP_CLAMP_C +#define BN_MP_CLEAR_C +#define BN_MP_CLEAR_MULTI_C +#define BN_MP_CMP_C +#define BN_MP_CMP_D_C +#define BN_MP_CMP_MAG_C +#define BN_MP_CNT_LSB_C +#define BN_MP_COPY_C +#define BN_MP_COUNT_BITS_C +#define BN_MP_DIV_C +#define BN_MP_DIV_2_C +#define BN_MP_DIV_2D_C +#define BN_MP_DIV_3_C +#define BN_MP_DIV_D_C +#define BN_MP_DR_IS_MODULUS_C +#define BN_MP_DR_REDUCE_C +#define BN_MP_DR_SETUP_C +#define BN_MP_EXCH_C +#define BN_MP_EXPT_D_C +#define BN_MP_EXPTMOD_C +#define BN_MP_EXPTMOD_FAST_C +#define BN_MP_EXTEUCLID_C +#define BN_MP_FREAD_C +#define BN_MP_FWRITE_C +#define BN_MP_GCD_C +#define BN_MP_GET_INT_C +#define BN_MP_GROW_C +#define BN_MP_INIT_C +#define BN_MP_INIT_COPY_C +#define BN_MP_INIT_MULTI_C +#define BN_MP_INIT_SET_C +#define BN_MP_INIT_SET_INT_C +#define BN_MP_INIT_SIZE_C +#define BN_MP_INVMOD_C +#define BN_MP_INVMOD_SLOW_C +#define BN_MP_IS_SQUARE_C +#define BN_MP_JACOBI_C +#define BN_MP_KARATSUBA_MUL_C +#define BN_MP_KARATSUBA_SQR_C +#define BN_MP_LCM_C +#define BN_MP_LSHD_C +#define BN_MP_MOD_C +#define BN_MP_MOD_2D_C +#define BN_MP_MOD_D_C +#define BN_MP_MONTGOMERY_CALC_NORMALIZATION_C +#define BN_MP_MONTGOMERY_REDUCE_C +#define BN_MP_MONTGOMERY_SETUP_C +#define BN_MP_MUL_C +#define BN_MP_MUL_2_C +#define BN_MP_MUL_2D_C +#define BN_MP_MUL_D_C +#define BN_MP_MULMOD_C +#define BN_MP_N_ROOT_C +#define BN_MP_NEG_C +#define BN_MP_OR_C +#define BN_MP_PRIME_FERMAT_C +#define BN_MP_PRIME_IS_DIVISIBLE_C +#define BN_MP_PRIME_IS_PRIME_C +#define BN_MP_PRIME_MILLER_RABIN_C +#define BN_MP_PRIME_NEXT_PRIME_C +#define BN_MP_PRIME_RABIN_MILLER_TRIALS_C +#define BN_MP_PRIME_RANDOM_EX_C +#define BN_MP_RADIX_SIZE_C +#define BN_MP_RADIX_SMAP_C +#define BN_MP_RAND_C +#define BN_MP_READ_RADIX_C +#define BN_MP_READ_SIGNED_BIN_C +#define BN_MP_READ_UNSIGNED_BIN_C +#define BN_MP_REDUCE_C +#define BN_MP_REDUCE_2K_C +#define BN_MP_REDUCE_2K_L_C +#define BN_MP_REDUCE_2K_SETUP_C +#define BN_MP_REDUCE_2K_SETUP_L_C +#define BN_MP_REDUCE_IS_2K_C +#define BN_MP_REDUCE_IS_2K_L_C +#define BN_MP_REDUCE_SETUP_C +#define BN_MP_RSHD_C +#define BN_MP_SET_C +#define BN_MP_SET_INT_C +#define BN_MP_SHRINK_C +#define BN_MP_SIGNED_BIN_SIZE_C +#define BN_MP_SQR_C +#define BN_MP_SQRMOD_C +#define BN_MP_SQRT_C +#define BN_MP_SUB_C +#define BN_MP_SUB_D_C +#define BN_MP_SUBMOD_C +#define BN_MP_TO_SIGNED_BIN_C +#define BN_MP_TO_SIGNED_BIN_N_C +#define BN_MP_TO_UNSIGNED_BIN_C +#define BN_MP_TO_UNSIGNED_BIN_N_C +#define BN_MP_TOOM_MUL_C +#define BN_MP_TOOM_SQR_C +#define BN_MP_TORADIX_C +#define BN_MP_TORADIX_N_C +#define BN_MP_UNSIGNED_BIN_SIZE_C +#define BN_MP_XOR_C +#define BN_MP_ZERO_C +#define BN_PRIME_TAB_C +#define BN_REVERSE_C +#define BN_S_MP_ADD_C +#define BN_S_MP_EXPTMOD_C +#define BN_S_MP_MUL_DIGS_C +#define BN_S_MP_MUL_HIGH_DIGS_C +#define BN_S_MP_SQR_C +#define BN_S_MP_SUB_C +#define BNCORE_C +#endif + +#if defined(BN_ERROR_C) + #define BN_MP_ERROR_TO_STRING_C +#endif + +#if defined(BN_FAST_MP_INVMOD_C) + #define BN_MP_ISEVEN_C + #define BN_MP_INIT_MULTI_C + #define BN_MP_COPY_C + #define BN_MP_MOD_C + #define BN_MP_SET_C + #define BN_MP_DIV_2_C + #define BN_MP_ISODD_C + #define BN_MP_SUB_C + #define BN_MP_CMP_C + #define BN_MP_ISZERO_C + #define BN_MP_CMP_D_C + #define BN_MP_ADD_C + #define BN_MP_EXCH_C + #define BN_MP_CLEAR_MULTI_C +#endif + +#if defined(BN_FAST_MP_MONTGOMERY_REDUCE_C) + #define BN_MP_GROW_C + #define BN_MP_RSHD_C + #define BN_MP_CLAMP_C + #define BN_MP_CMP_MAG_C + #define BN_S_MP_SUB_C +#endif + +#if defined(BN_FAST_S_MP_MUL_DIGS_C) + #define BN_MP_GROW_C + #define BN_MP_CLAMP_C +#endif + +#if defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C) + #define BN_MP_GROW_C + #define BN_MP_CLAMP_C +#endif + +#if defined(BN_FAST_S_MP_SQR_C) + #define BN_MP_GROW_C + #define BN_MP_CLAMP_C +#endif + +#if defined(BN_MP_2EXPT_C) + #define BN_MP_ZERO_C + #define BN_MP_GROW_C +#endif + +#if defined(BN_MP_ABS_C) + #define BN_MP_COPY_C +#endif + +#if defined(BN_MP_ADD_C) + #define BN_S_MP_ADD_C + #define BN_MP_CMP_MAG_C + #define BN_S_MP_SUB_C +#endif + +#if defined(BN_MP_ADD_D_C) + #define BN_MP_GROW_C + #define BN_MP_SUB_D_C + #define BN_MP_CLAMP_C +#endif + +#if defined(BN_MP_ADDMOD_C) + #define BN_MP_INIT_C + #define BN_MP_ADD_C + #define BN_MP_CLEAR_C + #define BN_MP_MOD_C +#endif + +#if defined(BN_MP_AND_C) + #define BN_MP_INIT_COPY_C + #define BN_MP_CLAMP_C + #define BN_MP_EXCH_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_CLAMP_C) +#endif + +#if defined(BN_MP_CLEAR_C) +#endif + +#if defined(BN_MP_CLEAR_MULTI_C) + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_CMP_C) + #define BN_MP_CMP_MAG_C +#endif + +#if defined(BN_MP_CMP_D_C) +#endif + +#if defined(BN_MP_CMP_MAG_C) +#endif + +#if defined(BN_MP_CNT_LSB_C) + #define BN_MP_ISZERO_C +#endif + +#if defined(BN_MP_COPY_C) + #define BN_MP_GROW_C +#endif + +#if defined(BN_MP_COUNT_BITS_C) +#endif + +#if defined(BN_MP_DIV_C) + #define BN_MP_ISZERO_C + #define BN_MP_CMP_MAG_C + #define BN_MP_COPY_C + #define BN_MP_ZERO_C + #define BN_MP_INIT_MULTI_C + #define BN_MP_SET_C + #define BN_MP_COUNT_BITS_C + #define BN_MP_ABS_C + #define BN_MP_MUL_2D_C + #define BN_MP_CMP_C + #define BN_MP_SUB_C + #define BN_MP_ADD_C + #define BN_MP_DIV_2D_C + #define BN_MP_EXCH_C + #define BN_MP_CLEAR_MULTI_C + #define BN_MP_INIT_SIZE_C + #define BN_MP_INIT_C + #define BN_MP_INIT_COPY_C + #define BN_MP_LSHD_C + #define BN_MP_RSHD_C + #define BN_MP_MUL_D_C + #define BN_MP_CLAMP_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_DIV_2_C) + #define BN_MP_GROW_C + #define BN_MP_CLAMP_C +#endif + +#if defined(BN_MP_DIV_2D_C) + #define BN_MP_COPY_C + #define BN_MP_ZERO_C + #define BN_MP_INIT_C + #define BN_MP_MOD_2D_C + #define BN_MP_CLEAR_C + #define BN_MP_RSHD_C + #define BN_MP_CLAMP_C + #define BN_MP_EXCH_C +#endif + +#if defined(BN_MP_DIV_3_C) + #define BN_MP_INIT_SIZE_C + #define BN_MP_CLAMP_C + #define BN_MP_EXCH_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_DIV_D_C) + #define BN_MP_ISZERO_C + #define BN_MP_COPY_C + #define BN_MP_DIV_2D_C + #define BN_MP_DIV_3_C + #define BN_MP_INIT_SIZE_C + #define BN_MP_CLAMP_C + #define BN_MP_EXCH_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_DR_IS_MODULUS_C) +#endif + +#if defined(BN_MP_DR_REDUCE_C) + #define BN_MP_GROW_C + #define BN_MP_CLAMP_C + #define BN_MP_CMP_MAG_C + #define BN_S_MP_SUB_C +#endif + +#if defined(BN_MP_DR_SETUP_C) +#endif + +#if defined(BN_MP_EXCH_C) +#endif + +#if defined(BN_MP_EXPT_D_C) + #define BN_MP_INIT_COPY_C + #define BN_MP_SET_C + #define BN_MP_SQR_C + #define BN_MP_CLEAR_C + #define BN_MP_MUL_C +#endif + +#if defined(BN_MP_EXPTMOD_C) + #define BN_MP_INIT_C + #define BN_MP_INVMOD_C + #define BN_MP_CLEAR_C + #define BN_MP_ABS_C + #define BN_MP_CLEAR_MULTI_C + #define BN_MP_REDUCE_IS_2K_L_C + #define BN_S_MP_EXPTMOD_C + #define BN_MP_DR_IS_MODULUS_C + #define BN_MP_REDUCE_IS_2K_C + #define BN_MP_ISODD_C + #define BN_MP_EXPTMOD_FAST_C +#endif + +#if defined(BN_MP_EXPTMOD_FAST_C) + #define BN_MP_COUNT_BITS_C + #define BN_MP_INIT_C + #define BN_MP_CLEAR_C + #define BN_MP_MONTGOMERY_SETUP_C + #define BN_FAST_MP_MONTGOMERY_REDUCE_C + #define BN_MP_MONTGOMERY_REDUCE_C + #define BN_MP_DR_SETUP_C + #define BN_MP_DR_REDUCE_C + #define BN_MP_REDUCE_2K_SETUP_C + #define BN_MP_REDUCE_2K_C + #define BN_MP_MONTGOMERY_CALC_NORMALIZATION_C + #define BN_MP_MULMOD_C + #define BN_MP_SET_C + #define BN_MP_MOD_C + #define BN_MP_COPY_C + #define BN_MP_SQR_C + #define BN_MP_MUL_C + #define BN_MP_EXCH_C +#endif + +#if defined(BN_MP_EXTEUCLID_C) + #define BN_MP_INIT_MULTI_C + #define BN_MP_SET_C + #define BN_MP_COPY_C + #define BN_MP_ISZERO_C + #define BN_MP_DIV_C + #define BN_MP_MUL_C + #define BN_MP_SUB_C + #define BN_MP_NEG_C + #define BN_MP_EXCH_C + #define BN_MP_CLEAR_MULTI_C +#endif + +#if defined(BN_MP_FREAD_C) + #define BN_MP_ZERO_C + #define BN_MP_S_RMAP_C + #define BN_MP_MUL_D_C + #define BN_MP_ADD_D_C + #define BN_MP_CMP_D_C +#endif + +#if defined(BN_MP_FWRITE_C) + #define BN_MP_RADIX_SIZE_C + #define BN_MP_TORADIX_C +#endif + +#if defined(BN_MP_GCD_C) + #define BN_MP_ISZERO_C + #define BN_MP_ABS_C + #define BN_MP_ZERO_C + #define BN_MP_INIT_COPY_C + #define BN_MP_CNT_LSB_C + #define BN_MP_DIV_2D_C + #define BN_MP_CMP_MAG_C + #define BN_MP_EXCH_C + #define BN_S_MP_SUB_C + #define BN_MP_MUL_2D_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_GET_INT_C) +#endif + +#if defined(BN_MP_GROW_C) +#endif + +#if defined(BN_MP_INIT_C) +#endif + +#if defined(BN_MP_INIT_COPY_C) + #define BN_MP_COPY_C +#endif + +#if defined(BN_MP_INIT_MULTI_C) + #define BN_MP_ERR_C + #define BN_MP_INIT_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_INIT_SET_C) + #define BN_MP_INIT_C + #define BN_MP_SET_C +#endif + +#if defined(BN_MP_INIT_SET_INT_C) + #define BN_MP_INIT_C + #define BN_MP_SET_INT_C +#endif + +#if defined(BN_MP_INIT_SIZE_C) + #define BN_MP_INIT_C +#endif + +#if defined(BN_MP_INVMOD_C) + #define BN_MP_ISZERO_C + #define BN_MP_ISODD_C + #define BN_FAST_MP_INVMOD_C + #define BN_MP_INVMOD_SLOW_C +#endif + +#if defined(BN_MP_INVMOD_SLOW_C) + #define BN_MP_ISZERO_C + #define BN_MP_INIT_MULTI_C + #define BN_MP_MOD_C + #define BN_MP_COPY_C + #define BN_MP_ISEVEN_C + #define BN_MP_SET_C + #define BN_MP_DIV_2_C + #define BN_MP_ISODD_C + #define BN_MP_ADD_C + #define BN_MP_SUB_C + #define BN_MP_CMP_C + #define BN_MP_CMP_D_C + #define BN_MP_CMP_MAG_C + #define BN_MP_EXCH_C + #define BN_MP_CLEAR_MULTI_C +#endif + +#if defined(BN_MP_IS_SQUARE_C) + #define BN_MP_MOD_D_C + #define BN_MP_INIT_SET_INT_C + #define BN_MP_MOD_C + #define BN_MP_GET_INT_C + #define BN_MP_SQRT_C + #define BN_MP_SQR_C + #define BN_MP_CMP_MAG_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_JACOBI_C) + #define BN_MP_CMP_D_C + #define BN_MP_ISZERO_C + #define BN_MP_INIT_COPY_C + #define BN_MP_CNT_LSB_C + #define BN_MP_DIV_2D_C + #define BN_MP_MOD_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_KARATSUBA_MUL_C) + #define BN_MP_MUL_C + #define BN_MP_INIT_SIZE_C + #define BN_MP_CLAMP_C + #define BN_MP_SUB_C + #define BN_MP_ADD_C + #define BN_MP_LSHD_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_KARATSUBA_SQR_C) + #define BN_MP_INIT_SIZE_C + #define BN_MP_CLAMP_C + #define BN_MP_SQR_C + #define BN_MP_SUB_C + #define BN_S_MP_ADD_C + #define BN_MP_LSHD_C + #define BN_MP_ADD_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_LCM_C) + #define BN_MP_INIT_MULTI_C + #define BN_MP_GCD_C + #define BN_MP_CMP_MAG_C + #define BN_MP_DIV_C + #define BN_MP_MUL_C + #define BN_MP_CLEAR_MULTI_C +#endif + +#if defined(BN_MP_LSHD_C) + #define BN_MP_GROW_C + #define BN_MP_RSHD_C +#endif + +#if defined(BN_MP_MOD_C) + #define BN_MP_INIT_C + #define BN_MP_DIV_C + #define BN_MP_CLEAR_C + #define BN_MP_ADD_C + #define BN_MP_EXCH_C +#endif + +#if defined(BN_MP_MOD_2D_C) + #define BN_MP_ZERO_C + #define BN_MP_COPY_C + #define BN_MP_CLAMP_C +#endif + +#if defined(BN_MP_MOD_D_C) + #define BN_MP_DIV_D_C +#endif + +#if defined(BN_MP_MONTGOMERY_CALC_NORMALIZATION_C) + #define BN_MP_COUNT_BITS_C + #define BN_MP_2EXPT_C + #define BN_MP_SET_C + #define BN_MP_MUL_2_C + #define BN_MP_CMP_MAG_C + #define BN_S_MP_SUB_C +#endif + +#if defined(BN_MP_MONTGOMERY_REDUCE_C) + #define BN_FAST_MP_MONTGOMERY_REDUCE_C + #define BN_MP_GROW_C + #define BN_MP_CLAMP_C + #define BN_MP_RSHD_C + #define BN_MP_CMP_MAG_C + #define BN_S_MP_SUB_C +#endif + +#if defined(BN_MP_MONTGOMERY_SETUP_C) +#endif + +#if defined(BN_MP_MUL_C) + #define BN_MP_TOOM_MUL_C + #define BN_MP_KARATSUBA_MUL_C + #define BN_FAST_S_MP_MUL_DIGS_C + #define BN_S_MP_MUL_C + #define BN_S_MP_MUL_DIGS_C +#endif + +#if defined(BN_MP_MUL_2_C) + #define BN_MP_GROW_C +#endif + +#if defined(BN_MP_MUL_2D_C) + #define BN_MP_COPY_C + #define BN_MP_GROW_C + #define BN_MP_LSHD_C + #define BN_MP_CLAMP_C +#endif + +#if defined(BN_MP_MUL_D_C) + #define BN_MP_GROW_C + #define BN_MP_CLAMP_C +#endif + +#if defined(BN_MP_MULMOD_C) + #define BN_MP_INIT_C + #define BN_MP_MUL_C + #define BN_MP_CLEAR_C + #define BN_MP_MOD_C +#endif + +#if defined(BN_MP_N_ROOT_C) + #define BN_MP_INIT_C + #define BN_MP_SET_C + #define BN_MP_COPY_C + #define BN_MP_EXPT_D_C + #define BN_MP_MUL_C + #define BN_MP_SUB_C + #define BN_MP_MUL_D_C + #define BN_MP_DIV_C + #define BN_MP_CMP_C + #define BN_MP_SUB_D_C + #define BN_MP_EXCH_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_NEG_C) + #define BN_MP_COPY_C + #define BN_MP_ISZERO_C +#endif + +#if defined(BN_MP_OR_C) + #define BN_MP_INIT_COPY_C + #define BN_MP_CLAMP_C + #define BN_MP_EXCH_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_PRIME_FERMAT_C) + #define BN_MP_CMP_D_C + #define BN_MP_INIT_C + #define BN_MP_EXPTMOD_C + #define BN_MP_CMP_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_PRIME_IS_DIVISIBLE_C) + #define BN_MP_MOD_D_C +#endif + +#if defined(BN_MP_PRIME_IS_PRIME_C) + #define BN_MP_CMP_D_C + #define BN_MP_PRIME_IS_DIVISIBLE_C + #define BN_MP_INIT_C + #define BN_MP_SET_C + #define BN_MP_PRIME_MILLER_RABIN_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_PRIME_MILLER_RABIN_C) + #define BN_MP_CMP_D_C + #define BN_MP_INIT_COPY_C + #define BN_MP_SUB_D_C + #define BN_MP_CNT_LSB_C + #define BN_MP_DIV_2D_C + #define BN_MP_EXPTMOD_C + #define BN_MP_CMP_C + #define BN_MP_SQRMOD_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_PRIME_NEXT_PRIME_C) + #define BN_MP_CMP_D_C + #define BN_MP_SET_C + #define BN_MP_SUB_D_C + #define BN_MP_ISEVEN_C + #define BN_MP_MOD_D_C + #define BN_MP_INIT_C + #define BN_MP_ADD_D_C + #define BN_MP_PRIME_MILLER_RABIN_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_PRIME_RABIN_MILLER_TRIALS_C) +#endif + +#if defined(BN_MP_PRIME_RANDOM_EX_C) + #define BN_MP_READ_UNSIGNED_BIN_C + #define BN_MP_PRIME_IS_PRIME_C + #define BN_MP_SUB_D_C + #define BN_MP_DIV_2_C + #define BN_MP_MUL_2_C + #define BN_MP_ADD_D_C +#endif + +#if defined(BN_MP_RADIX_SIZE_C) + #define BN_MP_COUNT_BITS_C + #define BN_MP_INIT_COPY_C + #define BN_MP_ISZERO_C + #define BN_MP_DIV_D_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_RADIX_SMAP_C) + #define BN_MP_S_RMAP_C +#endif + +#if defined(BN_MP_RAND_C) + #define BN_MP_ZERO_C + #define BN_MP_ADD_D_C + #define BN_MP_LSHD_C +#endif + +#if defined(BN_MP_READ_RADIX_C) + #define BN_MP_ZERO_C + #define BN_MP_S_RMAP_C + #define BN_MP_RADIX_SMAP_C + #define BN_MP_MUL_D_C + #define BN_MP_ADD_D_C + #define BN_MP_ISZERO_C +#endif + +#if defined(BN_MP_READ_SIGNED_BIN_C) + #define BN_MP_READ_UNSIGNED_BIN_C +#endif + +#if defined(BN_MP_READ_UNSIGNED_BIN_C) + #define BN_MP_GROW_C + #define BN_MP_ZERO_C + #define BN_MP_MUL_2D_C + #define BN_MP_CLAMP_C +#endif + +#if defined(BN_MP_REDUCE_C) + #define BN_MP_REDUCE_SETUP_C + #define BN_MP_INIT_COPY_C + #define BN_MP_RSHD_C + #define BN_MP_MUL_C + #define BN_S_MP_MUL_HIGH_DIGS_C + #define BN_FAST_S_MP_MUL_HIGH_DIGS_C + #define BN_MP_MOD_2D_C + #define BN_S_MP_MUL_DIGS_C + #define BN_MP_SUB_C + #define BN_MP_CMP_D_C + #define BN_MP_SET_C + #define BN_MP_LSHD_C + #define BN_MP_ADD_C + #define BN_MP_CMP_C + #define BN_S_MP_SUB_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_REDUCE_2K_C) + #define BN_MP_INIT_C + #define BN_MP_COUNT_BITS_C + #define BN_MP_DIV_2D_C + #define BN_MP_MUL_D_C + #define BN_S_MP_ADD_C + #define BN_MP_CMP_MAG_C + #define BN_S_MP_SUB_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_REDUCE_2K_L_C) + #define BN_MP_INIT_C + #define BN_MP_COUNT_BITS_C + #define BN_MP_DIV_2D_C + #define BN_MP_MUL_C + #define BN_S_MP_ADD_C + #define BN_MP_CMP_MAG_C + #define BN_S_MP_SUB_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_REDUCE_2K_SETUP_C) + #define BN_MP_INIT_C + #define BN_MP_COUNT_BITS_C + #define BN_MP_2EXPT_C + #define BN_MP_CLEAR_C + #define BN_S_MP_SUB_C +#endif + +#if defined(BN_MP_REDUCE_2K_SETUP_L_C) + #define BN_MP_INIT_C + #define BN_MP_2EXPT_C + #define BN_MP_COUNT_BITS_C + #define BN_S_MP_SUB_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_REDUCE_IS_2K_C) + #define BN_MP_REDUCE_2K_C + #define BN_MP_COUNT_BITS_C +#endif + +#if defined(BN_MP_REDUCE_IS_2K_L_C) +#endif + +#if defined(BN_MP_REDUCE_SETUP_C) + #define BN_MP_2EXPT_C + #define BN_MP_DIV_C +#endif + +#if defined(BN_MP_RSHD_C) + #define BN_MP_ZERO_C +#endif + +#if defined(BN_MP_SET_C) + #define BN_MP_ZERO_C +#endif + +#if defined(BN_MP_SET_INT_C) + #define BN_MP_ZERO_C + #define BN_MP_MUL_2D_C + #define BN_MP_CLAMP_C +#endif + +#if defined(BN_MP_SHRINK_C) +#endif + +#if defined(BN_MP_SIGNED_BIN_SIZE_C) + #define BN_MP_UNSIGNED_BIN_SIZE_C +#endif + +#if defined(BN_MP_SQR_C) + #define BN_MP_TOOM_SQR_C + #define BN_MP_KARATSUBA_SQR_C + #define BN_FAST_S_MP_SQR_C + #define BN_S_MP_SQR_C +#endif + +#if defined(BN_MP_SQRMOD_C) + #define BN_MP_INIT_C + #define BN_MP_SQR_C + #define BN_MP_CLEAR_C + #define BN_MP_MOD_C +#endif + +#if defined(BN_MP_SQRT_C) + #define BN_MP_N_ROOT_C + #define BN_MP_ISZERO_C + #define BN_MP_ZERO_C + #define BN_MP_INIT_COPY_C + #define BN_MP_RSHD_C + #define BN_MP_DIV_C + #define BN_MP_ADD_C + #define BN_MP_DIV_2_C + #define BN_MP_CMP_MAG_C + #define BN_MP_EXCH_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_SUB_C) + #define BN_S_MP_ADD_C + #define BN_MP_CMP_MAG_C + #define BN_S_MP_SUB_C +#endif + +#if defined(BN_MP_SUB_D_C) + #define BN_MP_GROW_C + #define BN_MP_ADD_D_C + #define BN_MP_CLAMP_C +#endif + +#if defined(BN_MP_SUBMOD_C) + #define BN_MP_INIT_C + #define BN_MP_SUB_C + #define BN_MP_CLEAR_C + #define BN_MP_MOD_C +#endif + +#if defined(BN_MP_TO_SIGNED_BIN_C) + #define BN_MP_TO_UNSIGNED_BIN_C +#endif + +#if defined(BN_MP_TO_SIGNED_BIN_N_C) + #define BN_MP_SIGNED_BIN_SIZE_C + #define BN_MP_TO_SIGNED_BIN_C +#endif + +#if defined(BN_MP_TO_UNSIGNED_BIN_C) + #define BN_MP_INIT_COPY_C + #define BN_MP_ISZERO_C + #define BN_MP_DIV_2D_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_TO_UNSIGNED_BIN_N_C) + #define BN_MP_UNSIGNED_BIN_SIZE_C + #define BN_MP_TO_UNSIGNED_BIN_C +#endif + +#if defined(BN_MP_TOOM_MUL_C) + #define BN_MP_INIT_MULTI_C + #define BN_MP_MOD_2D_C + #define BN_MP_COPY_C + #define BN_MP_RSHD_C + #define BN_MP_MUL_C + #define BN_MP_MUL_2_C + #define BN_MP_ADD_C + #define BN_MP_SUB_C + #define BN_MP_DIV_2_C + #define BN_MP_MUL_2D_C + #define BN_MP_MUL_D_C + #define BN_MP_DIV_3_C + #define BN_MP_LSHD_C + #define BN_MP_CLEAR_MULTI_C +#endif + +#if defined(BN_MP_TOOM_SQR_C) + #define BN_MP_INIT_MULTI_C + #define BN_MP_MOD_2D_C + #define BN_MP_COPY_C + #define BN_MP_RSHD_C + #define BN_MP_SQR_C + #define BN_MP_MUL_2_C + #define BN_MP_ADD_C + #define BN_MP_SUB_C + #define BN_MP_DIV_2_C + #define BN_MP_MUL_2D_C + #define BN_MP_MUL_D_C + #define BN_MP_DIV_3_C + #define BN_MP_LSHD_C + #define BN_MP_CLEAR_MULTI_C +#endif + +#if defined(BN_MP_TORADIX_C) + #define BN_MP_ISZERO_C + #define BN_MP_INIT_COPY_C + #define BN_MP_DIV_D_C + #define BN_MP_CLEAR_C + #define BN_MP_S_RMAP_C +#endif + +#if defined(BN_MP_TORADIX_N_C) + #define BN_MP_ISZERO_C + #define BN_MP_INIT_COPY_C + #define BN_MP_DIV_D_C + #define BN_MP_CLEAR_C + #define BN_MP_S_RMAP_C +#endif + +#if defined(BN_MP_UNSIGNED_BIN_SIZE_C) + #define BN_MP_COUNT_BITS_C +#endif + +#if defined(BN_MP_XOR_C) + #define BN_MP_INIT_COPY_C + #define BN_MP_CLAMP_C + #define BN_MP_EXCH_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_MP_ZERO_C) +#endif + +#if defined(BN_PRIME_TAB_C) +#endif + +#if defined(BN_REVERSE_C) +#endif + +#if defined(BN_S_MP_ADD_C) + #define BN_MP_GROW_C + #define BN_MP_CLAMP_C +#endif + +#if defined(BN_S_MP_EXPTMOD_C) + #define BN_MP_COUNT_BITS_C + #define BN_MP_INIT_C + #define BN_MP_CLEAR_C + #define BN_MP_REDUCE_SETUP_C + #define BN_MP_REDUCE_C + #define BN_MP_REDUCE_2K_SETUP_L_C + #define BN_MP_REDUCE_2K_L_C + #define BN_MP_MOD_C + #define BN_MP_COPY_C + #define BN_MP_SQR_C + #define BN_MP_MUL_C + #define BN_MP_SET_C + #define BN_MP_EXCH_C +#endif + +#if defined(BN_S_MP_MUL_DIGS_C) + #define BN_FAST_S_MP_MUL_DIGS_C + #define BN_MP_INIT_SIZE_C + #define BN_MP_CLAMP_C + #define BN_MP_EXCH_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_S_MP_MUL_HIGH_DIGS_C) + #define BN_FAST_S_MP_MUL_HIGH_DIGS_C + #define BN_MP_INIT_SIZE_C + #define BN_MP_CLAMP_C + #define BN_MP_EXCH_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_S_MP_SQR_C) + #define BN_MP_INIT_SIZE_C + #define BN_MP_CLAMP_C + #define BN_MP_EXCH_C + #define BN_MP_CLEAR_C +#endif + +#if defined(BN_S_MP_SUB_C) + #define BN_MP_GROW_C + #define BN_MP_CLAMP_C +#endif + +#if defined(BNCORE_C) +#endif + +#ifdef LTM3 +#define LTM_LAST +#endif +#include "mpi_superclass.h" +#include "mpi_class.h" +#else +#define LTM_LAST +#endif + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/mpi_superclass.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/mpi_superclass.h new file mode 100755 index 0000000..7347268 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/mpi_superclass.h @@ -0,0 +1,96 @@ +/* mpi_superclass.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +/* super class file for PK algos */ + +/* default ... include all MPI */ +#define LTM_ALL + +/* RSA only (does not support DH/DSA/ECC) */ +/* #define SC_RSA_1 */ + +/* For reference.... On an Athlon64 optimizing for speed... + + LTM's mpi.o with all functions [striped] is 142KiB in size. + +*/ + +/* Works for RSA only, mpi.o is 68KiB */ +#ifdef SC_RSA_1 + #define BN_MP_SHRINK_C + #define BN_MP_LCM_C + #define BN_MP_PRIME_RANDOM_EX_C + #define BN_MP_INVMOD_C + #define BN_MP_GCD_C + #define BN_MP_MOD_C + #define BN_MP_MULMOD_C + #define BN_MP_ADDMOD_C + #define BN_MP_EXPTMOD_C + #define BN_MP_SET_INT_C + #define BN_MP_INIT_MULTI_C + #define BN_MP_CLEAR_MULTI_C + #define BN_MP_UNSIGNED_BIN_SIZE_C + #define BN_MP_TO_UNSIGNED_BIN_C + #define BN_MP_MOD_D_C + #define BN_MP_PRIME_RABIN_MILLER_TRIALS_C + #define BN_REVERSE_C + #define BN_PRIME_TAB_C + + /* other modifiers */ + #define BN_MP_DIV_SMALL /* Slower division, not critical */ + + /* here we are on the last pass so we turn things off. The functions classes are still there + * but we remove them specifically from the build. This also invokes tweaks in functions + * like removing support for even moduli, etc... + */ +#ifdef LTM_LAST + #undef BN_MP_TOOM_MUL_C + #undef BN_MP_TOOM_SQR_C + #undef BN_MP_KARATSUBA_MUL_C + #undef BN_MP_KARATSUBA_SQR_C + #undef BN_MP_REDUCE_C + #undef BN_MP_REDUCE_SETUP_C + #undef BN_MP_DR_IS_MODULUS_C + #undef BN_MP_DR_SETUP_C + #undef BN_MP_DR_REDUCE_C + #undef BN_MP_REDUCE_IS_2K_C + #undef BN_MP_REDUCE_2K_SETUP_C + #undef BN_MP_REDUCE_2K_C + #undef BN_S_MP_EXPTMOD_C + #undef BN_MP_DIV_3_C + #undef BN_S_MP_MUL_HIGH_DIGS_C + #undef BN_FAST_S_MP_MUL_HIGH_DIGS_C + #undef BN_FAST_MP_INVMOD_C + + /* To safely undefine these you have to make sure your RSA key won't exceed the Comba threshold + * which is roughly 255 digits [7140 bits for 32-bit machines, 15300 bits for 64-bit machines] + * which means roughly speaking you can handle up to 2536-bit RSA keys with these defined without + * trouble. + */ + #undef BN_S_MP_MUL_DIGS_C + #undef BN_S_MP_SQR_C + #undef BN_MP_MONTGOMERY_REDUCE_C +#endif + +#endif + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/pkcs11.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/pkcs11.h new file mode 100755 index 0000000..0e5e7b2 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/pkcs11.h @@ -0,0 +1,537 @@ +/* pkcs11.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#ifndef _PKCS11_H_ +#define _PKCS11_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef NULL_PTR +#define NULL_PTR 0 +#endif +#define CK_TRUE 1 +#define CK_FALSE 0 + + +#define CK_INVALID_HANDLE 0UL + +#define CKN_SURRENDER 0UL + +#define CKF_TOKEN_PRESENT 0x00000001UL +#define CKF_REMOVABLE_DEVICE 0x00000002UL +#define CKF_HW_SLOT 0x00000004UL + +#define CKF_HW 0x00000001UL +#define CKF_ENCRYPT 0x00000100UL +#define CKF_DECRYPT 0x00000200UL +#define CKF_DIGEST 0x00000400UL +#define CKF_SIGN 0x00000800UL +#define CKF_SIGN_RECOVER 0x00001000UL +#define CKF_VERIFY 0x00002000UL +#define CKF_VERIFY_RECOVER 0x00004000UL +#define CKF_GENERATE 0x00008000UL +#define CKF_GENERATE_KEY_PAIR 0x00010000UL +#define CKF_WRAP 0x00020000UL +#define CKF_UNWRAP 0x00040000UL +#define CKF_DERIVE 0x00080000UL +#define CKF_EC_F_P 0x00100000UL +#define CKF_EC_F_2M 0x00200000UL +#define CKF_EC_ECPARAMETERS 0x00400000UL +#define CKF_EC_NAMEDCURVE 0x00800000UL +#define CKF_EC_UNCOMPRESS 0x01000000UL +#define CKF_EC_COMPRESS 0x02000000UL + +#define CKF_LIBRARY_CANT_CREATE_OS_THREADS 0x00000001UL +#define CKF_OS_LOCKING_OK 0x00000002UL + +#define CKU_SO 0UL +#define CKU_USER 1UL +#define CKU_CONTEXT_SPECIFIC 2UL + +#define CKF_RW_SESSION 0x00000002UL +#define CKF_SERIAL_SESSION 0x00000004UL + +#define CKO_PUBLIC_KEY 0x00000002UL +#define CKO_PRIVATE_KEY 0x00000003UL +#define CKO_SECRET_KEY 0x00000004UL + +#define CKK_RSA 0x00000000UL +#define CKK_DH 0x00000002UL +#define CKK_EC 0x00000003UL +#define CKK_GENERIC_SECRET 0x00000010UL +#define CKK_AES 0x0000001FUL +#define CKK_MD5_HMAC 0x00000027UL +#define CKK_SHA_1_HMAC 0x00000028UL +#define CKK_SHA256_HMAC 0x0000002bUL +#define CKK_SHA384_HMAC 0x0000002cUL +#define CKK_SHA512_HMAC 0x0000002dUL +#define CKK_SHA224_HMAC 0x0000002eUL + +#define CKA_CLASS 0x00000000UL +#define CKA_TOKEN 0x00000001UL +#define CKA_PRIVATE 0x00000002UL +#define CKA_LABEL 0x00000003UL +#define CKA_VALUE 0x00000011UL +#define CKA_OBJECT_ID 0x00000012UL +#define CKA_OWNER 0x00000084UL +#define CKA_TRUSTED 0x00000086UL +#define CKA_KEY_TYPE 0x00000100UL +#define CKA_ID 0x00000102UL +#define CKA_SENSITIVE 0x00000103UL +#define CKA_ENCRYPT 0x00000104UL +#define CKA_DECRYPT 0x00000105UL +#define CKA_WRAP 0x00000106UL +#define CKA_UNWRAP 0x00000107UL +#define CKA_SIGN 0x00000108UL +#define CKA_SIGN_RECOVER 0x00000109UL +#define CKA_VERIFY 0x0000010AUL +#define CKA_VERIFY_RECOVER 0x0000010BUL +#define CKA_DERIVE 0x0000010CUL +#define CKA_MODULUS 0x00000120UL +#define CKA_MODULUS_BITS 0x00000121UL +#define CKA_PUBLIC_EXPONENT 0x00000122UL +#define CKA_PRIVATE_EXPONENT 0x00000123UL +#define CKA_PRIME_1 0x00000124UL +#define CKA_PRIME_2 0x00000125UL +#define CKA_EXPONENT_1 0x00000126UL +#define CKA_EXPONENT_2 0x00000127UL +#define CKA_COEFFICIENT 0x00000128UL +#define CKA_PUBLIC_KEY_INFO 0x00000129UL +#define CKA_PRIME 0x00000130UL +#define CKA_BASE 0x00000132UL +#define CKA_PRIME_BITS 0x00000133UL +#define CKA_VALUE_BITS 0x00000160UL +#define CKA_VALUE_LEN 0x00000161UL +#define CKA_EXTRACTABLE 0x00000162UL +#define CKA_LOCAL 0x00000163UL +#define CKA_NEVER_EXTRACTABLE 0x00000164UL +#define CKA_ALWAYS_SENSITIVE 0x00000165UL +#define CKA_KEY_GEN_MECHANISM 0x00000166UL +#define CKA_MODIFIABLE 0x00000170UL +#define CKA_COPYABLE 0x00000171UL +#define CKA_DESTROYABLE 0x00000172UL +#define CKA_EC_PARAMS 0x00000180UL +#define CKA_EC_POINT 0x00000181UL +#define CKA_ALWAYS_AUTHENTICATE 0x00000202UL +#define CKA_HW_FEATURE_TYPE 0x00000300UL +#define CKA_RESET_ON_INIT 0x00000301UL +#define CKA_HAS_RESET 0x00000302UL + +#define CKM_RSA_PKCS_KEY_PAIR_GEN 0x00000000UL +#define CKM_RSA_X_509 0x00000003UL +#define CKM_DH_PKCS_KEY_PAIR_GEN 0x00000020UL +#define CKM_DH_PKCS_DERIVE 0x00000021UL +#define CKM_MD5_HMAC 0x00000211UL +#define CKM_SHA_1_HMAC 0x00000221UL +#define CKM_SHA256_HMAC 0x00000251UL +#define CKM_SHA224_HMAC 0x00000256UL +#define CKM_SHA384_HMAC 0x00000261UL +#define CKM_SHA512_HMAC 0x00000271UL +#define CKM_GENERIC_SECRET_KEY_GEN 0x00000350UL +#define CKM_EC_KEY_PAIR_GEN 0x00001040UL +#define CKM_ECDSA 0x00001041UL +#define CKM_ECDH1_DERIVE 0x00001050UL +#define CKM_ECDH1_COFACTOR_DERIVE 0x00001051UL +#define CKM_AES_KEY_GEN 0x00001080UL +#define CKM_AES_CBC 0x00001082UL +#define CKM_AES_GCM 0x00001087UL + +#define CKR_OK 0x00000000UL +#define CKR_MECHANISM_INVALID 0x00000070UL +#define CKR_SIGNATURE_INVALID 0x000000C0UL + +#define CKD_NULL 0x00000001UL + + +typedef unsigned char CK_BYTE; +typedef CK_BYTE CK_CHAR; +typedef CK_BYTE CK_UTF8CHAR; +typedef CK_BYTE CK_BBOOL; +typedef unsigned long int CK_ULONG; +typedef long int CK_LONG; +typedef CK_ULONG CK_FLAGS; +typedef CK_BYTE* CK_BYTE_PTR; +typedef CK_CHAR* CK_CHAR_PTR; +typedef CK_UTF8CHAR* CK_UTF8CHAR_PTR; +typedef CK_ULONG* CK_ULONG_PTR; +typedef void* CK_VOID_PTR; +typedef CK_VOID_PTR* CK_VOID_PTR_PTR; + + +typedef CK_ULONG CK_RV; + + +typedef struct CK_VERSION { + CK_BYTE major; + CK_BYTE minor; +} CK_VERSION; +typedef CK_VERSION* CK_VERSION_PTR; + + +/* Info Types */ +typedef struct CK_INFO { + CK_VERSION cryptokiVersion; + CK_UTF8CHAR manufacturerID[32]; + CK_FLAGS flags; + CK_UTF8CHAR libraryDescription[32]; + CK_VERSION libraryVersion; +} CK_INFO; +typedef CK_INFO* CK_INFO_PTR; + + +/* Slot Types */ +typedef CK_ULONG CK_SLOT_ID; +typedef CK_SLOT_ID* CK_SLOT_ID_PTR; + +typedef struct CK_SLOT_INFO { + CK_UTF8CHAR slotDescription[64]; + CK_UTF8CHAR manufacturerID[32]; + CK_FLAGS flags; + + CK_VERSION hardwareVersion; + CK_VERSION firmwareVersion; +} CK_SLOT_INFO; +typedef CK_SLOT_INFO* CK_SLOT_INFO_PTR; + + +/* Token Types */ +typedef struct CK_TOKEN_INFO { + CK_UTF8CHAR label[32]; + CK_UTF8CHAR manufacturerID[32]; + CK_UTF8CHAR model[16]; + CK_CHAR serialNumber[16]; + CK_FLAGS flags; + CK_ULONG ulMaxSessionCount; + CK_ULONG ulSessionCount; + CK_ULONG ulMaxRwSessionCount; + CK_ULONG ulRwSessionCount; + CK_ULONG ulMaxPinLen; + CK_ULONG ulMinPinLen; + CK_ULONG ulTotalPublicMemory; + CK_ULONG ulFreePublicMemory; + CK_ULONG ulTotalPrivateMemory; + CK_ULONG ulFreePrivateMemory; + CK_VERSION hardwareVersion; + CK_VERSION firmwareVersion; + CK_CHAR utcTime[16]; +} CK_TOKEN_INFO; +typedef CK_TOKEN_INFO* CK_TOKEN_INFO_PTR; + + +/* Session Types */ +typedef CK_ULONG CK_SESSION_HANDLE; +typedef CK_SESSION_HANDLE* CK_SESSION_HANDLE_PTR; + +typedef CK_ULONG CK_USER_TYPE; + +typedef CK_ULONG CK_STATE; + +typedef struct CK_SESSION_INFO { + CK_SLOT_ID slotID; + CK_STATE state; + CK_FLAGS flags; + CK_ULONG ulDeviceError; +} CK_SESSION_INFO; +typedef CK_SESSION_INFO* CK_SESSION_INFO_PTR; + + +/* Object Types */ +typedef CK_ULONG CK_OBJECT_HANDLE; +typedef CK_OBJECT_HANDLE* CK_OBJECT_HANDLE_PTR; + +typedef CK_ULONG CK_OBJECT_CLASS; +typedef CK_OBJECT_CLASS* CK_OBJECT_CLASS_PTR; + +typedef CK_ULONG CK_KEY_TYPE; + +typedef CK_ULONG CK_ATTRIBUTE_TYPE; + +typedef struct CK_ATTRIBUTE { + CK_ATTRIBUTE_TYPE type; + CK_VOID_PTR pValue; + CK_ULONG ulValueLen; +} CK_ATTRIBUTE; +typedef CK_ATTRIBUTE* CK_ATTRIBUTE_PTR; + + +/* Mechanism Types */ +typedef CK_ULONG CK_MECHANISM_TYPE; +typedef CK_MECHANISM_TYPE* CK_MECHANISM_TYPE_PTR; + +typedef struct CK_MECHANISM { + CK_MECHANISM_TYPE mechanism; + CK_VOID_PTR pParameter; + CK_ULONG ulParameterLen; +} CK_MECHANISM; +typedef CK_MECHANISM* CK_MECHANISM_PTR; + +typedef struct CK_MECHANISM_INFO { + CK_ULONG ulMinKeySize; + CK_ULONG ulMaxKeySize; + CK_FLAGS flags; +} CK_MECHANISM_INFO; +typedef CK_MECHANISM_INFO * CK_MECHANISM_INFO_PTR; + + +typedef CK_ULONG CK_NOTIFICATION; + +typedef CK_RV (*CK_NOTIFY)(CK_SESSION_HANDLE hSession, CK_NOTIFICATION event, + CK_VOID_PTR pApplication); + + +/* Threading types. */ +typedef CK_RV (*CK_CREATEMUTEX)(CK_VOID_PTR_PTR ppMutex); +typedef CK_RV (*CK_DESTROYMUTEX)(CK_VOID_PTR pMutex); +typedef CK_RV (*CK_LOCKMUTEX)(CK_VOID_PTR pMutex); +typedef CK_RV (*CK_UNLOCKMUTEX)(CK_VOID_PTR pMutex); + +typedef struct CK_C_INITIALIZE_ARGS { + CK_CREATEMUTEX CreateMutex; + CK_DESTROYMUTEX DestroyMutex; + CK_LOCKMUTEX LockMutex; + CK_UNLOCKMUTEX UnlockMutex; + CK_FLAGS flags; + CK_VOID_PTR pReserved; +} CK_C_INITIALIZE_ARGS; +typedef CK_C_INITIALIZE_ARGS* CK_C_INITIALIZE_ARGS_PTR; + + +/* Cryptographic algorithm types. */ +typedef CK_ULONG CK_EC_KDF_TYPE; + +typedef struct CK_ECDH1_DERIVE_PARAMS { + CK_EC_KDF_TYPE kdf; + CK_ULONG ulSharedDataLen; + CK_BYTE_PTR pSharedData; + CK_ULONG ulPublicDataLen; + CK_BYTE_PTR pPublicData; +} CK_ECDH1_DERIVE_PARAMS; +typedef CK_ECDH1_DERIVE_PARAMS* CK_ECDH1_DERIVE_PARAMS_PTR; + + +typedef struct CK_GCM_PARAMS { + CK_BYTE_PTR pIv; + CK_ULONG ulIvLen; + CK_ULONG ulIvBits; + CK_BYTE_PTR pAAD; + CK_ULONG ulAADLen; + CK_ULONG ulTagBits; +} CK_GCM_PARAMS; +typedef CK_GCM_PARAMS* CK_GCM_PARAMS_PTR; + +/* Function list types. */ +typedef struct CK_FUNCTION_LIST CK_FUNCTION_LIST; +typedef CK_FUNCTION_LIST* CK_FUNCTION_LIST_PTR; +typedef CK_FUNCTION_LIST_PTR* CK_FUNCTION_LIST_PTR_PTR; + +typedef CK_RV (*CK_C_GetFunctionList)(CK_FUNCTION_LIST_PTR_PTR ppFunctionList); + +struct CK_FUNCTION_LIST { + CK_VERSION version; + + CK_RV (*C_Initialize)(CK_VOID_PTR pInitArgs); + CK_RV (*C_Finalize)(CK_VOID_PTR pReserved); + CK_RV (*C_GetInfo)(CK_INFO_PTR pInfo); + CK_RV (*C_GetFunctionList)(CK_FUNCTION_LIST_PTR_PTR ppFunctionList); + CK_RV (*C_GetSlotList)(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, + CK_ULONG_PTR pulCount); + CK_RV (*C_GetSlotInfo)(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo); + CK_RV (*C_GetTokenInfo)(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo); + CK_RV (*C_GetMechanismList)(CK_SLOT_ID slotID, + CK_MECHANISM_TYPE_PTR pMechanismList, + CK_ULONG_PTR pulCount); + CK_RV (*C_GetMechanismInfo)(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, + CK_MECHANISM_INFO_PTR pInfo); + CK_RV (*C_InitToken)(CK_SLOT_ID slotID, CK_UTF8CHAR_PTR pPin, + CK_ULONG ulPinLen, CK_UTF8CHAR_PTR pLabel); + CK_RV (*C_InitPIN)(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pPin, + CK_ULONG ulPinLen); + CK_RV (*C_SetPIN)(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pOldPin, + CK_ULONG ulOldLen, CK_UTF8CHAR_PTR pNewPin, + CK_ULONG ulNewLen); + CK_RV (*C_OpenSession)(CK_SLOT_ID slotID, CK_FLAGS flags, + CK_VOID_PTR pApplication, CK_NOTIFY Notify, + CK_SESSION_HANDLE_PTR phSession); + CK_RV (*C_CloseSession)(CK_SESSION_HANDLE hSession); + CK_RV (*C_CloseAllSessions)(CK_SLOT_ID slotID); + CK_RV (*C_GetSessionInfo)(CK_SESSION_HANDLE hSession, + CK_SESSION_INFO_PTR pInfo); + CK_RV (*C_GetOperationState)(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pOperationState, + CK_ULONG_PTR pulOperationStateLen); + CK_RV (*C_SetOperationState)(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pOperationState, + CK_ULONG ulOperationStateLen, + CK_OBJECT_HANDLE hEncryptionKey, + CK_OBJECT_HANDLE hAuthenticationKey); + CK_RV (*C_Login)(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, + CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen); + CK_RV (*C_Logout)(CK_SESSION_HANDLE hSession); + CK_RV (*C_CreateObject)(CK_SESSION_HANDLE hSession, + CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, + CK_OBJECT_HANDLE_PTR phObject); + CK_RV (*C_CopyObject)(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, + CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, + CK_OBJECT_HANDLE_PTR phNewObject); + CK_RV (*C_DestroyObject)(CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hObject); + CK_RV (*C_GetObjectSize)(CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hObject, CK_ULONG_PTR pulSize); + CK_RV (*C_GetAttributeValue)(CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hObject, + CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount); + CK_RV (*C_SetAttributeValue)(CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE hObject, + CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount); + CK_RV (*C_FindObjectsInit)(CK_SESSION_HANDLE hSession, + CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount); + CK_RV (*C_FindObjects)(CK_SESSION_HANDLE hSession, + CK_OBJECT_HANDLE_PTR phObject, + CK_ULONG ulMaxObjectCount, + CK_ULONG_PTR pulObjectCount); + CK_RV (*C_FindObjectsFinal)(CK_SESSION_HANDLE hSession); + CK_RV (*C_EncryptInit)(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey); + CK_RV (*C_Encrypt)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, + CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, + CK_ULONG_PTR pulEncryptedDataLen); + CK_RV (*C_EncryptUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, + CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, + CK_ULONG_PTR pulEncryptedPartLen); + CK_RV (*C_EncryptFinal)(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pLastEncryptedPart, + CK_ULONG_PTR pulLastEncryptedPartLen); + CK_RV (*C_DecryptInit)(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey); + CK_RV (*C_Decrypt)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, + CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, + CK_ULONG_PTR pulDataLen); + CK_RV (*C_DecryptUpdate)(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pEncryptedPart, + CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, + CK_ULONG_PTR pulPartLen); + CK_RV (*C_DecryptFinal)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastPart, + CK_ULONG_PTR pulLastPartLen); + CK_RV (*C_DigestInit)(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism); + CK_RV (*C_Digest)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, + CK_ULONG ulDataLen, CK_BYTE_PTR pDigest, + CK_ULONG_PTR pulDigestLen); + CK_RV (*C_DigestUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, + CK_ULONG ulPartLen); + CK_RV (*C_DigestKey)(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey); + CK_RV (*C_DigestFinal)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pDigest, + CK_ULONG_PTR pulDigestLen); + CK_RV (*C_SignInit)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hKey); + CK_RV (*C_Sign)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, + CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, + CK_ULONG_PTR pulSignatureLen); + CK_RV (*C_SignUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, + CK_ULONG ulPartLen); + CK_RV (*C_SignFinal)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, + CK_ULONG_PTR pulSignatureLen); + CK_RV (*C_SignRecoverInit)(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hKey); + CK_RV (*C_SignRecover)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, + CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, + CK_ULONG_PTR pulSignatureLen); + CK_RV (*C_VerifyInit)(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey); + CK_RV (*C_Verify)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, + CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, + CK_ULONG ulSignatureLen); + CK_RV (*C_VerifyUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, + CK_ULONG ulPartLen); + CK_RV (*C_VerifyFinal)(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen); + CK_RV (*C_VerifyRecoverInit)(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hKey); + CK_RV (*C_VerifyRecover)(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen, + CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen); + CK_RV (*C_DigestEncryptUpdate)(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pPart, CK_ULONG ulPartLen, + CK_BYTE_PTR pEncryptedPart, + CK_ULONG_PTR pulEncryptedPartLen); + CK_RV (*C_DecryptDigestUpdate)(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pEncryptedPart, + CK_ULONG ulEncryptedPartLen, + CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen); + CK_RV (*C_SignEncryptUpdate)(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pPart, CK_ULONG ulPartLen, + CK_BYTE_PTR pEncryptedPart, + CK_ULONG_PTR pulEncryptedPartLen); + CK_RV (*C_DecryptVerifyUpdate)(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR pEncryptedPart, + CK_ULONG ulEncryptedPartLen, + CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen); + CK_RV (*C_GenerateKey)(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, + CK_OBJECT_HANDLE_PTR phKey); + CK_RV (*C_GenerateKeyPair)(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_ATTRIBUTE_PTR pPublicKeyTemplate, + CK_ULONG ulPublicKeyAttributeCount, + CK_ATTRIBUTE_PTR pPrivateKeyTemplate, + CK_ULONG ulPrivateKeyAttributeCount, + CK_OBJECT_HANDLE_PTR phPublicKey, + CK_OBJECT_HANDLE_PTR phPrivateKey); + CK_RV (*C_WrapKey)(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hWrappingKey, CK_OBJECT_HANDLE hKey, + CK_BYTE_PTR pWrappedKey, + CK_ULONG_PTR pulWrappedKeyLen); + CK_RV (*C_UnwrapKey)(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hUnwrappingKey, + CK_BYTE_PTR pWrappedKey, CK_ULONG ulWrappedKeyLen, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulAttributeCount, + CK_OBJECT_HANDLE_PTR phKey); + CK_RV (*C_DeriveKey)(CK_SESSION_HANDLE hSession, + CK_MECHANISM_PTR pMechanism, + CK_OBJECT_HANDLE hBaseKey, + CK_ATTRIBUTE_PTR pTemplate, + CK_ULONG ulAttributeCount, + CK_OBJECT_HANDLE_PTR phKey); + CK_RV (*C_SeedRandom)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed, + CK_ULONG ulSeedLen); + CK_RV (*C_GenerateRandom)(CK_SESSION_HANDLE hSession, + CK_BYTE_PTR RandomData, CK_ULONG ulRandomLen); + CK_RV (*C_GetFunctionStatus)(CK_SESSION_HANDLE hSession); + CK_RV (*C_CancelFunction)(CK_SESSION_HANDLE hSession); + CK_RV (*C_WaitForSlotEvent)(CK_FLAGS flags, CK_SLOT_ID_PTR pSlot, + CK_VOID_PTR pRserved); + +}; + +#ifdef __cplusplus +} +#endif + +#endif /* _PKCS11_H_ */ + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/pkcs12.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/pkcs12.h new file mode 100755 index 0000000..e19749b --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/pkcs12.h @@ -0,0 +1,70 @@ +/* pkcs12.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifndef WOLF_CRYPT_PKCS12_H +#define WOLF_CRYPT_PKCS12_H + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +#ifndef WOLFSSL_TYPES_DEFINED /* do not redeclare from ssl.h */ + typedef struct WC_PKCS12 WC_PKCS12; +#endif + +typedef struct WC_DerCertList { /* dereferenced in ssl.c */ + byte* buffer; + word32 bufferSz; + struct WC_DerCertList* next; +} WC_DerCertList; + +/* default values for creating PKCS12 */ +enum { + WC_PKCS12_ITT_DEFAULT = 2048, + WC_PKCS12_MAC_DEFAULT = 1, +}; + +WOLFSSL_API WC_PKCS12* wc_PKCS12_new(void); +WOLFSSL_API void wc_PKCS12_free(WC_PKCS12* pkcs12); +WOLFSSL_API int wc_d2i_PKCS12(const byte* der, word32 derSz, WC_PKCS12* pkcs12); +WOLFSSL_API int wc_PKCS12_parse(WC_PKCS12* pkcs12, const char* psw, + byte** pkey, word32* pkeySz, byte** cert, word32* certSz, + WC_DerCertList** ca); +WOLFSSL_API WC_PKCS12* wc_PKCS12_create(char* pass, word32 passSz, + char* name, byte* key, word32 keySz, byte* cert, word32 certSz, + WC_DerCertList* ca, int nidKey, int nidCert, int iter, int macIter, + int keyType, void* heap); + + +WOLFSSL_LOCAL int wc_PKCS12_SetHeap(WC_PKCS12* pkcs12, void* heap); +WOLFSSL_LOCAL void* wc_PKCS12_GetHeap(WC_PKCS12* pkcs12); + +WOLFSSL_LOCAL void wc_FreeCertList(WC_DerCertList* list, void* heap); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLF_CRYPT_PKCS12_H */ + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/pkcs7.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/pkcs7.h new file mode 100755 index 0000000..436aaf7 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/pkcs7.h @@ -0,0 +1,483 @@ +/* pkcs7.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/*! + \file wolfssl/wolfcrypt/pkcs7.h +*/ + +#ifndef WOLF_CRYPT_PKCS7_H +#define WOLF_CRYPT_PKCS7_H + +#include + +#ifdef HAVE_PKCS7 + +#ifndef NO_ASN + #include +#endif +#include +#include +#ifndef NO_AES + #include +#endif +#ifndef NO_DES3 + #include +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +/* Max number of certificates that PKCS7 structure can parse */ +#ifndef MAX_PKCS7_CERTS + #define MAX_PKCS7_CERTS 4 +#endif + +#ifndef MAX_ORI_TYPE_SZ + #define MAX_ORI_TYPE_SZ MAX_OID_SZ +#endif +#ifndef MAX_ORI_VALUE_SZ + #define MAX_ORI_VALUE_SZ 512 +#endif + +#ifndef MAX_SIGNED_ATTRIBS_SZ + #define MAX_SIGNED_ATTRIBS_SZ 7 +#endif + +#ifndef MAX_AUTH_ATTRIBS_SZ + #define MAX_AUTH_ATTRIBS_SZ 7 +#endif + +#ifndef MAX_UNAUTH_ATTRIBS_SZ + #define MAX_UNAUTH_ATTRIBS_SZ 7 +#endif + +/* PKCS#7 content types, ref RFC 2315 (Section 14) */ +enum PKCS7_TYPES { + PKCS7_MSG = 650, /* 1.2.840.113549.1.7 */ + DATA = 651, /* 1.2.840.113549.1.7.1 */ + SIGNED_DATA = 652, /* 1.2.840.113549.1.7.2 */ + ENVELOPED_DATA = 653, /* 1.2.840.113549.1.7.3 */ + SIGNED_AND_ENVELOPED_DATA = 654, /* 1.2.840.113549.1.7.4 */ + DIGESTED_DATA = 655, /* 1.2.840.113549.1.7.5 */ + ENCRYPTED_DATA = 656, /* 1.2.840.113549.1.7.6 */ +#if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA) + COMPRESSED_DATA = 678, /* 1.2.840.113549.1.9.16.1.9, RFC 3274 */ +#endif + FIRMWARE_PKG_DATA = 685, /* 1.2.840.113549.1.9.16.1.16, RFC 4108 */ + AUTH_ENVELOPED_DATA = 692 /* 1.2.840.113549.1.9.16.1.23, RFC 5083 */ +}; + +enum PKCS7_STATE { + WC_PKCS7_START = 0, + + /* decode encrypted */ + WC_PKCS7_STAGE2, + WC_PKCS7_STAGE3, + WC_PKCS7_STAGE4, + WC_PKCS7_STAGE5, + WC_PKCS7_STAGE6, + + WC_PKCS7_VERIFY_STAGE2, + WC_PKCS7_VERIFY_STAGE3, + WC_PKCS7_VERIFY_STAGE4, + WC_PKCS7_VERIFY_STAGE5, + WC_PKCS7_VERIFY_STAGE6, + + /* parse info set */ + WC_PKCS7_INFOSET_START, + WC_PKCS7_INFOSET_BER, + WC_PKCS7_INFOSET_STAGE1, + WC_PKCS7_INFOSET_STAGE2, + WC_PKCS7_INFOSET_END, + + /* decode enveloped data */ + WC_PKCS7_ENV_2, + WC_PKCS7_ENV_3, + WC_PKCS7_ENV_4, + WC_PKCS7_ENV_5, + + /* decode auth enveloped */ + WC_PKCS7_AUTHENV_2, + WC_PKCS7_AUTHENV_3, + WC_PKCS7_AUTHENV_4, + WC_PKCS7_AUTHENV_5, + WC_PKCS7_AUTHENV_6, + WC_PKCS7_AUTHENV_ATRB, + WC_PKCS7_AUTHENV_ATRBEND, + WC_PKCS7_AUTHENV_7, + + /* decryption state types */ + WC_PKCS7_DECRYPT_KTRI, + WC_PKCS7_DECRYPT_KTRI_2, + WC_PKCS7_DECRYPT_KTRI_3, + + + WC_PKCS7_DECRYPT_KARI, + WC_PKCS7_DECRYPT_KEKRI, + WC_PKCS7_DECRYPT_PWRI, + WC_PKCS7_DECRYPT_ORI, + + WC_PKCS7_DECRYPT_DONE, + +}; + +enum Pkcs7_Misc { + PKCS7_NONCE_SZ = 16, + MAX_ENCRYPTED_KEY_SZ = 512, /* max enc. key size, RSA <= 4096 */ + MAX_CONTENT_KEY_LEN = 32, /* highest current cipher is AES-256-CBC */ + MAX_CONTENT_IV_SIZE = 16, /* highest current is AES128 */ +#ifndef NO_AES + MAX_CONTENT_BLOCK_LEN = AES_BLOCK_SIZE, +#else + MAX_CONTENT_BLOCK_LEN = DES_BLOCK_SIZE, +#endif + MAX_RECIP_SZ = MAX_VERSION_SZ + + MAX_SEQ_SZ + ASN_NAME_MAX + MAX_SN_SZ + + MAX_SEQ_SZ + MAX_ALGO_SZ + 1 + MAX_ENCRYPTED_KEY_SZ, +#if (defined(HAVE_FIPS) && defined(HAVE_FIPS_VERSION) && \ + (HAVE_FIPS_VERSION >= 2)) || defined(HAVE_SELFTEST) + /* In the event of fips cert 3389 or CAVP selftest build, these enums are + * not in aes.h for use with pkcs7 so enumerate it here outside the fips + * boundary */ + GCM_NONCE_MID_SZ = 12, /* The usual default nonce size for AES-GCM. */ + CCM_NONCE_MIN_SZ = 7, +#endif +}; + +enum Cms_Options { + CMS_SKID = 1, + CMS_ISSUER_AND_SERIAL_NUMBER = 2, +}; +#define DEGENERATE_SID 3 + +/* CMS/PKCS#7 RecipientInfo types, RFC 5652, Section 6.2 */ +enum Pkcs7_RecipientInfo_Types { + PKCS7_KTRI = 0, + PKCS7_KARI = 1, + PKCS7_KEKRI = 2, + PKCS7_PWRI = 3, + PKCS7_ORI = 4 +}; + +typedef struct PKCS7Attrib { + const byte* oid; + word32 oidSz; + const byte* value; + word32 valueSz; +} PKCS7Attrib; + + +typedef struct PKCS7DecodedAttrib { + struct PKCS7DecodedAttrib* next; + byte* oid; + word32 oidSz; + byte* value; + word32 valueSz; +} PKCS7DecodedAttrib; + +typedef struct PKCS7State PKCS7State; +typedef struct Pkcs7Cert Pkcs7Cert; +typedef struct Pkcs7EncodedRecip Pkcs7EncodedRecip; +typedef struct PKCS7 PKCS7; +typedef struct PKCS7SignerInfo PKCS7SignerInfo; + +/* OtherRecipientInfo decrypt callback prototype */ +typedef int (*CallbackOriDecrypt)(PKCS7* pkcs7, byte* oriType, word32 oriTypeSz, + byte* oriValue, word32 oriValueSz, + byte* decryptedKey, word32* decryptedKeySz, + void* ctx); +typedef int (*CallbackOriEncrypt)(PKCS7* pkcs7, byte* cek, word32 cekSz, + byte* oriType, word32* oriTypeSz, + byte* oriValue, word32* oriValueSz, + void* ctx); +typedef int (*CallbackDecryptContent)(PKCS7* pkcs7, int encryptOID, + byte* iv, int ivSz, byte* aad, word32 aadSz, + byte* authTag, word32 authTagSz, byte* in, + int inSz, byte* out, void* ctx); +typedef int (*CallbackWrapCEK)(PKCS7* pkcs7, byte* cek, word32 cekSz, + byte* keyId, word32 keyIdSz, + byte* originKey, word32 originKeySz, + byte* out, word32 outSz, + int keyWrapAlgo, int type, int dir); + +/* Public Structure Warning: + * Existing members must not be changed to maintain backwards compatibility! + */ +struct PKCS7 { + WC_RNG* rng; + PKCS7Attrib* signedAttribs; + byte* content; /* inner content, not owner */ + byte* contentDynamic; /* content if constructed OCTET_STRING */ + byte* singleCert; /* recipient cert, DER, not owner */ + const byte* issuer; /* issuer name of singleCert */ + byte* privateKey; /* private key, DER, not owner */ + void* heap; /* heap hint for dynamic memory */ +#ifdef ASN_BER_TO_DER + byte* der; /* DER encoded version of message */ + word32 derSz; +#endif + byte* cert[MAX_PKCS7_CERTS]; + + /* Encrypted-data Content Type */ + byte* encryptionKey; /* block cipher encryption key */ + PKCS7Attrib* unprotectedAttribs; /* optional */ + PKCS7DecodedAttrib* decodedAttrib; /* linked list of decoded attribs */ + + /* Enveloped-data optional ukm, not owner */ + byte* ukm; + word32 ukmSz; + + word32 encryptionKeySz; /* size of key buffer, bytes */ + word32 unprotectedAttribsSz; + word32 contentSz; /* content size */ + word32 singleCertSz; /* size of recipient cert buffer, bytes */ + word32 issuerSz; /* length of issuer name */ + word32 issuerSnSz; /* length of serial number */ + + word32 publicKeySz; + word32 publicKeyOID; /* key OID (RSAk, ECDSAk, etc) */ + word32 privateKeySz; /* size of private key buffer, bytes */ + word32 signedAttribsSz; + int contentOID; /* PKCS#7 content type OID sum */ + int hashOID; + int encryptOID; /* key encryption algorithm OID */ + int keyWrapOID; /* key wrap algorithm OID */ + int keyAgreeOID; /* key agreement algorithm OID */ + int devId; /* device ID for HW based private key */ + byte issuerHash[KEYID_SIZE]; /* hash of all alt Names */ + byte issuerSn[MAX_SN_SZ]; /* singleCert's serial number */ + byte publicKey[MAX_RSA_INT_SZ + MAX_RSA_E_SZ]; /* MAX RSA key size (m + e)*/ + word32 certSz[MAX_PKCS7_CERTS]; + + /* flags - up to 16-bits */ + word16 isDynamic:1; + word16 noDegenerate:1; /* allow degenerate case in verify function */ + word16 detached:1; /* generate detached SignedData signature bundles */ + + byte contentType[MAX_OID_SZ]; /* custom contentType byte array */ + word32 contentTypeSz; /* size of contentType, bytes */ + + int sidType; /* SignerIdentifier type to use, of type + Pkcs7_SignerIdentifier_Types, default to + SID_ISSUER_AND_SERIAL_NUMBER */ + byte issuerSubjKeyId[KEYID_SIZE]; /* SubjectKeyIdentifier of singleCert */ + Pkcs7Cert* certList; /* certificates list for SignedData set */ + Pkcs7EncodedRecip* recipList; /* recipients list */ + byte* cek; /* content encryption key, random, dynamic */ + word32 cekSz; /* size of cek, bytes */ + byte* pass; /* password, for PWRI decryption */ + word32 passSz; /* size of pass, bytes */ + int kekEncryptOID; /* KEK encryption algorithm OID */ + + CallbackOriEncrypt oriEncryptCb; /* ORI encrypt callback */ + CallbackOriDecrypt oriDecryptCb; /* ORI decrypt callback */ + void* oriEncryptCtx; /* ORI encrypt user context ptr */ + void* oriDecryptCtx; /* ORI decrypt user context ptr */ + + PKCS7Attrib* authAttribs; /* authenticated attribs */ + word32 authAttribsSz; + PKCS7Attrib* unauthAttribs; /* unauthenticated attribs */ + word32 unauthAttribsSz; + +#ifndef NO_PKCS7_STREAM + PKCS7State* stream; +#endif + word32 state; + + word16 skipDefaultSignedAttribs:1; /* skip adding default signed attribs */ + + byte version; /* 1 for RFC 2315 and 3 for RFC 4108 */ + PKCS7SignerInfo* signerInfo; + CallbackDecryptContent decryptionCb; + CallbackWrapCEK wrapCEKCb; + void* decryptionCtx; + + byte* signature; + byte* plainDigest; + byte* pkcs7Digest; + word32 signatureSz; + word32 plainDigestSz; + word32 pkcs7DigestSz; + /* !! NEW DATA MEMBERS MUST BE ADDED AT END !! */ +}; + + +WOLFSSL_API PKCS7* wc_PKCS7_New(void* heap, int devId); +WOLFSSL_API int wc_PKCS7_Init(PKCS7* pkcs7, void* heap, int devId); +WOLFSSL_API int wc_PKCS7_InitWithCert(PKCS7* pkcs7, byte* der, word32 derSz); +WOLFSSL_API int wc_PKCS7_AddCertificate(PKCS7* pkcs7, byte* der, word32 derSz); +WOLFSSL_API void wc_PKCS7_Free(PKCS7* pkcs7); + +WOLFSSL_API int wc_PKCS7_GetAttributeValue(PKCS7* pkcs7, const byte* oid, + word32 oidSz, byte* out, word32* outSz); + +WOLFSSL_API int wc_PKCS7_SetSignerIdentifierType(PKCS7* pkcs7, int type); +WOLFSSL_API int wc_PKCS7_SetContentType(PKCS7* pkcs7, byte* contentType, + word32 sz); +WOLFSSL_API int wc_PKCS7_GetPadSize(word32 inputSz, word32 blockSz); +WOLFSSL_API int wc_PKCS7_PadData(byte* in, word32 inSz, byte* out, word32 outSz, + word32 blockSz); + +/* CMS/PKCS#7 Data */ +WOLFSSL_API int wc_PKCS7_EncodeData(PKCS7* pkcs7, byte* output, + word32 outputSz); + +/* CMS/PKCS#7 SignedData */ +WOLFSSL_API int wc_PKCS7_SetDetached(PKCS7* pkcs7, word16 flag); +WOLFSSL_API int wc_PKCS7_NoDefaultSignedAttribs(PKCS7* pkcs7); +WOLFSSL_API int wc_PKCS7_EncodeSignedData(PKCS7* pkcs7, + byte* output, word32 outputSz); +WOLFSSL_API int wc_PKCS7_EncodeSignedData_ex(PKCS7* pkcs7, const byte* hashBuf, + word32 hashSz, byte* outputHead, + word32* outputHeadSz, + byte* outputFoot, + word32* outputFootSz); +WOLFSSL_API void wc_PKCS7_AllowDegenerate(PKCS7* pkcs7, word16 flag); +WOLFSSL_API int wc_PKCS7_VerifySignedData(PKCS7* pkcs7, + byte* pkiMsg, word32 pkiMsgSz); +WOLFSSL_API int wc_PKCS7_VerifySignedData_ex(PKCS7* pkcs7, const byte* hashBuf, + word32 hashSz, byte* pkiMsgHead, + word32 pkiMsgHeadSz, byte* pkiMsgFoot, + word32 pkiMsgFootSz); + +WOLFSSL_API int wc_PKCS7_GetSignerSID(PKCS7* pkcs7, byte* out, word32* outSz); + +/* CMS single-shot API for Signed FirmwarePkgData */ +WOLFSSL_API int wc_PKCS7_EncodeSignedFPD(PKCS7* pkcs7, byte* privateKey, + word32 privateKeySz, int signOID, + int hashOID, byte* content, + word32 contentSz, + PKCS7Attrib* signedAttribs, + word32 signedAttribsSz, byte* output, + word32 outputSz); +#ifndef NO_PKCS7_ENCRYPTED_DATA +/* CMS single-shot API for Signed Encrypted FirmwarePkgData */ +WOLFSSL_API int wc_PKCS7_EncodeSignedEncryptedFPD(PKCS7* pkcs7, + byte* encryptKey, word32 encryptKeySz, + byte* privateKey, word32 privateKeySz, + int encryptOID, int signOID, + int hashOID, byte* content, + word32 contentSz, + PKCS7Attrib* unprotectedAttribs, + word32 unprotectedAttribsSz, + PKCS7Attrib* signedAttribs, + word32 signedAttribsSz, + byte* output, word32 outputSz); +#endif /* NO_PKCS7_ENCRYPTED_DATA */ +#if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA) +/* CMS single-shot API for Signed Compressed FirmwarePkgData */ +WOLFSSL_API int wc_PKCS7_EncodeSignedCompressedFPD(PKCS7* pkcs7, + byte* privateKey, word32 privateKeySz, + int signOID, int hashOID, + byte* content, word32 contentSz, + PKCS7Attrib* signedAttribs, + word32 signedAttribsSz, byte* output, + word32 outputSz); + +#ifndef NO_PKCS7_ENCRYPTED_DATA +/* CMS single-shot API for Signed Encrypted Compressed FirmwarePkgData */ +WOLFSSL_API int wc_PKCS7_EncodeSignedEncryptedCompressedFPD(PKCS7* pkcs7, + byte* encryptKey, word32 encryptKeySz, + byte* privateKey, word32 privateKeySz, + int encryptOID, int signOID, + int hashOID, byte* content, + word32 contentSz, + PKCS7Attrib* unprotectedAttribs, + word32 unprotectedAttribsSz, + PKCS7Attrib* signedAttribs, + word32 signedAttribsSz, + byte* output, word32 outputSz); +#endif /* !NO_PKCS7_ENCRYPTED_DATA */ +#endif /* HAVE_LIBZ && !NO_PKCS7_COMPRESSED_DATA */ + +/* EnvelopedData and AuthEnvelopedData RecipientInfo functions */ +WOLFSSL_API int wc_PKCS7_AddRecipient_KTRI(PKCS7* pkcs7, const byte* cert, + word32 certSz, int options); +WOLFSSL_API int wc_PKCS7_AddRecipient_KARI(PKCS7* pkcs7, const byte* cert, + word32 certSz, int keyWrapOID, + int keyAgreeOID, byte* ukm, + word32 ukmSz, int options); + +WOLFSSL_API int wc_PKCS7_SetKey(PKCS7* pkcs7, byte* key, word32 keySz); +WOLFSSL_API int wc_PKCS7_AddRecipient_KEKRI(PKCS7* pkcs7, int keyWrapOID, + byte* kek, word32 kekSz, + byte* keyID, word32 keyIdSz, + void* timePtr, byte* otherOID, + word32 otherOIDSz, byte* other, + word32 otherSz, int options); + +WOLFSSL_API int wc_PKCS7_SetPassword(PKCS7* pkcs7, byte* passwd, word32 pLen); +WOLFSSL_API int wc_PKCS7_AddRecipient_PWRI(PKCS7* pkcs7, byte* passwd, + word32 pLen, byte* salt, + word32 saltSz, int kdfOID, + int prfOID, int iterations, + int kekEncryptOID, int options); +WOLFSSL_API int wc_PKCS7_SetOriEncryptCtx(PKCS7* pkcs7, void* ctx); +WOLFSSL_API int wc_PKCS7_SetOriDecryptCtx(PKCS7* pkcs7, void* ctx); +WOLFSSL_API int wc_PKCS7_SetOriDecryptCb(PKCS7* pkcs7, CallbackOriDecrypt cb); +WOLFSSL_API int wc_PKCS7_AddRecipient_ORI(PKCS7* pkcs7, CallbackOriEncrypt cb, + int options); +WOLFSSL_API int wc_PKCS7_SetWrapCEKCb(PKCS7* pkcs7, + CallbackWrapCEK wrapCEKCb); + +/* CMS/PKCS#7 EnvelopedData */ +WOLFSSL_API int wc_PKCS7_EncodeEnvelopedData(PKCS7* pkcs7, + byte* output, word32 outputSz); +WOLFSSL_API int wc_PKCS7_DecodeEnvelopedData(PKCS7* pkcs7, byte* pkiMsg, + word32 pkiMsgSz, byte* output, + word32 outputSz); + +/* CMS/PKCS#7 AuthEnvelopedData */ +WOLFSSL_API int wc_PKCS7_EncodeAuthEnvelopedData(PKCS7* pkcs7, + byte* output, word32 outputSz); +WOLFSSL_API int wc_PKCS7_DecodeAuthEnvelopedData(PKCS7* pkcs7, byte* pkiMsg, + word32 pkiMsgSz, byte* output, + word32 outputSz); + +/* CMS/PKCS#7 EncryptedData */ +#ifndef NO_PKCS7_ENCRYPTED_DATA +WOLFSSL_API int wc_PKCS7_EncodeEncryptedData(PKCS7* pkcs7, + byte* output, word32 outputSz); +WOLFSSL_API int wc_PKCS7_DecodeEncryptedData(PKCS7* pkcs7, byte* pkiMsg, + word32 pkiMsgSz, byte* output, + word32 outputSz); +WOLFSSL_API int wc_PKCS7_SetDecodeEncryptedCb(PKCS7* pkcs7, + CallbackDecryptContent decryptionCb); +WOLFSSL_API int wc_PKCS7_SetDecodeEncryptedCtx(PKCS7* pkcs7, void* ctx); +#endif /* NO_PKCS7_ENCRYPTED_DATA */ + +/* CMS/PKCS#7 CompressedData */ +#if defined(HAVE_LIBZ) && !defined(NO_PKCS7_COMPRESSED_DATA) +WOLFSSL_API int wc_PKCS7_EncodeCompressedData(PKCS7* pkcs7, byte* output, + word32 outputSz); +WOLFSSL_API int wc_PKCS7_DecodeCompressedData(PKCS7* pkcs7, byte* pkiMsg, + word32 pkiMsgSz, byte* output, + word32 outputSz); +#endif /* HAVE_LIBZ && !NO_PKCS7_COMPRESSED_DATA */ + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* HAVE_PKCS7 */ +#endif /* WOLF_CRYPT_PKCS7_H */ + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/poly1305.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/poly1305.h new file mode 100755 index 0000000..0f81ca0 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/poly1305.h @@ -0,0 +1,127 @@ +/* poly1305.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/*! + \file wolfssl/wolfcrypt/poly1305.h +*/ + +#ifndef WOLF_CRYPT_POLY1305_H +#define WOLF_CRYPT_POLY1305_H + +#include + +#ifdef HAVE_POLY1305 + +#ifdef __cplusplus + extern "C" { +#endif + +/* auto detect between 32bit / 64bit */ +#if defined(__SIZEOF_INT128__) && defined(__LP64__) +#define WC_HAS_SIZEOF_INT128_64BIT +#endif + +#if defined(_MSC_VER) && defined(_M_X64) +#define WC_HAS_MSVC_64BIT +#endif + +#if (defined(__GNUC__) && defined(__LP64__) && \ + ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)))) +#define WC_HAS_GCC_4_4_64BIT +#endif + +#ifdef USE_INTEL_SPEEDUP +#elif (defined(WC_HAS_SIZEOF_INT128_64BIT) || defined(WC_HAS_MSVC_64BIT) || \ + defined(WC_HAS_GCC_4_4_64BIT)) +#define POLY130564 +#else +#define POLY130532 +#endif + +enum { + POLY1305 = 7, + POLY1305_BLOCK_SIZE = 16, + POLY1305_DIGEST_SIZE = 16, +}; + +#define WC_POLY1305_PAD_SZ 16 +#define WC_POLY1305_MAC_SZ 16 + +/* Poly1305 state */ +typedef struct Poly1305 { +#ifdef USE_INTEL_SPEEDUP + word64 r[3]; + word64 h[3]; + word64 pad[2]; + word64 hh[20]; + word32 r1[8]; + word32 r2[8]; + word32 r3[8]; + word32 r4[8]; + word64 hm[16]; + unsigned char buffer[8*POLY1305_BLOCK_SIZE]; + size_t leftover; + unsigned char finished; + unsigned char started; +#else +#if defined(WOLFSSL_ARMASM) && defined(__aarch64__) + ALIGN128 word32 r[5]; + ALIGN128 word32 r_2[5]; // r^2 + ALIGN128 word32 r_4[5]; // r^4 + ALIGN128 word32 h[5]; + word32 pad[4]; + word64 leftover; +#else +#if defined(POLY130564) + word64 r[3]; + word64 h[3]; + word64 pad[2]; +#else + word32 r[5]; + word32 h[5]; + word32 pad[4]; +#endif + size_t leftover; +#endif /* WOLFSSL_ARMASM */ + unsigned char buffer[POLY1305_BLOCK_SIZE]; + unsigned char finished; +#endif +} Poly1305; + +/* does init */ + +WOLFSSL_API int wc_Poly1305SetKey(Poly1305* poly1305, const byte* key, + word32 kySz); +WOLFSSL_API int wc_Poly1305Update(Poly1305* poly1305, const byte*, word32); +WOLFSSL_API int wc_Poly1305Final(Poly1305* poly1305, byte* tag); +WOLFSSL_API int wc_Poly1305_MAC(Poly1305* ctx, byte* additional, word32 addSz, + byte* input, word32 sz, byte* tag, word32 tagSz); + +void poly1305_block(Poly1305* ctx, const unsigned char *m); +void poly1305_blocks(Poly1305* ctx, const unsigned char *m, + size_t bytes); +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* HAVE_POLY1305 */ +#endif /* WOLF_CRYPT_POLY1305_H */ + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/pwdbased.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/pwdbased.h new file mode 100755 index 0000000..61de8f1 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/pwdbased.h @@ -0,0 +1,71 @@ +/* pwdbased.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/*! + \file wolfssl/wolfcrypt/pwdbased.h +*/ + +#ifndef WOLF_CRYPT_PWDBASED_H +#define WOLF_CRYPT_PWDBASED_H + +#include + +#ifndef NO_PWDBASED + + +#ifdef __cplusplus + extern "C" { +#endif + +/* + * hashType renamed to typeH to avoid shadowing global declaration here: + * wolfssl/wolfcrypt/asn.h line 173 in enum Oid_Types + */ +WOLFSSL_API int wc_PBKDF1_ex(byte* key, int keyLen, byte* iv, int ivLen, + const byte* passwd, int passwdLen, + const byte* salt, int saltLen, int iterations, + int hashType, void* heap); +WOLFSSL_API int wc_PBKDF1(byte* output, const byte* passwd, int pLen, + const byte* salt, int sLen, int iterations, int kLen, + int typeH); +WOLFSSL_API int wc_PBKDF2(byte* output, const byte* passwd, int pLen, + const byte* salt, int sLen, int iterations, int kLen, + int typeH); +WOLFSSL_API int wc_PKCS12_PBKDF(byte* output, const byte* passwd, int pLen, + const byte* salt, int sLen, int iterations, + int kLen, int typeH, int purpose); +WOLFSSL_API int wc_PKCS12_PBKDF_ex(byte* output, const byte* passwd,int passLen, + const byte* salt, int saltLen, int iterations, int kLen, + int hashType, int id, void* heap); + +#ifdef HAVE_SCRYPT +WOLFSSL_API int wc_scrypt(byte* output, const byte* passwd, int passLen, + const byte* salt, int saltLen, int cost, + int blockSize, int parallel, int dkLen); +#endif + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* NO_PWDBASED */ +#endif /* WOLF_CRYPT_PWDBASED_H */ diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/rabbit.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/rabbit.h new file mode 100755 index 0000000..0064c45 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/rabbit.h @@ -0,0 +1,73 @@ +/* rabbit.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/*! + \file wolfssl/wolfcrypt/rabbit.h +*/ + + +#ifndef WOLF_CRYPT_RABBIT_H +#define WOLF_CRYPT_RABBIT_H + +#include + +#ifndef NO_RABBIT + +#ifdef __cplusplus + extern "C" { +#endif + + +enum { + RABBIT_ENC_TYPE = 5 /* cipher unique type */ +}; + + +/* Rabbit Context */ +typedef struct RabbitCtx { + word32 x[8]; + word32 c[8]; + word32 carry; +} RabbitCtx; + + +/* Rabbit stream cipher */ +typedef struct Rabbit { + RabbitCtx masterCtx; + RabbitCtx workCtx; +#ifdef XSTREAM_ALIGN + void* heap; /* heap hint, currently XMALLOC only used with aligning */ +#endif +} Rabbit; + + +WOLFSSL_API int wc_RabbitProcess(Rabbit*, byte*, const byte*, word32); +WOLFSSL_API int wc_RabbitSetKey(Rabbit*, const byte* key, const byte* iv); + +WOLFSSL_LOCAL int wc_Rabbit_SetHeap(Rabbit* ctx, void* heap); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* NO_RABBIT */ +#endif /* WOLF_CRYPT_RABBIT_H */ + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/random.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/random.h new file mode 100755 index 0000000..2f678db --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/random.h @@ -0,0 +1,254 @@ +/* random.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/*! + \file wolfssl/wolfcrypt/random.h +*/ + + + +#ifndef WOLF_CRYPT_RANDOM_H +#define WOLF_CRYPT_RANDOM_H + +#include + +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + #include +#endif /* HAVE_FIPS_VERSION >= 2 */ + +/* included for fips @wc_fips */ +#if defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) +#include +#endif + +#ifdef __cplusplus + extern "C" { +#endif + + /* Maximum generate block length */ +#ifndef RNG_MAX_BLOCK_LEN + #ifdef HAVE_INTEL_QA + #define RNG_MAX_BLOCK_LEN (0xFFFFl) + #else + #define RNG_MAX_BLOCK_LEN (0x10000l) + #endif +#endif + +/* Size of the BRBG seed */ +#ifndef DRBG_SEED_LEN + #define DRBG_SEED_LEN (440/8) +#endif + + +#if !defined(CUSTOM_RAND_TYPE) + /* To maintain compatibility the default is byte */ + #define CUSTOM_RAND_TYPE byte +#endif + +/* make sure Hash DRBG is enabled, unless WC_NO_HASHDRBG is defined + or CUSTOM_RAND_GENERATE_BLOCK is defined */ +#if !defined(WC_NO_HASHDRBG) && !defined(CUSTOM_RAND_GENERATE_BLOCK) + #undef HAVE_HASHDRBG + #define HAVE_HASHDRBG + #ifndef WC_RESEED_INTERVAL + #define WC_RESEED_INTERVAL (1000000) + #endif +#endif + + +/* avoid redefinition of structs */ +#if !defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) + +/* RNG supports the following sources (in order): + * 1. CUSTOM_RAND_GENERATE_BLOCK: Defines name of function as RNG source and + * bypasses the options below. + * 2. HAVE_INTEL_RDRAND: Uses the Intel RDRAND if supported by CPU. + * 3. HAVE_HASHDRBG (requires SHA256 enabled): Uses SHA256 based P-RNG + * seeded via wc_GenerateSeed. This is the default source. + */ + + /* Seed source can be overridden by defining one of these: + CUSTOM_RAND_GENERATE_SEED + CUSTOM_RAND_GENERATE_SEED_OS + CUSTOM_RAND_GENERATE */ + +int os_get_random(unsigned char *buf, size_t sz); +int hw_get_random(unsigned char *buf, size_t len); + +static inline int __hw_get_random(uint8_t* buf, size_t len) { + return os_get_random(buf, len); +} + +#define CUSTOM_RAND_GENERATE_BLOCK __hw_get_random + + +#if defined(CUSTOM_RAND_GENERATE_BLOCK) + /* To use define the following: + * #define CUSTOM_RAND_GENERATE_BLOCK myRngFunc + * extern int myRngFunc(byte* output, word32 sz); + */ +#elif defined(HAVE_HASHDRBG) + #ifdef NO_SHA256 + #error "Hash DRBG requires SHA-256." + #endif /* NO_SHA256 */ + #include +#elif defined(HAVE_WNR) + /* allow whitewood as direct RNG source using wc_GenerateSeed directly */ +#elif defined(HAVE_INTEL_RDRAND) + /* Intel RDRAND or RDSEED */ +#elif !defined(WC_NO_RNG) + #error No RNG source defined! +#endif + +#ifdef HAVE_WNR + #include +#endif + +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif + + +#if defined(USE_WINDOWS_API) + #if defined(_WIN64) + typedef unsigned __int64 ProviderHandle; + /* type HCRYPTPROV, avoid #include */ + #else + typedef unsigned long ProviderHandle; + #endif +#endif + + +/* OS specific seeder */ +typedef struct OS_Seed { + #if defined(USE_WINDOWS_API) + ProviderHandle handle; + #else + int fd; + #endif + #if defined(WOLF_CRYPTO_CB) + int devId; + #endif +} OS_Seed; + + +#ifndef WC_RNG_TYPE_DEFINED /* guard on redeclaration */ + typedef struct WC_RNG WC_RNG; + #define WC_RNG_TYPE_DEFINED +#endif + +/* RNG context */ +struct WC_RNG { + OS_Seed seed; + void* heap; +#ifdef HAVE_HASHDRBG + /* Hash-based Deterministic Random Bit Generator */ + struct DRBG* drbg; +#if defined(WOLFSSL_NO_MALLOC) && !defined(WOLFSSL_STATIC_MEMORY) + #define DRBG_STRUCT_SZ ((sizeof(word32)*3) + (DRBG_SEED_LEN*2)) + #ifdef WOLFSSL_SMALL_STACK_CACHE + #define DRBG_STRUCT_SZ_SHA256 (sizeof(wc_Sha256)) + #else + #define DRBG_STRUCT_SZ_SHA256 0 + #endif + #if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB) + #define DRBG_STRUCT_SZ_ASYNC (sizeof(void*) + sizeof(int)) + #else + #define DRBG_STRUCT_SZ_ASYNC 0 + #endif + byte drbg_data[DRBG_STRUCT_SZ + DRBG_STRUCT_SZ_SHA256 + DRBG_STRUCT_SZ_ASYNC]; +#endif + byte status; +#endif +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV asyncDev; +#endif +#if defined(WOLFSSL_ASYNC_CRYPT) || defined(WOLF_CRYPTO_CB) + int devId; +#endif +}; + +#endif /* NO FIPS or have FIPS v2*/ + +/* NO_OLD_RNGNAME removes RNG struct name to prevent possible type conflicts, + * can't be used with CTaoCrypt FIPS */ +#if !defined(NO_OLD_RNGNAME) && !defined(HAVE_FIPS) + #define RNG WC_RNG +#endif + + +WOLFSSL_LOCAL +int wc_GenerateSeed(OS_Seed* os, byte* seed, word32 sz); + + +#ifdef HAVE_WNR + /* Whitewood netRandom client library */ + WOLFSSL_API int wc_InitNetRandom(const char*, wnr_hmac_key, int); + WOLFSSL_API int wc_FreeNetRandom(void); +#endif /* HAVE_WNR */ + +#ifndef WC_NO_RNG +WOLFSSL_API int wc_InitRng(WC_RNG*); +WOLFSSL_API int wc_InitRng_ex(WC_RNG* rng, void* heap, int devId); +WOLFSSL_API int wc_InitRngNonce(WC_RNG* rng, byte* nonce, word32 nonceSz); +WOLFSSL_API int wc_InitRngNonce_ex(WC_RNG* rng, byte* nonce, word32 nonceSz, + void* heap, int devId); +WOLFSSL_API int wc_RNG_GenerateBlock(WC_RNG*, byte*, word32 sz); +WOLFSSL_API int wc_RNG_GenerateByte(WC_RNG*, byte*); +WOLFSSL_API int wc_FreeRng(WC_RNG*); +#else +#include +#define wc_InitRng(rng) NOT_COMPILED_IN +#define wc_InitRng_ex(rng, h, d) NOT_COMPILED_IN +#define wc_InitRngNonce(rng, n, s) NOT_COMPILED_IN +#define wc_InitRngNonce_ex(rng, n, s, h, d) NOT_COMPILED_IN +#define wc_RNG_GenerateBlock(rng, b, s) NOT_COMPILED_IN +#define wc_RNG_GenerateByte(rng, b) NOT_COMPILED_IN +#define wc_FreeRng(rng) (void)NOT_COMPILED_IN +#endif + + + +#ifdef HAVE_HASHDRBG + WOLFSSL_LOCAL int wc_RNG_DRBG_Reseed(WC_RNG* rng, const byte* entropy, + word32 entropySz); + WOLFSSL_API int wc_RNG_TestSeed(const byte* seed, word32 seedSz); + WOLFSSL_API int wc_RNG_HealthTest(int reseed, + const byte* entropyA, word32 entropyASz, + const byte* entropyB, word32 entropyBSz, + byte* output, word32 outputSz); + WOLFSSL_API int wc_RNG_HealthTest_ex(int reseed, + const byte* nonce, word32 nonceSz, + const byte* entropyA, word32 entropyASz, + const byte* entropyB, word32 entropyBSz, + byte* output, word32 outputSz, + void* heap, int devId); +#endif /* HAVE_HASHDRBG */ + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLF_CRYPT_RANDOM_H */ + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/ripemd.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/ripemd.h new file mode 100755 index 0000000..cc9f130 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/ripemd.h @@ -0,0 +1,67 @@ +/* ripemd.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/*! + \file wolfssl/wolfcrypt/ripemd.h +*/ + +#ifndef WOLF_CRYPT_RIPEMD_H +#define WOLF_CRYPT_RIPEMD_H + +#include + +#ifdef WOLFSSL_RIPEMD + +#ifdef __cplusplus + extern "C" { +#endif + + +/* in bytes */ +enum { + RIPEMD = 3, /* hash type unique */ + RIPEMD_BLOCK_SIZE = 64, + RIPEMD_DIGEST_SIZE = 20, + RIPEMD_PAD_SIZE = 56 +}; + + +/* RipeMd 160 digest */ +typedef struct RipeMd { + word32 buffLen; /* in bytes */ + word32 loLen; /* length in bytes */ + word32 hiLen; /* length in bytes */ + word32 digest[RIPEMD_DIGEST_SIZE / sizeof(word32)]; + word32 buffer[RIPEMD_BLOCK_SIZE / sizeof(word32)]; +} RipeMd; + + +WOLFSSL_API int wc_InitRipeMd(RipeMd*); +WOLFSSL_API int wc_RipeMdUpdate(RipeMd*, const byte*, word32); +WOLFSSL_API int wc_RipeMdFinal(RipeMd*, byte*); + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLFSSL_RIPEMD */ +#endif /* WOLF_CRYPT_RIPEMD_H */ diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/rsa.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/rsa.h new file mode 100755 index 0000000..28a2e9b --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/rsa.h @@ -0,0 +1,356 @@ +/* rsa.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/*! + \file wolfssl/wolfcrypt/rsa.h +*/ + + +#ifndef WOLF_CRYPT_RSA_H +#define WOLF_CRYPT_RSA_H + +#include + +#ifndef NO_RSA + + +/* RSA default exponent */ +#ifndef WC_RSA_EXPONENT + #define WC_RSA_EXPONENT 65537L +#endif + +#if defined(WC_RSA_NONBLOCK) + /* enable support for fast math based non-blocking exptmod */ + /* this splits the RSA function into many smaller operations */ + #ifndef USE_FAST_MATH + #error RSA non-blocking mode only supported using fast math + #endif + #ifndef TFM_TIMING_RESISTANT + #error RSA non-blocking mode only supported with timing resistance enabled + #endif + + /* RSA bounds check is not supported with RSA non-blocking mode */ + #undef NO_RSA_BOUNDS_CHECK + #define NO_RSA_BOUNDS_CHECK +#endif + +/* allow for user to plug in own crypto */ +#if !defined(HAVE_FIPS) && (defined(HAVE_USER_RSA) || defined(HAVE_FAST_RSA)) + #include "user_rsa.h" +#else + +#if defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) +/* for fips @wc_fips */ +#include +#if defined(CYASSL_KEY_GEN) && !defined(WOLFSSL_KEY_GEN) + #define WOLFSSL_KEY_GEN +#endif +#else + #include + #include +#endif /* HAVE_FIPS && HAVE_FIPS_VERION 1 */ +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) +#include +#endif + +/* header file needed for OAEP padding */ +#include + +#ifdef WOLFSSL_XILINX_CRYPT +#include "xsecure_rsa.h" +#endif + +#if defined(WOLFSSL_CRYPTOCELL) + #include +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +enum { + RSA_MIN_SIZE = 512, + RSA_MAX_SIZE = 4096, +}; + +/* avoid redefinition of structs */ +#if !defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) + +#ifdef WOLFSSL_ASYNC_CRYPT + #include + #ifdef WOLFSSL_CERT_GEN + #include + #endif +#endif + +enum { + RSA_PUBLIC = 0, + RSA_PRIVATE = 1, + + RSA_TYPE_UNKNOWN = -1, + RSA_PUBLIC_ENCRYPT = 0, + RSA_PUBLIC_DECRYPT = 1, + RSA_PRIVATE_ENCRYPT = 2, + RSA_PRIVATE_DECRYPT = 3, + + RSA_BLOCK_TYPE_1 = 1, + RSA_BLOCK_TYPE_2 = 2, + + RSA_MIN_PAD_SZ = 11, /* separator + 0 + pad value + 8 pads */ + + RSA_PSS_PAD_SZ = 8, + RSA_PSS_SALT_MAX_SZ = 62, + +#ifdef OPENSSL_EXTRA + RSA_PKCS1_PADDING_SIZE = 11, + RSA_PKCS1_OAEP_PADDING_SIZE = 42, /* (2 * hashlen(SHA-1)) + 2 */ +#endif +#ifdef WC_RSA_PSS + RSA_PSS_PAD_TERM = 0xBC, +#endif + +#ifdef HAVE_PKCS11 + RSA_MAX_ID_LEN = 32, +#endif +}; + +#ifdef WC_RSA_NONBLOCK +typedef struct RsaNb { + exptModNb_t exptmod; /* non-block expt_mod */ + mp_int tmp; +} RsaNb; +#endif + +/* RSA */ +struct RsaKey { + mp_int n, e; +#ifndef WOLFSSL_RSA_PUBLIC_ONLY + mp_int d, p, q; +#if defined(WOLFSSL_KEY_GEN) || defined(OPENSSL_EXTRA) || !defined(RSA_LOW_MEM) + mp_int dP, dQ, u; +#endif +#endif + void* heap; /* for user memory overrides */ + byte* data; /* temp buffer for async RSA */ + int type; /* public or private */ + int state; + word32 dataLen; +#ifdef WC_RSA_BLINDING + WC_RNG* rng; /* for PrivateDecrypt blinding */ +#endif +#ifdef WOLF_CRYPTO_CB + int devId; +#endif +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV asyncDev; + #ifdef WOLFSSL_CERT_GEN + CertSignCtx certSignCtx; /* context info for cert sign (MakeSignature) */ + #endif +#endif /* WOLFSSL_ASYNC_CRYPT */ +#ifdef WOLFSSL_XILINX_CRYPT + word32 pubExp; /* to keep values in scope they are here in struct */ + byte* mod; + XSecure_Rsa xRsa; +#endif +#ifdef HAVE_PKCS11 + byte id[RSA_MAX_ID_LEN]; + int idLen; +#endif +#if defined(WOLFSSL_ASYNC_CRYPT) || !defined(WOLFSSL_RSA_VERIFY_INLINE) + byte dataIsAlloc; +#endif +#ifdef WC_RSA_NONBLOCK + RsaNb* nb; +#endif +#ifdef WOLFSSL_AFALG_XILINX_RSA + int alFd; + int rdFd; +#endif +#if defined(WOLFSSL_CRYPTOCELL) + rsa_context_t ctx; +#endif +}; + +#ifndef WC_RSAKEY_TYPE_DEFINED + typedef struct RsaKey RsaKey; + #define WC_RSAKEY_TYPE_DEFINED +#endif + +#endif /*HAVE_FIPS */ + +WOLFSSL_API int wc_InitRsaKey(RsaKey* key, void* heap); +WOLFSSL_API int wc_InitRsaKey_ex(RsaKey* key, void* heap, int devId); +WOLFSSL_API int wc_FreeRsaKey(RsaKey* key); +#ifdef HAVE_PKCS11 +WOLFSSL_API int wc_InitRsaKey_Id(RsaKey* key, unsigned char* id, int len, + void* heap, int devId); +#endif +WOLFSSL_API int wc_CheckRsaKey(RsaKey* key); +#ifdef WOLFSSL_XILINX_CRYPT +WOLFSSL_LOCAL int wc_InitRsaHw(RsaKey* key); +#endif /* WOLFSSL_XILINX_CRYPT */ + +WOLFSSL_API int wc_RsaFunction(const byte* in, word32 inLen, byte* out, + word32* outLen, int type, RsaKey* key, WC_RNG* rng); + +WOLFSSL_API int wc_RsaPublicEncrypt(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key, WC_RNG* rng); +WOLFSSL_API int wc_RsaPrivateDecryptInline(byte* in, word32 inLen, byte** out, + RsaKey* key); +WOLFSSL_API int wc_RsaPrivateDecrypt(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key); +WOLFSSL_API int wc_RsaSSL_Sign(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key, WC_RNG* rng); +WOLFSSL_API int wc_RsaPSS_Sign(const byte* in, word32 inLen, byte* out, + word32 outLen, enum wc_HashType hash, int mgf, + RsaKey* key, WC_RNG* rng); +WOLFSSL_API int wc_RsaPSS_Sign_ex(const byte* in, word32 inLen, byte* out, + word32 outLen, enum wc_HashType hash, + int mgf, int saltLen, RsaKey* key, + WC_RNG* rng); +WOLFSSL_API int wc_RsaSSL_VerifyInline(byte* in, word32 inLen, byte** out, + RsaKey* key); +WOLFSSL_API int wc_RsaSSL_Verify(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key); +WOLFSSL_API int wc_RsaPSS_VerifyInline(byte* in, word32 inLen, byte** out, + enum wc_HashType hash, int mgf, + RsaKey* key); +WOLFSSL_API int wc_RsaPSS_VerifyInline_ex(byte* in, word32 inLen, byte** out, + enum wc_HashType hash, int mgf, + int saltLen, RsaKey* key); +WOLFSSL_API int wc_RsaPSS_Verify(byte* in, word32 inLen, byte* out, + word32 outLen, enum wc_HashType hash, int mgf, + RsaKey* key); +WOLFSSL_API int wc_RsaPSS_Verify_ex(byte* in, word32 inLen, byte* out, + word32 outLen, enum wc_HashType hash, + int mgf, int saltLen, RsaKey* key); +WOLFSSL_API int wc_RsaPSS_CheckPadding(const byte* in, word32 inLen, byte* sig, + word32 sigSz, + enum wc_HashType hashType); +WOLFSSL_API int wc_RsaPSS_CheckPadding_ex(const byte* in, word32 inLen, + byte* sig, word32 sigSz, + enum wc_HashType hashType, + int saltLen, int bits); +WOLFSSL_API int wc_RsaPSS_VerifyCheckInline(byte* in, word32 inLen, byte** out, + const byte* digest, word32 digentLen, + enum wc_HashType hash, int mgf, + RsaKey* key); +WOLFSSL_API int wc_RsaPSS_VerifyCheck(byte* in, word32 inLen, + byte* out, word32 outLen, + const byte* digest, word32 digestLen, + enum wc_HashType hash, int mgf, + RsaKey* key); + +WOLFSSL_API int wc_RsaEncryptSize(RsaKey* key); + +#if !defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) +/* to avoid asn duplicate symbols @wc_fips */ +WOLFSSL_API int wc_RsaPrivateKeyDecode(const byte* input, word32* inOutIdx, + RsaKey*, word32); +WOLFSSL_API int wc_RsaPublicKeyDecode(const byte* input, word32* inOutIdx, + RsaKey*, word32); +WOLFSSL_API int wc_RsaPublicKeyDecodeRaw(const byte* n, word32 nSz, + const byte* e, word32 eSz, RsaKey* key); +#ifdef WOLFSSL_KEY_GEN + WOLFSSL_API int wc_RsaKeyToDer(RsaKey*, byte* output, word32 inLen); +#endif + +#ifdef WC_RSA_BLINDING + WOLFSSL_API int wc_RsaSetRNG(RsaKey* key, WC_RNG* rng); +#endif +#ifdef WC_RSA_NONBLOCK + WOLFSSL_API int wc_RsaSetNonBlock(RsaKey* key, RsaNb* nb); + #ifdef WC_RSA_NONBLOCK_TIME + WOLFSSL_API int wc_RsaSetNonBlockTime(RsaKey* key, word32 maxBlockUs, + word32 cpuMHz); + #endif +#endif + +/* + choice of padding added after fips, so not available when using fips RSA + */ + +/* Mask Generation Function Identifiers */ +#define WC_MGF1NONE 0 +#define WC_MGF1SHA1 26 +#define WC_MGF1SHA224 4 +#define WC_MGF1SHA256 1 +#define WC_MGF1SHA384 2 +#define WC_MGF1SHA512 3 + +/* Padding types */ +#define WC_RSA_PKCSV15_PAD 0 +#define WC_RSA_OAEP_PAD 1 +#define WC_RSA_PSS_PAD 2 +#define WC_RSA_NO_PAD 3 + +WOLFSSL_API int wc_RsaPublicEncrypt_ex(const byte* in, word32 inLen, byte* out, + word32 outLen, RsaKey* key, WC_RNG* rng, int type, + enum wc_HashType hash, int mgf, byte* label, word32 lableSz); +WOLFSSL_API int wc_RsaPrivateDecrypt_ex(const byte* in, word32 inLen, + byte* out, word32 outLen, RsaKey* key, int type, + enum wc_HashType hash, int mgf, byte* label, word32 lableSz); +WOLFSSL_API int wc_RsaPrivateDecryptInline_ex(byte* in, word32 inLen, + byte** out, RsaKey* key, int type, enum wc_HashType hash, + int mgf, byte* label, word32 lableSz); +#if defined(WC_RSA_DIRECT) || defined(WC_RSA_NO_PADDING) +WOLFSSL_API int wc_RsaDirect(byte* in, word32 inLen, byte* out, word32* outSz, + RsaKey* key, int type, WC_RNG* rng); +#endif + +#endif /* HAVE_FIPS */ + +WOLFSSL_API int wc_RsaFlattenPublicKey(RsaKey*, byte*, word32*, byte*, + word32*); +WOLFSSL_API int wc_RsaExportKey(RsaKey* key, + byte* e, word32* eSz, + byte* n, word32* nSz, + byte* d, word32* dSz, + byte* p, word32* pSz, + byte* q, word32* qSz); + +WOLFSSL_API int wc_RsaKeyToPublicDer(RsaKey*, byte* output, word32 inLen); + +#ifdef WOLFSSL_KEY_GEN + WOLFSSL_API int wc_MakeRsaKey(RsaKey* key, int size, long e, WC_RNG* rng); + WOLFSSL_API int wc_CheckProbablePrime_ex(const byte* p, word32 pSz, + const byte* q, word32 qSz, + const byte* e, word32 eSz, + int nlen, int* isPrime, WC_RNG* rng); + WOLFSSL_API int wc_CheckProbablePrime(const byte* p, word32 pSz, + const byte* q, word32 qSz, + const byte* e, word32 eSz, + int nlen, int* isPrime); +#endif + +#endif /* HAVE_USER_RSA */ + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* NO_RSA */ +#endif /* WOLF_CRYPT_RSA_H */ + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/selftest.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/selftest.h new file mode 100755 index 0000000..364b297 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/selftest.h @@ -0,0 +1,45 @@ +/* selftest.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +#ifndef WOLFCRYPT_SELF_TEST_H +#define WOLFCRYPT_SELF_TEST_H + +#include + + +#ifdef __cplusplus + extern "C" { +#endif + +#ifdef HAVE_SELFTEST + /* wolfCrypt self test, runs CAVP KATs */ + WOLFSSL_API int wolfCrypt_SelfTest(void); +#endif + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLFCRYPT_SELF_TEST_H */ + + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/settings.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/settings.h new file mode 100755 index 0000000..c4988f2 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/settings.h @@ -0,0 +1,969 @@ +/* settings.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +/* Place OS specific preprocessor flags, defines, includes here, will be + included into every file because types.h includes it */ + + +#ifndef WOLF_CRYPT_SETTINGS_H +#define WOLF_CRYPT_SETTINGS_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Uncomment next line if using IPHONE */ +/* #define IPHONE */ + +/* Uncomment next line if using ThreadX */ +/* #define THREADX */ + +/* Uncomment next line if using Micrium uC/OS-III */ +/* #define MICRIUM */ + +/* Uncomment next line if using Deos RTOS*/ +/* #define WOLFSSL_DEOS*/ + +/* Uncomment next line if using Mbed */ +/* #define MBED */ + +/* Uncomment next line if using Microchip PIC32 ethernet starter kit */ +/* #define MICROCHIP_PIC32 */ + +/* Uncomment next line if using Microchip TCP/IP stack, version 5 */ +/* #define MICROCHIP_TCPIP_V5 */ + +/* Uncomment next line if using Microchip TCP/IP stack, version 6 or later */ +/* #define MICROCHIP_TCPIP */ + +/* Uncomment next line if using PIC32MZ Crypto Engine */ +/* #define WOLFSSL_MICROCHIP_PIC32MZ */ + +/* Uncomment next line if using FreeRTOS */ +/* #define FREERTOS */ + +/* Uncomment next line if using FreeRTOS+ TCP */ +/* #define FREERTOS_TCP */ + +/* Uncomment next line if using FreeRTOS Windows Simulator */ +/* #define FREERTOS_WINSIM */ + +/* Uncomment next line if using RTIP */ +/* #define EBSNET */ + +/* Uncomment next line if using lwip */ +/* #define WOLFSSL_LWIP */ + +/* Uncomment next line if building wolfSSL for a game console */ +/* #define WOLFSSL_GAME_BUILD */ + +/* Uncomment next line if building wolfSSL for LSR */ +/* #define WOLFSSL_LSR */ + +/* Uncomment next line if building for Freescale Classic MQX version 4.0 */ +/* #define FREESCALE_MQX_4_0 */ + +/* Uncomment next line if building for Freescale Classic MQX/RTCS/MFS */ +/* #define FREESCALE_MQX */ + +/* Uncomment next line if building for Freescale KSDK MQX/RTCS/MFS */ +/* #define FREESCALE_KSDK_MQX */ + +/* Uncomment next line if building for Freescale KSDK Bare Metal */ +/* #define FREESCALE_KSDK_BM */ + +/* Uncomment next line if building for Freescale KSDK FreeRTOS, */ +/* (old name FREESCALE_FREE_RTOS) */ +/* #define FREESCALE_KSDK_FREERTOS */ + +/* Uncomment next line if using STM32F2 */ +/* #define WOLFSSL_STM32F2 */ + +/* Uncomment next line if using STM32F4 */ +/* #define WOLFSSL_STM32F4 */ + +/* Uncomment next line if using STM32FL */ +/* #define WOLFSSL_STM32FL */ + +/* Uncomment next line if using STM32F7 */ +/* #define WOLFSSL_STM32F7 */ + +/* Uncomment next line if using QL SEP settings */ +/* #define WOLFSSL_QL */ + +/* Uncomment next line if building for EROAD */ +/* #define WOLFSSL_EROAD */ + +/* Uncomment next line if building for IAR EWARM */ +/* #define WOLFSSL_IAR_ARM */ + +/* Uncomment next line if building for Rowley CrossWorks ARM */ +/* #define WOLFSSL_ROWLEY_ARM */ + +/* Uncomment next line if using TI-RTOS settings */ +/* #define WOLFSSL_TIRTOS */ + +/* Uncomment next line if building with PicoTCP */ +/* #define WOLFSSL_PICOTCP */ + +/* Uncomment next line if building for PicoTCP demo bundle */ +/* #define WOLFSSL_PICOTCP_DEMO */ + +/* Uncomment next line if building for uITRON4 */ +/* #define WOLFSSL_uITRON4 */ + +/* Uncomment next line if building for uT-Kernel */ +/* #define WOLFSSL_uTKERNEL2 */ + +/* Uncomment next line if using Max Strength build */ +/* #define WOLFSSL_MAX_STRENGTH */ + +/* Uncomment next line if building for VxWorks */ +/* #define WOLFSSL_VXWORKS */ + +/* Uncomment next line if building for Nordic nRF5x platofrm */ +/* #define WOLFSSL_NRF5x */ + +/* Uncomment next line to enable deprecated less secure static DH suites */ +/* #define WOLFSSL_STATIC_DH */ + +/* Uncomment next line to enable deprecated less secure static RSA suites */ +/* #define WOLFSSL_STATIC_RSA */ + +/* Uncomment next line if building for ARDUINO */ +/* Uncomment both lines if building for ARDUINO on INTEL_GALILEO */ +/* #define WOLFSSL_ARDUINO */ +/* #define INTEL_GALILEO */ + +/* Uncomment next line to enable asynchronous crypto WC_PENDING_E */ +/* #define WOLFSSL_ASYNC_CRYPT */ + +/* Uncomment next line if building for uTasker */ +/* #define WOLFSSL_UTASKER */ + +/* Uncomment next line if building for embOS */ +/* #define WOLFSSL_EMBOS */ + +/* Uncomment next line if building for RIOT-OS */ +/* #define WOLFSSL_RIOT_OS */ + +/* Uncomment next line if building for using XILINX hardened crypto */ +/* #define WOLFSSL_XILINX_CRYPT */ + +/* Uncomment next line if building for using XILINX */ +/* #define WOLFSSL_XILINX */ + +/* Uncomment next line if building for WICED Studio. */ +/* #define WOLFSSL_WICED */ + +/* Uncomment next line if building for Nucleus 1.2 */ +/* #define WOLFSSL_NUCLEUS_1_2 */ + +/* Uncomment next line if building for using Apache mynewt */ +/* #define WOLFSSL_APACHE_MYNEWT */ + +/* Uncomment next line if building for using ESP-IDF */ +/* #define WOLFSSL_ESPIDF */ + +/* Uncomment next line if using Espressif ESP32-WROOM-32 */ +/* #define WOLFSSL_ESPWROOM32 */ + +/* Uncomment next line if using Espressif ESP32-WROOM-32SE */ +/* #define WOLFSSL_ESPWROOM32SE */ + +/* Uncomment next line if using ARM CRYPTOCELL*/ +/* #define WOLFSSL_CRYPTOCELL */ + +#include + +#ifdef WOLFSSL_USER_SETTINGS + #include "user_settings.h" +#endif + +#include "sys_config.h" + +/* make sure old RNG name is used with CTaoCrypt FIPS */ +#ifdef HAVE_FIPS + #if !defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2) + #define WC_RNG RNG + #else + #ifndef WOLFSSL_STM32L4 + #define RNG WC_RNG + #endif + #endif + /* blinding adds API not available yet in FIPS mode */ + #undef WC_RSA_BLINDING +#endif + +#if defined(WOLFSSL_BEKEN) +#define FREERTOS +#define SIZEOF_LONG_LONG 8 +#define WOLFSSL_HAVE_MIN +#define WOLFSSL_HAVE_MAX +#define WOLFSSL_NO_CURRDIR +#define TFM_TIMING_RESISTANT +#define ECC_TIMING_RESISTANT +#define NO_DSA +#define NO_RSA +#define TFM_ECC256 +#define ECC_SHAMIR +#define NO_RC4 +#define NO_HC128 +#define NO_RABBIT +#define HAVE_HASHDRBG +#define HAVE_SUPPORTED_CURVES +#define NO_PSK +#define NO_PWDBASED +#define USE_FAST_MATH +#define WC_NO_ASYNC_THREADING +#define NO_DES3 +#define NO_WOLFSSL_DIR +#define WOLFSSL_NO_ASM +#define WOLFSSL_NO_SOCK +#define NO_CERTS +#define NO_WRITEV +#define NO_ERROR_STRINGS +#define WOLFSSL_SMALL_STACK +//#define WOLFSSL_SMALL_STACK_CACHE +#define HAVE_COMP_KEY +#define WOLFSSL_KEY_GEN +#define SQRTMOD_USE_MOD_EXP +#define FP_MAX_BITS 768 + +//#define WC_RSA_BLINDING +//#define BUILDING_WOLFSSL +//#define HAVE_FFDHE_2048 +//#define _POSIX_THREADS +//#define HAVE_THREAD_LS +//#define HAVE_AESGCM +//#define WOLFSSL_SHA512 +//#define WOLFSSL_SHA384 +//#define WOLFSSL_SHA224 +//#define WOLFSSL_SHA3 +//#define WOLFSSL_BASE64_ENCODE +//#define HAVE_POLY1305 +//#define HAVE_ONE_TIME_AUTH +//#define HAVE_CHACHA +//#define HAVE_TLS_EXTENSIONS +//#define HAVE_EXTENDED_MASTER +//#define WOLFSSL_X86_64_BUILD + +/* Customize ECC */ +#define HAVE_ECC +#define ECC_USER_CURVES +//#define ECC192 +//#define ECC224 +#define ECC256 +#define ECC384 +//#define ECC521 +#endif + + +#if defined(WOLFSSL_ESPIDF) + #define FREERTOS + #define WOLFSSL_LWIP + #define NO_WRITEV + #define SIZEOF_LONG_LONG 8 + #define NO_WOLFSSL_DIR + #define WOLFSSL_NO_CURRDIR + + #define TFM_TIMING_RESISTANT + #define ECC_TIMING_RESISTANT + #define WC_RSA_BLINDING + +#if defined(WOLFSSL_ESPWROOM32) || defined(WOLFSSL_ESPWROOM32SE) + #ifndef NO_ESP32WROOM32_CRYPT + #define WOLFSSL_ESP32WROOM32_CRYPT + #if defined(ESP32_USE_RSA_PRIMITIVE) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI) + #define WOLFSSL_ESP32WROOM32_CRYPT_RSA_PRI + #define USE_FAST_MATH + #define WOLFSSL_SMALL_STACK + #endif + #endif +#endif +#endif /* WOLFSSL_ESPIDF */ + +#if defined(HAVE_LWIP_NATIVE) /* using LwIP native TCP socket */ + #define WOLFSSL_LWIP + #define NO_WRITEV + #define SINGLE_THREADED + #define WOLFSSL_USER_IO + #define NO_FILESYSTEM +#endif + +#ifdef MBED + #define WOLFSSL_USER_IO + #define NO_FILESYSTEM + #define NO_CERTS + #if !defined(USE_CERT_BUFFERS_2048) && !defined(USE_CERT_BUFFERS_4096) + #define USE_CERT_BUFFERS_1024 + #endif + #define NO_WRITEV + #define NO_DEV_RANDOM + #define NO_SHA512 + #define NO_DH + /* Allows use of DH with fixed points if uncommented and NO_DH is removed */ + /* WOLFSSL_DH_CONST */ + #define NO_DSA + #define NO_HC128 + #define HAVE_ECC + #define NO_SESSION_CACHE + #define WOLFSSL_CMSIS_RTOS +#endif + + +#ifdef FREERTOS + #include "FreeRTOS.h" + + /* FreeRTOS pvPortRealloc() only in AVR32_UC3 port */ + #if !defined(XMALLOC_USER) && !defined(NO_WOLFSSL_MEMORY) && \ + !defined(WOLFSSL_STATIC_MEMORY) + + #if OSMALLOC_STATISTICAL + #define XMALLOC(s, h, type) pvPortMalloc_cm((const char*)NULL,__LINE__,(s), 0) + #define XFREE(p, h, type) vPortFree_cm((const char*)NULL,__LINE__,(p)) + #else + #define XMALLOC(s, h, type) pvPortMalloc((s)) + #define XFREE(p, h, type) vPortFree((p)) + #endif + #endif + #if defined(HAVE_ED25519) || defined(WOLFSSL_ESPIDF) + #define XREALLOC(p, n, h, t) wolfSSL_Realloc((p), (n)) + #endif + #ifndef NO_WRITEV + #define NO_WRITEV + #endif + #ifndef HAVE_SHA512 + #ifndef NO_SHA512 + #define NO_SHA512 + #endif + #endif + #ifndef HAVE_DH + #ifndef NO_DH + #define NO_DH + #endif + #endif + #ifndef NO_DSA + #define NO_DSA + #endif + #ifndef NO_HC128 + #define NO_HC128 + #endif + + #ifndef SINGLE_THREADED + #include "semphr.h" + #endif +#endif + +#ifdef FREERTOS_TCP + #if !defined(NO_WOLFSSL_MEMORY) && !defined(XMALLOC_USER) && \ + !defined(WOLFSSL_STATIC_MEMORY) + #define XMALLOC(s, h, type) pvPortMalloc((s)) + #define XFREE(p, h, type) vPortFree((p)) + #endif + + #define WOLFSSL_GENSEED_FORTEST + + #define NO_WOLFSSL_DIR + #define NO_WRITEV + #define USE_FAST_MATH + #define TFM_TIMING_RESISTANT + #define NO_MAIN_DRIVER +#endif + +#ifdef WOLFSSL_LOW_MEMORY + #undef RSA_LOW_MEM + #define RSA_LOW_MEM + #undef WOLFSSL_SMALL_STACK + #define WOLFSSL_SMALL_STACK + #undef TFM_TIMING_RESISTANT + #define TFM_TIMING_RESISTANT +#endif + +#ifdef WOLFSSL_QL + #ifndef WOLFSSL_SEP + #define WOLFSSL_SEP + #endif + #ifndef OPENSSL_EXTRA + #define OPENSSL_EXTRA + #endif + #ifndef SESSION_CERTS + #define SESSION_CERTS + #endif + #ifndef HAVE_AESCCM + #define HAVE_AESCCM + #endif + #ifndef ATOMIC_USER + #define ATOMIC_USER + #endif + #ifndef WOLFSSL_DER_LOAD + #define WOLFSSL_DER_LOAD + #endif + #ifndef KEEP_PEER_CERT + #define KEEP_PEER_CERT + #endif + #ifndef HAVE_ECC + #define HAVE_ECC + #endif + #ifndef SESSION_INDEX + #define SESSION_INDEX + #endif +#endif /* WOLFSSL_QL */ + + +/* if defined turn on all CAAM support */ +#if !defined(XMALLOC_USER) && !defined(MICRIUM_MALLOC) && \ + !defined(WOLFSSL_LEANPSK) && !defined(NO_WOLFSSL_MEMORY) && \ + !defined(XMALLOC_OVERRIDE) + #define USE_WOLFSSL_MEMORY +#endif + + +#if defined(OPENSSL_EXTRA) && !defined(NO_CERTS) + #undef KEEP_PEER_CERT + #define KEEP_PEER_CERT +#endif + + +/* stream ciphers except arc4 need 32bit alignment, intel ok without */ +#ifndef XSTREAM_ALIGN + #if defined(__x86_64__) || defined(__ia64__) || defined(__i386__) + #define NO_XSTREAM_ALIGN + #else + #define XSTREAM_ALIGN + #endif +#endif + +/* write dup cannot be used with secure renegotiation because write dup + * make write side write only and read side read only */ +#if defined(HAVE_WRITE_DUP) && defined(HAVE_SECURE_RENEGOTIATION) + #error "WRITE DUP and SECURE RENEGOTIATION cannot both be on" +#endif + +/* if using hardware crypto and have alignment requirements, specify the + requirement here. The record header of SSL/TLS will prevent easy alignment. + This hint tries to help as much as possible. */ +#ifndef WOLFSSL_GENERAL_ALIGNMENT + #ifdef WOLFSSL_AESNI + #define WOLFSSL_GENERAL_ALIGNMENT 16 + #elif defined(XSTREAM_ALIGN) + #define WOLFSSL_GENERAL_ALIGNMENT 4 + #elif defined(FREESCALE_MMCAU) || defined(FREESCALE_MMCAU_CLASSIC) + #define WOLFSSL_GENERAL_ALIGNMENT WOLFSSL_MMCAU_ALIGNMENT + #else + #define WOLFSSL_GENERAL_ALIGNMENT 0 + #endif +#endif + +#if defined(WOLFSSL_GENERAL_ALIGNMENT) && (WOLFSSL_GENERAL_ALIGNMENT > 0) + #if defined(_MSC_VER) + #define XGEN_ALIGN __declspec(align(WOLFSSL_GENERAL_ALIGNMENT)) + #elif defined(__GNUC__) + #define XGEN_ALIGN __attribute__((aligned(WOLFSSL_GENERAL_ALIGNMENT))) + #else + #define XGEN_ALIGN + #endif +#else + #define XGEN_ALIGN +#endif + +#ifdef HAVE_CRL + /* not widely supported yet */ + #undef NO_SKID + #define NO_SKID +#endif + + +#ifdef __INTEL_COMPILER + #pragma warning(disable:2259) /* explicit casts to smaller sizes, disable */ +#endif + +/* user can specify what curves they want with ECC_USER_CURVES otherwise + * all curves are on by default for now */ +#ifndef ECC_USER_CURVES + #if !defined(WOLFSSL_SP_MATH) && !defined(HAVE_ALL_CURVES) + #define HAVE_ALL_CURVES + #endif +#endif + +/* ECC Configs */ +#ifdef HAVE_ECC + /* By default enable Sign, Verify, DHE, Key Import and Key Export unless explicitly disabled */ + #ifndef NO_ECC_SIGN + #undef HAVE_ECC_SIGN + #define HAVE_ECC_SIGN + #endif + #ifndef NO_ECC_VERIFY + #undef HAVE_ECC_VERIFY + #define HAVE_ECC_VERIFY + #endif + #ifndef NO_ECC_CHECK_KEY + #undef HAVE_ECC_CHECK_KEY + #define HAVE_ECC_CHECK_KEY + #endif + #ifndef NO_ECC_DHE + #undef HAVE_ECC_DHE + #define HAVE_ECC_DHE + #endif + #ifndef NO_ECC_KEY_IMPORT + #undef HAVE_ECC_KEY_IMPORT + #define HAVE_ECC_KEY_IMPORT + #endif + #ifndef NO_ECC_KEY_EXPORT + #undef HAVE_ECC_KEY_EXPORT + #define HAVE_ECC_KEY_EXPORT + #endif +#endif /* HAVE_ECC */ + +/* Curve255519 Configs */ +#ifdef HAVE_CURVE25519 + /* By default enable shared secret, key export and import */ + #ifndef NO_CURVE25519_SHARED_SECRET + #undef HAVE_CURVE25519_SHARED_SECRET + #define HAVE_CURVE25519_SHARED_SECRET + #endif + #ifndef NO_CURVE25519_KEY_EXPORT + #undef HAVE_CURVE25519_KEY_EXPORT + #define HAVE_CURVE25519_KEY_EXPORT + #endif + #ifndef NO_CURVE25519_KEY_IMPORT + #undef HAVE_CURVE25519_KEY_IMPORT + #define HAVE_CURVE25519_KEY_IMPORT + #endif +#endif /* HAVE_CURVE25519 */ + +/* Ed255519 Configs */ +#ifdef HAVE_ED25519 + /* By default enable sign, verify, key export and import */ + #ifndef NO_ED25519_SIGN + #undef HAVE_ED25519_SIGN + #define HAVE_ED25519_SIGN + #endif + #ifndef NO_ED25519_VERIFY + #undef HAVE_ED25519_VERIFY + #define HAVE_ED25519_VERIFY + #endif + #ifndef NO_ED25519_KEY_EXPORT + #undef HAVE_ED25519_KEY_EXPORT + #define HAVE_ED25519_KEY_EXPORT + #endif + #ifndef NO_ED25519_KEY_IMPORT + #undef HAVE_ED25519_KEY_IMPORT + #define HAVE_ED25519_KEY_IMPORT + #endif +#endif /* HAVE_ED25519 */ + +/* AES Config */ +#ifndef NO_AES + /* By default enable all AES key sizes, decryption and CBC */ + #ifndef AES_MAX_KEY_SIZE + #undef AES_MAX_KEY_SIZE + #define AES_MAX_KEY_SIZE 256 + #endif + + #ifndef NO_AES_128 + #undef WOLFSSL_AES_128 + #define WOLFSSL_AES_128 + #endif + #if !defined(NO_AES_192) && AES_MAX_KEY_SIZE >= 192 + #undef WOLFSSL_AES_192 + #define WOLFSSL_AES_192 + #endif + #if !defined(NO_AES_256) && AES_MAX_KEY_SIZE >= 256 + #undef WOLFSSL_AES_256 + #define WOLFSSL_AES_256 + #endif + #if !defined(WOLFSSL_AES_128) && defined(HAVE_ECC_ENCRYPT) + #warning HAVE_ECC_ENCRYPT uses AES 128 bit keys + #endif + + #ifndef NO_AES_DECRYPT + #undef HAVE_AES_DECRYPT + #define HAVE_AES_DECRYPT + #endif + #ifndef NO_AES_CBC + #undef HAVE_AES_CBC + #define HAVE_AES_CBC + #endif + #ifdef WOLFSSL_AES_XTS + /* AES-XTS makes calls to AES direct functions */ + #ifndef WOLFSSL_AES_DIRECT + #define WOLFSSL_AES_DIRECT + #endif + #endif + #ifdef WOLFSSL_AES_CFB + /* AES-CFB makes calls to AES direct functions */ + #ifndef WOLFSSL_AES_DIRECT + #define WOLFSSL_AES_DIRECT + #endif + #endif +#endif + +#if (defined(WOLFSSL_TLS13) && defined(WOLFSSL_NO_TLS12)) || \ + (!defined(HAVE_AES_CBC) && defined(NO_DES3) && defined(NO_RC4) && \ + !defined(HAVE_CAMELLIA) && !defined(HAVE_IDEA) && \ + !defined(HAVE_NULL_CIPHER) && !defined(HAVE_HC128)) + #define WOLFSSL_AEAD_ONLY +#endif + +#if !defined(NO_DH) && !defined(HAVE_FFDHE) + #if defined(HAVE_FFDHE_2048) || defined(HAVE_FFDHE_3072) || \ + defined(HAVE_FFDHE_4096) || defined(HAVE_FFDHE_6144) || \ + defined(HAVE_FFDHE_8192) + #define HAVE_FFDHE + #endif +#endif +#if defined(HAVE_FFDHE_8192) + #define MIN_FFDHE_FP_MAX_BITS 16384 +#elif defined(HAVE_FFDHE_6144) + #define MIN_FFDHE_FP_MAX_BITS 12288 +#elif defined(HAVE_FFDHE_4096) + #define MIN_FFDHE_FP_MAX_BITS 8192 +#elif defined(HAVE_FFDHE_3072) + #define MIN_FFDHE_FP_MAX_BITS 6144 +#elif defined(HAVE_FFDHE_2048) + #define MIN_FFDHE_FP_MAX_BITS 4096 +#else + #define MIN_FFDHE_FP_MAX_BITS 0 +#endif +#if defined(HAVE_FFDHE) && defined(FP_MAX_BITS) + #if MIN_FFDHE_FP_MAX_BITS > FP_MAX_BITS + #error "FFDHE parameters are too large for FP_MAX_BIT as set" + #endif +#endif + +/* if desktop type system and fastmath increase default max bits */ +#ifdef WOLFSSL_X86_64_BUILD + #if defined(USE_FAST_MATH) && !defined(FP_MAX_BITS) + #if MIN_FFDHE_FP_MAX_BITS <= 8192 + #define FP_MAX_BITS 8192 + #else + #define FP_MAX_BITS MIN_FFDHE_FP_MAX_BITS + #endif + #endif +#endif + +/* If using the max strength build, ensure OLD TLS is disabled. */ +#ifdef WOLFSSL_MAX_STRENGTH + #undef NO_OLD_TLS + #define NO_OLD_TLS +#endif + + +/* Default AES minimum auth tag sz, allow user to override */ +#ifndef WOLFSSL_MIN_AUTH_TAG_SZ + #define WOLFSSL_MIN_AUTH_TAG_SZ 12 +#endif + + +/* sniffer requires: + * static RSA cipher suites + * session stats and peak stats + */ +#ifdef WOLFSSL_SNIFFER + #ifndef WOLFSSL_STATIC_RSA + #define WOLFSSL_STATIC_RSA + #endif + #ifndef WOLFSSL_SESSION_STATS + #define WOLFSSL_SESSION_STATS + #endif + #ifndef WOLFSSL_PEAK_SESSIONS + #define WOLFSSL_PEAK_SESSIONS + #endif +#endif + +/* Decode Public Key extras on by default, user can turn off with + * WOLFSSL_NO_DECODE_EXTRA */ +#ifndef WOLFSSL_NO_DECODE_EXTRA + #ifndef RSA_DECODE_EXTRA + #define RSA_DECODE_EXTRA + #endif + #ifndef ECC_DECODE_EXTRA + #define ECC_DECODE_EXTRA + #endif +#endif + +/* C Sharp wrapper defines */ +#ifdef HAVE_CSHARP + #ifndef WOLFSSL_DTLS + #define WOLFSSL_DTLS + #endif + #undef NO_PSK + #undef NO_SHA256 + #undef NO_DH +#endif + +/* Asynchronous Crypto */ +#ifdef WOLFSSL_ASYNC_CRYPT + /* Make sure wolf events are enabled */ + #undef HAVE_WOLF_EVENT + #define HAVE_WOLF_EVENT + + #ifdef WOLFSSL_ASYNC_CRYPT_TEST + #define WC_ASYNC_DEV_SIZE 168 + #else + #define WC_ASYNC_DEV_SIZE 336 + #endif + + #if !defined(HAVE_CAVIUM) && !defined(HAVE_INTEL_QA) && \ + !defined(WOLFSSL_ASYNC_CRYPT_TEST) + #error No async hardware defined with WOLFSSL_ASYNC_CRYPT! + #endif + + /* Enable ECC_CACHE_CURVE for ASYNC */ + #if !defined(ECC_CACHE_CURVE) + #define ECC_CACHE_CURVE + #endif +#endif /* WOLFSSL_ASYNC_CRYPT */ +#ifndef WC_ASYNC_DEV_SIZE + #define WC_ASYNC_DEV_SIZE 0 +#endif + +/* leantls checks */ +#ifdef WOLFSSL_LEANTLS + #ifndef HAVE_ECC + #error leantls build needs ECC + #endif +#endif /* WOLFSSL_LEANTLS*/ + +/* restriction with static memory */ +#ifdef WOLFSSL_STATIC_MEMORY + #if defined(HAVE_IO_POOL) || defined(XMALLOC_USER) || defined(NO_WOLFSSL_MEMORY) + #error static memory cannot be used with HAVE_IO_POOL, XMALLOC_USER or NO_WOLFSSL_MEMORY + #endif + #if !defined(USE_FAST_MATH) && !defined(NO_BIG_INT) + #error static memory requires fast math please define USE_FAST_MATH + #endif + #ifdef WOLFSSL_SMALL_STACK + #error static memory does not support small stack please undefine + #endif +#endif /* WOLFSSL_STATIC_MEMORY */ + +#ifdef HAVE_AES_KEYWRAP + #ifndef WOLFSSL_AES_DIRECT + #error AES key wrap requires AES direct please define WOLFSSL_AES_DIRECT + #endif +#endif + +#ifdef HAVE_PKCS7 + #if defined(NO_AES) && defined(NO_DES3) + #error PKCS7 needs either AES or 3DES enabled, please enable one + #endif + #ifndef HAVE_AES_KEYWRAP + #error PKCS7 requires AES key wrap please define HAVE_AES_KEYWRAP + #endif + #if defined(HAVE_ECC) && !defined(HAVE_X963_KDF) + #error PKCS7 requires X963 KDF please define HAVE_X963_KDF + #endif +#endif + +#ifndef NO_PKCS12 + #undef HAVE_PKCS12 + #define HAVE_PKCS12 +#endif + +#ifndef NO_PKCS8 + #undef HAVE_PKCS8 + #define HAVE_PKCS8 +#endif + +#if !defined(NO_PBKDF1) || defined(WOLFSSL_ENCRYPTED_KEYS) || defined(HAVE_PKCS8) || defined(HAVE_PKCS12) + #undef HAVE_PBKDF1 + #define HAVE_PBKDF1 +#endif + +#if !defined(NO_PBKDF2) || defined(HAVE_PKCS7) || defined(HAVE_SCRYPT) + #undef HAVE_PBKDF2 + #define HAVE_PBKDF2 +#endif + + +#if !defined(WOLFCRYPT_ONLY) && !defined(NO_OLD_TLS) && \ + (defined(NO_SHA) || defined(NO_MD5)) + #error old TLS requires MD5 and SHA +#endif + +/* for backwards compatibility */ +#if defined(TEST_IPV6) && !defined(WOLFSSL_IPV6) + #define WOLFSSL_IPV6 +#endif + + +/* Place any other flags or defines here */ + +#if defined(WOLFSSL_MYSQL_COMPATIBLE) && defined(_WIN32) \ + && defined(HAVE_GMTIME_R) + #undef HAVE_GMTIME_R /* don't trust macro with windows */ +#endif /* WOLFSSL_MYSQL_COMPATIBLE */ + +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + #define SSL_OP_NO_COMPRESSION SSL_OP_NO_COMPRESSION + #define OPENSSL_NO_ENGINE + #define X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT + #ifndef OPENSSL_EXTRA + #define OPENSSL_EXTRA + #endif + #ifndef HAVE_SESSION_TICKET + #define HAVE_SESSION_TICKET + #endif + #ifndef HAVE_OCSP + #define HAVE_OCSP + #endif + #ifndef KEEP_OUR_CERT + #define KEEP_OUR_CERT + #endif + #ifndef HAVE_SNI + #define HAVE_SNI + #endif +#endif + +#if defined(WOLFSSL_NGINX) + #define SSL_CTRL_SET_TLSEXT_HOSTNAME +#endif + + +/* both CURVE and ED small math should be enabled */ +#ifdef CURVED25519_SMALL + #define CURVE25519_SMALL + #define ED25519_SMALL +#endif + + +#ifndef WOLFSSL_ALERT_COUNT_MAX + #define WOLFSSL_ALERT_COUNT_MAX 5 +#endif + +/* warning for not using harden build options (default with ./configure) */ +#ifndef WC_NO_HARDEN + #if (defined(USE_FAST_MATH) && !defined(TFM_TIMING_RESISTANT)) || \ + (defined(HAVE_ECC) && !defined(ECC_TIMING_RESISTANT)) || \ + (!defined(NO_RSA) && !defined(WC_RSA_BLINDING) && !defined(HAVE_FIPS) && \ + !defined(WC_NO_RNG)) + + #ifndef _MSC_VER + #warning "For timing resistance / side-channel attack prevention consider using harden options" + #else + #pragma message("Warning: For timing resistance / side-channel attack prevention consider using harden options") + #endif + #endif +#endif + +#if defined(NO_OLD_WC_NAMES) || defined(OPENSSL_EXTRA) + /* added to have compatibility with SHA256() */ + #if !defined(NO_OLD_SHA_NAMES) && !defined(HAVE_FIPS) + #define NO_OLD_SHA_NAMES + #endif +#endif + +/* switch for compatibility layer functionality. Has subparts i.e. BIO/X509 + * When opensslextra is enabled all subparts should be turned on. */ +#ifdef OPENSSL_EXTRA + #undef OPENSSL_EXTRA_X509_SMALL + #define OPENSSL_EXTRA_X509_SMALL +#endif /* OPENSSL_EXTRA */ + +/* support for converting DER to PEM */ +#if defined(WOLFSSL_KEY_GEN) || defined(WOLFSSL_CERT_GEN) || \ + defined(OPENSSL_EXTRA) + #undef WOLFSSL_DER_TO_PEM + #define WOLFSSL_DER_TO_PEM +#endif + +/* keep backwards compatibility enabling encrypted private key */ +#ifndef WOLFSSL_ENCRYPTED_KEYS + #if defined(OPENSSL_EXTRA) || defined(OPENSSL_EXTRA_X509_SMALL) || \ + defined(HAVE_WEBSERVER) + #define WOLFSSL_ENCRYPTED_KEYS + #endif +#endif + +/* support for disabling PEM to DER */ +#if !defined(WOLFSSL_NO_PEM) + #undef WOLFSSL_PEM_TO_DER + #define WOLFSSL_PEM_TO_DER +#endif + +/* Parts of the openssl compatibility layer require peer certs */ +#if defined(OPENSSL_ALL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY) + #undef KEEP_PEER_CERT + #define KEEP_PEER_CERT +#endif + +/* RAW hash function APIs are not implemented with ARMv8 hardware acceleration*/ +#ifdef WOLFSSL_ARMASM + #undef WOLFSSL_NO_HASH_RAW + #define WOLFSSL_NO_HASH_RAW +#endif + +#if !defined(WOLFSSL_SHA384) && !defined(WOLFSSL_SHA512) && defined(NO_AES) && \ + !defined(WOLFSSL_SHA3) + #undef WOLFSSL_NO_WORD64_OPS + #define WOLFSSL_NO_WORD64_OPS +#endif + +#if !defined(WOLFCRYPT_ONLY) && !defined(WOLFSSL_NO_TLS12) + #undef WOLFSSL_HAVE_PRF + #define WOLFSSL_HAVE_PRF +#endif + +#if defined(NO_AES) && defined(NO_DES3) && !defined(HAVE_CAMELLIA) && \ + !defined(WOLFSSL_HAVE_PRF) && defined(NO_PWDBASED) && !defined(HAVE_IDEA) + #undef WOLFSSL_NO_XOR_OPS + #define WOLFSSL_NO_XOR_OPS +#endif + +#if defined(NO_ASN) && defined(WOLFCRYPT_ONLY) + #undef WOLFSSL_NO_INT_ENCODE + #define WOLFSSL_NO_INT_ENCODE + #undef WOLFSSL_NO_INT_DECODE + #define WOLFSSL_NO_INT_DECODE +#endif + +#if defined(WOLFCRYPT_ONLY) && defined(WOLFSSL_RSA_VERIFY_ONLY) && \ + defined(WC_NO_RSA_OAEP) + #undef WOLFSSL_NO_CT_OPS + #define WOLFSSL_NO_CT_OPS +#endif + +#if defined(WOLFCRYPT_ONLY) && defined(NO_AES) && !defined(HAVE_CURVE25519) && \ + defined(WC_NO_RNG) && defined(WC_NO_RSA_OAEP) + #undef WOLFSSL_NO_CONST_CMP + #define WOLFSSL_NO_CONST_CMP +#endif + +#if defined(WOLFCRYPT_ONLY) && defined(NO_AES) && !defined(WOLFSSL_SHA384) && \ + !defined(WOLFSSL_SHA512) && defined(WC_NO_RNG) && \ + defined(WOLFSSL_SP_MATH) && defined(WOLFSSL_RSA_PUBLIC_ONLY) + #undef WOLFSSL_NO_FORCE_ZERO + #define WOLFSSL_NO_FORCE_ZERO +#endif + +#if defined(WOLFSSL_TLS13) && defined(WOLFSSL_NO_SIGALG) + #error TLS 1.3 requires the Signature Algorithms extension to be enabled +#endif + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/sha.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/sha.h new file mode 100755 index 0000000..b48fc8f --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/sha.h @@ -0,0 +1,170 @@ +/* sha.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/*! + \file wolfssl/wolfcrypt/sha.h +*/ + + +#ifndef WOLF_CRYPT_SHA_H +#define WOLF_CRYPT_SHA_H + +#include + +#ifndef NO_SHA + +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + #include +#endif /* HAVE_FIPS_VERSION >= 2 */ + +#if defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) +#define wc_Sha Sha +#define WC_SHA SHA +#define WC_SHA_BLOCK_SIZE SHA_BLOCK_SIZE +#define WC_SHA_DIGEST_SIZE SHA_DIGEST_SIZE +#define WC_SHA_PAD_SIZE SHA_PAD_SIZE + +/* for fips @wc_fips */ +#include +#endif + +#ifdef FREESCALE_LTC_SHA + #include "fsl_ltc.h" +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +/* avoid redefinition of structs */ +#if !defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) + +#ifdef WOLFSSL_MICROCHIP_PIC32MZ + #include +#endif +#ifdef STM32_HASH + #include +#endif +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif +#ifdef WOLFSSL_ESP32WROOM32_CRYPT + #include +#endif + +#if !defined(NO_OLD_SHA_NAMES) + #define SHA WC_SHA +#endif + +#ifndef NO_OLD_WC_NAMES + #define Sha wc_Sha + #define SHA_BLOCK_SIZE WC_SHA_BLOCK_SIZE + #define SHA_DIGEST_SIZE WC_SHA_DIGEST_SIZE + #define SHA_PAD_SIZE WC_SHA_PAD_SIZE +#endif + +/* in bytes */ +enum { + WC_SHA = WC_HASH_TYPE_SHA, + WC_SHA_BLOCK_SIZE = 64, + WC_SHA_DIGEST_SIZE = 20, + WC_SHA_PAD_SIZE = 56 +}; + + +#if defined(WOLFSSL_TI_HASH) + #include "wolfssl/wolfcrypt/port/ti/ti-hash.h" + +#elif defined(WOLFSSL_IMX6_CAAM) + #include "wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h" + +#else +/* Sha digest */ +typedef struct wc_Sha { +#ifdef FREESCALE_LTC_SHA + ltc_hash_ctx_t ctx; +#elif defined(STM32_HASH) + STM32_HASH_Context stmCtx; +#else + word32 buffLen; /* in bytes */ + word32 loLen; /* length in bytes */ + word32 hiLen; /* length in bytes */ + word32 buffer[WC_SHA_BLOCK_SIZE / sizeof(word32)]; + #ifdef WOLFSSL_PIC32MZ_HASH + word32 digest[PIC32_DIGEST_SIZE / sizeof(word32)]; + #else + word32 digest[WC_SHA_DIGEST_SIZE / sizeof(word32)]; + #endif + void* heap; + #ifdef WOLFSSL_PIC32MZ_HASH + hashUpdCache cache; /* cache for updates */ + #endif + #ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV asyncDev; + #endif /* WOLFSSL_ASYNC_CRYPT */ + #ifdef WOLF_CRYPTO_CB + int devId; + void* devCtx; /* generic crypto callback context */ + #endif +#endif +#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + WC_ESP32SHA ctx; +#endif +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + word32 flags; /* enum wc_HashFlags in hash.h */ +#endif +} wc_Sha; + +#endif /* WOLFSSL_TI_HASH */ + + +#endif /* HAVE_FIPS */ + +WOLFSSL_API int wc_InitSha(wc_Sha*); +WOLFSSL_API int wc_InitSha_ex(wc_Sha* sha, void* heap, int devId); +WOLFSSL_API int wc_ShaUpdate(wc_Sha*, const byte*, word32); +WOLFSSL_API int wc_ShaFinalRaw(wc_Sha*, byte*); +WOLFSSL_API int wc_ShaFinal(wc_Sha*, byte*); +WOLFSSL_API void wc_ShaFree(wc_Sha*); + +WOLFSSL_API int wc_ShaGetHash(wc_Sha*, byte*); +WOLFSSL_API int wc_ShaCopy(wc_Sha*, wc_Sha*); + +#ifdef WOLFSSL_PIC32MZ_HASH +WOLFSSL_API void wc_ShaSizeSet(wc_Sha* sha, word32 len); +#endif + +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + WOLFSSL_LOCAL int wc_ShaSetFlags(wc_Sha* sha, word32 flags); + WOLFSSL_LOCAL int wc_ShaGetFlags(wc_Sha* sha, word32* flags); +#endif + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* NO_SHA */ +#endif /* WOLF_CRYPT_SHA_H */ + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/sha256.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/sha256.h new file mode 100755 index 0000000..5bfcc7c --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/sha256.h @@ -0,0 +1,243 @@ +/* sha256.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/*! + \file wolfssl/wolfcrypt/sha256.h +*/ + + + +#ifndef WOLF_CRYPT_SHA256_H +#define WOLF_CRYPT_SHA256_H + +#include + +#ifndef NO_SHA256 + +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + #include +#endif /* HAVE_FIPS_VERSION >= 2 */ + +#if defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) + #define wc_Sha256 Sha256 + #define WC_SHA256 SHA256 + #define WC_SHA256_BLOCK_SIZE SHA256_BLOCK_SIZE + #define WC_SHA256_DIGEST_SIZE SHA256_DIGEST_SIZE + #define WC_SHA256_PAD_SIZE SHA256_PAD_SIZE + + #ifdef WOLFSSL_SHA224 + #define wc_Sha224 Sha224 + #define WC_SHA224 SHA224 + #define WC_SHA224_BLOCK_SIZE SHA224_BLOCK_SIZE + #define WC_SHA224_DIGEST_SIZE SHA224_DIGEST_SIZE + #define WC_SHA224_PAD_SIZE SHA224_PAD_SIZE + #endif + + /* for fips @wc_fips */ + #include +#endif + +#ifdef FREESCALE_LTC_SHA + #include "fsl_ltc.h" +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + +/* avoid redefinition of structs */ +#if !defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) + +#ifdef WOLFSSL_MICROCHIP_PIC32MZ + #include +#endif +#ifdef STM32_HASH + #include +#endif +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif +#if defined(WOLFSSL_DEVCRYPTO) && defined(WOLFSSL_DEVCRYPTO_HASH) + #include +#endif +#if defined(WOLFSSL_ESP32WROOM32_CRYPT) + #include "wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h" +#endif +#if defined(WOLFSSL_CRYPTOCELL) + #include +#endif + +#if defined(_MSC_VER) + #define SHA256_NOINLINE __declspec(noinline) +#elif defined(__GNUC__) + #define SHA256_NOINLINE __attribute__((noinline)) +#else + #define SHA256_NOINLINE +#endif + +#if !defined(NO_OLD_SHA_NAMES) + #define SHA256 WC_SHA256 +#endif + +#ifndef NO_OLD_WC_NAMES + #define Sha256 wc_Sha256 + #define SHA256_BLOCK_SIZE WC_SHA256_BLOCK_SIZE + #define SHA256_DIGEST_SIZE WC_SHA256_DIGEST_SIZE + #define SHA256_PAD_SIZE WC_SHA256_PAD_SIZE +#endif + +/* in bytes */ +enum { + WC_SHA256 = WC_HASH_TYPE_SHA256, + WC_SHA256_BLOCK_SIZE = 64, + WC_SHA256_DIGEST_SIZE = 32, + WC_SHA256_PAD_SIZE = 56 +}; + + +#ifdef WOLFSSL_TI_HASH + #include "wolfssl/wolfcrypt/port/ti/ti-hash.h" +#elif defined(WOLFSSL_IMX6_CAAM) + #include "wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h" +#elif defined(WOLFSSL_AFALG_HASH) + #include "wolfssl/wolfcrypt/port/af_alg/afalg_hash.h" +#else +/* wc_Sha256 digest */ +typedef struct wc_Sha256 { +#ifdef FREESCALE_LTC_SHA + ltc_hash_ctx_t ctx; +#elif defined(STM32_HASH) + STM32_HASH_Context stmCtx; +#else + /* alignment on digest and buffer speeds up ARMv8 crypto operations */ + ALIGN16 word32 digest[WC_SHA256_DIGEST_SIZE / sizeof(word32)]; + ALIGN16 word32 buffer[WC_SHA256_BLOCK_SIZE / sizeof(word32)]; + word32 buffLen; /* in bytes */ + word32 loLen; /* length in bytes */ + word32 hiLen; /* length in bytes */ + void* heap; +#ifdef WOLFSSL_PIC32MZ_HASH + hashUpdCache cache; /* cache for updates */ +#endif +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV asyncDev; +#endif /* WOLFSSL_ASYNC_CRYPT */ +#ifdef WOLFSSL_SMALL_STACK_CACHE + word32* W; +#endif +#ifdef WOLFSSL_DEVCRYPTO_HASH + WC_CRYPTODEV ctx; + byte* msg; + word32 used; + word32 len; +#endif +#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + WC_ESP32SHA ctx; +#endif +#ifdef WOLFSSL_CRYPTOCELL + CRYS_HASHUserContext_t ctx; +#endif +#ifdef WOLF_CRYPTO_CB + int devId; + void* devCtx; /* generic crypto callback context */ +#endif +#endif +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + word32 flags; /* enum wc_HashFlags in hash.h */ +#endif +} wc_Sha256; + +#endif + +#endif /* HAVE_FIPS */ + +WOLFSSL_API int wc_InitSha256(wc_Sha256*); +WOLFSSL_API int wc_InitSha256_ex(wc_Sha256*, void*, int); +WOLFSSL_API int wc_Sha256Update(wc_Sha256*, const byte*, word32); +WOLFSSL_API int wc_Sha256FinalRaw(wc_Sha256*, byte*); +WOLFSSL_API int wc_Sha256Final(wc_Sha256*, byte*); +WOLFSSL_API void wc_Sha256Free(wc_Sha256*); + +WOLFSSL_API int wc_Sha256GetHash(wc_Sha256*, byte*); +WOLFSSL_API int wc_Sha256Copy(wc_Sha256* src, wc_Sha256* dst); + +#ifdef WOLFSSL_PIC32MZ_HASH +WOLFSSL_API void wc_Sha256SizeSet(wc_Sha256*, word32); +#endif + +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + WOLFSSL_LOCAL int wc_Sha256SetFlags(wc_Sha256* sha256, word32 flags); + WOLFSSL_LOCAL int wc_Sha256GetFlags(wc_Sha256* sha256, word32* flags); +#endif + +#ifdef WOLFSSL_SHA224 +/* avoid redefinition of structs */ +#if !defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) + +#ifndef NO_OLD_WC_NAMES + #define Sha224 wc_Sha224 + #define SHA224 WC_SHA224 + #define SHA224_BLOCK_SIZE WC_SHA224_BLOCK_SIZE + #define SHA224_DIGEST_SIZE WC_SHA224_DIGEST_SIZE + #define SHA224_PAD_SIZE WC_SHA224_PAD_SIZE +#endif + +/* in bytes */ +enum { + WC_SHA224 = WC_HASH_TYPE_SHA224, + WC_SHA224_BLOCK_SIZE = WC_SHA256_BLOCK_SIZE, + WC_SHA224_DIGEST_SIZE = 28, + WC_SHA224_PAD_SIZE = WC_SHA256_PAD_SIZE +}; + + +typedef wc_Sha256 wc_Sha224; +#endif /* HAVE_FIPS */ + +WOLFSSL_API int wc_InitSha224(wc_Sha224*); +WOLFSSL_API int wc_InitSha224_ex(wc_Sha224*, void*, int); +WOLFSSL_API int wc_Sha224Update(wc_Sha224*, const byte*, word32); +WOLFSSL_API int wc_Sha224Final(wc_Sha224*, byte*); +WOLFSSL_API void wc_Sha224Free(wc_Sha224*); + +WOLFSSL_API int wc_Sha224GetHash(wc_Sha224*, byte*); +WOLFSSL_API int wc_Sha224Copy(wc_Sha224* src, wc_Sha224* dst); + +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + WOLFSSL_LOCAL int wc_Sha224SetFlags(wc_Sha224* sha224, word32 flags); + WOLFSSL_LOCAL int wc_Sha224GetFlags(wc_Sha224* sha224, word32* flags); +#endif + +#endif /* WOLFSSL_SHA224 */ + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* NO_SHA256 */ +#endif /* WOLF_CRYPT_SHA256_H */ + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/sha3.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/sha3.h new file mode 100755 index 0000000..cde45b2 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/sha3.h @@ -0,0 +1,150 @@ +/* sha3.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifndef WOLF_CRYPT_SHA3_H +#define WOLF_CRYPT_SHA3_H + +#include + +#ifdef WOLFSSL_SHA3 + +#ifdef HAVE_FIPS + /* for fips @wc_fips */ + #include +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif + +/* in bytes */ +enum { + WC_SHA3_224 = WC_HASH_TYPE_SHA3_224, + WC_SHA3_224_DIGEST_SIZE = 28, + WC_SHA3_224_COUNT = 18, + + WC_SHA3_256 = WC_HASH_TYPE_SHA3_256, + WC_SHA3_256_DIGEST_SIZE = 32, + WC_SHA3_256_COUNT = 17, + + WC_SHA3_384 = WC_HASH_TYPE_SHA3_384, + WC_SHA3_384_DIGEST_SIZE = 48, + WC_SHA3_384_COUNT = 13, + + WC_SHA3_512 = WC_HASH_TYPE_SHA3_512, + WC_SHA3_512_DIGEST_SIZE = 64, + WC_SHA3_512_COUNT = 9, + +#ifndef HAVE_SELFTEST + /* These values are used for HMAC, not SHA-3 directly. + * They come from from FIPS PUB 202. */ + WC_SHA3_224_BLOCK_SIZE = 144, + WC_SHA3_256_BLOCK_SIZE = 136, + WC_SHA3_384_BLOCK_SIZE = 104, + WC_SHA3_512_BLOCK_SIZE = 72, +#endif +}; + +#ifndef NO_OLD_WC_NAMES + #define SHA3_224 WC_SHA3_224 + #define SHA3_224_DIGEST_SIZE WC_SHA3_224_DIGEST_SIZE + #define SHA3_256 WC_SHA3_256 + #define SHA3_256_DIGEST_SIZE WC_SHA3_256_DIGEST_SIZE + #define SHA3_384 WC_SHA3_384 + #define SHA3_384_DIGEST_SIZE WC_SHA3_384_DIGEST_SIZE + #define SHA3_512 WC_SHA3_512 + #define SHA3_512_DIGEST_SIZE WC_SHA3_512_DIGEST_SIZE + #define Sha3 wc_Sha3 +#endif + + + +#ifdef WOLFSSL_XILINX_CRYPT + #include "wolfssl/wolfcrypt/port/xilinx/xil-sha3.h" +#elif defined(WOLFSSL_AFALG_XILINX_SHA3) + #include +#else +/* Sha3 digest */ +typedef struct Sha3 { + /* State data that is processed for each block. */ + word64 s[25]; + /* Unprocessed message data. */ + byte t[200]; + /* Index into unprocessed data to place next message byte. */ + byte i; + + void* heap; + +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV asyncDev; +#endif /* WOLFSSL_ASYNC_CRYPT */ +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + word32 flags; /* enum wc_HashFlags in hash.h */ +#endif +} wc_Sha3; +#endif + + +WOLFSSL_API int wc_InitSha3_224(wc_Sha3*, void*, int); +WOLFSSL_API int wc_Sha3_224_Update(wc_Sha3*, const byte*, word32); +WOLFSSL_API int wc_Sha3_224_Final(wc_Sha3*, byte*); +WOLFSSL_API void wc_Sha3_224_Free(wc_Sha3*); +WOLFSSL_API int wc_Sha3_224_GetHash(wc_Sha3*, byte*); +WOLFSSL_API int wc_Sha3_224_Copy(wc_Sha3* src, wc_Sha3* dst); + +WOLFSSL_API int wc_InitSha3_256(wc_Sha3*, void*, int); +WOLFSSL_API int wc_Sha3_256_Update(wc_Sha3*, const byte*, word32); +WOLFSSL_API int wc_Sha3_256_Final(wc_Sha3*, byte*); +WOLFSSL_API void wc_Sha3_256_Free(wc_Sha3*); +WOLFSSL_API int wc_Sha3_256_GetHash(wc_Sha3*, byte*); +WOLFSSL_API int wc_Sha3_256_Copy(wc_Sha3* src, wc_Sha3* dst); + +WOLFSSL_API int wc_InitSha3_384(wc_Sha3*, void*, int); +WOLFSSL_API int wc_Sha3_384_Update(wc_Sha3*, const byte*, word32); +WOLFSSL_API int wc_Sha3_384_Final(wc_Sha3*, byte*); +WOLFSSL_API void wc_Sha3_384_Free(wc_Sha3*); +WOLFSSL_API int wc_Sha3_384_GetHash(wc_Sha3*, byte*); +WOLFSSL_API int wc_Sha3_384_Copy(wc_Sha3* src, wc_Sha3* dst); + +WOLFSSL_API int wc_InitSha3_512(wc_Sha3*, void*, int); +WOLFSSL_API int wc_Sha3_512_Update(wc_Sha3*, const byte*, word32); +WOLFSSL_API int wc_Sha3_512_Final(wc_Sha3*, byte*); +WOLFSSL_API void wc_Sha3_512_Free(wc_Sha3*); +WOLFSSL_API int wc_Sha3_512_GetHash(wc_Sha3*, byte*); +WOLFSSL_API int wc_Sha3_512_Copy(wc_Sha3* src, wc_Sha3* dst); + +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + WOLFSSL_LOCAL int wc_Sha3_SetFlags(wc_Sha3* sha3, word32 flags); + WOLFSSL_LOCAL int wc_Sha3_GetFlags(wc_Sha3* sha3, word32* flags); +#endif + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLFSSL_SHA3 */ +#endif /* WOLF_CRYPT_SHA3_H */ + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/sha512.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/sha512.h new file mode 100755 index 0000000..586289a --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/sha512.h @@ -0,0 +1,220 @@ +/* sha512.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/*! + \file wolfssl/wolfcrypt/sha512.h +*/ + + +#ifndef WOLF_CRYPT_SHA512_H +#define WOLF_CRYPT_SHA512_H + +#include + +#if defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384) + +#if defined(HAVE_FIPS) && \ + defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2) + #include +#endif /* HAVE_FIPS_VERSION >= 2 */ + +#if defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) + #ifdef WOLFSSL_SHA512 + #define wc_Sha512 Sha512 + #define WC_SHA512 SHA512 + #define WC_SHA512_BLOCK_SIZE SHA512_BLOCK_SIZE + #define WC_SHA512_DIGEST_SIZE SHA512_DIGEST_SIZE + #define WC_SHA512_PAD_SIZE SHA512_PAD_SIZE + #endif /* WOLFSSL_SHA512 */ + #ifdef WOLFSSL_SHA384 + #define wc_Sha384 Sha384 + #define WC_SHA384 SHA384 + #define WC_SHA384_BLOCK_SIZE SHA384_BLOCK_SIZE + #define WC_SHA384_DIGEST_SIZE SHA384_DIGEST_SIZE + #define WC_SHA384_PAD_SIZE SHA384_PAD_SIZE + #endif /* WOLFSSL_SHA384 */ + + #define CYASSL_SHA512 + #if defined(WOLFSSL_SHA384) + #define CYASSL_SHA384 + #endif + /* for fips @wc_fips */ + #include +#endif + +#ifdef __cplusplus + extern "C" { +#endif + +/* avoid redefinition of structs */ +#if !defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) + +#ifdef WOLFSSL_ASYNC_CRYPT + #include +#endif +#ifdef WOLFSSL_ESP32WROOM32_CRYPT + #include +#endif +#if defined(_MSC_VER) + #define SHA512_NOINLINE __declspec(noinline) +#elif defined(__GNUC__) + #define SHA512_NOINLINE __attribute__((noinline)) +#else + #define SHA512_NOINLINE +#endif + +#ifdef WOLFSSL_SHA512 + +#if !defined(NO_OLD_SHA_NAMES) + #define SHA512 WC_SHA512 +#endif + +#if !defined(NO_OLD_WC_NAMES) + #define Sha512 wc_Sha512 + #define SHA512_BLOCK_SIZE WC_SHA512_BLOCK_SIZE + #define SHA512_DIGEST_SIZE WC_SHA512_DIGEST_SIZE + #define SHA512_PAD_SIZE WC_SHA512_PAD_SIZE +#endif + +#endif /* WOLFSSL_SHA512 */ + +/* in bytes */ +enum { +#ifdef WOLFSSL_SHA512 + WC_SHA512 = WC_HASH_TYPE_SHA512, +#endif + WC_SHA512_BLOCK_SIZE = 128, + WC_SHA512_DIGEST_SIZE = 64, + WC_SHA512_PAD_SIZE = 112 +}; + + +#ifdef WOLFSSL_IMX6_CAAM + #include "wolfssl/wolfcrypt/port/caam/wolfcaam_sha.h" +#else +/* wc_Sha512 digest */ +typedef struct wc_Sha512 { + word64 digest[WC_SHA512_DIGEST_SIZE / sizeof(word64)]; + word64 buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64)]; + word32 buffLen; /* in bytes */ + word64 loLen; /* length in bytes */ + word64 hiLen; /* length in bytes */ + void* heap; +#ifdef USE_INTEL_SPEEDUP + const byte* data; +#endif +#ifdef WOLFSSL_ASYNC_CRYPT + WC_ASYNC_DEV asyncDev; +#endif /* WOLFSSL_ASYNC_CRYPT */ +#ifdef WOLFSSL_SMALL_STACK_CACHE + word64* W; +#endif +#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \ + !defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH) + WC_ESP32SHA ctx; +#endif +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + word32 flags; /* enum wc_HashFlags in hash.h */ +#endif +} wc_Sha512; +#endif + +#endif /* HAVE_FIPS */ + +#ifdef WOLFSSL_ARMASM +WOLFSSL_LOCAL void Transform_Sha512_Len(wc_Sha512* sha512, const byte* data, + word32 len); +#endif + +#ifdef WOLFSSL_SHA512 + +WOLFSSL_API int wc_InitSha512(wc_Sha512*); +WOLFSSL_API int wc_InitSha512_ex(wc_Sha512*, void*, int); +WOLFSSL_API int wc_Sha512Update(wc_Sha512*, const byte*, word32); +WOLFSSL_API int wc_Sha512FinalRaw(wc_Sha512*, byte*); +WOLFSSL_API int wc_Sha512Final(wc_Sha512*, byte*); +WOLFSSL_API void wc_Sha512Free(wc_Sha512*); + +WOLFSSL_API int wc_Sha512GetHash(wc_Sha512*, byte*); +WOLFSSL_API int wc_Sha512Copy(wc_Sha512* src, wc_Sha512* dst); + +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + WOLFSSL_LOCAL int wc_Sha512SetFlags(wc_Sha512* sha512, word32 flags); + WOLFSSL_LOCAL int wc_Sha512GetFlags(wc_Sha512* sha512, word32* flags); +#endif + +#endif /* WOLFSSL_SHA512 */ + +#if defined(WOLFSSL_SHA384) + +/* avoid redefinition of structs */ +#if !defined(HAVE_FIPS) || \ + (defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)) + +#if !defined(NO_OLD_SHA_NAMES) + #define SHA384 WC_SHA384 +#endif + +#if !defined(NO_OLD_WC_NAMES) + #define Sha384 wc_Sha384 + #define SHA384_BLOCK_SIZE WC_SHA384_BLOCK_SIZE + #define SHA384_DIGEST_SIZE WC_SHA384_DIGEST_SIZE + #define SHA384_PAD_SIZE WC_SHA384_PAD_SIZE +#endif + +/* in bytes */ +enum { + WC_SHA384 = WC_HASH_TYPE_SHA384, + WC_SHA384_BLOCK_SIZE = WC_SHA512_BLOCK_SIZE, + WC_SHA384_DIGEST_SIZE = 48, + WC_SHA384_PAD_SIZE = WC_SHA512_PAD_SIZE +}; + + +typedef wc_Sha512 wc_Sha384; +#endif /* HAVE_FIPS */ + +WOLFSSL_API int wc_InitSha384(wc_Sha384*); +WOLFSSL_API int wc_InitSha384_ex(wc_Sha384*, void*, int); +WOLFSSL_API int wc_Sha384Update(wc_Sha384*, const byte*, word32); +WOLFSSL_API int wc_Sha384FinalRaw(wc_Sha384*, byte*); +WOLFSSL_API int wc_Sha384Final(wc_Sha384*, byte*); +WOLFSSL_API void wc_Sha384Free(wc_Sha384*); + +WOLFSSL_API int wc_Sha384GetHash(wc_Sha384*, byte*); +WOLFSSL_API int wc_Sha384Copy(wc_Sha384* src, wc_Sha384* dst); + +#if defined(WOLFSSL_HASH_FLAGS) || defined(WOLF_CRYPTO_CB) + WOLFSSL_LOCAL int wc_Sha384SetFlags(wc_Sha384* sha384, word32 flags); + WOLFSSL_LOCAL int wc_Sha384GetFlags(wc_Sha384* sha384, word32* flags); +#endif + +#endif /* WOLFSSL_SHA384 */ + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLFSSL_SHA512 || WOLFSSL_SHA384 */ +#endif /* WOLF_CRYPT_SHA512_H */ + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/signature.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/signature.h new file mode 100755 index 0000000..a0cc4ea --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/signature.h @@ -0,0 +1,76 @@ +/* signature.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/*! + \file wolfssl/wolfcrypt/signature.h +*/ + + +#ifndef WOLF_CRYPT_SIGNATURE_H +#define WOLF_CRYPT_SIGNATURE_H + +#include +#include +#include + +#ifdef __cplusplus + extern "C" { +#endif + +enum wc_SignatureType { + WC_SIGNATURE_TYPE_NONE = 0, + WC_SIGNATURE_TYPE_ECC = 1, + WC_SIGNATURE_TYPE_RSA = 2, + WC_SIGNATURE_TYPE_RSA_W_ENC = 3, /* Adds DER header via wc_EncodeSignature */ +}; + +WOLFSSL_API int wc_SignatureGetSize(enum wc_SignatureType sig_type, + const void* key, word32 key_len); + +WOLFSSL_API int wc_SignatureVerifyHash( + enum wc_HashType hash_type, enum wc_SignatureType sig_type, + const byte* hash_data, word32 hash_len, + const byte* sig, word32 sig_len, + const void* key, word32 key_len); + +WOLFSSL_API int wc_SignatureVerify( + enum wc_HashType hash_type, enum wc_SignatureType sig_type, + const byte* data, word32 data_len, + const byte* sig, word32 sig_len, + const void* key, word32 key_len); + +WOLFSSL_API int wc_SignatureGenerateHash( + enum wc_HashType hash_type, enum wc_SignatureType sig_type, + const byte* hash_data, word32 hash_len, + byte* sig, word32 *sig_len, + const void* key, word32 key_len, WC_RNG* rng); +WOLFSSL_API int wc_SignatureGenerate( + enum wc_HashType hash_type, enum wc_SignatureType sig_type, + const byte* data, word32 data_len, + byte* sig, word32 *sig_len, + const void* key, word32 key_len, + WC_RNG* rng); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLF_CRYPT_SIGNATURE_H */ diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/sp.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/sp.h new file mode 100755 index 0000000..e53fca0 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/sp.h @@ -0,0 +1,122 @@ +/* sp.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifndef WOLF_CRYPT_SP_H +#define WOLF_CRYPT_SP_H + +#include + +#if defined(WOLFSSL_HAVE_SP_RSA) || defined(WOLFSSL_HAVE_SP_DH) || \ + defined(WOLFSSL_HAVE_SP_ECC) + +#include + +#include +#include + +#include + +#if defined(_MSC_VER) + #define SP_NOINLINE __declspec(noinline) +#elif defined(__GNUC__) + #define SP_NOINLINE __attribute__((noinline)) +#else + #define SP_NOINLINE +#endif + + +#ifdef __cplusplus + extern "C" { +#endif + +#ifdef WOLFSSL_HAVE_SP_RSA + +WOLFSSL_LOCAL int sp_RsaPublic_2048(const byte* in, word32 inLen, + mp_int* em, mp_int* mm, byte* out, word32* outLen); +WOLFSSL_LOCAL int sp_RsaPrivate_2048(const byte* in, word32 inLen, + mp_int* dm, mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, + mp_int* mm, byte* out, word32* outLen); + +WOLFSSL_LOCAL int sp_RsaPublic_3072(const byte* in, word32 inLen, + mp_int* em, mp_int* mm, byte* out, word32* outLen); +WOLFSSL_LOCAL int sp_RsaPrivate_3072(const byte* in, word32 inLen, + mp_int* dm, mp_int* pm, mp_int* qm, mp_int* dpm, mp_int* dqm, mp_int* qim, + mp_int* mm, byte* out, word32* outLen); + +#endif /* WOLFSSL_HAVE_SP_RSA */ + +#if defined(WOLFSSL_HAVE_SP_DH) || defined(WOLFSSL_HAVE_SP_RSA) + +WOLFSSL_LOCAL int sp_ModExp_1024(mp_int* base, mp_int* exp, mp_int* mod, + mp_int* res); +WOLFSSL_LOCAL int sp_ModExp_1536(mp_int* base, mp_int* exp, mp_int* mod, + mp_int* res); +WOLFSSL_LOCAL int sp_ModExp_2048(mp_int* base, mp_int* exp, mp_int* mod, + mp_int* res); +WOLFSSL_LOCAL int sp_ModExp_3072(mp_int* base, mp_int* exp, mp_int* mod, + mp_int* res); + +#endif + +#ifdef WOLFSSL_HAVE_SP_DH + +WOLFSSL_LOCAL int sp_DhExp_2048(mp_int* base, const byte* exp, word32 expLen, + mp_int* mod, byte* out, word32* outLen); +WOLFSSL_LOCAL int sp_DhExp_3072(mp_int* base, const byte* exp, word32 expLen, + mp_int* mod, byte* out, word32* outLen); + +#endif /* WOLFSSL_HAVE_SP_DH */ + +#ifdef WOLFSSL_HAVE_SP_ECC + +int sp_ecc_mulmod_256(mp_int* km, ecc_point* gm, ecc_point* rm, int map, + void* heap); +int sp_ecc_mulmod_base_256(mp_int* km, ecc_point* rm, int map, void* heap); + +int sp_ecc_make_key_256(WC_RNG* rng, mp_int* priv, ecc_point* pub, void* heap); +int sp_ecc_secret_gen_256(mp_int* priv, ecc_point* pub, byte* out, + word32* outlen, void* heap); +int sp_ecc_sign_256(const byte* hash, word32 hashLen, WC_RNG* rng, mp_int* priv, + mp_int* rm, mp_int* sm, void* heap); +int sp_ecc_verify_256(const byte* hash, word32 hashLen, mp_int* pX, mp_int* pY, + mp_int* pZ, mp_int* r, mp_int* sm, int* res, void* heap); +int sp_ecc_is_point_256(mp_int* pX, mp_int* pY); +int sp_ecc_check_key_256(mp_int* pX, mp_int* pY, mp_int* privm, void* heap); +int sp_ecc_proj_add_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* qX, mp_int* qY, mp_int* qZ, + mp_int* rX, mp_int* rY, mp_int* rZ); +int sp_ecc_proj_dbl_point_256(mp_int* pX, mp_int* pY, mp_int* pZ, + mp_int* rX, mp_int* rY, mp_int* rZ); +int sp_ecc_map_256(mp_int* pX, mp_int* pY, mp_int* pZ); +int sp_ecc_uncompress_256(mp_int* xm, int odd, mp_int* ym); + +#endif /*ifdef WOLFSSL_HAVE_SP_ECC */ + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLFSSL_HAVE_SP_RSA || WOLFSSL_HAVE_SP_DH || WOLFSSL_HAVE_SP_ECC */ + +#endif /* WOLF_CRYPT_SP_H */ + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/sp_int.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/sp_int.h new file mode 100755 index 0000000..ba69e15 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/sp_int.h @@ -0,0 +1,206 @@ +/* sp_int.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +#ifndef WOLF_CRYPT_SP_INT_H +#define WOLF_CRYPT_SP_INT_H + +#include +#include + +/* Make sure WOLFSSL_SP_ASM build option defined when requested */ +#if !defined(WOLFSSL_SP_ASM) && ( \ + defined(WOLFSSL_SP_X86_64_ASM) || defined(WOLFSSL_SP_ARM32_ASM) || \ + defined(WOLFSSL_SP_ARM64_ASM) || defined(WOLFSSL_SP_ARM_THUMB_ASM) || \ + defined(WOLFSSL_SP_ARM_CORTEX_M_ASM)) + #define WOLFSSL_SP_ASM +#endif + + +#ifdef WOLFSSL_SP_X86_64_ASM + #define SP_WORD_SIZE 64 + + #define HAVE_INTEL_AVX1 + #define HAVE_INTEL_AVX2 +#elif defined(WOLFSSL_SP_ARM64_ASM) + #define SP_WORD_SIZE 64 +#elif defined(WOLFSSL_SP_ARM32_ASM) + #define SP_WORD_SIZE 32 +#elif defined(WOLFSSL_SP_ARM_THUMB_ASM) + #define SP_WORD_SIZE 32 +#endif + +#ifndef SP_WORD_SIZE + #if defined(NO_64BIT) || !defined(HAVE___UINT128_T) + #define SP_WORD_SIZE 32 + #else + #define SP_WORD_SIZE 64 + #endif +#endif + +#ifndef WOLFSSL_SP_ASM + #if SP_WORD_SIZE == 32 + typedef int32_t sp_digit; + typedef uint32_t sp_int_digit; + #elif SP_WORD_SIZE == 64 + typedef int64_t sp_digit; + typedef uint64_t sp_int_digit; + typedef unsigned long uint128_t __attribute__ ((mode(TI))); + typedef long int128_t __attribute__ ((mode(TI))); + #else + #error Word size not defined + #endif +#else + #if SP_WORD_SIZE == 32 + typedef uint32_t sp_digit; + typedef uint32_t sp_int_digit; + #elif SP_WORD_SIZE == 64 + typedef uint64_t sp_digit; + typedef uint64_t sp_int_digit; + typedef unsigned long uint128_t __attribute__ ((mode(TI))); + typedef long int128_t __attribute__ ((mode(TI))); + #else + #error Word size not defined + #endif +#endif + +#ifdef WOLFSSL_SP_MATH +#include + +#if !defined(WOLFSSL_HAVE_SP_RSA) && !defined(WOLFSSL_HAVE_SP_DH) + #if !defined(NO_PWDBASED) && defined(WOLFSSL_SHA512) + #define SP_INT_DIGITS ((512 + SP_WORD_SIZE) / SP_WORD_SIZE) + #else + #define SP_INT_DIGITS ((256 + SP_WORD_SIZE) / SP_WORD_SIZE) + #endif +#elif defined(WOLFSSL_SP_NO_3072) + #define SP_INT_DIGITS ((2048 + SP_WORD_SIZE) / SP_WORD_SIZE) +#else + #define SP_INT_DIGITS ((3072 + SP_WORD_SIZE) / SP_WORD_SIZE) +#endif + +#define sp_isodd(a) (a->used != 0 && (a->dp[0] & 1)) + +#ifdef HAVE_WOLF_BIGINT + /* raw big integer */ + typedef struct WC_BIGINT { + byte* buf; + word32 len; + void* heap; + } WC_BIGINT; + #define WOLF_BIGINT_DEFINED +#endif + +typedef struct sp_int { + int used; + int size; + sp_int_digit dp[SP_INT_DIGITS]; +#ifdef HAVE_WOLF_BIGINT + struct WC_BIGINT raw; /* unsigned binary (big endian) */ +#endif +} sp_int; + +typedef sp_int mp_int; +typedef sp_digit mp_digit; + +#include + + +MP_API int sp_init(sp_int* a); +MP_API int sp_init_multi(sp_int* a, sp_int* b, sp_int* c, sp_int* d, + sp_int* e, sp_int* f); +MP_API void sp_clear(sp_int* a); +MP_API int sp_unsigned_bin_size(sp_int* a); +MP_API int sp_read_unsigned_bin(sp_int* a, const byte* in, word32 inSz); +MP_API int sp_read_radix(sp_int* a, const char* in, int radix); +MP_API int sp_cmp(sp_int* a, sp_int* b); +MP_API int sp_count_bits(sp_int* a); +MP_API int sp_leading_bit(sp_int* a); +MP_API int sp_to_unsigned_bin(sp_int* a, byte* out); +MP_API int sp_to_unsigned_bin_len(sp_int* a, byte* out, int outSz); +MP_API void sp_forcezero(sp_int* a); +MP_API int sp_copy(sp_int* a, sp_int* b); +MP_API int sp_set(sp_int* a, sp_int_digit d); +MP_API int sp_iszero(sp_int* a); +MP_API void sp_clamp(sp_int* a); +MP_API int sp_grow(sp_int* a, int l); +MP_API int sp_sub_d(sp_int* a, sp_int_digit d, sp_int* r); +MP_API int sp_cmp_d(sp_int* a, sp_int_digit d); +MP_API int sp_mod(sp_int* a, sp_int* m, sp_int* r); +MP_API void sp_zero(sp_int* a); +MP_API int sp_add_d(sp_int* a, sp_int_digit d, sp_int* r); +MP_API int sp_lshd(sp_int* a, int s); +MP_API int sp_add(sp_int* a, sp_int* b, sp_int* r); +MP_API int sp_set_int(sp_int* a, unsigned long b); +MP_API int sp_tohex(sp_int* a, char* str); + + +#define MP_OKAY 0 +#define MP_NO 0 +#define MP_YES 1 + +#define MP_RADIX_HEX 16 + +#define MP_GT 1 +#define MP_EQ 0 +#define MP_LT -1 + +#define MP_MEM -2 +#define MP_VAL -3 + +#define DIGIT_BIT SP_WORD_SIZE + +#define CheckFastMathSettings() 1 + +#define mp_free(a) + +#define mp_init sp_init +#define mp_init_multi sp_init_multi +#define mp_clear sp_clear +#define mp_read_unsigned_bin sp_read_unsigned_bin +#define mp_unsigned_bin_size sp_unsigned_bin_size +#define mp_read_radix sp_read_radix +#define mp_cmp sp_cmp +#define mp_count_bits sp_count_bits +#define mp_leading_bit sp_leading_bit +#define mp_to_unsigned_bin sp_to_unsigned_bin +#define mp_to_unsigned_bin_len sp_to_unsigned_bin_len +#define mp_forcezero sp_forcezero +#define mp_copy sp_copy +#define mp_set sp_set +#define mp_iszero sp_iszero +#define mp_clamp sp_clamp +#define mp_grow sp_grow +#define mp_sub_d sp_sub_d +#define mp_cmp_d sp_cmp_d +#define mp_mod sp_mod +#define mp_zero sp_zero +#define mp_add_d sp_add_d +#define mp_lshd sp_lshd +#define mp_add sp_add +#define mp_isodd sp_isodd +#define mp_set_int sp_set_int +#define mp_tohex sp_tohex + +#endif + +#endif /* WOLF_CRYPT_SP_H */ + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/srp.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/srp.h new file mode 100755 index 0000000..85db198 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/srp.h @@ -0,0 +1,311 @@ +/* srp.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/*! + \file wolfssl/wolfcrypt/srp.h +*/ + +#ifdef WOLFCRYPT_HAVE_SRP + +#ifndef WOLFCRYPT_SRP_H +#define WOLFCRYPT_SRP_H + +#include +#include +#include +#include +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/* Select the largest available hash for the buffer size. */ +#if defined(WOLFSSL_SHA512) + #define SRP_MAX_DIGEST_SIZE WC_SHA512_DIGEST_SIZE +#elif defined(WOLFSSL_SHA384) + #define SRP_MAX_DIGEST_SIZE WC_SHA384_DIGEST_SIZE +#elif !defined(NO_SHA256) + #define SRP_MAX_DIGEST_SIZE WC_SHA256_DIGEST_SIZE +#elif !defined(NO_SHA) + #define SRP_MAX_DIGEST_SIZE WC_SHA_DIGEST_SIZE +#else + #error "You have to have some kind of SHA hash if you want to use SRP." +#endif + +/* Set the minimum number of bits acceptable in an SRP modulus */ +#define SRP_MODULUS_MIN_BITS 512 + +/* Set the minimum number of bits acceptable for private keys (RFC 5054) */ +#define SRP_PRIVATE_KEY_MIN_BITS 256 + +/* salt size for SRP password */ +#define SRP_SALT_SIZE 16 + +/** + * SRP side, client or server. + */ +typedef enum { + SRP_CLIENT_SIDE = 0, + SRP_SERVER_SIDE = 1, +} SrpSide; + +/** + * SRP hash type, SHA[1|256|384|512]. + */ +typedef enum { + SRP_TYPE_SHA = 1, + SRP_TYPE_SHA256 = 2, + SRP_TYPE_SHA384 = 3, + SRP_TYPE_SHA512 = 4, +} SrpType; + + +/** + * SRP hash struct. + */ +typedef struct { + byte type; + union { + #ifndef NO_SHA + wc_Sha sha; + #endif + #ifndef NO_SHA256 + wc_Sha256 sha256; + #endif + #ifdef WOLFSSL_SHA384 + wc_Sha384 sha384; + #endif + #ifdef WOLFSSL_SHA512 + wc_Sha512 sha512; + #endif + } data; +} SrpHash; + +typedef struct Srp { + SrpSide side; /**< Client or Server, @see SrpSide. */ + SrpType type; /**< Hash type, @see SrpType. */ + byte* user; /**< Username, login. */ + word32 userSz; /**< Username length. */ + byte* salt; /**< Small salt. */ + word32 saltSz; /**< Salt length. */ + mp_int N; /**< Modulus. N = 2q+1, [q, N] are primes.*/ + mp_int g; /**< Generator. A generator modulo N. */ + byte k[SRP_MAX_DIGEST_SIZE]; /**< Multiplier parameter. k = H(N, g) */ + mp_int auth; /**< Client: x = H(salt + H(user:pswd)) */ + /**< Server: v = g ^ x % N */ + mp_int priv; /**< Private ephemeral value. */ + SrpHash client_proof; /**< Client proof. Sent to the Server. */ + SrpHash server_proof; /**< Server proof. Sent to the Client. */ + byte* key; /**< Session key. */ + word32 keySz; /**< Session key length. */ + int (*keyGenFunc_cb) (struct Srp* srp, byte* secret, word32 size); + /**< Function responsible for generating the session key. */ + /**< It MUST use XMALLOC with type DYNAMIC_TYPE_SRP to allocate the */ + /**< key buffer for this structure and set keySz to the buffer size. */ + /**< The default function used by this implementation is a modified */ + /**< version of t_mgf1 that uses the proper hash function according */ + /**< to srp->type. */ + void* heap; /**< heap hint pointer */ +} Srp; + +/** + * Initializes the Srp struct for usage. + * + * @param[out] srp the Srp structure to be initialized. + * @param[in] type the hash type to be used. + * @param[in] side the side of the communication. + * + * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h + */ +WOLFSSL_API int wc_SrpInit(Srp* srp, SrpType type, SrpSide side); + +/** + * Releases the Srp struct resources after usage. + * + * @param[in,out] srp the Srp structure to be terminated. + */ +WOLFSSL_API void wc_SrpTerm(Srp* srp); + +/** + * Sets the username. + * + * This function MUST be called after wc_SrpInit. + * + * @param[in,out] srp the Srp structure. + * @param[in] username the buffer containing the username. + * @param[in] size the username size in bytes + * + * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h + */ +WOLFSSL_API int wc_SrpSetUsername(Srp* srp, const byte* username, word32 size); + + +/** + * Sets the srp parameters based on the username. + * + * This function MUST be called after wc_SrpSetUsername. + * + * @param[in,out] srp the Srp structure. + * @param[in] N the Modulus. N = 2q+1, [q, N] are primes. + * @param[in] nSz the N size in bytes. + * @param[in] g the Generator modulo N. + * @param[in] gSz the g size in bytes + * @param[in] salt a small random salt. Specific for each username. + * @param[in] saltSz the salt size in bytes + * + * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h + */ +WOLFSSL_API int wc_SrpSetParams(Srp* srp, const byte* N, word32 nSz, + const byte* g, word32 gSz, + const byte* salt, word32 saltSz); + +/** + * Sets the password. + * + * Setting the password does not persists the clear password data in the + * srp structure. The client calculates x = H(salt + H(user:pswd)) and stores + * it in the auth field. + * + * This function MUST be called after wc_SrpSetParams and is CLIENT SIDE ONLY. + * + * @param[in,out] srp the Srp structure. + * @param[in] password the buffer containing the password. + * @param[in] size the password size in bytes. + * + * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h + */ +WOLFSSL_API int wc_SrpSetPassword(Srp* srp, const byte* password, word32 size); + +/** + * Sets the verifier. + * + * This function MUST be called after wc_SrpSetParams and is SERVER SIDE ONLY. + * + * @param[in,out] srp the Srp structure. + * @param[in] verifier the buffer containing the verifier. + * @param[in] size the verifier size in bytes. + * + * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h + */ +WOLFSSL_API int wc_SrpSetVerifier(Srp* srp, const byte* verifier, word32 size); + +/** + * Gets the verifier. + * + * The client calculates the verifier with v = g ^ x % N. + * This function MAY be called after wc_SrpSetPassword and is CLIENT SIDE ONLY. + * + * @param[in,out] srp the Srp structure. + * @param[out] verifier the buffer to write the verifier. + * @param[in,out] size the buffer size in bytes. Will be updated with the + * verifier size. + * + * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h + */ +WOLFSSL_API int wc_SrpGetVerifier(Srp* srp, byte* verifier, word32* size); + +/** + * Sets the private ephemeral value. + * + * The private ephemeral value is known as: + * a at the client side. a = random() + * b at the server side. b = random() + * This function is handy for unit test cases or if the developer wants to use + * an external random source to set the ephemeral value. + * This function MAY be called before wc_SrpGetPublic. + * + * @param[in,out] srp the Srp structure. + * @param[in] priv the ephemeral value. + * @param[in] size the private size in bytes. + * + * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h + */ +WOLFSSL_API int wc_SrpSetPrivate(Srp* srp, const byte* priv, word32 size); + +/** + * Gets the public ephemeral value. + * + * The public ephemeral value is known as: + * A at the client side. A = g ^ a % N + * B at the server side. B = (k * v + (g ˆ b % N)) % N + * This function MUST be called after wc_SrpSetPassword or wc_SrpSetVerifier. + * + * @param[in,out] srp the Srp structure. + * @param[out] pub the buffer to write the public ephemeral value. + * @param[in,out] size the the buffer size in bytes. Will be updated with + * the ephemeral value size. + * + * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h + */ +WOLFSSL_API int wc_SrpGetPublic(Srp* srp, byte* pub, word32* size); + + +/** + * Computes the session key. + * + * The key can be accessed at srp->key after success. + * + * @param[in,out] srp the Srp structure. + * @param[in] clientPubKey the client's public ephemeral value. + * @param[in] clientPubKeySz the client's public ephemeral value size. + * @param[in] serverPubKey the server's public ephemeral value. + * @param[in] serverPubKeySz the server's public ephemeral value size. + * + * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h + */ +WOLFSSL_API int wc_SrpComputeKey(Srp* srp, + byte* clientPubKey, word32 clientPubKeySz, + byte* serverPubKey, word32 serverPubKeySz); + +/** + * Gets the proof. + * + * This function MUST be called after wc_SrpComputeKey. + * + * @param[in,out] srp the Srp structure. + * @param[out] proof the buffer to write the proof. + * @param[in,out] size the buffer size in bytes. Will be updated with the + * proof size. + * + * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h + */ +WOLFSSL_API int wc_SrpGetProof(Srp* srp, byte* proof, word32* size); + +/** + * Verifies the peers proof. + * + * This function MUST be called before wc_SrpGetSessionKey. + * + * @param[in,out] srp the Srp structure. + * @param[in] proof the peers proof. + * @param[in] size the proof size in bytes. + * + * @return 0 on success, {@literal <} 0 on error. @see error-crypt.h + */ +WOLFSSL_API int wc_SrpVerifyPeersProof(Srp* srp, byte* proof, word32 size); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLFCRYPT_SRP_H */ +#endif /* WOLFCRYPT_HAVE_SRP */ diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/tfm.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/tfm.h new file mode 100755 index 0000000..22bc627 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/tfm.h @@ -0,0 +1,823 @@ +/* tfm.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + + +/* + * Based on public domain TomsFastMath 0.10 by Tom St Denis, tomstdenis@iahu.ca, + * http://math.libtomcrypt.com + */ + + +/** + * Edited by Moises Guimaraes (moises.guimaraes@phoebus.com.br) + * to fit CyaSSL's needs. + */ + +/*! + \file wolfssl/wolfcrypt/tfm.h +*/ + +#ifndef WOLF_CRYPT_TFM_H +#define WOLF_CRYPT_TFM_H + +#include +#ifndef CHAR_BIT + #include +#endif + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +#ifdef WOLFSSL_NO_ASM + #undef TFM_NO_ASM + #define TFM_NO_ASM +#endif + +#ifdef NO_64BIT + #undef NO_TFM_64BIT + #define NO_TFM_64BIT +#endif + +#ifndef NO_TFM_64BIT +/* autodetect x86-64 and make sure we are using 64-bit digits with x86-64 asm */ +#if defined(__x86_64__) + #if defined(TFM_X86) || defined(TFM_SSE2) || defined(TFM_ARM) + #error x86-64 detected, x86-32/SSE2/ARM optimizations are not valid! + #endif + #if !defined(TFM_X86_64) && !defined(TFM_NO_ASM) + #define TFM_X86_64 + #endif +#endif +#if defined(TFM_X86_64) + #if !defined(FP_64BIT) + #define FP_64BIT + #endif +#endif +/* use 64-bit digit even if not using asm on x86_64 */ +#if defined(__x86_64__) && !defined(FP_64BIT) + #define FP_64BIT +#endif +/* if intel compiler doesn't provide 128 bit type don't turn on 64bit */ +#if defined(FP_64BIT) && defined(__INTEL_COMPILER) && !defined(HAVE___UINT128_T) + #undef FP_64BIT + #undef TFM_X86_64 +#endif +#endif /* NO_TFM_64BIT */ + +/* try to detect x86-32 */ +#if defined(__i386__) && !defined(TFM_SSE2) + #if defined(TFM_X86_64) || defined(TFM_ARM) + #error x86-32 detected, x86-64/ARM optimizations are not valid! + #endif + #if !defined(TFM_X86) && !defined(TFM_NO_ASM) + #define TFM_X86 + #endif +#endif + +/* make sure we're 32-bit for x86-32/sse/arm/ppc32 */ +#if (defined(TFM_X86) || defined(TFM_SSE2) || defined(TFM_ARM) || defined(TFM_PPC32)) && defined(FP_64BIT) + #warning x86-32, SSE2 and ARM, PPC32 optimizations require 32-bit digits (undefining) + #undef FP_64BIT +#endif + +/* multi asms? */ +#ifdef TFM_X86 + #define TFM_ASM +#endif +#ifdef TFM_X86_64 + #ifdef TFM_ASM + #error TFM_ASM already defined! + #endif + #define TFM_ASM +#endif +#ifdef TFM_SSE2 + #ifdef TFM_ASM + #error TFM_ASM already defined! + #endif + #define TFM_ASM +#endif +#ifdef TFM_ARM + #ifdef TFM_ASM + #error TFM_ASM already defined! + #endif + #define TFM_ASM +#endif +#ifdef TFM_PPC32 + #ifdef TFM_ASM + #error TFM_ASM already defined! + #endif + #define TFM_ASM +#endif +#ifdef TFM_PPC64 + #ifdef TFM_ASM + #error TFM_ASM already defined! + #endif + #define TFM_ASM +#endif +#ifdef TFM_AVR32 + #ifdef TFM_ASM + #error TFM_ASM already defined! + #endif + #define TFM_ASM +#endif + +/* we want no asm? */ +#ifdef TFM_NO_ASM + #undef TFM_X86 + #undef TFM_X86_64 + #undef TFM_SSE2 + #undef TFM_ARM + #undef TFM_PPC32 + #undef TFM_PPC64 + #undef TFM_AVR32 + #undef TFM_ASM +#endif + +/* ECC helpers */ +#ifdef TFM_ECC192 + #ifdef FP_64BIT + #define TFM_MUL3 + #define TFM_SQR3 + #else + #define TFM_MUL6 + #define TFM_SQR6 + #endif +#endif + +#ifdef TFM_ECC224 + #ifdef FP_64BIT + #define TFM_MUL4 + #define TFM_SQR4 + #else + #define TFM_MUL7 + #define TFM_SQR7 + #endif +#endif + +#ifdef TFM_ECC256 + #ifdef FP_64BIT + #define TFM_MUL4 + #define TFM_SQR4 + #else + #define TFM_MUL8 + #define TFM_SQR8 + #endif +#endif + +#ifdef TFM_ECC384 + #ifdef FP_64BIT + #define TFM_MUL6 + #define TFM_SQR6 + #else + #define TFM_MUL12 + #define TFM_SQR12 + #endif +#endif + +#ifdef TFM_ECC521 + #ifdef FP_64BIT + #define TFM_MUL9 + #define TFM_SQR9 + #else + #define TFM_MUL17 + #define TFM_SQR17 + #endif +#endif + + +/* allow user to define on fp_digit, fp_word types */ +#ifndef WOLFSSL_BIGINT_TYPES + +/* some default configurations. + */ +#if defined(WC_16BIT_CPU) + typedef unsigned int fp_digit; + #define SIZEOF_FP_DIGIT 2 + typedef unsigned long fp_word; +#elif defined(FP_64BIT) + /* for GCC only on supported platforms */ + typedef unsigned long long fp_digit; /* 64bit, 128 uses mode(TI) below */ + #define SIZEOF_FP_DIGIT 8 + typedef unsigned long fp_word __attribute__ ((mode(TI))); +#else + + #ifndef NO_TFM_64BIT + #if defined(_MSC_VER) || defined(__BORLANDC__) + typedef unsigned __int64 ulong64; + #else + typedef unsigned long long ulong64; + #endif + typedef unsigned int fp_digit; + #define SIZEOF_FP_DIGIT 4 + typedef ulong64 fp_word; + #define FP_32BIT + #else + /* some procs like coldfire prefer not to place multiply into 64bit type + even though it exists */ + typedef unsigned short fp_digit; + #define SIZEOF_FP_DIGIT 2 + typedef unsigned int fp_word; + #endif +#endif + +#endif /* WOLFSSL_BIGINT_TYPES */ + + +/* # of digits this is */ +#define DIGIT_BIT ((CHAR_BIT) * SIZEOF_FP_DIGIT) + +/* Max size of any number in bits. Basically the largest size you will be + * multiplying should be half [or smaller] of FP_MAX_SIZE-four_digit + * + * It defaults to 4096-bits [allowing multiplications up to 2048x2048 bits ] + */ + + +#ifndef FP_MAX_BITS + #define FP_MAX_BITS 4096 +#endif +#define FP_MAX_SIZE (FP_MAX_BITS+(8*DIGIT_BIT)) + +/* will this lib work? */ +#if (CHAR_BIT & 7) + #error CHAR_BIT must be a multiple of eight. +#endif +#if FP_MAX_BITS % CHAR_BIT + #error FP_MAX_BITS must be a multiple of CHAR_BIT +#endif + +#define FP_MASK (fp_digit)(-1) +#define FP_DIGIT_MAX FP_MASK +#define FP_SIZE (FP_MAX_SIZE/DIGIT_BIT) + +#define FP_MAX_PRIME_SIZE (FP_MAX_BITS/(2*CHAR_BIT)) +/* In terms of FP_MAX_BITS, it is double the size possible for a number + * to allow for multiplication, divide that 2 out. Also divide by CHAR_BIT + * to convert from bits to bytes. (Note, FP_PRIME_SIZE is the number of + * values in the canned prime number list.) */ + +/* signs */ +#define FP_ZPOS 0 +#define FP_NEG 1 + +/* return codes */ +#define FP_OKAY 0 +#define FP_VAL -1 +#define FP_MEM -2 +#define FP_NOT_INF -3 +#define FP_WOULDBLOCK -4 + +/* equalities */ +#define FP_LT -1 /* less than */ +#define FP_EQ 0 /* equal to */ +#define FP_GT 1 /* greater than */ + +/* replies */ +#define FP_YES 1 /* yes response */ +#define FP_NO 0 /* no response */ + +#ifdef HAVE_WOLF_BIGINT + /* raw big integer */ + typedef struct WC_BIGINT { + byte* buf; + word32 len; + void* heap; + } WC_BIGINT; + #define WOLF_BIGINT_DEFINED +#endif + +/* a FP type */ +typedef struct fp_int { + int used; + int sign; +#if defined(ALT_ECC_SIZE) || defined(HAVE_WOLF_BIGINT) + int size; +#endif + fp_digit dp[FP_SIZE]; + +#ifdef HAVE_WOLF_BIGINT + struct WC_BIGINT raw; /* unsigned binary (big endian) */ +#endif +} fp_int; + +/* Types */ +typedef fp_digit mp_digit; +typedef fp_word mp_word; +typedef fp_int mp_int; + + +/* wolf big int and common functions */ +#include + + +/* externally define this symbol to ignore the default settings, useful for changing the build from the make process */ +#ifndef TFM_ALREADY_SET + +/* do we want the large set of small multiplications ? + Enable these if you are going to be doing a lot of small (<= 16 digit) multiplications say in ECC + Or if you're on a 64-bit machine doing RSA as a 1024-bit integer == 16 digits ;-) + */ +/* need to refactor the function */ +/*#define TFM_SMALL_SET */ + +/* do we want huge code + Enable these if you are doing 20, 24, 28, 32, 48, 64 digit multiplications (useful for RSA) + Less important on 64-bit machines as 32 digits == 2048 bits + */ +#if 0 +#define TFM_MUL3 +#define TFM_MUL4 +#define TFM_MUL6 +#define TFM_MUL7 +#define TFM_MUL8 +#define TFM_MUL9 +#define TFM_MUL12 +#define TFM_MUL17 +#endif +#ifdef TFM_HUGE_SET +#define TFM_MUL20 +#define TFM_MUL24 +#define TFM_MUL28 +#define TFM_MUL32 +#if (FP_MAX_BITS >= 6144) && defined(FP_64BIT) + #define TFM_MUL48 +#endif +#if (FP_MAX_BITS >= 8192) && defined(FP_64BIT) + #define TFM_MUL64 +#endif +#endif + +#if 0 +#define TFM_SQR3 +#define TFM_SQR4 +#define TFM_SQR6 +#define TFM_SQR7 +#define TFM_SQR8 +#define TFM_SQR9 +#define TFM_SQR12 +#define TFM_SQR17 +#endif +#ifdef TFM_HUGE_SET +#define TFM_SQR20 +#define TFM_SQR24 +#define TFM_SQR28 +#define TFM_SQR32 +#define TFM_SQR48 +#define TFM_SQR64 +#endif + +/* Optional math checks (enable WOLFSSL_DEBUG_MATH to print info) */ +/* #define TFM_CHECK */ + +/* Is the target a P4 Prescott + */ +/* #define TFM_PRESCOTT */ + +/* Do we want timing resistant fp_exptmod() ? + * This makes it slower but also timing invariant with respect to the exponent + */ +/* #define TFM_TIMING_RESISTANT */ + +#endif /* TFM_ALREADY_SET */ + +/* functions */ + +/* returns a TFM ident string useful for debugging... */ +/*const char *fp_ident(void);*/ + +/* initialize [or zero] an fp int */ +void fp_init(fp_int *a); +MP_API void fp_zero(fp_int *a); +MP_API void fp_clear(fp_int *a); /* uses ForceZero to clear sensitive memory */ +MP_API void fp_forcezero (fp_int * a); +MP_API void fp_free(fp_int* a); + +/* zero/even/odd ? */ +#define fp_iszero(a) (((a)->used == 0) ? FP_YES : FP_NO) +#define fp_isone(a) \ + ((((a)->used == 1) && ((a)->dp[0] == 1)) ? FP_YES : FP_NO) +#define fp_iseven(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 0)) ? FP_YES : FP_NO) +#define fp_isodd(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? FP_YES : FP_NO) +#define fp_isneg(a) (((a)->sign != 0) ? FP_YES : FP_NO) + +/* set to a small digit */ +void fp_set(fp_int *a, fp_digit b); +void fp_set_int(fp_int *a, unsigned long b); + +/* check if a bit is set */ +int fp_is_bit_set(fp_int *a, fp_digit b); +/* set the b bit to 1 */ +int fp_set_bit (fp_int * a, fp_digit b); + +/* copy from a to b */ +void fp_copy(fp_int *a, fp_int *b); +void fp_init_copy(fp_int *a, fp_int *b); + +/* clamp digits */ +#define fp_clamp(a) { while ((a)->used && (a)->dp[(a)->used-1] == 0) --((a)->used); (a)->sign = (a)->used ? (a)->sign : FP_ZPOS; } +#define mp_clamp(a) fp_clamp(a) +#define mp_grow(a,s) MP_OKAY + +/* negate and absolute */ +#define fp_neg(a, b) { fp_copy(a, b); (b)->sign ^= 1; fp_clamp(b); } +#define fp_abs(a, b) { fp_copy(a, b); (b)->sign = 0; } + +/* right shift x digits */ +void fp_rshd(fp_int *a, int x); + +/* right shift x bits */ +void fp_rshb(fp_int *a, int x); + +/* left shift x digits */ +void fp_lshd(fp_int *a, int x); + +/* signed comparison */ +int fp_cmp(fp_int *a, fp_int *b); + +/* unsigned comparison */ +int fp_cmp_mag(fp_int *a, fp_int *b); + +/* power of 2 operations */ +void fp_div_2d(fp_int *a, int b, fp_int *c, fp_int *d); +void fp_mod_2d(fp_int *a, int b, fp_int *c); +void fp_mul_2d(fp_int *a, int b, fp_int *c); +void fp_2expt (fp_int *a, int b); +void fp_mul_2(fp_int *a, fp_int *c); +void fp_div_2(fp_int *a, fp_int *c); + +/* Counts the number of lsbs which are zero before the first zero bit */ +int fp_cnt_lsb(fp_int *a); + +/* c = a + b */ +void fp_add(fp_int *a, fp_int *b, fp_int *c); + +/* c = a - b */ +void fp_sub(fp_int *a, fp_int *b, fp_int *c); + +/* c = a * b */ +int fp_mul(fp_int *a, fp_int *b, fp_int *c); + +/* b = a*a */ +int fp_sqr(fp_int *a, fp_int *b); + +/* a/b => cb + d == a */ +int fp_div(fp_int *a, fp_int *b, fp_int *c, fp_int *d); + +/* c = a mod b, 0 <= c < b */ +int fp_mod(fp_int *a, fp_int *b, fp_int *c); + +/* compare against a single digit */ +int fp_cmp_d(fp_int *a, fp_digit b); + +/* c = a + b */ +void fp_add_d(fp_int *a, fp_digit b, fp_int *c); + +/* c = a - b */ +int fp_sub_d(fp_int *a, fp_digit b, fp_int *c); + +/* c = a * b */ +void fp_mul_d(fp_int *a, fp_digit b, fp_int *c); + +/* a/b => cb + d == a */ +/*int fp_div_d(fp_int *a, fp_digit b, fp_int *c, fp_digit *d);*/ + +/* c = a mod b, 0 <= c < b */ +/*int fp_mod_d(fp_int *a, fp_digit b, fp_digit *c);*/ + +/* ---> number theory <--- */ +/* d = a + b (mod c) */ +/*int fp_addmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d);*/ + +/* d = a - b (mod c) */ +/*int fp_submod(fp_int *a, fp_int *b, fp_int *c, fp_int *d);*/ + +/* d = a * b (mod c) */ +int fp_mulmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d); + +/* d = a - b (mod c) */ +int fp_submod(fp_int *a, fp_int *b, fp_int *c, fp_int *d); + +/* d = a + b (mod c) */ +int fp_addmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d); + +/* c = a * a (mod b) */ +int fp_sqrmod(fp_int *a, fp_int *b, fp_int *c); + +/* c = 1/a (mod b) */ +int fp_invmod(fp_int *a, fp_int *b, fp_int *c); + +/* c = (a, b) */ +/*int fp_gcd(fp_int *a, fp_int *b, fp_int *c);*/ + +/* c = [a, b] */ +/*int fp_lcm(fp_int *a, fp_int *b, fp_int *c);*/ + +/* setups the montgomery reduction */ +int fp_montgomery_setup(fp_int *a, fp_digit *mp); + +/* computes a = B**n mod b without division or multiplication useful for + * normalizing numbers in a Montgomery system. + */ +void fp_montgomery_calc_normalization(fp_int *a, fp_int *b); + +/* computes x/R == x (mod N) via Montgomery Reduction */ +int fp_montgomery_reduce(fp_int *a, fp_int *m, fp_digit mp); + +/* d = a**b (mod c) */ +int fp_exptmod(fp_int *a, fp_int *b, fp_int *c, fp_int *d); + +#ifdef WC_RSA_NONBLOCK + +enum tfmExptModNbState { + TFM_EXPTMOD_NB_INIT = 0, + TFM_EXPTMOD_NB_MONT, + TFM_EXPTMOD_NB_MONT_RED, + TFM_EXPTMOD_NB_MONT_MUL, + TFM_EXPTMOD_NB_MONT_MOD, + TFM_EXPTMOD_NB_MONT_MODCHK, + TFM_EXPTMOD_NB_NEXT, + TFM_EXPTMOD_NB_MUL, + TFM_EXPTMOD_NB_MUL_RED, + TFM_EXPTMOD_NB_SQR, + TFM_EXPTMOD_NB_SQR_RED, + TFM_EXPTMOD_NB_RED, + TFM_EXPTMOD_NB_COUNT /* last item for total state count only */ +}; + +typedef struct { +#ifndef WC_NO_CACHE_RESISTANT + fp_int R[3]; +#else + fp_int R[2]; +#endif + fp_digit buf; + fp_digit mp; + int bitcnt; + int digidx; + int y; + int state; /* tfmExptModNbState */ +#ifdef WC_RSA_NONBLOCK_TIME + word32 maxBlockInst; /* maximum instructions to block */ + word32 totalInst; /* tracks total instructions */ +#endif +} exptModNb_t; + +#ifdef WC_RSA_NONBLOCK_TIME +enum { + TFM_EXPTMOD_NB_STOP = 0, /* stop and return FP_WOULDBLOCK */ + TFM_EXPTMOD_NB_CONTINUE = 1, /* keep blocking */ +}; +#endif + +/* non-blocking version of timing resistant fp_exptmod function */ +/* supports cache resistance */ +int fp_exptmod_nb(exptModNb_t* nb, fp_int* G, fp_int* X, fp_int* P, fp_int* Y); + +#endif /* WC_RSA_NONBLOCK */ + +/* primality stuff */ + +/* perform a Miller-Rabin test of a to the base b and store result in "result" */ +/*void fp_prime_miller_rabin (fp_int * a, fp_int * b, int *result);*/ + +#define FP_PRIME_SIZE 256 +/* 256 trial divisions + 8 Miller-Rabins, returns FP_YES if probable prime */ +/*int fp_isprime(fp_int *a);*/ +/* extended version of fp_isprime, do 't' Miller-Rabins instead of only 8 */ +/*int fp_isprime_ex(fp_int *a, int t, int* result);*/ + +/* Primality generation flags */ +/*#define TFM_PRIME_BBS 0x0001 */ /* BBS style prime */ +/*#define TFM_PRIME_SAFE 0x0002 */ /* Safe prime (p-1)/2 == prime */ +/*#define TFM_PRIME_2MSB_OFF 0x0004 */ /* force 2nd MSB to 0 */ +/*#define TFM_PRIME_2MSB_ON 0x0008 */ /* force 2nd MSB to 1 */ + +/* callback for fp_prime_random, should fill dst with random bytes and return how many read [up to len] */ +/*typedef int tfm_prime_callback(unsigned char *dst, int len, void *dat);*/ + +/*#define fp_prime_random(a, t, size, bbs, cb, dat) fp_prime_random_ex(a, t, ((size) * 8) + 1, (bbs==1)?TFM_PRIME_BBS:0, cb, dat)*/ + +/*int fp_prime_random_ex(fp_int *a, int t, int size, int flags, tfm_prime_callback cb, void *dat);*/ + +/* radix conversions */ +int fp_count_bits(fp_int *a); +int fp_leading_bit(fp_int *a); + +int fp_unsigned_bin_size(fp_int *a); +void fp_read_unsigned_bin(fp_int *a, const unsigned char *b, int c); +int fp_to_unsigned_bin(fp_int *a, unsigned char *b); +int fp_to_unsigned_bin_len(fp_int *a, unsigned char *b, int c); +int fp_to_unsigned_bin_at_pos(int x, fp_int *t, unsigned char *b); + +/*int fp_signed_bin_size(fp_int *a);*/ +/*void fp_read_signed_bin(fp_int *a, const unsigned char *b, int c);*/ +/*void fp_to_signed_bin(fp_int *a, unsigned char *b);*/ + +/*int fp_read_radix(fp_int *a, char *str, int radix);*/ +/*int fp_toradix(fp_int *a, char *str, int radix);*/ +/*int fp_toradix_n(fp_int * a, char *str, int radix, int maxlen);*/ + + +/* VARIOUS LOW LEVEL STUFFS */ +void s_fp_add(fp_int *a, fp_int *b, fp_int *c); +void s_fp_sub(fp_int *a, fp_int *b, fp_int *c); +void fp_reverse(unsigned char *s, int len); + +int fp_mul_comba(fp_int *a, fp_int *b, fp_int *c); + +int fp_mul_comba_small(fp_int *a, fp_int *b, fp_int *c); +int fp_mul_comba3(fp_int *a, fp_int *b, fp_int *c); +int fp_mul_comba4(fp_int *a, fp_int *b, fp_int *c); +int fp_mul_comba6(fp_int *a, fp_int *b, fp_int *c); +int fp_mul_comba7(fp_int *a, fp_int *b, fp_int *c); +int fp_mul_comba8(fp_int *a, fp_int *b, fp_int *c); +int fp_mul_comba9(fp_int *a, fp_int *b, fp_int *c); +int fp_mul_comba12(fp_int *a, fp_int *b, fp_int *c); +int fp_mul_comba17(fp_int *a, fp_int *b, fp_int *c); +int fp_mul_comba20(fp_int *a, fp_int *b, fp_int *c); +int fp_mul_comba24(fp_int *a, fp_int *b, fp_int *c); +int fp_mul_comba28(fp_int *a, fp_int *b, fp_int *c); +int fp_mul_comba32(fp_int *a, fp_int *b, fp_int *c); +int fp_mul_comba48(fp_int *a, fp_int *b, fp_int *c); +int fp_mul_comba64(fp_int *a, fp_int *b, fp_int *c); +int fp_sqr_comba(fp_int *a, fp_int *b); +int fp_sqr_comba_small(fp_int *a, fp_int *b); +int fp_sqr_comba3(fp_int *a, fp_int *b); +int fp_sqr_comba4(fp_int *a, fp_int *b); +int fp_sqr_comba6(fp_int *a, fp_int *b); +int fp_sqr_comba7(fp_int *a, fp_int *b); +int fp_sqr_comba8(fp_int *a, fp_int *b); +int fp_sqr_comba9(fp_int *a, fp_int *b); +int fp_sqr_comba12(fp_int *a, fp_int *b); +int fp_sqr_comba17(fp_int *a, fp_int *b); +int fp_sqr_comba20(fp_int *a, fp_int *b); +int fp_sqr_comba24(fp_int *a, fp_int *b); +int fp_sqr_comba28(fp_int *a, fp_int *b); +int fp_sqr_comba32(fp_int *a, fp_int *b); +int fp_sqr_comba48(fp_int *a, fp_int *b); +int fp_sqr_comba64(fp_int *a, fp_int *b); + + +/** + * Used by wolfSSL + */ + +/* Constants */ +#define MP_LT FP_LT /* less than */ +#define MP_EQ FP_EQ /* equal to */ +#define MP_GT FP_GT /* greater than */ +#define MP_VAL FP_VAL /* invalid */ +#define MP_MEM FP_MEM /* memory error */ +#define MP_NOT_INF FP_NOT_INF /* point not at infinity */ +#define MP_OKAY FP_OKAY /* ok result */ +#define MP_NO FP_NO /* yes/no result */ +#define MP_YES FP_YES /* yes/no result */ +#define MP_ZPOS FP_ZPOS +#define MP_NEG FP_NEG +#define MP_MASK FP_MASK + +/* Prototypes */ +#define mp_zero(a) fp_zero(a) +#define mp_isone(a) fp_isone(a) +#define mp_iseven(a) fp_iseven(a) +#define mp_isneg(a) fp_isneg(a) + +#define MP_RADIX_BIN 2 +#define MP_RADIX_OCT 8 +#define MP_RADIX_DEC 10 +#define MP_RADIX_HEX 16 +#define MP_RADIX_MAX 64 + +#define mp_tobinary(M, S) mp_toradix((M), (S), MP_RADIX_BIN) +#define mp_tooctal(M, S) mp_toradix((M), (S), MP_RADIX_OCT) +#define mp_todecimal(M, S) mp_toradix((M), (S), MP_RADIX_DEC) +#define mp_tohex(M, S) mp_toradix((M), (S), MP_RADIX_HEX) + +MP_API int mp_init (mp_int * a); +MP_API void mp_clear (mp_int * a); +MP_API void mp_free (mp_int * a); +MP_API void mp_forcezero (mp_int * a); +MP_API int mp_init_multi(mp_int* a, mp_int* b, mp_int* c, mp_int* d, mp_int* e, + mp_int* f); + +MP_API int mp_add (mp_int * a, mp_int * b, mp_int * c); +MP_API int mp_sub (mp_int * a, mp_int * b, mp_int * c); +MP_API int mp_add_d (mp_int * a, mp_digit b, mp_int * c); + +MP_API int mp_mul (mp_int * a, mp_int * b, mp_int * c); +MP_API int mp_mul_d (mp_int * a, mp_digit b, mp_int * c); +MP_API int mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d); +MP_API int mp_submod (mp_int* a, mp_int* b, mp_int* c, mp_int* d); +MP_API int mp_addmod (mp_int* a, mp_int* b, mp_int* c, mp_int* d); +MP_API int mp_mod(mp_int *a, mp_int *b, mp_int *c); +MP_API int mp_invmod(mp_int *a, mp_int *b, mp_int *c); +MP_API int mp_exptmod (mp_int * g, mp_int * x, mp_int * p, mp_int * y); +MP_API int mp_mul_2d(mp_int *a, int b, mp_int *c); +MP_API int mp_2expt(mp_int* a, int b); + +MP_API int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d); + +MP_API int mp_cmp(mp_int *a, mp_int *b); +MP_API int mp_cmp_d(mp_int *a, mp_digit b); + +MP_API int mp_unsigned_bin_size(mp_int * a); +MP_API int mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c); +MP_API int mp_to_unsigned_bin_at_pos(int x, mp_int *t, unsigned char *b); +MP_API int mp_to_unsigned_bin (mp_int * a, unsigned char *b); +MP_API int mp_to_unsigned_bin_len(mp_int * a, unsigned char *b, int c); + +MP_API int mp_sub_d(fp_int *a, fp_digit b, fp_int *c); +MP_API int mp_copy(fp_int* a, fp_int* b); +MP_API int mp_isodd(mp_int* a); +MP_API int mp_iszero(mp_int* a); +MP_API int mp_count_bits(mp_int *a); +MP_API int mp_leading_bit(mp_int *a); +MP_API int mp_set_int(mp_int *a, unsigned long b); +MP_API int mp_is_bit_set (mp_int * a, mp_digit b); +MP_API int mp_set_bit (mp_int * a, mp_digit b); +MP_API void mp_rshb(mp_int *a, int x); +MP_API void mp_rshd(mp_int *a, int x); +MP_API int mp_toradix (mp_int *a, char *str, int radix); +MP_API int mp_radix_size (mp_int * a, int radix, int *size); + +#ifdef WOLFSSL_DEBUG_MATH + MP_API void mp_dump(const char* desc, mp_int* a, byte verbose); +#else + #define mp_dump(desc, a, verbose) +#endif + +#if !defined(NO_DSA) || defined(HAVE_ECC) + MP_API int mp_read_radix(mp_int* a, const char* str, int radix); +#endif + +#ifdef HAVE_ECC + MP_API int mp_sqr(fp_int *a, fp_int *b); + MP_API int mp_montgomery_reduce(fp_int *a, fp_int *m, fp_digit mp); + MP_API int mp_montgomery_setup(fp_int *a, fp_digit *rho); + MP_API int mp_div_2(fp_int * a, fp_int * b); + MP_API int mp_init_copy(fp_int * a, fp_int * b); +#endif + +#if defined(HAVE_ECC) || !defined(NO_RSA) || !defined(NO_DSA) || \ + defined(WOLFSSL_KEY_GEN) + MP_API int mp_set(fp_int *a, fp_digit b); +#endif + +#if defined(HAVE_ECC) || defined(WOLFSSL_KEY_GEN) || !defined(NO_RSA) || \ + !defined(NO_DSA) || !defined(NO_DH) + MP_API int mp_sqrmod(mp_int* a, mp_int* b, mp_int* c); + MP_API int mp_montgomery_calc_normalization(mp_int *a, mp_int *b); +#endif + +#if !defined(NO_DH) || !defined(NO_DSA) || !defined(NO_RSA) || defined(WOLFSSL_KEY_GEN) +MP_API int mp_prime_is_prime(mp_int* a, int t, int* result); +MP_API int mp_prime_is_prime_ex(mp_int* a, int t, int* result, WC_RNG* rng); +#endif /* !NO_DH || !NO_DSA || !NO_RSA || WOLFSSL_KEY_GEN */ +#ifdef WOLFSSL_KEY_GEN +MP_API int mp_gcd(fp_int *a, fp_int *b, fp_int *c); +MP_API int mp_lcm(fp_int *a, fp_int *b, fp_int *c); +MP_API int mp_rand_prime(mp_int* N, int len, WC_RNG* rng, void* heap); +MP_API int mp_exch(mp_int *a, mp_int *b); +#endif /* WOLFSSL_KEY_GEN */ + +MP_API int mp_cnt_lsb(fp_int *a); +MP_API int mp_div_2d(fp_int *a, int b, fp_int *c, fp_int *d); +MP_API int mp_mod_d(fp_int* a, fp_digit b, fp_digit* c); +MP_API int mp_lshd (mp_int * a, int b); +MP_API int mp_abs(mp_int* a, mp_int* b); + +WOLFSSL_API word32 CheckRunTimeFastMath(void); + +/* If user uses RSA, DH, DSA, or ECC math lib directly then fast math FP_SIZE + must match, return 1 if a match otherwise 0 */ +#define CheckFastMathSettings() (FP_SIZE == CheckRunTimeFastMath()) + + +#ifdef __cplusplus + } +#endif + +#endif /* WOLF_CRYPT_TFM_H */ + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/types.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/types.h new file mode 100755 index 0000000..6bf0547 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/types.h @@ -0,0 +1,877 @@ +/* types.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/*! + \file wolfssl/wolfcrypt/types.h +*/ + +#ifndef WOLF_CRYPT_TYPES_H +#define WOLF_CRYPT_TYPES_H + + #include + #include + + #ifdef __cplusplus + extern "C" { + #endif + + + #if defined(WORDS_BIGENDIAN) + #define BIG_ENDIAN_ORDER + #endif + + #ifndef BIG_ENDIAN_ORDER + #define LITTLE_ENDIAN_ORDER + #endif + + #ifndef WOLFSSL_TYPES + #ifndef byte + typedef unsigned char byte; + #endif + #ifdef WC_16BIT_CPU + typedef unsigned int word16; + typedef unsigned long word32; + #else + typedef unsigned short word16; + typedef unsigned int word32; + #endif + typedef byte word24[3]; + #endif + + + /* try to set SIZEOF_LONG or LONG_LONG if user didn't */ + #if !defined(_MSC_VER) && !defined(__BCPLUSPLUS__) && !defined(__EMSCRIPTEN__) + #if !defined(SIZEOF_LONG_LONG) && !defined(SIZEOF_LONG) + #if (defined(__alpha__) || defined(__ia64__) || \ + defined(_ARCH_PPC64) || defined(__mips64) || \ + defined(__x86_64__) || \ + ((defined(sun) || defined(__sun)) && \ + (defined(LP64) || defined(_LP64)))) + /* long should be 64bit */ + #define SIZEOF_LONG 8 + #elif defined(__i386__) || defined(__CORTEX_M3__) + /* long long should be 64bit */ + #define SIZEOF_LONG_LONG 8 + #endif + #endif + #endif + + #if defined(_MSC_VER) || defined(__BCPLUSPLUS__) + #define WORD64_AVAILABLE + #define W64LIT(x) x##ui64 + typedef unsigned __int64 word64; + #elif defined(__EMSCRIPTEN__) + #define WORD64_AVAILABLE + #define W64LIT(x) x##ull + typedef unsigned long long word64; + #elif defined(SIZEOF_LONG) && SIZEOF_LONG == 8 + #define WORD64_AVAILABLE + #define W64LIT(x) x##LL + typedef unsigned long word64; + #elif defined(SIZEOF_LONG_LONG) && SIZEOF_LONG_LONG == 8 + #define WORD64_AVAILABLE + #define W64LIT(x) x##LL + typedef unsigned long long word64; + #elif defined(__SIZEOF_LONG_LONG__) && __SIZEOF_LONG_LONG__ == 8 + #define WORD64_AVAILABLE + #define W64LIT(x) x##LL + typedef unsigned long long word64; + #endif + +#if !defined(NO_64BIT) && defined(WORD64_AVAILABLE) && !defined(WC_16BIT_CPU) + /* These platforms have 64-bit CPU registers. */ + #if (defined(__alpha__) || defined(__ia64__) || defined(_ARCH_PPC64) || \ + defined(__mips64) || defined(__x86_64__) || defined(_M_X64)) || \ + defined(__aarch64__) || defined(__sparc64__) + typedef word64 wolfssl_word; + #define WC_64BIT_CPU + #elif (defined(sun) || defined(__sun)) && \ + (defined(LP64) || defined(_LP64)) + /* LP64 with GNU GCC compiler is reserved for when long int is 64 bits + * and int uses 32 bits. When using Solaris Studio sparc and __sparc are + * available for 32 bit detection but __sparc64__ could be missed. This + * uses LP64 for checking 64 bit CPU arch. */ + typedef word64 wolfssl_word; + #define WC_64BIT_CPU + #else + typedef word32 wolfssl_word; + #ifdef WORD64_AVAILABLE + #define WOLFCRYPT_SLOW_WORD64 + #endif + #endif + +#elif defined(WC_16BIT_CPU) + #undef WORD64_AVAILABLE + typedef word16 wolfssl_word; + #define MP_16BIT /* for mp_int, mp_word needs to be twice as big as + mp_digit, no 64 bit type so make mp_digit 16 bit */ + +#else + #undef WORD64_AVAILABLE + typedef word32 wolfssl_word; + #define MP_16BIT /* for mp_int, mp_word needs to be twice as big as + mp_digit, no 64 bit type so make mp_digit 16 bit */ +#endif + + enum { + WOLFSSL_WORD_SIZE = sizeof(wolfssl_word), + WOLFSSL_BIT_SIZE = 8, + WOLFSSL_WORD_BITS = WOLFSSL_WORD_SIZE * WOLFSSL_BIT_SIZE + }; + + #define WOLFSSL_MAX_16BIT 0xffffU + + /* use inlining if compiler allows */ + #ifndef WC_INLINE + #ifndef NO_INLINE + #ifdef _MSC_VER + #define WC_INLINE __inline + #elif defined(__GNUC__) + #ifdef WOLFSSL_VXWORKS + #define WC_INLINE __inline__ + #else + #define WC_INLINE inline + #endif + #elif defined(__IAR_SYSTEMS_ICC__) + #define WC_INLINE inline + #elif defined(THREADX) + #define WC_INLINE _Inline + #elif defined(__ghc__) + #ifndef __cplusplus + #define WC_INLINE __inline + #else + #define WC_INLINE inline + #endif + #else + #define WC_INLINE + #endif + #else + #define WC_INLINE + #endif + #endif + + #if defined(HAVE_FIPS) || defined(HAVE_SELFTEST) + #define INLINE WC_INLINE + #endif + + + /* set up rotate style */ + #if (defined(_MSC_VER) || defined(__BCPLUSPLUS__)) && \ + !defined(WOLFSSL_SGX) && !defined(INTIME_RTOS) + #define INTEL_INTRINSICS + #define FAST_ROTATE + #elif defined(__MWERKS__) && TARGET_CPU_PPC + #define PPC_INTRINSICS + #define FAST_ROTATE + #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) + /* GCC does peephole optimizations which should result in using rotate + instructions */ + #define FAST_ROTATE + #endif + + + /* set up thread local storage if available */ + #ifdef HAVE_THREAD_LS + #if defined(_MSC_VER) + #define THREAD_LS_T __declspec(thread) + /* Thread local storage only in FreeRTOS v8.2.1 and higher */ + #elif defined(FREERTOS) || defined(FREERTOS_TCP) || \ + defined(WOLFSSL_ZEPHYR) + #define THREAD_LS_T + #else + #define THREAD_LS_T __thread + #endif + #else + #define THREAD_LS_T + #endif + + /* GCC 7 has new switch() fall-through detection */ + #if defined(__GNUC__) + #if ((__GNUC__ > 7) || ((__GNUC__ == 7) && (__GNUC_MINOR__ >= 1))) + #define FALL_THROUGH __attribute__ ((fallthrough)) + #endif + #endif + #ifndef FALL_THROUGH + #define FALL_THROUGH + #endif + + /* Micrium will use Visual Studio for compilation but not the Win32 API */ + #if defined(_WIN32) && !defined(MICRIUM) && !defined(FREERTOS) && \ + !defined(FREERTOS_TCP) && !defined(EBSNET) && \ + !defined(WOLFSSL_UTASKER) && !defined(INTIME_RTOS) + #define USE_WINDOWS_API + #endif + + + /* idea to add global alloc override by Moises Guimaraes */ + /* default to libc stuff */ + /* XREALLOC is used once in normal math lib, not in fast math lib */ + /* XFREE on some embedded systems doesn't like free(0) so test */ + #if defined(HAVE_IO_POOL) + WOLFSSL_API void* XMALLOC(size_t n, void* heap, int type); + WOLFSSL_API void* XREALLOC(void *p, size_t n, void* heap, int type); + WOLFSSL_API void XFREE(void *p, void* heap, int type); + #elif defined(WOLFSSL_ASYNC_CRYPT) && defined(HAVE_INTEL_QA) + #include + #undef USE_WOLFSSL_MEMORY + #ifdef WOLFSSL_DEBUG_MEMORY + #define XMALLOC(s, h, t) IntelQaMalloc((s), (h), (t), __func__, __LINE__) + #define XFREE(p, h, t) IntelQaFree((p), (h), (t), __func__, __LINE__) + #define XREALLOC(p, n, h, t) IntelQaRealloc((p), (n), (h), (t), __func__, __LINE__) + #else + #define XMALLOC(s, h, t) IntelQaMalloc((s), (h), (t)) + #define XFREE(p, h, t) IntelQaFree((p), (h), (t)) + #define XREALLOC(p, n, h, t) IntelQaRealloc((p), (n), (h), (t)) + #endif /* WOLFSSL_DEBUG_MEMORY */ + #elif defined(XMALLOC_USER) + /* prototypes for user heap override functions */ + #include /* for size_t */ + extern void *XMALLOC(size_t n, void* heap, int type); + extern void *XREALLOC(void *p, size_t n, void* heap, int type); + extern void XFREE(void *p, void* heap, int type); + #elif defined(WOLFSSL_MEMORY_LOG) + #define XMALLOC(n, h, t) xmalloc(n, h, t, __func__, __FILE__, __LINE__) + #define XREALLOC(p, n, h, t) xrealloc(p, n, h, t, __func__, __FILE__, __LINE__) + #define XFREE(p, h, t) xfree(p, h, t, __func__, __FILE__, __LINE__) + + /* prototypes for user heap override functions */ + #include /* for size_t */ + #include + WOLFSSL_API void *xmalloc(size_t n, void* heap, int type, + const char* func, const char* file, unsigned int line); + WOLFSSL_API void *xrealloc(void *p, size_t n, void* heap, int type, + const char* func, const char* file, unsigned int line); + WOLFSSL_API void xfree(void *p, void* heap, int type, const char* func, + const char* file, unsigned int line); + #elif defined(XMALLOC_OVERRIDE) + /* override the XMALLOC, XFREE and XREALLOC macros */ + #elif defined(WOLFSSL_TELIT_M2MB) + /* Telit M2MB SDK requires use m2mb_os API's, not std malloc/free */ + /* Use of malloc/free will cause CPU reboot */ + #define XMALLOC(s, h, t) ((void)h, (void)t, m2mb_os_malloc((s))) + #define XFREE(p, h, t) {void* xp = (p); if((xp)) m2mb_os_free((xp));} + #define XREALLOC(p, n, h, t) m2mb_os_realloc((p), (n)) + + #elif defined(NO_WOLFSSL_MEMORY) + #ifdef WOLFSSL_NO_MALLOC + /* this platform does not support heap use */ + #ifdef WOLFSSL_MALLOC_CHECK + #include + static inline void* malloc_check(size_t sz) { + printf("wolfSSL_malloc failed"); + return NULL; + }; + #define XMALLOC(s, h, t) malloc_check((s)) + #define XFREE(p, h, t) + #define XREALLOC(p, n, h, t) (NULL) + #else + #define XMALLOC(s, h, t) (NULL) + #define XFREE(p, h, t) + #define XREALLOC(p, n, h, t) (NULL) + #endif + #else + /* just use plain C stdlib stuff if desired */ + #include + #define XMALLOC(s, h, t) ((void)h, (void)t, malloc((s))) + #define XFREE(p, h, t) {void* xp = (p); if((xp)) free((xp));} + #define XREALLOC(p, n, h, t) realloc((p), (n)) + #endif + #elif !defined(MICRIUM_MALLOC) && !defined(EBSNET) \ + && !defined(WOLFSSL_SAFERTOS) && !defined(FREESCALE_MQX) \ + && !defined(FREESCALE_KSDK_MQX) && !defined(FREESCALE_FREE_RTOS) \ + && !defined(WOLFSSL_LEANPSK) && !defined(WOLFSSL_uITRON4) + /* default C runtime, can install different routines at runtime via cbs */ + #include + #ifdef WOLFSSL_STATIC_MEMORY + #ifdef WOLFSSL_DEBUG_MEMORY + #define XMALLOC(s, h, t) wolfSSL_Malloc((s), (h), (t), __func__, __LINE__) + #define XFREE(p, h, t) {void* xp = (p); if((xp)) wolfSSL_Free((xp), (h), (t), __func__, __LINE__);} + #define XREALLOC(p, n, h, t) wolfSSL_Realloc((p), (n), (h), (t), __func__, __LINE__) + #else + #define XMALLOC(s, h, t) wolfSSL_Malloc((s), (h), (t)) + #define XFREE(p, h, t) {void* xp = (p); if((xp)) wolfSSL_Free((xp), (h), (t));} + #define XREALLOC(p, n, h, t) wolfSSL_Realloc((p), (n), (h), (t)) + #endif /* WOLFSSL_DEBUG_MEMORY */ + #elif !defined(FREERTOS) && !defined(FREERTOS_TCP) + #ifdef WOLFSSL_DEBUG_MEMORY + #define XMALLOC(s, h, t) ((void)h, (void)t, wolfSSL_Malloc((s), __func__, __LINE__)) + #define XFREE(p, h, t) {void* xp = (p); if((xp)) wolfSSL_Free((xp), __func__, __LINE__);} + #define XREALLOC(p, n, h, t) wolfSSL_Realloc((p), (n), __func__, __LINE__) + #else + #define XMALLOC(s, h, t) ((void)h, (void)t, wolfSSL_Malloc((s))) + #define XFREE(p, h, t) {void* xp = (p); if((xp)) wolfSSL_Free((xp));} + #define XREALLOC(p, n, h, t) wolfSSL_Realloc((p), (n)) + #endif /* WOLFSSL_DEBUG_MEMORY */ + #endif /* WOLFSSL_STATIC_MEMORY */ + #endif + + /* declare/free variable handling for async */ + #ifdef WOLFSSL_ASYNC_CRYPT + #define DECLARE_VAR(VAR_NAME, VAR_TYPE, VAR_SIZE, HEAP) \ + VAR_TYPE* VAR_NAME = (VAR_TYPE*)XMALLOC(sizeof(VAR_TYPE) * VAR_SIZE, (HEAP), DYNAMIC_TYPE_WOLF_BIGINT); + #define DECLARE_VAR_INIT(VAR_NAME, VAR_TYPE, VAR_SIZE, INIT_VALUE, HEAP) \ + VAR_TYPE* VAR_NAME = ({ \ + VAR_TYPE* ptr = (VAR_TYPE*)XMALLOC(sizeof(VAR_TYPE) * VAR_SIZE, (HEAP), DYNAMIC_TYPE_WOLF_BIGINT); \ + if (ptr && INIT_VALUE) { \ + XMEMCPY(ptr, INIT_VALUE, sizeof(VAR_TYPE) * VAR_SIZE); \ + } \ + ptr; \ + }) + #define DECLARE_ARRAY(VAR_NAME, VAR_TYPE, VAR_ITEMS, VAR_SIZE, HEAP) \ + VAR_TYPE* VAR_NAME[VAR_ITEMS]; \ + int idx##VAR_NAME; \ + for (idx##VAR_NAME=0; idx##VAR_NAME + #define XMEMCPY(d,s,l) memcpy((d),(s),(l)) + #define XMEMSET(b,c,l) memset((b),(c),(l)) + #define XMEMCMP(s1,s2,n) memcmp((s1),(s2),(n)) + #define XMEMMOVE(d,s,l) memmove((d),(s),(l)) + + #define XSTRLEN(s1) strlen((s1)) + #define XSTRNCPY(s1,s2,n) strncpy((s1),(s2),(n)) + /* strstr, strncmp, and strncat only used by wolfSSL proper, + * not required for wolfCrypt only */ + #define XSTRSTR(s1,s2) strstr((s1),(s2)) + #define XSTRNSTR(s1,s2,n) mystrnstr((s1),(s2),(n)) + #define XSTRNCMP(s1,s2,n) strncmp((s1),(s2),(n)) + #define XSTRNCAT(s1,s2,n) strncat((s1),(s2),(n)) + + #ifdef USE_WOLF_STRSEP + #define XSTRSEP(s1,d) wc_strsep((s1),(d)) + #else + #define XSTRSEP(s1,d) strsep((s1),(d)) + #endif + + #ifndef XSTRNCASECMP + #if defined(MICROCHIP_PIC32) || defined(WOLFSSL_TIRTOS) || \ + defined(WOLFSSL_ZEPHYR) + /* XC32 does not support strncasecmp, so use case sensitive one */ + #define XSTRNCASECMP(s1,s2,n) strncmp((s1),(s2),(n)) + #elif defined(USE_WINDOWS_API) || defined(FREERTOS_TCP_WINSIM) + #define XSTRNCASECMP(s1,s2,n) _strnicmp((s1),(s2),(n)) + #else + #if defined(HAVE_STRINGS_H) && defined(WOLF_C99) && \ + !defined(WOLFSSL_SGX) + #include + #endif + #if defined(WOLFSSL_DEOS) + + #define XSTRNCASECMP(s1,s2,n) strnicmp((s1),(s2),(n)) + #else +int os_strncasecmp(const char *s1, const char *s2, size_t n); + #define XSTRNCASECMP(s1,s2,n) os_strncasecmp((s1),(s2),(n)) + #endif + #endif + #endif /* !XSTRNCASECMP */ + + /* snprintf is used in asn.c for GetTimeString, PKCS7 test, and when + debugging is turned on */ + #ifndef USE_WINDOWS_API + #ifndef XSNPRINTF + #if defined(NO_FILESYSTEM) && (defined(OPENSSL_EXTRA) || \ + defined(HAVE_PKCS7)) && !defined(NO_STDIO_FILESYSTEM) + /* case where stdio is not included else where but is needed + for snprintf */ + #include + #endif + #define XSNPRINTF snprintf + #endif + #else + #ifdef _MSC_VER + #if (_MSC_VER >= 1900) + /* Beginning with the UCRT in Visual Studio 2015 and + Windows 10, snprintf is no longer identical to + _snprintf. The snprintf function behavior is now + C99 standard compliant. */ + #define XSNPRINTF snprintf + #else + /* 4996 warning to use MS extensions e.g., _sprintf_s + instead of _snprintf */ + #pragma warning(disable: 4996) + static WC_INLINE + int xsnprintf(char *buffer, size_t bufsize, + const char *format, ...) { + va_list ap; + int ret; + + if ((int)bufsize <= 0) return -1; + va_start(ap, format); + ret = vsnprintf(buffer, bufsize, format, ap); + if (ret >= (int)bufsize) + ret = -1; + va_end(ap); + return ret; + } + #define XSNPRINTF xsnprintf + #endif /* (_MSC_VER >= 1900) */ + #endif /* _MSC_VER */ + #endif /* USE_WINDOWS_API */ + + #if defined(WOLFSSL_CERT_EXT) || defined(HAVE_ALPN) + /* use only Thread Safe version of strtok */ + #if defined(USE_WOLF_STRTOK) + #define XSTRTOK(s1,d,ptr) wc_strtok((s1),(d),(ptr)) + #elif defined(USE_WINDOWS_API) || defined(INTIME_RTOS) + #define XSTRTOK(s1,d,ptr) strtok_s((s1),(d),(ptr)) + #else + #define XSTRTOK(s1,d,ptr) strtok_r((s1),(d),(ptr)) + #endif + #endif + #endif + + #ifdef USE_WOLF_STRTOK + WOLFSSL_API char* wc_strtok(char *str, const char *delim, char **nextp); + #endif + #ifdef USE_WOLF_STRSEP + WOLFSSL_API char* wc_strsep(char **stringp, const char *delim); + #endif + + #if !defined(NO_FILESYSTEM) && defined(OPENSSL_EXTRA) && \ + !defined(NO_STDIO_FILESYSTEM) + #ifndef XGETENV + #include + #define XGETENV getenv + #endif + #endif /* OPENSSL_EXTRA */ + + #ifndef CTYPE_USER + #include + #if defined(HAVE_ECC) || defined(HAVE_OCSP) || \ + defined(WOLFSSL_KEY_GEN) || !defined(NO_DSA) + #define XTOUPPER(c) toupper((c)) + #define XISALPHA(c) isalpha((c)) + #endif + /* needed by wolfSSL_check_domain_name() */ + #define XTOLOWER(c) tolower((c)) + #endif + + + /* memory allocation types for user hints */ + enum { + DYNAMIC_TYPE_CA = 1, + DYNAMIC_TYPE_CERT = 2, + DYNAMIC_TYPE_KEY = 3, + DYNAMIC_TYPE_FILE = 4, + DYNAMIC_TYPE_SUBJECT_CN = 5, + DYNAMIC_TYPE_PUBLIC_KEY = 6, + DYNAMIC_TYPE_SIGNER = 7, + DYNAMIC_TYPE_NONE = 8, + DYNAMIC_TYPE_BIGINT = 9, + DYNAMIC_TYPE_RSA = 10, + DYNAMIC_TYPE_METHOD = 11, + DYNAMIC_TYPE_OUT_BUFFER = 12, + DYNAMIC_TYPE_IN_BUFFER = 13, + DYNAMIC_TYPE_INFO = 14, + DYNAMIC_TYPE_DH = 15, + DYNAMIC_TYPE_DOMAIN = 16, + DYNAMIC_TYPE_SSL = 17, + DYNAMIC_TYPE_CTX = 18, + DYNAMIC_TYPE_WRITEV = 19, + DYNAMIC_TYPE_OPENSSL = 20, + DYNAMIC_TYPE_DSA = 21, + DYNAMIC_TYPE_CRL = 22, + DYNAMIC_TYPE_REVOKED = 23, + DYNAMIC_TYPE_CRL_ENTRY = 24, + DYNAMIC_TYPE_CERT_MANAGER = 25, + DYNAMIC_TYPE_CRL_MONITOR = 26, + DYNAMIC_TYPE_OCSP_STATUS = 27, + DYNAMIC_TYPE_OCSP_ENTRY = 28, + DYNAMIC_TYPE_ALTNAME = 29, + DYNAMIC_TYPE_SUITES = 30, + DYNAMIC_TYPE_CIPHER = 31, + DYNAMIC_TYPE_RNG = 32, + DYNAMIC_TYPE_ARRAYS = 33, + DYNAMIC_TYPE_DTLS_POOL = 34, + DYNAMIC_TYPE_SOCKADDR = 35, + DYNAMIC_TYPE_LIBZ = 36, + DYNAMIC_TYPE_ECC = 37, + DYNAMIC_TYPE_TMP_BUFFER = 38, + DYNAMIC_TYPE_DTLS_MSG = 39, + DYNAMIC_TYPE_X509 = 40, + DYNAMIC_TYPE_TLSX = 41, + DYNAMIC_TYPE_OCSP = 42, + DYNAMIC_TYPE_SIGNATURE = 43, + DYNAMIC_TYPE_HASHES = 44, + DYNAMIC_TYPE_SRP = 45, + DYNAMIC_TYPE_COOKIE_PWD = 46, + DYNAMIC_TYPE_USER_CRYPTO = 47, + DYNAMIC_TYPE_OCSP_REQUEST = 48, + DYNAMIC_TYPE_X509_EXT = 49, + DYNAMIC_TYPE_X509_STORE = 50, + DYNAMIC_TYPE_X509_CTX = 51, + DYNAMIC_TYPE_URL = 52, + DYNAMIC_TYPE_DTLS_FRAG = 53, + DYNAMIC_TYPE_DTLS_BUFFER = 54, + DYNAMIC_TYPE_SESSION_TICK = 55, + DYNAMIC_TYPE_PKCS = 56, + DYNAMIC_TYPE_MUTEX = 57, + DYNAMIC_TYPE_PKCS7 = 58, + DYNAMIC_TYPE_AES_BUFFER = 59, + DYNAMIC_TYPE_WOLF_BIGINT = 60, + DYNAMIC_TYPE_ASN1 = 61, + DYNAMIC_TYPE_LOG = 62, + DYNAMIC_TYPE_WRITEDUP = 63, + DYNAMIC_TYPE_PRIVATE_KEY = 64, + DYNAMIC_TYPE_HMAC = 65, + DYNAMIC_TYPE_ASYNC = 66, + DYNAMIC_TYPE_ASYNC_NUMA = 67, + DYNAMIC_TYPE_ASYNC_NUMA64 = 68, + DYNAMIC_TYPE_CURVE25519 = 69, + DYNAMIC_TYPE_ED25519 = 70, + DYNAMIC_TYPE_SECRET = 71, + DYNAMIC_TYPE_DIGEST = 72, + DYNAMIC_TYPE_RSA_BUFFER = 73, + DYNAMIC_TYPE_DCERT = 74, + DYNAMIC_TYPE_STRING = 75, + DYNAMIC_TYPE_PEM = 76, + DYNAMIC_TYPE_DER = 77, + DYNAMIC_TYPE_CERT_EXT = 78, + DYNAMIC_TYPE_ALPN = 79, + DYNAMIC_TYPE_ENCRYPTEDINFO= 80, + DYNAMIC_TYPE_DIRCTX = 81, + DYNAMIC_TYPE_HASHCTX = 82, + DYNAMIC_TYPE_SEED = 83, + DYNAMIC_TYPE_SYMMETRIC_KEY= 84, + DYNAMIC_TYPE_ECC_BUFFER = 85, + DYNAMIC_TYPE_QSH = 86, + DYNAMIC_TYPE_SALT = 87, + DYNAMIC_TYPE_HASH_TMP = 88, + DYNAMIC_TYPE_BLOB = 89, + DYNAMIC_TYPE_NAME_ENTRY = 90, + }; + + /* max error buffer string size */ + #ifndef WOLFSSL_MAX_ERROR_SZ + #define WOLFSSL_MAX_ERROR_SZ 80 + #endif + + /* stack protection */ + enum { + MIN_STACK_BUFFER = 8 + }; + + + /* Algorithm Types */ + enum wc_AlgoType { + WC_ALGO_TYPE_NONE = 0, + WC_ALGO_TYPE_HASH = 1, + WC_ALGO_TYPE_CIPHER = 2, + WC_ALGO_TYPE_PK = 3, + WC_ALGO_TYPE_RNG = 4, + WC_ALGO_TYPE_SEED = 5, + WC_ALGO_TYPE_HMAC = 6, + + WC_ALGO_TYPE_MAX = WC_ALGO_TYPE_HMAC + }; + + /* hash types */ + enum wc_HashType { + #if defined(HAVE_SELFTEST) || defined(HAVE_FIPS) + /* In selftest build, WC_* types are not mapped to WC_HASH_TYPE types. + * Values here are based on old selftest hmac.h enum, with additions. + * These values are fixed for backwards FIPS compatibility */ + WC_HASH_TYPE_NONE = 15, + WC_HASH_TYPE_MD2 = 16, + WC_HASH_TYPE_MD4 = 17, + WC_HASH_TYPE_MD5 = 0, + WC_HASH_TYPE_SHA = 1, /* SHA-1 (not old SHA-0) */ + WC_HASH_TYPE_SHA224 = 8, + WC_HASH_TYPE_SHA256 = 2, + WC_HASH_TYPE_SHA384 = 5, + WC_HASH_TYPE_SHA512 = 4, + WC_HASH_TYPE_MD5_SHA = 18, + WC_HASH_TYPE_SHA3_224 = 10, + WC_HASH_TYPE_SHA3_256 = 11, + WC_HASH_TYPE_SHA3_384 = 12, + WC_HASH_TYPE_SHA3_512 = 13, + WC_HASH_TYPE_BLAKE2B = 14, + WC_HASH_TYPE_BLAKE2S = 19, + + WC_HASH_TYPE_MAX = WC_HASH_TYPE_BLAKE2S + #else + WC_HASH_TYPE_NONE = 0, + WC_HASH_TYPE_MD2 = 1, + WC_HASH_TYPE_MD4 = 2, + WC_HASH_TYPE_MD5 = 3, + WC_HASH_TYPE_SHA = 4, /* SHA-1 (not old SHA-0) */ + WC_HASH_TYPE_SHA224 = 5, + WC_HASH_TYPE_SHA256 = 6, + WC_HASH_TYPE_SHA384 = 7, + WC_HASH_TYPE_SHA512 = 8, + WC_HASH_TYPE_MD5_SHA = 9, + WC_HASH_TYPE_SHA3_224 = 10, + WC_HASH_TYPE_SHA3_256 = 11, + WC_HASH_TYPE_SHA3_384 = 12, + WC_HASH_TYPE_SHA3_512 = 13, + WC_HASH_TYPE_BLAKE2B = 14, + WC_HASH_TYPE_BLAKE2S = 15, + + WC_HASH_TYPE_MAX = WC_HASH_TYPE_BLAKE2S + #endif /* HAVE_SELFTEST */ + }; + + /* cipher types */ + enum wc_CipherType { + WC_CIPHER_NONE = 0, + WC_CIPHER_AES = 1, + WC_CIPHER_AES_CBC = 2, + WC_CIPHER_AES_GCM = 3, + WC_CIPHER_AES_CTR = 4, + WC_CIPHER_AES_XTS = 5, + WC_CIPHER_AES_CFB = 6, + WC_CIPHER_DES3 = 7, + WC_CIPHER_DES = 8, + WC_CIPHER_CHACHA = 9, + WC_CIPHER_HC128 = 10, + WC_CIPHER_IDEA = 11, + + WC_CIPHER_MAX = WC_CIPHER_HC128 + }; + + /* PK=public key (asymmetric) based algorithms */ + enum wc_PkType { + WC_PK_TYPE_NONE = 0, + WC_PK_TYPE_RSA = 1, + WC_PK_TYPE_DH = 2, + WC_PK_TYPE_ECDH = 3, + WC_PK_TYPE_ECDSA_SIGN = 4, + WC_PK_TYPE_ECDSA_VERIFY = 5, + WC_PK_TYPE_ED25519 = 6, + WC_PK_TYPE_CURVE25519 = 7, + WC_PK_TYPE_RSA_KEYGEN = 8, + WC_PK_TYPE_EC_KEYGEN = 9, + + WC_PK_TYPE_MAX = WC_PK_TYPE_EC_KEYGEN + }; + + + /* settings detection for compile vs runtime math incompatibilities */ + enum { + #if !defined(USE_FAST_MATH) && !defined(SIZEOF_LONG) && !defined(SIZEOF_LONG_LONG) + CTC_SETTINGS = 0x0 + #elif !defined(USE_FAST_MATH) && defined(SIZEOF_LONG) && (SIZEOF_LONG == 8) + CTC_SETTINGS = 0x1 + #elif !defined(USE_FAST_MATH) && defined(SIZEOF_LONG_LONG) && (SIZEOF_LONG_LONG == 8) + CTC_SETTINGS = 0x2 + #elif !defined(USE_FAST_MATH) && defined(SIZEOF_LONG_LONG) && (SIZEOF_LONG_LONG == 4) + CTC_SETTINGS = 0x4 + #elif defined(USE_FAST_MATH) && !defined(SIZEOF_LONG) && !defined(SIZEOF_LONG_LONG) + CTC_SETTINGS = 0x8 + #elif defined(USE_FAST_MATH) && defined(SIZEOF_LONG) && (SIZEOF_LONG == 8) + CTC_SETTINGS = 0x10 + #elif defined(USE_FAST_MATH) && defined(SIZEOF_LONG_LONG) && (SIZEOF_LONG_LONG == 8) + CTC_SETTINGS = 0x20 + #elif defined(USE_FAST_MATH) && defined(SIZEOF_LONG_LONG) && (SIZEOF_LONG_LONG == 4) + CTC_SETTINGS = 0x40 + #else + #error "bad math long / long long settings" + #endif + }; + + + WOLFSSL_API word32 CheckRunTimeSettings(void); + + /* If user uses RSA, DH, DSA, or ECC math lib directly then fast math and long + types need to match at compile time and run time, CheckCtcSettings will + return 1 if a match otherwise 0 */ + #define CheckCtcSettings() (CTC_SETTINGS == CheckRunTimeSettings()) + + /* invalid device id */ + #define INVALID_DEVID -2 + + + /* AESNI requires alignment and ARMASM gains some performance from it + * Xilinx RSA operations require alignment */ + #if defined(WOLFSSL_AESNI) || defined(WOLFSSL_ARMASM) || \ + defined(USE_INTEL_SPEEDUP) || defined(WOLFSSL_AFALG_XILINX) + #if !defined(ALIGN16) + #if defined(__GNUC__) + #define ALIGN16 __attribute__ ( (aligned (16))) + #elif defined(_MSC_VER) + /* disable align warning, we want alignment ! */ + #pragma warning(disable: 4324) + #define ALIGN16 __declspec (align (16)) + #else + #define ALIGN16 + #endif + #endif /* !ALIGN16 */ + + #if !defined (ALIGN32) + #if defined (__GNUC__) + #define ALIGN32 __attribute__ ( (aligned (32))) + #elif defined(_MSC_VER) + /* disable align warning, we want alignment ! */ + #pragma warning(disable: 4324) + #define ALIGN32 __declspec (align (32)) + #else + #define ALIGN32 + #endif + #endif /* !ALIGN32 */ + + #if !defined(ALIGN64) + #if defined(__GNUC__) + #define ALIGN64 __attribute__ ( (aligned (64))) + #elif defined(_MSC_VER) + /* disable align warning, we want alignment ! */ + #pragma warning(disable: 4324) + #define ALIGN64 __declspec (align (64)) + #else + #define ALIGN64 + #endif + #endif /* !ALIGN64 */ + + #if defined(__GNUC__) + #define ALIGN128 __attribute__ ( (aligned (128))) + #elif defined(_MSC_VER) + /* disable align warning, we want alignment ! */ + #pragma warning(disable: 4324) + #define ALIGN128 __declspec (align (128)) + #else + #define ALIGN128 + #endif + + #if defined(__GNUC__) + #define ALIGN256 __attribute__ ( (aligned (256))) + #elif defined(_MSC_VER) + /* disable align warning, we want alignment ! */ + #pragma warning(disable: 4324) + #define ALIGN256 __declspec (align (256)) + #else + #define ALIGN256 + #endif + + #else + #ifndef ALIGN16 + #define ALIGN16 + #endif + #ifndef ALIGN32 + #define ALIGN32 + #endif + #ifndef ALIGN64 + #define ALIGN64 + #endif + #ifndef ALIGN128 + #define ALIGN128 + #endif + #ifndef ALIGN256 + #define ALIGN256 + #endif + #endif /* WOLFSSL_AESNI || WOLFSSL_ARMASM */ + + + #ifndef TRUE + #define TRUE 1 + #endif + #ifndef FALSE + #define FALSE 0 + #endif + + + #ifdef WOLFSSL_RIOT_OS + #define EXIT_TEST(ret) exit(ret) + #elif defined(HAVE_STACK_SIZE) + #define EXIT_TEST(ret) return (void*)((size_t)(ret)) + #else + #define EXIT_TEST(ret) return ret + #endif + + + #if defined(__GNUC__) + #define WOLFSSL_PACK __attribute__ ((packed)) + #else + #define WOLFSSL_PACK + #endif + + #ifndef __GNUC_PREREQ + #if defined(__GNUC__) && defined(__GNUC_MINOR__) + #define __GNUC_PREREQ(maj, min) \ + ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) + #else + #define __GNUC_PREREQ(maj, min) (0) /* not GNUC */ + #endif + #endif + + #if defined(__GNUC__) + #define WC_NORETURN __attribute__((noreturn)) + #else + #define WC_NORETURN + #endif + + #if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || \ + defined(WOLFSSL_DEBUG_MATH) || defined(DEBUG_WOLFSSL) || \ + defined(WOLFSSL_PUBLIC_MP) || defined(OPENSSL_EXTRA) || \ + (defined(HAVE_ECC) && defined(HAVE_ECC_KEY_EXPORT)) + #undef WC_MP_TO_RADIX + #define WC_MP_TO_RADIX + #endif + + #ifdef __cplusplus + } /* extern "C" */ + #endif + +#endif /* WOLF_CRYPT_TYPES_H */ diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/visibility.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/visibility.h new file mode 100755 index 0000000..07ba2f1 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/visibility.h @@ -0,0 +1,79 @@ +/* visibility.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + + +/* Visibility control macros */ + +#ifndef WOLF_CRYPT_VISIBILITY_H +#define WOLF_CRYPT_VISIBILITY_H + + +/* for compatibility and so that fips is using same name of macro @wc_fips */ +/* The following visibility wrappers are for old FIPS. New FIPS should use + * the same as a non-FIPS build. */ +#if defined(HAVE_FIPS) && \ + (!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2)) + #include + #define WOLFSSL_API CYASSL_API + #define WOLFSSL_LOCAL CYASSL_LOCAL +#else + +/* WOLFSSL_API is used for the public API symbols. + It either imports or exports (or does nothing for static builds) + + WOLFSSL_LOCAL is used for non-API symbols (private). +*/ + +#if defined(BUILDING_WOLFSSL) + #if defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN__) + #if defined(WOLFSSL_DLL) + #define WOLFSSL_API __declspec(dllexport) + #else + #define WOLFSSL_API + #endif + #define WOLFSSL_LOCAL + #elif defined(HAVE_VISIBILITY) && HAVE_VISIBILITY + #define WOLFSSL_API __attribute__ ((visibility("default"))) + #define WOLFSSL_LOCAL __attribute__ ((visibility("hidden"))) + #elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550) + #define WOLFSSL_API __global + #define WOLFSSL_LOCAL __hidden + #else + #define WOLFSSL_API + #define WOLFSSL_LOCAL + #endif /* HAVE_VISIBILITY */ +#else /* BUILDING_WOLFSSL */ + #if defined(_MSC_VER) || defined(__MINGW32__) || defined(__CYGWIN__) + #if defined(WOLFSSL_DLL) + #define WOLFSSL_API __declspec(dllimport) + #else + #define WOLFSSL_API + #endif + #define WOLFSSL_LOCAL + #else + #define WOLFSSL_API + #define WOLFSSL_LOCAL + #endif +#endif /* BUILDING_WOLFSSL */ + +#endif /* HAVE_FIPS */ +#endif /* WOLF_CRYPT_VISIBILITY_H */ + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/wc_encrypt.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/wc_encrypt.h new file mode 100755 index 0000000..d1f1fb7 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/wc_encrypt.h @@ -0,0 +1,101 @@ +/* wc_encrypt.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/*! + \file wolfssl/wolfcrypt/wc_encrypt.h +*/ + + +#ifndef WOLF_CRYPT_ENCRYPT_H +#define WOLF_CRYPT_ENCRYPT_H + +#include +#include +#include +#include +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/* determine max cipher key size */ +#ifndef NO_AES + #define WC_MAX_SYM_KEY_SIZE (AES_MAX_KEY_SIZE/8) +#elif defined(HAVE_CHACHA) + #define WC_MAX_SYM_KEY_SIZE CHACHA_MAX_KEY_SZ +#elif !defined(NO_DES3) + #define WC_MAX_SYM_KEY_SIZE DES3_KEY_SIZE +#elif !defined(NO_RC4) + #define WC_MAX_SYM_KEY_SIZE RC4_KEY_SIZE +#else + #define WC_MAX_SYM_KEY_SIZE 32 +#endif + + +#if !defined(NO_AES) && defined(HAVE_AES_CBC) +WOLFSSL_API int wc_AesCbcEncryptWithKey(byte* out, const byte* in, word32 inSz, + const byte* key, word32 keySz, + const byte* iv); +WOLFSSL_API int wc_AesCbcDecryptWithKey(byte* out, const byte* in, word32 inSz, + const byte* key, word32 keySz, + const byte* iv); +#endif /* !NO_AES */ + + +#ifndef NO_DES3 +WOLFSSL_API int wc_Des_CbcDecryptWithKey(byte* out, + const byte* in, word32 sz, + const byte* key, const byte* iv); +WOLFSSL_API int wc_Des_CbcEncryptWithKey(byte* out, + const byte* in, word32 sz, + const byte* key, const byte* iv); +WOLFSSL_API int wc_Des3_CbcEncryptWithKey(byte* out, + const byte* in, word32 sz, + const byte* key, const byte* iv); +WOLFSSL_API int wc_Des3_CbcDecryptWithKey(byte* out, + const byte* in, word32 sz, + const byte* key, const byte* iv); +#endif /* !NO_DES3 */ + + + + +#ifdef WOLFSSL_ENCRYPTED_KEYS + struct EncryptedInfo; + WOLFSSL_API int wc_BufferKeyDecrypt(struct EncryptedInfo* info, byte* der, word32 derSz, + const byte* password, int passwordSz, int hashType); + WOLFSSL_API int wc_BufferKeyEncrypt(struct EncryptedInfo* info, byte* der, word32 derSz, + const byte* password, int passwordSz, int hashType); +#endif /* WOLFSSL_ENCRYPTED_KEYS */ + +#ifndef NO_PWDBASED + WOLFSSL_LOCAL int wc_CryptKey(const char* password, int passwordSz, + byte* salt, int saltSz, int iterations, int id, byte* input, int length, + int version, byte* cbcIv, int enc); +#endif + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLF_CRYPT_ENCRYPT_H */ + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/wc_pkcs11.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/wc_pkcs11.h new file mode 100755 index 0000000..614f65d --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/wc_pkcs11.h @@ -0,0 +1,94 @@ +/* wc_pkcs11.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#ifndef _WOLFPKCS11_H_ +#define _WOLFPKCS11_H_ + +#include + +#ifdef HAVE_PKCS11 + +#ifndef WOLF_CRYPTO_CB + #error PKCS11 support requires ./configure --enable-cryptocb or WOLF_CRYPTO_CB to be defined +#endif + +#include +#include + +#ifdef __cplusplus + extern "C" { +#endif + + +typedef struct Pkcs11Dev { + void* dlHandle; /* Handle to library */ + CK_FUNCTION_LIST* func; /* Array of functions */ + void* heap; +} Pkcs11Dev; + +typedef struct Pkcs11Token { + CK_FUNCTION_LIST* func; /* Table of PKCS#11 function from lib */ + CK_SLOT_ID slotId; /* Id of slot to use */ + CK_SESSION_HANDLE handle; /* Handle to active session */ + CK_UTF8CHAR_PTR userPin; /* User's PIN to login with */ + CK_ULONG userPinSz; /* Size of user's PIN in bytes */ +} Pkcs11Token; + +typedef struct Pkcs11Session { + CK_FUNCTION_LIST* func; /* Table of PKCS#11 function from lib */ + CK_SLOT_ID slotId; /* Id of slot to use */ + CK_SESSION_HANDLE handle; /* Handle to active session */ +} Pkcs11Session; + +/* Types of keys that can be stored. */ +enum Pkcs11KeyType { + PKCS11_KEY_TYPE_AES_GCM, + PKCS11_KEY_TYPE_AES_CBC, + PKCS11_KEY_TYPE_HMAC, + PKCS11_KEY_TYPE_RSA, + PKCS11_KEY_TYPE_EC, +}; + + +WOLFSSL_API int wc_Pkcs11_Initialize(Pkcs11Dev* dev, const char* library, + void* heap); +WOLFSSL_API void wc_Pkcs11_Finalize(Pkcs11Dev* dev); + +WOLFSSL_API int wc_Pkcs11Token_Init(Pkcs11Token* token, Pkcs11Dev* dev, + int slotId, const char* tokenName, const unsigned char *userPin, + int userPinSz); +WOLFSSL_API void wc_Pkcs11Token_Final(Pkcs11Token* token); +WOLFSSL_API int wc_Pkcs11Token_Open(Pkcs11Token* token, int readWrite); +WOLFSSL_API void wc_Pkcs11Token_Close(Pkcs11Token* token); + +WOLFSSL_API int wc_Pkcs11StoreKey(Pkcs11Token* token, int type, int clear, + void* key); + +WOLFSSL_API int wc_Pkcs11_CryptoDevCb(int devId, wc_CryptoInfo* info, + void* ctx); + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* HAVE_PKCS11 */ + +#endif /* _WOLFPKCS11_H_ */ diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/wc_port.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/wc_port.h new file mode 100755 index 0000000..208f3f3 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/wc_port.h @@ -0,0 +1,725 @@ +/* wc_port.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/*! + \file wolfssl/wolfcrypt/wc_port.h +*/ + +#ifndef WOLF_CRYPT_PORT_H +#define WOLF_CRYPT_PORT_H + +#include +#include + +#ifdef __cplusplus + extern "C" { +#endif + +/* Detect if compiler supports C99. "NO_WOLF_C99" can be defined in + * user_settings.h to disable checking for C99 support. */ +#if !defined(WOLF_C99) && defined(__STDC_VERSION__) && \ + !defined(WOLFSSL_ARDUINO) && !defined(NO_WOLF_C99) + #if __STDC_VERSION__ >= 199901L + #define WOLF_C99 + #endif +#endif + +#ifdef USE_WINDOWS_API + #ifdef WOLFSSL_GAME_BUILD + #include "system/xtl.h" + #else + #ifndef WIN32_LEAN_AND_MEAN + #define WIN32_LEAN_AND_MEAN + #endif + #ifndef WOLFSSL_SGX + #if defined(_WIN32_WCE) || defined(WIN32_LEAN_AND_MEAN) + /* On WinCE winsock2.h must be included before windows.h */ + #include + #endif + #include + #endif /* WOLFSSL_SGX */ + #endif +#elif defined(THREADX) + #ifndef SINGLE_THREADED + #ifdef NEED_THREADX_TYPES + #include + #endif + #include + #endif +#elif defined(WOLFSSL_DEOS) + #include "mutexapi.h" +#elif defined(MICRIUM) + /* do nothing, just don't pick Unix */ +#elif defined(FREERTOS) || defined(FREERTOS_TCP) || defined(WOLFSSL_SAFERTOS) + /* do nothing */ +#elif defined(EBSNET) + /* do nothing */ +#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) + /* do nothing */ +#elif defined(FREESCALE_FREE_RTOS) + #include "fsl_os_abstraction.h" +#elif defined(WOLFSSL_VXWORKS) + #include +#elif defined(WOLFSSL_uITRON4) + #include "stddef.h" + #include "kernel.h" +#elif defined(WOLFSSL_uTKERNEL2) + #include "tk/tkernel.h" +#elif defined(WOLFSSL_CMSIS_RTOS) + #include "cmsis_os.h" +#elif defined(WOLFSSL_CMSIS_RTOSv2) + #include "cmsis_os2.h" +#elif defined(WOLFSSL_MDK_ARM) + #if defined(WOLFSSL_MDK5) + #include "cmsis_os.h" + #else + #include + #endif +#elif defined(WOLFSSL_CMSIS_RTOS) + #include "cmsis_os.h" +#elif defined(WOLFSSL_TIRTOS) + #include + #include +#elif defined(WOLFSSL_FROSTED) + #include +#elif defined(INTIME_RTOS) + #include + #include +#elif defined(WOLFSSL_NUCLEUS_1_2) + /* NU_DEBUG needed struct access in nucleus_realloc */ + #define NU_DEBUG + #include "plus/nucleus.h" + #include "nucleus.h" +#elif defined(WOLFSSL_APACHE_MYNEWT) + /* do nothing */ +#elif defined(WOLFSSL_ZEPHYR) + #ifndef SINGLE_THREADED + #include + #endif +#elif defined(WOLFSSL_TELIT_M2MB) + + /* Telit SDK uses C++ compile option (--cpp), which causes link issue + to API's if wrapped in extern "C" */ + #ifdef __cplusplus + } /* extern "C" */ + #endif + + #include "m2mb_types.h" + #include "m2mb_os_types.h" + #include "m2mb_os_api.h" + #include "m2mb_os.h" + #include "m2mb_os_mtx.h" + #ifndef NO_ASN_TIME + #include "m2mb_rtc.h" + #endif + #ifndef NO_FILESYSTEM + #include "m2mb_fs_posix.h" + #endif + + #undef kB /* eliminate conflict in asn.h */ + + #ifdef __cplusplus + extern "C" { + #endif + +#else + #ifndef SINGLE_THREADED + #define WOLFSSL_PTHREADS + #include + #endif + #if defined(OPENSSL_EXTRA) || defined(GOAHEAD_WS) + #include /* for close of BIO */ + #endif +#endif + +/* For FIPS keep the function names the same */ +#ifdef HAVE_FIPS +#define wc_InitMutex InitMutex +#define wc_FreeMutex FreeMutex +#define wc_LockMutex LockMutex +#define wc_UnLockMutex UnLockMutex +#endif /* HAVE_FIPS */ + +#ifdef SINGLE_THREADED + typedef int wolfSSL_Mutex; +#else /* MULTI_THREADED */ + /* FREERTOS comes first to enable use of FreeRTOS Windows simulator only */ + #if defined(FREERTOS) + typedef xSemaphoreHandle wolfSSL_Mutex; + #elif defined(FREERTOS_TCP) + #include "FreeRTOS.h" + #include "semphr.h" + typedef SemaphoreHandle_t wolfSSL_Mutex; + #elif defined(WOLFSSL_SAFERTOS) + typedef struct wolfSSL_Mutex { + signed char mutexBuffer[portQUEUE_OVERHEAD_BYTES]; + xSemaphoreHandle mutex; + } wolfSSL_Mutex; + #elif defined(USE_WINDOWS_API) + typedef CRITICAL_SECTION wolfSSL_Mutex; + #elif defined(WOLFSSL_PTHREADS) + typedef pthread_mutex_t wolfSSL_Mutex; + #elif defined(THREADX) + typedef TX_MUTEX wolfSSL_Mutex; + #elif defined(WOLFSSL_DEOS) + typedef mutex_handle_t wolfSSL_Mutex; + #elif defined(MICRIUM) + typedef OS_MUTEX wolfSSL_Mutex; + #elif defined(EBSNET) + typedef RTP_MUTEX wolfSSL_Mutex; + #elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) + typedef MUTEX_STRUCT wolfSSL_Mutex; + #elif defined(FREESCALE_FREE_RTOS) + typedef mutex_t wolfSSL_Mutex; + #elif defined(WOLFSSL_VXWORKS) + typedef SEM_ID wolfSSL_Mutex; + #elif defined(WOLFSSL_uITRON4) + typedef struct wolfSSL_Mutex { + T_CSEM sem ; + ID id ; + } wolfSSL_Mutex; + #elif defined(WOLFSSL_uTKERNEL2) + typedef struct wolfSSL_Mutex { + T_CSEM sem ; + ID id ; + } wolfSSL_Mutex; + #elif defined(WOLFSSL_MDK_ARM) + #if defined(WOLFSSL_CMSIS_RTOS) + typedef osMutexId wolfSSL_Mutex; + #else + typedef OS_MUT wolfSSL_Mutex; + #endif + #elif defined(WOLFSSL_CMSIS_RTOS) + typedef osMutexId wolfSSL_Mutex; + #elif defined(WOLFSSL_CMSIS_RTOSv2) + typedef osMutexId_t wolfSSL_Mutex; + #elif defined(WOLFSSL_TIRTOS) + typedef ti_sysbios_knl_Semaphore_Handle wolfSSL_Mutex; + #elif defined(WOLFSSL_FROSTED) + typedef mutex_t * wolfSSL_Mutex; + #elif defined(INTIME_RTOS) + typedef RTHANDLE wolfSSL_Mutex; + #elif defined(WOLFSSL_NUCLEUS_1_2) + typedef NU_SEMAPHORE wolfSSL_Mutex; + #elif defined(WOLFSSL_ZEPHYR) + typedef struct k_mutex wolfSSL_Mutex; + #elif defined(WOLFSSL_TELIT_M2MB) + typedef M2MB_OS_MTX_HANDLE wolfSSL_Mutex; + #else + #error Need a mutex type in multithreaded mode + #endif /* USE_WINDOWS_API */ +#endif /* SINGLE_THREADED */ + +/* Enable crypt HW mutex for Freescale MMCAU or PIC32MZ */ +#if defined(FREESCALE_MMCAU) || defined(WOLFSSL_MICROCHIP_PIC32MZ) + #ifndef WOLFSSL_CRYPT_HW_MUTEX + #define WOLFSSL_CRYPT_HW_MUTEX 1 + #endif +#endif /* FREESCALE_MMCAU */ + +#ifndef WOLFSSL_CRYPT_HW_MUTEX + #define WOLFSSL_CRYPT_HW_MUTEX 0 +#endif + +#if WOLFSSL_CRYPT_HW_MUTEX + /* wolfSSL_CryptHwMutexInit is called on first wolfSSL_CryptHwMutexLock, + however it's recommended to call this directly on Hw init to avoid possible + race condition where two calls to wolfSSL_CryptHwMutexLock are made at + the same time. */ + int wolfSSL_CryptHwMutexInit(void); + int wolfSSL_CryptHwMutexLock(void); + int wolfSSL_CryptHwMutexUnLock(void); +#else + /* Define stubs, since HW mutex is disabled */ + #define wolfSSL_CryptHwMutexInit() 0 /* Success */ + #define wolfSSL_CryptHwMutexLock() 0 /* Success */ + #define wolfSSL_CryptHwMutexUnLock() (void)0 /* Success */ +#endif /* WOLFSSL_CRYPT_HW_MUTEX */ + +/* Mutex functions */ +WOLFSSL_API int wc_InitMutex(wolfSSL_Mutex*); +WOLFSSL_API wolfSSL_Mutex* wc_InitAndAllocMutex(void); +WOLFSSL_API int wc_FreeMutex(wolfSSL_Mutex*); +WOLFSSL_API int wc_LockMutex(wolfSSL_Mutex*); +WOLFSSL_API int wc_UnLockMutex(wolfSSL_Mutex*); +#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) +/* dynamiclly set which mutex to use. unlock / lock is controlled by flag */ +typedef void (mutex_cb)(int flag, int type, const char* file, int line); + +WOLFSSL_API int wc_LockMutex_ex(int flag, int type, const char* file, int line); +WOLFSSL_API int wc_SetMutexCb(mutex_cb* cb); +#endif + +/* main crypto initialization function */ +WOLFSSL_API int wolfCrypt_Init(void); +WOLFSSL_API int wolfCrypt_Cleanup(void); + +/* filesystem abstraction layer, used by ssl.c */ +#ifndef NO_FILESYSTEM + +#if defined(EBSNET) + #include "vfapi.h" + #include "vfile.h" + + #define XFILE int + #define XFOPEN(NAME, MODE) vf_open((const char *)NAME, VO_RDONLY, 0); + #define XFSEEK vf_lseek + #define XFTELL vf_tell + #define XREWIND vf_rewind + #define XFREAD(BUF, SZ, AMT, FD) vf_read(FD, BUF, SZ*AMT) + #define XFWRITE(BUF, SZ, AMT, FD) vf_write(FD, BUF, SZ*AMT) + #define XFCLOSE vf_close + #define XSEEK_END VSEEK_END + #define XBADFILE -1 + #define XFGETS(b,s,f) -2 /* Not ported yet */ +#elif defined(LSR_FS) + #include + #define XFILE struct fs_file* + #define XFOPEN(NAME, MODE) fs_open((char*)NAME); + #define XFSEEK(F, O, W) (void)F + #define XFTELL(F) (F)->len + #define XREWIND(F) (void)F + #define XFREAD(BUF, SZ, AMT, F) fs_read(F, (char*)BUF, SZ*AMT) + #define XFWRITE(BUF, SZ, AMT, F) fs_write(F, (char*)BUF, SZ*AMT) + #define XFCLOSE fs_close + #define XSEEK_END 0 + #define XBADFILE NULL + #define XFGETS(b,s,f) -2 /* Not ported yet */ +#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) + #define XFILE MQX_FILE_PTR + #define XFOPEN fopen + #define XFSEEK fseek + #define XFTELL ftell + #define XREWIND(F) fseek(F, 0, IO_SEEK_SET) + #define XFREAD fread + #define XFWRITE fwrite + #define XFCLOSE fclose + #define XSEEK_END IO_SEEK_END + #define XBADFILE NULL + #define XFGETS fgets +#elif defined(WOLFSSL_DEOS) + #define NO_FILESYSTEM + #warning "TODO - DDC-I Certifiable Fast File System for Deos is not integrated" + //#define XFILE bfd * + +#elif defined(MICRIUM) + #include + #define XFILE FS_FILE* + #define XFOPEN fs_fopen + #define XFSEEK fs_fseek + #define XFTELL fs_ftell + #define XREWIND fs_rewind + #define XFREAD fs_fread + #define XFWRITE fs_fwrite + #define XFCLOSE fs_fclose + #define XSEEK_END FS_SEEK_END + #define XBADFILE NULL + #define XFGETS(b,s,f) -2 /* Not ported yet */ +#elif defined(WOLFSSL_NUCLEUS_1_2) + #include "fal/inc/fal.h" + #define XFILE FILE* + #define XFOPEN fopen + #define XFSEEK fseek + #define XFTELL ftell + #define XREWIND rewind + #define XFREAD fread + #define XFWRITE fwrite + #define XFCLOSE fclose + #define XSEEK_END PSEEK_END + #define XBADFILE NULL +#elif defined(WOLFSSL_APACHE_MYNEWT) + #include + #define XFILE struct fs_file* + + #define XFOPEN mynewt_fopen + #define XFSEEK mynewt_fseek + #define XFTELL mynewt_ftell + #define XREWIND mynewt_rewind + #define XFREAD mynewt_fread + #define XFWRITE mynewt_fwrite + #define XFCLOSE mynewt_fclose + #define XSEEK_END 2 + #define XBADFILE NULL + #define XFGETS(b,s,f) -2 /* Not ported yet */ +#elif defined(WOLFSSL_ZEPHYR) + #include + + #define XFILE struct fs_file_t* + #define STAT struct fs_dirent + + XFILE z_fs_open(const char* filename, const char* perm); + int z_fs_close(XFILE file); + + #define XFOPEN z_fs_open + #define XFCLOSE z_fs_close + #define XFSEEK fs_seek + #define XFTELL fs_tell + #define XFREWIND fs_rewind + #define XREWIND(F) fs_seek(F, 0, FS_SEEK_SET) + #define XFREAD(P,S,N,F) fs_read(F, P, S*N) + #define XFWRITE(P,S,N,F) fs_write(F, P, S*N) + #define XSEEK_END FS_SEEK_END + #define XBADFILE NULL + #define XFGETS(b,s,f) -2 /* Not ported yet */ + +#elif defined(WOLFSSL_TELIT_M2MB) + #define XFILE INT32 + #define XFOPEN(NAME, MODE) m2mb_fs_open((NAME), 0, (MODE)) + #define XFSEEK(F, O, W) m2mb_fs_lseek((F), (O), (W)) + #define XFTELL(F) m2mb_fs_lseek((F), 0, M2MB_SEEK_END) + #define XREWIND(F) (void)F + #define XFREAD(BUF, SZ, AMT, F) m2mb_fs_read((F), (BUF), (SZ)*(AMT)) + #define XFWRITE(BUF, SZ, AMT, F) m2mb_fs_write((F), (BUF), (SZ)*(AMT)) + #define XFCLOSE m2mb_fs_close + #define XSEEK_END M2MB_SEEK_END + #define XBADFILE -1 + #define XFGETS(b,s,f) -2 /* Not ported yet */ + +#elif defined(WOLFSSL_USER_FILESYSTEM) + /* To be defined in user_settings.h */ +#else + /* stdio, default case */ + #include + #define XFILE FILE* + #if defined(WOLFSSL_MDK_ARM) + extern FILE * wolfSSL_fopen(const char *name, const char *mode) ; + #define XFOPEN wolfSSL_fopen + #else + #define XFOPEN fopen + #endif + #define XFSEEK fseek + #define XFTELL ftell + #define XREWIND rewind + #define XFREAD fread + #define XFWRITE fwrite + #define XFCLOSE fclose + #define XSEEK_END SEEK_END + #define XBADFILE NULL + #define XFGETS fgets + + #if !defined(USE_WINDOWS_API) && !defined(NO_WOLFSSL_DIR)\ + && !defined(WOLFSSL_NUCLEUS) && !defined(WOLFSSL_NUCLEUS_1_2) + #include + #include + #include + #endif +#endif + + #ifndef MAX_FILENAME_SZ + #define MAX_FILENAME_SZ 256 /* max file name length */ + #endif + #ifndef MAX_PATH + #define MAX_PATH 256 + #endif + +#if !defined(NO_WOLFSSL_DIR) && !defined(WOLFSSL_NUCLEUS) && \ + !defined(WOLFSSL_NUCLEUS_1_2) + typedef struct ReadDirCtx { + #ifdef USE_WINDOWS_API + WIN32_FIND_DATAA FindFileData; + HANDLE hFind; + #elif defined(WOLFSSL_ZEPHYR) + struct fs_dirent entry; + struct fs_dir_t dir; + struct fs_dirent s; + struct fs_dir_t* dirp; + + #elif defined(WOLFSSL_TELIT_M2MB) + M2MB_DIR_T* dir; + struct M2MB_DIRENT* entry; + struct M2MB_STAT s; + #else + struct dirent* entry; + DIR* dir; + struct stat s; + #endif + char name[MAX_FILENAME_SZ]; + } ReadDirCtx; + + #define WC_READDIR_NOFILE -1 + + WOLFSSL_API int wc_ReadDirFirst(ReadDirCtx* ctx, const char* path, char** name); + WOLFSSL_API int wc_ReadDirNext(ReadDirCtx* ctx, const char* path, char** name); + WOLFSSL_API void wc_ReadDirClose(ReadDirCtx* ctx); +#endif /* !NO_WOLFSSL_DIR */ + +#endif /* !NO_FILESYSTEM */ + +/* Windows API defines its own min() macro. */ +#if defined(USE_WINDOWS_API) + #if defined(min) || defined(WOLFSSL_MYSQL_COMPATIBLE) + #define WOLFSSL_HAVE_MIN + #endif /* min */ + #if defined(max) || defined(WOLFSSL_MYSQL_COMPATIBLE) + #define WOLFSSL_HAVE_MAX + #endif /* max */ +#endif /* USE_WINDOWS_API */ + +/* Time functions */ +#ifndef NO_ASN_TIME +#if defined(USER_TIME) + /* Use our gmtime and time_t/struct tm types. + Only needs seconds since EPOCH using XTIME function. + time_t XTIME(time_t * timer) {} + */ + #define WOLFSSL_GMTIME + #ifndef HAVE_TM_TYPE + #define USE_WOLF_TM + #endif + #ifndef HAVE_TIME_T_TYPE + #define USE_WOLF_TIME_T + #endif + +#elif defined(TIME_OVERRIDES) + /* Override XTIME() and XGMTIME() functionality. + Requires user to provide these functions: + time_t XTIME(time_t * timer) {} + struct tm* XGMTIME(const time_t* timer, struct tm* tmp) {} + */ + #ifndef HAVE_TIME_T_TYPE + #define USE_WOLF_TIME_T + #endif + #ifndef HAVE_TM_TYPE + #define USE_WOLF_TM + #endif + #define NEED_TMP_TIME + +#elif defined(WOLFSSL_XILINX) && defined(FREERTOS) + #define USER_TIME + #include + +#elif defined(HAVE_RTP_SYS) + #include "os.h" /* dc_rtc_api needs */ + #include "dc_rtc_api.h" /* to get current time */ + + /* uses parital structures */ + #define XTIME(tl) (0) + #define XGMTIME(c, t) rtpsys_gmtime((c)) + +#elif defined(WOLFSSL_DEOS) + #define XTIME(t1) deos_time((t1)) + #define WOLFSSL_GMTIME + #define USE_WOLF_TM + #define USE_WOLF_TIME_T + +#elif defined(MICRIUM) + #include + #include + #define XTIME(t1) micrium_time((t1)) + #define WOLFSSL_GMTIME + +#elif defined(MICROCHIP_TCPIP_V5) || defined(MICROCHIP_TCPIP) + #include + #define XTIME(t1) pic32_time((t1)) + #define XGMTIME(c, t) gmtime((c)) + +#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) + #ifdef FREESCALE_MQX_4_0 + #include + extern time_t mqx_time(time_t* timer); + #else + #define HAVE_GMTIME_R + #endif + #define XTIME(t1) mqx_time((t1)) + +#elif defined(FREESCALE_KSDK_BM) || defined(FREESCALE_FREE_RTOS) || defined(FREESCALE_KSDK_FREERTOS) + #include + #ifndef XTIME + /*extern time_t ksdk_time(time_t* timer);*/ + #define XTIME(t1) ksdk_time((t1)) + #endif + #define XGMTIME(c, t) gmtime((c)) + +#elif defined(WOLFSSL_ATMEL) && defined(WOLFSSL_ATMEL_TIME) + #define XTIME(t1) atmel_get_curr_time_and_date((t1)) + #define WOLFSSL_GMTIME + #define USE_WOLF_TM + #define USE_WOLF_TIME_T + +#elif defined(WOLFSSL_WICED) + #include + time_t wiced_pseudo_unix_epoch_time(time_t * timer); + #define XTIME(t1) wiced_pseudo_unix_epoch_time((t1)) + #define HAVE_GMTIME_R + +#elif defined(IDIRECT_DEV_TIME) + /*Gets the timestamp from cloak software owned by VT iDirect + in place of time() from */ + #include + #define XTIME(t1) idirect_time((t1)) + #define XGMTIME(c, t) gmtime((c)) + +#elif defined(_WIN32_WCE) + #include + #define XTIME(t1) windows_time((t1)) + #define WOLFSSL_GMTIME + +#elif defined(WOLFSSL_APACHE_MYNEWT) + #include "os/os_time.h" + #define XTIME(t1) mynewt_time((t1)) + #define WOLFSSL_GMTIME + #define USE_WOLF_TM + #define USE_WOLF_TIME_T + +#elif defined(WOLFSSL_ZEPHYR) + #ifndef _POSIX_C_SOURCE + #include + #else + #include + #endif + + typedef signed int time_t; + + time_t z_time(time_t *timer); + + #define XTIME(tl) z_time((tl)) + #define XGMTIME(c, t) gmtime((c)) + #define WOLFSSL_GMTIME + + #define USE_WOLF_TM + +#elif defined(WOLFSSL_TELIT_M2MB) + typedef long time_t; + extern time_t m2mb_xtime(time_t * timer); + #define XTIME(tl) m2mb_xtime((tl)) + #ifdef WOLFSSL_TLS13 + extern time_t m2mb_xtime_ms(time_t * timer); + #define XTIME_MS(tl) m2mb_xtime_ms((tl)) + #endif + #ifndef NO_CRYPT_BENCHMARK + extern double m2mb_xtime_bench(int reset); + #define WOLFSSL_CURRTIME_REMAP m2mb_xtime_bench + #endif + #define XGMTIME(c, t) gmtime((c)) + #define WOLFSSL_GMTIME + #define USE_WOLF_TM + +#else + /* default */ + /* uses complete facility */ + #include + #if defined(HAVE_SYS_TIME_H) + #include + #endif + + /* PowerPC time_t is int */ + #ifdef __PPC__ + #define TIME_T_NOT_64BIT + #endif +#endif + +#ifdef SIZEOF_TIME_T + /* check if size of time_t from autoconf is less than 8 bytes (64bits) */ + #if SIZEOF_TIME_T < 8 + #undef TIME_T_NOT_64BIT + #define TIME_T_NOT_64BIT + #endif +#endif +#ifdef TIME_T_NOT_LONG + /* one old reference to TIME_T_NOT_LONG in GCC-ARM example README + * this keeps support for the old macro name */ + #undef TIME_T_NOT_64BIT + #define TIME_T_NOT_64BIT +#endif + +/* Map default time functions */ +#if !defined(XTIME) && !defined(TIME_OVERRIDES) && !defined(USER_TIME) + #define XTIME(tl) time((tl)) +#endif +#if !defined(XGMTIME) && !defined(TIME_OVERRIDES) + #if defined(WOLFSSL_GMTIME) || !defined(HAVE_GMTIME_R) || defined(WOLF_C99) + #define XGMTIME(c, t) gmtime((c)) + #else + #define XGMTIME(c, t) gmtime_r((c), (t)) + #define NEED_TMP_TIME + #endif +#endif +#if !defined(XVALIDATE_DATE) && !defined(HAVE_VALIDATE_DATE) + #define USE_WOLF_VALIDDATE + #define XVALIDATE_DATE(d, f, t) ValidateDate((d), (f), (t)) +#endif + +/* wolf struct tm and time_t */ +#if defined(USE_WOLF_TM) + struct tm { + int tm_sec; /* seconds after the minute [0-60] */ + int tm_min; /* minutes after the hour [0-59] */ + int tm_hour; /* hours since midnight [0-23] */ + int tm_mday; /* day of the month [1-31] */ + int tm_mon; /* months since January [0-11] */ + int tm_year; /* years since 1900 */ + int tm_wday; /* days since Sunday [0-6] */ + int tm_yday; /* days since January 1 [0-365] */ + int tm_isdst; /* Daylight Savings Time flag */ + long tm_gmtoff; /* offset from CUT in seconds */ + char *tm_zone; /* timezone abbreviation */ + }; +#endif /* USE_WOLF_TM */ +#if defined(USE_WOLF_TIME_T) + typedef long time_t; +#endif +#if defined(USE_WOLF_SUSECONDS_T) + typedef long suseconds_t; +#endif +#if defined(USE_WOLF_TIMEVAL_T) + struct timeval + { + time_t tv_sec; + suseconds_t tv_usec; + }; +#endif + + /* forward declarations */ +#if defined(USER_TIME) + struct tm* gmtime(const time_t* timer); + extern time_t XTIME(time_t * timer); + + #ifdef STACK_TRAP + /* for stack trap tracking, don't call os gmtime on OS X/linux, + uses a lot of stack spce */ + extern time_t time(time_t * timer); + #define XTIME(tl) time((tl)) + #endif /* STACK_TRAP */ + +#elif defined(TIME_OVERRIDES) + extern time_t XTIME(time_t * timer); + extern struct tm* XGMTIME(const time_t* timer, struct tm* tmp); +#elif defined(WOLFSSL_GMTIME) + struct tm* gmtime(const time_t* timer); +#endif +#endif /* NO_ASN_TIME */ + +#ifndef WOLFSSL_LEANPSK + char* mystrnstr(const char* s1, const char* s2, unsigned int n); +#endif + +#ifndef FILE_BUFFER_SIZE + #define FILE_BUFFER_SIZE 1024 /* default static file buffer size for input, + will use dynamic buffer if not big enough */ +#endif + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLF_CRYPT_PORT_H */ + diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/wolfevent.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/wolfevent.h new file mode 100755 index 0000000..0f8c08c --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/wolfevent.h @@ -0,0 +1,120 @@ +/* wolfevent.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#ifndef _WOLF_EVENT_H_ +#define _WOLF_EVENT_H_ + +#ifdef __cplusplus + extern "C" { +#endif + +#ifndef SINGLE_THREADED + #include +#endif + +typedef struct WOLF_EVENT WOLF_EVENT; +typedef unsigned short WOLF_EVENT_FLAG; + +typedef enum WOLF_EVENT_TYPE { + WOLF_EVENT_TYPE_NONE, +#ifdef WOLFSSL_ASYNC_CRYPT + WOLF_EVENT_TYPE_ASYNC_WOLFSSL, /* context is WOLFSSL* */ + WOLF_EVENT_TYPE_ASYNC_WOLFCRYPT, /* context is WC_ASYNC_DEV */ + WOLF_EVENT_TYPE_ASYNC_FIRST = WOLF_EVENT_TYPE_ASYNC_WOLFSSL, + WOLF_EVENT_TYPE_ASYNC_LAST = WOLF_EVENT_TYPE_ASYNC_WOLFCRYPT, +#endif /* WOLFSSL_ASYNC_CRYPT */ +} WOLF_EVENT_TYPE; + +typedef enum WOLF_EVENT_STATE { + WOLF_EVENT_STATE_READY, + WOLF_EVENT_STATE_PENDING, + WOLF_EVENT_STATE_DONE, +} WOLF_EVENT_STATE; + +struct WOLF_EVENT { + /* double linked list */ + WOLF_EVENT* next; + WOLF_EVENT* prev; + + void* context; + union { + void* ptr; +#ifdef WOLFSSL_ASYNC_CRYPT + struct WC_ASYNC_DEV* async; +#endif + } dev; +#ifdef HAVE_CAVIUM + word64 reqId; + #ifdef WOLFSSL_NITROX_DEBUG + word32 pendCount; + #endif +#endif +#ifndef WC_NO_ASYNC_THREADING + pthread_t threadId; +#endif + int ret; /* Async return code */ + unsigned int flags; + WOLF_EVENT_TYPE type; + WOLF_EVENT_STATE state; +}; + +enum WOLF_POLL_FLAGS { + WOLF_POLL_FLAG_CHECK_HW = 0x01, +}; + +typedef struct { + WOLF_EVENT* head; /* head of queue */ + WOLF_EVENT* tail; /* tail of queue */ +#ifndef SINGLE_THREADED + wolfSSL_Mutex lock; /* queue lock */ +#endif + int count; +} WOLF_EVENT_QUEUE; + + +#ifdef HAVE_WOLF_EVENT + +/* Event */ +WOLFSSL_API int wolfEvent_Init(WOLF_EVENT* event, WOLF_EVENT_TYPE type, void* context); +WOLFSSL_API int wolfEvent_Poll(WOLF_EVENT* event, WOLF_EVENT_FLAG flags); + +/* Event Queue */ +WOLFSSL_API int wolfEventQueue_Init(WOLF_EVENT_QUEUE* queue); +WOLFSSL_API int wolfEventQueue_Push(WOLF_EVENT_QUEUE* queue, WOLF_EVENT* event); +WOLFSSL_API int wolfEventQueue_Pop(WOLF_EVENT_QUEUE* queue, WOLF_EVENT** event); +WOLFSSL_API int wolfEventQueue_Poll(WOLF_EVENT_QUEUE* queue, void* context_filter, + WOLF_EVENT** events, int maxEvents, WOLF_EVENT_FLAG flags, int* eventCount); +WOLFSSL_API int wolfEventQueue_Count(WOLF_EVENT_QUEUE* queue); +WOLFSSL_API void wolfEventQueue_Free(WOLF_EVENT_QUEUE* queue); + +/* the queue mutex must be locked prior to calling these */ +WOLFSSL_API int wolfEventQueue_Add(WOLF_EVENT_QUEUE* queue, WOLF_EVENT* event); +WOLFSSL_API int wolfEventQueue_Remove(WOLF_EVENT_QUEUE* queue, WOLF_EVENT* event); + + +#endif /* HAVE_WOLF_EVENT */ + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* _WOLF_EVENT_H_ */ diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/wolfmath.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/wolfmath.h new file mode 100755 index 0000000..1db3223 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfcrypt/wolfmath.h @@ -0,0 +1,96 @@ +/* wolfmath.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +#ifndef __WOLFMATH_H__ +#define __WOLFMATH_H__ + +#ifdef __cplusplus + extern "C" { +#endif + +#ifdef WOLFSSL_PUBLIC_MP + #define MP_API WOLFSSL_API +#else + #define MP_API WOLFSSL_LOCAL +#endif + +#ifndef MIN + #define MIN(x,y) ((x)<(y)?(x):(y)) +#endif + +#ifndef MAX + #define MAX(x,y) ((x)>(y)?(x):(y)) +#endif + +/* timing resistance array */ +#if !defined(WC_NO_CACHE_RESISTANT) && \ + ((defined(HAVE_ECC) && defined(ECC_TIMING_RESISTANT)) || \ + (defined(USE_FAST_MATH) && defined(TFM_TIMING_RESISTANT))) + + extern const wolfssl_word wc_off_on_addr[2]; +#endif + + +/* common math functions */ +MP_API int get_digit_count(mp_int* a); +MP_API mp_digit get_digit(mp_int* a, int n); +MP_API int get_rand_digit(WC_RNG* rng, mp_digit* d); + +WOLFSSL_API int mp_rand(mp_int* a, int digits, WC_RNG* rng); + +enum { + /* format type */ + WC_TYPE_HEX_STR = 1, + WC_TYPE_UNSIGNED_BIN = 2, +}; + +WOLFSSL_API int wc_export_int(mp_int* mp, byte* buf, word32* len, + word32 keySz, int encType); + +#ifdef HAVE_WOLF_BIGINT + #if !defined(WOLF_BIGINT_DEFINED) + /* raw big integer */ + typedef struct WC_BIGINT { + byte* buf; + word32 len; + void* heap; + } WC_BIGINT; + #define WOLF_BIGINT_DEFINED + #endif + + WOLFSSL_LOCAL void wc_bigint_init(WC_BIGINT* a); + WOLFSSL_LOCAL int wc_bigint_alloc(WC_BIGINT* a, word32 sz); + WOLFSSL_LOCAL int wc_bigint_from_unsigned_bin(WC_BIGINT* a, const byte* in, word32 inlen); + WOLFSSL_LOCAL int wc_bigint_to_unsigned_bin(WC_BIGINT* a, byte* out, word32* outlen); + WOLFSSL_LOCAL void wc_bigint_zero(WC_BIGINT* a); + WOLFSSL_LOCAL void wc_bigint_free(WC_BIGINT* a); + + WOLFSSL_LOCAL int wc_mp_to_bigint(mp_int* src, WC_BIGINT* dst); + WOLFSSL_LOCAL int wc_mp_to_bigint_sz(mp_int* src, WC_BIGINT* dst, word32 sz); + WOLFSSL_LOCAL int wc_bigint_to_mp(WC_BIGINT* src, mp_int* dst); +#endif /* HAVE_WOLF_BIGINT */ + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* __WOLFMATH_H__ */ diff --git a/beken_os/beken378/func/wolfssl/wolfssl/wolfio.h b/beken_os/beken378/func/wolfssl/wolfssl/wolfio.h new file mode 100755 index 0000000..27290d0 --- /dev/null +++ b/beken_os/beken378/func/wolfssl/wolfssl/wolfio.h @@ -0,0 +1,547 @@ +/* io.h + * + * Copyright (C) 2006-2019 wolfSSL Inc. + * + * This file is part of wolfSSL. + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA + */ + +/*! + \file wolfssl/wolfio.h +*/ + +#ifndef WOLFSSL_IO_H +#define WOLFSSL_IO_H + +#ifdef __cplusplus + extern "C" { +#endif + +/* Micrium uses NetSock I/O callbacks in wolfio.c */ +#if !defined(WOLFSSL_USER_IO) + /* OCSP and CRL_IO require HTTP client */ + #if defined(HAVE_OCSP) || defined(HAVE_CRL_IO) + #ifndef HAVE_HTTP_CLIENT + #define HAVE_HTTP_CLIENT + #endif + #endif +#endif + +#if !defined(WOLFSSL_USER_IO) + /* Micrium uses NetSock I/O callbacks in wolfio.c */ + #if !defined(USE_WOLFSSL_IO) && !defined(MICRIUM) && !defined(WOLFSSL_CONTIKI) + #define USE_WOLFSSL_IO + #endif +#endif + + +#if defined(USE_WOLFSSL_IO) || defined(HAVE_HTTP_CLIENT) + +#ifdef HAVE_LIBZ + #include "zlib.h" +#endif + +#ifndef USE_WINDOWS_API + #if defined(WOLFSSL_LWIP) && !defined(WOLFSSL_APACHE_MYNEWT) + /* lwIP needs to be configured to use sockets API in this mode */ + /* LWIP_SOCKET 1 in lwip/opt.h or in build */ + #include "lwip/sockets.h" + #ifndef LWIP_PROVIDE_ERRNO + #include + #define LWIP_PROVIDE_ERRNO 1 + #endif + #elif defined(FREESCALE_MQX) + #include + #include + #elif defined(FREESCALE_KSDK_MQX) + #include + #elif (defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET)) + #include "rl_net.h" + #include "errno.h" + #elif defined(WOLFSSL_CMSIS_RTOS) + #include "cmsis_os.h" + #elif defined(WOLFSSL_CMSIS_RTOSv2) + #include "cmsis_os2.h" + #elif defined(WOLFSSL_TIRTOS) + #include + #elif defined(FREERTOS_TCP) + #include "FreeRTOS_Sockets.h" + #elif defined(WOLFSSL_IAR_ARM) + /* nothing */ + #elif defined(WOLFSSL_VXWORKS) + #include + #include + #elif defined(WOLFSSL_NUCLEUS_1_2) + #include + #include + #elif defined(WOLFSSL_ATMEL) + #include "socket/include/socket.h" + #elif defined(INTIME_RTOS) + #undef MIN + #undef MAX + #include + #include + #include + #include + #include + #include + /* defines these, to avoid conflict, do undef */ + #undef SOCKADDR + #undef SOCKADDR_IN + #elif defined(WOLFSSL_PRCONNECT_PRO) + #include + #include + #include + #include + #include + #include + #include + #elif defined(WOLFSSL_SGX) + #include + #elif defined(WOLFSSL_APACHE_MYNEWT) && !defined(WOLFSSL_LWIP) + #include + #elif defined(WOLFSSL_DEOS) + #include + #include + #include + #elif defined(WOLFSSL_ZEPHYR) + #include + #elif !defined(WOLFSSL_NO_SOCK) + #include + #include + #ifndef EBSNET + #include + #endif + #include + + #if defined(HAVE_RTP_SYS) + #include + #elif defined(EBSNET) + #include "rtipapi.h" /* errno */ + #include "socket.h" + #elif !defined(DEVKITPRO) && !defined(WOLFSSL_PICOTCP) \ + && !defined(WOLFSSL_CONTIKI) && !defined(WOLFSSL_WICED) + #include + #include + #include + #include + #ifdef __PPU + #include + #else + #include + #endif + #endif + #endif +#endif /* USE_WINDOWS_API */ + +#ifdef __sun + #include +#endif + +#ifdef USE_WINDOWS_API + /* no epipe yet */ + #ifndef WSAEPIPE + #define WSAEPIPE -12345 + #endif + #define SOCKET_EWOULDBLOCK WSAEWOULDBLOCK + #define SOCKET_EAGAIN WSAETIMEDOUT + #define SOCKET_ECONNRESET WSAECONNRESET + #define SOCKET_EINTR WSAEINTR + #define SOCKET_EPIPE WSAEPIPE + #define SOCKET_ECONNREFUSED WSAENOTCONN + #define SOCKET_ECONNABORTED WSAECONNABORTED +#elif defined(__PPU) + #define SOCKET_EWOULDBLOCK SYS_NET_EWOULDBLOCK + #define SOCKET_EAGAIN SYS_NET_EAGAIN + #define SOCKET_ECONNRESET SYS_NET_ECONNRESET + #define SOCKET_EINTR SYS_NET_EINTR + #define SOCKET_EPIPE SYS_NET_EPIPE + #define SOCKET_ECONNREFUSED SYS_NET_ECONNREFUSED + #define SOCKET_ECONNABORTED SYS_NET_ECONNABORTED +#elif defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX) + #if MQX_USE_IO_OLD + /* RTCS old I/O doesn't have an EWOULDBLOCK */ + #define SOCKET_EWOULDBLOCK EAGAIN + #define SOCKET_EAGAIN EAGAIN + #define SOCKET_ECONNRESET RTCSERR_TCP_CONN_RESET + #define SOCKET_EINTR EINTR + #define SOCKET_EPIPE EPIPE + #define SOCKET_ECONNREFUSED RTCSERR_TCP_CONN_REFUSED + #define SOCKET_ECONNABORTED RTCSERR_TCP_CONN_ABORTED + #else + #define SOCKET_EWOULDBLOCK NIO_EWOULDBLOCK + #define SOCKET_EAGAIN NIO_EAGAIN + #define SOCKET_ECONNRESET NIO_ECONNRESET + #define SOCKET_EINTR NIO_EINTR + #define SOCKET_EPIPE NIO_EPIPE + #define SOCKET_ECONNREFUSED NIO_ECONNREFUSED + #define SOCKET_ECONNABORTED NIO_ECONNABORTED + #endif +#elif defined(WOLFSSL_MDK_ARM)|| defined(WOLFSSL_KEIL_TCP_NET) + #define SOCKET_EWOULDBLOCK BSD_ERROR_WOULDBLOCK + #define SOCKET_EAGAIN BSD_ERROR_LOCKED + #define SOCKET_ECONNRESET BSD_ERROR_CLOSED + #define SOCKET_EINTR BSD_ERROR + #define SOCKET_EPIPE BSD_ERROR + #define SOCKET_ECONNREFUSED BSD_ERROR + #define SOCKET_ECONNABORTED BSD_ERROR +#elif defined(WOLFSSL_PICOTCP) + #define SOCKET_EWOULDBLOCK PICO_ERR_EAGAIN + #define SOCKET_EAGAIN PICO_ERR_EAGAIN + #define SOCKET_ECONNRESET PICO_ERR_ECONNRESET + #define SOCKET_EINTR PICO_ERR_EINTR + #define SOCKET_EPIPE PICO_ERR_EIO + #define SOCKET_ECONNREFUSED PICO_ERR_ECONNREFUSED + #define SOCKET_ECONNABORTED PICO_ERR_ESHUTDOWN +#elif defined(FREERTOS_TCP) + #define SOCKET_EWOULDBLOCK FREERTOS_EWOULDBLOCK + #define SOCKET_EAGAIN FREERTOS_EWOULDBLOCK + #define SOCKET_ECONNRESET FREERTOS_SOCKET_ERROR + #define SOCKET_EINTR FREERTOS_SOCKET_ERROR + #define SOCKET_EPIPE FREERTOS_SOCKET_ERROR + #define SOCKET_ECONNREFUSED FREERTOS_SOCKET_ERROR + #define SOCKET_ECONNABORTED FREERTOS_SOCKET_ERROR +#elif defined(WOLFSSL_NUCLEUS_1_2) + #define SOCKET_EWOULDBLOCK NU_WOULD_BLOCK + #define SOCKET_EAGAIN NU_WOULD_BLOCK + #define SOCKET_ECONNRESET NU_NOT_CONNECTED + #define SOCKET_EINTR NU_NOT_CONNECTED + #define SOCKET_EPIPE NU_NOT_CONNECTED + #define SOCKET_ECONNREFUSED NU_CONNECTION_REFUSED + #define SOCKET_ECONNABORTED NU_NOT_CONNECTED +#elif defined(WOLFSSL_DEOS) + #define SOCKET_EWOULDBLOCK EAGAIN + #define SOCKET_EAGAIN EAGAIN + #define SOCKET_ECONNRESET EINTR + #define SOCKET_EINTR EINTR + #define SOCKET_EPIPE EPIPE + #define SOCKET_ECONNREFUSED SOCKET_ERROR + #define SOCKET_ECONNABORTED SOCKET_ERROR +#else + #define SOCKET_EWOULDBLOCK EWOULDBLOCK + #define SOCKET_EAGAIN EAGAIN + #define SOCKET_ECONNRESET ECONNRESET + #define SOCKET_EINTR EINTR + #define SOCKET_EPIPE EPIPE + #define SOCKET_ECONNREFUSED ECONNREFUSED + #define SOCKET_ECONNABORTED ECONNABORTED +#endif /* USE_WINDOWS_API */ + +#ifdef DEVKITPRO + /* from network.h */ + int net_send(int, const void*, int, unsigned int); + int net_recv(int, void*, int, unsigned int); + #define SEND_FUNCTION net_send + #define RECV_FUNCTION net_recv +#elif defined(WOLFSSL_LWIP) && !defined(WOLFSSL_APACHE_MYNEWT) + #define SEND_FUNCTION lwip_send + #define RECV_FUNCTION lwip_recv +#elif defined(WOLFSSL_PICOTCP) + #define SEND_FUNCTION pico_send + #define RECV_FUNCTION pico_recv +#elif defined(FREERTOS_TCP) + #define RECV_FUNCTION(a,b,c,d) FreeRTOS_recv((Socket_t)(a),(void*)(b), (size_t)(c), (BaseType_t)(d)) + #define SEND_FUNCTION(a,b,c,d) FreeRTOS_send((Socket_t)(a),(void*)(b), (size_t)(c), (BaseType_t)(d)) +#elif defined(WOLFSSL_VXWORKS) + #define SEND_FUNCTION send + #define RECV_FUNCTION recv +#elif defined(WOLFSSL_NUCLEUS_1_2) + #define SEND_FUNCTION NU_Send + #define RECV_FUNCTION NU_Recv +#elif defined(WOLFSSL_ZEPHYR) + #ifndef WOLFSSL_MAX_SEND_SZ + #define WOLFSSL_MAX_SEND_SZ 256 + #endif + + #define SEND_FUNCTION send + #define RECV_FUNCTION recv +#else + #define SEND_FUNCTION send + #define RECV_FUNCTION recv + #if !defined(HAVE_SOCKADDR) && !defined(WOLFSSL_NO_SOCK) + #define HAVE_SOCKADDR + #endif +#endif + +#ifdef USE_WINDOWS_API + typedef unsigned int SOCKET_T; +#else + typedef int SOCKET_T; +#endif + +#ifndef WOLFSSL_NO_SOCK + #ifndef XSOCKLENT + #ifdef USE_WINDOWS_API + #define XSOCKLENT int + #else + #define XSOCKLENT socklen_t + #endif + #endif + + /* Socket Addr Support */ + #ifdef HAVE_SOCKADDR + typedef struct sockaddr SOCKADDR; + typedef struct sockaddr_storage SOCKADDR_S; + typedef struct sockaddr_in SOCKADDR_IN; + #ifdef WOLFSSL_IPV6 + typedef struct sockaddr_in6 SOCKADDR_IN6; + #endif + typedef struct hostent HOSTENT; + #endif /* HAVE_SOCKADDR */ + + /* use gethostbyname for c99 */ + #ifdef WOLF_C99 + #undef HAVE_GETADDRINFO + #endif + + #ifdef HAVE_GETADDRINFO + typedef struct addrinfo ADDRINFO; + #endif +#endif /* WOLFSSL_NO_SOCK */ + + +/* IO API's */ +#ifdef HAVE_IO_TIMEOUT + WOLFSSL_API int wolfIO_SetBlockingMode(SOCKET_T sockfd, int non_blocking); + WOLFSSL_API void wolfIO_SetTimeout(int to_sec); + WOLFSSL_API int wolfIO_Select(SOCKET_T sockfd, int to_sec); +#endif +WOLFSSL_API int wolfIO_TcpConnect(SOCKET_T* sockfd, const char* ip, + unsigned short port, int to_sec); +WOLFSSL_API int wolfIO_Send(SOCKET_T sd, char *buf, int sz, int wrFlags); +WOLFSSL_API int wolfIO_Recv(SOCKET_T sd, char *buf, int sz, int rdFlags); + +#endif /* USE_WOLFSSL_IO || HAVE_HTTP_CLIENT */ + + +#ifdef USE_WINDOWS_API + #ifndef CloseSocket + #define CloseSocket(s) closesocket(s) + #endif + #define StartTCP() { WSADATA wsd; WSAStartup(0x0002, &wsd); } +#elif defined(WOLFSSL_MDK_ARM) || defined(WOLFSSL_KEIL_TCP_NET) + #ifndef CloseSocket + extern int closesocket(int); + #define CloseSocket(s) closesocket(s) + #endif + #define StartTCP() +#else + #ifndef CloseSocket + #define CloseSocket(s) close(s) + #endif + #define StartTCP() + #ifdef FREERTOS_TCP_WINSIM + extern int close(int); + #endif +#endif + + +WOLFSSL_API int BioSend(WOLFSSL* ssl, char *buf, int sz, void *ctx); +WOLFSSL_API int BioReceive(WOLFSSL* ssl, char* buf, int sz, void* ctx); +#if defined(USE_WOLFSSL_IO) + /* default IO callbacks */ + WOLFSSL_API int EmbedReceive(WOLFSSL* ssl, char* buf, int sz, void* ctx); + WOLFSSL_API int EmbedSend(WOLFSSL* ssl, char* buf, int sz, void* ctx); + + #ifdef WOLFSSL_DTLS + WOLFSSL_API int EmbedReceiveFrom(WOLFSSL* ssl, char* buf, int sz, void*); + WOLFSSL_API int EmbedSendTo(WOLFSSL* ssl, char* buf, int sz, void* ctx); + WOLFSSL_API int EmbedGenerateCookie(WOLFSSL* ssl, unsigned char* buf, + int sz, void*); + #ifdef WOLFSSL_MULTICAST + WOLFSSL_API int EmbedReceiveFromMcast(WOLFSSL* ssl, + char* buf, int sz, void*); + #endif /* WOLFSSL_MULTICAST */ + #ifdef WOLFSSL_SESSION_EXPORT + WOLFSSL_API int EmbedGetPeer(WOLFSSL* ssl, char* ip, int* ipSz, + unsigned short* port, int* fam); + WOLFSSL_API int EmbedSetPeer(WOLFSSL* ssl, char* ip, int ipSz, + unsigned short port, int fam); + #endif /* WOLFSSL_SESSION_EXPORT */ + #endif /* WOLFSSL_DTLS */ +#endif /* USE_WOLFSSL_IO */ + +#ifdef HAVE_OCSP + WOLFSSL_API int wolfIO_HttpBuildRequestOcsp(const char* domainName, + const char* path, int ocspReqSz, unsigned char* buf, int bufSize); + WOLFSSL_API int wolfIO_HttpProcessResponseOcsp(int sfd, + unsigned char** respBuf, unsigned char* httpBuf, int httpBufSz, + void* heap); + + WOLFSSL_API int EmbedOcspLookup(void*, const char*, int, unsigned char*, + int, unsigned char**); + WOLFSSL_API void EmbedOcspRespFree(void*, unsigned char*); +#endif + +#ifdef HAVE_CRL_IO + WOLFSSL_API int wolfIO_HttpBuildRequestCrl(const char* url, int urlSz, + const char* domainName, unsigned char* buf, int bufSize); + WOLFSSL_API int wolfIO_HttpProcessResponseCrl(WOLFSSL_CRL* crl, int sfd, + unsigned char* httpBuf, int httpBufSz); + + WOLFSSL_API int EmbedCrlLookup(WOLFSSL_CRL* crl, const char* url, + int urlSz); +#endif + + +#if defined(HAVE_HTTP_CLIENT) + WOLFSSL_API int wolfIO_DecodeUrl(const char* url, int urlSz, char* outName, + char* outPath, unsigned short* outPort); + + WOLFSSL_API int wolfIO_HttpBuildRequest(const char* reqType, + const char* domainName, const char* path, int pathLen, int reqSz, + const char* contentType, unsigned char* buf, int bufSize); + WOLFSSL_LOCAL int wolfIO_HttpBuildRequest_ex(const char* reqType, + const char* domainName, const char* path, int pathLen, int reqSz, + const char* contentType, const char *exHdrs, unsigned char* buf, int bufSize); + WOLFSSL_API int wolfIO_HttpProcessResponse(int sfd, const char** appStrList, + unsigned char** respBuf, unsigned char* httpBuf, int httpBufSz, + int dynType, void* heap); +#endif /* HAVE_HTTP_CLIENT */ + + +/* I/O callbacks */ +typedef int (*CallbackIORecv)(WOLFSSL *ssl, char *buf, int sz, void *ctx); +typedef int (*CallbackIOSend)(WOLFSSL *ssl, char *buf, int sz, void *ctx); +WOLFSSL_API void wolfSSL_CTX_SetIORecv(WOLFSSL_CTX*, CallbackIORecv); +WOLFSSL_API void wolfSSL_CTX_SetIOSend(WOLFSSL_CTX*, CallbackIOSend); +WOLFSSL_API void wolfSSL_SSLSetIORecv(WOLFSSL*, CallbackIORecv); +WOLFSSL_API void wolfSSL_SSLSetIOSend(WOLFSSL*, CallbackIOSend); +/* deprecated old name */ +#define wolfSSL_SetIORecv wolfSSL_CTX_SetIORecv +#define wolfSSL_SetIOSend wolfSSL_CTX_SetIOSend + +WOLFSSL_API void wolfSSL_SetIOReadCtx( WOLFSSL* ssl, void *ctx); +WOLFSSL_API void wolfSSL_SetIOWriteCtx(WOLFSSL* ssl, void *ctx); + +WOLFSSL_API void* wolfSSL_GetIOReadCtx( WOLFSSL* ssl); +WOLFSSL_API void* wolfSSL_GetIOWriteCtx(WOLFSSL* ssl); + +WOLFSSL_API void wolfSSL_SetIOReadFlags( WOLFSSL* ssl, int flags); +WOLFSSL_API void wolfSSL_SetIOWriteFlags(WOLFSSL* ssl, int flags); + + +#ifdef HAVE_NETX + WOLFSSL_LOCAL int NetX_Receive(WOLFSSL *ssl, char *buf, int sz, void *ctx); + WOLFSSL_LOCAL int NetX_Send(WOLFSSL *ssl, char *buf, int sz, void *ctx); + + WOLFSSL_API void wolfSSL_SetIO_NetX(WOLFSSL* ssl, NX_TCP_SOCKET* nxsocket, + ULONG waitoption); +#endif /* HAVE_NETX */ + +#ifdef MICRIUM + WOLFSSL_LOCAL int MicriumSend(WOLFSSL* ssl, char* buf, int sz, void* ctx); + WOLFSSL_LOCAL int MicriumReceive(WOLFSSL* ssl, char* buf, int sz, + void* ctx); + WOLFSSL_LOCAL int MicriumReceiveFrom(WOLFSSL* ssl, char* buf, int sz, + void* ctx); + WOLFSSL_LOCAL int MicriumSendTo(WOLFSSL* ssl, char* buf, int sz, void* ctx); +#endif /* MICRIUM */ + +#if defined(WOLFSSL_APACHE_MYNEWT) && !defined(WOLFSSL_LWIP) + WOLFSSL_LOCAL int Mynewt_Receive(WOLFSSL *ssl, char *buf, int sz, void *ctx); + WOLFSSL_LOCAL int Mynewt_Send(WOLFSSL* ssl, char *buf, int sz, void *ctx); + WOLFSSL_API void wolfSSL_SetIO_Mynewt(WOLFSSL* ssl, struct mn_socket* mnSocket, + struct mn_sockaddr_in* mnSockAddrIn); +#endif /* defined(WOLFSSL_APACHE_MYNEWT) && !defined(WOLFSSL_LWIP) */ + +#ifdef WOLFSSL_UIP + + struct uip_wolfssl_ctx { + union socket_connector { + struct tcp_socket tcp; + struct udp_socket udp; + } conn; + WOLFSSL_CTX *ctx; + WOLFSSL *ssl; + uint8_t *input_databuf; + uint8_t *output_databuf; + uint8_t *ssl_rx_databuf; + int ssl_rb_len; + int ssl_rb_off; + struct process *process; + tcp_socket_data_callback_t input_callback; + tcp_socket_event_callback_t event_callback; + int closing; + uip_ipaddr_t peer_addr; + uint16_t peer_port; + }; + + typedef struct uip_wolfssl_ctx uip_wolfssl_ctx; + + WOLFSSL_LOCAL int uIPSend(WOLFSSL* ssl, char* buf, int sz, void* ctx); + WOLFSSL_LOCAL int uIPReceive(WOLFSSL* ssl, char* buf, int sz, + void* ctx); + WOLFSSL_LOCAL int uIPReceiveFrom(WOLFSSL* ssl, char* buf, int sz, + void* ctx); + WOLFSSL_LOCAL int uIPSendTo(WOLFSSL* ssl, char* buf, int sz, void* ctx); + +#endif + +#ifdef WOLFSSL_DTLS + typedef int (*CallbackGenCookie)(WOLFSSL* ssl, unsigned char* buf, int sz, + void* ctx); + WOLFSSL_API void wolfSSL_CTX_SetGenCookie(WOLFSSL_CTX*, CallbackGenCookie); + WOLFSSL_API void wolfSSL_SetCookieCtx(WOLFSSL* ssl, void *ctx); + WOLFSSL_API void* wolfSSL_GetCookieCtx(WOLFSSL* ssl); + + #ifdef WOLFSSL_SESSION_EXPORT + typedef int (*CallbackGetPeer)(WOLFSSL* ssl, char* ip, int* ipSz, + unsigned short* port, int* fam); + typedef int (*CallbackSetPeer)(WOLFSSL* ssl, char* ip, int ipSz, + unsigned short port, int fam); + + WOLFSSL_API void wolfSSL_CTX_SetIOGetPeer(WOLFSSL_CTX*, CallbackGetPeer); + WOLFSSL_API void wolfSSL_CTX_SetIOSetPeer(WOLFSSL_CTX*, CallbackSetPeer); + #endif /* WOLFSSL_SESSION_EXPORT */ +#endif + + + +#ifndef XINET_NTOP + #define XINET_NTOP(a,b,c,d) inet_ntop((a),(b),(c),(d)) + #ifdef USE_WINDOWS_API /* Windows-friendly definition */ + #undef XINET_NTOP + #define XINET_NTOP(a,b,c,d) InetNtop((a),(b),(c),(d)) + #endif +#endif +#ifndef XINET_PTON + #define XINET_PTON(a,b,c) inet_pton((a),(b),(c)) + #ifdef USE_WINDOWS_API /* Windows-friendly definition */ + #undef XINET_PTON + #define XINET_PTON(a,b,c) InetPton((a),(b),(c)) + #endif +#endif +#ifndef XHTONS + #define XHTONS(a) htons((a)) +#endif +#ifndef XNTOHS + #define XNTOHS(a) ntohs((a)) +#endif + +#ifndef WOLFSSL_IP4 + #define WOLFSSL_IP4 AF_INET +#endif +#ifndef WOLFSSL_IP6 + #define WOLFSSL_IP6 AF_INET6 +#endif + + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* WOLFSSL_IO_H */ diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/bk_patch/ddrv.c b/beken_os/beken378/func/wpa_supplicant-2.9/bk_patch/ddrv.c new file mode 100755 index 0000000..aa72328 --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/bk_patch/ddrv.c @@ -0,0 +1,50 @@ +#include "include.h" +#include "ddrv.h" + +#include "sk_intf.h" +#include "ieee802_11_defs.h" +#include "driver_beken.h" +#include "hostapd_intf_pub.h" + +int ioctl_host_ap(unsigned int cmd, unsigned long arg) +{ + int ret = 0; + switch(cmd) + { + case PRISM2_IOCTL_HOSTAPD: + ret = hapd_intf_ioctl(arg); + break; + + case PRISM2_IOCTL_PRISM2_PARAM: + break; + + case SIOCSIWESSID: + break; + + case SIOCGIWRANGE: + break; + + case SIOCSIWFREQ: + break; + + default: + break; + } + + return ret; +} + +int ioctl_inet(int dev, u8 vif_index, unsigned int cmd, unsigned long arg) +{ + int ret = 0; + + if(ioctl_get_socket_num(vif_index) == dev) + { + ret = ioctl_host_ap(cmd, arg); + } + + return ret; +} + +// eof + diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/bk_patch/ddrv.h b/beken_os/beken378/func/wpa_supplicant-2.9/bk_patch/ddrv.h new file mode 100755 index 0000000..5dbc05b --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/bk_patch/ddrv.h @@ -0,0 +1,19 @@ +#ifndef _DDRV_H_ +#define _DDRV_H_ + +/* These 32 ioctl are wireless device private, for 16 commands. + * Each driver is free to use them for whatever purpose it chooses, + * however the driver *must* export the description of those ioctls + * with SIOCGIWPRIV and *must* use arguments as defined below. + * If you don't follow those rules, DaveM is going to hate you (reason : + * it make mixed 32/64bit operation impossible). + */ +#define SIOCIWFIRSTPRIV 0x8BE0 +#define SIOCIWLASTPRIV 0x8BFF + +extern int ioctl_inet(int dev, u8 vif_index, unsigned int cmd, unsigned long arg); +extern void exit(int seconds); + +#endif +// eof + diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/bk_patch/errno-base.h b/beken_os/beken378/func/wpa_supplicant-2.9/bk_patch/errno-base.h new file mode 100755 index 0000000..6e851d3 --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/bk_patch/errno-base.h @@ -0,0 +1,160 @@ +#ifndef _ASM_GENERIC_ERRNO_BASE_H +#define _ASM_GENERIC_ERRNO_BASE_H + +#define ERRPERM 1 /* Operation not permitted */ +#define ERRNOENT 2 /* No such file or directory */ +#define ERRSRCH 3 /* No such process */ +#define ERRINTR 4 /* Interrupted system call */ +#define EERIO 5 /* I/O error */ +#define ERRNXIO 6 /* No such device or address */ +#define ERR2BIG 7 /* Argument list too long */ +#define ERRNOEXEC 8 /* Exec format error */ +#define ERRBADF 9 /* Bad file number */ +#define ERRCHILD 10 /* No child processes */ +#define ERRAGAIN 11 /* Try again */ +#define ERRNOMEM 12 /* Out of memory */ +#define ERRACCES 13 /* Permission denied */ +#define ERRFAULT 14 /* Bad address */ +#define ERRNOTBLK 15 /* Block device required */ +#define ERRBUSY 16 /* Device or resource busy */ +#define ERREXIST 17 /* File exists */ +#define ERRXDEV 18 /* Cross-device link */ +#define ERRNODEV 19 /* No such device */ +#define ERRNOTDIR 20 /* Not a directory */ +#define ERRISDIR 21 /* Is a directory */ +#define ERRINVAL 22 /* Invalid argument */ +#define ERRNFILE 23 /* File table overflow */ +#define ERRMFILE 24 /* Too many open files */ +#define ERRNOTTY 25 /* Not a typewriter */ +#define ERRTXTBSY 26 /* Text file busy */ +#define ERRFBIG 27 /* File too large */ +#define ERRNOSPC 28 /* No space left on device */ +#define ERRSPIPE 29 /* Illegal seek */ +#define ERRROFS 30 /* Read-only file system */ +#define ERRMLINK 31 /* Too many links */ +#define ERRPIPE 32 /* Broken pipe */ +#define ERRDOM 33 /* Math argument out of domain of func */ +#define ERRRANGE 34 /* Math result not representable */ + + +#define ERRNOMSG 35 /* No message of desired type */ +#define ERRIDRM 36 /* Identifier removed */ +#define ERRCHRNG 37 /* Channel number out of range */ +#define ERRL2NSYNC 38 /* Level 2 not synchronized */ +#define ERRL3HLT 39 /* Level 3 halted */ +#define ERRL3RST 40 /* Level 3 reset */ +#define ERRLNRNG 41 /* Link number out of range */ +#define ERRUNATCH 42 /* Protocol driver not attached */ +#define ERRNOCSI 43 /* No CSI structure available */ +#define ERRL2HLT 44 /* Level 2 halted */ +#define ERRDEADLK 45 /* Resource deadlock would occur */ +#define ERRDEADLOCK ERRDEADLK +#define ERRNOLCK 46 /* No record locks available */ +#define ERRILSEQ 47 /* Illegal byte sequence */ + +#define ERRNONET 50 /* Machine is not on the network */ +#define ERRNODATA 51 /* No data available */ +#define ERRTIME 52 /* Timer expired */ +#define ERRNOSR 53 /* Out of streams resources */ +#define ERRNOSTR 54 /* Device not a stream */ +#define ERRNOPKG 55 /* Package not installed */ + +#define ERRNOLINK 57 /* Link has been severed */ +#define ERRADV 58 /* Advertise error */ +#define ERRSRMNT 59 /* Srmount error */ +#define ERRCOMM 60 /* Communication error on send */ +#define ERRPROTO 61 /* Protocol error */ + +#define ERRMULTIHOP 64 /* Multihop attempted */ + +#define ERRDOTDOT 66 /* RFS specific error */ +#define ERRBADMSG 67 /* Not a data message */ +#define ERRUSERS 68 /* Too many users */ +#define ERRDQUOT 69 /* Quota exceeded */ +#define ERRSTALE 70 /* Stale NFS file handle */ +#define ERRREMOTE 71 /* Object is remote */ +#define ERROVERFLOW 72 /* Value too large for defined data type */ + +/* these errnos are defined by Linux but not HPUX. */ +#define ERRBADE 160 /* Invalid exchange */ +#define ERRBADR 161 /* Invalid request descriptor */ +#define ERRXFULL 162 /* Exchange full */ +#define ERRNOANO 163 /* No anode */ +#define ERRBADRQC 164 /* Invalid request code */ +#define ERRBADSLT 165 /* Invalid slot */ +#define ERRBFONT 166 /* Bad font file format */ +#define ERRNOTUNIQ 167 /* Name not unique on network */ +#define ERRBADFD 168 /* File descriptor in bad state */ +#define ERRREMCHG 169 /* Remote address changed */ +#define ERRLIBACC 170 /* Can not access a needed shared library */ +#define ERRLIBBAD 171 /* Accessing a corrupted shared library */ +#define ERRLIBSCN 172 /* .lib section in a.out corrupted */ +#define ERRLIBMAX 173 /* Attempting to link in too many shared libraries */ +#define ERRLIBEXEC 174 /* Cannot exec a shared library directly */ +#define ERRRESTART 175 /* Interrupted system call should be restarted */ +#define ERRSTRPIPE 176 /* Streams pipe error */ +#define ERRUCLEAN 177 /* Structure needs cleaning */ +#define ERRNOTNAM 178 /* Not a XENIX named type file */ +#define ERRNAVAIL 179 /* No XENIX semaphores available */ +#define ERRISNAM 180 /* Is a named type file */ +#define ERRREMOTEIO 181 /* Remote I/O error */ +#define ERRNOMEDIUM 182 /* No medium found */ +#define ERRMEDIUMTYPE 183 /*Wrong medium type */ +#define ERRNOKEY 184 /* Required key not available */ +#define ERRKEYEXPIRED 185 /* Key has expired */ +#define ERRKEYREVOKED 186 /* Key has been revoked */ +#define ERRKEYREJECTED 187 /* Key was rejected by service */ + +/* We now return you to your regularly scheduled HPUX. */ +#define ERRNOSYM 215 /* symbol does not exist in executable */ +#define ERRNOTSOCK 216 /* Socket operation on non-socket */ +#define ERRDESTADDRREQ 217 /* Destination address required */ +#define ERRMSGSIZE 218 /* Message too long */ +#define ERRPROTOTYPE 219 /* Protocol wrong type for socket */ +#define ERRNOPROTOOPT 220 /* Protocol not available */ +#define ERRPROTONOSUPPORT 221 /* Protocol not supported */ +#define ERRSOCKTNOSUPPORT 222 /* Socket type not supported */ +#define ERROPNOTSUPP 223 /* Operation not supported on transport endpoint */ +#define ERRPFNOSUPPORT 224 /* Protocol family not supported */ +#define ERRAFNOSUPPORT 225 /* Address family not supported by protocol */ +#define ERRADDRINUSE 226 /* Address already in use */ +#define ERRADDRNOTAVAIL 227 /* Cannot assign requested address */ +#define ERRNETDOWN 228 /* Network is down */ +#define ERRNETUNREACH 229 /* Network is unreachable */ +#define ERRNETRESET 230 /* Network dropped connection because of reset */ +#define ERRCONNABORTED 231 /* Software caused connection abort */ +#define ERRCONNRESET 232 /* Connection reset by peer */ +#define ERRNOBUFS 233 /*No buffer space available */ +#define ERRISCONN 234 /*Transport endpoint is already connected */ +#define ERRNOTCONN 235 /* Transport endpoint is not connected */ +#define ERRSHUTDOWN 236 /* Cannot send after transport endpoint shutdown */ +#define ERRTOOMANYREFS 237 /* Too many references: cannot splice */ +#define ERRREFUSED ERRCONNREFUSED /* for HP's NFS apparently */ +#define ERRTIMEDOUT 238 /* Connection timed out */ +#define ERRCONNREFUSED 239 /* Connection refused */ +#define ERRREMOTERELEASE 240 /* Remote peer released connection */ +#define ERRHOSTDOWN 241 /* Host is down */ +#define ERRHOSTUNREACH 242 /* No route to host */ + +#define ERRALREADY 244 /* Operation already in progress */ +#define ERRINPROGRESS 245 /* Operation now in progress */ +#define ERRWOULDBLOCK 246 /* Operation would block (Linux returns EAGAIN) */ +#define ERRNOTEMPTY 247 /* Directory not empty */ +#define ERRNAMETOOLONG 248 /* File name too long */ +#define ERRLOOP 249 /* Too many symbolic links encountered */ +#define ERRNOSYS 251 /* Function not implemented */ + +#define ERRNOTSUP 252 /* Function not implemented (POSIX.4 / HPUX) */ +#define ERRCANCELLED 253 /* aio request was canceled before complete (POSIX.4 / HPUX) */ +#define ERRCANCELED ERRCANCELLED /* SuSv3 and Solaris wants one 'L' */ + +/* for robust mutexes */ +#define ERROWNERDEAD 254 /* Owner died */ +#define ERRNOTRECOVERABLE 255 /* State not recoverable */ + +#define ERRRFKILL 256 /* Operation not possible due to RF-kill */ + +#define ERRHWPOISON 257 /* Memory page has hardware error */ +#endif +// eof + diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/bk_patch/fake_socket.c b/beken_os/beken378/func/wpa_supplicant-2.9/bk_patch/fake_socket.c new file mode 100755 index 0000000..e80295c --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/bk_patch/fake_socket.c @@ -0,0 +1,396 @@ +#include "include.h" +#include "fake_socket.h" +#include "mem_pub.h" +#include "uart_pub.h" +#include "hostapd_intf_pub.h" + +/* + * RWIP use ke_sk_xx to recv/send mesages, while non-RWIP use fsocket_xxxx. + */ + +static SOCKET_ENTITY socket_entity = { + DL_LIST_HEAD_INIT(socket_entity.sk_head) +}; + +extern void bmsg_skt_tx_sender(void *arg); + +/** + * append @buf to socket->sk_rx_msg list + */ +int ke_sk_send(SOCKET sk, const unsigned char *buf, int len, int flag) +{ + int ret = 0; + unsigned char *data_buf; + BK_SOCKET *element; + SOCKET_MSG *sk_msg; + GLOBAL_INT_DECLARATION(); + + SK_PRT("ke_tx:%d,buf:0x%x, len:%d\r\n", sk, buf, len); + element = sk_get_sk_element(sk); + if(0 == element) + { + goto tx_exit; + } + + sk_msg = (SOCKET_MSG *)os_malloc(sizeof(SOCKET_MSG)); + if(0 == sk_msg) + { + goto tx_exit; + } + data_buf = (unsigned char *)os_malloc(len); + if(0 == data_buf) + { + goto malloc_buf_exit; + } + ret = len; + sk_msg->len = len; + sk_msg->msg = data_buf; + + os_memcpy(sk_msg->msg, buf, len); + + GLOBAL_INT_DISABLE(); + dl_list_add_tail(&element->sk_rx_msg, &sk_msg->data); + GLOBAL_INT_RESTORE(); + + return ret; + +malloc_buf_exit: + os_free(sk_msg); + sk_msg = NULL; + +tx_exit: + return ret; +} + +/** + * recv buf from socket->sk_tx_msg list. + */ +int ke_sk_recv(SOCKET sk, const unsigned char *buf, int len, int flag) +{ + int count; + int ret = 0; + BK_SOCKET *element; + SOCKET_MSG *sk_msg, *tmp; + GLOBAL_INT_DECLARATION(); + + SK_PRT("ke_rx:%d,buf:0x%x, len:%d\r\n", sk, buf, len); + element = sk_get_sk_element(sk); + if(0 == element) + { + goto rx_exit; + } + + GLOBAL_INT_DISABLE(); + dl_list_for_each_safe(sk_msg, tmp, &element->sk_tx_msg, SOCKET_MSG, data) + { + count = MIN(sk_msg->len, len); + + ASSERT(count); + ASSERT(sk_msg); + SK_PRT("r1:%d,buf:0x%x, len:%d\r\n", sk, buf, count); + os_memcpy((void *)buf, (void *)sk_msg->msg, count); + + ret = count; + + os_free(sk_msg->msg); + sk_msg->msg = 0; + sk_msg->len = 0; + + dl_list_del(&sk_msg->data); + os_free(sk_msg); + sk_msg = 0; + + break; + } + + GLOBAL_INT_RESTORE(); + return ret; + +rx_exit: + return 0; +} + +int ke_sk_recv_peek_next_payload_size(SOCKET sk) +{ + int ret = 0; + BK_SOCKET *element; + SOCKET_MSG *sk_msg, *tmp; + GLOBAL_INT_DECLARATION(); + + element = sk_get_sk_element(sk); + if(0 == element) + { + goto rx_exit; + } + + GLOBAL_INT_DISABLE(); + dl_list_for_each_safe(sk_msg, tmp, &element->sk_tx_msg, SOCKET_MSG, data) + { + ret = sk_msg->len; + break; + } + + GLOBAL_INT_RESTORE(); + +rx_exit: + return ret; +} + +int ke_sk_send_peek_next_payload_size(SOCKET sk) +{ + int ret = 0; + BK_SOCKET *element; + SOCKET_MSG *sk_msg, *tmp; + GLOBAL_INT_DECLARATION(); + + element = sk_get_sk_element(sk); + if(0 == element) + { + goto rx_exit; + } + + GLOBAL_INT_DISABLE(); + dl_list_for_each_safe(sk_msg, tmp, &element->sk_rx_msg, SOCKET_MSG, data) + { + ret = sk_msg->len; + break; + } + + GLOBAL_INT_RESTORE(); + +rx_exit: + return ret; +} + +BK_SOCKET *sk_get_sk_element(SOCKET sk) +{ + BK_SOCKET *tmp; + BK_SOCKET *bk_sk_ptr; + GLOBAL_INT_DECLARATION(); + + GLOBAL_INT_DISABLE(); + + dl_list_for_each_safe(bk_sk_ptr, tmp, &socket_entity.sk_head, BK_SOCKET, sk_element) + { + if(sk == bk_sk_ptr->sk) + { + GLOBAL_INT_RESTORE(); + return bk_sk_ptr; + } + } + + GLOBAL_INT_RESTORE(); + return 0; +} + +SOCKET fsocket_init(int af, int type, int protocol) +{ + SOCKET sk; + BK_SOCKET *sk_ptr; + GLOBAL_INT_DECLARATION(); + + sk = af + type + protocol; + if (0 != sk_get_sk_element(sk)) + { + os_printf("%s sk=%d exist\n", __FUNCTION__, sk); + return sk; + } + + sk_ptr = (BK_SOCKET *)os_malloc(sizeof(BK_SOCKET)); + if(0 == sk_ptr) + { + SK_PRT("create fsocket_init unexceptionally\r\n"); + return 0; + } + + sk_ptr->sk = sk; + + GLOBAL_INT_DISABLE(); + dl_list_init(&sk_ptr->sk_rx_msg); + dl_list_init(&sk_ptr->sk_tx_msg); + + dl_list_add(&socket_entity.sk_head, &sk_ptr->sk_element); + GLOBAL_INT_RESTORE(); + + SK_PRT("create fsocket_init:%d\r\n", sk); + return sk; +} + +/* + * + */ +int fsocket_send(SOCKET sk, const unsigned char *buf, int len, S_TYPE_PTR type) +{ + int ret = 0; + BK_SOCKET *element; + SOCKET_MSG *sk_msg; + unsigned char *data_buf; + GLOBAL_INT_DECLARATION(); + + SK_PRT("hapd_tx:%d,buf:0x%x, len:%d\r\n", sk, buf, len); + element = sk_get_sk_element(sk); + if(0 == element) + { + goto tx_exit; + } + + sk_msg = (SOCKET_MSG *)os_malloc(sizeof(SOCKET_MSG)); + if(0 == sk_msg) + { + goto tx_exit; + } + + data_buf = (unsigned char *)os_malloc(len); + if(0 == data_buf) + { + goto malloc_buf_exit; + } + ret = len; + sk_msg->len = len; + sk_msg->msg = data_buf; + + os_memcpy(sk_msg->msg, buf, len); + + GLOBAL_INT_DISABLE(); + dl_list_add_tail(&element->sk_tx_msg, &sk_msg->data); + GLOBAL_INT_RESTORE(); + + bmsg_skt_tx_sender(type); + + return ret; + +malloc_buf_exit: + os_free(sk_msg); + +tx_exit: + return ret; +} + +int fsocket_recv(SOCKET sk, const unsigned char *buf, int len, int flag) +{ + int count; + int ret = 0; + BK_SOCKET *element; + SOCKET_MSG *sk_msg, *tmp; + GLOBAL_INT_DECLARATION(); + + SK_PRT("hapd_rx:%d,buf:0x%x, len:%d\r\n", sk, buf, len); + element = sk_get_sk_element(sk); + if(0 == element) + { + goto rx_exit; + } + + GLOBAL_INT_DISABLE(); + dl_list_for_each_safe(sk_msg, tmp, &element->sk_rx_msg, SOCKET_MSG, data) + { + if(sk_msg->len > len) + { + SK_WPRT("recv_buf_small:%d:%d\r\n", sk_msg->len, len); + } + + count = MIN(sk_msg->len, len); + + ASSERT(count); + ASSERT(sk_msg); + + os_memcpy((void *)buf, (void *)sk_msg->msg, count); + ret = count; + + os_free(sk_msg->msg); + sk_msg->msg = 0; + sk_msg->len = 0; + + dl_list_del(&sk_msg->data); + os_free(sk_msg); + sk_msg = 0; + + break; + } + GLOBAL_INT_RESTORE(); + + return ret; + +rx_exit: + return 0; +} + +void fsocket_close(SOCKET sk) +{ + BK_SOCKET *element; + SOCKET_MSG *sk_msg, *tmp; + GLOBAL_INT_DECLARATION(); + + SK_PRT("close_sk:%d\r\n", sk); + element = sk_get_sk_element(sk); + if(0 == element) + { + return; + } + + GLOBAL_INT_DISABLE(); + dl_list_for_each_safe(sk_msg, tmp, &element->sk_tx_msg, SOCKET_MSG, data) + { + dl_list_del(&sk_msg->data); + + if(sk_msg->msg) + { + os_free(sk_msg->msg); + sk_msg->msg = 0; + sk_msg->len = 0; + } + + os_free(sk_msg); + } + + dl_list_for_each_safe(sk_msg, tmp, &element->sk_rx_msg, SOCKET_MSG, data) + { + dl_list_del(&sk_msg->data); + + if(sk_msg->msg) + { + os_free(sk_msg->msg); + sk_msg->msg = 0; + sk_msg->len = 0; + } + + os_free(sk_msg); + } + + dl_list_del(&element->sk_element); + + os_free(element); + element = 0; + + GLOBAL_INT_RESTORE(); +} + +// same as ke_sk_send_peek_next_payload_size +int fsocket_peek_recv_next_payload_size(SOCKET sk) +{ + int ret = 0; + BK_SOCKET *element; + SOCKET_MSG *sk_msg, *tmp; + GLOBAL_INT_DECLARATION(); + + element = sk_get_sk_element(sk); + if(0 == element) + { + goto rx_exit; + } + + GLOBAL_INT_DISABLE(); + dl_list_for_each_safe(sk_msg, tmp, &element->sk_rx_msg, SOCKET_MSG, data) + { + ret = sk_msg->len; + break; + } + + GLOBAL_INT_RESTORE(); + return ret; + +rx_exit: + return 0; +} +// eof + diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/bk_patch/fake_socket.h b/beken_os/beken378/func/wpa_supplicant-2.9/bk_patch/fake_socket.h new file mode 100755 index 0000000..553faf7 --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/bk_patch/fake_socket.h @@ -0,0 +1,258 @@ +#ifndef _FAKE_SOCKET_H_ +#define _FAKE_SOCKET_H_ + +#include "list.h" + +//#define SK_DEBUG + +#ifdef SK_DEBUG + #define SK_PRT os_printf + #define SK_WPRT warning_prf +#else + #define SK_PRT os_null_printf + #define SK_WPRT warning_prf +#endif + +typedef int SOCKET; + +typedef struct +{ + struct dl_list data; + + unsigned char *msg; + int len; + +}SOCKET_MSG; + +typedef struct +{ + struct dl_list sk_tx_msg; // socket tx from non-rwip + struct dl_list sk_rx_msg; // socket recv from rwip + + struct dl_list sk_element; // list to global socket list + + SOCKET sk; +}BK_SOCKET; + +typedef struct +{ + struct dl_list sk_head; +}SOCKET_ENTITY; + +/** sock_type - Socket types + * + * Please notice that for binary compat reasons MIPS has to + * override the enum sock_type in include/linux/net.h, so + * we define ARCH_HAS_SOCKET_TYPES here. + * + * @SOCK_DGRAM - datagram (conn.less) socket + * @SOCK_STREAM - stream (connection) socket + * @SOCK_RAW - raw socket + * @SOCK_RDM - reliably-delivered message + * @SOCK_SEQPACKET - sequential packet socket + * @SOCK_PACKET - linux specific way of getting packets at the dev level. + * For writing rarp and other similar things on the user level. + */ +enum sock_type { + SOCK_DGRAM = 1, + SOCK_STREAM = 2, + SOCK_RAW = 3, + SOCK_RDM = 4, + SOCK_SEQPACKET = 5, + SOCK_DCCP = 6, + SOCK_PACKET = 10, +}; + +/* + * These 16 ioctls are available to devices via the do_ioctl() device + * vector. Each device should include this file and redefine these names + * as their own. Because these are device dependent it is a good idea + * _NOT_ to issue them to random objects and hope. + * + * THESE IOCTLS ARE _DEPRECATED_ AND WILL DISAPPEAR IN 2.5.X -DaveM + */ + +#define SIOCDEVPRIVATE 0x89F0 /* to 89FF */ + +/* + * These 16 ioctl calls are protocol private + */ + +#define SIOCPROTOPRIVATE 0x89E0 /* to 89EF */ + +typedef unsigned short sa_family_t; + +/* + * 1003.1g requires sa_family_t and that sa_data is char. + */ + +struct sockaddr { + sa_family_t sa_family; /* address family, AF_xxx */ + char sa_data[14]; /* 14 bytes of protocol address */ +}; + + +/* Supported address families. */ +#define AF_UNSPEC 0 +#define AF_UNIX 1 /* Unix domain sockets */ +#define AF_LOCAL 1 /* POSIX name for AF_UNIX */ +#define AF_INET 2 /* Internet IP Protocol */ +#define AF_AX25 3 /* Amateur Radio AX.25 */ +#define AF_IPX 4 /* Novell IPX */ +#define AF_APPLETALK 5 /* AppleTalk DDP */ +#define AF_NETROM 6 /* Amateur Radio NET/ROM */ +#define AF_BRIDGE 7 /* Multiprotocol bridge */ +#define AF_ATMPVC 8 /* ATM PVCs */ +#define AF_X25 9 /* Reserved for X.25 project */ +#define AF_INET6 10 /* IP version 6 */ +#define AF_ROSE 11 /* Amateur Radio X.25 PLP */ +#define AF_DECnet 12 /* Reserved for DECnet project */ +#define AF_NETBEUI 13 /* Reserved for 802.2LLC project*/ +#define AF_SECURITY 14 /* Security callback pseudo AF */ +#define AF_KEY 15 /* PF_KEY key management API */ +#define AF_NETLINK 16 +#define AF_ROUTE AF_NETLINK /* Alias to emulate 4.4BSD */ +#define AF_PACKET 17 /* Packet family */ +#define AF_ASH 18 /* Ash */ +#define AF_ECONET 19 /* Acorn Econet */ +#define AF_ATMSVC 20 /* ATM SVCs */ +#define AF_RDS 21 /* RDS sockets */ +#define AF_SNA 22 /* Linux SNA Project (nutters!) */ +#define AF_IRDA 23 /* IRDA sockets */ +#define AF_PPPOX 24 /* PPPoX sockets */ +#define AF_WANPIPE 25 /* Wanpipe API Sockets */ +#define AF_LLC 26 /* Linux LLC */ +#define AF_CAN 29 /* Controller Area Network */ +#define AF_TIPC 30 /* TIPC sockets */ +#define AF_BLUETOOTH 31 /* Bluetooth sockets */ +#define AF_IUCV 32 /* IUCV sockets */ +#define AF_RXRPC 33 /* RxRPC sockets */ +#define AF_ISDN 34 /* mISDN sockets */ +#define AF_PHONET 35 /* Phonet sockets */ +#define AF_IEEE802154 36 /* IEEE802154 sockets */ +#define AF_CAIF 37 /* CAIF sockets */ +#define AF_ALG 38 /* Algorithm sockets */ +#define AF_MAX 39 /* For now.. */ + +/* Protocol families, same as address families. */ +#define PF_UNSPEC AF_UNSPEC +#define PF_UNIX AF_UNIX +#define PF_LOCAL AF_LOCAL +#define PF_INET AF_INET +#define PF_AX25 AF_AX25 +#define PF_IPX AF_IPX +#define PF_APPLETALK AF_APPLETALK +#define PF_NETROM AF_NETROM +#define PF_BRIDGE AF_BRIDGE +#define PF_ATMPVC AF_ATMPVC +#define PF_X25 AF_X25 +#define PF_INET6 AF_INET6 +#define PF_ROSE AF_ROSE +#define PF_DECnet AF_DECnet +#define PF_NETBEUI AF_NETBEUI +#define PF_SECURITY AF_SECURITY +#define PF_KEY AF_KEY +#define PF_NETLINK AF_NETLINK +#define PF_ROUTE AF_ROUTE +#define PF_PACKET AF_PACKET +#define PF_ASH AF_ASH +#define PF_ECONET AF_ECONET +#define PF_ATMSVC AF_ATMSVC +#define PF_RDS AF_RDS +#define PF_SNA AF_SNA +#define PF_IRDA AF_IRDA +#define PF_PPPOX AF_PPPOX +#define PF_WANPIPE AF_WANPIPE +#define PF_LLC AF_LLC +#define PF_CAN AF_CAN +#define PF_TIPC AF_TIPC +#define PF_BLUETOOTH AF_BLUETOOTH +#define PF_IUCV AF_IUCV +#define PF_RXRPC AF_RXRPC +#define PF_ISDN AF_ISDN +#define PF_PHONET AF_PHONET +#define PF_IEEE802154 AF_IEEE802154 +#define PF_CAIF AF_CAIF +#define PF_ALG AF_ALG +#define PF_MAX AF_MAX + +#define SOL_SOCKET 1 + +#define SO_DEBUG 1 +#define SO_REUSEADDR 2 +#define SO_TYPE 3 +#define SO_ERROR 4 +#define SO_DONTROUTE 5 +#define SO_BROADCAST 6 +#define SO_SNDBUF 7 +#define SO_RCVBUF 8 +#define SO_SNDBUFFORCE 32 +#define SO_RCVBUFFORCE 33 +#define SO_KEEPALIVE 9 +#define SO_OOBINLINE 10 +#define SO_NO_CHECK 11 +#define SO_PRIORITY 12 +#define SO_LINGER 13 +#define SO_BSDCOMPAT 14 +/* To add :#define SO_REUSEPORT 15 */ +#define SO_PASSCRED 16 +#define SO_PEERCRED 17 +#define SO_RCVLOWAT 18 +#define SO_SNDLOWAT 19 +#define SO_RCVTIMEO 20 +#define SO_SNDTIMEO 21 + +/* Security levels - as per NRL IPv6 - don't actually do anything */ +#define SO_SECURITY_AUTHENTICATION 22 +#define SO_SECURITY_ENCRYPTION_TRANSPORT 23 +#define SO_SECURITY_ENCRYPTION_NETWORK 24 + +#define SO_BINDTODEVICE 25 + +/* Socket filtering */ +#define SO_ATTACH_FILTER 26 +#define SO_DETACH_FILTER 27 + +#define SO_PEERNAME 28 +#define SO_TIMESTAMP 29 +#define SCM_TIMESTAMP SO_TIMESTAMP + +#define SO_ACCEPTCONN 30 + +#define SO_PEERSEC 31 +#define SO_PASSSEC 34 +#define SO_TIMESTAMPNS 35 +#define SCM_TIMESTAMPNS SO_TIMESTAMPNS + +#define SO_MARK 36 + +#define SO_TIMESTAMPING 37 +#define SCM_TIMESTAMPING SO_TIMESTAMPING + +#define SO_PROTOCOL 38 +#define SO_DOMAIN 39 + +#define SO_RXQ_OVFL 40 + +typedef struct socket_type_st { + unsigned char type; + unsigned char vif_index; + uint16_t freq; + void *args; + int sync; +}S_TYPE_ST,*S_TYPE_PTR; + +extern SOCKET fsocket_init(int af, int type, int protocol); +extern int fsocket_send(SOCKET sk, const unsigned char *buf, int len, S_TYPE_PTR type); +extern int fsocket_recv(SOCKET sk, const unsigned char *buf, int len, int flag); +extern void fsocket_close(SOCKET sk); +extern int ke_sk_send(SOCKET sk, const unsigned char *buf, int len, int flag); +extern int ke_sk_recv(SOCKET sk, const unsigned char *buf, int len, int flag); +extern BK_SOCKET *sk_get_sk_element(SOCKET sk); +extern int ke_sk_recv_peek_next_payload_size(SOCKET sk); +extern int fsocket_peek_recv_next_payload_size(SOCKET sk); +extern int ke_sk_send_peek_next_payload_size(SOCKET sk); + +#endif // _FAKE_SOCKET_H_ +// eof + diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/bk_patch/signal.c b/beken_os/beken378/func/wpa_supplicant-2.9/bk_patch/signal.c new file mode 100755 index 0000000..4ba81ca --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/bk_patch/signal.c @@ -0,0 +1,14 @@ +#include "include.h" +#include "signal.h" + +void bk_signal(int sig_num, SIG_FUNC func) +{ +} + +extern unsigned int bk_alarm(unsigned int seconds) +{ + return 0; +} + +// eof + diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/bk_patch/signal.h b/beken_os/beken378/func/wpa_supplicant-2.9/bk_patch/signal.h new file mode 100755 index 0000000..04ca570 --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/bk_patch/signal.h @@ -0,0 +1,57 @@ +#ifndef _SIGNAL_H_ +#define _SIGNAL_H_ + +typedef void (*SIG_FUNC)(int); + +#define SIGHUP 1 +#define SIGINT 2 +#define SIGQUIT 3 +#define SIGILL 4 +#define SIGTRAP 5 +#define SIGABRT 6 +#define SIGEMT 7 +#define SIGFPE 8 +#define SIGKILL 9 +#define SIGBUS 10 +#define SIGSEGV 11 +#define SIGSYS 12 +#define SIGPIPE 13 +#define SIGALRM 14 +#define SIGTERM 15 +#define SIGURG 16 +#define SIGSTOP 17 +#define SIGTSTP 18 +#define SIGCONT 19 +#define SIGCHLD 20 +#define SIGTTIN 21 +#define SIGTTOU 22 +#define SIGIO 23 +#define SIGXCPU 24 +#define SIGXFSZ 25 +#define SIGVTALRM 26 +#define SIGPROF 27 +#define SIGWINCH 28 +#define SIGINFO 29 +#define SIGUSR1 30 +#define SIGUSR2 31 + +#define SIGSCAN 32 +#define SIGSCAN_START 33 +#define SIGASSOC 34 +#define SIGDISASSOC 35 +#define SIGDEAUTH 36 +#define SIGCSA 37 +#define SIGAUTH 38 + +#define SIGPOLL SIGIO +#define SIGPWR SIGINFO +#define SIGIOT SIGABRT + +#define SIGABOART 39 + +extern void bk_signal(int sig_num, SIG_FUNC func); +unsigned int bk_alarm(unsigned int seconds); + +#endif +// eof + diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/bk_patch/sk_intf.c b/beken_os/beken378/func/wpa_supplicant-2.9/bk_patch/sk_intf.c new file mode 100755 index 0000000..eaa7b02 --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/bk_patch/sk_intf.c @@ -0,0 +1,175 @@ +#include "include.h" +#include "sk_intf.h" +#include "main_none.h" +#include "eloop.h" + +#include "param_config.h" +#include "uart_pub.h" +#include "rw_pub.h" + +extern uint32_t wpa_hostapd_queue_poll(uint32_t param); + +SOCKET mgmt_get_socket_num(u8 vif_idx) +{ + return (SK_INTF_MGMT_SOCKET_NUM + vif_idx); +} + +SOCKET ioctl_get_socket_num(u8 vif_idx) +{ + return (SK_INTF_IOCTL_SOCKET_NUM + vif_idx); +} + +SOCKET data_get_socket_num(u8 vif_idx) +{ + return (SK_INTF_DATA_SOCKET_NUM + vif_idx); +} + +void handle_dummy_read(int sock, void *eloop_ctx, void *sock_ctx) +{ + int len; + unsigned char *buf; + +#ifndef TMP_BUF_LEN +#define TMP_BUF_LEN (512) +#endif + + buf = os_malloc(TMP_BUF_LEN); + if(!buf) + { + os_printf("dummy_read no mem\r\n"); + goto dummy_exit; + } + + len = fsocket_recv(sock, buf, TMP_BUF_LEN, 0); + if (len < 0) + { + wpa_printf(MSG_ERROR, "recv error"); + goto dummy_exit; + } + +dummy_exit: + if(buf) + { + os_free(buf); + } + + return; +} + +/* + * send to wpad or hapd. + */ +int ke_mgmt_packet_tx(unsigned char *buf, int len, int flag) +{ + int ret, poll_flag = 0; + SOCKET sk = mgmt_get_socket_num(flag); + + ret = ke_sk_send(sk, buf, len, flag); + if(ret) + { + poll_flag = wpa_hostapd_queue_poll((uint32_t)flag); + } + + if(poll_flag) + { + handle_dummy_read(sk, NULL, NULL); + } + + return ret; +} + +int ke_mgmt_packet_rx(unsigned char *buf, int len, int flag) +{ + SOCKET sk = mgmt_get_socket_num(flag); + + return ke_sk_recv(sk, buf, len, flag); +} + +int ke_mgmt_peek_txed_next_payload_size(int flag) +{ + SOCKET sk = mgmt_get_socket_num(flag); + + return ke_sk_send_peek_next_payload_size(sk); +} + +int ke_mgmt_peek_rxed_next_payload_size(int flag) +{ + SOCKET sk = mgmt_get_socket_num(flag); + + return ke_sk_recv_peek_next_payload_size(sk); +} + +int ke_l2_packet_tx(unsigned char *buf, int len, int flag) +{ + int ret, poll_flag = 0; + SOCKET sk = data_get_socket_num(flag); + + ret = ke_sk_send(sk, buf, len, flag); + if(0 != ret) + { + poll_flag = wpa_hostapd_queue_poll((uint32_t)flag); + } + + if(poll_flag) + { + handle_dummy_read(sk, NULL, NULL); + } + + return ret; +} + +int ke_l2_packet_rx(unsigned char *buf, int len, int flag) +{ + SOCKET sk = data_get_socket_num(flag); + + return ke_sk_recv(sk, buf, len, flag); +} + +int ke_data_peek_txed_next_payload_size(int flag) +{ + SOCKET sk = data_get_socket_num(flag); + + return ke_sk_send_peek_next_payload_size(sk); +} + +int ke_data_peek_rxed_next_payload_size(int flag) +{ + SOCKET sk = data_get_socket_num(flag); + + return ke_sk_recv_peek_next_payload_size(sk); +} + +int ws_mgmt_peek_rxed_next_payload_size(int flag) +{ + SOCKET sk = mgmt_get_socket_num(flag); + + return fsocket_peek_recv_next_payload_size(sk); +} + +int ws_get_mgmt_packet(unsigned char *buf, int len, int flag) +{ + SOCKET sk; + + sk = mgmt_get_socket_num(flag); + + return fsocket_recv(sk, buf, len, flag); +} + +int ws_data_peek_rxed_next_payload_size(int flag) +{ + SOCKET sk = data_get_socket_num(flag); + + return fsocket_peek_recv_next_payload_size(sk); +} + +int ws_get_data_packet(unsigned char *buf, int len, int flag) +{ + SOCKET sk; + + sk = data_get_socket_num(flag); + + return fsocket_recv(sk, buf, len, flag); +} + +// eof + diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/bk_patch/sk_intf.h b/beken_os/beken378/func/wpa_supplicant-2.9/bk_patch/sk_intf.h new file mode 100755 index 0000000..9c6687a --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/bk_patch/sk_intf.h @@ -0,0 +1,27 @@ +#ifndef _SK_INTF_H_ +#define _SK_INTF_H_ + +#include "common.h" +#include "fake_socket.h" + +#define SK_INTF_MGMT_SOCKET_NUM (PF_PACKET + SOCK_RAW + ETH_P_ALL) +#define SK_INTF_IOCTL_SOCKET_NUM (PF_INET + SOCK_DGRAM + 0) +#define SK_INTF_DATA_SOCKET_NUM (PF_PACKET + SOCK_RAW + ETH_P_PAE) + +extern int ke_mgmt_peek_rxed_next_payload_size(int flag); +extern int ke_mgmt_packet_rx(unsigned char *buf, int len, int flag); +extern int ke_mgmt_packet_tx(unsigned char *buf, int len, int flag); +extern int ke_l2_packet_tx(unsigned char *buf, int len, int flag); +extern int ke_l2_packet_rx(unsigned char *buf, int len, int flag); +extern int ke_data_peek_txed_next_payload_size(int flag); +extern int ke_data_peek_rxed_next_payload_size(int flag); +extern int ws_mgmt_peek_rxed_next_payload_size(int flag); +extern int ws_get_mgmt_packet(unsigned char *buf, int len, int flag); +extern int ws_data_peek_rxed_next_payload_size(int flag); +extern int ws_get_data_packet(unsigned char *buf, int len, int flag); +extern SOCKET mgmt_get_socket_num(u8 vif_idx); +extern SOCKET data_get_socket_num(u8 vif_idx); +extern SOCKET ioctl_get_socket_num(u8 vif_idx); +#endif +// eof + diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/hostapd/hostapd_cfg.h b/beken_os/beken378/func/wpa_supplicant-2.9/hostapd/hostapd_cfg.h new file mode 100755 index 0000000..21f03cc --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/hostapd/hostapd_cfg.h @@ -0,0 +1,15 @@ +#ifndef _HOSTAPD_CONFIG_H_ +#define _HOSTAPD_CONFIG_H_ + +#include "include.h" +#include "defs.h" +#include "rwnx_config.h" + +#define CFG_AUTH_ALG WPA_AUTH_ALG_OPEN + +#define CFG_SUPPORTED_MAX_STA_NUM CFG_STA_MAX// 2 +#define CFG_SUPPORT_80211G 1 + +#endif // _HOSTAPD_CONFIG_H_ + + diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/hostapd/main_none.c b/beken_os/beken378/func/wpa_supplicant-2.9/hostapd/main_none.c new file mode 100755 index 0000000..f3a517e --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/hostapd/main_none.c @@ -0,0 +1,1120 @@ +/* + * WPA Supplicant / Example program entrypoint + * Copyright (c) 2003-2005, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ +#include "include.h" +#include "uart_pub.h" +#include "includes.h" +#include "hostapd_cfg.h" +#include "common.h" +#include "ap/hostapd.h" +#include "eloop.h" +#include "main_none.h" +#include "ap/sta_info.h" +#include "ps.h" +#include "param_config.h" +#include "wlan_ui_pub.h" +#include "rtos_pub.h" +#include "rtos_error.h" +#include "wlan_ui_pub.h" +#include "ap/ap_drv_ops.h" +#include "common/eapol_common.h" +#include "signal.h" +#if CFG_WPA_CTRL_IFACE +#include "wpa_ctrl.h" +#endif + +beken_thread_t hostapd_thread_handle = NULL; +extern beken_thread_t wpas_thread_handle; +uint32_t hostapd_stack_size = 4000; +beken_semaphore_t hostapd_sema = NULL; +beken_semaphore_t wpa_hostapd_sema = NULL; +void *wpa_hostapd_param = NULL; +beken_queue_t wpah_queue = NULL; +static struct hapd_global s_hapd_global; +struct hapd_interfaces g_hapd_interfaces; + +char *bss_iface = "wlan0"; + +extern int ap_channel_switch(struct hostapd_iface *ap_iface, int new_freq); + +#if CFG_WPA_CTRL_IFACE +struct hapd_interfaces *hostapd_ctrl_get_interfaces() +{ + return &g_hapd_interfaces; +} +#endif + +struct hostapd_config *hostapd_config_read(const char *fname) +{ + struct hostapd_config *conf = 0; + int i; + int errors = 0; + struct hostapd_bss_config *bss; + + conf = hostapd_config_defaults(); + if (NULL == conf) + return NULL; + + conf->last_bss = conf->bss[0]; + bss = conf->last_bss; + + os_strcpy(bss->iface, bss_iface); + wifi_get_mac_address((char *)&bss->bssid, CONFIG_ROLE_AP); + /* set default driver based on configuration */ + conf->driver = wpa_drivers[0]; + conf->last_bss = conf->bss[0]; + + #if CFG_AP_SUPPORT_HT_IE + conf->ieee80211n = 1; + conf->ht_capab = HT_CAP_INFO_SMPS_DISABLED | HT_CAP_INFO_SHORT_GI20MHZ + | HT_CAP_INFO_TX_STBC + | HT_CAP_INFO_RX_STBC_1 + | HT_CAP_INFO_MAX_AMSDU_SIZE; + #endif + + bss->ssid.ssid_len = g_ap_param_ptr->ssid.length; + os_memcpy(bss->ssid.ssid, g_ap_param_ptr->ssid.array, bss->ssid.ssid_len); + bss->max_listen_interval = 65535; + bss->ieee802_1x = 0; + bss->ssid.ssid_set = 1; + + if(g_ap_param_ptr->cipher_suite == SECURITY_TYPE_WEP){ + bss->default_wep_key_len = 0; + bss->ssid.wep.keys_set = 1; + bss->ssid.wep.default_len = 10; + bss->ssid.wep.idx = 0; + bss->ssid.wep.len[0] = 5; + bss->ssid.wep.key[0] = (u8 *)os_malloc(bss->ssid.wep.len[0]); + if (bss->ssid.wep.key[0]) { + int wkey; + const char *wep_key = (char *)g_ap_param_ptr->key; + if (g_ap_param_ptr->key_len == 5) { + os_memcpy(bss->ssid.wep.key[0], wep_key, g_ap_param_ptr->key_len); + } else if (g_ap_param_ptr->key_len == 10) { + for (i = 0; i < bss->ssid.wep.len[0]; i ++) { + wkey = hex2byte(&wep_key[2 * i]); + ASSERT(-1 != wkey); + + bss->ssid.wep.key[0][i] = wkey; + } + } else { + os_printf("WEP_KEY_len_exception\r\n"); + } + } + }else if(g_ap_param_ptr->cipher_suite == SECURITY_TYPE_WPA_TKIP){ + bss->wpa = 1; + bss->wpa_pairwise = WPA_CIPHER_TKIP; + }else if(g_ap_param_ptr->cipher_suite == SECURITY_TYPE_WPA2_AES){ + bss->wpa = 2; + bss->wpa_pairwise = WPA_CIPHER_CCMP; + }else if(g_ap_param_ptr->cipher_suite == SECURITY_TYPE_WPA2_MIXED){ + bss->wpa = 2; + bss->wpa_pairwise = WPA_CIPHER_TKIP | WPA_CIPHER_CCMP; + } else if (g_ap_param_ptr->cipher_suite == SECURITY_TYPE_WPA3_SAE || + g_ap_param_ptr->cipher_suite == SECURITY_TYPE_WPA3_WPA2_MIXED) { + bss->wpa = 2; + bss->wpa_pairwise = WPA_CIPHER_CCMP; + } + + bss->wpa_key_mgmt = 0; + if (g_ap_param_ptr->cipher_suite > SECURITY_TYPE_WEP) { + const char *wpa_key = (char *)g_ap_param_ptr->key; + os_free(bss->ssid.wpa_passphrase); + bss->ssid.wpa_passphrase = os_strdup(wpa_key); + if (bss->ssid.wpa_passphrase) { + hostapd_config_clear_wpa_psk(&bss->ssid.wpa_psk); + bss->ssid.wpa_passphrase_set = 1; + } + bss->wpa_key_mgmt |= WPA_KEY_MGMT_PSK; + } + + //if (g_ap_param_ptr->cipher_suite >= BK_SECURITY_TYPE_WPA3_SAE) { + // bss->wpa_key_mgmt = WPA_KEY_MGMT_SAE;; + // bss->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL; + //} + if (g_ap_param_ptr->cipher_suite == SECURITY_TYPE_WPA3_SAE) { + bss->wpa_key_mgmt = WPA_KEY_MGMT_SAE; + } else if (g_ap_param_ptr->cipher_suite == SECURITY_TYPE_WPA3_WPA2_MIXED) { + bss->wpa_key_mgmt |= WPA_KEY_MGMT_SAE; + } + //os_printf("%s: wpa_key_mgmt 0x%x, cipher_suite %d\n", __func__, bss->wpa_key_mgmt, g_ap_param_ptr->cipher_suite); + + for (i = 0; i < conf->num_bss; i++) + hostapd_set_security_params(conf->bss[i], 1); + + if (hostapd_config_check(conf, 1)) + errors++; + + return conf; +} + +#if CFG_WPA_CTRL_IFACE +static int hostapd_config_parse_key_mgmt(int line, const char *value) +{ + int val = 0, last; + char *start, *end, *buf; + + buf = os_strdup(value); + if (buf == NULL) + return -1; + start = buf; + + while (*start != '\0') { + while (*start == ' ' || *start == '\t') + start++; + if (*start == '\0') + break; + end = start; + while (*end != ' ' && *end != '\t' && *end != '\0') + end++; + last = *end == '\0'; + *end = '\0'; + if (os_strcmp(start, "WPA-PSK") == 0) + val |= WPA_KEY_MGMT_PSK; + else if (os_strcmp(start, "WPA-EAP") == 0) + val |= WPA_KEY_MGMT_IEEE8021X; +#ifdef CONFIG_SAE_AP + else if (os_strcmp(start, "SAE") == 0) + val |= WPA_KEY_MGMT_SAE; + else if (os_strcmp(start, "FT-SAE") == 0) + val |= WPA_KEY_MGMT_FT_SAE; +#endif /* CONFIG_SAE_AP */ + else { + wpa_printf(MSG_ERROR, "Line %d: invalid key_mgmt '%s'", + line, start); + os_free(buf); + return -1; + } + + if (last) + break; + start = end + 1; + } + + os_free(buf); + if (val == 0) { + wpa_printf(MSG_ERROR, "Line %d: no key_mgmt values " + "configured.", line); + return -1; + } + + return val; +} + +static int hostapd_config_parse_cipher(int line, const char *value) +{ + int val = wpa_parse_cipher(value); + if (val < 0) { + wpa_printf(MSG_ERROR, "Line %d: invalid cipher '%s'.", + line, value); + return -1; + } + if (val == 0) { + wpa_printf(MSG_ERROR, "Line %d: no cipher values configured.", + line); + return -1; + } + return val; +} + +static int hostapd_config_read_wep(struct hostapd_wep_keys *wep, int keyidx, char *val) +{ + size_t len = os_strlen(val); + + if (keyidx < 0 || keyidx > 3 || wep->key[keyidx] != NULL) + return -1; + + if (val[0] == '"') { + if (len < 2 || val[len - 1] != '"') + return -1; + len -= 2; + wep->key[keyidx] = os_malloc(len); + if (wep->key[keyidx] == NULL) + return -1; + os_memcpy(wep->key[keyidx], val + 1, len); + wep->len[keyidx] = len; + } else { + if (len & 1) + return -1; + len /= 2; + wep->key[keyidx] = os_malloc(len); + if (wep->key[keyidx] == NULL) + return -1; + wep->len[keyidx] = len; + if (hexstr2bin(val, wep->key[keyidx], len) < 0) + return -1; + } + + wep->keys_set++; + + return 0; +} + +static int hostapd_parse_chanlist(struct hostapd_config *conf, char *val) +{ + char *pos; + + /* for backwards compatibility, translate ' ' in conf str to ',' */ + pos = val; + while (pos) { + pos = os_strchr(pos, ' '); + if (pos) + *pos++ = ','; + } + if (freq_range_list_parse(&conf->acs_ch_list, val)) + return -1; + + return 0; +} + +static int hostapd_parse_intlist(int **int_list, char *val) +{ + int *list; + int count; + char *pos, *end; + + os_free(*int_list); + *int_list = NULL; + + pos = val; + count = 0; + while (*pos != '\0') { + if (*pos == ' ') + count++; + pos++; + } + + list = os_malloc(sizeof(int) * (count + 2)); + if (list == NULL) + return -1; + pos = val; + count = 0; + while (*pos != '\0') { + end = os_strchr(pos, ' '); + if (end) + *end = '\0'; + + list[count++] = atoi(pos); + if (!end) + break; + pos = end + 1; + } + list[count] = -1; + + *int_list = list; + return 0; +} + +static int hostapd_config_fill(struct hostapd_config *conf, + struct hostapd_bss_config *bss, + const char *buf, char *pos, int line) +{ + if (os_strcmp(buf, "ssid") == 0) { + bss->ssid.ssid_len = os_strlen(pos); + if (bss->ssid.ssid_len > SSID_MAX_LEN || + bss->ssid.ssid_len < 1) { + wpa_printf(MSG_ERROR, "Line %d: invalid SSID '%s'", + line, pos); + return 1; + } + os_memcpy(bss->ssid.ssid, pos, bss->ssid.ssid_len); + bss->ssid.ssid_set = 1; + } else if (os_strcmp(buf, "utf8_ssid") == 0) { + bss->ssid.utf8_ssid = atoi(pos) > 0; + } else if (os_strcmp(buf, "ap_isolate") == 0) { + bss->isolate = atoi(pos); + } else if (os_strcmp(buf, "ap_max_inactivity") == 0) { + bss->ap_max_inactivity = atoi(pos); + } else if (os_strcmp(buf, "skip_inactivity_poll") == 0) { + bss->skip_inactivity_poll = atoi(pos); + } else if (os_strcmp(buf, "country_code") == 0) { + os_memcpy(conf->country, pos, 2); + /* FIX: make this configurable */ + conf->country[2] = ' '; + } else if (os_strcmp(buf, "ieee80211d") == 0) { + conf->ieee80211d = atoi(pos); + } else if (os_strcmp(buf, "ieee80211h") == 0) { + conf->ieee80211h = atoi(pos); + } else if (os_strcmp(buf, "eapol_version") == 0) { + bss->eapol_version = atoi(pos); + if (bss->eapol_version < 1 || bss->eapol_version > 2) { + wpa_printf(MSG_ERROR, + "Line %d: invalid EAPOL version (%d): '%s'.", + line, bss->eapol_version, pos); + return 1; + } + wpa_printf(MSG_DEBUG, "eapol_version=%d", bss->eapol_version); + } else if (os_strcmp(buf, "wep_rekey_period") == 0) { + bss->wep_rekeying_period = atoi(pos); + if (bss->wep_rekeying_period < 0) { + wpa_printf(MSG_ERROR, "Line %d: invalid period %d", + line, bss->wep_rekeying_period); + return 1; + } + } else if (os_strcmp(buf, "eap_reauth_period") == 0) { + bss->eap_reauth_period = atoi(pos); + if (bss->eap_reauth_period < 0) { + wpa_printf(MSG_ERROR, "Line %d: invalid period %d", + line, bss->eap_reauth_period); + return 1; + } + } else if (os_strcmp(buf, "eapol_key_index_workaround") == 0) { + bss->eapol_key_index_workaround = atoi(pos); + } else if (os_strcmp(buf, "auth_algs") == 0) { + bss->auth_algs = atoi(pos); + if (bss->auth_algs == 0) { + wpa_printf(MSG_ERROR, "Line %d: no authentication algorithms allowed", + line); + return 1; + } + } else if (os_strcmp(buf, "max_num_sta") == 0) { + bss->max_num_sta = atoi(pos); + if (bss->max_num_sta < 0 || + bss->max_num_sta > MAX_STA_COUNT) { + wpa_printf(MSG_ERROR, "Line %d: Invalid max_num_sta=%d; allowed range 0..%d", + line, bss->max_num_sta, MAX_STA_COUNT); + return 1; + } + } else if (os_strcmp(buf, "wpa") == 0) { + bss->wpa = atoi(pos); + } else if (os_strcmp(buf, "wpa_group_rekey") == 0) { + bss->wpa_group_rekey = atoi(pos); + } else if (os_strcmp(buf, "wpa_strict_rekey") == 0) { + bss->wpa_strict_rekey = atoi(pos); + } else if (os_strcmp(buf, "wpa_gmk_rekey") == 0) { + bss->wpa_gmk_rekey = atoi(pos); + } else if (os_strcmp(buf, "wpa_ptk_rekey") == 0) { + bss->wpa_ptk_rekey = atoi(pos); + } else if (os_strcmp(buf, "wpa_passphrase") == 0) { + int len = os_strlen(pos); + if (len < 8 || len > 63) { + wpa_printf(MSG_ERROR, "Line %d: invalid WPA passphrase length %d (expected 8..63)", + line, len); + return 1; + } + os_free(bss->ssid.wpa_passphrase); + bss->ssid.wpa_passphrase = os_strdup(pos); + if (bss->ssid.wpa_passphrase) { + hostapd_config_clear_wpa_psk(&bss->ssid.wpa_psk); + bss->ssid.wpa_passphrase_set = 1; + } + } else if (os_strcmp(buf, "wpa_psk") == 0) { + hostapd_config_clear_wpa_psk(&bss->ssid.wpa_psk); + bss->ssid.wpa_psk = os_zalloc(sizeof(struct hostapd_wpa_psk)); + if (bss->ssid.wpa_psk == NULL) + return 1; + if (hexstr2bin(pos, bss->ssid.wpa_psk->psk, PMK_LEN) || + pos[PMK_LEN * 2] != '\0') { + wpa_printf(MSG_ERROR, "Line %d: Invalid PSK '%s'.", + line, pos); + hostapd_config_clear_wpa_psk(&bss->ssid.wpa_psk); + return 1; + } + bss->ssid.wpa_psk->group = 1; + os_free(bss->ssid.wpa_passphrase); + bss->ssid.wpa_passphrase = NULL; + bss->ssid.wpa_psk_set = 1; + } else if (os_strcmp(buf, "wpa_key_mgmt") == 0) { + bss->wpa_key_mgmt = hostapd_config_parse_key_mgmt(line, pos); + if (bss->wpa_key_mgmt == -1) + return 1; + } else if (os_strcmp(buf, "wpa_pairwise") == 0) { + bss->wpa_pairwise = hostapd_config_parse_cipher(line, pos); + if (bss->wpa_pairwise == -1 || bss->wpa_pairwise == 0) + return 1; + if (bss->wpa_pairwise & + (WPA_CIPHER_NONE | WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104)) { + wpa_printf(MSG_ERROR, "Line %d: unsupported pairwise cipher suite '%s'", + bss->wpa_pairwise, pos); + return 1; + } + } else if (os_strcmp(buf, "rsn_pairwise") == 0) { + bss->rsn_pairwise = hostapd_config_parse_cipher(line, pos); + if (bss->rsn_pairwise == -1 || bss->rsn_pairwise == 0) + return 1; + if (bss->rsn_pairwise & + (WPA_CIPHER_NONE | WPA_CIPHER_WEP40 | WPA_CIPHER_WEP104)) { + wpa_printf(MSG_ERROR, "Line %d: unsupported pairwise cipher suite '%s'", + bss->rsn_pairwise, pos); + return 1; + } +#ifdef CONFIG_PEERKEY + } else if (os_strcmp(buf, "peerkey") == 0) { + bss->peerkey = atoi(pos); +#endif /* CONFIG_PEERKEY */ + } else if (os_strcmp(buf, "use_pae_group_addr") == 0) { + bss->use_pae_group_addr = atoi(pos); + } else if (os_strcmp(buf, "hw_mode") == 0) { + if (0) {} +#ifdef CONFIG_FULL_HOSTAPD + else if (os_strcmp(pos, "a") == 0) + conf->hw_mode = HOSTAPD_MODE_IEEE80211A; +#endif + else if (os_strcmp(pos, "b") == 0) + conf->hw_mode = HOSTAPD_MODE_IEEE80211B; + else if (os_strcmp(pos, "g") == 0) + conf->hw_mode = HOSTAPD_MODE_IEEE80211G; +#ifdef CONFIG_FULL_HOSTAPD + else if (os_strcmp(pos, "ad") == 0) + conf->hw_mode = HOSTAPD_MODE_IEEE80211AD; +#endif + else if (os_strcmp(pos, "any") == 0) + conf->hw_mode = HOSTAPD_MODE_IEEE80211ANY; + else { + wpa_printf(MSG_ERROR, "Line %d: unknown hw_mode '%s'", + line, pos); + return 1; + } +#ifdef CONFIG_WPS + } else if (os_strcmp(buf, "wps_rf_bands") == 0) { + if (os_strcmp(pos, "ad") == 0) + bss->wps_rf_bands = WPS_RF_60GHZ; + else if (os_strcmp(pos, "a") == 0) + bss->wps_rf_bands = WPS_RF_50GHZ; + else if (os_strcmp(pos, "g") == 0 || + os_strcmp(pos, "b") == 0) + bss->wps_rf_bands = WPS_RF_24GHZ; + else if (os_strcmp(pos, "ag") == 0 || + os_strcmp(pos, "ga") == 0) + bss->wps_rf_bands = WPS_RF_24GHZ | WPS_RF_50GHZ; + else { + wpa_printf(MSG_ERROR, + "Line %d: unknown wps_rf_band '%s'", + line, pos); + return 1; + } +#endif + } else if (os_strcmp(buf, "channel") == 0) { + conf->channel = atoi(pos); + conf->acs = conf->channel == 0; + } else if (os_strcmp(buf, "beacon_int") == 0) { + int val = atoi(pos); + /* MIB defines range as 1..65535, but very small values + * cause problems with the current implementation. + * Since it is unlikely that this small numbers are + * useful in real life scenarios, do not allow beacon + * period to be set below 15 TU. */ + if (val < 15 || val > 65535) { + wpa_printf(MSG_ERROR, "Line %d: invalid beacon_int %d (expected 15..65535)", + line, val); + return 1; + } + conf->beacon_int = val; + } else if (os_strcmp(buf, "dtim_period") == 0) { + bss->dtim_period = atoi(pos); + if (bss->dtim_period < 1 || bss->dtim_period > 255) { + wpa_printf(MSG_ERROR, "Line %d: invalid dtim_period %d", + line, bss->dtim_period); + return 1; + } + } else if (os_strcmp(buf, "supported_rates") == 0) { + if (hostapd_parse_intlist(&conf->supported_rates, pos)) { + wpa_printf(MSG_ERROR, "Line %d: invalid rate list", + line); + return 1; + } + } else if (os_strcmp(buf, "basic_rates") == 0) { + if (hostapd_parse_intlist(&conf->basic_rates, pos)) { + wpa_printf(MSG_ERROR, "Line %d: invalid rate list", + line); + return 1; + } + } else if (os_strcmp(buf, "ignore_broadcast_ssid") == 0) { + bss->ignore_broadcast_ssid = atoi(pos); + } else if (os_strcmp(buf, "wep_default_key") == 0) { + bss->ssid.wep.idx = atoi(pos); + if (bss->ssid.wep.idx > 3) { + wpa_printf(MSG_ERROR, + "Invalid wep_default_key index %d", + bss->ssid.wep.idx); + return 1; + } + } else if (os_strcmp(buf, "wep_key0") == 0 || + os_strcmp(buf, "wep_key1") == 0 || + os_strcmp(buf, "wep_key2") == 0 || + os_strcmp(buf, "wep_key3") == 0) { + if (hostapd_config_read_wep(&bss->ssid.wep, + buf[7] - '0', pos)) { + wpa_printf(MSG_ERROR, "Line %d: invalid WEP key '%s'", + line, buf); + return 1; + } + } else if (os_strcmp(buf, "ap_table_max_size") == 0) { + conf->ap_table_max_size = atoi(pos); + } else if (os_strcmp(buf, "ap_table_expiration_time") == 0) { + conf->ap_table_expiration_time = atoi(pos); + } else if (os_strcmp(buf, "max_listen_interval") == 0) { + bss->max_listen_interval = atoi(pos); + } else if (os_strcmp(buf, "disable_pmksa_caching") == 0) { + bss->disable_pmksa_caching = atoi(pos); + } else if (os_strcmp(buf, "okc") == 0) { + bss->okc = atoi(pos); + } else if (os_strcmp(buf, "disassoc_low_ack") == 0) { + bss->disassoc_low_ack = atoi(pos); +#ifdef CONFIG_SAE_AP + } else if (os_strcmp(buf, "sae_anti_clogging_threshold") == 0) { + bss->sae_anti_clogging_threshold = atoi(pos); + } else if (os_strcmp(buf, "sae_groups") == 0) { + if (hostapd_parse_intlist(&bss->sae_groups, pos)) { + wpa_printf(MSG_ERROR, + "Line %d: Invalid sae_groups value '%s'", + line, pos); + return 1; + } +#endif + } else { + wpa_printf(MSG_ERROR, + "Line %d: unknown configuration item '%s'", + line, buf); + return 1; + } + + return 0; +} + + +int hostapd_set_iface(struct hostapd_config *conf, + struct hostapd_bss_config *bss, const char *field, + char *value) +{ + int errors; + size_t i; + + errors = hostapd_config_fill(conf, bss, field, value, 0); + if (errors) { + wpa_printf(MSG_INFO, "Failed to set configuration field '%s' " + "to value '%s'", field, value); + return -1; + } + + for (i = 0; i < conf->num_bss; i++) + hostapd_set_security_params(conf->bss[i], 0); + + if (hostapd_config_check(conf, 0)) { + wpa_printf(MSG_ERROR, "Configuration check failed"); + return -1; + } + + return 0; +} +#endif /* CFG_WPA_CTRL_IFACE */ + +/** + * hostapd_driver_init - Preparate driver interface + */ +static int hostapd_driver_init(struct hostapd_iface *iface) +{ + struct wpa_init_params params; + size_t i; + struct hostapd_data *hapd = iface->bss[0]; + struct hostapd_bss_config *conf = hapd->conf; + u8 *b = conf->bssid; + struct wpa_driver_capa capa; + + if (hapd->driver == NULL || hapd->driver->hapd_init == NULL) { + wpa_printf(MSG_ERROR, "No hostapd driver wrapper available"); + return -1; + } + + /* Initialize the driver interface */ + if (is_zero_ether_addr(b)) { + b = NULL; + os_printf("hostapd_driver_init conf->bssid is null\r\n"); + return -1; + } + + os_memset(¶ms, 0, sizeof(params)); + for (i = 0; wpa_drivers[i]; i++) { + if (wpa_drivers[i] != hapd->driver) + continue; + + if (s_hapd_global.drv_priv[i] == NULL && + wpa_drivers[i]->global_init) { + s_hapd_global.drv_priv[i] = wpa_drivers[i]->global_init(iface->interfaces); + if (s_hapd_global.drv_priv[i] == NULL) { + wpa_printf(MSG_ERROR, "Failed to initialize " + "driver '%s'", + wpa_drivers[i]->name); + return -1; + } + } + + params.global_priv = s_hapd_global.drv_priv[i]; + break; + } + params.bssid = b; + params.ifname = hapd->conf->iface; + params.driver_params = hapd->iconf->driver_params; + params.use_pae_group_addr = hapd->conf->use_pae_group_addr; + + params.num_bridge = hapd->iface->num_bss; + params.bridge = os_calloc(hapd->iface->num_bss, sizeof(char *)); + if (params.bridge == NULL) + return -1; + + for (i = 0; i < hapd->iface->num_bss; i++) { + struct hostapd_data *bss = hapd->iface->bss[i]; +#ifdef CONFIG_FULL_HOSTAPD + if (bss->conf->bridge[0]) { + params.bridge[i] = bss->conf->bridge; + } +#endif + os_printf("[csa]csa_in_progress[%d:%d]-clear\r\n", i, bss->csa_in_progress); + bss->csa_in_progress = 0; /* test wangzhilei*/ + } + + os_memcpy(hapd->own_addr, b, ETH_ALEN); + params.own_addr = hapd->own_addr; + + hapd->drv_priv = hapd->driver->hapd_init(hapd, ¶ms); + os_free(params.bridge); + if (hapd->drv_priv == NULL) { + wpa_printf(MSG_ERROR, "%s driver initialization failed.", + hapd->driver->name); + hapd->driver = NULL; + return -1; + } + + if (hapd->driver->get_capa && + hapd->driver->get_capa(hapd->drv_priv, &capa) == 0) { +#ifdef CONFIG_FULL_HOSTAPD + struct wowlan_triggers *triggs; +#endif + + iface->drv_flags = capa.flags; + iface->smps_modes = capa.smps_modes; + iface->probe_resp_offloads = capa.probe_resp_offloads; + /* + * Use default extended capa values from per-radio information + */ + iface->extended_capa = capa.extended_capa; + iface->extended_capa_mask = capa.extended_capa_mask; + iface->extended_capa_len = capa.extended_capa_len; + iface->drv_max_acl_mac_addrs = capa.max_acl_mac_addrs; + + /* + * Override extended capa with per-interface type (AP), if + * available from the driver. + */ + hostapd_get_ext_capa(iface); + +#ifdef CONFIG_FULL_HOSTAPD + triggs = wpa_get_wowlan_triggers(conf->wowlan_triggers, &capa); + if (triggs && hapd->driver->set_wowlan) { + if (hapd->driver->set_wowlan(hapd->drv_priv, triggs)) + wpa_printf(MSG_ERROR, "set_wowlan failed"); + } + os_free(triggs); +#endif + } + + return 0; +} + + +/** + * hostapd_interface_init - Read configuration file and init BSS data + * + * This function is used to parse configuration file for a full interface (one + * or more BSSes sharing the same radio) and allocate memory for the BSS + * g_hapd_interfaces. No actiual driver operations are started. + */ +static struct hostapd_iface * +hostapd_interface_init(struct hapd_interfaces *interfaces, const char *if_name, + const char *config_fname, int debug) +{ + struct hostapd_iface *iface; + int k; + + wpa_printf(MSG_ERROR, "Configuration file: %s", config_fname); + iface = hostapd_init(interfaces, config_fname); + if (!iface) + return NULL; + + if (if_name) { + os_strlcpy(iface->conf->bss[0]->iface, if_name, + sizeof(iface->conf->bss[0]->iface)); + } + + iface->interfaces = interfaces; + + for (k = 0; k < debug; k++) { + if (iface->bss[0]->conf->logger_stdout_level > 0) + iface->bss[0]->conf->logger_stdout_level--; + } + + if (iface->conf->bss[0]->iface[0] == '\0' && + !hostapd_drv_none(iface->bss[0])) { + wpa_printf(MSG_ERROR, + "Interface name not specified in %s, nor by '-i' parameter", + config_fname); + hostapd_interface_deinit_free(iface); + return NULL; + } + + return iface; +} + +static int hostapd_global_init(struct hapd_interfaces *interfaces, + const char *entropy_file) +{ + int i; + + os_memset(&s_hapd_global, 0, sizeof(s_hapd_global)); + + //hostapd_logger_register_cb(hostapd_logger_cb); + + for (i = 0; wpa_drivers[i]; i++) + s_hapd_global.drv_count++; + if (s_hapd_global.drv_count == 0) { + wpa_printf(MSG_ERROR, "No drivers enabled"); + return -1; + } + s_hapd_global.drv_priv = os_calloc(s_hapd_global.drv_count, sizeof(void *)); + if (s_hapd_global.drv_priv == NULL) + return -1; + + return 0; +} + + +static void hostapd_global_deinit(const char *pid_file, int eloop_initialized) +{ + int i; + + for (i = 0; wpa_drivers[i] && s_hapd_global.drv_priv; i++) { + if (!s_hapd_global.drv_priv[i]) + continue; + + if(wpa_drivers[i]->global_deinit) + wpa_drivers[i]->global_deinit(s_hapd_global.drv_priv[i]); + } + os_free(s_hapd_global.drv_priv); + s_hapd_global.drv_priv = NULL; + + eloop_free_resource(); + + os_daemonize_terminate(pid_file); +} + +static int hostapd_global_run(struct hapd_interfaces *ifaces, int daemonize, + const char *pid_file) +{ + if (daemonize && os_daemonize(pid_file)) { + return -1; + } + + eloop_run(); + + return 0; +} + +static const char * hostapd_msg_ifname_cb(void *ctx) +{ + struct hostapd_data *hapd = ctx; + if (hapd && hapd->conf) + return hapd->conf->iface; + return NULL; +} + +/* Periodic cleanup tasks */ +static void hostapd_periodic(void *eloop_ctx, void *timeout_ctx) +{ +} + +int hostapd_main_exit(void) +{ + size_t i; + + if (0 == g_hapd_interfaces.count) + return 0; + + for (i = 0; i < g_hapd_interfaces.count; i++) { + if (!g_hapd_interfaces.iface[i]) + continue; + + g_hapd_interfaces.iface[i]->driver_ap_teardown = + !!(g_hapd_interfaces.iface[i]->drv_flags & + WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT); + + hostapd_interface_deinit_free(g_hapd_interfaces.iface[i]); + g_hapd_interfaces.iface[i] = NULL; + } + os_free(g_hapd_interfaces.iface); + g_hapd_interfaces.iface = NULL; + g_hapd_interfaces.count = 0; + + eloop_signals_remove_signal(SIGCSA); + eloop_cancel_timeout(hostapd_periodic, &g_hapd_interfaces, NULL); + hostapd_global_deinit(NULL, 1); + + return 0; +} + +/** + * Usage: + * hostapd -g /var/run/hostapd/global -b phy0:ath10k.conf -b phy0:ath10k-1.conf -b phy0:ath10k-2.conf + * -b : : add a bss config + * + * ath10k-1.conf: + * interface=wlan0-1 + * ssid=ath10k-1 + * bssid=02:00:00:00:03:01 + * + * ath10k-2.conf: + * interface=wlan0-2 + * ssid=ath10k-2 + * bssid=02:00:00:00:03:02 + * wpa=2 + * wpa_passphrase=0987654321 + * wpa_key_mgmt=WPA-PSK + * rsn_pairwise=CCMP + * + */ +int hostapd_main_entry(int argc, char *argv[]) +{ + int ret = 1; + size_t i; + int debug = 0; + char *pid_file = NULL; + const char *log_file = NULL; + const char *entropy_file = NULL; +#ifdef CONFIG_MBSSID + char *bss_config[1] = {CFG_BSS_CONFIG}; //"wangzhilei_config:bss_fname" +#endif + size_t num_bss_configs = 0; + //int start_ifaces_in_sync = 0; + //char **if_names = NULL; + //size_t if_names_size = 0; +#ifdef CONFIG_DPP + struct dpp_global_config dpp_conf; +#endif /* CONFIG_DPP */ + //char *ap_iface_buf = CFG_AP_IFACE_CONFIG; //"bss_config= wlan0" + + //ap_iface_buf = os_zalloc(strlen(CFG_AP_IFACE_CONFIG) + 2); + //if (0 == ap_iface_buf) + // return -1; + + //os_memcpy(ap_iface_buf, CFG_AP_IFACE_CONFIG,(strlen(CFG_AP_IFACE_CONFIG) + 1)); + if (os_program_init()) { + //os_free(ap_iface_buf); + return -1; + } + + os_memset(&g_hapd_interfaces, 0, sizeof(g_hapd_interfaces)); + g_hapd_interfaces.reload_config = hostapd_reload_config; + g_hapd_interfaces.config_read_cb = hostapd_config_read; + g_hapd_interfaces.for_each_interface = hostapd_for_each_interface; + g_hapd_interfaces.ctrl_iface_init = 0; + g_hapd_interfaces.ctrl_iface_deinit = 0; + g_hapd_interfaces.driver_init = hostapd_driver_init; +#ifdef CONFIG_DPP + os_memset(&dpp_conf, 0, sizeof(dpp_conf)); + /* TODO: dpp_conf.msg_ctx? */ + interfaces.dpp = dpp_global_init(&dpp_conf); + if (!interfaces.dpp) + return -1; +#endif /* CONFIG_DPP */ + + wpa_msg_register_ifname_cb(hostapd_msg_ifname_cb); + + g_hapd_interfaces.count = argc - 1; + if (g_hapd_interfaces.count || num_bss_configs) { + g_hapd_interfaces.iface = os_calloc(g_hapd_interfaces.count + num_bss_configs, + sizeof(struct hostapd_iface *)); + if (g_hapd_interfaces.iface == NULL) { + //os_free(ap_iface_buf); + fatal_prf("malloc failed\r\n"); + return -1; + } + } + + if (hostapd_global_init(&g_hapd_interfaces, entropy_file)) { + //os_free(ap_iface_buf); + fatal_prf("Failed to initialize global context\r\n"); + return -1; + } + + /* Allocate and parse configuration for full interface files */ + for (i = 0; i < g_hapd_interfaces.count; i++) { + char *config_fname = CFG_CONFIG_FNAME; //"beken_cfg_fname" + + g_hapd_interfaces.iface[i] = hostapd_interface_init(&g_hapd_interfaces, + "wlan0", + config_fname, + debug); + if (!g_hapd_interfaces.iface[i]) { + fatal_prf("Failed to initialize interface\r\n"); + goto out; + } + //if (start_ifaces_in_sync) + // interfaces.iface[i]->need_to_start_in_sync = 1; + } + +#ifdef CONFIG_MBSSID + /* Allocate and parse configuration for per-BSS files */ + for (i = 0; i < num_bss_configs; i++) { + struct hostapd_iface *iface; + char *fname; + + wpa_printf(MSG_INFO, "BSS config: %s", bss_config[i]); + fname = os_strchr(bss_config[i], ':'); + if (fname == NULL) { + wpa_printf(MSG_ERROR, + "Invalid BSS config identifier '%s'", + bss_config[i]); + goto out; + } + *fname++ = '\0'; + iface = hostapd_interface_init_bss(&g_hapd_interfaces, bss_config[i], + fname, debug); + if (iface == NULL) + goto out; + for (j = 0; j < g_hapd_interfaces.count; j++) { + if (g_hapd_interfaces.iface[j] == iface) + break; + } + if (j == g_hapd_interfaces.count) { + struct hostapd_iface **tmp; + tmp = os_realloc_array(g_hapd_interfaces.iface, + g_hapd_interfaces.count + 1, + sizeof(struct hostapd_iface *)); + if (tmp == NULL) { + hostapd_interface_deinit_free(iface); + goto out; + } + g_hapd_interfaces.iface = tmp; + g_hapd_interfaces.iface[g_hapd_interfaces.count++] = iface; + } + } +#endif + + /* + * Enable configured g_hapd_interfaces. Depending on channel configuration, + * this may complete full initialization before returning or use a + * callback mechanism to complete setup in case of operations like HT + * co-ex scans, ACS, or DFS are needed to determine channel parameters. + * In such case, the interface will be enabled from eloop context within + * hostapd_global_run(). + */ + g_hapd_interfaces.terminate_on_error = g_hapd_interfaces.count; + for (i = 0; i < g_hapd_interfaces.count; i++) { + if (hostapd_driver_init(g_hapd_interfaces.iface[i]) || + hostapd_setup_interface(g_hapd_interfaces.iface[i])) + goto out; + } + + //hostapd_global_ctrl_iface_init(&interfaces); +#if 0//def NOT_USED + hostapd_add_iface(&g_hapd_interfaces, ap_iface_buf); //ap_iface_buf: "bss_config= wlan0" +#endif + + ret = 0; + + //os_free(ap_iface_buf); + //ap_iface_buf = NULL; + + return ret; + +out: + /* Deinitialize all g_hapd_interfaces */ + fatal_prf("hostapd_main_init_failed\r\n"); + for (i = 0; i < g_hapd_interfaces.count; i++) { + if (!g_hapd_interfaces.iface[i]) + continue; + + g_hapd_interfaces.iface[i]->driver_ap_teardown = + !!(g_hapd_interfaces.iface[i]->drv_flags & + WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT); + + hostapd_interface_deinit_free(g_hapd_interfaces.iface[i]); + g_hapd_interfaces.iface[i] = NULL; + } + os_free(g_hapd_interfaces.iface); + g_hapd_interfaces.iface = NULL; + g_hapd_interfaces.count = 0; +#ifdef CONFIG_DPP + dpp_global_deinit(g_hapd_interfaces.dpp); +#endif /* CONFIG_DPP */ + + eloop_cancel_timeout(hostapd_periodic, &g_hapd_interfaces, NULL); + hostapd_global_deinit(pid_file, 1); + + os_free(pid_file); + pid_file = NULL; + + //os_free(ap_iface_buf); + //ap_iface_buf = NULL; + + if (log_file) + wpa_debug_close_file(); + wpa_debug_close_linux_tracing(); + + os_program_deinit(); + + return ret; +} + + +static void hostapd_thread_main( void *arg ) +{ + int daemonize = 0; + char *pid_file = NULL; + + if (hostapd_global_run(&g_hapd_interfaces, daemonize, pid_file)) { + wpa_printf(MSG_ERROR, "Failed to start eloop"); + } +} + +int hostapd_channel_switch(int new_freq) +{ +#if CFG_WPA_CTRL_IFACE + return wpa_ctrl_request_async(WPA_CTRL_CMD_AP_CHAN_SWITCH, (void *)new_freq); +#else + return ap_channel_switch(g_hapd_interfaces.iface[0], new_freq); +#endif +} + +#if CFG_WPA_CTRL_IFACE +int wpa_hostapd_queue_command(wpah_msg_t *msg) +{ + int ret = -1; + + if (!wpah_queue) + goto poll_exit; + + ret = rtos_push_to_queue(&wpah_queue, msg, BEKEN_NO_WAIT); + if (kNoErr != ret) + os_printf("wpa_hostapd_queue_command:%d\r\n", ret); + +poll_exit: + return ret; +} +#endif + +uint32_t wpa_hostapd_queue_poll(uint32_t param) +{ + OSStatus ret = 0; + wpah_msg_t msg = {0}; + + if (NULL == wpah_queue) + goto poll_exit; + +#if CFG_WPA_CTRL_IFACE + msg.cmd = WPA_CTRL_CMD_SOCKET;; +#endif + msg.argu = (u32)param; + ret = rtos_push_to_queue(&wpah_queue, &msg, BEKEN_NO_WAIT); + if (kNoErr != ret) + os_printf("wpa_hostapd_queue_poll_failed:%d\r\n", ret); + +poll_exit: + return ret; +} + +// eof + diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/hostapd/main_none.h b/beken_os/beken378/func/wpa_supplicant-2.9/hostapd/main_none.h new file mode 100755 index 0000000..240a2d8 --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/hostapd/main_none.h @@ -0,0 +1,35 @@ +#ifndef _MAIN_NONE_H_ +#define _MAIN_NONE_H_ + +#include "os.h" +#include "eloop.h" + +#define CFG_CONFIG_FNAME "beken_cfg_fname" +#define CFG_BSS_CONFIG "wangzhilei_config:bss_fname" +#define CFG_AP_IFACE_CONFIG "bss_config= wlan0" +#define WEP40_KEY_LENGTH 10 + +struct hapd_global { + void **drv_priv; + size_t drv_count; +}; + +extern char *bss_iface; + +void hostapd_thread_start(void); +void hostapd_thread_stop(void); +extern int hostapd_main_entry(int argc, char *argv[]); +extern int hostapd_channel_switch(int new_freq); +extern int supplicant_main_entry(char *oob_ssid); +extern int supplicant_main_exit(); +extern void wpa_supplicant_poll(void *param); +int wpa_hostapd_queue_command(wpah_msg_t *msg); +int hostapd_main_exit(void); +int hostapd_main_entry(int argc, char *argv[]); +struct wpa_supplicant *wpa_suppliant_ctrl_get_wpas(); +struct hapd_interfaces *hostapd_ctrl_get_interfaces(); + + +#endif // _MAIN_NONE_H_ +// eof + diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/accounting.h b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/accounting.h new file mode 100755 index 0000000..de5a33f --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/accounting.h @@ -0,0 +1,45 @@ +/* + * hostapd / RADIUS Accounting + * Copyright (c) 2002-2005, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef ACCOUNTING_H +#define ACCOUNTING_H + +#ifdef CONFIG_NO_ACCOUNTING +static inline int accounting_sta_get_id(struct hostapd_data *hapd, + struct sta_info *sta) +{ + return 0; +} + +static inline void accounting_sta_start(struct hostapd_data *hapd, + struct sta_info *sta) +{ +} + +static inline void accounting_sta_stop(struct hostapd_data *hapd, + struct sta_info *sta) +{ +} + +static inline int accounting_init(struct hostapd_data *hapd) +{ + return 0; +} + +static inline void accounting_deinit(struct hostapd_data *hapd) +{ +} +#else /* CONFIG_NO_ACCOUNTING */ +int accounting_sta_get_id(struct hostapd_data *hapd, struct sta_info *sta); +void accounting_sta_start(struct hostapd_data *hapd, struct sta_info *sta); +void accounting_sta_stop(struct hostapd_data *hapd, struct sta_info *sta); +int accounting_init(struct hostapd_data *hapd); +void accounting_deinit(struct hostapd_data *hapd); +#endif /* CONFIG_NO_ACCOUNTING */ + +#endif /* ACCOUNTING_H */ diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/acs.h b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/acs.h new file mode 100755 index 0000000..ec84f0e --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/acs.h @@ -0,0 +1,32 @@ +/* + * ACS - Automatic Channel Selection module + * Copyright (c) 2011, Atheros Communications + * Copyright (c) 2013, Qualcomm Atheros, Inc. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef ACS_H +#define ACS_H + +#ifdef CONFIG_ACS + +enum hostapd_chan_status acs_init(struct hostapd_iface *iface); +void acs_cleanup(struct hostapd_iface *iface); + +#else /* CONFIG_ACS */ + +static inline enum hostapd_chan_status acs_init(struct hostapd_iface *iface) +{ + wpa_printf(MSG_ERROR, "ACS was disabled on your build, rebuild hostapd with CONFIG_ACS=y or set channel"); + return HOSTAPD_CHAN_INVALID; +} + +static inline void acs_cleanup(struct hostapd_iface *iface) +{ +} + +#endif /* CONFIG_ACS */ + +#endif /* ACS_H */ diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/airtime_policy.h b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/airtime_policy.h new file mode 100755 index 0000000..c2a9b00 --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/airtime_policy.h @@ -0,0 +1,48 @@ +/* + * Airtime policy configuration + * Copyright (c) 2018-2019, Toke Høiland-Jørgensen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef AIRTIME_POLICY_H +#define AIRTIME_POLICY_H + +struct hostapd_iface; + +#ifdef CONFIG_AIRTIME_POLICY + +#define AIRTIME_DEFAULT_UPDATE_INTERVAL 200 /* ms */ +#define AIRTIME_BACKLOG_EXPIRY_FACTOR 2500 /* 2.5 intervals + convert to usec */ + +/* scale quantum so this becomes the effective quantum after applying the max + * weight, but never go below min or above max */ +#define AIRTIME_QUANTUM_MIN 8 /* usec */ +#define AIRTIME_QUANTUM_MAX 256 /* usec */ +#define AIRTIME_QUANTUM_TARGET 1024 /* usec */ + +int airtime_policy_new_sta(struct hostapd_data *hapd, struct sta_info *sta); +int airtime_policy_update_init(struct hostapd_iface *iface); +void airtime_policy_update_deinit(struct hostapd_iface *iface); + +#else /* CONFIG_AIRTIME_POLICY */ + +static inline int airtime_policy_new_sta(struct hostapd_data *hapd, + struct sta_info *sta) +{ + return -1; +} + +static inline int airtime_policy_update_init(struct hostapd_iface *iface) +{ + return -1; +} + +static inline void airtime_policy_update_deinit(struct hostapd_iface *iface) +{ +} + +#endif /* CONFIG_AIRTIME_POLICY */ + +#endif /* AIRTIME_POLICY_H */ diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ap_config.c b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ap_config.c new file mode 100755 index 0000000..cf52b26 --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ap_config.c @@ -0,0 +1,814 @@ +/* + * hostapd / Configuration helper functions + * Copyright (c) 2003-2014, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "crypto/sha1.h" +#include "common/ieee802_11_defs.h" +#include "common/eapol_common.h" +#include "wpa_auth.h" +#include "ap/sta_info.h" +#include "ap_config.h" + + +static void hostapd_config_free_vlan(struct hostapd_bss_config *bss) +{ + struct hostapd_vlan *vlan, *prev; + + vlan = bss->vlan; + prev = NULL; + while (vlan) { + prev = vlan; + vlan = vlan->next; + os_free(prev); + } + + bss->vlan = NULL; +} + + +#ifndef DEFAULT_WPA_DISABLE_EAPOL_KEY_RETRIES +#define DEFAULT_WPA_DISABLE_EAPOL_KEY_RETRIES 0 +#endif /* DEFAULT_WPA_DISABLE_EAPOL_KEY_RETRIES */ + +void hostapd_config_defaults_bss(struct hostapd_bss_config *bss) +{ +#ifdef CONFIG_INTERWORKING + dl_list_init(&bss->anqp_elem); +#endif + + bss->auth_algs = WPA_AUTH_ALG_OPEN /*| WPA_AUTH_ALG_SHARED*/; + + bss->wep_rekeying_period = 300; + /* use key0 in individual key and key1 in broadcast key */ + bss->broadcast_key_idx_min = 1; + bss->broadcast_key_idx_max = 2; + bss->eap_reauth_period = 3600; + + bss->wpa_group_rekey = 600; + bss->wpa_gmk_rekey = 86400; + bss->wpa_group_update_count = 4; + bss->wpa_pairwise_update_count = 4; + bss->wpa_disable_eapol_key_retries = + DEFAULT_WPA_DISABLE_EAPOL_KEY_RETRIES; + bss->wpa_key_mgmt = WPA_KEY_MGMT_PSK; + bss->wpa_pairwise = WPA_CIPHER_TKIP; + bss->wpa_group = WPA_CIPHER_TKIP; + bss->rsn_pairwise = 0; + + bss->max_num_sta = MAX_STA_COUNT; + + bss->dtim_period = 2; + + bss->ap_max_inactivity = AP_MAX_INACTIVITY; + bss->eapol_version = EAPOL_VERSION; + + bss->max_listen_interval = 65535; + +#ifdef CONFIG_IEEE80211W_AP +#if CFG_WFA_CERT + bss->ieee80211w = MGMT_FRAME_PROTECTION_REQUIRED; +#else + bss->ieee80211w = MGMT_FRAME_PROTECTION_OPTIONAL; +#endif + bss->assoc_sa_query_max_timeout = 1000; + bss->assoc_sa_query_retry_timeout = 201; + bss->group_mgmt_cipher = WPA_CIPHER_AES_128_CMAC; +#endif /* CONFIG_IEEE80211W_AP */ +#ifdef EAP_SERVER_FAST + /* both anonymous and authenticated provisioning */ + bss->eap_fast_prov = 3; + bss->pac_key_lifetime = 7 * 24 * 60 * 60; + bss->pac_key_refresh_time = 1 * 24 * 60 * 60; +#endif /* EAP_SERVER_FAST */ + + /* Set to -1 as defaults depends on HT in setup */ + bss->wmm_enabled = -1; + +#ifdef CONFIG_IEEE80211R_AP + bss->ft_over_ds = 1; + bss->rkh_pos_timeout = 86400; + bss->rkh_neg_timeout = 60; + bss->rkh_pull_timeout = 1000; + bss->rkh_pull_retries = 4; + bss->r0_key_lifetime = 1209600; +#endif /* CONFIG_IEEE80211R_AP */ +#ifdef CONFIG_SAE_AP + bss->sae_anti_clogging_threshold = 2; + bss->sae_sync = 5; +#endif + + bss->broadcast_deauth = 1; + + bss->send_probe_response = 1; + +} + + +struct hostapd_config * hostapd_config_defaults(void) +{ +#define ecw2cw(ecw) ((1 << (ecw)) - 1) + + struct hostapd_config *conf; + struct hostapd_bss_config *bss; + const int aCWmin = 4, aCWmax = 10; + const struct hostapd_wmm_ac_params ac_bk = + { aCWmin, aCWmax, 7, 0, 0 }; /* background traffic */ + const struct hostapd_wmm_ac_params ac_be = + { aCWmin, aCWmax, 3, 0, 0 }; /* best effort traffic */ + const struct hostapd_wmm_ac_params ac_vi = /* video traffic */ + { aCWmin - 1, aCWmin, 2, 3008 / 32, 0 }; + const struct hostapd_wmm_ac_params ac_vo = /* voice traffic */ + { aCWmin - 2, aCWmin - 1, 2, 1504 / 32, 0 }; + const struct hostapd_tx_queue_params txq_bk = + { 7, ecw2cw(aCWmin), ecw2cw(aCWmax), 0 }; + const struct hostapd_tx_queue_params txq_be = + { 3, ecw2cw(aCWmin), 4 * (ecw2cw(aCWmin) + 1) - 1, 0}; + const struct hostapd_tx_queue_params txq_vi = + { 1, (ecw2cw(aCWmin) + 1) / 2 - 1, ecw2cw(aCWmin), 30}; + const struct hostapd_tx_queue_params txq_vo = + { 1, (ecw2cw(aCWmin) + 1) / 4 - 1, + (ecw2cw(aCWmin) + 1) / 2 - 1, 15}; + +#undef ecw2cw + + conf = os_zalloc(sizeof(*conf)); + bss = os_zalloc(sizeof(*bss)); + if (conf == NULL || bss == NULL) { + wpa_printf(MSG_ERROR, "Failed to allocate memory for " + "configuration data."); + os_free(conf); + os_free(bss); + return NULL; + } + conf->bss = os_calloc(1, sizeof(struct hostapd_bss_config *)); + if (conf->bss == NULL) { + os_free(conf); + os_free(bss); + return NULL; + } + conf->bss[0] = bss; + + hostapd_config_defaults_bss(bss); + + conf->num_bss = 1; + + #if CFG_SUPPORT_80211G + conf->hw_mode = HOSTAPD_MODE_IEEE80211G; + #endif + + conf->beacon_int = 100; + conf->rts_threshold = -2; /* use driver default: 2347 */ + conf->fragm_threshold = -2; /* user driver default: 2346 */ + /* Set to invalid value means do not add Power Constraint IE */ + conf->local_pwr_constraint = -1; + + conf->wmm_ac_params[0] = ac_be; + conf->wmm_ac_params[1] = ac_bk; + conf->wmm_ac_params[2] = ac_vi; + conf->wmm_ac_params[3] = ac_vo; + + conf->tx_queue[0] = txq_vo; + conf->tx_queue[1] = txq_vi; + conf->tx_queue[2] = txq_be; + conf->tx_queue[3] = txq_bk; + + #if CFG_AP_SUPPORT_HT_IE + conf->ht_capab = HT_CAP_INFO_SMPS_DISABLED | HT_CAP_INFO_SHORT_GI20MHZ + | HT_CAP_INFO_TX_STBC + | HT_CAP_INFO_RX_STBC_1 + | HT_CAP_INFO_MAX_AMSDU_SIZE; + #else + conf->ht_capab = HT_CAP_INFO_SMPS_DISABLED; + #endif + + conf->ap_table_max_size = 255; + conf->ap_table_expiration_time = 60; + conf->track_sta_max_age = 0;//180; + + conf->acs = 0; + conf->acs_ch_list.num = 0; +#ifdef CONFIG_ACS + conf->acs_num_scans = 5; +#endif /* CONFIG_ACS */ + +#ifdef CONFIG_IEEE80211AX + conf->he_op.he_rts_threshold = HE_OPERATION_RTS_THRESHOLD_MASK >> + HE_OPERATION_RTS_THRESHOLD_OFFSET; + /* Set default basic MCS/NSS set to single stream MCS 0-7 */ + conf->he_op.he_basic_mcs_nss_set = 0xfffc; +#endif /* CONFIG_IEEE80211AX */ + + /* The third octet of the country string uses an ASCII space character + * by default to indicate that the regulations encompass all + * environments for the current frequency band in the country. */ + conf->country[2] = ' '; + + conf->rssi_reject_assoc_rssi = 0; + conf->rssi_reject_assoc_timeout = 30; + + return conf; +} + + +int hostapd_mac_comp(const void *a, const void *b) +{ + return os_memcmp(a, b, sizeof(macaddr)); +} + + + +static int hostapd_derive_psk(struct hostapd_ssid *ssid) +{ + ssid->wpa_psk = os_zalloc(sizeof(struct hostapd_wpa_psk)); + if (ssid->wpa_psk == NULL) { + wpa_printf(MSG_ERROR, "Unable to alloc space for PSK"); + return -1; + } + wpa_hexdump_ascii(MSG_DEBUG, "SSID", + (u8 *) ssid->ssid, ssid->ssid_len); + wpa_hexdump_ascii_key(MSG_DEBUG, "PSK (ASCII passphrase)", + (u8 *) ssid->wpa_passphrase, + os_strlen(ssid->wpa_passphrase)); + pbkdf2_sha1(ssid->wpa_passphrase, + ssid->ssid, ssid->ssid_len, + 4096, ssid->wpa_psk->psk, PMK_LEN); + wpa_hexdump_key(MSG_DEBUG, "PSK (from passphrase)", + ssid->wpa_psk->psk, PMK_LEN); + return 0; +} + + +int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf) +{ + struct hostapd_ssid *ssid = &conf->ssid; + + if (ssid->wpa_passphrase != NULL) { + if (ssid->wpa_psk != NULL) { + wpa_printf(MSG_DEBUG, "Using pre-configured WPA PSK " + "instead of passphrase"); + } else { + wpa_printf(MSG_DEBUG, "Deriving WPA PSK based on " + "passphrase"); + if (hostapd_derive_psk(ssid) < 0) + return -1; + } + ssid->wpa_psk->group = 1; + } + + return 0; +} + +static void hostapd_config_free_wep(struct hostapd_wep_keys *keys) +{ + int i; + for (i = 0; i < NUM_WEP_KEYS; i++) { + bin_clear_free(keys->key[i], keys->len[i]); + keys->key[i] = NULL; + } +} + + +void hostapd_config_clear_wpa_psk(struct hostapd_wpa_psk **l) +{ + struct hostapd_wpa_psk *psk, *tmp; + + for (psk = *l; psk;) { + tmp = psk; + psk = psk->next; + bin_clear_free(tmp, sizeof(*tmp)); + } + *l = NULL; +} + +#ifdef CONFIG_INTERWORKING +static void hostapd_config_free_anqp_elem(struct hostapd_bss_config *conf) +{ + struct anqp_element *elem; + + while ((elem = dl_list_first(&conf->anqp_elem, struct anqp_element, + list))) { + dl_list_del(&elem->list); + wpabuf_free(elem->payload); + os_free(elem); + } +} +#endif + + +#ifdef CONFIG_SAE_AP +static void hostapd_config_free_sae_passwords(struct hostapd_bss_config *conf) +{ + struct sae_password_entry *pw, *tmp; + + pw = conf->sae_passwords; + conf->sae_passwords = NULL; + while (pw) { + tmp = pw; + pw = pw->next; + str_clear_free(tmp->password); + os_free(tmp->identifier); + os_free(tmp); + } +} +#endif + +#ifdef CONFIG_DPP2 +static void hostapd_dpp_controller_conf_free(struct dpp_controller_conf *conf) +{ + struct dpp_controller_conf *prev; + + while (conf) { + prev = conf; + conf = conf->next; + os_free(prev); + } +} +#endif /* CONFIG_DPP2 */ + + +void hostapd_config_free_bss(struct hostapd_bss_config *conf) +{ + if (conf == NULL) + return; + + hostapd_config_clear_wpa_psk(&conf->ssid.wpa_psk); + + str_clear_free(conf->ssid.wpa_passphrase); + hostapd_config_free_wep(&conf->ssid.wep); +#ifdef CONFIG_FULL_DYNAMIC_VLAN + os_free(conf->ssid.vlan_tagged_interface); +#endif /* CONFIG_FULL_DYNAMIC_VLAN */ + + os_free(conf->rsn_preauth_interfaces); +#ifdef CONFIG_FULL_HOSTAPD + os_free(conf->ctrl_interface); + hostapd_config_free_vlan(conf); + os_free(conf->time_zone); +#endif + +#ifdef CONFIG_IEEE80211R_AP + { + struct ft_remote_r0kh *r0kh, *r0kh_prev; + struct ft_remote_r1kh *r1kh, *r1kh_prev; + + r0kh = conf->r0kh_list; + conf->r0kh_list = NULL; + while (r0kh) { + r0kh_prev = r0kh; + r0kh = r0kh->next; + os_free(r0kh_prev); + } + + r1kh = conf->r1kh_list; + conf->r1kh_list = NULL; + while (r1kh) { + r1kh_prev = r1kh; + r1kh = r1kh->next; + os_free(r1kh_prev); + } + } +#endif /* CONFIG_IEEE80211R_AP */ + +#ifdef CONFIG_INTERWORKING + hostapd_config_free_anqp_elem(conf); +#endif + + wpabuf_free(conf->vendor_elements); + wpabuf_free(conf->assocresp_elements); + +#ifdef CONFIG_SAE_AP + os_free(conf->sae_groups); +#endif +#ifdef CONFIG_OWE + os_free(conf->owe_groups); +#endif /* CONFIG_OWE */ + +#ifdef CONFIG_FULL_HOSTAPD + os_free(conf->wowlan_triggers); + os_free(conf->server_id); +#endif + + os_free(conf->no_probe_resp_if_seen_on); + os_free(conf->no_auth_if_seen_on); +#ifdef CONFIG_DPP + os_free(conf->dpp_connector); + wpabuf_free(conf->dpp_netaccesskey); + wpabuf_free(conf->dpp_csign); +#ifdef CONFIG_DPP2 + hostapd_dpp_controller_conf_free(conf->dpp_controller); +#endif /* CONFIG_DPP2 */ +#endif /* CONFIG_DPP */ + +#ifdef CONFIG_SAE_AP + hostapd_config_free_sae_passwords(conf); +#endif + + os_free(conf); +} + + +/** + * hostapd_config_free - Free hostapd configuration + * @conf: Configuration data from hostapd_config_read(). + */ +void hostapd_config_free(struct hostapd_config *conf) +{ + size_t i; + + if (conf == NULL) + return; + + for (i = 0; i < conf->num_bss; i++) + hostapd_config_free_bss(conf->bss[i]); + os_free(conf->bss); + os_free(conf->supported_rates); + os_free(conf->basic_rates); + os_free(conf->acs_ch_list.range); + os_free(conf->driver_params); +#ifdef CONFIG_ACS + os_free(conf->acs_chan_bias); +#endif /* CONFIG_ACS */ + + os_free(conf); +} + + +#ifdef CONFIG_HOSTAPD_ACL +/** + * hostapd_maclist_found - Find a MAC address from a list + * @list: MAC address list + * @num_entries: Number of addresses in the list + * @addr: Address to search for + * @vlan_id: Buffer for returning VLAN ID or %NULL if not needed + * Returns: 1 if address is in the list or 0 if not. + * + * Perform a binary search for given MAC address from a pre-sorted list. + */ +int hostapd_maclist_found(struct mac_acl_entry *list, int num_entries, + const u8 *addr, struct vlan_description *vlan_id) +{ + int start, end, middle, res; + + start = 0; + end = num_entries - 1; + + while (start <= end) { + middle = (start + end) / 2; + res = os_memcmp(list[middle].addr, addr, ETH_ALEN); + if (res == 0) { + if (vlan_id) + *vlan_id = list[middle].vlan_id; + return 1; + } + if (res < 0) + start = middle + 1; + else + end = middle - 1; + } + + return 0; +} +#endif + +int hostapd_rate_found(int *list, int rate) +{ + int i; + + if (list == NULL) + return 0; + + for (i = 0; list[i] >= 0; i++) + if (list[i] == rate) + return 1; + + return 0; +} + +const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf, + const u8 *addr, const u8 *p2p_dev_addr, + const u8 *prev_psk, int *vlan_id) +{ + struct hostapd_wpa_psk *psk; + int next_ok = prev_psk == NULL; + + if (vlan_id) + *vlan_id = 0; + + if (p2p_dev_addr && !is_zero_ether_addr(p2p_dev_addr)) { + wpa_printf(MSG_DEBUG, "Searching a PSK for " MACSTR + " p2p_dev_addr=" MACSTR " prev_psk=%p", + MAC2STR(addr), MAC2STR(p2p_dev_addr), prev_psk); + addr = NULL; /* Use P2P Device Address for matching */ + } else { + wpa_printf(MSG_DEBUG, "Searching a PSK for " MACSTR + " prev_psk=%p", + MAC2STR(addr), prev_psk); + } + + for (psk = conf->ssid.wpa_psk; psk != NULL; psk = psk->next) { + if (next_ok && + (psk->group || + (addr && os_memcmp(psk->addr, addr, ETH_ALEN) == 0) || + (!addr && p2p_dev_addr && + os_memcmp(psk->p2p_dev_addr, p2p_dev_addr, ETH_ALEN) == + 0))) { + if (vlan_id) + *vlan_id = psk->vlan_id; + return psk->psk; + } + + if (psk->psk == prev_psk) + next_ok = 1; + } + + return NULL; +} + + +static int hostapd_config_check_bss(struct hostapd_bss_config *bss, + struct hostapd_config *conf, + int full_config) +{ + if (bss->wpa) { + int wep, i; + + wep = bss->default_wep_key_len > 0 || + bss->individual_wep_key_len > 0; + for (i = 0; i < NUM_WEP_KEYS; i++) { + if (bss->ssid.wep.keys_set) { + wep = 1; + break; + } + } + + if (wep) { + wpa_printf(MSG_ERROR, "WEP configuration in a WPA network is not supported"); + return -1; + } + } + + if (full_config && bss->wpa && (bss->wpa_key_mgmt & WPA_KEY_MGMT_PSK) && + bss->ssid.wpa_psk == NULL && bss->ssid.wpa_passphrase == NULL) { + wpa_printf(MSG_ERROR, "WPA-PSK enabled, but PSK or passphrase " + "is not configured."); + return -1; + } + + if (full_config && !is_zero_ether_addr(bss->bssid)) { + size_t i; + + for (i = 0; i < conf->num_bss; i++) { + if (conf->bss[i] != bss && + (hostapd_mac_comp(conf->bss[i]->bssid, + bss->bssid) == 0)) { + wpa_printf(MSG_ERROR, "Duplicate BSSID " MACSTR + " on interface '%s' and '%s'.", + MAC2STR(bss->bssid), + conf->bss[i]->iface, bss->iface); + return -1; + } + } + } + +#ifdef CONFIG_IEEE80211R_AP + if (full_config && wpa_key_mgmt_ft(bss->wpa_key_mgmt) && + (bss->nas_identifier == NULL || + os_strlen(bss->nas_identifier) < 1 || + os_strlen(bss->nas_identifier) > FT_R0KH_ID_MAX_LEN)) { + wpa_printf(MSG_ERROR, "FT (IEEE 802.11r) requires " + "nas_identifier to be configured as a 1..48 octet " + "string"); + return -1; + } +#endif /* CONFIG_IEEE80211R_AP */ + +#ifdef CONFIG_IEEE80211N + if (full_config && conf->ieee80211n && + conf->hw_mode == HOSTAPD_MODE_IEEE80211B) { + bss->disable_11n = 1; + wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) in 11b mode is not " + "allowed, disabling HT capabilities"); + } + + if (full_config && conf->ieee80211n && + bss->ssid.security_policy == SECURITY_STATIC_WEP) { + bss->disable_11n = 1; + wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WEP is not " + "allowed, disabling HT capabilities"); + } + + if (full_config && conf->ieee80211n && bss->wpa && + !(bss->wpa_pairwise & WPA_CIPHER_CCMP) && + !(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP | + WPA_CIPHER_CCMP_256 | WPA_CIPHER_GCMP_256))) + { + bss->disable_11n = 1; + wpa_printf(MSG_ERROR, "HT (IEEE 802.11n) with WPA/WPA2 " + "requires CCMP/GCMP to be enabled, disabling HT " + "capabilities"); + } +#endif /* CONFIG_IEEE80211N */ + +#ifdef CONFIG_IEEE80211AC + if (full_config && conf->ieee80211ac && + bss->ssid.security_policy == SECURITY_STATIC_WEP) { + bss->disable_11ac = 1; + wpa_printf(MSG_ERROR, + "VHT (IEEE 802.11ac) with WEP is not allowed, disabling VHT capabilities"); + } + + if (full_config && conf->ieee80211ac && bss->wpa && + !(bss->wpa_pairwise & WPA_CIPHER_CCMP) && + !(bss->rsn_pairwise & (WPA_CIPHER_CCMP | WPA_CIPHER_GCMP | + WPA_CIPHER_CCMP_256 | WPA_CIPHER_GCMP_256))) + { + bss->disable_11ac = 1; + wpa_printf(MSG_ERROR, + "VHT (IEEE 802.11ac) with WPA/WPA2 requires CCMP/GCMP to be enabled, disabling VHT capabilities"); + } +#endif /* CONFIG_IEEE80211AC */ +#ifdef CONFIG_OCV + if (full_config && bss->ieee80211w == NO_MGMT_FRAME_PROTECTION && + bss->ocv) { + wpa_printf(MSG_ERROR, + "OCV: PMF needs to be enabled whenever using OCV"); + return -1; + } +#endif /* CONFIG_OCV */ + + return 0; +} + + +static int hostapd_config_check_cw(struct hostapd_config *conf, int queue) +{ + int tx_cwmin = conf->tx_queue[queue].cwmin; + int tx_cwmax = conf->tx_queue[queue].cwmax; + int ac_cwmin = conf->wmm_ac_params[queue].cwmin; + int ac_cwmax = conf->wmm_ac_params[queue].cwmax; + + if (tx_cwmin > tx_cwmax) { + wpa_printf(MSG_ERROR, + "Invalid TX queue cwMin/cwMax values. cwMin(%d) greater than cwMax(%d)", + tx_cwmin, tx_cwmax); + return -1; + } + if (ac_cwmin > ac_cwmax) { + wpa_printf(MSG_ERROR, + "Invalid WMM AC cwMin/cwMax values. cwMin(%d) greater than cwMax(%d)", + ac_cwmin, ac_cwmax); + return -1; + } + return 0; +} + + +int hostapd_config_check(struct hostapd_config *conf, int full_config) +{ + size_t i; + + if (full_config && conf->ieee80211d && + (!conf->country[0] || !conf->country[1])) { + wpa_printf(MSG_ERROR, "Cannot enable IEEE 802.11d without " + "setting the country_code"); + return -1; + } + + if (full_config && conf->ieee80211h && !conf->ieee80211d) { + wpa_printf(MSG_ERROR, "Cannot enable IEEE 802.11h without " + "IEEE 802.11d enabled"); + return -1; + } + + if (full_config && conf->local_pwr_constraint != -1 && + !conf->ieee80211d) { + wpa_printf(MSG_ERROR, "Cannot add Power Constraint element without Country element"); + return -1; + } + + if (full_config && conf->spectrum_mgmt_required && + conf->local_pwr_constraint == -1) { + wpa_printf(MSG_ERROR, "Cannot set Spectrum Management bit without Country and Power Constraint elements"); + return -1; + } + + for (i = 0; i < NUM_TX_QUEUES; i++) { + if (hostapd_config_check_cw(conf, i)) + return -1; + } + + for (i = 0; i < conf->num_bss; i++) { + if (hostapd_config_check_bss(conf->bss[i], conf, full_config)) + return -1; + } + + return 0; +} + + +void hostapd_set_security_params(struct hostapd_bss_config *bss, + int full_config) +{ + if (bss->individual_wep_key_len == 0) { + /* individual keys are not use; can use key idx0 for + * broadcast keys */ + bss->broadcast_key_idx_min = 0; + } + + if ((bss->wpa & 2) && bss->rsn_pairwise == 0) + bss->rsn_pairwise = bss->wpa_pairwise; + if (bss->group_cipher) + bss->wpa_group = bss->group_cipher; + else + bss->wpa_group = wpa_select_ap_group_cipher(bss->wpa, + bss->wpa_pairwise, + bss->rsn_pairwise); + if (!bss->wpa_group_rekey_set) + bss->wpa_group_rekey = bss->wpa_group == WPA_CIPHER_TKIP ? + 600 : 86400; + + + if (bss->wpa && bss->ieee802_1x) { + bss->ssid.security_policy = SECURITY_WPA; + } else if (bss->wpa) { + bss->ssid.security_policy = SECURITY_WPA_PSK; +#ifdef CONFIG_FULL_SUPPLICANT + } else if (bss->ieee802_1x) { + int cipher = WPA_CIPHER_NONE; + bss->ssid.security_policy = SECURITY_IEEE_802_1X; + bss->ssid.wep.default_len = bss->default_wep_key_len; + if (full_config && bss->default_wep_key_len) { + cipher = bss->default_wep_key_len >= 13 ? + WPA_CIPHER_WEP104 : WPA_CIPHER_WEP40; + } else if (full_config && bss->ssid.wep.keys_set) { + if (bss->ssid.wep.len[0] >= 13) + cipher = WPA_CIPHER_WEP104; + else + cipher = WPA_CIPHER_WEP40; + } + bss->wpa_group = cipher; + bss->wpa_pairwise = cipher; + bss->rsn_pairwise = cipher; + if (full_config) + bss->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X_NO_WPA; +#endif + } else if (bss->ssid.wep.keys_set) { + int cipher = WPA_CIPHER_WEP40; + if (bss->ssid.wep.len[0] >= 13) + cipher = WPA_CIPHER_WEP104; + bss->ssid.security_policy = SECURITY_STATIC_WEP; + bss->wpa_group = cipher; + bss->wpa_pairwise = cipher; + bss->rsn_pairwise = cipher; + if (full_config) + bss->wpa_key_mgmt = WPA_KEY_MGMT_NONE; +#ifdef CONFIG_FULL_SUPPLICANT + } else if (bss->osen) { + bss->ssid.security_policy = SECURITY_OSEN; + bss->wpa_group = WPA_CIPHER_CCMP; + bss->wpa_pairwise = 0; + bss->rsn_pairwise = WPA_CIPHER_CCMP; +#endif + } else { + bss->ssid.security_policy = SECURITY_PLAINTEXT; + if (full_config) { + bss->wpa_group = WPA_CIPHER_NONE; + bss->wpa_pairwise = WPA_CIPHER_NONE; + bss->rsn_pairwise = WPA_CIPHER_NONE; + bss->wpa_key_mgmt = WPA_KEY_MGMT_NONE; + } + } +} + + +#ifdef CONFIG_SAE_AP +int hostapd_sae_pw_id_in_use(struct hostapd_bss_config *conf) +{ + int with_id = 0, without_id = 0; + struct sae_password_entry *pw; + + if (conf->ssid.wpa_passphrase) + without_id = 1; + + for (pw = conf->sae_passwords; pw; pw = pw->next) { + if (pw->identifier) + with_id = 1; + else + without_id = 1; + if (with_id && without_id) + break; + } + + if (with_id && !without_id) + return 2; + return with_id; +} +#endif + diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ap_config.h b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ap_config.h new file mode 100755 index 0000000..bd129ed --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ap_config.h @@ -0,0 +1,826 @@ +/* + * hostapd / Configuration definitions and helpers functions + * Copyright (c) 2003-2015, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef HOSTAPD_CONFIG_H +#define HOSTAPD_CONFIG_H + +#include "common/defs.h" +#include "utils/list.h" +#include "ip_addr.h" +#include "common/wpa_common.h" +#include "common/ieee802_11_defs.h" +#include "common/ieee802_11_common.h" +#include "crypto/sha256.h" +#include "wps/wps.h" +#include "vlan.h" +#include "hostapd_cfg.h" + +/** + * mesh_conf - local MBSS state and settings + */ +struct mesh_conf { + u8 meshid[32]; + u8 meshid_len; + /* Active Path Selection Protocol Identifier */ + u8 mesh_pp_id; + /* Active Path Selection Metric Identifier */ + u8 mesh_pm_id; + /* Congestion Control Mode Identifier */ + u8 mesh_cc_id; + /* Synchronization Protocol Identifier */ + u8 mesh_sp_id; + /* Authentication Protocol Identifier */ + u8 mesh_auth_id; + u8 *rsn_ie; + int rsn_ie_len; +#define MESH_CONF_SEC_NONE BIT(0) +#define MESH_CONF_SEC_AUTH BIT(1) +#define MESH_CONF_SEC_AMPE BIT(2) + unsigned int security; + enum mfp_options ieee80211w; + int ocv; + unsigned int pairwise_cipher; + unsigned int group_cipher; + unsigned int mgmt_group_cipher; + int dot11MeshMaxRetries; + int dot11MeshRetryTimeout; /* msec */ + int dot11MeshConfirmTimeout; /* msec */ + int dot11MeshHoldingTimeout; /* msec */ +}; + +#define MAX_STA_COUNT CFG_SUPPORTED_MAX_STA_NUM /* 2007 */ +#define MAX_VLAN_ID 4094 + +typedef u8 macaddr[ETH_ALEN]; + +struct mac_acl_entry { + macaddr addr; + struct vlan_description vlan_id; +}; + +struct hostapd_radius_servers; +struct ft_remote_r0kh; +struct ft_remote_r1kh; + +#define NUM_WEP_KEYS 4 +struct hostapd_wep_keys { + u8 idx; + u8 *key[NUM_WEP_KEYS]; + size_t len[NUM_WEP_KEYS]; + int keys_set; + size_t default_len; /* key length used for dynamic key generation */ +}; + +typedef enum hostap_security_policy { + SECURITY_PLAINTEXT = 0, + SECURITY_STATIC_WEP = 1, + SECURITY_IEEE_802_1X = 2, + SECURITY_WPA_PSK = 3, + SECURITY_WPA = 4, + SECURITY_OSEN = 5 +} secpolicy; + +struct hostapd_ssid { + u8 ssid[SSID_MAX_LEN]; + size_t ssid_len; + unsigned int ssid_set:1; + unsigned int utf8_ssid:1; + unsigned int wpa_passphrase_set:1; + unsigned int wpa_psk_set:1; + +#ifndef CONFIG_NO_VLAN + char vlan[IFNAMSIZ + 1]; +#endif + secpolicy security_policy; + + struct hostapd_wpa_psk *wpa_psk; + char *wpa_passphrase; + + struct hostapd_wep_keys wep; + +#define DYNAMIC_VLAN_DISABLED 0 +#define DYNAMIC_VLAN_OPTIONAL 1 +#define DYNAMIC_VLAN_REQUIRED 2 + int dynamic_vlan; +#define DYNAMIC_VLAN_NAMING_WITHOUT_DEVICE 0 +#define DYNAMIC_VLAN_NAMING_WITH_DEVICE 1 +#define DYNAMIC_VLAN_NAMING_END 2 + int vlan_naming; + int per_sta_vif; +#ifdef CONFIG_FULL_DYNAMIC_VLAN + char *vlan_tagged_interface; +#endif /* CONFIG_FULL_DYNAMIC_VLAN */ +}; + + +#define VLAN_ID_WILDCARD -1 + +struct hostapd_vlan { + struct hostapd_vlan *next; + int vlan_id; /* VLAN ID or -1 (VLAN_ID_WILDCARD) for wildcard entry */ + struct vlan_description vlan_desc; + char ifname[IFNAMSIZ + 1]; + char bridge[IFNAMSIZ + 1]; + int configured; + int dynamic_vlan; +#ifdef CONFIG_FULL_DYNAMIC_VLAN + +#define DVLAN_CLEAN_WLAN_PORT 0x8 + int clean; +#endif /* CONFIG_FULL_DYNAMIC_VLAN */ +}; + +#define PMK_LEN 32 +#define KEYID_LEN 32 +#define MIN_PASSPHRASE_LEN 8 +#define MAX_PASSPHRASE_LEN 63 +struct hostapd_sta_wpa_psk_short { + struct hostapd_sta_wpa_psk_short *next; + unsigned int is_passphrase:1; + u8 psk[PMK_LEN]; + char passphrase[MAX_PASSPHRASE_LEN + 1]; + int ref; /* (number of references held) - 1 */ +}; + +struct hostapd_wpa_psk { + struct hostapd_wpa_psk *next; + int group; + char keyid[KEYID_LEN]; + u8 psk[PMK_LEN]; + u8 addr[ETH_ALEN]; + u8 p2p_dev_addr[ETH_ALEN]; + int vlan_id; +}; + +struct hostapd_eap_user { + struct hostapd_eap_user *next; + u8 *identity; + size_t identity_len; + struct { + int vendor; + u32 method; + } methods[EAP_MAX_METHODS]; + u8 *password; + size_t password_len; + u8 *salt; + size_t salt_len; /* non-zero when password is salted */ + int phase2; + int force_version; + unsigned int wildcard_prefix:1; + unsigned int password_hash:1; /* whether password is hashed with + * nt_password_hash() */ + unsigned int remediation:1; + unsigned int macacl:1; + int ttls_auth; /* EAP_TTLS_AUTH_* bitfield */ + struct hostapd_radius_attr *accept_attr; + u32 t_c_timestamp; +}; + +struct hostapd_radius_attr { + u8 type; + struct wpabuf *val; + struct hostapd_radius_attr *next; +}; + + +#define NUM_TX_QUEUES 4 + +struct hostapd_tx_queue_params { + int aifs; + int cwmin; + int cwmax; + int burst; /* maximum burst time in 0.1 ms, i.e., 10 = 1 ms */ +}; + + +#define MAX_ROAMING_CONSORTIUM_LEN 15 + +struct hostapd_roaming_consortium { + u8 len; + u8 oi[MAX_ROAMING_CONSORTIUM_LEN]; +}; + +struct hostapd_lang_string { + u8 lang[3]; + u8 name_len; + u8 name[252]; +}; + +struct hostapd_venue_url { + u8 venue_number; + u8 url_len; + u8 url[254]; +}; + +#define MAX_NAI_REALMS 10 +#define MAX_NAI_REALMLEN 255 +#define MAX_NAI_EAP_METHODS 5 +#define MAX_NAI_AUTH_TYPES 4 +struct hostapd_nai_realm_data { + u8 encoding; + char realm_buf[MAX_NAI_REALMLEN + 1]; + char *realm[MAX_NAI_REALMS]; + u8 eap_method_count; + struct hostapd_nai_realm_eap { + u8 eap_method; + u8 num_auths; + u8 auth_id[MAX_NAI_AUTH_TYPES]; + u8 auth_val[MAX_NAI_AUTH_TYPES]; + } eap_method[MAX_NAI_EAP_METHODS]; +}; + +struct anqp_element { + struct dl_list list; + u16 infoid; + struct wpabuf *payload; +}; + +struct sae_password_entry { + struct sae_password_entry *next; + char *password; + char *identifier; + u8 peer_addr[ETH_ALEN]; + int vlan_id; +}; + +struct dpp_controller_conf { + struct dpp_controller_conf *next; + u8 pkhash[SHA256_MAC_LEN]; + struct hostapd_ip_addr ipaddr; +}; + +/** + * struct hostapd_bss_config - Per-BSS configuration + */ +struct hostapd_bss_config { + char iface[IFNAMSIZ + 1]; +#ifdef CONFIG_FULL_HOSTAPD + char bridge[IFNAMSIZ + 1]; + char vlan_bridge[IFNAMSIZ + 1]; + char wds_bridge[IFNAMSIZ + 1]; +#endif + enum hostapd_logger_level logger_syslog_level, logger_stdout_level; + + int max_num_sta; /* maximum number of STAs in station table */ + + int dtim_period; +#ifdef CONFIG_FULL_HOSTAPD + unsigned int bss_load_update_period; + unsigned int chan_util_avg_period; +#endif + + int ieee802_1x; /* use IEEE 802.1X */ + int eapol_version; +#ifdef CONFIG_FULL_HOSTAPD + int eap_server; /* Use internal EAP server instead of external + * RADIUS server */ + struct hostapd_eap_user *eap_user; + char *eap_user_sqlite; + char *eap_sim_db; + unsigned int eap_sim_db_timeout; + int eap_server_erp; /* Whether ERP is enabled on internal EAP server */ + struct hostapd_ip_addr own_ip_addr; + char *nas_identifier; + struct hostapd_radius_servers *radius; + int acct_interim_interval; + int radius_request_cui; + struct hostapd_radius_attr *radius_auth_req_attr; + struct hostapd_radius_attr *radius_acct_req_attr; + char *radius_req_attr_sqlite; + int radius_das_port; + unsigned int radius_das_time_window; + int radius_das_require_event_timestamp; + int radius_das_require_message_authenticator; + struct hostapd_ip_addr radius_das_client_addr; + u8 *radius_das_shared_secret; + size_t radius_das_shared_secret_len; +#endif + + struct hostapd_ssid ssid; + + char *eap_req_id_text; /* optional displayable message sent with + * EAP Request-Identity */ + size_t eap_req_id_text_len; + int eapol_key_index_workaround; + + size_t default_wep_key_len; + int individual_wep_key_len; + int wep_rekeying_period; + int broadcast_key_idx_min, broadcast_key_idx_max; + int eap_reauth_period; + int erp_send_reauth_start; + +#ifdef CONFIG_FULL_HOSTAPD + char *erp_domain; + + int ieee802_11f; /* use IEEE 802.11f (IAPP) */ + char iapp_iface[IFNAMSIZ + 1]; /* interface used with IAPP broadcast + * frames */ + + enum macaddr_acl { + ACCEPT_UNLESS_DENIED = 0, + DENY_UNLESS_ACCEPTED = 1, + USE_EXTERNAL_RADIUS_AUTH = 2 + } macaddr_acl; + struct mac_acl_entry *accept_mac; + int num_accept_mac; + struct mac_acl_entry *deny_mac; + int num_deny_mac; + int wds_sta; +#endif + int isolate; + int start_disabled; + + int auth_algs; /* bitfield of allowed IEEE 802.11 authentication + * algorithms, WPA_AUTH_ALG_{OPEN,SHARED,LEAP} */ + + int wpa; /* bitfield of WPA_PROTO_WPA, WPA_PROTO_RSN */ + int wpa_key_mgmt; +#ifdef CONFIG_IEEE80211W_AP + enum mfp_options ieee80211w; + int group_mgmt_cipher; + /* dot11AssociationSAQueryMaximumTimeout (in TUs) */ + unsigned int assoc_sa_query_max_timeout; + /* dot11AssociationSAQueryRetryTimeout (in TUs) */ + int assoc_sa_query_retry_timeout; +#endif /* CONFIG_IEEE80211W_AP */ +#ifdef CONFIG_OCV + int ocv; /* Operating Channel Validation */ +#endif /* CONFIG_OCV */ + enum { + PSK_RADIUS_IGNORED = 0, + PSK_RADIUS_ACCEPTED = 1, + PSK_RADIUS_REQUIRED = 2 + } wpa_psk_radius; + int wpa_pairwise; + int group_cipher; /* wpa_group value override from configuation */ + int wpa_group; + int wpa_group_rekey; + int wpa_group_rekey_set; + int wpa_strict_rekey; + int wpa_gmk_rekey; + int wpa_ptk_rekey; + u32 wpa_group_update_count; + u32 wpa_pairwise_update_count; + int wpa_disable_eapol_key_retries; + int rsn_pairwise; + int rsn_preauth; + char *rsn_preauth_interfaces; + +#ifdef CONFIG_IEEE80211R_AP + /* IEEE 802.11r - Fast BSS Transition */ + u8 mobility_domain[MOBILITY_DOMAIN_ID_LEN]; + u8 r1_key_holder[FT_R1KH_ID_LEN]; + u32 r0_key_lifetime; /* PMK-R0 lifetime seconds */ + int rkh_pos_timeout; + int rkh_neg_timeout; + int rkh_pull_timeout; /* ms */ + int rkh_pull_retries; + u32 reassociation_deadline; + struct ft_remote_r0kh *r0kh_list; + struct ft_remote_r1kh *r1kh_list; + int pmk_r1_push; + int ft_over_ds; + int ft_psk_generate_local; + int r1_max_key_lifetime; +#endif /* CONFIG_IEEE80211R_AP */ + +#ifdef CONFIG_FULL_HOSTAPD + char *ctrl_interface; /* directory for UNIX domain sockets */ +#ifndef CONFIG_NATIVE_WINDOWS + int ctrl_interface_gid; +#endif /* CONFIG_NATIVE_WINDOWS */ + int ctrl_interface_gid_set; +#endif + + int use_pae_group_addr; /* Whether to send EAPOL frames to PAE group + * address instead of individual address + * (for driver_wired.c). + */ + + int ap_max_inactivity; + int ignore_broadcast_ssid; + int no_probe_resp_if_max_sta; + + int wmm_enabled; + int wmm_uapsd; + + struct hostapd_vlan *vlan; + + macaddr bssid; + + /* + * Maximum listen interval that STAs can use when associating with this + * BSS. If a STA tries to use larger value, the association will be + * denied with status code 51. + */ + u16 max_listen_interval; + + int disable_pmksa_caching; + int okc; /* Opportunistic Key Caching */ + + int wps_state; + int pbc_in_m1; + char *server_id; + +#define P2P_ENABLED BIT(0) +#define P2P_GROUP_OWNER BIT(1) +#define P2P_GROUP_FORMATION BIT(2) +#define P2P_MANAGE BIT(3) +#define P2P_ALLOW_CROSS_CONNECTION BIT(4) + int p2p; +#ifdef CONFIG_P2P + u8 ip_addr_go[4]; + u8 ip_addr_mask[4]; + u8 ip_addr_start[4]; + u8 ip_addr_end[4]; +#endif /* CONFIG_P2P */ + + int disassoc_low_ack; + int skip_inactivity_poll; + +#ifdef CONFIG_TDLS +#define TDLS_PROHIBIT BIT(0) +#define TDLS_PROHIBIT_CHAN_SWITCH BIT(1) + int tdls; +#endif + + int disable_11n; + int disable_11ac; + +#ifdef CONFIG_FULL_HOSTAPD + /* IEEE 802.11v */ + int time_advertisement; + char *time_zone; + int wnm_sleep_mode; + int wnm_sleep_mode_no_keys; + int bss_transition; +#endif + +#ifdef CONFIG_GAS + u16 gas_comeback_delay; + size_t gas_frag_limit; + int gas_address3; +#endif + + u8 qos_map_set[16 + 2 * 21]; + unsigned int qos_map_set_len; + + int osen; + int proxy_arp; + int na_mcast_to_ucast; + +#ifdef CONFIG_WPS + u8 wps_rf_bands; /* RF bands for WPS (WPS_RF_*) */ +#endif + +#ifdef CONFIG_RADIUS_TEST + char *dump_msk_file; +#endif /* CONFIG_RADIUS_TEST */ + + struct wpabuf *vendor_elements; + struct wpabuf *assocresp_elements; + +#ifdef CONFIG_SAE_AP + unsigned int sae_anti_clogging_threshold; + unsigned int sae_sync; + int sae_require_mfp; + int *sae_groups; + struct sae_password_entry *sae_passwords; +#endif + +#ifdef CONFIG_FULL_HOSTAPD + char *wowlan_triggers; /* Wake-on-WLAN triggers */ +#endif + +#define MESH_ENABLED BIT(0) + int mesh; + +#ifdef CONFIG_FULL_HOSTAPD + u8 radio_measurements[RRM_CAPABILITIES_IE_LEN]; +#endif +#ifdef CONFIG_IEEE80211AC + int vendor_vht; + int use_sta_nsts; +#endif + + char *no_probe_resp_if_seen_on; + char *no_auth_if_seen_on; + +#ifdef CONFIG_FULL_HOSTAPD + int pbss; +#endif + +#ifdef CONFIG_MBO + int mbo_enabled; + /** + * oce - Enable OCE in AP and/or STA-CFON mode + * - BIT(0) is Reserved + * - Set BIT(1) to enable OCE in STA-CFON mode + * - Set BIT(2) to enable OCE in AP mode + */ + unsigned int oce; + int mbo_cell_data_conn_pref; +#endif /* CONFIG_MBO */ + + int ftm_responder; + int ftm_initiator; + int multicast_to_unicast; + + int broadcast_deauth; + +#ifdef CONFIG_DPP + char *dpp_connector; + struct wpabuf *dpp_netaccesskey; + unsigned int dpp_netaccesskey_expiry; + struct wpabuf *dpp_csign; +#ifdef CONFIG_DPP2 + struct dpp_controller_conf *dpp_controller; +#endif /* CONFIG_DPP2 */ +#endif /* CONFIG_DPP */ + +#ifdef CONFIG_OWE + macaddr owe_transition_bssid; + u8 owe_transition_ssid[SSID_MAX_LEN]; + size_t owe_transition_ssid_len; + char owe_transition_ifname[IFNAMSIZ + 1]; + int *owe_groups; +#endif /* CONFIG_OWE */ + + u8 send_probe_response; + + int coloc_intf_reporting; + +#ifdef CONFIG_FULL_HOSTAPD +#define BACKHAUL_BSS 1 +#define FRONTHAUL_BSS 2 + int multi_ap; /* bitmap of BACKHAUL_BSS, FRONTHAUL_BSS */ +#endif +}; + +/** + * struct he_phy_capabilities_info - HE PHY capabilities + */ +struct he_phy_capabilities_info { + Boolean he_su_beamformer; + Boolean he_su_beamformee; + Boolean he_mu_beamformer; +}; + +/** + * struct he_operation - HE operation + */ +struct he_operation { + u8 he_bss_color; + u8 he_default_pe_duration; + u8 he_twt_required; + u16 he_rts_threshold; + u16 he_basic_mcs_nss_set; +}; + +/** + * struct spatial_reuse - Spatial reuse + */ +struct spatial_reuse { + u8 sr_control; + u8 non_srg_obss_pd_max_offset; + u8 srg_obss_pd_min_offset; + u8 srg_obss_pd_max_offset; + u8 srg_obss_color_bitmap; + u8 srg_obss_color_partial_bitmap; +}; + +/** + * struct hostapd_config - Per-radio interface configuration + */ +struct hostapd_config { + struct hostapd_bss_config **bss, *last_bss; + size_t num_bss; + + u16 beacon_int; + int rts_threshold; + int fragm_threshold; + u8 channel; + u8 acs; + struct wpa_freq_range_list acs_ch_list; + int acs_exclude_dfs; + enum hostapd_hw_mode hw_mode; /* HOSTAPD_MODE_IEEE80211A, .. */ + enum { + LONG_PREAMBLE = 0, + SHORT_PREAMBLE = 1 + } preamble; + + int *supported_rates; + int *basic_rates; + unsigned int beacon_rate; + enum beacon_rate_type rate_type; + + const struct wpa_driver_ops *driver; + char *driver_params; + + int ap_table_max_size; + int ap_table_expiration_time; + + unsigned int track_sta_max_num; + unsigned int track_sta_max_age; + + char country[3]; /* first two octets: country code as described in + * ISO/IEC 3166-1. Third octet: + * ' ' (ascii 32): all environments + * 'O': Outdoor environemnt only + * 'I': Indoor environment only + * 'X': Used with noncountry entity ("XXX") + * 0x00..0x31: identifying IEEE 802.11 standard + * Annex E table (0x04 = global table) + */ + + int ieee80211d; + + int ieee80211h; /* DFS */ + + /* + * Local power constraint is an octet encoded as an unsigned integer in + * units of decibels. Invalid value -1 indicates that Power Constraint + * element will not be added. + */ + int local_pwr_constraint; + + /* Control Spectrum Management bit */ + int spectrum_mgmt_required; + + struct hostapd_tx_queue_params tx_queue[NUM_TX_QUEUES]; + + /* + * WMM AC parameters, in same order as 802.1D, i.e. + * 0 = BE (best effort) + * 1 = BK (background) + * 2 = VI (video) + * 3 = VO (voice) + */ + struct hostapd_wmm_ac_params wmm_ac_params[4]; + + int ht_op_mode_fixed; + u16 ht_capab; + int ieee80211n; + int secondary_channel; + int no_pri_sec_switch; + int require_ht; + int obss_interval; + u32 vht_capab; + int ieee80211ac; + int require_vht; + u8 vht_oper_chwidth; + u8 vht_oper_centr_freq_seg0_idx; + u8 vht_oper_centr_freq_seg1_idx; + u8 ht40_plus_minus_allowed; + + /* Use driver-generated interface addresses when adding multiple BSSs */ + u8 use_driver_iface_addr; + +#ifdef CONFIG_FST + struct fst_iface_cfg fst_cfg; +#endif /* CONFIG_FST */ + +#ifdef CONFIG_P2P + u8 p2p_go_ctwindow; +#endif /* CONFIG_P2P */ + +#ifdef CONFIG_TESTING_OPTIONS + double ignore_probe_probability; + double ignore_auth_probability; + double ignore_assoc_probability; + double ignore_reassoc_probability; + double corrupt_gtk_rekey_mic_probability; + int ecsa_ie_only; +#endif /* CONFIG_TESTING_OPTIONS */ + +#ifdef CONFIG_ACS + unsigned int acs_num_scans; + struct acs_bias { + int channel; + double bias; + } *acs_chan_bias; + unsigned int num_acs_chan_bias; +#endif /* CONFIG_ACS */ + +#ifdef CONFIG_FULL_HOSTAPD + struct wpabuf *lci; + struct wpabuf *civic; + int stationary_ap; +#endif + + int ieee80211ax; +#ifdef CONFIG_IEEE80211AX + struct he_phy_capabilities_info he_phy_capab; + struct he_operation he_op; + struct ieee80211_he_mu_edca_parameter_set he_mu_edca; + struct spatial_reuse spr; + u8 he_oper_chwidth; + u8 he_oper_centr_freq_seg0_idx; + u8 he_oper_centr_freq_seg1_idx; +#endif /* CONFIG_IEEE80211AX */ + + /* VHT enable/disable config from CHAN_SWITCH */ +#define CH_SWITCH_VHT_ENABLED BIT(0) +#define CH_SWITCH_VHT_DISABLED BIT(1) + unsigned int ch_switch_vht_config; + + int rssi_reject_assoc_rssi; + int rssi_reject_assoc_timeout; +}; + + +static inline u8 hostapd_get_oper_chwidth(struct hostapd_config *conf) +{ +#ifdef CONFIG_IEEE80211AX + if (conf->ieee80211ax) + return conf->he_oper_chwidth; +#endif /* CONFIG_IEEE80211AX */ + return conf->vht_oper_chwidth; +} + +static inline void +hostapd_set_oper_chwidth(struct hostapd_config *conf, u8 oper_chwidth) +{ +#ifdef CONFIG_IEEE80211AX + if (conf->ieee80211ax) + conf->he_oper_chwidth = oper_chwidth; +#endif /* CONFIG_IEEE80211AX */ + conf->vht_oper_chwidth = oper_chwidth; +} + +static inline u8 +hostapd_get_oper_centr_freq_seg0_idx(struct hostapd_config *conf) +{ +#ifdef CONFIG_IEEE80211AX + if (conf->ieee80211ax) + return conf->he_oper_centr_freq_seg0_idx; +#endif /* CONFIG_IEEE80211AX */ + return conf->vht_oper_centr_freq_seg0_idx; +} + +static inline void +hostapd_set_oper_centr_freq_seg0_idx(struct hostapd_config *conf, + u8 oper_centr_freq_seg0_idx) +{ +#ifdef CONFIG_IEEE80211AX + if (conf->ieee80211ax) + conf->he_oper_centr_freq_seg0_idx = oper_centr_freq_seg0_idx; +#endif /* CONFIG_IEEE80211AX */ + conf->vht_oper_centr_freq_seg0_idx = oper_centr_freq_seg0_idx; +} + +static inline u8 +hostapd_get_oper_centr_freq_seg1_idx(struct hostapd_config *conf) +{ +#ifdef CONFIG_IEEE80211AX + if (conf->ieee80211ax) + return conf->he_oper_centr_freq_seg1_idx; +#endif /* CONFIG_IEEE80211AX */ + return conf->vht_oper_centr_freq_seg1_idx; +} + +static inline void +hostapd_set_oper_centr_freq_seg1_idx(struct hostapd_config *conf, + u8 oper_centr_freq_seg1_idx) +{ +#ifdef CONFIG_IEEE80211AX + if (conf->ieee80211ax) + conf->he_oper_centr_freq_seg1_idx = oper_centr_freq_seg1_idx; +#endif /* CONFIG_IEEE80211AX */ + conf->vht_oper_centr_freq_seg1_idx = oper_centr_freq_seg1_idx; +} + + +int hostapd_mac_comp(const void *a, const void *b); +struct hostapd_config * hostapd_config_defaults(void); +void hostapd_config_defaults_bss(struct hostapd_bss_config *bss); +void hostapd_config_free_radius_attr(struct hostapd_radius_attr *attr); +void hostapd_config_free_eap_user(struct hostapd_eap_user *user); +void hostapd_config_free_eap_users(struct hostapd_eap_user *user); +void hostapd_config_clear_wpa_psk(struct hostapd_wpa_psk **p); +void hostapd_config_free_bss(struct hostapd_bss_config *conf); +void hostapd_config_free(struct hostapd_config *conf); +int hostapd_maclist_found(struct mac_acl_entry *list, int num_entries, + const u8 *addr, struct vlan_description *vlan_id); +int hostapd_rate_found(int *list, int rate); +const u8 * hostapd_get_psk(const struct hostapd_bss_config *conf, + const u8 *addr, const u8 *p2p_dev_addr, + const u8 *prev_psk, int *vlan_id); +int hostapd_setup_wpa_psk(struct hostapd_bss_config *conf); +int hostapd_vlan_valid(struct hostapd_vlan *vlan, + struct vlan_description *vlan_desc); +const char * hostapd_get_vlan_id_ifname(struct hostapd_vlan *vlan, + int vlan_id); +struct hostapd_radius_attr * +hostapd_config_get_radius_attr(struct hostapd_radius_attr *attr, u8 type); +int hostapd_config_check(struct hostapd_config *conf, int full_config); +void hostapd_set_security_params(struct hostapd_bss_config *bss, + int full_config); + +#endif /* HOSTAPD_CONFIG_H */ diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ap_drv_ops.c b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ap_drv_ops.c new file mode 100755 index 0000000..0d82a6a --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ap_drv_ops.c @@ -0,0 +1,939 @@ +/* + * hostapd - Driver operations + * Copyright (c) 2009-2010, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "common/ieee802_11_defs.h" +#include "common/hw_features_common.h" +#include "wps/wps.h" +#include "ap/hostapd.h" +#include "ieee802_11.h" +#include "ap/sta_info.h" +#include "ap_config.h" +#include "p2p_hostapd.h" +#include "wpa_auth.h" +#include "ap_drv_ops.h" + + +u32 hostapd_sta_flags_to_drv(u32 flags) +{ + int res = 0; + if (flags & WLAN_STA_AUTHORIZED) + res |= WPA_STA_AUTHORIZED; + if (flags & WLAN_STA_WMM) + res |= WPA_STA_WMM; + if (flags & WLAN_STA_SHORT_PREAMBLE) + res |= WPA_STA_SHORT_PREAMBLE; + if (flags & WLAN_STA_MFP) + res |= WPA_STA_MFP; + if (flags & WLAN_STA_AUTH) + res |= WPA_STA_AUTHENTICATED; + if (flags & WLAN_STA_ASSOC) + res |= WPA_STA_ASSOCIATED; + return res; +} + + +static int add_buf(struct wpabuf **dst, const struct wpabuf *src) +{ + if (!src) + return 0; + if (wpabuf_resize(dst, wpabuf_len(src)) != 0) + return -1; + wpabuf_put_buf(*dst, src); + return 0; +} + + +static int add_buf_data(struct wpabuf **dst, const u8 *data, size_t len) +{ + if (!data || !len) + return 0; + if (wpabuf_resize(dst, len) != 0) + return -1; + wpabuf_put_data(*dst, data, len); + return 0; +} + + +int hostapd_build_ap_extra_ies(struct hostapd_data *hapd, + struct wpabuf **beacon_ret, + struct wpabuf **proberesp_ret, + struct wpabuf **assocresp_ret) +{ +#ifdef CONFIG_FULL_HOSTAPD + struct wpabuf *beacon = NULL, *proberesp = NULL, *assocresp = NULL; + u8 buf[200], *pos; + + *beacon_ret = *proberesp_ret = *assocresp_ret = NULL; + + pos = buf; + pos = hostapd_eid_time_adv(hapd, pos); + if (add_buf_data(&beacon, buf, pos - buf) < 0) + goto fail; + pos = hostapd_eid_time_zone(hapd, pos); + if (add_buf_data(&proberesp, buf, pos - buf) < 0) + goto fail; + + pos = buf; + pos = hostapd_eid_ext_capab(hapd, pos); + if (add_buf_data(&assocresp, buf, pos - buf) < 0) + goto fail; + pos = hostapd_eid_interworking(hapd, pos); + pos = hostapd_eid_adv_proto(hapd, pos); + pos = hostapd_eid_roaming_consortium(hapd, pos); + if (add_buf_data(&beacon, buf, pos - buf) < 0 || + add_buf_data(&proberesp, buf, pos - buf) < 0) + goto fail; + + +#ifdef CONFIG_P2P + if (add_buf(&beacon, hapd->p2p_beacon_ie) < 0 || + add_buf(&proberesp, hapd->p2p_probe_resp_ie) < 0) + goto fail; +#endif /* CONFIG_P2P */ + +#ifdef CONFIG_P2P_MANAGER + if (hapd->conf->p2p & P2P_MANAGE) { + if (wpabuf_resize(&beacon, 100) == 0) { + u8 *start, *p; + start = wpabuf_put(beacon, 0); + p = hostapd_eid_p2p_manage(hapd, start); + wpabuf_put(beacon, p - start); + } + + if (wpabuf_resize(&proberesp, 100) == 0) { + u8 *start, *p; + start = wpabuf_put(proberesp, 0); + p = hostapd_eid_p2p_manage(hapd, start); + wpabuf_put(proberesp, p - start); + } + } +#endif /* CONFIG_P2P_MANAGER */ + +#ifdef CONFIG_WPS + if (hapd->conf->wps_state) { + struct wpabuf *a = wps_build_assoc_resp_ie(); + add_buf(&assocresp, a); + wpabuf_free(a); + } +#endif /* CONFIG_WPS */ + +#ifdef CONFIG_P2P_MANAGER + if (hapd->conf->p2p & P2P_MANAGE) { + if (wpabuf_resize(&assocresp, 100) == 0) { + u8 *start, *p; + start = wpabuf_put(assocresp, 0); + p = hostapd_eid_p2p_manage(hapd, start); + wpabuf_put(assocresp, p - start); + } + } +#endif /* CONFIG_P2P_MANAGER */ + +#ifdef CONFIG_WIFI_DISPLAY + if (hapd->p2p_group) { + struct wpabuf *a; + a = p2p_group_assoc_resp_ie(hapd->p2p_group, P2P_SC_SUCCESS); + add_buf(&assocresp, a); + wpabuf_free(a); + } +#endif /* CONFIG_WIFI_DISPLAY */ + +#ifdef CONFIG_HS20 + pos = hostapd_eid_hs20_indication(hapd, buf); + if (add_buf_data(&beacon, buf, pos - buf) < 0 || + add_buf_data(&proberesp, buf, pos - buf) < 0) + goto fail; + + pos = hostapd_eid_osen(hapd, buf); + if (add_buf_data(&beacon, buf, pos - buf) < 0 || + add_buf_data(&proberesp, buf, pos - buf) < 0) + goto fail; +#endif /* CONFIG_HS20 */ + +#ifdef CONFIG_MBO + if (hapd->conf->mbo_enabled || + OCE_STA_CFON_ENABLED(hapd) || OCE_AP_ENABLED(hapd)) { + pos = hostapd_eid_mbo(hapd, buf, sizeof(buf)); + if (add_buf_data(&beacon, buf, pos - buf) < 0 || + add_buf_data(&proberesp, buf, pos - buf) < 0 || + add_buf_data(&assocresp, buf, pos - buf) < 0) + goto fail; + } +#endif /* CONFIG_MBO */ + +#ifdef CONFIG_OWE + pos = hostapd_eid_owe_trans(hapd, buf, sizeof(buf)); + if (add_buf_data(&beacon, buf, pos - buf) < 0 || + add_buf_data(&proberesp, buf, pos - buf) < 0) + goto fail; +#endif /* CONFIG_OWE */ + + add_buf(&beacon, hapd->conf->vendor_elements); + add_buf(&proberesp, hapd->conf->vendor_elements); + add_buf(&assocresp, hapd->conf->assocresp_elements); + + *beacon_ret = beacon; + *proberesp_ret = proberesp; + *assocresp_ret = assocresp; + + return 0; + +fail: + wpabuf_free(beacon); + wpabuf_free(proberesp); + wpabuf_free(assocresp); + return -1; + +#else + *beacon_ret = *proberesp_ret = *assocresp_ret = NULL; + + return 0; +#endif +} + + +void hostapd_free_ap_extra_ies(struct hostapd_data *hapd, + struct wpabuf *beacon, + struct wpabuf *proberesp, + struct wpabuf *assocresp) +{ + wpabuf_free(beacon); + wpabuf_free(proberesp); + wpabuf_free(assocresp); +} + + +int hostapd_reset_ap_wps_ie(struct hostapd_data *hapd) +{ + if (hapd->driver == NULL || hapd->driver->set_ap_wps_ie == NULL) + return 0; + + return hapd->driver->set_ap_wps_ie(hapd->drv_priv, NULL, NULL, NULL); +} + + +int hostapd_set_ap_wps_ie(struct hostapd_data *hapd) +{ + struct wpabuf *beacon = 0, *proberesp = 0, *assocresp = 0; + int ret; + + if (hapd->driver == NULL || hapd->driver->set_ap_wps_ie == NULL) + return 0; + + if (hostapd_build_ap_extra_ies(hapd, &beacon, &proberesp, &assocresp) < 0) + return -1; + + ret = hapd->driver->set_ap_wps_ie(hapd->drv_priv, beacon, proberesp, + assocresp); + + hostapd_free_ap_extra_ies(hapd, beacon, proberesp, assocresp); + + return ret; +} + + +int hostapd_set_authorized(struct hostapd_data *hapd, + struct sta_info *sta, int authorized) +{ + if (authorized) { + return hostapd_sta_set_flags(hapd, sta->addr, + hostapd_sta_flags_to_drv( + sta->flags), + WPA_STA_AUTHORIZED, ~0); + } + + return hostapd_sta_set_flags(hapd, sta->addr, + hostapd_sta_flags_to_drv(sta->flags), + 0, ~WPA_STA_AUTHORIZED); +} + + +int hostapd_set_sta_flags(struct hostapd_data *hapd, struct sta_info *sta) +{ + int set_flags, total_flags, flags_and, flags_or; + total_flags = hostapd_sta_flags_to_drv(sta->flags); + set_flags = WPA_STA_SHORT_PREAMBLE | WPA_STA_WMM | WPA_STA_MFP; + if (((!hapd->conf->ieee802_1x && !hapd->conf->wpa) || + sta->auth_alg == WLAN_AUTH_FT) && + sta->flags & WLAN_STA_AUTHORIZED) + set_flags |= WPA_STA_AUTHORIZED; + flags_or = total_flags & set_flags; + flags_and = total_flags | ~set_flags; + return hostapd_sta_set_flags(hapd, sta->addr, total_flags, + flags_or, flags_and); +} + + +int hostapd_set_drv_ieee8021x(struct hostapd_data *hapd, const char *ifname, + int enabled) +{ + struct wpa_bss_params params; + os_memset(¶ms, 0, sizeof(params)); + params.ifname = ifname; + params.enabled = enabled; + if (enabled) { + params.wpa = hapd->conf->wpa; + params.ieee802_1x = hapd->conf->ieee802_1x; + params.wpa_group = hapd->conf->wpa_group; + if ((hapd->conf->wpa & (WPA_PROTO_WPA | WPA_PROTO_RSN)) == + (WPA_PROTO_WPA | WPA_PROTO_RSN)) + params.wpa_pairwise = hapd->conf->wpa_pairwise | + hapd->conf->rsn_pairwise; + else if (hapd->conf->wpa & WPA_PROTO_RSN) + params.wpa_pairwise = hapd->conf->rsn_pairwise; + else if (hapd->conf->wpa & WPA_PROTO_WPA) + params.wpa_pairwise = hapd->conf->wpa_pairwise; + params.wpa_key_mgmt = hapd->conf->wpa_key_mgmt; + params.rsn_preauth = hapd->conf->rsn_preauth; +#ifdef CONFIG_IEEE80211W_AP + params.ieee80211w = hapd->conf->ieee80211w; +#endif /* CONFIG_IEEE80211W_AP */ + } + return hostapd_set_ieee8021x(hapd, ¶ms); +} + +#ifdef CONFIG_FULL_HOSTAPD +int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname) +{ + char force_ifname[IFNAMSIZ]; + u8 if_addr[ETH_ALEN]; + return hostapd_if_add(hapd, WPA_IF_AP_VLAN, ifname, hapd->own_addr, + NULL, NULL, force_ifname, if_addr, NULL, 0); +} + + +int hostapd_vlan_if_remove(struct hostapd_data *hapd, const char *ifname) +{ + return hostapd_if_remove(hapd, WPA_IF_AP_VLAN, ifname); +} + + +int hostapd_set_wds_sta(struct hostapd_data *hapd, char *ifname_wds, + const u8 *addr, int aid, int val) +{ + const char *bridge = NULL; + + if (hapd->driver == NULL || hapd->driver->set_wds_sta == NULL) + return -1; + if (hapd->conf->wds_bridge[0]) + bridge = hapd->conf->wds_bridge; + else if (hapd->conf->bridge[0]) + bridge = hapd->conf->bridge; + return hapd->driver->set_wds_sta(hapd->drv_priv, addr, aid, val, + bridge, ifname_wds); +} +#endif + +int hostapd_add_sta_node(struct hostapd_data *hapd, const u8 *addr, + u16 auth_alg) +{ + if (hapd->driver == NULL || hapd->driver->add_sta_node == NULL) + return 0; + return hapd->driver->add_sta_node(hapd->drv_priv, addr, auth_alg); +} + + +int hostapd_sta_auth(struct hostapd_data *hapd, const u8 *addr, + u16 seq, u16 status, const u8 *ie, size_t len) +{ + struct wpa_driver_sta_auth_params params; + if (hapd->driver == NULL || hapd->driver->sta_auth == NULL) + return 0; + + os_memset(¶ms, 0, sizeof(params)); + + + params.own_addr = hapd->own_addr; + params.addr = addr; + params.seq = seq; + params.status = status; + params.ie = ie; + params.len = len; + + return hapd->driver->sta_auth(hapd->drv_priv, ¶ms); +} + + +int hostapd_sta_assoc(struct hostapd_data *hapd, const u8 *addr, + int reassoc, u16 status, const u8 *ie, size_t len) +{ + if (hapd->driver == NULL || hapd->driver->sta_assoc == NULL) + return 0; + return hapd->driver->sta_assoc(hapd->drv_priv, hapd->own_addr, addr, + reassoc, status, ie, len); +} + + +int hostapd_sta_add(struct hostapd_data *hapd, + const u8 *addr, u16 aid, u16 capability, + const u8 *supp_rates, size_t supp_rates_len, + u16 listen_interval, + const struct ieee80211_ht_capabilities *ht_capab, + const struct ieee80211_vht_capabilities *vht_capab, + const struct ieee80211_he_capabilities *he_capab, + size_t he_capab_len, + u32 flags, u8 qosinfo, u8 vht_opmode, int supp_p2p_ps, + int set) +{ + struct hostapd_sta_add_params params; + + if (hapd->driver == NULL) + return 0; + if (hapd->driver->sta_add == NULL) + return 0; + + os_memset(¶ms, 0, sizeof(params)); + params.addr = addr; + params.aid = aid; + params.capability = capability; + params.supp_rates = supp_rates; + params.supp_rates_len = supp_rates_len; + params.listen_interval = listen_interval; + params.ht_capabilities = ht_capab; + params.vht_capabilities = vht_capab; + params.he_capab = he_capab; + params.he_capab_len = he_capab_len; + params.vht_opmode_enabled = !!(flags & WLAN_STA_VHT_OPMODE_ENABLED); + params.vht_opmode = vht_opmode; + params.flags = hostapd_sta_flags_to_drv(flags); + params.qosinfo = qosinfo; + params.support_p2p_ps = supp_p2p_ps; + params.set = set; + return hapd->driver->sta_add(hapd->drv_priv, ¶ms); +} + + +int hostapd_add_tspec(struct hostapd_data *hapd, const u8 *addr, + u8 *tspec_ie, size_t tspec_ielen) +{ + if (hapd->driver == NULL || hapd->driver->add_tspec == NULL) + return 0; + return hapd->driver->add_tspec(hapd->drv_priv, addr, tspec_ie, + tspec_ielen); +} + + +int hostapd_set_privacy(struct hostapd_data *hapd, int enabled) +{ + if (hapd->driver == NULL || hapd->driver->set_privacy == NULL) + return 0; + return hapd->driver->set_privacy(hapd->drv_priv, enabled); +} + + +int hostapd_set_generic_elem(struct hostapd_data *hapd, const u8 *elem, + size_t elem_len) +{ + if (hapd->driver == NULL || hapd->driver->set_generic_elem == NULL) + return 0; + return hapd->driver->set_generic_elem(hapd->drv_priv, elem, elem_len); +} + + +int hostapd_get_ssid(struct hostapd_data *hapd, u8 *buf, size_t len) +{ + if (hapd->driver == NULL || hapd->driver->hapd_get_ssid == NULL) + return 0; + return hapd->driver->hapd_get_ssid(hapd->drv_priv, buf, len); +} + + +int hostapd_set_ssid(struct hostapd_data *hapd, const u8 *buf, size_t len) +{ + if (hapd->driver == NULL || hapd->driver->hapd_set_ssid == NULL) + return 0; + return hapd->driver->hapd_set_ssid(hapd->drv_priv, buf, len); +} + + +int hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type, + const char *ifname, const u8 *addr, void *bss_ctx, + void **drv_priv, char *force_ifname, u8 *if_addr, + const char *bridge, int use_existing) +{ + if (hapd->driver == NULL || hapd->driver->if_add == NULL) + return -1; + return hapd->driver->if_add(hapd->drv_priv, type, ifname, addr, + bss_ctx, drv_priv, force_ifname, if_addr, + bridge, use_existing, 1); +} + + +int hostapd_if_remove(struct hostapd_data *hapd, enum wpa_driver_if_type type, + const char *ifname) +{ + if (hapd->driver == NULL || hapd->drv_priv == NULL || + hapd->driver->if_remove == NULL) + return -1; + return hapd->driver->if_remove(hapd->drv_priv, type, ifname); +} + + +int hostapd_set_ieee8021x(struct hostapd_data *hapd, + struct wpa_bss_params *params) +{ + if (hapd->driver == NULL || hapd->driver->set_ieee8021x == NULL) + return 0; + return hapd->driver->set_ieee8021x(hapd->drv_priv, params); +} + + +int hostapd_get_seqnum(const char *ifname, struct hostapd_data *hapd, + const u8 *addr, int idx, u8 *seq) +{ + if (hapd->driver == NULL || hapd->driver->get_seqnum == NULL) + return 0; + return hapd->driver->get_seqnum(ifname, hapd->drv_priv, addr, idx, + seq); +} + + +int hostapd_flush(struct hostapd_data *hapd) +{ + if (hapd->driver == NULL || hapd->driver->flush == NULL) + return 0; + return hapd->driver->flush(hapd->drv_priv); +} + + +int hostapd_set_freq(struct hostapd_data *hapd, enum hostapd_hw_mode mode, + int freq, int channel, int ht_enabled, int vht_enabled, + int he_enabled, + int sec_channel_offset, int oper_chwidth, + int center_segment0, int center_segment1) +{ + struct hostapd_freq_params data; + struct hostapd_hw_modes *cmode = hapd->iface->current_mode; + + if (hostapd_set_freq_params(&data, mode, freq, channel, ht_enabled, + vht_enabled, he_enabled, sec_channel_offset, + oper_chwidth, + center_segment0, center_segment1, + cmode ? cmode->vht_capab : 0, +#ifdef CONFIG_IEEE80211AX + cmode ? &cmode->he_capab[IEEE80211_MODE_AP] : +#endif + NULL)) + return -1; + + if (hapd->driver == NULL) + return 0; + if (hapd->driver->set_freq == NULL) + return 0; + return hapd->driver->set_freq(hapd->drv_priv, &data); +} + +int hostapd_set_rts(struct hostapd_data *hapd, int rts) +{ + if (hapd->driver == NULL || hapd->driver->set_rts == NULL) + return 0; + return hapd->driver->set_rts(hapd->drv_priv, rts); +} + + +int hostapd_set_frag(struct hostapd_data *hapd, int frag) +{ + if (hapd->driver == NULL || hapd->driver->set_frag == NULL) + return 0; + return hapd->driver->set_frag(hapd->drv_priv, frag); +} + + +int hostapd_sta_set_flags(struct hostapd_data *hapd, u8 *addr, + int total_flags, int flags_or, int flags_and) +{ + if (hapd->driver == NULL || hapd->driver->sta_set_flags == NULL) + return 0; + return hapd->driver->sta_set_flags(hapd->drv_priv, addr, total_flags, + flags_or, flags_and); +} + + +int hostapd_sta_set_airtime_weight(struct hostapd_data *hapd, const u8 *addr, + unsigned int weight) +{ + if (!hapd->driver || !hapd->driver->sta_set_airtime_weight) + return 0; + return hapd->driver->sta_set_airtime_weight(hapd->drv_priv, addr, + weight); +} + + +int hostapd_set_country(struct hostapd_data *hapd, const char *country) +{ + if (hapd->driver == NULL || + hapd->driver->set_country == NULL) + return 0; + return hapd->driver->set_country(hapd->drv_priv, country); +} + + +int hostapd_set_tx_queue_params(struct hostapd_data *hapd, int queue, int aifs, + int cw_min, int cw_max, int burst_time) +{ + if (hapd->driver == NULL || hapd->driver->set_tx_queue_params == NULL) + return 0; + return hapd->driver->set_tx_queue_params(hapd->drv_priv, queue, aifs, + cw_min, cw_max, burst_time); +} + + +struct hostapd_hw_modes * +hostapd_get_hw_feature_data(struct hostapd_data *hapd, u16 *num_modes, + u16 *flags, u8 *dfs_domain) +{ + if (hapd->driver == NULL || + hapd->driver->get_hw_feature_data == NULL) + return NULL; + return hapd->driver->get_hw_feature_data(hapd->drv_priv, num_modes, + flags, dfs_domain); +} + + +int hostapd_driver_commit(struct hostapd_data *hapd) +{ + if (hapd->driver == NULL || hapd->driver->commit == NULL) + return 0; + return hapd->driver->commit(hapd->drv_priv); +} + + +int hostapd_drv_none(struct hostapd_data *hapd) +{ + return hapd->driver && os_strcmp(hapd->driver->name, "none") == 0; +} + + +int hostapd_driver_scan(struct hostapd_data *hapd, + struct wpa_driver_scan_params *params) +{ + if (hapd->driver && hapd->driver->scan2) + return hapd->driver->scan2(hapd->drv_priv, params); + return -1; +} + + +struct wpa_scan_results * hostapd_driver_get_scan_results( + struct hostapd_data *hapd) +{ + if (hapd->driver && hapd->driver->get_scan_results2) + return hapd->driver->get_scan_results2(hapd->drv_priv); + return NULL; +} + + +int hostapd_driver_set_noa(struct hostapd_data *hapd, u8 count, int start, + int duration) +{ + if (hapd->driver && hapd->driver->set_noa) + return hapd->driver->set_noa(hapd->drv_priv, count, start, + duration); + return -1; +} + + +int hostapd_drv_set_key(const char *ifname, struct hostapd_data *hapd, + enum wpa_alg alg, const u8 *addr, + int key_idx, int set_tx, + const u8 *seq, size_t seq_len, + const u8 *key, size_t key_len) +{ + if (hapd->driver == NULL || hapd->driver->set_key == NULL) + return 0; + return hapd->driver->set_key(ifname, hapd->drv_priv, alg, addr, + key_idx, set_tx, seq, seq_len, key, + key_len); +} + + +int hostapd_drv_send_mlme(struct hostapd_data *hapd, + const void *msg, size_t len, int noack) +{ + if (!hapd->driver || !hapd->driver->send_mlme || !hapd->drv_priv) + return 0; + return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack, 0, + NULL, 0); +} + + +int hostapd_drv_send_mlme_csa(struct hostapd_data *hapd, + const void *msg, size_t len, int noack, + const u16 *csa_offs, size_t csa_offs_len) +{ + if (hapd->driver == NULL || hapd->driver->send_mlme == NULL) + return 0; + return hapd->driver->send_mlme(hapd->drv_priv, msg, len, noack, 0, + csa_offs, csa_offs_len); +} + + +int hostapd_drv_sta_deauth(struct hostapd_data *hapd, + const u8 *addr, int reason) +{ + if (!hapd->driver || !hapd->driver->sta_deauth || !hapd->drv_priv) + return 0; + return hapd->driver->sta_deauth(hapd->drv_priv, hapd->own_addr, addr, + reason); +} + + +int hostapd_drv_sta_disassoc(struct hostapd_data *hapd, + const u8 *addr, int reason) +{ + if (!hapd->driver || !hapd->driver->sta_disassoc || !hapd->drv_priv) + return 0; + return hapd->driver->sta_disassoc(hapd->drv_priv, hapd->own_addr, addr, + reason); +} + + +int hostapd_drv_wnm_oper(struct hostapd_data *hapd, enum wnm_oper oper, + const u8 *peer, u8 *buf, u16 *buf_len) +{ + if (hapd->driver == NULL || hapd->driver->wnm_oper == NULL) + return -1; + return hapd->driver->wnm_oper(hapd->drv_priv, oper, peer, buf, + buf_len); +} + + +int hostapd_drv_send_action(struct hostapd_data *hapd, unsigned int freq, + unsigned int wait, const u8 *dst, const u8 *data, + size_t len) +{ + const u8 *bssid; + const u8 wildcard_bssid[ETH_ALEN] = { + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + }; + + if (!hapd->driver || !hapd->driver->send_action || !hapd->drv_priv) + return 0; + bssid = hapd->own_addr; + if (!is_multicast_ether_addr(dst) && + len > 0 && data[0] == WLAN_ACTION_PUBLIC) { + struct sta_info *sta; + + /* + * Public Action frames to a STA that is not a member of the BSS + * shall use wildcard BSSID value. + */ + sta = ap_get_sta(hapd, dst); + if (!sta || !(sta->flags & WLAN_STA_ASSOC)) + bssid = wildcard_bssid; + } else if (is_broadcast_ether_addr(dst) && + len > 0 && data[0] == WLAN_ACTION_PUBLIC) { + /* + * The only current use case of Public Action frames with + * broadcast destination address is DPP PKEX. That case is + * directing all devices and not just the STAs within the BSS, + * so have to use the wildcard BSSID value. + */ + bssid = wildcard_bssid; + } + return hapd->driver->send_action(hapd->drv_priv, freq, wait, dst, + hapd->own_addr, bssid, data, len, 0); +} + + +int hostapd_drv_send_action_addr3_ap(struct hostapd_data *hapd, + unsigned int freq, + unsigned int wait, const u8 *dst, + const u8 *data, size_t len) +{ + if (hapd->driver == NULL || hapd->driver->send_action == NULL) + return 0; + return hapd->driver->send_action(hapd->drv_priv, freq, wait, dst, + hapd->own_addr, hapd->own_addr, data, + len, 0); +} + + +#ifdef CONFIG_FULL_HOSTAPD +int hostapd_start_dfs_cac(struct hostapd_iface *iface, + enum hostapd_hw_mode mode, int freq, + int channel, int ht_enabled, int vht_enabled, + int he_enabled, + int sec_channel_offset, int oper_chwidth, + int center_segment0, int center_segment1) +{ + struct hostapd_data *hapd = iface->bss[0]; + struct hostapd_freq_params data; + int res; + struct hostapd_hw_modes *cmode = iface->current_mode; + + if (!hapd->driver || !hapd->driver->start_dfs_cac || !cmode) + return 0; + + if (!iface->conf->ieee80211h) { + wpa_printf(MSG_ERROR, "Can't start DFS CAC, DFS functionality " + "is not enabled"); + return -1; + } + + if (hostapd_set_freq_params(&data, mode, freq, channel, ht_enabled, + vht_enabled, he_enabled, sec_channel_offset, + oper_chwidth, center_segment0, + center_segment1, + cmode->vht_capab, + &cmode->he_capab[IEEE80211_MODE_AP])) { + wpa_printf(MSG_ERROR, "Can't set freq params"); + return -1; + } + + res = hapd->driver->start_dfs_cac(hapd->drv_priv, &data); + if (!res) { + iface->cac_started = 1; + os_get_reltime(&iface->dfs_cac_start); + } + + return res; +} +#endif + +int hostapd_drv_set_qos_map(struct hostapd_data *hapd, + const u8 *qos_map_set, u8 qos_map_set_len) +{ + if (!hapd->driver || !hapd->driver->set_qos_map || !hapd->drv_priv) + return 0; + return hapd->driver->set_qos_map(hapd->drv_priv, qos_map_set, + qos_map_set_len); +} + + +static void hostapd_get_hw_mode_any_channels(struct hostapd_data *hapd, + struct hostapd_hw_modes *mode, + int acs_ch_list_all, + int **freq_list) +{ + int i; + + for (i = 0; i < mode->num_channels; i++) { + struct hostapd_channel_data *chan = &mode->channels[i]; + + if ((acs_ch_list_all || + freq_range_list_includes(&hapd->iface->conf->acs_ch_list, + chan->chan)) && + !(chan->flag & HOSTAPD_CHAN_DISABLED) && + !(hapd->iface->conf->acs_exclude_dfs && + (chan->flag & HOSTAPD_CHAN_RADAR))) + int_array_add_unique(freq_list, chan->freq); + } +} + + +void hostapd_get_ext_capa(struct hostapd_iface *iface) +{ + struct hostapd_data *hapd = iface->bss[0]; + + if (!hapd->driver || !hapd->driver->get_ext_capab) + return; + + hapd->driver->get_ext_capab(hapd->drv_priv, WPA_IF_AP_BSS, + &iface->extended_capa, + &iface->extended_capa_mask, + &iface->extended_capa_len); +} + + +int hostapd_drv_do_acs(struct hostapd_data *hapd) +{ + struct drv_acs_params params; + int ret, i, acs_ch_list_all = 0; + u8 *channels = NULL; + unsigned int num_channels = 0; + struct hostapd_hw_modes *mode; + int *freq_list = NULL; + + if (hapd->driver == NULL || hapd->driver->do_acs == NULL) + return 0; + + os_memset(¶ms, 0, sizeof(params)); + params.hw_mode = hapd->iface->conf->hw_mode; + + /* + * If no chanlist config parameter is provided, include all enabled + * channels of the selected hw_mode. + */ + if (!hapd->iface->conf->acs_ch_list.num) + acs_ch_list_all = 1; + + mode = hapd->iface->current_mode; + if (mode) { + channels = os_malloc(mode->num_channels); + if (channels == NULL) + return -1; + + for (i = 0; i < mode->num_channels; i++) { + struct hostapd_channel_data *chan = &mode->channels[i]; + if (!acs_ch_list_all && + !freq_range_list_includes( + &hapd->iface->conf->acs_ch_list, + chan->chan)) + continue; + if (hapd->iface->conf->acs_exclude_dfs && + (chan->flag & HOSTAPD_CHAN_RADAR)) + continue; + if (!(chan->flag & HOSTAPD_CHAN_DISABLED)) { + channels[num_channels++] = chan->chan; + int_array_add_unique(&freq_list, chan->freq); + } + } + } else { + for (i = 0; i < hapd->iface->num_hw_features; i++) { + mode = &hapd->iface->hw_features[i]; + hostapd_get_hw_mode_any_channels(hapd, mode, + acs_ch_list_all, + &freq_list); + } + } + + params.ch_list = channels; + params.ch_list_len = num_channels; + params.freq_list = freq_list; + + params.ht_enabled = !!(hapd->iface->conf->ieee80211n); + params.ht40_enabled = !!(hapd->iface->conf->ht_capab & + HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET); + params.vht_enabled = !!(hapd->iface->conf->ieee80211ac); + params.ch_width = 20; + if (hapd->iface->conf->ieee80211n && params.ht40_enabled) + params.ch_width = 40; + +#if defined(CONFIG_IEEE80211AC) || defined(CONFIG_IEEE80211AX) + /* Note: VHT20 is defined by combination of ht_capab & oper_chwidth + */ + if ((hapd->iface->conf->ieee80211ax || + hapd->iface->conf->ieee80211ac) && + params.ht40_enabled) { + u8 oper_chwidth = hostapd_get_oper_chwidth(hapd->iface->conf); + + if (oper_chwidth == CHANWIDTH_80MHZ) + params.ch_width = 80; + else if (oper_chwidth == CHANWIDTH_160MHZ || + oper_chwidth == CHANWIDTH_80P80MHZ) + params.ch_width = 160; + } +#endif + + ret = hapd->driver->do_acs(hapd->drv_priv, ¶ms); + os_free(channels); + + return ret; +} + + +int hostapd_drv_update_dh_ie(struct hostapd_data *hapd, const u8 *peer, + u16 reason_code, const u8 *ie, size_t ielen) +{ + if (!hapd->driver || !hapd->driver->update_dh_ie || !hapd->drv_priv) + return 0; + return hapd->driver->update_dh_ie(hapd->drv_priv, peer, reason_code, + ie, ielen); +} diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ap_drv_ops.h b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ap_drv_ops.h new file mode 100755 index 0000000..c30dbd1 --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ap_drv_ops.h @@ -0,0 +1,386 @@ +/* + * hostapd - Driver operations + * Copyright (c) 2009-2014, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef AP_DRV_OPS +#define AP_DRV_OPS + +#include "errno-base.h" + +enum wpa_driver_if_type; +struct wpa_bss_params; +struct wpa_driver_scan_params; +struct ieee80211_ht_capabilities; +struct ieee80211_vht_capabilities; +struct hostapd_freq_params; + +u32 hostapd_sta_flags_to_drv(u32 flags); +int hostapd_build_ap_extra_ies(struct hostapd_data *hapd, + struct wpabuf **beacon, + struct wpabuf **proberesp, + struct wpabuf **assocresp); +void hostapd_free_ap_extra_ies(struct hostapd_data *hapd, struct wpabuf *beacon, + struct wpabuf *proberesp, + struct wpabuf *assocresp); +int hostapd_reset_ap_wps_ie(struct hostapd_data *hapd); +int hostapd_set_ap_wps_ie(struct hostapd_data *hapd); +int hostapd_set_authorized(struct hostapd_data *hapd, + struct sta_info *sta, int authorized); +int hostapd_set_sta_flags(struct hostapd_data *hapd, struct sta_info *sta); +int hostapd_set_drv_ieee8021x(struct hostapd_data *hapd, const char *ifname, + int enabled); +int hostapd_vlan_if_add(struct hostapd_data *hapd, const char *ifname); +int hostapd_vlan_if_remove(struct hostapd_data *hapd, const char *ifname); +int hostapd_set_wds_sta(struct hostapd_data *hapd, char *ifname_wds, + const u8 *addr, int aid, int val); +int hostapd_sta_add(struct hostapd_data *hapd, + const u8 *addr, u16 aid, u16 capability, + const u8 *supp_rates, size_t supp_rates_len, + u16 listen_interval, + const struct ieee80211_ht_capabilities *ht_capab, + const struct ieee80211_vht_capabilities *vht_capab, + const struct ieee80211_he_capabilities *he_capab, + size_t he_capab_len, + u32 flags, u8 qosinfo, u8 vht_opmode, int supp_p2p_ps, + int set); +int hostapd_set_privacy(struct hostapd_data *hapd, int enabled); +int hostapd_set_generic_elem(struct hostapd_data *hapd, const u8 *elem, + size_t elem_len); +int hostapd_get_ssid(struct hostapd_data *hapd, u8 *buf, size_t len); +int hostapd_set_ssid(struct hostapd_data *hapd, const u8 *buf, size_t len); +int hostapd_if_add(struct hostapd_data *hapd, enum wpa_driver_if_type type, + const char *ifname, const u8 *addr, void *bss_ctx, + void **drv_priv, char *force_ifname, u8 *if_addr, + const char *bridge, int use_existing); +int hostapd_if_remove(struct hostapd_data *hapd, enum wpa_driver_if_type type, + const char *ifname); +int hostapd_set_ieee8021x(struct hostapd_data *hapd, + struct wpa_bss_params *params); +int hostapd_get_seqnum(const char *ifname, struct hostapd_data *hapd, + const u8 *addr, int idx, u8 *seq); +int hostapd_flush(struct hostapd_data *hapd); +int hostapd_set_freq(struct hostapd_data *hapd, enum hostapd_hw_mode mode, + int freq, int channel, int ht_enabled, int vht_enabled, + int he_enabled, int sec_channel_offset, int oper_chwidth, + int center_segment0, int center_segment1); +int hostapd_set_rts(struct hostapd_data *hapd, int rts); +int hostapd_set_frag(struct hostapd_data *hapd, int frag); +int hostapd_sta_set_flags(struct hostapd_data *hapd, u8 *addr, + int total_flags, int flags_or, int flags_and); +int hostapd_sta_set_airtime_weight(struct hostapd_data *hapd, const u8 *addr, + unsigned int weight); +int hostapd_set_country(struct hostapd_data *hapd, const char *country); +int hostapd_set_tx_queue_params(struct hostapd_data *hapd, int queue, int aifs, + int cw_min, int cw_max, int burst_time); +struct hostapd_hw_modes * +hostapd_get_hw_feature_data(struct hostapd_data *hapd, u16 *num_modes, + u16 *flags, u8 *dfs_domain); +int hostapd_driver_commit(struct hostapd_data *hapd); +int hostapd_drv_none(struct hostapd_data *hapd); +int hostapd_driver_scan(struct hostapd_data *hapd, + struct wpa_driver_scan_params *params); +struct wpa_scan_results * hostapd_driver_get_scan_results( + struct hostapd_data *hapd); +int hostapd_driver_set_noa(struct hostapd_data *hapd, u8 count, int start, + int duration); +int hostapd_drv_set_key(const char *ifname, + struct hostapd_data *hapd, + enum wpa_alg alg, const u8 *addr, + int key_idx, int set_tx, + const u8 *seq, size_t seq_len, + const u8 *key, size_t key_len); +int hostapd_drv_send_mlme(struct hostapd_data *hapd, + const void *msg, size_t len, int noack); +int hostapd_drv_send_mlme_csa(struct hostapd_data *hapd, + const void *msg, size_t len, int noack, + const u16 *csa_offs, size_t csa_offs_len); +int hostapd_drv_sta_deauth(struct hostapd_data *hapd, + const u8 *addr, int reason); +int hostapd_drv_sta_disassoc(struct hostapd_data *hapd, + const u8 *addr, int reason); +int hostapd_drv_send_action(struct hostapd_data *hapd, unsigned int freq, + unsigned int wait, const u8 *dst, const u8 *data, + size_t len); +int hostapd_drv_send_action_addr3_ap(struct hostapd_data *hapd, + unsigned int freq, + unsigned int wait, const u8 *dst, + const u8 *data, size_t len); +static inline void +hostapd_drv_send_action_cancel_wait(struct hostapd_data *hapd) +{ + if (!hapd->driver || !hapd->driver->send_action_cancel_wait || + !hapd->drv_priv) + return; + hapd->driver->send_action_cancel_wait(hapd->drv_priv); +} +int hostapd_add_sta_node(struct hostapd_data *hapd, const u8 *addr, + u16 auth_alg); +int hostapd_sta_auth(struct hostapd_data *hapd, const u8 *addr, + u16 seq, u16 status, const u8 *ie, size_t len); +int hostapd_sta_assoc(struct hostapd_data *hapd, const u8 *addr, + int reassoc, u16 status, const u8 *ie, size_t len); +int hostapd_add_tspec(struct hostapd_data *hapd, const u8 *addr, + u8 *tspec_ie, size_t tspec_ielen); +int hostapd_start_dfs_cac(struct hostapd_iface *iface, + enum hostapd_hw_mode mode, int freq, + int channel, int ht_enabled, int vht_enabled, + int he_enabled, + int sec_channel_offset, int oper_chwidth, + int center_segment0, int center_segment1); +int hostapd_drv_do_acs(struct hostapd_data *hapd); +int hostapd_drv_update_dh_ie(struct hostapd_data *hapd, const u8 *peer, + u16 reason_code, const u8 *ie, size_t ielen); + + +#include "drivers/driver.h" + +int hostapd_drv_wnm_oper(struct hostapd_data *hapd, + enum wnm_oper oper, const u8 *peer, + u8 *buf, u16 *buf_len); + +int hostapd_drv_set_qos_map(struct hostapd_data *hapd, const u8 *qos_map_set, + u8 qos_map_set_len); + +void hostapd_get_ext_capa(struct hostapd_iface *iface); + +static inline int hostapd_drv_set_countermeasures(struct hostapd_data *hapd, + int enabled) +{ + if (hapd->driver == NULL || + hapd->driver->hapd_set_countermeasures == NULL) + return 0; + return hapd->driver->hapd_set_countermeasures(hapd->drv_priv, enabled); +} + +static inline int hostapd_drv_set_sta_vlan(const char *ifname, + struct hostapd_data *hapd, + const u8 *addr, int vlan_id) +{ + if (hapd->driver == NULL || hapd->driver->set_sta_vlan == NULL) + return 0; + return hapd->driver->set_sta_vlan(hapd->drv_priv, addr, ifname, + vlan_id); +} + +static inline int hostapd_drv_get_inact_sec(struct hostapd_data *hapd, + const u8 *addr) +{ + if (hapd->driver == NULL || hapd->driver->get_inact_sec == NULL) + return 0; + return hapd->driver->get_inact_sec(hapd->drv_priv, addr); +} + +static inline int hostapd_drv_sta_remove(struct hostapd_data *hapd, + const u8 *addr) +{ + if (!hapd->driver || !hapd->driver->sta_remove || !hapd->drv_priv) + return 0; + return hapd->driver->sta_remove(hapd->drv_priv, addr); +} + +static inline int hostapd_drv_hapd_send_eapol(struct hostapd_data *hapd, + const u8 *addr, const u8 *data, + size_t data_len, int encrypt, + u32 flags) +{ + if (hapd->driver == NULL || hapd->driver->hapd_send_eapol == NULL) + return 0; + return hapd->driver->hapd_send_eapol(hapd->drv_priv, addr, data, + data_len, encrypt, + hapd->own_addr, flags); +} + +static inline int hostapd_drv_read_sta_data( + struct hostapd_data *hapd, struct hostap_sta_driver_data *data, + const u8 *addr) +{ + if (hapd->driver == NULL || hapd->driver->read_sta_data == NULL) + return -1; + return hapd->driver->read_sta_data(hapd->drv_priv, data, addr); +} + +static inline int hostapd_drv_sta_clear_stats(struct hostapd_data *hapd, + const u8 *addr) +{ + if (hapd->driver == NULL || hapd->driver->sta_clear_stats == NULL) + return 0; + return hapd->driver->sta_clear_stats(hapd->drv_priv, addr); +} + +static inline int hostapd_drv_set_acl(struct hostapd_data *hapd, + struct hostapd_acl_params *params) +{ + if (hapd->driver == NULL || hapd->driver->set_acl == NULL) + return 0; + return hapd->driver->set_acl(hapd->drv_priv, params); +} + +static inline int hostapd_drv_set_ap(struct hostapd_data *hapd, + struct wpa_driver_ap_params *params) +{ + if (hapd->driver == NULL || hapd->driver->set_ap == NULL) + return 0; + return hapd->driver->set_ap(hapd->drv_priv, params); +} + +static inline int hostapd_drv_set_radius_acl_auth(struct hostapd_data *hapd, + const u8 *mac, int accepted, + u32 session_timeout) +{ + if (hapd->driver == NULL || hapd->driver->set_radius_acl_auth == NULL) + return 0; + return hapd->driver->set_radius_acl_auth(hapd->drv_priv, mac, accepted, + session_timeout); +} + +static inline int hostapd_drv_set_radius_acl_expire(struct hostapd_data *hapd, + const u8 *mac) +{ + if (hapd->driver == NULL || + hapd->driver->set_radius_acl_expire == NULL) + return 0; + return hapd->driver->set_radius_acl_expire(hapd->drv_priv, mac); +} + +static inline int hostapd_drv_set_authmode(struct hostapd_data *hapd, + int auth_algs) +{ + if (hapd->driver == NULL || hapd->driver->set_authmode == NULL) + return 0; + return hapd->driver->set_authmode(hapd->drv_priv, auth_algs); +} + +static inline void hostapd_drv_poll_client(struct hostapd_data *hapd, + const u8 *own_addr, const u8 *addr, + int qos) +{ + if (hapd->driver == NULL || hapd->driver->poll_client == NULL) + return; + hapd->driver->poll_client(hapd->drv_priv, own_addr, addr, qos); +} + +static inline int hostapd_drv_get_survey(struct hostapd_data *hapd, + unsigned int freq) +{ + if (hapd->driver == NULL) + return -1; + if (!hapd->driver->get_survey) + return -1; + return hapd->driver->get_survey(hapd->drv_priv, freq); +} + +static inline int hostapd_get_country(struct hostapd_data *hapd, char *alpha2) +{ + if (hapd->driver == NULL || hapd->driver->get_country == NULL) + return -1; + return hapd->driver->get_country(hapd->drv_priv, alpha2); +} + +static inline const char * hostapd_drv_get_radio_name(struct hostapd_data *hapd) +{ + if (hapd->driver == NULL || hapd->drv_priv == NULL || + hapd->driver->get_radio_name == NULL) + return NULL; + return hapd->driver->get_radio_name(hapd->drv_priv); +} + +static inline int hostapd_drv_switch_channel(struct hostapd_data *hapd, + struct csa_settings *settings) +{ + if (hapd->driver == NULL || hapd->driver->switch_channel == NULL || + hapd->drv_priv == NULL) + return -1; + + return hapd->driver->switch_channel(hapd->drv_priv, settings); +} + +static inline int hostapd_drv_status(struct hostapd_data *hapd, char *buf, + size_t buflen) +{ + if (!hapd->driver || !hapd->driver->status || !hapd->drv_priv) + return -1; + return hapd->driver->status(hapd->drv_priv, buf, buflen); +} + +static inline int hostapd_drv_br_add_ip_neigh(struct hostapd_data *hapd, + int version, const u8 *ipaddr, + int prefixlen, const u8 *addr) +{ + if (hapd->driver == NULL || hapd->drv_priv == NULL || + hapd->driver->br_add_ip_neigh == NULL) + return -1; + return hapd->driver->br_add_ip_neigh(hapd->drv_priv, version, ipaddr, + prefixlen, addr); +} + +static inline int hostapd_drv_br_delete_ip_neigh(struct hostapd_data *hapd, + u8 version, const u8 *ipaddr) +{ + if (hapd->driver == NULL || hapd->drv_priv == NULL || + hapd->driver->br_delete_ip_neigh == NULL) + return -1; + return hapd->driver->br_delete_ip_neigh(hapd->drv_priv, version, + ipaddr); +} + +static inline int hostapd_drv_br_port_set_attr(struct hostapd_data *hapd, + enum drv_br_port_attr attr, + unsigned int val) +{ + if (hapd->driver == NULL || hapd->drv_priv == NULL || + hapd->driver->br_port_set_attr == NULL) + return -1; + return hapd->driver->br_port_set_attr(hapd->drv_priv, attr, val); +} + +static inline int hostapd_drv_br_set_net_param(struct hostapd_data *hapd, + enum drv_br_net_param param, + unsigned int val) +{ + if (hapd->driver == NULL || hapd->drv_priv == NULL || + hapd->driver->br_set_net_param == NULL) + return -1; + return hapd->driver->br_set_net_param(hapd->drv_priv, param, val); +} + +static inline int hostapd_drv_vendor_cmd(struct hostapd_data *hapd, + int vendor_id, int subcmd, + const u8 *data, size_t data_len, + struct wpabuf *buf) +{ + if (hapd->driver == NULL || hapd->driver->vendor_cmd == NULL) + return -1; + return hapd->driver->vendor_cmd(hapd->drv_priv, vendor_id, subcmd, data, + data_len, buf); +} + +static inline int hostapd_drv_stop_ap(struct hostapd_data *hapd) +{ + if (!hapd->driver || !hapd->driver->stop_ap || !hapd->drv_priv) + return 0; + return hapd->driver->stop_ap(hapd->drv_priv); +} + +static inline int hostapd_drv_channel_info(struct hostapd_data *hapd, + struct wpa_channel_info *ci) +{ + if (!hapd->driver || !hapd->driver->channel_info) + return -1; + return hapd->driver->channel_info(hapd->drv_priv, ci); +} + +static inline int +hostapd_drv_send_external_auth_status(struct hostapd_data *hapd, + struct external_auth *params) +{ + if (!hapd->driver || !hapd->drv_priv || + !hapd->driver->send_external_auth_status) + return -1; + return hapd->driver->send_external_auth_status(hapd->drv_priv, params); +} + +#endif /* AP_DRV_OPS */ diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ap_list.c b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ap_list.c new file mode 100755 index 0000000..1930231 --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ap_list.c @@ -0,0 +1,312 @@ +/* + * hostapd / AP table + * Copyright (c) 2002-2009, Jouni Malinen + * Copyright (c) 2003-2004, Instant802 Networks, Inc. + * Copyright (c) 2006, Devicescape Software, Inc. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "utils/eloop.h" +#include "common/ieee802_11_defs.h" +#include "common/ieee802_11_common.h" +#include "ap/hostapd.h" +#include "ap_config.h" +#include "ieee802_11.h" +#include "ap/sta_info.h" +#include "beacon.h" +#include "ap_list.h" + + +/* AP list is a double linked list with head->prev pointing to the end of the + * list and tail->next = NULL. Entries are moved to the head of the list + * whenever a beacon has been received from the AP in question. The tail entry + * in this link will thus be the least recently used entry. */ + + +static int ap_list_beacon_olbc(struct hostapd_iface *iface, struct ap_info *ap) +{ + int i; + + if (iface->current_mode == NULL || + iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G || + iface->conf->channel != ap->channel) + return 0; + + if (ap->erp != -1 && (ap->erp & ERP_INFO_NON_ERP_PRESENT)) + return 1; + + for (i = 0; i < WLAN_SUPP_RATES_MAX; i++) { + int rate = (ap->supported_rates[i] & 0x7f) * 5; + if (rate == 60 || rate == 90 || rate > 110) + return 0; + } + + return 1; +} + + +static struct ap_info * ap_get_ap(struct hostapd_iface *iface, const u8 *ap) +{ + struct ap_info *s; + + s = iface->ap_hash[STA_HASH(ap)]; + while (s != NULL && os_memcmp(s->addr, ap, ETH_ALEN) != 0) + s = s->hnext; + return s; +} + + +static void ap_ap_list_add(struct hostapd_iface *iface, struct ap_info *ap) +{ + if (iface->ap_list) { + ap->prev = iface->ap_list->prev; + iface->ap_list->prev = ap; + } else + ap->prev = ap; + ap->next = iface->ap_list; + iface->ap_list = ap; +} + + +static void ap_ap_list_del(struct hostapd_iface *iface, struct ap_info *ap) +{ + if (iface->ap_list == ap) + iface->ap_list = ap->next; + else + ap->prev->next = ap->next; + + if (ap->next) + ap->next->prev = ap->prev; + else if (iface->ap_list) + iface->ap_list->prev = ap->prev; +} + + +static void ap_ap_hash_add(struct hostapd_iface *iface, struct ap_info *ap) +{ + ap->hnext = iface->ap_hash[STA_HASH(ap->addr)]; + iface->ap_hash[STA_HASH(ap->addr)] = ap; +} + + +static void ap_ap_hash_del(struct hostapd_iface *iface, struct ap_info *ap) +{ + struct ap_info *s; + + s = iface->ap_hash[STA_HASH(ap->addr)]; + if (s == NULL) return; + if (os_memcmp(s->addr, ap->addr, ETH_ALEN) == 0) { + iface->ap_hash[STA_HASH(ap->addr)] = s->hnext; + return; + } + + while (s->hnext != NULL && + os_memcmp(s->hnext->addr, ap->addr, ETH_ALEN) != 0) + s = s->hnext; + if (s->hnext != NULL) + s->hnext = s->hnext->hnext; + else + wpa_printf(MSG_INFO, "AP: could not remove AP " MACSTR + " from hash table", MAC2STR(ap->addr)); +} + + +static void ap_free_ap(struct hostapd_iface *iface, struct ap_info *ap) +{ + ap_ap_hash_del(iface, ap); + ap_ap_list_del(iface, ap); + + iface->num_ap--; + os_free(ap); +} + + +static void hostapd_free_aps(struct hostapd_iface *iface) +{ + struct ap_info *ap, *prev; + + ap = iface->ap_list; + + while (ap) { + prev = ap; + ap = ap->next; + ap_free_ap(iface, prev); + } + + iface->ap_list = NULL; +} + + +static struct ap_info * ap_ap_add(struct hostapd_iface *iface, const u8 *addr) +{ + struct ap_info *ap; + + ap = os_zalloc(sizeof(struct ap_info)); + if (ap == NULL) + return NULL; + + /* initialize AP info data */ + os_memcpy(ap->addr, addr, ETH_ALEN); + ap_ap_list_add(iface, ap); + iface->num_ap++; + ap_ap_hash_add(iface, ap); + + if (iface->num_ap > iface->conf->ap_table_max_size && ap != ap->prev) { + wpa_printf(MSG_DEBUG, "Removing the least recently used AP " + MACSTR " from AP table", MAC2STR(ap->prev->addr)); + ap_free_ap(iface, ap->prev); + } + + return ap; +} + + +void ap_list_process_beacon(struct hostapd_iface *iface, + const struct ieee80211_mgmt *mgmt, + struct ieee802_11_elems *elems, + struct hostapd_frame_info *fi) +{ + struct ap_info *ap; + int new_ap = 0; + int set_beacon = 0; + + if (iface->conf->ap_table_max_size < 1) + return; + + ap = ap_get_ap(iface, mgmt->bssid); + if (!ap) { + ap = ap_ap_add(iface, mgmt->bssid); + if (!ap) { + wpa_printf(MSG_INFO, + "Failed to allocate AP information entry"); + return; + } + new_ap = 1; + } + + merge_byte_arrays(ap->supported_rates, WLAN_SUPP_RATES_MAX, + elems->supp_rates, elems->supp_rates_len, + elems->ext_supp_rates, elems->ext_supp_rates_len); + + if (elems->erp_info) + ap->erp = elems->erp_info[0]; + else + ap->erp = -1; + + if (elems->ds_params) + ap->channel = elems->ds_params[0]; + else if (elems->ht_operation) + ap->channel = elems->ht_operation[0]; + else if (fi) + ap->channel = fi->channel; + + if (elems->ht_capabilities) + ap->ht_support = 1; + else + ap->ht_support = 0; + + os_get_reltime(&ap->last_beacon); + + if (!new_ap && ap != iface->ap_list) { + /* move AP entry into the beginning of the list so that the + * oldest entry is always in the end of the list */ + ap_ap_list_del(iface, ap); + ap_ap_list_add(iface, ap); + } + + if (!iface->olbc && + ap_list_beacon_olbc(iface, ap)) { + iface->olbc = 1; + wpa_printf(MSG_DEBUG, "OLBC AP detected: " MACSTR + " (channel %d) - enable protection", + MAC2STR(ap->addr), ap->channel); + set_beacon++; + } + +#ifdef CONFIG_IEEE80211N + if (!iface->olbc_ht && !ap->ht_support && + (ap->channel == 0 || + ap->channel == iface->conf->channel || + ap->channel == iface->conf->channel + + iface->conf->secondary_channel * 4)) { + iface->olbc_ht = 1; + hostapd_ht_operation_update(iface); + wpa_printf(MSG_DEBUG, "OLBC HT AP detected: " MACSTR + " (channel %d) - enable protection", + MAC2STR(ap->addr), ap->channel); + set_beacon++; + } +#endif /* CONFIG_IEEE80211N */ + + if (set_beacon) + ieee802_11_update_beacons(iface); +} + + +void ap_list_timer(struct hostapd_iface *iface) +{ + struct os_reltime now; + struct ap_info *ap; + int set_beacon = 0; + + if (!iface->ap_list) + return; + + os_get_reltime(&now); + + while (iface->ap_list) { + ap = iface->ap_list->prev; + if (!os_reltime_expired(&now, &ap->last_beacon, + iface->conf->ap_table_expiration_time)) + break; + + ap_free_ap(iface, ap); + } + + if (iface->olbc || iface->olbc_ht) { + int olbc = 0; + int olbc_ht = 0; + + ap = iface->ap_list; + while (ap && (olbc == 0 || olbc_ht == 0)) { + if (ap_list_beacon_olbc(iface, ap)) + olbc = 1; + if (!ap->ht_support) + olbc_ht = 1; + ap = ap->next; + } + if (!olbc && iface->olbc) { + wpa_printf(MSG_DEBUG, "OLBC not detected anymore"); + iface->olbc = 0; + set_beacon++; + } +#ifdef CONFIG_IEEE80211N + if (!olbc_ht && iface->olbc_ht) { + wpa_printf(MSG_DEBUG, "OLBC HT not detected anymore"); + iface->olbc_ht = 0; + hostapd_ht_operation_update(iface); + set_beacon++; + } +#endif /* CONFIG_IEEE80211N */ + } + + if (set_beacon) + ieee802_11_update_beacons(iface); +} + + +int ap_list_init(struct hostapd_iface *iface) +{ + return 0; +} + + +void ap_list_deinit(struct hostapd_iface *iface) +{ + hostapd_free_aps(iface); +} diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ap_list.h b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ap_list.h new file mode 100755 index 0000000..9e0353c --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ap_list.h @@ -0,0 +1,58 @@ +/* + * hostapd / AP table + * Copyright (c) 2002-2003, Jouni Malinen + * Copyright (c) 2003-2004, Instant802 Networks, Inc. + * Copyright (c) 2006, Devicescape Software, Inc. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef AP_LIST_H +#define AP_LIST_H + +struct ap_info { + /* Note: next/prev pointers are updated whenever a new beacon is + * received because these are used to find the least recently used + * entries. */ + struct ap_info *next; /* next entry in AP list */ + struct ap_info *prev; /* previous entry in AP list */ + struct ap_info *hnext; /* next entry in hash table list */ + u8 addr[6]; + u8 supported_rates[WLAN_SUPP_RATES_MAX]; + int erp; /* ERP Info or -1 if ERP info element not present */ + + int channel; + + int ht_support; + + struct os_reltime last_beacon; +}; + +struct ieee802_11_elems; +struct hostapd_frame_info; + +void ap_list_process_beacon(struct hostapd_iface *iface, + const struct ieee80211_mgmt *mgmt, + struct ieee802_11_elems *elems, + struct hostapd_frame_info *fi); +#ifdef NEED_AP_MLME +int ap_list_init(struct hostapd_iface *iface); +void ap_list_deinit(struct hostapd_iface *iface); +void ap_list_timer(struct hostapd_iface *iface); +#else /* NEED_AP_MLME */ +static inline int ap_list_init(struct hostapd_iface *iface) +{ + return 0; +} + +static inline void ap_list_deinit(struct hostapd_iface *iface) +{ +} + +static inline void ap_list_timer(struct hostapd_iface *iface) +{ +} +#endif /* NEED_AP_MLME */ + +#endif /* AP_LIST_H */ diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ap_mlme.c b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ap_mlme.c new file mode 100755 index 0000000..ebcbd4e --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ap_mlme.c @@ -0,0 +1,191 @@ +/* + * hostapd / IEEE 802.11 MLME + * Copyright 2003-2006, Jouni Malinen + * Copyright 2003-2004, Instant802 Networks, Inc. + * Copyright 2005-2006, Devicescape Software, Inc. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "common/ieee802_11_defs.h" +#include "ieee802_11.h" +#include "wpa_auth.h" +#include "ap/sta_info.h" +#include "ap_mlme.h" +#include "ap/hostapd.h" + + +#if !defined(CONFIG_NO_HOSTAPD_LOGGER) || CFG_ENABLE_WPA_LOG +static const char * mlme_auth_alg_str(int alg) +{ + switch (alg) { + case WLAN_AUTH_OPEN: + return "OPEN_SYSTEM"; + case WLAN_AUTH_SHARED_KEY: + return "SHARED_KEY"; + case WLAN_AUTH_FT: + return "FT"; + } + + return "unknown"; +} +#endif /* CONFIG_NO_HOSTAPD_LOGGER */ + + +/** + * mlme_authenticate_indication - Report the establishment of an authentication + * relationship with a specific peer MAC entity + * @hapd: BSS data + * @sta: peer STA data + * + * MLME calls this function as a result of the establishment of an + * authentication relationship with a specific peer MAC entity that + * resulted from an authentication procedure that was initiated by + * that specific peer MAC entity. + * + * PeerSTAAddress = sta->addr + * AuthenticationType = sta->auth_alg (WLAN_AUTH_OPEN / WLAN_AUTH_SHARED_KEY) + */ +void mlme_authenticate_indication(struct hostapd_data *hapd, + struct sta_info *sta) +{ + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_MLME, + HOSTAPD_LEVEL_DEBUG, + "MLME-AUTHENTICATE.indication(" MACSTR ", %s)", + MAC2STR(sta->addr), mlme_auth_alg_str(sta->auth_alg)); + if (sta->auth_alg != WLAN_AUTH_FT && + sta->auth_alg != WLAN_AUTH_FILS_SK && + sta->auth_alg != WLAN_AUTH_FILS_SK_PFS && + sta->auth_alg != WLAN_AUTH_FILS_PK && + !(sta->flags & WLAN_STA_MFP)) + mlme_deletekeys_request(hapd, sta); + ap_sta_clear_disconnect_timeouts(hapd, sta); +} + + +/** + * mlme_deauthenticate_indication - Report the invalidation of an + * authentication relationship with a specific peer MAC entity + * @hapd: BSS data + * @sta: Peer STA data + * @reason_code: ReasonCode from Deauthentication frame + * + * MLME calls this function as a result of the invalidation of an + * authentication relationship with a specific peer MAC entity. + * + * PeerSTAAddress = sta->addr + */ +void mlme_deauthenticate_indication(struct hostapd_data *hapd, + struct sta_info *sta, u16 reason_code) +{ + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_MLME, + HOSTAPD_LEVEL_DEBUG, + "MLME-DEAUTHENTICATE.indication(" MACSTR ", %d)", + MAC2STR(sta->addr), reason_code); + if (!hapd->iface->driver_ap_teardown) + mlme_deletekeys_request(hapd, sta); +} + + +/** + * mlme_associate_indication - Report the establishment of an association with + * a specific peer MAC entity + * @hapd: BSS data + * @sta: peer STA data + * + * MLME calls this function as a result of the establishment of an + * association with a specific peer MAC entity that resulted from an + * association procedure that was initiated by that specific peer MAC entity. + * + * PeerSTAAddress = sta->addr + */ +void mlme_associate_indication(struct hostapd_data *hapd, struct sta_info *sta) +{ + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_MLME, + HOSTAPD_LEVEL_DEBUG, + "MLME-ASSOCIATE.indication(" MACSTR ")", + MAC2STR(sta->addr)); + if (sta->auth_alg != WLAN_AUTH_FT && + sta->auth_alg != WLAN_AUTH_FILS_SK && + sta->auth_alg != WLAN_AUTH_FILS_SK_PFS && + sta->auth_alg != WLAN_AUTH_FILS_PK) + mlme_deletekeys_request(hapd, sta); + ap_sta_clear_disconnect_timeouts(hapd, sta); +} + + +/** + * mlme_reassociate_indication - Report the establishment of an reassociation + * with a specific peer MAC entity + * @hapd: BSS data + * @sta: peer STA data + * + * MLME calls this function as a result of the establishment of an + * reassociation with a specific peer MAC entity that resulted from a + * reassociation procedure that was initiated by that specific peer MAC entity. + * + * PeerSTAAddress = sta->addr + */ +void mlme_reassociate_indication(struct hostapd_data *hapd, + struct sta_info *sta) +{ + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_MLME, + HOSTAPD_LEVEL_DEBUG, + "MLME-REASSOCIATE.indication(" MACSTR ")", + MAC2STR(sta->addr)); + if (sta->auth_alg != WLAN_AUTH_FT && + sta->auth_alg != WLAN_AUTH_FILS_SK && + sta->auth_alg != WLAN_AUTH_FILS_SK_PFS && + sta->auth_alg != WLAN_AUTH_FILS_PK) + mlme_deletekeys_request(hapd, sta); + ap_sta_clear_disconnect_timeouts(hapd, sta); +} + + +/** + * mlme_disassociate_indication - Report disassociation with a specific peer + * MAC entity + * @hapd: BSS data + * @sta: Peer STA data + * @reason_code: ReasonCode from Disassociation frame + * + * MLME calls this function as a result of the invalidation of an association + * relationship with a specific peer MAC entity. + * + * PeerSTAAddress = sta->addr + */ +void mlme_disassociate_indication(struct hostapd_data *hapd, + struct sta_info *sta, u16 reason_code) +{ + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_MLME, + HOSTAPD_LEVEL_DEBUG, + "MLME-DISASSOCIATE.indication(" MACSTR ", %d)", + MAC2STR(sta->addr), reason_code); + mlme_deletekeys_request(hapd, sta); +} + + +void mlme_michaelmicfailure_indication(struct hostapd_data *hapd, + const u8 *addr) +{ + hostapd_logger(hapd, addr, HOSTAPD_MODULE_MLME, + HOSTAPD_LEVEL_DEBUG, + "MLME-MichaelMICFailure.indication(" MACSTR ")", + MAC2STR(addr)); +} + + +void mlme_deletekeys_request(struct hostapd_data *hapd, struct sta_info *sta) +{ + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_MLME, + HOSTAPD_LEVEL_DEBUG, + "MLME-DELETEKEYS.request(" MACSTR ")", + MAC2STR(sta->addr)); + + if (sta->wpa_sm) + wpa_remove_ptk(sta->wpa_sm); +} diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ap_mlme.h b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ap_mlme.h new file mode 100755 index 0000000..e7fd69d --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ap_mlme.h @@ -0,0 +1,34 @@ +/* + * hostapd / IEEE 802.11 MLME + * Copyright 2003, Jouni Malinen + * Copyright 2003-2004, Instant802 Networks, Inc. + * Copyright 2005-2006, Devicescape Software, Inc. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef MLME_H +#define MLME_H + +void mlme_authenticate_indication(struct hostapd_data *hapd, + struct sta_info *sta); + +void mlme_deauthenticate_indication(struct hostapd_data *hapd, + struct sta_info *sta, u16 reason_code); + +void mlme_associate_indication(struct hostapd_data *hapd, + struct sta_info *sta); + +void mlme_reassociate_indication(struct hostapd_data *hapd, + struct sta_info *sta); + +void mlme_disassociate_indication(struct hostapd_data *hapd, + struct sta_info *sta, u16 reason_code); + +void mlme_michaelmicfailure_indication(struct hostapd_data *hapd, + const u8 *addr); + +void mlme_deletekeys_request(struct hostapd_data *hapd, struct sta_info *sta); + +#endif /* MLME_H */ diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/beacon.c b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/beacon.c new file mode 100755 index 0000000..d414655 --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/beacon.c @@ -0,0 +1,1380 @@ +/* + * hostapd / IEEE 802.11 Management: Beacon and Probe Request/Response + * Copyright (c) 2002-2004, Instant802 Networks, Inc. + * Copyright (c) 2005-2006, Devicescape Software, Inc. + * Copyright (c) 2008-2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#ifndef CONFIG_NATIVE_WINDOWS + +#include "utils/common.h" +#include "common/ieee802_11_defs.h" +#include "common/ieee802_11_common.h" +#include "common/hw_features_common.h" +#include "wps/wps_defs.h" +#include "ap/hostapd.h" +#include "ieee802_11.h" +#include "wpa_auth.h" +#include "wmm.h" +#include "ap_config.h" +#include "ap/sta_info.h" +#include "p2p_hostapd.h" +#include "ap_drv_ops.h" +#include "beacon.h" +#include "ap/dfs.h" +#include "ieee802_11_auth.h" + +#include "include.h" +#include "uart_pub.h" + +#ifdef NEED_AP_MLME +#ifdef CONFIG_FULL_HOSTAPD +static u8 * hostapd_eid_rm_enabled_capab(struct hostapd_data *hapd, u8 *eid, + size_t len) +{ + size_t i; + + for (i = 0; i < RRM_CAPABILITIES_IE_LEN; i++) { + if (hapd->conf->radio_measurements[i]) + break; + } + + if (i == RRM_CAPABILITIES_IE_LEN || len < 2 + RRM_CAPABILITIES_IE_LEN) + return eid; + + *eid++ = WLAN_EID_RRM_ENABLED_CAPABILITIES; + *eid++ = RRM_CAPABILITIES_IE_LEN; + os_memcpy(eid, hapd->conf->radio_measurements, RRM_CAPABILITIES_IE_LEN); + + return eid + RRM_CAPABILITIES_IE_LEN; +} +static u8 * hostapd_eid_bss_load(struct hostapd_data *hapd, u8 *eid, size_t len) +{ + if (len < 2 + 5) + return eid; + +#ifdef CONFIG_TESTING_OPTIONS + if (hapd->conf->bss_load_test_set) { + *eid++ = WLAN_EID_BSS_LOAD; + *eid++ = 5; + os_memcpy(eid, hapd->conf->bss_load_test, 5); + eid += 5; + return eid; + } +#endif /* CONFIG_TESTING_OPTIONS */ + if (hapd->conf->bss_load_update_period) { + *eid++ = WLAN_EID_BSS_LOAD; + *eid++ = 5; + WPA_PUT_LE16(eid, hapd->num_sta); + eid += 2; + *eid++ = hapd->iface->channel_utilization; + WPA_PUT_LE16(eid, 0); /* no available admission capabity */ + eid += 2; + } + return eid; +} +#endif /* CONFIG_FULL_HOSTAPD */ + +static u8 ieee802_11_erp_info(struct hostapd_data *hapd) +{ + u8 erp = 0; + + if (hapd->iface->current_mode == NULL || + hapd->iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G) + return 0; + + if (hapd->iface->olbc) + erp |= ERP_INFO_USE_PROTECTION; + if (hapd->iface->num_sta_non_erp > 0) { + erp |= ERP_INFO_NON_ERP_PRESENT | + ERP_INFO_USE_PROTECTION; + } + if (hapd->iface->num_sta_no_short_preamble > 0 || + hapd->iconf->preamble == LONG_PREAMBLE) + erp |= ERP_INFO_BARKER_PREAMBLE_MODE; + + return erp; +} + + +static u8 * hostapd_eid_ds_params(struct hostapd_data *hapd, u8 *eid) +{ + *eid++ = WLAN_EID_DS_PARAMS; + *eid++ = 1; + *eid++ = hapd->iconf->channel; + return eid; +} + + +static u8 * hostapd_eid_erp_info(struct hostapd_data *hapd, u8 *eid) +{ + if (hapd->iface->current_mode == NULL || + hapd->iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G) + return eid; + + /* Set NonERP_present and use_protection bits if there + * are any associated NonERP stations. */ + /* TODO: use_protection bit can be set to zero even if + * there are NonERP stations present. This optimization + * might be useful if NonERP stations are "quiet". + * See 802.11g/D6 E-1 for recommended practice. + * In addition, Non ERP present might be set, if AP detects Non ERP + * operation on other APs. */ + + /* Add ERP Information element */ + *eid++ = WLAN_EID_ERP_INFO; + *eid++ = 1; + *eid++ = ieee802_11_erp_info(hapd); + + return eid; +} + + +static u8 * hostapd_eid_pwr_constraint(struct hostapd_data *hapd, u8 *eid) +{ + u8 *pos = eid; + u8 local_pwr_constraint = 0; + int dfs = 0; + + if (hapd->iface->current_mode == NULL || + hapd->iface->current_mode->mode != HOSTAPD_MODE_IEEE80211A) + return eid; + + /* Let host drivers add this IE if DFS support is offloaded */ + if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) + return eid; + + /* + * There is no DFS support and power constraint was not directly + * requested by config option. + */ + if (!hapd->iconf->ieee80211h && + hapd->iconf->local_pwr_constraint == -1) + return eid; + +#ifdef CONFIG_DFS + /* Check if DFS is required by regulatory. */ + dfs = hostapd_is_dfs_required(hapd->iface); + if (dfs < 0) { + wpa_printf(MSG_WARNING, "Failed to check if DFS is required; ret=%d", + dfs); + dfs = 0; + } +#endif + + if (dfs == 0 && hapd->iconf->local_pwr_constraint == -1) + return eid; + + /* + * ieee80211h (DFS) is enabled so Power Constraint element shall + * be added when running on DFS channel whenever local_pwr_constraint + * is configured or not. In order to meet regulations when TPC is not + * implemented using a transmit power that is below the legal maximum + * (including any mitigation factor) should help. In this case, + * indicate 3 dB below maximum allowed transmit power. + */ + if (hapd->iconf->local_pwr_constraint == -1) + local_pwr_constraint = 3; + + /* + * A STA that is not an AP shall use a transmit power less than or + * equal to the local maximum transmit power level for the channel. + * The local maximum transmit power can be calculated from the formula: + * local max TX pwr = max TX pwr - local pwr constraint + * Where max TX pwr is maximum transmit power level specified for + * channel in Country element and local pwr constraint is specified + * for channel in this Power Constraint element. + */ + + /* Element ID */ + *pos++ = WLAN_EID_PWR_CONSTRAINT; + /* Length */ + *pos++ = 1; + /* Local Power Constraint */ + if (local_pwr_constraint) + *pos++ = local_pwr_constraint; + else + *pos++ = hapd->iconf->local_pwr_constraint; + + return pos; +} + + +static u8 * hostapd_eid_country_add(u8 *pos, u8 *end, int chan_spacing, + struct hostapd_channel_data *start, + struct hostapd_channel_data *prev) +{ + if (end - pos < 3) + return pos; + + /* first channel number */ + *pos++ = start->chan; + /* number of channels */ + *pos++ = (prev->chan - start->chan) / chan_spacing + 1; + /* maximum transmit power level */ + *pos++ = start->max_tx_power; + + return pos; +} + + +static u8 * hostapd_eid_country(struct hostapd_data *hapd, u8 *eid, + int max_len) +{ + u8 *pos = eid; + u8 *end = eid + max_len; + int i; + struct hostapd_hw_modes *mode; + struct hostapd_channel_data *start, *prev; + int chan_spacing = 1; + + if (!hapd->iconf->ieee80211d || max_len < 6 || + hapd->iface->current_mode == NULL) + return eid; + + *pos++ = WLAN_EID_COUNTRY; + pos++; /* length will be set later */ + os_memcpy(pos, hapd->iconf->country, 3); /* e.g., 'US ' */ + pos += 3; + + mode = hapd->iface->current_mode; + if (mode->mode == HOSTAPD_MODE_IEEE80211A) + chan_spacing = 4; + + start = prev = NULL; + for (i = 0; i < mode->num_channels; i++) { + struct hostapd_channel_data *chan = &mode->channels[i]; + if (chan->flag & HOSTAPD_CHAN_DISABLED) + continue; + if (start && prev && + prev->chan + chan_spacing == chan->chan && + start->max_tx_power == chan->max_tx_power) { + prev = chan; + continue; /* can use same entry */ + } + + if (start && prev) { + pos = hostapd_eid_country_add(pos, end, chan_spacing, + start, prev); + start = NULL; + } + + /* Start new group */ + start = prev = chan; + } + + if (start) { + pos = hostapd_eid_country_add(pos, end, chan_spacing, + start, prev); + } + + if ((pos - eid) & 1) { + if (end - pos < 1) + return eid; + *pos++ = 0; /* pad for 16-bit alignment */ + } + + eid[1] = (pos - eid) - 2; + + return pos; +} + + +static u8 * hostapd_eid_wpa(struct hostapd_data *hapd, u8 *eid, size_t len) +{ + const u8 *ie; + size_t ielen; + + ie = wpa_auth_get_wpa_ie(hapd->wpa_auth, &ielen); + if (ie == NULL || ielen > len) + return eid; + + os_memcpy(eid, ie, ielen); + return eid + ielen; +} + + +static u8 * hostapd_eid_csa(struct hostapd_data *hapd, u8 *eid) +{ +#ifdef CONFIG_TESTING_OPTIONS + if (hapd->iface->cs_oper_class && hapd->iconf->ecsa_ie_only) + return eid; +#endif /* CONFIG_TESTING_OPTIONS */ + + if (!hapd->cs_freq_params.channel) + return eid; + + *eid++ = WLAN_EID_CHANNEL_SWITCH; + *eid++ = 3; + *eid++ = hapd->cs_block_tx; + *eid++ = hapd->cs_freq_params.channel; + *eid++ = hapd->cs_count; + + return eid; +} + + +static u8 * hostapd_eid_ecsa(struct hostapd_data *hapd, u8 *eid) +{ + if (!hapd->cs_freq_params.channel || !hapd->iface->cs_oper_class) + return eid; + + *eid++ = WLAN_EID_EXT_CHANSWITCH_ANN; + *eid++ = 4; + *eid++ = hapd->cs_block_tx; + *eid++ = hapd->iface->cs_oper_class; + *eid++ = hapd->cs_freq_params.channel; + *eid++ = hapd->cs_count; + + return eid; +} + + +static u8 * hostapd_eid_supported_op_classes(struct hostapd_data *hapd, u8 *eid) +{ + u8 op_class, channel; + + if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_CSA) || + !hapd->iface->freq) + return eid; + + if (ieee80211_freq_to_channel_ext(hapd->iface->freq, + hapd->iconf->secondary_channel, + hostapd_get_oper_chwidth(hapd->iconf), + &op_class, &channel) == + NUM_HOSTAPD_MODES) + return eid; + + *eid++ = WLAN_EID_SUPPORTED_OPERATING_CLASSES; + *eid++ = 2; + + /* Current Operating Class */ + *eid++ = op_class; + + /* TODO: Advertise all the supported operating classes */ + *eid++ = 0; + + return eid; +} + + +static u8 * hostapd_gen_probe_resp(struct hostapd_data *hapd, + const struct ieee80211_mgmt *req, + int is_p2p, size_t *resp_len) +{ + struct ieee80211_mgmt *resp; + u8 *pos, *epos, *csa_pos; + size_t buflen; + +#define MAX_PROBERESP_LEN 768 + buflen = MAX_PROBERESP_LEN; +#ifdef CONFIG_WPS + if (hapd->wps_probe_resp_ie) + buflen += wpabuf_len(hapd->wps_probe_resp_ie); +#endif /* CONFIG_WPS */ +#ifdef CONFIG_P2P + if (hapd->p2p_probe_resp_ie) + buflen += wpabuf_len(hapd->p2p_probe_resp_ie); +#endif /* CONFIG_P2P */ +#ifdef CONFIG_FST + if (hapd->iface->fst_ies) + buflen += wpabuf_len(hapd->iface->fst_ies); +#endif /* CONFIG_FST */ + if (hapd->conf->vendor_elements) + buflen += wpabuf_len(hapd->conf->vendor_elements); +#ifdef CONFIG_IEEE80211AC + if (hapd->conf->vendor_vht) { + buflen += 5 + 2 + sizeof(struct ieee80211_vht_capabilities) + + 2 + sizeof(struct ieee80211_vht_operation); + } +#endif + +#ifdef CONFIG_IEEE80211AX + if (hapd->iconf->ieee80211ax) { + buflen += 3 + sizeof(struct ieee80211_he_capabilities) + + 3 + sizeof(struct ieee80211_he_operation) + + 3 + sizeof(struct ieee80211_he_mu_edca_parameter_set) + + 3 + sizeof(struct ieee80211_spatial_reuse); + } +#endif /* CONFIG_IEEE80211AX */ + +#ifdef CONFIG_MBO + buflen += hostapd_mbo_ie_len(hapd); +#endif +#ifdef CONFIG_OWE + buflen += hostapd_eid_owe_trans_len(hapd); +#endif + resp = os_zalloc(buflen); + if (resp == NULL) + return NULL; + + epos = ((u8 *) resp) + MAX_PROBERESP_LEN; + + resp->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, + WLAN_FC_STYPE_PROBE_RESP); + if (req) + os_memcpy(resp->da, req->sa, ETH_ALEN); + os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN); + + os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN); + resp->u.probe_resp.beacon_int = + host_to_le16(hapd->iconf->beacon_int); + + /* hardware or low-level driver will setup seq_ctrl and timestamp */ + resp->u.probe_resp.capab_info = + host_to_le16(hostapd_own_capab_info(hapd)); + + pos = resp->u.probe_resp.variable; + *pos++ = WLAN_EID_SSID; + *pos++ = hapd->conf->ssid.ssid_len; + os_memcpy(pos, hapd->conf->ssid.ssid, hapd->conf->ssid.ssid_len); + pos += hapd->conf->ssid.ssid_len; + + /* Supported rates */ + pos = hostapd_eid_supp_rates(hapd, pos); + + /* DS Params */ + pos = hostapd_eid_ds_params(hapd, pos); + +#ifdef CONFIG_FULL_HOSTAPD + pos = hostapd_eid_country(hapd, pos, epos - pos); + + /* Power Constraint element */ + pos = hostapd_eid_pwr_constraint(hapd, pos); +#endif + /* CSA IE */ + csa_pos = hostapd_eid_csa(hapd, pos); + if (csa_pos != pos) + hapd->cs_c_off_proberesp = csa_pos - (u8 *) resp - 1; + pos = csa_pos; + + /* ERP Information element */ + pos = hostapd_eid_erp_info(hapd, pos); + + /* Extended supported rates */ + pos = hostapd_eid_ext_supp_rates(hapd, pos); + + /* RSN, MDIE */ + if (hapd->conf->wpa != WPA_PROTO_WPA) + pos = hostapd_eid_wpa(hapd, pos, epos - pos); + +#ifdef CONFIG_FULL_HOSTAPD + pos = hostapd_eid_bss_load(hapd, pos, epos - pos); + + pos = hostapd_eid_rm_enabled_capab(hapd, pos, epos - pos); +#endif + /* eCSA IE */ + csa_pos = hostapd_eid_ecsa(hapd, pos); + if (csa_pos != pos) + hapd->cs_c_off_ecsa_proberesp = csa_pos - (u8 *) resp - 1; + pos = csa_pos; + + pos = hostapd_eid_supported_op_classes(hapd, pos); + +#ifdef CONFIG_IEEE80211N + /* Secondary Channel Offset element */ + /* TODO: The standard doesn't specify a position for this element. */ + pos = hostapd_eid_secondary_channel(hapd, pos); + + pos = hostapd_eid_ht_capabilities(hapd, pos); + pos = hostapd_eid_ht_operation(hapd, pos); +#endif /* CONFIG_IEEE80211N */ + + pos = hostapd_eid_ext_capab(hapd, pos); + +#ifdef CONFIG_FULL_HOSTAPD + pos = hostapd_eid_time_adv(hapd, pos); + pos = hostapd_eid_time_zone(hapd, pos); + + pos = hostapd_eid_interworking(hapd, pos); + pos = hostapd_eid_adv_proto(hapd, pos); + pos = hostapd_eid_roaming_consortium(hapd, pos); +#endif + +#ifdef CONFIG_FST + if (hapd->iface->fst_ies) { + os_memcpy(pos, wpabuf_head(hapd->iface->fst_ies), + wpabuf_len(hapd->iface->fst_ies)); + pos += wpabuf_len(hapd->iface->fst_ies); + } +#endif /* CONFIG_FST */ + +#ifdef CONFIG_IEEE80211AC + if (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) { + pos = hostapd_eid_vht_capabilities(hapd, pos, 0); + pos = hostapd_eid_vht_operation(hapd, pos); + pos = hostapd_eid_txpower_envelope(hapd, pos); + pos = hostapd_eid_wb_chsw_wrapper(hapd, pos); + } +#endif /* CONFIG_IEEE80211AC */ + +#ifdef CONFIG_IEEE80211AX + if (hapd->iconf->ieee80211ax) { + pos = hostapd_eid_he_capab(hapd, pos, IEEE80211_MODE_AP); + pos = hostapd_eid_he_operation(hapd, pos); + pos = hostapd_eid_he_mu_edca_parameter_set(hapd, pos); + pos = hostapd_eid_spatial_reuse(hapd, pos); + } +#endif /* CONFIG_IEEE80211AX */ + +#ifdef CONFIG_IEEE80211AC + if (hapd->conf->vendor_vht) + pos = hostapd_eid_vendor_vht(hapd, pos); +#endif /* CONFIG_IEEE80211AC */ + + /* WPA */ + if (hapd->conf->wpa == WPA_PROTO_WPA) + pos = hostapd_eid_wpa(hapd, pos, epos - pos); + + /* Wi-Fi Alliance WMM */ + pos = hostapd_eid_wmm(hapd, pos); + +#ifdef CONFIG_WPS + if (hapd->conf->wps_state && hapd->wps_probe_resp_ie) { + os_memcpy(pos, wpabuf_head(hapd->wps_probe_resp_ie), + wpabuf_len(hapd->wps_probe_resp_ie)); + pos += wpabuf_len(hapd->wps_probe_resp_ie); + } +#endif /* CONFIG_WPS */ + +#ifdef CONFIG_P2P + if ((hapd->conf->p2p & P2P_ENABLED) && is_p2p && + hapd->p2p_probe_resp_ie) { + os_memcpy(pos, wpabuf_head(hapd->p2p_probe_resp_ie), + wpabuf_len(hapd->p2p_probe_resp_ie)); + pos += wpabuf_len(hapd->p2p_probe_resp_ie); + } +#endif /* CONFIG_P2P */ +#ifdef CONFIG_P2P_MANAGER + if ((hapd->conf->p2p & (P2P_MANAGE | P2P_ENABLED | P2P_GROUP_OWNER)) == + P2P_MANAGE) + pos = hostapd_eid_p2p_manage(hapd, pos); +#endif /* CONFIG_P2P_MANAGER */ + +#ifdef CONFIG_HS20 + pos = hostapd_eid_hs20_indication(hapd, pos); + pos = hostapd_eid_osen(hapd, pos); +#endif /* CONFIG_HS20 */ + +#ifdef CONFIG_MBO + pos = hostapd_eid_mbo(hapd, pos, (u8 *) resp + buflen - pos); +#endif +#ifdef CONFIG_OWE + pos = hostapd_eid_owe_trans(hapd, pos, (u8 *) resp + buflen - pos); +#endif + + if (hapd->conf->vendor_elements) { + os_memcpy(pos, wpabuf_head(hapd->conf->vendor_elements), + wpabuf_len(hapd->conf->vendor_elements)); + pos += wpabuf_len(hapd->conf->vendor_elements); + } + + *resp_len = pos - (u8 *) resp; + return (u8 *) resp; +} + + +enum ssid_match_result { + NO_SSID_MATCH, + EXACT_SSID_MATCH, + WILDCARD_SSID_MATCH +}; + +static enum ssid_match_result ssid_match(struct hostapd_data *hapd, + const u8 *ssid, size_t ssid_len, + const u8 *ssid_list, + size_t ssid_list_len) +{ + const u8 *pos, *end; + int wildcard = 0; + + if (ssid_len == 0) + wildcard = 1; + if (ssid_len == hapd->conf->ssid.ssid_len && + os_memcmp(ssid, hapd->conf->ssid.ssid, ssid_len) == 0) + return EXACT_SSID_MATCH; + + if (ssid_list == NULL) + return wildcard ? WILDCARD_SSID_MATCH : NO_SSID_MATCH; + + pos = ssid_list; + end = ssid_list + ssid_list_len; + while (end - pos >= 2) { + if (2 + pos[1] > end - pos) + break; + if (pos[1] == 0) + wildcard = 1; + if (pos[1] == hapd->conf->ssid.ssid_len && + os_memcmp(pos + 2, hapd->conf->ssid.ssid, pos[1]) == 0) + return EXACT_SSID_MATCH; + pos += 2 + pos[1]; + } + + return wildcard ? WILDCARD_SSID_MATCH : NO_SSID_MATCH; +} + + +void sta_track_expire(struct hostapd_iface *iface, int force) +{ + struct os_reltime now; + struct hostapd_sta_info *info; + + if (!iface->num_sta_seen) + return; + + os_get_reltime(&now); + while (0 != (info = dl_list_first(&iface->sta_seen, struct hostapd_sta_info, + list))) { + if (!force && + !os_reltime_expired(&now, &info->last_seen, + iface->conf->track_sta_max_age)) + break; + force = 0; + + wpa_printf(MSG_MSGDUMP, "%s: Expire STA tracking entry for " + MACSTR, iface->bss[0]->conf->iface, + MAC2STR(info->addr)); + dl_list_del(&info->list); + iface->num_sta_seen--; + sta_track_del(info); + } +} + + +static struct hostapd_sta_info * sta_track_get(struct hostapd_iface *iface, + const u8 *addr) +{ + struct hostapd_sta_info *info; + + dl_list_for_each(info, &iface->sta_seen, struct hostapd_sta_info, list) + if (os_memcmp(addr, info->addr, ETH_ALEN) == 0) + return info; + + return NULL; +} + + +void sta_track_add(struct hostapd_iface *iface, const u8 *addr, int ssi_signal) +{ + struct hostapd_sta_info *info; + + info = sta_track_get(iface, addr); + if (info) { + /* Move the most recent entry to the end of the list */ + dl_list_del(&info->list); + dl_list_add_tail(&iface->sta_seen, &info->list); + os_get_reltime(&info->last_seen); + info->ssi_signal = ssi_signal; + return; + } + + /* Add a new entry */ + info = os_zalloc(sizeof(*info)); + if (info == NULL) + return; + os_memcpy(info->addr, addr, ETH_ALEN); + os_get_reltime(&info->last_seen); + info->ssi_signal = ssi_signal; + + if (iface->num_sta_seen >= iface->conf->track_sta_max_num) { + /* Expire oldest entry to make room for a new one */ + sta_track_expire(iface, 1); + } + + wpa_printf(MSG_MSGDUMP, "%s: Add STA tracking entry for " + MACSTR, iface->bss[0]->conf->iface, MAC2STR(addr)); + dl_list_add_tail(&iface->sta_seen, &info->list); + iface->num_sta_seen++; +} + + +struct hostapd_data * +sta_track_seen_on(struct hostapd_iface *iface, const u8 *addr, + const char *ifname) +{ + struct hapd_interfaces *interfaces = iface->interfaces; + size_t i, j; + + for (i = 0; i < interfaces->count; i++) { + struct hostapd_data *hapd = NULL; + + iface = interfaces->iface[i]; + for (j = 0; j < iface->num_bss; j++) { + hapd = iface->bss[j]; + if (os_strcmp(ifname, hapd->conf->iface) == 0) + break; + hapd = NULL; + } + + if (hapd && sta_track_get(iface, addr)) + return hapd; + } + + return NULL; +} + + +void handle_probe_req(struct hostapd_data *hapd, + const struct ieee80211_mgmt *mgmt, size_t len, + int ssi_signal) +{ + u8 *resp; + struct ieee802_11_elems elems; + const u8 *ie; + size_t ie_len; + size_t resp_len; + int noack; + enum ssid_match_result res; + int ret; + u16 csa_offs[2]; + size_t csa_offs_len; + + if (len < IEEE80211_HDRLEN) + return; + ie = ((const u8 *) mgmt) + IEEE80211_HDRLEN; + if (hapd->iconf->track_sta_max_num) + sta_track_add(hapd->iface, mgmt->sa, ssi_signal); + ie_len = len - IEEE80211_HDRLEN; + +#ifdef CONFIG_FULL_HOSTAPD + for (int i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++) + if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx, + mgmt->sa, mgmt->da, mgmt->bssid, + ie, ie_len, ssi_signal) > 0) + return; +#endif + + if (!hapd->conf->send_probe_response) + return; + + if (ieee802_11_parse_elems(ie, ie_len, &elems, 0) == ParseFailed) { + wpa_printf(MSG_DEBUG, "Could not parse ProbeReq from " MACSTR, + MAC2STR(mgmt->sa)); + return; + } + + if ((!elems.ssid || !elems.supp_rates)) { + wpa_printf(MSG_DEBUG, "STA " MACSTR " sent probe request " + "without SSID or supported rates element", + MAC2STR(mgmt->sa)); + return; + } + + /* + * No need to reply if the Probe Request frame was sent on an adjacent + * channel. IEEE Std 802.11-2012 describes this as a requirement for an + * AP with dot11RadioMeasurementActivated set to true, but strictly + * speaking does not allow such ignoring of Probe Request frames if + * dot11RadioMeasurementActivated is false. Anyway, this can help reduce + * number of unnecessary Probe Response frames for cases where the STA + * is less likely to see them (Probe Request frame sent on a + * neighboring, but partially overlapping, channel). + */ + if (elems.ds_params && + hapd->iface->current_mode && + (hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G || + hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211B) && + hapd->iconf->channel != elems.ds_params[0]) { +#if 0 + wpa_printf(MSG_DEBUG, + "Ignore Probe Request due to DS Params mismatch: chan=%u != ds.chan=%u", + hapd->iconf->channel, elems.ds_params[0]); +#endif + return; + } + + if (hapd->conf->ignore_broadcast_ssid && elems.ssid_len == 0 && + elems.ssid_list_len == 0) { + wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR " for " + "broadcast SSID ignored", MAC2STR(mgmt->sa)); + return; + } + +#ifdef CONFIG_P2P + if ((hapd->conf->p2p & P2P_GROUP_OWNER) && + elems.ssid_len == P2P_WILDCARD_SSID_LEN && + os_memcmp(elems.ssid, P2P_WILDCARD_SSID, + P2P_WILDCARD_SSID_LEN) == 0) { + /* Process P2P Wildcard SSID like Wildcard SSID */ + elems.ssid_len = 0; + } +#endif /* CONFIG_P2P */ + + res = ssid_match(hapd, elems.ssid, elems.ssid_len, + elems.ssid_list, elems.ssid_list_len); + if (res == NO_SSID_MATCH) { + if (!(mgmt->da[0] & 0x01)) { + wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR + " for foreign SSID '%s' (DA " MACSTR ")%s", + MAC2STR(mgmt->sa), + wpa_ssid_txt(elems.ssid, elems.ssid_len), + MAC2STR(mgmt->da), + elems.ssid_list ? " (SSID list)" : ""); + } + return; + } + +#ifdef CONFIG_INTERWORKING + if (hapd->conf->interworking && + elems.interworking && elems.interworking_len >= 1) { + u8 ant = elems.interworking[0] & 0x0f; + if (ant != INTERWORKING_ANT_WILDCARD && + ant != hapd->conf->access_network_type) { + wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR + " for mismatching ANT %u ignored", + MAC2STR(mgmt->sa), ant); + return; + } + } + + if (hapd->conf->interworking && elems.interworking && + (elems.interworking_len == 7 || elems.interworking_len == 9)) { + const u8 *hessid; + if (elems.interworking_len == 7) + hessid = elems.interworking + 1; + else + hessid = elems.interworking + 1 + 2; + if (!is_broadcast_ether_addr(hessid) && + os_memcmp(hessid, hapd->conf->hessid, ETH_ALEN) != 0) { + wpa_printf(MSG_MSGDUMP, "Probe Request from " MACSTR + " for mismatching HESSID " MACSTR + " ignored", + MAC2STR(mgmt->sa), MAC2STR(hessid)); + return; + } + } +#endif /* CONFIG_INTERWORKING */ + +#ifdef CONFIG_P2P + if ((hapd->conf->p2p & P2P_GROUP_OWNER) && + supp_rates_11b_only(&elems)) { + /* Indicates support for 11b rates only */ + wpa_printf(MSG_EXCESSIVE, "P2P: Ignore Probe Request from " + MACSTR " with only 802.11b rates", + MAC2STR(mgmt->sa)); + return; + } +#endif /* CONFIG_P2P */ + + /* TODO: verify that supp_rates contains at least one matching rate + * with AP configuration */ + + if (hapd->conf->no_probe_resp_if_seen_on && + is_multicast_ether_addr(mgmt->da) && + is_multicast_ether_addr(mgmt->bssid) && + sta_track_seen_on(hapd->iface, mgmt->sa, + hapd->conf->no_probe_resp_if_seen_on)) { + wpa_printf(MSG_MSGDUMP, "%s: Ignore Probe Request from " MACSTR + " since STA has been seen on %s", + hapd->conf->iface, MAC2STR(mgmt->sa), + hapd->conf->no_probe_resp_if_seen_on); + return; + } + + if (hapd->conf->no_probe_resp_if_max_sta && + is_multicast_ether_addr(mgmt->da) && + is_multicast_ether_addr(mgmt->bssid) && + hapd->num_sta >= hapd->conf->max_num_sta && + !ap_get_sta(hapd, mgmt->sa)) { + wpa_printf(MSG_MSGDUMP, "%s: Ignore Probe Request from " MACSTR + " since no room for additional STA", + hapd->conf->iface, MAC2STR(mgmt->sa)); + return; + } + +#ifdef CONFIG_TESTING_OPTIONS + if (hapd->iconf->ignore_probe_probability > 0.0 && + drand48() < hapd->iconf->ignore_probe_probability) { + wpa_printf(MSG_INFO, + "TESTING: ignoring probe request from " MACSTR, + MAC2STR(mgmt->sa)); + return; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + wpa_msg_ctrl(hapd->msg_ctx, MSG_INFO, RX_PROBE_REQUEST "sa=" MACSTR + " signal=%d", MAC2STR(mgmt->sa), ssi_signal); + + resp = hostapd_gen_probe_resp(hapd, mgmt, elems.p2p != NULL, + &resp_len); + if (resp == NULL) + return; + + /* + * If this is a broadcast probe request, apply no ack policy to avoid + * excessive retries. + */ + noack = !!(res == WILDCARD_SSID_MATCH && + is_broadcast_ether_addr(mgmt->da)); + + csa_offs_len = 0; + if (hapd->csa_in_progress) { + if (hapd->cs_c_off_proberesp) + csa_offs[csa_offs_len++] = + hapd->cs_c_off_proberesp; + + if (hapd->cs_c_off_ecsa_proberesp) + csa_offs[csa_offs_len++] = + hapd->cs_c_off_ecsa_proberesp; + } + + ret = hostapd_drv_send_mlme_csa(hapd, resp, resp_len, noack, + csa_offs_len ? csa_offs : NULL, + csa_offs_len); + + if (ret < 0) + wpa_printf(MSG_INFO, "handle_probe_req: send failed"); + + os_free(resp); + + wpa_printf(MSG_EXCESSIVE, "STA " MACSTR " sent probe request for %s " + "SSID", MAC2STR(mgmt->sa), + elems.ssid_len == 0 ? "broadcast" : "our"); +} + + +static u8 * hostapd_probe_resp_offloads(struct hostapd_data *hapd, + size_t *resp_len) +{ + /* check probe response offloading caps and print warnings */ + if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_PROBE_RESP_OFFLOAD)) + return NULL; + +#ifdef CONFIG_WPS + if (hapd->conf->wps_state && hapd->wps_probe_resp_ie && + (!(hapd->iface->probe_resp_offloads & + (WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS | + WPA_DRIVER_PROBE_RESP_OFFLOAD_WPS2)))) + wpa_printf(MSG_WARNING, "Device is trying to offload WPS " + "Probe Response while not supporting this"); +#endif /* CONFIG_WPS */ + +#ifdef CONFIG_P2P + if ((hapd->conf->p2p & P2P_ENABLED) && hapd->p2p_probe_resp_ie && + !(hapd->iface->probe_resp_offloads & + WPA_DRIVER_PROBE_RESP_OFFLOAD_P2P)) + wpa_printf(MSG_WARNING, "Device is trying to offload P2P " + "Probe Response while not supporting this"); +#endif /* CONFIG_P2P */ + +#ifdef CONFIG_INTERWORKING + if (hapd->conf->interworking && + !(hapd->iface->probe_resp_offloads & + WPA_DRIVER_PROBE_RESP_OFFLOAD_INTERWORKING)) + wpa_printf(MSG_WARNING, "Device is trying to offload " + "Interworking Probe Response while not supporting " + "this"); +#endif + + /* Generate a Probe Response template for the non-P2P case */ + return hostapd_gen_probe_resp(hapd, NULL, 0, resp_len); +} + +#endif /* NEED_AP_MLME */ + + +void sta_track_del(struct hostapd_sta_info *info) +{ +#ifdef CONFIG_TAXONOMY + wpabuf_free(info->probe_ie_taxonomy); + info->probe_ie_taxonomy = NULL; +#endif /* CONFIG_TAXONOMY */ + os_free(info); +} + + +int ieee802_11_build_ap_params(struct hostapd_data *hapd, + struct wpa_driver_ap_params *params) +{ + struct ieee80211_mgmt *head = NULL; + u8 *tail = NULL; + size_t head_len = 0, tail_len = 0; + u8 *resp = NULL; + size_t resp_len = 0; +#ifdef NEED_AP_MLME + u16 capab_info; + u8 *pos, *tailpos, *csa_pos; + +#define BEACON_HEAD_BUF_SIZE 256 +#define BEACON_TAIL_BUF_SIZE 512 + head = os_zalloc(BEACON_HEAD_BUF_SIZE); + tail_len = BEACON_TAIL_BUF_SIZE; + + if (hapd->conf->vendor_elements) + tail_len += wpabuf_len(hapd->conf->vendor_elements); + +#ifdef CONFIG_IEEE80211AC + if (hapd->conf->vendor_vht) { + tail_len += 5 + 2 + sizeof(struct ieee80211_vht_capabilities) + + 2 + sizeof(struct ieee80211_vht_operation); + } +#endif /* CONFIG_IEEE80211AC */ + +#ifdef CONFIG_IEEE80211AX + if (hapd->iconf->ieee80211ax) { + tail_len += 3 + sizeof(struct ieee80211_he_capabilities) + + 3 + sizeof(struct ieee80211_he_operation) + + 3 + sizeof(struct ieee80211_he_mu_edca_parameter_set) + + 3 + sizeof(struct ieee80211_spatial_reuse); + } +#endif /* CONFIG_IEEE80211AX */ + +#ifdef CONFIG_MBO + tail_len += hostapd_mbo_ie_len(hapd); +#endif +#ifdef CONFIG_OWE + tail_len += hostapd_eid_owe_trans_len(hapd); +#endif + + tailpos = tail = os_malloc(tail_len); + if (head == NULL || tail == NULL) { + wpa_printf(MSG_ERROR, "Failed to set beacon data"); + os_free(head); + os_free(tail); + return -1; + } + + head->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, + WLAN_FC_STYPE_BEACON); + head->duration = host_to_le16(0); + os_memset(head->da, 0xff, ETH_ALEN); + + os_memcpy(head->sa, hapd->own_addr, ETH_ALEN); + os_memcpy(head->bssid, hapd->own_addr, ETH_ALEN); + head->u.beacon.beacon_int = + host_to_le16(hapd->iconf->beacon_int); + + /* hardware or low-level driver will setup seq_ctrl and timestamp */ + capab_info = hostapd_own_capab_info(hapd); + head->u.beacon.capab_info = host_to_le16(capab_info); + pos = &head->u.beacon.variable[0]; + + /* SSID */ + *pos++ = WLAN_EID_SSID; + if (hapd->conf->ignore_broadcast_ssid == 2) { + /* clear the data, but keep the correct length of the SSID */ + *pos++ = hapd->conf->ssid.ssid_len; + os_memset(pos, 0, hapd->conf->ssid.ssid_len); + pos += hapd->conf->ssid.ssid_len; + } else if (hapd->conf->ignore_broadcast_ssid) { + *pos++ = 0; /* empty SSID */ + } else { + *pos++ = hapd->conf->ssid.ssid_len; + os_memcpy(pos, hapd->conf->ssid.ssid, + hapd->conf->ssid.ssid_len); + pos += hapd->conf->ssid.ssid_len; + } + + /* Supported rates */ + pos = hostapd_eid_supp_rates(hapd, pos); + + /* DS Params */ + pos = hostapd_eid_ds_params(hapd, pos); + + head_len = pos - (u8 *) head; + + tailpos = hostapd_eid_country(hapd, tailpos, + tail + BEACON_TAIL_BUF_SIZE - tailpos); + +#ifdef CONFIG_FULL_HOSTAPD + /* Power Constraint element */ + tailpos = hostapd_eid_pwr_constraint(hapd, tailpos); +#endif + /* CSA IE */ + csa_pos = hostapd_eid_csa(hapd, tailpos); + if (csa_pos != tailpos) + hapd->cs_c_off_beacon = csa_pos - tail - 1; + tailpos = csa_pos; + + /* ERP Information element */ + tailpos = hostapd_eid_erp_info(hapd, tailpos); + + /* Extended supported rates */ + tailpos = hostapd_eid_ext_supp_rates(hapd, tailpos); + + /* RSN, MDIE */ + if (hapd->conf->wpa != WPA_PROTO_WPA) + tailpos = hostapd_eid_wpa(hapd, tailpos, + tail + BEACON_TAIL_BUF_SIZE - + tailpos); + +#ifdef CONFIG_FULL_HOSTAPD + tailpos = hostapd_eid_rm_enabled_capab(hapd, tailpos, + tail + BEACON_TAIL_BUF_SIZE - + tailpos); + + tailpos = hostapd_eid_bss_load(hapd, tailpos, + tail + BEACON_TAIL_BUF_SIZE - tailpos); +#endif + /* eCSA IE */ + csa_pos = hostapd_eid_ecsa(hapd, tailpos); + if (csa_pos != tailpos) + hapd->cs_c_off_ecsa_beacon = csa_pos - tail - 1; + tailpos = csa_pos; + + tailpos = hostapd_eid_supported_op_classes(hapd, tailpos); + +#ifdef CONFIG_IEEE80211N + /* Secondary Channel Offset element */ + /* TODO: The standard doesn't specify a position for this element. */ + tailpos = hostapd_eid_secondary_channel(hapd, tailpos); + + tailpos = hostapd_eid_ht_capabilities(hapd, tailpos); + tailpos = hostapd_eid_ht_operation(hapd, tailpos); +#endif /* CONFIG_IEEE80211N */ + + tailpos = hostapd_eid_ext_capab(hapd, tailpos); + +#ifdef CONFIG_FULL_HOSTAPD + /* + * TODO: Time Advertisement element should only be included in some + * DTIM Beacon frames. + */ + tailpos = hostapd_eid_time_adv(hapd, tailpos); + + tailpos = hostapd_eid_interworking(hapd, tailpos); + tailpos = hostapd_eid_adv_proto(hapd, tailpos); + tailpos = hostapd_eid_roaming_consortium(hapd, tailpos); +#endif + +#ifdef CONFIG_IEEE80211AC + if (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) { + tailpos = hostapd_eid_vht_capabilities(hapd, tailpos, 0); + tailpos = hostapd_eid_vht_operation(hapd, tailpos); + tailpos = hostapd_eid_txpower_envelope(hapd, tailpos); + tailpos = hostapd_eid_wb_chsw_wrapper(hapd, tailpos); + } +#endif /* CONFIG_IEEE80211AC */ + +#ifdef CONFIG_IEEE80211AX + if (hapd->iconf->ieee80211ax) { + tailpos = hostapd_eid_he_capab(hapd, tailpos, + IEEE80211_MODE_AP); + tailpos = hostapd_eid_he_operation(hapd, tailpos); + tailpos = hostapd_eid_he_mu_edca_parameter_set(hapd, tailpos); + tailpos = hostapd_eid_spatial_reuse(hapd, tailpos); + } +#endif /* CONFIG_IEEE80211AX */ + +#ifdef CONFIG_IEEE80211AC + if (hapd->conf->vendor_vht) + tailpos = hostapd_eid_vendor_vht(hapd, tailpos); +#endif /* CONFIG_IEEE80211AC */ + + /* WPA */ + if (hapd->conf->wpa == WPA_PROTO_WPA) + tailpos = hostapd_eid_wpa(hapd, tailpos, + tail + BEACON_TAIL_BUF_SIZE - + tailpos); + + /* Wi-Fi Alliance WMM */ + tailpos = hostapd_eid_wmm(hapd, tailpos); +#ifdef CONFIG_MBO + tailpos = hostapd_eid_mbo(hapd, tailpos, tail + tail_len - tailpos); +#endif +#ifdef CONFIG_OWE + tailpos = hostapd_eid_owe_trans(hapd, tailpos, + tail + tail_len - tailpos); +#endif + + if (hapd->conf->vendor_elements) { + os_memcpy(tailpos, wpabuf_head(hapd->conf->vendor_elements), + wpabuf_len(hapd->conf->vendor_elements)); + tailpos += wpabuf_len(hapd->conf->vendor_elements); + } + + tail_len = tailpos > tail ? tailpos - tail : 0; + +#ifdef CONFIG_FULL_HOSTAPD + resp = hostapd_probe_resp_offloads(hapd, &resp_len); +#endif +#endif /* NEED_AP_MLME */ + + os_memset(params, 0, sizeof(*params)); + params->head = (u8 *) head; + params->head_len = head_len; + params->tail = tail; + params->tail_len = tail_len; + params->proberesp = resp; + params->proberesp_len = resp_len; + params->dtim_period = hapd->conf->dtim_period; + params->beacon_int = hapd->iconf->beacon_int; + params->basic_rates = hapd->iface->basic_rates; + params->beacon_rate = hapd->iconf->beacon_rate; + params->rate_type = hapd->iconf->rate_type; + params->ssid = hapd->conf->ssid.ssid; + params->ssid_len = hapd->conf->ssid.ssid_len; + if ((hapd->conf->wpa & (WPA_PROTO_WPA | WPA_PROTO_RSN)) == + (WPA_PROTO_WPA | WPA_PROTO_RSN)) + params->pairwise_ciphers = hapd->conf->wpa_pairwise | + hapd->conf->rsn_pairwise; + else if (hapd->conf->wpa & WPA_PROTO_RSN) + params->pairwise_ciphers = hapd->conf->rsn_pairwise; + else if (hapd->conf->wpa & WPA_PROTO_WPA) + params->pairwise_ciphers = hapd->conf->wpa_pairwise; + params->group_cipher = hapd->conf->wpa_group; + params->key_mgmt_suites = hapd->conf->wpa_key_mgmt; + params->auth_algs = hapd->conf->auth_algs; + params->wpa_version = hapd->conf->wpa; + params->privacy = hapd->conf->ssid.wep.keys_set || hapd->conf->wpa || + (hapd->conf->ieee802_1x && + (hapd->conf->default_wep_key_len || + hapd->conf->individual_wep_key_len)); + switch (hapd->conf->ignore_broadcast_ssid) { + case 0: + params->hide_ssid = NO_SSID_HIDING; + break; + case 1: + params->hide_ssid = HIDDEN_SSID_ZERO_LEN; + break; + case 2: + params->hide_ssid = HIDDEN_SSID_ZERO_CONTENTS; + break; + } + params->isolate = hapd->conf->isolate; + params->smps_mode = hapd->iconf->ht_capab & HT_CAP_INFO_SMPS_MASK; +#ifdef NEED_AP_MLME + params->cts_protect = !!(ieee802_11_erp_info(hapd) & + ERP_INFO_USE_PROTECTION); + params->preamble = hapd->iface->num_sta_no_short_preamble == 0 && + hapd->iconf->preamble == SHORT_PREAMBLE; + if (hapd->iface->current_mode && + hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G) + params->short_slot_time = + hapd->iface->num_sta_no_short_slot_time > 0 ? 0 : 1; + else + params->short_slot_time = -1; + if (!hapd->iconf->ieee80211n || hapd->conf->disable_11n) + params->ht_opmode = -1; + else + params->ht_opmode = hapd->iface->ht_op_mode; +#endif /* NEED_AP_MLME */ +#ifdef CONFIG_INTERWORKING + params->interworking = hapd->conf->interworking; + if (hapd->conf->interworking && + !is_zero_ether_addr(hapd->conf->hessid)) + params->hessid = hapd->conf->hessid; + params->access_network_type = hapd->conf->access_network_type; +#endif + params->ap_max_inactivity = hapd->conf->ap_max_inactivity; +#ifdef CONFIG_P2P + params->p2p_go_ctwindow = hapd->iconf->p2p_go_ctwindow; +#endif /* CONFIG_P2P */ +#ifdef CONFIG_HS20 + params->disable_dgaf = hapd->conf->disable_dgaf; + if (hapd->conf->osen) { + params->privacy = 1; + params->osen = 1; + } +#endif /* CONFIG_HS20 */ + params->multicast_to_unicast = hapd->conf->multicast_to_unicast; + return 0; +} + + +void ieee802_11_free_ap_params(struct wpa_driver_ap_params *params) +{ + os_free(params->tail); + params->tail = NULL; + os_free(params->head); + params->head = NULL; + os_free(params->proberesp); + params->proberesp = NULL; +} + + +int ieee802_11_set_beacon(struct hostapd_data *hapd) +{ + struct wpa_driver_ap_params params; + struct hostapd_freq_params freq; + struct hostapd_iface *iface = hapd->iface; + struct hostapd_config *iconf = iface->conf; + struct hostapd_hw_modes *cmode = iface->current_mode; + struct wpabuf *beacon, *proberesp, *assocresp; + int res, ret = -1; + + if (hapd->csa_in_progress) { + wpa_printf(MSG_ERROR, "Cannot set beacons during CSA period"); + return -1; + } + + hapd->beacon_set_done = 1; + + if (ieee802_11_build_ap_params(hapd, ¶ms) < 0) + return -1; + + if (hostapd_build_ap_extra_ies(hapd, &beacon, &proberesp, &assocresp) < + 0) + goto fail; + + params.beacon_ies = beacon; + params.proberesp_ies = proberesp; + params.assocresp_ies = assocresp; + params.reenable = hapd->reenable_beacon; + hapd->reenable_beacon = 0; + + if (cmode && + hostapd_set_freq_params(&freq, iconf->hw_mode, iface->freq, + iconf->channel, iconf->ieee80211n, + iconf->ieee80211ac, iconf->ieee80211ax, + iconf->secondary_channel, + hostapd_get_oper_chwidth(iconf), + hostapd_get_oper_centr_freq_seg0_idx(iconf), + hostapd_get_oper_centr_freq_seg1_idx(iconf), + cmode->vht_capab, +#ifdef CONFIG_IEEE80211AX + &cmode->he_capab[IEEE80211_MODE_AP] +#else + NULL +#endif + ) == 0) + params.freq = &freq; + + res = hostapd_drv_set_ap(hapd, ¶ms); + hostapd_free_ap_extra_ies(hapd, beacon, proberesp, assocresp); + if (res) + wpa_printf(MSG_ERROR, "Failed to set beacon parameters"); + else + ret = 0; +fail: + ieee802_11_free_ap_params(¶ms); + return ret; +} + + +int ieee802_11_set_beacons(struct hostapd_iface *iface) +{ + size_t i; + int ret = 0; + + for (i = 0; i < iface->num_bss; i++) { + if (iface->bss[i]->started && + ieee802_11_set_beacon(iface->bss[i]) < 0) + ret = -1; + } + + return ret; +} + + +/* only update beacons if started */ +int ieee802_11_update_beacons(struct hostapd_iface *iface) +{ + size_t i; + int ret = 0; + + for (i = 0; i < iface->num_bss; i++) { + if (iface->bss[i]->beacon_set_done && iface->bss[i]->started && + ieee802_11_set_beacon(iface->bss[i]) < 0) + ret = -1; + } + + return ret; +} + +#endif /* CONFIG_NATIVE_WINDOWS */ diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/beacon.h b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/beacon.h new file mode 100755 index 0000000..23220f4 --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/beacon.h @@ -0,0 +1,31 @@ +/* + * hostapd / IEEE 802.11 Management: Beacon and Probe Request/Response + * Copyright (c) 2002-2004, Instant802 Networks, Inc. + * Copyright (c) 2005-2006, Devicescape Software, Inc. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef BEACON_H +#define BEACON_H + +struct ieee80211_mgmt; + +void handle_probe_req(struct hostapd_data *hapd, + const struct ieee80211_mgmt *mgmt, size_t len, + int ssi_signal); +int ieee802_11_set_beacon(struct hostapd_data *hapd); +int ieee802_11_set_beacons(struct hostapd_iface *iface); +int ieee802_11_update_beacons(struct hostapd_iface *iface); +int ieee802_11_build_ap_params(struct hostapd_data *hapd, + struct wpa_driver_ap_params *params); +void ieee802_11_free_ap_params(struct wpa_driver_ap_params *params); +void sta_track_add(struct hostapd_iface *iface, const u8 *addr, int ssi_signal); +void sta_track_del(struct hostapd_sta_info *info); +void sta_track_expire(struct hostapd_iface *iface, int force); +struct hostapd_data * +sta_track_seen_on(struct hostapd_iface *iface, const u8 *addr, + const char *ifname); + +#endif /* BEACON_H */ diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/bss_load.h b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/bss_load.h new file mode 100755 index 0000000..ac3c793 --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/bss_load.h @@ -0,0 +1,17 @@ +/* + * BSS load update + * Copyright (c) 2014, Qualcomm Atheros, Inc. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef BSS_LOAD_UPDATE_H +#define BSS_LOAD_UPDATE_H + + +int bss_load_update_init(struct hostapd_data *hapd); +void bss_load_update_deinit(struct hostapd_data *hapd); + + +#endif /* BSS_LOAD_UPDATE_H */ diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/dfs.h b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/dfs.h new file mode 100755 index 0000000..f0fa6f6 --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/dfs.h @@ -0,0 +1,33 @@ +/* + * DFS - Dynamic Frequency Selection + * Copyright (c) 2002-2013, Jouni Malinen + * Copyright (c) 2013-2017, Qualcomm Atheros, Inc. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ +#ifndef DFS_H +#define DFS_H + +int hostapd_handle_dfs(struct hostapd_iface *iface); + +int hostapd_dfs_complete_cac(struct hostapd_iface *iface, int success, int freq, + int ht_enabled, int chan_offset, int chan_width, + int cf1, int cf2); +int hostapd_dfs_pre_cac_expired(struct hostapd_iface *iface, int freq, + int ht_enabled, int chan_offset, int chan_width, + int cf1, int cf2); +int hostapd_dfs_radar_detected(struct hostapd_iface *iface, int freq, + int ht_enabled, + int chan_offset, int chan_width, + int cf1, int cf2); +int hostapd_dfs_nop_finished(struct hostapd_iface *iface, int freq, + int ht_enabled, + int chan_offset, int chan_width, int cf1, int cf2); +int hostapd_is_dfs_required(struct hostapd_iface *iface); +int hostapd_dfs_start_cac(struct hostapd_iface *iface, int freq, + int ht_enabled, int chan_offset, int chan_width, + int cf1, int cf2); +int hostapd_handle_dfs_offload(struct hostapd_iface *iface); + +#endif /* DFS_H */ diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/dpp_hostapd.h b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/dpp_hostapd.h new file mode 100755 index 0000000..c1ec5d7 --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/dpp_hostapd.h @@ -0,0 +1,38 @@ +/* + * hostapd / DPP integration + * Copyright (c) 2017, Qualcomm Atheros, Inc. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef DPP_HOSTAPD_H +#define DPP_HOSTAPD_H + +int hostapd_dpp_qr_code(struct hostapd_data *hapd, const char *cmd); +int hostapd_dpp_auth_init(struct hostapd_data *hapd, const char *cmd); +int hostapd_dpp_listen(struct hostapd_data *hapd, const char *cmd); +void hostapd_dpp_listen_stop(struct hostapd_data *hapd); +void hostapd_dpp_rx_action(struct hostapd_data *hapd, const u8 *src, + const u8 *buf, size_t len, unsigned int freq); +void hostapd_dpp_tx_status(struct hostapd_data *hapd, const u8 *dst, + const u8 *data, size_t data_len, int ok); +struct wpabuf * +hostapd_dpp_gas_req_handler(struct hostapd_data *hapd, const u8 *sa, + const u8 *query, size_t query_len, + const u8 *data, size_t data_len); +void hostapd_dpp_gas_status_handler(struct hostapd_data *hapd, int ok); +int hostapd_dpp_configurator_add(struct hostapd_data *hapd, const char *cmd); +int hostapd_dpp_configurator_remove(struct hostapd_data *hapd, const char *id); +int hostapd_dpp_configurator_sign(struct hostapd_data *hapd, const char *cmd); +int hostapd_dpp_configurator_get_key(struct hostapd_data *hapd, unsigned int id, + char *buf, size_t buflen); +int hostapd_dpp_pkex_add(struct hostapd_data *hapd, const char *cmd); +int hostapd_dpp_pkex_remove(struct hostapd_data *hapd, const char *id); +void hostapd_dpp_stop(struct hostapd_data *hapd); +int hostapd_dpp_init(struct hostapd_data *hapd); +void hostapd_dpp_deinit(struct hostapd_data *hapd); +void hostapd_dpp_init_global(struct hapd_interfaces *ifaces); +void hostapd_dpp_deinit_global(struct hapd_interfaces *ifaces); + +#endif /* DPP_HOSTAPD_H */ diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/drv_callbacks.c b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/drv_callbacks.c new file mode 100755 index 0000000..3ef0765 --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/drv_callbacks.c @@ -0,0 +1,1753 @@ +/* + * hostapd / Callback functions for driver wrappers + * Copyright (c) 2002-2013, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "utils/eloop.h" +#include "drivers/driver.h" +#include "common/ieee802_11_defs.h" +#include "common/ieee802_11_common.h" +#include "common/wpa_ctrl.h" +#include "common/dpp.h" +#include "crypto/random.h" +#include "wps/wps.h" +#include "ap/hostapd.h" +#include "ieee802_11.h" +#include "ieee802_11_auth.h" +#include "ap/sta_info.h" +#include "accounting.h" +#include "tkip_countermeasures.h" +#include "ieee802_1x.h" +#include "wpa_auth.h" +#include "wps_hostapd.h" +#include "ap_drv_ops.h" +#include "ap_config.h" +#include "ap_mlme.h" +#include "hw_features.h" +#include "ap/dfs.h" +#include "beacon.h" +#include "hostapd_cfg.h" +#include "dpp_hostapd.h" +#include "include.h" + +#if CFG_ROLE_LAUNCH +#include "role_launch.h" +#endif + +int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr, + const u8 *req_ies, size_t req_ies_len, int reassoc) +{ + struct sta_info *sta; + int new_assoc, res; + struct ieee802_11_elems elems; + const u8 *ie; + size_t ielen; +#if defined(CONFIG_IEEE80211R_AP) || defined(CONFIG_IEEE80211W_AP) || defined(CONFIG_FILS) || defined(CONFIG_OWE) + u8 buf[sizeof(struct ieee80211_mgmt) + 1024]; + u8 *p = buf; +#endif /* CONFIG_IEEE80211R_AP || CONFIG_IEEE80211W_AP || CONFIG_FILS || CONFIG_OWE */ + u16 reason = WLAN_REASON_UNSPECIFIED; + u16 status = WLAN_STATUS_SUCCESS; + const u8 *p2p_dev_addr = NULL; + + if (addr == NULL) { + /* + * This could potentially happen with unexpected event from the + * driver wrapper. This was seen at least in one case where the + * driver ended up being set to station mode while hostapd was + * running, so better make sure we stop processing such an + * event here. + */ + wpa_printf(MSG_DEBUG, + "hostapd_notif_assoc: Skip event with no address"); + return -1; + } + random_add_randomness(addr, ETH_ALEN); + + hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, "associated"); + + ieee802_11_parse_elems(req_ies, req_ies_len, &elems, 0); + if (elems.wps_ie) { + ie = elems.wps_ie - 2; + ielen = elems.wps_ie_len + 2; + wpa_printf(MSG_DEBUG, "STA included WPS IE in (Re)AssocReq"); + } else if (elems.rsn_ie) { + ie = elems.rsn_ie - 2; + ielen = elems.rsn_ie_len + 2; + wpa_printf(MSG_DEBUG, "STA included RSN IE in (Re)AssocReq"); + } else if (elems.wpa_ie) { + ie = elems.wpa_ie - 2; + ielen = elems.wpa_ie_len + 2; + wpa_printf(MSG_DEBUG, "STA included WPA IE in (Re)AssocReq"); +#ifdef CONFIG_HS20 + } else if (elems.osen) { + ie = elems.osen - 2; + ielen = elems.osen_len + 2; + wpa_printf(MSG_DEBUG, "STA included OSEN IE in (Re)AssocReq"); +#endif /* CONFIG_HS20 */ + } else { + ie = NULL; + ielen = 0; + wpa_printf(MSG_DEBUG, + "STA did not include WPS/RSN/WPA IE in (Re)AssocReq"); + } + + sta = ap_get_sta(hapd, addr); + if (sta) { + ap_sta_no_session_timeout(hapd, sta); + accounting_sta_stop(hapd, sta); + + /* + * Make sure that the previously registered inactivity timer + * will not remove the STA immediately. + */ + sta->timeout_next = STA_NULLFUNC; + } else { + sta = ap_sta_add(hapd, addr); + if (sta == NULL) { + hostapd_drv_sta_disassoc(hapd, addr, + WLAN_REASON_DISASSOC_AP_BUSY); + return -1; + } + } + sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS | WLAN_STA_WPS2); + +#ifdef CONFIG_HOSTAPD_ACL + /* + * ACL configurations to the drivers (implementing AP SME and ACL + * offload) without hostapd's knowledge, can result in a disconnection + * though the driver accepts the connection. Skip the hostapd check for + * ACL if the driver supports ACL offload to avoid potentially + * conflicting ACL rules. + */ + if (hapd->iface->drv_max_acl_mac_addrs == 0 && + hostapd_check_acl(hapd, addr, NULL) != HOSTAPD_ACL_ACCEPT) { + wpa_printf(MSG_INFO, "STA " MACSTR " not allowed to connect", + MAC2STR(addr)); + reason = WLAN_REASON_UNSPECIFIED; + goto fail; + } +#endif + +#ifdef CONFIG_P2P + if (elems.p2p) { + wpabuf_free(sta->p2p_ie); + sta->p2p_ie = ieee802_11_vendor_ie_concat(req_ies, req_ies_len, + P2P_IE_VENDOR_TYPE); + if (sta->p2p_ie) + p2p_dev_addr = p2p_get_go_dev_addr(sta->p2p_ie); + } +#endif /* CONFIG_P2P */ + +#ifdef CONFIG_IEEE80211N +#ifdef NEED_AP_MLME + if (elems.ht_capabilities && + (hapd->iface->conf->ht_capab & + HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) { + struct ieee80211_ht_capabilities *ht_cap = + (struct ieee80211_ht_capabilities *) + elems.ht_capabilities; + + if (le_to_host16(ht_cap->ht_capabilities_info) & + HT_CAP_INFO_40MHZ_INTOLERANT) + ht40_intolerant_add(hapd->iface, sta); + } +#endif /* NEED_AP_MLME */ +#endif /* CONFIG_IEEE80211N */ +#ifdef CONFIG_MBO + mbo_ap_check_sta_assoc(hapd, sta, &elems); +#endif + ap_copy_sta_supp_op_classes(sta, elems.supp_op_classes, + elems.supp_op_classes_len); + + if (hapd->conf->wpa) { + if (ie == NULL || ielen == 0) { +#ifdef CONFIG_WPS + if (hapd->conf->wps_state) { + wpa_printf(MSG_DEBUG, + "STA did not include WPA/RSN IE in (Re)Association Request - possible WPS use"); + sta->flags |= WLAN_STA_MAYBE_WPS; + goto skip_wpa_check; + } +#endif /* CONFIG_WPS */ + + wpa_printf(MSG_DEBUG, "No WPA/RSN IE from STA"); + reason = WLAN_REASON_INVALID_IE; + status = WLAN_STATUS_INVALID_IE; + goto fail; + } +#ifdef CONFIG_WPS + if (hapd->conf->wps_state && ie[0] == 0xdd && ie[1] >= 4 && + os_memcmp(ie + 2, "\x00\x50\xf2\x04", 4) == 0) { + struct wpabuf *wps; + + sta->flags |= WLAN_STA_WPS; + wps = ieee802_11_vendor_ie_concat(ie, ielen, + WPS_IE_VENDOR_TYPE); + if (wps) { + if (wps_is_20(wps)) { + wpa_printf(MSG_DEBUG, + "WPS: STA supports WPS 2.0"); + sta->flags |= WLAN_STA_WPS2; + } + wpabuf_free(wps); + } + goto skip_wpa_check; + } +#endif /* CONFIG_WPS */ + + if (sta->wpa_sm == NULL) + sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, + sta->addr, + p2p_dev_addr); + if (sta->wpa_sm == NULL) { + wpa_printf(MSG_ERROR, + "Failed to initialize WPA state machine"); + return -1; + } + res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm, + hapd->iface->freq, + ie, ielen, + elems.mdie, elems.mdie_len, + elems.owe_dh, elems.owe_dh_len); + if (res != WPA_IE_OK) { + wpa_printf(MSG_DEBUG, + "WPA/RSN information element rejected? (res %u)", + res); + wpa_hexdump(MSG_DEBUG, "IE", ie, ielen); + if (res == WPA_INVALID_GROUP) { + reason = WLAN_REASON_GROUP_CIPHER_NOT_VALID; + status = WLAN_STATUS_GROUP_CIPHER_NOT_VALID; + } else if (res == WPA_INVALID_PAIRWISE) { + reason = WLAN_REASON_PAIRWISE_CIPHER_NOT_VALID; + status = WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID; + } else if (res == WPA_INVALID_AKMP) { + reason = WLAN_REASON_AKMP_NOT_VALID; + status = WLAN_STATUS_AKMP_NOT_VALID; + } +#ifdef CONFIG_IEEE80211W_AP + else if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION) { + reason = WLAN_REASON_INVALID_IE; + status = WLAN_STATUS_INVALID_IE; + } else if (res == WPA_INVALID_MGMT_GROUP_CIPHER) { + reason = WLAN_REASON_CIPHER_SUITE_REJECTED; + status = WLAN_STATUS_CIPHER_REJECTED_PER_POLICY; + } +#endif /* CONFIG_IEEE80211W_AP */ + else { + reason = WLAN_REASON_INVALID_IE; + status = WLAN_STATUS_INVALID_IE; + } + goto fail; + } +#ifdef CONFIG_IEEE80211W_AP + if ((sta->flags & (WLAN_STA_ASSOC | WLAN_STA_MFP)) == + (WLAN_STA_ASSOC | WLAN_STA_MFP) && + !sta->sa_query_timed_out && + sta->sa_query_count > 0) + ap_check_sa_query_timeout(hapd, sta); + if ((sta->flags & (WLAN_STA_ASSOC | WLAN_STA_MFP)) == + (WLAN_STA_ASSOC | WLAN_STA_MFP) && + !sta->sa_query_timed_out && + (sta->auth_alg != WLAN_AUTH_FT)) { + /* + * STA has already been associated with MFP and SA + * Query timeout has not been reached. Reject the + * association attempt temporarily and start SA Query, + * if one is not pending. + */ + + if (sta->sa_query_count == 0) + ap_sta_start_sa_query(hapd, sta); + + status = WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY; + + p = hostapd_eid_assoc_comeback_time(hapd, sta, p); + + hostapd_sta_assoc(hapd, addr, reassoc, status, buf, + p - buf); + return 0; + } + + if (wpa_auth_uses_mfp(sta->wpa_sm)) + sta->flags |= WLAN_STA_MFP; + else + sta->flags &= ~WLAN_STA_MFP; +#endif /* CONFIG_IEEE80211W_AP */ + +#ifdef CONFIG_IEEE80211R_AP + if (sta->auth_alg == WLAN_AUTH_FT) { + status = wpa_ft_validate_reassoc(sta->wpa_sm, req_ies, + req_ies_len); + if (status != WLAN_STATUS_SUCCESS) { + if (status == WLAN_STATUS_INVALID_PMKID) + reason = WLAN_REASON_INVALID_IE; + if (status == WLAN_STATUS_INVALID_MDIE) + reason = WLAN_REASON_INVALID_IE; + if (status == WLAN_STATUS_INVALID_FTIE) + reason = WLAN_REASON_INVALID_IE; + goto fail; + } + } +#endif /* CONFIG_IEEE80211R_AP */ + } else if (hapd->conf->wps_state) { +#ifdef CONFIG_WPS + struct wpabuf *wps; + + if (req_ies) + wps = ieee802_11_vendor_ie_concat(req_ies, req_ies_len, + WPS_IE_VENDOR_TYPE); + else + wps = NULL; +#ifdef CONFIG_WPS_STRICT + if (wps && wps_validate_assoc_req(wps) < 0) { + reason = WLAN_REASON_INVALID_IE; + status = WLAN_STATUS_INVALID_IE; + wpabuf_free(wps); + goto fail; + } +#endif /* CONFIG_WPS_STRICT */ + if (wps) { + sta->flags |= WLAN_STA_WPS; + if (wps_is_20(wps)) { + wpa_printf(MSG_DEBUG, + "WPS: STA supports WPS 2.0"); + sta->flags |= WLAN_STA_WPS2; + } + } else + sta->flags |= WLAN_STA_MAYBE_WPS; + wpabuf_free(wps); +#endif /* CONFIG_WPS */ +#ifdef CONFIG_HS20 + } else if (hapd->conf->osen) { + if (elems.osen == NULL) { + hostapd_logger( + hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, + "No HS 2.0 OSEN element in association request"); + return WLAN_STATUS_INVALID_IE; + } + + wpa_printf(MSG_DEBUG, "HS 2.0: OSEN association"); + if (sta->wpa_sm == NULL) + sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, + sta->addr, NULL); + if (sta->wpa_sm == NULL) { + wpa_printf(MSG_WARNING, + "Failed to initialize WPA state machine"); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + if (wpa_validate_osen(hapd->wpa_auth, sta->wpa_sm, + elems.osen - 2, elems.osen_len + 2) < 0) + return WLAN_STATUS_INVALID_IE; +#endif /* CONFIG_HS20 */ + } +#ifdef CONFIG_WPS +skip_wpa_check: +#endif /* CONFIG_WPS */ + +#ifdef CONFIG_IEEE80211R_AP + p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, buf, sizeof(buf), + sta->auth_alg, req_ies, req_ies_len); + if (!p) { + wpa_printf(MSG_DEBUG, "FT: Failed to write AssocResp IEs"); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } +#endif /* CONFIG_IEEE80211R_AP */ + +#ifdef CONFIG_OWE + if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE) && + wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_OWE && + elems.owe_dh) { + u8 *npos; + + npos = owe_assoc_req_process(hapd, sta, + elems.owe_dh, elems.owe_dh_len, + p, sizeof(buf) - (p - buf), + &reason); + if (npos) + p = npos; + if (!npos && + reason == WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED) { + status = WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED; + hostapd_sta_assoc(hapd, addr, reassoc, status, buf, + p - buf); + return 0; + } + + if (!npos || reason != WLAN_STATUS_SUCCESS) + goto fail; + } +#endif /* CONFIG_OWE */ + +#ifdef CONFIG_DPP2 + dpp_pfs_free(sta->dpp_pfs); + sta->dpp_pfs = NULL; + + if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) && + hapd->conf->dpp_netaccesskey && sta->wpa_sm && + wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_DPP && + elems.owe_dh) { + sta->dpp_pfs = dpp_pfs_init( + wpabuf_head(hapd->conf->dpp_netaccesskey), + wpabuf_len(hapd->conf->dpp_netaccesskey)); + if (!sta->dpp_pfs) { + wpa_printf(MSG_DEBUG, + "DPP: Could not initialize PFS"); + /* Try to continue without PFS */ + goto pfs_fail; + } + + if (dpp_pfs_process(sta->dpp_pfs, elems.owe_dh, + elems.owe_dh_len) < 0) { + dpp_pfs_free(sta->dpp_pfs); + sta->dpp_pfs = NULL; + reason = WLAN_REASON_UNSPECIFIED; + goto fail; + } + } + + wpa_auth_set_dpp_z(sta->wpa_sm, sta->dpp_pfs ? + sta->dpp_pfs->secret : NULL); + pfs_fail: +#endif /* CONFIG_DPP2 */ + +#if defined(CONFIG_IEEE80211R_AP) || defined(CONFIG_FILS) || defined(CONFIG_OWE) + hostapd_sta_assoc(hapd, addr, reassoc, status, buf, p - buf); + + if (sta->auth_alg == WLAN_AUTH_FT || + sta->auth_alg == WLAN_AUTH_FILS_SK || + sta->auth_alg == WLAN_AUTH_FILS_SK_PFS || + sta->auth_alg == WLAN_AUTH_FILS_PK) + ap_sta_set_authorized(hapd, sta, 1); +#else /* CONFIG_IEEE80211R_AP || CONFIG_FILS */ + /* Keep compiler silent about unused variables */ + if (status) { + } +#endif /* CONFIG_IEEE80211R_AP || CONFIG_FILS */ + + new_assoc = (sta->flags & WLAN_STA_ASSOC) == 0; + sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC; + sta->flags &= ~WLAN_STA_WNM_SLEEP_MODE; + + hostapd_set_sta_flags(hapd, sta); + +#ifdef CONFIG_FULL_HOSTAPD + if (reassoc && (sta->auth_alg == WLAN_AUTH_FT)) + wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC_FT); + else +#endif + wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC); + + hostapd_new_assoc_sta(hapd, sta, !new_assoc); + + ieee802_1x_notify_port_enabled(sta->eapol_sm, 1); + +#ifdef CONFIG_P2P + if (req_ies) { + p2p_group_notif_assoc(hapd->p2p_group, sta->addr, + req_ies, req_ies_len); + } +#endif /* CONFIG_P2P */ + + return 0; + +fail: +#ifdef CONFIG_IEEE80211R_AP + hostapd_sta_assoc(hapd, addr, reassoc, status, buf, p - buf); +#endif /* CONFIG_IEEE80211R_AP */ + hostapd_drv_sta_disassoc(hapd, sta->addr, reason); + ap_free_sta(hapd, sta); + return -1; +} + + +void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr) +{ + struct sta_info *sta; + + if (addr == NULL) { + /* + * This could potentially happen with unexpected event from the + * driver wrapper. This was seen at least in one case where the + * driver ended up reporting a station mode event while hostapd + * was running, so better make sure we stop processing such an + * event here. + */ + wpa_printf(MSG_DEBUG, + "hostapd_notif_disassoc: Skip event with no address"); + return; + } + + hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, "disassociated"); + + sta = ap_get_sta(hapd, addr); + if (sta == NULL) { + wpa_printf(MSG_DEBUG, + "Disassociation notification for unknown STA " + MACSTR, MAC2STR(addr)); + return; + } + + ap_sta_set_authorized(hapd, sta, 0); + sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC); + wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC); +#ifdef CONFIG_RADIUS + sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST; +#endif + ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); + ap_free_sta(hapd, sta); +} + + +void hostapd_event_sta_low_ack(struct hostapd_data *hapd, const u8 *addr) +{ + struct sta_info *sta = ap_get_sta(hapd, addr); + + if (!sta || !hapd->conf->disassoc_low_ack || sta->agreed_to_steer) + return; + + hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, + "disconnected due to excessive missing ACKs"); + hostapd_drv_sta_disassoc(hapd, addr, WLAN_REASON_DISASSOC_LOW_ACK); + ap_sta_disassociate(hapd, sta, WLAN_REASON_DISASSOC_LOW_ACK); +} + + +#ifdef CONFIG_FULL_HOSTAPD +void hostapd_event_sta_opmode_changed(struct hostapd_data *hapd, const u8 *addr, + enum smps_mode smps_mode, + enum chan_width chan_width, u8 rx_nss) +{ + struct sta_info *sta = ap_get_sta(hapd, addr); + const char *txt; + + if (!sta) + return; + + switch (smps_mode) { + case SMPS_AUTOMATIC: + txt = "automatic"; + break; + case SMPS_OFF: + txt = "off"; + break; + case SMPS_DYNAMIC: + txt = "dynamic"; + break; + case SMPS_STATIC: + txt = "static"; + break; + default: + txt = NULL; + break; + } + if (txt) { + wpa_msg(hapd->msg_ctx, MSG_INFO, STA_OPMODE_SMPS_MODE_CHANGED + MACSTR " %s", MAC2STR(addr), txt); + } + + switch (chan_width) { + case CHAN_WIDTH_20_NOHT: + txt = "20(no-HT)"; + break; + case CHAN_WIDTH_20: + txt = "20"; + break; + case CHAN_WIDTH_40: + txt = "40"; + break; + case CHAN_WIDTH_80: + txt = "80"; + break; + case CHAN_WIDTH_80P80: + txt = "80+80"; + break; + case CHAN_WIDTH_160: + txt = "160"; + break; + default: + txt = NULL; + break; + } + if (txt) { + wpa_msg(hapd->msg_ctx, MSG_INFO, STA_OPMODE_MAX_BW_CHANGED + MACSTR " %s", MAC2STR(addr), txt); + } + + if (rx_nss != 0xff) { + wpa_msg(hapd->msg_ctx, MSG_INFO, STA_OPMODE_N_SS_CHANGED + MACSTR " %d", MAC2STR(addr), rx_nss); + } +} +#endif + +void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht, + int offset, int width, int cf1, int cf2, + int finished) +{ + /* TODO: If OCV is enabled deauth STAs that don't perform a SA Query */ + +#ifdef NEED_AP_MLME + int channel, chwidth, is_dfs = 0; + u8 seg0_idx = 0, seg1_idx = 0; + + hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, + "driver %s channel switch: freq=%d, ht=%d, vht_ch=0x%x, offset=%d, width=%d (%s), cf1=%d, cf2=%d", + finished ? "had" : "starting", + freq, ht, hapd->iconf->ch_switch_vht_config, offset, + width, channel_width_to_string(width), cf1, cf2); + + if (!hapd->iface->current_mode) { + hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_WARNING, + "ignore channel switch since the interface is not yet ready"); + return; + } + + hapd->iface->freq = freq; + + channel = hostapd_hw_get_channel(hapd, freq); + if (!channel) { + hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_WARNING, + "driver switched to bad channel!"); + return; + } + + switch (width) { +#ifdef CONFIG_FULL_HOSTAPD + case CHAN_WIDTH_80: + chwidth = CHANWIDTH_80MHZ; + break; + case CHAN_WIDTH_80P80: + chwidth = CHANWIDTH_80P80MHZ; + break; + case CHAN_WIDTH_160: + chwidth = CHANWIDTH_160MHZ; + break; +#endif + case CHAN_WIDTH_20_NOHT: + case CHAN_WIDTH_20: + case CHAN_WIDTH_40: + default: + chwidth = CHANWIDTH_USE_HT; + break; + } + + switch (hapd->iface->current_mode->mode) { +#ifdef CONFIG_FULL_HOSTAPD + case HOSTAPD_MODE_IEEE80211A: + if (cf1 > 5000) + seg0_idx = (cf1 - 5000) / 5; + if (cf2 > 5000) + seg1_idx = (cf2 - 5000) / 5; + break; +#endif + default: + ieee80211_freq_to_chan(cf1, &seg0_idx); + ieee80211_freq_to_chan(cf2, &seg1_idx); + break; + } + + hapd->iconf->channel = channel; + hapd->iconf->ieee80211n = ht; + if (!ht) { + hapd->iconf->ieee80211ac = 0; + } else if (hapd->iconf->ch_switch_vht_config) { + /* CHAN_SWITCH VHT config */ + if (hapd->iconf->ch_switch_vht_config & + CH_SWITCH_VHT_ENABLED) + hapd->iconf->ieee80211ac = 1; + else if (hapd->iconf->ch_switch_vht_config & + CH_SWITCH_VHT_DISABLED) + hapd->iconf->ieee80211ac = 0; + } + hapd->iconf->ch_switch_vht_config = 0; + + hapd->iconf->secondary_channel = offset; + hostapd_set_oper_chwidth(hapd->iconf, chwidth); + hostapd_set_oper_centr_freq_seg0_idx(hapd->iconf, seg0_idx); + hostapd_set_oper_centr_freq_seg1_idx(hapd->iconf, seg1_idx); + +#ifdef CONFIG_FULL_HOSTAPD + is_dfs = ieee80211_is_dfs(freq, hapd->iface->hw_features, + hapd->iface->num_hw_features); +#endif + + wpa_msg(hapd->msg_ctx, MSG_INFO, + "%sfreq=%d ht_enabled=%d ch_offset=%d ch_width=%s cf1=%d cf2=%d dfs=%d", + finished ? WPA_EVENT_CHANNEL_SWITCH : + WPA_EVENT_CHANNEL_SWITCH_STARTED, + freq, ht, offset, channel_width_to_string(width), + cf1, cf2, is_dfs); + if (!finished) + return; + + if (hapd->csa_in_progress && + freq == hapd->cs_freq_params.freq) { + hostapd_cleanup_cs_params(hapd); + ieee802_11_set_beacon(hapd); + + wpa_msg(hapd->msg_ctx, MSG_INFO, AP_CSA_FINISHED + "freq=%d dfs=%d", freq, is_dfs); +#ifdef CONFIG_FULL_HOSTAPD + } else if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) { + wpa_msg(hapd->msg_ctx, MSG_INFO, AP_CSA_FINISHED + "freq=%d dfs=%d", freq, is_dfs); +#endif + } + +#ifdef CONFIG_FULL_HOSTAPD + for (i = 0; i < hapd->iface->num_bss; i++) + hostapd_neighbor_set_own_report(hapd->iface->bss[i]); +#endif + +#if CFG_ROLE_LAUNCH + rl_set_csa_switched(); +#endif + + (void)is_dfs; +#endif /* NEED_AP_MLME */ +} + + +void hostapd_event_connect_failed_reason(struct hostapd_data *hapd, + const u8 *addr, int reason_code) +{ + switch (reason_code) { + case MAX_CLIENT_REACHED: + wpa_msg(hapd->msg_ctx, MSG_INFO, AP_REJECTED_MAX_STA MACSTR, + MAC2STR(addr)); + break; + case BLOCKED_CLIENT: + wpa_msg(hapd->msg_ctx, MSG_INFO, AP_REJECTED_BLOCKED_STA MACSTR, + MAC2STR(addr)); + break; + } +} + + +#ifdef CONFIG_ACS +void hostapd_acs_channel_selected(struct hostapd_data *hapd, + struct acs_selected_channels *acs_res) +{ + int ret, i; + int err = 0; + + if (hapd->iconf->channel) { + wpa_printf(MSG_INFO, "ACS: Channel was already set to %d", + hapd->iconf->channel); + return; + } + + if (!hapd->iface->current_mode) { + for (i = 0; i < hapd->iface->num_hw_features; i++) { + struct hostapd_hw_modes *mode = + &hapd->iface->hw_features[i]; + + if (mode->mode == acs_res->hw_mode) { + hapd->iface->current_mode = mode; + break; + } + } + if (!hapd->iface->current_mode) { + hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_WARNING, + "driver selected to bad hw_mode"); + err = 1; + goto out; + } + } + + hapd->iface->freq = hostapd_hw_get_freq(hapd, acs_res->pri_channel); + + if (!acs_res->pri_channel) { + hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_WARNING, + "driver switched to bad channel"); + err = 1; + goto out; + } + + hapd->iconf->channel = acs_res->pri_channel; + hapd->iconf->acs = 1; + + if (acs_res->sec_channel == 0) + hapd->iconf->secondary_channel = 0; + else if (acs_res->sec_channel < acs_res->pri_channel) + hapd->iconf->secondary_channel = -1; + else if (acs_res->sec_channel > acs_res->pri_channel) + hapd->iconf->secondary_channel = 1; + else { + wpa_printf(MSG_ERROR, "Invalid secondary channel!"); + err = 1; + goto out; + } + +#if defined(CONFIG_IEEE80211AC) || defined(CONFIG_IEEE80211AX) + if (hapd->iface->conf->ieee80211ac || hapd->iface->conf->ieee80211ax) { + /* set defaults for backwards compatibility */ + hostapd_set_oper_centr_freq_seg1_idx(hapd->iconf, 0); + hostapd_set_oper_centr_freq_seg0_idx(hapd->iconf, 0); + hostapd_set_oper_chwidth(hapd->iconf, CHANWIDTH_USE_HT); + if (acs_res->ch_width == 80) { + hostapd_set_oper_centr_freq_seg0_idx( + hapd->iconf, acs_res->vht_seg0_center_ch); + hostapd_set_oper_chwidth(hapd->iconf, CHANWIDTH_80MHZ); + } else if (acs_res->ch_width == 160) { + if (acs_res->vht_seg1_center_ch == 0) { + hostapd_set_oper_centr_freq_seg0_idx( + hapd->iconf, + acs_res->vht_seg0_center_ch); + hostapd_set_oper_chwidth(hapd->iconf, + CHANWIDTH_160MHZ); + } else { + hostapd_set_oper_centr_freq_seg0_idx( + hapd->iconf, + acs_res->vht_seg0_center_ch); + hostapd_set_oper_centr_freq_seg1_idx( + hapd->iconf, + acs_res->vht_seg1_center_ch); + hostapd_set_oper_chwidth(hapd->iconf, + CHANWIDTH_80P80MHZ); + } + } + } +#endif + +out: + ret = hostapd_acs_completed(hapd->iface, err); + if (ret) { + wpa_printf(MSG_ERROR, + "ACS: Possibly channel configuration is invalid"); + } +} +#endif /* CONFIG_ACS */ + + +int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa, const u8 *da, + const u8 *bssid, const u8 *ie, size_t ie_len, + int ssi_signal) +{ + size_t i; + int ret = 0; + + if (sa == NULL || ie == NULL) + return -1; + + random_add_randomness(sa, ETH_ALEN); + for (i = 0; hapd->probereq_cb && i < hapd->num_probereq_cb; i++) { + if (hapd->probereq_cb[i].cb(hapd->probereq_cb[i].ctx, + sa, da, bssid, ie, ie_len, + ssi_signal) > 0) { + ret = 1; + break; + } + } + return ret; +} + + +#ifdef HOSTAPD + +#ifdef CONFIG_IEEE80211R_AP +static void hostapd_notify_auth_ft_finish(void *ctx, const u8 *dst, + const u8 *bssid, + u16 auth_transaction, u16 status, + const u8 *ies, size_t ies_len) +{ + struct hostapd_data *hapd = ctx; + struct sta_info *sta; + + sta = ap_get_sta(hapd, dst); + if (sta == NULL) + return; + + hostapd_logger(hapd, dst, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, "authentication OK (FT)"); + sta->flags |= WLAN_STA_AUTH; + + hostapd_sta_auth(hapd, dst, auth_transaction, status, ies, ies_len); +} +#endif /* CONFIG_IEEE80211R_AP */ + + +static void hostapd_notif_auth(struct hostapd_data *hapd, + struct auth_info *rx_auth) +{ + struct sta_info *sta; + u16 status = WLAN_STATUS_SUCCESS; + u8 resp_ies[2 + WLAN_AUTH_CHALLENGE_LEN]; + size_t resp_ies_len = 0; + + sta = ap_get_sta(hapd, rx_auth->peer); + if (!sta) { + sta = ap_sta_add(hapd, rx_auth->peer); + if (sta == NULL) { + status = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; + goto fail; + } + } + sta->flags &= ~WLAN_STA_PREAUTH; + ieee802_1x_notify_pre_auth(sta->eapol_sm, 0); +#ifdef CONFIG_IEEE80211R_AP + if (rx_auth->auth_type == WLAN_AUTH_FT && hapd->wpa_auth) { + sta->auth_alg = WLAN_AUTH_FT; + if (sta->wpa_sm == NULL) + sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, + sta->addr, NULL); + if (sta->wpa_sm == NULL) { + wpa_printf(MSG_DEBUG, + "FT: Failed to initialize WPA state machine"); + status = WLAN_STATUS_UNSPECIFIED_FAILURE; + goto fail; + } + wpa_ft_process_auth(sta->wpa_sm, rx_auth->bssid, + rx_auth->auth_transaction, rx_auth->ies, + rx_auth->ies_len, + hostapd_notify_auth_ft_finish, hapd); + return; + } +#endif /* CONFIG_IEEE80211R_AP */ + +fail: + hostapd_sta_auth(hapd, rx_auth->peer, rx_auth->auth_transaction + 1, + status, resp_ies, resp_ies_len); +} + + +#ifndef NEED_AP_MLME +static void hostapd_action_rx(struct hostapd_data *hapd, + struct rx_mgmt *drv_mgmt) +{ + struct ieee80211_mgmt *mgmt; + struct sta_info *sta; + size_t plen __maybe_unused; + u16 fc; + u8 *action __maybe_unused; + + if (drv_mgmt->frame_len < IEEE80211_HDRLEN + 2 + 1) + return; + + plen = drv_mgmt->frame_len - IEEE80211_HDRLEN; + + mgmt = (struct ieee80211_mgmt *) drv_mgmt->frame; + fc = le_to_host16(mgmt->frame_control); + if (WLAN_FC_GET_STYPE(fc) != WLAN_FC_STYPE_ACTION) + return; /* handled by the driver */ + + action = (u8 *) &mgmt->u.action.u; + wpa_printf(MSG_DEBUG, "RX_ACTION category %u action %u sa " MACSTR + " da " MACSTR " plen %d", + mgmt->u.action.category, *action, + MAC2STR(mgmt->sa), MAC2STR(mgmt->da), (int) plen); + + sta = ap_get_sta(hapd, mgmt->sa); + if (sta == NULL) { + wpa_printf(MSG_DEBUG, "%s: station not found", __func__); + return; + } +#ifdef CONFIG_IEEE80211R_AP + if (mgmt->u.action.category == WLAN_ACTION_FT) { + wpa_ft_action_rx(sta->wpa_sm, (u8 *) &mgmt->u.action, plen); + return; + } +#endif /* CONFIG_IEEE80211R_AP */ +#ifdef CONFIG_IEEE80211W_AP + if (mgmt->u.action.category == WLAN_ACTION_SA_QUERY) { + ieee802_11_sa_query_action(hapd, mgmt, drv_mgmt->frame_len); + return; + } +#endif /* CONFIG_IEEE80211W_AP */ +#ifdef CONFIG_WNM_AP + if (mgmt->u.action.category == WLAN_ACTION_WNM) { + ieee802_11_rx_wnm_action_ap(hapd, mgmt, drv_mgmt->frame_len); + return; + } +#endif /* CONFIG_WNM_AP */ +#ifdef CONFIG_FST + if (mgmt->u.action.category == WLAN_ACTION_FST && hapd->iface->fst) { + fst_rx_action(hapd->iface->fst, mgmt, drv_mgmt->frame_len); + return; + } +#endif /* CONFIG_FST */ +#ifdef CONFIG_DPP + if (plen >= 2 + 4 && + mgmt->u.action.u.vs_public_action.action == + WLAN_PA_VENDOR_SPECIFIC && + WPA_GET_BE24(mgmt->u.action.u.vs_public_action.oui) == + OUI_WFA && + mgmt->u.action.u.vs_public_action.variable[0] == + DPP_OUI_TYPE) { + const u8 *pos, *end; + + pos = mgmt->u.action.u.vs_public_action.oui; + end = drv_mgmt->frame + drv_mgmt->frame_len; + hostapd_dpp_rx_action(hapd, mgmt->sa, pos, end - pos, + drv_mgmt->freq); + return; + } +#endif /* CONFIG_DPP */ +} +#endif /* NEED_AP_MLME */ + + +#ifdef NEED_AP_MLME + +#define HAPD_BROADCAST ((struct hostapd_data *) -1) + +static struct hostapd_data * get_hapd_bssid(struct hostapd_iface *iface, + const u8 *bssid) +{ + size_t i; + u8 *b = (u8*)iface->bss[0]->own_addr; + + if (bssid == NULL) + return NULL; + if (bssid[0] == 0xff && bssid[1] == 0xff && bssid[2] == 0xff && + bssid[3] == 0xff && bssid[4] == 0xff && bssid[5] == 0xff) + return HAPD_BROADCAST; + + if (!(b[0] | b[1] | b[2] | b[3] | b[4] | b[5])) { + return NULL; + } + + for (i = 0; i < iface->num_bss; i++) { + if (os_memcmp(bssid, iface->bss[i]->own_addr, ETH_ALEN) == 0) + return iface->bss[i]; + } + + return NULL; +} + + +static void hostapd_rx_from_unknown_sta(struct hostapd_data *hapd, + const u8 *bssid, const u8 *addr, + int wds) +{ + hapd = get_hapd_bssid(hapd->iface, bssid); + if (hapd == NULL || hapd == HAPD_BROADCAST) + return; + + ieee802_11_rx_from_unknown(hapd, addr, wds); +} + + +static int hostapd_mgmt_rx(struct hostapd_data *hapd, struct rx_mgmt *rx_mgmt) +{ + struct hostapd_iface *iface = hapd->iface; + const struct ieee80211_hdr *hdr; + const u8 *bssid; + struct hostapd_frame_info fi; + int ret; + +#ifdef CONFIG_TESTING_OPTIONS + if (hapd->ext_mgmt_frame_handling) { + size_t hex_len = 2 * rx_mgmt->frame_len + 1; + char *hex = os_malloc(hex_len); + + if (hex) { + wpa_snprintf_hex(hex, hex_len, rx_mgmt->frame, + rx_mgmt->frame_len); + wpa_msg(hapd->msg_ctx, MSG_INFO, "MGMT-RX %s", hex); + os_free(hex); + } + return 1; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + hdr = (const struct ieee80211_hdr *) rx_mgmt->frame; + bssid = get_hdr_bssid(hdr, rx_mgmt->frame_len); + if (bssid == NULL) + return 0; + + hapd = get_hapd_bssid(iface, bssid); + if (hapd == NULL) { + u16 fc = le_to_host16(hdr->frame_control); + + /* + * Drop frames to unknown BSSIDs except for Beacon frames which + * could be used to update neighbor information. + */ + if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && + WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON) + hapd = iface->bss[0]; + else + return 0; + } + + os_memset(&fi, 0, sizeof(fi)); + fi.freq = rx_mgmt->freq; + fi.datarate = rx_mgmt->datarate; + fi.ssi_signal = rx_mgmt->ssi_signal; + + if (hapd == HAPD_BROADCAST) { + size_t i; + + ret = 0; + for (i = 0; i < iface->num_bss; i++) { + /* if bss is set, driver will call this function for + * each bss individually. */ + if (rx_mgmt->drv_priv && + (iface->bss[i]->drv_priv != rx_mgmt->drv_priv)) + continue; + + if (ieee802_11_mgmt(iface->bss[i], rx_mgmt->frame, + rx_mgmt->frame_len, &fi) > 0) + ret = 1; + } + } else + ret = ieee802_11_mgmt(hapd, rx_mgmt->frame, rx_mgmt->frame_len, + &fi); + + random_add_randomness(&fi, sizeof(fi)); + + return ret; +} + + +static void hostapd_mgmt_tx_cb(struct hostapd_data *hapd, const u8 *buf, + size_t len, u16 stype, int ok) +{ + struct ieee80211_hdr *hdr; + struct hostapd_data *orig_hapd = hapd; + + hdr = (struct ieee80211_hdr *) buf; + hapd = get_hapd_bssid(hapd->iface, get_hdr_bssid(hdr, len)); + if (!hapd) + return; + if (hapd == HAPD_BROADCAST) { + if (stype != WLAN_FC_STYPE_ACTION || len <= 25 || + buf[24] != WLAN_ACTION_PUBLIC) + return; + hapd = get_hapd_bssid(orig_hapd->iface, hdr->addr2); + if (!hapd || hapd == HAPD_BROADCAST) + return; + /* + * Allow processing of TX status for a Public Action frame that + * used wildcard BBSID. + */ + } + ieee802_11_mgmt_cb(hapd, buf, len, stype, ok); +} + +#endif /* NEED_AP_MLME */ + + +static int hostapd_event_new_sta(struct hostapd_data *hapd, const u8 *addr) +{ + struct sta_info *sta = ap_get_sta(hapd, addr); + + if (sta) + return 0; + + wpa_printf(MSG_DEBUG, "Data frame from unknown STA " MACSTR + " - adding a new STA", MAC2STR(addr)); + sta = ap_sta_add(hapd, addr); + if (sta) { + hostapd_new_assoc_sta(hapd, sta, 0); + } else { + wpa_printf(MSG_DEBUG, "Failed to add STA entry for " MACSTR, + MAC2STR(addr)); + return -1; + } + + return 0; +} + + +static void hostapd_event_eapol_rx(struct hostapd_data *hapd, const u8 *src, + const u8 *data, size_t data_len) +{ + struct hostapd_iface *iface = hapd->iface; + struct sta_info *sta; + size_t j; + + for (j = 0; j < iface->num_bss; j++) { + sta = ap_get_sta(iface->bss[j], src); + if (sta && sta->flags & WLAN_STA_ASSOC) { + hapd = iface->bss[j]; + break; + } + } + + ieee802_1x_receive(hapd, src, data, data_len); +} + + +static struct hostapd_channel_data * hostapd_get_mode_channel( + struct hostapd_iface *iface, unsigned int freq) +{ + int i; + struct hostapd_channel_data *chan; + + for (i = 0; i < iface->current_mode->num_channels; i++) { + chan = &iface->current_mode->channels[i]; + if (!chan) + return NULL; + if ((unsigned int) chan->freq == freq) + return chan; + } + + return NULL; +} + + +static void hostapd_update_nf(struct hostapd_iface *iface, + struct hostapd_channel_data *chan, + struct freq_survey *survey) +{ + if (!iface->chans_surveyed) { + chan->min_nf = survey->nf; + iface->lowest_nf = survey->nf; + } else { + if (dl_list_empty(&chan->survey_list)) + chan->min_nf = survey->nf; + else if (survey->nf < chan->min_nf) + chan->min_nf = survey->nf; + if (survey->nf < iface->lowest_nf) + iface->lowest_nf = survey->nf; + } +} + + +static void hostapd_single_channel_get_survey(struct hostapd_iface *iface, + struct survey_results *survey_res) +{ + struct hostapd_channel_data *chan; + struct freq_survey *survey; + u64 divisor, dividend; + + survey = dl_list_first(&survey_res->survey_list, struct freq_survey, + list); + if (!survey || !survey->freq) + return; + + chan = hostapd_get_mode_channel(iface, survey->freq); + if (!chan || chan->flag & HOSTAPD_CHAN_DISABLED) + return; + + wpa_printf(MSG_DEBUG, + "Single Channel Survey: (freq=%d channel_time=%ld channel_time_busy=%ld)", + survey->freq, + (unsigned long int) survey->channel_time, + (unsigned long int) survey->channel_time_busy); + + if (survey->channel_time > iface->last_channel_time && + survey->channel_time > survey->channel_time_busy) { + dividend = survey->channel_time_busy - + iface->last_channel_time_busy; + divisor = survey->channel_time - iface->last_channel_time; + + iface->channel_utilization = dividend * 255 / divisor; + wpa_printf(MSG_DEBUG, "Channel Utilization: %d", + iface->channel_utilization); + } + iface->last_channel_time = survey->channel_time; + iface->last_channel_time_busy = survey->channel_time_busy; +} + + +void hostapd_event_get_survey(struct hostapd_iface *iface, + struct survey_results *survey_results) +{ + struct freq_survey *survey, *tmp; + struct hostapd_channel_data *chan; + + if (dl_list_empty(&survey_results->survey_list)) { + wpa_printf(MSG_DEBUG, "No survey data received"); + return; + } + + if (survey_results->freq_filter) { + hostapd_single_channel_get_survey(iface, survey_results); + return; + } + + dl_list_for_each_safe(survey, tmp, &survey_results->survey_list, + struct freq_survey, list) { + chan = hostapd_get_mode_channel(iface, survey->freq); + if (!chan) + continue; + if (chan->flag & HOSTAPD_CHAN_DISABLED) + continue; + + dl_list_del(&survey->list); + dl_list_add_tail(&chan->survey_list, &survey->list); + + hostapd_update_nf(iface, chan, survey); + + iface->chans_surveyed++; + } +} + + +#ifdef NEED_AP_MLME + +static void hostapd_event_iface_unavailable(struct hostapd_data *hapd) +{ + wpa_printf(MSG_DEBUG, "Interface %s is unavailable -- stopped", + hapd->conf->iface); + + if (hapd->csa_in_progress) { + wpa_printf(MSG_INFO, "CSA failed (%s was stopped)", + hapd->conf->iface); + hostapd_switch_channel_fallback(hapd->iface, + &hapd->cs_freq_params); + } +} + +#ifdef CONFIG_DFS +static void hostapd_event_dfs_radar_detected(struct hostapd_data *hapd, + struct dfs_event *radar) +{ + wpa_printf(MSG_DEBUG, "DFS radar detected on %d MHz", radar->freq); + hostapd_dfs_radar_detected(hapd->iface, radar->freq, radar->ht_enabled, + radar->chan_offset, radar->chan_width, + radar->cf1, radar->cf2); +} + + +static void hostapd_event_dfs_pre_cac_expired(struct hostapd_data *hapd, + struct dfs_event *radar) +{ + wpa_printf(MSG_DEBUG, "DFS Pre-CAC expired on %d MHz", radar->freq); + hostapd_dfs_pre_cac_expired(hapd->iface, radar->freq, radar->ht_enabled, + radar->chan_offset, radar->chan_width, + radar->cf1, radar->cf2); +} + + +static void hostapd_event_dfs_cac_finished(struct hostapd_data *hapd, + struct dfs_event *radar) +{ + wpa_printf(MSG_DEBUG, "DFS CAC finished on %d MHz", radar->freq); + hostapd_dfs_complete_cac(hapd->iface, 1, radar->freq, radar->ht_enabled, + radar->chan_offset, radar->chan_width, + radar->cf1, radar->cf2); +} + + +static void hostapd_event_dfs_cac_aborted(struct hostapd_data *hapd, + struct dfs_event *radar) +{ + wpa_printf(MSG_DEBUG, "DFS CAC aborted on %d MHz", radar->freq); + hostapd_dfs_complete_cac(hapd->iface, 0, radar->freq, radar->ht_enabled, + radar->chan_offset, radar->chan_width, + radar->cf1, radar->cf2); +} + + +static void hostapd_event_dfs_nop_finished(struct hostapd_data *hapd, + struct dfs_event *radar) +{ + wpa_printf(MSG_DEBUG, "DFS NOP finished on %d MHz", radar->freq); + hostapd_dfs_nop_finished(hapd->iface, radar->freq, radar->ht_enabled, + radar->chan_offset, radar->chan_width, + radar->cf1, radar->cf2); +} + + +static void hostapd_event_dfs_cac_started(struct hostapd_data *hapd, + struct dfs_event *radar) +{ + wpa_printf(MSG_DEBUG, "DFS offload CAC started on %d MHz", radar->freq); + hostapd_dfs_start_cac(hapd->iface, radar->freq, radar->ht_enabled, + radar->chan_offset, radar->chan_width, + radar->cf1, radar->cf2); +} +#endif /* COFNIG_DFS */ + +#ifdef CONFIG_FULL_HOSTAPD +static void hostapd_event_wds_sta_interface_status(struct hostapd_data *hapd, + int istatus, + const char *ifname, + const u8 *addr) +{ + struct sta_info *sta = ap_get_sta(hapd, addr); + + if (sta) { + os_free(sta->ifname_wds); + if (istatus == INTERFACE_ADDED) + sta->ifname_wds = os_strdup(ifname); + else + sta->ifname_wds = NULL; + } + + wpa_msg(hapd->msg_ctx, MSG_INFO, "%sifname=%s sta_addr=" MACSTR, + istatus == INTERFACE_ADDED ? + WDS_STA_INTERFACE_ADDED : WDS_STA_INTERFACE_REMOVED, + ifname, MAC2STR(addr)); +} +#endif + +#ifdef CONFIG_OWE +static int hostapd_notif_update_dh_ie(struct hostapd_data *hapd, + const u8 *peer, const u8 *ie, + size_t ie_len) +{ + u16 status; + struct sta_info *sta; + struct ieee802_11_elems elems; + + if (!hapd || !hapd->wpa_auth) { + wpa_printf(MSG_DEBUG, "OWE: Invalid hapd context"); + return -1; + } + if (!peer) { + wpa_printf(MSG_DEBUG, "OWE: Peer unknown"); + return -1; + } + if (!(hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE)) { + wpa_printf(MSG_DEBUG, "OWE: No OWE AKM configured"); + status = WLAN_STATUS_AKMP_NOT_VALID; + goto err; + } + if (ieee802_11_parse_elems(ie, ie_len, &elems, 1) == ParseFailed) { + wpa_printf(MSG_DEBUG, "OWE: Failed to parse OWE IE for " + MACSTR, MAC2STR(peer)); + status = WLAN_STATUS_UNSPECIFIED_FAILURE; + goto err; + } + status = owe_validate_request(hapd, peer, elems.rsn_ie, + elems.rsn_ie_len, + elems.owe_dh, elems.owe_dh_len); + if (status != WLAN_STATUS_SUCCESS) + goto err; + + sta = ap_get_sta(hapd, peer); + if (sta) { + ap_sta_no_session_timeout(hapd, sta); + accounting_sta_stop(hapd, sta); + + /* + * Make sure that the previously registered inactivity timer + * will not remove the STA immediately. + */ + sta->timeout_next = STA_NULLFUNC; + } else { + sta = ap_sta_add(hapd, peer); + if (!sta) { + status = WLAN_STATUS_UNSPECIFIED_FAILURE; + goto err; + } + } + sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS | WLAN_STA_WPS2); + + status = owe_process_rsn_ie(hapd, sta, elems.rsn_ie, + elems.rsn_ie_len, elems.owe_dh, + elems.owe_dh_len); + if (status != WLAN_STATUS_SUCCESS) + ap_free_sta(hapd, sta); + + return 0; +err: + hostapd_drv_update_dh_ie(hapd, peer, status, NULL, 0); + return 0; +} +#endif /* CONFIG_OWE */ + +#endif /* NEED_AP_MLME */ + + +void wpa_supplicant_event(void *ctx, enum wpa_event_type event, + union wpa_event_data *data) +{ + struct hostapd_data *hapd = ctx; +#if 0//ndef CONFIG_NO_STDOUT_DEBUG + int level = MSG_DEBUG; + + if (event == EVENT_RX_MGMT && data->rx_mgmt.frame && + data->rx_mgmt.frame_len >= 24) { + const struct ieee80211_hdr *hdr; + u16 fc; + + hdr = (const struct ieee80211_hdr *) data->rx_mgmt.frame; + fc = le_to_host16(hdr->frame_control); + if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && + WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_BEACON) + level = MSG_EXCESSIVE; + if (WLAN_FC_GET_TYPE(fc) == WLAN_FC_TYPE_MGMT && + WLAN_FC_GET_STYPE(fc) == WLAN_FC_STYPE_PROBE_REQ) + level = MSG_EXCESSIVE; + } + + wpa_dbg(hapd->msg_ctx, level, "Event %s (%d) received", + event_to_string(event), event); +#endif /* CONFIG_NO_STDOUT_DEBUG */ + + switch (event) { + case EVENT_MICHAEL_MIC_FAILURE: + michael_mic_failure(hapd, data->michael_mic_failure.src, 1); + break; +#ifdef CONFIG_FULL_HOSTAPD + case EVENT_SCAN_RESULTS: + if (hapd->iface->scan_cb) + hapd->iface->scan_cb(hapd->iface); + break; + case EVENT_WPS_BUTTON_PUSHED: + hostapd_wps_button_pushed(hapd, NULL); + break; +#endif +#ifdef NEED_AP_MLME + case EVENT_TX_STATUS: + switch (data->tx_status.type) { + case WLAN_FC_TYPE_MGMT: + hostapd_mgmt_tx_cb(hapd, data->tx_status.data, + data->tx_status.data_len, + data->tx_status.stype, + data->tx_status.ack); + break; + case WLAN_FC_TYPE_DATA: + hostapd_tx_status(hapd, data->tx_status.dst, + data->tx_status.data, + data->tx_status.data_len, + data->tx_status.ack); + break; + } + break; + case EVENT_EAPOL_TX_STATUS: + hostapd_eapol_tx_status(hapd, data->eapol_tx_status.dst, + data->eapol_tx_status.data, + data->eapol_tx_status.data_len, + data->eapol_tx_status.ack); + break; + case EVENT_DRIVER_CLIENT_POLL_OK: + hostapd_client_poll_ok(hapd, data->client_poll.addr); + break; + case EVENT_RX_FROM_UNKNOWN: + hostapd_rx_from_unknown_sta(hapd, data->rx_from_unknown.bssid, + data->rx_from_unknown.addr, + data->rx_from_unknown.wds); + break; +#endif /* NEED_AP_MLME */ + case EVENT_RX_MGMT: + if (!data->rx_mgmt.frame) + break; +#ifdef NEED_AP_MLME + hostapd_mgmt_rx(hapd, &data->rx_mgmt); +#else /* NEED_AP_MLME */ + hostapd_action_rx(hapd, &data->rx_mgmt); +#endif /* NEED_AP_MLME */ + break; +#ifdef CONFIG_FULL_HOSTAPD + case EVENT_RX_PROBE_REQ: + if (data->rx_probe_req.sa == NULL || + data->rx_probe_req.ie == NULL) + break; + hostapd_probe_req_rx(hapd, data->rx_probe_req.sa, + data->rx_probe_req.da, + data->rx_probe_req.bssid, + data->rx_probe_req.ie, + data->rx_probe_req.ie_len, + data->rx_probe_req.ssi_signal); + break; + case EVENT_NEW_STA: + hostapd_event_new_sta(hapd, data->new_sta.addr); + break; +#endif + case EVENT_EAPOL_RX: + hostapd_event_eapol_rx(hapd, data->eapol_rx.src, + data->eapol_rx.data, + data->eapol_rx.data_len); + break; + case EVENT_ASSOC: + if (!data) + return; + hostapd_notif_assoc(hapd, data->assoc_info.addr, + data->assoc_info.req_ies, + data->assoc_info.req_ies_len, + data->assoc_info.reassoc); + break; +#ifdef CONFIG_OWE + case EVENT_UPDATE_DH: + if (!data) + return; + hostapd_notif_update_dh_ie(hapd, data->update_dh.peer, + data->update_dh.ie, + data->update_dh.ie_len); + break; +#endif /* CONFIG_OWE */ + case EVENT_DISASSOC: + if (data) + hostapd_notif_disassoc(hapd, data->disassoc_info.addr); + break; +#ifdef CONFIG_FULL_HOSTAPD + case EVENT_DEAUTH: + if (data) + hostapd_notif_disassoc(hapd, data->deauth_info.addr); + break; + case EVENT_STATION_LOW_ACK: + if (!data) + break; + hostapd_event_sta_low_ack(hapd, data->low_ack.addr); + break; + case EVENT_AUTH: + hostapd_notif_auth(hapd, &data->auth); + break; +#endif + case EVENT_CH_SWITCH_STARTED: + case EVENT_CH_SWITCH: + if (!data) + break; + hostapd_event_ch_switch(hapd, data->ch_switch.freq, + data->ch_switch.ht_enabled, + data->ch_switch.ch_offset, + data->ch_switch.ch_width, + data->ch_switch.cf1, + data->ch_switch.cf2, + event == EVENT_CH_SWITCH); + break; +#ifdef CONFIG_FULL_HOSTAPD + case EVENT_CONNECT_FAILED_REASON: + if (!data) + break; + hostapd_event_connect_failed_reason( + hapd, data->connect_failed_reason.addr, + data->connect_failed_reason.code); + break; + case EVENT_SURVEY: + hostapd_event_get_survey(hapd->iface, &data->survey_results); + break; +#endif +#ifdef NEED_AP_MLME +#ifdef CONFIG_DFS + case EVENT_DFS_RADAR_DETECTED: + if (!data) + break; + hostapd_event_dfs_radar_detected(hapd, &data->dfs_event); + break; + case EVENT_DFS_PRE_CAC_EXPIRED: + if (!data) + break; + hostapd_event_dfs_pre_cac_expired(hapd, &data->dfs_event); + break; + case EVENT_DFS_CAC_FINISHED: + if (!data) + break; + hostapd_event_dfs_cac_finished(hapd, &data->dfs_event); + break; + case EVENT_DFS_CAC_ABORTED: + if (!data) + break; + hostapd_event_dfs_cac_aborted(hapd, &data->dfs_event); + break; + case EVENT_DFS_NOP_FINISHED: + if (!data) + break; + hostapd_event_dfs_nop_finished(hapd, &data->dfs_event); + break; + case EVENT_DFS_CAC_STARTED: + if (!data) + break; + hostapd_event_dfs_cac_started(hapd, &data->dfs_event); + break; +#endif +#ifdef CONFIG_FULL_HOSTAPD + case EVENT_INTERFACE_UNAVAILABLE: + hostapd_event_iface_unavailable(hapd); + break; + case EVENT_CHANNEL_LIST_CHANGED: + /* channel list changed (regulatory?), update channel list */ + /* TODO: check this. hostapd_get_hw_features() initializes + * too much stuff. */ + /* hostapd_get_hw_features(hapd->iface); */ + hostapd_channel_list_updated( + hapd->iface, data->channel_list_changed.initiator); + break; +#endif /* CONFIG_FULL_SUPPLICANT */ +#endif /* NEED_AP_MLME */ +#ifdef CONFIG_FULL_HOSTAPD + case EVENT_INTERFACE_ENABLED: + wpa_msg(hapd->msg_ctx, MSG_INFO, INTERFACE_ENABLED); + if (hapd->disabled && hapd->started) { + hapd->disabled = 0; + /* + * Try to re-enable interface if the driver stopped it + * when the interface got disabled. + */ + if (hapd->wpa_auth) + wpa_auth_reconfig_group_keys(hapd->wpa_auth); + else + hostapd_reconfig_encryption(hapd); + hapd->reenable_beacon = 1; + ieee802_11_set_beacon(hapd); +#ifdef NEED_AP_MLME + } else if (hapd->disabled && hapd->iface->cac_started) { + wpa_printf(MSG_DEBUG, "DFS: restarting pending CAC"); + hostapd_handle_dfs(hapd->iface); +#endif /* NEED_AP_MLME */ + } + break; + case EVENT_INTERFACE_DISABLED: + hostapd_free_stas(hapd); + wpa_msg(hapd->msg_ctx, MSG_INFO, INTERFACE_DISABLED); + hapd->disabled = 1; + break; +#endif /* CONFIG_FULL_HOSTAPD */ +#ifdef CONFIG_ACS + case EVENT_ACS_CHANNEL_SELECTED: + hostapd_acs_channel_selected(hapd, + &data->acs_selected_channels); + break; +#endif /* CONFIG_ACS */ +#ifdef CONFIG_FULL_HOSTAPD + case EVENT_STATION_OPMODE_CHANGED: + hostapd_event_sta_opmode_changed(hapd, data->sta_opmode.addr, + data->sta_opmode.smps_mode, + data->sta_opmode.chan_width, + data->sta_opmode.rx_nss); + break; + case EVENT_WDS_STA_INTERFACE_STATUS: + hostapd_event_wds_sta_interface_status( + hapd, data->wds_sta_interface.istatus, + data->wds_sta_interface.ifname, + data->wds_sta_interface.sta_addr); + break; +#endif + default: + wpa_printf(MSG_DEBUG, "Unknown event %d", event); + break; + } +} + +#ifdef CONFIG_FULL_HOSTAPD +void wpa_supplicant_event_global(void *ctx, enum wpa_event_type event, + union wpa_event_data *data) +{ + struct hapd_interfaces *interfaces = ctx; + struct hostapd_data *hapd; + + if (event != EVENT_INTERFACE_STATUS) + return; + + hapd = hostapd_get_iface(interfaces, data->interface_status.ifname); + if (hapd && hapd->driver && hapd->driver->get_ifindex && + hapd->drv_priv) { + unsigned int ifindex; + + ifindex = hapd->driver->get_ifindex(hapd->drv_priv); + if (ifindex != data->interface_status.ifindex) { + wpa_dbg(hapd->msg_ctx, MSG_DEBUG, + "interface status ifindex %d mismatch (%d)", + ifindex, data->interface_status.ifindex); + return; + } + } + if (hapd) + wpa_supplicant_event(hapd, event, data); +} +#endif + +#endif /* HOSTAPD */ diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/hostapd.c b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/hostapd.c new file mode 100755 index 0000000..ee7a7fc --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/hostapd.c @@ -0,0 +1,3113 @@ +/* + * hostapd / Initialization and configuration + * Copyright (c) 2002-2019, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ +#include "utils/includes.h" +#include "utils/common.h" +#include "utils/eloop.h" +#include "common/ieee802_11_defs.h" +#include "common/wpa_ctrl.h" +#include "common/hw_features_common.h" +#include "eapol_auth/eapol_auth_sm.h" +#include "eapol_auth/eapol_auth_sm_i.h" +#include "ap/hostapd.h" +#include "ap/sta_info.h" +#include "accounting.h" +#include "ap_list.h" +#include "beacon.h" +#include "ieee802_1x.h" +#include "ieee802_11_auth.h" +#include "vlan_init.h" +#include "wpa_auth.h" +#include "wps_hostapd.h" +#include "dpp_hostapd.h" +#include "hw_features.h" +#include "wpa_auth_glue.h" +#include "ap_drv_ops.h" +#include "ap_config.h" +#include "p2p_hostapd.h" +#include "ap/dfs.h" +#include "ieee802_11.h" +#include "bss_load.h" +#include "wpa_auth_kay.h" +#include "errno-base.h" +#include "include.h" +#include "uart_pub.h" + +static int hostapd_flush_old_stations(struct hostapd_data *hapd, u16 reason); +static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd); +static int hostapd_broadcast_wep_clear(struct hostapd_data *hapd); +static int setup_interface2(struct hostapd_iface *iface); +static void channel_list_update_timeout(void *eloop_ctx, void *timeout_ctx); +static void hostapd_interface_setup_failure_handler(void *eloop_ctx, + void *timeout_ctx); + + +int hostapd_for_each_interface(struct hapd_interfaces *interfaces, + int (*cb)(struct hostapd_iface *iface, + void *ctx), void *ctx) +{ + size_t i; + int ret; + + for (i = 0; i < interfaces->count; i++) { + ret = cb(interfaces->iface[i], ctx); + if (ret) + return ret; + } + + return 0; +} + + +void hostapd_reconfig_encryption(struct hostapd_data *hapd) +{ + if (hapd->wpa_auth) + return; + + hostapd_set_privacy(hapd, 0); + hostapd_setup_encryption(hapd->conf->iface, hapd); +} + + +static void hostapd_reload_bss(struct hostapd_data *hapd) +{ + struct hostapd_ssid *ssid; + + if (!hapd->started) + return; + + if (hapd->conf->wmm_enabled < 0) + hapd->conf->wmm_enabled = hapd->iconf->ieee80211n; + +#ifndef CONFIG_NO_RADIUS + radius_client_reconfig(hapd->radius, hapd->conf->radius); +#endif /* CONFIG_NO_RADIUS */ + + ssid = &hapd->conf->ssid; + if (!ssid->wpa_psk_set && ssid->wpa_psk && !ssid->wpa_psk->next && + ssid->wpa_passphrase_set && ssid->wpa_passphrase) { + /* + * Force PSK to be derived again since SSID or passphrase may + * have changed. + */ + hostapd_config_clear_wpa_psk(&hapd->conf->ssid.wpa_psk); + } + if (hostapd_setup_wpa_psk(hapd->conf)) { + wpa_printf(MSG_ERROR, "Failed to re-configure WPA PSK " + "after reloading configuration"); + } + + if (hapd->conf->ieee802_1x || hapd->conf->wpa) + hostapd_set_drv_ieee8021x(hapd, hapd->conf->iface, 1); + else + hostapd_set_drv_ieee8021x(hapd, hapd->conf->iface, 0); + + if ((hapd->conf->wpa || hapd->conf->osen) && hapd->wpa_auth == NULL) { + hostapd_setup_wpa(hapd); + if (hapd->wpa_auth) + wpa_init_keys(hapd->wpa_auth); + } else if (hapd->conf->wpa) { + const u8 *wpa_ie; + size_t wpa_ie_len = 0; + hostapd_reconfig_wpa(hapd); + wpa_ie = wpa_auth_get_wpa_ie(hapd->wpa_auth, &wpa_ie_len); + if (hostapd_set_generic_elem(hapd, wpa_ie, wpa_ie_len)) + wpa_printf(MSG_ERROR, "Failed to configure WPA IE for " + "the kernel driver."); + } else if (hapd->wpa_auth) { + wpa_deinit(hapd->wpa_auth); + hapd->wpa_auth = NULL; + hostapd_set_privacy(hapd, 0); + hostapd_setup_encryption(hapd->conf->iface, hapd); + hostapd_set_generic_elem(hapd, (u8 *) "", 0); + } + + ieee802_11_set_beacon(hapd); + hostapd_update_wps(hapd); + + if (hapd->conf->ssid.ssid_set && + hostapd_set_ssid(hapd, hapd->conf->ssid.ssid, + hapd->conf->ssid.ssid_len)) { + wpa_printf(MSG_ERROR, "Could not set SSID for kernel driver"); + /* try to continue */ + } + wpa_printf(MSG_DEBUG, "Reconfigured interface %s", hapd->conf->iface); +} + + +static void hostapd_clear_old(struct hostapd_iface *iface) +{ + size_t j; + + /* + * Deauthenticate all stations since the new configuration may not + * allow them to use the BSS anymore. + */ + for (j = 0; j < iface->num_bss; j++) { + hostapd_flush_old_stations(iface->bss[j], + WLAN_REASON_PREV_AUTH_NOT_VALID); + hostapd_broadcast_wep_clear(iface->bss[j]); + +#ifndef CONFIG_NO_RADIUS + /* TODO: update dynamic data based on changed configuration + * items (e.g., open/close sockets, etc.) */ + radius_client_flush(iface->bss[j]->radius, 0); +#endif /* CONFIG_NO_RADIUS */ + } +} + + +static int hostapd_iface_conf_changed(struct hostapd_config *newconf, + struct hostapd_config *oldconf) +{ + size_t i; + + if (newconf->num_bss != oldconf->num_bss) + return 1; + + for (i = 0; i < newconf->num_bss; i++) { + if (os_strcmp(newconf->bss[i]->iface, + oldconf->bss[i]->iface) != 0) + return 1; + } + + return 0; +} + + +int hostapd_reload_config(struct hostapd_iface *iface) +{ +#ifdef CONFIG_FULL_HOSTAPD + struct hapd_interfaces *interfaces = iface->interfaces; +#endif + struct hostapd_data *hapd = iface->bss[0]; + struct hostapd_config *newconf, *oldconf; + size_t j; + +#if CFG_WPA_CTRL_IFACE + if (hostapd_csa_in_progress(iface)) { + return -2; + } +#endif + + if (iface->config_fname == NULL) { + /* Only in-memory config in use - assume it has been updated */ + hostapd_clear_old(iface); + for (j = 0; j < iface->num_bss; j++) + hostapd_reload_bss(iface->bss[j]); + return 0; + } + + if (iface->interfaces == NULL || + iface->interfaces->config_read_cb == NULL) + return -1; + newconf = iface->interfaces->config_read_cb(iface->config_fname); + if (newconf == NULL) + return -1; + + hostapd_clear_old(iface); + + oldconf = hapd->iconf; + +#ifdef CONFIG_FULL_HOSTAPD + if (hostapd_iface_conf_changed(newconf, oldconf)) { + char *fname; + int res; + + wpa_printf(MSG_DEBUG, + "Configuration changes include interface/BSS modification - force full disable+enable sequence"); + fname = os_strdup(iface->config_fname); + if (!fname) { + hostapd_config_free(newconf); + return -1; + } + hostapd_remove_iface(interfaces, hapd->conf->iface); + iface = hostapd_init(interfaces, fname); + os_free(fname); + hostapd_config_free(newconf); + if (!iface) { + wpa_printf(MSG_ERROR, + "Failed to initialize interface on config reload"); + return -1; + } + iface->interfaces = interfaces; + interfaces->iface[interfaces->count] = iface; + interfaces->count++; + res = hostapd_enable_iface(iface); + if (res < 0) + wpa_printf(MSG_ERROR, + "Failed to enable interface on config reload"); + return res; + } +#endif + + iface->conf = newconf; + + for (j = 0; j < iface->num_bss; j++) { + hapd = iface->bss[j]; + hapd->iconf = newconf; + hapd->iconf->channel = oldconf->channel; + hapd->iconf->acs = oldconf->acs; + hapd->iconf->secondary_channel = oldconf->secondary_channel; + hapd->iconf->ieee80211n = oldconf->ieee80211n; + hapd->iconf->ieee80211ac = oldconf->ieee80211ac; + hapd->iconf->ht_capab = oldconf->ht_capab; + hapd->iconf->vht_capab = oldconf->vht_capab; + hostapd_set_oper_chwidth(hapd->iconf, + hostapd_get_oper_chwidth(oldconf)); + hostapd_set_oper_centr_freq_seg0_idx( + hapd->iconf, + hostapd_get_oper_centr_freq_seg0_idx(oldconf)); + hostapd_set_oper_centr_freq_seg1_idx( + hapd->iconf, + hostapd_get_oper_centr_freq_seg1_idx(oldconf)); + hapd->conf = newconf->bss[j]; + hostapd_reload_bss(hapd); + } + + hostapd_config_free(oldconf); + + + return 0; +} + + +static void hostapd_broadcast_key_clear_iface(struct hostapd_data *hapd, + const char *ifname) +{ + int i; + + if (!ifname || !hapd->drv_priv) + return; + for (i = 0; i < NUM_WEP_KEYS; i++) { + if (hostapd_drv_set_key(ifname, hapd, WPA_ALG_NONE, NULL, i, + 0, NULL, 0, NULL, 0)) { + wpa_printf(MSG_DEBUG, "Failed to clear default " + "encryption keys (ifname=%s keyidx=%d)", + ifname, i); + } + } +#ifdef CONFIG_IEEE80211W_AP + if (hapd->conf->ieee80211w) { + for (i = NUM_WEP_KEYS; i < NUM_WEP_KEYS + 2; i++) { + if (hostapd_drv_set_key(ifname, hapd, WPA_ALG_NONE, + NULL, i, 0, NULL, + 0, NULL, 0)) { + wpa_printf(MSG_DEBUG, "Failed to clear " + "default mgmt encryption keys " + "(ifname=%s keyidx=%d)", ifname, i); + } + } + } +#endif /* CONFIG_IEEE80211W_AP */ +} + + +static int hostapd_broadcast_wep_clear(struct hostapd_data *hapd) +{ + hostapd_broadcast_key_clear_iface(hapd, hapd->conf->iface); + return 0; +} + + +static int hostapd_broadcast_wep_set(struct hostapd_data *hapd) +{ + int errors = 0, idx; + struct hostapd_ssid *ssid = &hapd->conf->ssid; + + idx = ssid->wep.idx; + if (ssid->wep.default_len && + hostapd_drv_set_key(hapd->conf->iface, + hapd, WPA_ALG_WEP, broadcast_ether_addr, idx, + 1, NULL, 0, ssid->wep.key[idx], + ssid->wep.len[idx])) { + wpa_printf(MSG_WARNING, "Could not set WEP encryption."); + errors++; + } + + return errors; +} + + +static void hostapd_free_hapd_data(struct hostapd_data *hapd) +{ + os_free(hapd->probereq_cb); + hapd->probereq_cb = NULL; + hapd->num_probereq_cb = 0; + +#ifdef CONFIG_P2P + wpabuf_free(hapd->p2p_beacon_ie); + hapd->p2p_beacon_ie = NULL; + wpabuf_free(hapd->p2p_probe_resp_ie); + hapd->p2p_probe_resp_ie = NULL; +#endif /* CONFIG_P2P */ + + if (!hapd->started) { + wpa_printf(MSG_ERROR, "%s: Interface %s wasn't started", + __func__, hapd->conf ? hapd->conf->iface : "N/A"); + return; + } + hapd->started = 0; + hapd->beacon_set_done = 0; + + wpa_printf(MSG_DEBUG, "%s(%s)", __func__, hapd->conf->iface); +#ifdef CONFIG_FULL_HOSTAPD + iapp_deinit(hapd->iapp); + hapd->iapp = NULL; + accounting_deinit(hapd); +#endif + hostapd_deinit_wpa(hapd); +#ifdef CONFIG_FULL_HOSTAPD + vlan_deinit(hapd); + hostapd_acl_deinit(hapd); +#endif +#ifndef CONFIG_NO_RADIUS + radius_client_deinit(hapd->radius); + hapd->radius = NULL; + radius_das_deinit(hapd->radius_das); + hapd->radius_das = NULL; +#endif /* CONFIG_NO_RADIUS */ + + hostapd_deinit_wps(hapd); +#ifdef IEEE8021X_EAPOL + ieee802_1x_dealloc_kay_sm_hapd(hapd); +#endif +#ifdef CONFIG_DPP + hostapd_dpp_deinit(hapd); +#endif +#ifdef CONFIG_AS + gas_query_ap_deinit(hapd->gas); +#endif /* CONFIG_DPP */ +#ifdef CONFIG_EAPOL + authsrv_deinit(hapd); +#endif + + if (hapd->interface_added) { + hapd->interface_added = 0; + if (hostapd_if_remove(hapd, WPA_IF_AP_BSS, hapd->conf->iface)) { + wpa_printf(MSG_WARNING, + "Failed to remove BSS interface %s", + hapd->conf->iface); + hapd->interface_added = 1; + } else { + /* + * Since this was a dynamically added interface, the + * driver wrapper may have removed its internal instance + * and hapd->drv_priv is not valid anymore. + */ + hapd->drv_priv = NULL; + } + } + +#ifdef CONFIG_FULL_HOSTAPD + wpabuf_free(hapd->time_adv); +#endif +#ifdef CONFIG_INTERWORKING + gas_serv_deinit(hapd); +#endif /* CONFIG_INTERWORKING */ + +#ifdef CONFIG_FULL_HOSTAPD + bss_load_update_deinit(hapd); + ndisc_snoop_deinit(hapd); + dhcp_snoop_deinit(hapd); + x_snoop_deinit(hapd); +#endif +#ifdef CONFIG_SQLITE + bin_clear_free(hapd->tmp_eap_user.identity, + hapd->tmp_eap_user.identity_len); + bin_clear_free(hapd->tmp_eap_user.password, + hapd->tmp_eap_user.password_len); +#endif /* CONFIG_SQLITE */ + +#ifdef CONFIG_MESH + wpabuf_free(hapd->mesh_pending_auth); + hapd->mesh_pending_auth = NULL; +#endif /* CONFIG_MESH */ +#ifdef CONFIG_SAE_AP + { + struct hostapd_sae_commit_queue *q; + + while ((q = dl_list_first(&hapd->sae_commit_queue, + struct hostapd_sae_commit_queue, + list))) { + dl_list_del(&q->list); + os_free(q); + } + } + eloop_cancel_timeout(auth_sae_process_commit, hapd, NULL); +#endif /* CONFIG_SAE_AP */ +} + + +/** + * hostapd_cleanup - Per-BSS cleanup (deinitialization) + * @hapd: Pointer to BSS data + * + * This function is used to free all per-BSS data structures and resources. + * Most of the modules that are initialized in hostapd_setup_bss() are + * deinitialized here. + */ +static void hostapd_cleanup(struct hostapd_data *hapd) +{ + wpa_printf(MSG_DEBUG, "%s(hapd=%p (%s))", __func__, hapd, + hapd->conf ? hapd->conf->iface : "N/A"); + if (hapd->iface->interfaces && + hapd->iface->interfaces->ctrl_iface_deinit) { + wpa_msg(hapd->msg_ctx, MSG_INFO, WPA_EVENT_TERMINATING); + hapd->iface->interfaces->ctrl_iface_deinit(hapd); + } + hostapd_free_hapd_data(hapd); +} + + +static void sta_track_deinit(struct hostapd_iface *iface) +{ + struct hostapd_sta_info *info; + + if (!iface->num_sta_seen) + return; + + while (0 != (info = dl_list_first(&iface->sta_seen, struct hostapd_sta_info, + list))) { + dl_list_del(&info->list); + iface->num_sta_seen--; + sta_track_del(info); + } +} + + +static void hostapd_cleanup_iface_partial(struct hostapd_iface *iface) +{ + wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface); +#ifdef CONFIG_IEEE80211N +#ifdef NEED_AP_MLME + hostapd_stop_setup_timers(iface); +#endif /* NEED_AP_MLME */ +#endif /* CONFIG_IEEE80211N */ + + hostapd_free_hw_features(iface->hw_features, iface->num_hw_features); + iface->hw_features = NULL; + iface->current_mode = NULL; + os_free(iface->current_rates); + iface->current_rates = NULL; + os_free(iface->basic_rates); + iface->basic_rates = NULL; + ap_list_deinit(iface); + sta_track_deinit(iface); +} + + +/** + * hostapd_cleanup_iface - Complete per-interface cleanup + * @iface: Pointer to interface data + * + * This function is called after per-BSS data structures are deinitialized + * with hostapd_cleanup(). + */ +static void hostapd_cleanup_iface(struct hostapd_iface *iface) +{ + wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface); + eloop_cancel_timeout(channel_list_update_timeout, iface, NULL); + eloop_cancel_timeout(hostapd_interface_setup_failure_handler, iface, + NULL); + + hostapd_cleanup_iface_partial(iface); + hostapd_config_free(iface->conf); + iface->conf = NULL; + + os_free(iface->config_fname); + os_free(iface->bss); + wpa_printf(MSG_DEBUG, "%s: free iface=%p", __func__, iface); + os_free(iface); +} + + +static void hostapd_clear_wep(struct hostapd_data *hapd) +{ + if (hapd->drv_priv && !hapd->iface->driver_ap_teardown && hapd->conf) { + hostapd_set_privacy(hapd, 0); + hostapd_broadcast_wep_clear(hapd); + } +} + + +static int hostapd_setup_encryption(char *iface, struct hostapd_data *hapd) +{ + int i; + + hostapd_broadcast_wep_set(hapd); + + if (hapd->conf->ssid.wep.default_len) { + hostapd_set_privacy(hapd, 1); + return 0; + } + + /* + * When IEEE 802.1X is not enabled, the driver may need to know how to + * set authentication algorithms for static WEP. + */ + hostapd_drv_set_authmode(hapd, hapd->conf->auth_algs); + + for (i = 0; i < 4; i++) { + if (hapd->conf->ssid.wep.key[i] && + hostapd_drv_set_key(iface, hapd, WPA_ALG_WEP, NULL, i, + i == hapd->conf->ssid.wep.idx, NULL, 0, + hapd->conf->ssid.wep.key[i], + hapd->conf->ssid.wep.len[i])) { + wpa_printf(MSG_WARNING, "Could not set WEP " + "encryption."); + return -1; + } + if (hapd->conf->ssid.wep.key[i] && + i == hapd->conf->ssid.wep.idx) + hostapd_set_privacy(hapd, 1); + } + + return 0; +} + + +static int hostapd_flush_old_stations(struct hostapd_data *hapd, u16 reason) +{ + int ret = 0; + u8 addr[ETH_ALEN]; + + if (hostapd_drv_none(hapd) || hapd->drv_priv == NULL) + return 0; + + if (!hapd->iface->driver_ap_teardown) { + wpa_dbg(hapd->msg_ctx, MSG_DEBUG, + "Flushing old station entries"); + + if (hostapd_flush(hapd)) { + wpa_msg(hapd->msg_ctx, MSG_WARNING, + "Could not connect to kernel driver"); + ret = -1; + } + } + if (hapd->conf && hapd->conf->broadcast_deauth) { + wpa_dbg(hapd->msg_ctx, MSG_DEBUG, + "Deauthenticate all stations"); + os_memset(addr, 0xff, ETH_ALEN); + hostapd_drv_sta_deauth(hapd, addr, reason); + } + hostapd_free_stas(hapd); + + return ret; +} + + +static void hostapd_bss_deinit_no_free(struct hostapd_data *hapd) +{ + hostapd_free_stas(hapd); + hostapd_flush_old_stations(hapd, WLAN_REASON_DEAUTH_LEAVING); + hostapd_clear_wep(hapd); +} + + +/** + * hostapd_validate_bssid_configuration - Validate BSSID configuration + * @iface: Pointer to interface data + * Returns: 0 on success, -1 on failure + * + * This function is used to validate that the configured BSSIDs are valid. + */ +static int hostapd_validate_bssid_configuration(struct hostapd_iface *iface) +{ + u8 mask[ETH_ALEN] = { 0 }; + struct hostapd_data *hapd = iface->bss[0]; + unsigned int i = iface->conf->num_bss, bits = 0, j; + int auto_addr = 0; + + if (hostapd_drv_none(hapd)) + return 0; + + if (iface->conf->use_driver_iface_addr) + return 0; + + /* Generate BSSID mask that is large enough to cover the BSSIDs. */ + + /* Determine the bits necessary to cover the number of BSSIDs. */ + for (i--; i; i >>= 1) + bits++; + + /* Determine the bits necessary to any configured BSSIDs, + if they are higher than the number of BSSIDs. */ + for (j = 0; j < iface->conf->num_bss; j++) { + if (is_zero_ether_addr(iface->conf->bss[j]->bssid)) { + if (j) + auto_addr++; + continue; + } + + for (i = 0; i < ETH_ALEN; i++) { + mask[i] |= + iface->conf->bss[j]->bssid[i] ^ + hapd->own_addr[i]; + } + } + + if (!auto_addr) + goto skip_mask_ext; + + for (i = 0; i < ETH_ALEN && mask[i] == 0; i++) + ; + j = 0; + if (i < ETH_ALEN) { + j = (5 - i) * 8; + + while (mask[i] != 0) { + mask[i] >>= 1; + j++; + } + } + + if (bits < j) + bits = j; + + if (bits > 40) { + wpa_printf(MSG_ERROR, "Too many bits in the BSSID mask (%u)", + bits); + return -1; + } + + os_memset(mask, 0xff, ETH_ALEN); + j = bits / 8; + for (i = 5; i > 5 - j; i--) + mask[i] = 0; + j = bits % 8; + while (j) { + j--; + mask[i] <<= 1; + } + +skip_mask_ext: + wpa_printf(MSG_DEBUG, "BSS count %lu, BSSID mask " MACSTR " (%d bits)", + (unsigned long) iface->conf->num_bss, MAC2STR(mask), bits); + + if (!auto_addr) + return 0; + + for (i = 0; i < ETH_ALEN; i++) { + if ((hapd->own_addr[i] & mask[i]) != hapd->own_addr[i]) { + wpa_printf(MSG_ERROR, "Invalid BSSID mask " MACSTR + " for start address " MACSTR ".", + MAC2STR(mask), MAC2STR(hapd->own_addr)); + wpa_printf(MSG_ERROR, "Start address must be the " + "first address in the block (i.e., addr " + "AND mask == addr)."); + return -1; + } + } + + return 0; +} + + +static int mac_in_conf(struct hostapd_config *conf, const void *a) +{ + size_t i; + + for (i = 0; i < conf->num_bss; i++) { + if (hostapd_mac_comp(conf->bss[i]->bssid, a) == 0) { + return 1; + } + } + + return 0; +} + + +/** + * hostapd_setup_bss - Per-BSS setup (initialization) + * @hapd: Pointer to BSS data + * @first: Whether this BSS is the first BSS of an interface; -1 = not first, + * but interface may exist + * + * This function is used to initialize all per-BSS data structures and + * resources. This gets called in a loop for each BSS when an interface is + * initialized. Most of the modules that are initialized here will be + * deinitialized in hostapd_cleanup(). + */ +static int hostapd_setup_bss(struct hostapd_data *hapd, int first) +{ + struct hostapd_bss_config *conf = hapd->conf; + u8 ssid[SSID_MAX_LEN + 1]; + int ssid_len, set_ssid; + char force_ifname[IFNAMSIZ]; + u8 if_addr[ETH_ALEN]; + int flush_old_stations = 1; + + wpa_printf(MSG_DEBUG, "%s(hapd=%p (%s), first=%d)", + __func__, hapd, conf->iface, first); + +#ifdef EAP_SERVER_TNC + if (conf->tnc && tncs_global_init() < 0) { + wpa_printf(MSG_ERROR, "Failed to initialize TNCS"); + return -1; + } +#endif /* EAP_SERVER_TNC */ + + if (hapd->started) { + wpa_printf(MSG_ERROR, "%s: Interface %s was already started", + __func__, conf->iface); + return -1; + } + hapd->started = 1; + + if (!first || first == -1) { + u8 *addr = hapd->own_addr; + + if (!is_zero_ether_addr(conf->bssid)) { + /* Allocate the configured BSSID. */ + os_memcpy(hapd->own_addr, conf->bssid, ETH_ALEN); + + if (hostapd_mac_comp(hapd->own_addr, + hapd->iface->bss[0]->own_addr) == + 0) { + wpa_printf(MSG_ERROR, "BSS '%s' may not have " + "BSSID set to the MAC address of " + "the radio", conf->iface); + return -1; + } + } else if (hapd->iconf->use_driver_iface_addr) { + addr = NULL; + } else { + /* Allocate the next available BSSID. */ + do { + inc_byte_array(hapd->own_addr, ETH_ALEN); + } while (mac_in_conf(hapd->iconf, hapd->own_addr)); + } + + hapd->interface_added = 1; + if (hostapd_if_add(hapd->iface->bss[0], WPA_IF_AP_BSS, + conf->iface, addr, hapd, + &hapd->drv_priv, force_ifname, if_addr, +#ifdef CONFIG_FULL_HOSTAPD + conf->bridge[0] ? conf->bridge : NULL, +#else + NULL, +#endif + first == -1)) { + wpa_printf(MSG_ERROR, "Failed to add BSS (BSSID=" + MACSTR ")", MAC2STR(hapd->own_addr)); + hapd->interface_added = 0; + return -1; + } + + if (!addr) + os_memcpy(hapd->own_addr, if_addr, ETH_ALEN); + } + + if (conf->wmm_enabled < 0) + conf->wmm_enabled = hapd->iconf->ieee80211n; + +#ifdef CONFIG_IEEE80211R_AP + if (is_zero_ether_addr(conf->r1_key_holder)) + os_memcpy(conf->r1_key_holder, hapd->own_addr, ETH_ALEN); +#endif /* CONFIG_IEEE80211R_AP */ + +#ifdef CONFIG_MESH + if ((hapd->conf->mesh & MESH_ENABLED) && hapd->iface->mconf == NULL) + flush_old_stations = 0; +#endif /* CONFIG_MESH */ + + if (flush_old_stations) + hostapd_flush_old_stations(hapd, + WLAN_REASON_PREV_AUTH_NOT_VALID); + hostapd_set_privacy(hapd, 0); + + hostapd_broadcast_wep_clear(hapd); + if (hostapd_setup_encryption(conf->iface, hapd)) + return -1; + + /* + * Fetch the SSID from the system and use it or, + * if one was specified in the config file, verify they + * match. + */ + ssid_len = hostapd_get_ssid(hapd, ssid, sizeof(ssid)); + if (ssid_len < 0) { + wpa_printf(MSG_ERROR, "Could not read SSID from system"); + return -1; + } + if (conf->ssid.ssid_set) { + /* + * If SSID is specified in the config file and it differs + * from what is being used then force installation of the + * new SSID. + */ + set_ssid = (conf->ssid.ssid_len != (size_t) ssid_len || + os_memcmp(conf->ssid.ssid, ssid, ssid_len) != 0); + } else { + /* + * No SSID in the config file; just use the one we got + * from the system. + */ + set_ssid = 0; + conf->ssid.ssid_len = ssid_len; + os_memcpy(conf->ssid.ssid, ssid, conf->ssid.ssid_len); + } + + if (!hostapd_drv_none(hapd)) { + wpa_printf(MSG_ERROR, "Using interface %s with hwaddr " MACSTR + " and ssid \"%s\"", + conf->iface, MAC2STR(hapd->own_addr), + wpa_ssid_txt(conf->ssid.ssid, conf->ssid.ssid_len)); + } + + if (hostapd_setup_wpa_psk(conf)) { + wpa_printf(MSG_ERROR, "WPA-PSK setup failed."); + return -1; + } + + /* Set SSID for the kernel driver (to be used in beacon and probe + * response frames) */ + if (set_ssid && hostapd_set_ssid(hapd, conf->ssid.ssid, + conf->ssid.ssid_len)) { + wpa_printf(MSG_ERROR, "Could not set SSID for kernel driver"); + return -1; + } + + + if (hostapd_acl_init(hapd)) { + wpa_printf(MSG_ERROR, "ACL initialization failed."); + return -1; + } + if (hostapd_init_wps(hapd, conf)) + return -1; + +#ifdef CONFIG_GAS + hapd->gas = gas_query_ap_init(hapd, hapd->msg_ctx); + if (!hapd->gas) + return -1; +#endif +#ifdef CONFIG_DPP + if (hostapd_dpp_init(hapd)) + return -1; +#endif /* CONFIG_DPP */ + + +#ifdef CONFIG_FULL_HOSTAPD + if (authsrv_init(hapd) < 0) + return -1; + + if (ieee802_1x_init(hapd)) { + wpa_printf(MSG_ERROR, "IEEE 802.1X initialization failed."); + return -1; + } +#endif + + if ((conf->wpa || conf->osen) && hostapd_setup_wpa(hapd)) + return -1; + + if (accounting_init(hapd)) { + wpa_printf(MSG_ERROR, "Accounting initialization failed."); + return -1; + } + +#ifdef CONFIG_FULL_HOSTAPD + if (conf->ieee802_11f && + (hapd->iapp = iapp_init(hapd, conf->iapp_iface)) == NULL) { + wpa_printf(MSG_ERROR, "IEEE 802.11F (IAPP) initialization " + "failed."); + return -1; + } +#endif +#ifdef CONFIG_INTERWORKING + if (gas_serv_init(hapd)) { + wpa_printf(MSG_ERROR, "GAS server initialization failed"); + return -1; + } + + if (conf->qos_map_set_len && + hostapd_drv_set_qos_map(hapd, conf->qos_map_set, + conf->qos_map_set_len)) { + wpa_printf(MSG_ERROR, "Failed to initialize QoS Map"); + return -1; + } +#endif /* CONFIG_INTERWORKING */ + +#ifdef CONFIG_FULL_HOSTAPD + if (conf->bss_load_update_period && bss_load_update_init(hapd)) { + wpa_printf(MSG_ERROR, "BSS Load initialization failed"); + return -1; + } + + if (conf->proxy_arp) { + if (x_snoop_init(hapd)) { + wpa_printf(MSG_ERROR, + "Generic snooping infrastructure initialization failed"); + return -1; + } + + if (dhcp_snoop_init(hapd)) { + wpa_printf(MSG_ERROR, + "DHCP snooping initialization failed"); + return -1; + } + + if (ndisc_snoop_init(hapd)) { + wpa_printf(MSG_ERROR, + "Neighbor Discovery snooping initialization failed"); + return -1; + } + } + + if (!hostapd_drv_none(hapd) && vlan_init(hapd)) { + wpa_printf(MSG_ERROR, "VLAN initialization failed."); + return -1; + } +#endif + + if (!conf->start_disabled && ieee802_11_set_beacon(hapd) < 0) + return -1; + + if (hapd->wpa_auth && wpa_init_keys(hapd->wpa_auth) < 0) + return -1; + + if (hapd->driver && hapd->driver->set_operstate) + hapd->driver->set_operstate(hapd->drv_priv, 1); + + return 0; +} + + +static void hostapd_tx_queue_params(struct hostapd_iface *iface) +{ + struct hostapd_data *hapd = iface->bss[0]; + int i; + struct hostapd_tx_queue_params *p; + +#ifdef CONFIG_MESH + if ((hapd->conf->mesh & MESH_ENABLED) && iface->mconf == NULL) + return; +#endif /* CONFIG_MESH */ + + for (i = 0; i < NUM_TX_QUEUES; i++) { + p = &iface->conf->tx_queue[i]; + + if (hostapd_set_tx_queue_params(hapd, i, p->aifs, p->cwmin, + p->cwmax, p->burst)) { + wpa_printf(MSG_DEBUG, "Failed to set TX queue " + "parameters for queue %d.", i); + /* Continue anyway */ + } + } +} + +#ifdef CONFIG_FULL_HOSTAPD + +static int hostapd_set_acl_list(struct hostapd_data *hapd, + struct mac_acl_entry *mac_acl, + int n_entries, u8 accept_acl) +{ + struct hostapd_acl_params *acl_params; + int i, err; + + acl_params = os_zalloc(sizeof(*acl_params) + + (n_entries * sizeof(acl_params->mac_acl[0]))); + if (!acl_params) + return -ERRNOMEM; + + for (i = 0; i < n_entries; i++) + os_memcpy(acl_params->mac_acl[i].addr, mac_acl[i].addr, + ETH_ALEN); + + acl_params->acl_policy = accept_acl; + acl_params->num_mac_acl = n_entries; + + err = hostapd_drv_set_acl(hapd, acl_params); + + os_free(acl_params); + + return err; +} + + +static void hostapd_set_acl(struct hostapd_data *hapd) +{ + struct hostapd_config *conf = hapd->iconf; + int err; + u8 accept_acl; + + if (hapd->iface->drv_max_acl_mac_addrs == 0) + return; + + if (conf->bss[0]->macaddr_acl == DENY_UNLESS_ACCEPTED) { + accept_acl = 1; + err = hostapd_set_acl_list(hapd, conf->bss[0]->accept_mac, + conf->bss[0]->num_accept_mac, + accept_acl); + if (err) { + wpa_printf(MSG_DEBUG, "Failed to set accept acl"); + return; + } + } else if (conf->bss[0]->macaddr_acl == ACCEPT_UNLESS_DENIED) { + accept_acl = 0; + err = hostapd_set_acl_list(hapd, conf->bss[0]->deny_mac, + conf->bss[0]->num_deny_mac, + accept_acl); + if (err) { + wpa_printf(MSG_DEBUG, "Failed to set deny acl"); + return; + } + } +} +#endif /* CONFIG_FULL_HOSTAPD */ + +static int start_ctrl_iface_bss(struct hostapd_data *hapd) +{ +#ifdef CONFIG_FULL_HOSTAPD + if (!hapd->iface->interfaces || + !hapd->iface->interfaces->ctrl_iface_init) + return 0; + + if (hapd->iface->interfaces->ctrl_iface_init(hapd)) { + wpa_printf(MSG_ERROR, + "Failed to setup control interface for %s", + hapd->conf->iface); + return -1; + } +#endif + + return 0; +} + + +static int start_ctrl_iface(struct hostapd_iface *iface) +{ +#ifdef CONFIG_FULL_HOSTAPD + size_t i; + + if (!iface->interfaces || !iface->interfaces->ctrl_iface_init) + return 0; + + for (i = 0; i < iface->num_bss; i++) { + struct hostapd_data *hapd = iface->bss[i]; + if (iface->interfaces->ctrl_iface_init(hapd)) { + wpa_printf(MSG_ERROR, + "Failed to setup control interface for %s", + hapd->conf->iface); + return -1; + } + } +#endif + + return 0; +} + + +static void channel_list_update_timeout(void *eloop_ctx, void *timeout_ctx) +{ + struct hostapd_iface *iface = eloop_ctx; + + if (!iface->wait_channel_update) { + wpa_printf(MSG_INFO, "Channel list update timeout, but interface was not waiting for it"); + return; + } + + /* + * It is possible that the existing channel list is acceptable, so try + * to proceed. + */ + wpa_printf(MSG_DEBUG, "Channel list update timeout - try to continue anyway"); + setup_interface2(iface); +} + + +void hostapd_channel_list_updated(struct hostapd_iface *iface, int initiator) +{ + if (!iface->wait_channel_update || initiator != REGDOM_SET_BY_USER) + return; + + wpa_printf(MSG_DEBUG, "Channel list updated - continue setup"); + eloop_cancel_timeout(channel_list_update_timeout, iface, NULL); + setup_interface2(iface); +} + + +static int setup_interface(struct hostapd_iface *iface) +{ + struct hostapd_data *hapd = iface->bss[0]; + size_t i; + + /* + * It is possible that setup_interface() is called after the interface + * was disabled etc., in which case driver_ap_teardown is possibly set + * to 1. Clear it here so any other key/station deletion, which is not + * part of a teardown flow, would also call the relevant driver + * callbacks. + */ + iface->driver_ap_teardown = 0; + + if (!iface->phy[0]) { + const char *phy = hostapd_drv_get_radio_name(hapd); + if (phy) { + wpa_printf(MSG_DEBUG, "phy: %s", phy); + os_strlcpy(iface->phy, phy, sizeof(iface->phy)); + } + } + + //if (iface->num_bss != iface->conf->num_bss) { + // os_printf("%s num_bss=%d vs %d\n", __FUNCTION__, iface->num_bss, iface->conf->num_bss); + // return -1; + //} + + /* + * Make sure that all BSSes get configured with a pointer to the same + * driver interface. + */ + for (i = 1; i < iface->num_bss; i++) { + iface->bss[i]->driver = hapd->driver; + iface->bss[i]->drv_priv = hapd->drv_priv; + } + + if (hostapd_validate_bssid_configuration(iface)) + return -1; + +#ifdef CONFIG_FULL_HOSTAPD + /* + * Initialize control interfaces early to allow external monitoring of + * channel setup operations that may take considerable amount of time + * especially for DFS cases. + */ + if (start_ctrl_iface(iface)) + return -1; + + if (hapd->iconf->country[0] && hapd->iconf->country[1]) { + char country[4], previous_country[4]; + + hostapd_set_state(iface, HAPD_IFACE_COUNTRY_UPDATE); + if (hostapd_get_country(hapd, previous_country) < 0) + previous_country[0] = '\0'; + + os_memcpy(country, hapd->iconf->country, 3); + country[3] = '\0'; + if (hostapd_set_country(hapd, country) < 0) { + wpa_printf(MSG_ERROR, "Failed to set country code"); + return -1; + } + + wpa_printf(MSG_DEBUG, "Previous country code %s, new country code %s", + previous_country, country); + + if (os_strncmp(previous_country, country, 2) != 0) { + wpa_printf(MSG_DEBUG, "Continue interface setup after channel list update"); + iface->wait_channel_update = 1; + eloop_register_timeout(5, 0, + channel_list_update_timeout, + iface, NULL); + return 0; + } + } +#endif + + return setup_interface2(iface); +} + + +static int setup_interface2(struct hostapd_iface *iface) +{ + iface->wait_channel_update = 0; + + if (hostapd_get_hw_features(iface)) { + /* Not all drivers support this yet, so continue without hw + * feature data. */ + } else { + int ret = hostapd_select_hw_mode(iface); + if (ret < 0) { + wpa_printf(MSG_ERROR, "Could not select hw_mode and " + "channel. (%d)", ret); + goto fail; + } + if (ret == 1) { + wpa_printf(MSG_DEBUG, "Interface initialization will be completed in a callback (ACS)"); + return 0; + } + ret = hostapd_check_ht_capab(iface); + if (ret < 0) + goto fail; + if (ret == 1) { + wpa_printf(MSG_DEBUG, "Interface initialization will " + "be completed in a callback"); + return 0; + } +#ifdef CONFIG_DFS + if (iface->conf->ieee80211h) + wpa_printf(MSG_DEBUG, "DFS support is enabled"); +#endif + } + return hostapd_setup_interface_complete(iface, 0); + +fail: + hostapd_set_state(iface, HAPD_IFACE_DISABLED); + wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, AP_EVENT_DISABLED); + if (iface->interfaces && iface->interfaces->terminate_on_error) + eloop_terminate(); + return -1; +} + + +#ifdef CONFIG_OWE + +static int hostapd_owe_iface_iter(struct hostapd_iface *iface, void *ctx) +{ + struct hostapd_data *hapd = ctx; + size_t i; + + for (i = 0; i < iface->num_bss; i++) { + struct hostapd_data *bss = iface->bss[i]; + + if (os_strcmp(hapd->conf->owe_transition_ifname, + bss->conf->iface) != 0) + continue; + + wpa_printf(MSG_DEBUG, + "OWE: ifname=%s found transition mode ifname=%s BSSID " + MACSTR " SSID %s", + hapd->conf->iface, bss->conf->iface, + MAC2STR(bss->own_addr), + wpa_ssid_txt(bss->conf->ssid.ssid, + bss->conf->ssid.ssid_len)); + if (!bss->conf->ssid.ssid_set || !bss->conf->ssid.ssid_len || + is_zero_ether_addr(bss->own_addr)) + continue; + + os_memcpy(hapd->conf->owe_transition_bssid, bss->own_addr, + ETH_ALEN); + os_memcpy(hapd->conf->owe_transition_ssid, + bss->conf->ssid.ssid, bss->conf->ssid.ssid_len); + hapd->conf->owe_transition_ssid_len = bss->conf->ssid.ssid_len; + wpa_printf(MSG_DEBUG, + "OWE: Copied transition mode information"); + return 1; + } + + return 0; +} + + +int hostapd_owe_trans_get_info(struct hostapd_data *hapd) +{ + if (hapd->conf->owe_transition_ssid_len > 0 && + !is_zero_ether_addr(hapd->conf->owe_transition_bssid)) + return 0; + + /* Find transition mode SSID/BSSID information from a BSS operated by + * this hostapd instance. */ + if (!hapd->iface->interfaces || + !hapd->iface->interfaces->for_each_interface) + return hostapd_owe_iface_iter(hapd->iface, hapd); + else + return hapd->iface->interfaces->for_each_interface( + hapd->iface->interfaces, hostapd_owe_iface_iter, hapd); +} + + +static int hostapd_owe_iface_iter2(struct hostapd_iface *iface, void *ctx) +{ + size_t i; + + for (i = 0; i < iface->num_bss; i++) { + struct hostapd_data *bss = iface->bss[i]; + int res; + + if (!bss->conf->owe_transition_ifname[0]) + continue; + res = hostapd_owe_trans_get_info(bss); + if (res == 0) + continue; + wpa_printf(MSG_DEBUG, + "OWE: Matching transition mode interface enabled - update beacon data for %s", + bss->conf->iface); + ieee802_11_set_beacon(bss); + } + + return 0; +} + +#endif /* CONFIG_OWE */ + + +static void hostapd_owe_update_trans(struct hostapd_iface *iface) +{ +#ifdef CONFIG_OWE + /* Check whether the enabled BSS can complete OWE transition mode + * configuration for any pending interface. */ + if (!iface->interfaces || + !iface->interfaces->for_each_interface) + hostapd_owe_iface_iter2(iface, NULL); + else + iface->interfaces->for_each_interface( + iface->interfaces, hostapd_owe_iface_iter2, NULL); +#endif /* CONFIG_OWE */ +} + + +static void hostapd_interface_setup_failure_handler(void *eloop_ctx, + void *timeout_ctx) +{ + struct hostapd_iface *iface = eloop_ctx; + struct hostapd_data *hapd; + + if (iface->num_bss < 1 || !iface->bss || !iface->bss[0]) + return; + hapd = iface->bss[0]; + if (hapd->setup_complete_cb) + hapd->setup_complete_cb(hapd->setup_complete_cb_ctx); +} + + + +/** + * hostapd_setup_interface_complete - Complete interface setup + * + * This function is called when previous steps in the interface setup has been + * completed. This can also start operations, e.g., DFS, that will require + * additional processing before interface is ready to be enabled. Such + * operations will call this function from eloop callbacks when finished. + */ +static int hostapd_setup_interface_complete_sync(struct hostapd_iface *iface, + int err) +{ + struct hostapd_data *hapd = iface->bss[0]; + size_t j; + u8 *prev_addr; + int delay_apply_cfg = 0; + int res_dfs_offload = 0; + + if (err) + goto fail; + + wpa_printf(MSG_DEBUG, "Completing interface initialization"); + if (iface->conf->channel) { + iface->freq = hostapd_hw_get_freq(hapd, iface->conf->channel); + wpa_printf(MSG_DEBUG, "Mode: %s Channel: %d " + "Frequency: %d MHz", + hostapd_hw_mode_txt(iface->conf->hw_mode), + iface->conf->channel, iface->freq); + +#ifdef NEED_AP_MLME + /* Handle DFS only if it is not offloaded to the driver */ +#ifdef CONFIG_DFS + if (!(iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD)) { + /* Check DFS */ + int res = hostapd_handle_dfs(iface); + if (res <= 0) { + if (res < 0) + goto fail; + return res; + } + } else { + /* If DFS is offloaded to the driver */ + res_dfs_offload = hostapd_handle_dfs_offload(iface); + if (res_dfs_offload <= 0) { + if (res_dfs_offload < 0) + goto fail; + } else { + wpa_printf(MSG_DEBUG, + "Proceed with AP/channel setup"); + /* + * If this is a DFS channel, move to completing + * AP setup. + */ + if (res_dfs_offload == 1) + goto dfs_offload; + /* Otherwise fall through. */ + } + } +#endif +#endif /* NEED_AP_MLME */ + +#ifdef CONFIG_MESH + if (iface->mconf != NULL) { + wpa_printf(MSG_DEBUG, + "%s: Mesh configuration will be applied while joining the mesh network", + iface->bss[0]->conf->iface); + delay_apply_cfg = 1; + } +#endif /* CONFIG_MESH */ + + if (!delay_apply_cfg && + hostapd_set_freq(hapd, hapd->iconf->hw_mode, iface->freq, + hapd->iconf->channel, + hapd->iconf->ieee80211n, + hapd->iconf->ieee80211ac, + hapd->iconf->ieee80211ax, + hapd->iconf->secondary_channel, + hostapd_get_oper_chwidth(hapd->iconf), + hostapd_get_oper_centr_freq_seg0_idx( + hapd->iconf), + hostapd_get_oper_centr_freq_seg1_idx( + hapd->iconf))) { + wpa_printf(MSG_ERROR, "Could not set channel for " + "kernel driver"); + goto fail; + } + } + + if (iface->current_mode) { + if (hostapd_prepare_rates(iface, iface->current_mode)) { + wpa_printf(MSG_ERROR, "Failed to prepare rates " + "table."); + hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_WARNING, + "Failed to prepare rates table."); + goto fail; + } + } + + if (hapd->iconf->rts_threshold >= -1 && + hostapd_set_rts(hapd, hapd->iconf->rts_threshold) && + hapd->iconf->rts_threshold >= -1) { + wpa_printf(MSG_ERROR, "Could not set RTS threshold for " + "kernel driver"); + goto fail; + } + + if (hapd->iconf->fragm_threshold >= -1 && + hostapd_set_frag(hapd, hapd->iconf->fragm_threshold) && + hapd->iconf->fragm_threshold != -1) { + wpa_printf(MSG_ERROR, "Could not set fragmentation threshold " + "for kernel driver"); + goto fail; + } + + prev_addr = hapd->own_addr; + + for (j = 0; j < iface->num_bss; j++) { + hapd = iface->bss[j]; + if (j) + os_memcpy(hapd->own_addr, prev_addr, ETH_ALEN); + if (hostapd_setup_bss(hapd, j == 0)) { + for (;;) { + hapd = iface->bss[j]; + hostapd_bss_deinit_no_free(hapd); + hostapd_free_hapd_data(hapd); + if (j == 0) + break; + j--; + } + goto fail; + } + if (is_zero_ether_addr(hapd->conf->bssid)) + prev_addr = hapd->own_addr; + } + hapd = iface->bss[0]; + + hostapd_tx_queue_params(iface); + + ap_list_init(iface); + +#ifdef CONFIG_FULL_HOSTAPD + hostapd_set_acl(hapd); +#endif + if (hostapd_driver_commit(hapd) < 0) { + wpa_printf(MSG_ERROR, "%s: Failed to commit driver " + "configuration", __func__); + goto fail; + } + + /* + * WPS UPnP module can be initialized only when the "upnp_iface" is up. + * If "interface" and "upnp_iface" are the same (e.g., non-bridge + * mode), the interface is up only after driver_commit, so initialize + * WPS after driver_commit. + */ + for (j = 0; j < iface->num_bss; j++) { + if (hostapd_init_wps_complete(iface->bss[j])) + goto fail; + } + + if ((iface->drv_flags & WPA_DRIVER_FLAGS_DFS_OFFLOAD) && + !res_dfs_offload) { + /* + * If freq is DFS, and DFS is offloaded to the driver, then wait + * for CAC to complete. + */ + wpa_printf(MSG_DEBUG, "%s: Wait for CAC to complete", __func__); + return res_dfs_offload; + } + +#ifdef NEED_AP_MLME +#ifdef CONFIG_DFS +dfs_offload: +#endif +#endif /* NEED_AP_MLME */ + +#ifdef CONFIG_FST + if (hapd->iconf->fst_cfg.group_id[0]) { + struct fst_wpa_obj iface_obj; + + fst_hostapd_fill_iface_obj(hapd, &iface_obj); + iface->fst = fst_attach(hapd->conf->iface, hapd->own_addr, + &iface_obj, &hapd->iconf->fst_cfg); + if (!iface->fst) { + wpa_printf(MSG_ERROR, "Could not attach to FST %s", + hapd->iconf->fst_cfg.group_id); + goto fail; + } + } +#endif /* CONFIG_FST */ + + hostapd_set_state(iface, HAPD_IFACE_ENABLED); + hostapd_owe_update_trans(iface); + wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, AP_EVENT_ENABLED); + if (hapd->setup_complete_cb) + hapd->setup_complete_cb(hapd->setup_complete_cb_ctx); + + wpa_printf(MSG_DEBUG, "%s: Setup of interface done.", + iface->bss[0]->conf->iface); + if (iface->interfaces && iface->interfaces->terminate_on_error > 0) + iface->interfaces->terminate_on_error--; + +#ifdef CONFIG_FULL_HOSTAPD + for (j = 0; j < iface->num_bss; j++) + hostapd_neighbor_set_own_report(iface->bss[j]); +#endif + + return 0; + +fail: + wpa_printf(MSG_ERROR, "Interface initialization failed"); + hostapd_set_state(iface, HAPD_IFACE_DISABLED); + wpa_msg(hapd->msg_ctx, MSG_INFO, AP_EVENT_DISABLED); +#ifdef CONFIG_FST + if (iface->fst) { + fst_detach(iface->fst); + iface->fst = NULL; + } +#endif /* CONFIG_FST */ + + if (iface->interfaces && iface->interfaces->terminate_on_error) { + eloop_terminate(); + } else if (hapd->setup_complete_cb) { + /* + * Calling hapd->setup_complete_cb directly may cause iface + * deinitialization which may be accessed later by the caller. + */ + eloop_register_timeout(0, 0, + hostapd_interface_setup_failure_handler, + iface, NULL); + } + + return -1; +} + + +/** + * hostapd_setup_interface_complete - Complete interface setup + * + * This function is called when previous steps in the interface setup has been + * completed. This can also start operations, e.g., DFS, that will require + * additional processing before interface is ready to be enabled. Such + * operations will call this function from eloop callbacks when finished. + */ +int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err) +{ +#ifdef CONFIG_FULL_HOSTAPD + struct hapd_interfaces *interfaces = iface->interfaces; + struct hostapd_data *hapd = iface->bss[0]; + unsigned int i; + int not_ready_in_sync_ifaces = 0; +#endif + + if (!iface->need_to_start_in_sync) + return hostapd_setup_interface_complete_sync(iface, err); + +#ifdef CONFIG_FULL_HOSTAPD + if (err) { + wpa_printf(MSG_ERROR, "Interface initialization failed"); + hostapd_set_state(iface, HAPD_IFACE_DISABLED); + iface->need_to_start_in_sync = 0; + wpa_msg(hapd->msg_ctx, MSG_INFO, AP_EVENT_DISABLED); + if (interfaces && interfaces->terminate_on_error) + eloop_terminate(); + return -1; + } + + if (iface->ready_to_start_in_sync) { + /* Already in ready and waiting. should never happpen */ + return 0; + } + + for (i = 0; i < interfaces->count; i++) { + if (interfaces->iface[i]->need_to_start_in_sync && + !interfaces->iface[i]->ready_to_start_in_sync) + not_ready_in_sync_ifaces++; + } + + /* + * Check if this is the last interface, if yes then start all the other + * waiting interfaces. If not, add this interface to the waiting list. + */ + if (not_ready_in_sync_ifaces > 1 && iface->state == HAPD_IFACE_DFS) { + /* + * If this interface went through CAC, do not synchronize, just + * start immediately. + */ + iface->need_to_start_in_sync = 0; + wpa_printf(MSG_INFO, + "%s: Finished CAC - bypass sync and start interface", + iface->bss[0]->conf->iface); + return hostapd_setup_interface_complete_sync(iface, err); + } + + if (not_ready_in_sync_ifaces > 1) { + /* need to wait as there are other interfaces still coming up */ + iface->ready_to_start_in_sync = 1; + wpa_printf(MSG_INFO, + "%s: Interface waiting to sync with other interfaces", + iface->bss[0]->conf->iface); + return 0; + } + + wpa_printf(MSG_INFO, + "%s: Last interface to sync - starting all interfaces", + iface->bss[0]->conf->iface); + iface->need_to_start_in_sync = 0; + hostapd_setup_interface_complete_sync(iface, err); + for (i = 0; i < interfaces->count; i++) { + if (interfaces->iface[i]->need_to_start_in_sync && + interfaces->iface[i]->ready_to_start_in_sync) { + hostapd_setup_interface_complete_sync( + interfaces->iface[i], 0); + /* Only once the interfaces are sync started */ + interfaces->iface[i]->need_to_start_in_sync = 0; + } + } +#endif + + return 0; +} + + +/** + * hostapd_setup_interface - Setup of an interface + * @iface: Pointer to interface data. + * Returns: 0 on success, -1 on failure + * + * Initializes the driver interface, validates the configuration, + * and sets driver parameters based on the configuration. + * Flushes old stations, sets the channel, encryption, + * beacons, and WDS links based on the configuration. + * + * If interface setup requires more time, e.g., to perform HT co-ex scans, ACS, + * or DFS operations, this function returns 0 before such operations have been + * completed. The pending operations are registered into eloop and will be + * completed from eloop callbacks. Those callbacks end up calling + * hostapd_setup_interface_complete() once setup has been completed. + */ +int hostapd_setup_interface(struct hostapd_iface *iface) +{ + int ret; + + ret = setup_interface(iface); + if (ret) { + wpa_printf(MSG_ERROR, "%s: Unable to setup interface.", + iface->bss[0]->conf->iface); + return -1; + } + + return 0; +} + + +/** + * hostapd_alloc_bss_data - Allocate and initialize per-BSS data + * @hapd_iface: Pointer to interface data + * @conf: Pointer to per-interface configuration + * @bss: Pointer to per-BSS configuration for this BSS + * Returns: Pointer to allocated BSS data + * + * This function is used to allocate per-BSS data structure. This data will be + * freed after hostapd_cleanup() is called for it during interface + * deinitialization. + */ +struct hostapd_data * +hostapd_alloc_bss_data(struct hostapd_iface *hapd_iface, + struct hostapd_config *conf, + struct hostapd_bss_config *bss) +{ + struct hostapd_data *hapd; + + hapd = os_zalloc(sizeof(*hapd)); + if (hapd == NULL) + return NULL; + + hapd->new_assoc_sta_cb = hostapd_new_assoc_sta; + hapd->iconf = conf; + hapd->conf = bss; + hapd->iface = hapd_iface; + if (conf) + hapd->driver = conf->driver; +#ifdef CONFIG_SAE_AP + dl_list_init(&hapd->sae_commit_queue); +#endif /* CONFIG_SAE_AP */ + + return hapd; +} + + +static void hostapd_bss_deinit(struct hostapd_data *hapd) +{ + if (!hapd) + return; + wpa_printf(MSG_DEBUG, "%s: deinit bss %s", __func__, + hapd->conf->iface); + hostapd_bss_deinit_no_free(hapd); + wpa_msg(hapd->msg_ctx, MSG_INFO, AP_EVENT_DISABLED); + hostapd_cleanup(hapd); +} + + +void hostapd_interface_deinit(struct hostapd_iface *iface) +{ + int j; + + wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface); + if (iface == NULL) + return; + + hostapd_set_state(iface, HAPD_IFACE_DISABLED); + + eloop_cancel_timeout(channel_list_update_timeout, iface, NULL); + iface->wait_channel_update = 0; + +#ifdef CONFIG_FST + if (iface->fst) { + fst_detach(iface->fst); + iface->fst = NULL; + } +#endif /* CONFIG_FST */ + + for (j = (int) iface->num_bss - 1; j >= 0; j--) { + if (!iface->bss) + break; + hostapd_bss_deinit(iface->bss[j]); + } + +#ifdef CONFIG_IEEE80211N +#ifdef NEED_AP_MLME + hostapd_stop_setup_timers(iface); + eloop_cancel_timeout(ap_ht2040_timeout, iface, NULL); +#endif /* NEED_AP_MLME */ +#endif /* CONFIG_IEEE80211N */ +} + + +void hostapd_interface_free(struct hostapd_iface *iface) +{ + size_t j; + wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface); + for (j = 0; j < iface->num_bss; j++) { + if (!iface->bss) + break; + wpa_printf(MSG_DEBUG, "%s: free hapd %p", + __func__, iface->bss[j]); + os_free(iface->bss[j]); + } + hostapd_cleanup_iface(iface); +} + + +struct hostapd_iface * hostapd_alloc_iface(void) +{ + struct hostapd_iface *hapd_iface; + + hapd_iface = os_zalloc(sizeof(*hapd_iface)); + if (!hapd_iface) + return NULL; + + dl_list_init(&hapd_iface->sta_seen); + + return hapd_iface; +} + + +/** + * hostapd_init - Allocate and initialize per-interface data + * @config_file: Path to the configuration file + * Returns: Pointer to the allocated interface data or %NULL on failure + * + * This function is used to allocate main data structures for per-interface + * data. The allocated data buffer will be freed by calling + * hostapd_cleanup_iface(). + */ +struct hostapd_iface * hostapd_init(struct hapd_interfaces *interfaces, + const char *config_file) +{ + struct hostapd_iface *hapd_iface = NULL; + struct hostapd_config *conf = NULL; + struct hostapd_data *hapd; + size_t i; + + hapd_iface = hostapd_alloc_iface(); + if (hapd_iface == NULL) + goto fail; + + hapd_iface->config_fname = os_strdup(config_file); + if (hapd_iface->config_fname == NULL) + goto fail; + + conf = interfaces->config_read_cb(hapd_iface->config_fname); //hostapd_config_read + if (conf == NULL) + goto fail; + hapd_iface->conf = conf; + + hapd_iface->num_bss = conf->num_bss; + hapd_iface->bss = os_calloc(conf->num_bss, + sizeof(struct hostapd_data *)); + if (hapd_iface->bss == NULL) + goto fail; + + for (i = 0; i < conf->num_bss; i++) { + hapd = hapd_iface->bss[i] = + hostapd_alloc_bss_data(hapd_iface, conf, + conf->bss[i]); + if (hapd == NULL) + goto fail; + hapd->msg_ctx = hapd; + } + + return hapd_iface; + +fail: + wpa_printf(MSG_ERROR, "Failed to set up interface with %s", + config_file); + if (conf) + hostapd_config_free(conf); + if (hapd_iface) { + os_free(hapd_iface->config_fname); + os_free(hapd_iface->bss); + wpa_printf(MSG_DEBUG, "%s: free iface %p", + __func__, hapd_iface); + os_free(hapd_iface); + } + return NULL; +} + + +static int ifname_in_use(struct hapd_interfaces *interfaces, const char *ifname) +{ + size_t i, j; + + for (i = 0; i < interfaces->count; i++) { + struct hostapd_iface *iface = interfaces->iface[i]; + for (j = 0; j < iface->num_bss; j++) { + struct hostapd_data *hapd = iface->bss[j]; + if (os_strcmp(ifname, hapd->conf->iface) == 0) + return 1; + } + } + + return 0; +} + + +/** + * hostapd_interface_init_bss - Read configuration file and init BSS data + * + * This function is used to parse configuration file for a BSS. This BSS is + * added to an existing interface sharing the same radio (if any) or a new + * interface is created if this is the first interface on a radio. This + * allocate memory for the BSS. No actual driver operations are started. + * + * This is similar to hostapd_interface_init(), but for a case where the + * configuration is used to add a single BSS instead of all BSSes for a radio. + */ +struct hostapd_iface * +hostapd_interface_init_bss(struct hapd_interfaces *interfaces, const char *phy, + const char *config_fname, int debug) +{ + struct hostapd_iface *new_iface = NULL, *iface = NULL; + struct hostapd_data *hapd; + int k; + size_t i, bss_idx; + + if (!phy || !*phy) + return NULL; + + for (i = 0; i < interfaces->count; i++) { + if (os_strcmp(interfaces->iface[i]->phy, phy) == 0) { + iface = interfaces->iface[i]; + break; + } + } + + wpa_printf(MSG_INFO, "Configuration file: %s (phy %s)%s", + config_fname, phy, iface ? "" : " --> new PHY"); + if (iface) { + struct hostapd_config *conf; + struct hostapd_bss_config **tmp_conf; + struct hostapd_data **tmp_bss; + struct hostapd_bss_config *bss; + const char *ifname; + + /* Add new BSS to existing iface */ + conf = interfaces->config_read_cb(config_fname); + if (conf == NULL) + return NULL; + if (conf->num_bss > 1) { + wpa_printf(MSG_ERROR, "Multiple BSSes specified in BSS-config"); + hostapd_config_free(conf); + return NULL; + } + + ifname = conf->bss[0]->iface; + if (ifname[0] != '\0' && ifname_in_use(interfaces, ifname)) { + wpa_printf(MSG_ERROR, + "Interface name %s already in use", ifname); + hostapd_config_free(conf); + return NULL; + } + + tmp_conf = os_realloc_array( + iface->conf->bss, iface->conf->num_bss + 1, + sizeof(struct hostapd_bss_config *)); + tmp_bss = os_realloc_array(iface->bss, iface->num_bss + 1, + sizeof(struct hostapd_data *)); + if (tmp_bss) + iface->bss = tmp_bss; + if (tmp_conf) { + iface->conf->bss = tmp_conf; + iface->conf->last_bss = tmp_conf[0]; + } + if (tmp_bss == NULL || tmp_conf == NULL) { + hostapd_config_free(conf); + return NULL; + } + bss = iface->conf->bss[iface->conf->num_bss] = conf->bss[0]; + iface->conf->num_bss++; + + hapd = hostapd_alloc_bss_data(iface, iface->conf, bss); + if (hapd == NULL) { + iface->conf->num_bss--; + hostapd_config_free(conf); + return NULL; + } + iface->conf->last_bss = bss; + iface->bss[iface->num_bss] = hapd; + hapd->msg_ctx = hapd; + + bss_idx = iface->num_bss++; + conf->num_bss--; + conf->bss[0] = NULL; + hostapd_config_free(conf); + } else { + /* Add a new iface with the first BSS */ + new_iface = iface = hostapd_init(interfaces, config_fname); + if (!iface) + return NULL; + os_strlcpy(iface->phy, phy, sizeof(iface->phy)); + iface->interfaces = interfaces; + bss_idx = 0; + } + + for (k = 0; k < debug; k++) { + if (iface->bss[bss_idx]->conf->logger_stdout_level > 0) + iface->bss[bss_idx]->conf->logger_stdout_level--; + } + + if (iface->conf->bss[bss_idx]->iface[0] == '\0' && + !hostapd_drv_none(iface->bss[bss_idx])) { + wpa_printf(MSG_ERROR, "Interface name not specified in %s", + config_fname); + if (new_iface) + hostapd_interface_deinit_free(new_iface); + return NULL; + } + + return iface; +} + + +void hostapd_interface_deinit_free(struct hostapd_iface *iface) +{ + const struct wpa_driver_ops *driver; + void *drv_priv; + + wpa_printf(MSG_DEBUG, "%s(%p)", __func__, iface); + if (iface == NULL) + return; + wpa_printf(MSG_DEBUG, "%s: num_bss=%u conf->num_bss=%u", + __func__, (unsigned int) iface->num_bss, + (unsigned int) iface->conf->num_bss); + driver = iface->bss[0]->driver; + drv_priv = iface->bss[0]->drv_priv; + hostapd_interface_deinit(iface); + wpa_printf(MSG_DEBUG, "%s: driver=%p drv_priv=%p -> hapd_deinit", + __func__, driver, drv_priv); + if (driver && driver->hapd_deinit && drv_priv) { + driver->hapd_deinit(drv_priv); + iface->bss[0]->drv_priv = NULL; + } + hostapd_interface_free(iface); +} + + +static void hostapd_deinit_driver(const struct wpa_driver_ops *driver, + void *drv_priv, + struct hostapd_iface *hapd_iface) +{ + size_t j; + + wpa_printf(MSG_DEBUG, "%s: driver=%p drv_priv=%p -> hapd_deinit", + __func__, driver, drv_priv); + if (driver && driver->hapd_deinit && drv_priv) { + driver->hapd_deinit(drv_priv); + for (j = 0; j < hapd_iface->num_bss; j++) { + wpa_printf(MSG_DEBUG, "%s:bss[%d]->drv_priv=%p", + __func__, (int) j, + hapd_iface->bss[j]->drv_priv); + if (hapd_iface->bss[j]->drv_priv == drv_priv) { + hapd_iface->bss[j]->drv_priv = NULL; + hapd_iface->extended_capa = NULL; + hapd_iface->extended_capa_mask = NULL; + hapd_iface->extended_capa_len = 0; + } + } + } +} + + +int hostapd_enable_iface(struct hostapd_iface *hapd_iface) +{ + size_t j; + + if (hapd_iface->bss[0]->drv_priv != NULL) { + wpa_printf(MSG_ERROR, "Interface %s already enabled", + hapd_iface->conf->bss[0]->iface); + return -1; + } + + wpa_printf(MSG_DEBUG, "Enable interface %s", + hapd_iface->conf->bss[0]->iface); + + for (j = 0; j < hapd_iface->num_bss; j++) + hostapd_set_security_params(hapd_iface->conf->bss[j], 1); + if (hostapd_config_check(hapd_iface->conf, 1) < 0) { + wpa_printf(MSG_INFO, "Invalid configuration - cannot enable"); + return -1; + } + + if (hapd_iface->interfaces == NULL || + hapd_iface->interfaces->driver_init == NULL || + hapd_iface->interfaces->driver_init(hapd_iface)) + return -1; + + if (hostapd_setup_interface(hapd_iface)) { + hostapd_deinit_driver(hapd_iface->bss[0]->driver, + hapd_iface->bss[0]->drv_priv, + hapd_iface); + return -1; + } + + return 0; +} + + +int hostapd_reload_iface(struct hostapd_iface *hapd_iface) +{ + size_t j; + + wpa_printf(MSG_DEBUG, "Reload interface %s", + hapd_iface->conf->bss[0]->iface); + for (j = 0; j < hapd_iface->num_bss; j++) + hostapd_set_security_params(hapd_iface->conf->bss[j], 1); + if (hostapd_config_check(hapd_iface->conf, 1) < 0) { + wpa_printf(MSG_ERROR, "Updated configuration is invalid"); + return -1; + } + hostapd_clear_old(hapd_iface); + for (j = 0; j < hapd_iface->num_bss; j++) + hostapd_reload_bss(hapd_iface->bss[j]); + + return 0; +} + + +int hostapd_disable_iface(struct hostapd_iface *hapd_iface) +{ + size_t j; + const struct wpa_driver_ops *driver; + void *drv_priv; + + if (hapd_iface == NULL) + return -1; + + if (hapd_iface->bss[0]->drv_priv == NULL) { + wpa_printf(MSG_INFO, "Interface %s already disabled", + hapd_iface->conf->bss[0]->iface); + return -1; + } + + wpa_msg(hapd_iface->bss[0]->msg_ctx, MSG_INFO, AP_EVENT_DISABLED); + driver = hapd_iface->bss[0]->driver; + drv_priv = hapd_iface->bss[0]->drv_priv; + + hapd_iface->driver_ap_teardown = + !!(hapd_iface->drv_flags & + WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT); + +#ifdef NEED_AP_MLME + for (j = 0; j < hapd_iface->num_bss; j++) + hostapd_cleanup_cs_params(hapd_iface->bss[j]); +#endif /* NEED_AP_MLME */ + + /* same as hostapd_interface_deinit without deinitializing ctrl-iface */ + for (j = 0; j < hapd_iface->num_bss; j++) { + struct hostapd_data *hapd = hapd_iface->bss[j]; + hostapd_bss_deinit_no_free(hapd); + hostapd_free_hapd_data(hapd); + } + + hostapd_deinit_driver(driver, drv_priv, hapd_iface); + + /* From hostapd_cleanup_iface: These were initialized in + * hostapd_setup_interface and hostapd_setup_interface_complete + */ + hostapd_cleanup_iface_partial(hapd_iface); + + wpa_printf(MSG_DEBUG, "Interface %s disabled", + hapd_iface->bss[0]->conf->iface); + hostapd_set_state(hapd_iface, HAPD_IFACE_DISABLED); + return 0; +} + + +static struct hostapd_iface * +hostapd_iface_alloc(struct hapd_interfaces *interfaces) +{ + struct hostapd_iface **iface, *hapd_iface; + + iface = os_realloc_array(interfaces->iface, interfaces->count + 1, + sizeof(struct hostapd_iface *)); + if (iface == NULL) + return NULL; + interfaces->iface = iface; + hapd_iface = interfaces->iface[interfaces->count] = + hostapd_alloc_iface(); + if (hapd_iface == NULL) { + wpa_printf(MSG_ERROR, "%s: Failed to allocate memory for " + "the interface", __func__); + return NULL; + } + interfaces->count++; + hapd_iface->interfaces = interfaces; + + return hapd_iface; +} + + +static struct hostapd_config * +hostapd_config_alloc(struct hapd_interfaces *interfaces, const char *ifname, + const char *ctrl_iface, const char *driver) +{ + struct hostapd_bss_config *bss; + struct hostapd_config *conf; + + /* Allocates memory for bss and conf */ + conf = hostapd_config_defaults(); + if (conf == NULL) { + wpa_printf(MSG_ERROR, "%s: Failed to allocate memory for " + "configuration", __func__); + return NULL; + } + +#if 0 + if (driver) { + int j; + + for (j = 0; wpa_drivers[j]; j++) { + if (os_strcmp(driver, wpa_drivers[j]->name) == 0) { + conf->driver = wpa_drivers[j]; + goto skip; + } + } + + wpa_printf(MSG_ERROR, + "Invalid/unknown driver '%s' - registering the default driver", + driver); + } +#endif + + conf->driver = wpa_drivers[0]; + if (conf->driver == NULL) { + wpa_printf(MSG_ERROR, "No driver wrappers registered!"); + hostapd_config_free(conf); + return NULL; + } + +//skip: + bss = conf->last_bss = conf->bss[0]; + + os_strlcpy(bss->iface, ifname, sizeof(bss->iface)); +#ifdef CONFIG_FULL_HOSTAPD + bss->ctrl_interface = os_strdup(ctrl_iface); + if (bss->ctrl_interface == NULL) { + hostapd_config_free(conf); + return NULL; + } +#endif + + /* Reading configuration file skipped, will be done in SET! + * From reading the configuration till the end has to be done in + * SET + */ + return conf; +} + + +static int hostapd_data_alloc(struct hostapd_iface *hapd_iface, + struct hostapd_config *conf) +{ + size_t i; + struct hostapd_data *hapd; + + hapd_iface->bss = os_calloc(conf->num_bss, + sizeof(struct hostapd_data *)); + if (hapd_iface->bss == NULL) + return -1; + + for (i = 0; i < conf->num_bss; i++) { + hapd = hapd_iface->bss[i] = + hostapd_alloc_bss_data(hapd_iface, conf, conf->bss[i]); + if (hapd == NULL) { + while (i > 0) { + i--; + os_free(hapd_iface->bss[i]); + hapd_iface->bss[i] = NULL; + } + os_free(hapd_iface->bss); + hapd_iface->bss = NULL; + return -1; + } + hapd->msg_ctx = hapd; + } + + hapd_iface->conf = conf; + hapd_iface->num_bss = conf->num_bss; + + return 0; +} + + +int hostapd_add_iface(struct hapd_interfaces *interfaces, char *buf) +{ + struct hostapd_config *conf = NULL; + struct hostapd_iface *hapd_iface = NULL, *new_iface = NULL; + struct hostapd_data *hapd; + char *ptr; + size_t i, j; + const char *conf_file = NULL, *phy_name = NULL; + + if (os_strncmp(buf, "bss_config=", 11) == 0) { + char *pos; + phy_name = buf + 11; + pos = os_strchr(phy_name, ':'); + if (!pos) + return -1; + *pos++ = '\0'; + conf_file = pos; + if (!os_strlen(conf_file)) + return -1; + + hapd_iface = hostapd_interface_init_bss(interfaces, phy_name, + conf_file, 0); + if (!hapd_iface) + return -1; + + for (j = 0; j < interfaces->count; j++) { + if (interfaces->iface[j] == hapd_iface) + break; + } + + if (j == interfaces->count) { + struct hostapd_iface **tmp; + tmp = os_realloc_array(interfaces->iface, + interfaces->count + 1, + sizeof(struct hostapd_iface *)); + if (!tmp) { + hostapd_interface_deinit_free(hapd_iface); + return -1; + } + interfaces->iface = tmp; + interfaces->iface[interfaces->count++] = hapd_iface; + new_iface = hapd_iface; + } + + if (new_iface) { + if (interfaces->driver_init(hapd_iface)) //hostapd_driver_init + goto fail; + + if (hostapd_setup_interface(hapd_iface)) { + hostapd_deinit_driver( + hapd_iface->bss[0]->driver, + hapd_iface->bss[0]->drv_priv, + hapd_iface); + goto fail; + } + } else { + /* Assign new BSS with bss[0]'s driver info */ + hapd = hapd_iface->bss[hapd_iface->num_bss - 1]; + hapd->driver = hapd_iface->bss[0]->driver; + hapd->drv_priv = hapd_iface->bss[0]->drv_priv; + os_memcpy(hapd->own_addr, hapd_iface->bss[0]->own_addr, + ETH_ALEN); + + if (start_ctrl_iface_bss(hapd) < 0 || + (hapd_iface->state == HAPD_IFACE_ENABLED && + hostapd_setup_bss(hapd, -1))) { + hostapd_cleanup(hapd); + hapd_iface->bss[hapd_iface->num_bss - 1] = NULL; + hapd_iface->conf->num_bss--; + hapd_iface->num_bss--; + wpa_printf(MSG_DEBUG, "%s: free hapd %p %s", + __func__, hapd, hapd->conf->iface); + hostapd_config_free_bss(hapd->conf); + hapd->conf = NULL; + os_free(hapd); + return -1; + } + } +#ifdef CONFIG_OWE + hostapd_owe_update_trans(hapd_iface); +#endif + return 0; + } + + ptr = os_strchr(buf, ' '); + if (ptr == NULL) + return -1; + *ptr++ = '\0'; + + if (os_strncmp(ptr, "config=", 7) == 0) + conf_file = ptr + 7; + + for (i = 0; i < interfaces->count; i++) { + if (!os_strcmp(interfaces->iface[i]->conf->bss[0]->iface, + buf)) { + wpa_printf(MSG_INFO, "Cannot add interface - it " + "already exists"); + return -1; + } + } + + hapd_iface = hostapd_iface_alloc(interfaces); + if (hapd_iface == NULL) { + wpa_printf(MSG_ERROR, "%s: Failed to allocate memory " + "for interface", __func__); + goto fail; + } + new_iface = hapd_iface; + + if (conf_file && interfaces->config_read_cb) { + conf = interfaces->config_read_cb(conf_file); + if (conf && conf->bss) + os_strlcpy(conf->bss[0]->iface, buf, + sizeof(conf->bss[0]->iface)); + } else { + char *driver = os_strchr(ptr, ' '); + + if (driver) + *driver++ = '\0'; + conf = hostapd_config_alloc(interfaces, buf, ptr, driver); + } + + if (conf == NULL || conf->bss == NULL) { + wpa_printf(MSG_ERROR, "%s: Failed to allocate memory " + "for configuration", __func__); + goto fail; + } + + if (hostapd_data_alloc(hapd_iface, conf) < 0) { + wpa_printf(MSG_ERROR, "%s: Failed to allocate memory " + "for hostapd", __func__); + goto fail; + } + conf = NULL; + + if (start_ctrl_iface(hapd_iface) < 0) + goto fail; + + wpa_printf(MSG_INFO, "Add interface '%s'", + hapd_iface->conf->bss[0]->iface); + + return 0; + +fail: + if (conf) + hostapd_config_free(conf); + if (hapd_iface) { + if (hapd_iface->bss) { + for (i = 0; i < hapd_iface->num_bss; i++) { + hapd = hapd_iface->bss[i]; + if (!hapd) + continue; + if (hapd_iface->interfaces && + hapd_iface->interfaces->ctrl_iface_deinit) + hapd_iface->interfaces-> + ctrl_iface_deinit(hapd); + wpa_printf(MSG_DEBUG, "%s: free hapd %p (%s)", + __func__, hapd_iface->bss[i], + hapd->conf->iface); + hostapd_cleanup(hapd); + os_free(hapd); + hapd_iface->bss[i] = NULL; + } + os_free(hapd_iface->bss); + hapd_iface->bss = NULL; + } + if (new_iface) { + interfaces->count--; + interfaces->iface[interfaces->count] = NULL; + } + hostapd_cleanup_iface(hapd_iface); + } + return -1; +} + + +static int hostapd_remove_bss(struct hostapd_iface *iface, unsigned int idx) +{ + size_t i; + + wpa_printf(MSG_INFO, "Remove BSS '%s'", iface->conf->bss[idx]->iface); + + /* Remove hostapd_data only if it has already been initialized */ + if (idx < iface->num_bss) { + struct hostapd_data *hapd = iface->bss[idx]; + + hostapd_bss_deinit(hapd); + wpa_printf(MSG_DEBUG, "%s: free hapd %p (%s)", + __func__, hapd, hapd->conf->iface); + hostapd_config_free_bss(hapd->conf); + hapd->conf = NULL; + os_free(hapd); + + iface->num_bss--; + + for (i = idx; i < iface->num_bss; i++) + iface->bss[i] = iface->bss[i + 1]; + } else { + hostapd_config_free_bss(iface->conf->bss[idx]); + iface->conf->bss[idx] = NULL; + } + + iface->conf->num_bss--; + for (i = idx; i < iface->conf->num_bss; i++) + iface->conf->bss[i] = iface->conf->bss[i + 1]; + + return 0; +} + + +int hostapd_remove_iface(struct hapd_interfaces *interfaces, char *buf) +{ + struct hostapd_iface *hapd_iface; + size_t i, j, k = 0; + + for (i = 0; i < interfaces->count; i++) { + hapd_iface = interfaces->iface[i]; + if (hapd_iface == NULL) + return -1; + if (!os_strcmp(hapd_iface->conf->bss[0]->iface, buf)) { + wpa_printf(MSG_INFO, "Remove interface '%s'", buf); + hapd_iface->driver_ap_teardown = + !!(hapd_iface->drv_flags & + WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT); + + hostapd_interface_deinit_free(hapd_iface); + k = i; + while (k < (interfaces->count - 1)) { + interfaces->iface[k] = + interfaces->iface[k + 1]; + k++; + } + interfaces->count--; + return 0; + } + + for (j = 0; j < hapd_iface->conf->num_bss; j++) { + if (!os_strcmp(hapd_iface->conf->bss[j]->iface, buf)) { + hapd_iface->driver_ap_teardown = + !(hapd_iface->drv_flags & + WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT); + return hostapd_remove_bss(hapd_iface, j); + } + } + } + return -1; +} + + +/** + * hostapd_new_assoc_sta - Notify that a new station associated with the AP + * @hapd: Pointer to BSS data + * @sta: Pointer to the associated STA data + * @reassoc: 1 to indicate this was a re-association; 0 = first association + * + * This function will be called whenever a station associates with the AP. It + * can be called from ieee802_11.c for drivers that export MLME to hostapd and + * from drv_callbacks.c based on driver events for drivers that take care of + * management frames (IEEE 802.11 authentication and association) internally. + */ +void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta, + int reassoc) +{ + if (hapd->tkip_countermeasures) { + hostapd_drv_sta_deauth(hapd, sta->addr, + WLAN_REASON_MICHAEL_MIC_FAILURE); + return; + } + + hostapd_prune_associations(hapd, sta->addr); + ap_sta_clear_disconnect_timeouts(hapd, sta); +#ifdef CONFIG_FULL_HOSTAPD + /* IEEE 802.11F (IAPP) */ + if (hapd->conf->ieee802_11f) + iapp_new_station(hapd->iapp, sta); +#endif +#ifdef CONFIG_P2P + if (sta->p2p_ie == NULL && !sta->no_p2p_set) { + sta->no_p2p_set = 1; + hapd->num_sta_no_p2p++; + if (hapd->num_sta_no_p2p == 1) + hostapd_p2p_non_p2p_sta_connected(hapd); + } +#endif /* CONFIG_P2P */ + + /* Start accounting here, if IEEE 802.1X and WPA are not used. + * IEEE 802.1X/WPA code will start accounting after the station has + * been authorized. */ + if (!hapd->conf->ieee802_1x && !hapd->conf->wpa && !hapd->conf->osen) { + ap_sta_set_authorized(hapd, sta, 1); + os_get_reltime(&sta->connected_time); + accounting_sta_start(hapd, sta); + } + +#ifdef IEEE8021X_EAPOL + /* Start IEEE 802.1X authentication process for new stations */ + ieee802_1x_new_station(hapd, sta); +#endif + if (reassoc) { + if (sta->auth_alg != WLAN_AUTH_FT && + sta->auth_alg != WLAN_AUTH_FILS_SK && + sta->auth_alg != WLAN_AUTH_FILS_SK_PFS && + sta->auth_alg != WLAN_AUTH_FILS_PK && + !(sta->flags & (WLAN_STA_WPS | WLAN_STA_MAYBE_WPS))) + wpa_auth_sm_event(sta->wpa_sm, WPA_REAUTH); + } else + wpa_auth_sta_associated(hapd->wpa_auth, sta->wpa_sm); + +#ifdef CONFIG_FULL_HOSTAPD + if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_WIRED) { + if (eloop_cancel_timeout(ap_handle_timer, hapd, sta) > 0) { + wpa_printf(MSG_DEBUG, + "%s: %s: canceled wired ap_handle_timer timeout for " + MACSTR, + hapd->conf->iface, __func__, + MAC2STR(sta->addr)); + } + } else +#endif + if (!(hapd->iface->drv_flags & + WPA_DRIVER_FLAGS_INACTIVITY_TIMER)) { + wpa_printf(MSG_DEBUG, + "%s: %s: reschedule ap_handle_timer timeout for " + MACSTR " (%d seconds - ap_max_inactivity)", + hapd->conf->iface, __func__, MAC2STR(sta->addr), + hapd->conf->ap_max_inactivity); + eloop_cancel_timeout(ap_handle_timer, hapd, sta); + eloop_register_timeout(hapd->conf->ap_max_inactivity, 0, + ap_handle_timer, hapd, sta); + } +} + + +const char * hostapd_state_text(enum hostapd_iface_state s) +{ + switch (s) { + case HAPD_IFACE_UNINITIALIZED: + return "UNINITIALIZED"; + case HAPD_IFACE_DISABLED: + return "DISABLED"; + case HAPD_IFACE_COUNTRY_UPDATE: + return "COUNTRY_UPDATE"; + case HAPD_IFACE_ACS: + return "ACS"; + case HAPD_IFACE_HT_SCAN: + return "HT_SCAN"; + case HAPD_IFACE_DFS: + return "DFS"; + case HAPD_IFACE_ENABLED: + return "ENABLED"; + } + + return "UNKNOWN"; +} + + +void hostapd_set_state(struct hostapd_iface *iface, enum hostapd_iface_state s) +{ + wpa_printf(MSG_INFO, "%s: interface state %s->%s", + iface->conf ? iface->conf->bss[0]->iface : "N/A", + hostapd_state_text(iface->state), hostapd_state_text(s)); + iface->state = s; +} + + +int hostapd_csa_in_progress(struct hostapd_iface *iface) +{ + unsigned int i; + + for (i = 0; i < iface->num_bss; i++) + if (iface->bss[i]->csa_in_progress) + return 1; + return 0; +} + + +#ifdef NEED_AP_MLME +static void free_beacon_data(struct beacon_data *beacon) +{ + os_free(beacon->head); + beacon->head = NULL; + os_free(beacon->tail); + beacon->tail = NULL; + os_free(beacon->probe_resp); + beacon->probe_resp = NULL; + os_free(beacon->beacon_ies); + beacon->beacon_ies = NULL; + os_free(beacon->proberesp_ies); + beacon->proberesp_ies = NULL; + os_free(beacon->assocresp_ies); + beacon->assocresp_ies = NULL; +} + + +static int hostapd_build_beacon_data(struct hostapd_data *hapd, + struct beacon_data *beacon) +{ + struct wpabuf *beacon_extra, *proberesp_extra, *assocresp_extra; + struct wpa_driver_ap_params params; + int ret; + + os_memset(beacon, 0, sizeof(*beacon)); + ret = ieee802_11_build_ap_params(hapd, ¶ms); + if (ret < 0) + return ret; + + ret = hostapd_build_ap_extra_ies(hapd, &beacon_extra, + &proberesp_extra, + &assocresp_extra); + if (ret) + goto free_ap_params; + + ret = -1; + beacon->head = os_memdup(params.head, params.head_len); + if (!beacon->head) + goto free_ap_extra_ies; + + beacon->head_len = params.head_len; + + beacon->tail = os_memdup(params.tail, params.tail_len); + if (!beacon->tail) + goto free_beacon; + + beacon->tail_len = params.tail_len; + + if (params.proberesp != NULL) { + beacon->probe_resp = os_memdup(params.proberesp, + params.proberesp_len); + if (!beacon->probe_resp) + goto free_beacon; + + beacon->probe_resp_len = params.proberesp_len; + } + + /* copy the extra ies */ + if (beacon_extra) { + beacon->beacon_ies = os_memdup(beacon_extra->buf, + wpabuf_len(beacon_extra)); + if (!beacon->beacon_ies) + goto free_beacon; + + beacon->beacon_ies_len = wpabuf_len(beacon_extra); + } + + if (proberesp_extra) { + beacon->proberesp_ies = os_memdup(proberesp_extra->buf, + wpabuf_len(proberesp_extra)); + if (!beacon->proberesp_ies) + goto free_beacon; + + beacon->proberesp_ies_len = wpabuf_len(proberesp_extra); + } + + if (assocresp_extra) { + beacon->assocresp_ies = os_memdup(assocresp_extra->buf, + wpabuf_len(assocresp_extra)); + if (!beacon->assocresp_ies) + goto free_beacon; + + beacon->assocresp_ies_len = wpabuf_len(assocresp_extra); + } + + ret = 0; +free_beacon: + /* if the function fails, the caller should not free beacon data */ + if (ret) + free_beacon_data(beacon); + +free_ap_extra_ies: + hostapd_free_ap_extra_ies(hapd, beacon_extra, proberesp_extra, + assocresp_extra); +free_ap_params: + ieee802_11_free_ap_params(¶ms); + return ret; +} + + +/* + * TODO: This flow currently supports only changing channel and width within + * the same hw_mode. Any other changes to MAC parameters or provided settings + * are not supported. + */ +static int hostapd_change_config_freq(struct hostapd_data *hapd, + struct hostapd_config *conf, + struct hostapd_freq_params *params, + struct hostapd_freq_params *old_params) +{ + int channel; +#ifdef CONFIG_FULL_HOSTAPD + u8 seg0, seg1; +#endif +#ifdef CONFIG_IEEE80211AX + struct hostapd_hw_modes *mode; +#endif + + if (!params->channel) { + /* check if the new channel is supported by hw */ + params->channel = hostapd_hw_get_channel(hapd, params->freq); + } + + channel = params->channel; + if (!channel) + return -1; + +#ifdef CONFIG_IEEE80211AX + mode = hapd->iface->current_mode; +#endif + + /* if a pointer to old_params is provided we save previous state */ + if (old_params && + hostapd_set_freq_params(old_params, conf->hw_mode, + hostapd_hw_get_freq(hapd, conf->channel), + conf->channel, conf->ieee80211n, + conf->ieee80211ac, conf->ieee80211ax, + conf->secondary_channel, + hostapd_get_oper_chwidth(conf), + hostapd_get_oper_centr_freq_seg0_idx(conf), + hostapd_get_oper_centr_freq_seg1_idx(conf), + conf->vht_capab, +#ifdef CONFIG_IEEE80211AX + mode ? &mode->he_capab[IEEE80211_MODE_AP] : +#endif + NULL)) + return -1; + + switch (params->bandwidth) { + case 0: + case 20: + case 40: + hostapd_set_oper_chwidth(conf, CHANWIDTH_USE_HT); + break; +#ifdef CONFIG_FULL_HOSTAPD + case 80: + if (params->center_freq2) + hostapd_set_oper_chwidth(conf, CHANWIDTH_80P80MHZ); + else + hostapd_set_oper_chwidth(conf, CHANWIDTH_80MHZ); + break; + case 160: + hostapd_set_oper_chwidth(conf, CHANWIDTH_160MHZ); + break; +#endif + default: + return -1; + } + + conf->channel = channel; + conf->ieee80211n = params->ht_enabled; + conf->secondary_channel = params->sec_channel_offset; +#ifdef CONFIG_FULL_HOSTAPD + ieee80211_freq_to_chan(params->center_freq1, + &seg0); + ieee80211_freq_to_chan(params->center_freq2, + &seg1); + hostapd_set_oper_centr_freq_seg0_idx(conf, seg0); + hostapd_set_oper_centr_freq_seg1_idx(conf, seg1); +#endif + /* TODO: maybe call here hostapd_config_check here? */ + + return 0; +} + + +static int hostapd_fill_csa_settings(struct hostapd_data *hapd, + struct csa_settings *settings) +{ + struct hostapd_iface *iface = hapd->iface; + struct hostapd_freq_params old_freq; + int ret; + u8 chan, bandwidth; + + os_memset(&old_freq, 0, sizeof(old_freq)); + if (!iface || !iface->freq || hapd->csa_in_progress) + return -1; + + switch (settings->freq_params.bandwidth) { +#ifdef CONFIG_FULL_HOSTAPD + case 80: + if (settings->freq_params.center_freq2) + bandwidth = CHANWIDTH_80P80MHZ; + else + bandwidth = CHANWIDTH_80MHZ; + break; + case 160: + bandwidth = CHANWIDTH_160MHZ; + break; +#endif + default: + bandwidth = CHANWIDTH_USE_HT; + break; + } + + if (ieee80211_freq_to_channel_ext( + settings->freq_params.freq, + settings->freq_params.sec_channel_offset, + bandwidth, + &hapd->iface->cs_oper_class, + &chan) == NUM_HOSTAPD_MODES) { + wpa_printf(MSG_DEBUG, + "invalid frequency for channel switch (freq=%d, sec_channel_offset=%d, vht_enabled=%d, he_enabled=%d)", + settings->freq_params.freq, + settings->freq_params.sec_channel_offset, + settings->freq_params.vht_enabled, + settings->freq_params.he_enabled); + return -1; + } + + settings->freq_params.channel = chan; + + ret = hostapd_change_config_freq(iface->bss[0], iface->conf, + &settings->freq_params, + &old_freq); + if (ret) + return ret; + + ret = hostapd_build_beacon_data(hapd, &settings->beacon_after); + + /* change back the configuration */ + hostapd_change_config_freq(iface->bss[0], iface->conf, + &old_freq, NULL); + + if (ret) + return ret; + + /* set channel switch parameters for csa ie */ + hapd->cs_freq_params = settings->freq_params; + hapd->cs_count = settings->cs_count; + hapd->cs_block_tx = settings->block_tx; + + ret = hostapd_build_beacon_data(hapd, &settings->beacon_csa); + if (ret) { + free_beacon_data(&settings->beacon_after); + return ret; + } + + settings->counter_offset_beacon[0] = hapd->cs_c_off_beacon; + settings->counter_offset_presp[0] = hapd->cs_c_off_proberesp; + settings->counter_offset_beacon[1] = hapd->cs_c_off_ecsa_beacon; + settings->counter_offset_presp[1] = hapd->cs_c_off_ecsa_proberesp; + + return 0; +} + + +void hostapd_cleanup_cs_params(struct hostapd_data *hapd) +{ + os_memset(&hapd->cs_freq_params, 0, sizeof(hapd->cs_freq_params)); + hapd->cs_count = 0; + hapd->cs_block_tx = 0; + hapd->cs_c_off_beacon = 0; + hapd->cs_c_off_proberesp = 0; + hapd->csa_in_progress = 0; + hapd->cs_c_off_ecsa_beacon = 0; + hapd->cs_c_off_ecsa_proberesp = 0; +} + + +void hostapd_chan_switch_vht_config(struct hostapd_data *hapd, int vht_enabled) +{ + if (vht_enabled) + hapd->iconf->ch_switch_vht_config |= CH_SWITCH_VHT_ENABLED; + else + hapd->iconf->ch_switch_vht_config |= CH_SWITCH_VHT_DISABLED; + + hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, "CHAN_SWITCH VHT CONFIG 0x%x", + hapd->iconf->ch_switch_vht_config); +} + + +int hostapd_switch_channel(struct hostapd_data *hapd, + struct csa_settings *settings) +{ + int ret; + + if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_CSA)) { + wpa_printf(MSG_INFO, "CSA is not supported"); + return -1; + } + + os_printf("hostapd_switch_channel\r\n"); + ret = hostapd_fill_csa_settings(hapd, settings); + if (ret) + return ret; + + ret = hostapd_drv_switch_channel(hapd, settings); + + free_beacon_data(&settings->beacon_csa); + free_beacon_data(&settings->beacon_after); + + if (ret) { + /* if we failed, clean cs parameters */ + hostapd_cleanup_cs_params(hapd); + return ret; + } + + hapd->csa_in_progress = 1; + + return 0; +} + + +void +hostapd_switch_channel_fallback(struct hostapd_iface *iface, + const struct hostapd_freq_params *freq_params) +{ + int seg0_idx = 0, seg1_idx = 0, bw = CHANWIDTH_USE_HT; + + wpa_printf(MSG_DEBUG, "Restarting all CSA-related BSSes"); + + if (freq_params->center_freq1) + seg0_idx = 36 + (freq_params->center_freq1 - 5180) / 5; + if (freq_params->center_freq2) + seg1_idx = 36 + (freq_params->center_freq2 - 5180) / 5; + + switch (freq_params->bandwidth) { + case 0: + case 20: + case 40: + bw = CHANWIDTH_USE_HT; + break; +#ifdef CONFIG_FULL_HOSTAPD + case 80: + if (freq_params->center_freq2) + bw = CHANWIDTH_80P80MHZ; + else + bw = CHANWIDTH_80MHZ; + break; + case 160: + bw = CHANWIDTH_160MHZ; + break; +#endif + default: + wpa_printf(MSG_WARNING, "Unknown CSA bandwidth: %d", + freq_params->bandwidth); + break; + } + + iface->freq = freq_params->freq; + iface->conf->channel = freq_params->channel; + iface->conf->secondary_channel = freq_params->sec_channel_offset; + hostapd_set_oper_centr_freq_seg0_idx(iface->conf, seg0_idx); + hostapd_set_oper_centr_freq_seg1_idx(iface->conf, seg1_idx); + hostapd_set_oper_chwidth(iface->conf, bw); + iface->conf->ieee80211n = freq_params->ht_enabled; + iface->conf->ieee80211ac = freq_params->vht_enabled; + iface->conf->ieee80211ax = freq_params->he_enabled; + + /* + * cs_params must not be cleared earlier because the freq_params + * argument may actually point to one of these. + * These params will be cleared during interface disable below. + */ + hostapd_disable_iface(iface); + hostapd_enable_iface(iface); +} + +#endif /* NEED_AP_MLME */ + + +struct hostapd_data * hostapd_get_iface(struct hapd_interfaces *interfaces, + const char *ifname) +{ + size_t i, j; + + for (i = 0; i < interfaces->count; i++) { + struct hostapd_iface *iface = interfaces->iface[i]; + + for (j = 0; j < iface->num_bss; j++) { + struct hostapd_data *hapd = iface->bss[j]; + + if (os_strcmp(ifname, hapd->conf->iface) == 0) + return hapd; + } + } + + return NULL; +} + + +void hostapd_periodic_iface(struct hostapd_iface *iface) +{ + size_t i; + + ap_list_timer(iface); + + for (i = 0; i < iface->num_bss; i++) { + struct hostapd_data *hapd = iface->bss[i]; + + if (!hapd->started) + continue; + +#ifndef CONFIG_NO_RADIUS + hostapd_acl_expire(hapd); +#endif /* CONFIG_NO_RADIUS */ + } +} + +int ap_channel_switch(struct hostapd_iface *ap_iface, int new_freq) +{ + struct csa_settings settings = {6}; + + settings.cs_count = 8; + settings.freq_params.freq = new_freq; + settings.freq_params.ht_enabled = 1; + settings.freq_params.ht_enabled = 0; + + if (!ap_iface || !ap_iface->bss[0]) + return -1; + + return hostapd_switch_channel(ap_iface->bss[0], &settings); +} + diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/hostapd.h b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/hostapd.h new file mode 100755 index 0000000..413e669 --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/hostapd.h @@ -0,0 +1,543 @@ +/* + * hostapd / Initialization and configuration + * Copyright (c) 2002-2014, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef HOSTAPD_H +#define HOSTAPD_H + +#include "common/defs.h" +#include "utils/list.h" +#include "ap_config.h" +#include "drivers/driver.h" + +#define OCE_STA_CFON_ENABLED(hapd) \ + ((hapd->conf->oce & OCE_STA_CFON) && \ + (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_OCE_STA_CFON)) +#define OCE_AP_ENABLED(hapd) \ + ((hapd->conf->oce & OCE_AP) && \ + (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_OCE_AP)) + +struct wpa_ctrl_dst; +struct radius_server_data; +struct upnp_wps_device_sm; +struct hostapd_data; +struct sta_info; +struct ieee80211_ht_capabilities; +struct full_dynamic_vlan; +enum wps_event; +union wps_event_data; +#ifdef CONFIG_MESH +struct mesh_conf; +#endif /* CONFIG_MESH */ + +struct hostapd_iface; + +struct hapd_interfaces { + int (*reload_config)(struct hostapd_iface *iface); + struct hostapd_config * (*config_read_cb)(const char *config_fname); + int (*ctrl_iface_init)(struct hostapd_data *hapd); + void (*ctrl_iface_deinit)(struct hostapd_data *hapd); + int (*for_each_interface)(struct hapd_interfaces *interfaces, + int (*cb)(struct hostapd_iface *iface, + void *ctx), void *ctx); + int (*driver_init)(struct hostapd_iface *iface); + + size_t count; + +#ifdef CONFIG_FULL_HOSTAPD + int global_ctrl_sock; + struct dl_list global_ctrl_dst; + char *global_iface_path; + char *global_iface_name; +#endif + + struct hostapd_iface **iface; + + size_t terminate_on_error; + int eloop_initialized; + +#ifdef CONFIG_DPP + struct dpp_global *dpp; +#endif /* CONFIG_DPP */ +}; + +enum hostapd_chan_status { + HOSTAPD_CHAN_VALID = 0, /* channel is ready */ + HOSTAPD_CHAN_INVALID = 1, /* no usable channel found */ + HOSTAPD_CHAN_ACS = 2, /* ACS work being performed */ +}; + +struct hostapd_probereq_cb { + int (*cb)(void *ctx, const u8 *sa, const u8 *da, const u8 *bssid, + const u8 *ie, size_t ie_len, int ssi_signal); + void *ctx; +}; + +#define HOSTAPD_RATE_BASIC 0x00000001 + +struct hostapd_rate_data { + int rate; /* rate in 100 kbps */ + int flags; /* HOSTAPD_RATE_ flags */ +}; + +struct hostapd_frame_info { + unsigned int freq; + u32 channel; + u32 datarate; + int ssi_signal; /* dBm */ +}; + +enum wps_status { + WPS_STATUS_SUCCESS = 1, + WPS_STATUS_FAILURE +}; + +enum pbc_status { + WPS_PBC_STATUS_DISABLE, + WPS_PBC_STATUS_ACTIVE, + WPS_PBC_STATUS_TIMEOUT, + WPS_PBC_STATUS_OVERLAP +}; + +struct wps_stat { + enum wps_status status; + enum wps_error_indication failure_reason; + enum pbc_status pbc_status; + u8 peer_addr[ETH_ALEN]; +}; + +struct hostapd_neighbor_entry { + struct dl_list list; + u8 bssid[ETH_ALEN]; + struct wpa_ssid_value ssid; + struct wpabuf *nr; + struct wpabuf *lci; + struct wpabuf *civic; + /* LCI update time */ + struct os_time lci_date; + int stationary; +}; + +struct hostapd_sae_commit_queue { + struct dl_list list; + int rssi; + size_t len; + u8 msg[]; +}; + +/** + * struct hostapd_data - hostapd per-BSS data structure + */ +struct hostapd_data { + struct hostapd_iface *iface; + struct hostapd_config *iconf; + struct hostapd_bss_config *conf; + int interface_added; /* virtual interface added for this BSS */ + unsigned int started:1; + unsigned int disabled:1; + unsigned int reenable_beacon:1; + + u8 own_addr[ETH_ALEN]; + + int num_sta; /* number of entries in sta_list */ + struct sta_info *sta_list; /* STA info list head */ +#define STA_HASH_SIZE 8 +#define STA_HASH(sta) (sta[5] & (STA_HASH_SIZE - 1)) + struct sta_info *sta_hash[STA_HASH_SIZE]; + + /* + * Bitfield for indicating which AIDs are allocated. Only AID values + * 1-2007 are used and as such, the bit at index 0 corresponds to AID + * 1. + */ +#define AID_WORDS ((CFG_STA_MAX + 31) / 32) + u32 sta_aid[AID_WORDS]; + + const struct wpa_driver_ops *driver; + void *drv_priv; + + void (*new_assoc_sta_cb)(struct hostapd_data *hapd, + struct sta_info *sta, int reassoc); + + void *msg_ctx; /* ctx for wpa_msg() calls */ + void *msg_ctx_parent; /* parent interface ctx for wpa_msg() calls */ + + struct wpa_authenticator *wpa_auth; + struct eapol_authenticator *eapol_auth; + + struct os_reltime michael_mic_failure; + int michael_mic_failures; + int tkip_countermeasures; + + int parameter_set_count; + +#ifdef CONFIG_FULL_HOSTAPD + /* Time Advertisement */ + u8 time_update_counter; + struct wpabuf *time_adv; +#endif + +#ifdef CONFIG_FULL_DYNAMIC_VLAN + struct full_dynamic_vlan *full_dynamic_vlan; +#endif /* CONFIG_FULL_DYNAMIC_VLAN */ + + struct l2_packet_data *l2; + + int beacon_set_done; + + struct hostapd_probereq_cb *probereq_cb; + size_t num_probereq_cb; + + void (*public_action_cb)(void *ctx, const u8 *buf, size_t len, + int freq); + void *public_action_cb_ctx; + void (*public_action_cb2)(void *ctx, const u8 *buf, size_t len, + int freq); + void *public_action_cb2_ctx; + + int (*vendor_action_cb)(void *ctx, const u8 *buf, size_t len, + int freq); + void *vendor_action_cb_ctx; + + void (*wps_reg_success_cb)(void *ctx, const u8 *mac_addr, + const u8 *uuid_e); + void *wps_reg_success_cb_ctx; + + void (*wps_event_cb)(void *ctx, enum wps_event event, + union wps_event_data *data); + void *wps_event_cb_ctx; + + void (*sta_authorized_cb)(void *ctx, const u8 *mac_addr, + int authorized, const u8 *p2p_dev_addr); + void *sta_authorized_cb_ctx; + + void (*setup_complete_cb)(void *ctx); + void *setup_complete_cb_ctx; + + void (*new_psk_cb)(void *ctx, const u8 *mac_addr, + const u8 *p2p_dev_addr, const u8 *psk, + size_t psk_len); + void *new_psk_cb_ctx; + + /* channel switch parameters */ + struct hostapd_freq_params cs_freq_params; + u8 cs_count; + int cs_block_tx; + unsigned int cs_c_off_beacon; + unsigned int cs_c_off_proberesp; + int csa_in_progress; + unsigned int cs_c_off_ecsa_beacon; + unsigned int cs_c_off_ecsa_proberesp; + +#ifdef CONFIG_P2P + struct p2p_data *p2p; + struct p2p_group *p2p_group; + struct wpabuf *p2p_beacon_ie; + struct wpabuf *p2p_probe_resp_ie; + + /* Number of non-P2P association stations */ + int num_sta_no_p2p; + + /* Periodic NoA (used only when no non-P2P clients in the group) */ + int noa_enabled; + int noa_start; + int noa_duration; +#endif /* CONFIG_P2P */ +#ifdef CONFIG_MESH + int num_plinks; + int max_plinks; + void (*mesh_sta_free_cb)(struct hostapd_data *hapd, + struct sta_info *sta); + struct wpabuf *mesh_pending_auth; + struct os_reltime mesh_pending_auth_time; + u8 mesh_required_peer[ETH_ALEN]; +#endif /* CONFIG_MESH */ + +#ifdef CONFIG_SAE_AP + /** Key used for generating SAE anti-clogging tokens */ + u8 sae_token_key[8]; + struct os_reltime last_sae_token_key_update; + u16 sae_token_idx; + u16 sae_pending_token_idx[256]; + int dot11RSNASAERetransPeriod; /* msec */ + struct dl_list sae_commit_queue; /* struct hostapd_sae_commit_queue */ +#endif /* CONFIG_SAE_AP */ + u8 beacon_req_token; +#ifdef CONFIG_DPP + int dpp_init_done; + struct dpp_authentication *dpp_auth; + u8 dpp_allowed_roles; + int dpp_qr_mutual; + int dpp_auth_ok_on_ack; + int dpp_in_response_listen; + struct gas_query_ap *gas; + struct dpp_pkex *dpp_pkex; + struct dpp_bootstrap_info *dpp_pkex_bi; + char *dpp_pkex_code; + char *dpp_pkex_identifier; + char *dpp_pkex_auth_cmd; + char *dpp_configurator_params; + struct os_reltime dpp_last_init; + struct os_reltime dpp_init_iter_start; + unsigned int dpp_init_max_tries; + unsigned int dpp_init_retry_time; + unsigned int dpp_resp_wait_time; + unsigned int dpp_resp_max_tries; + unsigned int dpp_resp_retry_time; +#endif /* CONFIG_DPP */ +}; + + +struct hostapd_sta_info { + struct dl_list list; + u8 addr[ETH_ALEN]; + struct os_reltime last_seen; + int ssi_signal; +}; + +/** + * struct hostapd_iface - hostapd per-interface data structure + */ +struct hostapd_iface { + struct hapd_interfaces *interfaces; + void *owner; + char *config_fname; + struct hostapd_config *conf; + char phy[16]; /* Name of the PHY (radio) */ + + enum hostapd_iface_state { + HAPD_IFACE_UNINITIALIZED, + HAPD_IFACE_DISABLED, + HAPD_IFACE_COUNTRY_UPDATE, + HAPD_IFACE_ACS, + HAPD_IFACE_HT_SCAN, + HAPD_IFACE_DFS, + HAPD_IFACE_ENABLED + } state; + +#ifdef CONFIG_MESH + struct mesh_conf *mconf; +#endif /* CONFIG_MESH */ + + size_t num_bss; + struct hostapd_data **bss; + + unsigned int wait_channel_update:1; + unsigned int cac_started:1; +#ifdef CONFIG_FST + struct fst_iface *fst; + const struct wpabuf *fst_ies; +#endif /* CONFIG_FST */ + + /* + * When set, indicates that the driver will handle the AP + * teardown: delete global keys, station keys, and stations. + */ + unsigned int driver_ap_teardown:1; + + /* + * When set, indicates that this interface is part of list of + * interfaces that need to be started together (synchronously). + */ + unsigned int need_to_start_in_sync:1; + + /* Ready to start but waiting for other interfaces to become ready. */ + unsigned int ready_to_start_in_sync:1; + + int num_ap; /* number of entries in ap_list */ + struct ap_info *ap_list; /* AP info list head */ + struct ap_info *ap_hash[STA_HASH_SIZE]; + + u64 drv_flags; + + /* SMPS modes supported by the driver (WPA_DRIVER_SMPS_MODE_*) */ + unsigned int smps_modes; + + /* + * A bitmap of supported protocols for probe response offload. See + * struct wpa_driver_capa in driver.h + */ + unsigned int probe_resp_offloads; + + /* extended capabilities supported by the driver */ + const u8 *extended_capa, *extended_capa_mask; + unsigned int extended_capa_len; + + unsigned int drv_max_acl_mac_addrs; + + struct hostapd_hw_modes *hw_features; + int num_hw_features; + struct hostapd_hw_modes *current_mode; + /* Rates that are currently used (i.e., filtered copy of + * current_mode->channels */ + int num_rates; + struct hostapd_rate_data *current_rates; + int *basic_rates; + int freq; + + u16 hw_flags; + + /* Number of associated Non-ERP stations (i.e., stations using 802.11b + * in 802.11g BSS) */ + int num_sta_non_erp; + + /* Number of associated stations that do not support Short Slot Time */ + int num_sta_no_short_slot_time; + + /* Number of associated stations that do not support Short Preamble */ + int num_sta_no_short_preamble; + + int olbc; /* Overlapping Legacy BSS Condition */ + + /* Number of HT associated stations that do not support greenfield */ + int num_sta_ht_no_gf; + + /* Number of associated non-HT stations */ + int num_sta_no_ht; + + /* Number of HT associated stations 20 MHz */ + int num_sta_ht_20mhz; + + /* Number of HT40 intolerant stations */ + int num_sta_ht40_intolerant; + + /* Overlapping BSS information */ + int olbc_ht; + + u16 ht_op_mode; + + /* surveying helpers */ + + /* number of channels surveyed */ + unsigned int chans_surveyed; + + /* lowest observed noise floor in dBm */ + s8 lowest_nf; + + /* channel utilization calculation */ + u64 last_channel_time; + u64 last_channel_time_busy; + u8 channel_utilization; + + unsigned int chan_util_samples_sum; + unsigned int chan_util_num_sample_periods; + unsigned int chan_util_average; + + /* eCSA IE will be added only if operating class is specified */ + u8 cs_oper_class; + + unsigned int dfs_cac_ms; + struct os_reltime dfs_cac_start; + + /* Latched with the actual secondary channel information and will be + * used while juggling between HT20 and HT40 modes. */ + int secondary_ch; + +#ifdef CONFIG_ACS + unsigned int acs_num_completed_scans; +#endif /* CONFIG_ACS */ + + void (*scan_cb)(struct hostapd_iface *iface); + int num_ht40_scan_tries; + + struct dl_list sta_seen; /* struct hostapd_sta_info */ + unsigned int num_sta_seen; + + u8 dfs_domain; + + /* Previous WMM element information */ + struct hostapd_wmm_ac_params prev_wmm[WMM_AC_NUM]; +}; + +/* hostapd.c */ +int hostapd_for_each_interface(struct hapd_interfaces *interfaces, + int (*cb)(struct hostapd_iface *iface, + void *ctx), void *ctx); +int hostapd_reload_config(struct hostapd_iface *iface); +void hostapd_reconfig_encryption(struct hostapd_data *hapd); +struct hostapd_data * +hostapd_alloc_bss_data(struct hostapd_iface *hapd_iface, + struct hostapd_config *conf, + struct hostapd_bss_config *bss); +int hostapd_setup_interface(struct hostapd_iface *iface); +int hostapd_setup_interface_complete(struct hostapd_iface *iface, int err); +void hostapd_interface_deinit(struct hostapd_iface *iface); +void hostapd_interface_free(struct hostapd_iface *iface); +struct hostapd_iface * hostapd_alloc_iface(void); +struct hostapd_iface * hostapd_init(struct hapd_interfaces *interfaces, + const char *config_file); +struct hostapd_iface * +hostapd_interface_init_bss(struct hapd_interfaces *interfaces, const char *phy, + const char *config_fname, int debug); +void hostapd_new_assoc_sta(struct hostapd_data *hapd, struct sta_info *sta, + int reassoc); +void hostapd_interface_deinit_free(struct hostapd_iface *iface); +int hostapd_enable_iface(struct hostapd_iface *hapd_iface); +int hostapd_reload_iface(struct hostapd_iface *hapd_iface); +int hostapd_disable_iface(struct hostapd_iface *hapd_iface); +int hostapd_add_iface(struct hapd_interfaces *ifaces, char *buf); +int hostapd_remove_iface(struct hapd_interfaces *ifaces, char *buf); +void hostapd_channel_list_updated(struct hostapd_iface *iface, int initiator); +void hostapd_set_state(struct hostapd_iface *iface, enum hostapd_iface_state s); +const char * hostapd_state_text(enum hostapd_iface_state s); +int hostapd_csa_in_progress(struct hostapd_iface *iface); +void hostapd_chan_switch_vht_config(struct hostapd_data *hapd, int vht_enabled); +int hostapd_switch_channel(struct hostapd_data *hapd, + struct csa_settings *settings); +void +hostapd_switch_channel_fallback(struct hostapd_iface *iface, + const struct hostapd_freq_params *freq_params); +void hostapd_cleanup_cs_params(struct hostapd_data *hapd); +void hostapd_periodic_iface(struct hostapd_iface *iface); +int hostapd_owe_trans_get_info(struct hostapd_data *hapd); + +/* utils.c */ +int hostapd_register_probereq_cb(struct hostapd_data *hapd, + int (*cb)(void *ctx, const u8 *sa, + const u8 *da, const u8 *bssid, + const u8 *ie, size_t ie_len, + int ssi_signal), + void *ctx); +void hostapd_prune_associations(struct hostapd_data *hapd, const u8 *addr); + +/* drv_callbacks.c (TODO: move to somewhere else?) */ +void hostapd_notify_assoc_fils_finish(struct hostapd_data *hapd, + struct sta_info *sta); +int hostapd_notif_assoc(struct hostapd_data *hapd, const u8 *addr, + const u8 *ie, size_t ielen, int reassoc); +void hostapd_notif_disassoc(struct hostapd_data *hapd, const u8 *addr); +void hostapd_event_sta_low_ack(struct hostapd_data *hapd, const u8 *addr); +void hostapd_event_connect_failed_reason(struct hostapd_data *hapd, + const u8 *addr, int reason_code); +int hostapd_probe_req_rx(struct hostapd_data *hapd, const u8 *sa, const u8 *da, + const u8 *bssid, const u8 *ie, size_t ie_len, + int ssi_signal); +void hostapd_event_ch_switch(struct hostapd_data *hapd, int freq, int ht, + int offset, int width, int cf1, int cf2, + int finished); +struct survey_results; +void hostapd_event_get_survey(struct hostapd_iface *iface, + struct survey_results *survey_results); +void hostapd_acs_channel_selected(struct hostapd_data *hapd, + struct acs_selected_channels *acs_res); + +const struct hostapd_eap_user * +hostapd_get_eap_user(struct hostapd_data *hapd, const u8 *identity, + size_t identity_len, int phase2); + +struct hostapd_data * hostapd_get_iface(struct hapd_interfaces *interfaces, + const char *ifname); +void hostapd_event_sta_opmode_changed(struct hostapd_data *hapd, const u8 *addr, + enum smps_mode smps_mode, + enum chan_width chan_width, u8 rx_nss); + +#ifdef CONFIG_FST +void fst_hostapd_fill_iface_obj(struct hostapd_data *hapd, + struct fst_wpa_obj *iface_obj); +#endif /* CONFIG_FST */ + +#endif /* HOSTAPD_H */ diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/hw_features.c b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/hw_features.c new file mode 100755 index 0000000..db1d969 --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/hw_features.c @@ -0,0 +1,998 @@ +/* + * hostapd / Hardware feature query and different modes + * Copyright 2002-2003, Instant802 Networks, Inc. + * Copyright 2005-2006, Devicescape Software, Inc. + * Copyright (c) 2008-2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "utils/eloop.h" +#include "common/ieee802_11_defs.h" +#include "common/ieee802_11_common.h" +#include "common/wpa_ctrl.h" +#include "common/hw_features_common.h" +#include "ap/hostapd.h" +#include "ap_config.h" +#include "ap_drv_ops.h" +#include "acs.h" +#include "ieee802_11.h" +#include "beacon.h" +#include "hw_features.h" +#include "hostapd_cfg.h" + +#include "include.h" +#include "param_config.h" + +void hostapd_free_hw_features(struct hostapd_hw_modes *hw_features, + size_t num_hw_features) +{ + size_t i; + + if (hw_features == NULL) + return; + + for (i = 0; i < num_hw_features; i++) { + os_free(hw_features[i].channels); + os_free(hw_features[i].rates); + } + + os_free(hw_features); +} + + +#ifndef CONFIG_NO_STDOUT_DEBUG +static char * dfs_info(struct hostapd_channel_data *chan) +{ + static char info[256]; + char *state; + + switch (chan->flag & HOSTAPD_CHAN_DFS_MASK) { + case HOSTAPD_CHAN_DFS_UNKNOWN: + state = "unknown"; + break; + case HOSTAPD_CHAN_DFS_USABLE: + state = "usable"; + break; + case HOSTAPD_CHAN_DFS_UNAVAILABLE: + state = "unavailable"; + break; + case HOSTAPD_CHAN_DFS_AVAILABLE: + state = "available"; + break; + default: + return ""; + } + os_snprintf(info, sizeof(info), " (DFS state = %s)", state); + info[sizeof(info) - 1] = '\0'; + + return info; +} +#endif /* CONFIG_NO_STDOUT_DEBUG */ + + +int hostapd_get_hw_features(struct hostapd_iface *iface) +{ + struct hostapd_data *hapd = iface->bss[0]; + int i, j; + u16 num_modes, flags; + struct hostapd_hw_modes *modes; + u8 dfs_domain; + + if (hostapd_drv_none(hapd)) + return -1; + modes = hostapd_get_hw_feature_data(hapd, &num_modes, &flags, + &dfs_domain); + if (modes == NULL) { + hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "Fetching hardware channel/rate support not " + "supported."); + return -1; + } + + iface->hw_flags = flags; + iface->dfs_domain = dfs_domain; + + /* free previous hw features */ + hostapd_free_hw_features(iface->hw_features, iface->num_hw_features); + iface->hw_features = modes; + iface->num_hw_features = num_modes; + + for (i = 0; i < num_modes; i++) { + struct hostapd_hw_modes *feature = &modes[i]; +#ifndef CONFIG_NO_STDOUT_DEBUG + int dfs_enabled = hapd->iconf->ieee80211h && + (iface->drv_flags & WPA_DRIVER_FLAGS_RADAR); +#endif + + /* set flag for channels we can use in current regulatory + * domain */ + for (j = 0; j < feature->num_channels; j++) { +#ifndef CONFIG_NO_STDOUT_DEBUG + int dfs = 0; +#endif + +#ifdef CONFIG_FULL_HOSTAPD + /* + * Disable all channels that are marked not to allow + * to initiate radiation (a.k.a. passive scan and no + * IBSS). + * Use radar channels only if the driver supports DFS. + */ + if ((feature->channels[j].flag & + HOSTAPD_CHAN_RADAR) && dfs_enabled) { + dfs = 1; + } else if (((feature->channels[j].flag & + HOSTAPD_CHAN_RADAR) && + !(iface->drv_flags & + WPA_DRIVER_FLAGS_DFS_OFFLOAD)) || + (feature->channels[j].flag & + HOSTAPD_CHAN_NO_IR)) { + feature->channels[j].flag |= + HOSTAPD_CHAN_DISABLED; + } + + if (feature->channels[j].flag & HOSTAPD_CHAN_DISABLED) + continue; +#endif + +#ifndef CONFIG_NO_STDOUT_DEBUG + wpa_printf(MSG_MSGDUMP, "Allowed channel: mode=%d " + "chan=%d freq=%d MHz max_tx_power=%d dBm%s", + feature->mode, + feature->channels[j].chan, + feature->channels[j].freq, + feature->channels[j].max_tx_power, + dfs ? dfs_info(&feature->channels[j]) : ""); +#endif /* CONFIG_NO_STDOUT_DEBUG */ + } + } + + return 0; +} + + +int hostapd_prepare_rates(struct hostapd_iface *iface, + struct hostapd_hw_modes *mode) +{ + int i, num_basic_rates = 0; +#ifdef CONFIG_FULL_HOSTAPD + int basic_rates_a[] = { 60, 120, 240, -1 }; +#endif + int basic_rates_b[] = { 10, 20, -1 }; + int basic_rates_g[] = { 10, 20, 55, 110, -1 }; + int *basic_rates; + + if (iface->conf->basic_rates) + basic_rates = iface->conf->basic_rates; + else switch (mode->mode) { +#ifdef CONFIG_FULL_HOSTAPD + case HOSTAPD_MODE_IEEE80211A: + basic_rates = basic_rates_a; + break; +#endif + case HOSTAPD_MODE_IEEE80211B: + basic_rates = basic_rates_b; + break; + case HOSTAPD_MODE_IEEE80211G: + basic_rates = basic_rates_g; + break; +#ifdef CONFIG_FULL_HOSTAPD + case HOSTAPD_MODE_IEEE80211AD: + return 0; /* No basic rates for 11ad */ +#endif + default: + return -1; + } + + i = 0; + while (basic_rates[i] >= 0) + i++; + if (i) + i++; /* -1 termination */ + os_free(iface->basic_rates); + iface->basic_rates = os_malloc(i * sizeof(int)); + if (iface->basic_rates) + os_memcpy(iface->basic_rates, basic_rates, i * sizeof(int)); + + if (iface->current_rates) + os_free(iface->current_rates); + iface->num_rates = 0; + + iface->current_rates = + os_calloc(mode->num_rates, sizeof(struct hostapd_rate_data)); + if (!iface->current_rates) { + wpa_printf(MSG_ERROR, "Failed to allocate memory for rate " + "table."); + return -1; + } + + for (i = 0; i < mode->num_rates; i++) { + struct hostapd_rate_data *rate; + + if (iface->conf->supported_rates && + !hostapd_rate_found(iface->conf->supported_rates, + mode->rates[i])) + continue; + + rate = &iface->current_rates[iface->num_rates]; + rate->rate = mode->rates[i]; + if (hostapd_rate_found(basic_rates, rate->rate)) { + rate->flags |= HOSTAPD_RATE_BASIC; + num_basic_rates++; + } + wpa_printf(MSG_DEBUG, "RATE[%d] rate=%d flags=0x%x", + iface->num_rates, rate->rate, rate->flags); + iface->num_rates++; + } + + if ((iface->num_rates == 0 || num_basic_rates == 0) && + (!iface->conf->ieee80211n || !iface->conf->require_ht)) { + wpa_printf(MSG_ERROR, "No rates remaining in supported/basic " + "rate sets (%d,%d).", + iface->num_rates, num_basic_rates); + return -1; + } + + return 0; +} + + +#ifdef CONFIG_IEEE80211N +static int ieee80211n_allowed_ht40_channel_pair(struct hostapd_iface *iface) +{ + int pri_chan, sec_chan; + + pri_chan = iface->conf->channel; + sec_chan = pri_chan + iface->conf->secondary_channel * 4; + + return allowed_ht40_channel_pair(iface->current_mode, pri_chan, + sec_chan); +} + + +static void ieee80211n_switch_pri_sec(struct hostapd_iface *iface) +{ + if (iface->conf->secondary_channel > 0) { + iface->conf->channel += 4; + iface->conf->secondary_channel = -1; + } else { + iface->conf->channel -= 4; + iface->conf->secondary_channel = 1; + } +} + + +static int ieee80211n_check_40mhz_5g(struct hostapd_iface *iface, + struct wpa_scan_results *scan_res) +{ + int pri_chan, sec_chan; + int res; + + pri_chan = iface->conf->channel; + sec_chan = pri_chan + iface->conf->secondary_channel * 4; + + res = check_40mhz_5g(iface->current_mode, scan_res, pri_chan, sec_chan); + + if (res == 2) { + if (iface->conf->no_pri_sec_switch) { + wpa_printf(MSG_DEBUG, + "Cannot switch PRI/SEC channels due to local constraint"); + } else { + ieee80211n_switch_pri_sec(iface); + } + } + + return !!res; +} + + +static int ieee80211n_check_40mhz_2g4(struct hostapd_iface *iface, + struct wpa_scan_results *scan_res) +{ + int pri_chan, sec_chan; + + pri_chan = iface->conf->channel; + sec_chan = pri_chan + iface->conf->secondary_channel * 4; + + return check_40mhz_2g4(iface->current_mode, scan_res, pri_chan, + sec_chan); +} + + +static void ieee80211n_check_scan(struct hostapd_iface *iface) +{ + struct wpa_scan_results *scan_res; + int oper40; + int res; + + /* Check list of neighboring BSSes (from scan) to see whether 40 MHz is + * allowed per IEEE Std 802.11-2012, 10.15.3.2 */ + + iface->scan_cb = NULL; + + scan_res = hostapd_driver_get_scan_results(iface->bss[0]); + if (scan_res == NULL) { + hostapd_setup_interface_complete(iface, 1); + return; + } + +#ifdef CONFIG_FULL_HOSTAPD + if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A) + oper40 = ieee80211n_check_40mhz_5g(iface, scan_res); + else +#endif + oper40 = ieee80211n_check_40mhz_2g4(iface, scan_res); + wpa_scan_results_free(scan_res); + + iface->secondary_ch = iface->conf->secondary_channel; + if (!oper40) { + wpa_printf(MSG_INFO, "20/40 MHz operation not permitted on " + "channel pri=%d sec=%d based on overlapping BSSes", + iface->conf->channel, + iface->conf->channel + + iface->conf->secondary_channel * 4); + iface->conf->secondary_channel = 0; + if (iface->drv_flags & WPA_DRIVER_FLAGS_HT_2040_COEX) { + /* + * TODO: Could consider scheduling another scan to check + * if channel width can be changed if no coex reports + * are received from associating stations. + */ + } + } + + res = ieee80211n_allowed_ht40_channel_pair(iface); + if (!res) { + iface->conf->secondary_channel = 0; + hostapd_set_oper_centr_freq_seg0_idx(iface->conf, 0); + hostapd_set_oper_centr_freq_seg1_idx(iface->conf, 0); + hostapd_set_oper_chwidth(iface->conf, CHANWIDTH_USE_HT); + res = 1; + wpa_printf(MSG_INFO, "Fallback to 20 MHz"); + } + + hostapd_setup_interface_complete(iface, !res); +} + + +static void ieee80211n_scan_channels_2g4(struct hostapd_iface *iface, + struct wpa_driver_scan_params *params) +{ + /* Scan only the affected frequency range */ + int pri_freq, sec_freq; + int affected_start, affected_end; + int i, pos; + struct hostapd_hw_modes *mode; + + if (iface->current_mode == NULL) + return; + + pri_freq = hostapd_hw_get_freq(iface->bss[0], iface->conf->channel); + if (iface->conf->secondary_channel > 0) + sec_freq = pri_freq + 20; + else + sec_freq = pri_freq - 20; + /* + * Note: Need to find the PRI channel also in cases where the affected + * channel is the SEC channel of a 40 MHz BSS, so need to include the + * scanning coverage here to be 40 MHz from the center frequency. + */ + affected_start = (pri_freq + sec_freq) / 2 - 40; + affected_end = (pri_freq + sec_freq) / 2 + 40; + wpa_printf(MSG_DEBUG, "40 MHz affected channel range: [%d,%d] MHz", + affected_start, affected_end); + + mode = iface->current_mode; + params->freqs = os_calloc(mode->num_channels + 1, sizeof(int)); + if (params->freqs == NULL) + return; + pos = 0; + + for (i = 0; i < mode->num_channels; i++) { + struct hostapd_channel_data *chan = &mode->channels[i]; + if (chan->flag & HOSTAPD_CHAN_DISABLED) + continue; + if (chan->freq < affected_start || + chan->freq > affected_end) + continue; + params->freqs[pos++] = chan->freq; + } +} + + +static void ieee80211n_scan_channels_5g(struct hostapd_iface *iface, + struct wpa_driver_scan_params *params) +{ + /* Scan only the affected frequency range */ + int pri_freq; + int affected_start, affected_end; + int i, pos; + struct hostapd_hw_modes *mode; + + if (iface->current_mode == NULL) + return; + + pri_freq = hostapd_hw_get_freq(iface->bss[0], iface->conf->channel); + if (iface->conf->secondary_channel > 0) { + affected_start = pri_freq - 10; + affected_end = pri_freq + 30; + } else { + affected_start = pri_freq - 30; + affected_end = pri_freq + 10; + } + wpa_printf(MSG_DEBUG, "40 MHz affected channel range: [%d,%d] MHz", + affected_start, affected_end); + + mode = iface->current_mode; + params->freqs = os_calloc(mode->num_channels + 1, sizeof(int)); + if (params->freqs == NULL) + return; + pos = 0; + + for (i = 0; i < mode->num_channels; i++) { + struct hostapd_channel_data *chan = &mode->channels[i]; + if (chan->flag & HOSTAPD_CHAN_DISABLED) + continue; + if (chan->freq < affected_start || + chan->freq > affected_end) + continue; + params->freqs[pos++] = chan->freq; + } +} + + +static void ap_ht40_scan_retry(void *eloop_data, void *user_data) +{ +#define HT2040_COEX_SCAN_RETRY 15 + struct hostapd_iface *iface = eloop_data; + struct wpa_driver_scan_params params; + int ret; + + os_memset(¶ms, 0, sizeof(params)); + if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G) + ieee80211n_scan_channels_2g4(iface, ¶ms); +#ifdef CONFIG_FULL_HOSTAPD + else + ieee80211n_scan_channels_5g(iface, ¶ms); +#endif + + ret = hostapd_driver_scan(iface->bss[0], ¶ms); + iface->num_ht40_scan_tries++; + os_free(params.freqs); + + if (ret == -ERRBUSY && + iface->num_ht40_scan_tries < HT2040_COEX_SCAN_RETRY) { + wpa_printf(MSG_ERROR, + "Failed to request a scan of neighboring BSSes ret=%d (%s) - try to scan again (attempt %d)", + ret, strerror(-ret), iface->num_ht40_scan_tries); + eloop_register_timeout(1, 0, ap_ht40_scan_retry, iface, NULL); + return; + } + + if (ret == 0) { + iface->scan_cb = ieee80211n_check_scan; + return; + } + + wpa_printf(MSG_DEBUG, + "Failed to request a scan in device, bringing up in HT20 mode"); + iface->conf->secondary_channel = 0; + iface->conf->ht_capab &= ~HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET; + hostapd_setup_interface_complete(iface, 0); +} + + +void hostapd_stop_setup_timers(struct hostapd_iface *iface) +{ + eloop_cancel_timeout(ap_ht40_scan_retry, iface, NULL); +} + + +static int ieee80211n_check_40mhz(struct hostapd_iface *iface) +{ + struct wpa_driver_scan_params params; + int ret; + + /* Check that HT40 is used and PRI / SEC switch is allowed */ + if (!iface->conf->secondary_channel || iface->conf->no_pri_sec_switch) + return 0; + + hostapd_set_state(iface, HAPD_IFACE_HT_SCAN); + wpa_printf(MSG_DEBUG, "Scan for neighboring BSSes prior to enabling " + "40 MHz channel"); + os_memset(¶ms, 0, sizeof(params)); + if (iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G) + ieee80211n_scan_channels_2g4(iface, ¶ms); +#ifdef CONFIG_FULL_HOSTAPD + else + ieee80211n_scan_channels_5g(iface, ¶ms); +#endif + + ret = hostapd_driver_scan(iface->bss[0], ¶ms); + os_free(params.freqs); + + if (ret == -ERRBUSY) { + wpa_printf(MSG_ERROR, + "Failed to request a scan of neighboring BSSes ret=%d (%s) - try to scan again", + ret, strerror(-ret)); + iface->num_ht40_scan_tries = 1; + eloop_cancel_timeout(ap_ht40_scan_retry, iface, NULL); + eloop_register_timeout(1, 0, ap_ht40_scan_retry, iface, NULL); + return 1; + } + + if (ret < 0) { + wpa_printf(MSG_ERROR, + "Failed to request a scan of neighboring BSSes ret=%d (%s)", + ret, strerror(-ret)); + return -1; + } + + iface->scan_cb = ieee80211n_check_scan; + return 1; +} + + +static int ieee80211n_supported_ht_capab(struct hostapd_iface *iface) +{ + u16 hw = iface->current_mode->ht_capab; + u16 conf = iface->conf->ht_capab; + + if ((conf & HT_CAP_INFO_LDPC_CODING_CAP) && + !(hw & HT_CAP_INFO_LDPC_CODING_CAP)) { + wpa_printf(MSG_ERROR, "Driver does not support configured " + "HT capability [LDPC]"); + return 0; + } + + /* + * Driver ACS chosen channel may not be HT40 due to internal driver + * restrictions. + */ + if (!iface->conf->acs && (conf & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) && + !(hw & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) { + wpa_printf(MSG_ERROR, "Driver does not support configured " + "HT capability [HT40*]"); + return 0; + } + + switch (conf & HT_CAP_INFO_SMPS_MASK) { + case HT_CAP_INFO_SMPS_STATIC: + if (!(iface->smps_modes & WPA_DRIVER_SMPS_MODE_STATIC)) { + wpa_printf(MSG_ERROR, + "Driver does not support configured HT capability [SMPS-STATIC]"); + return 0; + } + break; + case HT_CAP_INFO_SMPS_DYNAMIC: + if (!(iface->smps_modes & WPA_DRIVER_SMPS_MODE_DYNAMIC)) { + wpa_printf(MSG_ERROR, + "Driver does not support configured HT capability [SMPS-DYNAMIC]"); + return 0; + } + break; + case HT_CAP_INFO_SMPS_DISABLED: + default: + break; + } + + if ((conf & HT_CAP_INFO_GREEN_FIELD) && + !(hw & HT_CAP_INFO_GREEN_FIELD)) { + wpa_printf(MSG_ERROR, "Driver does not support configured " + "HT capability [GF]"); + return 0; + } + + if ((conf & HT_CAP_INFO_SHORT_GI20MHZ) && + !(hw & HT_CAP_INFO_SHORT_GI20MHZ)) { + wpa_printf(MSG_ERROR, "Driver does not support configured " + "HT capability [SHORT-GI-20]"); + return 0; + } + + if ((conf & HT_CAP_INFO_SHORT_GI40MHZ) && + !(hw & HT_CAP_INFO_SHORT_GI40MHZ)) { + wpa_printf(MSG_ERROR, "Driver does not support configured " + "HT capability [SHORT-GI-40]"); + return 0; + } + + if ((conf & HT_CAP_INFO_TX_STBC) && !(hw & HT_CAP_INFO_TX_STBC)) { + wpa_printf(MSG_ERROR, "Driver does not support configured " + "HT capability [TX-STBC]"); + return 0; + } + + if ((conf & HT_CAP_INFO_RX_STBC_MASK) > + (hw & HT_CAP_INFO_RX_STBC_MASK)) { + wpa_printf(MSG_ERROR, "Driver does not support configured " + "HT capability [RX-STBC*]"); + return 0; + } + + if ((conf & HT_CAP_INFO_DELAYED_BA) && + !(hw & HT_CAP_INFO_DELAYED_BA)) { + wpa_printf(MSG_ERROR, "Driver does not support configured " + "HT capability [DELAYED-BA]"); + return 0; + } + + if ((conf & HT_CAP_INFO_MAX_AMSDU_SIZE) && + !(hw & HT_CAP_INFO_MAX_AMSDU_SIZE)) { + wpa_printf(MSG_ERROR, "Driver does not support configured " + "HT capability [MAX-AMSDU-7935]"); + return 0; + } + + if ((conf & HT_CAP_INFO_DSSS_CCK40MHZ) && + !(hw & HT_CAP_INFO_DSSS_CCK40MHZ)) { + wpa_printf(MSG_ERROR, "Driver does not support configured " + "HT capability [DSSS_CCK-40]"); + return 0; + } + + if ((conf & HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT) && + !(hw & HT_CAP_INFO_LSIG_TXOP_PROTECT_SUPPORT)) { + wpa_printf(MSG_ERROR, "Driver does not support configured " + "HT capability [LSIG-TXOP-PROT]"); + return 0; + } + + return 1; +} + + +#ifdef CONFIG_IEEE80211AC +static int ieee80211ac_supported_vht_capab(struct hostapd_iface *iface) +{ + struct hostapd_hw_modes *mode = iface->current_mode; + u32 hw = mode->vht_capab; + u32 conf = iface->conf->vht_capab; + + wpa_printf(MSG_DEBUG, "hw vht capab: 0x%x, conf vht capab: 0x%x", + hw, conf); + + if (mode->mode == HOSTAPD_MODE_IEEE80211G && + iface->conf->bss[0]->vendor_vht && + mode->vht_capab == 0 && iface->hw_features) { + int i; + + for (i = 0; i < iface->num_hw_features; i++) { + if (iface->hw_features[i].mode == + HOSTAPD_MODE_IEEE80211A) { + mode = &iface->hw_features[i]; + hw = mode->vht_capab; + wpa_printf(MSG_DEBUG, + "update hw vht capab based on 5 GHz band: 0x%x", + hw); + break; + } + } + } + + return ieee80211ac_cap_check(hw, conf); +} +#endif /* CONFIG_IEEE80211AC */ + + +#ifdef CONFIG_IEEE80211AX +static int ieee80211ax_supported_he_capab(struct hostapd_iface *iface) +{ + return 1; +} +#endif /* CONFIG_IEEE80211AX */ + +#endif /* CONFIG_IEEE80211N */ + + +int hostapd_check_ht_capab(struct hostapd_iface *iface) +{ +#ifdef CONFIG_IEEE80211N + int ret; + if (!iface->conf->ieee80211n) + return 0; + + if (iface->current_mode->mode != HOSTAPD_MODE_IEEE80211B && + iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G && + (iface->conf->ht_capab & HT_CAP_INFO_DSSS_CCK40MHZ)) { + wpa_printf(MSG_DEBUG, + "Disable HT capability [DSSS_CCK-40] on 5 GHz band"); + iface->conf->ht_capab &= ~HT_CAP_INFO_DSSS_CCK40MHZ; + } + + if (!ieee80211n_supported_ht_capab(iface)) + return -1; +#ifdef CONFIG_IEEE80211AX + if (iface->conf->ieee80211ax && + !ieee80211ax_supported_he_capab(iface)) + return -1; +#endif /* CONFIG_IEEE80211AX */ +#ifdef CONFIG_IEEE80211AC + if (iface->conf->ieee80211ac && + !ieee80211ac_supported_vht_capab(iface)) + return -1; +#endif /* CONFIG_IEEE80211AC */ + ret = ieee80211n_check_40mhz(iface); + if (ret) + return ret; + if (!ieee80211n_allowed_ht40_channel_pair(iface)) + return -1; +#endif /* CONFIG_IEEE80211N */ + + return 0; +} + + +static int hostapd_is_usable_chan(struct hostapd_iface *iface, + int channel, int primary) +{ + struct hostapd_channel_data *chan; + + if (!iface->current_mode) + return 0; + + chan = hw_get_channel_chan(iface->current_mode, channel, NULL); + if (!chan) + return 0; + + if ((primary && chan_pri_allowed(chan)) || + (!primary && !(chan->flag & HOSTAPD_CHAN_DISABLED))) + return 1; + + wpa_printf(MSG_INFO, + "Channel %d (%s) not allowed for AP mode, flags: 0x%x%s%s", + channel, primary ? "primary" : "secondary", + chan->flag, + chan->flag & HOSTAPD_CHAN_NO_IR ? " NO-IR" : "", + chan->flag & HOSTAPD_CHAN_RADAR ? " RADAR" : ""); + return 0; +} + + +static int hostapd_is_usable_chans(struct hostapd_iface *iface) +{ + int secondary_chan; + struct hostapd_channel_data *pri_chan; + + pri_chan = hw_get_channel_chan(iface->current_mode, + iface->conf->channel, NULL); + if (!pri_chan) + return 0; + + if (!hostapd_is_usable_chan(iface, iface->conf->channel, 1)) + return 0; + + if (!iface->conf->secondary_channel) + return 1; + + if (!iface->conf->ht40_plus_minus_allowed) + return hostapd_is_usable_chan( + iface, iface->conf->channel + + iface->conf->secondary_channel * 4, 0); + + /* Both HT40+ and HT40- are set, pick a valid secondary channel */ + secondary_chan = iface->conf->channel + 4; + if (hostapd_is_usable_chan(iface, secondary_chan, 0) && + (pri_chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40P)) { + iface->conf->secondary_channel = 1; + return 1; + } + + secondary_chan = iface->conf->channel - 4; + if (hostapd_is_usable_chan(iface, secondary_chan, 0) && + (pri_chan->allowed_bw & HOSTAPD_CHAN_WIDTH_40M)) { + iface->conf->secondary_channel = -1; + return 1; + } + + return 0; +} + + +static enum hostapd_chan_status +hostapd_check_chans(struct hostapd_iface *iface) +{ + iface->conf->channel = g_ap_param_ptr->chann; + + if (iface->conf->channel) { + if (hostapd_is_usable_chans(iface)) + return HOSTAPD_CHAN_VALID; + else + return HOSTAPD_CHAN_INVALID; + } + + /* + * The user set channel=0 or channel=acs_survey + * which is used to trigger ACS. + */ + + switch (acs_init(iface)) { + case HOSTAPD_CHAN_ACS: + return HOSTAPD_CHAN_ACS; + case HOSTAPD_CHAN_VALID: + case HOSTAPD_CHAN_INVALID: + default: + return HOSTAPD_CHAN_INVALID; + } +} + + +static void hostapd_notify_bad_chans(struct hostapd_iface *iface) +{ + if (!iface->current_mode) { + hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_WARNING, + "Hardware does not support configured mode"); + return; + } + hostapd_logger(iface->bss[0], NULL, + HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_WARNING, + "Configured channel (%d) not found from the " + "channel list of current mode (%d) %s", + iface->conf->channel, + iface->current_mode->mode, + hostapd_hw_mode_txt(iface->current_mode->mode)); + hostapd_logger(iface->bss[0], NULL, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_WARNING, + "Hardware does not support configured channel"); +} + + +int hostapd_acs_completed(struct hostapd_iface *iface, int err) +{ + int ret = -1; + + if (err) + goto out; + + switch (hostapd_check_chans(iface)) { + case HOSTAPD_CHAN_VALID: + wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, + ACS_EVENT_COMPLETED "freq=%d channel=%d", + hostapd_hw_get_freq(iface->bss[0], + iface->conf->channel), + iface->conf->channel); + break; + case HOSTAPD_CHAN_ACS: + wpa_printf(MSG_ERROR, "ACS error - reported complete, but no result available"); + wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, ACS_EVENT_FAILED); + hostapd_notify_bad_chans(iface); + goto out; + case HOSTAPD_CHAN_INVALID: + default: + wpa_printf(MSG_ERROR, "ACS picked unusable channels"); + wpa_msg(iface->bss[0]->msg_ctx, MSG_INFO, ACS_EVENT_FAILED); + hostapd_notify_bad_chans(iface); + goto out; + } + + ret = hostapd_check_ht_capab(iface); + if (ret < 0) + goto out; + if (ret == 1) { + wpa_printf(MSG_DEBUG, "Interface initialization will be completed in a callback"); + return 0; + } + + ret = 0; +out: + return hostapd_setup_interface_complete(iface, ret); +} + + +/** + * hostapd_select_hw_mode - Select the hardware mode + * @iface: Pointer to interface data. + * Returns: 0 on success, < 0 on failure + * + * Sets up the hardware mode, channel, rates, and passive scanning + * based on the configuration. + */ +int hostapd_select_hw_mode(struct hostapd_iface *iface) +{ + int i; + + if (iface->num_hw_features < 1) + return -1; + + if ((iface->conf->hw_mode == HOSTAPD_MODE_IEEE80211G || + iface->conf->ieee80211n || iface->conf->ieee80211ac || + iface->conf->ieee80211ax) && + iface->conf->channel == 14) { + wpa_printf(MSG_INFO, "Disable OFDM/HT/VHT/HE on channel 14"); + iface->conf->hw_mode = HOSTAPD_MODE_IEEE80211B; + iface->conf->ieee80211n = 0; + iface->conf->ieee80211ac = 0; + iface->conf->ieee80211ax = 0; + } + + iface->current_mode = NULL; + for (i = 0; i < iface->num_hw_features; i++) { + struct hostapd_hw_modes *mode = &iface->hw_features[i]; + if (mode->mode == iface->conf->hw_mode) { + iface->current_mode = mode; + break; + } + } + + if (iface->current_mode == NULL) { + if (!(iface->drv_flags & WPA_DRIVER_FLAGS_ACS_OFFLOAD) || + !(iface->drv_flags & WPA_DRIVER_FLAGS_SUPPORT_HW_MODE_ANY)) + { + wpa_printf(MSG_ERROR, + "Hardware does not support configured mode"); + hostapd_logger(iface->bss[0], NULL, + HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_WARNING, + "Hardware does not support configured mode (%d) (hw_mode in hostapd.conf)", + (int) iface->conf->hw_mode); + return -2; + } + } + + switch (hostapd_check_chans(iface)) { + case HOSTAPD_CHAN_VALID: + return 0; + case HOSTAPD_CHAN_ACS: /* ACS will run and later complete */ + return 1; + case HOSTAPD_CHAN_INVALID: + default: + hostapd_notify_bad_chans(iface); + return -3; + } +} + + +const char * hostapd_hw_mode_txt(int mode) +{ + switch (mode) { + case HOSTAPD_MODE_IEEE80211A: + return "IEEE 802.11a"; + case HOSTAPD_MODE_IEEE80211B: + return "IEEE 802.11b"; + case HOSTAPD_MODE_IEEE80211G: + return "IEEE 802.11g"; + case HOSTAPD_MODE_IEEE80211AD: + return "IEEE 802.11ad"; + default: + return "UNKNOWN"; + } +} + + +int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan) +{ + return hw_get_freq(hapd->iface->current_mode, chan); +} + + +int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq) +{ + int i, channel; + struct hostapd_hw_modes *mode; + + if (hapd->iface->current_mode) { + channel = hw_get_chan(hapd->iface->current_mode, freq); + if (channel) + return channel; + } + + /* Check other available modes since the channel list for the current + * mode did not include the specified frequency. */ + if (!hapd->iface->hw_features) + return 0; + for (i = 0; i < hapd->iface->num_hw_features; i++) { + mode = &hapd->iface->hw_features[i]; + channel = hw_get_chan(mode, freq); + if (channel) + return channel; + } + return 0; +} diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/hw_features.h b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/hw_features.h new file mode 100755 index 0000000..ca7f22b --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/hw_features.h @@ -0,0 +1,76 @@ +/* + * hostapd / Hardware feature query and different modes + * Copyright 2002-2003, Instant802 Networks, Inc. + * Copyright 2005-2006, Devicescape Software, Inc. + * Copyright (c) 2008-2011, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef HW_FEATURES_H +#define HW_FEATURES_H + +#ifdef NEED_AP_MLME +void hostapd_free_hw_features(struct hostapd_hw_modes *hw_features, + size_t num_hw_features); +int hostapd_get_hw_features(struct hostapd_iface *iface); +int hostapd_acs_completed(struct hostapd_iface *iface, int err); +int hostapd_select_hw_mode(struct hostapd_iface *iface); +const char * hostapd_hw_mode_txt(int mode); +int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan); +int hostapd_hw_get_channel(struct hostapd_data *hapd, int freq); +int hostapd_check_ht_capab(struct hostapd_iface *iface); +int hostapd_prepare_rates(struct hostapd_iface *iface, + struct hostapd_hw_modes *mode); +void hostapd_stop_setup_timers(struct hostapd_iface *iface); +#else /* NEED_AP_MLME */ +static inline void +hostapd_free_hw_features(struct hostapd_hw_modes *hw_features, + size_t num_hw_features) +{ +} + +static inline int hostapd_get_hw_features(struct hostapd_iface *iface) +{ + return -1; +} + +static inline int hostapd_acs_completed(struct hostapd_iface *iface, int err) +{ + return -1; +} + +static inline int hostapd_select_hw_mode(struct hostapd_iface *iface) +{ + return -100; +} + +static inline const char * hostapd_hw_mode_txt(int mode) +{ + return NULL; +} + +static inline int hostapd_hw_get_freq(struct hostapd_data *hapd, int chan) +{ + return -1; +} + +static inline int hostapd_check_ht_capab(struct hostapd_iface *iface) +{ + return 0; +} + +static inline int hostapd_prepare_rates(struct hostapd_iface *iface, + struct hostapd_hw_modes *mode) +{ + return 0; +} + +static inline void hostapd_stop_setup_timers(struct hostapd_iface *iface) +{ +} + +#endif /* NEED_AP_MLME */ + +#endif /* HW_FEATURES_H */ diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ieee802_11.c b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ieee802_11.c new file mode 100755 index 0000000..4bd98b9 --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ieee802_11.c @@ -0,0 +1,4405 @@ +/* + * hostapd / IEEE 802.11 Management + * Copyright (c) 2002-2014, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "include.h" +#include "uart_pub.h" + +#include "includes.h" + +#include "utils/common.h" +#include "utils/eloop.h" +#include "crypto/crypto.h" +#include "crypto/sha256.h" +#include "crypto/sha384.h" +#include "crypto/sha512.h" +#include "crypto/random.h" +#include "common/ieee802_11_defs.h" +#include "common/ieee802_11_common.h" +#include "common/wpa_ctrl.h" +#include "common/sae.h" +#include "common/dpp.h" +#include "common/wpa_common.h" +#include "wps/wps.h" +#include "ap/hostapd.h" +#include "beacon.h" +#include "ieee802_11_auth.h" +#include "ap/sta_info.h" +#include "ieee802_1x.h" +#include "wpa_auth.h" +#include "pmksa_cache_auth.h" +#include "wmm.h" +#include "ap_list.h" +#include "accounting.h" +#include "ap_config.h" +#include "ap_mlme.h" +#include "p2p_hostapd.h" +#include "ap_drv_ops.h" +#include "hw_features.h" +#include "ieee802_11.h" +#include "ap/dfs.h" +#include "dpp_hostapd.h" + +#ifdef CONFIG_FILS +static struct wpabuf * +prepare_auth_resp_fils(struct hostapd_data *hapd, + struct sta_info *sta, u16 *resp, + struct rsn_pmksa_cache_entry *pmksa, + struct wpabuf *erp_resp, + const u8 *msk, size_t msk_len, + int *is_pub); +#endif /* CONFIG_FILS */ +static void handle_auth(struct hostapd_data *hapd, + const struct ieee80211_mgmt *mgmt, size_t len, + int rssi, int from_queue); + + +#ifdef CONFIG_FULL_HOSTAPD +u8 * hostapd_eid_multi_ap(struct hostapd_data *hapd, u8 *eid) +{ + u8 multi_ap_val = 0; + + if (!hapd->conf->multi_ap) + return eid; + if (hapd->conf->multi_ap & BACKHAUL_BSS) + multi_ap_val |= MULTI_AP_BACKHAUL_BSS; + if (hapd->conf->multi_ap & FRONTHAUL_BSS) + multi_ap_val |= MULTI_AP_FRONTHAUL_BSS; + + return eid + add_multi_ap_ie(eid, 9, multi_ap_val); +} +#endif + +u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid) +{ + u8 *pos = eid; + int i, num, count; + + if (hapd->iface->current_rates == NULL) + return eid; + + *pos++ = WLAN_EID_SUPP_RATES; + num = hapd->iface->num_rates; + if (hapd->iconf->ieee80211n && hapd->iconf->require_ht) + num++; + if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht) + num++; + if (num > 8) { + /* rest of the rates are encoded in Extended supported + * rates element */ + num = 8; + } + + *pos++ = num; + for (i = 0, count = 0; i < hapd->iface->num_rates && count < num; + i++) { + count++; + *pos = hapd->iface->current_rates[i].rate / 5; + if (hapd->iface->current_rates[i].flags & HOSTAPD_RATE_BASIC) + *pos |= 0x80; + pos++; + } + + if (hapd->iconf->ieee80211n && hapd->iconf->require_ht && count < 8) { + count++; + *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_HT_PHY; + } + +#ifdef CONFIG_FULL_HOSTAPD + if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht && count < 8) { + count++; + *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_VHT_PHY; + } +#endif + + return pos; +} + + +u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid) +{ + u8 *pos = eid; + int i, num, count; + + if (hapd->iface->current_rates == NULL) + return eid; + + num = hapd->iface->num_rates; + if (hapd->iconf->ieee80211n && hapd->iconf->require_ht) + num++; + if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht) + num++; + if (num <= 8) + return eid; + num -= 8; + + *pos++ = WLAN_EID_EXT_SUPP_RATES; + *pos++ = num; + for (i = 0, count = 0; i < hapd->iface->num_rates && count < num + 8; + i++) { + count++; + if (count <= 8) + continue; /* already in SuppRates IE */ + *pos = hapd->iface->current_rates[i].rate / 5; + if (hapd->iface->current_rates[i].flags & HOSTAPD_RATE_BASIC) + *pos |= 0x80; + pos++; + } + + if (hapd->iconf->ieee80211n && hapd->iconf->require_ht) { + count++; + if (count > 8) + *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_HT_PHY; + } + +#ifdef CONFIG_FULL_HOSTAPD + if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht) { + count++; + if (count > 8) + *pos++ = 0x80 | BSS_MEMBERSHIP_SELECTOR_VHT_PHY; + } +#endif + + return pos; +} + + +u16 hostapd_own_capab_info(struct hostapd_data *hapd) +{ + int capab = WLAN_CAPABILITY_ESS; + int privacy; + +#ifdef CONFIG_DFS + int dfs = 0; + + /* Check if any of configured channels require DFS */ + dfs = hostapd_is_dfs_required(hapd->iface); + if (dfs < 0) { + wpa_printf(MSG_WARNING, "Failed to check if DFS is required; ret=%d", + dfs); + dfs = 0; + } +#endif +#if 1 //wangzhilei + hapd->iface->num_sta_no_short_preamble = 0; + hapd->iconf->preamble = SHORT_PREAMBLE; +#endif + + if (hapd->iface->num_sta_no_short_preamble == 0 && + hapd->iconf->preamble == SHORT_PREAMBLE) + capab |= WLAN_CAPABILITY_SHORT_PREAMBLE; + + privacy = hapd->conf->ssid.wep.keys_set; + +#ifdef CONFIG_FULL_SUPPLICANT + if (hapd->conf->ieee802_1x && + (hapd->conf->default_wep_key_len || + hapd->conf->individual_wep_key_len)) + privacy = 1; +#endif + + if (hapd->conf->wpa) + privacy = 1; + +#ifdef CONFIG_HS20 + if (hapd->conf->osen) + privacy = 1; +#endif /* CONFIG_HS20 */ + + if (privacy) + capab |= WLAN_CAPABILITY_PRIVACY; + +#if 0 //wangzhilei + if (hapd->iface->current_mode && + hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G && + hapd->iface->num_sta_no_short_slot_time == 0) +#endif + capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME; + +#ifdef CONFIG_FULL_HOSTAPD + /* + * Currently, Spectrum Management capability bit is set when directly + * requested in configuration by spectrum_mgmt_required or when AP is + * running on DFS channel. + * TODO: Also consider driver support for TPC to set Spectrum Mgmt bit + */ + if (hapd->iface->current_mode && + hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211A && + (hapd->iconf->spectrum_mgmt_required || dfs)) + capab |= WLAN_CAPABILITY_SPECTRUM_MGMT; + + for (int i = 0; i < RRM_CAPABILITIES_IE_LEN; i++) { + if (hapd->conf->radio_measurements[i]) { + capab |= IEEE80211_CAP_RRM; + break; + } + } +#endif + + return capab; +} + + +#ifndef CONFIG_NO_RC4 +static u16 auth_shared_key(struct hostapd_data *hapd, struct sta_info *sta, + u16 auth_transaction, const u8 *challenge, + int iswep) +{ + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "authentication (shared key, transaction %d)", + auth_transaction); + + if (auth_transaction == 1) { + if (!sta->challenge) { + /* Generate a pseudo-random challenge */ + u8 key[8]; + + sta->challenge = os_zalloc(WLAN_AUTH_CHALLENGE_LEN); + if (sta->challenge == NULL) + return WLAN_STATUS_UNSPECIFIED_FAILURE; + + if (os_get_random(key, sizeof(key)) < 0) { + os_free(sta->challenge); + sta->challenge = NULL; + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + + rc4_skip(key, sizeof(key), 0, + sta->challenge, WLAN_AUTH_CHALLENGE_LEN); + } + return 0; + } + + if (auth_transaction != 3) + return WLAN_STATUS_UNSPECIFIED_FAILURE; + + /* Transaction 3 */ + if (!iswep || !sta->challenge || !challenge || + os_memcmp_const(sta->challenge, challenge, + WLAN_AUTH_CHALLENGE_LEN)) { + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, + "shared key authentication - invalid " + "challenge-response"); + return WLAN_STATUS_CHALLENGE_FAIL; + } + + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "authentication OK (shared key)"); + sta->flags |= WLAN_STA_AUTH; + wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH); + os_free(sta->challenge); + sta->challenge = NULL; + + return 0; +} +#endif /* CONFIG_NO_RC4 */ + + +static int send_auth_reply(struct hostapd_data *hapd, + const u8 *dst, const u8 *bssid, + u16 auth_alg, u16 auth_transaction, u16 resp, + const u8 *ies, size_t ies_len, const char *dbg) +{ + struct ieee80211_mgmt *reply; + u8 *buf; + size_t rlen; + int reply_res = WLAN_STATUS_UNSPECIFIED_FAILURE; + + rlen = IEEE80211_HDRLEN + sizeof(reply->u.auth) + ies_len; + buf = os_zalloc(rlen); + if (buf == NULL) + return -1; + + reply = (struct ieee80211_mgmt *) buf; + reply->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, + WLAN_FC_STYPE_AUTH); + os_memcpy(reply->da, dst, ETH_ALEN); + os_memcpy(reply->sa, hapd->own_addr, ETH_ALEN); + os_memcpy(reply->bssid, bssid, ETH_ALEN); + + reply->u.auth.auth_alg = host_to_le16(auth_alg); + reply->u.auth.auth_transaction = host_to_le16(auth_transaction); + reply->u.auth.status_code = host_to_le16(resp); + + if (ies && ies_len) + os_memcpy(reply->u.auth.variable, ies, ies_len); + + wpa_printf(MSG_DEBUG, "authentication reply: STA=" MACSTR + " auth_alg=%d auth_transaction=%d resp=%d (IE len=%lu) (dbg=%s)", + MAC2STR(dst), auth_alg, auth_transaction, + resp, (unsigned long) ies_len, dbg); + if (hostapd_drv_send_mlme(hapd, reply, rlen, 0) < 0) + wpa_printf(MSG_INFO, "send_auth_reply: send failed"); + else + reply_res = WLAN_STATUS_SUCCESS; + + os_free(buf); + + return reply_res; +} + + +#ifdef CONFIG_IEEE80211R_AP +static void handle_auth_ft_finish(void *ctx, const u8 *dst, const u8 *bssid, + u16 auth_transaction, u16 status, + const u8 *ies, size_t ies_len) +{ + struct hostapd_data *hapd = ctx; + struct sta_info *sta; + int reply_res; + + reply_res = send_auth_reply(hapd, dst, bssid, WLAN_AUTH_FT, + auth_transaction, status, ies, ies_len, + "auth-ft-finish"); + + sta = ap_get_sta(hapd, dst); + if (sta == NULL) + return; + + if (sta->added_unassoc && (reply_res != WLAN_STATUS_SUCCESS || + status != WLAN_STATUS_SUCCESS)) { + hostapd_drv_sta_remove(hapd, sta->addr); + sta->added_unassoc = 0; + return; + } + + if (status != WLAN_STATUS_SUCCESS) + return; + + hostapd_logger(hapd, dst, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, "authentication OK (FT)"); + sta->flags |= WLAN_STA_AUTH; + mlme_authenticate_indication(hapd, sta); +} +#endif /* CONFIG_IEEE80211R_AP */ + + +#ifdef CONFIG_SAE_AP + +static void sae_set_state(struct sta_info *sta, enum sae_state state, + const char *reason) +{ + wpa_printf(MSG_DEBUG, "SAE: State %s -> %s for peer " MACSTR " (%s)", + sae_state_txt(sta->sae->state), sae_state_txt(state), + MAC2STR(sta->addr), reason); + sta->sae->state = state; +} + + +static struct wpabuf * auth_build_sae_commit(struct hostapd_data *hapd, + struct sta_info *sta, int update) +{ + struct wpabuf *buf; + const char *password = NULL; + struct sae_password_entry *pw; + const char *rx_id = NULL; + + if (sta->sae->tmp) + rx_id = sta->sae->tmp->pw_id; + + for (pw = hapd->conf->sae_passwords; pw; pw = pw->next) { + if (!is_broadcast_ether_addr(pw->peer_addr) && + os_memcmp(pw->peer_addr, sta->addr, ETH_ALEN) != 0) + continue; + if ((rx_id && !pw->identifier) || (!rx_id && pw->identifier)) + continue; + if (rx_id && pw->identifier && + os_strcmp(rx_id, pw->identifier) != 0) + continue; + password = pw->password; + break; + } + if (!password) + password = hapd->conf->ssid.wpa_passphrase; + if (!password) { + wpa_printf(MSG_DEBUG, "SAE: No password available"); + return NULL; + } + + if (update && + sae_prepare_commit(hapd->own_addr, sta->addr, + (u8 *) password, os_strlen(password), rx_id, + sta->sae) < 0) { + wpa_printf(MSG_DEBUG, "SAE: Could not pick PWE"); + return NULL; + } + + if (pw && pw->vlan_id) { + if (!sta->sae->tmp) { + wpa_printf(MSG_INFO, + "SAE: No temporary data allocated - cannot store VLAN ID"); + return NULL; + } + sta->sae->tmp->vlan_id = pw->vlan_id; + } + + buf = wpabuf_alloc(SAE_COMMIT_MAX_LEN + + (rx_id ? 3 + os_strlen(rx_id) : 0)); + if (buf == NULL) + return NULL; + sae_write_commit(sta->sae, buf, sta->sae->tmp ? + sta->sae->tmp->anti_clogging_token : NULL, rx_id); + + return buf; +} + + +static struct wpabuf * auth_build_sae_confirm(struct hostapd_data *hapd, + struct sta_info *sta) +{ + struct wpabuf *buf; + + buf = wpabuf_alloc(SAE_CONFIRM_MAX_LEN); + if (buf == NULL) + return NULL; + + sae_write_confirm(sta->sae, buf); + + return buf; +} + + +static int auth_sae_send_commit(struct hostapd_data *hapd, + struct sta_info *sta, + const u8 *bssid, int update) +{ + struct wpabuf *data; + int reply_res; + + data = auth_build_sae_commit(hapd, sta, update); + if (!data && sta->sae->tmp && sta->sae->tmp->pw_id) + return WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER; + if (data == NULL) + return WLAN_STATUS_UNSPECIFIED_FAILURE; + + reply_res = send_auth_reply(hapd, sta->addr, bssid, WLAN_AUTH_SAE, 1, + WLAN_STATUS_SUCCESS, wpabuf_head(data), + wpabuf_len(data), "sae-send-commit"); + + wpabuf_free(data); + + return reply_res; +} + + +static int auth_sae_send_confirm(struct hostapd_data *hapd, + struct sta_info *sta, + const u8 *bssid) +{ + struct wpabuf *data; + int reply_res; + + data = auth_build_sae_confirm(hapd, sta); + if (data == NULL) + return WLAN_STATUS_UNSPECIFIED_FAILURE; + + reply_res = send_auth_reply(hapd, sta->addr, bssid, WLAN_AUTH_SAE, 2, + WLAN_STATUS_SUCCESS, wpabuf_head(data), + wpabuf_len(data), "sae-send-confirm"); + + wpabuf_free(data); + + return reply_res; +} + + +static int use_sae_anti_clogging(struct hostapd_data *hapd) +{ + struct sta_info *sta; + unsigned int open = 0; + + if (hapd->conf->sae_anti_clogging_threshold == 0) + return 1; + + for (sta = hapd->sta_list; sta; sta = sta->next) { + if (!sta->sae) + continue; + if (sta->sae->state != SAE_COMMITTED && + sta->sae->state != SAE_CONFIRMED) + continue; + open++; + if (open >= hapd->conf->sae_anti_clogging_threshold) + return 1; + } + + /* In addition to already existing open SAE sessions, check whether + * there are enough pending commit messages in the processing queue to + * potentially result in too many open sessions. */ + if (open + dl_list_len(&hapd->sae_commit_queue) >= + hapd->conf->sae_anti_clogging_threshold) + return 1; + + return 0; +} + + +static u8 sae_token_hash(struct hostapd_data *hapd, const u8 *addr) +{ + u8 hash[SHA256_MAC_LEN]; + + hmac_sha256(hapd->sae_token_key, sizeof(hapd->sae_token_key), + addr, ETH_ALEN, hash); + return hash[0]; +} + + +static int check_sae_token(struct hostapd_data *hapd, const u8 *addr, + const u8 *token, size_t token_len) +{ + u8 mac[SHA256_MAC_LEN]; + const u8 *addrs[2]; + size_t len[2]; + u16 token_idx; + u8 idx; + + if (token_len != SHA256_MAC_LEN) + return -1; + idx = sae_token_hash(hapd, addr); + token_idx = hapd->sae_pending_token_idx[idx]; + if (token_idx == 0 || token_idx != WPA_GET_BE16(token)) { + wpa_printf(MSG_DEBUG, "SAE: Invalid anti-clogging token from " + MACSTR " - token_idx 0x%04x, expected 0x%04x", + MAC2STR(addr), WPA_GET_BE16(token), token_idx); + return -1; + } + + addrs[0] = addr; + len[0] = ETH_ALEN; + addrs[1] = token; + len[1] = 2; + if (hmac_sha256_vector(hapd->sae_token_key, sizeof(hapd->sae_token_key), + 2, addrs, len, mac) < 0 || + os_memcmp_const(token + 2, &mac[2], SHA256_MAC_LEN - 2) != 0) + return -1; + + hapd->sae_pending_token_idx[idx] = 0; /* invalidate used token */ + + return 0; +} + + +static struct wpabuf * auth_build_token_req(struct hostapd_data *hapd, + int group, const u8 *addr) +{ + struct wpabuf *buf; + u8 *token; + struct os_reltime now; + u8 idx[2]; + const u8 *addrs[2]; + size_t len[2]; + u8 p_idx; + u16 token_idx; + + os_get_reltime(&now); + if (!os_reltime_initialized(&hapd->last_sae_token_key_update) || + os_reltime_expired(&now, &hapd->last_sae_token_key_update, 60) || + hapd->sae_token_idx == 0xffff) { + if (random_get_bytes(hapd->sae_token_key, + sizeof(hapd->sae_token_key)) < 0) + return NULL; + wpa_hexdump(MSG_DEBUG, "SAE: Updated token key", + hapd->sae_token_key, sizeof(hapd->sae_token_key)); + hapd->last_sae_token_key_update = now; + hapd->sae_token_idx = 0; + os_memset(hapd->sae_pending_token_idx, 0, + sizeof(hapd->sae_pending_token_idx)); + } + + buf = wpabuf_alloc(sizeof(le16) + SHA256_MAC_LEN); + if (buf == NULL) + return NULL; + + wpabuf_put_le16(buf, group); /* Finite Cyclic Group */ + + p_idx = sae_token_hash(hapd, addr); + token_idx = hapd->sae_pending_token_idx[p_idx]; + if (!token_idx) { + hapd->sae_token_idx++; + token_idx = hapd->sae_token_idx; + hapd->sae_pending_token_idx[p_idx] = token_idx; + } + WPA_PUT_BE16(idx, token_idx); + token = wpabuf_put(buf, SHA256_MAC_LEN); + addrs[0] = addr; + len[0] = ETH_ALEN; + addrs[1] = idx; + len[1] = sizeof(idx); + if (hmac_sha256_vector(hapd->sae_token_key, sizeof(hapd->sae_token_key), + 2, addrs, len, token) < 0) { + wpabuf_free(buf); + return NULL; + } + WPA_PUT_BE16(token, token_idx); + + return buf; +} + + +static int sae_check_big_sync(struct hostapd_data *hapd, struct sta_info *sta) +{ + if (sta->sae->sync > hapd->conf->sae_sync) { + sae_set_state(sta, SAE_NOTHING, "Sync > dot11RSNASAESync"); + sta->sae->sync = 0; + return -1; + } + return 0; +} + + +static void auth_sae_retransmit_timer(void *eloop_ctx, void *eloop_data) +{ + struct hostapd_data *hapd = eloop_ctx; + struct sta_info *sta = eloop_data; + int ret; + + if (sae_check_big_sync(hapd, sta)) + return; + sta->sae->sync++; + wpa_printf(MSG_DEBUG, "SAE: Auth SAE retransmit timer for " MACSTR + " (sync=%d state=%s)", + MAC2STR(sta->addr), sta->sae->sync, + sae_state_txt(sta->sae->state)); + + switch (sta->sae->state) { + case SAE_COMMITTED: + ret = auth_sae_send_commit(hapd, sta, hapd->own_addr, 0); + eloop_register_timeout(0, + hapd->dot11RSNASAERetransPeriod * 1000, + auth_sae_retransmit_timer, hapd, sta); + break; + case SAE_CONFIRMED: + ret = auth_sae_send_confirm(hapd, sta, hapd->own_addr); + eloop_register_timeout(0, + hapd->dot11RSNASAERetransPeriod * 1000, + auth_sae_retransmit_timer, hapd, sta); + break; + default: + ret = -1; + break; + } + + if (ret != WLAN_STATUS_SUCCESS) + wpa_printf(MSG_INFO, "SAE: Failed to retransmit: ret=%d", ret); +} + + +void sae_clear_retransmit_timer(struct hostapd_data *hapd, struct sta_info *sta) +{ + eloop_cancel_timeout(auth_sae_retransmit_timer, hapd, sta); +} + + +static void sae_set_retransmit_timer(struct hostapd_data *hapd, + struct sta_info *sta) +{ + if (!(hapd->conf->mesh & MESH_ENABLED)) + return; + + eloop_cancel_timeout(auth_sae_retransmit_timer, hapd, sta); + eloop_register_timeout(0, hapd->dot11RSNASAERetransPeriod * 1000, + auth_sae_retransmit_timer, hapd, sta); +} + + +static void sae_sme_send_external_auth_status(struct hostapd_data *hapd, + struct sta_info *sta, u16 status) +{ + struct external_auth params; + + os_memset(¶ms, 0, sizeof(params)); + params.status = status; + params.bssid = sta->addr; + if (status == WLAN_STATUS_SUCCESS && sta->sae && + !hapd->conf->disable_pmksa_caching) + params.pmkid = sta->sae->pmkid; + + hostapd_drv_send_external_auth_status(hapd, ¶ms); +} + + +void sae_accept_sta(struct hostapd_data *hapd, struct sta_info *sta) +{ + sta->flags |= WLAN_STA_AUTH; + sta->auth_alg = WLAN_AUTH_SAE; + mlme_authenticate_indication(hapd, sta); + wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH); + sae_set_state(sta, SAE_ACCEPTED, "Accept Confirm"); + wpa_auth_pmksa_add_sae(hapd->wpa_auth, sta->addr, + sta->sae->pmk, sta->sae->pmkid); + sae_sme_send_external_auth_status(hapd, sta, WLAN_STATUS_SUCCESS); +} + + +static int sae_sm_step(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *bssid, u8 auth_transaction, int allow_reuse, + int *sta_removed) +{ + int ret; + + *sta_removed = 0; + + if (auth_transaction != 1 && auth_transaction != 2) + return WLAN_STATUS_UNSPECIFIED_FAILURE; + + wpa_printf(MSG_DEBUG, "SAE: Peer " MACSTR " state=%s auth_trans=%u", + MAC2STR(sta->addr), sae_state_txt(sta->sae->state), + auth_transaction); + switch (sta->sae->state) { + case SAE_NOTHING: + if (auth_transaction == 1) { + ret = auth_sae_send_commit(hapd, sta, bssid, + !allow_reuse); + if (ret) + return ret; + sae_set_state(sta, SAE_COMMITTED, "Sent Commit"); + + if (sae_process_commit(sta->sae) < 0) + return WLAN_STATUS_UNSPECIFIED_FAILURE; + + /* + * In mesh case, both Commit and Confirm can be sent + * immediately. In infrastructure BSS, only a single + * Authentication frame (Commit) is expected from the AP + * here and the second one (Confirm) will be sent once + * the STA has sent its second Authentication frame + * (Confirm). + */ + if (hapd->conf->mesh & MESH_ENABLED) { + /* + * Send both Commit and Confirm immediately + * based on SAE finite state machine + * Nothing -> Confirm transition. + */ + ret = auth_sae_send_confirm(hapd, sta, bssid); + if (ret) + return ret; + sae_set_state(sta, SAE_CONFIRMED, + "Sent Confirm (mesh)"); + } else { + /* + * For infrastructure BSS, send only the Commit + * message now to get alternating sequence of + * Authentication frames between the AP and STA. + * Confirm will be sent in + * Committed -> Confirmed/Accepted transition + * when receiving Confirm from STA. + */ + } + sta->sae->sync = 0; + sae_set_retransmit_timer(hapd, sta); + } else { + hostapd_logger(hapd, sta->addr, + HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "SAE confirm before commit"); + } + break; + case SAE_COMMITTED: + sae_clear_retransmit_timer(hapd, sta); + if (auth_transaction == 1) { + if (sae_process_commit(sta->sae) < 0) + return WLAN_STATUS_UNSPECIFIED_FAILURE; + + ret = auth_sae_send_confirm(hapd, sta, bssid); + if (ret) + return ret; + sae_set_state(sta, SAE_CONFIRMED, "Sent Confirm"); + sta->sae->sync = 0; + sae_set_retransmit_timer(hapd, sta); + } else if (hapd->conf->mesh & MESH_ENABLED) { + /* + * In mesh case, follow SAE finite state machine and + * send Commit now, if sync count allows. + */ + if (sae_check_big_sync(hapd, sta)) + return WLAN_STATUS_SUCCESS; + sta->sae->sync++; + + ret = auth_sae_send_commit(hapd, sta, bssid, 0); + if (ret) + return ret; + + sae_set_retransmit_timer(hapd, sta); + } else { + /* + * For instructure BSS, send the postponed Confirm from + * Nothing -> Confirmed transition that was reduced to + * Nothing -> Committed above. + */ + ret = auth_sae_send_confirm(hapd, sta, bssid); + if (ret) + return ret; + + sae_set_state(sta, SAE_CONFIRMED, "Sent Confirm"); + + /* + * Since this was triggered on Confirm RX, run another + * step to get to Accepted without waiting for + * additional events. + */ + return sae_sm_step(hapd, sta, bssid, auth_transaction, + 0, sta_removed); + } + break; + case SAE_CONFIRMED: + sae_clear_retransmit_timer(hapd, sta); + if (auth_transaction == 1) { + if (sae_check_big_sync(hapd, sta)) + return WLAN_STATUS_SUCCESS; + sta->sae->sync++; + + ret = auth_sae_send_commit(hapd, sta, bssid, 1); + if (ret) + return ret; + + if (sae_process_commit(sta->sae) < 0) + return WLAN_STATUS_UNSPECIFIED_FAILURE; + + ret = auth_sae_send_confirm(hapd, sta, bssid); + if (ret) + return ret; + + sae_set_retransmit_timer(hapd, sta); + } else { + sta->sae->send_confirm = 0xffff; + sae_accept_sta(hapd, sta); + } + break; + case SAE_ACCEPTED: + if (auth_transaction == 1 && + (hapd->conf->mesh & MESH_ENABLED)) { + wpa_printf(MSG_DEBUG, "SAE: remove the STA (" MACSTR + ") doing reauthentication", + MAC2STR(sta->addr)); + wpa_auth_pmksa_remove(hapd->wpa_auth, sta->addr); + ap_free_sta(hapd, sta); + *sta_removed = 1; + } else if (auth_transaction == 1) { + wpa_printf(MSG_DEBUG, "SAE: Start reauthentication"); + ret = auth_sae_send_commit(hapd, sta, bssid, 1); + if (ret) + return ret; + sae_set_state(sta, SAE_COMMITTED, "Sent Commit"); + + if (sae_process_commit(sta->sae) < 0) + return WLAN_STATUS_UNSPECIFIED_FAILURE; + sta->sae->sync = 0; + sae_set_retransmit_timer(hapd, sta); + } else { + if (sae_check_big_sync(hapd, sta)) + return WLAN_STATUS_SUCCESS; + sta->sae->sync++; + + ret = auth_sae_send_confirm(hapd, sta, bssid); + sae_clear_temp_data(sta->sae); + if (ret) + return ret; + } + break; + default: + wpa_printf(MSG_ERROR, "SAE: invalid state %d", + sta->sae->state); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + return WLAN_STATUS_SUCCESS; +} + + +static void sae_pick_next_group(struct hostapd_data *hapd, struct sta_info *sta) +{ + struct sae_data *sae = sta->sae; + int i, *groups = hapd->conf->sae_groups; + int default_groups[] = { 19, 0 }; + + if (sae->state != SAE_COMMITTED) + return; + + wpa_printf(MSG_DEBUG, "SAE: Previously selected group: %d", sae->group); + + if (!groups) + groups = default_groups; + for (i = 0; groups[i] > 0; i++) { + if (sae->group == groups[i]) + break; + } + + if (groups[i] <= 0) { + wpa_printf(MSG_DEBUG, + "SAE: Previously selected group not found from the current configuration"); + return; + } + + for (;;) { + i++; + if (groups[i] <= 0) { + wpa_printf(MSG_INFO, + "SAE: No alternative group enabled"); + return; + } + + if (sae_set_group(sae, groups[i]) < 0) + continue; + + break; + } + wpa_printf(MSG_INFO, "SAE: Selected new group: %d", groups[i]); +} + + +static void handle_auth_sae(struct hostapd_data *hapd, struct sta_info *sta, + const struct ieee80211_mgmt *mgmt, size_t len, + u16 auth_transaction, u16 status_code) +{ + int resp = WLAN_STATUS_SUCCESS; + struct wpabuf *data = NULL; + int *groups = hapd->conf->sae_groups; + int default_groups[] = { 19, 0 }; + const u8 *pos, *end; + int sta_removed = 0; + + if (!groups) + groups = default_groups; + if (!sta->sae) { + if (auth_transaction != 1 || + status_code != WLAN_STATUS_SUCCESS) { + resp = -1; + goto remove_sta; + } + sta->sae = os_zalloc(sizeof(*sta->sae)); + if (!sta->sae) { + resp = -1; + goto remove_sta; + } + sae_set_state(sta, SAE_NOTHING, "Init"); + sta->sae->sync = 0; + } + + if (sta->mesh_sae_pmksa_caching) { + wpa_printf(MSG_DEBUG, + "SAE: Cancel use of mesh PMKSA caching because peer starts SAE authentication"); + wpa_auth_pmksa_remove(hapd->wpa_auth, sta->addr); + sta->mesh_sae_pmksa_caching = 0; + } + + if (auth_transaction == 1) { + const u8 *token = NULL; + size_t token_len = 0; + int allow_reuse = 0; + + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "start SAE authentication (RX commit, status=%u (%s))", + status_code, status2str(status_code)); + + if ((hapd->conf->mesh & MESH_ENABLED) && + status_code == WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ && + sta->sae->tmp) { + pos = mgmt->u.auth.variable; + end = ((const u8 *) mgmt) + len; + if (pos + sizeof(le16) > end) { + wpa_printf(MSG_ERROR, + "SAE: Too short anti-clogging token request"); + resp = WLAN_STATUS_UNSPECIFIED_FAILURE; + goto reply; + } + resp = sae_group_allowed(sta->sae, groups, + WPA_GET_LE16(pos)); + if (resp != WLAN_STATUS_SUCCESS) { + wpa_printf(MSG_ERROR, + "SAE: Invalid group in anti-clogging token request"); + goto reply; + } + pos += sizeof(le16); + + wpabuf_free(sta->sae->tmp->anti_clogging_token); + sta->sae->tmp->anti_clogging_token = + wpabuf_alloc_copy(pos, end - pos); + if (sta->sae->tmp->anti_clogging_token == NULL) { + wpa_printf(MSG_ERROR, + "SAE: Failed to alloc for anti-clogging token"); + resp = WLAN_STATUS_UNSPECIFIED_FAILURE; + goto remove_sta; + } + + /* + * IEEE Std 802.11-2012, 11.3.8.6.4: If the Status code + * is 76, a new Commit Message shall be constructed + * with the Anti-Clogging Token from the received + * Authentication frame, and the commit-scalar and + * COMMIT-ELEMENT previously sent. + */ + resp = auth_sae_send_commit(hapd, sta, mgmt->bssid, 0); + if (resp != WLAN_STATUS_SUCCESS) { + wpa_printf(MSG_ERROR, + "SAE: Failed to send commit message"); + goto remove_sta; + } + sae_set_state(sta, SAE_COMMITTED, + "Sent Commit (anti-clogging token case in mesh)"); + sta->sae->sync = 0; + sae_set_retransmit_timer(hapd, sta); + return; + } + + if ((hapd->conf->mesh & MESH_ENABLED) && + status_code == + WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED && + sta->sae->tmp) { + wpa_printf(MSG_DEBUG, + "SAE: Peer did not accept our SAE group"); + sae_pick_next_group(hapd, sta); + goto remove_sta; + } + + if (status_code != WLAN_STATUS_SUCCESS) + goto remove_sta; + + if (!(hapd->conf->mesh & MESH_ENABLED) && + sta->sae->state == SAE_COMMITTED) { + /* This is needed in the infrastructure BSS case to + * address a sequence where a STA entry may remain in + * hostapd across two attempts to do SAE authentication + * by the same STA. The second attempt may end up trying + * to use a different group and that would not be + * allowed if we remain in Committed state with the + * previously set parameters. */ + pos = mgmt->u.auth.variable; + end = ((const u8 *) mgmt) + len; + if (end - pos >= (int) sizeof(le16) && + sae_group_allowed(sta->sae, groups, + WPA_GET_LE16(pos)) == + WLAN_STATUS_SUCCESS) { + /* Do not waste resources deriving the same PWE + * again since the same group is reused. */ + sae_set_state(sta, SAE_NOTHING, + "Allow previous PWE to be reused"); + allow_reuse = 1; + } else { + sae_set_state(sta, SAE_NOTHING, + "Clear existing state to allow restart"); + sae_clear_data(sta->sae); + } + } + + resp = sae_parse_commit(sta->sae, mgmt->u.auth.variable, + ((const u8 *) mgmt) + len - + mgmt->u.auth.variable, &token, + &token_len, groups); + if (resp == SAE_SILENTLY_DISCARD) { + wpa_printf(MSG_DEBUG, + "SAE: Drop commit message from " MACSTR " due to reflection attack", + MAC2STR(sta->addr)); + goto remove_sta; + } + + if (resp == WLAN_STATUS_UNKNOWN_PASSWORD_IDENTIFIER) { + wpa_msg(hapd->msg_ctx, MSG_INFO, + WPA_EVENT_SAE_UNKNOWN_PASSWORD_IDENTIFIER + MACSTR, MAC2STR(sta->addr)); + sae_clear_retransmit_timer(hapd, sta); + sae_set_state(sta, SAE_NOTHING, + "Unknown Password Identifier"); + goto remove_sta; + } + + if (token && check_sae_token(hapd, sta->addr, token, token_len) + < 0) { + wpa_printf(MSG_DEBUG, "SAE: Drop commit message with " + "incorrect token from " MACSTR, + MAC2STR(sta->addr)); + resp = WLAN_STATUS_UNSPECIFIED_FAILURE; + goto remove_sta; + } + + if (resp != WLAN_STATUS_SUCCESS) + goto reply; + + if (!token && use_sae_anti_clogging(hapd) && !allow_reuse) { + wpa_printf(MSG_DEBUG, + "SAE: Request anti-clogging token from " + MACSTR, MAC2STR(sta->addr)); + data = auth_build_token_req(hapd, sta->sae->group, + sta->addr); + resp = WLAN_STATUS_ANTI_CLOGGING_TOKEN_REQ; + if (hapd->conf->mesh & MESH_ENABLED) + sae_set_state(sta, SAE_NOTHING, + "Request anti-clogging token case in mesh"); + goto reply; + } + + resp = sae_sm_step(hapd, sta, mgmt->bssid, auth_transaction, + allow_reuse, &sta_removed); + } else if (auth_transaction == 2) { + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "SAE authentication (RX confirm, status=%u (%s))", + status_code, status2str(status_code)); + if (status_code != WLAN_STATUS_SUCCESS) + goto remove_sta; + if (sta->sae->state >= SAE_CONFIRMED || + !(hapd->conf->mesh & MESH_ENABLED)) { + const u8 *var; + size_t var_len; + u16 peer_send_confirm; + + var = mgmt->u.auth.variable; + var_len = ((u8 *) mgmt) + len - mgmt->u.auth.variable; + if (var_len < 2) { + resp = WLAN_STATUS_UNSPECIFIED_FAILURE; + goto reply; + } + + peer_send_confirm = WPA_GET_LE16(var); + + if (sta->sae->state == SAE_ACCEPTED && + (peer_send_confirm <= sta->sae->rc || + peer_send_confirm == 0xffff)) { + wpa_printf(MSG_DEBUG, + "SAE: Silently ignore unexpected Confirm from peer " + MACSTR + " (peer-send-confirm=%u Rc=%u)", + MAC2STR(sta->addr), + peer_send_confirm, sta->sae->rc); + return; + } + + if (sae_check_confirm(sta->sae, var, var_len) < 0) { + resp = WLAN_STATUS_UNSPECIFIED_FAILURE; + goto reply; + } + sta->sae->rc = peer_send_confirm; + } + resp = sae_sm_step(hapd, sta, mgmt->bssid, auth_transaction, 0, + &sta_removed); + } else { + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "unexpected SAE authentication transaction %u (status=%u (%s))", + auth_transaction, status_code, + status2str(status_code)); + if (status_code != WLAN_STATUS_SUCCESS) + goto remove_sta; + resp = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION; + } + +reply: + if (!sta_removed && resp != WLAN_STATUS_SUCCESS) { + pos = mgmt->u.auth.variable; + end = ((const u8 *) mgmt) + len; + + /* Copy the Finite Cyclic Group field from the request if we + * rejected it as unsupported group. */ + if (resp == WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED && + !data && end - pos >= 2) + data = wpabuf_alloc_copy(pos, 2); + + sae_sme_send_external_auth_status(hapd, sta, resp); + send_auth_reply(hapd, mgmt->sa, mgmt->bssid, WLAN_AUTH_SAE, + auth_transaction, resp, + data ? wpabuf_head(data) : (u8 *) "", + data ? wpabuf_len(data) : 0, "auth-sae"); + } + +remove_sta: + if (!sta_removed && sta->added_unassoc && + (resp != WLAN_STATUS_SUCCESS || + status_code != WLAN_STATUS_SUCCESS)) { + hostapd_drv_sta_remove(hapd, sta->addr); + sta->added_unassoc = 0; + } + wpabuf_free(data); +} + + +/** + * auth_sae_init_committed - Send COMMIT and start SAE in committed state + * @hapd: BSS data for the device initiating the authentication + * @sta: the peer to which commit authentication frame is sent + * + * This function implements Init event handling (IEEE Std 802.11-2012, + * 11.3.8.6.3) in which initial COMMIT message is sent. Prior to calling, the + * sta->sae structure should be initialized appropriately via a call to + * sae_prepare_commit(). + */ +int auth_sae_init_committed(struct hostapd_data *hapd, struct sta_info *sta) +{ + int ret; + + if (!sta->sae || !sta->sae->tmp) + return -1; + + if (sta->sae->state != SAE_NOTHING) + return -1; + + ret = auth_sae_send_commit(hapd, sta, hapd->own_addr, 0); + if (ret) + return -1; + + sae_set_state(sta, SAE_COMMITTED, "Init and sent commit"); + sta->sae->sync = 0; + sae_set_retransmit_timer(hapd, sta); + + return 0; +} + + +void auth_sae_process_commit(void *eloop_ctx, void *user_ctx) +{ + struct hostapd_data *hapd = eloop_ctx; + struct hostapd_sae_commit_queue *q; + unsigned int queue_len; + + q = dl_list_first(&hapd->sae_commit_queue, + struct hostapd_sae_commit_queue, list); + if (!q) + return; + wpa_printf(MSG_DEBUG, + "SAE: Process next available message from queue"); + dl_list_del(&q->list); + handle_auth(hapd, (const struct ieee80211_mgmt *) q->msg, q->len, + q->rssi, 1); + os_free(q); + + if (eloop_is_timeout_registered(auth_sae_process_commit, hapd, NULL)) + return; + queue_len = dl_list_len(&hapd->sae_commit_queue); + eloop_register_timeout(0, queue_len * 10000, auth_sae_process_commit, + hapd, NULL); +} + + +static void auth_sae_queue(struct hostapd_data *hapd, + const struct ieee80211_mgmt *mgmt, size_t len, + int rssi) +{ + struct hostapd_sae_commit_queue *q, *q2; + unsigned int queue_len; + const struct ieee80211_mgmt *mgmt2; + + queue_len = dl_list_len(&hapd->sae_commit_queue); + if (queue_len >= 15) { + wpa_printf(MSG_DEBUG, + "SAE: No more room in message queue - drop the new frame from " + MACSTR, MAC2STR(mgmt->sa)); + return; + } + + wpa_printf(MSG_DEBUG, "SAE: Queue Authentication message from " + MACSTR " for processing (queue_len %u)", MAC2STR(mgmt->sa), + queue_len); + q = os_zalloc(sizeof(*q) + len); + if (!q) + return; + q->rssi = rssi; + q->len = len; + os_memcpy(q->msg, mgmt, len); + + /* Check whether there is already a queued Authentication frame from the + * same station with the same transaction number and if so, replace that + * queue entry with the new one. This avoids issues with a peer that + * sends multiple times (e.g., due to frequent SAE retries). There is no + * point in us trying to process the old attempts after a new one has + * obsoleted them. */ + dl_list_for_each(q2, &hapd->sae_commit_queue, + struct hostapd_sae_commit_queue, list) { + mgmt2 = (const struct ieee80211_mgmt *) q2->msg; + if (os_memcmp(mgmt->sa, mgmt2->sa, ETH_ALEN) == 0 && + mgmt->u.auth.auth_transaction == + mgmt2->u.auth.auth_transaction) { + wpa_printf(MSG_DEBUG, + "SAE: Replace queued message from same STA with same transaction number"); + dl_list_add(&q2->list, &q->list); + dl_list_del(&q2->list); + os_free(q2); + goto queued; + } + } + + /* No pending identical entry, so add to the end of the queue */ + dl_list_add_tail(&hapd->sae_commit_queue, &q->list); + +queued: + if (eloop_is_timeout_registered(auth_sae_process_commit, hapd, NULL)) + return; + eloop_register_timeout(0, queue_len * 10000, auth_sae_process_commit, + hapd, NULL); +} + + +static int auth_sae_queued_addr(struct hostapd_data *hapd, const u8 *addr) +{ + struct hostapd_sae_commit_queue *q; + const struct ieee80211_mgmt *mgmt; + + dl_list_for_each(q, &hapd->sae_commit_queue, + struct hostapd_sae_commit_queue, list) { + mgmt = (const struct ieee80211_mgmt *) q->msg; + if (os_memcmp(addr, mgmt->sa, ETH_ALEN) == 0) + return 1; + } + + return 0; +} + +#endif /* CONFIG_SAE_AP */ + + +static u16 wpa_res_to_status_code(int res) +{ + if (res == WPA_INVALID_GROUP) + return WLAN_STATUS_GROUP_CIPHER_NOT_VALID; + if (res == WPA_INVALID_PAIRWISE) + return WLAN_STATUS_PAIRWISE_CIPHER_NOT_VALID; + if (res == WPA_INVALID_AKMP) + return WLAN_STATUS_AKMP_NOT_VALID; + if (res == WPA_ALLOC_FAIL) + return WLAN_STATUS_UNSPECIFIED_FAILURE; +#ifdef CONFIG_IEEE80211W_AP + if (res == WPA_MGMT_FRAME_PROTECTION_VIOLATION) + return WLAN_STATUS_ROBUST_MGMT_FRAME_POLICY_VIOLATION; + if (res == WPA_INVALID_MGMT_GROUP_CIPHER) + return WLAN_STATUS_CIPHER_REJECTED_PER_POLICY; +#endif /* CONFIG_IEEE80211W_AP */ + if (res == WPA_INVALID_MDIE) + return WLAN_STATUS_INVALID_MDIE; + if (res == WPA_INVALID_PMKID) + return WLAN_STATUS_INVALID_PMKID; + if (res != WPA_IE_OK) + return WLAN_STATUS_INVALID_IE; + return WLAN_STATUS_SUCCESS; +} + + +int +ieee802_11_allowed_address(struct hostapd_data *hapd, const u8 *addr, + const u8 *msg, size_t len, u32 *session_timeout, + u32 *acct_interim_interval, + struct vlan_description *vlan_id, + struct hostapd_sta_wpa_psk_short **psk, + char **identity, char **radius_cui, int is_probe_req) +{ + int res; + + os_memset(vlan_id, 0, sizeof(*vlan_id)); +#ifdef CONFIG_FULL_HOSTAPD + res = hostapd_allowed_address(hapd, addr, msg, len, + session_timeout, acct_interim_interval, + vlan_id, psk, identity, radius_cui, + is_probe_req); +#else + res = HOSTAPD_ACL_ACCEPT; +#endif + +#ifdef CONFIG_FULL_HOSTAPD + if (res == HOSTAPD_ACL_REJECT) { + if (!is_probe_req) + wpa_printf(MSG_DEBUG, + "Station " MACSTR + " not allowed to authenticate", + MAC2STR(addr)); + return HOSTAPD_ACL_REJECT; + } + + if (res == HOSTAPD_ACL_PENDING) { + wpa_printf(MSG_DEBUG, "Authentication frame from " MACSTR + " waiting for an external authentication", + MAC2STR(addr)); + /* Authentication code will re-send the authentication frame + * after it has received (and cached) information from the + * external source. */ + return HOSTAPD_ACL_PENDING; + } +#endif + + return res; +} + +static void handle_auth(struct hostapd_data *hapd, + const struct ieee80211_mgmt *mgmt, size_t len, + int rssi, int from_queue) +{ + u16 auth_alg, auth_transaction, status_code; + u16 resp = WLAN_STATUS_SUCCESS; + struct sta_info *sta = NULL; + int res, reply_res; + u16 fc; + const u8 *challenge = NULL; +#ifdef CONFIG_HOSTAPD_ACL + u32 session_timeout, acct_interim_interval; + struct vlan_description vlan_id; +#endif + struct hostapd_sta_wpa_psk_short *psk = NULL; + u8 resp_ies[2 + WLAN_AUTH_CHALLENGE_LEN]; + size_t resp_ies_len = 0; + char *identity = NULL; + char *radius_cui = NULL; + u16 seq_ctrl; + + if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) { + wpa_printf(MSG_INFO, "handle_auth - too short payload (len=%lu)", + (unsigned long) len); + return; + } + +#ifdef CONFIG_TESTING_OPTIONS + if (hapd->iconf->ignore_auth_probability > 0.0 && + drand48() < hapd->iconf->ignore_auth_probability) { + wpa_printf(MSG_INFO, + "TESTING: ignoring auth frame from " MACSTR, + MAC2STR(mgmt->sa)); + return; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + auth_alg = le_to_host16(mgmt->u.auth.auth_alg); + auth_transaction = le_to_host16(mgmt->u.auth.auth_transaction); + status_code = le_to_host16(mgmt->u.auth.status_code); + fc = le_to_host16(mgmt->frame_control); + seq_ctrl = le_to_host16(mgmt->seq_ctrl); + + if (len >= IEEE80211_HDRLEN + sizeof(mgmt->u.auth) + + 2 + WLAN_AUTH_CHALLENGE_LEN && + mgmt->u.auth.variable[0] == WLAN_EID_CHALLENGE && + mgmt->u.auth.variable[1] == WLAN_AUTH_CHALLENGE_LEN) + challenge = &mgmt->u.auth.variable[2]; + + wpa_printf(MSG_DEBUG, "authentication: STA=" MACSTR " auth_alg=%d " + "auth_transaction=%d status_code=%d wep=%d%s " + "seq_ctrl=0x%x%s%s", + MAC2STR(mgmt->sa), auth_alg, auth_transaction, + status_code, !!(fc & WLAN_FC_ISWEP), + challenge ? " challenge" : "", + seq_ctrl, (fc & WLAN_FC_RETRY) ? " retry" : "", + from_queue ? " (from queue)" : ""); + +#ifdef CONFIG_NO_RC4 + if (auth_alg == WLAN_AUTH_SHARED_KEY) { + wpa_printf(MSG_INFO, + "Unsupported authentication algorithm (%d)", + auth_alg); + resp = WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG; + goto fail; + } +#endif /* CONFIG_NO_RC4 */ + + if (hapd->tkip_countermeasures) { + wpa_printf(MSG_DEBUG, + "Ongoing TKIP countermeasures (Michael MIC failure) - reject authentication"); + resp = WLAN_STATUS_UNSPECIFIED_FAILURE; + goto fail; + } + + if (!(((hapd->conf->auth_algs & WPA_AUTH_ALG_OPEN) && + auth_alg == WLAN_AUTH_OPEN) || +#ifdef CONFIG_IEEE80211R_AP + (hapd->conf->wpa && wpa_key_mgmt_ft(hapd->conf->wpa_key_mgmt) && + auth_alg == WLAN_AUTH_FT) || +#endif /* CONFIG_IEEE80211R_AP */ +#ifdef CONFIG_SAE_AP + (hapd->conf->wpa && wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) && + auth_alg == WLAN_AUTH_SAE) || +#endif /* CONFIG_SAE_AP */ + ((hapd->conf->auth_algs & WPA_AUTH_ALG_SHARED) && + auth_alg == WLAN_AUTH_SHARED_KEY))) { + wpa_printf(MSG_INFO, "Unsupported authentication algorithm (%d)", + auth_alg); + resp = WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG; + goto fail; + } + + if (!(auth_transaction == 1 || auth_alg == WLAN_AUTH_SAE || + (auth_alg == WLAN_AUTH_SHARED_KEY && auth_transaction == 3))) { + wpa_printf(MSG_INFO, "Unknown authentication transaction number (%d)", + auth_transaction); + resp = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION; + goto fail; + } + + if (os_memcmp(mgmt->sa, hapd->own_addr, ETH_ALEN) == 0) { + wpa_printf(MSG_INFO, "Station " MACSTR " not allowed to authenticate", + MAC2STR(mgmt->sa)); + resp = WLAN_STATUS_UNSPECIFIED_FAILURE; + goto fail; + } + + if (hapd->conf->no_auth_if_seen_on) { + struct hostapd_data *other; + + other = sta_track_seen_on(hapd->iface, mgmt->sa, + hapd->conf->no_auth_if_seen_on); + if (other) { + u8 *pos; + u32 info; + u8 op_class, channel, phytype; + + wpa_printf(MSG_DEBUG, "%s: Reject authentication from " + MACSTR " since STA has been seen on %s", + hapd->conf->iface, MAC2STR(mgmt->sa), + hapd->conf->no_auth_if_seen_on); + + resp = WLAN_STATUS_REJECTED_WITH_SUGGESTED_BSS_TRANSITION; + pos = &resp_ies[0]; + *pos++ = WLAN_EID_NEIGHBOR_REPORT; + *pos++ = 13; + os_memcpy(pos, other->own_addr, ETH_ALEN); + pos += ETH_ALEN; + info = 0; /* TODO: BSSID Information */ + WPA_PUT_LE32(pos, info); + pos += 4; + if (0) {} +#ifdef CONFIG_FULL_HOSTAPD + else if (other->iconf->hw_mode == HOSTAPD_MODE_IEEE80211AD) + phytype = 8; /* dmg */ + else if (other->iconf->ieee80211ac) + phytype = 9; /* vht */ +#endif + else if (other->iconf->ieee80211n) + phytype = 7; /* ht */ +#ifdef CONFIG_FULL_HOSTAPD + else if (other->iconf->hw_mode == + HOSTAPD_MODE_IEEE80211A) + phytype = 4; /* ofdm */ +#endif + else if (other->iconf->hw_mode == + HOSTAPD_MODE_IEEE80211G) + phytype = 6; /* erp */ + else + phytype = 5; /* hrdsss */ + if (ieee80211_freq_to_channel_ext( + hostapd_hw_get_freq(other, + other->iconf->channel), + other->iconf->secondary_channel, + other->iconf->ieee80211ac, + &op_class, &channel) == NUM_HOSTAPD_MODES) { + op_class = 0; + channel = other->iconf->channel; + } + *pos++ = op_class; + *pos++ = channel; + *pos++ = phytype; + resp_ies_len = pos - &resp_ies[0]; + goto fail; + } + } + +#ifdef CONFIG_HOSTAPD_ACL + res = ieee802_11_allowed_address( + hapd, mgmt->sa, (const u8 *) mgmt, len, &session_timeout, + &acct_interim_interval, &vlan_id, &psk, &identity, &radius_cui, + 0); + if (res == HOSTAPD_ACL_REJECT) { + wpa_msg(hapd->msg_ctx, MSG_DEBUG, + "Ignore Authentication frame from " MACSTR + " due to ACL reject", MAC2STR(mgmt->sa)); + resp = WLAN_STATUS_UNSPECIFIED_FAILURE; + goto fail; + } + if (res == HOSTAPD_ACL_PENDING) + return; +#else /* CONFIG_HOSTAPD_ACL */ + res = HOSTAPD_ACL_ACCEPT; +#endif + +#ifdef CONFIG_SAE_AP + if (auth_alg == WLAN_AUTH_SAE && !from_queue && + (auth_transaction == 1 || + (auth_transaction == 2 && auth_sae_queued_addr(hapd, mgmt->sa)))) { + /* Handle SAE Authentication commit message through a queue to + * provide more control for postponing the needed heavy + * processing under a possible DoS attack scenario. In addition, + * queue SAE Authentication confirm message if there happens to + * be a queued commit message from the same peer. This is needed + * to avoid reordering Authentication frames within the same + * SAE exchange. */ + auth_sae_queue(hapd, mgmt, len, rssi); + return; + } +#endif /* CONFIG_SAE_AP */ + + sta = ap_get_sta(hapd, mgmt->sa); + if (sta) { + sta->flags &= ~WLAN_STA_PENDING_FILS_ERP; + sta->ft_over_ds = 0; + if ((fc & WLAN_FC_RETRY) && + sta->last_seq_ctrl != WLAN_INVALID_MGMT_SEQ && + sta->last_seq_ctrl == seq_ctrl && + sta->last_subtype == WLAN_FC_STYPE_AUTH) { + hostapd_logger(hapd, sta->addr, + HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "Drop repeated authentication frame seq_ctrl=0x%x", + seq_ctrl); + return; + } +#ifdef CONFIG_MESH + if ((hapd->conf->mesh & MESH_ENABLED) && + sta->plink_state == PLINK_BLOCKED) { + wpa_printf(MSG_DEBUG, "Mesh peer " MACSTR + " is blocked - drop Authentication frame", + MAC2STR(mgmt->sa)); + return; + } +#endif /* CONFIG_MESH */ + } else { +#ifdef CONFIG_MESH + if (hapd->conf->mesh & MESH_ENABLED) { + /* if the mesh peer is not available, we don't do auth. + */ + wpa_printf(MSG_DEBUG, "Mesh peer " MACSTR + " not yet known - drop Authentication frame", + MAC2STR(mgmt->sa)); + /* + * Save a copy of the frame so that it can be processed + * if a new peer entry is added shortly after this. + */ + wpabuf_free(hapd->mesh_pending_auth); + hapd->mesh_pending_auth = wpabuf_alloc_copy(mgmt, len); + os_get_reltime(&hapd->mesh_pending_auth_time); + return; + } +#endif /* CONFIG_MESH */ + + sta = ap_sta_add(hapd, mgmt->sa); + if (!sta) { + wpa_printf(MSG_DEBUG, "ap_sta_add() failed"); + resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; + goto fail; + } + } + sta->last_seq_ctrl = seq_ctrl; + sta->last_subtype = WLAN_FC_STYPE_AUTH; +#ifdef CONFIG_MBO + sta->auth_rssi = rssi; +#endif /* CONFIG_MBO */ + +#ifdef CONFIG_FULL_HOSTAPD + res = ieee802_11_set_radius_info( + hapd, sta, res, session_timeout, acct_interim_interval, + &vlan_id, &psk, &identity, &radius_cui); + if (res) { + wpa_printf(MSG_DEBUG, "ieee802_11_set_radius_info() failed"); + resp = WLAN_STATUS_UNSPECIFIED_FAILURE; + goto fail; + } +#endif + + sta->flags &= ~WLAN_STA_PREAUTH; +#ifdef IEEE8021X_EAPOL + ieee802_1x_notify_pre_auth(sta->eapol_sm, 0); +#endif + +#ifdef CONFIG_FULL_HOSTAPD + /* + * If the driver supports full AP client state, add a station to the + * driver before sending authentication reply to make sure the driver + * has resources, and not to go through the entire authentication and + * association handshake, and fail it at the end. + * + * If this is not the first transaction, in a multi-step authentication + * algorithm, the station already exists in the driver + * (sta->added_unassoc = 1) so skip it. + * + * In mesh mode, the station was already added to the driver when the + * NEW_PEER_CANDIDATE event is received. + * + * If PMF was negotiated for the existing association, skip this to + * avoid dropping the STA entry and the associated keys. This is needed + * to allow the original connection work until the attempt can complete + * (re)association, so that unprotected Authentication frame cannot be + * used to bypass PMF protection. + */ + if (FULL_AP_CLIENT_STATE_SUPP(hapd->iface->drv_flags) && + (!(sta->flags & WLAN_STA_MFP) || !ap_sta_is_authorized(sta)) && + !(hapd->conf->mesh & MESH_ENABLED) && + !(sta->added_unassoc)) { + /* + * If a station that is already associated to the AP, is trying + * to authenticate again, remove the STA entry, in order to make + * sure the STA PS state gets cleared and configuration gets + * updated. To handle this, station's added_unassoc flag is + * cleared once the station has completed association. + */ + ap_sta_set_authorized(hapd, sta, 0); + hostapd_drv_sta_remove(hapd, sta->addr); + sta->flags &= ~(WLAN_STA_ASSOC | WLAN_STA_AUTH | + WLAN_STA_AUTHORIZED); + + if (hostapd_sta_add(hapd, sta->addr, 0, 0, + sta->supported_rates, + sta->supported_rates_len, + 0, NULL, NULL, NULL, 0, + sta->flags, 0, 0, 0, 0)) { + hostapd_logger(hapd, sta->addr, + HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_NOTICE, + "Could not add STA to kernel driver"); + resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; + goto fail; + } + + sta->added_unassoc = 1; + } +#endif + + switch (auth_alg) { + case WLAN_AUTH_OPEN: + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "authentication OK (open system)"); + sta->flags |= WLAN_STA_AUTH; + wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH); + sta->auth_alg = WLAN_AUTH_OPEN; + mlme_authenticate_indication(hapd, sta); + break; +#ifndef CONFIG_NO_RC4 + case WLAN_AUTH_SHARED_KEY: + resp = auth_shared_key(hapd, sta, auth_transaction, challenge, + fc & WLAN_FC_ISWEP); + if (resp != 0) + wpa_printf(MSG_DEBUG, + "auth_shared_key() failed: status=%d", resp); + sta->auth_alg = WLAN_AUTH_SHARED_KEY; + mlme_authenticate_indication(hapd, sta); + if (sta->challenge && auth_transaction == 1) { + resp_ies[0] = WLAN_EID_CHALLENGE; + resp_ies[1] = WLAN_AUTH_CHALLENGE_LEN; + os_memcpy(resp_ies + 2, sta->challenge, + WLAN_AUTH_CHALLENGE_LEN); + resp_ies_len = 2 + WLAN_AUTH_CHALLENGE_LEN; + } + break; +#endif /* CONFIG_NO_RC4 */ +#ifdef CONFIG_IEEE80211R_AP + case WLAN_AUTH_FT: + sta->auth_alg = WLAN_AUTH_FT; + if (sta->wpa_sm == NULL) + sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, + sta->addr, NULL); + if (sta->wpa_sm == NULL) { + wpa_printf(MSG_DEBUG, "FT: Failed to initialize WPA " + "state machine"); + resp = WLAN_STATUS_UNSPECIFIED_FAILURE; + goto fail; + } + wpa_ft_process_auth(sta->wpa_sm, mgmt->bssid, + auth_transaction, mgmt->u.auth.variable, + len - IEEE80211_HDRLEN - + sizeof(mgmt->u.auth), + handle_auth_ft_finish, hapd); + /* handle_auth_ft_finish() callback will complete auth. */ + return; +#endif /* CONFIG_IEEE80211R_AP */ +#ifdef CONFIG_SAE_AP + case WLAN_AUTH_SAE: +#ifdef CONFIG_MESH + if (status_code == WLAN_STATUS_SUCCESS && + hapd->conf->mesh & MESH_ENABLED) { + if (sta->wpa_sm == NULL) + sta->wpa_sm = + wpa_auth_sta_init(hapd->wpa_auth, + sta->addr, NULL); + if (sta->wpa_sm == NULL) { + wpa_printf(MSG_DEBUG, + "SAE: Failed to initialize WPA state machine"); + resp = WLAN_STATUS_UNSPECIFIED_FAILURE; + goto fail; + } + } +#endif /* CONFIG_MESH */ + handle_auth_sae(hapd, sta, mgmt, len, auth_transaction, + status_code); + return; +#endif /* CONFIG_SAE_AP */ + } + + fail: + os_free(identity); + os_free(radius_cui); + hostapd_free_psk_list(psk); + + reply_res = send_auth_reply(hapd, mgmt->sa, mgmt->bssid, auth_alg, + auth_transaction + 1, resp, resp_ies, + resp_ies_len, "handle-auth"); + + if (sta && sta->added_unassoc && (resp != WLAN_STATUS_SUCCESS || + reply_res != WLAN_STATUS_SUCCESS)) { + hostapd_drv_sta_remove(hapd, sta->addr); + sta->added_unassoc = 0; + } +} + + +int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta) +{ + int i, j = 32, aid; + + /* get a unique AID */ + if (sta->aid > 0) { + wpa_printf(MSG_DEBUG, " old AID %d", sta->aid); + return 0; + } + + for (i = 0; i < AID_WORDS; i++) { + if (hapd->sta_aid[i] == (u32) -1) + continue; + for (j = 0; j < 32; j++) { + if (!(hapd->sta_aid[i] & BIT(j))) + break; + } + if (j < 32) + break; + } + if (j == 32) + return -1; + aid = i * 32 + j + 1; + if (aid > 2007) + return -1; + + sta->aid = aid; + hapd->sta_aid[i] |= BIT(j); + wpa_printf(MSG_DEBUG, " new AID %d", sta->aid); + return 0; +} + + +static u16 check_ssid(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *ssid_ie, size_t ssid_ie_len) +{ + if (ssid_ie == NULL) + return WLAN_STATUS_UNSPECIFIED_FAILURE; + + if (ssid_ie_len != hapd->conf->ssid.ssid_len || + os_memcmp(ssid_ie, hapd->conf->ssid.ssid, ssid_ie_len) != 0) { + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, + "Station tried to associate with unknown SSID " + "'%s'", wpa_ssid_txt(ssid_ie, ssid_ie_len)); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + + return WLAN_STATUS_SUCCESS; +} + + +static u16 check_wmm(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *wmm_ie, size_t wmm_ie_len) +{ + sta->flags &= ~WLAN_STA_WMM; + sta->qosinfo = 0; + if (wmm_ie && hapd->conf->wmm_enabled) { + struct wmm_information_element *wmm; + + if (!hostapd_eid_wmm_valid(hapd, wmm_ie, wmm_ie_len)) { + hostapd_logger(hapd, sta->addr, + HOSTAPD_MODULE_WPA, + HOSTAPD_LEVEL_DEBUG, + "invalid WMM element in association " + "request"); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + + sta->flags |= WLAN_STA_WMM; + wmm = (struct wmm_information_element *) wmm_ie; + sta->qosinfo = wmm->qos_info; + } + return WLAN_STATUS_SUCCESS; +} + +#ifdef CONFIG_FULL_HOSTAPD +static u16 check_multi_ap(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *multi_ap_ie, size_t multi_ap_len) +{ + u8 multi_ap_value = 0; + + sta->flags &= ~WLAN_STA_MULTI_AP; + + if (!hapd->conf->multi_ap) + return WLAN_STATUS_SUCCESS; + + if (multi_ap_ie) { + const u8 *multi_ap_subelem; + + multi_ap_subelem = get_ie(multi_ap_ie + 4, + multi_ap_len - 4, + MULTI_AP_SUB_ELEM_TYPE); + if (multi_ap_subelem && multi_ap_subelem[1] == 1) { + multi_ap_value = multi_ap_subelem[2]; + } else { + hostapd_logger(hapd, sta->addr, + HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, + "Multi-AP IE has missing or invalid Multi-AP subelement"); + return WLAN_STATUS_INVALID_IE; + } + } + + if (multi_ap_value && multi_ap_value != MULTI_AP_BACKHAUL_STA) + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, + "Multi-AP IE with unexpected value 0x%02x", + multi_ap_value); + + if (!(multi_ap_value & MULTI_AP_BACKHAUL_STA)) { + if (hapd->conf->multi_ap & FRONTHAUL_BSS) + return WLAN_STATUS_SUCCESS; + + hostapd_logger(hapd, sta->addr, + HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, + "Non-Multi-AP STA tries to associate with backhaul-only BSS"); + return WLAN_STATUS_ASSOC_DENIED_UNSPEC; + } + + if (!(hapd->conf->multi_ap & BACKHAUL_BSS)) + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "Backhaul STA tries to associate with fronthaul-only BSS"); + + sta->flags |= WLAN_STA_MULTI_AP; + return WLAN_STATUS_SUCCESS; +} +#endif + +static u16 copy_supp_rates(struct hostapd_data *hapd, struct sta_info *sta, + struct ieee802_11_elems *elems) +{ +#ifdef CONFIG_FULL_HOSTAPD + /* Supported rates not used in IEEE 802.11ad/DMG */ + if (hapd->iface->current_mode && + hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211AD) + return WLAN_STATUS_SUCCESS; +#endif + + if (!elems->supp_rates) { + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "No supported rates element in AssocReq"); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + + if (elems->supp_rates_len + elems->ext_supp_rates_len > + sizeof(sta->supported_rates)) { + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "Invalid supported rates element length %d+%d", + elems->supp_rates_len, + elems->ext_supp_rates_len); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + + sta->supported_rates_len = merge_byte_arrays( + sta->supported_rates, sizeof(sta->supported_rates), + elems->supp_rates, elems->supp_rates_len, + elems->ext_supp_rates, elems->ext_supp_rates_len); + + return WLAN_STATUS_SUCCESS; +} + + +static u16 check_ext_capab(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *ext_capab_ie, size_t ext_capab_ie_len) +{ +#ifdef CONFIG_INTERWORKING + /* check for QoS Map support */ + if (ext_capab_ie_len >= 5) { + if (ext_capab_ie[4] & 0x01) + sta->qos_map_enabled = 1; + } +#endif /* CONFIG_INTERWORKING */ + + if (ext_capab_ie_len > 0) { + sta->ecsa_supported = !!(ext_capab_ie[0] & BIT(2)); + os_free(sta->ext_capability); + sta->ext_capability = os_malloc(1 + ext_capab_ie_len); + if (sta->ext_capability) { + sta->ext_capability[0] = ext_capab_ie_len; + os_memcpy(sta->ext_capability + 1, ext_capab_ie, + ext_capab_ie_len); + } + } + + return WLAN_STATUS_SUCCESS; +} + + +#ifdef CONFIG_OWE + +static int owe_group_supported(struct hostapd_data *hapd, u16 group) +{ + int i; + int *groups = hapd->conf->owe_groups; + + if (group != 19 && group != 20 && group != 21) + return 0; + + if (!groups) + return 1; + + for (i = 0; groups[i] > 0; i++) { + if (groups[i] == group) + return 1; + } + + return 0; +} + + +static u16 owe_process_assoc_req(struct hostapd_data *hapd, + struct sta_info *sta, const u8 *owe_dh, + u8 owe_dh_len) +{ + struct wpabuf *secret, *pub, *hkey; + int res; + u8 prk[SHA512_MAC_LEN], pmkid[SHA512_MAC_LEN]; + const char *info = "OWE Key Generation"; + const u8 *addr[2]; + size_t len[2]; + u16 group; + size_t hash_len, prime_len; + + if (wpa_auth_sta_get_pmksa(sta->wpa_sm)) { + wpa_printf(MSG_DEBUG, "OWE: Using PMKSA caching"); + return WLAN_STATUS_SUCCESS; + } + + group = WPA_GET_LE16(owe_dh); + if (!owe_group_supported(hapd, group)) { + wpa_printf(MSG_DEBUG, "OWE: Unsupported DH group %u", group); + return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED; + } + if (group == 19) + prime_len = 32; + else if (group == 20) + prime_len = 48; + else if (group == 21) + prime_len = 66; + else + return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED; + + crypto_ecdh_deinit(sta->owe_ecdh); + sta->owe_ecdh = crypto_ecdh_init(group); + if (!sta->owe_ecdh) + return WLAN_STATUS_FINITE_CYCLIC_GROUP_NOT_SUPPORTED; + sta->owe_group = group; + + secret = crypto_ecdh_set_peerkey(sta->owe_ecdh, 0, owe_dh + 2, + owe_dh_len - 2); + secret = wpabuf_zeropad(secret, prime_len); + if (!secret) { + wpa_printf(MSG_DEBUG, "OWE: Invalid peer DH public key"); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + wpa_hexdump_buf_key(MSG_DEBUG, "OWE: DH shared secret", secret); + + /* prk = HKDF-extract(C | A | group, z) */ + + pub = crypto_ecdh_get_pubkey(sta->owe_ecdh, 0); + if (!pub) { + wpabuf_clear_free(secret); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + + /* PMKID = Truncate-128(Hash(C | A)) */ + addr[0] = owe_dh + 2; + len[0] = owe_dh_len - 2; + addr[1] = wpabuf_head(pub); + len[1] = wpabuf_len(pub); + if (group == 19) { + res = sha256_vector(2, addr, len, pmkid); + hash_len = SHA256_MAC_LEN; + } else if (group == 20) { + res = sha384_vector(2, addr, len, pmkid); + hash_len = SHA384_MAC_LEN; + } else if (group == 21) { + res = sha512_vector(2, addr, len, pmkid); + hash_len = SHA512_MAC_LEN; + } else { + wpabuf_free(pub); + wpabuf_clear_free(secret); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + pub = wpabuf_zeropad(pub, prime_len); + if (res < 0 || !pub) { + wpabuf_free(pub); + wpabuf_clear_free(secret); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + + hkey = wpabuf_alloc(owe_dh_len - 2 + wpabuf_len(pub) + 2); + if (!hkey) { + wpabuf_free(pub); + wpabuf_clear_free(secret); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + + wpabuf_put_data(hkey, owe_dh + 2, owe_dh_len - 2); /* C */ + wpabuf_put_buf(hkey, pub); /* A */ + wpabuf_free(pub); + wpabuf_put_le16(hkey, group); /* group */ + if (group == 19) + res = hmac_sha256(wpabuf_head(hkey), wpabuf_len(hkey), + wpabuf_head(secret), wpabuf_len(secret), prk); + else if (group == 20) + res = hmac_sha384(wpabuf_head(hkey), wpabuf_len(hkey), + wpabuf_head(secret), wpabuf_len(secret), prk); + else if (group == 21) + res = hmac_sha512(wpabuf_head(hkey), wpabuf_len(hkey), + wpabuf_head(secret), wpabuf_len(secret), prk); + wpabuf_clear_free(hkey); + wpabuf_clear_free(secret); + if (res < 0) + return WLAN_STATUS_UNSPECIFIED_FAILURE; + + wpa_hexdump_key(MSG_DEBUG, "OWE: prk", prk, hash_len); + + /* PMK = HKDF-expand(prk, "OWE Key Generation", n) */ + + os_free(sta->owe_pmk); + sta->owe_pmk = os_malloc(hash_len); + if (!sta->owe_pmk) { + os_memset(prk, 0, SHA512_MAC_LEN); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + + if (group == 19) + res = hmac_sha256_kdf(prk, hash_len, NULL, (const u8 *) info, + os_strlen(info), sta->owe_pmk, hash_len); + else if (group == 20) + res = hmac_sha384_kdf(prk, hash_len, NULL, (const u8 *) info, + os_strlen(info), sta->owe_pmk, hash_len); + else if (group == 21) + res = hmac_sha512_kdf(prk, hash_len, NULL, (const u8 *) info, + os_strlen(info), sta->owe_pmk, hash_len); + os_memset(prk, 0, SHA512_MAC_LEN); + if (res < 0) { + os_free(sta->owe_pmk); + sta->owe_pmk = NULL; + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + sta->owe_pmk_len = hash_len; + + wpa_hexdump_key(MSG_DEBUG, "OWE: PMK", sta->owe_pmk, sta->owe_pmk_len); + wpa_hexdump(MSG_DEBUG, "OWE: PMKID", pmkid, PMKID_LEN); + wpa_auth_pmksa_add2(hapd->wpa_auth, sta->addr, sta->owe_pmk, + sta->owe_pmk_len, pmkid, 0, WPA_KEY_MGMT_OWE); + + return WLAN_STATUS_SUCCESS; +} + + +u16 owe_validate_request(struct hostapd_data *hapd, const u8 *peer, + const u8 *rsn_ie, size_t rsn_ie_len, + const u8 *owe_dh, size_t owe_dh_len) +{ + struct wpa_ie_data data; + int res; + + if (!rsn_ie || rsn_ie_len < 2) { + wpa_printf(MSG_DEBUG, "OWE: Invalid RSNE from " MACSTR, + MAC2STR(peer)); + return WLAN_STATUS_INVALID_IE; + } + rsn_ie -= 2; + rsn_ie_len += 2; + + res = wpa_parse_wpa_ie_rsn(rsn_ie, rsn_ie_len, &data); + if (res) { + wpa_printf(MSG_DEBUG, "Failed to parse RSNE from " MACSTR + " (res=%d)", MAC2STR(peer), res); + wpa_hexdump(MSG_DEBUG, "RSNE", rsn_ie, rsn_ie_len); + return wpa_res_to_status_code(res); + } + if (!(data.key_mgmt & WPA_KEY_MGMT_OWE)) { + wpa_printf(MSG_DEBUG, + "OWE: Unexpected key mgmt 0x%x from " MACSTR, + (unsigned int) data.key_mgmt, MAC2STR(peer)); + return WLAN_STATUS_AKMP_NOT_VALID; + } + if (!owe_dh) { + wpa_printf(MSG_DEBUG, + "OWE: No Diffie-Hellman Parameter element from " + MACSTR, MAC2STR(peer)); + return WLAN_STATUS_AKMP_NOT_VALID; + } + + return WLAN_STATUS_SUCCESS; +} + + +u16 owe_process_rsn_ie(struct hostapd_data *hapd, + struct sta_info *sta, + const u8 *rsn_ie, size_t rsn_ie_len, + const u8 *owe_dh, size_t owe_dh_len) +{ + u16 status; + u8 *owe_buf, ie[256 * 2]; + size_t ie_len = 0; + int res; + + if (!rsn_ie || rsn_ie_len < 2) { + wpa_printf(MSG_DEBUG, "OWE: No RSNE in (Re)AssocReq"); + status = WLAN_STATUS_INVALID_IE; + goto end; + } + + if (!sta->wpa_sm) + sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, sta->addr, + NULL); + if (!sta->wpa_sm) { + wpa_printf(MSG_WARNING, + "OWE: Failed to initialize WPA state machine"); + status = WLAN_STATUS_UNSPECIFIED_FAILURE; + goto end; + } + rsn_ie -= 2; + rsn_ie_len += 2; + res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm, + hapd->iface->freq, rsn_ie, rsn_ie_len, + NULL, 0, owe_dh, owe_dh_len); + status = wpa_res_to_status_code(res); + if (status != WLAN_STATUS_SUCCESS) + goto end; + status = owe_process_assoc_req(hapd, sta, owe_dh, owe_dh_len); + if (status != WLAN_STATUS_SUCCESS) + goto end; + owe_buf = wpa_auth_write_assoc_resp_owe(sta->wpa_sm, ie, sizeof(ie), + NULL, 0); + if (!owe_buf) { + status = WLAN_STATUS_UNSPECIFIED_FAILURE; + goto end; + } + + if (sta->owe_ecdh) { + struct wpabuf *pub; + + pub = crypto_ecdh_get_pubkey(sta->owe_ecdh, 0); + if (!pub) { + status = WLAN_STATUS_UNSPECIFIED_FAILURE; + goto end; + } + + /* OWE Diffie-Hellman Parameter element */ + *owe_buf++ = WLAN_EID_EXTENSION; /* Element ID */ + *owe_buf++ = 1 + 2 + wpabuf_len(pub); /* Length */ + *owe_buf++ = WLAN_EID_EXT_OWE_DH_PARAM; /* Element ID Extension + */ + WPA_PUT_LE16(owe_buf, sta->owe_group); + owe_buf += 2; + os_memcpy(owe_buf, wpabuf_head(pub), wpabuf_len(pub)); + owe_buf += wpabuf_len(pub); + wpabuf_free(pub); + sta->external_dh_updated = 1; + } + ie_len = owe_buf - ie; + +end: + wpa_printf(MSG_DEBUG, "OWE: Update status %d, ie len %d for peer " + MACSTR, status, (unsigned int) ie_len, + MAC2STR(sta->addr)); + hostapd_drv_update_dh_ie(hapd, sta->addr, status, + status == WLAN_STATUS_SUCCESS ? ie : NULL, + ie_len); + + return status; +} + +#endif /* CONFIG_OWE */ + + +static u16 check_assoc_ies(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *ies, size_t ies_len, int reassoc) +{ + struct ieee802_11_elems elems; + u16 resp; + const u8 *wpa_ie; + size_t wpa_ie_len; + const u8 *p2p_dev_addr = NULL; + + if (ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed) { + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, "Station sent an invalid " + "association request"); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + + resp = check_ssid(hapd, sta, elems.ssid, elems.ssid_len); + if (resp != WLAN_STATUS_SUCCESS) + return resp; + resp = check_wmm(hapd, sta, elems.wmm, elems.wmm_len); + if (resp != WLAN_STATUS_SUCCESS) + return resp; + resp = check_ext_capab(hapd, sta, elems.ext_capab, elems.ext_capab_len); + if (resp != WLAN_STATUS_SUCCESS) + return resp; + resp = copy_supp_rates(hapd, sta, &elems); + if (resp != WLAN_STATUS_SUCCESS) + return resp; + +#ifdef CONFIG_FULL_HOSTAPD + resp = check_multi_ap(hapd, sta, elems.multi_ap, elems.multi_ap_len); + if (resp != WLAN_STATUS_SUCCESS) + return resp; +#endif + +#ifdef CONFIG_IEEE80211N + resp = copy_sta_ht_capab(hapd, sta, elems.ht_capabilities); + if (resp != WLAN_STATUS_SUCCESS) + return resp; + if (hapd->iconf->ieee80211n && hapd->iconf->require_ht && + !(sta->flags & WLAN_STA_HT)) { + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, "Station does not support " + "mandatory HT PHY - reject association"); + return WLAN_STATUS_ASSOC_DENIED_NO_HT; + } +#endif /* CONFIG_IEEE80211N */ + +#ifdef CONFIG_IEEE80211AC + if (hapd->iconf->ieee80211ac) { + resp = copy_sta_vht_capab(hapd, sta, elems.vht_capabilities); + if (resp != WLAN_STATUS_SUCCESS) + return resp; + + resp = set_sta_vht_opmode(hapd, sta, elems.vht_opmode_notif); + if (resp != WLAN_STATUS_SUCCESS) + return resp; + } + + if (hapd->iconf->ieee80211ac && hapd->iconf->require_vht && + !(sta->flags & WLAN_STA_VHT)) { + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, "Station does not support " + "mandatory VHT PHY - reject association"); + return WLAN_STATUS_ASSOC_DENIED_NO_VHT; + } + + if (hapd->conf->vendor_vht && !elems.vht_capabilities) { + resp = copy_sta_vendor_vht(hapd, sta, elems.vendor_vht, + elems.vendor_vht_len); + if (resp != WLAN_STATUS_SUCCESS) + return resp; + } +#endif /* CONFIG_IEEE80211AC */ +#ifdef CONFIG_IEEE80211AX + if (hapd->iconf->ieee80211ax) { + resp = copy_sta_he_capab(hapd, sta, IEEE80211_MODE_AP, + elems.he_capabilities, + elems.he_capabilities_len); + if (resp != WLAN_STATUS_SUCCESS) + return resp; + } +#endif /* CONFIG_IEEE80211AX */ + +#ifdef CONFIG_P2P + if (elems.p2p) { + wpabuf_free(sta->p2p_ie); + sta->p2p_ie = ieee802_11_vendor_ie_concat(ies, ies_len, + P2P_IE_VENDOR_TYPE); + if (sta->p2p_ie) + p2p_dev_addr = p2p_get_go_dev_addr(sta->p2p_ie); + } else { + wpabuf_free(sta->p2p_ie); + sta->p2p_ie = NULL; + } +#endif /* CONFIG_P2P */ + + if ((hapd->conf->wpa & WPA_PROTO_RSN) && elems.rsn_ie) { + wpa_ie = elems.rsn_ie; + wpa_ie_len = elems.rsn_ie_len; + } else if ((hapd->conf->wpa & WPA_PROTO_WPA) && + elems.wpa_ie) { + wpa_ie = elems.wpa_ie; + wpa_ie_len = elems.wpa_ie_len; + } else { + wpa_ie = NULL; + wpa_ie_len = 0; + } + +#ifdef CONFIG_WPS + sta->flags &= ~(WLAN_STA_WPS | WLAN_STA_MAYBE_WPS | WLAN_STA_WPS2); + if (hapd->conf->wps_state && elems.wps_ie) { + wpa_printf(MSG_DEBUG, "STA included WPS IE in (Re)Association " + "Request - assume WPS is used"); + sta->flags |= WLAN_STA_WPS; + wpabuf_free(sta->wps_ie); + sta->wps_ie = ieee802_11_vendor_ie_concat(ies, ies_len, + WPS_IE_VENDOR_TYPE); + if (sta->wps_ie && wps_is_20(sta->wps_ie)) { + wpa_printf(MSG_DEBUG, "WPS: STA supports WPS 2.0"); + sta->flags |= WLAN_STA_WPS2; + } + wpa_ie = NULL; + wpa_ie_len = 0; + if (sta->wps_ie && wps_validate_assoc_req(sta->wps_ie) < 0) { + wpa_printf(MSG_DEBUG, "WPS: Invalid WPS IE in " + "(Re)Association Request - reject"); + return WLAN_STATUS_INVALID_IE; + } + } else if (hapd->conf->wps_state && wpa_ie == NULL) { + wpa_printf(MSG_DEBUG, "STA did not include WPA/RSN IE in " + "(Re)Association Request - possible WPS use"); + sta->flags |= WLAN_STA_MAYBE_WPS; + } else +#endif /* CONFIG_WPS */ + if (hapd->conf->wpa && wpa_ie == NULL) { + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, + "No WPA/RSN IE in association request"); + return WLAN_STATUS_INVALID_IE; + } + + if (hapd->conf->wpa && wpa_ie) { + int res; + wpa_ie -= 2; + wpa_ie_len += 2; + if (sta->wpa_sm == NULL) + sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, + sta->addr, + p2p_dev_addr); + if (sta->wpa_sm == NULL) { + wpa_printf(MSG_WARNING, "Failed to initialize WPA " + "state machine"); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + wpa_auth_set_auth_alg(sta->wpa_sm, sta->auth_alg); + res = wpa_validate_wpa_ie(hapd->wpa_auth, sta->wpa_sm, + hapd->iface->freq, + wpa_ie, wpa_ie_len, + elems.mdie, elems.mdie_len, + elems.owe_dh, elems.owe_dh_len); + resp = wpa_res_to_status_code(res); + if (resp != WLAN_STATUS_SUCCESS) + return resp; +#ifdef CONFIG_IEEE80211W_AP + if ((sta->flags & (WLAN_STA_ASSOC | WLAN_STA_MFP)) == + (WLAN_STA_ASSOC | WLAN_STA_MFP) && + !sta->sa_query_timed_out && + sta->sa_query_count > 0) + ap_check_sa_query_timeout(hapd, sta); + if ((sta->flags & (WLAN_STA_ASSOC | WLAN_STA_MFP)) == + (WLAN_STA_ASSOC | WLAN_STA_MFP) && + !sta->sa_query_timed_out && + (!reassoc || sta->auth_alg != WLAN_AUTH_FT)) { + /* + * STA has already been associated with MFP and SA + * Query timeout has not been reached. Reject the + * association attempt temporarily and start SA Query, + * if one is not pending. + */ + + if (sta->sa_query_count == 0) + ap_sta_start_sa_query(hapd, sta); + + return WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY; + } + + if (wpa_auth_uses_mfp(sta->wpa_sm)) + sta->flags |= WLAN_STA_MFP; + else + sta->flags &= ~WLAN_STA_MFP; +#endif /* CONFIG_IEEE80211W_AP */ + +#ifdef CONFIG_IEEE80211R_AP + if (sta->auth_alg == WLAN_AUTH_FT) { + if (!reassoc) { + wpa_printf(MSG_DEBUG, "FT: " MACSTR " tried " + "to use association (not " + "re-association) with FT auth_alg", + MAC2STR(sta->addr)); + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + + resp = wpa_ft_validate_reassoc(sta->wpa_sm, ies, + ies_len); + if (resp != WLAN_STATUS_SUCCESS) + return resp; + } +#endif /* CONFIG_IEEE80211R_AP */ + +#ifdef CONFIG_SAE_AP + if (wpa_auth_uses_sae(sta->wpa_sm) && sta->sae && + sta->sae->state == SAE_ACCEPTED) + wpa_auth_add_sae_pmkid(sta->wpa_sm, sta->sae->pmkid); + + if (wpa_auth_uses_sae(sta->wpa_sm) && + sta->auth_alg == WLAN_AUTH_OPEN) { + struct rsn_pmksa_cache_entry *sa; + sa = wpa_auth_sta_get_pmksa(sta->wpa_sm); + if (!sa || sa->akmp != WPA_KEY_MGMT_SAE) { + wpa_printf(MSG_DEBUG, + "SAE: No PMKSA cache entry found for " + MACSTR, MAC2STR(sta->addr)); + return WLAN_STATUS_INVALID_PMKID; + } + wpa_printf(MSG_DEBUG, "SAE: " MACSTR + " using PMKSA caching", MAC2STR(sta->addr)); + } else if (wpa_auth_uses_sae(sta->wpa_sm) && + sta->auth_alg != WLAN_AUTH_SAE && + !(sta->auth_alg == WLAN_AUTH_FT && + wpa_auth_uses_ft_sae(sta->wpa_sm))) { + wpa_printf(MSG_DEBUG, "SAE: " MACSTR " tried to use " + "SAE AKM after non-SAE auth_alg %u", + MAC2STR(sta->addr), sta->auth_alg); + return WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG; + } +#endif /* CONFIG_SAE_AP */ + +#ifdef CONFIG_OWE + if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE) && + wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_OWE && + elems.owe_dh) { + resp = owe_process_assoc_req(hapd, sta, elems.owe_dh, + elems.owe_dh_len); + if (resp != WLAN_STATUS_SUCCESS) + return resp; + } +#endif /* CONFIG_OWE */ + +#ifdef CONFIG_DPP2 + dpp_pfs_free(sta->dpp_pfs); + sta->dpp_pfs = NULL; + + if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) && + hapd->conf->dpp_netaccesskey && sta->wpa_sm && + wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_DPP && + elems.owe_dh) { + sta->dpp_pfs = dpp_pfs_init( + wpabuf_head(hapd->conf->dpp_netaccesskey), + wpabuf_len(hapd->conf->dpp_netaccesskey)); + if (!sta->dpp_pfs) { + wpa_printf(MSG_DEBUG, + "DPP: Could not initialize PFS"); + /* Try to continue without PFS */ + goto pfs_fail; + } + + if (dpp_pfs_process(sta->dpp_pfs, elems.owe_dh, + elems.owe_dh_len) < 0) { + dpp_pfs_free(sta->dpp_pfs); + sta->dpp_pfs = NULL; + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + } + + wpa_auth_set_dpp_z(sta->wpa_sm, sta->dpp_pfs ? + sta->dpp_pfs->secret : NULL); + pfs_fail: +#endif /* CONFIG_DPP2 */ + +#ifdef CONFIG_IEEE80211N + if ((sta->flags & (WLAN_STA_HT | WLAN_STA_VHT)) && + wpa_auth_get_pairwise(sta->wpa_sm) == WPA_CIPHER_TKIP) { + hostapd_logger(hapd, sta->addr, + HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, + "Station tried to use TKIP with HT " + "association"); + return WLAN_STATUS_CIPHER_REJECTED_PER_POLICY; + } +#endif /* CONFIG_IEEE80211N */ + } else + wpa_auth_sta_no_wpa(sta->wpa_sm); + +#ifdef CONFIG_P2P + p2p_group_notif_assoc(hapd->p2p_group, sta->addr, ies, ies_len); +#endif /* CONFIG_P2P */ + + ap_copy_sta_supp_op_classes(sta, elems.supp_op_classes, + elems.supp_op_classes_len); + + + if (elems.power_capab) { + sta->min_tx_power = elems.power_capab[0]; + sta->max_tx_power = elems.power_capab[1]; + sta->power_capab = 1; + } else { + sta->power_capab = 0; + } + + return WLAN_STATUS_SUCCESS; +} + + +static void send_deauth(struct hostapd_data *hapd, const u8 *addr, + u16 reason_code) +{ + int send_len; + struct ieee80211_mgmt reply; + + os_memset(&reply, 0, sizeof(reply)); + reply.frame_control = + IEEE80211_FC(WLAN_FC_TYPE_MGMT, WLAN_FC_STYPE_DEAUTH); + os_memcpy(reply.da, addr, ETH_ALEN); + os_memcpy(reply.sa, hapd->own_addr, ETH_ALEN); + os_memcpy(reply.bssid, hapd->own_addr, ETH_ALEN); + + send_len = IEEE80211_HDRLEN + sizeof(reply.u.deauth); + reply.u.deauth.reason_code = host_to_le16(reason_code); + + if (hostapd_drv_send_mlme(hapd, &reply, send_len, 0) < 0) + wpa_printf(MSG_INFO, "Failed to send deauth error"); +} + + +static int add_associated_sta(struct hostapd_data *hapd, + struct sta_info *sta, int reassoc) +{ + struct ieee80211_ht_capabilities ht_cap; + struct ieee80211_vht_capabilities vht_cap; + struct ieee80211_he_capabilities he_cap; + int set = 1; + + /* + * Remove the STA entry to ensure the STA PS state gets cleared and + * configuration gets updated. This is relevant for cases, such as + * FT-over-the-DS, where a station re-associates back to the same AP but + * skips the authentication flow, or if working with a driver that + * does not support full AP client state. + * + * Skip this if the STA has already completed FT reassociation and the + * TK has been configured since the TX/RX PN must not be reset to 0 for + * the same key. + * + * FT-over-the-DS has a special case where the STA entry (and as such, + * the TK) has not yet been configured to the driver depending on which + * driver interface is used. For that case, allow add-STA operation to + * be used (instead of set-STA). This is needed to allow mac80211-based + * drivers to accept the STA parameter configuration. Since this is + * after a new FT-over-DS exchange, a new TK has been derived, so key + * reinstallation is not a concern for this case. + */ + wpa_printf(MSG_DEBUG, "Add associated STA " MACSTR + " (added_unassoc=%d auth_alg=%u ft_over_ds=%u reassoc=%d authorized=%d ft_tk=%d fils_tk=%d)", + MAC2STR(sta->addr), sta->added_unassoc, sta->auth_alg, + sta->ft_over_ds, reassoc, + !!(sta->flags & WLAN_STA_AUTHORIZED), + wpa_auth_sta_ft_tk_already_set(sta->wpa_sm), + wpa_auth_sta_fils_tk_already_set(sta->wpa_sm)); + + if (!sta->added_unassoc && + (!(sta->flags & WLAN_STA_AUTHORIZED) || + (reassoc && sta->ft_over_ds && sta->auth_alg == WLAN_AUTH_FT) || + (!wpa_auth_sta_ft_tk_already_set(sta->wpa_sm) && + !wpa_auth_sta_fils_tk_already_set(sta->wpa_sm)))) { + hostapd_drv_sta_remove(hapd, sta->addr); + wpa_auth_sm_event(sta->wpa_sm, WPA_DRV_STA_REMOVED); + set = 0; + + /* Do not allow the FT-over-DS exception to be used more than + * once per authentication exchange to guarantee a new TK is + * used here */ + sta->ft_over_ds = 0; + } + +#ifdef CONFIG_IEEE80211N + if (sta->flags & WLAN_STA_HT) + hostapd_get_ht_capab(hapd, sta->ht_capabilities, &ht_cap); +#endif /* CONFIG_IEEE80211N */ +#ifdef CONFIG_IEEE80211AC + if (sta->flags & WLAN_STA_VHT) + hostapd_get_vht_capab(hapd, sta->vht_capabilities, &vht_cap); +#endif /* CONFIG_IEEE80211AC */ +#ifdef CONFIG_IEEE80211AX + if (sta->flags & WLAN_STA_HE) { + hostapd_get_he_capab(hapd, sta->he_capab, &he_cap, + sta->he_capab_len); + } +#endif /* CONFIG_IEEE80211AX */ + + /* + * Add the station with forced WLAN_STA_ASSOC flag. The sta->flags + * will be set when the ACK frame for the (Re)Association Response frame + * is processed (TX status driver event). + */ + if (hostapd_sta_add(hapd, sta->addr, sta->aid, sta->capability, + sta->supported_rates, sta->supported_rates_len, + sta->listen_interval, + sta->flags & WLAN_STA_HT ? &ht_cap : NULL, + sta->flags & WLAN_STA_VHT ? &vht_cap : NULL, + sta->flags & WLAN_STA_HE ? &he_cap : NULL, + sta->flags & WLAN_STA_HE ? sta->he_capab_len : 0, + sta->flags | WLAN_STA_ASSOC, sta->qosinfo, + sta->vht_opmode, sta->p2p_ie ? 1 : 0, + set)) { + hostapd_logger(hapd, sta->addr, + HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_NOTICE, + "Could not %s STA to kernel driver", + set ? "set" : "add"); + + if (sta->added_unassoc) { + hostapd_drv_sta_remove(hapd, sta->addr); + sta->added_unassoc = 0; + } + + return -1; + } + + sta->added_unassoc = 0; + + return 0; +} + + +static u16 send_assoc_resp(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *addr, u16 status_code, int reassoc, + const u8 *ies, size_t ies_len, int rssi) +{ + int send_len; + u8 *buf; + size_t buflen; + struct ieee80211_mgmt *reply; + u8 *p; + u16 res = WLAN_STATUS_SUCCESS; + + buflen = sizeof(struct ieee80211_mgmt) + 1024; +#ifdef CONFIG_OWE + if (sta && (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE)) + buflen += 150; +#endif /* CONFIG_OWE */ +#ifdef CONFIG_DPP2 + if (sta && sta->dpp_pfs) + buflen += 5 + sta->dpp_pfs->curve->prime_len; +#endif /* CONFIG_DPP2 */ + buf = os_zalloc(buflen); + if (!buf) { + res = WLAN_STATUS_UNSPECIFIED_FAILURE; + goto done; + } + reply = (struct ieee80211_mgmt *) buf; + reply->frame_control = + IEEE80211_FC(WLAN_FC_TYPE_MGMT, + (reassoc ? WLAN_FC_STYPE_REASSOC_RESP : + WLAN_FC_STYPE_ASSOC_RESP)); + os_memcpy(reply->da, addr, ETH_ALEN); + os_memcpy(reply->sa, hapd->own_addr, ETH_ALEN); + os_memcpy(reply->bssid, hapd->own_addr, ETH_ALEN); + + send_len = IEEE80211_HDRLEN; + send_len += sizeof(reply->u.assoc_resp); + reply->u.assoc_resp.capab_info = + host_to_le16(hostapd_own_capab_info(hapd)); + reply->u.assoc_resp.status_code = host_to_le16(status_code); + + reply->u.assoc_resp.aid = host_to_le16((sta ? sta->aid : 0) | + BIT(14) | BIT(15)); + /* Supported rates */ + p = hostapd_eid_supp_rates(hapd, reply->u.assoc_resp.variable); + /* Extended supported rates */ + p = hostapd_eid_ext_supp_rates(hapd, p); + +#ifdef CONFIG_IEEE80211R_AP + if (sta && status_code == WLAN_STATUS_SUCCESS) { + /* IEEE 802.11r: Mobility Domain Information, Fast BSS + * Transition Information, RSN, [RIC Response] */ + p = wpa_sm_write_assoc_resp_ies(sta->wpa_sm, p, + buf + buflen - p, + sta->auth_alg, ies, ies_len); + if (!p) { + wpa_printf(MSG_DEBUG, + "FT: Failed to write AssocResp IEs"); + res = WLAN_STATUS_UNSPECIFIED_FAILURE; + goto done; + } + } +#endif /* CONFIG_IEEE80211R_AP */ + +#ifdef CONFIG_OWE + if (sta && status_code == WLAN_STATUS_SUCCESS && + (hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE)) + p = wpa_auth_write_assoc_resp_owe(sta->wpa_sm, p, + buf + buflen - p, + ies, ies_len); +#endif /* CONFIG_OWE */ + +#ifdef CONFIG_IEEE80211W_AP + if (sta && status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY) + p = hostapd_eid_assoc_comeback_time(hapd, sta, p); +#endif /* CONFIG_IEEE80211W_AP */ + +#ifdef CONFIG_IEEE80211N + p = hostapd_eid_ht_capabilities(hapd, p); + p = hostapd_eid_ht_operation(hapd, p); +#endif /* CONFIG_IEEE80211N */ + +#ifdef CONFIG_IEEE80211AC + if (hapd->iconf->ieee80211ac && !hapd->conf->disable_11ac) { + u32 nsts = 0, sta_nsts; + + if (sta && hapd->conf->use_sta_nsts && sta->vht_capabilities) { + struct ieee80211_vht_capabilities *capa; + + nsts = (hapd->iface->conf->vht_capab >> + VHT_CAP_BEAMFORMEE_STS_OFFSET) & 7; + capa = sta->vht_capabilities; + sta_nsts = (le_to_host32(capa->vht_capabilities_info) >> + VHT_CAP_BEAMFORMEE_STS_OFFSET) & 7; + + if (nsts < sta_nsts) + nsts = 0; + else + nsts = sta_nsts; + } + p = hostapd_eid_vht_capabilities(hapd, p, nsts); + p = hostapd_eid_vht_operation(hapd, p); + } +#endif /* CONFIG_IEEE80211AC */ + +#ifdef CONFIG_IEEE80211AX + if (hapd->iconf->ieee80211ax) { + p = hostapd_eid_he_capab(hapd, p, IEEE80211_MODE_AP); + p = hostapd_eid_he_operation(hapd, p); + p = hostapd_eid_spatial_reuse(hapd, p); + p = hostapd_eid_he_mu_edca_parameter_set(hapd, p); + } +#endif /* CONFIG_IEEE80211AX */ + + p = hostapd_eid_ext_capab(hapd, p); + p = hostapd_eid_bss_max_idle_period(hapd, p); + if (sta && sta->qos_map_enabled) + p = hostapd_eid_qos_map_set(hapd, p); + +#ifdef CONFIG_FST + if (hapd->iface->fst_ies) { + os_memcpy(p, wpabuf_head(hapd->iface->fst_ies), + wpabuf_len(hapd->iface->fst_ies)); + p += wpabuf_len(hapd->iface->fst_ies); + } +#endif /* CONFIG_FST */ + +#ifdef CONFIG_OWE + if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE) && + sta && sta->owe_ecdh && status_code == WLAN_STATUS_SUCCESS && + wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_OWE) { + struct wpabuf *pub; + + pub = crypto_ecdh_get_pubkey(sta->owe_ecdh, 0); + if (!pub) { + res = WLAN_STATUS_UNSPECIFIED_FAILURE; + goto done; + } + /* OWE Diffie-Hellman Parameter element */ + *p++ = WLAN_EID_EXTENSION; /* Element ID */ + *p++ = 1 + 2 + wpabuf_len(pub); /* Length */ + *p++ = WLAN_EID_EXT_OWE_DH_PARAM; /* Element ID Extension */ + WPA_PUT_LE16(p, sta->owe_group); + p += 2; + os_memcpy(p, wpabuf_head(pub), wpabuf_len(pub)); + p += wpabuf_len(pub); + wpabuf_free(pub); + } +#endif /* CONFIG_OWE */ + +#ifdef CONFIG_DPP2 + if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) && + sta && sta->dpp_pfs && status_code == WLAN_STATUS_SUCCESS && + wpa_auth_sta_key_mgmt(sta->wpa_sm) == WPA_KEY_MGMT_DPP) { + os_memcpy(p, wpabuf_head(sta->dpp_pfs->ie), + wpabuf_len(sta->dpp_pfs->ie)); + p += wpabuf_len(sta->dpp_pfs->ie); + } +#endif /* CONFIG_DPP2 */ + +#ifdef CONFIG_IEEE80211AC + if (sta && hapd->conf->vendor_vht && (sta->flags & WLAN_STA_VENDOR_VHT)) + p = hostapd_eid_vendor_vht(hapd, p); +#endif /* CONFIG_IEEE80211AC */ + + if (sta && (sta->flags & WLAN_STA_WMM)) + p = hostapd_eid_wmm(hapd, p); + +#ifdef CONFIG_WPS + if (sta && + ((sta->flags & WLAN_STA_WPS) || + ((sta->flags & WLAN_STA_MAYBE_WPS) && hapd->conf->wpa))) { + struct wpabuf *wps = wps_build_assoc_resp_ie(); + if (wps) { + os_memcpy(p, wpabuf_head(wps), wpabuf_len(wps)); + p += wpabuf_len(wps); + wpabuf_free(wps); + } + } +#endif /* CONFIG_WPS */ + +#ifdef CONFIG_FULL_HOSTAPD + if (sta && (sta->flags & WLAN_STA_MULTI_AP)) + p = hostapd_eid_multi_ap(hapd, p); +#endif + +#ifdef CONFIG_P2P + if (sta && sta->p2p_ie && hapd->p2p_group) { + struct wpabuf *p2p_resp_ie; + enum p2p_status_code status; + switch (status_code) { + case WLAN_STATUS_SUCCESS: + status = P2P_SC_SUCCESS; + break; + case WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA: + status = P2P_SC_FAIL_LIMIT_REACHED; + break; + default: + status = P2P_SC_FAIL_INVALID_PARAMS; + break; + } + p2p_resp_ie = p2p_group_assoc_resp_ie(hapd->p2p_group, status); + if (p2p_resp_ie) { + os_memcpy(p, wpabuf_head(p2p_resp_ie), + wpabuf_len(p2p_resp_ie)); + p += wpabuf_len(p2p_resp_ie); + wpabuf_free(p2p_resp_ie); + } + } +#endif /* CONFIG_P2P */ + +#ifdef CONFIG_P2P_MANAGER + if (hapd->conf->p2p & P2P_MANAGE) + p = hostapd_eid_p2p_manage(hapd, p); +#endif /* CONFIG_P2P_MANAGER */ + +#ifdef CONFIG_MBO + p = hostapd_eid_mbo(hapd, p, buf + buflen - p); +#endif + + if (hapd->conf->assocresp_elements && + (size_t) (buf + buflen - p) >= + wpabuf_len(hapd->conf->assocresp_elements)) { + os_memcpy(p, wpabuf_head(hapd->conf->assocresp_elements), + wpabuf_len(hapd->conf->assocresp_elements)); + p += wpabuf_len(hapd->conf->assocresp_elements); + } + + send_len += p - reply->u.assoc_resp.variable; + + if (hostapd_drv_send_mlme(hapd, reply, send_len, 0) < 0) { + wpa_printf(MSG_INFO, "Failed to send assoc resp error"); + res = WLAN_STATUS_UNSPECIFIED_FAILURE; + } + +done: + os_free(buf); + return res; +} + + +#ifdef CONFIG_OWE +u8 * owe_assoc_req_process(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *owe_dh, u8 owe_dh_len, + u8 *owe_buf, size_t owe_buf_len, u16 *reason) +{ +#ifdef CONFIG_TESTING_OPTIONS + if (hapd->conf->own_ie_override) { + wpa_printf(MSG_DEBUG, "OWE: Using IE override"); + *reason = WLAN_STATUS_SUCCESS; + return wpa_auth_write_assoc_resp_owe(sta->wpa_sm, owe_buf, + owe_buf_len, NULL, 0); + } +#endif /* CONFIG_TESTING_OPTIONS */ + + if (wpa_auth_sta_get_pmksa(sta->wpa_sm)) { + wpa_printf(MSG_DEBUG, "OWE: Using PMKSA caching"); + owe_buf = wpa_auth_write_assoc_resp_owe(sta->wpa_sm, owe_buf, + owe_buf_len, NULL, 0); + *reason = WLAN_STATUS_SUCCESS; + return owe_buf; + } + + if (sta->owe_pmk && sta->external_dh_updated) { + wpa_printf(MSG_DEBUG, "OWE: Using previously derived PMK"); + *reason = WLAN_STATUS_SUCCESS; + return owe_buf; + } + + *reason = owe_process_assoc_req(hapd, sta, owe_dh, owe_dh_len); + if (*reason != WLAN_STATUS_SUCCESS) + return NULL; + + owe_buf = wpa_auth_write_assoc_resp_owe(sta->wpa_sm, owe_buf, + owe_buf_len, NULL, 0); + + if (sta->owe_ecdh && owe_buf) { + struct wpabuf *pub; + + pub = crypto_ecdh_get_pubkey(sta->owe_ecdh, 0); + if (!pub) { + *reason = WLAN_STATUS_UNSPECIFIED_FAILURE; + return owe_buf; + } + + /* OWE Diffie-Hellman Parameter element */ + *owe_buf++ = WLAN_EID_EXTENSION; /* Element ID */ + *owe_buf++ = 1 + 2 + wpabuf_len(pub); /* Length */ + *owe_buf++ = WLAN_EID_EXT_OWE_DH_PARAM; /* Element ID Extension + */ + WPA_PUT_LE16(owe_buf, sta->owe_group); + owe_buf += 2; + os_memcpy(owe_buf, wpabuf_head(pub), wpabuf_len(pub)); + owe_buf += wpabuf_len(pub); + wpabuf_free(pub); + } + + return owe_buf; +} +#endif /* CONFIG_OWE */ + +static void handle_assoc(struct hostapd_data *hapd, + const struct ieee80211_mgmt *mgmt, size_t len, + int reassoc, int rssi) +{ + u16 capab_info, listen_interval, seq_ctrl, fc; + u16 resp = WLAN_STATUS_SUCCESS, reply_res; + const u8 *pos; + int left, i; + struct sta_info *sta; + u8 *tmp = NULL; + struct hostapd_sta_wpa_psk_short *psk = NULL; +#ifdef CONFIG_IEEE80211AD + char *identity = NULL; + char *radius_cui = NULL; +#endif +#ifdef CONFIG_FILS + int delay_assoc = 0; +#endif /* CONFIG_FILS */ + + if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_req) : + sizeof(mgmt->u.assoc_req))) { + wpa_printf(MSG_INFO, "handle_assoc(reassoc=%d) - too short payload (len=%lu)", + reassoc, (unsigned long) len); + return; + } + +#ifdef CONFIG_TESTING_OPTIONS + if (reassoc) { + if (hapd->iconf->ignore_reassoc_probability > 0.0 && + drand48() < hapd->iconf->ignore_reassoc_probability) { + wpa_printf(MSG_INFO, + "TESTING: ignoring reassoc request from " + MACSTR, MAC2STR(mgmt->sa)); + return; + } + } else { + if (hapd->iconf->ignore_assoc_probability > 0.0 && + drand48() < hapd->iconf->ignore_assoc_probability) { + wpa_printf(MSG_INFO, + "TESTING: ignoring assoc request from " + MACSTR, MAC2STR(mgmt->sa)); + return; + } + } +#endif /* CONFIG_TESTING_OPTIONS */ + + fc = le_to_host16(mgmt->frame_control); + seq_ctrl = le_to_host16(mgmt->seq_ctrl); + + if (reassoc) { + capab_info = le_to_host16(mgmt->u.reassoc_req.capab_info); + listen_interval = le_to_host16( + mgmt->u.reassoc_req.listen_interval); + wpa_printf(MSG_DEBUG, "reassociation request: STA=" MACSTR + " capab_info=0x%02x listen_interval=%d current_ap=" + MACSTR " seq_ctrl=0x%x%s", + MAC2STR(mgmt->sa), capab_info, listen_interval, + MAC2STR(mgmt->u.reassoc_req.current_ap), + seq_ctrl, (fc & WLAN_FC_RETRY) ? " retry" : ""); + left = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.reassoc_req)); + pos = mgmt->u.reassoc_req.variable; + } else { + capab_info = le_to_host16(mgmt->u.assoc_req.capab_info); + listen_interval = le_to_host16( + mgmt->u.assoc_req.listen_interval); + wpa_printf(MSG_DEBUG, "association request: STA=" MACSTR + " capab_info=0x%02x listen_interval=%d " + "seq_ctrl=0x%x%s", + MAC2STR(mgmt->sa), capab_info, listen_interval, + seq_ctrl, (fc & WLAN_FC_RETRY) ? " retry" : ""); + left = len - (IEEE80211_HDRLEN + sizeof(mgmt->u.assoc_req)); + pos = mgmt->u.assoc_req.variable; + } + + sta = ap_get_sta(hapd, mgmt->sa); +#ifdef CONFIG_IEEE80211R_AP + if (sta && sta->auth_alg == WLAN_AUTH_FT && + (sta->flags & WLAN_STA_AUTH) == 0) { + wpa_printf(MSG_DEBUG, "FT: Allow STA " MACSTR " to associate " + "prior to authentication since it is using " + "over-the-DS FT", MAC2STR(mgmt->sa)); + + /* + * Mark station as authenticated, to avoid adding station + * entry in the driver as associated and not authenticated + */ + sta->flags |= WLAN_STA_AUTH; + } else +#endif /* CONFIG_IEEE80211R_AP */ + if (sta == NULL || (sta->flags & WLAN_STA_AUTH) == 0) { + if (hapd->iface->current_mode && + hapd->iface->current_mode->mode == + HOSTAPD_MODE_IEEE80211AD) { +#ifdef CONFIG_IEEE80211AD + int acl_res; + u32 session_timeout, acct_interim_interval; + struct vlan_description vlan_id; + + acl_res = ieee802_11_allowed_address( + hapd, mgmt->sa, (const u8 *) mgmt, len, + &session_timeout, &acct_interim_interval, + &vlan_id, &psk, &identity, &radius_cui, 0); + if (acl_res == HOSTAPD_ACL_REJECT) { + wpa_msg(hapd->msg_ctx, MSG_DEBUG, + "Ignore Association Request frame from " + MACSTR " due to ACL reject", + MAC2STR(mgmt->sa)); + resp = WLAN_STATUS_UNSPECIFIED_FAILURE; + goto fail; + } + if (acl_res == HOSTAPD_ACL_PENDING) + return; + + /* DMG/IEEE 802.11ad does not use authentication. + * Allocate sta entry upon association. */ + sta = ap_sta_add(hapd, mgmt->sa); + if (!sta) { + hostapd_logger(hapd, mgmt->sa, + HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, + "Failed to add STA"); + resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; + goto fail; + } + + acl_res = ieee802_11_set_radius_info( + hapd, sta, acl_res, session_timeout, + acct_interim_interval, &vlan_id, &psk, + &identity, &radius_cui); + if (acl_res) { + resp = WLAN_STATUS_UNSPECIFIED_FAILURE; + goto fail; + } + + hostapd_logger(hapd, sta->addr, + HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "Skip authentication for DMG/IEEE 802.11ad"); + sta->flags |= WLAN_STA_AUTH; + wpa_auth_sm_event(sta->wpa_sm, WPA_AUTH); + sta->auth_alg = WLAN_AUTH_OPEN; +#endif + } else { + hostapd_logger(hapd, mgmt->sa, + HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, + "Station tried to associate before authentication (aid=%d flags=0x%x)", + sta ? sta->aid : -1, + sta ? sta->flags : 0); + send_deauth(hapd, mgmt->sa, + WLAN_REASON_CLASS2_FRAME_FROM_NONAUTH_STA); + return; + } + } + + if ((fc & WLAN_FC_RETRY) && + sta->last_seq_ctrl != WLAN_INVALID_MGMT_SEQ && + sta->last_seq_ctrl == seq_ctrl && + sta->last_subtype == (reassoc ? WLAN_FC_STYPE_REASSOC_REQ : + WLAN_FC_STYPE_ASSOC_REQ)) { + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "Drop repeated association frame seq_ctrl=0x%x", + seq_ctrl); + return; + } + sta->last_seq_ctrl = seq_ctrl; + sta->last_subtype = reassoc ? WLAN_FC_STYPE_REASSOC_REQ : + WLAN_FC_STYPE_ASSOC_REQ; + + if (hapd->tkip_countermeasures) { + resp = WLAN_STATUS_UNSPECIFIED_FAILURE; + goto fail; + } + + if (listen_interval > hapd->conf->max_listen_interval) { + hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "Too large Listen Interval (%d)", + listen_interval); + resp = WLAN_STATUS_ASSOC_DENIED_LISTEN_INT_TOO_LARGE; + goto fail; + } + +#ifdef CONFIG_MBO + if (hapd->conf->mbo_enabled && hapd->mbo_assoc_disallow) { + resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; + goto fail; + } + + if (hapd->iconf->rssi_reject_assoc_rssi && rssi && + rssi < hapd->iconf->rssi_reject_assoc_rssi && + (sta->auth_rssi == 0 || + sta->auth_rssi < hapd->iconf->rssi_reject_assoc_rssi)) { + resp = WLAN_STATUS_DENIED_POOR_CHANNEL_CONDITIONS; + goto fail; + } +#endif /* CONFIG_MBO */ + + /* + * sta->capability is used in check_assoc_ies() for RRM enabled + * capability element. + */ + sta->capability = capab_info; + + /* followed by SSID and Supported rates; and HT capabilities if 802.11n + * is used */ + resp = check_assoc_ies(hapd, sta, pos, left, reassoc); + if (resp != WLAN_STATUS_SUCCESS) + goto fail; + + if (hostapd_get_aid(hapd, sta) < 0) { + hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, "No room for more AIDs"); + resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; + goto fail; + } + + sta->listen_interval = listen_interval; + + if (hapd->iface->current_mode && + hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G) + sta->flags |= WLAN_STA_NONERP; + for (i = 0; i < sta->supported_rates_len; i++) { + if ((sta->supported_rates[i] & 0x7f) > 22) { + sta->flags &= ~WLAN_STA_NONERP; + break; + } + } + if (sta->flags & WLAN_STA_NONERP && !sta->nonerp_set) { + sta->nonerp_set = 1; + hapd->iface->num_sta_non_erp++; + if (hapd->iface->num_sta_non_erp == 1) + ieee802_11_set_beacons(hapd->iface); + } + + if (!(sta->capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) && + !sta->no_short_slot_time_set) { + sta->no_short_slot_time_set = 1; + hapd->iface->num_sta_no_short_slot_time++; + if (hapd->iface->current_mode && + hapd->iface->current_mode->mode == + HOSTAPD_MODE_IEEE80211G && + hapd->iface->num_sta_no_short_slot_time == 1) + ieee802_11_set_beacons(hapd->iface); + } + + if (sta->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) + sta->flags |= WLAN_STA_SHORT_PREAMBLE; + else + sta->flags &= ~WLAN_STA_SHORT_PREAMBLE; + + if (!(sta->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) && + !sta->no_short_preamble_set) { + sta->no_short_preamble_set = 1; + hapd->iface->num_sta_no_short_preamble++; + if (hapd->iface->current_mode && + hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G + && hapd->iface->num_sta_no_short_preamble == 1) + ieee802_11_set_beacons(hapd->iface); + } + +#ifdef CONFIG_IEEE80211N + update_ht_state(hapd, sta); +#endif /* CONFIG_IEEE80211N */ + + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "association OK (aid %d)", sta->aid); + /* Station will be marked associated, after it acknowledges AssocResp + */ + sta->flags |= WLAN_STA_ASSOC_REQ_OK; + +#ifdef CONFIG_IEEE80211W_AP + if ((sta->flags & WLAN_STA_MFP) && sta->sa_query_timed_out) { + wpa_printf(MSG_DEBUG, "Allowing %sassociation after timed out " + "SA Query procedure", reassoc ? "re" : ""); + /* TODO: Send a protected Disassociate frame to the STA using + * the old key and Reason Code "Previous Authentication no + * longer valid". Make sure this is only sent protected since + * unprotected frame would be received by the STA that is now + * trying to associate. + */ + } +#endif /* CONFIG_IEEE80211W_AP */ + + /* Make sure that the previously registered inactivity timer will not + * remove the STA immediately. */ + sta->timeout_next = STA_NULLFUNC; + + + sta->pending_wds_enable = 0; + + fail: + hostapd_free_psk_list(psk); + + /* + * In case of a successful response, add the station to the driver. + * Otherwise, the kernel may ignore Data frames before we process the + * ACK frame (TX status). In case of a failure, this station will be + * removed. + * + * Note that this is not compliant with the IEEE 802.11 standard that + * states that a non-AP station should transition into the + * authenticated/associated state only after the station acknowledges + * the (Re)Association Response frame. However, still do this as: + * + * 1. In case the station does not acknowledge the (Re)Association + * Response frame, it will be removed. + * 2. Data frames will be dropped in the kernel until the station is + * set into authorized state, and there are no significant known + * issues with processing other non-Data Class 3 frames during this + * window. + */ + if (resp == WLAN_STATUS_SUCCESS && sta && + add_associated_sta(hapd, sta, reassoc)) + resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; + + reply_res = send_assoc_resp(hapd, sta, mgmt->sa, resp, reassoc, pos, + left, rssi); + os_free(tmp); + + /* + * Remove the station in case tranmission of a success response fails + * (the STA was added associated to the driver) or if the station was + * previously added unassociated. + */ + if (sta && ((reply_res != WLAN_STATUS_SUCCESS && + resp == WLAN_STATUS_SUCCESS) || sta->added_unassoc)) { + hostapd_drv_sta_remove(hapd, sta->addr); + sta->added_unassoc = 0; + } +} + + +static void handle_disassoc(struct hostapd_data *hapd, + const struct ieee80211_mgmt *mgmt, size_t len) +{ + struct sta_info *sta; + + if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.disassoc)) { + wpa_printf(MSG_INFO, "handle_disassoc - too short payload (len=%lu)", + (unsigned long) len); + return; + } + + wpa_printf(MSG_DEBUG, "disassocation: STA=" MACSTR " reason_code=%d", + MAC2STR(mgmt->sa), + le_to_host16(mgmt->u.disassoc.reason_code)); + + sta = ap_get_sta(hapd, mgmt->sa); + if (sta == NULL) { + wpa_printf(MSG_INFO, "Station " MACSTR " trying to disassociate, but it is not associated", + MAC2STR(mgmt->sa)); + return; + } + + ap_sta_set_authorized(hapd, sta, 0); + sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ; + sta->flags &= ~(WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK); + wpa_auth_sm_event(sta->wpa_sm, WPA_DISASSOC); + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, "disassociated"); +#ifdef CONFIG_FULL_HOSTAPD + sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST; +#endif + ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); + /* Stop Accounting and IEEE 802.1X sessions, but leave the STA + * authenticated. */ + accounting_sta_stop(hapd, sta); +#ifdef IEEE8021X_EAPOL + ieee802_1x_free_station(hapd, sta); +#endif + if (sta->ipaddr) + hostapd_drv_br_delete_ip_neigh(hapd, 4, (u8 *) &sta->ipaddr); + ap_sta_ip6addr_del(hapd, sta); + hostapd_drv_sta_remove(hapd, sta->addr); + sta->added_unassoc = 0; + + if (sta->timeout_next == STA_NULLFUNC || + sta->timeout_next == STA_DISASSOC) { + sta->timeout_next = STA_DEAUTH; + eloop_cancel_timeout(ap_handle_timer, hapd, sta); + eloop_register_timeout(AP_DEAUTH_DELAY, 0, ap_handle_timer, + hapd, sta); + } + + mlme_disassociate_indication( + hapd, sta, le_to_host16(mgmt->u.disassoc.reason_code)); + +#ifdef CONFIG_FULL_HOSTAPD + /* DMG/IEEE 802.11ad does not use deauthication. Deallocate sta upon + * disassociation. */ + if (hapd->iface->current_mode && + hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211AD) { + sta->flags &= ~WLAN_STA_AUTH; + wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH); + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, "deauthenticated"); + ap_free_sta(hapd, sta); + } +#endif +} + + +static void handle_deauth(struct hostapd_data *hapd, + const struct ieee80211_mgmt *mgmt, size_t len) +{ + struct sta_info *sta; + + if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.deauth)) { + wpa_msg(hapd->msg_ctx, MSG_DEBUG, "handle_deauth - too short " + "payload (len=%lu)", (unsigned long) len); + return; + } + + wpa_msg(hapd->msg_ctx, MSG_DEBUG, "deauthentication: STA=" MACSTR + " reason_code=%d", + MAC2STR(mgmt->sa), le_to_host16(mgmt->u.deauth.reason_code)); + + sta = ap_get_sta(hapd, mgmt->sa); + if (sta == NULL) { + wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Station " MACSTR " trying " + "to deauthenticate, but it is not authenticated", + MAC2STR(mgmt->sa)); + return; + } + + ap_sta_set_authorized(hapd, sta, 0); + sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ; + sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC | + WLAN_STA_ASSOC_REQ_OK); + wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH); + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, "deauthenticated"); + mlme_deauthenticate_indication( + hapd, sta, le_to_host16(mgmt->u.deauth.reason_code)); +#ifdef CONFIG_FULL_HOSTAPD + sta->acct_terminate_cause = RADIUS_ACCT_TERMINATE_CAUSE_USER_REQUEST; +#endif + ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); + ap_free_sta(hapd, sta); +} + + +static void handle_beacon(struct hostapd_data *hapd, + const struct ieee80211_mgmt *mgmt, size_t len, + struct hostapd_frame_info *fi) +{ + struct ieee802_11_elems elems; + + if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.beacon)) { + wpa_printf(MSG_INFO, "handle_beacon - too short payload (len=%lu)", + (unsigned long) len); + return; + } + + (void) ieee802_11_parse_elems(mgmt->u.beacon.variable, + len - (IEEE80211_HDRLEN + + sizeof(mgmt->u.beacon)), &elems, + 0); + + ap_list_process_beacon(hapd->iface, mgmt, &elems, fi); +} + + +#ifdef CONFIG_IEEE80211W_AP +static int robust_action_frame(u8 category) +{ + return category != WLAN_ACTION_PUBLIC && + category != WLAN_ACTION_HT; +} +#endif /* CONFIG_IEEE80211W_AP */ + + +static int handle_action(struct hostapd_data *hapd, + const struct ieee80211_mgmt *mgmt, size_t len, + unsigned int freq) +{ + struct sta_info *sta; + u8 *action __maybe_unused; + + if (len < IEEE80211_HDRLEN + 2 + 1) { + hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "handle_action - too short payload (len=%lu)", + (unsigned long) len); + return 0; + } + + action = (u8 *) &mgmt->u.action.u; + wpa_printf(MSG_DEBUG, "RX_ACTION category %u action %u sa " MACSTR + " da " MACSTR " len %d freq %u", + mgmt->u.action.category, *action, + MAC2STR(mgmt->sa), MAC2STR(mgmt->da), (int) len, freq); + + sta = ap_get_sta(hapd, mgmt->sa); + + if (mgmt->u.action.category != WLAN_ACTION_PUBLIC && + (sta == NULL || !(sta->flags & WLAN_STA_ASSOC))) { + wpa_printf(MSG_DEBUG, "IEEE 802.11: Ignored Action " + "frame (category=%u) from unassociated STA " MACSTR, + mgmt->u.action.category, MAC2STR(mgmt->sa)); + return 0; + } + +#ifdef CONFIG_IEEE80211W_AP + if (sta && (sta->flags & WLAN_STA_MFP) && + !(mgmt->frame_control & host_to_le16(WLAN_FC_ISWEP)) && + robust_action_frame(mgmt->u.action.category)) { + hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "Dropped unprotected Robust Action frame from " + "an MFP STA"); + return 0; + } +#endif /* CONFIG_IEEE80211W_AP */ + + if (sta) { + u16 fc = le_to_host16(mgmt->frame_control); + u16 seq_ctrl = le_to_host16(mgmt->seq_ctrl); + + if ((fc & WLAN_FC_RETRY) && + sta->last_seq_ctrl != WLAN_INVALID_MGMT_SEQ && + sta->last_seq_ctrl == seq_ctrl && + sta->last_subtype == WLAN_FC_STYPE_ACTION) { + hostapd_logger(hapd, sta->addr, + HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "Drop repeated action frame seq_ctrl=0x%x", + seq_ctrl); + return 1; + } + + sta->last_seq_ctrl = seq_ctrl; + sta->last_subtype = WLAN_FC_STYPE_ACTION; + } + + switch (mgmt->u.action.category) { +#ifdef CONFIG_IEEE80211R_AP + case WLAN_ACTION_FT: + if (!sta || + wpa_ft_action_rx(sta->wpa_sm, (u8 *) &mgmt->u.action, + len - IEEE80211_HDRLEN)) + break; + return 1; +#endif /* CONFIG_IEEE80211R_AP */ +#ifdef CONFIG_FULL_HOSTAPD + case WLAN_ACTION_WMM: + hostapd_wmm_action(hapd, mgmt, len); + return 1; +#endif +#ifdef CONFIG_IEEE80211W_AP + case WLAN_ACTION_SA_QUERY: + ieee802_11_sa_query_action(hapd, mgmt, len); + return 1; +#endif /* CONFIG_IEEE80211W_AP */ +#ifdef CONFIG_WNM_AP + case WLAN_ACTION_WNM: + ieee802_11_rx_wnm_action_ap(hapd, mgmt, len); + return 1; +#endif /* CONFIG_WNM_AP */ +#ifdef CONFIG_FST + case WLAN_ACTION_FST: + if (hapd->iface->fst) + fst_rx_action(hapd->iface->fst, mgmt, len); + else + wpa_printf(MSG_DEBUG, + "FST: Ignore FST Action frame - no FST attached"); + return 1; +#endif /* CONFIG_FST */ + case WLAN_ACTION_PUBLIC: + case WLAN_ACTION_PROTECTED_DUAL: +#ifdef CONFIG_IEEE80211N + if (len >= IEEE80211_HDRLEN + 2 && + mgmt->u.action.u.public_action.action == + WLAN_PA_20_40_BSS_COEX) { + hostapd_2040_coex_action(hapd, mgmt, len); + return 1; + } +#endif /* CONFIG_IEEE80211N */ +#ifdef CONFIG_DPP + if (len >= IEEE80211_HDRLEN + 6 && + mgmt->u.action.u.vs_public_action.action == + WLAN_PA_VENDOR_SPECIFIC && + WPA_GET_BE24(mgmt->u.action.u.vs_public_action.oui) == + OUI_WFA && + mgmt->u.action.u.vs_public_action.variable[0] == + DPP_OUI_TYPE) { + const u8 *pos, *end; + + pos = mgmt->u.action.u.vs_public_action.oui; + end = ((const u8 *) mgmt) + len; + hostapd_dpp_rx_action(hapd, mgmt->sa, pos, end - pos, + freq); + return 1; + } + if (len >= IEEE80211_HDRLEN + 2 && + (mgmt->u.action.u.public_action.action == + WLAN_PA_GAS_INITIAL_RESP || + mgmt->u.action.u.public_action.action == + WLAN_PA_GAS_COMEBACK_RESP)) { + const u8 *pos, *end; + + pos = &mgmt->u.action.u.public_action.action; + end = ((const u8 *) mgmt) + len; + gas_query_ap_rx(hapd->gas, mgmt->sa, + mgmt->u.action.category, + pos, end - pos, hapd->iface->freq); + return 1; + } +#endif /* CONFIG_DPP */ + if (hapd->public_action_cb) { + hapd->public_action_cb(hapd->public_action_cb_ctx, + (u8 *) mgmt, len, + hapd->iface->freq); + } + if (hapd->public_action_cb2) { + hapd->public_action_cb2(hapd->public_action_cb2_ctx, + (u8 *) mgmt, len, + hapd->iface->freq); + } + if (hapd->public_action_cb || hapd->public_action_cb2) + return 1; + break; + case WLAN_ACTION_VENDOR_SPECIFIC: + if (hapd->vendor_action_cb) { + if (hapd->vendor_action_cb(hapd->vendor_action_cb_ctx, + (u8 *) mgmt, len, + hapd->iface->freq) == 0) + return 1; + } + break; + } + + hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "handle_action - unknown action category %d or invalid " + "frame", + mgmt->u.action.category); + if (!is_multicast_ether_addr(mgmt->da) && + !(mgmt->u.action.category & 0x80) && + !is_multicast_ether_addr(mgmt->sa)) { + struct ieee80211_mgmt *resp; + + /* + * IEEE 802.11-REVma/D9.0 - 7.3.1.11 + * Return the Action frame to the source without change + * except that MSB of the Category set to 1. + */ + wpa_printf(MSG_DEBUG, "IEEE 802.11: Return unknown Action " + "frame back to sender"); + resp = os_memdup(mgmt, len); + if (resp == NULL) + return 0; + os_memcpy(resp->da, resp->sa, ETH_ALEN); + os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN); + os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN); + resp->u.action.category |= 0x80; + + if (hostapd_drv_send_mlme(hapd, resp, len, 0) < 0) { + wpa_printf(MSG_ERROR, "IEEE 802.11: Failed to send " + "Action frame"); + } + os_free(resp); + } + + return 1; +} + + +/** + * ieee802_11_mgmt - process incoming IEEE 802.11 management frames + * @hapd: hostapd BSS data structure (the BSS to which the management frame was + * sent to) + * @buf: management frame data (starting from IEEE 802.11 header) + * @len: length of frame data in octets + * @fi: meta data about received frame (signal level, etc.) + * + * Process all incoming IEEE 802.11 management frames. This will be called for + * each frame received from the kernel driver through wlan#ap interface. In + * addition, it can be called to re-inserted pending frames (e.g., when using + * external RADIUS server as an MAC ACL). + */ +int ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len, + struct hostapd_frame_info *fi) +{ + struct ieee80211_mgmt *mgmt; + u16 fc, stype; + int ret = 0; + unsigned int freq; + int ssi_signal = fi ? fi->ssi_signal : 0; + + if (len < 24) + return 0; + + if (fi && fi->freq) + freq = fi->freq; + else + freq = hapd->iface->freq; + + mgmt = (struct ieee80211_mgmt *) buf; + fc = le_to_host16(mgmt->frame_control); + stype = WLAN_FC_GET_STYPE(fc); + + if (stype == WLAN_FC_STYPE_BEACON) { + handle_beacon(hapd, mgmt, len, fi); + return 1; + } + + if (!is_broadcast_ether_addr(mgmt->bssid) && +#ifdef CONFIG_P2P + /* Invitation responses can be sent with the peer MAC as BSSID */ + !((hapd->conf->p2p & P2P_GROUP_OWNER) && + stype == WLAN_FC_STYPE_ACTION) && +#endif /* CONFIG_P2P */ +#ifdef CONFIG_MESH + !(hapd->conf->mesh & MESH_ENABLED) && +#endif /* CONFIG_MESH */ + os_memcmp(mgmt->bssid, hapd->own_addr, ETH_ALEN) != 0) { + wpa_printf(MSG_INFO, "MGMT: BSSID=" MACSTR " not our address", + MAC2STR(mgmt->bssid)); + return 0; + } + + + if (stype == WLAN_FC_STYPE_PROBE_REQ) { + handle_probe_req(hapd, mgmt, len, ssi_signal); + return 1; + } + + if ((!is_broadcast_ether_addr(mgmt->da) || + stype != WLAN_FC_STYPE_ACTION) && + os_memcmp(mgmt->da, hapd->own_addr, ETH_ALEN) != 0) { + hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "MGMT: DA=" MACSTR " not our address", + MAC2STR(mgmt->da)); + return 0; + } + + if (hapd->iconf->track_sta_max_num) + sta_track_add(hapd->iface, mgmt->sa, ssi_signal); + + switch (stype) { + case WLAN_FC_STYPE_AUTH: + wpa_printf(MSG_DEBUG, "mgmt::auth"); + handle_auth(hapd, mgmt, len, ssi_signal, 0); + ret = 1; + break; + case WLAN_FC_STYPE_ASSOC_REQ: + wpa_printf(MSG_DEBUG, "mgmt::assoc_req"); + handle_assoc(hapd, mgmt, len, 0, ssi_signal); + ret = 1; + break; + case WLAN_FC_STYPE_REASSOC_REQ: + wpa_printf(MSG_DEBUG, "mgmt::reassoc_req"); + handle_assoc(hapd, mgmt, len, 1, ssi_signal); + ret = 1; + break; + case WLAN_FC_STYPE_DISASSOC: + wpa_printf(MSG_DEBUG, "mgmt::disassoc"); + handle_disassoc(hapd, mgmt, len); + ret = 1; + break; + case WLAN_FC_STYPE_DEAUTH: + wpa_msg(hapd->msg_ctx, MSG_DEBUG, "mgmt::deauth"); + handle_deauth(hapd, mgmt, len); + ret = 1; + break; + case WLAN_FC_STYPE_ACTION: + wpa_printf(MSG_DEBUG, "mgmt::action"); + ret = handle_action(hapd, mgmt, len, freq); + break; + default: + hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "unknown mgmt frame subtype %d", stype); + break; + } + + return ret; +} + + +static void handle_auth_cb(struct hostapd_data *hapd, + const struct ieee80211_mgmt *mgmt, + size_t len, int ok) +{ + u16 auth_alg, auth_transaction, status_code; + struct sta_info *sta; + + sta = ap_get_sta(hapd, mgmt->da); + if (!sta) { + wpa_printf(MSG_DEBUG, "handle_auth_cb: STA " MACSTR + " not found", + MAC2STR(mgmt->da)); + return; + } + + auth_alg = le_to_host16(mgmt->u.auth.auth_alg); + auth_transaction = le_to_host16(mgmt->u.auth.auth_transaction); + status_code = le_to_host16(mgmt->u.auth.status_code); + + if (!ok) { + hostapd_logger(hapd, mgmt->da, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_NOTICE, + "did not acknowledge authentication response"); + goto fail; + } + + if (len < IEEE80211_HDRLEN + sizeof(mgmt->u.auth)) { + wpa_printf(MSG_INFO, "handle_auth_cb - too short payload (len=%lu)", + (unsigned long) len); + goto fail; + } + + if (status_code == WLAN_STATUS_SUCCESS && + ((auth_alg == WLAN_AUTH_OPEN && auth_transaction == 2) || + (auth_alg == WLAN_AUTH_SHARED_KEY && auth_transaction == 4))) { + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, "authenticated"); + sta->flags |= WLAN_STA_AUTH; + if (sta->added_unassoc) + hostapd_set_sta_flags(hapd, sta); + return; + } + +fail: + if (status_code != WLAN_STATUS_SUCCESS && sta->added_unassoc) { + hostapd_drv_sta_remove(hapd, sta->addr); + sta->added_unassoc = 0; + } +} + + +static void hostapd_set_wds_encryption(struct hostapd_data *hapd, + struct sta_info *sta, + char *ifname_wds) +{ + int i; + struct hostapd_ssid *ssid = &hapd->conf->ssid; + + if (hapd->conf->ieee802_1x || hapd->conf->wpa) + return; + + for (i = 0; i < 4; i++) { + if (ssid->wep.key[i] && + hostapd_drv_set_key(ifname_wds, hapd, WPA_ALG_WEP, NULL, i, + i == ssid->wep.idx, NULL, 0, + ssid->wep.key[i], ssid->wep.len[i])) { + wpa_printf(MSG_WARNING, + "Could not set WEP keys for WDS interface; %s", + ifname_wds); + break; + } + } +} + + +static void handle_assoc_cb(struct hostapd_data *hapd, + const struct ieee80211_mgmt *mgmt, + size_t len, int reassoc, int ok) +{ + u16 status; + struct sta_info *sta; + int new_assoc = 1; + + sta = ap_get_sta(hapd, mgmt->da); + if (!sta) { + wpa_printf(MSG_INFO, "handle_assoc_cb: STA " MACSTR " not found", + MAC2STR(mgmt->da)); + return; + } + + if (len < IEEE80211_HDRLEN + (reassoc ? sizeof(mgmt->u.reassoc_resp) : + sizeof(mgmt->u.assoc_resp))) { + wpa_printf(MSG_INFO, + "handle_assoc_cb(reassoc=%d) - too short payload (len=%lu)", + reassoc, (unsigned long) len); + hostapd_drv_sta_remove(hapd, sta->addr); + return; + } + + if (reassoc) + status = le_to_host16(mgmt->u.reassoc_resp.status_code); + else + status = le_to_host16(mgmt->u.assoc_resp.status_code); + + if (!ok) { + hostapd_logger(hapd, mgmt->da, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "did not acknowledge association response"); + sta->flags &= ~WLAN_STA_ASSOC_REQ_OK; + /* The STA is added only in case of SUCCESS */ + if (status == WLAN_STATUS_SUCCESS) + hostapd_drv_sta_remove(hapd, sta->addr); + + return; + } + + if (status != WLAN_STATUS_SUCCESS) + return; + + /* Stop previous accounting session, if one is started, and allocate + * new session id for the new session. */ + accounting_sta_stop(hapd, sta); + + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, + "associated (aid %d)", + sta->aid); + + if (sta->flags & WLAN_STA_ASSOC) + new_assoc = 0; + sta->flags |= WLAN_STA_ASSOC; + sta->flags &= ~WLAN_STA_WNM_SLEEP_MODE; + if ((!hapd->conf->ieee802_1x && !hapd->conf->wpa && + !hapd->conf->osen) || + sta->auth_alg == WLAN_AUTH_FILS_SK || + sta->auth_alg == WLAN_AUTH_FILS_SK_PFS || + sta->auth_alg == WLAN_AUTH_FILS_PK || + sta->auth_alg == WLAN_AUTH_FT) { + /* + * Open, static WEP, FT protocol, or FILS; no separate + * authorization step. + */ + ap_sta_set_authorized(hapd, sta, 1); + } + + if (reassoc) + mlme_reassociate_indication(hapd, sta); + else + mlme_associate_indication(hapd, sta); + +#ifdef CONFIG_IEEE80211W_AP + sta->sa_query_timed_out = 0; +#endif /* CONFIG_IEEE80211W_AP */ + + if (sta->eapol_sm == NULL) { + /* + * This STA does not use RADIUS server for EAP authentication, + * so bind it to the selected VLAN interface now, since the + * interface selection is not going to change anymore. + */ + if (ap_sta_bind_vlan(hapd, sta) < 0) + return; + } else if (sta->vlan_id) { + /* VLAN ID already set (e.g., by PMKSA caching), so bind STA */ + if (ap_sta_bind_vlan(hapd, sta) < 0) + return; + } + + hostapd_set_sta_flags(hapd, sta); + +#ifdef CONFIG_FULL_HOSTAPD + if (!(sta->flags & WLAN_STA_WDS) && sta->pending_wds_enable) { + wpa_printf(MSG_DEBUG, "Enable 4-address WDS mode for STA " + MACSTR " based on pending request", + MAC2STR(sta->addr)); + sta->pending_wds_enable = 0; + sta->flags |= WLAN_STA_WDS; + } + + if (sta->flags & (WLAN_STA_WDS | WLAN_STA_MULTI_AP)) { + int ret; + char ifname_wds[IFNAMSIZ + 1]; + + wpa_printf(MSG_DEBUG, "Reenable 4-address WDS mode for STA " + MACSTR " (aid %u)", + MAC2STR(sta->addr), sta->aid); + ret = hostapd_set_wds_sta(hapd, ifname_wds, sta->addr, + sta->aid, 1); + if (!ret) + hostapd_set_wds_encryption(hapd, sta, ifname_wds); + } +#endif + +#ifdef CONFIG_FULL_HOSTAPD + if (sta->auth_alg == WLAN_AUTH_FT) + wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC_FT); + else +#endif + wpa_auth_sm_event(sta->wpa_sm, WPA_ASSOC); + hapd->new_assoc_sta_cb(hapd, sta, !new_assoc); // hostapd_new_assoc_sta + + ieee802_1x_notify_port_enabled(sta->eapol_sm, 1); + +#ifdef IEEE8021X_EAPOL + if (sta->pending_eapol_rx) { + struct os_reltime now, age; + + os_get_reltime(&now); + os_reltime_sub(&now, &sta->pending_eapol_rx->rx_time, &age); + if (age.sec == 0 && age.usec < 200000) { + wpa_printf(MSG_DEBUG, + "Process pending EAPOL frame that was received from " MACSTR " just before association notification", + MAC2STR(sta->addr)); + ieee802_1x_receive( + hapd, mgmt->da, + wpabuf_head(sta->pending_eapol_rx->buf), + wpabuf_len(sta->pending_eapol_rx->buf)); + } + wpabuf_free(sta->pending_eapol_rx->buf); + os_free(sta->pending_eapol_rx); + sta->pending_eapol_rx = NULL; + } +#endif +} + + +static void handle_deauth_cb(struct hostapd_data *hapd, + const struct ieee80211_mgmt *mgmt, + size_t len, int ok) +{ + struct sta_info *sta; + if (is_multicast_ether_addr(mgmt->da)) + return; + sta = ap_get_sta(hapd, mgmt->da); + if (!sta) { + wpa_printf(MSG_DEBUG, "handle_deauth_cb: STA " MACSTR + " not found", MAC2STR(mgmt->da)); + return; + } + if (ok) + wpa_printf(MSG_DEBUG, "STA " MACSTR " acknowledged deauth", + MAC2STR(sta->addr)); + else + wpa_printf(MSG_DEBUG, "STA " MACSTR " did not acknowledge " + "deauth", MAC2STR(sta->addr)); + + ap_sta_deauth_cb(hapd, sta); +} + + +static void handle_disassoc_cb(struct hostapd_data *hapd, + const struct ieee80211_mgmt *mgmt, + size_t len, int ok) +{ + struct sta_info *sta; + if (is_multicast_ether_addr(mgmt->da)) + return; + sta = ap_get_sta(hapd, mgmt->da); + if (!sta) { + wpa_printf(MSG_DEBUG, "handle_disassoc_cb: STA " MACSTR + " not found", MAC2STR(mgmt->da)); + return; + } + if (ok) + wpa_printf(MSG_DEBUG, "STA " MACSTR " acknowledged disassoc", + MAC2STR(sta->addr)); + else + wpa_printf(MSG_DEBUG, "STA " MACSTR " did not acknowledge " + "disassoc", MAC2STR(sta->addr)); + + ap_sta_disassoc_cb(hapd, sta); +} + + +static void handle_action_cb(struct hostapd_data *hapd, + const struct ieee80211_mgmt *mgmt, + size_t len, int ok) +{ + struct sta_info *sta; +#ifdef CONFIG_RRM + const struct rrm_measurement_report_element *report; +#endif + + if (is_multicast_ether_addr(mgmt->da)) + return; +#ifdef CONFIG_DPP + if (len >= IEEE80211_HDRLEN + 6 && + mgmt->u.action.category == WLAN_ACTION_PUBLIC && + mgmt->u.action.u.vs_public_action.action == + WLAN_PA_VENDOR_SPECIFIC && + WPA_GET_BE24(mgmt->u.action.u.vs_public_action.oui) == + OUI_WFA && + mgmt->u.action.u.vs_public_action.variable[0] == + DPP_OUI_TYPE) { + const u8 *pos, *end; + + pos = &mgmt->u.action.u.vs_public_action.variable[1]; + end = ((const u8 *) mgmt) + len; + hostapd_dpp_tx_status(hapd, mgmt->da, pos, end - pos, ok); + return; + } + if (len >= IEEE80211_HDRLEN + 2 && + mgmt->u.action.category == WLAN_ACTION_PUBLIC && + (mgmt->u.action.u.public_action.action == + WLAN_PA_GAS_INITIAL_REQ || + mgmt->u.action.u.public_action.action == + WLAN_PA_GAS_COMEBACK_REQ)) { + const u8 *pos, *end; + + pos = mgmt->u.action.u.public_action.variable; + end = ((const u8 *) mgmt) + len; + gas_query_ap_tx_status(hapd->gas, mgmt->da, pos, end - pos, ok); + return; + } +#endif /* CONFIG_DPP */ + sta = ap_get_sta(hapd, mgmt->da); + if (!sta) { + wpa_printf(MSG_DEBUG, "handle_action_cb: STA " MACSTR + " not found", MAC2STR(mgmt->da)); + return; + } + +#ifdef CONFIG_RRM + if (len < 24 + 5 + sizeof(*report)) + return; + report = (const struct rrm_measurement_report_element *) + &mgmt->u.action.u.rrm.variable[2]; + + if (mgmt->u.action.category == WLAN_ACTION_RADIO_MEASUREMENT && + mgmt->u.action.u.rrm.action == WLAN_RRM_RADIO_MEASUREMENT_REQUEST && + report->eid == WLAN_EID_MEASURE_REQUEST && + report->len >= 3 && + report->type == MEASURE_TYPE_BEACON) + hostapd_rrm_beacon_req_tx_status(hapd, mgmt, len, ok); +#endif +} + + +/** + * ieee802_11_mgmt_cb - Process management frame TX status callback + * @hapd: hostapd BSS data structure (the BSS from which the management frame + * was sent from) + * @buf: management frame data (starting from IEEE 802.11 header) + * @len: length of frame data in octets + * @stype: management frame subtype from frame control field + * @ok: Whether the frame was ACK'ed + */ +void ieee802_11_mgmt_cb(struct hostapd_data *hapd, const u8 *buf, size_t len, + u16 stype, int ok) +{ + const struct ieee80211_mgmt *mgmt; + mgmt = (const struct ieee80211_mgmt *) buf; + +#ifdef CONFIG_TESTING_OPTIONS + if (hapd->ext_mgmt_frame_handling) { + size_t hex_len = 2 * len + 1; + char *hex = os_malloc(hex_len); + + if (hex) { + wpa_snprintf_hex(hex, hex_len, buf, len); + wpa_msg(hapd->msg_ctx, MSG_INFO, + "MGMT-TX-STATUS stype=%u ok=%d buf=%s", + stype, ok, hex); + os_free(hex); + } + return; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + switch (stype) { + case WLAN_FC_STYPE_AUTH: + wpa_printf(MSG_DEBUG, "mgmt::auth cb"); + handle_auth_cb(hapd, mgmt, len, ok); + break; + case WLAN_FC_STYPE_ASSOC_RESP: + wpa_printf(MSG_DEBUG, "mgmt::assoc_resp cb"); + handle_assoc_cb(hapd, mgmt, len, 0, ok); + break; + case WLAN_FC_STYPE_REASSOC_RESP: + wpa_printf(MSG_DEBUG, "mgmt::reassoc_resp cb"); + handle_assoc_cb(hapd, mgmt, len, 1, ok); + break; + case WLAN_FC_STYPE_PROBE_RESP: + wpa_printf(MSG_EXCESSIVE, "mgmt::proberesp cb ok=%d", ok); + break; + case WLAN_FC_STYPE_DEAUTH: + wpa_printf(MSG_DEBUG, "mgmt::deauth cb"); + handle_deauth_cb(hapd, mgmt, len, ok); + break; + case WLAN_FC_STYPE_DISASSOC: + wpa_printf(MSG_DEBUG, "mgmt::disassoc cb"); + handle_disassoc_cb(hapd, mgmt, len, ok); + break; + case WLAN_FC_STYPE_ACTION: + wpa_printf(MSG_DEBUG, "mgmt::action cb ok=%d", ok); +#ifdef CONFIG_FULL_HOSTAPD + handle_action_cb(hapd, mgmt, len, ok); +#endif + break; + default: + wpa_printf(MSG_INFO, "unknown mgmt cb frame subtype %d", stype); + break; + } +} + + +int ieee802_11_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen) +{ + /* TODO */ + return 0; +} + + +int ieee802_11_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta, + char *buf, size_t buflen) +{ + /* TODO */ + return 0; +} + + +void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr, + const u8 *buf, size_t len, int ack) +{ + struct sta_info *sta; + struct hostapd_iface *iface = hapd->iface; + + sta = ap_get_sta(hapd, addr); + if (sta == NULL && iface->num_bss > 1) { + size_t j; + for (j = 0; j < iface->num_bss; j++) { + hapd = iface->bss[j]; + sta = ap_get_sta(hapd, addr); + if (sta) + break; + } + } + if (sta == NULL || !(sta->flags & WLAN_STA_ASSOC)) + return; + if (sta->flags & WLAN_STA_PENDING_POLL) { + wpa_printf(MSG_DEBUG, "STA " MACSTR " %s pending " + "activity poll", MAC2STR(sta->addr), + ack ? "ACKed" : "did not ACK"); + if (ack) + sta->flags &= ~WLAN_STA_PENDING_POLL; + } + + ieee802_1x_tx_status(hapd, sta, buf, len, ack); +} + + +void hostapd_eapol_tx_status(struct hostapd_data *hapd, const u8 *dst, + const u8 *data, size_t len, int ack) +{ + struct sta_info *sta; + struct hostapd_iface *iface = hapd->iface; + + sta = ap_get_sta(hapd, dst); + if (sta == NULL && iface->num_bss > 1) { + size_t j; + for (j = 0; j < iface->num_bss; j++) { + hapd = iface->bss[j]; + sta = ap_get_sta(hapd, dst); + if (sta) + break; + } + } + if (sta == NULL || !(sta->flags & WLAN_STA_ASSOC)) { + wpa_printf(MSG_DEBUG, "Ignore TX status for Data frame to STA " + MACSTR " that is not currently associated", + MAC2STR(dst)); + return; + } + + ieee802_1x_eapol_tx_status(hapd, sta, data, len, ack); +} + + +void hostapd_client_poll_ok(struct hostapd_data *hapd, const u8 *addr) +{ + struct sta_info *sta; + struct hostapd_iface *iface = hapd->iface; + + sta = ap_get_sta(hapd, addr); + if (sta == NULL && iface->num_bss > 1) { + size_t j; + for (j = 0; j < iface->num_bss; j++) { + hapd = iface->bss[j]; + sta = ap_get_sta(hapd, addr); + if (sta) + break; + } + } + if (sta == NULL) + return; + wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_POLL_OK MACSTR, + MAC2STR(sta->addr)); + if (!(sta->flags & WLAN_STA_PENDING_POLL)) + return; + + wpa_printf(MSG_DEBUG, "STA " MACSTR " ACKed pending " + "activity poll", MAC2STR(sta->addr)); + sta->flags &= ~WLAN_STA_PENDING_POLL; +} + + +void ieee802_11_rx_from_unknown(struct hostapd_data *hapd, const u8 *src, + int wds) +{ + struct sta_info *sta; + + sta = ap_get_sta(hapd, src); +#ifdef CONFIG_FULL_HOSTAPD + if (sta && + ((sta->flags & WLAN_STA_ASSOC) || + ((sta->flags & WLAN_STA_ASSOC_REQ_OK) && wds))) { + if (!hapd->conf->wds_sta) + return; + + if ((sta->flags & (WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK)) == + WLAN_STA_ASSOC_REQ_OK) { + wpa_printf(MSG_DEBUG, + "Postpone 4-address WDS mode enabling for STA " + MACSTR " since TX status for AssocResp is not yet known", + MAC2STR(sta->addr)); + sta->pending_wds_enable = 1; + return; + } + + if (wds && !(sta->flags & WLAN_STA_WDS)) { + int ret; + char ifname_wds[IFNAMSIZ + 1]; + + wpa_printf(MSG_DEBUG, "Enable 4-address WDS mode for " + "STA " MACSTR " (aid %u)", + MAC2STR(sta->addr), sta->aid); + sta->flags |= WLAN_STA_WDS; + ret = hostapd_set_wds_sta(hapd, ifname_wds, + sta->addr, sta->aid, 1); + if (!ret) + hostapd_set_wds_encryption(hapd, sta, + ifname_wds); + } + return; + } +#endif + + wpa_printf(MSG_DEBUG, "Data/PS-poll frame from not associated STA " + MACSTR, MAC2STR(src)); + if (is_multicast_ether_addr(src)) { + /* Broadcast bit set in SA?! Ignore the frame silently. */ + return; + } + + if (sta && (sta->flags & WLAN_STA_ASSOC_REQ_OK)) { + wpa_printf(MSG_DEBUG, "Association Response to the STA has " + "already been sent, but no TX status yet known - " + "ignore Class 3 frame issue with " MACSTR, + MAC2STR(src)); + return; + } + + if (sta && (sta->flags & WLAN_STA_AUTH)) + hostapd_drv_sta_disassoc( + hapd, src, + WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); + else + hostapd_drv_sta_deauth( + hapd, src, + WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); +} diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ieee802_11.h b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ieee802_11.h new file mode 100755 index 0000000..b3a01d4 --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ieee802_11.h @@ -0,0 +1,196 @@ +/* + * hostapd / IEEE 802.11 Management + * Copyright (c) 2002-2009, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef IEEE802_11_H +#define IEEE802_11_H + +struct hostapd_iface; +struct hostapd_data; +struct sta_info; +struct hostapd_frame_info; +struct ieee80211_ht_capabilities; +struct ieee80211_vht_capabilities; +struct ieee80211_mgmt; +struct vlan_description; +struct hostapd_sta_wpa_psk_short; +enum ieee80211_op_mode; + +int ieee802_11_mgmt(struct hostapd_data *hapd, const u8 *buf, size_t len, + struct hostapd_frame_info *fi); +void ieee802_11_mgmt_cb(struct hostapd_data *hapd, const u8 *buf, size_t len, + u16 stype, int ok); +void hostapd_2040_coex_action(struct hostapd_data *hapd, + const struct ieee80211_mgmt *mgmt, size_t len); +#ifdef NEED_AP_MLME +int ieee802_11_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen); +int ieee802_11_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta, + char *buf, size_t buflen); +#else /* NEED_AP_MLME */ +static inline int ieee802_11_get_mib(struct hostapd_data *hapd, char *buf, + size_t buflen) +{ + return 0; +} + +static inline int ieee802_11_get_mib_sta(struct hostapd_data *hapd, + struct sta_info *sta, + char *buf, size_t buflen) +{ + return 0; +} +#endif /* NEED_AP_MLME */ +u16 hostapd_own_capab_info(struct hostapd_data *hapd); +void ap_ht2040_timeout(void *eloop_data, void *user_data); +u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid); +u8 * hostapd_eid_qos_map_set(struct hostapd_data *hapd, u8 *eid); +u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid); +u8 * hostapd_eid_ext_supp_rates(struct hostapd_data *hapd, u8 *eid); +u8 * hostapd_eid_ht_capabilities(struct hostapd_data *hapd, u8 *eid); +u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid); +u8 * hostapd_eid_secondary_channel(struct hostapd_data *hapd, u8 *eid); +u8 * hostapd_eid_vht_capabilities(struct hostapd_data *hapd, u8 *eid, u32 nsts); +u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid); +u8 * hostapd_eid_vendor_vht(struct hostapd_data *hapd, u8 *eid); +u8 * hostapd_eid_wb_chsw_wrapper(struct hostapd_data *hapd, u8 *eid); +u8 * hostapd_eid_txpower_envelope(struct hostapd_data *hapd, u8 *eid); +u8 * hostapd_eid_he_capab(struct hostapd_data *hapd, u8 *eid, + enum ieee80211_op_mode opmode); +u8 * hostapd_eid_he_operation(struct hostapd_data *hapd, u8 *eid); +u8 * hostapd_eid_he_mu_edca_parameter_set(struct hostapd_data *hapd, u8 *eid); +u8 * hostapd_eid_spatial_reuse(struct hostapd_data *hapd, u8 *eid); + +int hostapd_ht_operation_update(struct hostapd_iface *iface); +void ieee802_11_send_sa_query_req(struct hostapd_data *hapd, + const u8 *addr, const u8 *trans_id); +void hostapd_get_ht_capab(struct hostapd_data *hapd, + struct ieee80211_ht_capabilities *ht_cap, + struct ieee80211_ht_capabilities *neg_ht_cap); +void hostapd_get_vht_capab(struct hostapd_data *hapd, + struct ieee80211_vht_capabilities *vht_cap, + struct ieee80211_vht_capabilities *neg_vht_cap); +void hostapd_get_he_capab(struct hostapd_data *hapd, + const struct ieee80211_he_capabilities *he_cap, + struct ieee80211_he_capabilities *neg_he_cap, + size_t he_capab_len); +int hostapd_get_aid(struct hostapd_data *hapd, struct sta_info *sta); +u16 copy_sta_ht_capab(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *ht_capab); +u16 copy_sta_vendor_vht(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *ie, size_t len); + +void update_ht_state(struct hostapd_data *hapd, struct sta_info *sta); +void ht40_intolerant_add(struct hostapd_iface *iface, struct sta_info *sta); +void ht40_intolerant_remove(struct hostapd_iface *iface, struct sta_info *sta); +u16 copy_sta_vht_capab(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *vht_capab); +u16 copy_sta_vht_oper(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *vht_oper); +u16 set_sta_vht_opmode(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *vht_opmode); +u16 copy_sta_he_capab(struct hostapd_data *hapd, struct sta_info *sta, + enum ieee80211_op_mode opmode, const u8 *he_capab, + size_t he_capab_len); +void hostapd_tx_status(struct hostapd_data *hapd, const u8 *addr, + const u8 *buf, size_t len, int ack); +void hostapd_eapol_tx_status(struct hostapd_data *hapd, const u8 *dst, + const u8 *data, size_t len, int ack); +void ieee802_11_rx_from_unknown(struct hostapd_data *hapd, const u8 *src, + int wds); +u8 * hostapd_eid_assoc_comeback_time(struct hostapd_data *hapd, + struct sta_info *sta, u8 *eid); +void ieee802_11_sa_query_action(struct hostapd_data *hapd, + const struct ieee80211_mgmt *mgmt, + size_t len); +u8 * hostapd_eid_interworking(struct hostapd_data *hapd, u8 *eid); +u8 * hostapd_eid_adv_proto(struct hostapd_data *hapd, u8 *eid); +u8 * hostapd_eid_roaming_consortium(struct hostapd_data *hapd, u8 *eid); +u8 * hostapd_eid_time_adv(struct hostapd_data *hapd, u8 *eid); +u8 * hostapd_eid_time_zone(struct hostapd_data *hapd, u8 *eid); +int hostapd_update_time_adv(struct hostapd_data *hapd); +void hostapd_client_poll_ok(struct hostapd_data *hapd, const u8 *addr); +u8 * hostapd_eid_bss_max_idle_period(struct hostapd_data *hapd, u8 *eid); + +int auth_sae_init_committed(struct hostapd_data *hapd, struct sta_info *sta); +#ifdef CONFIG_SAE_AP +void sae_clear_retransmit_timer(struct hostapd_data *hapd, + struct sta_info *sta); +void sae_accept_sta(struct hostapd_data *hapd, struct sta_info *sta); +#else /* CONFIG_SAE_AP */ +static inline void sae_clear_retransmit_timer(struct hostapd_data *hapd, + struct sta_info *sta) +{ +} +#endif /* CONFIG_SAE_AP */ + +#ifdef CONFIG_MBO + +u8 * hostapd_eid_mbo(struct hostapd_data *hapd, u8 *eid, size_t len); + +u8 hostapd_mbo_ie_len(struct hostapd_data *hapd); + +u8 * hostapd_eid_mbo_rssi_assoc_rej(struct hostapd_data *hapd, u8 *eid, + size_t len, int delta); + +#else /* CONFIG_MBO */ + +static inline u8 * hostapd_eid_mbo(struct hostapd_data *hapd, u8 *eid, + size_t len) +{ + return eid; +} + +static inline u8 hostapd_mbo_ie_len(struct hostapd_data *hapd) +{ + return 0; +} + +#endif /* CONFIG_MBO */ + +void ap_copy_sta_supp_op_classes(struct sta_info *sta, + const u8 *supp_op_classes, + size_t supp_op_classes_len); + +u8 * hostapd_eid_fils_indic(struct hostapd_data *hapd, u8 *eid, int hessid); +void ieee802_11_finish_fils_auth(struct hostapd_data *hapd, + struct sta_info *sta, int success, + struct wpabuf *erp_resp, + const u8 *msk, size_t msk_len); +u8 * owe_assoc_req_process(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *owe_dh, u8 owe_dh_len, + u8 *owe_buf, size_t owe_buf_len, u16 *reason); +u16 owe_process_rsn_ie(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *rsn_ie, size_t rsn_ie_len, + const u8 *owe_dh, size_t owe_dh_len); +u16 owe_validate_request(struct hostapd_data *hapd, const u8 *peer, + const u8 *rsn_ie, size_t rsn_ie_len, + const u8 *owe_dh, size_t owe_dh_len); +void fils_hlp_timeout(void *eloop_ctx, void *eloop_data); +void fils_hlp_finish_assoc(struct hostapd_data *hapd, struct sta_info *sta); +void handle_auth_fils(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *pos, size_t len, u16 auth_alg, + u16 auth_transaction, u16 status_code, + void (*cb)(struct hostapd_data *hapd, + struct sta_info *sta, + u16 resp, struct wpabuf *data, int pub)); + +size_t hostapd_eid_owe_trans_len(struct hostapd_data *hapd); +u8 * hostapd_eid_owe_trans(struct hostapd_data *hapd, u8 *eid, size_t len); +int ieee802_11_allowed_address(struct hostapd_data *hapd, const u8 *addr, + const u8 *msg, size_t len, u32 *session_timeout, + u32 *acct_interim_interval, + struct vlan_description *vlan_id, + struct hostapd_sta_wpa_psk_short **psk, + char **identity, char **radius_cui, + int is_probe_req); + +int get_tx_parameters(struct sta_info *sta, int ap_max_chanwidth, + int ap_seg1_idx, int *bandwidth, int *seg1_idx); + +void auth_sae_process_commit(void *eloop_ctx, void *user_ctx); + +#endif /* IEEE802_11_H */ diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ieee802_11_auth.c b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ieee802_11_auth.c new file mode 100755 index 0000000..874c218 --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ieee802_11_auth.c @@ -0,0 +1,702 @@ +/* + * hostapd / IEEE 802.11 authentication (ACL) + * Copyright (c) 2003-2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + * + * Access control list for IEEE 802.11 authentication can uses statically + * configured ACL from configuration files or an external RADIUS server. + * Results from external RADIUS queries are cached to allow faster + * authentication frame processing. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "utils/eloop.h" +#include "crypto/sha1.h" +#include "ap/hostapd.h" +#include "ap_config.h" +#include "ap_drv_ops.h" +#include "ieee802_11.h" +#include "ieee802_1x.h" +#include "ieee802_11_auth.h" + +#define RADIUS_ACL_TIMEOUT 30 + + +struct hostapd_cached_radius_acl { + struct os_reltime timestamp; + macaddr addr; + int accepted; /* HOSTAPD_ACL_* */ + struct hostapd_cached_radius_acl *next; + u32 session_timeout; + u32 acct_interim_interval; + struct vlan_description vlan_id; + struct hostapd_sta_wpa_psk_short *psk; + char *identity; + char *radius_cui; +}; + + +struct hostapd_acl_query_data { + struct os_reltime timestamp; + u8 radius_id; + macaddr addr; + u8 *auth_msg; /* IEEE 802.11 authentication frame from station */ + size_t auth_msg_len; + struct hostapd_acl_query_data *next; +}; + + +#ifndef CONFIG_NO_RADIUS +static void hostapd_acl_cache_free_entry(struct hostapd_cached_radius_acl *e) +{ + os_free(e->identity); + os_free(e->radius_cui); + hostapd_free_psk_list(e->psk); + os_free(e); +} + + +static void hostapd_acl_cache_free(struct hostapd_cached_radius_acl *acl_cache) +{ + struct hostapd_cached_radius_acl *prev; + + while (acl_cache) { + prev = acl_cache; + acl_cache = acl_cache->next; + hostapd_acl_cache_free_entry(prev); + } +} + + +static void copy_psk_list(struct hostapd_sta_wpa_psk_short **psk, + struct hostapd_sta_wpa_psk_short *src) +{ + if (!psk) + return; + + if (src) + src->ref++; + + *psk = src; +} + + +static int hostapd_acl_cache_get(struct hostapd_data *hapd, const u8 *addr, + u32 *session_timeout, + u32 *acct_interim_interval, + struct vlan_description *vlan_id, + struct hostapd_sta_wpa_psk_short **psk, + char **identity, char **radius_cui) +{ + struct hostapd_cached_radius_acl *entry; + struct os_reltime now; + + os_get_reltime(&now); + + for (entry = hapd->acl_cache; entry; entry = entry->next) { + if (os_memcmp(entry->addr, addr, ETH_ALEN) != 0) + continue; + + if (os_reltime_expired(&now, &entry->timestamp, + RADIUS_ACL_TIMEOUT)) + return -1; /* entry has expired */ + if (entry->accepted == HOSTAPD_ACL_ACCEPT_TIMEOUT) + if (session_timeout) + *session_timeout = entry->session_timeout; + if (acct_interim_interval) + *acct_interim_interval = + entry->acct_interim_interval; + if (vlan_id) + *vlan_id = entry->vlan_id; + copy_psk_list(psk, entry->psk); + if (identity) { + if (entry->identity) + *identity = os_strdup(entry->identity); + else + *identity = NULL; + } + if (radius_cui) { + if (entry->radius_cui) + *radius_cui = os_strdup(entry->radius_cui); + else + *radius_cui = NULL; + } + return entry->accepted; + } + + return -1; +} +#endif /* CONFIG_NO_RADIUS */ + + +static void hostapd_acl_query_free(struct hostapd_acl_query_data *query) +{ + if (query == NULL) + return; + os_free(query->auth_msg); + os_free(query); +} + + +#ifndef CONFIG_NO_RADIUS +static int hostapd_radius_acl_query(struct hostapd_data *hapd, const u8 *addr, + struct hostapd_acl_query_data *query) +{ + struct radius_msg *msg; + char buf[128]; + + query->radius_id = radius_client_get_id(hapd->radius); + msg = radius_msg_new(RADIUS_CODE_ACCESS_REQUEST, query->radius_id); + if (msg == NULL) + return -1; + + if (radius_msg_make_authenticator(msg) < 0) { + wpa_printf(MSG_INFO, "Could not make Request Authenticator"); + goto fail; + } + + os_snprintf(buf, sizeof(buf), RADIUS_ADDR_FORMAT, MAC2STR(addr)); + if (!radius_msg_add_attr(msg, RADIUS_ATTR_USER_NAME, (u8 *) buf, + os_strlen(buf))) { + wpa_printf(MSG_DEBUG, "Could not add User-Name"); + goto fail; + } + + if (!radius_msg_add_attr_user_password( + msg, (u8 *) buf, os_strlen(buf), + hapd->conf->radius->auth_server->shared_secret, + hapd->conf->radius->auth_server->shared_secret_len)) { + wpa_printf(MSG_DEBUG, "Could not add User-Password"); + goto fail; + } + + if (add_common_radius_attr(hapd, hapd->conf->radius_auth_req_attr, + NULL, msg) < 0) + goto fail; + + os_snprintf(buf, sizeof(buf), RADIUS_802_1X_ADDR_FORMAT, + MAC2STR(addr)); + if (!radius_msg_add_attr(msg, RADIUS_ATTR_CALLING_STATION_ID, + (u8 *) buf, os_strlen(buf))) { + wpa_printf(MSG_DEBUG, "Could not add Calling-Station-Id"); + goto fail; + } + + os_snprintf(buf, sizeof(buf), "CONNECT 11Mbps 802.11b"); + if (!radius_msg_add_attr(msg, RADIUS_ATTR_CONNECT_INFO, + (u8 *) buf, os_strlen(buf))) { + wpa_printf(MSG_DEBUG, "Could not add Connect-Info"); + goto fail; + } + + if (radius_client_send(hapd->radius, msg, RADIUS_AUTH, addr) < 0) + goto fail; + return 0; + + fail: + radius_msg_free(msg); + return -1; +} +#endif /* CONFIG_NO_RADIUS */ + + +#ifdef CONFIG_HOSTAPD_ACL +/** + * hostapd_check_acl - Check a specified STA against accept/deny ACLs + * @hapd: hostapd BSS data + * @addr: MAC address of the STA + * @vlan_id: Buffer for returning VLAN ID + * Returns: HOSTAPD_ACL_ACCEPT, HOSTAPD_ACL_REJECT, or HOSTAPD_ACL_PENDING + */ +int hostapd_check_acl(struct hostapd_data *hapd, const u8 *addr, + struct vlan_description *vlan_id) +{ + if (hostapd_maclist_found(hapd->conf->accept_mac, + hapd->conf->num_accept_mac, addr, vlan_id)) + return HOSTAPD_ACL_ACCEPT; + + if (hostapd_maclist_found(hapd->conf->deny_mac, + hapd->conf->num_deny_mac, addr, vlan_id)) + return HOSTAPD_ACL_REJECT; + + if (hapd->conf->macaddr_acl == ACCEPT_UNLESS_DENIED) + return HOSTAPD_ACL_ACCEPT; + if (hapd->conf->macaddr_acl == DENY_UNLESS_ACCEPTED) + return HOSTAPD_ACL_REJECT; + + return HOSTAPD_ACL_PENDING; +} + + +/** + * hostapd_allowed_address - Check whether a specified STA can be authenticated + * @hapd: hostapd BSS data + * @addr: MAC address of the STA + * @msg: Authentication message + * @len: Length of msg in octets + * @session_timeout: Buffer for returning session timeout (from RADIUS) + * @acct_interim_interval: Buffer for returning account interval (from RADIUS) + * @vlan_id: Buffer for returning VLAN ID + * @psk: Linked list buffer for returning WPA PSK + * @identity: Buffer for returning identity (from RADIUS) + * @radius_cui: Buffer for returning CUI (from RADIUS) + * @is_probe_req: Whether this query for a Probe Request frame + * Returns: HOSTAPD_ACL_ACCEPT, HOSTAPD_ACL_REJECT, or HOSTAPD_ACL_PENDING + * + * The caller is responsible for freeing the returned *identity and *radius_cui + * values with os_free(). + */ +int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr, + const u8 *msg, size_t len, u32 *session_timeout, + u32 *acct_interim_interval, + struct vlan_description *vlan_id, + struct hostapd_sta_wpa_psk_short **psk, + char **identity, char **radius_cui, + int is_probe_req) +{ + int res; + + if (session_timeout) + *session_timeout = 0; + if (acct_interim_interval) + *acct_interim_interval = 0; + if (vlan_id) + os_memset(vlan_id, 0, sizeof(*vlan_id)); + if (psk) + *psk = NULL; + if (identity) + *identity = NULL; + if (radius_cui) + *radius_cui = NULL; + + res = hostapd_check_acl(hapd, addr, vlan_id); + if (res != HOSTAPD_ACL_PENDING) + return res; + + if (hapd->conf->macaddr_acl == USE_EXTERNAL_RADIUS_AUTH) { +#ifdef CONFIG_NO_RADIUS + return HOSTAPD_ACL_REJECT; +#else /* CONFIG_NO_RADIUS */ + struct hostapd_acl_query_data *query; + + if (is_probe_req) { + /* Skip RADIUS queries for Probe Request frames to avoid + * excessive load on the authentication server. */ + return HOSTAPD_ACL_ACCEPT; + }; + + if (hapd->conf->ssid.dynamic_vlan == DYNAMIC_VLAN_DISABLED) + vlan_id = NULL; + + /* Check whether ACL cache has an entry for this station */ + res = hostapd_acl_cache_get(hapd, addr, session_timeout, + acct_interim_interval, vlan_id, psk, + identity, radius_cui); + if (res == HOSTAPD_ACL_ACCEPT || + res == HOSTAPD_ACL_ACCEPT_TIMEOUT) + return res; + if (res == HOSTAPD_ACL_REJECT) + return HOSTAPD_ACL_REJECT; + + query = hapd->acl_queries; + while (query) { + if (os_memcmp(query->addr, addr, ETH_ALEN) == 0) { + /* pending query in RADIUS retransmit queue; + * do not generate a new one */ + if (identity) { + os_free(*identity); + *identity = NULL; + } + if (radius_cui) { + os_free(*radius_cui); + *radius_cui = NULL; + } + return HOSTAPD_ACL_PENDING; + } + query = query->next; + } + + if (!hapd->conf->radius->auth_server) + return HOSTAPD_ACL_REJECT; + + /* No entry in the cache - query external RADIUS server */ + query = os_zalloc(sizeof(*query)); + if (query == NULL) { + wpa_printf(MSG_ERROR, "malloc for query data failed"); + return HOSTAPD_ACL_REJECT; + } + os_get_reltime(&query->timestamp); + os_memcpy(query->addr, addr, ETH_ALEN); + if (hostapd_radius_acl_query(hapd, addr, query)) { + wpa_printf(MSG_DEBUG, "Failed to send Access-Request " + "for ACL query."); + hostapd_acl_query_free(query); + return HOSTAPD_ACL_REJECT; + } + + query->auth_msg = os_memdup(msg, len); + if (query->auth_msg == NULL) { + wpa_printf(MSG_ERROR, "Failed to allocate memory for " + "auth frame."); + hostapd_acl_query_free(query); + return HOSTAPD_ACL_REJECT; + } + query->auth_msg_len = len; + query->next = hapd->acl_queries; + hapd->acl_queries = query; + + /* Queued data will be processed in hostapd_acl_recv_radius() + * when RADIUS server replies to the sent Access-Request. */ + return HOSTAPD_ACL_PENDING; +#endif /* CONFIG_NO_RADIUS */ + } + + return HOSTAPD_ACL_REJECT; +} +#endif + +#ifndef CONFIG_NO_RADIUS +static void hostapd_acl_expire_cache(struct hostapd_data *hapd, + struct os_reltime *now) +{ + struct hostapd_cached_radius_acl *prev, *entry, *tmp; + + prev = NULL; + entry = hapd->acl_cache; + + while (entry) { + if (os_reltime_expired(now, &entry->timestamp, + RADIUS_ACL_TIMEOUT)) { + wpa_printf(MSG_DEBUG, "Cached ACL entry for " MACSTR + " has expired.", MAC2STR(entry->addr)); + if (prev) + prev->next = entry->next; + else + hapd->acl_cache = entry->next; + hostapd_drv_set_radius_acl_expire(hapd, entry->addr); + tmp = entry; + entry = entry->next; + hostapd_acl_cache_free_entry(tmp); + continue; + } + + prev = entry; + entry = entry->next; + } +} + + +static void hostapd_acl_expire_queries(struct hostapd_data *hapd, + struct os_reltime *now) +{ + struct hostapd_acl_query_data *prev, *entry, *tmp; + + prev = NULL; + entry = hapd->acl_queries; + + while (entry) { + if (os_reltime_expired(now, &entry->timestamp, + RADIUS_ACL_TIMEOUT)) { + wpa_printf(MSG_DEBUG, "ACL query for " MACSTR + " has expired.", MAC2STR(entry->addr)); + if (prev) + prev->next = entry->next; + else + hapd->acl_queries = entry->next; + + tmp = entry; + entry = entry->next; + hostapd_acl_query_free(tmp); + continue; + } + + prev = entry; + entry = entry->next; + } +} + + +/** + * hostapd_acl_expire - ACL cache expiration callback + * @hapd: struct hostapd_data * + */ +void hostapd_acl_expire(struct hostapd_data *hapd) +{ + struct os_reltime now; + + os_get_reltime(&now); + hostapd_acl_expire_cache(hapd, &now); + hostapd_acl_expire_queries(hapd, &now); +} + + +static void decode_tunnel_passwords(struct hostapd_data *hapd, + const u8 *shared_secret, + size_t shared_secret_len, + struct radius_msg *msg, + struct radius_msg *req, + struct hostapd_cached_radius_acl *cache) +{ + int passphraselen; + char *passphrase; + size_t i; + struct hostapd_sta_wpa_psk_short *psk; + + /* + * Decode all tunnel passwords as PSK and save them into a linked list. + */ + for (i = 0; ; i++) { + passphrase = radius_msg_get_tunnel_password( + msg, &passphraselen, shared_secret, shared_secret_len, + req, i); + /* + * Passphrase is NULL iff there is no i-th Tunnel-Password + * attribute in msg. + */ + if (passphrase == NULL) + break; + + /* + * Passphase should be 8..63 chars (to be hashed with SSID) + * or 64 chars hex string (no separate hashing with SSID). + */ + + if (passphraselen < MIN_PASSPHRASE_LEN || + passphraselen > MAX_PASSPHRASE_LEN + 1) + goto free_pass; + + /* + * passphrase does not contain the NULL termination. + * Add it here as pbkdf2_sha1() requires it. + */ + psk = os_zalloc(sizeof(struct hostapd_sta_wpa_psk_short)); + if (psk) { + if ((passphraselen == MAX_PASSPHRASE_LEN + 1) && + (hexstr2bin(passphrase, psk->psk, PMK_LEN) < 0)) { + hostapd_logger(hapd, cache->addr, + HOSTAPD_MODULE_RADIUS, + HOSTAPD_LEVEL_WARNING, + "invalid hex string (%d chars) in Tunnel-Password", + passphraselen); + goto skip; + } else if (passphraselen <= MAX_PASSPHRASE_LEN) { + os_memcpy(psk->passphrase, passphrase, + passphraselen); + psk->is_passphrase = 1; + } + psk->next = cache->psk; + cache->psk = psk; + psk = NULL; + } +skip: + os_free(psk); +free_pass: + os_free(passphrase); + } +} + + +/** + * hostapd_acl_recv_radius - Process incoming RADIUS Authentication messages + * @msg: RADIUS response message + * @req: RADIUS request message + * @shared_secret: RADIUS shared secret + * @shared_secret_len: Length of shared_secret in octets + * @data: Context data (struct hostapd_data *) + * Returns: RADIUS_RX_PROCESSED if RADIUS message was a reply to ACL query (and + * was processed here) or RADIUS_RX_UNKNOWN if not. + */ +static RadiusRxResult +hostapd_acl_recv_radius(struct radius_msg *msg, struct radius_msg *req, + const u8 *shared_secret, size_t shared_secret_len, + void *data) +{ + struct hostapd_data *hapd = data; + struct hostapd_acl_query_data *query, *prev; + struct hostapd_cached_radius_acl *cache; + struct radius_hdr *hdr = radius_msg_get_hdr(msg); + + query = hapd->acl_queries; + prev = NULL; + while (query) { + if (query->radius_id == hdr->identifier) + break; + prev = query; + query = query->next; + } + if (query == NULL) + return RADIUS_RX_UNKNOWN; + + wpa_printf(MSG_DEBUG, "Found matching Access-Request for RADIUS " + "message (id=%d)", query->radius_id); + + if (radius_msg_verify(msg, shared_secret, shared_secret_len, req, 0)) { + wpa_printf(MSG_INFO, "Incoming RADIUS packet did not have " + "correct authenticator - dropped\n"); + return RADIUS_RX_INVALID_AUTHENTICATOR; + } + + if (hdr->code != RADIUS_CODE_ACCESS_ACCEPT && + hdr->code != RADIUS_CODE_ACCESS_REJECT) { + wpa_printf(MSG_DEBUG, "Unknown RADIUS message code %d to ACL " + "query", hdr->code); + return RADIUS_RX_UNKNOWN; + } + + /* Insert Accept/Reject info into ACL cache */ + cache = os_zalloc(sizeof(*cache)); + if (cache == NULL) { + wpa_printf(MSG_DEBUG, "Failed to add ACL cache entry"); + goto done; + } + os_get_reltime(&cache->timestamp); + os_memcpy(cache->addr, query->addr, sizeof(cache->addr)); + if (hdr->code == RADIUS_CODE_ACCESS_ACCEPT) { + u8 *buf; + size_t len; + + if (radius_msg_get_attr_int32(msg, RADIUS_ATTR_SESSION_TIMEOUT, + &cache->session_timeout) == 0) + cache->accepted = HOSTAPD_ACL_ACCEPT_TIMEOUT; + else + cache->accepted = HOSTAPD_ACL_ACCEPT; + + if (radius_msg_get_attr_int32( + msg, RADIUS_ATTR_ACCT_INTERIM_INTERVAL, + &cache->acct_interim_interval) == 0 && + cache->acct_interim_interval < 60) { + wpa_printf(MSG_DEBUG, "Ignored too small " + "Acct-Interim-Interval %d for STA " MACSTR, + cache->acct_interim_interval, + MAC2STR(query->addr)); + cache->acct_interim_interval = 0; + } + + if (hapd->conf->ssid.dynamic_vlan != DYNAMIC_VLAN_DISABLED) + cache->vlan_id.notempty = !!radius_msg_get_vlanid( + msg, &cache->vlan_id.untagged, + MAX_NUM_TAGGED_VLAN, cache->vlan_id.tagged); + + decode_tunnel_passwords(hapd, shared_secret, shared_secret_len, + msg, req, cache); + + if (radius_msg_get_attr_ptr(msg, RADIUS_ATTR_USER_NAME, + &buf, &len, NULL) == 0) { + cache->identity = os_zalloc(len + 1); + if (cache->identity) + os_memcpy(cache->identity, buf, len); + } + if (radius_msg_get_attr_ptr( + msg, RADIUS_ATTR_CHARGEABLE_USER_IDENTITY, + &buf, &len, NULL) == 0) { + cache->radius_cui = os_zalloc(len + 1); + if (cache->radius_cui) + os_memcpy(cache->radius_cui, buf, len); + } + + if (hapd->conf->wpa_psk_radius == PSK_RADIUS_REQUIRED && + !cache->psk) + cache->accepted = HOSTAPD_ACL_REJECT; + + if (cache->vlan_id.notempty && + !hostapd_vlan_valid(hapd->conf->vlan, &cache->vlan_id)) { + hostapd_logger(hapd, query->addr, + HOSTAPD_MODULE_RADIUS, + HOSTAPD_LEVEL_INFO, + "Invalid VLAN %d%s received from RADIUS server", + cache->vlan_id.untagged, + cache->vlan_id.tagged[0] ? "+" : ""); + os_memset(&cache->vlan_id, 0, sizeof(cache->vlan_id)); + } + if (hapd->conf->ssid.dynamic_vlan == DYNAMIC_VLAN_REQUIRED && + !cache->vlan_id.notempty) + cache->accepted = HOSTAPD_ACL_REJECT; + } else + cache->accepted = HOSTAPD_ACL_REJECT; + cache->next = hapd->acl_cache; + hapd->acl_cache = cache; + +#ifdef CONFIG_DRIVER_RADIUS_ACL + hostapd_drv_set_radius_acl_auth(hapd, query->addr, cache->accepted, + cache->session_timeout); +#else /* CONFIG_DRIVER_RADIUS_ACL */ +#ifdef NEED_AP_MLME + /* Re-send original authentication frame for 802.11 processing */ + wpa_printf(MSG_DEBUG, "Re-sending authentication frame after " + "successful RADIUS ACL query"); + ieee802_11_mgmt(hapd, query->auth_msg, query->auth_msg_len, NULL); +#endif /* NEED_AP_MLME */ +#endif /* CONFIG_DRIVER_RADIUS_ACL */ + + done: + if (prev == NULL) + hapd->acl_queries = query->next; + else + prev->next = query->next; + + hostapd_acl_query_free(query); + + return RADIUS_RX_PROCESSED; +} +#endif /* CONFIG_NO_RADIUS */ + + +/** + * hostapd_acl_init: Initialize IEEE 802.11 ACL + * @hapd: hostapd BSS data + * Returns: 0 on success, -1 on failure + */ +int hostapd_acl_init(struct hostapd_data *hapd) +{ +#ifndef CONFIG_NO_RADIUS + if (radius_client_register(hapd->radius, RADIUS_AUTH, + hostapd_acl_recv_radius, hapd)) + return -1; +#endif /* CONFIG_NO_RADIUS */ + + return 0; +} + + +#ifdef CONFIG_FULL_HOSTAPD +/** + * hostapd_acl_deinit - Deinitialize IEEE 802.11 ACL + * @hapd: hostapd BSS data + */ +void hostapd_acl_deinit(struct hostapd_data *hapd) +{ + struct hostapd_acl_query_data *query, *prev; + +#ifndef CONFIG_NO_RADIUS + hostapd_acl_cache_free(hapd->acl_cache); + hapd->acl_cache = NULL; +#endif /* CONFIG_NO_RADIUS */ + + query = hapd->acl_queries; + hapd->acl_queries = NULL; + while (query) { + prev = query; + query = query->next; + hostapd_acl_query_free(prev); + } +} +#endif + +void hostapd_free_psk_list(struct hostapd_sta_wpa_psk_short *psk) +{ + if (psk && psk->ref) { + /* This will be freed when the last reference is dropped. */ + psk->ref--; + return; + } + + while (psk) { + struct hostapd_sta_wpa_psk_short *prev = psk; + psk = psk->next; + os_free(prev); + } +} diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ieee802_11_auth.h b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ieee802_11_auth.h new file mode 100755 index 0000000..5aece51 --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ieee802_11_auth.h @@ -0,0 +1,33 @@ +/* + * hostapd / IEEE 802.11 authentication (ACL) + * Copyright (c) 2003-2005, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef IEEE802_11_AUTH_H +#define IEEE802_11_AUTH_H + +enum { + HOSTAPD_ACL_REJECT = 0, + HOSTAPD_ACL_ACCEPT = 1, + HOSTAPD_ACL_PENDING = 2, + HOSTAPD_ACL_ACCEPT_TIMEOUT = 3 +}; + +int hostapd_check_acl(struct hostapd_data *hapd, const u8 *addr, + struct vlan_description *vlan_id); +int hostapd_allowed_address(struct hostapd_data *hapd, const u8 *addr, + const u8 *msg, size_t len, u32 *session_timeout, + u32 *acct_interim_interval, + struct vlan_description *vlan_id, + struct hostapd_sta_wpa_psk_short **psk, + char **identity, char **radius_cui, + int is_probe_req); +int hostapd_acl_init(struct hostapd_data *hapd); +void hostapd_acl_deinit(struct hostapd_data *hapd); +void hostapd_free_psk_list(struct hostapd_sta_wpa_psk_short *psk); +void hostapd_acl_expire(struct hostapd_data *hapd); + +#endif /* IEEE802_11_AUTH_H */ diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ieee802_11_he.c b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ieee802_11_he.c new file mode 100755 index 0000000..a51f3fc --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ieee802_11_he.c @@ -0,0 +1,348 @@ +/* + * hostapd / IEEE 802.11ax HE + * Copyright (c) 2016-2017, Qualcomm Atheros, Inc. + * Copyright (c) 2019 John Crispin + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "common/ieee802_11_defs.h" +#include "hostapd.h" +#include "ap_config.h" +#include "beacon.h" +#include "sta_info.h" +#include "ieee802_11.h" +#include "dfs.h" + +static u8 ieee80211_he_ppet_size(u8 ppe_thres_hdr, const u8 *phy_cap_info) +{ + u8 sz = 0, ru; + + if ((phy_cap_info[HE_PHYCAP_PPE_THRESHOLD_PRESENT_IDX] & + HE_PHYCAP_PPE_THRESHOLD_PRESENT) == 0) + return 0; + + ru = (ppe_thres_hdr >> HE_PPE_THRES_RU_INDEX_BITMASK_SHIFT) & + HE_PPE_THRES_RU_INDEX_BITMASK_MASK; + while (ru) { + if (ru & 0x1) + sz++; + ru >>= 1; + } + + sz *= 1 + (ppe_thres_hdr & HE_PPE_THRES_NSS_MASK); + sz = (sz * 6) + 7; + if (sz % 8) + sz += 8; + sz /= 8; + + return sz; +} + + +u8 * hostapd_eid_he_capab(struct hostapd_data *hapd, u8 *eid, + enum ieee80211_op_mode opmode) +{ + struct ieee80211_he_capabilities *cap; + struct hostapd_hw_modes *mode = hapd->iface->current_mode; + u8 he_oper_chwidth = ~HE_PHYCAP_CHANNEL_WIDTH_MASK; + u8 *pos = eid; + u8 ie_size = 0, mcs_nss_size = 0, ppet_size = 0; + + if (!mode) + return eid; + + ie_size = sizeof(struct ieee80211_he_capabilities); + ppet_size = ieee80211_he_ppet_size(mode->he_capab[opmode].ppet[0], + mode->he_capab[opmode].phy_cap); + + switch (hapd->iface->conf->he_oper_chwidth) { + case CHANWIDTH_80P80MHZ: + he_oper_chwidth |= + HE_PHYCAP_CHANNEL_WIDTH_SET_80PLUS80MHZ_IN_5G; + mcs_nss_size += 4; + /* fall through */ + case CHANWIDTH_160MHZ: + he_oper_chwidth |= HE_PHYCAP_CHANNEL_WIDTH_SET_160MHZ_IN_5G; + mcs_nss_size += 4; + /* fall through */ + case CHANWIDTH_80MHZ: + case CHANWIDTH_USE_HT: + he_oper_chwidth |= HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_IN_2G | + HE_PHYCAP_CHANNEL_WIDTH_SET_40MHZ_80MHZ_IN_5G; + mcs_nss_size += 4; + break; + } + + ie_size += mcs_nss_size + ppet_size; + + *pos++ = WLAN_EID_EXTENSION; + *pos++ = 1 + ie_size; + *pos++ = WLAN_EID_EXT_HE_CAPABILITIES; + + cap = (struct ieee80211_he_capabilities *) pos; + os_memset(cap, 0, sizeof(*cap)); + + os_memcpy(cap->he_mac_capab_info, mode->he_capab[opmode].mac_cap, + HE_MAX_MAC_CAPAB_SIZE); + os_memcpy(cap->he_phy_capab_info, mode->he_capab[opmode].phy_cap, + HE_MAX_PHY_CAPAB_SIZE); + os_memcpy(cap->optional, mode->he_capab[opmode].mcs, mcs_nss_size); + if (ppet_size) + os_memcpy(&cap->optional[mcs_nss_size], + mode->he_capab[opmode].ppet, ppet_size); + + if (hapd->iface->conf->he_phy_capab.he_su_beamformer) + cap->he_phy_capab_info[HE_PHYCAP_SU_BEAMFORMER_CAPAB_IDX] |= + HE_PHYCAP_SU_BEAMFORMER_CAPAB; + else + cap->he_phy_capab_info[HE_PHYCAP_SU_BEAMFORMER_CAPAB_IDX] &= + ~HE_PHYCAP_SU_BEAMFORMER_CAPAB; + + if (hapd->iface->conf->he_phy_capab.he_su_beamformee) + cap->he_phy_capab_info[HE_PHYCAP_SU_BEAMFORMEE_CAPAB_IDX] |= + HE_PHYCAP_SU_BEAMFORMEE_CAPAB; + else + cap->he_phy_capab_info[HE_PHYCAP_SU_BEAMFORMEE_CAPAB_IDX] &= + ~HE_PHYCAP_SU_BEAMFORMEE_CAPAB; + + if (hapd->iface->conf->he_phy_capab.he_mu_beamformer) + cap->he_phy_capab_info[HE_PHYCAP_MU_BEAMFORMER_CAPAB_IDX] |= + HE_PHYCAP_MU_BEAMFORMER_CAPAB; + else + cap->he_phy_capab_info[HE_PHYCAP_MU_BEAMFORMER_CAPAB_IDX] &= + ~HE_PHYCAP_MU_BEAMFORMER_CAPAB; + + cap->he_phy_capab_info[HE_PHYCAP_CHANNEL_WIDTH_SET_IDX] &= + he_oper_chwidth; + + pos += ie_size; + + return pos; +} + + +u8 * hostapd_eid_he_operation(struct hostapd_data *hapd, u8 *eid) +{ + struct ieee80211_he_operation *oper; + u8 *pos = eid; + int oper_size = 6; + u32 params = 0; + + if (!hapd->iface->current_mode) + return eid; + + *pos++ = WLAN_EID_EXTENSION; + *pos++ = 1 + oper_size; + *pos++ = WLAN_EID_EXT_HE_OPERATION; + + oper = (struct ieee80211_he_operation *) pos; + os_memset(oper, 0, sizeof(*oper)); + + if (hapd->iface->conf->he_op.he_default_pe_duration) + params |= (hapd->iface->conf->he_op.he_default_pe_duration << + HE_OPERATION_DFLT_PE_DURATION_OFFSET); + + if (hapd->iface->conf->he_op.he_twt_required) + params |= HE_OPERATION_TWT_REQUIRED; + + if (hapd->iface->conf->he_op.he_rts_threshold) + params |= (hapd->iface->conf->he_op.he_rts_threshold << + HE_OPERATION_RTS_THRESHOLD_OFFSET); + + if (hapd->iface->conf->he_op.he_bss_color) + params |= (hapd->iface->conf->he_op.he_bss_color << + HE_OPERATION_BSS_COLOR_OFFSET); + + /* HE minimum required basic MCS and NSS for STAs */ + oper->he_mcs_nss_set = + host_to_le16(hapd->iface->conf->he_op.he_basic_mcs_nss_set); + + /* TODO: conditional MaxBSSID Indicator subfield */ + + oper->he_oper_params = host_to_le32(params); + + pos += oper_size; + + return pos; +} + + +u8 * hostapd_eid_he_mu_edca_parameter_set(struct hostapd_data *hapd, u8 *eid) +{ + struct ieee80211_he_mu_edca_parameter_set *edca; + u8 *pos; + size_t i; + + pos = (u8 *) &hapd->iface->conf->he_mu_edca; + for (i = 0; i < sizeof(*edca); i++) { + if (pos[i]) + break; + } + if (i == sizeof(*edca)) + return eid; /* no MU EDCA Parameters configured */ + + pos = eid; + *pos++ = WLAN_EID_EXTENSION; + *pos++ = 1 + sizeof(*edca); + *pos++ = WLAN_EID_EXT_HE_MU_EDCA_PARAMS; + + edca = (struct ieee80211_he_mu_edca_parameter_set *) pos; + os_memcpy(edca, &hapd->iface->conf->he_mu_edca, sizeof(*edca)); + + wpa_hexdump(MSG_DEBUG, "HE: MU EDCA Parameter Set element", + pos, sizeof(*edca)); + + pos += sizeof(*edca); + + return pos; +} + + +u8 * hostapd_eid_spatial_reuse(struct hostapd_data *hapd, u8 *eid) +{ + struct ieee80211_spatial_reuse *spr; + u8 *pos = eid, *spr_param; + u8 sz = 1; + + if (!hapd->iface->conf->spr.sr_control) + return eid; + + if (hapd->iface->conf->spr.sr_control & + SPATIAL_REUSE_NON_SRG_OFFSET_PRESENT) + sz++; + + if (hapd->iface->conf->spr.sr_control & + SPATIAL_REUSE_SRG_INFORMATION_PRESENT) + sz += 18; + + *pos++ = WLAN_EID_EXTENSION; + *pos++ = 1 + sz; + *pos++ = WLAN_EID_EXT_SPATIAL_REUSE; + + spr = (struct ieee80211_spatial_reuse *) pos; + os_memset(spr, 0, sizeof(*spr)); + + spr->sr_ctrl = hapd->iface->conf->spr.sr_control; + pos++; + spr_param = spr->params; + if (spr->sr_ctrl & SPATIAL_REUSE_NON_SRG_OFFSET_PRESENT) { + *spr_param++ = + hapd->iface->conf->spr.non_srg_obss_pd_max_offset; + pos++; + } + if (spr->sr_ctrl & SPATIAL_REUSE_SRG_INFORMATION_PRESENT) { + *spr_param++ = hapd->iface->conf->spr.srg_obss_pd_min_offset; + *spr_param++ = hapd->iface->conf->spr.srg_obss_pd_max_offset; + pos += 18; + } + + return pos; +} + + +void hostapd_get_he_capab(struct hostapd_data *hapd, + const struct ieee80211_he_capabilities *he_cap, + struct ieee80211_he_capabilities *neg_he_cap, + size_t he_capab_len) +{ + if (!he_cap) + return; + + if (he_capab_len > sizeof(*neg_he_cap)) + he_capab_len = sizeof(*neg_he_cap); + /* TODO: mask out unsupported features */ + + os_memcpy(neg_he_cap, he_cap, he_capab_len); +} + + +static int check_valid_he_mcs(struct hostapd_data *hapd, const u8 *sta_he_capab, + enum ieee80211_op_mode opmode) +{ + u16 sta_rx_mcs_set, ap_tx_mcs_set; + u8 mcs_count = 0; + const u16 *ap_mcs_set, *sta_mcs_set; + int i; + + if (!hapd->iface->current_mode) + return 1; + ap_mcs_set = (u16 *) hapd->iface->current_mode->he_capab[opmode].mcs; + sta_mcs_set = (u16 *) ((const struct ieee80211_he_capabilities *) + sta_he_capab)->optional; + + /* + * Disable HE capabilities for STAs for which there is not even a single + * allowed MCS in any supported number of streams, i.e., STA is + * advertising 3 (not supported) as HE MCS rates for all supported + * band/stream cases. + */ + switch (hapd->iface->conf->he_oper_chwidth) { + case CHANWIDTH_80P80MHZ: + mcs_count = 3; + break; + case CHANWIDTH_160MHZ: + mcs_count = 2; + break; + default: + mcs_count = 1; + break; + } + + for (i = 0; i < mcs_count; i++) { + int j; + + /* AP Tx MCS map vs. STA Rx MCS map */ + sta_rx_mcs_set = WPA_GET_LE16((const u8 *) &sta_mcs_set[i * 2]); + ap_tx_mcs_set = WPA_GET_LE16((const u8 *) + &ap_mcs_set[(i * 2) + 1]); + + for (j = 0; j < HE_NSS_MAX_STREAMS; j++) { + if (((ap_tx_mcs_set >> (j * 2)) & 0x3) == 3) + continue; + + if (((sta_rx_mcs_set >> (j * 2)) & 0x3) == 3) + continue; + + return 1; + } + } + + wpa_printf(MSG_DEBUG, + "No matching HE MCS found between AP TX and STA RX"); + + return 0; +} + + +u16 copy_sta_he_capab(struct hostapd_data *hapd, struct sta_info *sta, + enum ieee80211_op_mode opmode, const u8 *he_capab, + size_t he_capab_len) +{ + if (!he_capab || !hapd->iconf->ieee80211ax || + !check_valid_he_mcs(hapd, he_capab, opmode) || + he_capab_len > sizeof(struct ieee80211_he_capabilities)) { + sta->flags &= ~WLAN_STA_HE; + os_free(sta->he_capab); + sta->he_capab = NULL; + return WLAN_STATUS_SUCCESS; + } + + if (!sta->he_capab) { + sta->he_capab = + os_zalloc(sizeof(struct ieee80211_he_capabilities)); + if (!sta->he_capab) + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + + sta->flags |= WLAN_STA_HE; + os_memset(sta->he_capab, 0, sizeof(struct ieee80211_he_capabilities)); + os_memcpy(sta->he_capab, he_capab, he_capab_len); + sta->he_capab_len = he_capab_len; + + return WLAN_STATUS_SUCCESS; +} diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ieee802_11_ht.c b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ieee802_11_ht.c new file mode 100755 index 0000000..73903a2 --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ieee802_11_ht.c @@ -0,0 +1,563 @@ +/* + * hostapd / IEEE 802.11n HT + * Copyright (c) 2002-2009, Jouni Malinen + * Copyright (c) 2007-2008, Intel Corporation + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "utils/eloop.h" +#include "common/ieee802_11_defs.h" +#include "ap/hostapd.h" +#include "ap_config.h" +#include "ap/sta_info.h" +#include "beacon.h" +#include "ieee802_11.h" +#include "hw_features.h" +#include "ap_drv_ops.h" + + +u8 * hostapd_eid_ht_capabilities(struct hostapd_data *hapd, u8 *eid) +{ + struct ieee80211_ht_capabilities *cap; + u8 *pos = eid; + + if (!hapd->iconf->ieee80211n || !hapd->iface->current_mode || + hapd->conf->disable_11n) + return eid; + + *pos++ = WLAN_EID_HT_CAP; + *pos++ = sizeof(*cap); + + cap = (struct ieee80211_ht_capabilities *) pos; + os_memset(cap, 0, sizeof(*cap)); + cap->ht_capabilities_info = host_to_le16(hapd->iconf->ht_capab); + cap->a_mpdu_params = hapd->iface->current_mode->a_mpdu_params; + os_memcpy(cap->supported_mcs_set, hapd->iface->current_mode->mcs_set, + 16); + + /* TODO: ht_extended_capabilities (now fully disabled) */ + /* TODO: tx_bf_capability_info (now fully disabled) */ + /* TODO: asel_capabilities (now fully disabled) */ + + pos += sizeof(*cap); + + if (hapd->iconf->obss_interval) { + struct ieee80211_obss_scan_parameters *scan_params; + + *pos++ = WLAN_EID_OVERLAPPING_BSS_SCAN_PARAMS; + *pos++ = sizeof(*scan_params); + + scan_params = (struct ieee80211_obss_scan_parameters *) pos; + os_memset(scan_params, 0, sizeof(*scan_params)); + scan_params->width_trigger_scan_interval = + host_to_le16(hapd->iconf->obss_interval); + + /* Fill in default values for remaining parameters + * (IEEE Std 802.11-2012, 8.4.2.61 and MIB defval) */ + scan_params->scan_passive_dwell = + host_to_le16(20); + scan_params->scan_active_dwell = + host_to_le16(10); + scan_params->scan_passive_total_per_channel = + host_to_le16(200); + scan_params->scan_active_total_per_channel = + host_to_le16(20); + scan_params->channel_transition_delay_factor = + host_to_le16(5); + scan_params->scan_activity_threshold = + host_to_le16(25); + + pos += sizeof(*scan_params); + } + + return pos; +} + + +u8 * hostapd_eid_ht_operation(struct hostapd_data *hapd, u8 *eid) +{ + struct ieee80211_ht_operation *oper; + u8 *pos = eid; + + if (!hapd->iconf->ieee80211n || hapd->conf->disable_11n) + return eid; + + *pos++ = WLAN_EID_HT_OPERATION; + *pos++ = sizeof(*oper); + + oper = (struct ieee80211_ht_operation *) pos; + os_memset(oper, 0, sizeof(*oper)); + + oper->primary_chan = hapd->iconf->channel; + oper->operation_mode = host_to_le16(hapd->iface->ht_op_mode); + if (hapd->iconf->secondary_channel == 1) + oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE | + HT_INFO_HT_PARAM_STA_CHNL_WIDTH; + if (hapd->iconf->secondary_channel == -1) + oper->ht_param |= HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW | + HT_INFO_HT_PARAM_STA_CHNL_WIDTH; + + pos += sizeof(*oper); + + return pos; +} + + +u8 * hostapd_eid_secondary_channel(struct hostapd_data *hapd, u8 *eid) +{ + u8 sec_ch; + + if (!hapd->cs_freq_params.channel || + !hapd->cs_freq_params.sec_channel_offset) + return eid; + + if (hapd->cs_freq_params.sec_channel_offset == -1) + sec_ch = HT_INFO_HT_PARAM_SECONDARY_CHNL_BELOW; + else if (hapd->cs_freq_params.sec_channel_offset == 1) + sec_ch = HT_INFO_HT_PARAM_SECONDARY_CHNL_ABOVE; + else + return eid; + + *eid++ = WLAN_EID_SECONDARY_CHANNEL_OFFSET; + *eid++ = 1; + *eid++ = sec_ch; + + return eid; +} + + +/* +op_mode +Set to 0 (HT pure) under the followign conditions + - all STAs in the BSS are 20/40 MHz HT in 20/40 MHz BSS or + - all STAs in the BSS are 20 MHz HT in 20 MHz BSS +Set to 1 (HT non-member protection) if there may be non-HT STAs + in both the primary and the secondary channel +Set to 2 if only HT STAs are associated in BSS, + however and at least one 20 MHz HT STA is associated +Set to 3 (HT mixed mode) when one or more non-HT STAs are associated +*/ +int hostapd_ht_operation_update(struct hostapd_iface *iface) +{ + u16 cur_op_mode, new_op_mode; + int op_mode_changes = 0; + + if (!iface->conf->ieee80211n || iface->conf->ht_op_mode_fixed) + return 0; + + wpa_printf(MSG_DEBUG, "%s current operation mode=0x%X", + __func__, iface->ht_op_mode); + + if (!(iface->ht_op_mode & HT_OPER_OP_MODE_NON_GF_HT_STAS_PRESENT) + && iface->num_sta_ht_no_gf) { + iface->ht_op_mode |= HT_OPER_OP_MODE_NON_GF_HT_STAS_PRESENT; + op_mode_changes++; + } else if ((iface->ht_op_mode & + HT_OPER_OP_MODE_NON_GF_HT_STAS_PRESENT) && + iface->num_sta_ht_no_gf == 0) { + iface->ht_op_mode &= ~HT_OPER_OP_MODE_NON_GF_HT_STAS_PRESENT; + op_mode_changes++; + } + + if (!(iface->ht_op_mode & HT_OPER_OP_MODE_OBSS_NON_HT_STAS_PRESENT) && + (iface->num_sta_no_ht || iface->olbc_ht)) { + iface->ht_op_mode |= HT_OPER_OP_MODE_OBSS_NON_HT_STAS_PRESENT; + op_mode_changes++; + } else if ((iface->ht_op_mode & + HT_OPER_OP_MODE_OBSS_NON_HT_STAS_PRESENT) && + (iface->num_sta_no_ht == 0 && !iface->olbc_ht)) { + iface->ht_op_mode &= ~HT_OPER_OP_MODE_OBSS_NON_HT_STAS_PRESENT; + op_mode_changes++; + } + + if (iface->num_sta_no_ht) + new_op_mode = HT_PROT_NON_HT_MIXED; + else if (iface->conf->secondary_channel && iface->num_sta_ht_20mhz) + new_op_mode = HT_PROT_20MHZ_PROTECTION; + else if (iface->olbc_ht) + new_op_mode = HT_PROT_NONMEMBER_PROTECTION; + else + new_op_mode = HT_PROT_NO_PROTECTION; + + cur_op_mode = iface->ht_op_mode & HT_OPER_OP_MODE_HT_PROT_MASK; + if (cur_op_mode != new_op_mode) { + iface->ht_op_mode &= ~HT_OPER_OP_MODE_HT_PROT_MASK; + iface->ht_op_mode |= new_op_mode; + op_mode_changes++; + } + + wpa_printf(MSG_DEBUG, "%s new operation mode=0x%X changes=%d", + __func__, iface->ht_op_mode, op_mode_changes); + + return op_mode_changes; +} + + +static int is_40_allowed(struct hostapd_iface *iface, int channel) +{ + int pri_freq, sec_freq; + int affected_start, affected_end; + int pri = 2407 + 5 * channel; + + if (iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G) + return 1; + + pri_freq = hostapd_hw_get_freq(iface->bss[0], iface->conf->channel); + + if (iface->conf->secondary_channel > 0) + sec_freq = pri_freq + 20; + else + sec_freq = pri_freq - 20; + + affected_start = (pri_freq + sec_freq) / 2 - 25; + affected_end = (pri_freq + sec_freq) / 2 + 25; + if ((pri < affected_start || pri > affected_end)) + return 1; /* not within affected channel range */ + + wpa_printf(MSG_ERROR, "40 MHz affected channel range: [%d,%d] MHz", + affected_start, affected_end); + wpa_printf(MSG_ERROR, "Neighboring BSS: freq=%d", pri); + return 0; +} + + +void hostapd_2040_coex_action(struct hostapd_data *hapd, + const struct ieee80211_mgmt *mgmt, size_t len) +{ + struct hostapd_iface *iface = hapd->iface; + struct ieee80211_2040_bss_coex_ie *bc_ie; + struct ieee80211_2040_intol_chan_report *ic_report; + int is_ht40_allowed = 1; + int i; + const u8 *start = (const u8 *) mgmt; + const u8 *data = start + IEEE80211_HDRLEN + 2; + struct sta_info *sta; + + wpa_printf(MSG_DEBUG, + "HT: Received 20/40 BSS Coexistence Management frame from " + MACSTR, MAC2STR(mgmt->sa)); + + hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, "hostapd_public_action - action=%d", + mgmt->u.action.u.public_action.action); + + if (!(iface->conf->ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET)) { + wpa_printf(MSG_DEBUG, + "Ignore 20/40 BSS Coexistence Management frame since 40 MHz capability is not enabled"); + return; + } + + if (len < IEEE80211_HDRLEN + 2 + sizeof(*bc_ie)) { + wpa_printf(MSG_DEBUG, + "Ignore too short 20/40 BSS Coexistence Management frame"); + return; + } + + /* 20/40 BSS Coexistence element */ + bc_ie = (struct ieee80211_2040_bss_coex_ie *) data; + if (bc_ie->element_id != WLAN_EID_20_40_BSS_COEXISTENCE || + bc_ie->length < 1) { + wpa_printf(MSG_DEBUG, "Unexpected IE (%u,%u) in coex report", + bc_ie->element_id, bc_ie->length); + return; + } + if (len < IEEE80211_HDRLEN + 2 + 2 + bc_ie->length) { + wpa_printf(MSG_DEBUG, + "Truncated 20/40 BSS Coexistence element"); + return; + } + data += 2 + bc_ie->length; + + wpa_printf(MSG_DEBUG, + "20/40 BSS Coexistence Information field: 0x%x (%s%s%s%s%s%s)", + bc_ie->coex_param, + (bc_ie->coex_param & BIT(0)) ? "[InfoReq]" : "", + (bc_ie->coex_param & BIT(1)) ? "[40MHzIntolerant]" : "", + (bc_ie->coex_param & BIT(2)) ? "[20MHzBSSWidthReq]" : "", + (bc_ie->coex_param & BIT(3)) ? "[OBSSScanExemptionReq]" : "", + (bc_ie->coex_param & BIT(4)) ? + "[OBSSScanExemptionGrant]" : "", + (bc_ie->coex_param & (BIT(5) | BIT(6) | BIT(7))) ? + "[Reserved]" : ""); + + if (bc_ie->coex_param & WLAN_20_40_BSS_COEX_20MHZ_WIDTH_REQ) { + /* Intra-BSS communication prohibiting 20/40 MHz BSS operation + */ + sta = ap_get_sta(hapd, mgmt->sa); + if (!sta || !(sta->flags & WLAN_STA_ASSOC)) { + wpa_printf(MSG_DEBUG, + "Ignore intra-BSS 20/40 BSS Coexistence Management frame from not-associated STA"); + return; + } + + hostapd_logger(hapd, mgmt->sa, + HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "20 MHz BSS width request bit is set in BSS coexistence information field"); + is_ht40_allowed = 0; + } + + if (bc_ie->coex_param & WLAN_20_40_BSS_COEX_40MHZ_INTOL) { + /* Inter-BSS communication prohibiting 20/40 MHz BSS operation + */ + hostapd_logger(hapd, mgmt->sa, + HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "40 MHz intolerant bit is set in BSS coexistence information field"); + is_ht40_allowed = 0; + } + + /* 20/40 BSS Intolerant Channel Report element (zero or more times) */ + while (start + len - data >= 3 && + data[0] == WLAN_EID_20_40_BSS_INTOLERANT && data[1] >= 1) { + u8 ielen = data[1]; + + if (ielen > start + len - data - 2) { + wpa_printf(MSG_DEBUG, + "Truncated 20/40 BSS Intolerant Channel Report element"); + return; + } + ic_report = (struct ieee80211_2040_intol_chan_report *) data; + wpa_printf(MSG_DEBUG, + "20/40 BSS Intolerant Channel Report: Operating Class %u", + ic_report->op_class); + + /* Go through the channel report to find any BSS there in the + * affected channel range */ + for (i = 0; i < ielen - 1; i++) { + u8 chan = ic_report->variable[i]; + + if (chan == iface->conf->channel) + continue; /* matching own primary channel */ + if (is_40_allowed(iface, chan)) + continue; /* not within affected channels */ + hostapd_logger(hapd, mgmt->sa, + HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "20_40_INTOLERANT channel %d reported", + chan); + is_ht40_allowed = 0; + } + + data += 2 + ielen; + } + wpa_printf(MSG_DEBUG, "is_ht40_allowed=%d num_sta_ht40_intolerant=%d", + is_ht40_allowed, iface->num_sta_ht40_intolerant); + +#ifdef CONFIG_FULL_HOSTAPD + if (!is_ht40_allowed && + (iface->drv_flags & WPA_DRIVER_FLAGS_HT_2040_COEX)) { + if (iface->conf->secondary_channel) { + hostapd_logger(hapd, mgmt->sa, + HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, + "Switching to 20 MHz operation"); + iface->conf->secondary_channel = 0; + ieee802_11_set_beacons(iface); + } + if (!iface->num_sta_ht40_intolerant && + iface->conf->obss_interval) { + unsigned int delay_time; + delay_time = OVERLAPPING_BSS_TRANS_DELAY_FACTOR * + iface->conf->obss_interval; + eloop_cancel_timeout(ap_ht2040_timeout, hapd->iface, + NULL); + eloop_register_timeout(delay_time, 0, ap_ht2040_timeout, + hapd->iface, NULL); + wpa_printf(MSG_DEBUG, + "Reschedule HT 20/40 timeout to occur in %u seconds", + delay_time); + } + } +#endif +} + + +u16 copy_sta_ht_capab(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *ht_capab) +{ + /* + * Disable HT caps for STAs associated to no-HT BSSes, or for stations + * that did not specify a valid WMM IE in the (Re)Association Request + * frame. + */ + if (!ht_capab || !(sta->flags & WLAN_STA_WMM) || + !hapd->iconf->ieee80211n || hapd->conf->disable_11n) { + sta->flags &= ~WLAN_STA_HT; + os_free(sta->ht_capabilities); + sta->ht_capabilities = NULL; + return WLAN_STATUS_SUCCESS; + } + + if (sta->ht_capabilities == NULL) { + sta->ht_capabilities = + os_zalloc(sizeof(struct ieee80211_ht_capabilities)); + if (sta->ht_capabilities == NULL) + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + + sta->flags |= WLAN_STA_HT; + os_memcpy(sta->ht_capabilities, ht_capab, + sizeof(struct ieee80211_ht_capabilities)); + + return WLAN_STATUS_SUCCESS; +} + + +void ht40_intolerant_add(struct hostapd_iface *iface, struct sta_info *sta) +{ + if (iface->current_mode->mode != HOSTAPD_MODE_IEEE80211G) + return; + + wpa_printf(MSG_INFO, "HT: Forty MHz Intolerant is set by STA " MACSTR + " in Association Request", MAC2STR(sta->addr)); + + if (sta->ht40_intolerant_set) + return; + + sta->ht40_intolerant_set = 1; + iface->num_sta_ht40_intolerant++; + eloop_cancel_timeout(ap_ht2040_timeout, iface, NULL); + +#ifdef CONFIG_FULL_HOSTAPD + if (iface->conf->secondary_channel && + (iface->drv_flags & WPA_DRIVER_FLAGS_HT_2040_COEX)) { + iface->conf->secondary_channel = 0; + ieee802_11_set_beacons(iface); + } +#endif +} + + +void ht40_intolerant_remove(struct hostapd_iface *iface, struct sta_info *sta) +{ + if (!sta->ht40_intolerant_set) + return; + + sta->ht40_intolerant_set = 0; + iface->num_sta_ht40_intolerant--; + +#ifdef CONFIG_FULL_HOSTAPD + if (iface->num_sta_ht40_intolerant == 0 && + (iface->conf->ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) && + (iface->drv_flags & WPA_DRIVER_FLAGS_HT_2040_COEX)) { + unsigned int delay_time = OVERLAPPING_BSS_TRANS_DELAY_FACTOR * + iface->conf->obss_interval; + wpa_printf(MSG_DEBUG, + "HT: Start 20->40 MHz transition timer (%d seconds)", + delay_time); + eloop_cancel_timeout(ap_ht2040_timeout, iface, NULL); + eloop_register_timeout(delay_time, 0, ap_ht2040_timeout, + iface, NULL); + } +#endif +} + + +static void update_sta_ht(struct hostapd_data *hapd, struct sta_info *sta) +{ + u16 ht_capab; + + ht_capab = le_to_host16(sta->ht_capabilities->ht_capabilities_info); + wpa_printf(MSG_DEBUG, "HT: STA " MACSTR " HT Capabilities Info: " + "0x%04x", MAC2STR(sta->addr), ht_capab); + if ((ht_capab & HT_CAP_INFO_GREEN_FIELD) == 0) { + if (!sta->no_ht_gf_set) { + sta->no_ht_gf_set = 1; + hapd->iface->num_sta_ht_no_gf++; + } + wpa_printf(MSG_DEBUG, "%s STA " MACSTR " - no greenfield, num " + "of non-gf stations %d", + __func__, MAC2STR(sta->addr), + hapd->iface->num_sta_ht_no_gf); + } + if ((ht_capab & HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET) == 0) { + if (!sta->ht_20mhz_set) { + sta->ht_20mhz_set = 1; + hapd->iface->num_sta_ht_20mhz++; + } + wpa_printf(MSG_DEBUG, "%s STA " MACSTR " - 20 MHz HT, num of " + "20MHz HT STAs %d", + __func__, MAC2STR(sta->addr), + hapd->iface->num_sta_ht_20mhz); + } + + if (ht_capab & HT_CAP_INFO_40MHZ_INTOLERANT) + ht40_intolerant_add(hapd->iface, sta); +} + + +static void update_sta_no_ht(struct hostapd_data *hapd, struct sta_info *sta) +{ + if (!sta->no_ht_set) { + sta->no_ht_set = 1; + hapd->iface->num_sta_no_ht++; + } + if (hapd->iconf->ieee80211n) { + wpa_printf(MSG_DEBUG, "%s STA " MACSTR " - no HT, num of " + "non-HT stations %d", + __func__, MAC2STR(sta->addr), + hapd->iface->num_sta_no_ht); + } +} + + +void update_ht_state(struct hostapd_data *hapd, struct sta_info *sta) +{ + if ((sta->flags & WLAN_STA_HT) && sta->ht_capabilities) + update_sta_ht(hapd, sta); + else + update_sta_no_ht(hapd, sta); + + if (hostapd_ht_operation_update(hapd->iface) > 0) + ieee802_11_set_beacons(hapd->iface); +} + + +void hostapd_get_ht_capab(struct hostapd_data *hapd, + struct ieee80211_ht_capabilities *ht_cap, + struct ieee80211_ht_capabilities *neg_ht_cap) +{ + u16 cap; + + if (ht_cap == NULL) + return; + os_memcpy(neg_ht_cap, ht_cap, sizeof(*neg_ht_cap)); + cap = le_to_host16(neg_ht_cap->ht_capabilities_info); + + /* + * Mask out HT features we don't support, but don't overwrite + * non-symmetric features like STBC and SMPS. Just because + * we're not in dynamic SMPS mode the STA might still be. + */ + cap &= (hapd->iconf->ht_capab | HT_CAP_INFO_RX_STBC_MASK | + HT_CAP_INFO_TX_STBC | HT_CAP_INFO_SMPS_MASK); + + /* + * STBC needs to be handled specially + * if we don't support RX STBC, mask out TX STBC in the STA's HT caps + * if we don't support TX STBC, mask out RX STBC in the STA's HT caps + */ + if (!(hapd->iconf->ht_capab & HT_CAP_INFO_RX_STBC_MASK)) + cap &= ~HT_CAP_INFO_TX_STBC; + if (!(hapd->iconf->ht_capab & HT_CAP_INFO_TX_STBC)) + cap &= ~HT_CAP_INFO_RX_STBC_MASK; + + neg_ht_cap->ht_capabilities_info = host_to_le16(cap); +} + + +void ap_ht2040_timeout(void *eloop_data, void *user_data) +{ + struct hostapd_iface *iface = eloop_data; + + wpa_printf(MSG_INFO, "Switching to 40 MHz operation"); + + iface->conf->secondary_channel = iface->secondary_ch; + ieee802_11_set_beacons(iface); +} diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ieee802_11_shared.c b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ieee802_11_shared.c new file mode 100755 index 0000000..abdb78f --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ieee802_11_shared.c @@ -0,0 +1,1015 @@ +/* + * hostapd / IEEE 802.11 Management + * Copyright (c) 2002-2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "common/ieee802_11_defs.h" +#include "ap/hostapd.h" +#include "ap/sta_info.h" +#include "ap_config.h" +#include "ap_drv_ops.h" +#include "wpa_auth.h" +#include "ieee802_11.h" + + +#ifdef CONFIG_IEEE80211W_AP + +u8 * hostapd_eid_assoc_comeback_time(struct hostapd_data *hapd, + struct sta_info *sta, u8 *eid) +{ + u8 *pos = eid; + u32 timeout, tu; + struct os_reltime now, passed; + + *pos++ = WLAN_EID_TIMEOUT_INTERVAL; + *pos++ = 5; + *pos++ = WLAN_TIMEOUT_ASSOC_COMEBACK; + os_get_reltime(&now); + os_reltime_sub(&now, &sta->sa_query_start, &passed); + tu = (passed.sec * 1000000 + passed.usec) / 1024; + if (hapd->conf->assoc_sa_query_max_timeout > tu) + timeout = hapd->conf->assoc_sa_query_max_timeout - tu; + else + timeout = 0; + if (timeout < hapd->conf->assoc_sa_query_max_timeout) + timeout++; /* add some extra time for local timers */ + WPA_PUT_LE32(pos, timeout); + pos += 4; + + return pos; +} + + +/* MLME-SAQuery.request */ +void ieee802_11_send_sa_query_req(struct hostapd_data *hapd, + const u8 *addr, const u8 *trans_id) +{ +#ifdef CONFIG_OCV + struct sta_info *sta; +#endif /* CONFIG_OCV */ + struct ieee80211_mgmt *mgmt; + u8 *oci_ie = NULL; + u8 oci_ie_len = 0; + u8 *end; + + wpa_printf(MSG_DEBUG, "IEEE 802.11: Sending SA Query Request to " + MACSTR, MAC2STR(addr)); + wpa_hexdump(MSG_DEBUG, "IEEE 802.11: SA Query Transaction ID", + trans_id, WLAN_SA_QUERY_TR_ID_LEN); + +#ifdef CONFIG_OCV + sta = ap_get_sta(hapd, addr); + if (sta && wpa_auth_uses_ocv(sta->wpa_sm)) { + struct wpa_channel_info ci; + + if (hostapd_drv_channel_info(hapd, &ci) != 0) { + wpa_printf(MSG_WARNING, + "Failed to get channel info for OCI element in SA Query Request"); + return; + } + + oci_ie_len = OCV_OCI_EXTENDED_LEN; + oci_ie = os_zalloc(oci_ie_len); + if (!oci_ie) { + wpa_printf(MSG_WARNING, + "Failed to allocate buffer for OCI element in SA Query Request"); + return; + } + + if (ocv_insert_extended_oci(&ci, oci_ie) < 0) { + os_free(oci_ie); + return; + } + } +#endif /* CONFIG_OCV */ + + mgmt = os_zalloc(sizeof(*mgmt) + oci_ie_len); + if (!mgmt) { + wpa_printf(MSG_DEBUG, + "Failed to allocate buffer for SA Query Response frame"); + os_free(oci_ie); + return; + } + + mgmt->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, + WLAN_FC_STYPE_ACTION); + os_memcpy(mgmt->da, addr, ETH_ALEN); + os_memcpy(mgmt->sa, hapd->own_addr, ETH_ALEN); + os_memcpy(mgmt->bssid, hapd->own_addr, ETH_ALEN); + mgmt->u.action.category = WLAN_ACTION_SA_QUERY; + mgmt->u.action.u.sa_query_req.action = WLAN_SA_QUERY_REQUEST; + os_memcpy(mgmt->u.action.u.sa_query_req.trans_id, trans_id, + WLAN_SA_QUERY_TR_ID_LEN); + end = mgmt->u.action.u.sa_query_req.variable; +#ifdef CONFIG_OCV + if (oci_ie_len > 0) { + os_memcpy(end, oci_ie, oci_ie_len); + end += oci_ie_len; + } +#endif /* CONFIG_OCV */ + if (hostapd_drv_send_mlme(hapd, mgmt, end - (u8 *) mgmt, 0) < 0) + wpa_printf(MSG_INFO, "ieee802_11_send_sa_query_req: send failed"); + + os_free(mgmt); + os_free(oci_ie); +} + + +static void ieee802_11_send_sa_query_resp(struct hostapd_data *hapd, + const u8 *sa, const u8 *trans_id) +{ + struct sta_info *sta; + struct ieee80211_mgmt *resp; + u8 *oci_ie = NULL; + u8 oci_ie_len = 0; + u8 *end; + + wpa_printf(MSG_DEBUG, "IEEE 802.11: Received SA Query Request from " + MACSTR, MAC2STR(sa)); + wpa_hexdump(MSG_DEBUG, "IEEE 802.11: SA Query Transaction ID", + trans_id, WLAN_SA_QUERY_TR_ID_LEN); + + sta = ap_get_sta(hapd, sa); + if (sta == NULL || !(sta->flags & WLAN_STA_ASSOC)) { + wpa_printf(MSG_DEBUG, "IEEE 802.11: Ignore SA Query Request " + "from unassociated STA " MACSTR, MAC2STR(sa)); + return; + } + +#ifdef CONFIG_OCV + if (wpa_auth_uses_ocv(sta->wpa_sm)) { + struct wpa_channel_info ci; + + if (hostapd_drv_channel_info(hapd, &ci) != 0) { + wpa_printf(MSG_WARNING, + "Failed to get channel info for OCI element in SA Query Response"); + return; + } + + oci_ie_len = OCV_OCI_EXTENDED_LEN; + oci_ie = os_zalloc(oci_ie_len); + if (!oci_ie) { + wpa_printf(MSG_WARNING, + "Failed to allocate buffer for for OCI element in SA Query Response"); + return; + } + + if (ocv_insert_extended_oci(&ci, oci_ie) < 0) { + os_free(oci_ie); + return; + } + } +#endif /* CONFIG_OCV */ + + resp = os_zalloc(sizeof(*resp) + oci_ie_len); + if (!resp) { + wpa_printf(MSG_DEBUG, + "Failed to allocate buffer for SA Query Response frame"); + os_free(oci_ie); + return; + } + + wpa_printf(MSG_DEBUG, "IEEE 802.11: Sending SA Query Response to " + MACSTR, MAC2STR(sa)); + + resp->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, + WLAN_FC_STYPE_ACTION); + os_memcpy(resp->da, sa, ETH_ALEN); + os_memcpy(resp->sa, hapd->own_addr, ETH_ALEN); + os_memcpy(resp->bssid, hapd->own_addr, ETH_ALEN); + resp->u.action.category = WLAN_ACTION_SA_QUERY; + resp->u.action.u.sa_query_req.action = WLAN_SA_QUERY_RESPONSE; + os_memcpy(resp->u.action.u.sa_query_req.trans_id, trans_id, + WLAN_SA_QUERY_TR_ID_LEN); + end = resp->u.action.u.sa_query_req.variable; +#ifdef CONFIG_OCV + if (oci_ie_len > 0) { + os_memcpy(end, oci_ie, oci_ie_len); + end += oci_ie_len; + } +#endif /* CONFIG_OCV */ + if (hostapd_drv_send_mlme(hapd, resp, end - (u8 *) resp, 0) < 0) + wpa_printf(MSG_INFO, "ieee80211_mgmt_sa_query_request: send failed"); + + os_free(resp); + os_free(oci_ie); +} + + +void ieee802_11_sa_query_action(struct hostapd_data *hapd, + const struct ieee80211_mgmt *mgmt, + size_t len) +{ + struct sta_info *sta; + int i; + const u8 *sa = mgmt->sa; + const u8 action_type = mgmt->u.action.u.sa_query_resp.action; + const u8 *trans_id = mgmt->u.action.u.sa_query_resp.trans_id; + + if (((const u8 *) mgmt) + len < + mgmt->u.action.u.sa_query_resp.variable) { + wpa_printf(MSG_DEBUG, + "IEEE 802.11: Too short SA Query Action frame (len=%lu)", + (unsigned long) len); + return; + } + + sta = ap_get_sta(hapd, sa); + +#ifdef CONFIG_OCV + if (sta && wpa_auth_uses_ocv(sta->wpa_sm)) { + struct ieee802_11_elems elems; + struct wpa_channel_info ci; + int tx_chanwidth; + int tx_seg1_idx; + size_t ies_len; + const u8 *ies; + + ies = mgmt->u.action.u.sa_query_resp.variable; + ies_len = len - (ies - (u8 *) mgmt); + if (ieee802_11_parse_elems(ies, ies_len, &elems, 1) == + ParseFailed) { + wpa_printf(MSG_DEBUG, + "SA Query: Failed to parse elements"); + return; + } + + if (hostapd_drv_channel_info(hapd, &ci) != 0) { + wpa_printf(MSG_WARNING, + "Failed to get channel info to validate received OCI in SA Query Action frame"); + return; + } + + if (get_sta_tx_parameters(sta->wpa_sm, + channel_width_to_int(ci.chanwidth), + ci.seg1_idx, &tx_chanwidth, + &tx_seg1_idx) < 0) + return; + + if (ocv_verify_tx_params(elems.oci, elems.oci_len, &ci, + tx_chanwidth, tx_seg1_idx) != 0) { + wpa_printf(MSG_WARNING, "%s", ocv_errorstr); + return; + } + } +#endif /* CONFIG_OCV */ + + if (action_type == WLAN_SA_QUERY_REQUEST) { + ieee802_11_send_sa_query_resp(hapd, sa, trans_id); + return; + } + + if (action_type != WLAN_SA_QUERY_RESPONSE) { + wpa_printf(MSG_DEBUG, "IEEE 802.11: Unexpected SA Query " + "Action %d", action_type); + return; + } + + wpa_printf(MSG_DEBUG, "IEEE 802.11: Received SA Query Response from " + MACSTR, MAC2STR(sa)); + wpa_hexdump(MSG_DEBUG, "IEEE 802.11: SA Query Transaction ID", + trans_id, WLAN_SA_QUERY_TR_ID_LEN); + + /* MLME-SAQuery.confirm */ + + if (sta == NULL || sta->sa_query_trans_id == NULL) { + wpa_printf(MSG_DEBUG, "IEEE 802.11: No matching STA with " + "pending SA Query request found"); + return; + } + + for (i = 0; i < sta->sa_query_count; i++) { + if (os_memcmp(sta->sa_query_trans_id + + i * WLAN_SA_QUERY_TR_ID_LEN, + trans_id, WLAN_SA_QUERY_TR_ID_LEN) == 0) + break; + } + + if (i >= sta->sa_query_count) { + wpa_printf(MSG_DEBUG, "IEEE 802.11: No matching SA Query " + "transaction identifier found"); + return; + } + + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "Reply to pending SA Query received"); + ap_sta_stop_sa_query(hapd, sta); +} + +#endif /* CONFIG_IEEE80211W_AP */ + + +static void hostapd_ext_capab_byte(struct hostapd_data *hapd, u8 *pos, int idx) +{ + *pos = 0x00; + + switch (idx) { + case 0: /* Bits 0-7 */ + if (hapd->iconf->obss_interval) + *pos |= 0x01; /* Bit 0 - Coexistence management */ + if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_CSA) + *pos |= 0x04; /* Bit 2 - Extended Channel Switching */ + break; + case 1: /* Bits 8-15 */ + if (hapd->conf->proxy_arp) + *pos |= 0x10; /* Bit 12 - Proxy ARP */ + if (hapd->conf->coloc_intf_reporting) { + /* Bit 13 - Collocated Interference Reporting */ + *pos |= 0x20; + } + break; + case 2: /* Bits 16-23 */ +#ifdef CONFIG_FULL_HOSTAPD + if (hapd->conf->wnm_sleep_mode) + *pos |= 0x02; /* Bit 17 - WNM-Sleep Mode */ + if (hapd->conf->bss_transition) + *pos |= 0x08; /* Bit 19 - BSS Transition */ +#endif + break; + case 3: /* Bits 24-31 */ +#ifdef CONFIG_WNM_AP + *pos |= 0x02; /* Bit 25 - SSID List */ +#endif /* CONFIG_WNM_AP */ +#ifdef CONFIG_FULL_HOSTAPD + if (hapd->conf->time_advertisement == 2) + *pos |= 0x08; /* Bit 27 - UTC TSF Offset */ +#endif +#ifdef CONFIG_INTERWORKING + if (hapd->conf->interworking) + *pos |= 0x80; /* Bit 31 - Interworking */ +#endif + break; + case 4: /* Bits 32-39 */ + if (hapd->conf->qos_map_set_len) + *pos |= 0x01; /* Bit 32 - QoS Map */ +#ifdef CONFIG_FULL_HOSTAPD + if (hapd->conf->tdls & TDLS_PROHIBIT) + *pos |= 0x40; /* Bit 38 - TDLS Prohibited */ + if (hapd->conf->tdls & TDLS_PROHIBIT_CHAN_SWITCH) { + /* Bit 39 - TDLS Channel Switching Prohibited */ + *pos |= 0x80; + } +#endif + break; + case 5: /* Bits 40-47 */ +#ifdef CONFIG_HS20 + if (hapd->conf->hs20) + *pos |= 0x40; /* Bit 46 - WNM-Notification */ +#endif /* CONFIG_HS20 */ +#ifdef CONFIG_MBO + if (hapd->conf->mbo_enabled) + *pos |= 0x40; /* Bit 46 - WNM-Notification */ +#endif /* CONFIG_MBO */ + break; + case 6: /* Bits 48-55 */ + if (hapd->conf->ssid.utf8_ssid) + *pos |= 0x01; /* Bit 48 - UTF-8 SSID */ + break; + case 7: /* Bits 56-63 */ + break; + case 8: /* Bits 64-71 */ + if (hapd->conf->ftm_responder) + *pos |= 0x40; /* Bit 70 - FTM responder */ + if (hapd->conf->ftm_initiator) + *pos |= 0x80; /* Bit 71 - FTM initiator */ + break; + case 9: /* Bits 72-79 */ +#ifdef CONFIG_FILS + if ((hapd->conf->wpa & WPA_PROTO_RSN) && + wpa_key_mgmt_fils(hapd->conf->wpa_key_mgmt)) + *pos |= 0x01; +#endif /* CONFIG_FILS */ + break; + case 10: /* Bits 80-87 */ +#ifdef CONFIG_SAE_AP + if (hapd->conf->wpa && + wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt)) { + int in_use = hostapd_sae_pw_id_in_use(hapd->conf); + + if (in_use) + *pos |= 0x02; /* Bit 81 - SAE Password + * Identifiers In Use */ + if (in_use == 2) + *pos |= 0x04; /* Bit 82 - SAE Password + * Identifiers Used Exclusively */ + } +#endif /* CONFIG_SAE_AP */ + break; + } +} + +u8 * hostapd_eid_ext_capab(struct hostapd_data *hapd, u8 *eid) +{ + u8 *pos = eid; + u8 len = 0, i; + +#ifdef CONFIG_FULL_HOSTAPD + if (hapd->conf->tdls & (TDLS_PROHIBIT | TDLS_PROHIBIT_CHAN_SWITCH)) + len = 5; +#endif +#ifdef CONFIG_INTERWORKING + if (len < 4 && hapd->conf->interworking) + len = 4; +#endif +#ifdef CONFIG_FULL_HOSTAPD + if (len < 3 && hapd->conf->wnm_sleep_mode) + len = 3; +#endif + if (len < 1 && hapd->iconf->obss_interval) + len = 1; + if (len < 7 && hapd->conf->ssid.utf8_ssid) + len = 7; + if (len < 9 && + (hapd->conf->ftm_initiator || hapd->conf->ftm_responder)) + len = 9; +#ifdef CONFIG_WNM_AP + if (len < 4) + len = 4; +#endif /* CONFIG_WNM_AP */ +#ifdef CONFIG_HS20 + if (hapd->conf->hs20 && len < 6) + len = 6; +#endif /* CONFIG_HS20 */ +#ifdef CONFIG_MBO + if (hapd->conf->mbo_enabled && len < 6) + len = 6; +#endif /* CONFIG_MBO */ +#ifdef CONFIG_FILS + if ((!(hapd->conf->wpa & WPA_PROTO_RSN) || + !wpa_key_mgmt_fils(hapd->conf->wpa_key_mgmt)) && len < 10) + len = 10; +#endif /* CONFIG_FILS */ +#ifdef CONFIG_SAE_AP + if (len < 11 && hapd->conf->wpa && + wpa_key_mgmt_sae(hapd->conf->wpa_key_mgmt) && + hostapd_sae_pw_id_in_use(hapd->conf)) + len = 11; +#endif /* CONFIG_SAE_AP */ + if (len < hapd->iface->extended_capa_len) + len = hapd->iface->extended_capa_len; + if (len == 0) + return eid; + + *pos++ = WLAN_EID_EXT_CAPAB; + *pos++ = len; + for (i = 0; i < len; i++, pos++) { + hostapd_ext_capab_byte(hapd, pos, i); + + if (i < hapd->iface->extended_capa_len) { + *pos &= ~hapd->iface->extended_capa_mask[i]; + *pos |= hapd->iface->extended_capa[i]; + } + } + + while (len > 0 && eid[1 + len] == 0) { + len--; + eid[1] = len; + } + if (len == 0) + return eid; + + return eid + 2 + len; +} + + +u8 * hostapd_eid_qos_map_set(struct hostapd_data *hapd, u8 *eid) +{ + u8 *pos = eid; + u8 len = hapd->conf->qos_map_set_len; + + if (!len) + return eid; + + *pos++ = WLAN_EID_QOS_MAP_SET; + *pos++ = len; + os_memcpy(pos, hapd->conf->qos_map_set, len); + pos += len; + + return pos; +} + + +u8 * hostapd_eid_interworking(struct hostapd_data *hapd, u8 *eid) +{ + u8 *pos = eid; +#ifdef CONFIG_INTERWORKING + u8 *len; + + if (!hapd->conf->interworking) + return eid; + + *pos++ = WLAN_EID_INTERWORKING; + len = pos++; + + *pos = hapd->conf->access_network_type; + if (hapd->conf->internet) + *pos |= INTERWORKING_ANO_INTERNET; + if (hapd->conf->asra) + *pos |= INTERWORKING_ANO_ASRA; + if (hapd->conf->esr) + *pos |= INTERWORKING_ANO_ESR; + if (hapd->conf->uesa) + *pos |= INTERWORKING_ANO_UESA; + pos++; + + if (hapd->conf->venue_info_set) { + *pos++ = hapd->conf->venue_group; + *pos++ = hapd->conf->venue_type; + } + + if (!is_zero_ether_addr(hapd->conf->hessid)) { + os_memcpy(pos, hapd->conf->hessid, ETH_ALEN); + pos += ETH_ALEN; + } + + *len = pos - len - 1; +#endif /* CONFIG_INTERWORKING */ + + return pos; +} + + +u8 * hostapd_eid_adv_proto(struct hostapd_data *hapd, u8 *eid) +{ + u8 *pos = eid; +#ifdef CONFIG_INTERWORKING + + /* TODO: Separate configuration for ANQP? */ + if (!hapd->conf->interworking) + return eid; + + *pos++ = WLAN_EID_ADV_PROTO; + *pos++ = 2; + *pos++ = 0x7F; /* Query Response Length Limit | PAME-BI */ + *pos++ = ACCESS_NETWORK_QUERY_PROTOCOL; +#endif /* CONFIG_INTERWORKING */ + + return pos; +} + + +u8 * hostapd_eid_roaming_consortium(struct hostapd_data *hapd, u8 *eid) +{ + u8 *pos = eid; +#ifdef CONFIG_INTERWORKING + u8 *len; + unsigned int i, count; + + if (!hapd->conf->interworking || + hapd->conf->roaming_consortium == NULL || + hapd->conf->roaming_consortium_count == 0) + return eid; + + *pos++ = WLAN_EID_ROAMING_CONSORTIUM; + len = pos++; + + /* Number of ANQP OIs (in addition to the max 3 listed here) */ + if (hapd->conf->roaming_consortium_count > 3 + 255) + *pos++ = 255; + else if (hapd->conf->roaming_consortium_count > 3) + *pos++ = hapd->conf->roaming_consortium_count - 3; + else + *pos++ = 0; + + /* OU #1 and #2 Lengths */ + *pos = hapd->conf->roaming_consortium[0].len; + if (hapd->conf->roaming_consortium_count > 1) + *pos |= hapd->conf->roaming_consortium[1].len << 4; + pos++; + + if (hapd->conf->roaming_consortium_count > 3) + count = 3; + else + count = hapd->conf->roaming_consortium_count; + + for (i = 0; i < count; i++) { + os_memcpy(pos, hapd->conf->roaming_consortium[i].oi, + hapd->conf->roaming_consortium[i].len); + pos += hapd->conf->roaming_consortium[i].len; + } + + *len = pos - len - 1; +#endif /* CONFIG_INTERWORKING */ + + return pos; +} + + +#ifdef CONFIG_FULL_HOSTAPD +u8 * hostapd_eid_time_adv(struct hostapd_data *hapd, u8 *eid) +{ + if (hapd->conf->time_advertisement != 2) + return eid; + + if (hapd->time_adv == NULL && + hostapd_update_time_adv(hapd) < 0) + return eid; + + if (hapd->time_adv == NULL) + return eid; + + os_memcpy(eid, wpabuf_head(hapd->time_adv), + wpabuf_len(hapd->time_adv)); + eid += wpabuf_len(hapd->time_adv); + + return eid; +} + + +u8 * hostapd_eid_time_zone(struct hostapd_data *hapd, u8 *eid) +{ + size_t len; + + if (hapd->conf->time_advertisement != 2 || !hapd->conf->time_zone) + return eid; + + len = os_strlen(hapd->conf->time_zone); + + *eid++ = WLAN_EID_TIME_ZONE; + *eid++ = len; + os_memcpy(eid, hapd->conf->time_zone, len); + eid += len; + + return eid; +} + + +int hostapd_update_time_adv(struct hostapd_data *hapd) +{ + const int elen = 2 + 1 + 10 + 5 + 1; + struct os_time t; + struct os_tm tm; + u8 *pos; + + if (hapd->conf->time_advertisement != 2) + return 0; + + if (os_get_time(&t) < 0 || os_gmtime(t.sec, &tm) < 0) + return -1; + + if (!hapd->time_adv) { + hapd->time_adv = wpabuf_alloc(elen); + if (hapd->time_adv == NULL) + return -1; + pos = wpabuf_put(hapd->time_adv, elen); + } else + pos = wpabuf_mhead_u8(hapd->time_adv); + + *pos++ = WLAN_EID_TIME_ADVERTISEMENT; + *pos++ = 1 + 10 + 5 + 1; + + *pos++ = 2; /* UTC time at which the TSF timer is 0 */ + + /* Time Value at TSF 0 */ + /* FIX: need to calculate this based on the current TSF value */ + WPA_PUT_LE16(pos, tm.year); /* Year */ + pos += 2; + *pos++ = tm.month; /* Month */ + *pos++ = tm.day; /* Day of month */ + *pos++ = tm.hour; /* Hours */ + *pos++ = tm.min; /* Minutes */ + *pos++ = tm.sec; /* Seconds */ + WPA_PUT_LE16(pos, 0); /* Milliseconds (not used) */ + pos += 2; + *pos++ = 0; /* Reserved */ + + /* Time Error */ + /* TODO: fill in an estimate on the error */ + *pos++ = 0; + *pos++ = 0; + *pos++ = 0; + *pos++ = 0; + *pos++ = 0; + + *pos++ = hapd->time_update_counter++; + + return 0; +} +#endif + +u8 * hostapd_eid_bss_max_idle_period(struct hostapd_data *hapd, u8 *eid) +{ + u8 *pos = eid; + +#ifdef CONFIG_WNM_AP + if (hapd->conf->ap_max_inactivity > 0) { + unsigned int val; + *pos++ = WLAN_EID_BSS_MAX_IDLE_PERIOD; + *pos++ = 3; + val = hapd->conf->ap_max_inactivity; + if (val > 68000) + val = 68000; + val *= 1000; + val /= 1024; + if (val == 0) + val = 1; + if (val > 65535) + val = 65535; + WPA_PUT_LE16(pos, val); + pos += 2; + *pos++ = 0x00; /* TODO: Protected Keep-Alive Required */ + } +#endif /* CONFIG_WNM_AP */ + + return pos; +} + + +#ifdef CONFIG_MBO + +u8 * hostapd_eid_mbo_rssi_assoc_rej(struct hostapd_data *hapd, u8 *eid, + size_t len, int delta) +{ + u8 mbo[4]; + + mbo[0] = OCE_ATTR_ID_RSSI_BASED_ASSOC_REJECT; + mbo[1] = 2; + /* Delta RSSI */ + mbo[2] = delta; + /* Retry delay */ + mbo[3] = hapd->iconf->rssi_reject_assoc_timeout; + + return eid + mbo_add_ie(eid, len, mbo, 4); +} + + +u8 * hostapd_eid_mbo(struct hostapd_data *hapd, u8 *eid, size_t len) +{ + u8 mbo[9], *mbo_pos = mbo; + u8 *pos = eid; + + if (!hapd->conf->mbo_enabled && + !OCE_STA_CFON_ENABLED(hapd) && !OCE_AP_ENABLED(hapd)) + return eid; + + if (hapd->conf->mbo_enabled) { + *mbo_pos++ = MBO_ATTR_ID_AP_CAPA_IND; + *mbo_pos++ = 1; + /* Not Cellular aware */ + *mbo_pos++ = 0; + } + + if (hapd->conf->mbo_enabled && hapd->mbo_assoc_disallow) { + *mbo_pos++ = MBO_ATTR_ID_ASSOC_DISALLOW; + *mbo_pos++ = 1; + *mbo_pos++ = hapd->mbo_assoc_disallow; + } + + if (OCE_STA_CFON_ENABLED(hapd) || OCE_AP_ENABLED(hapd)) { + u8 ctrl; + + ctrl = OCE_RELEASE; + if (OCE_STA_CFON_ENABLED(hapd) && !OCE_AP_ENABLED(hapd)) + ctrl |= OCE_IS_STA_CFON; + + *mbo_pos++ = OCE_ATTR_ID_CAPA_IND; + *mbo_pos++ = 1; + *mbo_pos++ = ctrl; + } + + pos += mbo_add_ie(pos, len, mbo, mbo_pos - mbo); + + return pos; +} + + +u8 hostapd_mbo_ie_len(struct hostapd_data *hapd) +{ + u8 len; + + if (!hapd->conf->mbo_enabled && + !OCE_STA_CFON_ENABLED(hapd) && !OCE_AP_ENABLED(hapd)) + return 0; + + /* + * MBO IE header (6) + Capability Indication attribute (3) + + * Association Disallowed attribute (3) = 12 + */ + len = 6; + if (hapd->conf->mbo_enabled) + len += 3 + (hapd->mbo_assoc_disallow ? 3 : 0); + + /* OCE capability indication attribute (3) */ + if (OCE_STA_CFON_ENABLED(hapd) || OCE_AP_ENABLED(hapd)) + len += 3; + + return len; +} + +#endif /* CONFIG_MBO */ + + +#ifdef CONFIG_OWE +static int hostapd_eid_owe_trans_enabled(struct hostapd_data *hapd) +{ + return hapd->conf->owe_transition_ssid_len > 0 && + !is_zero_ether_addr(hapd->conf->owe_transition_bssid); +} +#endif /* CONFIG_OWE */ + + +size_t hostapd_eid_owe_trans_len(struct hostapd_data *hapd) +{ +#ifdef CONFIG_OWE + if (!hostapd_eid_owe_trans_enabled(hapd)) + return 0; + return 6 + ETH_ALEN + 1 + hapd->conf->owe_transition_ssid_len; +#else /* CONFIG_OWE */ + return 0; +#endif /* CONFIG_OWE */ +} + + +u8 * hostapd_eid_owe_trans(struct hostapd_data *hapd, u8 *eid, + size_t len) +{ +#ifdef CONFIG_OWE + u8 *pos = eid; + size_t elen; + + if (hapd->conf->owe_transition_ifname[0] && + !hostapd_eid_owe_trans_enabled(hapd)) + hostapd_owe_trans_get_info(hapd); + + if (!hostapd_eid_owe_trans_enabled(hapd)) + return pos; + + elen = hostapd_eid_owe_trans_len(hapd); + if (len < elen) { + wpa_printf(MSG_DEBUG, + "OWE: Not enough room in the buffer for OWE IE"); + return pos; + } + + *pos++ = WLAN_EID_VENDOR_SPECIFIC; + *pos++ = elen - 2; + WPA_PUT_BE24(pos, OUI_WFA); + pos += 3; + *pos++ = OWE_OUI_TYPE; + os_memcpy(pos, hapd->conf->owe_transition_bssid, ETH_ALEN); + pos += ETH_ALEN; + *pos++ = hapd->conf->owe_transition_ssid_len; + os_memcpy(pos, hapd->conf->owe_transition_ssid, + hapd->conf->owe_transition_ssid_len); + pos += hapd->conf->owe_transition_ssid_len; + + return pos; +#else /* CONFIG_OWE */ + return eid; +#endif /* CONFIG_OWE */ +} + + +void ap_copy_sta_supp_op_classes(struct sta_info *sta, + const u8 *supp_op_classes, + size_t supp_op_classes_len) +{ + if (!supp_op_classes) + return; + os_free(sta->supp_op_classes); + sta->supp_op_classes = os_malloc(1 + supp_op_classes_len); + if (!sta->supp_op_classes) + return; + + sta->supp_op_classes[0] = supp_op_classes_len; + os_memcpy(sta->supp_op_classes + 1, supp_op_classes, + supp_op_classes_len); +} + + +u8 * hostapd_eid_fils_indic(struct hostapd_data *hapd, u8 *eid, int hessid) +{ + u8 *pos = eid; +#ifdef CONFIG_FILS + u8 *len; + u16 fils_info = 0; + size_t realms; + struct fils_realm *realm; + + if (!(hapd->conf->wpa & WPA_PROTO_RSN) || + !wpa_key_mgmt_fils(hapd->conf->wpa_key_mgmt)) + return pos; + + realms = dl_list_len(&hapd->conf->fils_realms); + if (realms > 7) + realms = 7; /* 3 bit count field limits this to max 7 */ + + *pos++ = WLAN_EID_FILS_INDICATION; + len = pos++; + /* TODO: B0..B2: Number of Public Key Identifiers */ + if (hapd->conf->erp_domain) { + /* B3..B5: Number of Realm Identifiers */ + fils_info |= realms << 3; + } + /* TODO: B6: FILS IP Address Configuration */ + if (hapd->conf->fils_cache_id_set) + fils_info |= BIT(7); + if (hessid && !is_zero_ether_addr(hapd->conf->hessid)) + fils_info |= BIT(8); /* HESSID Included */ + /* FILS Shared Key Authentication without PFS Supported */ + fils_info |= BIT(9); + if (hapd->conf->fils_dh_group) { + /* FILS Shared Key Authentication with PFS Supported */ + fils_info |= BIT(10); + } + /* TODO: B11: FILS Public Key Authentication Supported */ + /* B12..B15: Reserved */ + WPA_PUT_LE16(pos, fils_info); + pos += 2; + if (hapd->conf->fils_cache_id_set) { + os_memcpy(pos, hapd->conf->fils_cache_id, FILS_CACHE_ID_LEN); + pos += FILS_CACHE_ID_LEN; + } + if (hessid && !is_zero_ether_addr(hapd->conf->hessid)) { + os_memcpy(pos, hapd->conf->hessid, ETH_ALEN); + pos += ETH_ALEN; + } + + dl_list_for_each(realm, &hapd->conf->fils_realms, struct fils_realm, + list) { + if (realms == 0) + break; + realms--; + os_memcpy(pos, realm->hash, 2); + pos += 2; + } + *len = pos - len - 1; +#endif /* CONFIG_FILS */ + + return pos; +} + + +#ifdef CONFIG_OCV +int get_tx_parameters(struct sta_info *sta, int ap_max_chanwidth, + int ap_seg1_idx, int *bandwidth, int *seg1_idx) +{ + int ht_40mhz = 0; + int vht_80p80 = 0; + int requested_bw; + + if (sta->ht_capabilities) + ht_40mhz = !!(sta->ht_capabilities->ht_capabilities_info & + HT_CAP_INFO_SUPP_CHANNEL_WIDTH_SET); + + if (sta->vht_operation) { + struct ieee80211_vht_operation *oper = sta->vht_operation; + + /* + * If a VHT Operation element was present, use it to determine + * the supported channel bandwidth. + */ + if (oper->vht_op_info_chwidth == 0) { + requested_bw = ht_40mhz ? 40 : 20; + } else if (oper->vht_op_info_chan_center_freq_seg1_idx == 0) { + requested_bw = 80; + } else { + int diff; + + requested_bw = 160; + diff = abs((int) + oper->vht_op_info_chan_center_freq_seg0_idx - + (int) + oper->vht_op_info_chan_center_freq_seg1_idx); + vht_80p80 = oper->vht_op_info_chan_center_freq_seg1_idx + != 0 && diff > 16; + } + } else if (sta->vht_capabilities) { + struct ieee80211_vht_capabilities *capab; + int vht_chanwidth; + + capab = sta->vht_capabilities; + + /* + * If only the VHT Capabilities element is present (e.g., for + * normal clients), use it to determine the supported channel + * bandwidth. + */ + vht_chanwidth = capab->vht_capabilities_info & + VHT_CAP_SUPP_CHAN_WIDTH_MASK; + vht_80p80 = capab->vht_capabilities_info & + VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ; + + /* TODO: Also take into account Extended NSS BW Support field */ + requested_bw = vht_chanwidth ? 160 : 80; + } else { + requested_bw = ht_40mhz ? 40 : 20; + } + + *bandwidth = requested_bw < ap_max_chanwidth ? + requested_bw : ap_max_chanwidth; + + *seg1_idx = 0; + if (ap_seg1_idx && vht_80p80) + *seg1_idx = ap_seg1_idx; + + return 0; +} +#endif /* CONFIG_OCV */ diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ieee802_11_vht.c b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ieee802_11_vht.c new file mode 100755 index 0000000..269345f --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ieee802_11_vht.c @@ -0,0 +1,517 @@ +/* + * hostapd / IEEE 802.11ac VHT + * Copyright (c) 2002-2009, Jouni Malinen + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of BSD license + * + * See README and COPYING for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "common/ieee802_11_defs.h" +#include "hostapd.h" +#include "ap_config.h" +#include "sta_info.h" +#include "beacon.h" +#include "ieee802_11.h" +#include "dfs.h" + + +u8 * hostapd_eid_vht_capabilities(struct hostapd_data *hapd, u8 *eid, u32 nsts) +{ + struct ieee80211_vht_capabilities *cap; + struct hostapd_hw_modes *mode = hapd->iface->current_mode; + u8 *pos = eid; + + if (!mode) + return eid; + + if (mode->mode == HOSTAPD_MODE_IEEE80211G && hapd->conf->vendor_vht && + mode->vht_capab == 0 && hapd->iface->hw_features) { + int i; + + for (i = 0; i < hapd->iface->num_hw_features; i++) { + if (hapd->iface->hw_features[i].mode == + HOSTAPD_MODE_IEEE80211A) { + mode = &hapd->iface->hw_features[i]; + break; + } + } + } + + *pos++ = WLAN_EID_VHT_CAP; + *pos++ = sizeof(*cap); + + cap = (struct ieee80211_vht_capabilities *) pos; + os_memset(cap, 0, sizeof(*cap)); + cap->vht_capabilities_info = host_to_le32( + hapd->iface->conf->vht_capab); + + if (nsts != 0) { + u32 hapd_nsts; + + hapd_nsts = le_to_host32(cap->vht_capabilities_info); + hapd_nsts = (hapd_nsts >> VHT_CAP_BEAMFORMEE_STS_OFFSET) & 7; + cap->vht_capabilities_info &= + ~(host_to_le32(hapd_nsts << + VHT_CAP_BEAMFORMEE_STS_OFFSET)); + cap->vht_capabilities_info |= + host_to_le32(nsts << VHT_CAP_BEAMFORMEE_STS_OFFSET); + } + + /* Supported MCS set comes from hw */ + os_memcpy(&cap->vht_supported_mcs_set, mode->vht_mcs_set, 8); + + pos += sizeof(*cap); + + return pos; +} + + +u8 * hostapd_eid_vht_operation(struct hostapd_data *hapd, u8 *eid) +{ + struct ieee80211_vht_operation *oper; + u8 *pos = eid; + + *pos++ = WLAN_EID_VHT_OPERATION; + *pos++ = sizeof(*oper); + + oper = (struct ieee80211_vht_operation *) pos; + os_memset(oper, 0, sizeof(*oper)); + + /* + * center freq = 5 GHz + (5 * index) + * So index 42 gives center freq 5.210 GHz + * which is channel 42 in 5G band + */ + oper->vht_op_info_chan_center_freq_seg0_idx = + hapd->iconf->vht_oper_centr_freq_seg0_idx; + oper->vht_op_info_chan_center_freq_seg1_idx = + hapd->iconf->vht_oper_centr_freq_seg1_idx; + + oper->vht_op_info_chwidth = hapd->iconf->vht_oper_chwidth; + if (hapd->iconf->vht_oper_chwidth == 2) { + /* + * Convert 160 MHz channel width to new style as interop + * workaround. + */ + oper->vht_op_info_chwidth = 1; + oper->vht_op_info_chan_center_freq_seg1_idx = + oper->vht_op_info_chan_center_freq_seg0_idx; + if (hapd->iconf->channel < + hapd->iconf->vht_oper_centr_freq_seg0_idx) + oper->vht_op_info_chan_center_freq_seg0_idx -= 8; + else + oper->vht_op_info_chan_center_freq_seg0_idx += 8; + } else if (hapd->iconf->vht_oper_chwidth == 3) { + /* + * Convert 80+80 MHz channel width to new style as interop + * workaround. + */ + oper->vht_op_info_chwidth = 1; + } + + /* VHT Basic MCS set comes from hw */ + /* Hard code 1 stream, MCS0-7 is a min Basic VHT MCS rates */ + oper->vht_basic_mcs_set = host_to_le16(0xfffc); + pos += sizeof(*oper); + + return pos; +} + + +static int check_valid_vht_mcs(struct hostapd_hw_modes *mode, + const u8 *sta_vht_capab) +{ + const struct ieee80211_vht_capabilities *vht_cap; + struct ieee80211_vht_capabilities ap_vht_cap; + u16 sta_rx_mcs_set, ap_tx_mcs_set; + int i; + + if (!mode) + return 1; + + /* + * Disable VHT caps for STAs for which there is not even a single + * allowed MCS in any supported number of streams, i.e., STA is + * advertising 3 (not supported) as VHT MCS rates for all supported + * stream cases. + */ + os_memcpy(&ap_vht_cap.vht_supported_mcs_set, mode->vht_mcs_set, + sizeof(ap_vht_cap.vht_supported_mcs_set)); + vht_cap = (const struct ieee80211_vht_capabilities *) sta_vht_capab; + + /* AP Tx MCS map vs. STA Rx MCS map */ + sta_rx_mcs_set = le_to_host16(vht_cap->vht_supported_mcs_set.rx_map); + ap_tx_mcs_set = le_to_host16(ap_vht_cap.vht_supported_mcs_set.tx_map); + + for (i = 0; i < VHT_RX_NSS_MAX_STREAMS; i++) { + if ((ap_tx_mcs_set & (0x3 << (i * 2))) == 3) + continue; + + if ((sta_rx_mcs_set & (0x3 << (i * 2))) == 3) + continue; + + return 1; + } + + wpa_printf(MSG_DEBUG, + "No matching VHT MCS found between AP TX and STA RX"); + return 0; +} + + +u8 * hostapd_eid_wb_chsw_wrapper(struct hostapd_data *hapd, u8 *eid) +{ + u8 bw, chan1, chan2 = 0; + int freq1; + + if (!hapd->cs_freq_params.channel || + !hapd->cs_freq_params.vht_enabled) + return eid; + + /* bandwidth: 0: 40, 1: 80, 2: 160, 3: 80+80 */ + switch (hapd->cs_freq_params.bandwidth) { + case 40: + bw = 0; + break; + case 80: + /* check if it's 80+80 */ + if (!hapd->cs_freq_params.center_freq2) + bw = 1; + else + bw = 3; + break; + case 160: + bw = 2; + break; + default: + /* not valid VHT bandwidth or not in CSA */ + return eid; + } + + freq1 = hapd->cs_freq_params.center_freq1 ? + hapd->cs_freq_params.center_freq1 : + hapd->cs_freq_params.freq; + if (ieee80211_freq_to_chan(freq1, &chan1) != + HOSTAPD_MODE_IEEE80211A) + return eid; + + if (hapd->cs_freq_params.center_freq2 && + ieee80211_freq_to_chan(hapd->cs_freq_params.center_freq2, + &chan2) != HOSTAPD_MODE_IEEE80211A) + return eid; + + *eid++ = WLAN_EID_VHT_CHANNEL_SWITCH_WRAPPER; + *eid++ = 5; /* Length of Channel Switch Wrapper */ + *eid++ = WLAN_EID_VHT_WIDE_BW_CHSWITCH; + *eid++ = 3; /* Length of Wide Bandwidth Channel Switch element */ + *eid++ = bw; /* New Channel Width */ + *eid++ = chan1; /* New Channel Center Frequency Segment 0 */ + *eid++ = chan2; /* New Channel Center Frequency Segment 1 */ + + return eid; +} + + +u8 * hostapd_eid_txpower_envelope(struct hostapd_data *hapd, u8 *eid) +{ + struct hostapd_iface *iface = hapd->iface; + struct hostapd_config *iconf = iface->conf; + struct hostapd_hw_modes *mode = iface->current_mode; + struct hostapd_channel_data *chan; + int dfs, i; + u8 channel, tx_pwr_count, local_pwr_constraint; + int max_tx_power; + u8 tx_pwr; + + if (!mode) + return eid; + + if (ieee80211_freq_to_chan(iface->freq, &channel) == NUM_HOSTAPD_MODES) + return eid; + + for (i = 0; i < mode->num_channels; i++) { + if (mode->channels[i].freq == iface->freq) + break; + } + if (i == mode->num_channels) + return eid; + + switch (iface->conf->vht_oper_chwidth) { + case CHANWIDTH_USE_HT: + if (iconf->secondary_channel == 0) { + /* Max Transmit Power count = 0 (20 MHz) */ + tx_pwr_count = 0; + } else { + /* Max Transmit Power count = 1 (20, 40 MHz) */ + tx_pwr_count = 1; + } + break; + case CHANWIDTH_80MHZ: + /* Max Transmit Power count = 2 (20, 40, and 80 MHz) */ + tx_pwr_count = 2; + break; + case CHANWIDTH_80P80MHZ: + case CHANWIDTH_160MHZ: + /* Max Transmit Power count = 3 (20, 40, 80, 160/80+80 MHz) */ + tx_pwr_count = 3; + break; + default: + return eid; + } + + /* + * Below local_pwr_constraint logic is referred from + * hostapd_eid_pwr_constraint. + * + * Check if DFS is required by regulatory. + */ + dfs = hostapd_is_dfs_required(hapd->iface); + if (dfs < 0) + dfs = 0; + + /* + * In order to meet regulations when TPC is not implemented using + * a transmit power that is below the legal maximum (including any + * mitigation factor) should help. In this case, indicate 3 dB below + * maximum allowed transmit power. + */ + if (hapd->iconf->local_pwr_constraint == -1) + local_pwr_constraint = (dfs == 0) ? 0 : 3; + else + local_pwr_constraint = hapd->iconf->local_pwr_constraint; + + /* + * A STA that is not an AP shall use a transmit power less than or + * equal to the local maximum transmit power level for the channel. + * The local maximum transmit power can be calculated from the formula: + * local max TX pwr = max TX pwr - local pwr constraint + * Where max TX pwr is maximum transmit power level specified for + * channel in Country element and local pwr constraint is specified + * for channel in this Power Constraint element. + */ + chan = &mode->channels[i]; + max_tx_power = chan->max_tx_power - local_pwr_constraint; + + /* + * Local Maximum Transmit power is encoded as two's complement + * with a 0.5 dB step. + */ + max_tx_power *= 2; /* in 0.5 dB steps */ + if (max_tx_power > 127) { + /* 63.5 has special meaning of 63.5 dBm or higher */ + max_tx_power = 127; + } + if (max_tx_power < -128) + max_tx_power = -128; + if (max_tx_power < 0) + tx_pwr = 0x80 + max_tx_power + 128; + else + tx_pwr = max_tx_power; + + *eid++ = WLAN_EID_VHT_TRANSMIT_POWER_ENVELOPE; + *eid++ = 2 + tx_pwr_count; + + /* + * Max Transmit Power count and + * Max Transmit Power units = 0 (EIRP) + */ + *eid++ = tx_pwr_count; + + for (i = 0; i <= tx_pwr_count; i++) + *eid++ = tx_pwr; + + return eid; +} + + +u16 copy_sta_vht_capab(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *vht_capab) +{ + /* Disable VHT caps for STAs associated to no-VHT BSSes. */ + if (!vht_capab || + !hapd->iconf->ieee80211ac || hapd->conf->disable_11ac || + !check_valid_vht_mcs(hapd->iface->current_mode, vht_capab)) { + sta->flags &= ~WLAN_STA_VHT; + os_free(sta->vht_capabilities); + sta->vht_capabilities = NULL; + return WLAN_STATUS_SUCCESS; + } + + if (sta->vht_capabilities == NULL) { + sta->vht_capabilities = + os_zalloc(sizeof(struct ieee80211_vht_capabilities)); + if (sta->vht_capabilities == NULL) + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + + sta->flags |= WLAN_STA_VHT; + os_memcpy(sta->vht_capabilities, vht_capab, + sizeof(struct ieee80211_vht_capabilities)); + + return WLAN_STATUS_SUCCESS; +} + + +u16 copy_sta_vht_oper(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *vht_oper) +{ + if (!vht_oper) { + os_free(sta->vht_operation); + sta->vht_operation = NULL; + return WLAN_STATUS_SUCCESS; + } + + if (!sta->vht_operation) { + sta->vht_operation = + os_zalloc(sizeof(struct ieee80211_vht_operation)); + if (!sta->vht_operation) + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + + os_memcpy(sta->vht_operation, vht_oper, + sizeof(struct ieee80211_vht_operation)); + + return WLAN_STATUS_SUCCESS; +} + + +u16 copy_sta_vendor_vht(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *ie, size_t len) +{ + const u8 *vht_capab; + unsigned int vht_capab_len; + + if (!ie || len < 5 + 2 + sizeof(struct ieee80211_vht_capabilities) || + hapd->conf->disable_11ac) + goto no_capab; + + /* The VHT Capabilities element embedded in vendor VHT */ + vht_capab = ie + 5; + if (vht_capab[0] != WLAN_EID_VHT_CAP) + goto no_capab; + vht_capab_len = vht_capab[1]; + if (vht_capab_len < sizeof(struct ieee80211_vht_capabilities) || + (int) vht_capab_len > ie + len - vht_capab - 2) + goto no_capab; + vht_capab += 2; + + if (sta->vht_capabilities == NULL) { + sta->vht_capabilities = + os_zalloc(sizeof(struct ieee80211_vht_capabilities)); + if (sta->vht_capabilities == NULL) + return WLAN_STATUS_UNSPECIFIED_FAILURE; + } + + sta->flags |= WLAN_STA_VHT | WLAN_STA_VENDOR_VHT; + os_memcpy(sta->vht_capabilities, vht_capab, + sizeof(struct ieee80211_vht_capabilities)); + return WLAN_STATUS_SUCCESS; + +no_capab: + sta->flags &= ~WLAN_STA_VENDOR_VHT; + return WLAN_STATUS_SUCCESS; +} + + +u8 * hostapd_eid_vendor_vht(struct hostapd_data *hapd, u8 *eid) +{ + u8 *pos = eid; + + if (!hapd->iface->current_mode) + return eid; + + *pos++ = WLAN_EID_VENDOR_SPECIFIC; + *pos++ = (5 + /* The Vendor OUI, type and subtype */ + 2 + sizeof(struct ieee80211_vht_capabilities) + + 2 + sizeof(struct ieee80211_vht_operation)); + + WPA_PUT_BE32(pos, (OUI_BROADCOM << 8) | VENDOR_VHT_TYPE); + pos += 4; + *pos++ = VENDOR_VHT_SUBTYPE; + pos = hostapd_eid_vht_capabilities(hapd, pos, 0); + pos = hostapd_eid_vht_operation(hapd, pos); + + return pos; +} + + +u16 set_sta_vht_opmode(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *vht_oper_notif) +{ + if (!vht_oper_notif) { + sta->flags &= ~WLAN_STA_VHT_OPMODE_ENABLED; + return WLAN_STATUS_SUCCESS; + } + + sta->flags |= WLAN_STA_VHT_OPMODE_ENABLED; + sta->vht_opmode = *vht_oper_notif; + return WLAN_STATUS_SUCCESS; +} + + +void hostapd_get_vht_capab(struct hostapd_data *hapd, + struct ieee80211_vht_capabilities *vht_cap, + struct ieee80211_vht_capabilities *neg_vht_cap) +{ + u32 cap, own_cap, sym_caps; + + if (vht_cap == NULL) + return; + os_memcpy(neg_vht_cap, vht_cap, sizeof(*neg_vht_cap)); + + cap = le_to_host32(neg_vht_cap->vht_capabilities_info); + own_cap = hapd->iconf->vht_capab; + + /* mask out symmetric VHT capabilities we don't support */ + sym_caps = VHT_CAP_SHORT_GI_80 | VHT_CAP_SHORT_GI_160; + cap &= ~sym_caps | (own_cap & sym_caps); + + /* mask out beamformer/beamformee caps if not supported */ + if (!(own_cap & VHT_CAP_SU_BEAMFORMER_CAPABLE)) + cap &= ~(VHT_CAP_SU_BEAMFORMEE_CAPABLE | + VHT_CAP_BEAMFORMEE_STS_MAX); + + if (!(own_cap & VHT_CAP_SU_BEAMFORMEE_CAPABLE)) + cap &= ~(VHT_CAP_SU_BEAMFORMER_CAPABLE | + VHT_CAP_SOUNDING_DIMENSION_MAX); + + if (!(own_cap & VHT_CAP_MU_BEAMFORMER_CAPABLE)) + cap &= ~VHT_CAP_MU_BEAMFORMEE_CAPABLE; + + if (!(own_cap & VHT_CAP_MU_BEAMFORMEE_CAPABLE)) + cap &= ~VHT_CAP_MU_BEAMFORMER_CAPABLE; + + /* mask channel widths we don't support */ + switch (own_cap & VHT_CAP_SUPP_CHAN_WIDTH_MASK) { + case VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ: + break; + case VHT_CAP_SUPP_CHAN_WIDTH_160MHZ: + if (cap & VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ) { + cap &= ~VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ; + cap |= VHT_CAP_SUPP_CHAN_WIDTH_160MHZ; + } + break; + default: + cap &= ~VHT_CAP_SUPP_CHAN_WIDTH_MASK; + break; + } + + if (!(cap & VHT_CAP_SUPP_CHAN_WIDTH_MASK)) + cap &= ~VHT_CAP_SHORT_GI_160; + + /* + * if we don't support RX STBC, mask out TX STBC in the STA's HT caps + * if we don't support TX STBC, mask out RX STBC in the STA's HT caps + */ + if (!(own_cap & VHT_CAP_RXSTBC_MASK)) + cap &= ~VHT_CAP_TXSTBC; + if (!(own_cap & VHT_CAP_TXSTBC)) + cap &= ~VHT_CAP_RXSTBC_MASK; + + neg_vht_cap->vht_capabilities_info = host_to_le32(cap); +} diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ieee802_1x.c b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ieee802_1x.c new file mode 100755 index 0000000..1bfd914 --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ieee802_1x.c @@ -0,0 +1,237 @@ +/* + * hostapd / IEEE 802.1X-2004 Authenticator + * Copyright (c) 2002-2019, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "utils/eloop.h" +#include "crypto/md5.h" +#include "crypto/crypto.h" +#include "crypto/random.h" +#include "common/ieee802_11_defs.h" +#include "ap/hostapd.h" +#include "accounting.h" +#include "ap/sta_info.h" +#include "wpa_auth.h" +#include "preauth_auth.h" +#include "ap_config.h" +#include "ap_drv_ops.h" +#include "wps_hostapd.h" +#include "ieee802_1x.h" + + +static void ieee802_1x_finished(struct hostapd_data *hapd, + struct sta_info *sta, int success, + int remediation); + + +void ieee802_1x_set_sta_authorized(struct hostapd_data *hapd, + struct sta_info *sta, int authorized) +{ + int res; + + if (sta->flags & WLAN_STA_PREAUTH) + return; + + if (authorized) { + ap_sta_set_authorized(hapd, sta, 1); + res = hostapd_set_authorized(hapd, sta, 1); + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, + HOSTAPD_LEVEL_DEBUG, "authorizing port"); + } else { + ap_sta_set_authorized(hapd, sta, 0); + res = hostapd_set_authorized(hapd, sta, 0); + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, + HOSTAPD_LEVEL_DEBUG, "unauthorizing port"); + } +#ifdef CONFIG_NO_ACCOUNTING + (void)res; + if (authorized) { + os_get_reltime(&sta->connected_time); + accounting_sta_start(hapd, sta); + } +#endif +} + +/** + * ieee802_1x_receive - Process the EAPOL frames from the Supplicant + * @hapd: hostapd BSS data + * @sa: Source address (sender of the EAPOL frame) + * @buf: EAPOL frame + * @len: Length of buf in octets + * + * This function is called for each incoming EAPOL frame from the interface + */ +void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf, + size_t len) +{ + struct sta_info *sta; + struct ieee802_1x_hdr *hdr; + struct ieee802_1x_eapol_key *key; + u16 datalen; + + if (!hapd->conf->ieee802_1x && !hapd->conf->wpa && !hapd->conf->osen +#ifdef CONFIG_FULL_HOSTAPD + && !hapd->conf->wps_state +#endif + ) + return; + + wpa_printf(MSG_DEBUG, "IEEE 802.1X: %lu bytes from " MACSTR, + (unsigned long) len, MAC2STR(sa)); + sta = ap_get_sta(hapd, sa); + if (!sta || (!(sta->flags & (WLAN_STA_ASSOC | WLAN_STA_PREAUTH)) && + !(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_WIRED))) { + wpa_printf(MSG_DEBUG, "IEEE 802.1X data frame from not " + "associated/Pre-authenticating STA"); + return; + } + + if (len < sizeof(*hdr)) { + wpa_printf(MSG_INFO, " too short IEEE 802.1X packet"); + return; + } + + hdr = (struct ieee802_1x_hdr *) buf; + datalen = be_to_host16(hdr->length); + wpa_printf(MSG_DEBUG, " IEEE 802.1X: version=%d type=%d length=%d", + hdr->version, hdr->type, datalen); + + if (len - sizeof(*hdr) < datalen) { + wpa_printf(MSG_INFO, " frame too short for this IEEE 802.1X packet"); + return; + } + if (len - sizeof(*hdr) > datalen) { + wpa_printf(MSG_DEBUG, " ignoring %lu extra octets after " + "IEEE 802.1X packet", + (unsigned long) len - sizeof(*hdr) - datalen); + } + + + key = (struct ieee802_1x_eapol_key *) (hdr + 1); + if (datalen >= sizeof(struct ieee802_1x_eapol_key) && + hdr->type == IEEE802_1X_TYPE_EAPOL_KEY && + (key->type == EAPOL_KEY_TYPE_WPA || + key->type == EAPOL_KEY_TYPE_RSN)) { + wpa_receive(hapd->wpa_auth, sta->wpa_sm, (u8 *) hdr, + sizeof(*hdr) + datalen); + return; + } +} + +static void ieee802_1x_set_port_authorized(void *ctx, void *sta_ctx, + int authorized) +{ + struct hostapd_data *hapd = ctx; + struct sta_info *sta = sta_ctx; + ieee802_1x_set_sta_authorized(hapd, sta, authorized); +} + +int ieee802_1x_tx_status(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *buf, size_t len, int ack) +{ + struct ieee80211_hdr *hdr; + u8 *pos; + const unsigned char rfc1042_hdr[ETH_ALEN] = + { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; + + if (sta == NULL) + return -1; + if (len < sizeof(*hdr) + sizeof(rfc1042_hdr) + 2) + return 0; + + hdr = (struct ieee80211_hdr *) buf; + pos = (u8 *) (hdr + 1); + if (os_memcmp(pos, rfc1042_hdr, sizeof(rfc1042_hdr)) != 0) + return 0; + pos += sizeof(rfc1042_hdr); + if (WPA_GET_BE16(pos) != ETH_P_PAE) + return 0; + pos += 2; + + return ieee802_1x_eapol_tx_status(hapd, sta, pos, buf + len - pos, + ack); +} + + +int ieee802_1x_eapol_tx_status(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *buf, int len, int ack) +{ + const struct ieee802_1x_hdr *xhdr = + (const struct ieee802_1x_hdr *) buf; + const u8 *pos = buf + sizeof(*xhdr); + struct ieee802_1x_eapol_key *key; + + if (len < (int) sizeof(*xhdr)) + return 0; + wpa_printf(MSG_DEBUG, "IEEE 802.1X: " MACSTR " TX status - version=%d " + "type=%d length=%d - ack=%d", + MAC2STR(sta->addr), xhdr->version, xhdr->type, + be_to_host16(xhdr->length), ack); + + if (xhdr->type != IEEE802_1X_TYPE_EAPOL_KEY) + return 0; + + if (pos + sizeof(struct wpa_eapol_key) <= buf + len) { + const struct wpa_eapol_key *wpa; + wpa = (const struct wpa_eapol_key *) pos; + if (wpa->type == EAPOL_KEY_TYPE_RSN || + wpa->type == EAPOL_KEY_TYPE_WPA) + wpa_auth_eapol_key_tx_status(hapd->wpa_auth, + sta->wpa_sm, ack); + } + + /* EAPOL EAP-Packet packets are eventually re-sent by either Supplicant + * or Authenticator state machines, but EAPOL-Key packets are not + * retransmitted in case of failure. Try to re-send failed EAPOL-Key + * packets couple of times because otherwise STA keys become + * unsynchronized with AP. */ + if (!ack && pos + sizeof(*key) <= buf + len) { + key = (struct ieee802_1x_eapol_key *) pos; + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE8021X, + HOSTAPD_LEVEL_DEBUG, "did not Ack EAPOL-Key " + "frame (%scast index=%d)", + key->key_index & BIT(7) ? "uni" : "broad", + key->key_index & ~BIT(7)); + /* TODO: re-send EAPOL-Key couple of times (with short delay + * between them?). If all attempt fail, report error and + * deauthenticate STA so that it will get new keys when + * authenticating again (e.g., after returning in range). + * Separate limit/transmit state needed both for unicast and + * broadcast keys(?) */ + } + /* TODO: could move unicast key configuration from ieee802_1x_tx_key() + * to here and change the key only if the EAPOL-Key packet was Acked. + */ + (void)key; + + return 1; +} + +void ieee802_1x_notify_port_enabled(struct eapol_state_machine *sm, + int enabled) +{ + if (sm == NULL) + return; +} + + +void ieee802_1x_notify_port_valid(struct eapol_state_machine *sm, + int valid) +{ + if (sm == NULL) + return; +} + + +void ieee802_1x_notify_pre_auth(struct eapol_state_machine *sm, int pre_auth) +{ + if (sm == NULL) + return; +} + diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ieee802_1x.h b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ieee802_1x.h new file mode 100755 index 0000000..bb85b93 --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/ieee802_1x.h @@ -0,0 +1,70 @@ +/* + * hostapd / IEEE 802.1X-2004 Authenticator + * Copyright (c) 2002-2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef IEEE802_1X_H +#define IEEE802_1X_H + +struct hostapd_data; +struct sta_info; +struct eapol_state_machine; +struct hostapd_config; +struct hostapd_bss_config; +struct hostapd_radius_attr; +struct radius_msg; + + +void ieee802_1x_receive(struct hostapd_data *hapd, const u8 *sa, const u8 *buf, + size_t len); +void ieee802_1x_new_station(struct hostapd_data *hapd, struct sta_info *sta); +void ieee802_1x_free_station(struct hostapd_data *hapd, struct sta_info *sta); + +void ieee802_1x_abort_auth(struct hostapd_data *hapd, struct sta_info *sta); +void ieee802_1x_set_sta_authorized(struct hostapd_data *hapd, + struct sta_info *sta, int authorized); +void ieee802_1x_dump_state(FILE *f, const char *prefix, struct sta_info *sta); +int ieee802_1x_init(struct hostapd_data *hapd); +void ieee802_1x_erp_flush(struct hostapd_data *hapd); +void ieee802_1x_deinit(struct hostapd_data *hapd); +int ieee802_1x_tx_status(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *buf, size_t len, int ack); +int ieee802_1x_eapol_tx_status(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *data, int len, int ack); +u8 * ieee802_1x_get_identity(struct eapol_state_machine *sm, size_t *len); +u8 * ieee802_1x_get_radius_class(struct eapol_state_machine *sm, size_t *len, + int idx); +struct wpabuf * ieee802_1x_get_radius_cui(struct eapol_state_machine *sm); +const u8 * ieee802_1x_get_key(struct eapol_state_machine *sm, size_t *len); +const u8 * ieee802_1x_get_session_id(struct eapol_state_machine *sm, + size_t *len); +void ieee802_1x_notify_port_enabled(struct eapol_state_machine *sm, + int enabled); +void ieee802_1x_notify_port_valid(struct eapol_state_machine *sm, + int valid); +void ieee802_1x_notify_pre_auth(struct eapol_state_machine *sm, int pre_auth); +int ieee802_1x_get_mib(struct hostapd_data *hapd, char *buf, size_t buflen); +int ieee802_1x_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta, + char *buf, size_t buflen); +void hostapd_get_ntp_timestamp(u8 *buf); +char *eap_type_text(u8 type); + +const char *radius_mode_txt(struct hostapd_data *hapd); +int radius_sta_rate(struct hostapd_data *hapd, struct sta_info *sta); + +int add_common_radius_attr(struct hostapd_data *hapd, + struct hostapd_radius_attr *req_attr, + struct sta_info *sta, + struct radius_msg *msg); +int add_sqlite_radius_attr(struct hostapd_data *hapd, struct sta_info *sta, + struct radius_msg *msg, int acct); +void ieee802_1x_encapsulate_radius(struct hostapd_data *hapd, + struct sta_info *sta, + const u8 *eap, size_t len); +struct eapol_state_machine * +ieee802_1x_alloc_eapol_sm(struct hostapd_data *hapd, struct sta_info *sta); + +#endif /* IEEE802_1X_H */ diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/p2p_hostapd.h b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/p2p_hostapd.h new file mode 100755 index 0000000..0e3921c --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/p2p_hostapd.h @@ -0,0 +1,35 @@ +/* + * hostapd / P2P integration + * Copyright (c) 2009-2010, Atheros Communications + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef P2P_HOSTAPD_H +#define P2P_HOSTAPD_H + +#ifdef CONFIG_P2P + +int hostapd_p2p_get_mib_sta(struct hostapd_data *hapd, struct sta_info *sta, + char *buf, size_t buflen); +int hostapd_p2p_set_noa(struct hostapd_data *hapd, u8 count, int start, + int duration); +void hostapd_p2p_non_p2p_sta_connected(struct hostapd_data *hapd); +void hostapd_p2p_non_p2p_sta_disconnected(struct hostapd_data *hapd); + + +#else /* CONFIG_P2P */ + +static inline int hostapd_p2p_get_mib_sta(struct hostapd_data *hapd, + struct sta_info *sta, + char *buf, size_t buflen) +{ + return 0; +} + +#endif /* CONFIG_P2P */ + +u8 * hostapd_eid_p2p_manage(struct hostapd_data *hapd, u8 *eid); + +#endif /* P2P_HOSTAPD_H */ diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/pmksa_cache_auth.c b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/pmksa_cache_auth.c new file mode 100755 index 0000000..684ef48 --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/pmksa_cache_auth.c @@ -0,0 +1,667 @@ +/* + * hostapd - PMKSA cache for IEEE 802.11i RSN + * Copyright (c) 2004-2008, 2012-2015, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "utils/eloop.h" +#include "eapol_auth/eapol_auth_sm.h" +#include "eapol_auth/eapol_auth_sm_i.h" +#ifndef CONFIG_NO_RADIUS +#include "radius/radius_das.h" +#endif +#include "ap/sta_info.h" +#include "ap_config.h" +#include "pmksa_cache_auth.h" + + +static const int pmksa_cache_max_entries = 1024; +static const int dot11RSNAConfigPMKLifetime = 43200; + +struct rsn_pmksa_cache { +#define PMKID_HASH_SIZE 8 +#define PMKID_HASH(pmkid) (unsigned int) ((pmkid)[0] & (PMKID_HASH_SIZE - 1)) + struct rsn_pmksa_cache_entry *pmkid[PMKID_HASH_SIZE]; + struct rsn_pmksa_cache_entry *pmksa; + int pmksa_count; + + void (*free_cb)(struct rsn_pmksa_cache_entry *entry, void *ctx); + void *ctx; +}; + + +static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa); + + +static void _pmksa_cache_free_entry(struct rsn_pmksa_cache_entry *entry) +{ + os_free(entry->vlan_desc); + os_free(entry->identity); + wpabuf_free(entry->cui); +#ifndef CONFIG_NO_RADIUS + radius_free_class(&entry->radius_class); +#endif /* CONFIG_NO_RADIUS */ + bin_clear_free(entry, sizeof(*entry)); +} + + +void pmksa_cache_free_entry(struct rsn_pmksa_cache *pmksa, + struct rsn_pmksa_cache_entry *entry) +{ + struct rsn_pmksa_cache_entry *pos, *prev; + unsigned int hash; + + pmksa->pmksa_count--; + pmksa->free_cb(entry, pmksa->ctx); + + /* unlink from hash list */ + hash = PMKID_HASH(entry->pmkid); + pos = pmksa->pmkid[hash]; + prev = NULL; + while (pos) { + if (pos == entry) { + if (prev != NULL) + prev->hnext = entry->hnext; + else + pmksa->pmkid[hash] = entry->hnext; + break; + } + prev = pos; + pos = pos->hnext; + } + + /* unlink from entry list */ + pos = pmksa->pmksa; + prev = NULL; + while (pos) { + if (pos == entry) { + if (prev != NULL) + prev->next = entry->next; + else + pmksa->pmksa = entry->next; + break; + } + prev = pos; + pos = pos->next; + } + + _pmksa_cache_free_entry(entry); +} + + +/** + * pmksa_cache_auth_flush - Flush all PMKSA cache entries + * @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_init() + */ +void pmksa_cache_auth_flush(struct rsn_pmksa_cache *pmksa) +{ + while (pmksa->pmksa) { + wpa_printf(MSG_DEBUG, "RSN: Flush PMKSA cache entry for " + MACSTR, MAC2STR(pmksa->pmksa->spa)); + pmksa_cache_free_entry(pmksa, pmksa->pmksa); + } +} + + +static void pmksa_cache_expire(void *eloop_ctx, void *timeout_ctx) +{ + struct rsn_pmksa_cache *pmksa = eloop_ctx; + struct os_reltime now; + + os_get_reltime(&now); + while (pmksa->pmksa && pmksa->pmksa->expiration <= now.sec) { + wpa_printf(MSG_DEBUG, "RSN: expired PMKSA cache entry for " + MACSTR, MAC2STR(pmksa->pmksa->spa)); + pmksa_cache_free_entry(pmksa, pmksa->pmksa); + } + + pmksa_cache_set_expiration(pmksa); +} + + +static void pmksa_cache_set_expiration(struct rsn_pmksa_cache *pmksa) +{ + int sec; + struct os_reltime now; + + eloop_cancel_timeout(pmksa_cache_expire, pmksa, NULL); + if (pmksa->pmksa == NULL) + return; + os_get_reltime(&now); + sec = pmksa->pmksa->expiration - now.sec; + if (sec < 0) + sec = 0; + eloop_register_timeout(sec + 1, 0, pmksa_cache_expire, pmksa, NULL); +} + +#ifdef IEEE8021X_EAPOL +static void pmksa_cache_from_eapol_data(struct rsn_pmksa_cache_entry *entry, + struct eapol_state_machine *eapol) +{ + struct vlan_description *vlan_desc; + + if (eapol == NULL) + return; + + if (eapol->identity) { + entry->identity = os_malloc(eapol->identity_len); + if (entry->identity) { + entry->identity_len = eapol->identity_len; + os_memcpy(entry->identity, eapol->identity, + eapol->identity_len); + } + } + + if (eapol->radius_cui) + entry->cui = wpabuf_dup(eapol->radius_cui); + +#ifndef CONFIG_NO_RADIUS + radius_copy_class(&entry->radius_class, &eapol->radius_class); +#endif /* CONFIG_NO_RADIUS */ + + entry->eap_type_authsrv = eapol->eap_type_authsrv; + + vlan_desc = ((struct sta_info *) eapol->sta)->vlan_desc; + if (vlan_desc && vlan_desc->notempty) { + entry->vlan_desc = os_zalloc(sizeof(struct vlan_description)); + if (entry->vlan_desc) + *entry->vlan_desc = *vlan_desc; + } else { + entry->vlan_desc = NULL; + } + + entry->acct_multi_session_id = eapol->acct_multi_session_id; +} + + +void pmksa_cache_to_eapol_data(struct hostapd_data *hapd, + struct rsn_pmksa_cache_entry *entry, + struct eapol_state_machine *eapol) +{ + if (entry == NULL || eapol == NULL) + return; + + if (entry->identity) { + os_free(eapol->identity); + eapol->identity = os_malloc(entry->identity_len); + if (eapol->identity) { + eapol->identity_len = entry->identity_len; + os_memcpy(eapol->identity, entry->identity, + entry->identity_len); + } + wpa_hexdump_ascii(MSG_DEBUG, "STA identity from PMKSA", + eapol->identity, eapol->identity_len); + } + + if (entry->cui) { + wpabuf_free(eapol->radius_cui); + eapol->radius_cui = wpabuf_dup(entry->cui); + } + +#ifndef CONFIG_NO_RADIUS + radius_free_class(&eapol->radius_class); + radius_copy_class(&eapol->radius_class, &entry->radius_class); +#endif /* CONFIG_NO_RADIUS */ + if (eapol->radius_class.attr) { + wpa_printf(MSG_DEBUG, "Copied %lu Class attribute(s) from " + "PMKSA", (unsigned long) eapol->radius_class.count); + } + + eapol->eap_type_authsrv = entry->eap_type_authsrv; +#ifndef CONFIG_NO_VLAN + ap_sta_set_vlan(hapd, eapol->sta, entry->vlan_desc); +#endif /* CONFIG_NO_VLAN */ + + eapol->acct_multi_session_id = entry->acct_multi_session_id; +} +#endif /* IEEE8021X_EAPOL */ + + +static void pmksa_cache_link_entry(struct rsn_pmksa_cache *pmksa, + struct rsn_pmksa_cache_entry *entry) +{ + struct rsn_pmksa_cache_entry *pos, *prev; + int hash; + + /* Add the new entry; order by expiration time */ + pos = pmksa->pmksa; + prev = NULL; + while (pos) { + if (pos->expiration > entry->expiration) + break; + prev = pos; + pos = pos->next; + } + if (prev == NULL) { + entry->next = pmksa->pmksa; + pmksa->pmksa = entry; + } else { + entry->next = prev->next; + prev->next = entry; + } + + hash = PMKID_HASH(entry->pmkid); + entry->hnext = pmksa->pmkid[hash]; + pmksa->pmkid[hash] = entry; + + pmksa->pmksa_count++; + if (prev == NULL) + pmksa_cache_set_expiration(pmksa); + wpa_printf(MSG_DEBUG, "RSN: added PMKSA cache entry for " MACSTR, + MAC2STR(entry->spa)); + wpa_hexdump(MSG_DEBUG, "RSN: added PMKID", entry->pmkid, PMKID_LEN); +} + + +/** + * pmksa_cache_auth_add - Add a PMKSA cache entry + * @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_init() + * @pmk: The new pairwise master key + * @pmk_len: PMK length in bytes, usually PMK_LEN (32) + * @pmkid: Calculated PMKID + * @kck: Key confirmation key or %NULL if not yet derived + * @kck_len: KCK length in bytes + * @aa: Authenticator address + * @spa: Supplicant address + * @session_timeout: Session timeout + * @eapol: Pointer to EAPOL state machine data + * @akmp: WPA_KEY_MGMT_* used in key derivation + * Returns: Pointer to the added PMKSA cache entry or %NULL on error + * + * This function create a PMKSA entry for a new PMK and adds it to the PMKSA + * cache. If an old entry is already in the cache for the same Supplicant, + * this entry will be replaced with the new entry. PMKID will be calculated + * based on the PMK. + */ +struct rsn_pmksa_cache_entry * +pmksa_cache_auth_add(struct rsn_pmksa_cache *pmksa, + const u8 *pmk, size_t pmk_len, const u8 *pmkid, + const u8 *kck, size_t kck_len, + const u8 *aa, const u8 *spa, int session_timeout, + struct eapol_state_machine *eapol, int akmp) +{ + struct rsn_pmksa_cache_entry *entry; + + entry = pmksa_cache_auth_create_entry(pmk, pmk_len, pmkid, kck, kck_len, + aa, spa, session_timeout, eapol, + akmp); + + if (pmksa_cache_auth_add_entry(pmksa, entry) < 0) + return NULL; + + return entry; +} + + +/** + * pmksa_cache_auth_create_entry - Create a PMKSA cache entry + * @pmk: The new pairwise master key + * @pmk_len: PMK length in bytes, usually PMK_LEN (32) + * @pmkid: Calculated PMKID + * @kck: Key confirmation key or %NULL if not yet derived + * @kck_len: KCK length in bytes + * @aa: Authenticator address + * @spa: Supplicant address + * @session_timeout: Session timeout + * @eapol: Pointer to EAPOL state machine data + * @akmp: WPA_KEY_MGMT_* used in key derivation + * Returns: Pointer to the added PMKSA cache entry or %NULL on error + * + * This function creates a PMKSA entry. + */ +struct rsn_pmksa_cache_entry * +pmksa_cache_auth_create_entry(const u8 *pmk, size_t pmk_len, const u8 *pmkid, + const u8 *kck, size_t kck_len, const u8 *aa, + const u8 *spa, int session_timeout, + struct eapol_state_machine *eapol, int akmp) +{ + struct rsn_pmksa_cache_entry *entry; + struct os_reltime now; + + if (pmk_len > PMK_LEN_MAX) + return NULL; + + if (wpa_key_mgmt_suite_b(akmp) && !kck) + return NULL; + + entry = os_zalloc(sizeof(*entry)); + if (entry == NULL) + return NULL; + os_memcpy(entry->pmk, pmk, pmk_len); + entry->pmk_len = pmk_len; + if (pmkid) + os_memcpy(entry->pmkid, pmkid, PMKID_LEN); + else if (akmp == WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) + rsn_pmkid_suite_b_192(kck, kck_len, aa, spa, entry->pmkid); + else if (wpa_key_mgmt_suite_b(akmp)) + rsn_pmkid_suite_b(kck, kck_len, aa, spa, entry->pmkid); + else + rsn_pmkid(pmk, pmk_len, aa, spa, entry->pmkid, akmp); + os_get_reltime(&now); + entry->expiration = now.sec; + if (session_timeout > 0) + entry->expiration += session_timeout; + else + entry->expiration += dot11RSNAConfigPMKLifetime; + entry->akmp = akmp; + os_memcpy(entry->spa, spa, ETH_ALEN); +#ifdef IEEE8021X_EAPOL + pmksa_cache_from_eapol_data(entry, eapol); +#endif + + return entry; +} + + +/** + * pmksa_cache_auth_add_entry - Add a PMKSA cache entry + * @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_init() + * @entry: Pointer to PMKSA cache entry + * + * This function adds PMKSA cache entry to the PMKSA cache. If an old entry is + * already in the cache for the same Supplicant, this entry will be replaced + * with the new entry. PMKID will be calculated based on the PMK. + */ +int pmksa_cache_auth_add_entry(struct rsn_pmksa_cache *pmksa, + struct rsn_pmksa_cache_entry *entry) +{ + struct rsn_pmksa_cache_entry *pos; + + if (entry == NULL) + return -1; + + /* Replace an old entry for the same STA (if found) with the new entry + */ + pos = pmksa_cache_auth_get(pmksa, entry->spa, NULL); + if (pos) + pmksa_cache_free_entry(pmksa, pos); + + if (pmksa->pmksa_count >= pmksa_cache_max_entries && pmksa->pmksa) { + /* Remove the oldest entry to make room for the new entry */ + wpa_printf(MSG_DEBUG, "RSN: removed the oldest PMKSA cache " + "entry (for " MACSTR ") to make room for new one", + MAC2STR(pmksa->pmksa->spa)); + pmksa_cache_free_entry(pmksa, pmksa->pmksa); + } + + pmksa_cache_link_entry(pmksa, entry); + + return 0; +} + + +struct rsn_pmksa_cache_entry * +pmksa_cache_add_okc(struct rsn_pmksa_cache *pmksa, + const struct rsn_pmksa_cache_entry *old_entry, + const u8 *aa, const u8 *pmkid) +{ + struct rsn_pmksa_cache_entry *entry; + + entry = os_zalloc(sizeof(*entry)); + if (entry == NULL) + return NULL; + os_memcpy(entry->pmkid, pmkid, PMKID_LEN); + os_memcpy(entry->pmk, old_entry->pmk, old_entry->pmk_len); + entry->pmk_len = old_entry->pmk_len; + entry->expiration = old_entry->expiration; + entry->akmp = old_entry->akmp; + os_memcpy(entry->spa, old_entry->spa, ETH_ALEN); + entry->opportunistic = 1; + if (old_entry->identity) { + entry->identity = os_malloc(old_entry->identity_len); + if (entry->identity) { + entry->identity_len = old_entry->identity_len; + os_memcpy(entry->identity, old_entry->identity, + old_entry->identity_len); + } + } + if (old_entry->cui) + entry->cui = wpabuf_dup(old_entry->cui); +#ifndef CONFIG_NO_RADIUS + radius_copy_class(&entry->radius_class, &old_entry->radius_class); +#endif /* CONFIG_NO_RADIUS */ + entry->eap_type_authsrv = old_entry->eap_type_authsrv; + if (old_entry->vlan_desc) { + entry->vlan_desc = os_zalloc(sizeof(struct vlan_description)); + if (entry->vlan_desc) + *entry->vlan_desc = *old_entry->vlan_desc; + } else { + entry->vlan_desc = NULL; + } + entry->opportunistic = 1; + + pmksa_cache_link_entry(pmksa, entry); + + return entry; +} + + +/** + * pmksa_cache_auth_deinit - Free all entries in PMKSA cache + * @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_init() + */ +void pmksa_cache_auth_deinit(struct rsn_pmksa_cache *pmksa) +{ + struct rsn_pmksa_cache_entry *entry, *prev; + int i; + + if (pmksa == NULL) + return; + + entry = pmksa->pmksa; + while (entry) { + prev = entry; + entry = entry->next; + _pmksa_cache_free_entry(prev); + } + eloop_cancel_timeout(pmksa_cache_expire, pmksa, NULL); + pmksa->pmksa_count = 0; + pmksa->pmksa = NULL; + for (i = 0; i < PMKID_HASH_SIZE; i++) + pmksa->pmkid[i] = NULL; + os_free(pmksa); +} + + +/** + * pmksa_cache_auth_get - Fetch a PMKSA cache entry + * @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_init() + * @spa: Supplicant address or %NULL to match any + * @pmkid: PMKID or %NULL to match any + * Returns: Pointer to PMKSA cache entry or %NULL if no match was found + */ +struct rsn_pmksa_cache_entry * +pmksa_cache_auth_get(struct rsn_pmksa_cache *pmksa, + const u8 *spa, const u8 *pmkid) +{ + struct rsn_pmksa_cache_entry *entry; + + if (pmkid) { + for (entry = pmksa->pmkid[PMKID_HASH(pmkid)]; entry; + entry = entry->hnext) { + if ((spa == NULL || + os_memcmp(entry->spa, spa, ETH_ALEN) == 0) && + os_memcmp(entry->pmkid, pmkid, PMKID_LEN) == 0) + return entry; + } + } else { + for (entry = pmksa->pmksa; entry; entry = entry->next) { + if (spa == NULL || + os_memcmp(entry->spa, spa, ETH_ALEN) == 0) + return entry; + } + } + + return NULL; +} + + +/** + * pmksa_cache_get_okc - Fetch a PMKSA cache entry using OKC + * @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_init() + * @aa: Authenticator address + * @spa: Supplicant address + * @pmkid: PMKID + * Returns: Pointer to PMKSA cache entry or %NULL if no match was found + * + * Use opportunistic key caching (OKC) to find a PMK for a supplicant. + */ +struct rsn_pmksa_cache_entry * pmksa_cache_get_okc( + struct rsn_pmksa_cache *pmksa, const u8 *aa, const u8 *spa, + const u8 *pmkid) +{ + struct rsn_pmksa_cache_entry *entry; + u8 new_pmkid[PMKID_LEN]; + + for (entry = pmksa->pmksa; entry; entry = entry->next) { + if (os_memcmp(entry->spa, spa, ETH_ALEN) != 0) + continue; + rsn_pmkid(entry->pmk, entry->pmk_len, aa, spa, new_pmkid, + entry->akmp); + if (os_memcmp(new_pmkid, pmkid, PMKID_LEN) == 0) + return entry; + } + return NULL; +} + + +/** + * pmksa_cache_auth_init - Initialize PMKSA cache + * @free_cb: Callback function to be called when a PMKSA cache entry is freed + * @ctx: Context pointer for free_cb function + * Returns: Pointer to PMKSA cache data or %NULL on failure + */ +struct rsn_pmksa_cache * +pmksa_cache_auth_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry, + void *ctx), void *ctx) +{ + struct rsn_pmksa_cache *pmksa; + + pmksa = os_zalloc(sizeof(*pmksa)); + if (pmksa) { + pmksa->free_cb = free_cb; + pmksa->ctx = ctx; + } + + return pmksa; +} + +#ifdef CONFIG_FULL_HOSTAPD +static int das_attr_match(struct rsn_pmksa_cache_entry *entry, + struct radius_das_attrs *attr) +{ + int match = 0; + + if (attr->sta_addr) { + if (os_memcmp(attr->sta_addr, entry->spa, ETH_ALEN) != 0) + return 0; + match++; + } + + if (attr->acct_multi_session_id) { + char buf[20]; + + if (attr->acct_multi_session_id_len != 16) + return 0; + os_snprintf(buf, sizeof(buf), "%016llX", + (unsigned long long) entry->acct_multi_session_id); + if (os_memcmp(attr->acct_multi_session_id, buf, 16) != 0) + return 0; + match++; + } + + if (attr->cui) { + if (!entry->cui || + attr->cui_len != wpabuf_len(entry->cui) || + os_memcmp(attr->cui, wpabuf_head(entry->cui), + attr->cui_len) != 0) + return 0; + match++; + } + + if (attr->user_name) { + if (!entry->identity || + attr->user_name_len != entry->identity_len || + os_memcmp(attr->user_name, entry->identity, + attr->user_name_len) != 0) + return 0; + match++; + } + + return match; +} + + +int pmksa_cache_auth_radius_das_disconnect(struct rsn_pmksa_cache *pmksa, + struct radius_das_attrs *attr) +{ + int found = 0; + struct rsn_pmksa_cache_entry *entry, *prev; + + if (attr->acct_session_id) + return -1; + + entry = pmksa->pmksa; + while (entry) { + if (das_attr_match(entry, attr)) { + found++; + prev = entry; + entry = entry->next; + pmksa_cache_free_entry(pmksa, prev); + continue; + } + entry = entry->next; + } + + return found ? 0 : -1; +} +#endif + +/** + * pmksa_cache_auth_list - Dump text list of entries in PMKSA cache + * @pmksa: Pointer to PMKSA cache data from pmksa_cache_auth_init() + * @buf: Buffer for the list + * @len: Length of the buffer + * Returns: Number of bytes written to buffer + * + * This function is used to generate a text format representation of the + * current PMKSA cache contents for the ctrl_iface PMKSA command. + */ +int pmksa_cache_auth_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len) +{ + int i, ret; + char *pos = buf; + struct rsn_pmksa_cache_entry *entry; + struct os_reltime now; + + os_get_reltime(&now); + ret = os_snprintf(pos, buf + len - pos, + "Index / SPA / PMKID / expiration (in seconds) / opportunistic\n"); + if (os_snprintf_error(buf + len - pos, ret)) + return pos - buf; + pos += ret; + i = 0; + entry = pmksa->pmksa; + while (entry) { + ret = os_snprintf(pos, buf + len - pos, "%d " MACSTR " ", + i, MAC2STR(entry->spa)); + if (os_snprintf_error(buf + len - pos, ret)) + return pos - buf; + pos += ret; + pos += wpa_snprintf_hex(pos, buf + len - pos, entry->pmkid, + PMKID_LEN); + ret = os_snprintf(pos, buf + len - pos, " %d %d\n", + (int) (entry->expiration - now.sec), + entry->opportunistic); + if (os_snprintf_error(buf + len - pos, ret)) + return pos - buf; + pos += ret; + entry = entry->next; + } + return pos - buf; +} diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/pmksa_cache_auth.h b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/pmksa_cache_auth.h new file mode 100755 index 0000000..9f5ee30 --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/pmksa_cache_auth.h @@ -0,0 +1,78 @@ +/* + * hostapd - PMKSA cache for IEEE 802.11i RSN + * Copyright (c) 2004-2008, 2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef PMKSA_CACHE_H +#define PMKSA_CACHE_H + +//#include "radius/radius.h" + +/** + * struct rsn_pmksa_cache_entry - PMKSA cache entry + */ +struct rsn_pmksa_cache_entry { + struct rsn_pmksa_cache_entry *next, *hnext; + u8 pmkid[PMKID_LEN]; + u8 pmk[PMK_LEN_MAX]; + size_t pmk_len; + os_time_t expiration; + int akmp; /* WPA_KEY_MGMT_* */ + u8 spa[ETH_ALEN]; + + u8 *identity; + size_t identity_len; + struct wpabuf *cui; + //struct radius_class_data radius_class; + u8 eap_type_authsrv; + struct vlan_description *vlan_desc; + int opportunistic; + + u64 acct_multi_session_id; +}; + +struct rsn_pmksa_cache; + +struct rsn_pmksa_cache * +pmksa_cache_auth_init(void (*free_cb)(struct rsn_pmksa_cache_entry *entry, + void *ctx), void *ctx); +void pmksa_cache_auth_deinit(struct rsn_pmksa_cache *pmksa); +struct rsn_pmksa_cache_entry * +pmksa_cache_auth_get(struct rsn_pmksa_cache *pmksa, + const u8 *spa, const u8 *pmkid); +struct rsn_pmksa_cache_entry * pmksa_cache_get_okc( + struct rsn_pmksa_cache *pmksa, const u8 *spa, const u8 *aa, + const u8 *pmkid); +struct rsn_pmksa_cache_entry * +pmksa_cache_auth_add(struct rsn_pmksa_cache *pmksa, + const u8 *pmk, size_t pmk_len, const u8 *pmkid, + const u8 *kck, size_t kck_len, + const u8 *aa, const u8 *spa, int session_timeout, + struct eapol_state_machine *eapol, int akmp); +struct rsn_pmksa_cache_entry * +pmksa_cache_auth_create_entry(const u8 *pmk, size_t pmk_len, const u8 *pmkid, + const u8 *kck, size_t kck_len, const u8 *aa, + const u8 *spa, int session_timeout, + struct eapol_state_machine *eapol, int akmp); +int pmksa_cache_auth_add_entry(struct rsn_pmksa_cache *pmksa, + struct rsn_pmksa_cache_entry *entry); +struct rsn_pmksa_cache_entry * +pmksa_cache_add_okc(struct rsn_pmksa_cache *pmksa, + const struct rsn_pmksa_cache_entry *old_entry, + const u8 *aa, const u8 *pmkid); +void pmksa_cache_to_eapol_data(struct hostapd_data *hapd, + struct rsn_pmksa_cache_entry *entry, + struct eapol_state_machine *eapol); +void pmksa_cache_free_entry(struct rsn_pmksa_cache *pmksa, + struct rsn_pmksa_cache_entry *entry); +//int pmksa_cache_auth_radius_das_disconnect(struct rsn_pmksa_cache *pmksa, +// struct radius_das_attrs *attr); +int pmksa_cache_auth_list(struct rsn_pmksa_cache *pmksa, char *buf, size_t len); +void pmksa_cache_auth_flush(struct rsn_pmksa_cache *pmksa); +int pmksa_cache_auth_list_mesh(struct rsn_pmksa_cache *pmksa, const u8 *addr, + char *buf, size_t len); + +#endif /* PMKSA_CACHE_H */ diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/preauth_auth.h b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/preauth_auth.h new file mode 100755 index 0000000..69fb356 --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/preauth_auth.h @@ -0,0 +1,52 @@ +/* + * hostapd - Authenticator for IEEE 802.11i RSN pre-authentication + * Copyright (c) 2004-2005, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef PREAUTH_H +#define PREAUTH_H + +#ifdef CONFIG_RSN_PREAUTH + +int rsn_preauth_iface_init(struct hostapd_data *hapd); +void rsn_preauth_iface_deinit(struct hostapd_data *hapd); +void rsn_preauth_finished(struct hostapd_data *hapd, struct sta_info *sta, + int success); +void rsn_preauth_send(struct hostapd_data *hapd, struct sta_info *sta, + u8 *buf, size_t len); +void rsn_preauth_free_station(struct hostapd_data *hapd, struct sta_info *sta); + +#else /* CONFIG_RSN_PREAUTH */ + +static inline int rsn_preauth_iface_init(struct hostapd_data *hapd) +{ + return 0; +} + +static inline void rsn_preauth_iface_deinit(struct hostapd_data *hapd) +{ +} + +static inline void rsn_preauth_finished(struct hostapd_data *hapd, + struct sta_info *sta, + int success) +{ +} + +static inline void rsn_preauth_send(struct hostapd_data *hapd, + struct sta_info *sta, + u8 *buf, size_t len) +{ +} + +static inline void rsn_preauth_free_station(struct hostapd_data *hapd, + struct sta_info *sta) +{ +} + +#endif /* CONFIG_RSN_PREAUTH */ + +#endif /* PREAUTH_H */ diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/sta_info.c b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/sta_info.c new file mode 100755 index 0000000..96e71be --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/sta_info.c @@ -0,0 +1,1338 @@ +/* + * hostapd / Station table + * Copyright (c) 2002-2013, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ +#include "utils/includes.h" +#include "utils/common.h" +#include "utils/eloop.h" +#include "common/ieee802_11_defs.h" +#include "common/wpa_ctrl.h" +#include "common/sae.h" +#include "common/dpp.h" +#include "crypto/crypto.h" +#include "ap/hostapd.h" +#include "accounting.h" +#include "ieee802_1x.h" +#include "ieee802_11.h" +#include "ieee802_11_auth.h" +#include "wpa_auth.h" +#include "preauth_auth.h" +#include "ap_config.h" +#include "beacon.h" +#include "ap_mlme.h" +#include "vlan_init.h" +#include "p2p_hostapd.h" +#include "ap_drv_ops.h" +#include "ap/sta_info.h" +#include "vlan.h" + +#include "include.h" +#include "uart_pub.h" + +static void ap_sta_remove_in_other_bss(struct hostapd_data *hapd, + struct sta_info *sta); +static void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx); +static void ap_handle_session_warning_timer(void *eloop_ctx, void *timeout_ctx); +static void ap_sta_deauth_cb_timeout(void *eloop_ctx, void *timeout_ctx); +static void ap_sta_disassoc_cb_timeout(void *eloop_ctx, void *timeout_ctx); +#ifdef CONFIG_IEEE80211W_AP +static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx); +#endif /* CONFIG_IEEE80211W_AP */ +static int ap_sta_remove(struct hostapd_data *hapd, struct sta_info *sta); +static void ap_sta_delayed_1x_auth_fail_cb(void *eloop_ctx, void *timeout_ctx); + +int ap_for_each_sta(struct hostapd_data *hapd, + int (*cb)(struct hostapd_data *hapd, struct sta_info *sta, + void *ctx), + void *ctx) +{ + struct sta_info *sta; + + for (sta = hapd->sta_list; sta; sta = sta->next) { + if (cb(hapd, sta, ctx)) + return 1; + } + + return 0; +} + + +struct sta_info * ap_get_sta(struct hostapd_data *hapd, const u8 *sta) +{ + struct sta_info *s; + + s = hapd->sta_hash[STA_HASH(sta)]; + while (s != NULL && os_memcmp(s->addr, sta, 6) != 0) + s = s->hnext; + return s; +} + + +#ifdef CONFIG_P2P +struct sta_info * ap_get_sta_p2p(struct hostapd_data *hapd, const u8 *addr) +{ + struct sta_info *sta; + + for (sta = hapd->sta_list; sta; sta = sta->next) { + const u8 *p2p_dev_addr; + + if (sta->p2p_ie == NULL) + continue; + + p2p_dev_addr = p2p_get_go_dev_addr(sta->p2p_ie); + if (p2p_dev_addr == NULL) + continue; + + if (os_memcmp(p2p_dev_addr, addr, ETH_ALEN) == 0) + return sta; + } + + return NULL; +} +#endif /* CONFIG_P2P */ + + +static void ap_sta_list_del(struct hostapd_data *hapd, struct sta_info *sta) +{ + struct sta_info *tmp; + + if (hapd->sta_list == sta) { + hapd->sta_list = sta->next; + return; + } + + tmp = hapd->sta_list; + while (tmp != NULL && tmp->next != sta) + tmp = tmp->next; + if (tmp == NULL) { + wpa_printf(MSG_DEBUG, "Could not remove STA " MACSTR " from " + "list.", MAC2STR(sta->addr)); + } else + tmp->next = sta->next; +} + + +void ap_sta_hash_add(struct hostapd_data *hapd, struct sta_info *sta) +{ + sta->hnext = hapd->sta_hash[STA_HASH(sta->addr)]; + hapd->sta_hash[STA_HASH(sta->addr)] = sta; +} + + +static void ap_sta_hash_del(struct hostapd_data *hapd, struct sta_info *sta) +{ + struct sta_info *s; + + s = hapd->sta_hash[STA_HASH(sta->addr)]; + if (s == NULL) return; + if (os_memcmp(s->addr, sta->addr, 6) == 0) { + hapd->sta_hash[STA_HASH(sta->addr)] = s->hnext; + return; + } + + while (s->hnext != NULL && + os_memcmp(s->hnext->addr, sta->addr, ETH_ALEN) != 0) + s = s->hnext; + if (s->hnext != NULL) + s->hnext = s->hnext->hnext; + else + wpa_printf(MSG_DEBUG, "AP: could not remove STA " MACSTR + " from hash table", MAC2STR(sta->addr)); +} + + +void ap_sta_ip6addr_del(struct hostapd_data *hapd, struct sta_info *sta) +{ + //sta_ip6addr_del(hapd, sta); +} + + +void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta) +{ + int set_beacon = 0; + + accounting_sta_stop(hapd, sta); + + /* just in case */ + ap_sta_set_authorized(hapd, sta, 0); + +#ifdef CONFIG_FULL_HOSTAPD + if (sta->flags & (WLAN_STA_WDS | WLAN_STA_MULTI_AP)) + hostapd_set_wds_sta(hapd, NULL, sta->addr, sta->aid, 0); + + if (sta->ipaddr) + hostapd_drv_br_delete_ip_neigh(hapd, 4, (u8 *) &sta->ipaddr); +#endif + ap_sta_ip6addr_del(hapd, sta); + + if (!hapd->iface->driver_ap_teardown && + !(sta->flags & WLAN_STA_PREAUTH)) { + hostapd_drv_sta_remove(hapd, sta->addr); + sta->added_unassoc = 0; + } + + ap_sta_hash_del(hapd, sta); + ap_sta_list_del(hapd, sta); + + if (sta->aid > 0) + hapd->sta_aid[(sta->aid - 1) / 32] &= + ~BIT((sta->aid - 1) % 32); + + hapd->num_sta--; + if (sta->nonerp_set) { + sta->nonerp_set = 0; + hapd->iface->num_sta_non_erp--; + if (hapd->iface->num_sta_non_erp == 0) + set_beacon++; + } + + if (sta->no_short_slot_time_set) { + sta->no_short_slot_time_set = 0; + hapd->iface->num_sta_no_short_slot_time--; + if (hapd->iface->current_mode && + hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G + && hapd->iface->num_sta_no_short_slot_time == 0) + set_beacon++; + } + + if (sta->no_short_preamble_set) { + sta->no_short_preamble_set = 0; + hapd->iface->num_sta_no_short_preamble--; + if (hapd->iface->current_mode && + hapd->iface->current_mode->mode == HOSTAPD_MODE_IEEE80211G + && hapd->iface->num_sta_no_short_preamble == 0) + set_beacon++; + } + + if (sta->no_ht_gf_set) { + sta->no_ht_gf_set = 0; + hapd->iface->num_sta_ht_no_gf--; + } + + if (sta->no_ht_set) { + sta->no_ht_set = 0; + hapd->iface->num_sta_no_ht--; + } + + if (sta->ht_20mhz_set) { + sta->ht_20mhz_set = 0; + hapd->iface->num_sta_ht_20mhz--; + } + +#ifdef CONFIG_IEEE80211N + ht40_intolerant_remove(hapd->iface, sta); +#endif /* CONFIG_IEEE80211N */ + +#ifdef CONFIG_P2P + if (sta->no_p2p_set) { + sta->no_p2p_set = 0; + hapd->num_sta_no_p2p--; + if (hapd->num_sta_no_p2p == 0) + hostapd_p2p_non_p2p_sta_disconnected(hapd); + } +#endif /* CONFIG_P2P */ + +#if defined(NEED_AP_MLME) && defined(CONFIG_IEEE80211N) + if (hostapd_ht_operation_update(hapd->iface) > 0) + set_beacon++; +#endif /* NEED_AP_MLME && CONFIG_IEEE80211N */ + +#ifdef CONFIG_MESH + if (hapd->mesh_sta_free_cb) + hapd->mesh_sta_free_cb(hapd, sta); +#endif /* CONFIG_MESH */ + + if (set_beacon) + ieee802_11_set_beacons(hapd->iface); + + wpa_printf(MSG_DEBUG, "%s: cancel ap_handle_timer for " MACSTR, + __func__, MAC2STR(sta->addr)); + eloop_cancel_timeout(ap_handle_timer, hapd, sta); + eloop_cancel_timeout(ap_handle_session_timer, hapd, sta); + eloop_cancel_timeout(ap_handle_session_warning_timer, hapd, sta); + ap_sta_clear_disconnect_timeouts(hapd, sta); + sae_clear_retransmit_timer(hapd, sta); +#ifdef IEEE8021X_EAPOL + ieee802_1x_free_station(hapd, sta); +#endif + wpa_auth_sta_deinit(sta->wpa_sm); + rsn_preauth_free_station(hapd, sta); +#ifndef CONFIG_NO_RADIUS + if (hapd->radius) + radius_client_flush_auth(hapd->radius, sta->addr); +#endif /* CONFIG_NO_RADIUS */ + +#ifndef CONFIG_NO_VLAN + /* + * sta->wpa_sm->group needs to be released before so that + * vlan_remove_dynamic() can check that no stations are left on the + * AP_VLAN netdev. + */ + if (sta->vlan_id) + vlan_remove_dynamic(hapd, sta->vlan_id); + if (sta->vlan_id_bound) { + /* + * Need to remove the STA entry before potentially removing the + * VLAN. + */ + if (hapd->iface->driver_ap_teardown && + !(sta->flags & WLAN_STA_PREAUTH)) { + hostapd_drv_sta_remove(hapd, sta->addr); + sta->added_unassoc = 0; + } + vlan_remove_dynamic(hapd, sta->vlan_id_bound); + } +#endif /* CONFIG_NO_VLAN */ + + os_free(sta->challenge); + +#ifdef CONFIG_IEEE80211W_AP + os_free(sta->sa_query_trans_id); + eloop_cancel_timeout(ap_sa_query_timer, hapd, sta); +#endif /* CONFIG_IEEE80211W_AP */ + +#ifdef CONFIG_P2P + p2p_group_notif_disassoc(hapd->p2p_group, sta->addr); +#endif /* CONFIG_P2P */ + + wpabuf_free(sta->wps_ie); + wpabuf_free(sta->p2p_ie); + + os_free(sta->ht_capabilities); + os_free(sta->vht_capabilities); + os_free(sta->vht_operation); + os_free(sta->he_capab); + hostapd_free_psk_list(sta->psk); + +#ifdef CONFIG_SAE_AP + sae_clear_data(sta->sae); + os_free(sta->sae); +#endif /* CONFIG_SAE_AP */ + +#ifdef CONFIG_MBO + mbo_ap_sta_free(sta); +#endif + os_free(sta->supp_op_classes); + +#ifdef CONFIG_OWE + bin_clear_free(sta->owe_pmk, sta->owe_pmk_len); + crypto_ecdh_deinit(sta->owe_ecdh); +#endif /* CONFIG_OWE */ + +#ifdef CONFIG_DPP2 + dpp_pfs_free(sta->dpp_pfs); + sta->dpp_pfs = NULL; +#endif /* CONFIG_DPP2 */ + + os_free(sta->ext_capability); + +#ifdef CONFIG_WNM_AP + eloop_cancel_timeout(ap_sta_reset_steer_flag_timer, hapd, sta); +#endif /* CONFIG_WNM_AP */ + + os_free(sta->ifname_wds); + + os_free(sta); +} + + +void hostapd_free_stas(struct hostapd_data *hapd) +{ + struct sta_info *sta, *prev; + + sta = hapd->sta_list; + + while (sta) { + prev = sta; + if (sta->flags & WLAN_STA_AUTH) { + mlme_deauthenticate_indication( + hapd, sta, WLAN_REASON_UNSPECIFIED); + } + sta = sta->next; + wpa_printf(MSG_DEBUG, "Removing station " MACSTR, + MAC2STR(prev->addr)); + ap_free_sta(hapd, prev); + } +} + + +/** + * ap_handle_timer - Per STA timer handler + * @eloop_ctx: struct hostapd_data * + * @timeout_ctx: struct sta_info * + * + * This function is called to check station activity and to remove inactive + * stations. + */ +void ap_handle_timer(void *eloop_ctx, void *timeout_ctx) +{ + struct hostapd_data *hapd = eloop_ctx; + struct sta_info *sta = timeout_ctx; + unsigned long next_time = 0; + int reason; + +#if 0 + wpa_printf(MSG_DEBUG, "%s: %s: " MACSTR " flags=0x%x timeout_next=%d", + hapd->conf->iface, __func__, MAC2STR(sta->addr), sta->flags, + sta->timeout_next); +#endif + os_printf("ap_handle_timer\r\n"); + if (sta->timeout_next == STA_REMOVE) { + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, "deauthenticated due to " + "local deauth request"); + ap_free_sta(hapd, sta); + return; + } + + if ((sta->flags & WLAN_STA_ASSOC) && + (sta->timeout_next == STA_NULLFUNC || + sta->timeout_next == STA_DISASSOC)) { + int inactive_sec; + /* + * Add random value to timeout so that we don't end up bouncing + * all stations at the same time if we have lots of associated + * stations that are idle (but keep re-associating). + */ + int fuzz = 0; /*os_random() % 20;*/ + inactive_sec = hostapd_drv_get_inact_sec(hapd, sta->addr); + //os_printf("inactive_sec:%d fuzz:%d\r\n", inactive_sec, fuzz); + if (inactive_sec == -1) { + os_printf("Check inactivity: Could not " + "get station info from kernel driver for " + MACSTR, MAC2STR(sta->addr)); + /* + * The driver may not support this functionality. + * Anyway, try again after the next inactivity timeout, + * but do not disconnect the station now. + */ + next_time = hapd->conf->ap_max_inactivity + fuzz; + } else if (inactive_sec == -ERRNOENT) { + os_printf("Station " MACSTR " has lost its driver entry", + MAC2STR(sta->addr)); + + /* Avoid sending client probe on removed client */ + sta->timeout_next = STA_DISASSOC; + goto skip_poll; + } else if (inactive_sec < hapd->conf->ap_max_inactivity) { + /* station activity detected; reset timeout state */ + wpa_msg(hapd->msg_ctx, MSG_DEBUG, + "Station " MACSTR " has been active %is ago", + MAC2STR(sta->addr), inactive_sec); + sta->timeout_next = STA_NULLFUNC; + next_time = hapd->conf->ap_max_inactivity + fuzz - + inactive_sec; + }else if(STA_DISASSOC == sta->timeout_next){ + sta->timeout_next = STA_REMOVE; + os_printf("STA_REMOVE\r\n"); + } else { + wpa_msg(hapd->msg_ctx, MSG_DEBUG, + "Station " MACSTR " has been " + "inactive too long: %d sec, max allowed: %d", + MAC2STR(sta->addr), inactive_sec, + hapd->conf->ap_max_inactivity); + + if (hapd->conf->skip_inactivity_poll) + sta->timeout_next = STA_DISASSOC; + } + } + + if ((sta->flags & WLAN_STA_ASSOC) && + sta->timeout_next == STA_DISASSOC && + !(sta->flags & WLAN_STA_PENDING_POLL) && + !hapd->conf->skip_inactivity_poll) { + wpa_msg(hapd->msg_ctx, MSG_DEBUG, "Station " MACSTR + " has ACKed data poll", MAC2STR(sta->addr)); + /* data nullfunc frame poll did not produce TX errors; assume + * station ACKed it */ + sta->timeout_next = STA_NULLFUNC; + next_time = hapd->conf->ap_max_inactivity; + } + +skip_poll: + if (next_time) { + wpa_printf(MSG_DEBUG, "%s: register ap_handle_timer timeout " + "for " MACSTR " (%lu seconds)", + __func__, MAC2STR(sta->addr), next_time); + eloop_register_timeout(next_time, 0, ap_handle_timer, hapd, + sta); + return; + } + + if (sta->timeout_next == STA_NULLFUNC && + (sta->flags & WLAN_STA_ASSOC)) { + wpa_printf(MSG_DEBUG, " Polling STA"); + sta->flags |= WLAN_STA_PENDING_POLL; + hostapd_drv_poll_client(hapd, hapd->own_addr, sta->addr, + sta->flags & WLAN_STA_WMM); + } else if (sta->timeout_next != STA_REMOVE) { + int deauth = sta->timeout_next == STA_DEAUTH; + + if (!deauth && !(sta->flags & WLAN_STA_ASSOC)) { + /* Cannot disassociate not-associated STA, so move + * directly to deauthentication. */ + sta->timeout_next = STA_DEAUTH; + deauth = 1; + } + + wpa_dbg(hapd->msg_ctx, MSG_DEBUG, + "Timeout, sending %s info to STA " MACSTR, + deauth ? "deauthentication" : "disassociation", + MAC2STR(sta->addr)); + + if (deauth) { + hostapd_drv_sta_deauth( + hapd, sta->addr, + WLAN_REASON_PREV_AUTH_NOT_VALID); + } else { + reason = (sta->timeout_next == STA_DISASSOC) ? + WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY : + WLAN_REASON_PREV_AUTH_NOT_VALID; + os_printf("hostapd_drv_sta_disassoc\r\n"); + hostapd_drv_sta_disassoc(hapd, sta->addr, reason); + } + } + + switch (sta->timeout_next) { + case STA_NULLFUNC: + sta->timeout_next = STA_DISASSOC; + wpa_printf(MSG_DEBUG, "%s: register ap_handle_timer timeout " + "for " MACSTR " (%d seconds - AP_DISASSOC_DELAY)", + __func__, MAC2STR(sta->addr), AP_DISASSOC_DELAY); + eloop_register_timeout(AP_DISASSOC_DELAY, 0, ap_handle_timer, + hapd, sta); + break; + case STA_DISASSOC: + case STA_DISASSOC_FROM_CLI: + ap_sta_set_authorized(hapd, sta, 0); + sta->flags &= ~WLAN_STA_ASSOC; + ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); +#if 0 + if (!sta->acct_terminate_cause) + sta->acct_terminate_cause = + RADIUS_ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT; +#endif + accounting_sta_stop(hapd, sta); +#ifdef CONFIG_MBO + ieee802_1x_free_station(hapd, sta); +#endif + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, "disassociated due to " + "inactivity"); + reason = (sta->timeout_next == STA_DISASSOC) ? + WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY : + WLAN_REASON_PREV_AUTH_NOT_VALID; + sta->timeout_next = STA_DEAUTH; + wpa_printf(MSG_DEBUG, "%s: register ap_handle_timer timeout " + "for " MACSTR " (%d seconds - AP_DEAUTH_DELAY)", + __func__, MAC2STR(sta->addr), AP_DEAUTH_DELAY); + eloop_register_timeout(AP_DEAUTH_DELAY, 0, ap_handle_timer, + hapd, sta); + mlme_disassociate_indication(hapd, sta, reason); + break; + case STA_DEAUTH: + case STA_REMOVE: + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, "deauthenticated due to " + "inactivity (timer DEAUTH/REMOVE)"); +#if 0 + if (!sta->acct_terminate_cause) + sta->acct_terminate_cause = + RADIUS_ACCT_TERMINATE_CAUSE_IDLE_TIMEOUT; +#endif + os_printf("ap_free_sta\r\n"); + mlme_deauthenticate_indication( + hapd, sta, + WLAN_REASON_PREV_AUTH_NOT_VALID); + ap_free_sta(hapd, sta); + break; + } +} + + +static void ap_handle_session_timer(void *eloop_ctx, void *timeout_ctx) +{ + struct hostapd_data *hapd = eloop_ctx; + struct sta_info *sta = timeout_ctx; + + wpa_printf(MSG_DEBUG, "%s: Session timer for STA " MACSTR, + hapd->conf->iface, MAC2STR(sta->addr)); + if (!(sta->flags & WLAN_STA_AUTH)) { + if (sta->flags & WLAN_STA_GAS) { + wpa_printf(MSG_DEBUG, "GAS: Remove temporary STA " + "entry " MACSTR, MAC2STR(sta->addr)); + ap_free_sta(hapd, sta); + } + return; + } + + hostapd_drv_sta_deauth(hapd, sta->addr, + WLAN_REASON_PREV_AUTH_NOT_VALID); + mlme_deauthenticate_indication(hapd, sta, + WLAN_REASON_PREV_AUTH_NOT_VALID); + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, "deauthenticated due to " + "session timeout"); +#if 0 + sta->acct_terminate_cause = + RADIUS_ACCT_TERMINATE_CAUSE_SESSION_TIMEOUT; +#endif + ap_free_sta(hapd, sta); +} + + +void ap_sta_replenish_timeout(struct hostapd_data *hapd, struct sta_info *sta, + u32 session_timeout) +{ + if (eloop_replenish_timeout(session_timeout, 0, + ap_handle_session_timer, hapd, sta) == 1) { + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, "setting session timeout " + "to %d seconds", session_timeout); + } +} + + +void ap_sta_session_timeout(struct hostapd_data *hapd, struct sta_info *sta, + u32 session_timeout) +{ + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, "setting session timeout to %d " + "seconds", session_timeout); + eloop_cancel_timeout(ap_handle_session_timer, hapd, sta); + eloop_register_timeout(session_timeout, 0, ap_handle_session_timer, + hapd, sta); +} + + +void ap_sta_no_session_timeout(struct hostapd_data *hapd, struct sta_info *sta) +{ + eloop_cancel_timeout(ap_handle_session_timer, hapd, sta); +} + + +static void ap_handle_session_warning_timer(void *eloop_ctx, void *timeout_ctx) +{ +} + + +void ap_sta_session_warning_timeout(struct hostapd_data *hapd, + struct sta_info *sta, int warning_time) +{ + eloop_cancel_timeout(ap_handle_session_warning_timer, hapd, sta); + eloop_register_timeout(warning_time, 0, ap_handle_session_warning_timer, + hapd, sta); +} + + +struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr) +{ + struct sta_info *sta; + int i; + + sta = ap_get_sta(hapd, addr); + if (sta) + return sta; + + wpa_printf(MSG_DEBUG, " New STA"); + if (hapd->num_sta >= hapd->conf->max_num_sta) { + /* FIX: might try to remove some old STAs first? */ + wpa_printf(MSG_DEBUG, "no more room for new STAs (%d/%d)", + hapd->num_sta, hapd->conf->max_num_sta); + return NULL; + } + + sta = os_zalloc(sizeof(struct sta_info)); + if (sta == NULL) { + os_printf("ap_sta_add malloc failed\r\n"); + return NULL; + } +#ifdef CONFIG_FULL_HOSTAPD + sta->acct_interim_interval = hapd->conf->acct_interim_interval; + if (accounting_sta_get_id(hapd, sta) < 0) { + os_free(sta); + return NULL; + } +#endif + + for (i = 0; i < WLAN_SUPP_RATES_MAX; i++) { + if (!hapd->iface->basic_rates) + break; + if (hapd->iface->basic_rates[i] < 0) + break; + sta->supported_rates[i] = hapd->iface->basic_rates[i] / 5; + } + sta->supported_rates_len = i; + + if (!(hapd->iface->drv_flags & WPA_DRIVER_FLAGS_INACTIVITY_TIMER)) { + wpa_printf(MSG_DEBUG, "%s: register ap_handle_timer timeout " + "for " MACSTR " (%d seconds - ap_max_inactivity)", + __func__, MAC2STR(addr), + hapd->conf->ap_max_inactivity); + eloop_register_timeout(hapd->conf->ap_max_inactivity, 0, + ap_handle_timer, hapd, sta); + } + + /* initialize STA info data */ + os_memcpy(sta->addr, addr, ETH_ALEN); + sta->next = hapd->sta_list; + hapd->sta_list = sta; + hapd->num_sta++; + ap_sta_hash_add(hapd, sta); + ap_sta_remove_in_other_bss(hapd, sta); + sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ; + dl_list_init(&sta->ip6addr); + + return sta; +} + + +static int ap_sta_remove(struct hostapd_data *hapd, struct sta_info *sta) +{ + ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); + + if (sta->ipaddr) + hostapd_drv_br_delete_ip_neigh(hapd, 4, (u8 *) &sta->ipaddr); + ap_sta_ip6addr_del(hapd, sta); + + wpa_printf(MSG_DEBUG, "%s: Removing STA " MACSTR " from kernel driver", + hapd->conf->iface, MAC2STR(sta->addr)); + if (hostapd_drv_sta_remove(hapd, sta->addr) && + sta->flags & WLAN_STA_ASSOC) { + wpa_printf(MSG_DEBUG, "%s: Could not remove station " MACSTR + " from kernel driver", + hapd->conf->iface, MAC2STR(sta->addr)); + return -1; + } + sta->added_unassoc = 0; + return 0; +} + + +static void ap_sta_remove_in_other_bss(struct hostapd_data *hapd, + struct sta_info *sta) +{ + struct hostapd_iface *iface = hapd->iface; + size_t i; + + for (i = 0; i < iface->num_bss; i++) { + struct hostapd_data *bss = iface->bss[i]; + struct sta_info *sta2; + /* bss should always be set during operation, but it may be + * NULL during reconfiguration. Assume the STA is not + * associated to another BSS in that case to avoid NULL pointer + * dereferences. */ + if (bss == hapd || bss == NULL) + continue; + sta2 = ap_get_sta(bss, sta->addr); + if (!sta2) + continue; + + wpa_printf(MSG_DEBUG, "%s: disconnect old STA " MACSTR + " association from another BSS %s", + hapd->conf->iface, MAC2STR(sta2->addr), + bss->conf->iface); + ap_sta_disconnect(bss, sta2, sta2->addr, + WLAN_REASON_PREV_AUTH_NOT_VALID); + } +} + + +static void ap_sta_disassoc_cb_timeout(void *eloop_ctx, void *timeout_ctx) +{ + struct hostapd_data *hapd = eloop_ctx; + struct sta_info *sta = timeout_ctx; + + wpa_printf(MSG_DEBUG, "%s: Disassociation callback for STA " MACSTR, + hapd->conf->iface, MAC2STR(sta->addr)); + ap_sta_remove(hapd, sta); + mlme_disassociate_indication(hapd, sta, sta->disassoc_reason); +} + + +void ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta, + u16 reason) +{ + wpa_printf(MSG_DEBUG, "%s: disassociate STA " MACSTR, + hapd->conf->iface, MAC2STR(sta->addr)); + sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ; + sta->flags &= ~(WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK); + ap_sta_set_authorized(hapd, sta, 0); + sta->timeout_next = STA_DEAUTH; + wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout " + "for " MACSTR " (%d seconds - " + "AP_MAX_INACTIVITY_AFTER_DISASSOC)", + __func__, MAC2STR(sta->addr), + AP_MAX_INACTIVITY_AFTER_DISASSOC); + eloop_cancel_timeout(ap_handle_timer, hapd, sta); + eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DISASSOC, 0, + ap_handle_timer, hapd, sta); + accounting_sta_stop(hapd, sta); +#ifdef IEEE8021X_EAPOL + ieee802_1x_free_station(hapd, sta); + wpa_auth_sta_deinit(sta->wpa_sm); + sta->wpa_sm = NULL; +#endif + + sta->disassoc_reason = reason; + sta->flags |= WLAN_STA_PENDING_DISASSOC_CB; + eloop_cancel_timeout(ap_sta_disassoc_cb_timeout, hapd, sta); + eloop_register_timeout(hapd->iface->drv_flags & + WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS ? 2 : 0, 0, + ap_sta_disassoc_cb_timeout, hapd, sta); +} + + +static void ap_sta_deauth_cb_timeout(void *eloop_ctx, void *timeout_ctx) +{ + struct hostapd_data *hapd = eloop_ctx; + struct sta_info *sta = timeout_ctx; + + wpa_printf(MSG_DEBUG, "%s: Deauthentication callback for STA " MACSTR, + hapd->conf->iface, MAC2STR(sta->addr)); + ap_sta_remove(hapd, sta); + mlme_deauthenticate_indication(hapd, sta, sta->deauth_reason); +} + + +void ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta, + u16 reason) +{ + wpa_printf(MSG_DEBUG, "%s: deauthenticate STA " MACSTR, + hapd->conf->iface, MAC2STR(sta->addr)); + sta->last_seq_ctrl = WLAN_INVALID_MGMT_SEQ; + sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC | WLAN_STA_ASSOC_REQ_OK); + ap_sta_set_authorized(hapd, sta, 0); + sta->timeout_next = STA_REMOVE; + wpa_printf(MSG_DEBUG, "%s: reschedule ap_handle_timer timeout " + "for " MACSTR " (%d seconds - " + "AP_MAX_INACTIVITY_AFTER_DEAUTH)", + __func__, MAC2STR(sta->addr), + AP_MAX_INACTIVITY_AFTER_DEAUTH); + eloop_cancel_timeout(ap_handle_timer, hapd, sta); + eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DEAUTH, 0, + ap_handle_timer, hapd, sta); + accounting_sta_stop(hapd, sta); +#ifdef IEEE8021X_EAPOL + ieee802_1x_free_station(hapd, sta); +#endif + sta->deauth_reason = reason; + sta->flags |= WLAN_STA_PENDING_DEAUTH_CB; + eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta); + eloop_register_timeout(hapd->iface->drv_flags & + WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS ? 2 : 0, 0, + ap_sta_deauth_cb_timeout, hapd, sta); +} + +static int ap_sta_get_free_vlan_id(struct hostapd_data *hapd) +{ + struct hostapd_vlan *vlan; + int vlan_id = MAX_VLAN_ID + 2; + +retry: + for (vlan = hapd->conf->vlan; vlan; vlan = vlan->next) { + if (vlan->vlan_id == vlan_id) { + vlan_id++; + goto retry; + } + } + return vlan_id; +} + + +int ap_sta_set_vlan(struct hostapd_data *hapd, struct sta_info *sta, + struct vlan_description *vlan_desc) +{ + struct hostapd_vlan *vlan = NULL, *wildcard_vlan = NULL; + int old_vlan_id, vlan_id = 0, ret = 0; + + /* Check if there is something to do */ + if (hapd->conf->ssid.per_sta_vif && !sta->vlan_id) { + /* This sta is lacking its own vif */ + } else if (hapd->conf->ssid.dynamic_vlan == DYNAMIC_VLAN_DISABLED && + !hapd->conf->ssid.per_sta_vif && sta->vlan_id) { + /* sta->vlan_id needs to be reset */ + } else if (!vlan_compare(vlan_desc, sta->vlan_desc)) { + return 0; /* nothing to change */ + } + + /* Now the real VLAN changed or the STA just needs its own vif */ + if (hapd->conf->ssid.per_sta_vif) { + /* Assign a new vif, always */ + /* find a free vlan_id sufficiently big */ + vlan_id = ap_sta_get_free_vlan_id(hapd); + /* Get wildcard VLAN */ + for (vlan = hapd->conf->vlan; vlan; vlan = vlan->next) { + if (vlan->vlan_id == VLAN_ID_WILDCARD) + break; + } + if (!vlan) { + hostapd_logger(hapd, sta->addr, + HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "per_sta_vif missing wildcard"); + vlan_id = 0; + ret = -1; + goto done; + } + } else if (vlan_desc && vlan_desc->notempty) { + for (vlan = hapd->conf->vlan; vlan; vlan = vlan->next) { + if (!vlan_compare(&vlan->vlan_desc, vlan_desc)) + break; + if (vlan->vlan_id == VLAN_ID_WILDCARD) + wildcard_vlan = vlan; + } + if (vlan) { + vlan_id = vlan->vlan_id; + } else if (wildcard_vlan) { + vlan = wildcard_vlan; + vlan_id = vlan_desc->untagged; + if (vlan_desc->tagged[0]) { + /* Tagged VLAN configuration */ + vlan_id = ap_sta_get_free_vlan_id(hapd); + } + } else { + hostapd_logger(hapd, sta->addr, + HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "missing vlan and wildcard for vlan=%d%s", + vlan_desc->untagged, + vlan_desc->tagged[0] ? "+" : ""); + vlan_id = 0; + ret = -1; + goto done; + } + } + + if (vlan && vlan->vlan_id == VLAN_ID_WILDCARD) { + vlan = vlan_add_dynamic(hapd, vlan, vlan_id, vlan_desc); + if (vlan == NULL) { + hostapd_logger(hapd, sta->addr, + HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "could not add dynamic VLAN interface for vlan=%d%s", + vlan_desc ? vlan_desc->untagged : -1, + (vlan_desc && vlan_desc->tagged[0]) ? + "+" : ""); + vlan_id = 0; + ret = -1; + goto done; + } + + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "added new dynamic VLAN interface '%s'", + vlan->ifname); + } else if (vlan && vlan->dynamic_vlan > 0) { + vlan->dynamic_vlan++; + hostapd_logger(hapd, sta->addr, + HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "updated existing dynamic VLAN interface '%s'", + vlan->ifname); + } +done: + old_vlan_id = sta->vlan_id; + sta->vlan_id = vlan_id; + sta->vlan_desc = vlan ? &vlan->vlan_desc : NULL; + + if (vlan_id != old_vlan_id && old_vlan_id) + vlan_remove_dynamic(hapd, old_vlan_id); + + return ret; +} + + +int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta) +{ +#ifndef CONFIG_NO_VLAN + const char *iface; + struct hostapd_vlan *vlan = NULL; + int ret; + int old_vlanid = sta->vlan_id_bound; + + iface = hapd->conf->iface; + if (hapd->conf->ssid.vlan[0]) + iface = hapd->conf->ssid.vlan; + + if (sta->vlan_id > 0) { + for (vlan = hapd->conf->vlan; vlan; vlan = vlan->next) { + if (vlan->vlan_id == sta->vlan_id) + break; + } + if (vlan) + iface = vlan->ifname; + } + + /* + * Do not increment ref counters if the VLAN ID remains same, but do + * not skip hostapd_drv_set_sta_vlan() as hostapd_drv_sta_remove() might + * have been called before. + */ + if (sta->vlan_id == old_vlanid) + goto skip_counting; + + if (sta->vlan_id > 0 && vlan == NULL) { + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, "could not find VLAN for " + "binding station to (vlan_id=%d)", + sta->vlan_id); + ret = -1; + goto done; + } else if (vlan && vlan->dynamic_vlan > 0) { + vlan->dynamic_vlan++; + hostapd_logger(hapd, sta->addr, + HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "updated existing dynamic VLAN interface '%s'", + iface); + } + + /* ref counters have been increased, so mark the station */ + sta->vlan_id_bound = sta->vlan_id; + +skip_counting: + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, "binding station to interface " + "'%s'", iface); + + if (wpa_auth_sta_set_vlan(sta->wpa_sm, sta->vlan_id) < 0) + wpa_printf(MSG_INFO, "Failed to update VLAN-ID for WPA"); + + ret = hostapd_drv_set_sta_vlan(iface, hapd, sta->addr, sta->vlan_id); + if (ret < 0) { + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, "could not bind the STA " + "entry to vlan_id=%d", sta->vlan_id); + } + + /* During 1x reauth, if the vlan id changes, then remove the old id. */ + if (old_vlanid > 0 && old_vlanid != sta->vlan_id) + vlan_remove_dynamic(hapd, old_vlanid); +done: + + return ret; +#else /* CONFIG_NO_VLAN */ + return 0; +#endif /* CONFIG_NO_VLAN */ +} + + +#ifdef CONFIG_IEEE80211W_AP + +int ap_check_sa_query_timeout(struct hostapd_data *hapd, struct sta_info *sta) +{ + u32 tu; + struct os_reltime now, passed; + os_get_reltime(&now); + os_reltime_sub(&now, &sta->sa_query_start, &passed); + tu = (passed.sec * 1000000 + passed.usec) / 1024; + if (hapd->conf->assoc_sa_query_max_timeout < tu) { + hostapd_logger(hapd, sta->addr, + HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "association SA Query timed out"); + sta->sa_query_timed_out = 1; + os_free(sta->sa_query_trans_id); + sta->sa_query_trans_id = NULL; + sta->sa_query_count = 0; + eloop_cancel_timeout(ap_sa_query_timer, hapd, sta); + return 1; + } + + return 0; +} + + +static void ap_sa_query_timer(void *eloop_ctx, void *timeout_ctx) +{ + struct hostapd_data *hapd = eloop_ctx; + struct sta_info *sta = timeout_ctx; + unsigned int timeout, sec, usec; + u8 *trans_id, *nbuf; + + wpa_printf(MSG_DEBUG, "%s: SA Query timer for STA " MACSTR + " (count=%d)", + hapd->conf->iface, MAC2STR(sta->addr), sta->sa_query_count); + + if (sta->sa_query_count > 0 && + ap_check_sa_query_timeout(hapd, sta)) + return; + + nbuf = os_realloc_array(sta->sa_query_trans_id, + sta->sa_query_count + 1, + WLAN_SA_QUERY_TR_ID_LEN); + if (nbuf == NULL) + return; + if (sta->sa_query_count == 0) { + /* Starting a new SA Query procedure */ + os_get_reltime(&sta->sa_query_start); + } + trans_id = nbuf + sta->sa_query_count * WLAN_SA_QUERY_TR_ID_LEN; + sta->sa_query_trans_id = nbuf; + sta->sa_query_count++; + + if (os_get_random(trans_id, WLAN_SA_QUERY_TR_ID_LEN) < 0) { + /* + * We don't really care which ID is used here, so simply + * hardcode this if the mostly theoretical os_get_random() + * failure happens. + */ + trans_id[0] = 0x12; + trans_id[1] = 0x34; + } + + timeout = hapd->conf->assoc_sa_query_retry_timeout; + sec = ((timeout / 1000) * 1024) / 1000; + usec = (timeout % 1000) * 1024; + eloop_register_timeout(sec, usec, ap_sa_query_timer, hapd, sta); + + hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "association SA Query attempt %d", sta->sa_query_count); + + ieee802_11_send_sa_query_req(hapd, sta->addr, trans_id); +} + + +void ap_sta_start_sa_query(struct hostapd_data *hapd, struct sta_info *sta) +{ + ap_sa_query_timer(hapd, sta); +} + + +void ap_sta_stop_sa_query(struct hostapd_data *hapd, struct sta_info *sta) +{ + eloop_cancel_timeout(ap_sa_query_timer, hapd, sta); + os_free(sta->sa_query_trans_id); + sta->sa_query_trans_id = NULL; + sta->sa_query_count = 0; +} + +#endif /* CONFIG_IEEE80211W_AP */ + + +const char * ap_sta_wpa_get_keyid(struct hostapd_data *hapd, + struct sta_info *sta) +{ + struct hostapd_wpa_psk *psk; + struct hostapd_ssid *ssid; + const u8 *pmk; + int pmk_len; + + ssid = &hapd->conf->ssid; + + pmk = wpa_auth_get_pmk(sta->wpa_sm, &pmk_len); + if (!pmk || pmk_len != PMK_LEN) + return NULL; + + for (psk = ssid->wpa_psk; psk; psk = psk->next) + if (os_memcmp(pmk, psk->psk, PMK_LEN) == 0) + break; + if (!psk) + return NULL; + if (!psk || !psk->keyid[0]) + return NULL; + + return psk->keyid; +} + + +void ap_sta_set_authorized(struct hostapd_data *hapd, struct sta_info *sta, + int authorized) +{ + const u8 *dev_addr = NULL; + char buf[100]; +#ifdef CONFIG_P2P + u8 addr[ETH_ALEN]; + u8 ip_addr_buf[4]; +#endif /* CONFIG_P2P */ + + if (!!authorized == !!(sta->flags & WLAN_STA_AUTHORIZED)) + return; + + if (authorized) + sta->flags |= WLAN_STA_AUTHORIZED; + else + sta->flags &= ~WLAN_STA_AUTHORIZED; + +#ifdef CONFIG_P2P + if (hapd->p2p_group == NULL) { + if (sta->p2p_ie != NULL && + p2p_parse_dev_addr_in_p2p_ie(sta->p2p_ie, addr) == 0) + dev_addr = addr; + } else + dev_addr = p2p_group_get_dev_addr(hapd->p2p_group, sta->addr); + + if (dev_addr) + os_snprintf(buf, sizeof(buf), MACSTR " p2p_dev_addr=" MACSTR, + MAC2STR(sta->addr), MAC2STR(dev_addr)); + else +#endif /* CONFIG_P2P */ + os_snprintf(buf, sizeof(buf), MACSTR, MAC2STR(sta->addr)); + + if (hapd->sta_authorized_cb) + hapd->sta_authorized_cb(hapd->sta_authorized_cb_ctx, + sta->addr, authorized, dev_addr); + +#ifdef CONFIG_FULL_HOSTAPD + if (authorized) { + const char *keyid; + char keyid_buf[100]; + char ip_addr[100]; + + keyid_buf[0] = '\0'; + ip_addr[0] = '\0'; +#ifdef CONFIG_P2P + if (wpa_auth_get_ip_addr(sta->wpa_sm, ip_addr_buf) == 0) { + os_snprintf(ip_addr, sizeof(ip_addr), + " ip_addr=%u.%u.%u.%u", + ip_addr_buf[0], ip_addr_buf[1], + ip_addr_buf[2], ip_addr_buf[3]); + } +#endif /* CONFIG_P2P */ + + keyid = ap_sta_wpa_get_keyid(hapd, sta); + if (keyid) { + os_snprintf(keyid_buf, sizeof(keyid_buf), + " keyid=%s", keyid); + } + + wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_CONNECTED "%s%s%s", + buf, ip_addr, keyid_buf); + + if (hapd->msg_ctx_parent && + hapd->msg_ctx_parent != hapd->msg_ctx) + wpa_msg_no_global(hapd->msg_ctx_parent, MSG_INFO, + AP_STA_CONNECTED "%s%s%s", + buf, ip_addr, keyid_buf); + } else { + wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_DISCONNECTED "%s", buf); + + if (hapd->msg_ctx_parent && + hapd->msg_ctx_parent != hapd->msg_ctx) + wpa_msg_no_global(hapd->msg_ctx_parent, MSG_INFO, + AP_STA_DISCONNECTED "%s", buf); + } +#endif +} + + +void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *addr, u16 reason) +{ + if (sta) + wpa_printf(MSG_DEBUG, "%s: %s STA " MACSTR " reason=%u", + hapd->conf->iface, __func__, MAC2STR(sta->addr), + reason); + else if (addr) + wpa_printf(MSG_DEBUG, "%s: %s addr " MACSTR " reason=%u", + hapd->conf->iface, __func__, MAC2STR(addr), + reason); + + if (sta == NULL && addr) + sta = ap_get_sta(hapd, addr); + + if (addr) + hostapd_drv_sta_deauth(hapd, addr, reason); + + if (sta == NULL) + return; + ap_sta_set_authorized(hapd, sta, 0); + wpa_auth_sm_event(sta->wpa_sm, WPA_DEAUTH); + ieee802_1x_notify_port_enabled(sta->eapol_sm, 0); + sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC); + wpa_printf(MSG_DEBUG, "%s: %s: reschedule ap_handle_timer timeout " + "for " MACSTR " (%d seconds - " + "AP_MAX_INACTIVITY_AFTER_DEAUTH)", + hapd->conf->iface, __func__, MAC2STR(sta->addr), + AP_MAX_INACTIVITY_AFTER_DEAUTH); + eloop_cancel_timeout(ap_handle_timer, hapd, sta); + eloop_register_timeout(AP_MAX_INACTIVITY_AFTER_DEAUTH, 0, + ap_handle_timer, hapd, sta); + sta->timeout_next = STA_REMOVE; + + sta->deauth_reason = reason; + sta->flags |= WLAN_STA_PENDING_DEAUTH_CB; + eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta); + eloop_register_timeout(hapd->iface->drv_flags & + WPA_DRIVER_FLAGS_DEAUTH_TX_STATUS ? 2 : 0, 0, + ap_sta_deauth_cb_timeout, hapd, sta); +} + + +void ap_sta_deauth_cb(struct hostapd_data *hapd, struct sta_info *sta) +{ + if (!(sta->flags & WLAN_STA_PENDING_DEAUTH_CB)) { + wpa_printf(MSG_DEBUG, "Ignore deauth cb for test frame"); + return; + } + sta->flags &= ~WLAN_STA_PENDING_DEAUTH_CB; + eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta); + ap_sta_deauth_cb_timeout(hapd, sta); +} + + +void ap_sta_disassoc_cb(struct hostapd_data *hapd, struct sta_info *sta) +{ + if (!(sta->flags & WLAN_STA_PENDING_DISASSOC_CB)) { + wpa_printf(MSG_DEBUG, "Ignore disassoc cb for test frame"); + return; + } + sta->flags &= ~WLAN_STA_PENDING_DISASSOC_CB; + eloop_cancel_timeout(ap_sta_disassoc_cb_timeout, hapd, sta); + ap_sta_disassoc_cb_timeout(hapd, sta); +} + + +void ap_sta_clear_disconnect_timeouts(struct hostapd_data *hapd, + struct sta_info *sta) +{ + if (eloop_cancel_timeout(ap_sta_deauth_cb_timeout, hapd, sta) > 0) + wpa_printf(MSG_DEBUG, + "%s: Removed ap_sta_deauth_cb_timeout timeout for " + MACSTR, + hapd->conf->iface, MAC2STR(sta->addr)); + if (eloop_cancel_timeout(ap_sta_disassoc_cb_timeout, hapd, sta) > 0) + wpa_printf(MSG_DEBUG, + "%s: Removed ap_sta_disassoc_cb_timeout timeout for " + MACSTR, + hapd->conf->iface, MAC2STR(sta->addr)); +} + + +int ap_sta_flags_txt(u32 flags, char *buf, size_t buflen) +{ + int res; + + buf[0] = '\0'; + res = os_snprintf(buf, buflen, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", + (flags & WLAN_STA_AUTH ? "[AUTH]" : ""), + (flags & WLAN_STA_ASSOC ? "[ASSOC]" : ""), + (flags & WLAN_STA_AUTHORIZED ? "[AUTHORIZED]" : ""), + (flags & WLAN_STA_PENDING_POLL ? "[PENDING_POLL" : + ""), + (flags & WLAN_STA_SHORT_PREAMBLE ? + "[SHORT_PREAMBLE]" : ""), + (flags & WLAN_STA_PREAUTH ? "[PREAUTH]" : ""), + (flags & WLAN_STA_WMM ? "[WMM]" : ""), + (flags & WLAN_STA_MFP ? "[MFP]" : ""), + (flags & WLAN_STA_WPS ? "[WPS]" : ""), + (flags & WLAN_STA_MAYBE_WPS ? "[MAYBE_WPS]" : ""), + (flags & WLAN_STA_WDS ? "[WDS]" : ""), + (flags & WLAN_STA_NONERP ? "[NonERP]" : ""), + (flags & WLAN_STA_WPS2 ? "[WPS2]" : ""), + (flags & WLAN_STA_GAS ? "[GAS]" : ""), + (flags & WLAN_STA_HT ? "[HT]" : ""), + (flags & WLAN_STA_VHT ? "[VHT]" : ""), + (flags & WLAN_STA_VENDOR_VHT ? "[VENDOR_VHT]" : ""), + (flags & WLAN_STA_WNM_SLEEP_MODE ? + "[WNM_SLEEP_MODE]" : "")); + if (os_snprintf_error(buflen, res)) + res = -1; + + return res; +} diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/sta_info.h b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/sta_info.h new file mode 100755 index 0000000..403d92b --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/sta_info.h @@ -0,0 +1,286 @@ +/* + * hostapd / Station table + * Copyright (c) 2002-2011, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ +#ifndef STA_INFO_H +#define STA_INFO_H + +#ifdef CONFIG_MESH +/* needed for mesh_plink_state enum */ +#include "common/defs.h" +#include "common/wpa_common.h" +#endif /* CONFIG_MESH */ + +#include "list.h" +#include "vlan.h" +#include "common/wpa_common.h" +#include "common/ieee802_11_defs.h" + +/* STA flags */ +#define WLAN_STA_AUTH BIT(0) +#define WLAN_STA_ASSOC BIT(1) +#define WLAN_STA_AUTHORIZED BIT(5) +#define WLAN_STA_PENDING_POLL BIT(6) /* pending activity poll not ACKed */ +#define WLAN_STA_SHORT_PREAMBLE BIT(7) +#define WLAN_STA_PREAUTH BIT(8) +#define WLAN_STA_WMM BIT(9) +#define WLAN_STA_MFP BIT(10) +#define WLAN_STA_HT BIT(11) +#define WLAN_STA_WPS BIT(12) +#define WLAN_STA_MAYBE_WPS BIT(13) +#define WLAN_STA_WDS BIT(14) +#define WLAN_STA_ASSOC_REQ_OK BIT(15) +#define WLAN_STA_WPS2 BIT(16) +#define WLAN_STA_GAS BIT(17) +#define WLAN_STA_VHT BIT(18) +#define WLAN_STA_WNM_SLEEP_MODE BIT(19) +#define WLAN_STA_VHT_OPMODE_ENABLED BIT(20) +#define WLAN_STA_VENDOR_VHT BIT(21) +#define WLAN_STA_PENDING_FILS_ERP BIT(22) +#define WLAN_STA_MULTI_AP BIT(23) +#define WLAN_STA_HE BIT(24) +#define WLAN_STA_PENDING_DISASSOC_CB BIT(29) +#define WLAN_STA_PENDING_DEAUTH_CB BIT(30) +#define WLAN_STA_NONERP BIT(31) + +/* Maximum number of supported rates (from both Supported Rates and Extended + * Supported Rates IEs). */ +#define WLAN_SUPP_RATES_MAX 32 + +struct hostapd_data; + +struct mbo_non_pref_chan_info { + struct mbo_non_pref_chan_info *next; + u8 op_class; + u8 pref; + u8 reason_code; + u8 num_channels; + u8 channels[]; +}; + +struct pending_eapol_rx { + struct wpabuf *buf; + struct os_reltime rx_time; +}; + +struct sta_info { + struct sta_info *next; /* next entry in sta list */ + struct sta_info *hnext; /* next entry in hash table list */ + u8 addr[6]; + be32 ipaddr; + struct dl_list ip6addr; /* list head for struct ip6addr */ + u16 aid; /* STA's unique AID (1 .. 2007) or 0 if not yet assigned */ + u16 disconnect_reason_code; /* RADIUS server override */ + u32 flags; /* Bitfield of WLAN_STA_* */ + u16 capability; + u16 listen_interval; /* or beacon_int for APs */ + u8 supported_rates[WLAN_SUPP_RATES_MAX]; + int supported_rates_len; + u8 qosinfo; /* Valid when WLAN_STA_WMM is set */ + +#ifdef CONFIG_MESH + enum mesh_plink_state plink_state; + u16 peer_lid; + u16 my_lid; + u16 peer_aid; + u16 mpm_close_reason; + int mpm_retries; + u8 my_nonce[WPA_NONCE_LEN]; + u8 peer_nonce[WPA_NONCE_LEN]; + u8 aek[32]; /* SHA256 digest length */ + u8 mtk[WPA_TK_MAX_LEN]; + size_t mtk_len; + u8 mgtk_rsc[6]; + u8 mgtk_key_id; /* FIXME: Where to get Key ID? */ + u8 mgtk[WPA_TK_MAX_LEN]; + size_t mgtk_len; + u8 igtk_rsc[6]; + u8 igtk[WPA_TK_MAX_LEN]; + size_t igtk_len; + u16 igtk_key_id; + u8 sae_auth_retry; + + u8 sta_idx; /* FIXME: no here */ +#endif /* CONFIG_MESH */ + + unsigned int nonerp_set:1; + unsigned int no_short_slot_time_set:1; + unsigned int no_short_preamble_set:1; + unsigned int no_ht_gf_set:1; + unsigned int no_ht_set:1; + unsigned int ht40_intolerant_set:1; + unsigned int ht_20mhz_set:1; + unsigned int no_p2p_set:1; + unsigned int qos_map_enabled:1; + unsigned int remediation:1; + unsigned int hs20_deauth_requested:1; + unsigned int session_timeout_set:1; + unsigned int radius_das_match:1; + unsigned int ecsa_supported:1; + unsigned int added_unassoc:1; + unsigned int pending_wds_enable:1; + unsigned int power_capab:1; + unsigned int agreed_to_steer:1; + unsigned int hs20_t_c_filtering:1; + unsigned int ft_over_ds:1; + unsigned int external_dh_updated:1; + + u16 auth_alg; + + enum { + STA_NULLFUNC = 0, STA_DISASSOC, STA_DEAUTH, STA_REMOVE, + STA_DISASSOC_FROM_CLI + } timeout_next; + + u16 deauth_reason; + u16 disassoc_reason; + + /* IEEE 802.1X related data */ + struct eapol_state_machine *eapol_sm; + u8 *challenge; /* IEEE 802.11 Shared Key Authentication Challenge */ + + struct wpa_state_machine *wpa_sm; + + int vlan_id; /* 0: none, >0: VID */ + struct vlan_description *vlan_desc; + int vlan_id_bound; /* updated by ap_sta_bind_vlan() */ + /* PSKs from RADIUS authentication server */ + struct hostapd_sta_wpa_psk_short *psk; + + struct ieee80211_ht_capabilities *ht_capabilities; + struct ieee80211_vht_capabilities *vht_capabilities; + struct ieee80211_vht_operation *vht_operation; + u8 vht_opmode; + struct ieee80211_he_capabilities *he_capab; + size_t he_capab_len; + +#ifdef CONFIG_IEEE80211W_AP + int sa_query_count; /* number of pending SA Query requests; + * 0 = no SA Query in progress */ + int sa_query_timed_out; + u8 *sa_query_trans_id; /* buffer of WLAN_SA_QUERY_TR_ID_LEN * + * sa_query_count octets of pending SA Query + * transaction identifiers */ + struct os_reltime sa_query_start; +#endif /* CONFIG_IEEE80211W_AP */ + + struct wpabuf *wps_ie; /* WPS IE from (Re)Association Request */ + struct wpabuf *p2p_ie; /* P2P IE from (Re)Association Request */ + + struct os_reltime connected_time; /* accouting */ + +#ifdef CONFIG_SAE_AP + struct sae_data *sae; + unsigned int mesh_sae_pmksa_caching:1; +#endif /* CONFIG_SAE_AP */ + + /* valid only if session_timeout_set == 1 */ + struct os_reltime session_timeout; + + /* Last Authentication/(Re)Association Request/Action frame sequence + * control */ + u16 last_seq_ctrl; + /* Last Authentication/(Re)Association Request/Action frame subtype */ + u8 last_subtype; + + u8 *supp_op_classes; /* Supported Operating Classes element, if + * received, starting from the Length field */ + + u8 rrm_enabled_capa[5]; + + s8 min_tx_power; + s8 max_tx_power; + +#ifdef CONFIG_OWE + u8 *owe_pmk; + size_t owe_pmk_len; + struct crypto_ecdh *owe_ecdh; + u16 owe_group; +#endif /* CONFIG_OWE */ + + u8 *ext_capability; + char *ifname_wds; /* WDS ifname, if in use */ + +#ifdef CONFIG_DPP2 + struct dpp_pfs *dpp_pfs; +#endif /* CONFIG_DPP2 */ +}; + + +/* Default value for maximum station inactivity. After AP_MAX_INACTIVITY has + * passed since last received frame from the station, a nullfunc data frame is + * sent to the station. If this frame is not acknowledged and no other frames + * have been received, the station will be disassociated after + * AP_DISASSOC_DELAY seconds. Similarly, the station will be deauthenticated + * after AP_DEAUTH_DELAY seconds has passed after disassociation. */ +#define AP_MAX_INACTIVITY (15) +#define AP_DISASSOC_DELAY (1) +#define AP_DEAUTH_DELAY (1) +/* Number of seconds to keep STA entry with Authenticated flag after it has + * been disassociated. */ +#define AP_MAX_INACTIVITY_AFTER_DISASSOC (1 * 30) +/* Number of seconds to keep STA entry after it has been deauthenticated. */ +#define AP_MAX_INACTIVITY_AFTER_DEAUTH (1 * 5) + + +int ap_for_each_sta(struct hostapd_data *hapd, + int (*cb)(struct hostapd_data *hapd, struct sta_info *sta, + void *ctx), + void *ctx); +struct sta_info * ap_get_sta(struct hostapd_data *hapd, const u8 *sta); +struct sta_info * ap_get_sta_p2p(struct hostapd_data *hapd, const u8 *addr); +void ap_sta_hash_add(struct hostapd_data *hapd, struct sta_info *sta); +void ap_free_sta(struct hostapd_data *hapd, struct sta_info *sta); +void ap_sta_ip6addr_del(struct hostapd_data *hapd, struct sta_info *sta); +void hostapd_free_stas(struct hostapd_data *hapd); +void ap_handle_timer(void *eloop_ctx, void *timeout_ctx); +void ap_sta_replenish_timeout(struct hostapd_data *hapd, struct sta_info *sta, + u32 session_timeout); +void ap_sta_session_timeout(struct hostapd_data *hapd, struct sta_info *sta, + u32 session_timeout); +void ap_sta_no_session_timeout(struct hostapd_data *hapd, + struct sta_info *sta); +void ap_sta_session_warning_timeout(struct hostapd_data *hapd, + struct sta_info *sta, int warning_time); +struct sta_info * ap_sta_add(struct hostapd_data *hapd, const u8 *addr); +void ap_sta_disassociate(struct hostapd_data *hapd, struct sta_info *sta, + u16 reason); +void ap_sta_deauthenticate(struct hostapd_data *hapd, struct sta_info *sta, + u16 reason); +#ifdef CONFIG_WPS +int ap_sta_wps_cancel(struct hostapd_data *hapd, + struct sta_info *sta, void *ctx); +#endif /* CONFIG_WPS */ +int ap_sta_bind_vlan(struct hostapd_data *hapd, struct sta_info *sta); +int ap_sta_set_vlan(struct hostapd_data *hapd, struct sta_info *sta, + struct vlan_description *vlan_desc); +void ap_sta_start_sa_query(struct hostapd_data *hapd, struct sta_info *sta); +void ap_sta_stop_sa_query(struct hostapd_data *hapd, struct sta_info *sta); +int ap_check_sa_query_timeout(struct hostapd_data *hapd, struct sta_info *sta); +const char * ap_sta_wpa_get_keyid(struct hostapd_data *hapd, + struct sta_info *sta); +void ap_sta_disconnect(struct hostapd_data *hapd, struct sta_info *sta, + const u8 *addr, u16 reason); + +void ap_sta_set_authorized(struct hostapd_data *hapd, + struct sta_info *sta, int authorized); +static inline int ap_sta_is_authorized(struct sta_info *sta) +{ + return sta->flags & WLAN_STA_AUTHORIZED; +} + +void ap_sta_deauth_cb(struct hostapd_data *hapd, struct sta_info *sta); +void ap_sta_disassoc_cb(struct hostapd_data *hapd, struct sta_info *sta); +void ap_sta_clear_disconnect_timeouts(struct hostapd_data *hapd, + struct sta_info *sta); + +int ap_sta_flags_txt(u32 flags, char *buf, size_t buflen); +void ap_sta_delayed_1x_auth_fail_disconnect(struct hostapd_data *hapd, + struct sta_info *sta); +int ap_sta_pending_delayed_1x_auth_fail_disconnect(struct hostapd_data *hapd, + struct sta_info *sta); + +#endif /* STA_INFO_H */ diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/tkip_countermeasures.c b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/tkip_countermeasures.c new file mode 100755 index 0000000..f889723 --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/tkip_countermeasures.c @@ -0,0 +1,111 @@ +/* + * hostapd / TKIP countermeasures + * Copyright (c) 2002-2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "utils/eloop.h" +#include "common/ieee802_11_defs.h" +#include "ap/hostapd.h" +#include "ap/sta_info.h" +#include "ap_mlme.h" +#include "wpa_auth.h" +#include "ap_drv_ops.h" +#include "tkip_countermeasures.h" + + +static void ieee80211_tkip_countermeasures_stop(void *eloop_ctx, + void *timeout_ctx) +{ + struct hostapd_data *hapd = eloop_ctx; + hapd->tkip_countermeasures = 0; + hostapd_drv_set_countermeasures(hapd, 0); + hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, "TKIP countermeasures ended"); +} + + +static void ieee80211_tkip_countermeasures_start(struct hostapd_data *hapd) +{ + struct sta_info *sta; + + hostapd_logger(hapd, NULL, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, "TKIP countermeasures initiated"); + + wpa_auth_countermeasures_start(hapd->wpa_auth); + hapd->tkip_countermeasures = 1; + hostapd_drv_set_countermeasures(hapd, 1); + wpa_gtk_rekey(hapd->wpa_auth); + eloop_cancel_timeout(ieee80211_tkip_countermeasures_stop, hapd, NULL); + eloop_register_timeout(60, 0, ieee80211_tkip_countermeasures_stop, + hapd, NULL); + while ((sta = hapd->sta_list) != NULL) { +#if 0 + sta->acct_terminate_cause = + RADIUS_ACCT_TERMINATE_CAUSE_ADMIN_RESET; +#endif + if (sta->flags & WLAN_STA_AUTH) { + mlme_deauthenticate_indication( + hapd, sta, + WLAN_REASON_MICHAEL_MIC_FAILURE); + } + hostapd_drv_sta_deauth(hapd, sta->addr, + WLAN_REASON_MICHAEL_MIC_FAILURE); + ap_free_sta(hapd, sta); + } +} + + +void ieee80211_tkip_countermeasures_deinit(struct hostapd_data *hapd) +{ + eloop_cancel_timeout(ieee80211_tkip_countermeasures_stop, hapd, NULL); +} + + +int michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, int local) +{ + struct os_reltime now; + int ret = 0; + + hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, + "Michael MIC failure detected in received frame%s", + local ? " (local)" : ""); + + if (addr && local) { + struct sta_info *sta = ap_get_sta(hapd, addr); + if (sta != NULL) { + wpa_auth_sta_local_mic_failure_report(sta->wpa_sm); + hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_INFO, + "Michael MIC failure detected in " + "received frame"); + mlme_michaelmicfailure_indication(hapd, addr); + } else { + wpa_printf(MSG_DEBUG, + "MLME-MICHAELMICFAILURE.indication " + "for not associated STA (" MACSTR + ") ignored", MAC2STR(addr)); + return ret; + } + } + + os_get_reltime(&now); + if (os_reltime_expired(&now, &hapd->michael_mic_failure, 60)) { + hapd->michael_mic_failures = 1; + } else { + hapd->michael_mic_failures++; + if (hapd->michael_mic_failures > 1) { + ieee80211_tkip_countermeasures_start(hapd); + ret = 1; + } + } + hapd->michael_mic_failure = now; + + return ret; +} diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/tkip_countermeasures.h b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/tkip_countermeasures.h new file mode 100755 index 0000000..d3eaed3 --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/tkip_countermeasures.h @@ -0,0 +1,15 @@ +/* + * hostapd / TKIP countermeasures + * Copyright (c) 2002-2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef TKIP_COUNTERMEASURES_H +#define TKIP_COUNTERMEASURES_H + +int michael_mic_failure(struct hostapd_data *hapd, const u8 *addr, int local); +void ieee80211_tkip_countermeasures_deinit(struct hostapd_data *hapd); + +#endif /* TKIP_COUNTERMEASURES_H */ diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/utils.c b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/utils.c new file mode 100755 index 0000000..0bab135 --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/utils.c @@ -0,0 +1,95 @@ +/* + * AP mode helper functions + * Copyright (c) 2009, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "includes.h" + +#include "common.h" +#include "common/ieee802_11_defs.h" +#include "ap/sta_info.h" +#include "ap/hostapd.h" + + +int hostapd_register_probereq_cb(struct hostapd_data *hapd, + int (*cb)(void *ctx, const u8 *sa, + const u8 *da, const u8 *bssid, + const u8 *ie, size_t ie_len, + int ssi_signal), + void *ctx) +{ + struct hostapd_probereq_cb *n; + + n = os_realloc_array(hapd->probereq_cb, hapd->num_probereq_cb + 1, + sizeof(struct hostapd_probereq_cb)); + if (n == NULL) + return -1; + + hapd->probereq_cb = n; + n = &hapd->probereq_cb[hapd->num_probereq_cb]; + hapd->num_probereq_cb++; + + n->cb = cb; + n->ctx = ctx; + + return 0; +} + + +struct prune_data { + struct hostapd_data *hapd; + const u8 *addr; +}; + +static int prune_associations(struct hostapd_iface *iface, void *ctx) +{ + struct prune_data *data = ctx; + struct sta_info *osta; + struct hostapd_data *ohapd; + size_t j; + + for (j = 0; j < iface->num_bss; j++) { + ohapd = iface->bss[j]; + if (ohapd == data->hapd) + continue; +#ifdef CONFIG_FST + /* Don't prune STAs belong to same FST */ + if (ohapd->iface->fst && + data->hapd->iface->fst && + fst_are_ifaces_aggregated(ohapd->iface->fst, + data->hapd->iface->fst)) + continue; +#endif /* CONFIG_FST */ + osta = ap_get_sta(ohapd, data->addr); + if (!osta) + continue; + + wpa_printf(MSG_INFO, "%s: Prune association for " MACSTR, + ohapd->conf->iface, MAC2STR(osta->addr)); + ap_sta_disassociate(ohapd, osta, WLAN_REASON_UNSPECIFIED); + } + + return 0; +} + +/** + * hostapd_prune_associations - Remove extraneous associations + * @hapd: Pointer to BSS data for the most recent association + * @addr: Associated STA address + * + * This function looks through all radios and BSS's for previous + * (stale) associations of STA. If any are found they are removed. + */ +void hostapd_prune_associations(struct hostapd_data *hapd, const u8 *addr) +{ + struct prune_data data; + data.hapd = hapd; + data.addr = addr; + if (hapd->iface->interfaces && + hapd->iface->interfaces->for_each_interface) + hapd->iface->interfaces->for_each_interface( + hapd->iface->interfaces, prune_associations, &data); +} diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/vlan.h b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/vlan.h new file mode 100755 index 0000000..af84929 --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/vlan.h @@ -0,0 +1,30 @@ +/* + * hostapd / VLAN definition + * Copyright (c) 2015, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef VLAN_H +#define VLAN_H + +#define MAX_NUM_TAGGED_VLAN 32 + +struct vlan_description { + int notempty; /* 0 : no vlan information present, 1: else */ + int untagged; /* >0 802.1q vid */ + int tagged[MAX_NUM_TAGGED_VLAN]; /* first k items, ascending order */ +}; + +#ifndef CONFIG_NO_VLAN +int vlan_compare(struct vlan_description *a, struct vlan_description *b); +#else /* CONFIG_NO_VLAN */ +static inline int +vlan_compare(struct vlan_description *a, struct vlan_description *b) +{ + return 0; +} +#endif /* CONFIG_NO_VLAN */ + +#endif /* VLAN_H */ diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/vlan_init.h b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/vlan_init.h new file mode 100755 index 0000000..d17c82c --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/vlan_init.h @@ -0,0 +1,44 @@ +/* + * hostapd / VLAN initialization + * Copyright 2003, Instant802 Networks, Inc. + * Copyright 2005, Devicescape Software, Inc. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef VLAN_INIT_H +#define VLAN_INIT_H + +#ifndef CONFIG_NO_VLAN +int vlan_init(struct hostapd_data *hapd); +void vlan_deinit(struct hostapd_data *hapd); +struct hostapd_vlan * vlan_add_dynamic(struct hostapd_data *hapd, + struct hostapd_vlan *vlan, + int vlan_id, + struct vlan_description *vlan_desc); +int vlan_remove_dynamic(struct hostapd_data *hapd, int vlan_id); +#else /* CONFIG_NO_VLAN */ +static inline int vlan_init(struct hostapd_data *hapd) +{ + return 0; +} + +static inline void vlan_deinit(struct hostapd_data *hapd) +{ +} + +static inline struct hostapd_vlan * +vlan_add_dynamic(struct hostapd_data *hapd, struct hostapd_vlan *vlan, + int vlan_id, struct vlan_description *vlan_desc) +{ + return NULL; +} + +static inline int vlan_remove_dynamic(struct hostapd_data *hapd, int vlan_id) +{ + return -1; +} +#endif /* CONFIG_NO_VLAN */ + +#endif /* VLAN_INIT_H */ diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/vlan_util.h b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/vlan_util.h new file mode 100755 index 0000000..2446859 --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/vlan_util.h @@ -0,0 +1,31 @@ +/* + * hostapd / VLAN netlink/ioctl api + * Copyright (c) 2012, Michael Braun + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef VLAN_UTIL_H +#define VLAN_UTIL_H + +struct hostapd_data; +struct hostapd_vlan; +struct full_dynamic_vlan; + +int vlan_add(const char *if_name, int vid, const char *vlan_if_name); +int vlan_rem(const char *if_name); +int vlan_set_name_type(unsigned int name_type); + +int ifconfig_helper(const char *if_name, int up); +int ifconfig_up(const char *if_name); +int iface_exists(const char *ifname); +int vlan_if_remove(struct hostapd_data *hapd, struct hostapd_vlan *vlan); + +struct full_dynamic_vlan * +full_dynamic_vlan_init(struct hostapd_data *hapd); +void full_dynamic_vlan_deinit(struct full_dynamic_vlan *priv); +void vlan_newlink(const char *ifname, struct hostapd_data *hapd); +void vlan_dellink(const char *ifname, struct hostapd_data *hapd); + +#endif /* VLAN_UTIL_H */ diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/wmm.c b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/wmm.c new file mode 100755 index 0000000..1883c4a --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/wmm.c @@ -0,0 +1,421 @@ +/* + * hostapd / WMM (Wi-Fi Multimedia) + * Copyright 2002-2003, Instant802 Networks, Inc. + * Copyright 2005-2006, Devicescape Software, Inc. + * Copyright (c) 2009, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "common/ieee802_11_defs.h" +#include "common/ieee802_11_common.h" +#include "ap/hostapd.h" +#include "ieee802_11.h" +#include "ap/sta_info.h" +#include "ap_config.h" +#include "ap_drv_ops.h" +#include "wmm.h" + +#ifndef MIN +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#endif +#ifndef MAX +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) +#endif + + +u8 wmm_aci_aifsn(int aifsn, int acm, int aci) +{ + u8 ret; + ret = (aifsn << WMM_AC_AIFNS_SHIFT) & WMM_AC_AIFSN_MASK; + if (acm) + ret |= WMM_AC_ACM; + ret |= (aci << WMM_AC_ACI_SHIFT) & WMM_AC_ACI_MASK; + return ret; +} + + +static inline u8 wmm_ecw(int ecwmin, int ecwmax) +{ + return ((ecwmin << WMM_AC_ECWMIN_SHIFT) & WMM_AC_ECWMIN_MASK) | + ((ecwmax << WMM_AC_ECWMAX_SHIFT) & WMM_AC_ECWMAX_MASK); +} + + +static void +wmm_set_regulatory_limit(const struct hostapd_wmm_ac_params *wmm_conf, + struct hostapd_wmm_ac_params *wmm, + const struct hostapd_wmm_rule *wmm_reg) +{ + int ac; + + for (ac = 0; ac < WMM_AC_NUM; ac++) { + wmm[ac].cwmin = MAX(wmm_conf[ac].cwmin, wmm_reg[ac].min_cwmin); + wmm[ac].cwmax = MAX(wmm_conf[ac].cwmax, wmm_reg[ac].min_cwmax); + wmm[ac].aifs = MAX(wmm_conf[ac].aifs, wmm_reg[ac].min_aifs); + wmm[ac].txop_limit = + MIN(wmm_conf[ac].txop_limit, wmm_reg[ac].max_txop); + wmm[ac].admission_control_mandatory = + wmm_conf[ac].admission_control_mandatory; + } +} + + +/* + * Calculate WMM regulatory limit if any. + */ +static void wmm_calc_regulatory_limit(struct hostapd_data *hapd, + struct hostapd_wmm_ac_params *acp) +{ + struct hostapd_hw_modes *mode = hapd->iface->current_mode; + int c; + + os_memcpy(acp, hapd->iconf->wmm_ac_params, + sizeof(hapd->iconf->wmm_ac_params)); + + for (c = 0; mode && c < mode->num_channels; c++) { + struct hostapd_channel_data *chan = &mode->channels[c]; + + if (chan->freq != hapd->iface->freq) + continue; + + if (chan->wmm_rules_valid) + wmm_set_regulatory_limit(hapd->iconf->wmm_ac_params, + acp, chan->wmm_rules); + break; + } + + /* + * Check if we need to update set count. Since both were initialized to + * zero we can compare the whole array in one shot. + */ + if (os_memcmp(acp, hapd->iface->prev_wmm, + sizeof(hapd->iconf->wmm_ac_params)) != 0) { + os_memcpy(hapd->iface->prev_wmm, acp, + sizeof(hapd->iconf->wmm_ac_params)); + hapd->parameter_set_count++; + } +} + + +/* + * Add WMM Parameter Element to Beacon, Probe Response, and (Re)Association + * Response frames. + */ +u8 * hostapd_eid_wmm(struct hostapd_data *hapd, u8 *eid) +{ +#if 1 + u8 *rivieraWaveVendorIE = eid; + + rivieraWaveVendorIE[0] = WLAN_EID_VENDOR_SPECIFIC; + rivieraWaveVendorIE[1] = 0x18; + rivieraWaveVendorIE[2] = 0x00; + rivieraWaveVendorIE[3] = 0x50; + rivieraWaveVendorIE[4] = 0xf2; + rivieraWaveVendorIE[5] = 0x02; + rivieraWaveVendorIE[6] = 0x01; + rivieraWaveVendorIE[7] = 0x01; + rivieraWaveVendorIE[8] = 0x00; + rivieraWaveVendorIE[9] = 0x00; + rivieraWaveVendorIE[10] = 0x03; + rivieraWaveVendorIE[11] = 0xa4; + rivieraWaveVendorIE[12] = 0x00; + rivieraWaveVendorIE[13] = 0x00; + rivieraWaveVendorIE[14] = 0x27; + rivieraWaveVendorIE[15] = 0xa4; + rivieraWaveVendorIE[16] = 0x00; + rivieraWaveVendorIE[17] = 0x00; + rivieraWaveVendorIE[18] = 0x42; + rivieraWaveVendorIE[19] = 0x43; + rivieraWaveVendorIE[20] = 0x5e; + rivieraWaveVendorIE[21] = 0x00; + rivieraWaveVendorIE[22] = 0x62; + rivieraWaveVendorIE[23] = 0x32; + rivieraWaveVendorIE[24] = 0x2f; + rivieraWaveVendorIE[25] = 0x00; + + return (u8*)((u32)eid + rivieraWaveVendorIE[1] + 2); +#else + u8 *pos = eid; + struct wmm_parameter_element *wmm = + (struct wmm_parameter_element *) (pos + 2); + struct hostapd_wmm_ac_params wmmp[WMM_AC_NUM] = { 0 }; + int e; + + if (!hapd->conf->wmm_enabled) + return eid; + wmm_calc_regulatory_limit(hapd, wmmp); + eid[0] = WLAN_EID_VENDOR_SPECIFIC; + wmm->oui[0] = 0x00; + wmm->oui[1] = 0x50; + wmm->oui[2] = 0xf2; + wmm->oui_type = WMM_OUI_TYPE; + wmm->oui_subtype = WMM_OUI_SUBTYPE_PARAMETER_ELEMENT; + wmm->version = WMM_VERSION; + wmm->qos_info = hapd->parameter_set_count & 0xf; + + if (hapd->conf->wmm_uapsd && + (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_UAPSD)) + wmm->qos_info |= 0x80; + + wmm->reserved = 0; + + /* fill in a parameter set record for each AC */ + for (e = 0; e < 4; e++) { + struct wmm_ac_parameter *ac = &wmm->ac[e]; + struct hostapd_wmm_ac_params *acp = &wmmp[e]; + + ac->aci_aifsn = wmm_aci_aifsn(acp->aifs, + acp->admission_control_mandatory, + e); + ac->cw = wmm_ecw(acp->cwmin, acp->cwmax); + ac->txop_limit = host_to_le16(acp->txop_limit); + } + + pos = (u8 *) (wmm + 1); + eid[1] = pos - eid - 2; /* element length */ + + return pos; +#endif +} + + +/* + * This function is called when a station sends an association request with + * WMM info element. The function returns 1 on success or 0 on any error in WMM + * element. eid does not include Element ID and Length octets. + */ +int hostapd_eid_wmm_valid(struct hostapd_data *hapd, const u8 *eid, size_t len) +{ + struct wmm_information_element *wmm; + + wpa_hexdump(MSG_MSGDUMP, "WMM IE", eid, len); + + if (len < sizeof(struct wmm_information_element)) { + wpa_printf(MSG_DEBUG, "Too short WMM IE (len=%lu)", + (unsigned long) len); + return 0; + } + + wmm = (struct wmm_information_element *) eid; + wpa_printf(MSG_DEBUG, "Validating WMM IE: OUI %02x:%02x:%02x " + "OUI type %d OUI sub-type %d version %d QoS info 0x%x", + wmm->oui[0], wmm->oui[1], wmm->oui[2], wmm->oui_type, + wmm->oui_subtype, wmm->version, wmm->qos_info); + if (wmm->oui_subtype != WMM_OUI_SUBTYPE_INFORMATION_ELEMENT || + wmm->version != WMM_VERSION) { + wpa_printf(MSG_DEBUG, "Unsupported WMM IE Subtype/Version"); + return 0; + } + + return 1; +} + + +static void wmm_send_action(struct hostapd_data *hapd, const u8 *addr, + const struct wmm_tspec_element *tspec, + u8 action_code, u8 dialogue_token, u8 status_code) +{ + u8 buf[256]; + struct ieee80211_mgmt *m = (struct ieee80211_mgmt *) buf; + struct wmm_tspec_element *t = (struct wmm_tspec_element *) + m->u.action.u.wmm_action.variable; + int len; + + hostapd_logger(hapd, addr, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "action response - reason %d", status_code); + os_memset(buf, 0, sizeof(buf)); + m->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, + WLAN_FC_STYPE_ACTION); + os_memcpy(m->da, addr, ETH_ALEN); + os_memcpy(m->sa, hapd->own_addr, ETH_ALEN); + os_memcpy(m->bssid, hapd->own_addr, ETH_ALEN); + m->u.action.category = WLAN_ACTION_WMM; + m->u.action.u.wmm_action.action_code = action_code; + m->u.action.u.wmm_action.dialog_token = dialogue_token; + m->u.action.u.wmm_action.status_code = status_code; + os_memcpy(t, tspec, sizeof(struct wmm_tspec_element)); + len = ((u8 *) (t + 1)) - buf; + + if (hostapd_drv_send_mlme(hapd, m, len, 0) < 0) + wpa_printf(MSG_INFO, "wmm_send_action: send failed"); +} + + +int wmm_process_tspec(struct wmm_tspec_element *tspec) +{ + u64 medium_time; + unsigned int pps, duration; + unsigned int up, psb, dir, tid; + u16 val, surplus; + + up = (tspec->ts_info[1] >> 3) & 0x07; + psb = (tspec->ts_info[1] >> 2) & 0x01; + dir = (tspec->ts_info[0] >> 5) & 0x03; + tid = (tspec->ts_info[0] >> 1) & 0x0f; + wpa_printf(MSG_DEBUG, "WMM: TS Info: UP=%d PSB=%d Direction=%d TID=%d", + up, psb, dir, tid); + val = le_to_host16(tspec->nominal_msdu_size); + wpa_printf(MSG_DEBUG, "WMM: Nominal MSDU Size: %d%s", + val & 0x7fff, val & 0x8000 ? " (fixed)" : ""); + wpa_printf(MSG_DEBUG, "WMM: Mean Data Rate: %u bps", + le_to_host32(tspec->mean_data_rate)); + wpa_printf(MSG_DEBUG, "WMM: Minimum PHY Rate: %u bps", + le_to_host32(tspec->minimum_phy_rate)); + val = le_to_host16(tspec->surplus_bandwidth_allowance); + wpa_printf(MSG_DEBUG, "WMM: Surplus Bandwidth Allowance: %u.%04u", + val >> 13, 10000 * (val & 0x1fff) / 0x2000); + + val = le_to_host16(tspec->nominal_msdu_size); + if (val == 0) { + wpa_printf(MSG_DEBUG, "WMM: Invalid Nominal MSDU Size (0)"); + return WMM_ADDTS_STATUS_INVALID_PARAMETERS; + } + /* pps = Ceiling((Mean Data Rate / 8) / Nominal MSDU Size) */ + pps = ((le_to_host32(tspec->mean_data_rate) / 8) + val - 1) / val; + wpa_printf(MSG_DEBUG, "WMM: Packets-per-second estimate for TSPEC: %d", + pps); + + if (le_to_host32(tspec->minimum_phy_rate) < 1000000) { + wpa_printf(MSG_DEBUG, "WMM: Too small Minimum PHY Rate"); + return WMM_ADDTS_STATUS_INVALID_PARAMETERS; + } + + duration = (le_to_host16(tspec->nominal_msdu_size) & 0x7fff) * 8 / + (le_to_host32(tspec->minimum_phy_rate) / 1000000) + + 50 /* FIX: proper SIFS + ACK duration */; + + /* unsigned binary number with an implicit binary point after the + * leftmost 3 bits, i.e., 0x2000 = 1.0 */ + surplus = le_to_host16(tspec->surplus_bandwidth_allowance); + if (surplus <= 0x2000) { + wpa_printf(MSG_DEBUG, "WMM: Surplus Bandwidth Allowance not " + "greater than unity"); + return WMM_ADDTS_STATUS_INVALID_PARAMETERS; + } + + medium_time = (u64) surplus * pps * duration / 0x2000; + wpa_printf(MSG_DEBUG, "WMM: Estimated medium time: %lu", + (unsigned long) medium_time); + + /* + * TODO: store list of granted (and still active) TSPECs and check + * whether there is available medium time for this request. For now, + * just refuse requests that would by themselves take very large + * portion of the available bandwidth. + */ + if (medium_time > 750000) { + wpa_printf(MSG_DEBUG, "WMM: Refuse TSPEC request for over " + "75%% of available bandwidth"); + return WMM_ADDTS_STATUS_REFUSED; + } + + /* Convert to 32 microseconds per second unit */ + tspec->medium_time = host_to_le16(medium_time / 32); + + return WMM_ADDTS_STATUS_ADMISSION_ACCEPTED; +} + + +static void wmm_addts_req(struct hostapd_data *hapd, + const struct ieee80211_mgmt *mgmt, + struct wmm_tspec_element *tspec, size_t len) +{ + const u8 *end = ((const u8 *) mgmt) + len; + int res; + + if ((const u8 *) (tspec + 1) > end) { + wpa_printf(MSG_DEBUG, "WMM: TSPEC overflow in ADDTS Request"); + return; + } + + wpa_printf(MSG_DEBUG, "WMM: ADDTS Request (Dialog Token %d) for TSPEC " + "from " MACSTR, + mgmt->u.action.u.wmm_action.dialog_token, + MAC2STR(mgmt->sa)); + + res = wmm_process_tspec(tspec); + wpa_printf(MSG_DEBUG, "WMM: ADDTS processing result: %d", res); + + wmm_send_action(hapd, mgmt->sa, tspec, WMM_ACTION_CODE_ADDTS_RESP, + mgmt->u.action.u.wmm_action.dialog_token, res); +} + + +void hostapd_wmm_action(struct hostapd_data *hapd, + const struct ieee80211_mgmt *mgmt, size_t len) +{ + int action_code; + int left = len - IEEE80211_HDRLEN - 4; + const u8 *pos = ((const u8 *) mgmt) + IEEE80211_HDRLEN + 4; + struct ieee802_11_elems elems; + struct sta_info *sta = ap_get_sta(hapd, mgmt->sa); + + /* check that the request comes from a valid station */ + if (!sta || + (sta->flags & (WLAN_STA_ASSOC | WLAN_STA_WMM)) != + (WLAN_STA_ASSOC | WLAN_STA_WMM)) { + hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "wmm action received is not from associated wmm" + " station"); + /* TODO: respond with action frame refused status code */ + return; + } + + if (left < 0) + return; /* not a valid WMM Action frame */ + + /* extract the tspec info element */ + if (ieee802_11_parse_elems(pos, left, &elems, 1) == ParseFailed) { + hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "hostapd_wmm_action - could not parse wmm " + "action"); + /* TODO: respond with action frame invalid parameters status + * code */ + return; + } + + if (!elems.wmm_tspec || + elems.wmm_tspec_len != (sizeof(struct wmm_tspec_element) - 2)) { + hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "hostapd_wmm_action - missing or wrong length " + "tspec"); + /* TODO: respond with action frame invalid parameters status + * code */ + return; + } + + /* TODO: check the request is for an AC with ACM set, if not, refuse + * request */ + + action_code = mgmt->u.action.u.wmm_action.action_code; + switch (action_code) { + case WMM_ACTION_CODE_ADDTS_REQ: + wmm_addts_req(hapd, mgmt, (struct wmm_tspec_element *) + (elems.wmm_tspec - 2), len); + return; +#if 0 + /* TODO: needed for client implementation */ + case WMM_ACTION_CODE_ADDTS_RESP: + wmm_setup_request(hapd, mgmt, len); + return; + /* TODO: handle station teardown requests */ + case WMM_ACTION_CODE_DELTS: + wmm_teardown(hapd, mgmt, len); + return; +#endif + } + + hostapd_logger(hapd, mgmt->sa, HOSTAPD_MODULE_IEEE80211, + HOSTAPD_LEVEL_DEBUG, + "hostapd_wmm_action - unknown action code %d", + action_code); +} diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/wmm.h b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/wmm.h new file mode 100755 index 0000000..b70b863 --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/wmm.h @@ -0,0 +1,23 @@ +/* + * hostapd / WMM (Wi-Fi Multimedia) + * Copyright 2002-2003, Instant802 Networks, Inc. + * Copyright 2005-2006, Devicescape Software, Inc. + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef WME_H +#define WME_H + +struct ieee80211_mgmt; +struct wmm_tspec_element; + +u8 * hostapd_eid_wmm(struct hostapd_data *hapd, u8 *eid); +int hostapd_eid_wmm_valid(struct hostapd_data *hapd, const u8 *eid, + size_t len); +void hostapd_wmm_action(struct hostapd_data *hapd, + const struct ieee80211_mgmt *mgmt, size_t len); +int wmm_process_tspec(struct wmm_tspec_element *tspec); + +#endif /* WME_H */ diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/wpa_auth.c b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/wpa_auth.c new file mode 100755 index 0000000..256236e --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/wpa_auth.c @@ -0,0 +1,4926 @@ +/* + * IEEE 802.11 RSN / WPA Authenticator + * Copyright (c) 2004-2019, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "utils/eloop.h" +#include "utils/state_machine.h" +#include "utils/bitfield.h" +#include "common/ieee802_11_defs.h" +#include "common/ocv.h" +#include "crypto/aes.h" +#include "crypto/aes_wrap.h" +#include "crypto/aes_siv.h" +#include "crypto/crypto.h" +#include "crypto/sha1.h" +#include "crypto/sha256.h" +#include "crypto/sha384.h" +#include "crypto/random.h" +#include "eapol_auth/eapol_auth_sm.h" +#include "drivers/driver.h" +#include "ap_config.h" +#include "ieee802_11.h" +#include "wpa_auth.h" +#include "pmksa_cache_auth.h" +#include "wpa_auth_i.h" +#include "wpa_auth_ie.h" + +#define STATE_MACHINE_DATA struct wpa_state_machine +#define STATE_MACHINE_DEBUG_PREFIX "WPA" +#define STATE_MACHINE_ADDR sm->addr + + +static void wpa_send_eapol_timeout(void *eloop_ctx, void *timeout_ctx); +static int wpa_sm_step(struct wpa_state_machine *sm); +static int wpa_verify_key_mic(int akmp, size_t pmk_len, struct wpa_ptk *PTK, + u8 *data, size_t data_len); +#ifdef CONFIG_FILS +static int wpa_aead_decrypt(struct wpa_state_machine *sm, struct wpa_ptk *ptk, + u8 *buf, size_t buf_len, u16 *_key_data_len); +static struct wpabuf * fils_prepare_plainbuf(struct wpa_state_machine *sm, + const struct wpabuf *hlp); +#endif /* CONFIG_FILS */ +static void wpa_sm_call_step(void *eloop_ctx, void *timeout_ctx); +static void wpa_group_sm_step(struct wpa_authenticator *wpa_auth, + struct wpa_group *group); +static void wpa_request_new_ptk(struct wpa_state_machine *sm); +static int wpa_gtk_update(struct wpa_authenticator *wpa_auth, + struct wpa_group *group); +static int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth, + struct wpa_group *group); +static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce, + const u8 *pmk, unsigned int pmk_len, + struct wpa_ptk *ptk); +static void wpa_group_free(struct wpa_authenticator *wpa_auth, + struct wpa_group *group); +static void wpa_group_get(struct wpa_authenticator *wpa_auth, + struct wpa_group *group); +static void wpa_group_put(struct wpa_authenticator *wpa_auth, + struct wpa_group *group); +static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos); + +static const u32 eapol_key_timeout_first = 100; /* ms */ +static const u32 eapol_key_timeout_subseq = 1000; /* ms */ +static const u32 eapol_key_timeout_first_group = 500; /* ms */ +static const u32 eapol_key_timeout_no_retrans = 4000; /* ms */ + +/* TODO: make these configurable */ +static const int dot11RSNAConfigPMKLifetime = 43200; +static const int dot11RSNAConfigPMKReauthThreshold = 70; +static const int dot11RSNAConfigSATimeout = 60; + + +static inline int wpa_auth_mic_failure_report( + struct wpa_authenticator *wpa_auth, const u8 *addr) +{ + if (wpa_auth->cb->mic_failure_report) + return wpa_auth->cb->mic_failure_report(wpa_auth->cb_ctx, addr); + return 0; +} + + +static inline void wpa_auth_psk_failure_report( + struct wpa_authenticator *wpa_auth, const u8 *addr) +{ + if (wpa_auth->cb->psk_failure_report) + wpa_auth->cb->psk_failure_report(wpa_auth->cb_ctx, addr); +} + + +static inline void wpa_auth_set_eapol(struct wpa_authenticator *wpa_auth, + const u8 *addr, wpa_eapol_variable var, + int value) +{ + if (wpa_auth->cb->set_eapol) + wpa_auth->cb->set_eapol(wpa_auth->cb_ctx, addr, var, value); +} + + +static inline int wpa_auth_get_eapol(struct wpa_authenticator *wpa_auth, + const u8 *addr, wpa_eapol_variable var) +{ + if (wpa_auth->cb->get_eapol == NULL) + return -1; + return wpa_auth->cb->get_eapol(wpa_auth->cb_ctx, addr, var); +} + + +static inline const u8 * wpa_auth_get_psk(struct wpa_authenticator *wpa_auth, + const u8 *addr, + const u8 *p2p_dev_addr, + const u8 *prev_psk, size_t *psk_len, + int *vlan_id) +{ + if (wpa_auth->cb->get_psk == NULL) + return NULL; + return wpa_auth->cb->get_psk(wpa_auth->cb_ctx, addr, p2p_dev_addr, + prev_psk, psk_len, vlan_id); +} + + +static inline int wpa_auth_get_msk(struct wpa_authenticator *wpa_auth, + const u8 *addr, u8 *msk, size_t *len) +{ + if (wpa_auth->cb->get_msk == NULL) + return -1; + return wpa_auth->cb->get_msk(wpa_auth->cb_ctx, addr, msk, len); +} + + +static inline int wpa_auth_set_key(struct wpa_authenticator *wpa_auth, + int vlan_id, + enum wpa_alg alg, const u8 *addr, int idx, + u8 *key, size_t key_len) +{ + if (wpa_auth->cb->set_key == NULL) + return -1; + return wpa_auth->cb->set_key(wpa_auth->cb_ctx, vlan_id, alg, addr, idx, + key, key_len); +} + + +static inline int wpa_auth_get_seqnum(struct wpa_authenticator *wpa_auth, + const u8 *addr, int idx, u8 *seq) +{ + if (wpa_auth->cb->get_seqnum == NULL) + return -1; + return wpa_auth->cb->get_seqnum(wpa_auth->cb_ctx, addr, idx, seq); +} + + +static inline int +wpa_auth_send_eapol(struct wpa_authenticator *wpa_auth, const u8 *addr, + const u8 *data, size_t data_len, int encrypt) +{ + if (wpa_auth->cb->send_eapol == NULL) + return -1; + return wpa_auth->cb->send_eapol(wpa_auth->cb_ctx, addr, data, data_len, + encrypt); +} + + +#ifdef CONFIG_MESH +static inline int wpa_auth_start_ampe(struct wpa_authenticator *wpa_auth, + const u8 *addr) +{ + if (wpa_auth->cb->start_ampe == NULL) + return -1; + return wpa_auth->cb->start_ampe(wpa_auth->cb_ctx, addr); +} +#endif /* CONFIG_MESH */ + + +int wpa_auth_for_each_sta(struct wpa_authenticator *wpa_auth, + int (*cb)(struct wpa_state_machine *sm, void *ctx), + void *cb_ctx) +{ + if (wpa_auth->cb->for_each_sta == NULL) + return 0; + return wpa_auth->cb->for_each_sta(wpa_auth->cb_ctx, cb, cb_ctx); +} + + +int wpa_auth_for_each_auth(struct wpa_authenticator *wpa_auth, + int (*cb)(struct wpa_authenticator *a, void *ctx), + void *cb_ctx) +{ + if (wpa_auth->cb->for_each_auth == NULL) + return 0; + return wpa_auth->cb->for_each_auth(wpa_auth->cb_ctx, cb, cb_ctx); +} + +#if CFG_ENABLE_WPA_LOG +void wpa_auth_logger(struct wpa_authenticator *wpa_auth, const u8 *addr, + logger_level level, const char *txt) +{ + if (wpa_auth->cb->logger == NULL) + return; + wpa_auth->cb->logger(wpa_auth->cb_ctx, addr, level, txt); +} + +void wpa_auth_vlogger(struct wpa_authenticator *wpa_auth, const u8 *addr, + logger_level level, const char *fmt, ...) +{ + char *format; + int maxlen; + va_list ap; + + if (wpa_auth->cb->logger == NULL) + return; + + maxlen = os_strlen(fmt) + 100; + format = os_malloc(maxlen); + if (!format) + return; + + va_start(ap, fmt); + vsnprintf(format, maxlen, fmt, ap); + va_end(ap); + + wpa_auth_logger(wpa_auth, addr, level, format); + + os_free(format); +} +#endif + +static void wpa_sta_disconnect(struct wpa_authenticator *wpa_auth, + const u8 *addr, u16 reason) +{ + if (wpa_auth->cb->disconnect == NULL) + return; + wpa_printf(MSG_DEBUG, "wpa_sta_disconnect STA " MACSTR " (reason %u)", + MAC2STR(addr), reason); + wpa_auth->cb->disconnect(wpa_auth->cb_ctx, addr, reason); +} + + +#ifdef CONFIG_OCV +static int wpa_channel_info(struct wpa_authenticator *wpa_auth, + struct wpa_channel_info *ci) +{ + if (!wpa_auth->cb->channel_info) + return -1; + return wpa_auth->cb->channel_info(wpa_auth->cb_ctx, ci); +} +#endif /* CONFIG_OCV */ + + +static int wpa_auth_update_vlan(struct wpa_authenticator *wpa_auth, + const u8 *addr, int vlan_id) +{ + if (!wpa_auth->cb->update_vlan) + return -1; + return wpa_auth->cb->update_vlan(wpa_auth->cb_ctx, addr, vlan_id); +} + + +static void wpa_rekey_gmk(void *eloop_ctx, void *timeout_ctx) +{ + struct wpa_authenticator *wpa_auth = eloop_ctx; + + if (random_get_bytes(wpa_auth->group->GMK, WPA_GMK_LEN)) { + wpa_printf(MSG_ERROR, "Failed to get random data for WPA " + "initialization."); + } else { + wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG, "GMK rekeyd"); + wpa_hexdump_key(MSG_DEBUG, "GMK", + wpa_auth->group->GMK, WPA_GMK_LEN); + } + + if (wpa_auth->conf.wpa_gmk_rekey) { + eloop_register_timeout(wpa_auth->conf.wpa_gmk_rekey, 0, + wpa_rekey_gmk, wpa_auth, NULL); + } +} + + +static void wpa_rekey_gtk(void *eloop_ctx, void *timeout_ctx) +{ + struct wpa_authenticator *wpa_auth = eloop_ctx; + struct wpa_group *group, *next; + + wpa_auth_logger(wpa_auth, NULL, LOGGER_DEBUG, "rekeying GTK"); + group = wpa_auth->group; + while (group) { + wpa_group_get(wpa_auth, group); + + group->GTKReKey = TRUE; + do { + group->changed = FALSE; + wpa_group_sm_step(wpa_auth, group); + } while (group->changed); + + next = group->next; + wpa_group_put(wpa_auth, group); + group = next; + } + + if (wpa_auth->conf.wpa_group_rekey) { + eloop_register_timeout(wpa_auth->conf.wpa_group_rekey, + 0, wpa_rekey_gtk, wpa_auth, NULL); + } +} + + +static void wpa_rekey_ptk(void *eloop_ctx, void *timeout_ctx) +{ + struct wpa_authenticator *wpa_auth __maybe_unused = eloop_ctx; + struct wpa_state_machine *sm = timeout_ctx; + + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "rekeying PTK"); + wpa_request_new_ptk(sm); + wpa_sm_step(sm); +} + + +void wpa_auth_set_ptk_rekey_timer(struct wpa_state_machine *sm) +{ + if (sm && sm->wpa_auth->conf.wpa_ptk_rekey) { + wpa_printf(MSG_DEBUG, "WPA: Start PTK rekeying timer for " + MACSTR " (%d seconds)", MAC2STR(sm->addr), + sm->wpa_auth->conf.wpa_ptk_rekey); + eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm); + eloop_register_timeout(sm->wpa_auth->conf.wpa_ptk_rekey, 0, + wpa_rekey_ptk, sm->wpa_auth, sm); + } +} + + +static int wpa_auth_pmksa_clear_cb(struct wpa_state_machine *sm, void *ctx) +{ + if (sm->pmksa == ctx) + sm->pmksa = NULL; + return 0; +} + + +static void wpa_auth_pmksa_free_cb(struct rsn_pmksa_cache_entry *entry, + void *ctx) +{ + struct wpa_authenticator *wpa_auth = ctx; + wpa_auth_for_each_sta(wpa_auth, wpa_auth_pmksa_clear_cb, entry); +} + + +static int wpa_group_init_gmk_and_counter(struct wpa_authenticator *wpa_auth, + struct wpa_group *group) +{ + u8 buf[ETH_ALEN + 8 + sizeof(unsigned long)]; + u8 rkey[32]; + unsigned long ptr; + + if (random_get_bytes(group->GMK, WPA_GMK_LEN) < 0) + return -1; + wpa_hexdump_key(MSG_DEBUG, "GMK", group->GMK, WPA_GMK_LEN); + + /* + * Counter = PRF-256(Random number, "Init Counter", + * Local MAC Address || Time) + */ + os_memcpy(buf, wpa_auth->addr, ETH_ALEN); + wpa_get_ntp_timestamp(buf + ETH_ALEN); + ptr = (unsigned long) group; + os_memcpy(buf + ETH_ALEN + 8, &ptr, sizeof(ptr)); + if (random_get_bytes(rkey, sizeof(rkey)) < 0) + return -1; + + if (sha1_prf(rkey, sizeof(rkey), "Init Counter", buf, sizeof(buf), + group->Counter, WPA_NONCE_LEN) < 0) + return -1; + wpa_hexdump_key(MSG_DEBUG, "Key Counter", + group->Counter, WPA_NONCE_LEN); + + return 0; +} + + +static struct wpa_group * wpa_group_init(struct wpa_authenticator *wpa_auth, + int vlan_id, int delay_init) +{ + struct wpa_group *group; + + group = os_zalloc(sizeof(struct wpa_group)); + if (group == NULL) + return NULL; + + group->GTKAuthenticator = TRUE; + group->vlan_id = vlan_id; + group->GTK_len = wpa_cipher_key_len(wpa_auth->conf.wpa_group); + + if (random_pool_ready() != 1) { + wpa_printf(MSG_INFO, "WPA: Not enough entropy in random pool " + "for secure operations - update keys later when " + "the first station connects"); + } + + /* + * Set initial GMK/Counter value here. The actual values that will be + * used in negotiations will be set once the first station tries to + * connect. This allows more time for collecting additional randomness + * on embedded devices. + */ + if (wpa_group_init_gmk_and_counter(wpa_auth, group) < 0) { + wpa_printf(MSG_ERROR, "Failed to get random data for WPA " + "initialization."); + os_free(group); + return NULL; + } + + group->GInit = TRUE; + if (delay_init) { + wpa_printf(MSG_DEBUG, "WPA: Delay group state machine start " + "until Beacon frames have been configured"); + /* Initialization is completed in wpa_init_keys(). */ + } else { + wpa_group_sm_step(wpa_auth, group); + group->GInit = FALSE; + wpa_group_sm_step(wpa_auth, group); + } + + return group; +} + + +/** + * wpa_init - Initialize WPA authenticator + * @addr: Authenticator address + * @conf: Configuration for WPA authenticator + * @cb: Callback functions for WPA authenticator + * Returns: Pointer to WPA authenticator data or %NULL on failure + */ +struct wpa_authenticator * wpa_init(const u8 *addr, + struct wpa_auth_config *conf, + const struct wpa_auth_callbacks *cb, + void *cb_ctx) +{ + struct wpa_authenticator *wpa_auth; + + wpa_auth = os_zalloc(sizeof(struct wpa_authenticator)); + if (wpa_auth == NULL) + return NULL; + os_memcpy(wpa_auth->addr, addr, ETH_ALEN); + os_memcpy(&wpa_auth->conf, conf, sizeof(*conf)); + wpa_auth->cb = cb; + wpa_auth->cb_ctx = cb_ctx; + + if (wpa_auth_gen_wpa_ie(wpa_auth)) { + wpa_printf(MSG_ERROR, "Could not generate WPA IE."); + os_free(wpa_auth); + return NULL; + } + + wpa_auth->group = wpa_group_init(wpa_auth, 0, 1); + if (wpa_auth->group == NULL) { + os_free(wpa_auth->wpa_ie); + os_free(wpa_auth); + return NULL; + } + + wpa_auth->pmksa = pmksa_cache_auth_init(wpa_auth_pmksa_free_cb, + wpa_auth); + if (wpa_auth->pmksa == NULL) { + wpa_printf(MSG_ERROR, "PMKSA cache initialization failed."); + os_free(wpa_auth->group); + os_free(wpa_auth->wpa_ie); + os_free(wpa_auth); + return NULL; + } + +#ifdef CONFIG_IEEE80211R_AP + wpa_auth->ft_pmk_cache = wpa_ft_pmk_cache_init(); + if (wpa_auth->ft_pmk_cache == NULL) { + wpa_printf(MSG_ERROR, "FT PMK cache initialization failed."); + os_free(wpa_auth->group); + os_free(wpa_auth->wpa_ie); + pmksa_cache_auth_deinit(wpa_auth->pmksa); + os_free(wpa_auth); + return NULL; + } +#endif /* CONFIG_IEEE80211R_AP */ + +#ifdef CONFIG_FULL_HOSTAPD + if (wpa_auth->conf.wpa_gmk_rekey) { + eloop_register_timeout(wpa_auth->conf.wpa_gmk_rekey, 0, + wpa_rekey_gmk, wpa_auth, NULL); + } + + if (wpa_auth->conf.wpa_group_rekey) { + eloop_register_timeout(wpa_auth->conf.wpa_group_rekey, 0, + wpa_rekey_gtk, wpa_auth, NULL); + } +#endif + +#ifdef CONFIG_P2P + if (WPA_GET_BE32(conf->ip_addr_start)) { + int count = WPA_GET_BE32(conf->ip_addr_end) - + WPA_GET_BE32(conf->ip_addr_start) + 1; + if (count > 1000) + count = 1000; + if (count > 0) + wpa_auth->ip_pool = bitfield_alloc(count); + } +#endif /* CONFIG_P2P */ + + return wpa_auth; +} + + +int wpa_init_keys(struct wpa_authenticator *wpa_auth) +{ + struct wpa_group *group = wpa_auth->group; + + wpa_printf(MSG_DEBUG, "WPA: Start group state machine to set initial " + "keys"); + wpa_group_sm_step(wpa_auth, group); + group->GInit = FALSE; + wpa_group_sm_step(wpa_auth, group); + if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE) + return -1; + return 0; +} + + +/** + * wpa_deinit - Deinitialize WPA authenticator + * @wpa_auth: Pointer to WPA authenticator data from wpa_init() + */ +void wpa_deinit(struct wpa_authenticator *wpa_auth) +{ + struct wpa_group *group, *prev; + + eloop_cancel_timeout(wpa_rekey_gmk, wpa_auth, NULL); + eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL); + + pmksa_cache_auth_deinit(wpa_auth->pmksa); + +#ifdef CONFIG_IEEE80211R_AP + wpa_ft_pmk_cache_deinit(wpa_auth->ft_pmk_cache); + wpa_auth->ft_pmk_cache = NULL; + wpa_ft_deinit(wpa_auth); +#endif /* CONFIG_IEEE80211R_AP */ + +#ifdef CONFIG_P2P + bitfield_free(wpa_auth->ip_pool); +#endif /* CONFIG_P2P */ + + + os_free(wpa_auth->wpa_ie); + + group = wpa_auth->group; + while (group) { + prev = group; + group = group->next; + os_free(prev); + } + + os_free(wpa_auth); +} + + +/** + * wpa_reconfig - Update WPA authenticator configuration + * @wpa_auth: Pointer to WPA authenticator data from wpa_init() + * @conf: Configuration for WPA authenticator + */ +int wpa_reconfig(struct wpa_authenticator *wpa_auth, + struct wpa_auth_config *conf) +{ + struct wpa_group *group; + if (wpa_auth == NULL) + return 0; + + os_memcpy(&wpa_auth->conf, conf, sizeof(*conf)); + if (wpa_auth_gen_wpa_ie(wpa_auth)) { + wpa_printf(MSG_ERROR, "Could not generate WPA IE."); + return -1; + } + + /* + * Reinitialize GTK to make sure it is suitable for the new + * configuration. + */ + group = wpa_auth->group; + group->GTK_len = wpa_cipher_key_len(wpa_auth->conf.wpa_group); + group->GInit = TRUE; + wpa_group_sm_step(wpa_auth, group); + group->GInit = FALSE; + wpa_group_sm_step(wpa_auth, group); + + return 0; +} + + +struct wpa_state_machine * +wpa_auth_sta_init(struct wpa_authenticator *wpa_auth, const u8 *addr, + const u8 *p2p_dev_addr) +{ + struct wpa_state_machine *sm; + + if (wpa_auth->group->wpa_group_state == WPA_GROUP_FATAL_FAILURE) + return NULL; + + sm = os_zalloc(sizeof(struct wpa_state_machine)); + if (sm == NULL) + return NULL; + os_memcpy(sm->addr, addr, ETH_ALEN); + if (p2p_dev_addr) + os_memcpy(sm->p2p_dev_addr, p2p_dev_addr, ETH_ALEN); + + sm->wpa_auth = wpa_auth; + sm->group = wpa_auth->group; + wpa_group_get(sm->wpa_auth, sm->group); + + return sm; +} + + +int wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth, + struct wpa_state_machine *sm) +{ + if (wpa_auth == NULL || !wpa_auth->conf.wpa || sm == NULL) + return -1; + +#ifdef CONFIG_IEEE80211R_AP + if (sm->ft_completed) { + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, + "FT authentication already completed - do not " + "start 4-way handshake"); + /* Go to PTKINITDONE state to allow GTK rekeying */ + sm->wpa_ptk_state = WPA_PTK_PTKINITDONE; + sm->Pair = TRUE; + return 0; + } +#endif /* CONFIG_IEEE80211R_AP */ + +#ifdef CONFIG_FILS + if (sm->fils_completed) { + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, + "FILS authentication already completed - do not start 4-way handshake"); + /* Go to PTKINITDONE state to allow GTK rekeying */ + sm->wpa_ptk_state = WPA_PTK_PTKINITDONE; + sm->Pair = TRUE; + return 0; + } +#endif /* CONFIG_FILS */ + + if (sm->started) { + os_memset(&sm->key_replay, 0, sizeof(sm->key_replay)); + sm->ReAuthenticationRequest = TRUE; + return wpa_sm_step(sm); + } + + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, + "start authentication"); + sm->started = 1; + + sm->Init = TRUE; + if (wpa_sm_step(sm) == 1) + return 1; /* should not really happen */ + sm->Init = FALSE; + sm->AuthenticationRequest = TRUE; + return wpa_sm_step(sm); +} + + +void wpa_auth_sta_no_wpa(struct wpa_state_machine *sm) +{ + /* WPA/RSN was not used - clear WPA state. This is needed if the STA + * reassociates back to the same AP while the previous entry for the + * STA has not yet been removed. */ + if (sm == NULL) + return; + + sm->wpa_key_mgmt = 0; +} + + +static void wpa_free_sta_sm(struct wpa_state_machine *sm) +{ +#ifdef CONFIG_P2P + if (WPA_GET_BE32(sm->ip_addr)) { + u32 start; + wpa_printf(MSG_DEBUG, "P2P: Free assigned IP " + "address %u.%u.%u.%u from " MACSTR, + sm->ip_addr[0], sm->ip_addr[1], + sm->ip_addr[2], sm->ip_addr[3], + MAC2STR(sm->addr)); + start = WPA_GET_BE32(sm->wpa_auth->conf.ip_addr_start); + bitfield_clear(sm->wpa_auth->ip_pool, + WPA_GET_BE32(sm->ip_addr) - start); + } +#endif /* CONFIG_P2P */ + if (sm->GUpdateStationKeys) { + sm->group->GKeyDoneStations--; + sm->GUpdateStationKeys = FALSE; + } +#ifdef CONFIG_IEEE80211R_AP + os_free(sm->assoc_resp_ftie); + wpabuf_free(sm->ft_pending_req_ies); +#endif /* CONFIG_IEEE80211R_AP */ + os_free(sm->last_rx_eapol_key); + os_free(sm->wpa_ie); + wpa_group_put(sm->wpa_auth, sm->group); +#ifdef CONFIG_DPP2 + wpabuf_clear_free(sm->dpp_z); +#endif /* CONFIG_DPP2 */ + bin_clear_free(sm, sizeof(*sm)); +} + + +void wpa_auth_sta_deinit(struct wpa_state_machine *sm) +{ + if (sm == NULL) + return; + + if (sm->wpa_auth->conf.wpa_strict_rekey && sm->has_GTK) { + wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, + "strict rekeying - force GTK rekey since STA " + "is leaving"); + if (eloop_deplete_timeout(0, 500000, wpa_rekey_gtk, + sm->wpa_auth, NULL) == -1) + eloop_register_timeout(0, 500000, wpa_rekey_gtk, sm->wpa_auth, + NULL); + } + + eloop_cancel_timeout(wpa_send_eapol_timeout, sm->wpa_auth, sm); + sm->pending_1_of_4_timeout = 0; + eloop_cancel_timeout(wpa_sm_call_step, sm, NULL); + eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm); +#ifdef CONFIG_IEEE80211R_AP + wpa_ft_sta_deinit(sm); +#endif /* CONFIG_IEEE80211R_AP */ + if (sm->in_step_loop) { + /* Must not free state machine while wpa_sm_step() is running. + * Freeing will be completed in the end of wpa_sm_step(). */ + wpa_printf(MSG_DEBUG, "WPA: Registering pending STA state " + "machine deinit for " MACSTR, MAC2STR(sm->addr)); + sm->pending_deinit = 1; + } else + wpa_free_sta_sm(sm); +} + + +static void wpa_request_new_ptk(struct wpa_state_machine *sm) +{ + if (sm == NULL) + return; + + sm->PTKRequest = TRUE; + sm->PTK_valid = 0; +} + + +static int wpa_replay_counter_valid(struct wpa_key_replay_counter *ctr, + const u8 *replay_counter) +{ + int i; + for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) { + if (!ctr[i].valid) + break; + if (os_memcmp(replay_counter, ctr[i].counter, + WPA_REPLAY_COUNTER_LEN) == 0) + return 1; + } + return 0; +} + + +static void wpa_replay_counter_mark_invalid(struct wpa_key_replay_counter *ctr, + const u8 *replay_counter) +{ + int i; + for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) { + if (ctr[i].valid && + (replay_counter == NULL || + os_memcmp(replay_counter, ctr[i].counter, + WPA_REPLAY_COUNTER_LEN) == 0)) + ctr[i].valid = FALSE; + } +} + + +#ifdef CONFIG_IEEE80211R_AP +static int ft_check_msg_2_of_4(struct wpa_authenticator *wpa_auth, + struct wpa_state_machine *sm, + struct wpa_eapol_ie_parse *kde) +{ + struct wpa_ie_data ie; + struct rsn_mdie *mdie; + + if (wpa_parse_wpa_ie_rsn(kde->rsn_ie, kde->rsn_ie_len, &ie) < 0 || + ie.num_pmkid != 1 || ie.pmkid == NULL) { + wpa_printf(MSG_DEBUG, "FT: No PMKR1Name in " + "FT 4-way handshake message 2/4"); + return -1; + } + + os_memcpy(sm->sup_pmk_r1_name, ie.pmkid, PMKID_LEN); + wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name from Supplicant", + sm->sup_pmk_r1_name, PMKID_LEN); + + if (!kde->mdie || !kde->ftie) { + wpa_printf(MSG_DEBUG, "FT: No %s in FT 4-way handshake " + "message 2/4", kde->mdie ? "FTIE" : "MDIE"); + return -1; + } + + mdie = (struct rsn_mdie *) (kde->mdie + 2); + if (kde->mdie[1] < sizeof(struct rsn_mdie) || + os_memcmp(wpa_auth->conf.mobility_domain, mdie->mobility_domain, + MOBILITY_DOMAIN_ID_LEN) != 0) { + wpa_printf(MSG_DEBUG, "FT: MDIE mismatch"); + return -1; + } + + if (sm->assoc_resp_ftie && + (kde->ftie[1] != sm->assoc_resp_ftie[1] || + os_memcmp(kde->ftie, sm->assoc_resp_ftie, + 2 + sm->assoc_resp_ftie[1]) != 0)) { + wpa_printf(MSG_DEBUG, "FT: FTIE mismatch"); + wpa_hexdump(MSG_DEBUG, "FT: FTIE in EAPOL-Key msg 2/4", + kde->ftie, kde->ftie_len); + wpa_hexdump(MSG_DEBUG, "FT: FTIE in (Re)AssocResp", + sm->assoc_resp_ftie, 2 + sm->assoc_resp_ftie[1]); + return -1; + } + + return 0; +} +#endif /* CONFIG_IEEE80211R_AP */ + + +static int wpa_receive_error_report(struct wpa_authenticator *wpa_auth, + struct wpa_state_machine *sm, int group) +{ + /* Supplicant reported a Michael MIC error */ + wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, + "received EAPOL-Key Error Request " + "(STA detected Michael MIC failure (group=%d))", + group); + + if (group && wpa_auth->conf.wpa_group != WPA_CIPHER_TKIP) { + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, + "ignore Michael MIC failure report since " + "group cipher is not TKIP"); + } else if (!group && sm->pairwise != WPA_CIPHER_TKIP) { + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, + "ignore Michael MIC failure report since " + "pairwise cipher is not TKIP"); + } else { + if (wpa_auth_mic_failure_report(wpa_auth, sm->addr) > 0) + return 1; /* STA entry was removed */ + sm->dot11RSNAStatsTKIPRemoteMICFailures++; + wpa_auth->dot11RSNAStatsTKIPRemoteMICFailures++; + } + + /* + * Error report is not a request for a new key handshake, but since + * Authenticator may do it, let's change the keys now anyway. + */ + wpa_request_new_ptk(sm); + return 0; +} + + +static int wpa_try_alt_snonce(struct wpa_state_machine *sm, u8 *data, + size_t data_len) +{ + struct wpa_ptk PTK; + int ok = 0; + const u8 *pmk = NULL; + size_t pmk_len; + int vlan_id = 0; + + os_memset(&PTK, 0, sizeof(PTK)); + for (;;) { + if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) && + !wpa_key_mgmt_sae(sm->wpa_key_mgmt)) { + pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, + sm->p2p_dev_addr, pmk, &pmk_len, + &vlan_id); + if (pmk == NULL) + break; +#ifdef CONFIG_IEEE80211R_AP + if (wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt)) { + os_memcpy(sm->xxkey, pmk, pmk_len); + sm->xxkey_len = pmk_len; + } +#endif /* CONFIG_IEEE80211R_AP */ + } else { + pmk = sm->PMK; + pmk_len = sm->pmk_len; + } + + if (wpa_derive_ptk(sm, sm->alt_SNonce, pmk, pmk_len, &PTK) < 0) + break; + + if (wpa_verify_key_mic(sm->wpa_key_mgmt, pmk_len, &PTK, + data, data_len) == 0) { + if (sm->PMK != pmk) { + os_memcpy(sm->PMK, pmk, pmk_len); + sm->pmk_len = pmk_len; + } + ok = 1; + break; + } + + if (!wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) || + wpa_key_mgmt_sae(sm->wpa_key_mgmt)) + break; + } + + if (!ok) { + wpa_printf(MSG_DEBUG, + "WPA: Earlier SNonce did not result in matching MIC"); + return -1; + } + + wpa_printf(MSG_DEBUG, + "WPA: Earlier SNonce resulted in matching MIC"); + sm->alt_snonce_valid = 0; + + if (vlan_id && wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) && + wpa_auth_update_vlan(sm->wpa_auth, sm->addr, vlan_id) < 0) + return -1; + + os_memcpy(sm->SNonce, sm->alt_SNonce, WPA_NONCE_LEN); + os_memcpy(&sm->PTK, &PTK, sizeof(PTK)); + forced_memzero(&PTK, sizeof(PTK)); + sm->PTK_valid = TRUE; + + return 0; +} + + +void wpa_receive(struct wpa_authenticator *wpa_auth, + struct wpa_state_machine *sm, + u8 *data, size_t data_len) +{ + struct ieee802_1x_hdr *hdr; + struct wpa_eapol_key *key; + u16 key_info, key_data_length; + enum { PAIRWISE_2, PAIRWISE_4, GROUP_2, REQUEST } msg; + char *msgtxt; + struct wpa_eapol_ie_parse kde; + const u8 *key_data; + size_t keyhdrlen, mic_len; + u8 *mic; + + if (wpa_auth == NULL || !wpa_auth->conf.wpa || sm == NULL) + return; + wpa_hexdump(MSG_MSGDUMP, "WPA: RX EAPOL data", data, data_len); + + mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len); + keyhdrlen = sizeof(*key) + mic_len + 2; + + if (data_len < sizeof(*hdr) + keyhdrlen) { + wpa_printf(MSG_DEBUG, "WPA: Ignore too short EAPOL-Key frame"); + return; + } + + hdr = (struct ieee802_1x_hdr *) data; + key = (struct wpa_eapol_key *) (hdr + 1); + mic = (u8 *) (key + 1); + key_info = WPA_GET_BE16(key->key_info); + key_data = mic + mic_len + 2; + key_data_length = WPA_GET_BE16(mic + mic_len); + wpa_printf(MSG_DEBUG, "WPA: Received EAPOL-Key from " MACSTR + " key_info=0x%x type=%u mic_len=%u key_data_length=%u", + MAC2STR(sm->addr), key_info, key->type, + (unsigned int) mic_len, key_data_length); + wpa_hexdump(MSG_MSGDUMP, + "WPA: EAPOL-Key header (ending before Key MIC)", + key, sizeof(*key)); + wpa_hexdump(MSG_MSGDUMP, "WPA: EAPOL-Key Key MIC", + mic, mic_len); + if (key_data_length > data_len - sizeof(*hdr) - keyhdrlen) { + wpa_printf(MSG_INFO, "WPA: Invalid EAPOL-Key frame - " + "key_data overflow (%d > %lu)", + key_data_length, + (unsigned long) (data_len - sizeof(*hdr) - + keyhdrlen)); + return; + } + + if (sm->wpa == WPA_VERSION_WPA2) { + if (key->type == EAPOL_KEY_TYPE_WPA) { + /* + * Some deployed station implementations seem to send + * msg 4/4 with incorrect type value in WPA2 mode. + */ + wpa_printf(MSG_DEBUG, "Workaround: Allow EAPOL-Key " + "with unexpected WPA type in RSN mode"); + } else if (key->type != EAPOL_KEY_TYPE_RSN) { + wpa_printf(MSG_DEBUG, "Ignore EAPOL-Key with " + "unexpected type %d in RSN mode", + key->type); + return; + } + } else { + if (key->type != EAPOL_KEY_TYPE_WPA) { + wpa_printf(MSG_DEBUG, "Ignore EAPOL-Key with " + "unexpected type %d in WPA mode", + key->type); + return; + } + } + + wpa_hexdump(MSG_DEBUG, "WPA: Received Key Nonce", key->key_nonce, + WPA_NONCE_LEN); + wpa_hexdump(MSG_DEBUG, "WPA: Received Replay Counter", + key->replay_counter, WPA_REPLAY_COUNTER_LEN); + + /* FIX: verify that the EAPOL-Key frame was encrypted if pairwise keys + * are set */ + + if (key_info & WPA_KEY_INFO_SMK_MESSAGE) { + wpa_printf(MSG_DEBUG, "WPA: Ignore SMK message"); + return; + } + + if (key_info & WPA_KEY_INFO_REQUEST) { + msg = REQUEST; + msgtxt = "Request"; + } else if (!(key_info & WPA_KEY_INFO_KEY_TYPE)) { + msg = GROUP_2; + msgtxt = "2/2 Group"; + } else if (key_data_length == 0 || + (mic_len == 0 && (key_info & WPA_KEY_INFO_ENCR_KEY_DATA) && + key_data_length == AES_BLOCK_SIZE)) { + msg = PAIRWISE_4; + msgtxt = "4/4 Pairwise"; + } else { + msg = PAIRWISE_2; + msgtxt = "2/4 Pairwise"; + } + + if (msg == REQUEST || msg == PAIRWISE_2 || msg == PAIRWISE_4 || + msg == GROUP_2) { + u16 ver = key_info & WPA_KEY_INFO_TYPE_MASK; + if (sm->pairwise == WPA_CIPHER_CCMP || + sm->pairwise == WPA_CIPHER_GCMP) { + if (wpa_use_cmac(sm->wpa_key_mgmt) && + !wpa_use_akm_defined(sm->wpa_key_mgmt) && + ver != WPA_KEY_INFO_TYPE_AES_128_CMAC) { + wpa_auth_logger(wpa_auth, sm->addr, + LOGGER_WARNING, + "advertised support for " + "AES-128-CMAC, but did not " + "use it"); + return; + } + + if (!wpa_use_cmac(sm->wpa_key_mgmt) && + !wpa_use_akm_defined(sm->wpa_key_mgmt) && + ver != WPA_KEY_INFO_TYPE_HMAC_SHA1_AES) { + wpa_auth_logger(wpa_auth, sm->addr, + LOGGER_WARNING, + "did not use HMAC-SHA1-AES " + "with CCMP/GCMP"); + return; + } + } + + if (wpa_use_akm_defined(sm->wpa_key_mgmt) && + ver != WPA_KEY_INFO_TYPE_AKM_DEFINED) { + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_WARNING, + "did not use EAPOL-Key descriptor version 0 as required for AKM-defined cases"); + return; + } + } + + if (key_info & WPA_KEY_INFO_REQUEST) { + if (sm->req_replay_counter_used && + os_memcmp(key->replay_counter, sm->req_replay_counter, + WPA_REPLAY_COUNTER_LEN) <= 0) { + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_WARNING, + "received EAPOL-Key request with " + "replayed counter"); + return; + } + } + + if (!(key_info & WPA_KEY_INFO_REQUEST) && + !wpa_replay_counter_valid(sm->key_replay, key->replay_counter)) { + int i; + + if (msg == PAIRWISE_2 && + wpa_replay_counter_valid(sm->prev_key_replay, + key->replay_counter) && + sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING && + os_memcmp(sm->SNonce, key->key_nonce, WPA_NONCE_LEN) != 0) + { + /* + * Some supplicant implementations (e.g., Windows XP + * WZC) update SNonce for each EAPOL-Key 2/4. This + * breaks the workaround on accepting any of the + * pending requests, so allow the SNonce to be updated + * even if we have already sent out EAPOL-Key 3/4. + */ + wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, + "Process SNonce update from STA " + "based on retransmitted EAPOL-Key " + "1/4"); + sm->update_snonce = 1; + os_memcpy(sm->alt_SNonce, sm->SNonce, WPA_NONCE_LEN); + sm->alt_snonce_valid = TRUE; + os_memcpy(sm->alt_replay_counter, + sm->key_replay[0].counter, + WPA_REPLAY_COUNTER_LEN); + goto continue_processing; + } + + if (msg == PAIRWISE_4 && sm->alt_snonce_valid && + sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING && + os_memcmp(key->replay_counter, sm->alt_replay_counter, + WPA_REPLAY_COUNTER_LEN) == 0) { + /* + * Supplicant may still be using the old SNonce since + * there was two EAPOL-Key 2/4 messages and they had + * different SNonce values. + */ + wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, + "Try to process received EAPOL-Key 4/4 based on old Replay Counter and SNonce from an earlier EAPOL-Key 1/4"); + goto continue_processing; + } + + if (msg == PAIRWISE_2 && + wpa_replay_counter_valid(sm->prev_key_replay, + key->replay_counter) && + sm->wpa_ptk_state == WPA_PTK_PTKINITNEGOTIATING) { + wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, + "ignore retransmitted EAPOL-Key %s - " + "SNonce did not change", msgtxt); + } else { + wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, + "received EAPOL-Key %s with " + "unexpected replay counter", msgtxt); + } + for (i = 0; i < RSNA_MAX_EAPOL_RETRIES; i++) { + if (!sm->key_replay[i].valid) + break; + wpa_hexdump(MSG_DEBUG, "pending replay counter", + sm->key_replay[i].counter, + WPA_REPLAY_COUNTER_LEN); + } + wpa_hexdump(MSG_DEBUG, "received replay counter", + key->replay_counter, WPA_REPLAY_COUNTER_LEN); + return; + } + +continue_processing: +#ifdef CONFIG_FILS + if (sm->wpa == WPA_VERSION_WPA2 && mic_len == 0 && + !(key_info & WPA_KEY_INFO_ENCR_KEY_DATA)) { + wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, + "WPA: Encr Key Data bit not set even though AEAD cipher is supposed to be used - drop frame"); + return; + } +#endif /* CONFIG_FILS */ + + switch (msg) { + case PAIRWISE_2: + if (sm->wpa_ptk_state != WPA_PTK_PTKSTART && + sm->wpa_ptk_state != WPA_PTK_PTKCALCNEGOTIATING && + (!sm->update_snonce || + sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING)) { + wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, + "received EAPOL-Key msg 2/4 in " + "invalid state (%d) - dropped", + sm->wpa_ptk_state); + return; + } + random_add_randomness(key->key_nonce, WPA_NONCE_LEN); + if (sm->group->reject_4way_hs_for_entropy) { + /* + * The system did not have enough entropy to generate + * strong random numbers. Reject the first 4-way + * handshake(s) and collect some entropy based on the + * information from it. Once enough entropy is + * available, the next atempt will trigger GMK/Key + * Counter update and the station will be allowed to + * continue. + */ + wpa_printf(MSG_DEBUG, "WPA: Reject 4-way handshake to " + "collect more entropy for random number " + "generation"); + random_mark_pool_ready(); + wpa_sta_disconnect(wpa_auth, sm->addr, + WLAN_REASON_PREV_AUTH_NOT_VALID); + return; + } + break; + case PAIRWISE_4: + if (sm->wpa_ptk_state != WPA_PTK_PTKINITNEGOTIATING || + !sm->PTK_valid) { + wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, + "received EAPOL-Key msg 4/4 in " + "invalid state (%d) - dropped", + sm->wpa_ptk_state); + return; + } + break; + case GROUP_2: + if (sm->wpa_ptk_group_state != WPA_PTK_GROUP_REKEYNEGOTIATING + || !sm->PTK_valid) { + wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, + "received EAPOL-Key msg 2/2 in " + "invalid state (%d) - dropped", + sm->wpa_ptk_group_state); + return; + } + break; + case REQUEST: + break; + } + + wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, + "received EAPOL-Key frame (%s)", msgtxt); + + if (key_info & WPA_KEY_INFO_ACK) { + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, + "received invalid EAPOL-Key: Key Ack set"); + return; + } + + if (!wpa_key_mgmt_fils(sm->wpa_key_mgmt) && + !(key_info & WPA_KEY_INFO_MIC)) { + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, + "received invalid EAPOL-Key: Key MIC not set"); + return; + } + +#ifdef CONFIG_FILS + if (wpa_key_mgmt_fils(sm->wpa_key_mgmt) && + (key_info & WPA_KEY_INFO_MIC)) { + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, + "received invalid EAPOL-Key: Key MIC set"); + return; + } +#endif /* CONFIG_FILS */ + + sm->MICVerified = FALSE; + if (sm->PTK_valid && !sm->update_snonce) { + if (mic_len && + wpa_verify_key_mic(sm->wpa_key_mgmt, sm->pmk_len, &sm->PTK, + data, data_len) && + (msg != PAIRWISE_4 || !sm->alt_snonce_valid || + wpa_try_alt_snonce(sm, data, data_len))) { + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, + "received EAPOL-Key with invalid MIC"); + return; + } +#ifdef CONFIG_FILS + if (!mic_len && + wpa_aead_decrypt(sm, &sm->PTK, data, data_len, + &key_data_length) < 0) { + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, + "received EAPOL-Key with invalid MIC"); + return; + } +#endif /* CONFIG_FILS */ + sm->MICVerified = TRUE; + eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm); + sm->pending_1_of_4_timeout = 0; + } + + if (key_info & WPA_KEY_INFO_REQUEST) { + if (sm->MICVerified) { + sm->req_replay_counter_used = 1; + os_memcpy(sm->req_replay_counter, key->replay_counter, + WPA_REPLAY_COUNTER_LEN); + } else { + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, + "received EAPOL-Key request with " + "invalid MIC"); + return; + } + + /* + * TODO: should decrypt key data field if encryption was used; + * even though MAC address KDE is not normally encrypted, + * supplicant is allowed to encrypt it. + */ + if (key_info & WPA_KEY_INFO_ERROR) { + if (wpa_receive_error_report( + wpa_auth, sm, + !(key_info & WPA_KEY_INFO_KEY_TYPE)) > 0) + return; /* STA entry was removed */ + } else if (key_info & WPA_KEY_INFO_KEY_TYPE) { + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, + "received EAPOL-Key Request for new " + "4-Way Handshake"); + wpa_request_new_ptk(sm); + } else if (key_data_length > 0 && + wpa_parse_kde_ies(key_data, key_data_length, + &kde) == 0 && + kde.mac_addr) { + } else { + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, + "received EAPOL-Key Request for GTK " + "rekeying"); + eloop_cancel_timeout(wpa_rekey_gtk, wpa_auth, NULL); + wpa_rekey_gtk(wpa_auth, NULL); + } + } else { + /* Do not allow the same key replay counter to be reused. */ + wpa_replay_counter_mark_invalid(sm->key_replay, + key->replay_counter); + + if (msg == PAIRWISE_2) { + /* + * Maintain a copy of the pending EAPOL-Key frames in + * case the EAPOL-Key frame was retransmitted. This is + * needed to allow EAPOL-Key msg 2/4 reply to another + * pending msg 1/4 to update the SNonce to work around + * unexpected supplicant behavior. + */ + os_memcpy(sm->prev_key_replay, sm->key_replay, + sizeof(sm->key_replay)); + } else { + os_memset(sm->prev_key_replay, 0, + sizeof(sm->prev_key_replay)); + } + + /* + * Make sure old valid counters are not accepted anymore and + * do not get copied again. + */ + wpa_replay_counter_mark_invalid(sm->key_replay, NULL); + } + + os_free(sm->last_rx_eapol_key); + sm->last_rx_eapol_key = os_memdup(data, data_len); + if (sm->last_rx_eapol_key == NULL) + return; + sm->last_rx_eapol_key_len = data_len; + + sm->rx_eapol_key_secure = !!(key_info & WPA_KEY_INFO_SECURE); + sm->EAPOLKeyReceived = TRUE; + sm->EAPOLKeyPairwise = !!(key_info & WPA_KEY_INFO_KEY_TYPE); + sm->EAPOLKeyRequest = !!(key_info & WPA_KEY_INFO_REQUEST); + os_memcpy(sm->SNonce, key->key_nonce, WPA_NONCE_LEN); + wpa_sm_step(sm); +} + + +static int wpa_gmk_to_gtk(const u8 *gmk, const char *label, const u8 *addr, + const u8 *gnonce, u8 *gtk, size_t gtk_len) +{ + u8 data[ETH_ALEN + WPA_NONCE_LEN + 8 + WPA_GTK_MAX_LEN]; + u8 *pos; + int ret = 0; + + /* GTK = PRF-X(GMK, "Group key expansion", + * AA || GNonce || Time || random data) + * The example described in the IEEE 802.11 standard uses only AA and + * GNonce as inputs here. Add some more entropy since this derivation + * is done only at the Authenticator and as such, does not need to be + * exactly same. + */ + os_memset(data, 0, sizeof(data)); + os_memcpy(data, addr, ETH_ALEN); + os_memcpy(data + ETH_ALEN, gnonce, WPA_NONCE_LEN); + pos = data + ETH_ALEN + WPA_NONCE_LEN; + wpa_get_ntp_timestamp(pos); + pos += 8; + if (random_get_bytes(pos, gtk_len) < 0) + ret = -1; + +#ifdef CONFIG_SHA384 + if (sha384_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data), + gtk, gtk_len) < 0) + ret = -1; +#else /* CONFIG_SHA384 */ +#ifdef CONFIG_SHA256 + if (sha256_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data), + gtk, gtk_len) < 0) + ret = -1; +#else /* CONFIG_SHA256 */ + if (sha1_prf(gmk, WPA_GMK_LEN, label, data, sizeof(data), + gtk, gtk_len) < 0) + ret = -1; +#endif /* CONFIG_SHA256 */ +#endif /* CONFIG_SHA384 */ + + forced_memzero(data, sizeof(data)); + + return ret; +} + + +static void wpa_send_eapol_timeout(void *eloop_ctx, void *timeout_ctx) +{ + struct wpa_authenticator *wpa_auth __maybe_unused = eloop_ctx; + struct wpa_state_machine *sm = timeout_ctx; + + sm->pending_1_of_4_timeout = 0; + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, "EAPOL-Key timeout"); + sm->TimeoutEvt = TRUE; + wpa_sm_step(sm); +} + + +void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, + struct wpa_state_machine *sm, int key_info, + const u8 *key_rsc, const u8 *nonce, + const u8 *kde, size_t kde_len, + int keyidx, int encr, int force_version) +{ + struct ieee802_1x_hdr *hdr; + struct wpa_eapol_key *key; + size_t len, mic_len, keyhdrlen; + int alg; + int key_data_len, pad_len = 0; + u8 *buf, *pos; + int version, pairwise; + int i; + u8 *key_mic, *key_data; + + mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len); + keyhdrlen = sizeof(*key) + mic_len + 2; + + len = sizeof(struct ieee802_1x_hdr) + keyhdrlen; + + if (force_version) + version = force_version; + else if (wpa_use_akm_defined(sm->wpa_key_mgmt)) + version = WPA_KEY_INFO_TYPE_AKM_DEFINED; + else if (wpa_use_cmac(sm->wpa_key_mgmt)) + version = WPA_KEY_INFO_TYPE_AES_128_CMAC; + else if (sm->pairwise != WPA_CIPHER_TKIP) + version = WPA_KEY_INFO_TYPE_HMAC_SHA1_AES; + else + version = WPA_KEY_INFO_TYPE_HMAC_MD5_RC4; + + pairwise = !!(key_info & WPA_KEY_INFO_KEY_TYPE); + + wpa_printf(MSG_DEBUG, "WPA: Send EAPOL(version=%d secure=%d mic=%d " + "ack=%d install=%d pairwise=%d kde_len=%lu keyidx=%d " + "encr=%d)", + version, + (key_info & WPA_KEY_INFO_SECURE) ? 1 : 0, + (key_info & WPA_KEY_INFO_MIC) ? 1 : 0, + (key_info & WPA_KEY_INFO_ACK) ? 1 : 0, + (key_info & WPA_KEY_INFO_INSTALL) ? 1 : 0, + pairwise, (unsigned long) kde_len, keyidx, encr); + + key_data_len = kde_len; + + if ((version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES || + wpa_use_aes_key_wrap(sm->wpa_key_mgmt) || + version == WPA_KEY_INFO_TYPE_AES_128_CMAC) && encr) { + pad_len = key_data_len % 8; + if (pad_len) + pad_len = 8 - pad_len; + key_data_len += pad_len + 8; + } + + len += key_data_len; + if (!mic_len && encr) + len += AES_BLOCK_SIZE; + + hdr = os_zalloc(len); + if (hdr == NULL) + return; + hdr->version = wpa_auth->conf.eapol_version; + hdr->type = IEEE802_1X_TYPE_EAPOL_KEY; + hdr->length = host_to_be16(len - sizeof(*hdr)); + key = (struct wpa_eapol_key *) (hdr + 1); + key_mic = (u8 *) (key + 1); + key_data = ((u8 *) (hdr + 1)) + keyhdrlen; + + key->type = sm->wpa == WPA_VERSION_WPA2 ? + EAPOL_KEY_TYPE_RSN : EAPOL_KEY_TYPE_WPA; + key_info |= version; + if (encr && sm->wpa == WPA_VERSION_WPA2) + key_info |= WPA_KEY_INFO_ENCR_KEY_DATA; + if (sm->wpa != WPA_VERSION_WPA2) + key_info |= keyidx << WPA_KEY_INFO_KEY_INDEX_SHIFT; + WPA_PUT_BE16(key->key_info, key_info); + + alg = pairwise ? sm->pairwise : wpa_auth->conf.wpa_group; + if (sm->wpa == WPA_VERSION_WPA2 && !pairwise) + WPA_PUT_BE16(key->key_length, 0); + else + WPA_PUT_BE16(key->key_length, wpa_cipher_key_len(alg)); + + for (i = RSNA_MAX_EAPOL_RETRIES - 1; i > 0; i--) { + sm->key_replay[i].valid = sm->key_replay[i - 1].valid; + os_memcpy(sm->key_replay[i].counter, + sm->key_replay[i - 1].counter, + WPA_REPLAY_COUNTER_LEN); + } + inc_byte_array(sm->key_replay[0].counter, WPA_REPLAY_COUNTER_LEN); + os_memcpy(key->replay_counter, sm->key_replay[0].counter, + WPA_REPLAY_COUNTER_LEN); + wpa_hexdump(MSG_DEBUG, "WPA: Replay Counter", + key->replay_counter, WPA_REPLAY_COUNTER_LEN); + sm->key_replay[0].valid = TRUE; + + if (nonce) + os_memcpy(key->key_nonce, nonce, WPA_NONCE_LEN); + + if (key_rsc) + os_memcpy(key->key_rsc, key_rsc, WPA_KEY_RSC_LEN); + + if (kde && !encr) { + os_memcpy(key_data, kde, kde_len); + WPA_PUT_BE16(key_mic + mic_len, kde_len); +#ifdef CONFIG_FILS + } else if (!mic_len && kde) { + const u8 *aad[1]; + size_t aad_len[1]; + + WPA_PUT_BE16(key_mic, AES_BLOCK_SIZE + kde_len); + wpa_hexdump_key(MSG_DEBUG, "Plaintext EAPOL-Key Key Data", + kde, kde_len); + + wpa_hexdump_key(MSG_DEBUG, "WPA: KEK", + sm->PTK.kek, sm->PTK.kek_len); + /* AES-SIV AAD from EAPOL protocol version field (inclusive) to + * to Key Data (exclusive). */ + aad[0] = (u8 *) hdr; + aad_len[0] = key_mic + 2 - (u8 *) hdr; + if (aes_siv_encrypt(sm->PTK.kek, sm->PTK.kek_len, kde, kde_len, + 1, aad, aad_len, key_mic + 2) < 0) { + wpa_printf(MSG_DEBUG, "WPA: AES-SIV encryption failed"); + return; + } + + wpa_hexdump(MSG_DEBUG, "WPA: Encrypted Key Data from SIV", + key_mic + 2, AES_BLOCK_SIZE + kde_len); +#endif /* CONFIG_FILS */ + } else if (encr && kde) { + buf = os_zalloc(key_data_len); + if (buf == NULL) { + os_free(hdr); + return; + } + pos = buf; + os_memcpy(pos, kde, kde_len); + pos += kde_len; + + if (pad_len) + *pos++ = 0xdd; + + wpa_hexdump_key(MSG_DEBUG, "Plaintext EAPOL-Key Key Data", + buf, key_data_len); + if (version == WPA_KEY_INFO_TYPE_HMAC_SHA1_AES || + wpa_use_aes_key_wrap(sm->wpa_key_mgmt) || + version == WPA_KEY_INFO_TYPE_AES_128_CMAC) { + wpa_printf(MSG_DEBUG, + "WPA: Encrypt Key Data using AES-WRAP (KEK length %u)", + (unsigned int) sm->PTK.kek_len); + if (aes_wrap(sm->PTK.kek, sm->PTK.kek_len, + (key_data_len - 8) / 8, buf, key_data)) { + os_free(hdr); + os_free(buf); + return; + } + WPA_PUT_BE16(key_mic + mic_len, key_data_len); +#ifndef CONFIG_NO_RC4 + } else if (sm->PTK.kek_len == 16) { + u8 ek[32]; + + wpa_printf(MSG_DEBUG, + "WPA: Encrypt Key Data using RC4"); + os_memcpy(key->key_iv, + sm->group->Counter + WPA_NONCE_LEN - 16, 16); + inc_byte_array(sm->group->Counter, WPA_NONCE_LEN); + os_memcpy(ek, key->key_iv, 16); + os_memcpy(ek + 16, sm->PTK.kek, sm->PTK.kek_len); + os_memcpy(key_data, buf, key_data_len); + rc4_skip(ek, 32, 256, key_data, key_data_len); + WPA_PUT_BE16(key_mic + mic_len, key_data_len); +#endif /* CONFIG_NO_RC4 */ + } else { + os_free(hdr); + os_free(buf); + return; + } + os_free(buf); + } + + if (key_info & WPA_KEY_INFO_MIC) { + if (!sm->PTK_valid || !mic_len) { + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, + "PTK not valid when sending EAPOL-Key " + "frame"); + os_free(hdr); + return; + } + + if (wpa_eapol_key_mic(sm->PTK.kck, sm->PTK.kck_len, + sm->wpa_key_mgmt, version, + (u8 *) hdr, len, key_mic) < 0) { + os_free(hdr); + return; + } + } + + wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_inc_EapolFramesTx, + 1); + wpa_auth_send_eapol(wpa_auth, sm->addr, (u8 *) hdr, len, + sm->pairwise_set); + os_free(hdr); +} + + +static void wpa_send_eapol(struct wpa_authenticator *wpa_auth, + struct wpa_state_machine *sm, int key_info, + const u8 *key_rsc, const u8 *nonce, + const u8 *kde, size_t kde_len, + int keyidx, int encr) +{ + int timeout_ms; + int pairwise = key_info & WPA_KEY_INFO_KEY_TYPE; + u32 ctr; + + if (sm == NULL) + return; + + __wpa_send_eapol(wpa_auth, sm, key_info, key_rsc, nonce, kde, kde_len, + keyidx, encr, 0); + + ctr = pairwise ? sm->TimeoutCtr : sm->GTimeoutCtr; + if (ctr == 1 && wpa_auth->conf.tx_status) + timeout_ms = pairwise ? eapol_key_timeout_first : + eapol_key_timeout_first_group; + else + timeout_ms = eapol_key_timeout_subseq; + if (wpa_auth->conf.wpa_disable_eapol_key_retries && + (!pairwise || (key_info & WPA_KEY_INFO_MIC))) + timeout_ms = eapol_key_timeout_no_retrans; + if (pairwise && ctr == 1 && !(key_info & WPA_KEY_INFO_MIC)) + sm->pending_1_of_4_timeout = 1; + wpa_printf(MSG_DEBUG, "WPA: Use EAPOL-Key timeout of %u ms (retry " + "counter %u)", timeout_ms, ctr); + eloop_register_timeout(timeout_ms / 1000, (timeout_ms % 1000) * 1000, + wpa_send_eapol_timeout, wpa_auth, sm); +} + + +static int wpa_verify_key_mic(int akmp, size_t pmk_len, struct wpa_ptk *PTK, + u8 *data, size_t data_len) +{ + struct ieee802_1x_hdr *hdr; + struct wpa_eapol_key *key; + u16 key_info; + int ret = 0; + u8 mic[WPA_EAPOL_KEY_MIC_MAX_LEN], *mic_pos; + size_t mic_len = wpa_mic_len(akmp, pmk_len); + + if (data_len < sizeof(*hdr) + sizeof(*key)) + return -1; + + hdr = (struct ieee802_1x_hdr *) data; + key = (struct wpa_eapol_key *) (hdr + 1); + mic_pos = (u8 *) (key + 1); + key_info = WPA_GET_BE16(key->key_info); + os_memcpy(mic, mic_pos, mic_len); + os_memset(mic_pos, 0, mic_len); + if (wpa_eapol_key_mic(PTK->kck, PTK->kck_len, akmp, + key_info & WPA_KEY_INFO_TYPE_MASK, + data, data_len, mic_pos) || + os_memcmp_const(mic, mic_pos, mic_len) != 0) + ret = -1; + os_memcpy(mic_pos, mic, mic_len); + return ret; +} + + +void wpa_remove_ptk(struct wpa_state_machine *sm) +{ + sm->PTK_valid = FALSE; + os_memset(&sm->PTK, 0, sizeof(sm->PTK)); + if (wpa_auth_set_key(sm->wpa_auth, 0, WPA_ALG_NONE, sm->addr, 0, NULL, + 0)) + wpa_printf(MSG_DEBUG, + "RSN: PTK removal from the driver failed"); + sm->pairwise_set = FALSE; + eloop_cancel_timeout(wpa_rekey_ptk, sm->wpa_auth, sm); +} + + +int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event) +{ + int remove_ptk = 1; + + if (sm == NULL) + return -1; + + wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, + "event %d notification", event); + + switch (event) { + case WPA_AUTH: +#ifdef CONFIG_MESH + /* PTKs are derived through AMPE */ + if (wpa_auth_start_ampe(sm->wpa_auth, sm->addr)) { + /* not mesh */ + break; + } + return 0; +#endif /* CONFIG_MESH */ + case WPA_ASSOC: + break; + case WPA_DEAUTH: + case WPA_DISASSOC: + sm->DeauthenticationRequest = TRUE; +#ifdef CONFIG_IEEE80211R_AP + os_memset(sm->PMK, 0, sizeof(sm->PMK)); + sm->pmk_len = 0; + os_memset(sm->xxkey, 0, sizeof(sm->xxkey)); + sm->xxkey_len = 0; + os_memset(sm->pmk_r1, 0, sizeof(sm->pmk_r1)); + sm->pmk_r1_len = 0; +#endif /* CONFIG_IEEE80211R_AP */ + break; + case WPA_REAUTH: + case WPA_REAUTH_EAPOL: + if (!sm->started) { + /* + * When using WPS, we may end up here if the STA + * manages to re-associate without the previous STA + * entry getting removed. Consequently, we need to make + * sure that the WPA state machines gets initialized + * properly at this point. + */ + wpa_printf(MSG_DEBUG, "WPA state machine had not been " + "started - initialize now"); + sm->started = 1; + sm->Init = TRUE; + if (wpa_sm_step(sm) == 1) + return 1; /* should not really happen */ + sm->Init = FALSE; + sm->AuthenticationRequest = TRUE; + break; + } + if (sm->GUpdateStationKeys) { + /* + * Reauthentication cancels the pending group key + * update for this STA. + */ + sm->group->GKeyDoneStations--; + sm->GUpdateStationKeys = FALSE; + sm->PtkGroupInit = TRUE; + } + sm->ReAuthenticationRequest = TRUE; + break; + case WPA_ASSOC_FT: +#ifdef CONFIG_IEEE80211R_AP + wpa_printf(MSG_DEBUG, "FT: Retry PTK configuration " + "after association"); + wpa_ft_install_ptk(sm); + + /* Using FT protocol, not WPA auth state machine */ + sm->ft_completed = 1; + wpa_auth_set_ptk_rekey_timer(sm); + return 0; +#else /* CONFIG_IEEE80211R_AP */ + break; +#endif /* CONFIG_IEEE80211R_AP */ + case WPA_ASSOC_FILS: +#ifdef CONFIG_FILS + wpa_printf(MSG_DEBUG, + "FILS: TK configuration after association"); + fils_set_tk(sm); + sm->fils_completed = 1; + return 0; +#else /* CONFIG_FILS */ + break; +#endif /* CONFIG_FILS */ + case WPA_DRV_STA_REMOVED: + sm->tk_already_set = FALSE; + return 0; + } + +#ifdef CONFIG_IEEE80211R_AP + sm->ft_completed = 0; +#endif /* CONFIG_IEEE80211R_AP */ + +#ifdef CONFIG_IEEE80211W_AP + if (sm->mgmt_frame_prot && event == WPA_AUTH) + remove_ptk = 0; +#endif /* CONFIG_IEEE80211W_AP */ +#ifdef CONFIG_FILS + if (wpa_key_mgmt_fils(sm->wpa_key_mgmt) && + (event == WPA_AUTH || event == WPA_ASSOC)) + remove_ptk = 0; +#endif /* CONFIG_FILS */ + + if (remove_ptk) { + sm->PTK_valid = FALSE; + os_memset(&sm->PTK, 0, sizeof(sm->PTK)); + + if (event != WPA_REAUTH_EAPOL) + wpa_remove_ptk(sm); + } + + if (sm->in_step_loop) { + /* + * wpa_sm_step() is already running - avoid recursive call to + * it by making the existing loop process the new update. + */ + sm->changed = TRUE; + return 0; + } + return wpa_sm_step(sm); +} + + +SM_STATE(WPA_PTK, INITIALIZE) +{ + SM_ENTRY_MA(WPA_PTK, INITIALIZE, wpa_ptk); + if (sm->Init) { + /* Init flag is not cleared here, so avoid busy + * loop by claiming nothing changed. */ + sm->changed = FALSE; + } + + sm->keycount = 0; + if (sm->GUpdateStationKeys) + sm->group->GKeyDoneStations--; + sm->GUpdateStationKeys = FALSE; + if (sm->wpa == WPA_VERSION_WPA) + sm->PInitAKeys = FALSE; + if (1 /* Unicast cipher supported AND (ESS OR ((IBSS or WDS) and + * Local AA > Remote AA)) */) { + sm->Pair = TRUE; + } + wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portEnabled, 0); + wpa_remove_ptk(sm); + wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portValid, 0); + sm->TimeoutCtr = 0; + if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) || + sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP || + sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE) { + wpa_auth_set_eapol(sm->wpa_auth, sm->addr, + WPA_EAPOL_authorized, 0); + } +} + + +SM_STATE(WPA_PTK, DISCONNECT) +{ + u16 reason = sm->disconnect_reason; + + SM_ENTRY_MA(WPA_PTK, DISCONNECT, wpa_ptk); + sm->Disconnect = FALSE; + sm->disconnect_reason = 0; + if (!reason) + reason = WLAN_REASON_PREV_AUTH_NOT_VALID; + wpa_sta_disconnect(sm->wpa_auth, sm->addr, reason); +} + + +SM_STATE(WPA_PTK, DISCONNECTED) +{ + SM_ENTRY_MA(WPA_PTK, DISCONNECTED, wpa_ptk); + sm->DeauthenticationRequest = FALSE; +} + + +SM_STATE(WPA_PTK, AUTHENTICATION) +{ + SM_ENTRY_MA(WPA_PTK, AUTHENTICATION, wpa_ptk); + os_memset(&sm->PTK, 0, sizeof(sm->PTK)); + sm->PTK_valid = FALSE; + wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portControl_Auto, + 1); + wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portEnabled, 1); + sm->AuthenticationRequest = FALSE; +} + + +static void wpa_group_ensure_init(struct wpa_authenticator *wpa_auth, + struct wpa_group *group) +{ + if (group->first_sta_seen) + return; + /* + * System has run bit further than at the time hostapd was started + * potentially very early during boot up. This provides better chances + * of collecting more randomness on embedded systems. Re-initialize the + * GMK and Counter here to improve their strength if there was not + * enough entropy available immediately after system startup. + */ + wpa_printf(MSG_DEBUG, "WPA: Re-initialize GMK/Counter on first " + "station"); + if (random_pool_ready() != 1) { + wpa_printf(MSG_INFO, "WPA: Not enough entropy in random pool " + "to proceed - reject first 4-way handshake"); + group->reject_4way_hs_for_entropy = TRUE; + } else { + group->first_sta_seen = TRUE; + group->reject_4way_hs_for_entropy = FALSE; + } + + if (wpa_group_init_gmk_and_counter(wpa_auth, group) < 0 || + wpa_gtk_update(wpa_auth, group) < 0 || + wpa_group_config_group_keys(wpa_auth, group) < 0) { + wpa_printf(MSG_INFO, "WPA: GMK/GTK setup failed"); + group->first_sta_seen = FALSE; + group->reject_4way_hs_for_entropy = TRUE; + } +} + + +SM_STATE(WPA_PTK, AUTHENTICATION2) +{ + SM_ENTRY_MA(WPA_PTK, AUTHENTICATION2, wpa_ptk); + + wpa_group_ensure_init(sm->wpa_auth, sm->group); + sm->ReAuthenticationRequest = FALSE; + + /* + * Definition of ANonce selection in IEEE Std 802.11i-2004 is somewhat + * ambiguous. The Authenticator state machine uses a counter that is + * incremented by one for each 4-way handshake. However, the security + * analysis of 4-way handshake points out that unpredictable nonces + * help in preventing precomputation attacks. Instead of the state + * machine definition, use an unpredictable nonce value here to provide + * stronger protection against potential precomputation attacks. + */ + if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) { + wpa_printf(MSG_ERROR, "WPA: Failed to get random data for " + "ANonce."); + sm->Disconnect = TRUE; + return; + } + wpa_hexdump(MSG_DEBUG, "WPA: Assign ANonce", sm->ANonce, + WPA_NONCE_LEN); + /* IEEE 802.11i does not clear TimeoutCtr here, but this is more + * logical place than INITIALIZE since AUTHENTICATION2 can be + * re-entered on ReAuthenticationRequest without going through + * INITIALIZE. */ + sm->TimeoutCtr = 0; +} + + +static int wpa_auth_sm_ptk_update(struct wpa_state_machine *sm) +{ + if (random_get_bytes(sm->ANonce, WPA_NONCE_LEN)) { + wpa_printf(MSG_ERROR, + "WPA: Failed to get random data for ANonce"); + sm->Disconnect = TRUE; + return -1; + } + wpa_hexdump(MSG_DEBUG, "WPA: Assign new ANonce", sm->ANonce, + WPA_NONCE_LEN); + sm->TimeoutCtr = 0; + return 0; +} + + +SM_STATE(WPA_PTK, INITPMK) +{ + u8 msk[2 * PMK_LEN]; + size_t len = 2 * PMK_LEN; + + SM_ENTRY_MA(WPA_PTK, INITPMK, wpa_ptk); +#ifdef CONFIG_IEEE80211R_AP + sm->xxkey_len = 0; +#endif /* CONFIG_IEEE80211R_AP */ + if (sm->pmksa) { + wpa_printf(MSG_DEBUG, "WPA: PMK from PMKSA cache"); + os_memcpy(sm->PMK, sm->pmksa->pmk, sm->pmksa->pmk_len); + sm->pmk_len = sm->pmksa->pmk_len; +#ifdef CONFIG_DPP + } else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP) { + wpa_printf(MSG_DEBUG, + "DPP: No PMKSA cache entry for STA - reject connection"); + sm->Disconnect = TRUE; + sm->disconnect_reason = WLAN_REASON_INVALID_PMKID; + return; +#endif /* CONFIG_DPP */ + } else if (wpa_auth_get_msk(sm->wpa_auth, sm->addr, msk, &len) == 0) { + unsigned int pmk_len; + + if (wpa_key_mgmt_sha384(sm->wpa_key_mgmt)) + pmk_len = PMK_LEN_SUITE_B_192; + else + pmk_len = PMK_LEN; + wpa_printf(MSG_DEBUG, "WPA: PMK from EAPOL state machine " + "(MSK len=%lu PMK len=%u)", (unsigned long) len, + pmk_len); + if (len < pmk_len) { + wpa_printf(MSG_DEBUG, + "WPA: MSK not long enough (%u) to create PMK (%u)", + (unsigned int) len, (unsigned int) pmk_len); + sm->Disconnect = TRUE; + return; + } + os_memcpy(sm->PMK, msk, pmk_len); + sm->pmk_len = pmk_len; +#ifdef CONFIG_IEEE80211R_AP + if (len >= 2 * PMK_LEN) { + if (wpa_key_mgmt_sha384(sm->wpa_key_mgmt)) { + os_memcpy(sm->xxkey, msk, SHA384_MAC_LEN); + sm->xxkey_len = SHA384_MAC_LEN; + } else { + os_memcpy(sm->xxkey, msk + PMK_LEN, PMK_LEN); + sm->xxkey_len = PMK_LEN; + } + } +#endif /* CONFIG_IEEE80211R_AP */ + } else { + wpa_printf(MSG_DEBUG, "WPA: Could not get PMK, get_msk: %p", + sm->wpa_auth->cb->get_msk); + sm->Disconnect = TRUE; + return; + } + forced_memzero(msk, sizeof(msk)); + + sm->req_replay_counter_used = 0; + /* IEEE 802.11i does not set keyRun to FALSE, but not doing this + * will break reauthentication since EAPOL state machines may not be + * get into AUTHENTICATING state that clears keyRun before WPA state + * machine enters AUTHENTICATION2 state and goes immediately to INITPMK + * state and takes PMK from the previously used AAA Key. This will + * eventually fail in 4-Way Handshake because Supplicant uses PMK + * derived from the new AAA Key. Setting keyRun = FALSE here seems to + * be good workaround for this issue. */ + wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyRun, 0); +} + + +SM_STATE(WPA_PTK, INITPSK) +{ + const u8 *psk; + size_t psk_len; + + SM_ENTRY_MA(WPA_PTK, INITPSK, wpa_ptk); + psk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, sm->p2p_dev_addr, NULL, + &psk_len, NULL); + if (psk) { + os_memcpy(sm->PMK, psk, psk_len); + sm->pmk_len = psk_len; +#ifdef CONFIG_IEEE80211R_AP + os_memcpy(sm->xxkey, psk, PMK_LEN); + sm->xxkey_len = PMK_LEN; +#endif /* CONFIG_IEEE80211R_AP */ + } +#ifdef CONFIG_SAE_AP + if (wpa_auth_uses_sae(sm) && sm->pmksa) { + wpa_printf(MSG_DEBUG, "SAE: PMK from PMKSA cache"); + os_memcpy(sm->PMK, sm->pmksa->pmk, sm->pmksa->pmk_len); + sm->pmk_len = sm->pmksa->pmk_len; +#ifdef CONFIG_IEEE80211R_AP + os_memcpy(sm->xxkey, sm->pmksa->pmk, sm->pmksa->pmk_len); + sm->xxkey_len = sm->pmksa->pmk_len; +#endif /* CONFIG_IEEE80211R_AP */ + } +#endif /* CONFIG_SAE_AP */ + sm->req_replay_counter_used = 0; +} + + +SM_STATE(WPA_PTK, PTKSTART) +{ + u8 buf[2 + RSN_SELECTOR_LEN + PMKID_LEN], *pmkid = NULL; + size_t pmkid_len = 0; + + SM_ENTRY_MA(WPA_PTK, PTKSTART, wpa_ptk); + sm->PTKRequest = FALSE; + sm->TimeoutEvt = FALSE; + sm->alt_snonce_valid = FALSE; + + sm->TimeoutCtr++; + if (sm->TimeoutCtr > sm->wpa_auth->conf.wpa_pairwise_update_count) { + /* No point in sending the EAPOL-Key - we will disconnect + * immediately following this. */ + return; + } + + wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, + "sending 1/4 msg of 4-Way Handshake"); + /* + * For infrastructure BSS cases, it is better for the AP not to include + * the PMKID KDE in EAPOL-Key msg 1/4 since it could be used to initiate + * offline search for the passphrase/PSK without having to be able to + * capture a 4-way handshake from a STA that has access to the network. + * + * For IBSS cases, addition of PMKID KDE could be considered even with + * WPA2-PSK cases that use multiple PSKs, but only if there is a single + * possible PSK for this STA. However, this should not be done unless + * there is support for using that information on the supplicant side. + * The concern about exposing PMKID unnecessarily in infrastructure BSS + * cases would also apply here, but at least in the IBSS case, this + * would cover a potential real use case. + */ + if (sm->wpa == WPA_VERSION_WPA2 && + (wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) || + (sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE && sm->pmksa) || + wpa_key_mgmt_sae(sm->wpa_key_mgmt)) && + sm->wpa_key_mgmt != WPA_KEY_MGMT_OSEN) { + pmkid = buf; + pmkid_len = 2 + RSN_SELECTOR_LEN + PMKID_LEN; + pmkid[0] = WLAN_EID_VENDOR_SPECIFIC; + pmkid[1] = RSN_SELECTOR_LEN + PMKID_LEN; + RSN_SELECTOR_PUT(&pmkid[2], RSN_KEY_DATA_PMKID); + if (sm->pmksa) { + wpa_hexdump(MSG_DEBUG, + "RSN: Message 1/4 PMKID from PMKSA entry", + sm->pmksa->pmkid, PMKID_LEN); + os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN], + sm->pmksa->pmkid, PMKID_LEN); + } else if (wpa_key_mgmt_suite_b(sm->wpa_key_mgmt)) { + /* No KCK available to derive PMKID */ + wpa_printf(MSG_DEBUG, + "RSN: No KCK available to derive PMKID for message 1/4"); + pmkid = NULL; +#ifdef CONFIG_FILS + } else if (wpa_key_mgmt_fils(sm->wpa_key_mgmt)) { + if (sm->pmkid_set) { + wpa_hexdump(MSG_DEBUG, + "RSN: Message 1/4 PMKID from FILS/ERP", + sm->pmkid, PMKID_LEN); + os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN], + sm->pmkid, PMKID_LEN); + } else { + /* No PMKID available */ + wpa_printf(MSG_DEBUG, + "RSN: No FILS/ERP PMKID available for message 1/4"); + pmkid = NULL; + } +#endif /* CONFIG_FILS */ +#ifdef CONFIG_IEEE80211R_AP + } else if (wpa_key_mgmt_ft(sm->wpa_key_mgmt) && + sm->ft_completed) { + wpa_printf(MSG_DEBUG, + "FT: No PMKID in message 1/4 when using FT protocol"); + pmkid = NULL; + pmkid_len = 0; +#endif /* CONFIG_IEEE80211R_AP */ +#ifdef CONFIG_SAE_AP + } else if (wpa_key_mgmt_sae(sm->wpa_key_mgmt)) { + if (sm->pmkid_set) { + wpa_hexdump(MSG_DEBUG, + "RSN: Message 1/4 PMKID from SAE", + sm->pmkid, PMKID_LEN); + os_memcpy(&pmkid[2 + RSN_SELECTOR_LEN], + sm->pmkid, PMKID_LEN); + } else { + /* No PMKID available */ + wpa_printf(MSG_DEBUG, + "RSN: No SAE PMKID available for message 1/4"); + pmkid = NULL; + } +#endif /* CONFIG_SAE_AP */ + } else { + /* + * Calculate PMKID since no PMKSA cache entry was + * available with pre-calculated PMKID. + */ + rsn_pmkid(sm->PMK, sm->pmk_len, sm->wpa_auth->addr, + sm->addr, &pmkid[2 + RSN_SELECTOR_LEN], + sm->wpa_key_mgmt); + wpa_hexdump(MSG_DEBUG, + "RSN: Message 1/4 PMKID derived from PMK", + &pmkid[2 + RSN_SELECTOR_LEN], PMKID_LEN); + } + } + wpa_send_eapol(sm->wpa_auth, sm, + WPA_KEY_INFO_ACK | WPA_KEY_INFO_KEY_TYPE, NULL, + sm->ANonce, pmkid, pmkid_len, 0, 0); +} + + +static int wpa_derive_ptk(struct wpa_state_machine *sm, const u8 *snonce, + const u8 *pmk, unsigned int pmk_len, + struct wpa_ptk *ptk) +{ + const u8 *z = NULL; + size_t z_len = 0; + +#ifdef CONFIG_IEEE80211R_AP + if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { + if (sm->ft_completed) { + u8 ptk_name[WPA_PMK_NAME_LEN]; + + return wpa_pmk_r1_to_ptk(sm->pmk_r1, sm->pmk_r1_len, + sm->SNonce, sm->ANonce, + sm->addr, sm->wpa_auth->addr, + sm->pmk_r1_name, + ptk, ptk_name, + sm->wpa_key_mgmt, + sm->pairwise); + } + return wpa_auth_derive_ptk_ft(sm, ptk); + } +#endif /* CONFIG_IEEE80211R_AP */ + +#ifdef CONFIG_DPP2 + if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP && sm->dpp_z) { + z = wpabuf_head(sm->dpp_z); + z_len = wpabuf_len(sm->dpp_z); + } +#endif /* CONFIG_DPP2 */ + + return wpa_pmk_to_ptk(pmk, pmk_len, "Pairwise key expansion", + sm->wpa_auth->addr, sm->addr, sm->ANonce, snonce, + ptk, sm->wpa_key_mgmt, sm->pairwise, z, z_len); +} + + +#ifdef CONFIG_FILS + +int fils_auth_pmk_to_ptk(struct wpa_state_machine *sm, const u8 *pmk, + size_t pmk_len, const u8 *snonce, const u8 *anonce, + const u8 *dhss, size_t dhss_len, + struct wpabuf *g_sta, struct wpabuf *g_ap) +{ + u8 ick[FILS_ICK_MAX_LEN]; + size_t ick_len; + int res; + u8 fils_ft[FILS_FT_MAX_LEN]; + size_t fils_ft_len = 0; + + res = fils_pmk_to_ptk(pmk, pmk_len, sm->addr, sm->wpa_auth->addr, + snonce, anonce, dhss, dhss_len, + &sm->PTK, ick, &ick_len, + sm->wpa_key_mgmt, sm->pairwise, + fils_ft, &fils_ft_len); + if (res < 0) + return res; + sm->PTK_valid = TRUE; + sm->tk_already_set = FALSE; + +#ifdef CONFIG_IEEE80211R_AP + if (fils_ft_len) { + struct wpa_authenticator *wpa_auth = sm->wpa_auth; + struct wpa_auth_config *conf = &wpa_auth->conf; + u8 pmk_r0[PMK_LEN_MAX], pmk_r0_name[WPA_PMK_NAME_LEN]; + int use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt); + size_t pmk_r0_len = use_sha384 ? SHA384_MAC_LEN : PMK_LEN; + + if (wpa_derive_pmk_r0(fils_ft, fils_ft_len, + conf->ssid, conf->ssid_len, + conf->mobility_domain, + conf->r0_key_holder, + conf->r0_key_holder_len, + sm->addr, pmk_r0, pmk_r0_name, + use_sha384) < 0) + return -1; + + wpa_hexdump_key(MSG_DEBUG, "FILS+FT: PMK-R0", + pmk_r0, pmk_r0_len); + wpa_hexdump(MSG_DEBUG, "FILS+FT: PMKR0Name", + pmk_r0_name, WPA_PMK_NAME_LEN); + wpa_ft_store_pmk_fils(sm, pmk_r0, pmk_r0_name); + forced_memzero(fils_ft, sizeof(fils_ft)); + + res = wpa_derive_pmk_r1_name(pmk_r0_name, conf->r1_key_holder, + sm->addr, sm->pmk_r1_name, + use_sha384); + forced_memzero(pmk_r0, PMK_LEN_MAX); + if (res < 0) + return -1; + wpa_hexdump(MSG_DEBUG, "FILS+FT: PMKR1Name", sm->pmk_r1_name, + WPA_PMK_NAME_LEN); + sm->pmk_r1_name_valid = 1; + } +#endif /* CONFIG_IEEE80211R_AP */ + + res = fils_key_auth_sk(ick, ick_len, snonce, anonce, + sm->addr, sm->wpa_auth->addr, + g_sta ? wpabuf_head(g_sta) : NULL, + g_sta ? wpabuf_len(g_sta) : 0, + g_ap ? wpabuf_head(g_ap) : NULL, + g_ap ? wpabuf_len(g_ap) : 0, + sm->wpa_key_mgmt, sm->fils_key_auth_sta, + sm->fils_key_auth_ap, + &sm->fils_key_auth_len); + forced_memzero(ick, sizeof(ick)); + + /* Store nonces for (Re)Association Request/Response frame processing */ + os_memcpy(sm->SNonce, snonce, FILS_NONCE_LEN); + os_memcpy(sm->ANonce, anonce, FILS_NONCE_LEN); + + return res; +} + + +static int wpa_aead_decrypt(struct wpa_state_machine *sm, struct wpa_ptk *ptk, + u8 *buf, size_t buf_len, u16 *_key_data_len) +{ + struct ieee802_1x_hdr *hdr; + struct wpa_eapol_key *key; + u8 *pos; + u16 key_data_len; + u8 *tmp; + const u8 *aad[1]; + size_t aad_len[1]; + + hdr = (struct ieee802_1x_hdr *) buf; + key = (struct wpa_eapol_key *) (hdr + 1); + pos = (u8 *) (key + 1); + key_data_len = WPA_GET_BE16(pos); + if (key_data_len < AES_BLOCK_SIZE || + key_data_len > buf_len - sizeof(*hdr) - sizeof(*key) - 2) { + wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO, + "No room for AES-SIV data in the frame"); + return -1; + } + pos += 2; /* Pointing at the Encrypted Key Data field */ + + tmp = os_malloc(key_data_len); + if (!tmp) + return -1; + + /* AES-SIV AAD from EAPOL protocol version field (inclusive) to + * to Key Data (exclusive). */ + aad[0] = buf; + aad_len[0] = pos - buf; + if (aes_siv_decrypt(ptk->kek, ptk->kek_len, pos, key_data_len, + 1, aad, aad_len, tmp) < 0) { + wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO, + "Invalid AES-SIV data in the frame"); + bin_clear_free(tmp, key_data_len); + return -1; + } + + /* AEAD decryption and validation completed successfully */ + key_data_len -= AES_BLOCK_SIZE; + wpa_hexdump_key(MSG_DEBUG, "WPA: Decrypted Key Data", + tmp, key_data_len); + + /* Replace Key Data field with the decrypted version */ + os_memcpy(pos, tmp, key_data_len); + pos -= 2; /* Key Data Length field */ + WPA_PUT_BE16(pos, key_data_len); + bin_clear_free(tmp, key_data_len); + if (_key_data_len) + *_key_data_len = key_data_len; + return 0; +} + + +const u8 * wpa_fils_validate_fils_session(struct wpa_state_machine *sm, + const u8 *ies, size_t ies_len, + const u8 *fils_session) +{ + const u8 *ie, *end; + const u8 *session = NULL; + + if (!wpa_key_mgmt_fils(sm->wpa_key_mgmt)) { + wpa_printf(MSG_DEBUG, + "FILS: Not a FILS AKM - reject association"); + return NULL; + } + + /* Verify Session element */ + ie = ies; + end = ((const u8 *) ie) + ies_len; + while (ie + 1 < end) { + if (ie + 2 + ie[1] > end) + break; + if (ie[0] == WLAN_EID_EXTENSION && + ie[1] >= 1 + FILS_SESSION_LEN && + ie[2] == WLAN_EID_EXT_FILS_SESSION) { + session = ie; + break; + } + ie += 2 + ie[1]; + } + + if (!session) { + wpa_printf(MSG_DEBUG, + "FILS: %s: Could not find FILS Session element in Assoc Req - reject", + __func__); + return NULL; + } + + if (!fils_session) { + wpa_printf(MSG_DEBUG, + "FILS: %s: Could not find FILS Session element in STA entry - reject", + __func__); + return NULL; + } + + if (os_memcmp(fils_session, session + 3, FILS_SESSION_LEN) != 0) { + wpa_printf(MSG_DEBUG, "FILS: Session mismatch"); + wpa_hexdump(MSG_DEBUG, "FILS: Expected FILS Session", + fils_session, FILS_SESSION_LEN); + wpa_hexdump(MSG_DEBUG, "FILS: Received FILS Session", + session + 3, FILS_SESSION_LEN); + return NULL; + } + return session; +} + + +int wpa_fils_validate_key_confirm(struct wpa_state_machine *sm, const u8 *ies, + size_t ies_len) +{ + struct ieee802_11_elems elems; + + if (ieee802_11_parse_elems(ies, ies_len, &elems, 1) == ParseFailed) { + wpa_printf(MSG_DEBUG, + "FILS: Failed to parse decrypted elements"); + return -1; + } + + if (!elems.fils_session) { + wpa_printf(MSG_DEBUG, "FILS: No FILS Session element"); + return -1; + } + + if (!elems.fils_key_confirm) { + wpa_printf(MSG_DEBUG, "FILS: No FILS Key Confirm element"); + return -1; + } + + if (elems.fils_key_confirm_len != sm->fils_key_auth_len) { + wpa_printf(MSG_DEBUG, + "FILS: Unexpected Key-Auth length %d (expected %d)", + elems.fils_key_confirm_len, + (int) sm->fils_key_auth_len); + return -1; + } + + if (os_memcmp(elems.fils_key_confirm, sm->fils_key_auth_sta, + sm->fils_key_auth_len) != 0) { + wpa_printf(MSG_DEBUG, "FILS: Key-Auth mismatch"); + wpa_hexdump(MSG_DEBUG, "FILS: Received Key-Auth", + elems.fils_key_confirm, elems.fils_key_confirm_len); + wpa_hexdump(MSG_DEBUG, "FILS: Expected Key-Auth", + sm->fils_key_auth_sta, sm->fils_key_auth_len); + return -1; + } + + return 0; +} + + +int fils_decrypt_assoc(struct wpa_state_machine *sm, const u8 *fils_session, + const struct ieee80211_mgmt *mgmt, size_t frame_len, + u8 *pos, size_t left) +{ + u16 fc, stype; + const u8 *end, *ie_start, *ie, *session, *crypt; + const u8 *aad[5]; + size_t aad_len[5]; + + if (!sm || !sm->PTK_valid) { + wpa_printf(MSG_DEBUG, + "FILS: No KEK to decrypt Assocication Request frame"); + return -1; + } + + if (!wpa_key_mgmt_fils(sm->wpa_key_mgmt)) { + wpa_printf(MSG_DEBUG, + "FILS: Not a FILS AKM - reject association"); + return -1; + } + + end = ((const u8 *) mgmt) + frame_len; + fc = le_to_host16(mgmt->frame_control); + stype = WLAN_FC_GET_STYPE(fc); + if (stype == WLAN_FC_STYPE_REASSOC_REQ) + ie_start = mgmt->u.reassoc_req.variable; + else + ie_start = mgmt->u.assoc_req.variable; + ie = ie_start; + + /* + * Find FILS Session element which is the last unencrypted element in + * the frame. + */ + session = wpa_fils_validate_fils_session(sm, ie, end - ie, + fils_session); + if (!session) { + wpa_printf(MSG_DEBUG, "FILS: Session validation failed"); + return -1; + } + + crypt = session + 2 + session[1]; + + if (end - crypt < AES_BLOCK_SIZE) { + wpa_printf(MSG_DEBUG, + "FILS: Too short frame to include AES-SIV data"); + return -1; + } + + /* AES-SIV AAD vectors */ + + /* The STA's MAC address */ + aad[0] = mgmt->sa; + aad_len[0] = ETH_ALEN; + /* The AP's BSSID */ + aad[1] = mgmt->da; + aad_len[1] = ETH_ALEN; + /* The STA's nonce */ + aad[2] = sm->SNonce; + aad_len[2] = FILS_NONCE_LEN; + /* The AP's nonce */ + aad[3] = sm->ANonce; + aad_len[3] = FILS_NONCE_LEN; + /* + * The (Re)Association Request frame from the Capability Information + * field to the FILS Session element (both inclusive). + */ + aad[4] = (const u8 *) &mgmt->u.assoc_req.capab_info; + aad_len[4] = crypt - aad[4]; + + if (aes_siv_decrypt(sm->PTK.kek, sm->PTK.kek_len, crypt, end - crypt, + 5, aad, aad_len, pos + (crypt - ie_start)) < 0) { + wpa_printf(MSG_DEBUG, + "FILS: Invalid AES-SIV data in the frame"); + return -1; + } + wpa_hexdump(MSG_DEBUG, "FILS: Decrypted Association Request elements", + pos, left - AES_BLOCK_SIZE); + + if (wpa_fils_validate_key_confirm(sm, pos, left - AES_BLOCK_SIZE) < 0) { + wpa_printf(MSG_DEBUG, "FILS: Key Confirm validation failed"); + return -1; + } + + return left - AES_BLOCK_SIZE; +} + + +int fils_encrypt_assoc(struct wpa_state_machine *sm, u8 *buf, + size_t current_len, size_t max_len, + const struct wpabuf *hlp) +{ + u8 *end = buf + max_len; + u8 *pos = buf + current_len; + struct ieee80211_mgmt *mgmt; + struct wpabuf *plain; + const u8 *aad[5]; + size_t aad_len[5]; + + if (!sm || !sm->PTK_valid) + return -1; + + wpa_hexdump(MSG_DEBUG, + "FILS: Association Response frame before FILS processing", + buf, current_len); + + mgmt = (struct ieee80211_mgmt *) buf; + + /* AES-SIV AAD vectors */ + + /* The AP's BSSID */ + aad[0] = mgmt->sa; + aad_len[0] = ETH_ALEN; + /* The STA's MAC address */ + aad[1] = mgmt->da; + aad_len[1] = ETH_ALEN; + /* The AP's nonce */ + aad[2] = sm->ANonce; + aad_len[2] = FILS_NONCE_LEN; + /* The STA's nonce */ + aad[3] = sm->SNonce; + aad_len[3] = FILS_NONCE_LEN; + /* + * The (Re)Association Response frame from the Capability Information + * field (the same offset in both Association and Reassociation + * Response frames) to the FILS Session element (both inclusive). + */ + aad[4] = (const u8 *) &mgmt->u.assoc_resp.capab_info; + aad_len[4] = pos - aad[4]; + + /* The following elements will be encrypted with AES-SIV */ + plain = fils_prepare_plainbuf(sm, hlp); + if (!plain) { + wpa_printf(MSG_DEBUG, "FILS: Plain buffer prep failed"); + return -1; + } + + if (pos + wpabuf_len(plain) + AES_BLOCK_SIZE > end) { + wpa_printf(MSG_DEBUG, + "FILS: Not enough room for FILS elements"); + wpabuf_clear_free(plain); + return -1; + } + + wpa_hexdump_buf_key(MSG_DEBUG, "FILS: Association Response plaintext", + plain); + + if (aes_siv_encrypt(sm->PTK.kek, sm->PTK.kek_len, + wpabuf_head(plain), wpabuf_len(plain), + 5, aad, aad_len, pos) < 0) { + wpabuf_clear_free(plain); + return -1; + } + + wpa_hexdump(MSG_DEBUG, + "FILS: Encrypted Association Response elements", + pos, AES_BLOCK_SIZE + wpabuf_len(plain)); + current_len += wpabuf_len(plain) + AES_BLOCK_SIZE; + wpabuf_clear_free(plain); + + sm->fils_completed = 1; + + return current_len; +} + + +static struct wpabuf * fils_prepare_plainbuf(struct wpa_state_machine *sm, + const struct wpabuf *hlp) +{ + struct wpabuf *plain; + u8 *len, *tmp, *tmp2; + u8 hdr[2]; + u8 *gtk, dummy_gtk[32]; + size_t gtk_len; + struct wpa_group *gsm; + + plain = wpabuf_alloc(1000); + if (!plain) + return NULL; + + /* TODO: FILS Public Key */ + + /* FILS Key Confirmation */ + wpabuf_put_u8(plain, WLAN_EID_EXTENSION); /* Element ID */ + wpabuf_put_u8(plain, 1 + sm->fils_key_auth_len); /* Length */ + /* Element ID Extension */ + wpabuf_put_u8(plain, WLAN_EID_EXT_FILS_KEY_CONFIRM); + wpabuf_put_data(plain, sm->fils_key_auth_ap, sm->fils_key_auth_len); + + /* FILS HLP Container */ + if (hlp) + wpabuf_put_buf(plain, hlp); + + /* TODO: FILS IP Address Assignment */ + + /* Key Delivery */ + gsm = sm->group; + wpabuf_put_u8(plain, WLAN_EID_EXTENSION); /* Element ID */ + len = wpabuf_put(plain, 1); + wpabuf_put_u8(plain, WLAN_EID_EXT_KEY_DELIVERY); + wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, + wpabuf_put(plain, WPA_KEY_RSC_LEN)); + /* GTK KDE */ + gtk = gsm->GTK[gsm->GN - 1]; + gtk_len = gsm->GTK_len; + if (sm->wpa_auth->conf.disable_gtk || + sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) { + /* + * Provide unique random GTK to each STA to prevent use + * of GTK in the BSS. + */ + if (random_get_bytes(dummy_gtk, gtk_len) < 0) { + wpabuf_clear_free(plain); + return NULL; + } + gtk = dummy_gtk; + } + hdr[0] = gsm->GN & 0x03; + hdr[1] = 0; + tmp = wpabuf_put(plain, 0); + tmp2 = wpa_add_kde(tmp, RSN_KEY_DATA_GROUPKEY, hdr, 2, + gtk, gtk_len); + wpabuf_put(plain, tmp2 - tmp); + + /* IGTK KDE */ + tmp = wpabuf_put(plain, 0); + tmp2 = ieee80211w_kde_add(sm, tmp); + wpabuf_put(plain, tmp2 - tmp); + + *len = (u8 *) wpabuf_put(plain, 0) - len - 1; + +#ifdef CONFIG_OCV + if (wpa_auth_uses_ocv(sm)) { + struct wpa_channel_info ci; + u8 *pos; + + if (wpa_channel_info(sm->wpa_auth, &ci) != 0) { + wpa_printf(MSG_WARNING, + "FILS: Failed to get channel info for OCI element"); + wpabuf_clear_free(plain); + return NULL; + } + + pos = wpabuf_put(plain, OCV_OCI_EXTENDED_LEN); + if (ocv_insert_extended_oci(&ci, pos) < 0) { + wpabuf_clear_free(plain); + return NULL; + } + } +#endif /* CONFIG_OCV */ + + return plain; +} + + +int fils_set_tk(struct wpa_state_machine *sm) +{ + enum wpa_alg alg; + int klen; + + if (!sm || !sm->PTK_valid) { + wpa_printf(MSG_DEBUG, "FILS: No valid PTK available to set TK"); + return -1; + } + if (sm->tk_already_set) { + wpa_printf(MSG_DEBUG, "FILS: TK already set to the driver"); + return -1; + } + + alg = wpa_cipher_to_alg(sm->pairwise); + klen = wpa_cipher_key_len(sm->pairwise); + + wpa_printf(MSG_DEBUG, "FILS: Configure TK to the driver"); + if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0, + sm->PTK.tk, klen)) { + wpa_printf(MSG_DEBUG, "FILS: Failed to set TK to the driver"); + return -1; + } + sm->tk_already_set = TRUE; + + return 0; +} + + +u8 * hostapd_eid_assoc_fils_session(struct wpa_state_machine *sm, u8 *buf, + const u8 *fils_session, struct wpabuf *hlp) +{ + struct wpabuf *plain; + u8 *pos = buf; + + /* FILS Session */ + *pos++ = WLAN_EID_EXTENSION; /* Element ID */ + *pos++ = 1 + FILS_SESSION_LEN; /* Length */ + *pos++ = WLAN_EID_EXT_FILS_SESSION; /* Element ID Extension */ + os_memcpy(pos, fils_session, FILS_SESSION_LEN); + pos += FILS_SESSION_LEN; + + plain = fils_prepare_plainbuf(sm, hlp); + if (!plain) { + wpa_printf(MSG_DEBUG, "FILS: Plain buffer prep failed"); + return NULL; + } + + os_memcpy(pos, wpabuf_head(plain), wpabuf_len(plain)); + pos += wpabuf_len(plain); + + wpa_printf(MSG_DEBUG, "%s: plain buf_len: %u", __func__, + (unsigned int) wpabuf_len(plain)); + wpabuf_clear_free(plain); + sm->fils_completed = 1; + return pos; +} + +#endif /* CONFIG_FILS */ + + +#ifdef CONFIG_OCV +int get_sta_tx_parameters(struct wpa_state_machine *sm, int ap_max_chanwidth, + int ap_seg1_idx, int *bandwidth, int *seg1_idx) +{ + struct wpa_authenticator *wpa_auth = sm->wpa_auth; + + if (!wpa_auth->cb->get_sta_tx_params) + return -1; + return wpa_auth->cb->get_sta_tx_params(wpa_auth->cb_ctx, sm->addr, + ap_max_chanwidth, ap_seg1_idx, + bandwidth, seg1_idx); +} +#endif /* CONFIG_OCV */ + + +SM_STATE(WPA_PTK, PTKCALCNEGOTIATING) +{ + struct wpa_authenticator *wpa_auth = sm->wpa_auth; + struct wpa_ptk PTK; + int ok = 0, psk_found = 0; + const u8 *pmk = NULL; + size_t pmk_len; + int ft; + const u8 *eapol_key_ie, *key_data, *mic; + u16 key_data_length; + size_t mic_len, eapol_key_ie_len; + struct ieee802_1x_hdr *hdr; + struct wpa_eapol_key *key; + struct wpa_eapol_ie_parse kde; + int vlan_id = 0; + + SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING, wpa_ptk); + sm->EAPOLKeyReceived = FALSE; + sm->update_snonce = FALSE; + os_memset(&PTK, 0, sizeof(PTK)); + + mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len); + + /* WPA with IEEE 802.1X: use the derived PMK from EAP + * WPA-PSK: iterate through possible PSKs and select the one matching + * the packet */ + for (;;) { + if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) && + !wpa_key_mgmt_sae(sm->wpa_key_mgmt)) { + pmk = wpa_auth_get_psk(sm->wpa_auth, sm->addr, + sm->p2p_dev_addr, pmk, &pmk_len, + &vlan_id); + if (pmk == NULL) + break; + psk_found = 1; +#ifdef CONFIG_IEEE80211R_AP + if (wpa_key_mgmt_ft_psk(sm->wpa_key_mgmt)) { + os_memcpy(sm->xxkey, pmk, pmk_len); + sm->xxkey_len = pmk_len; + } +#endif /* CONFIG_IEEE80211R_AP */ + } else { + pmk = sm->PMK; + pmk_len = sm->pmk_len; + } + + if ((!pmk || !pmk_len) && sm->pmksa) { + wpa_printf(MSG_DEBUG, "WPA: Use PMK from PMKSA cache"); + pmk = sm->pmksa->pmk; + pmk_len = sm->pmksa->pmk_len; + } + + if (wpa_derive_ptk(sm, sm->SNonce, pmk, pmk_len, &PTK) < 0) + break; + + if (mic_len && + wpa_verify_key_mic(sm->wpa_key_mgmt, pmk_len, &PTK, + sm->last_rx_eapol_key, + sm->last_rx_eapol_key_len) == 0) { + if (sm->PMK != pmk) { + os_memcpy(sm->PMK, pmk, pmk_len); + sm->pmk_len = pmk_len; + } + ok = 1; + break; + } + +#ifdef CONFIG_FILS + if (!mic_len && + wpa_aead_decrypt(sm, &PTK, sm->last_rx_eapol_key, + sm->last_rx_eapol_key_len, NULL) == 0) { + ok = 1; + break; + } +#endif /* CONFIG_FILS */ + + if (!wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) || + wpa_key_mgmt_sae(sm->wpa_key_mgmt)) + break; + } + + if (!ok) { + wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, + "invalid MIC in msg 2/4 of 4-Way Handshake"); + if (psk_found) + wpa_auth_psk_failure_report(sm->wpa_auth, sm->addr); + return; + } + + /* + * Note: last_rx_eapol_key length fields have already been validated in + * wpa_receive(). + */ + hdr = (struct ieee802_1x_hdr *) sm->last_rx_eapol_key; + key = (struct wpa_eapol_key *) (hdr + 1); + mic = (u8 *) (key + 1); + key_data = mic + mic_len + 2; + key_data_length = WPA_GET_BE16(mic + mic_len); + if (key_data_length > sm->last_rx_eapol_key_len - sizeof(*hdr) - + sizeof(*key) - mic_len - 2) + return; + + if (wpa_parse_kde_ies(key_data, key_data_length, &kde) < 0) { + wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, + "received EAPOL-Key msg 2/4 with invalid Key Data contents"); + return; + } + if (kde.rsn_ie) { + eapol_key_ie = kde.rsn_ie; + eapol_key_ie_len = kde.rsn_ie_len; + } else if (kde.osen) { + eapol_key_ie = kde.osen; + eapol_key_ie_len = kde.osen_len; + } else { + eapol_key_ie = kde.wpa_ie; + eapol_key_ie_len = kde.wpa_ie_len; + } + ft = sm->wpa == WPA_VERSION_WPA2 && wpa_key_mgmt_ft(sm->wpa_key_mgmt); + if (sm->wpa_ie == NULL || + wpa_compare_rsn_ie(ft, sm->wpa_ie, sm->wpa_ie_len, + eapol_key_ie, eapol_key_ie_len)) { + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, + "WPA IE from (Re)AssocReq did not match with msg 2/4"); + if (sm->wpa_ie) { + wpa_hexdump(MSG_DEBUG, "WPA IE in AssocReq", + sm->wpa_ie, sm->wpa_ie_len); + } + wpa_hexdump(MSG_DEBUG, "WPA IE in msg 2/4", + eapol_key_ie, eapol_key_ie_len); + /* MLME-DEAUTHENTICATE.request */ + wpa_sta_disconnect(wpa_auth, sm->addr, + WLAN_REASON_PREV_AUTH_NOT_VALID); + return; + } +#ifdef CONFIG_OCV + if (wpa_auth_uses_ocv(sm)) { + struct wpa_channel_info ci; + int tx_chanwidth; + int tx_seg1_idx; + + if (wpa_channel_info(wpa_auth, &ci) != 0) { + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, + "Failed to get channel info to validate received OCI in EAPOL-Key 2/4"); + return; + } + + if (get_sta_tx_parameters(sm, + channel_width_to_int(ci.chanwidth), + ci.seg1_idx, &tx_chanwidth, + &tx_seg1_idx) < 0) + return; + + if (ocv_verify_tx_params(kde.oci, kde.oci_len, &ci, + tx_chanwidth, tx_seg1_idx) != 0) { + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, + ocv_errorstr); + return; + } + } +#endif /* CONFIG_OCV */ +#ifdef CONFIG_IEEE80211R_AP + if (ft && ft_check_msg_2_of_4(wpa_auth, sm, &kde) < 0) { + wpa_sta_disconnect(wpa_auth, sm->addr, + WLAN_REASON_PREV_AUTH_NOT_VALID); + return; + } +#endif /* CONFIG_IEEE80211R_AP */ +#ifdef CONFIG_P2P + if (kde.ip_addr_req && kde.ip_addr_req[0] && + wpa_auth->ip_pool && WPA_GET_BE32(sm->ip_addr) == 0) { + int idx; + wpa_printf(MSG_DEBUG, + "P2P: IP address requested in EAPOL-Key exchange"); + idx = bitfield_get_first_zero(wpa_auth->ip_pool); + if (idx >= 0) { + u32 start = WPA_GET_BE32(wpa_auth->conf.ip_addr_start); + bitfield_set(wpa_auth->ip_pool, idx); + WPA_PUT_BE32(sm->ip_addr, start + idx); + wpa_printf(MSG_DEBUG, + "P2P: Assigned IP address %u.%u.%u.%u to " + MACSTR, sm->ip_addr[0], sm->ip_addr[1], + sm->ip_addr[2], sm->ip_addr[3], + MAC2STR(sm->addr)); + } + } +#endif /* CONFIG_P2P */ + +#ifdef CONFIG_IEEE80211R_AP + if (sm->wpa == WPA_VERSION_WPA2 && wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { + /* + * Verify that PMKR1Name from EAPOL-Key message 2/4 matches + * with the value we derived. + */ + if (os_memcmp_const(sm->sup_pmk_r1_name, sm->pmk_r1_name, + WPA_PMK_NAME_LEN) != 0) { + wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, + "PMKR1Name mismatch in FT 4-way " + "handshake"); + wpa_hexdump(MSG_DEBUG, "FT: PMKR1Name from " + "Supplicant", + sm->sup_pmk_r1_name, WPA_PMK_NAME_LEN); + wpa_hexdump(MSG_DEBUG, "FT: Derived PMKR1Name", + sm->pmk_r1_name, WPA_PMK_NAME_LEN); + return; + } + } +#endif /* CONFIG_IEEE80211R_AP */ + +#ifdef CONFIG_FULL_SUPPLICANT + if (vlan_id && wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) && + wpa_auth_update_vlan(wpa_auth, sm->addr, vlan_id) < 0) { + wpa_sta_disconnect(wpa_auth, sm->addr, + WLAN_REASON_PREV_AUTH_NOT_VALID); + return; + } +#endif + + sm->pending_1_of_4_timeout = 0; + eloop_cancel_timeout(wpa_send_eapol_timeout, sm->wpa_auth, sm); + + if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt)) { + /* PSK may have changed from the previous choice, so update + * state machine data based on whatever PSK was selected here. + */ + os_memcpy(sm->PMK, pmk, PMK_LEN); + sm->pmk_len = PMK_LEN; + } + + sm->MICVerified = TRUE; + + os_memcpy(&sm->PTK, &PTK, sizeof(PTK)); + forced_memzero(&PTK, sizeof(PTK)); + sm->PTK_valid = TRUE; +} + + +SM_STATE(WPA_PTK, PTKCALCNEGOTIATING2) +{ + SM_ENTRY_MA(WPA_PTK, PTKCALCNEGOTIATING2, wpa_ptk); + sm->TimeoutCtr = 0; +} + + +#ifdef CONFIG_IEEE80211W_AP + +static int ieee80211w_kde_len(struct wpa_state_machine *sm) +{ + if (sm->mgmt_frame_prot) { + size_t len; + len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher); + return 2 + RSN_SELECTOR_LEN + WPA_IGTK_KDE_PREFIX_LEN + len; + } + + return 0; +} + + +static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos) +{ + struct wpa_igtk_kde igtk; + struct wpa_group *gsm = sm->group; + u8 rsc[WPA_KEY_RSC_LEN]; + size_t len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher); + + if (!sm->mgmt_frame_prot) + return pos; + + igtk.keyid[0] = gsm->GN_igtk; + igtk.keyid[1] = 0; + if (gsm->wpa_group_state != WPA_GROUP_SETKEYSDONE || + wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, rsc) < 0) + os_memset(igtk.pn, 0, sizeof(igtk.pn)); + else + os_memcpy(igtk.pn, rsc, sizeof(igtk.pn)); + os_memcpy(igtk.igtk, gsm->IGTK[gsm->GN_igtk - 4], len); + if (sm->wpa_auth->conf.disable_gtk || + sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) { + /* + * Provide unique random IGTK to each STA to prevent use of + * IGTK in the BSS. + */ + if (random_get_bytes(igtk.igtk, len) < 0) + return pos; + } + pos = wpa_add_kde(pos, RSN_KEY_DATA_IGTK, + (const u8 *) &igtk, WPA_IGTK_KDE_PREFIX_LEN + len, + NULL, 0); + + return pos; +} + +#else /* CONFIG_IEEE80211W_AP */ + +static int ieee80211w_kde_len(struct wpa_state_machine *sm) +{ + return 0; +} + + +static u8 * ieee80211w_kde_add(struct wpa_state_machine *sm, u8 *pos) +{ + return pos; +} + +#endif /* CONFIG_IEEE80211W_AP */ + + +static int ocv_oci_len(struct wpa_state_machine *sm) +{ +#ifdef CONFIG_OCV + if (wpa_auth_uses_ocv(sm)) + return OCV_OCI_KDE_LEN; +#endif /* CONFIG_OCV */ + return 0; +} + +static int ocv_oci_add(struct wpa_state_machine *sm, u8 **argpos) +{ +#ifdef CONFIG_OCV + struct wpa_channel_info ci; + + if (!wpa_auth_uses_ocv(sm)) + return 0; + + if (wpa_channel_info(sm->wpa_auth, &ci) != 0) { + wpa_printf(MSG_WARNING, + "Failed to get channel info for OCI element"); + return -1; + } + + return ocv_insert_oci_kde(&ci, argpos); +#else /* CONFIG_OCV */ + return 0; +#endif /* CONFIG_OCV */ +} + + +SM_STATE(WPA_PTK, PTKINITNEGOTIATING) +{ + u8 rsc[WPA_KEY_RSC_LEN], *_rsc, *gtk, *kde, *pos, dummy_gtk[32]; + size_t gtk_len, kde_len; + struct wpa_group *gsm = sm->group; + u8 *wpa_ie; + int wpa_ie_len, secure, keyidx, encr = 0; + + SM_ENTRY_MA(WPA_PTK, PTKINITNEGOTIATING, wpa_ptk); + sm->TimeoutEvt = FALSE; + + sm->TimeoutCtr++; + if (sm->wpa_auth->conf.wpa_disable_eapol_key_retries && + sm->TimeoutCtr > 1) { + /* Do not allow retransmission of EAPOL-Key msg 3/4 */ + return; + } + if (sm->TimeoutCtr > sm->wpa_auth->conf.wpa_pairwise_update_count) { + /* No point in sending the EAPOL-Key - we will disconnect + * immediately following this. */ + return; + } + + /* Send EAPOL(1, 1, 1, Pair, P, RSC, ANonce, MIC(PTK), RSNIE, [MDIE], + GTK[GN], IGTK, [FTIE], [TIE * 2]) + */ + os_memset(rsc, 0, WPA_KEY_RSC_LEN); + wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, rsc); + /* If FT is used, wpa_auth->wpa_ie includes both RSNIE and MDIE */ + wpa_ie = sm->wpa_auth->wpa_ie; + wpa_ie_len = sm->wpa_auth->wpa_ie_len; + if (sm->wpa == WPA_VERSION_WPA && + (sm->wpa_auth->conf.wpa & WPA_PROTO_RSN) && + wpa_ie_len > wpa_ie[1] + 2 && wpa_ie[0] == WLAN_EID_RSN) { + /* WPA-only STA, remove RSN IE and possible MDIE */ + wpa_ie = wpa_ie + wpa_ie[1] + 2; + if (wpa_ie[0] == WLAN_EID_MOBILITY_DOMAIN) + wpa_ie = wpa_ie + wpa_ie[1] + 2; + wpa_ie_len = wpa_ie[1] + 2; + } + wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, + "sending 3/4 msg of 4-Way Handshake"); + if (sm->wpa == WPA_VERSION_WPA2) { + /* WPA2 send GTK in the 4-way handshake */ + secure = 1; + gtk = gsm->GTK[gsm->GN - 1]; + gtk_len = gsm->GTK_len; + if (sm->wpa_auth->conf.disable_gtk || + sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) { + /* + * Provide unique random GTK to each STA to prevent use + * of GTK in the BSS. + */ + if (random_get_bytes(dummy_gtk, gtk_len) < 0) + return; + gtk = dummy_gtk; + } + keyidx = gsm->GN; + _rsc = rsc; + encr = 1; + } else { + /* WPA does not include GTK in msg 3/4 */ + secure = 0; + gtk = NULL; + gtk_len = 0; + keyidx = 0; + _rsc = NULL; + if (sm->rx_eapol_key_secure) { + /* + * It looks like Windows 7 supplicant tries to use + * Secure bit in msg 2/4 after having reported Michael + * MIC failure and it then rejects the 4-way handshake + * if msg 3/4 does not set Secure bit. Work around this + * by setting the Secure bit here even in the case of + * WPA if the supplicant used it first. + */ + wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, + "STA used Secure bit in WPA msg 2/4 - " + "set Secure for 3/4 as workaround"); + secure = 1; + } + } + + kde_len = wpa_ie_len + ieee80211w_kde_len(sm) + ocv_oci_len(sm); + if (gtk) + kde_len += 2 + RSN_SELECTOR_LEN + 2 + gtk_len; +#ifdef CONFIG_IEEE80211R_AP + if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { + kde_len += 2 + PMKID_LEN; /* PMKR1Name into RSN IE */ + kde_len += 300; /* FTIE + 2 * TIE */ + } +#endif /* CONFIG_IEEE80211R_AP */ +#ifdef CONFIG_P2P + if (WPA_GET_BE32(sm->ip_addr) > 0) + kde_len += 2 + RSN_SELECTOR_LEN + 3 * 4; +#endif /* CONFIG_P2P */ + kde = os_malloc(kde_len); + if (kde == NULL) + return; + + pos = kde; + os_memcpy(pos, wpa_ie, wpa_ie_len); + pos += wpa_ie_len; +#ifdef CONFIG_IEEE80211R_AP + if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { + int res; + size_t elen; + + elen = pos - kde; + res = wpa_insert_pmkid(kde, &elen, sm->pmk_r1_name); + if (res < 0) { + wpa_printf(MSG_ERROR, "FT: Failed to insert " + "PMKR1Name into RSN IE in EAPOL-Key data"); + os_free(kde); + return; + } + pos -= wpa_ie_len; + pos += elen; + } +#endif /* CONFIG_IEEE80211R_AP */ + if (gtk) { + u8 hdr[2]; + hdr[0] = keyidx & 0x03; + hdr[1] = 0; + pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2, + gtk, gtk_len); + } + pos = ieee80211w_kde_add(sm, pos); +#ifdef CONFIG_OCV + if (ocv_oci_add(sm, &pos) < 0) { + os_free(kde); + return; + } +#endif +#ifdef CONFIG_IEEE80211R_AP + if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { + int res; + struct wpa_auth_config *conf; + + conf = &sm->wpa_auth->conf; + if (sm->assoc_resp_ftie && + kde + kde_len - pos >= 2 + sm->assoc_resp_ftie[1]) { + os_memcpy(pos, sm->assoc_resp_ftie, + 2 + sm->assoc_resp_ftie[1]); + res = 2 + sm->assoc_resp_ftie[1]; + } else { + int use_sha384 = wpa_key_mgmt_sha384(sm->wpa_key_mgmt); + + res = wpa_write_ftie(conf, use_sha384, + conf->r0_key_holder, + conf->r0_key_holder_len, + NULL, NULL, pos, + kde + kde_len - pos, + NULL, 0); + } + if (res < 0) { + wpa_printf(MSG_ERROR, "FT: Failed to insert FTIE " + "into EAPOL-Key Key Data"); + os_free(kde); + return; + } + pos += res; + + /* TIE[ReassociationDeadline] (TU) */ + *pos++ = WLAN_EID_TIMEOUT_INTERVAL; + *pos++ = 5; + *pos++ = WLAN_TIMEOUT_REASSOC_DEADLINE; + WPA_PUT_LE32(pos, conf->reassociation_deadline); + pos += 4; + + /* TIE[KeyLifetime] (seconds) */ + *pos++ = WLAN_EID_TIMEOUT_INTERVAL; + *pos++ = 5; + *pos++ = WLAN_TIMEOUT_KEY_LIFETIME; + WPA_PUT_LE32(pos, conf->r0_key_lifetime); + pos += 4; + } +#endif /* CONFIG_IEEE80211R_AP */ +#ifdef CONFIG_P2P + if (WPA_GET_BE32(sm->ip_addr) > 0) { + u8 addr[3 * 4]; + os_memcpy(addr, sm->ip_addr, 4); + os_memcpy(addr + 4, sm->wpa_auth->conf.ip_addr_mask, 4); + os_memcpy(addr + 8, sm->wpa_auth->conf.ip_addr_go, 4); + pos = wpa_add_kde(pos, WFA_KEY_DATA_IP_ADDR_ALLOC, + addr, sizeof(addr), NULL, 0); + } +#endif /* CONFIG_P2P */ + + wpa_send_eapol(sm->wpa_auth, sm, + (secure ? WPA_KEY_INFO_SECURE : 0) | + (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ? + WPA_KEY_INFO_MIC : 0) | + WPA_KEY_INFO_ACK | WPA_KEY_INFO_INSTALL | + WPA_KEY_INFO_KEY_TYPE, + _rsc, sm->ANonce, kde, pos - kde, keyidx, encr); + os_free(kde); +} + + +SM_STATE(WPA_PTK, PTKINITDONE) +{ + SM_ENTRY_MA(WPA_PTK, PTKINITDONE, wpa_ptk); + sm->EAPOLKeyReceived = FALSE; + if (sm->Pair) { + enum wpa_alg alg = wpa_cipher_to_alg(sm->pairwise); + int klen = wpa_cipher_key_len(sm->pairwise); + if (wpa_auth_set_key(sm->wpa_auth, 0, alg, sm->addr, 0, + sm->PTK.tk, klen)) { + wpa_sta_disconnect(sm->wpa_auth, sm->addr, + WLAN_REASON_PREV_AUTH_NOT_VALID); + return; + } + /* FIX: MLME-SetProtection.Request(TA, Tx_Rx) */ + sm->pairwise_set = TRUE; + + wpa_auth_set_ptk_rekey_timer(sm); + + if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) || + sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP || + sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE) { + wpa_auth_set_eapol(sm->wpa_auth, sm->addr, + WPA_EAPOL_authorized, 1); + } + } + + if (0 /* IBSS == TRUE */) { + sm->keycount++; + if (sm->keycount == 2) { + wpa_auth_set_eapol(sm->wpa_auth, sm->addr, + WPA_EAPOL_portValid, 1); + } + } else { + wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_portValid, + 1); + } + wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyAvailable, 0); + wpa_auth_set_eapol(sm->wpa_auth, sm->addr, WPA_EAPOL_keyDone, 1); + if (sm->wpa == WPA_VERSION_WPA) + sm->PInitAKeys = TRUE; + else + sm->has_GTK = TRUE; + wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO, + "pairwise key handshake completed (%s)", + sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN"); + +#ifdef CONFIG_IEEE80211R_AP + wpa_ft_push_pmk_r1(sm->wpa_auth, sm->addr); +#endif /* CONFIG_IEEE80211R_AP */ +} + + +SM_STEP(WPA_PTK) +{ + struct wpa_authenticator *wpa_auth = sm->wpa_auth; + + if (sm->Init) + SM_ENTER(WPA_PTK, INITIALIZE); + else if (sm->Disconnect + /* || FIX: dot11RSNAConfigSALifetime timeout */) { + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_DEBUG, + "WPA_PTK: sm->Disconnect"); + SM_ENTER(WPA_PTK, DISCONNECT); + } + else if (sm->DeauthenticationRequest) + SM_ENTER(WPA_PTK, DISCONNECTED); + else if (sm->AuthenticationRequest) + SM_ENTER(WPA_PTK, AUTHENTICATION); + else if (sm->ReAuthenticationRequest) + SM_ENTER(WPA_PTK, AUTHENTICATION2); + else if (sm->PTKRequest) { + if (wpa_auth_sm_ptk_update(sm) < 0) + SM_ENTER(WPA_PTK, DISCONNECTED); + else + SM_ENTER(WPA_PTK, PTKSTART); + } else switch (sm->wpa_ptk_state) { + case WPA_PTK_INITIALIZE: + break; + case WPA_PTK_DISCONNECT: + SM_ENTER(WPA_PTK, DISCONNECTED); + break; + case WPA_PTK_DISCONNECTED: + SM_ENTER(WPA_PTK, INITIALIZE); + break; + case WPA_PTK_AUTHENTICATION: + SM_ENTER(WPA_PTK, AUTHENTICATION2); + break; + case WPA_PTK_AUTHENTICATION2: +#ifdef CONFIG_FULL_HOSTAPD + if (wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) && + wpa_auth_get_eapol(sm->wpa_auth, sm->addr, + WPA_EAPOL_keyRun) > 0) + SM_ENTER(WPA_PTK, INITPMK); + else +#endif + if (wpa_key_mgmt_wpa_psk(sm->wpa_key_mgmt) || + sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE + /* FIX: && 802.1X::keyRun */) + SM_ENTER(WPA_PTK, INITPSK); + else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP) + SM_ENTER(WPA_PTK, INITPMK); + break; + case WPA_PTK_INITPMK: + if (wpa_auth_get_eapol(sm->wpa_auth, sm->addr, + WPA_EAPOL_keyAvailable) > 0) { + SM_ENTER(WPA_PTK, PTKSTART); +#ifdef CONFIG_DPP + } else if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP && sm->pmksa) { + SM_ENTER(WPA_PTK, PTKSTART); +#endif /* CONFIG_DPP */ + } else { + wpa_auth->dot11RSNA4WayHandshakeFailures++; + wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO, + "INITPMK - keyAvailable = false"); + SM_ENTER(WPA_PTK, DISCONNECT); + } + break; + case WPA_PTK_INITPSK: + if (wpa_auth_get_psk(sm->wpa_auth, sm->addr, sm->p2p_dev_addr, + NULL, NULL, NULL)) { + SM_ENTER(WPA_PTK, PTKSTART); +#ifdef CONFIG_SAE_AP + } else if (wpa_auth_uses_sae(sm) && sm->pmksa) { + SM_ENTER(WPA_PTK, PTKSTART); +#endif /* CONFIG_SAE_AP */ + } else { + wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_INFO, + "no PSK configured for the STA"); + wpa_auth->dot11RSNA4WayHandshakeFailures++; + SM_ENTER(WPA_PTK, DISCONNECT); + } + break; + case WPA_PTK_PTKSTART: + if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest && + sm->EAPOLKeyPairwise) + SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING); + else if (sm->TimeoutCtr > + sm->wpa_auth->conf.wpa_pairwise_update_count) { + wpa_auth->dot11RSNA4WayHandshakeFailures++; + wpa_auth_vlogger( + sm->wpa_auth, sm->addr, LOGGER_DEBUG, + "PTKSTART: Retry limit %u reached", + sm->wpa_auth->conf.wpa_pairwise_update_count); + SM_ENTER(WPA_PTK, DISCONNECT); + } else if (sm->TimeoutEvt) + SM_ENTER(WPA_PTK, PTKSTART); + break; + case WPA_PTK_PTKCALCNEGOTIATING: + if (sm->MICVerified) + SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING2); + else if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest && + sm->EAPOLKeyPairwise) + SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING); + else if (sm->TimeoutEvt) + SM_ENTER(WPA_PTK, PTKSTART); + break; + case WPA_PTK_PTKCALCNEGOTIATING2: + SM_ENTER(WPA_PTK, PTKINITNEGOTIATING); + break; + case WPA_PTK_PTKINITNEGOTIATING: + if (sm->update_snonce) + SM_ENTER(WPA_PTK, PTKCALCNEGOTIATING); + else if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest && + sm->EAPOLKeyPairwise && sm->MICVerified) + SM_ENTER(WPA_PTK, PTKINITDONE); + else if (sm->TimeoutCtr > + sm->wpa_auth->conf.wpa_pairwise_update_count || + (sm->wpa_auth->conf.wpa_disable_eapol_key_retries && + sm->TimeoutCtr > 1)) { + wpa_auth->dot11RSNA4WayHandshakeFailures++; + wpa_auth_vlogger( + sm->wpa_auth, sm->addr, LOGGER_DEBUG, + "PTKINITNEGOTIATING: Retry limit %u reached", + sm->wpa_auth->conf.wpa_pairwise_update_count); + SM_ENTER(WPA_PTK, DISCONNECT); + } else if (sm->TimeoutEvt) + SM_ENTER(WPA_PTK, PTKINITNEGOTIATING); + break; + case WPA_PTK_PTKINITDONE: + break; + } +} + + +SM_STATE(WPA_PTK_GROUP, IDLE) +{ + SM_ENTRY_MA(WPA_PTK_GROUP, IDLE, wpa_ptk_group); + if (sm->Init) { + /* Init flag is not cleared here, so avoid busy + * loop by claiming nothing changed. */ + sm->changed = FALSE; + } + sm->GTimeoutCtr = 0; +} + + +SM_STATE(WPA_PTK_GROUP, REKEYNEGOTIATING) +{ + u8 rsc[WPA_KEY_RSC_LEN]; + struct wpa_group *gsm = sm->group; + const u8 *kde; + u8 *kde_buf = NULL, *pos, hdr[2]; + size_t kde_len; + u8 *gtk, dummy_gtk[32]; + + SM_ENTRY_MA(WPA_PTK_GROUP, REKEYNEGOTIATING, wpa_ptk_group); + + sm->GTimeoutCtr++; + if (sm->wpa_auth->conf.wpa_disable_eapol_key_retries && + sm->GTimeoutCtr > 1) { + /* Do not allow retransmission of EAPOL-Key group msg 1/2 */ + return; + } + if (sm->GTimeoutCtr > sm->wpa_auth->conf.wpa_group_update_count) { + /* No point in sending the EAPOL-Key - we will disconnect + * immediately following this. */ + return; + } + + if (sm->wpa == WPA_VERSION_WPA) + sm->PInitAKeys = FALSE; + sm->TimeoutEvt = FALSE; + /* Send EAPOL(1, 1, 1, !Pair, G, RSC, GNonce, MIC(PTK), GTK[GN]) */ + os_memset(rsc, 0, WPA_KEY_RSC_LEN); + if (gsm->wpa_group_state == WPA_GROUP_SETKEYSDONE) + wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, rsc); + wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, + "sending 1/2 msg of Group Key Handshake"); + + gtk = gsm->GTK[gsm->GN - 1]; + if (sm->wpa_auth->conf.disable_gtk || + sm->wpa_key_mgmt == WPA_KEY_MGMT_OSEN) { + /* + * Provide unique random GTK to each STA to prevent use + * of GTK in the BSS. + */ + if (random_get_bytes(dummy_gtk, gsm->GTK_len) < 0) + return; + gtk = dummy_gtk; + } + if (sm->wpa == WPA_VERSION_WPA2) { + kde_len = 2 + RSN_SELECTOR_LEN + 2 + gsm->GTK_len + + ieee80211w_kde_len(sm) + ocv_oci_len(sm); + kde_buf = os_malloc(kde_len); + if (kde_buf == NULL) + return; + + kde = pos = kde_buf; + hdr[0] = gsm->GN & 0x03; + hdr[1] = 0; + pos = wpa_add_kde(pos, RSN_KEY_DATA_GROUPKEY, hdr, 2, + gtk, gsm->GTK_len); + pos = ieee80211w_kde_add(sm, pos); + if (ocv_oci_add(sm, &pos) < 0) { + os_free(kde_buf); + return; + } + kde_len = pos - kde; + } else { + kde = gtk; + kde_len = gsm->GTK_len; + } + + wpa_send_eapol(sm->wpa_auth, sm, + WPA_KEY_INFO_SECURE | + (wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len) ? + WPA_KEY_INFO_MIC : 0) | + WPA_KEY_INFO_ACK | + (!sm->Pair ? WPA_KEY_INFO_INSTALL : 0), + rsc, NULL, kde, kde_len, gsm->GN, 1); + + os_free(kde_buf); +} + + +SM_STATE(WPA_PTK_GROUP, REKEYESTABLISHED) +{ +#ifdef CONFIG_OCV + struct wpa_authenticator *wpa_auth = sm->wpa_auth; + const u8 *key_data, *mic; + struct ieee802_1x_hdr *hdr; + struct wpa_eapol_key *key; + struct wpa_eapol_ie_parse kde; + size_t mic_len; + u16 key_data_length; +#endif /* CONFIG_OCV */ + + SM_ENTRY_MA(WPA_PTK_GROUP, REKEYESTABLISHED, wpa_ptk_group); + sm->EAPOLKeyReceived = FALSE; + +#ifdef CONFIG_OCV + mic_len = wpa_mic_len(sm->wpa_key_mgmt, sm->pmk_len); + + /* + * Note: last_rx_eapol_key length fields have already been validated in + * wpa_receive(). + */ + hdr = (struct ieee802_1x_hdr *) sm->last_rx_eapol_key; + key = (struct wpa_eapol_key *) (hdr + 1); + mic = (u8 *) (key + 1); + key_data = mic + mic_len + 2; + key_data_length = WPA_GET_BE16(mic + mic_len); + if (key_data_length > sm->last_rx_eapol_key_len - sizeof(*hdr) - + sizeof(*key) - mic_len - 2) + return; + + if (wpa_parse_kde_ies(key_data, key_data_length, &kde) < 0) { + wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_INFO, + "received EAPOL-Key group msg 2/2 with invalid Key Data contents"); + return; + } + + if (wpa_auth_uses_ocv(sm)) { + struct wpa_channel_info ci; + int tx_chanwidth; + int tx_seg1_idx; + + if (wpa_channel_info(wpa_auth, &ci) != 0) { + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, + "Failed to get channel info to validate received OCI in EAPOL-Key group 1/2"); + return; + } + + if (get_sta_tx_parameters(sm, + channel_width_to_int(ci.chanwidth), + ci.seg1_idx, &tx_chanwidth, + &tx_seg1_idx) < 0) + return; + + if (ocv_verify_tx_params(kde.oci, kde.oci_len, &ci, + tx_chanwidth, tx_seg1_idx) != 0) { + wpa_auth_logger(wpa_auth, sm->addr, LOGGER_INFO, + ocv_errorstr); + return; + } + } +#endif /* CONFIG_OCV */ + + if (sm->GUpdateStationKeys) + sm->group->GKeyDoneStations--; + sm->GUpdateStationKeys = FALSE; + sm->GTimeoutCtr = 0; + /* FIX: MLME.SetProtection.Request(TA, Tx_Rx) */ + wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO, + "group key handshake completed (%s)", + sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN"); + sm->has_GTK = TRUE; +} + + +SM_STATE(WPA_PTK_GROUP, KEYERROR) +{ + SM_ENTRY_MA(WPA_PTK_GROUP, KEYERROR, wpa_ptk_group); + if (sm->GUpdateStationKeys) + sm->group->GKeyDoneStations--; + sm->GUpdateStationKeys = FALSE; + sm->Disconnect = TRUE; + wpa_auth_vlogger(sm->wpa_auth, sm->addr, LOGGER_INFO, + "group key handshake failed (%s) after %u tries", + sm->wpa == WPA_VERSION_WPA ? "WPA" : "RSN", + sm->wpa_auth->conf.wpa_group_update_count); +} + + +SM_STEP(WPA_PTK_GROUP) +{ + if (sm->Init || sm->PtkGroupInit) { + SM_ENTER(WPA_PTK_GROUP, IDLE); + sm->PtkGroupInit = FALSE; + } else switch (sm->wpa_ptk_group_state) { + case WPA_PTK_GROUP_IDLE: + if (sm->GUpdateStationKeys || + (sm->wpa == WPA_VERSION_WPA && sm->PInitAKeys)) + SM_ENTER(WPA_PTK_GROUP, REKEYNEGOTIATING); + break; + case WPA_PTK_GROUP_REKEYNEGOTIATING: + if (sm->EAPOLKeyReceived && !sm->EAPOLKeyRequest && + !sm->EAPOLKeyPairwise && sm->MICVerified) + SM_ENTER(WPA_PTK_GROUP, REKEYESTABLISHED); + else if (sm->GTimeoutCtr > + sm->wpa_auth->conf.wpa_group_update_count || + (sm->wpa_auth->conf.wpa_disable_eapol_key_retries && + sm->GTimeoutCtr > 1)) + SM_ENTER(WPA_PTK_GROUP, KEYERROR); + else if (sm->TimeoutEvt) + SM_ENTER(WPA_PTK_GROUP, REKEYNEGOTIATING); + break; + case WPA_PTK_GROUP_KEYERROR: + SM_ENTER(WPA_PTK_GROUP, IDLE); + break; + case WPA_PTK_GROUP_REKEYESTABLISHED: + SM_ENTER(WPA_PTK_GROUP, IDLE); + break; + } +} + + +static int wpa_gtk_update(struct wpa_authenticator *wpa_auth, + struct wpa_group *group) +{ + int ret = 0; + + os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN); + inc_byte_array(group->Counter, WPA_NONCE_LEN); + if (wpa_gmk_to_gtk(group->GMK, "Group key expansion", + wpa_auth->addr, group->GNonce, + group->GTK[group->GN - 1], group->GTK_len) < 0) + ret = -1; + wpa_hexdump_key(MSG_DEBUG, "GTK", + group->GTK[group->GN - 1], group->GTK_len); + +#ifdef CONFIG_IEEE80211W_AP + if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION) { + size_t len; + len = wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher); + os_memcpy(group->GNonce, group->Counter, WPA_NONCE_LEN); + inc_byte_array(group->Counter, WPA_NONCE_LEN); + if (wpa_gmk_to_gtk(group->GMK, "IGTK key expansion", + wpa_auth->addr, group->GNonce, + group->IGTK[group->GN_igtk - 4], len) < 0) + ret = -1; + wpa_hexdump_key(MSG_DEBUG, "IGTK", + group->IGTK[group->GN_igtk - 4], len); + } +#endif /* CONFIG_IEEE80211W_AP */ + + return ret; +} + + +static void wpa_group_gtk_init(struct wpa_authenticator *wpa_auth, + struct wpa_group *group) +{ + wpa_printf(MSG_DEBUG, "WPA: group state machine entering state " + "GTK_INIT (VLAN-ID %d)", group->vlan_id); + group->changed = FALSE; /* GInit is not cleared here; avoid loop */ + group->wpa_group_state = WPA_GROUP_GTK_INIT; + + /* GTK[0..N] = 0 */ + os_memset(group->GTK, 0, sizeof(group->GTK)); + group->GN = 1; + group->GM = 2; +#ifdef CONFIG_IEEE80211W_AP + group->GN_igtk = 4; + group->GM_igtk = 5; +#endif /* CONFIG_IEEE80211W_AP */ + /* GTK[GN] = CalcGTK() */ + wpa_gtk_update(wpa_auth, group); +} + + +static int wpa_group_update_sta(struct wpa_state_machine *sm, void *ctx) +{ + if (ctx != NULL && ctx != sm->group) + return 0; + + if (sm->wpa_ptk_state != WPA_PTK_PTKINITDONE) { + wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, + "Not in PTKINITDONE; skip Group Key update"); + sm->GUpdateStationKeys = FALSE; + return 0; + } + if (sm->GUpdateStationKeys) { + /* + * This should not really happen, so add a debug log entry. + * Since we clear the GKeyDoneStations before the loop, the + * station needs to be counted here anyway. + */ + wpa_auth_logger(sm->wpa_auth, sm->addr, LOGGER_DEBUG, + "GUpdateStationKeys was already set when " + "marking station for GTK rekeying"); + } + + /* Do not rekey GTK/IGTK when STA is in WNM-Sleep Mode */ + if (sm->is_wnmsleep) + return 0; + + sm->group->GKeyDoneStations++; + sm->GUpdateStationKeys = TRUE; + + wpa_sm_step(sm); + return 0; +} + + +#ifdef CONFIG_WNM_AP +/* update GTK when exiting WNM-Sleep Mode */ +void wpa_wnmsleep_rekey_gtk(struct wpa_state_machine *sm) +{ + if (sm == NULL || sm->is_wnmsleep) + return; + + wpa_group_update_sta(sm, NULL); +} + + +void wpa_set_wnmsleep(struct wpa_state_machine *sm, int flag) +{ + if (sm) + sm->is_wnmsleep = !!flag; +} + + +int wpa_wnmsleep_gtk_subelem(struct wpa_state_machine *sm, u8 *pos) +{ + struct wpa_group *gsm = sm->group; + u8 *start = pos; + + /* + * GTK subelement: + * Sub-elem ID[1] | Length[1] | Key Info[2] | Key Length[1] | RSC[8] | + * Key[5..32] + */ + *pos++ = WNM_SLEEP_SUBELEM_GTK; + *pos++ = 11 + gsm->GTK_len; + /* Key ID in B0-B1 of Key Info */ + WPA_PUT_LE16(pos, gsm->GN & 0x03); + pos += 2; + *pos++ = gsm->GTK_len; + if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN, pos) != 0) + return 0; + pos += 8; + os_memcpy(pos, gsm->GTK[gsm->GN - 1], gsm->GTK_len); + pos += gsm->GTK_len; + + wpa_printf(MSG_DEBUG, "WNM: GTK Key ID %u in WNM-Sleep Mode exit", + gsm->GN); + wpa_hexdump_key(MSG_DEBUG, "WNM: GTK in WNM-Sleep Mode exit", + gsm->GTK[gsm->GN - 1], gsm->GTK_len); + + return pos - start; +} + + +#ifdef CONFIG_IEEE80211W_AP +int wpa_wnmsleep_igtk_subelem(struct wpa_state_machine *sm, u8 *pos) +{ + struct wpa_group *gsm = sm->group; + u8 *start = pos; + size_t len = wpa_cipher_key_len(sm->wpa_auth->conf.group_mgmt_cipher); + + /* + * IGTK subelement: + * Sub-elem ID[1] | Length[1] | KeyID[2] | PN[6] | Key[16] + */ + *pos++ = WNM_SLEEP_SUBELEM_IGTK; + *pos++ = 2 + 6 + len; + WPA_PUT_LE16(pos, gsm->GN_igtk); + pos += 2; + if (wpa_auth_get_seqnum(sm->wpa_auth, NULL, gsm->GN_igtk, pos) != 0) + return 0; + pos += 6; + + os_memcpy(pos, gsm->IGTK[gsm->GN_igtk - 4], len); + pos += len; + + wpa_printf(MSG_DEBUG, "WNM: IGTK Key ID %u in WNM-Sleep Mode exit", + gsm->GN_igtk); + wpa_hexdump_key(MSG_DEBUG, "WNM: IGTK in WNM-Sleep Mode exit", + gsm->IGTK[gsm->GN_igtk - 4], len); + + return pos - start; +} +#endif /* CONFIG_IEEE80211W_AP */ +#endif /* CONFIG_WNM_AP */ + + +static void wpa_group_setkeys(struct wpa_authenticator *wpa_auth, + struct wpa_group *group) +{ + int tmp; + + wpa_printf(MSG_DEBUG, "WPA: group state machine entering state " + "SETKEYS (VLAN-ID %d)", group->vlan_id); + group->changed = TRUE; + group->wpa_group_state = WPA_GROUP_SETKEYS; + group->GTKReKey = FALSE; + tmp = group->GM; + group->GM = group->GN; + group->GN = tmp; +#ifdef CONFIG_IEEE80211W_AP + tmp = group->GM_igtk; + group->GM_igtk = group->GN_igtk; + group->GN_igtk = tmp; +#endif /* CONFIG_IEEE80211W_AP */ + /* "GKeyDoneStations = GNoStations" is done in more robust way by + * counting the STAs that are marked with GUpdateStationKeys instead of + * including all STAs that could be in not-yet-completed state. */ + wpa_gtk_update(wpa_auth, group); + + if (group->GKeyDoneStations) { + wpa_printf(MSG_DEBUG, "wpa_group_setkeys: Unexpected " + "GKeyDoneStations=%d when starting new GTK rekey", + group->GKeyDoneStations); + group->GKeyDoneStations = 0; + } + wpa_auth_for_each_sta(wpa_auth, wpa_group_update_sta, group); + wpa_printf(MSG_DEBUG, "wpa_group_setkeys: GKeyDoneStations=%d", + group->GKeyDoneStations); +} + + +static int wpa_group_config_group_keys(struct wpa_authenticator *wpa_auth, + struct wpa_group *group) +{ + int ret = 0; + + if (wpa_auth_set_key(wpa_auth, group->vlan_id, + wpa_cipher_to_alg(wpa_auth->conf.wpa_group), + broadcast_ether_addr, group->GN, + group->GTK[group->GN - 1], group->GTK_len) < 0) + ret = -1; + +#ifdef CONFIG_IEEE80211W_AP + if (wpa_auth->conf.ieee80211w != NO_MGMT_FRAME_PROTECTION) { + enum wpa_alg alg; + size_t len; + + alg = wpa_cipher_to_alg(wpa_auth->conf.group_mgmt_cipher); + len = wpa_cipher_key_len(wpa_auth->conf.group_mgmt_cipher); + + if (ret == 0 && + wpa_auth_set_key(wpa_auth, group->vlan_id, alg, + broadcast_ether_addr, group->GN_igtk, + group->IGTK[group->GN_igtk - 4], len) < 0) + ret = -1; + } +#endif /* CONFIG_IEEE80211W_AP */ + + return ret; +} + + +static int wpa_group_disconnect_cb(struct wpa_state_machine *sm, void *ctx) +{ + if (sm->group == ctx) { + wpa_printf(MSG_DEBUG, "WPA: Mark STA " MACSTR + " for discconnection due to fatal failure", + MAC2STR(sm->addr)); + sm->Disconnect = TRUE; + } + + return 0; +} + + +static void wpa_group_fatal_failure(struct wpa_authenticator *wpa_auth, + struct wpa_group *group) +{ + wpa_printf(MSG_DEBUG, "WPA: group state machine entering state FATAL_FAILURE"); + group->changed = TRUE; + group->wpa_group_state = WPA_GROUP_FATAL_FAILURE; + wpa_auth_for_each_sta(wpa_auth, wpa_group_disconnect_cb, group); +} + + +static int wpa_group_setkeysdone(struct wpa_authenticator *wpa_auth, + struct wpa_group *group) +{ + wpa_printf(MSG_DEBUG, "WPA: group state machine entering state " + "SETKEYSDONE (VLAN-ID %d)", group->vlan_id); + group->changed = TRUE; + group->wpa_group_state = WPA_GROUP_SETKEYSDONE; + + if (wpa_group_config_group_keys(wpa_auth, group) < 0) { + wpa_group_fatal_failure(wpa_auth, group); + return -1; + } + + return 0; +} + + +static void wpa_group_sm_step(struct wpa_authenticator *wpa_auth, + struct wpa_group *group) +{ + if (group->GInit) { + wpa_group_gtk_init(wpa_auth, group); + } else if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE) { + /* Do not allow group operations */ + } else if (group->wpa_group_state == WPA_GROUP_GTK_INIT && + group->GTKAuthenticator) { + wpa_group_setkeysdone(wpa_auth, group); + } else if (group->wpa_group_state == WPA_GROUP_SETKEYSDONE && + group->GTKReKey) { + wpa_group_setkeys(wpa_auth, group); + } else if (group->wpa_group_state == WPA_GROUP_SETKEYS) { + if (group->GKeyDoneStations == 0) + wpa_group_setkeysdone(wpa_auth, group); + else if (group->GTKReKey) + wpa_group_setkeys(wpa_auth, group); + } +} + + +static int wpa_sm_step(struct wpa_state_machine *sm) +{ + if (sm == NULL) + return 0; + + if (sm->in_step_loop) { + /* This should not happen, but if it does, make sure we do not + * end up freeing the state machine too early by exiting the + * recursive call. */ + wpa_printf(MSG_ERROR, "WPA: wpa_sm_step() called recursively"); + return 0; + } + + sm->in_step_loop = 1; + do { + if (sm->pending_deinit) + break; + + sm->changed = FALSE; + sm->wpa_auth->group->changed = FALSE; + + SM_STEP_RUN(WPA_PTK); + if (sm->pending_deinit) + break; + SM_STEP_RUN(WPA_PTK_GROUP); + if (sm->pending_deinit) + break; + wpa_group_sm_step(sm->wpa_auth, sm->group); + } while (sm->changed || sm->wpa_auth->group->changed); + sm->in_step_loop = 0; + + if (sm->pending_deinit) { + wpa_printf(MSG_DEBUG, "WPA: Completing pending STA state " + "machine deinit for " MACSTR, MAC2STR(sm->addr)); + wpa_free_sta_sm(sm); + return 1; + } + return 0; +} + + +static void wpa_sm_call_step(void *eloop_ctx, void *timeout_ctx) +{ + struct wpa_state_machine *sm = eloop_ctx; + wpa_sm_step(sm); +} + + +void wpa_auth_sm_notify(struct wpa_state_machine *sm) +{ + if (sm == NULL) + return; + eloop_register_timeout(0, 0, wpa_sm_call_step, sm, NULL); +} + + +void wpa_gtk_rekey(struct wpa_authenticator *wpa_auth) +{ + int tmp, i; + struct wpa_group *group; + + if (wpa_auth == NULL) + return; + + group = wpa_auth->group; + + for (i = 0; i < 2; i++) { + tmp = group->GM; + group->GM = group->GN; + group->GN = tmp; +#ifdef CONFIG_IEEE80211W_AP + tmp = group->GM_igtk; + group->GM_igtk = group->GN_igtk; + group->GN_igtk = tmp; +#endif /* CONFIG_IEEE80211W_AP */ + wpa_gtk_update(wpa_auth, group); + wpa_group_config_group_keys(wpa_auth, group); + } +} + + +static const char * wpa_bool_txt(int val) +{ + return val ? "TRUE" : "FALSE"; +} + + +#define RSN_SUITE "%02x-%02x-%02x-%d" +#define RSN_SUITE_ARG(s) \ +((s) >> 24) & 0xff, ((s) >> 16) & 0xff, ((s) >> 8) & 0xff, (s) & 0xff + +int wpa_get_mib(struct wpa_authenticator *wpa_auth, char *buf, size_t buflen) +{ + int len = 0, ret; + char pmkid_txt[PMKID_LEN * 2 + 1]; +#ifdef CONFIG_RSN_PREAUTH + const int preauth = 1; +#else /* CONFIG_RSN_PREAUTH */ + const int preauth = 0; +#endif /* CONFIG_RSN_PREAUTH */ + + if (wpa_auth == NULL) + return len; + + ret = os_snprintf(buf + len, buflen - len, + "dot11RSNAOptionImplemented=TRUE\n" + "dot11RSNAPreauthenticationImplemented=%s\n" + "dot11RSNAEnabled=%s\n" + "dot11RSNAPreauthenticationEnabled=%s\n", + wpa_bool_txt(preauth), + wpa_bool_txt(wpa_auth->conf.wpa & WPA_PROTO_RSN), + wpa_bool_txt(wpa_auth->conf.rsn_preauth)); + if (os_snprintf_error(buflen - len, ret)) + return len; + len += ret; + + wpa_snprintf_hex(pmkid_txt, sizeof(pmkid_txt), + wpa_auth->dot11RSNAPMKIDUsed, PMKID_LEN); + + ret = os_snprintf( + buf + len, buflen - len, + "dot11RSNAConfigVersion=%u\n" + "dot11RSNAConfigPairwiseKeysSupported=9999\n" + /* FIX: dot11RSNAConfigGroupCipher */ + /* FIX: dot11RSNAConfigGroupRekeyMethod */ + /* FIX: dot11RSNAConfigGroupRekeyTime */ + /* FIX: dot11RSNAConfigGroupRekeyPackets */ + "dot11RSNAConfigGroupRekeyStrict=%u\n" + "dot11RSNAConfigGroupUpdateCount=%u\n" + "dot11RSNAConfigPairwiseUpdateCount=%u\n" + "dot11RSNAConfigGroupCipherSize=%u\n" + "dot11RSNAConfigPMKLifetime=%u\n" + "dot11RSNAConfigPMKReauthThreshold=%u\n" + "dot11RSNAConfigNumberOfPTKSAReplayCounters=0\n" + "dot11RSNAConfigSATimeout=%u\n" + "dot11RSNAAuthenticationSuiteSelected=" RSN_SUITE "\n" + "dot11RSNAPairwiseCipherSelected=" RSN_SUITE "\n" + "dot11RSNAGroupCipherSelected=" RSN_SUITE "\n" + "dot11RSNAPMKIDUsed=%s\n" + "dot11RSNAAuthenticationSuiteRequested=" RSN_SUITE "\n" + "dot11RSNAPairwiseCipherRequested=" RSN_SUITE "\n" + "dot11RSNAGroupCipherRequested=" RSN_SUITE "\n" + "dot11RSNATKIPCounterMeasuresInvoked=%u\n" + "dot11RSNA4WayHandshakeFailures=%u\n" + "dot11RSNAConfigNumberOfGTKSAReplayCounters=0\n", + RSN_VERSION, + !!wpa_auth->conf.wpa_strict_rekey, + wpa_auth->conf.wpa_group_update_count, + wpa_auth->conf.wpa_pairwise_update_count, + wpa_cipher_key_len(wpa_auth->conf.wpa_group) * 8, + dot11RSNAConfigPMKLifetime, + dot11RSNAConfigPMKReauthThreshold, + dot11RSNAConfigSATimeout, + RSN_SUITE_ARG(wpa_auth->dot11RSNAAuthenticationSuiteSelected), + RSN_SUITE_ARG(wpa_auth->dot11RSNAPairwiseCipherSelected), + RSN_SUITE_ARG(wpa_auth->dot11RSNAGroupCipherSelected), + pmkid_txt, + RSN_SUITE_ARG(wpa_auth->dot11RSNAAuthenticationSuiteRequested), + RSN_SUITE_ARG(wpa_auth->dot11RSNAPairwiseCipherRequested), + RSN_SUITE_ARG(wpa_auth->dot11RSNAGroupCipherRequested), + wpa_auth->dot11RSNATKIPCounterMeasuresInvoked, + wpa_auth->dot11RSNA4WayHandshakeFailures); + if (os_snprintf_error(buflen - len, ret)) + return len; + len += ret; + + /* TODO: dot11RSNAConfigPairwiseCiphersTable */ + /* TODO: dot11RSNAConfigAuthenticationSuitesTable */ + + /* Private MIB */ + ret = os_snprintf(buf + len, buflen - len, "hostapdWPAGroupState=%d\n", + wpa_auth->group->wpa_group_state); + if (os_snprintf_error(buflen - len, ret)) + return len; + len += ret; + + return len; +} + + +int wpa_get_mib_sta(struct wpa_state_machine *sm, char *buf, size_t buflen) +{ + int len = 0, ret; + u32 pairwise = 0; + + if (sm == NULL) + return 0; + + /* TODO: FF-FF-FF-FF-FF-FF entry for broadcast/multicast stats */ + + /* dot11RSNAStatsEntry */ + + pairwise = wpa_cipher_to_suite(sm->wpa == WPA_VERSION_WPA2 ? + WPA_PROTO_RSN : WPA_PROTO_WPA, + sm->pairwise); + if (pairwise == 0) + return 0; + + ret = os_snprintf( + buf + len, buflen - len, + /* TODO: dot11RSNAStatsIndex */ + "dot11RSNAStatsSTAAddress=" MACSTR "\n" + "dot11RSNAStatsVersion=1\n" + "dot11RSNAStatsSelectedPairwiseCipher=" RSN_SUITE "\n" + /* TODO: dot11RSNAStatsTKIPICVErrors */ + "dot11RSNAStatsTKIPLocalMICFailures=%u\n" + "dot11RSNAStatsTKIPRemoteMICFailures=%u\n" + /* TODO: dot11RSNAStatsCCMPReplays */ + /* TODO: dot11RSNAStatsCCMPDecryptErrors */ + /* TODO: dot11RSNAStatsTKIPReplays */, + MAC2STR(sm->addr), + RSN_SUITE_ARG(pairwise), + sm->dot11RSNAStatsTKIPLocalMICFailures, + sm->dot11RSNAStatsTKIPRemoteMICFailures); + if (os_snprintf_error(buflen - len, ret)) + return len; + len += ret; + + /* Private MIB */ + ret = os_snprintf(buf + len, buflen - len, + "wpa=%d\n" + "AKMSuiteSelector=" RSN_SUITE "\n" + "hostapdWPAPTKState=%d\n" + "hostapdWPAPTKGroupState=%d\n", + sm->wpa, + RSN_SUITE_ARG(wpa_akm_to_suite(sm->wpa_key_mgmt)), + sm->wpa_ptk_state, + sm->wpa_ptk_group_state); + if (os_snprintf_error(buflen - len, ret)) + return len; + len += ret; + + return len; +} + + +void wpa_auth_countermeasures_start(struct wpa_authenticator *wpa_auth) +{ + if (wpa_auth) + wpa_auth->dot11RSNATKIPCounterMeasuresInvoked++; +} + + +int wpa_auth_pairwise_set(struct wpa_state_machine *sm) +{ + return sm && sm->pairwise_set; +} + + +int wpa_auth_get_pairwise(struct wpa_state_machine *sm) +{ + return sm->pairwise; +} + + +const u8 * wpa_auth_get_pmk(struct wpa_state_machine *sm, int *len) +{ + if (!sm) + return NULL; + *len = sm->pmk_len; + return sm->PMK; +} + + +int wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm) +{ + if (sm == NULL) + return -1; + return sm->wpa_key_mgmt; +} + + +int wpa_auth_sta_wpa_version(struct wpa_state_machine *sm) +{ + if (sm == NULL) + return 0; + return sm->wpa; +} + + +int wpa_auth_sta_ft_tk_already_set(struct wpa_state_machine *sm) +{ + if (!sm || !wpa_key_mgmt_ft(sm->wpa_key_mgmt)) + return 0; + return sm->tk_already_set; +} + + +int wpa_auth_sta_fils_tk_already_set(struct wpa_state_machine *sm) +{ + if (!sm || !wpa_key_mgmt_fils(sm->wpa_key_mgmt)) + return 0; + return sm->tk_already_set; +} + + +int wpa_auth_sta_clear_pmksa(struct wpa_state_machine *sm, + struct rsn_pmksa_cache_entry *entry) +{ + if (sm == NULL || sm->pmksa != entry) + return -1; + sm->pmksa = NULL; + return 0; +} + + +struct rsn_pmksa_cache_entry * +wpa_auth_sta_get_pmksa(struct wpa_state_machine *sm) +{ + return sm ? sm->pmksa : NULL; +} + + +void wpa_auth_sta_local_mic_failure_report(struct wpa_state_machine *sm) +{ + if (sm) + sm->dot11RSNAStatsTKIPLocalMICFailures++; +} + + +const u8 * wpa_auth_get_wpa_ie(struct wpa_authenticator *wpa_auth, size_t *len) +{ + if (wpa_auth == NULL) + return NULL; + *len = wpa_auth->wpa_ie_len; + return wpa_auth->wpa_ie; +} + + +int wpa_auth_pmksa_add(struct wpa_state_machine *sm, const u8 *pmk, + unsigned int pmk_len, + int session_timeout, struct eapol_state_machine *eapol) +{ + if (sm == NULL || sm->wpa != WPA_VERSION_WPA2 || + sm->wpa_auth->conf.disable_pmksa_caching) + return -1; + +#ifdef CONFIG_IEEE80211R_AP + if (pmk_len >= 2 * PMK_LEN && wpa_key_mgmt_ft(sm->wpa_key_mgmt) && + wpa_key_mgmt_wpa_ieee8021x(sm->wpa_key_mgmt) && + !wpa_key_mgmt_sha384(sm->wpa_key_mgmt)) { + /* Cache MPMK/XXKey instead of initial part from MSK */ + pmk = pmk + PMK_LEN; + pmk_len = PMK_LEN; + } else +#endif /* CONFIG_IEEE80211R_AP */ + if (wpa_key_mgmt_sha384(sm->wpa_key_mgmt)) { + if (pmk_len > PMK_LEN_SUITE_B_192) + pmk_len = PMK_LEN_SUITE_B_192; + } else if (pmk_len > PMK_LEN) { + pmk_len = PMK_LEN; + } + + wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK", pmk, pmk_len); + if (pmksa_cache_auth_add(sm->wpa_auth->pmksa, pmk, pmk_len, NULL, + sm->PTK.kck, sm->PTK.kck_len, + sm->wpa_auth->addr, sm->addr, session_timeout, + eapol, sm->wpa_key_mgmt)) + return 0; + + return -1; +} + + +int wpa_auth_pmksa_add_preauth(struct wpa_authenticator *wpa_auth, + const u8 *pmk, size_t len, const u8 *sta_addr, + int session_timeout, + struct eapol_state_machine *eapol) +{ + if (wpa_auth == NULL) + return -1; + + wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK from preauth", pmk, len); + if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, len, NULL, + NULL, 0, + wpa_auth->addr, + sta_addr, session_timeout, eapol, + WPA_KEY_MGMT_IEEE8021X)) + return 0; + + return -1; +} + + +int wpa_auth_pmksa_add_sae(struct wpa_authenticator *wpa_auth, const u8 *addr, + const u8 *pmk, const u8 *pmkid) +{ + if (wpa_auth->conf.disable_pmksa_caching) + return -1; + + wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK from SAE", pmk, PMK_LEN); + if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, PMK_LEN, pmkid, + NULL, 0, + wpa_auth->addr, addr, 0, NULL, + WPA_KEY_MGMT_SAE)) + return 0; + + return -1; +} + + +void wpa_auth_add_sae_pmkid(struct wpa_state_machine *sm, const u8 *pmkid) +{ + os_memcpy(sm->pmkid, pmkid, PMKID_LEN); + sm->pmkid_set = 1; +} + + +int wpa_auth_pmksa_add2(struct wpa_authenticator *wpa_auth, const u8 *addr, + const u8 *pmk, size_t pmk_len, const u8 *pmkid, + int session_timeout, int akmp) +{ + if (wpa_auth->conf.disable_pmksa_caching) + return -1; + + wpa_hexdump_key(MSG_DEBUG, "RSN: Cache PMK (2)", pmk, PMK_LEN); + if (pmksa_cache_auth_add(wpa_auth->pmksa, pmk, pmk_len, pmkid, + NULL, 0, wpa_auth->addr, addr, session_timeout, + NULL, akmp)) + return 0; + + return -1; +} + + +void wpa_auth_pmksa_remove(struct wpa_authenticator *wpa_auth, + const u8 *sta_addr) +{ + struct rsn_pmksa_cache_entry *pmksa; + + if (wpa_auth == NULL || wpa_auth->pmksa == NULL) + return; + pmksa = pmksa_cache_auth_get(wpa_auth->pmksa, sta_addr, NULL); + if (pmksa) { + wpa_printf(MSG_DEBUG, "WPA: Remove PMKSA cache entry for " + MACSTR " based on request", MAC2STR(sta_addr)); + pmksa_cache_free_entry(wpa_auth->pmksa, pmksa); + } +} + + +int wpa_auth_pmksa_list(struct wpa_authenticator *wpa_auth, char *buf, + size_t len) +{ + if (!wpa_auth || !wpa_auth->pmksa) + return 0; + return pmksa_cache_auth_list(wpa_auth->pmksa, buf, len); +} + + +void wpa_auth_pmksa_flush(struct wpa_authenticator *wpa_auth) +{ + if (wpa_auth && wpa_auth->pmksa) + pmksa_cache_auth_flush(wpa_auth->pmksa); +} + + +#ifdef CONFIG_PMKSA_CACHE_EXTERNAL +#ifdef CONFIG_MESH + +int wpa_auth_pmksa_list_mesh(struct wpa_authenticator *wpa_auth, const u8 *addr, + char *buf, size_t len) +{ + if (!wpa_auth || !wpa_auth->pmksa) + return 0; + + return pmksa_cache_auth_list_mesh(wpa_auth->pmksa, addr, buf, len); +} + + +struct rsn_pmksa_cache_entry * +wpa_auth_pmksa_create_entry(const u8 *aa, const u8 *spa, const u8 *pmk, + const u8 *pmkid, int expiration) +{ + struct rsn_pmksa_cache_entry *entry; + struct os_reltime now; + + entry = pmksa_cache_auth_create_entry(pmk, PMK_LEN, pmkid, NULL, 0, aa, + spa, 0, NULL, WPA_KEY_MGMT_SAE); + if (!entry) + return NULL; + + os_get_reltime(&now); + entry->expiration = now.sec + expiration; + return entry; +} + + +int wpa_auth_pmksa_add_entry(struct wpa_authenticator *wpa_auth, + struct rsn_pmksa_cache_entry *entry) +{ + int ret; + + if (!wpa_auth || !wpa_auth->pmksa) + return -1; + + ret = pmksa_cache_auth_add_entry(wpa_auth->pmksa, entry); + if (ret < 0) + wpa_printf(MSG_DEBUG, + "RSN: Failed to store external PMKSA cache for " + MACSTR, MAC2STR(entry->spa)); + + return ret; +} + +#endif /* CONFIG_MESH */ +#endif /* CONFIG_PMKSA_CACHE_EXTERNAL */ + + +struct rsn_pmksa_cache_entry * +wpa_auth_pmksa_get(struct wpa_authenticator *wpa_auth, const u8 *sta_addr, + const u8 *pmkid) +{ + if (!wpa_auth || !wpa_auth->pmksa) + return NULL; + return pmksa_cache_auth_get(wpa_auth->pmksa, sta_addr, pmkid); +} + + +void wpa_auth_pmksa_set_to_sm(struct rsn_pmksa_cache_entry *pmksa, + struct wpa_state_machine *sm, + struct wpa_authenticator *wpa_auth, + u8 *pmkid, u8 *pmk) +{ + if (!sm) + return; + + sm->pmksa = pmksa; + os_memcpy(pmk, pmksa->pmk, PMK_LEN); + os_memcpy(pmkid, pmksa->pmkid, PMKID_LEN); + os_memcpy(wpa_auth->dot11RSNAPMKIDUsed, pmksa->pmkid, PMKID_LEN); +} + + +/* + * Remove and free the group from wpa_authenticator. This is triggered by a + * callback to make sure nobody is currently iterating the group list while it + * gets modified. + */ +static void wpa_group_free(struct wpa_authenticator *wpa_auth, + struct wpa_group *group) +{ + struct wpa_group *prev = wpa_auth->group; + + wpa_printf(MSG_DEBUG, "WPA: Remove group state machine for VLAN-ID %d", + group->vlan_id); + + while (prev) { + if (prev->next == group) { + /* This never frees the special first group as needed */ + prev->next = group->next; + os_free(group); + break; + } + prev = prev->next; + } + +} + + +/* Increase the reference counter for group */ +static void wpa_group_get(struct wpa_authenticator *wpa_auth, + struct wpa_group *group) +{ + /* Skip the special first group */ + if (wpa_auth->group == group) + return; + + group->references++; +} + + +/* Decrease the reference counter and maybe free the group */ +static void wpa_group_put(struct wpa_authenticator *wpa_auth, + struct wpa_group *group) +{ + /* Skip the special first group */ + if (wpa_auth->group == group) + return; + + group->references--; + if (group->references) + return; + wpa_group_free(wpa_auth, group); +} + + +/* + * Add a group that has its references counter set to zero. Caller needs to + * call wpa_group_get() on the return value to mark the entry in use. + */ +static struct wpa_group * +wpa_auth_add_group(struct wpa_authenticator *wpa_auth, int vlan_id) +{ + struct wpa_group *group; + + if (wpa_auth == NULL || wpa_auth->group == NULL) + return NULL; + + wpa_printf(MSG_DEBUG, "WPA: Add group state machine for VLAN-ID %d", + vlan_id); + group = wpa_group_init(wpa_auth, vlan_id, 0); + if (group == NULL) + return NULL; + + group->next = wpa_auth->group->next; + wpa_auth->group->next = group; + + return group; +} + + +/* + * Enforce that the group state machine for the VLAN is running, increase + * reference counter as interface is up. References might have been increased + * even if a negative value is returned. + * Returns: -1 on error (group missing, group already failed); otherwise, 0 + */ +int wpa_auth_ensure_group(struct wpa_authenticator *wpa_auth, int vlan_id) +{ + struct wpa_group *group; + + if (wpa_auth == NULL) + return 0; + + group = wpa_auth->group; + while (group) { + if (group->vlan_id == vlan_id) + break; + group = group->next; + } + + if (group == NULL) { + group = wpa_auth_add_group(wpa_auth, vlan_id); + if (group == NULL) + return -1; + } + + wpa_printf(MSG_DEBUG, + "WPA: Ensure group state machine running for VLAN ID %d", + vlan_id); + + wpa_group_get(wpa_auth, group); + group->num_setup_iface++; + + if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE) + return -1; + + return 0; +} + + +/* + * Decrease reference counter, expected to be zero afterwards. + * returns: -1 on error (group not found, group in fail state) + * -2 if wpa_group is still referenced + * 0 else + */ +int wpa_auth_release_group(struct wpa_authenticator *wpa_auth, int vlan_id) +{ + struct wpa_group *group; + int ret = 0; + + if (wpa_auth == NULL) + return 0; + + group = wpa_auth->group; + while (group) { + if (group->vlan_id == vlan_id) + break; + group = group->next; + } + + if (group == NULL) + return -1; + + wpa_printf(MSG_DEBUG, + "WPA: Try stopping group state machine for VLAN ID %d", + vlan_id); + + if (group->num_setup_iface <= 0) { + wpa_printf(MSG_ERROR, + "WPA: wpa_auth_release_group called more often than wpa_auth_ensure_group for VLAN ID %d, skipping.", + vlan_id); + return -1; + } + group->num_setup_iface--; + + if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE) + ret = -1; + + if (group->references > 1) { + wpa_printf(MSG_DEBUG, + "WPA: Cannot stop group state machine for VLAN ID %d as references are still hold", + vlan_id); + ret = -2; + } + + wpa_group_put(wpa_auth, group); + + return ret; +} + + +int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id) +{ + struct wpa_group *group; + + if (sm == NULL || sm->wpa_auth == NULL) + return 0; + + group = sm->wpa_auth->group; + while (group) { + if (group->vlan_id == vlan_id) + break; + group = group->next; + } + + if (group == NULL) { + group = wpa_auth_add_group(sm->wpa_auth, vlan_id); + if (group == NULL) + return -1; + } + + if (sm->group == group) + return 0; + + if (group->wpa_group_state == WPA_GROUP_FATAL_FAILURE) + return -1; + + wpa_printf(MSG_DEBUG, "WPA: Moving STA " MACSTR " to use group state " + "machine for VLAN ID %d", MAC2STR(sm->addr), vlan_id); + + wpa_group_get(sm->wpa_auth, group); + wpa_group_put(sm->wpa_auth, sm->group); + sm->group = group; + + return 0; +} + + +void wpa_auth_eapol_key_tx_status(struct wpa_authenticator *wpa_auth, + struct wpa_state_machine *sm, int ack) +{ + if (wpa_auth == NULL || sm == NULL) + return; + wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key TX status for STA " MACSTR + " ack=%d", MAC2STR(sm->addr), ack); + if (sm->pending_1_of_4_timeout && ack) { + /* + * Some deployed supplicant implementations update their SNonce + * for each EAPOL-Key 2/4 message even within the same 4-way + * handshake and then fail to use the first SNonce when + * deriving the PTK. This results in unsuccessful 4-way + * handshake whenever the relatively short initial timeout is + * reached and EAPOL-Key 1/4 is retransmitted. Try to work + * around this by increasing the timeout now that we know that + * the station has received the frame. + */ + int timeout_ms = eapol_key_timeout_subseq; + wpa_printf(MSG_DEBUG, "WPA: Increase initial EAPOL-Key 1/4 " + "timeout by %u ms because of acknowledged frame", + timeout_ms); + eloop_cancel_timeout(wpa_send_eapol_timeout, wpa_auth, sm); + eloop_register_timeout(timeout_ms / 1000, + (timeout_ms % 1000) * 1000, + wpa_send_eapol_timeout, wpa_auth, sm); + } + +#ifdef CONFIG_TESTING_OPTIONS + if (sm->eapol_status_cb) { + sm->eapol_status_cb(sm->eapol_status_cb_ctx1, + sm->eapol_status_cb_ctx2); + sm->eapol_status_cb = NULL; + } +#endif /* CONFIG_TESTING_OPTIONS */ +} + + +int wpa_auth_uses_sae(struct wpa_state_machine *sm) +{ + if (sm == NULL) + return 0; + return wpa_key_mgmt_sae(sm->wpa_key_mgmt); +} + + +int wpa_auth_uses_ft_sae(struct wpa_state_machine *sm) +{ + if (sm == NULL) + return 0; + return sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_SAE; +} + + +#ifdef CONFIG_P2P +int wpa_auth_get_ip_addr(struct wpa_state_machine *sm, u8 *addr) +{ + if (sm == NULL || WPA_GET_BE32(sm->ip_addr) == 0) + return -1; + os_memcpy(addr, sm->ip_addr, 4); + return 0; +} +#endif /* CONFIG_P2P */ + + +#ifdef CONFIG_RADIUS +int wpa_auth_radius_das_disconnect_pmksa(struct wpa_authenticator *wpa_auth, + struct radius_das_attrs *attr) +{ + return pmksa_cache_auth_radius_das_disconnect(wpa_auth->pmksa, attr); +} +#endif + + +void wpa_auth_reconfig_group_keys(struct wpa_authenticator *wpa_auth) +{ + struct wpa_group *group; + + if (!wpa_auth) + return; + for (group = wpa_auth->group; group; group = group->next) + wpa_group_config_group_keys(wpa_auth, group); +} + + +#ifdef CONFIG_FILS + +struct wpa_auth_fils_iter_data { + struct wpa_authenticator *auth; + const u8 *cache_id; + struct rsn_pmksa_cache_entry *pmksa; + const u8 *spa; + const u8 *pmkid; +}; + + +static int wpa_auth_fils_iter(struct wpa_authenticator *a, void *ctx) +{ + struct wpa_auth_fils_iter_data *data = ctx; + + if (a == data->auth || !a->conf.fils_cache_id_set || + os_memcmp(a->conf.fils_cache_id, data->cache_id, + FILS_CACHE_ID_LEN) != 0) + return 0; + data->pmksa = pmksa_cache_auth_get(a->pmksa, data->spa, data->pmkid); + return data->pmksa != NULL; +} + + +struct rsn_pmksa_cache_entry * +wpa_auth_pmksa_get_fils_cache_id(struct wpa_authenticator *wpa_auth, + const u8 *sta_addr, const u8 *pmkid) +{ + struct wpa_auth_fils_iter_data idata; + + if (!wpa_auth->conf.fils_cache_id_set) + return NULL; + idata.auth = wpa_auth; + idata.cache_id = wpa_auth->conf.fils_cache_id; + idata.pmksa = NULL; + idata.spa = sta_addr; + idata.pmkid = pmkid; + wpa_auth_for_each_auth(wpa_auth, wpa_auth_fils_iter, &idata); + return idata.pmksa; +} + + +#ifdef CONFIG_IEEE80211R_AP +int wpa_auth_write_fte(struct wpa_authenticator *wpa_auth, int use_sha384, + u8 *buf, size_t len) +{ + struct wpa_auth_config *conf = &wpa_auth->conf; + + return wpa_write_ftie(conf, use_sha384, conf->r0_key_holder, + conf->r0_key_holder_len, + NULL, NULL, buf, len, NULL, 0); +} +#endif /* CONFIG_IEEE80211R_AP */ + + +void wpa_auth_get_fils_aead_params(struct wpa_state_machine *sm, + u8 *fils_anonce, u8 *fils_snonce, + u8 *fils_kek, size_t *fils_kek_len) +{ + os_memcpy(fils_anonce, sm->ANonce, WPA_NONCE_LEN); + os_memcpy(fils_snonce, sm->SNonce, WPA_NONCE_LEN); + os_memcpy(fils_kek, sm->PTK.kek, WPA_KEK_MAX_LEN); + *fils_kek_len = sm->PTK.kek_len; +} + + +void wpa_auth_add_fils_pmk_pmkid(struct wpa_state_machine *sm, const u8 *pmk, + size_t pmk_len, const u8 *pmkid) +{ + os_memcpy(sm->PMK, pmk, pmk_len); + sm->pmk_len = pmk_len; + os_memcpy(sm->pmkid, pmkid, PMKID_LEN); + sm->pmkid_set = 1; +} + +#endif /* CONFIG_FILS */ + + +void wpa_auth_set_auth_alg(struct wpa_state_machine *sm, u16 auth_alg) +{ + if (sm) + sm->auth_alg = auth_alg; +} + + +#ifdef CONFIG_DPP2 +void wpa_auth_set_dpp_z(struct wpa_state_machine *sm, const struct wpabuf *z) +{ + if (sm) { + wpabuf_clear_free(sm->dpp_z); + sm->dpp_z = z ? wpabuf_dup(z) : NULL; + } +} +#endif /* CONFIG_DPP2 */ diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/wpa_auth.h b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/wpa_auth.h new file mode 100755 index 0000000..5cf9b7b --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/wpa_auth.h @@ -0,0 +1,496 @@ +/* + * hostapd - IEEE 802.11i-2004 / WPA Authenticator + * Copyright (c) 2004-2017, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef WPA_AUTH_H +#define WPA_AUTH_H + +#include "common/defs.h" +#include "common/eapol_common.h" +#include "common/wpa_common.h" +#include "common/ieee802_11_defs.h" + +struct vlan_description; + +#define MAX_OWN_IE_OVERRIDE 256 + +#ifdef _MSC_VER +#pragma pack(push, 1) +#endif /* _MSC_VER */ + +/* IEEE Std 802.11r-2008, 11A.10.3 - Remote request/response frame definition + */ +struct ft_rrb_frame { + u8 frame_type; /* RSN_REMOTE_FRAME_TYPE_FT_RRB */ + u8 packet_type; /* FT_PACKET_REQUEST/FT_PACKET_RESPONSE */ + le16 action_length; /* little endian length of action_frame */ + u8 ap_address[ETH_ALEN]; + /* + * Followed by action_length bytes of FT Action frame (from Category + * field to the end of Action Frame body. + */ +} STRUCT_PACKED; + +#define RSN_REMOTE_FRAME_TYPE_FT_RRB 1 + +#define FT_PACKET_REQUEST 0 +#define FT_PACKET_RESPONSE 1 + +/* Vendor-specific types for R0KH-R1KH protocol; not defined in 802.11r. These + * use OUI Extended EtherType as the encapsulating format. */ +#define FT_PACKET_R0KH_R1KH_PULL 0x01 +#define FT_PACKET_R0KH_R1KH_RESP 0x02 +#define FT_PACKET_R0KH_R1KH_PUSH 0x03 +#define FT_PACKET_R0KH_R1KH_SEQ_REQ 0x04 +#define FT_PACKET_R0KH_R1KH_SEQ_RESP 0x05 + +/* packet layout + * IEEE 802 extended OUI ethertype frame header + * u16 authlen (little endian) + * multiple of struct ft_rrb_tlv (authenticated only, length = authlen) + * multiple of struct ft_rrb_tlv (AES-SIV encrypted, AES-SIV needs an extra + * blocksize length) + * + * AES-SIV AAD; + * source MAC address (6) + * authenticated-only TLVs (authlen) + * subtype (1; FT_PACKET_*) + */ + +#define FT_RRB_NONCE_LEN 16 + +#define FT_RRB_LAST_EMPTY 0 /* placeholder or padding */ + +#define FT_RRB_SEQ 1 /* struct ft_rrb_seq */ +#define FT_RRB_NONCE 2 /* size FT_RRB_NONCE_LEN */ +#define FT_RRB_TIMESTAMP 3 /* le32 unix seconds */ + +#define FT_RRB_R0KH_ID 4 /* FT_R0KH_ID_MAX_LEN */ +#define FT_RRB_R1KH_ID 5 /* FT_R1KH_ID_LEN */ +#define FT_RRB_S1KH_ID 6 /* ETH_ALEN */ + +#define FT_RRB_PMK_R0_NAME 7 /* WPA_PMK_NAME_LEN */ +#define FT_RRB_PMK_R0 8 /* PMK_LEN */ +#define FT_RRB_PMK_R1_NAME 9 /* WPA_PMK_NAME_LEN */ +#define FT_RRB_PMK_R1 10 /* PMK_LEN */ + +#define FT_RRB_PAIRWISE 11 /* le16 */ +#define FT_RRB_EXPIRES_IN 12 /* le16 seconds */ + +#define FT_RRB_VLAN_UNTAGGED 13 /* le16 */ +#define FT_RRB_VLAN_TAGGED 14 /* n times le16 */ + +#define FT_RRB_IDENTITY 15 +#define FT_RRB_RADIUS_CUI 16 +#define FT_RRB_SESSION_TIMEOUT 17 /* le32 seconds */ + +struct ft_rrb_tlv { + le16 type; + le16 len; + /* followed by data of length len */ +} STRUCT_PACKED; + +struct ft_rrb_seq { + le32 dom; + le32 seq; + le32 ts; +} STRUCT_PACKED; + +/* session TLVs: + * required: PMK_R1, PMK_R1_NAME, PAIRWISE + * optional: VLAN_UNTAGGED, VLAN_TAGGED, EXPIRES_IN, IDENTITY, RADIUS_CUI, + * SESSION_TIMEOUT + * + * pull frame TLVs: + * auth: + * required: SEQ, NONCE, R0KH_ID, R1KH_ID + * encrypted: + * required: PMK_R0_NAME, S1KH_ID + * + * response frame TLVs: + * auth: + * required: SEQ, NONCE, R0KH_ID, R1KH_ID + * encrypted: + * required: S1KH_ID + * optional: session TLVs + * + * push frame TLVs: + * auth: + * required: SEQ, R0KH_ID, R1KH_ID + * encrypted: + * required: S1KH_ID, PMK_R0_NAME, session TLVs + * + * sequence number request frame TLVs: + * auth: + * required: R0KH_ID, R1KH_ID, NONCE + * + * sequence number response frame TLVs: + * auth: + * required: SEQ, NONCE, R0KH_ID, R1KH_ID + */ + +#ifdef _MSC_VER +#pragma pack(pop) +#endif /* _MSC_VER */ + + +/* per STA state machine data */ + +struct wpa_authenticator; +struct wpa_state_machine; +struct rsn_pmksa_cache_entry; +struct eapol_state_machine; +struct ft_remote_seq; +struct wpa_channel_info; + + +struct ft_remote_r0kh { + struct ft_remote_r0kh *next; + u8 addr[ETH_ALEN]; + u8 id[FT_R0KH_ID_MAX_LEN]; + size_t id_len; + u8 key[32]; + struct ft_remote_seq *seq; +}; + + +struct ft_remote_r1kh { + struct ft_remote_r1kh *next; + u8 addr[ETH_ALEN]; + u8 id[FT_R1KH_ID_LEN]; + u8 key[32]; + struct ft_remote_seq *seq; +}; + + +struct wpa_auth_config { + int wpa; + int wpa_key_mgmt; + int wpa_pairwise; + int wpa_group; + int wpa_group_rekey; + int wpa_strict_rekey; + int wpa_gmk_rekey; + int wpa_ptk_rekey; + u32 wpa_group_update_count; + u32 wpa_pairwise_update_count; + int wpa_disable_eapol_key_retries; + int rsn_pairwise; + int rsn_preauth; + int eapol_version; + int wmm_enabled; + int wmm_uapsd; + int disable_pmksa_caching; + int okc; + int tx_status; +#ifdef CONFIG_IEEE80211W_AP + enum mfp_options ieee80211w; + int group_mgmt_cipher; + int sae_require_mfp; +#endif /* CONFIG_IEEE80211W_AP */ +#ifdef CONFIG_OCV + int ocv; /* Operating Channel Validation */ +#endif /* CONFIG_OCV */ +#ifdef CONFIG_IEEE80211R_AP + u8 ssid[SSID_MAX_LEN]; + size_t ssid_len; + u8 mobility_domain[MOBILITY_DOMAIN_ID_LEN]; + u8 r0_key_holder[FT_R0KH_ID_MAX_LEN]; + size_t r0_key_holder_len; + u8 r1_key_holder[FT_R1KH_ID_LEN]; + u32 r0_key_lifetime; /* PMK-R0 lifetime seconds */ + int rkh_pos_timeout; + int rkh_neg_timeout; + int rkh_pull_timeout; /* ms */ + int rkh_pull_retries; + int r1_max_key_lifetime; + u32 reassociation_deadline; + struct ft_remote_r0kh **r0kh_list; + struct ft_remote_r1kh **r1kh_list; + int pmk_r1_push; + int ft_over_ds; + int ft_psk_generate_local; +#endif /* CONFIG_IEEE80211R_AP */ + int disable_gtk; + int ap_mlme; +#ifdef CONFIG_TESTING_OPTIONS + double corrupt_gtk_rekey_mic_probability; + u8 own_ie_override[MAX_OWN_IE_OVERRIDE]; + size_t own_ie_override_len; +#endif /* CONFIG_TESTING_OPTIONS */ +#ifdef CONFIG_P2P + u8 ip_addr_go[4]; + u8 ip_addr_mask[4]; + u8 ip_addr_start[4]; + u8 ip_addr_end[4]; +#endif /* CONFIG_P2P */ +#ifdef CONFIG_FILS + unsigned int fils_cache_id_set:1; + u8 fils_cache_id[FILS_CACHE_ID_LEN]; +#endif /* CONFIG_FILS */ +}; + +typedef enum { + LOGGER_DEBUG, LOGGER_INFO, LOGGER_WARNING +} logger_level; + +typedef enum { + WPA_EAPOL_portEnabled, WPA_EAPOL_portValid, WPA_EAPOL_authorized, + WPA_EAPOL_portControl_Auto, WPA_EAPOL_keyRun, WPA_EAPOL_keyAvailable, + WPA_EAPOL_keyDone, WPA_EAPOL_inc_EapolFramesTx +} wpa_eapol_variable; + +struct wpa_auth_callbacks { + void (*logger)(void *ctx, const u8 *addr, logger_level level, + const char *txt); + void (*disconnect)(void *ctx, const u8 *addr, u16 reason); + int (*mic_failure_report)(void *ctx, const u8 *addr); + void (*psk_failure_report)(void *ctx, const u8 *addr); + void (*set_eapol)(void *ctx, const u8 *addr, wpa_eapol_variable var, + int value); + int (*get_eapol)(void *ctx, const u8 *addr, wpa_eapol_variable var); + const u8 * (*get_psk)(void *ctx, const u8 *addr, const u8 *p2p_dev_addr, + const u8 *prev_psk, size_t *psk_len, + int *vlan_id); + int (*get_msk)(void *ctx, const u8 *addr, u8 *msk, size_t *len); + int (*set_key)(void *ctx, int vlan_id, enum wpa_alg alg, + const u8 *addr, int idx, u8 *key, size_t key_len); + int (*get_seqnum)(void *ctx, const u8 *addr, int idx, u8 *seq); + int (*send_eapol)(void *ctx, const u8 *addr, const u8 *data, + size_t data_len, int encrypt); + int (*for_each_sta)(void *ctx, int (*cb)(struct wpa_state_machine *sm, + void *ctx), void *cb_ctx); + int (*for_each_auth)(void *ctx, int (*cb)(struct wpa_authenticator *a, + void *ctx), void *cb_ctx); + int (*send_ether)(void *ctx, const u8 *dst, u16 proto, const u8 *data, + size_t data_len); + int (*send_oui)(void *ctx, const u8 *dst, u8 oui_suffix, const u8 *data, + size_t data_len); + int (*channel_info)(void *ctx, struct wpa_channel_info *ci); + int (*update_vlan)(void *ctx, const u8 *addr, int vlan_id); + int (*get_sta_tx_params)(void *ctx, const u8 *addr, + int ap_max_chanwidth, int ap_seg1_idx, + int *bandwidth, int *seg1_idx); +#ifdef CONFIG_IEEE80211R_AP + struct wpa_state_machine * (*add_sta)(void *ctx, const u8 *sta_addr); + int (*set_vlan)(void *ctx, const u8 *sta_addr, + struct vlan_description *vlan); + int (*get_vlan)(void *ctx, const u8 *sta_addr, + struct vlan_description *vlan); + int (*set_identity)(void *ctx, const u8 *sta_addr, + const u8 *identity, size_t identity_len); + size_t (*get_identity)(void *ctx, const u8 *sta_addr, const u8 **buf); + int (*set_radius_cui)(void *ctx, const u8 *sta_addr, + const u8 *radius_cui, size_t radius_cui_len); + size_t (*get_radius_cui)(void *ctx, const u8 *sta_addr, const u8 **buf); + void (*set_session_timeout)(void *ctx, const u8 *sta_addr, + int session_timeout); + int (*get_session_timeout)(void *ctx, const u8 *sta_addr); + + int (*send_ft_action)(void *ctx, const u8 *dst, + const u8 *data, size_t data_len); + int (*add_tspec)(void *ctx, const u8 *sta_addr, u8 *tspec_ie, + size_t tspec_ielen); +#endif /* CONFIG_IEEE80211R_AP */ +#ifdef CONFIG_MESH + int (*start_ampe)(void *ctx, const u8 *sta_addr); +#endif /* CONFIG_MESH */ +}; + +struct wpa_authenticator * wpa_init(const u8 *addr, + struct wpa_auth_config *conf, + const struct wpa_auth_callbacks *cb, + void *cb_ctx); +int wpa_init_keys(struct wpa_authenticator *wpa_auth); +void wpa_deinit(struct wpa_authenticator *wpa_auth); +int wpa_reconfig(struct wpa_authenticator *wpa_auth, + struct wpa_auth_config *conf); + +enum { + WPA_IE_OK, WPA_INVALID_IE, WPA_INVALID_GROUP, WPA_INVALID_PAIRWISE, + WPA_INVALID_AKMP, WPA_NOT_ENABLED, WPA_ALLOC_FAIL, + WPA_MGMT_FRAME_PROTECTION_VIOLATION, WPA_INVALID_MGMT_GROUP_CIPHER, + WPA_INVALID_MDIE, WPA_INVALID_PROTO, WPA_INVALID_PMKID +}; + +int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, + struct wpa_state_machine *sm, int freq, + const u8 *wpa_ie, size_t wpa_ie_len, + const u8 *mdie, size_t mdie_len, + const u8 *owe_dh, size_t owe_dh_len); +int wpa_validate_osen(struct wpa_authenticator *wpa_auth, + struct wpa_state_machine *sm, + const u8 *osen_ie, size_t osen_ie_len); +int wpa_auth_uses_mfp(struct wpa_state_machine *sm); +void wpa_auth_set_ocv(struct wpa_state_machine *sm, int ocv); +int wpa_auth_uses_ocv(struct wpa_state_machine *sm); +struct wpa_state_machine * +wpa_auth_sta_init(struct wpa_authenticator *wpa_auth, const u8 *addr, + const u8 *p2p_dev_addr); +int wpa_auth_sta_associated(struct wpa_authenticator *wpa_auth, + struct wpa_state_machine *sm); +void wpa_auth_sta_no_wpa(struct wpa_state_machine *sm); +void wpa_auth_sta_deinit(struct wpa_state_machine *sm); +void wpa_receive(struct wpa_authenticator *wpa_auth, + struct wpa_state_machine *sm, + u8 *data, size_t data_len); +enum wpa_event { + WPA_AUTH, WPA_ASSOC, WPA_DISASSOC, WPA_DEAUTH, WPA_REAUTH, + WPA_REAUTH_EAPOL, WPA_ASSOC_FT, WPA_ASSOC_FILS, WPA_DRV_STA_REMOVED +}; +void wpa_remove_ptk(struct wpa_state_machine *sm); +int wpa_auth_sm_event(struct wpa_state_machine *sm, enum wpa_event event); +void wpa_auth_sm_notify(struct wpa_state_machine *sm); +void wpa_gtk_rekey(struct wpa_authenticator *wpa_auth); +int wpa_get_mib(struct wpa_authenticator *wpa_auth, char *buf, size_t buflen); +int wpa_get_mib_sta(struct wpa_state_machine *sm, char *buf, size_t buflen); +void wpa_auth_countermeasures_start(struct wpa_authenticator *wpa_auth); +int wpa_auth_pairwise_set(struct wpa_state_machine *sm); +int wpa_auth_get_pairwise(struct wpa_state_machine *sm); +const u8 * wpa_auth_get_pmk(struct wpa_state_machine *sm, int *len); +int wpa_auth_sta_key_mgmt(struct wpa_state_machine *sm); +int wpa_auth_sta_wpa_version(struct wpa_state_machine *sm); +int wpa_auth_sta_ft_tk_already_set(struct wpa_state_machine *sm); +int wpa_auth_sta_fils_tk_already_set(struct wpa_state_machine *sm); +int wpa_auth_sta_clear_pmksa(struct wpa_state_machine *sm, + struct rsn_pmksa_cache_entry *entry); +struct rsn_pmksa_cache_entry * +wpa_auth_sta_get_pmksa(struct wpa_state_machine *sm); +void wpa_auth_sta_local_mic_failure_report(struct wpa_state_machine *sm); +const u8 * wpa_auth_get_wpa_ie(struct wpa_authenticator *wpa_auth, + size_t *len); +int wpa_auth_pmksa_add(struct wpa_state_machine *sm, const u8 *pmk, + unsigned int pmk_len, + int session_timeout, struct eapol_state_machine *eapol); +int wpa_auth_pmksa_add_preauth(struct wpa_authenticator *wpa_auth, + const u8 *pmk, size_t len, const u8 *sta_addr, + int session_timeout, + struct eapol_state_machine *eapol); +int wpa_auth_pmksa_add_sae(struct wpa_authenticator *wpa_auth, const u8 *addr, + const u8 *pmk, const u8 *pmkid); +void wpa_auth_add_sae_pmkid(struct wpa_state_machine *sm, const u8 *pmkid); +int wpa_auth_pmksa_add2(struct wpa_authenticator *wpa_auth, const u8 *addr, + const u8 *pmk, size_t pmk_len, const u8 *pmkid, + int session_timeout, int akmp); +void wpa_auth_pmksa_remove(struct wpa_authenticator *wpa_auth, + const u8 *sta_addr); +int wpa_auth_pmksa_list(struct wpa_authenticator *wpa_auth, char *buf, + size_t len); +void wpa_auth_pmksa_flush(struct wpa_authenticator *wpa_auth); +int wpa_auth_pmksa_list_mesh(struct wpa_authenticator *wpa_auth, const u8 *addr, + char *buf, size_t len); +struct rsn_pmksa_cache_entry * +wpa_auth_pmksa_create_entry(const u8 *aa, const u8 *spa, const u8 *pmk, + const u8 *pmkid, int expiration); +int wpa_auth_pmksa_add_entry(struct wpa_authenticator *wpa_auth, + struct rsn_pmksa_cache_entry *entry); +struct rsn_pmksa_cache_entry * +wpa_auth_pmksa_get(struct wpa_authenticator *wpa_auth, const u8 *sta_addr, + const u8 *pmkid); +struct rsn_pmksa_cache_entry * +wpa_auth_pmksa_get_fils_cache_id(struct wpa_authenticator *wpa_auth, + const u8 *sta_addr, const u8 *pmkid); +void wpa_auth_pmksa_set_to_sm(struct rsn_pmksa_cache_entry *pmksa, + struct wpa_state_machine *sm, + struct wpa_authenticator *wpa_auth, + u8 *pmkid, u8 *pmk); +int wpa_auth_sta_set_vlan(struct wpa_state_machine *sm, int vlan_id); +void wpa_auth_eapol_key_tx_status(struct wpa_authenticator *wpa_auth, + struct wpa_state_machine *sm, int ack); + +#ifdef CONFIG_IEEE80211R_AP +u8 * wpa_sm_write_assoc_resp_ies(struct wpa_state_machine *sm, u8 *pos, + size_t max_len, int auth_alg, + const u8 *req_ies, size_t req_ies_len); +void wpa_ft_process_auth(struct wpa_state_machine *sm, const u8 *bssid, + u16 auth_transaction, const u8 *ies, size_t ies_len, + void (*cb)(void *ctx, const u8 *dst, const u8 *bssid, + u16 auth_transaction, u16 resp, + const u8 *ies, size_t ies_len), + void *ctx); +u16 wpa_ft_validate_reassoc(struct wpa_state_machine *sm, const u8 *ies, + size_t ies_len); +int wpa_ft_action_rx(struct wpa_state_machine *sm, const u8 *data, size_t len); +int wpa_ft_rrb_rx(struct wpa_authenticator *wpa_auth, const u8 *src_addr, + const u8 *data, size_t data_len); +void wpa_ft_rrb_oui_rx(struct wpa_authenticator *wpa_auth, const u8 *src_addr, + const u8 *dst_addr, u8 oui_suffix, const u8 *data, + size_t data_len); +void wpa_ft_push_pmk_r1(struct wpa_authenticator *wpa_auth, const u8 *addr); +void wpa_ft_deinit(struct wpa_authenticator *wpa_auth); +void wpa_ft_sta_deinit(struct wpa_state_machine *sm); +#endif /* CONFIG_IEEE80211R_AP */ + +void wpa_wnmsleep_rekey_gtk(struct wpa_state_machine *sm); +void wpa_set_wnmsleep(struct wpa_state_machine *sm, int flag); +int wpa_wnmsleep_gtk_subelem(struct wpa_state_machine *sm, u8 *pos); +int wpa_wnmsleep_igtk_subelem(struct wpa_state_machine *sm, u8 *pos); + +int wpa_auth_uses_sae(struct wpa_state_machine *sm); +int wpa_auth_uses_ft_sae(struct wpa_state_machine *sm); + +int wpa_auth_get_ip_addr(struct wpa_state_machine *sm, u8 *addr); + +struct radius_das_attrs; +int wpa_auth_radius_das_disconnect_pmksa(struct wpa_authenticator *wpa_auth, + struct radius_das_attrs *attr); +void wpa_auth_reconfig_group_keys(struct wpa_authenticator *wpa_auth); + +int wpa_auth_ensure_group(struct wpa_authenticator *wpa_auth, int vlan_id); +int wpa_auth_release_group(struct wpa_authenticator *wpa_auth, int vlan_id); +int fils_auth_pmk_to_ptk(struct wpa_state_machine *sm, const u8 *pmk, + size_t pmk_len, const u8 *snonce, const u8 *anonce, + const u8 *dhss, size_t dhss_len, + struct wpabuf *g_sta, struct wpabuf *g_ap); +int fils_decrypt_assoc(struct wpa_state_machine *sm, const u8 *fils_session, + const struct ieee80211_mgmt *mgmt, size_t frame_len, + u8 *pos, size_t left); +int fils_encrypt_assoc(struct wpa_state_machine *sm, u8 *buf, + size_t current_len, size_t max_len, + const struct wpabuf *hlp); +int fils_set_tk(struct wpa_state_machine *sm); +u8 * hostapd_eid_assoc_fils_session(struct wpa_state_machine *sm, u8 *eid, + const u8 *fils_session, + struct wpabuf *fils_hlp_resp); +const u8 * wpa_fils_validate_fils_session(struct wpa_state_machine *sm, + const u8 *ies, size_t ies_len, + const u8 *fils_session); +int wpa_fils_validate_key_confirm(struct wpa_state_machine *sm, const u8 *ies, + size_t ies_len); + +int get_sta_tx_parameters(struct wpa_state_machine *sm, int ap_max_chanwidth, + int ap_seg1_idx, int *bandwidth, int *seg1_idx); + +int wpa_auth_write_fte(struct wpa_authenticator *wpa_auth, int use_sha384, + u8 *buf, size_t len); +void wpa_auth_get_fils_aead_params(struct wpa_state_machine *sm, + u8 *fils_anonce, u8 *fils_snonce, + u8 *fils_kek, size_t *fils_kek_len); +void wpa_auth_add_fils_pmk_pmkid(struct wpa_state_machine *sm, const u8 *pmk, + size_t pmk_len, const u8 *pmkid); +u8 * wpa_auth_write_assoc_resp_owe(struct wpa_state_machine *sm, + u8 *pos, size_t max_len, + const u8 *req_ies, size_t req_ies_len); +u8 * wpa_auth_write_assoc_resp_fils(struct wpa_state_machine *sm, + u8 *pos, size_t max_len, + const u8 *req_ies, size_t req_ies_len); +void wpa_auth_set_auth_alg(struct wpa_state_machine *sm, u16 auth_alg); +void wpa_auth_set_dpp_z(struct wpa_state_machine *sm, const struct wpabuf *z); + +int wpa_auth_resend_m1(struct wpa_state_machine *sm, int change_anonce, + void (*cb)(void *ctx1, void *ctx2), + void *ctx1, void *ctx2); +int wpa_auth_resend_m3(struct wpa_state_machine *sm, + void (*cb)(void *ctx1, void *ctx2), + void *ctx1, void *ctx2); +int wpa_auth_resend_group_m1(struct wpa_state_machine *sm, + void (*cb)(void *ctx1, void *ctx2), + void *ctx1, void *ctx2); +int wpa_auth_rekey_gtk(struct wpa_authenticator *wpa_auth); +void wpa_auth_set_ptk_rekey_timer(struct wpa_state_machine *sm); + +#endif /* WPA_AUTH_H */ diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/wpa_auth_glue.c b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/wpa_auth_glue.c new file mode 100755 index 0000000..d01a903 --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/wpa_auth_glue.c @@ -0,0 +1,866 @@ +/* + * hostapd / WPA authenticator glue code + * Copyright (c) 2002-2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "utils/eloop.h" +#include "utils/list.h" +#include "common/ieee802_11_defs.h" +#include "common/sae.h" +#include "common/wpa_ctrl.h" +#include "crypto/sha1.h" +#include "eapol_auth/eapol_auth_sm.h" +#include "eapol_auth/eapol_auth_sm_i.h" +#include "l2_packet/l2_packet.h" +#include "ap/hostapd.h" +#include "ieee802_1x.h" +#include "preauth_auth.h" +#include "ap/sta_info.h" +#include "tkip_countermeasures.h" +#include "ap_drv_ops.h" +#include "ap_config.h" +#include "ieee802_11.h" +#include "pmksa_cache_auth.h" +#include "wpa_auth.h" +#include "wpa_auth_glue.h" + + +static void hostapd_wpa_auth_conf(struct hostapd_bss_config *conf, + struct hostapd_config *iconf, + struct wpa_auth_config *wconf) +{ + os_memset(wconf, 0, sizeof(*wconf)); + wconf->wpa = conf->wpa; + wconf->wpa_key_mgmt = conf->wpa_key_mgmt; + wconf->wpa_pairwise = conf->wpa_pairwise; + wconf->wpa_group = conf->wpa_group; + wconf->wpa_group_rekey = conf->wpa_group_rekey; + wconf->wpa_strict_rekey = conf->wpa_strict_rekey; + wconf->wpa_gmk_rekey = conf->wpa_gmk_rekey; + wconf->wpa_ptk_rekey = conf->wpa_ptk_rekey; + wconf->wpa_group_update_count = conf->wpa_group_update_count; + wconf->wpa_disable_eapol_key_retries = + conf->wpa_disable_eapol_key_retries; + wconf->wpa_pairwise_update_count = conf->wpa_pairwise_update_count; + wconf->rsn_pairwise = conf->rsn_pairwise; + wconf->rsn_preauth = conf->rsn_preauth; + wconf->eapol_version = conf->eapol_version; + wconf->wmm_enabled = conf->wmm_enabled; + wconf->wmm_uapsd = conf->wmm_uapsd; + wconf->disable_pmksa_caching = conf->disable_pmksa_caching; +#ifdef CONFIG_OCV + wconf->ocv = conf->ocv; +#endif /* CONFIG_OCV */ + wconf->okc = conf->okc; +#ifdef CONFIG_IEEE80211W_AP + wconf->ieee80211w = conf->ieee80211w; + wconf->group_mgmt_cipher = conf->group_mgmt_cipher; + wconf->sae_require_mfp = conf->sae_require_mfp; +#endif /* CONFIG_IEEE80211W_AP */ +#ifdef CONFIG_IEEE80211R_AP + wconf->ssid_len = conf->ssid.ssid_len; + if (wconf->ssid_len > SSID_MAX_LEN) + wconf->ssid_len = SSID_MAX_LEN; + os_memcpy(wconf->ssid, conf->ssid.ssid, wconf->ssid_len); + os_memcpy(wconf->mobility_domain, conf->mobility_domain, + MOBILITY_DOMAIN_ID_LEN); + if (conf->nas_identifier && + os_strlen(conf->nas_identifier) <= FT_R0KH_ID_MAX_LEN) { + wconf->r0_key_holder_len = os_strlen(conf->nas_identifier); + os_memcpy(wconf->r0_key_holder, conf->nas_identifier, + wconf->r0_key_holder_len); + } + os_memcpy(wconf->r1_key_holder, conf->r1_key_holder, FT_R1KH_ID_LEN); + wconf->r0_key_lifetime = conf->r0_key_lifetime; + wconf->r1_max_key_lifetime = conf->r1_max_key_lifetime; + wconf->reassociation_deadline = conf->reassociation_deadline; + wconf->rkh_pos_timeout = conf->rkh_pos_timeout; + wconf->rkh_neg_timeout = conf->rkh_neg_timeout; + wconf->rkh_pull_timeout = conf->rkh_pull_timeout; + wconf->rkh_pull_retries = conf->rkh_pull_retries; + wconf->r0kh_list = &conf->r0kh_list; + wconf->r1kh_list = &conf->r1kh_list; + wconf->pmk_r1_push = conf->pmk_r1_push; + wconf->ft_over_ds = conf->ft_over_ds; + wconf->ft_psk_generate_local = conf->ft_psk_generate_local; +#endif /* CONFIG_IEEE80211R_AP */ +#ifdef CONFIG_HS20 + wconf->disable_gtk = conf->disable_dgaf; + if (conf->osen) { + wconf->disable_gtk = 1; + wconf->wpa = WPA_PROTO_OSEN; + wconf->wpa_key_mgmt = WPA_KEY_MGMT_OSEN; + wconf->wpa_pairwise = 0; + wconf->wpa_group = WPA_CIPHER_CCMP; + wconf->rsn_pairwise = WPA_CIPHER_CCMP; + wconf->rsn_preauth = 0; + wconf->disable_pmksa_caching = 1; +#ifdef CONFIG_IEEE80211W_AP + wconf->ieee80211w = 1; +#endif /* CONFIG_IEEE80211W_AP */ + } +#endif /* CONFIG_HS20 */ +#ifdef CONFIG_TESTING_OPTIONS + wconf->corrupt_gtk_rekey_mic_probability = + iconf->corrupt_gtk_rekey_mic_probability; + if (conf->own_ie_override && + wpabuf_len(conf->own_ie_override) <= MAX_OWN_IE_OVERRIDE) { + wconf->own_ie_override_len = wpabuf_len(conf->own_ie_override); + os_memcpy(wconf->own_ie_override, + wpabuf_head(conf->own_ie_override), + wconf->own_ie_override_len); + } +#endif /* CONFIG_TESTING_OPTIONS */ +#ifdef CONFIG_P2P + os_memcpy(wconf->ip_addr_go, conf->ip_addr_go, 4); + os_memcpy(wconf->ip_addr_mask, conf->ip_addr_mask, 4); + os_memcpy(wconf->ip_addr_start, conf->ip_addr_start, 4); + os_memcpy(wconf->ip_addr_end, conf->ip_addr_end, 4); +#endif /* CONFIG_P2P */ +#ifdef CONFIG_FILS + wconf->fils_cache_id_set = conf->fils_cache_id_set; + os_memcpy(wconf->fils_cache_id, conf->fils_cache_id, + FILS_CACHE_ID_LEN); +#endif /* CONFIG_FILS */ +} + + +static void hostapd_wpa_auth_logger(void *ctx, const u8 *addr, + logger_level level, const char *txt) +{ +#ifndef CONFIG_NO_HOSTAPD_LOGGER + struct hostapd_data *hapd = ctx; + int hlevel; + + switch (level) { + case LOGGER_WARNING: + hlevel = HOSTAPD_LEVEL_WARNING; + break; + case LOGGER_INFO: + hlevel = HOSTAPD_LEVEL_INFO; + break; + case LOGGER_DEBUG: + default: + hlevel = HOSTAPD_LEVEL_DEBUG; + break; + } + + hostapd_logger(hapd, addr, HOSTAPD_MODULE_WPA, hlevel, "%s", txt); +#endif /* CONFIG_NO_HOSTAPD_LOGGER */ +} + + +static void hostapd_wpa_auth_disconnect(void *ctx, const u8 *addr, + u16 reason) +{ + struct hostapd_data *hapd = ctx; + wpa_printf(MSG_DEBUG, "%s: WPA authenticator requests disconnect: " + "STA " MACSTR " reason %d", + __func__, MAC2STR(addr), reason); + ap_sta_disconnect(hapd, NULL, addr, reason); +} + + +static int hostapd_wpa_auth_mic_failure_report(void *ctx, const u8 *addr) +{ + struct hostapd_data *hapd = ctx; + return michael_mic_failure(hapd, addr, 0); +} + + +static void hostapd_wpa_auth_psk_failure_report(void *ctx, const u8 *addr) +{ + struct hostapd_data *hapd __maybe_unused = ctx; + wpa_msg(hapd->msg_ctx, MSG_INFO, AP_STA_POSSIBLE_PSK_MISMATCH MACSTR, + MAC2STR(addr)); +} + + +static void hostapd_wpa_auth_set_eapol(void *ctx, const u8 *addr, + wpa_eapol_variable var, int value) +{ + struct hostapd_data *hapd = ctx; + struct sta_info *sta = ap_get_sta(hapd, addr); + if (sta == NULL) + return; + switch (var) { + case WPA_EAPOL_portEnabled: + ieee802_1x_notify_port_enabled(sta->eapol_sm, value); + break; + case WPA_EAPOL_portValid: + ieee802_1x_notify_port_valid(sta->eapol_sm, value); + break; + case WPA_EAPOL_authorized: + ieee802_1x_set_sta_authorized(hapd, sta, value); + break; +#ifdef CONFIG_FULL_HOSTAPD + case WPA_EAPOL_portControl_Auto: + if (sta->eapol_sm) + sta->eapol_sm->portControl = Auto; + break; + case WPA_EAPOL_keyRun: + if (sta->eapol_sm) + sta->eapol_sm->keyRun = value ? TRUE : FALSE; + break; + case WPA_EAPOL_keyAvailable: + if (sta->eapol_sm) + sta->eapol_sm->eap_if->eapKeyAvailable = + value ? TRUE : FALSE; + break; + case WPA_EAPOL_keyDone: + if (sta->eapol_sm) + sta->eapol_sm->keyDone = value ? TRUE : FALSE; + break; + case WPA_EAPOL_inc_EapolFramesTx: + if (sta->eapol_sm) + sta->eapol_sm->dot1xAuthEapolFramesTx++; + break; +#else + /* GCC complains */ + case WPA_EAPOL_portControl_Auto: + case WPA_EAPOL_keyRun: + case WPA_EAPOL_keyAvailable: + case WPA_EAPOL_keyDone: + case WPA_EAPOL_inc_EapolFramesTx: + break; +#endif + } +} + + +static int hostapd_wpa_auth_get_eapol(void *ctx, const u8 *addr, + wpa_eapol_variable var) +{ + struct hostapd_data *hapd = ctx; + struct sta_info *sta = ap_get_sta(hapd, addr); + if (sta == NULL || sta->eapol_sm == NULL) + return -1; +#ifdef CONFIG_FULL_HOSTAPD + switch (var) { + case WPA_EAPOL_keyRun: + return sta->eapol_sm->keyRun; + case WPA_EAPOL_keyAvailable: + return sta->eapol_sm->eap_if->eapKeyAvailable; + default: + return -1; + } +#endif + return -1; +} + + +static const u8 * hostapd_wpa_auth_get_psk(void *ctx, const u8 *addr, + const u8 *p2p_dev_addr, + const u8 *prev_psk, size_t *psk_len, + int *vlan_id) +{ + struct hostapd_data *hapd = ctx; + struct sta_info *sta = ap_get_sta(hapd, addr); + const u8 *psk; + + if (vlan_id) + *vlan_id = 0; + if (psk_len) + *psk_len = PMK_LEN; + +#ifdef CONFIG_SAE_AP + if (sta && sta->auth_alg == WLAN_AUTH_SAE) { + if (!sta->sae || prev_psk) + return NULL; + return sta->sae->pmk; + } + if (sta && wpa_auth_uses_sae(sta->wpa_sm)) { + wpa_printf(MSG_DEBUG, + "No PSK for STA trying to use SAE with PMKSA caching"); + return NULL; + } +#endif /* CONFIG_SAE_AP */ + +#ifdef CONFIG_OWE + if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE) && + sta && sta->owe_pmk) { + if (psk_len) + *psk_len = sta->owe_pmk_len; + return sta->owe_pmk; + } + if ((hapd->conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE) && sta) { + struct rsn_pmksa_cache_entry *sa; + + sa = wpa_auth_sta_get_pmksa(sta->wpa_sm); + if (sa && sa->akmp == WPA_KEY_MGMT_OWE) { + if (psk_len) + *psk_len = sa->pmk_len; + return sa->pmk; + } + } +#endif /* CONFIG_OWE */ + + psk = hostapd_get_psk(hapd->conf, addr, p2p_dev_addr, prev_psk, + vlan_id); + /* + * This is about to iterate over all psks, prev_psk gives the last + * returned psk which should not be returned again. + * logic list (all hostapd_get_psk; all sta->psk) + */ + if (sta && sta->psk && !psk) { + struct hostapd_sta_wpa_psk_short *pos; + + if (vlan_id) + *vlan_id = 0; + psk = sta->psk->psk; + for (pos = sta->psk; pos; pos = pos->next) { + if (pos->is_passphrase) { + pbkdf2_sha1(pos->passphrase, + hapd->conf->ssid.ssid, + hapd->conf->ssid.ssid_len, 4096, + pos->psk, PMK_LEN); + pos->is_passphrase = 0; + } + if (pos->psk == prev_psk) { + psk = pos->next ? pos->next->psk : NULL; + break; + } + } + } + return psk; +} + + +static int hostapd_wpa_auth_get_msk(void *ctx, const u8 *addr, u8 *msk, + size_t *len) +{ +#ifdef CONFIG_FULL_HOSTAPD + struct hostapd_data *hapd = ctx; + const u8 *key; + size_t keylen; + struct sta_info *sta; + + sta = ap_get_sta(hapd, addr); + if (sta == NULL) { + wpa_printf(MSG_DEBUG, "AUTH_GET_MSK: Cannot find STA"); + return -1; + } + + key = ieee802_1x_get_key(sta->eapol_sm, &keylen); + if (key == NULL) { + wpa_printf(MSG_DEBUG, "AUTH_GET_MSK: Key is null, eapol_sm: %p", + sta->eapol_sm); + return -1; + } + + if (keylen > *len) + keylen = *len; + os_memcpy(msk, key, keylen); + *len = keylen; + + return 0; +#else + return -1; +#endif +} + + +static int hostapd_wpa_auth_set_key(void *ctx, int vlan_id, enum wpa_alg alg, + const u8 *addr, int idx, u8 *key, + size_t key_len) +{ + struct hostapd_data *hapd = ctx; + const char *ifname = hapd->conf->iface; + +#ifdef CONFIG_FULL_HOSTAPD + if (vlan_id > 0) { + ifname = hostapd_get_vlan_id_ifname(hapd->conf->vlan, vlan_id); + if (ifname == NULL) + return -1; + } +#endif + return hostapd_drv_set_key(ifname, hapd, alg, addr, idx, 1, NULL, 0, + key, key_len); +} + + +static int hostapd_wpa_auth_get_seqnum(void *ctx, const u8 *addr, int idx, + u8 *seq) +{ + struct hostapd_data *hapd = ctx; + return hostapd_get_seqnum(hapd->conf->iface, hapd, addr, idx, seq); +} + + +static int hostapd_wpa_auth_send_eapol(void *ctx, const u8 *addr, + const u8 *data, size_t data_len, + int encrypt) +{ + struct hostapd_data *hapd = ctx; + struct sta_info *sta; + u32 flags = 0; + +#ifdef CONFIG_TESTING_OPTIONS + if (hapd->ext_eapol_frame_io) { + size_t hex_len = 2 * data_len + 1; + char *hex = os_malloc(hex_len); + + if (hex == NULL) + return -1; + wpa_snprintf_hex(hex, hex_len, data, data_len); + wpa_msg(hapd->msg_ctx, MSG_INFO, "EAPOL-TX " MACSTR " %s", + MAC2STR(addr), hex); + os_free(hex); + return 0; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + sta = ap_get_sta(hapd, addr); + if (sta) + flags = hostapd_sta_flags_to_drv(sta->flags); + + return hostapd_drv_hapd_send_eapol(hapd, addr, data, data_len, + encrypt, flags); +} + + +static int hostapd_wpa_auth_for_each_sta( + void *ctx, int (*cb)(struct wpa_state_machine *sm, void *ctx), + void *cb_ctx) +{ + struct hostapd_data *hapd = ctx; + struct sta_info *sta; + + for (sta = hapd->sta_list; sta; sta = sta->next) { + if (sta->wpa_sm && cb(sta->wpa_sm, cb_ctx)) + return 1; + } + return 0; +} + + +struct wpa_auth_iface_iter_data { + int (*cb)(struct wpa_authenticator *sm, void *ctx); + void *cb_ctx; +}; + +static int wpa_auth_iface_iter(struct hostapd_iface *iface, void *ctx) +{ + struct wpa_auth_iface_iter_data *data = ctx; + size_t i; + for (i = 0; i < iface->num_bss; i++) { + if (iface->bss[i]->wpa_auth && + data->cb(iface->bss[i]->wpa_auth, data->cb_ctx)) + return 1; + } + return 0; +} + + +static int hostapd_wpa_auth_for_each_auth( + void *ctx, int (*cb)(struct wpa_authenticator *sm, void *ctx), + void *cb_ctx) +{ + struct hostapd_data *hapd = ctx; + struct wpa_auth_iface_iter_data data; + if (hapd->iface->interfaces == NULL || + hapd->iface->interfaces->for_each_interface == NULL) + return -1; + data.cb = cb; + data.cb_ctx = cb_ctx; + return hapd->iface->interfaces->for_each_interface( + hapd->iface->interfaces, wpa_auth_iface_iter, &data); +} + + +#ifdef CONFIG_IEEE80211R_AP + +struct wpa_ft_rrb_rx_later_data { + struct dl_list list; + u8 addr[ETH_ALEN]; + size_t data_len; + /* followed by data_len octets of data */ +}; + +static void hostapd_wpa_ft_rrb_rx_later(void *eloop_ctx, void *timeout_ctx) +{ + struct hostapd_data *hapd = eloop_ctx; + struct wpa_ft_rrb_rx_later_data *data, *n; + + dl_list_for_each_safe(data, n, &hapd->l2_queue, + struct wpa_ft_rrb_rx_later_data, list) { + if (hapd->wpa_auth) { + wpa_ft_rrb_rx(hapd->wpa_auth, data->addr, + (const u8 *) (data + 1), + data->data_len); + } + dl_list_del(&data->list); + os_free(data); + } +} + + +struct wpa_auth_ft_iface_iter_data { + struct hostapd_data *src_hapd; + const u8 *dst; + const u8 *data; + size_t data_len; +}; + + +static int hostapd_wpa_auth_ft_iter(struct hostapd_iface *iface, void *ctx) +{ + struct wpa_auth_ft_iface_iter_data *idata = ctx; + struct wpa_ft_rrb_rx_later_data *data; + struct hostapd_data *hapd; + size_t j; + + for (j = 0; j < iface->num_bss; j++) { + hapd = iface->bss[j]; + if (hapd == idata->src_hapd || + !hapd->wpa_auth || + os_memcmp(hapd->own_addr, idata->dst, ETH_ALEN) != 0) + continue; + + wpa_printf(MSG_DEBUG, + "FT: Send RRB data directly to locally managed BSS " + MACSTR "@%s -> " MACSTR "@%s", + MAC2STR(idata->src_hapd->own_addr), + idata->src_hapd->conf->iface, + MAC2STR(hapd->own_addr), hapd->conf->iface); + + /* Defer wpa_ft_rrb_rx() until next eloop step as this is + * when it would be triggered when reading from a socket. + * This avoids + * hapd0:send -> hapd1:recv -> hapd1:send -> hapd0:recv, + * that is calling hapd0:recv handler from within + * hapd0:send directly. + */ + data = os_zalloc(sizeof(*data) + idata->data_len); + if (!data) + return 1; + + os_memcpy(data->addr, idata->src_hapd->own_addr, ETH_ALEN); + os_memcpy(data + 1, idata->data, idata->data_len); + data->data_len = idata->data_len; + + dl_list_add(&hapd->l2_queue, &data->list); + + if (!eloop_is_timeout_registered(hostapd_wpa_ft_rrb_rx_later, + hapd, NULL)) + eloop_register_timeout(0, 0, + hostapd_wpa_ft_rrb_rx_later, + hapd, NULL); + + return 1; + } + + return 0; +} + +#endif /* CONFIG_IEEE80211R_AP */ + + +static int hostapd_wpa_auth_send_ether(void *ctx, const u8 *dst, u16 proto, + const u8 *data, size_t data_len) +{ + struct hostapd_data *hapd = ctx; + struct l2_ethhdr *buf; + int ret; + +#ifdef CONFIG_TESTING_OPTIONS + if (hapd->ext_eapol_frame_io && proto == ETH_P_EAPOL) { + size_t hex_len = 2 * data_len + 1; + char *hex = os_malloc(hex_len); + + if (hex == NULL) + return -1; + wpa_snprintf_hex(hex, hex_len, data, data_len); + wpa_msg(hapd->msg_ctx, MSG_INFO, "EAPOL-TX " MACSTR " %s", + MAC2STR(dst), hex); + os_free(hex); + return 0; + } +#endif /* CONFIG_TESTING_OPTIONS */ + +#ifdef CONFIG_IEEE80211R_AP + if (proto == ETH_P_RRB && hapd->iface->interfaces && + hapd->iface->interfaces->for_each_interface) { + int res; + struct wpa_auth_ft_iface_iter_data idata; + idata.src_hapd = hapd; + idata.dst = dst; + idata.data = data; + idata.data_len = data_len; + res = hapd->iface->interfaces->for_each_interface( + hapd->iface->interfaces, hostapd_wpa_auth_ft_iter, + &idata); + if (res == 1) + return data_len; + } +#endif /* CONFIG_IEEE80211R_AP */ + + if (hapd->driver && hapd->driver->send_ether) + return hapd->driver->send_ether(hapd->drv_priv, dst, + hapd->own_addr, proto, + data, data_len); + if (hapd->l2 == NULL) + return -1; + + buf = os_malloc(sizeof(*buf) + data_len); + if (buf == NULL) + return -1; + os_memcpy(buf->h_dest, dst, ETH_ALEN); + os_memcpy(buf->h_source, hapd->own_addr, ETH_ALEN); + buf->h_proto = host_to_be16(proto); + os_memcpy(buf + 1, data, data_len); + ret = l2_packet_send(hapd->l2, dst, proto, (u8 *) buf, + sizeof(*buf) + data_len); + os_free(buf); + return ret; +} + + +#ifdef CONFIG_IEEE80211R_AP + +static int hostapd_wpa_auth_send_ft_action(void *ctx, const u8 *dst, + const u8 *data, size_t data_len) +{ + struct hostapd_data *hapd = ctx; + int res; + struct ieee80211_mgmt *m; + size_t mlen; + struct sta_info *sta; + + sta = ap_get_sta(hapd, dst); + if (sta == NULL || sta->wpa_sm == NULL) + return -1; + + m = os_zalloc(sizeof(*m) + data_len); + if (m == NULL) + return -1; + mlen = ((u8 *) &m->u - (u8 *) m) + data_len; + m->frame_control = IEEE80211_FC(WLAN_FC_TYPE_MGMT, + WLAN_FC_STYPE_ACTION); + os_memcpy(m->da, dst, ETH_ALEN); + os_memcpy(m->sa, hapd->own_addr, ETH_ALEN); + os_memcpy(m->bssid, hapd->own_addr, ETH_ALEN); + os_memcpy(&m->u, data, data_len); + + res = hostapd_drv_send_mlme(hapd, (u8 *) m, mlen, 0); + os_free(m); + return res; +} + + +static struct wpa_state_machine * +hostapd_wpa_auth_add_sta(void *ctx, const u8 *sta_addr) +{ + struct hostapd_data *hapd = ctx; + struct sta_info *sta; + + wpa_printf(MSG_DEBUG, "Add station entry for " MACSTR + " based on WPA authenticator callback", + MAC2STR(sta_addr)); + if (hostapd_add_sta_node(hapd, sta_addr, WLAN_AUTH_FT) < 0) + return NULL; + + sta = ap_sta_add(hapd, sta_addr); + if (sta == NULL) + return NULL; + if (hapd->driver && hapd->driver->add_sta_node) + sta->added_unassoc = 1; + sta->ft_over_ds = 1; + if (sta->wpa_sm) { + sta->auth_alg = WLAN_AUTH_FT; + return sta->wpa_sm; + } + + sta->wpa_sm = wpa_auth_sta_init(hapd->wpa_auth, sta->addr, NULL); + if (sta->wpa_sm == NULL) { + ap_free_sta(hapd, sta); + return NULL; + } + sta->auth_alg = WLAN_AUTH_FT; + + return sta->wpa_sm; +} + + +static void hostapd_rrb_receive(void *ctx, const u8 *src_addr, const u8 *buf, + size_t len) +{ + struct hostapd_data *hapd = ctx; + struct l2_ethhdr *ethhdr; + if (len < sizeof(*ethhdr)) + return; + ethhdr = (struct l2_ethhdr *) buf; + wpa_printf(MSG_DEBUG, "FT: RRB received packet " MACSTR " -> " + MACSTR, MAC2STR(ethhdr->h_source), MAC2STR(ethhdr->h_dest)); + if (!is_multicast_ether_addr(ethhdr->h_dest) && + os_memcmp(hapd->own_addr, ethhdr->h_dest, ETH_ALEN) != 0) + return; + wpa_ft_rrb_rx(hapd->wpa_auth, ethhdr->h_source, buf + sizeof(*ethhdr), + len - sizeof(*ethhdr)); +} + + +static int hostapd_wpa_auth_add_tspec(void *ctx, const u8 *sta_addr, + u8 *tspec_ie, size_t tspec_ielen) +{ + struct hostapd_data *hapd = ctx; + return hostapd_add_tspec(hapd, sta_addr, tspec_ie, tspec_ielen); +} + +#endif /* CONFIG_IEEE80211R */ + + +int hostapd_setup_wpa(struct hostapd_data *hapd) +{ + struct wpa_auth_config _conf; + static const struct wpa_auth_callbacks cb = { + .logger = hostapd_wpa_auth_logger, + .disconnect = hostapd_wpa_auth_disconnect, + .mic_failure_report = hostapd_wpa_auth_mic_failure_report, + .psk_failure_report = hostapd_wpa_auth_psk_failure_report, + .set_eapol = hostapd_wpa_auth_set_eapol, + .get_eapol = hostapd_wpa_auth_get_eapol, + .get_psk = hostapd_wpa_auth_get_psk, + .get_msk = hostapd_wpa_auth_get_msk, + .set_key = hostapd_wpa_auth_set_key, + .get_seqnum = hostapd_wpa_auth_get_seqnum, + .send_eapol = hostapd_wpa_auth_send_eapol, + .for_each_sta = hostapd_wpa_auth_for_each_sta, + .for_each_auth = hostapd_wpa_auth_for_each_auth, + .send_ether = hostapd_wpa_auth_send_ether, +#ifdef CONFIG_FULL_HOSTAPD + .send_oui = hostapd_wpa_auth_send_oui, + .channel_info = hostapd_channel_info, + .update_vlan = hostapd_wpa_auth_update_vlan, +#endif +#ifdef CONFIG_OCV + .get_sta_tx_params = hostapd_get_sta_tx_params, +#endif /* CONFIG_OCV */ +#ifdef CONFIG_IEEE80211R_AP + .send_ft_action = hostapd_wpa_auth_send_ft_action, + .add_sta = hostapd_wpa_auth_add_sta, + .add_tspec = hostapd_wpa_auth_add_tspec, + .set_vlan = hostapd_wpa_auth_set_vlan, + .get_vlan = hostapd_wpa_auth_get_vlan, + .set_identity = hostapd_wpa_auth_set_identity, + .get_identity = hostapd_wpa_auth_get_identity, + .set_radius_cui = hostapd_wpa_auth_set_radius_cui, + .get_radius_cui = hostapd_wpa_auth_get_radius_cui, + .set_session_timeout = hostapd_wpa_auth_set_session_timeout, + .get_session_timeout = hostapd_wpa_auth_get_session_timeout, +#endif /* CONFIG_IEEE80211R_AP */ + }; + const u8 *wpa_ie; + size_t wpa_ie_len; + + hostapd_wpa_auth_conf(hapd->conf, hapd->iconf, &_conf); +#ifdef CONFIG_FULL_HOSTAPD + if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_EAPOL_TX_STATUS) + _conf.tx_status = 1; + if (hapd->iface->drv_flags & WPA_DRIVER_FLAGS_AP_MLME) + _conf.ap_mlme = 1; +#endif + hapd->wpa_auth = wpa_init(hapd->own_addr, &_conf, &cb, hapd); + if (hapd->wpa_auth == NULL) { + wpa_printf(MSG_ERROR, "WPA initialization failed."); + return -1; + } + + if (hostapd_set_privacy(hapd, 1)) { + wpa_printf(MSG_ERROR, "Could not set PrivacyInvoked " + "for interface %s", hapd->conf->iface); + return -1; + } + + wpa_ie = wpa_auth_get_wpa_ie(hapd->wpa_auth, &wpa_ie_len); + if (hostapd_set_generic_elem(hapd, wpa_ie, wpa_ie_len)) { + wpa_printf(MSG_ERROR, "Failed to configure WPA IE for " + "the kernel driver."); + return -1; + } + + if (rsn_preauth_iface_init(hapd)) { + wpa_printf(MSG_ERROR, "Initialization of RSN " + "pre-authentication failed."); + return -1; + } + +#ifdef CONFIG_IEEE80211R_AP + if (!hostapd_drv_none(hapd) && + wpa_key_mgmt_ft(hapd->conf->wpa_key_mgmt)) { + const char *ft_iface; + + ft_iface = hapd->conf->bridge[0] ? hapd->conf->bridge : + hapd->conf->iface; + hapd->l2 = l2_packet_init(ft_iface, NULL, ETH_P_RRB, + hostapd_rrb_receive, hapd, 1); + if (hapd->l2 == NULL && + (hapd->driver == NULL || + hapd->driver->send_ether == NULL)) { + wpa_printf(MSG_ERROR, "Failed to open l2_packet " + "interface"); + return -1; + } + + if (hostapd_wpa_register_ft_oui(hapd, ft_iface)) { + wpa_printf(MSG_ERROR, + "Failed to open ETH_P_OUI interface"); + return -1; + } + } +#endif /* CONFIG_IEEE80211R_AP */ + + return 0; + +} + + +void hostapd_reconfig_wpa(struct hostapd_data *hapd) +{ + struct wpa_auth_config wpa_auth_conf; + hostapd_wpa_auth_conf(hapd->conf, hapd->iconf, &wpa_auth_conf); + wpa_reconfig(hapd->wpa_auth, &wpa_auth_conf); +} + + +void hostapd_deinit_wpa(struct hostapd_data *hapd) +{ + ieee80211_tkip_countermeasures_deinit(hapd); + rsn_preauth_iface_deinit(hapd); + if (hapd->wpa_auth) { + wpa_deinit(hapd->wpa_auth); + hapd->wpa_auth = NULL; + + if (hapd->drv_priv && hostapd_set_privacy(hapd, 0)) { + wpa_printf(MSG_DEBUG, "Could not disable " + "PrivacyInvoked for interface %s", + hapd->conf->iface); + } + + if (hapd->drv_priv && + hostapd_set_generic_elem(hapd, (u8 *) "", 0)) { + wpa_printf(MSG_DEBUG, "Could not remove generic " + "information element from interface %s", + hapd->conf->iface); + } + } +#ifdef IEEE8021X_EAPOL + ieee802_1x_deinit(hapd); +#endif + +#ifdef CONFIG_IEEE80211R_AP + eloop_cancel_timeout(hostapd_wpa_ft_rrb_rx_later, hapd, ELOOP_ALL_CTX); + hostapd_wpa_ft_rrb_rx_later(hapd, NULL); /* flush without delivering */ + eloop_cancel_timeout(hostapd_oui_deliver_later, hapd, ELOOP_ALL_CTX); + hostapd_oui_deliver_later(hapd, NULL); /* flush without delivering */ + l2_packet_deinit(hapd->l2); + hapd->l2 = NULL; + hostapd_wpa_unregister_ft_oui(hapd); +#endif /* CONFIG_IEEE80211R_AP */ +} diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/wpa_auth_glue.h b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/wpa_auth_glue.h new file mode 100755 index 0000000..1b13ae7 --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/wpa_auth_glue.h @@ -0,0 +1,16 @@ +/* + * hostapd / WPA authenticator glue code + * Copyright (c) 2002-2009, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef WPA_AUTH_GLUE_H +#define WPA_AUTH_GLUE_H + +int hostapd_setup_wpa(struct hostapd_data *hapd); +void hostapd_reconfig_wpa(struct hostapd_data *hapd); +void hostapd_deinit_wpa(struct hostapd_data *hapd); + +#endif /* WPA_AUTH_GLUE_H */ diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/wpa_auth_i.h b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/wpa_auth_i.h new file mode 100755 index 0000000..ec0e2a9 --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/wpa_auth_i.h @@ -0,0 +1,308 @@ +/* + * hostapd - IEEE 802.11i-2004 / WPA Authenticator: Internal definitions + * Copyright (c) 2004-2015, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef WPA_AUTH_I_H +#define WPA_AUTH_I_H + +#include "utils/list.h" + +/* max(dot11RSNAConfigGroupUpdateCount,dot11RSNAConfigPairwiseUpdateCount) */ +#define RSNA_MAX_EAPOL_RETRIES 4 + +struct wpa_group; + +struct wpa_state_machine { + struct wpa_authenticator *wpa_auth; + struct wpa_group *group; + + u8 addr[ETH_ALEN]; + u8 p2p_dev_addr[ETH_ALEN]; + u16 auth_alg; + + enum { + WPA_PTK_INITIALIZE, WPA_PTK_DISCONNECT, WPA_PTK_DISCONNECTED, + WPA_PTK_AUTHENTICATION, WPA_PTK_AUTHENTICATION2, + WPA_PTK_INITPMK, WPA_PTK_INITPSK, WPA_PTK_PTKSTART, + WPA_PTK_PTKCALCNEGOTIATING, WPA_PTK_PTKCALCNEGOTIATING2, + WPA_PTK_PTKINITNEGOTIATING, WPA_PTK_PTKINITDONE + } wpa_ptk_state; + + enum { + WPA_PTK_GROUP_IDLE = 0, + WPA_PTK_GROUP_REKEYNEGOTIATING, + WPA_PTK_GROUP_REKEYESTABLISHED, + WPA_PTK_GROUP_KEYERROR + } wpa_ptk_group_state; + + Boolean Init; + Boolean DeauthenticationRequest; + Boolean AuthenticationRequest; + Boolean ReAuthenticationRequest; + Boolean Disconnect; + u16 disconnect_reason; /* specific reason code to use with Disconnect */ + u32 TimeoutCtr; + u32 GTimeoutCtr; + Boolean TimeoutEvt; + Boolean EAPOLKeyReceived; + Boolean EAPOLKeyPairwise; + Boolean EAPOLKeyRequest; + Boolean MICVerified; + Boolean GUpdateStationKeys; + u8 ANonce[WPA_NONCE_LEN]; + u8 SNonce[WPA_NONCE_LEN]; + u8 alt_SNonce[WPA_NONCE_LEN]; + u8 alt_replay_counter[WPA_REPLAY_COUNTER_LEN]; + u8 PMK[PMK_LEN_MAX]; + unsigned int pmk_len; + u8 pmkid[PMKID_LEN]; /* valid if pmkid_set == 1 */ + struct wpa_ptk PTK; + Boolean PTK_valid; + Boolean pairwise_set; + Boolean tk_already_set; + int keycount; + Boolean Pair; + struct wpa_key_replay_counter { + u8 counter[WPA_REPLAY_COUNTER_LEN]; + Boolean valid; + } key_replay[RSNA_MAX_EAPOL_RETRIES], + prev_key_replay[RSNA_MAX_EAPOL_RETRIES]; + Boolean PInitAKeys; /* WPA only, not in IEEE 802.11i */ + Boolean PTKRequest; /* not in IEEE 802.11i state machine */ + Boolean has_GTK; + Boolean PtkGroupInit; /* init request for PTK Group state machine */ + + u8 *last_rx_eapol_key; /* starting from IEEE 802.1X header */ + size_t last_rx_eapol_key_len; + + unsigned int changed:1; + unsigned int in_step_loop:1; + unsigned int pending_deinit:1; + unsigned int started:1; + unsigned int mgmt_frame_prot:1; + unsigned int rx_eapol_key_secure:1; + unsigned int update_snonce:1; + unsigned int alt_snonce_valid:1; +#ifdef CONFIG_IEEE80211R_AP + unsigned int ft_completed:1; + unsigned int pmk_r1_name_valid:1; +#endif /* CONFIG_IEEE80211R_AP */ + unsigned int is_wnmsleep:1; + unsigned int pmkid_set:1; +#ifdef CONFIG_OCV + unsigned int ocv_enabled:1; +#endif /* CONFIG_OCV */ + + u8 req_replay_counter[WPA_REPLAY_COUNTER_LEN]; + int req_replay_counter_used; + + u8 *wpa_ie; + size_t wpa_ie_len; + + enum { + WPA_VERSION_NO_WPA = 0 /* WPA not used */, + WPA_VERSION_WPA = 1 /* WPA / IEEE 802.11i/D3.0 */, + WPA_VERSION_WPA2 = 2 /* WPA2 / IEEE 802.11i */ + } wpa; + int pairwise; /* Pairwise cipher suite, WPA_CIPHER_* */ + int wpa_key_mgmt; /* the selected WPA_KEY_MGMT_* */ + struct rsn_pmksa_cache_entry *pmksa; + + u32 dot11RSNAStatsTKIPLocalMICFailures; + u32 dot11RSNAStatsTKIPRemoteMICFailures; + +#ifdef CONFIG_IEEE80211R_AP + u8 xxkey[PMK_LEN_MAX]; /* PSK or the second 256 bits of MSK, or the + * first 384 bits of MSK */ + size_t xxkey_len; + u8 pmk_r1[PMK_LEN_MAX]; + unsigned int pmk_r1_len; + u8 pmk_r1_name[WPA_PMK_NAME_LEN]; /* PMKR1Name derived from FT Auth + * Request */ + u8 r0kh_id[FT_R0KH_ID_MAX_LEN]; /* R0KH-ID from FT Auth Request */ + size_t r0kh_id_len; + u8 sup_pmk_r1_name[WPA_PMK_NAME_LEN]; /* PMKR1Name from EAPOL-Key + * message 2/4 */ + u8 *assoc_resp_ftie; + + void (*ft_pending_cb)(void *ctx, const u8 *dst, const u8 *bssid, + u16 auth_transaction, u16 status, + const u8 *ies, size_t ies_len); + void *ft_pending_cb_ctx; + struct wpabuf *ft_pending_req_ies; + u8 ft_pending_pull_nonce[FT_RRB_NONCE_LEN]; + u8 ft_pending_auth_transaction; + u8 ft_pending_current_ap[ETH_ALEN]; + int ft_pending_pull_left_retries; +#endif /* CONFIG_IEEE80211R_AP */ + + int pending_1_of_4_timeout; + +#ifdef CONFIG_P2P + u8 ip_addr[4]; +#endif /* CONFIG_P2P */ + +#ifdef CONFIG_FILS + u8 fils_key_auth_sta[FILS_MAX_KEY_AUTH_LEN]; + u8 fils_key_auth_ap[FILS_MAX_KEY_AUTH_LEN]; + size_t fils_key_auth_len; + unsigned int fils_completed:1; +#endif /* CONFIG_FILS */ + +#ifdef CONFIG_DPP2 + struct wpabuf *dpp_z; +#endif /* CONFIG_DPP2 */ + +#ifdef CONFIG_TESTING_OPTIONS + void (*eapol_status_cb)(void *ctx1, void *ctx2); + void *eapol_status_cb_ctx1; + void *eapol_status_cb_ctx2; +#endif /* CONFIG_TESTING_OPTIONS */ +}; + + +/* per group key state machine data */ +struct wpa_group { + struct wpa_group *next; + int vlan_id; + + Boolean GInit; + int GKeyDoneStations; + Boolean GTKReKey; + int GTK_len; + int GN, GM; + Boolean GTKAuthenticator; + u8 Counter[WPA_NONCE_LEN]; + + enum { + WPA_GROUP_GTK_INIT = 0, + WPA_GROUP_SETKEYS, WPA_GROUP_SETKEYSDONE, + WPA_GROUP_FATAL_FAILURE + } wpa_group_state; + + u8 GMK[WPA_GMK_LEN]; + u8 GTK[2][WPA_GTK_MAX_LEN]; + u8 GNonce[WPA_NONCE_LEN]; + Boolean changed; + Boolean first_sta_seen; + Boolean reject_4way_hs_for_entropy; +#ifdef CONFIG_IEEE80211W_AP + u8 IGTK[2][WPA_IGTK_MAX_LEN]; + int GN_igtk, GM_igtk; +#endif /* CONFIG_IEEE80211W_AP */ + /* Number of references except those in struct wpa_group->next */ + unsigned int references; + unsigned int num_setup_iface; +}; + + +struct wpa_ft_pmk_cache; + +/* per authenticator data */ +struct wpa_authenticator { + struct wpa_group *group; + + unsigned int dot11RSNAStatsTKIPRemoteMICFailures; + u32 dot11RSNAAuthenticationSuiteSelected; + u32 dot11RSNAPairwiseCipherSelected; + u32 dot11RSNAGroupCipherSelected; + u8 dot11RSNAPMKIDUsed[PMKID_LEN]; + u32 dot11RSNAAuthenticationSuiteRequested; /* FIX: update */ + u32 dot11RSNAPairwiseCipherRequested; /* FIX: update */ + u32 dot11RSNAGroupCipherRequested; /* FIX: update */ + unsigned int dot11RSNATKIPCounterMeasuresInvoked; + unsigned int dot11RSNA4WayHandshakeFailures; + + struct wpa_auth_config conf; + const struct wpa_auth_callbacks *cb; + void *cb_ctx; + + u8 *wpa_ie; + size_t wpa_ie_len; + + u8 addr[ETH_ALEN]; + + struct rsn_pmksa_cache *pmksa; + struct wpa_ft_pmk_cache *ft_pmk_cache; + +#ifdef CONFIG_P2P + struct bitfield *ip_pool; +#endif /* CONFIG_P2P */ +}; + + +#ifdef CONFIG_IEEE80211R_AP + +#define FT_REMOTE_SEQ_BACKLOG 16 +struct ft_remote_seq_rx { + u32 dom; + struct os_reltime time_offset; /* local time - offset = remote time */ + + /* accepted sequence numbers: (offset ... offset + 0x40000000] + * (except those in last) + * dropped sequence numbers: (offset - 0x40000000 ... offset] + * all others trigger SEQ_REQ message (except first message) + */ + u32 last[FT_REMOTE_SEQ_BACKLOG]; + unsigned int num_last; + u32 offsetidx; + + struct dl_list queue; /* send nonces + rrb msgs awaiting seq resp */ +}; + +struct ft_remote_seq_tx { + u32 dom; /* non zero if initialized */ + u32 seq; +}; + +struct ft_remote_seq { + struct ft_remote_seq_rx rx; + struct ft_remote_seq_tx tx; +}; + +#endif /* CONFIG_IEEE80211R_AP */ + + +int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len, + const u8 *pmkid); +#if 0 == CFG_ENABLE_WPA_LOG +#define wpa_auth_logger(args...) do {} while (0) +#define wpa_auth_vlogger(args...) do {} while (0) +#else +void wpa_auth_logger(struct wpa_authenticator *wpa_auth, const u8 *addr, + logger_level level, const char *txt); +void wpa_auth_vlogger(struct wpa_authenticator *wpa_auth, const u8 *addr, + logger_level level, const char *fmt, ...); +#endif +void __wpa_send_eapol(struct wpa_authenticator *wpa_auth, + struct wpa_state_machine *sm, int key_info, + const u8 *key_rsc, const u8 *nonce, + const u8 *kde, size_t kde_len, + int keyidx, int encr, int force_version); +int wpa_auth_for_each_sta(struct wpa_authenticator *wpa_auth, + int (*cb)(struct wpa_state_machine *sm, void *ctx), + void *cb_ctx); +int wpa_auth_for_each_auth(struct wpa_authenticator *wpa_auth, + int (*cb)(struct wpa_authenticator *a, void *ctx), + void *cb_ctx); + +#ifdef CONFIG_IEEE80211R_AP +int wpa_write_mdie(struct wpa_auth_config *conf, u8 *buf, size_t len); +int wpa_write_ftie(struct wpa_auth_config *conf, int use_sha384, + const u8 *r0kh_id, size_t r0kh_id_len, + const u8 *anonce, const u8 *snonce, + u8 *buf, size_t len, const u8 *subelem, + size_t subelem_len); +int wpa_auth_derive_ptk_ft(struct wpa_state_machine *sm, struct wpa_ptk *ptk); +struct wpa_ft_pmk_cache * wpa_ft_pmk_cache_init(void); +void wpa_ft_pmk_cache_deinit(struct wpa_ft_pmk_cache *cache); +void wpa_ft_install_ptk(struct wpa_state_machine *sm); +int wpa_ft_store_pmk_fils(struct wpa_state_machine *sm, const u8 *pmk_r0, + const u8 *pmk_r0_name); +#endif /* CONFIG_IEEE80211R_AP */ + +#endif /* WPA_AUTH_I_H */ diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/wpa_auth_ie.c b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/wpa_auth_ie.c new file mode 100755 index 0000000..fdf72a7 --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/wpa_auth_ie.c @@ -0,0 +1,1222 @@ +/* + * hostapd - WPA/RSN IE and KDE definitions + * Copyright (c) 2004-2018, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" + +#include "utils/common.h" +#include "common/ieee802_11_defs.h" +#include "eapol_auth/eapol_auth_sm.h" +#include "ap_config.h" +#include "ieee802_11.h" +#include "wpa_auth.h" +#include "pmksa_cache_auth.h" +#include "wpa_auth_ie.h" +#include "wpa_auth_i.h" + + +#ifdef CONFIG_RSN_TESTING +int rsn_testing = 0; +#endif /* CONFIG_RSN_TESTING */ + + +static int wpa_write_wpa_ie(struct wpa_auth_config *conf, u8 *buf, size_t len) +{ + struct wpa_ie_hdr *hdr; + int num_suites; + u8 *pos, *count; + u32 suite; + + hdr = (struct wpa_ie_hdr *) buf; + hdr->elem_id = WLAN_EID_VENDOR_SPECIFIC; + RSN_SELECTOR_PUT(hdr->oui, WPA_OUI_TYPE); + WPA_PUT_LE16(hdr->version, WPA_VERSION); + pos = (u8 *) (hdr + 1); + + suite = wpa_cipher_to_suite(WPA_PROTO_WPA, conf->wpa_group); + if (suite == 0) { + wpa_printf(MSG_DEBUG, "Invalid group cipher (%d).", + conf->wpa_group); + return -1; + } + RSN_SELECTOR_PUT(pos, suite); + pos += WPA_SELECTOR_LEN; + + count = pos; + pos += 2; + + num_suites = wpa_cipher_put_suites(pos, conf->wpa_pairwise); + if (num_suites == 0) { + wpa_printf(MSG_DEBUG, "Invalid pairwise cipher (%d).", + conf->wpa_pairwise); + return -1; + } + pos += num_suites * WPA_SELECTOR_LEN; + WPA_PUT_LE16(count, num_suites); + + num_suites = 0; + count = pos; + pos += 2; + +#ifdef CONFIG_FULL_HOSTAPD + if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) { + RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_UNSPEC_802_1X); + pos += WPA_SELECTOR_LEN; + num_suites++; + } +#endif + if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) { + RSN_SELECTOR_PUT(pos, WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X); + pos += WPA_SELECTOR_LEN; + num_suites++; + } + + if (num_suites == 0) { + wpa_printf(MSG_DEBUG, "Invalid key management type (%d).", + conf->wpa_key_mgmt); + return -1; + } + WPA_PUT_LE16(count, num_suites); + + /* WPA Capabilities; use defaults, so no need to include it */ + + hdr->len = (pos - buf) - 2; + + return pos - buf; +} + + +int wpa_write_rsn_ie(struct wpa_auth_config *conf, u8 *buf, size_t len, + const u8 *pmkid) +{ + struct rsn_ie_hdr *hdr; + int num_suites, res; + u8 *pos, *count; + u16 capab; + u32 suite; + + hdr = (struct rsn_ie_hdr *) buf; + hdr->elem_id = WLAN_EID_RSN; + WPA_PUT_LE16(hdr->version, RSN_VERSION); + pos = (u8 *) (hdr + 1); + + suite = wpa_cipher_to_suite(WPA_PROTO_RSN, conf->wpa_group); + if (suite == 0) { + wpa_printf(MSG_DEBUG, "Invalid group cipher (%d).", + conf->wpa_group); + return -1; + } + RSN_SELECTOR_PUT(pos, suite); + pos += RSN_SELECTOR_LEN; + + num_suites = 0; + count = pos; + pos += 2; + +#ifdef CONFIG_RSN_TESTING + if (rsn_testing) { + RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 1)); + pos += RSN_SELECTOR_LEN; + num_suites++; + } +#endif /* CONFIG_RSN_TESTING */ + + res = rsn_cipher_put_suites(pos, conf->rsn_pairwise); + num_suites += res; + pos += res * RSN_SELECTOR_LEN; + +#ifdef CONFIG_RSN_TESTING + if (rsn_testing) { + RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 2)); + pos += RSN_SELECTOR_LEN; + num_suites++; + } +#endif /* CONFIG_RSN_TESTING */ + + if (num_suites == 0) { + wpa_printf(MSG_DEBUG, "Invalid pairwise cipher (%d).", + conf->rsn_pairwise); + return -1; + } + WPA_PUT_LE16(count, num_suites); + + num_suites = 0; + count = pos; + pos += 2; + +#ifdef CONFIG_RSN_TESTING + if (rsn_testing) { + RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 1)); + pos += RSN_SELECTOR_LEN; + num_suites++; + } +#endif /* CONFIG_RSN_TESTING */ + +#ifdef CONFIG_FULL_HOSTAPD + if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_UNSPEC_802_1X); + pos += RSN_SELECTOR_LEN; + num_suites++; + } +#endif + if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X); + pos += RSN_SELECTOR_LEN; + num_suites++; + } +#ifdef CONFIG_IEEE80211R_AP + if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X); + pos += RSN_SELECTOR_LEN; + num_suites++; + } +#ifdef CONFIG_SHA384 + if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_802_1X_SHA384); + pos += RSN_SELECTOR_LEN; + num_suites++; + } +#endif /* CONFIG_SHA384 */ + if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_PSK) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_PSK); + pos += RSN_SELECTOR_LEN; + num_suites++; + } +#endif /* CONFIG_IEEE80211R_AP */ +#ifdef CONFIG_IEEE80211W_AP + if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SHA256); + pos += RSN_SELECTOR_LEN; + num_suites++; + } + if (conf->wpa_key_mgmt & WPA_KEY_MGMT_PSK_SHA256) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_PSK_SHA256); + pos += RSN_SELECTOR_LEN; + num_suites++; + } +#endif /* CONFIG_IEEE80211W_AP */ +#ifdef CONFIG_SAE_AP + if (conf->wpa_key_mgmt & WPA_KEY_MGMT_SAE) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_SAE); + pos += RSN_SELECTOR_LEN; + num_suites++; + } + if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_SAE) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_SAE); + pos += RSN_SELECTOR_LEN; + num_suites++; + } +#endif /* CONFIG_SAE_AP */ +#ifdef CONFIG_FULL_HOSTAPD + if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SUITE_B); + pos += RSN_SELECTOR_LEN; + num_suites++; + } + if (conf->wpa_key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192); + pos += RSN_SELECTOR_LEN; + num_suites++; + } +#endif +#ifdef CONFIG_FILS + if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FILS_SHA256) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FILS_SHA256); + pos += RSN_SELECTOR_LEN; + num_suites++; + } + if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FILS_SHA384) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FILS_SHA384); + pos += RSN_SELECTOR_LEN; + num_suites++; + } +#ifdef CONFIG_IEEE80211R_AP + if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_FILS_SHA256); + pos += RSN_SELECTOR_LEN; + num_suites++; + } + if (conf->wpa_key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_FT_FILS_SHA384); + pos += RSN_SELECTOR_LEN; + num_suites++; + } +#endif /* CONFIG_IEEE80211R_AP */ +#endif /* CONFIG_FILS */ +#ifdef CONFIG_OWE + if (conf->wpa_key_mgmt & WPA_KEY_MGMT_OWE) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_OWE); + pos += RSN_SELECTOR_LEN; + num_suites++; + } +#endif /* CONFIG_OWE */ +#ifdef CONFIG_DPP + if (conf->wpa_key_mgmt & WPA_KEY_MGMT_DPP) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_DPP); + pos += RSN_SELECTOR_LEN; + num_suites++; + } +#endif /* CONFIG_DPP */ +#ifdef CONFIG_HS20 + if (conf->wpa_key_mgmt & WPA_KEY_MGMT_OSEN) { + RSN_SELECTOR_PUT(pos, RSN_AUTH_KEY_MGMT_OSEN); + pos += RSN_SELECTOR_LEN; + num_suites++; + } +#endif /* CONFIG_HS20 */ + +#ifdef CONFIG_RSN_TESTING + if (rsn_testing) { + RSN_SELECTOR_PUT(pos, RSN_SELECTOR(0x12, 0x34, 0x56, 2)); + pos += RSN_SELECTOR_LEN; + num_suites++; + } +#endif /* CONFIG_RSN_TESTING */ + + if (num_suites == 0) { + wpa_printf(MSG_DEBUG, "Invalid key management type (%d).", + conf->wpa_key_mgmt); + return -1; + } + WPA_PUT_LE16(count, num_suites); + + /* RSN Capabilities */ + capab = 0; + if (conf->rsn_preauth) + capab |= WPA_CAPABILITY_PREAUTH; + if (conf->wmm_enabled) { + /* 4 PTKSA replay counters when using WMM */ + capab |= (RSN_NUM_REPLAY_COUNTERS_16 << 2); + } +#ifdef CONFIG_IEEE80211W_AP + if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) { + capab |= WPA_CAPABILITY_MFPC; + if (conf->ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED) + capab |= WPA_CAPABILITY_MFPR; + } +#endif /* CONFIG_IEEE80211W_AP */ +#ifdef CONFIG_OCV + if (conf->ocv) + capab |= WPA_CAPABILITY_OCVC; +#endif /* CONFIG_OCV */ +#ifdef CONFIG_RSN_TESTING + if (rsn_testing) + capab |= BIT(8) | BIT(15); +#endif /* CONFIG_RSN_TESTING */ + WPA_PUT_LE16(pos, capab); + pos += 2; + + if (pmkid) { + if (2 + PMKID_LEN > buf + len - pos) + return -1; + /* PMKID Count */ + WPA_PUT_LE16(pos, 1); + pos += 2; + os_memcpy(pos, pmkid, PMKID_LEN); + pos += PMKID_LEN; + } + +#ifdef CONFIG_IEEE80211W_AP + if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION && + conf->group_mgmt_cipher != WPA_CIPHER_AES_128_CMAC) { + if (2 + 4 > buf + len - pos) + return -1; + if (pmkid == NULL) { + /* PMKID Count */ + WPA_PUT_LE16(pos, 0); + pos += 2; + } + + /* Management Group Cipher Suite */ + switch (conf->group_mgmt_cipher) { + case WPA_CIPHER_AES_128_CMAC: + RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC); + break; + case WPA_CIPHER_BIP_GMAC_128: + RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_BIP_GMAC_128); + break; + case WPA_CIPHER_BIP_GMAC_256: + RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_BIP_GMAC_256); + break; + case WPA_CIPHER_BIP_CMAC_256: + RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_BIP_CMAC_256); + break; + default: + wpa_printf(MSG_DEBUG, + "Invalid group management cipher (0x%x)", + conf->group_mgmt_cipher); + return -1; + } + pos += RSN_SELECTOR_LEN; + } +#endif /* CONFIG_IEEE80211W_AP */ + +#ifdef CONFIG_RSN_TESTING + if (rsn_testing) { + /* + * Fill in any defined fields and add extra data to the end of + * the element. + */ + int pmkid_count_set = pmkid != NULL; + if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) + pmkid_count_set = 1; + /* PMKID Count */ + WPA_PUT_LE16(pos, 0); + pos += 2; + if (conf->ieee80211w == NO_MGMT_FRAME_PROTECTION) { + /* Management Group Cipher Suite */ + RSN_SELECTOR_PUT(pos, RSN_CIPHER_SUITE_AES_128_CMAC); + pos += RSN_SELECTOR_LEN; + } + + os_memset(pos, 0x12, 17); + pos += 17; + } +#endif /* CONFIG_RSN_TESTING */ + + hdr->len = (pos - buf) - 2; + + return pos - buf; +} + + +static u8 * wpa_write_osen(struct wpa_auth_config *conf, u8 *eid) +{ + u8 *len; + u16 capab; + + *eid++ = WLAN_EID_VENDOR_SPECIFIC; + len = eid++; /* to be filled */ + WPA_PUT_BE24(eid, OUI_WFA); + eid += 3; + *eid++ = HS20_OSEN_OUI_TYPE; + + /* Group Data Cipher Suite */ + RSN_SELECTOR_PUT(eid, RSN_CIPHER_SUITE_NO_GROUP_ADDRESSED); + eid += RSN_SELECTOR_LEN; + + /* Pairwise Cipher Suite Count and List */ + WPA_PUT_LE16(eid, 1); + eid += 2; + RSN_SELECTOR_PUT(eid, RSN_CIPHER_SUITE_CCMP); + eid += RSN_SELECTOR_LEN; + + /* AKM Suite Count and List */ + WPA_PUT_LE16(eid, 1); + eid += 2; + RSN_SELECTOR_PUT(eid, RSN_AUTH_KEY_MGMT_OSEN); + eid += RSN_SELECTOR_LEN; + + /* RSN Capabilities */ + capab = 0; + if (conf->wmm_enabled) { + /* 4 PTKSA replay counters when using WMM */ + capab |= (RSN_NUM_REPLAY_COUNTERS_16 << 2); + } +#ifdef CONFIG_IEEE80211W_AP + if (conf->ieee80211w != NO_MGMT_FRAME_PROTECTION) { + capab |= WPA_CAPABILITY_MFPC; + if (conf->ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED) + capab |= WPA_CAPABILITY_MFPR; + } +#endif /* CONFIG_IEEE80211W_AP */ +#ifdef CONFIG_OCV + if (conf->ocv) + capab |= WPA_CAPABILITY_OCVC; +#endif /* CONFIG_OCV */ + WPA_PUT_LE16(eid, capab); + eid += 2; + + *len = eid - len - 1; + + return eid; +} + + +int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth) +{ + u8 *pos, buf[128]; + int res; + +#ifdef CONFIG_TESTING_OPTIONS + if (wpa_auth->conf.own_ie_override_len) { + wpa_hexdump(MSG_DEBUG, "WPA: Forced own IE(s) for testing", + wpa_auth->conf.own_ie_override, + wpa_auth->conf.own_ie_override_len); + os_free(wpa_auth->wpa_ie); + wpa_auth->wpa_ie = + os_malloc(wpa_auth->conf.own_ie_override_len); + if (wpa_auth->wpa_ie == NULL) + return -1; + os_memcpy(wpa_auth->wpa_ie, wpa_auth->conf.own_ie_override, + wpa_auth->conf.own_ie_override_len); + wpa_auth->wpa_ie_len = wpa_auth->conf.own_ie_override_len; + return 0; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + pos = buf; + +#ifdef CONFIG_FULL_HOSTAPD + if (wpa_auth->conf.wpa == WPA_PROTO_OSEN) { + pos = wpa_write_osen(&wpa_auth->conf, pos); + } +#endif + if (wpa_auth->conf.wpa & WPA_PROTO_RSN) { + res = wpa_write_rsn_ie(&wpa_auth->conf, + pos, buf + sizeof(buf) - pos, NULL); + if (res < 0) + return res; + pos += res; + } +#ifdef CONFIG_IEEE80211R_AP + if (wpa_key_mgmt_ft(wpa_auth->conf.wpa_key_mgmt)) { + res = wpa_write_mdie(&wpa_auth->conf, pos, + buf + sizeof(buf) - pos); + if (res < 0) + return res; + pos += res; + } +#endif /* CONFIG_IEEE80211R_AP */ + if (wpa_auth->conf.wpa & WPA_PROTO_WPA) { + res = wpa_write_wpa_ie(&wpa_auth->conf, + pos, buf + sizeof(buf) - pos); + if (res < 0) + return res; + pos += res; + } + + os_free(wpa_auth->wpa_ie); + wpa_auth->wpa_ie = os_malloc(pos - buf); + if (wpa_auth->wpa_ie == NULL) + return -1; + os_memcpy(wpa_auth->wpa_ie, buf, pos - buf); + wpa_auth->wpa_ie_len = pos - buf; + + return 0; +} + + +u8 * wpa_add_kde(u8 *pos, u32 kde, const u8 *data, size_t data_len, + const u8 *data2, size_t data2_len) +{ + *pos++ = WLAN_EID_VENDOR_SPECIFIC; + *pos++ = RSN_SELECTOR_LEN + data_len + data2_len; + RSN_SELECTOR_PUT(pos, kde); + pos += RSN_SELECTOR_LEN; + os_memcpy(pos, data, data_len); + pos += data_len; + if (data2) { + os_memcpy(pos, data2, data2_len); + pos += data2_len; + } + return pos; +} + + +struct wpa_auth_okc_iter_data { + struct rsn_pmksa_cache_entry *pmksa; + const u8 *aa; + const u8 *spa; + const u8 *pmkid; +}; + + +static int wpa_auth_okc_iter(struct wpa_authenticator *a, void *ctx) +{ + struct wpa_auth_okc_iter_data *data = ctx; + data->pmksa = pmksa_cache_get_okc(a->pmksa, data->aa, data->spa, + data->pmkid); + if (data->pmksa) + return 1; + return 0; +} + + +int wpa_validate_wpa_ie(struct wpa_authenticator *wpa_auth, + struct wpa_state_machine *sm, int freq, + const u8 *wpa_ie, size_t wpa_ie_len, + const u8 *mdie, size_t mdie_len, + const u8 *owe_dh, size_t owe_dh_len) +{ + struct wpa_ie_data data; + int ciphers, key_mgmt, res, version; + u32 selector; + size_t i; + const u8 *pmkid = NULL; + + if (wpa_auth == NULL || sm == NULL) + return WPA_NOT_ENABLED; + + if (wpa_ie == NULL || wpa_ie_len < 1) + return WPA_INVALID_IE; + + if (wpa_ie[0] == WLAN_EID_RSN) + version = WPA_PROTO_RSN; + else + version = WPA_PROTO_WPA; + + if (!(wpa_auth->conf.wpa & version)) { + wpa_printf(MSG_DEBUG, "Invalid WPA proto (%d) from " MACSTR, + version, MAC2STR(sm->addr)); + return WPA_INVALID_PROTO; + } + + if (version == WPA_PROTO_RSN) { + res = wpa_parse_wpa_ie_rsn(wpa_ie, wpa_ie_len, &data); + if (!data.has_pairwise) + data.pairwise_cipher = wpa_default_rsn_cipher(freq); + if (!data.has_group) + data.group_cipher = wpa_default_rsn_cipher(freq); + +#ifdef CONFIG_FULL_HOSTAPD + if (wpa_key_mgmt_ft(data.key_mgmt) && !mdie && + !wpa_key_mgmt_only_ft(data.key_mgmt)) { + /* Workaround for some HP and Epson printers that seem + * to incorrectly copy the FT-PSK + WPA-PSK AKMs from AP + * advertised RSNE to Association Request frame. */ + wpa_printf(MSG_DEBUG, + "RSN: FT set in RSNE AKM but MDE is missing from " + MACSTR + " - ignore FT AKM(s) because there's also a non-FT AKM", + MAC2STR(sm->addr)); + data.key_mgmt &= ~WPA_KEY_MGMT_FT; + } +#endif + selector = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X; + if (0) { + } +#ifdef CONFIG_FULL_HOSTAPD + else if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) + selector = RSN_AUTH_KEY_MGMT_802_1X_SUITE_B_192; + else if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) + selector = RSN_AUTH_KEY_MGMT_802_1X_SUITE_B; +#endif +#ifdef CONFIG_FILS +#ifdef CONFIG_IEEE80211R_AP + else if (data.key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384) + selector = RSN_AUTH_KEY_MGMT_FT_FILS_SHA384; + else if (data.key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256) + selector = RSN_AUTH_KEY_MGMT_FT_FILS_SHA256; +#endif /* CONFIG_IEEE80211R_AP */ + else if (data.key_mgmt & WPA_KEY_MGMT_FILS_SHA384) + selector = RSN_AUTH_KEY_MGMT_FILS_SHA384; + else if (data.key_mgmt & WPA_KEY_MGMT_FILS_SHA256) + selector = RSN_AUTH_KEY_MGMT_FILS_SHA256; +#endif /* CONFIG_FILS */ +#ifdef CONFIG_IEEE80211R_AP +#ifdef CONFIG_SHA384 + else if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) + selector = RSN_AUTH_KEY_MGMT_FT_802_1X_SHA384; +#endif /* CONFIG_SHA384 */ + else if (data.key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) + selector = RSN_AUTH_KEY_MGMT_FT_802_1X; + else if (data.key_mgmt & WPA_KEY_MGMT_FT_PSK) + selector = RSN_AUTH_KEY_MGMT_FT_PSK; +#endif /* CONFIG_IEEE80211R_AP */ +#ifdef CONFIG_IEEE80211W_AP + else if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) + selector = RSN_AUTH_KEY_MGMT_802_1X_SHA256; + else if (data.key_mgmt & WPA_KEY_MGMT_PSK_SHA256) + selector = RSN_AUTH_KEY_MGMT_PSK_SHA256; +#endif /* CONFIG_IEEE80211W_AP */ +#ifdef CONFIG_SAE_AP + else if (data.key_mgmt & WPA_KEY_MGMT_SAE) + selector = RSN_AUTH_KEY_MGMT_SAE; + else if (data.key_mgmt & WPA_KEY_MGMT_FT_SAE) + selector = RSN_AUTH_KEY_MGMT_FT_SAE; +#endif /* CONFIG_SAE_AP */ +#ifdef CONFIG_FULL_HOSTAPD + else if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) + selector = RSN_AUTH_KEY_MGMT_UNSPEC_802_1X; +#endif + else if (data.key_mgmt & WPA_KEY_MGMT_PSK) + selector = RSN_AUTH_KEY_MGMT_PSK_OVER_802_1X; +#ifdef CONFIG_OWE + else if (data.key_mgmt & WPA_KEY_MGMT_OWE) + selector = RSN_AUTH_KEY_MGMT_OWE; +#endif /* CONFIG_OWE */ +#ifdef CONFIG_DPP + else if (data.key_mgmt & WPA_KEY_MGMT_DPP) + selector = RSN_AUTH_KEY_MGMT_DPP; +#endif /* CONFIG_DPP */ +#ifdef CONFIG_HS20 + else if (data.key_mgmt & WPA_KEY_MGMT_OSEN) + selector = RSN_AUTH_KEY_MGMT_OSEN; +#endif /* CONFIG_HS20 */ + wpa_auth->dot11RSNAAuthenticationSuiteSelected = selector; + + selector = wpa_cipher_to_suite(WPA_PROTO_RSN, + data.pairwise_cipher); + if (!selector) + selector = RSN_CIPHER_SUITE_CCMP; + wpa_auth->dot11RSNAPairwiseCipherSelected = selector; + + selector = wpa_cipher_to_suite(WPA_PROTO_RSN, + data.group_cipher); + if (!selector) + selector = RSN_CIPHER_SUITE_CCMP; + wpa_auth->dot11RSNAGroupCipherSelected = selector; + } else { + res = wpa_parse_wpa_ie_wpa(wpa_ie, wpa_ie_len, &data); + + selector = WPA_AUTH_KEY_MGMT_UNSPEC_802_1X; +#ifdef CONFIG_FULL_HOSTAPD + if (data.key_mgmt & WPA_KEY_MGMT_IEEE8021X) + selector = WPA_AUTH_KEY_MGMT_UNSPEC_802_1X; + else +#endif + if (data.key_mgmt & WPA_KEY_MGMT_PSK) + selector = WPA_AUTH_KEY_MGMT_PSK_OVER_802_1X; + wpa_auth->dot11RSNAAuthenticationSuiteSelected = selector; + + selector = wpa_cipher_to_suite(WPA_PROTO_WPA, + data.pairwise_cipher); + if (!selector) + selector = RSN_CIPHER_SUITE_TKIP; + wpa_auth->dot11RSNAPairwiseCipherSelected = selector; + + selector = wpa_cipher_to_suite(WPA_PROTO_WPA, + data.group_cipher); + if (!selector) + selector = WPA_CIPHER_SUITE_TKIP; + wpa_auth->dot11RSNAGroupCipherSelected = selector; + } + if (res) { + wpa_printf(MSG_DEBUG, "Failed to parse WPA/RSN IE from " + MACSTR " (res=%d)", MAC2STR(sm->addr), res); + wpa_hexdump(MSG_DEBUG, "WPA/RSN IE", wpa_ie, wpa_ie_len); + return WPA_INVALID_IE; + } + + if (data.group_cipher != wpa_auth->conf.wpa_group) { + wpa_printf(MSG_DEBUG, "Invalid WPA group cipher (0x%x) from " + MACSTR, data.group_cipher, MAC2STR(sm->addr)); + return WPA_INVALID_GROUP; + } + + key_mgmt = data.key_mgmt & wpa_auth->conf.wpa_key_mgmt; + if (!key_mgmt) { + wpa_printf(MSG_DEBUG, "Invalid WPA key mgmt (0x%x) from " + MACSTR, data.key_mgmt, MAC2STR(sm->addr)); + return WPA_INVALID_AKMP; + } + if (0) { + } +#ifdef CONFIG_FULL_HOSTAPD + else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B_192) + sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B_192; + else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SUITE_B) + sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X_SUITE_B; +#endif +#ifdef CONFIG_FILS +#ifdef CONFIG_IEEE80211R_AP + else if (key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA384) + sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA384; + else if (data.key_mgmt & WPA_KEY_MGMT_FT_FILS_SHA256) + sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_FILS_SHA256; +#endif /* CONFIG_IEEE80211R_AP */ + else if (key_mgmt & WPA_KEY_MGMT_FILS_SHA384) + sm->wpa_key_mgmt = WPA_KEY_MGMT_FILS_SHA384; + else if (key_mgmt & WPA_KEY_MGMT_FILS_SHA256) + sm->wpa_key_mgmt = WPA_KEY_MGMT_FILS_SHA256; +#endif /* CONFIG_FILS */ +#ifdef CONFIG_IEEE80211R_AP +#ifdef CONFIG_SHA384 + else if (key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X_SHA384) + sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X_SHA384; +#endif /* CONFIG_SHA384 */ + else if (key_mgmt & WPA_KEY_MGMT_FT_IEEE8021X) + sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_IEEE8021X; + else if (key_mgmt & WPA_KEY_MGMT_FT_PSK) + sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_PSK; +#endif /* CONFIG_IEEE80211R_AP */ +#ifdef CONFIG_IEEE80211W_AP + else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X_SHA256) + sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X_SHA256; + else if (key_mgmt & WPA_KEY_MGMT_PSK_SHA256) + sm->wpa_key_mgmt = WPA_KEY_MGMT_PSK_SHA256; +#endif /* CONFIG_IEEE80211W_AP */ +#ifdef CONFIG_SAE_AP + else if (key_mgmt & WPA_KEY_MGMT_SAE) + sm->wpa_key_mgmt = WPA_KEY_MGMT_SAE; + else if (key_mgmt & WPA_KEY_MGMT_FT_SAE) + sm->wpa_key_mgmt = WPA_KEY_MGMT_FT_SAE; +#endif /* CONFIG_SAE_AP */ +#ifdef CONFIG_FULL_HOSTAPD + else if (key_mgmt & WPA_KEY_MGMT_IEEE8021X) + sm->wpa_key_mgmt = WPA_KEY_MGMT_IEEE8021X; +#endif +#ifdef CONFIG_OWE + else if (key_mgmt & WPA_KEY_MGMT_OWE) + sm->wpa_key_mgmt = WPA_KEY_MGMT_OWE; +#endif /* CONFIG_OWE */ +#ifdef CONFIG_DPP + else if (key_mgmt & WPA_KEY_MGMT_DPP) + sm->wpa_key_mgmt = WPA_KEY_MGMT_DPP; +#endif /* CONFIG_DPP */ +#ifdef CONFIG_HS20 + else if (key_mgmt & WPA_KEY_MGMT_OSEN) + sm->wpa_key_mgmt = WPA_KEY_MGMT_OSEN; +#endif /* CONFIG_HS20 */ + else + sm->wpa_key_mgmt = WPA_KEY_MGMT_PSK; + + if (version == WPA_PROTO_RSN) + ciphers = data.pairwise_cipher & wpa_auth->conf.rsn_pairwise; + else + ciphers = data.pairwise_cipher & wpa_auth->conf.wpa_pairwise; + if (!ciphers) { + wpa_printf(MSG_DEBUG, "Invalid %s pairwise cipher (0x%x) " + "from " MACSTR, + version == WPA_PROTO_RSN ? "RSN" : "WPA", + data.pairwise_cipher, MAC2STR(sm->addr)); + return WPA_INVALID_PAIRWISE; + } + +#ifdef CONFIG_IEEE80211W_AP + if (wpa_auth->conf.ieee80211w == MGMT_FRAME_PROTECTION_REQUIRED) { + if (!(data.capabilities & WPA_CAPABILITY_MFPC)) { + wpa_printf(MSG_DEBUG, "Management frame protection " + "required, but client did not enable it"); + return WPA_MGMT_FRAME_PROTECTION_VIOLATION; + } + + if (data.mgmt_group_cipher != wpa_auth->conf.group_mgmt_cipher) + { + wpa_printf(MSG_DEBUG, "Unsupported management group " + "cipher %d", data.mgmt_group_cipher); + return WPA_INVALID_MGMT_GROUP_CIPHER; + } + } + +#ifdef CONFIG_SAE_AP + if (wpa_auth->conf.ieee80211w == MGMT_FRAME_PROTECTION_OPTIONAL && + wpa_auth->conf.sae_require_mfp && + wpa_key_mgmt_sae(sm->wpa_key_mgmt) && + !(data.capabilities & WPA_CAPABILITY_MFPC)) { + wpa_printf(MSG_DEBUG, + "Management frame protection required with SAE, but client did not enable it"); + return WPA_MGMT_FRAME_PROTECTION_VIOLATION; + } +#endif /* CONFIG_SAE_AP */ + +#ifdef CONFIG_OCV + if ((data.capabilities & WPA_CAPABILITY_OCVC) && + !(data.capabilities & WPA_CAPABILITY_MFPC)) { + wpa_printf(MSG_DEBUG, + "Management frame protection required with OCV, but client did not enable it"); + return WPA_MGMT_FRAME_PROTECTION_VIOLATION; + } + wpa_auth_set_ocv(sm, wpa_auth->conf.ocv && + (data.capabilities & WPA_CAPABILITY_OCVC)); +#endif /* CONFIG_OCV */ + + if (wpa_auth->conf.ieee80211w == NO_MGMT_FRAME_PROTECTION || + !(data.capabilities & WPA_CAPABILITY_MFPC)) + sm->mgmt_frame_prot = 0; + else + sm->mgmt_frame_prot = 1; + + if (sm->mgmt_frame_prot && (ciphers & WPA_CIPHER_TKIP)) { + wpa_printf(MSG_DEBUG, + "Management frame protection cannot use TKIP"); + return WPA_MGMT_FRAME_PROTECTION_VIOLATION; + } +#endif /* CONFIG_IEEE80211W_AP */ + +#ifdef CONFIG_IEEE80211R_AP + if (wpa_key_mgmt_ft(sm->wpa_key_mgmt)) { + if (mdie == NULL || mdie_len < MOBILITY_DOMAIN_ID_LEN + 1) { + wpa_printf(MSG_DEBUG, "RSN: Trying to use FT, but " + "MDIE not included"); + return WPA_INVALID_MDIE; + } + if (os_memcmp(mdie, wpa_auth->conf.mobility_domain, + MOBILITY_DOMAIN_ID_LEN) != 0) { + wpa_hexdump(MSG_DEBUG, "RSN: Attempted to use unknown " + "MDIE", mdie, MOBILITY_DOMAIN_ID_LEN); + return WPA_INVALID_MDIE; + } + } else if (mdie != NULL) { + wpa_printf(MSG_DEBUG, + "RSN: Trying to use non-FT AKM suite, but MDIE included"); + return WPA_INVALID_AKMP; + } +#endif /* CONFIG_IEEE80211R_AP */ + +#ifdef CONFIG_OWE + if (sm->wpa_key_mgmt == WPA_KEY_MGMT_OWE && !owe_dh) { + wpa_printf(MSG_DEBUG, + "OWE: No Diffie-Hellman Parameter element"); + return WPA_INVALID_AKMP; + } +#ifdef CONFIG_DPP + if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP && owe_dh) { + /* Diffie-Hellman Parameter element can be used with DPP as + * well, so allow this to proceed. */ + } else +#endif /* CONFIG_DPP */ + if (sm->wpa_key_mgmt != WPA_KEY_MGMT_OWE && owe_dh) { + wpa_printf(MSG_DEBUG, + "OWE: Unexpected Diffie-Hellman Parameter element with non-OWE AKM"); + return WPA_INVALID_AKMP; + } +#endif /* CONFIG_OWE */ + + sm->pairwise = wpa_pick_pairwise_cipher(ciphers, 0); + if (sm->pairwise < 0) + return WPA_INVALID_PAIRWISE; + + /* TODO: clear WPA/WPA2 state if STA changes from one to another */ + if (wpa_ie[0] == WLAN_EID_RSN) + sm->wpa = WPA_VERSION_WPA2; + else + sm->wpa = WPA_VERSION_WPA; + +#if defined(CONFIG_IEEE80211R_AP) && defined(CONFIG_FILS) + if ((sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_FILS_SHA256 || + sm->wpa_key_mgmt == WPA_KEY_MGMT_FT_FILS_SHA384) && + (sm->auth_alg == WLAN_AUTH_FILS_SK || + sm->auth_alg == WLAN_AUTH_FILS_SK_PFS || + sm->auth_alg == WLAN_AUTH_FILS_PK) && + (data.num_pmkid != 1 || !data.pmkid || !sm->pmk_r1_name_valid || + os_memcmp_const(data.pmkid, sm->pmk_r1_name, + WPA_PMK_NAME_LEN) != 0)) { + wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, + "No PMKR1Name match for FILS+FT"); + return WPA_INVALID_PMKID; + } +#endif /* CONFIG_IEEE80211R_AP && CONFIG_FILS */ + + sm->pmksa = NULL; + for (i = 0; i < data.num_pmkid; i++) { + wpa_hexdump(MSG_DEBUG, "RSN IE: STA PMKID", + &data.pmkid[i * PMKID_LEN], PMKID_LEN); + sm->pmksa = pmksa_cache_auth_get(wpa_auth->pmksa, sm->addr, + &data.pmkid[i * PMKID_LEN]); + if (sm->pmksa) { + pmkid = sm->pmksa->pmkid; + break; + } + } +#ifdef CONFIG_FULL_HOSTAPD + for (i = 0; sm->pmksa == NULL && wpa_auth->conf.okc && + i < data.num_pmkid; i++) { + struct wpa_auth_okc_iter_data idata; + idata.pmksa = NULL; + idata.aa = wpa_auth->addr; + idata.spa = sm->addr; + idata.pmkid = &data.pmkid[i * PMKID_LEN]; + wpa_auth_for_each_auth(wpa_auth, wpa_auth_okc_iter, &idata); + if (idata.pmksa) { + wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, + "OKC match for PMKID"); + sm->pmksa = pmksa_cache_add_okc(wpa_auth->pmksa, + idata.pmksa, + wpa_auth->addr, + idata.pmkid); + pmkid = idata.pmkid; + break; + } + } +#endif + if (sm->pmksa && pmkid) { + struct vlan_description *vlan; + + vlan = sm->pmksa->vlan_desc; + wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, + "PMKID found from PMKSA cache eap_type=%d vlan=%d%s", + sm->pmksa->eap_type_authsrv, + vlan ? vlan->untagged : 0, + (vlan && vlan->tagged[0]) ? "+" : ""); + os_memcpy(wpa_auth->dot11RSNAPMKIDUsed, pmkid, PMKID_LEN); + } + +#ifdef CONFIG_SAE_AP + if (sm->wpa_key_mgmt == WPA_KEY_MGMT_SAE && data.num_pmkid && + !sm->pmksa) { + wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, + "No PMKSA cache entry found for SAE"); + return WPA_INVALID_PMKID; + } +#endif /* CONFIG_SAE_AP */ + +#ifdef CONFIG_DPP + if (sm->wpa_key_mgmt == WPA_KEY_MGMT_DPP && !sm->pmksa) { + wpa_auth_vlogger(wpa_auth, sm->addr, LOGGER_DEBUG, + "No PMKSA cache entry found for DPP"); + return WPA_INVALID_PMKID; + } +#endif /* CONFIG_DPP */ + + if (sm->wpa_ie == NULL || sm->wpa_ie_len < wpa_ie_len) { + os_free(sm->wpa_ie); + sm->wpa_ie = os_malloc(wpa_ie_len); + if (sm->wpa_ie == NULL) + return WPA_ALLOC_FAIL; + } + os_memcpy(sm->wpa_ie, wpa_ie, wpa_ie_len); + sm->wpa_ie_len = wpa_ie_len; + + return WPA_IE_OK; +} + + +#ifdef CONFIG_HS20 +int wpa_validate_osen(struct wpa_authenticator *wpa_auth, + struct wpa_state_machine *sm, + const u8 *osen_ie, size_t osen_ie_len) +{ + if (wpa_auth == NULL || sm == NULL) + return -1; + + /* TODO: parse OSEN element */ + sm->wpa_key_mgmt = WPA_KEY_MGMT_OSEN; + sm->mgmt_frame_prot = 1; + sm->pairwise = WPA_CIPHER_CCMP; + sm->wpa = WPA_VERSION_WPA2; + + if (sm->wpa_ie == NULL || sm->wpa_ie_len < osen_ie_len) { + os_free(sm->wpa_ie); + sm->wpa_ie = os_malloc(osen_ie_len); + if (sm->wpa_ie == NULL) + return -1; + } + + os_memcpy(sm->wpa_ie, osen_ie, osen_ie_len); + sm->wpa_ie_len = osen_ie_len; + + return 0; +} + +#endif /* CONFIG_HS20 */ + + +/** + * wpa_parse_generic - Parse EAPOL-Key Key Data Generic IEs + * @pos: Pointer to the IE header + * @end: Pointer to the end of the Key Data buffer + * @ie: Pointer to parsed IE data + * Returns: 0 on success, 1 if end mark is found, -1 on failure + */ +static int wpa_parse_generic(const u8 *pos, const u8 *end, + struct wpa_eapol_ie_parse *ie) +{ + if (pos[1] == 0) + return 1; + + if (pos[1] >= 6 && + RSN_SELECTOR_GET(pos + 2) == WPA_OUI_TYPE && + pos[2 + WPA_SELECTOR_LEN] == 1 && + pos[2 + WPA_SELECTOR_LEN + 1] == 0) { + ie->wpa_ie = pos; + ie->wpa_ie_len = pos[1] + 2; + return 0; + } + +#ifdef CONFIG_FULL_HOSTAPD + if (pos[1] >= 4 && WPA_GET_BE32(pos + 2) == OSEN_IE_VENDOR_TYPE) { + ie->osen = pos; + ie->osen_len = pos[1] + 2; + return 0; + } +#endif + + if (1 + RSN_SELECTOR_LEN < end - pos && + pos[1] >= RSN_SELECTOR_LEN + PMKID_LEN && + RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_PMKID) { + ie->pmkid = pos + 2 + RSN_SELECTOR_LEN; + return 0; + } + + if (pos[1] > RSN_SELECTOR_LEN + 2 && + RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_GROUPKEY) { + ie->gtk = pos + 2 + RSN_SELECTOR_LEN; + ie->gtk_len = pos[1] - RSN_SELECTOR_LEN; + return 0; + } + + if (pos[1] > RSN_SELECTOR_LEN + 2 && + RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_MAC_ADDR) { + ie->mac_addr = pos + 2 + RSN_SELECTOR_LEN; + ie->mac_addr_len = pos[1] - RSN_SELECTOR_LEN; + return 0; + } + +#ifdef CONFIG_IEEE80211W_AP + if (pos[1] > RSN_SELECTOR_LEN + 2 && + RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_IGTK) { + ie->igtk = pos + 2 + RSN_SELECTOR_LEN; + ie->igtk_len = pos[1] - RSN_SELECTOR_LEN; + return 0; + } +#endif /* CONFIG_IEEE80211W_AP */ + +#ifdef CONFIG_P2P + if (pos[1] >= RSN_SELECTOR_LEN + 1 && + RSN_SELECTOR_GET(pos + 2) == WFA_KEY_DATA_IP_ADDR_REQ) { + ie->ip_addr_req = pos + 2 + RSN_SELECTOR_LEN; + wpa_hexdump(MSG_DEBUG, "WPA: IP Address Request in EAPOL-Key", + ie->ip_addr_req, pos[1] - RSN_SELECTOR_LEN); + return 0; + } + + if (pos[1] >= RSN_SELECTOR_LEN + 3 * 4 && + RSN_SELECTOR_GET(pos + 2) == WFA_KEY_DATA_IP_ADDR_ALLOC) { + ie->ip_addr_alloc = pos + 2 + RSN_SELECTOR_LEN; + wpa_hexdump(MSG_DEBUG, + "WPA: IP Address Allocation in EAPOL-Key", + ie->ip_addr_alloc, pos[1] - RSN_SELECTOR_LEN); + return 0; + } +#endif /* CONFIG_P2P */ + +#ifdef CONFIG_OCV + if (pos[1] > RSN_SELECTOR_LEN + 2 && + RSN_SELECTOR_GET(pos + 2) == RSN_KEY_DATA_OCI) { + ie->oci = pos + 2 + RSN_SELECTOR_LEN; + ie->oci_len = pos[1] - RSN_SELECTOR_LEN; + return 0; + } +#endif /* CONFIG_OCV */ + + return 0; +} + + +/** + * wpa_parse_kde_ies - Parse EAPOL-Key Key Data IEs + * @buf: Pointer to the Key Data buffer + * @len: Key Data Length + * @ie: Pointer to parsed IE data + * Returns: 0 on success, -1 on failure + */ +int wpa_parse_kde_ies(const u8 *buf, size_t len, struct wpa_eapol_ie_parse *ie) +{ + const u8 *pos, *end; + int ret = 0; + + os_memset(ie, 0, sizeof(*ie)); + for (pos = buf, end = pos + len; end - pos > 1; pos += 2 + pos[1]) { + if (pos[0] == 0xdd && + ((pos == buf + len - 1) || pos[1] == 0)) { + /* Ignore padding */ + break; + } + if (2 + pos[1] > end - pos) { + wpa_printf(MSG_DEBUG, "WPA: EAPOL-Key Key Data " + "underflow (ie=%d len=%d pos=%d)", + pos[0], pos[1], (int) (pos - buf)); + wpa_hexdump_key(MSG_DEBUG, "WPA: Key Data", + buf, len); + ret = -1; + break; + } + if (*pos == WLAN_EID_RSN) { + ie->rsn_ie = pos; + ie->rsn_ie_len = pos[1] + 2; +#ifdef CONFIG_IEEE80211R_AP + } else if (*pos == WLAN_EID_MOBILITY_DOMAIN) { + ie->mdie = pos; + ie->mdie_len = pos[1] + 2; + } else if (*pos == WLAN_EID_FAST_BSS_TRANSITION) { + ie->ftie = pos; + ie->ftie_len = pos[1] + 2; +#endif /* CONFIG_IEEE80211R_AP */ + } else if (*pos == WLAN_EID_VENDOR_SPECIFIC) { + ret = wpa_parse_generic(pos, end, ie); + if (ret < 0) + break; + if (ret > 0) { + ret = 0; + break; + } + } else { + wpa_hexdump(MSG_DEBUG, "WPA: Unrecognized EAPOL-Key " + "Key Data IE", pos, 2 + pos[1]); + } + } + + return ret; +} + + +int wpa_auth_uses_mfp(struct wpa_state_machine *sm) +{ + return sm ? sm->mgmt_frame_prot : 0; +} + + +#ifdef CONFIG_OCV + +void wpa_auth_set_ocv(struct wpa_state_machine *sm, int ocv) +{ + if (sm) + sm->ocv_enabled = ocv; +} + + +int wpa_auth_uses_ocv(struct wpa_state_machine *sm) +{ + return sm ? sm->ocv_enabled : 0; +} + +#endif /* CONFIG_OCV */ + + +#ifdef CONFIG_OWE +u8 * wpa_auth_write_assoc_resp_owe(struct wpa_state_machine *sm, + u8 *pos, size_t max_len, + const u8 *req_ies, size_t req_ies_len) +{ + int res; + struct wpa_auth_config *conf; + + if (!sm) + return pos; + conf = &sm->wpa_auth->conf; + +#ifdef CONFIG_TESTING_OPTIONS + if (conf->own_ie_override_len) { + if (max_len < conf->own_ie_override_len) + return NULL; + wpa_hexdump(MSG_DEBUG, "WPA: Forced own IE(s) for testing", + conf->own_ie_override, conf->own_ie_override_len); + os_memcpy(pos, conf->own_ie_override, + conf->own_ie_override_len); + return pos + conf->own_ie_override_len; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + res = wpa_write_rsn_ie(conf, pos, max_len, + sm->pmksa ? sm->pmksa->pmkid : NULL); + if (res < 0) + return pos; + return pos + res; +} +#endif /* CONFIG_OWE */ + + +#ifdef CONFIG_FILS +u8 * wpa_auth_write_assoc_resp_fils(struct wpa_state_machine *sm, + u8 *pos, size_t max_len, + const u8 *req_ies, size_t req_ies_len) +{ + int res; + + if (!sm || + sm->wpa_key_mgmt & (WPA_KEY_MGMT_FT_FILS_SHA256 | + WPA_KEY_MGMT_FT_FILS_SHA384)) + return pos; + + res = wpa_write_rsn_ie(&sm->wpa_auth->conf, pos, max_len, NULL); + if (res < 0) + return pos; + return pos + res; +} +#endif /* CONFIG_FILS */ diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/wpa_auth_ie.h b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/wpa_auth_ie.h new file mode 100755 index 0000000..f18b26d --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/wpa_auth_ie.h @@ -0,0 +1,51 @@ +/* + * hostapd - WPA/RSN IE and KDE definitions + * Copyright (c) 2004-2007, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef WPA_AUTH_IE_H +#define WPA_AUTH_IE_H + +struct wpa_eapol_ie_parse { + const u8 *wpa_ie; + size_t wpa_ie_len; + const u8 *rsn_ie; + size_t rsn_ie_len; + const u8 *pmkid; + const u8 *gtk; + size_t gtk_len; + const u8 *mac_addr; + size_t mac_addr_len; +#ifdef CONFIG_IEEE80211W_AP + const u8 *igtk; + size_t igtk_len; +#endif /* CONFIG_IEEE80211W_AP */ +#ifdef CONFIG_IEEE80211R_AP + const u8 *mdie; + size_t mdie_len; + const u8 *ftie; + size_t ftie_len; +#endif /* CONFIG_IEEE80211R_AP */ +#ifdef CONFIG_P2P + const u8 *ip_addr_req; + const u8 *ip_addr_alloc; +#endif /* CONFIG_P2P */ +#ifdef CONFIG_OCV + const u8 *oci; + size_t oci_len; +#endif /* CONFIG_OCV */ + + const u8 *osen; + size_t osen_len; +}; + +int wpa_parse_kde_ies(const u8 *buf, size_t len, + struct wpa_eapol_ie_parse *ie); +u8 * wpa_add_kde(u8 *pos, u32 kde, const u8 *data, size_t data_len, + const u8 *data2, size_t data2_len); +int wpa_auth_gen_wpa_ie(struct wpa_authenticator *wpa_auth); + +#endif /* WPA_AUTH_IE_H */ diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/wpa_auth_kay.h b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/wpa_auth_kay.h new file mode 100755 index 0000000..0dd7e41 --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/wpa_auth_kay.h @@ -0,0 +1,51 @@ +/* + * IEEE 802.1X-2010 KaY Interface + * Copyright (c) 2019, The Linux Foundation + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef WPA_AUTH_KAY_H +#define WPA_AUTH_KAY_H + +#ifdef CONFIG_MACSEC + +int ieee802_1x_alloc_kay_sm_hapd(struct hostapd_data *hapd, + struct sta_info *sta); +void * ieee802_1x_notify_create_actor_hapd(struct hostapd_data *hapd, + struct sta_info *sta); +void ieee802_1x_dealloc_kay_sm_hapd(struct hostapd_data *hapd); + +void * ieee802_1x_create_preshared_mka_hapd(struct hostapd_data *hapd, + struct sta_info *sta); + +#else /* CONFIG_MACSEC */ + +static inline int ieee802_1x_alloc_kay_sm_hapd(struct hostapd_data *hapd, + struct sta_info *sta) +{ + return 0; +} + +static inline void * +ieee802_1x_notify_create_actor_hapd(struct hostapd_data *hapd, + struct sta_info *sta) +{ + return NULL; +} + +static inline void ieee802_1x_dealloc_kay_sm_hapd(struct hostapd_data *hapd) +{ +} + +static inline void * +ieee802_1x_create_preshared_mka_hapd(struct hostapd_data *hapd, + struct sta_info *sta) +{ + return NULL; +} + +#endif /* CONFIG_MACSEC */ + +#endif /* WPA_AUTH_KAY_H */ diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/wps_hostapd.h b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/wps_hostapd.h new file mode 100755 index 0000000..204bd82 --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/ap/wps_hostapd.h @@ -0,0 +1,92 @@ +/* + * hostapd / WPS integration + * Copyright (c) 2008-2012, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef WPS_HOSTAPD_H +#define WPS_HOSTAPD_H + +#ifdef CONFIG_WPS + +int hostapd_init_wps(struct hostapd_data *hapd, + struct hostapd_bss_config *conf); +int hostapd_init_wps_complete(struct hostapd_data *hapd); +void hostapd_deinit_wps(struct hostapd_data *hapd); +void hostapd_update_wps(struct hostapd_data *hapd); +void hostapd_wps_eap_completed(struct hostapd_data *hapd); +int hostapd_wps_add_pin(struct hostapd_data *hapd, const u8 *addr, + const char *uuid, const char *pin, int timeout); +int hostapd_wps_button_pushed(struct hostapd_data *hapd, + const u8 *p2p_dev_addr); +int hostapd_wps_cancel(struct hostapd_data *hapd); +int hostapd_wps_get_mib_sta(struct hostapd_data *hapd, const u8 *addr, + char *buf, size_t buflen); +void hostapd_wps_ap_pin_disable(struct hostapd_data *hapd); +const char * hostapd_wps_ap_pin_random(struct hostapd_data *hapd, int timeout); +const char * hostapd_wps_ap_pin_get(struct hostapd_data *hapd); +int hostapd_wps_ap_pin_set(struct hostapd_data *hapd, const char *pin, + int timeout); +void hostapd_wps_update_ie(struct hostapd_data *hapd); +int hostapd_wps_config_ap(struct hostapd_data *hapd, const char *ssid, + const char *auth, const char *encr, const char *key); +int hostapd_wps_nfc_tag_read(struct hostapd_data *hapd, + const struct wpabuf *data); +struct wpabuf * hostapd_wps_nfc_config_token(struct hostapd_data *hapd, + int ndef); +struct wpabuf * hostapd_wps_nfc_hs_cr(struct hostapd_data *hapd, int ndef); +int hostapd_wps_nfc_report_handover(struct hostapd_data *hapd, + const struct wpabuf *req, + const struct wpabuf *sel); +struct wpabuf * hostapd_wps_nfc_token_gen(struct hostapd_data *hapd, int ndef); +int hostapd_wps_nfc_token_enable(struct hostapd_data *hapd); +void hostapd_wps_nfc_token_disable(struct hostapd_data *hapd); + +#else /* CONFIG_WPS */ + +static inline int hostapd_init_wps(struct hostapd_data *hapd, + struct hostapd_bss_config *conf) +{ + return 0; +} + +static inline void hostapd_deinit_wps(struct hostapd_data *hapd) +{ +} + +static inline int hostapd_init_wps_complete(struct hostapd_data *hapd) +{ + return 0; +} + +static inline void hostapd_update_wps(struct hostapd_data *hapd) +{ +} + +static inline void hostapd_wps_eap_completed(struct hostapd_data *hapd) +{ +} + +static inline int hostapd_wps_get_mib_sta(struct hostapd_data *hapd, + const u8 *addr, + char *buf, size_t buflen) +{ + return 0; +} + +static inline int hostapd_wps_button_pushed(struct hostapd_data *hapd, + const u8 *p2p_dev_addr) +{ + return 0; +} + +static inline int hostapd_wps_cancel(struct hostapd_data *hapd) +{ + return 0; +} + +#endif /* CONFIG_WPS */ + +#endif /* WPS_HOSTAPD_H */ diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/common/defs.h b/beken_os/beken378/func/wpa_supplicant-2.9/src/common/defs.h new file mode 100755 index 0000000..ac36a2f --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/common/defs.h @@ -0,0 +1,433 @@ +/* + * WPA Supplicant - Common definitions + * Copyright (c) 2004-2015, Jouni Malinen + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#ifndef DEFS_H +#define DEFS_H + +#include "include.h" + +#ifdef FALSE +#undef FALSE +#endif +#ifdef TRUE +#undef TRUE +#endif + +typedef enum { FALSE = 0, TRUE = 1 } Boolean; + +/** + * @brief WPA cipher definition + */ +#define WPA_CIPHER_NONE BIT(0) +#define WPA_CIPHER_WEP40 BIT(1) +#define WPA_CIPHER_WEP104 BIT(2) +#define WPA_CIPHER_TKIP BIT(3) +#define WPA_CIPHER_CCMP BIT(4) +#define WPA_CIPHER_AES_128_CMAC BIT(5) +#define WPA_CIPHER_GCMP BIT(6) +#define WPA_CIPHER_SMS4 BIT(7) +#define WPA_CIPHER_GCMP_256 BIT(8) +#define WPA_CIPHER_CCMP_256 BIT(9) +#define WPA_CIPHER_BIP_GMAC_128 BIT(11) +#define WPA_CIPHER_BIP_GMAC_256 BIT(12) +#define WPA_CIPHER_BIP_CMAC_256 BIT(13) +#define WPA_CIPHER_GTK_NOT_USED BIT(14) +#define WPA_CIPHER_MASK 0x7fffUL + +/** + * @brief WPA key management definition + */ +#define WPA_KEY_MGMT_IEEE8021X BIT(0) +#define WPA_KEY_MGMT_PSK BIT(1) +#define WPA_KEY_MGMT_NONE BIT(2) +#define WPA_KEY_MGMT_IEEE8021X_NO_WPA BIT(3) +#define WPA_KEY_MGMT_WPA_NONE BIT(4) +#define WPA_KEY_MGMT_FT_IEEE8021X BIT(5) +#define WPA_KEY_MGMT_FT_PSK BIT(6) +#define WPA_KEY_MGMT_IEEE8021X_SHA256 BIT(7) +#define WPA_KEY_MGMT_PSK_SHA256 BIT(8) +#define WPA_KEY_MGMT_WPS BIT(9) +#define WPA_KEY_MGMT_SAE BIT(10) +#define WPA_KEY_MGMT_FT_SAE BIT(11) +#define WPA_KEY_MGMT_WAPI_PSK BIT(12) +#define WPA_KEY_MGMT_WAPI_CERT BIT(13) +#define WPA_KEY_MGMT_CCKM BIT(14) +#define WPA_KEY_MGMT_OSEN BIT(15) +#define WPA_KEY_MGMT_IEEE8021X_SUITE_B BIT(16) +#define WPA_KEY_MGMT_IEEE8021X_SUITE_B_192 BIT(17) +#define WPA_KEY_MGMT_FILS_SHA256 BIT(18) +#define WPA_KEY_MGMT_FILS_SHA384 BIT(19) +#define WPA_KEY_MGMT_FT_FILS_SHA256 BIT(20) +#define WPA_KEY_MGMT_FT_FILS_SHA384 BIT(21) +#define WPA_KEY_MGMT_OWE BIT(22) +#define WPA_KEY_MGMT_DPP BIT(23) +#define WPA_KEY_MGMT_FT_IEEE8021X_SHA384 BIT(24) + +#define WPA_KEY_MGMT_FT (WPA_KEY_MGMT_FT_PSK | \ + WPA_KEY_MGMT_FT_IEEE8021X | \ + WPA_KEY_MGMT_FT_IEEE8021X_SHA384 | \ + WPA_KEY_MGMT_FT_SAE | \ + WPA_KEY_MGMT_FT_FILS_SHA256 | \ + WPA_KEY_MGMT_FT_FILS_SHA384) + +#define WPA_KEY_MGMT_MASK 0x3ffffUL + +static inline int wpa_key_mgmt_wpa_ieee8021x(int akm) +{ + return !!(akm & (WPA_KEY_MGMT_IEEE8021X | + WPA_KEY_MGMT_FT_IEEE8021X | + WPA_KEY_MGMT_FT_IEEE8021X_SHA384 | + WPA_KEY_MGMT_CCKM | + WPA_KEY_MGMT_OSEN | + WPA_KEY_MGMT_IEEE8021X_SHA256 | + WPA_KEY_MGMT_IEEE8021X_SUITE_B | + WPA_KEY_MGMT_IEEE8021X_SUITE_B_192 | + WPA_KEY_MGMT_FILS_SHA256 | + WPA_KEY_MGMT_FILS_SHA384 | + WPA_KEY_MGMT_FT_FILS_SHA256 | + WPA_KEY_MGMT_FT_FILS_SHA384)); +} + +static inline int wpa_key_mgmt_wpa_psk(int akm) +{ + return !!(akm & (WPA_KEY_MGMT_PSK | + WPA_KEY_MGMT_FT_PSK | + WPA_KEY_MGMT_PSK_SHA256 | + WPA_KEY_MGMT_SAE | + WPA_KEY_MGMT_FT_SAE)); +} + +static inline int wpa_key_mgmt_ft(int akm) +{ + return !!(akm & WPA_KEY_MGMT_FT); +} + +static inline int wpa_key_mgmt_only_ft(int akm) +{ + int ft = wpa_key_mgmt_ft(akm); + akm &= ~WPA_KEY_MGMT_FT; + return ft && !akm; +} + +static inline int wpa_key_mgmt_ft_psk(int akm) +{ + return !!(akm & WPA_KEY_MGMT_FT_PSK); +} + +static inline int wpa_key_mgmt_sae(int akm) +{ + return !!(akm & (WPA_KEY_MGMT_SAE | + WPA_KEY_MGMT_FT_SAE)); +} + +static inline int wpa_key_mgmt_fils(int akm) +{ + return !!(akm & (WPA_KEY_MGMT_FILS_SHA256 | + WPA_KEY_MGMT_FILS_SHA384 | + WPA_KEY_MGMT_FT_FILS_SHA256 | + WPA_KEY_MGMT_FT_FILS_SHA384)); +} + +static inline int wpa_key_mgmt_sha256(int akm) +{ + return !!(akm & (WPA_KEY_MGMT_PSK_SHA256 | + WPA_KEY_MGMT_IEEE8021X_SHA256 | + WPA_KEY_MGMT_SAE | + WPA_KEY_MGMT_FT_SAE | + WPA_KEY_MGMT_OSEN | + WPA_KEY_MGMT_IEEE8021X_SUITE_B | + WPA_KEY_MGMT_FILS_SHA256 | + WPA_KEY_MGMT_FT_FILS_SHA256)); +} + +static inline int wpa_key_mgmt_sha384(int akm) +{ + return !!(akm & (WPA_KEY_MGMT_IEEE8021X_SUITE_B_192 | + WPA_KEY_MGMT_FT_IEEE8021X_SHA384 | + WPA_KEY_MGMT_FILS_SHA384 | + WPA_KEY_MGMT_FT_FILS_SHA384)); +} + +static inline int wpa_key_mgmt_suite_b(int akm) +{ + return !!(akm & (WPA_KEY_MGMT_IEEE8021X_SUITE_B | + WPA_KEY_MGMT_IEEE8021X_SUITE_B_192)); +} + +static inline int wpa_key_mgmt_wpa(int akm) +{ + return wpa_key_mgmt_wpa_ieee8021x(akm) || + wpa_key_mgmt_wpa_psk(akm) || + wpa_key_mgmt_fils(akm) || + wpa_key_mgmt_sae(akm) || + akm == WPA_KEY_MGMT_OWE || + akm == WPA_KEY_MGMT_DPP; +} + +static inline int wpa_key_mgmt_wpa_any(int akm) +{ + return wpa_key_mgmt_wpa(akm) || (akm & WPA_KEY_MGMT_WPA_NONE); +} + +static inline int wpa_key_mgmt_cckm(int akm) +{ + return akm == WPA_KEY_MGMT_CCKM; +} + + +#define WPA_PROTO_WPA BIT(0) +#define WPA_PROTO_RSN BIT(1) +#define WPA_PROTO_WAPI BIT(2) +#define WPA_PROTO_OSEN BIT(3) + +#define WPA_AUTH_ALG_OPEN BIT(0) +#define WPA_AUTH_ALG_SHARED BIT(1) +#define WPA_AUTH_ALG_LEAP BIT(2) +#define WPA_AUTH_ALG_FT BIT(3) +#define WPA_AUTH_ALG_SAE BIT(4) +#define WPA_AUTH_ALG_FILS BIT(5) +#define WPA_AUTH_ALG_FILS_SK_PFS BIT(6) + +static inline int wpa_auth_alg_fils(int alg) +{ + return !!(alg & (WPA_AUTH_ALG_FILS | WPA_AUTH_ALG_FILS_SK_PFS)); +} + +enum wpa_alg { + WPA_ALG_NONE, + WPA_ALG_WEP, + WPA_ALG_TKIP, + WPA_ALG_CCMP, + WPA_ALG_IGTK, + WPA_ALG_PMK, + WPA_ALG_GCMP, + WPA_ALG_SMS4, + WPA_ALG_KRK, + WPA_ALG_GCMP_256, + WPA_ALG_CCMP_256, + WPA_ALG_BIP_GMAC_128, + WPA_ALG_BIP_GMAC_256, + WPA_ALG_BIP_CMAC_256 +}; + +/** + * enum wpa_states - wpa_supplicant state + * + * These enumeration values are used to indicate the current wpa_supplicant + * state (wpa_s->wpa_state). The current state can be retrieved with + * wpa_supplicant_get_state() function and the state can be changed by calling + * wpa_supplicant_set_state(). In WPA state machine (wpa.c and preauth.c), the + * wrapper functions wpa_sm_get_state() and wpa_sm_set_state() should be used + * to access the state variable. + */ +enum wpa_states { + /** + * WPA_DISCONNECTED - Disconnected state + * + * This state indicates that client is not associated, but is likely to + * start looking for an access point. This state is entered when a + * connection is lost. + */ + WPA_DISCONNECTED, + + /** + * WPA_INTERFACE_DISABLED - Interface disabled + * + * This state is entered if the network interface is disabled, e.g., + * due to rfkill. wpa_supplicant refuses any new operations that would + * use the radio until the interface has been enabled. + */ + WPA_INTERFACE_DISABLED, + + /** + * WPA_INACTIVE - Inactive state (wpa_supplicant disabled) + * + * This state is entered if there are no enabled networks in the + * configuration. wpa_supplicant is not trying to associate with a new + * network and external interaction (e.g., ctrl_iface call to add or + * enable a network) is needed to start association. + */ + WPA_INACTIVE, + + /** + * WPA_SCANNING - Scanning for a network + * + * This state is entered when wpa_supplicant starts scanning for a + * network. + */ + WPA_SCANNING, + + /** + * WPA_AUTHENTICATING - Trying to authenticate with a BSS/SSID + * + * This state is entered when wpa_supplicant has found a suitable BSS + * to authenticate with and the driver is configured to try to + * authenticate with this BSS. This state is used only with drivers + * that use wpa_supplicant as the SME. + */ + WPA_AUTHENTICATING, + + /** + * WPA_ASSOCIATING - Trying to associate with a BSS/SSID + * + * This state is entered when wpa_supplicant has found a suitable BSS + * to associate with and the driver is configured to try to associate + * with this BSS in ap_scan=1 mode. When using ap_scan=2 mode, this + * state is entered when the driver is configured to try to associate + * with a network using the configured SSID and security policy. + */ + WPA_ASSOCIATING, + + /** + * WPA_ASSOCIATED - Association completed + * + * This state is entered when the driver reports that association has + * been successfully completed with an AP. If IEEE 802.1X is used + * (with or without WPA/WPA2), wpa_supplicant remains in this state + * until the IEEE 802.1X/EAPOL authentication has been completed. + */ + WPA_ASSOCIATED, + + /** + * WPA_4WAY_HANDSHAKE - WPA 4-Way Key Handshake in progress + * + * This state is entered when WPA/WPA2 4-Way Handshake is started. In + * case of WPA-PSK, this happens when receiving the first EAPOL-Key + * frame after association. In case of WPA-EAP, this state is entered + * when the IEEE 802.1X/EAPOL authentication has been completed. + */ + WPA_4WAY_HANDSHAKE, + + /** + * WPA_GROUP_HANDSHAKE - WPA Group Key Handshake in progress + * + * This state is entered when 4-Way Key Handshake has been completed + * (i.e., when the supplicant sends out message 4/4) and when Group + * Key rekeying is started by the AP (i.e., when supplicant receives + * message 1/2). + */ + WPA_GROUP_HANDSHAKE, + + /** + * WPA_COMPLETED - All authentication completed + * + * This state is entered when the full authentication process is + * completed. In case of WPA2, this happens when the 4-Way Handshake is + * successfully completed. With WPA, this state is entered after the + * Group Key Handshake; with IEEE 802.1X (non-WPA) connection is + * completed after dynamic keys are received (or if not used, after + * the EAP authentication has been completed). With static WEP keys and + * plaintext connections, this state is entered when an association + * has been completed. + * + * This state indicates that the supplicant has completed its + * processing for the association phase and that data connection is + * fully configured. + */ + WPA_COMPLETED +}; + +#define MLME_SETPROTECTION_PROTECT_TYPE_NONE 0 +#define MLME_SETPROTECTION_PROTECT_TYPE_RX 1 +#define MLME_SETPROTECTION_PROTECT_TYPE_TX 2 +#define MLME_SETPROTECTION_PROTECT_TYPE_RX_TX 3 + +#define MLME_SETPROTECTION_KEY_TYPE_GROUP 0 +#define MLME_SETPROTECTION_KEY_TYPE_PAIRWISE 1 + + +/** + * enum mfp_options - Management frame protection (IEEE 802.11w) options + */ +enum mfp_options { + NO_MGMT_FRAME_PROTECTION = 0, + MGMT_FRAME_PROTECTION_OPTIONAL = 1, + MGMT_FRAME_PROTECTION_REQUIRED = 2, +}; +#define MGMT_FRAME_PROTECTION_DEFAULT 3 + +/** + * enum hostapd_hw_mode - Hardware mode + */ +enum hostapd_hw_mode { + HOSTAPD_MODE_IEEE80211B, + HOSTAPD_MODE_IEEE80211G, + HOSTAPD_MODE_IEEE80211A, + HOSTAPD_MODE_IEEE80211AD, + HOSTAPD_MODE_IEEE80211ANY, + NUM_HOSTAPD_MODES +}; + +/** + * enum wpa_ctrl_req_type - Control interface request types + */ +enum wpa_ctrl_req_type { + WPA_CTRL_REQ_UNKNOWN, + WPA_CTRL_REQ_EAP_IDENTITY, + WPA_CTRL_REQ_EAP_PASSWORD, + WPA_CTRL_REQ_EAP_NEW_PASSWORD, + WPA_CTRL_REQ_EAP_PIN, + WPA_CTRL_REQ_EAP_OTP, + WPA_CTRL_REQ_EAP_PASSPHRASE, + WPA_CTRL_REQ_SIM, + WPA_CTRL_REQ_PSK_PASSPHRASE, + WPA_CTRL_REQ_EXT_CERT_CHECK, + NUM_WPA_CTRL_REQS +}; + +/* Maximum number of EAP methods to store for EAP server user information */ +#define EAP_MAX_METHODS 8 + +enum mesh_plink_state { + PLINK_IDLE = 1, + PLINK_OPN_SNT, + PLINK_OPN_RCVD, + PLINK_CNF_RCVD, + PLINK_ESTAB, + PLINK_HOLDING, + PLINK_BLOCKED, /* not defined in the IEEE 802.11 standard */ +}; + +enum set_band { + WPA_SETBAND_AUTO, + WPA_SETBAND_5G, + WPA_SETBAND_2G +}; + +enum wpa_radio_work_band { + BAND_2_4_GHZ = BIT(0), + BAND_5_GHZ = BIT(1), + BAND_60_GHZ = BIT(2), +}; + +enum beacon_rate_type { + BEACON_RATE_LEGACY, + BEACON_RATE_HT, + BEACON_RATE_VHT +}; + +enum eap_proxy_sim_state { + SIM_STATE_ERROR, +}; + +#define OCE_STA BIT(0) +#define OCE_STA_CFON BIT(1) +#define OCE_AP BIT(2) + +/* enum chan_width - Channel width definitions */ +enum chan_width { + CHAN_WIDTH_20_NOHT, + CHAN_WIDTH_20, + CHAN_WIDTH_40, + CHAN_WIDTH_80, + CHAN_WIDTH_80P80, + CHAN_WIDTH_160, + CHAN_WIDTH_UNKNOWN +}; + +#endif /* DEFS_H */ diff --git a/beken_os/beken378/func/wpa_supplicant-2.9/src/common/dpp.c b/beken_os/beken378/func/wpa_supplicant-2.9/src/common/dpp.c new file mode 100755 index 0000000..dcbc80b --- /dev/null +++ b/beken_os/beken378/func/wpa_supplicant-2.9/src/common/dpp.c @@ -0,0 +1,10056 @@ +/* + * DPP functionality shared between hostapd and wpa_supplicant + * Copyright (c) 2017, Qualcomm Atheros, Inc. + * Copyright (c) 2018-2019, The Linux Foundation + * + * This software may be distributed under the terms of the BSD license. + * See README for more details. + */ + +#include "utils/includes.h" +#include +#include +#include +#include +#include + +#include "utils/common.h" +#include "utils/base64.h" +#include "utils/json.h" +#include "utils/ip_addr.h" +#include "utils/eloop.h" +#include "common/ieee802_11_common.h" +#include "common/ieee802_11_defs.h" +#include "common/wpa_ctrl.h" +#include "common/gas.h" +#include "crypto/crypto.h" +#include "crypto/random.h" +#include "crypto/aes.h" +#include "crypto/aes_siv.h" +#include "crypto/sha384.h" +#include "crypto/sha512.h" +#include "drivers/driver.h" +#include "dpp.h" + + +#ifdef CONFIG_TESTING_OPTIONS +enum dpp_test_behavior dpp_test = DPP_TEST_DISABLED; +u8 dpp_pkex_own_mac_override[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; +u8 dpp_pkex_peer_mac_override[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 }; +u8 dpp_pkex_ephemeral_key_override[600]; +size_t dpp_pkex_ephemeral_key_override_len = 0; +u8 dpp_protocol_key_override[600]; +size_t dpp_protocol_key_override_len = 0; +u8 dpp_nonce_override[DPP_MAX_NONCE_LEN]; +size_t dpp_nonce_override_len = 0; + +static int dpp_test_gen_invalid_key(struct wpabuf *msg, + const struct dpp_curve_params *curve); +#endif /* CONFIG_TESTING_OPTIONS */ + +#if OPENSSL_VERSION_NUMBER < 0x10100000L || \ + (defined(LIBRESSL_VERSION_NUMBER) && \ + LIBRESSL_VERSION_NUMBER < 0x20700000L) +/* Compatibility wrappers for older versions. */ + +static int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s) +{ + sig->r = r; + sig->s = s; + return 1; +} + + +static void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, + const BIGNUM **ps) +{ + if (pr) + *pr = sig->r; + if (ps) + *ps = sig->s; +} + +#endif + + +struct dpp_connection { + struct dl_list list; + struct dpp_controller *ctrl; + struct dpp_relay_controller *relay; + struct dpp_global *global; + struct dpp_authentication *auth; + int sock; + u8 mac_addr[ETH_ALEN]; + unsigned int freq; + u8 msg_len[4]; + size_t msg_len_octets; + struct wpabuf *msg; + struct wpabuf *msg_out; + size_t msg_out_pos; + unsigned int read_eloop:1; + unsigned int write_eloop:1; + unsigned int on_tcp_tx_complete_gas_done:1; + unsigned int on_tcp_tx_complete_remove:1; + unsigned int on_tcp_tx_complete_auth_ok:1; +}; + +/* Remote Controller */ +struct dpp_relay_controller { + struct dl_list list; + struct dpp_global *global; + u8 pkhash[SHA256_MAC_LEN]; + struct hostapd_ip_addr ipaddr; + void *cb_ctx; + void (*tx)(void *ctx, const u8 *addr, unsigned int freq, const u8 *msg, + size_t len); + void (*gas_resp_tx)(void *ctx, const u8 *addr, u8 dialog_token, + int prot, struct wpabuf *buf); + struct dl_list conn; /* struct dpp_connection */ +}; + +/* Local Controller */ +struct dpp_controller { + struct dpp_global *global; + u8 allowed_roles; + int qr_mutual; + int sock; + struct dl_list conn; /* struct dpp_connection */ + char *configurator_params; +}; + +struct dpp_global { + void *msg_ctx; + struct dl_list bootstrap; /* struct dpp_bootstrap_info */ + struct dl_list configurator; /* struct dpp_configurator */ +#ifdef CONFIG_DPP2 + struct dl_list controllers; /* struct dpp_relay_controller */ + struct dpp_controller *controller; + struct dl_list tcp_init; /* struct dpp_connection */ + void *cb_ctx; + int (*process_conf_obj)(void *ctx, struct dpp_authentication *auth); +#endif /* CONFIG_DPP2 */ +}; + +static const struct dpp_curve_params dpp_curves[] = { + /* The mandatory to support and the default NIST P-256 curve needs to + * be the first entry on this list. */ + { "prime256v1", 32, 32, 16, 32, "P-256", 19, "ES256" }, + { "secp384r1", 48, 48, 24, 48, "P-384", 20, "ES384" }, + { "secp521r1", 64, 64, 32, 66, "P-521", 21, "ES512" }, + { "brainpoolP256r1", 32, 32, 16, 32, "BP-256", 28, "BS256" }, + { "brainpoolP384r1", 48, 48, 24, 48, "BP-384", 29, "BS384" }, + { "brainpoolP512r1", 64, 64, 32, 64, "BP-512", 30, "BS512" }, + { NULL, 0, 0, 0, 0, NULL, 0, NULL } +}; + + +/* Role-specific elements for PKEX */ + +/* NIST P-256 */ +static const u8 pkex_init_x_p256[32] = { + 0x56, 0x26, 0x12, 0xcf, 0x36, 0x48, 0xfe, 0x0b, + 0x07, 0x04, 0xbb, 0x12, 0x22, 0x50, 0xb2, 0x54, + 0xb1, 0x94, 0x64, 0x7e, 0x54, 0xce, 0x08, 0x07, + 0x2e, 0xec, 0xca, 0x74, 0x5b, 0x61, 0x2d, 0x25 + }; +static const u8 pkex_init_y_p256[32] = { + 0x3e, 0x44, 0xc7, 0xc9, 0x8c, 0x1c, 0xa1, 0x0b, + 0x20, 0x09, 0x93, 0xb2, 0xfd, 0xe5, 0x69, 0xdc, + 0x75, 0xbc, 0xad, 0x33, 0xc1, 0xe7, 0xc6, 0x45, + 0x4d, 0x10, 0x1e, 0x6a, 0x3d, 0x84, 0x3c, 0xa4 + }; +static const u8 pkex_resp_x_p256[32] = { + 0x1e, 0xa4, 0x8a, 0xb1, 0xa4, 0xe8, 0x42, 0x39, + 0xad, 0x73, 0x07, 0xf2, 0x34, 0xdf, 0x57, 0x4f, + 0xc0, 0x9d, 0x54, 0xbe, 0x36, 0x1b, 0x31, 0x0f, + 0x59, 0x91, 0x52, 0x33, 0xac, 0x19, 0x9d, 0x76 +}; +static const u8 pkex_resp_y_p256[32] = { + 0xd9, 0xfb, 0xf6, 0xb9, 0xf5, 0xfa, 0xdf, 0x19, + 0x58, 0xd8, 0x3e, 0xc9, 0x89, 0x7a, 0x35, 0xc1, + 0xbd, 0xe9, 0x0b, 0x77, 0x7a, 0xcb, 0x91, 0x2a, + 0xe8, 0x21, 0x3f, 0x47, 0x52, 0x02, 0x4d, 0x67 +}; + +/* NIST P-384 */ +static const u8 pkex_init_x_p384[48] = { + 0x95, 0x3f, 0x42, 0x9e, 0x50, 0x7f, 0xf9, 0xaa, + 0xac, 0x1a, 0xf2, 0x85, 0x2e, 0x64, 0x91, 0x68, + 0x64, 0xc4, 0x3c, 0xb7, 0x5c, 0xf8, 0xc9, 0x53, + 0x6e, 0x58, 0x4c, 0x7f, 0xc4, 0x64, 0x61, 0xac, + 0x51, 0x8a, 0x6f, 0xfe, 0xab, 0x74, 0xe6, 0x12, + 0x81, 0xac, 0x38, 0x5d, 0x41, 0xe6, 0xb9, 0xa3 +}; +static const u8 pkex_init_y_p384[48] = { + 0x76, 0x2f, 0x68, 0x84, 0xa6, 0xb0, 0x59, 0x29, + 0x83, 0xa2, 0x6c, 0xa4, 0x6c, 0x3b, 0xf8, 0x56, + 0x76, 0x11, 0x2a, 0x32, 0x90, 0xbd, 0x07, 0xc7, + 0x37, 0x39, 0x9d, 0xdb, 0x96, 0xf3, 0x2b, 0xb6, + 0x27, 0xbb, 0x29, 0x3c, 0x17, 0x33, 0x9d, 0x94, + 0xc3, 0xda, 0xac, 0x46, 0xb0, 0x8e, 0x07, 0x18 +}; +static const u8 pkex_resp_x_p384[48] = { + 0xad, 0xbe, 0xd7, 0x1d, 0x3a, 0x71, 0x64, 0x98, + 0x5f, 0xb4, 0xd6, 0x4b, 0x50, 0xd0, 0x84, 0x97, + 0x4b, 0x7e, 0x57, 0x70, 0xd2, 0xd9, 0xf4, 0x92, + 0x2a, 0x3f, 0xce, 0x99, 0xc5, 0x77, 0x33, 0x44, + 0x14, 0x56, 0x92, 0xcb, 0xae, 0x46, 0x64, 0xdf, + 0xe0, 0xbb, 0xd7, 0xb1, 0x29, 0x20, 0x72, 0xdf +}; +static const u8 pkex_resp_y_p384[48] = { + 0xab, 0xa7, 0xdf, 0x52, 0xaa, 0xe2, 0x35, 0x0c, + 0xe3, 0x75, 0x32, 0xe6, 0xbf, 0x06, 0xc8, 0x7c, + 0x38, 0x29, 0x4c, 0xec, 0x82, 0xac, 0xd7, 0xa3, + 0x09, 0xd2, 0x0e, 0x22, 0x5a, 0x74, 0x52, 0xa1, + 0x7e, 0x54, 0x4e, 0xfe, 0xc6, 0x29, 0x33, 0x63, + 0x15, 0xe1, 0x7b, 0xe3, 0x40, 0x1c, 0xca, 0x06 +}; + +/* NIST P-521 */ +static const u8 pkex_init_x_p521[66] = { + 0x00, 0x16, 0x20, 0x45, 0x19, 0x50, 0x95, 0x23, + 0x0d, 0x24, 0xbe, 0x00, 0x87, 0xdc, 0xfa, 0xf0, + 0x58, 0x9a, 0x01, 0x60, 0x07, 0x7a, 0xca, 0x76, + 0x01, 0xab, 0x2d, 0x5a, 0x46, 0xcd, 0x2c, 0xb5, + 0x11, 0x9a, 0xff, 0xaa, 0x48, 0x04, 0x91, 0x38, + 0xcf, 0x86, 0xfc, 0xa4, 0xa5, 0x0f, 0x47, 0x01, + 0x80, 0x1b, 0x30, 0xa3, 0xae, 0xe8, 0x1c, 0x2e, + 0xea, 0xcc, 0xf0, 0x03, 0x9f, 0x77, 0x4c, 0x8d, + 0x97, 0x76 +}; +static const u8 pkex_init_y_p521[66] = { + 0x00, 0xb3, 0x8e, 0x02, 0xe4, 0x2a, 0x63, 0x59, + 0x12, 0xc6, 0x10, 0xba, 0x3a, 0xf9, 0x02, 0x99, + 0x3f, 0x14, 0xf0, 0x40, 0xde, 0x5c, 0xc9, 0x8b, + 0x02, 0x55, 0xfa, 0x91, 0xb1, 0xcc, 0x6a, 0xbd, + 0xe5, 0x62, 0xc0, 0xc5, 0xe3, 0xa1, 0x57, 0x9f, + 0x08, 0x1a, 0xa6, 0xe2, 0xf8, 0x55, 0x90, 0xbf, + 0xf5, 0xa6, 0xc3, 0xd8, 0x52, 0x1f, 0xb7, 0x02, + 0x2e, 0x7c, 0xc8, 0xb3, 0x20, 0x1e, 0x79, 0x8d, + 0x03, 0xa8 +}; +static const u8 pkex_resp_x_p521[66] = { + 0x00, 0x79, 0xe4, 0x4d, 0x6b, 0x5e, 0x12, 0x0a, + 0x18, 0x2c, 0xb3, 0x05, 0x77, 0x0f, 0xc3, 0x44, + 0x1a, 0xcd, 0x78, 0x46, 0x14, 0xee, 0x46, 0x3f, + 0xab, 0xc9, 0x59, 0x7c, 0x85, 0xa0, 0xc2, 0xfb, + 0x02, 0x32, 0x99, 0xde, 0x5d, 0xe1, 0x0d, 0x48, + 0x2d, 0x71, 0x7d, 0x8d, 0x3f, 0x61, 0x67, 0x9e, + 0x2b, 0x8b, 0x12, 0xde, 0x10, 0x21, 0x55, 0x0a, + 0x5b, 0x2d, 0xe8, 0x05, 0x09, 0xf6, 0x20, 0x97, + 0x84, 0xb4 +}; +static const u8 pkex_resp_y_p521[66] = { + 0x00, 0x46, 0x63, 0x39, 0xbe, 0xcd, 0xa4, 0x2d, + 0xca, 0x27, 0x74, 0xd4, 0x1b, 0x91, 0x33, 0x20, + 0x83, 0xc7, 0x3b, 0xa4, 0x09, 0x8b, 0x8e, 0xa3, + 0x88, 0xe9, 0x75, 0x7f, 0x56, 0x7b, 0x38, 0x84, + 0x62, 0x02, 0x7c, 0x90, 0x51, 0x07, 0xdb, 0xe9, + 0xd0, 0xde, 0xda, 0x9a, 0x5d, 0xe5, 0x94, 0xd2, + 0xcf, 0x9d, 0x4c, 0x33, 0x91, 0xa6, 0xc3, 0x80, + 0xa7, 0x6e, 0x7e, 0x8d, 0xf8, 0x73, 0x6e, 0x53, + 0xce, 0xe1 +}; + +/* Brainpool P-256r1 */ +static const u8 pkex_init_x_bp_p256r1[32] = { + 0x46, 0x98, 0x18, 0x6c, 0x27, 0xcd, 0x4b, 0x10, + 0x7d, 0x55, 0xa3, 0xdd, 0x89, 0x1f, 0x9f, 0xca, + 0xc7, 0x42, 0x5b, 0x8a, 0x23, 0xed, 0xf8, 0x75, + 0xac, 0xc7, 0xe9, 0x8d, 0xc2, 0x6f, 0xec, 0xd8 +}; +static const u8 pkex_init_y_bp_p256r1[32] = { + 0x93, 0xca, 0xef, 0xa9, 0x66, 0x3e, 0x87, 0xcd, + 0x52, 0x6e, 0x54, 0x13, 0xef, 0x31, 0x67, 0x30, + 0x15, 0x13, 0x9d, 0x6d, 0xc0, 0x95, 0x32, 0xbe, + 0x4f, 0xab, 0x5d, 0xf7, 0xbf, 0x5e, 0xaa, 0x0b +}; +static const u8 pkex_resp_x_bp_p256r1[32] = { + 0x90, 0x18, 0x84, 0xc9, 0xdc, 0xcc, 0xb5, 0x2f, + 0x4a, 0x3f, 0x4f, 0x18, 0x0a, 0x22, 0x56, 0x6a, + 0xa9, 0xef, 0xd4, 0xe6, 0xc3, 0x53, 0xc2, 0x1a, + 0x23, 0x54, 0xdd, 0x08, 0x7e, 0x10, 0xd8, 0xe3 +}; +static const u8 pkex_resp_y_bp_p256r1[32] = { + 0x2a, 0xfa, 0x98, 0x9b, 0xe3, 0xda, 0x30, 0xfd, + 0x32, 0x28, 0xcb, 0x66, 0xfb, 0x40, 0x7f, 0xf2, + 0xb2, 0x25, 0x80, 0x82, 0x44, 0x85, 0x13, 0x7e, + 0x4b, 0xb5, 0x06, 0xc0, 0x03, 0x69, 0x23, 0x64 +}; + +/* Brainpool P-384r1 */ +static const u8 pkex_init_x_bp_p384r1[48] = { + 0x0a, 0x2c, 0xeb, 0x49, 0x5e, 0xb7, 0x23, 0xbd, + 0x20, 0x5b, 0xe0, 0x49, 0xdf, 0xcf, 0xcf, 0x19, + 0x37, 0x36, 0xe1, 0x2f, 0x59, 0xdb, 0x07, 0x06, + 0xb5, 0xeb, 0x2d, 0xae, 0xc2, 0xb2, 0x38, 0x62, + 0xa6, 0x73, 0x09, 0xa0, 0x6c, 0x0a, 0xa2, 0x30, + 0x99, 0xeb, 0xf7, 0x1e, 0x47, 0xb9, 0x5e, 0xbe +}; +static const u8 pkex_init_y_bp_p384r1[48] = { + 0x54, 0x76, 0x61, 0x65, 0x75, 0x5a, 0x2f, 0x99, + 0x39, 0x73, 0xca, 0x6c, 0xf9, 0xf7, 0x12, 0x86, + 0x54, 0xd5, 0xd4, 0xad, 0x45, 0x7b, 0xbf, 0x32, + 0xee, 0x62, 0x8b, 0x9f, 0x52, 0xe8, 0xa0, 0xc9, + 0xb7, 0x9d, 0xd1, 0x09, 0xb4, 0x79, 0x1c, 0x3e, + 0x1a, 0xbf, 0x21, 0x45, 0x66, 0x6b, 0x02, 0x52 +}; +static const u8 pkex_resp_x_bp_p384r1[48] = { + 0x03, 0xa2, 0x57, 0xef, 0xe8, 0x51, 0x21, 0xa0, + 0xc8, 0x9e, 0x21, 0x02, 0xb5, 0x9a, 0x36, 0x25, + 0x74, 0x22, 0xd1, 0xf2, 0x1b, 0xa8, 0x9a, 0x9b, + 0x97, 0xbc, 0x5a, 0xeb, 0x26, 0x15, 0x09, 0x71, + 0x77, 0x59, 0xec, 0x8b, 0xb7, 0xe1, 0xe8, 0xce, + 0x65, 0xb8, 0xaf, 0xf8, 0x80, 0xae, 0x74, 0x6c +}; +static const u8 pkex_resp_y_bp_p384r1[48] = { + 0x2f, 0xd9, 0x6a, 0xc7, 0x3e, 0xec, 0x76, 0x65, + 0x2d, 0x38, 0x7f, 0xec, 0x63, 0x26, 0x3f, 0x04, + 0xd8, 0x4e, 0xff, 0xe1, 0x0a, 0x51, 0x74, 0x70, + 0xe5, 0x46, 0x63, 0x7f, 0x5c, 0xc0, 0xd1, 0x7c, + 0xfb, 0x2f, 0xea, 0xe2, 0xd8, 0x0f, 0x84, 0xcb, + 0xe9, 0x39, 0x5c, 0x64, 0xfe, 0xcb, 0x2f, 0xf1 +}; + +/* Brainpool P-512r1 */ +static const u8 pkex_init_x_bp_p512r1[64] = { + 0x4c, 0xe9, 0xb6, 0x1c, 0xe2, 0x00, 0x3c, 0x9c, + 0xa9, 0xc8, 0x56, 0x52, 0xaf, 0x87, 0x3e, 0x51, + 0x9c, 0xbb, 0x15, 0x31, 0x1e, 0xc1, 0x05, 0xfc, + 0x7c, 0x77, 0xd7, 0x37, 0x61, 0x27, 0xd0, 0x95, + 0x98, 0xee, 0x5d, 0xa4, 0x3d, 0x09, 0xdb, 0x3d, + 0xfa, 0x89, 0x9e, 0x7f, 0xa6, 0xa6, 0x9c, 0xff, + 0x83, 0x5c, 0x21, 0x6c, 0x3e, 0xf2, 0xfe, 0xdc, + 0x63, 0xe4, 0xd1, 0x0e, 0x75, 0x45, 0x69, 0x0f +}; +static const u8 pkex_init_y_bp_p512r1[64] = { + 0x50, 0xb5, 0x9b, 0xfa, 0x45, 0x67, 0x75, 0x94, + 0x44, 0xe7, 0x68, 0xb0, 0xeb, 0x3e, 0xb3, 0xb8, + 0xf9, 0x99, 0x05, 0xef, 0xae, 0x6c, 0xbc, 0xe3, + 0xe1, 0xd2, 0x51, 0x54, 0xdf, 0x59, 0xd4, 0x45, + 0x41, 0x3a, 0xa8, 0x0b, 0x76, 0x32, 0x44, 0x0e, + 0x07, 0x60, 0x3a, 0x6e, 0xbe, 0xfe, 0xe0, 0x58, + 0x52, 0xa0, 0xaa, 0x8b, 0xd8, 0x5b, 0xf2, 0x71, + 0x11, 0x9a, 0x9e, 0x8f, 0x1a, 0xd1, 0xc9, 0x99 +}; +static const u8 pkex_resp_x_bp_p512r1[64] = { + 0x2a, 0x60, 0x32, 0x27, 0xa1, 0xe6, 0x94, 0x72, + 0x1c, 0x48, 0xbe, 0xc5, 0x77, 0x14, 0x30, 0x76, + 0xe4, 0xbf, 0xf7, 0x7b, 0xc5, 0xfd, 0xdf, 0x19, + 0x1e, 0x0f, 0xdf, 0x1c, 0x40, 0xfa, 0x34, 0x9e, + 0x1f, 0x42, 0x24, 0xa3, 0x2c, 0xd5, 0xc7, 0xc9, + 0x7b, 0x47, 0x78, 0x96, 0xf1, 0x37, 0x0e, 0x88, + 0xcb, 0xa6, 0x52, 0x29, 0xd7, 0xa8, 0x38, 0x29, + 0x8e, 0x6e, 0x23, 0x47, 0xd4, 0x4b, 0x70, 0x3e +}; +static const u8 pkex_resp_y_bp_p512r1[64] = { + 0x80, 0x1f, 0x43, 0xd2, 0x17, 0x35, 0xec, 0x81, + 0xd9, 0x4b, 0xdc, 0x81, 0x19, 0xd9, 0x5f, 0x68, + 0x16, 0x84, 0xfe, 0x63, 0x4b, 0x8d, 0x5d, 0xaa, + 0x88, 0x4a, 0x47, 0x48, 0xd4, 0xea, 0xab, 0x7d, + 0x6a, 0xbf, 0xe1, 0x28, 0x99, 0x6a, 0x87, 0x1c, + 0x30, 0xb4, 0x44, 0x2d, 0x75, 0xac, 0x35, 0x09, + 0x73, 0x24, 0x3d, 0xb4, 0x43, 0xb1, 0xc1, 0x56, + 0x56, 0xad, 0x30, 0x87, 0xf4, 0xc3, 0x00, 0xc7 +}; + + +static void dpp_debug_print_point(const char *title, const EC_GROUP *group, + const EC_POINT *point) +{ + BIGNUM *x, *y; + BN_CTX *ctx; + char *x_str = NULL, *y_str = NULL; + + if (!wpa_debug_show_keys) + return; + + ctx = BN_CTX_new(); + x = BN_new(); + y = BN_new(); + if (!ctx || !x || !y || + EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx) != 1) + goto fail; + + x_str = BN_bn2hex(x); + y_str = BN_bn2hex(y); + if (!x_str || !y_str) + goto fail; + + wpa_printf(MSG_DEBUG, "%s (%s,%s)", title, x_str, y_str); + +fail: + OPENSSL_free(x_str); + OPENSSL_free(y_str); + BN_free(x); + BN_free(y); + BN_CTX_free(ctx); +} + + +static int dpp_hash_vector(const struct dpp_curve_params *curve, + size_t num_elem, const u8 *addr[], const size_t *len, + u8 *mac) +{ + if (curve->hash_len == 32) + return sha256_vector(num_elem, addr, len, mac); + if (curve->hash_len == 48) + return sha384_vector(num_elem, addr, len, mac); + if (curve->hash_len == 64) + return sha512_vector(num_elem, addr, len, mac); + return -1; +} + + +static int dpp_hkdf_expand(size_t hash_len, const u8 *secret, size_t secret_len, + const char *label, u8 *out, size_t outlen) +{ + if (hash_len == 32) + return hmac_sha256_kdf(secret, secret_len, NULL, + (const u8 *) label, os_strlen(label), + out, outlen); + if (hash_len == 48) + return hmac_sha384_kdf(secret, secret_len, NULL, + (const u8 *) label, os_strlen(label), + out, outlen); + if (hash_len == 64) + return hmac_sha512_kdf(secret, secret_len, NULL, + (const u8 *) label, os_strlen(label), + out, outlen); + return -1; +} + + +static int dpp_hmac_vector(size_t hash_len, const u8 *key, size_t key_len, + size_t num_elem, const u8 *addr[], + const size_t *len, u8 *mac) +{ + if (hash_len == 32) + return hmac_sha256_vector(key, key_len, num_elem, addr, len, + mac); + if (hash_len == 48) + return hmac_sha384_vector(key, key_len, num_elem, addr, len, + mac); + if (hash_len == 64) + return hmac_sha512_vector(key, key_len, num_elem, addr, len, + mac); + return -1; +} + + +static int dpp_hmac(size_t hash_len, const u8 *key, size_t key_len, + const u8 *data, size_t data_len, u8 *mac) +{ + if (hash_len == 32) + return hmac_sha256(key, key_len, data, data_len, mac); + if (hash_len == 48) + return hmac_sha384(key, key_len, data, data_len, mac); + if (hash_len == 64) + return hmac_sha512(key, key_len, data, data_len, mac); + return -1; +} + + +static int dpp_bn2bin_pad(const BIGNUM *bn, u8 *pos, size_t len) +{ + int num_bytes, offset; + + num_bytes = BN_num_bytes(bn); + if ((size_t) num_bytes > len) + return -1; + offset = len - num_bytes; + os_memset(pos, 0, offset); + BN_bn2bin(bn, pos + offset); + return 0; +} + + +static struct wpabuf * dpp_get_pubkey_point(EVP_PKEY *pkey, int prefix) +{ + int len, res; + EC_KEY *eckey; + struct wpabuf *buf; + unsigned char *pos; + + eckey = EVP_PKEY_get1_EC_KEY(pkey); + if (!eckey) + return NULL; + EC_KEY_set_conv_form(eckey, POINT_CONVERSION_UNCOMPRESSED); + len = i2o_ECPublicKey(eckey, NULL); + if (len <= 0) { + wpa_printf(MSG_ERROR, + "DDP: Failed to determine public key encoding length"); + EC_KEY_free(eckey); + return NULL; + } + + buf = wpabuf_alloc(len); + if (!buf) { + EC_KEY_free(eckey); + return NULL; + } + + pos = wpabuf_put(buf, len); + res = i2o_ECPublicKey(eckey, &pos); + EC_KEY_free(eckey); + if (res != len) { + wpa_printf(MSG_ERROR, + "DDP: Failed to encode public key (res=%d/%d)", + res, len); + wpabuf_free(buf); + return NULL; + } + + if (!prefix) { + /* Remove 0x04 prefix to match DPP definition */ + pos = wpabuf_mhead(buf); + os_memmove(pos, pos + 1, len - 1); + buf->used--; + } + + return buf; +} + + +static EVP_PKEY * dpp_set_pubkey_point_group(const EC_GROUP *group, + const u8 *buf_x, const u8 *buf_y, + size_t len) +{ + EC_KEY *eckey = NULL; + BN_CTX *ctx; + EC_POINT *point = NULL; + BIGNUM *x = NULL, *y = NULL; + EVP_PKEY *pkey = NULL; + + ctx = BN_CTX_new(); + if (!ctx) { + wpa_printf(MSG_ERROR, "DPP: Out of memory"); + return NULL; + } + + point = EC_POINT_new(group); + x = BN_bin2bn(buf_x, len, NULL); + y = BN_bin2bn(buf_y, len, NULL); + if (!point || !x || !y) { + wpa_printf(MSG_ERROR, "DPP: Out of memory"); + goto fail; + } + + if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) { + wpa_printf(MSG_ERROR, + "DPP: OpenSSL: EC_POINT_set_affine_coordinates_GFp failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + + if (!EC_POINT_is_on_curve(group, point, ctx) || + EC_POINT_is_at_infinity(group, point)) { + wpa_printf(MSG_ERROR, "DPP: Invalid point"); + goto fail; + } + dpp_debug_print_point("DPP: dpp_set_pubkey_point_group", group, point); + + eckey = EC_KEY_new(); + if (!eckey || + EC_KEY_set_group(eckey, group) != 1 || + EC_KEY_set_public_key(eckey, point) != 1) { + wpa_printf(MSG_ERROR, + "DPP: Failed to set EC_KEY: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + EC_KEY_set_asn1_flag(eckey, OPENSSL_EC_NAMED_CURVE); + + pkey = EVP_PKEY_new(); + if (!pkey || EVP_PKEY_set1_EC_KEY(pkey, eckey) != 1) { + wpa_printf(MSG_ERROR, "DPP: Could not create EVP_PKEY"); + goto fail; + } + +out: + BN_free(x); + BN_free(y); + EC_KEY_free(eckey); + EC_POINT_free(point); + BN_CTX_free(ctx); + return pkey; +fail: + EVP_PKEY_free(pkey); + pkey = NULL; + goto out; +} + + +static EVP_PKEY * dpp_set_pubkey_point(EVP_PKEY *group_key, + const u8 *buf, size_t len) +{ + EC_KEY *eckey; + const EC_GROUP *group; + EVP_PKEY *pkey = NULL; + + if (len & 1) + return NULL; + + eckey = EVP_PKEY_get1_EC_KEY(group_key); + if (!eckey) { + wpa_printf(MSG_ERROR, + "DPP: Could not get EC_KEY from group_key"); + return NULL; + } + + group = EC_KEY_get0_group(eckey); + if (group) + pkey = dpp_set_pubkey_point_group(group, buf, buf + len / 2, + len / 2); + else + wpa_printf(MSG_ERROR, "DPP: Could not get EC group"); + + EC_KEY_free(eckey); + return pkey; +} + + +static int dpp_ecdh(EVP_PKEY *own, EVP_PKEY *peer, + u8 *secret, size_t *secret_len) +{ + EVP_PKEY_CTX *ctx; + int ret = -1; + + ERR_clear_error(); + *secret_len = 0; + + ctx = EVP_PKEY_CTX_new(own, NULL); + if (!ctx) { + wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_CTX_new failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + return -1; + } + + if (EVP_PKEY_derive_init(ctx) != 1) { + wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_derive_init failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + + if (EVP_PKEY_derive_set_peer(ctx, peer) != 1) { + wpa_printf(MSG_ERROR, + "DPP: EVP_PKEY_derive_set_peet failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + + if (EVP_PKEY_derive(ctx, NULL, secret_len) != 1) { + wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_derive(NULL) failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + + if (*secret_len > DPP_MAX_SHARED_SECRET_LEN) { + u8 buf[200]; + int level = *secret_len > 200 ? MSG_ERROR : MSG_DEBUG; + + /* It looks like OpenSSL can return unexpectedly large buffer + * need for shared secret from EVP_PKEY_derive(NULL) in some + * cases. For example, group 19 has shown cases where secret_len + * is set to 72 even though the actual length ends up being + * updated to 32 when EVP_PKEY_derive() is called with a buffer + * for the value. Work around this by trying to fetch the value + * and continue if it is within supported range even when the + * initial buffer need is claimed to be larger. */ + wpa_printf(level, + "DPP: Unexpected secret_len=%d from EVP_PKEY_derive()", + (int) *secret_len); + if (*secret_len > 200) + goto fail; + if (EVP_PKEY_derive(ctx, buf, secret_len) != 1) { + wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_derive failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + if (*secret_len > DPP_MAX_SHARED_SECRET_LEN) { + wpa_printf(MSG_ERROR, + "DPP: Unexpected secret_len=%d from EVP_PKEY_derive()", + (int) *secret_len); + goto fail; + } + wpa_hexdump_key(MSG_DEBUG, "DPP: Unexpected secret_len change", + buf, *secret_len); + os_memcpy(secret, buf, *secret_len); + forced_memzero(buf, sizeof(buf)); + goto done; + } + + if (EVP_PKEY_derive(ctx, secret, secret_len) != 1) { + wpa_printf(MSG_ERROR, "DPP: EVP_PKEY_derive failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + +done: + ret = 0; + +fail: + EVP_PKEY_CTX_free(ctx); + return ret; +} + + +static void dpp_auth_fail(struct dpp_authentication *auth, const char *txt) +{ + wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_FAIL "%s", txt); +} + + +struct wpabuf * dpp_alloc_msg(enum dpp_public_action_frame_type type, + size_t len) +{ + struct wpabuf *msg; + + msg = wpabuf_alloc(8 + len); + if (!msg) + return NULL; + wpabuf_put_u8(msg, WLAN_ACTION_PUBLIC); + wpabuf_put_u8(msg, WLAN_PA_VENDOR_SPECIFIC); + wpabuf_put_be24(msg, OUI_WFA); + wpabuf_put_u8(msg, DPP_OUI_TYPE); + wpabuf_put_u8(msg, 1); /* Crypto Suite */ + wpabuf_put_u8(msg, type); + return msg; +} + + +const u8 * dpp_get_attr(const u8 *buf, size_t len, u16 req_id, u16 *ret_len) +{ + u16 id, alen; + const u8 *pos = buf, *end = buf + len; + + while (end - pos >= 4) { + id = WPA_GET_LE16(pos); + pos += 2; + alen = WPA_GET_LE16(pos); + pos += 2; + if (alen > end - pos) + return NULL; + if (id == req_id) { + *ret_len = alen; + return pos; + } + pos += alen; + } + + return NULL; +} + + +int dpp_check_attrs(const u8 *buf, size_t len) +{ + const u8 *pos, *end; + int wrapped_data = 0; + + pos = buf; + end = buf + len; + while (end - pos >= 4) { + u16 id, alen; + + id = WPA_GET_LE16(pos); + pos += 2; + alen = WPA_GET_LE16(pos); + pos += 2; + wpa_printf(MSG_MSGDUMP, "DPP: Attribute ID %04x len %u", + id, alen); + if (alen > end - pos) { + wpa_printf(MSG_DEBUG, + "DPP: Truncated message - not enough room for the attribute - dropped"); + return -1; + } + if (wrapped_data) { + wpa_printf(MSG_DEBUG, + "DPP: An unexpected attribute included after the Wrapped Data attribute"); + return -1; + } + if (id == DPP_ATTR_WRAPPED_DATA) + wrapped_data = 1; + pos += alen; + } + + if (end != pos) { + wpa_printf(MSG_DEBUG, + "DPP: Unexpected octets (%d) after the last attribute", + (int) (end - pos)); + return -1; + } + + return 0; +} + + +void dpp_bootstrap_info_free(struct dpp_bootstrap_info *info) +{ + if (!info) + return; + os_free(info->uri); + os_free(info->info); + EVP_PKEY_free(info->pubkey); + os_free(info); +} + + +const char * dpp_bootstrap_type_txt(enum dpp_bootstrap_type type) +{ + switch (type) { + case DPP_BOOTSTRAP_QR_CODE: + return "QRCODE"; + case DPP_BOOTSTRAP_PKEX: + return "PKEX"; + } + return "??"; +} + + +static int dpp_uri_valid_info(const char *info) +{ + while (*info) { + unsigned char val = *info++; + + if (val < 0x20 || val > 0x7e || val == 0x3b) + return 0; + } + + return 1; +} + + +static int dpp_clone_uri(struct dpp_bootstrap_info *bi, const char *uri) +{ + bi->uri = os_strdup(uri); + return bi->uri ? 0 : -1; +} + + +int dpp_parse_uri_chan_list(struct dpp_bootstrap_info *bi, + const char *chan_list) +{ + const char *pos = chan_list, *pos2; + int opclass = -1, channel, freq; + + while (pos && *pos && *pos != ';') { + pos2 = pos; + while (*pos2 >= '0' && *pos2 <= '9') + pos2++; + if (*pos2 == '/') { + opclass = atoi(pos); + pos = pos2 + 1; + } + if (opclass <= 0) + goto fail; + channel = atoi(pos); + if (channel <= 0) + goto fail; + while (*pos >= '0' && *pos <= '9') + pos++; + freq = ieee80211_chan_to_freq(NULL, opclass, channel); + wpa_printf(MSG_DEBUG, + "DPP: URI channel-list: opclass=%d channel=%d ==> freq=%d", + opclass, channel, freq); + if (freq < 0) { + wpa_printf(MSG_DEBUG, + "DPP: Ignore unknown URI channel-list channel (opclass=%d channel=%d)", + opclass, channel); + } else if (bi->num_freq == DPP_BOOTSTRAP_MAX_FREQ) { + wpa_printf(MSG_DEBUG, + "DPP: Too many channels in URI channel-list - ignore list"); + bi->num_freq = 0; + break; + } else { + bi->freq[bi->num_freq++] = freq; + } + + if (*pos == ';' || *pos == '\0') + break; + if (*pos != ',') + goto fail; + pos++; + } + + return 0; +fail: + wpa_printf(MSG_DEBUG, "DPP: Invalid URI channel-list"); + return -1; +} + + +int dpp_parse_uri_mac(struct dpp_bootstrap_info *bi, const char *mac) +{ + if (!mac) + return 0; + + if (hwaddr_aton2(mac, bi->mac_addr) < 0) { + wpa_printf(MSG_DEBUG, "DPP: Invalid URI mac"); + return -1; + } + + wpa_printf(MSG_DEBUG, "DPP: URI mac: " MACSTR, MAC2STR(bi->mac_addr)); + + return 0; +} + + +int dpp_parse_uri_info(struct dpp_bootstrap_info *bi, const char *info) +{ + const char *end; + + if (!info) + return 0; + + end = os_strchr(info, ';'); + if (!end) + end = info + os_strlen(info); + bi->info = os_malloc(end - info + 1); + if (!bi->info) + return -1; + os_memcpy(bi->info, info, end - info); + bi->info[end - info] = '\0'; + wpa_printf(MSG_DEBUG, "DPP: URI(information): %s", bi->info); + if (!dpp_uri_valid_info(bi->info)) { + wpa_printf(MSG_DEBUG, "DPP: Invalid URI information payload"); + return -1; + } + + return 0; +} + + +static const struct dpp_curve_params * +dpp_get_curve_oid(const ASN1_OBJECT *poid) +{ + ASN1_OBJECT *oid; + int i; + + for (i = 0; dpp_curves[i].name; i++) { + oid = OBJ_txt2obj(dpp_curves[i].name, 0); + if (oid && OBJ_cmp(poid, oid) == 0) + return &dpp_curves[i]; + } + return NULL; +} + + +static const struct dpp_curve_params * dpp_get_curve_nid(int nid) +{ + int i, tmp; + + if (!nid) + return NULL; + for (i = 0; dpp_curves[i].name; i++) { + tmp = OBJ_txt2nid(dpp_curves[i].name); + if (tmp == nid) + return &dpp_curves[i]; + } + return NULL; +} + + +static int dpp_parse_uri_pk(struct dpp_bootstrap_info *bi, const char *info) +{ + const char *end; + u8 *data; + size_t data_len; + EVP_PKEY *pkey; + const unsigned char *p; + int res; + X509_PUBKEY *pub = NULL; + ASN1_OBJECT *ppkalg; + const unsigned char *pk; + int ppklen; + X509_ALGOR *pa; +#if OPENSSL_VERSION_NUMBER < 0x10100000L || \ + (defined(LIBRESSL_VERSION_NUMBER) && \ + LIBRESSL_VERSION_NUMBER < 0x20800000L) + ASN1_OBJECT *pa_oid; +#else + const ASN1_OBJECT *pa_oid; +#endif + const void *pval; + int ptype; + const ASN1_OBJECT *poid; + char buf[100]; + + end = os_strchr(info, ';'); + if (!end) + return -1; + + data = base64_decode((const unsigned char *) info, end - info, + &data_len); + if (!data) { + wpa_printf(MSG_DEBUG, + "DPP: Invalid base64 encoding on URI public-key"); + return -1; + } + wpa_hexdump(MSG_DEBUG, "DPP: Base64 decoded URI public-key", + data, data_len); + + if (sha256_vector(1, (const u8 **) &data, &data_len, + bi->pubkey_hash) < 0) { + wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key"); + os_free(data); + return -1; + } + wpa_hexdump(MSG_DEBUG, "DPP: Public key hash", + bi->pubkey_hash, SHA256_MAC_LEN); + + /* DER encoded ASN.1 SubjectPublicKeyInfo + * + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING } + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL } + * + * subjectPublicKey = compressed format public key per ANSI X9.63 + * algorithm = ecPublicKey (1.2.840.10045.2.1) + * parameters = shall be present and shall be OBJECT IDENTIFIER; e.g., + * prime256v1 (1.2.840.10045.3.1.7) + */ + + p = data; + pkey = d2i_PUBKEY(NULL, &p, data_len); + os_free(data); + + if (!pkey) { + wpa_printf(MSG_DEBUG, + "DPP: Could not parse URI public-key SubjectPublicKeyInfo"); + return -1; + } + + if (EVP_PKEY_type(EVP_PKEY_id(pkey)) != EVP_PKEY_EC) { + wpa_printf(MSG_DEBUG, + "DPP: SubjectPublicKeyInfo does not describe an EC key"); + EVP_PKEY_free(pkey); + return -1; + } + + res = X509_PUBKEY_set(&pub, pkey); + if (res != 1) { + wpa_printf(MSG_DEBUG, "DPP: Could not set pubkey"); + goto fail; + } + + res = X509_PUBKEY_get0_param(&ppkalg, &pk, &ppklen, &pa, pub); + if (res != 1) { + wpa_printf(MSG_DEBUG, + "DPP: Could not extract SubjectPublicKeyInfo parameters"); + goto fail; + } + res = OBJ_obj2txt(buf, sizeof(buf), ppkalg, 0); + if (res < 0 || (size_t) res >= sizeof(buf)) { + wpa_printf(MSG_DEBUG, + "DPP: Could not extract SubjectPublicKeyInfo algorithm"); + goto fail; + } + wpa_printf(MSG_DEBUG, "DPP: URI subjectPublicKey algorithm: %s", buf); + if (os_strcmp(buf, "id-ecPublicKey") != 0) { + wpa_printf(MSG_DEBUG, + "DPP: Unsupported SubjectPublicKeyInfo algorithm"); + goto fail; + } + + X509_ALGOR_get0(&pa_oid, &ptype, (void *) &pval, pa); + if (ptype != V_ASN1_OBJECT) { + wpa_printf(MSG_DEBUG, + "DPP: SubjectPublicKeyInfo parameters did not contain an OID"); + goto fail; + } + poid = pval; + res = OBJ_obj2txt(buf, sizeof(buf), poid, 0); + if (res < 0 || (size_t) res >= sizeof(buf)) { + wpa_printf(MSG_DEBUG, + "DPP: Could not extract SubjectPublicKeyInfo parameters OID"); + goto fail; + } + wpa_printf(MSG_DEBUG, "DPP: URI subjectPublicKey parameters: %s", buf); + bi->curve = dpp_get_curve_oid(poid); + if (!bi->curve) { + wpa_printf(MSG_DEBUG, + "DPP: Unsupported SubjectPublicKeyInfo curve: %s", + buf); + goto fail; + } + + wpa_hexdump(MSG_DEBUG, "DPP: URI subjectPublicKey", pk, ppklen); + + X509_PUBKEY_free(pub); + bi->pubkey = pkey; + return 0; +fail: + X509_PUBKEY_free(pub); + EVP_PKEY_free(pkey); + return -1; +} + + +static struct dpp_bootstrap_info * dpp_parse_uri(const char *uri) +{ + const char *pos = uri; + const char *end; + const char *chan_list = NULL, *mac = NULL, *info = NULL, *pk = NULL; + struct dpp_bootstrap_info *bi; + + wpa_hexdump_ascii(MSG_DEBUG, "DPP: URI", uri, os_strlen(uri)); + + if (os_strncmp(pos, "DPP:", 4) != 0) { + wpa_printf(MSG_INFO, "DPP: Not a DPP URI"); + return NULL; + } + pos += 4; + + for (;;) { + end = os_strchr(pos, ';'); + if (!end) + break; + + if (end == pos) { + /* Handle terminating ";;" and ignore unexpected ";" + * for parsing robustness. */ + pos++; + continue; + } + + if (pos[0] == 'C' && pos[1] == ':' && !chan_list) + chan_list = pos + 2; + else if (pos[0] == 'M' && pos[1] == ':' && !mac) + mac = pos + 2; + else if (pos[0] == 'I' && pos[1] == ':' && !info) + info = pos + 2; + else if (pos[0] == 'K' && pos[1] == ':' && !pk) + pk = pos + 2; + else + wpa_hexdump_ascii(MSG_DEBUG, + "DPP: Ignore unrecognized URI parameter", + pos, end - pos); + pos = end + 1; + } + + if (!pk) { + wpa_printf(MSG_INFO, "DPP: URI missing public-key"); + return NULL; + } + + bi = os_zalloc(sizeof(*bi)); + if (!bi) + return NULL; + + if (dpp_clone_uri(bi, uri) < 0 || + dpp_parse_uri_chan_list(bi, chan_list) < 0 || + dpp_parse_uri_mac(bi, mac) < 0 || + dpp_parse_uri_info(bi, info) < 0 || + dpp_parse_uri_pk(bi, pk) < 0) { + dpp_bootstrap_info_free(bi); + bi = NULL; + } + + return bi; +} + + +struct dpp_bootstrap_info * dpp_parse_qr_code(const char *uri) +{ + struct dpp_bootstrap_info *bi; + + bi = dpp_parse_uri(uri); + if (bi) + bi->type = DPP_BOOTSTRAP_QR_CODE; + return bi; +} + + +static void dpp_debug_print_key(const char *title, EVP_PKEY *key) +{ + EC_KEY *eckey; + BIO *out; + size_t rlen; + char *txt; + int res; + unsigned char *der = NULL; + int der_len; + const EC_GROUP *group; + const EC_POINT *point; + + out = BIO_new(BIO_s_mem()); + if (!out) + return; + + EVP_PKEY_print_private(out, key, 0, NULL); + rlen = BIO_ctrl_pending(out); + txt = os_malloc(rlen + 1); + if (txt) { + res = BIO_read(out, txt, rlen); + if (res > 0) { + txt[res] = '\0'; + wpa_printf(MSG_DEBUG, "%s: %s", title, txt); + } + os_free(txt); + } + BIO_free(out); + + eckey = EVP_PKEY_get1_EC_KEY(key); + if (!eckey) + return; + + group = EC_KEY_get0_group(eckey); + point = EC_KEY_get0_public_key(eckey); + if (group && point) + dpp_debug_print_point(title, group, point); + + der_len = i2d_ECPrivateKey(eckey, &der); + if (der_len > 0) + wpa_hexdump_key(MSG_DEBUG, "DPP: ECPrivateKey", der, der_len); + OPENSSL_free(der); + if (der_len <= 0) { + der = NULL; + der_len = i2d_EC_PUBKEY(eckey, &der); + if (der_len > 0) + wpa_hexdump(MSG_DEBUG, "DPP: EC_PUBKEY", der, der_len); + OPENSSL_free(der); + } + + EC_KEY_free(eckey); +} + + +static EVP_PKEY * dpp_gen_keypair(const struct dpp_curve_params *curve) +{ + EVP_PKEY_CTX *kctx = NULL; + EC_KEY *ec_params = NULL; + EVP_PKEY *params = NULL, *key = NULL; + int nid; + + wpa_printf(MSG_DEBUG, "DPP: Generating a keypair"); + + nid = OBJ_txt2nid(curve->name); + if (nid == NID_undef) { + wpa_printf(MSG_INFO, "DPP: Unsupported curve %s", curve->name); + return NULL; + } + + ec_params = EC_KEY_new_by_curve_name(nid); + if (!ec_params) { + wpa_printf(MSG_ERROR, + "DPP: Failed to generate EC_KEY parameters"); + goto fail; + } + EC_KEY_set_asn1_flag(ec_params, OPENSSL_EC_NAMED_CURVE); + params = EVP_PKEY_new(); + if (!params || EVP_PKEY_set1_EC_KEY(params, ec_params) != 1) { + wpa_printf(MSG_ERROR, + "DPP: Failed to generate EVP_PKEY parameters"); + goto fail; + } + + kctx = EVP_PKEY_CTX_new(params, NULL); + if (!kctx || + EVP_PKEY_keygen_init(kctx) != 1 || + EVP_PKEY_keygen(kctx, &key) != 1) { + wpa_printf(MSG_ERROR, "DPP: Failed to generate EC key"); + key = NULL; + goto fail; + } + + if (wpa_debug_show_keys) + dpp_debug_print_key("Own generated key", key); + +fail: + EC_KEY_free(ec_params); + EVP_PKEY_free(params); + EVP_PKEY_CTX_free(kctx); + return key; +} + + +static const struct dpp_curve_params * +dpp_get_curve_name(const char *name) +{ + int i; + + for (i = 0; dpp_curves[i].name; i++) { + if (os_strcmp(name, dpp_curves[i].name) == 0 || + (dpp_curves[i].jwk_crv && + os_strcmp(name, dpp_curves[i].jwk_crv) == 0)) + return &dpp_curves[i]; + } + return NULL; +} + + +static const struct dpp_curve_params * +dpp_get_curve_jwk_crv(const char *name) +{ + int i; + + for (i = 0; dpp_curves[i].name; i++) { + if (dpp_curves[i].jwk_crv && + os_strcmp(name, dpp_curves[i].jwk_crv) == 0) + return &dpp_curves[i]; + } + return NULL; +} + + +static EVP_PKEY * dpp_set_keypair(const struct dpp_curve_params **curve, + const u8 *privkey, size_t privkey_len) +{ + EVP_PKEY *pkey; + EC_KEY *eckey; + const EC_GROUP *group; + int nid; + + pkey = EVP_PKEY_new(); + if (!pkey) + return NULL; + eckey = d2i_ECPrivateKey(NULL, &privkey, privkey_len); + if (!eckey) { + wpa_printf(MSG_INFO, + "DPP: OpenSSL: d2i_ECPrivateKey() failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + EVP_PKEY_free(pkey); + return NULL; + } + group = EC_KEY_get0_group(eckey); + if (!group) { + EC_KEY_free(eckey); + EVP_PKEY_free(pkey); + return NULL; + } + nid = EC_GROUP_get_curve_name(group); + *curve = dpp_get_curve_nid(nid); + if (!*curve) { + wpa_printf(MSG_INFO, + "DPP: Unsupported curve (nid=%d) in pre-assigned key", + nid); + EC_KEY_free(eckey); + EVP_PKEY_free(pkey); + return NULL; + } + + if (EVP_PKEY_assign_EC_KEY(pkey, eckey) != 1) { + EC_KEY_free(eckey); + EVP_PKEY_free(pkey); + return NULL; + } + return pkey; +} + + +typedef struct { + /* AlgorithmIdentifier ecPublicKey with optional parameters present + * as an OID identifying the curve */ + X509_ALGOR *alg; + /* Compressed format public key per ANSI X9.63 */ + ASN1_BIT_STRING *pub_key; +} DPP_BOOTSTRAPPING_KEY; + +ASN1_SEQUENCE(DPP_BOOTSTRAPPING_KEY) = { + ASN1_SIMPLE(DPP_BOOTSTRAPPING_KEY, alg, X509_ALGOR), + ASN1_SIMPLE(DPP_BOOTSTRAPPING_KEY, pub_key, ASN1_BIT_STRING) +} ASN1_SEQUENCE_END(DPP_BOOTSTRAPPING_KEY); + +IMPLEMENT_ASN1_FUNCTIONS(DPP_BOOTSTRAPPING_KEY); + + +static struct wpabuf * dpp_bootstrap_key_der(EVP_PKEY *key) +{ + unsigned char *der = NULL; + int der_len; + EC_KEY *eckey; + struct wpabuf *ret = NULL; + size_t len; + const EC_GROUP *group; + const EC_POINT *point; + BN_CTX *ctx; + DPP_BOOTSTRAPPING_KEY *bootstrap = NULL; + int nid; + + ctx = BN_CTX_new(); + eckey = EVP_PKEY_get1_EC_KEY(key); + if (!ctx || !eckey) + goto fail; + + group = EC_KEY_get0_group(eckey); + point = EC_KEY_get0_public_key(eckey); + if (!group || !point) + goto fail; + dpp_debug_print_point("DPP: bootstrap public key", group, point); + nid = EC_GROUP_get_curve_name(group); + + bootstrap = DPP_BOOTSTRAPPING_KEY_new(); + if (!bootstrap || + X509_ALGOR_set0(bootstrap->alg, OBJ_nid2obj(EVP_PKEY_EC), + V_ASN1_OBJECT, (void *) OBJ_nid2obj(nid)) != 1) + goto fail; + + len = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED, + NULL, 0, ctx); + if (len == 0) + goto fail; + + der = OPENSSL_malloc(len); + if (!der) + goto fail; + len = EC_POINT_point2oct(group, point, POINT_CONVERSION_COMPRESSED, + der, len, ctx); + + OPENSSL_free(bootstrap->pub_key->data); + bootstrap->pub_key->data = der; + der = NULL; + bootstrap->pub_key->length = len; + /* No unused bits */ + bootstrap->pub_key->flags &= ~(ASN1_STRING_FLAG_BITS_LEFT | 0x07); + bootstrap->pub_key->flags |= ASN1_STRING_FLAG_BITS_LEFT; + + der_len = i2d_DPP_BOOTSTRAPPING_KEY(bootstrap, &der); + if (der_len <= 0) { + wpa_printf(MSG_ERROR, + "DDP: Failed to build DER encoded public key"); + goto fail; + } + + ret = wpabuf_alloc_copy(der, der_len); +fail: + DPP_BOOTSTRAPPING_KEY_free(bootstrap); + OPENSSL_free(der); + EC_KEY_free(eckey); + BN_CTX_free(ctx); + return ret; +} + + +int dpp_bootstrap_key_hash(struct dpp_bootstrap_info *bi) +{ + struct wpabuf *der; + int res; + const u8 *addr[1]; + size_t len[1]; + + der = dpp_bootstrap_key_der(bi->pubkey); + if (!der) + return -1; + wpa_hexdump_buf(MSG_DEBUG, "DPP: Compressed public key (DER)", + der); + + addr[0] = wpabuf_head(der); + len[0] = wpabuf_len(der); + res = sha256_vector(1, addr, len, bi->pubkey_hash); + if (res < 0) + wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key"); + else + wpa_hexdump(MSG_DEBUG, "DPP: Public key hash", bi->pubkey_hash, + SHA256_MAC_LEN); + wpabuf_free(der); + return res; +} + + +char * dpp_keygen(struct dpp_bootstrap_info *bi, const char *curve, + const u8 *privkey, size_t privkey_len) +{ + unsigned char *base64 = NULL; + char *pos, *end; + size_t len; + struct wpabuf *der = NULL; + const u8 *addr[1]; + int res; + + if (!curve) { + bi->curve = &dpp_curves[0]; + } else { + bi->curve = dpp_get_curve_name(curve); + if (!bi->curve) { + wpa_printf(MSG_INFO, "DPP: Unsupported curve: %s", + curve); + return NULL; + } + } + if (privkey) + bi->pubkey = dpp_set_keypair(&bi->curve, privkey, privkey_len); + else + bi->pubkey = dpp_gen_keypair(bi->curve); + if (!bi->pubkey) + goto fail; + bi->own = 1; + + der = dpp_bootstrap_key_der(bi->pubkey); + if (!der) + goto fail; + wpa_hexdump_buf(MSG_DEBUG, "DPP: Compressed public key (DER)", + der); + + addr[0] = wpabuf_head(der); + len = wpabuf_len(der); + res = sha256_vector(1, addr, &len, bi->pubkey_hash); + if (res < 0) { + wpa_printf(MSG_DEBUG, "DPP: Failed to hash public key"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: Public key hash", bi->pubkey_hash, + SHA256_MAC_LEN); + + base64 = base64_encode(wpabuf_head(der), wpabuf_len(der), &len); + wpabuf_free(der); + der = NULL; + if (!base64) + goto fail; + pos = (char *) base64; + end = pos + len; + for (;;) { + pos = os_strchr(pos, '\n'); + if (!pos) + break; + os_memmove(pos, pos + 1, end - pos); + } + return (char *) base64; +fail: + os_free(base64); + wpabuf_free(der); + return NULL; +} + + +static int dpp_derive_k1(const u8 *Mx, size_t Mx_len, u8 *k1, + unsigned int hash_len) +{ + u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN]; + const char *info = "first intermediate key"; + int res; + + /* k1 = HKDF(<>, "first intermediate key", M.x) */ + + /* HKDF-Extract(<>, M.x) */ + os_memset(salt, 0, hash_len); + if (dpp_hmac(hash_len, salt, hash_len, Mx, Mx_len, prk) < 0) + return -1; + wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=M.x)", + prk, hash_len); + + /* HKDF-Expand(PRK, info, L) */ + res = dpp_hkdf_expand(hash_len, prk, hash_len, info, k1, hash_len); + os_memset(prk, 0, hash_len); + if (res < 0) + return -1; + + wpa_hexdump_key(MSG_DEBUG, "DPP: k1 = HKDF-Expand(PRK, info, L)", + k1, hash_len); + return 0; +} + + +static int dpp_derive_k2(const u8 *Nx, size_t Nx_len, u8 *k2, + unsigned int hash_len) +{ + u8 salt[DPP_MAX_HASH_LEN], prk[DPP_MAX_HASH_LEN]; + const char *info = "second intermediate key"; + int res; + + /* k2 = HKDF(<>, "second intermediate key", N.x) */ + + /* HKDF-Extract(<>, N.x) */ + os_memset(salt, 0, hash_len); + res = dpp_hmac(hash_len, salt, hash_len, Nx, Nx_len, prk); + if (res < 0) + return -1; + wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM=N.x)", + prk, hash_len); + + /* HKDF-Expand(PRK, info, L) */ + res = dpp_hkdf_expand(hash_len, prk, hash_len, info, k2, hash_len); + os_memset(prk, 0, hash_len); + if (res < 0) + return -1; + + wpa_hexdump_key(MSG_DEBUG, "DPP: k2 = HKDF-Expand(PRK, info, L)", + k2, hash_len); + return 0; +} + + +static int dpp_derive_ke(struct dpp_authentication *auth, u8 *ke, + unsigned int hash_len) +{ + size_t nonce_len; + u8 nonces[2 * DPP_MAX_NONCE_LEN]; + const char *info_ke = "DPP Key"; + u8 prk[DPP_MAX_HASH_LEN]; + int res; + const u8 *addr[3]; + size_t len[3]; + size_t num_elem = 0; + + if (!auth->Mx_len || !auth->Nx_len) { + wpa_printf(MSG_DEBUG, + "DPP: Mx/Nx not available - cannot derive ke"); + return -1; + } + + /* ke = HKDF(I-nonce | R-nonce, "DPP Key", M.x | N.x [| L.x]) */ + + /* HKDF-Extract(I-nonce | R-nonce, M.x | N.x [| L.x]) */ + nonce_len = auth->curve->nonce_len; + os_memcpy(nonces, auth->i_nonce, nonce_len); + os_memcpy(&nonces[nonce_len], auth->r_nonce, nonce_len); + addr[num_elem] = auth->Mx; + len[num_elem] = auth->Mx_len; + num_elem++; + addr[num_elem] = auth->Nx; + len[num_elem] = auth->Nx_len; + num_elem++; + if (auth->peer_bi && auth->own_bi) { + if (!auth->Lx_len) { + wpa_printf(MSG_DEBUG, + "DPP: Lx not available - cannot derive ke"); + return -1; + } + addr[num_elem] = auth->Lx; + len[num_elem] = auth->secret_len; + num_elem++; + } + res = dpp_hmac_vector(hash_len, nonces, 2 * nonce_len, + num_elem, addr, len, prk); + if (res < 0) + return -1; + wpa_hexdump_key(MSG_DEBUG, "DPP: PRK = HKDF-Extract(<>, IKM)", + prk, hash_len); + + /* HKDF-Expand(PRK, info, L) */ + res = dpp_hkdf_expand(hash_len, prk, hash_len, info_ke, ke, hash_len); + os_memset(prk, 0, hash_len); + if (res < 0) + return -1; + + wpa_hexdump_key(MSG_DEBUG, "DPP: ke = HKDF-Expand(PRK, info, L)", + ke, hash_len); + return 0; +} + + +static void dpp_build_attr_status(struct wpabuf *msg, + enum dpp_status_error status) +{ + wpa_printf(MSG_DEBUG, "DPP: Status %d", status); + wpabuf_put_le16(msg, DPP_ATTR_STATUS); + wpabuf_put_le16(msg, 1); + wpabuf_put_u8(msg, status); +} + + +static void dpp_build_attr_r_bootstrap_key_hash(struct wpabuf *msg, + const u8 *hash) +{ + if (hash) { + wpa_printf(MSG_DEBUG, "DPP: R-Bootstrap Key Hash"); + wpabuf_put_le16(msg, DPP_ATTR_R_BOOTSTRAP_KEY_HASH); + wpabuf_put_le16(msg, SHA256_MAC_LEN); + wpabuf_put_data(msg, hash, SHA256_MAC_LEN); + } +} + + +static void dpp_build_attr_i_bootstrap_key_hash(struct wpabuf *msg, + const u8 *hash) +{ + if (hash) { + wpa_printf(MSG_DEBUG, "DPP: I-Bootstrap Key Hash"); + wpabuf_put_le16(msg, DPP_ATTR_I_BOOTSTRAP_KEY_HASH); + wpabuf_put_le16(msg, SHA256_MAC_LEN); + wpabuf_put_data(msg, hash, SHA256_MAC_LEN); + } +} + + +static struct wpabuf * dpp_auth_build_req(struct dpp_authentication *auth, + const struct wpabuf *pi, + size_t nonce_len, + const u8 *r_pubkey_hash, + const u8 *i_pubkey_hash, + unsigned int neg_freq) +{ + struct wpabuf *msg; + u8 clear[4 + DPP_MAX_NONCE_LEN + 4 + 1]; + u8 wrapped_data[4 + DPP_MAX_NONCE_LEN + 4 + 1 + AES_BLOCK_SIZE]; + u8 *pos; + const u8 *addr[2]; + size_t len[2], siv_len, attr_len; + u8 *attr_start, *attr_end; + + /* Build DPP Authentication Request frame attributes */ + attr_len = 2 * (4 + SHA256_MAC_LEN) + 4 + (pi ? wpabuf_len(pi) : 0) + + 4 + sizeof(wrapped_data); + if (neg_freq > 0) + attr_len += 4 + 2; +#ifdef CONFIG_DPP2 + attr_len += 5; +#endif /* CONFIG_DPP2 */ +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_REQ) + attr_len += 5; +#endif /* CONFIG_TESTING_OPTIONS */ + msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_REQ, attr_len); + if (!msg) + return NULL; + + attr_start = wpabuf_put(msg, 0); + + /* Responder Bootstrapping Key Hash */ + dpp_build_attr_r_bootstrap_key_hash(msg, r_pubkey_hash); + + /* Initiator Bootstrapping Key Hash */ + dpp_build_attr_i_bootstrap_key_hash(msg, i_pubkey_hash); + + /* Initiator Protocol Key */ + if (pi) { + wpabuf_put_le16(msg, DPP_ATTR_I_PROTOCOL_KEY); + wpabuf_put_le16(msg, wpabuf_len(pi)); + wpabuf_put_buf(msg, pi); + } + + /* Channel */ + if (neg_freq > 0) { + u8 op_class, channel; + + if (ieee80211_freq_to_channel_ext(neg_freq, 0, 0, &op_class, + &channel) == + NUM_HOSTAPD_MODES) { + wpa_printf(MSG_INFO, + "DPP: Unsupported negotiation frequency request: %d", + neg_freq); + wpabuf_free(msg); + return NULL; + } + wpabuf_put_le16(msg, DPP_ATTR_CHANNEL); + wpabuf_put_le16(msg, 2); + wpabuf_put_u8(msg, op_class); + wpabuf_put_u8(msg, channel); + } + +#ifdef CONFIG_DPP2 + /* Protocol Version */ + wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION); + wpabuf_put_le16(msg, 1); + wpabuf_put_u8(msg, 2); +#endif /* CONFIG_DPP2 */ + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_AUTH_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data"); + goto skip_wrapped_data; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + /* Wrapped data ({I-nonce, I-capabilities}k1) */ + pos = clear; + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_NO_I_NONCE_AUTH_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - no I-nonce"); + goto skip_i_nonce; + } + if (dpp_test == DPP_TEST_INVALID_I_NONCE_AUTH_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - invalid I-nonce"); + WPA_PUT_LE16(pos, DPP_ATTR_I_NONCE); + pos += 2; + WPA_PUT_LE16(pos, nonce_len - 1); + pos += 2; + os_memcpy(pos, auth->i_nonce, nonce_len - 1); + pos += nonce_len - 1; + goto skip_i_nonce; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + /* I-nonce */ + WPA_PUT_LE16(pos, DPP_ATTR_I_NONCE); + pos += 2; + WPA_PUT_LE16(pos, nonce_len); + pos += 2; + os_memcpy(pos, auth->i_nonce, nonce_len); + pos += nonce_len; + +#ifdef CONFIG_TESTING_OPTIONS +skip_i_nonce: + if (dpp_test == DPP_TEST_NO_I_CAPAB_AUTH_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - no I-capab"); + goto skip_i_capab; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + /* I-capabilities */ + WPA_PUT_LE16(pos, DPP_ATTR_I_CAPABILITIES); + pos += 2; + WPA_PUT_LE16(pos, 1); + pos += 2; + auth->i_capab = auth->allowed_roles; + *pos++ = auth->i_capab; +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_ZERO_I_CAPAB) { + wpa_printf(MSG_INFO, "DPP: TESTING - zero I-capabilities"); + pos[-1] = 0; + } +skip_i_capab: +#endif /* CONFIG_TESTING_OPTIONS */ + + attr_end = wpabuf_put(msg, 0); + + /* OUI, OUI type, Crypto Suite, DPP frame type */ + addr[0] = wpabuf_head_u8(msg) + 2; + len[0] = 3 + 1 + 1 + 1; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); + + /* Attributes before Wrapped Data */ + addr[1] = attr_start; + len[1] = attr_end - attr_start; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); + + siv_len = pos - clear; + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", clear, siv_len); + if (aes_siv_encrypt(auth->k1, auth->curve->hash_len, clear, siv_len, + 2, addr, len, wrapped_data) < 0) { + wpabuf_free(msg); + return NULL; + } + siv_len += AES_BLOCK_SIZE; + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", + wrapped_data, siv_len); + + wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA); + wpabuf_put_le16(msg, siv_len); + wpabuf_put_data(msg, wrapped_data, siv_len); + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data"); + dpp_build_attr_status(msg, DPP_STATUS_OK); + } +skip_wrapped_data: +#endif /* CONFIG_TESTING_OPTIONS */ + + wpa_hexdump_buf(MSG_DEBUG, + "DPP: Authentication Request frame attributes", msg); + + return msg; +} + + +static struct wpabuf * dpp_auth_build_resp(struct dpp_authentication *auth, + enum dpp_status_error status, + const struct wpabuf *pr, + size_t nonce_len, + const u8 *r_pubkey_hash, + const u8 *i_pubkey_hash, + const u8 *r_nonce, const u8 *i_nonce, + const u8 *wrapped_r_auth, + size_t wrapped_r_auth_len, + const u8 *siv_key) +{ + struct wpabuf *msg; +#define DPP_AUTH_RESP_CLEAR_LEN 2 * (4 + DPP_MAX_NONCE_LEN) + 4 + 1 + \ + 4 + 4 + DPP_MAX_HASH_LEN + AES_BLOCK_SIZE + u8 clear[DPP_AUTH_RESP_CLEAR_LEN]; + u8 wrapped_data[DPP_AUTH_RESP_CLEAR_LEN + AES_BLOCK_SIZE]; + const u8 *addr[2]; + size_t len[2], siv_len, attr_len; + u8 *attr_start, *attr_end, *pos; + + auth->waiting_auth_conf = 1; + auth->auth_resp_tries = 0; + + /* Build DPP Authentication Response frame attributes */ + attr_len = 4 + 1 + 2 * (4 + SHA256_MAC_LEN) + + 4 + (pr ? wpabuf_len(pr) : 0) + 4 + sizeof(wrapped_data); +#ifdef CONFIG_DPP2 + attr_len += 5; +#endif /* CONFIG_DPP2 */ +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_RESP) + attr_len += 5; +#endif /* CONFIG_TESTING_OPTIONS */ + msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_RESP, attr_len); + if (!msg) + return NULL; + + attr_start = wpabuf_put(msg, 0); + + /* DPP Status */ + if (status != 255) + dpp_build_attr_status(msg, status); + + /* Responder Bootstrapping Key Hash */ + dpp_build_attr_r_bootstrap_key_hash(msg, r_pubkey_hash); + + /* Initiator Bootstrapping Key Hash (mutual authentication) */ + dpp_build_attr_i_bootstrap_key_hash(msg, i_pubkey_hash); + + /* Responder Protocol Key */ + if (pr) { + wpabuf_put_le16(msg, DPP_ATTR_R_PROTOCOL_KEY); + wpabuf_put_le16(msg, wpabuf_len(pr)); + wpabuf_put_buf(msg, pr); + } + +#ifdef CONFIG_DPP2 + /* Protocol Version */ + wpabuf_put_le16(msg, DPP_ATTR_PROTOCOL_VERSION); + wpabuf_put_le16(msg, 1); + wpabuf_put_u8(msg, 2); +#endif /* CONFIG_DPP2 */ + + attr_end = wpabuf_put(msg, 0); + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data"); + goto skip_wrapped_data; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + /* Wrapped data ({R-nonce, I-nonce, R-capabilities, {R-auth}ke}k2) */ + pos = clear; + + if (r_nonce) { + /* R-nonce */ + WPA_PUT_LE16(pos, DPP_ATTR_R_NONCE); + pos += 2; + WPA_PUT_LE16(pos, nonce_len); + pos += 2; + os_memcpy(pos, r_nonce, nonce_len); + pos += nonce_len; + } + + if (i_nonce) { + /* I-nonce */ + WPA_PUT_LE16(pos, DPP_ATTR_I_NONCE); + pos += 2; + WPA_PUT_LE16(pos, nonce_len); + pos += 2; + os_memcpy(pos, i_nonce, nonce_len); +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_I_NONCE_MISMATCH_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - I-nonce mismatch"); + pos[nonce_len / 2] ^= 0x01; + } +#endif /* CONFIG_TESTING_OPTIONS */ + pos += nonce_len; + } + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_NO_R_CAPAB_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - no R-capab"); + goto skip_r_capab; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + /* R-capabilities */ + WPA_PUT_LE16(pos, DPP_ATTR_R_CAPABILITIES); + pos += 2; + WPA_PUT_LE16(pos, 1); + pos += 2; + auth->r_capab = auth->configurator ? DPP_CAPAB_CONFIGURATOR : + DPP_CAPAB_ENROLLEE; + *pos++ = auth->r_capab; +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_ZERO_R_CAPAB) { + wpa_printf(MSG_INFO, "DPP: TESTING - zero R-capabilities"); + pos[-1] = 0; + } else if (dpp_test == DPP_TEST_INCOMPATIBLE_R_CAPAB_AUTH_RESP) { + wpa_printf(MSG_INFO, + "DPP: TESTING - incompatible R-capabilities"); + if ((auth->i_capab & DPP_CAPAB_ROLE_MASK) == + (DPP_CAPAB_CONFIGURATOR | DPP_CAPAB_ENROLLEE)) + pos[-1] = 0; + else + pos[-1] = auth->configurator ? DPP_CAPAB_ENROLLEE : + DPP_CAPAB_CONFIGURATOR; + } +skip_r_capab: +#endif /* CONFIG_TESTING_OPTIONS */ + + if (wrapped_r_auth) { + /* {R-auth}ke */ + WPA_PUT_LE16(pos, DPP_ATTR_WRAPPED_DATA); + pos += 2; + WPA_PUT_LE16(pos, wrapped_r_auth_len); + pos += 2; + os_memcpy(pos, wrapped_r_auth, wrapped_r_auth_len); + pos += wrapped_r_auth_len; + } + + /* OUI, OUI type, Crypto Suite, DPP frame type */ + addr[0] = wpabuf_head_u8(msg) + 2; + len[0] = 3 + 1 + 1 + 1; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); + + /* Attributes before Wrapped Data */ + addr[1] = attr_start; + len[1] = attr_end - attr_start; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); + + siv_len = pos - clear; + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", clear, siv_len); + if (aes_siv_encrypt(siv_key, auth->curve->hash_len, clear, siv_len, + 2, addr, len, wrapped_data) < 0) { + wpabuf_free(msg); + return NULL; + } + siv_len += AES_BLOCK_SIZE; + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", + wrapped_data, siv_len); + + wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA); + wpabuf_put_le16(msg, siv_len); + wpabuf_put_data(msg, wrapped_data, siv_len); + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data"); + dpp_build_attr_status(msg, DPP_STATUS_OK); + } +skip_wrapped_data: +#endif /* CONFIG_TESTING_OPTIONS */ + + wpa_hexdump_buf(MSG_DEBUG, + "DPP: Authentication Response frame attributes", msg); + return msg; +} + + +static int dpp_channel_ok_init(struct hostapd_hw_modes *own_modes, + u16 num_modes, unsigned int freq) +{ + u16 m; + int c, flag; + + if (!own_modes || !num_modes) + return 1; + + for (m = 0; m < num_modes; m++) { + for (c = 0; c < own_modes[m].num_channels; c++) { + if ((unsigned int) own_modes[m].channels[c].freq != + freq) + continue; + flag = own_modes[m].channels[c].flag; + if (!(flag & (HOSTAPD_CHAN_DISABLED | + HOSTAPD_CHAN_NO_IR | + HOSTAPD_CHAN_RADAR))) + return 1; + } + } + + wpa_printf(MSG_DEBUG, "DPP: Peer channel %u MHz not supported", freq); + return 0; +} + + +static int freq_included(const unsigned int freqs[], unsigned int num, + unsigned int freq) +{ + while (num > 0) { + if (freqs[--num] == freq) + return 1; + } + return 0; +} + + +static void freq_to_start(unsigned int freqs[], unsigned int num, + unsigned int freq) +{ + unsigned int i; + + for (i = 0; i < num; i++) { + if (freqs[i] == freq) + break; + } + if (i == 0 || i >= num) + return; + os_memmove(&freqs[1], &freqs[0], i * sizeof(freqs[0])); + freqs[0] = freq; +} + + +static int dpp_channel_intersect(struct dpp_authentication *auth, + struct hostapd_hw_modes *own_modes, + u16 num_modes) +{ + struct dpp_bootstrap_info *peer_bi = auth->peer_bi; + unsigned int i, freq; + + for (i = 0; i < peer_bi->num_freq; i++) { + freq = peer_bi->freq[i]; + if (freq_included(auth->freq, auth->num_freq, freq)) + continue; + if (dpp_channel_ok_init(own_modes, num_modes, freq)) + auth->freq[auth->num_freq++] = freq; + } + if (!auth->num_freq) { + wpa_printf(MSG_INFO, + "DPP: No available channels for initiating DPP Authentication"); + return -1; + } + auth->curr_freq = auth->freq[0]; + return 0; +} + + +static int dpp_channel_local_list(struct dpp_authentication *auth, + struct hostapd_hw_modes *own_modes, + u16 num_modes) +{ + u16 m; + int c, flag; + unsigned int freq; + + auth->num_freq = 0; + + if (!own_modes || !num_modes) { + auth->freq[0] = 2412; + auth->freq[1] = 2437; + auth->freq[2] = 2462; + auth->num_freq = 3; + return 0; + } + + for (m = 0; m < num_modes; m++) { + for (c = 0; c < own_modes[m].num_channels; c++) { + freq = own_modes[m].channels[c].freq; + flag = own_modes[m].channels[c].flag; + if (flag & (HOSTAPD_CHAN_DISABLED | + HOSTAPD_CHAN_NO_IR | + HOSTAPD_CHAN_RADAR)) + continue; + if (freq_included(auth->freq, auth->num_freq, freq)) + continue; + auth->freq[auth->num_freq++] = freq; + if (auth->num_freq == DPP_BOOTSTRAP_MAX_FREQ) { + m = num_modes; + break; + } + } + } + + return auth->num_freq == 0 ? -1 : 0; +} + + +static int dpp_prepare_channel_list(struct dpp_authentication *auth, + struct hostapd_hw_modes *own_modes, + u16 num_modes) +{ + int res; + char freqs[DPP_BOOTSTRAP_MAX_FREQ * 6 + 10], *pos, *end; + unsigned int i; + + if (auth->peer_bi->num_freq > 0) + res = dpp_channel_intersect(auth, own_modes, num_modes); + else + res = dpp_channel_local_list(auth, own_modes, num_modes); + if (res < 0) + return res; + + /* Prioritize 2.4 GHz channels 6, 1, 11 (in this order) to hit the most + * likely channels first. */ + freq_to_start(auth->freq, auth->num_freq, 2462); + freq_to_start(auth->freq, auth->num_freq, 2412); + freq_to_start(auth->freq, auth->num_freq, 2437); + + auth->freq_idx = 0; + auth->curr_freq = auth->freq[0]; + + pos = freqs; + end = pos + sizeof(freqs); + for (i = 0; i < auth->num_freq; i++) { + res = os_snprintf(pos, end - pos, " %u", auth->freq[i]); + if (os_snprintf_error(end - pos, res)) + break; + pos += res; + } + *pos = '\0'; + wpa_printf(MSG_DEBUG, "DPP: Possible frequencies for initiating:%s", + freqs); + + return 0; +} + + +static int dpp_autogen_bootstrap_key(struct dpp_authentication *auth) +{ + struct dpp_bootstrap_info *bi; + char *pk = NULL; + size_t len; + + if (auth->own_bi) + return 0; /* already generated */ + + bi = os_zalloc(sizeof(*bi)); + if (!bi) + return -1; + bi->type = DPP_BOOTSTRAP_QR_CODE; + pk = dpp_keygen(bi, auth->peer_bi->curve->name, NULL, 0); + if (!pk) + goto fail; + + len = 4; /* "DPP:" */ + len += 4 + os_strlen(pk); + bi->uri = os_malloc(len + 1); + if (!bi->uri) + goto fail; + os_snprintf(bi->uri, len + 1, "DPP:K:%s;;", pk); + wpa_printf(MSG_DEBUG, + "DPP: Auto-generated own bootstrapping key info: URI %s", + bi->uri); + + auth->tmp_own_bi = auth->own_bi = bi; + + os_free(pk); + + return 0; +fail: + os_free(pk); + dpp_bootstrap_info_free(bi); + return -1; +} + + +struct dpp_authentication * dpp_auth_init(void *msg_ctx, + struct dpp_bootstrap_info *peer_bi, + struct dpp_bootstrap_info *own_bi, + u8 dpp_allowed_roles, + unsigned int neg_freq, + struct hostapd_hw_modes *own_modes, + u16 num_modes) +{ + struct dpp_authentication *auth; + size_t nonce_len; + size_t secret_len; + struct wpabuf *pi = NULL; + const u8 *r_pubkey_hash, *i_pubkey_hash; +#ifdef CONFIG_TESTING_OPTIONS + u8 test_hash[SHA256_MAC_LEN]; +#endif /* CONFIG_TESTING_OPTIONS */ + + auth = os_zalloc(sizeof(*auth)); + if (!auth) + return NULL; + auth->msg_ctx = msg_ctx; + auth->initiator = 1; + auth->waiting_auth_resp = 1; + auth->allowed_roles = dpp_allowed_roles; + auth->configurator = !!(dpp_allowed_roles & DPP_CAPAB_CONFIGURATOR); + auth->peer_bi = peer_bi; + auth->own_bi = own_bi; + auth->curve = peer_bi->curve; + + if (dpp_autogen_bootstrap_key(auth) < 0 || + dpp_prepare_channel_list(auth, own_modes, num_modes) < 0) + goto fail; + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_nonce_override_len > 0) { + wpa_printf(MSG_INFO, "DPP: TESTING - override I-nonce"); + nonce_len = dpp_nonce_override_len; + os_memcpy(auth->i_nonce, dpp_nonce_override, nonce_len); + } else { + nonce_len = auth->curve->nonce_len; + if (random_get_bytes(auth->i_nonce, nonce_len)) { + wpa_printf(MSG_ERROR, + "DPP: Failed to generate I-nonce"); + goto fail; + } + } +#else /* CONFIG_TESTING_OPTIONS */ + nonce_len = auth->curve->nonce_len; + if (random_get_bytes(auth->i_nonce, nonce_len)) { + wpa_printf(MSG_ERROR, "DPP: Failed to generate I-nonce"); + goto fail; + } +#endif /* CONFIG_TESTING_OPTIONS */ + wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", auth->i_nonce, nonce_len); + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_protocol_key_override_len) { + const struct dpp_curve_params *tmp_curve; + + wpa_printf(MSG_INFO, + "DPP: TESTING - override protocol key"); + auth->own_protocol_key = dpp_set_keypair( + &tmp_curve, dpp_protocol_key_override, + dpp_protocol_key_override_len); + } else { + auth->own_protocol_key = dpp_gen_keypair(auth->curve); + } +#else /* CONFIG_TESTING_OPTIONS */ + auth->own_protocol_key = dpp_gen_keypair(auth->curve); +#endif /* CONFIG_TESTING_OPTIONS */ + if (!auth->own_protocol_key) + goto fail; + + pi = dpp_get_pubkey_point(auth->own_protocol_key, 0); + if (!pi) + goto fail; + + /* ECDH: M = pI * BR */ + if (dpp_ecdh(auth->own_protocol_key, auth->peer_bi->pubkey, + auth->Mx, &secret_len) < 0) + goto fail; + auth->secret_len = secret_len; + + wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (M.x)", + auth->Mx, auth->secret_len); + auth->Mx_len = auth->secret_len; + + if (dpp_derive_k1(auth->Mx, auth->secret_len, auth->k1, + auth->curve->hash_len) < 0) + goto fail; + + r_pubkey_hash = auth->peer_bi->pubkey_hash; + i_pubkey_hash = auth->own_bi->pubkey_hash; + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_NO_R_BOOTSTRAP_KEY_HASH_AUTH_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - no R-Bootstrap Key Hash"); + r_pubkey_hash = NULL; + } else if (dpp_test == DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_AUTH_REQ) { + wpa_printf(MSG_INFO, + "DPP: TESTING - invalid R-Bootstrap Key Hash"); + os_memcpy(test_hash, r_pubkey_hash, SHA256_MAC_LEN); + test_hash[SHA256_MAC_LEN - 1] ^= 0x01; + r_pubkey_hash = test_hash; + } else if (dpp_test == DPP_TEST_NO_I_BOOTSTRAP_KEY_HASH_AUTH_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - no I-Bootstrap Key Hash"); + i_pubkey_hash = NULL; + } else if (dpp_test == DPP_TEST_INVALID_I_BOOTSTRAP_KEY_HASH_AUTH_REQ) { + wpa_printf(MSG_INFO, + "DPP: TESTING - invalid I-Bootstrap Key Hash"); + os_memcpy(test_hash, i_pubkey_hash, SHA256_MAC_LEN); + test_hash[SHA256_MAC_LEN - 1] ^= 0x01; + i_pubkey_hash = test_hash; + } else if (dpp_test == DPP_TEST_NO_I_PROTO_KEY_AUTH_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - no I-Proto Key"); + wpabuf_free(pi); + pi = NULL; + } else if (dpp_test == DPP_TEST_INVALID_I_PROTO_KEY_AUTH_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - invalid I-Proto Key"); + wpabuf_free(pi); + pi = wpabuf_alloc(2 * auth->curve->prime_len); + if (!pi || dpp_test_gen_invalid_key(pi, auth->curve) < 0) + goto fail; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + auth->req_msg = dpp_auth_build_req(auth, pi, nonce_len, r_pubkey_hash, + i_pubkey_hash, neg_freq); + if (!auth->req_msg) + goto fail; + +out: + wpabuf_free(pi); + return auth; +fail: + dpp_auth_deinit(auth); + auth = NULL; + goto out; +} + + +static struct wpabuf * dpp_build_conf_req_attr(struct dpp_authentication *auth, + const char *json) +{ + size_t nonce_len; + size_t json_len, clear_len; + struct wpabuf *clear = NULL, *msg = NULL; + u8 *wrapped; + size_t attr_len; + + wpa_printf(MSG_DEBUG, "DPP: Build configuration request"); + + nonce_len = auth->curve->nonce_len; + if (random_get_bytes(auth->e_nonce, nonce_len)) { + wpa_printf(MSG_ERROR, "DPP: Failed to generate E-nonce"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: E-nonce", auth->e_nonce, nonce_len); + json_len = os_strlen(json); + wpa_hexdump_ascii(MSG_DEBUG, "DPP: configAttr JSON", json, json_len); + + /* { E-nonce, configAttrib }ke */ + clear_len = 4 + nonce_len + 4 + json_len; + clear = wpabuf_alloc(clear_len); + attr_len = 4 + clear_len + AES_BLOCK_SIZE; +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_CONF_REQ) + attr_len += 5; +#endif /* CONFIG_TESTING_OPTIONS */ + msg = wpabuf_alloc(attr_len); + if (!clear || !msg) + goto fail; + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_NO_E_NONCE_CONF_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - no E-nonce"); + goto skip_e_nonce; + } + if (dpp_test == DPP_TEST_INVALID_E_NONCE_CONF_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - invalid E-nonce"); + wpabuf_put_le16(clear, DPP_ATTR_ENROLLEE_NONCE); + wpabuf_put_le16(clear, nonce_len - 1); + wpabuf_put_data(clear, auth->e_nonce, nonce_len - 1); + goto skip_e_nonce; + } + if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_CONF_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data"); + goto skip_wrapped_data; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + /* E-nonce */ + wpabuf_put_le16(clear, DPP_ATTR_ENROLLEE_NONCE); + wpabuf_put_le16(clear, nonce_len); + wpabuf_put_data(clear, auth->e_nonce, nonce_len); + +#ifdef CONFIG_TESTING_OPTIONS +skip_e_nonce: + if (dpp_test == DPP_TEST_NO_CONFIG_ATTR_OBJ_CONF_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - no configAttrib"); + goto skip_conf_attr_obj; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + /* configAttrib */ + wpabuf_put_le16(clear, DPP_ATTR_CONFIG_ATTR_OBJ); + wpabuf_put_le16(clear, json_len); + wpabuf_put_data(clear, json, json_len); + +#ifdef CONFIG_TESTING_OPTIONS +skip_conf_attr_obj: +#endif /* CONFIG_TESTING_OPTIONS */ + + wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA); + wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE); + wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE); + + /* No AES-SIV AD */ + wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear); + if (aes_siv_encrypt(auth->ke, auth->curve->hash_len, + wpabuf_head(clear), wpabuf_len(clear), + 0, NULL, NULL, wrapped) < 0) + goto fail; + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", + wrapped, wpabuf_len(clear) + AES_BLOCK_SIZE); + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_CONF_REQ) { + wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data"); + dpp_build_attr_status(msg, DPP_STATUS_OK); + } +skip_wrapped_data: +#endif /* CONFIG_TESTING_OPTIONS */ + + wpa_hexdump_buf(MSG_DEBUG, + "DPP: Configuration Request frame attributes", msg); + wpabuf_free(clear); + return msg; + +fail: + wpabuf_free(clear); + wpabuf_free(msg); + return NULL; +} + + +static void dpp_write_adv_proto(struct wpabuf *buf) +{ + /* Advertisement Protocol IE */ + wpabuf_put_u8(buf, WLAN_EID_ADV_PROTO); + wpabuf_put_u8(buf, 8); /* Length */ + wpabuf_put_u8(buf, 0x7f); + wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC); + wpabuf_put_u8(buf, 5); + wpabuf_put_be24(buf, OUI_WFA); + wpabuf_put_u8(buf, DPP_OUI_TYPE); + wpabuf_put_u8(buf, 0x01); +} + + +static void dpp_write_gas_query(struct wpabuf *buf, struct wpabuf *query) +{ + /* GAS Query */ + wpabuf_put_le16(buf, wpabuf_len(query)); + wpabuf_put_buf(buf, query); +} + + +struct wpabuf * dpp_build_conf_req(struct dpp_authentication *auth, + const char *json) +{ + struct wpabuf *buf, *conf_req; + + conf_req = dpp_build_conf_req_attr(auth, json); + if (!conf_req) { + wpa_printf(MSG_DEBUG, + "DPP: No configuration request data available"); + return NULL; + } + + buf = gas_build_initial_req(0, 10 + 2 + wpabuf_len(conf_req)); + if (!buf) { + wpabuf_free(conf_req); + return NULL; + } + + dpp_write_adv_proto(buf); + dpp_write_gas_query(buf, conf_req); + wpabuf_free(conf_req); + wpa_hexdump_buf(MSG_MSGDUMP, "DPP: GAS Config Request", buf); + + return buf; +} + + +static void dpp_auth_success(struct dpp_authentication *auth) +{ + wpa_printf(MSG_DEBUG, + "DPP: Authentication success - clear temporary keys"); + os_memset(auth->Mx, 0, sizeof(auth->Mx)); + auth->Mx_len = 0; + os_memset(auth->Nx, 0, sizeof(auth->Nx)); + auth->Nx_len = 0; + os_memset(auth->Lx, 0, sizeof(auth->Lx)); + auth->Lx_len = 0; + os_memset(auth->k1, 0, sizeof(auth->k1)); + os_memset(auth->k2, 0, sizeof(auth->k2)); + + auth->auth_success = 1; +} + + +static int dpp_gen_r_auth(struct dpp_authentication *auth, u8 *r_auth) +{ + struct wpabuf *pix, *prx, *bix, *brx; + const u8 *addr[7]; + size_t len[7]; + size_t i, num_elem = 0; + size_t nonce_len; + u8 zero = 0; + int res = -1; + + /* R-auth = H(I-nonce | R-nonce | PI.x | PR.x | [BI.x |] BR.x | 0) */ + nonce_len = auth->curve->nonce_len; + + if (auth->initiator) { + pix = dpp_get_pubkey_point(auth->own_protocol_key, 0); + prx = dpp_get_pubkey_point(auth->peer_protocol_key, 0); + if (auth->own_bi) + bix = dpp_get_pubkey_point(auth->own_bi->pubkey, 0); + else + bix = NULL; + brx = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0); + } else { + pix = dpp_get_pubkey_point(auth->peer_protocol_key, 0); + prx = dpp_get_pubkey_point(auth->own_protocol_key, 0); + if (auth->peer_bi) + bix = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0); + else + bix = NULL; + brx = dpp_get_pubkey_point(auth->own_bi->pubkey, 0); + } + if (!pix || !prx || !brx) + goto fail; + + addr[num_elem] = auth->i_nonce; + len[num_elem] = nonce_len; + num_elem++; + + addr[num_elem] = auth->r_nonce; + len[num_elem] = nonce_len; + num_elem++; + + addr[num_elem] = wpabuf_head(pix); + len[num_elem] = wpabuf_len(pix) / 2; + num_elem++; + + addr[num_elem] = wpabuf_head(prx); + len[num_elem] = wpabuf_len(prx) / 2; + num_elem++; + + if (bix) { + addr[num_elem] = wpabuf_head(bix); + len[num_elem] = wpabuf_len(bix) / 2; + num_elem++; + } + + addr[num_elem] = wpabuf_head(brx); + len[num_elem] = wpabuf_len(brx) / 2; + num_elem++; + + addr[num_elem] = &zero; + len[num_elem] = 1; + num_elem++; + + wpa_printf(MSG_DEBUG, "DPP: R-auth hash components"); + for (i = 0; i < num_elem; i++) + wpa_hexdump(MSG_DEBUG, "DPP: hash component", addr[i], len[i]); + res = dpp_hash_vector(auth->curve, num_elem, addr, len, r_auth); + if (res == 0) + wpa_hexdump(MSG_DEBUG, "DPP: R-auth", r_auth, + auth->curve->hash_len); +fail: + wpabuf_free(pix); + wpabuf_free(prx); + wpabuf_free(bix); + wpabuf_free(brx); + return res; +} + + +static int dpp_gen_i_auth(struct dpp_authentication *auth, u8 *i_auth) +{ + struct wpabuf *pix = NULL, *prx = NULL, *bix = NULL, *brx = NULL; + const u8 *addr[7]; + size_t len[7]; + size_t i, num_elem = 0; + size_t nonce_len; + u8 one = 1; + int res = -1; + + /* I-auth = H(R-nonce | I-nonce | PR.x | PI.x | BR.x | [BI.x |] 1) */ + nonce_len = auth->curve->nonce_len; + + if (auth->initiator) { + pix = dpp_get_pubkey_point(auth->own_protocol_key, 0); + prx = dpp_get_pubkey_point(auth->peer_protocol_key, 0); + if (auth->own_bi) + bix = dpp_get_pubkey_point(auth->own_bi->pubkey, 0); + else + bix = NULL; + if (!auth->peer_bi) + goto fail; + brx = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0); + } else { + pix = dpp_get_pubkey_point(auth->peer_protocol_key, 0); + prx = dpp_get_pubkey_point(auth->own_protocol_key, 0); + if (auth->peer_bi) + bix = dpp_get_pubkey_point(auth->peer_bi->pubkey, 0); + else + bix = NULL; + if (!auth->own_bi) + goto fail; + brx = dpp_get_pubkey_point(auth->own_bi->pubkey, 0); + } + if (!pix || !prx || !brx) + goto fail; + + addr[num_elem] = auth->r_nonce; + len[num_elem] = nonce_len; + num_elem++; + + addr[num_elem] = auth->i_nonce; + len[num_elem] = nonce_len; + num_elem++; + + addr[num_elem] = wpabuf_head(prx); + len[num_elem] = wpabuf_len(prx) / 2; + num_elem++; + + addr[num_elem] = wpabuf_head(pix); + len[num_elem] = wpabuf_len(pix) / 2; + num_elem++; + + addr[num_elem] = wpabuf_head(brx); + len[num_elem] = wpabuf_len(brx) / 2; + num_elem++; + + if (bix) { + addr[num_elem] = wpabuf_head(bix); + len[num_elem] = wpabuf_len(bix) / 2; + num_elem++; + } + + addr[num_elem] = &one; + len[num_elem] = 1; + num_elem++; + + wpa_printf(MSG_DEBUG, "DPP: I-auth hash components"); + for (i = 0; i < num_elem; i++) + wpa_hexdump(MSG_DEBUG, "DPP: hash component", addr[i], len[i]); + res = dpp_hash_vector(auth->curve, num_elem, addr, len, i_auth); + if (res == 0) + wpa_hexdump(MSG_DEBUG, "DPP: I-auth", i_auth, + auth->curve->hash_len); +fail: + wpabuf_free(pix); + wpabuf_free(prx); + wpabuf_free(bix); + wpabuf_free(brx); + return res; +} + + +static int dpp_auth_derive_l_responder(struct dpp_authentication *auth) +{ + const EC_GROUP *group; + EC_POINT *l = NULL; + EC_KEY *BI = NULL, *bR = NULL, *pR = NULL; + const EC_POINT *BI_point; + BN_CTX *bnctx; + BIGNUM *lx, *sum, *q; + const BIGNUM *bR_bn, *pR_bn; + int ret = -1; + + /* L = ((bR + pR) modulo q) * BI */ + + bnctx = BN_CTX_new(); + sum = BN_new(); + q = BN_new(); + lx = BN_new(); + if (!bnctx || !sum || !q || !lx) + goto fail; + BI = EVP_PKEY_get1_EC_KEY(auth->peer_bi->pubkey); + if (!BI) + goto fail; + BI_point = EC_KEY_get0_public_key(BI); + group = EC_KEY_get0_group(BI); + if (!group) + goto fail; + + bR = EVP_PKEY_get1_EC_KEY(auth->own_bi->pubkey); + pR = EVP_PKEY_get1_EC_KEY(auth->own_protocol_key); + if (!bR || !pR) + goto fail; + bR_bn = EC_KEY_get0_private_key(bR); + pR_bn = EC_KEY_get0_private_key(pR); + if (!bR_bn || !pR_bn) + goto fail; + if (EC_GROUP_get_order(group, q, bnctx) != 1 || + BN_mod_add(sum, bR_bn, pR_bn, q, bnctx) != 1) + goto fail; + l = EC_POINT_new(group); + if (!l || + EC_POINT_mul(group, l, NULL, BI_point, sum, bnctx) != 1 || + EC_POINT_get_affine_coordinates_GFp(group, l, lx, NULL, + bnctx) != 1) { + wpa_printf(MSG_ERROR, + "OpenSSL: failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + + if (dpp_bn2bin_pad(lx, auth->Lx, auth->secret_len) < 0) + goto fail; + wpa_hexdump_key(MSG_DEBUG, "DPP: L.x", auth->Lx, auth->secret_len); + auth->Lx_len = auth->secret_len; + ret = 0; +fail: + EC_POINT_clear_free(l); + EC_KEY_free(BI); + EC_KEY_free(bR); + EC_KEY_free(pR); + BN_clear_free(lx); + BN_clear_free(sum); + BN_free(q); + BN_CTX_free(bnctx); + return ret; +} + + +static int dpp_auth_derive_l_initiator(struct dpp_authentication *auth) +{ + const EC_GROUP *group; + EC_POINT *l = NULL, *sum = NULL; + EC_KEY *bI = NULL, *BR = NULL, *PR = NULL; + const EC_POINT *BR_point, *PR_point; + BN_CTX *bnctx; + BIGNUM *lx; + const BIGNUM *bI_bn; + int ret = -1; + + /* L = bI * (BR + PR) */ + + bnctx = BN_CTX_new(); + lx = BN_new(); + if (!bnctx || !lx) + goto fail; + BR = EVP_PKEY_get1_EC_KEY(auth->peer_bi->pubkey); + PR = EVP_PKEY_get1_EC_KEY(auth->peer_protocol_key); + if (!BR || !PR) + goto fail; + BR_point = EC_KEY_get0_public_key(BR); + PR_point = EC_KEY_get0_public_key(PR); + + bI = EVP_PKEY_get1_EC_KEY(auth->own_bi->pubkey); + if (!bI) + goto fail; + group = EC_KEY_get0_group(bI); + bI_bn = EC_KEY_get0_private_key(bI); + if (!group || !bI_bn) + goto fail; + sum = EC_POINT_new(group); + l = EC_POINT_new(group); + if (!sum || !l || + EC_POINT_add(group, sum, BR_point, PR_point, bnctx) != 1 || + EC_POINT_mul(group, l, NULL, sum, bI_bn, bnctx) != 1 || + EC_POINT_get_affine_coordinates_GFp(group, l, lx, NULL, + bnctx) != 1) { + wpa_printf(MSG_ERROR, + "OpenSSL: failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + + if (dpp_bn2bin_pad(lx, auth->Lx, auth->secret_len) < 0) + goto fail; + wpa_hexdump_key(MSG_DEBUG, "DPP: L.x", auth->Lx, auth->secret_len); + auth->Lx_len = auth->secret_len; + ret = 0; +fail: + EC_POINT_clear_free(l); + EC_POINT_clear_free(sum); + EC_KEY_free(bI); + EC_KEY_free(BR); + EC_KEY_free(PR); + BN_clear_free(lx); + BN_CTX_free(bnctx); + return ret; +} + + +static int dpp_auth_build_resp_ok(struct dpp_authentication *auth) +{ + size_t nonce_len; + size_t secret_len; + struct wpabuf *msg, *pr = NULL; + u8 r_auth[4 + DPP_MAX_HASH_LEN]; + u8 wrapped_r_auth[4 + DPP_MAX_HASH_LEN + AES_BLOCK_SIZE], *w_r_auth; + size_t wrapped_r_auth_len; + int ret = -1; + const u8 *r_pubkey_hash, *i_pubkey_hash, *r_nonce, *i_nonce; + enum dpp_status_error status = DPP_STATUS_OK; +#ifdef CONFIG_TESTING_OPTIONS + u8 test_hash[SHA256_MAC_LEN]; +#endif /* CONFIG_TESTING_OPTIONS */ + + wpa_printf(MSG_DEBUG, "DPP: Build Authentication Response"); + if (!auth->own_bi) + return -1; + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_nonce_override_len > 0) { + wpa_printf(MSG_INFO, "DPP: TESTING - override R-nonce"); + nonce_len = dpp_nonce_override_len; + os_memcpy(auth->r_nonce, dpp_nonce_override, nonce_len); + } else { + nonce_len = auth->curve->nonce_len; + if (random_get_bytes(auth->r_nonce, nonce_len)) { + wpa_printf(MSG_ERROR, + "DPP: Failed to generate R-nonce"); + goto fail; + } + } +#else /* CONFIG_TESTING_OPTIONS */ + nonce_len = auth->curve->nonce_len; + if (random_get_bytes(auth->r_nonce, nonce_len)) { + wpa_printf(MSG_ERROR, "DPP: Failed to generate R-nonce"); + goto fail; + } +#endif /* CONFIG_TESTING_OPTIONS */ + wpa_hexdump(MSG_DEBUG, "DPP: R-nonce", auth->r_nonce, nonce_len); + + EVP_PKEY_free(auth->own_protocol_key); +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_protocol_key_override_len) { + const struct dpp_curve_params *tmp_curve; + + wpa_printf(MSG_INFO, + "DPP: TESTING - override protocol key"); + auth->own_protocol_key = dpp_set_keypair( + &tmp_curve, dpp_protocol_key_override, + dpp_protocol_key_override_len); + } else { + auth->own_protocol_key = dpp_gen_keypair(auth->curve); + } +#else /* CONFIG_TESTING_OPTIONS */ + auth->own_protocol_key = dpp_gen_keypair(auth->curve); +#endif /* CONFIG_TESTING_OPTIONS */ + if (!auth->own_protocol_key) + goto fail; + + pr = dpp_get_pubkey_point(auth->own_protocol_key, 0); + if (!pr) + goto fail; + + /* ECDH: N = pR * PI */ + if (dpp_ecdh(auth->own_protocol_key, auth->peer_protocol_key, + auth->Nx, &secret_len) < 0) + goto fail; + + wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (N.x)", + auth->Nx, auth->secret_len); + auth->Nx_len = auth->secret_len; + + if (dpp_derive_k2(auth->Nx, auth->secret_len, auth->k2, + auth->curve->hash_len) < 0) + goto fail; + + if (auth->own_bi && auth->peer_bi) { + /* Mutual authentication */ + if (dpp_auth_derive_l_responder(auth) < 0) + goto fail; + } + + if (dpp_derive_ke(auth, auth->ke, auth->curve->hash_len) < 0) + goto fail; + + /* R-auth = H(I-nonce | R-nonce | PI.x | PR.x | [BI.x |] BR.x | 0) */ + WPA_PUT_LE16(r_auth, DPP_ATTR_R_AUTH_TAG); + WPA_PUT_LE16(&r_auth[2], auth->curve->hash_len); + if (dpp_gen_r_auth(auth, r_auth + 4) < 0) + goto fail; +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_R_AUTH_MISMATCH_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - R-auth mismatch"); + r_auth[4 + auth->curve->hash_len / 2] ^= 0x01; + } +#endif /* CONFIG_TESTING_OPTIONS */ + if (aes_siv_encrypt(auth->ke, auth->curve->hash_len, + r_auth, 4 + auth->curve->hash_len, + 0, NULL, NULL, wrapped_r_auth) < 0) + goto fail; + wrapped_r_auth_len = 4 + auth->curve->hash_len + AES_BLOCK_SIZE; + wpa_hexdump(MSG_DEBUG, "DPP: {R-auth}ke", + wrapped_r_auth, wrapped_r_auth_len); + w_r_auth = wrapped_r_auth; + + r_pubkey_hash = auth->own_bi->pubkey_hash; + if (auth->peer_bi) + i_pubkey_hash = auth->peer_bi->pubkey_hash; + else + i_pubkey_hash = NULL; + + i_nonce = auth->i_nonce; + r_nonce = auth->r_nonce; + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_NO_R_BOOTSTRAP_KEY_HASH_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - no R-Bootstrap Key Hash"); + r_pubkey_hash = NULL; + } else if (dpp_test == + DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_AUTH_RESP) { + wpa_printf(MSG_INFO, + "DPP: TESTING - invalid R-Bootstrap Key Hash"); + os_memcpy(test_hash, r_pubkey_hash, SHA256_MAC_LEN); + test_hash[SHA256_MAC_LEN - 1] ^= 0x01; + r_pubkey_hash = test_hash; + } else if (dpp_test == DPP_TEST_NO_I_BOOTSTRAP_KEY_HASH_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - no I-Bootstrap Key Hash"); + i_pubkey_hash = NULL; + } else if (dpp_test == + DPP_TEST_INVALID_I_BOOTSTRAP_KEY_HASH_AUTH_RESP) { + wpa_printf(MSG_INFO, + "DPP: TESTING - invalid I-Bootstrap Key Hash"); + if (i_pubkey_hash) + os_memcpy(test_hash, i_pubkey_hash, SHA256_MAC_LEN); + else + os_memset(test_hash, 0, SHA256_MAC_LEN); + test_hash[SHA256_MAC_LEN - 1] ^= 0x01; + i_pubkey_hash = test_hash; + } else if (dpp_test == DPP_TEST_NO_R_PROTO_KEY_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - no R-Proto Key"); + wpabuf_free(pr); + pr = NULL; + } else if (dpp_test == DPP_TEST_INVALID_R_PROTO_KEY_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - invalid R-Proto Key"); + wpabuf_free(pr); + pr = wpabuf_alloc(2 * auth->curve->prime_len); + if (!pr || dpp_test_gen_invalid_key(pr, auth->curve) < 0) + goto fail; + } else if (dpp_test == DPP_TEST_NO_R_AUTH_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - no R-Auth"); + w_r_auth = NULL; + wrapped_r_auth_len = 0; + } else if (dpp_test == DPP_TEST_NO_STATUS_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - no Status"); + status = 255; + } else if (dpp_test == DPP_TEST_INVALID_STATUS_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - invalid Status"); + status = 254; + } else if (dpp_test == DPP_TEST_NO_R_NONCE_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - no R-nonce"); + r_nonce = NULL; + } else if (dpp_test == DPP_TEST_NO_I_NONCE_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - no I-nonce"); + i_nonce = NULL; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + msg = dpp_auth_build_resp(auth, status, pr, nonce_len, + r_pubkey_hash, i_pubkey_hash, + r_nonce, i_nonce, + w_r_auth, wrapped_r_auth_len, + auth->k2); + if (!msg) + goto fail; + wpabuf_free(auth->resp_msg); + auth->resp_msg = msg; + ret = 0; +fail: + wpabuf_free(pr); + return ret; +} + + +static int dpp_auth_build_resp_status(struct dpp_authentication *auth, + enum dpp_status_error status) +{ + struct wpabuf *msg; + const u8 *r_pubkey_hash, *i_pubkey_hash, *i_nonce; +#ifdef CONFIG_TESTING_OPTIONS + u8 test_hash[SHA256_MAC_LEN]; +#endif /* CONFIG_TESTING_OPTIONS */ + + if (!auth->own_bi) + return -1; + wpa_printf(MSG_DEBUG, "DPP: Build Authentication Response"); + + r_pubkey_hash = auth->own_bi->pubkey_hash; + if (auth->peer_bi) + i_pubkey_hash = auth->peer_bi->pubkey_hash; + else + i_pubkey_hash = NULL; + + i_nonce = auth->i_nonce; + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_NO_R_BOOTSTRAP_KEY_HASH_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - no R-Bootstrap Key Hash"); + r_pubkey_hash = NULL; + } else if (dpp_test == + DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_AUTH_RESP) { + wpa_printf(MSG_INFO, + "DPP: TESTING - invalid R-Bootstrap Key Hash"); + os_memcpy(test_hash, r_pubkey_hash, SHA256_MAC_LEN); + test_hash[SHA256_MAC_LEN - 1] ^= 0x01; + r_pubkey_hash = test_hash; + } else if (dpp_test == DPP_TEST_NO_I_BOOTSTRAP_KEY_HASH_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - no I-Bootstrap Key Hash"); + i_pubkey_hash = NULL; + } else if (dpp_test == + DPP_TEST_INVALID_I_BOOTSTRAP_KEY_HASH_AUTH_RESP) { + wpa_printf(MSG_INFO, + "DPP: TESTING - invalid I-Bootstrap Key Hash"); + if (i_pubkey_hash) + os_memcpy(test_hash, i_pubkey_hash, SHA256_MAC_LEN); + else + os_memset(test_hash, 0, SHA256_MAC_LEN); + test_hash[SHA256_MAC_LEN - 1] ^= 0x01; + i_pubkey_hash = test_hash; + } else if (dpp_test == DPP_TEST_NO_STATUS_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - no Status"); + status = 255; + } else if (dpp_test == DPP_TEST_NO_I_NONCE_AUTH_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - no I-nonce"); + i_nonce = NULL; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + msg = dpp_auth_build_resp(auth, status, NULL, auth->curve->nonce_len, + r_pubkey_hash, i_pubkey_hash, + NULL, i_nonce, NULL, 0, auth->k1); + if (!msg) + return -1; + wpabuf_free(auth->resp_msg); + auth->resp_msg = msg; + return 0; +} + + +struct dpp_authentication * +dpp_auth_req_rx(void *msg_ctx, u8 dpp_allowed_roles, int qr_mutual, + struct dpp_bootstrap_info *peer_bi, + struct dpp_bootstrap_info *own_bi, + unsigned int freq, const u8 *hdr, const u8 *attr_start, + size_t attr_len) +{ + EVP_PKEY *pi = NULL; + EVP_PKEY_CTX *ctx = NULL; + size_t secret_len; + const u8 *addr[2]; + size_t len[2]; + u8 *unwrapped = NULL; + size_t unwrapped_len = 0; + const u8 *wrapped_data, *i_proto, *i_nonce, *i_capab, *i_bootstrap, + *channel; + u16 wrapped_data_len, i_proto_len, i_nonce_len, i_capab_len, + i_bootstrap_len, channel_len; + struct dpp_authentication *auth = NULL; +#ifdef CONFIG_DPP2 + const u8 *version; + u16 version_len; +#endif /* CONFIG_DPP2 */ + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_STOP_AT_AUTH_REQ) { + wpa_printf(MSG_INFO, + "DPP: TESTING - stop at Authentication Request"); + return NULL; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA, + &wrapped_data_len); + if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) { + wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_FAIL + "Missing or invalid required Wrapped Data attribute"); + return NULL; + } + wpa_hexdump(MSG_MSGDUMP, "DPP: Wrapped Data", + wrapped_data, wrapped_data_len); + attr_len = wrapped_data - 4 - attr_start; + + auth = os_zalloc(sizeof(*auth)); + if (!auth) + goto fail; + auth->msg_ctx = msg_ctx; + auth->peer_bi = peer_bi; + auth->own_bi = own_bi; + auth->curve = own_bi->curve; + auth->curr_freq = freq; + + auth->peer_version = 1; /* default to the first version */ +#ifdef CONFIG_DPP2 + version = dpp_get_attr(attr_start, attr_len, DPP_ATTR_PROTOCOL_VERSION, + &version_len); + if (version) { + if (version_len < 1 || version[0] == 0) { + dpp_auth_fail(auth, + "Invalid Protocol Version attribute"); + goto fail; + } + auth->peer_version = version[0]; + wpa_printf(MSG_DEBUG, "DPP: Peer protocol version %u", + auth->peer_version); + } +#endif /* CONFIG_DPP2 */ + + channel = dpp_get_attr(attr_start, attr_len, DPP_ATTR_CHANNEL, + &channel_len); + if (channel) { + int neg_freq; + + if (channel_len < 2) { + dpp_auth_fail(auth, "Too short Channel attribute"); + goto fail; + } + + neg_freq = ieee80211_chan_to_freq(NULL, channel[0], channel[1]); + wpa_printf(MSG_DEBUG, + "DPP: Initiator requested different channel for negotiation: op_class=%u channel=%u --> freq=%d", + channel[0], channel[1], neg_freq); + if (neg_freq < 0) { + dpp_auth_fail(auth, + "Unsupported Channel attribute value"); + goto fail; + } + + if (auth->curr_freq != (unsigned int) neg_freq) { + wpa_printf(MSG_DEBUG, + "DPP: Changing negotiation channel from %u MHz to %u MHz", + freq, neg_freq); + auth->curr_freq = neg_freq; + } + } + + i_proto = dpp_get_attr(attr_start, attr_len, DPP_ATTR_I_PROTOCOL_KEY, + &i_proto_len); + if (!i_proto) { + dpp_auth_fail(auth, + "Missing required Initiator Protocol Key attribute"); + goto fail; + } + wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Protocol Key", + i_proto, i_proto_len); + + /* M = bR * PI */ + pi = dpp_set_pubkey_point(own_bi->pubkey, i_proto, i_proto_len); + if (!pi) { + dpp_auth_fail(auth, "Invalid Initiator Protocol Key"); + goto fail; + } + dpp_debug_print_key("Peer (Initiator) Protocol Key", pi); + + if (dpp_ecdh(own_bi->pubkey, pi, auth->Mx, &secret_len) < 0) + goto fail; + auth->secret_len = secret_len; + + wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (M.x)", + auth->Mx, auth->secret_len); + auth->Mx_len = auth->secret_len; + + if (dpp_derive_k1(auth->Mx, auth->secret_len, auth->k1, + auth->curve->hash_len) < 0) + goto fail; + + addr[0] = hdr; + len[0] = DPP_HDR_LEN; + addr[1] = attr_start; + len[1] = attr_len; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", + wrapped_data, wrapped_data_len); + unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE; + unwrapped = os_malloc(unwrapped_len); + if (!unwrapped) + goto fail; + if (aes_siv_decrypt(auth->k1, auth->curve->hash_len, + wrapped_data, wrapped_data_len, + 2, addr, len, unwrapped) < 0) { + dpp_auth_fail(auth, "AES-SIV decryption failed"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", + unwrapped, unwrapped_len); + + if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) { + dpp_auth_fail(auth, "Invalid attribute in unwrapped data"); + goto fail; + } + + i_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_NONCE, + &i_nonce_len); + if (!i_nonce || i_nonce_len != auth->curve->nonce_len) { + dpp_auth_fail(auth, "Missing or invalid I-nonce"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", i_nonce, i_nonce_len); + os_memcpy(auth->i_nonce, i_nonce, i_nonce_len); + + i_capab = dpp_get_attr(unwrapped, unwrapped_len, + DPP_ATTR_I_CAPABILITIES, + &i_capab_len); + if (!i_capab || i_capab_len < 1) { + dpp_auth_fail(auth, "Missing or invalid I-capabilities"); + goto fail; + } + auth->i_capab = i_capab[0]; + wpa_printf(MSG_DEBUG, "DPP: I-capabilities: 0x%02x", auth->i_capab); + + bin_clear_free(unwrapped, unwrapped_len); + unwrapped = NULL; + + switch (auth->i_capab & DPP_CAPAB_ROLE_MASK) { + case DPP_CAPAB_ENROLLEE: + if (!(dpp_allowed_roles & DPP_CAPAB_CONFIGURATOR)) { + wpa_printf(MSG_DEBUG, + "DPP: Local policy does not allow Configurator role"); + goto not_compatible; + } + wpa_printf(MSG_DEBUG, "DPP: Acting as Configurator"); + auth->configurator = 1; + break; + case DPP_CAPAB_CONFIGURATOR: + if (!(dpp_allowed_roles & DPP_CAPAB_ENROLLEE)) { + wpa_printf(MSG_DEBUG, + "DPP: Local policy does not allow Enrollee role"); + goto not_compatible; + } + wpa_printf(MSG_DEBUG, "DPP: Acting as Enrollee"); + auth->configurator = 0; + break; + case DPP_CAPAB_CONFIGURATOR | DPP_CAPAB_ENROLLEE: + if (dpp_allowed_roles & DPP_CAPAB_ENROLLEE) { + wpa_printf(MSG_DEBUG, "DPP: Acting as Enrollee"); + auth->configurator = 0; + } else if (dpp_allowed_roles & DPP_CAPAB_CONFIGURATOR) { + wpa_printf(MSG_DEBUG, "DPP: Acting as Configurator"); + auth->configurator = 1; + } else { + wpa_printf(MSG_DEBUG, + "DPP: Local policy does not allow Configurator/Enrollee role"); + goto not_compatible; + } + break; + default: + wpa_printf(MSG_DEBUG, "DPP: Unexpected role in I-capabilities"); + wpa_msg(auth->msg_ctx, MSG_INFO, + DPP_EVENT_FAIL "Invalid role in I-capabilities 0x%02x", + auth->i_capab & DPP_CAPAB_ROLE_MASK); + goto fail; + } + + auth->peer_protocol_key = pi; + pi = NULL; + if (qr_mutual && !peer_bi && own_bi->type == DPP_BOOTSTRAP_QR_CODE) { + char hex[SHA256_MAC_LEN * 2 + 1]; + + wpa_printf(MSG_DEBUG, + "DPP: Mutual authentication required with QR Codes, but peer info is not yet available - request more time"); + if (dpp_auth_build_resp_status(auth, + DPP_STATUS_RESPONSE_PENDING) < 0) + goto fail; + i_bootstrap = dpp_get_attr(attr_start, attr_len, + DPP_ATTR_I_BOOTSTRAP_KEY_HASH, + &i_bootstrap_len); + if (i_bootstrap && i_bootstrap_len == SHA256_MAC_LEN) { + auth->response_pending = 1; + os_memcpy(auth->waiting_pubkey_hash, + i_bootstrap, i_bootstrap_len); + wpa_snprintf_hex(hex, sizeof(hex), i_bootstrap, + i_bootstrap_len); + } else { + hex[0] = '\0'; + } + + wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_SCAN_PEER_QR_CODE + "%s", hex); + return auth; + } + if (dpp_auth_build_resp_ok(auth) < 0) + goto fail; + + return auth; + +not_compatible: + wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_NOT_COMPATIBLE + "i-capab=0x%02x", auth->i_capab); + if (dpp_allowed_roles & DPP_CAPAB_CONFIGURATOR) + auth->configurator = 1; + else + auth->configurator = 0; + auth->peer_protocol_key = pi; + pi = NULL; + if (dpp_auth_build_resp_status(auth, DPP_STATUS_NOT_COMPATIBLE) < 0) + goto fail; + + auth->remove_on_tx_status = 1; + return auth; +fail: + bin_clear_free(unwrapped, unwrapped_len); + EVP_PKEY_free(pi); + EVP_PKEY_CTX_free(ctx); + dpp_auth_deinit(auth); + return NULL; +} + + +int dpp_notify_new_qr_code(struct dpp_authentication *auth, + struct dpp_bootstrap_info *peer_bi) +{ + if (!auth || !auth->response_pending || + os_memcmp(auth->waiting_pubkey_hash, peer_bi->pubkey_hash, + SHA256_MAC_LEN) != 0) + return 0; + + wpa_printf(MSG_DEBUG, + "DPP: New scanned QR Code has matching public key that was needed to continue DPP Authentication exchange with " + MACSTR, MAC2STR(auth->peer_mac_addr)); + auth->peer_bi = peer_bi; + + if (dpp_auth_build_resp_ok(auth) < 0) + return -1; + + return 1; +} + + +static struct wpabuf * dpp_auth_build_conf(struct dpp_authentication *auth, + enum dpp_status_error status) +{ + struct wpabuf *msg; + u8 i_auth[4 + DPP_MAX_HASH_LEN]; + size_t i_auth_len; + u8 r_nonce[4 + DPP_MAX_NONCE_LEN]; + size_t r_nonce_len; + const u8 *addr[2]; + size_t len[2], attr_len; + u8 *wrapped_i_auth; + u8 *wrapped_r_nonce; + u8 *attr_start, *attr_end; + const u8 *r_pubkey_hash, *i_pubkey_hash; +#ifdef CONFIG_TESTING_OPTIONS + u8 test_hash[SHA256_MAC_LEN]; +#endif /* CONFIG_TESTING_OPTIONS */ + + wpa_printf(MSG_DEBUG, "DPP: Build Authentication Confirmation"); + + i_auth_len = 4 + auth->curve->hash_len; + r_nonce_len = 4 + auth->curve->nonce_len; + /* Build DPP Authentication Confirmation frame attributes */ + attr_len = 4 + 1 + 2 * (4 + SHA256_MAC_LEN) + + 4 + i_auth_len + r_nonce_len + AES_BLOCK_SIZE; +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_CONF) + attr_len += 5; +#endif /* CONFIG_TESTING_OPTIONS */ + msg = dpp_alloc_msg(DPP_PA_AUTHENTICATION_CONF, attr_len); + if (!msg) + goto fail; + + attr_start = wpabuf_put(msg, 0); + + r_pubkey_hash = auth->peer_bi->pubkey_hash; + if (auth->own_bi) + i_pubkey_hash = auth->own_bi->pubkey_hash; + else + i_pubkey_hash = NULL; + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_NO_STATUS_AUTH_CONF) { + wpa_printf(MSG_INFO, "DPP: TESTING - no Status"); + goto skip_status; + } else if (dpp_test == DPP_TEST_INVALID_STATUS_AUTH_CONF) { + wpa_printf(MSG_INFO, "DPP: TESTING - invalid Status"); + status = 254; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + /* DPP Status */ + dpp_build_attr_status(msg, status); + +#ifdef CONFIG_TESTING_OPTIONS +skip_status: + if (dpp_test == DPP_TEST_NO_R_BOOTSTRAP_KEY_HASH_AUTH_CONF) { + wpa_printf(MSG_INFO, "DPP: TESTING - no R-Bootstrap Key Hash"); + r_pubkey_hash = NULL; + } else if (dpp_test == + DPP_TEST_INVALID_R_BOOTSTRAP_KEY_HASH_AUTH_CONF) { + wpa_printf(MSG_INFO, + "DPP: TESTING - invalid R-Bootstrap Key Hash"); + os_memcpy(test_hash, r_pubkey_hash, SHA256_MAC_LEN); + test_hash[SHA256_MAC_LEN - 1] ^= 0x01; + r_pubkey_hash = test_hash; + } else if (dpp_test == DPP_TEST_NO_I_BOOTSTRAP_KEY_HASH_AUTH_CONF) { + wpa_printf(MSG_INFO, "DPP: TESTING - no I-Bootstrap Key Hash"); + i_pubkey_hash = NULL; + } else if (dpp_test == + DPP_TEST_INVALID_I_BOOTSTRAP_KEY_HASH_AUTH_CONF) { + wpa_printf(MSG_INFO, + "DPP: TESTING - invalid I-Bootstrap Key Hash"); + if (i_pubkey_hash) + os_memcpy(test_hash, i_pubkey_hash, SHA256_MAC_LEN); + else + os_memset(test_hash, 0, SHA256_MAC_LEN); + test_hash[SHA256_MAC_LEN - 1] ^= 0x01; + i_pubkey_hash = test_hash; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + /* Responder Bootstrapping Key Hash */ + dpp_build_attr_r_bootstrap_key_hash(msg, r_pubkey_hash); + + /* Initiator Bootstrapping Key Hash (mutual authentication) */ + dpp_build_attr_i_bootstrap_key_hash(msg, i_pubkey_hash); + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_AUTH_CONF) + goto skip_wrapped_data; + if (dpp_test == DPP_TEST_NO_I_AUTH_AUTH_CONF) + i_auth_len = 0; +#endif /* CONFIG_TESTING_OPTIONS */ + + attr_end = wpabuf_put(msg, 0); + + /* OUI, OUI type, Crypto Suite, DPP frame type */ + addr[0] = wpabuf_head_u8(msg) + 2; + len[0] = 3 + 1 + 1 + 1; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); + + /* Attributes before Wrapped Data */ + addr[1] = attr_start; + len[1] = attr_end - attr_start; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); + + if (status == DPP_STATUS_OK) { + /* I-auth wrapped with ke */ + wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA); + wpabuf_put_le16(msg, i_auth_len + AES_BLOCK_SIZE); + wrapped_i_auth = wpabuf_put(msg, i_auth_len + AES_BLOCK_SIZE); + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_NO_I_AUTH_AUTH_CONF) + goto skip_i_auth; +#endif /* CONFIG_TESTING_OPTIONS */ + + /* I-auth = H(R-nonce | I-nonce | PR.x | PI.x | BR.x | [BI.x |] + * 1) */ + WPA_PUT_LE16(i_auth, DPP_ATTR_I_AUTH_TAG); + WPA_PUT_LE16(&i_auth[2], auth->curve->hash_len); + if (dpp_gen_i_auth(auth, i_auth + 4) < 0) + goto fail; + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_I_AUTH_MISMATCH_AUTH_CONF) { + wpa_printf(MSG_INFO, "DPP: TESTING - I-auth mismatch"); + i_auth[4 + auth->curve->hash_len / 2] ^= 0x01; + } +skip_i_auth: +#endif /* CONFIG_TESTING_OPTIONS */ + if (aes_siv_encrypt(auth->ke, auth->curve->hash_len, + i_auth, i_auth_len, + 2, addr, len, wrapped_i_auth) < 0) + goto fail; + wpa_hexdump(MSG_DEBUG, "DPP: {I-auth}ke", + wrapped_i_auth, i_auth_len + AES_BLOCK_SIZE); + } else { + /* R-nonce wrapped with k2 */ + wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA); + wpabuf_put_le16(msg, r_nonce_len + AES_BLOCK_SIZE); + wrapped_r_nonce = wpabuf_put(msg, r_nonce_len + AES_BLOCK_SIZE); + + WPA_PUT_LE16(r_nonce, DPP_ATTR_R_NONCE); + WPA_PUT_LE16(&r_nonce[2], auth->curve->nonce_len); + os_memcpy(r_nonce + 4, auth->r_nonce, auth->curve->nonce_len); + + if (aes_siv_encrypt(auth->k2, auth->curve->hash_len, + r_nonce, r_nonce_len, + 2, addr, len, wrapped_r_nonce) < 0) + goto fail; + wpa_hexdump(MSG_DEBUG, "DPP: {R-nonce}k2", + wrapped_r_nonce, r_nonce_len + AES_BLOCK_SIZE); + } + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_AUTH_CONF) { + wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data"); + dpp_build_attr_status(msg, DPP_STATUS_OK); + } +skip_wrapped_data: +#endif /* CONFIG_TESTING_OPTIONS */ + + wpa_hexdump_buf(MSG_DEBUG, + "DPP: Authentication Confirmation frame attributes", + msg); + if (status == DPP_STATUS_OK) + dpp_auth_success(auth); + + return msg; + +fail: + wpabuf_free(msg); + return NULL; +} + + +static void +dpp_auth_resp_rx_status(struct dpp_authentication *auth, const u8 *hdr, + const u8 *attr_start, size_t attr_len, + const u8 *wrapped_data, u16 wrapped_data_len, + enum dpp_status_error status) +{ + const u8 *addr[2]; + size_t len[2]; + u8 *unwrapped = NULL; + size_t unwrapped_len = 0; + const u8 *i_nonce, *r_capab; + u16 i_nonce_len, r_capab_len; + + if (status == DPP_STATUS_NOT_COMPATIBLE) { + wpa_printf(MSG_DEBUG, + "DPP: Responder reported incompatible roles"); + } else if (status == DPP_STATUS_RESPONSE_PENDING) { + wpa_printf(MSG_DEBUG, + "DPP: Responder reported more time needed"); + } else { + wpa_printf(MSG_DEBUG, + "DPP: Responder reported failure (status %d)", + status); + dpp_auth_fail(auth, "Responder reported failure"); + return; + } + + addr[0] = hdr; + len[0] = DPP_HDR_LEN; + addr[1] = attr_start; + len[1] = attr_len; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", + wrapped_data, wrapped_data_len); + unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE; + unwrapped = os_malloc(unwrapped_len); + if (!unwrapped) + goto fail; + if (aes_siv_decrypt(auth->k1, auth->curve->hash_len, + wrapped_data, wrapped_data_len, + 2, addr, len, unwrapped) < 0) { + dpp_auth_fail(auth, "AES-SIV decryption failed"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", + unwrapped, unwrapped_len); + + if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) { + dpp_auth_fail(auth, "Invalid attribute in unwrapped data"); + goto fail; + } + + i_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_NONCE, + &i_nonce_len); + if (!i_nonce || i_nonce_len != auth->curve->nonce_len) { + dpp_auth_fail(auth, "Missing or invalid I-nonce"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", i_nonce, i_nonce_len); + if (os_memcmp(auth->i_nonce, i_nonce, i_nonce_len) != 0) { + dpp_auth_fail(auth, "I-nonce mismatch"); + goto fail; + } + + r_capab = dpp_get_attr(unwrapped, unwrapped_len, + DPP_ATTR_R_CAPABILITIES, + &r_capab_len); + if (!r_capab || r_capab_len < 1) { + dpp_auth_fail(auth, "Missing or invalid R-capabilities"); + goto fail; + } + auth->r_capab = r_capab[0]; + wpa_printf(MSG_DEBUG, "DPP: R-capabilities: 0x%02x", auth->r_capab); + if (status == DPP_STATUS_NOT_COMPATIBLE) { + wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_NOT_COMPATIBLE + "r-capab=0x%02x", auth->r_capab); + } else if (status == DPP_STATUS_RESPONSE_PENDING) { + u8 role = auth->r_capab & DPP_CAPAB_ROLE_MASK; + + if ((auth->configurator && role != DPP_CAPAB_ENROLLEE) || + (!auth->configurator && role != DPP_CAPAB_CONFIGURATOR)) { + wpa_msg(auth->msg_ctx, MSG_INFO, + DPP_EVENT_FAIL "Unexpected role in R-capabilities 0x%02x", + role); + } else { + wpa_printf(MSG_DEBUG, + "DPP: Continue waiting for full DPP Authentication Response"); + wpa_msg(auth->msg_ctx, MSG_INFO, + DPP_EVENT_RESPONSE_PENDING "%s", + auth->tmp_own_bi ? auth->tmp_own_bi->uri : ""); + } + } +fail: + bin_clear_free(unwrapped, unwrapped_len); +} + + +struct wpabuf * +dpp_auth_resp_rx(struct dpp_authentication *auth, const u8 *hdr, + const u8 *attr_start, size_t attr_len) +{ + EVP_PKEY *pr; + size_t secret_len; + const u8 *addr[2]; + size_t len[2]; + u8 *unwrapped = NULL, *unwrapped2 = NULL; + size_t unwrapped_len = 0, unwrapped2_len = 0; + const u8 *r_bootstrap, *i_bootstrap, *wrapped_data, *status, *r_proto, + *r_nonce, *i_nonce, *r_capab, *wrapped2, *r_auth; + u16 r_bootstrap_len, i_bootstrap_len, wrapped_data_len, status_len, + r_proto_len, r_nonce_len, i_nonce_len, r_capab_len, + wrapped2_len, r_auth_len; + u8 r_auth2[DPP_MAX_HASH_LEN]; + u8 role; +#ifdef CONFIG_DPP2 + const u8 *version; + u16 version_len; +#endif /* CONFIG_DPP2 */ + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_STOP_AT_AUTH_RESP) { + wpa_printf(MSG_INFO, + "DPP: TESTING - stop at Authentication Response"); + return NULL; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + if (!auth->initiator || !auth->peer_bi) { + dpp_auth_fail(auth, "Unexpected Authentication Response"); + return NULL; + } + + auth->waiting_auth_resp = 0; + + wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA, + &wrapped_data_len); + if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) { + dpp_auth_fail(auth, + "Missing or invalid required Wrapped Data attribute"); + return NULL; + } + wpa_hexdump(MSG_DEBUG, "DPP: Wrapped data", + wrapped_data, wrapped_data_len); + + attr_len = wrapped_data - 4 - attr_start; + + r_bootstrap = dpp_get_attr(attr_start, attr_len, + DPP_ATTR_R_BOOTSTRAP_KEY_HASH, + &r_bootstrap_len); + if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) { + dpp_auth_fail(auth, + "Missing or invalid required Responder Bootstrapping Key Hash attribute"); + return NULL; + } + wpa_hexdump(MSG_DEBUG, "DPP: Responder Bootstrapping Key Hash", + r_bootstrap, r_bootstrap_len); + if (os_memcmp(r_bootstrap, auth->peer_bi->pubkey_hash, + SHA256_MAC_LEN) != 0) { + dpp_auth_fail(auth, + "Unexpected Responder Bootstrapping Key Hash value"); + wpa_hexdump(MSG_DEBUG, + "DPP: Expected Responder Bootstrapping Key Hash", + auth->peer_bi->pubkey_hash, SHA256_MAC_LEN); + return NULL; + } + + i_bootstrap = dpp_get_attr(attr_start, attr_len, + DPP_ATTR_I_BOOTSTRAP_KEY_HASH, + &i_bootstrap_len); + if (i_bootstrap) { + if (i_bootstrap_len != SHA256_MAC_LEN) { + dpp_auth_fail(auth, + "Invalid Initiator Bootstrapping Key Hash attribute"); + return NULL; + } + wpa_hexdump(MSG_MSGDUMP, + "DPP: Initiator Bootstrapping Key Hash", + i_bootstrap, i_bootstrap_len); + if (!auth->own_bi || + os_memcmp(i_bootstrap, auth->own_bi->pubkey_hash, + SHA256_MAC_LEN) != 0) { + dpp_auth_fail(auth, + "Initiator Bootstrapping Key Hash attribute did not match"); + return NULL; + } + } else if (auth->own_bi && auth->own_bi->type == DPP_BOOTSTRAP_PKEX) { + /* PKEX bootstrapping mandates use of mutual authentication */ + dpp_auth_fail(auth, + "Missing Initiator Bootstrapping Key Hash attribute"); + return NULL; + } + + auth->peer_version = 1; /* default to the first version */ +#ifdef CONFIG_DPP2 + version = dpp_get_attr(attr_start, attr_len, DPP_ATTR_PROTOCOL_VERSION, + &version_len); + if (version) { + if (version_len < 1 || version[0] == 0) { + dpp_auth_fail(auth, + "Invalid Protocol Version attribute"); + return NULL; + } + auth->peer_version = version[0]; + wpa_printf(MSG_DEBUG, "DPP: Peer protocol version %u", + auth->peer_version); + } +#endif /* CONFIG_DPP2 */ + + status = dpp_get_attr(attr_start, attr_len, DPP_ATTR_STATUS, + &status_len); + if (!status || status_len < 1) { + dpp_auth_fail(auth, + "Missing or invalid required DPP Status attribute"); + return NULL; + } + wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]); + auth->auth_resp_status = status[0]; + if (status[0] != DPP_STATUS_OK) { + dpp_auth_resp_rx_status(auth, hdr, attr_start, + attr_len, wrapped_data, + wrapped_data_len, status[0]); + return NULL; + } + + if (!i_bootstrap && auth->own_bi) { + wpa_printf(MSG_DEBUG, + "DPP: Responder decided not to use mutual authentication"); + auth->own_bi = NULL; + } + + wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_AUTH_DIRECTION "mutual=%d", + auth->own_bi != NULL); + + r_proto = dpp_get_attr(attr_start, attr_len, DPP_ATTR_R_PROTOCOL_KEY, + &r_proto_len); + if (!r_proto) { + dpp_auth_fail(auth, + "Missing required Responder Protocol Key attribute"); + return NULL; + } + wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Protocol Key", + r_proto, r_proto_len); + + /* N = pI * PR */ + pr = dpp_set_pubkey_point(auth->own_protocol_key, r_proto, r_proto_len); + if (!pr) { + dpp_auth_fail(auth, "Invalid Responder Protocol Key"); + return NULL; + } + dpp_debug_print_key("Peer (Responder) Protocol Key", pr); + + if (dpp_ecdh(auth->own_protocol_key, pr, auth->Nx, &secret_len) < 0) { + dpp_auth_fail(auth, "Failed to derive ECDH shared secret"); + goto fail; + } + EVP_PKEY_free(auth->peer_protocol_key); + auth->peer_protocol_key = pr; + pr = NULL; + + wpa_hexdump_key(MSG_DEBUG, "DPP: ECDH shared secret (N.x)", + auth->Nx, auth->secret_len); + auth->Nx_len = auth->secret_len; + + if (dpp_derive_k2(auth->Nx, auth->secret_len, auth->k2, + auth->curve->hash_len) < 0) + goto fail; + + addr[0] = hdr; + len[0] = DPP_HDR_LEN; + addr[1] = attr_start; + len[1] = attr_len; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", + wrapped_data, wrapped_data_len); + unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE; + unwrapped = os_malloc(unwrapped_len); + if (!unwrapped) + goto fail; + if (aes_siv_decrypt(auth->k2, auth->curve->hash_len, + wrapped_data, wrapped_data_len, + 2, addr, len, unwrapped) < 0) { + dpp_auth_fail(auth, "AES-SIV decryption failed"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", + unwrapped, unwrapped_len); + + if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) { + dpp_auth_fail(auth, "Invalid attribute in unwrapped data"); + goto fail; + } + + r_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_R_NONCE, + &r_nonce_len); + if (!r_nonce || r_nonce_len != auth->curve->nonce_len) { + dpp_auth_fail(auth, "DPP: Missing or invalid R-nonce"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: R-nonce", r_nonce, r_nonce_len); + os_memcpy(auth->r_nonce, r_nonce, r_nonce_len); + + i_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_NONCE, + &i_nonce_len); + if (!i_nonce || i_nonce_len != auth->curve->nonce_len) { + dpp_auth_fail(auth, "Missing or invalid I-nonce"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: I-nonce", i_nonce, i_nonce_len); + if (os_memcmp(auth->i_nonce, i_nonce, i_nonce_len) != 0) { + dpp_auth_fail(auth, "I-nonce mismatch"); + goto fail; + } + + if (auth->own_bi) { + /* Mutual authentication */ + if (dpp_auth_derive_l_initiator(auth) < 0) + goto fail; + } + + r_capab = dpp_get_attr(unwrapped, unwrapped_len, + DPP_ATTR_R_CAPABILITIES, + &r_capab_len); + if (!r_capab || r_capab_len < 1) { + dpp_auth_fail(auth, "Missing or invalid R-capabilities"); + goto fail; + } + auth->r_capab = r_capab[0]; + wpa_printf(MSG_DEBUG, "DPP: R-capabilities: 0x%02x", auth->r_capab); + role = auth->r_capab & DPP_CAPAB_ROLE_MASK; + if ((auth->allowed_roles == + (DPP_CAPAB_CONFIGURATOR | DPP_CAPAB_ENROLLEE)) && + (role == DPP_CAPAB_CONFIGURATOR || role == DPP_CAPAB_ENROLLEE)) { + /* Peer selected its role, so move from "either role" to the + * role that is compatible with peer's selection. */ + auth->configurator = role == DPP_CAPAB_ENROLLEE; + wpa_printf(MSG_DEBUG, "DPP: Acting as %s", + auth->configurator ? "Configurator" : "Enrollee"); + } else if ((auth->configurator && role != DPP_CAPAB_ENROLLEE) || + (!auth->configurator && role != DPP_CAPAB_CONFIGURATOR)) { + wpa_printf(MSG_DEBUG, "DPP: Incompatible role selection"); + wpa_msg(auth->msg_ctx, MSG_INFO, DPP_EVENT_FAIL + "Unexpected role in R-capabilities 0x%02x", + role); + if (role != DPP_CAPAB_ENROLLEE && + role != DPP_CAPAB_CONFIGURATOR) + goto fail; + bin_clear_free(unwrapped, unwrapped_len); + auth->remove_on_tx_status = 1; + return dpp_auth_build_conf(auth, DPP_STATUS_NOT_COMPATIBLE); + } + + wrapped2 = dpp_get_attr(unwrapped, unwrapped_len, + DPP_ATTR_WRAPPED_DATA, &wrapped2_len); + if (!wrapped2 || wrapped2_len < AES_BLOCK_SIZE) { + dpp_auth_fail(auth, + "Missing or invalid Secondary Wrapped Data"); + goto fail; + } + + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", + wrapped2, wrapped2_len); + + if (dpp_derive_ke(auth, auth->ke, auth->curve->hash_len) < 0) + goto fail; + + unwrapped2_len = wrapped2_len - AES_BLOCK_SIZE; + unwrapped2 = os_malloc(unwrapped2_len); + if (!unwrapped2) + goto fail; + if (aes_siv_decrypt(auth->ke, auth->curve->hash_len, + wrapped2, wrapped2_len, + 0, NULL, NULL, unwrapped2) < 0) { + dpp_auth_fail(auth, "AES-SIV decryption failed"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", + unwrapped2, unwrapped2_len); + + if (dpp_check_attrs(unwrapped2, unwrapped2_len) < 0) { + dpp_auth_fail(auth, + "Invalid attribute in secondary unwrapped data"); + goto fail; + } + + r_auth = dpp_get_attr(unwrapped2, unwrapped2_len, DPP_ATTR_R_AUTH_TAG, + &r_auth_len); + if (!r_auth || r_auth_len != auth->curve->hash_len) { + dpp_auth_fail(auth, + "Missing or invalid Responder Authenticating Tag"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: Received Responder Authenticating Tag", + r_auth, r_auth_len); + /* R-auth' = H(I-nonce | R-nonce | PI.x | PR.x | [BI.x |] BR.x | 0) */ + if (dpp_gen_r_auth(auth, r_auth2) < 0) + goto fail; + wpa_hexdump(MSG_DEBUG, "DPP: Calculated Responder Authenticating Tag", + r_auth2, r_auth_len); + if (os_memcmp(r_auth, r_auth2, r_auth_len) != 0) { + dpp_auth_fail(auth, "Mismatching Responder Authenticating Tag"); + bin_clear_free(unwrapped, unwrapped_len); + bin_clear_free(unwrapped2, unwrapped2_len); + auth->remove_on_tx_status = 1; + return dpp_auth_build_conf(auth, DPP_STATUS_AUTH_FAILURE); + } + + bin_clear_free(unwrapped, unwrapped_len); + bin_clear_free(unwrapped2, unwrapped2_len); + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_AUTH_RESP_IN_PLACE_OF_CONF) { + wpa_printf(MSG_INFO, + "DPP: TESTING - Authentication Response in place of Confirm"); + if (dpp_auth_build_resp_ok(auth) < 0) + return NULL; + return wpabuf_dup(auth->resp_msg); + } +#endif /* CONFIG_TESTING_OPTIONS */ + + return dpp_auth_build_conf(auth, DPP_STATUS_OK); + +fail: + bin_clear_free(unwrapped, unwrapped_len); + bin_clear_free(unwrapped2, unwrapped2_len); + EVP_PKEY_free(pr); + return NULL; +} + + +static int dpp_auth_conf_rx_failure(struct dpp_authentication *auth, + const u8 *hdr, + const u8 *attr_start, size_t attr_len, + const u8 *wrapped_data, + u16 wrapped_data_len, + enum dpp_status_error status) +{ + const u8 *addr[2]; + size_t len[2]; + u8 *unwrapped = NULL; + size_t unwrapped_len = 0; + const u8 *r_nonce; + u16 r_nonce_len; + + /* Authentication Confirm failure cases are expected to include + * {R-nonce}k2 in the Wrapped Data attribute. */ + + addr[0] = hdr; + len[0] = DPP_HDR_LEN; + addr[1] = attr_start; + len[1] = attr_len; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", + wrapped_data, wrapped_data_len); + unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE; + unwrapped = os_malloc(unwrapped_len); + if (!unwrapped) { + dpp_auth_fail(auth, "Authentication failed"); + goto fail; + } + if (aes_siv_decrypt(auth->k2, auth->curve->hash_len, + wrapped_data, wrapped_data_len, + 2, addr, len, unwrapped) < 0) { + dpp_auth_fail(auth, "AES-SIV decryption failed"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", + unwrapped, unwrapped_len); + + if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) { + dpp_auth_fail(auth, "Invalid attribute in unwrapped data"); + goto fail; + } + + r_nonce = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_R_NONCE, + &r_nonce_len); + if (!r_nonce || r_nonce_len != auth->curve->nonce_len) { + dpp_auth_fail(auth, "DPP: Missing or invalid R-nonce"); + goto fail; + } + if (os_memcmp(r_nonce, auth->r_nonce, r_nonce_len) != 0) { + wpa_hexdump(MSG_DEBUG, "DPP: Received R-nonce", + r_nonce, r_nonce_len); + wpa_hexdump(MSG_DEBUG, "DPP: Expected R-nonce", + auth->r_nonce, r_nonce_len); + dpp_auth_fail(auth, "R-nonce mismatch"); + goto fail; + } + + if (status == DPP_STATUS_NOT_COMPATIBLE) + dpp_auth_fail(auth, "Peer reported incompatible R-capab role"); + else if (status == DPP_STATUS_AUTH_FAILURE) + dpp_auth_fail(auth, "Peer reported authentication failure)"); + +fail: + bin_clear_free(unwrapped, unwrapped_len); + return -1; +} + + +int dpp_auth_conf_rx(struct dpp_authentication *auth, const u8 *hdr, + const u8 *attr_start, size_t attr_len) +{ + const u8 *r_bootstrap, *i_bootstrap, *wrapped_data, *status, *i_auth; + u16 r_bootstrap_len, i_bootstrap_len, wrapped_data_len, status_len, + i_auth_len; + const u8 *addr[2]; + size_t len[2]; + u8 *unwrapped = NULL; + size_t unwrapped_len = 0; + u8 i_auth2[DPP_MAX_HASH_LEN]; + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) { + wpa_printf(MSG_INFO, + "DPP: TESTING - stop at Authentication Confirm"); + return -1; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + if (auth->initiator || !auth->own_bi) { + dpp_auth_fail(auth, "Unexpected Authentication Confirm"); + return -1; + } + + auth->waiting_auth_conf = 0; + + wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA, + &wrapped_data_len); + if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) { + dpp_auth_fail(auth, + "Missing or invalid required Wrapped Data attribute"); + return -1; + } + wpa_hexdump(MSG_DEBUG, "DPP: Wrapped data", + wrapped_data, wrapped_data_len); + + attr_len = wrapped_data - 4 - attr_start; + + r_bootstrap = dpp_get_attr(attr_start, attr_len, + DPP_ATTR_R_BOOTSTRAP_KEY_HASH, + &r_bootstrap_len); + if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) { + dpp_auth_fail(auth, + "Missing or invalid required Responder Bootstrapping Key Hash attribute"); + return -1; + } + wpa_hexdump(MSG_DEBUG, "DPP: Responder Bootstrapping Key Hash", + r_bootstrap, r_bootstrap_len); + if (os_memcmp(r_bootstrap, auth->own_bi->pubkey_hash, + SHA256_MAC_LEN) != 0) { + wpa_hexdump(MSG_DEBUG, + "DPP: Expected Responder Bootstrapping Key Hash", + auth->peer_bi->pubkey_hash, SHA256_MAC_LEN); + dpp_auth_fail(auth, + "Responder Bootstrapping Key Hash mismatch"); + return -1; + } + + i_bootstrap = dpp_get_attr(attr_start, attr_len, + DPP_ATTR_I_BOOTSTRAP_KEY_HASH, + &i_bootstrap_len); + if (i_bootstrap) { + if (i_bootstrap_len != SHA256_MAC_LEN) { + dpp_auth_fail(auth, + "Invalid Initiator Bootstrapping Key Hash attribute"); + return -1; + } + wpa_hexdump(MSG_MSGDUMP, + "DPP: Initiator Bootstrapping Key Hash", + i_bootstrap, i_bootstrap_len); + if (!auth->peer_bi || + os_memcmp(i_bootstrap, auth->peer_bi->pubkey_hash, + SHA256_MAC_LEN) != 0) { + dpp_auth_fail(auth, + "Initiator Bootstrapping Key Hash mismatch"); + return -1; + } + } else if (auth->peer_bi) { + /* Mutual authentication and peer did not include its + * Bootstrapping Key Hash attribute. */ + dpp_auth_fail(auth, + "Missing Initiator Bootstrapping Key Hash attribute"); + return -1; + } + + status = dpp_get_attr(attr_start, attr_len, DPP_ATTR_STATUS, + &status_len); + if (!status || status_len < 1) { + dpp_auth_fail(auth, + "Missing or invalid required DPP Status attribute"); + return -1; + } + wpa_printf(MSG_DEBUG, "DPP: Status %u", status[0]); + if (status[0] == DPP_STATUS_NOT_COMPATIBLE || + status[0] == DPP_STATUS_AUTH_FAILURE) + return dpp_auth_conf_rx_failure(auth, hdr, attr_start, + attr_len, wrapped_data, + wrapped_data_len, status[0]); + + if (status[0] != DPP_STATUS_OK) { + dpp_auth_fail(auth, "Authentication failed"); + return -1; + } + + addr[0] = hdr; + len[0] = DPP_HDR_LEN; + addr[1] = attr_start; + len[1] = attr_len; + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[0]", addr[0], len[0]); + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD[1]", addr[1], len[1]); + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", + wrapped_data, wrapped_data_len); + unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE; + unwrapped = os_malloc(unwrapped_len); + if (!unwrapped) + return -1; + if (aes_siv_decrypt(auth->ke, auth->curve->hash_len, + wrapped_data, wrapped_data_len, + 2, addr, len, unwrapped) < 0) { + dpp_auth_fail(auth, "AES-SIV decryption failed"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", + unwrapped, unwrapped_len); + + if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) { + dpp_auth_fail(auth, "Invalid attribute in unwrapped data"); + goto fail; + } + + i_auth = dpp_get_attr(unwrapped, unwrapped_len, DPP_ATTR_I_AUTH_TAG, + &i_auth_len); + if (!i_auth || i_auth_len != auth->curve->hash_len) { + dpp_auth_fail(auth, + "Missing or invalid Initiator Authenticating Tag"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: Received Initiator Authenticating Tag", + i_auth, i_auth_len); + /* I-auth' = H(R-nonce | I-nonce | PR.x | PI.x | BR.x | [BI.x |] 1) */ + if (dpp_gen_i_auth(auth, i_auth2) < 0) + goto fail; + wpa_hexdump(MSG_DEBUG, "DPP: Calculated Initiator Authenticating Tag", + i_auth2, i_auth_len); + if (os_memcmp(i_auth, i_auth2, i_auth_len) != 0) { + dpp_auth_fail(auth, "Mismatching Initiator Authenticating Tag"); + goto fail; + } + + bin_clear_free(unwrapped, unwrapped_len); + dpp_auth_success(auth); + return 0; +fail: + bin_clear_free(unwrapped, unwrapped_len); + return -1; +} + + +static int bin_str_eq(const char *val, size_t len, const char *cmp) +{ + return os_strlen(cmp) == len && os_memcmp(val, cmp, len) == 0; +} + + +struct dpp_configuration * dpp_configuration_alloc(const char *type) +{ + struct dpp_configuration *conf; + const char *end; + size_t len; + + conf = os_zalloc(sizeof(*conf)); + if (!conf) + goto fail; + + end = os_strchr(type, ' '); + if (end) + len = end - type; + else + len = os_strlen(type); + + if (bin_str_eq(type, len, "psk")) + conf->akm = DPP_AKM_PSK; + else if (bin_str_eq(type, len, "sae")) + conf->akm = DPP_AKM_SAE; + else if (bin_str_eq(type, len, "psk-sae") || + bin_str_eq(type, len, "psk+sae")) + conf->akm = DPP_AKM_PSK_SAE; + else if (bin_str_eq(type, len, "sae-dpp") || + bin_str_eq(type, len, "dpp+sae")) + conf->akm = DPP_AKM_SAE_DPP; + else if (bin_str_eq(type, len, "psk-sae-dpp") || + bin_str_eq(type, len, "dpp+psk+sae")) + conf->akm = DPP_AKM_PSK_SAE_DPP; + else if (bin_str_eq(type, len, "dpp")) + conf->akm = DPP_AKM_DPP; + else + goto fail; + + return conf; +fail: + dpp_configuration_free(conf); + return NULL; +} + + +int dpp_akm_psk(enum dpp_akm akm) +{ + return akm == DPP_AKM_PSK || akm == DPP_AKM_PSK_SAE || + akm == DPP_AKM_PSK_SAE_DPP; +} + + +int dpp_akm_sae(enum dpp_akm akm) +{ + return akm == DPP_AKM_SAE || akm == DPP_AKM_PSK_SAE || + akm == DPP_AKM_SAE_DPP || akm == DPP_AKM_PSK_SAE_DPP; +} + + +int dpp_akm_legacy(enum dpp_akm akm) +{ + return akm == DPP_AKM_PSK || akm == DPP_AKM_PSK_SAE || + akm == DPP_AKM_SAE; +} + + +int dpp_akm_dpp(enum dpp_akm akm) +{ + return akm == DPP_AKM_DPP || akm == DPP_AKM_SAE_DPP || + akm == DPP_AKM_PSK_SAE_DPP; +} + + +int dpp_akm_ver2(enum dpp_akm akm) +{ + return akm == DPP_AKM_SAE_DPP || akm == DPP_AKM_PSK_SAE_DPP; +} + + +int dpp_configuration_valid(const struct dpp_configuration *conf) +{ + if (conf->ssid_len == 0) + return 0; + if (dpp_akm_psk(conf->akm) && !conf->passphrase && !conf->psk_set) + return 0; + if (dpp_akm_sae(conf->akm) && !conf->passphrase) + return 0; + return 1; +} + + +void dpp_configuration_free(struct dpp_configuration *conf) +{ + if (!conf) + return; + str_clear_free(conf->passphrase); + os_free(conf->group_id); + bin_clear_free(conf, sizeof(*conf)); +} + + +static int dpp_configuration_parse(struct dpp_authentication *auth, + const char *cmd) +{ + const char *pos, *end; + struct dpp_configuration *conf_sta = NULL, *conf_ap = NULL; + struct dpp_configuration *conf = NULL; + + pos = os_strstr(cmd, " conf=sta-"); + if (pos) { + conf_sta = dpp_configuration_alloc(pos + 10); + if (!conf_sta) + goto fail; + conf = conf_sta; + } + + pos = os_strstr(cmd, " conf=ap-"); + if (pos) { + conf_ap = dpp_configuration_alloc(pos + 9); + if (!conf_ap) + goto fail; + conf = conf_ap; + } + + if (!conf) + return 0; + + pos = os_strstr(cmd, " ssid="); + if (pos) { + pos += 6; + end = os_strchr(pos, ' '); + conf->ssid_len = end ? (size_t) (end - pos) : os_strlen(pos); + conf->ssid_len /= 2; + if (conf->ssid_len > sizeof(conf->ssid) || + hexstr2bin(pos, conf->ssid, conf->ssid_len) < 0) + goto fail; + } else { +#ifdef CONFIG_TESTING_OPTIONS + /* use a default SSID for legacy testing reasons */ + os_memcpy(conf->ssid, "test", 4); + conf->ssid_len = 4; +#else /* CONFIG_TESTING_OPTIONS */ + goto fail; +#endif /* CONFIG_TESTING_OPTIONS */ + } + + pos = os_strstr(cmd, " pass="); + if (pos) { + size_t pass_len; + + pos += 6; + end = os_strchr(pos, ' '); + pass_len = end ? (size_t) (end - pos) : os_strlen(pos); + pass_len /= 2; + if (pass_len > 63 || pass_len < 8) + goto fail; + conf->passphrase = os_zalloc(pass_len + 1); + if (!conf->passphrase || + hexstr2bin(pos, (u8 *) conf->passphrase, pass_len) < 0) + goto fail; + } + + pos = os_strstr(cmd, " psk="); + if (pos) { + pos += 5; + if (hexstr2bin(pos, conf->psk, PMK_LEN) < 0) + goto fail; + conf->psk_set = 1; + } + + pos = os_strstr(cmd, " group_id="); + if (pos) { + size_t group_id_len; + + pos += 10; + end = os_strchr(pos, ' '); + group_id_len = end ? (size_t) (end - pos) : os_strlen(pos); + conf->group_id = os_malloc(group_id_len + 1); + if (!conf->group_id) + goto fail; + os_memcpy(conf->group_id, pos, group_id_len); + conf->group_id[group_id_len] = '\0'; + } + + pos = os_strstr(cmd, " expiry="); + if (pos) { + long int val; + + pos += 8; + val = strtol(pos, NULL, 0); + if (val <= 0) + goto fail; + conf->netaccesskey_expiry = val; + } + + if (!dpp_configuration_valid(conf)) + goto fail; + + auth->conf_sta = conf_sta; + auth->conf_ap = conf_ap; + return 0; + +fail: + dpp_configuration_free(conf_sta); + dpp_configuration_free(conf_ap); + return -1; +} + + +static struct dpp_configurator * +dpp_configurator_get_id(struct dpp_global *dpp, unsigned int id) +{ + struct dpp_configurator *conf; + + if (!dpp) + return NULL; + + dl_list_for_each(conf, &dpp->configurator, + struct dpp_configurator, list) { + if (conf->id == id) + return conf; + } + return NULL; +} + + +int dpp_set_configurator(struct dpp_global *dpp, void *msg_ctx, + struct dpp_authentication *auth, + const char *cmd) +{ + const char *pos; + + if (!cmd) + return 0; + + wpa_printf(MSG_DEBUG, "DPP: Set configurator parameters: %s", cmd); + + pos = os_strstr(cmd, " configurator="); + if (pos) { + pos += 14; + auth->conf = dpp_configurator_get_id(dpp, atoi(pos)); + if (!auth->conf) { + wpa_printf(MSG_INFO, + "DPP: Could not find the specified configurator"); + return -1; + } + } + + if (dpp_configuration_parse(auth, cmd) < 0) { + wpa_msg(msg_ctx, MSG_INFO, + "DPP: Failed to set configurator parameters"); + return -1; + } + return 0; +} + + +void dpp_auth_deinit(struct dpp_authentication *auth) +{ + if (!auth) + return; + dpp_configuration_free(auth->conf_ap); + dpp_configuration_free(auth->conf_sta); + EVP_PKEY_free(auth->own_protocol_key); + EVP_PKEY_free(auth->peer_protocol_key); + wpabuf_free(auth->req_msg); + wpabuf_free(auth->resp_msg); + wpabuf_free(auth->conf_req); + os_free(auth->connector); + wpabuf_free(auth->net_access_key); + wpabuf_free(auth->c_sign_key); + dpp_bootstrap_info_free(auth->tmp_own_bi); +#ifdef CONFIG_TESTING_OPTIONS + os_free(auth->config_obj_override); + os_free(auth->discovery_override); + os_free(auth->groups_override); +#endif /* CONFIG_TESTING_OPTIONS */ + bin_clear_free(auth, sizeof(*auth)); +} + + +static struct wpabuf * +dpp_build_conf_start(struct dpp_authentication *auth, + struct dpp_configuration *conf, size_t tailroom) +{ + struct wpabuf *buf; + char ssid[6 * sizeof(conf->ssid) + 1]; + +#ifdef CONFIG_TESTING_OPTIONS + if (auth->discovery_override) + tailroom += os_strlen(auth->discovery_override); +#endif /* CONFIG_TESTING_OPTIONS */ + + buf = wpabuf_alloc(200 + tailroom); + if (!buf) + return NULL; + wpabuf_put_str(buf, "{\"wi-fi_tech\":\"infra\",\"discovery\":"); +#ifdef CONFIG_TESTING_OPTIONS + if (auth->discovery_override) { + wpa_printf(MSG_DEBUG, "DPP: TESTING - discovery override: '%s'", + auth->discovery_override); + wpabuf_put_str(buf, auth->discovery_override); + wpabuf_put_u8(buf, ','); + return buf; + } +#endif /* CONFIG_TESTING_OPTIONS */ + wpabuf_put_str(buf, "{\"ssid\":\""); + json_escape_string(ssid, sizeof(ssid), + (const char *) conf->ssid, conf->ssid_len); + wpabuf_put_str(buf, ssid); + wpabuf_put_str(buf, "\"},"); + + return buf; +} + + +static int dpp_build_jwk(struct wpabuf *buf, const char *name, EVP_PKEY *key, + const char *kid, const struct dpp_curve_params *curve) +{ + struct wpabuf *pub; + const u8 *pos; + char *x = NULL, *y = NULL; + int ret = -1; + + pub = dpp_get_pubkey_point(key, 0); + if (!pub) + goto fail; + pos = wpabuf_head(pub); + x = (char *) base64_url_encode(pos, curve->prime_len, NULL, 0); + pos += curve->prime_len; + y = (char *) base64_url_encode(pos, curve->prime_len, NULL, 0); + if (!x || !y) + goto fail; + + wpabuf_put_str(buf, "\""); + wpabuf_put_str(buf, name); + wpabuf_put_str(buf, "\":{\"kty\":\"EC\",\"crv\":\""); + wpabuf_put_str(buf, curve->jwk_crv); + wpabuf_put_str(buf, "\",\"x\":\""); + wpabuf_put_str(buf, x); + wpabuf_put_str(buf, "\",\"y\":\""); + wpabuf_put_str(buf, y); + if (kid) { + wpabuf_put_str(buf, "\",\"kid\":\""); + wpabuf_put_str(buf, kid); + } + wpabuf_put_str(buf, "\"}"); + ret = 0; +fail: + wpabuf_free(pub); + os_free(x); + os_free(y); + return ret; +} + + +static void dpp_build_legacy_cred_params(struct wpabuf *buf, + struct dpp_configuration *conf) +{ + if (conf->passphrase && os_strlen(conf->passphrase) < 64) { + char pass[63 * 6 + 1]; + + json_escape_string(pass, sizeof(pass), conf->passphrase, + os_strlen(conf->passphrase)); + wpabuf_put_str(buf, "\"pass\":\""); + wpabuf_put_str(buf, pass); + wpabuf_put_str(buf, "\""); + os_memset(pass, 0, sizeof(pass)); + } else if (conf->psk_set) { + char psk[2 * sizeof(conf->psk) + 1]; + + wpa_snprintf_hex(psk, sizeof(psk), + conf->psk, sizeof(conf->psk)); + wpabuf_put_str(buf, "\"psk_hex\":\""); + wpabuf_put_str(buf, psk); + wpabuf_put_str(buf, "\""); + os_memset(psk, 0, sizeof(psk)); + } +} + + +static struct wpabuf * +dpp_build_conf_obj_dpp(struct dpp_authentication *auth, int ap, + struct dpp_configuration *conf) +{ + struct wpabuf *buf = NULL; + char *signed1 = NULL, *signed2 = NULL, *signed3 = NULL; + size_t tailroom; + const struct dpp_curve_params *curve; + char jws_prot_hdr[100]; + size_t signed1_len, signed2_len, signed3_len; + struct wpabuf *dppcon = NULL; + unsigned char *signature = NULL; + const unsigned char *p; + size_t signature_len; + EVP_MD_CTX *md_ctx = NULL; + ECDSA_SIG *sig = NULL; + char *dot = "."; + const EVP_MD *sign_md; + const BIGNUM *r, *s; + size_t extra_len = 1000; + int incl_legacy; + enum dpp_akm akm; + + if (!auth->conf) { + wpa_printf(MSG_INFO, + "DPP: No configurator specified - cannot generate DPP config object"); + goto fail; + } + curve = auth->conf->curve; + if (curve->hash_len == SHA256_MAC_LEN) { + sign_md = EVP_sha256(); + } else if (curve->hash_len == SHA384_MAC_LEN) { + sign_md = EVP_sha384(); + } else if (curve->hash_len == SHA512_MAC_LEN) { + sign_md = EVP_sha512(); + } else { + wpa_printf(MSG_DEBUG, "DPP: Unknown signature algorithm"); + goto fail; + } + + akm = conf->akm; + if (dpp_akm_ver2(akm) && auth->peer_version < 2) { + wpa_printf(MSG_DEBUG, + "DPP: Convert DPP+legacy credential to DPP-only for peer that does not support version 2"); + akm = DPP_AKM_DPP; + } + +#ifdef CONFIG_TESTING_OPTIONS + if (auth->groups_override) + extra_len += os_strlen(auth->groups_override); +#endif /* CONFIG_TESTING_OPTIONS */ + + if (conf->group_id) + extra_len += os_strlen(conf->group_id); + + /* Connector (JSON dppCon object) */ + dppcon = wpabuf_alloc(extra_len + 2 * auth->curve->prime_len * 4 / 3); + if (!dppcon) + goto fail; +#ifdef CONFIG_TESTING_OPTIONS + if (auth->groups_override) { + wpabuf_put_u8(dppcon, '{'); + if (auth->groups_override) { + wpa_printf(MSG_DEBUG, + "DPP: TESTING - groups override: '%s'", + auth->groups_override); + wpabuf_put_str(dppcon, "\"groups\":"); + wpabuf_put_str(dppcon, auth->groups_override); + wpabuf_put_u8(dppcon, ','); + } + goto skip_groups; + } +#endif /* CONFIG_TESTING_OPTIONS */ + wpabuf_printf(dppcon, "{\"groups\":[{\"groupId\":\"%s\",", + conf->group_id ? conf->group_id : "*"); + wpabuf_printf(dppcon, "\"netRole\":\"%s\"}],", ap ? "ap" : "sta"); +#ifdef CONFIG_TESTING_OPTIONS +skip_groups: +#endif /* CONFIG_TESTING_OPTIONS */ + if (dpp_build_jwk(dppcon, "netAccessKey", auth->peer_protocol_key, NULL, + auth->curve) < 0) { + wpa_printf(MSG_DEBUG, "DPP: Failed to build netAccessKey JWK"); + goto fail; + } + if (conf->netaccesskey_expiry) { + struct os_tm tm; + + if (os_gmtime(conf->netaccesskey_expiry, &tm) < 0) { + wpa_printf(MSG_DEBUG, + "DPP: Failed to generate expiry string"); + goto fail; + } + wpabuf_printf(dppcon, + ",\"expiry\":\"%04u-%02u-%02uT%02u:%02u:%02uZ\"", + tm.year, tm.month, tm.day, + tm.hour, tm.min, tm.sec); + } + wpabuf_put_u8(dppcon, '}'); + wpa_printf(MSG_DEBUG, "DPP: dppCon: %s", + (const char *) wpabuf_head(dppcon)); + + os_snprintf(jws_prot_hdr, sizeof(jws_prot_hdr), + "{\"typ\":\"dppCon\",\"kid\":\"%s\",\"alg\":\"%s\"}", + auth->conf->kid, curve->jws_alg); + signed1 = (char *) base64_url_encode((unsigned char *) jws_prot_hdr, + os_strlen(jws_prot_hdr), + &signed1_len, 0); + signed2 = (char *) base64_url_encode(wpabuf_head(dppcon), + wpabuf_len(dppcon), + &signed2_len, 0); + if (!signed1 || !signed2) + goto fail; + + md_ctx = EVP_MD_CTX_create(); + if (!md_ctx) + goto fail; + + ERR_clear_error(); + if (EVP_DigestSignInit(md_ctx, NULL, sign_md, NULL, + auth->conf->csign) != 1) { + wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignInit failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + if (EVP_DigestSignUpdate(md_ctx, signed1, signed1_len) != 1 || + EVP_DigestSignUpdate(md_ctx, dot, 1) != 1 || + EVP_DigestSignUpdate(md_ctx, signed2, signed2_len) != 1) { + wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignUpdate failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + if (EVP_DigestSignFinal(md_ctx, NULL, &signature_len) != 1) { + wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignFinal failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + signature = os_malloc(signature_len); + if (!signature) + goto fail; + if (EVP_DigestSignFinal(md_ctx, signature, &signature_len) != 1) { + wpa_printf(MSG_DEBUG, "DPP: EVP_DigestSignFinal failed: %s", + ERR_error_string(ERR_get_error(), NULL)); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: signedConnector ECDSA signature (DER)", + signature, signature_len); + /* Convert to raw coordinates r,s */ + p = signature; + sig = d2i_ECDSA_SIG(NULL, &p, signature_len); + if (!sig) + goto fail; + ECDSA_SIG_get0(sig, &r, &s); + if (dpp_bn2bin_pad(r, signature, curve->prime_len) < 0 || + dpp_bn2bin_pad(s, signature + curve->prime_len, + curve->prime_len) < 0) + goto fail; + signature_len = 2 * curve->prime_len; + wpa_hexdump(MSG_DEBUG, "DPP: signedConnector ECDSA signature (raw r,s)", + signature, signature_len); + signed3 = (char *) base64_url_encode(signature, signature_len, + &signed3_len, 0); + if (!signed3) + goto fail; + + incl_legacy = dpp_akm_psk(akm) || dpp_akm_sae(akm); + tailroom = 1000; + tailroom += 2 * curve->prime_len * 4 / 3 + os_strlen(auth->conf->kid); + tailroom += signed1_len + signed2_len + signed3_len; + if (incl_legacy) + tailroom += 1000; + buf = dpp_build_conf_start(auth, conf, tailroom); + if (!buf) + goto fail; + + wpabuf_printf(buf, "\"cred\":{\"akm\":\"%s\",", dpp_akm_str(akm)); + if (incl_legacy) { + dpp_build_legacy_cred_params(buf, conf); + wpabuf_put_str(buf, ","); + } + wpabuf_put_str(buf, "\"signedConnector\":\""); + wpabuf_put_str(buf, signed1); + wpabuf_put_u8(buf, '.'); + wpabuf_put_str(buf, signed2); + wpabuf_put_u8(buf, '.'); + wpabuf_put_str(buf, signed3); + wpabuf_put_str(buf, "\","); + if (dpp_build_jwk(buf, "csign", auth->conf->csign, auth->conf->kid, + curve) < 0) { + wpa_printf(MSG_DEBUG, "DPP: Failed to build csign JWK"); + goto fail; + } + + wpabuf_put_str(buf, "}}"); + + wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: Configuration Object", + wpabuf_head(buf), wpabuf_len(buf)); + +out: + EVP_MD_CTX_destroy(md_ctx); + ECDSA_SIG_free(sig); + os_free(signed1); + os_free(signed2); + os_free(signed3); + os_free(signature); + wpabuf_free(dppcon); + return buf; +fail: + wpa_printf(MSG_DEBUG, "DPP: Failed to build configuration object"); + wpabuf_free(buf); + buf = NULL; + goto out; +} + + +static struct wpabuf * +dpp_build_conf_obj_legacy(struct dpp_authentication *auth, int ap, + struct dpp_configuration *conf) +{ + struct wpabuf *buf; + + buf = dpp_build_conf_start(auth, conf, 1000); + if (!buf) + return NULL; + + wpabuf_printf(buf, "\"cred\":{\"akm\":\"%s\",", dpp_akm_str(conf->akm)); + dpp_build_legacy_cred_params(buf, conf); + wpabuf_put_str(buf, "}}"); + + wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: Configuration Object (legacy)", + wpabuf_head(buf), wpabuf_len(buf)); + + return buf; +} + + +static struct wpabuf * +dpp_build_conf_obj(struct dpp_authentication *auth, int ap) +{ + struct dpp_configuration *conf; + +#ifdef CONFIG_TESTING_OPTIONS + if (auth->config_obj_override) { + wpa_printf(MSG_DEBUG, "DPP: Testing - Config Object override"); + return wpabuf_alloc_copy(auth->config_obj_override, + os_strlen(auth->config_obj_override)); + } +#endif /* CONFIG_TESTING_OPTIONS */ + + conf = ap ? auth->conf_ap : auth->conf_sta; + if (!conf) { + wpa_printf(MSG_DEBUG, + "DPP: No configuration available for Enrollee(%s) - reject configuration request", + ap ? "ap" : "sta"); + return NULL; + } + + if (dpp_akm_dpp(conf->akm)) + return dpp_build_conf_obj_dpp(auth, ap, conf); + return dpp_build_conf_obj_legacy(auth, ap, conf); +} + + +static struct wpabuf * +dpp_build_conf_resp(struct dpp_authentication *auth, const u8 *e_nonce, + u16 e_nonce_len, int ap) +{ + struct wpabuf *conf; + size_t clear_len, attr_len; + struct wpabuf *clear = NULL, *msg = NULL; + u8 *wrapped; + const u8 *addr[1]; + size_t len[1]; + enum dpp_status_error status; + + conf = dpp_build_conf_obj(auth, ap); + if (conf) { + wpa_hexdump_ascii(MSG_DEBUG, "DPP: configurationObject JSON", + wpabuf_head(conf), wpabuf_len(conf)); + } + status = conf ? DPP_STATUS_OK : DPP_STATUS_CONFIGURE_FAILURE; + auth->conf_resp_status = status; + + /* { E-nonce, configurationObject}ke */ + clear_len = 4 + e_nonce_len; + if (conf) + clear_len += 4 + wpabuf_len(conf); + clear = wpabuf_alloc(clear_len); + attr_len = 4 + 1 + 4 + clear_len + AES_BLOCK_SIZE; +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_CONF_RESP) + attr_len += 5; +#endif /* CONFIG_TESTING_OPTIONS */ + msg = wpabuf_alloc(attr_len); + if (!clear || !msg) + goto fail; + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_NO_E_NONCE_CONF_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - no E-nonce"); + goto skip_e_nonce; + } + if (dpp_test == DPP_TEST_E_NONCE_MISMATCH_CONF_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - E-nonce mismatch"); + wpabuf_put_le16(clear, DPP_ATTR_ENROLLEE_NONCE); + wpabuf_put_le16(clear, e_nonce_len); + wpabuf_put_data(clear, e_nonce, e_nonce_len - 1); + wpabuf_put_u8(clear, e_nonce[e_nonce_len - 1] ^ 0x01); + goto skip_e_nonce; + } + if (dpp_test == DPP_TEST_NO_WRAPPED_DATA_CONF_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - no Wrapped Data"); + goto skip_wrapped_data; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + /* E-nonce */ + wpabuf_put_le16(clear, DPP_ATTR_ENROLLEE_NONCE); + wpabuf_put_le16(clear, e_nonce_len); + wpabuf_put_data(clear, e_nonce, e_nonce_len); + +#ifdef CONFIG_TESTING_OPTIONS +skip_e_nonce: + if (dpp_test == DPP_TEST_NO_CONFIG_OBJ_CONF_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - Config Object"); + goto skip_config_obj; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + if (conf) { + wpabuf_put_le16(clear, DPP_ATTR_CONFIG_OBJ); + wpabuf_put_le16(clear, wpabuf_len(conf)); + wpabuf_put_buf(clear, conf); + } + +#ifdef CONFIG_TESTING_OPTIONS +skip_config_obj: + if (dpp_test == DPP_TEST_NO_STATUS_CONF_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - Status"); + goto skip_status; + } + if (dpp_test == DPP_TEST_INVALID_STATUS_CONF_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - invalid Status"); + status = 255; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + /* DPP Status */ + dpp_build_attr_status(msg, status); + +#ifdef CONFIG_TESTING_OPTIONS +skip_status: +#endif /* CONFIG_TESTING_OPTIONS */ + + addr[0] = wpabuf_head(msg); + len[0] = wpabuf_len(msg); + wpa_hexdump(MSG_DEBUG, "DDP: AES-SIV AD", addr[0], len[0]); + + wpabuf_put_le16(msg, DPP_ATTR_WRAPPED_DATA); + wpabuf_put_le16(msg, wpabuf_len(clear) + AES_BLOCK_SIZE); + wrapped = wpabuf_put(msg, wpabuf_len(clear) + AES_BLOCK_SIZE); + + wpa_hexdump_buf(MSG_DEBUG, "DPP: AES-SIV cleartext", clear); + if (aes_siv_encrypt(auth->ke, auth->curve->hash_len, + wpabuf_head(clear), wpabuf_len(clear), + 1, addr, len, wrapped) < 0) + goto fail; + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", + wrapped, wpabuf_len(clear) + AES_BLOCK_SIZE); + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_AFTER_WRAPPED_DATA_CONF_RESP) { + wpa_printf(MSG_INFO, "DPP: TESTING - attr after Wrapped Data"); + dpp_build_attr_status(msg, DPP_STATUS_OK); + } +skip_wrapped_data: +#endif /* CONFIG_TESTING_OPTIONS */ + + wpa_hexdump_buf(MSG_DEBUG, + "DPP: Configuration Response attributes", msg); +out: + wpabuf_free(conf); + wpabuf_free(clear); + + return msg; +fail: + wpabuf_free(msg); + msg = NULL; + goto out; +} + + +struct wpabuf * +dpp_conf_req_rx(struct dpp_authentication *auth, const u8 *attr_start, + size_t attr_len) +{ + const u8 *wrapped_data, *e_nonce, *config_attr; + u16 wrapped_data_len, e_nonce_len, config_attr_len; + u8 *unwrapped = NULL; + size_t unwrapped_len = 0; + struct wpabuf *resp = NULL; + struct json_token *root = NULL, *token; + int ap; + +#ifdef CONFIG_TESTING_OPTIONS + if (dpp_test == DPP_TEST_STOP_AT_CONF_REQ) { + wpa_printf(MSG_INFO, + "DPP: TESTING - stop at Config Request"); + return NULL; + } +#endif /* CONFIG_TESTING_OPTIONS */ + + if (dpp_check_attrs(attr_start, attr_len) < 0) { + dpp_auth_fail(auth, "Invalid attribute in config request"); + return NULL; + } + + wrapped_data = dpp_get_attr(attr_start, attr_len, DPP_ATTR_WRAPPED_DATA, + &wrapped_data_len); + if (!wrapped_data || wrapped_data_len < AES_BLOCK_SIZE) { + dpp_auth_fail(auth, + "Missing or invalid required Wrapped Data attribute"); + return NULL; + } + + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV ciphertext", + wrapped_data, wrapped_data_len); + unwrapped_len = wrapped_data_len - AES_BLOCK_SIZE; + unwrapped = os_malloc(unwrapped_len); + if (!unwrapped) + return NULL; + if (aes_siv_decrypt(auth->ke, auth->curve->hash_len, + wrapped_data, wrapped_data_len, + 0, NULL, NULL, unwrapped) < 0) { + dpp_auth_fail(auth, "AES-SIV decryption failed"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: AES-SIV cleartext", + unwrapped, unwrapped_len); + + if (dpp_check_attrs(unwrapped, unwrapped_len) < 0) { + dpp_auth_fail(auth, "Invalid attribute in unwrapped data"); + goto fail; + } + + e_nonce = dpp_get_attr(unwrapped, unwrapped_len, + DPP_ATTR_ENROLLEE_NONCE, + &e_nonce_len); + if (!e_nonce || e_nonce_len != auth->curve->nonce_len) { + dpp_auth_fail(auth, + "Missing or invalid Enrollee Nonce attribute"); + goto fail; + } + wpa_hexdump(MSG_DEBUG, "DPP: Enrollee Nonce", e_nonce, e_nonce_len); + os_memcpy(auth->e_nonce, e_nonce, e_nonce_len); + + config_attr = dpp_get_attr(unwrapped, unwrapped_len, + DPP_ATTR_CONFIG_ATTR_OBJ, + &config_attr_len); + if (!config_attr) { + dpp_auth_fail(auth, + "Missing or invalid Config Attributes attribute"); + goto fail; + } + wpa_hexdump_ascii(MSG_DEBUG, "DPP: Config Attributes", + config_attr, config_attr_len); + + root = json_parse((const char *) config_attr, config_attr_len); + if (!root) { + dpp_auth_fail(auth, "Could not parse Config Attributes"); + goto fail; + } + + token = json_get_member(root, "name"); + if (!token || token->type != JSON_STRING) { + dpp_auth_fail(auth, "No Config Attributes - name"); + goto fail; + } + wpa_printf(MSG_DEBUG, "DPP: Enrollee name = '%s'", token->string); + + token = json_get_member(root, "wi-fi_tech"); + if (!token || token->type != JSON_STRING) { + dpp_auth_fail(auth, "No Config Attributes - wi-fi_tech"); + goto fail; + } + wpa_printf(MSG_DEBUG, "DPP: wi-fi_tech = '%s'", token->string); + if (os_strcmp(token->string, "infra") != 0) { + wpa_printf(MSG_DEBUG, "DPP: Unsupported wi-fi_tech '%s'", + token->string); + dpp_auth_fail(auth, "Unsupported wi-fi_tech"); + goto fail; + } + + token = json_get_member(root, "netRole"); + if (!token || token->type != JSON_STRING) { + dpp_auth_fail(auth, "No Config Attributes - netRole"); + goto fail; + } + wpa_printf(MSG_DEBUG, "DPP: netRole = '%s'", token->string); + if (os_strcmp(token->string, "sta") == 0) { + ap = 0; + } else if (os_strcmp(token->string, "ap") == 0) { + ap = 1; + } else { + wpa_printf(MSG_DEBUG, "DPP: Unsupported netRole '%s'", + token->string); + dpp_auth_fail(auth, "Unsupported netRole"); + goto fail; + } + + resp = dpp_build_conf_resp(auth, e_nonce, e_nonce_len, ap); + +fail: + json_free(root); + os_free(unwrapped); + return resp; +} + + +static struct wpabuf * +dpp_parse_jws_prot_hdr(const struct dpp_curve_params *curve, + const u8 *prot_hdr, u16 prot_hdr_len, + const EVP_MD **ret_md) +{ + struct json_token *root, *token; + struct wpabuf *kid = NULL; + + root = json_parse((const char *) prot_hdr, prot_hdr_len); + if (!root) { + wpa_printf(MSG_DEBUG, + "DPP: JSON parsing failed for JWS Protected Header"); + goto fail; + } + + if (root->type != JSON_OBJECT) { + wpa_printf(MSG_DEBUG, + "DPP: JWS Protected Header root is not an object"); + goto fail; + } + + token = json_get_member(root, "typ"); + if (!token || token->type != JSON_STRING) { + wpa_printf(MSG_DEBUG, "DPP: No typ string value found"); + goto fail; + } + wpa_printf(MSG_DEBUG, "DPP: JWS Protected Header typ=%s", + token->string); + if (os_strcmp(token->string, "dppCon") != 0) { + wpa_printf(MSG_DEBUG, + "DPP: Unsupported JWS Protected Header typ=%s", + token->string); + goto fail; + } + + token = json_get_member(root, "alg"); + if (!token || token->type != JSON_STRING) { + wpa_printf(MSG_DEBUG, "DPP: No alg string value found"); + goto fail; + } + wpa_printf(MSG_DEBUG, "DPP: JWS Protected Header alg=%s", + token->string); + if (os_strcmp(token->string, curve->jws_alg) != 0) { + wpa_printf(MSG_DEBUG, + "DPP: Unexpected JWS Protected Header alg=%s (expected %s based on C-sign-key)", + token->string, curve->jws_alg); + goto fail; + } + if (os_strcmp(token->string, "ES256") == 0 || + os_strcmp(token->string, "BS256") == 0) + *ret_md = EVP_sha256(); + else if (os_strcmp(token->string, "ES384") == 0 || + os_strcmp(token->string, "BS384") == 0) + *ret_md = EVP_sha384(); + else if (os_strcmp(token->string, "ES512") == 0 || + os_strcmp(token->string, "BS512") == 0) + *ret_md = EVP_sha512(); + else + *ret_md = NULL; + if (!*ret_md) { + wpa_printf(MSG_DEBUG, + "DPP: Unsupported JWS Protected Header alg=%s", + token->string); + goto fail; + } + + kid = json_get_member_base64url(root, "kid"); + if (!kid) { + wpa_printf(MSG_DEBUG, "DPP: No kid string value found"); + goto fail; + } + wpa_hexdump_buf(MSG_DEBUG, "DPP: JWS Protected Header kid (decoded)", + kid); + +fail: + json_free(root); + return kid; +} + + +static int dpp_parse_cred_legacy(struct dpp_authentication *auth, + struct json_token *cred) +{ + struct json_token *pass, *psk_hex; + + wpa_printf(MSG_DEBUG, "DPP: Legacy akm=psk credential"); + + pass = json_get_member(cred, "pass"); + psk_hex = json_get_member(cred, "psk_hex"); + + if (pass && pass->type == JSON_STRING) { + size_t len = os_strlen(pass->string); + + wpa_hexdump_ascii_key(MSG_DEBUG, "DPP: Legacy passphrase", + pass->string, len); + if (len < 8 || len > 63) + return -1; + os_strlcpy(auth->passphrase, pass->string, + sizeof(auth->passphrase)); + } else if (psk_hex && psk_hex->type == JSON_STRING) { + if (dpp_akm_sae(auth->akm) && !dpp_akm_psk(auth->akm)) { + wpa_printf(MSG_DEBUG, + "DPP: Unexpected psk_hex with akm=sae"); + return -1; + } + if (os_strlen(psk_hex->string) != PMK_LEN * 2 || + hexstr2bin(psk_hex->string, auth->psk, PMK_LEN) < 0) { + wpa_printf(MSG_DEBUG, "DPP: Invalid psk_hex encoding"); + return -1; + } + wpa_hexdump_key(MSG_DEBUG, "DPP: Legacy PSK", + auth->psk, PMK_LEN); + auth->psk_set = 1; + } else { + wpa_printf(MSG_DEBUG, "DPP: No pass or psk_hex strings found"); + return -1; + } + + if (dpp_akm_sae(auth->akm) && !auth->passphrase[0]) { + wpa_printf(MSG_DEBUG, "DPP: No pass for sae found"); + return -1; + } + + return 0; +} + + +static EVP_PKEY * dpp_parse_jwk(struct json_token *jwk, + const struct dpp_curve_params **key_curve) +{ + struct json_token *token; + const struct dpp_curve_params *curve; + struct wpabuf *x = NULL, *y = NULL; + EC_GROUP *group; + EVP_PKEY *pkey = NULL; + + token = json_get_member(jwk, "kty"); + if (!token || token->type != JSON_STRING) { + wpa_printf(MSG_DEBUG, "DPP: No kty in JWK"); + goto fail; + } + if (os_strcmp(token->string, "EC") != 0) { + wpa_printf(MSG_DEBUG, "DPP: Unexpected JWK kty '%s'", + token->string); + goto fail; + } + + token = json_get_member(jwk, "crv"); + if (!token || token->type != JSON_STRING) { + wpa_printf(MSG_DEBUG, "DPP: No crv in JWK"); + goto fail; + } + curve = dpp_get_curve_jwk_crv(token->string); + if (!curve) { + wpa_printf(MSG_DEBUG, "DPP: Unsupported JWK crv '%s'", + token->string); + goto fail; + } + + x = json_get_member_base64url(jwk, "x"); + if (!x) { + wpa_printf(MSG_DEBUG, "DPP: No x in JWK"); + goto fail; + } + wpa_hexdump_buf(MSG_DEBUG, "DPP: JWK x", x); + if (wpabuf_len(x) != curve->prime_len) { + wpa_printf(MSG_DEBUG, + "DPP: Unexpected JWK x length %u (expected %u for curve %s)", + (unsigned int) wpabuf_len(x), + (unsigned int) curve->prime_len, curve->name); + goto fail; + } + + y = json_get_member_base64url(jwk, "y"); + if (!y) { + wpa_printf(MSG_DEBUG, "DPP: No y in JWK"); + goto fail; + } + wpa_hexdump_buf(MSG_DEBUG, "DPP: JWK y", y); + if (wpabuf_len(y) != curve->prime_len) { + wpa_printf(MSG_DEBUG, + "DPP: Unexpected JWK y length %u (expected %u for curve %s)", + (unsigned int) wpabuf_len(y), + (unsigned int) curve->prime_len, curve->name); + goto fail; + } + + group = EC_GROUP_new_by_curve_name(OBJ_txt2nid(curve->name)); + if (!group) { + wpa_printf(MSG_DEBUG, "DPP: Could not prepare group for JWK"); + goto fail; + } + + pkey = dpp_set_pubkey_point_group(group, wpabuf_head(x), wpabuf_head(y), + wpabuf_len(x)); + EC_GROUP_free(group); + *key_curve = curve; + +fail: + wpabuf_free(x); + wpabuf_free(y); + + return pkey; +} + + +int dpp_key_expired(const char *timestamp, os_time_t *expiry) +{ + struct os_time now; + unsigned int year, month, day, hour, min, sec; + os_time_t utime; + const char *pos; + + /* ISO 8601 date and time: + * T